[Pkg-javascript-commits] [dojo] 11/18: Imported Upstream version 1.5.0+dfsg

David Prévot taffit at alioth.debian.org
Fri Oct 25 19:59:09 UTC 2013


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository dojo.

commit d58fe9c41ebfbafa2ab4bb6ffd35dff75bbb1591
Author: David Prévot <taffit at debian.org>
Date:   Thu Oct 24 18:21:03 2013 -0400

    Imported Upstream version 1.5.0+dfsg
---
 dijit/Calendar.js                                  |  746 +-
 dijit/CheckedMenuItem.js                           |   63 +-
 dijit/ColorPalette.js                              |  205 +-
 dijit/Declaration.js                               |  116 +-
 dijit/Dialog.js                                    |  749 +-
 dijit/DialogUnderlay.js                            |  139 +-
 dijit/Editor.js                                    | 1094 +-
 dijit/InlineEditBox.js                             |  770 +-
 dijit/LICENSE                                      |    2 +-
 dijit/Menu.js                                      | 1010 +-
 dijit/MenuBar.js                                   |  101 +-
 dijit/MenuBarItem.js                               |   28 +-
 dijit/MenuItem.js                                  |  248 +-
 dijit/MenuSeparator.js                             |   39 +-
 dijit/PopupMenuBarItem.js                          |   18 +-
 dijit/PopupMenuItem.js                             |  102 +-
 dijit/ProgressBar.js                               |  184 +-
 dijit/TitlePane.js                                 |  346 +-
 dijit/Toolbar.js                                   |   53 +-
 dijit/ToolbarSeparator.js                          |   35 +-
 dijit/Tooltip.js                                   |  522 +-
 dijit/TooltipDialog.js                             |  186 +-
 dijit/Tree.js                                      | 2241 +-
 dijit/_Calendar.js                                 |   18 +-
 dijit/_Contained.js                                |   92 +-
 dijit/_Container.js                                |  190 +-
 dijit/_CssStateMixin.js                            |  252 +
 dijit/_DialogMixin.js                              |   97 +-
 dijit/_HasDropDown.js                              |  612 +-
 dijit/_KeyNavContainer.js                          |  320 +-
 dijit/_PaletteMixin.js                             |  313 +
 dijit/_Templated.js                                |  501 +-
 dijit/_TimePicker.js                               |  752 +-
 dijit/_Widget.js                                   | 1501 +-
 dijit/_base.js                                     |   11 +-
 dijit/_base/focus.js                               |  805 +-
 dijit/_base/manager.js                             |  695 +-
 dijit/_base/place.js                               |  445 +-
 dijit/_base/popup.js                               |  514 +-
 dijit/_base/scroll.js                              |  105 +-
 dijit/_base/sniff.js                               |   40 +-
 dijit/_base/typematic.js                           |  260 +-
 dijit/_base/wai.js                                 |  204 +-
 dijit/_base/window.js                              |   21 +-
 dijit/_editor/RichText.js                          | 2876 ++-
 dijit/_editor/_Plugin.js                           |  242 +-
 dijit/_editor/html.js                              |  319 +-
 dijit/_editor/nls/FontChoice.js                    |   27 +-
 dijit/_editor/nls/LinkDialog.js                    |   13 +-
 dijit/_editor/nls/ar/FontChoice.js                 |   26 +-
 dijit/_editor/nls/ar/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/ar/commands.js                   |   50 +-
 dijit/_editor/nls/ca/FontChoice.js                 |   27 +-
 dijit/_editor/nls/ca/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/ca/commands.js                   |   50 +-
 dijit/_editor/nls/commands.js                      |   50 +-
 dijit/_editor/nls/cs/FontChoice.js                 |   26 +-
 dijit/_editor/nls/cs/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/cs/commands.js                   |   49 +-
 dijit/_editor/nls/da/FontChoice.js                 |   26 +-
 dijit/_editor/nls/da/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/da/commands.js                   |   50 +-
 dijit/_editor/nls/de/FontChoice.js                 |   26 +-
 dijit/_editor/nls/de/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/de/commands.js                   |   50 +-
 dijit/_editor/nls/el/FontChoice.js                 |   26 +-
 dijit/_editor/nls/el/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/el/commands.js                   |   49 +-
 dijit/_editor/nls/es/FontChoice.js                 |   26 +-
 dijit/_editor/nls/es/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/es/commands.js                   |   50 +-
 dijit/_editor/nls/fi/FontChoice.js                 |   26 +-
 dijit/_editor/nls/fi/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/fi/commands.js                   |   49 +-
 dijit/_editor/nls/fr/FontChoice.js                 |   26 +-
 dijit/_editor/nls/fr/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/fr/commands.js                   |   49 +-
 dijit/_editor/nls/he/FontChoice.js                 |   26 +-
 dijit/_editor/nls/he/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/he/commands.js                   |   51 +-
 dijit/_editor/nls/hu/FontChoice.js                 |   26 +-
 dijit/_editor/nls/hu/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/hu/commands.js                   |   49 +-
 dijit/_editor/nls/it/FontChoice.js                 |   26 +-
 dijit/_editor/nls/it/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/it/commands.js                   |   49 +-
 dijit/_editor/nls/ja/FontChoice.js                 |   26 +-
 dijit/_editor/nls/ja/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/ja/commands.js                   |   48 +-
 dijit/_editor/nls/ko/FontChoice.js                 |   26 +-
 dijit/_editor/nls/ko/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/ko/commands.js                   |   49 +-
 dijit/_editor/nls/nb/FontChoice.js                 |   26 +-
 dijit/_editor/nls/nb/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/nb/commands.js                   |   49 +-
 dijit/_editor/nls/nl/FontChoice.js                 |   26 +-
 dijit/_editor/nls/nl/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/nl/commands.js                   |   49 +-
 dijit/_editor/nls/pl/FontChoice.js                 |   26 +-
 dijit/_editor/nls/pl/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/pl/commands.js                   |   50 +-
 dijit/_editor/nls/pt-pt/FontChoice.js              |   26 +-
 dijit/_editor/nls/pt-pt/LinkDialog.js              |   14 +-
 dijit/_editor/nls/pt-pt/commands.js                |   49 +-
 dijit/_editor/nls/pt/FontChoice.js                 |   26 +-
 dijit/_editor/nls/pt/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/pt/commands.js                   |   49 +-
 dijit/_editor/nls/ro/FontChoice.js                 |   27 +
 dijit/_editor/nls/ro/LinkDialog.js                 |   13 +
 dijit/_editor/nls/ro/commands.js                   |   48 +
 dijit/_editor/nls/ru/FontChoice.js                 |   26 +-
 dijit/_editor/nls/ru/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/ru/commands.js                   |   49 +-
 dijit/_editor/nls/sk/FontChoice.js                 |   27 +-
 dijit/_editor/nls/sk/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/sk/commands.js                   |   49 +-
 dijit/_editor/nls/sl/FontChoice.js                 |   27 +-
 dijit/_editor/nls/sl/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/sl/commands.js                   |   49 +-
 dijit/_editor/nls/sv/FontChoice.js                 |   26 +-
 dijit/_editor/nls/sv/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/sv/commands.js                   |   51 +-
 dijit/_editor/nls/th/FontChoice.js                 |   27 +-
 dijit/_editor/nls/th/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/th/commands.js                   |   49 +-
 dijit/_editor/nls/tr/FontChoice.js                 |   26 +-
 dijit/_editor/nls/tr/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/tr/commands.js                   |   49 +-
 dijit/_editor/nls/zh-tw/FontChoice.js              |   26 +-
 dijit/_editor/nls/zh-tw/LinkDialog.js              |   14 +-
 dijit/_editor/nls/zh-tw/commands.js                |   49 +-
 dijit/_editor/nls/zh/FontChoice.js                 |   26 +-
 dijit/_editor/nls/zh/LinkDialog.js                 |   14 +-
 dijit/_editor/nls/zh/commands.js                   |   49 +-
 dijit/_editor/plugins/AlwaysShowToolbar.js         |  292 +-
 dijit/_editor/plugins/EnterKeyHandling.js          | 1028 +-
 dijit/_editor/plugins/FontChoice.js                |  708 +-
 dijit/_editor/plugins/FullScreen.js                |  614 +-
 dijit/_editor/plugins/LinkDialog.js                |  683 +-
 dijit/_editor/plugins/NewPage.js                   |   89 +-
 dijit/_editor/plugins/Print.js                     |  161 +-
 dijit/_editor/plugins/TabIndent.js                 |   75 +-
 dijit/_editor/plugins/TextColor.js                 |  109 +-
 dijit/_editor/plugins/ToggleDir.js                 |   96 +-
 dijit/_editor/plugins/ViewSource.js                |  845 +-
 dijit/_editor/range.js                             |  952 +-
 dijit/_editor/selection.js                         |  572 +-
 dijit/_tree/dndSource.js                           |   17 +-
 dijit/dijit-all.js                                 |   93 +-
 dijit/dijit-all.js.uncompressed.js                 |24901 --------------------
 dijit/dijit.js                                     |   36 +-
 dijit/dijit.js.uncompressed.js                     | 5596 -----
 dijit/form/Button.js                               |  481 +-
 dijit/form/CheckBox.js                             |  263 +-
 dijit/form/ComboBox.js                             | 1840 +-
 dijit/form/ComboButton.js                          |   10 -
 dijit/form/CurrencyTextBox.js                      |  102 +-
 dijit/form/DateTextBox.js                          |   36 +-
 dijit/form/DropDownButton.js                       |   11 +-
 dijit/form/FilteringSelect.js                      |  291 +-
 dijit/form/Form.js                                 |  231 +-
 dijit/form/HorizontalRule.js                       |   93 +-
 dijit/form/HorizontalRuleLabels.js                 |  120 +-
 dijit/form/HorizontalSlider.js                     |  517 +-
 dijit/form/MappedTextBox.js                        |   10 -
 dijit/form/MultiSelect.js                          |  151 +-
 dijit/form/NumberSpinner.js                        |   92 +-
 dijit/form/NumberTextBox.js                        |  350 +-
 dijit/form/RadioButton.js                          |   12 +-
 dijit/form/RangeBoundTextBox.js                    |   10 -
 dijit/form/Select.js                               |  409 +-
 dijit/form/SimpleTextarea.js                       |  146 +-
 dijit/form/Slider.js                               |   14 +-
 dijit/form/TextBox.js                              |  562 +-
 dijit/form/Textarea.js                             |  240 +-
 dijit/form/TimeTextBox.js                          |   51 +-
 dijit/form/ToggleButton.js                         |   10 -
 dijit/form/ValidationTextBox.js                    |  662 +-
 dijit/form/VerticalRule.js                         |   34 +-
 dijit/form/VerticalRuleLabels.js                   |   33 +-
 dijit/form/VerticalSlider.js                       |   67 +-
 dijit/form/_DateTimeTextBox.js                     |  405 +-
 dijit/form/_FormMixin.js                           |  560 +-
 dijit/form/_FormSelectWidget.js                    |  871 +-
 dijit/form/_FormWidget.js                          |  578 +-
 dijit/form/_Spinner.js                             |  192 +-
 dijit/form/nls/ComboBox.js                         |    5 +-
 dijit/form/nls/Textarea.js                         |    8 +-
 dijit/form/nls/ar/ComboBox.js                      |    5 +-
 dijit/form/nls/ar/Textarea.js                      |    7 +-
 dijit/form/nls/ar/validate.js                      |    6 +-
 dijit/form/nls/ca/ComboBox.js                      |    6 +-
 dijit/form/nls/ca/Textarea.js                      |    9 +-
 dijit/form/nls/ca/validate.js                      |    7 +-
 dijit/form/nls/cs/ComboBox.js                      |    5 +-
 dijit/form/nls/cs/Textarea.js                      |    7 +-
 dijit/form/nls/cs/validate.js                      |    6 +-
 dijit/form/nls/da/ComboBox.js                      |    5 +-
 dijit/form/nls/da/Textarea.js                      |    7 +-
 dijit/form/nls/da/validate.js                      |    6 +-
 dijit/form/nls/de/ComboBox.js                      |    5 +-
 dijit/form/nls/de/Textarea.js                      |    8 +-
 dijit/form/nls/de/validate.js                      |    6 +-
 dijit/form/nls/el/ComboBox.js                      |    5 +-
 dijit/form/nls/el/Textarea.js                      |    7 +-
 dijit/form/nls/el/validate.js                      |    6 +-
 dijit/form/nls/es/ComboBox.js                      |    5 +-
 dijit/form/nls/es/Textarea.js                      |    7 +-
 dijit/form/nls/es/validate.js                      |    6 +-
 dijit/form/nls/fi/ComboBox.js                      |    5 +-
 dijit/form/nls/fi/Textarea.js                      |    7 +-
 dijit/form/nls/fi/validate.js                      |    6 +-
 dijit/form/nls/fr/ComboBox.js                      |    5 +-
 dijit/form/nls/fr/Textarea.js                      |    7 +-
 dijit/form/nls/fr/validate.js                      |    6 +-
 dijit/form/nls/he/ComboBox.js                      |    5 +-
 dijit/form/nls/he/Textarea.js                      |    7 +-
 dijit/form/nls/he/validate.js                      |    6 +-
 dijit/form/nls/hu/ComboBox.js                      |    5 +-
 dijit/form/nls/hu/Textarea.js                      |    7 +-
 dijit/form/nls/hu/validate.js                      |    6 +-
 dijit/form/nls/it/ComboBox.js                      |    5 +-
 dijit/form/nls/it/Textarea.js                      |    7 +-
 dijit/form/nls/it/validate.js                      |    6 +-
 dijit/form/nls/ja/ComboBox.js                      |    5 +-
 dijit/form/nls/ja/Textarea.js                      |    7 +-
 dijit/form/nls/ja/validate.js                      |    6 +-
 dijit/form/nls/ko/ComboBox.js                      |    5 +-
 dijit/form/nls/ko/Textarea.js                      |    7 +-
 dijit/form/nls/ko/validate.js                      |    6 +-
 dijit/form/nls/nb/ComboBox.js                      |    5 +-
 dijit/form/nls/nb/Textarea.js                      |    7 +-
 dijit/form/nls/nb/validate.js                      |    6 +-
 dijit/form/nls/nl/ComboBox.js                      |    5 +-
 dijit/form/nls/nl/Textarea.js                      |    7 +-
 dijit/form/nls/nl/validate.js                      |    6 +-
 dijit/form/nls/pl/ComboBox.js                      |    5 +-
 dijit/form/nls/pl/Textarea.js                      |    7 +-
 dijit/form/nls/pl/validate.js                      |    6 +-
 dijit/form/nls/pt-pt/ComboBox.js                   |    5 +-
 dijit/form/nls/pt-pt/Textarea.js                   |    7 +-
 dijit/form/nls/pt-pt/validate.js                   |    6 +-
 dijit/form/nls/pt/ComboBox.js                      |    5 +-
 dijit/form/nls/pt/Textarea.js                      |    7 +-
 dijit/form/nls/pt/validate.js                      |    6 +-
 dijit/form/nls/ro/ComboBox.js                      |    5 +
 dijit/form/nls/ro/Textarea.js                      |    8 +
 dijit/form/nls/ro/validate.js                      |    6 +
 dijit/form/nls/ru/ComboBox.js                      |    5 +-
 dijit/form/nls/ru/Textarea.js                      |    7 +-
 dijit/form/nls/ru/validate.js                      |    6 +-
 dijit/form/nls/sk/ComboBox.js                      |    6 +-
 dijit/form/nls/sk/Textarea.js                      |    9 +-
 dijit/form/nls/sk/validate.js                      |    7 +-
 dijit/form/nls/sl/ComboBox.js                      |    6 +-
 dijit/form/nls/sl/Textarea.js                      |    9 +-
 dijit/form/nls/sl/validate.js                      |    7 +-
 dijit/form/nls/sv/ComboBox.js                      |    5 +-
 dijit/form/nls/sv/Textarea.js                      |    7 +-
 dijit/form/nls/sv/validate.js                      |    6 +-
 dijit/form/nls/th/ComboBox.js                      |    6 +-
 dijit/form/nls/th/Textarea.js                      |    9 +-
 dijit/form/nls/th/validate.js                      |    7 +-
 dijit/form/nls/tr/ComboBox.js                      |    5 +-
 dijit/form/nls/tr/Textarea.js                      |    7 +-
 dijit/form/nls/tr/validate.js                      |    6 +-
 dijit/form/nls/validate.js                         |    6 +-
 dijit/form/nls/zh-tw/ComboBox.js                   |    5 +-
 dijit/form/nls/zh-tw/Textarea.js                   |    7 +-
 dijit/form/nls/zh-tw/validate.js                   |    6 +-
 dijit/form/nls/zh/ComboBox.js                      |    5 +-
 dijit/form/nls/zh/Textarea.js                      |    7 +-
 dijit/form/nls/zh/validate.js                      |    6 +-
 dijit/form/templates/Button.html                   |   17 +
 dijit/form/templates/CheckBox.html                 |    7 +
 dijit/form/templates/ComboBox.html                 |   18 +
 dijit/form/templates/ComboButton.html              |   23 +
 dijit/form/templates/DropDownButton.html           |   20 +
 dijit/form/templates/HorizontalSlider.html         |   37 +
 dijit/form/templates/Select.html                   |   14 +
 dijit/form/templates/Spinner.html                  |   27 +
 dijit/form/templates/TextBox.html                  |    6 +
 dijit/form/templates/ValidationTextBox.html        |   10 +
 dijit/form/templates/VerticalSlider.html           |   45 +
 dijit/icons/commonIcons.css                        |  164 +
 dijit/icons/commonIcons_rtl.css                    |  127 +
 dijit/icons/editorIcons.css                        |   78 +
 dijit/icons/editorIcons_rtl.css                    |   23 +
 dijit/icons/images/commonIconsObjActDisabled.png   |  Bin 0 -> 4956 bytes
 .../icons/images/commonIconsObjActDisabled_rtl.png |  Bin 0 -> 5820 bytes
 dijit/icons/images/commonIconsObjActEnabled.png    |  Bin 0 -> 12474 bytes
 .../icons/images/commonIconsObjActEnabled8bit.png  |  Bin 0 -> 4334 bytes
 .../images/commonIconsObjActEnabled8bit_rtl.png    |  Bin 0 -> 5258 bytes
 .../icons/images/commonIconsObjActEnabled_rtl.png  |  Bin 0 -> 10481 bytes
 dijit/icons/images/editorIconsDisabled.png         |  Bin 0 -> 3289 bytes
 dijit/icons/images/editorIconsDisabled_rtl.png     |  Bin 0 -> 6965 bytes
 dijit/icons/images/editorIconsEnabled.png          |  Bin 0 -> 3846 bytes
 dijit/icons/images/editorIconsEnabled_rtl.png      |  Bin 0 -> 7144 bytes
 dijit/icons/images/loadingAnimation_rtl.gif        |  Bin 0 -> 1513 bytes
 dijit/layout/AccordionContainer.js                 |  600 +-
 dijit/layout/AccordionPane.js                      |   31 +-
 dijit/layout/BorderContainer.js                    |  974 +-
 dijit/layout/ContentPane.js                        | 1000 +-
 dijit/layout/LayoutContainer.js                    |   99 +-
 dijit/layout/LinkPane.js                           |   54 +-
 dijit/layout/ScrollingTabController.js             |  646 +-
 dijit/layout/SplitContainer.js                     |  914 +-
 dijit/layout/StackContainer.js                     |  458 +-
 dijit/layout/StackController.js                    |  468 +-
 dijit/layout/TabContainer.js                       |   81 +-
 dijit/layout/TabController.js                      |  235 +-
 dijit/layout/_LayoutWidget.js                      |  389 +-
 dijit/layout/_TabContainerBase.js                  |  192 +-
 dijit/layout/templates/AccordionButton.html        |   10 +
 dijit/layout/templates/ScrollingTabController.html |   18 +
 dijit/layout/templates/TabContainer.html           |    5 +
 .../templates/_ScrollingTabControllerButton.html   |    8 +
 dijit/layout/templates/_TabButton.html             |   14 +
 dijit/nls/ar/common.js                             |    7 +-
 dijit/nls/ar/loading.js                            |    5 +-
 dijit/nls/ca/common.js                             |    8 +-
 dijit/nls/ca/loading.js                            |    6 +-
 dijit/nls/common.js                                |    7 +-
 dijit/nls/cs/common.js                             |    7 +-
 dijit/nls/cs/loading.js                            |    5 +-
 dijit/nls/da/common.js                             |    7 +-
 dijit/nls/da/loading.js                            |    5 +-
 dijit/nls/de/common.js                             |    7 +-
 dijit/nls/de/loading.js                            |    5 +-
 dijit/nls/dijit-all_ROOT.js                        |    1 -
 dijit/nls/dijit-all_ar.js                          |    1 -
 dijit/nls/dijit-all_ca.js                          |    1 -
 dijit/nls/dijit-all_cs.js                          |    1 -
 dijit/nls/dijit-all_da.js                          |    1 -
 dijit/nls/dijit-all_de-de.js                       |    1 -
 dijit/nls/dijit-all_de.js                          |    1 -
 dijit/nls/dijit-all_el.js                          |    1 -
 dijit/nls/dijit-all_en-gb.js                       |    1 -
 dijit/nls/dijit-all_en-us.js                       |    1 -
 dijit/nls/dijit-all_en.js                          |    1 -
 dijit/nls/dijit-all_es-es.js                       |    1 -
 dijit/nls/dijit-all_es.js                          |    1 -
 dijit/nls/dijit-all_fi-fi.js                       |    1 -
 dijit/nls/dijit-all_fi.js                          |    1 -
 dijit/nls/dijit-all_fr-fr.js                       |    1 -
 dijit/nls/dijit-all_fr.js                          |    1 -
 dijit/nls/dijit-all_he-il.js                       |    1 -
 dijit/nls/dijit-all_he.js                          |    1 -
 dijit/nls/dijit-all_hu.js                          |    1 -
 dijit/nls/dijit-all_it-it.js                       |    1 -
 dijit/nls/dijit-all_it.js                          |    1 -
 dijit/nls/dijit-all_ja-jp.js                       |    1 -
 dijit/nls/dijit-all_ja.js                          |    1 -
 dijit/nls/dijit-all_ko-kr.js                       |    1 -
 dijit/nls/dijit-all_ko.js                          |    1 -
 dijit/nls/dijit-all_nb.js                          |    1 -
 dijit/nls/dijit-all_nl-nl.js                       |    1 -
 dijit/nls/dijit-all_nl.js                          |    1 -
 dijit/nls/dijit-all_pl.js                          |    1 -
 dijit/nls/dijit-all_pt-br.js                       |    1 -
 dijit/nls/dijit-all_pt-pt.js                       |    1 -
 dijit/nls/dijit-all_pt.js                          |    1 -
 dijit/nls/dijit-all_ru.js                          |    1 -
 dijit/nls/dijit-all_sk.js                          |    1 -
 dijit/nls/dijit-all_sl.js                          |    1 -
 dijit/nls/dijit-all_sv.js                          |    1 -
 dijit/nls/dijit-all_th.js                          |    1 -
 dijit/nls/dijit-all_tr.js                          |    1 -
 dijit/nls/dijit-all_xx.js                          |    1 -
 dijit/nls/dijit-all_zh-cn.js                       |    1 -
 dijit/nls/dijit-all_zh-tw.js                       |    1 -
 dijit/nls/dijit-all_zh.js                          |    1 -
 dijit/nls/el/common.js                             |    7 +-
 dijit/nls/el/loading.js                            |    5 +-
 dijit/nls/es/common.js                             |    7 +-
 dijit/nls/es/loading.js                            |    5 +-
 dijit/nls/fi/common.js                             |    7 +-
 dijit/nls/fi/loading.js                            |    5 +-
 dijit/nls/fr/common.js                             |    7 +-
 dijit/nls/fr/loading.js                            |    5 +-
 dijit/nls/he/common.js                             |    7 +-
 dijit/nls/he/loading.js                            |    5 +-
 dijit/nls/hu/common.js                             |    7 +-
 dijit/nls/hu/loading.js                            |    5 +-
 dijit/nls/it/common.js                             |    7 +-
 dijit/nls/it/loading.js                            |    5 +-
 dijit/nls/ja/common.js                             |    7 +-
 dijit/nls/ja/loading.js                            |    5 +-
 dijit/nls/ko/common.js                             |    7 +-
 dijit/nls/ko/loading.js                            |    5 +-
 dijit/nls/loading.js                               |    5 +-
 dijit/nls/nb/common.js                             |    7 +-
 dijit/nls/nb/loading.js                            |    5 +-
 dijit/nls/nl/common.js                             |    7 +-
 dijit/nls/nl/loading.js                            |    5 +-
 dijit/nls/pl/common.js                             |    7 +-
 dijit/nls/pl/loading.js                            |    5 +-
 dijit/nls/pt-pt/common.js                          |    7 +-
 dijit/nls/pt-pt/loading.js                         |    5 +-
 dijit/nls/pt/common.js                             |    7 +-
 dijit/nls/pt/loading.js                            |    5 +-
 dijit/nls/ro/common.js                             |    7 +
 dijit/nls/ro/loading.js                            |    5 +
 dijit/nls/ru/common.js                             |    7 +-
 dijit/nls/ru/loading.js                            |    5 +-
 dijit/nls/sk/common.js                             |    8 +-
 dijit/nls/sk/loading.js                            |    6 +-
 dijit/nls/sl/common.js                             |    8 +-
 dijit/nls/sl/loading.js                            |    6 +-
 dijit/nls/sv/common.js                             |    7 +-
 dijit/nls/sv/loading.js                            |    5 +-
 dijit/nls/th/common.js                             |    8 +-
 dijit/nls/th/loading.js                            |    6 +-
 dijit/nls/tr/common.js                             |    7 +-
 dijit/nls/tr/loading.js                            |    5 +-
 dijit/nls/zh-tw/common.js                          |    7 +-
 dijit/nls/zh-tw/loading.js                         |    5 +-
 dijit/nls/zh/common.js                             |    7 +-
 dijit/nls/zh/loading.js                            |    5 +-
 dijit/resources/_modules.js                        |   21 +-
 dijit/robot.js                                     |   62 -
 dijit/robotx.js                                    |   30 +-
 dijit/templates/Calendar.html                      |   42 +
 dijit/templates/CheckedMenuItem.html               |   10 +
 dijit/templates/ColorPalette.html                  |    6 +
 dijit/templates/Dialog.html                        |    9 +
 dijit/templates/InlineEditBox.html                 |    8 +
 dijit/templates/Menu.html                          |    3 +
 dijit/templates/MenuBar.html                       |    1 +
 dijit/templates/MenuBarItem.html                   |    4 +
 dijit/templates/MenuItem.html                      |   14 +
 dijit/templates/MenuSeparator.html                 |   10 +
 dijit/templates/ProgressBar.html                   |    8 +
 dijit/templates/TimePicker.html                    |    9 +
 dijit/templates/TitlePane.html                     |   17 +
 dijit/templates/Tooltip.html                       |    4 +
 dijit/templates/TooltipDialog.html                 |    6 +
 dijit/templates/Tree.html                          |    4 +
 dijit/templates/TreeNode.html                      |   13 +
 dijit/tests/Tree.html                              |  249 +
 dijit/tests/Tree_with_JRS.html                     |  119 +
 dijit/tests/Widget-placeAt.html                    |  152 +
 dijit/tests/_Container.html                        |  109 +
 dijit/tests/_Templated-widgetsInTemplate.html      |  473 +
 dijit/tests/_Templated.html                        |  220 +
 dijit/tests/_Widget-attr.html                      |  156 +
 dijit/tests/_Widget-connect-performance.html       |   70 +
 dijit/tests/_Widget-deferredConnect.html           |   80 +
 dijit/tests/_Widget-lifecycle.html                 |   95 +
 dijit/tests/_Widget-ondijitclick.html              |   77 +
 dijit/tests/_Widget-subscribe.html                 |   96 +
 dijit/tests/_altCalendar.html                      |   44 +
 dijit/tests/_base/manager.html                     |  258 +
 dijit/tests/_base/module.js                        |   19 +
 dijit/tests/_base/multiversion.html                |   86 +
 dijit/tests/_base/place.html                       |  141 +
 dijit/tests/_base/robot/FocusManager.html          |  164 +
 dijit/tests/_base/robot/focus_mouse.html           |  228 +
 dijit/tests/_base/robot/popup.html                 |  208 +
 dijit/tests/_base/robot/typematic.html             |   72 +
 dijit/tests/_base/tabindex.html                    |  290 +
 dijit/tests/_base/test_CrossWindow.html            |  134 +
 dijit/tests/_base/test_FocusManager.html           |   60 +
 dijit/tests/_base/test_focusWidget.html            |  144 +
 dijit/tests/_base/test_popup.html                  |  270 +
 dijit/tests/_base/test_typematic.html              |   65 +
 dijit/tests/_base/wai.html                         |  194 +
 dijit/tests/_data/SlowStore.js                     |   92 +
 dijit/tests/_data/categories.json                  |   12 +
 dijit/tests/_data/categoriesNested.json            |   13 +
 dijit/tests/_data/countries.json                   |   46 +
 dijit/tests/_data/dijits.json                      |    1 +
 dijit/tests/_data/states.json                      |   67 +
 dijit/tests/_data/treeTest.json                    |   22 +
 dijit/tests/_loadTest.js                           |   87 +
 dijit/tests/_testCommon.js                         |  101 +
 dijit/tests/_testMatrix.php                        |   75 +
 dijit/tests/bidi.html                              |  188 +
 dijit/tests/css/dijitTests.css                     |  116 +
 dijit/tests/editor/BackForwardState.html           |   46 +
 dijit/tests/editor/BackForwardStateHelper.html     |   11 +
 dijit/tests/editor/EnterKeyHandling.html           |   85 +
 dijit/tests/editor/_Editor.html                    |   51 +
 dijit/tests/editor/customIcon.gif                  |  Bin 0 -> 204 bytes
 dijit/tests/editor/module.js                       |   29 +
 dijit/tests/editor/nls_8859-2.html                 |   43 +
 dijit/tests/editor/nls_sjis.html                   |   43 +
 dijit/tests/editor/nls_utf8.html                   |   43 +
 dijit/tests/editor/robot/BackForwardState.html     |  113 +
 dijit/tests/editor/robot/Editor_FontChoice.html    |  616 +
 dijit/tests/editor/robot/Editor_FullScreen.html    |  800 +
 dijit/tests/editor/robot/Editor_LinkDialog.html    | 1113 +
 dijit/tests/editor/robot/Editor_NewPage.html       |  128 +
 dijit/tests/editor/robot/Editor_ViewSource.html    |  787 +
 dijit/tests/editor/robot/Editor_a11y.html          |  332 +
 dijit/tests/editor/robot/Editor_misc.html          |  186 +
 dijit/tests/editor/robot/Editor_mouse.html         |  143 +
 dijit/tests/editor/robot/EnterKeyHandling.html     |  269 +
 dijit/tests/editor/runTests.html                   |    9 +
 dijit/tests/editor/sample.jpg                      |  Bin 0 -> 858 bytes
 dijit/tests/editor/sample2.jpg                     |  Bin 0 -> 1021 bytes
 dijit/tests/editor/test_CustomPlugin.html          |   97 +
 dijit/tests/editor/test_Editor.html                |  208 +
 dijit/tests/editor/test_FontChoice.html            |  144 +
 dijit/tests/editor/test_FullScreen.html            |  208 +
 dijit/tests/editor/test_LinkDialog.html            |   45 +
 dijit/tests/editor/test_NewPage.html               |   63 +
 dijit/tests/editor/test_Print.html                 |   49 +
 dijit/tests/editor/test_RichText.html              |   60 +
 dijit/tests/editor/test_TabIndent.html             |   49 +
 dijit/tests/editor/test_ToggleDir.html             |   38 +
 dijit/tests/editor/test_ToggleDir_rtl.html         |   38 +
 dijit/tests/editor/test_ViewSource.html            |  114 +
 dijit/tests/editor/test_resize.html                |   32 +
 dijit/tests/editor/test_richtext.css               |    4 +
 dijit/tests/form/Form.html                         |  551 +
 dijit/tests/form/FormInvalid.html                  |   54 +
 dijit/tests/form/TextBox_sizes.html                |  532 +
 dijit/tests/form/TextBox_sizes.js                  |  456 +
 dijit/tests/form/_autoComplete.html                |  546 +
 dijit/tests/form/images/Alabama.jpg                |  Bin 0 -> 4585 bytes
 dijit/tests/form/module.js                         |   55 +
 dijit/tests/form/robot/Button_a11y.html            |  468 +
 dijit/tests/form/robot/Button_mouse.html           |  689 +
 dijit/tests/form/robot/ComboBox_a11y.html          |   12 +
 dijit/tests/form/robot/ComboBox_mouse.html         |   12 +
 dijit/tests/form/robot/DateTextBox.html            |  446 +
 dijit/tests/form/robot/FilteringSelect_a11y.html   |   12 +
 dijit/tests/form/robot/FilteringSelect_mouse.html  |   12 +
 dijit/tests/form/robot/Form.html                   |   72 +
 dijit/tests/form/robot/Select.html                 |  410 +
 dijit/tests/form/robot/Slider_a11y.html            |  344 +
 dijit/tests/form/robot/Slider_mouse.html           |  339 +
 dijit/tests/form/robot/Spinner_a11y.html           |  682 +
 dijit/tests/form/robot/Spinner_mouse.html          |  397 +
 dijit/tests/form/robot/Textarea.html               |  178 +
 dijit/tests/form/robot/TimeTextBox.html            |   81 +
 dijit/tests/form/robot/_autoComplete_a11y.html     |  941 +
 dijit/tests/form/robot/_autoComplete_mouse.html    |  399 +
 dijit/tests/form/robot/test_validate.html          | 1113 +
 dijit/tests/form/robot/validationMessages.html     |  470 +
 dijit/tests/form/runTests.html                     |    9 +
 dijit/tests/form/test_Button.html                  |  451 +
 dijit/tests/form/test_CheckBox.html                |  311 +
 dijit/tests/form/test_ComboBox.html                |   12 +
 dijit/tests/form/test_ComboBox_destroy.html        |   66 +
 dijit/tests/form/test_DateTextBox.html             |  216 +
 dijit/tests/form/test_DateTextBox_iframe.html      |    5 +
 dijit/tests/form/test_FilteringSelect.html         |   12 +
 dijit/tests/form/test_Form_onsubmit.html           |   98 +
 dijit/tests/form/test_MultiSelect.html             |  158 +
 dijit/tests/form/test_Select.html                  |  573 +
 dijit/tests/form/test_SimpleTextarea.html          |   92 +
 dijit/tests/form/test_Slider.html                  |  223 +
 dijit/tests/form/test_Spinner.html                 |  128 +
 dijit/tests/form/test_Textarea.html                |  141 +
 dijit/tests/form/test_TimeTextBox.html             |  174 +
 dijit/tests/form/test_validStatePerformance.html   |  116 +
 dijit/tests/form/test_validate.html                |  491 +
 dijit/tests/form/test_validationState.html         |  102 +
 dijit/tests/formAction.html                        |   26 +
 dijit/tests/general-module.js                      |   29 +
 dijit/tests/helpers.js                             |   19 +
 dijit/tests/i18n/README                            |    4 +
 dijit/tests/i18n/calendar.html                     |   93 +
 dijit/tests/i18n/currency.html                     |  211 +
 dijit/tests/i18n/date.html                         |  156 +
 dijit/tests/i18n/digit.html                        |  295 +
 dijit/tests/i18n/module.js                         |   14 +
 dijit/tests/i18n/number.html                       |  137 +
 dijit/tests/i18n/test_i18n.js                      |  206 +
 dijit/tests/i18n/textbox.html                      |  174 +
 dijit/tests/i18n/time.html                         |  208 +
 dijit/tests/images/arrowSmall.gif                  |  Bin 0 -> 54 bytes
 dijit/tests/images/copy.gif                        |  Bin 0 -> 241 bytes
 dijit/tests/images/cut.gif                         |  Bin 0 -> 160 bytes
 dijit/tests/images/flatScreen.gif                  |  Bin 0 -> 824 bytes
 dijit/tests/images/folderIcons.gif                 |  Bin 0 -> 1757 bytes
 dijit/tests/images/folderIcons.png                 |  Bin 0 -> 2908 bytes
 dijit/tests/images/note.gif                        |  Bin 0 -> 577 bytes
 dijit/tests/images/paste.gif                       |  Bin 0 -> 256 bytes
 dijit/tests/images/plus.gif                        |  Bin 0 -> 88 bytes
 dijit/tests/images/testsBodyBg.gif                 |  Bin 0 -> 753 bytes
 dijit/tests/images/tube.gif                        |  Bin 0 -> 147 bytes
 dijit/tests/images/tubeTall.gif                    |  Bin 0 -> 256 bytes
 dijit/tests/infrastructure-module.js               |   20 +
 dijit/tests/layout/AccordionContainer.html         |  229 +
 dijit/tests/layout/ContentPane.html                |  879 +
 dijit/tests/layout/ContentPaneLayout.html          |  651 +
 dijit/tests/layout/TabContainer.html               |  479 +
 dijit/tests/layout/_lorem.html                     |    3 +
 dijit/tests/layout/borderContainer.php             |   32 +
 dijit/tests/layout/combotab.html                   |   11 +
 dijit/tests/layout/doc0.html                       |   14 +
 dijit/tests/layout/doc1.html                       |   13 +
 dijit/tests/layout/doc2.html                       |   13 +
 dijit/tests/layout/getResponse.php                 |   57 +
 dijit/tests/layout/module.js                       |   20 +
 dijit/tests/layout/multipleLayoutWidgets.php       |   14 +
 dijit/tests/layout/nestedStack.html                |  194 +
 .../layout/robot/AccordionContainer_a11y.html      |   68 +
 .../layout/robot/AccordionContainer_mouse.html     |   53 +
 dijit/tests/layout/robot/BorderContainer.html      |  358 +
 dijit/tests/layout/robot/TabContainer_a11y.html    |  278 +
 dijit/tests/layout/robot/TabContainer_mouse.html   |  151 +
 dijit/tests/layout/tab1.html                       |    6 +
 dijit/tests/layout/tab2.html                       |    3 +
 dijit/tests/layout/tab3.html                       |   39 +
 dijit/tests/layout/tab3_noLayout.html              |   39 +
 dijit/tests/layout/tab4.html                       |   40 +
 dijit/tests/layout/test_AccordionContainer.html    |  308 +
 .../layout/test_AccordionContainerDestroy.html     |   57 +
 dijit/tests/layout/test_BorderContainer.html       |  241 +
 .../tests/layout/test_BorderContainer_complex.html |  182 +
 .../layout/test_BorderContainer_experimental.html  |  258 +
 dijit/tests/layout/test_BorderContainer_full.html  |   64 +
 .../tests/layout/test_BorderContainer_nested.html  |  118 +
 dijit/tests/layout/test_BorderContainer_prog.html  |   56 +
 dijit/tests/layout/test_ContentPane.html           |  208 +
 dijit/tests/layout/test_ContentPane_prog.html      |   49 +
 dijit/tests/layout/test_Gui.html                   |  275 +
 dijit/tests/layout/test_LayoutContainer.html       |  183 +
 dijit/tests/layout/test_SplitContainer.html        |  125 +
 dijit/tests/layout/test_StackContainer.html        |  171 +
 dijit/tests/layout/test_StackContainer_code.html   |   72 +
 dijit/tests/layout/test_TabContainer.html          | 1059 +
 dijit/tests/layout/test_TabContainerTitlePane.html |   82 +
 dijit/tests/layout/test_TabContainer_noLayout.html |  172 +
 dijit/tests/layout/test_TabContainer_prog.html     |   61 +
 dijit/tests/layout/test_TabContainer_remote.html   |  116 +
 dijit/tests/layout/test_refreshOnShow.html         |   65 +
 dijit/tests/loose.html                             |    7 +
 dijit/tests/module.js                              |   16 +
 dijit/tests/quirks.html                            |    5 +
 dijit/tests/robot/Calendar_a11y.html               |  126 +
 dijit/tests/robot/ColorPalette.html                |  228 +
 dijit/tests/robot/Dialog_a11y.html                 |  501 +
 dijit/tests/robot/Dialog_mouse.html                |  169 +
 dijit/tests/robot/InlineEditBox.html               |  399 +
 dijit/tests/robot/Menu_a11y.html                   |  447 +
 dijit/tests/robot/Menu_mouse.html                  |  489 +
 dijit/tests/robot/TitlePane.html                   |  254 +
 dijit/tests/robot/Toolbar.html                     |  250 +
 dijit/tests/robot/TooltipDialog_a11y.html          |  370 +
 dijit/tests/robot/TooltipDialog_mouse.html         |  121 +
 dijit/tests/robot/Tooltip_a11y.html                |  352 +
 dijit/tests/robot/Tooltip_mouse.html               |   73 +
 dijit/tests/robot/Tree_a11y.html                   |  772 +
 dijit/tests/robot/Tree_dnd.html                    |  340 +
 dijit/tests/robot/Tree_dnd.js                      |  103 +
 dijit/tests/robot/Tree_dnd_multiParent.html        |  273 +
 dijit/tests/robot/_Widget-deferredConnect.html     |   74 +
 dijit/tests/robot/_Widget-ondijitclick_a11y.html   |  166 +
 dijit/tests/robot/_Widget-ondijitclick_mouse.html  |   52 +
 dijit/tests/runTests.html                          |    9 +
 dijit/tests/strict.html                            |    7 +
 dijit/tests/test.html                              |   37 +
 dijit/tests/test_Calendar.html                     |   84 +
 dijit/tests/test_ColorPalette.html                 |   61 +
 dijit/tests/test_ColorPalette_quirks.html          |    5 +
 dijit/tests/test_Declaration.html                  |   95 +
 dijit/tests/test_Dialog.html                       |  599 +
 dijit/tests/test_Dialog_focusDestroy.html          |   68 +
 dijit/tests/test_InlineEditBox.html                |  261 +
 dijit/tests/test_Menu.html                         |  466 +
 dijit/tests/test_Menu_iframe.html                  |   38 +
 dijit/tests/test_ProgressBar.html                  |  172 +
 dijit/tests/test_TitlePane.html                    |  162 +
 dijit/tests/test_Toolbar.html                      |  159 +
 dijit/tests/test_Tooltip.html                      |  192 +
 dijit/tests/test_TooltipDialog.html                |  405 +
 dijit/tests/test_Tree.html                         |  174 +
 .../tests/test_Tree_Notification_API_Support.html  |  293 +
 dijit/tests/test_bgIframe.html                     |   88 +
 dijit/tests/test_instantiate.html                  |  118 +
 dijit/tests/tree/module.js                         |   16 +
 dijit/tests/tree/node1.1                           |    4 +
 dijit/tests/tree/node1.2                           |    1 +
 dijit/tests/tree/places.json                       |   29 +
 dijit/tests/tree/test_CustomLabel.html             |   56 +
 dijit/tests/tree/test_Tree_DnD.html                |  214 +
 dijit/tests/tree/test_Tree_Programmatic.html       |   67 +
 dijit/tests/tree/test_Tree_Styling.html            |  113 +
 dijit/tests/tree/test_Tree_v1.html                 |  118 +
 dijit/tests/tree/treeTestRoot                      |   10 +
 dijit/themes/a11y/colors3x4-rtl.png                |  Bin 0 -> 282 bytes
 dijit/themes/a11y/colors3x4.png                    |  Bin 786 -> 282 bytes
 dijit/themes/a11y/colors7x10-rtl.png               |  Bin 0 -> 808 bytes
 dijit/themes/a11y/colors7x10.png                   |  Bin 2641 -> 808 bytes
 dijit/themes/claro/Calendar.css                    |  257 +
 dijit/themes/claro/Calendar_rtl.css                |   19 +
 dijit/themes/claro/ColorPalette.css                |   44 +
 dijit/themes/claro/Common.css                      |   79 +
 dijit/themes/claro/Dialog.css                      |  212 +
 dijit/themes/claro/Dialog_rtl.css                  |   10 +
 dijit/themes/claro/Editor.css                      |   56 +
 dijit/themes/claro/Editor_rtl.css                  |    7 +
 dijit/themes/claro/InlineEditBox.css               |   23 +
 dijit/themes/claro/Menu.css                        |  182 +
 dijit/themes/claro/Menu_rtl.css                    |    9 +
 dijit/themes/claro/ProgressBar.css                 |   53 +
 dijit/themes/claro/TimePicker.css                  |  125 +
 dijit/themes/claro/TimePicker_rtl.css              |   10 +
 dijit/themes/claro/TitlePane.css                   |   73 +
 dijit/themes/claro/TitlePane_rtl.css               |    4 +
 dijit/themes/claro/Toolbar.css                     |  170 +
 dijit/themes/claro/Tree.css                        |  122 +
 dijit/themes/claro/claro.css                       |   29 +
 dijit/themes/claro/claro_rtl.css                   |   15 +
 dijit/themes/claro/document.css                    |  109 +
 dijit/themes/claro/form/Button.css                 |  168 +
 dijit/themes/claro/form/Button_rtl.css             |   22 +
 dijit/themes/claro/form/Checkbox.css               |   77 +
 dijit/themes/claro/form/Common.css                 |  176 +
 dijit/themes/claro/form/Common_rtl.css             |   10 +
 dijit/themes/claro/form/NumberSpinner.css          |  143 +
 dijit/themes/claro/form/RadioButton.css            |   82 +
 dijit/themes/claro/form/Select.css                 |  124 +
 dijit/themes/claro/form/Select_rtl.css             |    4 +
 dijit/themes/claro/form/Slider.css                 |  359 +
 dijit/themes/claro/form/Slider_rtl.css             |   31 +
 dijit/themes/claro/form/images/button.png          |  Bin 0 -> 680 bytes
 dijit/themes/claro/form/images/buttonArrows.png    |  Bin 0 -> 297 bytes
 dijit/themes/claro/form/images/button_grad_d.png   |  Bin 0 -> 3897 bytes
 .../form/images/checkboxAndRadioButtons_IE6.png    |  Bin 0 -> 2160 bytes
 .../form/images/checkboxRadioButtonStates.png      |  Bin 0 -> 3438 bytes
 .../themes/claro/form/images/commonFormArrows.png  |  Bin 0 -> 314 bytes
 dijit/themes/claro/form/images/error.png           |  Bin 0 -> 355 bytes
 dijit/themes/claro/form/images/formHighlight.png   |  Bin 0 -> 339 bytes
 dijit/themes/claro/form/images/shadow.png          |  Bin 0 -> 4624 bytes
 .../themes/claro/form/images/sliderHorizontal.png  |  Bin 0 -> 180 bytes
 dijit/themes/claro/form/images/sliderThumbs.png    |  Bin 0 -> 1222 bytes
 dijit/themes/claro/form/images/sliderVertical.png  |  Bin 0 -> 177 bytes
 dijit/themes/claro/form/images/textBox_back.png    |  Bin 0 -> 2837 bytes
 dijit/themes/claro/images/calendarArrows.png       |  Bin 0 -> 1425 bytes
 dijit/themes/claro/images/calendarArrows8bit.png   |  Bin 0 -> 1053 bytes
 .../claro/images/calendarContainerImages.png       |  Bin 0 -> 3347 bytes
 .../{tundra => claro}/images/checkmarkNoBorder.gif |  Bin 1658 -> 1658 bytes
 .../{tundra => claro}/images/checkmarkNoBorder.png |  Bin 4401 -> 4401 bytes
 dijit/themes/claro/images/commonHighlight.png      |  Bin 0 -> 339 bytes
 dijit/themes/claro/images/dialogCloseIcon.png      |  Bin 0 -> 1660 bytes
 dijit/themes/claro/images/dialogCloseIcon8bit.png  |  Bin 0 -> 705 bytes
 dijit/themes/claro/images/dnd.png                  |  Bin 0 -> 2996 bytes
 dijit/themes/{tundra => claro}/images/loading.gif  |  Bin 751 -> 751 bytes
 dijit/themes/claro/images/loadingAnimation.gif     |  Bin 0 -> 718 bytes
 dijit/themes/claro/images/menuHighlight.png        |  Bin 0 -> 339 bytes
 dijit/themes/claro/images/progressBarAnim.gif      |  Bin 0 -> 4458 bytes
 dijit/themes/claro/images/progressBarEmpty.png     |  Bin 0 -> 2849 bytes
 dijit/themes/claro/images/progressBarFull.png      |  Bin 0 -> 177 bytes
 dijit/themes/claro/images/spriteArrows.png         |  Bin 0 -> 233 bytes
 dijit/themes/claro/images/titlebar.png             |  Bin 0 -> 640 bytes
 dijit/themes/claro/images/tooltip.png              |  Bin 0 -> 1941 bytes
 dijit/themes/claro/images/tooltip8bit.png          |  Bin 0 -> 589 bytes
 dijit/themes/claro/images/treeExpandImages.png     |  Bin 0 -> 676 bytes
 dijit/themes/claro/images/treeExpandImages8bit.png |  Bin 0 -> 799 bytes
 dijit/themes/claro/images/treeExpand_loading.gif   |  Bin 0 -> 1944 bytes
 dijit/themes/claro/layout/AccordionContainer.css   |  108 +
 dijit/themes/claro/layout/BorderContainer.css      |  134 +
 dijit/themes/claro/layout/ContentPane.css          |   40 +
 dijit/themes/claro/layout/TabContainer.css         |  439 +
 dijit/themes/claro/layout/TabContainer_rtl.css     |   77 +
 dijit/themes/claro/layout/images/accordion.png     |  Bin 0 -> 640 bytes
 .../layout/images/splitterHorizontalHover.png      |  Bin 0 -> 3711 bytes
 .../claro/layout/images/splitterVerticalHover.png  |  Bin 0 -> 3869 bytes
 dijit/themes/claro/layout/images/tabBottom.png     |  Bin 0 -> 753 bytes
 dijit/themes/claro/layout/images/tabClose.png      |  Bin 0 -> 1410 bytes
 dijit/themes/claro/layout/images/tabLeft.png       |  Bin 0 -> 1692 bytes
 dijit/themes/claro/layout/images/tabNested.png     |  Bin 0 -> 272 bytes
 dijit/themes/claro/layout/images/tabRight.png      |  Bin 0 -> 1759 bytes
 dijit/themes/claro/layout/images/tabTop.png        |  Bin 0 -> 748 bytes
 dijit/themes/dijit.css                             | 1488 +-
 dijit/themes/dijit_rtl.css                         |  150 +-
 dijit/themes/nihilo/Calendar.css                   |   59 +-
 dijit/themes/nihilo/Calendar_rtl.css               |    2 +
 dijit/themes/nihilo/ColorPalette.css               |    2 +-
 dijit/themes/nihilo/Common.css                     |    6 +-
 dijit/themes/nihilo/Dialog.css                     |   66 +-
 dijit/themes/nihilo/Dialog_rtl.css                 |    1 +
 dijit/themes/nihilo/Editor.css                     |   61 +-
 dijit/themes/nihilo/Editor_rtl.css                 |   11 +-
 dijit/themes/nihilo/Menu.css                       |   21 +-
 dijit/themes/nihilo/Menu_rtl.css                   |    4 +-
 dijit/themes/nihilo/ProgressBar.css                |   19 +-
 dijit/themes/nihilo/TimePicker.css                 |   21 +-
 dijit/themes/nihilo/TimePicker_rtl.css             |    4 +
 dijit/themes/nihilo/TitlePane.css                  |   41 +-
 dijit/themes/nihilo/TitlePane_rtl.css              |    2 +-
 dijit/themes/nihilo/Toolbar.css                    |   21 +-
 dijit/themes/nihilo/Tree.css                       |   53 +-
 dijit/themes/nihilo/Tree_rtl.css                   |   28 +-
 dijit/themes/nihilo/form/Button.css                |   88 +-
 dijit/themes/nihilo/form/Button_rtl.css            |    1 +
 dijit/themes/nihilo/form/Checkbox.css              |   45 +-
 dijit/themes/nihilo/form/ComboBox.css              |   10 -
 dijit/themes/nihilo/form/Common.css                |   76 +-
 dijit/themes/nihilo/form/Common_rtl.css            |    7 -
 dijit/themes/nihilo/form/RadioButton.css           |   44 +-
 dijit/themes/nihilo/form/Select.css                |   24 +-
 dijit/themes/nihilo/form/Slider.css                |   32 +-
 dijit/themes/nihilo/form/Slider_rtl.css            |    7 +
 dijit/themes/nihilo/form/TimeTextBox.css           |    2 +-
 dijit/themes/nihilo/images/editor.gif              |  Bin 5409 -> 0 bytes
 dijit/themes/nihilo/images/editorDisabled.gif      |  Bin 4979 -> 0 bytes
 dijit/themes/nihilo/images/editorDisabled_rtl.gif  |  Bin 4994 -> 0 bytes
 dijit/themes/nihilo/images/editor_rtl.gif          |  Bin 5424 -> 0 bytes
 dijit/themes/nihilo/layout/AccordionContainer.css  |   17 +-
 .../nihilo/layout/AccordionContainer_rtl.css       |    5 +-
 dijit/themes/nihilo/layout/BorderContainer.css     |   25 +-
 dijit/themes/nihilo/layout/ContentPane.css         |    8 +-
 dijit/themes/nihilo/layout/SplitContainer.css      |    9 +-
 dijit/themes/nihilo/layout/TabContainer.css        |  245 +-
 dijit/themes/nihilo/layout/TabContainer_rtl.css    |   13 +-
 dijit/themes/nihilo/nihilo.css                     | 3199 +--
 dijit/themes/nihilo/nihilo_rtl.css                 |  246 +-
 dijit/themes/soria/Calendar.css                    |   58 +-
 dijit/themes/soria/Calendar_rtl.css                |    2 +
 dijit/themes/soria/ColorPalette.css                |    2 +-
 dijit/themes/soria/Common.css                      |    6 +-
 dijit/themes/soria/Dialog.css                      |   66 +-
 dijit/themes/soria/Dialog_rtl.css                  |    2 +-
 dijit/themes/soria/Editor.css                      |   62 +-
 dijit/themes/soria/Editor_rtl.css                  |    9 +-
 dijit/themes/soria/Menu.css                        |   21 +-
 dijit/themes/soria/Menu_rtl.css                    |    2 +
 dijit/themes/soria/ProgressBar.css                 |   19 +-
 dijit/themes/soria/TimePicker.css                  |   19 +-
 dijit/themes/soria/TimePicker_rtl.css              |    4 +
 dijit/themes/soria/TitlePane.css                   |   41 +-
 dijit/themes/soria/TitlePane_rtl.css               |    2 +-
 dijit/themes/soria/Toolbar.css                     |   19 +-
 dijit/themes/soria/Tree.css                        |   55 +-
 dijit/themes/soria/Tree_rtl.css                    |   23 +-
 dijit/themes/soria/form/Button.css                 |   95 +-
 dijit/themes/soria/form/Checkbox.css               |   45 +-
 dijit/themes/soria/form/ComboBox.css               |   10 -
 dijit/themes/soria/form/Common.css                 |   74 +-
 dijit/themes/soria/form/Common_rtl.css             |    7 -
 dijit/themes/soria/form/RadioButton.css            |   44 +-
 dijit/themes/soria/form/Select.css                 |   24 +-
 dijit/themes/soria/form/Slider.css                 |   33 +-
 dijit/themes/soria/form/Slider_rtl.css             |    7 +
 dijit/themes/soria/form/TimeTextBox.css            |    2 +-
 dijit/themes/soria/images/editor.gif               |  Bin 5409 -> 0 bytes
 dijit/themes/soria/images/editorDisabled.gif       |  Bin 4979 -> 0 bytes
 dijit/themes/soria/images/editorDisabled_rtl.gif   |  Bin 4994 -> 0 bytes
 dijit/themes/soria/images/editor_rtl.gif           |  Bin 5424 -> 0 bytes
 dijit/themes/soria/layout/AccordionContainer.css   |   19 +-
 .../themes/soria/layout/AccordionContainer_rtl.css |    5 +-
 dijit/themes/soria/layout/BorderContainer.css      |   26 +-
 dijit/themes/soria/layout/ContentPane.css          |    8 +-
 dijit/themes/soria/layout/SplitContainer.css       |    9 +-
 dijit/themes/soria/layout/TabContainer.css         |  189 +-
 dijit/themes/soria/layout/TabContainer_rtl.css     |   13 +-
 dijit/themes/soria/soria.css                       | 3144 +--
 dijit/themes/soria/soria_rtl.css                   |  241 +-
 dijit/themes/themeTester.html                      | 1235 +
 .../themeTesterImages/blackButtonEnabled.gif       |  Bin 0 -> 151 bytes
 .../themes/themeTesterImages/blackButtonHover.gif  |  Bin 0 -> 99 bytes
 dijit/themes/themeTesterQuirk.html                 |    5 +
 dijit/themes/tundra/Calendar.css                   |   70 +-
 dijit/themes/tundra/Calendar_rtl.css               |    6 +-
 dijit/themes/tundra/ColorPalette.css               |    2 +-
 dijit/themes/tundra/Common.css                     |    8 +-
 dijit/themes/tundra/Dialog.css                     |   73 +-
 dijit/themes/tundra/Dialog_rtl.css                 |    4 +-
 dijit/themes/tundra/Editor.css                     |   63 +-
 dijit/themes/tundra/Editor_rtl.css                 |   13 +-
 dijit/themes/tundra/Menu.css                       |   21 +-
 dijit/themes/tundra/Menu_rtl.css                   |    8 +-
 dijit/themes/tundra/ProgressBar.css                |   13 +-
 dijit/themes/tundra/TimePicker.css                 |   20 +-
 dijit/themes/tundra/TimePicker_rtl.css             |    4 +
 dijit/themes/tundra/TitlePane.css                  |   42 +-
 dijit/themes/tundra/TitlePane_rtl.css              |    4 +-
 dijit/themes/tundra/Toolbar.css                    |   33 +-
 dijit/themes/tundra/Tree.css                       |   53 +-
 dijit/themes/tundra/Tree_rtl.css                   |   18 +-
 dijit/themes/tundra/form/Button.css                |  112 +-
 dijit/themes/tundra/form/Checkbox.css              |   29 +-
 dijit/themes/tundra/form/Common.css                |  111 +-
 dijit/themes/tundra/form/Common_rtl.css            |    6 -
 dijit/themes/tundra/form/RadioButton.css           |   46 +-
 dijit/themes/tundra/form/Select.css                |   46 +-
 dijit/themes/tundra/form/Slider.css                |   26 +-
 dijit/themes/tundra/form/Slider_rtl.css            |   29 +-
 dijit/themes/tundra/images/checkmark.gif           |  Bin 2060 -> 2060 bytes
 dijit/themes/tundra/images/checkmarkNoBorder.gif   |  Bin 1658 -> 1658 bytes
 dijit/themes/tundra/images/checkmarkNoBorder.png   |  Bin 4401 -> 4401 bytes
 dijit/themes/tundra/images/circleIcon.gif          |  Bin 204 -> 204 bytes
 dijit/themes/tundra/images/circleIcon.png          |  Bin 2975 -> 2975 bytes
 .../themes/tundra/images/dojoTundraGradientBg.gif  |  Bin 65 -> 65 bytes
 dijit/themes/tundra/images/editor.gif              |  Bin 5409 -> 0 bytes
 dijit/themes/tundra/images/editorDisabled.gif      |  Bin 4979 -> 0 bytes
 dijit/themes/tundra/images/editorDisabled_rtl.gif  |  Bin 4994 -> 0 bytes
 dijit/themes/tundra/images/editorMaster.png        |  Bin 10338 -> 0 bytes
 dijit/themes/tundra/images/editor_rtl.gif          |  Bin 5424 -> 0 bytes
 dijit/themes/tundra/images/i.gif                   |  Bin 48 -> 48 bytes
 dijit/themes/tundra/images/i_half.gif              |  Bin 63 -> 63 bytes
 dijit/themes/tundra/images/loading.gif             |  Bin 751 -> 751 bytes
 dijit/themes/tundra/images/noX.gif                 |  Bin 80 -> 80 bytes
 dijit/themes/tundra/images/preciseSliderThumb.gif  |  Bin 212 -> 212 bytes
 dijit/themes/tundra/images/sliderFullFocus.png     |  Bin 163 -> 163 bytes
 .../tundra/images/sliderFullVerticalFocus.png      |  Bin 164 -> 164 bytes
 dijit/themes/tundra/images/tabClose.gif            |  Bin 193 -> 193 bytes
 dijit/themes/tundra/images/tabCloseHover.gif       |  Bin 193 -> 193 bytes
 dijit/themes/tundra/images/tabHover.gif            |  Bin 156 -> 156 bytes
 dijit/themes/tundra/images/treeExpand_minus.gif    |  Bin 211 -> 211 bytes
 dijit/themes/tundra/images/treeExpand_plus.gif     |  Bin 216 -> 216 bytes
 dijit/themes/tundra/images/validationInputBg.gif   |  Bin 109 -> 109 bytes
 dijit/themes/tundra/layout/AccordionContainer.css  |   14 +-
 dijit/themes/tundra/layout/BorderContainer.css     |   20 +-
 dijit/themes/tundra/layout/ContentPane.css         |    8 +-
 dijit/themes/tundra/layout/SplitContainer.css      |    6 +-
 dijit/themes/tundra/layout/TabContainer.css        |  146 +-
 dijit/themes/tundra/layout/TabContainer_rtl.css    |   38 +-
 dijit/themes/tundra/tundra.css                     | 3269 +--
 dijit/themes/tundra/tundra_rtl.css                 |  212 +-
 dijit/tree/ForestStoreModel.js                     |  318 +-
 dijit/tree/TreeStoreModel.js                       |  504 +-
 dijit/tree/_dndContainer.js                        |  196 +-
 dijit/tree/_dndSelector.js                         |  337 +-
 dijit/tree/dndSource.js                            |  758 +-
 dijit/tree/model.js                                |  148 +-
 dojo/AdapterRegistry.js                            |  128 +-
 dojo/DeferredList.js                               |  137 +-
 dojo/LICENSE                                       |    2 +-
 dojo/NodeList-fx.js                                |  243 +-
 dojo/NodeList-html.js                              |   53 +-
 dojo/NodeList-manipulate.js                        |  924 +-
 dojo/NodeList-traverse.js                          |  631 +-
 dojo/OpenAjax.js                                   |  343 +-
 dojo/Stateful.js                                   |  123 +
 dojo/_base.js                                      |   14 +-
 dojo/_base/Color.js                                |  308 +-
 dojo/_base/Deferred.js                             |  460 +-
 dojo/_base/NodeList.js                             | 1228 +-
 dojo/_base/_loader/bootstrap.js                    |  615 +-
 dojo/_base/_loader/hostenv_browser.js              |  695 +-
 dojo/_base/_loader/hostenv_ff_ext.js               |  494 +-
 dojo/_base/_loader/hostenv_rhino.js                |  314 +-
 dojo/_base/_loader/hostenv_spidermonkey.js         |  104 +-
 dojo/_base/_loader/loader.js                       | 1091 +-
 dojo/_base/_loader/loader_debug.js                 |  126 +-
 dojo/_base/_loader/loader_xd.js                    | 1139 +-
 dojo/_base/array.js                                |  340 +-
 dojo/_base/browser.js                              |   20 +-
 dojo/_base/connect.js                              |  381 +-
 dojo/_base/declare.js                              | 1406 +-
 dojo/_base/event.js                                | 1003 +-
 dojo/_base/fx.js                                   |  953 +-
 dojo/_base/html.js                                 | 2605 +-
 dojo/_base/json.js                                 |  214 +-
 dojo/_base/lang.js                                 |  529 +-
 dojo/_base/query-sizzle.js                         | 1450 +-
 dojo/_base/query.js                                | 2427 +-
 dojo/_base/window.js                               |  134 +-
 dojo/_base/xhr.js                                  | 1361 +-
 dojo/_firebug/firebug.css                          |    5 +-
 dojo/_firebug/firebug.js                           | 2117 +-
 dojo/back.js                                       |  653 +-
 dojo/behavior.js                                   |  327 +-
 dojo/build.txt                                     |  308 -
 dojo/cache.js                                      |  162 +-
 dojo/cldr/monetary.js                              |   43 +-
 dojo/cldr/nls/ar/currency.js                       |   15 +-
 dojo/cldr/nls/ar/gregorian.js                      |  236 +-
 dojo/cldr/nls/ar/hebrew.js                         |  121 +-
 dojo/cldr/nls/ar/islamic-civil.js                  |  222 +-
 dojo/cldr/nls/ar/islamic.js                        |  153 +-
 dojo/cldr/nls/ar/number.js                         |   26 +-
 dojo/cldr/nls/buddhist.js                          |  236 +
 dojo/cldr/nls/ca/currency.js                       |   14 +-
 dojo/cldr/nls/ca/gregorian.js                      |  232 +-
 dojo/cldr/nls/ca/number.js                         |   20 +-
 dojo/cldr/nls/cs/currency.js                       |   14 +-
 dojo/cldr/nls/cs/gregorian.js                      |  195 +-
 dojo/cldr/nls/cs/number.js                         |   20 +-
 dojo/cldr/nls/currency.js                          |   13 +-
 dojo/cldr/nls/da/currency.js                       |   15 +-
 dojo/cldr/nls/da/gregorian.js                      |  233 +-
 dojo/cldr/nls/da/number.js                         |   20 +-
 dojo/cldr/nls/de-de/number.js                      |    1 -
 dojo/cldr/nls/de/currency.js                       |   16 +-
 dojo/cldr/nls/de/gregorian.js                      |  235 +-
 dojo/cldr/nls/de/number.js                         |   20 +-
 dojo/cldr/nls/el/currency.js                       |   14 +-
 dojo/cldr/nls/el/gregorian.js                      |  239 +-
 dojo/cldr/nls/el/number.js                         |   18 +-
 dojo/cldr/nls/en-au/currency.js                    |    7 +-
 dojo/cldr/nls/en-au/gregorian.js                   |   16 +-
 dojo/cldr/nls/en-au/number.js                      |    5 +-
 dojo/cldr/nls/en-ca/currency.js                    |    7 +-
 dojo/cldr/nls/en-ca/gregorian.js                   |   19 +-
 dojo/cldr/nls/en-gb/gregorian.js                   |   22 +-
 dojo/cldr/nls/en-gb/number.js                      |    5 +-
 dojo/cldr/nls/en-us/currency.js                    |    1 -
 dojo/cldr/nls/en-us/number.js                      |    1 -
 dojo/cldr/nls/en/currency.js                       |   16 +-
 dojo/cldr/nls/en/gregorian.js                      |  226 +-
 dojo/cldr/nls/en/number.js                         |   20 +-
 dojo/cldr/nls/es-es/gregorian.js                   |    1 -
 dojo/cldr/nls/es-es/number.js                      |    1 -
 dojo/cldr/nls/es/currency.js                       |   14 +-
 dojo/cldr/nls/es/gregorian.js                      |  235 +-
 dojo/cldr/nls/es/number.js                         |   19 +-
 dojo/cldr/nls/fi/currency.js                       |   21 +-
 dojo/cldr/nls/fi/gregorian.js                      |  236 +-
 dojo/cldr/nls/fi/number.js                         |   20 +-
 dojo/cldr/nls/fr/currency.js                       |   22 +-
 dojo/cldr/nls/fr/gregorian.js                      |  244 +-
 dojo/cldr/nls/fr/number.js                         |   20 +-
 dojo/cldr/nls/gregorian.js                         |  254 +-
 dojo/cldr/nls/he/currency.js                       |   14 +-
 dojo/cldr/nls/he/gregorian.js                      |  210 +-
 dojo/cldr/nls/he/hebrew.js                         |  122 +-
 dojo/cldr/nls/he/islamic.js                        |  116 +-
 dojo/cldr/nls/he/number.js                         |   20 +-
 dojo/cldr/nls/hebrew.js                            |  249 +-
 dojo/cldr/nls/hu/currency.js                       |   16 +-
 dojo/cldr/nls/hu/gregorian.js                      |  220 +-
 dojo/cldr/nls/hu/number.js                         |   19 +-
 dojo/cldr/nls/islamic-civil.js                     |    1 -
 dojo/cldr/nls/islamic.js                           |  237 +-
 dojo/cldr/nls/it-it/gregorian.js                   |    1 -
 dojo/cldr/nls/it/currency.js                       |   14 +-
 dojo/cldr/nls/it/gregorian.js                      |  231 +-
 dojo/cldr/nls/it/number.js                         |   10 +-
 dojo/cldr/nls/ja-jp/number.js                      |    1 -
 dojo/cldr/nls/ja/currency.js                       |   17 +-
 dojo/cldr/nls/ja/gregorian.js                      |  219 +-
 dojo/cldr/nls/ja/number.js                         |   10 +-
 dojo/cldr/nls/ko-kr/gregorian.js                   |    1 -
 dojo/cldr/nls/ko-kr/number.js                      |    1 -
 dojo/cldr/nls/ko/currency.js                       |   14 +-
 dojo/cldr/nls/ko/gregorian.js                      |  239 +-
 dojo/cldr/nls/ko/number.js                         |   20 +-
 dojo/cldr/nls/nb/currency.js                       |   22 +-
 dojo/cldr/nls/nb/gregorian.js                      |  231 +-
 dojo/cldr/nls/nb/number.js                         |   20 +-
 dojo/cldr/nls/nl/currency.js                       |   14 +-
 dojo/cldr/nls/nl/gregorian.js                      |  229 +-
 dojo/cldr/nls/nl/number.js                         |   20 +-
 dojo/cldr/nls/number.js                            |   26 +-
 dojo/cldr/nls/pl/currency.js                       |   14 +-
 dojo/cldr/nls/pl/gregorian.js                      |  239 +-
 dojo/cldr/nls/pl/number.js                         |   20 +-
 dojo/cldr/nls/pt-br/gregorian.js                   |    1 -
 dojo/cldr/nls/pt-pt/gregorian.js                   |  133 +-
 dojo/cldr/nls/pt-pt/number.js                      |    6 +-
 dojo/cldr/nls/pt/currency.js                       |   14 +-
 dojo/cldr/nls/pt/gregorian.js                      |  234 +-
 dojo/cldr/nls/pt/number.js                         |   20 +-
 dojo/cldr/nls/ru/currency.js                       |   15 +-
 dojo/cldr/nls/ru/gregorian.js                      |  229 +-
 dojo/cldr/nls/ru/number.js                         |   19 +-
 dojo/cldr/nls/sk/currency.js                       |   14 +-
 dojo/cldr/nls/sk/gregorian.js                      |  222 +-
 dojo/cldr/nls/sk/number.js                         |    7 +-
 dojo/cldr/nls/sl/currency.js                       |   16 +-
 dojo/cldr/nls/sl/gregorian.js                      |  210 +-
 dojo/cldr/nls/sl/number.js                         |   20 +-
 dojo/cldr/nls/sv/currency.js                       |   17 +-
 dojo/cldr/nls/sv/gregorian.js                      |  242 +-
 dojo/cldr/nls/sv/number.js                         |   20 +-
 dojo/cldr/nls/th/buddhist.js                       |  115 +-
 dojo/cldr/nls/th/currency.js                       |   15 +-
 dojo/cldr/nls/th/gregorian.js                      |  229 +-
 dojo/cldr/nls/th/number.js                         |   20 +-
 dojo/cldr/nls/tr/currency.js                       |   16 +-
 dojo/cldr/nls/tr/gregorian.js                      |  236 +-
 dojo/cldr/nls/tr/number.js                         |   20 +-
 dojo/cldr/nls/zh-cn/gregorian.js                   |    1 -
 dojo/cldr/nls/zh-cn/number.js                      |    1 -
 dojo/cldr/nls/zh-tw/currency.js                    |  346 +-
 dojo/cldr/nls/zh-tw/gregorian.js                   |  177 +-
 dojo/cldr/nls/zh-tw/number.js                      |    1 -
 dojo/cldr/nls/zh/currency.js                       |   15 +-
 dojo/cldr/nls/zh/gregorian.js                      |  244 +-
 dojo/cldr/nls/zh/number.js                         |   10 +-
 dojo/cldr/supplemental.js                          |  105 +-
 dojo/colors.js                                     |  291 +-
 dojo/cookie.js                                     |  131 +-
 dojo/currency.js                                   |  152 +-
 dojo/data/ItemFileReadStore.js                     | 1498 +-
 dojo/data/ItemFileWriteStore.js                    | 1313 +-
 dojo/data/api/Identity.js                          |  125 +-
 dojo/data/api/Notification.js                      |  132 +-
 dojo/data/api/Read.js                              |  553 +-
 dojo/data/api/Request.js                           |   38 +-
 dojo/data/api/Write.js                             |  257 +-
 dojo/data/util/filter.js                           |  111 +-
 dojo/data/util/simpleFetch.js                      |  144 +-
 dojo/data/util/sorter.js                           |  151 +-
 dojo/date.js                                       |  535 +-
 dojo/date/locale.js                                | 1079 +-
 dojo/date/stamp.js                                 |  213 +-
 dojo/dnd/Avatar.js                                 |  165 +-
 dojo/dnd/Container.js                              |  645 +-
 dojo/dnd/Manager.js                                |  327 +-
 dojo/dnd/Moveable.js                               |  240 +-
 dojo/dnd/Mover.js                                  |  165 +-
 dojo/dnd/Selector.js                               |  556 +-
 dojo/dnd/Source.js                                 |  827 +-
 dojo/dnd/TimedMoveable.js                          |  102 +-
 dojo/dnd/autoscroll.js                             |  194 +-
 dojo/dnd/common.js                                 |   46 +-
 dojo/dnd/move.js                                   |  356 +-
 dojo/dojo.js                                       |  214 +-
 dojo/dojo.js.uncompressed.js                       |11239 ---------
 dojo/fx.js                                         |  641 +-
 dojo/fx/Toggler.js                                 |  122 +-
 dojo/fx/easing.js                                  |  437 +-
 dojo/gears.js                                      |   91 +-
 dojo/hash.js                                       |  357 +-
 dojo/html.js                                       |  462 +-
 dojo/i18n.js                                       |  400 +-
 dojo/io/iframe.js                                  |  659 +-
 dojo/io/script.js                                  |  363 +-
 dojo/jaxer.js                                      |   26 +-
 dojo/nls/ar/colors.js                              |  155 +-
 dojo/nls/ca/colors.js                              |  156 +-
 dojo/nls/colors.js                                 |  155 +-
 dojo/nls/cs/colors.js                              |  155 +-
 dojo/nls/da/colors.js                              |  155 +-
 dojo/nls/de/colors.js                              |  155 +-
 dojo/nls/el/colors.js                              |  155 +-
 dojo/nls/es/colors.js                              |  155 +-
 dojo/nls/fi/colors.js                              |  155 +-
 dojo/nls/fr/colors.js                              |  155 +-
 dojo/nls/he/colors.js                              |  155 +-
 dojo/nls/hu/colors.js                              |  155 +-
 dojo/nls/it/colors.js                              |  155 +-
 dojo/nls/ja/colors.js                              |  155 +-
 dojo/nls/ko/colors.js                              |  155 +-
 dojo/nls/nb/colors.js                              |  155 +-
 dojo/nls/nl/colors.js                              |  155 +-
 dojo/nls/pl/colors.js                              |  155 +-
 dojo/nls/pt-pt/colors.js                           |  155 +-
 dojo/nls/pt/colors.js                              |  155 +-
 dojo/nls/ro/colors.js                              |  155 +
 dojo/nls/ru/colors.js                              |  155 +-
 dojo/nls/sk/colors.js                              |  156 +-
 dojo/nls/sl/colors.js                              |  156 +-
 dojo/nls/sv/colors.js                              |  155 +-
 dojo/nls/th/colors.js                              |  156 +-
 dojo/nls/tr/colors.js                              |  155 +-
 dojo/nls/zh-tw/colors.js                           |  155 +-
 dojo/nls/zh/colors.js                              |  155 +-
 dojo/number.js                                     |  867 +-
 dojo/parser.js                                     |  653 +-
 dojo/regexp.js                                     |   86 +-
 dojo/resources/_modules.js                         |   39 +-
 dojo/resources/dnd.css                             |    4 +-
 dojo/resources/dojo.css                            |  109 +-
 dojo/robot.js                                      |  208 +-
 dojo/robotx.js                                     |  185 +-
 dojo/rpc/JsonService.js                            |  112 +-
 dojo/rpc/JsonpService.js                           |   85 +-
 dojo/rpc/RpcService.js                             |  251 +-
 dojo/string.js                                     |  198 +-
 dojo/tests.js                                      |   12 +
 dojo/tests/AdapterRegistry.js                      |   71 +
 dojo/tests/DeferredList.js                         |  202 +
 dojo/tests/NodeList-fx.html                        |  170 +
 dojo/tests/NodeList-manipulate.html                |  380 +
 dojo/tests/NodeList-manipulate.js                  |    4 +
 dojo/tests/NodeList-traverse.html                  |  122 +
 dojo/tests/NodeList-traverse.js                    |    4 +
 dojo/tests/Stateful.js                             |   36 +
 dojo/tests/TODO                                    |   10 +
 dojo/tests/_base.js                                |  134 +
 dojo/tests/_base/Color.js                          |   28 +
 dojo/tests/_base/Deferred.js                       |  180 +
 dojo/tests/_base/NodeList.html                     |  617 +
 dojo/tests/_base/_loader/8976.html                 |   32 +
 dojo/tests/_base/_loader/addLoadEvents.html        |   45 +
 dojo/tests/_base/_loader/afterOnLoad.html          |   71 +
 dojo/tests/_base/_loader/bootstrap.js              |  123 +
 dojo/tests/_base/_loader/debugConsole.html         |   51 +
 dojo/tests/_base/_loader/fastbackTest.html         |   34 +
 dojo/tests/_base/_loader/getText.txt               |    1 +
 dojo/tests/_base/_loader/hostenv_browser.js        |   11 +
 dojo/tests/_base/_loader/hostenv_rhino.js          |   13 +
 dojo/tests/_base/_loader/hostenv_spidermonkey.js   |   11 +
 dojo/tests/_base/_loader/loader.js                 |  115 +
 dojo/tests/_base/_loader/scope/scope04.html        |   80 +
 dojo/tests/_base/_loader/scope/scopeContained.html |   71 +
 .../_base/_loader/scope/scopeContainedXd.html      |   84 +
 dojo/tests/_base/_loader/scope/scopeDjConfig.html  |   64 +
 dojo/tests/_base/_loader/scope/scopeSingle.html    |   62 +
 .../tests/_base/_loader/scope/scopeSingleDaac.html |   63 +
 dojo/tests/_base/abs.html                          |  102 +
 dojo/tests/_base/absQuirk.html                     |  101 +
 dojo/tests/_base/absQuirksIframe.html              |   10 +
 dojo/tests/_base/absStrictIframe.html              |   10 +
 dojo/tests/_base/array.js                          |  304 +
 dojo/tests/_base/connect.js                        |  221 +
 dojo/tests/_base/declare.js                        |  470 +
 dojo/tests/_base/eventKeyPress.html                |   84 +
 dojo/tests/_base/eventKeyPressRobot.html           |  165 +
 dojo/tests/_base/fx.html                           |  567 +
 dojo/tests/_base/fx.js                             |    4 +
 dojo/tests/_base/fx_delay.html                     |   22 +
 dojo/tests/_base/html.html                         |  797 +
 dojo/tests/_base/html.js                           |   12 +
 dojo/tests/_base/html_box.html                     |  207 +
 dojo/tests/_base/html_box_quirks.html              |  205 +
 dojo/tests/_base/html_docScroll.html               |  102 +
 dojo/tests/_base/html_element.html                 |  308 +
 dojo/tests/_base/html_id.html                      |   94 +
 dojo/tests/_base/html_isBodyLtr.html               |   60 +
 dojo/tests/_base/html_quirks.html                  |  331 +
 dojo/tests/_base/html_rtl.html                     |  130 +
 dojo/tests/_base/json.js                           |   33 +
 dojo/tests/_base/lang.js                           |  279 +
 dojo/tests/_base/object.js                         |   42 +
 dojo/tests/_base/query.html                        |  325 +
 dojo/tests/_base/query.js                          |    5 +
 dojo/tests/_base/queryPortability.html             |   24 +
 dojo/tests/_base/timeout.php                       |    7 +
 dojo/tests/_base/window.js                         |   52 +
 dojo/tests/_base/xhr.html                          |  519 +
 dojo/tests/_base/xhr.js                            |    4 +
 dojo/tests/_base/xhr.xml                           |    2 +
 dojo/tests/_base/xhrDummyMethod.php                |    7 +
 dojo/tests/_base/xhtml.php                         |   29 +
 dojo/tests/back-hash.js                            |   29 +
 dojo/tests/back.html                               |  107 +
 dojo/tests/back.js                                 |    4 +
 dojo/tests/behavior.html                           |  106 +
 dojo/tests/behavior.js                             |    4 +
 dojo/tests/cache.js                                |   33 +
 dojo/tests/cache/object.html                       |   11 +
 dojo/tests/cache/regular.html                      |    1 +
 dojo/tests/cache/sanitized.html                    |   11 +
 dojo/tests/cldr.js                                 |   15 +
 dojo/tests/colors.js                               |   44 +
 dojo/tests/cookie.html                             |   84 +
 dojo/tests/cookie.js                               |    4 +
 dojo/tests/currency.js                             |   46 +
 dojo/tests/data.js                                 |    8 +
 dojo/tests/data/ItemFileReadStore.js               |    6 +
 dojo/tests/data/ItemFileWriteStore.js              | 1586 ++
 dojo/tests/data/countries.json                     |   11 +
 dojo/tests/data/countries_commentFiltered.json     |   12 +
 dojo/tests/data/countries_idcollision.json         |   10 +
 dojo/tests/data/countries_references.json          |   44 +
 dojo/tests/data/countries_withBoolean.json         |   11 +
 dojo/tests/data/countries_withDates.json           |   21 +
 dojo/tests/data/countries_withNull.json            |   10 +
 dojo/tests/data/countries_withoutid.json           |   10 +
 dojo/tests/data/data_multitype.json                |   18 +
 dojo/tests/data/geography_hierarchy_large.json     |   44 +
 dojo/tests/data/geography_hierarchy_small.json     |   19 +
 dojo/tests/data/readOnlyItemFileTestTemplates.js   | 3105 +++
 dojo/tests/data/reference_integrity.json           |   27 +
 dojo/tests/data/runTests.html                      |    9 +
 dojo/tests/data/utils.js                           |  199 +
 dojo/tests/date.js                                 |  712 +
 dojo/tests/date/locale.js                          |  430 +
 dojo/tests/date/stamp.js                           |   98 +
 dojo/tests/dnd/dndDefault.css                      |   77 +
 dojo/tests/dnd/flickr_viewer.html                  |  168 +
 dojo/tests/dnd/robot/test_dnd.html                 |  100 +
 dojo/tests/dnd/test_box_constraints.html           |   61 +
 dojo/tests/dnd/test_container.html                 |   74 +
 dojo/tests/dnd/test_container_markup.html          |   67 +
 dojo/tests/dnd/test_custom_constraints.html        |   51 +
 dojo/tests/dnd/test_dnd.html                       |  141 +
 dojo/tests/dnd/test_dnd_handles.html               |   65 +
 dojo/tests/dnd/test_form.html                      |  103 +
 dojo/tests/dnd/test_moveable.html                  |  106 +
 dojo/tests/dnd/test_moveable_markup.html           |   83 +
 dojo/tests/dnd/test_params.html                    |   61 +
 dojo/tests/dnd/test_parent_constraints.html        |   53 +
 .../tests/dnd/test_parent_constraints_margins.html |   51 +
 dojo/tests/dnd/test_selector.html                  |   80 +
 dojo/tests/dnd/test_selector_markup.html           |   71 +
 dojo/tests/dnd/test_timed_moveable.html            |  112 +
 dojo/tests/fx.html                                 |  448 +
 dojo/tests/fx.js                                   |    5 +
 dojo/tests/hash.js                                 |  324 +
 dojo/tests/html.js                                 |    4 +
 dojo/tests/html/test_set.html                      |  500 +
 dojo/tests/i18n.js                                 |   84 +
 dojo/tests/io/iframe.html                          |  164 +
 dojo/tests/io/iframe.js                            |    4 +
 dojo/tests/io/iframeResponse.html                  |    8 +
 dojo/tests/io/iframeResponse.js.html               |    7 +
 dojo/tests/io/iframeResponse.json.html             |    7 +
 dojo/tests/io/iframeResponse.text.html             |    7 +
 dojo/tests/io/iframeResponse.xml                   |   17 +
 dojo/tests/io/iframeUploadTest.html                |   50 +
 dojo/tests/io/script.html                          |  119 +
 dojo/tests/io/script.js                            |    4 +
 dojo/tests/io/scriptJsonp.js                       |   57 +
 dojo/tests/io/scriptLoad.js                        |    2 +
 dojo/tests/io/scriptSimple.js                      |    5 +
 dojo/tests/io/scriptTimeout.html                   |   67 +
 dojo/tests/io/upload.cgi                           |   62 +
 dojo/tests/module.js                               |   34 +
 dojo/tests/nls/ar/salutations.js                   |    8 +
 dojo/tests/nls/cs/salutations.js                   |    4 +
 dojo/tests/nls/de/salutations.js                   |    4 +
 dojo/tests/nls/el/salutations.js                   |    4 +
 dojo/tests/nls/en-au/salutations.js                |    3 +
 dojo/tests/nls/en-us-hawaii/salutations.js         |    3 +
 .../nls/en-us-new_york-brooklyn/salutations.js     |    3 +
 dojo/tests/nls/en-us-texas/salutations.js          |    3 +
 dojo/tests/nls/es/salutations.js                   |    5 +
 dojo/tests/nls/fa/salutations.js                   |    4 +
 dojo/tests/nls/fr/salutations.js                   |    4 +
 dojo/tests/nls/he/salutations.js                   |    4 +
 dojo/tests/nls/hi/salutations.js                   |    4 +
 dojo/tests/nls/it/salutations.js                   |    4 +
 dojo/tests/nls/ja/salutations.js                   |    4 +
 dojo/tests/nls/ko/salutations.js                   |    4 +
 dojo/tests/nls/pl/salutations.js                   |    4 +
 dojo/tests/nls/pt/salutations.js                   |    4 +
 dojo/tests/nls/ru/salutations.js                   |    4 +
 dojo/tests/nls/salutations.js                      |   32 +
 dojo/tests/nls/sw/salutations.js                   |    3 +
 dojo/tests/nls/th/salutations.js                   |    4 +
 dojo/tests/nls/tr/salutations.js                   |    4 +
 dojo/tests/nls/yi/salutations.js                   |    4 +
 dojo/tests/nls/zh-cn/salutations.js                |    4 +
 dojo/tests/nls/zh-tw/salutations.js                |    4 +
 dojo/tests/number.js                               | 1119 +
 dojo/tests/parser.html                             |  408 +
 dojo/tests/parser.js                               |    4 +
 dojo/tests/regexp.js                               |   12 +
 dojo/tests/resources/ApplicationState.js           |   28 +
 dojo/tests/resources/JSON.php                      |  724 +
 dojo/tests/resources/testClass.php                 |   20 +
 dojo/tests/resources/testClass.smd                 |   39 +
 dojo/tests/resources/test_JsonRPCMediator.php      |   43 +
 dojo/tests/resources/test_css.html                 |  100 +
 dojo/tests/resources/yahoo_smd_v1.smd              |  268 +
 dojo/tests/rpc.js                                  |  147 +
 dojo/tests/runTests.html                           |    9 +
 dojo/tests/string.js                               |   92 +
 dojo/tests/test_FirebugLite.html                   |  100 +
 dojo/tests/test_FirebugLitePopup.html              |  101 +
 dojo/tests/test_fx.html                            |  108 +
 dojo/tests/uacss.js                                |   10 +
 dojo/tests/uacss/sniffQuirks.html                  |   65 +
 dojo/tests/uacss/sniffStandards.html               |   63 +
 dojo/tests/window.js                               |   11 +
 dojo/tests/window/test_scroll.html                 |  640 +
 dojo/tests/window/test_scrollNoDTD.html            |   74 +
 dojo/tests/window/test_scrollStrictDTD.html        |   76 +
 dojo/tests/window/viewport.html                    |   82 +
 dojo/tests/window/viewportQuirks.html              |    5 +
 dojo/uacss.js                                      |   63 +
 dojo/window.js                                     |  132 +
 dojox/LICENSE                                      |    2 +-
 dojox/analytics.js                                 |   11 +-
 dojox/analytics/Urchin.js                          |  155 +-
 dojox/analytics/_base.js                           |  208 +-
 dojox/analytics/logger/JSON.php                    |  724 +
 dojox/analytics/logger/dojoxAnalytics.php          |   31 +
 dojox/analytics/plugins/consoleMessages.js         |   41 +-
 dojox/analytics/plugins/dojo.js                    |    4 -
 dojox/analytics/plugins/idle.js                    |   61 +-
 dojox/analytics/plugins/mouseClick.js              |   92 +-
 dojox/analytics/plugins/mouseOver.js               |  158 +-
 dojox/analytics/plugins/window.js                  |   62 +-
 dojox/analytics/profiles/analytics.profile.js      |   27 +-
 .../analytics/profiles/analyticsInBase.profile.js  |   28 +-
 dojox/analytics/tests/test_GoogleAnalytics.html    |   63 +
 .../tests/test_GoogleAnalyticsMarkup.html          |   52 +
 dojox/analytics/tests/test_analytics.html          |  100 +
 dojox/atom/io/Connection.js                        |  687 +-
 dojox/atom/io/model.js                             | 2232 +-
 dojox/atom/tests/io/app.php                        |    5 +
 dojox/atom/tests/io/appFail.php                    |    8 +
 dojox/atom/tests/io/module.js                      |  517 +
 dojox/atom/tests/io/runTests.html                  |    9 +
 dojox/atom/tests/io/sampleEntry.xml                |   21 +
 dojox/atom/tests/io/sampleFeedXMLContent.xml       |   42 +
 dojox/atom/tests/io/samplefeedEdit.xml             |   54 +
 dojox/atom/tests/io/service.xml                    |   10 +
 dojox/atom/tests/widget/samplefeed.xml             |  130 +
 dojox/atom/tests/widget/samplefeedEdit.xml         |  175 +
 dojox/atom/tests/widget/test_FeedViewer_bind.html  |   53 +
 .../test_FeedViewer_bind_split_declarative.html    |  131 +
 .../tests/widget/test_FeedViewer_bind_sync.html    |   53 +
 dojox/atom/tests/widget/test_FeedViewer_local.html |   52 +
 .../widget/test_FeedViewer_local_declarative.html  |   45 +
 dojox/atom/widget/FeedEntryEditor.js               | 1936 +-
 dojox/atom/widget/FeedEntryViewer.js               | 1159 +-
 dojox/atom/widget/FeedViewer.js                    | 1196 +-
 dojox/atom/widget/nls/FeedEntryEditor.js           |    7 +-
 dojox/atom/widget/nls/FeedEntryViewer.js           |   12 +-
 dojox/atom/widget/nls/FeedViewerEntry.js           |    4 +-
 dojox/atom/widget/nls/PeopleEditor.js              |    6 +-
 dojox/atom/widget/nls/ar/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/ar/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/ar/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/ar/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/ca/FeedEntryEditor.js        |    8 +-
 dojox/atom/widget/nls/ca/FeedEntryViewer.js        |   13 +-
 dojox/atom/widget/nls/ca/FeedViewerEntry.js        |    5 +-
 dojox/atom/widget/nls/ca/PeopleEditor.js           |    7 +-
 dojox/atom/widget/nls/cs/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/cs/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/cs/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/cs/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/da/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/da/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/da/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/da/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/de/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/de/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/de/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/de/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/el/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/el/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/el/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/el/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/es/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/es/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/es/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/es/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/fi/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/fi/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/fi/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/fi/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/fr/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/fr/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/fr/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/fr/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/he/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/he/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/he/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/he/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/hu/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/hu/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/hu/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/hu/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/it/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/it/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/it/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/it/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/ja/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/ja/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/ja/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/ja/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/ko/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/ko/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/ko/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/ko/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/nb/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/nb/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/nb/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/nb/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/nl/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/nl/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/nl/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/nl/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/pl/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/pl/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/pl/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/pl/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/pt-pt/FeedEntryEditor.js     |    7 +-
 dojox/atom/widget/nls/pt-pt/FeedEntryViewer.js     |   12 +-
 dojox/atom/widget/nls/pt-pt/FeedViewerEntry.js     |    4 +-
 dojox/atom/widget/nls/pt-pt/PeopleEditor.js        |    6 +-
 dojox/atom/widget/nls/pt/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/pt/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/pt/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/pt/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/ro/FeedEntryEditor.js        |    7 +
 dojox/atom/widget/nls/ro/FeedEntryViewer.js        |   12 +
 dojox/atom/widget/nls/ro/FeedViewerEntry.js        |    4 +
 dojox/atom/widget/nls/ro/PeopleEditor.js           |    6 +
 dojox/atom/widget/nls/ru/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/ru/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/ru/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/ru/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/sk/FeedEntryEditor.js        |    8 +-
 dojox/atom/widget/nls/sk/FeedEntryViewer.js        |   13 +-
 dojox/atom/widget/nls/sk/FeedViewerEntry.js        |    5 +-
 dojox/atom/widget/nls/sk/PeopleEditor.js           |    7 +-
 dojox/atom/widget/nls/sl/FeedEntryEditor.js        |    8 +-
 dojox/atom/widget/nls/sl/FeedEntryViewer.js        |   13 +-
 dojox/atom/widget/nls/sl/FeedViewerEntry.js        |    5 +-
 dojox/atom/widget/nls/sl/PeopleEditor.js           |    7 +-
 dojox/atom/widget/nls/sv/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/sv/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/sv/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/sv/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/th/FeedEntryEditor.js        |    8 +-
 dojox/atom/widget/nls/th/FeedEntryViewer.js        |   13 +-
 dojox/atom/widget/nls/th/FeedViewerEntry.js        |    5 +-
 dojox/atom/widget/nls/th/PeopleEditor.js           |    7 +-
 dojox/atom/widget/nls/tr/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/tr/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/tr/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/tr/PeopleEditor.js           |    6 +-
 dojox/atom/widget/nls/zh-tw/FeedEntryEditor.js     |    7 +-
 dojox/atom/widget/nls/zh-tw/FeedEntryViewer.js     |   12 +-
 dojox/atom/widget/nls/zh-tw/FeedViewerEntry.js     |    4 +-
 dojox/atom/widget/nls/zh-tw/PeopleEditor.js        |    6 +-
 dojox/atom/widget/nls/zh/FeedEntryEditor.js        |    7 +-
 dojox/atom/widget/nls/zh/FeedEntryViewer.js        |   12 +-
 dojox/atom/widget/nls/zh/FeedViewerEntry.js        |    4 +-
 dojox/atom/widget/nls/zh/PeopleEditor.js           |    6 +-
 dojox/atom/widget/templates/css/EntryHeader.css    |   10 +-
 .../widget/templates/css/HtmlFeedEntryEditor.css   |   14 +
 .../widget/templates/css/HtmlFeedEntryViewer.css   |   25 +-
 dojox/atom/widget/templates/css/HtmlFeedViewer.css |    2 +
 .../widget/templates/css/HtmlFeedViewerEntry.css   |   10 +
 dojox/charting/Chart2D.js                          | 1372 +-
 dojox/charting/Chart3D.js                          |  147 +-
 dojox/charting/DataChart.js                        |  731 +-
 dojox/charting/DataSeries.js                       |  183 +
 dojox/charting/Element.js                          |  294 +-
 dojox/charting/Series.js                           |   78 +-
 dojox/charting/Theme.js                            |  686 +-
 dojox/charting/action2d/Base.js                    |  113 +-
 dojox/charting/action2d/Highlight.js               |  194 +-
 dojox/charting/action2d/Magnify.js                 |  173 +-
 dojox/charting/action2d/MoveSlice.js               |  177 +-
 dojox/charting/action2d/Shake.js                   |  164 +-
 dojox/charting/action2d/Tooltip.js                 |  409 +-
 dojox/charting/axis2d/Base.js                      |   94 +-
 dojox/charting/axis2d/Default.js                   |  819 +-
 dojox/charting/axis2d/Invisible.js                 |  290 +
 dojox/charting/axis2d/common.js                    |  238 +-
 dojox/charting/plot2d/Areas.js                     |   24 +-
 dojox/charting/plot2d/Bars.js                      |  262 +-
 dojox/charting/plot2d/Base.js                      |  270 +-
 dojox/charting/plot2d/Bubble.js                    |  305 +-
 dojox/charting/plot2d/Candlesticks.js              |  336 +-
 dojox/charting/plot2d/ClusteredBars.js             |  172 +-
 dojox/charting/plot2d/ClusteredColumns.js          |  172 +-
 dojox/charting/plot2d/Columns.js                   |  245 +-
 dojox/charting/plot2d/Default.js                   |  482 +-
 dojox/charting/plot2d/Grid.js                      |  360 +-
 dojox/charting/plot2d/Lines.js                     |   24 +-
 dojox/charting/plot2d/Markers.js                   |   24 +-
 dojox/charting/plot2d/MarkersOnly.js               |   26 +-
 dojox/charting/plot2d/OHLC.js                      |  315 +-
 dojox/charting/plot2d/Pie.js                       |  590 +-
 dojox/charting/plot2d/Scatter.js                   |  208 +-
 dojox/charting/plot2d/Stacked.js                   |  335 +-
 dojox/charting/plot2d/StackedAreas.js              |   26 +-
 dojox/charting/plot2d/StackedBars.js               |  238 +-
 dojox/charting/plot2d/StackedColumns.js            |  234 +-
 dojox/charting/plot2d/StackedLines.js              |   24 +-
 dojox/charting/plot2d/_PlotEvents.js               |  123 +
 dojox/charting/plot2d/common.js                    |  405 +-
 dojox/charting/plot3d/Bars.js                      |  118 +-
 dojox/charting/plot3d/Base.js                      |   38 +-
 dojox/charting/plot3d/Cylinders.js                 |  126 +-
 dojox/charting/scaler/common.js                    |  104 +-
 dojox/charting/scaler/linear.js                    |  460 +-
 dojox/charting/scaler/primitive.js                 |   56 +-
 dojox/charting/tests/Theme.js                      |   67 +
 dojox/charting/tests/charting.js                   |    7 +
 dojox/charting/tests/data/goog_prices.csv          |  796 +
 dojox/charting/tests/data/msft_prices.csv          |  796 +
 dojox/charting/tests/data/yahoo_prices.csv         |  796 +
 .../charting/tests/gradients/test_grad_bars1.html  |   85 +
 .../charting/tests/gradients/test_grad_bars2.html  |   79 +
 .../charting/tests/gradients/test_grad_bars3.html  |   79 +
 .../charting/tests/gradients/test_grad_bars4.html  |   79 +
 .../charting/tests/gradients/test_grad_bars5.html  |   82 +
 .../tests/gradients/test_grad_bubble1.html         |   71 +
 .../tests/gradients/test_grad_bubble2.html         |   65 +
 .../tests/gradients/test_grad_bubble3.html         |   66 +
 .../tests/gradients/test_grad_bubble4.html         |   65 +
 .../tests/gradients/test_grad_bubble6.html         |   71 +
 .../tests/gradients/test_grad_columns1.html        |   85 +
 .../tests/gradients/test_grad_columns2.html        |   79 +
 .../tests/gradients/test_grad_columns3.html        |   79 +
 .../tests/gradients/test_grad_columns4.html        |   79 +
 .../tests/gradients/test_grad_columns5.html        |   82 +
 dojox/charting/tests/gradients/test_grad_pie1.html |   58 +
 dojox/charting/tests/gradients/test_grad_pie2.html |   52 +
 dojox/charting/tests/gradients/test_grad_pie3.html |   53 +
 dojox/charting/tests/gradients/test_grad_pie4.html |   52 +
 dojox/charting/tests/gradients/test_grad_pie7.html |   52 +
 dojox/charting/tests/gradients/test_grad_pie8.html |   52 +
 dojox/charting/tests/gradients/test_grad_pie9.html |   52 +
 dojox/charting/tests/gradients/test_grad_pieA.html |   52 +
 .../tests/gradients/test_grad_scatter1.html        |   71 +
 .../tests/gradients/test_grad_scatter2.html        |   65 +
 .../tests/gradients/test_grad_scatterB.html        |   54 +
 dojox/charting/tests/runTests.html                 |    9 +
 dojox/charting/tests/stock.json                    |    8 +
 dojox/charting/tests/test_DataChart.html           |  199 +
 dojox/charting/tests/test_DataSeries.html          |  216 +
 dojox/charting/tests/test_anim2d.html              |  108 +
 dojox/charting/tests/test_axes.html                |   81 +
 dojox/charting/tests/test_axisZoomControl.html     |   91 +
 dojox/charting/tests/test_bars.html                |   67 +
 dojox/charting/tests/test_chart2d.html             |  851 +
 dojox/charting/tests/test_chart2d_dynamics.html    |  236 +
 dojox/charting/tests/test_chart2d_updating.html    |   97 +
 dojox/charting/tests/test_cylinders.html           |   67 +
 dojox/charting/tests/test_event2d.html             |  270 +
 dojox/charting/tests/test_fireEvent.html           |  204 +
 dojox/charting/tests/test_labels2d.html            |  214 +
 dojox/charting/tests/test_nulls.html               |   89 +
 dojox/charting/tests/test_pie2d.html               |  164 +
 dojox/charting/tests/test_plot_order.html          |   96 +
 dojox/charting/tests/test_rotatedLabels.html       |   85 +
 dojox/charting/tests/test_scaler.html              |  101 +
 dojox/charting/tests/test_series_order.html        |   88 +
 dojox/charting/tests/test_sparklines.html          |  203 +
 dojox/charting/tests/test_tension.html             |   55 +
 dojox/charting/tests/test_themes.html              |  296 +
 dojox/charting/tests/test_widget2d.html            |  124 +
 dojox/charting/tests/test_win2d.html               |  210 +
 dojox/charting/tests/theme_preview.html            |   69 +
 dojox/charting/themes/Adobebricks.js               |   23 +-
 dojox/charting/themes/Algae.js                     |   23 +-
 dojox/charting/themes/Bahamation.js                |   23 +-
 dojox/charting/themes/BlueDusk.js                  |   23 +-
 dojox/charting/themes/Charged.js                   |   91 +
 dojox/charting/themes/Chris.js                     |   77 +
 dojox/charting/themes/CubanShirts.js               |   25 +-
 dojox/charting/themes/Desert.js                    |   25 +-
 dojox/charting/themes/Distinctive.js               |   52 +-
 dojox/charting/themes/Dollar.js                    |   23 +-
 dojox/charting/themes/ET/greys.js                  |   64 +-
 dojox/charting/themes/Electric.js                  |   92 +
 dojox/charting/themes/Grasshopper.js               |   23 +-
 dojox/charting/themes/Grasslands.js                |   25 +-
 dojox/charting/themes/GreySkies.js                 |   15 +-
 dojox/charting/themes/Harmony.js                   |   52 +-
 dojox/charting/themes/IndigoNation.js              |   25 +-
 dojox/charting/themes/Ireland.js                   |   23 +-
 dojox/charting/themes/Julie.js                     |   70 +
 dojox/charting/themes/MiamiNice.js                 |   23 +-
 dojox/charting/themes/Midwest.js                   |   23 +-
 dojox/charting/themes/Minty.js                     |   23 +-
 dojox/charting/themes/PlotKit/base.js              |   53 +
 dojox/charting/themes/PlotKit/blue.js              |   21 +-
 dojox/charting/themes/PlotKit/cyan.js              |   21 +-
 dojox/charting/themes/PlotKit/green.js             |   21 +-
 dojox/charting/themes/PlotKit/orange.js            |   21 +-
 dojox/charting/themes/PlotKit/purple.js            |   21 +-
 dojox/charting/themes/PlotKit/red.js               |   21 +-
 dojox/charting/themes/PrimaryColors.js             |   14 +
 dojox/charting/themes/PurpleRain.js                |   25 +-
 dojox/charting/themes/Renkoo.js                    |   85 +
 dojox/charting/themes/RoyalPurples.js              |   23 +-
 dojox/charting/themes/SageToLime.js                |   28 +-
 dojox/charting/themes/Shrooms.js                   |   32 +-
 dojox/charting/themes/ThreeD.js                    |   49 +
 dojox/charting/themes/Tom.js                       |   87 +
 dojox/charting/themes/Tufte.js                     |   66 +-
 dojox/charting/themes/WatersEdge.js                |   23 +-
 dojox/charting/themes/Wetland.js                   |   23 +-
 dojox/charting/themes/gradientGenerator.js         |   83 +
 dojox/charting/widget/Chart2D.js                   |  278 +-
 dojox/charting/widget/Chart2D.js.uncompressed.js   |13949 -----------
 dojox/charting/widget/Legend.js                    |  277 +-
 dojox/charting/widget/Sparkline.js                 |   86 +-
 dojox/collections.js                               |   10 -
 dojox/collections/ArrayList.js                     |  227 +-
 dojox/collections/BinaryTree.js                    |  454 +-
 dojox/collections/Dictionary.js                    |  197 +-
 dojox/collections/Queue.js                         |  121 +-
 dojox/collections/Set.js                           |  161 +-
 dojox/collections/SortedList.js                    |  349 +-
 dojox/collections/Stack.js                         |  119 +-
 dojox/collections/_base.js                         |  159 +-
 dojox/collections/tests/ArrayList.js               |   79 +
 dojox/collections/tests/BinaryTree.js              |   79 +
 dojox/collections/tests/Dictionary.js              |   78 +
 dojox/collections/tests/Queue.js                   |   45 +
 dojox/collections/tests/Set.js                     |   31 +
 dojox/collections/tests/SortedList.js              |  164 +
 dojox/collections/tests/Stack.js                   |   45 +
 dojox/collections/tests/_base.js                   |   80 +
 dojox/collections/tests/collections.js             |   15 +
 dojox/collections/tests/runTests.html              |    9 +
 dojox/color.js                                     |   10 -
 dojox/color/Colorspace.js                          | 1016 +-
 dojox/color/Palette.js                             |  646 +-
 dojox/color/_base.js                               |  355 +-
 dojox/color/tests/Generator.js                     |  150 +
 dojox/color/tests/Palette.js                       |   86 +
 dojox/color/tests/_base.js                         |   78 +
 dojox/color/tests/color.js                         |   11 +
 dojox/color/tests/runTests.html                    |    9 +
 dojox/cometd.js                                    |   11 +-
 dojox/cometd/HttpChannels.js                       |   40 +-
 dojox/cometd/RestChannels.js                       |  811 +-
 dojox/cometd/_base.js                              | 1144 +-
 dojox/cometd/ack.js                                |   90 +-
 dojox/cometd/callbackPollTransport.js              |  166 +-
 dojox/cometd/longPollTransport.js                  |   10 -
 dojox/cometd/longPollTransportFormEncoded.js       |  269 +-
 dojox/cometd/longPollTransportJsonEncoded.js       |  272 +-
 dojox/cometd/tests/_base.js                        |   31 +
 dojox/cometd/tests/all.js                          |    8 +
 dojox/cometd/tests/runTests.html                   |   10 +
 dojox/cometd/timestamp.js                          |   18 +-
 dojox/cometd/timesync.js                           |  210 +-
 dojox/css3/fx.js                                   |  183 +
 dojox/data/AndOrReadStore.js                       | 1702 +-
 dojox/data/AndOrWriteStore.js                      | 1314 +-
 dojox/data/AppStore.js                             | 1367 +-
 dojox/data/AtomReadStore.js                        |  878 +-
 dojox/data/CdfStore.js                             |  909 +-
 dojox/data/ClientFilter.js                         |  473 +-
 dojox/data/CouchDBRestStore.js                     |  138 +-
 dojox/data/CssClassStore.js                        |  258 +-
 dojox/data/CssRuleStore.js                         |  789 +-
 dojox/data/CsvStore.js                             | 1159 +-
 dojox/data/FileStore.js                            |  662 +-
 dojox/data/FlickrRestStore.js                      |  772 +-
 dojox/data/FlickrStore.js                          |  422 +-
 dojox/data/GoogleFeedStore.js                      |  108 +-
 dojox/data/GoogleSearchStore.js                    |  885 +-
 dojox/data/HtmlStore.js                            |  868 +-
 dojox/data/HtmlTableStore.js                       |  725 +-
 dojox/data/ItemExplorer.js                         | 1063 +-
 dojox/data/JsonQueryRestStore.js                   |   26 +-
 dojox/data/JsonRestStore.js                        |  704 +-
 dojox/data/KeyValueStore.js                        |  606 +-
 dojox/data/OpenSearchStore.js                      |  572 +-
 dojox/data/OpmlStore.js                            |  842 +-
 dojox/data/PersevereStore.js                       |  178 +-
 dojox/data/PicasaStore.js                          |  434 +-
 dojox/data/QueryReadStore.js                       |  764 +-
 dojox/data/RailsStore.js                           |  280 +-
 dojox/data/S3Store.js                              |   57 +-
 dojox/data/ServiceStore.js                         |  549 +-
 dojox/data/SnapLogicStore.js                       |  505 +-
 dojox/data/StoreExplorer.js                        |  325 +-
 dojox/data/WikipediaStore.js                       |  168 +-
 dojox/data/XmlStore.js                             | 2435 +-
 dojox/data/css.js                                  |  176 +-
 dojox/data/demos/GoogleFeedTemplate.html           |   26 +
 dojox/data/demos/GoogleTemplate.html               |    7 +
 dojox/data/demos/GoogleTemplateBlog.html           |    7 +
 dojox/data/demos/GoogleTemplateImage.html          |    7 +
 dojox/data/demos/GoogleTemplateLocal.html          |    7 +
 dojox/data/demos/GoogleTemplateVideo.html          |    7 +
 .../data/demos/demo_CssStores_combo_tree_grid.html |   95 +
 dojox/data/demos/demo_DataDemoTable.html           |  143 +
 dojox/data/demos/demo_FileStore_dojotree.html      |  119 +
 .../demos/demo_FileStore_dojoxdata_combo_grid.html |  157 +
 dojox/data/demos/demo_FlickrRestStore.html         |  236 +
 dojox/data/demos/demo_FlickrStore.html             |  161 +
 dojox/data/demos/demo_GoogleFeedStore.html         |  113 +
 dojox/data/demos/demo_GoogleSearchStore.html       |  125 +
 dojox/data/demos/demo_GoogleSearchStore_Grid.html  |   73 +
 dojox/data/demos/demo_LazyLoad.html                |   66 +
 dojox/data/demos/demo_MultiStores.html             |  116 +
 dojox/data/demos/demo_OpenSearchStore.html         |  215 +
 dojox/data/demos/demo_PicasaStore.html             |  190 +
 dojox/data/demos/demo_QueryReadStore_ComboBox.html |   58 +
 .../demos/demo_QueryReadStore_FilteringSelect.html |   56 +
 dojox/data/demos/demo_QueryReadStore_grid.html     |  110 +
 dojox/data/demos/demo_WikipediaStore.html          |   82 +
 dojox/data/demos/geography.json                    |   45 +
 dojox/data/demos/geography.xml                     |   51 +
 dojox/data/demos/geography/Argentina/data.json     |    5 +
 dojox/data/demos/geography/Brazil/data.json        |    5 +
 dojox/data/demos/geography/Canada/Ottawa/data.json |    6 +
 .../data/demos/geography/Canada/Toronto/data.json  |    6 +
 dojox/data/demos/geography/Canada/data.json        |   10 +
 dojox/data/demos/geography/China/data.json         |    4 +
 .../geography/Commonwealth of Australia/data.json  |    5 +
 dojox/data/demos/geography/Egypt/data.json         |    5 +
 dojox/data/demos/geography/France/data.json        |    4 +
 dojox/data/demos/geography/Germany/data.json       |    4 +
 dojox/data/demos/geography/India/data.json         |    4 +
 dojox/data/demos/geography/Italy/data.json         |    4 +
 dojox/data/demos/geography/Kenya/Mombasa/data.json |    5 +
 dojox/data/demos/geography/Kenya/Nairobi/data.json |    5 +
 dojox/data/demos/geography/Kenya/data.json         |    9 +
 .../demos/geography/Mexico/Guadalajara/data.json   |    7 +
 .../demos/geography/Mexico/Mexico City/data.json   |    6 +
 dojox/data/demos/geography/Mexico/data.json        |   10 +
 dojox/data/demos/geography/Mongolia/data.json      |    4 +
 dojox/data/demos/geography/Russia/data.json        |    4 +
 dojox/data/demos/geography/Spain/data.json         |    4 +
 .../data/demos/geography/Sudan/Khartoum/data.json  |    5 +
 dojox/data/demos/geography/Sudan/data.json         |    6 +
 .../geography/United States of America/data.json   |    4 +
 dojox/data/demos/geography/root.json               |   39 +
 dojox/data/demos/geography2.xml                    |   44 +
 dojox/data/demos/openSearchProxy.php               |   33 +
 dojox/data/demos/picasaDemo.css                    |   44 +
 dojox/data/demos/stores/LazyLoadJSIStore.js        |  138 +
 dojox/data/demos/stores/filestore_dojotree.php     |  179 +
 dojox/data/demos/stores/filestore_dojoxdata.php    |  179 +
 dojox/data/demos/stores/filestore_funcs.php        |  366 +
 dojox/data/demos/widgets/FileView.js               |   40 +
 dojox/data/demos/widgets/FlickrViewList.js         |   30 +
 dojox/data/demos/widgets/PicasaView.js             |   33 +
 dojox/data/demos/widgets/PicasaViewList.js         |   33 +
 dojox/data/demos/widgets/templates/FileView.html   |   62 +
 .../demos/widgets/templates/FlickrViewList.html    |   20 +
 dojox/data/demos/widgets/templates/PicasaView.html |   35 +
 .../demos/widgets/templates/PicasaViewList.html    |    2 +
 dojox/data/dom.js                                  |  123 +-
 dojox/data/restListener.js                         |   80 +-
 dojox/data/s3/proxy.example-php                    |  146 +-
 dojox/data/tests/ClientFilter.js                   |  150 +
 dojox/data/tests/QueryReadStore.html               |  221 +
 dojox/data/tests/dom.js                            |  147 +
 dojox/data/tests/ml/divList.html                   |   14 +
 dojox/data/tests/ml/orderedList.html               |   16 +
 dojox/data/tests/ml/table.html                     |   46 +
 .../tests/ml/test_HtmlStore_declaratively.html     |  172 +
 dojox/data/tests/ml/test_HtmlStore_remote.html     |  115 +
 .../ml/test_HtmlTableStore_declaratively.html      |  120 +
 dojox/data/tests/ml/unorderedList.html             |   17 +
 dojox/data/tests/module.js                         |   39 +
 dojox/data/tests/performance/CsvStore.js           |  166 +
 dojox/data/tests/performance/module.js             |    4 +
 dojox/data/tests/performance/runTests.html         |    9 +
 dojox/data/tests/runTests.html                     |    9 +
 dojox/data/tests/stores/AndOrReadStore.js          | 3575 +++
 dojox/data/tests/stores/AndOrWriteStore.js         | 4965 ++++
 dojox/data/tests/stores/AppStore.js                |  898 +
 dojox/data/tests/stores/AtomReadStore.js           |  637 +
 dojox/data/tests/stores/CssClassStore.js           |  964 +
 dojox/data/tests/stores/CssRuleStore.js            |  838 +
 dojox/data/tests/stores/CsvStore.js                | 1411 ++
 dojox/data/tests/stores/FileStore.js               |  697 +
 dojox/data/tests/stores/FlickrRestStore.js         |  472 +
 dojox/data/tests/stores/FlickrStore.js             |  406 +
 dojox/data/tests/stores/GoogleFeedStore.js         |  570 +
 dojox/data/tests/stores/GoogleSearchStore.js       |  603 +
 dojox/data/tests/stores/HtmlStore.js               |  861 +
 dojox/data/tests/stores/HtmlTableStore.js          |  698 +
 dojox/data/tests/stores/JsonQueryRestStore.js      |  205 +
 dojox/data/tests/stores/JsonRestStore.js           |  345 +
 dojox/data/tests/stores/KeyValueStore.js           |  998 +
 dojox/data/tests/stores/OpenSearchStore.js         | 1306 +
 dojox/data/tests/stores/OpmlStore.js               | 1072 +
 dojox/data/tests/stores/PicasaStore.js             |  407 +
 dojox/data/tests/stores/QueryReadStore.js          |  438 +
 dojox/data/tests/stores/QueryReadStore.php         |  139 +
 dojox/data/tests/stores/ServiceStore.js            |  161 +
 dojox/data/tests/stores/SnapLogicStore.js          |  434 +
 dojox/data/tests/stores/WikipediaStore.js          |  449 +
 dojox/data/tests/stores/XmlStore.js                | 1397 ++
 dojox/data/tests/stores/atom1.xml                  |  848 +
 dojox/data/tests/stores/books.html                 |  118 +
 dojox/data/tests/stores/books.xml                  |  103 +
 dojox/data/tests/stores/books2.html                |   43 +
 dojox/data/tests/stores/books2.xml                 |   32 +
 dojox/data/tests/stores/books3.html                |   14 +
 dojox/data/tests/stores/books3.xml                 |   31 +
 dojox/data/tests/stores/books3Whitespace.html      |   27 +
 dojox/data/tests/stores/booksWhitespace.html       |  241 +
 dojox/data/tests/stores/books_isbnAttr.xml         |   23 +
 dojox/data/tests/stores/books_isbnAttr2.xml        |   23 +
 dojox/data/tests/stores/cdata_test.xml             |   12 +
 dojox/data/tests/stores/cdf1.xml                   |   16 +
 dojox/data/tests/stores/countries.json             |   12 +
 dojox/data/tests/stores/countries_withNull.json    |   10 +
 dojox/data/tests/stores/empty.csv                  |    1 +
 .../tests/stores/explore_ItemFileWriteStore.html   |   83 +
 dojox/data/tests/stores/filestore_dojoxdatageo.php |  178 +
 dojox/data/tests/stores/filestore_funcs.php        |  366 +
 dojox/data/tests/stores/geography.xml              |   51 +
 dojox/data/tests/stores/geography2.xml             |   44 +
 .../tests/stores/geography_withspeciallabel.xml    |   51 +
 dojox/data/tests/stores/movies.csv                 |    9 +
 dojox/data/tests/stores/movies2.csv                |    9 +
 dojox/data/tests/stores/movies3.csv                |   11 +
 dojox/data/tests/stores/node1.1                    |    4 +
 dojox/data/tests/stores/node1.2                    |    1 +
 dojox/data/tests/stores/opensearch_atom.xml        |    5 +
 dojox/data/tests/stores/opensearch_html.xml        |    5 +
 dojox/data/tests/stores/opensearch_rss.xml         |    5 +
 dojox/data/tests/stores/patterns.csv               |   11 +
 dojox/data/tests/stores/pipeSeparator.csv          |    7 +
 dojox/data/tests/stores/pipeSeparatorInData.csv    |    7 +
 dojox/data/tests/stores/properties.js              |   10 +
 dojox/data/tests/stores/rss1.xml                   |  436 +
 dojox/data/tests/stores/semicolonSeparator.csv     |    7 +
 dojox/data/tests/stores/snap_pipeline.php          |   72 +
 dojox/data/tests/stores/test1.css                  |    2 +
 dojox/data/tests/stores/test2.css                  |    1 +
 .../tests/stores/test_Tree_on_JsonRestStore.html   |  114 +
 dojox/data/tests/stores/treeTestRoot               |   10 +
 dojox/data/tests/treeTest.json                     |   10 +
 dojox/data/util/JsonQuery.js                       |  178 +-
 dojox/date/README                                  |    8 +-
 dojox/date/buddhist.js                             |  410 +-
 dojox/date/buddhist/Date.js                        |  527 +-
 dojox/date/buddhist/locale.js                      |  733 +-
 dojox/date/hebrew.js                               |  428 +-
 dojox/date/hebrew/Date.js                          | 1002 +-
 dojox/date/hebrew/locale.js                        |  894 +-
 dojox/date/hebrew/numerals.js                      |  234 +-
 dojox/date/islamic.js                              |  422 +-
 dojox/date/islamic/Date.js                         |  718 +-
 dojox/date/islamic/locale.js                       |  763 +-
 dojox/date/php.js                                  |  483 +-
 dojox/date/posix.js                                |  489 +-
 dojox/date/relative.js                             |  132 +-
 dojox/date/tests/HebrewDateTest1.html              |  175 +
 dojox/date/tests/buddhist/Date.js                  |  174 +
 dojox/date/tests/hebrew/Date.js                    |  406 +
 dojox/date/tests/islamic/Date.js                   |  231 +
 dojox/date/tests/module.js                         |   12 +
 dojox/date/tests/posix.js                          |  261 +
 dojox/date/tests/relative.js                       |   58 +
 dojox/date/tests/runTests.html                     |    9 +
 dojox/date/tests/test_DateTextBoxBuddhist.html     |  148 +
 dojox/date/tests/test_DateTextBoxIslamic.html      |  146 +
 .../date/tests/test_DateTextBoxNewHebrewGreg.html  |  148 +
 dojox/date/tests/timezone.js                       |  421 +
 dojox/date/tests/timezoneFormatting.js             |   83 +
 dojox/date/tests/tztests/tz_Africa-Abidjan.json    |   14 +
 dojox/date/tests/tztests/tz_Africa-Accra.json      |   42 +
 .../date/tests/tztests/tz_Africa-Addis_Ababa.json  |   14 +
 dojox/date/tests/tztests/tz_Africa-Algiers.json    |   78 +
 dojox/date/tests/tztests/tz_Africa-Asmara.json     |   14 +
 dojox/date/tests/tztests/tz_Africa-Bamako.json     |   18 +
 dojox/date/tests/tztests/tz_Africa-Bangui.json     |   14 +
 dojox/date/tests/tztests/tz_Africa-Banjul.json     |   18 +
 dojox/date/tests/tztests/tz_Africa-Bissau.json     |   16 +
 dojox/date/tests/tztests/tz_Africa-Blantyre.json   |   14 +
 .../date/tests/tztests/tz_Africa-Brazzaville.json  |   14 +
 dojox/date/tests/tztests/tz_Africa-Bujumbura.json  |   12 +
 dojox/date/tests/tztests/tz_Africa-Cairo.json      |  360 +
 dojox/date/tests/tztests/tz_Africa-Casablanca.json |   58 +
 dojox/date/tests/tztests/tz_Africa-Ceuta.json      |  262 +
 dojox/date/tests/tztests/tz_Africa-Conakry.json    |   18 +
 dojox/date/tests/tztests/tz_Africa-Dakar.json      |   16 +
 .../tests/tztests/tz_Africa-Dar_es_Salaam.json     |   18 +
 dojox/date/tests/tztests/tz_Africa-Djibouti.json   |   14 +
 dojox/date/tests/tztests/tz_Africa-Douala.json     |   14 +
 dojox/date/tests/tztests/tz_Africa-El_Aaiun.json   |   16 +
 dojox/date/tests/tztests/tz_Africa-Freetown.json   |   72 +
 dojox/date/tests/tztests/tz_Africa-Gaborone.json   |   16 +
 dojox/date/tests/tztests/tz_Africa-Harare.json     |   14 +
 .../date/tests/tztests/tz_Africa-Johannesburg.json |   22 +
 dojox/date/tests/tztests/tz_Africa-Kampala.json    |   20 +
 dojox/date/tests/tztests/tz_Africa-Khartoum.json   |   80 +
 dojox/date/tests/tztests/tz_Africa-Kigali.json     |   14 +
 dojox/date/tests/tztests/tz_Africa-Kinshasa.json   |   12 +
 dojox/date/tests/tztests/tz_Africa-Lagos.json      |   14 +
 dojox/date/tests/tztests/tz_Africa-Libreville.json |   14 +
 dojox/date/tests/tztests/tz_Africa-Lome.json       |   12 +
 dojox/date/tests/tztests/tz_Africa-Luanda.json     |   14 +
 dojox/date/tests/tztests/tz_Africa-Lubumbashi.json |   12 +
 dojox/date/tests/tztests/tz_Africa-Lusaka.json     |   14 +
 dojox/date/tests/tztests/tz_Africa-Malabo.json     |   16 +
 dojox/date/tests/tztests/tz_Africa-Maputo.json     |   14 +
 dojox/date/tests/tztests/tz_Africa-Maseru.json     |   18 +
 dojox/date/tests/tztests/tz_Africa-Mbabane.json    |   14 +
 dojox/date/tests/tztests/tz_Africa-Mogadishu.json  |   16 +
 dojox/date/tests/tztests/tz_Africa-Monrovia.json   |   16 +
 dojox/date/tests/tztests/tz_Africa-Nairobi.json    |   20 +
 dojox/date/tests/tztests/tz_Africa-Ndjamena.json   |   18 +
 dojox/date/tests/tztests/tz_Africa-Niamey.json     |   18 +
 dojox/date/tests/tztests/tz_Africa-Nouakchott.json |   18 +
 .../date/tests/tztests/tz_Africa-Ouagadougou.json  |   14 +
 dojox/date/tests/tztests/tz_Africa-Porto-Novo.json |   16 +
 dojox/date/tests/tztests/tz_Africa-Sao_Tome.json   |   14 +
 dojox/date/tests/tztests/tz_Africa-Tripoli.json    |   70 +
 dojox/date/tests/tztests/tz_Africa-Tunis.json      |  190 +
 dojox/date/tests/tztests/tz_Africa-Windhoek.json   |  196 +
 dojox/date/tests/tztests/tz_America-Adak.json      |  298 +
 dojox/date/tests/tztests/tz_America-Anchorage.json |  298 +
 dojox/date/tests/tztests/tz_America-Anguilla.json  |   14 +
 dojox/date/tests/tztests/tz_America-Antigua.json   |   16 +
 dojox/date/tests/tztests/tz_America-Araguaina.json |  110 +
 .../tztests/tz_America-Argentina-Buenos_Aires.json |  246 +
 .../tztests/tz_America-Argentina-Catamarca.json    |  132 +
 .../tztests/tz_America-Argentina-Cordoba.json      |  246 +
 .../tests/tztests/tz_America-Argentina-Jujuy.json  |  128 +
 .../tztests/tz_America-Argentina-La_Rioja.json     |  134 +
 .../tztests/tz_America-Argentina-Mendoza.json      |  132 +
 .../tztests/tz_America-Argentina-Rio_Gallegos.json |  132 +
 .../tests/tztests/tz_America-Argentina-Salta.json  |  128 +
 .../tztests/tz_America-Argentina-San_Juan.json     |  134 +
 .../tztests/tz_America-Argentina-San_Luis.json     |  242 +
 .../tztests/tz_America-Argentina-Tucuman.json      |  250 +
 .../tztests/tz_America-Argentina-Ushuaia.json      |  132 +
 dojox/date/tests/tztests/tz_America-Aruba.json     |   16 +
 dojox/date/tests/tztests/tz_America-Asuncion.json  |  268 +
 dojox/date/tests/tztests/tz_America-Atikokan.json  |   24 +
 dojox/date/tests/tztests/tz_America-Bahia.json     |  130 +
 dojox/date/tests/tztests/tz_America-Barbados.json  |   32 +
 dojox/date/tests/tztests/tz_America-Belem.json     |   70 +
 dojox/date/tests/tztests/tz_America-Belize.json    |  122 +
 .../tests/tztests/tz_America-Blanc-Sablon.json     |   22 +
 dojox/date/tests/tztests/tz_America-Boa_Vista.json |   78 +
 dojox/date/tests/tztests/tz_America-Bogota.json    |   18 +
 dojox/date/tests/tztests/tz_America-Boise.json     |  312 +
 .../tests/tztests/tz_America-Cambridge_Bay.json    |  258 +
 .../tests/tztests/tz_America-Campo_Grande.json     |  268 +
 dojox/date/tests/tztests/tz_America-Cancun.json    |  186 +
 dojox/date/tests/tztests/tz_America-Caracas.json   |   18 +
 dojox/date/tests/tztests/tz_America-Cayenne.json   |   16 +
 dojox/date/tests/tztests/tz_America-Cayman.json    |   14 +
 dojox/date/tests/tztests/tz_America-Chicago.json   |  482 +
 dojox/date/tests/tztests/tz_America-Chihuahua.json |  192 +
 .../date/tests/tztests/tz_America-Costa_Rica.json  |   30 +
 dojox/date/tests/tztests/tz_America-Cuiaba.json    |  264 +
 dojox/date/tests/tztests/tz_America-Curacao.json   |   16 +
 .../tests/tztests/tz_America-Danmarkshavn.json     |   80 +
 dojox/date/tests/tztests/tz_America-Dawson.json    |  264 +
 .../tests/tztests/tz_America-Dawson_Creek.json     |  126 +
 dojox/date/tests/tztests/tz_America-Denver.json    |  326 +
 dojox/date/tests/tztests/tz_America-Detroit.json   |  290 +
 dojox/date/tests/tztests/tz_America-Dominica.json  |   14 +
 dojox/date/tests/tztests/tz_America-Edmonton.json  |  320 +
 dojox/date/tests/tztests/tz_America-Eirunepe.json  |   76 +
 .../date/tests/tztests/tz_America-El_Salvador.json |   22 +
 dojox/date/tests/tztests/tz_America-Fortaleza.json |   90 +
 dojox/date/tests/tztests/tz_America-Glace_Bay.json |  292 +
 dojox/date/tests/tztests/tz_America-Godthab.json   |  246 +
 dojox/date/tests/tztests/tz_America-Goose_Bay.json |  418 +
 .../date/tests/tztests/tz_America-Grand_Turk.json  |  250 +
 dojox/date/tests/tztests/tz_America-Grenada.json   |   14 +
 .../date/tests/tztests/tz_America-Guadeloupe.json  |   14 +
 dojox/date/tests/tztests/tz_America-Guatemala.json |   30 +
 dojox/date/tests/tztests/tz_America-Guayaquil.json |   14 +
 dojox/date/tests/tztests/tz_America-Guyana.json    |   20 +
 dojox/date/tests/tztests/tz_America-Halifax.json   |  468 +
 dojox/date/tests/tztests/tz_America-Havana.json    |  322 +
 .../date/tests/tztests/tz_America-Hermosillo.json  |   42 +
 .../tztests/tz_America-Indiana-Indianapolis.json   |  208 +
 .../tests/tztests/tz_America-Indiana-Knox.json     |  318 +
 .../tests/tztests/tz_America-Indiana-Marengo.json  |  216 +
 .../tztests/tz_America-Indiana-Petersburg.json     |  242 +
 .../tztests/tz_America-Indiana-Tell_City.json      |  212 +
 .../tests/tztests/tz_America-Indiana-Vevay.json    |  172 +
 .../tztests/tz_America-Indiana-Vincennes.json      |  212 +
 .../tests/tztests/tz_America-Indiana-Winamac.json  |  224 +
 dojox/date/tests/tztests/tz_America-Inuvik.json    |  252 +
 dojox/date/tests/tztests/tz_America-Iqaluit.json   |  254 +
 dojox/date/tests/tztests/tz_America-Jamaica.json   |   54 +
 dojox/date/tests/tztests/tz_America-Juneau.json    |  296 +
 .../tztests/tz_America-Kentucky-Louisville.json    |  366 +
 .../tztests/tz_America-Kentucky-Monticello.json    |  306 +
 dojox/date/tests/tztests/tz_America-La_Paz.json    |   16 +
 dojox/date/tests/tztests/tz_America-Lima.json      |   42 +
 .../date/tests/tztests/tz_America-Los_Angeles.json |  382 +
 dojox/date/tests/tztests/tz_America-Maceio.json    |   94 +
 dojox/date/tests/tztests/tz_America-Managua.json   |   42 +
 dojox/date/tests/tztests/tz_America-Manaus.json    |   74 +
 .../date/tests/tztests/tz_America-Martinique.json  |   18 +
 dojox/date/tests/tztests/tz_America-Mazatlan.json  |  198 +
 dojox/date/tests/tztests/tz_America-Menominee.json |  296 +
 dojox/date/tests/tztests/tz_America-Merida.json    |  186 +
 .../date/tests/tztests/tz_America-Mexico_City.json |  208 +
 dojox/date/tests/tztests/tz_America-Miquelon.json  |  220 +
 dojox/date/tests/tztests/tz_America-Moncton.json   |  424 +
 dojox/date/tests/tztests/tz_America-Monterrey.json |  186 +
 .../date/tests/tztests/tz_America-Montevideo.json  |  274 +
 dojox/date/tests/tztests/tz_America-Montreal.json  |  476 +
 .../date/tests/tztests/tz_America-Montserrat.json  |   14 +
 dojox/date/tests/tztests/tz_America-Nassau.json    |  310 +
 dojox/date/tests/tztests/tz_America-New_York.json  |  482 +
 dojox/date/tests/tztests/tz_America-Nipigon.json   |  280 +
 dojox/date/tests/tztests/tz_America-Nome.json      |  298 +
 dojox/date/tests/tztests/tz_America-Noronha.json   |   90 +
 .../tztests/tz_America-North_Dakota-Center.json    |  310 +
 .../tztests/tz_America-North_Dakota-New_Salem.json |  310 +
 dojox/date/tests/tztests/tz_America-Panama.json    |   14 +
 .../date/tests/tztests/tz_America-Pangnirtung.json |  256 +
 .../date/tests/tztests/tz_America-Paramaribo.json  |   22 +
 dojox/date/tests/tztests/tz_America-Phoenix.json   |   32 +
 .../tests/tztests/tz_America-Port-au-Prince.json   |   82 +
 .../tests/tztests/tz_America-Port_of_Spain.json    |   14 +
 .../date/tests/tztests/tz_America-Porto_Velho.json |   70 +
 .../date/tests/tztests/tz_America-Puerto_Rico.json |   18 +
 .../date/tests/tztests/tz_America-Rainy_River.json |  280 +
 .../tests/tztests/tz_America-Rankin_Inlet.json     |  250 +
 dojox/date/tests/tztests/tz_America-Recife.json    |   90 +
 dojox/date/tests/tztests/tz_America-Regina.json    |  118 +
 dojox/date/tests/tztests/tz_America-Resolute.json  |  250 +
 .../date/tests/tztests/tz_America-Rio_Branco.json  |   72 +
 dojox/date/tests/tztests/tz_America-Santarem.json  |   72 +
 dojox/date/tests/tztests/tz_America-Santiago.json  |  328 +
 .../tests/tztests/tz_America-Santo_Domingo.json    |   44 +
 dojox/date/tests/tztests/tz_America-Sao_Paulo.json |  268 +
 .../tests/tztests/tz_America-Scoresbysund.json     |  246 +
 dojox/date/tests/tztests/tz_America-St_Johns.json  |  488 +
 dojox/date/tests/tztests/tz_America-St_Kitts.json  |   14 +
 dojox/date/tests/tztests/tz_America-St_Lucia.json  |   14 +
 dojox/date/tests/tztests/tz_America-St_Thomas.json |   14 +
 .../date/tests/tztests/tz_America-St_Vincent.json  |   14 +
 .../tests/tztests/tz_America-Swift_Current.json    |   58 +
 .../date/tests/tztests/tz_America-Tegucigalpa.json |   26 +
 dojox/date/tests/tztests/tz_America-Thule.json     |  202 +
 .../date/tests/tztests/tz_America-Thunder_Bay.json |  288 +
 dojox/date/tests/tztests/tz_America-Tijuana.json   |  310 +
 dojox/date/tests/tztests/tz_America-Toronto.json   |  476 +
 dojox/date/tests/tztests/tz_America-Tortola.json   |   14 +
 dojox/date/tests/tztests/tz_America-Vancouver.json |  390 +
 .../date/tests/tztests/tz_America-Whitehorse.json  |  264 +
 dojox/date/tests/tztests/tz_America-Winnipeg.json  |  382 +
 dojox/date/tests/tztests/tz_America-Yakutat.json   |  296 +
 .../date/tests/tztests/tz_America-Yellowknife.json |  256 +
 dojox/date/tests/tztests/tz_Antarctica-Casey.json  |   14 +
 dojox/date/tests/tztests/tz_Antarctica-Davis.json  |   18 +
 .../tztests/tz_Antarctica-DumontDUrville.json      |   18 +
 dojox/date/tests/tztests/tz_Antarctica-Mawson.json |   14 +
 .../date/tests/tztests/tz_Antarctica-McMurdo.json  |  268 +
 dojox/date/tests/tztests/tz_Antarctica-Palmer.json |  262 +
 .../date/tests/tztests/tz_Antarctica-Rothera.json  |   14 +
 dojox/date/tests/tztests/tz_Antarctica-Syowa.json  |   14 +
 dojox/date/tests/tztests/tz_Antarctica-Vostok.json |   14 +
 dojox/date/tests/tztests/tz_Asia-Aden.json         |   14 +
 dojox/date/tests/tztests/tz_Asia-Almaty.json       |  108 +
 dojox/date/tests/tztests/tz_Asia-Amman.json        |  250 +
 dojox/date/tests/tztests/tz_Asia-Anadyr.json       |  246 +
 dojox/date/tests/tztests/tz_Asia-Aqtau.json        |  112 +
 dojox/date/tests/tztests/tz_Asia-Aqtobe.json       |  110 +
 dojox/date/tests/tztests/tz_Asia-Ashgabat.json     |   64 +
 dojox/date/tests/tztests/tz_Asia-Baghdad.json      |  118 +
 dojox/date/tests/tztests/tz_Asia-Bahrain.json      |   16 +
 dojox/date/tests/tztests/tz_Asia-Baku.json         |  234 +
 dojox/date/tests/tztests/tz_Asia-Bangkok.json      |   14 +
 dojox/date/tests/tztests/tz_Asia-Beirut.json       |  292 +
 dojox/date/tests/tztests/tz_Asia-Bishkek.json      |  116 +
 dojox/date/tests/tztests/tz_Asia-Brunei.json       |   16 +
 dojox/date/tests/tztests/tz_Asia-Choibalsan.json   |  106 +
 dojox/date/tests/tztests/tz_Asia-Chongqing.json    |   40 +
 dojox/date/tests/tztests/tz_Asia-Colombo.json      |   26 +
 dojox/date/tests/tztests/tz_Asia-Damascus.json     |  314 +
 dojox/date/tests/tztests/tz_Asia-Dhaka.json        |   24 +
 dojox/date/tests/tztests/tz_Asia-Dili.json         |   22 +
 dojox/date/tests/tztests/tz_Asia-Dubai.json        |   14 +
 dojox/date/tests/tztests/tz_Asia-Dushanbe.json     |   60 +
 dojox/date/tests/tztests/tz_Asia-Gaza.json         |  298 +
 dojox/date/tests/tztests/tz_Asia-Harbin.json       |   46 +
 dojox/date/tests/tztests/tz_Asia-Ho_Chi_Minh.json  |   20 +
 dojox/date/tests/tztests/tz_Asia-Hong_Kong.json    |  150 +
 dojox/date/tests/tztests/tz_Asia-Hovd.json         |  104 +
 dojox/date/tests/tztests/tz_Asia-Irkutsk.json      |  246 +
 dojox/date/tests/tztests/tz_Asia-Jakarta.json      |   26 +
 dojox/date/tests/tztests/tz_Asia-Jayapura.json     |   18 +
 dojox/date/tests/tztests/tz_Asia-Jerusalem.json    |  296 +
 dojox/date/tests/tztests/tz_Asia-Kabul.json        |   14 +
 dojox/date/tests/tztests/tz_Asia-Kamchatka.json    |  246 +
 dojox/date/tests/tztests/tz_Asia-Karachi.json      |   34 +
 dojox/date/tests/tztests/tz_Asia-Kashgar.json      |   42 +
 dojox/date/tests/tztests/tz_Asia-Kathmandu.json    |   16 +
 dojox/date/tests/tztests/tz_Asia-Kolkata.json      |   20 +
 dojox/date/tests/tztests/tz_Asia-Krasnoyarsk.json  |  246 +
 dojox/date/tests/tztests/tz_Asia-Kuala_Lumpur.json |   26 +
 dojox/date/tests/tztests/tz_Asia-Kuching.json      |   50 +
 dojox/date/tests/tztests/tz_Asia-Kuwait.json       |   14 +
 dojox/date/tests/tztests/tz_Asia-Macau.json        |   96 +
 dojox/date/tests/tztests/tz_Asia-Magadan.json      |  246 +
 dojox/date/tests/tztests/tz_Asia-Makassar.json     |   20 +
 dojox/date/tests/tztests/tz_Asia-Manila.json       |   28 +
 dojox/date/tests/tztests/tz_Asia-Muscat.json       |   14 +
 dojox/date/tests/tztests/tz_Asia-Nicosia.json      |  266 +
 dojox/date/tests/tztests/tz_Asia-Novosibirsk.json  |  248 +
 dojox/date/tests/tztests/tz_Asia-Omsk.json         |  246 +
 dojox/date/tests/tztests/tz_Asia-Oral.json         |  112 +
 dojox/date/tests/tztests/tz_Asia-Phnom_Penh.json   |   20 +
 dojox/date/tests/tztests/tz_Asia-Pontianak.json    |   28 +
 dojox/date/tests/tztests/tz_Asia-Pyongyang.json    |   22 +
 dojox/date/tests/tztests/tz_Asia-Qatar.json        |   16 +
 dojox/date/tests/tztests/tz_Asia-Qyzylorda.json    |  112 +
 dojox/date/tests/tztests/tz_Asia-Rangoon.json      |   18 +
 dojox/date/tests/tztests/tz_Asia-Riyadh.json       |   14 +
 dojox/date/tests/tztests/tz_Asia-Sakhalin.json     |  248 +
 dojox/date/tests/tztests/tz_Asia-Samarkand.json    |   62 +
 dojox/date/tests/tztests/tz_Asia-Seoul.json        |   36 +
 dojox/date/tests/tztests/tz_Asia-Shanghai.json     |   46 +
 dojox/date/tests/tztests/tz_Asia-Singapore.json    |   28 +
 dojox/date/tests/tztests/tz_Asia-Taipei.json       |   92 +
 dojox/date/tests/tztests/tz_Asia-Tashkent.json     |   62 +
 dojox/date/tests/tztests/tz_Asia-Tbilisi.json      |  114 +
 dojox/date/tests/tztests/tz_Asia-Tehran.json       |  212 +
 dojox/date/tests/tztests/tz_Asia-Thimphu.json      |   16 +
 dojox/date/tests/tztests/tz_Asia-Tokyo.json        |   30 +
 dojox/date/tests/tztests/tz_Asia-Ulaanbaatar.json  |  104 +
 dojox/date/tests/tztests/tz_Asia-Urumqi.json       |   40 +
 dojox/date/tests/tztests/tz_Asia-Vientiane.json    |   20 +
 dojox/date/tests/tztests/tz_Asia-Vladivostok.json  |  246 +
 dojox/date/tests/tztests/tz_Asia-Yakutsk.json      |  246 +
 .../date/tests/tztests/tz_Asia-Yekaterinburg.json  |  246 +
 dojox/date/tests/tztests/tz_Asia-Yerevan.json      |  242 +
 dojox/date/tests/tztests/tz_Atlantic-Azores.json   |  452 +
 dojox/date/tests/tztests/tz_Atlantic-Bermuda.json  |  270 +
 dojox/date/tests/tztests/tz_Atlantic-Canary.json   |  248 +
 .../date/tests/tztests/tz_Atlantic-Cape_Verde.json |   20 +
 dojox/date/tests/tztests/tz_Atlantic-Faroe.json    |  242 +
 dojox/date/tests/tztests/tz_Atlantic-Madeira.json  |  452 +
 .../date/tests/tztests/tz_Atlantic-Reykjavik.json  |  140 +
 .../tests/tztests/tz_Atlantic-South_Georgia.json   |   12 +
 .../date/tests/tztests/tz_Atlantic-St_Helena.json  |   14 +
 dojox/date/tests/tztests/tz_Atlantic-Stanley.json  |  258 +
 .../date/tests/tztests/tz_Australia-Adelaide.json  |  294 +
 .../date/tests/tztests/tz_Australia-Brisbane.json  |   44 +
 .../tests/tztests/tz_Australia-Broken_Hill.json    |  294 +
 dojox/date/tests/tztests/tz_Australia-Currie.json  |  294 +
 dojox/date/tests/tztests/tz_Australia-Darwin.json  |   28 +
 dojox/date/tests/tztests/tz_Australia-Eucla.json   |   48 +
 dojox/date/tests/tztests/tz_Australia-Hobart.json  |  310 +
 .../date/tests/tztests/tz_Australia-Lindeman.json  |   52 +
 .../date/tests/tztests/tz_Australia-Lord_Howe.json |  240 +
 .../date/tests/tztests/tz_Australia-Melbourne.json |  294 +
 dojox/date/tests/tztests/tz_Australia-Perth.json   |   48 +
 dojox/date/tests/tztests/tz_Australia-Sydney.json  |  294 +
 dojox/date/tests/tztests/tz_CET.json               |  284 +
 dojox/date/tests/tztests/tz_CST6CDT.json           |  310 +
 dojox/date/tests/tztests/tz_EET.json               |  256 +
 dojox/date/tests/tztests/tz_EST.json               |   12 +
 dojox/date/tests/tztests/tz_EST5EDT.json           |  310 +
 dojox/date/tests/tztests/tz_Europe-Amsterdam.json  |  370 +
 dojox/date/tests/tztests/tz_Europe-Andorra.json    |  226 +
 dojox/date/tests/tztests/tz_Europe-Athens.json     |  286 +
 dojox/date/tests/tztests/tz_Europe-Belgrade.json   |  248 +
 dojox/date/tests/tztests/tz_Europe-Berlin.json     |  296 +
 dojox/date/tests/tztests/tz_Europe-Brussels.json   |  378 +
 dojox/date/tests/tztests/tz_Europe-Bucharest.json  |  282 +
 dojox/date/tests/tztests/tz_Europe-Budapest.json   |  316 +
 dojox/date/tests/tztests/tz_Europe-Chisinau.json   |  288 +
 dojox/date/tests/tztests/tz_Europe-Copenhagen.json |  276 +
 dojox/date/tests/tztests/tz_Europe-Dublin.json     |  466 +
 dojox/date/tests/tztests/tz_Europe-Gibraltar.json  |  406 +
 dojox/date/tests/tztests/tz_Europe-Helsinki.json   |  246 +
 dojox/date/tests/tztests/tz_Europe-Istanbul.json   |  352 +
 .../date/tests/tztests/tz_Europe-Kaliningrad.json  |  272 +
 dojox/date/tests/tztests/tz_Europe-Kiev.json       |  248 +
 dojox/date/tests/tztests/tz_Europe-Lisbon.json     |  454 +
 dojox/date/tests/tztests/tz_Europe-London.json     |  494 +
 dojox/date/tests/tztests/tz_Europe-Luxembourg.json |  378 +
 dojox/date/tests/tztests/tz_Europe-Madrid.json     |  338 +
 dojox/date/tests/tztests/tz_Europe-Malta.json      |  348 +
 dojox/date/tests/tztests/tz_Europe-Minsk.json      |  252 +
 dojox/date/tests/tztests/tz_Europe-Monaco.json     |  380 +
 dojox/date/tests/tztests/tz_Europe-Moscow.json     |  270 +
 dojox/date/tests/tztests/tz_Europe-Oslo.json       |  292 +
 dojox/date/tests/tztests/tz_Europe-Paris.json      |  378 +
 dojox/date/tests/tztests/tz_Europe-Prague.json     |  292 +
 dojox/date/tests/tztests/tz_Europe-Riga.json       |  262 +
 dojox/date/tests/tztests/tz_Europe-Rome.json       |  348 +
 dojox/date/tests/tztests/tz_Europe-Samara.json     |  248 +
 dojox/date/tests/tztests/tz_Europe-Simferopol.json |  252 +
 dojox/date/tests/tztests/tz_Europe-Sofia.json      |  260 +
 dojox/date/tests/tztests/tz_Europe-Stockholm.json  |  248 +
 dojox/date/tests/tztests/tz_Europe-Tallinn.json    |  256 +
 dojox/date/tests/tztests/tz_Europe-Tirane.json     |  278 +
 dojox/date/tests/tztests/tz_Europe-Uzhgorod.json   |  250 +
 dojox/date/tests/tztests/tz_Europe-Vaduz.json      |  240 +
 dojox/date/tests/tztests/tz_Europe-Vienna.json     |  288 +
 dojox/date/tests/tztests/tz_Europe-Vilnius.json    |  250 +
 dojox/date/tests/tztests/tz_Europe-Volgograd.json  |  246 +
 dojox/date/tests/tztests/tz_Europe-Warsaw.json     |  340 +
 dojox/date/tests/tztests/tz_Europe-Zaporozhye.json |  254 +
 dojox/date/tests/tztests/tz_Europe-Zurich.json     |  248 +
 dojox/date/tests/tztests/tz_HST.json               |   12 +
 .../date/tests/tztests/tz_Indian-Antananarivo.json |   18 +
 dojox/date/tests/tztests/tz_Indian-Chagos.json     |   16 +
 dojox/date/tests/tztests/tz_Indian-Christmas.json  |   12 +
 dojox/date/tests/tztests/tz_Indian-Cocos.json      |   12 +
 dojox/date/tests/tztests/tz_Indian-Comoro.json     |   14 +
 dojox/date/tests/tztests/tz_Indian-Kerguelen.json  |   14 +
 dojox/date/tests/tztests/tz_Indian-Mahe.json       |   14 +
 dojox/date/tests/tztests/tz_Indian-Maldives.json   |   14 +
 dojox/date/tests/tztests/tz_Indian-Mauritius.json  |  136 +
 dojox/date/tests/tztests/tz_Indian-Mayotte.json    |   14 +
 dojox/date/tests/tztests/tz_Indian-Reunion.json    |   14 +
 dojox/date/tests/tztests/tz_MET.json               |  284 +
 dojox/date/tests/tztests/tz_MST.json               |   12 +
 dojox/date/tests/tztests/tz_MST7MDT.json           |  310 +
 dojox/date/tests/tztests/tz_PST8PDT.json           |  310 +
 dojox/date/tests/tztests/tz_Pacific-Apia.json      |   16 +
 dojox/date/tests/tztests/tz_Pacific-Auckland.json  |  322 +
 dojox/date/tests/tztests/tz_Pacific-Chatham.json   |  268 +
 dojox/date/tests/tztests/tz_Pacific-Easter.json    |  298 +
 dojox/date/tests/tztests/tz_Pacific-Efate.json     |   54 +
 dojox/date/tests/tztests/tz_Pacific-Enderbury.json |   16 +
 dojox/date/tests/tztests/tz_Pacific-Fakaofo.json   |   12 +
 dojox/date/tests/tztests/tz_Pacific-Fiji.json      |   22 +
 dojox/date/tests/tztests/tz_Pacific-Funafuti.json  |   12 +
 dojox/date/tests/tztests/tz_Pacific-Galapagos.json |   16 +
 dojox/date/tests/tztests/tz_Pacific-Gambier.json   |   14 +
 .../date/tests/tztests/tz_Pacific-Guadalcanal.json |   14 +
 dojox/date/tests/tztests/tz_Pacific-Guam.json      |   14 +
 dojox/date/tests/tztests/tz_Pacific-Honolulu.json  |   24 +
 dojox/date/tests/tztests/tz_Pacific-Johnston.json  |   12 +
 .../date/tests/tztests/tz_Pacific-Kiritimati.json  |   16 +
 dojox/date/tests/tztests/tz_Pacific-Kosrae.json    |   16 +
 dojox/date/tests/tztests/tz_Pacific-Kwajalein.json |   16 +
 dojox/date/tests/tztests/tz_Pacific-Majuro.json    |   14 +
 dojox/date/tests/tztests/tz_Pacific-Marquesas.json |   14 +
 dojox/date/tests/tztests/tz_Pacific-Midway.json    |   20 +
 dojox/date/tests/tztests/tz_Pacific-Nauru.json     |   20 +
 dojox/date/tests/tztests/tz_Pacific-Niue.json      |   16 +
 dojox/date/tests/tztests/tz_Pacific-Norfolk.json   |   14 +
 dojox/date/tests/tztests/tz_Pacific-Noumea.json    |   26 +
 dojox/date/tests/tztests/tz_Pacific-Pago_Pago.json |   20 +
 dojox/date/tests/tztests/tz_Pacific-Palau.json     |   12 +
 dojox/date/tests/tztests/tz_Pacific-Pitcairn.json  |   14 +
 dojox/date/tests/tztests/tz_Pacific-Ponape.json    |   12 +
 .../tests/tztests/tz_Pacific-Port_Moresby.json     |   12 +
 dojox/date/tests/tztests/tz_Pacific-Rarotonga.json |   64 +
 dojox/date/tests/tztests/tz_Pacific-Saipan.json    |   16 +
 dojox/date/tests/tztests/tz_Pacific-Tahiti.json    |   14 +
 dojox/date/tests/tztests/tz_Pacific-Tarawa.json    |   12 +
 dojox/date/tests/tztests/tz_Pacific-Tongatapu.json |   26 +
 dojox/date/tests/tztests/tz_Pacific-Truk.json      |   12 +
 dojox/date/tests/tztests/tz_Pacific-Wake.json      |   12 +
 dojox/date/tests/tztests/tz_Pacific-Wallis.json    |   12 +
 dojox/date/tests/tztests/tz_WET.json               |  256 +
 dojox/date/tests/tztests_from_zdump.pl             |  227 +
 dojox/date/timezone.js                             | 1141 +-
 dojox/dnd/BoundingBoxController.js                 |  130 +
 dojox/dnd/README                                   |   22 +
 dojox/dnd/Selector.js                              |  159 +
 dojox/dnd/tests/robot/test_selector.html           |   71 +
 dojox/dnd/tests/test_selector.html                 |   57 +
 dojox/drawing.js                                   |   12 +-
 dojox/drawing/Drawing.js                           |  771 +-
 dojox/drawing/_base.js                             |   23 +-
 dojox/drawing/annotations/Angle.js                 |  152 +-
 dojox/drawing/annotations/Arrow.js                 |  103 +-
 dojox/drawing/annotations/BoxShadow.js             |  425 +-
 dojox/drawing/annotations/Label.js                 |  172 +-
 dojox/drawing/defaults.js                          |  324 +-
 dojox/drawing/library/icons.js                     |  171 +-
 dojox/drawing/manager/Anchors.js                   |  696 +-
 dojox/drawing/manager/Canvas.js                    |  244 +-
 dojox/drawing/manager/Mouse.js                     |  698 +-
 dojox/drawing/manager/Stencil.js                   |  903 +-
 dojox/drawing/manager/StencilUI.js                 |  109 +-
 dojox/drawing/manager/Undo.js                      |  106 +-
 dojox/drawing/manager/_registry.js                 |   61 +-
 dojox/drawing/manager/keys.js                      |  412 +-
 dojox/drawing/plugins/_Plugin.js                   |   65 +-
 dojox/drawing/plugins/drawing/Grid.js              |  146 +-
 dojox/drawing/plugins/drawing/Silverlight.js       |  329 +-
 dojox/drawing/plugins/tools/Iconize.js             |  172 +-
 dojox/drawing/plugins/tools/Pan.js                 |  362 +-
 dojox/drawing/plugins/tools/Zoom.js                |  168 +-
 dojox/drawing/resources/drawing.css                |    9 +-
 dojox/drawing/resources/images/tool_icons.png      |  Bin 7213 -> 7213 bytes
 dojox/drawing/resources/toolbar.css                |   50 +-
 dojox/drawing/stencil/Ellipse.js                   |  127 +-
 dojox/drawing/stencil/Image.js                     |  213 +-
 dojox/drawing/stencil/Line.js                      |  150 +-
 dojox/drawing/stencil/Path.js                      |  251 +-
 dojox/drawing/stencil/Rect.js                      |  112 +-
 dojox/drawing/stencil/Text.js                      |  315 +-
 dojox/drawing/stencil/_Base.js                     | 1769 +-
 dojox/drawing/tests/drawing.html                   |  183 +
 dojox/drawing/tests/test_drawing.html              |  158 +
 dojox/drawing/tests/test_drawing_toolbar.html      |  101 +
 dojox/drawing/tests/test_paths.html                |  116 +
 dojox/drawing/tests/test_shadows.html              |   99 +
 dojox/drawing/tools/Arrow.js                       |  102 +-
 dojox/drawing/tools/Ellipse.js                     |  121 +-
 dojox/drawing/tools/Line.js                        |  175 +-
 dojox/drawing/tools/Path.js                        |  351 +-
 dojox/drawing/tools/Pencil.js                      |  135 +-
 dojox/drawing/tools/Rect.js                        |  116 +-
 dojox/drawing/tools/TextBlock.js                   | 1036 +-
 dojox/drawing/tools/custom/Axes.js                 |  773 +-
 dojox/drawing/tools/custom/Equation.js             |   38 +-
 dojox/drawing/tools/custom/Vector.js               |  446 +-
 dojox/drawing/ui/Button.js                         |  362 +-
 dojox/drawing/ui/Toolbar.js                        |  398 +-
 dojox/drawing/ui/Tooltip.js                        |  173 +-
 dojox/drawing/ui/dom/Pan.js                        |  321 +-
 dojox/drawing/ui/dom/Toolbar.js                    |  317 +-
 dojox/drawing/ui/dom/Zoom.js                       |  182 +-
 dojox/drawing/util/common.js                       |  382 +-
 dojox/drawing/util/oo.js                           |  172 +-
 dojox/drawing/util/positioning.js                  |  104 +-
 dojox/dtl.js                                       |   18 +-
 dojox/dtl.js.uncompressed.js                       | 2855 ---
 dojox/dtl/Context.js                               |  128 +-
 dojox/dtl/DomInline.js                             |   65 +-
 dojox/dtl/HtmlInline.js                            |   16 +-
 dojox/dtl/Inline.js                                |   57 +-
 dojox/dtl/_DomTemplated.js                         |  131 +-
 dojox/dtl/_HtmlTemplated.js                        |   16 +-
 dojox/dtl/_Templated.js                            |  190 +-
 dojox/dtl/_base.js                                 | 1272 +-
 dojox/dtl/contrib/data.js                          |  271 +-
 dojox/dtl/contrib/dijit.js                         |  396 +-
 dojox/dtl/contrib/dom.js                           |  294 +-
 dojox/dtl/contrib/html.js                          |   12 +-
 dojox/dtl/contrib/objects.js                       |   22 +-
 dojox/dtl/demos/demo_Animation.html                |   45 +
 dojox/dtl/demos/demo_Blog.html                     |   95 +
 dojox/dtl/demos/demo_Data.html                     |   59 +
 dojox/dtl/demos/demo_Dijitless.html                |   50 +
 dojox/dtl/demos/demo_DomTemplated.html             |   44 +
 dojox/dtl/demos/demo_Events.html                   |   46 +
 dojox/dtl/demos/demo_Inline.html                   |   51 +
 dojox/dtl/demos/demo_NodeList.html                 |   37 +
 dojox/dtl/demos/demo_Table.html                    | 4073 ++++
 dojox/dtl/demos/demo_Templated.html                |   36 +
 dojox/dtl/demos/demo_Tree.html                     |   48 +
 dojox/dtl/demos/json/blog/get_blog_1.json          |    1 +
 dojox/dtl/demos/json/blog/get_blog_3.json          |    1 +
 dojox/dtl/demos/json/blog/get_blog_list.json       |    1 +
 dojox/dtl/demos/json/blog/get_page_about.json      |    1 +
 dojox/dtl/demos/json/fruit.json                    |    1 +
 dojox/dtl/demos/json/morefruit.json                |    1 +
 dojox/dtl/demos/templates/animation.html           |    5 +
 dojox/dtl/demos/templates/blog_base.html           |   11 +
 dojox/dtl/demos/templates/blog_detail.html         |   10 +
 dojox/dtl/demos/templates/blog_list.html           |    9 +
 dojox/dtl/demos/templates/blog_page.html           |    7 +
 dojox/dtl/demos/templates/gallery.html             |   16 +
 dojox/dtl/demos/templates/nodelist.html            |    5 +
 dojox/dtl/dom.js                                   | 1885 +-
 dojox/dtl/ext-dojo/NodeList.js                     |   54 +-
 dojox/dtl/filter/dates.js                          |  115 +-
 dojox/dtl/filter/htmlstrings.js                    |   78 +-
 dojox/dtl/filter/integers.js                       |   54 +-
 dojox/dtl/filter/lists.js                          |  228 +-
 dojox/dtl/filter/logic.js                          |   67 +-
 dojox/dtl/filter/misc.js                           |  103 +-
 dojox/dtl/filter/strings.js                        |  587 +-
 dojox/dtl/html.js                                  |   14 +-
 dojox/dtl/render/dom.js                            |   60 +-
 dojox/dtl/render/html.js                           |   12 +-
 dojox/dtl/tag/date.js                              |   56 +-
 dojox/dtl/tag/loader.js                            |  551 +-
 dojox/dtl/tag/logic.js                             |  515 +-
 dojox/dtl/tag/loop.js                              |  348 +-
 dojox/dtl/tag/misc.js                              |  502 +-
 dojox/dtl/tests/context.js                         |   84 +
 dojox/dtl/tests/demo_Templated_Jaxer.html          |   87 +
 dojox/dtl/tests/dom/buffer.js                      |   31 +
 dojox/dtl/tests/dom/tag.js                         |  324 +
 dojox/dtl/tests/dom/util.js                        |  157 +
 dojox/dtl/tests/module.js                          |   11 +
 dojox/dtl/tests/runTests.html                      |    9 +
 dojox/dtl/tests/templates/base.html                |    1 +
 dojox/dtl/tests/templates/hello.html               |    1 +
 dojox/dtl/tests/templates/pocket.html              |    1 +
 dojox/dtl/tests/templates/pocket2.html             |    1 +
 dojox/dtl/tests/text/filter.js                     |  736 +
 dojox/dtl/tests/text/load.js                       |    2 +
 dojox/dtl/tests/text/tag.js                        |  490 +
 dojox/dtl/utils/date.js                            |  125 +-
 dojox/editor/README                                |   97 +-
 dojox/editor/plugins/Blockquote.js                 |  506 +
 dojox/editor/plugins/Breadcrumb.js                 |  556 +-
 dojox/editor/plugins/CollapsibleToolbar.js         |  174 +
 dojox/editor/plugins/EntityPalette.js              |  367 +-
 dojox/editor/plugins/FindReplace.js                | 1092 +-
 dojox/editor/plugins/InsertAnchor.js               |  430 +
 dojox/editor/plugins/InsertEntity.js               |  126 +-
 dojox/editor/plugins/NormalizeIndentOutdent.js     | 1503 +-
 dojox/editor/plugins/NormalizeStyle.js             |  551 +
 dojox/editor/plugins/PageBreak.js                  |  229 +-
 dojox/editor/plugins/PasteFromWord.js              |  206 +
 dojox/editor/plugins/PrettyPrint.js                |  141 +-
 dojox/editor/plugins/Preview.js                    |  136 +-
 dojox/editor/plugins/Save.js                       |  172 +-
 dojox/editor/plugins/ShowBlockNodes.js             |  254 +-
 dojox/editor/plugins/Smiley.js                     |  139 +-
 dojox/editor/plugins/StatusBar.js                  |  172 +
 dojox/editor/plugins/TablePlugins.js               | 1639 +-
 dojox/editor/plugins/TextColor.js                  |  191 +
 dojox/editor/plugins/ToolbarLineBreak.js           |   55 +-
 dojox/editor/plugins/UploadImage.js                |  144 +-
 dojox/editor/plugins/_SmileyPalette.js             |  259 +-
 dojox/editor/plugins/nls/Blockquote.js             |    3 +
 dojox/editor/plugins/nls/Breadcrumb.js             |   10 +-
 dojox/editor/plugins/nls/CollapsibleToolbar.js     |    4 +
 dojox/editor/plugins/nls/FindReplace.js            |   22 +-
 dojox/editor/plugins/nls/InsertAnchor.js           |    8 +
 dojox/editor/plugins/nls/InsertEntity.js           |    4 +-
 dojox/editor/plugins/nls/PageBreak.js              |    4 +-
 dojox/editor/plugins/nls/PasteFromWord.js          |    6 +
 dojox/editor/plugins/nls/Preview.js                |    4 +-
 dojox/editor/plugins/nls/Save.js                   |    4 +-
 dojox/editor/plugins/nls/ShowBlockNodes.js         |    4 +-
 dojox/editor/plugins/nls/Smiley.js                 |   22 +-
 dojox/editor/plugins/nls/TableDialog.js            |   30 +-
 dojox/editor/plugins/nls/TextColor.js              |    4 +
 dojox/editor/plugins/nls/ar/TableDialog.js         |   30 +-
 dojox/editor/plugins/nls/ca/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/cs/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/cs/FindReplace.js         |   13 +-
 dojox/editor/plugins/nls/cs/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/cs/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/cs/Preview.js             |    5 +-
 dojox/editor/plugins/nls/cs/Save.js                |    5 +-
 dojox/editor/plugins/nls/cs/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/cs/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/cs/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/cs/latinEntities.js       |  258 +-
 dojox/editor/plugins/nls/da/TableDialog.js         |   30 +-
 dojox/editor/plugins/nls/de/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/de/FindReplace.js         |   13 +-
 dojox/editor/plugins/nls/de/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/de/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/de/Preview.js             |    5 +-
 dojox/editor/plugins/nls/de/Save.js                |    5 +-
 dojox/editor/plugins/nls/de/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/de/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/de/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/de/latinEntities.js       |  258 +-
 dojox/editor/plugins/nls/el/TableDialog.js         |   30 +-
 dojox/editor/plugins/nls/es/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/es/FindReplace.js         |   13 +-
 dojox/editor/plugins/nls/es/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/es/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/es/Preview.js             |    5 +-
 dojox/editor/plugins/nls/es/Save.js                |    5 +-
 dojox/editor/plugins/nls/es/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/es/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/es/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/es/latinEntities.js       |  258 +-
 dojox/editor/plugins/nls/fi/TableDialog.js         |   30 +-
 dojox/editor/plugins/nls/fr/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/fr/FindReplace.js         |   13 +-
 dojox/editor/plugins/nls/fr/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/fr/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/fr/Preview.js             |    5 +-
 dojox/editor/plugins/nls/fr/Save.js                |    5 +-
 dojox/editor/plugins/nls/fr/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/fr/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/fr/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/fr/latinEntities.js       |  258 +-
 dojox/editor/plugins/nls/he/TableDialog.js         |   30 +-
 dojox/editor/plugins/nls/hu/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/hu/FindReplace.js         |   13 +-
 dojox/editor/plugins/nls/hu/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/hu/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/hu/Preview.js             |    5 +-
 dojox/editor/plugins/nls/hu/Save.js                |    5 +-
 dojox/editor/plugins/nls/hu/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/hu/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/hu/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/hu/latinEntities.js       |  258 +-
 dojox/editor/plugins/nls/it/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/it/FindReplace.js         |   13 +-
 dojox/editor/plugins/nls/it/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/it/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/it/Preview.js             |    5 +-
 dojox/editor/plugins/nls/it/Save.js                |    5 +-
 dojox/editor/plugins/nls/it/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/it/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/it/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/it/latinEntities.js       |  258 +-
 dojox/editor/plugins/nls/ja/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/ja/FindReplace.js         |   13 +-
 dojox/editor/plugins/nls/ja/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/ja/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/ja/Preview.js             |    5 +-
 dojox/editor/plugins/nls/ja/Save.js                |    5 +-
 dojox/editor/plugins/nls/ja/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/ja/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/ja/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/ja/latinEntities.js       |  258 +-
 dojox/editor/plugins/nls/ko/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/ko/FindReplace.js         |   13 +-
 dojox/editor/plugins/nls/ko/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/ko/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/ko/Preview.js             |    5 +-
 dojox/editor/plugins/nls/ko/Save.js                |    5 +-
 dojox/editor/plugins/nls/ko/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/ko/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/ko/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/ko/latinEntities.js       |  258 +-
 dojox/editor/plugins/nls/latinEntities.js          |  257 +-
 dojox/editor/plugins/nls/nb/TableDialog.js         |   30 +-
 dojox/editor/plugins/nls/nl/TableDialog.js         |   30 +-
 dojox/editor/plugins/nls/pl/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/pl/FindReplace.js         |   13 +-
 dojox/editor/plugins/nls/pl/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/pl/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/pl/Preview.js             |    5 +-
 dojox/editor/plugins/nls/pl/Save.js                |    5 +-
 dojox/editor/plugins/nls/pl/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/pl/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/pl/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/pl/latinEntities.js       |  258 +-
 dojox/editor/plugins/nls/pt-pt/TableDialog.js      |   30 +-
 dojox/editor/plugins/nls/pt/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/pt/FindReplace.js         |   13 +-
 dojox/editor/plugins/nls/pt/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/pt/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/pt/Preview.js             |    5 +-
 dojox/editor/plugins/nls/pt/Save.js                |    5 +-
 dojox/editor/plugins/nls/pt/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/pt/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/pt/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/pt/latinEntities.js       |  258 +-
 dojox/editor/plugins/nls/ro/Blockquote.js          |    4 +
 dojox/editor/plugins/nls/ro/Breadcrumb.js          |   10 +
 dojox/editor/plugins/nls/ro/CollapsibleToolbar.js  |    5 +
 dojox/editor/plugins/nls/ro/FindReplace.js         |   22 +
 dojox/editor/plugins/nls/ro/InsertAnchor.js        |    9 +
 dojox/editor/plugins/nls/ro/InsertEntity.js        |    4 +
 dojox/editor/plugins/nls/ro/PageBreak.js           |    4 +
 dojox/editor/plugins/nls/ro/PasteFromWord.js       |    7 +
 dojox/editor/plugins/nls/ro/Preview.js             |    4 +
 dojox/editor/plugins/nls/ro/Save.js                |    4 +
 dojox/editor/plugins/nls/ro/ShowBlockNodes.js      |    4 +
 dojox/editor/plugins/nls/ro/Smiley.js              |   22 +
 dojox/editor/plugins/nls/ro/TableDialog.js         |   30 +
 dojox/editor/plugins/nls/ro/TextColor.js           |    5 +
 dojox/editor/plugins/nls/ro/latinEntities.js       |  257 +
 dojox/editor/plugins/nls/ru/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/ru/FindReplace.js         |   13 +-
 dojox/editor/plugins/nls/ru/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/ru/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/ru/Preview.js             |    5 +-
 dojox/editor/plugins/nls/ru/Save.js                |    5 +-
 dojox/editor/plugins/nls/ru/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/ru/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/ru/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/ru/latinEntities.js       |  258 +-
 dojox/editor/plugins/nls/sk/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/sl/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/sv/TableDialog.js         |   30 +-
 dojox/editor/plugins/nls/th/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/tr/TableDialog.js         |   30 +-
 dojox/editor/plugins/nls/zh-tw/Breadcrumb.js       |   11 +-
 dojox/editor/plugins/nls/zh-tw/FindReplace.js      |   13 +-
 dojox/editor/plugins/nls/zh-tw/InsertEntity.js     |    5 +-
 dojox/editor/plugins/nls/zh-tw/PageBreak.js        |    5 +-
 dojox/editor/plugins/nls/zh-tw/Preview.js          |    5 +-
 dojox/editor/plugins/nls/zh-tw/Save.js             |    5 +-
 dojox/editor/plugins/nls/zh-tw/ShowBlockNodes.js   |    5 +-
 dojox/editor/plugins/nls/zh-tw/Smiley.js           |   23 +-
 dojox/editor/plugins/nls/zh-tw/TableDialog.js      |   31 +-
 dojox/editor/plugins/nls/zh-tw/latinEntities.js    |  258 +-
 dojox/editor/plugins/nls/zh/Breadcrumb.js          |   11 +-
 dojox/editor/plugins/nls/zh/FindReplace.js         |   23 +-
 dojox/editor/plugins/nls/zh/InsertEntity.js        |    5 +-
 dojox/editor/plugins/nls/zh/PageBreak.js           |    5 +-
 dojox/editor/plugins/nls/zh/Preview.js             |    5 +-
 dojox/editor/plugins/nls/zh/Save.js                |    5 +-
 dojox/editor/plugins/nls/zh/ShowBlockNodes.js      |    5 +-
 dojox/editor/plugins/nls/zh/Smiley.js              |   23 +-
 dojox/editor/plugins/nls/zh/TableDialog.js         |   31 +-
 dojox/editor/plugins/nls/zh/latinEntities.js       |  258 +-
 dojox/editor/plugins/resources/css/Blockquote.css  |   17 +
 dojox/editor/plugins/resources/css/Breadcrumb.css  |    3 +
 .../plugins/resources/css/CollapsibleToolbar.css   |  173 +
 dojox/editor/plugins/resources/css/FindReplace.css |  129 +-
 .../editor/plugins/resources/css/InsertAnchor.css  |   17 +
 .../editor/plugins/resources/css/InsertEntity.css  |   59 +-
 dojox/editor/plugins/resources/css/PageBreak.css   |    3 +
 .../editor/plugins/resources/css/PasteFromWord.css |   30 +
 dojox/editor/plugins/resources/css/Preview.css     |    3 +
 dojox/editor/plugins/resources/css/Save.css        |    3 +
 .../plugins/resources/css/ShowBlockNodes.css       |    3 +
 dojox/editor/plugins/resources/css/Smiley.css      |   90 +-
 dojox/editor/plugins/resources/css/StatusBar.css   |   75 +
 dojox/editor/plugins/resources/css/TextColor.css   |    7 +
 dojox/editor/plugins/resources/editorPlugins.css   |   20 +-
 dojox/editor/plugins/resources/icons/anchor.gif    |  Bin 0 -> 197 bytes
 .../plugins/resources/icons/anchorDisabled.gif     |  Bin 0 -> 877 bytes
 .../editor/plugins/resources/icons/blockquote.gif  |  Bin 0 -> 1007 bytes
 .../plugins/resources/icons/blockquoteDisabled.gif |  Bin 0 -> 960 bytes
 .../plugins/resources/icons/breadcrumbDown.gif     |  Bin 866 -> 866 bytes
 .../editor/plugins/resources/icons/claro/close.gif |  Bin 0 -> 881 bytes
 .../icons/editorIconsFindReplaceDisabled.png       |  Bin 0 -> 812 bytes
 .../icons/editorIconsFindReplaceEnabled.png        |  Bin 0 -> 983 bytes
 dojox/editor/plugins/resources/icons/findIcon.gif  |  Bin 341 -> 0 bytes
 .../plugins/resources/icons/findIconDisabled.gif   |  Bin 902 -> 0 bytes
 .../editor/plugins/resources/icons/findReplace.gif |  Bin 347 -> 0 bytes
 .../resources/icons/findReplaceDisabled.gif        |  Bin 923 -> 0 bytes
 .../plugins/resources/icons/insertEntity.gif       |  Bin 177 -> 177 bytes
 .../resources/icons/insertEntityDisabled.gif       |  Bin 177 -> 177 bytes
 .../plugins/resources/icons/nihilo/close.gif       |  Bin 0 -> 965 bytes
 dojox/editor/plugins/resources/icons/pageBreak.gif |  Bin 564 -> 564 bytes
 .../plugins/resources/icons/pageBreakDisabled.gif  |  Bin 912 -> 912 bytes
 .../plugins/resources/icons/pasteFromWord.gif      |  Bin 0 -> 1005 bytes
 .../resources/icons/pasteFromWordDisabled.gif      |  Bin 0 -> 269 bytes
 dojox/editor/plugins/resources/icons/preview.gif   |  Bin 577 -> 577 bytes
 .../plugins/resources/icons/previewDisabled.gif    |  Bin 913 -> 913 bytes
 .../editor/plugins/resources/icons/replaceIcon.gif |  Bin 574 -> 0 bytes
 .../resources/icons/replaceIconDisabled.gif        |  Bin 933 -> 0 bytes
 dojox/editor/plugins/resources/icons/save.gif      |  Bin 639 -> 639 bytes
 .../plugins/resources/icons/saveDisabled.gif       |  Bin 378 -> 378 bytes
 .../plugins/resources/icons/showBlockNodes.gif     |  Bin 599 -> 599 bytes
 .../resources/icons/showBlockNodesDisabled.gif     |  Bin 957 -> 957 bytes
 .../plugins/resources/icons/smileyDisabled.gif     |  Bin 0 -> 404 bytes
 .../editor/plugins/resources/icons/soria/close.gif |  Bin 0 -> 941 bytes
 .../plugins/resources/icons/tundra/close.gif       |  Bin 193 -> 193 bytes
 dojox/editor/plugins/resources/images/anchor.gif   |  Bin 0 -> 197 bytes
 .../resources/images/blockelems/address.gif        |  Bin 936 -> 936 bytes
 .../resources/images/blockelems/blockquote.gif     |  Bin 935 -> 935 bytes
 .../plugins/resources/images/blockelems/button.gif |  Bin 929 -> 929 bytes
 .../plugins/resources/images/blockelems/center.gif |  Bin 931 -> 931 bytes
 .../plugins/resources/images/blockelems/dd.gif     |  Bin 888 -> 888 bytes
 .../plugins/resources/images/blockelems/del.gif    |  Bin 898 -> 898 bytes
 .../plugins/resources/images/blockelems/div.gif    |  Bin 896 -> 896 bytes
 .../plugins/resources/images/blockelems/dt.gif     |  Bin 887 -> 887 bytes
 .../resources/images/blockelems/fieldset.gif       |  Bin 933 -> 933 bytes
 .../plugins/resources/images/blockelems/form.gif   |  Bin 918 -> 918 bytes
 .../plugins/resources/images/blockelems/h1.gif     |  Bin 886 -> 886 bytes
 .../plugins/resources/images/blockelems/h2.gif     |  Bin 889 -> 889 bytes
 .../plugins/resources/images/blockelems/h3.gif     |  Bin 891 -> 891 bytes
 .../plugins/resources/images/blockelems/h4.gif     |  Bin 890 -> 890 bytes
 .../plugins/resources/images/blockelems/h5.gif     |  Bin 892 -> 892 bytes
 .../plugins/resources/images/blockelems/h6.gif     |  Bin 890 -> 890 bytes
 .../plugins/resources/images/blockelems/hr.gif     |  Bin 891 -> 891 bytes
 .../plugins/resources/images/blockelems/iframe.gif |  Bin 929 -> 929 bytes
 .../plugins/resources/images/blockelems/ins.gif    |  Bin 898 -> 898 bytes
 .../plugins/resources/images/blockelems/li.gif     |  Bin 880 -> 880 bytes
 .../plugins/resources/images/blockelems/map.gif    |  Bin 907 -> 907 bytes
 .../resources/images/blockelems/noscript.gif       |  Bin 943 -> 943 bytes
 .../plugins/resources/images/blockelems/object.gif |  Bin 925 -> 925 bytes
 .../plugins/resources/images/blockelems/ol.gif     |  Bin 887 -> 887 bytes
 .../plugins/resources/images/blockelems/p.gif      |  Bin 875 -> 875 bytes
 .../plugins/resources/images/blockelems/pre.gif    |  Bin 898 -> 898 bytes
 .../plugins/resources/images/blockelems/script.gif |  Bin 924 -> 924 bytes
 .../plugins/resources/images/blockelems/table.gif  |  Bin 917 -> 917 bytes
 .../plugins/resources/images/blockelems/ul.gif     |  Bin 884 -> 884 bytes
 .../plugins/resources/images/claro/collapse.gif    |  Bin 0 -> 860 bytes
 .../plugins/resources/images/claro/expand.gif      |  Bin 0 -> 871 bytes
 .../plugins/resources/images/nihilo/collapse.gif   |  Bin 0 -> 860 bytes
 .../plugins/resources/images/nihilo/expand.gif     |  Bin 0 -> 871 bytes
 .../plugins/resources/images/nihilo/sidebar.gif    |  Bin 0 -> 832 bytes
 .../plugins/resources/images/soria/collapse.gif    |  Bin 0 -> 860 bytes
 .../plugins/resources/images/soria/expand.gif      |  Bin 0 -> 871 bytes
 .../plugins/resources/images/soria/sidebar.gif     |  Bin 0 -> 832 bytes
 .../plugins/resources/images/tundra/collapse.gif   |  Bin 0 -> 860 bytes
 .../plugins/resources/images/tundra/expand.gif     |  Bin 0 -> 871 bytes
 .../plugins/resources/images/tundra/sidebar.gif    |  Bin 0 -> 834 bytes
 dojox/editor/tests/dummySave.php                   |    5 +
 dojox/editor/tests/editorBlockquote.html           |  118 +
 dojox/editor/tests/editorBreadcrumb.html           |  120 +
 dojox/editor/tests/editorCollapsibleToolbar.html   |  131 +
 dojox/editor/tests/editorFindReplace.html          |  121 +
 dojox/editor/tests/editorInsertAnchor.html         |  119 +
 dojox/editor/tests/editorInsertEntity.html         |  170 +
 .../editor/tests/editorNormalizeIndentOutdent.html |  120 +
 dojox/editor/tests/editorNormalizeStyle.html       |  163 +
 dojox/editor/tests/editorPageBreak.html            |   99 +
 dojox/editor/tests/editorPasteFromWord.html        |   98 +
 dojox/editor/tests/editorPrettyPrint.html          |  327 +
 dojox/editor/tests/editorPreview.html              |  249 +
 dojox/editor/tests/editorSave.html                 |  104 +
 dojox/editor/tests/editorShowBlockNodes.html       |   97 +
 dojox/editor/tests/editorSmileyPlugin.html         |   92 +
 dojox/editor/tests/editorStatusBar.html            |  232 +
 dojox/editor/tests/editorTablePlugs.html           |   87 +
 dojox/editor/tests/editorTextColor.html            |   97 +
 dojox/editor/tests/editorToolbarLineBreak.html     |   95 +
 dojox/editor/tests/editorUploadPlug.html           |   69 +
 dojox/editor/tests/module.js                       |   15 +
 dojox/editor/tests/robot/Editor_Smiley.html        |   60 +
 dojox/editor/tests/runTests.html                   |    9 +
 dojox/editor/tests/testBodySheet.css               |    4 +
 dojox/editor/tests/testContentSheet.css            |   20 +
 dojox/editor/tests/testPluginsAll.html             |  206 +
 dojox/embed/Flash.js                               |  808 +-
 dojox/embed/IE/flash.js                            |   35 +-
 dojox/embed/Object.js                              |  134 +-
 dojox/embed/Quicktime.js                           |  396 +-
 dojox/embed/flashVars.js                           |   90 +-
 dojox/embed/tests/flash.html                       |   58 +
 dojox/embed/tests/object.html                      |   29 +
 dojox/embed/tests/quicktime.html                   |   46 +
 dojox/embed/tests/resources/TestFlash.swf          |  Bin 0 -> 1863 bytes
 dojox/embed/tests/resources/hfp.swf                |  Bin 0 -> 13671 bytes
 dojox/encoding/_base.js                            |   10 +-
 dojox/encoding/ascii85.js                          |  124 +-
 dojox/encoding/base64.js                           |  126 +-
 dojox/encoding/bits.js                             |  122 +-
 dojox/encoding/compression/lzw.js                  |  162 +-
 dojox/encoding/compression/splay.js                |  119 +-
 dojox/encoding/crypto/Blowfish.js                  |  744 +-
 dojox/encoding/crypto/RSAKey-ext.js                |  215 +-
 dojox/encoding/crypto/RSAKey.js                    |  127 +-
 dojox/encoding/crypto/SimpleAES.js                 |  561 +-
 dojox/encoding/crypto/_base.js                     |   25 +-
 dojox/encoding/digests/MD5.js                      |  323 +-
 dojox/encoding/digests/SHA1.js                     |  279 +-
 dojox/encoding/digests/_base.js                    |  125 +-
 dojox/encoding/easy64.js                           |   87 +-
 dojox/encoding/tests/ascii85.js                    |   31 +
 dojox/encoding/tests/bits.js                       |   70 +
 dojox/encoding/tests/compression/_base.js          |    8 +
 dojox/encoding/tests/compression/colors.js         |  152 +
 dojox/encoding/tests/compression/colors2.html      |  104 +
 dojox/encoding/tests/compression/colors2.js        |   60 +
 dojox/encoding/tests/compression/colors3.html      |  104 +
 dojox/encoding/tests/compression/colors3.js        |   49 +
 dojox/encoding/tests/compression/lzw.js            |   50 +
 dojox/encoding/tests/compression/runTests.html     |    9 +
 dojox/encoding/tests/compression/splay.js          |   45 +
 dojox/encoding/tests/compression/test.html         |   61 +
 dojox/encoding/tests/compression/vq.html           |  185 +
 dojox/encoding/tests/crypto/Blowfish.js            |   31 +
 dojox/encoding/tests/crypto/RSA.js                 |  175 +
 dojox/encoding/tests/crypto/SimpleAES.js           |   20 +
 dojox/encoding/tests/crypto/_base.js               |   10 +
 dojox/encoding/tests/crypto/runTests.html          |    9 +
 dojox/encoding/tests/digests/MD5.js                |   22 +
 dojox/encoding/tests/digests/SHA1.js               |   22 +
 dojox/encoding/tests/digests/_base.js              |    9 +
 dojox/encoding/tests/digests/runTests.html         |    9 +
 dojox/encoding/tests/easy64.js                     |   31 +
 dojox/encoding/tests/encoding.js                   |    9 +
 dojox/encoding/tests/runTests.html                 |    9 +
 dojox/flash.js                                     |   10 -
 dojox/flash/_base.js                               | 1036 +-
 dojox/flash/tests/TestFlash.as                     |   42 +
 dojox/flash/tests/TestFlash.swf                    |  Bin 0 -> 1943 bytes
 dojox/flash/tests/buildFlashTest.sh                |    4 +
 dojox/flash/tests/test_flash.html                  |   15 +
 dojox/flash/tests/test_flash.js                    |  191 +
 dojox/form/BusyButton.js                           |  198 +-
 dojox/form/CheckedMultiSelect.js                   |  266 +-
 dojox/form/DateTextBox.js                          |  229 +-
 dojox/form/DropDownSelect.js                       |   14 +-
 dojox/form/DropDownStack.js                        |   18 +-
 dojox/form/FileInput.js                            |  118 +-
 dojox/form/FileInputAuto.js                        |  300 +-
 dojox/form/FileInputBlind.js                       |   14 +-
 dojox/form/FilePickerTextBox.js                    |  575 +-
 dojox/form/FileUploader.js                         | 2191 +-
 dojox/form/ListInput.js                            | 1429 +-
 dojox/form/Manager.js                              |   53 +-
 dojox/form/MultiComboBox.js                        |   97 +-
 dojox/form/PasswordValidator.js                    |  457 +-
 dojox/form/RadioStack.js                           |   17 +-
 dojox/form/RangeSlider.js                          |  674 +-
 dojox/form/Rating.js                               |  145 +-
 dojox/form/TimeSpinner.js                          |   82 +-
 dojox/form/_FormSelectWidget.js                    |   14 +-
 dojox/form/_HasDropDown.js                         |   14 +-
 dojox/form/_SelectStackMixin.js                    |  359 +-
 dojox/form/manager/_ClassMixin.js                  |   93 +-
 dojox/form/manager/_DisplayMixin.js                |   84 +-
 dojox/form/manager/_EnableMixin.js                 |  116 +-
 dojox/form/manager/_FormMixin.js                   |  191 +-
 dojox/form/manager/_Mixin.js                       |  750 +-
 dojox/form/manager/_NodeMixin.js                   |  591 +-
 dojox/form/manager/_ValueMixin.js                  |  121 +-
 dojox/form/nls/PasswordValidator.js                |    5 +-
 dojox/form/nls/ar/PasswordValidator.js             |    6 +-
 dojox/form/nls/ca/PasswordValidator.js             |    6 +-
 dojox/form/nls/cs/PasswordValidator.js             |    6 +-
 dojox/form/nls/da/PasswordValidator.js             |    6 +-
 dojox/form/nls/de/PasswordValidator.js             |    6 +-
 dojox/form/nls/el/PasswordValidator.js             |    6 +-
 dojox/form/nls/es/PasswordValidator.js             |    6 +-
 dojox/form/nls/fi/PasswordValidator.js             |    6 +-
 dojox/form/nls/fr/PasswordValidator.js             |    6 +-
 dojox/form/nls/he/PasswordValidator.js             |    6 +-
 dojox/form/nls/hu/PasswordValidator.js             |    6 +-
 dojox/form/nls/it/PasswordValidator.js             |    6 +-
 dojox/form/nls/ja/PasswordValidator.js             |    6 +-
 dojox/form/nls/ko/PasswordValidator.js             |    6 +-
 dojox/form/nls/nb/PasswordValidator.js             |    6 +-
 dojox/form/nls/nl/PasswordValidator.js             |    6 +-
 dojox/form/nls/pl/PasswordValidator.js             |    6 +-
 dojox/form/nls/pt-pt/PasswordValidator.js          |    6 +-
 dojox/form/nls/pt/PasswordValidator.js             |    6 +-
 dojox/form/nls/ro/PasswordValidator.js             |    5 +
 dojox/form/nls/ru/PasswordValidator.js             |    6 +-
 dojox/form/nls/sk/PasswordValidator.js             |    6 +-
 dojox/form/nls/sl/PasswordValidator.js             |    6 +-
 dojox/form/nls/sv/PasswordValidator.js             |    6 +-
 dojox/form/nls/th/PasswordValidator.js             |    6 +-
 dojox/form/nls/tr/PasswordValidator.js             |    6 +-
 dojox/form/nls/zh-tw/PasswordValidator.js          |    6 +-
 dojox/form/nls/zh/PasswordValidator.js             |    6 +-
 dojox/form/resources/BusyButton.css                |    8 +-
 dojox/form/resources/CheckedMultiSelect.css        |   74 +-
 dojox/form/resources/CheckedMultiSelect.html       |    2 +-
 dojox/form/resources/FileInput.css                 |   46 +-
 dojox/form/resources/FilePickerTextBox.css         |  220 +-
 dojox/form/resources/FilePickerTextBox.html        |    4 +-
 dojox/form/resources/FileUploader.css              |   34 +-
 dojox/form/resources/HorizontalRangeSlider.html    |   76 +-
 dojox/form/resources/ListInput.css                 |    1 +
 dojox/form/resources/RangeSlider.css               |   16 +-
 dojox/form/resources/Rating.css                    |    4 +
 dojox/form/resources/RecieveFile.php               |   37 +
 dojox/form/resources/VerticalRangeSlider.html      |   99 +-
 dojox/form/resources/_CheckedMultiSelectItem.html  |    2 +-
 dojox/form/tests/UploadFile.php.disabled           |  235 +
 dojox/form/tests/_tags.json                        |  100 +
 dojox/form/tests/cLOG.php.disabled                 |   54 +
 dojox/form/tests/images/grad.jpg                   |  Bin 0 -> 361 bytes
 dojox/form/tests/images/grad_down.jpg              |  Bin 0 -> 352 bytes
 dojox/form/tests/images/grad_over.jpg              |  Bin 0 -> 381 bytes
 dojox/form/tests/images/rating_empty.gif           |  Bin 0 -> 1277 bytes
 dojox/form/tests/images/rating_full.gif            |  Bin 0 -> 1314 bytes
 dojox/form/tests/images/rndBtnSprite.png           |  Bin 0 -> 9402 bytes
 dojox/form/tests/images/rndBtn_down.png            |  Bin 0 -> 4035 bytes
 dojox/form/tests/images/rndBtn_norm.png            |  Bin 0 -> 3977 bytes
 dojox/form/tests/images/rndBtn_over.png            |  Bin 0 -> 3945 bytes
 dojox/form/tests/test_BusyButton.html              |  104 +
 dojox/form/tests/test_CheckedMultiSelect.html      |  323 +
 dojox/form/tests/test_DateTextBox.html             |  192 +
 dojox/form/tests/test_FileInput.html               |  121 +
 dojox/form/tests/test_FilePickerTextBox.html       |   49 +
 dojox/form/tests/test_FileUploader.html            |  272 +
 dojox/form/tests/test_FileUploaderCSS.html         |  264 +
 dojox/form/tests/test_FileUploaderDialog.html      |  115 +
 dojox/form/tests/test_FileUploaderForm.html        |  298 +
 dojox/form/tests/test_FileUploaderTabs.html        |  147 +
 dojox/form/tests/test_ListInput.html               |  189 +
 dojox/form/tests/test_Manager1.html                |  213 +
 dojox/form/tests/test_MultiComboBox.html           |   70 +
 dojox/form/tests/test_PasswordValidator.html       |  236 +
 dojox/form/tests/test_RangeSlider.html             |  101 +
 dojox/form/tests/test_Rating.html                  |  108 +
 dojox/form/tests/test_SelectStack.html             |  129 +
 dojox/form/tests/test_TimeSpinner.html             |   60 +
 dojox/form/tests/uploads/README                    |   11 +
 dojox/fx.js                                        |   13 +-
 dojox/fx/Shadow.js                                 |  259 +-
 dojox/fx/Timeline.js                               |  210 +
 dojox/fx/_arg.js                                   |   38 +-
 dojox/fx/_base.js                                  |  417 +-
 dojox/fx/_core.js                                  |   86 +-
 dojox/fx/easing.js                                 |   18 +-
 dojox/fx/ext-dojo/NodeList-style.js                |   81 +-
 dojox/fx/ext-dojo/NodeList.js                      |   79 +-
 dojox/fx/ext-dojo/complex.js                       |  169 +
 dojox/fx/ext-dojo/reverse.js                       |   98 +
 dojox/fx/flip.js                                   |  676 +-
 dojox/fx/scroll.js                                 |   70 +-
 dojox/fx/split.js                                  |  974 +-
 dojox/fx/style.js                                  |  302 +-
 dojox/fx/tests/_animation.css                      |  113 +
 dojox/fx/tests/_base.js                            |   63 +
 dojox/fx/tests/example_Line.html                   |   80 +
 dojox/fx/tests/example_backgroundPosition.html     |   57 +
 dojox/fx/tests/example_dojoAnimations.html         |  439 +
 dojox/fx/tests/example_easingChart2D.html          |  147 +
 dojox/fx/tests/images/averycutedog.jpg             |  Bin 0 -> 40879 bytes
 dojox/fx/tests/images/dot.png                      |  Bin 0 -> 4064 bytes
 dojox/fx/tests/images/longBg.png                   |  Bin 0 -> 12217 bytes
 dojox/fx/tests/runTests.html                       |   10 +
 dojox/fx/tests/test_Nodelist-fx.html               |  282 +
 dojox/fx/tests/test_Shadow.html                    |   93 +
 dojox/fx/tests/test_Timeline.html                  |  173 +
 dojox/fx/tests/test_animateClass.html              |  221 +
 dojox/fx/tests/test_complex.html                   |   87 +
 dojox/fx/tests/test_crossFade.html                 |  145 +
 dojox/fx/tests/test_easing.html                    |  130 +
 dojox/fx/tests/test_flip.html                      |  531 +
 dojox/fx/tests/test_highlight.html                 |   45 +
 dojox/fx/tests/test_reverse.html                   |  100 +
 dojox/fx/tests/test_scroll.html                    |   98 +
 dojox/fx/tests/test_sizeTo.html                    |  171 +
 dojox/fx/tests/test_slideBy.html                   |   75 +
 dojox/fx/tests/test_split.html                     |  443 +
 dojox/fx/tests/test_text.html                      |  373 +
 dojox/fx/tests/test_transform.html                 |  210 +
 dojox/fx/tests/test_wipeTo.html                    |  109 +
 dojox/fx/text.js                                   |  697 +-
 dojox/geo/README                                   |   37 +
 dojox/geo/charting/Map.js                          |  140 +
 dojox/geo/charting/_Feature.js                     |  169 +
 dojox/geo/charting/_Marker.js                      |   52 +
 dojox/geo/charting/_base.js                        |   53 +
 dojox/geo/charting/resources/Map.css               |   30 +
 dojox/geo/charting/resources/data/NOTICES          |   63 +
 dojox/geo/charting/resources/data/USStates.json    |  261 +
 dojox/geo/charting/resources/img/zoomin.gif        |  Bin 0 -> 287 bytes
 dojox/geo/charting/resources/img/zoomin.png        |  Bin 0 -> 573 bytes
 dojox/geo/charting/resources/img/zoomout.gif       |  Bin 0 -> 283 bytes
 dojox/geo/charting/resources/img/zoomout.png       |  Bin 0 -> 522 bytes
 dojox/geo/charting/resources/markers/USStates.json |    1 +
 dojox/geo/charting/tests/datastore/dataStore.json  |    1 +
 dojox/geo/charting/tests/test_mapWithCharting.html |   72 +
 dojox/geo/charting/tests/test_mapWithLegend.html   |   63 +
 dojox/geo/charting/tests/test_maps.html            |   37 +
 dojox/geo/charting/widget/Legend.js                |   62 +
 dojox/gfx.js                                       |  110 +-
 dojox/gfx.js.uncompressed.js                       |  945 -
 dojox/gfx/Moveable.js                              |  146 +-
 dojox/gfx/Mover.js                                 |   94 +-
 dojox/gfx/README                                   |   11 +-
 dojox/gfx/README-svgweb                            |   98 +
 dojox/gfx/VectorText.js                            | 1131 +-
 dojox/gfx/_base.js                                 |  583 +-
 dojox/gfx/arc.js                                   |  175 +-
 dojox/gfx/attach.js                                |   17 +-
 dojox/gfx/canvas.js                                | 1180 +-
 dojox/gfx/canvas_attach.js                         |   14 +-
 dojox/gfx/decompose.js                             |  233 +-
 dojox/gfx/demos/PI.html                            |   75 +
 dojox/gfx/demos/beautify.html                      |   48 +
 dojox/gfx/demos/butterfly.html                     |   87 +
 dojox/gfx/demos/career_test.html                   |  463 +
 dojox/gfx/demos/circles.html                       |   83 +
 dojox/gfx/demos/circles2.html                      |   69 +
 dojox/gfx/demos/clock.html                         |  249 +
 dojox/gfx/demos/clockWidget.html                   |  328 +
 dojox/gfx/demos/clock_black.html                   |  249 +
 dojox/gfx/demos/creator.html                       |  119 +
 dojox/gfx/demos/data/Lars.json                     | 1823 ++
 dojox/gfx/demos/data/Lars.svg                      |  532 +
 dojox/gfx/demos/data/LarsDreaming.json             | 1823 ++
 dojox/gfx/demos/data/LarsDreaming.svg              |  537 +
 dojox/gfx/demos/data/Nils.json                     |  717 +
 dojox/gfx/demos/data/Nils.svg                      |  189 +
 dojox/gfx/demos/data/buratino-bg.png               |  Bin 0 -> 27507 bytes
 dojox/gfx/demos/data/buratino-head.png             |  Bin 0 -> 30696 bytes
 dojox/gfx/demos/data/buratino-left-arm.png         |  Bin 0 -> 9631 bytes
 dojox/gfx/demos/data/buratino-left-leg.png         |  Bin 0 -> 21682 bytes
 dojox/gfx/demos/data/buratino-lollipop.png         |  Bin 0 -> 21976 bytes
 dojox/gfx/demos/data/buratino-nose-large.png       |  Bin 0 -> 4182 bytes
 dojox/gfx/demos/data/buratino-nose-medium.png      |  Bin 0 -> 2587 bytes
 dojox/gfx/demos/data/buratino-right-arm.png        |  Bin 0 -> 13033 bytes
 dojox/gfx/demos/data/buratino-right-leg.png        |  Bin 0 -> 23025 bytes
 dojox/gfx/demos/data/buratino-torso.png            |  Bin 0 -> 23405 bytes
 dojox/gfx/demos/data/buratino.jpg                  |  Bin 0 -> 33344 bytes
 dojox/gfx/demos/data/buratino.json                 |   12 +
 dojox/gfx/demos/data/transform.json                | 1567 ++
 dojox/gfx/demos/images/clock_face.jpg              |  Bin 0 -> 31088 bytes
 dojox/gfx/demos/images/clock_face_black.jpg        |  Bin 0 -> 17347 bytes
 dojox/gfx/demos/inspector.html                     |  161 +
 dojox/gfx/demos/lion.html                          |  234 +
 dojox/gfx/demos/roundedPane.html                   |  191 +
 dojox/gfx/demos/tiger.html                         |  565 +
 dojox/gfx/demos/tooltip.html                       |  234 +
 dojox/gfx/fx.js                                    |  496 +-
 dojox/gfx/gradient.js                              |  160 +
 dojox/gfx/gradutils.js                             |   91 +
 dojox/gfx/matrix.js                                |  605 +-
 dojox/gfx/move.js                                  |   11 +-
 dojox/gfx/path.js                                  |  692 +-
 dojox/gfx/resources/svg2gfx.xsl                    |   67 +-
 dojox/gfx/shape.js                                 | 1119 +-
 dojox/gfx/silverlight.js                           | 1264 +-
 dojox/gfx/silverlight_attach.js                    |  152 +-
 dojox/gfx/svg.js                                   | 1235 +-
 dojox/gfx/svg_attach.js                            |  407 +-
 dojox/gfx/tests/decompose.js                       |  110 +
 dojox/gfx/tests/images/eugene-sm.gif               |  Bin 0 -> 34644 bytes
 dojox/gfx/tests/images/eugene-sm.jpg               |  Bin 0 -> 16619 bytes
 dojox/gfx/tests/images/eugene-sm.png               |  Bin 0 -> 92113 bytes
 dojox/gfx/tests/matrix.js                          |  224 +
 dojox/gfx/tests/module.js                          |   10 +
 dojox/gfx/tests/performance/gfx_fill.html          |  199 +
 dojox/gfx/tests/performance/gfx_primitives.html    |  347 +
 dojox/gfx/tests/performance/gfx_scenes.html        | 2277 ++
 dojox/gfx/tests/performance/images/testImage.jpg   |  Bin 0 -> 3282 bytes
 dojox/gfx/tests/performance/module.js              |    8 +
 dojox/gfx/tests/performance/runTests.html          |    9 +
 dojox/gfx/tests/runTests.html                      |    9 +
 dojox/gfx/tests/svgweb/README                      |   15 +
 dojox/gfx/tests/svgweb/sample.html                 |  171 +
 dojox/gfx/tests/svgweb/svgweb/COPYING.txt          |   65 +
 dojox/gfx/tests/svgweb/svgweb/src/svg.htc          |    1 +
 dojox/gfx/tests/svgweb/svgweb/src/svg.js           |    1 +
 dojox/gfx/tests/svgweb/svgweb/src/svg.swf          |  Bin 0 -> 45561 bytes
 dojox/gfx/tests/svgweb/test.roundrect.html         |   39 +
 dojox/gfx/tests/svgweb/test_arc.html               |   66 +
 dojox/gfx/tests/svgweb/test_bezier.html            |   81 +
 dojox/gfx/tests/svgweb/test_destroy.html           |   58 +
 dojox/gfx/tests/svgweb/test_fill.html              |   45 +
 dojox/gfx/tests/svgweb/test_fx.html                |  104 +
 dojox/gfx/tests/svgweb/test_fx_shapes.html         |  123 +
 dojox/gfx/tests/svgweb/test_gfx.html               |  565 +
 dojox/gfx/tests/svgweb/test_gradient.html          |   77 +
 dojox/gfx/tests/svgweb/test_group1.html            |   70 +
 dojox/gfx/tests/svgweb/test_group2.html            |   54 +
 dojox/gfx/tests/svgweb/test_image1.html            |   80 +
 dojox/gfx/tests/svgweb/test_image2.html            |   52 +
 dojox/gfx/tests/svgweb/test_image3.html            |   77 +
 dojox/gfx/tests/svgweb/test_image4.html            |   58 +
 dojox/gfx/tests/svgweb/test_image5.html            |   67 +
 dojox/gfx/tests/svgweb/test_linearGradient.html    |   75 +
 dojox/gfx/tests/svgweb/test_linestyle.html         |   43 +
 dojox/gfx/tests/svgweb/test_pattern.html           |   43 +
 dojox/gfx/tests/svgweb/test_poly.html              |   49 +
 dojox/gfx/tests/svgweb/test_resize.html            |   57 +
 dojox/gfx/tests/svgweb/test_setPath.html           |   86 +
 dojox/gfx/tests/svgweb/test_tbbox.html             |  113 +
 dojox/gfx/tests/svgweb/test_text.html              |   80 +
 dojox/gfx/tests/svgweb/test_textpath.html          |   77 +
 dojox/gfx/tests/svgweb/test_transform.html         |   99 +
 dojox/gfx/tests/svgweb/test_utils.html             |  234 +
 dojox/gfx/tests/svgweb/test_vectortext_draw.html   |   64 +
 dojox/gfx/tests/svgweb/test_vectortext_load.html   |   97 +
 dojox/gfx/tests/test.roundrect.html                |   34 +
 dojox/gfx/tests/test_arc.html                      |   70 +
 dojox/gfx/tests/test_bezier.html                   |   81 +
 dojox/gfx/tests/test_decompose.html                |   54 +
 dojox/gfx/tests/test_destroy.html                  |   56 +
 dojox/gfx/tests/test_fill.html                     |   43 +
 dojox/gfx/tests/test_fx.html                       |  108 +
 dojox/gfx/tests/test_fx_shapes.html                |  115 +
 dojox/gfx/tests/test_gfx.html                      |  483 +
 dojox/gfx/tests/test_gradient.html                 |   66 +
 dojox/gfx/tests/test_group1.html                   |   69 +
 dojox/gfx/tests/test_group2.html                   |   50 +
 dojox/gfx/tests/test_image1.html                   |   72 +
 dojox/gfx/tests/test_image2.html                   |   55 +
 dojox/gfx/tests/test_image3.html                   |   65 +
 dojox/gfx/tests/test_image4.html                   |   53 +
 dojox/gfx/tests/test_image5.html                   |   62 +
 dojox/gfx/tests/test_linearGradient.html           |   77 +
 dojox/gfx/tests/test_linestyle.html                |   41 +
 dojox/gfx/tests/test_pattern.html                  |   41 +
 dojox/gfx/tests/test_poly.html                     |   49 +
 dojox/gfx/tests/test_refproj.html                  |  109 +
 dojox/gfx/tests/test_resize.html                   |   57 +
 dojox/gfx/tests/test_setPath.html                  |   82 +
 dojox/gfx/tests/test_tbbox.html                    |  113 +
 dojox/gfx/tests/test_text.html                     |   79 +
 dojox/gfx/tests/test_textpath.html                 |   76 +
 dojox/gfx/tests/test_transform.html                |   94 +
 dojox/gfx/tests/test_utils.html                    |  198 +
 dojox/gfx/tests/test_vectortext_draw.html          |   57 +
 dojox/gfx/tests/test_vectortext_load.html          |   79 +
 dojox/gfx/utils.js                                 |  467 +-
 dojox/gfx/vml.js                                   | 2068 +-
 dojox/gfx/vml_attach.js                            |  654 +-
 dojox/gfx3d.js                                     |   13 +-
 dojox/gfx3d/_base.js                               |   25 +-
 dojox/gfx3d/gradient.js                            |   55 +-
 dojox/gfx3d/lighting.js                            |  387 +-
 dojox/gfx3d/matrix.js                              |  487 +-
 dojox/gfx3d/object.js                              | 1669 +-
 dojox/gfx3d/scheduler.js                           |  223 +-
 dojox/gfx3d/tests/test_camerarotate.html           |   93 +
 dojox/gfx3d/tests/test_camerarotate_shaded.html    |  101 +
 dojox/gfx3d/tests/test_cube.html                   |   50 +
 dojox/gfx3d/tests/test_cylinder.html               |   66 +
 dojox/gfx3d/tests/test_drawer.html                 |   92 +
 dojox/gfx3d/tests/test_edges.html                  |   73 +
 dojox/gfx3d/tests/test_matrix.html                 |   89 +
 dojox/gfx3d/tests/test_orbit.html                  |   50 +
 dojox/gfx3d/tests/test_overlap.html                |   69 +
 dojox/gfx3d/tests/test_polygon.html                |   44 +
 dojox/gfx3d/tests/test_quads.html                  |   78 +
 dojox/gfx3d/tests/test_rotate.html                 |  123 +
 dojox/gfx3d/tests/test_scene.html                  |   66 +
 dojox/gfx3d/tests/test_triangles.html              |   82 +
 dojox/gfx3d/tests/test_vector.html                 |   59 +
 dojox/gfx3d/vector.js                              |  161 +-
 dojox/grid/DataGrid.js                             |  641 +-
 dojox/grid/DataGrid.js.uncompressed.js             |16328 -------------
 dojox/grid/DataSelection.js                        |  129 +-
 dojox/grid/EnhancedGrid.js                         |  236 +-
 dojox/grid/README                                  |   57 +
 dojox/grid/Selection.js                            |  469 +-
 dojox/grid/TreeGrid.js                             | 1642 +-
 dojox/grid/TreeSelection.js                        |  416 +-
 dojox/grid/_Builder.js                             | 1262 +-
 dojox/grid/_CheckBoxSelector.js                    |   11 +-
 dojox/grid/_EditManager.js                         |  365 +-
 dojox/grid/_Events.js                              |  715 +-
 dojox/grid/_FocusManager.js                        | 1056 +-
 dojox/grid/_Grid.js                                | 2064 +-
 dojox/grid/_Layout.js                              |  459 +-
 dojox/grid/_RadioSelector.js                       |   11 +-
 dojox/grid/_RowManager.js                          |  100 +-
 dojox/grid/_RowSelector.js                         |   96 +-
 dojox/grid/_Scroller.js                            |  894 +-
 dojox/grid/_Selector.js                            |  364 +-
 dojox/grid/_TreeView.js                            |  837 +-
 dojox/grid/_View.js                                | 1429 +-
 dojox/grid/_ViewManager.js                         |  508 +-
 dojox/grid/cells.js                                |   10 -
 dojox/grid/cells/_base.js                          |  714 +-
 dojox/grid/cells/dijit.js                          |  383 +-
 dojox/grid/cells/tree.js                           |  131 +-
 dojox/grid/enhanced/_Builder.js                    |  190 +-
 dojox/grid/enhanced/_Events.js                     |  878 +-
 dojox/grid/enhanced/_Plugin.js                     |  548 +-
 dojox/grid/enhanced/dnd/_DndBuilder.js             |   60 +-
 dojox/grid/enhanced/dnd/_DndEvents.js              |  127 +-
 dojox/grid/enhanced/dnd/_DndFocusManager.js        |  194 +-
 dojox/grid/enhanced/dnd/_DndGrid.js                |   60 +-
 dojox/grid/enhanced/dnd/_DndMover.js               |   72 +-
 dojox/grid/enhanced/dnd/_DndMovingManager.js       | 1669 +-
 dojox/grid/enhanced/dnd/_DndRowSelector.js         |   46 +-
 dojox/grid/enhanced/dnd/_DndSelectingManager.js    | 1090 +-
 dojox/grid/enhanced/nls/EnhancedGrid.js            |    9 +-
 dojox/grid/enhanced/nls/ar/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/ca/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/cs/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/nls/da/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/de/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/nls/el/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/es/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/nls/fi/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/fr/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/nls/he/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/hu/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/nls/it/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/nls/ja/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/nls/ko/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/nls/nb/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/nl/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/pl/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/nls/pt-pt/EnhancedGrid.js      |    8 +
 dojox/grid/enhanced/nls/pt/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/nls/ro/EnhancedGrid.js         |    9 +
 dojox/grid/enhanced/nls/ru/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/nls/sk/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/sl/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/sv/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/th/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/tr/EnhancedGrid.js         |    8 +
 dojox/grid/enhanced/nls/zh-tw/EnhancedGrid.js      |    9 +-
 dojox/grid/enhanced/nls/zh/EnhancedGrid.js         |    9 +-
 dojox/grid/enhanced/plugins/DnD.js                 |   19 +-
 dojox/grid/enhanced/plugins/IndirectSelection.js   |  851 +-
 dojox/grid/enhanced/plugins/Menu.js                |  197 +-
 dojox/grid/enhanced/plugins/NestedSorting.js       | 2030 +-
 dojox/grid/enhanced/resources/EnhancedGrid.css     |  108 +-
 dojox/grid/enhanced/resources/EnhancedGrid_rtl.css |   34 +-
 .../grid/enhanced/resources/claroEnhancedGrid.css  |  104 +
 .../grid/enhanced/resources/tundraEnhancedGrid.css |  771 +-
 dojox/grid/nls/DataGrid_ROOT.js                    |    1 -
 dojox/grid/nls/DataGrid_ar.js                      |    1 -
 dojox/grid/nls/DataGrid_ca.js                      |    1 -
 dojox/grid/nls/DataGrid_cs.js                      |    1 -
 dojox/grid/nls/DataGrid_da.js                      |    1 -
 dojox/grid/nls/DataGrid_de-de.js                   |    1 -
 dojox/grid/nls/DataGrid_de.js                      |    1 -
 dojox/grid/nls/DataGrid_el.js                      |    1 -
 dojox/grid/nls/DataGrid_en-gb.js                   |    1 -
 dojox/grid/nls/DataGrid_en-us.js                   |    1 -
 dojox/grid/nls/DataGrid_en.js                      |    1 -
 dojox/grid/nls/DataGrid_es-es.js                   |    1 -
 dojox/grid/nls/DataGrid_es.js                      |    1 -
 dojox/grid/nls/DataGrid_fi-fi.js                   |    1 -
 dojox/grid/nls/DataGrid_fi.js                      |    1 -
 dojox/grid/nls/DataGrid_fr-fr.js                   |    1 -
 dojox/grid/nls/DataGrid_fr.js                      |    1 -
 dojox/grid/nls/DataGrid_he-il.js                   |    1 -
 dojox/grid/nls/DataGrid_he.js                      |    1 -
 dojox/grid/nls/DataGrid_hu.js                      |    1 -
 dojox/grid/nls/DataGrid_it-it.js                   |    1 -
 dojox/grid/nls/DataGrid_it.js                      |    1 -
 dojox/grid/nls/DataGrid_ja-jp.js                   |    1 -
 dojox/grid/nls/DataGrid_ja.js                      |    1 -
 dojox/grid/nls/DataGrid_ko-kr.js                   |    1 -
 dojox/grid/nls/DataGrid_ko.js                      |    1 -
 dojox/grid/nls/DataGrid_nb.js                      |    1 -
 dojox/grid/nls/DataGrid_nl-nl.js                   |    1 -
 dojox/grid/nls/DataGrid_nl.js                      |    1 -
 dojox/grid/nls/DataGrid_pl.js                      |    1 -
 dojox/grid/nls/DataGrid_pt-br.js                   |    1 -
 dojox/grid/nls/DataGrid_pt-pt.js                   |    1 -
 dojox/grid/nls/DataGrid_pt.js                      |    1 -
 dojox/grid/nls/DataGrid_ru.js                      |    1 -
 dojox/grid/nls/DataGrid_sk.js                      |    1 -
 dojox/grid/nls/DataGrid_sl.js                      |    1 -
 dojox/grid/nls/DataGrid_sv.js                      |    1 -
 dojox/grid/nls/DataGrid_th.js                      |    1 -
 dojox/grid/nls/DataGrid_tr.js                      |    1 -
 dojox/grid/nls/DataGrid_xx.js                      |    1 -
 dojox/grid/nls/DataGrid_zh-cn.js                   |    1 -
 dojox/grid/nls/DataGrid_zh-tw.js                   |    1 -
 dojox/grid/nls/DataGrid_zh.js                      |    1 -
 dojox/grid/resources/Grid.css                      |   93 +-
 dojox/grid/resources/Grid_rtl.css                  |   13 +-
 dojox/grid/resources/_Grid.html                    |    2 +-
 dojox/grid/resources/claroGrid.css                 |  216 +
 dojox/grid/resources/images/header.png             |  Bin 0 -> 3276 bytes
 dojox/grid/resources/images/header_shadow.png      |  Bin 0 -> 197 bytes
 dojox/grid/resources/images/row_back.png           |  Bin 0 -> 3077 bytes
 dojox/grid/resources/images/td_button_down.png     |  Bin 0 -> 3105 bytes
 dojox/grid/resources/nihiloGrid.css                |  400 +-
 dojox/grid/resources/soriaGrid.css                 |  399 +-
 dojox/grid/resources/tundraGrid.css                |  403 +-
 dojox/grid/tests/databaseModel.js                  |  333 +
 .../tests/enhanced/support/music-for-demo.part.csv |  309 +
 dojox/grid/tests/enhanced/support/test_ue.js       |   29 +
 dojox/grid/tests/enhanced/test_enhanced_grid.html  |  181 +
 .../tests/enhanced/test_enhanced_grid_claro.html   |   70 +
 dojox/grid/tests/images/closed.gif                 |  Bin 0 -> 907 bytes
 dojox/grid/tests/images/flatScreen.gif             |  Bin 0 -> 824 bytes
 dojox/grid/tests/images/open.gif                   |  Bin 0 -> 907 bytes
 dojox/grid/tests/performance/_gridPerfFramework.js |  191 +
 dojox/grid/tests/performance/creation.html         |   57 +
 dojox/grid/tests/performance/dataNotification.html |  103 +
 dojox/grid/tests/performance/module.js             |   26 +
 dojox/grid/tests/performance/runTests.html         |    9 +
 dojox/grid/tests/robot/7815.html                   |   57 +
 dojox/grid/tests/robot/DataGrid_a11y.html          |  179 +
 dojox/grid/tests/robot/DataGrid_mouse.html         |  550 +
 dojox/grid/tests/robot/_DataGrid.html              |   96 +
 dojox/grid/tests/robot/module.js                   |   20 +
 dojox/grid/tests/robot/runTests.html               |    9 +
 dojox/grid/tests/robot/stores.js                   |   49 +
 dojox/grid/tests/robot/structures.js               |   40 +
 dojox/grid/tests/support/books.xml                 |  103 +
 dojox/grid/tests/support/countryStore.json         |   45 +
 dojox/grid/tests/support/data.php                  |  379 +
 dojox/grid/tests/support/gamedata.json             |  520 +
 dojox/grid/tests/support/geography.xml             |   51 +
 dojox/grid/tests/support/json.php                  |  794 +
 dojox/grid/tests/support/movies.csv                |    9 +
 dojox/grid/tests/support/numbers.json              |  104 +
 dojox/grid/tests/support/test_data.js              |   26 +
 dojox/grid/tests/support/test_data_date.js         |   27 +
 dojox/grid/tests/support/test_resize_data.json     |   34 +
 dojox/grid/tests/support/testtbl.sql               |  944 +
 dojox/grid/tests/support/yahoo_search.js           |  134 +
 dojox/grid/tests/test_backwards_compatibility.html |   86 +
 dojox/grid/tests/test_change_structure.html        |  114 +
 dojox/grid/tests/test_custom_sort.html             |   69 +
 dojox/grid/tests/test_data_grid.html               |   51 +
 dojox/grid/tests/test_data_grid_autoheight.html    |   83 +
 dojox/grid/tests/test_data_grid_autowidth.html     |   83 +
 dojox/grid/tests/test_data_grid_edit.html          |   50 +
 dojox/grid/tests/test_data_grid_edit_dijit.html    |   54 +
 .../tests/test_data_grid_edit_large_resultset.html |  102 +
 dojox/grid/tests/test_data_grid_empty.html         |   62 +
 dojox/grid/tests/test_data_grid_hideHdr.html       |   54 +
 dojox/grid/tests/test_data_grid_large.html         |   66 +
 .../tests/test_data_grid_large_flex_cells.html     |   94 +
 dojox/grid/tests/test_data_grid_multiStores.html   |  238 +
 dojox/grid/tests/test_data_grid_notification.html  |   67 +
 dojox/grid/tests/test_data_grid_page_cache.html    |   45 +
 dojox/grid/tests/test_data_grid_pctWidth.html      |   58 +
 dojox/grid/tests/test_data_grid_processError.html  |   54 +
 dojox/grid/tests/test_data_grid_relWidth.html      |  113 +
 dojox/grid/tests/test_data_grid_setStore.html      |  104 +
 dojox/grid/tests/test_edit.html                    |  115 +
 dojox/grid/tests/test_edit_canEdit.html            |  125 +
 dojox/grid/tests/test_edit_dijit.html              |  112 +
 dojox/grid/tests/test_edit_keyNav.html             |  118 +
 dojox/grid/tests/test_events.html                  |  191 +
 dojox/grid/tests/test_expand.html                  |  109 +
 dojox/grid/tests/test_grid.html                    |   58 +
 dojox/grid/tests/test_grid_autorender.html         |   61 +
 dojox/grid/tests/test_grid_colspan_resize.html     |   85 +
 dojox/grid/tests/test_grid_column_display.html     |  179 +
 dojox/grid/tests/test_grid_column_reorder.html     |   61 +
 dojox/grid/tests/test_grid_csv_export.html         |   95 +
 dojox/grid/tests/test_grid_dlg.html                |   79 +
 dojox/grid/tests/test_grid_formatters.html         |  151 +
 dojox/grid/tests/test_grid_headerHeight.html       |   80 +
 dojox/grid/tests/test_grid_hidden_rows.html        |  211 +
 dojox/grid/tests/test_grid_layout.html             |  121 +
 .../tests/test_grid_layout_LayoutContainer.html    |   93 +
 .../tests/test_grid_layout_borderContainer.html    |   78 +
 dojox/grid/tests/test_grid_messages.html           |   98 +
 .../grid/tests/test_grid_messages_autoheight.html  |   99 +
 dojox/grid/tests/test_grid_performance.html        |  122 +
 dojox/grid/tests/test_grid_programmatic.html       |   61 +
 .../grid/tests/test_grid_programmatic_layout.html  |   75 +
 .../tests/test_grid_programmatic_leak_test.html    |   73 +
 dojox/grid/tests/test_grid_rtl.html                |   57 +
 dojox/grid/tests/test_grid_selectors.html          |   85 +
 dojox/grid/tests/test_grid_simple_structure.html   |   51 +
 dojox/grid/tests/test_grid_simple_structure2.html  |   55 +
 dojox/grid/tests/test_grid_tab_container.html      |  142 +
 dojox/grid/tests/test_grid_themes.html             |  126 +
 dojox/grid/tests/test_grid_tooltip_menu.html       |  169 +
 dojox/grid/tests/test_keyboard.html                |   84 +
 dojox/grid/tests/test_markup.html                  |   96 +
 dojox/grid/tests/test_mysql_edit.html              |  145 +
 dojox/grid/tests/test_selection.html               |   70 +
 dojox/grid/tests/test_sizing.html                  |  142 +
 dojox/grid/tests/test_sizing_100rows.html          |  148 +
 dojox/grid/tests/test_sizing_ResizeHandle.html     |  108 +
 dojox/grid/tests/test_styling.html                 |  127 +
 dojox/grid/tests/test_subgrid.html                 |  195 +
 dojox/grid/tests/test_treegrid.html                |  250 +
 dojox/grid/tests/test_treegrid_loading.html        |  151 +
 dojox/grid/tests/test_treegrid_model.html          |  207 +
 dojox/grid/tests/test_treegrid_model_lazy.html     |  107 +
 dojox/grid/tests/test_treegrid_performance.html    |  205 +
 dojox/grid/tests/test_tundra_edit.html             |  119 +
 dojox/grid/tests/test_yahoo_images.html            |   84 +
 dojox/grid/tests/test_yahoo_search.html            |  131 +
 dojox/grid/tests/yahooSearch.js                    |   76 +
 dojox/grid/util.js                                 |  128 +-
 dojox/help/_base.js                                |  847 +-
 dojox/help/console.js                              |  148 +-
 dojox/help/demos/demo_Console.html                 |   32 +
 dojox/highlight.js                                 |   12 +-
 dojox/highlight/_base.js                           |  783 +-
 dojox/highlight/languages/_all.js                  |   13 +-
 dojox/highlight/languages/_dynamic.js              |   17 +-
 dojox/highlight/languages/_static.js               |   15 +-
 dojox/highlight/languages/_www.js                  |   14 +-
 dojox/highlight/languages/cpp.js                   |   57 +-
 dojox/highlight/languages/css.js                   |   99 +-
 dojox/highlight/languages/delphi.js                |  130 +-
 dojox/highlight/languages/django.js                |  101 +-
 dojox/highlight/languages/groovy.js                |   67 +
 dojox/highlight/languages/html.js                  |   77 +-
 dojox/highlight/languages/java.js                  |   58 +
 dojox/highlight/languages/javascript.js            |   59 +-
 dojox/highlight/languages/pygments/_html.js        |   29 +-
 dojox/highlight/languages/pygments/_www.js         |   15 +-
 dojox/highlight/languages/pygments/css.js          |  214 +-
 dojox/highlight/languages/pygments/html.js         |  108 +-
 dojox/highlight/languages/pygments/javascript.js   |  156 +-
 dojox/highlight/languages/pygments/xml.js          |   85 +-
 dojox/highlight/languages/python.js                |  106 +-
 dojox/highlight/languages/sql.js                   |  106 +-
 dojox/highlight/languages/xml.js                   |   76 +-
 dojox/highlight/languages/xquery.js                |   56 +
 dojox/highlight/resources/highlight.css            |    7 +
 dojox/highlight/resources/pygments/autumn.css      |    6 +
 dojox/highlight/resources/pygments/borland.css     |    6 +
 dojox/highlight/resources/pygments/colorful.css    |    6 +
 dojox/highlight/resources/pygments/default.css     |    7 +
 dojox/highlight/resources/pygments/emacs.css       |    7 +
 dojox/highlight/resources/pygments/friendly.css    |    7 +
 dojox/highlight/resources/pygments/fruity.css      |    6 +
 dojox/highlight/resources/pygments/manni.css       |    7 +
 dojox/highlight/resources/pygments/murphy.css      |    6 +
 dojox/highlight/resources/pygments/native.css      |    7 +
 dojox/highlight/resources/pygments/pastie.css      |    6 +
 dojox/highlight/resources/pygments/perldoc.css     |    7 +
 dojox/highlight/resources/pygments/trac.css        |    6 +
 dojox/highlight/tests/highlight.js                 |   26 +
 dojox/highlight/tests/module.js                    |    9 +
 dojox/highlight/tests/runTests.html                |   11 +
 dojox/highlight/tests/test_highlight.html          |  467 +
 dojox/highlight/tests/test_pygments.html           |  146 +
 dojox/html.js                                      |   12 +-
 dojox/html/_base.js                                |  557 +-
 dojox/html/ellipsis.js                             |  350 +-
 dojox/html/entities.js                             |  282 +-
 dojox/html/ext-dojo/style.js                       |  460 +
 dojox/html/format.js                               |  809 +-
 dojox/html/metrics.js                              |  311 +-
 dojox/html/resources/ellipsis.css                  |    1 +
 dojox/html/styles.js                               |  527 +-
 dojox/html/tests/entities.js                       |   97 +
 dojox/html/tests/format.js                         |  354 +
 dojox/html/tests/formatted.html                    |   30 +
 dojox/html/tests/images/blank.gif                  |  Bin 0 -> 43 bytes
 dojox/html/tests/images/dojoLogo.png               |  Bin 0 -> 14712 bytes
 dojox/html/tests/images/testImage.gif              |  Bin 0 -> 14171 bytes
 dojox/html/tests/module.js                         |    8 +
 dojox/html/tests/performance/format.js             |   63 +
 dojox/html/tests/performance/largedoc.txt          |  665 +
 dojox/html/tests/performance/module.js             |    6 +
 dojox/html/tests/performance/runTests.html         |    9 +
 dojox/html/tests/performance/smalldoc.txt          |   77 +
 dojox/html/tests/remote/commentedScript.html       |   22 +
 dojox/html/tests/remote/getResponse.php            |   95 +
 dojox/html/tests/runTests.html                     |    9 +
 dojox/html/tests/test_ellipsis.html                |  431 +
 dojox/html/tests/test_metrics.html                 |   60 +
 dojox/html/tests/test_set.html                     | 1043 +
 dojox/html/tests/test_style-html.html              |  310 +
 dojox/html/tests/test_styles.html                  |  167 +
 dojox/html/tests/test_themes.html                  |  121 +
 dojox/html/tests/unformatted.html                  |   25 +
 dojox/image.js                                     |   10 -
 dojox/image/Badge.js                               |  316 +-
 dojox/image/FlickrBadge.js                         |  157 +-
 dojox/image/Gallery.js                             |  239 +-
 dojox/image/Lightbox.js                            |  816 +-
 dojox/image/LightboxNano.js                        |  427 +-
 dojox/image/Magnifier.js                           |   96 +-
 dojox/image/MagnifierLite.js                       |  170 +-
 dojox/image/SlideShow.js                           | 1031 +-
 dojox/image/ThumbnailPicker.js                     |  884 +-
 dojox/image/_base.js                               |  137 +-
 dojox/image/resources/Badge.css                    |    7 +
 dojox/image/resources/Gallery.css                  |    1 +
 dojox/image/resources/Lightbox.css                 |   31 +-
 dojox/image/resources/Lightbox.html                |    6 +-
 dojox/image/resources/SlideShow.css                |   12 +-
 dojox/image/resources/ThumbnailPicker.css          |   26 +-
 dojox/image/resources/image.css                    |  342 +-
 dojox/image/resources/images/close.gif             |  Bin 936 -> 936 bytes
 dojox/image/resources/images/close.png             |  Bin 675 -> 675 bytes
 dojox/image/resources/images/close_dark.png        |  Bin 711 -> 711 bytes
 dojox/image/resources/images/left.gif              |  Bin 921 -> 921 bytes
 dojox/image/resources/images/left.png              |  Bin 626 -> 626 bytes
 dojox/image/resources/images/loading.gif           |  Bin 4178 -> 4178 bytes
 dojox/image/resources/images/right.gif             |  Bin 920 -> 920 bytes
 dojox/image/resources/images/right.png             |  Bin 621 -> 621 bytes
 dojox/image/tests/Lightbox.html                    |  184 +
 dojox/image/tests/images.json                      |   32 +
 dojox/image/tests/images/chris1_lg.jpg             |  Bin 0 -> 168094 bytes
 dojox/image/tests/images/chris1_sm.jpg             |  Bin 0 -> 25601 bytes
 dojox/image/tests/images/chris2_lg.jpg             |  Bin 0 -> 198747 bytes
 dojox/image/tests/images/chris2_sm.jpg             |  Bin 0 -> 30404 bytes
 dojox/image/tests/images/chris3_lg.jpg             |  Bin 0 -> 141577 bytes
 dojox/image/tests/images/chris3_sm.jpg             |  Bin 0 -> 19205 bytes
 dojox/image/tests/images/enlarge.png               |  Bin 0 -> 572 bytes
 dojox/image/tests/images/extraWide.jpg             |  Bin 0 -> 49250 bytes
 dojox/image/tests/images/huuuge.png                |  Bin 0 -> 37958 bytes
 dojox/image/tests/images/imageHoriz.jpg            |  Bin 0 -> 47693 bytes
 dojox/image/tests/images/imageHoriz2.jpg           |  Bin 0 -> 77176 bytes
 dojox/image/tests/images/imageVert.jpg             |  Bin 0 -> 71533 bytes
 dojox/image/tests/images/loading-dark.gif          |  Bin 0 -> 2545 bytes
 dojox/image/tests/images/spanke.jpg                |  Bin 0 -> 302741 bytes
 dojox/image/tests/images/square.jpg                |  Bin 0 -> 93704 bytes
 dojox/image/tests/module.js                        |   13 +
 dojox/image/tests/onloads.html                     |  317 +
 dojox/image/tests/runTests.html                    |    9 +
 dojox/image/tests/test_Badge.html                  |  234 +
 dojox/image/tests/test_FlickrBadge.html            |   70 +
 dojox/image/tests/test_Gallery.html                |   76 +
 dojox/image/tests/test_Gallery_GoogleData.html     |   84 +
 .../image/tests/test_Gallery_in_TabContainer.html  |   85 +
 dojox/image/tests/test_Lightbox.html               |  249 +
 dojox/image/tests/test_LightboxNano.html           |  166 +
 dojox/image/tests/test_Magnifier.html              |   98 +
 dojox/image/tests/test_MagnifierLite.html          |   92 +
 dojox/image/tests/test_SlideShow.html              |   76 +
 dojox/image/tests/test_SlideShow_GoogleData.html   |   51 +
 dojox/image/tests/test_ThumbnailPicker.html        |  172 +
 .../image/tests/test_ThumbnailPickerLightbox.html  |   97 +
 dojox/image/tests/test_base.html                   |   80 +
 dojox/io/OAuth.js                                  |  463 +-
 dojox/io/httpParse.js                              |  139 +-
 dojox/io/proxy/tests/frag.xml                      |    4 +
 dojox/io/proxy/tests/xip.html                      |   62 +
 dojox/io/proxy/xip.js                              |  687 +-
 dojox/io/proxy/xip_client.html                     |    2 +-
 dojox/io/proxy/xip_server.html                     |    2 +-
 dojox/io/scriptFrame.js                            |  127 +-
 dojox/io/tests/attackerFrame.html                  |   34 +
 dojox/io/tests/crossSite.php                       |   12 +
 dojox/io/tests/result.txt                          |    1 +
 dojox/io/tests/scriptFrame.html                    |   91 +
 dojox/io/tests/scriptFrame.js                      |    5 +
 dojox/io/tests/scriptFrameRepeat.html              |   44 +
 dojox/io/tests/windowName.html                     |   59 +
 dojox/io/tests/windowName.js                       |   59 +
 dojox/io/tests/xhrMultiPart.html                   |   82 +
 dojox/io/tests/xhrPlugins.js                       |   58 +
 dojox/io/windowName.js                             |  370 +-
 dojox/io/xhrMultiPart.js                           |  215 +-
 dojox/io/xhrPlugins.js                             |  281 +-
 dojox/io/xhrScriptPlugin.js                        |   54 +-
 dojox/io/xhrWindowNamePlugin.js                    |   87 +-
 dojox/jq.js                                        | 3207 ++-
 dojox/json/query.js                                |  398 +-
 dojox/json/ref.js                                  |  599 +-
 dojox/json/schema.js                               |  394 +-
 dojox/json/tests/module.js                         |   10 +
 dojox/json/tests/query.js                          |  367 +
 dojox/json/tests/ref.js                            |   69 +
 dojox/json/tests/runTests.html                     |    9 +
 dojox/json/tests/schema.js                         |  276 +
 dojox/jsonPath.js                                  |   10 -
 dojox/jsonPath/query.js                            |  359 +-
 dojox/jsonPath/tests/jsonPath.js                   |  206 +
 dojox/jsonPath/tests/module.js                     |    8 +
 dojox/jsonPath/tests/runTests.html                 |    9 +
 dojox/lang/README                                  |   15 +-
 dojox/lang/aspect.js                               |  569 +-
 dojox/lang/aspect/cflow.js                         |   80 +-
 dojox/lang/aspect/counter.js                       |   50 +-
 dojox/lang/aspect/memoizer.js                      |   88 +-
 dojox/lang/aspect/memoizerGuard.js                 |   64 +-
 dojox/lang/aspect/profiler.js                      |   58 +-
 dojox/lang/aspect/timer.js                         |   57 +-
 dojox/lang/aspect/tracer.js                        |   74 +-
 dojox/lang/async.js                                |  199 +
 dojox/lang/async/event.js                          |   41 +
 dojox/lang/async/timeout.js                        |   41 +
 dojox/lang/async/topic.js                          |   41 +
 dojox/lang/docs.js                                 |  400 +-
 dojox/lang/functional.js                           |   11 +-
 dojox/lang/functional/array.js                     |  317 +-
 dojox/lang/functional/binrec.js                    |  223 +-
 dojox/lang/functional/curry.js                     |  149 +-
 dojox/lang/functional/fold.js                      |  216 +-
 dojox/lang/functional/lambda.js                    |  211 +-
 dojox/lang/functional/linrec.js                    |  193 +-
 dojox/lang/functional/listcomp.js                  |   75 +-
 dojox/lang/functional/multirec.js                  |  214 +-
 dojox/lang/functional/numrec.js                    |  112 +-
 dojox/lang/functional/object.js                    |  130 +-
 dojox/lang/functional/reversed.js                  |  139 +-
 dojox/lang/functional/scan.js                      |  196 +-
 dojox/lang/functional/sequence.js                  |   61 +-
 dojox/lang/functional/tailrec.js                   |  156 +-
 dojox/lang/functional/util.js                      |   71 +-
 dojox/lang/functional/zip.js                       |   60 +-
 dojox/lang/observable.js                           |  400 +-
 dojox/lang/oo/Decorator.js                         |   54 +-
 dojox/lang/oo/Filter.js                            |   65 +-
 dojox/lang/oo/aop.js                               |  118 +-
 dojox/lang/oo/general.js                           |  101 +-
 dojox/lang/oo/mixin.js                             |  205 +-
 dojox/lang/oo/rearrange.js                         |  107 +-
 dojox/lang/tests/array.js                          |   82 +
 dojox/lang/tests/async.js                          |  216 +
 dojox/lang/tests/bench_decl.html                   |  480 +
 dojox/lang/tests/curry.js                          |   27 +
 dojox/lang/tests/declare-old.js                    |  244 +
 dojox/lang/tests/docs.js                           |   29 +
 dojox/lang/tests/fold.js                           |   84 +
 dojox/lang/tests/fun_perf.html                     |  178 +
 dojox/lang/tests/lambda.js                         |   20 +
 dojox/lang/tests/listcomp.js                       |   24 +
 dojox/lang/tests/main.js                           |   19 +
 dojox/lang/tests/misc.js                           |   21 +
 dojox/lang/tests/object.js                         |   18 +
 dojox/lang/tests/observable.js                     |  126 +
 dojox/lang/tests/oo_mixin.js                       |   26 +
 dojox/lang/tests/rec_perf.html                     |  484 +
 dojox/lang/tests/recomb.js                         |   92 +
 dojox/lang/tests/runTests.html                     |    9 +
 dojox/lang/tests/test_aspect.html                  |  478 +
 dojox/lang/tests/test_oo_decl.html                 |  492 +
 dojox/lang/tests/test_oo_mixin.html                |  162 +
 dojox/lang/tests/typed.js                          |  144 +
 dojox/lang/typed.js                                |  290 +-
 dojox/lang/utils.js                                |  156 +-
 dojox/layout/BorderContainer.js                    |   13 +-
 dojox/layout/ContentPane.js                        |  133 +-
 dojox/layout/DragPane.js                           |   93 +-
 dojox/layout/ExpandoPane.js                        |  399 +-
 dojox/layout/FloatingPane.js                       |  616 +-
 dojox/layout/GridContainer.js                      | 1443 +-
 dojox/layout/GridContainerLite.js                  |  811 +
 dojox/layout/README                                |    2 +-
 dojox/layout/RadioGroup.js                         |  424 +-
 dojox/layout/ResizeHandle.js                       |  533 +-
 dojox/layout/RotatorContainer.js                   |  623 +-
 dojox/layout/ScrollPane.js                         |  221 +-
 dojox/layout/TableContainer.js                     |  405 +-
 dojox/layout/ToggleSplitter.js                     |  386 +-
 dojox/layout/dnd/Avatar.js                         |   69 +-
 dojox/layout/dnd/PlottedDnd.js                     |  902 +-
 .../ext-dijit/layout/StackContainer-touch.js       |   83 +-
 dojox/layout/resources/DndGridContainer.css        |    7 +-
 dojox/layout/resources/ExpandoPane.css             |   74 +-
 dojox/layout/resources/ExpandoPane.html            |    4 +-
 dojox/layout/resources/FloatingPane.css            |   34 +-
 dojox/layout/resources/GridContainer.css           |  112 +-
 dojox/layout/resources/GridContainer.html          |   14 +-
 dojox/layout/resources/RadioGroup.css              |    9 +-
 dojox/layout/resources/ResizeHandle.css            |   24 +
 dojox/layout/resources/RotatorContainer.css        |    6 +
 dojox/layout/resources/ScrollPane.css              |    3 +
 dojox/layout/resources/ToggleSplitter.css          |    7 +
 .../layout/resources/icons/gridcontainer_grip.gif  |  Bin 0 -> 80 bytes
 dojox/layout/resources/icons/grip_bg.gif           |  Bin 46 -> 46 bytes
 dojox/layout/resources/icons/pixel.gif             |  Bin 64 -> 64 bytes
 dojox/layout/resources/icons/resize.png            |  Bin 319 -> 319 bytes
 dojox/layout/resources/icons/resizeRtl.png         |  Bin 0 -> 269 bytes
 dojox/layout/resources/icons/rotator.png           |  Bin 1895 -> 1895 bytes
 dojox/layout/tests/ContentPane.html                | 1050 +
 dojox/layout/tests/_bottomPane.html                |   53 +
 dojox/layout/tests/_expando.css                    |   64 +
 dojox/layout/tests/_floating.html                  |   48 +
 dojox/layout/tests/_lorem.html                     |   11 +
 dojox/layout/tests/_script.html                    |    9 +
 dojox/layout/tests/doc0.html                       |   14 +
 dojox/layout/tests/images/blank.gif                |  Bin 0 -> 43 bytes
 dojox/layout/tests/images/dojoLogo.png             |  Bin 0 -> 14712 bytes
 dojox/layout/tests/images/gridUnderlay.png         |  Bin 0 -> 915 bytes
 dojox/layout/tests/images/testImage.gif            |  Bin 0 -> 14171 bytes
 dojox/layout/tests/remote/getResponse.php          |  108 +
 dojox/layout/tests/resources/script_dnd.js         |  158 +
 dojox/layout/tests/resources/set_complete_dnd.css  |   61 +
 dojox/layout/tests/test_DragPane.html              |  202 +
 dojox/layout/tests/test_ExpandoPane.html           |  327 +
 dojox/layout/tests/test_ExpandoPane_code.html      |  108 +
 dojox/layout/tests/test_ExpandoPane_more.html      |  149 +
 dojox/layout/tests/test_ExpandoPane_prog.html      |  105 +
 dojox/layout/tests/test_ExpandoPane_splitters.html |   52 +
 dojox/layout/tests/test_FloatingPane.html          |  186 +
 dojox/layout/tests/test_GridContainer.html         |   97 +
 .../layout/tests/test_GridContainerColWidths.html  |  164 +
 dojox/layout/tests/test_GridContainerLite.html     |  122 +
 .../tests/test_GridContainerLite_doLayout.html     |  112 +
 .../test_GridContainerLite_dragRestriction.html    |  148 +
 .../tests/test_GridContainer_ResizableCol.html     |   93 +
 .../tests/test_GridContainer_TitlePanes.html       |   85 +
 .../test_GridContainer_complete_solution.html      |  103 +
 .../tests/test_GridContainer_dragHandle.html       |  107 +
 .../test_GridContainer_in_BorderContainer.html     |  150 +
 ...test_GridContainer_in_BorderContainer_prog.html |  231 +
 dojox/layout/tests/test_RadioGroup.html            |  150 +
 dojox/layout/tests/test_ResizeHandle.html          |  196 +
 dojox/layout/tests/test_RotatorContainer.html      |   98 +
 dojox/layout/tests/test_ScrollPane.html            |  194 +
 dojox/layout/tests/test_ScrollPaneSingle.html      |   79 +
 dojox/layout/tests/test_TableContainer.html        |  321 +
 dojox/layout/tests/test_ToggleSplitter.html        |  132 +
 dojox/layout/tests/test_TouchStackContainer.html   |   69 +
 dojox/math.js                                      |   10 -
 dojox/math/BigInteger-ext.js                       | 1444 +-
 dojox/math/BigInteger.js                           | 1213 +-
 dojox/math/LICENSE-BigInteger                      |   40 -
 dojox/math/README                                  |    3 -
 dojox/math/_base.js                                |  239 +-
 dojox/math/curves.js                               |  381 +-
 dojox/math/matrix.js                               |  539 +-
 dojox/math/random/Secure.js                        |  144 +-
 dojox/math/random/Simple.js                        |   36 +-
 dojox/math/random/prng4.js                         |   92 +-
 dojox/math/round.js                                |   83 +-
 dojox/math/stats.js                                |  292 +-
 dojox/math/tests/BigInteger.js                     |   14 +
 dojox/math/tests/main.js                           |   12 +
 dojox/math/tests/math.js                           |   29 +
 dojox/math/tests/random.js                         |   24 +
 dojox/math/tests/round.js                          |  142 +
 dojox/math/tests/runTests.html                     |    9 +
 dojox/math/tests/stats.js                          |  102 +
 dojox/mdnd/AreaManager.js                          |  707 +
 dojox/mdnd/AutoScroll.js                           |  195 +
 dojox/mdnd/DropIndicator.js                        |   86 +
 dojox/mdnd/LazyManager.js                          |   68 +
 dojox/mdnd/Moveable.js                             |  251 +
 dojox/mdnd/PureSource.js                           |  208 +
 dojox/mdnd/README                                  |   94 +
 dojox/mdnd/adapter/DndFromDojo.js                  |  366 +
 dojox/mdnd/adapter/DndToDojo.js                    |  484 +
 dojox/mdnd/dropMode/DefaultDropMode.js             |  333 +
 dojox/mdnd/dropMode/OverDropMode.js                |  308 +
 dojox/mdnd/dropMode/VerticalDropMode.js            |  343 +
 dojox/mdnd/resources/dnd.css                       |   93 +
 .../tests/functionalTests/test_dnd_acceptance.html |   71 +
 .../tests/functionalTests/test_dnd_autoScroll.html |   52 +
 .../functionalTests/test_dnd_defaultDropMode.html  |   55 +
 .../functionalTests/test_dnd_dndFromDojo.html      |   73 +
 .../tests/functionalTests/test_dnd_dndToDojo.html  |   93 +
 .../test_dnd_dndToDojo_dndFromDojo.html            |   70 +
 .../functionalTests/test_dnd_overDropMode.html     |   57 +
 .../tests/functionalTests/test_dnd_stress.html     |   83 +
 .../functionalTests/test_dnd_verticalDropMode.html |   55 +
 dojox/mdnd/tests/module.js                         |   16 +
 dojox/mdnd/tests/resources/test_dnd.css            |   68 +
 dojox/mdnd/tests/robot/module.js                   |   16 +
 dojox/mdnd/tests/robot/test_dnd_acceptance.html    |  284 +
 .../mdnd/tests/robot/test_dnd_defaultDropMode.html |  101 +
 dojox/mdnd/tests/robot/test_dnd_dndFromDojo.html   |  322 +
 dojox/mdnd/tests/robot/test_dnd_dndToDojo.html     |  198 +
 dojox/mdnd/tests/robot/test_dnd_overDropMode.html  |  272 +
 .../tests/robot/test_dnd_verticalDropMode.html     |  101 +
 dojox/mdnd/tests/runTests.html                     |    9 +
 .../areaManager/AreaManagerCoverPresence.html      |  110 +
 .../areaManager/AreaManagerManagingDragItems.html  |  149 +
 .../areaManager/AreaManagerRegistering.html        |  124 +
 dojox/mdnd/tests/unitTests/areaManager/module.js   |   12 +
 .../unitTests/dropIndicator/DropIndicatorTest.html |  187 +
 dojox/mdnd/tests/unitTests/dropIndicator/module.js |    8 +
 .../unitTests/dropMode/DefaultDropModeTest.html    |  241 +
 dojox/mdnd/tests/unitTests/dropMode/FixtureLib.js  |   87 +
 .../tests/unitTests/dropMode/OverDropModeTest.html |  195 +
 .../unitTests/dropMode/VerticalDropModeTest.html   |  241 +
 dojox/mdnd/tests/unitTests/dropMode/module.js      |   10 +
 .../unitTests/dropMode/resources/domElement.html   |  130 +
 dojox/mdnd/tests/unitTests/module.js               |    9 +
 dojox/mobile.js                                    |    4 +
 dojox/mobile/README                                |   55 +
 dojox/mobile/_base.js                              | 1451 ++
 dojox/mobile/app.js                                |    3 +
 dojox/mobile/app/AlertDialog.js                    |  182 +
 dojox/mobile/app/ImageThumbView.js                 |  254 +
 dojox/mobile/app/ImageView.js                      |  716 +
 dojox/mobile/app/List.js                           |  577 +
 dojox/mobile/app/ListSelector.js                   |  218 +
 dojox/mobile/app/SceneAssistant.js                 |   56 +
 dojox/mobile/app/SceneController.js                |  157 +
 dojox/mobile/app/StageController.js                |  137 +
 dojox/mobile/app/TextBox.js                        |  321 +
 dojox/mobile/app/_FormWidget.js                    |  294 +
 dojox/mobile/app/_Widget.js                        |   30 +
 dojox/mobile/app/_base.js                          |  226 +
 dojox/mobile/app/_event.js                         |  119 +
 dojox/mobile/app/compat.js                         |  109 +
 dojox/mobile/build/build.bat                       |   47 +
 dojox/mobile/build/build.sh                        |   50 +
 dojox/mobile/build/profiles/mobile-all.profile.js  |   36 +
 dojox/mobile/build/profiles/mobile.profile.js      |   40 +
 dojox/mobile/compat.js                             |  399 +
 dojox/mobile/parser.js                             |   80 +
 .../app/assistants/main-assistant.js               |  123 +
 .../app/views/main/emptyTemplate.html              |    3 +
 .../complexListApp/app/views/main/main-scene.html  |   23 +
 .../complexListApp/app/views/main/rowTemplate.html |   15 +
 .../tests/complexListApp/images/i-icon-1.png       |  Bin 0 -> 677 bytes
 .../tests/complexListApp/images/i-icon-2.png       |  Bin 0 -> 680 bytes
 .../tests/complexListApp/images/i-icon-3.png       |  Bin 0 -> 682 bytes
 .../tests/complexListApp/images/i-icon-4.png       |  Bin 0 -> 697 bytes
 dojox/mobile/tests/complexListApp/index.html       |   37 +
 dojox/mobile/tests/complexListApp/styles/style.css |   38 +
 .../dialogApp/app/assistants/main-assistant.js     |   75 +
 .../tests/dialogApp/app/views/main/main-scene.html |   10 +
 dojox/mobile/tests/dialogApp/index.html            |   37 +
 .../flickr-image-thumb-view-assistant.js           |  198 +
 .../app/assistants/flickr-image-view-assistant.js  |  170 +
 .../assistants/flickr-search-group-assistant.js    |  123 +
 .../flickr-search-selection-assistant.js           |   54 +
 .../app/assistants/flickr-search-text-assistant.js |  119 +
 .../app/assistants/image-view-assistant.js         |   92 +
 .../app/assistants/main-assistant.js               |   40 +
 .../flickr-image-thumb-view-scene.html             |   17 +
 .../flickr-image-view/flickr-image-view-scene.html |   10 +
 .../views/flickr-search-group/emptyTemplate.html   |    3 +
 .../flickr-search-group-scene.html                 |   19 +
 .../app/views/flickr-search-group/rowTemplate.html |    8 +
 .../flickr-search-selection-scene.html             |    7 +
 .../views/flickr-search-selection/rowTemplate.html |    8 +
 .../views/flickr-search-text/emptyTemplate.html    |    3 +
 .../flickr-search-group-scene.html                 |   19 +
 .../app/views/flickr-search-text/rowTemplate.html  |   15 +
 .../app/views/image-view/image-view-scene.html     |   23 +
 .../app/views/main/main-scene.html                 |    6 +
 .../app/views/main/rowTemplate.html                |    8 +
 .../tests/imageControlsApp/images/chris1_lg.jpg    |  Bin 0 -> 168094 bytes
 .../tests/imageControlsApp/images/chris2_lg.jpg    |  Bin 0 -> 198747 bytes
 .../tests/imageControlsApp/images/imageHoriz.jpg   |  Bin 0 -> 47693 bytes
 .../tests/imageControlsApp/images/imageVert.jpg    |  Bin 0 -> 71533 bytes
 .../tests/imageControlsApp/images/square.jpg       |  Bin 0 -> 93704 bytes
 dojox/mobile/tests/imageControlsApp/index.html     |   39 +
 .../tests/imageControlsApp/styles/styles.css       |   13 +
 .../tests/imageControlsApp/view-resources.json     |   14 +
 dojox/mobile/tests/images/a-icon-1-41x41.png       |  Bin 0 -> 3886 bytes
 dojox/mobile/tests/images/a-icon-1.png             |  Bin 0 -> 550 bytes
 dojox/mobile/tests/images/a-icon-10.png            |  Bin 0 -> 332 bytes
 dojox/mobile/tests/images/a-icon-11.png            |  Bin 0 -> 343 bytes
 dojox/mobile/tests/images/a-icon-12.png            |  Bin 0 -> 613 bytes
 dojox/mobile/tests/images/a-icon-13.png            |  Bin 0 -> 278 bytes
 dojox/mobile/tests/images/a-icon-14.png            |  Bin 0 -> 612 bytes
 dojox/mobile/tests/images/a-icon-15.png            |  Bin 0 -> 765 bytes
 dojox/mobile/tests/images/a-icon-16.png            |  Bin 0 -> 597 bytes
 dojox/mobile/tests/images/a-icon-17.png            |  Bin 0 -> 942 bytes
 dojox/mobile/tests/images/a-icon-18.png            |  Bin 0 -> 832 bytes
 dojox/mobile/tests/images/a-icon-2-41x41.png       |  Bin 0 -> 923 bytes
 dojox/mobile/tests/images/a-icon-2.png             |  Bin 0 -> 644 bytes
 dojox/mobile/tests/images/a-icon-3.png             |  Bin 0 -> 1346 bytes
 dojox/mobile/tests/images/a-icon-4.png             |  Bin 0 -> 695 bytes
 dojox/mobile/tests/images/i-icon-1.png             |  Bin 0 -> 677 bytes
 dojox/mobile/tests/images/i-icon-10.png            |  Bin 0 -> 689 bytes
 dojox/mobile/tests/images/i-icon-2.png             |  Bin 0 -> 680 bytes
 dojox/mobile/tests/images/i-icon-3.png             |  Bin 0 -> 682 bytes
 dojox/mobile/tests/images/i-icon-4.png             |  Bin 0 -> 697 bytes
 dojox/mobile/tests/images/i-icon-5.png             |  Bin 0 -> 693 bytes
 dojox/mobile/tests/images/i-icon-6.png             |  Bin 0 -> 694 bytes
 dojox/mobile/tests/images/i-icon-7.png             |  Bin 0 -> 691 bytes
 dojox/mobile/tests/images/i-icon-8.png             |  Bin 0 -> 695 bytes
 dojox/mobile/tests/images/i-icon-9.png             |  Bin 0 -> 689 bytes
 dojox/mobile/tests/images/i-icon-all.png           |  Bin 0 -> 4450 bytes
 dojox/mobile/tests/images/icon-1.png               |  Bin 0 -> 2626 bytes
 dojox/mobile/tests/images/not-images.png           |  Bin 0 -> 18459 bytes
 dojox/mobile/tests/images/red-button-bg.png        |  Bin 0 -> 178 bytes
 dojox/mobile/tests/images/red-button-sel-bg.png    |  Bin 0 -> 185 bytes
 dojox/mobile/tests/images/widget-bg.png            |  Bin 0 -> 26234 bytes
 dojox/mobile/tests/index.html                      |   55 +
 .../app/assistants/text-input-assistant.js         |   21 +
 .../app/views/text-input/text-input-scene.html     |   50 +
 dojox/mobile/tests/inputApp/index.html             |   37 +
 .../multiSceneApp/app/assistants/main-assistant.js |   41 +
 .../app/assistants/second-assistant.js             |   32 +
 .../app/assistants/third-assistant.js              |   33 +
 .../multiSceneApp/app/views/main/main-scene.html   |   16 +
 .../app/views/second/second-scene.html             |   12 +
 .../multiSceneApp/app/views/third/third-scene.html |   13 +
 dojox/mobile/tests/multiSceneApp/index.html        |   37 +
 .../simpleApp/app/assistants/main-assistant.js     |   23 +
 .../tests/simpleApp/app/views/main/main-scene.html |    3 +
 dojox/mobile/tests/simpleApp/index.html            |   36 +
 .../simpleListApp/app/assistants/main-assistant.js |   66 +
 .../simpleListApp/app/views/main/main-scene.html   |   14 +
 .../simpleListApp/app/views/main/rowTemplate.html  |    3 +
 dojox/mobile/tests/simpleListApp/index.html        |   36 +
 dojox/mobile/tests/test_Android-ButtonList.html    |   68 +
 dojox/mobile/tests/test_Android-EdgeToEdge.html    |   50 +
 .../tests/test_Android-EdgeToEdgeCategory.html     |   46 +
 dojox/mobile/tests/test_Android-Icon.html          |   58 +
 dojox/mobile/tests/test_Android-RoundRectList.html |   60 +
 dojox/mobile/tests/test_Android-Settings.html      |  104 +
 dojox/mobile/tests/test_Android-Switch.html        |   23 +
 dojox/mobile/tests/test_Android-TabContainer.html  |  139 +
 .../tests/test_Android-VariableHeightList.html     |  100 +
 dojox/mobile/tests/test_ajax-html.html             |   34 +
 dojox/mobile/tests/test_ajax-json.html             |   34 +
 dojox/mobile/tests/test_anchor-label.html          |   74 +
 dojox/mobile/tests/test_bookmarkable.html          |  112 +
 dojox/mobile/tests/test_buttons.html               |   21 +
 dojox/mobile/tests/test_dynamic-icons.html         |   53 +
 dojox/mobile/tests/test_dynamic-items.html         |   98 +
 dojox/mobile/tests/test_dynamic-view.html          |   58 +
 dojox/mobile/tests/test_hash-parameter.html        |   71 +
 dojox/mobile/tests/test_iPhone-Animation.html      |   81 +
 dojox/mobile/tests/test_iPhone-Button.html         |   41 +
 dojox/mobile/tests/test_iPhone-ButtonList.html     |   50 +
 dojox/mobile/tests/test_iPhone-EdgeToEdge.html     |   47 +
 .../tests/test_iPhone-EdgeToEdgeCategory.html      |   46 +
 dojox/mobile/tests/test_iPhone-Heading.html        |   24 +
 dojox/mobile/tests/test_iPhone-Icon.html           |   58 +
 dojox/mobile/tests/test_iPhone-IconMulti.html      |   36 +
 dojox/mobile/tests/test_iPhone-IconSingle.html     |   35 +
 .../mobile/tests/test_iPhone-IconSingleBelow.html  |   35 +
 dojox/mobile/tests/test_iPhone-ResultList.html     |   65 +
 dojox/mobile/tests/test_iPhone-RoundRect.html      |   27 +
 dojox/mobile/tests/test_iPhone-RoundRectList.html  |   54 +
 dojox/mobile/tests/test_iPhone-Settings.html       |  168 +
 dojox/mobile/tests/test_iPhone-Switch.html         |   23 +
 dojox/mobile/tests/test_iPhone-TabContainer.html   |  169 +
 .../tests/test_iPhone-VariableHeightList.html      |   99 +
 dojox/mobile/tests/test_progress-indicator.html    |   83 +
 dojox/mobile/tests/view-sample.html                |   38 +
 dojox/mobile/tests/view1.html                      |   14 +
 dojox/mobile/tests/view1.json                      |   18 +
 dojox/mobile/tests/view2.html                      |    9 +
 dojox/mobile/tests/view2.json                      |   31 +
 dojox/mobile/tests/view3.html                      |   16 +
 dojox/mobile/tests/view3.json                      |   44 +
 dojox/mobile/themes/android/android-compat.css     |  284 +
 dojox/mobile/themes/android/android.css            |  738 +
 .../themes/android/compat/arrow-button-bg.png      |  Bin 0 -> 182 bytes
 .../themes/android/compat/arrow-button-head.png    |  Bin 0 -> 566 bytes
 .../themes/android/compat/blue-button-bg.png       |  Bin 0 -> 199 bytes
 .../themes/android/compat/blue-button-sel-bg.png   |  Bin 0 -> 182 bytes
 dojox/mobile/themes/android/compat/gray-arrow.png  |  Bin 0 -> 920 bytes
 .../android/compat/icon-content-heading-bg.png     |  Bin 0 -> 193 bytes
 .../themes/android/compat/switch-blue-bg.png       |  Bin 0 -> 199 bytes
 .../themes/android/compat/switch-gray-bg.png       |  Bin 0 -> 183 bytes
 .../themes/android/compat/switch-green-bg.png      |  Bin 0 -> 161 bytes
 .../themes/android/compat/switch-knob-bg.png       |  Bin 0 -> 174 bytes
 .../mobile/themes/android/compat/tab-button-bg.png |  Bin 0 -> 277 bytes
 .../themes/android/compat/tab-orange-button-bg.png |  Bin 0 -> 197 bytes
 .../themes/android/compat/tab-sel-button-bg.png    |  Bin 0 -> 286 bytes
 dojox/mobile/themes/buttons-compat.css             |   30 +
 dojox/mobile/themes/buttons.css                    |  191 +
 dojox/mobile/themes/compat/check-off-button.png    |  Bin 0 -> 1081 bytes
 dojox/mobile/themes/compat/check-on-button.png     |  Bin 0 -> 1148 bytes
 .../mobile/themes/compat/small-blue-button-bg.png  |  Bin 0 -> 190 bytes
 .../themes/compat/small-darkblue-button-bg.png     |  Bin 0 -> 192 bytes
 dojox/mobile/themes/compat/small-red-button-bg.png |  Bin 0 -> 186 bytes
 .../themes/iphone/compat/arrow-button-bg.png       |  Bin 0 -> 195 bytes
 .../themes/iphone/compat/arrow-button-head.png     |  Bin 0 -> 878 bytes
 .../mobile/themes/iphone/compat/blue-button-bg.png |  Bin 0 -> 199 bytes
 .../themes/iphone/compat/blue-button-sel-bg.png    |  Bin 0 -> 182 bytes
 .../mobile/themes/iphone/compat/edge-categ-bg.png  |  Bin 0 -> 130 bytes
 dojox/mobile/themes/iphone/compat/gray-arrow.png   |  Bin 0 -> 920 bytes
 dojox/mobile/themes/iphone/compat/heading-bg.png   |  Bin 0 -> 207 bytes
 .../iphone/compat/icon-content-heading-bg.png      |  Bin 0 -> 193 bytes
 .../mobile/themes/iphone/compat/switch-blue-bg.png |  Bin 0 -> 199 bytes
 .../mobile/themes/iphone/compat/switch-gray-bg.png |  Bin 0 -> 183 bytes
 .../mobile/themes/iphone/compat/switch-knob-bg.png |  Bin 0 -> 174 bytes
 .../mobile/themes/iphone/compat/tab-button-bg.png  |  Bin 0 -> 197 bytes
 .../themes/iphone/compat/tab-sel-button-bg.png     |  Bin 0 -> 200 bytes
 dojox/mobile/themes/iphone/compat/white-arrow.png  |  Bin 0 -> 920 bytes
 .../mobile/themes/iphone/images/thumb-overlay.png  |  Bin 0 -> 2010 bytes
 dojox/mobile/themes/iphone/iphone-app-compat.css   |   24 +
 dojox/mobile/themes/iphone/iphone-app.css          |  281 +
 dojox/mobile/themes/iphone/iphone-compat.css       |  290 +
 dojox/mobile/themes/iphone/iphone.css              |  751 +
 dojox/rails.js                                     |  143 +
 dojox/rails/README                                 |   41 +
 dojox/rails/tests/module.js                        |    7 +
 dojox/rails/tests/plugd/trigger.js                 |  187 +
 dojox/rails/tests/runTests.html                    |    9 +
 dojox/rails/tests/success_response.html            |    1 +
 dojox/rails/tests/test_rails.html                  |  320 +
 dojox/resources/_modules.js                        |  255 +-
 dojox/resources/explore.php                        |  149 +
 dojox/robot/recorder.js                            |  784 +-
 dojox/robot/tests/module.js                        |    8 +
 dojox/robot/tests/robotml.js                       |    9 +
 dojox/robot/tests/runTests.html                    |    9 +
 dojox/robot/tests/test_recorder.html               |  103 +
 dojox/rpc/Client.js                                |   38 +-
 dojox/rpc/JsonRPC.js                               |   86 +-
 dojox/rpc/JsonRest.js                              |  791 +-
 dojox/rpc/OfflineRest.js                           |  452 +-
 dojox/rpc/ProxiedPath.js                           |   53 +-
 dojox/rpc/Rest.js                                  |  215 +-
 dojox/rpc/SMDLibrary/wikipedia.smd                 |   98 +-
 dojox/rpc/Service.js                               |  524 +-
 dojox/rpc/demos/demo_GoogleAjax.html               |  122 +
 dojox/rpc/demos/demo_GoogleAjaxTranslate.html      |  155 +
 dojox/rpc/demos/demo_GoogleFeed.html               |   97 +
 dojox/rpc/demos/demo_jabsorb.html                  |   70 +
 dojox/rpc/demos/documentation.html                 |   33 +
 dojox/rpc/demos/templates/documentation.html       |    8 +
 dojox/rpc/demos/templates/wikipedia.html           |   10 +
 dojox/rpc/demos/templates/yahoo.html               |   31 +
 dojox/rpc/demos/wikipedia.html                     |   41 +
 dojox/rpc/demos/yahoo.html                         |   39 +
 dojox/rpc/tests/FriendFeed.js                      |  104 +
 dojox/rpc/tests/Geonames.js                        |  227 +
 dojox/rpc/tests/Service.js                         |  725 +
 dojox/rpc/tests/Wikipedia.js                       |   55 +
 dojox/rpc/tests/Yahoo.js                           |  313 +
 dojox/rpc/tests/libraryTests.js                    |   11 +
 dojox/rpc/tests/module.js                          |    9 +
 dojox/rpc/tests/resources/JSON.php                 |  724 +
 dojox/rpc/tests/resources/bigQuery                 |    1 +
 dojox/rpc/tests/resources/bigQuery5                |    1 +
 dojox/rpc/tests/resources/echo.php                 |   11 +
 dojox/rpc/tests/resources/echoJson.php             |    8 +
 dojox/rpc/tests/resources/fakestore.php            |   38 +
 dojox/rpc/tests/resources/jsonRpc10.php            |   47 +
 dojox/rpc/tests/resources/jsonRpc11.php            |   52 +
 dojox/rpc/tests/resources/jsonRpc12.php            |   54 +
 dojox/rpc/tests/resources/jsonRpcPostGetEcho.php   |   41 +
 dojox/rpc/tests/resources/jsonpEcho.php            |   26 +
 dojox/rpc/tests/resources/jsonpEcho.phps           |   26 +
 dojox/rpc/tests/resources/jsonpJsonRpcEcho.php     |   40 +
 dojox/rpc/tests/resources/obj1                     |    1 +
 dojox/rpc/tests/resources/obj1lazyValue            |    1 +
 dojox/rpc/tests/resources/obj1testArray            |    1 +
 dojox/rpc/tests/resources/obj3                     |    1 +
 dojox/rpc/tests/resources/obj4                     |    1 +
 dojox/rpc/tests/resources/query                    |    6 +
 dojox/rpc/tests/resources/rawEcho.php              |    8 +
 dojox/rpc/tests/resources/res                      |    1 +
 dojox/rpc/tests/resources/test.smd                 |  207 +
 dojox/rpc/tests/runLibraryTests.html               |    9 +
 dojox/rpc/tests/runTests.html                      |    9 +
 dojox/rpc/tests/stores/JsonRestStore.js            |  233 +
 dojox/secure/DOM.js                                |  483 +-
 dojox/secure/capability.js                         |  230 +-
 dojox/secure/sandbox.js                            |  563 +-
 dojox/secure/tests/DOM.js                          |  183 +
 dojox/secure/tests/bad.html                        |   18 +
 dojox/secure/tests/bad.js                          |    2 +
 dojox/secure/tests/good.html                       |   19 +
 dojox/secure/tests/good.js                         |    2 +
 dojox/secure/tests/load.html                       |  216 +
 dojox/secure/tests/sandbox.js                      |  120 +
 dojox/sketch.js                                    |   12 +-
 dojox/sketch/Anchor.js                             |  127 +-
 dojox/sketch/Annotation.js                         |  510 +-
 dojox/sketch/DoubleArrowAnnotation.js              |  402 +-
 dojox/sketch/Figure.js                             |  984 +-
 dojox/sketch/LeadAnnotation.js                     |  303 +-
 dojox/sketch/PreexistingAnnotation.js              |  296 +-
 dojox/sketch/SingleArrowAnnotation.js              |  402 +-
 dojox/sketch/Slider.js                             |   68 +-
 dojox/sketch/Toolbar.js                            |  166 +-
 dojox/sketch/UnderlineAnnotation.js                |  250 +-
 dojox/sketch/UndoStack.js                          |  163 +-
 dojox/sketch/_Plugin.js                            |  121 +-
 dojox/sketch/tests/FTHelper.js                     |   44 +
 dojox/sketch/tests/annotation.svg                  |   39 +
 dojox/sketch/tests/images/figure2.gif              |  Bin 0 -> 40349 bytes
 dojox/sketch/tests/images/testsBodyBg.gif          |  Bin 0 -> 753 bytes
 dojox/sketch/tests/test_full.html                  |  130 +
 dojox/sql.js                                       |   12 +-
 dojox/sql/_base.js                                 |  865 +-
 dojox/sql/_crypto.js                               |  727 +-
 dojox/sql/demos/customers/customers.html           |  292 +
 dojox/storage.js                                   |   10 -
 dojox/string/BidiComplex.js                        |  553 +-
 dojox/string/Builder.js                            |  215 +-
 dojox/string/sprintf.js                            |  676 +-
 dojox/string/tests/BidiComplex.js                  |   67 +
 dojox/string/tests/Builder.js                      |  104 +
 dojox/string/tests/BuilderArguments.html           |  505 +
 dojox/string/tests/BuilderPerf.html                |  413 +
 dojox/string/tests/PerfFun.html                    |  263 +
 dojox/string/tests/lipsum.js                       |  133 +
 dojox/string/tests/notes.txt                       |  153 +
 dojox/string/tests/peller.html                     |   78 +
 dojox/string/tests/runTests.html                   |    9 +
 dojox/string/tests/sprintf.js                      |  273 +
 dojox/string/tests/string.js                       |    7 +
 dojox/string/tests/test_BidiComplex.html           |   60 +
 dojox/string/tokenize.js                           |   76 +-
 dojox/testing/DocTest.js                           |  362 +-
 dojox/testing/tests/DocTest.js                     |    6 +
 dojox/testing/tests/module.js                      |    7 +
 dojox/testing/tests/runTests.html                  |    9 +
 dojox/timing.js                                    |   12 +-
 dojox/timing/Sequence.js                           |  230 +-
 dojox/timing/Streamer.js                           |  148 +-
 dojox/timing/ThreadPool.js                         |  285 +-
 dojox/timing/_base.js                              |   89 +-
 dojox/timing/doLater.js                            |   62 +-
 dojox/timing/tests/test_Sequence.html              |   85 +
 dojox/timing/tests/test_ThreadPool.html            |   16 +
 dojox/timing/tests/test_doLater.html               |  140 +
 dojox/uuid.js                                      |   10 -
 dojox/uuid/Uuid.js                                 |  267 +-
 dojox/uuid/_base.js                                |  359 +-
 dojox/uuid/generateRandomUuid.js                   |   80 +-
 dojox/uuid/generateTimeBasedUuid.js                |  471 +-
 dojox/uuid/tests/runTests.html                     |   10 +
 dojox/uuid/tests/uuid.js                           |  373 +
 dojox/validate.js                                  |   12 +-
 dojox/validate/_base.js                            |  191 +-
 dojox/validate/br.js                               |  466 +-
 dojox/validate/ca.js                               |   68 +-
 dojox/validate/check.js                            |  544 +-
 dojox/validate/creditCard.js                       |  160 +-
 dojox/validate/isbn.js                             |   74 +-
 dojox/validate/regexp.js                           |  436 +-
 dojox/validate/tests/br.js                         |  104 +
 dojox/validate/tests/creditcard.js                 |  115 +
 dojox/validate/tests/module.js                     |   11 +
 dojox/validate/tests/runTests.html                 |    9 +
 dojox/validate/tests/validate.js                   |  321 +
 dojox/validate/us.js                               |   86 +-
 dojox/validate/web.js                              |  113 +-
 dojox/widget/AnalogGauge.js                        |  594 +-
 dojox/widget/AutoRotator.js                        |  315 +-
 dojox/widget/BarGauge.js                           |  476 +-
 dojox/widget/Calendar.js                           | 1371 +-
 dojox/widget/Calendar/Calendar.css                 |   49 +-
 dojox/widget/CalendarFx.js                         |   38 +-
 dojox/widget/CalendarViews.js                      |  186 +-
 dojox/widget/ColorPicker.js                        |  732 +-
 dojox/widget/ColorPicker/ColorPicker.css           |   61 +-
 dojox/widget/ColorPicker/ColorPicker.html          |  101 +-
 dojox/widget/ColorPicker/images/hue.png            |  Bin 1991 -> 1991 bytes
 dojox/widget/ColorPicker/images/hueHandle.png      |  Bin 280 -> 280 bytes
 dojox/widget/ColorPicker/images/hueHandleA11y.png  |  Bin 0 -> 199 bytes
 dojox/widget/ColorPicker/images/pickerPointer.png  |  Bin 228 -> 228 bytes
 dojox/widget/ColorPicker/images/underlay.png       |  Bin 10788 -> 10788 bytes
 dojox/widget/DataPresentation.js                   | 1272 +-
 dojox/widget/Dialog.js                             |  331 +-
 dojox/widget/Dialog/Dialog.css                     |   30 +-
 dojox/widget/DocTester.js                          |  144 +-
 dojox/widget/DocTester/DocTester.css               |    2 +
 dojox/widget/DynamicTooltip.js                     |  145 +-
 dojox/widget/FeedPortlet.js                        |  641 +-
 dojox/widget/FilePicker.js                         |  377 +-
 dojox/widget/FilePicker/FilePicker.css             |  149 +-
 dojox/widget/FisheyeList.js                        | 1121 +-
 dojox/widget/FisheyeList/FisheyeList.css           |    4 +
 dojox/widget/FisheyeLite.js                        |  183 +-
 dojox/widget/Iterator.js                           |  246 +-
 dojox/widget/Loader.js                             |  151 +-
 dojox/widget/Loader/Loader.css                     |    3 +
 dojox/widget/Loader/icons/loading.gif              |  Bin 751 -> 751 bytes
 dojox/widget/Pager.js                              |  923 +-
 dojox/widget/Pager/Pager.css                       |   23 +-
 dojox/widget/PlaceholderMenuItem.js                |  176 +-
 dojox/widget/Portlet.js                            |  633 +-
 dojox/widget/Portlet/Portlet.css                   |   14 +-
 dojox/widget/Roller.js                             |  304 +-
 dojox/widget/RollingList.js                        | 2074 +-
 dojox/widget/RollingList/RollingList.css           |   28 +-
 dojox/widget/Rotator.js                            |  506 +-
 dojox/widget/SortList.js                           |  230 +-
 dojox/widget/SortList/SortList.css                 |   11 +
 dojox/widget/Standby.js                            | 1054 +-
 dojox/widget/Standby/images/loading.gif            |  Bin 4178 -> 4178 bytes
 dojox/widget/Toaster.js                            |  441 +-
 dojox/widget/Toaster/Toaster.css                   |    8 +
 dojox/widget/UpgradeBar.js                         |  312 +-
 dojox/widget/UpgradeBar/UpgradeBar.css             |   12 +
 dojox/widget/Wizard.js                             |  299 +-
 dojox/widget/Wizard/Wizard.css                     |    8 +
 dojox/widget/gauge/AnalogArcIndicator.js           |  131 +-
 dojox/widget/gauge/AnalogArrowIndicator.js         |   61 +-
 dojox/widget/gauge/AnalogNeedleIndicator.js        |   57 +-
 dojox/widget/gauge/BarIndicator.js                 |  148 +-
 dojox/widget/gauge/_Gauge.css                      |   14 +-
 dojox/widget/gauge/_Gauge.js                       | 1042 +-
 dojox/widget/nls/ColorPicker.js                    |   13 +-
 dojox/widget/nls/FilePicker.js                     |    6 +-
 dojox/widget/nls/Wizard.js                         |    6 +-
 dojox/widget/nls/ar/ColorPicker.js                 |    3 +
 dojox/widget/nls/ar/FilePicker.js                  |    6 +-
 dojox/widget/nls/ar/Wizard.js                      |    6 +-
 dojox/widget/nls/ca/ColorPicker.js                 |    6 +
 dojox/widget/nls/ca/FilePicker.js                  |    7 +-
 dojox/widget/nls/ca/Wizard.js                      |    7 +-
 dojox/widget/nls/cs/ColorPicker.js                 |   11 +-
 dojox/widget/nls/cs/FilePicker.js                  |    6 +-
 dojox/widget/nls/cs/Wizard.js                      |    6 +-
 dojox/widget/nls/da/ColorPicker.js                 |    3 +
 dojox/widget/nls/da/FilePicker.js                  |    6 +-
 dojox/widget/nls/da/Wizard.js                      |    6 +-
 dojox/widget/nls/de/ColorPicker.js                 |    4 +-
 dojox/widget/nls/de/FilePicker.js                  |    6 +-
 dojox/widget/nls/de/Wizard.js                      |    6 +-
 dojox/widget/nls/el/ColorPicker.js                 |   10 +
 dojox/widget/nls/el/FilePicker.js                  |    6 +-
 dojox/widget/nls/el/Wizard.js                      |    6 +-
 dojox/widget/nls/es/ColorPicker.js                 |    4 +-
 dojox/widget/nls/es/FilePicker.js                  |    6 +-
 dojox/widget/nls/es/Wizard.js                      |    6 +-
 dojox/widget/nls/fi/ColorPicker.js                 |    3 +
 dojox/widget/nls/fi/FilePicker.js                  |    6 +-
 dojox/widget/nls/fi/Wizard.js                      |    6 +-
 dojox/widget/nls/fr/ColorPicker.js                 |   11 +-
 dojox/widget/nls/fr/FilePicker.js                  |    6 +-
 dojox/widget/nls/fr/Wizard.js                      |    6 +-
 dojox/widget/nls/he/ColorPicker.js                 |   10 +
 dojox/widget/nls/he/FilePicker.js                  |    6 +-
 dojox/widget/nls/he/Wizard.js                      |    6 +-
 dojox/widget/nls/hu/ColorPicker.js                 |    4 +-
 dojox/widget/nls/hu/FilePicker.js                  |    6 +-
 dojox/widget/nls/hu/Wizard.js                      |    6 +-
 dojox/widget/nls/it/ColorPicker.js                 |   11 +-
 dojox/widget/nls/it/FilePicker.js                  |    6 +-
 dojox/widget/nls/it/Wizard.js                      |    6 +-
 dojox/widget/nls/ja/ColorPicker.js                 |    5 +-
 dojox/widget/nls/ja/FilePicker.js                  |    6 +-
 dojox/widget/nls/ja/Wizard.js                      |    6 +-
 dojox/widget/nls/ko/ColorPicker.js                 |   11 +-
 dojox/widget/nls/ko/FilePicker.js                  |    6 +-
 dojox/widget/nls/ko/Wizard.js                      |    6 +-
 dojox/widget/nls/nb/ColorPicker.js                 |    3 +
 dojox/widget/nls/nb/FilePicker.js                  |    6 +-
 dojox/widget/nls/nb/Wizard.js                      |    6 +-
 dojox/widget/nls/nl/ColorPicker.js                 |    6 +
 dojox/widget/nls/nl/FilePicker.js                  |    6 +-
 dojox/widget/nls/nl/Wizard.js                      |    6 +-
 dojox/widget/nls/pl/ColorPicker.js                 |   11 +-
 dojox/widget/nls/pl/FilePicker.js                  |    6 +-
 dojox/widget/nls/pl/Wizard.js                      |    6 +-
 dojox/widget/nls/pt-pt/ColorPicker.js              |    8 +
 dojox/widget/nls/pt-pt/FilePicker.js               |    6 +-
 dojox/widget/nls/pt-pt/Wizard.js                   |    6 +-
 dojox/widget/nls/pt/ColorPicker.js                 |    4 +-
 dojox/widget/nls/pt/FilePicker.js                  |    6 +-
 dojox/widget/nls/pt/Wizard.js                      |    6 +-
 dojox/widget/nls/ro/ColorPicker.js                 |    5 +
 dojox/widget/nls/ro/FilePicker.js                  |    6 +
 dojox/widget/nls/ro/Wizard.js                      |    6 +
 dojox/widget/nls/ru/ColorPicker.js                 |   11 +-
 dojox/widget/nls/ru/FilePicker.js                  |    6 +-
 dojox/widget/nls/ru/Wizard.js                      |    6 +-
 dojox/widget/nls/sk/ColorPicker.js                 |    3 +
 dojox/widget/nls/sk/FilePicker.js                  |    7 +-
 dojox/widget/nls/sk/Wizard.js                      |    7 +-
 dojox/widget/nls/sl/ColorPicker.js                 |    3 +
 dojox/widget/nls/sl/FilePicker.js                  |    7 +-
 dojox/widget/nls/sl/Wizard.js                      |    7 +-
 dojox/widget/nls/sv/ColorPicker.js                 |    6 +
 dojox/widget/nls/sv/FilePicker.js                  |    6 +-
 dojox/widget/nls/sv/Wizard.js                      |    6 +-
 dojox/widget/nls/th/ColorPicker.js                 |   10 +-
 dojox/widget/nls/th/FilePicker.js                  |    7 +-
 dojox/widget/nls/th/Wizard.js                      |    7 +-
 dojox/widget/nls/tr/ColorPicker.js                 |   10 +
 dojox/widget/nls/tr/FilePicker.js                  |    6 +-
 dojox/widget/nls/tr/Wizard.js                      |    6 +-
 dojox/widget/nls/zh-tw/ColorPicker.js              |    5 +-
 dojox/widget/nls/zh-tw/FilePicker.js               |    6 +-
 dojox/widget/nls/zh-tw/Wizard.js                   |    6 +-
 dojox/widget/nls/zh/ColorPicker.js                 |    5 +-
 dojox/widget/nls/zh/FilePicker.js                  |    6 +-
 dojox/widget/nls/zh/Wizard.js                      |    6 +-
 dojox/widget/rotator/Controller.js                 |  275 +-
 dojox/widget/rotator/Fade.js                       |   59 +-
 dojox/widget/rotator/Pan.js                        |  274 +-
 dojox/widget/rotator/Slide.js                      |   87 +-
 dojox/widget/rotator/ThumbnailController.js        |   96 +
 dojox/widget/rotator/Wipe.js                       |  133 +-
 dojox/widget/tests/CalendarStackLayout.js          |   99 +
 dojox/widget/tests/_pager-data.json                |   19 +
 dojox/widget/tests/demo_FisheyeList.html           |  117 +
 dojox/widget/tests/demo_FisheyeLite.html           |  175 +
 dojox/widget/tests/get_time.php                    |    5 +
 dojox/widget/tests/honey.php                       |   27 +
 dojox/widget/tests/images/busy.gif                 |  Bin 0 -> 5492 bytes
 dojox/widget/tests/images/fisheye_1.png            |  Bin 0 -> 3799 bytes
 dojox/widget/tests/images/fisheye_2.png            |  Bin 0 -> 4479 bytes
 dojox/widget/tests/images/fisheye_3.png            |  Bin 0 -> 4321 bytes
 dojox/widget/tests/images/fisheye_4.png            |  Bin 0 -> 4389 bytes
 dojox/widget/tests/images/flare.png                |  Bin 0 -> 9839 bytes
 dojox/widget/tests/images/gaugeOverlay.png         |  Bin 0 -> 10675 bytes
 dojox/widget/tests/images/icon_browser.png         |  Bin 0 -> 18619 bytes
 dojox/widget/tests/images/icon_calendar.png        |  Bin 0 -> 10822 bytes
 dojox/widget/tests/images/icon_email.png           |  Bin 0 -> 17133 bytes
 dojox/widget/tests/images/icon_texteditor.png      |  Bin 0 -> 25271 bytes
 dojox/widget/tests/images/icon_update.png          |  Bin 0 -> 21984 bytes
 dojox/widget/tests/images/icon_users.png           |  Bin 0 -> 24802 bytes
 dojox/widget/tests/images/rotator_aol.png          |  Bin 0 -> 10416 bytes
 dojox/widget/tests/images/rotator_aptana.png       |  Bin 0 -> 7021 bytes
 dojox/widget/tests/images/rotator_bea.png          |  Bin 0 -> 8837 bytes
 dojox/widget/tests/images/rotator_bg.gif           |  Bin 0 -> 607 bytes
 dojox/widget/tests/images/rotator_dots.png         |  Bin 0 -> 3117 bytes
 dojox/widget/tests/images/rotator_google.png       |  Bin 0 -> 6016 bytes
 dojox/widget/tests/images/rotator_ibm.png          |  Bin 0 -> 7746 bytes
 dojox/widget/tests/images/rotator_icons.gif        |  Bin 0 -> 463 bytes
 dojox/widget/tests/images/rotator_nexaweb.png      |  Bin 0 -> 5831 bytes
 dojox/widget/tests/images/rotator_openlaszlo.png   |  Bin 0 -> 20632 bytes
 dojox/widget/tests/images/rotator_renkoo.png       |  Bin 0 -> 8770 bytes
 dojox/widget/tests/images/rotator_sitepen.png      |  Bin 0 -> 2274 bytes
 dojox/widget/tests/images/rotator_sun.png          |  Bin 0 -> 42665 bytes
 dojox/widget/tests/images/rotator_tibco.png        |  Bin 0 -> 22406 bytes
 dojox/widget/tests/images/rotator_uxebu.png        |  Bin 0 -> 27894 bytes
 dojox/widget/tests/images/rotator_wavemaker.png    |  Bin 0 -> 13660 bytes
 dojox/widget/tests/images/rotator_webtide.png      |  Bin 0 -> 14122 bytes
 dojox/widget/tests/images/rotator_zend.png         |  Bin 0 -> 4852 bytes
 dojox/widget/tests/testAtom.xml                    |  662 +
 dojox/widget/tests/test_AnalogGaugeWidget.html     |  554 +
 dojox/widget/tests/test_AutoRotator.html           |  389 +
 dojox/widget/tests/test_BarGaugeWidget.html        |  339 +
 dojox/widget/tests/test_Calendar.html              |  217 +
 dojox/widget/tests/test_CalendarViews.html         |  109 +
 dojox/widget/tests/test_ColorPicker.html           |   86 +
 dojox/widget/tests/test_DataPresentation.html      |  158 +
 dojox/widget/tests/test_Dialog.html                |  307 +
 dojox/widget/tests/test_DocTester.html             |   47 +
 dojox/widget/tests/test_DynamicTooltip.html        |  178 +
 dojox/widget/tests/test_FilePicker.html            |   44 +
 dojox/widget/tests/test_FisheyeList.html           |  144 +
 dojox/widget/tests/test_FisheyeLite.html           |  327 +
 dojox/widget/tests/test_Iterator.html              |   77 +
 dojox/widget/tests/test_Loader.html                |   81 +
 dojox/widget/tests/test_Pager.html                 |   87 +
 dojox/widget/tests/test_PlaceholderMenuItem.html   |  130 +
 dojox/widget/tests/test_Portlet.html               |   94 +
 .../widget/tests/test_PortletInGridContainer.html  |  657 +
 dojox/widget/tests/test_PortletInGridContainer.js  |  239 +
 .../tests/test_PortletInGridContainerColumns.html  |   78 +
 dojox/widget/tests/test_Roller.html                |  226 +
 dojox/widget/tests/test_RollingList.html           |  203 +
 dojox/widget/tests/test_Rotator.html               |  709 +
 dojox/widget/tests/test_RotatorController.html     |  346 +
 .../tests/test_Rotator_ThumbnailController.html    |   63 +
 dojox/widget/tests/test_SortList.html              |   82 +
 dojox/widget/tests/test_Standby.html               |  388 +
 dojox/widget/tests/test_Standby_quirks.html        |  386 +
 dojox/widget/tests/test_Standby_rtl.html           |  387 +
 dojox/widget/tests/test_Toaster.html               |  161 +
 dojox/widget/tests/test_UpgradeBar.html            |   59 +
 dojox/widget/tests/test_UpgradeBar_markup.html     |   50 +
 dojox/widget/tests/test_Wizard.html                |  236 +
 dojox/wire.js                                      |   11 +-
 dojox/wire/CompositeWire.js                        |  137 +-
 dojox/wire/DataWire.js                             |  255 +-
 dojox/wire/TableAdapter.js                         |  117 +-
 dojox/wire/TextAdapter.js                          |  120 +-
 dojox/wire/TreeAdapter.js                          |  268 +-
 dojox/wire/Wire.js                                 |  604 +-
 dojox/wire/XmlWire.js                              |  371 +-
 dojox/wire/_base.js                                |  275 +-
 dojox/wire/demos/TableContainer.css                |   30 +
 dojox/wire/demos/TableContainer.js                 |   64 +
 dojox/wire/demos/WidgetRepeater.js                 |   29 +
 dojox/wire/demos/markup/countries.json             |   43 +
 dojox/wire/demos/markup/demo_ActionChaining.html   |  112 +
 dojox/wire/demos/markup/demo_ActionWiring.html     |  138 +
 dojox/wire/demos/markup/demo_BasicChildWire.html   |   78 +
 .../wire/demos/markup/demo_BasicColumnWiring.html  |   90 +
 .../wire/demos/markup/demo_ConditionalActions.html |  221 +
 dojox/wire/demos/markup/demo_FlickrStoreWire.html  |  227 +
 dojox/wire/demos/markup/demo_TopicWiring.html      |   84 +
 dojox/wire/demos/markup/flickrDemo.css             |   35 +
 dojox/wire/demos/markup/states.json                |   56 +
 dojox/wire/ml/Action.js                            |  320 +-
 dojox/wire/ml/Data.js                              |  214 +-
 dojox/wire/ml/DataStore.js                         |  151 +-
 dojox/wire/ml/Invocation.js                        |  270 +-
 dojox/wire/ml/Service.js                           |  486 +-
 dojox/wire/ml/Transfer.js                          |  459 +-
 dojox/wire/ml/util.js                              |  498 +-
 dojox/wire/tests/markup/Action.html                |  147 +
 dojox/wire/tests/markup/Data.html                  |  105 +
 dojox/wire/tests/markup/DataStore.html             |   66 +
 dojox/wire/tests/markup/DataStore.xml              |   18 +
 dojox/wire/tests/markup/Invocation.html            |   53 +
 dojox/wire/tests/markup/Service.html               |   84 +
 dojox/wire/tests/markup/Service/JSON.smd           |   11 +
 dojox/wire/tests/markup/Service/XML.smd            |   11 +
 dojox/wire/tests/markup/Service/a.json             |    5 +
 dojox/wire/tests/markup/Service/a.xml              |    5 +
 dojox/wire/tests/markup/Transfer.html              |  157 +
 dojox/wire/tests/module.js                         |    9 +
 dojox/wire/tests/programmatic/CompositeWire.js     |   47 +
 dojox/wire/tests/programmatic/ConverterDynamic.js  |    8 +
 dojox/wire/tests/programmatic/DataWire.js          |   21 +
 dojox/wire/tests/programmatic/TableAdapter.js      |   20 +
 dojox/wire/tests/programmatic/TextAdapter.js       |   21 +
 dojox/wire/tests/programmatic/TreeAdapter.js       |   25 +
 dojox/wire/tests/programmatic/Wire.js              |  119 +
 dojox/wire/tests/programmatic/XmlWire.js           |   28 +
 dojox/wire/tests/programmatic/_base.js             |  107 +
 dojox/wire/tests/runTests.html                     |    9 +
 dojox/wire/tests/wire.js                           |   14 +
 dojox/wire/tests/wireml.js                         |   14 +
 dojox/xml/DomParser.js                             |  708 +-
 dojox/xml/Script.js                                |   21 +-
 dojox/xml/parser.js                                |  310 +-
 dojox/xml/tests/mail.html                          |  484 +
 dojox/xml/tests/mail/mail.css                      |  266 +
 dojox/xml/tests/mail/mail.json                     |   76 +
 dojox/xml/tests/mail/newMail.xml                   |   16 +
 dojox/xml/tests/module.js                          |    8 +
 dojox/xml/tests/myPage.xml                         |    3 +
 dojox/xml/tests/parser.js                          |  147 +
 dojox/xml/tests/runTests.html                      |    9 +
 dojox/xml/tests/widgetParser.html                  |  107 +
 dojox/xml/widgetParser.js                          |  226 +-
 dojox/xmpp/ChatService.js                          |  223 +-
 dojox/xmpp/PresenceService.js                      |  464 +-
 dojox/xmpp/RosterService.js                        |  474 +-
 dojox/xmpp/TransportSession.js                     |  796 +-
 dojox/xmpp/UserService.js                          |  165 +-
 dojox/xmpp/bosh.js                                 |  360 +-
 dojox/xmpp/sasl.js                                 |  285 +-
 dojox/xmpp/tests/test_xmppService.html             |  515 +
 dojox/xmpp/util.js                                 |  260 +-
 dojox/xmpp/widget/ChatSession.js                   |   64 +-
 dojox/xmpp/xmppSession.js                          | 1385 +-
 util/LICENSE                                       |  195 +
 {dijit => util/buildscripts}/LICENSE               |    0
 util/buildscripts/README                           |   44 +
 util/buildscripts/build.bat                        |    3 +
 util/buildscripts/build.js                         |  374 +
 util/buildscripts/build.sh                         |    6 +
 util/buildscripts/build_notice.txt                 |    7 +
 util/buildscripts/build_release.sh                 |  140 +
 util/buildscripts/cdnBuild.sh                      |   39 +
 util/buildscripts/cdnBuild.txt                     |   18 +
 util/buildscripts/changeVersion.js                 |   13 +
 util/buildscripts/cldr/README                      |   13 +
 util/buildscripts/cldr/alias.js                    |  242 +
 util/buildscripts/cldr/arrayInherit.js             |  128 +
 util/buildscripts/cldr/build.xml                   |  266 +
 util/buildscripts/cldr/calendar.xsl                |  716 +
 util/buildscripts/cldr/cldrUtil.js                 |   49 +
 util/buildscripts/cldr/currency.xsl                |  118 +
 .../cldr/ldml/CatalogManager.properties            |   16 +
 util/buildscripts/cldr/ldml/LICENSE                |   29 +
 util/buildscripts/cldr/ldml/README                 |    3 +
 util/buildscripts/cldr/ldml/catalog                |    8 +
 util/buildscripts/cldr/ldml/core.zip               |  Bin 0 -> 3407639 bytes
 util/buildscripts/cldr/lib/APL-2.0.html            |  408 +
 util/buildscripts/cldr/lib/LICENSE                 |   10 +
 util/buildscripts/cldr/lib/MPL-1.0.html            |  420 +
 util/buildscripts/cldr/lib/ant-apache-bsf.jar      |  Bin 0 -> 12597 bytes
 util/buildscripts/cldr/lib/bsf.jar                 |  Bin 0 -> 113369 bytes
 .../cldr/lib/commons-logging-1.1.1.jar             |  Bin 0 -> 60841 bytes
 util/buildscripts/cldr/lib/resolver.jar            |  Bin 0 -> 84091 bytes
 util/buildscripts/cldr/lib/saxon9.jar              |  Bin 0 -> 5032115 bytes
 util/buildscripts/cldr/number.xsl                  |  212 +
 util/buildscripts/cldr/specialLocale.js            |  188 +
 util/buildscripts/cldr/util.xsl                    |   91 +
 util/buildscripts/clean_release.sh                 |   99 +
 util/buildscripts/copyright.txt                    |    6 +
 util/buildscripts/jslib/buildUtil.js               | 2031 ++
 util/buildscripts/jslib/buildUtilXd.js             |  192 +
 util/buildscripts/jslib/checkBuildSize.js          |   13 +
 util/buildscripts/jslib/convertTestsToXDomain.js   |   17 +
 util/buildscripts/jslib/dojoGuardEnd.jsfrag        |   12 +
 util/buildscripts/jslib/dojoGuardStart.jsfrag      |   39 +
 util/buildscripts/jslib/fileUtil.js                |  191 +
 util/buildscripts/jslib/i18nUtil.js                |  334 +
 util/buildscripts/jslib/logger.js                  |   36 +
 util/buildscripts/listProfileDeps.js               |   18 +
 util/buildscripts/makeDojoJsWeb.js                 |  103 +
 util/buildscripts/mk_branch.sh                     |   19 +
 util/buildscripts/profiles/base.profile.js         |    1 +
 util/buildscripts/profiles/baseplus.profile.js     |   21 +
 util/buildscripts/profiles/cometd.profile.js       |   15 +
 util/buildscripts/profiles/demos-all.profile.js    |  107 +
 util/buildscripts/profiles/dtkapi.profile.js       |   17 +
 util/buildscripts/profiles/fx.profile.js           |   18 +
 util/buildscripts/profiles/layers.profile.js       |   66 +
 util/buildscripts/profiles/rhino.profile.js        |   16 +
 util/buildscripts/profiles/sql.profile.js          |   21 +
 util/buildscripts/profiles/standard.profile.js     |   66 +
 .../profiles/standardCustomBase.profile.js         |   40 +
 util/buildscripts/profiles/storage.profile.js      |   21 +
 util/buildscripts/tests/conditionalTest.js         |   21 +
 util/buildscripts/tests/conditionalTest.txt        |   17 +
 util/buildscripts/tests/css/blue/one.css           |    9 +
 util/buildscripts/tests/css/blue/two/two.css       |   12 +
 util/buildscripts/tests/css/flattenTest.js         |   18 +
 util/buildscripts/tests/foo/page/view.js           |    7 +
 .../tests/profiles/customBase.profile.js           |   15 +
 .../tests/profiles/nestedNls.profile.js            |   21 +
 util/buildscripts/webbuild.html                    |   34 +
 util/buildscripts/webbuild/index.html              |   60 +
 .../webbuild/makeWebBuildModuleList.js             |  107 +
 util/buildscripts/webbuild/server/build.xml        |  172 +
 util/buildscripts/webbuild/server/js/build.js      |  203 +
 util/buildscripts/webbuild/server/lib/js.jar       |  Bin 0 -> 756883 bytes
 .../webbuild/server/lib/shrinksafe.jar             |  Bin 0 -> 19030 bytes
 .../server/src/org/dtk/BuilderContextAction.java   |   80 +
 .../server/src/org/dtk/BuilderServlet.java         |  149 +
 .../webbuild/server/src/org/dtk/FileUtil.java      |   86 +
 .../webbuild/server/web/WEB-INF/web.xml            |   40 +
 util/buildscripts/zoneinfo/LICENSE                 |   10 +
 util/buildscripts/zoneinfo/README                  |    9 +
 util/buildscripts/zoneinfo/strip_olson_comments.rb |   30 +
 util/buildscripts/zoneinfo/tzdata2009k.tar.gz      |  Bin 0 -> 179697 bytes
 util/checkstyle/checkstyle.bat                     |    3 +
 util/checkstyle/checkstyle.php.rename.html         |   31 +
 util/checkstyle/checkstyle.sh                      |    6 +
 util/checkstyle/checkstyleReport.html              |  518 +
 util/checkstyle/checkstyleUtil.js                  |  828 +
 util/checkstyle/readme.txt                         |   27 +
 util/checkstyle/runCheckstyle.js                   |  127 +
 util/docscripts/LICENSE                            |  195 +
 util/docscripts/README                             |   12 +
 util/docscripts/_browse.php                        |  236 +
 util/docscripts/_browse2.php                       |  258 +
 util/docscripts/cheat.php                          |  148 +
 util/docscripts/cheat/cheat.css                    |  123 +
 util/docscripts/cheat/lib.js                       |  313 +
 util/docscripts/generate.php                       |  440 +
 util/docscripts/includes/dojo.inc                  |  565 +
 util/docscripts/lib/generator/JsonSerializer.php   |  141 +
 util/docscripts/lib/generator/XmlSerializer.php    |  118 +
 .../lib/generator/common/AbstractSerializer.php    |  350 +
 util/docscripts/lib/generator/common/db.php        |   18 +
 util/docscripts/lib/generator/file/Freezer.php     |  133 +
 util/docscripts/lib/generator/file/Serializer.php  |  208 +
 util/docscripts/lib/generator/mysql/Freezer.php    |   47 +
 util/docscripts/lib/generator/mysql/Serializer.php |   86 +
 util/docscripts/lib/generator/resource/Freezer.php |    3 +
 .../lib/generator/resource/Serializer.php          |  176 +
 util/docscripts/lib/parser/Dojo.php                |   82 +
 util/docscripts/lib/parser/DojoArray.php           |   20 +
 util/docscripts/lib/parser/DojoBlock.php           |   37 +
 util/docscripts/lib/parser/DojoBoolean.php         |   16 +
 .../docscripts/lib/parser/DojoExecutedFunction.php |  108 +
 util/docscripts/lib/parser/DojoFunctionBody.php    |  707 +
 util/docscripts/lib/parser/DojoFunctionCall.php    |   81 +
 util/docscripts/lib/parser/DojoFunctionDeclare.php |  464 +
 util/docscripts/lib/parser/DojoNull.php            |   18 +
 util/docscripts/lib/parser/DojoObject.php          |  209 +
 util/docscripts/lib/parser/DojoPackage.php         |  515 +
 util/docscripts/lib/parser/DojoParameter.php       |  166 +
 util/docscripts/lib/parser/DojoParameters.php      |   60 +
 util/docscripts/lib/parser/DojoString.php          |   18 +
 util/docscripts/lib/parser/DojoVariable.php        |   21 +
 util/docscripts/lib/parser/README                  |    2 +
 util/docscripts/lib/parser/Text.php                |  213 +
 util/docscripts/lib/parser2/Destructable.php       |   21 +
 util/docscripts/lib/parser2/Dojo.php               |  206 +
 util/docscripts/lib/parser2/DojoCommentBlock.php   |   98 +
 util/docscripts/lib/parser2/JavaScriptArray.php    |   98 +
 .../lib/parser2/JavaScriptAssignment.php           |   56 +
 util/docscripts/lib/parser2/JavaScriptFunction.php |   42 +
 .../lib/parser2/JavaScriptFunctionCall.php         |   74 +
 util/docscripts/lib/parser2/JavaScriptLanguage.php |  265 +
 util/docscripts/lib/parser2/JavaScriptLiteral.php  |   56 +
 util/docscripts/lib/parser2/JavaScriptNumber.php   |    9 +
 util/docscripts/lib/parser2/JavaScriptObject.php   |   44 +
 util/docscripts/lib/parser2/JavaScriptOr.php       |   37 +
 util/docscripts/lib/parser2/JavaScriptParser.php   |  129 +
 util/docscripts/lib/parser2/JavaScriptRegExp.php   |    9 +
 .../lib/parser2/JavaScriptStatements.php           |  146 +
 util/docscripts/lib/parser2/JavaScriptString.php   |    9 +
 util/docscripts/lib/parser2/JavaScriptSymbol.php   |  644 +
 util/docscripts/lib/parser2/JavaScriptTernary.php  |   42 +
 util/docscripts/lib/parser2/JavaScriptVariable.php |   63 +
 util/docscripts/lib/parser2/Parser.php             |  407 +
 util/docscripts/lib/parser2/Scope.php              |  201 +
 util/docscripts/lib/parser2/Symbol.php             |  252 +
 util/docscripts/lib/parser2/dojo2.inc              |  383 +
 util/docscripts/makeCix.php                        |  326 +
 util/docscripts/modules/dijit.module               |   29 +
 util/docscripts/modules/dojo.module                |   29 +
 util/docscripts/modules/dojox.module.properties    |    1 +
 {dijit => util/doh}/LICENSE                        |    0
 util/doh/README                                    |   12 +
 util/doh/Robot.html                                |  186 +
 util/doh/_browserRunner.js                         |  883 +
 util/doh/_rhinoRunner.js                           |   18 +
 util/doh/_sounds/LICENSE                           |   10 +
 util/doh/_sounds/doh.wav                           |  Bin 0 -> 2878 bytes
 util/doh/_sounds/dohaaa.wav                        |  Bin 0 -> 14318 bytes
 util/doh/_sounds/woohoo.wav                        |  Bin 0 -> 3814 bytes
 util/doh/robot.js                                  |  540 +
 util/doh/robot/DOHRobot.jar                        |  Bin 0 -> 43794 bytes
 util/doh/robot/DOHRobot.java                       | 1660 ++
 util/doh/robot/README                              |   19 +
 util/doh/robot/compilerobot.bat                    |   10 +
 util/doh/robot/compilerobot.sh                     |    8 +
 util/doh/robot/robot.css                           |    4 +
 util/doh/runner.html                               |  320 +
 util/doh/runner.js                                 | 1503 ++
 util/doh/runner.sh                                 |    3 +
 util/doh/small_logo.png                            |  Bin 0 -> 1893 bytes
 util/doh/tests/robot.html                          |   80 +
 util/jsdoc/INSTALL                                 |   55 +
 util/jsdoc/LICENSE                                 |  195 +
 util/jsdoc/jsdoc.css                               |   24 +
 util/jsdoc/jsdoc.info                              |    4 +
 util/jsdoc/jsdoc.install                           |   23 +
 util/jsdoc/jsdoc.js                                |   91 +
 util/jsdoc/jsdoc.module                            | 3003 +++
 util/jsdoc/lib/EXTERNALS                           |    2 +
 util/jsdoc/template.php                            |   16 +
 util/migration/dijitCss14to15.sed                  |   67 +
 util/shrinksafe/LICENSE                            |    6 +
 util/shrinksafe/MPL-1.1.html                       |  389 +
 util/shrinksafe/README                             |   16 +
 util/shrinksafe/build.sh                           |   23 +
 util/shrinksafe/js.jar                             |  Bin 0 -> 756883 bytes
 util/shrinksafe/shrinksafe.jar                     |  Bin 0 -> 19066 bytes
 util/shrinksafe/src/manifest                       |    3 +
 .../src/org/dojotoolkit/shrinksafe/Compressor.java | 1017 +
 .../src/org/dojotoolkit/shrinksafe/DebugData.java  |   37 +
 .../src/org/dojotoolkit/shrinksafe/Main.java       |  315 +
 .../org/dojotoolkit/shrinksafe/ReplacedTokens.java |  198 +
 .../org/dojotoolkit/shrinksafe/TokenMapper.java    |  325 +
 .../shrinksafe/resources/Messages.properties       |   53 +
 util/shrinksafe/tests/1768.js                      |   16 +
 util/shrinksafe/tests/3241.js                      |   14 +
 util/shrinksafe/tests/5303.js                      |   21 +
 util/shrinksafe/tests/8828.js                      |   55 +
 util/shrinksafe/tests/8974.js                      |    7 +
 util/shrinksafe/tests/9444.js                      |   11 +
 util/shrinksafe/tests/9676.js                      |    3 +
 util/shrinksafe/tests/escapeunicode.js             |    1 +
 util/shrinksafe/tests/module.js                    |  209 +
 util/shrinksafe/tests/runner.sh                    |    4 +
 util/shrinksafe/tests/stripcomplex.js              |   42 +
 util/shrinksafe/tests/stripconsole.js              |   28 +
 4606 files changed, 555265 insertions(+), 205159 deletions(-)

diff --git a/dijit/Calendar.js b/dijit/Calendar.js
index 8c1c500..becf3ca 100644
--- a/dijit/Calendar.js
+++ b/dijit/Calendar.js
@@ -1,252 +1,506 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.Calendar"]){
-dojo._hasResource["dijit.Calendar"]=true;
 dojo.provide("dijit.Calendar");
+
 dojo.require("dojo.cldr.supplemental");
 dojo.require("dojo.date");
 dojo.require("dojo.date.locale");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.declare("dijit.Calendar",[dijit._Widget,dijit._Templated],{templateString:dojo.cache("dijit","templates/Calendar.html","<table cellspacing=\"0\" cellpadding=\"0\" class=\"dijitCalendarContainer\" role=\"grid\" dojoAttachEvent=\"onkeypress: _onKeyPress\">\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 [...]
-dojo.deprecated("dijit.Calendar:setValue() is deprecated.  Use attr('value', ...) instead.","","2.0");
-this.attr("value",_1);
-},_getValueAttr:function(){
-var _2=new this.dateClassObj(this.value);
-_2.setHours(0,0,0,0);
-if(_2.getDate()<this.value.getDate()){
-_2=this.dateFuncObj.add(_2,"hour",1);
-}
-return _2;
-},_setValueAttr:function(_3){
-if(!this.value||this.dateFuncObj.compare(_3,this.value)){
-_3=new this.dateClassObj(_3);
-_3.setHours(1);
-this.displayMonth=new this.dateClassObj(_3);
-if(!this.isDisabledDate(_3,this.lang)){
-this.value=_3;
-this.onChange(this.attr("value"));
-}
-dojo.attr(this.domNode,"aria-label",this.dateLocaleModule.format(_3,{selector:"date",formatLength:"full"}));
-this._populateGrid();
-}
-},_setText:function(_4,_5){
-while(_4.firstChild){
-_4.removeChild(_4.firstChild);
-}
-_4.appendChild(dojo.doc.createTextNode(_5));
-},_populateGrid:function(){
-var _6=this.displayMonth;
-_6.setDate(1);
-var _7=_6.getDay(),_8=this.dateFuncObj.getDaysInMonth(_6),_9=this.dateFuncObj.getDaysInMonth(this.dateFuncObj.add(_6,"month",-1)),_a=new this.dateClassObj(),_b=dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);
-if(_b>_7){
-_b-=7;
-}
-dojo.query(".dijitCalendarDateTemplate",this.domNode).forEach(function(_c,i){
-i+=_b;
-var _d=new this.dateClassObj(_6),_e,_f="dijitCalendar",adj=0;
-if(i<_7){
-_e=_9-_7+i+1;
-adj=-1;
-_f+="Previous";
-}else{
-if(i>=(_7+_8)){
-_e=i-_7-_8+1;
-adj=1;
-_f+="Next";
-}else{
-_e=i-_7+1;
-_f+="Current";
-}
-}
-if(adj){
-_d=this.dateFuncObj.add(_d,"month",adj);
-}
-_d.setDate(_e);
-if(!this.dateFuncObj.compare(_d,_a,"date")){
-_f="dijitCalendarCurrentDate "+_f;
-}
-if(this._isSelectedDate(_d,this.lang)){
-_f="dijitCalendarSelectedDate "+_f;
-}
-if(this.isDisabledDate(_d,this.lang)){
-_f="dijitCalendarDisabledDate "+_f;
-}
-var _10=this.getClassForDate(_d,this.lang);
-if(_10){
-_f=_10+" "+_f;
-}
-_c.className=_f+"Month dijitCalendarDateTemplate";
-_c.dijitDateValue=_d.valueOf();
-var _11=dojo.query(".dijitCalendarDateLabel",_c)[0],_12=_d.getDateLocalized?_d.getDateLocalized(this.lang):_d.getDate();
-this._setText(_11,_12);
-},this);
-var _13=this.dateLocaleModule.getNames("months","wide","standAlone",this.lang);
-this._setText(this.monthLabelNode,_13[_6.getMonth()]);
-var y=_6.getFullYear()-1;
-var d=new this.dateClassObj();
-dojo.forEach(["previous","current","next"],function(_14){
-d.setFullYear(y++);
-this._setText(this[_14+"YearLabelNode"],this.dateLocaleModule.format(d,{selector:"year",locale:this.lang}));
-},this);
-var _15=this;
-var _16=function(_17,_18,adj){
-_15._connects.push(dijit.typematic.addMouseListener(_15[_17],_15,function(_19){
-if(_19>=0){
-_15._adjustDisplay(_18,adj);
-}
-},0.8,500));
-};
-_16("incrementMonth","month",1);
-_16("decrementMonth","month",-1);
-_16("nextYearLabelNode","year",1);
-_16("previousYearLabelNode","year",-1);
-},goToToday:function(){
-this.attr("value",new this.dateClassObj());
-},constructor:function(_1a){
-var _1b=(_1a.datePackage&&(_1a.datePackage!="dojo.date"))?_1a.datePackage+".Date":"Date";
-this.dateClassObj=dojo.getObject(_1b,false);
-this.datePackage=_1a.datePackage||this.datePackage;
-this.dateFuncObj=dojo.getObject(this.datePackage,false);
-this.dateLocaleModule=dojo.getObject(this.datePackage+".locale",false);
-},postMixInProperties:function(){
-if(isNaN(this.value)){
-delete this.value;
-}
-this.inherited(arguments);
-},postCreate:function(){
-this.inherited(arguments);
-dojo.setSelectable(this.domNode,false);
-var _1c=dojo.hitch(this,function(_1d,n){
-var _1e=dojo.query(_1d,this.domNode)[0];
-for(var i=0;i<n;i++){
-_1e.parentNode.appendChild(_1e.cloneNode(true));
-}
-});
-_1c(".dijitCalendarDayLabelTemplate",6);
-_1c(".dijitCalendarDateTemplate",6);
-_1c(".dijitCalendarWeekTemplate",5);
-var _1f=this.dateLocaleModule.getNames("days",this.dayWidth,"standAlone",this.lang);
-var _20=dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);
-dojo.query(".dijitCalendarDayLabel",this.domNode).forEach(function(_21,i){
-this._setText(_21,_1f[(i+_20)%7]);
-},this);
-var _22=this.dateLocaleModule.getNames("months","wide","standAlone",this.lang);
-_1c(".dijitCalendarMonthLabelTemplate",_22.length-1);
-dojo.query(".dijitCalendarMonthLabelTemplate",this.domNode).forEach(function(_23,i){
-dojo.attr(_23,"month",i);
-this._setText(_23,_22[i]);
-dojo.place(_23.cloneNode(true),this.monthLabelSpacer);
-},this);
-var _24=this.value;
-this.value=null;
-this.attr("value",new this.dateClassObj(_24));
-},_onMenuHover:function(e){
-dojo.stopEvent(e);
-dojo.toggleClass(e.target,"dijitMenuItemHover");
-},_adjustDisplay:function(_25,_26){
-this.displayMonth=this.dateFuncObj.add(this.displayMonth,_25,_26);
-this._populateGrid();
-},_onMonthToggle:function(evt){
-dojo.stopEvent(evt);
-if(evt.type=="mousedown"){
-var _27=dojo.position(this.monthLabelNode);
-var dim={width:_27.w+"px",top:-this.displayMonth.getMonth()*_27.h+"px"};
-if((dojo.isIE&&dojo.isQuirks)||dojo.isIE<7){
-dim.left=-_27.w/2+"px";
-}
-dojo.style(this.monthDropDown,dim);
-this._popupHandler=this.connect(document,"onmouseup","_onMonthToggle");
-}else{
-this.disconnect(this._popupHandler);
-delete this._popupHandler;
-}
-dojo.toggleClass(this.monthDropDown,"dijitHidden");
-dojo.toggleClass(this.monthLabelNode,"dijitVisible");
-},_onMonthSelect:function(evt){
-this._onMonthToggle(evt);
-this.displayMonth.setMonth(dojo.attr(evt.target,"month"));
-this._populateGrid();
-},_onDayClick:function(evt){
-dojo.stopEvent(evt);
-for(var _28=evt.target;_28&&!_28.dijitDateValue;_28=_28.parentNode){
-}
-if(_28&&!dojo.hasClass(_28,"dijitCalendarDisabledDate")){
-this.attr("value",_28.dijitDateValue);
-this.onValueSelected(this.attr("value"));
-}
-},_onDayMouseOver:function(evt){
-var _29=evt.target;
-if(_29&&(_29.dijitDateValue||_29==this.previousYearLabelNode||_29==this.nextYearLabelNode)){
-dojo.addClass(_29,"dijitCalendarHoveredDate");
-this._currentNode=_29;
-}
-},_onDayMouseOut:function(evt){
-if(!this._currentNode){
-return;
-}
-for(var _2a=evt.relatedTarget;_2a;){
-if(_2a==this._currentNode){
-return;
-}
-try{
-_2a=_2a.parentNode;
-}
-catch(x){
-_2a=null;
-}
-}
-dojo.removeClass(this._currentNode,"dijitCalendarHoveredDate");
-this._currentNode=null;
-},_onKeyPress:function(evt){
-var dk=dojo.keys,_2b=-1,_2c,_2d=this.value;
-switch(evt.keyCode){
-case dk.RIGHT_ARROW:
-_2b=1;
-case dk.LEFT_ARROW:
-_2c="day";
-if(!this.isLeftToRight()){
-_2b*=-1;
-}
-break;
-case dk.DOWN_ARROW:
-_2b=1;
-case dk.UP_ARROW:
-_2c="week";
-break;
-case dk.PAGE_DOWN:
-_2b=1;
-case dk.PAGE_UP:
-_2c=evt.ctrlKey?"year":"month";
-break;
-case dk.END:
-_2d=this.dateFuncObj.add(_2d,"month",1);
-_2c="day";
-case dk.HOME:
-_2d=new Date(_2d).setDate(1);
-break;
-case dk.ENTER:
-this.onValueSelected(this.attr("value"));
-break;
-case dk.ESCAPE:
-default:
-return;
-}
-dojo.stopEvent(evt);
-if(_2c){
-_2d=this.dateFuncObj.add(_2d,_2c,_2b);
-}
-this.attr("value",_2d);
-},onValueSelected:function(_2e){
-},onChange:function(_2f){
-},_isSelectedDate:function(_30,_31){
-return !this.dateFuncObj.compare(_30,this.value,"date");
-},isDisabledDate:function(_32,_33){
-},getClassForDate:function(_34,_35){
-}});
-}
+dojo.require("dijit._CssStateMixin");
+
+dojo.declare(
+	"dijit.Calendar",
+	[dijit._Widget, dijit._Templated, dijit._CssStateMixin],
+	{
+		// 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 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: dojo.cache("dijit", "templates/Calendar.html"),
+
+		// value: Date
+		//		The currently selected Date
+		value: new Date(),
+
+		// datePackage: String
+		//		JavaScript namespace to find Calendar routines.  Uses Gregorian Calendar routines
+		//		at dojo.date by default.
+		datePackage: "dojo.date",
+
+		// dayWidth: String
+		//		How to represent the days of the week in the calendar header. See dojo.date.locale
+		dayWidth: "narrow",
+
+		// tabIndex: Integer
+		//		Order fields are traversed when user hits the tab key
+		tabIndex: "0",
+		
+		baseClass:"dijitCalendar",
+
+		// Set node classes for various mouse events, see dijit._CssStateMixin for more details 
+		cssStateNodes: {
+			"decrementMonth": "dijitCalendarArrow",
+			"incrementMonth": "dijitCalendarArrow",
+			"previousYearLabelNode": "dijitCalendarPreviousYear",
+			"nextYearLabelNode": "dijitCalendarNextYear"			
+		},
+
+		attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+			tabIndex: "domNode"
+ 		}),
+
+		setValue: function(/*Date*/ value){
+			// summary:
+			//      Deprecated.   Used attr('value', ...) instead.
+			// tags:
+			//      deprecated
+			dojo.deprecated("dijit.Calendar:setValue() is deprecated.  Use set('value', ...) instead.", "", "2.0");
+			this.set('value', value);
+		},
+
+		_getValueAttr: function(){
+			// summary:
+			//		Support getter attr('value')
+			var value = new this.dateClassObj(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 = this.dateFuncObj.add(value, "hour", 1);
+			}
+			return value;
+		},
+
+		_setValueAttr: function(/*Date*/ value){
+			// summary:
+			//		Support setter attr("value", ...)
+			// description:
+			// 		Set the current date and update the UI.  If the date is disabled, the value will
+			//		not change, but the display will change to the corresponding month.
+			// tags:
+			//      protected
+			if(!this.value || this.dateFuncObj.compare(value, this.value)){
+				value = new this.dateClassObj(value);
+				value.setHours(1); // to avoid issues when DST shift occurs at midnight, see #8521, #9366
+				this.displayMonth = new this.dateClassObj(value);
+				if(!this.isDisabledDate(value, this.lang)){
+					this.value = value;
+					this.onChange(this.get('value'));
+				}
+				dojo.attr(this.domNode, "aria-label",
+					this.dateLocaleModule.format(value,
+						{selector:"date", formatLength:"full"}));
+				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(),
+				daysInMonth = this.dateFuncObj.getDaysInMonth(month),
+				daysInPreviousMonth = this.dateFuncObj.getDaysInMonth(this.dateFuncObj.add(month, "month", -1)),
+				today = new this.dateClassObj(),
+				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 this.dateClassObj(month),
+					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 = this.dateFuncObj.add(date, "month", adj);
+				}
+				date.setDate(number);
+
+				if(!this.dateFuncObj.compare(date, today, "date")){
+					clazz = "dijitCalendarCurrentDate " + clazz;
+				}
+
+				if(this._isSelectedDate(date, this.lang)){
+					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],
+					text = date.getDateLocalized ? date.getDateLocalized(this.lang) : date.getDate();
+				this._setText(label, text);
+			}, this);
+
+			// Fill in localized month name
+			var monthNames = this.dateLocaleModule.getNames('months', 'wide', 'standAlone', this.lang, month);
+			this._setText(this.monthLabelNode, monthNames[month.getMonth()]);
+			// Repopulate month list based on current year (Hebrew calendar)
+			dojo.query(".dijitCalendarMonthLabelTemplate", this.domNode).forEach(function(node, i){
+				dojo.toggleClass(node, "dijitHidden", !(i in monthNames)); // hide leap months (Hebrew)
+				this._setText(node, monthNames[i]);
+			}, this);
+
+			// Fill in localized prev/current/next years
+			var y = month.getFullYear() - 1;
+			var d = new this.dateClassObj();
+			dojo.forEach(["previous", "current", "next"], function(name){
+				d.setFullYear(y++);
+				this._setText(this[name+"YearLabelNode"],
+					this.dateLocaleModule.format(d, {selector:'year', locale:this.lang}));
+			}, this);
+
+			// Set up repeating mouse behavior
+			var _this = this;
+			var typematic = function(nodeProp, dateProp, adj){
+//FIXME: leaks (collects) listeners if populateGrid is called multiple times.  Do this once?
+				_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.set('value', new this.dateClassObj());
+		},
+
+		constructor: function(/*Object*/args){
+			var dateClass = (args.datePackage && (args.datePackage != "dojo.date"))? args.datePackage + ".Date" : "Date";
+			this.dateClassObj = dojo.getObject(dateClass, false);
+			this.datePackage = args.datePackage || this.datePackage;
+			this.dateFuncObj = dojo.getObject(this.datePackage, false);
+			this.dateLocaleModule = dojo.getObject(this.datePackage + ".locale", false);
+		},
+
+		postMixInProperties: function(){
+			// parser.instantiate sometimes passes in NaN for IE.  Use default value in prototype instead.
+			if(isNaN(this.value)){ delete this.value; }
+			this.inherited(arguments);
+		},
+
+		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 = this.dateLocaleModule.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);
+
+			var dateObj = new this.dateClassObj(this.value);
+			// Fill in spacer/month dropdown element with all the month names (invisible) so that the maximum width will affect layout
+			var monthNames = this.dateLocaleModule.getNames('months', 'wide', 'standAlone', this.lang, dateObj);
+			cloneClass(".dijitCalendarMonthLabelTemplate", monthNames.length-1);
+			dojo.query(".dijitCalendarMonthLabelTemplate", this.domNode).forEach(function(node, i){
+				dojo.attr(node, "month", i);
+				if(i in monthNames){ this._setText(node, monthNames[i]); }
+				dojo.place(node.cloneNode(true), this.monthLabelSpacer);
+			}, this);
+
+			this.value = null;
+			this.set('value', dateObj);
+		},
+
+		_onMenuHover: function(e){
+			dojo.stopEvent(e);
+			dojo.toggleClass(e.target, "dijitMenuItemHover");
+		},
+
+		_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 = this.dateFuncObj.add(this.displayMonth, part, amount);
+			this._populateGrid();
+		},
+
+		_onMonthToggle: function(/*Event*/ evt){
+			// summary:
+			//      Handler for when user triggers or dismisses the month list
+			// tags:
+			//      protected
+			dojo.stopEvent(evt);
+
+			if(evt.type == "mousedown"){
+				var coords = dojo.position(this.monthLabelNode);
+//				coords.y -= dojo.position(this.domNode, true).y;
+				// Size the dropdown's width to match the label in the widget
+				// so that they are horizontally aligned
+				var dim = {
+					width: coords.w + "px",
+					top: -this.displayMonth.getMonth() * coords.h + "px"
+				};
+				if((dojo.isIE && dojo.isQuirks) || dojo.isIE < 7){
+					dim.left = -coords.w/2 + "px";
+				}
+				dojo.style(this.monthDropDown, dim);
+				this._popupHandler = this.connect(document, "onmouseup", "_onMonthToggle");
+			}else{
+				this.disconnect(this._popupHandler);
+				delete this._popupHandler;
+			}
+
+			dojo.toggleClass(this.monthDropDown, "dijitHidden");
+			dojo.toggleClass(this.monthLabelNode, "dijitVisible");
+		},
+
+		_onMonthSelect: function(/*Event*/ evt){
+			// summary:
+			//      Handler for when user selects a month from a list
+			// tags:
+			//      protected
+			this._onMonthToggle(evt);
+			this.displayMonth.setMonth(dojo.attr(evt.target, "month"));
+			this._populateGrid();
+		},
+
+		_onDayClick: function(/*Event*/ evt){
+			// summary:
+			//      Handler for day clicks, selects the date if appropriate
+			// tags:
+			//      protected
+			dojo.stopEvent(evt);
+			for(var node = evt.target; node && !node.dijitDateValue; node = node.parentNode);
+			if(node && !dojo.hasClass(node, "dijitCalendarDisabledDate")){
+				this.set('value', node.dijitDateValue);
+				this.onValueSelected(this.get('value'));
+			}
+		},
+
+		_onDayMouseOver: function(/*Event*/ evt){
+			// summary:
+			//      Handler for mouse over events on days, sets hovered style
+			// tags:
+			//      protected
+
+			// event can occur on <td> or the <span> inside the td,
+			// set node to the <td>.
+			var node =
+				dojo.hasClass(evt.target, "dijitCalendarDateLabel") ?
+				evt.target.parentNode :
+				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 mouse out events on days, clears hovered style
+			// tags:
+			//      protected
+	
+			if(!this._currentNode){ return; }
+			
+			// if mouse out occurs moving from <td> to <span> inside <td>, ignore it
+			if(evt.relatedTarget && evt.relatedTarget.parentNode == this._currentNode){ return; }
+
+			dojo.removeClass(this._currentNode, "dijitCalendarHoveredDate");
+			if(dojo.hasClass(this._currentNode, "dijitCalendarActiveDate")) {
+				dojo.removeClass(this._currentNode, "dijitCalendarActiveDate");
+			}
+			this._currentNode = null;
+		},
+		
+		_onDayMouseDown: function(/*Event*/ evt){
+			var node = evt.target.parentNode;
+			if(node && node.dijitDateValue){
+				dojo.addClass(node, "dijitCalendarActiveDate");
+				this._currentNode = node;
+			}
+		},
+		
+		_onDayMouseUp: function(/*Event*/ evt){
+			var node = evt.target.parentNode;
+			if(node && node.dijitDateValue){
+				dojo.removeClass(node, "dijitCalendarActiveDate");
+			}
+		},
+
+//TODO: use typematic
+//TODO: skip disabled dates without ending up in a loop
+//TODO: could optimize by avoiding populate grid when month does not change
+		_onKeyPress: function(/*Event*/evt){
+			// summary:
+			//		Provides keyboard navigation of calendar
+			// tags:
+			//		protected
+			var dk = dojo.keys,
+				increment = -1,
+				interval,
+				newValue = this.value;
+			switch(evt.keyCode){
+				case dk.RIGHT_ARROW:
+					increment = 1;
+					//fallthrough...
+				case dk.LEFT_ARROW:
+					interval = "day";
+					if(!this.isLeftToRight()){ increment *= -1; }
+					break;
+				case dk.DOWN_ARROW:
+					increment = 1;
+					//fallthrough...
+				case dk.UP_ARROW:
+					interval = "week";
+					break;
+				case dk.PAGE_DOWN:
+					increment = 1;
+					//fallthrough...
+				case dk.PAGE_UP:
+					interval = evt.ctrlKey ? "year" : "month";
+					break;
+				case dk.END:
+					// go to the next month
+					newValue = this.dateFuncObj.add(newValue, "month", 1);
+					// subtract a day from the result when we're done
+					interval = "day";
+					//fallthrough...
+				case dk.HOME:
+					newValue = new Date(newValue).setDate(1);
+					break;
+				case dk.ENTER:
+					this.onValueSelected(this.get('value'));
+					break;
+				case dk.ESCAPE:
+					//TODO
+				default:
+					return;
+			}
+			dojo.stopEvent(evt);
+
+			if(interval){
+				newValue = this.dateFuncObj.add(newValue, interval, increment);
+			}
+
+			this.set("value", newValue);
+		},
+
+		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
+		},
+
+		_isSelectedDate: function(/*Date*/ dateObject, /*String?*/ locale){
+			// summary:
+			//		Extension point so developers can subclass Calendar to
+			//		support multiple (concurrently) selected dates
+			// tags:
+			//		protected extension
+			return !this.dateFuncObj.compare(dateObject, this.value, "date")
+		},
+
+		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
+=====*/
+		}
+	}
+);
diff --git a/dijit/CheckedMenuItem.js b/dijit/CheckedMenuItem.js
index cc18b16..09313a9 100644
--- a/dijit/CheckedMenuItem.js
+++ b/dijit/CheckedMenuItem.js
@@ -1,24 +1,43 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.CheckedMenuItem"]){
-dojo._hasResource["dijit.CheckedMenuItem"]=true;
 dojo.provide("dijit.CheckedMenuItem");
+
 dojo.require("dijit.MenuItem");
-dojo.declare("dijit.CheckedMenuItem",dijit.MenuItem,{templateString:dojo.cache("dijit","templates/CheckedMenuItem.html","<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= [...]
-dojo.toggleClass(this.domNode,"dijitCheckedMenuItemChecked",_1);
-dijit.setWaiState(this.domNode,"checked",_1);
-this.checked=_1;
-},onChange:function(_2){
-},_onClick:function(e){
-if(!this.disabled){
-this.attr("checked",!this.checked);
-this.onChange(this.checked);
-}
-this.inherited(arguments);
-}});
-}
+
+dojo.declare("dijit.CheckedMenuItem",
+		dijit.MenuItem,
+		{
+		// summary:
+		//		A checkbox-like menu item for toggling on and off
+
+		templateString: dojo.cache("dijit", "templates/CheckedMenuItem.html"),
+
+		// 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.set("checked", !this.checked);
+				this.onChange(this.checked);
+			}
+			this.inherited(arguments);
+		}
+	});
diff --git a/dijit/ColorPalette.js b/dijit/ColorPalette.js
index 300a378..7a389a0 100644
--- a/dijit/ColorPalette.js
+++ b/dijit/ColorPalette.js
@@ -1,106 +1,109 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.ColorPalette"]){
-dojo._hasResource["dijit.ColorPalette"]=true;
 dojo.provide("dijit.ColorPalette");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dojo.colors");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojo","colors",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit.ColorPalette",[dijit._Widget,dijit._Templated],{defaultTimeout:500,timeoutChangeRate:0.9,palette:"7x10",value:null,_currentFocus:0,_xDim:null,_yDim:null,_palettes:{"7x10":[["white","seashell","cornsilk","lemonchiffon","lightyellow","palegreen","paleturquoise","lightcyan","lavender","plum"],["lightgray","pink","bisque","moccasin","khaki","lightgreen","lightseagreen","lightskyblue","cornflowerblue","violet"],["silver","lightcoral","sandybrown","orange","palegoldenrod"," [...]
-this.inherited(arguments);
-dojo.mixin(this.divNode.style,this._paletteDims[this.palette]);
-this.imageNode.setAttribute("src",this._imagePaths[this.palette].toString());
-var _1=this._palettes[this.palette];
-this.domNode.style.position="relative";
-this._cellNodes=[];
-this.colorNames=dojo.i18n.getLocalization("dojo","colors",this.lang);
-var _2=this._blankGif,_3=new dojo.Color(),_4=this._paletteCoords;
-for(var _5=0;_5<_1.length;_5++){
-var _6=dojo.create("div",{role:"row"},this.divNode);
-for(var _7=0;_7<_1[_5].length;_7++){
-var _8=_1[_5][_7],_9=_3.setColor(dojo.Color.named[_8]);
-var _a=dojo.create("span",{"class":"dijitPaletteCell",tabIndex:"-1",title:this.colorNames[_8],style:{top:_4.topOffset+(_5*_4.cHeight)+"px",left:_4.leftOffset+(_7*_4.cWidth)+"px"}});
-var _b=dojo.create("img",{src:_2,"class":"dijitPaletteImg",alt:this.colorNames[_8]},_a);
-_b.color=_9.toHex();
-var _c=_b.style;
-_c.color=_c.backgroundColor=_b.color;
-dojo.forEach(["Dijitclick","MouseEnter","MouseLeave","Focus"],function(_d){
-this.connect(_a,"on"+_d.toLowerCase(),"_onCell"+_d);
-},this);
-dojo.place(_a,_6);
-dijit.setWaiRole(_a,"gridcell");
-_a.index=this._cellNodes.length;
-this._cellNodes.push(_a);
-}
-}
-this._xDim=_1[0].length;
-this._yDim=_1.length;
-var _e={UP_ARROW:-this._xDim,DOWN_ARROW:this._xDim,RIGHT_ARROW:1,LEFT_ARROW:-1};
-for(var _f in _e){
-this._connects.push(dijit.typematic.addKeyListener(this.domNode,{charOrCode:dojo.keys[_f],ctrlKey:false,altKey:false,shiftKey:false},this,function(){
-var _10=_e[_f];
-return function(_11){
-this._navigateByKey(_10,_11);
-};
-}(),this.timeoutChangeRate,this.defaultTimeout));
-}
-},postCreate:function(){
-this.inherited(arguments);
-this._currentFocus=this._cellNodes[0];
-dojo.attr(this._currentFocus,"tabIndex",this.tabIndex);
-},focus:function(){
-dojo.addClass(this._currentFocus,"dijitPaletteCellHighlight");
-dijit.focus(this._currentFocus);
-},onChange:function(_12){
-},_onFocus:function(){
-dojo.addClass(this._currentFocus,"dijitPaletteCellHighlight");
-this.inherited(arguments);
-},_onBlur:function(){
-dojo.attr(this._currentFocus,"tabIndex","-1");
-dojo.removeClass(this._currentFocus,"dijitPaletteCellHighlight");
-this._currentFocus=this._cellNodes[0];
-dojo.attr(this._currentFocus,"tabIndex",this.tabIndex);
-this.inherited(arguments);
-},_onCellDijitclick:function(evt){
-var _13=evt.currentTarget;
-this._selectColor(_13);
-dojo.stopEvent(evt);
-},_onCellMouseEnter:function(evt){
-var _14=evt.currentTarget;
-this._setCurrent(_14);
-},_onCellMouseLeave:function(evt){
-dojo.removeClass(this._currentFocus,"dijitPaletteCellHighlight");
-},_onCellFocus:function(evt){
-this._setCurrent(evt.currentTarget);
-},_setCurrent:function(_15){
-if("_currentFocus" in this){
-dojo.attr(this._currentFocus,"tabIndex","-1");
-dojo.removeClass(this._currentFocus,"dijitPaletteCellHighlight");
-}
-this._currentFocus=_15;
-if(_15){
-dojo.attr(_15,"tabIndex",this.tabIndex);
-dojo.addClass(_15,"dijitPaletteCellHighlight");
-}
-},_selectColor:function(_16){
-var img=_16.getElementsByTagName("img")[0];
-this.onChange(this.value=img.color);
-},_navigateByKey:function(_17,_18){
-if(_18==-1){
-return;
-}
-var _19=this._currentFocus.index+_17;
-if(_19<this._cellNodes.length&&_19>-1){
-var _1a=this._cellNodes[_19];
-this._setCurrent(_1a);
-setTimeout(dojo.hitch(dijit,"focus",_1a),0);
-}
-}});
-}
+
+dojo.require("dijit._PaletteMixin");
+
+dojo.requireLocalization("dojo", "colors");
+
+dojo.declare("dijit.ColorPalette",
+	[dijit._Widget, dijit._Templated, dijit._PaletteMixin],
+	{
+	// summary:
+	//		A keyboard accessible color-picking widget
+	// description:
+	//		Grid showing various colors, so the user can pick a certain color.
+	//		Can be used standalone, or as a popup.
+	//
+	// example:
+	// |	<div dojoType="dijit.ColorPalette"></div>
+	//
+	// example:
+	// |	var picker = new dijit.ColorPalette({ },srcNode);
+	// |	picker.startup();
+
+
+	// palette: String
+	//		Size of grid, either "7x10" or "3x4".
+	palette: "7x10",
+
+	// _palettes: [protected] Map
+	// 		This represents the value of the colors.
+	//		The first level is a hashmap of the different palettes available.
+	//		The next two dimensions represent the columns and rows of colors.
+	_palettes: {
+		"7x10":	[["white", "seashell", "cornsilk", "lemonchiffon","lightyellow", "palegreen", "paleturquoise", "lightcyan",	"lavender", "plum"],
+				["lightgray", "pink", "bisque", "moccasin", "khaki", "lightgreen", "lightseagreen", "lightskyblue", "cornflowerblue", "violet"],
+				["silver", "lightcoral", "sandybrown", "orange", "palegoldenrod", "chartreuse", "mediumturquoise", 	"skyblue", "mediumslateblue","orchid"],
+				["gray", "red", "orangered", "darkorange", "yellow", "limegreen", 	"darkseagreen", "royalblue", "slateblue", "mediumorchid"],
+				["dimgray", "crimson", 	"chocolate", "coral", "gold", "forestgreen", "seagreen", "blue", "blueviolet", "darkorchid"],
+				["darkslategray","firebrick","saddlebrown", "sienna", "olive", "green", "darkcyan", "mediumblue","darkslateblue", "darkmagenta" ],
+				["black", "darkred", "maroon", "brown", "darkolivegreen", "darkgreen", "midnightblue", "navy", "indigo", 	"purple"]],
+
+		"3x4": [["white", "lime", "green", "blue"],
+			["silver", "yellow", "fuchsia", "navy"],
+			["gray", "red", "purple", "black"]]
+	},
+
+	// _imagePaths: [protected] Map
+	//		This is stores the path to the palette images
+	_imagePaths: {
+		"7x10": dojo.moduleUrl("dijit.themes", "a11y/colors7x10.png"),
+		"3x4": dojo.moduleUrl("dijit.themes", "a11y/colors3x4.png"),
+		"7x10-rtl": dojo.moduleUrl("dijit.themes", "a11y/colors7x10-rtl.png"),
+		"3x4-rtl": dojo.moduleUrl("dijit.themes", "a11y/colors3x4-rtl.png")
+	},
+
+	// templateString: String
+	//		The template of this widget.
+	templateString: dojo.cache("dijit", "templates/ColorPalette.html"),
+
+	baseClass: "dijitColorPalette",
+
+	dyeClass: 'dijit._Color',
+
+	buildRendering: function(){
+		// Instantiate the template, which makes a skeleton into which we'll insert a bunch of
+		// <img> nodes
+
+		this.inherited(arguments);
+
+		this.imageNode.setAttribute("src", this._imagePaths[this.palette + (this.isLeftToRight() ? "" : "-rtl")].toString());
+
+		var i18nColorNames = dojo.i18n.getLocalization("dojo", "colors", this.lang);
+		this._preparePalette(
+			this._palettes[this.palette],
+			i18nColorNames
+		);
+	}
+});
+
+dojo.declare("dijit._Color", dojo.Color,
+	// summary:
+	//		Object associated with each cell in a ColorPalette palette.
+	//		Implements dijit.Dye.
+	{
+		constructor: function(/*String*/alias){
+			this._alias = alias;
+			this.setColor(dojo.Color.named[alias]);
+		},
+
+		getValue: function(){
+			// summary:
+			//		Note that although dijit._Color is initialized with a value like "white" getValue() always
+			//		returns a hex value
+			return this.toHex();
+		},
+
+		fillCell: function(/*DOMNode*/ cell, /*String*/ blankGif){
+			dojo.create("img", {
+				src: blankGif,
+				"class": "dijitPaletteImg",
+				alt: this._alias
+			}, cell);
+		}
+	}
+);
diff --git a/dijit/Declaration.js b/dijit/Declaration.js
index 4ca4574..cfdd582 100644
--- a/dijit/Declaration.js
+++ b/dijit/Declaration.js
@@ -1,36 +1,86 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.Declaration"]){
-dojo._hasResource["dijit.Declaration"]=true;
 dojo.provide("dijit.Declaration");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.declare("dijit.Declaration",dijit._Widget,{_noScript:true,widgetClass:"",defaults:null,mixins:[],buildRendering:function(){
-var _1=this.srcNodeRef.parentNode.removeChild(this.srcNodeRef),_2=dojo.query("> script[type^='dojo/method'][event]",_1).orphan(),_3=dojo.query("> script[type^='dojo/method']",_1).orphan(),_4=dojo.query("> script[type^='dojo/connect']",_1).orphan(),_5=_1.nodeName;
-var _6=this.defaults||{};
-dojo.forEach(_2,function(s){
-var _7=s.getAttribute("event"),_8=dojo.parser._functionFromScript(s);
-_6[_7]=_8;
-});
-this.mixins=this.mixins.length?dojo.map(this.mixins,function(_9){
-return dojo.getObject(_9);
-}):[dijit._Widget,dijit._Templated];
-_6.widgetsInTemplate=true;
-_6._skipNodeCache=true;
-_6.templateString="<"+_5+" class='"+_1.className+"' dojoAttachPoint='"+(_1.getAttribute("dojoAttachPoint")||"")+"' dojoAttachEvent='"+(_1.getAttribute("dojoAttachEvent")||"")+"' >"+_1.innerHTML.replace(/\%7B/g,"{").replace(/\%7D/g,"}")+"</"+_5+">";
-dojo.query("[dojoType]",_1).forEach(function(_a){
-_a.removeAttribute("dojoType");
-});
-var wc=dojo.declare(this.widgetClass,this.mixins,_6);
-var _b=_4.concat(_3);
-dojo.forEach(_b,function(s){
-var _c=s.getAttribute("event")||"postscript",_d=dojo.parser._functionFromScript(s);
-dojo.connect(wc.prototype,_c,_d);
-});
-}});
-}
+
+dojo.declare(
+	"dijit.Declaration",
+	dijit._Widget,
+	{
+		// summary:
+		//		The Declaration widget allows a developer to declare new widget
+		//		classes directly from a snippet of markup.
+
+		// _noScript: [private] Boolean
+		//		Flag to parser to leave alone the script tags contained inside of me
+		_noScript: true,
+
+		// widgetClass: String
+		//		Name of class being declared, ex: "acme.myWidget"
+		widgetClass: "",
+
+		// propList: Object
+		//		Set of attributes for this widget along with default values, ex:
+		//		{delay: 100, title: "hello world"}
+		defaults: null,
+
+		// mixins: String[]
+		//		List containing the prototype for this widget, and also any mixins,
+		//		ex: ["dijit._Widget", "dijit._Container"]
+		mixins: [],
+
+		buildRendering: function(){
+			var src = this.srcNodeRef.parentNode.removeChild(this.srcNodeRef),
+				methods = dojo.query("> script[type^='dojo/method'][event]", src).orphan(),
+				postscriptConnects = dojo.query("> script[type^='dojo/method']", src).orphan(),
+				regularConnects = dojo.query("> script[type^='dojo/connect']", src).orphan(),
+				srcType = src.nodeName;
+
+			var propList = this.defaults || {};
+
+			// For all methods defined like <script type="dojo/method" event="foo">,
+			// add that method to prototype
+			dojo.forEach(methods, function(s){
+				var evt = s.getAttribute("event"),
+					func = dojo.parser._functionFromScript(s);
+				propList[evt] = func;
+			});
+
+			// map array of strings like [ "dijit.form.Button" ] to array of mixin objects
+			// (note that dojo.map(this.mixins, dojo.getObject) doesn't work because it passes
+			// a bogus third argument to getObject(), confusing it)
+			this.mixins = this.mixins.length ?
+				dojo.map(this.mixins, function(name){ return dojo.getObject(name); } ) :
+				[ dijit._Widget, dijit._Templated ];
+
+			propList.widgetsInTemplate = true;
+			propList._skipNodeCache = true;
+			propList.templateString = "<"+srcType+" class='"+src.className+"' dojoAttachPoint='"+(src.getAttribute("dojoAttachPoint") || '')+"' dojoAttachEvent='"+(src.getAttribute("dojoAttachEvent") || '')+"' >"+src.innerHTML.replace(/\%7B/g,"{").replace(/\%7D/g,"}")+"</"+srcType+">";
+
+			// strip things so we don't create stuff under us in the initial setup phase
+			dojo.query("[dojoType]", src).forEach(function(node){
+				node.removeAttribute("dojoType");
+			});
+
+			// create the new widget class
+			var wc = dojo.declare(
+				this.widgetClass,
+				this.mixins,
+				propList
+			);
+
+			// Handle <script> blocks of form:
+			//		<script type="dojo/connect" event="foo">
+			// and
+			//		<script type="dojo/method">
+			// (Note that the second one is just shorthand for a dojo/connect to postscript)
+			// Since this is a connect in the declaration, we are actually connection to the method
+			// in the _prototype_.
+			var connects = regularConnects.concat(postscriptConnects);
+			dojo.forEach(connects, function(s){
+				var evt = s.getAttribute("event") || "postscript",
+					func = dojo.parser._functionFromScript(s);
+				dojo.connect(wc.prototype, evt, func);
+			});
+		}
+	}
+);
diff --git a/dijit/Dialog.js b/dijit/Dialog.js
index da6b7b5..7ac1b8e 100644
--- a/dijit/Dialog.js
+++ b/dijit/Dialog.js
@@ -1,252 +1,519 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.Dialog"]){
-dojo._hasResource["dijit.Dialog"]=true;
 dojo.provide("dijit.Dialog");
+
 dojo.require("dojo.dnd.move");
 dojo.require("dojo.dnd.TimedMoveable");
 dojo.require("dojo.fx");
+dojo.require("dojo.window");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
+dojo.require("dijit._CssStateMixin");
 dojo.require("dijit.form._FormMixin");
 dojo.require("dijit._DialogMixin");
 dojo.require("dijit.DialogUnderlay");
 dojo.require("dijit.layout.ContentPane");
-dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit._DialogBase",[dijit._Templated,dijit.form._FormMixin,dijit._DialogMixin],{templateString:dojo.cache("dijit","templates/Dialog.html","<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\" doj [...]
-var _1=dojo.i18n.getLocalization("dijit","common");
-dojo.mixin(this,_1);
-this.inherited(arguments);
-},postCreate:function(){
-dojo.style(this.domNode,{display:"none",position:"absolute"});
-dojo.body().appendChild(this.domNode);
-this.inherited(arguments);
-this.connect(this,"onExecute","hide");
-this.connect(this,"onCancel","hide");
-this._modalconnects=[];
-},onLoad:function(){
-this._position();
-this.inherited(arguments);
-},_endDrag:function(e){
-if(e&&e.node&&e.node===this.domNode){
-this._relativePosition=dojo.position(e.node);
-}
-},_setup:function(){
-var _2=this.domNode;
-if(this.titleBar&&this.draggable){
-this._moveable=(dojo.isIE==6)?new dojo.dnd.TimedMoveable(_2,{handle:this.titleBar}):new dojo.dnd.Moveable(_2,{handle:this.titleBar,timeout:0});
-dojo.subscribe("/dnd/move/stop",this,"_endDrag");
-}else{
-dojo.addClass(_2,"dijitDialogFixed");
-}
-this.underlayAttrs={dialogId:this.id,"class":dojo.map(this["class"].split(/\s/),function(s){
-return s+"_underlay";
-}).join(" ")};
-this._fadeIn=dojo.fadeIn({node:_2,duration:this.duration,beforeBegin:dojo.hitch(this,function(){
-var _3=dijit._underlay;
-if(!_3){
-_3=dijit._underlay=new dijit.DialogUnderlay(this.underlayAttrs);
-}else{
-_3.attr(this.underlayAttrs);
-}
-var _4=948+dijit._dialogStack.length*2;
-dojo.style(dijit._underlay.domNode,"zIndex",_4);
-dojo.style(this.domNode,"zIndex",_4+1);
-_3.show();
-}),onEnd:dojo.hitch(this,function(){
-if(this.autofocus){
-this._getFocusItems(this.domNode);
-dijit.focus(this._firstFocusItem);
-}
-})});
-this._fadeOut=dojo.fadeOut({node:_2,duration:this.duration,onEnd:dojo.hitch(this,function(){
-_2.style.display="none";
-var ds=dijit._dialogStack;
-if(ds.length==0){
-dijit._underlay.hide();
-}else{
-dojo.style(dijit._underlay.domNode,"zIndex",948+ds.length*2);
-dijit._underlay.attr(ds[ds.length-1].underlayAttrs);
-}
-if(this.refocus){
-var _5=this._savedFocus;
-if(ds.length>0){
-var pd=ds[ds.length-1];
-if(!dojo.isDescendant(_5.node,pd.domNode)){
-pd._getFocusItems(pd.domNode);
-_5=pd._firstFocusItem;
-}
-}
-dijit.focus(_5);
-}
-})});
-},uninitialize:function(){
-var _6=false;
-if(this._fadeIn&&this._fadeIn.status()=="playing"){
-_6=true;
-this._fadeIn.stop();
-}
-if(this._fadeOut&&this._fadeOut.status()=="playing"){
-_6=true;
-this._fadeOut.stop();
-}
-if((this.open||_6)&&!dijit._underlay._destroyed){
-dijit._underlay.hide();
-}
-if(this._moveable){
-this._moveable.destroy();
-}
-this.inherited(arguments);
-},_size:function(){
-this._checkIfSingleChild();
-if(this._singleChild){
-if(this._singleChildOriginalStyle){
-this._singleChild.domNode.style.cssText=this._singleChildOriginalStyle;
-}
-delete this._singleChildOriginalStyle;
-}else{
-dojo.style(this.containerNode,{width:"auto",height:"auto"});
-}
-var mb=dojo.marginBox(this.domNode);
-var _7=dijit.getViewport();
-if(mb.w>=_7.w||mb.h>=_7.h){
-var w=Math.min(mb.w,Math.floor(_7.w*0.75)),h=Math.min(mb.h,Math.floor(_7.h*0.75));
-if(this._singleChild&&this._singleChild.resize){
-this._singleChildOriginalStyle=this._singleChild.domNode.style.cssText;
-this._singleChild.resize({w:w,h:h});
-}else{
-dojo.style(this.containerNode,{width:w+"px",height:h+"px",overflow:"auto",position:"relative"});
-}
-}else{
-if(this._singleChild&&this._singleChild.resize){
-this._singleChild.resize();
-}
-}
-},_position:function(){
-if(!dojo.hasClass(dojo.body(),"dojoMove")){
-var _8=this.domNode,_9=dijit.getViewport(),p=this._relativePosition,bb=p?null:dojo._getBorderBox(_8),l=Math.floor(_9.l+(p?p.x:(_9.w-bb.w)/2)),t=Math.floor(_9.t+(p?p.y:(_9.h-bb.h)/2));
-dojo.style(_8,{left:l+"px",top:t+"px"});
-}
-},_onKey:function(_a){
-var ds=dijit._dialogStack;
-if(ds[ds.length-1]!=this){
-return;
-}
-if(_a.charOrCode){
-var dk=dojo.keys;
-var _b=_a.target;
-if(_a.charOrCode===dk.TAB){
-this._getFocusItems(this.domNode);
-}
-var _c=(this._firstFocusItem==this._lastFocusItem);
-if(_b==this._firstFocusItem&&_a.shiftKey&&_a.charOrCode===dk.TAB){
-if(!_c){
-dijit.focus(this._lastFocusItem);
-}
-dojo.stopEvent(_a);
-}else{
-if(_b==this._lastFocusItem&&_a.charOrCode===dk.TAB&&!_a.shiftKey){
-if(!_c){
-dijit.focus(this._firstFocusItem);
-}
-dojo.stopEvent(_a);
-}else{
-while(_b){
-if(_b==this.domNode||dojo.hasClass(_b,"dijitPopup")){
-if(_a.charOrCode==dk.ESCAPE){
-this.onCancel();
-}else{
-return;
-}
-}
-_b=_b.parentNode;
-}
-if(_a.charOrCode!==dk.TAB){
-dojo.stopEvent(_a);
-}else{
-if(!dojo.isOpera){
-try{
-this._firstFocusItem.focus();
-}
-catch(e){
-}
-}
-}
-}
-}
-}
-},show:function(){
-if(this.open){
-return;
-}
-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(){
-var _d=dijit.getViewport();
-if(!this._oldViewport||_d.h!=this._oldViewport.h||_d.w!=this._oldViewport.w){
-this.layout();
-this._oldViewport=_d;
-}
-}));
-this._modalconnects.push(dojo.connect(dojo.doc.documentElement,"onkeypress",this,"_onKey"));
-dojo.style(this.domNode,{opacity:0,display:""});
-this.open=true;
-this._onShow();
-this._size();
-this._position();
-dijit._dialogStack.push(this);
-this._fadeIn.play();
-this._savedFocus=dijit.getFocus(this);
-},hide:function(){
-var ds=dijit._dialogStack;
-if(!this._alreadyInitialized||this!=ds[ds.length-1]){
-return;
-}
-if(this._fadeIn.status()=="playing"){
-this._fadeIn.stop();
-}
-ds.pop();
-this._fadeOut.play();
-if(this._scrollConnected){
-this._scrollConnected=false;
-}
-dojo.forEach(this._modalconnects,dojo.disconnect);
-this._modalconnects=[];
-if(this._relativePosition){
-delete this._relativePosition;
-}
-this.open=false;
-this.onHide();
-},layout:function(){
-if(this.domNode.style.display!="none"){
-if(dijit._underlay){
-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(){
-dojo.addClass(this.closeButtonNode,"dijitDialogCloseIcon-hover");
-},_onCloseLeave:function(){
-dojo.removeClass(this.closeButtonNode,"dijitDialogCloseIcon-hover");
-}});
-dojo.declare("dijit.Dialog",[dijit.layout.ContentPane,dijit._DialogBase],{});
-dijit._dialogStack=[];
+dojo.requireLocalization("dijit", "common");
+
+/*=====
+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._DialogBase",
+	[dijit._Templated, dijit.form._FormMixin, dijit._DialogMixin, dijit._CssStateMixin],
+	{
+		// 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: dojo.cache("dijit", "templates/Dialog.html"),
+		
+		baseClass: "dijitDialog",
+		
+		cssStateNodes: {
+			closeButtonNode: "dijitDialogCloseIcon"
+		},
+
+		attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+			title: [
+				{ node: "titleNode", type: "innerHTML" },
+				{ node: "titleBar", type: "attribute" }
+			],
+			"aria-describedby":""
+		}),
+
+		// 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,
+
+		//aria-describedby: String
+		//		Allows the user to add an aria-describedby attribute onto the dialog.   The value should
+		//		be the id of the container element of text that describes the dialog purpose (usually
+		//		the first text in the dialog).
+		//		<div dojoType="dijit.Dialog" aria-describedby="intro" .....>
+		//			<div id="intro">Introductory text</div>
+		//			<div>rest of dialog contents</div>
+		//		</div>
+		"aria-describedby":"",
+
+		postMixInProperties: function(){
+			var _nlsResources = dojo.i18n.getLocalization("dijit", "common");
+			dojo.mixin(this, _nlsResources);
+			this.inherited(arguments);
+		},
+
+		postCreate: function(){
+			dojo.style(this.domNode, {
+				display: "none",
+				position:"absolute"
+			});
+			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
+			// and find the focusable elements
+			this._position();
+			if(this.autofocus){
+				this._getFocusItems(this.domNode);
+				dijit.focus(this._firstFocusItem);
+			}
+			this.inherited(arguments);
+		},
+
+		_endDrag: function(e){
+			// summary:
+			//		Called after dragging the Dialog. Saves the position of the dialog in the viewport.
+			// tags:
+			//		private
+			if(e && e.node && e.node === this.domNode){
+				this._relativePosition = dojo.position(e.node);
+			}
+		},
+
+		_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");
+			}
+
+			this.underlayAttrs = {
+				dialogId: this.id,
+				"class": dojo.map(this["class"].split(/\s/), function(s){ return s+"_underlay"; }).join(" ")
+			};
+
+			this._fadeIn = dojo.fadeIn({
+				node: node,
+				duration: this.duration,
+				beforeBegin: dojo.hitch(this, function(){
+					var underlay = dijit._underlay;
+					if(!underlay){
+						underlay = dijit._underlay = new dijit.DialogUnderlay(this.underlayAttrs);
+					}else{
+						underlay.set(this.underlayAttrs);
+					}
+
+					var ds = dijit._dialogStack,
+						zIndex = 948 + ds.length*2;
+					if(ds.length == 1){	// first dialog
+						underlay.show();
+					}
+					dojo.style(dijit._underlay.domNode, 'zIndex', zIndex);
+					dojo.style(this.domNode, 'zIndex', zIndex + 1);
+				}),
+				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: dojo.hitch(this, function(){
+					node.style.display = "none";
+
+					// Restore the previous dialog in the stack, or if this is the only dialog
+					// then restore to original page
+					var ds = dijit._dialogStack;
+					if(ds.length == 0){
+						dijit._underlay.hide();
+					}else{
+						dojo.style(dijit._underlay.domNode, 'zIndex', 948 + ds.length*2);
+						dijit._underlay.set(ds[ds.length-1].underlayAttrs);
+					}
+
+					// Restore focus to wherever it was before this dialog was displayed
+					if(this.refocus){
+						var focus = this._savedFocus;
+
+						// If we are returning control to a previous dialog but for some reason
+						// that dialog didn't have a focused field, set focus to first focusable item.
+						// This situation could happen if two dialogs appeared at nearly the same time,
+						// since a dialog doesn't set it's focus until the fade-in is finished.
+						if(ds.length > 0){
+							var pd = ds[ds.length-1];
+							if(!dojo.isDescendant(focus.node, pd.domNode)){
+								pd._getFocusItems(pd.domNode);
+								focus = pd._firstFocusItem;
+							}
+						}
+
+						dijit.focus(focus);
+					}
+				})
+			 });
+		},
+
+		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();
+			}
+			
+			// Hide the underlay, unless the underlay widget has already been destroyed
+			// because we are being called during page unload (when all widgets are destroyed)
+			if((this.open || wasPlaying) && !dijit._underlay._destroyed){
+				dijit._underlay.hide();
+			}
+
+			if(this._moveable){
+				this._moveable.destroy();
+			}
+			this.inherited(arguments);
+		},
+
+		_size: function(){
+			// summary:
+			// 		If necessary, shrink dialog contents so dialog fits in viewport
+			// tags:
+			//		private
+
+			this._checkIfSingleChild();
+
+			// If we resized the dialog contents earlier, reset them back to original size, so
+			// that if the user later increases the viewport size, the dialog can display w/out a scrollbar.
+			// Need to do this before the dojo.marginBox(this.domNode) call below.
+			if(this._singleChild){
+				if(this._singleChildOriginalStyle){
+					this._singleChild.domNode.style.cssText = this._singleChildOriginalStyle;
+				}
+				delete this._singleChildOriginalStyle;
+			}else{
+				dojo.style(this.containerNode, {
+					width:"auto",
+					height:"auto"
+				});
+			}
+
+			var mb = dojo.marginBox(this.domNode);
+			var viewport = dojo.window.getBox();
+			if(mb.w >= viewport.w || mb.h >= viewport.h){
+				// Reduce size of dialog contents so that dialog fits in viewport
+
+				var w = Math.min(mb.w, Math.floor(viewport.w * 0.75)),
+					h = Math.min(mb.h, Math.floor(viewport.h * 0.75));
+
+				if(this._singleChild && this._singleChild.resize){
+					this._singleChildOriginalStyle = this._singleChild.domNode.style.cssText;
+					this._singleChild.resize({w: w, h: h});
+				}else{
+					dojo.style(this.containerNode, {
+						width: w + "px",
+						height: h + "px",
+						overflow: "auto",
+						position: "relative"	// workaround IE bug moving scrollbar or dragging dialog
+					});
+				}
+			}else{
+				if(this._singleChild && this._singleChild.resize){
+					this._singleChild.resize();
+				}
+			}
+		},
+
+		_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,
+					viewport = dojo.window.getBox(),
+					p = this._relativePosition,
+					bb = p ? null : dojo._getBorderBox(node),
+					l = Math.floor(viewport.l + (p ? p.x : (viewport.w - bb.w) / 2)),
+					t = Math.floor(viewport.t + (p ? p.y : (viewport.h - bb.h) / 2))
+				;
+				dojo.style(node,{
+					left: l + "px",
+					top: t + "px"
+				});
+			}
+		},
+
+		_onKey: function(/*Event*/ evt){
+			// summary:
+			//		Handles the keyboard events for accessibility reasons
+			// tags:
+			//		private
+
+			var ds = dijit._dialogStack;
+			if(ds[ds.length-1] != this){
+				// console.debug(this.id + ': skipping because', this, 'is not the active dialog');
+				return;
+			}
+
+			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 || dojo.hasClass(node, "dijitPopup")){
+							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 = dojo.window.getBox();
+				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,
+				display:""
+			});
+
+			this.open = true;
+			this._onShow(); // lazy load trigger
+
+			this._size();
+			this._position();
+			dijit._dialogStack.push(this);
+			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
+			// or if we aren't the active dialog, don't allow us to close yet
+			var ds = dijit._dialogStack;
+			if(!this._alreadyInitialized || this != ds[ds.length-1]){
+				return;
+			}
+
+			if(this._fadeIn.status() == "playing"){
+				this._fadeIn.stop();
+			}
+
+			// throw away current active dialog from stack -- making the previous dialog or the node on the original page active
+			ds.pop();
+
+			this._fadeOut.play();
+
+			if(this._scrollConnected){
+				this._scrollConnected = false;
+			}
+			dojo.forEach(this._modalconnects, dojo.disconnect);
+			this._modalconnects = [];
+
+			if(this._relativePosition){
+				delete this._relativePosition;
+			}
+			this.open = false;
+
+			this.onHide();
+		},
+
+		layout: function(){
+			// summary:
+			//		Position the Dialog and the underlay
+			// tags:
+			//		private
+			if(this.domNode.style.display != "none"){
+				if(dijit._underlay){	// avoid race condition during show()
+					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);
+		}
+	}
+);
+
+dojo.declare(
+	"dijit.Dialog",
+	[dijit.layout.ContentPane, dijit._DialogBase],
+	{}
+);
+
+// Stack of currenctly displayed dialogs, layered on top of each other
+dijit._dialogStack = [];
+
+// For back-compat.  TODO: remove in 2.0
 dojo.require("dijit.TooltipDialog");
-}
diff --git a/dijit/DialogUnderlay.js b/dijit/DialogUnderlay.js
index 99405b9..89c9d26 100644
--- a/dijit/DialogUnderlay.js
+++ b/dijit/DialogUnderlay.js
@@ -1,41 +1,106 @@
-/*
-	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
-*/
+dojo.provide("dijit.DialogUnderlay");
 
+dojo.require("dojo.window");
 
-if(!dojo._hasResource["dijit.DialogUnderlay"]){
-dojo._hasResource["dijit.DialogUnderlay"]=true;
-dojo.provide("dijit.DialogUnderlay");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.declare("dijit.DialogUnderlay",[dijit._Widget,dijit._Templated],{templateString:"<div class='dijitDialogUnderlayWrapper'><div class='dijitDialogUnderlay' dojoAttachPoint='node'></div></div>",dialogId:"","class":"",attributeMap:{id:"domNode"},_setDialogIdAttr:function(id){
-dojo.attr(this.node,"id",id+"_underlay");
-},_setClassAttr:function(_1){
-this.node.className="dijitDialogUnderlay "+_1;
-},postCreate:function(){
-dojo.body().appendChild(this.domNode);
-},layout:function(){
-var is=this.node.style,os=this.domNode.style;
-os.display="none";
-var _2=dijit.getViewport();
-os.top=_2.t+"px";
-os.left=_2.l+"px";
-is.width=_2.w+"px";
-is.height=_2.h+"px";
-os.display="block";
-},show:function(){
-this.domNode.style.display="block";
-this.layout();
-this.bgIframe=new dijit.BackgroundIframe(this.domNode);
-},hide:function(){
-this.bgIframe.destroy();
-this.domNode.style.display="none";
-},uninitialize:function(){
-if(this.bgIframe){
-this.bgIframe.destroy();
-}
-this.inherited(arguments);
-}});
-}
+
+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);
+		},
+
+		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 = dojo.window.getBox();
+			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();
+			this.bgIframe = new dijit.BackgroundIframe(this.domNode);
+		},
+
+		hide: function(){
+			// summary:
+			//		Hides the dialog underlay
+			this.bgIframe.destroy();
+			this.domNode.style.display = "none";
+		},
+
+		uninitialize: function(){
+			if(this.bgIframe){
+				this.bgIframe.destroy();
+			}
+			this.inherited(arguments);
+		}
+	}
+);
diff --git a/dijit/Editor.js b/dijit/Editor.js
index 459e66a..ff894ee 100644
--- a/dijit/Editor.js
+++ b/dijit/Editor.js
@@ -1,14 +1,6 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.Editor"]){
-dojo._hasResource["dijit.Editor"]=true;
 dojo.provide("dijit.Editor");
 dojo.require("dijit._editor.RichText");
+
 dojo.require("dijit.Toolbar");
 dojo.require("dijit.ToolbarSeparator");
 dojo.require("dijit._editor._Plugin");
@@ -16,345 +8,747 @@ dojo.require("dijit._editor.plugins.EnterKeyHandling");
 dojo.require("dijit._editor.range");
 dojo.require("dijit._Container");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dijit._editor","commands",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit.Editor",dijit._editor.RichText,{plugins:null,extraPlugins:null,constructor:function(){
-if(!dojo.isArray(this.plugins)){
-this.plugins=["undo","redo","|","cut","copy","paste","|","bold","italic","underline","strikethrough","|","insertOrderedList","insertUnorderedList","indent","outdent","|","justifyLeft","justifyRight","justifyCenter","justifyFull","dijit._editor.plugins.EnterKeyHandling"];
-}
-this._plugins=[];
-this._editInterval=this.editActionInterval*1000;
-if(dojo.isIE){
-this.events.push("onBeforeDeactivate");
-this.events.push("onBeforeActivate");
-}
-},postCreate:function(){
-if(this.customUndo){
-dojo["require"]("dijit._editor.range");
-this._steps=this._steps.slice(0);
-this._undoedSteps=this._undoedSteps.slice(0);
-}
-if(dojo.isArray(this.extraPlugins)){
-this.plugins=this.plugins.concat(this.extraPlugins);
-}
-this.inherited(arguments);
-this.commands=dojo.i18n.getLocalization("dijit._editor","commands",this.lang);
-if(!this.toolbar){
-this.toolbar=new dijit.Toolbar({});
-dojo.place(this.toolbar.domNode,this.editingArea,"before");
-}
-dojo.forEach(this.plugins,this.addPlugin,this);
-this.onNormalizedDisplayChanged();
-this.toolbar.startup();
-},destroy:function(){
-dojo.forEach(this._plugins,function(p){
-if(p&&p.destroy){
-p.destroy();
-}
-});
-this._plugins=[];
-this.toolbar.destroyRecursive();
-delete this.toolbar;
-this.inherited(arguments);
-},addPlugin:function(_1,_2){
-var _3=dojo.isString(_1)?{name:_1}:_1;
-if(!_3.setEditor){
-var o={"args":_3,"plugin":null,"editor":this};
-dojo.publish(dijit._scopeName+".Editor.getPlugin",[o]);
-if(!o.plugin){
-var pc=dojo.getObject(_3.name);
-if(pc){
-o.plugin=new pc(_3);
-}
-}
-if(!o.plugin){
-console.warn("Cannot find plugin",_1);
-return;
-}
-_1=o.plugin;
-}
-if(arguments.length>1){
-this._plugins[_2]=_1;
-}else{
-this._plugins.push(_1);
-}
-_1.setEditor(this);
-if(dojo.isFunction(_1.setToolbar)){
-_1.setToolbar(this.toolbar);
-}
-},startup:function(){
-},resize:function(_4){
-if(_4){
-dijit.layout._LayoutWidget.prototype.resize.apply(this,arguments);
-}
-},layout:function(){
-this.editingArea.style.height=(this._contentBox.h-dojo.marginBox(this.toolbar.domNode).h)+"px";
-if(this.iframe){
-this.iframe.style.height="100%";
-}
-this._layoutMode=true;
-},_onIEMouseDown:function(e){
-var _5=this.document.body.componentFromPoint(e.x,e.y);
-if(!_5){
-delete this._savedSelection;
-if(e.target.tagName=="BODY"){
-setTimeout(dojo.hitch(this,"placeCursorAtEnd"),0);
-}
-this.inherited(arguments);
-}
-},onBeforeActivate:function(e){
-this._restoreSelection();
-},onBeforeDeactivate:function(e){
-if(this.customUndo){
-this.endEditing(true);
-}
-if(e.target.tagName!="BODY"){
-this._saveSelection();
-}
-},customUndo:dojo.isIE,editActionInterval:3,beginEditing:function(_6){
-if(!this._inEditing){
-this._inEditing=true;
-this._beginEditing(_6);
-}
-if(this.editActionInterval>0){
-if(this._editTimer){
-clearTimeout(this._editTimer);
-}
-this._editTimer=setTimeout(dojo.hitch(this,this.endEditing),this._editInterval);
-}
-},_steps:[],_undoedSteps:[],execCommand:function(_7){
-if(this.customUndo&&(_7=="undo"||_7=="redo")){
-return this[_7]();
-}else{
-if(this.customUndo){
-this.endEditing();
-this._beginEditing();
-}
-var r;
-try{
-r=this.inherited("execCommand",arguments);
-if(dojo.isWebKit&&_7=="paste"&&!r){
-throw {code:1011};
-}
-}
-catch(e){
-if(e.code==1011&&/copy|cut|paste/.test(_7)){
-var _8=dojo.string.substitute,_9={cut:"X",copy:"C",paste:"V"};
-alert(_8(this.commands.systemShortcut,[this.commands[_7],_8(this.commands[dojo.isMac?"appleKey":"ctrlKey"],[_9[_7]])]));
-}
-r=false;
-}
-if(this.customUndo){
-this._endEditing();
-}
-return r;
-}
-},queryCommandEnabled:function(_a){
-if(this.customUndo&&(_a=="undo"||_a=="redo")){
-return _a=="undo"?(this._steps.length>1):(this._undoedSteps.length>0);
-}else{
-return this.inherited("queryCommandEnabled",arguments);
-}
-},_moveToBookmark:function(b){
-var _b=b.mark;
-var _c=b.mark;
-var _d=b.isCollapsed;
-if(dojo.isIE){
-if(dojo.isArray(_c)){
-_b=[];
-dojo.forEach(_c,function(n){
-_b.push(dijit.range.getNode(n,this.editNode));
-},this);
-}
-}else{
-var r=dijit.range.create(this.window);
-r.setStart(dijit.range.getNode(b.startContainer,this.editNode),b.startOffset);
-r.setEnd(dijit.range.getNode(b.endContainer,this.editNode),b.endOffset);
-_b=r;
-}
-dojo.withGlobal(this.window,"moveToBookmark",dijit,[{mark:_b,isCollapsed:_d}]);
-},_changeToStep:function(_e,to){
-this.setValue(to.text);
-var b=to.bookmark;
-if(!b){
-return;
-}
-this._moveToBookmark(b);
-},undo:function(){
-this.endEditing(true);
-var s=this._steps.pop();
-if(this._steps.length>0){
-this.focus();
-this._changeToStep(s,this._steps[this._steps.length-1]);
-this._undoedSteps.push(s);
-this.onDisplayChanged();
-return true;
-}
-return false;
-},redo:function(){
-this.endEditing(true);
-var s=this._undoedSteps.pop();
-if(s&&this._steps.length>0){
-this.focus();
-this._changeToStep(this._steps[this._steps.length-1],s);
-this._steps.push(s);
-this.onDisplayChanged();
-return true;
-}
-return false;
-},endEditing:function(_f){
-if(this._editTimer){
-clearTimeout(this._editTimer);
-}
-if(this._inEditing){
-this._endEditing(_f);
-this._inEditing=false;
-}
-},_getBookmark:function(){
-var b=dojo.withGlobal(this.window,dijit.getBookmark);
-var tmp=[];
-if(b.mark){
-var _10=b.mark;
-if(dojo.isIE){
-if(dojo.isArray(_10)){
-dojo.forEach(_10,function(n){
-tmp.push(dijit.range.getIndex(n,this.editNode).o);
-},this);
-b.mark=tmp;
-}
-}else{
-tmp=dijit.range.getIndex(_10.startContainer,this.editNode).o;
-b.mark={startContainer:tmp,startOffset:_10.startOffset,endContainer:_10.endContainer===_10.startContainer?tmp:dijit.range.getIndex(_10.endContainer,this.editNode).o,endOffset:_10.endOffset};
-}
-}
-return b;
-},_beginEditing:function(cmd){
-if(this._steps.length===0){
-this._steps.push({"text":this.savedContent,"bookmark":this._getBookmark()});
-}
-},_endEditing:function(_11){
-var v=this.getValue(true);
-this._undoedSteps=[];
-this._steps.push({text:v,bookmark:this._getBookmark()});
-},onKeyDown:function(e){
-if(!dojo.isIE&&!this.iframe&&e.keyCode==dojo.keys.TAB&&!this.tabIndent){
-this._saveSelection();
-}
-if(!this.customUndo){
-this.inherited(arguments);
-return;
-}
-var k=e.keyCode,ks=dojo.keys;
-if(e.ctrlKey&&!e.altKey){
-if(k==90||k==122){
-dojo.stopEvent(e);
-this.undo();
-return;
-}else{
-if(k==89||k==121){
-dojo.stopEvent(e);
-this.redo();
-return;
-}
-}
-}
-this.inherited(arguments);
-switch(k){
-case ks.ENTER:
-case ks.BACKSPACE:
-case ks.DELETE:
-this.beginEditing();
-break;
-case 88:
-case 86:
-if(e.ctrlKey&&!e.altKey&&!e.metaKey){
-this.endEditing();
-if(e.keyCode==88){
-this.beginEditing("cut");
-setTimeout(dojo.hitch(this,this.endEditing),1);
-}else{
-this.beginEditing("paste");
-setTimeout(dojo.hitch(this,this.endEditing),1);
-}
-break;
-}
-default:
-if(!e.ctrlKey&&!e.altKey&&!e.metaKey&&(e.keyCode<dojo.keys.F1||e.keyCode>dojo.keys.F15)){
-this.beginEditing();
-break;
-}
-case ks.ALT:
-this.endEditing();
-break;
-case ks.UP_ARROW:
-case ks.DOWN_ARROW:
-case ks.LEFT_ARROW:
-case ks.RIGHT_ARROW:
-case ks.HOME:
-case ks.END:
-case ks.PAGE_UP:
-case ks.PAGE_DOWN:
-this.endEditing(true);
-break;
-case ks.CTRL:
-case ks.SHIFT:
-case ks.TAB:
-break;
-}
-},_onBlur:function(){
-this.inherited("_onBlur",arguments);
-this.endEditing(true);
-},_saveSelection:function(){
-this._savedSelection=this._getBookmark();
-},_restoreSelection:function(){
-if(this._savedSelection){
-if(dojo.withGlobal(this.window,"isCollapsed",dijit)){
-this._moveToBookmark(this._savedSelection);
-}
-delete this._savedSelection;
-}
-},onClick:function(){
-this.endEditing(true);
-this.inherited(arguments);
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _12=o.args,p;
-var _13=dijit._editor._Plugin;
-var _14=_12.name;
-switch(_14){
-case "undo":
-case "redo":
-case "cut":
-case "copy":
-case "paste":
-case "insertOrderedList":
-case "insertUnorderedList":
-case "indent":
-case "outdent":
-case "justifyCenter":
-case "justifyFull":
-case "justifyLeft":
-case "justifyRight":
-case "delete":
-case "selectAll":
-case "removeFormat":
-case "unlink":
-case "insertHorizontalRule":
-p=new _13({command:_14});
-break;
-case "bold":
-case "italic":
-case "underline":
-case "strikethrough":
-case "subscript":
-case "superscript":
-p=new _13({buttonClass:dijit.form.ToggleButton,command:_14});
-break;
-case "|":
-p=new _13({button:new dijit.ToolbarSeparator()});
-}
-o.plugin=p;
+dojo.require("dijit.layout._LayoutWidget");
+dojo.require("dijit._editor.range");
+dojo.requireLocalization("dijit._editor", "commands");
+
+dojo.declare(
+	"dijit.Editor",
+	dijit._editor.RichText,
+	{
+		// summary:
+		//		A rich text Editing widget
+		//
+		// description:
+		//		This widget provides basic WYSIWYG editing features, based on the browser's
+		//		underlying rich text editing capability, accompanied by a toolbar (`dijit.Toolbar`).
+		//		A plugin model is available to extend the editor's capabilities as well as the
+		//		the options available in the toolbar.  Content generation may vary across
+		//		browsers, and clipboard operations may have different results, to name
+		//		a few limitations.  Note: this widget should not be used with the HTML
+		//		<TEXTAREA> tag -- see dijit._editor.RichText for details.
+
+		// plugins: Object[]
+		//		A list of plugin names (as strings) or instances (as objects)
+		//		for this widget.
+		//
+		//		When declared in markup, it might look like:
+		//	|	plugins="['bold',{name:'dijit._editor.plugins.FontChoice', command:'fontName', generic:true}]"
+		plugins: null,
+
+		// extraPlugins: Object[]
+		//		A list of extra plugin names which will be appended to plugins array
+		extraPlugins: null,
+
+		constructor: function(){
+			// summary:
+			//		Runs on widget initialization to setup arrays etc.
+			// tags:
+			//		private
+
+			if(!dojo.isArray(this.plugins)){
+				this.plugins=["undo","redo","|","cut","copy","paste","|","bold","italic","underline","strikethrough","|",
+				"insertOrderedList","insertUnorderedList","indent","outdent","|","justifyLeft","justifyRight","justifyCenter","justifyFull",
+				"dijit._editor.plugins.EnterKeyHandling" /*, "createLink"*/];
+			}
+
+			this._plugins=[];
+			this._editInterval = this.editActionInterval * 1000;
+
+			//IE will always lose focus when other element gets focus, while for FF and safari,
+			//when no iframe is used, focus will be lost whenever another element gets focus.
+			//For IE, we can connect to onBeforeDeactivate, which will be called right before
+			//the focus is lost, so we can obtain the selected range. For other browsers,
+			//no equivelent of onBeforeDeactivate, so we need to do two things to make sure
+			//selection is properly saved before focus is lost: 1) when user clicks another
+			//element in the page, in which case we listen to mousedown on the entire page and
+			//see whether user clicks out of a focus editor, if so, save selection (focus will
+			//only lost after onmousedown event is fired, so we can obtain correct caret pos.)
+			//2) when user tabs away from the editor, which is handled in onKeyDown below.
+			if(dojo.isIE){
+				this.events.push("onBeforeDeactivate");
+				this.events.push("onBeforeActivate");
+			}
+		},
+
+		postCreate: function(){
+			//for custom undo/redo, if enabled.
+			this._steps=this._steps.slice(0);
+			this._undoedSteps=this._undoedSteps.slice(0);
+
+			if(dojo.isArray(this.extraPlugins)){
+				this.plugins=this.plugins.concat(this.extraPlugins);
+			}
+
+			// Set up a deferred so that the value isn't applied to the editor 
+			// until all the plugins load, needed to avoid timing condition
+			// reported in #10537.
+			this.setValueDeferred = new dojo.Deferred();
+
+			this.inherited(arguments);
+
+			this.commands = dojo.i18n.getLocalization("dijit._editor", "commands", this.lang);
+
+			if(!this.toolbar){
+				// if we haven't been assigned a toolbar, create one
+				this.toolbar = new dijit.Toolbar({
+					dir: this.dir,
+					lang: this.lang
+				});
+				this.header.appendChild(this.toolbar.domNode);
+			}
+
+			dojo.forEach(this.plugins, this.addPlugin, this);
+
+			// Okay, denote the value can now be set.
+			this.setValueDeferred.callback(true);
+
+			dojo.addClass(this.iframe.parentNode, "dijitEditorIFrameContainer");
+			dojo.addClass(this.iframe, "dijitEditorIFrame");
+			dojo.attr(this.iframe, "allowTransparency", true);
+
+			if(dojo.isWebKit){
+				// Disable selecting the entire editor by inadvertant double-clicks.
+				// on buttons, title bar, etc.  Otherwise clicking too fast on
+				// a button such as undo/redo selects the entire editor.
+				dojo.style(this.domNode, "KhtmlUserSelect", "none");
+			}
+			this.toolbar.startup();
+			this.onNormalizedDisplayChanged(); //update toolbar button status
+		},
+		destroy: function(){
+			dojo.forEach(this._plugins, function(p){
+				if(p && p.destroy){
+					p.destroy();
+				}
+			});
+			this._plugins=[];
+			this.toolbar.destroyRecursive();
+			delete this.toolbar;
+			this.inherited(arguments);
+		},
+		addPlugin: function(/*String||Object*/plugin, /*Integer?*/index){
+			// summary:
+			//		takes a plugin name as a string or a plugin instance and
+			//		adds it to the toolbar and associates it with this editor
+			//		instance. The resulting plugin is added to the Editor's
+			//		plugins array. If index is passed, it's placed in the plugins
+			//		array at that index. No big magic, but a nice helper for
+			//		passing in plugin names via markup.
+			//
+			// plugin: String, args object or plugin instance
+			//
+			// args:
+			//		This object will be passed to the plugin constructor
+			//
+			// index: Integer
+			//		Used when creating an instance from
+			//		something already in this.plugins. Ensures that the new
+			//		instance is assigned to this.plugins at that index.
+			var args=dojo.isString(plugin)?{name:plugin}:plugin;
+			if(!args.setEditor){
+				var o={"args":args,"plugin":null,"editor":this};
+				dojo.publish(dijit._scopeName + ".Editor.getPlugin",[o]);
+				if(!o.plugin){
+					var pc = dojo.getObject(args.name);
+					if(pc){
+						o.plugin=new pc(args);
+					}
+				}
+				if(!o.plugin){
+					console.warn('Cannot find plugin',plugin);
+					return;
+				}
+				plugin=o.plugin;
+			}
+			if(arguments.length > 1){
+				this._plugins[index] = plugin;
+			}else{
+				this._plugins.push(plugin);
+			}
+			plugin.setEditor(this);
+			if(dojo.isFunction(plugin.setToolbar)){
+				plugin.setToolbar(this.toolbar);
+			}
+		},
+		//the following 3 functions are required to make the editor play nice under a layout widget, see #4070
+		startup: function(){
+			// summary:
+			//		Exists to make Editor work as a child of a layout widget.
+			//		Developers don't need to call this method.
+			// tags:
+			//		protected
+			//console.log('startup',arguments);
+		},
+		resize: function(size){
+			// summary:
+			//		Resize the editor to the specified size, see `dijit.layout._LayoutWidget.resize`
+			if(size){
+				// we've been given a height/width for the entire editor (toolbar + contents), calls layout()
+				// to split the allocated size between the toolbar and the contents
+				dijit.layout._LayoutWidget.prototype.resize.apply(this, arguments);
+			}
+			/*
+			else{
+				// do nothing, the editor is already laid out correctly.   The user has probably specified
+				// the height parameter, which was used to set a size on the iframe
+			}
+			*/
+		},
+		layout: function(){
+			// summary:
+			//		Called from `dijit.layout._LayoutWidget.resize`.  This shouldn't be called directly
+			// tags:
+			//		protected
+
+			// Converts the iframe (or rather the <div> surrounding it) to take all the available space
+			// except what's needed for the header (toolbars) and footer (breadcrumbs, etc).
+			// A class was added to the iframe container and some themes style it, so we have to
+			// calc off the added margins and padding too. See tracker: #10662
+			var areaHeight = (this._contentBox.h - 
+				(this.getHeaderHeight() + this.getFooterHeight() + 
+				 dojo._getPadBorderExtents(this.iframe.parentNode).h +
+				 dojo._getMarginExtents(this.iframe.parentNode).h));
+			this.editingArea.style.height = areaHeight + "px";
+			if(this.iframe){
+				this.iframe.style.height="100%";
+			}
+			this._layoutMode = true;
+		},
+		_onIEMouseDown: function(/*Event*/ e){
+			// summary:
+			//		IE only to prevent 2 clicks to focus
+			// tags:
+			//		private
+			var outsideClientArea;
+			// IE 8's componentFromPoint is broken, which is a shame since it
+			// was smaller code, but oh well.  We have to do this brute force
+			// to detect if the click was scroller or not.
+			var b = this.document.body;
+			var clientWidth = b.clientWidth;
+			var clientHeight = b.clientHeight;
+			var clientLeft = b.clientLeft;
+			var offsetWidth = b.offsetWidth;
+			var offsetHeight = b.offsetHeight;
+			var offsetLeft = b.offsetLeft;
+
+			//Check for vertical scroller click.
+			bodyDir = b.dir?b.dir.toLowerCase():""
+			if(bodyDir != "rtl"){
+				if(clientWidth < offsetWidth && e.x > clientWidth && e.x < offsetWidth){ 
+					// Check the click was between width and offset width, if so, scroller
+					outsideClientArea = true;
+				}
+			}else{
+				// RTL mode, we have to go by the left offsets.
+				if(e.x < clientLeft && e.x > offsetLeft){
+					// Check the click was between width and offset width, if so, scroller
+					outsideClientArea = true;
+				}
+			}
+			if(!outsideClientArea){
+				// Okay, might be horiz scroller, check that.
+				if(clientHeight < offsetHeight && e.y > clientHeight && e.y < offsetHeight){
+					// Horizontal scroller.
+					outsideClientArea = true;
+				}
+			}
+			if(!outsideClientArea){
+				delete this._cursorToStart; // Remove the force to cursor to start position. 
+				delete this._savedSelection; // new mouse position overrides old selection
+				if(e.target.tagName == "BODY"){
+					setTimeout(dojo.hitch(this, "placeCursorAtEnd"), 0);
+				}
+				this.inherited(arguments);
+			}
+		},
+		onBeforeActivate: function(e){
+			this._restoreSelection();
+		},
+		onBeforeDeactivate: function(e){
+			// summary:
+			//		Called on IE right before focus is lost.   Saves the selected range.
+			// tags:
+			//		private
+			if(this.customUndo){
+				this.endEditing(true);
+			}
+			//in IE, the selection will be lost when other elements get focus,
+			//let's save focus before the editor is deactivated
+			if(e.target.tagName != "BODY"){
+				this._saveSelection();
+			}
+			//console.log('onBeforeDeactivate',this);
+		},
+
+		/* beginning of custom undo/redo support */
+
+		// customUndo: Boolean
+		//		Whether we shall use custom undo/redo support instead of the native
+		//		browser support. By default, we only enable customUndo for IE, as it
+		//		has broken native undo/redo support. Note: the implementation does
+		//		support other browsers which have W3C DOM2 Range API implemented.
+		//		It was also enabled on WebKit, to fix undo/redo enablement. (#9613)
+		customUndo: dojo.isIE || dojo.isWebKit,
+
+		// editActionInterval: Integer
+		//		When using customUndo, not every keystroke will be saved as a step.
+		//		Instead typing (including delete) will be grouped together: after
+		//		a user stops typing for editActionInterval seconds, a step will be
+		//		saved; if a user resume typing within editActionInterval seconds,
+		//		the timeout will be restarted. By default, editActionInterval is 3
+		//		seconds.
+		editActionInterval: 3,
+
+		beginEditing: function(cmd){
+			// summary:
+			//		Called to note that the user has started typing alphanumeric characters, if it's not already noted.
+			//		Deals with saving undo; see editActionInterval parameter.
+			// tags:
+			//		private
+			if(!this._inEditing){
+				this._inEditing=true;
+				this._beginEditing(cmd);
+			}
+			if(this.editActionInterval>0){
+				if(this._editTimer){
+					clearTimeout(this._editTimer);
+				}
+				this._editTimer = setTimeout(dojo.hitch(this, this.endEditing), this._editInterval);
+			}
+		},
+		_steps:[],
+		_undoedSteps:[],
+		execCommand: function(cmd){
+			// summary:
+			//		Main handler for executing any commands to the editor, like paste, bold, etc.
+			//      Called by plugins, but not meant to be called by end users.
+			// tags:
+			//		protected
+			if(this.customUndo && (cmd == 'undo' || cmd == 'redo')){
+				return this[cmd]();
+			}else{
+				if(this.customUndo){
+					this.endEditing();
+					this._beginEditing();
+				}
+				var r;
+				try{
+					r = this.inherited('execCommand', arguments);
+					if(dojo.isWebKit && cmd == 'paste' && !r){ //see #4598: safari does not support invoking paste from js
+						throw { code: 1011 }; // throw an object like Mozilla's error
+					}
+				}catch(e){
+					//TODO: when else might we get an exception?  Do we need the Mozilla test below?
+					if(e.code == 1011 /* Mozilla: service denied */ && /copy|cut|paste/.test(cmd)){
+						// Warn user of platform limitation.  Cannot programmatically access clipboard. See ticket #4136
+						var sub = dojo.string.substitute,
+							accel = {cut:'X', copy:'C', paste:'V'};
+						alert(sub(this.commands.systemShortcut,
+							[this.commands[cmd], sub(this.commands[dojo.isMac ? 'appleKey' : 'ctrlKey'], [accel[cmd]])]));
+					}
+					r = false;
+				}
+				if(this.customUndo){
+					this._endEditing();
+				}
+				return r;
+			}
+		},
+		queryCommandEnabled: function(cmd){
+			// summary:
+			//		Returns true if specified editor command is enabled.
+			//      Used by the plugins to know when to highlight/not highlight buttons.
+			// tags:
+			//		protected
+			if(this.customUndo && (cmd == 'undo' || cmd == 'redo')){
+				return cmd == 'undo' ? (this._steps.length > 1) : (this._undoedSteps.length > 0);
+			}else{
+				return this.inherited('queryCommandEnabled',arguments);
+			}
+		},
+		_moveToBookmark: function(b){
+			// summary:
+			//		Selects the text specified in bookmark b
+			// tags:
+			//		private
+			var bookmark = b.mark;
+			var mark = b.mark;
+			var col = b.isCollapsed;
+			var r, sNode, eNode, sel;
+			if(mark){
+				if(dojo.isIE){
+					if(dojo.isArray(mark)){
+						//IE CONTROL, have to use the native bookmark.
+						bookmark = [];
+						dojo.forEach(mark,function(n){
+							bookmark.push(dijit.range.getNode(n,this.editNode));
+						},this);
+						dojo.withGlobal(this.window,'moveToBookmark',dijit,[{mark: bookmark, isCollapsed: col}]);
+					}else{
+						if(mark.startContainer && mark.endContainer){
+							// Use the pseudo WC3 range API.  This works better for positions
+							// than the IE native bookmark code.
+							sel = dijit.range.getSelection(this.window);
+							if(sel && sel.removeAllRanges){
+								sel.removeAllRanges();
+								r = dijit.range.create(this.window);
+								sNode = dijit.range.getNode(mark.startContainer,this.editNode);
+								eNode = dijit.range.getNode(mark.endContainer,this.editNode);
+								if(sNode && eNode){
+									// Okay, we believe we found the position, so add it into the selection
+									// There are cases where it may not be found, particularly in undo/redo, when
+									// IE changes the underlying DOM on us (wraps text in a <p> tag or similar.
+									// So, in those cases, don't bother restoring selection.
+									r.setStart(sNode,mark.startOffset);
+									r.setEnd(eNode,mark.endOffset);
+									sel.addRange(r);
+								}
+							}
+						}
+					}
+				}else{//w3c range
+					sel = dijit.range.getSelection(this.window);
+					if(sel && sel.removeAllRanges){
+						sel.removeAllRanges();
+						r = dijit.range.create(this.window);
+						sNode = dijit.range.getNode(mark.startContainer,this.editNode);
+						eNode = dijit.range.getNode(mark.endContainer,this.editNode);
+						if(sNode && eNode){
+							// Okay, we believe we found the position, so add it into the selection
+							// There are cases where it may not be found, particularly in undo/redo, when
+							// formatting as been done and so on, so don't restore selection then.
+							r.setStart(sNode,mark.startOffset);
+							r.setEnd(eNode,mark.endOffset);
+							sel.addRange(r);
+						}
+					}
+				}
+			}
+		},
+		_changeToStep: function(from, to){
+			// summary:
+			//		Reverts editor to "to" setting, from the undo stack.
+			// tags:
+			//		private
+			this.setValue(to.text);
+			var b=to.bookmark;
+			if(!b){ return; }
+			this._moveToBookmark(b);
+		},
+		undo: function(){
+			// summary:
+			//		Handler for editor undo (ex: ctrl-z) operation
+			// tags:
+			//		private
+			//console.log('undo');
+			var ret = false;
+			if(!this._undoRedoActive){
+				this._undoRedoActive = true;
+				this.endEditing(true);
+				var s=this._steps.pop();
+				if(s && this._steps.length>0){
+					this.focus();
+					this._changeToStep(s,this._steps[this._steps.length-1]);
+					this._undoedSteps.push(s);
+					this.onDisplayChanged();
+					delete this._undoRedoActive;
+					ret = true;
+				}
+				delete this._undoRedoActive;
+			}	
+			return ret;
+		},
+		redo: function(){
+			// summary:
+			//		Handler for editor redo (ex: ctrl-y) operation
+			// tags:
+			//		private
+			//console.log('redo');
+			var ret = false;
+			if(!this._undoRedoActive){
+				this._undoRedoActive = true;
+				this.endEditing(true);
+				var s=this._undoedSteps.pop();
+				if(s && this._steps.length>0){
+					this.focus();
+					this._changeToStep(this._steps[this._steps.length-1],s);
+					this._steps.push(s);
+					this.onDisplayChanged();
+					ret = true;
+				}
+				delete this._undoRedoActive;
+			}
+			return ret;
+		},
+		endEditing: function(ignore_caret){
+			// summary:
+			//		Called to note that the user has stopped typing alphanumeric characters, if it's not already noted.
+			//		Deals with saving undo; see editActionInterval parameter.
+			// tags:
+			//		private
+			if(this._editTimer){
+				clearTimeout(this._editTimer);
+			}
+			if(this._inEditing){
+				this._endEditing(ignore_caret);
+				this._inEditing=false;
+			}
+		},
+
+		_getBookmark: function(){
+			// summary:
+			//		Get the currently selected text
+			// tags:
+			//		protected
+			var b=dojo.withGlobal(this.window,dijit.getBookmark);
+			var tmp=[];
+			if(b && b.mark){
+				var mark = b.mark;
+				if(dojo.isIE){
+					// Try to use the pseudo range API on IE for better accuracy.
+					var sel = dijit.range.getSelection(this.window);
+					if(!dojo.isArray(mark)){
+						if(sel){
+							var range;
+							if(sel.rangeCount){
+								range = sel.getRangeAt(0);
+							}
+							if(range){
+								b.mark = range.cloneRange();
+							}else{
+								b.mark = dojo.withGlobal(this.window,dijit.getBookmark);
+							}
+						}
+					}else{
+						// Control ranges (img, table, etc), handle differently.
+						dojo.forEach(b.mark,function(n){
+							tmp.push(dijit.range.getIndex(n,this.editNode).o);
+						},this);
+						b.mark = tmp;
+					}
+				}
+				try{
+					if(b.mark && b.mark.startContainer){
+						tmp=dijit.range.getIndex(b.mark.startContainer,this.editNode).o;
+						b.mark={startContainer:tmp,
+							startOffset:b.mark.startOffset,
+							endContainer:b.mark.endContainer===b.mark.startContainer?tmp:dijit.range.getIndex(b.mark.endContainer,this.editNode).o,
+							endOffset:b.mark.endOffset};
+					}
+				}catch(e){
+					b.mark = null;
+				}
+			}
+			return b;
+		},
+		_beginEditing: function(cmd){
+			// summary:
+			//		Called when the user starts typing alphanumeric characters.
+			//		Deals with saving undo; see editActionInterval parameter.
+			// tags:
+			//		private
+			if(this._steps.length === 0){
+				// You want to use the editor content without post filtering
+				// to make sure selection restores right for the 'initial' state.
+				// and undo is called.  So not using this.savedContent, as it was 'processed'
+				// and the line-up for selections may have been altered.
+				this._steps.push({'text':dijit._editor.getChildrenHtml(this.editNode),'bookmark':this._getBookmark()});
+			}
+		},
+		_endEditing: function(ignore_caret){
+			// summary:
+			//		Called when the user stops typing alphanumeric characters.
+			//		Deals with saving undo; see editActionInterval parameter.
+			// tags:
+			//		private
+			// Avoid filtering to make sure selections restore.
+			var v = dijit._editor.getChildrenHtml(this.editNode);
+
+			this._undoedSteps=[];//clear undoed steps
+			this._steps.push({text: v, bookmark: this._getBookmark()});
+		},
+		onKeyDown: function(e){
+			// summary:
+			//		Handler for onkeydown event.
+			// tags:
+			//		private
+
+			//We need to save selection if the user TAB away from this editor
+			//no need to call _saveSelection for IE, as that will be taken care of in onBeforeDeactivate
+			if(!dojo.isIE && !this.iframe && e.keyCode == dojo.keys.TAB && !this.tabIndent){
+				this._saveSelection();
+			}
+			if(!this.customUndo){
+				this.inherited(arguments);
+				return;
+			}
+			var k = e.keyCode, ks = dojo.keys;
+			if(e.ctrlKey && !e.altKey){//undo and redo only if the special right Alt + z/y are not pressed #5892
+				if(k == 90 || k == 122){ //z
+					dojo.stopEvent(e);
+					this.undo();
+					return;
+				}else if(k == 89 || k == 121){ //y
+					dojo.stopEvent(e);
+					this.redo();
+					return;
+				}
+			}
+			this.inherited(arguments);
+
+			switch(k){
+					case ks.ENTER:
+					case ks.BACKSPACE:
+					case ks.DELETE:
+						this.beginEditing();
+						break;
+					case 88: //x
+					case 86: //v
+						if(e.ctrlKey && !e.altKey && !e.metaKey){
+							this.endEditing();//end current typing step if any
+							if(e.keyCode == 88){
+								this.beginEditing('cut');
+								//use timeout to trigger after the cut is complete
+								setTimeout(dojo.hitch(this, this.endEditing), 1);
+							}else{
+								this.beginEditing('paste');
+								//use timeout to trigger after the paste is complete
+								setTimeout(dojo.hitch(this, this.endEditing), 1);
+							}
+							break;
+						}
+						//pass through
+					default:
+						if(!e.ctrlKey && !e.altKey && !e.metaKey && (e.keyCode<dojo.keys.F1 || e.keyCode>dojo.keys.F15)){
+							this.beginEditing();
+							break;
+						}
+						//pass through
+					case ks.ALT:
+						this.endEditing();
+						break;
+					case ks.UP_ARROW:
+					case ks.DOWN_ARROW:
+					case ks.LEFT_ARROW:
+					case ks.RIGHT_ARROW:
+					case ks.HOME:
+					case ks.END:
+					case ks.PAGE_UP:
+					case ks.PAGE_DOWN:
+						this.endEditing(true);
+						break;
+					//maybe ctrl+backspace/delete, so don't endEditing when ctrl is pressed
+					case ks.CTRL:
+					case ks.SHIFT:
+					case ks.TAB:
+						break;
+				}
+		},
+		_onBlur: function(){
+			// summary:
+			//		Called from focus manager when focus has moved away from this editor
+			// tags:
+			//		protected
+
+			//this._saveSelection();
+			this.inherited('_onBlur',arguments);
+			this.endEditing(true);
+		},
+		_saveSelection: function(){
+			// summary:
+			//		Save the currently selected text in _savedSelection attribute
+			// tags:
+			//		private
+			this._savedSelection=this._getBookmark();
+			//console.log('save selection',this._savedSelection,this);
+		},
+		_restoreSelection: function(){
+			// summary:
+			//		Re-select the text specified in _savedSelection attribute;
+			//		see _saveSelection().
+			// tags:
+			//		private
+			if(this._savedSelection){
+				// Clear off cursor to start, we're deliberately going to a selection.
+				delete this._cursorToStart;
+				// only restore the selection if the current range is collapsed
+				// if not collapsed, then it means the editor does not lose
+				// selection and there is no need to restore it
+				if(dojo.withGlobal(this.window,'isCollapsed',dijit)){
+					this._moveToBookmark(this._savedSelection);
+				}
+				delete this._savedSelection;
+			}
+		},
+
+		onClick: function(){
+			// summary:
+			//		Handler for when editor is clicked
+			// tags:
+			//		protected
+			this.endEditing(true);
+			this.inherited(arguments);
+		},
+
+		_setDisabledAttr: function(/*Boolean*/ value){
+			if(!this.disabled && value){
+				// Disable editor: disable all enabled buttons and remember that list
+				this._buttonEnabledPlugins = dojo.filter(this._plugins, function(p){
+					if (p && p.button && !p.button.get("disabled")) {
+						p.button.set("disabled", true);
+						return true;
+					}
+					return false;
+				});
+			}else if(this.disabled && !value){
+				// Enable editor: we only want to enable the buttons that should be
+				// enabled (for example, the outdent button shouldn't be enabled if the current
+				// text can't be outdented).
+				dojo.forEach(this._buttonEnabledPlugins, function(p){
+					p.button.attr("disabled", false);
+					p.updateState && p.updateState();	// just in case something changed, like caret position
+				});
+			}
+			
+			this.inherited(arguments);
+		},
+		
+		_setStateClass: function(){
+			this.inherited(arguments);
+			
+			// Let theme set the editor's text color based on editor enabled/disabled state.
+			// We need to jump through hoops because the main document (where the theme CSS is)
+			// is separate from the iframe's document.
+			if(this.document && this.document.body){
+				dojo.style(this.document.body, "color", dojo.style(this.iframe, "color"));
+			}
+		}
+	}
+);
+
+// Register the "default plugins", ie, the built-in editor commands
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var args = o.args, p;
+	var _p = dijit._editor._Plugin;
+	var name = args.name;
+	switch(name){
+		case "undo": case "redo": case "cut": case "copy": case "paste": case "insertOrderedList":
+		case "insertUnorderedList": case "indent": case "outdent": case "justifyCenter":
+		case "justifyFull": case "justifyLeft": case "justifyRight": case "delete":
+		case "selectAll": case "removeFormat": case "unlink":
+		case "insertHorizontalRule":
+			p = new _p({ command: name });
+			break;
+
+		case "bold": case "italic": case "underline": case "strikethrough":
+		case "subscript": case "superscript":
+			p = new _p({ buttonClass: dijit.form.ToggleButton, command: name });
+			break;
+		case "|":
+			p = new _p({ button: new dijit.ToolbarSeparator(), setEditor: function(editor) {this.editor = editor;} });
+	}
+//	console.log('name',name,p);
+	o.plugin=p;
 });
-}
diff --git a/dijit/InlineEditBox.js b/dijit/InlineEditBox.js
index 768d525..6413676 100644
--- a/dijit/InlineEditBox.js
+++ b/dijit/InlineEditBox.js
@@ -1,220 +1,562 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.InlineEditBox"]){
-dojo._hasResource["dijit.InlineEditBox"]=true;
 dojo.provide("dijit.InlineEditBox");
+
 dojo.require("dojo.i18n");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Container");
 dojo.require("dijit.form.Button");
 dojo.require("dijit.form.TextBox");
-dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit.InlineEditBox",dijit._Widget,{editing:false,autoSave:true,buttonSave:"",buttonCancel:"",renderAsHtml:false,editor:"dijit.form.TextBox",editorWrapper:"dijit._InlineEditor",editorParams:{},onChange:function(_1){
-},onCancel:function(){
-},width:"100%",value:"",noValueIndicator:"<span style='font-family: wingdings; text-decoration: underline;'>    &#x270d;    </span>",constructor:function(){
-this.editorParams={};
-},postMixInProperties:function(){
-this.inherited(arguments);
-this.displayNode=this.srcNodeRef;
-var _2={ondijitclick:"_onClick",onmouseover:"_onMouseOver",onmouseout:"_onMouseOut",onfocus:"_onMouseOver",onblur:"_onMouseOut"};
-for(var _3 in _2){
-this.connect(this.displayNode,_3,_2[_3]);
-}
-dijit.setWaiRole(this.displayNode,"button");
-if(!this.displayNode.getAttribute("tabIndex")){
-this.displayNode.setAttribute("tabIndex",0);
-}
-this.attr("value",this.value||this.displayNode.innerHTML);
-},setDisabled:function(_4){
-dojo.deprecated("dijit.InlineEditBox.setDisabled() is deprecated.  Use attr('disabled', bool) instead.","","2.0");
-this.attr("disabled",_4);
-},_setDisabledAttr:function(_5){
-this.disabled=_5;
-dijit.setWaiState(this.domNode,"disabled",_5);
-if(_5){
-this.displayNode.removeAttribute("tabIndex");
-}else{
-this.displayNode.setAttribute("tabIndex",0);
-}
-},_onMouseOver:function(){
-dojo.addClass(this.displayNode,this.disabled?"dijitDisabledClickableRegion":"dijitClickableRegion");
-},_onMouseOut:function(){
-dojo.removeClass(this.displayNode,this.disabled?"dijitDisabledClickableRegion":"dijitClickableRegion");
-},_onClick:function(e){
-if(this.disabled){
-return;
-}
-if(e){
-dojo.stopEvent(e);
-}
-this._onMouseOut();
-setTimeout(dojo.hitch(this,"edit"),0);
-},edit:function(){
-if(this.disabled||this.editing){
-return;
-}
-this.editing=true;
-this._savedPosition=dojo.style(this.displayNode,"position")||"static";
-this._savedOpacity=dojo.style(this.displayNode,"opacity")||"1";
-this._savedTabIndex=dojo.attr(this.displayNode,"tabIndex")||"0";
-if(this.wrapperWidget){
-this.wrapperWidget.editWidget.attr("displayedValue" in this.editorParams?"displayedValue":"value",this.value);
-}else{
-var _6=dojo.create("span",null,this.domNode,"before");
-var _7=dojo.getObject(this.editorWrapper);
-this.wrapperWidget=new _7({value:this.value,buttonSave:this.buttonSave,buttonCancel:this.buttonCancel,tabIndex:this._savedTabIndex,editor:this.editor,inlineEditBox:this,sourceStyle:dojo.getComputedStyle(this.displayNode),save:dojo.hitch(this,"save"),cancel:dojo.hitch(this,"cancel")},_6);
-}
-var ww=this.wrapperWidget;
-if(dojo.isIE){
-dijit.focus(dijit.getFocus());
-}
-dojo.style(this.displayNode,{position:"absolute",opacity:"0",display:"none"});
-dojo.style(ww.domNode,{position:this._savedPosition,visibility:"visible",opacity:"1"});
-dojo.attr(this.displayNode,"tabIndex","-1");
-setTimeout(dojo.hitch(this,function(){
-ww.focus();
-ww._resetValue=ww.getValue();
-}),0);
-},_onBlur:function(){
-this.inherited(arguments);
-if(!this.editing){
-setTimeout(dojo.hitch(this,function(){
-if(this.wrapperWidget){
-this.wrapperWidget.destroy();
-delete this.wrapperWidget;
-}
-}),0);
-}
-},_showText:function(_8){
-var ww=this.wrapperWidget;
-dojo.style(ww.domNode,{position:"absolute",visibility:"hidden",opacity:"0"});
-dojo.style(this.displayNode,{position:this._savedPosition,opacity:this._savedOpacity,display:""});
-dojo.attr(this.displayNode,"tabIndex",this._savedTabIndex);
-if(_8){
-dijit.focus(this.displayNode);
-}
-},save:function(_9){
-if(this.disabled||!this.editing){
-return;
-}
-this.editing=false;
-var ww=this.wrapperWidget;
-var _a=ww.getValue();
-this.attr("value",_a);
-setTimeout(dojo.hitch(this,"onChange",_a),0);
-this._showText(_9);
-},setValue:function(_b){
-dojo.deprecated("dijit.InlineEditBox.setValue() is deprecated.  Use attr('value', ...) instead.","","2.0");
-return this.attr("value",_b);
-},_setValueAttr:function(_c){
-this.value=_c=dojo.trim(_c);
-if(!this.renderAsHtml){
-_c=_c.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,""").replace(/\n/g,"<br>");
-}
-this.displayNode.innerHTML=_c||this.noValueIndicator;
-},getValue:function(){
-dojo.deprecated("dijit.InlineEditBox.getValue() is deprecated.  Use attr('value') instead.","","2.0");
-return this.attr("value");
-},cancel:function(_d){
-if(this.disabled||!this.editing){
-return;
-}
-this.editing=false;
-setTimeout(dojo.hitch(this,"onCancel"),0);
-this._showText(_d);
-}});
-dojo.declare("dijit._InlineEditor",[dijit._Widget,dijit._Templated],{templateString:dojo.cache("dijit","templates/InlineEditBox.html","<span dojoAttachPoint=\"editNode\" waiRole=\"presentation\" style=\"position: absolute; visibility:hidden\" class=\"dijitReset dijitInline\"\n\tdojoAttachEvent=\"onkeypress: _onKeyPress\"\n\t><span dojoAttachPoint=\"editorPlaceholder\"></span\n\t><span dojoAttachPoint=\"buttonContainer\"\n\t\t><button class='saveButton' dojoAttachPoint=\"saveButton\" dojo [...]
-this.inherited(arguments);
-this.messages=dojo.i18n.getLocalization("dijit","common",this.lang);
-dojo.forEach(["buttonSave","buttonCancel"],function(_e){
-if(!this[_e]){
-this[_e]=this.messages[_e];
-}
-},this);
-},postCreate:function(){
-var _f=dojo.getObject(this.editor);
-var _10=this.sourceStyle;
-var _11="line-height:"+_10.lineHeight+";";
-dojo.forEach(["Weight","Family","Size","Style"],function(_12){
-_11+="font-"+_12+":"+_10["font"+_12]+";";
-},this);
-dojo.forEach(["marginTop","marginBottom","marginLeft","marginRight"],function(_13){
-this.domNode.style[_13]=_10[_13];
-},this);
-var _14=this.inlineEditBox.width;
-if(_14=="100%"){
-_11+="width:100%;";
-this.domNode.style.display="block";
-}else{
-_11+="width:"+(_14+(Number(_14)==_14?"px":""))+";";
-}
-var _15=this.inlineEditBox.editorParams;
-_15.style=_11;
-_15["displayedValue" in _f.prototype?"displayedValue":"value"]=this.value;
-var ew=this.editWidget=new _f(_15,this.editorPlaceholder);
-if(this.inlineEditBox.autoSave){
-this.buttonContainer.style.display="none";
-this.connect(ew,"onChange","_onChange");
-this.connect(ew,"onKeyPress","_onKeyPress");
-}else{
-if("intermediateChanges" in _f.prototype){
-ew.attr("intermediateChanges",true);
-this.connect(ew,"onChange","_onIntermediateChange");
-this.saveButton.attr("disabled",true);
-}
-}
-},_onIntermediateChange:function(val){
-this.saveButton.attr("disabled",(this.getValue()==this._resetValue)||!this.enableSave());
-},destroy:function(){
-this.editWidget.destroy(true);
-this.inherited(arguments);
-},getValue:function(){
-var ew=this.editWidget;
-return String(ew.attr("displayedValue" in ew?"displayedValue":"value"));
-},_onKeyPress:function(e){
-if(this.inlineEditBox.autoSave&&this.inlineEditBox.editing){
-if(e.altKey||e.ctrlKey){
-return;
-}
-if(e.charOrCode==dojo.keys.ESCAPE){
-dojo.stopEvent(e);
-this.cancel(true);
-}else{
-if(e.charOrCode==dojo.keys.ENTER&&e.target.tagName=="INPUT"){
-dojo.stopEvent(e);
-this._onChange();
-}
-}
-}
-},_onBlur:function(){
-this.inherited(arguments);
-if(this.inlineEditBox.autoSave&&this.inlineEditBox.editing){
-if(this.getValue()==this._resetValue){
-this.cancel(false);
-}else{
-if(this.enableSave()){
-this.save(false);
-}
-}
-}
-},_onChange:function(){
-if(this.inlineEditBox.autoSave&&this.inlineEditBox.editing&&this.enableSave()){
-dojo.style(this.inlineEditBox.displayNode,{display:""});
-dijit.focus(this.inlineEditBox.displayNode);
-}
-},enableSave:function(){
-return (this.editWidget.isValid?this.editWidget.isValid():true);
-},focus:function(){
-this.editWidget.focus();
-setTimeout(dojo.hitch(this,function(){
-if(this.editWidget.focusNode.tagName=="INPUT"){
-dijit.selectInputText(this.editWidget.focusNode);
-}
-}),0);
-}});
-}
+
+dojo.requireLocalization("dijit", "common");
+
+dojo.declare("dijit.InlineEditBox",
+	dijit._Widget,
+	{
+	// summary:
+	//		An element with in-line edit capabilites
+	//
+	// description:
+	//		Behavior for an existing node (`<p>`, `<div>`, `<span>`, etc.) so that
+	// 		when you click it, an editor shows up in place of the original
+	//		text.  Optionally, Save and Cancel button are displayed below the edit widget.
+	//		When Save is clicked, the text is pulled from the edit
+	//		widget and redisplayed and the edit widget is again hidden.
+	//		By default a plain Textarea widget is used as the editor (or for
+	//		inline values a TextBox), but you can specify an editor such as
+	//		dijit.Editor (for editing HTML) or a Slider (for adjusting a number).
+	//		An edit widget must support the following API to be used:
+	//			- displayedValue or value as initialization parameter,
+	//			and available through set('displayedValue') / set('value')
+	//			- void focus()
+	//			- DOM-node focusNode = node containing editable text
+
+	// editing: [readonly] Boolean
+	//		Is the node currently in edit mode?
+	editing: false,
+
+	// autoSave: Boolean
+	//		Changing the value automatically saves it; don't have to push save button
+	//		(and save button isn't even displayed)
+	autoSave: true,
+
+	// buttonSave: String
+	//		Save button label
+	buttonSave: "",
+
+	// buttonCancel: String
+	//		Cancel button label
+	buttonCancel: "",
+
+	// renderAsHtml: Boolean
+	//		Set this to true if the specified Editor's value should be interpreted as HTML
+	//		rather than plain text (ex: `dijit.Editor`)
+	renderAsHtml: false,
+
+	// editor: String
+	//		Class name for Editor widget
+	editor: "dijit.form.TextBox",
+
+	// editorWrapper: String
+	//		Class name for widget that wraps the editor widget, displaying save/cancel
+	//		buttons.
+	editorWrapper: "dijit._InlineEditor",
+
+	// editorParams: Object
+	//		Set of parameters for editor, like {required: true}
+	editorParams: {},
+
+	onChange: function(value){
+		// summary:
+		//		Set this handler to be notified of changes to value.
+		// tags:
+		//		callback
+	},
+
+	onCancel: function(){
+		// summary:
+		//		Set this handler to be notified when editing is cancelled.
+		// tags:
+		//		callback
+	},
+
+	// width: String
+	//		Width of editor.  By default it's width=100% (ie, block mode).
+	width: "100%",
+
+	// value: String
+	//		The display value of the widget in read-only mode
+	value: "",
+
+	// noValueIndicator: [const] String
+	//		The text that gets displayed when there is no value (so that the user has a place to click to edit)
+	noValueIndicator: dojo.isIE <= 6 ?	// font-family needed on IE6 but it messes up IE8
+		"<span style='font-family: wingdings; text-decoration: underline;'>    &#x270d;    </span>" :
+		"<span style='text-decoration: underline;'>    &#x270d;    </span>",
+
+	constructor: function(){
+		// summary:
+		//		Sets up private arrays etc.
+		// tags:
+		//		private
+		this.editorParams = {};
+	},
+
+	postMixInProperties: function(){
+		this.inherited(arguments);
+
+		// save pointer to original source node, since Widget nulls-out srcNodeRef
+		this.displayNode = this.srcNodeRef;
+
+		// connect handlers to the display node
+		var events = {
+			ondijitclick: "_onClick",
+			onmouseover: "_onMouseOver",
+			onmouseout: "_onMouseOut",
+			onfocus: "_onMouseOver",
+			onblur: "_onMouseOut"
+		};
+		for(var name in events){
+			this.connect(this.displayNode, name, events[name]);
+		}
+		dijit.setWaiRole(this.displayNode, "button");
+		if(!this.displayNode.getAttribute("tabIndex")){
+			this.displayNode.setAttribute("tabIndex", 0);
+		}
+
+		if(!this.value && !("value" in this.params)){ // "" is a good value if specified directly so check params){
+		   this.value = dojo.trim(this.renderAsHtml ? this.displayNode.innerHTML :
+		      (this.displayNode.innerText||this.displayNode.textContent||""));
+		}
+		if(!this.value){
+		    this.displayNode.innerHTML = this.noValueIndicator;
+		}
+
+		dojo.addClass(this.displayNode, 'dijitInlineEditBoxDisplayMode');
+	},
+
+	setDisabled: function(/*Boolean*/ disabled){
+		// summary:
+		//		Deprecated.   Use set('disabled', ...) instead.
+		// tags:
+		//		deprecated
+		dojo.deprecated("dijit.InlineEditBox.setDisabled() is deprecated.  Use set('disabled', bool) instead.", "", "2.0");
+		this.set('disabled', disabled);
+	},
+
+	_setDisabledAttr: function(/*Boolean*/ disabled){
+		// summary:
+		//		Hook to make set("disabled", ...) work.
+		//		Set disabled state of widget.
+		this.disabled = disabled;
+		dijit.setWaiState(this.domNode, "disabled", disabled);
+		if(disabled){
+			this.displayNode.removeAttribute("tabIndex");
+		}else{
+			this.displayNode.setAttribute("tabIndex", 0);
+		}
+		dojo.toggleClass(this.displayNode, "dijitInlineEditBoxDisplayModeDisabled", disabled);
+	},
+
+	_onMouseOver: function(){
+		// summary:
+		//		Handler for onmouseover and onfocus event.
+		// tags:
+		//		private
+		if(!this.disabled){
+			dojo.addClass(this.displayNode, "dijitInlineEditBoxDisplayModeHover");
+		}
+	},
+
+	_onMouseOut: function(){
+		// summary:
+		//		Handler for onmouseout and onblur event.
+		// tags:
+		//		private
+		dojo.removeClass(this.displayNode, "dijitInlineEditBoxDisplayModeHover");
+	},
+
+	_onClick: function(/*Event*/ e){
+		// summary:
+		//		Handler for onclick event.
+		// tags:
+		//		private
+		if(this.disabled){ return; }
+		if(e){ dojo.stopEvent(e); }
+		this._onMouseOut();
+
+		// Since FF gets upset if you move a node while in an event handler for that node...
+		setTimeout(dojo.hitch(this, "edit"), 0);
+	},
+
+	edit: function(){
+		// summary:
+		//		Display the editor widget in place of the original (read only) markup.
+		// tags:
+		//		private
+
+		if(this.disabled || this.editing){ return; }
+		this.editing = true;
+
+		// save some display node values that can be restored later
+		this._savedPosition = dojo.style(this.displayNode, "position") || "static";
+		this._savedOpacity = dojo.style(this.displayNode, "opacity") || "1";
+		this._savedTabIndex = dojo.attr(this.displayNode, "tabIndex") || "0";
+
+		if(this.wrapperWidget){
+			var ew = this.wrapperWidget.editWidget;
+			ew.set("displayedValue" in ew ? "displayedValue" : "value", this.value);
+		}else{
+			// Placeholder for edit widget
+			// Put place holder (and eventually editWidget) before the display node so that it's positioned correctly
+			// when Calendar dropdown appears, which happens automatically on focus.
+			var placeholder = dojo.create("span", null, this.domNode, "before");
+
+			// Create the editor wrapper (the thing that holds the editor widget and the save/cancel buttons)
+			var ewc = dojo.getObject(this.editorWrapper);
+			this.wrapperWidget = new ewc({
+				value: this.value,
+				buttonSave: this.buttonSave,
+				buttonCancel: this.buttonCancel,
+				dir: this.dir,
+				lang: this.lang,
+				tabIndex: this._savedTabIndex,
+				editor: this.editor,
+				inlineEditBox: this,
+				sourceStyle: dojo.getComputedStyle(this.displayNode),
+				save: dojo.hitch(this, "save"),
+				cancel: dojo.hitch(this, "cancel")
+			}, placeholder);
+		}
+		var ww = this.wrapperWidget;
+
+		if(dojo.isIE){
+			dijit.focus(dijit.getFocus()); // IE (at least 8) needs help with tab order changes
+		}
+		// to avoid screen jitter, we first create the editor with position:absolute, visibility:hidden,
+		// and then when it's finished rendering, we switch from display mode to editor
+		// position:absolute releases screen space allocated to the display node
+		// opacity:0 is the same as visibility:hidden but is still focusable
+		// visiblity:hidden removes focus outline
+
+		dojo.style(this.displayNode, { position: "absolute", opacity: "0", display: "none" }); // makes display node invisible, display style used for focus-ability
+		dojo.style(ww.domNode, { position: this._savedPosition, visibility: "visible", opacity: "1" });
+		dojo.attr(this.displayNode, "tabIndex", "-1"); // needed by WebKit for TAB from editor to skip displayNode
+
+		// Replace the display widget with edit widget, leaving them both displayed for a brief time so that
+		// focus can be shifted without incident.  (browser may needs some time to render the editor.)
+		setTimeout(dojo.hitch(this, function(){
+			ww.focus(); // both nodes are showing, so we can switch focus safely
+			ww._resetValue = ww.getValue();
+		}), 0);
+	},
+
+	_onBlur: function(){
+		// summary:
+		//		Called when focus moves outside the InlineEditBox.
+		//		Performs garbage collection.
+		// tags:
+		//		private
+
+		this.inherited(arguments);
+		if(!this.editing){
+			/* causes IE focus problems, see TooltipDialog_a11y.html...
+			setTimeout(dojo.hitch(this, function(){
+				if(this.wrapperWidget){
+					this.wrapperWidget.destroy();
+					delete this.wrapperWidget;
+				}
+			}), 0);
+			*/
+		}
+	},
+
+	destroy: function(){
+		if(this.wrapperWidget){
+			this.wrapperWidget.destroy();
+			delete this.wrapperWidget;
+		}
+		this.inherited(arguments);
+	},
+
+	_showText: function(/*Boolean*/ focus){
+		// summary:
+		//		Revert to display mode, and optionally focus on display node
+		// tags:
+		//		private
+
+		var ww = this.wrapperWidget;
+		dojo.style(ww.domNode, { position: "absolute", visibility: "hidden", opacity: "0" }); // hide the editor from mouse/keyboard events
+		dojo.style(this.displayNode, { position: this._savedPosition, opacity: this._savedOpacity, display: "" }); // make the original text visible
+		dojo.attr(this.displayNode, "tabIndex", this._savedTabIndex);
+		if(focus){
+			dijit.focus(this.displayNode);
+		}
+	},
+
+	save: function(/*Boolean*/ focus){
+		// summary:
+		//		Save the contents of the editor and revert to display mode.
+		// focus: Boolean
+		//		Focus on the display mode text
+		// tags:
+		//		private
+
+		if(this.disabled || !this.editing){ return; }
+		this.editing = false;
+
+		var ww = this.wrapperWidget;
+		var value = ww.getValue();
+		this.set('value', value); // display changed, formatted value
+
+		// tell the world that we have changed
+		setTimeout(dojo.hitch(this, "onChange", value), 0); // setTimeout prevents browser freeze for long-running event handlers
+
+		this._showText(focus); // set focus as needed
+	},
+
+	setValue: function(/*String*/ val){
+		// summary:
+		//		Deprecated.   Use set('value', ...) instead.
+		// tags:
+		//		deprecated
+		dojo.deprecated("dijit.InlineEditBox.setValue() is deprecated.  Use set('value', ...) instead.", "", "2.0");
+		return this.set("value", val);
+	},
+
+	_setValueAttr: function(/*String*/ val){
+		// summary:
+		// 		Hook to make set("value", ...) work.
+		//		Inserts specified HTML value into this node, or an "input needed" character if node is blank.
+
+		this.value = val = dojo.trim(val);
+		if(!this.renderAsHtml){
+			val = val.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """).replace(/\n/g, "<br>");
+		}
+		this.displayNode.innerHTML = val || this.noValueIndicator;
+	},
+
+	getValue: function(){
+		// summary:
+		//		Deprecated.   Use get('value') instead.
+		// tags:
+		//		deprecated
+		dojo.deprecated("dijit.InlineEditBox.getValue() is deprecated.  Use get('value') instead.", "", "2.0");
+		return this.get("value");
+	},
+
+	cancel: function(/*Boolean*/ focus){
+		// summary:
+		//		Revert to display mode, discarding any changes made in the editor
+		// tags:
+		//		private
+
+		if(this.disabled || !this.editing){ return; }
+		this.editing = false;
+
+		// tell the world that we have no changes
+		setTimeout(dojo.hitch(this, "onCancel"), 0); // setTimeout prevents browser freeze for long-running event handlers
+
+		this._showText(focus);
+	}
+});
+
+dojo.declare(
+	"dijit._InlineEditor",
+	 [dijit._Widget, dijit._Templated],
+{
+	// summary:
+	// 		Internal widget used by InlineEditBox, displayed when in editing mode
+	//		to display the editor and maybe save/cancel buttons.  Calling code should
+	//		connect to save/cancel methods to detect when editing is finished
+	//
+	//		Has mainly the same parameters as InlineEditBox, plus these values:
+	//
+	// style: Object
+	//		Set of CSS attributes of display node, to replicate in editor
+	//
+	// value: String
+	//		Value as an HTML string or plain text string, depending on renderAsHTML flag
+
+	templateString: dojo.cache("dijit", "templates/InlineEditBox.html"),
+	widgetsInTemplate: true,
+
+	postMixInProperties: function(){
+		this.inherited(arguments);
+		this.messages = dojo.i18n.getLocalization("dijit", "common", this.lang);
+		dojo.forEach(["buttonSave", "buttonCancel"], function(prop){
+			if(!this[prop]){ this[prop] = this.messages[prop]; }
+		}, this);
+	},
+
+	postCreate: function(){
+		// Create edit widget in place in the template
+		var cls = dojo.getObject(this.editor);
+
+		// Copy the style from the source
+		// Don't copy ALL properties though, just the necessary/applicable ones.
+		// wrapperStyle/destStyle code is to workaround IE bug where getComputedStyle().fontSize
+		// is a relative value like 200%, rather than an absolute value like 24px, and
+		// the 200% can refer *either* to a setting on the node or it's ancestor (see #11175)
+		var srcStyle = this.sourceStyle,
+			editStyle = "line-height:" + srcStyle.lineHeight + ";",
+			destStyle = dojo.getComputedStyle(this.domNode);
+		dojo.forEach(["Weight","Family","Size","Style"], function(prop){
+			var textStyle = srcStyle["font"+prop],
+				wrapperStyle = destStyle["font"+prop];
+			if(wrapperStyle != textStyle){
+				editStyle += "font-"+prop+":"+srcStyle["font"+prop]+";";
+			}
+		}, this);
+		dojo.forEach(["marginTop","marginBottom","marginLeft", "marginRight"], function(prop){
+			this.domNode.style[prop] = srcStyle[prop];
+		}, this);
+		var width = this.inlineEditBox.width;
+		if(width == "100%"){
+			// block mode
+			editStyle += "width:100%;";
+			this.domNode.style.display = "block";
+		}else{
+			// inline-block mode
+			editStyle += "width:" + (width + (Number(width) == width ? "px" : "")) + ";";
+		}
+		var editorParams = dojo.delegate(this.inlineEditBox.editorParams, {
+			style: editStyle,
+			dir: this.dir,
+			lang: this.lang
+		});
+		editorParams[ "displayedValue" in cls.prototype ? "displayedValue" : "value"] = this.value;
+		var ew = (this.editWidget = new cls(editorParams, this.editorPlaceholder));
+
+		if(this.inlineEditBox.autoSave){
+			// Remove the save/cancel buttons since saving is done by simply tabbing away or
+			// selecting a value from the drop down list
+			dojo.destroy(this.buttonContainer);
+
+			// Selecting a value from a drop down list causes an onChange event and then we save
+			this.connect(ew, "onChange", "_onChange");
+
+			// ESC and TAB should cancel and save.  Note that edit widgets do a stopEvent() on ESC key (to
+			// prevent Dialog from closing when the user just wants to revert the value in the edit widget),
+			// so this is the only way we can see the key press event.
+			this.connect(ew, "onKeyPress", "_onKeyPress");
+		}else{
+			// If possible, enable/disable save button based on whether the user has changed the value
+			if("intermediateChanges" in cls.prototype){
+				ew.set("intermediateChanges", true);
+				this.connect(ew, "onChange", "_onIntermediateChange");
+				this.saveButton.set("disabled", true);
+			}
+		}
+	},
+
+	_onIntermediateChange: function(val){
+		// summary:
+		//		Called for editor widgets that support the intermediateChanges=true flag as a way
+		//		to detect when to enable/disabled the save button
+		this.saveButton.set("disabled", (this.getValue() == this._resetValue) || !this.enableSave());
+	},
+
+	destroy: function(){
+		this.editWidget.destroy(true); // let the parent wrapper widget clean up the DOM
+		this.inherited(arguments);
+	},
+
+	getValue: function(){
+		// summary:
+		//		Return the [display] value of the edit widget
+		var ew = this.editWidget;
+		return String(ew.get("displayedValue" in ew ? "displayedValue" : "value"));
+	},
+
+	_onKeyPress: function(e){
+		// summary:
+		//		Handler for keypress in the edit box in autoSave mode.
+		// description:
+		//		For autoSave widgets, if Esc/Enter, call cancel/save.
+		// tags:
+		//		private
+
+		if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){
+			if(e.altKey || e.ctrlKey){ return; }
+			// If Enter/Esc pressed, treat as save/cancel.
+			if(e.charOrCode == dojo.keys.ESCAPE){
+				dojo.stopEvent(e);
+				this.cancel(true); // sets editing=false which short-circuits _onBlur processing
+			}else if(e.charOrCode == dojo.keys.ENTER && e.target.tagName == "INPUT"){
+				dojo.stopEvent(e);
+				this._onChange(); // fire _onBlur and then save
+			}
+
+			// _onBlur will handle TAB automatically by allowing
+			// the TAB to change focus before we mess with the DOM: #6227
+			// Expounding by request:
+			// 	The current focus is on the edit widget input field.
+			//	save() will hide and destroy this widget.
+			//	We want the focus to jump from the currently hidden
+			//	displayNode, but since it's hidden, it's impossible to
+			//	unhide it, focus it, and then have the browser focus
+			//	away from it to the next focusable element since each
+			//	of these events is asynchronous and the focus-to-next-element
+			//	is already queued.
+			//	So we allow the browser time to unqueue the move-focus event
+			//	before we do all the hide/show stuff.
+		}
+	},
+
+	_onBlur: function(){
+		// summary:
+		//		Called when focus moves outside the editor
+		// tags:
+		//		private
+
+		this.inherited(arguments);
+		if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){
+			if(this.getValue() == this._resetValue){
+				this.cancel(false);
+			}else if(this.enableSave()){
+				this.save(false);
+			}
+		}
+	},
+
+	_onChange: function(){
+		// summary:
+		//		Called when the underlying widget fires an onChange event,
+		//		such as when the user selects a value from the drop down list of a ComboBox,
+		//		which means that the user has finished entering the value and we should save.
+		// tags:
+		//		private
+
+		if(this.inlineEditBox.autoSave && this.inlineEditBox.editing && this.enableSave()){
+			dojo.style(this.inlineEditBox.displayNode, { display: "" });
+			dijit.focus(this.inlineEditBox.displayNode); // fires _onBlur which will save the formatted value
+		}
+	},
+
+	enableSave: function(){
+		// summary:
+		//		User overridable function returning a Boolean to indicate
+		// 		if the Save button should be enabled or not - usually due to invalid conditions
+		// tags:
+		//		extension
+		return (
+			this.editWidget.isValid
+			? this.editWidget.isValid()
+			: true
+		);
+	},
+
+	focus: function(){
+		// summary:
+		//		Focus the edit widget.
+		// tags:
+		//		protected
+
+		this.editWidget.focus();
+		setTimeout(dojo.hitch(this, function(){
+			if(this.editWidget.focusNode && this.editWidget.focusNode.tagName == "INPUT"){
+				dijit.selectInputText(this.editWidget.focusNode);
+			}
+		}), 0);
+	}
+});
diff --git a/dijit/LICENSE b/dijit/LICENSE
index ad1676a..4c93ded 100644
--- a/dijit/LICENSE
+++ b/dijit/LICENSE
@@ -13,7 +13,7 @@ The text of the AFL and BSD licenses is reproduced below.
 The "New" BSD License:
 **********************
 
-Copyright (c) 2005-2009, The Dojo Foundation
+Copyright (c) 2005-2010, The Dojo Foundation
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/dijit/Menu.js b/dijit/Menu.js
index d92df0f..299c8de 100644
--- a/dijit/Menu.js
+++ b/dijit/Menu.js
@@ -1,332 +1,700 @@
-/*
-	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
-*/
+dojo.provide("dijit.Menu");
 
+dojo.require("dojo.window");
 
-if(!dojo._hasResource["dijit.Menu"]){
-dojo._hasResource["dijit.Menu"]=true;
-dojo.provide("dijit.Menu");
 dojo.require("dijit._Widget");
 dojo.require("dijit._KeyNavContainer");
 dojo.require("dijit._Templated");
-dojo.declare("dijit._MenuBase",[dijit._Widget,dijit._Templated,dijit._KeyNavContainer],{parentMenu:null,popupDelay:500,startup:function(){
-if(this._started){
-return;
-}
-dojo.forEach(this.getChildren(),function(_1){
-_1.startup();
-});
-this.startupKeyNavChildren();
-this.inherited(arguments);
-},onExecute:function(){
-},onCancel:function(_2){
-},_moveToPopup:function(_3){
-if(this.focusedChild&&this.focusedChild.popup&&!this.focusedChild.disabled){
-this.focusedChild._onClick(_3);
-}else{
-var _4=this._getTopMenu();
-if(_4&&_4._isMenuBar){
-_4.focusNext();
-}
-}
-},_onPopupHover:function(_5){
-if(this.currentPopup&&this.currentPopup._pendingClose_timer){
-var _6=this.currentPopup.parentMenu;
-if(_6.focusedChild){
-_6.focusedChild._setSelected(false);
-}
-_6.focusedChild=this.currentPopup.from_item;
-_6.focusedChild._setSelected(true);
-this._stopPendingCloseTimer(this.currentPopup);
-}
-},onItemHover:function(_7){
-if(this.isActive){
-this.focusChild(_7);
-if(this.focusedChild.popup&&!this.focusedChild.disabled&&!this.hover_timer){
-this.hover_timer=setTimeout(dojo.hitch(this,"_openPopup"),this.popupDelay);
-}
-}
-if(this.focusedChild){
-this.focusChild(_7);
-}
-this._hoveredChild=_7;
-},_onChildBlur:function(_8){
-this._stopPopupTimer();
-_8._setSelected(false);
-var _9=_8.popup;
-if(_9){
-this._stopPendingCloseTimer(_9);
-_9._pendingClose_timer=setTimeout(function(){
-_9._pendingClose_timer=null;
-if(_9.parentMenu){
-_9.parentMenu.currentPopup=null;
-}
-dijit.popup.close(_9);
-},this.popupDelay);
-}
-},onItemUnhover:function(_a){
-if(this.isActive){
-this._stopPopupTimer();
-}
-if(this._hoveredChild==_a){
-this._hoveredChild=null;
-}
-},_stopPopupTimer:function(){
-if(this.hover_timer){
-clearTimeout(this.hover_timer);
-this.hover_timer=null;
-}
-},_stopPendingCloseTimer:function(_b){
-if(_b._pendingClose_timer){
-clearTimeout(_b._pendingClose_timer);
-_b._pendingClose_timer=null;
-}
-},_stopFocusTimer:function(){
-if(this._focus_timer){
-clearTimeout(this._focus_timer);
-this._focus_timer=null;
-}
-},_getTopMenu:function(){
-for(var _c=this;_c.parentMenu;_c=_c.parentMenu){
-}
-return _c;
-},onItemClick:function(_d,_e){
-if(_d.disabled){
-return false;
-}
-if(typeof this.isShowingNow=="undefined"){
-this._markActive();
-}
-this.focusChild(_d);
-if(_d.popup){
-this._openPopup();
-}else{
-this.onExecute();
-_d.onClick(_e);
-}
-},_openPopup:function(){
-this._stopPopupTimer();
-var _f=this.focusedChild;
-if(!_f){
-return;
-}
-var _10=_f.popup;
-if(_10.isShowingNow){
-return;
-}
-if(this.currentPopup){
-this._stopPendingCloseTimer(this.currentPopup);
-dijit.popup.close(this.currentPopup);
-}
-_10.parentMenu=this;
-_10.from_item=_f;
-var _11=this;
-dijit.popup.open({parent:this,popup:_10,around:_f.domNode,orient:this._orient||(this.isLeftToRight()?{"TR":"TL","TL":"TR","BR":"BL","BL":"BR"}:{"TL":"TR","TR":"TL","BL":"BR","BR":"BL"}),onCancel:function(){
-_11.focusChild(_f);
-_11._cleanUp();
-_f._setSelected(true);
-_11.focusedChild=_f;
-},onExecute:dojo.hitch(this,"_cleanUp")});
-this.currentPopup=_10;
-_10.connect(_10.domNode,"onmouseenter",dojo.hitch(_11,"_onPopupHover"));
-if(_10.focus){
-_10._focus_timer=setTimeout(dojo.hitch(_10,function(){
-this._focus_timer=null;
-this.focus();
-}),0);
-}
-},_markActive:function(){
-this.isActive=true;
-dojo.addClass(this.domNode,"dijitMenuActive");
-dojo.removeClass(this.domNode,"dijitMenuPassive");
-},onOpen:function(e){
-this.isShowingNow=true;
-this._markActive();
-},_markInactive:function(){
-this.isActive=false;
-dojo.removeClass(this.domNode,"dijitMenuActive");
-dojo.addClass(this.domNode,"dijitMenuPassive");
-},onClose:function(){
-this._stopFocusTimer();
-this._markInactive();
-this.isShowingNow=false;
-this.parentMenu=null;
-},_closeChild:function(){
-this._stopPopupTimer();
-if(this.focusedChild){
-this.focusedChild._setSelected(false);
-this.focusedChild._onUnhover();
-this.focusedChild=null;
-}
-if(this.currentPopup){
-dijit.popup.close(this.currentPopup);
-this.currentPopup=null;
-}
-},_onItemFocus:function(_12){
-if(this._hoveredChild&&this._hoveredChild!=_12){
-this._hoveredChild._onUnhover();
-}
-},_onBlur:function(){
-this._cleanUp();
-this.inherited(arguments);
-},_cleanUp:function(){
-this._closeChild();
-if(typeof this.isShowingNow=="undefined"){
-this._markInactive();
-}
-}});
-dojo.declare("dijit.Menu",dijit._MenuBase,{constructor:function(){
-this._bindings=[];
-},templateString:dojo.cache("dijit","templates/Menu.html","<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:[],contextMenuForWindow:false,leftClickToOpen:false,refocus:true,_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(evt){
-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;
-}
-},_iframeContentWindow:function(_13){
-var win=dijit.getDocumentWindow(this._iframeContentDocument(_13))||this._iframeContentDocument(_13)["__parent__"]||(_13.name&&dojo.doc.frames[_13.name])||null;
-return win;
-},_iframeContentDocument:function(_14){
-var doc=_14.contentDocument||(_14.contentWindow&&_14.contentWindow.document)||(_14.name&&dojo.doc.frames[_14.name]&&dojo.doc.frames[_14.name].document)||null;
-return doc;
-},bindDomNode:function(_15){
-_15=dojo.byId(_15);
-var cn;
-if(_15.tagName.toLowerCase()=="iframe"){
-var _16=_15,win=this._iframeContentWindow(_16);
-cn=dojo.withGlobal(win,dojo.body);
-}else{
-cn=(_15==dojo.body()?dojo.doc.documentElement:_15);
-}
-var _17={node:_15,iframe:_16};
-dojo.attr(_15,"_dijitMenu"+this.id,this._bindings.push(_17));
-var _18=dojo.hitch(this,function(cn){
-return [dojo.connect(cn,(this.leftClickToOpen)?"onclick":"oncontextmenu",this,function(evt){
-this._openMyself(evt,cn,_16);
-}),dojo.connect(cn,"onkeydown",this,"_contextKey"),dojo.connect(cn,"onmousedown",this,"_contextMouse")];
-});
-_17.connects=cn?_18(cn):[];
-if(_16){
-_17.onloadHandler=dojo.hitch(this,function(){
-var win=this._iframeContentWindow(_16);
-cn=dojo.withGlobal(win,dojo.body);
-_17.connects=_18(cn);
+
+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();
+			}
+		}
+	},
+
+	_onPopupHover: function(/*Event*/ evt){
+		// summary:
+		//		This handler is called when the mouse moves over the popup.
+		// tags:
+		//		private
+
+		// if the mouse hovers over a menu popup that is in pending-close state,
+		// then stop the close operation.
+		// This can't be done in onItemHover since some popup targets don't have MenuItems (e.g. ColorPicker)
+		if(this.currentPopup && this.currentPopup._pendingClose_timer){
+			var parentMenu = this.currentPopup.parentMenu;
+			// highlight the parent menu item pointing to this popup
+			if(parentMenu.focusedChild){
+				parentMenu.focusedChild._setSelected(false);
+			}
+			parentMenu.focusedChild = this.currentPopup.from_item;
+			parentMenu.focusedChild._setSelected(true);
+			// cancel the pending close
+			this._stopPendingCloseTimer(this.currentPopup);
+		}
+	},
+
+	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) 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);
+			}
+		}
+		// if the user is mixing mouse and keyboard navigation,
+		// then the menu may not be active but a menu item has focus,
+		// but it's not the item that the mouse just hovered over.
+		// To avoid both keyboard and mouse selections, use the latest.
+		if(this.focusedChild){
+			this.focusChild(item);
+		}
+		this._hoveredChild = item;
+	},
+
+	_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
+		this._stopPopupTimer();
+		item._setSelected(false);
+		// Close all popups that are open and descendants of this menu
+		var itemPopup = item.popup;
+		if(itemPopup){
+			this._stopPendingCloseTimer(itemPopup);
+			itemPopup._pendingClose_timer = setTimeout(function(){
+				itemPopup._pendingClose_timer = null;
+				if(itemPopup.parentMenu){
+					itemPopup.parentMenu.currentPopup = null;
+				}
+				dijit.popup.close(itemPopup); // this calls onClose
+			}, this.popupDelay);
+		}
+	},
+
+	onItemUnhover: function(/*MenuItem*/ item){
+		// summary:
+		//		Callback fires when mouse exits a MenuItem
+		// tags:
+		//		protected
+
+		if(this.isActive){
+			this._stopPopupTimer();
+		}
+		if(this._hoveredChild == item){ this._hoveredChild = null; }
+	},
+
+	_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;
+		}
+	},
+
+	_stopPendingCloseTimer: function(/*dijit._Widget*/ popup){
+		// summary:
+		//		Cancels the pending-close timer because the close has been preempted
+		// tags:
+		//		private
+		if(popup._pendingClose_timer){
+			clearTimeout(popup._pendingClose_timer);
+			popup._pendingClose_timer = null;
+		}
+	},
+
+	_stopFocusTimer: function(){
+		// summary:
+		//		Cancels the pending-focus timer because the menu was closed before focus occured
+		// tags:
+		//		private
+		if(this._focus_timer){
+			clearTimeout(this._focus_timer);
+			this._focus_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(/*dijit._Widget*/ item, /*Event*/ evt){
+		// summary:
+		//		Handle clicks on an item.
+		// tags:
+		//		private
+
+		// this can't be done in _onFocus since the _onFocus events occurs asynchronously
+		if(typeof this.isShowingNow == 'undefined'){ // non-popup menu
+			this._markActive();
+		}
+
+		this.focusChild(item);
+
+		if(item.disabled){ return false; }
+
+		if(item.popup){
+			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;
+		if(!from_item){ return; } // the focused child lost focus since the timer was started
+		var popup = from_item.popup;
+		if(popup.isShowingNow){ return; }
+		if(this.currentPopup){
+			this._stopPendingCloseTimer(this.currentPopup);
+			dijit.popup.close(this.currentPopup);
+		}
+		popup.parentMenu = this;
+		popup.from_item = from_item; // helps finding the parent item that should be focused for this popup
+		var self = this;
+		dijit.popup.open({
+			parent: this,
+			popup: popup,
+			around: from_item.domNode,
+			orient: this._orient || (this.isLeftToRight() ?
+									{'TR': 'TL', 'TL': 'TR', 'BR': 'BL', 'BL': 'BR'} :
+									{'TL': 'TR', 'TR': 'TL', 'BL': 'BR', 'BR': 'BL'}),
+			onCancel: function(){ // called when the child menu is canceled
+				// set isActive=false (_closeChild vs _cleanUp) so that subsequent hovering will NOT open child menus
+				// which seems aligned with the UX of most applications (e.g. notepad, wordpad, paint shop pro)
+				self.focusChild(from_item);	// put focus back on my node
+				self._cleanUp();			// close the submenu (be sure this is done _after_ focus is moved)
+				from_item._setSelected(true); // oops, _cleanUp() deselected the item
+				self.focusedChild = from_item;	// and unset focusedChild
+			},
+			onExecute: dojo.hitch(this, "_cleanUp")
+		});
+
+		this.currentPopup = popup;
+		// detect mouseovers to handle lazy mouse movements that temporarily focus other menu items
+		popup.connect(popup.domNode, "onmouseenter", dojo.hitch(self, "_onPopupHover")); // cleaned up when the popped-up widget is destroyed on close
+
+		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)
+			popup._focus_timer = setTimeout(dojo.hitch(popup, function(){
+				this._focus_timer = null;
+				this.focus();
+			}), 0);
+		}
+	},
+
+	_markActive: function(){
+		// summary:
+		//              Mark this menu's state as active.
+		//		Called when this Menu gets focus from:
+		//			1) clicking it (mouse or via space/arrow key)
+		//			2) being opened by a parent menu.
+		//		This is not called just from mouse hover.
+		//		Focusing a menu via TAB does NOT automatically set isActive
+		//		since TAB is a navigation operation and not a selection one.
+		//		For Windows apps, pressing the ALT key focuses the menubar
+		//		menus (similar to TAB navigation) but the menu is not active
+		//		(ie no dropdown) until an item is clicked.
+		this.isActive = true;
+		dojo.addClass(this.domNode, "dijitMenuActive");
+		dojo.removeClass(this.domNode, "dijitMenuPassive");
+	},
+
+	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;
+		this._markActive();
+	},
+
+	_markInactive: function(){
+		// summary:
+		//		Mark this menu's state as inactive.
+		this.isActive = false; // don't do this in _onBlur since the state is pending-close until we get here
+		dojo.removeClass(this.domNode, "dijitMenuActive");
+		dojo.addClass(this.domNode, "dijitMenuPassive");
+	},
+
+	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._stopFocusTimer();
+		this._markInactive();
+		this.isShowingNow = false;
+		this.parentMenu = null;
+	},
+
+	_closeChild: function(){
+		// summary:
+		//		Called when submenu is clicked or focus is lost.  Close hierarchy of menus.
+		// tags:
+		//		private
+		this._stopPopupTimer();
+		if(this.focusedChild){ // unhighlight the focused item
+			this.focusedChild._setSelected(false);
+			this.focusedChild._onUnhover();
+			this.focusedChild = null;
+		}
+		if(this.currentPopup){
+			// Close all popups that are open and descendants of this menu
+			dijit.popup.close(this.currentPopup);
+			this.currentPopup = null;
+		}
+	},
+
+	_onItemFocus: function(/*MenuItem*/ item){
+		// summary:
+		//		Called when child of 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.
+		if(this._hoveredChild && this._hoveredChild != item){
+			this._hoveredChild._onUnhover(); // any previous mouse movement is trumped by focus selection
+		}
+	},
+
+	_onBlur: function(){
+		// summary:
+		//		Called when focus is moved away from this Menu and it's submenus.
+		// tags:
+		//		protected
+		this._cleanUp();
+		this.inherited(arguments);
+	},
+
+	_cleanUp: function(){
+		// summary:
+		//		Called when the user is done with this menu.  Closes hierarchy of menus.
+		// tags:
+		//		private
+
+		this._closeChild(); // don't call this.onClose since that's incorrect for MenuBar's that never close
+		if(typeof this.isShowingNow == 'undefined'){ // non-popup menu doesn't call onClose
+			this._markInactive();
+		}
+	}
 });
-if(_16.addEventListener){
-_16.addEventListener("load",_17.onloadHandler,false);
-}else{
-_16.attachEvent("onload",_17.onloadHandler);
-}
-}
-},unBindDomNode:function(_19){
-var _1a;
-try{
-_1a=dojo.byId(_19);
-}
-catch(e){
-return;
-}
-var _1b="_dijitMenu"+this.id;
-if(_1a&&dojo.hasAttr(_1a,_1b)){
-var bid=dojo.attr(_1a,_1b)-1,b=this._bindings[bid];
-dojo.forEach(b.connects,dojo.disconnect);
-var _1c=b.iframe;
-if(_1c){
-if(_1c.removeEventListener){
-_1c.removeEventListener("load",b.onloadHandler,false);
-}else{
-_1c.detachEvent("onload",b.onloadHandler);
-}
-}
-dojo.removeAttr(_1a,_1b);
-delete this._bindings[bid];
-}
-},_contextKey:function(e){
-this._contextMenuWithMouse=false;
-if(e.keyCode==dojo.keys.F10){
-dojo.stopEvent(e);
-if(e.shiftKey&&e.type=="keydown"){
-var _1d={target:e.target,pageX:e.pageX,pageY:e.pageY};
-_1d.preventDefault=_1d.stopPropagation=function(){
-};
-window.setTimeout(dojo.hitch(this,function(){
-this._openMyself(_1d);
-}),1);
-}
-}
-},_contextMouse:function(e){
-this._contextMenuWithMouse=true;
-},_openMyself:function(e,_1e,_1f){
-if(this.leftClickToOpen&&e.button>0){
-return;
-}
-dojo.stopEvent(e);
-var x,y;
-if(dojo.isSafari||this._contextMenuWithMouse){
-x=e.pageX;
-y=e.pageY;
-if(_1f){
-var od=e.target.ownerDocument,ifc=dojo.position(_1f,true),win=this._iframeContentWindow(_1f),_20=dojo.withGlobal(win,"_docScroll",dojo);
-var cs=dojo.getComputedStyle(_1f),tp=dojo._toPixelValue,_21=(dojo.isIE&&dojo.isQuirks?0:tp(_1f,cs.paddingLeft))+(dojo.isIE&&dojo.isQuirks?tp(_1f,cs.borderLeftWidth):0),top=(dojo.isIE&&dojo.isQuirks?0:tp(_1f,cs.paddingTop))+(dojo.isIE&&dojo.isQuirks?tp(_1f,cs.borderTopWidth):0);
-x+=ifc.x+_21-_20.x;
-y+=ifc.y+top-_20.y;
-}
-}else{
-var _22=dojo.position(e.target,true);
-x=_22.x+10;
-y=_22.y+10;
-}
-var _23=this;
-var _24=dijit.getFocus(this);
-function _25(){
-if(_23.refocus){
-dijit.focus(_24);
-}
-dijit.popup.close(_23);
-};
-dijit.popup.open({popup:this,x:x,y:y,onExecute:_25,onCancel:_25,orient:this.isLeftToRight()?"L":"R"});
-this.focus();
-this._onBlur=function(){
-this.inherited("_onBlur",arguments);
-dijit.popup.close(this);
-};
-},uninitialize:function(){
-dojo.forEach(this._bindings,function(b){
-if(b){
-this.unBindDomNode(b.node);
+
+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: dojo.cache("dijit", "templates/Menu.html"),
+
+	baseClass: "dijitMenu",
+
+	// 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,
+
+	// refocus: Boolean
+	// 		When this menu closes, re-focus the element which had focus before it was opened.
+	refocus: true,
+
+	postCreate: function(){
+		if(this.contextMenuForWindow){
+			this.bindDomNode(dojo.body());
+		}else{
+			// TODO: should have _setTargetNodeIds() method to handle initialization and a possible
+			// later attr('targetNodeIds', ...) call.   There's also a problem that targetNodeIds[]
+			// gets stale after calls to bindDomNode()/unBindDomNode() as it still is just the original list (see #9610)
+			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 = dojo.window.get(this._iframeContentDocument(iframe_el)) ||
+			// Moz. TODO: is this available when defaultView isn't?
+			this._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);
+
+		var cn;	// Connect node
+
+		// Support context menus on iframes.   Rather than binding to the iframe itself we need
+		// to bind to the <body> node inside the iframe.
+		if(node.tagName.toLowerCase() == "iframe"){
+			var iframe = node,
+				win = this._iframeContentWindow(iframe);
+			cn = dojo.withGlobal(win, dojo.body);
+		}else{
+			
+			// To capture these events at the top level, attach to <html>, not <body>.
+			// Otherwise right-click context menu just doesn't work.
+			cn = (node == dojo.body() ? dojo.doc.documentElement : node);
+		}
+
+
+		// "binding" is the object to track our connection to the node (ie, the parameter to bindDomNode())
+		var binding = {
+			node: node,
+			iframe: iframe
+		};
+
+		// Save info about binding in _bindings[], and make node itself record index(+1) into
+		// _bindings[] array.   Prefix w/_dijitMenu to avoid setting an attribute that may
+		// start with a number, which fails on FF/safari.
+		dojo.attr(node, "_dijitMenu" + this.id, this._bindings.push(binding));
+
+		// Setup the connections to monitor click etc., unless we are connecting to an iframe which hasn't finished
+		// loading yet, in which case we need to wait for the onload event first, and then connect
+		// On linux Shift-F10 produces the oncontextmenu event, but on Windows it doesn't, so
+		// we need to monitor keyboard events in addition to the oncontextmenu event.
+		var doConnects = dojo.hitch(this, function(cn){
+			return [
+				// TODO: when leftClickToOpen is true then shouldn't space/enter key trigger the menu,
+				// rather than shift-F10?
+				dojo.connect(cn, this.leftClickToOpen ? "onclick" : "oncontextmenu", this, function(evt){
+					// Schedule context menu to be opened unless it's already been scheduled from onkeydown handler
+					dojo.stopEvent(evt);
+					this._scheduleOpen(evt.target, iframe, {x: evt.pageX, y: evt.pageY});
+				}),
+				dojo.connect(cn, "onkeydown", this, function(evt){
+					if(evt.shiftKey && evt.keyCode == dojo.keys.F10){
+						dojo.stopEvent(evt);
+						this._scheduleOpen(evt.target, iframe);	// no coords - open near target node
+					}
+				})
+			];	
+		});
+		binding.connects = cn ? doConnects(cn) : [];
+
+		if(iframe){
+			// Setup handler to [re]bind to the iframe when the contents are initially loaded,
+			// and every time the contents change.
+			// Need to do this b/c we are actually binding to the iframe's <body> node.
+			// Note: can't use dojo.connect(), see #9609.
+
+			binding.onloadHandler = dojo.hitch(this, function(){
+				// want to remove old connections, but IE throws exceptions when trying to
+				// access the <body> node because it's already gone, or at least in a state of limbo
+
+				var win = this._iframeContentWindow(iframe);
+					cn = dojo.withGlobal(win, dojo.body);
+				binding.connects = doConnects(cn);
+			});
+			if(iframe.addEventListener){
+				iframe.addEventListener("load", binding.onloadHandler, false);
+			}else{
+				iframe.attachEvent("onload", binding.onloadHandler);
+			}
+		}
+	},
+
+	unBindDomNode: function(/*String|DomNode*/ nodeName){
+		// summary:
+		//		Detach menu from given node
+
+		var node;
+		try{
+			node = dojo.byId(nodeName);
+		}catch(e){
+			// On IE the dojo.byId() call will get an exception if the attach point was
+			// the <body> node of an <iframe> that has since been reloaded (and thus the
+			// <body> node is in a limbo state of destruction.
+			return;
+		}
+
+		// node["_dijitMenu" + this.id] contains index(+1) into my _bindings[] array
+		var attrName = "_dijitMenu" + this.id;
+		if(node && dojo.hasAttr(node, attrName)){
+			var bid = dojo.attr(node, attrName)-1, b = this._bindings[bid];
+			dojo.forEach(b.connects, dojo.disconnect);
+
+			// Remove listener for iframe onload events
+			var iframe = b.iframe;
+			if(iframe){
+				if(iframe.removeEventListener){
+					iframe.removeEventListener("load", b.onloadHandler, false);
+				}else{
+					iframe.detachEvent("onload", b.onloadHandler);
+				}
+			}
+
+			dojo.removeAttr(node, attrName);
+			delete this._bindings[bid];
+		}
+	},
+
+	_scheduleOpen: function(/*DomNode?*/ target, /*DomNode?*/ iframe, /*Object?*/ coords){
+		// summary:
+		//		Set timer to display myself.  Using a timer rather than displaying immediately solves
+		//		two problems:
+		//
+		//		1. IE: without the delay, focus work in "open" causes the system
+		//		context menu to appear in spite of stopEvent.
+		//
+		//		2. Avoid double-shows on linux, where shift-F10 generates an oncontextmenu event
+		//		even after a dojo.stopEvent(e).  (Shift-F10 on windows doesn't generate the
+		//		oncontextmenu event.)
+
+		if(!this._openTimer){
+			this._openTimer = setTimeout(dojo.hitch(this, function(){
+				delete this._openTimer;
+				this._openMyself({
+					target: target,
+					iframe: iframe,
+					coords: coords
+				});
+			}), 1);
+		}
+	},
+
+	_openMyself: function(args){
+		// summary:
+		//		Internal function for opening myself when the user does a right-click or something similar.
+		// args:
+		//		This is an Object containing:
+		//		* target:
+		//			The node that is being clicked
+		//		* iframe:
+		//			If an <iframe> is being clicked, iframe points to that iframe
+		//		* coords:
+		//			Put menu at specified x/y position in viewport, or if iframe is
+		//			specified, then relative to iframe.
+		//
+		//		_openMyself() formerly took the event object, and since various code references
+		//		evt.target (after connecting to _openMyself()), using an Object for parameters
+		//		(so that old code still works).
+
+		var target = args.target,
+			iframe = args.iframe,
+			coords = args.coords;
+
+		// Get coordinates to open menu, either at specified (mouse) position or (if triggered via keyboard)
+		// then near the node the menu is assigned to.
+		if(coords){
+			if(iframe){
+				// Specified coordinates are on <body> node of an <iframe>, convert to match main document
+				var od = target.ownerDocument,
+					ifc = dojo.position(iframe, true),
+					win = this._iframeContentWindow(iframe),
+					scroll = dojo.withGlobal(win, "_docScroll", dojo);
+	
+				var cs = dojo.getComputedStyle(iframe),
+					tp = dojo._toPixelValue,
+					left = (dojo.isIE && dojo.isQuirks ? 0 : tp(iframe, cs.paddingLeft)) + (dojo.isIE && dojo.isQuirks ? tp(iframe, cs.borderLeftWidth) : 0),
+					top = (dojo.isIE && dojo.isQuirks ? 0 : tp(iframe, cs.paddingTop)) + (dojo.isIE && dojo.isQuirks ? tp(iframe, cs.borderTopWidth) : 0);
+
+				coords.x += ifc.x + left - scroll.x;
+				coords.y += ifc.y + top - scroll.y;
+			}
+		}else{
+			coords = dojo.position(target, true);
+			coords.x += 10;
+			coords.y += 10;
+		}
+
+		var self=this;
+		var savedFocus = dijit.getFocus(this);
+		function closeAndRestoreFocus(){
+			// user has clicked on a menu or popup
+			if(self.refocus){
+				dijit.focus(savedFocus);
+			}
+			dijit.popup.close(self);
+		}
+		dijit.popup.open({
+			popup: this,
+			x: coords.x,
+			y: coords.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._bindings, function(b){ if(b){ this.unBindDomNode(b.node); } }, this);
+ 		this.inherited(arguments);
+	}
 }
-},this);
-this.inherited(arguments);
-}});
+);
+
+// Back-compat (TODO: remove in 2.0)
 dojo.require("dijit.MenuItem");
 dojo.require("dijit.PopupMenuItem");
 dojo.require("dijit.CheckedMenuItem");
 dojo.require("dijit.MenuSeparator");
-}
+
diff --git a/dijit/MenuBar.js b/dijit/MenuBar.js
index 9e9a7fd..65a0833 100644
--- a/dijit/MenuBar.js
+++ b/dijit/MenuBar.js
@@ -1,39 +1,66 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.MenuBar"]){
-dojo._hasResource["dijit.MenuBar"]=true;
 dojo.provide("dijit.MenuBar");
+
 dojo.require("dijit.Menu");
-dojo.declare("dijit.MenuBar",dijit._MenuBase,{templateString:dojo.cache("dijit","templates/MenuBar.html","<div class=\"dijitMenuBar dijitMenuPassive\" dojoAttachPoint=\"containerNode\"  waiRole=\"menubar\" tabIndex=\"${tabIndex}\" dojoAttachEvent=\"onkeypress: _onKeyPress\"></div>\n"),_isMenuBar:true,constructor:function(){
-this._orient=this.isLeftToRight()?{BL:"TL"}:{BR:"TR"};
-},postCreate:function(){
-var k=dojo.keys,l=this.isLeftToRight();
-this.connectKeyNavHandlers(l?[k.LEFT_ARROW]:[k.RIGHT_ARROW],l?[k.RIGHT_ARROW]:[k.LEFT_ARROW]);
-},focusChild:function(_1){
-var _2=this.focusedChild,_3=_2&&_2.popup&&_2.popup.isShowingNow;
-this.inherited(arguments);
-if(_3&&_1.popup&&!_1.disabled){
-this._openPopup();
-}
-},_onKeyPress:function(_4){
-if(_4.ctrlKey||_4.altKey){
-return;
-}
-switch(_4.charOrCode){
-case dojo.keys.DOWN_ARROW:
-this._moveToPopup(_4);
-dojo.stopEvent(_4);
-}
-},onItemClick:function(_5,_6){
-if(_5.popup&&_5.popup.isShowingNow){
-_5.popup.onCancel();
-}else{
-this.inherited(arguments);
-}
-}});
-}
+
+dojo.declare("dijit.MenuBar", dijit._MenuBase, {
+	// summary:
+	//		A menu bar, listing menu choices horizontally, like the "File" menu in most desktop applications
+
+	templateString: dojo.cache("dijit", "templates/MenuBar.html"),
+
+	baseClass: "dijitMenuBar",
+
+	// _isMenuBar: [protected] Boolean
+	//		This is a MenuBar widget, not a (vertical) Menu widget.
+	_isMenuBar: true,
+
+	postCreate: function(){
+		var k = dojo.keys, l = this.isLeftToRight();
+		this.connectKeyNavHandlers(
+			l ? [k.LEFT_ARROW] : [k.RIGHT_ARROW],
+			l ? [k.RIGHT_ARROW] : [k.LEFT_ARROW]
+		);
+
+		// parameter to dijit.popup.open() about where to put popup (relative to this.domNode)
+		this._orient = this.isLeftToRight() ? {BL: 'TL'} : {BR: 'TR'};
+	},
+
+	focusChild: function(item){
+		// overload focusChild so that whenever the focus is moved to a new item,
+		// check the previous focused whether it has its popup open, if so, after
+		// focusing the new item, open its submenu immediately
+		var prev_item = this.focusedChild,
+			showpopup = prev_item && prev_item.popup && prev_item.popup.isShowingNow;
+		this.inherited(arguments);
+		if(showpopup && item.popup && !item.disabled){
+			this._openPopup();		// TODO: on down arrow, _openPopup() is called here and in onItemClick()
+		}
+	},
+
+	_onKeyPress: function(/*Event*/ evt){
+		// summary:
+		//		Handle keyboard based menu navigation.
+		// tags:
+		//		protected
+
+		if(evt.ctrlKey || evt.altKey){ return; }
+
+		switch(evt.charOrCode){
+			case dojo.keys.DOWN_ARROW:
+				this._moveToPopup(evt);
+				dojo.stopEvent(evt);
+		}
+	},
+
+	onItemClick: function(/*dijit._Widget*/ item, /*Event*/ evt){
+		// summary:
+		//		Handle clicks on an item. Cancels a dropdown if already open.
+		// tags:
+		//		private
+		if(item.popup && item.popup.isShowingNow){
+			item.popup.onCancel();
+		}else{
+			this.inherited(arguments);
+		}
+	}
+});
diff --git a/dijit/MenuBarItem.js b/dijit/MenuBarItem.js
index 5f95e8f..d32c2fd 100644
--- a/dijit/MenuBarItem.js
+++ b/dijit/MenuBarItem.js
@@ -1,14 +1,18 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.MenuBarItem"]){
-dojo._hasResource["dijit.MenuBarItem"]=true;
 dojo.provide("dijit.MenuBarItem");
+
 dojo.require("dijit.MenuItem");
-dojo.declare("dijit._MenuBarItemMixin",null,{templateString:dojo.cache("dijit","templates/MenuBarItem.html","<div class=\"dijitReset dijitInline dijitMenuItem dijitMenuItemLabel\" dojoAttachPoint=\"focusNode\" waiRole=\"menuitem\" tabIndex=\"-1\"'\n\t\tdojoAttachEvent=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<span dojoAttachPoint=\"containerNode\"></span>\n</div>\n"),attributeMap:dojo.delegate(dijit._Widget.prototype.attributeMap,{label:{node:"container [...]
-dojo.declare("dijit.MenuBarItem",[dijit.MenuItem,dijit._MenuBarItemMixin],{});
-}
+
+dojo.declare("dijit._MenuBarItemMixin", null, {
+	templateString: dojo.cache("dijit", "templates/MenuBarItem.html"),
+
+	// overriding attributeMap because we don't have icon
+	attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+		label: { node: "containerNode", type: "innerHTML" }
+	})
+});
+
+dojo.declare("dijit.MenuBarItem", [dijit.MenuItem, dijit._MenuBarItemMixin], {
+	// summary:
+	//		Item in a MenuBar that's clickable, and doesn't spawn a submenu when pressed (or hovered)
+
+});
\ No newline at end of file
diff --git a/dijit/MenuItem.js b/dijit/MenuItem.js
index 9f23be0..044d0dc 100644
--- a/dijit/MenuItem.js
+++ b/dijit/MenuItem.js
@@ -1,68 +1,188 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.MenuItem"]){
-dojo._hasResource["dijit.MenuItem"]=true;
 dojo.provide("dijit.MenuItem");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Contained");
-dojo.declare("dijit.MenuItem",[dijit._Widget,dijit._Templated,dijit._Contained],{templateString:dojo.cache("dijit","templates/MenuItem.html","<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\" [...]
-if(_1&&!("label" in this.params)){
-this.attr("label",_1.innerHTML);
-}
-},postCreate:function(){
-dojo.setSelectable(this.domNode,false);
-var _2=this.id+"_text";
-dojo.attr(this.containerNode,"id",_2);
-if(this.accelKeyNode){
-dojo.attr(this.accelKeyNode,"id",this.id+"_accel");
-_2+=" "+this.id+"_accel";
-}
-dijit.setWaiState(this.domNode,"labelledby",_2);
-},_onHover:function(){
-dojo.addClass(this.domNode,"dijitMenuItemHover");
-this.getParent().onItemHover(this);
-},_onUnhover:function(){
-dojo.removeClass(this.domNode,"dijitMenuItemHover");
-this.getParent().onItemUnhover(this);
-},_onClick:function(_3){
-this.getParent().onItemClick(this,_3);
-dojo.stopEvent(_3);
-},onClick:function(_4){
-},focus:function(){
-try{
-if(dojo.isIE==8){
-this.containerNode.focus();
-}
-dijit.focus(this.focusNode);
-}
-catch(e){
-}
-},_onFocus:function(){
-this._setSelected(true);
-this.getParent()._onItemFocus(this);
-this.inherited(arguments);
-},_setSelected:function(_5){
-dojo.toggleClass(this.domNode,"dijitMenuItemSelected",_5);
-},setLabel:function(_6){
-dojo.deprecated("dijit.MenuItem.setLabel() is deprecated.  Use attr('label', ...) instead.","","2.0");
-this.attr("label",_6);
-},setDisabled:function(_7){
-dojo.deprecated("dijit.Menu.setDisabled() is deprecated.  Use attr('disabled', bool) instead.","","2.0");
-this.attr("disabled",_7);
-},_setDisabledAttr:function(_8){
-this.disabled=_8;
-dojo[_8?"addClass":"removeClass"](this.domNode,"dijitMenuItemDisabled");
-dijit.setWaiState(this.focusNode,"disabled",_8?"true":"false");
-},_setAccelKeyAttr:function(_9){
-this.accelKey=_9;
-this.accelKeyNode.style.display=_9?"":"none";
-this.accelKeyNode.innerHTML=_9;
-dojo.attr(this.containerNode,"colSpan",_9?"1":"2");
-}});
-}
+dojo.require("dijit._CssStateMixin");
+
+dojo.declare("dijit.MenuItem",
+		[dijit._Widget, dijit._Templated, dijit._Contained, dijit._CssStateMixin],
+		{
+		// summary:
+		//		A line item in a Menu Widget
+
+		// Make 3 columns
+		// icon, label, and expand arrow (BiDi-dependent) indicating sub-menu
+		templateString: dojo.cache("dijit", "templates/MenuItem.html"),
+
+		attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+			label: { node: "containerNode", type: "innerHTML" },
+			iconClass: { node: "iconNode", type: "class" }
+		}),
+
+		baseClass: "dijitMenuItem",
+
+		// 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.set('label', source.innerHTML);
+			}
+		},
+
+		postCreate: function(){
+			this.inherited(arguments);
+			dojo.setSelectable(this.domNode, false);
+			var label = this.id+"_text";
+			dojo.attr(this.containerNode, "id", label);
+			if(this.accelKeyNode){
+				dojo.attr(this.accelKeyNode, "id", this.id + "_accel");
+				label += " " + this.id + "_accel";
+			}
+			dijit.setWaiState(this.domNode, "labelledby", label);
+		},
+
+		_onHover: function(){
+			// summary:
+			//		Handler when mouse is moved onto menu item
+			// tags:
+			//		protected
+			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
+			this.getParent().onItemUnhover(this);
+
+			// _onUnhover() is called when the menu is hidden (collapsed), due to clicking
+			// a MenuItem and having it execut.  When that happens, FF and IE don't generate
+			// an onmouseout event for the MenuItem, so give _CssStateMixin some help
+			this._hovering = false;
+			this._setStateClass();
+		},
+
+		_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{
+				if(dojo.isIE == 8){
+					// needed for IE8 which won't scroll TR tags into view on focus yet calling scrollIntoView creates flicker (#10275)
+					this.containerNode.focus();
+				}
+				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);
+			this.getParent()._onItemFocus(this);
+
+			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 set('label', ...) instead.
+			// tags:
+			//		deprecated
+			dojo.deprecated("dijit.MenuItem.setLabel() is deprecated.  Use set('label', ...) instead.", "", "2.0");
+			this.set("label", content);
+		},
+
+		setDisabled: function(/*Boolean*/ disabled){
+			// summary:
+			//		Deprecated.   Use set('disabled', bool) instead.
+			// tags:
+			//		deprecated
+			dojo.deprecated("dijit.Menu.setDisabled() is deprecated.  Use set('disabled', bool) instead.", "", "2.0");
+			this.set('disabled', disabled);
+		},
+		_setDisabledAttr: function(/*Boolean*/ value){
+			// summary:
+			//		Hook for attr('disabled', ...) to work.
+			//		Enable or disable this menu item.
+			this.disabled = value;
+			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");
+		}
+	});
diff --git a/dijit/MenuSeparator.js b/dijit/MenuSeparator.js
index 5aad370..3acd1a9 100644
--- a/dijit/MenuSeparator.js
+++ b/dijit/MenuSeparator.js
@@ -1,19 +1,28 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.MenuSeparator"]){
-dojo._hasResource["dijit.MenuSeparator"]=true;
 dojo.provide("dijit.MenuSeparator");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Contained");
-dojo.declare("dijit.MenuSeparator",[dijit._Widget,dijit._Templated,dijit._Contained],{templateString:dojo.cache("dijit","templates/MenuSeparator.html","<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(){
-return false;
-}});
-}
+
+dojo.declare("dijit.MenuSeparator",
+		[dijit._Widget, dijit._Templated, dijit._Contained],
+		{
+		// summary:
+		//		A line between two menu items
+
+		templateString: dojo.cache("dijit", "templates/MenuSeparator.html"),
+
+		postCreate: function(){
+			dojo.setSelectable(this.domNode, false);
+		},
+
+		isFocusable: function(){
+			// summary:
+			//		Override to always return false
+			// tags:
+			//		protected
+
+			return false; // Boolean
+		}
+	});
+
diff --git a/dijit/PopupMenuBarItem.js b/dijit/PopupMenuBarItem.js
index e6181f0..e8fe6f9 100644
--- a/dijit/PopupMenuBarItem.js
+++ b/dijit/PopupMenuBarItem.js
@@ -1,14 +1,10 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.PopupMenuBarItem"]){
-dojo._hasResource["dijit.PopupMenuBarItem"]=true;
 dojo.provide("dijit.PopupMenuBarItem");
+
 dojo.require("dijit.PopupMenuItem");
 dojo.require("dijit.MenuBarItem");
-dojo.declare("dijit.PopupMenuBarItem",[dijit.PopupMenuItem,dijit._MenuBarItemMixin],{});
-}
+
+dojo.declare("dijit.PopupMenuBarItem", [dijit.PopupMenuItem, dijit._MenuBarItemMixin], {
+	// summary:
+	//		Item in a MenuBar like "File" or "Edit", that spawns a submenu when pressed (or hovered)
+});
+
diff --git a/dijit/PopupMenuItem.js b/dijit/PopupMenuItem.js
index 38929f6..3e65ed1 100644
--- a/dijit/PopupMenuItem.js
+++ b/dijit/PopupMenuItem.js
@@ -1,42 +1,64 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.PopupMenuItem"]){
-dojo._hasResource["dijit.PopupMenuItem"]=true;
 dojo.provide("dijit.PopupMenuItem");
+
 dojo.require("dijit.MenuItem");
-dojo.declare("dijit.PopupMenuItem",dijit.MenuItem,{_fillContent:function(){
-if(this.srcNodeRef){
-var _1=dojo.query("*",this.srcNodeRef);
-dijit.PopupMenuItem.superclass._fillContent.call(this,_1[0]);
-this.dropDownContainer=this.srcNodeRef;
-}
-},startup:function(){
-if(this._started){
-return;
-}
-this.inherited(arguments);
-if(!this.popup){
-var _2=dojo.query("[widgetId]",this.dropDownContainer)[0];
-this.popup=dijit.byNode(_2);
-}
-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){
-if(!this.popup._destroyed){
-this.popup.destroyRecursive();
-}
-delete this.popup;
-}
-this.inherited(arguments);
-}});
-}
+
+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.startup();
+
+			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){
+				// Destroy the popup, unless it's already been destroyed.  This can happen because
+				// the popup is a direct child of <body> even though it's logically my child.
+				if(!this.popup._destroyed){
+					this.popup.destroyRecursive();
+				}
+				delete this.popup;
+			}
+			this.inherited(arguments);
+		}
+	});
+
diff --git a/dijit/ProgressBar.js b/dijit/ProgressBar.js
index a8965f5..a90fff0 100644
--- a/dijit/ProgressBar.js
+++ b/dijit/ProgressBar.js
@@ -1,59 +1,135 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.ProgressBar"]){
-dojo._hasResource["dijit.ProgressBar"]=true;
 dojo.provide("dijit.ProgressBar");
+
 dojo.require("dojo.fx");
 dojo.require("dojo.number");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.declare("dijit.ProgressBar",[dijit._Widget,dijit._Templated],{progress:"0",maximum:100,places:0,indeterminate:false,name:"",templateString:dojo.cache("dijit","templates/ProgressBar.html","<div class=\"dijitProgressBar dijitProgressBarEmpty\"\n\t><div waiRole=\"progressbar\" dojoAttachPoint=\"internalProgress\" class=\"dijitProgressBarFull\"\n\t\t><div class=\"dijitProgressBarTile\"></div\n\t\t><span style=\"visibility:hidden\"> </span\n\t></div\n\t><div dojoAttachPoint=\"label\ [...]
-this.inherited(arguments);
-this.indeterminateHighContrastImage.setAttribute("src",this._indeterminateHighContrastImagePath.toString());
-this.update();
-},update:function(_1){
-dojo.mixin(this,_1||{});
-var _2=this.internalProgress;
-var _3=1,_4;
-if(this.indeterminate){
-_4="addClass";
-dijit.removeWaiState(_2,"valuenow");
-dijit.removeWaiState(_2,"valuemin");
-dijit.removeWaiState(_2,"valuemax");
-}else{
-_4="removeClass";
-if(String(this.progress).indexOf("%")!=-1){
-_3=Math.min(parseFloat(this.progress)/100,1);
-this.progress=_3*this.maximum;
-}else{
-this.progress=Math.min(this.progress,this.maximum);
-_3=this.progress/this.maximum;
-}
-var _5=this.report(_3);
-this.label.firstChild.nodeValue=_5;
-dijit.setWaiState(_2,"describedby",this.label.id);
-dijit.setWaiState(_2,"valuenow",this.progress);
-dijit.setWaiState(_2,"valuemin",0);
-dijit.setWaiState(_2,"valuemax",this.maximum);
-}
-dojo[_4](this.domNode,"dijitProgressBarIndeterminate");
-_2.style.width=(_3*100)+"%";
-this.onChange();
-},_setValueAttr:function(v){
-if(v==Infinity){
-this.update({indeterminate:true});
-}else{
-this.update({indeterminate:false,progress:v});
-}
-},_getValueAttr:function(){
-return this.progress;
-},report:function(_6){
-return dojo.number.format(_6,{type:"percent",places:this.places,locale:this.lang});
-},onChange:function(){
-}});
-}
+
+dojo.declare("dijit.ProgressBar", [dijit._Widget, dijit._Templated], {
+	// summary:
+	//		A progress indication widget, showing the amount completed
+	//		(often the percentage completed) of a task.
+	//
+	// example:
+	// |	<div dojoType="ProgressBar"
+	// |		 places="0"
+	// |		 progress="..." maximum="...">
+	// |	</div>
+	//
+	// description:
+	//		Note that the progress bar is updated via (a non-standard)
+	//		update() method, rather than via attr() like other widgets.
+
+	// progress: [const] String (Percentage or Number)
+	//		Number or percentage indicating amount of task completed.
+	// 		With "%": percentage value, 0% <= progress <= 100%, or
+	// 		without "%": absolute value, 0 <= progress <= maximum
+	// TODO: rename to value for 2.0
+	progress: "0",
+
+	// maximum: [const] Float
+	//		Max sample number
+	maximum: 100,
+
+	// places: [const] Number
+	//		Number of places to show in values; 0 by default
+	places: 0,
+
+	// indeterminate: [const] Boolean
+	// 		If false: show progress value (number or percentage).
+	// 		If true: show that a process is underway but that the amount completed is unknown.
+	indeterminate: false,
+
+	// name: String
+	//		this is the field name (for a form) if set. This needs to be set if you want to use
+	//		this widget in a dijit.form.Form widget (such as dijit.Dialog)
+	name: '',
+
+	templateString: dojo.cache("dijit", "templates/ProgressBar.html"),
+
+	// _indeterminateHighContrastImagePath: [private] dojo._URL
+	//		URL to image to use for indeterminate progress bar when display is in high contrast mode
+	_indeterminateHighContrastImagePath:
+		dojo.moduleUrl("dijit", "themes/a11y/indeterminate_progress.gif"),
+
+	// public functions
+	postCreate: function(){
+		this.inherited(arguments);
+		this.indeterminateHighContrastImage.setAttribute("src",
+			this._indeterminateHighContrastImagePath.toString());
+		this.update();
+	},
+
+	update: function(/*Object?*/attributes){
+		// summary:
+		//		Change attributes of ProgressBar, similar to attr(hash).
+		//
+		// attributes:
+		//		May provide progress and/or maximum properties on this parameter;
+		//		see attribute specs for details.
+		//
+		// example:
+		//	|	myProgressBar.update({'indeterminate': true});
+		//	|	myProgressBar.update({'progress': 80});
+
+		// TODO: deprecate this method and use set() instead
+
+		dojo.mixin(this, attributes || {});
+		var tip = this.internalProgress;
+		var percent = 1, classFunc;
+		if(this.indeterminate){
+			classFunc = "addClass";
+			dijit.removeWaiState(tip, "valuenow");
+			dijit.removeWaiState(tip, "valuemin");
+			dijit.removeWaiState(tip, "valuemax");
+		}else{
+			classFunc = "removeClass";
+			if(String(this.progress).indexOf("%") != -1){
+				percent = Math.min(parseFloat(this.progress)/100, 1);
+				this.progress = percent * this.maximum;
+			}else{
+				this.progress = Math.min(this.progress, this.maximum);
+				percent = this.progress / this.maximum;
+			}
+			var text = this.report(percent);
+			this.label.firstChild.nodeValue = text;
+			dijit.setWaiState(tip, "describedby", this.label.id);
+			dijit.setWaiState(tip, "valuenow", this.progress);
+			dijit.setWaiState(tip, "valuemin", 0);
+			dijit.setWaiState(tip, "valuemax", this.maximum);
+		}
+		dojo[classFunc](this.domNode, "dijitProgressBarIndeterminate");
+		tip.style.width = (percent * 100) + "%";
+		this.onChange();
+	},
+
+	_setValueAttr: function(v){
+		if(v == Infinity){
+			this.update({indeterminate:true});
+		}else{
+			this.update({indeterminate:false, progress:v});
+		}
+	},
+
+	_getValueAttr: function(){
+		return this.progress;
+	},
+
+	report: function(/*float*/percent){
+		// summary:
+		//		Generates message to show inside progress bar (normally indicating amount of task completed).
+		//		May be overridden.
+		// tags:
+		//		extension
+
+		return dojo.number.format(percent, { type: "percent", places: this.places, locale: this.lang });
+	},
+
+	onChange: function(){
+		// summary:
+		//		Callback fired when progress updates.
+		// tags:
+		//		progress
+	}
+});
diff --git a/dijit/TitlePane.js b/dijit/TitlePane.js
index 4ca186a..46899eb 100644
--- a/dijit/TitlePane.js
+++ b/dijit/TitlePane.js
@@ -1,116 +1,240 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.TitlePane"]){
-dojo._hasResource["dijit.TitlePane"]=true;
 dojo.provide("dijit.TitlePane");
+
 dojo.require("dojo.fx");
+
 dojo.require("dijit._Templated");
 dojo.require("dijit.layout.ContentPane");
-dojo.declare("dijit.TitlePane",[dijit.layout.ContentPane,dijit._Templated],{title:"",open:true,toggleable:true,tabIndex:"0",duration:dijit.defaultDuration,baseClass:"dijitTitlePane",templateString:dojo.cache("dijit","templates/TitlePane.html","<div class=\"${baseClass}\">\n\t<div dojoAttachEvent=\"onclick:_onTitleClick, onkeypress:_onTitleKey, onfocus:_handleFocus, onblur:_handleFocus, onmouseenter:_onTitleEnter, onmouseleave:_onTitleLeave\"\n\t\t\tclass=\"dijitTitlePaneTitle\" dojoAttac [...]
-if(!this.open){
-this.hideNode.style.display=this.wipeNode.style.display="none";
-}
-this._setCss();
-dojo.setSelectable(this.titleNode,false);
-dijit.setWaiState(this.containerNode,"hidden",this.open?"false":"true");
-dijit.setWaiState(this.focusNode,"pressed",this.open?"true":"false");
-var _1=this.hideNode,_2=this.wipeNode;
-this._wipeIn=dojo.fx.wipeIn({node:this.wipeNode,duration:this.duration,beforeBegin:function(){
-_1.style.display="";
-}});
-this._wipeOut=dojo.fx.wipeOut({node:this.wipeNode,duration:this.duration,onEnd:function(){
-_1.style.display="none";
-}});
-this.inherited(arguments);
-},_setOpenAttr:function(_3){
-if(this.open!==_3){
-this.toggle();
-}
-},_setToggleableAttr:function(_4){
-this.toggleable=_4;
-dijit.setWaiRole(this.focusNode,_4?"button":"heading");
-dojo.attr(this.focusNode,"tabIndex",_4?this.tabIndex:"-1");
-if(_4){
-dijit.setWaiState(this.focusNode,"controls",this.id+"_pane");
-}
-this._setCss();
-},_setContentAttr:function(_5){
-if(!this.open||!this._wipeOut||this._wipeOut.status()=="playing"){
-this.inherited(arguments);
-}else{
-if(this._wipeIn&&this._wipeIn.status()=="playing"){
-this._wipeIn.stop();
-}
-dojo.marginBox(this.wipeNode,{h:dojo.marginBox(this.wipeNode).h});
-this.inherited(arguments);
-if(this._wipeIn){
-this._wipeIn.play();
-}else{
-this.hideNode.style.display="";
-}
-}
-},toggle:function(){
-dojo.forEach([this._wipeIn,this._wipeOut],function(_6){
-if(_6&&_6.status()=="playing"){
-_6.stop();
-}
+dojo.require("dijit._CssStateMixin");
+
+dojo.declare(
+	"dijit.TitlePane",
+	[dijit.layout.ContentPane, dijit._Templated, dijit._CssStateMixin],
+{
+	// 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 useful 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,
+
+	// toggleable: Boolean
+	//		Whether pane can be opened or closed by clicking the title bar.
+	toggleable: true,
+
+	// tabIndex: String
+	//		Tabindex setting for the title (so users can tab to the title then
+	//		use space/enter to open/close the title pane)
+	tabIndex: "0",
+
+	// duration: Integer
+	//		Time in milliseconds to fade in/fade out
+	duration: dijit.defaultDuration,
+
+	// baseClass: [protected] String
+	//		The root className to be placed on this widget's domNode.
+	baseClass: "dijitTitlePane",
+
+	templateString: dojo.cache("dijit", "templates/TitlePane.html"),
+
+	attributeMap: dojo.delegate(dijit.layout.ContentPane.prototype.attributeMap, {
+		title: { node: "titleNode", type: "innerHTML" },
+		tooltip: {node: "focusNode", type: "attribute", attribute: "title"},	// focusNode spans the entire width, titleNode doesn't
+		id:""
+	}),
+
+	postCreate: function(){
+		if(!this.open){
+			this.hideNode.style.display = this.wipeNode.style.display = "none";
+		}
+		
+		// Hover and focus effect on title bar, except for non-toggleable TitlePanes
+		// This should really be controlled from _setToggleableAttr() but _CssStateMixin
+		// doesn't provide a way to disconnect a previous _trackMouseState() call
+		if(this.toggleable){
+			this._trackMouseState(this.titleBarNode, "dijitTitlePaneTitle");
+		}
+		this._setCss();
+		dojo.setSelectable(this.titleNode, false);
+
+		// 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(); }
+		dijit.setWaiState(this.containerNode,"hidden", this.open ? "false" : "true");
+		dijit.setWaiState(this.focusNode, "pressed", this.open ? "true" : "false");
+	},
+
+	_setToggleableAttr: function(/* Boolean */ canToggle){
+		// summary:
+		//		Hook to make attr("canToggle", boolean) work.
+		// canToggle: Boolean
+		//		True to allow user to open/close pane by clicking title bar.
+		this.toggleable = canToggle;
+		dijit.setWaiRole(this.focusNode, canToggle ? "button" : "heading");
+		if(canToggle){
+			// TODO: if canToggle is switched from true false shouldn't we remove this setting?
+			dijit.setWaiState(this.focusNode, "controls", this.id+"_pane");
+			dojo.attr(this.focusNode, "tabIndex", this.tabIndex);
+		}
+		else{
+			dojo.removeAttr(this.focusNode, "tabIndex");
+		}
+		this._setCss();
+	},
+
+	_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)
+		if(this.open){
+			this._onShow();
+		}else{
+			this.onHide();
+		}
+
+		this._setCss();
+	},
+
+	_setCss: function(){
+		// summary:
+		//		Set the open/close css state for the TitlePane
+		// tags:
+		//		private
+
+		var node = this.titleBarNode || this.focusNode;
+
+		if(this._titleBarClass){
+			dojo.removeClass(node, this._titleBarClass);
+		}
+		this._titleBarClass = "dijit" + (this.toggleable ? "" : "Fixed") + (this.open ? "Open" : "Closed");
+		dojo.addClass(node, this._titleBarClass);
+		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 == ' '){
+			if(this.toggleable){
+				this.toggle();
+			}
+			dojo.stopEvent(e);
+		}else if(e.charOrCode == dojo.keys.DOWN_ARROW && this.open){
+			this.containerNode.focus();
+			e.preventDefault();
+	 	}
+	},
+
+	_onTitleClick: function(){
+		// summary:
+		//		Handler when user clicks the title bar
+		// tags:
+		//		private
+		if(this.toggleable){
+			this.toggle();
+		}
+	},
+
+	setTitle: function(/*String*/ title){
+		// summary:
+		//		Deprecated.  Use set('title', ...) instead.
+		// tags:
+		//		deprecated
+		dojo.deprecated("dijit.TitlePane.setTitle() is deprecated.  Use set('title', ...) instead.", "", "2.0");
+		this.set("title", title);
+	}
 });
-var _7=this[this.open?"_wipeOut":"_wipeIn"];
-if(_7){
-_7.play();
-}else{
-this.hideNode.style.display=this.open?"":"none";
-}
-this.open=!this.open;
-dijit.setWaiState(this.containerNode,"hidden",this.open?"false":"true");
-dijit.setWaiState(this.focusNode,"pressed",this.open?"true":"false");
-if(this.open){
-this._onShow();
-}else{
-this.onHide();
-}
-this._setCss();
-},_setCss:function(){
-var _8=this.titleBarNode||this.focusNode;
-if(this._titleBarClass){
-dojo.removeClass(_8,this._titleBarClass);
-}
-this._titleBarClass="dijit"+(this.toggleable?"":"Fixed")+(this.open?"Open":"Closed");
-dojo.addClass(_8,this._titleBarClass);
-this.arrowNodeInner.innerHTML=this.open?"-":"+";
-},_onTitleKey:function(e){
-if(e.charOrCode==dojo.keys.ENTER||e.charOrCode==" "){
-if(this.toggleable){
-this.toggle();
-}
-dojo.stopEvent(e);
-}else{
-if(e.charOrCode==dojo.keys.DOWN_ARROW&&this.open){
-this.containerNode.focus();
-e.preventDefault();
-}
-}
-},_onTitleEnter:function(){
-if(this.toggleable){
-dojo.addClass(this.focusNode,"dijitTitlePaneTitle-hover");
-}
-},_onTitleLeave:function(){
-if(this.toggleable){
-dojo.removeClass(this.focusNode,"dijitTitlePaneTitle-hover");
-}
-},_onTitleClick:function(){
-if(this.toggleable){
-this.toggle();
-}
-},_handleFocus:function(e){
-dojo.toggleClass(this.focusNode,this.baseClass+"Focused",e.type=="focus");
-},setTitle:function(_9){
-dojo.deprecated("dijit.TitlePane.setTitle() is deprecated.  Use attr('title', ...) instead.","","2.0");
-this.attr("title",_9);
-}});
-}
diff --git a/dijit/Toolbar.js b/dijit/Toolbar.js
index 70480cd..8099b44 100644
--- a/dijit/Toolbar.js
+++ b/dijit/Toolbar.js
@@ -1,24 +1,41 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.Toolbar"]){
-dojo._hasResource["dijit.Toolbar"]=true;
 dojo.provide("dijit.Toolbar");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._KeyNavContainer");
 dojo.require("dijit._Templated");
-dojo.declare("dijit.Toolbar",[dijit._Widget,dijit._Templated,dijit._KeyNavContainer],{templateString:"<div class=\"dijit dijitToolbar\" waiRole=\"toolbar\" tabIndex=\"${tabIndex}\" dojoAttachPoint=\"containerNode\">"+"</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;
+
+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" 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>',
+
+	baseClass: "dijitToolbar",
+
+	postCreate: function(){
+		this.connectKeyNavHandlers(
+			this.isLeftToRight() ? [dojo.keys.LEFT_ARROW] : [dojo.keys.RIGHT_ARROW],
+			this.isLeftToRight() ? [dojo.keys.RIGHT_ARROW] : [dojo.keys.LEFT_ARROW]
+		);
+		this.inherited(arguments);
+	},
+
+	startup: function(){
+		if(this._started){ return; }
+
+		this.startupKeyNavChildren();
+
+		this.inherited(arguments);
+	}
 }
-this.startupKeyNavChildren();
-this.inherited(arguments);
-}});
+);
+
+// For back-compat, remove for 2.0
 dojo.require("dijit.ToolbarSeparator");
-}
diff --git a/dijit/ToolbarSeparator.js b/dijit/ToolbarSeparator.js
index 76644d9..987bbee 100644
--- a/dijit/ToolbarSeparator.js
+++ b/dijit/ToolbarSeparator.js
@@ -1,18 +1,23 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.ToolbarSeparator"]){
-dojo._hasResource["dijit.ToolbarSeparator"]=true;
 dojo.provide("dijit.ToolbarSeparator");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.declare("dijit.ToolbarSeparator",[dijit._Widget,dijit._Templated],{templateString:"<div class=\"dijitToolbarSeparator dijitInline\"></div>",postCreate:function(){
-dojo.setSelectable(this.domNode,false);
-},isFocusable:function(){
-return false;
-}});
-}
+
+dojo.declare("dijit.ToolbarSeparator",
+		[ dijit._Widget, dijit._Templated ],
+		{
+		// summary:
+		//		A spacer between two `dijit.Toolbar` items
+		templateString: '<div class="dijitToolbarSeparator dijitInline" waiRole="presentation"></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;
+		}
+
+	});
+
+
diff --git a/dijit/Tooltip.js b/dijit/Tooltip.js
index 8379b34..17db535 100644
--- a/dijit/Tooltip.js
+++ b/dijit/Tooltip.js
@@ -1,158 +1,374 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.Tooltip"]){
-dojo._hasResource["dijit.Tooltip"]=true;
 dojo.provide("dijit.Tooltip");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.declare("dijit._MasterTooltip",[dijit._Widget,dijit._Templated],{duration:dijit.defaultDuration,templateString:dojo.cache("dijit","templates/Tooltip.html","<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);
-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(_1,_2,_3){
-if(this.aroundNode&&this.aroundNode===_2){
-return;
-}
-if(this.fadeOut.status()=="playing"){
-this._onDeck=arguments;
-return;
-}
-this.containerNode.innerHTML=_1;
-this.domNode.style.top=(this.domNode.offsetTop+1)+"px";
-var _4=dijit.placeOnScreenAroundElement(this.domNode,_2,dijit.getPopupAroundAlignment((_3&&_3.length)?_3:dijit.Tooltip.defaultPosition,this.isLeftToRight()),dojo.hitch(this,"orient"));
-dojo.style(this.domNode,"opacity",0);
-this.fadeIn.play();
-this.isShowingNow=true;
-this.aroundNode=_2;
-},orient:function(_5,_6,_7){
-_5.className="dijitTooltip "+{"BL-TL":"dijitTooltipBelow dijitTooltipABLeft","TL-BL":"dijitTooltipAbove dijitTooltipABLeft","BR-TR":"dijitTooltipBelow dijitTooltipABRight","TR-BR":"dijitTooltipAbove dijitTooltipABRight","BR-BL":"dijitTooltipRight","BL-BR":"dijitTooltipLeft"}[_6+"-"+_7];
-},_onShow:function(){
-if(dojo.isIE){
-this.domNode.style.filter="";
-}
-},hide:function(_8){
-if(this._onDeck&&this._onDeck[1]==_8){
-this._onDeck=null;
-}else{
-if(this.aroundNode===_8){
-this.fadeIn.stop();
-this.isShowingNow=false;
-this.aroundNode=null;
-this.fadeOut.play();
-}else{
-}
-}
-},_onHide:function(){
-this.domNode.style.cssText="";
-if(this._onDeck){
-this.show.apply(this,this._onDeck);
-this._onDeck=null;
-}
-}});
-dijit.showTooltip=function(_9,_a,_b){
-if(!dijit._masterTT){
-dijit._masterTT=new dijit._MasterTooltip();
-}
-return dijit._masterTT.show(_9,_a,_b);
+
+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: dojo.cache("dijit", "templates/Tooltip.html"),
+
+		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, /*Boolean*/ rtl){
+			// summary:
+			//		Display tooltip w/specified contents to right of specified node
+			//		(To left if there's no space on the right, or if rtl == true)
+
+			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;
+
+			var pos = dijit.placeOnScreenAroundElement(this.domNode, aroundNode, dijit.getPopupAroundAlignment((position && position.length) ? position : dijit.Tooltip.defaultPosition, !rtl), 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
+			this.containerNode.innerHTML="";
+			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, /*Boolean*/ rtl){
+	// 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, rtl);
 };
-dijit.hideTooltip=function(_c){
-if(!dijit._masterTT){
-dijit._masterTT=new dijit._MasterTooltip();
-}
-return dijit._masterTT.hide(_c);
+
+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,{label:"",showDelay:400,connectId:[],position:[],constructor:function(){
-this._nodeConnectionsById={};
-},_setConnectIdAttr:function(_d){
-for(var _e in this._nodeConnectionsById){
-this.removeTarget(_e);
-}
-dojo.forEach(dojo.isArrayLike(_d)?_d:[_d],this.addTarget,this);
-},_getConnectIdAttr:function(){
-var _f=[];
-for(var id in this._nodeConnectionsById){
-_f.push(id);
-}
-return _f;
-},addTarget:function(id){
-var _10=dojo.byId(id);
-if(!_10){
-return;
-}
-if(_10.id in this._nodeConnectionsById){
-return;
-}
-this._nodeConnectionsById[_10.id]=[this.connect(_10,"onmouseenter","_onTargetMouseEnter"),this.connect(_10,"onmouseleave","_onTargetMouseLeave"),this.connect(_10,"onfocus","_onTargetFocus"),this.connect(_10,"onblur","_onTargetBlur")];
-if(dojo.isIE&&!_10.style.zoom){
-_10.style.zoom=1;
-}
-},removeTarget:function(_11){
-var id=_11.id||_11;
-if(id in this._nodeConnectionsById){
-dojo.forEach(this._nodeConnectionsById[id],this.disconnect,this);
-delete this._nodeConnectionsById[id];
-}
-},postCreate:function(){
-dojo.addClass(this.domNode,"dijitTooltipData");
-},startup:function(){
-this.inherited(arguments);
-var ids=this.connectId;
-dojo.forEach(dojo.isArrayLike(ids)?ids:[ids],this.addTarget,this);
-},_onTargetMouseEnter:function(e){
-this._onHover(e);
-},_onTargetMouseLeave:function(e){
-this._onUnHover(e);
-},_onTargetFocus:function(e){
-this._focus=true;
-this._onHover(e);
-},_onTargetBlur:function(e){
-this._focus=false;
-this._onUnHover(e);
-},_onHover:function(e){
-if(!this._showTimer){
-var _12=e.target;
-this._showTimer=setTimeout(dojo.hitch(this,function(){
-this.open(_12);
-}),this.showDelay);
-}
-},_onUnHover:function(e){
-if(this._focus){
-return;
-}
-if(this._showTimer){
-clearTimeout(this._showTimer);
-delete this._showTimer;
-}
-this.close();
-},open:function(_13){
-if(this._showTimer){
-clearTimeout(this._showTimer);
-delete this._showTimer;
-}
-dijit.showTooltip(this.label||this.domNode.innerHTML,_13,this.position);
-this._connectNode=_13;
-this.onShow(_13,this.position);
-},close:function(){
-if(this._connectNode){
-dijit.hideTooltip(this._connectNode);
-delete this._connectNode;
-this.onHide();
-}
-if(this._showTimer){
-clearTimeout(this._showTimer);
-delete this._showTimer;
-}
-},onShow:function(_14,_15){
-},onHide:function(){
-},uninitialize:function(){
-this.close();
-this.inherited(arguments);
-}});
-dijit.Tooltip.defaultPosition=["after","before"];
-}
+
+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: [],
+
+		constructor: function(){
+			// Map id's of nodes I'm connected to to a list of the this.connect() handles
+			this._nodeConnectionsById = {};
+		},
+
+		_setConnectIdAttr: function(newIds){
+			for(var oldId in this._nodeConnectionsById){
+				this.removeTarget(oldId);
+			}
+			dojo.forEach(dojo.isArrayLike(newIds) ? newIds : [newIds], this.addTarget, this);
+		},
+
+		_getConnectIdAttr: function(){
+			var ary = [];
+			for(var id in this._nodeConnectionsById){
+				ary.push(id);
+			}
+			return ary;
+		},
+
+		addTarget: function(/*DOMNODE || String*/ id){
+			// summary:
+			//		Attach tooltip to specified node, if it's not already connected
+			var node = dojo.byId(id);
+			if(!node){ return; }
+			if(node.id in this._nodeConnectionsById){ return; }//Already connected
+
+			this._nodeConnectionsById[node.id] = [
+				this.connect(node, "onmouseenter", "_onTargetMouseEnter"),
+				this.connect(node, "onmouseleave", "_onTargetMouseLeave"),
+				this.connect(node, "onfocus", "_onTargetFocus"),
+				this.connect(node, "onblur", "_onTargetBlur")
+			];
+		},
+
+		removeTarget: function(/*DOMNODE || String*/ node){
+			// summary:
+			//		Detach tooltip from specified node
+
+			// map from DOMNode back to plain id string
+			var id = node.id || node;
+
+			if(id in this._nodeConnectionsById){
+				dojo.forEach(this._nodeConnectionsById[id], this.disconnect, this);
+				delete this._nodeConnectionsById[id];
+			}
+		},
+
+		postCreate: function(){
+			dojo.addClass(this.domNode,"dijitTooltipData");
+		},
+
+		startup: function(){
+			this.inherited(arguments);
+
+			// If this tooltip was created in a template, or for some other reason the specified connectId[s]
+			// didn't exist during the widget's initialization, then connect now.
+			var ids = this.connectId;
+			dojo.forEach(dojo.isArrayLike(ids) ? ids : [ids], this.addTarget, this);
+		},
+
+		_onTargetMouseEnter: function(/*Event*/ e){
+			// summary:
+			//		Handler for mouseenter event on the target node
+			// tags:
+			//		private
+			this._onHover(e);
+		},
+
+		_onTargetMouseLeave: function(/*Event*/ e){
+			// summary:
+			//		Handler for mouseleave event on the target node
+			// tags:
+			//		private
+			this._onUnHover(e);
+		},
+
+		_onTargetFocus: function(/*Event*/ e){
+			// summary:
+			//		Handler for focus event on the target node
+			// tags:
+			//		private
+
+			this._focus = true;
+			this._onHover(e);
+		},
+
+		_onTargetBlur: function(/*Event*/ e){
+			// summary:
+			//		Handler for blur event on the target node
+			// tags:
+			//		private
+
+			this._focus = false;
+			this._onUnHover(e);
+		},
+
+		_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
+
+			if(this._showTimer){
+				clearTimeout(this._showTimer);
+				delete this._showTimer;
+			}
+			dijit.showTooltip(this.label || this.domNode.innerHTML, target, this.position, !this.isLeftToRight());
+
+			this._connectNode = target;
+			this.onShow(target, this.position);
+		},
+
+		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;
+				this.onHide();
+			}
+			if(this._showTimer){
+				// if tooltip is scheduled to be shown (after a brief delay)
+				clearTimeout(this._showTimer);
+				delete this._showTimer;
+			}
+		},
+
+		onShow: function(target, position){
+			// summary:
+			//		Called when the tooltip is shown
+			// tags:
+			//		callback
+		},
+
+		onHide: function(){
+			// summary:
+			//		Called when the tooltip is hidden
+			// tags:
+			//		callback
+		},
+
+		uninitialize: function(){
+			this.close();
+			this.inherited(arguments);
+		}
+	}
+);
+
+// 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"];
diff --git a/dijit/TooltipDialog.js b/dijit/TooltipDialog.js
index 49feb3a..60ea483 100644
--- a/dijit/TooltipDialog.js
+++ b/dijit/TooltipDialog.js
@@ -1,66 +1,130 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.TooltipDialog"]){
-dojo._hasResource["dijit.TooltipDialog"]=true;
 dojo.provide("dijit.TooltipDialog");
+
 dojo.require("dijit.layout.ContentPane");
 dojo.require("dijit._Templated");
 dojo.require("dijit.form._FormMixin");
 dojo.require("dijit._DialogMixin");
-dojo.declare("dijit.TooltipDialog",[dijit.layout.ContentPane,dijit._Templated,dijit.form._FormMixin,dijit._DialogMixin],{title:"",doLayout:false,autofocus:true,baseClass:"dijitTooltipDialog",_firstFocusItem:null,_lastFocusItem:null,templateString:dojo.cache("dijit","templates/TooltipDialog.html","<div waiRole=\"presentation\">\n\t<div class=\"dijitTooltipContainer\" waiRole=\"presentation\">\n\t\t<div class =\"dijitTooltipContents dijitTooltipFocusNode\" dojoAttachPoint=\"containerNode\" [...]
-this.inherited(arguments);
-this.connect(this.containerNode,"onkeypress","_onKey");
-this.containerNode.title=this.title;
-},orient:function(_1,_2,_3){
-var c=this._currentOrientClass;
-if(c){
-dojo.removeClass(this.domNode,c);
-}
-c="dijitTooltipAB"+(_3.charAt(1)=="L"?"Left":"Right")+" dijitTooltip"+(_3.charAt(0)=="T"?"Below":"Above");
-dojo.addClass(this.domNode,c);
-this._currentOrientClass=c;
-},onOpen:function(_4){
-this.orient(this.domNode,_4.aroundCorner,_4.corner);
-this._onShow();
-if(this.autofocus){
-this._getFocusItems(this.containerNode);
-dijit.focus(this._firstFocusItem);
-}
-},onClose:function(){
-this.onHide();
-},_onKey:function(_5){
-var _6=_5.target;
-var dk=dojo.keys;
-if(_5.charOrCode===dk.TAB){
-this._getFocusItems(this.containerNode);
-}
-var _7=(this._firstFocusItem==this._lastFocusItem);
-if(_5.charOrCode==dk.ESCAPE){
-setTimeout(dojo.hitch(this,"onCancel"),0);
-dojo.stopEvent(_5);
-}else{
-if(_6==this._firstFocusItem&&_5.shiftKey&&_5.charOrCode===dk.TAB){
-if(!_7){
-dijit.focus(this._lastFocusItem);
-}
-dojo.stopEvent(_5);
-}else{
-if(_6==this._lastFocusItem&&_5.charOrCode===dk.TAB&&!_5.shiftKey){
-if(!_7){
-dijit.focus(this._firstFocusItem);
-}
-dojo.stopEvent(_5);
-}else{
-if(_5.charOrCode===dk.TAB){
-_5.stopPropagation();
-}
-}
-}
-}
-}});
-}
+
+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: dojo.cache("dijit", "templates/TooltipDialog.html"),
+
+			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);
+				}
+			},
+
+			onClose: function(){
+				// summary:
+				//		Called when dialog is hidden.
+				//		This is called from the dijit.popup code, and should not be called directly.
+				// tags:
+				//		protected
+				this.onHide();
+			},
+
+			_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){
+					// Use setTimeout to avoid crash on IE, see #10396.
+					setTimeout(dojo.hitch(this, "onCancel"), 0);
+					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();
+				}
+			}
+		}
+	);
diff --git a/dijit/Tree.js b/dijit/Tree.js
index 4ac6dfc..e402326 100644
--- a/dijit/Tree.js
+++ b/dijit/Tree.js
@@ -1,665 +1,1600 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.Tree"]){
-dojo._hasResource["dijit.Tree"]=true;
 dojo.provide("dijit.Tree");
+
 dojo.require("dojo.fx");
 dojo.require("dojo.DeferredList");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Container");
 dojo.require("dijit._Contained");
+dojo.require("dijit._CssStateMixin");
 dojo.require("dojo.cookie");
-dojo.declare("dijit._TreeNode",[dijit._Widget,dijit._Templated,dijit._Container,dijit._Contained],{item:null,isTreeNode:true,label:"",isExpandable:null,isExpanded:false,state:"UNCHECKED",templateString:dojo.cache("dijit","templates/TreeNode.html","<div class=\"dijitTreeNode\" waiRole=\"presentation\"\n\t><div dojoAttachPoint=\"rowNode\" class=\"dijitTreeRow\" waiRole=\"presentation\" dojoAttachEvent=\"onmouseenter:_onMouseEnter, onmouseleave:_onMouseLeave, onclick:_onClick, ondblclick:_o [...]
-this._setExpando();
-this._updateItemClasses(this.item);
-if(this.isExpandable){
-dijit.setWaiState(this.labelNode,"expanded",this.isExpanded);
-}
-},_setIndentAttr:function(_1){
-this.indent=_1;
-var _2=(Math.max(_1,0)*this.tree._nodePixelIndent)+"px";
-dojo.style(this.domNode,"backgroundPosition",_2+" 0px");
-dojo.style(this.rowNode,dojo._isBodyLtr()?"paddingLeft":"paddingRight",_2);
-dojo.forEach(this.getChildren(),function(_3){
-_3.attr("indent",_1+1);
-});
-},markProcessing:function(){
-this.state="LOADING";
-this._setExpando(true);
-},unmarkProcessing:function(){
-this._setExpando(false);
-},_updateItemClasses:function(_4){
-var _5=this.tree,_6=_5.model;
-if(_5._v10Compat&&_4===_6.root){
-_4=null;
-}
-this._applyClassAndStyle(_4,"icon","Icon");
-this._applyClassAndStyle(_4,"label","Label");
-this._applyClassAndStyle(_4,"row","Row");
-},_applyClassAndStyle:function(_7,_8,_9){
-var _a="_"+_8+"Class";
-var _b=_8+"Node";
-if(this[_a]){
-dojo.removeClass(this[_b],this[_a]);
-}
-this[_a]=this.tree["get"+_9+"Class"](_7,this.isExpanded);
-if(this[_a]){
-dojo.addClass(this[_b],this[_a]);
-}
-dojo.style(this[_b],this.tree["get"+_9+"Style"](_7,this.isExpanded)||{});
-},_updateLayout:function(){
-var _c=this.getParent();
-if(!_c||_c.rowNode.style.display=="none"){
-dojo.addClass(this.domNode,"dijitTreeIsRoot");
-}else{
-dojo.toggleClass(this.domNode,"dijitTreeIsLast",!this.getNextSibling());
-}
-},_setExpando:function(_d){
-var _e=["dijitTreeExpandoLoading","dijitTreeExpandoOpened","dijitTreeExpandoClosed","dijitTreeExpandoLeaf"],_f=["*","-","+","*"],idx=_d?0:(this.isExpandable?(this.isExpanded?1:2):3);
-dojo.removeClass(this.expandoNode,_e);
-dojo.addClass(this.expandoNode,_e[idx]);
-this.expandoNodeText.innerHTML=_f[idx];
-},expand:function(){
-if(this._expandDeferred){
-return this._expandDeferred;
-}
-this._wipeOut&&this._wipeOut.stop();
-this.isExpanded=true;
-dijit.setWaiState(this.labelNode,"expanded","true");
-dijit.setWaiRole(this.containerNode,"group");
-dojo.addClass(this.contentNode,"dijitTreeContentExpanded");
-this._setExpando();
-this._updateItemClasses(this.item);
-if(this==this.tree.rootNode){
-dijit.setWaiState(this.tree.domNode,"expanded","true");
-}
-var def,_10=dojo.fx.wipeIn({node:this.containerNode,duration:dijit.defaultDuration,onEnd:function(){
-def.callback(true);
-}});
-def=(this._expandDeferred=new dojo.Deferred(function(){
-_10.stop();
-}));
-_10.play();
-return def;
-},collapse:function(){
-if(!this.isExpanded){
-return;
-}
-if(this._expandDeferred){
-this._expandDeferred.cancel();
-delete this._expandDeferred;
-}
-this.isExpanded=false;
-dijit.setWaiState(this.labelNode,"expanded","false");
-if(this==this.tree.rootNode){
-dijit.setWaiState(this.tree.domNode,"expanded","false");
-}
-dojo.removeClass(this.contentNode,"dijitTreeContentExpanded");
-this._setExpando();
-this._updateItemClasses(this.item);
-if(!this._wipeOut){
-this._wipeOut=dojo.fx.wipeOut({node:this.containerNode,duration:dijit.defaultDuration});
-}
-this._wipeOut.play();
-},indent:0,setChildItems:function(_11){
-var _12=this.tree,_13=_12.model,_14=[];
-this.getChildren().forEach(function(_15){
-dijit._Container.prototype.removeChild.call(this,_15);
-},this);
-this.state="LOADED";
-if(_11&&_11.length>0){
-this.isExpandable=true;
-dojo.forEach(_11,function(_16){
-var id=_13.getIdentity(_16),_17=_12._itemNodesMap[id],_18;
-if(_17){
-for(var i=0;i<_17.length;i++){
-if(_17[i]&&!_17[i].getParent()){
-_18=_17[i];
-_18.attr("indent",this.indent+1);
-break;
-}
-}
-}
-if(!_18){
-_18=this.tree._createTreeNode({item:_16,tree:_12,isExpandable:_13.mayHaveChildren(_16),label:_12.getLabel(_16),tooltip:_12.getTooltip(_16),indent:this.indent+1});
-if(_17){
-_17.push(_18);
-}else{
-_12._itemNodesMap[id]=[_18];
-}
-}
-this.addChild(_18);
-if(this.tree.autoExpand||this.tree._state(_16)){
-_14.push(_12._expandNode(_18));
-}
-},this);
-dojo.forEach(this.getChildren(),function(_19,idx){
-_19._updateLayout();
-});
-}else{
-this.isExpandable=false;
-}
-if(this._setExpando){
-this._setExpando(false);
-}
-if(this==_12.rootNode){
-var fc=this.tree.showRoot?this:this.getChildren()[0];
-if(fc){
-fc.setSelected(true);
-_12.lastFocused=fc;
-}else{
-_12.domNode.setAttribute("tabIndex","0");
-}
-}
-return new dojo.DeferredList(_14);
-},removeChild:function(_1a){
-this.inherited(arguments);
-var _1b=this.getChildren();
-if(_1b.length==0){
-this.isExpandable=false;
-this.collapse();
-}
-dojo.forEach(_1b,function(_1c){
-_1c._updateLayout();
-});
-},makeExpandable:function(){
-this.isExpandable=true;
-this._setExpando(false);
-},_onLabelFocus:function(evt){
-dojo.addClass(this.labelNode,"dijitTreeLabelFocused");
-this.tree._onNodeFocus(this);
-},_onLabelBlur:function(evt){
-dojo.removeClass(this.labelNode,"dijitTreeLabelFocused");
-},setSelected:function(_1d){
-var _1e=this.labelNode;
-_1e.setAttribute("tabIndex",_1d?"0":"-1");
-dijit.setWaiState(_1e,"selected",_1d);
-dojo.toggleClass(this.rowNode,"dijitTreeNodeSelected",_1d);
-},_onClick:function(evt){
-this.tree._onClick(this,evt);
-},_onDblClick:function(evt){
-this.tree._onDblClick(this,evt);
-},_onMouseEnter:function(evt){
-dojo.addClass(this.rowNode,"dijitTreeNodeHover");
-this.tree._onNodeMouseEnter(this,evt);
-},_onMouseLeave:function(evt){
-dojo.removeClass(this.rowNode,"dijitTreeNodeHover");
-this.tree._onNodeMouseLeave(this,evt);
-}});
-dojo.declare("dijit.Tree",[dijit._Widget,dijit._Templated],{store:null,model:null,query:null,label:"",showRoot:true,childrenAttr:["children"],path:[],selectedItem:null,openOnClick:false,openOnDblClick:false,templateString:dojo.cache("dijit","templates/Tree.html","<div class=\"dijitTree dijitTreeContainer\" waiRole=\"tree\"\n\tdojoAttachEvent=\"onkeypress:_onKeyPress\">\n\t<div class=\"dijitInline dijitTreeIndent\" style=\"position: absolute; top: -9999px\" dojoAttachPoint=\"indentDetecto [...]
-dojo.publish(this.id,[dojo.mixin({tree:this,event:_1f},_20||{})]);
-},postMixInProperties:function(){
-this.tree=this;
-this._itemNodesMap={};
-if(!this.cookieName){
-this.cookieName=this.id+"SaveStateCookie";
-}
-this._loadDeferred=new dojo.Deferred();
-this.inherited(arguments);
-},postCreate:function(){
-this._initState();
-if(!this.model){
-this._store2model();
-}
-this.connect(this.model,"onChange","_onItemChange");
-this.connect(this.model,"onChildrenChange","_onItemChildrenChange");
-this.connect(this.model,"onDelete","_onItemDelete");
-this._load();
-this.inherited(arguments);
-if(this.dndController){
-if(dojo.isString(this.dndController)){
-this.dndController=dojo.getObject(this.dndController);
-}
-var _21={};
-for(var i=0;i<this.dndParams.length;i++){
-if(this[this.dndParams[i]]){
-_21[this.dndParams[i]]=this[this.dndParams[i]];
-}
-}
-this.dndController=new this.dndController(this,_21);
-}
-},_store2model:function(){
-this._v10Compat=true;
-dojo.deprecated("Tree: from version 2.0, should specify a model object rather than a store/query");
-var _22={id:this.id+"_ForestStoreModel",store:this.store,query:this.query,childrenAttrs:this.childrenAttr};
-if(this.params.mayHaveChildren){
-_22.mayHaveChildren=dojo.hitch(this,"mayHaveChildren");
-}
-if(this.params.getItemChildren){
-_22.getChildren=dojo.hitch(this,function(_23,_24,_25){
-this.getItemChildren((this._v10Compat&&_23===this.model.root)?null:_23,_24,_25);
-});
-}
-this.model=new dijit.tree.ForestStoreModel(_22);
-this.showRoot=Boolean(this.label);
-},onLoad:function(){
-},_load:function(){
-this.model.getRoot(dojo.hitch(this,function(_26){
-var rn=(this.rootNode=this.tree._createTreeNode({item:_26,tree:this,isExpandable:true,label:this.label||this.getLabel(_26),indent:this.showRoot?0:-1}));
-if(!this.showRoot){
-rn.rowNode.style.display="none";
-}
-this.domNode.appendChild(rn.domNode);
-var _27=this.model.getIdentity(_26);
-if(this._itemNodesMap[_27]){
-this._itemNodesMap[_27].push(rn);
-}else{
-this._itemNodesMap[_27]=[rn];
-}
-rn._updateLayout();
-this._expandNode(rn).addCallback(dojo.hitch(this,function(){
-this._loadDeferred.callback(true);
-this.onLoad();
-}));
-}),function(err){
-console.error(this,": error loading root: ",err);
-});
-},getNodesByItem:function(_28){
-if(!_28){
-return [];
-}
-var _29=dojo.isString(_28)?_28:this.model.getIdentity(_28);
-return [].concat(this._itemNodesMap[_29]);
-},_setSelectedItemAttr:function(_2a){
-var _2b=this.attr("selectedItem");
-var _2c=(!_2a||dojo.isString(_2a))?_2a:this.model.getIdentity(_2a);
-if(_2c==_2b?this.model.getIdentity(_2b):null){
-return;
-}
-var _2d=this._itemNodesMap[_2c];
-if(_2d&&_2d.length){
-this.focusNode(_2d[0]);
-}else{
-if(this.lastFocused){
-this.lastFocused.setSelected(false);
-this.lastFocused=null;
-}
-}
-},_getSelectedItemAttr:function(){
-return this.lastFocused&&this.lastFocused.item;
-},_setPathAttr:function(_2e){
-if(!_2e||!_2e.length){
-return;
-}
-this._loadDeferred.addCallback(dojo.hitch(this,function(){
-if(!this.rootNode){
-return;
-}
-if(_2e[0]!==this.rootNode.item&&(dojo.isString(_2e[0])&&_2e[0]!=this.model.getIdentity(this.rootNode.item))){
-console.error(this,":path[0] doesn't match this.rootNode.item.  Maybe you are using the wrong tree.");
-return;
-}
-_2e.shift();
-var _2f=this.rootNode;
-function _30(){
-var _31=_2e.shift(),_32=dojo.isString(_31)?_31:this.model.getIdentity(_31);
-dojo.some(this._itemNodesMap[_32],function(n){
-if(n.getParent()==_2f){
-_2f=n;
-return true;
-}
-return false;
-});
-if(_2e.length){
-this._expandNode(_2f).addCallback(dojo.hitch(this,_30));
-}else{
-if(this.lastFocused!=_2f){
-this.focusNode(_2f);
-}
-}
-};
-this._expandNode(_2f).addCallback(dojo.hitch(this,_30));
-}));
-},_getPathAttr:function(){
-if(!this.lastFocused){
-return;
-}
-var res=[];
-var _33=this.lastFocused;
-while(_33&&_33!==this.rootNode){
-res.unshift(_33.item);
-_33=_33.getParent();
-}
-res.unshift(this.rootNode.item);
-return res;
-},mayHaveChildren:function(_34){
-},getItemChildren:function(_35,_36){
-},getLabel:function(_37){
-return this.model.getLabel(_37);
-},getIconClass:function(_38,_39){
-return (!_38||this.model.mayHaveChildren(_38))?(_39?"dijitFolderOpened":"dijitFolderClosed"):"dijitLeaf";
-},getLabelClass:function(_3a,_3b){
-},getRowClass:function(_3c,_3d){
-},getIconStyle:function(_3e,_3f){
-},getLabelStyle:function(_40,_41){
-},getRowStyle:function(_42,_43){
-},getTooltip:function(_44){
-return "";
-},_onKeyPress:function(e){
-if(e.altKey){
-return;
-}
-var dk=dojo.keys;
-var _45=dijit.getEnclosingWidget(e.target);
-if(!_45){
-return;
-}
-var key=e.charOrCode;
-if(typeof key=="string"){
-if(!e.altKey&&!e.ctrlKey&&!e.shiftKey&&!e.metaKey){
-this._onLetterKeyNav({node:_45,key:key.toLowerCase()});
-dojo.stopEvent(e);
-}
-}else{
-if(this._curSearch){
-clearTimeout(this._curSearch.timer);
-delete this._curSearch;
-}
-var map=this._keyHandlerMap;
-if(!map){
-map={};
-map[dk.ENTER]="_onEnterKey";
-map[this.isLeftToRight()?dk.LEFT_ARROW:dk.RIGHT_ARROW]="_onLeftArrow";
-map[this.isLeftToRight()?dk.RIGHT_ARROW:dk.LEFT_ARROW]="_onRightArrow";
-map[dk.UP_ARROW]="_onUpArrow";
-map[dk.DOWN_ARROW]="_onDownArrow";
-map[dk.HOME]="_onHomeKey";
-map[dk.END]="_onEndKey";
-this._keyHandlerMap=map;
-}
-if(this._keyHandlerMap[key]){
-this[this._keyHandlerMap[key]]({node:_45,item:_45.item,evt:e});
-dojo.stopEvent(e);
-}
-}
-},_onEnterKey:function(_46,evt){
-this._publish("execute",{item:_46.item,node:_46.node});
-this.onClick(_46.item,_46.node,evt);
-},_onDownArrow:function(_47){
-var _48=this._getNextNode(_47.node);
-if(_48&&_48.isTreeNode){
-this.focusNode(_48);
-}
-},_onUpArrow:function(_49){
-var _4a=_49.node;
-var _4b=_4a.getPreviousSibling();
-if(_4b){
-_4a=_4b;
-while(_4a.isExpandable&&_4a.isExpanded&&_4a.hasChildren()){
-var _4c=_4a.getChildren();
-_4a=_4c[_4c.length-1];
-}
-}else{
-var _4d=_4a.getParent();
-if(!(!this.showRoot&&_4d===this.rootNode)){
-_4a=_4d;
-}
-}
-if(_4a&&_4a.isTreeNode){
-this.focusNode(_4a);
-}
-},_onRightArrow:function(_4e){
-var _4f=_4e.node;
-if(_4f.isExpandable&&!_4f.isExpanded){
-this._expandNode(_4f);
-}else{
-if(_4f.hasChildren()){
-_4f=_4f.getChildren()[0];
-if(_4f&&_4f.isTreeNode){
-this.focusNode(_4f);
-}
-}
-}
-},_onLeftArrow:function(_50){
-var _51=_50.node;
-if(_51.isExpandable&&_51.isExpanded){
-this._collapseNode(_51);
-}else{
-var _52=_51.getParent();
-if(_52&&_52.isTreeNode&&!(!this.showRoot&&_52===this.rootNode)){
-this.focusNode(_52);
-}
-}
-},_onHomeKey:function(){
-var _53=this._getRootOrFirstNode();
-if(_53){
-this.focusNode(_53);
-}
-},_onEndKey:function(_54){
-var _55=this.rootNode;
-while(_55.isExpanded){
-var c=_55.getChildren();
-_55=c[c.length-1];
-}
-if(_55&&_55.isTreeNode){
-this.focusNode(_55);
-}
-},multiCharSearchDuration:250,_onLetterKeyNav:function(_56){
-var cs=this._curSearch;
-if(cs){
-cs.pattern=cs.pattern+_56.key;
-clearTimeout(cs.timer);
-}else{
-cs=this._curSearch={pattern:_56.key,startNode:_56.node};
-}
-var _57=this;
-cs.timer=setTimeout(function(){
-delete _57._curSearch;
-},this.multiCharSearchDuration);
-var _58=cs.startNode;
-do{
-_58=this._getNextNode(_58);
-if(!_58){
-_58=this._getRootOrFirstNode();
-}
-}while(_58!==cs.startNode&&(_58.label.toLowerCase().substr(0,cs.pattern.length)!=cs.pattern));
-if(_58&&_58.isTreeNode){
-if(_58!==cs.startNode){
-this.focusNode(_58);
-}
-}
-},_onClick:function(_59,e){
-var _5a=e.target;
-if((this.openOnClick&&_59.isExpandable)||(_5a==_59.expandoNode||_5a==_59.expandoNodeText)){
-if(_59.isExpandable){
-this._onExpandoClick({node:_59});
-}
-}else{
-this._publish("execute",{item:_59.item,node:_59,evt:e});
-this.onClick(_59.item,_59,e);
-this.focusNode(_59);
-}
-dojo.stopEvent(e);
-},_onDblClick:function(_5b,e){
-var _5c=e.target;
-if((this.openOnDblClick&&_5b.isExpandable)||(_5c==_5b.expandoNode||_5c==_5b.expandoNodeText)){
-if(_5b.isExpandable){
-this._onExpandoClick({node:_5b});
-}
-}else{
-this._publish("execute",{item:_5b.item,node:_5b,evt:e});
-this.onDblClick(_5b.item,_5b,e);
-this.focusNode(_5b);
-}
-dojo.stopEvent(e);
-},_onExpandoClick:function(_5d){
-var _5e=_5d.node;
-this.focusNode(_5e);
-if(_5e.isExpanded){
-this._collapseNode(_5e);
-}else{
-this._expandNode(_5e);
-}
-},onClick:function(_5f,_60,evt){
-},onDblClick:function(_61,_62,evt){
-},onOpen:function(_63,_64){
-},onClose:function(_65,_66){
-},_getNextNode:function(_67){
-if(_67.isExpandable&&_67.isExpanded&&_67.hasChildren()){
-return _67.getChildren()[0];
-}else{
-while(_67&&_67.isTreeNode){
-var _68=_67.getNextSibling();
-if(_68){
-return _68;
-}
-_67=_67.getParent();
-}
-return null;
-}
-},_getRootOrFirstNode:function(){
-return this.showRoot?this.rootNode:this.rootNode.getChildren()[0];
-},_collapseNode:function(_69){
-if(_69._expandNodeDeferred){
-delete _69._expandNodeDeferred;
-}
-if(_69.isExpandable){
-if(_69.state=="LOADING"){
-return;
-}
-_69.collapse();
-this.onClose(_69.item,_69);
-if(_69.item){
-this._state(_69.item,false);
-this._saveState();
-}
-}
-},_expandNode:function(_6a,_6b){
-if(_6a._expandNodeDeferred&&!_6b){
-return _6a._expandNodeDeferred;
-}
-var _6c=this.model,_6d=_6a.item,_6e=this;
-switch(_6a.state){
-case "UNCHECKED":
-_6a.markProcessing();
-var def=(_6a._expandNodeDeferred=new dojo.Deferred());
-_6c.getChildren(_6d,function(_6f){
-_6a.unmarkProcessing();
-var _70=_6a.setChildItems(_6f);
-var ed=_6e._expandNode(_6a,true);
-_70.addCallback(function(){
-ed.addCallback(function(){
-def.callback();
-});
-});
-},function(err){
-console.error(_6e,": error loading root children: ",err);
-});
-break;
-default:
-def=(_6a._expandNodeDeferred=_6a.expand());
-this.onOpen(_6a.item,_6a);
-if(_6d){
-this._state(_6d,true);
-this._saveState();
-}
-}
-return def;
-},focusNode:function(_71){
-dijit.focus(_71.labelNode);
-},_onNodeFocus:function(_72){
-if(_72){
-if(_72!=this.lastFocused&&this.lastFocused&&!this.lastFocused._destroyed){
-this.lastFocused.setSelected(false);
-}
-_72.setSelected(true);
-this.lastFocused=_72;
-}
-},_onNodeMouseEnter:function(_73){
-},_onNodeMouseLeave:function(_74){
-},_onItemChange:function(_75){
-var _76=this.model,_77=_76.getIdentity(_75),_78=this._itemNodesMap[_77];
-if(_78){
-var _79=this;
-dojo.forEach(_78,function(_7a){
-_7a.attr({label:_79.getLabel(_75),tooltip:_79.getTooltip(_75)});
-_7a._updateItemClasses(_75);
-});
-}
-},_onItemChildrenChange:function(_7b,_7c){
-var _7d=this.model,_7e=_7d.getIdentity(_7b),_7f=this._itemNodesMap[_7e];
-if(_7f){
-dojo.forEach(_7f,function(_80){
-_80.setChildItems(_7c);
+
+dojo.declare(
+	"dijit._TreeNode",
+	[dijit._Widget, dijit._Templated, dijit._Container, dijit._Contained, dijit._CssStateMixin],
+{
+	// summary:
+	//		Single node within a tree.   This class is used internally
+	//		by Tree and should not be accessed directly.
+	// tags:
+	//		private
+
+	// item: dojo.data.Item
+	//		the dojo.data entry this tree represents
+	item: null,
+
+	// isTreeNode: [protected] Boolean
+	//		Indicates that this is a TreeNode.   Used by `dijit.Tree` only,
+	//		should not be accessed directly.
+	isTreeNode: true,
+
+	// label: String
+	//		Text of this tree node
+	label: "",
+
+	// isExpandable: [private] Boolean
+	//		This node has children, so show the expando node (+ sign)
+	isExpandable: null,
+
+	// isExpanded: [readonly] Boolean
+	//		This node is currently expanded (ie, opened)
+	isExpanded: false,
+
+	// state: [private] String
+	//		Dynamic loading-related stuff.
+	//		When an empty folder node appears, it is "UNCHECKED" first,
+	//		then after dojo.data query it becomes "LOADING" and, finally "LOADED"
+	state: "UNCHECKED",
+
+	templateString: dojo.cache("dijit", "templates/TreeNode.html"),
+
+	baseClass: "dijitTreeNode",
+
+	// For hover effect for tree node, and focus effect for label
+	cssStateNodes: {
+		rowNode: "dijitTreeRow",
+		labelNode: "dijitTreeLabel"
+	},
+
+	attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+		label: {node: "labelNode", type: "innerText"},
+		tooltip: {node: "rowNode", type: "attribute", attribute: "title"}
+	}),
+
+	postCreate: function(){
+		this.inherited(arguments);
+
+		// set expand icon for leaf
+		this._setExpando();
+
+		// set icon and label class based on item
+		this._updateItemClasses(this.item);
+
+		if(this.isExpandable){
+			dijit.setWaiState(this.labelNode, "expanded", this.isExpanded);
+		}
+	},
+
+	_setIndentAttr: function(indent){
+		// summary:
+		//		Tell this node how many levels it should be indented
+		// description:
+		//		0 for top level nodes, 1 for their children, 2 for their
+		//		grandchildren, etc.
+		this.indent = indent;
+
+		// Math.max() is to prevent negative padding on hidden root node (when indent == -1)
+		var pixels = (Math.max(indent, 0) * this.tree._nodePixelIndent) + "px";
+
+		dojo.style(this.domNode, "backgroundPosition",	pixels + " 0px");
+		dojo.style(this.rowNode, this.isLeftToRight() ? "paddingLeft" : "paddingRight", pixels);
+
+		dojo.forEach(this.getChildren(), function(child){
+			child.set("indent", indent+1);
+		});
+	},
+
+	markProcessing: function(){
+		// summary:
+		//		Visually denote that tree is loading data, etc.
+		// tags:
+		//		private
+		this.state = "LOADING";
+		this._setExpando(true);
+	},
+
+	unmarkProcessing: function(){
+		// summary:
+		//		Clear markup from markProcessing() call
+		// tags:
+		//		private
+		this._setExpando(false);
+	},
+
+	_updateItemClasses: function(item){
+		// summary:
+		//		Set appropriate CSS classes for icon and label dom node
+		//		(used to allow for item updates to change respective CSS)
+		// tags:
+		//		private
+		var tree = this.tree, model = tree.model;
+		if(tree._v10Compat && item === model.root){
+			// For back-compat with 1.0, need to use null to specify root item (TODO: remove in 2.0)
+			item = null;
+		}
+		this._applyClassAndStyle(item, "icon", "Icon");
+		this._applyClassAndStyle(item, "label", "Label");
+		this._applyClassAndStyle(item, "row", "Row");
+	},
+
+	_applyClassAndStyle: function(item, lower, upper){
+		// summary:
+		//		Set the appropriate CSS classes and styles for labels, icons and rows.
+		//
+		// item:
+		//		The data item.
+		//
+		// lower:
+		//		The lower case attribute to use, e.g. 'icon', 'label' or 'row'.
+		//
+		// upper:
+		//		The upper case attribute to use, e.g. 'Icon', 'Label' or 'Row'.
+		//
+		// tags:
+		//		private
+
+		var clsName = "_" + lower + "Class";
+		var nodeName = lower + "Node";
+
+		if(this[clsName]){
+			dojo.removeClass(this[nodeName], this[clsName]);
+ 		}
+		this[clsName] = this.tree["get" + upper + "Class"](item, this.isExpanded);
+		if(this[clsName]){
+			dojo.addClass(this[nodeName], this[clsName]);
+ 		}
+		dojo.style(this[nodeName], this.tree["get" + upper + "Style"](item, this.isExpanded) || {});
+ 	},
+
+	_updateLayout: function(){
+		// summary:
+		//		Set appropriate CSS classes for this.domNode
+		// tags:
+		//		private
+		var parent = this.getParent();
+		if(!parent || parent.rowNode.style.display == "none"){
+			/* if we are hiding the root node then make every first level child look like a root node */
+			dojo.addClass(this.domNode, "dijitTreeIsRoot");
+		}else{
+			dojo.toggleClass(this.domNode, "dijitTreeIsLast", !this.getNextSibling());
+		}
+	},
+
+	_setExpando: function(/*Boolean*/ processing){
+		// summary:
+		//		Set the right image for the expando node
+		// tags:
+		//		private
+
+		var styles = ["dijitTreeExpandoLoading", "dijitTreeExpandoOpened",
+						"dijitTreeExpandoClosed", "dijitTreeExpandoLeaf"],
+			_a11yStates = ["*","-","+","*"],
+			idx = processing ? 0 : (this.isExpandable ?	(this.isExpanded ? 1 : 2) : 3);
+
+		// apply the appropriate class to the expando node
+		dojo.removeClass(this.expandoNode, styles);
+		dojo.addClass(this.expandoNode, styles[idx]);
+
+		// provide a non-image based indicator for images-off mode
+		this.expandoNodeText.innerHTML = _a11yStates[idx];
+
+	},
+
+	expand: function(){
+		// summary:
+		//		Show my children
+		// returns:
+		//		Deferred that fires when expansion is complete
+
+		// If there's already an expand in progress or we are already expanded, just return
+		if(this._expandDeferred){
+			return this._expandDeferred;		// dojo.Deferred
+		}
+
+		// cancel in progress collapse operation
+		this._wipeOut && this._wipeOut.stop();
+
+		// All the state information for when a node is expanded, maybe this should be
+		// set when the animation completes instead
+		this.isExpanded = true;
+		dijit.setWaiState(this.labelNode, "expanded", "true");
+		dijit.setWaiRole(this.containerNode, "group");
+		dojo.addClass(this.contentNode,'dijitTreeContentExpanded');
+		this._setExpando();
+		this._updateItemClasses(this.item);
+		if(this == this.tree.rootNode){
+			dijit.setWaiState(this.tree.domNode, "expanded", "true");
+		}
+
+		var def,
+			wipeIn = dojo.fx.wipeIn({
+				node: this.containerNode, duration: dijit.defaultDuration,
+				onEnd: function(){
+					def.callback(true);
+				}
+			});
+
+		// Deferred that fires when expand is complete
+		def = (this._expandDeferred = new dojo.Deferred(function(){
+			// Canceller
+			wipeIn.stop();
+		}));
+
+		wipeIn.play();
+
+		return def;		// dojo.Deferred
+	},
+
+	collapse: function(){
+		// summary:
+		//		Collapse this node (if it's expanded)
+
+		if(!this.isExpanded){ return; }
+
+		// cancel in progress expand operation
+		if(this._expandDeferred){
+			this._expandDeferred.cancel();
+			delete this._expandDeferred;
+		}
+
+		this.isExpanded = false;
+		dijit.setWaiState(this.labelNode, "expanded", "false");
+		if(this == this.tree.rootNode){
+			dijit.setWaiState(this.tree.domNode, "expanded", "false");
+		}
+		dojo.removeClass(this.contentNode,'dijitTreeContentExpanded');
+		this._setExpando();
+		this._updateItemClasses(this.item);
+
+		if(!this._wipeOut){
+			this._wipeOut = dojo.fx.wipeOut({
+				node: this.containerNode, duration: dijit.defaultDuration
+			});
+		}
+		this._wipeOut.play();
+	},
+
+	// indent: Integer
+	//		Levels from this node to the root node
+	indent: 0,
+
+	setChildItems: function(/* Object[] */ items){
+		// summary:
+		//		Sets the child items of this node, removing/adding nodes
+		//		from current children to match specified items[] array.
+		//		Also, if this.persist == true, expands any children that were previously
+		// 		opened.
+		// returns:
+		//		Deferred object that fires after all previously opened children
+		//		have been expanded again (or fires instantly if there are no such children).
+
+		var tree = this.tree,
+			model = tree.model,
+			defs = [];	// list of deferreds that need to fire before I am complete
+
+
+		// Orphan all my existing children.
+		// If items contains some of the same items as before then we will reattach them.
+		// Don't call this.removeChild() because that will collapse the tree etc.
+		dojo.forEach(this.getChildren(), function(child){
+			dijit._Container.prototype.removeChild.call(this, child);
+		}, this);
+
+		this.state = "LOADED";
+
+		if(items && items.length > 0){
+			this.isExpandable = true;
+
+			// Create _TreeNode widget for each specified tree node, unless one already
+			// exists and isn't being used (presumably it's from a DnD move and was recently
+			// released
+			dojo.forEach(items, function(item){
+				var id = model.getIdentity(item),
+					existingNodes = tree._itemNodesMap[id],
+					node;
+				if(existingNodes){
+					for(var i=0;i<existingNodes.length;i++){
+						if(existingNodes[i] && !existingNodes[i].getParent()){
+							node = existingNodes[i];
+							node.set('indent', this.indent+1);
+							break;
+						}
+					}
+				}
+				if(!node){
+					node = this.tree._createTreeNode({
+							item: item,
+							tree: tree,
+							isExpandable: model.mayHaveChildren(item),
+							label: tree.getLabel(item),
+							tooltip: tree.getTooltip(item),
+							dir: tree.dir,
+							lang: tree.lang,
+							indent: this.indent + 1
+						});
+					if(existingNodes){
+						existingNodes.push(node);
+					}else{
+						tree._itemNodesMap[id] = [node];
+					}
+				}
+				this.addChild(node);
+
+				// If node was previously opened then open it again now (this may trigger
+				// more data store accesses, recursively)
+				if(this.tree.autoExpand || this.tree._state(item)){
+					defs.push(tree._expandNode(node));
+				}
+			}, this);
+
+			// note that updateLayout() needs to be called on each child after
+			// _all_ the children exist
+			dojo.forEach(this.getChildren(), function(child, idx){
+				child._updateLayout();
+			});
+		}else{
+			this.isExpandable=false;
+		}
+
+		if(this._setExpando){
+			// change expando to/from dot or + icon, as appropriate
+			this._setExpando(false);
+		}
+
+		// Set leaf icon or folder icon, as appropriate
+		this._updateItemClasses(this.item);
+
+		// On initial tree show, make the selected TreeNode as either the root node of the tree,
+		// or the first child, if the root node is hidden
+		if(this == tree.rootNode){
+			var fc = this.tree.showRoot ? this : this.getChildren()[0];
+			if(fc){
+				fc.setFocusable(true);
+				tree.lastFocused = fc;
+			}else{
+				// fallback: no nodes in tree so focus on Tree <div> itself
+				tree.domNode.setAttribute("tabIndex", "0");
+			}
+		}
+
+		return new dojo.DeferredList(defs);	// dojo.Deferred
+	},
+
+	removeChild: function(/* treeNode */ node){
+		this.inherited(arguments);
+
+		var children = this.getChildren();
+		if(children.length == 0){
+			this.isExpandable = false;
+			this.collapse();
+		}
+
+		dojo.forEach(children, function(child){
+				child._updateLayout();
+		});
+	},
+
+	makeExpandable: function(){
+		// summary:
+		//		if this node wasn't already showing the expando node,
+		//		turn it into one and call _setExpando()
+
+		// TODO: hmm this isn't called from anywhere, maybe should remove it for 2.0
+
+		this.isExpandable = true;
+		this._setExpando(false);
+	},
+
+	_onLabelFocus: function(evt){
+		// summary:
+		//		Called when this row is focused (possibly programatically)
+		//		Note that we aren't using _onFocus() builtin to dijit
+		//		because it's called when focus is moved to a descendant TreeNode.
+		// tags:
+		//		private
+		this.tree._onNodeFocus(this);
+	},
+
+	setSelected: function(/*Boolean*/ selected){
+		// summary:
+		//		A Tree has a (single) currently selected node.
+		//		Mark that this node is/isn't that currently selected node.
+		// description:
+		//		In particular, setting a node as selected involves setting tabIndex
+		//		so that when user tabs to the tree, focus will go to that node (only).
+		dijit.setWaiState(this.labelNode, "selected", selected);
+		dojo.toggleClass(this.rowNode, "dijitTreeRowSelected", selected);
+	},
+
+	setFocusable: function(/*Boolean*/ selected){
+		// summary:
+		//		A Tree has a (single) node that's focusable.
+		//		Mark that this node is/isn't that currently focsuable node.
+		// description:
+		//		In particular, setting a node as selected involves setting tabIndex
+		//		so that when user tabs to the tree, focus will go to that node (only).
+
+		this.labelNode.setAttribute("tabIndex", selected ? "0" : "-1");
+	},
+
+	_onClick: function(evt){
+		// summary:
+		//		Handler for onclick event on a node
+		// tags:
+		//		private
+		this.tree._onClick(this, evt);
+	},
+	_onDblClick: function(evt){
+		// summary:
+		//		Handler for ondblclick event on a node
+		// tags:
+		//		private
+		this.tree._onDblClick(this, evt);
+	},
+
+	_onMouseEnter: function(evt){
+		// summary:
+		//		Handler for onmouseenter event on a node
+		// tags:
+		//		private
+		this.tree._onNodeMouseEnter(this, evt);
+	},
+
+	_onMouseLeave: function(evt){
+		// summary:
+		//		Handler for onmouseenter event on a node
+		// tags:
+		//		private
+		this.tree._onNodeMouseLeave(this, evt);
+	}
 });
-}
-},_onItemDelete:function(_81){
-var _82=this.model,_83=_82.getIdentity(_81),_84=this._itemNodesMap[_83];
-if(_84){
-dojo.forEach(_84,function(_85){
-var _86=_85.getParent();
-if(_86){
-_86.removeChild(_85);
-}
-_85.destroyRecursive();
+
+dojo.declare(
+	"dijit.Tree",
+	[dijit._Widget, dijit._Templated],
+{
+	// summary:
+	//		This widget displays hierarchical data from a store.
+
+	// store: [deprecated] String||dojo.data.Store
+	//		Deprecated.  Use "model" parameter instead.
+	//		The store to get data to display in the tree.
+	store: null,
+
+	// model: dijit.Tree.model
+	//		Interface to read tree data, get notifications of changes to tree data,
+	//		and for handling drop operations (i.e drag and drop onto the tree)
+	model: null,
+
+	// query: [deprecated] anything
+	//		Deprecated.  User should specify query to the model directly instead.
+	//		Specifies datastore query to return the root item or top items for the tree.
+	query: null,
+
+	// label: [deprecated] String
+	//		Deprecated.  Use dijit.tree.ForestStoreModel directly instead.
+	//		Used in conjunction with query parameter.
+	//		If a query is specified (rather than a root node id), and a label is also specified,
+	//		then a fake root node is created and displayed, with this label.
+	label: "",
+
+	// showRoot: [const] Boolean
+	//		Should the root node be displayed, or hidden?
+	showRoot: true,
+
+	// childrenAttr: [deprecated] String[]
+	//		Deprecated.   This information should be specified in the model.
+	//		One ore more attributes that holds children of a tree node
+	childrenAttr: ["children"],
+
+	// path: String[] or Item[]
+	//		Full path from rootNode to selected node expressed as array of items or array of ids.
+	//		Since setting the path may be asynchronous (because ofwaiting on dojo.data), set("path", ...)
+	//		returns a Deferred to indicate when the set is complete.
+	path: [],
+
+	// selectedItem: [readonly] Item
+	//		The currently selected item in this tree.
+	//		This property can only be set (via set('selectedItem', ...)) when that item is already
+	//		visible in the tree.   (I.e. the tree has already been expanded to show that node.)
+	//		Should generally use `path` attribute to set the selected item instead.
+	selectedItem: null,
+
+	// openOnClick: Boolean
+	//		If true, clicking a folder node's label will open it, rather than calling onClick()
+	openOnClick: false,
+
+	// openOnDblClick: Boolean
+	//		If true, double-clicking a folder node's label will open it, rather than calling onDblClick()
+	openOnDblClick: false,
+
+	templateString: dojo.cache("dijit", "templates/Tree.html"),
+
+	// persist: Boolean
+	//		Enables/disables use of cookies for state saving.
+	persist: true,
+
+	// autoExpand: Boolean
+	//		Fully expand the tree on load.   Overrides `persist`
+	autoExpand: false,
+
+	// dndController: [protected] String
+	//		Class name to use as as the dnd controller.  Specifying this class enables DnD.
+	//		Generally you should specify this as "dijit.tree.dndSource".
+	dndController: null,
+
+	// parameters to pull off of the tree and pass on to the dndController as its params
+	dndParams: ["onDndDrop","itemCreator","onDndCancel","checkAcceptance", "checkItemAcceptance", "dragThreshold", "betweenThreshold"],
+
+	//declare the above items so they can be pulled from the tree's markup
+
+	// onDndDrop: [protected] Function
+	//		Parameter to dndController, see `dijit.tree.dndSource.onDndDrop`.
+	//		Generally this doesn't need to be set.
+	onDndDrop: null,
+
+	/*=====
+	itemCreator: function(nodes, target, source){
+		// summary:
+		//		Returns objects passed to `Tree.model.newItem()` based on DnD nodes
+		//		dropped onto the tree.   Developer must override this method to enable
+		// 		dropping from external sources onto this Tree, unless the Tree.model's items
+		//		happen to look like {id: 123, name: "Apple" } with no other attributes.
+		// description:
+		//		For each node in nodes[], which came from source, create a hash of name/value
+		//		pairs to be passed to Tree.model.newItem().  Returns array of those hashes.
+		// nodes: DomNode[]
+		//		The DOMNodes dragged from the source container
+		// target: DomNode
+		//		The target TreeNode.rowNode
+		// source: dojo.dnd.Source
+		//		The source container the nodes were dragged from, perhaps another Tree or a plain dojo.dnd.Source
+		// returns: Object[]
+		//		Array of name/value hashes for each new item to be added to the Tree, like:
+		// |	[
+		// |		{ id: 123, label: "apple", foo: "bar" },
+		// |		{ id: 456, label: "pear", zaz: "bam" }
+		// |	]
+		// tags:
+		//		extension
+		return [{}];
+	},
+	=====*/
+	itemCreator: null,
+
+	// onDndCancel: [protected] Function
+	//		Parameter to dndController, see `dijit.tree.dndSource.onDndCancel`.
+	//		Generally this doesn't need to be set.
+	onDndCancel: null,
+
+/*=====
+	checkAcceptance: function(source, nodes){
+		// summary:
+		//		Checks if the Tree itself can accept nodes from this source
+		// source: dijit.tree._dndSource
+		//		The source which provides items
+		// nodes: DOMNode[]
+		//		Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if
+		//		source is a dijit.Tree.
+		// tags:
+		//		extension
+		return true;	// Boolean
+	},
+=====*/
+	checkAcceptance: null,
+
+/*=====
+	checkItemAcceptance: function(target, source, position){
+		// summary:
+		//		Stub function to be overridden if one wants to check for the ability to drop at the node/item level
+		// description:
+		//		In the base case, this is called to check if target can become a child of source.
+		//		When betweenThreshold is set, position="before" or "after" means that we
+		//		are asking if the source node can be dropped before/after the target node.
+		// target: DOMNode
+		//		The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to
+		//		Use dijit.getEnclosingWidget(target) to get the TreeNode.
+		// source: dijit.tree.dndSource
+		//		The (set of) nodes we are dropping
+		// position: String
+		//		"over", "before", or "after"
+		// tags:
+		//		extension
+		return true;	// Boolean
+	},
+=====*/
+	checkItemAcceptance: null,
+
+	// dragThreshold: Integer
+	//		Number of pixels mouse moves before it's considered the start of a drag operation
+	dragThreshold: 5,
+
+	// betweenThreshold: Integer
+	//		Set to a positive value to allow drag and drop "between" nodes.
+	//
+	//		If during DnD mouse is over a (target) node but less than betweenThreshold
+	//		pixels from the bottom edge, dropping the the dragged node will make it
+	//		the next sibling of the target node, rather than the child.
+	//
+	//		Similarly, if mouse is over a target node but less that betweenThreshold
+	//		pixels from the top edge, dropping the dragged node will make it
+	//		the target node's previous sibling rather than the target node's child.
+	betweenThreshold: 0,
+
+	// _nodePixelIndent: Integer
+	//		Number of pixels to indent tree nodes (relative to parent node).
+	//		Default is 19 but can be overridden by setting CSS class dijitTreeIndent
+	//		and calling resize() or startup() on tree after it's in the DOM.
+	_nodePixelIndent: 19,
+
+	_publish: function(/*String*/ topicName, /*Object*/ message){
+		// summary:
+		//		Publish a message for this widget/topic
+		dojo.publish(this.id, [dojo.mixin({tree: this, event: topicName}, message || {})]);
+	},
+
+	postMixInProperties: function(){
+		this.tree = this;
+
+		if(this.autoExpand){
+			// There's little point in saving opened/closed state of nodes for a Tree
+			// that initially opens all it's nodes.
+			this.persist = false;
+		}
+
+		this._itemNodesMap={};
+
+		if(!this.cookieName){
+			this.cookieName = this.id + "SaveStateCookie";
+		}
+
+		this._loadDeferred = new dojo.Deferred();
+
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		this._initState();
+
+		// Create glue between store and Tree, if not specified directly by user
+		if(!this.model){
+			this._store2model();
+		}
+
+		// monitor changes to items
+		this.connect(this.model, "onChange", "_onItemChange");
+		this.connect(this.model, "onChildrenChange", "_onItemChildrenChange");
+		this.connect(this.model, "onDelete", "_onItemDelete");
+
+		this._load();
+
+		this.inherited(arguments);
+
+		if(this.dndController){
+			if(dojo.isString(this.dndController)){
+				this.dndController = dojo.getObject(this.dndController);
+			}
+			var params={};
+			for(var i=0; i<this.dndParams.length;i++){
+				if(this[this.dndParams[i]]){
+					params[this.dndParams[i]] = this[this.dndParams[i]];
+				}
+			}
+			this.dndController = new this.dndController(this, params);
+		}
+	},
+
+	_store2model: function(){
+		// summary:
+		//		User specified a store&query rather than model, so create model from store/query
+		this._v10Compat = true;
+		dojo.deprecated("Tree: from version 2.0, should specify a model object rather than a store/query");
+
+		var modelParams = {
+			id: this.id + "_ForestStoreModel",
+			store: this.store,
+			query: this.query,
+			childrenAttrs: this.childrenAttr
+		};
+
+		// Only override the model's mayHaveChildren() method if the user has specified an override
+		if(this.params.mayHaveChildren){
+			modelParams.mayHaveChildren = dojo.hitch(this, "mayHaveChildren");
+		}
+
+		if(this.params.getItemChildren){
+			modelParams.getChildren = dojo.hitch(this, function(item, onComplete, onError){
+				this.getItemChildren((this._v10Compat && item === this.model.root) ? null : item, onComplete, onError);
+			});
+		}
+		this.model = new dijit.tree.ForestStoreModel(modelParams);
+
+		// For backwards compatibility, the visibility of the root node is controlled by
+		// whether or not the user has specified a label
+		this.showRoot = Boolean(this.label);
+	},
+
+	onLoad: function(){
+		// summary:
+		//		Called when tree finishes loading and expanding.
+		// description:
+		//		If persist == true the loading may encompass many levels of fetches
+		//		from the data store, each asynchronous.   Waits for all to finish.
+		// tags:
+		//		callback
+	},
+
+	_load: function(){
+		// summary:
+		//		Initial load of the tree.
+		//		Load root node (possibly hidden) and it's children.
+		this.model.getRoot(
+			dojo.hitch(this, function(item){
+				var rn = (this.rootNode = this.tree._createTreeNode({
+					item: item,
+					tree: this,
+					isExpandable: true,
+					label: this.label || this.getLabel(item),
+					indent: this.showRoot ? 0 : -1
+				}));
+				if(!this.showRoot){
+					rn.rowNode.style.display="none";
+				}
+				this.domNode.appendChild(rn.domNode);
+				var identity = this.model.getIdentity(item);
+				if(this._itemNodesMap[identity]){
+					this._itemNodesMap[identity].push(rn);
+				}else{
+					this._itemNodesMap[identity] = [rn];
+				}
+
+				rn._updateLayout();		// sets "dijitTreeIsRoot" CSS classname
+
+				// load top level children and then fire onLoad() event
+				this._expandNode(rn).addCallback(dojo.hitch(this, function(){
+					this._loadDeferred.callback(true);
+					this.onLoad();
+				}));
+			}),
+			function(err){
+				console.error(this, ": error loading root: ", err);
+			}
+		);
+	},
+
+	getNodesByItem: function(/*dojo.data.Item or id*/ item){
+		// summary:
+		//		Returns all tree nodes that refer to an item
+		// returns:
+		//		Array of tree nodes that refer to passed item
+
+		if(!item){ return []; }
+		var identity = dojo.isString(item) ? item : this.model.getIdentity(item);
+		// return a copy so widget don't get messed up by changes to returned array
+		return [].concat(this._itemNodesMap[identity]);
+	},
+
+	_setSelectedItemAttr: function(/*dojo.data.Item or id*/ item){
+		// summary:
+		//		Select a tree node related to passed item.
+		//		WARNING: if model use multi-parented items or desired tree node isn't already loaded
+		//		behavior is undefined. Use set('path', ...) instead.
+
+		var oldValue = this.get("selectedItem");
+		var identity = (!item || dojo.isString(item)) ? item : this.model.getIdentity(item);
+		if(identity == oldValue ? this.model.getIdentity(oldValue) : null){ return; }
+		var nodes = this._itemNodesMap[identity];
+		this._selectNode((nodes && nodes[0]) || null);	//select the first item
+	},
+
+	_getSelectedItemAttr: function(){
+		// summary:
+		//		Return item related to selected tree node.
+		return this.selectedNode && this.selectedNode.item;
+	},
+
+	_setPathAttr: function(/*Item[] || String[]*/ path){
+		// summary:
+		//		Select the tree node identified by passed path.
+		// path:
+		//		Array of items or item id's
+		// returns:
+		//		Deferred to indicate when the set is complete
+
+		var d = new dojo.Deferred();
+
+		this._selectNode(null);
+		if(!path || !path.length){
+			d.resolve(true);
+			return d;
+		}
+
+		// If this is called during initialization, defer running until Tree has finished loading
+		this._loadDeferred.addCallback(dojo.hitch(this, function(){
+			if(!this.rootNode){
+				d.reject(new Error("!this.rootNode"));
+				return;
+			}
+			if(path[0] !== this.rootNode.item && (dojo.isString(path[0]) && path[0] != this.model.getIdentity(this.rootNode.item))){
+				d.reject(new Error(this.id + ":path[0] doesn't match this.rootNode.item.  Maybe you are using the wrong tree."));
+				return;
+			}
+			path.shift();
+
+			var node = this.rootNode;
+
+			function advance(){
+				// summary:
+				// 		Called when "node" has completed loading and expanding.   Pop the next item from the path
+				//		(which must be a child of "node") and advance to it, and then recurse.
+
+				// Set item and identity to next item in path (node is pointing to the item that was popped
+				// from the path _last_ time.
+				var item = path.shift(),
+					identity = dojo.isString(item) ? item : this.model.getIdentity(item);
+
+				// Change "node" from previous item in path to the item we just popped from path
+				dojo.some(this._itemNodesMap[identity], function(n){
+					if(n.getParent() == node){
+						node = n;
+						return true;
+					}
+					return false;
+				});
+
+				if(path.length){
+					// Need to do more expanding
+					this._expandNode(node).addCallback(dojo.hitch(this, advance));
+				}else{
+					// Final destination node, select it
+					this._selectNode(node);
+					
+					// signal that path setting is finished
+					d.resolve(true);
+				}
+			}
+
+			this._expandNode(node).addCallback(dojo.hitch(this, advance));
+		}));
+			
+		return d;
+	},
+
+	_getPathAttr: function(){
+		// summary:
+		//		Return an array of items that is the path to selected tree node.
+		if(!this.selectedNode){ return; }
+		var res = [];
+		var treeNode = this.selectedNode;
+		while(treeNode && treeNode !== this.rootNode){
+			res.unshift(treeNode.item);
+			treeNode = treeNode.getParent();
+		}
+		res.unshift(this.rootNode.item);
+		return res;
+	},
+
+	////////////// Data store related functions //////////////////////
+	// These just get passed to the model; they are here for back-compat
+
+	mayHaveChildren: function(/*dojo.data.Item*/ item){
+		// summary:
+		//		Deprecated.   This should be specified on the model itself.
+		//
+		//		Overridable function to tell if an item has or may have children.
+		//		Controls whether or not +/- expando icon is shown.
+		//		(For efficiency reasons we may not want to check if an element actually
+		//		has children until user clicks the expando node)
+		// tags:
+		//		deprecated
+	},
+
+	getItemChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete){
+		// summary:
+		//		Deprecated.   This should be specified on the model itself.
+		//
+		// 		Overridable function that return array of child items of given parent item,
+		//		or if parentItem==null then return top items in tree
+		// tags:
+		//		deprecated
+	},
+
+	///////////////////////////////////////////////////////
+	// Functions for converting an item to a TreeNode
+	getLabel: function(/*dojo.data.Item*/ item){
+		// summary:
+		//		Overridable function to get the label for a tree node (given the item)
+		// tags:
+		//		extension
+		return this.model.getLabel(item);	// String
+	},
+
+	getIconClass: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
+		// summary:
+		//		Overridable function to return CSS class name to display icon
+		// tags:
+		//		extension
+		return (!item || this.model.mayHaveChildren(item)) ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "dijitLeaf"
+	},
+
+	getLabelClass: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
+		// summary:
+		//		Overridable function to return CSS class name to display label
+		// tags:
+		//		extension
+	},
+
+	getRowClass: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
+		// summary:
+		//		Overridable function to return CSS class name to display row
+		// tags:
+		//		extension
+	},
+
+	getIconStyle: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
+		// summary:
+		//		Overridable function to return CSS styles to display icon
+		// returns:
+		//		Object suitable for input to dojo.style() like {backgroundImage: "url(...)"}
+		// tags:
+		//		extension
+	},
+
+	getLabelStyle: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
+		// summary:
+		//		Overridable function to return CSS styles to display label
+		// returns:
+		//		Object suitable for input to dojo.style() like {color: "red", background: "green"}
+		// tags:
+		//		extension
+	},
+
+	getRowStyle: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
+		// summary:
+		//		Overridable function to return CSS styles to display row
+		// returns:
+		//		Object suitable for input to dojo.style() like {background-color: "#bbb"}
+		// tags:
+		//		extension
+	},
+
+	getTooltip: function(/*dojo.data.Item*/ item){
+		// summary:
+		//		Overridable function to get the tooltip for a tree node (given the item)
+		// tags:
+		//		extension
+		return "";	// String
+	},
+
+	/////////// Keyboard and Mouse handlers ////////////////////
+
+	_onKeyPress: function(/*Event*/ e){
+		// summary:
+		//		Translates keypress events into commands for the controller
+		if(e.altKey){ return; }
+		var dk = dojo.keys;
+		var treeNode = dijit.getEnclosingWidget(e.target);
+		if(!treeNode){ return; }
+
+		var key = e.charOrCode;
+		if(typeof key == "string"){	// handle printables (letter navigation)
+			// Check for key navigation.
+			if(!e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey){
+				this._onLetterKeyNav( { node: treeNode, key: key.toLowerCase() } );
+				dojo.stopEvent(e);
+			}
+		}else{	// handle non-printables (arrow keys)
+			// clear record of recent printables (being saved for multi-char letter navigation),
+			// because "a", down-arrow, "b" shouldn't search for "ab"
+			if(this._curSearch){
+				clearTimeout(this._curSearch.timer);
+				delete this._curSearch;
+			}
+
+			var map = this._keyHandlerMap;
+			if(!map){
+				// setup table mapping keys to events
+				map = {};
+				map[dk.ENTER]="_onEnterKey";
+				map[this.isLeftToRight() ? dk.LEFT_ARROW : dk.RIGHT_ARROW]="_onLeftArrow";
+				map[this.isLeftToRight() ? dk.RIGHT_ARROW : dk.LEFT_ARROW]="_onRightArrow";
+				map[dk.UP_ARROW]="_onUpArrow";
+				map[dk.DOWN_ARROW]="_onDownArrow";
+				map[dk.HOME]="_onHomeKey";
+				map[dk.END]="_onEndKey";
+				this._keyHandlerMap = map;
+			}
+			if(this._keyHandlerMap[key]){
+				this[this._keyHandlerMap[key]]( { node: treeNode, item: treeNode.item, evt: e } );
+				dojo.stopEvent(e);
+			}
+		}
+	},
+
+	_onEnterKey: function(/*Object*/ message, /*Event*/ evt){
+		this._publish("execute", { item: message.item, node: message.node } );
+		this._selectNode(message.node);
+		this.onClick(message.item, message.node, evt);
+	},
+
+	_onDownArrow: function(/*Object*/ message){
+		// summary:
+		//		down arrow pressed; get next visible node, set focus there
+		var node = this._getNextNode(message.node);
+		if(node && node.isTreeNode){
+			this.focusNode(node);
+		}
+	},
+
+	_onUpArrow: function(/*Object*/ message){
+		// summary:
+		//		Up arrow pressed; move to previous visible node
+
+		var node = message.node;
+
+		// if younger siblings
+		var previousSibling = node.getPreviousSibling();
+		if(previousSibling){
+			node = previousSibling;
+			// if the previous node is expanded, dive in deep
+			while(node.isExpandable && node.isExpanded && node.hasChildren()){
+				// move to the last child
+				var children = node.getChildren();
+				node = children[children.length-1];
+			}
+		}else{
+			// if this is the first child, return the parent
+			// unless the parent is the root of a tree with a hidden root
+			var parent = node.getParent();
+			if(!(!this.showRoot && parent === this.rootNode)){
+				node = parent;
+			}
+		}
+
+		if(node && node.isTreeNode){
+			this.focusNode(node);
+		}
+	},
+
+	_onRightArrow: function(/*Object*/ message){
+		// summary:
+		//		Right arrow pressed; go to child node
+		var node = message.node;
+
+		// if not expanded, expand, else move to 1st child
+		if(node.isExpandable && !node.isExpanded){
+			this._expandNode(node);
+		}else if(node.hasChildren()){
+			node = node.getChildren()[0];
+			if(node && node.isTreeNode){
+				this.focusNode(node);
+			}
+		}
+	},
+
+	_onLeftArrow: function(/*Object*/ message){
+		// summary:
+		//		Left arrow pressed.
+		//		If not collapsed, collapse, else move to parent.
+
+		var node = message.node;
+
+		if(node.isExpandable && node.isExpanded){
+			this._collapseNode(node);
+		}else{
+			var parent = node.getParent();
+			if(parent && parent.isTreeNode && !(!this.showRoot && parent === this.rootNode)){
+				this.focusNode(parent);
+			}
+		}
+	},
+
+	_onHomeKey: function(){
+		// summary:
+		//		Home key pressed; get first visible node, and set focus there
+		var node = this._getRootOrFirstNode();
+		if(node){
+			this.focusNode(node);
+		}
+	},
+
+	_onEndKey: function(/*Object*/ message){
+		// summary:
+		//		End key pressed; go to last visible node.
+
+		var node = this.rootNode;
+		while(node.isExpanded){
+			var c = node.getChildren();
+			node = c[c.length - 1];
+		}
+
+		if(node && node.isTreeNode){
+			this.focusNode(node);
+		}
+	},
+
+	// multiCharSearchDuration: Number
+	//		If multiple characters are typed where each keystroke happens within
+	//		multiCharSearchDuration of the previous keystroke,
+	//		search for nodes matching all the keystrokes.
+	//
+	//		For example, typing "ab" will search for entries starting with
+	//		"ab" unless the delay between "a" and "b" is greater than multiCharSearchDuration.
+	multiCharSearchDuration: 250,
+
+	_onLetterKeyNav: function(message){
+		// summary:
+		//		Called when user presses a prinatable key; search for node starting with recently typed letters.
+		// message: Object
+		//		Like { node: TreeNode, key: 'a' } where key is the key the user pressed.
+
+		// Branch depending on whether this key starts a new search, or modifies an existing search
+		var cs = this._curSearch;
+		if(cs){
+			// We are continuing a search.  Ex: user has pressed 'a', and now has pressed
+			// 'b', so we want to search for nodes starting w/"ab".
+			cs.pattern = cs.pattern + message.key;
+			clearTimeout(cs.timer);
+		}else{
+			// We are starting a new search
+			cs = this._curSearch = {
+					pattern: message.key,
+					startNode: message.node
+			};
+		}
+
+		// set/reset timer to forget recent keystrokes
+		var self = this;
+		cs.timer = setTimeout(function(){
+			delete self._curSearch;
+		}, this.multiCharSearchDuration);
+
+		// Navigate to TreeNode matching keystrokes [entered so far].
+		var node = cs.startNode;
+		do{
+			node = this._getNextNode(node);
+			//check for last node, jump to first node if necessary
+			if(!node){
+				node = this._getRootOrFirstNode();
+			}
+		}while(node !== cs.startNode && (node.label.toLowerCase().substr(0, cs.pattern.length) != cs.pattern));
+		if(node && node.isTreeNode){
+			// no need to set focus if back where we started
+			if(node !== cs.startNode){
+				this.focusNode(node);
+			}
+		}
+	},
+
+	_onClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){
+		// summary:
+		//		Translates click events into commands for the controller to process
+
+		var domElement = e.target,
+			isExpandoClick = (domElement == nodeWidget.expandoNode || domElement == nodeWidget.expandoNodeText);
+
+		if( (this.openOnClick && nodeWidget.isExpandable) || isExpandoClick ){
+			// expando node was clicked, or label of a folder node was clicked; open it
+			if(nodeWidget.isExpandable){
+				this._onExpandoClick({node:nodeWidget});
+			}
+		}else{
+			this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } );
+			this.onClick(nodeWidget.item, nodeWidget, e);
+			this.focusNode(nodeWidget);
+		}
+		if(!isExpandoClick){
+			this._selectNode(nodeWidget);
+		}
+		dojo.stopEvent(e);
+	},
+	_onDblClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){
+		// summary:
+		//		Translates double-click events into commands for the controller to process
+
+		var domElement = e.target,
+			isExpandoClick = (domElement == nodeWidget.expandoNode || domElement == nodeWidget.expandoNodeText);
+
+		if( (this.openOnDblClick && nodeWidget.isExpandable) ||isExpandoClick ){
+			// expando node was clicked, or label of a folder node was clicked; open it
+			if(nodeWidget.isExpandable){
+				this._onExpandoClick({node:nodeWidget});
+			}
+		}else{
+			this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } );
+			this.onDblClick(nodeWidget.item, nodeWidget, e);
+			this.focusNode(nodeWidget);
+		}
+		if(!isExpandoClick){
+			this._selectNode(nodeWidget);
+		}
+		dojo.stopEvent(e);
+	},
+
+	_onExpandoClick: function(/*Object*/ message){
+		// summary:
+		//		User clicked the +/- icon; expand or collapse my children.
+		var node = message.node;
+
+		// If we are collapsing, we might be hiding the currently focused node.
+		// Also, clicking the expando node might have erased focus from the current node.
+		// For simplicity's sake just focus on the node with the expando.
+		this.focusNode(node);
+
+		if(node.isExpanded){
+			this._collapseNode(node);
+		}else{
+			this._expandNode(node);
+		}
+	},
+
+	onClick: function(/* dojo.data */ item, /*TreeNode*/ node, /*Event*/ evt){
+		// summary:
+		//		Callback when a tree node is clicked
+		// tags:
+		//		callback
+	},
+	onDblClick: function(/* dojo.data */ item, /*TreeNode*/ node, /*Event*/ evt){
+		// summary:
+		//		Callback when a tree node is double-clicked
+		// tags:
+		//		callback
+	},
+	onOpen: function(/* dojo.data */ item, /*TreeNode*/ node){
+		// summary:
+		//		Callback when a node is opened
+		// tags:
+		//		callback
+	},
+	onClose: function(/* dojo.data */ item, /*TreeNode*/ node){
+		// summary:
+		//		Callback when a node is closed
+		// tags:
+		//		callback
+	},
+
+	_getNextNode: function(node){
+		// summary:
+		//		Get next visible node
+
+		if(node.isExpandable && node.isExpanded && node.hasChildren()){
+			// if this is an expanded node, get the first child
+			return node.getChildren()[0];		// _TreeNode
+		}else{
+			// find a parent node with a sibling
+			while(node && node.isTreeNode){
+				var returnNode = node.getNextSibling();
+				if(returnNode){
+					return returnNode;		// _TreeNode
+				}
+				node = node.getParent();
+			}
+			return null;
+		}
+	},
+
+	_getRootOrFirstNode: function(){
+		// summary:
+		//		Get first visible node
+		return this.showRoot ? this.rootNode : this.rootNode.getChildren()[0];
+	},
+
+	_collapseNode: function(/*_TreeNode*/ node){
+		// summary:
+		//		Called when the user has requested to collapse the node
+
+		if(node._expandNodeDeferred){
+			delete node._expandNodeDeferred;
+		}
+
+		if(node.isExpandable){
+			if(node.state == "LOADING"){
+				// ignore clicks while we are in the process of loading data
+				return;
+			}
+
+			node.collapse();
+			this.onClose(node.item, node);
+
+			if(node.item){
+				this._state(node.item,false);
+				this._saveState();
+			}
+		}
+	},
+
+	_expandNode: function(/*_TreeNode*/ node, /*Boolean?*/ recursive){
+		// summary:
+		//		Called when the user has requested to expand the node
+		// recursive:
+		//		Internal flag used when _expandNode() calls itself, don't set.
+		// returns:
+		//		Deferred that fires when the node is loaded and opened and (if persist=true) all it's descendants
+		//		that were previously opened too
+
+		if(node._expandNodeDeferred && !recursive){
+			// there's already an expand in progress (or completed), so just return
+			return node._expandNodeDeferred;	// dojo.Deferred
+		}
+
+		var model = this.model,
+			item = node.item,
+			_this = this;
+
+		switch(node.state){
+			case "UNCHECKED":
+				// need to load all the children, and then expand
+				node.markProcessing();
+
+				// Setup deferred to signal when the load and expand are finished.
+				// Save that deferred in this._expandDeferred as a flag that operation is in progress.
+				var def = (node._expandNodeDeferred = new dojo.Deferred());
+
+				// Get the children
+				model.getChildren(
+					item,
+					function(items){
+						node.unmarkProcessing();
+
+						// Display the children and also start expanding any children that were previously expanded
+						// (if this.persist == true).   The returned Deferred will fire when those expansions finish.
+						var scid = node.setChildItems(items);
+
+						// Call _expandNode() again but this time it will just to do the animation (default branch).
+						// The returned Deferred will fire when the animation completes.
+						// TODO: seems like I can avoid recursion and just use a deferred to sequence the events?
+						var ed = _this._expandNode(node, true);
+
+						// After the above two tasks (setChildItems() and recursive _expandNode()) finish,
+						// signal that I am done.
+						scid.addCallback(function(){
+							ed.addCallback(function(){
+								def.callback();
+							})
+						});
+					},
+					function(err){
+						console.error(_this, ": error loading root children: ", err);
+					}
+				);
+				break;
+
+			default:	// "LOADED"
+				// data is already loaded; just expand node
+				def = (node._expandNodeDeferred = node.expand());
+
+				this.onOpen(node.item, node);
+
+				if(item){
+					this._state(item, true);
+					this._saveState();
+				}
+		}
+
+		return def;	// dojo.Deferred
+	},
+
+	////////////////// Miscellaneous functions ////////////////
+
+	focusNode: function(/* _tree.Node */ node){
+		// summary:
+		//		Focus on the specified node (which must be visible)
+		// tags:
+		//		protected
+
+		// set focus so that the label will be voiced using screen readers
+		dijit.focus(node.labelNode);
+	},
+
+	_selectNode: function(/*_tree.Node*/ node){
+		// summary:
+		//		Mark specified node as select, and unmark currently selected node.
+		// tags:
+		//		protected
+
+		if(this.selectedNode && !this.selectedNode._destroyed){
+			this.selectedNode.setSelected(false);
+		}
+		if(node){
+			node.setSelected(true);
+		}
+		this.selectedNode = node;
+	},
+
+	_onNodeFocus: function(/*dijit._Widget*/ node){
+		// summary:
+		//		Called when a TreeNode gets focus, either by user clicking
+		//		it, or programatically by arrow key handling code.
+		// description:
+		//		It marks that the current node is the selected one, and the previously
+		//		selected node no longer is.
+
+		if(node && node != this.lastFocused){
+			if(this.lastFocused && !this.lastFocused._destroyed){
+				// mark that the previously focsable node is no longer focusable
+				this.lastFocused.setFocusable(false);
+			}
+
+			// mark that the new node is the currently selected one
+			node.setFocusable(true);
+			this.lastFocused = node;
+		}
+	},
+
+	_onNodeMouseEnter: function(/*dijit._Widget*/ node){
+		// summary:
+		//		Called when mouse is over a node (onmouseenter event),
+		//		this is monitored by the DND code
+	},
+
+	_onNodeMouseLeave: function(/*dijit._Widget*/ node){
+		// summary:
+		//		Called when mouse leaves a node (onmouseleave event),
+		//		this is monitored by the DND code
+	},
+
+	//////////////// Events from the model //////////////////////////
+
+	_onItemChange: function(/*Item*/ item){
+		// summary:
+		//		Processes notification of a change to an item's scalar values like label
+		var model = this.model,
+			identity = model.getIdentity(item),
+			nodes = this._itemNodesMap[identity];
+
+		if(nodes){
+			var label = this.getLabel(item),
+				tooltip = this.getTooltip(item);
+			dojo.forEach(nodes, function(node){
+				node.set({
+					item: item,		// theoretically could be new JS Object representing same item
+					label: label,
+					tooltip: tooltip
+				});
+				node._updateItemClasses(item);
+			});
+		}
+	},
+
+	_onItemChildrenChange: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
+		// summary:
+		//		Processes notification of a change to an item's children
+		var model = this.model,
+			identity = model.getIdentity(parent),
+			parentNodes = this._itemNodesMap[identity];
+
+		if(parentNodes){
+			dojo.forEach(parentNodes,function(parentNode){
+				parentNode.setChildItems(newChildrenList);
+			});
+		}
+	},
+
+	_onItemDelete: function(/*Item*/ item){
+		// summary:
+		//		Processes notification of a deletion of an item
+		var model = this.model,
+			identity = model.getIdentity(item),
+			nodes = this._itemNodesMap[identity];
+
+		if(nodes){
+			dojo.forEach(nodes,function(node){
+				var parent = node.getParent();
+				if(parent){
+					// if node has not already been orphaned from a _onSetItem(parent, "children", ..) call...
+					parent.removeChild(node);
+				}
+				node.destroyRecursive();
+			});
+			delete this._itemNodesMap[identity];
+		}
+	},
+
+	/////////////// Miscellaneous funcs
+
+	_initState: function(){
+		// summary:
+		//		Load in which nodes should be opened automatically
+		if(this.persist){
+			var cookie = dojo.cookie(this.cookieName);
+			this._openedItemIds = {};
+			if(cookie){
+				dojo.forEach(cookie.split(','), function(item){
+					this._openedItemIds[item] = true;
+				}, this);
+			}
+		}
+	},
+	_state: function(item,expanded){
+		// summary:
+		//		Query or set expanded state for an item,
+		if(!this.persist){
+			return false;
+		}
+		var id=this.model.getIdentity(item);
+		if(arguments.length === 1){
+			return this._openedItemIds[id];
+		}
+		if(expanded){
+			this._openedItemIds[id] = true;
+		}else{
+			delete this._openedItemIds[id];
+		}
+	},
+	_saveState: function(){
+		// summary:
+		//		Create and save a cookie with the currently expanded nodes identifiers
+		if(!this.persist){
+			return;
+		}
+		var ary = [];
+		for(var id in this._openedItemIds){
+			ary.push(id);
+		}
+		dojo.cookie(this.cookieName, ary.join(","), {expires:365});
+	},
+
+	destroy: function(){
+		if(this._curSearch){
+			clearTimeout(this._curSearch.timer);
+			delete this._curSearch;
+		}
+		if(this.rootNode){
+			this.rootNode.destroyRecursive();
+		}
+		if(this.dndController && !dojo.isString(this.dndController)){
+			this.dndController.destroy();
+		}
+		this.rootNode = null;
+		this.inherited(arguments);
+	},
+
+	destroyRecursive: function(){
+		// A tree is treated as a leaf, not as a node with children (like a grid),
+		// but defining destroyRecursive for back-compat.
+		this.destroy();
+	},
+
+	resize: function(changeSize){
+		if(changeSize){
+			dojo.marginBox(this.domNode, changeSize);
+			dojo.style(this.domNode, "overflow", "auto");	// for scrollbars
+		}
+
+		// The only JS sizing involved w/tree is the indentation, which is specified
+		// in CSS and read in through this dummy indentDetector node (tree must be
+		// visible and attached to the DOM to read this)
+		this._nodePixelIndent = dojo.marginBox(this.tree.indentDetector).w;
+
+		if(this.tree.rootNode){
+			// If tree has already loaded, then reset indent for all the nodes
+			this.tree.rootNode.set('indent', this.showRoot ? 0 : -1);
+		}
+	},
+
+	_createTreeNode: function(/*Object*/ args){
+		// summary:
+		//		creates a TreeNode
+		// description:
+		//		Developers can override this method to define their own TreeNode class;
+		//		However it will probably be removed in a future release in favor of a way
+		//		of just specifying a widget for the label, rather than one that contains
+		//		the children too.
+		return new dijit._TreeNode(args);
+	}
 });
-delete this._itemNodesMap[_83];
-}
-},_initState:function(){
-if(this.persist){
-var _87=dojo.cookie(this.cookieName);
-this._openedItemIds={};
-if(_87){
-dojo.forEach(_87.split(","),function(_88){
-this._openedItemIds[_88]=true;
-},this);
-}
-}
-},_state:function(_89,_8a){
-if(!this.persist){
-return false;
-}
-var id=this.model.getIdentity(_89);
-if(arguments.length===1){
-return this._openedItemIds[id];
-}
-if(_8a){
-this._openedItemIds[id]=true;
-}else{
-delete this._openedItemIds[id];
-}
-},_saveState:function(){
-if(!this.persist){
-return;
-}
-var ary=[];
-for(var id in this._openedItemIds){
-ary.push(id);
-}
-dojo.cookie(this.cookieName,ary.join(","),{expires:365});
-},destroy:function(){
-if(this._curSearch){
-clearTimeout(this._curSearch.timer);
-delete this._curSearch;
-}
-if(this.rootNode){
-this.rootNode.destroyRecursive();
-}
-if(this.dndController&&!dojo.isString(this.dndController)){
-this.dndController.destroy();
-}
-this.rootNode=null;
-this.inherited(arguments);
-},destroyRecursive:function(){
-this.destroy();
-},resize:function(_8b){
-if(_8b){
-dojo.marginBox(this.domNode,_8b);
-dojo.style(this.domNode,"overflow","auto");
-}
-this._nodePixelIndent=dojo.marginBox(this.tree.indentDetector).w;
-if(this.tree.rootNode){
-this.tree.rootNode.attr("indent",this.showRoot?0:-1);
-}
-},_createTreeNode:function(_8c){
-return new dijit._TreeNode(_8c);
-}});
+
+// For back-compat.  TODO: remove in 2.0
 dojo.require("dijit.tree.TreeStoreModel");
 dojo.require("dijit.tree.ForestStoreModel");
-}
diff --git a/dijit/_Calendar.js b/dijit/_Calendar.js
index b4f5856..ce169f1 100644
--- a/dijit/_Calendar.js
+++ b/dijit/_Calendar.js
@@ -1,14 +1,8 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._Calendar"]){
-dojo._hasResource["dijit._Calendar"]=true;
 dojo.provide("dijit._Calendar");
+
 dojo.require("dijit.Calendar");
-dojo.deprecated("dijit._Calendar is deprecated","dijit._Calendar moved to dijit.Calendar",1.5);
-dijit._Calendar=dijit.Calendar;
-}
+dojo.deprecated("dijit._Calendar is deprecated", "dijit._Calendar moved to dijit.Calendar", 1.5);
+
+// dijit._Calendar had an underscore all this time merely because it did
+// not satisfy dijit's a11y policy.
+dijit._Calendar = dijit.Calendar;
diff --git a/dijit/_Contained.js b/dijit/_Contained.js
index 2b71174..8fd7b3d 100644
--- a/dijit/_Contained.js
+++ b/dijit/_Contained.js
@@ -1,31 +1,65 @@
-/*
-	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
-*/
+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
+				//		specifies isContainer
+				var parent = dijit.getEnclosingWidget(this.domNode.parentNode);
+				return parent && parent.isContainer ? parent : null;
+			},
+
+			_getSibling: function(/*String*/ 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);
+				return node && dijit.byNode(node);	// dijit._Widget
+			},
+
+			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"); // dijit._Widget
+			},
+
+			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"); // dijit._Widget
+			},
+
+			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._Contained"]){
-dojo._hasResource["dijit._Contained"]=true;
-dojo.provide("dijit._Contained");
-dojo.declare("dijit._Contained",null,{getParent:function(){
-var _1=dijit.getEnclosingWidget(this.domNode.parentNode);
-return _1&&_1.isContainer?_1:null;
-},_getSibling:function(_2){
-var _3=this.domNode;
-do{
-_3=_3[_2+"Sibling"];
-}while(_3&&_3.nodeType!=1);
-return _3&&dijit.byNode(_3);
-},getPreviousSibling:function(){
-return this._getSibling("previous");
-},getNextSibling:function(){
-return this._getSibling("next");
-},getIndexInParent:function(){
-var p=this.getParent();
-if(!p||!p.getIndexOfChild){
-return -1;
-}
-return p.getIndexOfChild(this);
-}});
-}
diff --git a/dijit/_Container.js b/dijit/_Container.js
index 820a5db..46c7ea9 100644
--- a/dijit/_Container.js
+++ b/dijit/_Container.js
@@ -1,62 +1,132 @@
-/*
-	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
-*/
+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.
 
-if(!dojo._hasResource["dijit._Container"]){
-dojo._hasResource["dijit._Container"]=true;
-dojo.provide("dijit._Container");
-dojo.declare("dijit._Container",null,{isContainer:true,buildRendering:function(){
-this.inherited(arguments);
-if(!this.containerNode){
-this.containerNode=this.domNode;
-}
-},addChild:function(_1,_2){
-var _3=this.containerNode;
-if(_2&&typeof _2=="number"){
-var _4=this.getChildren();
-if(_4&&_4.length>=_2){
-_3=_4[_2-1].domNode;
-_2="after";
-}
-}
-dojo.place(_1.domNode,_3,_2);
-if(this._started&&!_1._started){
-_1.startup();
-}
-},removeChild:function(_5){
-if(typeof _5=="number"&&_5>0){
-_5=this.getChildren()[_5];
-}
-if(_5&&_5.domNode){
-var _6=_5.domNode;
-_6.parentNode.removeChild(_6);
-}
-},getChildren:function(){
-return dojo.query("> [widgetId]",this.containerNode).map(dijit.byNode);
-},hasChildren:function(){
-return dojo.query("> [widgetId]",this.containerNode).length>0;
-},destroyDescendants:function(_7){
-dojo.forEach(this.getChildren(),function(_8){
-_8.destroyRecursive(_7);
-});
-},_getSiblingOfChild:function(_9,_a){
-var _b=_9.domNode,_c=(_a>0?"nextSibling":"previousSibling");
-do{
-_b=_b[_c];
-}while(_b&&(_b.nodeType!=1||!dijit.byNode(_b)));
-return _b&&dijit.byNode(_b);
-},getIndexOfChild:function(_d){
-return dojo.indexOf(this.getChildren(),_d);
-},startup:function(){
-if(this._started){
-return;
-}
-dojo.forEach(this.getChildren(),function(_e){
-_e.startup();
-});
-this.inherited(arguments);
-}});
-}
+		// isContainer: [protected] Boolean
+		//		Indicates that this widget acts as a "parent" to the descendant widgets.
+		//		When the parent is started it will call startup() on the child widgets.
+		//		See also `isLayoutContainer`.
+		isContainer: true,
+
+		buildRendering: function(){
+			this.inherited(arguments);
+			if(!this.containerNode){
+				// all widgets with descendants must set containerNode
+	 				this.containerNode = this.domNode;
+			}
+		},
+
+		addChild: function(/*dijit._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(widget){
+				var node = widget.domNode;
+				if(node && node.parentNode){
+					node.parentNode.removeChild(node); // detach but don't destroy
+				}
+			}
+		},
+
+		hasChildren: function(){
+			// summary:
+			//		Returns true if widget has children, i.e. if this.containerNode contains something.
+			return this.getChildren().length > 0;	// 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(/*dijit._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,
+				which = (dir>0 ? "nextSibling" : "previousSibling");
+			do{
+				node = node[which];
+			}while(node && (node.nodeType != 1 || !dijit.byNode(node)));
+			return node && dijit.byNode(node);	// dijit._Widget
+		},
+
+		getIndexOfChild: function(/*dijit._Widget*/ child){
+			// summary:
+			//		Gets the index of the child in this container or -1 if not found
+			return dojo.indexOf(this.getChildren(), child);	// int
+		},
+
+		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; }
+
+			// Startup all children of this widget
+			dojo.forEach(this.getChildren(), function(child){ child.startup(); });
+
+			this.inherited(arguments);
+		}
+	}
+);
diff --git a/dijit/_CssStateMixin.js b/dijit/_CssStateMixin.js
new file mode 100644
index 0000000..545c650
--- /dev/null
+++ b/dijit/_CssStateMixin.js
@@ -0,0 +1,252 @@
+dojo.provide("dijit._CssStateMixin");
+
+
+dojo.declare("dijit._CssStateMixin", [], {
+	// summary:
+	//		Mixin for widgets to set CSS classes on the widget DOM nodes depending on hover/mouse press/focus
+	//		state changes, and also higher-level state changes such becoming disabled or selected.
+	//
+	// description:
+	//		By mixing this class into your widget, and setting the this.baseClass attribute, it will automatically
+	//		maintain CSS classes on the widget root node (this.domNode) depending on hover,
+	//		active, focus, etc. state.   Ex: with a baseClass of dijitButton, it will apply the classes
+	//		dijitButtonHovered and dijitButtonActive, as the user moves the mouse over the widget and clicks it.
+	//
+	//		It also sets CSS like dijitButtonDisabled based on widget semantic state.
+	//
+	//		By setting the cssStateNodes attribute, a widget can also track events on subnodes (like buttons
+	//		within the widget).
+
+	// cssStateNodes: [protected] Object
+	//		List of sub-nodes within the widget that need CSS classes applied on mouse hover/press and focus
+	//.
+	//		Each entry in the hash is a an attachpoint names (like "upArrowButton") mapped to a CSS class names
+	//		(like "dijitUpArrowButton"). Example:
+	//	|		{
+	//	|			"upArrowButton": "dijitUpArrowButton",
+	//	|			"downArrowButton": "dijitDownArrowButton"
+	//	|		}
+	//		The above will set the CSS class dijitUpArrowButton to the this.upArrowButton DOMNode when it
+	//		is hovered, etc.
+	cssStateNodes: {},
+
+	postCreate: function(){
+		this.inherited(arguments);
+
+		// Automatically monitor mouse events (essentially :hover and :active) on this.domNode
+		dojo.forEach(["onmouseenter", "onmouseleave", "onmousedown"], function(e){
+			this.connect(this.domNode, e, "_cssMouseEvent");
+		}, this);
+		
+		// Monitoring changes to disabled, readonly, etc. state, and update CSS class of root node
+		this.connect(this, "set", function(name, value){
+			if(arguments.length >= 2 && {disabled: true, readOnly: true, checked:true, selected:true}[name]){
+				this._setStateClass();
+			}
+		});
+
+		// The widget coming in/out of the focus change affects it's state
+		dojo.forEach(["_onFocus", "_onBlur"], function(ap){
+			this.connect(this, ap, "_setStateClass");
+		}, this);
+
+		// Events on sub nodes within the widget
+		for(var ap in this.cssStateNodes){
+			this._trackMouseState(this[ap], this.cssStateNodes[ap]);
+		}
+		// Set state initially; there's probably no hover/active/focus state but widget might be
+		// disabled/readonly so we want to set CSS classes for those conditions.
+		this._setStateClass();
+	},
+
+	_cssMouseEvent: function(/*Event*/ event){
+		// summary:
+		//	Sets _hovering and _active properties depending on mouse state,
+		//	then calls _setStateClass() to set appropriate CSS classes for this.domNode.
+
+		if(!this.disabled){
+			switch(event.type){
+				case "mouseenter":
+				case "mouseover":	// generated on non-IE browsers even though we connected to mouseenter
+					this._hovering = true;
+					this._active = this._mouseDown;
+					break;
+
+				case "mouseleave":
+				case "mouseout":	// generated on non-IE browsers even though we connected to 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 this.domNode before the mouse up event.
+					// Alternately could set active=false on mouseout.
+					var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
+						this._active = false;
+						this._mouseDown = false;
+						this._setStateClass();
+						this.disconnect(mouseUpConnector);
+					});
+					break;
+			}
+			this._setStateClass();
+		}
+	},
+
+	_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".
+		//
+		//		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.isLeftToRight()){
+			// For RTL mode we need to set an addition class like dijitTextBoxRtl.
+			multiply("Rtl");
+		}
+
+		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("Active");
+			}else if(this._hovering){
+				multiply("Hover");
+			}
+		}
+
+		if(this._focused){
+			multiply("Focused");
+		}
+
+		// 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;
+	},
+
+	_trackMouseState: function(/*DomNode*/ node, /*String*/ clazz){
+		// summary:
+		//		Track mouse/focus events on specified node and set CSS class on that node to indicate
+		//		current state.   Usually not called directly, but via cssStateNodes attribute.
+		// description:
+		//		Given class=foo, will set the following CSS class on the node
+		//			- fooActive: if the user is currently pressing down the mouse button while over the node
+		//			- fooHover: if the user is hovering the mouse over the node, but not pressing down a button
+		//			- fooFocus: if the node is focused
+		//
+		//		Note that it won't set any classes if the widget is disabled.
+		// node: DomNode
+		//		Should be a sub-node of the widget, not the top node (this.domNode), since the top node
+		//		is handled specially and automatically just by mixing in this class.
+		// clazz: String
+		//		CSS class name (ex: dijitSliderUpArrow).
+
+		// Current state of node (initially false)
+		// NB: setting specifically to false because dojo.toggleClass() needs true boolean as third arg
+		var hovering=false, active=false, focused=false;
+
+		var self = this,
+			cn = dojo.hitch(this, "connect", node);
+
+		function setClass(){
+			var disabled = ("disabled" in self && self.disabled) || ("readonly" in self && self.readonly);
+			dojo.toggleClass(node, clazz+"Hover", hovering && !active && !disabled);
+			dojo.toggleClass(node, clazz+"Active", active && !disabled);
+			dojo.toggleClass(node, clazz+"Focused", focused && !disabled);
+		}
+
+		// Mouse
+		cn("onmouseenter", function(){
+			hovering = true;
+			setClass();
+		});
+		cn("onmouseleave", function(){
+			hovering = false;
+			active = false;
+			setClass();
+		});
+		cn("onmousedown", function(){
+			active = true;
+			setClass();
+		});
+		cn("onmouseup", function(){
+			active = false;
+			setClass();
+		});
+
+		// Focus
+		cn("onfocus", function(){
+			focused = true;
+			setClass();
+		});
+		cn("onblur", function(){
+			focused = false;
+			setClass();
+		});
+
+		// Just in case widget is enabled/disabled while it has focus/hover/active state.
+		// Maybe this is overkill.
+		this.connect(this, "set", function(name, value){
+			if(name == "disabled" || name == "readOnly"){
+				setClass();
+			}
+		});
+	}
+});
diff --git a/dijit/_DialogMixin.js b/dijit/_DialogMixin.js
index 20c7bf7..add8dc1 100644
--- a/dijit/_DialogMixin.js
+++ b/dijit/_DialogMixin.js
@@ -1,26 +1,75 @@
-/*
-	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
-*/
+dojo.provide("dijit._DialogMixin");
 
+dojo.require("dijit._Widget");
 
-if(!dojo._hasResource["dijit._DialogMixin"]){
-dojo._hasResource["dijit._DialogMixin"]=true;
-dojo.provide("dijit._DialogMixin");
-dojo.declare("dijit._DialogMixin",null,{attributeMap:dijit._Widget.prototype.attributeMap,execute:function(_1){
-},onCancel:function(){
-},onExecute:function(){
-},_onSubmit:function(){
-this.onExecute();
-this.execute(this.attr("value"));
-},_getFocusItems:function(_2){
-var _3=dijit._getTabNavigable(dojo.byId(_2));
-this._firstFocusItem=_3.lowest||_3.first||_2;
-this._lastFocusItem=_3.last||_3.highest||this._firstFocusItem;
-if(dojo.isMoz&&this._firstFocusItem.tagName.toLowerCase()=="input"&&dojo.getNodeProp(this._firstFocusItem,"type").toLowerCase()=="file"){
-dojo.attr(_2,"tabIndex","0");
-this._firstFocusItem=_2;
-}
-}});
-}
+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.get('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.getNodeProp(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;
+			}
+		}
+	}
+);
\ No newline at end of file
diff --git a/dijit/_HasDropDown.js b/dijit/_HasDropDown.js
index 7d03423..c964577 100644
--- a/dijit/_HasDropDown.js
+++ b/dijit/_HasDropDown.js
@@ -1,221 +1,397 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._HasDropDown"]){
-dojo._hasResource["dijit._HasDropDown"]=true;
 dojo.provide("dijit._HasDropDown");
+
 dojo.require("dijit._base.place");
 dojo.require("dijit._Widget");
-dojo.declare("dijit._HasDropDown",null,{_buttonNode:null,_arrowWrapperNode:null,_popupStateNode:null,_aroundNode:null,dropDown:null,autoWidth:true,forceWidth:false,maxHeight:0,dropDownPosition:["below","above"],_stopClickEvents:true,_onDropDownMouse:function(e){
-if(e.type=="click"&&!this._seenKeydown){
-return;
-}
-this._seenKeydown=false;
-if(e.type=="mousedown"){
-this._docHandler=this.connect(dojo.doc,"onmouseup","_onDropDownMouseup");
-}
-if(this.disabled||this.readOnly){
-return;
-}
-if(this._stopClickEvents){
-dojo.stopEvent(e);
-}
-this.toggleDropDown();
-if(e.type=="click"||e.type=="keypress"){
-this._onDropDownMouseup();
-}
-},_onDropDownMouseup:function(e){
-if(e&&this._docHandler){
-this.disconnect(this._docHandler);
-}
-var _1=this.dropDown,_2=false;
-if(e&&this._opened){
-var c=dojo.position(this._buttonNode,true);
-if(!(e.pageX>=c.x&&e.pageX<=c.x+c.w)||!(e.pageY>=c.y&&e.pageY<=c.y+c.h)){
-var t=e.target;
-while(t&&!_2){
-if(dojo.hasClass(t,"dijitPopup")){
-_2=true;
-}else{
-t=t.parentNode;
-}
-}
-if(_2){
-t=e.target;
-if(_1.onItemClick){
-var _3;
-while(t&&!(_3=dijit.byNode(t))){
-t=t.parentNode;
-}
-if(_3&&_3.onClick&&_3.getParent){
-_3.getParent().onItemClick(_3,e);
-}
-}
-return;
-}
-}
-}
-if(this._opened&&_1.focus){
-window.setTimeout(dojo.hitch(_1,"focus"),1);
-}
-},_setupDropdown:function(){
-this._buttonNode=this._buttonNode||this.focusNode||this.domNode;
-this._popupStateNode=this._popupStateNode||this.focusNode||this._buttonNode;
-this._aroundNode=this._aroundNode||this.domNode;
-this.connect(this._buttonNode,"onmousedown","_onDropDownMouse");
-this.connect(this._buttonNode,"onclick","_onDropDownMouse");
-this.connect(this._buttonNode,"onkeydown","_onDropDownKeydown");
-this.connect(this._buttonNode,"onblur","_onDropDownBlur");
-this.connect(this._buttonNode,"onkeypress","_onKey");
-if(this._setStateClass){
-this.connect(this,"openDropDown","_setStateClass");
-this.connect(this,"closeDropDown","_setStateClass");
-}
-var _4={"after":this.isLeftToRight()?"Right":"Left","before":this.isLeftToRight()?"Left":"Right","above":"Up","below":"Down","left":"Left","right":"Right"}[this.dropDownPosition[0]]||this.dropDownPosition[0]||"Down";
-dojo.addClass(this._arrowWrapperNode||this._buttonNode,"dijit"+_4+"ArrowButton");
-},postCreate:function(){
-this._setupDropdown();
-this.inherited(arguments);
-},destroyDescendants:function(){
-if(this.dropDown){
-if(!this.dropDown._destroyed){
-this.dropDown.destroyRecursive();
-}
-delete this.dropDown;
-}
-this.inherited(arguments);
-},_onDropDownKeydown:function(e){
-this._seenKeydown=true;
-},_onKeyPress:function(e){
-if(this._opened&&e.charOrCode==dojo.keys.ESCAPE&&!e.shiftKey&&!e.ctrlKey&&!e.altKey){
-this.toggleDropDown();
-dojo.stopEvent(e);
-return;
-}
-this.inherited(arguments);
-},_onDropDownBlur:function(e){
-this._seenKeydown=false;
-},_onKey:function(e){
-if(this.disabled||this.readOnly){
-return;
-}
-var d=this.dropDown;
-if(d&&this._opened&&d.handleKey){
-if(d.handleKey(e)===false){
-return;
-}
-}
-if(d&&this._opened&&e.keyCode==dojo.keys.ESCAPE){
-this.toggleDropDown();
-return;
-}
-if(e.keyCode==dojo.keys.DOWN_ARROW||e.keyCode==dojo.keys.ENTER||e.charOrCode==" "){
-this._onDropDownMouse(e);
-}
-},_onBlur:function(){
-this.closeDropDown();
-this.inherited(arguments);
-},isLoaded:function(){
-return true;
-},loadDropDown:function(_5){
-_5();
-},toggleDropDown:function(){
-if(this.disabled||this.readOnly){
-return;
-}
-this.focus();
-var _6=this.dropDown;
-if(!_6){
-return;
-}
-if(!this._opened){
-if(!this.isLoaded()){
-this.loadDropDown(dojo.hitch(this,"openDropDown"));
-return;
-}else{
-this.openDropDown();
-}
-}else{
-this.closeDropDown();
-}
-},openDropDown:function(){
-var _7=this.dropDown;
-var _8=_7.domNode;
-var _9=this;
-if(!this._preparedNode){
-dijit.popup.moveOffScreen(_8);
-this._preparedNode=true;
-if(_8.style.width){
-this._explicitDDWidth=true;
-}
-if(_8.style.height){
-this._explicitDDHeight=true;
-}
-}
-if(this.maxHeight||this.forceWidth||this.autoWidth){
-var _a={display:"",visibility:"hidden"};
-if(!this._explicitDDWidth){
-_a.width="";
-}
-if(!this._explicitDDHeight){
-_a.height="";
-}
-dojo.style(_8,_a);
-var mb=dojo.marginBox(_8);
-var _b=(this.maxHeight&&mb.h>this.maxHeight);
-dojo.style(_8,{overflow:_b?"auto":"hidden"});
-if(this.forceWidth){
-mb.w=this.domNode.offsetWidth;
-}else{
-if(this.autoWidth){
-mb.w=Math.max(mb.w,this.domNode.offsetWidth);
-}else{
-delete mb.w;
-}
-}
-if(_b){
-mb.h=this.maxHeight;
-if("w" in mb){
-mb.w+=16;
-}
-}else{
-delete mb.h;
-}
-delete mb.t;
-delete mb.l;
-if(dojo.isFunction(_7.resize)){
-_7.resize(mb);
-}else{
-dojo.marginBox(_8,mb);
-}
-}
-var _c=dijit.popup.open({parent:this,popup:_7,around:this._aroundNode,orient:dijit.getPopupAroundAlignment((this.dropDownPosition&&this.dropDownPosition.length)?this.dropDownPosition:["below"],this.isLeftToRight()),onExecute:function(){
-_9.closeDropDown(true);
-},onCancel:function(){
-_9.closeDropDown(true);
-},onClose:function(){
-dojo.attr(_9._popupStateNode,"popupActive",false);
-dojo.removeClass(_9._popupStateNode,"dijitHasDropDownOpen");
-_9._opened=false;
-_9.state="";
-}});
-dojo.attr(this._popupStateNode,"popupActive","true");
-dojo.addClass(_9._popupStateNode,"dijitHasDropDownOpen");
-this._opened=true;
-this.state="Opened";
-return _c;
-},closeDropDown:function(_d){
-if(this._opened){
-dijit.popup.close(this.dropDown);
-if(_d){
-this.focus();
-}
-this._opened=false;
-this.state="";
-}
-}});
-}
+
+dojo.declare("dijit._HasDropDown",
+	null,
+	{
+		// summary:
+		//		Mixin for widgets that need drop down ability.
+
+		// _buttonNode: [protected] DomNode
+		//		The button/icon/node to click to display the drop down.
+		//		Can be set via a dojoAttachPoint assignment.
+		//		If missing, then either focusNode or domNode (if focusNode is also missing) will be used.
+		_buttonNode: null,
+
+		// _arrowWrapperNode: [protected] DomNode
+		//		Will set CSS class dijitUpArrow, dijitDownArrow, dijitRightArrow etc. on this node depending
+		//		on where the drop down is set to be positioned.
+		//		Can be set via a dojoAttachPoint assignment.
+		//		If missing, then _buttonNode will be used.
+		_arrowWrapperNode: null,
+
+		// _popupStateNode: [protected] DomNode
+		//		The node to set the popupActive class on.
+		//		Can be set via a dojoAttachPoint assignment.
+		//		If missing, then focusNode or _buttonNode (if focusNode is missing) will be used.
+		_popupStateNode: null,
+
+		// _aroundNode: [protected] DomNode
+		//		The node to display the popup around.
+		//		Can be set via a dojoAttachPoint assignment.
+		//		If missing, then domNode will be used.
+		_aroundNode: null,
+
+		// dropDown: [protected] Widget
+		//		The widget to display as a popup.  This widget *must* be
+		//		defined before the startup function is called.
+		dropDown: null,
+
+		// autoWidth: [protected] Boolean
+		//		Set to true to make the drop down at least as wide as this
+		//		widget.  Set to false if the drop down should just be its
+		//		default width
+		autoWidth: true,
+
+		// forceWidth: [protected] Boolean
+		//		Set to true to make the drop down exactly as wide as this
+		//		widget.  Overrides autoWidth.
+		forceWidth: false,
+
+		// maxHeight: [protected] Integer
+		//		The max height for our dropdown.  Set to 0 for no max height.
+		//		any dropdown taller than this will have scrollbars
+		maxHeight: 0,
+
+		// dropDownPosition: [const] String[]
+		//		This variable controls the position of the drop down.
+		//		It's an array of strings with the following values:
+		//
+		//			* before: places drop down to the left of the target node/widget, or to the right in
+		//			  the case of RTL scripts like Hebrew and Arabic
+		//			* after: places drop down to the right of the target node/widget, or to the left in
+		//			  the case of RTL scripts like Hebrew and Arabic
+		//			* above: drop down goes above target node
+		//			* below: drop down goes below target node
+		//
+		//		The list is positions is tried, in order, until a position is found where the drop down fits
+		//		within the viewport.
+		//
+		dropDownPosition: ["below","above"],
+
+		// _stopClickEvents: Boolean
+		//		When set to false, the click events will not be stopped, in
+		//		case you want to use them in your subwidget
+		_stopClickEvents: true,
+
+		_onDropDownMouseDown: function(/*Event*/ e){
+			// summary:
+			//		Callback when the user mousedown's on the arrow icon
+
+			if(this.disabled || this.readOnly){ return; }
+
+			this._docHandler = this.connect(dojo.doc, "onmouseup", "_onDropDownMouseUp");
+
+			this.toggleDropDown();
+		},
+
+		_onDropDownMouseUp: function(/*Event?*/ e){
+			// summary:
+			//		Callback when the user lifts their mouse after mouse down on the arrow icon.
+			//		If the drop is a simple menu and the mouse is over the menu, we execute it, otherwise, we focus our
+			//		dropDown node.  If the event is missing, then we are not
+			//		a mouseup event.
+			//
+			//		This is useful for the common mouse movement pattern
+			//		with native browser <select> nodes:
+			//			1. mouse down on the select node (probably on the arrow)
+			//			2. move mouse to a menu item while holding down the mouse button
+			//			3. mouse up.  this selects the menu item as though the user had clicked it.
+			if(e && this._docHandler){
+				this.disconnect(this._docHandler);
+			}
+			var dropDown = this.dropDown, overMenu = false;
+
+			if(e && this._opened){
+				// This code deals with the corner-case when the drop down covers the original widget,
+				// because it's so large.  In that case mouse-up shouldn't select a value from the menu.
+				// Find out if our target is somewhere in our dropdown widget,
+				// but not over our _buttonNode (the clickable node)
+				var c = dojo.position(this._buttonNode, true);
+				if(!(e.pageX >= c.x && e.pageX <= c.x + c.w) ||
+					!(e.pageY >= c.y && e.pageY <= c.y + c.h)){
+					var t = e.target;
+					while(t && !overMenu){
+						if(dojo.hasClass(t, "dijitPopup")){
+							overMenu = true;
+						}else{
+							t = t.parentNode;
+						}
+					}
+					if(overMenu){
+						t = e.target;
+						if(dropDown.onItemClick){
+							var menuItem;
+							while(t && !(menuItem = dijit.byNode(t))){
+								t = t.parentNode;
+							}
+							if(menuItem && menuItem.onClick && menuItem.getParent){
+								menuItem.getParent().onItemClick(menuItem, e);
+							}
+						}
+						return;
+					}
+				}
+			}
+			if(this._opened && dropDown.focus){
+				// Focus the dropdown widget - do it on a delay so that we
+				// don't steal our own focus.
+				window.setTimeout(dojo.hitch(dropDown, "focus"), 1);
+			}
+		},
+
+		_onDropDownClick: function(/*Event*/ e){
+			// the drop down was already opened on mousedown/keydown; just need to call stopEvent()
+			if(this._stopClickEvents){
+				dojo.stopEvent(e);
+			}			
+		},
+
+		_setupDropdown: function(){
+			// summary:
+			//		set up nodes and connect our mouse and keypress events
+			this._buttonNode = this._buttonNode || this.focusNode || this.domNode;
+			this._popupStateNode = this._popupStateNode || this.focusNode || this._buttonNode;
+			this._aroundNode = this._aroundNode || this.domNode;
+			this.connect(this._buttonNode, "onmousedown", "_onDropDownMouseDown");
+			this.connect(this._buttonNode, "onclick", "_onDropDownClick");
+			this.connect(this._buttonNode, "onkeydown", "_onDropDownKeydown");
+			this.connect(this._buttonNode, "onkeyup", "_onKey");
+
+			// If we have a _setStateClass function (which happens when
+			// we are a form widget), then we need to connect our open/close
+			// functions to it
+			if(this._setStateClass){
+				this.connect(this, "openDropDown", "_setStateClass");
+				this.connect(this, "closeDropDown", "_setStateClass");
+			}
+
+			// Add a class to the "dijitDownArrowButton" type class to _buttonNode so theme can set direction of arrow
+			// based on where drop down will normally appear
+			var defaultPos = {
+					"after" : this.isLeftToRight() ? "Right" : "Left",
+					"before" : this.isLeftToRight() ? "Left" : "Right",
+					"above" : "Up",
+					"below" : "Down",
+					"left" : "Left",
+					"right" : "Right"
+			}[this.dropDownPosition[0]] || this.dropDownPosition[0] || "Down";
+			dojo.addClass(this._arrowWrapperNode || this._buttonNode, "dijit" + defaultPos + "ArrowButton");
+		},
+
+		postCreate: function(){
+			this._setupDropdown();
+			this.inherited(arguments);
+		},
+
+		destroyDescendants: function(){
+			if(this.dropDown){
+				// Destroy the drop down, unless it's already been destroyed.  This can happen because
+				// the drop down is a direct child of <body> even though it's logically my child.
+				if(!this.dropDown._destroyed){
+					this.dropDown.destroyRecursive();
+				}
+				delete this.dropDown;
+			}
+			this.inherited(arguments);
+		},
+
+		_onDropDownKeydown: function(/*Event*/ e){
+			if(e.keyCode == dojo.keys.DOWN_ARROW || e.keyCode == dojo.keys.ENTER || e.keyCode == dojo.keys.SPACE){
+				e.preventDefault();	// stop IE screen jump
+			}
+		},
+
+		_onKey: function(/*Event*/ e){
+			// summary:
+			//		Callback when the user presses a key while focused on the button node
+
+			if(this.disabled || this.readOnly){ return; }
+			var d = this.dropDown;
+			if(d && this._opened && d.handleKey){
+				if(d.handleKey(e) === false){ return; }
+			}
+			if(d && this._opened && e.keyCode == dojo.keys.ESCAPE){
+				this.toggleDropDown();
+			}else if(d && !this._opened && 
+					(e.keyCode == dojo.keys.DOWN_ARROW || e.keyCode == dojo.keys.ENTER || e.keyCode == dojo.keys.SPACE)){
+				this.toggleDropDown();
+				if(d.focus){
+					setTimeout(dojo.hitch(d, "focus"), 1);
+				}
+			}
+		},
+
+		_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);
+		},
+
+		isLoaded: function(){
+			// summary:
+			//		Returns whether or not the dropdown is loaded.  This can
+			//		be overridden in order to force a call to loadDropDown().
+			// tags:
+			//		protected
+
+			return true;
+		},
+
+		loadDropDown: function(/* Function */ loadCallback){
+			// summary:
+			//		Loads the data for the dropdown, and at some point, calls
+			//		the given callback
+			// tags:
+			//		protected
+
+			loadCallback();
+		},
+
+		toggleDropDown: function(){
+			// summary:
+			//		Toggle the drop-down widget; if it is up, close it, if not, open it
+			// tags:
+			//		protected
+
+			if(this.disabled || this.readOnly){ return; }
+			this.focus();
+			var dropDown = this.dropDown;
+			if(!dropDown){ return; }
+			if(!this._opened){
+				// If we aren't loaded, load it first so there isn't a flicker
+				if(!this.isLoaded()){
+					this.loadDropDown(dojo.hitch(this, "openDropDown"));
+					return;
+				}else{
+					this.openDropDown();
+				}
+			}else{
+				this.closeDropDown();
+			}
+		},
+
+		openDropDown: function(){
+			// summary:
+			//		Opens the dropdown for this widget - it returns the
+			//		return value of dijit.popup.open
+			// tags:
+			//		protected
+
+			var dropDown = this.dropDown;
+			var ddNode = dropDown.domNode;
+			var self = this;
+
+			// Prepare our popup's height and honor maxHeight if it exists.
+
+			// TODO: isn't maxHeight dependent on the return value from dijit.popup.open(),
+			// ie, dependent on how much space is available (BK)
+
+			if(!this._preparedNode){
+				dijit.popup.moveOffScreen(ddNode);
+				this._preparedNode = true;			
+				// Check if we have explicitly set width and height on the dropdown widget dom node
+				if(ddNode.style.width){
+					this._explicitDDWidth = true;
+				}
+				if(ddNode.style.height){
+					this._explicitDDHeight = true;
+				}
+			}
+
+			// Code for resizing dropdown (height limitation, or increasing width to match my width)
+			if(this.maxHeight || this.forceWidth || this.autoWidth){
+				var myStyle = {
+					display: "",
+					visibility: "hidden"
+				};
+				if(!this._explicitDDWidth){
+					myStyle.width = "";
+				}
+				if(!this._explicitDDHeight){
+					myStyle.height = "";
+				}
+				dojo.style(ddNode, myStyle);
+				
+				// Get size of drop down, and determine if vertical scroll bar needed
+				var mb = dojo.marginBox(ddNode);
+				var overHeight = (this.maxHeight && mb.h > this.maxHeight);
+				dojo.style(ddNode, {
+					overflowX: "hidden",
+					overflowY: overHeight ? "auto" : "hidden"
+				});
+				if(overHeight){
+					mb.h = this.maxHeight;
+					if("w" in mb){
+						mb.w += 16;	// room for vertical scrollbar
+					}
+				}else{
+					delete mb.h;
+				}
+				delete mb.t;
+				delete mb.l;
+
+				// Adjust dropdown width to match or be larger than my width
+				if(this.forceWidth){
+					mb.w = this.domNode.offsetWidth;
+				}else if(this.autoWidth){
+					mb.w = Math.max(mb.w, this.domNode.offsetWidth);
+				}else{
+					delete mb.w;
+				}
+				
+				// And finally, resize the dropdown to calculated height and width
+				if(dojo.isFunction(dropDown.resize)){
+					dropDown.resize(mb);
+				}else{
+					dojo.marginBox(ddNode, mb);
+				}
+			}
+
+			var retVal = dijit.popup.open({
+				parent: this,
+				popup: dropDown,
+				around: this._aroundNode,
+				orient: dijit.getPopupAroundAlignment((this.dropDownPosition && this.dropDownPosition.length) ? this.dropDownPosition : ["below"],this.isLeftToRight()),
+				onExecute: function(){
+					self.closeDropDown(true);
+				},
+				onCancel: function(){
+					self.closeDropDown(true);
+				},
+				onClose: function(){
+					dojo.attr(self._popupStateNode, "popupActive", false);
+					dojo.removeClass(self._popupStateNode, "dijitHasDropDownOpen");
+					self._opened = false;
+					self.state = "";
+				}
+			});
+			dojo.attr(this._popupStateNode, "popupActive", "true");
+			dojo.addClass(self._popupStateNode, "dijitHasDropDownOpen");
+			this._opened=true;
+			this.state="Opened";
+			// TODO: set this.checked and call setStateClass(), to affect button look while drop down is shown
+			return retVal;
+		},
+
+		closeDropDown: function(/*Boolean*/ focus){
+			// summary:
+			//		Closes the drop down on this widget
+			// tags:
+			//		protected
+
+			if(this._opened){
+				if(focus){ this.focus(); }
+				dijit.popup.close(this.dropDown);
+				this._opened = false;
+				this.state = "";
+			}
+		}
+
+	}
+);
diff --git a/dijit/_KeyNavContainer.js b/dijit/_KeyNavContainer.js
index e9b6605..1ca8311 100644
--- a/dijit/_KeyNavContainer.js
+++ b/dijit/_KeyNavContainer.js
@@ -1,95 +1,229 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._KeyNavContainer"]){
-dojo._hasResource["dijit._KeyNavContainer"]=true;
 dojo.provide("dijit._KeyNavContainer");
 dojo.require("dijit._Container");
-dojo.declare("dijit._KeyNavContainer",dijit._Container,{tabIndex:"0",_keyNavCodes:{},connectKeyNavHandlers:function(_1,_2){
-var _3=(this._keyNavCodes={});
-var _4=dojo.hitch(this,this.focusPrev);
-var _5=dojo.hitch(this,this.focusNext);
-dojo.forEach(_1,function(_6){
-_3[_6]=_4;
-});
-dojo.forEach(_2,function(_7){
-_3[_7]=_5;
-});
-this.connect(this.domNode,"onkeypress","_onContainerKeypress");
-this.connect(this.domNode,"onfocus","_onContainerFocus");
-},startupKeyNavChildren:function(){
-dojo.forEach(this.getChildren(),dojo.hitch(this,"_startupChild"));
-},addChild:function(_8,_9){
-dijit._KeyNavContainer.superclass.addChild.apply(this,arguments);
-this._startupChild(_8);
-},focus:function(){
-this.focusFirstChild();
-},focusFirstChild:function(){
-var _a=this._getFirstFocusableChild();
-if(_a){
-this.focusChild(_a);
-}
-},focusNext:function(){
-var _b=this._getNextFocusableChild(this.focusedChild,1);
-this.focusChild(_b);
-},focusPrev:function(){
-var _c=this._getNextFocusableChild(this.focusedChild,-1);
-this.focusChild(_c,true);
-},focusChild:function(_d,_e){
-if(this.focusedChild&&_d!==this.focusedChild){
-this._onChildBlur(this.focusedChild);
-}
-_d.focus(_e?"end":"start");
-this.focusedChild=_d;
-},_startupChild:function(_f){
-_f.attr("tabIndex","-1");
-this.connect(_f,"_onFocus",function(){
-_f.attr("tabIndex",this.tabIndex);
-});
-this.connect(_f,"_onBlur",function(){
-_f.attr("tabIndex","-1");
-});
-},_onContainerFocus:function(evt){
-if(evt.target!==this.domNode){
-return;
-}
-this.focusFirstChild();
-dojo.attr(this.domNode,"tabIndex","-1");
-},_onBlur:function(evt){
-if(this.tabIndex){
-dojo.attr(this.domNode,"tabIndex",this.tabIndex);
-}
-this.inherited(arguments);
-},_onContainerKeypress:function(evt){
-if(evt.ctrlKey||evt.altKey){
-return;
-}
-var _10=this._keyNavCodes[evt.charOrCode];
-if(_10){
-_10();
-dojo.stopEvent(evt);
-}
-},_onChildBlur:function(_11){
-},_getFirstFocusableChild:function(){
-return this._getNextFocusableChild(null,1);
-},_getNextFocusableChild:function(_12,dir){
-if(_12){
-_12=this._getSiblingOfChild(_12,dir);
-}
-var _13=this.getChildren();
-for(var i=0;i<_13.length;i++){
-if(!_12){
-_12=_13[(dir>0)?0:(_13.length-1)];
-}
-if(_12.isFocusable()){
-return _12;
-}
-_12=this._getSiblingOfChild(_12,dir);
-}
-return null;
-}});
-}
+
+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(/*dijit._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
+			var child = this._getFirstFocusableChild();
+			if(child){ // edge case: Menu could be empty or hidden
+				this.focusChild(child);
+			}
+		},
+
+		focusNext: function(){
+			// summary:
+			//		Focus the next widget
+			// tags:
+			//		protected
+			var child = this._getNextFocusableChild(this.focusedChild, 1);
+			this.focusChild(child);
+		},
+
+		focusPrev: function(){
+			// summary:
+			//		Focus the last focusable node in the previous widget
+			//		(ex: go to the ComboButton icon section rather than button section)
+			// tags:
+			//		protected
+			var child = this._getNextFocusableChild(this.focusedChild, -1);
+			this.focusChild(child, true);
+		},
+
+		focusChild: function(/*dijit._Widget*/ widget, /*Boolean*/ last){
+			// summary:
+			//		Focus widget.
+			// widget:
+			//		Reference to container's child widget
+			// last:
+			//		If true and if widget has multiple focusable nodes, focus the
+			//		last one instead of the first one
+			// tags:
+			//		protected
+			
+			if(this.focusedChild && widget !== this.focusedChild){
+				this._onChildBlur(this.focusedChild);
+			}
+			widget.focus(last ? "end" : "start");
+			this.focusedChild = widget;
+		},
+
+		_startupChild: function(/*dijit._Widget*/ widget){
+			// summary:
+			//		Setup for each child widget
+			// description:
+			//		Sets tabIndex=-1 on each child, so that the tab key will 
+			//		leave the container rather than visiting each child.
+			// tags:
+			//		private
+			
+			widget.set("tabIndex", "-1");
+			
+			this.connect(widget, "_onFocus", function(){
+				// Set valid tabIndex so tabbing away from widget goes to right place, see #10272
+				widget.set("tabIndex", this.tabIndex);
+			});
+			this.connect(widget, "_onBlur", function(){
+				widget.set("tabIndex", "-1");
+			});
+		},
+
+		_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 set the container's tabIndex to -1,
+			// (don't remove as that breaks Safari 4)
+			// so that tab or shift-tab will go to the fields after/before
+			// the container, rather than the container itself
+			dojo.attr(this.domNode, "tabIndex", "-1");
+		},
+
+		_onBlur: function(evt){
+			// When focus is moved away the container, and its 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);
+			}
+			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);
+			}
+		},
+
+		_onChildBlur: function(/*dijit._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);	// dijit._Widget
+		},
+
+		_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;	// dijit._Widget
+				}
+				child = this._getSiblingOfChild(child, dir);
+			}
+			// no focusable child found
+			return null;	// dijit._Widget
+		}
+	}
+);
diff --git a/dijit/_PaletteMixin.js b/dijit/_PaletteMixin.js
new file mode 100644
index 0000000..86cfe01
--- /dev/null
+++ b/dijit/_PaletteMixin.js
@@ -0,0 +1,313 @@
+dojo.provide("dijit._PaletteMixin");
+dojo.require("dijit._CssStateMixin");
+
+dojo.declare("dijit._PaletteMixin",
+	[dijit._CssStateMixin],
+	{
+	// summary:
+	//		A keyboard accessible palette, for picking a color/emoticon/etc.
+	// description:
+	//		A mixin for a grid showing various entities, so the user can pick a certain entity.
+
+	// defaultTimeout: Number
+	//		Number of milliseconds before a held key or button becomes typematic
+	defaultTimeout: 500,
+
+	// timeoutChangeRate: Number
+	//		Fraction of time used to change the typematic timer between events
+	//		1.0 means that each typematic event fires at defaultTimeout intervals
+	//		< 1.0 means that each typematic event fires at an increasing faster rate
+	timeoutChangeRate: 0.90,
+
+	// value: String
+	//		Currently selected color/emoticon/etc.
+	value: null,
+	
+	// _selectedCell: [private] Integer
+	//		Index of the currently selected cell. Initially, none selected
+	_selectedCell: -1,
+
+	// _currentFocus: [private] DomNode
+	//		The currently focused cell (if the palette itself has focus), or otherwise
+	//		the cell to be focused when the palette itself gets focus.
+	//		Different from value, which represents the selected (i.e. clicked) cell.
+/*=====
+	_currentFocus: null,
+=====*/
+
+	// _xDim: [protected] Integer
+	//		This is the number of cells horizontally across.
+/*=====
+	_xDim: null,
+=====*/
+
+	// _yDim: [protected] Integer
+	//		This is the number of cells vertically down.
+/*=====
+	_yDim: null,
+=====*/
+
+	// tabIndex: String
+	//		Widget tab index.
+	tabIndex: "0",
+
+	// cellClass: [protected] String
+	//		CSS class applied to each cell in the palette
+	cellClass: "dijitPaletteCell",
+
+	// dyeClass: [protected] String
+	//	 Name of javascript class for Object created for each cell of the palette.
+	//	 dyeClass should implements dijit.Dye interface
+	dyeClass: '',
+
+	_preparePalette: function(choices, titles) {
+		// summary:
+		//		Subclass must call _preparePalette() from postCreate(), passing in the tooltip
+		//		for each cell
+		// choices: String[][]
+		//		id's for each cell of the palette, used to create Dye JS object for each cell
+		// titles: String[]
+		//		Localized tooltip for each cell
+
+		this._cells = [];
+		var url = this._blankGif;
+		
+		var dyeClassObj = dojo.getObject(this.dyeClass);
+
+		for(var row=0; row < choices.length; row++){
+			var rowNode = dojo.create("tr", {tabIndex: "-1"}, this.gridNode);
+			for(var col=0; col < choices[row].length; col++){
+				var value = choices[row][col];
+				if(value){
+					var cellObject = new dyeClassObj(value);
+					
+					var cellNode = dojo.create("td", {
+						"class": this.cellClass,
+						tabIndex: "-1",
+						title: titles[value]
+					});
+
+					// prepare cell inner structure
+					cellObject.fillCell(cellNode, url);
+
+					this.connect(cellNode, "ondijitclick", "_onCellClick");
+					this._trackMouseState(cellNode, this.cellClass);
+
+					dojo.place(cellNode, rowNode);
+
+					cellNode.index = this._cells.length;
+
+					// save cell info into _cells
+					this._cells.push({node:cellNode, dye:cellObject});
+				}
+			}
+		}
+		this._xDim = choices[0].length;
+		this._yDim = choices.length;
+
+		// Now set all events
+		// The palette itself is navigated to with the tab key on the keyboard
+		// Keyboard navigation within the Palette is with the arrow keys
+		// Spacebar selects the cell.
+		// For the up key the index is changed by negative the x dimension.
+
+		var keyIncrementMap = {
+			UP_ARROW: -this._xDim,
+			// The down key the index is increase by the x dimension.
+			DOWN_ARROW: this._xDim,
+			// Right and left move the index by 1.
+			RIGHT_ARROW: this.isLeftToRight() ? 1 : -1,
+			LEFT_ARROW: this.isLeftToRight() ? -1 : 1
+		};
+		for(var key in keyIncrementMap){
+			this._connects.push(
+				dijit.typematic.addKeyListener(
+					this.domNode,
+					{charOrCode:dojo.keys[key], ctrlKey:false, altKey:false, shiftKey:false},
+					this,
+					function(){
+						var increment = keyIncrementMap[key];
+						return function(count){ this._navigateByKey(increment, count); };
+					}(),
+					this.timeoutChangeRate,
+					this.defaultTimeout
+				)
+			);
+		}
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+
+		// Set initial navigable node.
+		this._setCurrent(this._cells[0].node);
+	},
+
+	focus: function(){
+		// summary:
+		//		Focus this widget.  Puts focus on the most recently focused cell.
+
+		// The cell already has tabIndex set, just need to set CSS and focus it
+		dijit.focus(this._currentFocus);
+	},
+
+	_onCellClick: function(/*Event*/ evt){
+		// summary:
+		//		Handler for click, enter key & space key. Selects the cell.
+		// evt:
+		//		The event.
+		// tags:
+		//		private
+
+		var target = evt.currentTarget,	
+			value = this._getDye(target).getValue();
+
+		// First focus the clicked cell, and then send onChange() notification.
+		// onChange() (via _setValueAttr) must be after the focus call, because
+		// it may trigger a refocus to somewhere else (like the Editor content area), and that
+		// second focus should win.
+		// Use setTimeout because IE doesn't like changing focus inside of an event handler.
+		this._setCurrent(target);
+		setTimeout(dojo.hitch(this, function(){
+			dijit.focus(target);		
+			this._setValueAttr(value, true);		
+		}));
+
+		// workaround bug where hover class is not removed on popup because the popup is
+		// closed and then there's no onblur event on the cell
+		dojo.removeClass(target, "dijitPaletteCellHover");
+
+		dojo.stopEvent(evt);
+	},
+
+	_setCurrent: function(/*DomNode*/ node){
+		// summary:
+		//		Sets which node is the focused cell.
+		// description:
+   		//		At any point in time there's exactly one
+		//		cell with tabIndex != -1.   If focus is inside the palette then
+		// 		focus is on that cell.
+		//
+		//		After calling this method, arrow key handlers and mouse click handlers
+		//		should focus the cell in a setTimeout().
+		// tags:
+		//		protected
+		if("_currentFocus" in this){
+			// Remove tabIndex on old cell
+			dojo.attr(this._currentFocus, "tabIndex", "-1");
+		}
+
+		// Set tabIndex of new cell
+		this._currentFocus = node;
+		if(node){
+			dojo.attr(node, "tabIndex", this.tabIndex);
+		}
+	},
+
+	_setValueAttr: function(value, priorityChange){
+		// summary:
+		// 		This selects a cell. It triggers the onChange event.
+		// value: String value of the cell to select
+		// tags:
+		//		protected
+		// priorityChange:
+		//		Optional parameter used to tell the select whether or not to fire
+		//		onChange event.
+		
+		// clear old value and selected cell
+		this.value = null;
+		if(this._selectedCell >= 0){
+			dojo.removeClass(this._cells[this._selectedCell].node, "dijitPaletteCellSelected");
+		}
+		this._selectedCell = -1;
+
+		// search for cell matching specified value
+		if(value){
+			for(var i = 0; i < this._cells.length; i++){
+				if(value == this._cells[i].dye.getValue()){
+					this._selectedCell = i;
+					this.value = value;
+
+					dojo.addClass(this._cells[i].node, "dijitPaletteCellSelected");
+
+					if(priorityChange || priorityChange === undefined){
+						this.onChange(value);
+					}
+
+					break;
+				}
+			}
+		}
+	},
+
+	onChange: function(value){
+		// summary:
+		//		Callback when a cell is selected.
+		// value: String
+		//		Value corresponding to cell.
+	},
+
+	_navigateByKey: function(increment, typeCount){
+		// summary:
+		// 	  	This is the callback for typematic.
+		// 		It changes the focus and the highlighed cell.
+		// increment:
+		// 		How much the key is navigated.
+		// typeCount:
+		//		How many times typematic has fired.
+		// tags:
+		//		private
+
+		// typecount == -1 means the key is released.
+		if(typeCount == -1){ return; }
+
+		var newFocusIndex = this._currentFocus.index + increment;
+		if(newFocusIndex < this._cells.length && newFocusIndex > -1){
+			var focusNode = this._cells[newFocusIndex].node;
+			this._setCurrent(focusNode);
+
+			// Actually focus the node, for the benefit of screen readers.
+			// Use setTimeout because IE doesn't like changing focus inside of an event handler
+			setTimeout(dojo.hitch(dijit, "focus", focusNode), 0);
+		}
+	},
+
+	_getDye: function(/*DomNode*/ cell){
+		// summary:
+		//		Get JS object for given cell DOMNode
+
+		return this._cells[cell.index].dye;
+	}
+});
+
+/*=====
+dojo.declare("dijit.Dye",
+	null,
+	{
+		// summary:
+		//		Interface for the JS Object associated with a palette cell (i.e. DOMNode)
+
+		constructor: function(alias){
+			// summary:
+			//		Initialize according to value or alias like "white"
+			// alias: String
+		},
+
+		getValue: function(){
+			// summary:
+			//		Return "value" of cell; meaning of "value" varies by subclass.
+			// description:
+			//		For example color hex value, emoticon ascii value etc, entity hex value.
+		},
+
+		fillCell: function(cell, blankGif){
+			// summary:
+			//		Add cell DOMNode inner structure
+			//	cell: DomNode
+			//		The surrounding cell
+			//	blankGif: String
+			//		URL for blank cell image
+		}
+	}
+);
+=====*/
\ No newline at end of file
diff --git a/dijit/_Templated.js b/dijit/_Templated.js
index 4a19e14..09d6b6d 100644
--- a/dijit/_Templated.js
+++ b/dijit/_Templated.js
@@ -1,184 +1,335 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._Templated"]){
-dojo._hasResource["dijit._Templated"]=true;
 dojo.provide("dijit._Templated");
+
 dojo.require("dijit._Widget");
 dojo.require("dojo.string");
 dojo.require("dojo.parser");
 dojo.require("dojo.cache");
-dojo.declare("dijit._Templated",null,{templateString:null,templatePath:null,widgetsInTemplate:false,_skipNodeCache:false,_earlyTemplatedStartup:false,constructor:function(){
-this._attachPoints=[];
-},_stringRepl:function(_1){
-var _2=this.declaredClass,_3=this;
-return dojo.string.substitute(_1,this,function(_4,_5){
-if(_5.charAt(0)=="!"){
-_4=dojo.getObject(_5.substr(1),false,_3);
-}
-if(typeof _4=="undefined"){
-throw new Error(_2+" template:"+_5);
-}
-if(_4==null){
-return "";
-}
-return _5.charAt(0)=="!"?_4:_4.toString().replace(/"/g,""");
-},this);
-},buildRendering:function(){
-var _6=dijit._Templated.getCachedTemplate(this.templatePath,this.templateString,this._skipNodeCache);
-var _7;
-if(dojo.isString(_6)){
-_7=dojo._toDom(this._stringRepl(_6));
-if(_7.nodeType!=1){
-throw new Error("Invalid template: "+_6);
-}
-}else{
-_7=_6.cloneNode(true);
-}
-this.domNode=_7;
-this._attachTemplateNodes(_7);
-if(this.widgetsInTemplate){
-var _8=dojo.parser,_9,_a;
-if(_8._query!="[dojoType]"){
-_9=_8._query;
-_a=_8._attrName;
-_8._query="[dojoType]";
-_8._attrName="dojoType";
-}
-var cw=(this._startupWidgets=dojo.parser.parse(_7,{noStart:!this._earlyTemplatedStartup}));
-if(_9){
-_8._query=_9;
-_8._attrName=_a;
-}
-this._supportingWidgets=dijit.findWidgets(_7);
-this._attachTemplateNodes(cw,function(n,p){
-return n[p];
-});
-}
-this._fillContent(this.srcNodeRef);
-},_fillContent:function(_b){
-var _c=this.containerNode;
-if(_b&&_c){
-while(_b.hasChildNodes()){
-_c.appendChild(_b.firstChild);
-}
-}
-},_attachTemplateNodes:function(_d,_e){
-_e=_e||function(n,p){
-return n.getAttribute(p);
-};
-var _f=dojo.isArray(_d)?_d:(_d.all||_d.getElementsByTagName("*"));
-var x=dojo.isArray(_d)?0:-1;
-for(;x<_f.length;x++){
-var _10=(x==-1)?_d:_f[x];
-if(this.widgetsInTemplate&&_e(_10,"dojoType")){
-continue;
-}
-var _11=_e(_10,"dojoAttachPoint");
-if(_11){
-var _12,_13=_11.split(/\s*,\s*/);
-while((_12=_13.shift())){
-if(dojo.isArray(this[_12])){
-this[_12].push(_10);
-}else{
-this[_12]=_10;
-}
-this._attachPoints.push(_12);
-}
-}
-var _14=_e(_10,"dojoAttachEvent");
-if(_14){
-var _15,_16=_14.split(/\s*,\s*/);
-var _17=dojo.trim;
-while((_15=_16.shift())){
-if(_15){
-var _18=null;
-if(_15.indexOf(":")!=-1){
-var _19=_15.split(":");
-_15=_17(_19[0]);
-_18=_17(_19[1]);
-}else{
-_15=_17(_15);
-}
-if(!_18){
-_18=_15;
-}
-this.connect(_10,_15,_18);
-}
-}
-}
-var _1a=_e(_10,"waiRole");
-if(_1a){
-dijit.setWaiRole(_10,_1a);
-}
-var _1b=_e(_10,"waiState");
-if(_1b){
-dojo.forEach(_1b.split(/\s*,\s*/),function(_1c){
-if(_1c.indexOf("-")!=-1){
-var _1d=_1c.split("-");
-dijit.setWaiState(_10,_1d[0],_1d[1]);
-}
-});
-}
-}
-},startup:function(){
-dojo.forEach(this._startupWidgets,function(w){
-if(w&&!w._started&&w.startup){
-w.startup();
-}
-});
-this.inherited(arguments);
-},destroyRendering:function(){
-dojo.forEach(this._attachPoints,function(_1e){
-delete this[_1e];
-},this);
-this._attachPoints=[];
-this.inherited(arguments);
-}});
-dijit._Templated._templateCache={};
-dijit._Templated.getCachedTemplate=function(_1f,_20,_21){
-var _22=dijit._Templated._templateCache;
-var key=_20||_1f;
-var _23=_22[key];
-if(_23){
-try{
-if(!_23.ownerDocument||_23.ownerDocument==dojo.doc){
-return _23;
-}
-}
-catch(e){
-}
-dojo.destroy(_23);
-}
-if(!_20){
-_20=dojo.cache(_1f,{sanitize:true});
-}
-_20=dojo.string.trim(_20);
-if(_21||_20.match(/\$\{([^\}]+)\}/g)){
-return (_22[key]=_20);
-}else{
-var _24=dojo._toDom(_20);
-if(_24.nodeType!=1){
-throw new Error("Invalid template: "+_20);
-}
-return (_22[key]=_24);
-}
+
+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.
+		//
+		//		Use in conjunction with dojo.cache() to load from a file.
+		templateString: null,
+
+		// templatePath: [protected deprecated] String
+		//		Path to template (HTML file) for this widget relative to dojo.baseUrl.
+		//		Deprecated: use templateString with dojo.cache() instead.
+		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,
+
+		// _earlyTemplatedStartup: Boolean
+		//		A fallback to preserve the 1.0 - 1.3 behavior of children in
+		//		templates having their startup called before the parent widget
+		//		fires postCreate. Defaults to 'false', causing child widgets to
+		//		have their .startup() called immediately before a parent widget
+		//		.startup(), but always after the parent .postCreate(). Set to
+		//		'true' to re-enable to previous, arguably broken, behavior.
+		_earlyTemplatedStartup: false,
+
+		// _attachPoints: [private] String[]
+		//		List of widget attribute names associated with dojoAttachPoint=... in the
+		//		template, ex: ["containerNode", "labelNode"]
+/*=====
+ 		_attachPoints: [],
+ =====*/
+
+		constructor: function(){
+			this._attachPoints = [];
+		},
+
+		_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,"""); //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));
+				if(node.nodeType != 1){
+					// Flag common problems such as templates with multiple top level nodes (nodeType == 11)
+					throw new Error("Invalid template: " + 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){
+				// Make sure dojoType is used for parsing widgets in template.
+				// The dojo.parser.query could be changed from multiversion support.
+				var parser = dojo.parser, qry, attr;
+				if(parser._query != "[dojoType]"){
+					qry = parser._query;
+					attr = parser._attrName;
+					parser._query = "[dojoType]";
+					parser._attrName = "dojoType";
+				}
+
+				// Store widgets that we need to start at a later point in time
+				var cw = (this._startupWidgets = dojo.parser.parse(node, {
+					noStart: !this._earlyTemplatedStartup,
+					inherited: {dir: this.dir, lang: this.lang}
+				}));
+
+				// Restore the query.
+				if(qry){
+					parser._query = qry;
+					parser._attrName = attr;
+				}
+
+				this._supportingWidgets = dijit.findWidgets(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;
+						}
+						this._attachPoints.push(point);
+					}
+				}
+
+				// 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]);
+						}
+					});
+				}
+			}
+		},
+
+		startup: function(){
+			dojo.forEach(this._startupWidgets, function(w){
+				if(w && !w._started && w.startup){
+					w.startup();
+				}
+			});
+			this.inherited(arguments);
+		},
+
+		destroyRendering: function(){
+			// Delete all attach points to prevent IE6 memory leaks.
+			dojo.forEach(this._attachPoints, function(point){
+				delete this[point];
+			}, this);
+			this._attachPoints = [];
+
+			this.inherited(arguments);
+		}
+	}
+);
+
+// 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||dojo.uri.Uri
+	//		The URL to get the template from.
+	// 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){
+		try{
+			// if the cached value is an innerHTML string (no ownerDocument) or a DOM tree created within the current document, then use the current cached value
+			if(!cached.ownerDocument || cached.ownerDocument == dojo.doc){
+				// string or node of the same document
+				return cached;
+			}
+		}catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded
+		dojo.destroy(cached);
+	}
+
+	// If necessary, load template string from template path
+	if(!templateString){
+		templateString = dojo.cache(templatePath, {sanitize: true});
+	}
+	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
+		var node = dojo._toDom(templateString);
+		if(node.nodeType != 1){
+			throw new Error("Invalid template: " + templateString);
+		}
+		return (tmplts[key] = node); //Node
+	}
 };
+
 if(dojo.isIE){
-dojo.addOnWindowUnload(function(){
-var _25=dijit._Templated._templateCache;
-for(var key in _25){
-var _26=_25[key];
-if(typeof _26=="object"){
-dojo.destroy(_26);
-}
-delete _25[key];
+	dojo.addOnWindowUnload(function(){
+		var cache = dijit._Templated._templateCache;
+		for(var key in cache){
+			var value = cache[key];
+			if(typeof value == "object"){ // value is either a string or a DOM node template
+				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:""
 });
-}
-dojo.extend(dijit._Widget,{dojoAttachEvent:"",dojoAttachPoint:"",waiRole:"",waiState:""});
-}
diff --git a/dijit/_TimePicker.js b/dijit/_TimePicker.js
index 31a3340..60d0392 100644
--- a/dijit/_TimePicker.js
+++ b/dijit/_TimePicker.js
@@ -1,265 +1,493 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._TimePicker"]){
-dojo._hasResource["dijit._TimePicker"]=true;
 dojo.provide("dijit._TimePicker");
+
 dojo.require("dijit.form._FormWidget");
 dojo.require("dojo.date.locale");
-dojo.declare("dijit._TimePicker",[dijit._Widget,dijit._Templated],{templateString:dojo.cache("dijit","templates/TimePicker.html","<div id=\"widget_${id}\" class=\"dijitMenu ${baseClass}\"\n    ><div dojoAttachPoint=\"upArrow\" class=\"dijitButtonNode dijitUpArrowButton\" dojoAttachEvent=\"onmouseenter:_buttonMouse,onmouseleave:_buttonMouse\"\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonInner\" wairole=\"presentation\" role=\"presentation\"> </div\n\t\t><div class=\"diji [...]
-dojo.deprecated("dijit._TimePicker:setValue() is deprecated.  Use attr('value') instead.","","2.0");
-this.attr("value",_1);
-},_setValueAttr:function(_2){
-this.value=_2;
-this._showText();
-},onOpen:function(_3){
-if(this._beenOpened&&this.domNode.parentNode){
-var p=dijit.byId(this.domNode.parentNode.dijitPopupParent);
-if(p){
-var _4=p.attr("displayedValue");
-if(_4&&!p.parse(_4,p.constraints)){
-this._filterString=_4;
-}else{
-this._filterString="";
-}
-this._showText();
-}
-}
-this._beenOpened=true;
-},isDisabledDate:function(_5,_6){
-return false;
-},_getFilteredNodes:function(_7,_8,_9){
-var _a=[],n,i=_7,_b=this._maxIncrement+Math.abs(i),_c=_9?-1:1,_d=_9?1:0,_e=_9?0:1;
-do{
-i=i-_d;
-n=this._createOption(i);
-if(n){
-_a.push(n);
-}
-i=i+_e;
-}while(_a.length<_8&&(i*_c)<_b);
-if(_9){
-_a.reverse();
-}
-return _a;
-},_showText:function(){
-this.timeMenu.innerHTML="";
-var _f=dojo.date.stamp.fromISOString;
-this._clickableIncrementDate=_f(this.clickableIncrement);
-this._visibleIncrementDate=_f(this.visibleIncrement);
-this._visibleRangeDate=_f(this.visibleRange);
-var _10=function(_11){
-return _11.getHours()*60*60+_11.getMinutes()*60+_11.getSeconds();
-};
-var _12=_10(this._clickableIncrementDate);
-var _13=_10(this._visibleIncrementDate);
-var _14=_10(this._visibleRangeDate);
-var _15=this.value.getTime();
-this._refDate=new Date(_15-_15%(_13*1000));
-this._refDate.setFullYear(1970,0,1);
-this._clickableIncrement=1;
-this._totalIncrements=_14/_12;
-this._visibleIncrement=_13/_12;
-this._maxIncrement=(60*60*24)/_12;
-var _16=this._getFilteredNodes(0,this._totalIncrements>>1,true);
-var _17=this._getFilteredNodes(0,this._totalIncrements>>1,false);
-if(_16.length<this._totalIncrements>>1){
-_16=_16.slice(_16.length/2);
-_17=_17.slice(0,_17.length/2);
-}
-dojo.forEach(_16.concat(_17),function(n){
-this.timeMenu.appendChild(n);
-},this);
-},postCreate:function(){
-if(this.constraints===dijit._TimePicker.prototype.constraints){
-this.constraints={};
-}
-dojo.mixin(this,this.constraints);
-if(!this.constraints.locale){
-this.constraints.locale=this.lang;
-}
-this.connect(this.timeMenu,dojo.isIE?"onmousewheel":"DOMMouseScroll","_mouseWheeled");
-var _18=this;
-var _19=function(){
-_18._connects.push(dijit.typematic.addMouseListener.apply(null,arguments));
-};
-_19(this.upArrow,this,this._onArrowUp,1,50);
-_19(this.downArrow,this,this._onArrowDown,1,50);
-var _1a=function(cb){
-return function(cnt){
-if(cnt>0){
-cb.call(this,arguments);
-}
-};
-};
-var _1b=function(_1c,cb){
-return function(e){
-dojo.stopEvent(e);
-dijit.typematic.trigger(e,this,_1c,_1a(cb),_1c,1,50);
-};
-};
-this.connect(this.upArrow,"onmouseover",_1b(this.upArrow,this._onArrowUp));
-this.connect(this.downArrow,"onmouseover",_1b(this.downArrow,this._onArrowDown));
-this.inherited(arguments);
-},_buttonMouse:function(e){
-dojo.toggleClass(e.currentTarget,"dijitButtonNodeHover",e.type=="mouseover");
-},_createOption:function(_1d){
-var _1e=new Date(this._refDate);
-var _1f=this._clickableIncrementDate;
-_1e.setHours(_1e.getHours()+_1f.getHours()*_1d,_1e.getMinutes()+_1f.getMinutes()*_1d,_1e.getSeconds()+_1f.getSeconds()*_1d);
-if(this.constraints.selector=="time"){
-_1e.setFullYear(1970,0,1);
-}
-var _20=dojo.date.locale.format(_1e,this.constraints);
-if(this._filterString&&_20.toLowerCase().indexOf(this._filterString)!==0){
-return null;
-}
-var div=dojo.create("div",{"class":this.baseClass+"Item"});
-div.date=_1e;
-div.index=_1d;
-dojo.create("div",{"class":this.baseClass+"ItemInner",innerHTML:_20},div);
-if(_1d%this._visibleIncrement<1&&_1d%this._visibleIncrement>-1){
-dojo.addClass(div,this.baseClass+"Marker");
-}else{
-if(!(_1d%this._clickableIncrement)){
-dojo.addClass(div,this.baseClass+"Tick");
-}
-}
-if(this.isDisabledDate(_1e)){
-dojo.addClass(div,this.baseClass+"ItemDisabled");
-}
-if(!dojo.date.compare(this.value,_1e,this.constraints.selector)){
-div.selected=true;
-dojo.addClass(div,this.baseClass+"ItemSelected");
-if(dojo.hasClass(div,this.baseClass+"Marker")){
-dojo.addClass(div,this.baseClass+"MarkerSelected");
-}else{
-dojo.addClass(div,this.baseClass+"TickSelected");
-}
-}
-return div;
-},_onOptionSelected:function(tgt){
-var _21=tgt.target.date||tgt.target.parentNode.date;
-if(!_21||this.isDisabledDate(_21)){
-return;
-}
-this._highlighted_option=null;
-this.attr("value",_21);
-this.onValueSelected(_21);
-},onValueSelected:function(_22){
-},_highlightOption:function(_23,_24){
-if(!_23){
-return;
-}
-if(_24){
-if(this._highlighted_option){
-this._highlightOption(this._highlighted_option,false);
-}
-this._highlighted_option=_23;
-}else{
-if(this._highlighted_option!==_23){
-return;
-}else{
-this._highlighted_option=null;
-}
-}
-dojo.toggleClass(_23,this.baseClass+"ItemHover",_24);
-if(dojo.hasClass(_23,this.baseClass+"Marker")){
-dojo.toggleClass(_23,this.baseClass+"MarkerHover",_24);
-}else{
-dojo.toggleClass(_23,this.baseClass+"TickHover",_24);
-}
-},onmouseover:function(e){
-this._keyboardSelected=null;
-var tgr=(e.target.parentNode===this.timeMenu)?e.target:e.target.parentNode;
-if(!dojo.hasClass(tgr,this.baseClass+"Item")){
-return;
-}
-this._highlightOption(tgr,true);
-},onmouseout:function(e){
-this._keyboardSelected=null;
-var tgr=(e.target.parentNode===this.timeMenu)?e.target:e.target.parentNode;
-this._highlightOption(tgr,false);
-},_mouseWheeled:function(e){
-this._keyboardSelected=null;
-dojo.stopEvent(e);
-var _25=(dojo.isIE?e.wheelDelta:-e.detail);
-this[(_25>0?"_onArrowUp":"_onArrowDown")]();
-},_onArrowUp:function(_26){
-if(typeof _26=="number"&&_26==-1){
-return;
-}
-if(!this.timeMenu.childNodes.length){
-return;
-}
-var _27=this.timeMenu.childNodes[0].index;
-var _28=this._getFilteredNodes(_27,1,true);
-if(_28.length){
-this.timeMenu.removeChild(this.timeMenu.childNodes[this.timeMenu.childNodes.length-1]);
-this.timeMenu.insertBefore(_28[0],this.timeMenu.childNodes[0]);
-}
-},_onArrowDown:function(_29){
-if(typeof _29=="number"&&_29==-1){
-return;
-}
-if(!this.timeMenu.childNodes.length){
-return;
-}
-var _2a=this.timeMenu.childNodes[this.timeMenu.childNodes.length-1].index+1;
-var _2b=this._getFilteredNodes(_2a,1,false);
-if(_2b.length){
-this.timeMenu.removeChild(this.timeMenu.childNodes[0]);
-this.timeMenu.appendChild(_2b[0]);
-}
-},handleKey:function(e){
-var dk=dojo.keys;
-if(e.keyChar||e.charOrCode===dk.BACKSPACE||e.charOrCode==dk.DELETE){
-setTimeout(dojo.hitch(this,function(){
-this._filterString=e.target.value.toLowerCase();
-this._showText();
-}),1);
-}else{
-if(e.charOrCode==dk.DOWN_ARROW||e.charOrCode==dk.UP_ARROW){
-dojo.stopEvent(e);
-if(this._highlighted_option&&!this._highlighted_option.parentNode){
-this._highlighted_option=null;
-}
-var _2c=this.timeMenu,tgt=this._highlighted_option||dojo.query("."+this.baseClass+"ItemSelected",_2c)[0];
-if(!tgt){
-tgt=_2c.childNodes[0];
-}else{
-if(_2c.childNodes.length){
-if(e.charOrCode==dk.DOWN_ARROW&&!tgt.nextSibling){
-this._onArrowDown();
-}else{
-if(e.charOrCode==dk.UP_ARROW&&!tgt.previousSibling){
-this._onArrowUp();
-}
-}
-if(e.charOrCode==dk.DOWN_ARROW){
-tgt=tgt.nextSibling;
-}else{
-tgt=tgt.previousSibling;
-}
-}
-}
-this._highlightOption(tgt,true);
-this._keyboardSelected=tgt;
-}else{
-if(this._highlighted_option&&(e.charOrCode==dk.ENTER||e.charOrCode===dk.TAB)){
-if(!this._keyboardSelected&&e.charOrCode===dk.TAB){
-return;
-}
-if(e.charOrCode==dk.ENTER){
-dojo.stopEvent(e);
-}
-this._onOptionSelected({target:this._highlighted_option});
-}
-}
-}
-}});
-}
+
+/*=====
+dojo.declare(
+	"dijit._TimePicker.__Constraints",
+	dojo.date.locale.__FormatOptions,
+	{
+		// clickableIncrement: String
+		//		See `dijit._TimePicker.clickableIncrement`
+		clickableIncrement: "T00:15:00",
+
+		// visibleIncrement: String
+		//		See `dijit._TimePicker.visibleIncrement`
+		visibleIncrement: "T01:00:00",
+
+		// visibleRange: String
+		//		See `dijit._TimePicker.visibleRange`
+		visibleRange: "T05:00:00"
+	}
+);
+=====*/
+
+dojo.declare("dijit._TimePicker",
+	[dijit._Widget, dijit._Templated],
+	{
+		// summary:
+		//		A graphical time picker.
+		//		This widget is used internally by other widgets and is not available
+		//		as a standalone widget due to lack of accessibility support.
+
+		templateString: dojo.cache("dijit", "templates/TimePicker.html"),
+
+		// baseClass: [protected] String
+		//		The root className to use for the various states of this widget
+		baseClass: "dijitTimePicker",
+
+		// clickableIncrement: String
+		//		ISO-8601 string representing the amount by which
+		//		every clickable element in the time picker increases.
+		//		Set in local time, without a time zone.
+		//		Example: `T00:15:00` creates 15 minute increments
+		//		Must divide dijit._TimePicker.visibleIncrement evenly
+		clickableIncrement: "T00:15:00",
+
+		// visibleIncrement: String
+		//		ISO-8601 string representing the amount by which
+		//		every element with a visible time in the time picker increases.
+		//		Set in local time, without a time zone.
+		//		Example: `T01:00:00` creates text in every 1 hour increment
+		visibleIncrement: "T01:00:00",
+
+		// visibleRange: String
+		//		ISO-8601 string representing the range of this TimePicker.
+		//		The TimePicker will only display times in this range.
+		//		Example: `T05:00:00` displays 5 hours of options
+		visibleRange: "T05:00:00",
+
+		// value: String
+		//		Date to display.
+		//		Defaults to current time and date.
+		//		Can be a Date object or an ISO-8601 string.
+		//		If you specify the GMT time zone (`-01:00`),
+		//		the time will be converted to the local time in the local time zone.
+		//		Otherwise, the time is considered to be in the local time zone.
+		//		If you specify the date and isDate is true, the date is used.
+		//		Example: if your local time zone is `GMT -05:00`,
+		//		`T10:00:00` becomes `T10:00:00-05:00` (considered to be local time),
+		//		`T10:00:00-01:00` becomes `T06:00:00-05:00` (4 hour difference),
+		//		`T10:00:00Z` becomes `T05:00:00-05:00` (5 hour difference between Zulu and local time)
+		//		`yyyy-mm-ddThh:mm:ss` is the format to set the date and time
+		//		Example: `2007-06-01T09:00:00`
+		value: new Date(),
+
+		_visibleIncrement:2,
+		_clickableIncrement:1,
+		_totalIncrements:10,
+
+		// constraints: dijit._TimePicker.__Constraints
+		//		Specifies valid range of times (start time, end time)
+		constraints:{},
+
+/*=====
+		serialize: function(val, options){
+			// summary:
+			//		User overridable function used to convert the attr('value') result to a String
+			// val: Date
+			//		The current value
+			// options: Object?
+			// tags:
+			//		protected
+		},
+=====*/
+		serialize: dojo.date.stamp.toISOString,
+
+		// _filterString: string
+		//		The string to filter by
+		_filterString: "",
+
+		setValue: function(/*Date*/ value){
+			// summary:
+			//		Deprecated.  Used attr('value') instead.
+			// tags:
+			//		deprecated
+			dojo.deprecated("dijit._TimePicker:setValue() is deprecated.  Use set('value', ...) instead.", "", "2.0");
+			this.set('value', value);
+		},
+		_setValueAttr: function(/*Date*/ date){
+			// summary:
+			//		Hook so attr('value', ...) works.
+			// description:
+			//		Set the value of the TimePicker.
+			//		Redraws the TimePicker around the new date.
+			// tags:
+			//		protected
+			this.value = date;
+			this._showText();
+		},
+
+		onOpen: function(best){
+			// summary:
+			//		This is called by the popup manager when a TimeTextBox is displayed on the screen
+			// best:
+			//		Whether it is being displayed above or below the `dijit.form.TimeTextBox`
+			// tags:
+			//		protected
+			if(this._beenOpened && this.domNode.parentNode){
+				// We've been opened before - so set our filter to to the
+				// currently-displayed value (or empty string if it's already
+				// valid)
+				var p = dijit.byId(this.domNode.parentNode.dijitPopupParent);
+				if(p){
+					var val = p.get('displayedValue');
+					if(val && !p.parse(val, p.constraints)){
+						this._filterString = val;
+					}else{
+						this._filterString = "";
+					}
+					this._showText();
+				}
+			}
+			this._beenOpened = true;
+		},
+
+		isDisabledDate: function(/*Date*/ dateObject, /*String?*/ locale){
+			// summary:
+			//		May be overridden to disable certain dates in the TimePicker e.g. `isDisabledDate=dojo.date.locale.isWeekend`
+			// type:
+			//		extension
+			return false; // Boolean
+		},
+
+		_getFilteredNodes: function(/*number*/ start, /*number*/ maxNum, /*Boolean*/ before){
+			// summary:
+			//		Returns an array of nodes with the filter applied.  At most maxNum nodes
+			//		will be returned - but fewer may be returned as well.  If the
+			//		before parameter is set to true, then it will return the elements
+			//		before the given index
+			// tags:
+			//		private
+			var nodes = [], n, i = start, max = this._maxIncrement + Math.abs(i),
+				chk = before?-1:1, dec = before?1:0, inc = before?0:1;
+			do{
+				i = i - dec;
+				n = this._createOption(i);
+				if(n){nodes.push(n);}
+				i = i + inc;
+			}while(nodes.length < maxNum && (i*chk) < max);
+			if(before){ nodes.reverse(); }
+			return nodes;
+		},
+
+		_showText: function(){
+			// summary:
+			//		Displays the relevant choices in the drop down list
+			// tags:
+			//		private
+			this.timeMenu.innerHTML = "";
+			var fromIso = dojo.date.stamp.fromISOString;
+			this._clickableIncrementDate=fromIso(this.clickableIncrement);
+			this._visibleIncrementDate=fromIso(this.visibleIncrement);
+			this._visibleRangeDate=fromIso(this.visibleRange);
+			// get the value of the increments and the range in seconds (since 00:00:00) to find out how many divs to create
+			var sinceMidnight = function(/*Date*/ date){
+				return date.getHours() * 60 * 60 + date.getMinutes() * 60 + date.getSeconds();
+			};
+
+			var clickableIncrementSeconds = sinceMidnight(this._clickableIncrementDate);
+			var visibleIncrementSeconds = sinceMidnight(this._visibleIncrementDate);
+			var visibleRangeSeconds = sinceMidnight(this._visibleRangeDate);
+
+			// round reference date to previous visible increment
+			var time = this.value.getTime();
+			this._refDate = new Date(time - time % (visibleIncrementSeconds*1000));
+			this._refDate.setFullYear(1970,0,1); // match parse defaults
+
+			// assume clickable increment is the smallest unit
+			this._clickableIncrement = 1;
+			// divide the visible range by the clickable increment to get the number of divs to create
+			// example: 10:00:00/00:15:00 -> display 40 divs
+			this._totalIncrements = visibleRangeSeconds / clickableIncrementSeconds;
+			// divide the visible increments by the clickable increments to get how often to display the time inline
+			// example: 01:00:00/00:15:00 -> display the time every 4 divs
+			this._visibleIncrement = visibleIncrementSeconds / clickableIncrementSeconds;
+			// divide the number of seconds in a day by the clickable increment in seconds to get the
+			// absolute max number of increments.
+			this._maxIncrement = (60 * 60 * 24) / clickableIncrementSeconds;
+
+			// find the nodes we should display based on our filter
+			var before = this._getFilteredNodes(0, this._totalIncrements >> 1, true);
+			var after = this._getFilteredNodes(0, this._totalIncrements >> 1, false);
+			if(before.length < this._totalIncrements >> 1){
+				before = before.slice(before.length / 2);
+				after = after.slice(0, after.length / 2);
+			}
+			dojo.forEach(before.concat(after), function(n){this.timeMenu.appendChild(n);}, this);
+
+			// TODO:
+			// I commented this out because it
+			// causes problems for a TimeTextBox in a Dialog, or as the editor of an InlineEditBox,
+			// because the timeMenu node isn't visible yet. -- Bill (Bug #????)
+			// dijit.focus(this.timeMenu);
+		},
+
+		postCreate: function(){
+			// instantiate constraints
+			if(this.constraints === dijit._TimePicker.prototype.constraints){
+				this.constraints={};
+			}
+
+			// brings in visibleRange, increments, etc.
+			dojo.mixin(this, this.constraints);
+
+			// dojo.date.locale needs the lang in the constraints as locale
+			if(!this.constraints.locale){
+				this.constraints.locale=this.lang;
+			}
+
+			// assign typematic mouse listeners to the arrow buttons
+			this.connect(this.timeMenu, dojo.isIE ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");
+			var _this = this;
+			var typematic = function(){
+				_this._connects.push(
+					dijit.typematic.addMouseListener.apply(null, arguments)
+				);
+			};
+			typematic(this.upArrow,this,this._onArrowUp, 1.0, 50);
+			typematic(this.downArrow,this,this._onArrowDown, 1.0, 50);
+
+			// Connect some callback functions to the hover event of the arrows
+			var triggerFx = function(cb){
+				return function(cnt){
+					// don't run on the first firing
+					if(cnt > 0){cb.call(this, arguments);}
+				};
+			};
+			var hoverFx = function(node, cb){
+				return function(e){
+					dojo.stopEvent(e);
+					dijit.typematic.trigger(e, this, node, triggerFx(cb), node, 1.0, 50);
+				};
+			};
+			this.connect(this.upArrow, "onmouseover", hoverFx(this.upArrow, this._onArrowUp));
+			this.connect(this.downArrow, "onmouseover", hoverFx(this.downArrow, this._onArrowDown));
+
+			this.inherited(arguments);
+		},
+
+		_buttonMouse: function(/*Event*/ e){
+			// summary:
+			//		Handler for hover (and unhover) on up/down arrows
+			// tags:
+			//		private
+
+			// in non-IE browser the "mouseenter" event will become "mouseover", 
+			// but in IE it's still "mouseenter"
+			dojo.toggleClass(e.currentTarget, e.currentTarget == this.upArrow ? "dijitUpArrowHover" : "dijitDownArrowHover", 
+				e.type == "mouseenter" || e.type == "mouseover");
+		},
+
+		_createOption: function(/*Number*/ index){
+			// summary:
+			//		Creates a clickable time option
+			// tags:
+			//		private
+			var date = new Date(this._refDate);
+			var incrementDate = this._clickableIncrementDate;
+			date.setHours(date.getHours() + incrementDate.getHours() * index,
+				date.getMinutes() + incrementDate.getMinutes() * index,
+				date.getSeconds() + incrementDate.getSeconds() * index);
+			if(this.constraints.selector == "time"){
+				date.setFullYear(1970,0,1); // make sure each time is for the same date
+			}
+			var dateString = dojo.date.locale.format(date, this.constraints);
+			if(this._filterString && dateString.toLowerCase().indexOf(this._filterString) !== 0){
+				// Doesn't match the filter - return null
+				return null;
+			}
+
+			var div = dojo.create("div", {"class": this.baseClass+"Item"});
+			div.date = date;
+			div.index = index;
+			dojo.create('div',{
+				"class": this.baseClass + "ItemInner",
+				innerHTML: dateString
+			}, div);
+
+			if(index%this._visibleIncrement<1 && index%this._visibleIncrement>-1){
+				dojo.addClass(div, this.baseClass+"Marker");
+			}else if(!(index%this._clickableIncrement)){
+				dojo.addClass(div, this.baseClass+"Tick");
+			}
+
+			if(this.isDisabledDate(date)){
+				// set disabled
+				dojo.addClass(div, this.baseClass+"ItemDisabled");
+			}
+			if(!dojo.date.compare(this.value, date, this.constraints.selector)){
+				div.selected = true;
+				dojo.addClass(div, this.baseClass+"ItemSelected");
+				if(dojo.hasClass(div, this.baseClass+"Marker")){
+					dojo.addClass(div, this.baseClass+"MarkerSelected");
+				}else{
+					dojo.addClass(div, this.baseClass+"TickSelected");
+				}
+			}
+			return div;
+		},
+
+		_onOptionSelected: function(/*Object*/ tgt){
+			// summary:
+			//		Called when user clicks an option in the drop down list
+			// tags:
+			//		private
+			var tdate = tgt.target.date || tgt.target.parentNode.date;
+			if(!tdate || this.isDisabledDate(tdate)){ return; }
+			this._highlighted_option = null;
+			this.set('value', tdate);
+			this.onValueSelected(tdate);
+		},
+
+		onValueSelected: function(/*Date*/ time){
+			// summary:
+			//		Notification that a time was selected.  It may be the same as the previous value.
+			// description:
+			//      Used by `dijit.form._DateTimeTextBox` (and thus `dijit.form.TimeTextBox`)
+			//      to get notification when the user has clicked a time.
+			// tags:
+			//      protected
+		},
+
+
+		_highlightOption: function(/*node*/ node, /*Boolean*/ highlight){
+			// summary:
+			//		Turns on/off hover effect on a node based on mouse out/over event
+			// tags:
+			//		private
+			if(!node){return;}
+			if(highlight){
+				if(this._highlighted_option){
+					this._highlightOption(this._highlighted_option, false);
+				}
+				this._highlighted_option = node;
+			}else if(this._highlighted_option !== node){
+				return;
+			}else{
+				this._highlighted_option = null;
+			}
+			dojo.toggleClass(node, this.baseClass+"ItemHover", highlight);
+			if(dojo.hasClass(node, this.baseClass+"Marker")){
+				dojo.toggleClass(node, this.baseClass+"MarkerHover", highlight);
+			}else{
+				dojo.toggleClass(node, this.baseClass+"TickHover", highlight);
+			}
+		},
+
+		onmouseover: function(/*Event*/ e){
+			// summary:
+			//		Handler for onmouseover event
+			// tags:
+			//		private
+			this._keyboardSelected = null;
+			var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode;
+			// if we aren't targeting an item, then we return
+			if(!dojo.hasClass(tgr, this.baseClass+"Item")){return;}
+			this._highlightOption(tgr, true);
+		},
+
+		onmouseout: function(/*Event*/ e){
+			// summary:
+			//		Handler for onmouseout event
+			// tags:
+			//		private
+			this._keyboardSelected = null;
+			var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode;
+			this._highlightOption(tgr, false);
+		},
+
+		_mouseWheeled: function(/*Event*/ e){
+			// summary:
+			//		Handle the mouse wheel events
+			// tags:
+			//		private
+			this._keyboardSelected = null;
+			dojo.stopEvent(e);
+			// we're not _measuring_ the scroll amount, just direction
+			var scrollAmount = (dojo.isIE ? e.wheelDelta : -e.detail);
+			this[(scrollAmount>0 ? "_onArrowUp" : "_onArrowDown")](); // yes, we're making a new dom node every time you mousewheel, or click
+		},
+
+		_onArrowUp: function(count){
+			// summary:
+			//		Handler for up arrow key.
+			// description:
+			//		Removes the bottom time and add one to the top
+			// tags:
+			//		private
+			if(typeof count == "number" && count == -1){ return; } // typematic end
+			if(!this.timeMenu.childNodes.length){ return; }
+			var index = this.timeMenu.childNodes[0].index;
+			var divs = this._getFilteredNodes(index, 1, true);
+			if(divs.length){
+				this.timeMenu.removeChild(this.timeMenu.childNodes[this.timeMenu.childNodes.length - 1]);
+				this.timeMenu.insertBefore(divs[0], this.timeMenu.childNodes[0]);
+			}
+		},
+
+		_onArrowDown: function(count){
+			// summary:
+			//		Handler for up arrow key.
+			// description:
+			//		Remove the top time and add one to the bottom
+			// tags:
+			//		private
+			if(typeof count == "number" && count == -1){ return; } // typematic end
+			if(!this.timeMenu.childNodes.length){ return; }
+			var index = this.timeMenu.childNodes[this.timeMenu.childNodes.length - 1].index + 1;
+			var divs = this._getFilteredNodes(index, 1, false);
+			if(divs.length){
+				this.timeMenu.removeChild(this.timeMenu.childNodes[0]);
+				this.timeMenu.appendChild(divs[0]);
+			}
+		},
+
+		handleKey: function(/*Event*/ e){
+			// summary:
+			//		Called from `dijit.form._DateTimeTextBox` to pass a keypress event
+			//		from the `dijit.form.TimeTextBox` to be handled in this widget
+			// tags:
+			//		protected
+			var dk = dojo.keys;
+			if(e.keyChar || e.charOrCode === dk.BACKSPACE || e.charOrCode == dk.DELETE){
+				// Set a timeout to kick off our filter
+				setTimeout(dojo.hitch(this, function(){
+					this._filterString = e.target.value.toLowerCase();
+					this._showText();
+				}),1);
+			}else if(e.charOrCode == dk.DOWN_ARROW || e.charOrCode == dk.UP_ARROW){
+				dojo.stopEvent(e);
+				// Figure out which option to highlight now and then highlight it
+				if(this._highlighted_option && !this._highlighted_option.parentNode){
+					this._highlighted_option = null;
+				}
+				var timeMenu = this.timeMenu,
+					tgt = this._highlighted_option || dojo.query("." + this.baseClass + "ItemSelected", timeMenu)[0];
+				if(!tgt){
+					tgt = timeMenu.childNodes[0];
+				}else if(timeMenu.childNodes.length){
+					if(e.charOrCode == dk.DOWN_ARROW && !tgt.nextSibling){
+						this._onArrowDown();
+					}else if(e.charOrCode == dk.UP_ARROW && !tgt.previousSibling){
+						this._onArrowUp();
+					}
+					if(e.charOrCode == dk.DOWN_ARROW){
+						tgt = tgt.nextSibling;
+					}else{
+						tgt = tgt.previousSibling;
+					}
+				}
+				this._highlightOption(tgt, true);
+				this._keyboardSelected = tgt;
+			}else if(this._highlighted_option && (e.charOrCode == dk.ENTER || e.charOrCode === dk.TAB)){
+				// Accept the currently-highlighted option as the value
+				if(!this._keyboardSelected && e.charOrCode === dk.TAB){ return; } // mouse hover followed by TAB is NO selection
+				if(e.charOrCode == dk.ENTER){dojo.stopEvent(e);}
+				this._onOptionSelected({target: this._highlighted_option});
+			}
+		}
+	}
+);
+
diff --git a/dijit/_Widget.js b/dijit/_Widget.js
index 2ad0cb6..5d7ba32 100644
--- a/dijit/_Widget.js
+++ b/dijit/_Widget.js
@@ -1,322 +1,1195 @@
-/*
-	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
-*/
+dojo.provide("dijit._Widget");
 
+//>>excludeStart("dijitBaseExclude", kwArgs.customDijitBase == "true");
+dojo.require( "dijit._base" );
+//>>excludeEnd("dijitBaseExclude");
 
-if(!dojo._hasResource["dijit._Widget"]){
-dojo._hasResource["dijit._Widget"]=true;
-dojo.provide("dijit._Widget");
-dojo.require("dijit._base");
-dojo.connect(dojo,"_connect",function(_1,_2){
-if(_1&&dojo.isFunction(_1._onConnect)){
-_1._onConnect(_2);
-}
-});
-dijit._connectOnUseEventHandler=function(_3){
-};
-dijit._lastKeyDownNode=null;
+
+// This code is to assist deferring dojo.connect() calls in widgets (connecting to events on the widgets'
+// DOM nodes) until someone actually needs to monitor that event.
+dojo.connect(dojo, "_connect",
+	function(/*dijit._Widget*/ widget, /*String*/ event){
+		if(widget && dojo.isFunction(widget._onConnect)){
+			widget._onConnect(event);
+		}
+	});
+
+dijit._connectOnUseEventHandler = function(/*Event*/ event){};
+
+// Keep track of where the last keydown event was, to help avoid generating
+// spurious ondijitclick events when:
+// 1. focus is on a <button> or <a>
+// 2. user presses then releases the ENTER key
+// 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
+// 4. onkeyup event fires, causing the ondijitclick handler to fire
+dijit._lastKeyDownNode = null;
 if(dojo.isIE){
-(function(){
-var _4=function(_5){
-dijit._lastKeyDownNode=_5.srcElement;
-};
-dojo.doc.attachEvent("onkeydown",_4);
-dojo.addOnWindowUnload(function(){
-dojo.doc.detachEvent("onkeydown",_4);
-});
-})();
+	(function(){
+		var keydownCallback = function(evt){
+			dijit._lastKeyDownNode = evt.srcElement;
+		};
+		dojo.doc.attachEvent('onkeydown', keydownCallback);
+		dojo.addOnWindowUnload(function(){
+			dojo.doc.detachEvent('onkeydown', keydownCallback);
+		});
+	})();
 }else{
-dojo.doc.addEventListener("keydown",function(_6){
-dijit._lastKeyDownNode=_6.target;
-},true);
+	dojo.doc.addEventListener('keydown', function(evt){
+		dijit._lastKeyDownNode = evt.target;
+	}, true);
 }
+
 (function(){
-var _7={},_8=function(_9){
-var dc=_9.declaredClass;
-if(!_7[dc]){
-var r=[],_a,_b=_9.constructor.prototype;
-for(var _c in _b){
-if(dojo.isFunction(_b[_c])&&(_a=_c.match(/^_set([a-zA-Z]*)Attr$/))&&_a[1]){
-r.push(_a[1].charAt(0).toLowerCase()+_a[1].substr(1));
-}
-}
-_7[dc]=r;
-}
-return _7[dc]||[];
-};
-dojo.declare("dijit._Widget",null,{id:"",lang:"",dir:"","class":"",style:"",title:"",tooltip:"",srcNodeRef:null,domNode:null,containerNode:null,attributeMap:{id:"",dir:"",lang:"","class":"",style:"",title:""},_deferredConnects:{onClick:"",onDblClick:"",onKeyDown:"",onKeyPress:"",onKeyUp:"",onMouseMove:"",onMouseDown:"",onMouseOut:"",onMouseOver:"",onMouseLeave:"",onMouseEnter:"",onMouseUp:""},onClick:dijit._connectOnUseEventHandler,onDblClick:dijit._connectOnUseEventHandler,onKeyDown:dij [...]
-this.create(_d,_e);
-},create:function(_f,_10){
-this.srcNodeRef=dojo.byId(_10);
-this._connects=[];
-this._subscribes=[];
-this._deferredConnects=dojo.clone(this._deferredConnects);
-for(var _11 in this.attributeMap){
-delete this._deferredConnects[_11];
-}
-for(_11 in this._deferredConnects){
-if(this[_11]!==dijit._connectOnUseEventHandler){
-delete this._deferredConnects[_11];
-}
-}
-if(this.srcNodeRef&&(typeof this.srcNodeRef.id=="string")){
-this.id=this.srcNodeRef.id;
-}
-if(_f){
-this.params=_f;
-dojo.mixin(this,_f);
-}
-this.postMixInProperties();
-if(!this.id){
-this.id=dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
-}
-dijit.registry.add(this);
-this.buildRendering();
-if(this.domNode){
-this._applyAttributes();
-var _12=this.srcNodeRef;
-if(_12&&_12.parentNode){
-_12.parentNode.replaceChild(this.domNode,_12);
-}
-for(_11 in this.params){
-this._onConnect(_11);
-}
-}
-if(this.domNode){
-this.domNode.setAttribute("widgetId",this.id);
-}
-this.postCreate();
-if(this.srcNodeRef&&!this.srcNodeRef.parentNode){
-delete this.srcNodeRef;
-}
-this._created=true;
-},_applyAttributes:function(){
-var _13=function(_14,_15){
-if((_15.params&&_14 in _15.params)||_15[_14]){
-_15.attr(_14,_15[_14]);
-}
-};
-for(var _16 in this.attributeMap){
-_13(_16,this);
-}
-dojo.forEach(_8(this),function(a){
-if(!(a in this.attributeMap)){
-_13(a,this);
-}
-},this);
-},postMixInProperties:function(){
-},buildRendering:function(){
-this.domNode=this.srcNodeRef||dojo.create("div");
-},postCreate:function(){
-},startup:function(){
-this._started=true;
-},destroyRecursive:function(_17){
-this._beingDestroyed=true;
-this.destroyDescendants(_17);
-this.destroy(_17);
-},destroy:function(_18){
-this._beingDestroyed=true;
-this.uninitialize();
-var d=dojo,dfe=d.forEach,dun=d.unsubscribe;
-dfe(this._connects,function(_19){
-dfe(_19,d.disconnect);
-});
-dfe(this._subscribes,function(_1a){
-dun(_1a);
-});
-dfe(this._supportingWidgets||[],function(w){
-if(w.destroyRecursive){
-w.destroyRecursive();
-}else{
-if(w.destroy){
-w.destroy();
-}
-}
-});
-this.destroyRendering(_18);
-dijit.registry.remove(this.id);
-this._destroyed=true;
-},destroyRendering:function(_1b){
-if(this.bgIframe){
-this.bgIframe.destroy(_1b);
-delete this.bgIframe;
-}
-if(this.domNode){
-if(_1b){
-dojo.removeAttr(this.domNode,"widgetId");
-}else{
-dojo.destroy(this.domNode);
-}
-delete this.domNode;
-}
-if(this.srcNodeRef){
-if(!_1b){
-dojo.destroy(this.srcNodeRef);
-}
-delete this.srcNodeRef;
-}
-},destroyDescendants:function(_1c){
-dojo.forEach(this.getChildren(),function(_1d){
-if(_1d.destroyRecursive){
-_1d.destroyRecursive(_1c);
-}
+
+var _attrReg = {},	// cached results from getSetterAttributes
+	getSetterAttributes = function(widget){
+		// summary:
+		//		Returns list of attributes with custom setters for specified widget
+		var dc = widget.declaredClass;
+		if(!_attrReg[dc]){
+			var r = [],
+				attrs,
+				proto = widget.constructor.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] || [];	// String[]
+	};
+
+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
+	//		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".  If undefined, widgets renders in page's
+	//		default direction.
+	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.
+	//
+	//		For form widgets this specifies a tooltip to display when hovering over
+	//		the widget (just like the native HTML title attribute).
+	//
+	//		For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
+	//		etc., it's used to specify the tab label, accordion pane title, etc.
+	title: "",
+
+	// tooltip: String
+	//		When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
+	//		this specifies the tooltip to appear when the mouse is hovered over that text.
+	tooltip: "",
+
+	// baseClass: [protected] String
+	//		Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate
+	//		widget state.
+	baseClass: "",
+
+	// 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,
+
+/*=====
+	// _started: Boolean
+	//		startup() has completed.
+	_started: false,
+=====*/
+
+	// 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 innerText
+	//	|		title: { node: "titleNode", type: "innerText" }
+	//		Maps this.title to this.titleNode.innerText
+	//
+	//		- 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] String
+	//		Path to a blank 1x1 image.
+	//		Used by <img> nodes in templates that really get their image via CSS background-image.
+	_blankGif: (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")).toString(),
+
+	//////////// 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:
+		//		Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
+		//		etc.), some of which of you'll want to override. See http://docs.dojocampus.org/dijit/_Widget
+		//		for a discussion of the widget creation lifecycle.
+		//
+		//		Of course, adventurous developers could override create entirely, but this should
+		//		only be done as a last resort.
+		// 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 = [];
+
+		// For garbage collection.  An array of handles returned by Widget.subscribe()
+		// The handle returned from Widget.subscribe() is the handle returned from dojo.subscribe()
+		this._subscribes = [];
+
+		// 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.set(attr, scope[attr]);
+			}
+		};
+
+		// Do the attributes in attributeMap
+		for(var attr in this.attributeMap){
+			condAttrApply(attr, this);
+		}
+
+		// And also any attributes with custom setters
+		dojo.forEach(getSetterAttributes(this), 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
+		// description:
+		//		Most widgets will mixin `dijit._Templated`, which implements this
+		//		method.
+		// tags:
+		//		protected
+		this.domNode = this.srcNodeRef || dojo.create('div');
+	},
+
+	postCreate: function(){
+		// summary:
+		//		Processing after the DOM fragment is created
+		// description:
+		//		Called after the DOM fragment has been created, but not necessarily
+		//		added to the document.  Do not include any operations which rely on
+		//		node dimensions or placement.
+		// tags:
+		//		protected
+
+		// baseClass is a single class name or occasionally a space-separated list of names.
+		// Add those classes to the DOMNod.  If RTL mode then also add with Rtl suffix.		
+		if(this.baseClass){
+			var classes = this.baseClass.split(" ");
+			if(!this.isLeftToRight()){
+				classes = classes.concat( dojo.map(classes, function(name){ return name+"Rtl"; }));
+			}
+			dojo.addClass(this.domNode, classes);
+		}
+	},
+
+	startup: function(){
+		// summary:
+		//		Processing after the DOM fragment is added to the document
+		// description:
+		//		Called after a widget and its children have been created and added to the page,
+		//		and all related widgets have finished their create() cycle, up through postCreate().
+		//		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 its descendants
+		// description:
+		//		This is the generic "destructor" function that all widget users
+		// 		should call to cleanly discard with a widget. Once a widget is
+		// 		destroyed, it is 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._beingDestroyed = true;
+		this.destroyDescendants(preserveDom);
+		this.destroy(preserveDom);
+	},
+
+	destroy: function(/*Boolean*/ preserveDom){
+		// summary:
+		// 		Destroy this widget, but not its descendants.
+		//		This method 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._beingDestroyed = true;
+		this.uninitialize();
+		var d = dojo,
+			dfe = d.forEach,
+			dun = d.unsubscribe;
+		dfe(this._connects, function(array){
+			dfe(array, d.disconnect);
+		});
+		dfe(this._subscribes, function(handle){
+			dun(handle);
+		});
+
+		// destroy widgets created as part of template, etc.
+		dfe(this._supportingWidgets || [], function(w){
+			if(w.destroyRecursive){
+				w.destroyRecursive();
+			}else if(w.destroy){
+				w.destroy();
+			}
+		});
+
+		this.destroyRendering(preserveDom);
+		dijit.registry.remove(this.id);
+		this._destroyed = true;
+	},
+
+	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 set() instead.
+		// tags:
+		//		deprecated
+		dojo.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0");
+		this.set(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, innerText, or attribute
+
+			switch(type){
+				case "attribute":
+					if(dojo.isFunction(value)){ // functions execute in the context of the widget
+						value = dojo.hitch(this, value);
+					}
+
+					// Get the name of the DOM node attribute; usually it's the same
+					// as the name of the attribute in the widget (attr), but can be overridden.
+					// Also maps handler names to lowercase, like onSubmit --> onsubmit
+					var attrName = command.attribute ? command.attribute :
+						(/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
+
+					dojo.attr(mapNode, attrName, value);
+					break;
+				case "innerText":
+					mapNode.innerHTML = "";
+					mapNode.appendChild(dojo.doc.createTextNode(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:
+		//		This method is deprecated, use get() or set() directly.
+
+		// Print deprecation warning but only once per calling function
+		if(dojo.config.isDebug){
+			var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}),
+				caller = (arguments.callee.caller || "unknown caller").toString();
+			if(!alreadyCalledHash[caller]){
+				dojo.deprecated(this.declaredClass + "::attr() is deprecated. Use get() or set() instead, called from " +
+				caller, "", "2.0");
+				alreadyCalledHash[caller] = true;
+			}
+		}
+
+		var args = arguments.length;
+		if(args >= 2 || typeof name === "object"){ // setter
+			return this.set.apply(this, arguments);
+		}else{ // getter
+			return this.get(name);
+		}
+	},
+	
+	get: function(name){
+		// summary:
+		//		Get a property from a widget.
+		//	name:
+		//		The property to get.
+		// description:
+		//		Get a named property from a widget. The property may
+		//		potentially be retrieved via a getter method. If no getter is defined, this
+		// 		just retrieves the object's property.  
+		// 		For example, if the widget has a properties "foo"
+		//		and "bar" and a method named "_getFooAttr", calling:
+		//	|	myWidget.get("foo");
+		//		would be equivalent to writing:
+		//	|	widget._getFooAttr();
+		//		and:
+		//	|	myWidget.get("bar");
+		//		would be equivalent to writing:
+		//	|	widget.bar;
+		var names = this._getAttrNames(name);
+		return this[names.g] ? this[names.g]() : this[name];
+	},
+	
+	set: function(name, value){
+		// summary:
+		//		Set a property on a widget
+		//	name:
+		//		The property to set. 
+		//	value:
+		//		The value to set in the property.
+		// description:
+		//		Sets named properties on a widget which may potentially be handled by a 
+		// 		setter in the widget.
+		// 		For example, if the widget has a properties "foo"
+		//		and "bar" and a method named "_setFooAttr", calling:
+		//	|	myWidget.set("foo", "Howdy!");
+		//		would be equivalent to writing:
+		//	|	widget._setFooAttr("Howdy!");
+		//		and:
+		//	|	myWidget.set("bar", 3);
+		//		would be equivalent to writing:
+		//	|	widget.bar = 3;
+		//
+		//	set() may also be called with a hash of name/value pairs, ex:
+		//	|	myWidget.set({
+		//	|		foo: "Howdy",
+		//	|		bar: 3
+		//	|	})
+		//	This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
+
+		if(typeof name === "object"){
+			for(var x in name){
+				this.set(x, name[x]); 
+			}
+			return this;
+		}
+		var names = this._getAttrNames(name);
+		if(this[names.s]){
+			// use the explicit setter
+			var result = this[names.s].apply(this, Array.prototype.slice.call(arguments, 1));
+		}else{
+			// if param is specified as DOM node attribute, copy it
+			if(name in this.attributeMap){
+				this._attrToDom(name, value);
+			}
+			var oldValue = this[name];
+			// FIXME: what about function assignments? Any way to connect() here?
+			this[name] = value;
+		}
+		return result || this;
+	},
+	
+	_attrPairNames: {},		// shared between all widgets
+	_getAttrNames: function(name){
+		// summary:
+		//		Helper function for get() and set().
+		//		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
+		// description:
+		//		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 reversible
+		//		serialization.
+		return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
+	},
+
+	getDescendants: function(){
+		// summary:
+		//		Returns all the widgets 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.
+
+		return this.containerNode ? dojo.query('[widgetId]', this.containerNode).map(dijit.byNode) : []; // dijit._Widget[]
+	},
+
+	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.
+		return this.containerNode ? dijit.findWidgets(this.containerNode) : []; // dijit._Widget[]
+	},
+
+	// 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 or enter keyup
+		// returns:
+		//		A handle that can be passed to `disconnect` in order to disconnect before
+		//		the widget is destroyed.
+		// 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(){
+		//	|		console.debug(this.toString());
+		//	|	});
+		// tags:
+		//		protected
+
+		var d = dojo,
+			dc = d._connect,
+			handles = [];
+		if(event == "ondijitclick"){
+			// add key based click activation for unsupported nodes.
+			// do all processing onkey up to prevent spurious clicks
+			// for details see comments at top of this file where _lastKeyDownNode is defined
+			if(dojo.indexOf(this.nodesWithKeyClick, obj.nodeName.toLowerCase()) == -1){ // is NOT input or button
+				var m = d.hitch(this, method);
+				handles.push(
+					dc(obj, "onkeydown", this, function(e){
+						//console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
+						if((e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
+							!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
+							// needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
+							dijit._lastKeyDownNode = e.target;
+							e.preventDefault();		// stop event to prevent scrolling on space key in IE
+						}
+			 		}),
+					dc(obj, "onkeyup", this, function(e){
+						//console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
+						if( (e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
+							e.target === dijit._lastKeyDownNode &&
+							!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
+								//need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
+								dijit._lastKeyDownNode = null;
+								return m(e);
+						}
+					})
+				);
+			}
+			event = "onclick";
+		}
+		handles.push(dc(obj, event, this, method));
+
+		this._connects.push(handles);
+		return handles;		// _Widget.Handle
+	},
+
+	disconnect: function(/* _Widget.Handle */ handles){
+		// summary:
+		//		Disconnects handle created by `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;
+			}
+		}
+	},
+
+	subscribe: function(
+			/*String*/ topic,
+			/*String|Function*/ method){
+		// summary:
+		//		Subscribes to the specified topic and calls the specified method
+		//		of this object and registers for unsubscribe() on widget destroy.
+		// description:
+		//		Provide widget-specific analog to dojo.subscribe, except with the
+		//		implicit use of this widget as the target object.
+		// example:
+		//	|	var btn = new dijit.form.Button();
+		//	|	// when /my/topic is published, this button changes its label to
+		//	|   // be the parameter of the topic.
+		//	|	btn.subscribe("/my/topic", function(v){
+		//	|		this.set("label", v);
+		//	|	});
+		var d = dojo,
+			handle = d.subscribe(topic, this, method);
+
+		// return handles for Any widget that may need them
+		this._subscribes.push(handle);
+		return handle;
+	},
+
+	unsubscribe: function(/*Object*/ handle){
+		// summary:
+		//		Unsubscribes handle created by this.subscribe.
+		//		Also removes handle from this widget's list of subscriptions
+		for(var i=0; i<this._subscribes.length; i++){
+			if(this._subscribes[i] == handle){
+				dojo.unsubscribe(handle);
+				this._subscribes.splice(i, 1);
+				return;
+			}
+		}
+	},
+
+	isLeftToRight: function(){
+		// summary:
+		//		Return this widget's explicit or implicit orientation (true for LTR, false for RTL)
+		// tags:
+		//		protected
+		return this.dir ? (this.dir == "ltr") : 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){ console.log('click'); });
+		//
+		// 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;
+	},
+
+	_onShow: function(){
+		// summary:
+		//		Internal method called when this widget is made visible.
+		//		See `onShow` for details.
+		this.onShow();
+	},
+
+	onShow: function(){
+		// summary:
+		//		Called when this widget becomes the selected pane in a
+		//		`dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
+		//		`dijit.layout.AccordionContainer`, etc.
+		//
+		//		Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
+		// tags:
+		//		callback
+	},
+
+	onHide: function(){
+		// summary:
+			//		Called when another widget becomes the selected pane in a
+			//		`dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
+			//		`dijit.layout.AccordionContainer`, etc.
+			//
+			//		Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
+			// tags:
+			//		callback
+	},
+
+	onClose: function(){
+		// summary:
+		//		Called when this widget is being displayed as a popup (ex: a Calendar popped
+		//		up from a DateTextBox), and it is hidden.
+		//		This is called from the dijit.popup code, and should not be called directly.
+		//
+		//		Also used as a parameter for children of `dijit.layout.StackContainer` or subclasses.
+		//		Callback if a user tries to close the child.   Child will be closed if this function returns true.
+		// tags:
+		//		extension
+
+		return true;		// Boolean
+	}
 });
-},uninitialize:function(){
-return false;
-},onFocus:function(){
-},onBlur:function(){
-},_onFocus:function(e){
-this.onFocus();
-},_onBlur:function(){
-this.onBlur();
-},_onConnect:function(_1e){
-if(_1e in this._deferredConnects){
-var _1f=this[this._deferredConnects[_1e]||"domNode"];
-this.connect(_1f,_1e.toLowerCase(),_1e);
-delete this._deferredConnects[_1e];
-}
-},_setClassAttr:function(_20){
-var _21=this[this.attributeMap["class"]||"domNode"];
-dojo.removeClass(_21,this["class"]);
-this["class"]=_20;
-dojo.addClass(_21,_20);
-},_setStyleAttr:function(_22){
-var _23=this[this.attributeMap.style||"domNode"];
-if(dojo.isObject(_22)){
-dojo.style(_23,_22);
-}else{
-if(_23.style.cssText){
-_23.style.cssText+="; "+_22;
-}else{
-_23.style.cssText=_22;
-}
-}
-this.style=_22;
-},setAttribute:function(_24,_25){
-dojo.deprecated(this.declaredClass+"::setAttribute() is deprecated. Use attr() instead.","","2.0");
-this.attr(_24,_25);
-},_attrToDom:function(_26,_27){
-var _28=this.attributeMap[_26];
-dojo.forEach(dojo.isArray(_28)?_28:[_28],function(_29){
-var _2a=this[_29.node||_29||"domNode"];
-var _2b=_29.type||"attribute";
-switch(_2b){
-case "attribute":
-if(dojo.isFunction(_27)){
-_27=dojo.hitch(this,_27);
-}
-var _2c=_29.attribute?_29.attribute:(/^on[A-Z][a-zA-Z]*$/.test(_26)?_26.toLowerCase():_26);
-dojo.attr(_2a,_2c,_27);
-break;
-case "innerText":
-_2a.innerHTML="";
-_2a.appendChild(dojo.doc.createTextNode(_27));
-break;
-case "innerHTML":
-_2a.innerHTML=_27;
-break;
-case "class":
-dojo.removeClass(_2a,this[_26]);
-dojo.addClass(_2a,_27);
-break;
-}
-},this);
-this[_26]=_27;
-},attr:function(_2d,_2e){
-var _2f=arguments.length;
-if(_2f==1&&!dojo.isString(_2d)){
-for(var x in _2d){
-this.attr(x,_2d[x]);
-}
-return this;
-}
-var _30=this._getAttrNames(_2d);
-if(_2f>=2){
-if(this[_30.s]){
-_2f=dojo._toArray(arguments,1);
-return this[_30.s].apply(this,_2f)||this;
-}else{
-if(_2d in this.attributeMap){
-this._attrToDom(_2d,_2e);
-}
-this[_2d]=_2e;
-}
-return this;
-}else{
-return this[_30.g]?this[_30.g]():this[_2d];
-}
-},_attrPairNames:{},_getAttrNames:function(_31){
-var apn=this._attrPairNames;
-if(apn[_31]){
-return apn[_31];
-}
-var uc=_31.charAt(0).toUpperCase()+_31.substr(1);
-return (apn[_31]={n:_31+"Node",s:"_set"+uc+"Attr",g:"_get"+uc+"Attr"});
-},toString:function(){
-return "[Widget "+this.declaredClass+", "+(this.id||"NO ID")+"]";
-},getDescendants:function(){
-return this.containerNode?dojo.query("[widgetId]",this.containerNode).map(dijit.byNode):[];
-},getChildren:function(){
-return this.containerNode?dijit.findWidgets(this.containerNode):[];
-},nodesWithKeyClick:["input","button"],connect:function(obj,_32,_33){
-var d=dojo,dc=d._connect,_34=[];
-if(_32=="ondijitclick"){
-if(!this.nodesWithKeyClick[obj.tagName.toLowerCase()]){
-var m=d.hitch(this,_33);
-_34.push(dc(obj,"onkeydown",this,function(e){
-if((e.keyCode==d.keys.ENTER||e.keyCode==d.keys.SPACE)&&!e.ctrlKey&&!e.shiftKey&&!e.altKey&&!e.metaKey){
-dijit._lastKeyDownNode=e.target;
-d.stopEvent(e);
-}
-}),dc(obj,"onkeyup",this,function(e){
-if((e.keyCode==d.keys.ENTER||e.keyCode==d.keys.SPACE)&&e.target===dijit._lastKeyDownNode&&!e.ctrlKey&&!e.shiftKey&&!e.altKey&&!e.metaKey){
-dijit._lastKeyDownNode=null;
-return m(e);
-}
-}));
-}
-_32="onclick";
-}
-_34.push(dc(obj,_32,this,_33));
-this._connects.push(_34);
-return _34;
-},disconnect:function(_35){
-for(var i=0;i<this._connects.length;i++){
-if(this._connects[i]==_35){
-dojo.forEach(_35,dojo.disconnect);
-this._connects.splice(i,1);
-return;
-}
-}
-},subscribe:function(_36,_37){
-var d=dojo,_38=d.subscribe(_36,this,_37);
-this._subscribes.push(_38);
-return _38;
-},unsubscribe:function(_39){
-for(var i=0;i<this._subscribes.length;i++){
-if(this._subscribes[i]==_39){
-dojo.unsubscribe(_39);
-this._subscribes.splice(i,1);
-return;
-}
-}
-},isLeftToRight:function(){
-return dojo._isBodyLtr();
-},isFocusable:function(){
-return this.focus&&(dojo.style(this.domNode,"display")!="none");
-},placeAt:function(_3a,_3b){
-if(_3a.declaredClass&&_3a.addChild){
-_3a.addChild(this,_3b);
-}else{
-dojo.place(this.domNode,_3a,_3b);
-}
-return this;
-},_onShow:function(){
-this.onShow();
-},onShow:function(){
-},onHide:function(){
-}});
+
 })();
-}
diff --git a/dijit/_base.js b/dijit/_base.js
index 9c173e0..c5f6673 100644
--- a/dijit/_base.js
+++ b/dijit/_base.js
@@ -1,13 +1,5 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._base"]){
-dojo._hasResource["dijit._base"]=true;
 dojo.provide("dijit._base");
+
 dojo.require("dijit._base.focus");
 dojo.require("dijit._base.manager");
 dojo.require("dijit._base.place");
@@ -17,4 +9,3 @@ dojo.require("dijit._base.sniff");
 dojo.require("dijit._base.typematic");
 dojo.require("dijit._base.wai");
 dojo.require("dijit._base.window");
-}
diff --git a/dijit/_base/focus.js b/dijit/_base/focus.js
index 1e0bdc7..231a7df 100644
--- a/dijit/_base/focus.js
+++ b/dijit/_base/focus.js
@@ -1,301 +1,514 @@
-/*
-	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
-*/
+dojo.provide("dijit._base.focus");
 
+dojo.require("dojo.window");
+dojo.require("dijit._base.manager");	// for dijit.isTabNavigable()
 
-if(!dojo._hasResource["dijit._base.focus"]){
-dojo._hasResource["dijit._base.focus"]=true;
-dojo.provide("dijit._base.focus");
-dojo.require("dijit._base.manager");
-dojo.mixin(dijit,{_curFocus:null,_prevFocus:null,isCollapsed:function(){
-return dijit.getBookmark().isCollapsed;
-},getBookmark:function(){
-var bm,rg,tg,_1=dojo.doc.selection,cf=dijit._curFocus;
-if(dojo.global.getSelection){
-_1=dojo.global.getSelection();
-if(_1){
-if(_1.isCollapsed){
-tg=cf?cf.tagName:"";
-if(tg){
-tg=tg.toLowerCase();
-if(tg=="textarea"||(tg=="input"&&(!cf.type||cf.type.toLowerCase()=="text"))){
-_1={start:cf.selectionStart,end:cf.selectionEnd,node:cf,pRange:true};
-return {isCollapsed:(_1.end<=_1.start),mark:_1};
-}
-}
-bm={isCollapsed:true};
-}else{
-rg=_1.getRangeAt(0);
-bm={isCollapsed:false,mark:rg.cloneRange()};
-}
-}
-}else{
-if(_1){
-tg=cf?cf.tagName:"";
-tg=tg.toLowerCase();
-if(cf&&tg&&(tg=="button"||tg=="textarea"||tg=="input")){
-if(_1.type&&_1.type.toLowerCase()=="none"){
-return {isCollapsed:true,mark:null};
-}else{
-rg=_1.createRange();
-return {isCollapsed:rg.text&&rg.text.length?false:true,mark:{range:rg,pRange:true}};
-}
-}
-bm={};
-try{
-rg=_1.createRange();
-bm.isCollapsed=!(_1.type=="Text"?rg.htmlText.length:rg.length);
-}
-catch(e){
-bm.isCollapsed=true;
-return bm;
-}
-if(_1.type.toUpperCase()=="CONTROL"){
-if(rg.length){
-bm.mark=[];
-var i=0,_2=rg.length;
-while(i<_2){
-bm.mark.push(rg.item(i++));
-}
-}else{
-bm.isCollapsed=true;
-bm.mark=null;
-}
-}else{
-bm.mark=rg.getBookmark();
-}
-}else{
-console.warn("No idea how to store the current selection for this browser!");
-}
-}
-return bm;
-},moveToBookmark:function(_3){
-var _4=dojo.doc,_5=_3.mark;
-if(_5){
-if(dojo.global.getSelection){
-var _6=dojo.global.getSelection();
-if(_6&&_6.removeAllRanges){
-if(_5.pRange){
-var r=_5;
-var n=r.node;
-n.selectionStart=r.start;
-n.selectionEnd=r.end;
-}else{
-_6.removeAllRanges();
-_6.addRange(_5);
-}
-}else{
-console.warn("No idea how to restore selection for this browser!");
-}
-}else{
-if(_4.selection&&_5){
-var rg;
-if(_5.pRange){
-rg=_5.range;
-}else{
-if(dojo.isArray(_5)){
-rg=_4.body.createControlRange();
-dojo.forEach(_5,function(n){
-rg.addElement(n);
+// summary:
+//		These functions are used to query or set the focus and selection.
+//
+//		Also, they trace when widgets become activated/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
+		return dijit.getBookmark().isCollapsed;
+	},
+
+	getBookmark: function(){
+		// summary:
+		//		Retrieves a bookmark that can be used with moveToBookmark to return to the same range
+		var bm, rg, tg, sel = dojo.doc.selection, cf = dijit._curFocus;
+
+		if(dojo.global.getSelection){
+			//W3C Range API for selections.
+			sel = dojo.global.getSelection();
+			if(sel){
+				if(sel.isCollapsed){
+					tg = cf? cf.tagName : "";
+					if(tg){
+						//Create a fake rangelike item to restore selections.
+						tg = tg.toLowerCase();
+						if(tg == "textarea" ||
+								(tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
+							sel = {
+								start: cf.selectionStart,
+								end: cf.selectionEnd,
+								node: cf,
+								pRange: true
+							};
+							return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
+						}
+					}
+					bm = {isCollapsed:true};
+				}else{
+					rg = sel.getRangeAt(0);
+					bm = {isCollapsed: false, mark: rg.cloneRange()};
+				}
+			}
+		}else if(sel){
+			// If the current focus was a input of some sort and no selection, don't bother saving
+			// a native bookmark.  This is because it causes issues with dialog/page selection restore.
+			// So, we need to create psuedo bookmarks to work with.
+			tg = cf ? cf.tagName : "";
+			tg = tg.toLowerCase();
+			if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
+				if(sel.type && sel.type.toLowerCase() == "none"){
+					return {
+						isCollapsed: true,
+						mark: null
+					}
+				}else{
+					rg = sel.createRange();
+					return {
+						isCollapsed: rg.text && rg.text.length?false:true,
+						mark: {
+							range: rg,
+							pRange: true
+						}
+					};
+				}
+			}
+			bm = {};
+
+			//'IE' way for selections.
+			try{
+				// createRange() throws exception when dojo in iframe
+				//and nothing selected, see #9632
+				rg = sel.createRange();
+				bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
+			}catch(e){
+				bm.isCollapsed = true;
+				return bm;
+			}
+			if(sel.type.toUpperCase() == 'CONTROL'){
+				if(rg.length){
+					bm.mark=[];
+					var i=0,len=rg.length;
+					while(i<len){
+						bm.mark.push(rg.item(i++));
+					}
+				}else{
+					bm.isCollapsed = true;
+					bm.mark = null;
+				}
+			}else{
+				bm.mark = rg.getBookmark();
+			}
+		}else{
+			console.warn("No idea how to store the current selection for this browser!");
+		}
+		return bm; // Object
+	},
+
+	moveToBookmark: function(/*Object*/bookmark){
+		// summary:
+		//		Moves current selection to a bookmark
+		// bookmark:
+		//		This should be a returned object from dijit.getBookmark()
+
+		var _doc = dojo.doc,
+			mark = bookmark.mark;
+		if(mark){
+			if(dojo.global.getSelection){
+				//W3C Rangi API (FF, WebKit, Opera, etc)
+				var sel = dojo.global.getSelection();
+				if(sel && sel.removeAllRanges){
+					if(mark.pRange){
+						var r = mark;
+						var n = r.node;
+						n.selectionStart = r.start;
+						n.selectionEnd = r.end;
+					}else{
+						sel.removeAllRanges();
+						sel.addRange(mark);
+					}
+				}else{
+					console.warn("No idea how to restore selection for this browser!");
+				}
+			}else if(_doc.selection && mark){
+				//'IE' way.
+				var rg;
+				if(mark.pRange){
+					rg = mark.range;
+				}else if(dojo.isArray(mark)){
+					rg = _doc.body.createControlRange();
+					//rg.addElement does not have call/apply method, so can not call it directly
+					//rg is not available in "range.addElement(item)", so can't use that either
+					dojo.forEach(mark, function(n){
+						rg.addElement(n);
+					});
+				}else{
+					rg = _doc.body.createTextRange();
+					rg.moveToBookmark(mark);
+				}
+				rg.select();
+			}
+		}
+	},
+
+	getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){
+		// summary:
+		//		Called as getFocus(), this returns an Object showing the current focus
+		//		and selected text.
+		//
+		//		Called as getFocus(widget), where widget is a (widget representing) a button
+		//		that was just pressed, it returns where focus was before that button
+		//		was pressed.   (Pressing the button may have either shifted focus to the button,
+		//		or removed focus altogether.)   In this case the selected text is not returned,
+		//		since it can't be accurately determined.
+		//
+		// menu: dijit._Widget or {domNode: DomNode} structure
+		//		The button that was just pressed.  If focus has disappeared or moved
+		//		to this button, returns the previous focus.  In this case the bookmark
+		//		information is already lost, and null is returned.
+		//
+		// openedForWindow:
+		//		iframe in which menu was opened
+		//
+		// returns:
+		//		A handle to restore focus/selection, to be passed to `dijit.focus`
+		var node = !dijit._curFocus || (menu && dojo.isDescendant(dijit._curFocus, menu.domNode)) ? dijit._prevFocus : dijit._curFocus;
+		return {
+			node: node,
+			bookmark: (node == dijit._curFocus) && dojo.withGlobal(openedForWindow || dojo.global, dijit.getBookmark),
+			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,
+			collapsed = bookmark ? bookmark.isCollapsed : false;
+
+		// 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) or if previous selection was collapsed
+		// as it may cause focus shift (Esp in IE).
+		if(bookmark && dojo.withGlobal(openedForWindow || dojo.global, dijit.isCollapsed) && !collapsed){
+			if(openedForWindow){
+				openedForWindow.focus();
+			}
+			try{
+				dojo.withGlobal(openedForWindow || dojo.global, dijit.moveToBookmark, null, [bookmark]);
+			}catch(e2){
+				/*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
+			}
+		}
+	},
+
+	// _activeStack: dijit._Widget[]
+	//		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.
+		// returns:
+		//		Handle to pass to unregisterIframe()
+		return dijit.registerWin(iframe.contentWindow, iframe);
+	},
+
+	unregisterIframe: function(/*Object*/ handle){
+		// summary:
+		//		Unregisters listeners on the specified iframe created by registerIframe.
+		//		After calling be sure to delete or null out the handle itself.
+		// handle:
+		//		Handle returned by registerIframe()
+
+		dijit.unregisterWin(handle);
+	},
+
+	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.
+		// returns:
+		//		Handle to pass to unregisterWin()
+
+		// TODO: make this function private in 2.0; Editor/users should call registerIframe(),
+
+		var mousedownListener = function(evt){
+			dijit._justMouseDowned = true;
+			setTimeout(function(){ dijit._justMouseDowned = false; }, 0);
+			
+			// workaround weird IE bug where the click is on an orphaned node
+			// (first time clicking a Select/DropDownButton inside a TooltipDialog)
+			if(dojo.isIE && evt && evt.srcElement && evt.srcElement.parentNode == null){
+				return;
+			}
+
+			dijit._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse");
+		};
+		//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.
+		// Connect to <html> (rather than document) on IE to avoid memory leaks, but document on other browsers because
+		// (at least for FF) the focus event doesn't fire on <html> or <body>.
+		var doc = dojo.isIE ? targetWindow.document.documentElement : targetWindow.document;
+		if(doc){
+			if(dojo.isIE){
+				doc.attachEvent('onmousedown', mousedownListener);
+				var activateListener = function(evt){
+					// IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
+					// Should consider those more like a mouse-click than a focus....
+					if(evt.srcElement.tagName.toLowerCase() != "#document" &&
+						dijit.isTabNavigable(evt.srcElement)){
+						dijit._onFocusNode(effectiveNode || evt.srcElement);
+					}else{
+						dijit._onTouchNode(effectiveNode || evt.srcElement);
+					}
+				};
+				doc.attachEvent('onactivate', activateListener);
+				var deactivateListener =  function(evt){
+					dijit._onBlurNode(effectiveNode || evt.srcElement);
+				};
+				doc.attachEvent('ondeactivate', deactivateListener);
+
+				return function(){
+					doc.detachEvent('onmousedown', mousedownListener);
+					doc.detachEvent('onactivate', activateListener);
+					doc.detachEvent('ondeactivate', deactivateListener);
+					doc = null;	// prevent memory leak (apparent circular reference via closure)
+				};
+			}else{
+				doc.addEventListener('mousedown', mousedownListener, true);
+				var focusListener = function(evt){
+					dijit._onFocusNode(effectiveNode || evt.target);
+				};
+				doc.addEventListener('focus', focusListener, true);
+				var blurListener = function(evt){
+					dijit._onBlurNode(effectiveNode || evt.target);
+				};
+				doc.addEventListener('blur', blurListener, true);
+
+				return function(){
+					doc.removeEventListener('mousedown', mousedownListener, true);
+					doc.removeEventListener('focus', focusListener, true);
+					doc.removeEventListener('blur', blurListener, true);
+					doc = null;	// prevent memory leak (apparent circular reference via closure)
+				};
+			}
+		}
+	},
+
+	unregisterWin: function(/*Handle*/ handle){
+		// summary:
+		//		Unregisters listeners on the specified window (either the main
+		//		window or an iframe's window) according to handle returned from registerWin().
+		//		After calling be sure to delete or null out the handle itself.
+
+		// Currently our handle is actually a function
+		handle && handle();
+	},
+
+	_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, /*String*/ by){
+		// summary:
+		//		Callback when node is focused or mouse-downed
+		// node:
+		//		The node that was touched.
+		// by:
+		//		"mouse" if the focus/touch was caused by a mouse down event
+
+		// 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){
+				var popupParent = dojo.attr(node, "dijitPopupParent");
+				if(popupParent){
+					node=dijit.byId(popupParent).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=dojo.window.get(node.ownerDocument).frameElement;
+				}else{
+					// if this node is the root node of a widget, then add widget id to stack,
+					// except ignore clicks on disabled widgets (actually focusing a disabled widget still works,
+					// to support MenuItem)
+					var id = node.getAttribute && node.getAttribute("widgetId"),
+						widget = id && dijit.byId(id);
+					if(widget && !(by == "mouse" && widget.get("disabled"))){
+						newStack.unshift(id);
+					}
+					node=node.parentNode;
+				}
+			}
+		}catch(e){ /* squelch */ }
+
+		dijit._setStack(newStack, by);
+	},
+
+	_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(/*String[]*/ newStack, /*String*/ by){
+		// summary:
+		//		The stack of active widgets has changed.  Send out appropriate events and records new stack.
+		// newStack:
+		//		array of widget id's, starting from the top (outermost) widget
+		// by:
+		//		"mouse" if the focus/touch was caused by a mouse down event
+
+		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;
+			}
+		}
+
+		var widget;
+		// for all elements that have gone out of focus, send blur event
+		for(var i=oldStack.length-1; i>=nCommon; i--){
+			widget = dijit.byId(oldStack[i]);
+			if(widget){
+				widget._focused = false;
+				widget._hasBeenBlurred = true;
+				if(widget._onBlur){
+					widget._onBlur(by);
+				}
+				dojo.publish("widgetBlur", [widget, by]);
+			}
+		}
+
+		// 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(by);
+				}
+				dojo.publish("widgetFocus", [widget, by]);
+			}
+		}
+	}
 });
-}else{
-rg=_4.body.createTextRange();
-rg.moveToBookmark(_5);
-}
-}
-rg.select();
-}
-}
-}
-},getFocus:function(_7,_8){
-var _9=!dijit._curFocus||(_7&&dojo.isDescendant(dijit._curFocus,_7.domNode))?dijit._prevFocus:dijit._curFocus;
-return {node:_9,bookmark:(_9==dijit._curFocus)&&dojo.withGlobal(_8||dojo.global,dijit.getBookmark),openedForWindow:_8};
-},focus:function(_a){
-if(!_a){
-return;
-}
-var _b="node" in _a?_a.node:_a,_c=_a.bookmark,_d=_a.openedForWindow,_e=_c?_c.isCollapsed:false;
-if(_b){
-var _f=(_b.tagName.toLowerCase()=="iframe")?_b.contentWindow:_b;
-if(_f&&_f.focus){
-try{
-_f.focus();
-}
-catch(e){
-}
-}
-dijit._onFocusNode(_b);
-}
-if(_c&&dojo.withGlobal(_d||dojo.global,dijit.isCollapsed)&&!_e){
-if(_d){
-_d.focus();
-}
-try{
-dojo.withGlobal(_d||dojo.global,dijit.moveToBookmark,null,[_c]);
-}
-catch(e2){
-}
-}
-},_activeStack:[],registerIframe:function(_10){
-return dijit.registerWin(_10.contentWindow,_10);
-},unregisterIframe:function(_11){
-dijit.unregisterWin(_11);
-},registerWin:function(_12,_13){
-var _14=function(evt){
-dijit._justMouseDowned=true;
-setTimeout(function(){
-dijit._justMouseDowned=false;
-},0);
-dijit._onTouchNode(_13||evt.target||evt.srcElement,"mouse");
-};
-var doc=dojo.isIE?_12.document.documentElement:_12.document;
-if(doc){
-if(dojo.isIE){
-doc.attachEvent("onmousedown",_14);
-var _15=function(evt){
-if(evt.srcElement.tagName.toLowerCase()!="#document"&&dijit.isTabNavigable(evt.srcElement)){
-dijit._onFocusNode(_13||evt.srcElement);
-}else{
-dijit._onTouchNode(_13||evt.srcElement);
-}
-};
-doc.attachEvent("onactivate",_15);
-var _16=function(evt){
-dijit._onBlurNode(_13||evt.srcElement);
-};
-doc.attachEvent("ondeactivate",_16);
-return function(){
-doc.detachEvent("onmousedown",_14);
-doc.detachEvent("onactivate",_15);
-doc.detachEvent("ondeactivate",_16);
-doc=null;
-};
-}else{
-doc.addEventListener("mousedown",_14,true);
-var _17=function(evt){
-dijit._onFocusNode(_13||evt.target);
-};
-doc.addEventListener("focus",_17,true);
-var _18=function(evt){
-dijit._onBlurNode(_13||evt.target);
-};
-doc.addEventListener("blur",_18,true);
-return function(){
-doc.removeEventListener("mousedown",_14,true);
-doc.removeEventListener("focus",_17,true);
-doc.removeEventListener("blur",_18,true);
-doc=null;
-};
-}
-}
-},unregisterWin:function(_19){
-_19&&_19();
-},_onBlurNode:function(_1a){
-dijit._prevFocus=dijit._curFocus;
-dijit._curFocus=null;
-if(dijit._justMouseDowned){
-return;
-}
-if(dijit._clearActiveWidgetsTimer){
-clearTimeout(dijit._clearActiveWidgetsTimer);
-}
-dijit._clearActiveWidgetsTimer=setTimeout(function(){
-delete dijit._clearActiveWidgetsTimer;
-dijit._setStack([]);
-dijit._prevFocus=null;
-},100);
-},_onTouchNode:function(_1b,by){
-if(dijit._clearActiveWidgetsTimer){
-clearTimeout(dijit._clearActiveWidgetsTimer);
-delete dijit._clearActiveWidgetsTimer;
-}
-var _1c=[];
-try{
-while(_1b){
-var _1d=dojo.attr(_1b,"dijitPopupParent");
-if(_1d){
-_1b=dijit.byId(_1d).domNode;
-}else{
-if(_1b.tagName&&_1b.tagName.toLowerCase()=="body"){
-if(_1b===dojo.body()){
-break;
-}
-_1b=dijit.getDocumentWindow(_1b.ownerDocument).frameElement;
-}else{
-var id=_1b.getAttribute&&_1b.getAttribute("widgetId");
-if(id){
-_1c.unshift(id);
-}
-_1b=_1b.parentNode;
-}
-}
-}
-}
-catch(e){
-}
-dijit._setStack(_1c,by);
-},_onFocusNode:function(_1e){
-if(!_1e){
-return;
-}
-if(_1e.nodeType==9){
-return;
-}
-dijit._onTouchNode(_1e);
-if(_1e==dijit._curFocus){
-return;
-}
-if(dijit._curFocus){
-dijit._prevFocus=dijit._curFocus;
-}
-dijit._curFocus=_1e;
-dojo.publish("focusNode",[_1e]);
-},_setStack:function(_1f,by){
-var _20=dijit._activeStack;
-dijit._activeStack=_1f;
-for(var _21=0;_21<Math.min(_20.length,_1f.length);_21++){
-if(_20[_21]!=_1f[_21]){
-break;
-}
-}
-var _22;
-for(var i=_20.length-1;i>=_21;i--){
-_22=dijit.byId(_20[i]);
-if(_22){
-_22._focused=false;
-_22._hasBeenBlurred=true;
-if(_22._onBlur){
-_22._onBlur(by);
-}
-if(_22._setStateClass){
-_22._setStateClass();
-}
-dojo.publish("widgetBlur",[_22,by]);
-}
-}
-for(i=_21;i<_1f.length;i++){
-_22=dijit.byId(_1f[i]);
-if(_22){
-_22._focused=true;
-if(_22._onFocus){
-_22._onFocus(by);
-}
-if(_22._setStateClass){
-_22._setStateClass();
-}
-dojo.publish("widgetFocus",[_22,by]);
-}
-}
-}});
+
+// register top window and all the iframes it contains
 dojo.addOnLoad(function(){
-var _23=dijit.registerWin(window);
-if(dojo.isIE){
-dojo.addOnWindowUnload(function(){
-dijit.unregisterWin(_23);
-_23=null;
-});
-}
+	var handle = dijit.registerWin(window);
+	if(dojo.isIE){
+		dojo.addOnWindowUnload(function(){
+			dijit.unregisterWin(handle);
+			handle = null;
+		})
+	}
 });
-}
diff --git a/dijit/_base/manager.js b/dijit/_base/manager.js
index b258b15..57bd9a8 100644
--- a/dijit/_base/manager.js
+++ b/dijit/_base/manager.js
@@ -1,233 +1,468 @@
-/*
-	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
-*/
+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 = {};
+		this.length = 0;
+	},
+
+	add: function(/*dijit._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;
+		this.length++;
+	},
+
+	remove: function(/*String*/ id){
+		// summary:
+		//		Remove a widget from this WidgetSet. Does not destroy the widget; simply
+		//		removes the reference.
+		if(this._hash[id]){
+			delete this._hash[id];
+			this.length--;
+		}
+	},
+
+	forEach: function(/*Function*/ func, /* Object? */thisObj){
+		// summary:
+		//		Call specified function for each widget in this set.
+		//
+		// func:
+		//		A callback function to run for each item. Is passed the widget, the index
+		//		in the iteration, and the full hash, similar to `dojo.forEach`.
+		//
+		// thisObj:
+		//		An optional scope parameter
+		//
+		// example:
+		//		Using the default `dijit.registry` instance:
+		//		|	dijit.registry.forEach(function(widget){
+		//		|		console.log(widget.declaredClass);
+		//		|	});
+		//
+		// returns:
+		//		Returns self, in order to allow for further chaining.
+
+		thisObj = thisObj || dojo.global;
+		var i = 0, id;
+		for(id in this._hash){
+			func.call(thisObj, this._hash[id], i++, this._hash);
+		}
+		return this;	// dijit.WidgetSet
+	},
+
+	filter: function(/*Function*/ filter, /* Object? */thisObj){
+		// 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. Is passed the widget
+		//		reference and the pseudo-index in the object.
+		//
+		// thisObj: Object?
+		//		Option scope to use for the filter function.
+		//
+		// example:
+		//		Arbitrary: select the odd widgets in this list
+		//		|	dijit.registry.filter(function(w, i){
+		//		|		return i % 2 == 0;
+		//		|	}).forEach(function(w){ /* odd ones */ });
+
+		thisObj = thisObj || dojo.global;
+		var res = new dijit.WidgetSet(), i = 0, id;
+		for(id in this._hash){
+			var w = this._hash[id];
+			if(filter.call(thisObj, w, i++, this._hash)){
+				res.add(w);
+			}
+		}
+		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`
+		//
+		// cls: String
+		//		The Class to scan for. Full dot-notated string.
+		//
+		// example:
+		//		Find all `dijit.TitlePane`s in a page:
+		//		|	dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); });
+
+		var res = new dijit.WidgetSet(), id, widget;
+		for(id in this._hash){
+			widget = this._hash[id];
+			if(widget.declaredClass == cls){
+				res.add(widget);
+			}
+		 }
+		 return res; // dijit.WidgetSet
+},
+
+	toArray: function(){
+		// summary:
+		//		Convert this WidgetSet into a true Array
+		//
+		// example:
+		//		Work with the widget .domNodes in a real Array
+		//		|	dojo.map(dijit.registry.toArray(), function(w){ return w.domNode; });
+
+		var ar = [];
+		for(var id in this._hash){
+			ar.push(this._hash[id]);
+		}
+		return ar;	// dijit._Widget[]
+},
+
+	map: function(/* Function */func, /* Object? */thisObj){
+		// summary:
+		//		Create a new Array from this WidgetSet, following the same rules as `dojo.map`
+		// example:
+		//		|	var nodes = dijit.registry.map(function(w){ return w.domNode; });
+		//
+		// returns:
+		//		A new array of the returned values.
+		return dojo.map(this.toArray(), func, thisObj); // Array
+	},
+
+	every: function(func, thisObj){
+		// summary:
+		// 		A synthetic clone of `dojo.every` acting explicitly on this WidgetSet
+		//
+		// func: Function
+		//		A callback function run for every widget in this list. Exits loop
+		//		when the first false return is encountered.
+		//
+		// thisObj: Object?
+		//		Optional scope parameter to use for the callback
+
+		thisObj = thisObj || dojo.global;
+		var x = 0, i;
+		for(i in this._hash){
+			if(!func.call(thisObj, this._hash[i], x++, this._hash)){
+				return false; // Boolean
+			}
+		}
+		return true; // Boolean
+	},
+
+	some: function(func, thisObj){
+		// summary:
+		// 		A synthetic clone of `dojo.some` acting explictly on this WidgetSet
+		//
+		// func: Function
+		//		A callback function run for every widget in this list. Exits loop
+		//		when the first true return is encountered.
+		//
+		// thisObj: Object?
+		//		Optional scope parameter to use for the callback
+
+		thisObj = thisObj || dojo.global;
+		var x = 0, i;
+		for(i in this._hash){
+			if(func.call(thisObj, this._hash[i], x++, this._hash)){
+				return true; // Boolean
+			}
+		}
+		return false; // Boolean
+	}
 
-if(!dojo._hasResource["dijit._base.manager"]){
-dojo._hasResource["dijit._base.manager"]=true;
-dojo.provide("dijit._base.manager");
-dojo.declare("dijit.WidgetSet",null,{constructor:function(){
-this._hash={};
-this.length=0;
-},add:function(_1){
-if(this._hash[_1.id]){
-throw new Error("Tried to register widget with id=="+_1.id+" but that id is already registered");
-}
-this._hash[_1.id]=_1;
-this.length++;
-},remove:function(id){
-if(this._hash[id]){
-delete this._hash[id];
-this.length--;
-}
-},forEach:function(_2,_3){
-_3=_3||dojo.global;
-var i=0,id;
-for(id in this._hash){
-_2.call(_3,this._hash[id],i++,this._hash);
-}
-return this;
-},filter:function(_4,_5){
-_5=_5||dojo.global;
-var _6=new dijit.WidgetSet(),i=0,id;
-for(id in this._hash){
-var w=this._hash[id];
-if(_4.call(_5,w,i++,this._hash)){
-_6.add(w);
-}
-}
-return _6;
-},byId:function(id){
-return this._hash[id];
-},byClass:function(_7){
-var _8=new dijit.WidgetSet(),id,_9;
-for(id in this._hash){
-_9=this._hash[id];
-if(_9.declaredClass==_7){
-_8.add(_9);
-}
-}
-return _8;
-},toArray:function(){
-var ar=[];
-for(var id in this._hash){
-ar.push(this._hash[id]);
-}
-return ar;
-},map:function(_a,_b){
-return dojo.map(this.toArray(),_a,_b);
-},every:function(_c,_d){
-_d=_d||dojo.global;
-var x=0,i;
-for(i in this._hash){
-if(!_c.call(_d,this._hash[i],x++,this._hash)){
-return false;
-}
-}
-return true;
-},some:function(_e,_f){
-_f=_f||dojo.global;
-var x=0,i;
-for(i in this._hash){
-if(_e.call(_f,this._hash[i],x++,this._hash)){
-return true;
-}
-}
-return false;
-}});
-dijit.registry=new dijit.WidgetSet();
-dijit._widgetTypeCtr={};
-dijit.getUniqueId=function(_10){
-var id;
-do{
-id=_10+"_"+(_10 in dijit._widgetTypeCtr?++dijit._widgetTypeCtr[_10]:dijit._widgetTypeCtr[_10]=0);
-}while(dijit.byId(id));
-return dijit._scopeName=="dijit"?id:dijit._scopeName+"_"+id;
-};
-dijit.findWidgets=function(_11){
-var _12=[];
-function _13(_14){
-for(var _15=_14.firstChild;_15;_15=_15.nextSibling){
-if(_15.nodeType==1){
-var _16=_15.getAttribute("widgetId");
-if(_16){
-var _17=dijit.byId(_16);
-_12.push(_17);
-}else{
-_13(_15);
-}
-}
-}
-};
-_13(_11);
-return _12;
-};
-dijit._destroyAll=function(){
-dijit._curFocus=null;
-dijit._prevFocus=null;
-dijit._activeStack=[];
-dojo.forEach(dijit.findWidgets(dojo.body()),function(_18){
-if(!_18._destroyed){
-if(_18.destroyRecursive){
-_18.destroyRecursive();
-}else{
-if(_18.destroy){
-_18.destroy();
-}
-}
-}
-});
-};
-if(dojo.isIE){
-dojo.addOnWindowUnload(function(){
-dijit._destroyAll();
-});
-}
-dijit.byId=function(id){
-return typeof id=="string"?dijit.registry._hash[id]:id;
-};
-dijit.byNode=function(_19){
-return dijit.registry.byId(_19.getAttribute("widgetId"));
-};
-dijit.getEnclosingWidget=function(_1a){
-while(_1a){
-var id=_1a.getAttribute&&_1a.getAttribute("widgetId");
-if(id){
-return dijit.byId(id);
-}
-_1a=_1a.parentNode;
-}
-return null;
-};
-dijit._isElementShown=function(_1b){
-var _1c=dojo.style(_1b);
-return (_1c.visibility!="hidden")&&(_1c.visibility!="collapsed")&&(_1c.display!="none")&&(dojo.attr(_1b,"type")!="hidden");
-};
-dijit.isTabNavigable=function(_1d){
-if(dojo.attr(_1d,"disabled")){
-return false;
-}else{
-if(dojo.hasAttr(_1d,"tabIndex")){
-return dojo.attr(_1d,"tabIndex")>=0;
-}else{
-switch(_1d.nodeName.toLowerCase()){
-case "a":
-return dojo.hasAttr(_1d,"href");
-case "area":
-case "button":
-case "input":
-case "object":
-case "select":
-case "textarea":
-return true;
-case "iframe":
-if(dojo.isMoz){
-return _1d.contentDocument.designMode=="on";
-}else{
-if(dojo.isWebKit){
-var doc=_1d.contentDocument,_1e=doc&&doc.body;
-return _1e&&_1e.contentEditable=="true";
-}else{
-try{
-doc=_1d.contentWindow.document;
-_1e=doc&&doc.body;
-return _1e&&_1e.firstChild&&_1e.firstChild.contentEditable=="true";
-}
-catch(e){
-return false;
-}
-}
-}
-default:
-return _1d.contentEditable=="true";
-}
-}
-}
-};
-dijit._getTabNavigable=function(_1f){
-var _20,_21,_22,_23,_24,_25;
-var _26=function(_27){
-dojo.query("> *",_27).forEach(function(_28){
-var _29=dijit._isElementShown(_28);
-if(_29&&dijit.isTabNavigable(_28)){
-var _2a=dojo.attr(_28,"tabIndex");
-if(!dojo.hasAttr(_28,"tabIndex")||_2a==0){
-if(!_20){
-_20=_28;
-}
-_21=_28;
-}else{
-if(_2a>0){
-if(!_22||_2a<_23){
-_23=_2a;
-_22=_28;
-}
-if(!_24||_2a>=_25){
-_25=_2a;
-_24=_28;
-}
-}
-}
-}
-if(_29&&_28.nodeName.toUpperCase()!="SELECT"){
-_26(_28);
-}
 });
-};
-if(dijit._isElementShown(_1f)){
-_26(_1f);
-}
-return {first:_20,last:_21,lowest:_22,highest:_24};
-};
-dijit.getFirstInTabbingOrder=function(_2b){
-var _2c=dijit._getTabNavigable(dojo.byId(_2b));
-return _2c.lowest?_2c.lowest:_2c.first;
-};
-dijit.getLastInTabbingOrder=function(_2d){
-var _2e=dijit._getTabNavigable(dojo.byId(_2d));
-return _2e.last?_2e.last:_2e.highest;
-};
-dijit.defaultDuration=dojo.config["defaultDuration"]||200;
-}
+
+(function(){
+
+	/*=====
+	dijit.registry = {
+		// summary:
+		//		A list of widgets on a page.
+		// description:
+		//		Is an instance of `dijit.WidgetSet`
+	};
+	=====*/
+	dijit.registry = new dijit.WidgetSet();
+
+	var hash = dijit.registry._hash,
+		attr = dojo.attr,
+		hasAttr = dojo.hasAttr,
+		style = dojo.style;
+
+	dijit.byId = function(/*String|dijit._Widget*/ id){
+		// summary:
+		//		Returns a widget by it's id, or if passed a widget, no-op (like dojo.byId())
+		return typeof id == "string" ? hash[id] : id; // dijit._Widget
+	};
+
+	var _widgetTypeCtr = {};
+	dijit.getUniqueId = function(/*String*/widgetType){
+		// summary:
+		//		Generates a unique id for a given widgetType
+	
+		var id;
+		do{
+			id = widgetType + "_" +
+				(widgetType in _widgetTypeCtr ?
+					++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0);
+		}while(hash[id]);
+		return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
+	};
+	
+	dijit.findWidgets = function(/*DomNode*/ root){
+		// summary:
+		//		Search subtree under root returning widgets found.
+		//		Doesn't search for nested widgets (ie, widgets inside other widgets).
+	
+		var outAry = [];
+	
+		function getChildrenHelper(root){
+			for(var node = root.firstChild; node; node = node.nextSibling){
+				if(node.nodeType == 1){
+					var widgetId = node.getAttribute("widgetId");
+					if(widgetId){
+						outAry.push(hash[widgetId]);
+					}else{
+						getChildrenHelper(node);
+					}
+				}
+			}
+		}
+	
+		getChildrenHelper(root);
+		return outAry;
+	};
+	
+	dijit._destroyAll = function(){
+		// summary:
+		//		Code to destroy all widgets and do other cleanup on page unload
+	
+		// Clean up focus manager lingering references to widgets and nodes
+		dijit._curFocus = null;
+		dijit._prevFocus = null;
+		dijit._activeStack = [];
+	
+		// Destroy all the widgets, top down
+		dojo.forEach(dijit.findWidgets(dojo.body()), function(widget){
+			// Avoid double destroy of widgets like Menu that are attached to <body>
+			// even though they are logically children of other widgets.
+			if(!widget._destroyed){
+				if(widget.destroyRecursive){
+					widget.destroyRecursive();
+				}else if(widget.destroy){
+					widget.destroy();
+				}
+			}
+		});
+	};
+	
+	if(dojo.isIE){
+		// Only run _destroyAll() 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(){
+			dijit._destroyAll();
+		});
+	}
+	
+	dijit.byNode = function(/*DOMNode*/ node){
+		// summary:
+		//		Returns the widget corresponding to the given DOMNode
+		return hash[node.getAttribute("widgetId")]; // dijit._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){
+			var id = node.getAttribute && node.getAttribute("widgetId");
+			if(id){
+				return hash[id];
+			}
+			node = node.parentNode;
+		}
+		return null;
+	};
+
+	var shown = (dijit._isElementShown = function(/*Element*/ elem){
+		var s = style(elem);
+		return (s.visibility != "hidden")
+			&& (s.visibility != "collapsed")
+			&& (s.display != "none")
+			&& (attr(elem, "type") != "hidden");
+	});
+	
+	dijit.hasDefaultTabStop = function(/*Element*/ elem){
+		// summary:
+		//		Tests if element is tab-navigable even without an explicit tabIndex setting
+	
+		// No explicit tabIndex setting, need to investigate node type
+		switch(elem.nodeName.toLowerCase()){
+			case "a":
+				// An <a> w/out a tabindex is only navigable if it has an href
+				return hasAttr(elem, "href");
+			case "area":
+			case "button":
+			case "input":
+			case "object":
+			case "select":
+			case "textarea":
+				// These are navigable by default
+				return true;
+			case "iframe":
+				// If it's an editor <iframe> then it's tab navigable.
+				//TODO: feature detect "designMode" in elem.contentDocument?
+				if(dojo.isMoz){
+					try{
+						return elem.contentDocument.designMode == "on";
+					}catch(err){
+						return false;
+					}
+				}else if(dojo.isWebKit){
+					var doc = elem.contentDocument,
+						body = doc && doc.body;
+					return body && body.contentEditable == 'true';
+				}else{
+					// contentWindow.document isn't accessible within IE7/8
+					// if the iframe.src points to a foreign url and this
+					// page contains an element, that could get focus
+					try{
+						doc = elem.contentWindow.document;
+						body = doc && doc.body;
+						return body && body.firstChild && body.firstChild.contentEditable == 'true';
+					}catch(e){
+						return false;
+					}
+				}
+			default:
+				return elem.contentEditable == 'true';
+		}
+	};
+	
+	var isTabNavigable = (dijit.isTabNavigable = function(/*Element*/ elem){
+		// summary:
+		//		Tests if an element is tab-navigable
+	
+		// TODO: convert (and rename method) to return effective tabIndex; will save time in _getTabNavigable()
+		if(attr(elem, "disabled")){
+			return false;
+		}else if(hasAttr(elem, "tabIndex")){
+			// Explicit tab index setting
+			return attr(elem, "tabIndex") >= 0; // boolean
+		}else{
+			// No explicit tabIndex setting, so depends on node type
+			return dijit.hasDefaultTabStop(elem);
+		}
+	});
+
+	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){
+				// Skip hidden elements, and also non-HTML elements (those in custom namespaces) in IE,
+				// since show() invokes getAttribute("type"), which crash on VML nodes in IE.
+				if((dojo.isIE && child.scopeName!=="HTML") || !shown(child)){
+					return;
+				}
+
+				if(isTabNavigable(child)){
+					var tabindex = attr(child, "tabIndex");
+					if(!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(child.nodeName.toUpperCase() != 'SELECT'){
+					walkTree(child);
+				}
+			});
+		};
+		if(shown(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: 200
+	});
+	=====*/
+	
+	dijit.defaultDuration = dojo.config["defaultDuration"] || 200;
+
+})();
diff --git a/dijit/_base/place.js b/dijit/_base/place.js
index 55190ff..c357682 100644
--- a/dijit/_base/place.js
+++ b/dijit/_base/place.js
@@ -1,135 +1,334 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._base.place"]){
-dojo._hasResource["dijit._base.place"]=true;
 dojo.provide("dijit._base.place");
+
+dojo.require("dojo.window");
 dojo.require("dojo.AdapterRegistry");
-dijit.getViewport=function(){
-var _1=(dojo.doc.compatMode=="BackCompat")?dojo.body():dojo.doc.documentElement;
-var _2=dojo._docScroll();
-return {w:_1.clientWidth,h:_1.clientHeight,l:_2.x,t:_2.y};
-};
-dijit.placeOnScreen=function(_3,_4,_5,_6){
-var _7=dojo.map(_5,function(_8){
-var c={corner:_8,pos:{x:_4.x,y:_4.y}};
-if(_6){
-c.pos.x+=_8.charAt(1)=="L"?_6.x:-_6.x;
-c.pos.y+=_8.charAt(0)=="T"?_6.y:-_6.y;
-}
-return c;
-});
-return dijit._place(_3,_7);
+
+
+dijit.getViewport = function(){
+	// summary:
+	//		Returns the dimensions and scroll position of the viewable area of a browser window
+
+	return dojo.window.getBox();
 };
-dijit._place=function(_9,_a,_b){
-var _c=dijit.getViewport();
-if(!_9.parentNode||String(_9.parentNode.tagName).toLowerCase()!="body"){
-dojo.body().appendChild(_9);
-}
-var _d=null;
-dojo.some(_a,function(_e){
-var _f=_e.corner;
-var pos=_e.pos;
-if(_b){
-_b(_9,_e.aroundCorner,_f);
+
+/*=====
+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;
 }
-var _10=_9.style;
-var _11=_10.display;
-var _12=_10.visibility;
-_10.visibility="hidden";
-_10.display="";
-var mb=dojo.marginBox(_9);
-_10.display=_11;
-_10.visibility=_12;
-var _13=Math.max(_c.l,_f.charAt(1)=="L"?pos.x:(pos.x-mb.w)),_14=Math.max(_c.t,_f.charAt(0)=="T"?pos.y:(pos.y-mb.h)),_15=Math.min(_c.l+_c.w,_f.charAt(1)=="L"?(_13+mb.w):pos.x),_16=Math.min(_c.t+_c.h,_f.charAt(0)=="T"?(_14+mb.h):pos.y),_17=_15-_13,_18=_16-_14,_19=(mb.w-_17)+(mb.h-_18);
-if(_d==null||_19<_d.overflow){
-_d={corner:_f,aroundCorner:_e.aroundCorner,x:_13,y:_14,w:_17,h:_18,overflow:_19};
+=====*/
+
+
+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);
 }
-return !_19;
-});
-_9.style.left=_d.x+"px";
-_9.style.top=_d.y+"px";
-if(_d.overflow&&_b){
-_b(_9,_d.aroundCorner,_d.corner);
+
+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 = dojo.window.getBox();
+
+	// 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 = Math.max(view.l, corner.charAt(1) == 'L' ? pos.x : (pos.x - mb.w)),
+			startY = Math.max(view.t, corner.charAt(0) == 'T' ? pos.y : (pos.y - mb.h)),
+			endX = Math.min(view.l + view.w, corner.charAt(1) == 'L' ? (startX + mb.w) : pos.x),
+			endY = Math.min(view.t + view.h, corner.charAt(0) == 'T' ? (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;
 }
-return _d;
-};
-dijit.placeOnScreenAroundNode=function(_1a,_1b,_1c,_1d){
-_1b=dojo.byId(_1b);
-var _1e=_1b.style.display;
-_1b.style.display="";
-var _1f=dojo.position(_1b,true);
-_1b.style.display=_1e;
-return dijit._placeOnScreenAroundRect(_1a,_1f.x,_1f.y,_1f.w,_1f.h,_1c,_1d);
-};
-dijit.placeOnScreenAroundRectangle=function(_20,_21,_22,_23){
-return dijit._placeOnScreenAroundRect(_20,_21.x,_21.y,_21.width,_21.height,_22,_23);
+
+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 aroundNodePos = dojo.position(aroundNode, true);
+	aroundNode.style.display=oldDisplay;
+
+	// place the node around the calculated rectangle
+	return dijit._placeOnScreenAroundRect(node,
+		aroundNodePos.x, aroundNodePos.y, aroundNodePos.w, aroundNodePos.h,	// rectangle
+		aroundCorners, layoutNode);
 };
-dijit._placeOnScreenAroundRect=function(_24,x,y,_25,_26,_27,_28){
-var _29=[];
-for(var _2a in _27){
-_29.push({aroundCorner:_2a,corner:_27[_2a],pos:{x:x+(_2a.charAt(1)=="L"?0:_25),y:y+(_2a.charAt(0)=="T"?0:_26)}});
+
+/*=====
+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
+
+	this.x = x;
+	this.y = y;
+	this.width = width;
+	this.height = height;
 }
-return dijit._place(_24,_29,_28);
+=====*/
+
+
+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.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(_2b,_2c,_2d,_2e){
-return dijit.placementRegistry.match.apply(dijit.placementRegistry,arguments);
+
+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.getPopupAlignment=function(_2f,_30){
-var _31={};
-dojo.forEach(_2f,function(pos){
-switch(pos){
-case "after":
-_31[_30?"BR":"BL"]=_30?"BL":"BR";
-break;
-case "before":
-_31[_30?"BL":"BR"]=_30?"BR":"BL";
-break;
-case "below":
-_31[_30?"BL":"BR"]=_30?"TL":"TR";
-_31[_30?"BR":"BL"]=_30?"TR":"TL";
-break;
-case "above":
-default:
-_31[_30?"TL":"TR"]=_30?"BL":"BR";
-_31[_30?"TR":"TL"]=_30?"BR":"BL";
-break;
-}
-});
-return _31;
+
+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);
 };
-dijit.getPopupAroundAlignment=function(_32,_33){
-var _34={};
-dojo.forEach(_32,function(pos){
-switch(pos){
-case "after":
-_34[_33?"BR":"BL"]=_33?"BL":"BR";
-break;
-case "before":
-_34[_33?"BL":"BR"]=_33?"BR":"BL";
-break;
-case "below":
-_34[_33?"BL":"BR"]=_33?"TL":"TR";
-_34[_33?"BR":"BL"]=_33?"TR":"TL";
-break;
-case "above":
-default:
-_34[_33?"TL":"TR"]=_33?"BL":"BR";
-_34[_33?"TR":"TL"]=_33?"BR":"BL";
-break;
-}
-});
-return _34;
+
+dijit.getPopupAroundAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
+	// summary:
+	//		Transforms the passed array of preferred positions into a format suitable for passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
+	//
+	// position: String[]
+	//		This variable controls the position of the drop down.
+	//		It's an array of strings with the following values:
+	//
+	//			* before: places drop down to the left of the target node/widget, or to the right in
+	//			  the case of RTL scripts like Hebrew and Arabic
+	//			* after: places drop down to the right of the target node/widget, or to the left in
+	//			  the case of RTL scripts like Hebrew and Arabic
+	//			* above: drop down goes above target node
+	//			* below: drop down goes below target node
+	//
+	//		The list is positions is tried, in order, until a position is found where the drop down fits
+	//		within the viewport.
+	//
+	// leftToRight: Boolean
+	//		Whether the popup will be displaying in leftToRight mode.
+	//
+	var align = {};
+	dojo.forEach(position, function(pos){
+		switch(pos){
+			case "after":
+				align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
+				break;
+			case "before":
+				align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
+				break;
+			case "below":
+				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
+				align[leftToRight ? "BL" : "BR"] = leftToRight ? "TL" : "TR";
+				align[leftToRight ? "BR" : "BL"] = leftToRight ? "TR" : "TL";
+				break;
+			case "above":
+			default:
+				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
+				align[leftToRight ? "TL" : "TR"] = leftToRight ? "BL" : "BR";
+				align[leftToRight ? "TR" : "TL"] = leftToRight ? "BR" : "BL";
+				break;
+		}
+	});
+	return align;
 };
-}
diff --git a/dijit/_base/popup.js b/dijit/_base/popup.js
index 9b6a197..80b42fe 100644
--- a/dijit/_base/popup.js
+++ b/dijit/_base/popup.js
@@ -1,166 +1,366 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._base.popup"]){
-dojo._hasResource["dijit._base.popup"]=true;
 dojo.provide("dijit._base.popup");
+
 dojo.require("dijit._base.focus");
 dojo.require("dijit._base.place");
 dojo.require("dijit._base.window");
-dijit.popup=new function(){
-var _1=[],_2=1000,_3=1;
-this.moveOffScreen=function(_4){
-var s=_4.style;
-s.visibility="hidden";
-s.position="absolute";
-s.top="-9999px";
-if(s.display=="none"){
-s.display="";
-}
-dojo.body().appendChild(_4);
-};
-var _5=function(){
-for(var pi=_1.length-1;pi>0&&_1[pi].parent===_1[pi-1].widget;pi--){
-}
-return _1[pi];
-};
-var _6=[];
-this.open=function(_7){
-var _8=_7.popup,_9=_7.orient||(dojo._isBodyLtr()?{"BL":"TL","BR":"TR","TL":"BL","TR":"BR"}:{"BR":"TR","BL":"TL","TR":"BR","TL":"BL"}),_a=_7.around,id=(_7.around&&_7.around.id)?(_7.around.id+"_dropdown"):("popup_"+_3++);
-var _b=_6.pop(),_c,_d;
-if(!_b){
-_c=dojo.create("div",{"class":"dijitPopup"},dojo.body());
-dijit.setWaiRole(_c,"presentation");
-}else{
-_c=_b[0];
-_d=_b[1];
-}
-dojo.attr(_c,{id:id,style:{zIndex:_2+_1.length,visibility:"hidden",top:"-9999px"},dijitPopupParent:_7.parent?_7.parent.id:""});
-var s=_8.domNode.style;
-s.display="";
-s.visibility="";
-s.position="";
-s.top="0px";
-_c.appendChild(_8.domNode);
-if(!_d){
-_d=new dijit.BackgroundIframe(_c);
-}else{
-_d.resize(_c);
-}
-var _e=_a?dijit.placeOnScreenAroundElement(_c,_a,_9,_8.orient?dojo.hitch(_8,"orient"):null):dijit.placeOnScreen(_c,_7,_9=="R"?["TR","BR","TL","BL"]:["TL","BL","TR","BR"],_7.padding);
-_c.style.visibility="visible";
-var _f=[];
-_f.push(dojo.connect(_c,"onkeypress",this,function(evt){
-if(evt.charOrCode==dojo.keys.ESCAPE&&_7.onCancel){
-dojo.stopEvent(evt);
-_7.onCancel();
-}else{
-if(evt.charOrCode===dojo.keys.TAB){
-dojo.stopEvent(evt);
-var _10=_5();
-if(_10&&_10.onCancel){
-_10.onCancel();
-}
-}
-}
-}));
-if(_8.onCancel){
-_f.push(dojo.connect(_8,"onCancel",_7.onCancel));
-}
-_f.push(dojo.connect(_8,_8.onExecute?"onExecute":"onChange",function(){
-var _11=_5();
-if(_11&&_11.onExecute){
-_11.onExecute();
-}
-}));
-_1.push({wrapper:_c,iframe:_d,widget:_8,parent:_7.parent,onExecute:_7.onExecute,onCancel:_7.onCancel,onClose:_7.onClose,handlers:_f});
-if(_8.onOpen){
-_8.onOpen(_e);
-}
-return _e;
-};
-this.close=function(_12){
-while(dojo.some(_1,function(_13){
-return _13.widget==_12;
-})){
-var top=_1.pop(),_14=top.wrapper,_15=top.iframe,_16=top.widget,_17=top.onClose;
-if(_16.onClose){
-_16.onClose();
-}
-dojo.forEach(top.handlers,dojo.disconnect);
-if(_16&&_16.domNode){
-this.moveOffScreen(_16.domNode);
-}
-_14.style.top="-9999px";
-_14.style.visibility="hidden";
-_6.push([_14,_15]);
-if(_17){
-_17();
-}
+
+/*=====
+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.  (Specify 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;
 }
+=====*/
+
+dijit.popup = {
+	// summary:
+	//		This singleton is used to show/hide widgets as popups.
+
+	// _stack: dijit._Widget[]
+	//		Stack of currently popped up widgets.
+	//		(someone opened _stack[0], and then it opened _stack[1], etc.)
+	_stack: [],
+	
+	// _beginZIndex: Number
+	//		Z-index of the first popup.   (If first popup opens other
+	//		popups they get a higher z-index.)
+	_beginZIndex: 1000,
+
+	_idGen: 1,
+
+	moveOffScreen: function(/*DomNode*/ node){
+		// summary:
+		//		Initialization for nodes that will be used as popups
+		//
+		// description:
+		//		Puts node inside a wrapper <div>, and
+		//		positions wrapper div 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 wrapper = node.parentNode;
+
+		// Create a wrapper widget for when this node (in the future) will be used as a popup.
+		// This is done early because of IE bugs where creating/moving DOM nodes causes focus
+		// to go wonky, see tests/robot/Toolbar.html to reproduce
+		if(!wrapper || !dojo.hasClass(wrapper, "dijitPopup")){
+			wrapper = dojo.create("div",{
+				"class":"dijitPopup",
+				style:{
+					visibility:"hidden",
+					top: "-9999px"
+				}
+			}, dojo.body());
+			dijit.setWaiRole(wrapper, "presentation");
+			wrapper.appendChild(node);
+		}
+
+
+		var s = node.style;
+		s.display = "";
+		s.visibility = "";
+		s.position = "";
+		s.top = "0px";
+
+		dojo.style(wrapper, {
+			visibility: "hidden",
+			// prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
+			top: "-9999px"
+		});
+	},
+
+	getTopPopup: function(){
+		// summary:
+		//		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 stack = this._stack;
+		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];
+	},
+
+	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 stack = this._stack,
+			widget = args.popup,
+			orient = args.orient || (
+				(args.parent ? args.parent.isLeftToRight() : dojo._isBodyLtr()) ?
+				{'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'} :
+				{'BR':'TR', 'BL':'TL', 'TR':'BR', 'TL':'BL'}
+			),
+			around = args.around,
+			id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+this._idGen++);
+
+
+		// The wrapper may have already been created, but in case it wasn't, create here
+		var wrapper = widget.domNode.parentNode;
+		if(!wrapper || !dojo.hasClass(wrapper, "dijitPopup")){
+			this.moveOffScreen(widget.domNode);
+			wrapper = widget.domNode.parentNode;
+		}
+
+		dojo.attr(wrapper, {
+			id: id,
+			style: {
+				zIndex: this._beginZIndex + stack.length
+			},
+			"class": "dijitPopup " + (widget.baseClass || widget["class"] || "").split(" ")[0] +"Popup",
+			dijitPopupParent: args.parent ? args.parent.id : ""
+		});
+
+		if(dojo.isIE || dojo.isMoz){
+			var iframe = wrapper.childNodes[1];
+			if(!iframe){
+				iframe = new dijit.BackgroundIframe(wrapper);
+			}
+		}
+
+		// position the wrapper node and make it visible
+		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";
+		widget.domNode.style.visibility = "visible";	// counteract effects from _HasDropDown
+
+		var handlers = [];
+
+		// 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 = this.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", args.onCancel));
+		}
+
+		handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", this, function(){
+			var topPopup = this.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){
+			// TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here)
+			widget.onOpen(best);
+		}
+
+		return best;
+	},
+
+	close: function(/*dijit._Widget*/ popup){
+		// summary:
+		//		Close specified popup and any popups that it parented
+
+		var stack = this._stack;
+
+		// Basically work backwards from the top of the stack closing popups
+		// until we hit the specified popup, but IIRC there was some issue where closing
+		// a popup would cause others to close too.  Thus if we are trying to close B in [A,B,C]
+		// closing C might close B indirectly and then the while() condition will run where stack==[A]...
+		// so the while condition is constructed defensively.
+		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){
+				// TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here)
+				widget.onClose();
+			}
+			dojo.forEach(top.handlers, dojo.disconnect);
+
+			// Move the widget plus it's wrapper off screen, unless it has already been destroyed in above onClose() etc.
+			if(widget && widget.domNode){
+				this.moveOffScreen(widget.domNode);
+			}else{
+				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";
+				dojo.style(iframe, "opacity", 0.1);
+			}
+			iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didnt work.
+			dijit.setWaiRole(iframe,"presentation");
+		}
+		return iframe;
+	};
+
+	this.push = function(iframe){
+		iframe.style.display="none";
+		queue.push(iframe);
+	}
 }();
-dijit._frames=new function(){
-var _18=[];
-this.pop=function(){
-var _19;
-if(_18.length){
-_19=_18.pop();
-_19.style.display="";
-}else{
-if(dojo.isIE){
-var _1a=dojo.config["dojoBlankHtmlUrl"]||(dojo.moduleUrl("dojo","resources/blank.html")+"")||"javascript:\"\"";
-var _1b="<iframe src='"+_1a+"'"+" style='position: absolute; left: 0px; top: 0px;"+"z-index: -1; filter:Alpha(Opacity=\"0\");'>";
-_19=dojo.doc.createElement(_1b);
-}else{
-_19=dojo.create("iframe");
-_19.src="javascript:\"\"";
-_19.className="dijitBackgroundIframe";
-dojo.style(_19,"opacity",0.1);
-}
-_19.tabIndex=-1;
-}
-return _19;
-};
-this.push=function(_1c){
-_1c.style.display="none";
-_18.push(_1c);
+
+
+dijit.BackgroundIframe = function(/* DomNode */node){
+	// summary:
+	//		For IE/FF 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 || dojo.isMoz){
+		var iframe = dijit._frames.pop();
+		node.appendChild(iframe);
+		if(dojo.isIE<7){
+			this.resize(node);
+			this._conn = dojo.connect(node, 'onresize', this, function(){
+				this.resize(node);
+			});
+		}else{
+			dojo.style(iframe, {
+				width: '100%',
+				height: '100%'
+			});
+		}
+		this.iframe = iframe;
+	}
 };
-}();
-dijit.BackgroundIframe=function(_1d){
-if(!_1d.id){
-throw new Error("no id");
-}
-if(dojo.isIE||dojo.isMoz){
-var _1e=dijit._frames.pop();
-_1d.appendChild(_1e);
-if(dojo.isIE<7){
-this.resize(_1d);
-this._conn=dojo.connect(_1d,"onresize",this,function(){
-this.resize(_1d);
+
+dojo.extend(dijit.BackgroundIframe, {
+	resize: function(node){
+		// summary:
+		// 		resize the iframe so its the same size as node
+		// description:
+		//		this function is a no-op in all browsers except
+		//		IE6, which does not support 100% width/height 
+		//		of absolute positioned iframes
+		if(this.iframe && dojo.isIE<7){
+			dojo.style(this.iframe, {
+				width: node.offsetWidth + 'px',
+				height: node.offsetHeight + 'px'
+			});
+		}
+	},
+	destroy: function(){
+		// summary:
+		//		destroy the iframe
+		if(this._conn){
+			dojo.disconnect(this._conn);
+			this._conn = null;
+		}
+		if(this.iframe){
+			dijit._frames.push(this.iframe);
+			delete this.iframe;
+		}
+	}
 });
-}else{
-dojo.style(_1e,{width:"100%",height:"100%"});
-}
-this.iframe=_1e;
-}
-};
-dojo.extend(dijit.BackgroundIframe,{resize:function(_1f){
-if(this.iframe&&dojo.isIE<7){
-dojo.style(this.iframe,{width:_1f.offsetWidth+"px",height:_1f.offsetHeight+"px"});
-}
-},destroy:function(){
-if(this._conn){
-dojo.disconnect(this._conn);
-this._conn=null;
-}
-if(this.iframe){
-dijit._frames.push(this.iframe);
-delete this.iframe;
-}
-}});
-}
diff --git a/dijit/_base/scroll.js b/dijit/_base/scroll.js
index 398d15f..651d5d1 100644
--- a/dijit/_base/scroll.js
+++ b/dijit/_base/scroll.js
@@ -1,100 +1,11 @@
-/*
-	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
-*/
+dojo.provide("dijit._base.scroll");
 
+dojo.require("dojo.window");
 
-if(!dojo._hasResource["dijit._base.scroll"]){
-dojo._hasResource["dijit._base.scroll"]=true;
-dojo.provide("dijit._base.scroll");
-dijit.scrollIntoView=function(_1,_2){
-try{
-_1=dojo.byId(_1);
-var _3=_1.ownerDocument||dojo.doc,_4=_3.body||dojo.body(),_5=_3.documentElement||_4.parentNode,_6=dojo.isIE,_7=dojo.isWebKit;
-if((!(dojo.isMoz||_6||_7)||_1==_4||_1==_5)&&(typeof _1.scrollIntoView!="undefined")){
-_1.scrollIntoView(false);
-return;
-}
-var _8=_3.compatMode=="BackCompat",_9=_8?_4:_5,_a=_7?_4:_9,_b=_9.clientWidth,_c=_9.clientHeight,_d=!dojo._isBodyLtr(),_e=_2||dojo.position(_1),el=_1.parentNode,_f=function(el){
-return ((_6<=6||(_6&&_8))?false:(dojo.style(el,"position").toLowerCase()=="fixed"));
-};
-if(_f(_1)){
-return;
-}
-while(el){
-if(el==_4){
-el=_a;
-}
-var _10=dojo.position(el),_11=_f(el);
-with(_10){
-if(el==_a){
-w=_b,h=_c;
-if(_a==_5&&_6&&_d){
-x+=_a.offsetWidth-w;
-}
-if(x<0||!_6){
-x=0;
-}
-if(y<0||!_6){
-y=0;
-}
-}else{
-var pb=dojo._getPadBorderExtents(el);
-w-=pb.w;
-h-=pb.h;
-x+=pb.l;
-y+=pb.t;
-}
-with(el){
-if(el!=_a){
-var _12=clientWidth,_13=w-_12;
-if(_12>0&&_13>0){
-w=_12;
-if(_6&&_d){
-x+=_13;
-}
-}
-_12=clientHeight;
-_13=h-_12;
-if(_12>0&&_13>0){
-h=_12;
-}
-}
-if(_11){
-if(y<0){
-h+=y,y=0;
-}
-if(x<0){
-w+=x,x=0;
-}
-if(y+h>_c){
-h=_c-y;
-}
-if(x+w>_b){
-w=_b-x;
-}
-}
-var l=_e.x-x,t=_e.y-Math.max(y,0),r=l+_e.w-w,bot=t+_e.h-h;
-if(r*l>0){
-var s=Math[l<0?"max":"min"](l,r);
-_e.x+=scrollLeft;
-scrollLeft+=(_6>=8&&!_8&&_d)?-s:s;
-_e.x-=scrollLeft;
-}
-if(bot*t>0){
-_e.y+=scrollTop;
-scrollTop+=Math[t<0?"max":"min"](t,bot);
-_e.y-=scrollTop;
-}
-}
-}
-el=(el!=_a)&&!_11&&el.parentNode;
-}
-}
-catch(error){
-console.error("scrollIntoView: "+error);
-_1.scrollIntoView(false);
-}
+dijit.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
+	// summary:
+	//		Scroll the passed node into view, if it is not already.
+	//		Deprecated, use `dojo.window.scrollIntoView` instead.
+	
+	dojo.window.scrollIntoView(node, pos);
 };
-}
diff --git a/dijit/_base/sniff.js b/dijit/_base/sniff.js
index 1d2de9d..e6db29c 100644
--- a/dijit/_base/sniff.js
+++ b/dijit/_base/sniff.js
@@ -1,34 +1,10 @@
-/*
-	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
-*/
+// summary:
+//		Applies pre-set CSS classes to the top-level HTML node, see
+//		`dojo.uacss` for details.
+//
+//		Simply doing a require on this module will
+//		establish this CSS.  Modified version of Morris' CSS hack.
 
-
-if(!dojo._hasResource["dijit._base.sniff"]){
-dojo._hasResource["dijit._base.sniff"]=true;
 dojo.provide("dijit._base.sniff");
-(function(){
-var d=dojo,_1=d.doc.documentElement,ie=d.isIE,_2=d.isOpera,_3=Math.floor,ff=d.isFF,_4=d.boxModel.replace(/-/,""),_5={dj_ie:ie,dj_ie6:_3(ie)==6,dj_ie7:_3(ie)==7,dj_ie8:_3(ie)==8,dj_iequirks:ie&&d.isQuirks,dj_opera:_2,dj_khtml:d.isKhtml,dj_webkit:d.isWebKit,dj_safari:d.isSafari,dj_chrome:d.isChrome,dj_gecko:d.isMozilla,dj_ff3:_3(ff)==3};
-_5["dj_"+_4]=true;
-for(var p in _5){
-if(_5[p]){
-if(_1.className){
-_1.className+=" "+p;
-}else{
-_1.className=p;
-}
-}
-}
-dojo._loaders.unshift(function(){
-if(!dojo._isBodyLtr()){
-_1.className+=" dijitRtl";
-for(var p in _5){
-if(_5[p]){
-_1.className+=" "+p+"-rtl";
-}
-}
-}
-});
-})();
-}
+
+dojo.require("dojo.uacss");
diff --git a/dijit/_base/typematic.js b/dijit/_base/typematic.js
index 9c02105..6702705 100644
--- a/dijit/_base/typematic.js
+++ b/dijit/_base/typematic.js
@@ -1,85 +1,179 @@
-/*
-	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
-*/
+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.
 
-if(!dojo._hasResource["dijit._base.typematic"]){
-dojo._hasResource["dijit._base.typematic"]=true;
-dojo.provide("dijit._base.typematic");
-dijit.typematic={_fireEventAndReload:function(){
-this._timer=null;
-this._callback(++this._count,this._node,this._evt);
-this._currentTimeout=Math.max(this._currentTimeout<0?this._initialDelay:(this._subsequentDelay>1?this._subsequentDelay:Math.round(this._currentTimeout*this._subsequentDelay)),10);
-this._timer=setTimeout(dojo.hitch(this,"_fireEventAndReload"),this._currentTimeout);
-},trigger:function(_1,_2,_3,_4,_5,_6,_7){
-if(_5!=this._obj){
-this.stop();
-this._initialDelay=_7||500;
-this._subsequentDelay=_6||0.9;
-this._obj=_5;
-this._evt=_1;
-this._node=_3;
-this._currentTimeout=-1;
-this._count=-1;
-this._callback=dojo.hitch(_2,_4);
-this._fireEventAndReload();
-}
-},stop:function(){
-if(this._timer){
-clearTimeout(this._timer);
-this._timer=null;
-}
-if(this._obj){
-this._callback(-1,this._node,this._evt);
-this._obj=null;
-}
-},addKeyListener:function(_8,_9,_a,_b,_c,_d){
-if(_9.keyCode){
-_9.charOrCode=_9.keyCode;
-dojo.deprecated("keyCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.","","2.0");
-}else{
-if(_9.charCode){
-_9.charOrCode=String.fromCharCode(_9.charCode);
-dojo.deprecated("charCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.","","2.0");
-}
-}
-return [dojo.connect(_8,"onkeypress",this,function(_e){
-if(_e.charOrCode==_9.charOrCode&&(_9.ctrlKey===undefined||_9.ctrlKey==_e.ctrlKey)&&(_9.altKey===undefined||_9.altKey==_e.altKey)&&(_9.metaKey===undefined||_9.metaKey==(_e.metaKey||false))&&(_9.shiftKey===undefined||_9.shiftKey==_e.shiftKey)){
-dojo.stopEvent(_e);
-dijit.typematic.trigger(_9,_a,_8,_b,_9,_c,_d);
-}else{
-if(dijit.typematic._obj==_9){
-dijit.typematic.stop();
-}
-}
-}),dojo.connect(_8,"onkeyup",this,function(_f){
-if(dijit.typematic._obj==_9){
-dijit.typematic.stop();
-}
-})];
-},addMouseListener:function(_10,_11,_12,_13,_14){
-var dc=dojo.connect;
-return [dc(_10,"mousedown",this,function(evt){
-dojo.stopEvent(evt);
-dijit.typematic.trigger(evt,_11,_10,_12,_10,_13,_14);
-}),dc(_10,"mouseup",this,function(evt){
-dojo.stopEvent(evt);
-dijit.typematic.stop();
-}),dc(_10,"mouseout",this,function(evt){
-dojo.stopEvent(evt);
-dijit.typematic.stop();
-}),dc(_10,"mousemove",this,function(evt){
-dojo.stopEvent(evt);
-}),dc(_10,"dblclick",this,function(evt){
-dojo.stopEvent(evt);
-if(dojo.isIE){
-dijit.typematic.trigger(evt,_11,_10,_12,_10,_13,_14);
-setTimeout(dojo.hitch(this,dijit.typematic.stop),50);
-}
-})];
-},addListener:function(_15,_16,_17,_18,_19,_1a,_1b){
-return this.addKeyListener(_16,_17,_18,_19,_1a,_1b).concat(this.addMouseListener(_15,_18,_19,_1a,_1b));
-}};
-}
+	_fireEventAndReload: function(){
+		this._timer = null;
+		this._callback(++this._count, this._node, this._evt);
+		
+		// Schedule next event, timer is at most minDelay (default 10ms) to avoid
+		// browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup)
+		this._currentTimeout = Math.max(
+			this._currentTimeout < 0 ? this._initialDelay :
+				(this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)),
+			this._minDelay);
+		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, /*Number?*/ minDelay){
+		// 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 (optional):
+		//		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 (optional):
+		//		the number of milliseconds until the 2nd event occurs, default=500ms
+		// minDelay (optional):
+		//		the maximum delay in milliseconds for event to fire, default=10ms
+		if(obj != this._obj){
+			this.stop();
+			this._initialDelay = initialDelay || 500;
+			this._subsequentDelay = subsequentDelay || 0.90;
+			this._minDelay = minDelay || 10;
+			this._obj = obj;
+			this._evt = evt;
+			this._node = node;
+			this._currentTimeout = -1;
+			this._count = -1;
+			this._callback = dojo.hitch(_this, callback);
+			this._fireEventAndReload();
+			this._evt = dojo.mixin({faux: true}, evt);
+		}
+	},
+
+	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, /*Number?*/ minDelay){
+		// 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 callback 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.altKey) &&
+				(keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey
+				(keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){
+					dojo.stopEvent(evt);
+					dijit.typematic.trigger(evt, _this, node, callback, keyObject, subsequentDelay, initialDelay, minDelay);
+				}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, /*Number?*/ minDelay){
+		// 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, minDelay);
+			}),
+			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){
+				evt.preventDefault();
+			}),
+			dc(node, "dblclick", this, function(evt){
+				dojo.stopEvent(evt);
+				if(dojo.isIE){
+					dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
+					setTimeout(dojo.hitch(this, dijit.typematic.stop), 50);
+				}
+			})
+		];
+	},
+
+	addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
+		// 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, minDelay).concat(
+			this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay, minDelay));
+	}
+};
diff --git a/dijit/_base/wai.js b/dijit/_base/wai.js
index 198ea35..16c8289 100644
--- a/dijit/_base/wai.js
+++ b/dijit/_base/wai.js
@@ -1,64 +1,146 @@
-/*
-	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
-*/
+dojo.provide("dijit._base.wai");
 
+dijit.wai = {
+	onload: function(){
+		// summary:
+		//		Detects if we are in high-contrast mode or not
 
-if(!dojo._hasResource["dijit._base.wai"]){
-dojo._hasResource["dijit._base.wai"]=true;
-dojo.provide("dijit._base.wai");
-dijit.wai={onload:function(){
-var _1=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());
-var cs=dojo.getComputedStyle(_1);
-if(cs){
-var _2=cs.backgroundImage;
-var _3=(cs.borderTopColor==cs.borderRightColor)||(_2!=null&&(_2=="none"||_2=="url(invalid-url:)"));
-dojo[_3?"addClass":"removeClass"](dojo.body(),"dijit_a11y");
-if(dojo.isIE){
-_1.outerHTML="";
-}else{
-dojo.body().removeChild(_1);
-}
-}
-}};
-if(dojo.isIE||dojo.isMoz){
-dojo._loaders.unshift(dijit.wai.onload);
-}
-dojo.mixin(dijit,{_XhtmlRoles:/banner|contentinfo|definition|main|navigation|search|note|secondary|seealso/,hasWaiRole:function(_4,_5){
-var _6=this.getWaiRole(_4);
-return _5?(_6.indexOf(_5)>-1):(_6.length>0);
-},getWaiRole:function(_7){
-return dojo.trim((dojo.attr(_7,"role")||"").replace(this._XhtmlRoles,"").replace("wairole:",""));
-},setWaiRole:function(_8,_9){
-var _a=dojo.attr(_8,"role")||"";
-if(!this._XhtmlRoles.test(_a)){
-dojo.attr(_8,"role",_9);
-}else{
-if((" "+_a+" ").indexOf(" "+_9+" ")<0){
-var _b=dojo.trim(_a.replace(this._XhtmlRoles,""));
-var _c=dojo.trim(_a.replace(_b,""));
-dojo.attr(_8,"role",_c+(_c?" ":"")+_9);
-}
-}
-},removeWaiRole:function(_d,_e){
-var _f=dojo.attr(_d,"role");
-if(!_f){
-return;
-}
-if(_e){
-var t=dojo.trim((" "+_f+" ").replace(" "+_e+" "," "));
-dojo.attr(_d,"role",t);
-}else{
-_d.removeAttribute("role");
-}
-},hasWaiState:function(_10,_11){
-return _10.hasAttribute?_10.hasAttribute("aria-"+_11):!!_10.getAttribute("aria-"+_11);
-},getWaiState:function(_12,_13){
-return _12.getAttribute("aria-"+_13)||"";
-},setWaiState:function(_14,_15,_16){
-_14.setAttribute("aria-"+_15,_16);
-},removeWaiState:function(_17,_18){
-_17.removeAttribute("aria-"+_18);
-}});
+		// 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:
+		//		Replace existing role attribute with new role.
+		//		If elem already has an XHTML role, append this role to XHTML role
+		//		and remove other ARIA roles.
+
+		var curRole = dojo.attr(elem, "role") || "";
+		if(!this._XhtmlRoles.test(curRole)){
+			dojo.attr(elem, "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 t = dojo.trim((" " + roleValue + " ").replace(" " + role + " ", " "));
+			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:
+		//		Checks for an attribute called "aria-"+state.
+		// returns:
+		//		true if elem has a value for the given state and
+		//		false if it does not.
+
+		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:
+		//		Checks 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.
+
+		return elem.getAttribute("aria-"+state) || "";
+	},
+
+	setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
+		// summary:
+		//		Sets a state on an element.
+		// description:
+		//		Sets an attribute called "aria-"+state.
+
+		elem.setAttribute("aria-"+state, value);
+	},
+
+	removeWaiState: function(/*Element*/ elem, /*String*/ state){
+		// summary:
+		//		Removes a state from an element.
+		// description:
+		//		Sets an attribute called "aria-"+state.
+
+		elem.removeAttribute("aria-"+state);
+	}
+});
diff --git a/dijit/_base/window.js b/dijit/_base/window.js
index 65c50cc..1ec6db4 100644
--- a/dijit/_base/window.js
+++ b/dijit/_base/window.js
@@ -1,20 +1,7 @@
-/*
-	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
-*/
+dojo.provide("dijit._base.window");
 
+dojo.require("dojo.window");
 
-if(!dojo._hasResource["dijit._base.window"]){
-dojo._hasResource["dijit._base.window"]=true;
-dojo.provide("dijit._base.window");
-dijit.getDocumentWindow=function(_1){
-if(dojo.isIE&&window!==document.parentWindow&&!_1._parentWindow){
-_1.parentWindow.execScript("document._parentWindow = window;","Javascript");
-var _2=_1._parentWindow;
-_1._parentWindow=null;
-return _2;
-}
-return _1._parentWindow||_1.parentWindow||_1.defaultView;
+dijit.getDocumentWindow = function(doc){
+	return dojo.window.get(doc);
 };
-}
diff --git a/dijit/_editor/RichText.js b/dijit/_editor/RichText.js
index 1cc89b1..6b2c293 100644
--- a/dijit/_editor/RichText.js
+++ b/dijit/_editor/RichText.js
@@ -1,984 +1,1906 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._editor.RichText"]){
-dojo._hasResource["dijit._editor.RichText"]=true;
 dojo.provide("dijit._editor.RichText");
+
 dojo.require("dijit._Widget");
+dojo.require("dijit._CssStateMixin");
 dojo.require("dijit._editor.selection");
 dojo.require("dijit._editor.range");
 dojo.require("dijit._editor.html");
-if(!dojo.config["useXDomain"]||dojo.config["allowXdRichTextSave"]){
-if(dojo._postLoad){
-(function(){
-var _1=dojo.doc.createElement("textarea");
-_1.id=dijit._scopeName+"._editor.RichText.savedContent";
-dojo.style(_1,{display:"none",position:"absolute",top:"-100px",height:"3px",width:"3px"});
-dojo.body().appendChild(_1);
-})();
-}else{
-try{
-dojo.doc.write("<textarea id=\""+dijit._scopeName+"._editor.RichText.savedContent\" "+"style=\"display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;\"></textarea>");
-}
-catch(e){
-}
-}
-}
-dojo.declare("dijit._editor.RichText",dijit._Widget,{constructor:function(_2){
-this.contentPreFilters=[];
-this.contentPostFilters=[];
-this.contentDomPreFilters=[];
-this.contentDomPostFilters=[];
-this.editingAreaStyleSheets=[];
-this.events=[].concat(this.events);
-this._keyHandlers={};
-this.contentPreFilters.push(dojo.hitch(this,"_preFixUrlAttributes"));
-if(dojo.isMoz){
-this.contentPreFilters.push(this._normalizeFontStyle);
-this.contentPostFilters.push(this._removeMozBogus);
-}
-if(dojo.isWebKit){
-this.contentPreFilters.push(this._removeWebkitBogus);
-this.contentPostFilters.push(this._removeWebkitBogus);
-}
-if(dojo.isIE){
-this.contentPostFilters.push(this._normalizeFontStyle);
-}
-this.onLoadDeferred=new dojo.Deferred();
-},inheritWidth:false,focusOnLoad:false,name:"",styleSheets:"",_content:"",height:"300px",minHeight:"1em",isClosed:true,isLoaded:false,_SEPARATOR:"@@**%%__RICHTEXTBOUNDRY__%%**@@",onLoadDeferred:null,isTabIndent:false,disableSpellCheck:false,postCreate:function(){
-if("textarea"==this.domNode.tagName.toLowerCase()){
-console.warn("RichText should not be used with the TEXTAREA tag.  See dijit._editor.RichText docs.");
-}
-dojo.publish(dijit._scopeName+"._editor.RichText::init",[this]);
-this.open();
-this.setupDefaultShortcuts();
-},setupDefaultShortcuts:function(){
-var _3=dojo.hitch(this,function(_4,_5){
-return function(){
-return !this.execCommand(_4,_5);
-};
-});
-var _6={b:_3("bold"),i:_3("italic"),u:_3("underline"),a:_3("selectall"),s:function(){
-this.save(true);
-},m:function(){
-this.isTabIndent=!this.isTabIndent;
-},"1":_3("formatblock","h1"),"2":_3("formatblock","h2"),"3":_3("formatblock","h3"),"4":_3("formatblock","h4"),"\\":_3("insertunorderedlist")};
-if(!dojo.isIE){
-_6.Z=_3("redo");
-}
-for(var _7 in _6){
-this.addKeyHandler(_7,true,false,_6[_7]);
-}
-},events:["onKeyPress","onKeyDown","onKeyUp","onClick"],captureEvents:[],_editorCommandsLocalized:false,_localizeEditorCommands:function(){
-if(this._editorCommandsLocalized){
-return;
-}
-this._editorCommandsLocalized=true;
-var _8=["div","p","pre","h1","h2","h3","h4","h5","h6","ol","ul","address"];
-var _9="",_a,i=0;
-while((_a=_8[i++])){
-if(_a.charAt(1)!="l"){
-_9+="<"+_a+"><span>content</span></"+_a+"><br/>";
-}else{
-_9+="<"+_a+"><li>content</li></"+_a+"><br/>";
-}
-}
-var _b=dojo.doc.createElement("div");
-dojo.style(_b,{position:"absolute",top:"-2000px"});
-dojo.doc.body.appendChild(_b);
-_b.innerHTML=_9;
-var _c=_b.firstChild;
-while(_c){
-dijit._editor.selection.selectElement(_c.firstChild);
-dojo.withGlobal(this.window,"selectElement",dijit._editor.selection,[_c.firstChild]);
-var _d=_c.tagName.toLowerCase();
-this._local2NativeFormatNames[_d]=document.queryCommandValue("formatblock");
-this._native2LocalFormatNames[this._local2NativeFormatNames[_d]]=_d;
-_c=_c.nextSibling.nextSibling;
-}
-dojo.body().removeChild(_b);
-},open:function(_e){
-if(!this.onLoadDeferred||this.onLoadDeferred.fired>=0){
-this.onLoadDeferred=new dojo.Deferred();
-}
-if(!this.isClosed){
-this.close();
-}
-dojo.publish(dijit._scopeName+"._editor.RichText::open",[this]);
-this._content="";
-if(arguments.length==1&&_e.nodeName){
-this.domNode=_e;
-}
-var dn=this.domNode;
-var _f;
-if(dn.nodeName&&dn.nodeName.toLowerCase()=="textarea"){
-var ta=(this.textarea=dn);
-this.name=ta.name;
-_f=ta.value;
-dn=this.domNode=dojo.doc.createElement("div");
-dn.setAttribute("widgetId",this.id);
-ta.removeAttribute("widgetId");
-dn.cssText=ta.cssText;
-dn.className+=" "+ta.className;
-dojo.place(dn,ta,"before");
-var _10=dojo.hitch(this,function(){
-dojo.style(ta,{display:"block",position:"absolute",top:"-1000px"});
-if(dojo.isIE){
-var s=ta.style;
-this.__overflow=s.overflow;
-s.overflow="hidden";
-}
-});
-if(dojo.isIE){
-setTimeout(_10,10);
-}else{
-_10();
-}
-if(ta.form){
-dojo.connect(ta.form,"onsubmit",this,function(){
-ta.value=this.getValue();
-});
-}
-}else{
-_f=dijit._editor.getChildrenHtml(dn);
-dn.innerHTML="";
-}
-var _11=dojo.contentBox(dn);
-this._oldHeight=_11.h;
-this._oldWidth=_11.w;
-this.savedContent=_f;
-if(dn.nodeName&&dn.nodeName=="LI"){
-dn.innerHTML=" <br>";
-}
-this.editingArea=dn.ownerDocument.createElement("div");
-dn.appendChild(this.editingArea);
-if(this.name!==""&&(!dojo.config["useXDomain"]||dojo.config["allowXdRichTextSave"])){
-var _12=dojo.byId(dijit._scopeName+"._editor.RichText.savedContent");
-if(_12.value!==""){
-var _13=_12.value.split(this._SEPARATOR),i=0,dat;
-while((dat=_13[i++])){
-var _14=dat.split(":");
-if(_14[0]==this.name){
-_f=_14[1];
-_13.splice(i,1);
-break;
-}
-}
-}
-dojo.addOnUnload(dojo.hitch(this,"_saveContent"));
-}
-this.isClosed=false;
-var ifr=(this.editorObject=this.iframe=dojo.doc.createElement("iframe"));
-ifr.id=this.id+"_iframe";
-this._iframeSrc=this._getIframeDocTxt();
-ifr.style.border="none";
-ifr.style.width="100%";
-if(this._layoutMode){
-ifr.style.height="100%";
-}else{
-if(dojo.isIE>=7){
-if(this.height){
-ifr.style.height=this.height;
-}
-if(this.minHeight){
-ifr.style.minHeight=this.minHeight;
-}
-}else{
-ifr.style.height=this.height?this.height:this.minHeight;
-}
-}
-ifr.frameBorder=0;
-ifr._loadFunc=dojo.hitch(this,function(win){
-this.window=win;
-this.document=this.window.document;
-if(dojo.isIE){
-this._localizeEditorCommands();
-}
-this.onLoad(_f);
-this.savedContent=this.getValue(true);
-});
-var s="javascript:parent."+dijit._scopeName+".byId(\""+this.id+"\")._iframeSrc";
-ifr.setAttribute("src",s);
-this.editingArea.appendChild(ifr);
-if(dojo.isSafari){
-setTimeout(function(){
-ifr.setAttribute("src",s);
-},0);
-}
-if(dn.nodeName=="LI"){
-dn.lastChild.style.marginTop="-1.2em";
-}
-dojo.addClass(this.domNode,"RichTextEditable");
-},_local2NativeFormatNames:{},_native2LocalFormatNames:{},_getIframeDocTxt:function(){
-var _15=dojo.getComputedStyle(this.domNode);
-var _16="";
-if(dojo.isIE||(!this.height&&!dojo.isMoz)){
-_16="<div></div>";
-}else{
-if(dojo.isMoz){
-this._cursorToStart=true;
-_16=" ";
-}
-}
-var _17=[_15.fontWeight,_15.fontSize,_15.fontFamily].join(" ");
-var _18=_15.lineHeight;
-if(_18.indexOf("px")>=0){
-_18=parseFloat(_18)/parseFloat(_15.fontSize);
-}else{
-if(_18.indexOf("em")>=0){
-_18=parseFloat(_18);
-}else{
-_18="normal";
-}
-}
-var _19="";
-this.style.replace(/(^|;)(line-|font-?)[^;]+/g,function(_1a){
-_19+=_1a.replace(/^;/g,"")+";";
-});
-var _1b=dojo.query("label[for=\""+this.id+"\"]");
-return [this.isLeftToRight()?"<html><head>":"<html dir='rtl'><head>",(dojo.isMoz&&_1b.length?"<title>"+_1b[0].innerHTML+"</title>":""),"<meta http-equiv='Content-Type' content='text/html'>","<style>","body,html {","\tbackground:transparent;","\tpadding: 1px 0 0 0;","\tmargin: -1px 0 0 0;",(dojo.isWebKit?"\twidth: 100%;":""),(dojo.isWebKit?"\theight: 100%;":""),"}","body{","\ttop:0px; left:0px; right:0px;","\tfont:",_17,";",((this.height||dojo.isOpera)?"":"position: fixed;"),"\tmin-height [...]
-},_applyEditingAreaStyleSheets:function(){
-var _1c=[];
-if(this.styleSheets){
-_1c=this.styleSheets.split(";");
-this.styleSheets="";
-}
-_1c=_1c.concat(this.editingAreaStyleSheets);
-this.editingAreaStyleSheets=[];
-var _1d="",i=0,url;
-while((url=_1c[i++])){
-var _1e=(new dojo._Url(dojo.global.location,url)).toString();
-this.editingAreaStyleSheets.push(_1e);
-_1d+="<link rel=\"stylesheet\" type=\"text/css\" href=\""+_1e+"\"/>";
-}
-return _1d;
-},addStyleSheet:function(uri){
-var url=uri.toString();
-if(url.charAt(0)=="."||(url.charAt(0)!="/"&&!uri.host)){
-url=(new dojo._Url(dojo.global.location,url)).toString();
-}
-if(dojo.indexOf(this.editingAreaStyleSheets,url)>-1){
-return;
-}
-this.editingAreaStyleSheets.push(url);
-this.onLoadDeferred.addCallback(dojo.hitch(function(){
-if(this.document.createStyleSheet){
-this.document.createStyleSheet(url);
-}else{
-var _1f=this.document.getElementsByTagName("head")[0];
-var _20=this.document.createElement("link");
-_20.rel="stylesheet";
-_20.type="text/css";
-_20.href=url;
-_1f.appendChild(_20);
-}
-}));
-},removeStyleSheet:function(uri){
-var url=uri.toString();
-if(url.charAt(0)=="."||(url.charAt(0)!="/"&&!uri.host)){
-url=(new dojo._Url(dojo.global.location,url)).toString();
-}
-var _21=dojo.indexOf(this.editingAreaStyleSheets,url);
-if(_21==-1){
-return;
-}
-delete this.editingAreaStyleSheets[_21];
-dojo.withGlobal(this.window,"query",dojo,["link:[href=\""+url+"\"]"]).orphan();
-},disabled:false,_mozSettingProps:{"styleWithCSS":false},_setDisabledAttr:function(_22){
-this.disabled=_22;
-if(!this.isLoaded){
-return;
-}
-_22=!!_22;
-if(dojo.isIE||dojo.isWebKit||dojo.isOpera){
-var _23=dojo.isIE&&(this.isLoaded||!this.focusOnLoad);
-if(_23){
-this.editNode.unselectable="on";
-}
-this.editNode.contentEditable=!_22;
-if(_23){
-var _24=this;
-setTimeout(function(){
-_24.editNode.unselectable="off";
-},0);
-}
-}else{
-try{
-this.document.designMode=(_22?"off":"on");
-}
-catch(e){
-return;
-}
-if(!_22&&this._mozSettingProps){
-var ps=this._mozSettingProps;
-for(var n in ps){
-if(ps.hasOwnProperty(n)){
-try{
-this.document.execCommand(n,false,ps[n]);
-}
-catch(e2){
-}
-}
-}
-}
-}
-this._disabledOK=true;
-},onLoad:function(_25){
-if(!this.window.__registeredWindow){
-this.window.__registeredWindow=true;
-this._iframeRegHandle=dijit.registerIframe(this.iframe);
-}
-if(!dojo.isIE&&(this.height||dojo.isMoz)){
-this.editNode=this.document.body;
-}else{
-this.editNode=this.document.body.firstChild;
-var _26=this;
-if(dojo.isIE){
-var _27=(this.tabStop=dojo.doc.createElement("<div tabIndex=-1>"));
-this.editingArea.appendChild(_27);
-this.iframe.onfocus=function(){
-_26.editNode.setActive();
-};
-}
-}
-this.focusNode=this.editNode;
-var _28=this.events.concat(this.captureEvents);
-var ap=this.iframe?this.document:this.editNode;
-dojo.forEach(_28,function(_29){
-this.connect(ap,_29.toLowerCase(),_29);
-},this);
-if(dojo.isIE){
-this.connect(this.document,"onmousedown","_onIEMouseDown");
-this.editNode.style.zoom=1;
-}
-if(dojo.isWebKit){
-this._webkitListener=this.connect(this.document,"onmouseup","onDisplayChanged");
-}
-if(dojo.isIE){
-try{
-this.document.execCommand("RespectVisibilityInDesign",true,null);
-}
-catch(e){
-}
-}
-this.isLoaded=true;
-this.attr("disabled",this.disabled);
-this.setValue(_25);
-if(this.onLoadDeferred){
-this.onLoadDeferred.callback(true);
-}
-this.onDisplayChanged();
-if(this.focusOnLoad){
-dojo.addOnLoad(dojo.hitch(this,function(){
-setTimeout(dojo.hitch(this,"focus"),this.updateInterval);
-}));
-}
-},onKeyDown:function(e){
-if(e.keyCode===dojo.keys.TAB&&this.isTabIndent){
-dojo.stopEvent(e);
-if(this.queryCommandEnabled((e.shiftKey?"outdent":"indent"))){
-this.execCommand((e.shiftKey?"outdent":"indent"));
-}
-}
-if(dojo.isIE){
-if(e.keyCode==dojo.keys.TAB&&!this.isTabIndent){
-if(e.shiftKey&&!e.ctrlKey&&!e.altKey){
-this.iframe.focus();
-}else{
-if(!e.shiftKey&&!e.ctrlKey&&!e.altKey){
-this.tabStop.focus();
-}
-}
-}else{
-if(e.keyCode===dojo.keys.BACKSPACE&&this.document.selection.type==="Control"){
-dojo.stopEvent(e);
-this.execCommand("delete");
-}else{
-if((65<=e.keyCode&&e.keyCode<=90)||(e.keyCode>=37&&e.keyCode<=40)){
-e.charCode=e.keyCode;
-this.onKeyPress(e);
-}
-}
-}
-}
-return true;
-},onKeyUp:function(e){
-return;
-},setDisabled:function(_2a){
-dojo.deprecated("dijit.Editor::setDisabled is deprecated","use dijit.Editor::attr(\"disabled\",boolean) instead",2);
-this.attr("disabled",_2a);
-},_setValueAttr:function(_2b){
-this.setValue(_2b);
-},_setDisableSpellCheckAttr:function(_2c){
-if(this.document){
-dojo.attr(this.document.body,"spellcheck",!_2c);
-}else{
-this.onLoadDeferred.addCallback(dojo.hitch(this,function(){
-dojo.attr(this.document.body,"spellcheck",!_2c);
-}));
-}
-this.disableSpellCheck=_2c;
-},onKeyPress:function(e){
-var c=(e.keyChar&&e.keyChar.toLowerCase())||e.keyCode,_2d=this._keyHandlers[c],_2e=arguments;
-if(_2d&&!e.altKey){
-dojo.some(_2d,function(h){
-if(!(h.shift^e.shiftKey)&&!(h.ctrl^e.ctrlKey)){
-if(!h.handler.apply(this,_2e)){
-e.preventDefault();
-}
-return true;
-}
-},this);
-}
-if(!this._onKeyHitch){
-this._onKeyHitch=dojo.hitch(this,"onKeyPressed");
-}
-setTimeout(this._onKeyHitch,1);
-return true;
-},addKeyHandler:function(key,_2f,_30,_31){
-if(!dojo.isArray(this._keyHandlers[key])){
-this._keyHandlers[key]=[];
-}
-this._keyHandlers[key].push({shift:_30||false,ctrl:_2f||false,handler:_31});
-},onKeyPressed:function(){
-this.onDisplayChanged();
-},onClick:function(e){
-this.onDisplayChanged(e);
-},_onIEMouseDown:function(e){
-if(!this._focused&&!this.disabled){
-this.focus();
-}
-},_onBlur:function(e){
-this.inherited(arguments);
-var _32=this.getValue(true);
-if(_32!=this.savedContent){
-this.onChange(_32);
-this.savedContent=_32;
-}
-},_onFocus:function(e){
-if(!this.disabled){
-if(!this._disabledOK){
-this.attr("disabled",false);
-}
-this.inherited(arguments);
-}
-},blur:function(){
-if(!dojo.isIE&&this.window.document.documentElement&&this.window.document.documentElement.focus){
-this.window.document.documentElement.focus();
-}else{
-if(dojo.doc.body.focus){
-dojo.doc.body.focus();
-}
-}
-},focus:function(){
-if(!dojo.isIE){
-dijit.focus(this.iframe);
-if(this._cursorToStart){
-delete this._cursorToStart;
-if(this.editNode.childNodes&&this.editNode.childNodes.length===1&&this.editNode.innerHTML===" "){
-this.placeCursorAtStart();
-}
-}
-}else{
-if(this.editNode&&this.editNode.focus){
-this.iframe.fireEvent("onfocus",document.createEventObject());
-}
-}
-},updateInterval:200,_updateTimer:null,onDisplayChanged:function(e){
-if(this._updateTimer){
-clearTimeout(this._updateTimer);
-}
-if(!this._updateHandler){
-this._updateHandler=dojo.hitch(this,"onNormalizedDisplayChanged");
-}
-this._updateTimer=setTimeout(this._updateHandler,this.updateInterval);
-},onNormalizedDisplayChanged:function(){
-delete this._updateTimer;
-},onChange:function(_33){
-},_normalizeCommand:function(cmd,_34){
-var _35=cmd.toLowerCase();
-if(_35=="formatblock"){
-if(dojo.isSafari&&_34===undefined){
-_35="heading";
-}
-}else{
-if(_35=="hilitecolor"&&!dojo.isMoz){
-_35="backcolor";
-}
-}
-return _35;
-},_qcaCache:{},queryCommandAvailable:function(_36){
-var ca=this._qcaCache[_36];
-if(ca!==undefined){
-return ca;
-}
-return (this._qcaCache[_36]=this._queryCommandAvailable(_36));
-},_queryCommandAvailable:function(_37){
-var ie=1;
-var _38=1<<1;
-var _39=1<<2;
-var _3a=1<<3;
-var _3b=1<<4;
-function _3c(_3d){
-return {ie:Boolean(_3d&ie),mozilla:Boolean(_3d&_38),webkit:Boolean(_3d&_39),webkit420:Boolean(_3d&_3b),opera:Boolean(_3d&_3a)};
-};
-var _3e=null;
-switch(_37.toLowerCase()){
-case "bold":
-case "italic":
-case "underline":
-case "subscript":
-case "superscript":
-case "fontname":
-case "fontsize":
-case "forecolor":
-case "hilitecolor":
-case "justifycenter":
-case "justifyfull":
-case "justifyleft":
-case "justifyright":
-case "delete":
-case "selectall":
-case "toggledir":
-_3e=_3c(_38|ie|_39|_3a);
-break;
-case "createlink":
-case "unlink":
-case "removeformat":
-case "inserthorizontalrule":
-case "insertimage":
-case "insertorderedlist":
-case "insertunorderedlist":
-case "indent":
-case "outdent":
-case "formatblock":
-case "inserthtml":
-case "undo":
-case "redo":
-case "strikethrough":
-case "tabindent":
-_3e=_3c(_38|ie|_3a|_3b);
-break;
-case "blockdirltr":
-case "blockdirrtl":
-case "dirltr":
-case "dirrtl":
-case "inlinedirltr":
-case "inlinedirrtl":
-_3e=_3c(ie);
-break;
-case "cut":
-case "copy":
-case "paste":
-_3e=_3c(ie|_38|_3b);
-break;
-case "inserttable":
-_3e=_3c(_38|ie);
-break;
-case "insertcell":
-case "insertcol":
-case "insertrow":
-case "deletecells":
-case "deletecols":
-case "deleterows":
-case "mergecells":
-case "splitcell":
-_3e=_3c(ie|_38);
-break;
-default:
-return false;
-}
-return (dojo.isIE&&_3e.ie)||(dojo.isMoz&&_3e.mozilla)||(dojo.isWebKit&&_3e.webkit)||(dojo.isWebKit>420&&_3e.webkit420)||(dojo.isOpera&&_3e.opera);
-},execCommand:function(_3f,_40){
-var _41;
-this.focus();
-_3f=this._normalizeCommand(_3f,_40);
-if(_40!==undefined){
-if(_3f=="heading"){
-throw new Error("unimplemented");
-}else{
-if((_3f=="formatblock")&&dojo.isIE){
-_40="<"+_40+">";
-}
-}
-}
-var _42="_"+_3f+"Impl";
-if(this[_42]){
-_41=this[_42](_40);
-}else{
-_40=arguments.length>1?_40:null;
-if(_40||_3f!="createlink"){
-_41=this.document.execCommand(_3f,false,_40);
-}
-}
-this.onDisplayChanged();
-return _41;
-},queryCommandEnabled:function(_43){
-if(this.disabled||!this._disabledOK){
-return false;
-}
-_43=this._normalizeCommand(_43);
-if(dojo.isMoz||dojo.isWebKit){
-if(_43=="unlink"){
-return this._sCall("hasAncestorElement",["a"]);
-}else{
-if(_43=="inserttable"){
-return true;
-}
-}
-}
-if(dojo.isWebKit){
-if(_43=="copy"){
-_43="cut";
-}else{
-if(_43=="paste"){
-return true;
-}
-}
-}
-var _44=dojo.isIE?this.document.selection.createRange():this.document;
-try{
-return _44.queryCommandEnabled(_43);
-}
-catch(e){
-return false;
-}
-},queryCommandState:function(_45){
-if(this.disabled||!this._disabledOK){
-return false;
-}
-_45=this._normalizeCommand(_45);
-try{
-return this.document.queryCommandState(_45);
-}
-catch(e){
-return false;
-}
-},queryCommandValue:function(_46){
-if(this.disabled||!this._disabledOK){
-return false;
-}
-var r;
-_46=this._normalizeCommand(_46);
-if(dojo.isIE&&_46=="formatblock"){
-r=this._native2LocalFormatNames[this.document.queryCommandValue(_46)];
-}else{
-if(dojo.isMoz&&_46==="hilitecolor"){
-var _47;
-try{
-_47=this.document.queryCommandValue("styleWithCSS");
-}
-catch(e){
-_47=false;
-}
-this.document.execCommand("styleWithCSS",false,true);
-r=this.document.queryCommandValue(_46);
-this.document.execCommand("styleWithCSS",false,_47);
-}else{
-r=this.document.queryCommandValue(_46);
-}
-}
-return r;
-},_sCall:function(_48,_49){
-return dojo.withGlobal(this.window,_48,dijit._editor.selection,_49);
-},placeCursorAtStart:function(){
-this.focus();
-var _4a=false;
-if(dojo.isMoz){
-var _4b=this.editNode.firstChild;
-while(_4b){
-if(_4b.nodeType==3){
-if(_4b.nodeValue.replace(/^\s+|\s+$/g,"").length>0){
-_4a=true;
-this._sCall("selectElement",[_4b]);
-break;
-}
-}else{
-if(_4b.nodeType==1){
-_4a=true;
-var tg=_4b.tagName?_4b.tagName.toLowerCase():"";
-if(/br|input|img|base|meta|area|basefont|hr|link/.test(tg)){
-this._sCall("selectElement",[_4b]);
-}else{
-this._sCall("selectElementChildren",[_4b]);
-}
-break;
-}
-}
-_4b=_4b.nextSibling;
-}
-}else{
-_4a=true;
-this._sCall("selectElementChildren",[this.editNode]);
-}
-if(_4a){
-this._sCall("collapse",[true]);
-}
-},placeCursorAtEnd:function(){
-this.focus();
-var _4c=false;
-if(dojo.isMoz){
-var _4d=this.editNode.lastChild;
-while(_4d){
-if(_4d.nodeType==3){
-if(_4d.nodeValue.replace(/^\s+|\s+$/g,"").length>0){
-_4c=true;
-this._sCall("selectElement",[_4d]);
-break;
-}
-}else{
-if(_4d.nodeType==1){
-_4c=true;
-if(_4d.lastChild){
-this._sCall("selectElement",[_4d.lastChild]);
-}else{
-this._sCall("selectElement",[_4d]);
-}
-break;
-}
-}
-_4d=_4d.previousSibling;
-}
-}else{
-_4c=true;
-this._sCall("selectElementChildren",[this.editNode]);
-}
-if(_4c){
-this._sCall("collapse",[false]);
-}
-},getValue:function(_4e){
-if(this.textarea){
-if(this.isClosed||!this.isLoaded){
-return this.textarea.value;
-}
-}
-return this._postFilterContent(null,_4e);
-},_getValueAttr:function(){
-return this.getValue(true);
-},setValue:function(_4f){
-if(!this.isLoaded){
-this.onLoadDeferred.addCallback(dojo.hitch(this,function(){
-this.setValue(_4f);
-}));
-return;
-}
-if(this.textarea&&(this.isClosed||!this.isLoaded)){
-this.textarea.value=_4f;
-}else{
-_4f=this._preFilterContent(_4f);
-var _50=this.isClosed?this.domNode:this.editNode;
-if(!_4f&&dojo.isWebKit){
-this._cursorToStart=true;
-_4f=" ";
-}
-_50.innerHTML=_4f;
-this._preDomFilterContent(_50);
-}
-this.onDisplayChanged();
-},replaceValue:function(_51){
-if(this.isClosed){
-this.setValue(_51);
-}else{
-if(this.window&&this.window.getSelection&&!dojo.isMoz){
-this.setValue(_51);
-}else{
-if(this.window&&this.window.getSelection){
-_51=this._preFilterContent(_51);
-this.execCommand("selectall");
-if(!_51){
-this._cursorToStart=true;
-_51=" ";
-}
-this.execCommand("inserthtml",_51);
-this._preDomFilterContent(this.editNode);
-}else{
-if(this.document&&this.document.selection){
-this.setValue(_51);
-}
-}
-}
-}
-},_preFilterContent:function(_52){
-var ec=_52;
-dojo.forEach(this.contentPreFilters,function(ef){
-if(ef){
-ec=ef(ec);
-}
-});
-return ec;
-},_preDomFilterContent:function(dom){
-dom=dom||this.editNode;
-dojo.forEach(this.contentDomPreFilters,function(ef){
-if(ef&&dojo.isFunction(ef)){
-ef(dom);
-}
-},this);
-},_postFilterContent:function(dom,_53){
-var ec;
-if(!dojo.isString(dom)){
-dom=dom||this.editNode;
-if(this.contentDomPostFilters.length){
-if(_53){
-dom=dojo.clone(dom);
-}
-dojo.forEach(this.contentDomPostFilters,function(ef){
-dom=ef(dom);
-});
-}
-ec=dijit._editor.getChildrenHtml(dom);
-}else{
-ec=dom;
-}
-if(!dojo.trim(ec.replace(/^\xA0\xA0*/,"").replace(/\xA0\xA0*$/,"")).length){
-ec="";
+
+// used to restore content when user leaves this page then comes back
+// but do not try doing dojo.doc.write if we are using xd loading.
+// dojo.doc.write will only work if RichText.js is included in the dojo.js
+// file. If it is included in dojo.js and you want to allow rich text saving
+// for back/forward actions, then set dojo.config.allowXdRichTextSave = true.
+if(!dojo.config["useXDomain"] || dojo.config["allowXdRichTextSave"]){
+	if(dojo._postLoad){
+		(function(){
+			var savetextarea = dojo.doc.createElement('textarea');
+			savetextarea.id = dijit._scopeName + "._editor.RichText.savedContent";
+			dojo.style(savetextarea, {
+				display:'none',
+				position:'absolute',
+				top:"-100px",
+				height:"3px",
+				width:"3px"
+			});
+			dojo.body().appendChild(savetextarea);
+		})();
+	}else{
+		//dojo.body() is not available before onLoad is fired
+		try{
+			dojo.doc.write('<textarea id="' + dijit._scopeName + '._editor.RichText.savedContent" ' +
+				'style="display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;"></textarea>');
+		}catch(e){ }
+	}
 }
-dojo.forEach(this.contentPostFilters,function(ef){
-ec=ef(ec);
+
+dojo.declare("dijit._editor.RichText", [dijit._Widget, dijit._CssStateMixin], {
+	constructor: function(params){
+		// summary:
+		//		dijit._editor.RichText is the core of dijit.Editor, which provides basic
+		//		WYSIWYG editing features.
+		//
+		// description:
+		//		dijit._editor.RichText is the core of dijit.Editor, which provides basic
+		//		WYSIWYG editing features. It also encapsulates the differences
+		//		of different js engines for various browsers.  Do not use this widget
+		//		with an HTML <TEXTAREA> tag, since the browser unescapes XML escape characters,
+		//		like <.  This can have unexpected behavior and lead to security issues
+		//		such as scripting attacks.
+		//
+		// tags:
+		//		private
+
+		// contentPreFilters: Function(String)[]
+		//		Pre content filter function register array.
+		//		these filters will be executed before the actual
+		//		editing area gets the html content.
+		this.contentPreFilters = [];
+
+		// contentPostFilters: Function(String)[]
+		//		post content filter function register array.
+		//		These will be used on the resulting html
+		//		from contentDomPostFilters. The resulting
+		//		content is the final html (returned by getValue()).
+		this.contentPostFilters = [];
+
+		// contentDomPreFilters: Function(DomNode)[]
+		//		Pre content dom filter function register array.
+		//		These filters are applied after the result from
+		//		contentPreFilters are set to the editing area.
+		this.contentDomPreFilters = [];
+
+		// contentDomPostFilters: Function(DomNode)[]
+		//		Post content dom filter function register array.
+		//		These filters are executed on the editing area dom.
+		//		The result from these will be passed to contentPostFilters.
+		this.contentDomPostFilters = [];
+
+		// editingAreaStyleSheets: dojo._URL[]
+		//		array to store all the stylesheets applied to the editing area
+		this.editingAreaStyleSheets = [];
+
+		// Make a copy of this.events before we start writing into it, otherwise we
+		// will modify the prototype which leads to bad things on pages w/multiple editors
+		this.events = [].concat(this.events);
+
+		this._keyHandlers = {};
+		this.contentPreFilters.push(dojo.hitch(this, "_preFixUrlAttributes"));
+		if(dojo.isMoz){
+			this.contentPreFilters.push(this._normalizeFontStyle);
+			this.contentPostFilters.push(this._removeMozBogus);
+		}
+		if(dojo.isWebKit){
+			// Try to clean up WebKit bogus artifacts.  The inserted classes
+			// made by WebKit sometimes messes things up.
+			this.contentPreFilters.push(this._removeWebkitBogus);
+			this.contentPostFilters.push(this._removeWebkitBogus);
+		}
+		if(dojo.isIE){
+			// IE generates <strong> and <em> but we want to normalize to <b> and <i>
+			this.contentPostFilters.push(this._normalizeFontStyle);
+		}
+		//this.contentDomPostFilters.push(this._postDomFixUrlAttributes);
+
+		if(params && dojo.isString(params.value)){
+			this.value = params.value;
+		}
+
+		this.onLoadDeferred = new dojo.Deferred();
+	},
+
+	baseClass: "dijitEditor",
+
+	// inheritWidth: Boolean
+	//		whether to inherit the parent's width or simply use 100%
+	inheritWidth: false,
+
+	// focusOnLoad: [deprecated] Boolean
+	//		Focus into this widget when the page is loaded
+	focusOnLoad: false,
+
+	// name: String?
+	//		Specifies the name of a (hidden) <textarea> node on the page that's used to save
+	//		the editor content on page leave.   Used to restore editor contents after navigating
+	//		to a new page and then hitting the back button.
+	name: "",
+
+	// styleSheets: [const] String
+	//		semicolon (";") separated list of css files for the editing area
+	styleSheets: "",
+
+	// _content: [private] String
+	//		temporary content storage
+	_content: "",
+
+	// height: String
+	//		Set height to fix the editor at a specific height, with scrolling.
+	//		By default, this is 300px.  If you want to have the editor always
+	//		resizes to accommodate the content, use AlwaysShowToolbar plugin
+	//		and set height="".  If this editor is used within a layout widget,
+	//		set height="100%".
+	height: "300px",
+
+	// minHeight: String
+	//		The minimum height that the editor should have.
+	minHeight: "1em",
+
+	// isClosed: [private] Boolean
+	isClosed: true,
+
+	// isLoaded: [private] Boolean
+	isLoaded: false,
+
+	// _SEPARATOR: [private] String
+	//		Used to concat contents from multiple editors into a single string,
+	//		so they can be saved into a single <textarea> node.  See "name" attribute.
+	_SEPARATOR: "@@**%%__RICHTEXTBOUNDRY__%%**@@",
+
+	// onLoadDeferred: [protected] dojo.Deferred
+	//		Deferred which is fired when the editor finishes loading
+	onLoadDeferred: null,
+
+	// isTabIndent: Boolean
+	//		Make tab key and shift-tab indent and outdent rather than navigating.
+	//		Caution: sing this makes web pages inaccessible to users unable to use a mouse.
+	isTabIndent: false,
+
+	// disableSpellCheck: [const] Boolean
+	//		When true, disables the browser's native spell checking, if supported.
+	//		Works only in Firefox.
+	disableSpellCheck: false,
+
+	postCreate: function(){
+		if("textarea" == this.domNode.tagName.toLowerCase()){
+			console.warn("RichText should not be used with the TEXTAREA tag.  See dijit._editor.RichText docs.");
+		}
+
+		this.inherited(arguments);
+
+		dojo.publish(dijit._scopeName + "._editor.RichText::init", [this]);
+		this.open();
+		this.setupDefaultShortcuts();
+	},
+
+	setupDefaultShortcuts: function(){
+		// summary:
+		//		Add some default key handlers
+		// description:
+		// 		Overwrite this to setup your own handlers. The default
+		// 		implementation does not use Editor commands, but directly
+		//		executes the builtin commands within the underlying browser
+		//		support.
+		// tags:
+		//		protected
+		var exec = dojo.hitch(this, function(cmd, arg){
+			return function(){
+				return !this.execCommand(cmd,arg);
+			};
+		});
+
+		var ctrlKeyHandlers = {
+			b: exec("bold"),
+			i: exec("italic"),
+			u: exec("underline"),
+			a: exec("selectall"),
+			s: function(){ this.save(true); },
+			m: function(){ this.isTabIndent = !this.isTabIndent; },
+
+			"1": exec("formatblock", "h1"),
+			"2": exec("formatblock", "h2"),
+			"3": exec("formatblock", "h3"),
+			"4": exec("formatblock", "h4"),
+
+			"\\": exec("insertunorderedlist")
+		};
+
+		if(!dojo.isIE){
+			ctrlKeyHandlers.Z = exec("redo"); //FIXME: undo?
+		}
+
+		for(var key in ctrlKeyHandlers){
+			this.addKeyHandler(key, true, false, ctrlKeyHandlers[key]);
+		}
+	},
+
+	// events: [private] String[]
+	//		 events which should be connected to the underlying editing area
+	events: ["onKeyPress", "onKeyDown", "onKeyUp", "onClick"],
+
+	// captureEvents: [deprecated] String[]
+	//		 Events which should be connected to the underlying editing
+	//		 area, events in this array will be addListener with
+	//		 capture=true.
+	// TODO: looking at the code I don't see any distinction between events and captureEvents,
+	// so get rid of this for 2.0 if not sooner
+	captureEvents: [],
+
+	_editorCommandsLocalized: false,
+	_localizeEditorCommands: function(){
+		// summary:
+		//		When IE is running in a non-English locale, the API actually changes,
+		//		so that we have to say (for example) danraku instead of p (for paragraph).
+		//		Handle that here.
+		// tags:
+		//		private
+		if(this._editorCommandsLocalized){
+			return;
+		}
+		this._editorCommandsLocalized = true;
+
+		//in IE, names for blockformat is locale dependent, so we cache the values here
+
+		//if the normal way fails, we try the hard way to get the list
+
+		//do not use _cacheLocalBlockFormatNames here, as it will
+		//trigger security warning in IE7
+
+		//put p after div, so if IE returns Normal, we show it as paragraph
+		//We can distinguish p and div if IE returns Normal, however, in order to detect that,
+		//we have to call this.document.selection.createRange().parentElement() or such, which
+		//could slow things down. Leave it as it is for now
+		var formats = ['div', 'p', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul', 'address'];
+		var localhtml = "", format, i=0;
+		while((format=formats[i++])){
+			//append a <br> after each element to separate the elements more reliably
+			if(format.charAt(1) != 'l'){
+				localhtml += "<"+format+"><span>content</span></"+format+"><br/>";
+			}else{
+				localhtml += "<"+format+"><li>content</li></"+format+"><br/>";
+			}
+		}
+		//queryCommandValue returns empty if we hide editNode, so move it out of screen temporary
+		var div = dojo.doc.createElement('div');
+		dojo.style(div, {
+			position: "absolute",
+			top: "-2000px"
+		});
+		dojo.doc.body.appendChild(div);
+		div.innerHTML = localhtml;
+		var node = div.firstChild;
+		while(node){
+			dijit._editor.selection.selectElement(node.firstChild);
+			dojo.withGlobal(this.window, "selectElement", dijit._editor.selection, [node.firstChild]);
+			var nativename = node.tagName.toLowerCase();
+			this._local2NativeFormatNames[nativename] = document.queryCommandValue("formatblock");
+			//this.queryCommandValue("formatblock");
+			this._native2LocalFormatNames[this._local2NativeFormatNames[nativename]] = nativename;
+			node = node.nextSibling.nextSibling;
+		}
+		dojo.body().removeChild(div);
+	},
+
+	open: function(/*DomNode?*/ element){
+		// summary:
+		//		Transforms the node referenced in this.domNode into a rich text editing
+		//		node.
+		// description:
+		//		Sets up the editing area asynchronously. This will result in
+		//		the creation and replacement with an iframe.
+		//
+		//		A dojo.Deferred object is created at this.onLoadDeferred, and
+		//		users may attach to it to be informed when the rich-text area
+		//		initialization is finalized.
+		// tags:
+		//		private
+
+		if(!this.onLoadDeferred || this.onLoadDeferred.fired >= 0){
+			this.onLoadDeferred = new dojo.Deferred();
+		}
+
+		if(!this.isClosed){ this.close(); }
+		dojo.publish(dijit._scopeName + "._editor.RichText::open", [ this ]);
+
+		this._content = "";
+		if(arguments.length == 1 && element.nodeName){ // else unchanged
+			this.domNode = element;
+		}
+
+		var dn = this.domNode;
+
+		// "html" will hold the innerHTML of the srcNodeRef and will be used to
+		// initialize the editor.
+		var html;
+
+		if(dojo.isString(this.value)){
+			// Allow setting the editor content programmatically instead of
+			// relying on the initial content being contained within the target
+			// domNode.
+			html = this.value;
+			delete this.value;
+			dn.innerHTML = "";
+		}else if(dn.nodeName && dn.nodeName.toLowerCase() == "textarea"){
+			// if we were created from a textarea, then we need to create a
+			// new editing harness node.
+			var ta = (this.textarea = dn);
+			this.name = ta.name;
+			html = ta.value;
+			dn = this.domNode = dojo.doc.createElement("div");
+			dn.setAttribute('widgetId', this.id);
+			ta.removeAttribute('widgetId');
+			dn.cssText = ta.cssText;
+			dn.className += " " + ta.className;
+			dojo.place(dn, ta, "before");
+			var tmpFunc = dojo.hitch(this, function(){
+				//some browsers refuse to submit display=none textarea, so
+				//move the textarea off screen instead
+				dojo.style(ta, {
+					display: "block",
+					position: "absolute",
+					top: "-1000px"
+				});
+
+				if(dojo.isIE){ //nasty IE bug: abnormal formatting if overflow is not hidden
+					var s = ta.style;
+					this.__overflow = s.overflow;
+					s.overflow = "hidden";
+				}
+			});
+			if(dojo.isIE){
+				setTimeout(tmpFunc, 10);
+			}else{
+				tmpFunc();
+			}
+
+			if(ta.form){
+				dojo.connect(ta.form, "onsubmit", this, function(){
+					// FIXME: should we be calling close() here instead?
+					ta.value = this.getValue();
+				});
+			}
+		}else{
+			html = dijit._editor.getChildrenHtml(dn);
+			dn.innerHTML = "";
+		}
+
+		var content = dojo.contentBox(dn);
+		this._oldHeight = content.h;
+		this._oldWidth = content.w;
+
+		this.savedContent = html;
+
+		// If we're a list item we have to put in a blank line to force the
+		// bullet to nicely align at the top of text
+		if(dn.nodeName && dn.nodeName == "LI"){
+			dn.innerHTML = " <br>";
+		}
+	
+		// Construct the editor div structure.
+		this.header = dn.ownerDocument.createElement("div");
+		dn.appendChild(this.header);
+		this.editingArea = dn.ownerDocument.createElement("div");
+		dn.appendChild(this.editingArea);
+		this.footer = dn.ownerDocument.createElement("div");
+		dn.appendChild(this.footer);
+
+		// User has pressed back/forward button so we lost the text in the editor, but it's saved
+		// in a hidden <textarea> (which contains the data for all the editors on this page),
+		// so get editor value from there
+		if(this.name !== "" && (!dojo.config["useXDomain"] || dojo.config["allowXdRichTextSave"])){
+			var saveTextarea = dojo.byId(dijit._scopeName + "._editor.RichText.savedContent");
+			if(saveTextarea.value !== ""){
+				var datas = saveTextarea.value.split(this._SEPARATOR), i=0, dat;
+				while((dat=datas[i++])){
+					var data = dat.split(":");
+					if(data[0] == this.name){
+						html = data[1];
+						datas.splice(i, 1);	// TODO: this has no effect
+						break;
+					}
+				}
+			}
+
+			// TODO: this is troublesome if this editor has been destroyed, should have global handler.
+			// TODO: need to clear <textarea> in global handler
+			dojo.addOnUnload(dojo.hitch(this, "_saveContent"));
+		}
+
+		this.isClosed = false;
+
+		var ifr = (this.editorObject = this.iframe = dojo.doc.createElement('iframe'));
+		ifr.id = this.id+"_iframe";
+		this._iframeSrc = this._getIframeDocTxt();
+		ifr.style.border = "none";
+		ifr.style.width = "100%";
+		if(this._layoutMode){
+			// iframe should be 100% height, thus getting it's height from surrounding
+			// <div> (which has the correct height set by Editor)
+			ifr.style.height = "100%";
+		}else{
+			if(dojo.isIE >= 7){
+				if(this.height){
+					ifr.style.height = this.height;
+				}
+				if(this.minHeight){
+					ifr.style.minHeight = this.minHeight;
+				}
+			}else{
+				ifr.style.height = this.height ? this.height : this.minHeight;
+			}
+		}
+		ifr.frameBorder = 0;
+		ifr._loadFunc = dojo.hitch( this, function(win){
+			this.window = win;
+			this.document = this.window.document;
+
+			if(dojo.isIE){
+				this._localizeEditorCommands();
+			}
+			
+			// Do final setup and set initial contents of editor
+			this.onLoad(html);
+		});
+
+		// Set the iframe's initial (blank) content.
+		var s = 'javascript:parent.' + dijit._scopeName + '.byId("'+this.id+'")._iframeSrc';
+		ifr.setAttribute('src', s);
+		this.editingArea.appendChild(ifr);
+
+		// TODO: this is a guess at the default line-height, kinda works
+		if(dn.nodeName == "LI"){
+			dn.lastChild.style.marginTop = "-1.2em";
+		}
+
+		dojo.addClass(this.domNode, this.baseClass);
+	},
+
+	//static cache variables shared among all instance of this class
+	_local2NativeFormatNames: {},
+	_native2LocalFormatNames: {},
+
+	_getIframeDocTxt: function(){
+		// summary:
+		//		Generates the boilerplate text of the document inside the iframe (ie, <html><head>...</head><body/></html>).
+		//		Editor content (if not blank) should be added afterwards.
+		// tags:
+		//		private
+		var _cs = dojo.getComputedStyle(this.domNode);
+
+		// The contents inside of <body>.  The real contents are set later via a call to setValue().
+		var html = "";
+		var setBodyId = true;
+		if(dojo.isIE || (!this.height && !dojo.isMoz)){
+			// In auto-expand mode, need a wrapper div for AlwaysShowToolbar plugin to correctly
+			// expand/contract the editor as the content changes.
+			html = "<div id='dijitEditorBody'></div>";
+			setBodyId = false;
+		}else if(dojo.isMoz){
+			// workaround bug where can't select then delete text (until user types something
+			// into the editor)... and/or issue where typing doesn't erase selected text
+			this._cursorToStart = true;
+			html = " ";
+		}
+
+		var font = [ _cs.fontWeight, _cs.fontSize, _cs.fontFamily ].join(" ");
+
+		// line height is tricky - applying a units value will mess things up.
+		// if we can't get a non-units value, bail out.
+		var lineHeight = _cs.lineHeight;
+		if(lineHeight.indexOf("px") >= 0){
+			lineHeight = parseFloat(lineHeight)/parseFloat(_cs.fontSize);
+			// console.debug(lineHeight);
+		}else if(lineHeight.indexOf("em")>=0){
+			lineHeight = parseFloat(lineHeight);
+		}else{
+			// If we can't get a non-units value, just default
+			// it to the CSS spec default of 'normal'.  Seems to
+			// work better, esp on IE, than '1.0'
+			lineHeight = "normal";
+		}
+		var userStyle = "";
+		var self = this;
+		this.style.replace(/(^|;)\s*(line-|font-?)[^;]+/ig, function(match){ 
+			match = match.replace(/^;/ig,"") + ';'; 
+			var s = match.split(":")[0];
+			if(s){
+				s = dojo.trim(s);
+				s = s.toLowerCase();
+				var i;
+				var sC = "";
+				for(i = 0; i < s.length; i++){
+					var c = s.charAt(i);
+					switch(c){
+						case "-":
+							i++;
+							c = s.charAt(i).toUpperCase();
+						default:
+							sC += c;
+					}
+				}
+				dojo.style(self.domNode, sC, "");
+			}
+			userStyle += match + ';'; 
+		});
+
+
+		// need to find any associated label element and update iframe document title
+		var label=dojo.query('label[for="'+this.id+'"]');
+
+		return [
+			this.isLeftToRight() ? "<html>\n<head>\n" : "<html dir='rtl'>\n<head>\n",
+			(dojo.isMoz && label.length ? "<title>" + label[0].innerHTML + "</title>\n" : ""),
+			"<meta http-equiv='Content-Type' content='text/html'>\n",
+			"<style>\n",
+			"\tbody,html {\n",
+			"\t\tbackground:transparent;\n",
+			"\t\tpadding: 1px 0 0 0;\n",
+			"\t\tmargin: -1px 0 0 0;\n", // remove extraneous vertical scrollbar on safari and firefox
+
+			// Set the html/body sizing.  Webkit always needs this, other browsers
+			// only set it when height is defined (not auto-expanding), otherwise 
+			// scrollers do not appear.
+			((dojo.isWebKit)?"\t\twidth: 100%;\n":""),
+			((dojo.isWebKit)?"\t\theight: 100%;\n":""),
+			"\t}\n",
+			
+			// TODO: left positioning will cause contents to disappear out of view
+			//	   if it gets too wide for the visible area
+			"\tbody{\n",
+			"\t\ttop:0px;\n",
+			"\t\tleft:0px;\n",
+			"\t\tright:0px;\n",
+			"\t\tfont:", font, ";\n",
+				((this.height||dojo.isOpera) ? "" : "\t\tposition: fixed;\n"),
+			// FIXME: IE 6 won't understand min-height?
+			"\t\tmin-height:", this.minHeight, ";\n",
+			"\t\tline-height:", lineHeight,";\n",
+			"\t}\n",
+			"\tp{ margin: 1em 0; }\n",
+			
+			// Determine how scrollers should be applied.  In autoexpand mode (height = "") no scrollers on y at all.
+			// But in fixed height mode we want both x/y scrollers.  Also, if it's using wrapping div and in auto-expand
+			// (Mainly IE) we need to kill the y scroller on body and html.
+			(!setBodyId && !this.height ? "\tbody,html {overflow-y: hidden;}\n" : ""),
+			"\t#dijitEditorBody{overflow-x: auto; overflow-y:" + (this.height ? "auto;" : "hidden;") + "}\n",
+			"\tli > ul:-moz-first-node, li > ol:-moz-first-node{ padding-top: 1.2em; }\n",
+			"\tli{ min-height:1.2em; }\n",
+			"</style>\n",
+			this._applyEditingAreaStyleSheets(),"\n",
+			"</head>\n<body ",
+			(setBodyId?"id='dijitEditorBody' ":""),
+			"onload='frameElement._loadFunc(window,document)' style='"+userStyle+"'>", html, "</body>\n</html>"
+		].join(""); // String
+	},
+
+	_applyEditingAreaStyleSheets: function(){
+		// summary:
+		//		apply the specified css files in styleSheets
+		// tags:
+		//		private
+		var files = [];
+		if(this.styleSheets){
+			files = this.styleSheets.split(';');
+			this.styleSheets = '';
+		}
+
+		//empty this.editingAreaStyleSheets here, as it will be filled in addStyleSheet
+		files = files.concat(this.editingAreaStyleSheets);
+		this.editingAreaStyleSheets = [];
+
+		var text='', i=0, url;
+		while((url=files[i++])){
+			var abstring = (new dojo._Url(dojo.global.location, url)).toString();
+			this.editingAreaStyleSheets.push(abstring);
+			text += '<link rel="stylesheet" type="text/css" href="'+abstring+'"/>';
+		}
+		return text;
+	},
+
+	addStyleSheet: function(/*dojo._Url*/ uri){
+		// summary:
+		//		add an external stylesheet for the editing area
+		// uri:
+		//		A dojo.uri.Uri pointing to the url of the external css file
+		var url=uri.toString();
+
+		//if uri is relative, then convert it to absolute so that it can be resolved correctly in iframe
+		if(url.charAt(0) == '.' || (url.charAt(0) != '/' && !uri.host)){
+			url = (new dojo._Url(dojo.global.location, url)).toString();
+		}
+
+		if(dojo.indexOf(this.editingAreaStyleSheets, url) > -1){
+//			console.debug("dijit._editor.RichText.addStyleSheet: Style sheet "+url+" is already applied");
+			return;
+		}
+
+		this.editingAreaStyleSheets.push(url);
+		this.onLoadDeferred.addCallback(dojo.hitch(function(){
+			if(this.document.createStyleSheet){ //IE
+				this.document.createStyleSheet(url);
+			}else{ //other browser
+				var head = this.document.getElementsByTagName("head")[0];
+				var stylesheet = this.document.createElement("link");
+				stylesheet.rel="stylesheet";
+				stylesheet.type="text/css";
+				stylesheet.href=url;
+				head.appendChild(stylesheet);
+			}
+		}));
+	},
+
+	removeStyleSheet: function(/*dojo._Url*/ uri){
+		// summary:
+		//		remove an external stylesheet for the editing area
+		var url=uri.toString();
+		//if uri is relative, then convert it to absolute so that it can be resolved correctly in iframe
+		if(url.charAt(0) == '.' || (url.charAt(0) != '/' && !uri.host)){
+			url = (new dojo._Url(dojo.global.location, url)).toString();
+		}
+		var index = dojo.indexOf(this.editingAreaStyleSheets, url);
+		if(index == -1){
+//			console.debug("dijit._editor.RichText.removeStyleSheet: Style sheet "+url+" has not been applied");
+			return;
+		}
+		delete this.editingAreaStyleSheets[index];
+		dojo.withGlobal(this.window,'query', dojo, ['link:[href="'+url+'"]']).orphan();
+	},
+
+	// disabled: Boolean
+	//		The editor is disabled; the text cannot be changed.
+	disabled: false,
+
+	_mozSettingProps: {'styleWithCSS':false},
+	_setDisabledAttr: function(/*Boolean*/ value){
+		this.disabled = value;
+		if(!this.isLoaded){ return; } // this method requires init to be complete
+		value = !!value;
+		if(dojo.isIE || dojo.isWebKit || dojo.isOpera){
+			var preventIEfocus = dojo.isIE && (this.isLoaded || !this.focusOnLoad);
+			if(preventIEfocus){ this.editNode.unselectable = "on"; }
+			this.editNode.contentEditable = !value;
+			if(preventIEfocus){
+				var _this = this;
+				setTimeout(function(){ _this.editNode.unselectable = "off"; }, 0);
+			}
+		}else{ //moz
+			try{
+				this.document.designMode=(value?'off':'on');
+			}catch(e){ return; } // ! _disabledOK
+			if(!value && this._mozSettingProps){
+				var ps = this._mozSettingProps;
+				for(var n in ps){
+					if(ps.hasOwnProperty(n)){
+						try{
+							this.document.execCommand(n,false,ps[n]);
+						}catch(e2){}
+					}
+				}
+			}
+//			this.document.execCommand('contentReadOnly', false, value);
+//				if(value){
+//					this.blur(); //to remove the blinking caret
+//				}
+		}
+		this._disabledOK = true;
+	},
+
+/* Event handlers
+ *****************/
+
+	onLoad: function(/*String*/ html){
+		// summary:
+		//		Handler after the iframe finishes loading.
+		// html: String
+		//		Editor contents should be set to this value
+		// tags:
+		//		protected
+
+		// TODO: rename this to _onLoad, make empty public onLoad() method, deprecate/make protected onLoadDeferred handler?
+
+		if(!this.window.__registeredWindow){
+			this.window.__registeredWindow = true;
+			this._iframeRegHandle = dijit.registerIframe(this.iframe);
+		}
+		if(!dojo.isIE && (this.height || dojo.isMoz)){
+			this.editNode=this.document.body;
+		}else{
+			// there's a wrapper div around the content, see _getIframeDocTxt().
+			this.editNode=this.document.body.firstChild;
+			var _this = this;
+			if(dojo.isIE){ // #4996 IE wants to focus the BODY tag
+				var tabStop = (this.tabStop = dojo.doc.createElement('<div tabIndex=-1>'));
+				this.editingArea.appendChild(tabStop);
+				this.iframe.onfocus = function(){ _this.editNode.setActive(); };
+			}
+		}
+		this.focusNode = this.editNode; // for InlineEditBox
+
+
+		var events = this.events.concat(this.captureEvents);
+		var ap = this.iframe ? this.document : this.editNode;
+		dojo.forEach(events, function(item){
+			this.connect(ap, item.toLowerCase(), item);
+		}, this);
+
+		if(dojo.isIE){ // IE contentEditable
+			this.connect(this.document, "onmousedown", "_onIEMouseDown"); // #4996 fix focus
+
+			// give the node Layout on IE
+			// TODO: this may no longer be needed, since we've reverted IE to using an iframe,
+			// not contentEditable.   Removing it would also probably remove the need for creating
+			// the extra <div> in _getIframeDocTxt()
+			this.editNode.style.zoom = 1.0;
+		}else{
+			this.connect(this.document, "onmousedown", function(){
+				// Clear the moveToStart focus, as mouse 
+				// down will set cursor point.  Required to properly
+				// work with selection/position driven plugins and clicks in
+				// the window. refs: #10678
+				delete this._cursorToStart;
+			}); 
+		}
+
+		if(dojo.isWebKit){
+			//WebKit sometimes doesn't fire right on selections, so the toolbar
+			//doesn't update right.  Therefore, help it out a bit with an additional
+			//listener.  A mouse up will typically indicate a display change, so fire this
+			//and get the toolbar to adapt.  Reference: #9532
+			this._webkitListener = this.connect(this.document, "onmouseup", "onDisplayChanged");
+		}
+
+		if(dojo.isIE){
+			// Try to make sure 'hidden' elements aren't visible in edit mode (like browsers other than IE
+			// do).  See #9103
+			try{
+				this.document.execCommand('RespectVisibilityInDesign', true, null);
+			}catch(e){/* squelch */}
+		}
+
+		this.isLoaded = true;
+
+		this.set('disabled', this.disabled); // initialize content to editable (or not)
+
+		// Note that setValue() call will only work after isLoaded is set to true (above)
+
+		// Set up a function to allow delaying the setValue until a callback is fired
+		// This ensures extensions like dijit.Editor have a way to hold the value set 
+		// until plugins load (and do things like register filters.
+		var setContent = dojo.hitch(this, function(){
+			this.setValue(html);
+			if(this.onLoadDeferred){
+				this.onLoadDeferred.callback(true);
+			}
+			this.onDisplayChanged();
+			if(this.focusOnLoad){
+				// after the document loads, then set focus after updateInterval expires so that
+				// onNormalizedDisplayChanged has run to avoid input caret issues
+				dojo.addOnLoad(dojo.hitch(this, function(){ setTimeout(dojo.hitch(this, "focus"), this.updateInterval); }));
+			}
+			// Save off the initial content now
+			this.savedContent = this.getValue(true);
+		});
+		if(this.setValueDeferred){
+			this.setValueDeferred.addCallback(setContent);
+		}else{
+			setContent();
+		}
+
+	},
+
+	onKeyDown: function(/* Event */ e){
+		// summary:
+		//		Handler for onkeydown event
+		// tags:
+		//		protected
+
+		// we need this event at the moment to get the events from control keys
+		// such as the backspace. It might be possible to add this to Dojo, so that
+		// keyPress events can be emulated by the keyDown and keyUp detection.
+
+		if(e.keyCode === dojo.keys.TAB && this.isTabIndent ){
+			dojo.stopEvent(e); //prevent tab from moving focus out of editor
+
+			// FIXME: this is a poor-man's indent/outdent. It would be
+			// better if it added 4 " " chars in an undoable way.
+			// Unfortunately pasteHTML does not prove to be undoable
+			if(this.queryCommandEnabled((e.shiftKey ? "outdent" : "indent"))){
+				this.execCommand((e.shiftKey ? "outdent" : "indent"));
+			}
+		}
+		if(dojo.isIE){
+			if(e.keyCode == dojo.keys.TAB && !this.isTabIndent){
+				if(e.shiftKey && !e.ctrlKey && !e.altKey){
+					// focus the BODY so the browser will tab away from it instead
+					this.iframe.focus();
+				}else if(!e.shiftKey && !e.ctrlKey && !e.altKey){
+					// focus the BODY so the browser will tab away from it instead
+					this.tabStop.focus();
+				}
+			}else if(e.keyCode === dojo.keys.BACKSPACE && this.document.selection.type === "Control"){
+				// IE has a bug where if a non-text object is selected in the editor,
+				// hitting backspace would act as if the browser's back button was
+				// clicked instead of deleting the object. see #1069
+				dojo.stopEvent(e);
+				this.execCommand("delete");
+			}else if((65 <= e.keyCode && e.keyCode <= 90) ||
+				(e.keyCode>=37 && e.keyCode<=40) // FIXME: get this from connect() instead!
+			){ //arrow keys
+				e.charCode = e.keyCode;
+				this.onKeyPress(e);
+			}
+		}
+		return true;
+	},
+
+	onKeyUp: function(e){
+		// summary:
+		//		Handler for onkeyup event
+		// tags:
+		//      callback
+		return;
+	},
+
+	setDisabled: function(/*Boolean*/ disabled){
+		// summary:
+		//		Deprecated, use set('disabled', ...) instead.
+		// tags:
+		//		deprecated
+		dojo.deprecated('dijit.Editor::setDisabled is deprecated','use dijit.Editor::attr("disabled",boolean) instead', 2.0);
+		this.set('disabled',disabled);
+	},
+	_setValueAttr: function(/*String*/ value){
+		// summary:
+		//      Registers that attr("value", foo) should call setValue(foo)
+		this.setValue(value);
+	},
+	_setDisableSpellCheckAttr: function(/*Boolean*/ disabled){
+		if(this.document){
+			dojo.attr(this.document.body, "spellcheck", !disabled);
+		}else{
+			// try again after the editor is finished loading
+			this.onLoadDeferred.addCallback(dojo.hitch(this, function(){
+				dojo.attr(this.document.body, "spellcheck", !disabled);
+			}));
+		}
+		this.disableSpellCheck = disabled;
+	},
+
+	onKeyPress: function(e){
+		// summary:
+		//		Handle the various key events
+		// tags:
+		//		protected
+
+		var c = (e.keyChar && e.keyChar.toLowerCase()) || e.keyCode,
+			handlers = this._keyHandlers[c],
+			args = arguments;
+
+		if(handlers && !e.altKey){
+			dojo.some(handlers, function(h){
+				// treat meta- same as ctrl-, for benefit of mac users
+				if(!(h.shift ^ e.shiftKey) && !(h.ctrl ^ (e.ctrlKey||e.metaKey))){
+					if(!h.handler.apply(this, args)){
+						e.preventDefault();
+					}
+					return true;
+				}
+			}, this);
+		}
+
+		// function call after the character has been inserted
+		if(!this._onKeyHitch){
+			this._onKeyHitch = dojo.hitch(this, "onKeyPressed");
+		}
+		setTimeout(this._onKeyHitch, 1);
+		return true;
+	},
+
+	addKeyHandler: function(/*String*/ key, /*Boolean*/ ctrl, /*Boolean*/ shift, /*Function*/ handler){
+		// summary:
+		//		Add a handler for a keyboard shortcut
+		// description:
+		//		The key argument should be in lowercase if it is a letter character
+		// tags:
+		//		protected
+		if(!dojo.isArray(this._keyHandlers[key])){
+			this._keyHandlers[key] = [];
+		}
+		//TODO: would be nice to make this a hash instead of an array for quick lookups
+		this._keyHandlers[key].push({
+			shift: shift || false,
+			ctrl: ctrl || false,
+			handler: handler
+		});
+	},
+
+	onKeyPressed: function(){
+		// summary:
+		//		Handler for after the user has pressed a key, and the display has been updated.
+		//		(Runs on a timer so that it runs after the display is updated)
+		// tags:
+		//		private
+		this.onDisplayChanged(/*e*/); // can't pass in e
+	},
+
+	onClick: function(/*Event*/ e){
+		// summary:
+		//		Handler for when the user clicks.
+		// tags:
+		//		private
+
+		// console.info('onClick',this._tryDesignModeOn);
+		this.onDisplayChanged(e);
+	},
+
+	_onIEMouseDown: function(/*Event*/ e){
+		// summary:
+		//		IE only to prevent 2 clicks to focus
+		// tags:
+		//		protected
+
+		if(!this._focused && !this.disabled){
+			this.focus();
+		}
+	},
+
+	_onBlur: function(e){
+		// summary:
+		//		Called from focus manager when focus has moved away from this editor
+		// tags:
+		//		protected
+
+		// console.info('_onBlur')
+
+		this.inherited(arguments);
+		var _c=this.getValue(true);
+
+		if(_c!=this.savedContent){
+			this.onChange(_c);
+			this.savedContent=_c;
+		}
+	},
+	_onFocus: function(/*Event*/ e){
+		// summary:
+		//		Called from focus manager when focus has moved into this editor
+		// tags:
+		//		protected
+
+		// console.info('_onFocus')
+		if(!this.disabled){
+			if(!this._disabledOK){
+				this.set('disabled', false);
+			}
+			this.inherited(arguments);
+		}
+	},
+
+	// TODO: why is this needed - should we deprecate this ?
+	blur: function(){
+		// summary:
+		//		Remove focus from this instance.
+		// tags:
+		//		deprecated
+		if(!dojo.isIE && this.window.document.documentElement && this.window.document.documentElement.focus){
+			this.window.document.documentElement.focus();
+		}else if(dojo.doc.body.focus){
+			dojo.doc.body.focus();
+		}
+	},
+
+	focus: function(){
+		// summary:
+		//		Move focus to this editor
+		if(!this.isLoaded){
+			this.focusOnLoad = true;
+			return;
+		}
+		if(this._cursorToStart){ 
+			delete this._cursorToStart;
+			if(this.editNode.childNodes){
+				this.placeCursorAtStart(); // this calls focus() so return
+				return;
+			}
+		}
+		if(!dojo.isIE){
+			dijit.focus(this.iframe);
+		}else if(this.editNode && this.editNode.focus){
+			// editNode may be hidden in display:none div, lets just punt in this case
+			//this.editNode.focus(); -> causes IE to scroll always (strict and quirks mode) to the top the Iframe
+			// if we fire the event manually and let the browser handle the focusing, the latest
+			// cursor position is focused like in FF
+			this.iframe.fireEvent('onfocus', document.createEventObject()); // createEventObject only in IE
+		//	}else{
+		// TODO: should we throw here?
+		// console.debug("Have no idea how to focus into the editor!");
+		}
+	},
+
+	// _lastUpdate: 0,
+	updateInterval: 200,
+	_updateTimer: null,
+	onDisplayChanged: function(/*Event*/ e){
+		// summary:
+		//		This event will be fired everytime the display context
+		//		changes and the result needs to be reflected in the UI.
+		// description:
+		//		If you don't want to have update too often,
+		//		onNormalizedDisplayChanged should be used instead
+		// tags:
+		//		private
+
+		// var _t=new Date();
+		if(this._updateTimer){
+			clearTimeout(this._updateTimer);
+		}
+		if(!this._updateHandler){
+			this._updateHandler = dojo.hitch(this,"onNormalizedDisplayChanged");
+		}
+		this._updateTimer = setTimeout(this._updateHandler, this.updateInterval);
+	},
+	onNormalizedDisplayChanged: function(){
+		// summary:
+		//		This event is fired every updateInterval ms or more
+		// description:
+		//		If something needs to happen immediately after a
+		//		user change, please use onDisplayChanged instead.
+		// tags:
+		//		private
+		delete this._updateTimer;
+	},
+	onChange: function(newContent){
+		// summary:
+		//		This is fired if and only if the editor loses focus and
+		//		the content is changed.
+	},
+	_normalizeCommand: function(/*String*/ cmd, /*Anything?*/argument){
+		// summary:
+		//		Used as the advice function by dojo.connect to map our
+		//		normalized set of commands to those supported by the target
+		//		browser.
+		// tags:
+		//		private
+
+		var command = cmd.toLowerCase();
+		if(command == "formatblock"){
+			if(dojo.isSafari && argument === undefined){ command = "heading"; }
+		}else if(command == "hilitecolor" && !dojo.isMoz){
+			command = "backcolor";
+		}
+
+		return command;
+	},
+
+	_qcaCache: {},
+	queryCommandAvailable: function(/*String*/ command){
+		// summary:
+		//		Tests whether a command is supported by the host. Clients
+		//		SHOULD check whether a command is supported before attempting
+		//		to use it, behaviour for unsupported commands is undefined.
+		// command:
+		//		The command to test for
+		// tags:
+		//		private
+
+		// memoizing version. See _queryCommandAvailable for computing version
+		var ca = this._qcaCache[command];
+		if(ca !== undefined){ return ca; }
+		return (this._qcaCache[command] = this._queryCommandAvailable(command));
+	},
+
+	_queryCommandAvailable: function(/*String*/ command){
+		// summary:
+		//		See queryCommandAvailable().
+		// tags:
+		//		private
+
+		var ie = 1;
+		var mozilla = 1 << 1;
+		var webkit = 1 << 2;
+		var opera = 1 << 3;
+		var webkit420 = 1 << 4;
+
+		function isSupportedBy(browsers){
+			return {
+				ie: Boolean(browsers & ie),
+				mozilla: Boolean(browsers & mozilla),
+				webkit: Boolean(browsers & webkit),
+				webkit420: Boolean(browsers & webkit420),
+				opera: Boolean(browsers & opera)
+			};
+		}
+
+		var supportedBy = null;
+
+		switch(command.toLowerCase()){
+			case "bold": case "italic": case "underline":
+			case "subscript": case "superscript":
+			case "fontname": case "fontsize":
+			case "forecolor": case "hilitecolor":
+			case "justifycenter": case "justifyfull": case "justifyleft":
+			case "justifyright": case "delete": case "selectall": case "toggledir":
+				supportedBy = isSupportedBy(mozilla | ie | webkit | opera);
+				break;
+
+			case "createlink": case "unlink": case "removeformat":
+			case "inserthorizontalrule": case "insertimage":
+			case "insertorderedlist": case "insertunorderedlist":
+			case "indent": case "outdent": case "formatblock":
+			case "inserthtml": case "undo": case "redo": case "strikethrough": case "tabindent":
+				supportedBy = isSupportedBy(mozilla | ie | opera | webkit420);
+				break;
+
+			case "blockdirltr": case "blockdirrtl":
+			case "dirltr": case "dirrtl":
+			case "inlinedirltr": case "inlinedirrtl":
+				supportedBy = isSupportedBy(ie);
+				break;
+			case "cut": case "copy": case "paste":
+				supportedBy = isSupportedBy( ie | mozilla | webkit420);
+				break;
+
+			case "inserttable":
+				supportedBy = isSupportedBy(mozilla | ie);
+				break;
+
+			case "insertcell": case "insertcol": case "insertrow":
+			case "deletecells": case "deletecols": case "deleterows":
+			case "mergecells": case "splitcell":
+				supportedBy = isSupportedBy(ie | mozilla);
+				break;
+
+			default: return false;
+		}
+
+		return (dojo.isIE && supportedBy.ie) ||
+			(dojo.isMoz && supportedBy.mozilla) ||
+			(dojo.isWebKit && supportedBy.webkit) ||
+			(dojo.isWebKit > 420 && supportedBy.webkit420) ||
+			(dojo.isOpera && supportedBy.opera);	// Boolean return true if the command is supported, false otherwise
+	},
+
+	execCommand: function(/*String*/ command, argument){
+		// summary:
+		//		Executes a command in the Rich Text area
+		// command:
+		//		The command to execute
+		// argument:
+		//		An optional argument to the command
+		// tags:
+		//		protected
+		var returnValue;
+
+		//focus() is required for IE to work
+		//In addition, focus() makes sure after the execution of
+		//the command, the editor receives the focus as expected
+		this.focus();
+
+		command = this._normalizeCommand(command, argument);
+
+
+		if(argument !== undefined){
+			if(command == "heading"){
+				throw new Error("unimplemented");
+			}else if((command == "formatblock") && dojo.isIE){
+				argument = '<'+argument+'>';
+			}
+		}
+
+		//Check to see if we have any over-rides for commands, they will be functions on this
+		//widget of the form _commandImpl.  If we don't, fall through to the basic native
+		//exec command of the browser.
+		var implFunc = "_" + command + "Impl";
+		if(this[implFunc]){
+			returnValue = this[implFunc](argument);
+		}else{
+			argument = arguments.length > 1 ? argument : null;
+			if(argument || command!="createlink"){
+				returnValue = this.document.execCommand(command, false, argument);
+			}
+		}
+
+		this.onDisplayChanged();
+		return returnValue;
+	},
+
+	queryCommandEnabled: function(/*String*/ command){
+		// summary:
+		//		Check whether a command is enabled or not.
+		// tags:
+		//		protected
+		if(this.disabled || !this._disabledOK){ return false; }
+		command = this._normalizeCommand(command);
+		if(dojo.isMoz || dojo.isWebKit){
+			if(command == "unlink"){ // mozilla returns true always
+				// console.debug(this._sCall("hasAncestorElement", ['a']));
+				return this._sCall("hasAncestorElement", ["a"]);
+			}else if(command == "inserttable"){
+				return true;
+			}
+		}
+		//see #4109
+		if(dojo.isWebKit){
+			if(command == "copy"){
+				command = "cut";
+			}else if(command == "paste"){
+				return true;
+			}
+		}
+
+		var elem = dojo.isIE ? this.document.selection.createRange() : this.document;
+		try{
+			return elem.queryCommandEnabled(command);
+		}catch(e){
+			//Squelch, occurs if editor is hidden on FF 3 (and maybe others.)
+			return false;
+		}
+
+	},
+
+	queryCommandState: function(command){
+		// summary:
+		//		Check the state of a given command and returns true or false.
+		// tags:
+		//		protected
+
+		if(this.disabled || !this._disabledOK){ return false; }
+		command = this._normalizeCommand(command);
+		try{
+			return this.document.queryCommandState(command);
+		}catch(e){
+			//Squelch, occurs if editor is hidden on FF 3 (and maybe others.)
+			return false;
+		}
+	},
+
+	queryCommandValue: function(command){
+		// summary:
+		//		Check the value of a given command. This matters most for
+		//		custom selections and complex values like font value setting.
+		// tags:
+		//		protected
+
+		if(this.disabled || !this._disabledOK){ return false; }
+		var r;
+		command = this._normalizeCommand(command);
+		if(dojo.isIE && command == "formatblock"){
+			r = this._native2LocalFormatNames[this.document.queryCommandValue(command)];
+		}else if(dojo.isMoz && command === "hilitecolor"){
+			var oldValue;
+			try{
+				oldValue = this.document.queryCommandValue("styleWithCSS");
+			}catch(e){
+				oldValue = false;
+			}
+			this.document.execCommand("styleWithCSS", false, true);
+			r = this.document.queryCommandValue(command);
+			this.document.execCommand("styleWithCSS", false, oldValue);
+		}else{
+			r = this.document.queryCommandValue(command);
+		}
+		return r;
+	},
+
+	// Misc.
+
+	_sCall: function(name, args){
+		// summary:
+		//		Run the named method of dijit._editor.selection over the
+		//		current editor instance's window, with the passed args.
+		// tags:
+		//		private
+		return dojo.withGlobal(this.window, name, dijit._editor.selection, args);
+	},
+
+	// FIXME: this is a TON of code duplication. Why?
+
+	placeCursorAtStart: function(){
+		// summary:
+		//		Place the cursor at the start of the editing area.
+		// tags:
+		//		private
+
+		this.focus();
+
+		//see comments in placeCursorAtEnd
+		var isvalid=false;
+		if(dojo.isMoz){
+			// TODO:  Is this branch even necessary?
+			var first=this.editNode.firstChild;
+			while(first){
+				if(first.nodeType == 3){
+					if(first.nodeValue.replace(/^\s+|\s+$/g, "").length>0){
+						isvalid=true;
+						this._sCall("selectElement", [ first ]);
+						break;
+					}
+				}else if(first.nodeType == 1){
+					isvalid=true;
+					var tg = first.tagName ? first.tagName.toLowerCase() : "";
+					// Collapse before childless tags.
+					if(/br|input|img|base|meta|area|basefont|hr|link/.test(tg)){
+						this._sCall("selectElement", [ first ]);
+					}else{
+						// Collapse inside tags with children.
+						this._sCall("selectElementChildren", [ first ]);
+					}
+					break;
+				}
+				first = first.nextSibling;
+			}
+		}else{
+			isvalid=true;
+			this._sCall("selectElementChildren", [ this.editNode ]);
+		}
+		if(isvalid){
+			this._sCall("collapse", [ true ]);
+		}
+	},
+
+	placeCursorAtEnd: function(){
+		// summary:
+		//		Place the cursor at the end of the editing area.
+		// tags:
+		//		private
+
+		this.focus();
+
+		//In mozilla, if last child is not a text node, we have to use
+		// selectElementChildren on this.editNode.lastChild otherwise the
+		// cursor would be placed at the end of the closing tag of
+		//this.editNode.lastChild
+		var isvalid=false;
+		if(dojo.isMoz){
+			var last=this.editNode.lastChild;
+			while(last){
+				if(last.nodeType == 3){
+					if(last.nodeValue.replace(/^\s+|\s+$/g, "").length>0){
+						isvalid=true;
+						this._sCall("selectElement", [ last ]);
+						break;
+					}
+				}else if(last.nodeType == 1){
+					isvalid=true;
+					if(last.lastChild){
+						this._sCall("selectElement", [ last.lastChild ]);
+					}else{
+						this._sCall("selectElement", [ last ]);
+					}
+					break;
+				}
+				last = last.previousSibling;
+			}
+		}else{
+			isvalid=true;
+			this._sCall("selectElementChildren", [ this.editNode ]);
+		}
+		if(isvalid){
+			this._sCall("collapse", [ false ]);
+		}
+	},
+
+	getValue: function(/*Boolean?*/ nonDestructive){
+		// summary:
+		//		Return the current content of the editing area (post filters
+		//		are applied).  Users should call attr('value') instead.
+		//	nonDestructive:
+		//		defaults to false. Should the post-filtering be run over a copy
+		//		of the live DOM? Most users should pass "true" here unless they
+		//		*really* know that none of the installed filters are going to
+		//		mess up the editing session.
+		// tags:
+		//		private
+		if(this.textarea){
+			if(this.isClosed || !this.isLoaded){
+				return this.textarea.value;
+			}
+		}
+
+		return this._postFilterContent(null, nonDestructive);
+	},
+	_getValueAttr: function(){
+		// summary:
+		//		Hook to make attr("value") work
+		return this.getValue(true);
+	},
+
+	setValue: function(/*String*/ html){
+		// summary:
+		//		This function sets the content. No undo history is preserved.
+		//		Users should use set('value', ...) instead.
+		// tags:
+		//		deprecated
+
+		// TODO: remove this and getValue() for 2.0, and move code to _setValueAttr()
+
+		if(!this.isLoaded){
+			// try again after the editor is finished loading
+			this.onLoadDeferred.addCallback(dojo.hitch(this, function(){
+				this.setValue(html);
+			}));
+			return;
+		}
+		this._cursorToStart = true;
+		if(this.textarea && (this.isClosed || !this.isLoaded)){
+			this.textarea.value=html;
+		}else{
+			html = this._preFilterContent(html);
+			var node = this.isClosed ? this.domNode : this.editNode;
+
+			// Use   to avoid webkit problems where editor is disabled until the user clicks it
+			if(!html && dojo.isWebKit){
+				html = " ";
+			}
+			node.innerHTML = html;
+			this._preDomFilterContent(node);
+		}
+		this.onDisplayChanged();
+	},
+
+	replaceValue: function(/*String*/ html){
+		// summary:
+		//		This function set the content while trying to maintain the undo stack
+		//		(now only works fine with Moz, this is identical to setValue in all
+		//		other browsers)
+		// tags:
+		//		protected
+
+		if(this.isClosed){
+			this.setValue(html);
+		}else if(this.window && this.window.getSelection && !dojo.isMoz){ // Safari
+			// look ma! it's a totally f'd browser!
+			this.setValue(html);
+		}else if(this.window && this.window.getSelection){ // Moz
+			html = this._preFilterContent(html);
+			this.execCommand("selectall");
+			if(!html){ 
+				this._cursorToStart = true;
+				html = " "; 
+			}
+			this.execCommand("inserthtml", html);
+			this._preDomFilterContent(this.editNode);
+		}else if(this.document && this.document.selection){//IE
+			//In IE, when the first element is not a text node, say
+			//an <a> tag, when replacing the content of the editing
+			//area, the <a> tag will be around all the content
+			//so for now, use setValue for IE too
+			this.setValue(html);
+		}
+	},
+
+	_preFilterContent: function(/*String*/ html){
+		// summary:
+		//		Filter the input before setting the content of the editing
+		//		area. DOM pre-filtering may happen after this
+		//		string-based filtering takes place but as of 1.2, this is not
+		//		guaranteed for operations such as the inserthtml command.
+		// tags:
+		//		private
+
+		var ec = html;
+		dojo.forEach(this.contentPreFilters, function(ef){ if(ef){ ec = ef(ec); } });
+		return ec;
+	},
+	_preDomFilterContent: function(/*DomNode*/ dom){
+		// summary:
+		//		filter the input's live DOM. All filter operations should be
+		//		considered to be "live" and operating on the DOM that the user
+		//		will be interacting with in their editing session.
+		// tags:
+		//		private
+		dom = dom || this.editNode;
+		dojo.forEach(this.contentDomPreFilters, function(ef){
+			if(ef && dojo.isFunction(ef)){
+				ef(dom);
+			}
+		}, this);
+	},
+
+	_postFilterContent: function(
+		/*DomNode|DomNode[]|String?*/ dom,
+		/*Boolean?*/ nonDestructive){
+		// summary:
+		//		filter the output after getting the content of the editing area
+		//
+		// description:
+		//		post-filtering allows plug-ins and users to specify any number
+		//		of transforms over the editor's content, enabling many common
+		//		use-cases such as transforming absolute to relative URLs (and
+		//		vice-versa), ensuring conformance with a particular DTD, etc.
+		//		The filters are registered in the contentDomPostFilters and
+		//		contentPostFilters arrays. Each item in the
+		//		contentDomPostFilters array is a function which takes a DOM
+		//		Node or array of nodes as its only argument and returns the
+		//		same. It is then passed down the chain for further filtering.
+		//		The contentPostFilters array behaves the same way, except each
+		//		member operates on strings. Together, the DOM and string-based
+		//		filtering allow the full range of post-processing that should
+		//		be necessaray to enable even the most agressive of post-editing
+		//		conversions to take place.
+		//
+		//		If nonDestructive is set to "true", the nodes are cloned before
+		//		filtering proceeds to avoid potentially destructive transforms
+		//		to the content which may still needed to be edited further.
+		//		Once DOM filtering has taken place, the serialized version of
+		//		the DOM which is passed is run through each of the
+		//		contentPostFilters functions.
+		//
+		//	dom:
+		//		a node, set of nodes, which to filter using each of the current
+		//		members of the contentDomPostFilters and contentPostFilters arrays.
+		//
+		//	nonDestructive:
+		//		defaults to "false". If true, ensures that filtering happens on
+		//		a clone of the passed-in content and not the actual node
+		//		itself.
+		//
+		// tags:
+		//		private
+
+		var ec;
+		if(!dojo.isString(dom)){
+			dom = dom || this.editNode;
+			if(this.contentDomPostFilters.length){
+				if(nonDestructive){
+					dom = dojo.clone(dom);
+				}
+				dojo.forEach(this.contentDomPostFilters, function(ef){
+					dom = ef(dom);
+				});
+			}
+			ec = dijit._editor.getChildrenHtml(dom);
+		}else{
+			ec = dom;
+		}
+
+		if(!dojo.trim(ec.replace(/^\xA0\xA0*/, '').replace(/\xA0\xA0*$/, '')).length){
+			ec = "";
+		}
+
+		//	if(dojo.isIE){
+		//		//removing appended <P> </P> for IE
+		//		ec = ec.replace(/(?:<p> </p>[\n\r]*)+$/i,"");
+		//	}
+		dojo.forEach(this.contentPostFilters, function(ef){
+			ec = ef(ec);
+		});
+
+		return ec;
+	},
+
+	_saveContent: function(/*Event*/ e){
+		// summary:
+		//		Saves the content in an onunload event if the editor has not been closed
+		// tags:
+		//		private
+
+		var saveTextarea = dojo.byId(dijit._scopeName + "._editor.RichText.savedContent");
+		if(saveTextarea.value){
+			saveTextarea.value += this._SEPARATOR;
+		}
+		saveTextarea.value += this.name + ":" + this.getValue(true);
+	},
+
+
+	escapeXml: function(/*String*/ str, /*Boolean*/ noSingleQuotes){
+		// summary:
+		//		Adds escape sequences for special characters in XML.
+		//		Optionally skips escapes for single quotes
+		// tags:
+		//		private
+
+		str = str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """);
+		if(!noSingleQuotes){
+			str = str.replace(/'/gm, "'");
+		}
+		return str; // string
+	},
+
+	getNodeHtml: function(/* DomNode */ node){
+		// summary:
+		//		Deprecated.   Use dijit._editor._getNodeHtml() instead.
+		// tags:
+		//		deprecated
+		dojo.deprecated('dijit.Editor::getNodeHtml is deprecated','use dijit._editor.getNodeHtml instead', 2);
+		return dijit._editor.getNodeHtml(node); // String
+	},
+
+	getNodeChildrenHtml: function(/* DomNode */ dom){
+		// summary:
+		//		Deprecated.   Use dijit._editor.getChildrenHtml() instead.
+		// tags:
+		//		deprecated
+		dojo.deprecated('dijit.Editor::getNodeChildrenHtml is deprecated','use dijit._editor.getChildrenHtml instead', 2);
+		return dijit._editor.getChildrenHtml(dom);
+	},
+
+	close: function(/*Boolean*/ save){
+		// summary:
+		//		Kills the editor and optionally writes back the modified contents to the
+		//		element from which it originated.
+		// save:
+		//		Whether or not to save the changes. If false, the changes are discarded.
+		// tags:
+		//		private
+
+		if(this.isClosed){return false; }
+
+		if(!arguments.length){ save = true; }
+		this._content = this.getValue();
+		var changed = (this.savedContent != this._content);
+
+		// line height is squashed for iframes
+		// FIXME: why was this here? if (this.iframe){ this.domNode.style.lineHeight = null; }
+
+		if(this.interval){ clearInterval(this.interval); }
+
+		if(this._webkitListener){
+			//Cleaup of WebKit fix: #9532
+			this.disconnect(this._webkitListener);
+			delete this._webkitListener;
+		}
+
+		// Guard against memory leaks on IE (see #9268)
+		if(dojo.isIE){
+			 this.iframe.onfocus = null;
+		}
+		this.iframe._loadFunc = null;
+
+		if(this._iframeRegHandle){
+			dijit.unregisterIframe(this._iframeRegHandle);
+			delete this._iframeRegHandle;
+		}
+
+		if(this.textarea){
+			var s = this.textarea.style;
+			s.position = "";
+			s.left = s.top = "";
+			if(dojo.isIE){
+				s.overflow = this.__overflow;
+				this.__overflow = null;
+			}
+			this.textarea.value = save ? this._content : this.savedContent;
+			dojo.destroy(this.domNode);
+			this.domNode = this.textarea;
+		}else{
+			// if(save){
+			// why we treat moz differently? comment out to fix #1061
+			//		if(dojo.isMoz){
+			//			var nc = dojo.doc.createElement("span");
+			//			this.domNode.appendChild(nc);
+			//			nc.innerHTML = this.editNode.innerHTML;
+			//		}else{
+			//			this.domNode.innerHTML = this._content;
+			//		}
+			// }
+
+			// Note that this destroys the iframe
+			this.domNode.innerHTML = save ? this._content : this.savedContent;
+		}
+		delete this.iframe;
+
+		dojo.removeClass(this.domNode, this.baseClass);
+		this.isClosed = true;
+		this.isLoaded = false;
+
+		delete this.editNode;
+		delete this.focusNode;
+
+		if(this.window && this.window._frameElement){
+			this.window._frameElement = null;
+		}
+
+		this.window = null;
+		this.document = null;
+		this.editingArea = null;
+		this.editorObject = null;
+
+		return changed; // Boolean: whether the content has been modified
+	},
+
+	destroy: function(){
+		if(!this.isClosed){ this.close(false); }
+		this.inherited(arguments);
+	},
+
+	_removeMozBogus: function(/* String */ html){
+		// summary:
+		//		Post filter to remove unwanted HTML attributes generated by mozilla
+		// tags:
+		//		private
+		return html.replace(/\stype="_moz"/gi, '').replace(/\s_moz_dirty=""/gi, '').replace(/_moz_resizing="(true|false)"/gi,''); // String
+	},
+	_removeWebkitBogus: function(/* String */ html){
+		// summary:
+		//		Post filter to remove unwanted HTML attributes generated by webkit
+		// tags:
+		//		private
+		html = html.replace(/\sclass="webkit-block-placeholder"/gi, '');
+		html = html.replace(/\sclass="apple-style-span"/gi, '');
+		return html; // String
+	},
+	_normalizeFontStyle: function(/* String */ html){
+		// summary:
+		//		Convert 'strong' and 'em' to 'b' and 'i'.
+		// description:
+		//		Moz can not handle strong/em tags correctly, so to help
+		//		mozilla and also to normalize output, convert them to 'b' and 'i'.
+		//
+		//		Note the IE generates 'strong' and 'em' rather than 'b' and 'i'
+		// tags:
+		//		private
+		return html.replace(/<(\/)?strong([ \>])/gi, '<$1b$2')
+			.replace(/<(\/)?em([ \>])/gi, '<$1i$2' ); // String
+	},
+
+	_preFixUrlAttributes: function(/* String */ html){
+		// summary:
+		//		Pre-filter to do fixing to href attributes on <a> and <img> tags
+		// tags:
+		//		private
+		return html.replace(/(?:(<a(?=\s).*?\shref=)("|')(.*?)\2)|(?:(<a\s.*?href=)([^"'][^ >]+))/gi,
+				'$1$4$2$3$5$2 _djrealurl=$2$3$5$2')
+			.replace(/(?:(<img(?=\s).*?\ssrc=)("|')(.*?)\2)|(?:(<img\s.*?src=)([^"'][^ >]+))/gi,
+				'$1$4$2$3$5$2 _djrealurl=$2$3$5$2'); // String
+	},
+
+	/*****************************************************************************
+		The following functions implement HTML manipulation commands for various
+		browser/contentEditable implementations.  The goal of them is to enforce
+		standard behaviors of them.
+	******************************************************************************/
+
+	_inserthorizontalruleImpl: function(argument){
+		// summary:
+		//		This function implements the insertion of HTML 'HR' tags.
+		//		into a point on the page.  IE doesn't to it right, so
+		//		we have to use an alternate form
+		// argument:
+		//		arguments to the exec command, if any.
+		// tags:
+		//		protected
+		if(dojo.isIE){
+			return this._inserthtmlImpl("<hr>");
+		}
+		return this.document.execCommand("inserthorizontalrule", false, argument);
+	},
+
+	_unlinkImpl: function(argument){
+		// summary:
+		//		This function implements the unlink of an 'a' tag.
+		// argument:
+		//		arguments to the exec command, if any.
+		// tags:
+		//		protected
+		if((this.queryCommandEnabled("unlink")) && (dojo.isMoz || dojo.isWebKit)){
+			var a = this._sCall("getAncestorElement", [ "a" ]);
+			this._sCall("selectElement", [ a ]);
+			return this.document.execCommand("unlink", false, null);
+		}
+		return this.document.execCommand("unlink", false, argument);
+	},
+
+	_hilitecolorImpl: function(argument){
+		// summary:
+		//		This function implements the hilitecolor command
+		// argument:
+		//		arguments to the exec command, if any.
+		// tags:
+		//		protected
+		var returnValue;
+		if(dojo.isMoz){
+			// mozilla doesn't support hilitecolor properly when useCSS is
+			// set to false (bugzilla #279330)
+			this.document.execCommand("styleWithCSS", false, true);
+			returnValue = this.document.execCommand("hilitecolor", false, argument);
+			this.document.execCommand("styleWithCSS", false, false);
+		}else{
+			returnValue = this.document.execCommand("hilitecolor", false, argument);
+		}
+		return returnValue;
+	},
+
+	_backcolorImpl: function(argument){
+		// summary:
+		//		This function implements the backcolor command
+		// argument:
+		//		arguments to the exec command, if any.
+		// tags:
+		//		protected
+		if(dojo.isIE){
+			// Tested under IE 6 XP2, no problem here, comment out
+			// IE weirdly collapses ranges when we exec these commands, so prevent it
+			//	var tr = this.document.selection.createRange();
+			argument = argument ? argument : null;
+		}
+		return this.document.execCommand("backcolor", false, argument);
+	},
+
+	_forecolorImpl: function(argument){
+		// summary:
+		//		This function implements the forecolor command
+		// argument:
+		//		arguments to the exec command, if any.
+		// tags:
+		//		protected
+		if(dojo.isIE){
+			// Tested under IE 6 XP2, no problem here, comment out
+			// IE weirdly collapses ranges when we exec these commands, so prevent it
+			//	var tr = this.document.selection.createRange();
+			argument = argument? argument : null;
+		}
+		return this.document.execCommand("forecolor", false, argument);
+	},
+
+	_inserthtmlImpl: function(argument){
+		// summary:
+		//		This function implements the insertion of HTML content into
+		//		a point on the page.
+		// argument:
+		//		The content to insert, if any.
+		// tags:
+		//		protected
+		argument = this._preFilterContent(argument);
+		var rv = true;
+		if(dojo.isIE){
+			var insertRange = this.document.selection.createRange();
+			if(this.document.selection.type.toUpperCase() == 'CONTROL'){
+				var n=insertRange.item(0);
+				while(insertRange.length){
+					insertRange.remove(insertRange.item(0));
+				}
+				n.outerHTML=argument;
+			}else{
+				insertRange.pasteHTML(argument);
+			}
+			insertRange.select();
+			//insertRange.collapse(true);
+		}else if(dojo.isMoz && !argument.length){
+			//mozilla can not inserthtml an empty html to delete current selection
+			//so we delete the selection instead in this case
+			this._sCall("remove"); // FIXME
+		}else{
+			rv = this.document.execCommand("inserthtml", false, argument);
+		}
+		return rv;
+	},
+
+	getHeaderHeight: function(){
+		// summary:
+		//		A function for obtaining the height of the header node
+		return this._getNodeChildrenHeight(this.header); // Number
+	},
+
+	getFooterHeight: function(){
+		// summary:
+		//		A function for obtaining the height of the footer node
+		return this._getNodeChildrenHeight(this.footer); // Number
+	},
+
+	_getNodeChildrenHeight: function(node){
+		// summary:
+		//		An internal function for computing the cumulative height of all child nodes of 'node'
+		// node:
+		//		The node to process the children of;
+		var h = 0;
+		if(node && node.childNodes){
+			// IE didn't compute it right when position was obtained on the node directly is some cases, 
+			// so we have to walk over all the children manually.
+			var i; 
+			for(i = 0; i < node.childNodes.length; i++){ 
+				var size = dojo.position(node.childNodes[i]); 
+				h += size.h;   
+			} 
+		}
+		return h; // Number
+	}
 });
-return ec;
-},_saveContent:function(e){
-var _54=dojo.byId(dijit._scopeName+"._editor.RichText.savedContent");
-if(_54.value){
-_54.value+=this._SEPARATOR;
-}
-_54.value+=this.name+":"+this.getValue(true);
-},escapeXml:function(str,_55){
-str=str.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,""");
-if(!_55){
-str=str.replace(/'/gm,"'");
-}
-return str;
-},getNodeHtml:function(_56){
-dojo.deprecated("dijit.Editor::getNodeHtml is deprecated","use dijit._editor.getNodeHtml instead",2);
-return dijit._editor.getNodeHtml(_56);
-},getNodeChildrenHtml:function(dom){
-dojo.deprecated("dijit.Editor::getNodeChildrenHtml is deprecated","use dijit._editor.getChildrenHtml instead",2);
-return dijit._editor.getChildrenHtml(dom);
-},close:function(_57){
-if(this.isClosed){
-return false;
-}
-if(!arguments.length){
-_57=true;
-}
-this._content=this.getValue();
-var _58=(this.savedContent!=this._content);
-if(this.interval){
-clearInterval(this.interval);
-}
-if(this._webkitListener){
-this.disconnect(this._webkitListener);
-delete this._webkitListener;
-}
-if(dojo.isIE){
-this.iframe.onfocus=null;
-}
-this.iframe._loadFunc=null;
-if(this._iframeRegHandle){
-dijit.unregisterIframe(this._iframeRegHandle);
-delete this._iframeRegHandle;
-}
-if(this.textarea){
-var s=this.textarea.style;
-s.position="";
-s.left=s.top="";
-if(dojo.isIE){
-s.overflow=this.__overflow;
-this.__overflow=null;
-}
-this.textarea.value=_57?this._content:this.savedContent;
-dojo.destroy(this.domNode);
-this.domNode=this.textarea;
-}else{
-this.domNode.innerHTML=_57?this._content:this.savedContent;
-}
-delete this.iframe;
-dojo.removeClass(this.domNode,"RichTextEditable");
-this.isClosed=true;
-this.isLoaded=false;
-delete this.editNode;
-delete this.focusNode;
-if(this.window&&this.window._frameElement){
-this.window._frameElement=null;
-}
-this.window=null;
-this.document=null;
-this.editingArea=null;
-this.editorObject=null;
-return _58;
-},destroy:function(){
-if(!this.isClosed){
-this.close(false);
-}
-this.inherited(arguments);
-},_removeMozBogus:function(_59){
-return _59.replace(/\stype="_moz"/gi,"").replace(/\s_moz_dirty=""/gi,"").replace(/_moz_resizing="(true|false)"/gi,"");
-},_removeWebkitBogus:function(_5a){
-_5a=_5a.replace(/\sclass="webkit-block-placeholder"/gi,"");
-_5a=_5a.replace(/\sclass="apple-style-span"/gi,"");
-return _5a;
-},_normalizeFontStyle:function(_5b){
-return _5b.replace(/<(\/)?strong([ \>])/gi,"<$1b$2").replace(/<(\/)?em([ \>])/gi,"<$1i$2");
-},_preFixUrlAttributes:function(_5c){
-return _5c.replace(/(?:(<a(?=\s).*?\shref=)("|')(.*?)\2)|(?:(<a\s.*?href=)([^"'][^ >]+))/gi,"$1$4$2$3$5$2 _djrealurl=$2$3$5$2").replace(/(?:(<img(?=\s).*?\ssrc=)("|')(.*?)\2)|(?:(<img\s.*?src=)([^"'][^ >]+))/gi,"$1$4$2$3$5$2 _djrealurl=$2$3$5$2");
-},_inserthorizontalruleImpl:function(_5d){
-if(dojo.isIE){
-return this._inserthtmlImpl("<hr>");
-}
-return this.document.execCommand("inserthorizontalrule",false,_5d);
-},_unlinkImpl:function(_5e){
-if((this.queryCommandEnabled("unlink"))&&(dojo.isMoz||dojo.isWebKit)){
-var a=this._sCall("getAncestorElement",["a"]);
-this._sCall("selectElement",[a]);
-return this.document.execCommand("unlink",false,null);
-}
-return this.document.execCommand("unlink",false,_5e);
-},_hilitecolorImpl:function(_5f){
-var _60;
-if(dojo.isMoz){
-this.document.execCommand("styleWithCSS",false,true);
-_60=this.document.execCommand("hilitecolor",false,_5f);
-this.document.execCommand("styleWithCSS",false,false);
-}else{
-_60=this.document.execCommand("hilitecolor",false,_5f);
-}
-return _60;
-},_backcolorImpl:function(_61){
-if(dojo.isIE){
-_61=_61?_61:null;
-}
-return this.document.execCommand("backcolor",false,_61);
-},_forecolorImpl:function(_62){
-if(dojo.isIE){
-_62=_62?_62:null;
-}
-return this.document.execCommand("forecolor",false,_62);
-},_inserthtmlImpl:function(_63){
-_63=this._preFilterContent(_63);
-var rv=true;
-if(dojo.isIE){
-var _64=this.document.selection.createRange();
-if(this.document.selection.type.toUpperCase()=="CONTROL"){
-var n=_64.item(0);
-while(_64.length){
-_64.remove(_64.item(0));
-}
-n.outerHTML=_63;
-}else{
-_64.pasteHTML(_63);
-}
-_64.select();
-}else{
-if(dojo.isMoz&&!_63.length){
-this._sCall("remove");
-}else{
-rv=this.document.execCommand("inserthtml",false,_63);
-}
-}
-return rv;
-}});
-}
diff --git a/dijit/_editor/_Plugin.js b/dijit/_editor/_Plugin.js
index c92ba5f..49a5225 100644
--- a/dijit/_editor/_Plugin.js
+++ b/dijit/_editor/_Plugin.js
@@ -1,76 +1,172 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._editor._Plugin"]){
-dojo._hasResource["dijit._editor._Plugin"]=true;
 dojo.provide("dijit._editor._Plugin");
 dojo.require("dijit._Widget");
-dojo.require("dijit.Editor");
 dojo.require("dijit.form.Button");
-dojo.declare("dijit._editor._Plugin",null,{constructor:function(_1,_2){
-this.params=_1||{};
-dojo.mixin(this,this.params);
-this._connects=[];
-},editor:null,iconClassPrefix:"dijitEditorIcon",button:null,command:"",useDefaultCommand:true,buttonClass:dijit.form.Button,getLabel:function(_3){
-return this.editor.commands[_3];
-},_initButton:function(){
-if(this.command.length){
-var _4=this.getLabel(this.command);
-var _5=this.iconClassPrefix+" "+this.iconClassPrefix+this.command.charAt(0).toUpperCase()+this.command.substr(1);
-if(!this.button){
-var _6=dojo.mixin({label:_4,showLabel:false,iconClass:_5,dropDown:this.dropDown,tabIndex:"-1"},this.params||{});
-this.button=new this.buttonClass(_6);
-}
-}
-},destroy:function(){
-dojo.forEach(this._connects,dojo.disconnect);
-if(this.dropDown){
-this.dropDown.destroyRecursive();
-}
-},connect:function(o,f,tf){
-this._connects.push(dojo.connect(o,f,this,tf));
-},updateState:function(){
-var e=this.editor,c=this.command,_7,_8;
-if(!e||!e.isLoaded||!c.length){
-return;
-}
-if(this.button){
-try{
-_8=e.queryCommandEnabled(c);
-if(this.enabled!==_8){
-this.enabled=_8;
-this.button.attr("disabled",!_8);
-}
-if(typeof this.button.checked=="boolean"){
-_7=e.queryCommandState(c);
-if(this.checked!==_7){
-this.checked=_7;
-this.button.attr("checked",e.queryCommandState(c));
-}
-}
-}
-catch(e){
-}
-}
-},setEditor:function(_9){
-this.editor=_9;
-this._initButton();
-if(this.command.length&&!this.editor.queryCommandAvailable(this.command)){
-if(this.button){
-this.button.domNode.style.display="none";
-}
-}
-if(this.button&&this.useDefaultCommand){
-this.connect(this.button,"onClick",dojo.hitch(this.editor,"execCommand",this.command,this.commandArg));
-}
-this.connect(this.editor,"onNormalizedDisplayChanged","updateState");
-},setToolbar:function(_a){
-if(this.button){
-_a.addChild(this.button);
-}
-}});
-}
+
+dojo.declare("dijit._editor._Plugin", null, {
+	// summary
+	//		Base class for a "plugin" to the editor, which is usually
+	//		a single button on the Toolbar and some associated code
+
+	constructor: function(/*Object?*/args, /*DomNode?*/node){
+		this.params = args || {};
+		dojo.mixin(this, this.params);
+		this._connects=[];
+	},
+
+	// editor: [const] dijit.Editor
+	//		Points to the parent editor
+	editor: null,
+
+	// iconClassPrefix: [const] String
+	//		The CSS class name for the button node is formed from `iconClassPrefix` and `command`
+	iconClassPrefix: "dijitEditorIcon",
+
+	// button: dijit._Widget?
+	//		Pointer to `dijit.form.Button` or other widget (ex: `dijit.form.FilteringSelect`)
+	//		that is added to the toolbar to control this plugin.
+	//		If not specified, will be created on initialization according to `buttonClass`
+	button: null,
+
+	// command: String
+	//		String like "insertUnorderedList", "outdent", "justifyCenter", etc. that represents an editor command.
+	//		Passed to editor.execCommand() if `useDefaultCommand` is true.
+	command: "",
+
+	// useDefaultCommand: Boolean
+	//		If true, this plugin executes by calling Editor.execCommand() with the argument specified in `command`.
+	useDefaultCommand: true,
+
+	// buttonClass: Widget Class
+	//		Class of widget (ex: dijit.form.Button or dijit.form.FilteringSelect)
+	//		that is added to the toolbar to control this plugin.
+	//		This is used to instantiate the button, unless `button` itself is specified directly.
+	buttonClass: dijit.form.Button,
+
+	getLabel: function(/*String*/key){
+		// summary:
+		//		Returns the label to use for the button
+		// tags:
+		//		private
+		return this.editor.commands[key];		// String
+	},
+
+	_initButton: function(){
+		// summary:
+		//		Initialize the button or other widget that will control this plugin.
+		//		This code only works for plugins controlling built-in commands in the editor.
+		// tags:
+		//		protected extension
+		if(this.command.length){
+			var label = this.getLabel(this.command),
+				editor = this.editor,
+				className = this.iconClassPrefix+" "+this.iconClassPrefix + this.command.charAt(0).toUpperCase() + this.command.substr(1);
+			if(!this.button){
+				var props = dojo.mixin({
+					label: label,
+					dir: editor.dir,
+					lang: editor.lang,
+					showLabel: false,
+					iconClass: className,
+					dropDown: this.dropDown,
+					tabIndex: "-1"
+				}, this.params || {});
+				this.button = new this.buttonClass(props);
+			}
+		}
+	},
+
+	destroy: function(){
+		// summary:
+		//		Destroy this plugin
+
+		dojo.forEach(this._connects, dojo.disconnect);
+		if(this.dropDown){
+			this.dropDown.destroyRecursive();
+		}
+	},
+
+	connect: function(o, f, tf){
+		// summary:
+		//		Make a dojo.connect() that is automatically disconnected when this plugin is destroyed.
+		//		Similar to `dijit._Widget.connect`.
+		// tags:
+		//		protected
+		this._connects.push(dojo.connect(o, f, this, tf));
+	},
+
+	updateState: function(){
+		// summary:
+		//		Change state of the plugin to respond to events in the editor.
+		// description:
+		//		This is called on meaningful events in the editor, such as change of selection
+		//		or caret position (but not simple typing of alphanumeric keys).   It gives the
+		//		plugin a chance to update the CSS of its button.
+		//
+		//		For example, the "bold" plugin will highlight/unhighlight the bold button depending on whether the
+		//		characters next to the caret are bold or not.
+		//
+		//		Only makes sense when `useDefaultCommand` is true, as it calls Editor.queryCommandEnabled(`command`).
+		var e = this.editor,
+			c = this.command,
+			checked, enabled;
+		if(!e || !e.isLoaded || !c.length){ return; }
+		if(this.button){
+			try{
+				enabled = e.queryCommandEnabled(c);
+				if(this.enabled !== enabled){
+					this.enabled = enabled;
+					this.button.set('disabled', !enabled);
+				}
+				if(typeof this.button.checked == 'boolean'){
+					checked = e.queryCommandState(c);
+					if(this.checked !== checked){
+						this.checked = checked;
+						this.button.set('checked', e.queryCommandState(c));
+					}
+				}
+			}catch(e){
+				console.log(e); // FIXME: we shouldn't have debug statements in our code.  Log as an error?
+			}
+		}
+	},
+
+	setEditor: function(/*dijit.Editor*/ editor){
+		// summary:
+		//		Tell the plugin which Editor it is associated with.
+
+		// TODO: refactor code to just pass editor to constructor.
+
+		// FIXME: detach from previous editor!!
+		this.editor = editor;
+
+		// FIXME: prevent creating this if we don't need to (i.e., editor can't handle our command)
+		this._initButton();
+
+		// Processing for buttons that execute by calling editor.execCommand()
+		if(this.button && this.useDefaultCommand){
+			if(this.editor.queryCommandAvailable(this.command)){
+				this.connect(this.button, "onClick",
+					dojo.hitch(this.editor, "execCommand", this.command, this.commandArg)
+				);
+			}else{
+				// hide button because editor doesn't support command (due to browser limitations)
+				this.button.domNode.style.display = "none";			
+			}
+		}
+
+		this.connect(this.editor, "onNormalizedDisplayChanged", "updateState");
+	},
+
+	setToolbar: function(/*dijit.Toolbar*/ toolbar){
+		// summary:
+		//		Tell the plugin to add it's controller widget (often a button)
+		//		to the toolbar.  Does nothing if there is no controller widget.
+
+		// TODO: refactor code to just pass toolbar to constructor.
+
+		if(this.button){
+			toolbar.addChild(this.button);
+		}
+		// console.debug("adding", this.button, "to:", toolbar);
+	}
+});
diff --git a/dijit/_editor/html.js b/dijit/_editor/html.js
old mode 100644
new mode 100755
index b2d4e91..d683413
--- a/dijit/_editor/html.js
+++ b/dijit/_editor/html.js
@@ -1,147 +1,180 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._editor.html"]){
-dojo._hasResource["dijit._editor.html"]=true;
 dojo.provide("dijit._editor.html");
-dijit._editor.escapeXml=function(_1,_2){
-_1=_1.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,""");
-if(!_2){
-_1=_1.replace(/'/gm,"'");
-}
-return _1;
+
+dijit._editor.escapeXml=function(/*String*/str, /*Boolean?*/noSingleQuotes){
+	// summary:
+	//		Adds escape sequences for special characters in XML: &<>"'
+	//		Optionally skips escapes for single quotes
+	str = str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """);
+	if(!noSingleQuotes){
+		str = str.replace(/'/gm, "'");
+	}
+	return str; // string
 };
-dijit._editor.getNodeHtml=function(_3){
-var _4;
-switch(_3.nodeType){
-case 1:
-var _5=_3.nodeName.toLowerCase();
-if(_5.charAt(0)=="/"){
-return "";
-}
-_4="<"+_5;
-var _6=[];
-var _7;
-if(dojo.isIE&&_3.outerHTML){
-var s=_3.outerHTML;
-s=s.substr(0,s.indexOf(">")).replace(/(['"])[^"']*\1/g,"");
-var _8=/(\b\w+)\s?=/g;
-var m,_9;
-while((m=_8.exec(s))){
-_9=m[1];
-if(_9.substr(0,3)!="_dj"){
-if(_9=="src"||_9=="href"){
-if(_3.getAttribute("_djrealurl")){
-_6.push([_9,_3.getAttribute("_djrealurl")]);
-continue;
-}
-}
-var _a,_b;
-switch(_9){
-case "style":
-_a=_3.style.cssText.toLowerCase();
-break;
-case "class":
-_a=_3.className;
-break;
-case "width":
-if(_5==="img"){
-_b=/width=(\S+)/i.exec(s);
-if(_b){
-_a=_b[1];
-}
-break;
-}
-case "height":
-if(_5==="img"){
-_b=/height=(\S+)/i.exec(s);
-if(_b){
-_a=_b[1];
-}
-break;
-}
-default:
-_a=_3.getAttribute(_9);
-}
-if(_a!=null){
-_6.push([_9,_a.toString()]);
-}
-}
-}
-}else{
-var i=0;
-while((_7=_3.attributes[i++])){
-var n=_7.name;
-if(n.substr(0,3)!="_dj"){
-var v=_7.value;
-if(n=="src"||n=="href"){
-if(_3.getAttribute("_djrealurl")){
-v=_3.getAttribute("_djrealurl");
-}
-}
-_6.push([n,v]);
-}
-}
-}
-_6.sort(function(a,b){
-return a[0]<b[0]?-1:(a[0]==b[0]?0:1);
-});
-var j=0;
-while((_7=_6[j++])){
-_4+=" "+_7[0]+"=\""+(dojo.isString(_7[1])?dijit._editor.escapeXml(_7[1],true):_7[1])+"\"";
-}
-if(_5==="script"){
-_4+=">"+_3.innerHTML+"</"+_5+">";
-}else{
-if(_3.childNodes.length){
-_4+=">"+dijit._editor.getChildrenHtml(_3)+"</"+_5+">";
-}else{
-switch(_5){
-case "br":
-case "hr":
-case "img":
-case "input":
-case "base":
-case "meta":
-case "area":
-case "basefont":
-_4+=" />";
-break;
-default:
-_4+="></"+_5+">";
-}
-}
-}
-break;
-case 4:
-case 3:
-_4=dijit._editor.escapeXml(_3.nodeValue,true);
-break;
-case 8:
-_4="<!--"+dijit._editor.escapeXml(_3.nodeValue,true)+"-->";
-break;
-default:
-_4="<!-- Element not recognized - Type: "+_3.nodeType+" Name: "+_3.nodeName+"-->";
-}
-return _4;
+
+dijit._editor.getNodeHtml=function(/* DomNode */node){
+	var output;
+	switch(node.nodeType){
+		case 1: //element node
+			var lName = node.nodeName.toLowerCase();
+			if(!lName || lName.charAt(0) == "/"){
+				// IE does some strange things with malformed HTML input, like
+				// treating a close tag </span> without an open tag <span>, as
+				// a new tag with tagName of /span.  Corrupts output HTML, remove
+				// them.  Other browsers don't prefix tags that way, so will
+				// never show up.
+				return "";
+			}
+			output = '<' + lName;
+
+			//store the list of attributes and sort it to have the
+			//attributes appear in the dictionary order
+			var attrarray = [];
+			var attr;
+			if(dojo.isIE && node.outerHTML){
+				var s = node.outerHTML;
+				s = s.substr(0, s.indexOf('>'))
+					.replace(/(['"])[^"']*\1/g, ''); //to make the following regexp safe
+				var reg = /(\b\w+)\s?=/g;
+				var m, key;
+				while((m = reg.exec(s))){
+					key = m[1];
+					if(key.substr(0,3) != '_dj'){
+						if(key == 'src' || key == 'href'){
+							if(node.getAttribute('_djrealurl')){
+								attrarray.push([key,node.getAttribute('_djrealurl')]);
+								continue;
+							}
+						}
+						var val, match;
+						switch(key){
+							case 'style':
+								val = node.style.cssText.toLowerCase();
+								break;
+							case 'class':
+								val = node.className;
+								break;
+							case 'width':
+								if(lName === "img"){
+									// This somehow gets lost on IE for IMG tags and the like
+									// and we have to find it in outerHTML, known IE oddity.
+									match=/width=(\S+)/i.exec(s);
+									if(match){
+										val = match[1];
+									}
+									break;
+								}
+							case 'height':
+								if(lName === "img"){
+									// This somehow gets lost on IE for IMG tags and the like
+									// and we have to find it in outerHTML, known IE oddity.
+									match=/height=(\S+)/i.exec(s);
+									if(match){
+										val = match[1];
+									}
+									break;
+								}
+							default:
+								val = node.getAttribute(key);
+						}
+						if(val != null){
+							attrarray.push([key, val.toString()]);
+						}
+					}
+				}
+			}else{
+				var i = 0;
+				while((attr = node.attributes[i++])){
+					//ignore all attributes starting with _dj which are
+					//internal temporary attributes used by the editor
+					var n = attr.name;
+					if(n.substr(0,3) != '_dj' /*&&
+						(attr.specified == undefined || attr.specified)*/){
+						var v = attr.value;
+						if(n == 'src' || n == 'href'){
+							if(node.getAttribute('_djrealurl')){
+								v = node.getAttribute('_djrealurl');
+							}
+						}
+						attrarray.push([n,v]);
+					}
+				}
+			}
+			attrarray.sort(function(a,b){
+				return a[0] < b[0] ? -1 : (a[0] == b[0] ? 0 : 1);
+			});
+			var j = 0;
+			while((attr = attrarray[j++])){
+				output += ' ' + attr[0] + '="' +
+					(dojo.isString(attr[1]) ? dijit._editor.escapeXml(attr[1], true) : attr[1]) + '"';
+			}
+			if(lName === "script"){
+				// Browsers handle script tags differently in how you get content,
+				// but innerHTML always seems to work, so insert its content that way
+				// Yes, it's bad to allow script tags in the editor code, but some people
+				// seem to want to do it, so we need to at least return them right.
+				// other plugins/filters can strip them.
+				output += '>' + node.innerHTML +'</' + lName + '>';
+			}else{
+				if(node.childNodes.length){
+					output += '>' + dijit._editor.getChildrenHtml(node)+'</' + lName +'>';
+				}else{
+					switch(lName){
+						case 'br':
+						case 'hr':
+						case 'img':
+						case 'input':
+						case 'base':
+						case 'meta':
+						case 'area':
+						case 'basefont':
+							// These should all be singly closed
+							output += ' />';
+							break;
+						default:
+							// Assume XML style separate closure for everything else.
+							output += '></' + lName + '>';
+					}
+				}
+			}
+			break;
+		case 4: // cdata
+		case 3: // text
+			// FIXME:
+			output = dijit._editor.escapeXml(node.nodeValue, true);
+			break;
+		case 8: //comment
+			// FIXME:
+			output = '<!--' + dijit._editor.escapeXml(node.nodeValue, true) + '-->';
+			break;
+		default:
+			output = "<!-- Element not recognized - Type: " + node.nodeType + " Name: " + node.nodeName + "-->";
+	}
+	return output;
 };
-dijit._editor.getChildrenHtml=function(_c){
-var _d="";
-if(!_c){
-return _d;
-}
-var _e=_c["childNodes"]||_c;
-var _f=!dojo.isIE||_e!==_c;
-var _10,i=0;
-while((_10=_e[i++])){
-if(!_f||_10.parentNode==_c){
-_d+=dijit._editor.getNodeHtml(_10);
-}
-}
-return _d;
+
+dijit._editor.getChildrenHtml = function(/* DomNode */dom){
+	// summary:
+	//		Returns the html content of a DomNode and children
+	var out = "";
+	if(!dom){ return out; }
+	var nodes = dom["childNodes"] || dom;
+
+	//IE issue.
+	//If we have an actual node we can check parent relationships on for IE,
+	//We should check, as IE sometimes builds invalid DOMS.  If no parent, we can't check
+	//And should just process it and hope for the best.
+	var checkParent = !dojo.isIE || nodes !== dom;
+
+	var node, i = 0;
+	while((node = nodes[i++])){
+		//IE is broken.  DOMs are supposed to be a tree.  But in the case of malformed HTML, IE generates a graph
+		//meaning one node ends up with multiple references (multiple parents).  This is totally wrong and invalid, but
+		//such is what it is.  We have to keep track and check for this because otherise the source output HTML will have dups.
+		//No other browser generates a graph.  Leave it to IE to break a fundamental DOM rule.  So, we check the parent if we can
+		//If we can't, nothing more we can do other than walk it.
+		if(!checkParent || node.parentNode == dom){
+			out += dijit._editor.getNodeHtml(node);
+		}
+	}
+	return out; // String
 };
-}
diff --git a/dijit/_editor/nls/FontChoice.js b/dijit/_editor/nls/FontChoice.js
index 71da48d..1855400 100644
--- a/dijit/_editor/nls/FontChoice.js
+++ b/dijit/_editor/nls/FontChoice.js
@@ -1 +1,26 @@
-({"1":"xx-small","2":"x-small","formatBlock":"Format","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Paragraph","pre":"Pre-formatted","sans-serif":"sans-serif","fontName":"Font","h1":"Heading","h2":"Subheading","h3":"Sub-subheading","monospace":"monospace","fontSize":"Size","cursive":"cursive"})
\ No newline at end of file
+({
+	fontSize: "Size",
+	fontName: "Font",
+	formatBlock: "Format",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursive",
+	fantasy: "fantasy",
+
+	noFormat: "None",
+	p: "Paragraph",
+	h1: "Heading",
+	h2: "Subheading",
+	h3: "Sub-subheading",
+	pre: "Pre-formatted",
+
+	1: "xx-small",
+	2: "x-small",
+	3: "small",
+	4: "medium",
+	5: "large",
+	6: "x-large",
+	7: "xx-large"
+})
diff --git a/dijit/_editor/nls/LinkDialog.js b/dijit/_editor/nls/LinkDialog.js
index 0dd81f1..ad13eb6 100644
--- a/dijit/_editor/nls/LinkDialog.js
+++ b/dijit/_editor/nls/LinkDialog.js
@@ -1 +1,12 @@
-({"text":"Description:","insertImageTitle":"Image Properties","set":"Set","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","createLinkTitle":"Link Properties","parentWindow":"Parent Window","currentWindow":"Current Window","url":"URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "Link Properties",
+	insertImageTitle: "Image Properties",
+	url: "URL:",
+	text: "Description:",
+	target: "Target:",
+	set: "Set",
+	currentWindow: "Current Window",
+	parentWindow: "Parent Window",
+	topWindow: "Topmost Window",
+	newWindow: "New Window"
+})
diff --git a/dijit/_editor/nls/ar/FontChoice.js b/dijit/_editor/nls/ar/FontChoice.js
index 78c3ed9..621c142 100644
--- a/dijit/_editor/nls/ar/FontChoice.js
+++ b/dijit/_editor/nls/ar/FontChoice.js
@@ -1 +1,25 @@
-({"1":"صغير جدا جدا","2":"صغير جدا","formatBlock":"النسق","3":"صغير","4":"متوسط","5":"كبير","6":"كبير جدا","7":"كبير جدا جدا","fantasy":"خيالي","serif":"serif","p":"فقرة","pre":"منسق بصفة مسبقة","sans-serif":"sans-serif","fontName":"طاقم طباعة","h1":"عنوان","h2":"عنوان فرعي","h3":"فرعي-عنوان فرعي","monospace":"أحادي المسافة","fontSize":"الحجم","cursive":"كتابة بحروف متصلة"})
\ No newline at end of file
+({
+	fontSize: "الحجم",
+	fontName: "طاقم طباعة",
+	formatBlock: "النسق",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "أحادي المسافة",
+	cursive: "كتابة بحروف متصلة",
+	fantasy: "خيالي",
+
+	p: "فقرة",
+	h1: "عنوان",
+	h2: "عنوان فرعي",
+	h3: "فرعي-عنوان فرعي",
+	pre: "منسق بصفة مسبقة",
+
+	1: "صغير جدا جدا",
+	2: "صغير جدا",
+	3: "صغير",
+	4: "متوسط",
+	5: "كبير",
+	6: "كبير جدا",
+	7: "كبير جدا جدا"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/ar/LinkDialog.js b/dijit/_editor/nls/ar/LinkDialog.js
index 8545531..9483616 100644
--- a/dijit/_editor/nls/ar/LinkDialog.js
+++ b/dijit/_editor/nls/ar/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"تحديد","text":"الوصف:","insertImageTitle":"خصائص الصورة","url":"عنوان URL:","createLinkTitle":"خصائص الوصلة","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "خصائص الوصلة",
+	insertImageTitle: "خصائص الصورة",
+	url: "عنوان URL:",
+	text: "الوصف:",
+	target: "الهدف: ",
+	set: "تحديد",
+	currentWindow: "النافذة الحالية",
+	parentWindow: "النافذة الرئيسية",
+	topWindow: "النافذة العلوية",
+	newWindow: "نافذة جديدة"
+})
+
diff --git a/dijit/_editor/nls/ar/commands.js b/dijit/_editor/nls/ar/commands.js
index 23e83e7..3bb35e7 100644
--- a/dijit/_editor/nls/ar/commands.js
+++ b/dijit/_editor/nls/ar/commands.js
@@ -1 +1,49 @@
-({"removeFormat":"ازالة النسق","copy":"نسخ","paste":"لصق","selectAll":"اختيار كل","insertOrderedList":"‏كشف مرقم‏","insertTable":"ادراج/تحرير جدول","underline":"تسطير","foreColor":"لون الواجهة الأمامية","htmlToggle":"مصدر HTML","formatBlock":"نمط الفقرة","insertHorizontalRule":"مسطرة أفقية","delete":"حذف","insertUnorderedList":"كشف نقطي","tableProp":"خصائص الجدول","insertImage":"ادراج صورة","superscript":"رمز علوي","subscript":"رمز سفلي","createLink":"تكوين وصلة","undo":"تراجع","italic": [...]
\ No newline at end of file
+({
+	'bold': 'عري~ض',
+	'copy': 'نسخ',
+	'cut': 'قص',
+	'delete': 'حذف',
+	'indent': '‏ازاحة للداخل‏',
+	'insertHorizontalRule': 'مسطرة أفقية',
+	'insertOrderedList': '‏كشف مرقم‏',
+	'insertUnorderedList': 'كشف نقطي',
+	'italic': '~مائل',
+	'justifyCenter': 'محاذاة في الوسط',
+	'justifyFull': 'ضبط',
+	'justifyLeft': 'محاذاة الى اليسار',
+	'justifyRight': 'محاذاة الى اليمين',
+	'outdent': 'ازاحة للخارج',
+	'paste': 'لصق',
+	'redo': '‏اعادة‏',
+	'removeFormat': 'ازالة النسق',
+	'selectAll': 'اختيار كل',
+	'strikethrough': 'تشطيب',
+	'subscript': 'رمز سفلي',
+	'superscript': 'رمز علوي',
+	'underline': '~تسطير',
+	'undo': 'تراجع',
+	'unlink': 'ازالة وصلة',
+	'createLink': 'تكوين وصلة',
+	'toggleDir': 'تبديل الاتجاه',
+	'insertImage': 'ادراج صورة',
+	'insertTable': 'ادراج/تحرير جدول',
+	'toggleTableBorder': 'تبديل حدود الجدول',
+	'deleteTable': 'حذف جدول',
+	'tableProp': 'خصائص الجدول',
+	'htmlToggle': 'مصدر HTML',
+	'foreColor': 'لون الواجهة الأمامية',
+	'hiliteColor': '‏لون الخلفية‏',
+	'plainFormatBlock': 'نمط الفقرة',
+	'formatBlock': 'نمط الفقرة',
+	'fontSize': 'حجم طاقم الطباعة',
+	'fontName': 'اسم طاقم الطباعة',
+	'tabIndent': 'ازاحة للداخل باستخدام Tab',
+	"fullScreen": "تبديل الشاشة الكاملة",
+	"viewSource": "\u202bمشاهدة مصدر HTML\u202c",
+	"print": "‏طباعة‏",
+	"newPage": "صفحة جديدة",
+	/* Error messages */
+	'systemShortcut': 'التصرف "${0}" يكون متاحا فقط في برنامج الاستعراض الخاص بك باستخدام المسار المختصر للوحة المفاتيح. استخدم ${1}.',
+	'ctrlKey':'ctrl+${0}'
+})
+
diff --git a/dijit/_editor/nls/ca/FontChoice.js b/dijit/_editor/nls/ca/FontChoice.js
index 8d3dabe..b430f31 100644
--- a/dijit/_editor/nls/ca/FontChoice.js
+++ b/dijit/_editor/nls/ca/FontChoice.js
@@ -1 +1,26 @@
-({"1":"xx-petit","2":"x-petit","formatBlock":"Format","3":"petit","4":"mitjà","5":"gran","6":"x-gran","7":"xx-gran","fantasy":"Fantasia","serif":"serif","p":"Paràgraf","pre":"Format previ","sans-serif":"sans-serif","fontName":"Tipus de lletra","h1":"Títol","h2":"Subtítol","h3":"Subsubtítol","monospace":"monoespai","fontSize":"Mida","cursive":"Cursiva"})
\ No newline at end of file
+({
+	fontSize: "Mida",
+	fontName: "Tipus de lletra",
+	formatBlock: "Format",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monoespai",
+	cursive: "Cursiva",
+	fantasy: "Fantasia",
+
+	p: "Paràgraf",
+	h1: "Títol",
+	h2: "Subtítol",
+	h3: "Subsubtítol",
+	pre: "Format previ",
+
+	1: "xx-petit",
+	2: "x-petit",
+	3: "petit",
+	4: "mitjà",
+	5: "gran",
+	6: "x-gran",
+	7: "xx-gran"
+})
+
diff --git a/dijit/_editor/nls/ca/LinkDialog.js b/dijit/_editor/nls/ca/LinkDialog.js
index 7b3aa02..900c52e 100644
--- a/dijit/_editor/nls/ca/LinkDialog.js
+++ b/dijit/_editor/nls/ca/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"Defineix","text":"Descripció:","insertImageTitle":"Propietats de la imatge","url":"URL:","createLinkTitle":"Propietats de l'enllaç","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "Propietats de l\'enllaç",
+	insertImageTitle: "Propietats de la imatge",
+	url: "URL:",
+	text: "Descipció:",
+	target: "Destinació:",
+	set: "Defineix",
+	currentWindow: "Finestra actual",
+	parentWindow: "Finestra pare",
+	topWindow: "Finestra superior",
+	newWindow: "Finestra nova"
+})
+
diff --git a/dijit/_editor/nls/ca/commands.js b/dijit/_editor/nls/ca/commands.js
index aec09d8..8a94eae 100644
--- a/dijit/_editor/nls/ca/commands.js
+++ b/dijit/_editor/nls/ca/commands.js
@@ -1 +1,49 @@
-({"removeFormat":"Elimina el format","copy":"Copia","paste":"Enganxa","selectAll":"Selecciona-ho tot","insertOrderedList":"Llista numerada","insertTable":"Insereix/edita la taula","underline":"Subratllat","foreColor":"Color de primer pla","htmlToggle":"Font HTML","formatBlock":"Estil de paràgraf","insertHorizontalRule":"Regle horitzontal","delete":"Suprimeix","insertUnorderedList":"Llista de vinyetes","tableProp":"Propietat de taula","insertImage":"Insereix imatge","superscript":"Superín [...]
\ No newline at end of file
+({
+	'bold': 'Negreta',
+	'copy': 'Copia',
+	'cut': 'Retalla',
+	'delete': 'Suprimeix',
+	'indent': 'Sagnat',
+	'insertHorizontalRule': 'Regle horitzontal',
+	'insertOrderedList': 'Llista numerada',
+	'insertUnorderedList': 'Llista de vinyetes',
+	'italic': 'Cursiva',
+	'justifyCenter': 'Centra',
+	'justifyFull': 'Justifica',
+	'justifyLeft': 'Alinea a la esquerra',
+	'justifyRight': 'Alinea a la dreta',
+	'outdent': 'Sagna a l\'esquerra',
+	'paste': 'Enganxa',
+	'redo': 'Refés',
+	'removeFormat': 'Elimina el format',
+	'selectAll': 'Selecciona-ho tot',
+	'strikethrough': 'Ratllat',
+	'subscript': 'Subíndex',
+	'superscript': 'Superíndex',
+	'underline': 'Subratllat',
+	'undo': 'Desfés',
+	'unlink': 'Elimina l\'enllaç',
+	'createLink': 'Crea un enllaç',
+	'toggleDir': 'Inverteix la direcció',
+	'insertImage': 'Insereix imatge',
+	'insertTable': 'Insereix/edita la taula',
+	'toggleTableBorder': 'Inverteix els contorns de taula',
+	'deleteTable': 'Suprimeix la taula',
+	'tableProp': 'Propietat de taula',
+	'htmlToggle': 'Font HTML',
+	'foreColor': 'Color de primer pla',
+	'hiliteColor': 'Color de fons',
+	'plainFormatBlock': 'Estil de paràgraf',
+	'formatBlock': 'Estil de paràgraf',
+	'fontSize': 'Cos de la lletra',
+	'fontName': 'Nom del tipus de lletra',
+	'tabIndent': 'Sagnat',
+	"fullScreen": "Commuta pantalla completa",
+	"viewSource": "Visualitza font HTML",
+	"print": "Imprimeix",
+	"newPage": "Pàgina nova",
+	/* Error messages */
+	'systemShortcut': 'L\'acció "${0}" és l\'única disponible al navegador utilitzant una drecera del teclat. Utilitzeu ${1}.',
+	'ctrlKey':'control+${0}'
+})
+
diff --git a/dijit/_editor/nls/commands.js b/dijit/_editor/nls/commands.js
index 582b782..25d7c29 100644
--- a/dijit/_editor/nls/commands.js
+++ b/dijit/_editor/nls/commands.js
@@ -1 +1,49 @@
-({"removeFormat":"Remove Format","copy":"Copy","paste":"Paste","selectAll":"Select All","insertOrderedList":"Numbered List","insertTable":"Insert/Edit Table","print":"Print","underline":"Underline","foreColor":"Foreground Color","htmlToggle":"HTML Source","formatBlock":"Paragraph Style","newPage":"New Page","insertHorizontalRule":"Horizontal Rule","delete":"Delete","appleKey":"⌘${0}","insertUnorderedList":"Bullet List","tableProp":"Table Property","insertImage":"Insert Image","superscrip [...]
\ No newline at end of file
+({
+	'bold': 'Bold',
+	'copy': 'Copy',
+	'cut': 'Cut',
+	'delete': 'Delete',
+	'indent': 'Indent',
+	'insertHorizontalRule': 'Horizontal Rule',
+	'insertOrderedList': 'Numbered List',
+	'insertUnorderedList': 'Bullet List',
+	'italic': 'Italic',
+	'justifyCenter': 'Align Center',
+	'justifyFull': 'Justify',
+	'justifyLeft': 'Align Left',
+	'justifyRight': 'Align Right',
+	'outdent': 'Outdent',
+	'paste': 'Paste',
+	'redo': 'Redo',
+	'removeFormat': 'Remove Format',
+	'selectAll': 'Select All',
+	'strikethrough': 'Strikethrough',
+	'subscript': 'Subscript',
+	'superscript': 'Superscript',
+	'underline': 'Underline',
+	'undo': 'Undo',
+	'unlink': 'Remove Link',
+	'createLink': 'Create Link',
+	'toggleDir': 'Toggle Direction',
+	'insertImage': 'Insert Image',
+	'insertTable': 'Insert/Edit Table',
+	'toggleTableBorder': 'Toggle Table Border',
+	'deleteTable': 'Delete Table',
+	'tableProp': 'Table Property',
+	'htmlToggle': 'HTML Source',
+	'foreColor': 'Foreground Color',
+	'hiliteColor': 'Background Color',
+	'plainFormatBlock': 'Paragraph Style',
+	'formatBlock': 'Paragraph Style',
+	'fontSize': 'Font Size',
+	'fontName': 'Font Name',
+	'tabIndent': 'Tab Indent',
+	"fullScreen": "Toggle Full Screen",
+	"viewSource": "View HTML Source",
+	"print": "Print",
+	"newPage": "New Page",
+	/* Error messages */
+	'systemShortcut': 'The "${0}" action is only available in your browser using a keyboard shortcut. Use ${1}.',
+	'ctrlKey':'ctrl+${0}',
+	'appleKey':'\u2318${0}' // "command" or open-apple key on Macintosh
+})
diff --git a/dijit/_editor/nls/cs/FontChoice.js b/dijit/_editor/nls/cs/FontChoice.js
index 4f82895..fa836c8 100644
--- a/dijit/_editor/nls/cs/FontChoice.js
+++ b/dijit/_editor/nls/cs/FontChoice.js
@@ -1 +1,25 @@
-({"1":"extra malé","2":"velmi malé","formatBlock":"Formát","3":"malé","4":"střední","5":"velké","6":"velmi velké","7":"extra velké","fantasy":"fantasy","serif":"serif","p":"Odstavec","pre":"Předformátované","sans-serif":"sans-serif","fontName":"Písmo","h1":"Nadpis","h2":"Podnadpis","h3":"Podnadpis 2","monospace":"monospace","fontSize":"Velikost","cursive":"cursive"})
\ No newline at end of file
+({
+	fontSize: "Velikost",
+	fontName: "Písmo",
+	formatBlock: "Formát",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursive",
+	fantasy: "fantasy",
+
+	p: "Odstavec",
+	h1: "Nadpis",
+	h2: "Podnadpis",
+	h3: "Podnadpis 2",
+	pre: "Předformátované",
+
+	1: "extra malé",
+	2: "velmi malé",
+	3: "malé",
+	4: "střední",
+	5: "velké",
+	6: "velmi velké",
+	7: "extra velké"
+})
diff --git a/dijit/_editor/nls/cs/LinkDialog.js b/dijit/_editor/nls/cs/LinkDialog.js
index 41dad34..e24ac48 100644
--- a/dijit/_editor/nls/cs/LinkDialog.js
+++ b/dijit/_editor/nls/cs/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"Popis:","insertImageTitle":"Vlastnosti obrázku","set":"Nastavit","newWindow":"Nové okno","topWindow":"Okno nejvyšší úrovně","target":"Cíl:","createLinkTitle":"Vlastnosti odkazu","parentWindow":"Nadřízené okno","currentWindow":"Aktuální okno","url":"Adresa URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "Vlastnosti odkazu",
+	insertImageTitle: "Vlastnosti obrázku",
+	url: "Adresa URL:",
+	text: "Popis:",
+	target: "Cíl:",
+	set: "Nastavit",
+	currentWindow: "Aktuální okno",
+	parentWindow: "Nadřízené okno",
+	topWindow: "Okno nejvyšší úrovně",
+	newWindow: "Nové okno"
+})
+
diff --git a/dijit/_editor/nls/cs/commands.js b/dijit/_editor/nls/cs/commands.js
index ce51558..7e52895 100644
--- a/dijit/_editor/nls/cs/commands.js
+++ b/dijit/_editor/nls/cs/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Odebrat formát","copy":"Kopírovat","paste":"Vložit","selectAll":"Vybrat vše","insertOrderedList":"Číslovaný seznam","insertTable":"Vložit/upravit tabulku","print":"Tisk","underline":"Podtržení","foreColor":"Barva popředí","htmlToggle":"Zdroj HTML","formatBlock":"Styl odstavce","newPage":"Nová stránka","insertHorizontalRule":"Vodorovná čára","delete":"Odstranit","insertUnorderedList":"Seznam s odrážkami","tableProp":"Vlastnost tabulky","insertImage":"Vložit obrázek","sup [...]
\ No newline at end of file
+({
+	'bold': 'Tučné',
+	'copy': 'Kopírovat',
+	'cut': 'Vyjmout',
+	'delete': 'Odstranit',
+	'indent': 'Odsadit',
+	'insertHorizontalRule': 'Vodorovná čára',
+	'insertOrderedList': 'Číslovaný seznam',
+	'insertUnorderedList': 'Seznam s odrážkami',
+	'italic': 'Kurzíva',
+	'justifyCenter': 'Zarovnat na střed',
+	'justifyFull': 'Do bloku',
+	'justifyLeft': 'Zarovnat vlevo',
+	'justifyRight': 'Zarovnat vpravo',
+	'outdent': 'Předsadit',
+	'paste': 'Vložit',
+	'redo': 'Opakovat',
+	'removeFormat': 'Odebrat formát',
+	'selectAll': 'Vybrat vše',
+	'strikethrough': 'Přeškrtnutí',
+	'subscript': 'Dolní index',
+	'superscript': 'Horní index',
+	'underline': 'Podtržení',
+	'undo': 'Zpět',
+	'unlink': 'Odebrat odkaz',
+	'createLink': 'Vytvořit odkaz',
+	'toggleDir': 'Přepnout směr',
+	'insertImage': 'Vložit obrázek',
+	'insertTable': 'Vložit/upravit tabulku',
+	'toggleTableBorder': 'Přepnout ohraničení tabulky',
+	'deleteTable': 'Odstranit tabulku',
+	'tableProp': 'Vlastnost tabulky',
+	'htmlToggle': 'Zdroj HTML',
+	'foreColor': 'Barva popředí',
+	'hiliteColor': 'Barva pozadí',
+	'plainFormatBlock': 'Styl odstavce',
+	'formatBlock': 'Styl odstavce',
+	'fontSize': 'Velikost písma',
+	'fontName': 'Název písma',
+	'tabIndent': 'Odsazení tabulátoru',
+	"fullScreen": "Přepnout režim celé obrazovky",
+	"viewSource": "Zobrazit zdroj ve formátu HTML",
+	"print": "Tisk",
+	"newPage": "Nová stránka",
+	/* Error messages */
+	'systemShortcut': 'Akce "${0}" je v prohlížeči dostupná pouze prostřednictvím klávesové zkratky. Použijte klávesovou zkratku ${1}.'
+})
+
diff --git a/dijit/_editor/nls/da/FontChoice.js b/dijit/_editor/nls/da/FontChoice.js
index 2ecab08..1994287 100644
--- a/dijit/_editor/nls/da/FontChoice.js
+++ b/dijit/_editor/nls/da/FontChoice.js
@@ -1 +1,25 @@
-({"1":"xx-small","2":"x-small","formatBlock":"Format","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Afsnit","pre":"Forudformateret","sans-serif":"sans-serif","fontName":"Skrifttype","h1":"Overskrift","h2":"Underoverskrift","h3":"Underunderoverskrift","monospace":"monospace","fontSize":"Størrelse","cursive":"kursiv"})
\ No newline at end of file
+({
+	fontSize: "Størrelse",
+	fontName: "Skrifttype",
+	formatBlock: "Format",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "kursiv",
+	fantasy: "fantasy",
+
+	p: "Afsnit",
+	h1: "Overskrift",
+	h2: "Underoverskrift",
+	h3: "Underunderoverskrift",
+	pre: "Forudformateret",
+
+	1: "xx-small",
+	2: "x-small",
+	3: "small",
+	4: "medium",
+	5: "large",
+	6: "x-large",
+	7: "xx-large"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/da/LinkDialog.js b/dijit/_editor/nls/da/LinkDialog.js
index c7590f0..60ccf05 100644
--- a/dijit/_editor/nls/da/LinkDialog.js
+++ b/dijit/_editor/nls/da/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"Definér","text":"Beskrivelse:","insertImageTitle":"Billedegenskaber","url":"URL:","createLinkTitle":"Linkegenskaber","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "Linkegenskaber",
+	insertImageTitle: "Billedegenskaber",
+	url: "URL:",
+	text: "Beskrivelse:",
+	target: "Mål:",
+	set: "Definér",
+	currentWindow: "Aktuelt vindue",
+	parentWindow: "Overordnet vindue",
+	topWindow: "Øverste vindue",
+	newWindow: "Nyt vindue"
+})
+
diff --git a/dijit/_editor/nls/da/commands.js b/dijit/_editor/nls/da/commands.js
index b7aed14..58ef957 100644
--- a/dijit/_editor/nls/da/commands.js
+++ b/dijit/_editor/nls/da/commands.js
@@ -1 +1,49 @@
-({"removeFormat":"Fjern format","copy":"Kopiér","paste":"Sæt ind","selectAll":"Markér alle","insertOrderedList":"Nummereret liste","insertTable":"Indsæt/redigér tabel","underline":"Understreget","foreColor":"Forgrundsfarve","htmlToggle":"HTML-kilde","formatBlock":"Afsnitstypografi","insertHorizontalRule":"Vandret linje","delete":"Slet","insertUnorderedList":"Punktliste","tableProp":"Tabelegenskab","insertImage":"Indsæt billede","superscript":"Hævet skrift","subscript":"Sænket skrift","cr [...]
\ No newline at end of file
+({
+	'bold': 'Fed',
+	'copy': 'Kopiér',
+	'cut': 'Klip',
+	'delete': 'Slet',
+	'indent': 'Indrykning',
+	'insertHorizontalRule': 'Vandret linje',
+	'insertOrderedList': 'Nummereret liste',
+	'insertUnorderedList': 'Punktliste',
+	'italic': 'Kursiv',
+	'justifyCenter': 'Centreret',
+	'justifyFull': 'Lige margener',
+	'justifyLeft': 'Venstrejusteret',
+	'justifyRight': 'Højrejusteret',
+	'outdent': 'Udrykning',
+	'paste': 'Sæt ind',
+	'redo': 'Annullér Fortryd',
+	'removeFormat': 'Fjern format',
+	'selectAll': 'Markér alle',
+	'strikethrough': 'Gennemstreget',
+	'subscript': 'Sænket skrift',
+	'superscript': 'Hævet skrift',
+	'underline': 'Understreget',
+	'undo': 'Fortryd',
+	'unlink': 'Fjern link',
+	'createLink': 'Opret link',
+	'toggleDir': 'Skift retning',
+	'insertImage': 'Indsæt billede',
+	'insertTable': 'Indsæt/redigér tabel',
+	'toggleTableBorder': 'Skift tabelramme',
+	'deleteTable': 'Slet tabel',
+	'tableProp': 'Tabelegenskab',
+	'htmlToggle': 'HTML-kilde',
+	'foreColor': 'Forgrundsfarve',
+	'hiliteColor': 'Baggrundsfarve',
+	'plainFormatBlock': 'Afsnitstypografi',
+	'formatBlock': 'Afsnitstypografi',
+	'fontSize': 'Skriftstørrelse',
+	'fontName': 'Skriftnavn',
+	'tabIndent': 'Indrykning med tabulator',
+	"fullScreen": "Aktivér/deaktivér fuldskærm",
+	"viewSource": "Vis HTML-kilde",
+	"print": "Udskriv",
+	"newPage": "Ny side",
+	/* Error messages */
+	'systemShortcut': 'Funktionen "${0}" kan kun bruges i din browser med en tastaturgenvej. Brug ${1}.',
+	'ctrlKey':'Ctrl+${0}'
+})
+
diff --git a/dijit/_editor/nls/de/FontChoice.js b/dijit/_editor/nls/de/FontChoice.js
index f16b312..0f45e8f 100644
--- a/dijit/_editor/nls/de/FontChoice.js
+++ b/dijit/_editor/nls/de/FontChoice.js
@@ -1 +1,25 @@
-({"1":"XXS","2":"XS","formatBlock":"Format","3":"S","4":"M","5":"L","6":"XL","7":"XXL","fantasy":"Fantasie","serif":"Serife","p":"Absatz","pre":"Vorformatiert","sans-serif":"Serifenlos","fontName":"Schriftart","h1":"Überschrift","h2":"Unterüberschrift","h3":"Unterunterüberschrift","monospace":"Monospaceschrift","fontSize":"Größe","cursive":"Kursiv"})
\ No newline at end of file
+({
+	fontSize: "Größe",
+	fontName: "Schriftart",
+	formatBlock: "Format",
+
+	serif: "Serife",
+	"sans-serif": "Serifenlos",
+	monospace: "Monospaceschrift",
+	cursive: "Kursiv",
+	fantasy: "Fantasie",
+
+	p: "Absatz",
+	h1: "Überschrift",
+	h2: "Unterüberschrift",
+	h3: "Unterunterüberschrift",
+	pre: "Vorformatiert",
+
+	1: "XXS",
+	2: "XS",
+	3: "S",
+	4: "M",
+	5: "L",
+	6: "XL",
+	7: "XXL"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/de/LinkDialog.js b/dijit/_editor/nls/de/LinkDialog.js
index b1eab6c..266add8 100644
--- a/dijit/_editor/nls/de/LinkDialog.js
+++ b/dijit/_editor/nls/de/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"Beschreibung:","insertImageTitle":"Grafikeigenschaften","set":"Festlegen","newWindow":"Neues Fenster","topWindow":"Aktives Fenster","target":"Ziel:","createLinkTitle":"Linkeigenschaften","parentWindow":"Übergeordnetes Fenster","currentWindow":"Aktuelles Fenster","url":"URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "Linkeigenschaften",
+	insertImageTitle: "Grafikeigenschaften",
+	url: "URL:",
+	text: "Beschreibung:",
+	target: "Ziel:",
+	set: "Festlegen",
+	currentWindow: "Aktuelles Fenster",
+	parentWindow: "Übergeordnetes Fenster",
+	topWindow: "Aktives Fenster",
+	newWindow: "Neues Fenster"
+})
+
diff --git a/dijit/_editor/nls/de/commands.js b/dijit/_editor/nls/de/commands.js
old mode 100644
new mode 100755
index 8fa589c..3191e18
--- a/dijit/_editor/nls/de/commands.js
+++ b/dijit/_editor/nls/de/commands.js
@@ -1 +1,49 @@
-({"removeFormat":"Formatierung entfernen","copy":"Kopieren","paste":"Einfügen","selectAll":"Alles auswählen","insertOrderedList":"Nummerierung","insertTable":"Tabelle einfügen/bearbeiten","print":"Drucken","underline":"Unterstrichen","foreColor":"Vordergrundfarbe","htmlToggle":"HTML-Quelltext","formatBlock":"Absatzstil","newPage":"Neue Seite","insertHorizontalRule":"Horizontaler Strich","delete":"Löschen","insertUnorderedList":"Aufzählungszeichen","tableProp":"Tabelleneigenschaft","inser [...]
\ No newline at end of file
+({
+	'bold': 'Fett',
+	'copy': 'Kopieren',
+	'cut': 'Ausschneiden',
+	'delete': 'Löschen',
+	'indent': 'Einrücken',
+	'insertHorizontalRule': 'Horizontaler Strich',
+	'insertOrderedList': 'Nummerierung',
+	'insertUnorderedList': 'Aufzählungszeichen',
+	'italic': 'Kursiv',
+	'justifyCenter': 'Zentriert',
+	'justifyFull': 'Blocksatz',
+	'justifyLeft': 'Linksbündig',
+	'justifyRight': 'Rechtsbündig',
+	'outdent': 'Ausrücken',
+	'paste': 'Einfügen',
+	'redo': 'Wiederherstellen',
+	'removeFormat': 'Formatierung entfernen',
+	'selectAll': 'Alles auswählen',
+	'strikethrough': 'Durchgestrichen',
+	'subscript': 'Tiefgestellt',
+	'superscript': 'Hochgestellt',
+	'underline': 'Unterstrichen',
+	'undo': 'Rückgängig',
+	'unlink': 'Link entfernen',
+	'createLink': 'Link erstellen',
+	'toggleDir': 'Wechselrichtung',
+	'insertImage': 'Grafik einfügen',
+	'insertTable': 'Tabelle einfügen/bearbeiten',
+	'toggleTableBorder': 'Tabellenumrandung ein-/ausschalten',
+	'deleteTable': 'Tabelle löschen',
+	'tableProp': 'Tabelleneigenschaft',
+	'htmlToggle': 'HTML-Quelltext',
+	'foreColor': 'Vordergrundfarbe',
+	'hiliteColor': 'Hintergrundfarbe',
+	'plainFormatBlock': 'Absatzstil',
+	'formatBlock': 'Absatzstil',
+	'fontSize': 'Schriftgröße',
+	'fontName': 'Schriftartname',
+	'tabIndent': 'Tabulatoreinrückung',
+	"fullScreen": "Gesamtanzeige",
+	"viewSource": "HTML-Quelle",
+	"print": "Drucken",
+	"newPage": "Neue Seite",
+	/* Error messages */
+	'systemShortcut': 'Die Aktion "${0}" ist nur über einen Direktaufruf in Ihrem Browser verfügbar. Verwenden Sie ${1}.',
+	'ctrlKey':'Strg+${0}'
+})
+
diff --git a/dijit/_editor/nls/el/FontChoice.js b/dijit/_editor/nls/el/FontChoice.js
index 2d51628..e9fee55 100644
--- a/dijit/_editor/nls/el/FontChoice.js
+++ b/dijit/_editor/nls/el/FontChoice.js
@@ -1 +1,25 @@
-({"1":"xx-μικρά","2":"x-μικρά","formatBlock":"Μορφή","3":"μικρά","4":"μεσαία","5":"μεγάλα","6":"x-μεγάλα","7":"xx-μεγάλα","fantasy":"φαντασίας","serif":"με πατούρες (serif)","p":"Παράγραφος","pre":"Προ-μορφοποιημένο","sans-serif":"χωρίς πατούρες (sans-serif)","fontName":"Γραμματοσειρά","h1":"Επικεφαλίδα","h2":"Δευτερεύουσα επικεφαλίδα","h3":"Δευτερεύουσα επικεφαλίδα τρίτου επιπέδου","monospace":"σταθερού πλάτους","fontSize":"Μέγεθος","cursive":"πλάγιοι"})
\ No newline at end of file
+({
+	fontSize: "Μέγεθος",
+	fontName: "Γραμματοσειρά",
+	formatBlock: "Μορφή",
+
+	serif: "με πατούρες (serif)",
+	"sans-serif": "χωρίς πατούρες (sans-serif)",
+	monospace: "σταθερού πλάτους",
+	cursive: "πλάγιοι",
+	fantasy: "φαντασίας",
+
+	p: "Παράγραφος",
+	h1: "Επικεφαλίδα",
+	h2: "Δευτερεύουσα επικεφαλίδα",
+	h3: "Δευτερεύουσα επικεφαλίδα τρίτου επιπέδου",
+	pre: "Προ-μορφοποιημένο",
+
+	1: "xx-μικρά",
+	2: "x-μικρά",
+	3: "μικρά",
+	4: "μεσαία",
+	5: "μεγάλα",
+	6: "x-μεγάλα",
+	7: "xx-μεγάλα"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/el/LinkDialog.js b/dijit/_editor/nls/el/LinkDialog.js
index 9eef633..9cbc6f0 100644
--- a/dijit/_editor/nls/el/LinkDialog.js
+++ b/dijit/_editor/nls/el/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"Ορισμός","text":"Περιγραφή:","insertImageTitle":"Ιδιότητες εικόνας","url":"Διεύθυνση URL:","createLinkTitle":"Ιδιότητες διασύνδεσης","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "Ιδιότητες σύνδεσης",
+	insertImageTitle: "Ιδιότητες εικόνας",
+	url: "Διεύθυνση URL:",
+	text: "Περιγραφή:",
+	target: "Προορισμός:",
+	set: "Ορισμός",
+	currentWindow: "Τρέχον παράθυρο",
+	parentWindow: "Γονικό παράθυρο",
+	topWindow: "Παράθυρο σε πρώτο πλάνο",
+	newWindow: "Νέο παράθυρο"
+})
+
diff --git a/dijit/_editor/nls/el/commands.js b/dijit/_editor/nls/el/commands.js
index eaf90eb..a23feac 100644
--- a/dijit/_editor/nls/el/commands.js
+++ b/dijit/_editor/nls/el/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Αφαίρεση μορφοποίησης","copy":"Αντιγραφή","paste":"Επικόλληση","selectAll":"Επιλογή όλων","insertOrderedList":"Αριθμημένη λίστα","insertTable":"Εισαγωγή/Τροποποίηση πίνακα","underline":"Υπογράμμιση","foreColor":"Χρώμα προσκηνίου","htmlToggle":"Πρωτογενής κώδικας HTML","formatBlock":"Στυλ παραγράφου","insertHorizontalRule":"Οριζόντια γραμμή","delete":"Διαγραφή","insertUnorderedList":"Λίστα με κουκίδες","tableProp":"Ιδιότητα πίνακα","insertImage":"Εισαγωγή εικόνας","super [...]
\ No newline at end of file
+({
+	'bold': 'Έντονα',
+	'copy': 'Αντιγραφή',
+	'cut': 'Αποκοπή',
+	'delete': 'Διαγραφή',
+	'indent': 'Εσοχή',
+	'insertHorizontalRule': 'Οριζόντια γραμμή',
+	'insertOrderedList': 'Αριθμημένη λίστα',
+	'insertUnorderedList': 'Λίστα με κουκίδες',
+	'italic': 'Πλάγια',
+	'justifyCenter': 'Στοίχιση στο κέντρο',
+	'justifyFull': 'Πλήρης στοίχιση',
+	'justifyLeft': 'Στοίχιση αριστερά',
+	'justifyRight': 'Στοίχιση δεξιά',
+	'outdent': 'Μείωση περιθωρίου',
+	'paste': 'Επικόλληση',
+	'redo': 'Ακύρωση αναίρεσης',
+	'removeFormat': 'Αφαίρεση μορφοποίησης',
+	'selectAll': 'Επιλογή όλων',
+	'strikethrough': 'Διαγράμμιση',
+	'subscript': 'Δείκτης',
+	'superscript': 'Εκθέτης',
+	'underline': 'Υπογράμμιση',
+	'undo': 'Αναίρεση',
+	'unlink': 'Αφαίρεση σύνδεσης',
+	'createLink': 'Δημιουργία σύνδεσης',
+	'toggleDir': 'Εναλλαγή κατεύθυνσης',
+	'insertImage': 'Εισαγωγή εικόνας',
+	'insertTable': 'Εισαγωγή/Τροποποίηση πίνακα',
+	'toggleTableBorder': 'Εναλλαγή εμφάνισης περιγράμματος πίνακα',
+	'deleteTable': 'Διαγραφή πίνακα',
+	'tableProp': 'Ιδιότητα πίνακα',
+	'htmlToggle': 'Πρωτογενής κώδικας HTML',
+	'foreColor': 'Χρώμα προσκηνίου',
+	'hiliteColor': 'Χρώμα φόντου',
+	'plainFormatBlock': 'Στυλ παραγράφου',
+	'formatBlock': 'Στυλ παραγράφου',
+	'fontSize': 'Μέγεθος γραμματοσειράς',
+	'fontName': 'Όνομα γραμματοσειράς',
+	'tabIndent': 'Εσοχή με το πλήκτρο Tab',
+	"fullScreen": "Εναλλαγή κατάστασης πλήρους οθόνης",
+	"viewSource": "Προβολή προέλευσης HTML",
+	"print": "Εκτύπωση",
+	"newPage": "Νέα σελίδα",
+	/* Error messages */
+	'systemShortcut': 'Σε αυτό το πρόγραμμα πλοήγησης, η ενέργεια "${0}" είναι διαθέσιμη μόνο με τη χρήση μιας συντόμευσης πληκτρολογίου. Χρησιμοποιήστε τη συντόμευση ${1}.'
+})
+
diff --git a/dijit/_editor/nls/es/FontChoice.js b/dijit/_editor/nls/es/FontChoice.js
index bacacf0..8592dc9 100644
--- a/dijit/_editor/nls/es/FontChoice.js
+++ b/dijit/_editor/nls/es/FontChoice.js
@@ -1 +1,25 @@
-({"1":"xx-pequeño","2":"x-pequeño","formatBlock":"Formato","3":"pequeño","4":"medio","5":"grande","6":"x-grande","7":"xx-grande","fantasy":"fantasía","serif":"serif","p":"Párrafo","pre":"Preformateado","sans-serif":"sans-serif","fontName":"Font","h1":"Cabecera","h2":"Subcabecera","h3":"Sub-subcabecera","monospace":"espacio sencillo","fontSize":"Tamaño","cursive":"cursiva"})
\ No newline at end of file
+({
+	fontSize: "Tamaño",
+	fontName: "Font",
+	formatBlock: "Formato",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "espacio sencillo",
+	cursive: "cursiva",
+	fantasy: "fantasía",
+
+	p: "Párrafo",
+	h1: "Cabecera",
+	h2: "Subcabecera",
+	h3: "Sub-subcabecera",
+	pre: "Preformateado",
+
+	1: "xx-pequeño",
+	2: "x-pequeño",
+	3: "pequeño",
+	4: "medio",
+	5: "grande",
+	6: "x-grande",
+	7: "xx-grande"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/es/LinkDialog.js b/dijit/_editor/nls/es/LinkDialog.js
index 15802d7..27d996c 100644
--- a/dijit/_editor/nls/es/LinkDialog.js
+++ b/dijit/_editor/nls/es/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"Descripción: ","insertImageTitle":"Propiedades de la imagen","set":"Establecer","newWindow":"Nueva ventana","topWindow":"Ventana superior","target":"Destino: ","createLinkTitle":"Propiedades del enlace","parentWindow":"Ventana padre","currentWindow":"Ventana actual","url":"URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "Propiedades del enlace",
+	insertImageTitle: "Propiedades de la imagen",
+	url: "URL:",
+	text: "Descripción: ",
+	target: "Destino: ",
+	set: "Establecer",
+	currentWindow: "Ventana actual",
+	parentWindow: "Ventana padre",
+	topWindow: "Ventana superior",
+	newWindow: "Nueva ventana"
+})
+
diff --git a/dijit/_editor/nls/es/commands.js b/dijit/_editor/nls/es/commands.js
index 0d189dc..9e540f9 100644
--- a/dijit/_editor/nls/es/commands.js
+++ b/dijit/_editor/nls/es/commands.js
@@ -1 +1,49 @@
-({"removeFormat":"Eliminar formato","copy":"Copiar","paste":"Pegar","selectAll":"Seleccionar todo","insertOrderedList":"Lista numerada","insertTable":"Insertar/Editar tabla","print":"Imprimir","underline":"Subrayado","foreColor":"Color de primer plano","htmlToggle":"Fuente HTML","formatBlock":"Estilo de párrafo","newPage":"Nueva página","insertHorizontalRule":"Regla horizontal","delete":"Suprimir","insertUnorderedList":"Lista con viñetas","tableProp":"Propiedad de tabla","insertImage":"I [...]
\ No newline at end of file
+({
+	'bold': 'Negrita',
+	'copy': 'Copiar',
+	'cut': 'Cortar',
+	'delete': 'Suprimir',
+	'indent': 'Sangría',
+	'insertHorizontalRule': 'Regla horizontal',
+	'insertOrderedList': 'Lista numerada',
+	'insertUnorderedList': 'Lista con viñetas',
+	'italic': 'Cursiva',
+	'justifyCenter': 'Alinear centro',
+	'justifyFull': 'Justificar',
+	'justifyLeft': 'Alinear izquierda',
+	'justifyRight': 'Alinear derecha',
+	'outdent': 'Anular sangría',
+	'paste': 'Pegar',
+	'redo': 'Rehacer',
+	'removeFormat': 'Eliminar formato',
+	'selectAll': 'Seleccionar todo',
+	'strikethrough': 'Tachado',
+	'subscript': 'Subíndice',
+	'superscript': 'Superíndice',
+	'underline': 'Subrayado',
+	'undo': 'Deshacer',
+	'unlink': 'Eliminar enlace',
+	'createLink': 'Crear enlace',
+	'toggleDir': 'Conmutar dirección',
+	'insertImage': 'Insertar imagen',
+	'insertTable': 'Insertar/Editar tabla',
+	'toggleTableBorder': 'Conmutar borde de tabla',
+	'deleteTable': 'Suprimir tabla',
+	'tableProp': 'Propiedad de tabla',
+	'htmlToggle': 'Fuente HTML',
+	'foreColor': 'Color de primer plano',
+	'hiliteColor': 'Color de segundo plano',
+	'plainFormatBlock': 'Estilo de párrafo',
+	'formatBlock': 'Estilo de párrafo',
+	'fontSize': 'Tamaño de font',
+	'fontName': 'Nombre de font',
+	'tabIndent': 'Sangría de tabulador',
+	"fullScreen": "Conmutar pantalla completa",
+	"viewSource": "Ver fuente HTML",
+	"print": "Imprimir",
+	"newPage": "Nueva página",
+	/* Error messages */
+	'systemShortcut': 'La acción "${0}" sólo está disponible en su navegador mediante un atajo de teclado. Utilice ${1}.',
+	'ctrlKey':'control+${0}'
+})
+
diff --git a/dijit/_editor/nls/fi/FontChoice.js b/dijit/_editor/nls/fi/FontChoice.js
index 37d3962..ad48fc0 100644
--- a/dijit/_editor/nls/fi/FontChoice.js
+++ b/dijit/_editor/nls/fi/FontChoice.js
@@ -1 +1,25 @@
-({"1":"xx-small","2":"x-small","formatBlock":"Muoto","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Kappale","pre":"Esimuotoiltu","sans-serif":"sans-serif","fontName":"Fontti","h1":"Otsikko","h2":"Alatason otsikko","h3":"Alimman tason otsikko","monospace":"monospace","fontSize":"Koko","cursive":"cursive"})
\ No newline at end of file
+({
+	fontSize: "Koko",
+	fontName: "Fontti",
+	formatBlock: "Muoto",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursive",
+	fantasy: "fantasy",
+
+	p: "Kappale",
+	h1: "Otsikko",
+	h2: "Alatason otsikko",
+	h3: "Alimman tason otsikko",
+	pre: "Esimuotoiltu",
+
+	1: "xx-small",
+	2: "x-small",
+	3: "small",
+	4: "medium",
+	5: "large",
+	6: "x-large",
+	7: "xx-large"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/fi/LinkDialog.js b/dijit/_editor/nls/fi/LinkDialog.js
index 0f8c69f..75bf456 100644
--- a/dijit/_editor/nls/fi/LinkDialog.js
+++ b/dijit/_editor/nls/fi/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"Aseta","text":"Kuvaus:","insertImageTitle":"Kuvan ominaisuudet","url":"URL-osoite:","createLinkTitle":"Linkin ominaisuudet","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "Linkin ominaisuudet",
+	insertImageTitle: "Kuvan ominaisuudet",
+	url: "URL-osoite:",
+	text: "Kuvaus:",
+	target: "Kohde:",
+	set: "Aseta",
+	currentWindow: "Nykyinen ikkuna",
+	parentWindow: "Pääikkuna",
+	topWindow: "Päällimmäinen ikkuna",
+	newWindow: "Uusi ikkuna"
+})
+
diff --git a/dijit/_editor/nls/fi/commands.js b/dijit/_editor/nls/fi/commands.js
index 60f87bb..6db52cb 100644
--- a/dijit/_editor/nls/fi/commands.js
+++ b/dijit/_editor/nls/fi/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Poista muotoilu","copy":"Kopioi","paste":"Liitä","selectAll":"Valitse kaikki","insertOrderedList":"Numeroitu luettelo","insertTable":"Lisää taulukko/muokkaa taulukkoa","underline":"Alleviivaus","foreColor":"Edustaväri","htmlToggle":"HTML-lähde","formatBlock":"Kappaletyyli","insertHorizontalRule":"Vaakasuuntainen viiva","delete":"Poista","insertUnorderedList":"Numeroimaton luettelo","tableProp":"Taulukon ominaisuudet","insertImage":"Lisää kuva","superscript":"Korotettu", [...]
\ No newline at end of file
+({
+	'bold': 'Lihavointi',
+	'copy': 'Kopioi',
+	'cut': 'Leikkaa',
+	'delete': 'Poista',
+	'indent': 'Sisennä',
+	'insertHorizontalRule': 'Vaakasuuntainen viiva',
+	'insertOrderedList': 'Numeroitu luettelo',
+	'insertUnorderedList': 'Numeroimaton luettelo',
+	'italic': 'Kursivointi',
+	'justifyCenter': 'Tasaus keskelle',
+	'justifyFull': 'Tasaus',
+	'justifyLeft': 'Tasaus vasemmalle',
+	'justifyRight': 'Tasaus oikealle',
+	'outdent': 'Ulonna',
+	'paste': 'Liitä',
+	'redo': 'Tee uudelleen',
+	'removeFormat': 'Poista muotoilu',
+	'selectAll': 'Valitse kaikki',
+	'strikethrough': 'Yliviivaus',
+	'subscript': 'Alaindeksi',
+	'superscript': 'Yläindeksi',
+	'underline': 'Alleviivaus',
+	'undo': 'Kumoa',
+	'unlink': 'Poista linkki',
+	'createLink': 'Luo linkki',
+	'toggleDir': 'Vaihda suuntaa',
+	'insertImage': 'Lisää kuva',
+	'insertTable': 'Lisää taulukko/muokkaa taulukkoa',
+	'toggleTableBorder': 'Ota taulukon kehys käyttöön/poista kehys käytöstä',
+	'deleteTable': 'Poista taulukko',
+	'tableProp': 'Taulukon ominaisuudet',
+	'htmlToggle': 'HTML-lähde',
+	'foreColor': 'Edustaväri',
+	'hiliteColor': 'Taustaväri',
+	'plainFormatBlock': 'Kappaletyyli',
+	'formatBlock': 'Kappaletyyli',
+	'fontSize': 'Fontin koko',
+	'fontName': 'Fontin nimi',
+	'tabIndent': 'Sarkainsisennys',
+	"fullScreen": "Vaihda koko näyttö",
+	"viewSource": "Näytä HTML-lähde",
+	"print": "Tulosta",
+	"newPage": "Uusi sivu",
+	/* Error messages */
+	'systemShortcut': 'Toiminto "${0}" on käytettävissä selaimessa vain näppäimistön pikatoiminnolla. Käytä seuraavaa: ${1}.'
+})
+
diff --git a/dijit/_editor/nls/fr/FontChoice.js b/dijit/_editor/nls/fr/FontChoice.js
index 9063de8..c96716d 100644
--- a/dijit/_editor/nls/fr/FontChoice.js
+++ b/dijit/_editor/nls/fr/FontChoice.js
@@ -1 +1,25 @@
-({"1":"xxs","2":"xs","formatBlock":"Mise en forme","3":"s","4":"m","5":"l","6":"xl","7":"xxl","fantasy":"fantaisie","serif":"serif","p":"Paragraphe","pre":"Pré-mise en forme","sans-serif":"sans serif","fontName":"Police","h1":"En-tête","h2":"Sous-en-tête","h3":"Sous-sous-en-tête","monospace":"espacement fixe","fontSize":"Taille","cursive":"cursive"})
\ No newline at end of file
+({
+	fontSize: "Taille",
+	fontName: "Police",
+	formatBlock: "Mise en forme",
+
+	serif: "serif",
+	"sans-serif": "sans serif",
+	monospace: "espacement fixe",
+	cursive: "cursive",
+	fantasy: "fantaisie",
+
+	p: "Paragraphe",
+	h1: "En-tête",
+	h2: "Sous-en-tête",
+	h3: "Sous-sous-en-tête",
+	pre: "Pré-mise en forme",
+
+	1: "xxs",
+	2: "xs",
+	3: "s",
+	4: "m",
+	5: "l",
+	6: "xl",
+	7: "xxl"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/fr/LinkDialog.js b/dijit/_editor/nls/fr/LinkDialog.js
index 7094601..5949bc9 100644
--- a/dijit/_editor/nls/fr/LinkDialog.js
+++ b/dijit/_editor/nls/fr/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"Description :","insertImageTitle":"Propriétés des images","set":"Définir","newWindow":"Nouvelle fenêtre","topWindow":"Première fenêtre","target":"Cible :","createLinkTitle":"Propriétés des liens","parentWindow":"Fenêtre parent","currentWindow":"Fenêtre en cours","url":"URL :"})
\ No newline at end of file
+({
+	createLinkTitle: "Propriétés des liens",
+	insertImageTitle: "Propriétés des images",
+	url: "URL :",
+	text: "Description :",
+	target: "Cible :",
+	set: "Définir",
+	currentWindow: "Fenêtre en cours",
+	parentWindow: "Fenêtre parent",
+	topWindow: "Première fenêtre",
+	newWindow: "Nouvelle fenêtre"
+})
+
diff --git a/dijit/_editor/nls/fr/commands.js b/dijit/_editor/nls/fr/commands.js
index df8cb3b..98f2697 100644
--- a/dijit/_editor/nls/fr/commands.js
+++ b/dijit/_editor/nls/fr/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Supprimer la mise en forme","copy":"Copier","paste":"Coller","selectAll":"Sélectionner tout","insertOrderedList":"Liste numérotée","insertTable":"Insérer/Modifier un tableau","print":"Imprimer","underline":"Souligner","foreColor":"Couleur avant-plan","htmlToggle":"Source HTML","formatBlock":"Style de paragraphe","newPage":"Nouvelle page","insertHorizontalRule":"Règle horizontale","delete":"Supprimer","insertUnorderedList":"Liste à puces","tableProp":"Propriété du tablea [...]
\ No newline at end of file
+({
+	'bold': 'Gras',
+	'copy': 'Copier',
+	'cut': 'Couper',
+	'delete': 'Supprimer',
+	'indent': 'Retrait',
+	'insertHorizontalRule': 'Règle horizontale',
+	'insertOrderedList': 'Liste numérotée',
+	'insertUnorderedList': 'Liste à puces',
+	'italic': 'Italique',
+	'justifyCenter': 'Aligner au centre',
+	'justifyFull': 'Justifier',
+	'justifyLeft': 'Aligner à gauche',
+	'justifyRight': 'Aligner à droite',
+	'outdent': 'Retrait négatif',
+	'paste': 'Coller',
+	'redo': 'Rétablir',
+	'removeFormat': 'Supprimer la mise en forme',
+	'selectAll': 'Sélectionner tout',
+	'strikethrough': 'Barrer',
+	'subscript': 'Indice',
+	'superscript': 'Exposant',
+	'underline': 'Souligner',
+	'undo': 'Annuler',
+	'unlink': 'Supprimer le lien',
+	'createLink': 'Créer un lien',
+	'toggleDir': 'Changer de sens',
+	'insertImage': 'Insérer une image',
+	'insertTable': 'Insérer/Modifier un tableau',
+	'toggleTableBorder': 'Afficher/Masquer la bordure du tableau',
+	'deleteTable': 'Supprimer le tableau',
+	'tableProp': 'Propriété du tableau',
+	'htmlToggle': 'Source HTML',
+	'foreColor': 'Couleur avant-plan',
+	'hiliteColor': 'Couleur arrière-plan',
+	'plainFormatBlock': 'Style de paragraphe',
+	'formatBlock': 'Style de paragraphe',
+	'fontSize': 'Taille de police',
+	'fontName': 'Nom de police',
+	'tabIndent': 'Retrait de tabulation',
+	"fullScreen": "Basculer vers le mode plein écran",
+	"viewSource": "Afficher la source HTML",
+	"print": "Imprimer",
+	"newPage": "Nouvelle page",
+	/* Error messages */
+	'systemShortcut': 'Action "${0}" uniquement disponible dans votre navigateur via un raccourci clavier. Utilisez ${1}.'
+})
+
diff --git a/dijit/_editor/nls/he/FontChoice.js b/dijit/_editor/nls/he/FontChoice.js
index 9f1b213..bcffb70 100644
--- a/dijit/_editor/nls/he/FontChoice.js
+++ b/dijit/_editor/nls/he/FontChoice.js
@@ -1 +1,25 @@
-({"1":"קטן ביות","2":"קטן מאוד","formatBlock":"עיצוב","3":"קטן","4":"בינוני","5":"גדול","6":"גדול מאוד","7":"גדול ביותר","fantasy":"fantasy","serif":"serif","p":"פיסקה","pre":"מעוצב מראש","sans-serif":"sans-serif","fontName":"גופן","h1":"כותרת","h2":"תת-כותרת","h3":"תת-תת-כותרת","monospace":"monospace","fontSize":"גודל","cursive":"cursive"})
\ No newline at end of file
+({
+	fontSize: "גודל",
+	fontName: "גופן",
+	formatBlock: "עיצוב",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursive",
+	fantasy: "fantasy",
+
+	p: "פיסקה",
+	h1: "כותרת",
+	h2: "תת-כותרת",
+	h3: "תת-תת-כותרת",
+	pre: "מעוצב מראש",
+
+	1: "קטן ביות",
+	2: "קטן מאוד",
+	3: "קטן",
+	4: "בינוני",
+	5: "גדול",
+	6: "גדול מאוד",
+	7: "גדול ביותר"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/he/LinkDialog.js b/dijit/_editor/nls/he/LinkDialog.js
index bd36d66..5566e91 100644
--- a/dijit/_editor/nls/he/LinkDialog.js
+++ b/dijit/_editor/nls/he/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"הגדרה","text":"תיאור:","insertImageTitle":"תכונות תמונה","url":"URL:‏","createLinkTitle":"תכונות קישור","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "תכונות קישור",
+	insertImageTitle: "תכונות תמונה",
+	url: "URL:‏",
+	text: "תיאור:",
+	target: "יעד:",
+	set: "הגדרה",
+	currentWindow: "חלון נוכחי ",
+	parentWindow: "חלון אב",
+	topWindow: "חלון עליון ",
+	newWindow: "חלון חדש"
+})
+
diff --git a/dijit/_editor/nls/he/commands.js b/dijit/_editor/nls/he/commands.js
index f599a63..b872a60 100644
--- a/dijit/_editor/nls/he/commands.js
+++ b/dijit/_editor/nls/he/commands.js
@@ -1 +1,50 @@
-({"removeFormat":"סילוק עיצוב","copy":"העתקה","paste":"הדבקה","selectAll":"בחירת הכל","insertOrderedList":"רשימה ממוספרת","insertTable":"הוספת/עריכת טבלה","underline":"קו תחתי","foreColor":"צבע חזית","htmlToggle":"מקור HTML","formatBlock":"סגנון פיסקה","insertHorizontalRule":"קו אופקי","delete":"מחיקה","insertUnorderedList":"רשימה עם תבליטים","tableProp":"תכונת טבלה","insertImage":"הוספת תמונה","superscript":"כתב עילי","subscript":"כתב תחתי","createLink":"יצירת קישור","undo":"ביטול פעולה [...]
\ No newline at end of file
+({
+	'bold': 'מודגש',
+	'copy': 'עותק',
+	'cut': 'גזירה',
+	'delete': 'מחיקה',
+	'indent': 'הגדלת כניסה',
+	'insertHorizontalRule': 'קו אופקי',
+	'insertOrderedList': 'רשימה ממוספרת',
+	'insertUnorderedList': 'רשימה עם תבליטים',
+	'italic': 'נטוי',
+	'justifyCenter': 'יישור למרכז',
+	'justifyFull': 'יישור דו-צדדי',
+	'justifyLeft': 'יישור לשמאל',
+	'justifyRight': 'יישור לימין',
+	'outdent': 'הקטנת כניסה',
+	'paste': 'הדבקה',
+	'redo': 'שחזור פעולה',
+	'removeFormat': 'סילוק עיצוב',
+	'selectAll': 'בחירת הכל',
+	'strikethrough': 'קו חוצה',
+	'subscript': 'כתב תחתי',
+	'superscript': 'כתב עילי',
+	'underline': 'קו תחתי',
+	'undo': 'ביטול פעולה',
+	'unlink': 'סילוק הקישור',
+	'createLink': 'יצירת קישור',
+	'toggleDir': 'מיתוג כיוון',
+	'insertImage': 'הוספת תמונה',
+	'insertTable': 'הוספת/עריכת טבלה',
+	'toggleTableBorder': 'מיתוג גבול טבלה',
+	'deleteTable': 'מחיקת טבלה',
+	'tableProp': 'תכונת טבלה',
+	'htmlToggle': 'מקור HTML',
+	'foreColor': 'צבע חזית',
+	'hiliteColor': 'צבע רקע',
+	'plainFormatBlock': 'סגנון פיסקה',
+	'formatBlock': 'סגנון פיסקה',
+	'fontSize': 'גופן יחסי',
+	'fontName': 'שם גופן',
+	'tabIndent': 'כניסת טאב',
+	"fullScreen": "מיתוג מסך מלא ",
+	"viewSource": "הצגת מקור HTML ",
+	"print": "הדפסה",
+	"newPage": "דף חדש ",
+	/* Error messages */
+	'systemShortcut': 'הפעולה "${0}" זמינה בדפדפן רק באמצעות קיצור דרך במקלדת. השתמשו בקיצור ${1}.',
+	'ctrlKey':'ctrl+${0}‎',
+	'appleKey':'\u2318${0}‎' // "command" or open-apple key on Macintosh
+})
+
diff --git a/dijit/_editor/nls/hu/FontChoice.js b/dijit/_editor/nls/hu/FontChoice.js
index 858d77a..e925dec 100644
--- a/dijit/_editor/nls/hu/FontChoice.js
+++ b/dijit/_editor/nls/hu/FontChoice.js
@@ -1 +1,25 @@
-({"1":"xx-kicsi","2":"x-kicsi","formatBlock":"Formátum","3":"kicsi","4":"közepes","5":"nagy","6":"x-nagy","7":"xx-nagy","fantasy":"fantázia","serif":"talpas","p":"Bekezdés","pre":"Előformázott","sans-serif":"talpatlan","fontName":"Betűtípus","h1":"Címsor","h2":"Alcím","h3":"Al-alcím","monospace":"rögzített szélességű","fontSize":"Méret","cursive":"kurzív"})
\ No newline at end of file
+({
+	fontSize: "Méret",
+	fontName: "Betűtípus",
+	formatBlock: "Formátum",
+
+	serif: "talpas",
+	"sans-serif": "talpatlan",
+	monospace: "rögzített szélességű",
+	cursive: "kurzív",
+	fantasy: "fantázia",
+
+	p: "Bekezdés",
+	h1: "Címsor",
+	h2: "Alcím",
+	h3: "Al-alcím",
+	pre: "Előformázott",
+
+	1: "xx-kicsi",
+	2: "x-kicsi",
+	3: "kicsi",
+	4: "közepes",
+	5: "nagy",
+	6: "x-nagy",
+	7: "xx-nagy"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/hu/LinkDialog.js b/dijit/_editor/nls/hu/LinkDialog.js
index 23f765e..dcc5a06 100644
--- a/dijit/_editor/nls/hu/LinkDialog.js
+++ b/dijit/_editor/nls/hu/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"Leírás:","insertImageTitle":"Kép tulajdonságai","set":"Beállítás","newWindow":"Új ablak","topWindow":"Legfelső szintű ablak","target":"Cél:","createLinkTitle":"Hivatkozás tulajdonságai","parentWindow":"Szülő ablak","currentWindow":"Aktuális ablak","url":"URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "Hivatkozás tulajdonságai",
+	insertImageTitle: "Kép tulajdonságai",
+	url: "URL:",
+	text: "Leírás:",
+	target: "Cél:",
+	set: "Beállítás",
+	currentWindow: "Aktuális ablak",
+	parentWindow: "Szülő ablak",
+	topWindow: "Legfelső szintű ablak",
+	newWindow: "Új ablak"
+})
+
diff --git a/dijit/_editor/nls/hu/commands.js b/dijit/_editor/nls/hu/commands.js
index bd016cf..cffd776 100644
--- a/dijit/_editor/nls/hu/commands.js
+++ b/dijit/_editor/nls/hu/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Formázás eltávolítása","copy":"Másolás","paste":"Beillesztés","selectAll":"Összes kijelölése","insertOrderedList":"Számozott lista","insertTable":"Táblázat beszúrása/szerkesztése","print":"Nyomtatás","underline":"Aláhúzott","foreColor":"Előtérszín","htmlToggle":"HTML forrás","formatBlock":"Bekezdés stílusa","newPage":"Új oldal","insertHorizontalRule":"Vízszintes vonalzó","delete":"Törlés","insertUnorderedList":"Felsorolásjeles lista","tableProp":"Táblázat tulajdonságai" [...]
\ No newline at end of file
+({
+	'bold': 'Félkövér',
+	'copy': 'Másolás',
+	'cut': 'Kivágás',
+	'delete': 'Törlés',
+	'indent': 'Behúzás',
+	'insertHorizontalRule': 'Vízszintes vonalzó',
+	'insertOrderedList': 'Számozott lista',
+	'insertUnorderedList': 'Felsorolásjeles lista',
+	'italic': 'Dőlt',
+	'justifyCenter': 'Középre igazítás',
+	'justifyFull': 'Sorkizárás',
+	'justifyLeft': 'Balra igazítás',
+	'justifyRight': 'Jobbra igazítás',
+	'outdent': 'Negatív behúzás',
+	'paste': 'Beillesztés',
+	'redo': 'Újra',
+	'removeFormat': 'Formázás eltávolítása',
+	'selectAll': 'Összes kijelölése',
+	'strikethrough': 'Áthúzott',
+	'subscript': 'Alsó index',
+	'superscript': 'Felső index',
+	'underline': 'Aláhúzott',
+	'undo': 'Visszavonás',
+	'unlink': 'Hivatkozás eltávolítása',
+	'createLink': 'Hivatkozás létrehozása',
+	'toggleDir': 'Irány váltókapcsoló',
+	'insertImage': 'Kép beszúrása',
+	'insertTable': 'Táblázat beszúrása/szerkesztése',
+	'toggleTableBorder': 'Táblázatszegély ki-/bekapcsolása',
+	'deleteTable': 'Táblázat törlése',
+	'tableProp': 'Táblázat tulajdonságai',
+	'htmlToggle': 'HTML forrás',
+	'foreColor': 'Előtérszín',
+	'hiliteColor': 'Háttérszín',
+	'plainFormatBlock': 'Bekezdés stílusa',
+	'formatBlock': 'Bekezdés stílusa',
+	'fontSize': 'Betűméret',
+	'fontName': 'Betűtípus',
+	'tabIndent': 'Tab behúzás',
+	"fullScreen": "Váltás teljes képernyőre",
+	"viewSource": "HTML forrás megjelenítése",
+	"print": "Nyomtatás",
+	"newPage": "Új oldal",
+	/* Error messages */
+	'systemShortcut': 'A(z) "${0}" művelet a böngészőben csak billentyűparancs használatával érhető el. Használja a következőt: ${1}.'
+})
+
diff --git a/dijit/_editor/nls/it/FontChoice.js b/dijit/_editor/nls/it/FontChoice.js
index 1a180df..4f818ce 100644
--- a/dijit/_editor/nls/it/FontChoice.js
+++ b/dijit/_editor/nls/it/FontChoice.js
@@ -1 +1,25 @@
-({"1":"xx-small","2":"x-small","formatBlock":"Formato","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Paragrafo","pre":"Preformattato","sans-serif":"sans-serif","fontName":"Carattere","h1":"Intestazione","h2":"Sottointestazione","h3":"Sottointestazione secondaria","monospace":"spaziatura fissa","fontSize":"Dimensione","cursive":"corsivo"})
\ No newline at end of file
+({
+	fontSize: "Dimensione",
+	fontName: "Carattere",
+	formatBlock: "Formato",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "spaziatura fissa",
+	cursive: "corsivo",
+	fantasy: "fantasy",
+
+	p: "Paragrafo",
+	h1: "Intestazione",
+	h2: "Sottointestazione",
+	h3: "Sottointestazione secondaria",
+	pre: "Preformattato",
+
+	1: "xx-small",
+	2: "x-small",
+	3: "small",
+	4: "medium",
+	5: "large",
+	6: "x-large",
+	7: "xx-large"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/it/LinkDialog.js b/dijit/_editor/nls/it/LinkDialog.js
index ad3adef..9af2670 100644
--- a/dijit/_editor/nls/it/LinkDialog.js
+++ b/dijit/_editor/nls/it/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"Descrizione:","insertImageTitle":"Proprietà immagine","set":"Imposta","newWindow":"Nuova finestra","topWindow":"Finestra superiore","target":"Destinazione:","createLinkTitle":"Proprietà collegamento","parentWindow":"Finestra padre","currentWindow":"Finestra corrente","url":"URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "Proprietà collegamento",
+	insertImageTitle: "Proprietà immagine",
+	url: "URL:",
+	text: "Descrizione:",
+	target: "Destinazione:",
+	set: "Imposta",
+	currentWindow: "Finestra corrente",
+	parentWindow: "Finestra padre",
+	topWindow: "Finestra superiore",
+	newWindow: "Nuova finestra"
+})
+
diff --git a/dijit/_editor/nls/it/commands.js b/dijit/_editor/nls/it/commands.js
index 4abbd7e..711acf2 100644
--- a/dijit/_editor/nls/it/commands.js
+++ b/dijit/_editor/nls/it/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Rimuovi formato","copy":"Copia","paste":"Incolla","selectAll":"Seleziona tutto","insertOrderedList":"Elenco numerato","insertTable":"Inserisci/Modifica tabella","print":"Stampa","underline":"Sottolinea","foreColor":"Colore primo piano","htmlToggle":"Origine HTML","formatBlock":"Stile paragrafo","newPage":"Nuova pagina","insertHorizontalRule":"Righello orizzontale","delete":"Elimina","insertUnorderedList":"Elenco puntato","tableProp":"Proprietà tabella","insertImage":"In [...]
\ No newline at end of file
+({
+	'bold': 'Grassetto',
+	'copy': 'Copia',
+	'cut': 'Taglia',
+	'delete': 'Elimina',
+	'indent': 'Rientro',
+	'insertHorizontalRule': 'Righello orizzontale',
+	'insertOrderedList': 'Elenco numerato',
+	'insertUnorderedList': 'Elenco puntato',
+	'italic': 'Corsivo',
+	'justifyCenter': 'Allinea al centro',
+	'justifyFull': 'Giustifica',
+	'justifyLeft': 'Allinea a sinistra',
+	'justifyRight': 'Allinea a destra',
+	'outdent': 'Annulla rientro',
+	'paste': 'Incolla',
+	'redo': 'Ripristina',
+	'removeFormat': 'Rimuovi formato',
+	'selectAll': 'Seleziona tutto',
+	'strikethrough': 'Barrato',
+	'subscript': 'Pedice',
+	'superscript': 'Apice',
+	'underline': 'Sottolinea',
+	'undo': 'Annulla',
+	'unlink': 'Rimuovi collegamento',
+	'createLink': 'Crea collegamento',
+	'toggleDir': 'Attiva/Disattiva direzione',
+	'insertImage': 'Inserisci immagine',
+	'insertTable': 'Inserisci/Modifica tabella',
+	'toggleTableBorder': 'Attiva/Disattiva bordo tabella',
+	'deleteTable': 'Elimina tabella',
+	'tableProp': 'Proprietà tabella',
+	'htmlToggle': 'Origine HTML',
+	'foreColor': 'Colore primo piano',
+	'hiliteColor': 'Colore sfondo',
+	'plainFormatBlock': 'Stile paragrafo',
+	'formatBlock': 'Stile paragrafo',
+	'fontSize': 'Dimensione carattere',
+	'fontName': 'Nome carattere',
+	'tabIndent': 'Rientro tabulazione',
+	"fullScreen": "Attiva/Disattiva schermo intero",
+	"viewSource": "Visualizza origine HTML",
+	"print": "Stampa",
+	"newPage": "Nuova pagina",
+	/* Error messages */
+	'systemShortcut': 'La azione "${0}" è disponibile solo nel browser tramite un tasto di scelta rapida. Utilizzare ${1}.'
+})
+
diff --git a/dijit/_editor/nls/ja/FontChoice.js b/dijit/_editor/nls/ja/FontChoice.js
index a938d6b..d7e62f3 100644
--- a/dijit/_editor/nls/ja/FontChoice.js
+++ b/dijit/_editor/nls/ja/FontChoice.js
@@ -1 +1,25 @@
-({"1":"超極小","2":"極小","formatBlock":"フォーマット","3":"小","4":"標準","5":"大","6":"特大","7":"超特大","fantasy":"fantasy","serif":"serif","p":"段落","pre":"事前フォーマット済み","sans-serif":"sans-serif","fontName":"フォント","h1":"見出し","h2":"副見出し","h3":"副見出しの副見出し","monospace":"monospace","fontSize":"サイズ","cursive":"cursive"})
\ No newline at end of file
+({
+	fontSize: "サイズ",
+	fontName: "フォント",
+	formatBlock: "フォーマット",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursive",
+	fantasy: "fantasy",
+
+	p: "段落",
+	h1: "見出し",
+	h2: "副見出し",
+	h3: "副見出しの副見出し",
+	pre: "事前フォーマット済み",
+
+	1: "超極小",
+	2: "極小",
+	3: "小",
+	4: "標準",
+	5: "大",
+	6: "特大",
+	7: "超特大"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/ja/LinkDialog.js b/dijit/_editor/nls/ja/LinkDialog.js
index 815f508..b9f2ab1 100644
--- a/dijit/_editor/nls/ja/LinkDialog.js
+++ b/dijit/_editor/nls/ja/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"説明:","insertImageTitle":"イメージ・プロパティー","set":"設定","newWindow":"新規ウィンドウ","topWindow":"最上位ウィンドウ","target":"ターゲット:","createLinkTitle":"リンク・プロパティー","parentWindow":"親ウィンドウ","currentWindow":"現行ウィンドウ","url":"URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "リンク・プロパティー",
+	insertImageTitle: "イメージ・プロパティー",
+	url: "URL:",
+	text: "説明:",
+	target: "ターゲット:",
+	set: "設定",
+	currentWindow: "現行ウィンドウ",
+	parentWindow: "親ウィンドウ",
+	topWindow: "最上位ウィンドウ",
+	newWindow: "新規ウィンドウ"
+})
+
diff --git a/dijit/_editor/nls/ja/commands.js b/dijit/_editor/nls/ja/commands.js
index 0ca112a..e1b5471 100644
--- a/dijit/_editor/nls/ja/commands.js
+++ b/dijit/_editor/nls/ja/commands.js
@@ -1 +1,47 @@
-({"removeFormat":"形式の除去","copy":"コピー","paste":"貼り付け","selectAll":"すべて選択","insertOrderedList":"番号付きリスト","insertTable":"テーブルの挿入/編集","print":"印刷","underline":"下線","foreColor":"前景色","htmlToggle":"HTML ソース","formatBlock":"段落スタイル","newPage":"改ページ","insertHorizontalRule":"水平罫線","delete":"削除","insertUnorderedList":"黒丸付きリスト","tableProp":"テーブル・プロパティー","insertImage":"イメージの挿入","superscript":"上付き文字","subscript":"下付き文字","createLink":"リンクの作成","undo":"元に戻す","fullScreen":"フルスクリーンの切り替え","italic":"イタリック"," [...]
\ No newline at end of file
+({
+	'bold': '太字',
+	'copy': 'コピー',
+	'cut': '切り取り',
+	'delete': '削除',
+	'indent': 'インデント',
+	'insertHorizontalRule': '水平罫線',
+	'insertOrderedList': '番号付きリスト',
+	'insertUnorderedList': '黒丸付きリスト',
+	'italic': '斜体',
+	'justifyCenter': '中央揃え',
+	'justifyFull': '両端揃え',
+	'justifyLeft': '左揃え',
+	'justifyRight': '右揃え',
+	'outdent': 'アウトデント',
+	'paste': '貼り付け',
+	'redo': 'やり直し',
+	'removeFormat': '形式の除去',
+	'selectAll': 'すべて選択',
+	'strikethrough': '取り消し線',
+	'subscript': '下付き文字',
+	'superscript': '上付き文字',
+	'underline': '下線',
+	'undo': '元に戻す',
+	'unlink': 'リンクの削除',
+	'createLink': 'リンクの作成',
+	'toggleDir': '方向の切り替え',
+	'insertImage': 'イメージの挿入',
+	'insertTable': 'テーブルの挿入/編集',
+	'toggleTableBorder': 'テーブルボーダーの切り替え',
+	'deleteTable': 'テーブルの削除',
+	'tableProp': 'テーブルプロパティ',
+	'htmlToggle': 'HTML ソース',
+	'foreColor': '前景色',
+	'hiliteColor': '背景色',
+	'plainFormatBlock': '段落スタイル',
+	'formatBlock': '段落スタイル',
+	'fontSize': 'フォントサイズ',
+	'fontName': 'フォント名',
+	'tabIndent': 'タブインデント',
+	"fullScreen": "全画面表示に切り替え",
+	"viewSource": "HTML ソースの表示",
+	"print": "印刷",
+	"newPage": "新しいページ",
+	/* Error messages */
+	'systemShortcut': '"${0}" アクションを使用できるのは、ブラウザーでキーボードショートカットを使用する場合のみです。 ${1} を使用してください。'
+})
diff --git a/dijit/_editor/nls/ko/FontChoice.js b/dijit/_editor/nls/ko/FontChoice.js
index 2603063..7fe52f3 100644
--- a/dijit/_editor/nls/ko/FontChoice.js
+++ b/dijit/_editor/nls/ko/FontChoice.js
@@ -1 +1,25 @@
-({"1":"가장 작게","2":"조금 작게","formatBlock":"서식","3":"작게","4":"중간","5":"크게","6":"조금 크게","7":"가장 크게","fantasy":"fantasy","serif":"serif","p":"단락","pre":"서식이 지정됨","sans-serif":"sans-serif","fontName":"글꼴","h1":"제목","h2":"부제목","h3":"하위 부제목","monospace":"monospace","fontSize":"크기","cursive":"cursive"})
\ No newline at end of file
+({
+	fontSize: "크기",
+	fontName: "글꼴",
+	formatBlock: "서식",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursive",
+	fantasy: "fantasy",
+
+	p: "단락",
+	h1: "제목",
+	h2: "부제목",
+	h3: "하위 부제목",
+	pre: "서식이 지정됨",
+
+	1: "가장 작게",
+	2: "조금 작게",
+	3: "작게",
+	4: "중간",
+	5: "크게",
+	6: "조금 크게",
+	7: "가장 크게"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/ko/LinkDialog.js b/dijit/_editor/nls/ko/LinkDialog.js
index 1f46bd7..ea87569 100644
--- a/dijit/_editor/nls/ko/LinkDialog.js
+++ b/dijit/_editor/nls/ko/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"설명:","insertImageTitle":"이미지 특성","set":"설정","newWindow":"새 창","topWindow":"최상위 창","target":"대상:","createLinkTitle":"링크 특성","parentWindow":"상위 창","currentWindow":"현재 창","url":"URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "링크 특성",
+	insertImageTitle: "이미지 특성",
+	url: "URL:",
+	text: "설명:",
+	target: "대상:",
+	set: "설정",
+	currentWindow: "현재 창",
+	parentWindow: "상위 창",
+	topWindow: "최상위 창",
+	newWindow: "새 창"
+})
+
diff --git a/dijit/_editor/nls/ko/commands.js b/dijit/_editor/nls/ko/commands.js
index 4c8f954..d278c4b 100644
--- a/dijit/_editor/nls/ko/commands.js
+++ b/dijit/_editor/nls/ko/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"형식 제거","copy":"복사","paste":"붙여넣기","selectAll":"모두 선택","insertOrderedList":"번호 목록","insertTable":"테이블 삽입/편집","print":"인쇄","underline":"밑줄","foreColor":"전경색","htmlToggle":"HTML 소스","formatBlock":"단락 스타일","newPage":"새 페이지","insertHorizontalRule":"수평 자","delete":"삭제","insertUnorderedList":"글머리표 목록","tableProp":"테이블 특성","insertImage":"이미지 삽입","superscript":"위첨자","subscript":"아래첨자","createLink":"링크 작성","undo":"실행 취소","fullScreen":"토글 전체 화면","italic":"기울임체","fontName":"글꼴 이름", [...]
\ No newline at end of file
+({
+	'bold': '굵은체',
+	'copy': '복사',
+	'cut': '잘라내기',
+	'delete': '삭제',
+	'indent': '들여쓰기',
+	'insertHorizontalRule': '수평 자',
+	'insertOrderedList': '번호 목록',
+	'insertUnorderedList': '글머리표 목록',
+	'italic': '기울임체',
+	'justifyCenter': '가운데 맞춤',
+	'justifyFull': '양쪽 맞춤',
+	'justifyLeft': '왼쪽 맞춤',
+	'justifyRight': '오른쪽 맞춤',
+	'outdent': '내어쓰기',
+	'paste': '붙여넣기',
+	'redo': '다시 실행',
+	'removeFormat': '형식 제거',
+	'selectAll': '모두 선택',
+	'strikethrough': '취소선',
+	'subscript': '아래첨자',
+	'superscript': '위첨자',
+	'underline': '밑줄',
+	'undo': '실행 취소',
+	'unlink': '링크 제거',
+	'createLink': '링크 작성',
+	'toggleDir': '토글 방향',
+	'insertImage': '이미지 삽입',
+	'insertTable': '테이블 삽입/편집',
+	'toggleTableBorder': '토글 테이블 테두리',
+	'deleteTable': '테이블 삭제',
+	'tableProp': '테이블 특성',
+	'htmlToggle': 'HTML 소스',
+	'foreColor': '전경색',
+	'hiliteColor': '배경색',
+	'plainFormatBlock': '단락 스타일',
+	'formatBlock': '단락 스타일',
+	'fontSize': '글꼴 크기',
+	'fontName': '글꼴 이름',
+	'tabIndent': '탭 들여쓰기',
+	"fullScreen": "토글 전체 화면",
+	"viewSource": "HTML 소스 보기",
+	"print": "인쇄",
+	"newPage": "새 페이지",
+	/* Error messages */
+	'systemShortcut': '"${0}" 조치는 브라우저에서 키보드 단축키를 이용해서만 사용할 수 있습니다. ${1}을(를) 사용하십시오.'
+})
+
diff --git a/dijit/_editor/nls/nb/FontChoice.js b/dijit/_editor/nls/nb/FontChoice.js
index f22d972..84b00a9 100644
--- a/dijit/_editor/nls/nb/FontChoice.js
+++ b/dijit/_editor/nls/nb/FontChoice.js
@@ -1 +1,25 @@
-({"1":"xx-liten","2":"x-liten","formatBlock":"Format","3":"liten","4":"middels","5":"stor","6":"x-stor","7":"xx-stor","fantasy":"fantasi","serif":"serif","p":"Avsnitt","pre":"Forhåndsformatert","sans-serif":"sans-serif","fontName":"Skrift","h1":"Overskrift","h2":"Undertittel","h3":"Under-undertittel","monospace":"monospace","fontSize":"Størrelse","cursive":"kursiv"})
\ No newline at end of file
+({
+	fontSize: "Størrelse",
+	fontName: "Skrift",
+	formatBlock: "Format",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "kursiv",
+	fantasy: "fantasi",
+
+	p: "Avsnitt",
+	h1: "Overskrift",
+	h2: "Undertittel",
+	h3: "Under-undertittel",
+	pre: "Forhåndsformatert",
+
+	1: "xx-liten",
+	2: "x-liten",
+	3: "liten",
+	4: "middels",
+	5: "stor",
+	6: "x-stor",
+	7: "xx-stor"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/nb/LinkDialog.js b/dijit/_editor/nls/nb/LinkDialog.js
index 6349943..e7f0f8d 100644
--- a/dijit/_editor/nls/nb/LinkDialog.js
+++ b/dijit/_editor/nls/nb/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"Definer","text":"Beskrivelse:","insertImageTitle":"Bildeegenskaper","url":"URL:","createLinkTitle":"Koblingsegenskaper","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "Koblingsegenskaper",
+	insertImageTitle: "Bildeegenskaper",
+	url: "URL:",
+	text: "Beskrivelse:",
+	target: "Mål:",
+	set: "Definer",
+	currentWindow: "Gjeldende vindu",
+	parentWindow: "Overordnet vindu",
+	topWindow: "Øverste vindu",
+	newWindow: "Nytt vindu"
+})
+
diff --git a/dijit/_editor/nls/nb/commands.js b/dijit/_editor/nls/nb/commands.js
index 1b3a56f..7b47e4f 100644
--- a/dijit/_editor/nls/nb/commands.js
+++ b/dijit/_editor/nls/nb/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Fjern format","copy":"Kopier","paste":"Lim inn","selectAll":"Velg alle","insertOrderedList":"Nummerert liste","insertTable":"Sett inn/rediger tabell","underline":"Understreking","foreColor":"Forgrunnsfarge","htmlToggle":"HTML-kilde","formatBlock":"Avsnittsstil","insertHorizontalRule":"Vannrett strek","delete":"Slett","insertUnorderedList":"Punktliste","tableProp":"Tabellegenskap","insertImage":"Sett inn bilde","superscript":"Hevet skrift","subscript":"Senket skrift","cr [...]
\ No newline at end of file
+({
+	'bold': 'Fet',
+	'copy': 'Kopier',
+	'cut': 'Klipp ut',
+	'delete': 'Slett',
+	'indent': 'Innrykk',
+	'insertHorizontalRule': 'Vannrett strek',
+	'insertOrderedList': 'Nummerert liste',
+	'insertUnorderedList': 'Punktliste',
+	'italic': 'Kursiv',
+	'justifyCenter': 'Midtstill',
+	'justifyFull': 'Juster',
+	'justifyLeft': 'Venstrejuster',
+	'justifyRight': 'Høyrejuster',
+	'outdent': 'Fjern innrykk',
+	'paste': 'Lim inn',
+	'redo': 'Gjør om',
+	'removeFormat': 'Fjern format',
+	'selectAll': 'Velg alle',
+	'strikethrough': 'Gjennomstreking',
+	'subscript': 'Senket skrift',
+	'superscript': 'Hevet skrift',
+	'underline': 'Understreking',
+	'undo': 'Angre',
+	'unlink': 'Fjern kobling',
+	'createLink': 'Opprett kobling',
+	'toggleDir': 'Bytt retning',
+	'insertImage': 'Sett inn bilde',
+	'insertTable': 'Sett inn/rediger tabell',
+	'toggleTableBorder': 'Bytt tabellkant',
+	'deleteTable': 'Slett tabell',
+	'tableProp': 'Tabellegenskap',
+	'htmlToggle': 'HTML-kilde',
+	'foreColor': 'Forgrunnsfarge',
+	'hiliteColor': 'Bakgrunnsfarge',
+	'plainFormatBlock': 'Avsnittsstil',
+	'formatBlock': 'Avsnittsstil',
+	'fontSize': 'Skriftstørrelse',
+	'fontName': 'Skriftnavn',
+	'tabIndent': 'Tabulatorinnrykk',
+	"fullScreen": "Slå på/av full skjerm",
+	"viewSource": "Vis HTML-kilde",
+	"print": "Skriv ut",
+	"newPage": "Ny side",
+	/* Error messages */
+	'systemShortcut': 'Handlingen "${0}" er bare tilgjengelig i nettleseren ved hjelp av en tastatursnarvei. Bruk ${1}.'
+})
+
diff --git a/dijit/_editor/nls/nl/FontChoice.js b/dijit/_editor/nls/nl/FontChoice.js
index e6811aa..db9a8ba 100644
--- a/dijit/_editor/nls/nl/FontChoice.js
+++ b/dijit/_editor/nls/nl/FontChoice.js
@@ -1 +1,25 @@
-({"1":"xx-klein","2":"x-klein","formatBlock":"Opmaak","3":"klein","4":"gemiddeld","5":"groot","6":"x-groot","7":"xx-groot","fantasy":"fantasy","serif":"serif","p":"Alinea","pre":"Vooraf opgemaakt","sans-serif":"sans-serif","fontName":"Lettertype","h1":"Kop","h2":"Subkop","h3":"Sub-subkop","monospace":"monospace","fontSize":"Grootte","cursive":"cursief"})
\ No newline at end of file
+({
+	fontSize: "Grootte",
+	fontName: "Lettertype",
+	formatBlock: "Opmaak",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursief",
+	fantasy: "fantasy",
+
+	p: "Alinea",
+	h1: "Kop",
+	h2: "Subkop",
+	h3: "Sub-subkop",
+	pre: "Vooraf opgemaakt",
+
+	1: "xx-klein",
+	2: "x-klein",
+	3: "klein",
+	4: "gemiddeld",
+	5: "groot",
+	6: "x-groot",
+	7: "xx-groot"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/nl/LinkDialog.js b/dijit/_editor/nls/nl/LinkDialog.js
index ddcd2fd..38840ee 100644
--- a/dijit/_editor/nls/nl/LinkDialog.js
+++ b/dijit/_editor/nls/nl/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"Instellen","text":"Beschrijving:","insertImageTitle":"Afbeeldingseigenschappen","url":"URL:","createLinkTitle":"Linkeigenschappen","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "Linkeigenschappen",
+	insertImageTitle: "Afbeeldingseigenschappen",
+	url: "URL:",
+	text: "Beschrijving:",
+	target: "Doel:",
+	set: "Instellen",
+	currentWindow: "Huidig venster",
+	parentWindow: "Hoofdvenster",
+	topWindow: "Bovenste venster",
+	newWindow: "Nieuw venster"
+})
+
diff --git a/dijit/_editor/nls/nl/commands.js b/dijit/_editor/nls/nl/commands.js
index bae4fe8..01366f7 100644
--- a/dijit/_editor/nls/nl/commands.js
+++ b/dijit/_editor/nls/nl/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Opmaak verwijderen","copy":"Kopiëren","paste":"Plakken","selectAll":"Alles selecteren","insertOrderedList":"Genummerde lijst","insertTable":"Tabel invoegen/bewerken","underline":"Onderstrepen","foreColor":"Voorgrondkleur","htmlToggle":"HTML-bron","formatBlock":"Alineastijl","insertHorizontalRule":"Horizontale liniaal","delete":"Wissen","insertUnorderedList":"Lijst met opsommingstekens","tableProp":"Tabeleigenschap","insertImage":"Afbeelding invoegen","superscript":"Supe [...]
\ No newline at end of file
+({
+	'bold': 'Vet',
+	'copy': 'Kopiëren',
+	'cut': 'Knippen',
+	'delete': 'Wissen',
+	'indent': 'Inspringen',
+	'insertHorizontalRule': 'Horizontale liniaal',
+	'insertOrderedList': 'Genummerde lijst',
+	'insertUnorderedList': 'Lijst met opsommingstekens',
+	'italic': 'Cursief',
+	'justifyCenter': 'Centreren',
+	'justifyFull': 'Uitvullen',
+	'justifyLeft': 'Links uitlijnen',
+	'justifyRight': 'Rechts uitlijnen',
+	'outdent': 'Uitspringen',
+	'paste': 'Plakken',
+	'redo': 'Opnieuw',
+	'removeFormat': 'Opmaak verwijderen',
+	'selectAll': 'Alles selecteren',
+	'strikethrough': 'Doorhalen',
+	'subscript': 'Subscript',
+	'superscript': 'Superscript',
+	'underline': 'Onderstrepen',
+	'undo': 'Ongedaan maken',
+	'unlink': 'Link verwijderen',
+	'createLink': 'Link maken',
+	'toggleDir': 'Schrijfrichting wijzigen',
+	'insertImage': 'Afbeelding invoegen',
+	'insertTable': 'Tabel invoegen/bewerken',
+	'toggleTableBorder': 'Tabelkader wijzigen',
+	'deleteTable': 'Tabel wissen',
+	'tableProp': 'Tabeleigenschap',
+	'htmlToggle': 'HTML-bron',
+	'foreColor': 'Voorgrondkleur',
+	'hiliteColor': 'Achtergrondkleur',
+	'plainFormatBlock': 'Alineastijl',
+	'formatBlock': 'Alineastijl',
+	'fontSize': 'Lettergrootte',
+	'fontName': 'Lettertype',
+	'tabIndent': 'Inspringen',
+	"fullScreen": "Volledig scherm in-/uitschakelen",
+	"viewSource": "HTML-bron bekijken",
+	"print": "Afdrukken",
+	"newPage": "Nieuwe pagina",
+	/* Error messages */
+	'systemShortcut': 'De actie "${0}" is alleen beschikbaar in uw browser via een sneltoetscombinatie. Gebruik ${1}.'
+})
+
diff --git a/dijit/_editor/nls/pl/FontChoice.js b/dijit/_editor/nls/pl/FontChoice.js
index 3c03893..8a1546c 100644
--- a/dijit/_editor/nls/pl/FontChoice.js
+++ b/dijit/_editor/nls/pl/FontChoice.js
@@ -1 +1,25 @@
-({"1":"najmniejsza","2":"mniejsza","formatBlock":"Format","3":"mała","4":"średnia","5":"duża","6":"większa","7":"największa","fantasy":"fantazyjna","serif":"szeryfowa","p":"Akapit","pre":"Wstępnie sformatowane","sans-serif":"bezszeryfowa","fontName":"Czcionka","h1":"Nagłówek","h2":"Nagłówek 2-go poziomu","h3":"Nagłówek 3-go poziomu","monospace":"czcionka o stałej szerokości","fontSize":"Wielkość","cursive":"kursywa"})
\ No newline at end of file
+({
+	fontSize: "Wielkość",
+	fontName: "Czcionka",
+	formatBlock: "Format",
+
+	serif: "szeryfowa",
+	"sans-serif": "bezszeryfowa",
+	monospace: "czcionka o stałej szerokości",
+	cursive: "kursywa",
+	fantasy: "fantazyjna",
+
+	p: "Akapit",
+	h1: "Nagłówek",
+	h2: "Nagłówek 2-go poziomu",
+	h3: "Nagłówek 3-go poziomu",
+	pre: "Wstępnie sformatowane",
+
+	1: "najmniejsza",
+	2: "mniejsza",
+	3: "mała",
+	4: "średnia",
+	5: "duża",
+	6: "większa",
+	7: "największa"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/pl/LinkDialog.js b/dijit/_editor/nls/pl/LinkDialog.js
index 86f71e5..138d55f 100644
--- a/dijit/_editor/nls/pl/LinkDialog.js
+++ b/dijit/_editor/nls/pl/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"Opis:","insertImageTitle":"Właściwości obrazu","set":"Ustaw","newWindow":"Nowe okno","topWindow":"Okno najwyższego poziomu","target":"Cel:","createLinkTitle":"Właściwości odsyłacza","parentWindow":"Okno macierzyste","currentWindow":"Bieżące okno","url":"Adres URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "Właściwości odsyłacza",
+	insertImageTitle: "Właściwości obrazu",
+	url: "Adres URL:",
+	text: "Opis:",
+	target: "Cel:",
+	set: "Ustaw",
+	currentWindow: "Bieżące okno",
+	parentWindow: "Okno macierzyste",
+	topWindow: "Okno najwyższego poziomu",
+	newWindow: "Nowe okno"
+})
+
diff --git a/dijit/_editor/nls/pl/commands.js b/dijit/_editor/nls/pl/commands.js
index 8ee8acf..8b388b4 100644
--- a/dijit/_editor/nls/pl/commands.js
+++ b/dijit/_editor/nls/pl/commands.js
@@ -1 +1,49 @@
-({"removeFormat":"Usuń formatowanie","copy":"Kopiuj","paste":"Wklej","selectAll":"Wybierz wszystko","insertOrderedList":"Lista numerowana","insertTable":"Wstaw/edytuj tabelę","print":"Drukuj","underline":"Podkreślenie","foreColor":"Kolor pierwszego planu","htmlToggle":"Źródło HTML","formatBlock":"Styl akapitu","newPage":"Nowa strona","insertHorizontalRule":"Linia pozioma","delete":"Usuń","insertUnorderedList":"Lista wypunktowana","tableProp":"Właściwość tabeli","insertImage":"Wstaw obraz [...]
\ No newline at end of file
+({
+	'bold': 'Pogrubienie',
+	'copy': 'Kopiuj',
+	'cut': 'Wytnij',
+	'delete': 'Usuń',
+	'indent': 'Wcięcie',
+	'insertHorizontalRule': 'Linia pozioma',
+	'insertOrderedList': 'Lista numerowana',
+	'insertUnorderedList': 'Lista wypunktowana',
+	'italic': 'Kursywa',
+	'justifyCenter': 'Wyrównaj do środka',
+	'justifyFull': 'Wyrównaj do lewej i prawej',
+	'justifyLeft': 'Wyrównaj do lewej',
+	'justifyRight': 'Wyrównaj do prawej',
+	'outdent': 'Usuń wcięcie',
+	'paste': 'Wklej',
+	'redo': 'Ponów',
+	'removeFormat': 'Usuń formatowanie',
+	'selectAll': 'Wybierz wszystko',
+	'strikethrough': 'Przekreślenie',
+	'subscript': 'Indeks dolny',
+	'superscript': 'Indeks górny',
+	'underline': 'Podkreślenie',
+	'undo': 'Cofnij',
+	'unlink': 'Usuń odsyłacz',
+	'createLink': 'Utwórz odsyłacz',
+	'toggleDir': 'Przełącz kierunek',
+	'insertImage': 'Wstaw obraz',
+	'insertTable': 'Wstaw/edytuj tabelę',
+	'toggleTableBorder': 'Przełącz ramkę tabeli',
+	'deleteTable': 'Usuń tabelę',
+	'tableProp': 'Właściwość tabeli',
+	'htmlToggle': 'Źródło HTML',
+	'foreColor': 'Kolor pierwszego planu',
+	'hiliteColor': 'Kolor tła',
+	'plainFormatBlock': 'Styl akapitu',
+	'formatBlock': 'Styl akapitu',
+	'fontSize': 'Wielkość czcionki',
+	'fontName': 'Nazwa czcionki',
+	'tabIndent': 'Wcięcie o tabulator',
+	"fullScreen": "Przełącz pełny ekran",
+	"viewSource": "Wyświetl kod źródłowy HTML",
+	"print": "Drukuj",
+	"newPage": "Nowa strona",
+	/* Error messages */
+	'systemShortcut': 'Działanie ${0} jest dostępne w tej przeglądarce wyłącznie przy użyciu skrótu klawiaturowego. Należy użyć klawiszy ${1}.',
+	'ctrlKey':'Ctrl+${0}'
+})
+
diff --git a/dijit/_editor/nls/pt-pt/FontChoice.js b/dijit/_editor/nls/pt-pt/FontChoice.js
index c72a102..f038d84 100644
--- a/dijit/_editor/nls/pt-pt/FontChoice.js
+++ b/dijit/_editor/nls/pt-pt/FontChoice.js
@@ -1 +1,25 @@
-({"1":"xxs","2":"xs","formatBlock":"Formato","3":"small","4":"medium","5":"large","6":"xl","7":"xxl","fantasy":"fantasy","serif":"serif","p":"Parágrafo","pre":"Pré-formatado","sans-serif":"sans-serif","fontName":"Tipo de letra","h1":"Título","h2":"Sub-título","h3":"Sub-subtítulo","monospace":"monospace","fontSize":"Tamanho","cursive":"cursive"})
\ No newline at end of file
+({
+	fontSize: "Tamanho",
+	fontName: "Tipo de letra",
+	formatBlock: "Formato",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursive",
+	fantasy: "fantasy",
+
+	p: "Parágrafo",
+	h1: "Título",
+	h2: "Sub-título",
+	h3: "Sub-subtítulo",
+	pre: "Pré-formatado",
+
+	1: "xxs",
+	2: "xs",
+	3: "small",
+	4: "medium",
+	5: "large",
+	6: "xl",
+	7: "xxl"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/pt-pt/LinkDialog.js b/dijit/_editor/nls/pt-pt/LinkDialog.js
index 09da9f6..70f0f52 100644
--- a/dijit/_editor/nls/pt-pt/LinkDialog.js
+++ b/dijit/_editor/nls/pt-pt/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"Definir","text":"Descrição:","insertImageTitle":"Propriedades da imagem","url":"URL:","createLinkTitle":"Propriedades da ligação","newWindow":"Nova Janela","topWindow":"Primeira Janela","target":"Destino:","parentWindow":"Janela Pai","currentWindow":"Janela Atual"})
\ No newline at end of file
+({
+	createLinkTitle: "Propriedades da ligação",
+	insertImageTitle: "Propriedades da imagem",
+	url: "URL:",
+	text: "Descrição:",
+	target: "Destino:",
+	set: "Definir",
+	currentWindow: "Janela actual",
+	parentWindow: "Janela ascendente",
+	topWindow: "Janela superior",
+	newWindow: "Nova janela"
+})
+
diff --git a/dijit/_editor/nls/pt-pt/commands.js b/dijit/_editor/nls/pt-pt/commands.js
index 678ba22..30080d2 100644
--- a/dijit/_editor/nls/pt-pt/commands.js
+++ b/dijit/_editor/nls/pt-pt/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Remover formato","copy":"Copiar","paste":"Colar","selectAll":"Seleccionar tudo","insertOrderedList":"Lista numerada","insertTable":"Inserir/Editar tabela","underline":"Sublinhado","foreColor":"Cor de primeiro plano","htmlToggle":"Origem HTML","formatBlock":"Estilo de parágrafo","insertHorizontalRule":"Régua horizontal","delete":"Eliminar","insertUnorderedList":"Lista marcada","tableProp":"Propriedades da tabela","insertImage":"Inserir imagem","superscript":"Superior à l [...]
\ No newline at end of file
+({
+	'bold': 'Negrito',
+	'copy': 'Copiar',
+	'cut': 'Cortar',
+	'delete': 'Eliminar',
+	'indent': 'Indentar',
+	'insertHorizontalRule': 'Régua horizontal',
+	'insertOrderedList': 'Lista numerada',
+	'insertUnorderedList': 'Lista marcada',
+	'italic': 'Itálico',
+	'justifyCenter': 'Alinhar ao centro',
+	'justifyFull': 'Justificar',
+	'justifyLeft': 'Alinhar à esquerda',
+	'justifyRight': 'Alinhar à direita',
+	'outdent': 'Recuar',
+	'paste': 'Colar',
+	'redo': 'Repetir',
+	'removeFormat': 'Remover formato',
+	'selectAll': 'Seleccionar tudo',
+	'strikethrough': 'Rasurado',
+	'subscript': 'Inferior à linha',
+	'superscript': 'Superior à linha',
+	'underline': 'Sublinhado',
+	'undo': 'Anular',
+	'unlink': 'Remover ligação',
+	'createLink': 'Criar ligação',
+	'toggleDir': 'Alternar direcção',
+	'insertImage': 'Inserir imagem',
+	'insertTable': 'Inserir/Editar tabela',
+	'toggleTableBorder': 'Alternar contorno da tabela',
+	'deleteTable': 'Eliminar tabela',
+	'tableProp': 'Propriedades da tabela',
+	'htmlToggle': 'Origem HTML',
+	'foreColor': 'Cor de primeiro plano',
+	'hiliteColor': 'Cor de segundo plano',
+	'plainFormatBlock': 'Estilo de parágrafo',
+	'formatBlock': 'Estilo de parágrafo',
+	'fontSize': 'Tamanho do tipo de letra',
+	'fontName': 'Nome do tipo de letra',
+	'tabIndent': 'Indentar com a tecla Tab',
+	"fullScreen": "Alternar ecrã completo",
+	"viewSource": "Ver origem HTML",
+	"print": "Imprimir",
+	"newPage": "Nova página",
+	/* Error messages */
+	'systemShortcut': 'A acção "${0}" apenas está disponível no navegador utilizando um atalho de teclado. Utilize ${1}.'
+})
+
diff --git a/dijit/_editor/nls/pt/FontChoice.js b/dijit/_editor/nls/pt/FontChoice.js
index 5919b43..ee93dcc 100644
--- a/dijit/_editor/nls/pt/FontChoice.js
+++ b/dijit/_editor/nls/pt/FontChoice.js
@@ -1 +1,25 @@
-({"1":"extra-extra-pequeno","2":"extra-pequeno","formatBlock":"Formatar","3":"pequena","4":"médio","5":"grande","6":"extra-grande","7":"extra-extra-grande","fantasy":"fantasy","serif":"serif","p":"Parágrafo","pre":"Pré-formatado","sans-serif":"sans-serif","fontName":"Fonte","h1":"Título","h2":"Subtítulo","h3":"Sub-subtítulo","monospace":"espaço simples","fontSize":"Tamanho","cursive":"cursiva"})
\ No newline at end of file
+({
+	fontSize: "Tamanho",
+	fontName: "Fonte",
+	formatBlock: "Formatar",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "espaço simples",
+	cursive: "cursiva",
+	fantasy: "fantasy",
+
+	p: "Parágrafo",
+	h1: "Título",
+	h2: "Subtítulo",
+	h3: "Sub-subtítulo",
+	pre: "Pré-formatado",
+
+	1: "extra-extra-pequeno",
+	2: "extra-pequeno",
+	3: "pequena",
+	4: "médio",
+	5: "grande",
+	6: "extra-grande",
+	7: "extra-extra-grande"
+})
diff --git a/dijit/_editor/nls/pt/LinkDialog.js b/dijit/_editor/nls/pt/LinkDialog.js
index 0a55795..4e09587 100644
--- a/dijit/_editor/nls/pt/LinkDialog.js
+++ b/dijit/_editor/nls/pt/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"Descrição:","insertImageTitle":"Propriedades de Imagem","set":"Definir","newWindow":"Nova Janela","topWindow":"Primeira Janela","target":"Destino:","createLinkTitle":"Propriedades de Link","parentWindow":"Janela Pai","currentWindow":"Janela Atual","url":"URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "Propriedades de Link",
+	insertImageTitle: "Propriedades de Imagem",
+	url: "URL:",
+	text: "Descrição:",
+	target: "Destino:",
+	set: "Definir",
+	currentWindow: "Janela Atual",
+	parentWindow: "Janela Pai",
+	topWindow: "Primeira Janela",
+	newWindow: "Nova Janela"
+})
+
diff --git a/dijit/_editor/nls/pt/commands.js b/dijit/_editor/nls/pt/commands.js
index 271c6cf..e0e6d75 100644
--- a/dijit/_editor/nls/pt/commands.js
+++ b/dijit/_editor/nls/pt/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Remover Formato","copy":"Copiar","paste":"Colar","selectAll":"Selecionar Todos","insertOrderedList":"Lista Numerada","insertTable":"Inserir/Editar Tabela","print":"Impressão","underline":"Sublinhado","foreColor":"Cor do Primeiro Plano","htmlToggle":"Origem HTML","formatBlock":"Estilo de Parágrafo","newPage":"Nova Página","insertHorizontalRule":"Régua Horizontal","delete":"Excluir","insertUnorderedList":"Lista com Marcadores","tableProp":"Propriedade da Tabela","insertIm [...]
\ No newline at end of file
+({
+	'bold': 'Negrito',
+	'copy': 'Copiar',
+	'cut': 'Recortar',
+	'delete': 'Excluir',
+	'indent': 'Recuar',
+	'insertHorizontalRule': 'Régua Horizontal',
+	'insertOrderedList': 'Lista Numerada',
+	'insertUnorderedList': 'Lista com Marcadores',
+	'italic': 'Itálico',
+	'justifyCenter': 'Alinhar pelo Centro',
+	'justifyFull': 'Justificar',
+	'justifyLeft': 'Alinhar pela Esquerda',
+	'justifyRight': 'Alinhar pela Direita',
+	'outdent': 'Não-chanfrado',
+	'paste': 'Colar',
+	'redo': 'Refazer',
+	'removeFormat': 'Remover Formato',
+	'selectAll': 'Selecionar Todos',
+	'strikethrough': 'Tachado',
+	'subscript': 'Subscrito',
+	'superscript': 'Sobrescrito',
+	'underline': 'Sublinhado',
+	'undo': 'Desfazer',
+	'unlink': 'Remover Link',
+	'createLink': 'Criar Link',
+	'toggleDir': 'Comutar Direção',
+	'insertImage': 'Inserir Imagem',
+	'insertTable': 'Inserir/Editar Tabela',
+	'toggleTableBorder': 'Alternar Moldura da Tabela',
+	'deleteTable': 'Excluir Tabela',
+	'tableProp': 'Propriedade da Tabela',
+	'htmlToggle': 'Origem HTML',
+	'foreColor': 'Cor do Primeiro Plano',
+	'hiliteColor': 'Cor de segundo plano',
+	'plainFormatBlock': 'Estilo de Parágrafo',
+	'formatBlock': 'Estilo de Parágrafo',
+	'fontSize': 'Tamanho da Fonte',
+	'fontName': 'Nome da Fonte',
+	'tabIndent': 'Recuo de Guia',
+	"fullScreen": "Comutar Tela Cheia",
+	"viewSource": "Visualizar Origem HTML",
+	"print": "Impressão",
+	"newPage": "Nova Página",
+	/* Error messages */
+	'systemShortcut': 'A ação "${0}" está disponível em seu navegador apenas usando um atalho do teclado. Use ${1}.'
+})
+
diff --git a/dijit/_editor/nls/ro/FontChoice.js b/dijit/_editor/nls/ro/FontChoice.js
new file mode 100644
index 0000000..1badfb3
--- /dev/null
+++ b/dijit/_editor/nls/ro/FontChoice.js
@@ -0,0 +1,27 @@
+({
+	fontSize: "Dimensiune",
+	fontName: "Font",
+	formatBlock: "Format",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursive",
+	fantasy: "fantasy",
+
+	noFormat: "Fără",
+	p: "Paragraf",
+	h1: "Titlu",
+	h2: "Subtitlu",
+	h3: "Sub-subtitlu",
+	pre: "Preformatat",
+
+	1: "xxs (xx-small)",
+	2: "xs (x-small)",
+	3: "s (small)",
+	4: "m (medium)",
+	5: "l (large)",
+	6: "xl (x-large)",
+	7: "xxl (xx-large)"
+})
+
diff --git a/dijit/_editor/nls/ro/LinkDialog.js b/dijit/_editor/nls/ro/LinkDialog.js
new file mode 100644
index 0000000..edb7add
--- /dev/null
+++ b/dijit/_editor/nls/ro/LinkDialog.js
@@ -0,0 +1,13 @@
+({
+	createLinkTitle: "Proprietăţi legătură",
+	insertImageTitle: "Proprietăţi imagine",
+	url: "URL:",
+	text: "Descriere:",
+	target: "Ţintă:",
+	set: "Setare",
+	currentWindow: "Fereastra curentă",
+	parentWindow: "Fereastra părinte",
+	topWindow: "Fereastra cea mai de sus",
+	newWindow: "Fereastră nouă"
+})
+
diff --git a/dijit/_editor/nls/ro/commands.js b/dijit/_editor/nls/ro/commands.js
new file mode 100644
index 0000000..a6a383a
--- /dev/null
+++ b/dijit/_editor/nls/ro/commands.js
@@ -0,0 +1,48 @@
+({
+	'bold': 'Aldine',
+	'copy': 'Copiere',
+	'cut': 'Tăiere',
+	'delete': 'Ştergere',
+	'indent': 'Indentare',
+	'insertHorizontalRule': 'Regulă orizontală',
+	'insertOrderedList': 'Listă numerotată',
+	'insertUnorderedList': 'Listă cu marcaje',
+	'italic': 'Cursive',
+	'justifyCenter': 'Aliniere pe centru',
+	'justifyFull': 'Aliniere',
+	'justifyLeft': 'Aliniere la stânga',
+	'justifyRight': 'Aliniere la dreapta',
+	'outdent': 'Outdentare',
+	'paste': 'Lipire',
+	'redo': 'Repetare acţiune',
+	'removeFormat': 'Înlăturare format',
+	'selectAll': 'Selectare toate',
+	'strikethrough': 'Suprascriere linie',
+	'subscript': 'Scriere indice inferior',
+	'superscript': 'Scriere indice superior',
+	'underline': 'Subliniere',
+	'undo': 'Anulare acţiune',
+	'unlink': 'Înlăturare legătură',
+	'createLink': 'Creare legătură',
+	'toggleDir': 'Comutare direcţie',
+	'insertImage': 'Inserare imagine',
+	'insertTable': 'Inserare/Editare tabelă',
+	'toggleTableBorder': 'Comutare bordură tabelă',
+	'deleteTable': 'Ştergere tabelă',
+	'tableProp': 'Proprietăţi tabelă',
+	'htmlToggle': 'Sursă HTML',
+	'foreColor': 'Culoare prim plan',
+	'hiliteColor': 'Culoare fundal',
+	'plainFormatBlock': 'Stil paragraf',
+	'formatBlock': 'Stil paragraf',
+	'fontSize': 'Dimensiune font',
+	'fontName': 'Nume font',
+	'tabIndent': 'Indentare cu tab',
+	"fullScreen": "Comutare ecran complet",
+	"viewSource": "Vizualizare sursă HTML",
+	"print": "Tipărire",
+	"newPage": "Pagină nouă",
+	/* Error messages */
+	'systemShortcut': 'Acţiunea "${0}" este disponibilă în browser folosind o scurtătură de la tastatură. Folosiţi ${1}.'
+})
+
diff --git a/dijit/_editor/nls/ru/FontChoice.js b/dijit/_editor/nls/ru/FontChoice.js
index cebf574..daf517f 100644
--- a/dijit/_editor/nls/ru/FontChoice.js
+++ b/dijit/_editor/nls/ru/FontChoice.js
@@ -1 +1,25 @@
-({"1":"самый маленький","2":"очень маленький","formatBlock":"Формат","3":"маленький","4":"средний","5":"большой","6":"очень большой","7":"самый большой","fantasy":"артистический","serif":"с засечками","p":"Абзац","pre":"Заранее отформатированный","sans-serif":"без засечек","fontName":"Шрифт","h1":"Заголовок","h2":"Подзаголовок","h3":"Вложенный подзаголовок","monospace":"непропорциональный","fontSize":"Размер","cursive":"курсив"})
\ No newline at end of file
+({
+	fontSize: "Размер",
+	fontName: "Шрифт",
+	formatBlock: "Формат",
+
+	serif: "с засечками",
+	"sans-serif": "без засечек",
+	monospace: "непропорциональный",
+	cursive: "курсив",
+	fantasy: "артистический",
+
+	p: "Абзац",
+	h1: "Заголовок",
+	h2: "Подзаголовок",
+	h3: "Вложенный подзаголовок",
+	pre: "Заранее отформатированный",
+
+	1: "самый маленький",
+	2: "очень маленький",
+	3: "маленький",
+	4: "средний",
+	5: "большой",
+	6: "очень большой",
+	7: "самый большой"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/ru/LinkDialog.js b/dijit/_editor/nls/ru/LinkDialog.js
index ddc2f7b..d985008 100644
--- a/dijit/_editor/nls/ru/LinkDialog.js
+++ b/dijit/_editor/nls/ru/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"Описание:","insertImageTitle":"Свойства изображения","set":"Задать","newWindow":"Новое окно","topWindow":"Окно верхнего уровня","target":"Целевой объект:","createLinkTitle":"Свойства ссылки","parentWindow":"Родительское окно","currentWindow":"Текущее окно","url":"URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "Свойства ссылки",
+	insertImageTitle: "Свойства изображения",
+	url: "URL:",
+	text: "Описание:",
+	target: "Целевой объект:",
+	set: "Задать",
+	currentWindow: "Текущее окно",
+	parentWindow: "Родительское окно",
+	topWindow: "Окно верхнего уровня",
+	newWindow: "Новое окно"
+})
+
diff --git a/dijit/_editor/nls/ru/commands.js b/dijit/_editor/nls/ru/commands.js
index bbc7617..f609cee 100644
--- a/dijit/_editor/nls/ru/commands.js
+++ b/dijit/_editor/nls/ru/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Удалить формат","copy":"Копировать","paste":"Вставить","selectAll":"Выбрать все","insertOrderedList":"Нумерованный список","insertTable":"Вставить/изменить таблицу","print":"Печать","underline":"Подчеркивание","foreColor":"Цвет текста","htmlToggle":"Код HTML","formatBlock":"Стиль абзаца","newPage":"Создать страницу","insertHorizontalRule":"Горизонтальная линейка","delete":"Удалить","insertUnorderedList":"Список с маркерами","tableProp":"Свойства таблицы","insertImage":" [...]
\ No newline at end of file
+({
+	'bold': 'Полужирный',
+	'copy': 'Копировать',
+	'cut': 'Вырезать',
+	'delete': 'Удалить',
+	'indent': 'Отступ',
+	'insertHorizontalRule': 'Горизонтальная линейка',
+	'insertOrderedList': 'Нумерованный список',
+	'insertUnorderedList': 'Список с маркерами',
+	'italic': 'Курсив',
+	'justifyCenter': 'По центру',
+	'justifyFull': 'По ширине',
+	'justifyLeft': 'По левому краю',
+	'justifyRight': 'По правому краю',
+	'outdent': 'Втяжка',
+	'paste': 'Вставить',
+	'redo': 'Повторить',
+	'removeFormat': 'Удалить формат',
+	'selectAll': 'Выбрать все',
+	'strikethrough': 'Перечеркивание',
+	'subscript': 'Нижний индекс',
+	'superscript': 'Верхний индекс',
+	'underline': 'Подчеркивание',
+	'undo': 'Отменить',
+	'unlink': 'Удалить ссылку',
+	'createLink': 'Создать ссылку',
+	'toggleDir': 'Изменить направление',
+	'insertImage': 'Вставить изображение',
+	'insertTable': 'Вставить/изменить таблицу',
+	'toggleTableBorder': 'Переключить рамку таблицы',
+	'deleteTable': 'Удалить таблицу',
+	'tableProp': 'Свойства таблицы',
+	'htmlToggle': 'Код HTML',
+	'foreColor': 'Цвет текста',
+	'hiliteColor': 'Цвет фона',
+	'plainFormatBlock': 'Стиль абзаца',
+	'formatBlock': 'Стиль абзаца',
+	'fontSize': 'Размер шрифта',
+	'fontName': 'Название шрифта',
+	'tabIndent': 'Табуляция',
+	"fullScreen": "Переключить полноэкранный режим",
+	"viewSource": "Показать исходный код HTML",
+	"print": "Печать",
+	"newPage": "Создать страницу",
+	/* Error messages */
+	'systemShortcut': 'Действие "${0}" можно выполнить в браузере только путем нажатия клавиш ${1}.'
+})
+
diff --git a/dijit/_editor/nls/sk/FontChoice.js b/dijit/_editor/nls/sk/FontChoice.js
index 9f8dc09..7bf92c8 100644
--- a/dijit/_editor/nls/sk/FontChoice.js
+++ b/dijit/_editor/nls/sk/FontChoice.js
@@ -1 +1,26 @@
-({"1":"xx-small","2":"x-small","formatBlock":"Formát","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Odsek","pre":"Predformátované","sans-serif":"sans-serif","fontName":"Písmo","h1":"Hlavička","h2":"Podhlavička","h3":"Pod-podhlavička","monospace":"monospace","fontSize":"Veľkosť","cursive":"cursive"})
\ No newline at end of file
+({
+	fontSize: "Veľkosť",
+	fontName: "Písmo",
+	formatBlock: "Formát",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursive",
+	fantasy: "fantasy",
+
+	p: "Odsek",
+	h1: "Hlavička",
+	h2: "Podhlavička",
+	h3: "Pod-podhlavička",
+	pre: "Predformátované",
+
+	1: "xx-small",
+	2: "x-small",
+	3: "small",
+	4: "medium",
+	5: "large",
+	6: "x-large",
+	7: "xx-large"
+})
+
diff --git a/dijit/_editor/nls/sk/LinkDialog.js b/dijit/_editor/nls/sk/LinkDialog.js
index 3b4d7a8..9c8e0ba 100644
--- a/dijit/_editor/nls/sk/LinkDialog.js
+++ b/dijit/_editor/nls/sk/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"Nastaviť","text":"Popis:","insertImageTitle":"Vlastnosti obrázku","url":"URL:","createLinkTitle":"Vlastnosti odkazu","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "Pripojiť vlastnosti",
+	insertImageTitle: "Vlastnosti obrázka ",
+	url: "URL:",
+	text: "Opis:",
+	target: "Cieľ:",
+	set: "Nastaviť",
+	currentWindow: "Aktuálne okno ",
+	parentWindow: "Rodičovské okno ",
+	topWindow: "Najvrchnejšie okno ",
+	newWindow: "Nové okno "
+})
+
diff --git a/dijit/_editor/nls/sk/commands.js b/dijit/_editor/nls/sk/commands.js
index 1118482..03105d5 100644
--- a/dijit/_editor/nls/sk/commands.js
+++ b/dijit/_editor/nls/sk/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Odstrániť formát","copy":"Kopírovať","paste":"Nalepiť","selectAll":"Vybrať všetko","insertOrderedList":"Číslovaný zoznam","insertTable":"Vložiť/upraviť tabuľku","underline":"Podčiarknuť","foreColor":"Farba popredia","htmlToggle":"Zdroj HTML","formatBlock":"Štýl odseku","insertHorizontalRule":"Horizontálna čiara","delete":"Vymazať","insertUnorderedList":"Zoznam s odrážkami","tableProp":"Vlastnosť tabuľky","insertImage":"Vložiť obrázok","superscript":"Horný index","subscr [...]
\ No newline at end of file
+({
+	'bold': 'Tučné písmo',
+	'copy': 'Kopírovať',
+	'cut': 'Vystrihnúť',
+	'delete': 'Vymazať',
+	'indent': 'Odsadiť',
+	'insertHorizontalRule': 'Horizontálna čiara',
+	'insertOrderedList': 'Číslovaný zoznam',
+	'insertUnorderedList': 'Zoznam s odrážkami',
+	'italic': 'Kurzíva',
+	'justifyCenter': 'Zarovnať na stred',
+	'justifyFull': 'Zarovnať podľa okraja',
+	'justifyLeft': 'Zarovnať doľava',
+	'justifyRight': 'Zarovnať doprava',
+	'outdent': 'Predsadiť',
+	'paste': 'Nalepiť',
+	'redo': 'Znova vykonať',
+	'removeFormat': 'Odstrániť formát',
+	'selectAll': 'Vybrať všetko',
+	'strikethrough': 'Prečiarknuť',
+	'subscript': 'Dolný index',
+	'superscript': 'Horný index',
+	'underline': 'Podčiarknuť',
+	'undo': 'Vrátiť späť',
+	'unlink': 'Odstrániť prepojenie',
+	'createLink': 'Vytvoriť prepojenie',
+	'toggleDir': 'Prepnúť smer',
+	'insertImage': 'Vložiť obrázok',
+	'insertTable': 'Vložiť/upraviť tabuľku',
+	'toggleTableBorder': 'Prepnúť rámček tabuľky',
+	'deleteTable': 'Vymazať tabuľku',
+	'tableProp': 'Vlastnosť tabuľky',
+	'htmlToggle': 'Zdroj HTML',
+	'foreColor': 'Farba popredia',
+	'hiliteColor': 'Farba pozadia',
+	'plainFormatBlock': 'Štýl odseku',
+	'formatBlock': 'Štýl odseku',
+	'fontSize': 'Veľkosť písma',
+	'fontName': 'Názov písma',
+	'tabIndent': 'Odsadenie tabulátora',
+	"fullScreen": "Zobraziť na celú obrazovku",
+	"viewSource": "Zobraziť zdrojový kód HTML ",
+	"print": "Tlačiť",
+	"newPage": "Nová stránka ",
+	/* Error messages */
+	'systemShortcut': 'Akcia "${0}" je vo vašom prehliadači dostupná len s použitím klávesovej skratky. Použite ${1}.'
+})
+
diff --git a/dijit/_editor/nls/sl/FontChoice.js b/dijit/_editor/nls/sl/FontChoice.js
index 3a7094c..ff41d9c 100644
--- a/dijit/_editor/nls/sl/FontChoice.js
+++ b/dijit/_editor/nls/sl/FontChoice.js
@@ -1 +1,26 @@
-({"1":"xx-majhno","2":"x-majhno","formatBlock":"Oblika","3":"majhno","4":"srednje","5":"veliko","6":"x-veliko","7":"xx-veliko","fantasy":"fantasy","serif":"serif","p":"Odstavek","pre":"Vnaprej oblikovano","sans-serif":"sans-serif","fontName":"Pisava","h1":"Naslov","h2":"Podnaslov","h3":"Pod podnaslov","monospace":"monospace","fontSize":"Velikost","cursive":"cursive"})
\ No newline at end of file
+({
+	fontSize: "Velikost",
+	fontName: "Pisava",
+	formatBlock: "Oblika",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursive",
+	fantasy: "fantasy",
+
+	p: "Odstavek",
+	h1: "Naslov",
+	h2: "Podnaslov",
+	h3: "Pod podnaslov",
+	pre: "Vnaprej oblikovano",
+
+	1: "xx-majhno",
+	2: "x-majhno",
+	3: "majhno",
+	4: "srednje",
+	5: "veliko",
+	6: "x-veliko",
+	7: "xx-veliko"
+})
+
diff --git a/dijit/_editor/nls/sl/LinkDialog.js b/dijit/_editor/nls/sl/LinkDialog.js
index 203a25d..26e536c 100644
--- a/dijit/_editor/nls/sl/LinkDialog.js
+++ b/dijit/_editor/nls/sl/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"Nastavi","text":"Opis:","insertImageTitle":"Lastnosti slike","url":"URL:","createLinkTitle":"Lastnosti povezave","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "Lastnosti povezave",
+	insertImageTitle: "Lastnosti slike",
+	url: "URL:",
+	text: "Opis:",
+	target: "Cilj:",
+	set: "Nastavi",
+	currentWindow: "Trenutno okno",
+	parentWindow: "Nadrejeno okno",
+	topWindow: "Najvišje okno",
+	newWindow: "Novo okno"
+})
+
diff --git a/dijit/_editor/nls/sl/commands.js b/dijit/_editor/nls/sl/commands.js
index 4fb720c..bbdded1 100644
--- a/dijit/_editor/nls/sl/commands.js
+++ b/dijit/_editor/nls/sl/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Odstrani obliko zapisa","copy":"Prekopiraj","paste":"Prilepi","selectAll":"Izberi vse","insertOrderedList":"Oštevilčen seznam","insertTable":"Vstavi/Uredi tabelo","underline":"Podčrtano","foreColor":"Barva ospredja","htmlToggle":"Izvor HTML","formatBlock":"Slog odstavka","insertHorizontalRule":"Horizontalno pravilo","delete":"Izbriši","insertUnorderedList":"Naštevni seznam","tableProp":"Lastnost tabele","insertImage":"Vstavi sliko","superscript":"Nadpisano","subscript": [...]
\ No newline at end of file
+({
+	'bold': 'Krepko',
+	'copy': 'Prekopiraj',
+	'cut': 'Izreži',
+	'delete': 'Izbriši',
+	'indent': 'Zamik',
+	'insertHorizontalRule': 'Vodoravno ravnilo',
+	'insertOrderedList': 'Oštevilčen seznam',
+	'insertUnorderedList': 'Naštevni seznam',
+	'italic': 'Ležeče',
+	'justifyCenter': 'Poravnaj na sredino',
+	'justifyFull': 'Obojestranska poravnava',
+	'justifyLeft': 'Poravnaj levo',
+	'justifyRight': 'Poravnaj desno',
+	'outdent': 'Viseč odstavek',
+	'paste': 'Prilepi',
+	'redo': 'Znova uveljavi',
+	'removeFormat': 'Odstrani obliko zapisa',
+	'selectAll': 'Izberi vse',
+	'strikethrough': 'Prečrtano',
+	'subscript': 'Podpisano',
+	'superscript': 'Nadpisano',
+	'underline': 'Podčrtano',
+	'undo': 'Razveljavi',
+	'unlink': 'Odstrani povezavo',
+	'createLink': 'Ustvari povezavo',
+	'toggleDir': 'Preklopi na usmeritev',
+	'insertImage': 'Vstavi sliko',
+	'insertTable': 'Vstavi/uredi tabelo',
+	'toggleTableBorder': 'Preklopi na rob tabele',
+	'deleteTable': 'Izbriši tabelo',
+	'tableProp': 'Lastnost tabele',
+	'htmlToggle': 'Izvorna koda HTML',
+	'foreColor': 'Barva ospredja',
+	'hiliteColor': 'Barva ozadja',
+	'plainFormatBlock': 'Slog odstavka',
+	'formatBlock': 'Slog odstavka',
+	'fontSize': 'Velikost pisave',
+	'fontName': 'Ime pisave',
+	'tabIndent': 'Zamik tabulatorja',
+	"fullScreen": "Preklopi na celozaslonski način",
+	"viewSource": "Prikaži izvorno kodo HTML",
+	"print": "Natisni",
+	"newPage": "Nova stran",
+	/* Error messages */
+	'systemShortcut': 'Dejanje "${0}" lahko v vašem brskalniku uporabite samo z bližnjico na tipkovnici. Uporabite ${1}.'
+})
+
diff --git a/dijit/_editor/nls/sv/FontChoice.js b/dijit/_editor/nls/sv/FontChoice.js
index 106f020..cbfc0f2 100644
--- a/dijit/_editor/nls/sv/FontChoice.js
+++ b/dijit/_editor/nls/sv/FontChoice.js
@@ -1 +1,25 @@
-({"1":"mycket, mycket litet","2":"mycket litet","formatBlock":"Format","3":"litet","4":"medelstort","5":"stort","6":"extra stort","7":"extra extra stort","fantasy":"fantasy","serif":"serif","p":"Stycke","pre":"Förformaterat","sans-serif":"sans-serif","fontName":"Teckensnitt","h1":"Rubrik","h2":"Underrubrik","h3":"Underunderrubrik","monospace":"monospace","fontSize":"Storlek","cursive":"kursivt"})
\ No newline at end of file
+({
+	fontSize: "Storlek",
+	fontName: "Teckensnitt",
+	formatBlock: "Format",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "kursivt",
+	fantasy: "fantasy",
+
+	p: "Stycke",
+	h1: "Rubrik",
+	h2: "Underrubrik",
+	h3: "Underunderrubrik",
+	pre: "Förformaterat",
+
+	1: "mycket, mycket litet",
+	2: "mycket litet",
+	3: "litet",
+	4: "medelstort",
+	5: "stort",
+	6: "extra stort",
+	7: "extra extra stort"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/sv/LinkDialog.js b/dijit/_editor/nls/sv/LinkDialog.js
index ed6c3da..8ac889d 100644
--- a/dijit/_editor/nls/sv/LinkDialog.js
+++ b/dijit/_editor/nls/sv/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"Ange","text":"Beskrivning:","insertImageTitle":"Bildegenskaper","url":"URL-adress:","createLinkTitle":"Länkegenskaper","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "Länkegenskaper",
+	insertImageTitle: "Bildegenskaper",
+	url: "URL-adress:",
+	text: "Beskrivning:",
+	target: "Mål:",
+	set: "Ange",
+	currentWindow: "aktuellt fönster",
+	parentWindow: "överordnat fönster",
+	topWindow: "översta fönstret",
+	newWindow: "nytt fönster"
+})
+
diff --git a/dijit/_editor/nls/sv/commands.js b/dijit/_editor/nls/sv/commands.js
index df5e091..5bca9c7 100644
--- a/dijit/_editor/nls/sv/commands.js
+++ b/dijit/_editor/nls/sv/commands.js
@@ -1 +1,50 @@
-({"removeFormat":"Ta bort format","copy":"Kopiera","paste":"Klistra in","selectAll":"Markera allt","insertOrderedList":"Numrerad lista","insertTable":"Infoga/redigera tabell","underline":"Understrykning","foreColor":"Förgrundsfärg","htmlToggle":"HTML-källkod","formatBlock":"Styckeformat","insertHorizontalRule":"Horisontell linjal","delete":"Ta bort","insertUnorderedList":"Punktlista","tableProp":"Tabellegenskap","insertImage":"Infoga bild","superscript":"Upphöjt","subscript":"Nedsänkt"," [...]
\ No newline at end of file
+({
+	'bold': 'Fetstil',
+	'copy': 'Kopiera',
+	'cut': 'Klipp ut',
+	'delete': 'Ta bort',
+	'indent': 'Indrag',
+	'insertHorizontalRule': 'Horisontell linjal',
+	'insertOrderedList': 'Numrerad lista',
+	'insertUnorderedList': 'Punktlista',
+	'italic': 'Kursiv',
+	'justifyCenter': 'Centrera',
+	'justifyFull': 'Marginaljustera',
+	'justifyLeft': 'Vänsterjustera',
+	'justifyRight': 'Högerjustera',
+	'outdent': 'Utdrag',
+	'paste': 'Klistra in',
+	'redo': 'Gör om',
+	'removeFormat': 'Ta bort format',
+	'selectAll': 'Markera allt',
+	'strikethrough': 'Genomstruken',
+	'subscript': 'Nedsänkt',
+	'superscript': 'Upphöjt',
+	'underline': 'Understrykning',
+	'undo': 'Ångra',
+	'unlink': 'Ta bort länk',
+	'createLink': 'Skapa länk',
+	'toggleDir': 'Växla riktning',
+	'insertImage': 'Infoga bild',
+	'insertTable': 'Infoga/redigera tabell',
+	'toggleTableBorder': 'Aktivera/avaktivera tabellram',
+	'deleteTable': 'Ta bort tabell',
+	'tableProp': 'Tabellegenskap',
+	'htmlToggle': 'HTML-källkod',
+	'foreColor': 'Förgrundsfärg',
+	'hiliteColor': 'Bakgrundsfärg',
+	'plainFormatBlock': 'Styckeformat',
+	'formatBlock': 'Styckeformat',
+	'fontSize': 'Teckenstorlek',
+	'fontName': 'Teckensnittsnamn',
+	'tabIndent': 'Tabbindrag',
+	"fullScreen": "Växla helskärm",
+	"viewSource": "Visa HTML-kod",
+	"print": "Skriv ut",
+	"newPage": "Ny sida",
+	/* Error messages */
+	'systemShortcut': 'Åtgärden "${0}" är endast tillgänglig i webbläsaren med hjälp av ett kortkommando. Använd ${1}.',
+	'ctrlKey':'Ctrl+${0}',
+	'appleKey':'\u2318+${0}' // "command" or open-apple key on Macintosh
+})
+
diff --git a/dijit/_editor/nls/th/FontChoice.js b/dijit/_editor/nls/th/FontChoice.js
index 63613a4..e90d262 100644
--- a/dijit/_editor/nls/th/FontChoice.js
+++ b/dijit/_editor/nls/th/FontChoice.js
@@ -1 +1,26 @@
-({"1":"xx-small","2":"x-small","formatBlock":"รูปแบบ","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"ย่อหน้า","pre":"การกำหนดรูปแบบล่วงหน้า","sans-serif":"sans-serif","fontName":"ฟอนต์","h1":"ส่วนหัว","h2":"ส่วนหัวย่อย","h3":"ส่วนย่อยของส่วนหัวย่อย","monospace":"monospace","fontSize":"ขนาด","cursive":"cursive"})
\ No newline at end of file
+({
+	fontSize: "ขนาด",
+	fontName: "ฟอนต์",
+	formatBlock: "รูปแบบ",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "monospace",
+	cursive: "cursive",
+	fantasy: "fantasy",
+
+	p: "ย่อหน้า",
+	h1: "ส่วนหัว",
+	h2: "ส่วนหัวย่อย",
+	h3: "ส่วนย่อยของส่วนหัวย่อย",
+	pre: "การกำหนดรูปแบบล่วงหน้า",
+
+	1: "xx-small",
+	2: "x-small",
+	3: "small",
+	4: "medium",
+	5: "large",
+	6: "x-large",
+	7: "xx-large"
+})
+
diff --git a/dijit/_editor/nls/th/LinkDialog.js b/dijit/_editor/nls/th/LinkDialog.js
index b5ce3f8..0e29ed5 100644
--- a/dijit/_editor/nls/th/LinkDialog.js
+++ b/dijit/_editor/nls/th/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"ตั้งค่า","text":"รายละเอียด","insertImageTitle":"คุณสมบัติอิมเมจ","url":"URL:","createLinkTitle":"คุณสมบัติลิงก์","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "คุณสมบัติลิงก์",
+	insertImageTitle: "คุณสมบัติอิมเมจ",
+	url: "URL:",
+	text: "รายละเอียด",
+	target: "เป้าหมาย:",
+	set: "ตั้งค่า",
+	currentWindow: "หน้าต่างปัจจุบัน",
+	parentWindow: "หน้าต่างหลัก",
+	topWindow: "หน้าต่างบนสุด",
+	newWindow: "หน้าต่างใหม่"
+})
+
diff --git a/dijit/_editor/nls/th/commands.js b/dijit/_editor/nls/th/commands.js
index ec513a5..e2cee6f 100644
--- a/dijit/_editor/nls/th/commands.js
+++ b/dijit/_editor/nls/th/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"ลบรูปแบบออก","copy":"คัดลอก","paste":"วาง","selectAll":"เลือกทั้งหมด","insertOrderedList":"ลำดับเลข","insertTable":"แทรก/แก้ไข ตาราง","underline":"ขีดเส้นใต้","foreColor":"สีพื้นหน้า","htmlToggle":"ซอร์ส HTML","formatBlock":"ลักษณะย่อหน้า","insertHorizontalRule":"ไม้บรรทัดแนวนอน","delete":"ลบ","insertUnorderedList":"หัวข้อย่อย","tableProp":"คุณสมบัติตาราง","insertImage":"แทรกอิมเมจ","superscript":"ตัวยก","subscript":"ตัวห้อย","createLink":"สร้างลิงก์","undo":"เลิกทำ","i [...]
\ No newline at end of file
+({
+	'bold': 'ตัวหนา',
+	'copy': 'คัดลอก',
+	'cut': 'ตัด',
+	'delete': 'ลบ',
+	'indent': 'เพิ่มการเยื้อง',
+	'insertHorizontalRule': 'ไม้บรรทัดแนวนอน',
+	'insertOrderedList': 'ลำดับเลข',
+	'insertUnorderedList': 'หัวข้อย่อย',
+	'italic': 'ตัวเอียง',
+	'justifyCenter': 'จัดกึ่งกลาง',
+	'justifyFull': 'จัดชิดขอบ',
+	'justifyLeft': 'จัดชิดซ้าย',
+	'justifyRight': 'จัดชิดขวา',
+	'outdent': 'ลดการเยื้อง',
+	'paste': 'วาง',
+	'redo': 'ทำซ้ำ',
+	'removeFormat': 'ลบรูปแบบออก',
+	'selectAll': 'เลือกทั้งหมด',
+	'strikethrough': 'ขีดทับ',
+	'subscript': 'ตัวห้อย',
+	'superscript': 'ตัวยก',
+	'underline': 'ขีดเส้นใต้',
+	'undo': 'เลิกทำ',
+	'unlink': 'ลบลิงก์ออก',
+	'createLink': 'สร้างลิงก์',
+	'toggleDir': 'สลับทิศทาง',
+	'insertImage': 'แทรกอิมเมจ',
+	'insertTable': 'แทรก/แก้ไขตาราง',
+	'toggleTableBorder': 'สลับเส้นขอบตาราง',
+	'deleteTable': 'ลบตาราง',
+	'tableProp': 'คุณสมบัติตาราง',
+	'htmlToggle': 'ซอร์ส HTML',
+	'foreColor': 'สีพื้นหน้า',
+	'hiliteColor': 'สีพื้นหลัง',
+	'plainFormatBlock': 'ลักษณะย่อหน้า',
+	'formatBlock': 'ลักษณะย่อหน้า',
+	'fontSize': 'ขนาดฟอนต์',
+	'fontName': 'ชื่อฟอนต์',
+	'tabIndent': 'เยื้องแท็บ',
+	"fullScreen": "สลับจอภาพแบบเต็ม",
+	"viewSource": "ดูซอร์ส HTML",
+	"print": "พิมพ์",
+	"newPage": "หน้าใหม่",
+	/* Error messages */
+	'systemShortcut': 'การดำเนินการ"${0}" ใช้งานได้เฉพาะกับเบราว์เซอร์ของคุณโดยใช้แป้นพิมพ์ลัด ใช้ ${1}'
+})
+
diff --git a/dijit/_editor/nls/tr/FontChoice.js b/dijit/_editor/nls/tr/FontChoice.js
index d2ca7c4..0860cdc 100644
--- a/dijit/_editor/nls/tr/FontChoice.js
+++ b/dijit/_editor/nls/tr/FontChoice.js
@@ -1 +1,25 @@
-({"1":"xx-küçük","2":"x-küçük","formatBlock":"Biçim","3":"küçük","4":"orta","5":"büyük","6":"x-büyük","7":"xx-büyük","fantasy":"fantazi","serif":"serif","p":"Paragraf","pre":"Önceden Biçimlendirilmiş","sans-serif":"sans-serif","fontName":"Yazı Tipi","h1":"Başlık","h2":"Alt Başlık","h3":"Alt Alt Başlık","monospace":"tek aralıklı","fontSize":"Boyut","cursive":"el yazısı"})
\ No newline at end of file
+({
+	fontSize: "Boyut",
+	fontName: "Yazı Tipi",
+	formatBlock: "Biçim",
+
+	serif: "serif",
+	"sans-serif": "sans-serif",
+	monospace: "tek aralıklı",
+	cursive: "el yazısı",
+	fantasy: "fantazi",
+
+	p: "Paragraf",
+	h1: "Başlık",
+	h2: "Alt Başlık",
+	h3: "Alt Alt Başlık",
+	pre: "Önceden Biçimlendirilmiş",
+
+	1: "xx-küçük",
+	2: "x-küçük",
+	3: "küçük",
+	4: "orta",
+	5: "büyük",
+	6: "x-büyük",
+	7: "xx-büyük"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/tr/LinkDialog.js b/dijit/_editor/nls/tr/LinkDialog.js
index 2a2491a..b10cff6 100644
--- a/dijit/_editor/nls/tr/LinkDialog.js
+++ b/dijit/_editor/nls/tr/LinkDialog.js
@@ -1 +1,13 @@
-({"set":"Ayarla","text":"Açıklama:","insertImageTitle":"Resim Özellikleri","url":"URL:","createLinkTitle":"Bağlantı Özellikleri","newWindow":"New Window","topWindow":"Topmost Window","target":"Target:","parentWindow":"Parent Window","currentWindow":"Current Window"})
\ No newline at end of file
+({
+	createLinkTitle: "Bağlantı Özellikleri",
+	insertImageTitle: "Resim Özellikleri",
+	url: "URL:",
+	text: "Açıklama:",
+	target: "Hedef:",
+	set: "Ayarla",
+	currentWindow: "Geçerli Pencere",
+	parentWindow: "Üst Pencere",
+	topWindow: "En Üst Pencere",
+	newWindow: "Yeni Pencere"
+})
+
diff --git a/dijit/_editor/nls/tr/commands.js b/dijit/_editor/nls/tr/commands.js
index 99c966c..3423ed8 100644
--- a/dijit/_editor/nls/tr/commands.js
+++ b/dijit/_editor/nls/tr/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"Biçimi Kaldır","copy":"Kopyala","paste":"Yapıştır","selectAll":"Tümünü Seç","insertOrderedList":"Numaralı Liste","insertTable":"Tablo Ekle/Düzenle","underline":"Altı Çizili","foreColor":"Ön Plan Rengi","htmlToggle":"HTML Kaynağı","formatBlock":"Paragraf Stili","insertHorizontalRule":"Yatay Kural","delete":"Sil","insertUnorderedList":"Madde İşaretli Liste","tableProp":"Tablo Özelliği","insertImage":"Resim Ekle","superscript":"Üst Simge","subscript":"Alt Simge","createLin [...]
\ No newline at end of file
+({
+	'bold': 'Kalın',
+	'copy': 'Kopyala',
+	'cut': 'Kes',
+	'delete': 'Sil',
+	'indent': 'Girinti',
+	'insertHorizontalRule': 'Yatay Kural',
+	'insertOrderedList': 'Numaralı Liste',
+	'insertUnorderedList': 'Madde İşaretli Liste',
+	'italic': 'İtalik',
+	'justifyCenter': 'Ortaya Hizala',
+	'justifyFull': 'Yasla',
+	'justifyLeft': 'Sola Hizala',
+	'justifyRight': 'Sağa Hizala',
+	'outdent': 'Çıkıntı',
+	'paste': 'Yapıştır',
+	'redo': 'Yinele',
+	'removeFormat': 'Biçimi Kaldır',
+	'selectAll': 'Tümünü Seç',
+	'strikethrough': 'Üstü Çizili',
+	'subscript': 'Alt Simge',
+	'superscript': 'Üst Simge',
+	'underline': 'Altı Çizili',
+	'undo': 'Geri Al',
+	'unlink': 'Bağlantıyı Kaldır',
+	'createLink': 'Bağlantı Oluştur',
+	'toggleDir': 'Yönü Değiştir',
+	'insertImage': 'Resim Ekle',
+	'insertTable': 'Tablo Ekle/Düzenle',
+	'toggleTableBorder': 'Tablo Kenarlığını Göster/Gizle',
+	'deleteTable': 'Tabloyu Sil',
+	'tableProp': 'Tablo Özelliği',
+	'htmlToggle': 'HTML Kaynağı',
+	'foreColor': 'Ön Plan Rengi',
+	'hiliteColor': 'Arka Plan Rengi',
+	'plainFormatBlock': 'Paragraf Stili',
+	'formatBlock': 'Paragraf Stili',
+	'fontSize': 'Yazı Tipi Boyutu',
+	'fontName': 'Yazı Tipi Adı',
+	'tabIndent': 'Sekme Girintisi',
+	"fullScreen": "Tam Ekranı Aç/Kapat",
+	"viewSource": "HTML Kaynağını Görüntüle",
+	"print": "Yazdır",
+	"newPage": "Yeni Sayfa",
+	/* Error messages */
+	'systemShortcut': '"${0}" işlemi yalnızca tarayıcınızda bir klavye kısayoluyla birlikte kullanılabilir. Şunu kullanın: ${1}.'
+})
+
diff --git a/dijit/_editor/nls/zh-tw/FontChoice.js b/dijit/_editor/nls/zh-tw/FontChoice.js
index d32e163..e77c569 100644
--- a/dijit/_editor/nls/zh-tw/FontChoice.js
+++ b/dijit/_editor/nls/zh-tw/FontChoice.js
@@ -1 +1,25 @@
-({"1":"最小","2":"較小","formatBlock":"格式","3":"小","4":"中","5":"大","6":"較大","7":"最大","fantasy":"Fantasy","serif":"新細明體","p":"段落","pre":"預先格式化","sans-serif":"新細明體","fontName":"字型","h1":"標題","h2":"子標題","h3":"次子標題","monospace":"等寬","fontSize":"大小","cursive":"Cursive"})
\ No newline at end of file
+({
+	fontSize: "大小",
+	fontName: "字型",
+	formatBlock: "格式",
+
+	serif: "新細明體",
+	"sans-serif": "新細明體",
+	monospace: "等寬",
+	cursive: "Cursive",
+	fantasy: "Fantasy",
+
+	p: "段落",
+	h1: "標題",
+	h2: "子標題",
+	h3: "次子標題",
+	pre: "預先格式化",
+
+	1: "最小",
+	2: "較小",
+	3: "小",
+	4: "中",
+	5: "大",
+	6: "較大",
+	7: "最大"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/zh-tw/LinkDialog.js b/dijit/_editor/nls/zh-tw/LinkDialog.js
index a639ac7..d766166 100644
--- a/dijit/_editor/nls/zh-tw/LinkDialog.js
+++ b/dijit/_editor/nls/zh-tw/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"說明:","insertImageTitle":"影像內容","set":"設定","newWindow":"新視窗","topWindow":"最上層視窗","target":"目標:","createLinkTitle":"鏈結內容","parentWindow":"上層視窗","currentWindow":"現行視窗","url":"URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "鏈結內容",
+	insertImageTitle: "影像內容",
+	url: "URL:",
+	text: "說明:",
+	target: "目標:",
+	set: "設定",
+	currentWindow: "現行視窗",
+	parentWindow: "上層視窗",
+	topWindow: "最上面的視窗",
+	newWindow: "新視窗"
+})
+
diff --git a/dijit/_editor/nls/zh-tw/commands.js b/dijit/_editor/nls/zh-tw/commands.js
index d72dc4e..7e2ba3d 100644
--- a/dijit/_editor/nls/zh-tw/commands.js
+++ b/dijit/_editor/nls/zh-tw/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"移除格式","copy":"複製","paste":"貼上","selectAll":"全選","insertOrderedList":"編號清單","insertTable":"插入/編輯表格","print":"列印","underline":"底線","foreColor":"前景顏色","htmlToggle":"HTML 原始檔","formatBlock":"段落樣式","newPage":"新建頁面","insertHorizontalRule":"水平尺規","delete":"刪除","insertUnorderedList":"項目符號清單","tableProp":"表格內容","insertImage":"插入影像","superscript":"上標","subscript":"下標","createLink":"建立鏈結","undo":"復原","fullScreen":"切換全螢幕","italic":"斜體","fontName":"字型名稱","justifyLeft":"靠左對齊","unlink [...]
\ No newline at end of file
+({
+	'bold': '粗體',
+	'copy': '複製',
+	'cut': '剪下',
+	'delete': '刪除',
+	'indent': '縮排',
+	'insertHorizontalRule': '水平尺規',
+	'insertOrderedList': '編號清單',
+	'insertUnorderedList': '項目符號清單',
+	'italic': '斜體',
+	'justifyCenter': '置中對齊',
+	'justifyFull': '對齊',
+	'justifyLeft': '靠左對齊',
+	'justifyRight': '靠右對齊',
+	'outdent': '凸排',
+	'paste': '貼上',
+	'redo': '重做',
+	'removeFormat': '移除格式',
+	'selectAll': '全選',
+	'strikethrough': '加刪除線',
+	'subscript': '下標',
+	'superscript': '上標',
+	'underline': '底線',
+	'undo': '復原',
+	'unlink': '移除鏈結',
+	'createLink': '建立鏈結',
+	'toggleDir': '切換方向',
+	'insertImage': '插入影像',
+	'insertTable': '插入/編輯表格',
+	'toggleTableBorder': '切換表格邊框',
+	'deleteTable': '刪除表格',
+	'tableProp': '表格內容',
+	'htmlToggle': 'HTML 原始檔',
+	'foreColor': '前景顏色',
+	'hiliteColor': '背景顏色',
+	'plainFormatBlock': '段落樣式',
+	'formatBlock': '段落樣式',
+	'fontSize': '字型大小',
+	'fontName': '字型名稱',
+	'tabIndent': '定位點縮排',
+	"fullScreen": "切換全螢幕",
+	"viewSource": "檢視 HTML 原始檔",
+	"print": "列印",
+	"newPage": "新建頁面",
+	/* Error messages */
+	'systemShortcut': '"${0}" 動作只能在瀏覽器中透過使用鍵盤快速鍵來使用。請使用 ${1}。'
+})
+
diff --git a/dijit/_editor/nls/zh/FontChoice.js b/dijit/_editor/nls/zh/FontChoice.js
index c5d8510..cc056a7 100644
--- a/dijit/_editor/nls/zh/FontChoice.js
+++ b/dijit/_editor/nls/zh/FontChoice.js
@@ -1 +1,25 @@
-({"1":"XXS 号","2":"XS 号","formatBlock":"格式","3":"S 号","4":"M 号","5":"L 号","6":"XL 号","7":"XXL 号","fantasy":"虚线","serif":"有衬线","p":"段落","pre":"预设有格式的","sans-serif":"无衬线","fontName":"字体","h1":"标题","h2":"子标题","h3":"二级子标题","monospace":"等宽字体","fontSize":"大小","cursive":"草书"})
\ No newline at end of file
+({
+	fontSize: "大小",
+	fontName: "字体",
+	formatBlock: "格式",
+
+	serif: "有衬线",
+	"sans-serif": "无衬线",
+	monospace: "等宽字体",
+	cursive: "草书",
+	fantasy: "虚线",
+
+	p: "段落",
+	h1: "标题",
+	h2: "子标题",
+	h3: "二级子标题",
+	pre: "预设有格式的",
+
+	1: "XXS 号",
+	2: "XS 号",
+	3: "S 号",
+	4: "M 号",
+	5: "L 号",
+	6: "XL 号",
+	7: "XXL 号"
+})
\ No newline at end of file
diff --git a/dijit/_editor/nls/zh/LinkDialog.js b/dijit/_editor/nls/zh/LinkDialog.js
index da4c500..bb24f31 100644
--- a/dijit/_editor/nls/zh/LinkDialog.js
+++ b/dijit/_editor/nls/zh/LinkDialog.js
@@ -1 +1,13 @@
-({"text":"描述:","insertImageTitle":"图像属性","set":"设置","newWindow":"新窗口","topWindow":"最顶部窗口","target":"目标:","createLinkTitle":"链接属性","parentWindow":"父窗口","currentWindow":"当前窗口","url":"URL:"})
\ No newline at end of file
+({
+	createLinkTitle: "链接属性",
+	insertImageTitle: "图像属性",
+	url: "URL:",
+	text: "描述:",
+	target: "目标:",
+	set: "设置",
+	currentWindow: "当前窗口",
+	parentWindow: "父窗口",
+	topWindow: "最顶部窗口",
+	newWindow: "新窗口"
+})
+
diff --git a/dijit/_editor/nls/zh/commands.js b/dijit/_editor/nls/zh/commands.js
index 43d29c8..1618b6d 100644
--- a/dijit/_editor/nls/zh/commands.js
+++ b/dijit/_editor/nls/zh/commands.js
@@ -1 +1,48 @@
-({"removeFormat":"除去格式","copy":"复制","paste":"粘贴","selectAll":"全选","insertOrderedList":"编号列表","insertTable":"插入/编辑表","print":"打印","underline":"下划线","foreColor":"前景色","htmlToggle":"HTML 源代码","formatBlock":"段落样式","newPage":"新建页面","insertHorizontalRule":"水平线","delete":"删除","insertUnorderedList":"符号列表","tableProp":"表属性","insertImage":"插入图像","superscript":"上标","subscript":"下标","createLink":"创建链接","undo":"撤销","fullScreen":"切换全屏","italic":"斜体","fontName":"字体名称","justifyLeft":"左对齐","unlink":"除去链接 [...]
\ No newline at end of file
+({
+	'bold': '粗体',
+	'copy': '复制',
+	'cut': '剪切',
+	'delete': '删除',
+	'indent': '增加缩进',
+	'insertHorizontalRule': '水平线',
+	'insertOrderedList': '编号列表',
+	'insertUnorderedList': '符号列表',
+	'italic': '斜体',
+	'justifyCenter': '居中',
+	'justifyFull': '对齐',
+	'justifyLeft': '左对齐',
+	'justifyRight': '右对齐',
+	'outdent': '减少缩进',
+	'paste': '粘贴',
+	'redo': '重做',
+	'removeFormat': '除去格式',
+	'selectAll': '全选',
+	'strikethrough': '删除线',
+	'subscript': '下标',
+	'superscript': '上标',
+	'underline': '下划线',
+	'undo': '撤销',
+	'unlink': '除去链接',
+	'createLink': '创建链接',
+	'toggleDir': '固定方向',
+	'insertImage': '插入图像',
+	'insertTable': '插入/编辑表',
+	'toggleTableBorder': '切换表边框',
+	'deleteTable': '删除表',
+	'tableProp': '表属性',
+	'htmlToggle': 'HTML 源代码',
+	'foreColor': '前景色',
+	'hiliteColor': '背景色',
+	'plainFormatBlock': '段落样式',
+	'formatBlock': '段落样式',
+	'fontSize': '字体大小',
+	'fontName': '字体名称',
+	'tabIndent': '制表符缩进',
+	"fullScreen": "切换全屏幕",
+	"viewSource": "查看 HTML 源代码",
+	"print": "打印",
+	"newPage": "新建页面",
+	/* Error messages */
+	'systemShortcut': '只能在浏览器中通过键盘快捷方式执行“${0}”操作。使用 ${1}。'
+})
+
diff --git a/dijit/_editor/plugins/AlwaysShowToolbar.js b/dijit/_editor/plugins/AlwaysShowToolbar.js
index a86d9ff..0a5d1a6 100644
--- a/dijit/_editor/plugins/AlwaysShowToolbar.js
+++ b/dijit/_editor/plugins/AlwaysShowToolbar.js
@@ -1,119 +1,177 @@
-/*
-	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
-*/
+dojo.provide("dijit._editor.plugins.AlwaysShowToolbar");
 
+dojo.declare("dijit._editor.plugins.AlwaysShowToolbar", dijit._editor._Plugin,
+	{
+	// summary:
+	//		This plugin is required for Editors in auto-expand mode.
+	//		It handles the auto-expansion as the user adds/deletes text,
+	//		and keeps the editor's toolbar visible even when the top of the editor
+	//		has scrolled off the top of the viewport (usually when editing a long
+	//		document).
+	// description:
+	//		Specify this in extraPlugins (or plugins) parameter and also set
+	//		height to "".
+	// example:
+	//	|	<div dojoType="dijit.Editor" height=""
+	//	|	extraPlugins="['dijit._editor.plugins.AlwaysShowToolbar']">
 
-if(!dojo._hasResource["dijit._editor.plugins.AlwaysShowToolbar"]){
-dojo._hasResource["dijit._editor.plugins.AlwaysShowToolbar"]=true;
-dojo.provide("dijit._editor.plugins.AlwaysShowToolbar");
-dojo.declare("dijit._editor.plugins.AlwaysShowToolbar",dijit._editor._Plugin,{_handleScroll:true,setEditor:function(e){
-if(!e.iframe){
-return;
-}
-this.editor=e;
-e.onLoadDeferred.addCallback(dojo.hitch(this,this.enable));
-},enable:function(d){
-this._updateHeight();
-this.connect(window,"onscroll","globalOnScrollHandler");
-this.connect(this.editor,"onNormalizedDisplayChanged","_updateHeight");
-return d;
-},_updateHeight:function(){
-var e=this.editor;
-if(!e.isLoaded){
-return;
-}
-if(e.height){
-return;
-}
-var _1=dojo.marginBox(e.editNode).h;
-if(dojo.isOpera){
-_1=e.editNode.scrollHeight;
-}
-if(!_1){
-_1=dojo.marginBox(e.document.body).h;
-}
-if(_1==0){
-return;
-}
-if(dojo.isIE<=7&&this.editor.minHeight){
-var _2=parseInt(this.editor.minHeight);
-if(_1<_2){
-_1=_2;
-}
-}
-if(_1!=this._lastHeight){
-this._lastHeight=_1;
-dojo.marginBox(e.iframe,{h:this._lastHeight});
-}
-},_lastHeight:0,globalOnScrollHandler:function(){
-var _3=dojo.isIE<7;
-if(!this._handleScroll){
-return;
-}
-var _4=this.editor.toolbar.domNode;
-var db=dojo.body;
-if(!this._scrollSetUp){
-this._scrollSetUp=true;
-this._scrollThreshold=dojo.position(_4,true).y;
-}
-var _5=dojo._docScroll().y;
-var s=_4.style;
-if(_5>this._scrollThreshold&&_5<this._scrollThreshold+this._lastHeight){
-if(!this._fixEnabled){
-var _6=dojo.marginBox(_4);
-this.editor.iframe.style.marginTop=_6.h+"px";
-if(_3){
-s.left=dojo.position(_4).x;
-if(_4.previousSibling){
-this._IEOriginalPos=["after",_4.previousSibling];
-}else{
-if(_4.nextSibling){
-this._IEOriginalPos=["before",_4.nextSibling];
-}else{
-this._IEOriginalPos=["last",_4.parentNode];
-}
-}
-dojo.body().appendChild(_4);
-dojo.addClass(_4,"dijitIEFixedToolbar");
-}else{
-s.position="fixed";
-s.top="0px";
-}
-dojo.marginBox(_4,{w:_6.w});
-s.zIndex=2000;
-this._fixEnabled=true;
-}
-var _7=(this.height)?parseInt(this.editor.height):this.editor._lastHeight;
-s.display=(_5>this._scrollThreshold+_7)?"none":"";
-}else{
-if(this._fixEnabled){
-this.editor.iframe.style.marginTop="";
-s.position="";
-s.top="";
-s.zIndex="";
-s.display="";
-if(_3){
-s.left="";
-dojo.removeClass(_4,"dijitIEFixedToolbar");
-if(this._IEOriginalPos){
-dojo.place(_4,this._IEOriginalPos[1],this._IEOriginalPos[0]);
-this._IEOriginalPos=null;
-}else{
-dojo.place(_4,this.editor.iframe,"before");
-}
-}
-s.width="";
-this._fixEnabled=false;
-}
-}
-},destroy:function(){
-this._IEOriginalPos=null;
-this._handleScroll=false;
-dojo.forEach(this._connects,dojo.disconnect);
-if(dojo.isIE<7){
-dojo.removeClass(this.editor.toolbar.domNode,"dijitIEFixedToolbar");
-}
-}});
-}
+	// _handleScroll: Boolean
+	//		Enables/disables the handler for scroll events
+	_handleScroll: true,
+
+	setEditor: function(e){
+		// Overrides _Plugin.setEditor().
+		if(!e.iframe){
+			console.log('Port AlwaysShowToolbar plugin to work with Editor without iframe');
+			return;
+		}
+
+		this.editor = e;
+
+		e.onLoadDeferred.addCallback(dojo.hitch(this, this.enable));
+	},
+
+	enable: function(d){
+		// summary:
+		//		Enable plugin.  Called when Editor has finished initializing.
+		// tags:
+		//		private
+
+		this._updateHeight();
+		this.connect(window, 'onscroll', "globalOnScrollHandler");
+		this.connect(this.editor, 'onNormalizedDisplayChanged', "_updateHeight");
+		return d;
+	},
+
+	_updateHeight: function(){
+		// summary:
+		//		Updates the height of the editor area to fit the contents.
+		var e = this.editor;
+		if(!e.isLoaded){ return; }
+		if(e.height){ return; }
+
+		var height = dojo.marginBox(e.editNode).h;
+		if(dojo.isOpera){
+			height = e.editNode.scrollHeight;
+		}
+		// console.debug('height',height);
+		// alert(this.editNode);
+
+		//height maybe zero in some cases even though the content is not empty,
+		//we try the height of body instead
+		if(!height){
+			height = dojo.marginBox(e.document.body).h;
+		}
+
+		if(height == 0){
+			console.debug("Can not figure out the height of the editing area!");
+			return; //prevent setting height to 0
+		}
+		if(dojo.isIE <= 7 && this.editor.minHeight){
+			var min = parseInt(this.editor.minHeight);
+			if(height < min){ height = min; }
+		}
+		if(height != this._lastHeight){
+			this._lastHeight = height;
+			// this.editorObject.style.height = this._lastHeight + "px";
+			dojo.marginBox(e.iframe, { h: this._lastHeight });
+		}
+	},
+
+	// _lastHeight: Integer
+	//		Height in px of the editor at the last time we did sizing
+	_lastHeight: 0,
+
+	globalOnScrollHandler: function(){
+		// summary:
+		//		Handler for scroll events that bubbled up to <html>
+		// tags:
+		//		private
+
+		var isIE6 = dojo.isIE < 7;
+		if(!this._handleScroll){ return; }
+		var tdn = this.editor.header;
+		var db = dojo.body;
+
+		if(!this._scrollSetUp){
+			this._scrollSetUp = true;
+			this._scrollThreshold = dojo.position(tdn, true).y;
+//			console.log("threshold:", this._scrollThreshold);
+			//what's this for?? comment out for now
+//			if((isIE6)&&(db)&&(dojo.style(db, "backgroundIimage")=="none")){
+//				db.style.backgroundImage = "url(" + dojo.uri.moduleUri("dijit", "templates/blank.gif") + ")";
+//				db.style.backgroundAttachment = "fixed";
+//			}
+		}
+
+		var scrollPos = dojo._docScroll().y;
+		var s = tdn.style;
+
+		if(scrollPos > this._scrollThreshold && scrollPos < this._scrollThreshold+this._lastHeight){
+			// dojo.debug(scrollPos);
+			if(!this._fixEnabled){
+				var tdnbox = dojo.marginBox(tdn);
+				this.editor.iframe.style.marginTop = tdnbox.h+"px";
+
+				if(isIE6){
+					s.left = dojo.position(tdn).x;
+					if(tdn.previousSibling){
+						this._IEOriginalPos = ['after',tdn.previousSibling];
+					}else if(tdn.nextSibling){
+						this._IEOriginalPos = ['before',tdn.nextSibling];
+					}else{
+						this._IEOriginalPos = ['last',tdn.parentNode];
+					}
+					dojo.body().appendChild(tdn);
+					dojo.addClass(tdn,'dijitIEFixedToolbar');
+				}else{
+					s.position = "fixed";
+					s.top = "0px";
+				}
+
+				dojo.marginBox(tdn, { w: tdnbox.w });
+				s.zIndex = 2000;
+				this._fixEnabled = true;
+			}
+			// if we're showing the floating toolbar, make sure that if
+			// we've scrolled past the bottom of the editor that we hide
+			// the toolbar for this instance of the editor.
+
+			// TODO: when we get multiple editor toolbar support working
+			// correctly, ensure that we check this against the scroll
+			// position of the bottom-most editor instance.
+			var eHeight = (this.height) ? parseInt(this.editor.height) : this.editor._lastHeight;
+			s.display = (scrollPos > this._scrollThreshold+eHeight) ? "none" : "";
+		}else if(this._fixEnabled){
+			this.editor.iframe.style.marginTop = '';
+			s.position = "";
+			s.top = "";
+			s.zIndex = "";
+			s.display = "";
+			if(isIE6){
+				s.left = "";
+				dojo.removeClass(tdn,'dijitIEFixedToolbar');
+				if(this._IEOriginalPos){
+					dojo.place(tdn, this._IEOriginalPos[1], this._IEOriginalPos[0]);
+					this._IEOriginalPos = null;
+				}else{
+					dojo.place(tdn, this.editor.iframe, 'before');
+				}
+			}
+			s.width = "";
+			this._fixEnabled = false;
+		}
+	},
+
+	destroy: function(){
+		// Overrides _Plugin.destroy().   TODO: call this.inherited() rather than repeating code.
+		this._IEOriginalPos = null;
+		this._handleScroll = false;
+		dojo.forEach(this._connects, dojo.disconnect);
+//		clearInterval(this.scrollInterval);
+
+		if(dojo.isIE < 7){
+			dojo.removeClass(this.editor.header, 'dijitIEFixedToolbar');
+		}
+	}
+});
diff --git a/dijit/_editor/plugins/EnterKeyHandling.js b/dijit/_editor/plugins/EnterKeyHandling.js
index ece69d8..f8d8e57 100644
--- a/dijit/_editor/plugins/EnterKeyHandling.js
+++ b/dijit/_editor/plugins/EnterKeyHandling.js
@@ -1,362 +1,672 @@
-/*
-	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
-*/
+dojo.provide("dijit._editor.plugins.EnterKeyHandling");
 
+dojo.require("dojo.window");
 
-if(!dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"]){
-dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"]=true;
-dojo.provide("dijit._editor.plugins.EnterKeyHandling");
-dojo.require("dijit._base.scroll");
-dojo.declare("dijit._editor.plugins.EnterKeyHandling",dijit._editor._Plugin,{blockNodeForEnter:"BR",constructor:function(_1){
-if(_1){
-dojo.mixin(this,_1);
-}
-},setEditor:function(_2){
-this.editor=_2;
-if(this.blockNodeForEnter=="BR"){
-if(dojo.isIE){
-_2.contentDomPreFilters.push(dojo.hitch(this,"regularPsToSingleLinePs"));
-_2.contentDomPostFilters.push(dojo.hitch(this,"singleLinePsToRegularPs"));
-_2.onLoadDeferred.addCallback(dojo.hitch(this,"_fixNewLineBehaviorForIE"));
-}else{
-_2.onLoadDeferred.addCallback(dojo.hitch(this,function(d){
-try{
-this.editor.document.execCommand("insertBrOnReturn",false,true);
-}
-catch(e){
-}
-return d;
-}));
-}
-}else{
-if(this.blockNodeForEnter){
-dojo["require"]("dijit._editor.range");
-var h=dojo.hitch(this,this.handleEnterKey);
-_2.addKeyHandler(13,0,0,h);
-_2.addKeyHandler(13,0,1,h);
-this.connect(this.editor,"onKeyPressed","onKeyPressed");
-}
-}
-},onKeyPressed:function(e){
-if(this._checkListLater){
-if(dojo.withGlobal(this.editor.window,"isCollapsed",dijit)){
-var _3=dojo.withGlobal(this.editor.window,"getAncestorElement",dijit._editor.selection,["LI"]);
-if(!_3){
-dijit._editor.RichText.prototype.execCommand.call(this.editor,"formatblock",this.blockNodeForEnter);
-var _4=dojo.withGlobal(this.editor.window,"getAncestorElement",dijit._editor.selection,[this.blockNodeForEnter]);
-if(_4){
-_4.innerHTML=this.bogusHtmlContent;
-if(dojo.isIE){
-var r=this.editor.document.selection.createRange();
-r.move("character",-1);
-r.select();
-}
-}else{
-console.error("onKeyPressed: Cannot find the new block node");
-}
-}else{
-if(dojo.isMoz){
-if(_3.parentNode.parentNode.nodeName=="LI"){
-_3=_3.parentNode.parentNode;
-}
-}
-var fc=_3.firstChild;
-if(fc&&fc.nodeType==1&&(fc.nodeName=="UL"||fc.nodeName=="OL")){
-_3.insertBefore(fc.ownerDocument.createTextNode(" "),fc);
-var _5=dijit.range.create(this.editor.window);
-_5.setStart(_3.firstChild,0);
-var _6=dijit.range.getSelection(this.editor.window,true);
-_6.removeAllRanges();
-_6.addRange(_5);
-}
-}
-}
-this._checkListLater=false;
-}
-if(this._pressedEnterInBlock){
-if(this._pressedEnterInBlock.previousSibling){
-this.removeTrailingBr(this._pressedEnterInBlock.previousSibling);
-}
-delete this._pressedEnterInBlock;
-}
-},bogusHtmlContent:" ",blockNodes:/^(?:P|H1|H2|H3|H4|H5|H6|LI)$/,handleEnterKey:function(e){
-var _7,_8,_9,_a=this.editor.document,br;
-if(e.shiftKey){
-var _b=dojo.withGlobal(this.editor.window,"getParentElement",dijit._editor.selection);
-var _c=dijit.range.getAncestor(_b,this.blockNodes);
-if(_c){
-if(!e.shiftKey&&_c.tagName=="LI"){
-return true;
-}
-_7=dijit.range.getSelection(this.editor.window);
-_8=_7.getRangeAt(0);
-if(!_8.collapsed){
-_8.deleteContents();
-_7=dijit.range.getSelection(this.editor.window);
-_8=_7.getRangeAt(0);
-}
-if(dijit.range.atBeginningOfContainer(_c,_8.startContainer,_8.startOffset)){
-if(e.shiftKey){
-br=_a.createElement("br");
-_9=dijit.range.create(this.editor.window);
-_c.insertBefore(br,_c.firstChild);
-_9.setStartBefore(br.nextSibling);
-_7.removeAllRanges();
-_7.addRange(_9);
-}else{
-dojo.place(br,_c,"before");
-}
-}else{
-if(dijit.range.atEndOfContainer(_c,_8.startContainer,_8.startOffset)){
-_9=dijit.range.create(this.editor.window);
-br=_a.createElement("br");
-if(e.shiftKey){
-_c.appendChild(br);
-_c.appendChild(_a.createTextNode(" "));
-_9.setStart(_c.lastChild,0);
-}else{
-dojo.place(br,_c,"after");
-_9.setStartAfter(_c);
-}
-_7.removeAllRanges();
-_7.addRange(_9);
-}else{
-return true;
-}
-}
-}else{
-dijit._editor.RichText.prototype.execCommand.call(this.editor,"inserthtml","<br>");
-}
-return false;
-}
-var _d=true;
-_7=dijit.range.getSelection(this.editor.window);
-_8=_7.getRangeAt(0);
-if(!_8.collapsed){
-_8.deleteContents();
-_7=dijit.range.getSelection(this.editor.window);
-_8=_7.getRangeAt(0);
-}
-var _e=dijit.range.getBlockAncestor(_8.endContainer,null,this.editor.editNode);
-var _f=_e.blockNode;
-if((this._checkListLater=(_f&&(_f.nodeName=="LI"||_f.parentNode.nodeName=="LI")))){
-if(dojo.isMoz){
-this._pressedEnterInBlock=_f;
-}
-if(/^(\s| |\xA0|<span\b[^>]*\bclass=['"]Apple-style-span['"][^>]*>(\s| |\xA0)<\/span>)?(<br>)?$/.test(_f.innerHTML)){
-_f.innerHTML="";
-if(dojo.isWebKit){
-_9=dijit.range.create(this.editor.window);
-_9.setStart(_f,0);
-_7.removeAllRanges();
-_7.addRange(_9);
-}
-this._checkListLater=false;
-}
-return true;
-}
-if(!_e.blockNode||_e.blockNode===this.editor.editNode){
-try{
-dijit._editor.RichText.prototype.execCommand.call(this.editor,"formatblock",this.blockNodeForEnter);
-}
-catch(e2){
-}
-_e={blockNode:dojo.withGlobal(this.editor.window,"getAncestorElement",dijit._editor.selection,[this.blockNodeForEnter]),blockContainer:this.editor.editNode};
-if(_e.blockNode){
-if(_e.blockNode!=this.editor.editNode&&(!(_e.blockNode.textContent||_e.blockNode.innerHTML).replace(/^\s+|\s+$/g,"").length)){
-this.removeTrailingBr(_e.blockNode);
-return false;
-}
-}else{
-_e.blockNode=this.editor.editNode;
-}
-_7=dijit.range.getSelection(this.editor.window);
-_8=_7.getRangeAt(0);
-}
-var _10=_a.createElement(this.blockNodeForEnter);
-_10.innerHTML=this.bogusHtmlContent;
-this.removeTrailingBr(_e.blockNode);
-if(dijit.range.atEndOfContainer(_e.blockNode,_8.endContainer,_8.endOffset)){
-if(_e.blockNode===_e.blockContainer){
-_e.blockNode.appendChild(_10);
-}else{
-dojo.place(_10,_e.blockNode,"after");
-}
-_d=false;
-_9=dijit.range.create(this.editor.window);
-_9.setStart(_10,0);
-_7.removeAllRanges();
-_7.addRange(_9);
-if(this.editor.height){
-dijit.scrollIntoView(_10);
-}
-}else{
-if(dijit.range.atBeginningOfContainer(_e.blockNode,_8.startContainer,_8.startOffset)){
-dojo.place(_10,_e.blockNode,_e.blockNode===_e.blockContainer?"first":"before");
-if(_10.nextSibling&&this.editor.height){
-_9=dijit.range.create(this.editor.window);
-_9.setStart(_10.nextSibling,0);
-_7.removeAllRanges();
-_7.addRange(_9);
-dijit.scrollIntoView(_10.nextSibling);
-}
-_d=false;
-}else{
-if(dojo.isMoz){
-this._pressedEnterInBlock=_e.blockNode;
-}
-}
-}
-return _d;
-},removeTrailingBr:function(_11){
-var _12=/P|DIV|LI/i.test(_11.tagName)?_11:dijit._editor.selection.getParentOfType(_11,["P","DIV","LI"]);
-if(!_12){
-return;
-}
-if(_12.lastChild){
-if((_12.childNodes.length>1&&_12.lastChild.nodeType==3&&/^[\s\xAD]*$/.test(_12.lastChild.nodeValue))||_12.lastChild.tagName=="BR"){
-dojo.destroy(_12.lastChild);
-}
-}
-if(!_12.childNodes.length){
-_12.innerHTML=this.bogusHtmlContent;
-}
-},_fixNewLineBehaviorForIE:function(d){
-var doc=this.editor.document;
-if(doc.__INSERTED_EDITIOR_NEWLINE_CSS===undefined){
-var _13=dojo.create("style",{type:"text/css"},doc.getElementsByTagName("head")[0]);
-_13.styleSheet.cssText="p{margin:0;}";
-this.editor.document.__INSERTED_EDITIOR_NEWLINE_CSS=true;
-}
-return d;
-},regularPsToSingleLinePs:function(_14,_15){
-function _16(el){
-function _17(_18){
-var _19=_18[0].ownerDocument.createElement("p");
-_18[0].parentNode.insertBefore(_19,_18[0]);
-dojo.forEach(_18,function(_1a){
-_19.appendChild(_1a);
-});
-};
-var _1b=0;
-var _1c=[];
-var _1d;
-while(_1b<el.childNodes.length){
-_1d=el.childNodes[_1b];
-if(_1d.nodeType==3||(_1d.nodeType==1&&_1d.nodeName!="BR"&&dojo.style(_1d,"display")!="block")){
-_1c.push(_1d);
-}else{
-var _1e=_1d.nextSibling;
-if(_1c.length){
-_17(_1c);
-_1b=(_1b+1)-_1c.length;
-if(_1d.nodeName=="BR"){
-dojo.destroy(_1d);
-}
-}
-_1c=[];
-}
-_1b++;
-}
-if(_1c.length){
-_17(_1c);
-}
-};
-function _1f(el){
-var _20=null;
-var _21=[];
-var _22=el.childNodes.length-1;
-for(var i=_22;i>=0;i--){
-_20=el.childNodes[i];
-if(_20.nodeName=="BR"){
-var _23=_20.ownerDocument.createElement("p");
-dojo.place(_23,el,"after");
-if(_21.length==0&&i!=_22){
-_23.innerHTML=" ";
-}
-dojo.forEach(_21,function(_24){
-_23.appendChild(_24);
-});
-dojo.destroy(_20);
-_21=[];
-}else{
-_21.unshift(_20);
-}
-}
-};
-var _25=[];
-var ps=_14.getElementsByTagName("p");
-dojo.forEach(ps,function(p){
-_25.push(p);
+dojo.declare("dijit._editor.plugins.EnterKeyHandling", dijit._editor._Plugin, {
+	// summary:
+	//		This plugin tries to make all browsers behave consistently w.r.t
+	//		displaying paragraphs, specifically dealing with when the user presses
+	//		the ENTER key.
+	//
+	//		It deals mainly with how the text appears on the screen (specifically
+	//		address the double-spaced line problem on IE), but also has some code
+	//		to normalize what attr('value') returns.
+	//
+	// description:
+	//		This plugin has three modes:
+	//
+	//			* blockModeForEnter=BR
+	//			* blockModeForEnter=DIV
+	//			* blockModeForEnter=P
+	//
+	//		In blockModeForEnter=P, the ENTER key semantically means "start a new
+	//		paragraph", whereas shift-ENTER means  "new line in the current paragraph".
+	//		For example:
+	//
+	//		|	first paragraph <shift-ENTER>
+	//		|	second line of first paragraph <ENTER>
+	//		|
+	//		|	second paragraph
+	//
+	//		In the other two modes, the ENTER key means to go to a new line in the
+	//		current paragraph, and users [visually] create a new paragraph by pressing ENTER twice.
+	//		For example, if the user enters text into an editor like this:
+	//
+	//		|		one <ENTER>
+	//		|		two <ENTER>
+	//		|		three <ENTER>
+	//		|		<ENTER>
+	//		|		four <ENTER>
+	//		|		five <ENTER>
+	//		|		six <ENTER>
+	//
+	//		It will appear on the screen as two paragraphs of three lines each.
+	//
+	//		blockNodeForEnter=BR
+	//		--------------------
+	//		On IE, typing the above keystrokes in the editor will internally produce DOM of:
+	//
+	//		|		<p>one</p>
+	//		|		<p>two</p>
+	//		|		<p>three</p>
+	//		|		<p></p>
+	//		|		<p>four</p>
+	//		|		<p>five</p>
+	//		|		<p>six</p>
+	//
+	//		However, blockNodeForEnter=BR makes the Editor on IE display like other browsers, by
+	//		changing the CSS for the <p> node to not have top/bottom margins,
+	//		thus eliminating the double-spaced appearance.
+	//
+	//		Also, attr('value') when used w/blockNodeForEnter=br on IE will return:
+	//
+	//		|	<p> one <br> two <br> three </p>
+	//		|	<p> four <br> five <br> six </p>
+	//
+	//		This output normalization implemented by a filter when the
+	//		editor writes out it's data, to convert consecutive <p>
+	//		nodes into a single <p> node with internal <br> separators.
+	//
+	//		There's also a pre-filter to mirror the post-filter.
+	//		It converts a single <p> with <br> line breaks
+	//		into separate <p> nodes, and creates empty <p> nodes for spacing
+	//		between paragraphs.
+	//
+	//		On FF typing the above keystrokes will internally generate:
+	//
+	//		|		one <br> two <br> three <br> <br> four <br> five <br> six <br>
+	//
+	//		And on Safari it will generate:
+	//
+	//		|		"one"
+	//		|		<div>two</div>
+	//		|		<div>three</div>
+	//		|		<div><br></div>
+	//		|		<div>four</div>
+	//		|		<div>five</div>
+	//		|		<div>six</div>
+	//
+	//		Thus, Safari and FF already look correct although semantically their content is a bit strange.
+	//		On Safari or Firefox blockNodeForEnter=BR uses the builtin editor command "insertBrOnReturn",
+	//		but that doesn't seem to do anything.
+	//		Thus, attr('value') on safari/FF returns the browser-specific HTML listed above,
+	//		rather than the semantically meaningful value that IE returns: <p>one<br>two</p> <p>three<br>four</p>.
+	//
+	//		(Note: originally based on http://bugs.dojotoolkit.org/ticket/2859)
+	//
+	//		blockNodeForEnter=P
+	//		-------------------
+	//		Plugin will monitor keystrokes and update the editor's content on the fly,
+	//		so that the ENTER key will create a new <p> on FF and Safari (it already
+	//		works that way by default on IE).
+	//
+	//		blockNodeForEnter=DIV
+	//		---------------------
+	//		Follows the same code path as blockNodeForEnter=P but inserting a <div>
+	//		on ENTER key.  Although it produces strange internal DOM, like this:
+	//
+	//		|	<div>paragraph one</div>
+	//		|	<div>paragraph one, line 2</div>
+	//		|	<div> </div>
+	//		|	<div>paragraph two</div>
+	//
+	//		it does provide a consistent look on all browsers, and the on-the-fly DOM updating
+	//		can be useful for collaborative editing.
+
+	// blockNodeForEnter: String
+	//		This property decides the behavior of Enter key. It can be either P,
+	//		DIV, BR, or empty (which means disable this feature). Anything else
+	//		will trigger errors.
+	//
+	//		See class description for more details.
+	blockNodeForEnter: 'BR',
+
+	constructor: function(args){
+		if(args){
+			dojo.mixin(this,args);
+		}
+	},
+
+	setEditor: function(editor){
+		// Overrides _Plugin.setEditor().
+		this.editor = editor;
+		if(this.blockNodeForEnter == 'BR'){
+			if(dojo.isIE){
+				editor.contentDomPreFilters.push(dojo.hitch(this, "regularPsToSingleLinePs"));
+				editor.contentDomPostFilters.push(dojo.hitch(this, "singleLinePsToRegularPs"));
+				editor.onLoadDeferred.addCallback(dojo.hitch(this, "_fixNewLineBehaviorForIE"));
+			}else{
+				editor.onLoadDeferred.addCallback(dojo.hitch(this,function(d){
+					try{
+						this.editor.document.execCommand("insertBrOnReturn", false, true);
+					}catch(e){}
+					return d;
+				}));
+			}
+		}else if(this.blockNodeForEnter){
+			// add enter key handler
+			// FIXME: need to port to the new event code!!
+			dojo['require']('dijit._editor.range');
+			var h = dojo.hitch(this,this.handleEnterKey);
+			editor.addKeyHandler(13, 0, 0, h); //enter
+			editor.addKeyHandler(13, 0, 1, h); //shift+enter
+			this.connect(this.editor,'onKeyPressed','onKeyPressed');
+		}
+	},
+	onKeyPressed: function(e){
+		// summary:
+		//		Handler for keypress events.
+		// tags:
+		//		private
+		if(this._checkListLater){
+			if(dojo.withGlobal(this.editor.window, 'isCollapsed', dijit)){
+				var liparent=dojo.withGlobal(this.editor.window, 'getAncestorElement', dijit._editor.selection, ['LI']);
+				if(!liparent){
+					// circulate the undo detection code by calling RichText::execCommand directly
+					dijit._editor.RichText.prototype.execCommand.call(this.editor, 'formatblock',this.blockNodeForEnter);
+					// set the innerHTML of the new block node
+					var block = dojo.withGlobal(this.editor.window, 'getAncestorElement', dijit._editor.selection, [this.blockNodeForEnter]);
+					if(block){
+						block.innerHTML=this.bogusHtmlContent;
+						if(dojo.isIE){
+							// move to the start by moving backwards one char
+							var r = this.editor.document.selection.createRange();
+							r.move('character',-1);
+							r.select();
+						}
+					}else{
+						console.error('onKeyPressed: Cannot find the new block node'); // FIXME
+					}
+				}else{
+					if(dojo.isMoz){
+						if(liparent.parentNode.parentNode.nodeName == 'LI'){
+							liparent=liparent.parentNode.parentNode;
+						}
+					}
+					var fc=liparent.firstChild;
+					if(fc && fc.nodeType == 1 && (fc.nodeName == 'UL' || fc.nodeName == 'OL')){
+						liparent.insertBefore(fc.ownerDocument.createTextNode('\xA0'),fc);
+						var newrange = dijit.range.create(this.editor.window);
+						newrange.setStart(liparent.firstChild,0);
+						var selection = dijit.range.getSelection(this.editor.window, true);
+						selection.removeAllRanges();
+						selection.addRange(newrange);
+					}
+				}
+			}
+			this._checkListLater = false;
+		}
+		if(this._pressedEnterInBlock){
+			// the new created is the original current P, so we have previousSibling below
+			if(this._pressedEnterInBlock.previousSibling){
+				this.removeTrailingBr(this._pressedEnterInBlock.previousSibling);
+			}
+			delete this._pressedEnterInBlock;
+		}
+	},
+
+	// bogusHtmlContent: [private] String
+	//		HTML to stick into a new empty block
+	bogusHtmlContent: ' ',
+
+	// blockNodes: [private] Regex
+	//		Regex for testing if a given tag is a block level (display:block) tag
+	blockNodes: /^(?:P|H1|H2|H3|H4|H5|H6|LI)$/,
+
+	handleEnterKey: function(e){
+		// summary:
+		//		Handler for enter key events when blockModeForEnter is DIV or P.
+		// description:
+		//		Manually handle enter key event to make the behavior consistent across
+		//		all supported browsers. See class description for details.
+		// tags:
+		//		private
+
+		var selection, range, newrange, doc=this.editor.document,br;
+		if(e.shiftKey){		// shift+enter always generates <br>
+			var parent = dojo.withGlobal(this.editor.window, "getParentElement", dijit._editor.selection);
+			var header = dijit.range.getAncestor(parent,this.blockNodes);
+			if(header){
+				if(!e.shiftKey && header.tagName == 'LI'){
+					return true; // let browser handle
+				}
+				selection = dijit.range.getSelection(this.editor.window);
+				range = selection.getRangeAt(0);
+				if(!range.collapsed){
+					range.deleteContents();
+					selection = dijit.range.getSelection(this.editor.window);
+					range = selection.getRangeAt(0);
+				}
+				if(dijit.range.atBeginningOfContainer(header, range.startContainer, range.startOffset)){
+					if(e.shiftKey){
+						br=doc.createElement('br');
+						newrange = dijit.range.create(this.editor.window);
+						header.insertBefore(br,header.firstChild);
+						newrange.setStartBefore(br.nextSibling);
+						selection.removeAllRanges();
+						selection.addRange(newrange);
+					}else{
+						dojo.place(br, header, "before");
+					}
+				}else if(dijit.range.atEndOfContainer(header, range.startContainer, range.startOffset)){
+					newrange = dijit.range.create(this.editor.window);
+					br=doc.createElement('br');
+					if(e.shiftKey){
+						header.appendChild(br);
+						header.appendChild(doc.createTextNode('\xA0'));
+						newrange.setStart(header.lastChild,0);
+					}else{
+						dojo.place(br, header, "after");
+						newrange.setStartAfter(header);
+					}
+
+					selection.removeAllRanges();
+					selection.addRange(newrange);
+				}else{
+					return true; // let browser handle
+				}
+			}else{
+				// don't change this: do not call this.execCommand, as that may have other logic in subclass
+				dijit._editor.RichText.prototype.execCommand.call(this.editor, 'inserthtml', '<br>');
+			}
+			return false;
+		}
+		var _letBrowserHandle = true;
+
+		// first remove selection
+		selection = dijit.range.getSelection(this.editor.window);
+		range = selection.getRangeAt(0);
+		if(!range.collapsed){
+			range.deleteContents();
+			selection = dijit.range.getSelection(this.editor.window);
+			range = selection.getRangeAt(0);
+		}
+
+		var block = dijit.range.getBlockAncestor(range.endContainer, null, this.editor.editNode);
+		var blockNode = block.blockNode;
+
+		// if this is under a LI or the parent of the blockNode is LI, just let browser to handle it
+		if((this._checkListLater = (blockNode && (blockNode.nodeName == 'LI' || blockNode.parentNode.nodeName == 'LI')))){
+			if(dojo.isMoz){
+				// press enter in middle of P may leave a trailing <br/>, let's remove it later
+				this._pressedEnterInBlock = blockNode;
+			}
+			// if this li only contains spaces, set the content to empty so the browser will outdent this item
+			if(/^(\s| |\xA0|<span\b[^>]*\bclass=['"]Apple-style-span['"][^>]*>(\s| |\xA0)<\/span>)?(<br>)?$/.test(blockNode.innerHTML)){
+				// empty LI node
+				blockNode.innerHTML = '';
+				if(dojo.isWebKit){ // WebKit tosses the range when innerHTML is reset
+					newrange = dijit.range.create(this.editor.window);
+					newrange.setStart(blockNode, 0);
+					selection.removeAllRanges();
+					selection.addRange(newrange);
+				}
+				this._checkListLater = false; // nothing to check since the browser handles outdent
+			}
+			return true;
+		}
+
+		// text node directly under body, let's wrap them in a node
+		if(!block.blockNode || block.blockNode===this.editor.editNode){
+			try{
+				dijit._editor.RichText.prototype.execCommand.call(this.editor, 'formatblock',this.blockNodeForEnter);
+			}catch(e2){ /*squelch FF3 exception bug when editor content is a single BR*/ }
+			// get the newly created block node
+			// FIXME
+			block = {blockNode:dojo.withGlobal(this.editor.window, "getAncestorElement", dijit._editor.selection, [this.blockNodeForEnter]),
+					blockContainer: this.editor.editNode};
+			if(block.blockNode){
+				if(block.blockNode != this.editor.editNode &&
+					(!(block.blockNode.textContent || block.blockNode.innerHTML).replace(/^\s+|\s+$/g, "").length)){
+					this.removeTrailingBr(block.blockNode);
+					return false;
+				}
+			}else{	// we shouldn't be here if formatblock worked
+				block.blockNode = this.editor.editNode;
+			}
+			selection = dijit.range.getSelection(this.editor.window);
+			range = selection.getRangeAt(0);
+		}
+
+		var newblock = doc.createElement(this.blockNodeForEnter);
+		newblock.innerHTML=this.bogusHtmlContent;
+		this.removeTrailingBr(block.blockNode);
+		if(dijit.range.atEndOfContainer(block.blockNode, range.endContainer, range.endOffset)){
+			if(block.blockNode === block.blockContainer){
+				block.blockNode.appendChild(newblock);
+			}else{
+				dojo.place(newblock, block.blockNode, "after");
+			}
+			_letBrowserHandle = false;
+			// lets move caret to the newly created block
+			newrange = dijit.range.create(this.editor.window);
+			newrange.setStart(newblock, 0);
+			selection.removeAllRanges();
+			selection.addRange(newrange);
+			if(this.editor.height){
+				dojo.window.scrollIntoView(newblock);
+			}
+		}else if(dijit.range.atBeginningOfContainer(block.blockNode,
+				range.startContainer, range.startOffset)){
+			dojo.place(newblock, block.blockNode, block.blockNode === block.blockContainer ? "first" : "before");
+			if(newblock.nextSibling && this.editor.height){
+				// position input caret - mostly WebKit needs this
+				newrange = dijit.range.create(this.editor.window);
+				newrange.setStart(newblock.nextSibling, 0);
+				selection.removeAllRanges();
+				selection.addRange(newrange);
+				// browser does not scroll the caret position into view, do it manually
+				dojo.window.scrollIntoView(newblock.nextSibling);
+			}
+			_letBrowserHandle = false;
+		}else{ //press enter in the middle of P/DIV/Whatever/
+			if(block.blockNode === block.blockContainer){
+				block.blockNode.appendChild(newblock);
+			}else{
+				dojo.place(newblock, block.blockNode, "after");
+			}
+			_letBrowserHandle = false;
+
+			// Clone any block level styles.
+			if(block.blockNode.style){
+				if(newblock.style){
+					if(block.blockNode.style.cssText){
+						newblock.style.cssText = block.blockNode.style.cssText;
+					}
+				}
+			}
+			
+			// Okay, we probably have to split.
+			var rs = range.startContainer;
+			if(rs && rs.nodeType == 3){
+				// Text node, we have to split it.
+				var nodeToMove, tNode;
+				var txt = rs.nodeValue;
+				var startNode = doc.createTextNode(txt.substring(0, range.startOffset));
+				var endNode = doc.createTextNode(txt.substring(range.startOffset, txt.length));
+
+				// Place the split, then remove original nodes.
+				dojo.place(startNode, rs, "before");
+				dojo.place(endNode, rs, "after");
+				dojo.destroy(rs);
+
+				// Okay, we split the text.  Now we need to see if we're
+				// parented to the block element we're splitting and if
+				// not, we have to split all the way up.  Ugh.
+				var parentC = startNode.parentNode;
+				while(parentC !== block.blockNode){
+					var tg = parentC.tagName;
+					var newTg = doc.createElement(tg);
+					// Clone over any 'style' data. 
+					if(parentC.style){
+						if(newTg.style){
+							if(parentC.style.cssText){
+								newTg.style.cssText = parentC.style.cssText;
+							}
+						}
+					}
+
+					nodeToMove = endNode;
+					while(nodeToMove){
+						tNode = nodeToMove.nextSibling;
+						newTg.appendChild(nodeToMove);
+						nodeToMove = tNode;
+					}
+					dojo.place(newTg, parentC, "after");
+					startNode = parentC;
+					endNode = newTg;
+					parentC = parentC.parentNode;
+				}
+
+				// Lastly, move the split out tags to the new block.
+				// as they should now be split properly.
+				nodeToMove = endNode;
+				if(nodeToMove.nodeType == 1 || (nodeToMove.nodeType == 3 && nodeToMove.nodeValue)){
+					// Non-blank text and non-text nodes need to clear out that blank space
+					// before moving the contents.
+					newblock.innerHTML = "";
+				}
+				while(nodeToMove){
+					tNode = nodeToMove.nextSibling;
+					newblock.appendChild(nodeToMove);
+					nodeToMove = tNode;
+				}
+			}
+			
+			//lets move caret to the newly created block
+			newrange = dijit.range.create(this.editor.window);
+			newrange.setStart(newblock, 0);
+			selection.removeAllRanges();
+			selection.addRange(newrange);
+			if(this.editor.height){
+				dijit.scrollIntoView(newblock);
+			}
+			if(dojo.isMoz){
+				// press enter in middle of P may leave a trailing <br/>, let's remove it later
+				this._pressedEnterInBlock = block.blockNode;
+			}
+		}
+		return _letBrowserHandle;
+	},
+
+	removeTrailingBr: function(container){
+		// summary:
+		//		If last child of container is a <br>, then remove it.
+		// tags:
+		//		private
+		var para = /P|DIV|LI/i.test(container.tagName) ?
+			container : dijit._editor.selection.getParentOfType(container,['P','DIV','LI']);
+
+		if(!para){ return; }
+		if(para.lastChild){
+			if((para.childNodes.length > 1 && para.lastChild.nodeType == 3 && /^[\s\xAD]*$/.test(para.lastChild.nodeValue)) ||
+				para.lastChild.tagName=='BR'){
+
+				dojo.destroy(para.lastChild);
+			}
+		}
+		if(!para.childNodes.length){
+			para.innerHTML=this.bogusHtmlContent;
+		}
+	},
+	_fixNewLineBehaviorForIE: function(d){
+		// summary:
+		//		Insert CSS so <p> nodes don't have spacing around them,
+		//		thus hiding the fact that ENTER key on IE is creating new
+		//		paragraphs
+
+		// cannot use !important since there may be custom user styling;
+		var doc = this.editor.document;
+		if(doc.__INSERTED_EDITIOR_NEWLINE_CSS === undefined){
+			var style = dojo.create("style", {type: "text/css"}, doc.getElementsByTagName("head")[0]);
+			style.styleSheet.cssText = "p{margin:0;}"; // cannot use !important since there may be custom user styling;
+			this.editor.document.__INSERTED_EDITIOR_NEWLINE_CSS = true;
+		}
+		return d;
+	},
+	regularPsToSingleLinePs: function(element, noWhiteSpaceInEmptyP){
+		// summary:
+		//		Converts a <p> node containing <br>'s into multiple <p> nodes.
+		// description:
+		//		See singleLinePsToRegularPs().   This method does the
+		//		opposite thing, and is used as a pre-filter when loading the
+		//		editor, to mirror the effects of the post-filter at end of edit.
+		// tags:
+		//		private
+		function wrapLinesInPs(el){
+		  // move "lines" of top-level text nodes into ps
+			function wrapNodes(nodes){
+				// nodes are assumed to all be siblings
+				var newP = nodes[0].ownerDocument.createElement('p'); // FIXME: not very idiomatic
+				nodes[0].parentNode.insertBefore(newP, nodes[0]);
+				dojo.forEach(nodes, function(node){
+					newP.appendChild(node);
+				});
+			}
+
+			var currentNodeIndex = 0;
+			var nodesInLine = [];
+			var currentNode;
+			while(currentNodeIndex < el.childNodes.length){
+				currentNode = el.childNodes[currentNodeIndex];
+				if( currentNode.nodeType==3 ||	// text node
+					(currentNode.nodeType==1 && currentNode.nodeName!='BR' && dojo.style(currentNode, "display")!="block")
+				){
+					nodesInLine.push(currentNode);
+				}else{
+					// hit line delimiter; process nodesInLine if there are any
+					var nextCurrentNode = currentNode.nextSibling;
+					if(nodesInLine.length){
+						wrapNodes(nodesInLine);
+						currentNodeIndex = (currentNodeIndex+1)-nodesInLine.length;
+						if(currentNode.nodeName=="BR"){
+							dojo.destroy(currentNode);
+						}
+					}
+					nodesInLine = [];
+				}
+				currentNodeIndex++;
+			}
+			if(nodesInLine.length){ wrapNodes(nodesInLine); }
+		}
+
+		function splitP(el){
+			// split a paragraph into seperate paragraphs at BRs
+			var currentNode = null;
+			var trailingNodes = [];
+			var lastNodeIndex = el.childNodes.length-1;
+			for(var i=lastNodeIndex; i>=0; i--){
+				currentNode = el.childNodes[i];
+				if(currentNode.nodeName=="BR"){
+					var newP = currentNode.ownerDocument.createElement('p');
+					dojo.place(newP, el, "after");
+					if(trailingNodes.length==0 && i != lastNodeIndex){
+						newP.innerHTML = " "
+					}
+					dojo.forEach(trailingNodes, function(node){
+						newP.appendChild(node);
+					});
+					dojo.destroy(currentNode);
+					trailingNodes = [];
+				}else{
+					trailingNodes.unshift(currentNode);
+				}
+			}
+		}
+
+		var pList = [];
+		var ps = element.getElementsByTagName('p');
+		dojo.forEach(ps, function(p){ pList.push(p); });
+		dojo.forEach(pList, function(p){
+			var prevSib = p.previousSibling;
+			if(	(prevSib) && (prevSib.nodeType == 1) && 
+				(prevSib.nodeName == 'P' || dojo.style(prevSib, 'display') != 'block')
+			){
+				var newP = p.parentNode.insertBefore(this.document.createElement('p'), p);
+				// this is essential to prevent IE from losing the P.
+				// if it's going to be innerHTML'd later we need
+				// to add the   to _really_ force the issue
+				newP.innerHTML = noWhiteSpaceInEmptyP ? "" : " ";
+			}
+			splitP(p);
+		},this.editor);
+		wrapLinesInPs(element);
+		return element;
+	},
+
+	singleLinePsToRegularPs: function(element){
+		// summary:
+		//		Called as post-filter.
+		//		Apparently collapses adjacent <p> nodes into a single <p>
+		//		nodes with <br> separating each line.
+		//
+		// example:
+		//		Given this input:
+		//	|	<p>line 1</p>
+		//	|	<p>line 2</p>
+		//	|	<ol>
+		//	|		<li>item 1
+		//	|		<li>item 2
+		//	|	</ol>
+		//	|	<p>line 3</p>
+		//	|	<p>line 4</p>
+		//
+		//		Will convert to:
+		//	|	<p>line 1<br>line 2</p>
+		//	|	<ol>
+		//	|		<li>item 1
+		//	|		<li>item 2
+		//	|	</ol>
+		//	|	<p>line 3<br>line 4</p>
+		//
+		//		Not sure why this situation would even come up after the pre-filter and
+		//		the enter-key-handling code.
+		//
+		// tags:
+		//		private
+
+		function getParagraphParents(node){
+			// summary:
+			//		Used to get list of all nodes that contain paragraphs.
+			//		Seems like that would just be the very top node itself, but apparently not.
+			var ps = node.getElementsByTagName('p');
+			var parents = [];
+			for(var i=0; i<ps.length; i++){
+				var p = ps[i];
+				var knownParent = false;
+				for(var k=0; k < parents.length; k++){
+					if(parents[k] === p.parentNode){
+						knownParent = true;
+						break;
+					}
+				}
+				if(!knownParent){
+					parents.push(p.parentNode);
+				}
+			}
+			return parents;
+		}
+
+		function isParagraphDelimiter(node){
+			return (!node.childNodes.length || node.innerHTML==" ");
+		}
+
+		var paragraphContainers = getParagraphParents(element);
+		for(var i=0; i<paragraphContainers.length; i++){
+			var container = paragraphContainers[i];
+			var firstPInBlock = null;
+			var node = container.firstChild;
+			var deleteNode = null;
+			while(node){
+				if(node.nodeType != 1 || node.tagName != 'P' ||
+						(node.getAttributeNode('style') || {/*no style*/}).specified){
+					firstPInBlock = null;
+				}else if(isParagraphDelimiter(node)){
+					deleteNode = node;
+					firstPInBlock = null;
+				}else{
+					if(firstPInBlock == null){
+						firstPInBlock = node;
+					}else{
+						if( (!firstPInBlock.lastChild || firstPInBlock.lastChild.nodeName != 'BR') &&
+							(node.firstChild) &&
+							(node.firstChild.nodeName != 'BR')
+						){
+							firstPInBlock.appendChild(this.editor.document.createElement('br'));
+						}
+						while(node.firstChild){
+							firstPInBlock.appendChild(node.firstChild);
+						}
+						deleteNode = node;
+					}
+				}
+				node = node.nextSibling;
+				if(deleteNode){
+					dojo.destroy(deleteNode);
+					deleteNode = null;
+				}
+			}
+		}
+		return element;
+	}
 });
-dojo.forEach(_25,function(p){
-var _26=p.previousSibling;
-if((_26)&&(_26.nodeType==1)&&(_26.nodeName=="P"||dojo.style(_26,"display")!="block")){
-var _27=p.parentNode.insertBefore(this.document.createElement("p"),p);
-_27.innerHTML=_15?"":" ";
-}
-_1f(p);
-},this.editor);
-_16(_14);
-return _14;
-},singleLinePsToRegularPs:function(_28){
-function _29(_2a){
-var ps=_2a.getElementsByTagName("p");
-var _2b=[];
-for(var i=0;i<ps.length;i++){
-var p=ps[i];
-var _2c=false;
-for(var k=0;k<_2b.length;k++){
-if(_2b[k]===p.parentNode){
-_2c=true;
-break;
-}
-}
-if(!_2c){
-_2b.push(p.parentNode);
-}
-}
-return _2b;
-};
-function _2d(_2e){
-return (!_2e.childNodes.length||_2e.innerHTML==" ");
-};
-var _2f=_29(_28);
-for(var i=0;i<_2f.length;i++){
-var _30=_2f[i];
-var _31=null;
-var _32=_30.firstChild;
-var _33=null;
-while(_32){
-if(_32.nodeType!=1||_32.tagName!="P"||(_32.getAttributeNode("style")||{}).specified){
-_31=null;
-}else{
-if(_2d(_32)){
-_33=_32;
-_31=null;
-}else{
-if(_31==null){
-_31=_32;
-}else{
-if((!_31.lastChild||_31.lastChild.nodeName!="BR")&&(_32.firstChild)&&(_32.firstChild.nodeName!="BR")){
-_31.appendChild(this.editor.document.createElement("br"));
-}
-while(_32.firstChild){
-_31.appendChild(_32.firstChild);
-}
-_33=_32;
-}
-}
-}
-_32=_32.nextSibling;
-if(_33){
-dojo.destroy(_33);
-_33=null;
-}
-}
-}
-return _28;
-}});
-}
diff --git a/dijit/_editor/plugins/FontChoice.js b/dijit/_editor/plugins/FontChoice.js
index f5add30..cc47175 100644
--- a/dijit/_editor/plugins/FontChoice.js
+++ b/dijit/_editor/plugins/FontChoice.js
@@ -1,151 +1,573 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._editor.plugins.FontChoice"]){
-dojo._hasResource["dijit._editor.plugins.FontChoice"]=true;
 dojo.provide("dijit._editor.plugins.FontChoice");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit._editor.range");
+dojo.require("dijit._editor.selection");
 dojo.require("dijit.form.FilteringSelect");
 dojo.require("dojo.data.ItemFileReadStore");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dijit._editor","FontChoice",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit._editor.plugins._FontDropDown",[dijit._Widget,dijit._Templated],{label:"",widgetsInTemplate:true,plainText:false,templateString:"<span style='white-space: nowrap' class='dijit dijitReset dijitInline'>"+"<label class='dijitLeft dijitInline' for='${selectId}'>${label}</label>"+"<input dojoType='dijit.form.FilteringSelect' required=false labelType=html labelAttr=label searchAttr=name "+"tabIndex='-1' id='${selectId}' dojoAttachPoint='select' value=''/>"+"</span>",postMix [...]
-this.inherited(arguments);
-this.strings=dojo.i18n.getLocalization("dijit._editor","FontChoice");
-this.label=this.strings[this.command];
-this.id=dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
-this.selectId=this.id+"_select";
-this.inherited(arguments);
-},postCreate:function(){
-var _1=dojo.map(this.values,function(_2){
-var _3=this.strings[_2]||_2;
-return {label:this.getLabel(_2,_3),name:_3,value:_2};
-},this);
-this.select.store=new dojo.data.ItemFileReadStore({data:{identifier:"value",items:_1}});
-this.select.attr("value","",false);
-this.disabled=this.select.attr("disabled");
-},_setValueAttr:function(_4,_5){
-_5=_5!==false?true:false;
-this.select.attr("value",dojo.indexOf(this.values,_4)<0?"":_4,_5);
-if(!_5){
-this.select._lastValueReported=null;
-}
-},_getValueAttr:function(){
-return this.select.attr("value");
-},focus:function(){
-this.select.focus();
-},_setDisabledAttr:function(_6){
-this.disabled=_6;
-this.select.attr("disabled",_6);
-}});
-dojo.declare("dijit._editor.plugins._FontNameDropDown",dijit._editor.plugins._FontDropDown,{generic:false,command:"fontName",postMixInProperties:function(){
-if(!this.values){
-this.values=this.generic?["serif","sans-serif","monospace","cursive","fantasy"]:["Arial","Times New Roman","Comic Sans MS","Courier New"];
-}
-this.inherited(arguments);
-},getLabel:function(_7,_8){
-if(this.plainText){
-return _8;
-}else{
-return "<div style='font-family: "+_7+"'>"+_8+"</div>";
-}
-},_setValueAttr:function(_9,_a){
-_a=_a!==false?true:false;
-if(this.generic){
-var _b={"Arial":"sans-serif","Helvetica":"sans-serif","Myriad":"sans-serif","Times":"serif","Times New Roman":"serif","Comic Sans MS":"cursive","Apple Chancery":"cursive","Courier":"monospace","Courier New":"monospace","Papyrus":"fantasy"};
-_9=_b[_9]||_9;
-}
-this.inherited(arguments,[_9,_a]);
-}});
-dojo.declare("dijit._editor.plugins._FontSizeDropDown",dijit._editor.plugins._FontDropDown,{command:"fontSize",values:[1,2,3,4,5,6,7],getLabel:function(_c,_d){
-if(this.plainText){
-return _d;
-}else{
-return "<font size="+_c+"'>"+_d+"</font>";
-}
-},_setValueAttr:function(_e,_f){
-_f=_f!==false?true:false;
-if(_e.indexOf&&_e.indexOf("px")!=-1){
-var _10=parseInt(_e,10);
-_e={10:1,13:2,16:3,18:4,24:5,32:6,48:7}[_10]||_e;
-}
-this.inherited(arguments,[_e,_f]);
-}});
-dojo.declare("dijit._editor.plugins._FormatBlockDropDown",dijit._editor.plugins._FontDropDown,{command:"formatBlock",values:["p","h1","h2","h3","pre"],getLabel:function(_11,_12){
-if(this.plainText){
-return _12;
-}else{
-return "<"+_11+">"+_12+"</"+_11+">";
-}
-}});
-dojo.declare("dijit._editor.plugins.FontChoice",dijit._editor._Plugin,{useDefaultCommand:false,_initButton:function(){
-var _13={fontName:dijit._editor.plugins._FontNameDropDown,fontSize:dijit._editor.plugins._FontSizeDropDown,formatBlock:dijit._editor.plugins._FormatBlockDropDown}[this.command],_14=this.params;
-if(this.params.custom){
-_14.values=this.params.custom;
-}
-this.button=new _13(_14);
-this.connect(this.button.select,"onChange",function(_15){
-this.editor.focus();
-if(this.command=="fontName"&&_15.indexOf(" ")!=-1){
-_15="'"+_15+"'";
-}
-this.editor.execCommand(this.command,_15);
+
+dojo.requireLocalization("dijit._editor", "FontChoice");
+
+dojo.declare("dijit._editor.plugins._FontDropDown",
+	[dijit._Widget, dijit._Templated],{
+	// summary:
+	//		Base class for widgets that contains a label (like "Font:")
+	//		and a FilteringSelect drop down to pick a value.
+	//		Used as Toolbar entry.
+
+	// label: [public] String
+	//		The label to apply to this particular FontDropDown.
+	label: "",
+
+	// widgetsInTemplate: [public] boolean
+	//		Over-ride denoting the template has widgets to parse.
+	widgetsInTemplate: true,
+
+	// plainText: [public] boolean
+	//		Flag to indicate that the returned label should be plain text
+	//		instead of an example.
+	plainText: false,
+
+	// templateString: [public] String
+	//		The template used to construct the labeled dropdown.
+	templateString:
+		"<span style='white-space: nowrap' class='dijit dijitReset dijitInline'>" +
+			"<label class='dijitLeft dijitInline' for='${selectId}'>${label}</label>" +
+			"<input dojoType='dijit.form.FilteringSelect' required=false labelType=html labelAttr=label searchAttr=name " +
+					"tabIndex='-1' id='${selectId}' dojoAttachPoint='select' value=''/>" +
+		"</span>",
+
+	postMixInProperties: function(){
+		// summary:
+		//		Over-ride to misin specific properties.
+		this.inherited(arguments);
+
+		this.strings = dojo.i18n.getLocalization("dijit._editor", "FontChoice");
+
+		// Set some substitution variables used in the template
+		this.label = this.strings[this.command];
+		this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
+		this.selectId = this.id + "_select";
+
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		// summary:
+		//		Over-ride for the default postCreate action
+		//		This establishes the filtering selects and the like.
+
+		// Initialize the list of items in the drop down by creating data store with items like:
+		// {value: 1, name: "xx-small", label: "<font size=1>xx-small</font-size>" }
+		var	items = dojo.map(this.values, function(value){
+				var name = this.strings[value] || value;
+				return {
+					label: this.getLabel(value, name),
+					name: name,
+					value: value
+				};
+			}, this);
+
+		this.select.store = new dojo.data.ItemFileReadStore({
+			data: {
+				identifier: "value",
+				items: items
+			}
+		});
+
+		this.select.set("value", "", false);
+		this.disabled = this.select.get("disabled");
+	},
+
+	_setValueAttr: function(value, priorityChange){
+		// summary:
+		//		Over-ride for the default action of setting the
+		//		widget value, maps the input to known values
+		// value: Object|String
+		//		The value to set in the select.
+		// priorityChange:
+		//		Optional parameter used to tell the select whether or not to fire
+		//		onChange event.
+
+		//if the value is not a permitted value, just set empty string to prevent showing the warning icon
+		priorityChange = priorityChange !== false?true:false;
+		this.select.set('value', dojo.indexOf(this.values,value) < 0 ? "" : value, priorityChange);
+		if(!priorityChange){
+			// Clear the last state in case of updateState calls.  Ref: #10466
+			this.select._lastValueReported=null;
+		}
+	},
+
+	_getValueAttr: function(){
+		// summary:
+		//		Allow retreiving the value from the composite select on
+		//		call to button.get("value");
+		return this.select.get('value');
+	},
+
+	focus: function(){
+		// summary:
+		//		Over-ride for focus control of this widget.  Delegates focus down to the
+		//		filtering select.
+		this.select.focus();
+	},
+
+	_setDisabledAttr: function(value){
+		// summary:
+		//		Over-ride for the button's 'disabled' attribute so that it can be
+		//		disabled programmatically.
+
+		// Save off ths disabled state so the get retrieves it correctly
+		//without needing to have a function proxy it.
+		this.disabled = value;
+		this.select.set("disabled", value);
+	}
+});
+
+
+dojo.declare("dijit._editor.plugins._FontNameDropDown", dijit._editor.plugins._FontDropDown, {
+	// summary:
+	//		Dropdown to select a font; goes in editor toolbar.
+
+	// generic: Boolean
+	//		Use generic (web standard) font names
+	generic: false,
+
+	// command: [public] String
+	//		The editor 'command' implemented by this plugin.
+	command: "fontName",
+
+	postMixInProperties: function(){
+		// summary:
+		//		Over-ride for the default posr mixin control
+		if(!this.values){
+			this.values = this.generic ?
+				["serif", "sans-serif", "monospace", "cursive", "fantasy"] : // CSS font-family generics
+					["Arial", "Times New Roman", "Comic Sans MS", "Courier New"];
+		}
+		this.inherited(arguments);
+	},
+
+	getLabel: function(value, name){
+		// summary:
+		//		Function used to generate the labels of the format dropdown
+		//		will return a formatted, or plain label based on the value
+		//		of the plainText option.
+		// value: String
+		//		The 'insert value' associated with a name
+		// name: String
+		//		The text name of the value
+		if(this.plainText){
+			return name;
+		}else{
+			return "<div style='font-family: "+value+"'>" + name + "</div>";
+		}
+	},
+
+	_setValueAttr: function(value, priorityChange){
+		// summary:
+		//		Over-ride for the default action of setting the
+		//		widget value, maps the input to known values
+
+		priorityChange = priorityChange !== false?true:false;
+		if(this.generic){
+			var map = {
+				"Arial": "sans-serif",
+				"Helvetica": "sans-serif",
+				"Myriad": "sans-serif",
+				"Times": "serif",
+				"Times New Roman": "serif",
+				"Comic Sans MS": "cursive",
+				"Apple Chancery": "cursive",
+				"Courier": "monospace",
+				"Courier New": "monospace",
+				"Papyrus": "fantasy"
+//					,"????": "fantasy" TODO: IE doesn't map fantasy font-family?
+			};
+			value = map[value] || value;
+		}
+		this.inherited(arguments, [value, priorityChange]);
+	}
+});
+
+dojo.declare("dijit._editor.plugins._FontSizeDropDown", dijit._editor.plugins._FontDropDown, {
+	// summary:
+	//		Dropdown to select a font size; goes in editor toolbar.
+
+	// command: [public] String
+	//		The editor 'command' implemented by this plugin.
+	command: "fontSize",
+
+	// values: [public] Number[]
+	//		The HTML font size values supported by this plugin
+	values: [1,2,3,4,5,6,7], // sizes according to the old HTML FONT SIZE
+
+	getLabel: function(value, name){
+		// summary:
+		//		Function used to generate the labels of the format dropdown
+		//		will return a formatted, or plain label based on the value
+		//		of the plainText option.
+		//		We're stuck using the deprecated FONT tag to correspond
+		//		with the size measurements used by the editor
+		// value: String
+		//		The 'insert value' associated with a name
+		// name: String
+		//		The text name of the value
+		if(this.plainText){
+			return name;
+		}else{
+			return "<font size=" + value + "'>" + name + "</font>";
+		}
+	},
+
+	_setValueAttr: function(value, priorityChange){
+		// summary:
+		//		Over-ride for the default action of setting the
+		//		widget value, maps the input to known values
+		priorityChange = priorityChange !== false?true:false;
+		if(value.indexOf && value.indexOf("px") != -1){
+			var pixels = parseInt(value, 10);
+			value = {10:1, 13:2, 16:3, 18:4, 24:5, 32:6, 48:7}[pixels] || value;
+		}
+
+		this.inherited(arguments, [value, priorityChange]);
+	}
+});
+
+
+dojo.declare("dijit._editor.plugins._FormatBlockDropDown", dijit._editor.plugins._FontDropDown, {
+	// summary:
+	//		Dropdown to select a format (like paragraph or heading); goes in editor toolbar.
+
+	// command: [public] String
+	//		The editor 'command' implemented by this plugin.
+	command: "formatBlock",
+
+	// values: [public] Array
+	//		The HTML format tags supported by this plugin
+	values: ["noFormat", "p", "h1", "h2", "h3", "pre"],
+
+	postCreate: function(){
+		// Init and set the default value to no formatting.  Update state will adjust it
+		// as needed.
+		this.inherited(arguments);
+		this.set("value", "noFormat", false);
+	},
+
+	getLabel: function(value, name){
+		// summary:
+		//		Function used to generate the labels of the format dropdown
+		//		will return a formatted, or plain label based on the value
+		//		of the plainText option.
+		// value: String
+		//		The 'insert value' associated with a name
+		// name: String
+		//		The text name of the value
+		if(this.plainText){
+			return name;
+		}else{
+			return "<" + value + ">" + name + "</" + value + ">";
+		}
+	},
+
+	_execCommand: function(editor, command, choice){
+		// summary:
+		//		Over-ride for default exec-command label.
+		// 		Allows us to treat 'none' as special.
+		if(choice === "noFormat"){
+			var start;
+			var end;
+			var sel = dijit.range.getSelection(editor.window);
+			if(sel && sel.rangeCount > 0){
+				var range = sel.getRangeAt(0);
+				var node, tag;
+				if(range){
+					start = range.startContainer;
+					end = range.endContainer;
+
+					// find containing nodes of start/end.
+					while(start && start !== editor.editNode && 
+						  start !== editor.document.body && 
+						  start.nodeType !== 1){
+						start = start.parentNode;
+					}
+
+					while(end && end !== editor.editNode && 
+						  end !== editor.document.body && 
+						  end.nodeType !== 1){
+						end = end.parentNode;
+					}
+
+					var processChildren = dojo.hitch(this, function(node, array){
+						if(node.childNodes && node.childNodes.length){
+							var i;
+							for(i = 0; i < node.childNodes.length; i++){
+								var c = node.childNodes[i];
+								if(c.nodeType == 1){
+									if(dojo.withGlobal(editor.window, "inSelection", dijit._editor.selection, [c])){
+										var tag = c.tagName? c.tagName.toLowerCase(): "";
+										if(dojo.indexOf(this.values, tag) !== -1){
+											array.push(c);
+										}
+										processChildren(c,array);
+									}
+								}
+							}
+						}
+					});
+
+					var unformatNodes = dojo.hitch(this, function(nodes){
+						// summary:
+						//		Internal function to clear format nodes.
+						// nodes:
+						//		The array of nodes to strip formatting from.
+						if(nodes && nodes.length){
+							editor.beginEditing();
+							while(nodes.length){
+								this._removeFormat(editor, nodes.pop());
+							}
+							editor.endEditing();
+						}
+					});
+
+					var clearNodes = [];
+					if(start == end){
+						//Contained within the same block, may be collapsed, but who cares, see if we
+						// have a block element to remove.
+						var block;
+						node = start;
+						while(node && node !== editor.editNode && node !== editor.document.body){
+							if(node.nodeType == 1){
+								tag = node.tagName? node.tagName.toLowerCase(): "";
+								if(dojo.indexOf(this.values, tag) !== -1){
+									block = node;
+									break;
+								}
+							}
+							node = node.parentNode;
+						}
+
+						//Also look for all child nodes in the selection that may need to be 
+						//cleared of formatting
+						processChildren(start, clearNodes);
+						if(block) { clearNodes = [block].concat(clearNodes); }
+						unformatNodes(clearNodes);
+					}else{
+						// Probably a multi select, so we have to process it.  Whee.
+						node = start;
+						while(dojo.withGlobal(editor.window, "inSelection", dijit._editor.selection, [node])){
+							if(node.nodeType == 1){
+								tag = node.tagName? node.tagName.toLowerCase(): "";
+								if(dojo.indexOf(this.values, tag) !== -1){
+									clearNodes.push(node);
+								}
+								processChildren(node,clearNodes);
+							}
+							node = node.nextSibling;
+						}
+						unformatNodes(clearNodes);
+					}
+					editor.onDisplayChanged();
+				}
+			}
+		}else{
+			editor.execCommand(command, choice);
+		}
+	},
+
+	_removeFormat: function(editor, node){
+		// summary:
+		//		function to remove the block format node.
+		// node:
+		//		The block format node to remove (and leave the contents behind)
+		if(editor.customUndo){
+			// So of course IE doesn't work right with paste-overs.
+			// We have to do this manually, which is okay since IE already uses
+			// customUndo and we turned it on for WebKit.  WebKit pasted funny, 
+			// so couldn't use the execCommand approach
+			while(node.firstChild){
+				dojo.place(node.firstChild, node, "before");
+			}
+			node.parentNode.removeChild(node);
+		}else{
+			// Everyone else works fine this way, a paste-over and is native
+			// undo friendly.
+			dojo.withGlobal(editor.window, 
+				 "selectElementChildren", dijit._editor.selection, [node]);
+			var html = 	dojo.withGlobal(editor.window, 
+				 "getSelectedHtml", dijit._editor.selection, [null]);
+			dojo.withGlobal(editor.window, 
+				 "selectElement", dijit._editor.selection, [node]);
+			editor.execCommand("inserthtml", html||"");
+		}
+	}
 });
-},updateState:function(){
-var _16=this.editor;
-var _17=this.command;
-if(!_16||!_16.isLoaded||!_17.length){
-return;
-}
-if(this.button){
-var _18;
-try{
-_18=_16.queryCommandValue(_17)||"";
-}
-catch(e){
-_18="";
-}
-var _19=dojo.isString(_18)&&_18.match(/'([^']*)'/);
-if(_19){
-_18=_19[1];
-}
-if(!_18&&_17==="formatBlock"){
-var _1a;
-var sel=dijit.range.getSelection(this.editor.window);
-if(sel&&sel.rangeCount>0){
-var _1b=sel.getRangeAt(0);
-if(_1b){
-_1a=_1b.endContainer;
-}
-}
-while(_1a&&_1a!==_16.editNode&&_1a!==_16.document){
-var tg=_1a.tagName?_1a.tagName.toLowerCase():"";
-if(tg&&dojo.indexOf(this.button.values,tg)>-1){
-_18=tg;
-break;
-}
-_1a=_1a.parentNode;
-}
-}
-if(_18!==this.button.attr("value")){
-this.button.attr("value",_18,false);
-}
-}
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-switch(o.args.name){
-case "fontName":
-case "fontSize":
-case "formatBlock":
-o.plugin=new dijit._editor.plugins.FontChoice({command:o.args.name,plainText:o.args.plainText?o.args.plainText:false});
-}
+
+// TODO: for 2.0, split into FontChoice plugin into three separate classes,
+// one for each command (and change registry below)
+dojo.declare("dijit._editor.plugins.FontChoice", dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides three drop downs for setting style in the editor
+	//		(font, font size, and format block), as controlled by command.
+	//
+	// description:
+	//		The commands provided by this plugin are:
+	//
+	//		* fontName
+	//	|		Provides a drop down to select from a list of font names
+	//		* fontSize
+	//	|		Provides a drop down to select from a list of font sizes
+	//		* formatBlock
+	//	|		Provides a drop down to select from a list of block styles
+	//	|
+	//
+	//		which can easily be added to an editor by including one or more of the above commands
+	//		in the `plugins` attribute as follows:
+	//
+	//	|	plugins="['fontName','fontSize',...]"
+	//
+	//		It is possible to override the default dropdown list by providing an Array for the `custom` property when
+	//		instantiating this plugin, e.g.
+	//
+	//	|	plugins="[{name:'dijit._editor.plugins.FontChoice', command:'fontName', custom:['Verdana','Myriad','Garamond']},...]"
+	//
+	//		Alternatively, for `fontName` only, `generic:true` may be specified to provide a dropdown with
+	//		[CSS generic font families](http://www.w3.org/TR/REC-CSS2/fonts.html#generic-font-families)
+	//
+	//		Note that the editor is often unable to properly handle font styling information defined outside
+	//		the context of the current editor instance, such as pre-populated HTML.
+
+	// useDefaultCommand: [protected] booleam
+	//		Override _Plugin.useDefaultCommand...
+	//		processing is handled by this plugin, not by dijit.Editor.
+	useDefaultCommand: false,
+
+	_initButton: function(){
+		// summary:
+		//		Overrides _Plugin._initButton(), to initialize the FilteringSelect+label in toolbar,
+		//		rather than a simple button.
+		// tags:
+		//		protected
+
+		// Create the widget to go into the toolbar (the so-called "button")
+		var clazz = {
+				fontName: dijit._editor.plugins._FontNameDropDown,
+				fontSize: dijit._editor.plugins._FontSizeDropDown,
+				formatBlock: dijit._editor.plugins._FormatBlockDropDown
+			}[this.command],
+		params = this.params;
+
+		// For back-compat reasons support setting custom values via "custom" parameter
+		// rather than "values" parameter
+		if(this.params.custom){
+			params.values = this.params.custom;
+		}
+
+		var editor = this.editor;
+		this.button = new clazz(dojo.delegate({dir: editor.dir, lang: editor.lang}, params));
+
+		// Reflect changes to the drop down in the editor
+		this.connect(this.button.select, "onChange", function(choice){
+			// User invoked change, since all internal updates set priorityChange to false and will
+			// not trigger an onChange event.
+			this.editor.focus();
+			
+			if(this.command == "fontName" && choice.indexOf(" ") != -1){ choice = "'" + choice + "'"; }
+
+			// Invoke, the editor already normalizes commands called through its
+			// execCommand.
+			if(this.button._execCommand){
+				this.button._execCommand(this.editor, this.command, choice);
+			}else{
+				this.editor.execCommand(this.command, choice);
+			}
+			
+			// Enable custom undo for webkit, needed for noFormat to work properly
+			// and still undo.
+			this.editor.customUndo = this.editor.customUndo || dojo.isWebKit;
+		});
+	},
+
+	updateState: function(){
+		// summary:
+		//		Overrides _Plugin.updateState().  This controls updating the menu
+		//		options to the right values on state changes in the document (that trigger a
+		//		test of the actions.)
+		//		It set value of drop down in toolbar to reflect font/font size/format block
+		//		of text at current caret position.
+		// tags:
+		//		protected
+		var _e = this.editor;
+		var _c = this.command;
+		if(!_e || !_e.isLoaded || !_c.length){ return; }
+		if(this.button){
+			var value;
+			try{
+				value = _e.queryCommandValue(_c) || "";
+			}catch(e){
+				//Firefox may throw error above if the editor is just loaded, ignore it
+				value = "";
+			}
+
+			// strip off single quotes, if any
+			var quoted = dojo.isString(value) && value.match(/'([^']*)'/);
+			if(quoted){ value = quoted[1]; }
+
+			if(_c === "formatBlock"){
+				if(!value || value == "p"){
+					// Some browsers (WebKit) doesn't actually get the tag info right.
+					// and IE returns paragraph when in a DIV!, so incorrect a lot,
+					// so we have double-check it.
+					value = null;
+					var elem;
+					// Try to find the current element where the caret is.
+					var sel = dijit.range.getSelection(this.editor.window);
+					if(sel && sel.rangeCount > 0){
+						var range = sel.getRangeAt(0);
+						if(range){
+							elem = range.endContainer;
+						}
+					}
+
+					// Okay, now see if we can find one of the formatting types we're in.
+					while(elem && elem !== _e.editNode && elem !== _e.document){
+						var tg = elem.tagName?elem.tagName.toLowerCase():"";
+						if(tg && dojo.indexOf(this.button.values, tg) > -1){
+							value = tg;
+							break;
+						}
+						elem = elem.parentNode;
+					}
+					if(!value){
+						// Still no value, so lets select 'none'.
+						value = "noFormat";
+					}
+				}else{
+					// Check that the block format is one allowed, if not,
+					// null it so that it gets set to empty.
+					if(dojo.indexOf(this.button.values, value) < 0){
+						value = "noFormat";
+					}
+				}
+			}
+			if(value !== this.button.get("value")){
+				// Set the value, but denote it is not a priority change, so no
+				// onchange fires.
+				this.button.set('value', value, false);
+			}
+		}
+	}
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	switch(o.args.name){
+	case "fontName": case "fontSize": case "formatBlock":
+		o.plugin = new dijit._editor.plugins.FontChoice({
+			command: o.args.name,
+			plainText: o.args.plainText?o.args.plainText:false
+		});
+	}
 });
-}
diff --git a/dijit/_editor/plugins/FullScreen.js b/dijit/_editor/plugins/FullScreen.js
old mode 100644
new mode 100755
index 25c9561..c4203a3
--- a/dijit/_editor/plugins/FullScreen.js
+++ b/dijit/_editor/plugins/FullScreen.js
@@ -1,198 +1,426 @@
-/*
-	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
-*/
+dojo.provide("dijit._editor.plugins.FullScreen");
 
+dojo.require("dojo.window");
+dojo.require("dojo.i18n");
 
-if(!dojo._hasResource["dijit._editor.plugins.FullScreen"]){
-dojo._hasResource["dijit._editor.plugins.FullScreen"]=true;
-dojo.provide("dijit._editor.plugins.FullScreen");
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.form.Button");
-dojo.require("dojo.i18n");
-dojo.requireLocalization("dijit._editor","commands",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit._editor.plugins.FullScreen",dijit._editor._Plugin,{zIndex:500,_origState:null,_origiFrameState:null,_resizeHandle:null,isFullscreen:false,toggle:function(){
-this.button.attr("checked",!this.button.attr("checked"));
-},_initButton:function(){
-var _1=dojo.i18n.getLocalization("dijit._editor","commands");
-this.button=new dijit.form.ToggleButton({label:_1["fullScreen"],showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"FullScreen",tabIndex:"-1",onChange:dojo.hitch(this,"_setFullScreen")});
-},setEditor:function(_2){
-this.editor=_2;
-this._initButton();
-this.editor.addKeyHandler(dojo.keys.F11,true,true,dojo.hitch(this,function(e){
-this.toggle();
-dojo.stopEvent(e);
-setTimeout(dojo.hitch(this,function(){
-this.editor.focus();
-}),250);
-return true;
-}));
-this.connect(this.editor.domNode,"onkeydown","_containFocus");
-},_containFocus:function(e){
-if(this.isFullscreen){
-var ed=this.editor;
-if(!ed.isTabIndent&&ed._fullscreen_oldOnKeyDown&&e.keyCode===dojo.keys.TAB){
-var f=dijit.getFocus();
-var _3=this._getAltViewNode();
-if(f.node==ed.iframe||(_3&&f.node===_3)){
-setTimeout(dojo.hitch(this,function(){
-ed.toolbar.focus();
-}),10);
-}else{
-if(_3&&dojo.style(ed.iframe,"display")==="none"){
-setTimeout(dojo.hitch(this,function(){
-dijit.focus(_3);
-}),10);
-}else{
-setTimeout(dojo.hitch(this,function(){
-ed.focus();
-}),10);
-}
-}
-dojo.stopEvent(e);
-}else{
-if(ed._fullscreen_oldOnKeyDown){
-ed._fullscreen_oldOnKeyDown(e);
-}
-}
-}
-},_resizeEditor:function(){
-var vp=dijit.getViewport();
-dojo.marginBox(this.editor.domNode,{w:vp.w,h:vp.h});
-var _4=dojo.marginBox(this.editor.toolbar.domNode);
-var _5=dojo._getPadBorderExtents(this.editor.domNode);
-var _6=vp.h-(_4.h+_5.h);
-dojo.marginBox(this.editor.iframe.parentNode,{h:_6});
-dojo.marginBox(this.editor.iframe,{h:_6});
-},_getAltViewNode:function(){
-},_setFullScreen:function(_7){
-var vp=dijit.getViewport();
-var ed=this.editor;
-var _8=dojo.body();
-var _9=ed.domNode.parentNode;
-this.isFullscreen=_7;
-if(_7){
-while(_9&&_9!==dojo.body()){
-dojo.addClass(_9,"dijitForceStatic");
-_9=_9.parentNode;
-}
-this._editorResizeHolder=this.editor.resize;
-ed.resize=function(){
-};
-ed._fullscreen_oldOnKeyDown=ed.onKeyDown;
-ed.onKeyDown=dojo.hitch(this,this._containFocus);
-this._origState={};
-this._origiFrameState={};
-var _a=ed.domNode,_b=_a&&_a.style||{};
-this._origState={width:_b.width||"",height:_b.height||"",top:dojo.style(_a,"top")||"",left:dojo.style(_a,"left")||"",position:dojo.style(_a,"position")||"static"};
-var _c=ed.iframe,_d=_c&&_c.style||{};
-var bc=dojo.style(ed.iframe,"backgroundColor");
-this._origiFrameState={backgroundColor:bc||"transparent",width:_d.width||"auto",height:_d.height||"auto",zIndex:_d.zIndex||""};
-dojo.style(ed.domNode,{position:"absolute",top:"0px",left:"0px",zIndex:this.zIndex,width:vp.w+"px",height:vp.h+"px"});
-dojo.style(ed.iframe,{height:"100%",width:"100%",zIndex:this.zIndex,backgroundColor:bc!=="transparent"&&bc!=="rgba(0, 0, 0, 0)"?bc:"white"});
-dojo.style(ed.iframe.parentNode,{height:"95%",width:"100%"});
-if(_8.style&&_8.style.overflow){
-this._oldOverflow=dojo.style(_8,"overflow");
-}else{
-this._oldOverflow="";
-}
-if(dojo.isIE&&!dojo.isQuirks){
-if(_8.parentNode&&_8.parentNode.style&&_8.parentNode.style.overflow){
-this._oldBodyParentOverflow=_8.parentNode.style.overflow;
-}else{
-this._oldBodyParentOverflow="scroll";
-}
-dojo.style(_8.parentNode,"overflow","hidden");
-}
-dojo.style(_8,"overflow","hidden");
-var _e=function(){
-var vp=dijit.getViewport();
-if("_prevW" in this&&"_prevH" in this){
-if(vp.w===this._prevW&&vp.h===this._prevH){
-return;
-}
-}else{
-this._prevW=vp.w;
-this._prevH=vp.h;
-}
-if(this._resizer){
-clearTimeout(this._resizer);
-delete this._resizer;
-}
-this._resizer=setTimeout(dojo.hitch(this,function(){
-delete this._resizer;
-this._resizeEditor();
-}),10);
-};
-this._resizeHandle=dojo.connect(window,"onresize",this,_e);
-this._resizeEditor();
-var dn=this.editor.toolbar.domNode;
-setTimeout(function(){
-dijit.scrollIntoView(dn);
-},250);
-}else{
-if(this._editorResizeHolder){
-this.editor.resize=this._editorResizeHolder;
-}
-if(!this._origState&&!this._origiFrameState){
-return;
-}
-if(ed._fullscreen_oldOnKeyDown){
-ed.onKeyDown=ed._fullscreen_oldOnKeyDown;
-delete ed._fullscreen_oldOnKeyDown;
-}
-if(this._resizeHandle){
-dojo.disconnect(this._resizeHandle);
-this._resizeHandle=null;
-}
-if(this._rst){
-clearTimeout(this._rst);
-this._rst=null;
-}
-while(_9&&_9!==dojo.body()){
-dojo.removeClass(_9,"dijitForceStatic");
-_9=_9.parentNode;
-}
-var _f=this;
-setTimeout(function(){
-if(dojo.isIE&&!dojo.isQuirks){
-_8.parentNode.style.overflow=_f._oldBodyParentOverflow;
-delete _f._oldBodyParentOverflow;
-}
-dojo.style(_8,"overflow",_f._oldOverflow);
-delete _f._oldOverflow;
-dojo.style(ed.domNode,_f._origState);
-dojo.style(ed.iframe.parentNode,{height:"",width:""});
-dojo.style(ed.iframe,_f._origiFrameState);
-delete _f._origState;
-delete _f._origiFrameState;
-ed.resize();
-var _10=dijit.getEnclosingWidget(ed.domNode.parentNode);
-if(_10&&_10.resize){
-_10.resize();
-}
-dijit.scrollIntoView(_f.editor.toolbar.domNode);
-},100);
-}
-},destroy:function(){
-if(this._resizeHandle){
-dojo.disconnect(this._resizeHandle);
-this._resizeHandle=null;
-}
-if(this._resizer){
-clearTimeout(this._resizer);
-this._resizer=null;
-}
-this.inherited(arguments);
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _11=o.args.name.toLowerCase();
-if(_11==="fullscreen"){
-o.plugin=new dijit._editor.plugins.FullScreen({zIndex:("zIndex" in o.args)?o.args.zIndex:500});
-}
+
+dojo.requireLocalization("dijit._editor", "commands");
+
+dojo.declare("dijit._editor.plugins.FullScreen",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides FullScreen cabability to the editor.  When
+	//		toggled on, it will render the editor into the full window and
+	//		overlay everything.  It also binds to the hotkey: CTRL-SHIFT-F11
+	//		for toggling fullscreen mode.
+
+	// zIndex: [public] Number
+	//		zIndex value used for overlaying the full page.
+	//		default is 500.
+	zIndex: 500,
+
+	// _origState: [private] Object
+	//		The original view state of the editor.
+	_origState: null,
+
+	// _origiFrameState: [private] Object
+	//		The original view state of the iframe of the editor.
+	_origiFrameState: null,
+
+	// _resizeHandle: [private] Object
+	//		Connection point used for handling resize when window resizes.
+	_resizeHandle: null,
+
+	// isFullscreen: [const] boolean
+	//		Read-Only variable used to denote of the editor is in fullscreen mode or not.
+	isFullscreen: false,
+
+	toggle: function(){
+		// summary:
+		//		Function to allow programmatic toggling of the view.
+		this.button.set("checked", !this.button.get("checked"));
+	},
+
+	_initButton: function(){
+		// summary:
+		//		Over-ride for creation of the resize button.
+		var strings = dojo.i18n.getLocalization("dijit._editor", "commands"),
+			editor = this.editor;
+		this.button = new dijit.form.ToggleButton({
+			label: strings["fullScreen"],
+			dir: editor.dir,
+			lang: editor.lang,
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "FullScreen",
+			tabIndex: "-1",
+			onChange: dojo.hitch(this, "_setFullScreen")
+		});
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._initButton();
+
+		this.editor.addKeyHandler(dojo.keys.F11, true, true, dojo.hitch(this, function(e){
+			// Enable the CTRL-SHIFT-F11 hotkey for fullscreen mode.
+			this.toggle();
+			dojo.stopEvent(e);
+			setTimeout(dojo.hitch(this, function(){this.editor.focus();}), 250);
+			return true;
+		}));
+		this.connect(this.editor.domNode, "onkeydown", "_containFocus");
+	},
+
+	_containFocus: function(e){
+		// summary:
+		//		When in Full Screen mode, it's good to try and retain focus in the editor
+		//		so this function is intended to try and constrain the TAB key.
+		// e: Event
+		//		The key event.
+		// tags:
+		//		private
+		if(this.isFullscreen){
+			var ed = this.editor;
+			if(!ed.isTabIndent &&
+				ed._fullscreen_oldOnKeyDown &&
+				e.keyCode === dojo.keys.TAB){
+				// If we're in fullscreen mode, we want to take over how tab moves focus a bit.
+				// to keep it within the editor since it's hiding the rest of the page.
+				// IE hates changing focus IN the event handler, so need to put calls
+				// in a timeout.  Gotta love IE.
+				// Also need to check for alternate view nodes if present and active.
+				var f = dijit.getFocus();
+				var avn = this._getAltViewNode();
+				if(f.node == ed.iframe ||
+					(avn && f.node === avn)){
+					setTimeout(dojo.hitch(this, function(){
+						ed.toolbar.focus();
+					}), 10);
+				}else{
+					if(avn && dojo.style(ed.iframe, "display") === "none"){
+						setTimeout(dojo.hitch(this, function(){
+							dijit.focus(avn);
+						}), 10);
+					}else{
+						setTimeout(dojo.hitch(this, function(){
+							ed.focus();
+						}), 10);
+					}
+				}
+				dojo.stopEvent(e);
+			}else if(ed._fullscreen_oldOnKeyDown){
+				// Only call up when it's a different function.  Traps corner case event issue
+				// on IE which caused stack overflow on handler cleanup.
+				ed._fullscreen_oldOnKeyDown(e);
+			}
+		}
+	},
+
+	_resizeEditor: function(){
+		// summary:
+		//		Function to handle resizing the editor as the viewport
+		//		resizes (window scaled)
+		// tags:
+		//		private
+		var vp = dojo.window.getBox();
+		dojo.marginBox(this.editor.domNode, {
+			w: vp.w,
+			h: vp.h
+		});
+
+		//Adjust the inernal heights too, as they can be a bit off.
+		var hHeight = this.editor.getHeaderHeight();
+		var fHeight = this.editor.getFooterHeight();
+		var extents = dojo._getPadBorderExtents(this.editor.domNode);
+		var fcpExtents = dojo._getPadBorderExtents(this.editor.iframe.parentNode);
+		var fcmExtents = dojo._getMarginExtents(this.editor.iframe.parentNode);
+		
+		var cHeight = vp.h - (hHeight + extents.h + fHeight);
+		dojo.marginBox(this.editor.iframe.parentNode, {
+			h: cHeight,
+			w: vp.w
+		});
+		dojo.marginBox(this.editor.iframe, {
+			h: cHeight - (fcpExtents.h + fcmExtents.h)
+		});
+	},
+
+	_getAltViewNode: function(){
+		// summary:
+		//		This function is intended as a hook point for setting an
+		//		alternate view node for when in full screen mode and the
+		//		editable iframe is hidden.
+		// tags:
+		//		protected.
+	},
+
+	_setFullScreen: function(full){
+		// summary:
+		//		Function to handle toggling between full screen and
+		//		regular view.
+		// tags:
+		//		private
+		var vp = dojo.window.getBox();
+
+		//Alias this for shorter code.
+		var ed = this.editor;
+		var body = dojo.body();
+		var editorParent = ed.domNode.parentNode;
+
+		this.isFullscreen = full;
+
+		if(full){
+			//Parent classes can royally screw up this plugin, so we 
+			//have to set eveything to position static.
+			while(editorParent && editorParent !== dojo.body()){
+				dojo.addClass(editorParent, "dijitForceStatic");
+				editorParent = editorParent.parentNode;
+			}
+
+			// Save off the resize function.  We want to kill its behavior.
+			this._editorResizeHolder = this.editor.resize;
+			ed.resize = function() {} ;
+
+			// Try to constrain focus control.
+			ed._fullscreen_oldOnKeyDown = ed.onKeyDown;
+			ed.onKeyDown = dojo.hitch(this, this._containFocus);
+
+			this._origState = {};
+			this._origiFrameState = {};
+
+			// Store the basic editor state we have to restore later.
+			// Not using dojo.style here, had problems, didn't
+			// give me stuff like 100%, gave me pixel calculated values.
+			// Need the exact original values.
+			var domNode = ed.domNode,
+				domStyle = domNode && domNode.style || {};
+			this._origState = {
+				width: domStyle.width || "",
+				height: domStyle.height || "",
+				top: dojo.style(domNode, "top") || "",
+				left: dojo.style(domNode, "left") || "",
+				position: dojo.style(domNode, "position") || "static",
+				marginBox: dojo.marginBox(ed.domNode)
+			};
+
+			// Store the iframe state we have to restore later.
+			// Not using dojo.style here, had problems, didn't
+			// give me stuff like 100%, gave me pixel calculated values.
+			// Need the exact original values.
+			var iframe = ed.iframe,
+				iframeStyle = iframe && iframe.style || {};
+
+			var bc = dojo.style(ed.iframe, "backgroundColor");
+			this._origiFrameState = {
+				backgroundColor: bc || "transparent",
+				width: iframeStyle.width || "auto",
+				height: iframeStyle.height || "auto",
+				zIndex: iframeStyle.zIndex || ""
+			};
+
+			// Okay, size everything.
+			dojo.style(ed.domNode, {
+				position: "absolute",
+				top: "0px",
+				left: "0px",
+				zIndex: this.zIndex,
+				width: vp.w + "px",
+				height: vp.h + "px"
+			});
+
+			dojo.style(ed.iframe, {
+				height: "100%",
+				width: "100%",
+				zIndex: this.zIndex,
+				backgroundColor: bc !== "transparent" &&
+					bc !== "rgba(0, 0, 0, 0)"?bc:"white"
+			});
+
+			dojo.style(ed.iframe.parentNode, {
+				height: "95%",
+				width: "100%"
+			});
+
+			// Store the overflow state we have to restore later.
+			// IE had issues, so have to check that it's defined.  Ugh.
+			if(body.style && body.style.overflow){
+				this._oldOverflow = dojo.style(body, "overflow");
+			}else{
+				this._oldOverflow = "";
+			}
+
+			if(dojo.isIE && !dojo.isQuirks){
+				// IE will put scrollbars in anyway, html (parent of body)
+				// also controls them in standards mode, so we have to
+				// remove them, argh.
+				if(body.parentNode &&
+					body.parentNode.style &&
+					body.parentNode.style.overflow){
+					this._oldBodyParentOverflow = body.parentNode.style.overflow;
+				}else{
+					try{
+						this._oldBodyParentOverflow = dojo.style(body.parentNode, "overflow");
+					}catch(e){
+						this._oldBodyParentOverflow = "scroll";
+					}
+				}
+				dojo.style(body.parentNode, "overflow", "hidden");
+			}
+			dojo.style(body, "overflow", "hidden");
+
+			var resizer = function(){
+				// function to handle resize events.
+				// Will check current VP and only resize if
+				// different.
+				var vp = dojo.window.getBox();
+				if("_prevW" in this && "_prevH" in this){
+					// No actual size change, ignore.
+					if(vp.w === this._prevW && vp.h === this._prevH){
+						return;
+					}
+				}else{
+					this._prevW = vp.w;
+					this._prevH = vp.h;
+				}
+				if(this._resizer){
+					clearTimeout(this._resizer);
+					delete this._resizer;
+				}
+				// Timeout it to help avoid spamming resize on IE.
+				// Works for all browsers.
+				this._resizer = setTimeout(dojo.hitch(this, function(){
+					delete this._resizer;
+					this._resizeEditor();
+				}), 10);
+			};
+			this._resizeHandle = dojo.connect(window, "onresize", this, resizer);
+
+			// Also monitor for direct calls to resize and adapt editor.
+			this._resizeHandle2 = dojo.connect(ed, "resize", dojo.hitch(this, function(){
+				if(this._resizer){
+					clearTimeout(this._resizer);
+					delete this._resizer;
+				}
+				this._resizer = setTimeout(dojo.hitch(this, function(){
+					delete this._resizer;
+					this._resizeEditor();
+				}), 10);
+			}));
+
+			// Call it once to work around IE glitchiness.  Safe for other browsers too.
+			this._resizeEditor();
+			var dn = this.editor.toolbar.domNode;
+			setTimeout(function(){dojo.window.scrollIntoView(dn);}, 250);
+		}else{
+			if(this._resizeHandle){
+				// Cleanup resizing listeners
+				dojo.disconnect(this._resizeHandle);
+				this._resizeHandle = null;
+			}
+			if(this._resizeHandle2){
+				// Cleanup resizing listeners
+				dojo.disconnect(this._resizeHandle2);
+				this._resizeHandle2 = null;
+			}
+			if(this._rst){
+				clearTimeout(this._rst);
+				this._rst = null;
+			}
+			
+			//Remove all position static class assigns.
+			while(editorParent && editorParent !== dojo.body()){
+				dojo.removeClass(editorParent, "dijitForceStatic");
+				editorParent = editorParent.parentNode;
+			}
+			
+			// Restore resize function
+			if(this._editorResizeHolder){
+				this.editor.resize = this._editorResizeHolder;
+			}
+
+			if(!this._origState && !this._origiFrameState){
+				// If we actually didn't toggle, then don't do anything.
+				return;
+			}
+			if(ed._fullscreen_oldOnKeyDown){
+				ed.onKeyDown = ed._fullscreen_oldOnKeyDown;
+				delete ed._fullscreen_oldOnKeyDown;
+			}
+
+			// Add a timeout to make sure we don't have a resize firing in the
+			// background at the time of minimize.
+			var self = this;
+			setTimeout(function(){
+				// Restore all the editor state.
+				var mb = self._origState.marginBox;
+				var oh = self._origState.height;
+				if(dojo.isIE && !dojo.isQuirks){
+					body.parentNode.style.overflow = self._oldBodyParentOverflow;
+					delete self._oldBodyParentOverflow;
+				}
+				dojo.style(body, "overflow", self._oldOverflow);
+				delete self._oldOverflow;
+
+				dojo.style(ed.domNode, self._origState);
+				dojo.style(ed.iframe.parentNode, {
+					height: "",
+					width: ""
+				});
+				dojo.style(ed.iframe, self._origiFrameState);
+				delete self._origState;
+				delete self._origiFrameState;
+				// In case it is contained in a layout and the layout changed size,
+				// go ahead and call resize.
+				var pWidget = dijit.getEnclosingWidget(ed.domNode.parentNode);
+				if(pWidget && pWidget.resize){
+					pWidget.resize();
+				}else{
+					if(!oh || oh.indexOf("%") < 0){
+						// Resize if the original size wasn't set
+						// or wasn't in percent.  Timeout is to avoid
+						// an IE crash in unit testing.
+						setTimeout(dojo.hitch(this, function(){ed.resize({h: mb.h});}), 0);		
+					}
+				}
+				dojo.window.scrollIntoView(self.editor.toolbar.domNode);
+			}, 100);
+		}
+	},
+
+	destroy: function(){
+		// summary:
+		//		Over-ride to ensure the resize handle gets cleaned up.
+		if(this._resizeHandle){
+			// Cleanup resizing listeners
+			dojo.disconnect(this._resizeHandle);
+			this._resizeHandle = null;
+		}
+		if(this._resizeHandle2){
+			// Cleanup resizing listeners
+			dojo.disconnect(this._resizeHandle2);
+			this._resizeHandle2 = null;
+		}
+		if(this._resizer){
+			clearTimeout(this._resizer);
+			this._resizer = null;
+		}
+		this.inherited(arguments);
+	}
+});
+
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "fullscreen"){
+		o.plugin = new dijit._editor.plugins.FullScreen({
+			zIndex: ("zIndex" in o.args)?o.args.zIndex:500
+		});
+	}
 });
-}
diff --git a/dijit/_editor/plugins/LinkDialog.js b/dijit/_editor/plugins/LinkDialog.js
index 4404276..c1099d6 100644
--- a/dijit/_editor/plugins/LinkDialog.js
+++ b/dijit/_editor/plugins/LinkDialog.js
@@ -1,13 +1,5 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._editor.plugins.LinkDialog"]){
-dojo._hasResource["dijit._editor.plugins.LinkDialog"]=true;
 dojo.provide("dijit._editor.plugins.LinkDialog");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._editor._Plugin");
@@ -18,190 +10,493 @@ dojo.require("dijit.form.Select");
 dojo.require("dijit._editor.range");
 dojo.require("dojo.i18n");
 dojo.require("dojo.string");
-dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.requireLocalization("dijit._editor","LinkDialog",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit._editor.plugins.LinkDialog",dijit._editor._Plugin,{buttonClass:dijit.form.DropDownButton,useDefaultCommand:false,urlRegExp:"((https?|ftps?|file)\\://|./|/|)(/[a-zA-Z]{1,1}:/|)(((?:(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)\\.)*(?:[a-zA-Z](?:[-\\da-zA-Z]{0,80}[\\da-zA-Z])?)\\.?)|(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])|(0[xX]0*[\\da-fA-F]?[\\da-fA-F]\\.){3}0[xX]0*[\\da-fA-F]?[\\da-fA-F]|(0+[0-3][0-7][0-7]\\.){3}0+ [...]
-var _1=this;
-this.tag=this.command=="insertImage"?"img":"a";
-var _2=dojo.mixin(dojo.i18n.getLocalization("dijit","common",this.lang),dojo.i18n.getLocalization("dijit._editor","LinkDialog",this.lang));
-var _3=(this.dropDown=new dijit.TooltipDialog({title:_2[this.command+"Title"],execute:dojo.hitch(this,"setValue"),onOpen:function(){
-_1._onOpenDialog();
-dijit.TooltipDialog.prototype.onOpen.apply(this,arguments);
-},onCancel:function(){
-setTimeout(dojo.hitch(_1,"_onCloseDialog"),0);
-}}));
-_2.urlRegExp=this.urlRegExp;
-_2.id=dijit.getUniqueId(this.editor.id);
-this._uniqueId=_2.id;
-this._setContent(_3.title+"<div style='border-bottom: 1px black solid;padding-bottom:2pt;margin-bottom:4pt'></div>"+dojo.string.substitute(this.linkDialogTemplate,_2));
-_3.startup();
-this._urlInput=dijit.byId(this._uniqueId+"_urlInput");
-this._textInput=dijit.byId(this._uniqueId+"_textInput");
-this._setButton=dijit.byId(this._uniqueId+"_setButton");
-this.connect(dijit.byId(this._uniqueId+"_cancelButton"),"onClick",function(){
-this.dropDown.onCancel();
+dojo.requireLocalization("dijit", "common");
+dojo.requireLocalization("dijit._editor", "LinkDialog");
+
+dojo.declare("dijit._editor.plugins.LinkDialog", dijit._editor._Plugin, {
+	// summary:
+	//		This plugin provides the basis for an 'anchor' (link) dialog and an extension of it
+	//		provides the image link dialog.
+	//
+	// description:
+	//		The command provided by this plugin is:
+	//		* createLink
+
+	// Override _Plugin.buttonClass.   This plugin is controlled by a DropDownButton
+	// (which triggers a TooltipDialog).
+	buttonClass: dijit.form.DropDownButton,
+
+	// Override _Plugin.useDefaultCommand... processing is handled by this plugin, not by dijit.Editor.
+	useDefaultCommand: false,
+
+	// urlRegExp: [protected] String
+	//		Used for validating input as correct URL.  While file:// urls are not terribly
+	//		useful, they are technically valid.
+	urlRegExp: "((https?|ftps?|file)\\://|\./|/|)(/[a-zA-Z]{1,1}:/|)(((?:(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)\\.)*(?:[a-zA-Z](?:[-\\da-zA-Z]{0,80}[\\da-zA-Z])?)\\.?)|(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])|(0[xX]0*[\\da-fA-F]?[\\da-fA-F]\\.){3}0[xX]0*[\\da-fA-F]?[\\da-fA-F]|(0+[0-3][0-7][0-7]\\.){3}0+[0-3][0-7][0-7]|(0|[1-9]\\d{0,8}|[1-3]\\d{9}|4[01]\\d{8}|42[0-8]\\d{7}|429[0-3]\\d{6}|4294[0-8]\\d{5}|42949[0-5]\\d{4}|429496[0-6] [...]
+
+	// emailRegExp: [protected] String
+	//		Used for validating input as correct email address.  Taken from dojox.validate
+	emailRegExp:  "<?(mailto\\:)([!#-'*+\\-\\/-9=?A-Z^-~]+[.])*[!#-'*+\\-\\/-9=?A-Z^-~]+" /*username*/ + "@" +  
+        "((?:(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)\\.)+(?:[a-zA-Z](?:[-\\da-zA-Z]{0,6}[\\da-zA-Z])?)\\.?)|localhost|^[^-][a-zA-Z0-9_-]*>?",	// host.
+
+	// htmlTemplate: [protected] String
+	//		String used for templating the HTML to insert at the desired point.
+	htmlTemplate: "<a href=\"${urlInput}\" _djrealurl=\"${urlInput}\"" +
+		" target=\"${targetSelect}\"" +
+		">${textInput}</a>",
+
+	// tag: [protected] String
+	//		Tag used for the link type.
+	tag: "a",
+
+	// _hostRxp [private] RegExp
+	//		Regular expression used to validate url fragments (ip address, hostname, etc)
+	_hostRxp:  new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"),
+
+	// _userAtRxp [private] RegExp
+	//		Regular expression used to validate e-mail address fragment.
+	_userAtRxp: new RegExp("^([!#-'*+\\-\\/-9=?A-Z^-~]+[.])*[!#-'*+\\-\\/-9=?A-Z^-~]+@", "i"),
+
+	// linkDialogTemplate: [protected] String
+	//		Template for contents of TooltipDialog to pick URL
+	linkDialogTemplate: [
+		"<table><tr><td>",
+		"<label for='${id}_urlInput'>${url}</label>",
+		"</td><td>",
+		"<input dojoType='dijit.form.ValidationTextBox' required='true' " +
+		"id='${id}_urlInput' name='urlInput' intermediateChanges='true'>",
+		"</td></tr><tr><td>",
+		"<label for='${id}_textInput'>${text}</label>",
+		"</td><td>",
+		"<input dojoType='dijit.form.ValidationTextBox' required='true' id='${id}_textInput' " +
+		"name='textInput' intermediateChanges='true'>",
+		"</td></tr><tr><td>",
+		"<label for='${id}_targetSelect'>${target}</label>",
+		"</td><td>",
+		"<select id='${id}_targetSelect' name='targetSelect' dojoType='dijit.form.Select'>",
+		"<option selected='selected' value='_self'>${currentWindow}</option>",
+		"<option value='_blank'>${newWindow}</option>",
+		"<option value='_top'>${topWindow}</option>",
+		"<option value='_parent'>${parentWindow}</option>",
+		"</select>",
+		"</td></tr><tr><td colspan='2'>",
+		"<button dojoType='dijit.form.Button' type='submit' id='${id}_setButton'>${set}</button>",
+		"<button dojoType='dijit.form.Button' type='button' id='${id}_cancelButton'>${buttonCancel}</button>",
+		"</td></tr></table>"
+	].join(""),
+
+	_initButton: function(){
+		// Override _Plugin._initButton() to initialize DropDownButton and TooltipDialog.
+		var _this = this;
+		this.tag = this.command == 'insertImage' ? 'img' : 'a';
+		var messages = dojo.mixin(dojo.i18n.getLocalization("dijit", "common", this.lang),
+			dojo.i18n.getLocalization("dijit._editor", "LinkDialog", this.lang));
+		var dropDown = (this.dropDown = new dijit.TooltipDialog({
+			title: messages[this.command + "Title"],
+			execute: dojo.hitch(this, "setValue"),
+			onOpen: function(){
+				_this._onOpenDialog();
+				dijit.TooltipDialog.prototype.onOpen.apply(this, arguments);
+			},
+			onCancel: function(){
+				setTimeout(dojo.hitch(_this, "_onCloseDialog"),0);
+			}
+		}));
+		messages.urlRegExp = this.urlRegExp;
+		messages.id = dijit.getUniqueId(this.editor.id);
+		this._uniqueId = messages.id;
+		this._setContent(dropDown.title +
+			"<div style='border-bottom: 1px black solid;padding-bottom:2pt;margin-bottom:4pt'></div>" +
+			dojo.string.substitute(this.linkDialogTemplate, messages));
+		dropDown.startup();
+		this._urlInput = dijit.byId(this._uniqueId + "_urlInput");
+		this._textInput = dijit.byId(this._uniqueId + "_textInput");
+		this._setButton = dijit.byId(this._uniqueId + "_setButton");
+		this.connect(dijit.byId(this._uniqueId + "_cancelButton"), "onClick", function(){
+			this.dropDown.onCancel();
+		});
+		if(this._urlInput){
+			this.connect(this._urlInput, "onChange", "_checkAndFixInput");
+		}
+		if(this._textInput){
+			this.connect(this._textInput, "onChange", "_checkAndFixInput");
+		}
+
+		// Build up the dual check for http/https/file:, and mailto formats.
+		this._urlRegExp = new RegExp("^" + this.urlRegExp + "$", "i");
+		this._emailRegExp = new RegExp("^" + this.emailRegExp + "$", "i");
+		this._urlInput.isValid = dojo.hitch(this, function(){
+			// Function over-ride of isValid to test if the input matches a url or a mailto style link.
+			var value = this._urlInput.get("value");
+			return this._urlRegExp.test(value) || this._emailRegExp.test(value);
+		});
+
+		this._connectTagEvents();
+		this.inherited(arguments);
+	},
+
+	_checkAndFixInput: function(){
+		// summary:
+		//		A function to listen for onChange events and test the input contents
+		//		for valid information, such as valid urls with http/https/ftp and if
+		//		not present, try and guess if the input url is relative or not, and if
+		//		not, append http:// to it.  Also validates other fields as determined by
+		//		the internal _isValid function.
+		var self = this;
+		var url = this._urlInput.get("value");
+		var fixupUrl = function(url){
+			var appendHttp = false;
+			var appendMailto = false;
+			if(url && url.length > 1){
+				url = dojo.trim(url);
+				if(url.indexOf("mailto:") !== 0){
+					if(url.indexOf("/") > 0){
+						if(url.indexOf("://") === -1){
+							// Check that it doesn't start with / or ./, which would
+							// imply 'target server relativeness'
+							if(url.charAt(0) !== '/' && url.indexOf("./") !== 0){
+								if(self._hostRxp.test(url)){
+									appendHttp = true;
+								}
+							}
+						}
+					}else if(self._userAtRxp.test(url)){
+						// If it looks like a foo@, append a mailto.
+						appendMailto = true;
+					}
+				}
+			}
+			if(appendHttp){
+				self._urlInput.set("value", "http://" + url);
+			}
+			if(appendMailto){
+				self._urlInput.set("value", "mailto:" + url);
+			}
+			self._setButton.set("disabled", !self._isValid());
+		};
+		if(this._delayedCheck){
+			clearTimeout(this._delayedCheck);
+			this._delayedCheck = null;
+		}
+		this._delayedCheck = setTimeout(function(){
+			fixupUrl(url);
+		}, 250);
+	},
+
+	_connectTagEvents: function(){
+		// summary:
+		//		Over-ridable function that connects tag specific events.
+		this.editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){
+			this.connect(this.editor.editNode, "ondblclick", this._onDblClick);
+		}));
+	},
+
+	_isValid: function(){
+		// summary:
+		//		Internal function to allow validating of the inputs
+		//		for a link to determine if set should be disabled or not
+		// tags:
+		//		protected
+		return this._urlInput.isValid() && this._textInput.isValid();
+	},
+
+	_setContent: function(staticPanel){
+		// summary:
+		//		Helper for _initButton above.   Not sure why it's a separate method.
+		this.dropDown.set('content', staticPanel);
+	},
+
+	_checkValues: function(args){
+		// summary:
+		//		Function to check the values in args and 'fix' them up as needed.
+		// args: Object
+		//		Content being set.		
+		// tags: 
+		//		protected
+		if(args && args.urlInput){
+			args.urlInput = args.urlInput.replace(/"/g, """);
+		}
+		return args;
+	},
+
+	setValue: function(args){
+		// summary:
+		//		Callback from the dialog when user presses "set" button.
+		// tags:
+		//		private
+		//TODO: prevent closing popup if the text is empty
+		this._onCloseDialog();
+		if(dojo.isIE){ //see #4151
+			var sel = dijit.range.getSelection(this.editor.window);
+			var range = sel.getRangeAt(0);
+			var a = range.endContainer;
+			if(a.nodeType === 3){
+				// Text node, may be the link contents, so check parent.
+				// This plugin doesn't really support nested HTML elements
+				// in the link, it assumes all link content is text.
+				a = a.parentNode;
+			}
+			if(a && (a.nodeName && a.nodeName.toLowerCase() !== this.tag)){
+				// Stll nothing, one last thing to try on IE, as it might be 'img'
+				// and thus considered a control.
+				a = dojo.withGlobal(this.editor.window,
+					"getSelectedElement", dijit._editor.selection, [this.tag]);
+			}
+			if(a && (a.nodeName && a.nodeName.toLowerCase() === this.tag)){
+				// Okay, we do have a match.  IE, for some reason, sometimes pastes before
+				// instead of removing the targetted paste-over element, so we unlink the
+				// old one first.  If we do not the <a> tag remains, but it has no content,
+				// so isn't readily visible (but is wrong for the action).
+				if(this.editor.queryCommandEnabled("unlink")){
+					// Select all the link childent, then unlink.  The following insert will
+					// then replace the selected text.
+					dojo.withGlobal(this.editor.window,
+						"selectElementChildren", dijit._editor.selection, [a]);
+					this.editor.execCommand("unlink");
+				}
+			}
+		}
+		// make sure values are properly escaped, etc.
+		args = this._checkValues(args); 
+		this.editor.execCommand('inserthtml',
+			dojo.string.substitute(this.htmlTemplate, args));
+	},
+
+	_onCloseDialog: function(){
+		// summary:
+		//		Handler for close event on the dialog
+		this.editor.focus();
+	},
+
+	_getCurrentValues: function(a){
+		// summary:
+		//		Over-ride for getting the values to set in the dropdown.
+		// a:
+		//		The anchor/link to process for data for the dropdown.
+		// tags:
+		//		protected
+		var url, text, target;
+		if(a && a.tagName.toLowerCase() === this.tag){
+			url = a.getAttribute('_djrealurl') || a.getAttribute('href');
+			target = a.getAttribute('target') || "_self";
+			text = a.textContent || a.innerText;
+			dojo.withGlobal(this.editor.window, "selectElement", dijit._editor.selection, [a, true]);
+		}else{
+			text = dojo.withGlobal(this.editor.window, dijit._editor.selection.getSelectedText);
+		}
+		return {urlInput: url || '', textInput: text || '', targetSelect: target || ''}; //Object;
+	},
+
+	_onOpenDialog: function(){
+		// summary:
+		//		Handler for when the dialog is opened.
+		//		If the caret is currently in a URL then populate the URL's info into the dialog.
+		var a;
+		if(dojo.isIE){
+			// IE is difficult to select the element in, using the range unified
+			// API seems to work reasonably well.
+			var sel = dijit.range.getSelection(this.editor.window);
+			var range = sel.getRangeAt(0);
+			a = range.endContainer;
+			if(a.nodeType === 3){
+				// Text node, may be the link contents, so check parent.
+				// This plugin doesn't really support nested HTML elements
+				// in the link, it assumes all link content is text.
+				a = a.parentNode;
+			}
+			if(a && (a.nodeName && a.nodeName.toLowerCase() !== this.tag)){
+				// Stll nothing, one last thing to try on IE, as it might be 'img'
+				// and thus considered a control.
+				a = dojo.withGlobal(this.editor.window,
+					"getSelectedElement", dijit._editor.selection, [this.tag]);
+			}
+		}else{
+			a = dojo.withGlobal(this.editor.window,
+				"getAncestorElement", dijit._editor.selection, [this.tag]);
+		}
+		this.dropDown.reset();
+		this._setButton.set("disabled", true);
+		this.dropDown.set("value", this._getCurrentValues(a));
+	},
+
+	_onDblClick: function(e){
+		// summary:
+		// 		Function to define a behavior on double clicks on the element
+		//		type this dialog edits to select it and pop up the editor
+		//		dialog.
+		// e: Object
+		//		The double-click event.
+		// tags:
+		//		protected.
+		if(e && e.target){
+			var t = e.target;
+			var tg = t.tagName? t.tagName.toLowerCase() : "";
+			if(tg === this.tag && dojo.attr(t,"href")){
+				dojo.withGlobal(this.editor.window,
+					 "selectElement",
+					 dijit._editor.selection, [t]);
+				this.editor.onDisplayChanged();
+				setTimeout(dojo.hitch(this, function(){
+					// Focus shift outside the event handler.
+					// IE doesn't like focus changes in event handles.
+					this.button.set("disabled", false);
+					this.button.openDropDown();
+				}), 10);
+			}
+		}
+	}
 });
-if(this._urlInput){
-this.connect(this._urlInput,"onChange","_checkAndFixInput");
-}
-if(this._textInput){
-this.connect(this._textInput,"onChange","_checkAndFixInput");
-}
-this._connectTagEvents();
-this.inherited(arguments);
-},_checkAndFixInput:function(){
-var _4=this;
-var _5=this._urlInput.attr("value");
-var _6=function(_7){
-var _8=false;
-if(_7&&_7.length>7){
-_7=dojo.trim(_7);
-if(_7.indexOf("/")>0){
-if(_7.indexOf("://")===-1){
-if(_7.charAt(0)!=="/"&&_7.indexOf("./")!==0){
-if(_4._hostRxp.test(_7)){
-_8=true;
-}
-}
-}
-}
-}
-if(_8){
-_4._urlInput.attr("value","http://"+_7);
-}
-_4._setButton.attr("disabled",!_4._isValid());
-};
-if(this._delayedCheck){
-clearTimeout(this._delayedCheck);
-this._delayedCheck=null;
-}
-this._delayedCheck=setTimeout(function(){
-_6(_5);
-},250);
-},_connectTagEvents:function(){
-this.editor.onLoadDeferred.addCallback(dojo.hitch(this,function(){
-this.connect(this.editor.editNode,"ondblclick",this._onDblClick);
-}));
-},_isValid:function(){
-return this._urlInput.isValid()&&this._textInput.isValid();
-},_setContent:function(_9){
-this.dropDown.attr("content",_9);
-},_checkValues:function(_a){
-if(_a&&_a.urlInput){
-_a.urlInput=_a.urlInput.replace(/"/g,""");
-}
-return _a;
-},setValue:function(_b){
-this._onCloseDialog();
-if(dojo.isIE){
-var _c=dijit.range.getSelection(this.editor.window);
-var _d=_c.getRangeAt(0);
-var a=_d.endContainer;
-if(a.nodeType===3){
-a=a.parentNode;
-}
-if(a&&(a.nodeName&&a.nodeName.toLowerCase()!==this.tag)){
-a=dojo.withGlobal(this.editor.window,"getSelectedElement",dijit._editor.selection,[this.tag]);
-}
-if(a&&(a.nodeName&&a.nodeName.toLowerCase()===this.tag)){
-if(this.editor.queryCommandEnabled("unlink")){
-dojo.withGlobal(this.editor.window,"selectElementChildren",dijit._editor.selection,[a]);
-this.editor.execCommand("unlink");
-}
-}
-}
-_b=this._checkValues(_b);
-this.editor.execCommand("inserthtml",dojo.string.substitute(this.htmlTemplate,_b));
-},_onCloseDialog:function(){
-this.editor.focus();
-},_getCurrentValues:function(a){
-var _e,_f,_10;
-if(a&&a.tagName.toLowerCase()===this.tag){
-_e=a.getAttribute("_djrealurl");
-_10=a.getAttribute("target")||"_self";
-_f=a.textContent||a.innerText;
-dojo.withGlobal(this.editor.window,"selectElement",dijit._editor.selection,[a,true]);
-}else{
-_f=dojo.withGlobal(this.editor.window,dijit._editor.selection.getSelectedText);
-}
-return {urlInput:_e||"",textInput:_f||"",targetSelect:_10||""};
-},_onOpenDialog:function(){
-var a;
-if(dojo.isIE){
-var sel=dijit.range.getSelection(this.editor.window);
-var _11=sel.getRangeAt(0);
-a=_11.endContainer;
-if(a.nodeType===3){
-a=a.parentNode;
-}
-if(a&&(a.nodeName&&a.nodeName.toLowerCase()!==this.tag)){
-a=dojo.withGlobal(this.editor.window,"getSelectedElement",dijit._editor.selection,[this.tag]);
-}
-}else{
-a=dojo.withGlobal(this.editor.window,"getAncestorElement",dijit._editor.selection,[this.tag]);
-}
-this.dropDown.reset();
-this._setButton.attr("disabled",true);
-this.dropDown.attr("value",this._getCurrentValues(a));
-},_onDblClick:function(e){
-if(e&&e.target){
-var t=e.target;
-var tg=t.tagName?t.tagName.toLowerCase():"";
-if(tg===this.tag){
-this.editor.onDisplayChanged();
-dojo.withGlobal(this.editor.window,"selectElement",dijit._editor.selection,[t]);
-setTimeout(dojo.hitch(this,function(){
-this.button.attr("disabled",false);
-this.button.openDropDown();
-}),10);
-}
-}
-}});
-dojo.declare("dijit._editor.plugins.ImgLinkDialog",[dijit._editor.plugins.LinkDialog],{linkDialogTemplate:["<table><tr><td>","<label for='${id}_urlInput'>${url}</label>","</td><td>","<input dojoType='dijit.form.ValidationTextBox' regExp='${urlRegExp}' "+"required='true' id='${id}_urlInput' name='urlInput' intermediateChanges='true'>","</td></tr><tr><td>","<label for='${id}_textInput'>${text}</label>","</td><td>","<input dojoType='dijit.form.ValidationTextBox' required='false' id='${id}_t [...]
-var url,_12;
-if(img&&img.tagName.toLowerCase()===this.tag){
-url=img.getAttribute("_djrealurl");
-_12=img.getAttribute("alt");
-dojo.withGlobal(this.editor.window,"selectElement",dijit._editor.selection,[img,true]);
-}else{
-_12=dojo.withGlobal(this.editor.window,dijit._editor.selection.getSelectedText);
-}
-return {urlInput:url||"",textInput:_12||""};
-},_isValid:function(){
-return this._urlInput.isValid();
-},_connectTagEvents:function(){
-this.inherited(arguments);
-this.editor.onLoadDeferred.addCallback(dojo.hitch(this,function(){
-this.connect(this.editor.editNode,"onclick",this._selectTag);
-}));
-},_selectTag:function(e){
-if(e&&e.target){
-var t=e.target;
-var tg=t.tagName?t.tagName.toLowerCase():"";
-if(tg===this.tag){
-dojo.withGlobal(this.editor.window,"selectElement",dijit._editor.selection,[t]);
-}
-}
-},_checkValues:function(_13){
-if(_13&&_13.urlInput){
-_13.urlInput=_13.urlInput.replace(/"/g,""");
-}
-if(_13&&_13.textInput){
-_13.textInput=_13.textInput.replace(/"/g,""");
-}
-return _13;
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-switch(o.args.name){
-case "createLink":
-o.plugin=new dijit._editor.plugins.LinkDialog({command:o.args.name});
-break;
-case "insertImage":
-o.plugin=new dijit._editor.plugins.ImgLinkDialog({command:o.args.name});
-break;
-}
+
+dojo.declare("dijit._editor.plugins.ImgLinkDialog", [dijit._editor.plugins.LinkDialog], {
+	// summary:
+	//		This plugin extends LinkDialog and adds in a plugin for handling image links.
+	//		provides the image link dialog.
+	//
+	// description:
+	//		The command provided by this plugin is:
+	//		* insertImage
+
+	// linkDialogTemplate: [protected] String
+	//		Over-ride for template since img dialog doesn't need target that anchor tags may.
+	linkDialogTemplate: [
+		"<table><tr><td>",
+		"<label for='${id}_urlInput'>${url}</label>",
+		"</td><td>",
+		"<input dojoType='dijit.form.ValidationTextBox' regExp='${urlRegExp}' " +
+		"required='true' id='${id}_urlInput' name='urlInput' intermediateChanges='true'>",
+		"</td></tr><tr><td>",
+		"<label for='${id}_textInput'>${text}</label>",
+		"</td><td>",
+		"<input dojoType='dijit.form.ValidationTextBox' required='false' id='${id}_textInput' " +
+		"name='textInput' intermediateChanges='true'>",
+		"</td></tr><tr><td>",
+		"</td><td>",
+		"</td></tr><tr><td colspan='2'>",
+		"<button dojoType='dijit.form.Button' type='submit' id='${id}_setButton'>${set}</button>",
+		"<button dojoType='dijit.form.Button' type='button' id='${id}_cancelButton'>${buttonCancel}</button>",
+		"</td></tr></table>"
+	].join(""),
+
+	// htmlTemplate: [protected] String
+	//		String used for templating the <img> HTML to insert at the desired point.
+	htmlTemplate: "<img src=\"${urlInput}\" _djrealurl=\"${urlInput}\" alt=\"${textInput}\" />",
+
+	// tag: [protected] String
+	//		Tag used for the link type (img).
+	tag: "img",
+
+	_getCurrentValues: function(img){
+		// summary:
+		//		Over-ride for getting the values to set in the dropdown.
+		// a:
+		//		The anchor/link to process for data for the dropdown.
+		// tags:
+		//		protected
+		var url, text;
+		if(img && img.tagName.toLowerCase() === this.tag){
+			url = img.getAttribute('_djrealurl') || img.getAttribute('src');
+			text = img.getAttribute('alt');
+			dojo.withGlobal(this.editor.window,
+				"selectElement", dijit._editor.selection, [img, true]);
+		}else{
+			text = dojo.withGlobal(this.editor.window, dijit._editor.selection.getSelectedText);
+		}
+		return {urlInput: url || '', textInput: text || ''}; //Object;
+	},
+
+	_isValid: function(){
+		// summary:
+		//		Over-ride for images.  You can have alt text of blank, it is valid.
+		// tags:
+		//		protected
+		return this._urlInput.isValid();
+	},
+
+	_connectTagEvents: function(){
+		// summary:
+		//		Over-ridable function that connects tag specific events.
+		this.inherited(arguments);
+		this.editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){
+			// Use onmousedown instead of onclick.  Seems that IE eats the first onclick
+			// to wrap it in a selector box, then the second one acts as onclick.  See #10420
+			this.connect(this.editor.editNode, "onmousedown", this._selectTag);
+		}));
+	},
+
+	_selectTag: function(e){
+		// summary:
+		//		A simple event handler that lets me select an image if it is clicked on.
+		//		makes it easier to select images in a standard way across browsers.  Otherwise
+		//		selecting an image for edit becomes difficult.
+		// e: Event
+		//		The mousedown event.
+		// tags:
+		//		private
+		if(e && e.target){
+			var t = e.target;
+			var tg = t.tagName? t.tagName.toLowerCase() : "";
+			if(tg === this.tag){
+				dojo.withGlobal(this.editor.window,
+					"selectElement",
+					dijit._editor.selection, [t]);
+			}
+		}
+	},
+
+	_checkValues: function(args){
+		// summary:
+		//		Function to check the values in args and 'fix' them up as needed 
+		//		(special characters in the url or alt text)
+		// args: Object
+		//		Content being set.		
+		// tags: 
+		//		protected
+		if(args && args.urlInput){
+			args.urlInput = args.urlInput.replace(/"/g, """);
+		}
+		if(args && args.textInput){
+			args.textInput = args.textInput.replace(/"/g, """);
+		}
+		return args;
+	},
+
+	_onDblClick: function(e){
+		// summary:
+		// 		Function to define a behavior on double clicks on the element
+		//		type this dialog edits to select it and pop up the editor
+		//		dialog.
+		// e: Object
+		//		The double-click event.
+		// tags:
+		//		protected.
+		if(e && e.target){
+			var t = e.target;
+			var tg = t.tagName? t.tagName.toLowerCase() : "";
+			if(tg === this.tag && dojo.attr(t,"src")){
+				dojo.withGlobal(this.editor.window,
+					 "selectElement",
+					 dijit._editor.selection, [t]);
+				this.editor.onDisplayChanged();
+				setTimeout(dojo.hitch(this, function(){
+					// Focus shift outside the event handler.
+					// IE doesn't like focus changes in event handles.
+					this.button.set("disabled", false);
+					this.button.openDropDown();
+				}), 10);
+			}
+		}
+	}
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	switch(o.args.name){
+		case "createLink":
+			o.plugin = new dijit._editor.plugins.LinkDialog({command: o.args.name});
+			break;
+		case "insertImage":
+			o.plugin = new dijit._editor.plugins.ImgLinkDialog({command: o.args.name});
+			break;
+	}
 });
-}
diff --git a/dijit/_editor/plugins/NewPage.js b/dijit/_editor/plugins/NewPage.js
index 3e6a4b1..7d0ea3f 100644
--- a/dijit/_editor/plugins/NewPage.js
+++ b/dijit/_editor/plugins/NewPage.js
@@ -1,34 +1,65 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._editor.plugins.NewPage"]){
-dojo._hasResource["dijit._editor.plugins.NewPage"]=true;
 dojo.provide("dijit._editor.plugins.NewPage");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.form.Button");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dijit._editor","commands",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit._editor.plugins.NewPage",dijit._editor._Plugin,{content:"<br>",_initButton:function(){
-var _1=dojo.i18n.getLocalization("dijit._editor","commands");
-this.button=new dijit.form.Button({label:_1["newPage"],showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"NewPage",tabIndex:"-1",onClick:dojo.hitch(this,"_newPage")});
-},setEditor:function(_2){
-this.editor=_2;
-this._initButton();
-},_newPage:function(){
-this.editor.attr("value",this.content);
-this.editor.focus();
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _3=o.args.name.toLowerCase();
-if(_3==="newpage"){
-o.plugin=new dijit._editor.plugins.NewPage({content:("content" in o.args)?o.args.content:"<br>"});
-}
+
+dojo.requireLocalization("dijit._editor", "commands");
+
+dojo.declare("dijit._editor.plugins.NewPage",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides a simple 'new page' calability.  In other
+	//		words, set content to some default user defined string.
+
+	// content: [public] String
+	//		The default content to insert into the editor as the new page.
+	//		The default is the <br> tag, a single blank line.
+	content: "<br>",
+
+	_initButton: function(){
+		// summary:
+		//		Over-ride for creation of the Print button.
+		var strings = dojo.i18n.getLocalization("dijit._editor", "commands"),
+			editor = this.editor;
+		this.button = new dijit.form.Button({
+			label: strings["newPage"],
+			dir: editor.dir,
+			lang: editor.lang,
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "NewPage",
+			tabIndex: "-1",
+			onClick: dojo.hitch(this, "_newPage")
+		});
+	},
+
+	setEditor: function(/*dijit.Editor*/ editor){
+		// summary:
+		//		Tell the plugin which Editor it is associated with.
+		// editor: Object
+		//		The editor object to attach the newPage capability to.
+		this.editor = editor;
+		this._initButton();
+	},
+
+	_newPage: function(){
+		// summary:
+		//		Function to set the content to blank.
+		// tags:
+		//		private
+		this.editor.beginEditing();
+		this.editor.set("value", this.content);
+		this.editor.endEditing();
+		this.editor.focus();
+	}
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "newpage"){
+		o.plugin = new dijit._editor.plugins.NewPage({
+			content: ("content" in o.args)?o.args.content:"<br>"
+		});
+	}
 });
-}
diff --git a/dijit/_editor/plugins/Print.js b/dijit/_editor/plugins/Print.js
old mode 100644
new mode 100755
index 81977fa..4853e7a
--- a/dijit/_editor/plugins/Print.js
+++ b/dijit/_editor/plugins/Print.js
@@ -1,65 +1,106 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._editor.plugins.Print"]){
-dojo._hasResource["dijit._editor.plugins.Print"]=true;
 dojo.provide("dijit._editor.plugins.Print");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.form.Button");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dijit._editor","commands",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit._editor.plugins.Print",dijit._editor._Plugin,{_initButton:function(){
-var _1=dojo.i18n.getLocalization("dijit._editor","commands");
-this.button=new dijit.form.Button({label:_1["print"],showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"Print",tabIndex:"-1",onClick:dojo.hitch(this,"_print")});
-},setEditor:function(_2){
-this.editor=_2;
-this._initButton();
-this.editor.onLoadDeferred.addCallback(dojo.hitch(this,function(){
-if(!this.editor.iframe.contentWindow["print"]){
-this.button.attr("disabled",true);
-}
-}));
-},_print:function(){
-var _3=this.editor.iframe;
-if(_3.contentWindow["print"]){
-if(!dojo.isOpera&&!dojo.isChrome){
-dijit.focus(_3);
-_3.contentWindow.print();
-}else{
-var _4=this.editor.document;
-var _5=this.editor.attr("value");
-_5="<html><head><meta http-equiv='Content-Type' "+"content='text/html; charset='UTF-8'></head><body>"+_5+"</body></html>";
-var _6=window.open("javascript: ''","","status=0,menubar=0,location=0,toolbar=0,"+"width=1,height=1,resizable=0,scrollbars=0");
-_6.document.open();
-_6.document.write(_5);
-_6.document.close();
-var _7=[];
-var _8=_4.getElementsByTagName("style");
-if(_8){
-var i;
-for(i=0;i<_8.length;i++){
-var _9=_8[i].innerHTML;
-var _a=_6.document.createElement("style");
-_a.appendChild(_6.document.createTextNode(_9));
-_6.document.getElementsByTagName("head")[0].appendChild(_a);
-}
-}
-_6.print();
-_6.close();
-}
-}
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _b=o.args.name.toLowerCase();
-if(_b==="print"){
-o.plugin=new dijit._editor.plugins.Print({command:"print"});
-}
+
+dojo.requireLocalization("dijit._editor", "commands");
+
+dojo.declare("dijit._editor.plugins.Print",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides Print cabability to the editor.  When
+	//		clicked, the document in the editor frame will be printed.
+
+	_initButton: function(){
+		// summary:
+		//		Over-ride for creation of the Print button.
+		var strings = dojo.i18n.getLocalization("dijit._editor", "commands"),
+			editor = this.editor;
+		this.button = new dijit.form.Button({
+			label: strings["print"],
+			dir: editor.dir,
+			lang: editor.lang,
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "Print",
+			tabIndex: "-1",
+			onClick: dojo.hitch(this, "_print")
+		});
+	},
+
+	setEditor: function(/*dijit.Editor*/ editor){
+		// summary:
+		//		Tell the plugin which Editor it is associated with.
+		// editor: Object
+		//		The editor object to attach the print capability to.
+		this.editor = editor;
+		this._initButton();
+
+		// Set up a check that we have a print function
+		// and disable button if we do not.
+		this.editor.onLoadDeferred.addCallback(
+			dojo.hitch(this, function(){
+				if(!this.editor.iframe.contentWindow["print"]){
+					this.button.set("disabled", true);
+				}
+			})
+		);
+	},
+
+	_print: function(){
+		// summary:
+		//		Function to trigger printing of the editor document
+		// tags:
+		//		private
+		var edFrame = this.editor.iframe;
+		if(edFrame.contentWindow["print"]){
+			// IE requires the frame to be focused for
+			// print to work, but since this is okay for all
+			// no special casing.
+			if(!dojo.isOpera && !dojo.isChrome){
+				dijit.focus(edFrame);
+				edFrame.contentWindow.print();
+			}else{
+				// Neither Opera nor Chrome 3 et you print single frames.
+				// So, open a new 'window', print it, and close it.
+				// Also, can't use size 0x0, have to use 1x1
+				var edDoc = this.editor.document;
+				var content = this.editor.get("value");
+				content = "<html><head><meta http-equiv='Content-Type' " +
+					"content='text/html; charset='UTF-8'></head><body>" +
+					content + "</body></html>";
+				var win = window.open("javascript: ''",
+					"",
+					"status=0,menubar=0,location=0,toolbar=0," +
+					"width=1,height=1,resizable=0,scrollbars=0");
+				win.document.open();
+				win.document.write(content);
+				win.document.close();
+				var styles = [];
+				var styleNodes = edDoc.getElementsByTagName("style");
+				if(styleNodes){
+					// Clone over any editor view styles, since we can't print the iframe
+					// directly.
+					var i;
+					for(i = 0; i < styleNodes.length; i++){
+						var style = styleNodes[i].innerHTML;
+						var sNode = win.document.createElement("style");
+						sNode.appendChild(win.document.createTextNode(style));
+						win.document.getElementsByTagName("head")[0].appendChild(sNode);
+					}
+				}
+				win.print();
+				win.close();
+			}
+		}
+	}
 });
-}
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "print"){
+		o.plugin = new dijit._editor.plugins.Print({command: "print"});
+	}
+});
+
diff --git a/dijit/_editor/plugins/TabIndent.js b/dijit/_editor/plugins/TabIndent.js
index 9376320..ff850b0 100644
--- a/dijit/_editor/plugins/TabIndent.js
+++ b/dijit/_editor/plugins/TabIndent.js
@@ -1,33 +1,52 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._editor.plugins.TabIndent"]){
-dojo._hasResource["dijit._editor.plugins.TabIndent"]=true;
 dojo.provide("dijit._editor.plugins.TabIndent");
 dojo.experimental("dijit._editor.plugins.TabIndent");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.form.ToggleButton");
-dojo.declare("dijit._editor.plugins.TabIndent",dijit._editor._Plugin,{useDefaultCommand:false,buttonClass:dijit.form.ToggleButton,command:"tabIndent",_initButton:function(){
-this.inherited(arguments);
-var e=this.editor;
-this.connect(this.button,"onChange",function(_1){
-e.attr("isTabIndent",_1);
-});
-this.updateState();
-},updateState:function(){
-this.button.attr("checked",this.editor.isTabIndent,false);
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-switch(o.args.name){
-case "tabIndent":
-o.plugin=new dijit._editor.plugins.TabIndent({command:o.args.name});
-}
+
+dojo.declare("dijit._editor.plugins.TabIndent",
+	dijit._editor._Plugin,
+	{
+		// summary:
+		//		This plugin is used to allow the use of the tab and shift-tab keys
+		//		to indent/outdent list items.  This overrides the default behavior
+		//		of moving focus from/to the toolbar
+
+		// Override _Plugin.useDefaultCommand... processing is handled by this plugin, not by dijit.Editor.
+		useDefaultCommand: false,
+
+		// Override _Plugin.buttonClass to use a ToggleButton for this plugin rather than a vanilla Button
+		buttonClass: dijit.form.ToggleButton,
+
+		command: "tabIndent",
+
+		_initButton: function(){
+			// Override _Plugin._initButton() to setup listener on button click
+			this.inherited(arguments);
+
+			var e = this.editor;
+			this.connect(this.button, "onChange", function(val){
+				e.set("isTabIndent", val);
+			});
+
+			// Set initial checked state of button based on Editor.isTabIndent
+			this.updateState();
+		},
+
+		updateState: function(){
+			// Overrides _Plugin.updateState().
+			// Ctrl-m in the editor will switch tabIndent mode on/off, so we need to react to that.
+
+			this.button.set('checked', this.editor.isTabIndent, false);
+		}
+	}
+);
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	switch(o.args.name){
+	case "tabIndent":
+		o.plugin = new dijit._editor.plugins.TabIndent({command: o.args.name});
+	}
 });
-}
diff --git a/dijit/_editor/plugins/TextColor.js b/dijit/_editor/plugins/TextColor.js
index 5f0ac31..288204e 100644
--- a/dijit/_editor/plugins/TextColor.js
+++ b/dijit/_editor/plugins/TextColor.js
@@ -1,29 +1,90 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._editor.plugins.TextColor"]){
-dojo._hasResource["dijit._editor.plugins.TextColor"]=true;
 dojo.provide("dijit._editor.plugins.TextColor");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.ColorPalette");
-dojo.declare("dijit._editor.plugins.TextColor",dijit._editor._Plugin,{buttonClass:dijit.form.DropDownButton,constructor:function(){
-this.dropDown=new dijit.ColorPalette();
-this.connect(this.dropDown,"onChange",function(_1){
-this.editor.execCommand(this.command,_1);
+
+dojo.declare("dijit._editor.plugins.TextColor", dijit._editor._Plugin, {
+	// summary:
+	//		This plugin provides dropdown color pickers for setting text color and background color
+	//
+	// description:
+	//		The commands provided by this plugin are:
+	//		* foreColor - sets the text color
+	//		* hiliteColor - sets the background color
+	
+	// Override _Plugin.buttonClass to use DropDownButton (with ColorPalette) to control this plugin
+	buttonClass: dijit.form.DropDownButton,
+	
+	// useDefaultCommand: Boolean
+	//		False as we do not use the default editor command/click behavior.
+	useDefaultCommand: false,
+
+	constructor: function(){
+		this.dropDown = new dijit.ColorPalette();
+		this.connect(this.dropDown, "onChange", function(color){
+			this.editor.execCommand(this.command, color);
+			
+		});
+	},
+
+	updateState: function(){
+		// summary:
+		//		Overrides _Plugin.updateState().  This updates the ColorPalette
+		//		to show the color of the currently selected text.
+		// tags:
+		//		protected
+		
+		var _e = this.editor;
+		var _c = this.command;
+		if(!_e || !_e.isLoaded || !_c.length){
+			return;
+		}
+		
+		if(this.button){
+			var value;
+			try{
+				value = _e.queryCommandValue(_c)|| "";
+			}catch(e){
+				//Firefox may throw error above if the editor is just loaded, ignore it
+				value = "";
+			}
+		}
+		
+		if(value == ""){
+			value = "#000000";
+		}
+		if(value == "transparent"){
+			value = "#ffffff";
+		}
+
+		if(typeof value == "string"){
+			//if RGB value, convert to hex value	
+			if(value.indexOf("rgb")> -1){
+				value = dojo.colorFromRgb(value).toHex();
+			}
+		}else{	//it's an integer(IE returns an MS access #)
+			value =((value & 0x0000ff)<< 16)|(value & 0x00ff00)|((value & 0xff0000)>>> 16);
+			value = value.toString(16);
+			value = "#000000".slice(0, 7 - value.length)+ value;
+			
+		}
+		
+		if(value !== this.dropDown.get('value')){
+			this.dropDown.set('value', value, false);
+		}
+	}
 });
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-switch(o.args.name){
-case "foreColor":
-case "hiliteColor":
-o.plugin=new dijit._editor.plugins.TextColor({command:o.args.name});
-}
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin", null, function(o){
+	if(o.plugin){
+		return;
+	}
+	switch(o.args.name){
+		case "foreColor":
+		case "hiliteColor":
+			o.plugin = new dijit._editor.plugins.TextColor({
+				command: o.args.name
+			});
+	}
 });
-}
diff --git a/dijit/_editor/plugins/ToggleDir.js b/dijit/_editor/plugins/ToggleDir.js
index 3424950..cde17f2 100644
--- a/dijit/_editor/plugins/ToggleDir.js
+++ b/dijit/_editor/plugins/ToggleDir.js
@@ -1,42 +1,64 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._editor.plugins.ToggleDir"]){
-dojo._hasResource["dijit._editor.plugins.ToggleDir"]=true;
 dojo.provide("dijit._editor.plugins.ToggleDir");
 dojo.experimental("dijit._editor.plugins.ToggleDir");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.form.ToggleButton");
-dojo.declare("dijit._editor.plugins.ToggleDir",dijit._editor._Plugin,{useDefaultCommand:false,command:"toggleDir",buttonClass:dijit.form.ToggleButton,_initButton:function(){
-this.inherited(arguments);
-this.editor.onLoadDeferred.addCallback(dojo.hitch(this,function(){
-var _1=this.editor.editorObject.contentWindow.document.documentElement;
-_1=_1.getElementsByTagName("body")[0];
-var _2=dojo.getComputedStyle(_1).direction=="ltr";
-this.button.attr("checked",!_2);
-this.connect(this.button,"onChange","_setRtl");
-}));
-},updateState:function(){
-},_setRtl:function(_3){
-var _4="ltr";
-if(_3){
-_4="rtl";
-}
-var _5=this.editor.editorObject.contentWindow.document.documentElement;
-_5=_5.getElementsByTagName("body")[0];
-_5.dir=_4;
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-switch(o.args.name){
-case "toggleDir":
-o.plugin=new dijit._editor.plugins.ToggleDir({command:o.args.name});
-}
+
+dojo.declare("dijit._editor.plugins.ToggleDir",
+	dijit._editor._Plugin,
+	{
+		// summary:
+		//		This plugin is used to toggle direction of the edited document,
+		//		independent of what direction the whole page is.
+
+		// Override _Plugin.useDefaultCommand: processing is done in this plugin
+		// rather than by sending commands to the Editor
+		useDefaultCommand: false,
+
+		command: "toggleDir",
+
+		// Override _Plugin.buttonClass to use a ToggleButton for this plugin rather than a vanilla Button
+		buttonClass: dijit.form.ToggleButton,
+
+		_initButton: function(){
+			// Override _Plugin._initButton() to setup handler for button click events.
+			this.inherited(arguments);
+			this.editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){
+				var editDoc = this.editor.editorObject.contentWindow.document.documentElement;
+				//IE direction has to toggle on the body, not document itself.
+				//If you toggle just the document, things get very strange in the
+				//view.  But, the nice thing is this works for all supported browsers.
+				editDoc = editDoc.getElementsByTagName("body")[0];
+				var isLtr = dojo.getComputedStyle(editDoc).direction == "ltr";
+				this.button.set("checked", !isLtr);
+				this.connect(this.button, "onChange", "_setRtl");
+			}));
+		},
+
+		updateState: function(){
+			// Override _Plugin.updateState() to do nothing, since we don't need to react to changes in the
+			// editor like arrow keys etc.
+		},
+
+		_setRtl: function(rtl){
+			// summary:
+			//		Handler for button click events, to switch the text direction of the editor
+			var dir = "ltr";
+			if(rtl){
+				dir = "rtl";
+			}
+			var editDoc = this.editor.editorObject.contentWindow.document.documentElement;
+			editDoc = editDoc.getElementsByTagName("body")[0];
+			editDoc.dir/*html node*/ = dir;
+		}
+	}
+);
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	switch(o.args.name){
+	case "toggleDir":
+		o.plugin = new dijit._editor.plugins.ToggleDir({command: o.args.name});
+	}
 });
-}
diff --git a/dijit/_editor/plugins/ViewSource.js b/dijit/_editor/plugins/ViewSource.js
old mode 100644
new mode 100755
index 9a91943..fa54501
--- a/dijit/_editor/plugins/ViewSource.js
+++ b/dijit/_editor/plugins/ViewSource.js
@@ -1,300 +1,557 @@
-/*
-	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
-*/
+dojo.provide("dijit._editor.plugins.ViewSource");
 
+dojo.require("dojo.window");
+dojo.require("dojo.i18n");
 
-if(!dojo._hasResource["dijit._editor.plugins.ViewSource"]){
-dojo._hasResource["dijit._editor.plugins.ViewSource"]=true;
-dojo.provide("dijit._editor.plugins.ViewSource");
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.form.Button");
-dojo.require("dojo.i18n");
-dojo.requireLocalization("dijit._editor","commands",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit._editor.plugins.ViewSource",dijit._editor._Plugin,{stripScripts:true,stripComments:true,stripIFrames:true,readOnly:false,_fsPlugin:null,toggle:function(){
-if(dojo.isWebKit){
-this._vsFocused=true;
-}
-this.button.attr("checked",!this.button.attr("checked"));
-},_initButton:function(){
-var _1=dojo.i18n.getLocalization("dijit._editor","commands");
-this.button=new dijit.form.ToggleButton({label:_1["viewSource"],showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"ViewSource",tabIndex:"-1",onChange:dojo.hitch(this,"_showSource")});
-if(dojo.isIE==7){
-this._ieFixNode=dojo.create("div",{style:{opacity:"0",zIndex:"-1000",position:"absolute",top:"-1000px"}},dojo.body());
-}
-this.button.attr("readOnly",false);
-},setEditor:function(_2){
-this.editor=_2;
-this._initButton();
-this.editor.addKeyHandler(dojo.keys.F12,true,true,dojo.hitch(this,function(e){
-this.button.focus();
-this.toggle();
-dojo.stopEvent(e);
-setTimeout(dojo.hitch(this,function(){
-this.editor.focus();
-}),100);
-}));
-},_showSource:function(_3){
-var ed=this.editor;
-var _4=ed._plugins;
-var _5;
-this._sourceShown=_3;
-var _6=this;
-try{
-if(!this.sourceArea){
-this._createSourceView();
-}
-if(_3){
-ed._sourceQueryCommandEnabled=ed.queryCommandEnabled;
-ed.queryCommandEnabled=function(_7){
-var _8=_7.toLowerCase();
-if(_8==="viewsource"){
-return true;
-}else{
-return false;
-}
-};
-this.editor.onDisplayChanged();
-_5=ed.attr("value");
-_5=this._filter(_5);
-ed.attr("value",_5);
-this._pluginList=[];
-this._disabledPlugins=dojo.filter(_4,function(p){
-if(p&&p.button&&!p.button.attr("disabled")&&!(p instanceof dijit._editor.plugins.ViewSource)){
-p._vs_updateState=p.updateState;
-p.updateState=function(){
-return false;
-};
-p.button.attr("disabled",true);
-if(p.command){
-switch(p.command){
-case "bold":
-case "italic":
-case "underline":
-case "strikethrough":
-case "superscript":
-case "subscript":
-p.button.attr("checked",false);
-break;
-default:
-break;
-}
-}
-return true;
-}
-});
-if(this._fsPlugin){
-this._fsPlugin._getAltViewNode=function(){
-return _6.sourceArea;
-};
-}
-this.sourceArea.value=_5;
-var is=dojo.marginBox(ed.iframe.parentNode);
-dojo.marginBox(this.sourceArea,{w:is.w,h:is.h});
-dojo.style(ed.iframe,"display","none");
-dojo.style(this.sourceArea,{display:"block"});
-var _9=function(){
-var vp=dijit.getViewport();
-if("_prevW" in this&&"_prevH" in this){
-if(vp.w===this._prevW&&vp.h===this._prevH){
-return;
-}else{
-this._prevW=vp.w;
-this._prevH=vp.h;
-}
-}else{
-this._prevW=vp.w;
-this._prevH=vp.h;
-}
-if(this._resizer){
-clearTimeout(this._resizer);
-delete this._resizer;
-}
-this._resizer=setTimeout(dojo.hitch(this,function(){
-delete this._resizer;
-this._resize();
-}),10);
-};
-this._resizeHandle=dojo.connect(window,"onresize",this,_9);
-setTimeout(dojo.hitch(this,this._resize),100);
-this.editor.onNormalizedDisplayChanged();
-}else{
-if(!ed._sourceQueryCommandEnabled){
-return;
-}
-dojo.disconnect(this._resizeHandle);
-delete this._resizeHandle;
-ed.queryCommandEnabled=ed._sourceQueryCommandEnabled;
-if(!this._readOnly){
-_5=this.sourceArea.value;
-_5=this._filter(_5);
-ed.attr("value",_5);
-}
-dojo.forEach(this._disabledPlugins,function(p){
-p.button.attr("disabled",false);
-if(p._vs_updateState){
-p.updateState=p._vs_updateState;
-}
+
+dojo.requireLocalization("dijit._editor", "commands");
+
+dojo.declare("dijit._editor.plugins.ViewSource",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides a simple view source capability.  When view
+	//		source mode is enabled, it disables all other buttons/plugins on the RTE.
+	//		It also binds to the hotkey: CTRL-SHIFT-F11 for toggling ViewSource mode.
+
+	// stripScripts: [public] Boolean
+	//		Boolean flag used to indicate if script tags should be stripped from the document.
+	//		Defaults to true.
+	stripScripts: true,
+
+	// stripComments: [public] Boolean
+	//		Boolean flag used to indicate if comment tags should be stripped from the document.
+	//		Defaults to true.
+	stripComments: true,
+
+	// stripComments: [public] Boolean
+	//		Boolean flag used to indicate if iframe tags should be stripped from the document.
+	//		Defaults to true.
+	stripIFrames: true,
+
+	// readOnly: [const] Boolean
+	//		Boolean flag used to indicate if the source view should be readonly or not.
+	//		Cannot be changed after initialization of the plugin.
+	//		Defaults to false.
+	readOnly: false,
+
+	// _fsPlugin: [private] Object
+	//		Reference to a registered fullscreen plugin so that viewSource knows
+	//		how to scale.
+	_fsPlugin: null,
+
+	toggle: function(){
+		// summary:
+		//		Function to allow programmatic toggling of the view.
+
+		// For Webkit, we have to focus a very particular way.
+		// when swapping views, otherwise focus doesn't shift right
+		// but can't focus this way all the time, only for VS changes.
+		// If we did it all the time, buttons like bold, italic, etc
+		// break.
+		if(dojo.isWebKit){this._vsFocused = true;}
+		this.button.set("checked", !this.button.get("checked"));
+
+	},
+
+	_initButton: function(){
+		// summary:
+		//		Over-ride for creation of the resize button.
+		var strings = dojo.i18n.getLocalization("dijit._editor", "commands"),
+			editor = this.editor;
+		this.button = new dijit.form.ToggleButton({
+			label: strings["viewSource"],
+			dir: editor.dir,
+			lang: editor.lang,
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "ViewSource",
+			tabIndex: "-1",
+			onChange: dojo.hitch(this, "_showSource")
+		});
+
+		// IE 7 has a horrible bug with zoom, so we have to create this node
+		// to cross-check later.  Sigh.
+		if(dojo.isIE == 7){
+			this._ieFixNode = dojo.create("div", {
+				style: {
+					opacity: "0",
+					zIndex: "-1000",
+					position: "absolute",
+					top: "-1000px"
+				}
+			}, dojo.body());
+		}
+		// Make sure readonly mode doesn't make the wrong cursor appear over the button.
+		this.button.set("readOnly", false);
+	},
+
+
+	setEditor: function(/*dijit.Editor*/ editor){
+		// summary:
+		//		Tell the plugin which Editor it is associated with.
+		// editor: Object
+		//		The editor object to attach the print capability to.
+		this.editor = editor;
+		this._initButton();
+
+		this.editor.addKeyHandler(dojo.keys.F12, true, true, dojo.hitch(this, function(e){
+			// Move the focus before switching
+			// It'll focus back.  Hiding a focused
+			// node causes issues.
+			this.button.focus();
+			this.toggle();
+			dojo.stopEvent(e);
+
+			// Call the focus shift outside of the handler.
+			setTimeout(dojo.hitch(this, function(){
+				// We over-ride focus, so we just need to call.
+				this.editor.focus();
+			}), 100);
+		}));
+	},
+
+	_showSource: function(source){
+		// summary:
+		//		Function to toggle between the source and RTE views.
+		// source: boolean
+		//		Boolean value indicating if it should be in source mode or not.
+		// tags:
+		//		private
+		var ed = this.editor;
+		var edPlugins = ed._plugins;
+		var html;
+		this._sourceShown = source;
+		var self = this;
+		try{
+			if(!this.sourceArea){
+				this._createSourceView();
+			}
+			if(source){
+				// Update the QueryCommandEnabled function to disable everything but
+				// the source view mode.  Have to over-ride a function, then kick all
+				// plugins to check their state.
+				ed._sourceQueryCommandEnabled = ed.queryCommandEnabled;
+				ed.queryCommandEnabled = function(cmd){
+					var lcmd = cmd.toLowerCase();
+					if(lcmd === "viewsource"){
+						return true;
+					}else{
+						return false;
+					}
+				};
+				this.editor.onDisplayChanged();
+				html = ed.get("value");
+				html = this._filter(html);
+				ed.set("value", html);
+				this._pluginList = [];
+				this._disabledPlugins = dojo.filter(edPlugins, function(p){
+					// Turn off any plugins not controlled by queryCommandenabled.
+					if(p && p.button && !p.button.get("disabled") &&
+						!(p instanceof dijit._editor.plugins.ViewSource)){
+						p._vs_updateState = p.updateState;
+						p.updateState = function(){
+							return false;
+						};
+						p.button.set("disabled", true);
+						if(p.command){
+							// FF has a weird behavior when spellcheck is off,
+							// queryCommandValue() returns true on the doc, and as such
+							// toggles 'on' some actions.  So, we need to explictly 
+							// toggle them off.  TODO:  Add a disable API to _Plugin.js
+							// It would aleviate the need for this.
+							switch(p.command){
+								case "bold":
+								case "italic":
+								case "underline":
+								case "strikethrough":
+								case "superscript":
+								case "subscript":
+									p.button.set("checked", false);
+									break;
+								default:
+									break;
+							}
+						}
+						return true;
+					}
+				});
+
+				// We actually do need to trap this plugin and adjust how we
+				// display the textarea.
+				if(this._fsPlugin){
+					this._fsPlugin._getAltViewNode = function(){
+						return self.sourceArea;
+					};
+				}
+
+				this.sourceArea.value = html;
+				var is = dojo.marginBox(ed.iframe.parentNode);
+
+				dojo.marginBox(this.sourceArea, {
+					w: is.w,
+					h: is.h
+				});
+
+				dojo.style(ed.iframe, "display", "none");
+				dojo.style(this.sourceArea, {
+					display: "block"
+				});
+
+				var resizer = function(){
+					// function to handle resize events.
+					// Will check current VP and only resize if
+					// different.
+					var vp = dojo.window.getBox();
+
+					if("_prevW" in this && "_prevH" in this){
+						// No actual size change, ignore.
+						if(vp.w === this._prevW && vp.h === this._prevH){
+							return;
+						}else{
+							this._prevW = vp.w;
+							this._prevH = vp.h;
+						}
+					}else{
+						this._prevW = vp.w;
+						this._prevH = vp.h;
+					}
+					if(this._resizer){
+						clearTimeout(this._resizer);
+						delete this._resizer;
+					}
+					// Timeout it to help avoid spamming resize on IE.
+					// Works for all browsers.
+					this._resizer = setTimeout(dojo.hitch(this, function(){
+						delete this._resizer;
+						this._resize();
+					}), 10);
+				};
+				this._resizeHandle = dojo.connect(window, "onresize", this, resizer);
+
+				//Call this on a delay once to deal with IE glitchiness on initial size.
+				setTimeout(dojo.hitch(this, this._resize), 100);
+
+				//Trigger a check for command enablement/disablement.
+				this.editor.onNormalizedDisplayChanged();
+			}else{
+				// First check that we were in source view before doing anything.
+				// corner case for being called with a value of false and we hadn't
+				// actually been in source display mode.
+				if(!ed._sourceQueryCommandEnabled){
+					return;
+				}
+				dojo.disconnect(this._resizeHandle);
+				delete this._resizeHandle;
+
+				// Restore all the plugin buttons state.
+				ed.queryCommandEnabled = ed._sourceQueryCommandEnabled;
+				if(!this._readOnly){
+					html = this.sourceArea.value;
+					html = this._filter(html);
+					ed.beginEditing();
+					ed.set("value", html);
+					ed.endEditing();
+				}
+
+				dojo.forEach(this._disabledPlugins, function(p){
+					// Turn back on any plugins we turned off.
+					p.button.set("disabled", false);
+					if(p._vs_updateState){
+						p.updateState = p._vs_updateState;
+					}
+				});
+
+				this._disabledPlugins = null;
+				dojo.style(this.sourceArea, "display", "none");
+				dojo.style(ed.iframe, "display", "block");
+				delete ed._sourceQueryCommandEnabled;
+                
+				//Trigger a check for command enablement/disablement.
+				this.editor.onDisplayChanged();
+			}
+			// Call a delayed resize to wait for some things to display in header/footer.
+			setTimeout(dojo.hitch(this, function(){
+				// Make resize calls.
+				var parent = ed.domNode.parentNode;
+				if(parent){
+					var container = dijit.getEnclosingWidget(parent);
+					if(container && container.resize){
+						container.resize();
+					}
+				}
+                ed.resize();
+			}), 300);
+		}catch(e){
+			console.log(e);
+		}
+	},
+
+	_resize: function(){
+		// summary:
+		//		Internal function to resize the source view
+		// tags:
+		//		private
+		var ed = this.editor;
+		var tbH = ed.getHeaderHeight();
+		var fH = ed.getFooterHeight();
+		var eb = dojo.position(ed.domNode);
+
+		// Styles are now applied to the internal source container, so we have
+		// to subtract them off.
+		var containerPadding = dojo._getPadBorderExtents(ed.iframe.parentNode);
+		var containerMargin = dojo._getMarginExtents(ed.iframe.parentNode);
+
+		var extents = dojo._getPadBorderExtents(ed.domNode);
+		var mExtents = dojo._getMarginExtents(ed.domNode);
+		var edb = {
+			w: eb.w - (extents.w + mExtents.w),
+			h: eb.h - (tbH + extents.h + mExtents.h + fH)
+		};
+
+		// Fullscreen gets odd, so we need to check for the FS plugin and
+		// adapt.
+		if(this._fsPlugin && this._fsPlugin.isFullscreen){
+			//Okay, probably in FS, adjust.
+			var vp = dojo.window.getBox();
+			edb.w = (vp.w - extents.w);
+			edb.h = (vp.h - (tbH + extents.h + fH));
+		}
+
+		if(dojo.isIE){
+			// IE is always off by 2px, so we have to adjust here
+			// Note that IE ZOOM is broken here.  I can't get
+			//it to scale right.
+			edb.h -= 2;
+		}
+
+		// IE has a horrible zoom bug.  So, we have to try and account for
+		// it and fix up the scaling.
+		if(this._ieFixNode){
+			var _ie7zoom = -this._ieFixNode.offsetTop / 1000;
+			edb.w = Math.floor((edb.w + 0.9) / _ie7zoom);
+			edb.h = Math.floor((edb.h + 0.9) / _ie7zoom);
+		}
+
+		dojo.marginBox(this.sourceArea, {
+			w: edb.w - (containerPadding.w + containerMargin.w),
+			h: edb.h - (containerPadding.h + containerMargin.h)
+		});
+
+		// Scale the parent container too in this case.
+		dojo.marginBox(ed.iframe.parentNode, {
+			h: edb.h
+		});
+	},
+
+	_createSourceView: function(){
+		// summary:
+		//		Internal function for creating the source view area.
+		// tags:
+		//		private
+		var ed = this.editor;
+		var edPlugins = ed._plugins;
+		this.sourceArea = dojo.create("textarea");
+		if(this.readOnly){
+			dojo.attr(this.sourceArea, "readOnly", true);
+			this._readOnly = true;
+		}
+		dojo.style(this.sourceArea, {
+			padding: "0px",
+			margin: "0px",
+			borderWidth: "0px",
+			borderStyle: "none"
+		});
+		dojo.place(this.sourceArea, ed.iframe, "before");
+
+		if(dojo.isIE && ed.iframe.parentNode.lastChild !== ed.iframe){
+			// There's some weirdo div in IE used for focus control
+			// But is messed up scaling the textarea if we don't config
+			// it some so it doesn't have a varying height.
+			dojo.style(ed.iframe.parentNode.lastChild,{
+				width: "0px",
+				height: "0px",
+				padding: "0px",
+				margin: "0px",
+				borderWidth: "0px",
+				borderStyle: "none"
+			});
+		}
+
+		// We also need to take over editor focus a bit here, so that focus calls to
+		// focus the editor will focus to the right node when VS is active.
+		ed._viewsource_oldFocus = ed.focus;
+		var self = this;
+		ed.focus = function(){
+			if(self._sourceShown){
+				self.setSourceAreaCaret();
+			}else{
+				try{
+					if(this._vsFocused){
+						delete this._vsFocused;
+						// Must focus edit node in this case (webkit only) or
+						// focus doesn't shift right, but in normal
+						// cases we focus with the regular function.
+						dijit.focus(ed.editNode);
+					}else{
+						ed._viewsource_oldFocus();
+					}
+				}catch(e){
+					console.log(e);
+				}
+			}
+		};
+
+		var i, p;
+		for(i = 0; i < edPlugins.length; i++){
+			// We actually do need to trap this plugin and adjust how we
+			// display the textarea.
+			p = edPlugins[i];
+			if(p && (p.declaredClass === "dijit._editor.plugins.FullScreen" ||
+					p.declaredClass === (dijit._scopeName +
+					"._editor.plugins.FullScreen"))){
+				this._fsPlugin = p;
+				break;
+			}
+		}
+		if(this._fsPlugin){
+			// Found, we need to over-ride the alt-view node function
+			// on FullScreen with our own, chain up to parent call when appropriate.
+			this._fsPlugin._viewsource_getAltViewNode = this._fsPlugin._getAltViewNode;
+			this._fsPlugin._getAltViewNode = function(){
+				return self._sourceShown?self.sourceArea:this._viewsource_getAltViewNode();
+			};
+		}
+
+		// Listen to the source area for key events as well, as we need to be able to hotkey toggle
+		// it from there too.
+		this.connect(this.sourceArea, "onkeydown", dojo.hitch(this, function(e){
+			if(this._sourceShown && e.keyCode == dojo.keys.F12 && e.ctrlKey && e.shiftKey){
+				this.button.focus();
+				this.button.set("checked", false);
+				setTimeout(dojo.hitch(this, function(){ed.focus();}), 100);
+				dojo.stopEvent(e);
+			}
+		}));
+	},
+
+	_stripScripts: function(html){
+		// summary:
+		//		Strips out script tags from the HTML used in editor.
+		// html: String
+		//		The HTML to filter
+		// tags:
+		//		private
+		if(html){
+			// Look for closed and unclosed (malformed) script attacks.
+			html = html.replace(/<\s*script[^>]*>((.|\s)*?)<\\?\/\s*script\s*>/ig, "");
+			html = html.replace(/<\s*script\b([^<>]|\s)*>?/ig, "");
+			html = html.replace(/<[^>]*=(\s|)*[("|')]javascript:[^$1][(\s|.)]*[$1][^>]*>/ig, "");
+		}
+		return html;
+	},
+
+	_stripComments: function(html){
+		// summary:
+		//		Strips out comments from the HTML used in editor.
+		// html: String
+		//		The HTML to filter
+		// tags:
+		//		private
+		if(html){
+			html = html.replace(/<!--(.|\s){1,}?-->/g, "");
+		}
+		return html;
+	},
+
+	_stripIFrames: function(html){
+		// summary:
+		//		Strips out iframe tags from the content, to avoid iframe script
+		//		style injection attacks.
+		// html: String
+		//		The HTML to filter
+		// tags:
+		//		private
+		if(html){
+			html = html.replace(/<\s*iframe[^>]*>((.|\s)*?)<\\?\/\s*iframe\s*>/ig, "");
+		}
+		return html;
+	},
+
+	_filter: function(html){
+		// summary:
+		//		Internal function to perform some filtering on the HTML.
+		// html: String
+		//		The HTML to filter
+		// tags:
+		//		private
+		if(html){
+			if(this.stripScripts){
+				html = this._stripScripts(html);
+			}
+			if(this.stripComments){
+				html = this._stripComments(html);
+			}
+			if(this.stripIFrames){
+				html = this._stripIFrames(html);
+			}
+		}
+		return html;
+	},
+
+	setSourceAreaCaret: function(){
+		// summary:
+		//		Internal function to set the caret in the sourceArea
+		//		to 0x0
+		var win = dojo.global;
+		var elem = this.sourceArea;
+		dijit.focus(elem);
+		if(this._sourceShown && !this.readOnly){
+			if(dojo.isIE){
+				if(this.sourceArea.createTextRange){
+					var range = elem.createTextRange();
+					range.collapse(true);
+					range.moveStart("character", -99999); // move to 0
+					range.moveStart("character", 0); // delta from 0 is the correct position
+					range.moveEnd("character", 0);
+					range.select();
+				}
+			}else if(win.getSelection){
+				if(elem.setSelectionRange){
+					elem.setSelectionRange(0,0);
+				}
+			}
+		}
+	},
+
+	destroy: function(){
+		// summary:
+		//		Over-ride to remove the node used to correct for IE's
+		//		zoom bug.
+		if(this._ieFixNode){
+			dojo.body().removeChild(this._ieFixNode);
+		}
+		if(this._resizer){
+			clearTimeout(this._resizer);
+			delete this._resizer;
+		}
+		if(this._resizeHandle){
+			dojo.disconnect(this._resizeHandle);
+			delete this._resizeHandle;
+		}
+		this.inherited(arguments);
+	}
 });
-this._disabledPlugins=null;
-dojo.style(this.sourceArea,"display","none");
-dojo.style(ed.iframe,"display","block");
-delete ed._sourceQueryCommandEnabled;
-this.editor.onDisplayChanged();
-}
-}
-catch(e){
-}
-},_resize:function(){
-var ed=this.editor;
-var tb=dojo.position(ed.toolbar.domNode);
-var eb=dojo.position(ed.domNode);
-var _a=dojo._getPadBorderExtents(ed.domNode);
-var _b={w:eb.w-_a.w,h:eb.h-(tb.h+_a.h)};
-if(this._fsPlugin&&this._fsPlugin.isFullscreen){
-var vp=dijit.getViewport();
-_b.w=(vp.w-_a.w);
-_b.h=(vp.h-(tb.h+_a.h));
-}
-if(dojo.isIE){
-_b.h-=2;
-}
-if(this._ieFixNode){
-var _c=-this._ieFixNode.offsetTop/1000;
-_b.w=Math.floor((_b.w+0.9)/_c);
-_b.h=Math.floor((_b.h+0.9)/_c);
-}
-dojo.marginBox(this.sourceArea,{w:_b.w,h:_b.h});
-},_createSourceView:function(){
-var ed=this.editor;
-var _d=ed._plugins;
-this.sourceArea=dojo.create("textarea");
-if(this.readOnly){
-dojo.attr(this.sourceArea,"readOnly",true);
-this._readOnly=true;
-}
-dojo.style(this.sourceArea,{padding:"0px",margin:"0px",borderWidth:"0px",borderStyle:"none"});
-dojo.place(this.sourceArea,ed.iframe,"before");
-dojo.style(this.sourceArea.parentNode,{padding:"0px",margin:"0px",borderWidth:"0px",borderStyle:"none"});
-if(dojo.isIE&&ed.iframe.parentNode.lastChild!==ed.iframe){
-dojo.style(ed.iframe.parentNode.lastChild,{width:"0px",height:"0px",padding:"0px",margin:"0px",borderWidth:"0px",borderStyle:"none"});
-}
-ed._viewsource_oldFocus=ed.focus;
-var _e=this;
-ed.focus=function(){
-if(_e._sourceShown){
-_e.setSourceAreaCaret();
-}else{
-try{
-if(this._vsFocused){
-delete this._vsFocused;
-dijit.focus(ed.editNode);
-}else{
-ed._viewsource_oldFocus();
-}
-}
-catch(e){
-}
-}
-};
-var i,p;
-for(i=0;i<_d.length;i++){
-p=_d[i];
-if(p&&(p.declaredClass==="dijit._editor.plugins.FullScreen"||p.declaredClass===(dijit._scopeName+"._editor.plugins.FullScreen"))){
-this._fsPlugin=p;
-break;
-}
-}
-if(this._fsPlugin){
-this._fsPlugin._viewsource_getAltViewNode=this._fsPlugin._getAltViewNode;
-this._fsPlugin._getAltViewNode=function(){
-return _e._sourceShown?_e.sourceArea:this._viewsource_getAltViewNode();
-};
-}
-this.connect(this.sourceArea,"onkeydown",dojo.hitch(this,function(e){
-if(this._sourceShown&&e.keyCode==dojo.keys.F12&&e.ctrlKey&&e.shiftKey){
-this.button.focus();
-this.button.attr("checked",false);
-setTimeout(dojo.hitch(this,function(){
-ed.focus();
-}),100);
-dojo.stopEvent(e);
-}
-}));
-},_stripScripts:function(_f){
-if(_f){
-_f=_f.replace(/<\s*script[^>]*>((.|\s)*?)<\\?\/\s*script\s*>/ig,"");
-_f=_f.replace(/<\s*script\b([^<>]|\s)*>?/ig,"");
-_f=_f.replace(/<[^>]*=(\s|)*[("|')]javascript:[^$1][(\s|.)]*[$1][^>]*>/ig,"");
-}
-return _f;
-},_stripComments:function(_10){
-if(_10){
-_10=_10.replace(/<!--(.|\s){1,}?-->/g,"");
-}
-return _10;
-},_stripIFrames:function(_11){
-if(_11){
-_11=_11.replace(/<\s*iframe[^>]*>((.|\s)*?)<\\?\/\s*iframe\s*>/ig,"");
-}
-return _11;
-},_filter:function(_12){
-if(_12){
-if(this.stripScripts){
-_12=this._stripScripts(_12);
-}
-if(this.stripComments){
-_12=this._stripComments(_12);
-}
-if(this.stripIFrames){
-_12=this._stripIFrames(_12);
-}
-}
-return _12;
-},setSourceAreaCaret:function(){
-var win=dojo.global;
-var _13=this.sourceArea;
-dijit.focus(_13);
-if(this._sourceShown&&!this.readOnly){
-if(dojo.isIE){
-if(this.sourceArea.createTextRange){
-var _14=_13.createTextRange();
-_14.collapse(true);
-_14.moveStart("character",-99999);
-_14.moveStart("character",0);
-_14.moveEnd("character",0);
-_14.select();
-}
-}else{
-if(win.getSelection){
-if(_13.setSelectionRange){
-_13.setSelectionRange(0,0);
-}
-}
-}
-}
-},destroy:function(){
-if(this._ieFixNode){
-dojo.body().removeChild(this._ieFixNode);
-}
-if(this._resizer){
-clearTimeout(this._resizer);
-delete this._resizer;
-}
-if(this._resizeHandle){
-dojo.disconnect(this._resizeHandle);
-delete this._resizeHandle;
-}
-this.inherited(arguments);
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _15=o.args.name.toLowerCase();
-if(_15==="viewsource"){
-o.plugin=new dijit._editor.plugins.ViewSource({readOnly:("readOnly" in o.args)?o.args.readOnly:false,stripComments:("stripComments" in o.args)?o.args.stripComments:true,stripScripts:("stripScripts" in o.args)?o.args.stripScripts:true,stripIFrames:("stripIFrames" in o.args)?o.args.stripIFrames:true});
-}
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name ===  "viewsource"){
+		o.plugin = new dijit._editor.plugins.ViewSource({
+			readOnly: ("readOnly" in o.args)?o.args.readOnly:false,
+			stripComments: ("stripComments" in o.args)?o.args.stripComments:true,
+			stripScripts: ("stripScripts" in o.args)?o.args.stripScripts:true,
+			stripIFrames: ("stripIFrames" in o.args)?o.args.stripIFrames:true
+		});
+	}
 });
-}
diff --git a/dijit/_editor/range.js b/dijit/_editor/range.js
index efe0736..873bb2d 100644
--- a/dijit/_editor/range.js
+++ b/dijit/_editor/range.js
@@ -1,453 +1,529 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._editor.range"]){
-dojo._hasResource["dijit._editor.range"]=true;
 dojo.provide("dijit._editor.range");
+
 dijit.range={};
-dijit.range.getIndex=function(_1,_2){
-var _3=[],_4=[];
-var _5=_2;
-var _6=_1;
-var _7,n;
-while(_1!=_5){
-var i=0;
-_7=_1.parentNode;
-while((n=_7.childNodes[i++])){
-if(n===_1){
---i;
-break;
-}
-}
-if(i>=_7.childNodes.length){
-dojo.debug("Error finding index of a node in dijit.range.getIndex");
-}
-_3.unshift(i);
-_4.unshift(i-_7.childNodes.length);
-_1=_7;
-}
-if(_3.length>0&&_6.nodeType==3){
-n=_6.previousSibling;
-while(n&&n.nodeType==3){
-_3[_3.length-1]--;
-n=n.previousSibling;
-}
-n=_6.nextSibling;
-while(n&&n.nodeType==3){
-_4[_4.length-1]++;
-n=n.nextSibling;
-}
-}
-return {o:_3,r:_4};
-};
-dijit.range.getNode=function(_8,_9){
-if(!dojo.isArray(_8)||_8.length==0){
-return _9;
-}
-var _a=_9;
-dojo.every(_8,function(i){
-if(i>=0&&i<_a.childNodes.length){
-_a=_a.childNodes[i];
-}else{
-_a=null;
-return false;
-}
-return true;
-});
-return _a;
-};
-dijit.range.getCommonAncestor=function(n1,n2){
-var _b=function(n){
-var as=[];
-while(n){
-as.unshift(n);
-if(n.nodeName!="BODY"){
-n=n.parentNode;
-}else{
-break;
-}
-}
-return as;
-};
-var _c=_b(n1);
-var _d=_b(n2);
-var m=Math.min(_c.length,_d.length);
-var _e=_c[0];
-for(var i=1;i<m;i++){
-if(_c[i]===_d[i]){
-_e=_c[i];
-}else{
-break;
-}
-}
-return _e;
-};
-dijit.range.getAncestor=function(_f,_10,_11){
-_11=_11||_f.ownerDocument.body;
-while(_f&&_f!==_11){
-var _12=_f.nodeName.toUpperCase();
-if(_10.test(_12)){
-return _f;
-}
-_f=_f.parentNode;
-}
-return null;
-};
-dijit.range.BlockTagNames=/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/;
-dijit.range.getBlockAncestor=function(_13,_14,_15){
-_15=_15||_13.ownerDocument.body;
-_14=_14||dijit.range.BlockTagNames;
-var _16=null,_17;
-while(_13&&_13!==_15){
-var _18=_13.nodeName.toUpperCase();
-if(!_16&&_14.test(_18)){
-_16=_13;
-}
-if(!_17&&(/^(?:BODY|TD|TH|CAPTION)$/).test(_18)){
-_17=_13;
-}
-_13=_13.parentNode;
-}
-return {blockNode:_16,blockContainer:_17||_13.ownerDocument.body};
-};
-dijit.range.atBeginningOfContainer=function(_19,_1a,_1b){
-var _1c=false;
-var _1d=(_1b==0);
-if(!_1d&&_1a.nodeType==3){
-if(/^[\s\xA0]+$/.test(_1a.nodeValue.substr(0,_1b))){
-_1d=true;
-}
-}
-if(_1d){
-var _1e=_1a;
-_1c=true;
-while(_1e&&_1e!==_19){
-if(_1e.previousSibling){
-_1c=false;
-break;
-}
-_1e=_1e.parentNode;
-}
-}
-return _1c;
-};
-dijit.range.atEndOfContainer=function(_1f,_20,_21){
-var _22=false;
-var _23=(_21==(_20.length||_20.childNodes.length));
-if(!_23&&_20.nodeType==3){
-if(/^[\s\xA0]+$/.test(_20.nodeValue.substr(_21))){
-_23=true;
+
+dijit.range.getIndex=function(/*DomNode*/node, /*DomNode*/parent){
+//	dojo.profile.start("dijit.range.getIndex");
+	var ret=[], retR=[];
+	var stop = parent;
+	var onode = node;
+
+	var pnode, n;
+	while(node != stop){
+		var i = 0;
+		pnode = node.parentNode;
+		while((n=pnode.childNodes[i++])){
+			if(n === node){
+				--i;
+				break;
+			}
+		}
+		//if(i>=pnode.childNodes.length){
+			//dojo.debug("Error finding index of a node in dijit.range.getIndex");
+		//}
+		ret.unshift(i);
+		retR.unshift(i-pnode.childNodes.length);
+		node = pnode;
+	}
+
+	//normalized() can not be called so often to prevent
+	//invalidating selection/range, so we have to detect
+	//here that any text nodes in a row
+	if(ret.length > 0 && onode.nodeType == 3){
+		n = onode.previousSibling;
+		while(n && n.nodeType == 3){
+			ret[ret.length-1]--;
+			n = n.previousSibling;
+		}
+		n = onode.nextSibling;
+		while(n && n.nodeType == 3){
+			retR[retR.length-1]++;
+			n = n.nextSibling;
+		}
+	}
+//	dojo.profile.end("dijit.range.getIndex");
+	return {o: ret, r:retR};
 }
+
+dijit.range.getNode = function(/*Array*/index, /*DomNode*/parent){
+	if(!dojo.isArray(index) || index.length == 0){
+		return parent;
+	}
+	var node = parent;
+//	if(!node)debugger
+	dojo.every(index, function(i){
+		if(i >= 0 && i < node.childNodes.length){
+			node = node.childNodes[i];
+		}else{
+			node = null;
+			//console.debug('Error: can not find node with index',index,'under parent node',parent );
+			return false; //terminate dojo.every
+		}
+		return true; //carry on the every loop
+	});
+
+	return node;
 }
-if(_23){
-var _24=_20;
-_22=true;
-while(_24&&_24!==_1f){
-if(_24.nextSibling){
-_22=false;
-break;
+
+dijit.range.getCommonAncestor = function(n1,n2,root){
+	root = root||n1.ownerDocument.body;
+	var getAncestors = function(n){
+		var as=[];
+		while(n){
+			as.unshift(n);
+			if(n !== root){
+				n = n.parentNode;
+			}else{
+				break;
+			}
+		}
+		return as;
+	};
+	var n1as = getAncestors(n1);
+	var n2as = getAncestors(n2);
+
+	var m = Math.min(n1as.length,n2as.length);
+	var com = n1as[0]; //at least, one element should be in the array: the root (BODY by default)
+	for(var i=1;i<m;i++){
+		if(n1as[i] === n2as[i]){
+			com = n1as[i]
+		}else{
+			break;
+		}
+	}
+	return com;
 }
-_24=_24.parentNode;
+
+dijit.range.getAncestor = function(/*DomNode*/node, /*RegEx?*/regex, /*DomNode?*/root){
+	root = root || node.ownerDocument.body;
+	while(node && node !== root){
+		var name = node.nodeName.toUpperCase() ;
+		if(regex.test(name)){
+			return node;
+		}
+
+		node = node.parentNode;
+	}
+	return null;
 }
+
+dijit.range.BlockTagNames = /^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/;
+dijit.range.getBlockAncestor = function(/*DomNode*/node, /*RegEx?*/regex, /*DomNode?*/root){
+	root = root || node.ownerDocument.body;
+	regex = regex || dijit.range.BlockTagNames;
+	var block=null, blockContainer;
+	while(node && node !== root){
+		var name = node.nodeName.toUpperCase() ;
+		if(!block && regex.test(name)){
+			block = node;
+		}
+		if(!blockContainer && (/^(?:BODY|TD|TH|CAPTION)$/).test(name)){
+			blockContainer = node;
+		}
+
+		node = node.parentNode;
+	}
+	return {blockNode:block, blockContainer:blockContainer || node.ownerDocument.body};
 }
-return _22;
-};
-dijit.range.adjacentNoneTextNode=function(_25,_26){
-var _27=_25;
-var len=(0-_25.length)||0;
-var _28=_26?"nextSibling":"previousSibling";
-while(_27){
-if(_27.nodeType!=3){
-break;
+
+dijit.range.atBeginningOfContainer = function(/*DomNode*/container, /*DomNode*/node, /*Int*/offset){
+	var atBeginning = false;
+	var offsetAtBeginning = (offset == 0);
+	if(!offsetAtBeginning && node.nodeType == 3){ //if this is a text node, check whether the left part is all space
+		if(/^[\s\xA0]+$/.test(node.nodeValue.substr(0,offset))){
+			offsetAtBeginning = true;
+		}
+	}
+	if(offsetAtBeginning){
+		var cnode = node;
+		atBeginning = true;
+		while(cnode && cnode !== container){
+			if(cnode.previousSibling){
+				atBeginning = false;
+				break;
+			}
+			cnode = cnode.parentNode;
+		}
+	}
+	return atBeginning;
 }
-len+=_27.length;
-_27=_27[_28];
+
+dijit.range.atEndOfContainer = function(/*DomNode*/container, /*DomNode*/node, /*Int*/offset){
+	var atEnd = false;
+	var offsetAtEnd = (offset == (node.length || node.childNodes.length));
+	if(!offsetAtEnd && node.nodeType == 3){ //if this is a text node, check whether the right part is all space
+		if(/^[\s\xA0]+$/.test(node.nodeValue.substr(offset))){
+			offsetAtEnd = true;
+		}
+	}
+	if(offsetAtEnd){
+		var cnode = node;
+		atEnd = true;
+		while(cnode && cnode !== container){
+			if(cnode.nextSibling){
+				atEnd = false;
+				break;
+			}
+			cnode = cnode.parentNode;
+		}
+	}
+	return atEnd;
 }
-return [_27,len];
-};
-dijit.range._w3c=Boolean(window["getSelection"]);
-dijit.range.create=function(win){
-if(dijit.range._w3c){
-return (win||dojo.global).document.createRange();
-}else{
-return new dijit.range.W3CRange;
+
+dijit.range.adjacentNoneTextNode=function(startnode, next){
+	var node = startnode;
+	var len = (0-startnode.length) || 0;
+	var prop = next?'nextSibling':'previousSibling';
+	while(node){
+		if(node.nodeType!=3){
+			break;
+		}
+		len += node.length
+		node = node[prop];
+	}
+	return [node,len];
 }
-};
-dijit.range.getSelection=function(win,_29){
-if(dijit.range._w3c){
-return win.getSelection();
-}else{
-var s=new dijit.range.ie.selection(win);
-if(!_29){
-s._getCurrentSelection();
+
+dijit.range._w3c = Boolean(window['getSelection']);
+dijit.range.create = function(/*Window?*/win){
+	if(dijit.range._w3c){
+		return (win || dojo.global).document.createRange();
+	}else{//IE
+		return new dijit.range.W3CRange;
+	}
 }
-return s;
+
+dijit.range.getSelection = function(/*Window*/win, /*Boolean?*/ignoreUpdate){
+	if(dijit.range._w3c){
+		return win.getSelection();
+	}else{//IE
+		var s = new dijit.range.ie.selection(win);
+		if(!ignoreUpdate){
+			s._getCurrentSelection();
+		}
+		return s;
+	}
 }
-};
+
 if(!dijit.range._w3c){
-dijit.range.ie={cachedSelection:{},selection:function(win){
-this._ranges=[];
-this.addRange=function(r,_2a){
-this._ranges.push(r);
-if(!_2a){
-r._select();
-}
-this.rangeCount=this._ranges.length;
-};
-this.removeAllRanges=function(){
-this._ranges=[];
-this.rangeCount=0;
-};
-var _2b=function(){
-var r=win.document.selection.createRange();
-var _2c=win.document.selection.type.toUpperCase();
-if(_2c=="CONTROL"){
-return new dijit.range.W3CRange(dijit.range.ie.decomposeControlRange(r));
-}else{
-return new dijit.range.W3CRange(dijit.range.ie.decomposeTextRange(r));
-}
-};
-this.getRangeAt=function(i){
-return this._ranges[i];
-};
-this._getCurrentSelection=function(){
-this.removeAllRanges();
-var r=_2b();
-if(r){
-this.addRange(r,true);
-}
-};
-},decomposeControlRange:function(_2d){
-var _2e=_2d.item(0),_2f=_2d.item(_2d.length-1);
-var _30=_2e.parentNode,_31=_2f.parentNode;
-var _32=dijit.range.getIndex(_2e,_30).o;
-var _33=dijit.range.getIndex(_2f,_31).o+1;
-return [_30,_32,_31,_33];
-},getEndPoint:function(_34,end){
-var _35=_34.duplicate();
-_35.collapse(!end);
-var _36="EndTo"+(end?"End":"Start");
-var _37=_35.parentElement();
-var _38,_39,_3a;
-if(_37.childNodes.length>0){
-dojo.every(_37.childNodes,function(_3b,i){
-var _3c;
-if(_3b.nodeType!=3){
-_35.moveToElementText(_3b);
-if(_35.compareEndPoints(_36,_34)>0){
-if(_3a&&_3a.nodeType==3){
-_38=_3a;
-_3c=true;
-}else{
-_38=_37;
-_39=i;
-return false;
-}
-}else{
-if(i==_37.childNodes.length-1){
-_38=_37;
-_39=_37.childNodes.length;
-return false;
-}
-}
-}else{
-if(i==_37.childNodes.length-1){
-_38=_3b;
-_3c=true;
-}
-}
-if(_3c&&_38){
-var _3d=dijit.range.adjacentNoneTextNode(_38)[0];
-if(_3d){
-_38=_3d.nextSibling;
-}else{
-_38=_37.firstChild;
-}
-var _3e=dijit.range.adjacentNoneTextNode(_38);
-_3d=_3e[0];
-var _3f=_3e[1];
-if(_3d){
-_35.moveToElementText(_3d);
-_35.collapse(false);
-}else{
-_35.moveToElementText(_37);
-}
-_35.setEndPoint(_36,_34);
-_39=_35.text.length-_3f;
-return false;
+	dijit.range.ie={
+		cachedSelection: {},
+		selection: function(win){
+			this._ranges = [];
+			this.addRange = function(r, /*boolean*/internal){
+				this._ranges.push(r);
+				if(!internal){
+					r._select();
+				}
+				this.rangeCount = this._ranges.length;
+			};
+			this.removeAllRanges = function(){
+				//don't detach, the range may be used later
+//				for(var i=0;i<this._ranges.length;i++){
+//					this._ranges[i].detach();
+//				}
+				this._ranges = [];
+				this.rangeCount = 0;
+			};
+			var _initCurrentRange = function(){
+				var r = win.document.selection.createRange();
+				var type=win.document.selection.type.toUpperCase();
+				if(type == "CONTROL"){
+					//TODO: multiple range selection(?)
+					return new dijit.range.W3CRange(dijit.range.ie.decomposeControlRange(r));
+				}else{
+					return new dijit.range.W3CRange(dijit.range.ie.decomposeTextRange(r));
+				}
+			};
+			this.getRangeAt = function(i){
+				return this._ranges[i];
+			};
+			this._getCurrentSelection = function(){
+				this.removeAllRanges();
+				var r=_initCurrentRange();
+				if(r){
+					this.addRange(r, true);
+				}
+			};
+		},
+		decomposeControlRange: function(range){
+			var firstnode = range.item(0), lastnode = range.item(range.length-1);
+			var startContainer = firstnode.parentNode, endContainer = lastnode.parentNode;
+			var startOffset = dijit.range.getIndex(firstnode, startContainer).o;
+			var endOffset = dijit.range.getIndex(lastnode, endContainer).o+1;
+			return [startContainer, startOffset,endContainer, endOffset];
+		},
+		getEndPoint: function(range, end){
+			var atmrange = range.duplicate();
+			atmrange.collapse(!end);
+			var cmpstr = 'EndTo' + (end?'End':'Start');
+			var parentNode = atmrange.parentElement();
+
+			var startnode, startOffset, lastNode;
+			if(parentNode.childNodes.length>0){
+				dojo.every(parentNode.childNodes, function(node,i){
+					var calOffset;
+					if(node.nodeType != 3){
+						atmrange.moveToElementText(node);
+
+						if(atmrange.compareEndPoints(cmpstr,range) > 0){
+							//startnode = node.previousSibling;
+							if(lastNode && lastNode.nodeType == 3){
+								//where shall we put the start? in the text node or after?
+								startnode = lastNode;
+								calOffset = true;
+							}else{
+								startnode = parentNode;
+								startOffset = i;
+								return false;
+							}
+						}else{
+							if(i == parentNode.childNodes.length-1){
+								startnode = parentNode;
+								startOffset = parentNode.childNodes.length;
+								return false;
+							}
+						}
+					}else{
+						if(i == parentNode.childNodes.length-1){//at the end of this node
+							startnode = node;
+							calOffset = true;
+						}
+					}
+		//			try{
+						if(calOffset && startnode){
+							var prevnode = dijit.range.adjacentNoneTextNode(startnode)[0];
+							if(prevnode){
+								startnode = prevnode.nextSibling;
+							}else{
+								startnode = parentNode.firstChild; //firstChild must be a text node
+							}
+							var prevnodeobj = dijit.range.adjacentNoneTextNode(startnode);
+							prevnode = prevnodeobj[0];
+							var lenoffset = prevnodeobj[1];
+							if(prevnode){
+								atmrange.moveToElementText(prevnode);
+								atmrange.collapse(false);
+							}else{
+								atmrange.moveToElementText(parentNode);
+							}
+							atmrange.setEndPoint(cmpstr, range);
+							startOffset = atmrange.text.length-lenoffset;
+
+							return false;
+						}
+		//			}catch(e){ debugger }
+					lastNode = node;
+					return true;
+				});
+			}else{
+				startnode = parentNode;
+				startOffset = 0;
+			}
+
+			//if at the end of startnode and we are dealing with start container, then
+			//move the startnode to nextSibling if it is a text node
+			//TODO: do this for end container?
+			if(!end && startnode.nodeType == 1 && startOffset == startnode.childNodes.length){
+				var nextnode=startnode.nextSibling;
+				if(nextnode && nextnode.nodeType == 3){
+					startnode = nextnode;
+					startOffset = 0;
+				}
+			}
+			return [startnode, startOffset];
+		},
+		setEndPoint: function(range, container, offset){
+			//text node
+			var atmrange = range.duplicate(), node, len;
+			if(container.nodeType!=3){ //normal node
+				if(offset > 0){
+					node = container.childNodes[offset-1];
+					if(node){
+						if(node.nodeType == 3){
+							container = node;
+							offset = node.length;
+							//pass through
+						}else{
+							if(node.nextSibling && node.nextSibling.nodeType == 3){
+								container=node.nextSibling;
+								offset=0;
+								//pass through
+							}else{
+								atmrange.moveToElementText(node.nextSibling?node:container);
+								var parent = node.parentNode;
+								var tempNode = parent.insertBefore(node.ownerDocument.createTextNode(' '), node.nextSibling);
+								atmrange.collapse(false);
+								parent.removeChild(tempNode);
+							}
+						}
+					}
+				}else{
+					atmrange.moveToElementText(container);
+					atmrange.collapse(true);
+				}
+			}
+			if(container.nodeType == 3){
+				var prevnodeobj = dijit.range.adjacentNoneTextNode(container);
+				var prevnode = prevnodeobj[0];
+				len = prevnodeobj[1];
+				if(prevnode){
+					atmrange.moveToElementText(prevnode);
+					atmrange.collapse(false);
+					//if contentEditable is not inherit, the above collapse won't make the end point
+					//in the correctly position: it always has a -1 offset, so compensate it
+					if(prevnode.contentEditable!='inherit'){
+						len++;
+					}
+				}else{
+					atmrange.moveToElementText(container.parentNode);
+					atmrange.collapse(true);
+				}
+
+				offset += len;
+				if(offset>0){
+					if(atmrange.move('character',offset) != offset){
+						console.error('Error when moving!');
+					}
+				}
+			}
+
+			return atmrange;
+		},
+		decomposeTextRange: function(range){
+			var tmpary = dijit.range.ie.getEndPoint(range);
+			var startContainer = tmpary[0], startOffset = tmpary[1];
+			var endContainer = tmpary[0], endOffset = tmpary[1];
+
+			if(range.htmlText.length){
+				if(range.htmlText == range.text){ //in the same text node
+					endOffset = startOffset+range.text.length;
+				}else{
+					tmpary = dijit.range.ie.getEndPoint(range,true);
+					endContainer = tmpary[0], endOffset = tmpary[1];
+//					if(startContainer.tagName == "BODY"){
+//						startContainer = startContainer.firstChild;
+//					}
+				}
+			}
+			return [startContainer, startOffset, endContainer, endOffset];
+		},
+		setRange: function(range, startContainer,
+			startOffset, endContainer, endOffset, collapsed){
+			var start=dijit.range.ie.setEndPoint(range, startContainer, startOffset);
+
+			range.setEndPoint('StartToStart',start);
+			if(!collapsed){
+				var end=dijit.range.ie.setEndPoint(range, endContainer, endOffset);
+			}
+			range.setEndPoint('EndToEnd',end || start);
+
+			return range;
+		}
+	}
+
+dojo.declare("dijit.range.W3CRange",null, {
+	constructor: function(){
+		if(arguments.length>0){
+			this.setStart(arguments[0][0],arguments[0][1]);
+			this.setEnd(arguments[0][2],arguments[0][3]);
+		}else{
+			this.commonAncestorContainer = null;
+			this.startContainer = null;
+			this.startOffset = 0;
+			this.endContainer = null;
+			this.endOffset = 0;
+			this.collapsed = true;
+		}
+	},
+	_updateInternal: function(){
+		if(this.startContainer !== this.endContainer){
+			this.commonAncestorContainer = dijit.range.getCommonAncestor(this.startContainer, this.endContainer);
+		}else{
+			this.commonAncestorContainer = this.startContainer;
+		}
+		this.collapsed = (this.startContainer === this.endContainer) && (this.startOffset == this.endOffset);
+	},
+	setStart: function(node, offset){
+		offset=parseInt(offset);
+		if(this.startContainer === node && this.startOffset == offset){
+			return;
+		}
+		delete this._cachedBookmark;
+
+		this.startContainer = node;
+		this.startOffset = offset;
+		if(!this.endContainer){
+			this.setEnd(node, offset);
+		}else{
+			this._updateInternal();
+		}
+	},
+	setEnd: function(node, offset){
+		offset=parseInt(offset);
+		if(this.endContainer === node && this.endOffset == offset){
+			return;
+		}
+		delete this._cachedBookmark;
+
+		this.endContainer = node;
+		this.endOffset = offset;
+		if(!this.startContainer){
+			this.setStart(node, offset);
+		}else{
+			this._updateInternal();
+		}
+	},
+	setStartAfter: function(node, offset){
+		this._setPoint('setStart', node, offset, 1);
+	},
+	setStartBefore: function(node, offset){
+		this._setPoint('setStart', node, offset, 0);
+	},
+	setEndAfter: function(node, offset){
+		this._setPoint('setEnd', node, offset, 1);
+	},
+	setEndBefore: function(node, offset){
+		this._setPoint('setEnd', node, offset, 0);
+	},
+	_setPoint: function(what, node, offset, ext){
+		var index = dijit.range.getIndex(node, node.parentNode).o;
+		this[what](node.parentNode, index.pop()+ext);
+	},
+	_getIERange: function(){
+		var r = (this._body || this.endContainer.ownerDocument.body).createTextRange();
+		dijit.range.ie.setRange(r, this.startContainer, this.startOffset, this.endContainer, this.endOffset, this.collapsed);
+		return r;
+	},
+	getBookmark: function(body){
+		this._getIERange();
+		return this._cachedBookmark;
+	},
+	_select: function(){
+		var r = this._getIERange();
+		r.select();
+	},
+	deleteContents: function(){
+		var r = this._getIERange();
+		r.pasteHTML('');
+		this.endContainer = this.startContainer;
+		this.endOffset = this.startOffset;
+		this.collapsed = true;
+	},
+	cloneRange: function(){
+		var r = new dijit.range.W3CRange([this.startContainer,this.startOffset,
+			this.endContainer,this.endOffset]);
+		r._body = this._body;
+		return r;
+	},
+	detach: function(){
+		this._body = null;
+		this.commonAncestorContainer = null;
+		this.startContainer = null;
+		this.startOffset = 0;
+		this.endContainer = null;
+		this.endOffset = 0;
+		this.collapsed = true;
 }
-_3a=_3b;
-return true;
 });
-}else{
-_38=_37;
-_39=0;
-}
-if(!end&&_38.nodeType==1&&_39==_38.childNodes.length){
-var _40=_38.nextSibling;
-if(_40&&_40.nodeType==3){
-_38=_40;
-_39=0;
-}
-}
-return [_38,_39];
-},setEndPoint:function(_41,_42,_43){
-var _44=_41.duplicate(),_45,len;
-if(_42.nodeType!=3){
-if(_43>0){
-_45=_42.childNodes[_43-1];
-if(_45.nodeType==3){
-_42=_45;
-_43=_45.length;
-}else{
-if(_45.nextSibling&&_45.nextSibling.nodeType==3){
-_42=_45.nextSibling;
-_43=0;
-}else{
-_44.moveToElementText(_45.nextSibling?_45:_42);
-var _46=_45.parentNode;
-var _47=_46.insertBefore(_45.ownerDocument.createTextNode(" "),_45.nextSibling);
-_44.collapse(false);
-_46.removeChild(_47);
-}
-}
-}else{
-_44.moveToElementText(_42);
-_44.collapse(true);
-}
-}
-if(_42.nodeType==3){
-var _48=dijit.range.adjacentNoneTextNode(_42);
-var _49=_48[0];
-len=_48[1];
-if(_49){
-_44.moveToElementText(_49);
-_44.collapse(false);
-if(_49.contentEditable!="inherit"){
-len++;
-}
-}else{
-_44.moveToElementText(_42.parentNode);
-_44.collapse(true);
-}
-_43+=len;
-if(_43>0){
-if(_44.move("character",_43)!=_43){
-console.error("Error when moving!");
-}
-}
-}
-return _44;
-},decomposeTextRange:function(_4a){
-var _4b=dijit.range.ie.getEndPoint(_4a);
-var _4c=_4b[0],_4d=_4b[1];
-var _4e=_4b[0],_4f=_4b[1];
-if(_4a.htmlText.length){
-if(_4a.htmlText==_4a.text){
-_4f=_4d+_4a.text.length;
-}else{
-_4b=dijit.range.ie.getEndPoint(_4a,true);
-_4e=_4b[0],_4f=_4b[1];
-}
-}
-return [_4c,_4d,_4e,_4f];
-},setRange:function(_50,_51,_52,_53,_54,_55){
-var _56=dijit.range.ie.setEndPoint(_50,_51,_52);
-_50.setEndPoint("StartToStart",_56);
-if(!_55){
-var end=dijit.range.ie.setEndPoint(_50,_53,_54);
-}
-_50.setEndPoint("EndToEnd",end||_56);
-return _50;
-}};
-dojo.declare("dijit.range.W3CRange",null,{constructor:function(){
-if(arguments.length>0){
-this.setStart(arguments[0][0],arguments[0][1]);
-this.setEnd(arguments[0][2],arguments[0][3]);
-}else{
-this.commonAncestorContainer=null;
-this.startContainer=null;
-this.startOffset=0;
-this.endContainer=null;
-this.endOffset=0;
-this.collapsed=true;
-}
-},_updateInternal:function(){
-if(this.startContainer!==this.endContainer){
-this.commonAncestorContainer=dijit.range.getCommonAncestor(this.startContainer,this.endContainer);
-}else{
-this.commonAncestorContainer=this.startContainer;
-}
-this.collapsed=(this.startContainer===this.endContainer)&&(this.startOffset==this.endOffset);
-},setStart:function(_57,_58){
-_58=parseInt(_58);
-if(this.startContainer===_57&&this.startOffset==_58){
-return;
-}
-delete this._cachedBookmark;
-this.startContainer=_57;
-this.startOffset=_58;
-if(!this.endContainer){
-this.setEnd(_57,_58);
-}else{
-this._updateInternal();
-}
-},setEnd:function(_59,_5a){
-_5a=parseInt(_5a);
-if(this.endContainer===_59&&this.endOffset==_5a){
-return;
-}
-delete this._cachedBookmark;
-this.endContainer=_59;
-this.endOffset=_5a;
-if(!this.startContainer){
-this.setStart(_59,_5a);
-}else{
-this._updateInternal();
-}
-},setStartAfter:function(_5b,_5c){
-this._setPoint("setStart",_5b,_5c,1);
-},setStartBefore:function(_5d,_5e){
-this._setPoint("setStart",_5d,_5e,0);
-},setEndAfter:function(_5f,_60){
-this._setPoint("setEnd",_5f,_60,1);
-},setEndBefore:function(_61,_62){
-this._setPoint("setEnd",_61,_62,0);
-},_setPoint:function(_63,_64,_65,ext){
-var _66=dijit.range.getIndex(_64,_64.parentNode).o;
-this[_63](_64.parentNode,_66.pop()+ext);
-},_getIERange:function(){
-var r=(this._body||this.endContainer.ownerDocument.body).createTextRange();
-dijit.range.ie.setRange(r,this.startContainer,this.startOffset,this.endContainer,this.endOffset,this.collapsed);
-return r;
-},getBookmark:function(_67){
-this._getIERange();
-return this._cachedBookmark;
-},_select:function(){
-var r=this._getIERange();
-r.select();
-},deleteContents:function(){
-var r=this._getIERange();
-r.pasteHTML("");
-this.endContainer=this.startContainer;
-this.endOffset=this.startOffset;
-this.collapsed=true;
-},cloneRange:function(){
-var r=new dijit.range.W3CRange([this.startContainer,this.startOffset,this.endContainer,this.endOffset]);
-r._body=this._body;
-return r;
-},detach:function(){
-this._body=null;
-this.commonAncestorContainer=null;
-this.startContainer=null;
-this.startOffset=0;
-this.endContainer=null;
-this.endOffset=0;
-this.collapsed=true;
-}});
-}
-}
+} //if(!dijit.range._w3c)
diff --git a/dijit/_editor/selection.js b/dijit/_editor/selection.js
index 1e3e510..37ea03d 100644
--- a/dijit/_editor/selection.js
+++ b/dijit/_editor/selection.js
@@ -1,226 +1,350 @@
-/*
-	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
-*/
+dojo.provide("dijit._editor.selection");
 
+// FIXME:
+//		all of these methods branch internally for IE. This is probably
+//		sub-optimal in terms of runtime performance. We should investigate the
+//		size difference for differentiating at definition time.
 
-if(!dojo._hasResource["dijit._editor.selection"]){
-dojo._hasResource["dijit._editor.selection"]=true;
-dojo.provide("dijit._editor.selection");
-dojo.mixin(dijit._editor.selection,{getType:function(){
-if(dojo.isIE){
-return dojo.doc.selection.type.toLowerCase();
-}else{
-var _1="text";
-var _2;
-try{
-_2=dojo.global.getSelection();
-}
-catch(e){
-}
-if(_2&&_2.rangeCount==1){
-var _3=_2.getRangeAt(0);
-if((_3.startContainer==_3.endContainer)&&((_3.endOffset-_3.startOffset)==1)&&(_3.startContainer.nodeType!=3)){
-_1="control";
-}
-}
-return _1;
-}
-},getSelectedText:function(){
-if(dojo.isIE){
-if(dijit._editor.selection.getType()=="control"){
-return null;
-}
-return dojo.doc.selection.createRange().text;
-}else{
-var _4=dojo.global.getSelection();
-if(_4){
-return _4.toString();
-}
-}
-return "";
-},getSelectedHtml:function(){
-if(dojo.isIE){
-if(dijit._editor.selection.getType()=="control"){
-return null;
-}
-return dojo.doc.selection.createRange().htmlText;
-}else{
-var _5=dojo.global.getSelection();
-if(_5&&_5.rangeCount){
-var i;
-var _6="";
-for(i=0;i<_5.rangeCount;i++){
-var _7=_5.getRangeAt(i).cloneContents();
-var _8=dojo.doc.createElement("div");
-_8.appendChild(_7);
-_6+=_8.innerHTML;
-}
-return _6;
-}
-return null;
-}
-},getSelectedElement:function(){
-if(dijit._editor.selection.getType()=="control"){
-if(dojo.isIE){
-var _9=dojo.doc.selection.createRange();
-if(_9&&_9.item){
-return dojo.doc.selection.createRange().item(0);
-}
-}else{
-var _a=dojo.global.getSelection();
-return _a.anchorNode.childNodes[_a.anchorOffset];
-}
-}
-return null;
-},getParentElement:function(){
-if(dijit._editor.selection.getType()=="control"){
-var p=this.getSelectedElement();
-if(p){
-return p.parentNode;
-}
-}else{
-if(dojo.isIE){
-var r=dojo.doc.selection.createRange();
-r.collapse(true);
-return r.parentElement();
-}else{
-var _b=dojo.global.getSelection();
-if(_b){
-var _c=_b.anchorNode;
-while(_c&&(_c.nodeType!=1)){
-_c=_c.parentNode;
-}
-return _c;
-}
-}
-}
-return null;
-},hasAncestorElement:function(_d){
-return this.getAncestorElement.apply(this,arguments)!=null;
-},getAncestorElement:function(_e){
-var _f=this.getSelectedElement()||this.getParentElement();
-return this.getParentOfType(_f,arguments);
-},isTag:function(_10,_11){
-if(_10&&_10.tagName){
-var _12=_10.tagName.toLowerCase();
-for(var i=0;i<_11.length;i++){
-var _13=String(_11[i]).toLowerCase();
-if(_12==_13){
-return _13;
-}
-}
-}
-return "";
-},getParentOfType:function(_14,_15){
-while(_14){
-if(this.isTag(_14,_15).length){
-return _14;
-}
-_14=_14.parentNode;
-}
-return null;
-},collapse:function(_16){
-if(window.getSelection){
-var _17=dojo.global.getSelection();
-if(_17.removeAllRanges){
-if(_16){
-_17.collapseToStart();
-}else{
-_17.collapseToEnd();
-}
-}else{
-_17.collapse(_16);
-}
-}else{
-if(dojo.isIE){
-var _18=dojo.doc.selection.createRange();
-_18.collapse(_16);
-_18.select();
-}
-}
-},remove:function(){
-var sel=dojo.doc.selection;
-if(dojo.isIE){
-if(sel.type.toLowerCase()!="none"){
-sel.clear();
-}
-return sel;
-}else{
-sel=dojo.global.getSelection();
-sel.deleteFromDocument();
-return sel;
-}
-},selectElementChildren:function(_19,_1a){
-var win=dojo.global;
-var doc=dojo.doc;
-var _1b;
-_19=dojo.byId(_19);
-if(doc.selection&&dojo.isIE&&dojo.body().createTextRange){
-_1b=_19.ownerDocument.body.createTextRange();
-_1b.moveToElementText(_19);
-if(!_1a){
-try{
-_1b.select();
-}
-catch(e){
-}
-}
-}else{
-if(win.getSelection){
-var _1c=dojo.global.getSelection();
-if(_1c.setBaseAndExtent){
-_1c.setBaseAndExtent(_19,0,_19,_19.innerText.length-1);
-}else{
-if(dojo.isOpera){
-if(_1c.rangeCount){
-_1b=_1c.getRangeAt(0);
-}else{
-_1b=doc.createRange();
-}
-_1b.setStart(_19,0);
-_1b.setEnd(_19,(_19.nodeType==3)?_19.length:_19.childNodes.length);
-_1c.addRange(_1b);
-}else{
-if(_1c.selectAllChildren){
-_1c.selectAllChildren(_19);
-}
-}
-}
-}
-}
-},selectElement:function(_1d,_1e){
-var _1f;
-var doc=dojo.doc;
-var win=dojo.global;
-_1d=dojo.byId(_1d);
-if(dojo.isIE&&dojo.body().createTextRange){
-try{
-_1f=dojo.body().createControlRange();
-_1f.addElement(_1d);
-if(!_1e){
-_1f.select();
-}
-}
-catch(e){
-this.selectElementChildren(_1d,_1e);
-}
-}else{
-if(dojo.global.getSelection){
-var _20=win.getSelection();
-_1f=doc.createRange();
-if(_20.removeAllRanges){
-if(dojo.isOpera){
-if(_20.getRangeAt(0)){
-_1f=_20.getRangeAt(0);
-}
-}
-_1f.selectNode(_1d);
-_20.removeAllRanges();
-_20.addRange(_1f);
-}
-}
-}
-}});
-}
+dojo.mixin(dijit._editor.selection, {
+	getType: function(){
+		// summary:
+		//		Get the selection type (like dojo.doc.select.type in IE).
+		if(dojo.isIE){
+			return dojo.doc.selection.type.toLowerCase();
+		}else{
+			var stype = "text";
+
+			// Check if the actual selection is a CONTROL (IMG, TABLE, HR, etc...).
+			var oSel;
+			try{
+				oSel = dojo.global.getSelection();
+			}catch(e){ /*squelch*/ }
+
+			if(oSel && oSel.rangeCount == 1){
+				var oRange = oSel.getRangeAt(0);
+				if(	(oRange.startContainer == oRange.endContainer) &&
+					((oRange.endOffset - oRange.startOffset) == 1) &&
+					(oRange.startContainer.nodeType != 3 /* text node*/)
+				){
+					stype = "control";
+				}
+			}
+			return stype; //String
+		}
+	},
+
+	getSelectedText: function(){
+		// summary:
+		//		Return the text (no html tags) included in the current selection or null if no text is selected
+		if(dojo.isIE){
+			if(dijit._editor.selection.getType() == 'control'){
+				return null;
+			}
+			return dojo.doc.selection.createRange().text;
+		}else{
+			var selection = dojo.global.getSelection();
+			if(selection){
+				return selection.toString(); //String
+			}
+		}
+		return '';
+	},
+
+	getSelectedHtml: function(){
+		// summary:
+		//		Return the html text of the current selection or null if unavailable
+		if(dojo.isIE){
+			if(dijit._editor.selection.getType() == 'control'){
+				return null;
+			}
+			return dojo.doc.selection.createRange().htmlText;
+		}else{
+			var selection = dojo.global.getSelection();
+			if(selection && selection.rangeCount){
+				var i;
+				var html = "";
+				for(i = 0; i < selection.rangeCount; i++){
+					//Handle selections spanning ranges, such as Opera
+					var frag = selection.getRangeAt(i).cloneContents();
+					var div = dojo.doc.createElement("div");
+					div.appendChild(frag);
+					html += div.innerHTML;
+				}
+				return html; //String
+			}
+			return null;
+		}
+	},
+
+	getSelectedElement: function(){
+		// summary:
+		//		Retrieves the selected element (if any), just in the case that
+		//		a single element (object like and image or a table) is
+		//		selected.
+		if(dijit._editor.selection.getType() == "control"){
+			if(dojo.isIE){
+				var range = dojo.doc.selection.createRange();
+				if(range && range.item){
+					return dojo.doc.selection.createRange().item(0);
+				}
+			}else{
+				var selection = dojo.global.getSelection();
+				return selection.anchorNode.childNodes[ selection.anchorOffset ];
+			}
+		}
+		return null;
+	},
+
+	getParentElement: function(){
+		// summary:
+		//		Get the parent element of the current selection
+		if(dijit._editor.selection.getType() == "control"){
+			var p = this.getSelectedElement();
+			if(p){ return p.parentNode; }
+		}else{
+			if(dojo.isIE){
+				var r = dojo.doc.selection.createRange();
+				r.collapse(true);
+				return r.parentElement();
+			}else{
+				var selection = dojo.global.getSelection();
+				if(selection){
+					var node = selection.anchorNode;
+					while(node && (node.nodeType != 1)){ // not an element
+						node = node.parentNode;
+					}
+					return node;
+				}
+			}
+		}
+		return null;
+	},
+
+	hasAncestorElement: function(/*String*/tagName /* ... */){
+		// summary:
+		// 		Check whether current selection has a  parent element which is
+		// 		of type tagName (or one of the other specified tagName)
+		// tagName: String
+		//		The tag name to determine if it has an ancestor of.
+		return this.getAncestorElement.apply(this, arguments) != null; //Boolean
+	},
+
+	getAncestorElement: function(/*String*/tagName /* ... */){
+		// summary:
+		//		Return the parent element of the current selection which is of
+		//		type tagName (or one of the other specified tagName)
+		// tagName: String
+		//		The tag name to determine if it has an ancestor of.
+		var node = this.getSelectedElement() || this.getParentElement();
+		return this.getParentOfType(node, arguments); //DOMNode
+	},
+
+	isTag: function(/*DomNode*/ node, /*String[]*/ tags){
+		// summary:
+		//		Function to determine if a node is one of an array of tags.
+		// node:
+		//		The node to inspect.
+		// tags:
+		//		An array of tag name strings to check to see if the node matches.
+		if(node && node.tagName){
+			var _nlc = node.tagName.toLowerCase();
+			for(var i=0; i<tags.length; i++){
+				var _tlc = String(tags[i]).toLowerCase();
+				if(_nlc == _tlc){
+					return _tlc; // String
+				}
+			}
+		}
+		return "";
+	},
+
+	getParentOfType: function(/*DomNode*/ node, /*String[]*/ tags){
+		// summary:
+		//		Function to locate a parent node that matches one of a set of tags
+		// node:
+		//		The node to inspect.
+		// tags:
+		//		An array of tag name strings to check to see if the node matches.
+		while(node){
+			if(this.isTag(node, tags).length){
+				return node; // DOMNode
+			}
+			node = node.parentNode;
+		}
+		return null;
+	},
+
+	collapse: function(/*Boolean*/beginning){
+		// summary:
+		//		Function to collapse (clear), the current selection
+		// beginning: Boolean
+		//		Boolean to indicate whether to collapse the cursor to the beginning of the selection or end.
+		if(window.getSelection){
+			var selection = dojo.global.getSelection();
+			if(selection.removeAllRanges){ // Mozilla
+				if(beginning){
+					selection.collapseToStart();
+				}else{
+					selection.collapseToEnd();
+				}
+			}else{ // Safari
+				// pulled from WebCore/ecma/kjs_window.cpp, line 2536
+				selection.collapse(beginning);
+			}
+		}else if(dojo.isIE){ // IE
+			var range = dojo.doc.selection.createRange();
+			range.collapse(beginning);
+			range.select();
+		}
+	},
+
+	remove: function(){
+		// summary:
+		//		Function to delete the currently selected content from the document.
+		var sel = dojo.doc.selection;
+		if(dojo.isIE){
+			if(sel.type.toLowerCase() != "none"){
+				sel.clear();
+			}
+			return sel; //Selection
+		}else{
+			sel = dojo.global.getSelection();
+			sel.deleteFromDocument();
+			return sel; //Selection
+		}
+	},
+
+	selectElementChildren: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
+		// summary:
+		//		clear previous selection and select the content of the node
+		//		(excluding the node itself)
+		// element: DOMNode
+		//		The element you wish to select the children content of.
+		// nochangefocus: Boolean
+		//		Boolean to indicate if the foxus should change or not.
+		var win = dojo.global;
+		var doc = dojo.doc;
+		var range;
+		element = dojo.byId(element);
+		if(doc.selection && dojo.isIE && dojo.body().createTextRange){ // IE
+			range = element.ownerDocument.body.createTextRange();
+			range.moveToElementText(element);
+			if(!nochangefocus){
+				try{
+					range.select(); // IE throws an exception here if the widget is hidden.  See #5439
+				}catch(e){ /* squelch */}
+			}
+		}else if(win.getSelection){
+			var selection = dojo.global.getSelection();
+			if(dojo.isOpera){
+				//Opera's selectAllChildren doesn't seem to work right
+				//against <body> nodes and possibly others ... so
+				//we use the W3C range API
+				if(selection.rangeCount){
+					range = selection.getRangeAt(0);
+				}else{
+					range = doc.createRange();
+				}
+				range.setStart(element, 0);
+				range.setEnd(element,(element.nodeType == 3)?element.length:element.childNodes.length);
+				selection.addRange(range);
+			}else{
+				selection.selectAllChildren(element);
+			}
+		}
+	},
+
+	selectElement: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
+		// summary:
+		//		clear previous selection and select element (including all its children)
+		// element:  DOMNode
+		//		The element to select.
+		// nochangefocus: Boolean
+		//		Boolean indicating if the focus should be changed.  IE only.
+		var range;
+		var doc = dojo.doc;
+		var win = dojo.global;
+		element = dojo.byId(element);
+		if(dojo.isIE && dojo.body().createTextRange){
+			try{
+				range = dojo.body().createControlRange();
+				range.addElement(element);
+				if(!nochangefocus){
+					range.select();
+				}
+			}catch(e){
+				this.selectElementChildren(element,nochangefocus);
+			}
+		}else if(dojo.global.getSelection){
+			var selection = win.getSelection();
+			range = doc.createRange();
+			if(selection.removeAllRanges){ // Mozilla
+				// FIXME: does this work on Safari?
+				if(dojo.isOpera){
+					//Opera works if you use the current range on
+					//the selection if present.
+					if(selection.getRangeAt(0)){
+						range = selection.getRangeAt(0);
+					}
+				}
+				range.selectNode(element);
+				selection.removeAllRanges();
+				selection.addRange(range);
+			}
+		}
+	},
+
+	inSelection: function(node){
+		// summary:
+		//		This function determines if 'node' is
+		//		in the current selection.
+		// tags:
+		//		public
+		if(node){
+			var newRange;
+			var doc = dojo.doc;
+			var range;
+
+			if(dojo.global.getSelection){
+				//WC3
+				var sel = dojo.global.getSelection();
+				if(sel && sel.rangeCount > 0){
+					range = sel.getRangeAt(0);
+				}
+				if(range && range.compareBoundaryPoints && doc.createRange){
+					try{
+						newRange = doc.createRange();
+						newRange.setStart(node, 0);
+						if(range.compareBoundaryPoints(range.START_TO_END, newRange) === 1){
+							return true;
+						}
+					}catch(e){ /* squelch */}
+				}
+			}else if(doc.selection){
+				// Probably IE, so we can't use the range object as the pseudo
+				// range doesn't implement the boundry checking, we have to 
+				// use IE specific crud.
+				range = doc.selection.createRange();
+				try{
+					newRange = node.ownerDocument.body.createControlRange();
+					if(newRange){
+						newRange.addElement(node);
+					}
+				}catch(e1){
+					try{
+						newRange = node.ownerDocument.body.createTextRange();
+						newRange.moveToElementText(node);
+					}catch(e2){/* squelch */}
+				}
+				if(range && newRange){
+					// We can finally compare similar to W3C
+					if(range.compareEndPoints("EndToStart", newRange) === 1){
+						return true;
+					}
+				}
+			}
+		}
+		return false; // boolean
+	}
+
+});
diff --git a/dijit/_tree/dndSource.js b/dijit/_tree/dndSource.js
index 48bab03..a9c93d8 100644
--- a/dijit/_tree/dndSource.js
+++ b/dijit/_tree/dndSource.js
@@ -1,14 +1,7 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit._tree.dndSource"]){
-dojo._hasResource["dijit._tree.dndSource"]=true;
 dojo.provide("dijit._tree.dndSource");
 dojo.require("dijit.tree.dndSource");
-dojo.deprecated("dijit._tree.dndSource has been moved to dijit.tree.dndSource, use that instead","","2.0");
-dijit._tree.dndSource=dijit.tree.dndSource;
-}
+
+// TODO: remove this file in 2.0
+dojo.deprecated("dijit._tree.dndSource has been moved to dijit.tree.dndSource, use that instead", "", "2.0");
+
+dijit._tree.dndSource = dijit.tree.dndSource;
diff --git a/dijit/dijit-all.js b/dijit/dijit-all.js
index 562907c..10be88a 100644
--- a/dijit/dijit-all.js
+++ b/dijit/dijit-all.js
@@ -1,16 +1,85 @@
-/*
-	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
-*/
+console.warn("dijit-all may include much more code than your application actually requires. We strongly recommend that you investigate a custom build or the web build tool");
+dojo.provide("dijit.dijit-all");
 
-/*
-	This is a compiled version of Dojo, built for deployment and not for
-	development. To get an editable version, please visit:
+/*=====
+dijit["dijit-all"] = {
+	// summary:
+	//		A rollup that includes every dijit. You probably don't need this.
+};
+=====*/
 
-		http://dojotoolkit.org
+dojo.require("dijit.dijit");
 
-	for documentation and information on getting the source.
-*/
+dojo.require("dijit.ColorPalette");
+dojo.require("dijit.Declaration");
 
-if(!dojo._hasResource["dojo.colors"]){dojo._hasResource["dojo.colors"]=true;dojo.provide("dojo.colors");(function(){var _1=function(m1,m2,h){if(h<0){++h;}if(h>1){--h;}var h6=6*h;if(h6<1){return m1+(m2-m1)*h6;}if(2*h<1){return m2;}if(3*h<2){return m1+(m2-m1)*(2/3-h)*6;}return m1;};dojo.colorFromRgb=function(_2,_3){var m=_2.toLowerCase().match(/^(rgba?|hsla?)\(([\s\.\-,%0-9]+)\)/);if(m){var c=m[2].split(/\s*,\s*/),l=c.length,t=m[1],a;if((t=="rgb"&&l==3)||(t=="rgba"&&l==4)){var r=c[0];if(r. [...]
+dojo.require("dijit.Dialog");
+dojo.require("dijit.DialogUnderlay");
+dojo.require("dijit.TooltipDialog");
+
+// Editor
+dojo.require("dijit.Editor");
+dojo.require("dijit._editor.plugins.FontChoice");
+dojo.require("dijit._editor.plugins.LinkDialog");
+
+dojo.require("dijit.Menu");
+dojo.require("dijit.MenuItem");
+dojo.require("dijit.PopupMenuItem");
+dojo.require("dijit.MenuBar");
+dojo.require("dijit.MenuBarItem");
+dojo.require("dijit.PopupMenuBarItem");
+dojo.require("dijit.MenuSeparator");
+
+dojo.require("dijit.ProgressBar");
+dojo.require("dijit.TitlePane");
+dojo.require("dijit.Toolbar");
+dojo.require("dijit.Tooltip");
+dojo.require("dijit.Tree");
+dojo.require("dijit.InlineEditBox");
+
+// Form widgets
+dojo.require("dijit.form.Form");
+
+// Button widgets
+dojo.require("dijit.form.Button");
+dojo.require("dijit.form.DropDownButton");
+dojo.require("dijit.form.ComboButton");
+dojo.require("dijit.form.ToggleButton");
+dojo.require("dijit.form.CheckBox");
+dojo.require("dijit.form.RadioButton");
+
+// TextBox widgets
+dojo.require("dijit.form.TextBox");
+dojo.require("dijit.form.ValidationTextBox");
+dojo.require("dijit.form.CurrencyTextBox");
+dojo.require("dijit.form.DateTextBox");
+dojo.require("dijit.form.NumberSpinner");
+dojo.require("dijit.form.NumberTextBox");
+
+// Select widgets
+dojo.require("dijit.form.ComboBox");
+dojo.require("dijit.form.FilteringSelect");
+dojo.require("dijit.form.MultiSelect");
+dojo.require("dijit.form.Select");
+
+// Slider widgets
+dojo.require("dijit.form.HorizontalSlider");
+dojo.require("dijit.form.VerticalSlider");
+dojo.require("dijit.form.HorizontalRule");
+dojo.require("dijit.form.VerticalRule");
+dojo.require("dijit.form.HorizontalRuleLabels");
+dojo.require("dijit.form.VerticalRuleLabels");
+
+// Textarea widgets
+dojo.require("dijit.form.SimpleTextarea");
+dojo.require("dijit.form.Textarea");
+
+// Layout widgets
+dojo.require("dijit.layout.AccordionContainer");
+dojo.require("dijit.layout.ContentPane");
+dojo.require("dijit.layout.BorderContainer");
+dojo.require("dijit.layout.LayoutContainer"); //deprecated
+dojo.require("dijit.layout.LinkPane");
+dojo.require("dijit.layout.SplitContainer"); //deprecated
+dojo.require("dijit.layout.StackContainer");
+dojo.require("dijit.layout.TabContainer");
diff --git a/dijit/dijit-all.js.uncompressed.js b/dijit/dijit-all.js.uncompressed.js
deleted file mode 100644
index a44d0ef..0000000
--- a/dijit/dijit-all.js.uncompressed.js
+++ /dev/null
@@ -1,24901 +0,0 @@
-/*
-	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.colors"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.colors"] = true;
-dojo.provide("dojo.colors");
-
-//TODO: this module appears to break naming conventions
-
-/*=====
-dojo.colors = {
-	// summary: Color utilities
-}
-=====*/
-
-(function(){
-	// this is a standard conversion prescribed by the CSS3 Color Module
-	var hue2rgb = function(m1, m2, h){
-		if(h < 0){ ++h; }
-		if(h > 1){ --h; }
-		var h6 = 6 * h;
-		if(h6 < 1){ return m1 + (m2 - m1) * h6; }
-		if(2 * h < 1){ return m2; }
-		if(3 * h < 2){ return m1 + (m2 - m1) * (2 / 3 - h) * 6; }
-		return m1;
-	};
-	
-	dojo.colorFromRgb = function(/*String*/ color, /*dojo.Color?*/ obj){
-		// summary:
-		//		get rgb(a) array from css-style color declarations
-		// description:
-		//		this function can handle all 4 CSS3 Color Module formats: rgb,
-		//		rgba, hsl, hsla, including rgb(a) with percentage values.
-		var m = color.toLowerCase().match(/^(rgba?|hsla?)\(([\s\.\-,%0-9]+)\)/);
-		if(m){
-			var c = m[2].split(/\s*,\s*/), l = c.length, t = m[1], a;
-			if((t == "rgb" && l == 3) || (t == "rgba" && l == 4)){
-				var r = c[0];
-				if(r.charAt(r.length - 1) == "%"){
-					// 3 rgb percentage values
-					a = dojo.map(c, function(x){
-						return parseFloat(x) * 2.56;
-					});
-					if(l == 4){ a[3] = c[3]; }
-					return dojo.colorFromArray(a, obj);	// dojo.Color
-				}
-				return dojo.colorFromArray(c, obj);	// dojo.Color
-			}
-			if((t == "hsl" && l == 3) || (t == "hsla" && l == 4)){
-				// normalize hsl values
-				var H = ((parseFloat(c[0]) % 360) + 360) % 360 / 360,
-					S = parseFloat(c[1]) / 100,
-					L = parseFloat(c[2]) / 100,
-					// calculate rgb according to the algorithm 
-					// recommended by the CSS3 Color Module 
-					m2 = L <= 0.5 ? L * (S + 1) : L + S - L * S, 
-					m1 = 2 * L - m2;
-				a = [
-					hue2rgb(m1, m2, H + 1 / 3) * 256,
-					hue2rgb(m1, m2, H) * 256,
-					hue2rgb(m1, m2, H - 1 / 3) * 256,
-					1
-				];
-				if(l == 4){ a[3] = c[3]; }
-				return dojo.colorFromArray(a, obj);	// dojo.Color
-			}
-		}
-		return null;	// dojo.Color
-	};
-	
-	var confine = function(c, low, high){
-		// summary:
-		//		sanitize a color component by making sure it is a number,
-		//		and clamping it to valid values
-		c = Number(c);
-		return isNaN(c) ? high : c < low ? low : c > high ? high : c;	// Number
-	};
-	
-	dojo.Color.prototype.sanitize = function(){
-		// summary: makes sure that the object has correct attributes
-		var t = this;
-		t.r = Math.round(confine(t.r, 0, 255));
-		t.g = Math.round(confine(t.g, 0, 255));
-		t.b = Math.round(confine(t.b, 0, 255));
-		t.a = confine(t.a, 0, 1);
-		return this;	// dojo.Color
-	};
-})();
-
-
-dojo.colors.makeGrey = function(/*Number*/ g, /*Number?*/ a){
-	// summary: creates a greyscale color with an optional alpha
-	return dojo.colorFromArray([g, g, g, a]);
-};
-
-// mixin all CSS3 named colors not already in _base, along with SVG 1.0 variant spellings
-dojo.mixin(dojo.Color.named, {
-	aliceblue:	[240,248,255],
-	antiquewhite:	[250,235,215],
-	aquamarine:	[127,255,212],
-	azure:	[240,255,255],
-	beige:	[245,245,220],
-	bisque:	[255,228,196],
-	blanchedalmond:	[255,235,205],
-	blueviolet:	[138,43,226],
-	brown:	[165,42,42],
-	burlywood:	[222,184,135],
-	cadetblue:	[95,158,160],
-	chartreuse:	[127,255,0],
-	chocolate:	[210,105,30],
-	coral:	[255,127,80],
-	cornflowerblue:	[100,149,237],
-	cornsilk:	[255,248,220],
-	crimson:	[220,20,60],
-	cyan:	[0,255,255],
-	darkblue:	[0,0,139],
-	darkcyan:	[0,139,139],
-	darkgoldenrod:	[184,134,11],
-	darkgray:	[169,169,169],
-	darkgreen:	[0,100,0],
-	darkgrey:	[169,169,169],
-	darkkhaki:	[189,183,107],
-	darkmagenta:	[139,0,139],
-	darkolivegreen:	[85,107,47],
-	darkorange:	[255,140,0],
-	darkorchid:	[153,50,204],
-	darkred:	[139,0,0],
-	darksalmon:	[233,150,122],
-	darkseagreen:	[143,188,143],
-	darkslateblue:	[72,61,139],
-	darkslategray:	[47,79,79],
-	darkslategrey:	[47,79,79],
-	darkturquoise:	[0,206,209],
-	darkviolet:	[148,0,211],
-	deeppink:	[255,20,147],
-	deepskyblue:	[0,191,255],
-	dimgray:	[105,105,105],
-	dimgrey:	[105,105,105],
-	dodgerblue:	[30,144,255],
-	firebrick:	[178,34,34],
-	floralwhite:	[255,250,240],
-	forestgreen:	[34,139,34],
-	gainsboro:	[220,220,220],
-	ghostwhite:	[248,248,255],
-	gold:	[255,215,0],
-	goldenrod:	[218,165,32],
-	greenyellow:	[173,255,47],
-	grey:	[128,128,128],
-	honeydew:	[240,255,240],
-	hotpink:	[255,105,180],
-	indianred:	[205,92,92],
-	indigo:	[75,0,130],
-	ivory:	[255,255,240],
-	khaki:	[240,230,140],
-	lavender:	[230,230,250],
-	lavenderblush:	[255,240,245],
-	lawngreen:	[124,252,0],
-	lemonchiffon:	[255,250,205],
-	lightblue:	[173,216,230],
-	lightcoral:	[240,128,128],
-	lightcyan:	[224,255,255],
-	lightgoldenrodyellow:	[250,250,210],
-	lightgray:	[211,211,211],
-	lightgreen:	[144,238,144],
-	lightgrey:	[211,211,211],
-	lightpink:	[255,182,193],
-	lightsalmon:	[255,160,122],
-	lightseagreen:	[32,178,170],
-	lightskyblue:	[135,206,250],
-	lightslategray:	[119,136,153],
-	lightslategrey:	[119,136,153],
-	lightsteelblue:	[176,196,222],
-	lightyellow:	[255,255,224],
-	limegreen:	[50,205,50],
-	linen:	[250,240,230],
-	magenta:	[255,0,255],
-	mediumaquamarine:	[102,205,170],
-	mediumblue:	[0,0,205],
-	mediumorchid:	[186,85,211],
-	mediumpurple:	[147,112,219],
-	mediumseagreen:	[60,179,113],
-	mediumslateblue:	[123,104,238],
-	mediumspringgreen:	[0,250,154],
-	mediumturquoise:	[72,209,204],
-	mediumvioletred:	[199,21,133],
-	midnightblue:	[25,25,112],
-	mintcream:	[245,255,250],
-	mistyrose:	[255,228,225],
-	moccasin:	[255,228,181],
-	navajowhite:	[255,222,173],
-	oldlace:	[253,245,230],
-	olivedrab:	[107,142,35],
-	orange:	[255,165,0],
-	orangered:	[255,69,0],
-	orchid:	[218,112,214],
-	palegoldenrod:	[238,232,170],
-	palegreen:	[152,251,152],
-	paleturquoise:	[175,238,238],
-	palevioletred:	[219,112,147],
-	papayawhip:	[255,239,213],
-	peachpuff:	[255,218,185],
-	peru:	[205,133,63],
-	pink:	[255,192,203],
-	plum:	[221,160,221],
-	powderblue:	[176,224,230],
-	rosybrown:	[188,143,143],
-	royalblue:	[65,105,225],
-	saddlebrown:	[139,69,19],
-	salmon:	[250,128,114],
-	sandybrown:	[244,164,96],
-	seagreen:	[46,139,87],
-	seashell:	[255,245,238],
-	sienna:	[160,82,45],
-	skyblue:	[135,206,235],
-	slateblue:	[106,90,205],
-	slategray:	[112,128,144],
-	slategrey:	[112,128,144],
-	snow:	[255,250,250],
-	springgreen:	[0,255,127],
-	steelblue:	[70,130,180],
-	tan:	[210,180,140],
-	thistle:	[216,191,216],
-	tomato:	[255,99,71],
-	transparent: [0, 0, 0, 0],
-	turquoise:	[64,224,208],
-	violet:	[238,130,238],
-	wheat:	[245,222,179],
-	whitesmoke:	[245,245,245],
-	yellowgreen:	[154,205,50]
-});
-
-}
-
-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["dijit.ColorPalette"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.ColorPalette"] = true;
-dojo.provide("dijit.ColorPalette");
-
-
-
-
-
-
-
-dojo.declare("dijit.ColorPalette",
-	[dijit._Widget, dijit._Templated],
-	{
-	// summary:
-	//		A keyboard accessible color-picking widget
-	// description:
-	//		Grid showing various colors, so the user can pick a certain color.
-	//		Can be used standalone, or as a popup.
-	//
-	// example:
-	// |	<div dojoType="dijit.ColorPalette"></div>
-	//
-	// example:
-	// |    var picker = new dijit.ColorPalette({ },srcNode);
-	// |	picker.startup();
-
-	// defaultTimeout: Number
-	//		Number of milliseconds before a held key or button becomes typematic
-	defaultTimeout: 500,
-
-	// timeoutChangeRate: Number
-	//		Fraction of time used to change the typematic timer between events
-	//		1.0 means that each typematic event fires at defaultTimeout intervals
-	//		< 1.0 means that each typematic event fires at an increasing faster rate
-	timeoutChangeRate: 0.90,
-
-	// palette: String
-	//		Size of grid, either "7x10" or "3x4".
-	palette: "7x10",
-
-	// value: String
-	//		The value of the selected color.
-	value: null,
-
-	// _currentFocus: [private] DomNode
-	//		The currently focused or hovered color.
-	//		Different from value, which represents the selected (i.e. clicked) color.
-	_currentFocus: 0,
-
-	// _xDim: [protected] Integer
-	//		This is the number of colors horizontally across.
-	_xDim: null,
-
-	// _yDim: [protected] Integer
-	///		This is the number of colors vertically down.
-	_yDim: null,
-
-	// _palettes: [protected] Map
-	// 		This represents the value of the colors.
-	//		The first level is a hashmap of the different arrays available
-	//		The next two dimensions represent the columns and rows of colors.
-	_palettes: {
-		"7x10":	[["white", "seashell", "cornsilk", "lemonchiffon","lightyellow", "palegreen", "paleturquoise", "lightcyan",	"lavender", "plum"],
-				["lightgray", "pink", "bisque", "moccasin", "khaki", "lightgreen", "lightseagreen", "lightskyblue", "cornflowerblue", "violet"],
-				["silver", "lightcoral", "sandybrown", "orange", "palegoldenrod", "chartreuse", "mediumturquoise", 	"skyblue", "mediumslateblue","orchid"],
-				["gray", "red", "orangered", "darkorange", "yellow", "limegreen", 	"darkseagreen", "royalblue", "slateblue", "mediumorchid"],
-				["dimgray", "crimson", 	"chocolate", "coral", "gold", "forestgreen", "seagreen", "blue", "blueviolet", "darkorchid"],
-				["darkslategray","firebrick","saddlebrown", "sienna", "olive", "green", "darkcyan", "mediumblue","darkslateblue", "darkmagenta" ],
-				["black", "darkred", "maroon", "brown", "darkolivegreen", "darkgreen", "midnightblue", "navy", "indigo", 	"purple"]],
-
-		"3x4": [["white", "lime", "green", "blue"],
-			["silver", "yellow", "fuchsia", "navy"],
-			["gray", "red", "purple", "black"]]
-	},
-
-	// _imagePaths: [protected] Map
-	//		This is stores the path to the palette images
-	_imagePaths: {
-		"7x10": dojo.moduleUrl("dijit.themes", "a11y/colors7x10.png"),
-		"3x4": dojo.moduleUrl("dijit.themes", "a11y/colors3x4.png")
-	},
-
-	// _paletteCoords: [protected] Map
-	//		This is a map that is used to calculate the coordinates of the
-	//		images that make up the palette.
-	_paletteCoords: {
-		"leftOffset": 3, "topOffset": 3,
-		"cWidth": 20, "cHeight": 20
-	},
-
-	// templateString: String
-	//		The template of this widget.
-	templateString: dojo.cache("dijit", "templates/ColorPalette.html", "<div class=\"dijitInline dijitColorPalette\">\n\t<div class=\"dijitColorPaletteInner\" dojoAttachPoint=\"divNode\" waiRole=\"grid\"\">\n\t\t<img class=\"dijitColorPaletteUnder\" dojoAttachPoint=\"imageNode\" waiRole=\"presentation\" alt=\"\">\n\t</div>\n</div>\n"),
-
-	// _paletteDims: [protected] Object
-	//		Size of the supported palettes for alignment purposes.
-	_paletteDims: {
-		"7x10": {"width": "206px", "height": "145px"},
-		"3x4": {"width": "86px", "height": "64px"}
-	},
-
-	// tabIndex: String
-	//		Widget tab index.
-	tabIndex: "0",
-
-	buildRendering: function(){
-		// Instantiate the template, which makes a skeleton into which we'll insert a bunch of
-		// <img> nodes
-		this.inherited(arguments);
-	
-		// A name has to be given to the colorMap, this needs to be unique per Palette.
-		dojo.mixin(this.divNode.style, this._paletteDims[this.palette]);
-		this.imageNode.setAttribute("src", this._imagePaths[this.palette].toString());
-		var choices = this._palettes[this.palette];
-		this.domNode.style.position = "relative";
-		this._cellNodes = [];
-		this.colorNames = dojo.i18n.getLocalization("dojo", "colors", this.lang);
-		var url = this._blankGif,
-			colorObject = new dojo.Color(),
-			coords = this._paletteCoords;
-		for(var row=0; row < choices.length; row++){
-			var rowNode = dojo.create("div", {
-				role: "row"
-			}, this.divNode);
-			for(var col=0; col < choices[row].length; col++){
-
-				var color = choices[row][col],
-						colorValue = colorObject.setColor(dojo.Color.named[color]);
-
-				var cellNode = dojo.create("span", {
-					"class": "dijitPaletteCell",
-					tabIndex: "-1",
-					title: this.colorNames[color],
-					style: {
-						top: coords.topOffset + (row * coords.cHeight) + "px",
-						left: coords.leftOffset + (col * coords.cWidth) + "px"
-					}
-				});
-
-				var imgNode = dojo.create("img",{
-					src: url,
-					"class":"dijitPaletteImg",
-					alt: this.colorNames[color]
-				}, cellNode);
-
-				// FIXME: color is an attribute of img?
-				imgNode.color = colorValue.toHex();
-				var imgStyle = imgNode.style;
-				imgStyle.color = imgStyle.backgroundColor = imgNode.color;
-
-				dojo.forEach(["Dijitclick", "MouseEnter", "MouseLeave", "Focus"], function(handler){
-					this.connect(cellNode, "on" + handler.toLowerCase(), "_onCell" + handler);
-				}, this);
-
-				dojo.place(cellNode, rowNode);
-
-				dijit.setWaiRole(cellNode, "gridcell");
-				cellNode.index = this._cellNodes.length;
-				this._cellNodes.push(cellNode);
-			}
-		}
-		this._xDim = choices[0].length;
-		this._yDim = choices.length;
-
-		// Now set all events
-		// The palette itself is navigated to with the tab key on the keyboard
-		// Keyboard navigation within the Palette is with the arrow keys
-		// Spacebar selects the color.
-		// For the up key the index is changed by negative the x dimension.
-
-		var keyIncrementMap = {
-			UP_ARROW: -this._xDim,
-			// The down key the index is increase by the x dimension.
-			DOWN_ARROW: this._xDim,
-			// Right and left move the index by 1.
-			RIGHT_ARROW: 1,
-			LEFT_ARROW: -1
-		};
-		for(var key in keyIncrementMap){
-			this._connects.push(dijit.typematic.addKeyListener(this.domNode,
-				{charOrCode:dojo.keys[key], ctrlKey:false, altKey:false, shiftKey:false},
-				this,
-				function(){
-					var increment = keyIncrementMap[key];
-					return function(count){ this._navigateByKey(increment, count); };
-				}(),
-				this.timeoutChangeRate, this.defaultTimeout));
-		}
-	},
-	
-	postCreate: function(){
-		this.inherited(arguments);
-
-		// Set initial navigable node.   At any point in time there's exactly one
-		// cell with tabIndex != -1.   If focus is inside the ColorPalette then
-		// focus is on that cell.
-		// TODO: if we set aria info (for the current value) on the ColorPalette itself then can we avoid
-		// having to focus each individual cell?
-		this._currentFocus = this._cellNodes[0];
-		dojo.attr(this._currentFocus, "tabIndex", this.tabIndex);
-	},
-
-	focus: function(){
-		// summary:
-		//		Focus this ColorPalette.  Puts focus on the most recently focused cell.
-
-		// The cell already has tabIndex set, just need to set CSS and focus it
-		dojo.addClass(this._currentFocus, "dijitPaletteCellHighlight");
-		dijit.focus(this._currentFocus);
-	},
-
-	onChange: function(color){
-		// summary:
-		//		Callback when a color is selected.
-		// color: String
-		//		Hex value corresponding to color.
-//		console.debug("Color selected is: "+color);
-	},
-
-	_onFocus: function(){
-		// summary:
-		//		Handler for when the ColorPalette gets focus (because a cell inside
-		//		the ColorPalette got focus)
-		// tags:
-		//		protected
-
-		dojo.addClass(this._currentFocus, "dijitPaletteCellHighlight");
-		this.inherited(arguments);
-	},
-
-	_onBlur: function(){
-		// summary:
-		//		Handler for when the ColorPalette loses focus
-		// tags:
-		//		protected
-
-		// Just to be the same as 1.3, when I am focused again go to first (0,0) cell rather than
-		// currently focused node.
-		dojo.attr(this._currentFocus, "tabIndex", "-1");
-		dojo.removeClass(this._currentFocus, "dijitPaletteCellHighlight");
-		this._currentFocus = this._cellNodes[0];
-		dojo.attr(this._currentFocus, "tabIndex", this.tabIndex);
-
-		this.inherited(arguments);
-	},
-
-	_onCellDijitclick: function(/*Event*/ evt){
-		// summary:
-		//		Handler for click, enter key & space key. Selects the color.
-		// evt:
-		//		The event.
-		// tags:
-		//		private
-
-		var target = evt.currentTarget;
-		this._selectColor(target);
-		dojo.stopEvent(evt);
-	},
-
-	_onCellMouseEnter: function(/*Event*/ evt){
-		// summary:
-		//		Handler for onMouseEnter event on a cell. Put highlight on the color under the mouse.
-		// evt:
-		//		The mouse event.
-		// tags:
-		//		private
-
-		var target = evt.currentTarget;
-		this._setCurrent(target);
-	},
-
-	_onCellMouseLeave: function(/*Event*/ evt){
-		// summary:
-		//		Handler for onMouseLeave event on a cell. Remove highlight on the color under the mouse.
-		// evt:
-		//		The mouse event.
-		// tags:
-		//		private
-
-		dojo.removeClass(this._currentFocus, "dijitPaletteCellHighlight");
-	},
-
-	_onCellFocus: function(/*Event*/ evt){
-		// summary:
-		//		Handler for onFocus of a cell.
-		// description:
-		//		Removes highlight of the color that just lost focus, and highlights
-		//		the new color.  Also moves the tabIndex setting to the new cell.
-		//		
-		// evt:
-		//		The focus event.
-		// tags:
-		//		private
-
-		this._setCurrent(evt.currentTarget);
-	},
-
-	_setCurrent: function(/*Node*/ node){
-		// summary:
-		//		Called when a color is hovered or focused.
-		// description:
-		//		Removes highlight of the old color, and highlights
-		//		the new color.  Also moves the tabIndex setting to the new cell.
-		// tags:
-		//		protected
-		if("_currentFocus" in this){
-			// Remove highlight and tabIndex on old cell
-			dojo.attr(this._currentFocus, "tabIndex", "-1");
-			dojo.removeClass(this._currentFocus, "dijitPaletteCellHighlight");
-		}
-
-		// Set highlight and tabIndex of new cell
-		this._currentFocus = node;
-		if(node){
-			dojo.attr(node, "tabIndex", this.tabIndex);
-			dojo.addClass(node, "dijitPaletteCellHighlight");
-		}
-	},
-
-	_selectColor: function(selectNode){
-		// summary:
-		// 		This selects a color. It triggers the onChange event
-		// area:
-		//		The area node that covers the color being selected.
-		// tags:
-		//		private
-		var img = selectNode.getElementsByTagName("img")[0];
-		this.onChange(this.value = img.color);
-	},
-
-	_navigateByKey: function(increment, typeCount){
-		// summary:
-		// 	  	This is the callback for typematic.
-		// 		It changes the focus and the highlighed color.
-		// increment:
-		// 		How much the key is navigated.
-		// typeCount:
-		//		How many times typematic has fired.
-		// tags:
-		//		private
-
-		// typecount == -1 means the key is released.
-		if(typeCount == -1){ return; }
-
-		var newFocusIndex = this._currentFocus.index + increment;
-		if(newFocusIndex < this._cellNodes.length && newFocusIndex > -1)
-		{
-			var focusNode = this._cellNodes[newFocusIndex];
-			this._setCurrent(focusNode);
-
-			// Actually focus the node, for the benefit of screen readers.
-			// Use setTimeout because IE doesn't like changing focus inside of an event handler
-			setTimeout(dojo.hitch(dijit, "focus", focusNode), 0);
-		}
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.Declaration"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.Declaration"] = true;
-dojo.provide("dijit.Declaration");
-
-
-
-dojo.declare(
-	"dijit.Declaration",
-	dijit._Widget,
-	{
-		// summary:
-		//		The Declaration widget allows a developer to declare new widget
-		//		classes directly from a snippet of markup.
-
-		// _noScript: [private] Boolean
-		//		Flag to parser to leave alone the script tags contained inside of me
-		_noScript: true,
-
-		// widgetClass: String
-		//		Name of class being declared, ex: "acme.myWidget"
-		widgetClass: "",
-
-		// propList: Object
-		//		Set of attributes for this widget along with default values, ex:
-		//		{delay: 100, title: "hello world"}
-		defaults: null,
-
-		// mixins: String[]
-		//		List containing the prototype for this widget, and also any mixins,
-		//		ex: ["dijit._Widget", "dijit._Container"]
-		mixins: [],
-
-		buildRendering: function(){
-			var src = this.srcNodeRef.parentNode.removeChild(this.srcNodeRef),
-				methods = dojo.query("> script[type^='dojo/method'][event]", src).orphan(),
-				postscriptConnects = dojo.query("> script[type^='dojo/method']", src).orphan(),
-				regularConnects = dojo.query("> script[type^='dojo/connect']", src).orphan(),
-				srcType = src.nodeName;
-
-			var propList = this.defaults || {};
-
-			// For all methods defined like <script type="dojo/method" event="foo">,
-			// add that method to prototype
-			dojo.forEach(methods, function(s){
-				var evt = s.getAttribute("event"),
-					func = dojo.parser._functionFromScript(s);
-				propList[evt] = func;
-			});
-
-			// map array of strings like [ "dijit.form.Button" ] to array of mixin objects
-			// (note that dojo.map(this.mixins, dojo.getObject) doesn't work because it passes
-			// a bogus third argument to getObject(), confusing it)
-			this.mixins = this.mixins.length ?
-				dojo.map(this.mixins, function(name){ return dojo.getObject(name); } ) :
-				[ dijit._Widget, dijit._Templated ];
-
-			propList.widgetsInTemplate = true;
-			propList._skipNodeCache = true;
-			propList.templateString = "<"+srcType+" class='"+src.className+"' dojoAttachPoint='"+(src.getAttribute("dojoAttachPoint") || '')+"' dojoAttachEvent='"+(src.getAttribute("dojoAttachEvent") || '')+"' >"+src.innerHTML.replace(/\%7B/g,"{").replace(/\%7D/g,"}")+"</"+srcType+">";
-
-			// strip things so we don't create stuff under us in the initial setup phase
-			dojo.query("[dojoType]", src).forEach(function(node){
-				node.removeAttribute("dojoType");
-			});
-
-			// create the new widget class
-			var wc = dojo.declare(
-				this.widgetClass,
-				this.mixins,
-				propList
-			);
-
-			// Handle <script> blocks of form:
-			//		<script type="dojo/connect" event="foo">
-			// and
-			//		<script type="dojo/method">
-			// (Note that the second one is just shorthand for a dojo/connect to postscript)
-			// Since this is a connect in the declaration, we are actually connection to the method
-			// in the _prototype_.
-			var connects = regularConnects.concat(postscriptConnects);
-			dojo.forEach(connects, function(s){
-				var evt = s.getAttribute("event") || "postscript",
-					func = dojo.parser._functionFromScript(s);
-				dojo.connect(wc.prototype, evt, func);
-			});
-		}
-	}
-);
-
-}
-
-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.getCopyKeyState = dojo.isCopyKeyPressed;
-
-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
-};
-
-}
-
-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)
-
-	// TODO: remove this when getViewport() moved to dojo core, see #7028
-
-	// 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.position(n, true);
-				//console.log(b.l, b.t, t.x, t.y, n.scrollLeft, n.scrollTop);
-				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.position()
-					// 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;
-					}
-				}
-				//console.log("ry =", ry, "b.h =", b.h, "h =", h);
-				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.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.__MoveableArgs", [], {
-	// handle: Node||String
-	//		A node (or node's id), which is used as a mouse handle.
-	//		If omitted, the node itself is used as a handle.
-	handle: null,
-
-	// delay: Number
-	//		delay move by this number of pixels
-	delay: 0,
-
-	// skip: Boolean
-	//		skip move of form elements
-	skip: false,
-
-	// mover: Object
-	//		a constructor of custom Mover
-	mover: dojo.dnd.Mover
-});
-=====*/
-
-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: dojo.dnd.__MoveableArgs?
-		//		optional parameters
-		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.__constrainedMoveableArgs", [dojo.dnd.__MoveableArgs], {
-	// constraints: Function
-	//		Calculates a constraint box.
-	//		It is called in a context of the moveable object.
-	constraints: function(){},
-
-	// within: Boolean
-	//		restrict move within boundaries.
-	within: false
-});
-=====*/
-
-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 that makes a node moveable
-		// node: Node
-		//		a node (or node's id) to be moved
-		// params: dojo.dnd.move.__constrainedMoveableArgs?
-		//		an optional object with additional parameters;
-		//		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.__boxConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
-	// box: Object
-	//		a constraint box
-	box: {}
-});
-=====*/
-
-dojo.declare("dojo.dnd.move.boxConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
-	// box:
-	//		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: dojo.dnd.move.__boxConstrainedMoveableArgs?
-		//		an optional object with parameters
-		var box = params && params.box;
-		this.constraints = function(){ return box; };
-	}
-});
-
-/*=====
-dojo.declare("dojo.dnd.move.__parentConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
-	// area: String
-	//		A parent's area to restrict the move.
-	//		Can be "margin", "border", "padding", or "content".
-	area: ""
-});
-=====*/
-
-dojo.declare("dojo.dnd.move.parentConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
-	// area:
-	//		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: dojo.dnd.move.__parentConstrainedMoveableArgs?
-		//		an optional object with parameters
-		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 within 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");
-
-
-
-/*=====
-dojo.declare("dojo.dnd.__TimedMoveableArgs", [dojo.dnd.__MoveableArgs], {
-	// timeout: Number
-	//		delay move by this number of ms,
-	//		accumulating position changes during the timeout
-	timeout: 0
-});
-=====*/
-
-(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 that makes a node moveable with a timer
-			// node: Node||String
-			//		a node (or node's id) to be moved
-			// params: dojo.dnd.__TimedMoveableArgs
-			//		object with additional parameters.
-			
-			// 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:
-	//		A simple `dojo.Animation` toggler API.
-	//
-	// description:
-	//		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. All available members are mixed into 
-	//		these animations from the constructor (for example, `node`, 
-	//		`showDuration`, `hideDuration`). 
-	//
-	// example:
-	//	|	var t = new dojo.fx.Toggler({
-	//	|		node: "nodeId",
-	//	|		showDuration: 500,
-	//	|		// hideDuration will default to "200"
-	//	|		showFunc: dojo.fx.wipeIn, 
-	//	|		// hideFunc will default to "fadeOut"
-	//	|	});
-	//	|	t.show(100); // delay showing for 100ms
-	//	|	// ...time passes...
-	//	|	t.hide();
-
-	// node: DomNode
-	//		the node to target for the showing and hiding animations
-	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,
-
-	// 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.
-	// FIXME: also would be nice to specify individual showArgs/hideArgs mixed into
-	// each animation individually. 
-	// FIXME: also would be nice to have events from the animations exposed/bridged
-
-	/*=====
-	_showArgs: null,
-	_showAnim: null,
-
-	_hideArgs: null,
-	_hideAnim: null,
-
-	_isShowing: false,
-	_isHiding: false,
-	=====*/
-
-	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));
-	},
-
-	show: function(delay){
-		// summary: Toggle the node to showing
-		// delay: Integer?
-		//		Ammount of time to stall playing the show animation
-		return this.showAnim.play(delay || 0);
-	},
-
-	hide: function(delay){
-		// summary: Toggle the node to hidden
-		// delay: Integer?
-		//		Ammount of time to stall playing the hide animation
-		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");
- // FIXME: remove this back-compat require in 2.0 
-/*=====
-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
-		//
-		// description:
-		//		Return a `dojo.Animation` which will play all passed
-		//		`dojo.Animation` instances in sequence, firing its own
-		//		synthesized events simulating a single animation. (eg:
-		//		onEnd of this animation means the end of the chain, 
-		//		not the individual animations within)
-		//
-		// example:
-		//	Once `node` is faded out, fade in `otherNode`
-		//	|	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", "onEnd"], 
-			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 a list 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:
-		//	Fade out `node` while fading in `otherNode` simultaneously
-		//	|	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:
-		//		Expand a node to it's natural height.
-		//
-		// description:
-		//		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: Object
-		//		A hash-map of standard `dojo.Animation` constructor properties
-		//		(such as easing: node: duration: and so on)
-		//
-		// example:
-		//	|	dojo.fx.wipeIn({
-		//	|		node:"someId"
-		//	|	}).play()
-		var node = args.node = d.byId(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:
-		//		Shrink a node to nothing and hide it. 
-		//
-		// description:
-		//		Returns an animation that will shrink node defined in "args"
-		//		from it's current height to 1px, and then hide it.
-		//
-		// args: Object
-		//		A hash-map of standard `dojo.Animation` constructor properties
-		//		(such as easing: node: duration: and so on)
-		// 
-		// example:
-		//	|	dojo.fx.wipeOut({ node:"someId" }).play()
-		
-		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:
-		//		Slide a node to a new top/left position
-		//
-		// description:
-		//		Returns an animation that will slide "node" 
-		//		defined in args Object from its current position to
-		//		the position defined by (args.left, args.top).
-		//
-		// args: Object
-		//		A hash-map of standard `dojo.Animation` constructor properties
-		//		(such as easing: node: duration: and so on). Special args members
-		//		are `top` and `left`, which indicate the new position to slide to.
-		//
-		// example:
-		//	|	dojo.fx.slideTo({ node: node, left:"40", top:"50", units:"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.position(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].multiple){
-					// 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)
-
-				// TODO: maybe should call dojo.getNodeProp() instead
-				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{
-					var prev=dojo.getObject(name, false, obj);
-					if(typeof prev != "undefined"){
-						if(dojo.isArray(prev)){
-							prev.push(value);
-						}else{
-							dojo.setObject(name, [prev, value], obj);
-						}
-					}else{
-						// unique name
-						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.getNodeProp(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);
-		},
-
-		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();
-			this.bgIframe = new dijit.BackgroundIframe(this.domNode);
-		},
-
-		hide: function(){
-			// summary:
-			//		Hides the dialog underlay
-			this.bgIframe.destroy();
-			this.domNode.style.display = "none";
-		},
-
-		uninitialize: function(){
-			if(this.bgIframe){
-				this.bgIframe.destroy();
-			}
-			this.inherited(arguments);
-		}
-	}
-);
-
-}
-
-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, 
-		d = dojo;
-	
-	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){
-		// summary:
-		//		inserts the given content into the given node
-		//	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
-		
-		// always empty
-		d.empty(node);
-
-		if(cont) {
-			if(typeof cont == "string") {
-				cont = d._toDom(cont, node.ownerDocument);
-			}
-			if(!cont.nodeType && d.isArrayLike(cont)) {
-				// handle as enumerable, but it may shrink as we enumerate it
-				for(var startlen=cont.length, i=0; i<cont.length; i=startlen==cont.length ? i+1 : 0) {
-					d.place( cont[i], node, "last");
-				}
-			} else {
-				// pass nodes, documentFragments and unknowns through to dojo.place
-				d.place(cont, node, "last");
-			}
-		}
-
-		// 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 stand alone widget
-	//		or as a base class 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
-	//		Indicates that this widget acts as a "parent" to the descendant widgets.
-	//		When the parent is started it will call startup() on the child widgets.
-	//		See also `isLayoutContainer`.
-	isContainer: true,
-
-	// isLayoutContainer: [protected] Boolean
-	//		Indicates that this widget will call resize() on it's child widgets
-	//		when they become visible.
-	isLayoutContainer: true,
-
-	// onLoadDeferred: [readonly] dojo.Deferred
-	//		This is the `dojo.Deferred` returned by attr('href', ...) and refresh().
-	//		Calling onLoadDeferred.addCallback() or addErrback() registers your
-	//		callback to be called only once, when the prior attr('href', ...) call or
-	//		the initial href parameter to the constructor finishes loading.
-	//
-	//		This is different than an onLoad() handler which gets called any time any href is loaded.
-	onLoadDeferred: null,
-
-	// Override _Widget's attributeMap because we don't want the title attribute (used to specify
-	// tab labels) to be copied to ContentPane.domNode... otherwise a tooltip shows up over the
-	// entire pane.
-	attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-		title: []
-	}),
-
-	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; }
-
-		var parent = dijit._Contained.prototype.getParent.call(this);
-		this._childOfLayoutWidget = parent && parent.isLayoutContainer;
-
-		// I need to call resize() on my child/children (when I become visible), unless
-		// I'm the child of a layout widget in which case my parent will call resize() on me and I'll do it then.
-		this._needLayout = !this._childOfLayoutWidget;
-
-		if(this.isLoaded){
-			dojo.forEach(this.getChildren(), function(child){
-				child.startup();
-			});
-		}
-
-		if(this._isShown() || this.preload){
-			this._onShow();
-		}
-
-		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).filter(function(node){
-				return node.tagName !== "SCRIPT"; // or a regexp for hidden elements like script|area|map|etc..
-			}),
-			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;
-		}
-
-		// So we can set overflow: hidden to avoid a safari bug w/scrollbars showing up (#9449)
-		dojo.toggleClass(this.containerNode, this.baseClass + "SingleChild", !!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.onLoadDeferred = new dojo.Deferred(dojo.hitch(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())){
-			this._load();
-		}else{
-			// Set flag to indicate that href needs to be loaded the next time the
-			// ContentPane is made visible
-			this._hrefChanged = true;
-		}
-
-		return this.onLoadDeferred;		// dojo.Deferred
-	},
-
-	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();
-
-		// Even though user is just setting content directly, still need to define an onLoadDeferred
-		// because the _onLoadHandler() handler is still getting called from setContent()
-		this.onLoadDeferred = new dojo.Deferred(dojo.hitch(this, "cancel"));
-
-		this._setContent(data || "");
-
-		this._isDownloaded = false; // mark that content is from a attr('content') not an attr('href')
-
-		return this.onLoadDeferred; 	// dojo.Deferred
-	},
-	_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
-
-		this.onLoadDeferred = null;
-	},
-
-	uninitialize: function(){
-		if(this._beingDestroyed){
-			this.cancel();
-		}
-		this.inherited(arguments);
-	},
-
-	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.inherited(arguments);
-	},
-
-	resize: function(changeSize, resultSize){
-		// summary:
-		//		See `dijit.layout._LayoutWidget.resize` for description.
-		//		Although ContentPane doesn't extend _LayoutWidget, it does implement
-		//		the same API.
-
-		// For the TabContainer --> BorderContainer --> ContentPane case, _onShow() is
-		// never called, so resize() is our trigger to do the initial href download.
-		if(!this._wasShown){
-			this._onShow();
-		}
-
-		this._resizeCalled = true;
-
-		// Set margin box size, unless it wasn't specified, in which case use current size.
-		if(changeSize){
-			dojo.marginBox(this.domNode, changeSize);
-		}
-
-		// Compute content box size of containerNode in case we [later] need to size our single child.
-		var cn = this.containerNode;
-		if(cn === this.domNode){
-			// If changeSize or resultSize was passed to this method and this.containerNode ==
-			// this.domNode then we can compute the content-box size without querying the node,
-			// which is more reliable (similar to LayoutWidget.resize) (see for example #9449).
-			var mb = resultSize || {};
-			dojo.mixin(mb, changeSize || {}); // changeSize overrides resultSize
-			if(!("h" in mb) || !("w" in mb)){
-				mb = dojo.mixin(dojo.marginBox(cn), mb); // just use dojo.marginBox() to fill in missing values
-			}
-			this._contentBox = dijit.layout.marginBox2contentBox(cn, mb);
-		}else{
-			this._contentBox = dojo.contentBox(cn);
-		}
-
-		// Make my children layout, or size my single child widget
-		this._layoutChildren();
-	},
-
-	_isShown: function(){
-		// summary:
-		//		Returns true if the content is currently shown.
-		// description:
-		//		If I am a child of a layout widget then it actually returns true if I've ever been visible,
-		//		not whether I'm currently visible, since that's much faster than tracing up the DOM/widget
-		//		tree every call, and at least solves the performance problem on page load by deferring loading
-		//		hidden ContentPanes until they are first shown
-
-		if(this._childOfLayoutWidget){
-			// If we are TitlePane, etc - we return that only *IF* we've been resized
-			if(this._resizeCalled && "open" in this){
-				return this.open;
-			}
-			return this._resizeCalled;
-		}else if("open" in this){
-			return this.open;		// for TitlePane, etc.
-		}else{
-			// TODO: with _childOfLayoutWidget check maybe this branch no longer necessary?
-			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 whenever the pane is made visible.
-		//
-		//		Does necessary processing, including href download and layout/resize of
-		//		child widget(s)
-
-		if(this.href){
-			if(!this._xhrDfd && // if there's an href that isn't already being loaded
-				(!this.isLoaded || this._hrefChanged || this.refreshOnShow)
-			){
-				this.refresh();
-			}
-		}else{
-			// If we are the child of a layout widget then the layout widget will call resize() on
-			// us, and then we will size our child/children.   Otherwise, we need to do it now.
-			if(!this._childOfLayoutWidget && this._needLayout){
-				// If a layout has been scheduled for when we become visible, do it now
-				this._layoutChildren();
-			}
-		}
-
-		this.inherited(arguments);
-
-		// Need to keep track of whether ContentPane has been shown (which is different than
-		// whether or not it's currently visible).
-		this._wasShown = true;
-	},
-
-	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 in-flight request
-		this.cancel();
-
-		this.onLoadDeferred = new dojo.Deferred(dojo.hitch(this, "cancel"));
-		this._load();
-		return this.onLoadDeferred;
-	},
-
-	_load: function(){
-		// summary:
-		//		Load/reload the href specified in this.href
-
-		// 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;
-		});
-
-		// Remove flag saying that a load is needed
-		delete this._hrefChanged;
-	},
-
-	_onLoadHandler: function(data){
-		// summary:
-		//		This is called whenever new content is being loaded
-		this.isLoaded = true;
-		try{
-			this.onLoadDeferred.callback(data);
-			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);
-
-		// Delete any state information we have about current contents
-		delete this._singleChild;
-	},
-
-	_setContent: function(cont, isFakeContent){
-		// summary:
-		//		Insert the content into the container node
-
-		// first get rid of child widgets
-		this.destroyDescendants();
-
-		// dojo.html.set will take care of the rest of the details
-		// we provide an override 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){
-			// Startup each top level child widget (and they will start their children, recursively)
-			dojo.forEach(this.getChildren(), function(child){
-				// The parser has already called startup on all widgets *without* a getParent() method
-				if(!this.parseOnLoad || child.getParent){
-					child.startup();
-				}
-			}, this);
-
-			// 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){
-		this.onLoadDeferred.errback(err);
-
-		// 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.doLayout){
-			this._checkIfSingleChild();
-		}
-
-		if(this._singleChild && this._singleChild.resize){
-			var cb = this._contentBox || dojo.contentBox(this.containerNode);
-
-			// 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});
-		}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: dojo.cache("dijit", "templates/TooltipDialog.html", "<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);
-				}
-			},
-
-			onClose: function(){
-				// summary:
-				//		Called when dialog is hidden.
-				//		This is called from the dijit.popup code, and should not be called directly.
-				// tags:
-				//		protected
-				this.onHide();
-			},
-
-			_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){
-					// Use setTimeout to avoid crash on IE, see #10396.
-					setTimeout(dojo.hitch(this, "onCancel"), 0);
-					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._DialogBase",
-	[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: dojo.cache("dijit", "templates/Dialog.html", "<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: _onCloseLeav [...]
-
-		attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-			title: [
-				{ node: "titleNode", type: "innerHTML" },
-				{ node: "titleBar", type: "attribute" }
-			],
-			"aria-describedby":""
-		}),
-
-		// 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,
-
-		//aria-describedby: String
-		//		Allows the user to add an aria-describedby attribute onto the dialog.   The value should
-		//		be the id of the container element of text that describes the dialog purpose (usually
-		//		the first text in the dialog).
-		//		<div dojoType="dijit.Dialog" aria-describedby="intro" .....>
-		//			<div id="intro">Introductory text</div>
-		//			<div>rest of dialog contents</div>
-		//		</div>
-		"aria-describedby":"",
-
-		postMixInProperties: function(){
-			var _nlsResources = dojo.i18n.getLocalization("dijit", "common");
-			dojo.mixin(this, _nlsResources);
-			this.inherited(arguments);
-		},
-
-		postCreate: function(){
-			dojo.style(this.domNode, {
-				display: "none",
-				position:"absolute"
-			});
-			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. Saves the position of the dialog in the viewport.
-			// tags:
-			//		private
-			if(e && e.node && e.node === this.domNode){
-				this._relativePosition = dojo.position(e.node);
-			}
-		},
-
-		_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");
-			}
-
-			this.underlayAttrs = {
-				dialogId: this.id,
-				"class": dojo.map(this["class"].split(/\s/), function(s){ return s+"_underlay"; }).join(" ")
-			};
-
-			this._fadeIn = dojo.fadeIn({
-				node: node,
-				duration: this.duration,
-				beforeBegin: dojo.hitch(this, function(){
-					var underlay = dijit._underlay;
-					if(!underlay){
-						underlay = dijit._underlay = new dijit.DialogUnderlay(this.underlayAttrs);
-					}else{
-						underlay.attr(this.underlayAttrs);
-					}
-
-					var zIndex = 948 + dijit._dialogStack.length*2;
-					dojo.style(dijit._underlay.domNode, 'zIndex', zIndex);
-					dojo.style(this.domNode, 'zIndex', zIndex + 1);
-					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: dojo.hitch(this, function(){
-					node.style.display = "none";
-
-					// Restore the previous dialog in the stack, or if this is the only dialog
-					// then restore to original page
-					var ds = dijit._dialogStack;
-					if(ds.length == 0){
-						dijit._underlay.hide();
-					}else{
-						dojo.style(dijit._underlay.domNode, 'zIndex', 948 + ds.length*2);
-						dijit._underlay.attr(ds[ds.length-1].underlayAttrs);
-					}
-
-					// Restore focus to wherever it was before this dialog was displayed
-					if(this.refocus){
-						var focus = this._savedFocus;
-
-						// If we are returning control to a previous dialog but for some reason
-						// that dialog didn't have a focused field, set focus to first focusable item.
-						// This situation could happen if two dialogs appeared at nearly the same time,
-						// since a dialog doesn't set it's focus until the fade-in is finished.
-						if(ds.length > 0){
-							var pd = ds[ds.length-1];
-							if(!dojo.isDescendant(focus.node, pd.domNode)){
-								pd._getFocusItems(pd.domNode);
-								focus = pd._firstFocusItem;
-							}
-						}
-
-						dijit.focus(focus);
-					}
-				})
-			 });
-		},
-
-		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();
-			}
-			
-			// Hide the underlay, unless the underlay widget has already been destroyed
-			// because we are being called during page unload (when all widgets are destroyed)
-			if((this.open || wasPlaying) && !dijit._underlay._destroyed){
-				dijit._underlay.hide();
-			}
-			if(this._moveable){
-				this._moveable.destroy();
-			}
-			this.inherited(arguments);
-		},
-
-		_size: function(){
-			// summary:
-			// 		If necessary, shrink dialog contents so dialog fits in viewport
-			// tags:
-			//		private
-
-			this._checkIfSingleChild();
-
-			// If we resized the dialog contents earlier, reset them back to original size, so
-			// that if the user later increases the viewport size, the dialog can display w/out a scrollbar.
-			// Need to do this before the dojo.marginBox(this.domNode) call below.
-			if(this._singleChild){
-				if(this._singleChildOriginalStyle){
-					this._singleChild.domNode.style.cssText = this._singleChildOriginalStyle;
-				}
-				delete this._singleChildOriginalStyle;
-			}else{
-				dojo.style(this.containerNode, {
-					width:"auto",
-					height:"auto"
-				});
-			}
-
-			var mb = dojo.marginBox(this.domNode);
-			var viewport = dijit.getViewport();
-			if(mb.w >= viewport.w || mb.h >= viewport.h){
-				// Reduce size of dialog contents so that dialog fits in viewport
-
-				var w = Math.min(mb.w, Math.floor(viewport.w * 0.75)),
-					h = Math.min(mb.h, Math.floor(viewport.h * 0.75));
-
-				if(this._singleChild && this._singleChild.resize){
-					this._singleChildOriginalStyle = this._singleChild.domNode.style.cssText;
-					this._singleChild.resize({w: w, h: h});
-				}else{
-					dojo.style(this.containerNode, {
-						width: w + "px",
-						height: h + "px",
-						overflow: "auto",
-						position: "relative"	// workaround IE bug moving scrollbar or dragging dialog
-					});
-				}
-			}else{
-				if(this._singleChild && this._singleChild.resize){
-					this._singleChild.resize();
-				}
-			}
-		},
-
-		_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,
-					viewport = dijit.getViewport(),
-					p = this._relativePosition,
-					bb = p ? null : dojo._getBorderBox(node),
-					l = Math.floor(viewport.l + (p ? p.x : (viewport.w - bb.w) / 2)),
-					t = Math.floor(viewport.t + (p ? p.y : (viewport.h - bb.h) / 2))
-				;
-				dojo.style(node,{
-					left: l + "px",
-					top: t + "px"
-				});
-			}
-		},
-
-		_onKey: function(/*Event*/ evt){
-			// summary:
-			//		Handles the keyboard events for accessibility reasons
-			// tags:
-			//		private
-
-			var ds = dijit._dialogStack;
-			if(ds[ds.length-1] != this){
-				// console.debug(this.id + ': skipping because', this, 'is not the active dialog');
-				return;
-			}
-
-			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 || dojo.hasClass(node, "dijitPopup")){
-							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,
-				display:""
-			});
-
-			this.open = true;
-			this._onShow(); // lazy load trigger
-
-			this._size();
-			this._position();
-			dijit._dialogStack.push(this);
-			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
-			// or if we aren't the active dialog, don't allow us to close yet
-			var ds = dijit._dialogStack;
-			if(!this._alreadyInitialized || this != ds[ds.length-1]){
-				return;
-			}
-
-			if(this._fadeIn.status() == "playing"){
-				this._fadeIn.stop();
-			}
-
-			// throw away current active dialog from stack -- making the previous dialog or the node on the original page active
-			ds.pop();
-
-			this._fadeOut.play();
-
-			if(this._scrollConnected){
-				this._scrollConnected = false;
-			}
-			dojo.forEach(this._modalconnects, dojo.disconnect);
-			this._modalconnects = [];
-
-			if(this._relativePosition){
-				delete this._relativePosition;
-			}
-			this.open = false;
-
-			this.onHide();
-		},
-
-		layout: function(){
-			// summary:
-			//		Position the Dialog and the underlay
-			// tags:
-			//		private
-			if(this.domNode.style.display != "none"){
-				if(dijit._underlay){	// avoid race condition during show()
-					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");
-		}
-	}
-);
-
-dojo.declare(
-	"dijit.Dialog",
-	[dijit.layout.ContentPane, dijit._DialogBase],
-	{}
-);
-
-// Stack of currenctly displayed dialogs, layered on top of each other
-dijit._dialogStack = [];
-
-// For back-compat.  TODO: remove in 2.0
-
-
-}
-
-if(!dojo._hasResource["dijit._editor.selection"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._editor.selection"] = true;
-dojo.provide("dijit._editor.selection");
-
-// FIXME:
-//		all of these methods branch internally for IE. This is probably
-//		sub-optimal in terms of runtime performance. We should investigate the
-//		size difference for differentiating at definition time.
-
-dojo.mixin(dijit._editor.selection, {
-	getType: function(){
-		// summary:
-		//		Get the selection type (like dojo.doc.select.type in IE).
-		if(dojo.isIE){
-			return dojo.doc.selection.type.toLowerCase();
-		}else{
-			var stype = "text";
-
-			// Check if the actual selection is a CONTROL (IMG, TABLE, HR, etc...).
-			var oSel;
-			try{
-				oSel = dojo.global.getSelection();
-			}catch(e){ /*squelch*/ }
-
-			if(oSel && oSel.rangeCount == 1){
-				var oRange = oSel.getRangeAt(0);
-				if(	(oRange.startContainer == oRange.endContainer) &&
-					((oRange.endOffset - oRange.startOffset) == 1) &&
-					(oRange.startContainer.nodeType != 3 /* text node*/)
-				){
-					stype = "control";
-				}
-			}
-			return stype; //String
-		}
-	},
-
-	getSelectedText: function(){
-		// summary:
-		//		Return the text (no html tags) included in the current selection or null if no text is selected
-		if(dojo.isIE){
-			if(dijit._editor.selection.getType() == 'control'){
-				return null;
-			}
-			return dojo.doc.selection.createRange().text;
-		}else{
-			var selection = dojo.global.getSelection();
-			if(selection){
-				return selection.toString(); //String
-			}
-		}
-		return '';
-	},
-
-	getSelectedHtml: function(){
-		// summary:
-		//		Return the html text of the current selection or null if unavailable
-		if(dojo.isIE){
-			if(dijit._editor.selection.getType() == 'control'){
-				return null;
-			}
-			return dojo.doc.selection.createRange().htmlText;
-		}else{
-			var selection = dojo.global.getSelection();
-			if(selection && selection.rangeCount){
-				var i;
-				var html = "";
-				for(i = 0; i < selection.rangeCount; i++){
-					//Handle selections spanning ranges, such as Opera
-					var frag = selection.getRangeAt(i).cloneContents();
-					var div = dojo.doc.createElement("div");
-					div.appendChild(frag);
-					html += div.innerHTML;
-				}
-				return html; //String
-			}
-			return null;
-		}
-	},
-
-	getSelectedElement: function(){
-		// summary:
-		//		Retrieves the selected element (if any), just in the case that
-		//		a single element (object like and image or a table) is
-		//		selected.
-		if(dijit._editor.selection.getType() == "control"){
-			if(dojo.isIE){
-				var range = dojo.doc.selection.createRange();
-				if(range && range.item){
-					return dojo.doc.selection.createRange().item(0);
-				}
-			}else{
-				var selection = dojo.global.getSelection();
-				return selection.anchorNode.childNodes[ selection.anchorOffset ];
-			}
-		}
-		return null;
-	},
-
-	getParentElement: function(){
-		// summary:
-		//		Get the parent element of the current selection
-		if(dijit._editor.selection.getType() == "control"){
-			var p = this.getSelectedElement();
-			if(p){ return p.parentNode; }
-		}else{
-			if(dojo.isIE){
-				var r = dojo.doc.selection.createRange();
-				r.collapse(true);
-				return r.parentElement();
-			}else{
-				var selection = dojo.global.getSelection();
-				if(selection){
-					var node = selection.anchorNode;
-					while(node && (node.nodeType != 1)){ // not an element
-						node = node.parentNode;
-					}
-					return node;
-				}
-			}
-		}
-		return null;
-	},
-
-	hasAncestorElement: function(/*String*/tagName /* ... */){
-		// summary:
-		// 		Check whether current selection has a  parent element which is
-		// 		of type tagName (or one of the other specified tagName)
-		// tagName: String
-		//		The tag name to determine if it has an ancestor of.
-		return this.getAncestorElement.apply(this, arguments) != null; //Boolean
-	},
-
-	getAncestorElement: function(/*String*/tagName /* ... */){
-		// summary:
-		//		Return the parent element of the current selection which is of
-		//		type tagName (or one of the other specified tagName)
-		// tagName: String
-		//		The tag name to determine if it has an ancestor of.
-		var node = this.getSelectedElement() || this.getParentElement();
-		return this.getParentOfType(node, arguments); //DOMNode
-	},
-
-	isTag: function(/*DomNode*/ node, /*String[]*/ tags){
-		// summary:
-		//		Function to determine if a node is one of an array of tags.
-		// node:
-		//		The node to inspect.
-		// tags:
-		//		An array of tag name strings to check to see if the node matches.
-		if(node && node.tagName){
-			var _nlc = node.tagName.toLowerCase();
-			for(var i=0; i<tags.length; i++){
-				var _tlc = String(tags[i]).toLowerCase();
-				if(_nlc == _tlc){
-					return _tlc; // String
-				}
-			}
-		}
-		return "";
-	},
-
-	getParentOfType: function(/*DomNode*/ node, /*String[]*/ tags){
-		// summary:
-		//		Function to locate a parent node that matches one of a set of tags
-		// node:
-		//		The node to inspect.
-		// tags:
-		//		An array of tag name strings to check to see if the node matches.
-		while(node){
-			if(this.isTag(node, tags).length){
-				return node; // DOMNode
-			}
-			node = node.parentNode;
-		}
-		return null;
-	},
-
-	collapse: function(/*Boolean*/beginning){
-		// summary:
-		//		Function to collapse (clear), the current selection
-		// beginning: Boolean
-		//		Boolean to indicate whether to collapse the cursor to the beginning of the selection or end.
-		if(window.getSelection){
-			var selection = dojo.global.getSelection();
-			if(selection.removeAllRanges){ // Mozilla
-				if(beginning){
-					selection.collapseToStart();
-				}else{
-					selection.collapseToEnd();
-				}
-			}else{ // Safari
-				// pulled from WebCore/ecma/kjs_window.cpp, line 2536
-				selection.collapse(beginning);
-			}
-		}else if(dojo.isIE){ // IE
-			var range = dojo.doc.selection.createRange();
-			range.collapse(beginning);
-			range.select();
-		}
-	},
-
-	remove: function(){
-		// summary:
-		//		Function to delete the currently selected content from the document.
-		var sel = dojo.doc.selection;
-		if(dojo.isIE){
-			if(sel.type.toLowerCase() != "none"){
-				sel.clear();
-			}
-			return sel; //Selection
-		}else{
-			sel = dojo.global.getSelection();
-			sel.deleteFromDocument();
-			return sel; //Selection
-		}
-	},
-
-	selectElementChildren: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
-		// summary:
-		//		clear previous selection and select the content of the node
-		//		(excluding the node itself)
-		// element: DOMNode
-		//		The element you wish to select the children content of.
-		// nochangefocus: Boolean
-		//		Boolean to indicate if the foxus should change or not.
-		var win = dojo.global;
-		var doc = dojo.doc;
-		var range;
-		element = dojo.byId(element);
-		if(doc.selection && dojo.isIE && dojo.body().createTextRange){ // IE
-			range = element.ownerDocument.body.createTextRange();
-			range.moveToElementText(element);
-			if(!nochangefocus){
-				try{
-					range.select(); // IE throws an exception here if the widget is hidden.  See #5439
-				}catch(e){ /* squelch */}
-			}
-		}else if(win.getSelection){
-			var selection = dojo.global.getSelection();
-			if(selection.setBaseAndExtent){ // Safari
-				selection.setBaseAndExtent(element, 0, element, element.innerText.length - 1);
-			}else if(dojo.isOpera){
-				//Opera's selectAllChildren doesn't seem to work right
-				//against <body> nodes and possibly others ... so
-				//we use the W3C range API
-				if(selection.rangeCount){
-					range = selection.getRangeAt(0);
-				}else{
-					range = doc.createRange();
-				}
-				range.setStart(element, 0);
-				range.setEnd(element,(element.nodeType == 3)?element.length:element.childNodes.length);
-				selection.addRange(range);
-			}else if(selection.selectAllChildren){ // Mozilla
-				selection.selectAllChildren(element);
-			}
-		}
-	},
-
-	selectElement: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
-		// summary:
-		//		clear previous selection and select element (including all its children)
-		// element:  DOMNode
-		//		The element to select.
-		// nochangefocus: Boolean
-		//		Boolean indicating if the focus should be changed.  IE only.
-		var range;
-		var doc = dojo.doc;
-		var win = dojo.global;
-		element = dojo.byId(element);
-		if(dojo.isIE && dojo.body().createTextRange){
-			try{
-				range = dojo.body().createControlRange();
-				range.addElement(element);
-				if(!nochangefocus){
-					range.select();
-				}
-			}catch(e){
-				this.selectElementChildren(element,nochangefocus);
-			}
-		}else if(dojo.global.getSelection){
-			var selection = win.getSelection();
-			range = doc.createRange();
-			if(selection.removeAllRanges){ // Mozilla
-				// FIXME: does this work on Safari?
-				if(dojo.isOpera){
-					//Opera works if you use the current range on
-					//the selection if present.
-					if(selection.getRangeAt(0)){
-						range = selection.getRangeAt(0);
-					}
-				}
-				range.selectNode(element);
-				selection.removeAllRanges();
-				selection.addRange(range);
-			}
-		}
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit._editor.range"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._editor.range"] = true;
-dojo.provide("dijit._editor.range");
-
-dijit.range={};
-
-dijit.range.getIndex=function(/*DomNode*/node, /*DomNode*/parent){
-//	dojo.profile.start("dijit.range.getIndex");
-	var ret=[], retR=[];
-	var stop = parent;
-	var onode = node;
-
-	var pnode, n;
-	while(node != stop){
-		var i = 0;
-		pnode = node.parentNode;
-		while((n=pnode.childNodes[i++])){
-			if(n === node){
-				--i;
-				break;
-			}
-		}
-		if(i>=pnode.childNodes.length){
-			dojo.debug("Error finding index of a node in dijit.range.getIndex");
-		}
-		ret.unshift(i);
-		retR.unshift(i-pnode.childNodes.length);
-		node = pnode;
-	}
-
-	//normalized() can not be called so often to prevent
-	//invalidating selection/range, so we have to detect
-	//here that any text nodes in a row
-	if(ret.length > 0 && onode.nodeType == 3){
-		n = onode.previousSibling;
-		while(n && n.nodeType == 3){
-			ret[ret.length-1]--;
-			n = n.previousSibling;
-		}
-		n = onode.nextSibling;
-		while(n && n.nodeType == 3){
-			retR[retR.length-1]++;
-			n = n.nextSibling;
-		}
-	}
-//	dojo.profile.end("dijit.range.getIndex");
-	return {o: ret, r:retR};
-}
-
-dijit.range.getNode = function(/*Array*/index, /*DomNode*/parent){
-	if(!dojo.isArray(index) || index.length == 0){
-		return parent;
-	}
-	var node = parent;
-//	if(!node)debugger
-	dojo.every(index, function(i){
-		if(i >= 0 && i < node.childNodes.length){
-			node = node.childNodes[i];
-		}else{
-			node = null;
-			console.debug('Error: can not find node with index',index,'under parent node',parent );
-			return false; //terminate dojo.every
-		}
-		return true; //carry on the every loop
-	});
-
-	return node;
-}
-
-dijit.range.getCommonAncestor = function(n1,n2){
-	var getAncestors = function(n){
-		var as=[];
-		while(n){
-			as.unshift(n);
-			if(n.nodeName!='BODY'){
-				n = n.parentNode;
-			}else{
-				break;
-			}
-		}
-		return as;
-	};
-	var n1as = getAncestors(n1);
-	var n2as = getAncestors(n2);
-
-	var m = Math.min(n1as.length,n2as.length);
-	var com = n1as[0]; //at least, one element should be in the array: the root (BODY by default)
-	for(var i=1;i<m;i++){
-		if(n1as[i] === n2as[i]){
-			com = n1as[i]
-		}else{
-			break;
-		}
-	}
-	return com;
-}
-
-dijit.range.getAncestor = function(/*DomNode*/node, /*RegEx?*/regex, /*DomNode?*/root){
-	root = root || node.ownerDocument.body;
-	while(node && node !== root){
-		var name = node.nodeName.toUpperCase() ;
-		if(regex.test(name)){
-			return node;
-		}
-
-		node = node.parentNode;
-	}
-	return null;
-}
-
-dijit.range.BlockTagNames = /^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/;
-dijit.range.getBlockAncestor = function(/*DomNode*/node, /*RegEx?*/regex, /*DomNode?*/root){
-	root = root || node.ownerDocument.body;
-	regex = regex || dijit.range.BlockTagNames;
-	var block=null, blockContainer;
-	while(node && node !== root){
-		var name = node.nodeName.toUpperCase() ;
-		if(!block && regex.test(name)){
-			block = node;
-		}
-		if(!blockContainer && (/^(?:BODY|TD|TH|CAPTION)$/).test(name)){
-			blockContainer = node;
-		}
-
-		node = node.parentNode;
-	}
-	return {blockNode:block, blockContainer:blockContainer || node.ownerDocument.body};
-}
-
-dijit.range.atBeginningOfContainer = function(/*DomNode*/container, /*DomNode*/node, /*Int*/offset){
-	var atBeginning = false;
-	var offsetAtBeginning = (offset == 0);
-	if(!offsetAtBeginning && node.nodeType == 3){ //if this is a text node, check whether the left part is all space
-		if(/^[\s\xA0]+$/.test(node.nodeValue.substr(0,offset))){
-			offsetAtBeginning = true;
-		}
-	}
-	if(offsetAtBeginning){
-		var cnode = node;
-		atBeginning = true;
-		while(cnode && cnode !== container){
-			if(cnode.previousSibling){
-				atBeginning = false;
-				break;
-			}
-			cnode = cnode.parentNode;
-		}
-	}
-	return atBeginning;
-}
-
-dijit.range.atEndOfContainer = function(/*DomNode*/container, /*DomNode*/node, /*Int*/offset){
-	var atEnd = false;
-	var offsetAtEnd = (offset == (node.length || node.childNodes.length));
-	if(!offsetAtEnd && node.nodeType == 3){ //if this is a text node, check whether the right part is all space
-		if(/^[\s\xA0]+$/.test(node.nodeValue.substr(offset))){
-			offsetAtEnd = true;
-		}
-	}
-	if(offsetAtEnd){
-		var cnode = node;
-		atEnd = true;
-		while(cnode && cnode !== container){
-			if(cnode.nextSibling){
-				atEnd = false;
-				break;
-			}
-			cnode = cnode.parentNode;
-		}
-	}
-	return atEnd;
-}
-
-dijit.range.adjacentNoneTextNode=function(startnode, next){
-	var node = startnode;
-	var len = (0-startnode.length) || 0;
-	var prop = next?'nextSibling':'previousSibling';
-	while(node){
-		if(node.nodeType!=3){
-			break;
-		}
-		len += node.length
-		node = node[prop];
-	}
-	return [node,len];
-}
-
-dijit.range._w3c = Boolean(window['getSelection']);
-dijit.range.create = function(/*Window?*/win){
-	if(dijit.range._w3c){
-		return (win || dojo.global).document.createRange();
-	}else{//IE
-		return new dijit.range.W3CRange;
-	}
-}
-
-dijit.range.getSelection = function(/*Window*/win, /*Boolean?*/ignoreUpdate){
-	if(dijit.range._w3c){
-		return win.getSelection();
-	}else{//IE
-		var s = new dijit.range.ie.selection(win);
-		if(!ignoreUpdate){
-			s._getCurrentSelection();
-		}
-		return s;
-	}
-}
-
-if(!dijit.range._w3c){
-	dijit.range.ie={
-		cachedSelection: {},
-		selection: function(win){
-			this._ranges = [];
-			this.addRange = function(r, /*boolean*/internal){
-				this._ranges.push(r);
-				if(!internal){
-					r._select();
-				}
-				this.rangeCount = this._ranges.length;
-			};
-			this.removeAllRanges = function(){
-				//don't detach, the range may be used later
-//				for(var i=0;i<this._ranges.length;i++){
-//					this._ranges[i].detach();
-//				}
-				this._ranges = [];
-				this.rangeCount = 0;
-			};
-			var _initCurrentRange = function(){
-				var r = win.document.selection.createRange();
-				var type=win.document.selection.type.toUpperCase();
-				if(type == "CONTROL"){
-					//TODO: multiple range selection(?)
-					return new dijit.range.W3CRange(dijit.range.ie.decomposeControlRange(r));
-				}else{
-					return new dijit.range.W3CRange(dijit.range.ie.decomposeTextRange(r));
-				}
-			};
-			this.getRangeAt = function(i){
-				return this._ranges[i];
-			};
-			this._getCurrentSelection = function(){
-				this.removeAllRanges();
-				var r=_initCurrentRange();
-				if(r){
-					this.addRange(r, true);
-				}
-			};
-		},
-		decomposeControlRange: function(range){
-			var firstnode = range.item(0), lastnode = range.item(range.length-1);
-			var startContainer = firstnode.parentNode, endContainer = lastnode.parentNode;
-			var startOffset = dijit.range.getIndex(firstnode, startContainer).o;
-			var endOffset = dijit.range.getIndex(lastnode, endContainer).o+1;
-			return [startContainer, startOffset,endContainer, endOffset];
-		},
-		getEndPoint: function(range, end){
-			var atmrange = range.duplicate();
-			atmrange.collapse(!end);
-			var cmpstr = 'EndTo' + (end?'End':'Start');
-			var parentNode = atmrange.parentElement();
-
-			var startnode, startOffset, lastNode;
-			if(parentNode.childNodes.length>0){
-				dojo.every(parentNode.childNodes, function(node,i){
-					var calOffset;
-					if(node.nodeType != 3){
-						atmrange.moveToElementText(node);
-
-						if(atmrange.compareEndPoints(cmpstr,range) > 0){
-							//startnode = node.previousSibling;
-							if(lastNode && lastNode.nodeType == 3){
-								//where shall we put the start? in the text node or after?
-								startnode = lastNode;
-								calOffset = true;
-							}else{
-								startnode = parentNode;
-								startOffset = i;
-								return false;
-							}
-						}else{
-							if(i == parentNode.childNodes.length-1){
-								startnode = parentNode;
-								startOffset = parentNode.childNodes.length;
-								return false;
-							}
-						}
-					}else{
-						if(i == parentNode.childNodes.length-1){//at the end of this node
-							startnode = node;
-							calOffset = true;
-						}
-					}
-		//			try{
-						if(calOffset && startnode){
-							var prevnode = dijit.range.adjacentNoneTextNode(startnode)[0];
-							if(prevnode){
-								startnode = prevnode.nextSibling;
-							}else{
-								startnode = parentNode.firstChild; //firstChild must be a text node
-							}
-							var prevnodeobj = dijit.range.adjacentNoneTextNode(startnode);
-							prevnode = prevnodeobj[0];
-							var lenoffset = prevnodeobj[1];
-							if(prevnode){
-								atmrange.moveToElementText(prevnode);
-								atmrange.collapse(false);
-							}else{
-								atmrange.moveToElementText(parentNode);
-							}
-							atmrange.setEndPoint(cmpstr, range);
-							startOffset = atmrange.text.length-lenoffset;
-
-							return false;
-						}
-		//			}catch(e){ debugger }
-					lastNode = node;
-					return true;
-				});
-			}else{
-				startnode = parentNode;
-				startOffset = 0;
-			}
-
-			//if at the end of startnode and we are dealing with start container, then
-			//move the startnode to nextSibling if it is a text node
-			//TODO: do this for end container?
-			if(!end && startnode.nodeType == 1 && startOffset == startnode.childNodes.length){
-				var nextnode=startnode.nextSibling;
-				if(nextnode && nextnode.nodeType == 3){
-					startnode = nextnode;
-					startOffset = 0;
-				}
-			}
-			return [startnode, startOffset];
-		},
-		setEndPoint: function(range, container, offset){
-			//text node
-			var atmrange = range.duplicate(), node, len;
-			if(container.nodeType!=3){ //normal node
-				if(offset > 0){
-					node = container.childNodes[offset-1];
-					if(node.nodeType == 3){
-						container = node;
-						offset = node.length;
-						//pass through
-					}else{
-						if(node.nextSibling && node.nextSibling.nodeType == 3){
-							container=node.nextSibling;
-							offset=0;
-							//pass through
-						}else{
-							atmrange.moveToElementText(node.nextSibling?node:container);
-							var parent = node.parentNode;
-							var tempNode = parent.insertBefore(node.ownerDocument.createTextNode(' '), node.nextSibling);
-							atmrange.collapse(false);
-							parent.removeChild(tempNode);
-						}
-					}
-				}else{
-					atmrange.moveToElementText(container);
-					atmrange.collapse(true);
-				}
-			}
-			if(container.nodeType == 3){
-				var prevnodeobj = dijit.range.adjacentNoneTextNode(container);
-				var prevnode = prevnodeobj[0];
-				len = prevnodeobj[1];
-				if(prevnode){
-					atmrange.moveToElementText(prevnode);
-					atmrange.collapse(false);
-					//if contentEditable is not inherit, the above collapse won't make the end point
-					//in the correctly position: it always has a -1 offset, so compensate it
-					if(prevnode.contentEditable!='inherit'){
-						len++;
-					}
-				}else{
-					atmrange.moveToElementText(container.parentNode);
-					atmrange.collapse(true);
-				}
-
-				offset += len;
-				if(offset>0){
-					if(atmrange.move('character',offset) != offset){
-						console.error('Error when moving!');
-					}
-				}
-			}
-
-			return atmrange;
-		},
-		decomposeTextRange: function(range){
-			var tmpary = dijit.range.ie.getEndPoint(range);
-			var startContainer = tmpary[0], startOffset = tmpary[1];
-			var endContainer = tmpary[0], endOffset = tmpary[1];
-
-			if(range.htmlText.length){
-				if(range.htmlText == range.text){ //in the same text node
-					endOffset = startOffset+range.text.length;
-				}else{
-					tmpary = dijit.range.ie.getEndPoint(range,true);
-					endContainer = tmpary[0], endOffset = tmpary[1];
-//					if(startContainer.tagName == "BODY"){
-//						startContainer = startContainer.firstChild;
-//					}
-				}
-			}
-			return [startContainer, startOffset, endContainer, endOffset];
-		},
-		setRange: function(range, startContainer,
-			startOffset, endContainer, endOffset, collapsed){
-			var start=dijit.range.ie.setEndPoint(range, startContainer, startOffset);
-
-			range.setEndPoint('StartToStart',start);
-			if(!collapsed){
-				var end=dijit.range.ie.setEndPoint(range, endContainer, endOffset);
-			}
-			range.setEndPoint('EndToEnd',end || start);
-
-			return range;
-		}
-	}
-
-dojo.declare("dijit.range.W3CRange",null, {
-	constructor: function(){
-		if(arguments.length>0){
-			this.setStart(arguments[0][0],arguments[0][1]);
-			this.setEnd(arguments[0][2],arguments[0][3]);
-		}else{
-			this.commonAncestorContainer = null;
-			this.startContainer = null;
-			this.startOffset = 0;
-			this.endContainer = null;
-			this.endOffset = 0;
-			this.collapsed = true;
-		}
-	},
-	_updateInternal: function(){
-		if(this.startContainer !== this.endContainer){
-			this.commonAncestorContainer = dijit.range.getCommonAncestor(this.startContainer, this.endContainer);
-		}else{
-			this.commonAncestorContainer = this.startContainer;
-		}
-		this.collapsed = (this.startContainer === this.endContainer) && (this.startOffset == this.endOffset);
-	},
-	setStart: function(node, offset){
-		offset=parseInt(offset);
-		if(this.startContainer === node && this.startOffset == offset){
-			return;
-		}
-		delete this._cachedBookmark;
-
-		this.startContainer = node;
-		this.startOffset = offset;
-		if(!this.endContainer){
-			this.setEnd(node, offset);
-		}else{
-			this._updateInternal();
-		}
-	},
-	setEnd: function(node, offset){
-		offset=parseInt(offset);
-		if(this.endContainer === node && this.endOffset == offset){
-			return;
-		}
-		delete this._cachedBookmark;
-
-		this.endContainer = node;
-		this.endOffset = offset;
-		if(!this.startContainer){
-			this.setStart(node, offset);
-		}else{
-			this._updateInternal();
-		}
-	},
-	setStartAfter: function(node, offset){
-		this._setPoint('setStart', node, offset, 1);
-	},
-	setStartBefore: function(node, offset){
-		this._setPoint('setStart', node, offset, 0);
-	},
-	setEndAfter: function(node, offset){
-		this._setPoint('setEnd', node, offset, 1);
-	},
-	setEndBefore: function(node, offset){
-		this._setPoint('setEnd', node, offset, 0);
-	},
-	_setPoint: function(what, node, offset, ext){
-		var index = dijit.range.getIndex(node, node.parentNode).o;
-		this[what](node.parentNode, index.pop()+ext);
-	},
-	_getIERange: function(){
-		var r = (this._body || this.endContainer.ownerDocument.body).createTextRange();
-		dijit.range.ie.setRange(r, this.startContainer, this.startOffset, this.endContainer, this.endOffset, this.collapsed);
-		return r;
-	},
-	getBookmark: function(body){
-		this._getIERange();
-		return this._cachedBookmark;
-	},
-	_select: function(){
-		var r = this._getIERange();
-		r.select();
-	},
-	deleteContents: function(){
-		var r = this._getIERange();
-		r.pasteHTML('');
-		this.endContainer = this.startContainer;
-		this.endOffset = this.startOffset;
-		this.collapsed = true;
-	},
-	cloneRange: function(){
-		var r = new dijit.range.W3CRange([this.startContainer,this.startOffset,
-			this.endContainer,this.endOffset]);
-		r._body = this._body;
-		return r;
-	},
-	detach: function(){
-		this._body = null;
-		this.commonAncestorContainer = null;
-		this.startContainer = null;
-		this.startOffset = 0;
-		this.endContainer = null;
-		this.endOffset = 0;
-		this.collapsed = true;
-}
-});
-} //if(!dijit.range._w3c)
-
-}
-
-if(!dojo._hasResource["dijit._editor.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._editor.html"] = true;
-dojo.provide("dijit._editor.html");
-
-dijit._editor.escapeXml=function(/*String*/str, /*Boolean?*/noSingleQuotes){
-	// summary:
-	//		Adds escape sequences for special characters in XML: &<>"'
-	//		Optionally skips escapes for single quotes
-	str = str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """);
-	if(!noSingleQuotes){
-		str = str.replace(/'/gm, "'");
-	}
-	return str; // string
-};
-
-dijit._editor.getNodeHtml=function(/* DomNode */node){
-	var output;
-	switch(node.nodeType){
-		case 1: //element node
-			var lName = node.nodeName.toLowerCase();
-			if(lName.charAt(0) == "/"){
-				// IE does some strange things with malformed HTML input, like
-				// treating a close tag </span> without an open tag <span>, as
-				// a new tag with tagName of /span.  Corrupts output HTML, remove
-				// them.  Other browsers don't prefix tags that way, so will
-				// never show up.
-				return "";
-			}
-			output = '<' + lName;
-
-			//store the list of attributes and sort it to have the
-			//attributes appear in the dictionary order
-			var attrarray = [];
-			var attr;
-			if(dojo.isIE && node.outerHTML){
-				var s = node.outerHTML;
-				s = s.substr(0, s.indexOf('>'))
-					.replace(/(['"])[^"']*\1/g, ''); //to make the following regexp safe
-				var reg = /(\b\w+)\s?=/g;
-				var m, key;
-				while((m = reg.exec(s))){
-					key = m[1];
-					if(key.substr(0,3) != '_dj'){
-						if(key == 'src' || key == 'href'){
-							if(node.getAttribute('_djrealurl')){
-								attrarray.push([key,node.getAttribute('_djrealurl')]);
-								continue;
-							}
-						}
-						var val, match;
-						switch(key){
-							case 'style':
-								val = node.style.cssText.toLowerCase();
-								break;
-							case 'class':
-								val = node.className;
-								break;
-							case 'width':
-								if(lName === "img"){
-									// This somehow gets lost on IE for IMG tags and the like
-									// and we have to find it in outerHTML, known IE oddity.
-									match=/width=(\S+)/i.exec(s);
-									if(match){
-										val = match[1];
-									}
-									break;
-								}
-							case 'height':
-								if(lName === "img"){
-									// This somehow gets lost on IE for IMG tags and the like
-									// and we have to find it in outerHTML, known IE oddity.
-									match=/height=(\S+)/i.exec(s);
-									if(match){
-										val = match[1];
-									}
-									break;
-								}
-							default:
-								val = node.getAttribute(key);
-						}
-						if(val != null){
-							attrarray.push([key, val.toString()]);
-						}
-					}
-				}
-			}else{
-				var i = 0;
-				while((attr = node.attributes[i++])){
-					//ignore all attributes starting with _dj which are
-					//internal temporary attributes used by the editor
-					var n = attr.name;
-					if(n.substr(0,3) != '_dj' /*&&
-						(attr.specified == undefined || attr.specified)*/){
-						var v = attr.value;
-						if(n == 'src' || n == 'href'){
-							if(node.getAttribute('_djrealurl')){
-								v = node.getAttribute('_djrealurl');
-							}
-						}
-						attrarray.push([n,v]);
-					}
-				}
-			}
-			attrarray.sort(function(a,b){
-				return a[0] < b[0] ? -1 : (a[0] == b[0] ? 0 : 1);
-			});
-			var j = 0;
-			while((attr = attrarray[j++])){
-				output += ' ' + attr[0] + '="' +
-					(dojo.isString(attr[1]) ? dijit._editor.escapeXml(attr[1], true) : attr[1]) + '"';
-			}
-			if(lName === "script"){
-				// Browsers handle script tags differently in how you get content,
-				// but innerHTML always seems to work, so insert its content that way
-				// Yes, it's bad to allow script tags in the editor code, but some people
-				// seem to want to do it, so we need to at least return them right.
-				// other plugins/filters can strip them.
-				output += '>' + node.innerHTML +'</' + lName + '>';
-			}else{
-				if(node.childNodes.length){
-					output += '>' + dijit._editor.getChildrenHtml(node)+'</' + lName +'>';
-				}else{
-					switch(lName){
-						case 'br':
-						case 'hr':
-						case 'img':
-						case 'input':
-						case 'base':
-						case 'meta':
-						case 'area':
-						case 'basefont':
-							// These should all be singly closed
-							output += ' />';
-							break;
-						default:
-							// Assume XML style separate closure for everything else.
-							output += '></' + lName + '>';
-					}
-				}
-			}
-			break;
-		case 4: // cdata
-		case 3: // text
-			// FIXME:
-			output = dijit._editor.escapeXml(node.nodeValue, true);
-			break;
-		case 8: //comment
-			// FIXME:
-			output = '<!--' + dijit._editor.escapeXml(node.nodeValue, true) + '-->';
-			break;
-		default:
-			output = "<!-- Element not recognized - Type: " + node.nodeType + " Name: " + node.nodeName + "-->";
-	}
-	return output;
-};
-
-dijit._editor.getChildrenHtml = function(/* DomNode */dom){
-	// summary:
-	//		Returns the html content of a DomNode and children
-	var out = "";
-	if(!dom){ return out; }
-	var nodes = dom["childNodes"] || dom;
-
-	//IE issue.
-	//If we have an actual node we can check parent relationships on for IE,
-	//We should check, as IE sometimes builds invalid DOMS.  If no parent, we can't check
-	//And should just process it and hope for the best.
-	var checkParent = !dojo.isIE || nodes !== dom;
-
-	var node, i = 0;
-	while((node = nodes[i++])){
-		//IE is broken.  DOMs are supposed to be a tree.  But in the case of malformed HTML, IE generates a graph
-		//meaning one node ends up with multiple references (multiple parents).  This is totally wrong and invalid, but
-		//such is what it is.  We have to keep track and check for this because otherise the source output HTML will have dups.
-		//No other browser generates a graph.  Leave it to IE to break a fundamental DOM rule.  So, we check the parent if we can
-		//If we can't, nothing more we can do other than walk it.
-		if(!checkParent || node.parentNode == dom){
-			out += dijit._editor.getNodeHtml(node);
-		}
-	}
-	return out; // String
-};
-
-}
-
-if(!dojo._hasResource["dijit._editor.RichText"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._editor.RichText"] = true;
-dojo.provide("dijit._editor.RichText");
-
-
-
-
-
-
-// used to restore content when user leaves this page then comes back
-// but do not try doing dojo.doc.write if we are using xd loading.
-// dojo.doc.write will only work if RichText.js is included in the dojo.js
-// file. If it is included in dojo.js and you want to allow rich text saving
-// for back/forward actions, then set dojo.config.allowXdRichTextSave = true.
-if(!dojo.config["useXDomain"] || dojo.config["allowXdRichTextSave"]){
-	if(dojo._postLoad){
-		(function(){
-			var savetextarea = dojo.doc.createElement('textarea');
-			savetextarea.id = dijit._scopeName + "._editor.RichText.savedContent";
-			dojo.style(savetextarea, {
-				display:'none',
-				position:'absolute',
-				top:"-100px",
-				height:"3px",
-				width:"3px"
-			});
-			dojo.body().appendChild(savetextarea);
-		})();
-	}else{
-		//dojo.body() is not available before onLoad is fired
-		try{
-			dojo.doc.write('<textarea id="' + dijit._scopeName + '._editor.RichText.savedContent" ' +
-				'style="display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;"></textarea>');
-		}catch(e){ }
-	}
-}
-
-dojo.declare("dijit._editor.RichText", dijit._Widget, {
-	constructor: function(params){
-		// summary:
-		//		dijit._editor.RichText is the core of dijit.Editor, which provides basic
-		//		WYSIWYG editing features.
-		//
-		// description:
-		//		dijit._editor.RichText is the core of dijit.Editor, which provides basic
-		//		WYSIWYG editing features. It also encapsulates the differences
-		//		of different js engines for various browsers.  Do not use this widget
-		//		with an HTML <TEXTAREA> tag, since the browser unescapes XML escape characters,
-		//		like <.  This can have unexpected behavior and lead to security issues
-		//		such as scripting attacks.
-		//
-		// tags:
-		//		private
-
-		// contentPreFilters: Function(String)[]
-		//		Pre content filter function register array.
-		//		these filters will be executed before the actual
-		//		editing area gets the html content.
-		this.contentPreFilters = [];
-
-		// contentPostFilters: Function(String)[]
-		//		post content filter function register array.
-		//		These will be used on the resulting html
-		//		from contentDomPostFilters. The resulting
-		//		content is the final html (returned by getValue()).
-		this.contentPostFilters = [];
-
-		// contentDomPreFilters: Function(DomNode)[]
-		//		Pre content dom filter function register array.
-		//		These filters are applied after the result from
-		//		contentPreFilters are set to the editing area.
-		this.contentDomPreFilters = [];
-
-		// contentDomPostFilters: Function(DomNode)[]
-		//		Post content dom filter function register array.
-		//		These filters are executed on the editing area dom.
-		//		The result from these will be passed to contentPostFilters.
-		this.contentDomPostFilters = [];
-
-		// editingAreaStyleSheets: dojo._URL[]
-		//		array to store all the stylesheets applied to the editing area
-		this.editingAreaStyleSheets = [];
-
-		// Make a copy of this.events before we start writing into it, otherwise we
-		// will modify the prototype which leads to bad things on pages w/multiple editors
-		this.events = [].concat(this.events);
-
-		this._keyHandlers = {};
-		this.contentPreFilters.push(dojo.hitch(this, "_preFixUrlAttributes"));
-		if(dojo.isMoz){
-			this.contentPreFilters.push(this._normalizeFontStyle);
-			this.contentPostFilters.push(this._removeMozBogus);
-		}
-		if(dojo.isWebKit){
-			// Try to clean up WebKit bogus artifacts.  The inserted classes
-			// made by WebKit sometimes messes things up.
-			this.contentPreFilters.push(this._removeWebkitBogus);
-			this.contentPostFilters.push(this._removeWebkitBogus);
-		}
-		if(dojo.isIE){
-			// IE generates <strong> and <em> but we want to normalize to <b> and <i>
-			this.contentPostFilters.push(this._normalizeFontStyle);
-		}
-		//this.contentDomPostFilters.push(this._postDomFixUrlAttributes);
-
-		this.onLoadDeferred = new dojo.Deferred();
-	},
-
-	// inheritWidth: Boolean
-	//		whether to inherit the parent's width or simply use 100%
-	inheritWidth: false,
-
-	// focusOnLoad: [deprecated] Boolean
-	//		Focus into this widget when the page is loaded
-	focusOnLoad: false,
-
-	// name: String?
-	//		Specifies the name of a (hidden) <textarea> node on the page that's used to save
-	//		the editor content on page leave.   Used to restore editor contents after navigating
-	//		to a new page and then hitting the back button.
-	name: "",
-
-	// styleSheets: [const] String
-	//		semicolon (";") separated list of css files for the editing area
-	styleSheets: "",
-
-	// _content: [private] String
-	//		temporary content storage
-	_content: "",
-
-	// height: String
-	//		Set height to fix the editor at a specific height, with scrolling.
-	//		By default, this is 300px.  If you want to have the editor always
-	//		resizes to accommodate the content, use AlwaysShowToolbar plugin
-	//		and set height="".  If this editor is used within a layout widget,
-	//		set height="100%".
-	height: "300px",
-
-	// minHeight: String
-	//		The minimum height that the editor should have.
-	minHeight: "1em",
-
-	// isClosed: [private] Boolean
-	isClosed: true,
-
-	// isLoaded: [private] Boolean
-	isLoaded: false,
-
-	// _SEPARATOR: [private] String
-	//		Used to concat contents from multiple editors into a single string,
-	//		so they can be saved into a single <textarea> node.  See "name" attribute.
-	_SEPARATOR: "@@**%%__RICHTEXTBOUNDRY__%%**@@",
-
-	// onLoadDeferred: [protected] dojo.Deferred
-	//		Deferred which is fired when the editor finishes loading
-	onLoadDeferred: null,
-
-	// isTabIndent: Boolean
-	//		Make tab key and shift-tab indent and outdent rather than navigating.
-	//		Caution: sing this makes web pages inaccessible to users unable to use a mouse.
-	isTabIndent: false,
-
-	// disableSpellCheck: [const] Boolean
-	//		When true, disables the browser's native spell checking, if supported.
-	//		Works only in Firefox.
-	disableSpellCheck: false,
-
-	postCreate: function(){
-		if("textarea" == this.domNode.tagName.toLowerCase()){
-			console.warn("RichText should not be used with the TEXTAREA tag.  See dijit._editor.RichText docs.");
-		}
-		dojo.publish(dijit._scopeName + "._editor.RichText::init", [this]);
-		this.open();
-		this.setupDefaultShortcuts();
-	},
-
-	setupDefaultShortcuts: function(){
-		// summary:
-		//		Add some default key handlers
-		// description:
-		// 		Overwrite this to setup your own handlers. The default
-		// 		implementation does not use Editor commands, but directly
-		//		executes the builtin commands within the underlying browser
-		//		support.
-		// tags:
-		//		protected
-		var exec = dojo.hitch(this, function(cmd, arg){
-			return function(){
-				return !this.execCommand(cmd,arg);
-			};
-		});
-
-		var ctrlKeyHandlers = {
-			b: exec("bold"),
-			i: exec("italic"),
-			u: exec("underline"),
-			a: exec("selectall"),
-			s: function(){ this.save(true); },
-			m: function(){ this.isTabIndent = !this.isTabIndent; },
-
-			"1": exec("formatblock", "h1"),
-			"2": exec("formatblock", "h2"),
-			"3": exec("formatblock", "h3"),
-			"4": exec("formatblock", "h4"),
-
-			"\\": exec("insertunorderedlist")
-		};
-
-		if(!dojo.isIE){
-			ctrlKeyHandlers.Z = exec("redo"); //FIXME: undo?
-		}
-
-		for(var key in ctrlKeyHandlers){
-			this.addKeyHandler(key, true, false, ctrlKeyHandlers[key]);
-		}
-	},
-
-	// events: [private] String[]
-	//		 events which should be connected to the underlying editing area
-	events: ["onKeyPress", "onKeyDown", "onKeyUp", "onClick"],
-
-	// captureEvents: [deprecated] String[]
-	//		 Events which should be connected to the underlying editing
-	//		 area, events in this array will be addListener with
-	//		 capture=true.
-	// TODO: looking at the code I don't see any distinction between events and captureEvents,
-	// so get rid of this for 2.0 if not sooner
-	captureEvents: [],
-
-	_editorCommandsLocalized: false,
-	_localizeEditorCommands: function(){
-		// summary:
-		//		When IE is running in a non-English locale, the API actually changes,
-		//		so that we have to say (for example) danraku instead of p (for paragraph).
-		//		Handle that here.
-		// tags:
-		//		private
-		if(this._editorCommandsLocalized){
-			return;
-		}
-		this._editorCommandsLocalized = true;
-
-		//in IE, names for blockformat is locale dependent, so we cache the values here
-
-		//if the normal way fails, we try the hard way to get the list
-
-		//do not use _cacheLocalBlockFormatNames here, as it will
-		//trigger security warning in IE7
-
-		//put p after div, so if IE returns Normal, we show it as paragraph
-		//We can distinguish p and div if IE returns Normal, however, in order to detect that,
-		//we have to call this.document.selection.createRange().parentElement() or such, which
-		//could slow things down. Leave it as it is for now
-		var formats = ['div', 'p', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul', 'address'];
-		var localhtml = "", format, i=0;
-		while((format=formats[i++])){
-			//append a <br> after each element to separate the elements more reliably
-			if(format.charAt(1) != 'l'){
-				localhtml += "<"+format+"><span>content</span></"+format+"><br/>";
-			}else{
-				localhtml += "<"+format+"><li>content</li></"+format+"><br/>";
-			}
-		}
-		//queryCommandValue returns empty if we hide editNode, so move it out of screen temporary
-		var div = dojo.doc.createElement('div');
-		dojo.style(div, {
-			position: "absolute",
-			top: "-2000px"
-		});
-		dojo.doc.body.appendChild(div);
-		div.innerHTML = localhtml;
-		var node = div.firstChild;
-		while(node){
-			dijit._editor.selection.selectElement(node.firstChild);
-			dojo.withGlobal(this.window, "selectElement", dijit._editor.selection, [node.firstChild]);
-			var nativename = node.tagName.toLowerCase();
-			this._local2NativeFormatNames[nativename] = document.queryCommandValue("formatblock");
-			//this.queryCommandValue("formatblock");
-			this._native2LocalFormatNames[this._local2NativeFormatNames[nativename]] = nativename;
-			node = node.nextSibling.nextSibling;
-		}
-		dojo.body().removeChild(div);
-	},
-
-	open: function(/*DomNode?*/ element){
-		// summary:
-		//		Transforms the node referenced in this.domNode into a rich text editing
-		//		node.
-		// description:
-		//		Sets up the editing area asynchronously. This will result in
-		//		the creation and replacement with an <iframe>.
-		//
-		//		A dojo.Deferred object is created at this.onLoadDeferred, and
-		//		users may attach to it to be informed when the rich-text area
-		//		initialization is finalized.
-		// tags:
-		//		private
-
-		if(!this.onLoadDeferred || this.onLoadDeferred.fired >= 0){
-			this.onLoadDeferred = new dojo.Deferred();
-		}
-
-		if(!this.isClosed){ this.close(); }
-		dojo.publish(dijit._scopeName + "._editor.RichText::open", [ this ]);
-
-		this._content = "";
-		if(arguments.length == 1 && element.nodeName){ // else unchanged
-			this.domNode = element;
-		}
-
-		var dn = this.domNode;
-
-		// "html" will hold the innerHTML of the srcNodeRef and will be used to
-		// initialize the editor.
-		var html;
-
-		if(dn.nodeName && dn.nodeName.toLowerCase() == "textarea"){
-			// if we were created from a textarea, then we need to create a
-			// new editing harness node.
-			var ta = (this.textarea = dn);
-			this.name = ta.name;
-			html = ta.value;
-			dn = this.domNode = dojo.doc.createElement("div");
-			dn.setAttribute('widgetId', this.id);
-			ta.removeAttribute('widgetId');
-			dn.cssText = ta.cssText;
-			dn.className += " " + ta.className;
-			dojo.place(dn, ta, "before");
-			var tmpFunc = dojo.hitch(this, function(){
-				//some browsers refuse to submit display=none textarea, so
-				//move the textarea off screen instead
-				dojo.style(ta, {
-					display: "block",
-					position: "absolute",
-					top: "-1000px"
-				});
-
-				if(dojo.isIE){ //nasty IE bug: abnormal formatting if overflow is not hidden
-					var s = ta.style;
-					this.__overflow = s.overflow;
-					s.overflow = "hidden";
-				}
-			});
-			if(dojo.isIE){
-				setTimeout(tmpFunc, 10);
-			}else{
-				tmpFunc();
-			}
-
-			if(ta.form){
-				dojo.connect(ta.form, "onsubmit", this, function(){
-					// FIXME: should we be calling close() here instead?
-					ta.value = this.getValue();
-				});
-			}
-		}else{
-			html = dijit._editor.getChildrenHtml(dn);
-			dn.innerHTML = "";
-		}
-
-		var content = dojo.contentBox(dn);
-		this._oldHeight = content.h;
-		this._oldWidth = content.w;
-
-		this.savedContent = html;
-
-		// If we're a list item we have to put in a blank line to force the
-		// bullet to nicely align at the top of text
-		if(dn.nodeName && dn.nodeName == "LI"){
-			dn.innerHTML = " <br>";
-		}
-
-		this.editingArea = dn.ownerDocument.createElement("div");
-		dn.appendChild(this.editingArea);
-
-		// User has pressed back/forward button so we lost the text in the editor, but it's saved
-		// in a hidden <textarea> (which contains the data for all the editors on this page),
-		// so get editor value from there
-		if(this.name !== "" && (!dojo.config["useXDomain"] || dojo.config["allowXdRichTextSave"])){
-			var saveTextarea = dojo.byId(dijit._scopeName + "._editor.RichText.savedContent");
-			if(saveTextarea.value !== ""){
-				var datas = saveTextarea.value.split(this._SEPARATOR), i=0, dat;
-				while((dat=datas[i++])){
-					var data = dat.split(":");
-					if(data[0] == this.name){
-						html = data[1];
-						datas.splice(i, 1);	// TODO: this has no effect
-						break;
-					}
-				}
-			}
-
-			// TODO: this is troublesome if this editor has been destroyed, should have global handler.
-			// TODO: need to clear <textarea> in global handler
-			dojo.addOnUnload(dojo.hitch(this, "_saveContent"));
-		}
-
-		this.isClosed = false;
-
-		var ifr = (this.editorObject = this.iframe = dojo.doc.createElement('iframe'));
-		ifr.id = this.id+"_iframe";
-		this._iframeSrc = this._getIframeDocTxt();
-		ifr.style.border = "none";
-		ifr.style.width = "100%";
-		if(this._layoutMode){
-			// iframe should be 100% height, thus getting it's height from surrounding
-			// <div> (which has the correct height set by Editor)
-			ifr.style.height = "100%";
-		}else{
-			if(dojo.isIE >= 7){
-				if(this.height){
-					ifr.style.height = this.height;
-				}
-				if(this.minHeight){
-					ifr.style.minHeight = this.minHeight;
-				}
-			}else{
-				ifr.style.height = this.height ? this.height : this.minHeight;
-			}
-		}
-		ifr.frameBorder = 0;
-		ifr._loadFunc = dojo.hitch( this, function(win){
-			this.window = win;
-			this.document = this.window.document;
-
-			if(dojo.isIE){
-				this._localizeEditorCommands();
-			}
-
-			// Do final setup and set initial contents of editor
-			this.onLoad(html);
-
-			this.savedContent = this.getValue(true);
-		});
-
-		// Set the iframe's initial (blank) content.
-		var s = 'javascript:parent.' + dijit._scopeName + '.byId("'+this.id+'")._iframeSrc';
-		ifr.setAttribute('src', s);
-		this.editingArea.appendChild(ifr);
-
-		if(dojo.isSafari){ // Safari seems to always append iframe with src=about:blank
-			setTimeout(function(){ifr.setAttribute('src', s);},0);
-		}
-
-		// TODO: this is a guess at the default line-height, kinda works
-		if(dn.nodeName == "LI"){
-			dn.lastChild.style.marginTop = "-1.2em";
-		}
-
-		dojo.addClass(this.domNode, "RichTextEditable");
-	},
-
-	//static cache variables shared among all instance of this class
-	_local2NativeFormatNames: {},
-	_native2LocalFormatNames: {},
-
-	_getIframeDocTxt: function(){
-		// summary:
-		//		Generates the boilerplate text of the document inside the iframe (ie, <html><head>...</head><body/></html>).
-		//		Editor content (if not blank) should be added afterwards.
-		// tags:
-		//		private
-		var _cs = dojo.getComputedStyle(this.domNode);
-
-		// The contents inside of <body>.  The real contents are set later via a call to setValue().
-		var html = "";
-		if(dojo.isIE || (!this.height && !dojo.isMoz)){
-			// In auto-expand mode, need a wrapper div for AlwaysShowToolbar plugin to correctly
-			// expand/contract the editor as the content changes.
-			html = "<div></div>";
-		}else if(dojo.isMoz){
-			// workaround bug where can't select then delete text (until user types something
-			// into the editor)... and/or issue where typing doesn't erase selected text
-			this._cursorToStart = true;
-			html = " ";
-		}
-
-		var font = [ _cs.fontWeight, _cs.fontSize, _cs.fontFamily ].join(" ");
-
-		// line height is tricky - applying a units value will mess things up.
-		// if we can't get a non-units value, bail out.
-		var lineHeight = _cs.lineHeight;
-		if(lineHeight.indexOf("px") >= 0){
-			lineHeight = parseFloat(lineHeight)/parseFloat(_cs.fontSize);
-			// console.debug(lineHeight);
-		}else if(lineHeight.indexOf("em")>=0){
-			lineHeight = parseFloat(lineHeight);
-		}else{
-			// If we can't get a non-units value, just default
-			// it to the CSS spec default of 'normal'.  Seems to
-			// work better, esp on IE, than '1.0'
-			lineHeight = "normal";
-		}
-		var userStyle = "";
-		this.style.replace(/(^|;)(line-|font-?)[^;]+/g, function(match){ userStyle += match.replace(/^;/g,"") + ';'; });
-
-		// need to find any associated label element and update iframe document title
-		var label=dojo.query('label[for="'+this.id+'"]');
-
-		return [
-			this.isLeftToRight() ? "<html><head>" : "<html dir='rtl'><head>",
-			(dojo.isMoz && label.length ? "<title>" + label[0].innerHTML + "</title>" : ""),
-			"<meta http-equiv='Content-Type' content='text/html'>",
-			"<style>",
-			"body,html {",
-			"\tbackground:transparent;",
-			"\tpadding: 1px 0 0 0;",
-			"\tmargin: -1px 0 0 0;", // remove extraneous vertical scrollbar on safari and firefox
-			(dojo.isWebKit?"\twidth: 100%;":""),
-			(dojo.isWebKit?"\theight: 100%;":""),
-			"}",
-			// TODO: left positioning will cause contents to disappear out of view
-			//	   if it gets too wide for the visible area
-			"body{",
-			"\ttop:0px; left:0px; right:0px;",
-			"\tfont:", font, ";",
-				((this.height||dojo.isOpera) ? "" : "position: fixed;"),
-			// FIXME: IE 6 won't understand min-height?
-			"\tmin-height:", this.minHeight, ";",
-			"\tline-height:", lineHeight,
-			"}",
-			"p{ margin: 1em 0; }",
-			(this.height ? // height:auto undoes the height:100%
-				"" : "body,html{overflow-y:hidden;/*for IE*/} body > div {overflow-x:auto;/*FF:horizontal scrollbar*/ overflow-y:hidden;/*safari*/ min-height:"+this.minHeight+";/*safari*/}"
-			),
-			"li > ul:-moz-first-node, li > ol:-moz-first-node{ padding-top: 1.2em; } ",
-			"li{ min-height:1.2em; }",
-			"</style>",
-			this._applyEditingAreaStyleSheets(),
-			"</head><body onload='frameElement._loadFunc(window,document)' style='"+userStyle+"'>", html, "</body></html>"
-		].join(""); // String
-	},
-
-	_applyEditingAreaStyleSheets: function(){
-		// summary:
-		//		apply the specified css files in styleSheets
-		// tags:
-		//		private
-		var files = [];
-		if(this.styleSheets){
-			files = this.styleSheets.split(';');
-			this.styleSheets = '';
-		}
-
-		//empty this.editingAreaStyleSheets here, as it will be filled in addStyleSheet
-		files = files.concat(this.editingAreaStyleSheets);
-		this.editingAreaStyleSheets = [];
-
-		var text='', i=0, url;
-		while((url=files[i++])){
-			var abstring = (new dojo._Url(dojo.global.location, url)).toString();
-			this.editingAreaStyleSheets.push(abstring);
-			text += '<link rel="stylesheet" type="text/css" href="'+abstring+'"/>';
-		}
-		return text;
-	},
-
-	addStyleSheet: function(/*dojo._Url*/ uri){
-		// summary:
-		//		add an external stylesheet for the editing area
-		// uri:
-		//		A dojo.uri.Uri pointing to the url of the external css file
-		var url=uri.toString();
-
-		//if uri is relative, then convert it to absolute so that it can be resolved correctly in iframe
-		if(url.charAt(0) == '.' || (url.charAt(0) != '/' && !uri.host)){
-			url = (new dojo._Url(dojo.global.location, url)).toString();
-		}
-
-		if(dojo.indexOf(this.editingAreaStyleSheets, url) > -1){
-//			console.debug("dijit._editor.RichText.addStyleSheet: Style sheet "+url+" is already applied");
-			return;
-		}
-
-		this.editingAreaStyleSheets.push(url);
-		this.onLoadDeferred.addCallback(dojo.hitch(function(){
-			if(this.document.createStyleSheet){ //IE
-				this.document.createStyleSheet(url);
-			}else{ //other browser
-				var head = this.document.getElementsByTagName("head")[0];
-				var stylesheet = this.document.createElement("link");
-				stylesheet.rel="stylesheet";
-				stylesheet.type="text/css";
-				stylesheet.href=url;
-				head.appendChild(stylesheet);
-			}
-		}));
-	},
-
-	removeStyleSheet: function(/*dojo._Url*/ uri){
-		// summary:
-		//		remove an external stylesheet for the editing area
-		var url=uri.toString();
-		//if uri is relative, then convert it to absolute so that it can be resolved correctly in iframe
-		if(url.charAt(0) == '.' || (url.charAt(0) != '/' && !uri.host)){
-			url = (new dojo._Url(dojo.global.location, url)).toString();
-		}
-		var index = dojo.indexOf(this.editingAreaStyleSheets, url);
-		if(index == -1){
-//			console.debug("dijit._editor.RichText.removeStyleSheet: Style sheet "+url+" has not been applied");
-			return;
-		}
-		delete this.editingAreaStyleSheets[index];
-		dojo.withGlobal(this.window,'query', dojo, ['link:[href="'+url+'"]']).orphan();
-	},
-
-	// disabled: Boolean
-	//		The editor is disabled; the text cannot be changed.
-	disabled: false,
-
-	_mozSettingProps: {'styleWithCSS':false},
-	_setDisabledAttr: function(/*Boolean*/ value){
-		this.disabled = value;
-		if(!this.isLoaded){ return; } // this method requires init to be complete
-		value = !!value;
-		if(dojo.isIE || dojo.isWebKit || dojo.isOpera){
-			var preventIEfocus = dojo.isIE && (this.isLoaded || !this.focusOnLoad);
-			if(preventIEfocus){ this.editNode.unselectable = "on"; }
-			this.editNode.contentEditable = !value;
-			if(preventIEfocus){
-				var _this = this;
-				setTimeout(function(){ _this.editNode.unselectable = "off"; }, 0);
-			}
-		}else{ //moz
-			try{
-				this.document.designMode=(value?'off':'on');
-			}catch(e){ return; } // ! _disabledOK
-			if(!value && this._mozSettingProps){
-				var ps = this._mozSettingProps;
-				for(var n in ps){
-					if(ps.hasOwnProperty(n)){
-						try{
-							this.document.execCommand(n,false,ps[n]);
-						}catch(e2){}
-					}
-				}
-			}
-//			this.document.execCommand('contentReadOnly', false, value);
-//				if(value){
-//					this.blur(); //to remove the blinking caret
-//				}
-		}
-		this._disabledOK = true;
-	},
-
-/* Event handlers
- *****************/
-
-	onLoad: function(/*String*/ html){
-		// summary:
-		//		Handler after the iframe finishes loading.
-		// html: String
-		//		Editor contents should be set to this value
-		// tags:
-		//		protected
-
-		// TODO: rename this to _onLoad, make empty public onLoad() method, deprecate/make protected onLoadDeferred handler?
-
-		if(!this.window.__registeredWindow){
-			this.window.__registeredWindow = true;
-			this._iframeRegHandle = dijit.registerIframe(this.iframe);
-		}
-		if(!dojo.isIE && (this.height || dojo.isMoz)){
-			this.editNode=this.document.body;
-		}else{
-			// there's a wrapper div around the content, see _getIframeDocTxt().
-			this.editNode=this.document.body.firstChild;
-			var _this = this;
-			if(dojo.isIE){ // #4996 IE wants to focus the BODY tag
-				var tabStop = (this.tabStop = dojo.doc.createElement('<div tabIndex=-1>'));
-				this.editingArea.appendChild(tabStop);
-				this.iframe.onfocus = function(){ _this.editNode.setActive(); };
-			}
-		}
-		this.focusNode = this.editNode; // for InlineEditBox
-
-
-		var events = this.events.concat(this.captureEvents);
-		var ap = this.iframe ? this.document : this.editNode;
-		dojo.forEach(events, function(item){
-			this.connect(ap, item.toLowerCase(), item);
-		}, this);
-
-		if(dojo.isIE){ // IE contentEditable
-			this.connect(this.document, "onmousedown", "_onIEMouseDown"); // #4996 fix focus
-
-			// give the node Layout on IE
-			// TODO: this may no longer be needed, since we've reverted IE to using an iframe,
-			// not contentEditable.   Removing it would also probably remove the need for creating
-			// the extra <div> in _getIframeDocTxt()
-			this.editNode.style.zoom = 1.0;
-		}
-
-		if(dojo.isWebKit){
-			//WebKit sometimes doesn't fire right on selections, so the toolbar
-			//doesn't update right.  Therefore, help it out a bit with an additional
-			//listener.  A mouse up will typically indicate a display change, so fire this
-			//and get the toolbar to adapt.  Reference: #9532
-			this._webkitListener = this.connect(this.document, "onmouseup", "onDisplayChanged");
-		}
-
-		if(dojo.isIE){
-			// Try to make sure 'hidden' elements aren't visible in edit mode (like browsers other than IE
-			// do).  See #9103
-			try{
-				this.document.execCommand('RespectVisibilityInDesign', true, null);
-			}catch(e){/* squelch */}
-		}
-
-		this.isLoaded = true;
-
-		this.attr('disabled', this.disabled); // initialize content to editable (or not)
-
-		// Note that setValue() call will only work after isLoaded is set to true (above)
-		this.setValue(html);
-
-		if(this.onLoadDeferred){
-			this.onLoadDeferred.callback(true);
-		}
-
-		this.onDisplayChanged();
-
-		if(this.focusOnLoad){
-			// after the document loads, then set focus after updateInterval expires so that
-			// onNormalizedDisplayChanged has run to avoid input caret issues
-			dojo.addOnLoad(dojo.hitch(this, function(){ setTimeout(dojo.hitch(this, "focus"), this.updateInterval); }));
-		}
-	},
-
-	onKeyDown: function(/* Event */ e){
-		// summary:
-		//		Handler for onkeydown event
-		// tags:
-		//		protected
-
-		// we need this event at the moment to get the events from control keys
-		// such as the backspace. It might be possible to add this to Dojo, so that
-		// keyPress events can be emulated by the keyDown and keyUp detection.
-
-		if(e.keyCode === dojo.keys.TAB && this.isTabIndent ){
-			dojo.stopEvent(e); //prevent tab from moving focus out of editor
-
-			// FIXME: this is a poor-man's indent/outdent. It would be
-			// better if it added 4 " " chars in an undoable way.
-			// Unfortunately pasteHTML does not prove to be undoable
-			if(this.queryCommandEnabled((e.shiftKey ? "outdent" : "indent"))){
-				this.execCommand((e.shiftKey ? "outdent" : "indent"));
-			}
-		}
-		if(dojo.isIE){
-			if(e.keyCode == dojo.keys.TAB && !this.isTabIndent){
-				if(e.shiftKey && !e.ctrlKey && !e.altKey){
-					// focus the BODY so the browser will tab away from it instead
-					this.iframe.focus();
-				}else if(!e.shiftKey && !e.ctrlKey && !e.altKey){
-					// focus the BODY so the browser will tab away from it instead
-					this.tabStop.focus();
-				}
-			}else if(e.keyCode === dojo.keys.BACKSPACE && this.document.selection.type === "Control"){
-				// IE has a bug where if a non-text object is selected in the editor,
-				// hitting backspace would act as if the browser's back button was
-				// clicked instead of deleting the object. see #1069
-				dojo.stopEvent(e);
-				this.execCommand("delete");
-			}else if((65 <= e.keyCode && e.keyCode <= 90) ||
-				(e.keyCode>=37 && e.keyCode<=40) // FIXME: get this from connect() instead!
-			){ //arrow keys
-				e.charCode = e.keyCode;
-				this.onKeyPress(e);
-			}
-		}
-		return true;
-	},
-
-	onKeyUp: function(e){
-		// summary:
-		//		Handler for onkeyup event
-		// tags:
-		//      callback
-		return;
-	},
-
-	setDisabled: function(/*Boolean*/ disabled){
-		// summary:
-		//		Deprecated, use attr('disabled', ...) instead.
-		// tags:
-		//		deprecated
-		dojo.deprecated('dijit.Editor::setDisabled is deprecated','use dijit.Editor::attr("disabled",boolean) instead', 2.0);
-		this.attr('disabled',disabled);
-	},
-	_setValueAttr: function(/*String*/ value){
-		// summary:
-		//      Registers that attr("value", foo) should call setValue(foo)
-		this.setValue(value);
-	},
-	_setDisableSpellCheckAttr: function(/*Boolean*/ disabled){
-		if(this.document){
-			dojo.attr(this.document.body, "spellcheck", !disabled);
-		}else{
-			// try again after the editor is finished loading
-			this.onLoadDeferred.addCallback(dojo.hitch(this, function(){
-				dojo.attr(this.document.body, "spellcheck", !disabled);
-			}));
-		}
-		this.disableSpellCheck = disabled;
-	},
-
-	onKeyPress: function(e){
-		// summary:
-		//		Handle the various key events
-		// tags:
-		//		protected
-
-		var c = (e.keyChar && e.keyChar.toLowerCase()) || e.keyCode,
-			handlers = this._keyHandlers[c],
-			args = arguments;
-
-		if(handlers && !e.altKey){
-			dojo.some(handlers, function(h){
-				if(!(h.shift ^ e.shiftKey) && !(h.ctrl ^ e.ctrlKey)){
-					if(!h.handler.apply(this, args)){
-						e.preventDefault();
-					}
-					return true;
-				}
-			}, this);
-		}
-
-		// function call after the character has been inserted
-		if(!this._onKeyHitch){
-			this._onKeyHitch = dojo.hitch(this, "onKeyPressed");
-		}
-		setTimeout(this._onKeyHitch, 1);
-		return true;
-	},
-
-	addKeyHandler: function(/*String*/ key, /*Boolean*/ ctrl, /*Boolean*/ shift, /*Function*/ handler){
-		// summary:
-		//		Add a handler for a keyboard shortcut
-		// description:
-		//		The key argument should be in lowercase if it is a letter character
-		// tags:
-		//		protected
-		if(!dojo.isArray(this._keyHandlers[key])){
-			this._keyHandlers[key] = [];
-		}
-		//TODO: would be nice to make this a hash instead of an array for quick lookups
-		this._keyHandlers[key].push({
-			shift: shift || false,
-			ctrl: ctrl || false,
-			handler: handler
-		});
-	},
-
-	onKeyPressed: function(){
-		// summary:
-		//		Handler for after the user has pressed a key, and the display has been updated.
-		//		(Runs on a timer so that it runs after the display is updated)
-		// tags:
-		//		private
-		this.onDisplayChanged(/*e*/); // can't pass in e
-	},
-
-	onClick: function(/*Event*/ e){
-		// summary:
-		//		Handler for when the user clicks.
-		// tags:
-		//		private
-
-		// console.info('onClick',this._tryDesignModeOn);
-		this.onDisplayChanged(e);
-	},
-
-	_onIEMouseDown: function(/*Event*/ e){
-		// summary:
-		//		IE only to prevent 2 clicks to focus
-		// tags:
-		//		protected
-
-		if(!this._focused && !this.disabled){
-			this.focus();
-		}
-	},
-
-	_onBlur: function(e){
-		// summary:
-		//		Called from focus manager when focus has moved away from this editor
-		// tags:
-		//		protected
-
-		// console.info('_onBlur')
-
-		this.inherited(arguments);
-		var _c=this.getValue(true);
-
-		if(_c!=this.savedContent){
-			this.onChange(_c);
-			this.savedContent=_c;
-		}
-	},
-	_onFocus: function(/*Event*/ e){
-		// summary:
-		//		Called from focus manager when focus has moved into this editor
-		// tags:
-		//		protected
-
-		// console.info('_onFocus')
-		if(!this.disabled){
-			if(!this._disabledOK){
-				this.attr('disabled', false);
-			}
-			this.inherited(arguments);
-		}
-	},
-
-	// TODO: why is this needed - should we deprecate this ?
-	blur: function(){
-		// summary:
-		//		Remove focus from this instance.
-		// tags:
-		//		deprecated
-		if(!dojo.isIE && this.window.document.documentElement && this.window.document.documentElement.focus){
-			this.window.document.documentElement.focus();
-		}else if(dojo.doc.body.focus){
-			dojo.doc.body.focus();
-		}
-	},
-
-	focus: function(){
-		// summary:
-		//		Move focus to this editor
-		if(!dojo.isIE){
-			dijit.focus(this.iframe);
-			if(this._cursorToStart){ 
-				delete this._cursorToStart;
-				if(this.editNode.childNodes && 
-					this.editNode.childNodes.length === 1 && 
-					this.editNode.innerHTML === " "){
-						this.placeCursorAtStart();
-				}
-			}
-		}else if(this.editNode && this.editNode.focus){
-			// editNode may be hidden in display:none div, lets just punt in this case
-			//this.editNode.focus(); -> causes IE to scroll always (strict and quirks mode) to the top the Iframe
-			// if we fire the event manually and let the browser handle the focusing, the latest
-			// cursor position is focused like in FF
-			this.iframe.fireEvent('onfocus', document.createEventObject()); // createEventObject only in IE
-		//	}else{
-		// TODO: should we throw here?
-		// console.debug("Have no idea how to focus into the editor!");
-		}
-	},
-
-	// _lastUpdate: 0,
-	updateInterval: 200,
-	_updateTimer: null,
-	onDisplayChanged: function(/*Event*/ e){
-		// summary:
-		//		This event will be fired everytime the display context
-		//		changes and the result needs to be reflected in the UI.
-		// description:
-		//		If you don't want to have update too often,
-		//		onNormalizedDisplayChanged should be used instead
-		// tags:
-		//		private
-
-		// var _t=new Date();
-		if(this._updateTimer){
-			clearTimeout(this._updateTimer);
-		}
-		if(!this._updateHandler){
-			this._updateHandler = dojo.hitch(this,"onNormalizedDisplayChanged");
-		}
-		this._updateTimer = setTimeout(this._updateHandler, this.updateInterval);
-	},
-	onNormalizedDisplayChanged: function(){
-		// summary:
-		//		This event is fired every updateInterval ms or more
-		// description:
-		//		If something needs to happen immediately after a
-		//		user change, please use onDisplayChanged instead.
-		// tags:
-		//		private
-		delete this._updateTimer;
-	},
-	onChange: function(newContent){
-		// summary:
-		//		This is fired if and only if the editor loses focus and
-		//		the content is changed.
-	},
-	_normalizeCommand: function(/*String*/ cmd, /*Anything?*/argument){
-		// summary:
-		//		Used as the advice function by dojo.connect to map our
-		//		normalized set of commands to those supported by the target
-		//		browser.
-		// tags:
-		//		private
-
-		var command = cmd.toLowerCase();
-		if(command == "formatblock"){
-			if(dojo.isSafari && argument === undefined){ command = "heading"; }
-		}else if(command == "hilitecolor" && !dojo.isMoz){
-			command = "backcolor";
-		}
-
-		return command;
-	},
-
-	_qcaCache: {},
-	queryCommandAvailable: function(/*String*/ command){
-		// summary:
-		//		Tests whether a command is supported by the host. Clients
-		//		SHOULD check whether a command is supported before attempting
-		//		to use it, behaviour for unsupported commands is undefined.
-		// command:
-		//		The command to test for
-		// tags:
-		//		private
-
-		// memoizing version. See _queryCommandAvailable for computing version
-		var ca = this._qcaCache[command];
-		if(ca !== undefined){ return ca; }
-		return (this._qcaCache[command] = this._queryCommandAvailable(command));
-	},
-
-	_queryCommandAvailable: function(/*String*/ command){
-		// summary:
-		//		See queryCommandAvailable().
-		// tags:
-		//		private
-
-		var ie = 1;
-		var mozilla = 1 << 1;
-		var webkit = 1 << 2;
-		var opera = 1 << 3;
-		var webkit420 = 1 << 4;
-
-		function isSupportedBy(browsers){
-			return {
-				ie: Boolean(browsers & ie),
-				mozilla: Boolean(browsers & mozilla),
-				webkit: Boolean(browsers & webkit),
-				webkit420: Boolean(browsers & webkit420),
-				opera: Boolean(browsers & opera)
-			};
-		}
-
-		var supportedBy = null;
-
-		switch(command.toLowerCase()){
-			case "bold": case "italic": case "underline":
-			case "subscript": case "superscript":
-			case "fontname": case "fontsize":
-			case "forecolor": case "hilitecolor":
-			case "justifycenter": case "justifyfull": case "justifyleft":
-			case "justifyright": case "delete": case "selectall": case "toggledir":
-				supportedBy = isSupportedBy(mozilla | ie | webkit | opera);
-				break;
-
-			case "createlink": case "unlink": case "removeformat":
-			case "inserthorizontalrule": case "insertimage":
-			case "insertorderedlist": case "insertunorderedlist":
-			case "indent": case "outdent": case "formatblock":
-			case "inserthtml": case "undo": case "redo": case "strikethrough": case "tabindent":
-				supportedBy = isSupportedBy(mozilla | ie | opera | webkit420);
-				break;
-
-			case "blockdirltr": case "blockdirrtl":
-			case "dirltr": case "dirrtl":
-			case "inlinedirltr": case "inlinedirrtl":
-				supportedBy = isSupportedBy(ie);
-				break;
-			case "cut": case "copy": case "paste":
-				supportedBy = isSupportedBy( ie | mozilla | webkit420);
-				break;
-
-			case "inserttable":
-				supportedBy = isSupportedBy(mozilla | ie);
-				break;
-
-			case "insertcell": case "insertcol": case "insertrow":
-			case "deletecells": case "deletecols": case "deleterows":
-			case "mergecells": case "splitcell":
-				supportedBy = isSupportedBy(ie | mozilla);
-				break;
-
-			default: return false;
-		}
-
-		return (dojo.isIE && supportedBy.ie) ||
-			(dojo.isMoz && supportedBy.mozilla) ||
-			(dojo.isWebKit && supportedBy.webkit) ||
-			(dojo.isWebKit > 420 && supportedBy.webkit420) ||
-			(dojo.isOpera && supportedBy.opera);	// Boolean return true if the command is supported, false otherwise
-	},
-
-	execCommand: function(/*String*/ command, argument){
-		// summary:
-		//		Executes a command in the Rich Text area
-		// command:
-		//		The command to execute
-		// argument:
-		//		An optional argument to the command
-		// tags:
-		//		protected
-		var returnValue;
-
-		//focus() is required for IE to work
-		//In addition, focus() makes sure after the execution of
-		//the command, the editor receives the focus as expected
-		this.focus();
-
-		command = this._normalizeCommand(command, argument);
-
-
-		if(argument !== undefined){
-			if(command == "heading"){
-				throw new Error("unimplemented");
-			}else if((command == "formatblock") && dojo.isIE){
-				argument = '<'+argument+'>';
-			}
-		}
-
-		//Check to see if we have any over-rides for commands, they will be functions on this
-		//widget of the form _commandImpl.  If we don't, fall through to the basic native
-		//exec command of the browser.
-		var implFunc = "_" + command + "Impl";
-		if(this[implFunc]){
-			returnValue = this[implFunc](argument);
-		}else{
-			argument = arguments.length > 1 ? argument : null;
-			if(argument || command!="createlink"){
-				returnValue = this.document.execCommand(command, false, argument);
-			}
-		}
-
-		this.onDisplayChanged();
-		return returnValue;
-	},
-
-	queryCommandEnabled: function(/*String*/ command){
-		// summary:
-		//		Check whether a command is enabled or not.
-		// tags:
-		//		protected
-		if(this.disabled || !this._disabledOK){ return false; }
-		command = this._normalizeCommand(command);
-		if(dojo.isMoz || dojo.isWebKit){
-			if(command == "unlink"){ // mozilla returns true always
-				// console.debug(this._sCall("hasAncestorElement", ['a']));
-				return this._sCall("hasAncestorElement", ["a"]);
-			}else if(command == "inserttable"){
-				return true;
-			}
-		}
-		//see #4109
-		if(dojo.isWebKit){
-			if(command == "copy"){
-				command = "cut";
-			}else if(command == "paste"){
-				return true;
-			}
-		}
-
-		var elem = dojo.isIE ? this.document.selection.createRange() : this.document;
-		try{
-			return elem.queryCommandEnabled(command);
-		}catch(e){
-			//Squelch, occurs if editor is hidden on FF 3 (and maybe others.)
-			return false;
-		}
-
-	},
-
-	queryCommandState: function(command){
-		// summary:
-		//		Check the state of a given command and returns true or false.
-		// tags:
-		//		protected
-
-		if(this.disabled || !this._disabledOK){ return false; }
-		command = this._normalizeCommand(command);
-		try{
-			return this.document.queryCommandState(command);
-		}catch(e){
-			//Squelch, occurs if editor is hidden on FF 3 (and maybe others.)
-			return false;
-		}
-	},
-
-	queryCommandValue: function(command){
-		// summary:
-		//		Check the value of a given command. This matters most for
-		//		custom selections and complex values like font value setting.
-		// tags:
-		//		protected
-
-		if(this.disabled || !this._disabledOK){ return false; }
-		var r;
-		command = this._normalizeCommand(command);
-		if(dojo.isIE && command == "formatblock"){
-			r = this._native2LocalFormatNames[this.document.queryCommandValue(command)];
-		}else if(dojo.isMoz && command === "hilitecolor"){
-			var oldValue;
-			try{
-				oldValue = this.document.queryCommandValue("styleWithCSS");
-			}catch(e){
-				oldValue = false;
-			}
-			this.document.execCommand("styleWithCSS", false, true);
-			r = this.document.queryCommandValue(command);
-			this.document.execCommand("styleWithCSS", false, oldValue);
-		}else{
-			r = this.document.queryCommandValue(command);
-		}
-		return r;
-	},
-
-	// Misc.
-
-	_sCall: function(name, args){
-		// summary:
-		//		Run the named method of dijit._editor.selection over the
-		//		current editor instance's window, with the passed args.
-		// tags:
-		//		private
-		return dojo.withGlobal(this.window, name, dijit._editor.selection, args);
-	},
-
-	// FIXME: this is a TON of code duplication. Why?
-
-	placeCursorAtStart: function(){
-		// summary:
-		//		Place the cursor at the start of the editing area.
-		// tags:
-		//		private
-
-		this.focus();
-
-		//see comments in placeCursorAtEnd
-		var isvalid=false;
-		if(dojo.isMoz){
-			// TODO:  Is this branch even necessary?
-			var first=this.editNode.firstChild;
-			while(first){
-				if(first.nodeType == 3){
-					if(first.nodeValue.replace(/^\s+|\s+$/g, "").length>0){
-						isvalid=true;
-						this._sCall("selectElement", [ first ]);
-						break;
-					}
-				}else if(first.nodeType == 1){
-					isvalid=true;
-					var tg = first.tagName ? first.tagName.toLowerCase() : "";
-					// Collapse before childless tags.
-					if(/br|input|img|base|meta|area|basefont|hr|link/.test(tg)){
-						this._sCall("selectElement", [ first ]);
-					}else{
-						// Collapse inside tags with children.
-						this._sCall("selectElementChildren", [ first ]);
-					}
-					break;
-				}
-				first = first.nextSibling;
-			}
-		}else{
-			isvalid=true;
-			this._sCall("selectElementChildren", [ this.editNode ]);
-		}
-		if(isvalid){
-			this._sCall("collapse", [ true ]);
-		}
-	},
-
-	placeCursorAtEnd: function(){
-		// summary:
-		//		Place the cursor at the end of the editing area.
-		// tags:
-		//		private
-
-		this.focus();
-
-		//In mozilla, if last child is not a text node, we have to use
-		// selectElementChildren on this.editNode.lastChild otherwise the
-		// cursor would be placed at the end of the closing tag of
-		//this.editNode.lastChild
-		var isvalid=false;
-		if(dojo.isMoz){
-			var last=this.editNode.lastChild;
-			while(last){
-				if(last.nodeType == 3){
-					if(last.nodeValue.replace(/^\s+|\s+$/g, "").length>0){
-						isvalid=true;
-						this._sCall("selectElement", [ last ]);
-						break;
-					}
-				}else if(last.nodeType == 1){
-					isvalid=true;
-					if(last.lastChild){
-						this._sCall("selectElement", [ last.lastChild ]);
-					}else{
-						this._sCall("selectElement", [ last ]);
-					}
-					break;
-				}
-				last = last.previousSibling;
-			}
-		}else{
-			isvalid=true;
-			this._sCall("selectElementChildren", [ this.editNode ]);
-		}
-		if(isvalid){
-			this._sCall("collapse", [ false ]);
-		}
-	},
-
-	getValue: function(/*Boolean?*/ nonDestructive){
-		// summary:
-		//		Return the current content of the editing area (post filters
-		//		are applied).  Users should call attr('value') instead.
-		//	nonDestructive:
-		//		defaults to false. Should the post-filtering be run over a copy
-		//		of the live DOM? Most users should pass "true" here unless they
-		//		*really* know that none of the installed filters are going to
-		//		mess up the editing session.
-		// tags:
-		//		private
-		if(this.textarea){
-			if(this.isClosed || !this.isLoaded){
-				return this.textarea.value;
-			}
-		}
-
-		return this._postFilterContent(null, nonDestructive);
-	},
-	_getValueAttr: function(){
-		// summary:
-		//		Hook to make attr("value") work
-		return this.getValue(true);
-	},
-
-	setValue: function(/*String*/ html){
-		// summary:
-		//		This function sets the content. No undo history is preserved.
-		//		Users should use attr('value', ...) instead.
-		// tags:
-		//		deprecated
-
-		// TODO: remove this and getValue() for 2.0, and move code to _setValueAttr()
-
-		if(!this.isLoaded){
-			// try again after the editor is finished loading
-			this.onLoadDeferred.addCallback(dojo.hitch(this, function(){
-				this.setValue(html);
-			}));
-			return;
-		}
-		if(this.textarea && (this.isClosed || !this.isLoaded)){
-			this.textarea.value=html;
-		}else{
-			html = this._preFilterContent(html);
-			var node = this.isClosed ? this.domNode : this.editNode;
-
-			// Use   to avoid webkit problems where editor is disabled until the user clicks it
-			if(!html && dojo.isWebKit){
-				this._cursorToStart = true;
-				html = " ";
-			}
-			node.innerHTML = html;
-			this._preDomFilterContent(node);
-		}
-		this.onDisplayChanged();
-	},
-
-	replaceValue: function(/*String*/ html){
-		// summary:
-		//		This function set the content while trying to maintain the undo stack
-		//		(now only works fine with Moz, this is identical to setValue in all
-		//		other browsers)
-		// tags:
-		//		protected
-
-		if(this.isClosed){
-			this.setValue(html);
-		}else if(this.window && this.window.getSelection && !dojo.isMoz){ // Safari
-			// look ma! it's a totally f'd browser!
-			this.setValue(html);
-		}else if(this.window && this.window.getSelection){ // Moz
-			html = this._preFilterContent(html);
-			this.execCommand("selectall");
-			if(!html){ 
-				this._cursorToStart = true;
-				html = " "; 
-			}
-			this.execCommand("inserthtml", html);
-			this._preDomFilterContent(this.editNode);
-		}else if(this.document && this.document.selection){//IE
-			//In IE, when the first element is not a text node, say
-			//an <a> tag, when replacing the content of the editing
-			//area, the <a> tag will be around all the content
-			//so for now, use setValue for IE too
-			this.setValue(html);
-		}
-	},
-
-	_preFilterContent: function(/*String*/ html){
-		// summary:
-		//		Filter the input before setting the content of the editing
-		//		area. DOM pre-filtering may happen after this
-		//		string-based filtering takes place but as of 1.2, this is not
-		//		guaranteed for operations such as the inserthtml command.
-		// tags:
-		//		private
-
-		var ec = html;
-		dojo.forEach(this.contentPreFilters, function(ef){ if(ef){ ec = ef(ec); } });
-		return ec;
-	},
-	_preDomFilterContent: function(/*DomNode*/ dom){
-		// summary:
-		//		filter the input's live DOM. All filter operations should be
-		//		considered to be "live" and operating on the DOM that the user
-		//		will be interacting with in their editing session.
-		// tags:
-		//		private
-		dom = dom || this.editNode;
-		dojo.forEach(this.contentDomPreFilters, function(ef){
-			if(ef && dojo.isFunction(ef)){
-				ef(dom);
-			}
-		}, this);
-	},
-
-	_postFilterContent: function(
-		/*DomNode|DomNode[]|String?*/ dom,
-		/*Boolean?*/ nonDestructive){
-		// summary:
-		//		filter the output after getting the content of the editing area
-		//
-		// description:
-		//		post-filtering allows plug-ins and users to specify any number
-		//		of transforms over the editor's content, enabling many common
-		//		use-cases such as transforming absolute to relative URLs (and
-		//		vice-versa), ensuring conformance with a particular DTD, etc.
-		//		The filters are registered in the contentDomPostFilters and
-		//		contentPostFilters arrays. Each item in the
-		//		contentDomPostFilters array is a function which takes a DOM
-		//		Node or array of nodes as its only argument and returns the
-		//		same. It is then passed down the chain for further filtering.
-		//		The contentPostFilters array behaves the same way, except each
-		//		member operates on strings. Together, the DOM and string-based
-		//		filtering allow the full range of post-processing that should
-		//		be necessaray to enable even the most agressive of post-editing
-		//		conversions to take place.
-		//
-		//		If nonDestructive is set to "true", the nodes are cloned before
-		//		filtering proceeds to avoid potentially destructive transforms
-		//		to the content which may still needed to be edited further.
-		//		Once DOM filtering has taken place, the serialized version of
-		//		the DOM which is passed is run through each of the
-		//		contentPostFilters functions.
-		//
-		//	dom:
-		//		a node, set of nodes, which to filter using each of the current
-		//		members of the contentDomPostFilters and contentPostFilters arrays.
-		//
-		//	nonDestructive:
-		//		defaults to "false". If true, ensures that filtering happens on
-		//		a clone of the passed-in content and not the actual node
-		//		itself.
-		//
-		// tags:
-		//		private
-
-		var ec;
-		if(!dojo.isString(dom)){
-			dom = dom || this.editNode;
-			if(this.contentDomPostFilters.length){
-				if(nonDestructive){
-					dom = dojo.clone(dom);
-				}
-				dojo.forEach(this.contentDomPostFilters, function(ef){
-					dom = ef(dom);
-				});
-			}
-			ec = dijit._editor.getChildrenHtml(dom);
-		}else{
-			ec = dom;
-		}
-
-		if(!dojo.trim(ec.replace(/^\xA0\xA0*/, '').replace(/\xA0\xA0*$/, '')).length){
-			ec = "";
-		}
-
-		//	if(dojo.isIE){
-		//		//removing appended <P> </P> for IE
-		//		ec = ec.replace(/(?:<p> </p>[\n\r]*)+$/i,"");
-		//	}
-		dojo.forEach(this.contentPostFilters, function(ef){
-			ec = ef(ec);
-		});
-
-		return ec;
-	},
-
-	_saveContent: function(/*Event*/ e){
-		// summary:
-		//		Saves the content in an onunload event if the editor has not been closed
-		// tags:
-		//		private
-
-		var saveTextarea = dojo.byId(dijit._scopeName + "._editor.RichText.savedContent");
-		if(saveTextarea.value){
-			saveTextarea.value += this._SEPARATOR;
-		}
-		saveTextarea.value += this.name + ":" + this.getValue(true);
-	},
-
-
-	escapeXml: function(/*String*/ str, /*Boolean*/ noSingleQuotes){
-		// summary:
-		//		Adds escape sequences for special characters in XML: &<>"'
-		//		Optionally skips escapes for single quotes
-		// tags:
-		//		private
-
-		str = str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """);
-		if(!noSingleQuotes){
-			str = str.replace(/'/gm, "'");
-		}
-		return str; // string
-	},
-
-	getNodeHtml: function(/* DomNode */ node){
-		// summary:
-		//		Deprecated.   Use dijit._editor._getNodeHtml() instead.
-		// tags:
-		//		deprecated
-		dojo.deprecated('dijit.Editor::getNodeHtml is deprecated','use dijit._editor.getNodeHtml instead', 2);
-		return dijit._editor.getNodeHtml(node); // String
-	},
-
-	getNodeChildrenHtml: function(/* DomNode */ dom){
-		// summary:
-		//		Deprecated.   Use dijit._editor.getChildrenHtml() instead.
-		// tags:
-		//		deprecated
-		dojo.deprecated('dijit.Editor::getNodeChildrenHtml is deprecated','use dijit._editor.getChildrenHtml instead', 2);
-		return dijit._editor.getChildrenHtml(dom);
-	},
-
-	close: function(/*Boolean*/ save){
-		// summary:
-		//		Kills the editor and optionally writes back the modified contents to the
-		//		element from which it originated.
-		// save:
-		//		Whether or not to save the changes. If false, the changes are discarded.
-		// tags:
-		//		private
-
-		if(this.isClosed){return false; }
-
-		if(!arguments.length){ save = true; }
-		this._content = this.getValue();
-		var changed = (this.savedContent != this._content);
-
-		// line height is squashed for iframes
-		// FIXME: why was this here? if (this.iframe){ this.domNode.style.lineHeight = null; }
-
-		if(this.interval){ clearInterval(this.interval); }
-
-		if(this._webkitListener){
-			//Cleaup of WebKit fix: #9532
-			this.disconnect(this._webkitListener);
-			delete this._webkitListener;
-		}
-
-		// Guard against memory leaks on IE (see #9268)
-		if(dojo.isIE){
-			 this.iframe.onfocus = null;
-		}
-		this.iframe._loadFunc = null;
-
-		if(this._iframeRegHandle){
-			dijit.unregisterIframe(this._iframeRegHandle);
-			delete this._iframeRegHandle;
-		}
-
-		if(this.textarea){
-			var s = this.textarea.style;
-			s.position = "";
-			s.left = s.top = "";
-			if(dojo.isIE){
-				s.overflow = this.__overflow;
-				this.__overflow = null;
-			}
-			this.textarea.value = save ? this._content : this.savedContent;
-			dojo.destroy(this.domNode);
-			this.domNode = this.textarea;
-		}else{
-			// if(save){
-			// why we treat moz differently? comment out to fix #1061
-			//		if(dojo.isMoz){
-			//			var nc = dojo.doc.createElement("span");
-			//			this.domNode.appendChild(nc);
-			//			nc.innerHTML = this.editNode.innerHTML;
-			//		}else{
-			//			this.domNode.innerHTML = this._content;
-			//		}
-			// }
-
-			// Note that this destroys the iframe
-			this.domNode.innerHTML = save ? this._content : this.savedContent;
-		}
-		delete this.iframe;
-
-		dojo.removeClass(this.domNode, "RichTextEditable");
-		this.isClosed = true;
-		this.isLoaded = false;
-
-		delete this.editNode;
-		delete this.focusNode;
-
-		if(this.window && this.window._frameElement){
-			this.window._frameElement = null;
-		}
-
-		this.window = null;
-		this.document = null;
-		this.editingArea = null;
-		this.editorObject = null;
-
-		return changed; // Boolean: whether the content has been modified
-	},
-
-	destroy: function(){
-		if(!this.isClosed){ this.close(false); }
-		this.inherited(arguments);
-	},
-
-	_removeMozBogus: function(/* String */ html){
-		// summary:
-		//		Post filter to remove unwanted HTML attributes generated by mozilla
-		// tags:
-		//		private
-		return html.replace(/\stype="_moz"/gi, '').replace(/\s_moz_dirty=""/gi, '').replace(/_moz_resizing="(true|false)"/gi,''); // String
-	},
-	_removeWebkitBogus: function(/* String */ html){
-		// summary:
-		//		Post filter to remove unwanted HTML attributes generated by webkit
-		// tags:
-		//		private
-		html = html.replace(/\sclass="webkit-block-placeholder"/gi, '');
-		html = html.replace(/\sclass="apple-style-span"/gi, '');
-		return html; // String
-	},
-	_normalizeFontStyle: function(/* String */ html){
-		// summary:
-		//		Convert <strong> and <em> to <b> and <i>.
-		// description:
-		//		Moz can not handle strong/em tags correctly, so to help
-		//		mozilla and also to normalize output, convert them to <b> and <i>.
-		//
-		//		Note the IE generates <strong> and <em> rather than <b> and <i>
-		// tags:
-		//		private
-		return html.replace(/<(\/)?strong([ \>])/gi, '<$1b$2')
-			.replace(/<(\/)?em([ \>])/gi, '<$1i$2' ); // String
-	},
-
-	_preFixUrlAttributes: function(/* String */ html){
-		// summary:
-		//		Pre-filter to do fixing to href attributes on <a> and <img> tags
-		// tags:
-		//		private
-		return html.replace(/(?:(<a(?=\s).*?\shref=)("|')(.*?)\2)|(?:(<a\s.*?href=)([^"'][^ >]+))/gi,
-				'$1$4$2$3$5$2 _djrealurl=$2$3$5$2')
-			.replace(/(?:(<img(?=\s).*?\ssrc=)("|')(.*?)\2)|(?:(<img\s.*?src=)([^"'][^ >]+))/gi,
-				'$1$4$2$3$5$2 _djrealurl=$2$3$5$2'); // String
-	},
-
-	/*****************************************************************************
-		The following functions implement HTML manipulation commands for various
-		browser/contentEditable implementations.  The goal of them is to enforce
-		standard behaviors of them.
-	******************************************************************************/
-
-	_inserthorizontalruleImpl: function(argument){
-		// summary:
-		//		This function implements the insertion of HTML <HR> tags.
-		//		into a point on the page.  IE doesn't to it right, so
-		//		we have to use an alternate form
-		// argument:
-		//		arguments to the exec command, if any.
-		// tags:
-		//		protected
-		if(dojo.isIE){
-			return this._inserthtmlImpl("<hr>");
-		}
-		return this.document.execCommand("inserthorizontalrule", false, argument);
-	},
-
-	_unlinkImpl: function(argument){
-		// summary:
-		//		This function implements the unlink of an <a> tag.
-		// argument:
-		//		arguments to the exec command, if any.
-		// tags:
-		//		protected
-		if((this.queryCommandEnabled("unlink")) && (dojo.isMoz || dojo.isWebKit)){
-			var a = this._sCall("getAncestorElement", [ "a" ]);
-			this._sCall("selectElement", [ a ]);
-			return this.document.execCommand("unlink", false, null);
-		}
-		return this.document.execCommand("unlink", false, argument);
-	},
-
-	_hilitecolorImpl: function(argument){
-		// summary:
-		//		This function implements the hilitecolor command
-		// argument:
-		//		arguments to the exec command, if any.
-		// tags:
-		//		protected
-		var returnValue;
-		if(dojo.isMoz){
-			// mozilla doesn't support hilitecolor properly when useCSS is
-			// set to false (bugzilla #279330)
-			this.document.execCommand("styleWithCSS", false, true);
-			returnValue = this.document.execCommand("hilitecolor", false, argument);
-			this.document.execCommand("styleWithCSS", false, false);
-		}else{
-			returnValue = this.document.execCommand("hilitecolor", false, argument);
-		}
-		return returnValue;
-	},
-
-	_backcolorImpl: function(argument){
-		// summary:
-		//		This function implements the backcolor command
-		// argument:
-		//		arguments to the exec command, if any.
-		// tags:
-		//		protected
-		if(dojo.isIE){
-			// Tested under IE 6 XP2, no problem here, comment out
-			// IE weirdly collapses ranges when we exec these commands, so prevent it
-			//	var tr = this.document.selection.createRange();
-			argument = argument ? argument : null;
-		}
-		return this.document.execCommand("backcolor", false, argument);
-	},
-
-	_forecolorImpl: function(argument){
-		// summary:
-		//		This function implements the forecolor command
-		// argument:
-		//		arguments to the exec command, if any.
-		// tags:
-		//		protected
-		if(dojo.isIE){
-			// Tested under IE 6 XP2, no problem here, comment out
-			// IE weirdly collapses ranges when we exec these commands, so prevent it
-			//	var tr = this.document.selection.createRange();
-			argument = argument? argument : null;
-		}
-		return this.document.execCommand("forecolor", false, argument);
-	},
-
-	_inserthtmlImpl: function(argument){
-		// summary:
-		//		This function implements the insertion of HTML content into
-		//		a point on the page.
-		// argument:
-		//		The content to insert, if any.
-		// tags:
-		//		protected
-		argument = this._preFilterContent(argument);
-		var rv = true;
-		if(dojo.isIE){
-			var insertRange = this.document.selection.createRange();
-			if(this.document.selection.type.toUpperCase() == 'CONTROL'){
-				var n=insertRange.item(0);
-				while(insertRange.length){
-					insertRange.remove(insertRange.item(0));
-				}
-				n.outerHTML=argument;
-			}else{
-				insertRange.pasteHTML(argument);
-			}
-			insertRange.select();
-			//insertRange.collapse(true);
-		}else if(dojo.isMoz && !argument.length){
-			//mozilla can not inserthtml an empty html to delete current selection
-			//so we delete the selection instead in this case
-			this._sCall("remove"); // FIXME
-		}else{
-			rv = this.document.execCommand("inserthtml", false, argument);
-		}
-		return rv;
-	}
-});
-
-}
-
-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(/*dijit._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
-			var child = this._getFirstFocusableChild();
-			if(child){ // edge case: Menu could be empty or hidden
-				this.focusChild(child);
-			}
-		},
-
-		focusNext: function(){
-			// summary:
-			//		Focus the next widget
-			// tags:
-			//		protected
-			var child = this._getNextFocusableChild(this.focusedChild, 1);
-			this.focusChild(child);
-		},
-
-		focusPrev: function(){
-			// summary:
-			//		Focus the last focusable node in the previous widget
-			//		(ex: go to the ComboButton icon section rather than button section)
-			// tags:
-			//		protected
-			var child = this._getNextFocusableChild(this.focusedChild, -1);
-			this.focusChild(child, true);
-		},
-
-		focusChild: function(/*dijit._Widget*/ widget, /*Boolean*/ last){
-			// summary:
-			//		Focus widget.
-			// widget:
-			//		Reference to container's child widget
-			// last:
-			//		If true and if widget has multiple focusable nodes, focus the
-			//		last one instead of the first one
-			// tags:
-			//		protected
-			
-			if(this.focusedChild && widget !== this.focusedChild){
-				this._onChildBlur(this.focusedChild);
-			}
-			widget.focus(last ? "end" : "start");
-			this.focusedChild = widget;
-		},
-
-		_startupChild: function(/*dijit._Widget*/ widget){
-			// summary:
-			//		Setup for each child widget
-			// description:
-			//		Sets tabIndex=-1 on each child, so that the tab key will 
-			//		leave the container rather than visiting each child.
-			// tags:
-			//		private
-			
-			widget.attr("tabIndex", "-1");
-			
-			this.connect(widget, "_onFocus", function(){
-				// Set valid tabIndex so tabbing away from widget goes to right place, see #10272
-				widget.attr("tabIndex", this.tabIndex);
-			});
-			this.connect(widget, "_onBlur", function(){
-				widget.attr("tabIndex", "-1");
-			});
-		},
-
-		_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 set the container's tabIndex to -1,
-			// (don't remove as that breaks Safari 4)
-			// so that tab or shift-tab will go to the fields after/before
-			// the container, rather than the container itself
-			dojo.attr(this.domNode, "tabIndex", "-1");
-		},
-
-		_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);
-			}
-			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);
-			}
-		},
-
-		_onChildBlur: function(/*dijit._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);	// dijit._Widget
-		},
-
-		_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;	// dijit._Widget
-				}
-				child = this._getSiblingOfChild(child, dir);
-			}
-			// no focusable child found
-			return null;	// dijit._Widget
-		}
-	}
-);
-
-}
-
-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._HasDropDown"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._HasDropDown"] = true;
-dojo.provide("dijit._HasDropDown");
-
-
-
-
-dojo.declare("dijit._HasDropDown",
-	null,
-	{
-		// summary:
-		//		Mixin for widgets that need drop down ability.
-
-		// _buttonNode: [protected] DomNode
-		//		The button/icon/node to click to display the drop down.
-		//		Can be set via a dojoAttachPoint assignment.
-		//		If missing, then either focusNode or domNode (if focusNode is also missing) will be used.
-		_buttonNode: null,
-
-		// _arrowWrapperNode: [protected] DomNode
-		//		Will set CSS class dijitUpArrow, dijitDownArrow, dijitRightArrow etc. on this node depending
-		//		on where the drop down is set to be positioned.
-		//		Can be set via a dojoAttachPoint assignment.
-		//		If missing, then _buttonNode will be used.
-		_arrowWrapperNode: null,
-
-		// _popupStateNode: [protected] DomNode
-		//		The node to set the popupActive class on.
-		//		Can be set via a dojoAttachPoint assignment.
-		//		If missing, then focusNode or _buttonNode (if focusNode is missing) will be used.
-		_popupStateNode: null,
-
-		// _aroundNode: [protected] DomNode
-		//		The node to display the popup around.
-		//		Can be set via a dojoAttachPoint assignment.
-		//		If missing, then domNode will be used.
-		_aroundNode: null,
-
-		// dropDown: [protected] Widget
-		//		The widget to display as a popup.  This widget *must* be
-		//		defined before the startup function is called.
-		dropDown: null,
-
-		// autoWidth: [protected] Boolean
-		//		Set to true to make the drop down at least as wide as this
-		//		widget.  Set to false if the drop down should just be its
-		//		default width
-		autoWidth: true,
-
-		// forceWidth: [protected] Boolean
-		//		Set to true to make the drop down exactly as wide as this
-		//		widget.  Overrides autoWidth.
-		forceWidth: false,
-
-		// maxHeight: [protected] Integer
-		//		The max height for our dropdown.  Set to 0 for no max height.
-		//		any dropdown taller than this will have scrollbars
-		maxHeight: 0,
-
-		// dropDownPosition: [const] String[]
-		//		This variable controls the position of the drop down.
-		//		It's an array of strings with the following values:
-		//
-		//			* before: places drop down to the left of the target node/widget, or to the right in
-		//			  the case of RTL scripts like Hebrew and Arabic
-		//			* after: places drop down to the right of the target node/widget, or to the left in
-		//			  the case of RTL scripts like Hebrew and Arabic
-		//			* above: drop down goes above target node
-		//			* below: drop down goes below target node
-		//
-		//		The list is positions is tried, in order, until a position is found where the drop down fits
-		//		within the viewport.
-		//
-		dropDownPosition: ["below","above"],
-
-		// _stopClickEvents: Boolean
-		//		When set to false, the click events will not be stopped, in
-		//		case you want to use them in your subwidget
-		_stopClickEvents: true,
-
-		_onDropDownMouse: function(/*Event*/ e){
-			// summary:
-			//		Callback when the user mouse clicks on the arrow icon, or presses the down
-			//		arrow key, to open the drop down.
-
-			// We handle mouse events using onmousedown in order to allow for selecting via
-			// a mouseDown --> mouseMove --> mouseUp.  So, our click is already handled, unless
-			// we are executed via keypress - in which case, this._seenKeydown
-			// will be set to true.
-			if(e.type == "click" && !this._seenKeydown){ return; }
-			this._seenKeydown = false;
-
-			// If we are a mouse event, set up the mouseup handler.  See _onDropDownMouse() for
-			// details on this handler.
-			if(e.type == "mousedown"){
-				this._docHandler = this.connect(dojo.doc, "onmouseup", "_onDropDownMouseup");
-			}
-			if(this.disabled || this.readOnly){ return; }
-			if(this._stopClickEvents){
-				dojo.stopEvent(e);
-			}
-			this.toggleDropDown();
-
-			// If we are a click, then we'll pretend we did a mouse up
-			if(e.type == "click" || e.type == "keypress"){
-				this._onDropDownMouseup();
-			}
-		},
-
-		_onDropDownMouseup: function(/*Event?*/ e){
-			// summary:
-			//		Callback when the user lifts their mouse after mouse down on the arrow icon.
-			//		If the drop is a simple menu and the mouse is over the menu, we execute it, otherwise, we focus our
-			//		dropDown node.  If the event is missing, then we are not
-			//		a mouseup event.
-			//
-			//		This is useful for the common mouse movement pattern
-			//		with native browser <select> nodes:
-			//			1. mouse down on the select node (probably on the arrow)
-			//			2. move mouse to a menu item while holding down the mouse button
-			//			3. mouse up.  this selects the menu item as though the user had clicked it.
-
-			if(e && this._docHandler){
-				this.disconnect(this._docHandler);
-			}
-			var dropDown = this.dropDown, overMenu = false;
-
-			if(e && this._opened){
-				// This code deals with the corner-case when the drop down covers the original widget,
-				// because it's so large.  In that case mouse-up shouldn't select a value from the menu.
-				// Find out if our target is somewhere in our dropdown widget,
-				// but not over our _buttonNode (the clickable node)
-				var c = dojo.position(this._buttonNode, true);
-				if(!(e.pageX >= c.x && e.pageX <= c.x + c.w) ||
-					!(e.pageY >= c.y && e.pageY <= c.y + c.h)){
-					var t = e.target;
-					while(t && !overMenu){
-						if(dojo.hasClass(t, "dijitPopup")){
-							overMenu = true;
-						}else{
-							t = t.parentNode;
-						}
-					}
-					if(overMenu){
-						t = e.target;
-						if(dropDown.onItemClick){
-							var menuItem;
-							while(t && !(menuItem = dijit.byNode(t))){
-								t = t.parentNode;
-							}
-							if(menuItem && menuItem.onClick && menuItem.getParent){
-								menuItem.getParent().onItemClick(menuItem, e);
-							}
-						}
-						return;
-					}
-				}
-			}
-			if(this._opened && dropDown.focus){
-				// Focus the dropdown widget - do it on a delay so that we
-				// don't steal our own focus.
-				window.setTimeout(dojo.hitch(dropDown, "focus"), 1);
-			}
-		},
-
-		_setupDropdown: function(){
-			// summary:
-			//		set up nodes and connect our mouse and keypress events
-			this._buttonNode = this._buttonNode || this.focusNode || this.domNode;
-			this._popupStateNode = this._popupStateNode || this.focusNode || this._buttonNode;
-			this._aroundNode = this._aroundNode || this.domNode;
-			this.connect(this._buttonNode, "onmousedown", "_onDropDownMouse");
-			this.connect(this._buttonNode, "onclick", "_onDropDownMouse");
-			this.connect(this._buttonNode, "onkeydown", "_onDropDownKeydown");
-			this.connect(this._buttonNode, "onblur", "_onDropDownBlur");
-			this.connect(this._buttonNode, "onkeypress", "_onKey");
-
-			// If we have a _setStateClass function (which happens when
-			// we are a form widget), then we need to connect our open/close
-			// functions to it
-			if(this._setStateClass){
-				this.connect(this, "openDropDown", "_setStateClass");
-				this.connect(this, "closeDropDown", "_setStateClass");
-			}
-
-			// Add a class to the "dijitDownArrowButton" type class to _buttonNode so theme can set direction of arrow
-			// based on where drop down will normally appear
-			var defaultPos = {
-					"after" : this.isLeftToRight() ? "Right" : "Left",
-					"before" : this.isLeftToRight() ? "Left" : "Right",
-					"above" : "Up",
-					"below" : "Down",
-					"left" : "Left",
-					"right" : "Right"
-			}[this.dropDownPosition[0]] || this.dropDownPosition[0] || "Down";
-			dojo.addClass(this._arrowWrapperNode || this._buttonNode, "dijit" + defaultPos + "ArrowButton");
-		},
-
-		postCreate: function(){
-			this._setupDropdown();
-			this.inherited(arguments);
-		},
-
-		destroyDescendants: function(){
-			if(this.dropDown){
-				// Destroy the drop down, unless it's already been destroyed.  This can happen because
-				// the drop down is a direct child of <body> even though it's logically my child.
-				if(!this.dropDown._destroyed){
-					this.dropDown.destroyRecursive();
-				}
-				delete this.dropDown;
-			}
-			this.inherited(arguments);
-		},
-
-		_onDropDownKeydown: function(/*Event*/ e){
-			this._seenKeydown = true;
-		},
-
-		_onKeyPress: function(/*Event*/ e){
-			if(this._opened && e.charOrCode == dojo.keys.ESCAPE && !e.shiftKey && !e.ctrlKey && !e.altKey){
-				this.toggleDropDown();
-				dojo.stopEvent(e);
-				return;
-			}
-			this.inherited(arguments);
-		},
-
-		_onDropDownBlur: function(/*Event*/ e){
-			this._seenKeydown = false;
-		},
-
-		_onKey: function(/*Event*/ e){
-			// summary:
-			//		Callback when the user presses a key on menu popup node
-
-			if(this.disabled || this.readOnly){ return; }
-			var d = this.dropDown;
-			if(d && this._opened && d.handleKey){
-				if(d.handleKey(e) === false){ return; }
-			}
-			if(d && this._opened && e.keyCode == dojo.keys.ESCAPE){
-				this.toggleDropDown();
-				return;
-			}
-			if(e.keyCode == dojo.keys.DOWN_ARROW || e.keyCode == dojo.keys.ENTER || e.charOrCode == " "){
-				this._onDropDownMouse(e);
-			}
-		},
-
-		_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);
-		},
-
-		isLoaded: function(){
-			// summary:
-			//		Returns whether or not the dropdown is loaded.  This can
-			//		be overridden in order to force a call to loadDropDown().
-			// tags:
-			//		protected
-
-			return true;
-		},
-
-		loadDropDown: function(/* Function */ loadCallback){
-			// summary:
-			//		Loads the data for the dropdown, and at some point, calls
-			//		the given callback
-			// tags:
-			//		protected
-
-			loadCallback();
-		},
-
-		toggleDropDown: function(){
-			// summary:
-			//		Toggle the drop-down widget; if it is up, close it, if not, open it
-			// tags:
-			//		protected
-
-			if(this.disabled || this.readOnly){ return; }
-			this.focus();
-			var dropDown = this.dropDown;
-			if(!dropDown){ return; }
-			if(!this._opened){
-				// If we aren't loaded, load it first so there isn't a flicker
-				if(!this.isLoaded()){
-					this.loadDropDown(dojo.hitch(this, "openDropDown"));
-					return;
-				}else{
-					this.openDropDown();
-				}
-			}else{
-				this.closeDropDown();
-			}
-		},
-
-		openDropDown: function(){
-			// summary:
-			//		Opens the dropdown for this widget - it returns the
-			//		return value of dijit.popup.open
-			// tags:
-			//		protected
-
-			var dropDown = this.dropDown;
-			var ddNode = dropDown.domNode;
-			var self = this;
-
-			// Prepare our popup's height and honor maxHeight if it exists.
-
-			// TODO: isn't maxHeight dependent on the return value from dijit.popup.open(),
-			// ie, dependent on how much space is available (BK)
-
-			if(!this._preparedNode){
-				dijit.popup.moveOffScreen(ddNode);
-				this._preparedNode = true;			
-				// Check if we have explicitly set width and height on the dropdown widget dom node
-				if(ddNode.style.width){
-					this._explicitDDWidth = true;
-				}
-				if(ddNode.style.height){
-					this._explicitDDHeight = true;
-				}
-			}
-			if(this.maxHeight || this.forceWidth || this.autoWidth){
-				var myStyle = {
-					display: "",
-					visibility: "hidden"
-				};
-				if(!this._explicitDDWidth){
-					myStyle.width = "";
-				}
-				if(!this._explicitDDHeight){
-					myStyle.height = "";
-				}
-				dojo.style(ddNode, myStyle);
-				var mb = dojo.marginBox(ddNode);
-				var overHeight = (this.maxHeight && mb.h > this.maxHeight);
-				dojo.style(ddNode, {overflow: overHeight ? "auto" : "hidden"});
-				if(this.forceWidth){
-					mb.w = this.domNode.offsetWidth;
-				}else if(this.autoWidth){
-					mb.w = Math.max(mb.w, this.domNode.offsetWidth);
-				}else{
-					delete mb.w;
-				}
-				if(overHeight){
-					mb.h = this.maxHeight;
-					if("w" in mb){
-						mb.w += 16;
-					}
-				}else{
-					delete mb.h;
-				}
-				delete mb.t;
-				delete mb.l;
-				if(dojo.isFunction(dropDown.resize)){
-					dropDown.resize(mb);
-				}else{
-					dojo.marginBox(ddNode, mb);
-				}
-			}
-			var retVal = dijit.popup.open({
-				parent: this,
-				popup: dropDown,
-				around: this._aroundNode,
-				orient: dijit.getPopupAroundAlignment((this.dropDownPosition && this.dropDownPosition.length) ? this.dropDownPosition : ["below"],this.isLeftToRight()),
-				onExecute: function(){
-					self.closeDropDown(true);
-				},
-				onCancel: function(){
-					self.closeDropDown(true);
-				},
-				onClose: function(){
-					dojo.attr(self._popupStateNode, "popupActive", false);
-					dojo.removeClass(self._popupStateNode, "dijitHasDropDownOpen");
-					self._opened = false;
-					self.state = "";
-				}
-			});
-			dojo.attr(this._popupStateNode, "popupActive", "true");
-			dojo.addClass(self._popupStateNode, "dijitHasDropDownOpen");
-			this._opened=true;
-			this.state="Opened";
-			// TODO: set this.checked and call setStateClass(), to affect button look while drop down is shown
-			return retVal;
-		},
-
-		closeDropDown: function(/*Boolean*/ focus){
-			// summary:
-			//		Closes the drop down on this widget
-			// tags:
-			//		protected
-
-			if(this._opened){
-				dijit.popup.close(this.dropDown);
-				if(focus){ this.focus(); }
-				this._opened = false;
-				this.state = "";
-			}
-		}
-
-	}
-);
-
-}
-
-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 DOMNode 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: dojo.cache("dijit.form", "templates/Button.html", "<span class=\"dijit dijitReset dijitLeft dijitInline\"\n\tdojoAttachEvent=\"onclick:_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${nameAttrSetti [...]
-
-	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){
-			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(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){
-				console.debug('Cannot change the value attribute on a Button widget.');
-			}
-		}
-	},
-
-	_fillContent: function(/*DomNode*/ source){
-		// Overrides _Templated._fillContent().
-		// If button label is specified as srcNodeRef.innerHTML rather than
-		// this.params.label, handle it here.
-		if(source && (!this.params || !("label" in this.params))){
-			this.attr('label', source.innerHTML);
-		}
-	},
-
-	postCreate: function(){
-		dojo.setSelectable(this.focusNode, false);
-		this.inherited(arguments);
-	},
-
-	_setShowLabelAttr: function(val){
-		if(this.containerNode){
-			dojo.toggleClass(this.containerNode, "dijitDisplayNone", !val);
-		}
-		this.showLabel = val;
-	},
-
-	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;
-		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, dijit._HasDropDown], {
-	// 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: dojo.cache("dijit.form", "templates/DropDownButton.html", "<span class=\"dijit dijitReset dijitLeft dijitInline\"\n\tdojoAttachPoint=\"_buttonNode\"\n\tdojoAttachEvent=\"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\t${nameAttrSetting} type=\"${type}\" value=\"${va [...]
-
-	_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.moveOffScreen(this.dropDown.domNode);
-
-		this.inherited(arguments);
-	},
-
-	isLoaded: function(){
-		// Returns whether or not we are loaded - if our dropdown has an href,
-		// then we want to check that.
-		var dropDown = this.dropDown;
-		return (!dropDown.href || dropDown.isLoaded);
-	},
-
-	loadDropDown: function(){
-		// Loads our dropdown
-		var dropDown = this.dropDown;
-		if(!dropDown){ return; }
-		if(!this.isLoaded()){
-			var handler = dojo.connect(dropDown, "onLoad", this, function(){
-				dojo.disconnect(handler);
-				this.openDropDown();
-			});
-			dropDown.refresh();
-		}else{
-			this.openDropDown();
-		}
-	},
-
-	isFocusable: function(){
-		// Overridden so that focus is handled by the _HasDropDown mixin, not by
-		// the _FormWidget mixin.
-		return this.inherited(arguments) && !this._mouseDown;
-	}
-});
-
-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: dojo.cache("dijit.form", "templates/ComboButton.html", "<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 dijitButtonNode\"><button id=\"${id}_button\" class=\"dijitReset dijitButtonContents\"\n\t\t\tdojoAttachEvent=\"onclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMous [...]
-
-	attributeMap: dojo.mixin(dojo.clone(dijit.form.Button.prototype.attributeMap), {
-		id: "",
-		tabIndex: ["focusNode", "titleNode"],
-		title: "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];
-		var isIE = dojo.isIE;
-		dojo.forEach(this._focalNodes, dojo.hitch(this, function(node){
-			this.connect(node, isIE? "onactivate" : "onfocus", this._onNodeFocus);
-			this.connect(node, isIE? "ondeactivate" : "onblur", this._onNodeBlur);
-		}));
-		if(isIE && (isIE < 8 || dojo.isQuirks)){ // fixed in IE8/strict
-			with(this.titleNode){ // resize BUTTON tag so parent TD won't inherit extra padding
-				style.width = scrollWidth + "px";
-				this.connect(this.titleNode, "onresize", function(){
-					setTimeout( function(){ style.width = scrollWidth + "px"; }, 0);
-				});
-			}
-		}
-	},
-
-	_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;
-	},
-	
-	_onButtonKeyPress: function(/*Event*/ evt){
-		// summary:
-		//		Handler for right arrow key when focus is on left part of button
-		if(evt.charOrCode == dojo.keys[this.isLeftToRight() ? "RIGHT_ARROW" : "LEFT_ARROW"]){
-			dijit.focus(this._popupStateNode);
-			dojo.stopEvent(evt);
-		}
-	},
-
-	_onArrowKeyPress: function(/*Event*/ evt){
-		// summary:
-		//		Handler for left arrow key when focus is on right part of button
-		if(evt.charOrCode == dojo.keys[this.isLeftToRight() ? "LEFT_ARROW" : "RIGHT_ARROW"]){
-			dijit.focus(this.titleNode);
-			dojo.stopEvent(evt);
-		}
-	},
-	
-	focus: function(/*String*/ position){
-		// summary:
-		//		Focuses this widget to according to position, if specified,
-		//		otherwise on arrow node
-		// position:
-		//		"start" or "end"
-		
-		dijit.focus(position == "start" ? this.titleNode : this._popupStateNode);
-	}
-});
-
-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._editor._Plugin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._editor._Plugin"] = true;
-dojo.provide("dijit._editor._Plugin");
-
-
-
-
-dojo.declare("dijit._editor._Plugin", null, {
-	// summary
-	//		Base class for a "plugin" to the editor, which is usually
-	//		a single button on the Toolbar and some associated code
-
-	constructor: function(/*Object?*/args, /*DomNode?*/node){
-		this.params = args || {};
-		dojo.mixin(this, this.params);
-		this._connects=[];
-	},
-
-	// editor: [const] dijit.Editor
-	//		Points to the parent editor
-	editor: null,
-
-	// iconClassPrefix: [const] String
-	//		The CSS class name for the button node is formed from `iconClassPrefix` and `command`
-	iconClassPrefix: "dijitEditorIcon",
-
-	// button: dijit._Widget?
-	//		Pointer to `dijit.form.Button` or other widget (ex: `dijit.form.FilteringSelect`)
-	//		that is added to the toolbar to control this plugin.
-	//		If not specified, will be created on initialization according to `buttonClass`
-	button: null,
-
-	// command: String
-	//		String like "insertUnorderedList", "outdent", "justifyCenter", etc. that represents an editor command.
-	//		Passed to editor.execCommand() if `useDefaultCommand` is true.
-	command: "",
-
-	// useDefaultCommand: Boolean
-	//		If true, this plugin executes by calling Editor.execCommand() with the argument specified in `command`.
-	useDefaultCommand: true,
-
-	// buttonClass: Widget Class
-	//		Class of widget (ex: dijit.form.Button or dijit.form.FilteringSelect)
-	//		that is added to the toolbar to control this plugin.
-	//		This is used to instantiate the button, unless `button` itself is specified directly.
-	buttonClass: dijit.form.Button,
-
-	getLabel: function(/*String*/key){
-		// summary:
-		//		Returns the label to use for the button
-		// tags:
-		//		private
-		return this.editor.commands[key];		// String
-	},
-
-	_initButton: function(){
-		// summary:
-		//		Initialize the button or other widget that will control this plugin.
-		//		This code only works for plugins controlling built-in commands in the editor.
-		// tags:
-		//		protected extension
-		if(this.command.length){
-			var label = this.getLabel(this.command);
-			var className = this.iconClassPrefix+" "+this.iconClassPrefix + this.command.charAt(0).toUpperCase() + this.command.substr(1);
-			if(!this.button){
-				var props = dojo.mixin({
-					label: label,
-					showLabel: false,
-					iconClass: className,
-					dropDown: this.dropDown,
-					tabIndex: "-1"
-				}, this.params || {});
-				this.button = new this.buttonClass(props);
-			}
-		}
-	},
-
-	destroy: function(){
-		// summary:
-		//		Destroy this plugin
-
-		dojo.forEach(this._connects, dojo.disconnect);
-		if(this.dropDown){
-			this.dropDown.destroyRecursive();
-		}
-	},
-
-	connect: function(o, f, tf){
-		// summary:
-		//		Make a dojo.connect() that is automatically disconnected when this plugin is destroyed.
-		//		Similar to `dijit._Widget.connect`.
-		// tags:
-		//		protected
-		this._connects.push(dojo.connect(o, f, this, tf));
-	},
-
-	updateState: function(){
-		// summary:
-		//		Change state of the plugin to respond to events in the editor.
-		// description:
-		//		This is called on meaningful events in the editor, such as change of selection
-		//		or caret position (but not simple typing of alphanumeric keys).   It gives the
-		//		plugin a chance to update the CSS of its button.
-		//
-		//		For example, the "bold" plugin will highlight/unhighlight the bold button depending on whether the
-		//		characters next to the caret are bold or not.
-		//
-		//		Only makes sense when `useDefaultCommand` is true, as it calls Editor.queryCommandEnabled(`command`).
-		var e = this.editor,
-			c = this.command,
-			checked, enabled;
-		if(!e || !e.isLoaded || !c.length){ return; }
-		if(this.button){
-			try{
-				enabled = e.queryCommandEnabled(c);
-				if(this.enabled !== enabled){
-					this.enabled = enabled;
-					this.button.attr('disabled', !enabled);
-				}
-				if(typeof this.button.checked == 'boolean'){
-					checked = e.queryCommandState(c);
-					if(this.checked !== checked){
-						this.checked = checked;
-						this.button.attr('checked', e.queryCommandState(c));
-					}
-				}
-			}catch(e){
-				console.log(e); // FIXME: we shouldn't have debug statements in our code.  Log as an error?
-			}
-		}
-	},
-
-	setEditor: function(/*dijit.Editor*/ editor){
-		// summary:
-		//		Tell the plugin which Editor it is associated with.
-
-		// TODO: refactor code to just pass editor to constructor.
-
-		// FIXME: detach from previous editor!!
-		this.editor = editor;
-
-		// FIXME: prevent creating this if we don't need to (i.e., editor can't handle our command)
-		this._initButton();
-
-		// FIXME: wire up editor to button here!
-		if(this.command.length &&
-			!this.editor.queryCommandAvailable(this.command)){
-			// console.debug("hiding:", this.command);
-			if(this.button){
-				this.button.domNode.style.display = "none";
-			}
-		}
-		if(this.button && this.useDefaultCommand){
-			this.connect(this.button, "onClick",
-				dojo.hitch(this.editor, "execCommand", this.command, this.commandArg)
-			);
-		}
-		this.connect(this.editor, "onNormalizedDisplayChanged", "updateState");
-	},
-
-	setToolbar: function(/*dijit.Toolbar*/ toolbar){
-		// summary:
-		//		Tell the plugin to add it's controller widget (often a button)
-		//		to the toolbar.  Does nothing if there is no controller widget.
-
-		// TODO: refactor code to just pass toolbar to constructor.
-
-		if(this.button){
-			toolbar.addChild(this.button);
-		}
-		// console.debug("adding", this.button, "to:", toolbar);
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"] = true;
-dojo.provide("dijit._editor.plugins.EnterKeyHandling");
-
-
-
-dojo.declare("dijit._editor.plugins.EnterKeyHandling", dijit._editor._Plugin, {
-	// summary:
-	//		This plugin tries to make all browsers behave consistently w.r.t
-	//		displaying paragraphs, specifically dealing with when the user presses
-	//		the ENTER key.
-	//
-	//		It deals mainly with how the text appears on the screen (specifically
-	//		address the double-spaced line problem on IE), but also has some code
-	//		to normalize what attr('value') returns.
-	//
-	// description:
-	//		This plugin has three modes:
-	//
-	//			* blockModeForEnter=BR
-	//			* blockModeForEnter=DIV
-	//			* blockModeForEnter=P
-	//
-	//		In blockModeForEnter=P, the ENTER key semantically means "start a new
-	//		paragraph", whereas shift-ENTER means  "new line in the current paragraph".
-	//		For example:
-	//
-	//		|	first paragraph <shift-ENTER>
-	//		|	second line of first paragraph <ENTER>
-	//		|
-	//		|	second paragraph
-	//
-	//		In the other two modes, the ENTER key means to go to a new line in the
-	//		current paragraph, and users [visually] create a new paragraph by pressing ENTER twice.
-	//		For example, if the user enters text into an editor like this:
-	//
-	//		|		one <ENTER>
-	//		|		two <ENTER>
-	//		|		three <ENTER>
-	//		|		<ENTER>
-	//		|		four <ENTER>
-	//		|		five <ENTER>
-	//		|		six <ENTER>
-	//
-	//		It will appear on the screen as two paragraphs of three lines each.
-	//
-	//		blockNodeForEnter=BR
-	//		--------------------
-	//		On IE, typing the above keystrokes in the editor will internally produce DOM of:
-	//
-	//		|		<p>one</p>
-	//		|		<p>two</p>
-	//		|		<p>three</p>
-	//		|		<p></p>
-	//		|		<p>four</p>
-	//		|		<p>five</p>
-	//		|		<p>six</p>
-	//
-	//		However, blockNodeForEnter=BR makes the Editor on IE display like other browsers, by
-	//		changing the CSS for the <p> node to not have top/bottom margins,
-	//		thus eliminating the double-spaced appearance.
-	//
-	//		Also, attr('value') when used w/blockNodeForEnter=br on IE will return:
-	//
-	//		|	<p> one <br> two <br> three </p>
-	//		|	<p> four <br> five <br> six </p>
-	//
-	//		This output normalization implemented by a filter when the
-	//		editor writes out it's data, to convert consecutive <p>
-	//		nodes into a single <p> node with internal <br> separators.
-	//
-	//		There's also a pre-filter to mirror the post-filter.
-	//		It converts a single <p> with <br> line breaks
-	//		into separate <p> nodes, and creates empty <p> nodes for spacing
-	//		between paragraphs.
-	//
-	//		On FF typing the above keystrokes will internally generate:
-	//
-	//		|		one <br> two <br> three <br> <br> four <br> five <br> six <br>
-	//
-	//		And on Safari it will generate:
-	//
-	//		|		"one"
-	//		|		<div>two</div>
-	//		|		<div>three</div>
-	//		|		<div><br></div>
-	//		|		<div>four</div>
-	//		|		<div>five</div>
-	//		|		<div>six</div>
-	//
-	//		Thus, Safari and FF already look correct although semantically their content is a bit strange.
-	//		On Safari or Firefox blockNodeForEnter=BR uses the builtin editor command "insertBrOnReturn",
-	//		but that doesn't seem to do anything.
-	//		Thus, attr('value') on safari/FF returns the browser-specific HTML listed above,
-	//		rather than the semantically meaningful value that IE returns: <p>one<br>two</p> <p>three<br>four</p>.
-	//
-	//		(Note: originally based on http://bugs.dojotoolkit.org/ticket/2859)
-	//
-	//		blockNodeForEnter=P
-	//		-------------------
-	//		Plugin will monitor keystrokes and update the editor's content on the fly,
-	//		so that the ENTER key will create a new <p> on FF and Safari (it already
-	//		works that way by default on IE).
-	//
-	//		blockNodeForEnter=DIV
-	//		---------------------
-	//		Follows the same code path as blockNodeForEnter=P but inserting a <div>
-	//		on ENTER key.  Although it produces strange internal DOM, like this:
-	//
-	//		|	<div>paragraph one</div>
-	//		|	<div>paragraph one, line 2</div>
-	//		|	<div> </div>
-	//		|	<div>paragraph two</div>
-	//
-	//		it does provide a consistent look on all browsers, and the on-the-fly DOM updating
-	//		can be useful for collaborative editing.
-
-	// blockNodeForEnter: String
-	//		This property decides the behavior of Enter key. It can be either P,
-	//		DIV, BR, or empty (which means disable this feature). Anything else
-	//		will trigger errors.
-	//
-	//		See class description for more details.
-	blockNodeForEnter: 'BR',
-
-	constructor: function(args){
-		if(args){
-			dojo.mixin(this,args);
-		}
-	},
-
-	setEditor: function(editor){
-		// Overrides _Plugin.setEditor().
-		this.editor = editor;
-		if(this.blockNodeForEnter == 'BR'){
-			if(dojo.isIE){
-				editor.contentDomPreFilters.push(dojo.hitch(this, "regularPsToSingleLinePs"));
-				editor.contentDomPostFilters.push(dojo.hitch(this, "singleLinePsToRegularPs"));
-				editor.onLoadDeferred.addCallback(dojo.hitch(this, "_fixNewLineBehaviorForIE"));
-			}else{
-				editor.onLoadDeferred.addCallback(dojo.hitch(this,function(d){
-					try{
-						this.editor.document.execCommand("insertBrOnReturn", false, true);
-					}catch(e){}
-					return d;
-				}));
-			}
-		}else if(this.blockNodeForEnter){
-			// add enter key handler
-			// FIXME: need to port to the new event code!!
-			dojo['require']('dijit._editor.range');
-			var h = dojo.hitch(this,this.handleEnterKey);
-			editor.addKeyHandler(13, 0, 0, h); //enter
-			editor.addKeyHandler(13, 0, 1, h); //shift+enter
-			this.connect(this.editor,'onKeyPressed','onKeyPressed');
-		}
-	},
-	onKeyPressed: function(e){
-		// summary:
-		//		Handler for keypress events.
-		// tags:
-		//		private
-		if(this._checkListLater){
-			if(dojo.withGlobal(this.editor.window, 'isCollapsed', dijit)){
-				var liparent=dojo.withGlobal(this.editor.window, 'getAncestorElement', dijit._editor.selection, ['LI']);
-				if(!liparent){
-					// circulate the undo detection code by calling RichText::execCommand directly
-					dijit._editor.RichText.prototype.execCommand.call(this.editor, 'formatblock',this.blockNodeForEnter);
-					// set the innerHTML of the new block node
-					var block = dojo.withGlobal(this.editor.window, 'getAncestorElement', dijit._editor.selection, [this.blockNodeForEnter]);
-					if(block){
-						block.innerHTML=this.bogusHtmlContent;
-						if(dojo.isIE){
-							// move to the start by moving backwards one char
-							var r = this.editor.document.selection.createRange();
-							r.move('character',-1);
-							r.select();
-						}
-					}else{
-						console.error('onKeyPressed: Cannot find the new block node'); // FIXME
-					}
-				}else{
-					if(dojo.isMoz){
-						if(liparent.parentNode.parentNode.nodeName == 'LI'){
-							liparent=liparent.parentNode.parentNode;
-						}
-					}
-					var fc=liparent.firstChild;
-					if(fc && fc.nodeType == 1 && (fc.nodeName == 'UL' || fc.nodeName == 'OL')){
-						liparent.insertBefore(fc.ownerDocument.createTextNode('\xA0'),fc);
-						var newrange = dijit.range.create(this.editor.window);
-						newrange.setStart(liparent.firstChild,0);
-						var selection = dijit.range.getSelection(this.editor.window, true);
-						selection.removeAllRanges();
-						selection.addRange(newrange);
-					}
-				}
-			}
-			this._checkListLater = false;
-		}
-		if(this._pressedEnterInBlock){
-			// the new created is the original current P, so we have previousSibling below
-			if(this._pressedEnterInBlock.previousSibling){
-				this.removeTrailingBr(this._pressedEnterInBlock.previousSibling);
-			}
-			delete this._pressedEnterInBlock;
-		}
-	},
-
-	// bogusHtmlContent: [private] String
-	//		HTML to stick into a new empty block
-	bogusHtmlContent: ' ',
-
-	// blockNodes: [private] Regex
-	//		Regex for testing if a given tag is a block level (display:block) tag
-	blockNodes: /^(?:P|H1|H2|H3|H4|H5|H6|LI)$/,
-
-	handleEnterKey: function(e){
-		// summary:
-		//		Handler for enter key events when blockModeForEnter is DIV or P.
-		// description:
-		//		Manually handle enter key event to make the behavior consistent across
-		//		all supported browsers. See class description for details.
-		// tags:
-		//		private
-
-		var selection, range, newrange, doc=this.editor.document,br;
-		if(e.shiftKey){		// shift+enter always generates <br>
-			var parent = dojo.withGlobal(this.editor.window, "getParentElement", dijit._editor.selection);
-			var header = dijit.range.getAncestor(parent,this.blockNodes);
-			if(header){
-				if(!e.shiftKey && header.tagName == 'LI'){
-					return true; // let browser handle
-				}
-				selection = dijit.range.getSelection(this.editor.window);
-				range = selection.getRangeAt(0);
-				if(!range.collapsed){
-					range.deleteContents();
-					selection = dijit.range.getSelection(this.editor.window);
-					range = selection.getRangeAt(0);
-				}
-				if(dijit.range.atBeginningOfContainer(header, range.startContainer, range.startOffset)){
-					if(e.shiftKey){
-						br=doc.createElement('br');
-						newrange = dijit.range.create(this.editor.window);
-						header.insertBefore(br,header.firstChild);
-						newrange.setStartBefore(br.nextSibling);
-						selection.removeAllRanges();
-						selection.addRange(newrange);
-					}else{
-						dojo.place(br, header, "before");
-					}
-				}else if(dijit.range.atEndOfContainer(header, range.startContainer, range.startOffset)){
-					newrange = dijit.range.create(this.editor.window);
-					br=doc.createElement('br');
-					if(e.shiftKey){
-						header.appendChild(br);
-						header.appendChild(doc.createTextNode('\xA0'));
-						newrange.setStart(header.lastChild,0);
-					}else{
-						dojo.place(br, header, "after");
-						newrange.setStartAfter(header);
-					}
-
-					selection.removeAllRanges();
-					selection.addRange(newrange);
-				}else{
-					return true; // let browser handle
-				}
-			}else{
-				// don't change this: do not call this.execCommand, as that may have other logic in subclass
-				dijit._editor.RichText.prototype.execCommand.call(this.editor, 'inserthtml', '<br>');
-			}
-			return false;
-		}
-		var _letBrowserHandle = true;
-
-		// first remove selection
-		selection = dijit.range.getSelection(this.editor.window);
-		range = selection.getRangeAt(0);
-		if(!range.collapsed){
-			range.deleteContents();
-			selection = dijit.range.getSelection(this.editor.window);
-			range = selection.getRangeAt(0);
-		}
-
-		var block = dijit.range.getBlockAncestor(range.endContainer, null, this.editor.editNode);
-		var blockNode = block.blockNode;
-
-		// if this is under a LI or the parent of the blockNode is LI, just let browser to handle it
-		if((this._checkListLater = (blockNode && (blockNode.nodeName == 'LI' || blockNode.parentNode.nodeName == 'LI')))){
-			if(dojo.isMoz){
-				// press enter in middle of P may leave a trailing <br/>, let's remove it later
-				this._pressedEnterInBlock = blockNode;
-			}
-			// if this li only contains spaces, set the content to empty so the browser will outdent this item
-			if(/^(\s| |\xA0|<span\b[^>]*\bclass=['"]Apple-style-span['"][^>]*>(\s| |\xA0)<\/span>)?(<br>)?$/.test(blockNode.innerHTML)){
-				// empty LI node
-				blockNode.innerHTML = '';
-				if(dojo.isWebKit){ // WebKit tosses the range when innerHTML is reset
-					newrange = dijit.range.create(this.editor.window);
-					newrange.setStart(blockNode, 0);
-					selection.removeAllRanges();
-					selection.addRange(newrange);
-				}
-				this._checkListLater = false; // nothing to check since the browser handles outdent
-			}
-			return true;
-		}
-
-		// text node directly under body, let's wrap them in a node
-		if(!block.blockNode || block.blockNode===this.editor.editNode){
-			try{
-				dijit._editor.RichText.prototype.execCommand.call(this.editor, 'formatblock',this.blockNodeForEnter);
-			}catch(e2){ /*squelch FF3 exception bug when editor content is a single BR*/ }
-			// get the newly created block node
-			// FIXME
-			block = {blockNode:dojo.withGlobal(this.editor.window, "getAncestorElement", dijit._editor.selection, [this.blockNodeForEnter]),
-					blockContainer: this.editor.editNode};
-			if(block.blockNode){
-				if(block.blockNode != this.editor.editNode &&
-					(!(block.blockNode.textContent || block.blockNode.innerHTML).replace(/^\s+|\s+$/g, "").length)){
-					this.removeTrailingBr(block.blockNode);
-					return false;
-				}
-			}else{	// we shouldn't be here if formatblock worked
-				block.blockNode = this.editor.editNode;
-			}
-			selection = dijit.range.getSelection(this.editor.window);
-			range = selection.getRangeAt(0);
-		}
-
-		var newblock = doc.createElement(this.blockNodeForEnter);
-		newblock.innerHTML=this.bogusHtmlContent;
-		this.removeTrailingBr(block.blockNode);
-		if(dijit.range.atEndOfContainer(block.blockNode, range.endContainer, range.endOffset)){
-			if(block.blockNode === block.blockContainer){
-				block.blockNode.appendChild(newblock);
-			}else{
-				dojo.place(newblock, block.blockNode, "after");
-			}
-			_letBrowserHandle = false;
-			// lets move caret to the newly created block
-			newrange = dijit.range.create(this.editor.window);
-			newrange.setStart(newblock, 0);
-			selection.removeAllRanges();
-			selection.addRange(newrange);
-			if(this.editor.height){
-				dijit.scrollIntoView(newblock);
-			}
-		}else if(dijit.range.atBeginningOfContainer(block.blockNode,
-				range.startContainer, range.startOffset)){
-			dojo.place(newblock, block.blockNode, block.blockNode === block.blockContainer ? "first" : "before");
-			if(newblock.nextSibling && this.editor.height){
-				// position input caret - mostly WebKit needs this
-				newrange = dijit.range.create(this.editor.window);
-				newrange.setStart(newblock.nextSibling, 0);
-				selection.removeAllRanges();
-				selection.addRange(newrange);
-				// browser does not scroll the caret position into view, do it manually
-				dijit.scrollIntoView(newblock.nextSibling);
-			}
-			_letBrowserHandle = false;
-		}else{ // press enter in the middle of P
-			if(dojo.isMoz){
-				// press enter in middle of P may leave a trailing <br/>, let's remove it later
-				this._pressedEnterInBlock = block.blockNode;
-			}
-		}
-		return _letBrowserHandle;
-	},
-
-	removeTrailingBr: function(container){
-		// summary:
-		//		If last child of container is a <br>, then remove it.
-		// tags:
-		//		private
-		var para = /P|DIV|LI/i.test(container.tagName) ?
-			container : dijit._editor.selection.getParentOfType(container,['P','DIV','LI']);
-
-		if(!para){ return; }
-		if(para.lastChild){
-			if((para.childNodes.length > 1 && para.lastChild.nodeType == 3 && /^[\s\xAD]*$/.test(para.lastChild.nodeValue)) ||
-				para.lastChild.tagName=='BR'){
-
-				dojo.destroy(para.lastChild);
-			}
-		}
-		if(!para.childNodes.length){
-			para.innerHTML=this.bogusHtmlContent;
-		}
-	},
-	_fixNewLineBehaviorForIE: function(d){
-		// summary:
-		//		Insert CSS so <p> nodes don't have spacing around them,
-		//		thus hiding the fact that ENTER key on IE is creating new
-		//		paragraphs
-
-		// cannot use !important since there may be custom user styling;
-		var doc = this.editor.document;
-		if(doc.__INSERTED_EDITIOR_NEWLINE_CSS === undefined){
-			var style = dojo.create("style", {type: "text/css"}, doc.getElementsByTagName("head")[0]);
-			style.styleSheet.cssText = "p{margin:0;}"; // cannot use !important since there may be custom user styling;
-			this.editor.document.__INSERTED_EDITIOR_NEWLINE_CSS = true;
-		}
-		return d;
-	},
-	regularPsToSingleLinePs: function(element, noWhiteSpaceInEmptyP){
-		// summary:
-		//		Converts a <p> node containing <br>'s into multiple <p> nodes.
-		// description:
-		//		See singleLinePsToRegularPs().   This method does the
-		//		opposite thing, and is used as a pre-filter when loading the
-		//		editor, to mirror the effects of the post-filter at end of edit.
-		// tags:
-		//		private
-		function wrapLinesInPs(el){
-		  // move "lines" of top-level text nodes into ps
-			function wrapNodes(nodes){
-				// nodes are assumed to all be siblings
-				var newP = nodes[0].ownerDocument.createElement('p'); // FIXME: not very idiomatic
-				nodes[0].parentNode.insertBefore(newP, nodes[0]);
-				dojo.forEach(nodes, function(node){
-					newP.appendChild(node);
-				});
-			}
-
-			var currentNodeIndex = 0;
-			var nodesInLine = [];
-			var currentNode;
-			while(currentNodeIndex < el.childNodes.length){
-				currentNode = el.childNodes[currentNodeIndex];
-				if( currentNode.nodeType==3 ||	// text node
-					(currentNode.nodeType==1 && currentNode.nodeName!='BR' && dojo.style(currentNode, "display")!="block")
-				){
-					nodesInLine.push(currentNode);
-				}else{
-					// hit line delimiter; process nodesInLine if there are any
-					var nextCurrentNode = currentNode.nextSibling;
-					if(nodesInLine.length){
-						wrapNodes(nodesInLine);
-						currentNodeIndex = (currentNodeIndex+1)-nodesInLine.length;
-						if(currentNode.nodeName=="BR"){
-							dojo.destroy(currentNode);
-						}
-					}
-					nodesInLine = [];
-				}
-				currentNodeIndex++;
-			}
-			if(nodesInLine.length){ wrapNodes(nodesInLine); }
-		}
-
-		function splitP(el){
-			// split a paragraph into seperate paragraphs at BRs
-			var currentNode = null;
-			var trailingNodes = [];
-			var lastNodeIndex = el.childNodes.length-1;
-			for(var i=lastNodeIndex; i>=0; i--){
-				currentNode = el.childNodes[i];
-				if(currentNode.nodeName=="BR"){
-					var newP = currentNode.ownerDocument.createElement('p');
-					dojo.place(newP, el, "after");
-					if(trailingNodes.length==0 && i != lastNodeIndex){
-						newP.innerHTML = " "
-					}
-					dojo.forEach(trailingNodes, function(node){
-						newP.appendChild(node);
-					});
-					dojo.destroy(currentNode);
-					trailingNodes = [];
-				}else{
-					trailingNodes.unshift(currentNode);
-				}
-			}
-		}
-
-		var pList = [];
-		var ps = element.getElementsByTagName('p');
-		dojo.forEach(ps, function(p){ pList.push(p); });
-		dojo.forEach(pList, function(p){
-			var prevSib = p.previousSibling;
-			if(	(prevSib) && (prevSib.nodeType == 1) && 
-				(prevSib.nodeName == 'P' || dojo.style(prevSib, 'display') != 'block')
-			){
-				var newP = p.parentNode.insertBefore(this.document.createElement('p'), p);
-				// this is essential to prevent IE from losing the P.
-				// if it's going to be innerHTML'd later we need
-				// to add the   to _really_ force the issue
-				newP.innerHTML = noWhiteSpaceInEmptyP ? "" : " ";
-			}
-			splitP(p);
-		},this.editor);
-		wrapLinesInPs(element);
-		return element;
-	},
-
-	singleLinePsToRegularPs: function(element){
-		// summary:
-		//		Called as post-filter.
-		//		Apparently collapses adjacent <p> nodes into a single <p>
-		//		nodes with <br> separating each line.
-		//
-		// example:
-		//		Given this input:
-		//	|	<p>line 1</p>
-		//	|	<p>line 2</p>
-		//	|	<ol>
-		//	|		<li>item 1
-		//	|		<li>item 2
-		//	|	</ol>
-		//	|	<p>line 3</p>
-		//	|	<p>line 4</p>
-		//
-		//		Will convert to:
-		//	|	<p>line 1<br>line 2</p>
-		//	|	<ol>
-		//	|		<li>item 1
-		//	|		<li>item 2
-		//	|	</ol>
-		//	|	<p>line 3<br>line 4</p>
-		//
-		//		Not sure why this situation would even come up after the pre-filter and
-		//		the enter-key-handling code.
-		//
-		// tags:
-		//		private
-
-		function getParagraphParents(node){
-			// summary:
-			//		Used to get list of all nodes that contain paragraphs.
-			//		Seems like that would just be the very top node itself, but apparently not.
-			var ps = node.getElementsByTagName('p');
-			var parents = [];
-			for(var i=0; i<ps.length; i++){
-				var p = ps[i];
-				var knownParent = false;
-				for(var k=0; k < parents.length; k++){
-					if(parents[k] === p.parentNode){
-						knownParent = true;
-						break;
-					}
-				}
-				if(!knownParent){
-					parents.push(p.parentNode);
-				}
-			}
-			return parents;
-		}
-
-		function isParagraphDelimiter(node){
-			return (!node.childNodes.length || node.innerHTML==" ");
-		}
-
-		var paragraphContainers = getParagraphParents(element);
-		for(var i=0; i<paragraphContainers.length; i++){
-			var container = paragraphContainers[i];
-			var firstPInBlock = null;
-			var node = container.firstChild;
-			var deleteNode = null;
-			while(node){
-				if(node.nodeType != 1 || node.tagName != 'P' ||
-						(node.getAttributeNode('style') || {/*no style*/}).specified){
-					firstPInBlock = null;
-				}else if(isParagraphDelimiter(node)){
-					deleteNode = node;
-					firstPInBlock = null;
-				}else{
-					if(firstPInBlock == null){
-						firstPInBlock = node;
-					}else{
-						if( (!firstPInBlock.lastChild || firstPInBlock.lastChild.nodeName != 'BR') &&
-							(node.firstChild) &&
-							(node.firstChild.nodeName != 'BR')
-						){
-							firstPInBlock.appendChild(this.editor.document.createElement('br'));
-						}
-						while(node.firstChild){
-							firstPInBlock.appendChild(node.firstChild);
-						}
-						deleteNode = node;
-					}
-				}
-				node = node.nextSibling;
-				if(deleteNode){
-					dojo.destroy(deleteNode);
-					deleteNode = null;
-				}
-			}
-		}
-		return element;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.Editor"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.Editor"] = true;
-dojo.provide("dijit.Editor");
-
-
-
-
-
-
-
-
-
-
-dojo.declare(
-	"dijit.Editor",
-	dijit._editor.RichText,
-	{
-		// summary:
-		//		A rich text Editing widget
-		//
-		// description:
-		//		This widget provides basic WYSIWYG editing features, based on the browser's
-		//		underlying rich text editing capability, accompanied by a toolbar (`dijit.Toolbar`).
-		//		A plugin model is available to extend the editor's capabilities as well as the
-		//		the options available in the toolbar.  Content generation may vary across
-		//		browsers, and clipboard operations may have different results, to name
-		//		a few limitations.  Note: this widget should not be used with the HTML
-		//		<TEXTAREA> tag -- see dijit._editor.RichText for details.
-
-		// plugins: Object[]
-		//		A list of plugin names (as strings) or instances (as objects)
-		//		for this widget.
-		//
-		//		When declared in markup, it might look like:
-		//	|	plugins="['bold',{name:'dijit._editor.plugins.FontChoice', command:'fontName', generic:true}]"
-		plugins: null,
-
-		// extraPlugins: Object[]
-		//		A list of extra plugin names which will be appended to plugins array
-		extraPlugins: null,
-
-		constructor: function(){
-			// summary:
-			//		Runs on widget initialization to setup arrays etc.
-			// tags:
-			//		private
-
-			if(!dojo.isArray(this.plugins)){
-				this.plugins=["undo","redo","|","cut","copy","paste","|","bold","italic","underline","strikethrough","|",
-				"insertOrderedList","insertUnorderedList","indent","outdent","|","justifyLeft","justifyRight","justifyCenter","justifyFull",
-				"dijit._editor.plugins.EnterKeyHandling" /*, "createLink"*/];
-			}
-
-			this._plugins=[];
-			this._editInterval = this.editActionInterval * 1000;
-
-			//IE will always lose focus when other element gets focus, while for FF and safari,
-			//when no iframe is used, focus will be lost whenever another element gets focus.
-			//For IE, we can connect to onBeforeDeactivate, which will be called right before
-			//the focus is lost, so we can obtain the selected range. For other browsers,
-			//no equivelent of onBeforeDeactivate, so we need to do two things to make sure
-			//selection is properly saved before focus is lost: 1) when user clicks another
-			//element in the page, in which case we listen to mousedown on the entire page and
-			//see whether user clicks out of a focus editor, if so, save selection (focus will
-			//only lost after onmousedown event is fired, so we can obtain correct caret pos.)
-			//2) when user tabs away from the editor, which is handled in onKeyDown below.
-			if(dojo.isIE){
-				this.events.push("onBeforeDeactivate");
-				this.events.push("onBeforeActivate");
-			}
-		},
-
-		postCreate: function(){
-			//for custom undo/redo
-			if(this.customUndo){
-				dojo['require']("dijit._editor.range");
-				this._steps=this._steps.slice(0);
-				this._undoedSteps=this._undoedSteps.slice(0);
-//				this.addKeyHandler('z',this.KEY_CTRL,this.undo);
-//				this.addKeyHandler('y',this.KEY_CTRL,this.redo);
-			}
-			if(dojo.isArray(this.extraPlugins)){
-				this.plugins=this.plugins.concat(this.extraPlugins);
-			}
-
-//			try{
-			this.inherited(arguments);
-//			dijit.Editor.superclass.postCreate.apply(this, arguments);
-
-			this.commands = dojo.i18n.getLocalization("dijit._editor", "commands", this.lang);
-
-			if(!this.toolbar){
-				// if we haven't been assigned a toolbar, create one
-				this.toolbar = new dijit.Toolbar({});
-				dojo.place(this.toolbar.domNode, this.editingArea, "before");
-			}
-
-			dojo.forEach(this.plugins, this.addPlugin, this);
-			this.onNormalizedDisplayChanged(); //update toolbar button status
-//			}catch(e){ console.debug(e); }
-
-			this.toolbar.startup();
-		},
-		destroy: function(){
-			dojo.forEach(this._plugins, function(p){
-				if(p && p.destroy){
-					p.destroy();
-				}
-			});
-			this._plugins=[];
-			this.toolbar.destroyRecursive();
-			delete this.toolbar;
-			this.inherited(arguments);
-		},
-		addPlugin: function(/*String||Object*/plugin, /*Integer?*/index){
-			// summary:
-			//		takes a plugin name as a string or a plugin instance and
-			//		adds it to the toolbar and associates it with this editor
-			//		instance. The resulting plugin is added to the Editor's
-			//		plugins array. If index is passed, it's placed in the plugins
-			//		array at that index. No big magic, but a nice helper for
-			//		passing in plugin names via markup.
-			//
-			// plugin: String, args object or plugin instance
-			//
-			// args:
-			//		This object will be passed to the plugin constructor
-			//
-			// index: Integer
-			//		Used when creating an instance from
-			//		something already in this.plugins. Ensures that the new
-			//		instance is assigned to this.plugins at that index.
-			var args=dojo.isString(plugin)?{name:plugin}:plugin;
-			if(!args.setEditor){
-				var o={"args":args,"plugin":null,"editor":this};
-				dojo.publish(dijit._scopeName + ".Editor.getPlugin",[o]);
-				if(!o.plugin){
-					var pc = dojo.getObject(args.name);
-					if(pc){
-						o.plugin=new pc(args);
-					}
-				}
-				if(!o.plugin){
-					console.warn('Cannot find plugin',plugin);
-					return;
-				}
-				plugin=o.plugin;
-			}
-			if(arguments.length > 1){
-				this._plugins[index] = plugin;
-			}else{
-				this._plugins.push(plugin);
-			}
-			plugin.setEditor(this);
-			if(dojo.isFunction(plugin.setToolbar)){
-				plugin.setToolbar(this.toolbar);
-			}
-		},
-		//the following 3 functions are required to make the editor play nice under a layout widget, see #4070
-		startup: function(){
-			// summary:
-			//		Exists to make Editor work as a child of a layout widget.
-			//		Developers don't need to call this method.
-			// tags:
-			//		protected
-			//console.log('startup',arguments);
-		},
-		resize: function(size){
-			// summary:
-			//		Resize the editor to the specified size, see `dijit.layout._LayoutWidget.resize`
-			if(size){
-				// we've been given a height/width for the entire editor (toolbar + contents), calls layout()
-				// to split the allocated size between the toolbar and the contents
-				dijit.layout._LayoutWidget.prototype.resize.apply(this, arguments);
-			}
-			/*
-			else{
-				// do nothing, the editor is already laid out correctly.   The user has probably specified
-				// the height parameter, which was used to set a size on the iframe
-			}
-			*/
-		},
-		layout: function(){
-			// summary:
-			//		Called from `dijit.layout._LayoutWidget.resize`.  This shouldn't be called directly
-			// tags:
-			//		protected
-
-			// Converts the iframe (or rather the <div> surrounding it) to take all the available space
-			// except what's needed for the toolbar
-			this.editingArea.style.height = (this._contentBox.h - dojo.marginBox(this.toolbar.domNode).h)+"px";
-			if(this.iframe){
-				this.iframe.style.height="100%";
-			}
-			this._layoutMode = true;
-		},
-		_onIEMouseDown: function(/*Event*/ e){
-			// summary:
-			//		IE only to prevent 2 clicks to focus
-			// tags:
-			//		private
-
-			var outsideClientArea = this.document.body.componentFromPoint(e.x, e.y);
-			if(!outsideClientArea){
-				delete this._savedSelection; // new mouse position overrides old selection
-				if(e.target.tagName == "BODY"){
-					setTimeout(dojo.hitch(this, "placeCursorAtEnd"), 0);
-				}
-				this.inherited(arguments);
-			}
-		},
-		onBeforeActivate: function(e){
-			this._restoreSelection();
-		},
-		onBeforeDeactivate: function(e){
-			// summary:
-			//		Called on IE right before focus is lost.   Saves the selected range.
-			// tags:
-			//		private
-			if(this.customUndo){
-				this.endEditing(true);
-			}
-			//in IE, the selection will be lost when other elements get focus,
-			//let's save focus before the editor is deactivated
-			if(e.target.tagName != "BODY"){
-				this._saveSelection();
-			}
-			//console.log('onBeforeDeactivate',this);
-		},
-
-		/* beginning of custom undo/redo support */
-
-		// customUndo: Boolean
-		//		Whether we shall use custom undo/redo support instead of the native
-		//		browser support. By default, we only enable customUndo for IE, as it
-		//		has broken native undo/redo support. Note: the implementation does
-		//		support other browsers which have W3C DOM2 Range API implemented.
-		customUndo: dojo.isIE,
-
-		// editActionInterval: Integer
-		//		When using customUndo, not every keystroke will be saved as a step.
-		//		Instead typing (including delete) will be grouped together: after
-		//		a user stops typing for editActionInterval seconds, a step will be
-		//		saved; if a user resume typing within editActionInterval seconds,
-		//		the timeout will be restarted. By default, editActionInterval is 3
-		//		seconds.
-		editActionInterval: 3,
-
-		beginEditing: function(cmd){
-			// summary:
-			//		Called to note that the user has started typing alphanumeric characters, if it's not already noted.
-			//		Deals with saving undo; see editActionInterval parameter.
-			// tags:
-			//		private
-			if(!this._inEditing){
-				this._inEditing=true;
-				this._beginEditing(cmd);
-			}
-			if(this.editActionInterval>0){
-				if(this._editTimer){
-					clearTimeout(this._editTimer);
-				}
-				this._editTimer = setTimeout(dojo.hitch(this, this.endEditing), this._editInterval);
-			}
-		},
-		_steps:[],
-		_undoedSteps:[],
-		execCommand: function(cmd){
-			// summary:
-			//		Main handler for executing any commands to the editor, like paste, bold, etc.
-			//      Called by plugins, but not meant to be called by end users.
-			// tags:
-			//		protected
-			if(this.customUndo && (cmd == 'undo' || cmd == 'redo')){
-				return this[cmd]();
-			}else{
-				if(this.customUndo){
-					this.endEditing();
-					this._beginEditing();
-				}
-				var r;
-				try{
-					r = this.inherited('execCommand', arguments);
-					if(dojo.isWebKit && cmd == 'paste' && !r){ //see #4598: safari does not support invoking paste from js
-						throw { code: 1011 }; // throw an object like Mozilla's error
-					}
-				}catch(e){
-					//TODO: when else might we get an exception?  Do we need the Mozilla test below?
-					if(e.code == 1011 /* Mozilla: service denied */ && /copy|cut|paste/.test(cmd)){
-						// Warn user of platform limitation.  Cannot programmatically access clipboard. See ticket #4136
-						var sub = dojo.string.substitute,
-							accel = {cut:'X', copy:'C', paste:'V'};
-						alert(sub(this.commands.systemShortcut,
-							[this.commands[cmd], sub(this.commands[dojo.isMac ? 'appleKey' : 'ctrlKey'], [accel[cmd]])]));
-					}
-					r = false;
-				}
-				if(this.customUndo){
-					this._endEditing();
-				}
-				return r;
-			}
-		},
-		queryCommandEnabled: function(cmd){
-			// summary:
-			//		Returns true if specified editor command is enabled.
-			//      Used by the plugins to know when to highlight/not highlight buttons.
-			// tags:
-			//		protected
-			if(this.customUndo && (cmd == 'undo' || cmd == 'redo')){
-				return cmd == 'undo' ? (this._steps.length > 1) : (this._undoedSteps.length > 0);
-			}else{
-				return this.inherited('queryCommandEnabled',arguments);
-			}
-		},
-
-		_moveToBookmark: function(b){
-			// summary:
-			//		Selects the text specified in bookmark b
-			// tags:
-			//		private
-			var bookmark = b.mark;
-			var mark = b.mark;
-			var col = b.isCollapsed;
-			if(dojo.isIE){
-				if(dojo.isArray(mark)){//IE CONTROL
-					bookmark = [];
-					dojo.forEach(mark,function(n){
-						bookmark.push(dijit.range.getNode(n,this.editNode));
-					},this);
-				}
-			}else{//w3c range
-				var r=dijit.range.create(this.window);
-				r.setStart(dijit.range.getNode(b.startContainer,this.editNode),b.startOffset);
-				r.setEnd(dijit.range.getNode(b.endContainer,this.editNode),b.endOffset);
-				bookmark=r;
-			}
-			dojo.withGlobal(this.window,'moveToBookmark',dijit,[{mark: bookmark, isCollapsed: col}]);
-		},
-
-		_changeToStep: function(from, to){
-			// summary:
-			//		Reverts editor to "to" setting, from the undo stack.
-			// tags:
-			//		private
-			this.setValue(to.text);
-			var b=to.bookmark;
-			if(!b){ return; }
-			this._moveToBookmark(b);
-		},
-		undo: function(){
-			// summary:
-			//		Handler for editor undo (ex: ctrl-z) operation
-			// tags:
-			//		private
-//			console.log('undo');
-			this.endEditing(true);
-			var s=this._steps.pop();
-			if(this._steps.length>0){
-				this.focus();
-				this._changeToStep(s,this._steps[this._steps.length-1]);
-				this._undoedSteps.push(s);
-				this.onDisplayChanged();
-				return true;
-			}
-			return false;
-		},
-		redo: function(){
-			// summary:
-			//		Handler for editor redo (ex: ctrl-y) operation
-			// tags:
-			//		private
-
-//			console.log('redo');
-			this.endEditing(true);
-			var s=this._undoedSteps.pop();
-			if(s && this._steps.length>0){
-				this.focus();
-				this._changeToStep(this._steps[this._steps.length-1],s);
-				this._steps.push(s);
-				this.onDisplayChanged();
-				return true;
-			}
-			return false;
-		},
-		endEditing: function(ignore_caret){
-			// summary:
-			//		Called to note that the user has stopped typing alphanumeric characters, if it's not already noted.
-			//		Deals with saving undo; see editActionInterval parameter.
-			// tags:
-			//		private
-			if(this._editTimer){
-				clearTimeout(this._editTimer);
-			}
-			if(this._inEditing){
-				this._endEditing(ignore_caret);
-				this._inEditing=false;
-			}
-		},
-		_getBookmark: function(){
-			// summary:
-			//		Get the currently selected text
-			// tags:
-			//		protected
-			var b=dojo.withGlobal(this.window,dijit.getBookmark);
-			var tmp=[];
-			if(b.mark){
-				var mark = b.mark;
-				if(dojo.isIE){
-					if(dojo.isArray(mark)){//CONTROL
-						dojo.forEach(mark,function(n){
-							tmp.push(dijit.range.getIndex(n,this.editNode).o);
-						},this);
-						b.mark = tmp;
-					}
-				}else{//w3c range
-					tmp=dijit.range.getIndex(mark.startContainer,this.editNode).o;
-					b.mark ={startContainer:tmp,
-						startOffset:mark.startOffset,
-						endContainer:mark.endContainer === mark.startContainer?tmp:dijit.range.getIndex(mark.endContainer,this.editNode).o,
-						endOffset:mark.endOffset};
-				}
-			}
-			return b;
-		},
-		_beginEditing: function(cmd){
-			// summary:
-			//		Called when the user starts typing alphanumeric characters.
-			//		Deals with saving undo; see editActionInterval parameter.
-			// tags:
-			//		private
-			if(this._steps.length === 0){
-				this._steps.push({'text':this.savedContent,'bookmark':this._getBookmark()});
-			}
-		},
-		_endEditing: function(ignore_caret){
-			// summary:
-			//		Called when the user stops typing alphanumeric characters.
-			//		Deals with saving undo; see editActionInterval parameter.
-			// tags:
-			//		private
-			var v=this.getValue(true);
-
-			this._undoedSteps=[];//clear undoed steps
-			this._steps.push({text: v, bookmark: this._getBookmark()});
-		},
-		onKeyDown: function(e){
-			// summary:
-			//		Handler for onkeydown event.
-			// tags:
-			//		private
-
-			//We need to save selection if the user TAB away from this editor
-			//no need to call _saveSelection for IE, as that will be taken care of in onBeforeDeactivate
-			if(!dojo.isIE && !this.iframe && e.keyCode == dojo.keys.TAB && !this.tabIndent){
-				this._saveSelection();
-			}
-			if(!this.customUndo){
-				this.inherited(arguments);
-				return;
-			}
-			var k = e.keyCode, ks = dojo.keys;
-			if(e.ctrlKey && !e.altKey){//undo and redo only if the special right Alt + z/y are not pressed #5892
-				if(k == 90 || k == 122){ //z
-					dojo.stopEvent(e);
-					this.undo();
-					return;
-				}else if(k == 89 || k == 121){ //y
-					dojo.stopEvent(e);
-					this.redo();
-					return;
-				}
-			}
-			this.inherited(arguments);
-
-			switch(k){
-					case ks.ENTER:
-					case ks.BACKSPACE:
-					case ks.DELETE:
-						this.beginEditing();
-						break;
-					case 88: //x
-					case 86: //v
-						if(e.ctrlKey && !e.altKey && !e.metaKey){
-							this.endEditing();//end current typing step if any
-							if(e.keyCode == 88){
-								this.beginEditing('cut');
-								//use timeout to trigger after the cut is complete
-								setTimeout(dojo.hitch(this, this.endEditing), 1);
-							}else{
-								this.beginEditing('paste');
-								//use timeout to trigger after the paste is complete
-								setTimeout(dojo.hitch(this, this.endEditing), 1);
-							}
-							break;
-						}
-						//pass through
-					default:
-						if(!e.ctrlKey && !e.altKey && !e.metaKey && (e.keyCode<dojo.keys.F1 || e.keyCode>dojo.keys.F15)){
-							this.beginEditing();
-							break;
-						}
-						//pass through
-					case ks.ALT:
-						this.endEditing();
-						break;
-					case ks.UP_ARROW:
-					case ks.DOWN_ARROW:
-					case ks.LEFT_ARROW:
-					case ks.RIGHT_ARROW:
-					case ks.HOME:
-					case ks.END:
-					case ks.PAGE_UP:
-					case ks.PAGE_DOWN:
-						this.endEditing(true);
-						break;
-					//maybe ctrl+backspace/delete, so don't endEditing when ctrl is pressed
-					case ks.CTRL:
-					case ks.SHIFT:
-					case ks.TAB:
-						break;
-				}
-		},
-		_onBlur: function(){
-			// summary:
-			//		Called from focus manager when focus has moved away from this editor
-			// tags:
-			//		protected
-
-			//this._saveSelection();
-			this.inherited('_onBlur',arguments);
-			this.endEditing(true);
-		},
-		_saveSelection: function(){
-			// summary:
-			//		Save the currently selected text in _savedSelection attribute
-			// tags:
-			//		private
-			this._savedSelection=this._getBookmark();
-			//console.log('save selection',this._savedSelection,this);
-		},
-		_restoreSelection: function(){
-			// summary:
-			//		Re-select the text specified in _savedSelection attribute;
-			//		see _saveSelection().
-			// tags:
-			//		private
-			if(this._savedSelection){
-				// only restore the selection if the current range is collapsed
-				// if not collapsed, then it means the editor does not lose
-				// selection and there is no need to restore it
-				if(dojo.withGlobal(this.window,'isCollapsed',dijit)){
-					this._moveToBookmark(this._savedSelection);
-				}
-				delete this._savedSelection;
-			}
-		},
-
-		onClick: function(){
-			// summary:
-			//		Handler for when editor is clicked
-			// tags:
-			//		protected
-			this.endEditing(true);
-			this.inherited(arguments);
-		}
-		/* end of custom undo/redo support */
-	}
-);
-
-// Register the "default plugins", ie, the built-in editor commands
-dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
-	if(o.plugin){ return; }
-	var args = o.args, p;
-	var _p = dijit._editor._Plugin;
-	var name = args.name;
-	switch(name){
-		case "undo": case "redo": case "cut": case "copy": case "paste": case "insertOrderedList":
-		case "insertUnorderedList": case "indent": case "outdent": case "justifyCenter":
-		case "justifyFull": case "justifyLeft": case "justifyRight": case "delete":
-		case "selectAll": case "removeFormat": case "unlink":
-		case "insertHorizontalRule":
-			p = new _p({ command: name });
-			break;
-
-		case "bold": case "italic": case "underline": case "strikethrough":
-		case "subscript": case "superscript":
-			p = new _p({ buttonClass: dijit.form.ToggleButton, command: name });
-			break;
-		case "|":
-			p = new _p({ button: new dijit.ToolbarSeparator() });
-	}
-//	console.log('name',name,p);
-	o.plugin=p;
-});
-
-}
-
-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: dojo.cache("dijit", "templates/MenuItem.html", "<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\" dojo [...]
-
-		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);
-			var label = this.id+"_text";
-			dojo.attr(this.containerNode, "id", label);
-			if(this.accelKeyNode){
-				dojo.attr(this.accelKeyNode, "id", this.id + "_accel");
-				label += " " + this.id + "_accel";
-			}
-			dijit.setWaiState(this.domNode, "labelledby", label);
-		},
-
-		_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{
-				if(dojo.isIE == 8){
-					// needed for IE8 which won't scroll TR tags into view on focus yet calling scrollIntoView creates flicker (#10275)
-					this.containerNode.focus();
-				}
-				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);
-			this.getParent()._onItemFocus(this);
-
-			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){
-				// Destroy the popup, unless it's already been destroyed.  This can happen because
-				// the popup is a direct child of <body> even though it's logically my child.
-				if(!this.popup._destroyed){
-					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: dojo.cache("dijit", "templates/CheckedMenuItem.html", "<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=\"dijitCheckedMen [...]
-
-		// 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: dojo.cache("dijit", "templates/MenuSeparator.html", "<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();
-			}
-		}
-	},
-
-	_onPopupHover: function(/*Event*/ evt){
-		// summary:
-		//		This handler is called when the mouse moves over the popup.
-		// tags:
-		//		private
-
-		// if the mouse hovers over a menu popup that is in pending-close state,
-		// then stop the close operation.
-		// This can't be done in onItemHover since some popup targets don't have MenuItems (e.g. ColorPicker)
-		if(this.currentPopup && this.currentPopup._pendingClose_timer){
-			var parentMenu = this.currentPopup.parentMenu;
-			// highlight the parent menu item pointing to this popup
-			if(parentMenu.focusedChild){
-				parentMenu.focusedChild._setSelected(false);
-			}
-			parentMenu.focusedChild = this.currentPopup.from_item;
-			parentMenu.focusedChild._setSelected(true);
-			// cancel the pending close
-			this._stopPendingCloseTimer(this.currentPopup);
-		}
-	},
-
-	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) 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);
-			}
-		}
-		// if the user is mixing mouse and keyboard navigation,
-		// then the menu may not be active but a menu item has focus,
-		// but it's not the item that the mouse just hovered over.
-		// To avoid both keyboard and mouse selections, use the latest.
-		if(this.focusedChild){
-			this.focusChild(item);
-		}
-		this._hoveredChild = item;
-	},
-
-	_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
-		this._stopPopupTimer();
-		item._setSelected(false);
-		// Close all popups that are open and descendants of this menu
-		var itemPopup = item.popup;
-		if(itemPopup){
-			this._stopPendingCloseTimer(itemPopup);
-			itemPopup._pendingClose_timer = setTimeout(function(){
-				itemPopup._pendingClose_timer = null;
-				if(itemPopup.parentMenu){
-					itemPopup.parentMenu.currentPopup = null;
-				}
-				dijit.popup.close(itemPopup); // this calls onClose
-			}, this.popupDelay);
-		}
-	},
-
-	onItemUnhover: function(/*MenuItem*/ item){
-		// summary:
-		//		Callback fires when mouse exits a MenuItem
-		// tags:
-		//		protected
-
-		if(this.isActive){
-			this._stopPopupTimer();
-		}
-		if(this._hoveredChild == item){ this._hoveredChild = null; }
-	},
-
-	_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;
-		}
-	},
-
-	_stopPendingCloseTimer: function(/*dijit._Widget*/ popup){
-		// summary:
-		//		Cancels the pending-close timer because the close has been preempted
-		// tags:
-		//		private
-		if(popup._pendingClose_timer){
-			clearTimeout(popup._pendingClose_timer);
-			popup._pendingClose_timer = null;
-		}
-	},
-
-	_stopFocusTimer: function(){
-		// summary:
-		//		Cancels the pending-focus timer because the menu was closed before focus occured
-		// tags:
-		//		private
-		if(this._focus_timer){
-			clearTimeout(this._focus_timer);
-			this._focus_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(/*dijit._Widget*/ item, /*Event*/ evt){
-		// summary:
-		//		Handle clicks on an item.
-		// tags:
-		//		private
-		if(item.disabled){ return false; }
-
-		// this can't be done in _onFocus since the _onFocus events occurs asynchronously
-		if(typeof this.isShowingNow == 'undefined'){ // non-popup menu
-			this._markActive();
-		}
-
-		this.focusChild(item);
-
-		if(item.popup){
-			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;
-		if(!from_item){ return; } // the focused child lost focus since the timer was started
-		var popup = from_item.popup;
-		if(popup.isShowingNow){ return; }
-		if(this.currentPopup){
-			this._stopPendingCloseTimer(this.currentPopup);
-			dijit.popup.close(this.currentPopup);
-		}
-		popup.parentMenu = this;
-		popup.from_item = from_item; // helps finding the parent item that should be focused for this popup
-		var self = this;
-		dijit.popup.open({
-			parent: this,
-			popup: popup,
-			around: from_item.domNode,
-			orient: this._orient || (this.isLeftToRight() ?
-									{'TR': 'TL', 'TL': 'TR', 'BR': 'BL', 'BL': 'BR'} :
-									{'TL': 'TR', 'TR': 'TL', 'BL': 'BR', 'BR': 'BL'}),
-			onCancel: function(){ // called when the child menu is canceled
-				// set isActive=false (_closeChild vs _cleanUp) so that subsequent hovering will NOT open child menus
-				// which seems aligned with the UX of most applications (e.g. notepad, wordpad, paint shop pro)
-				self.focusChild(from_item);	// put focus back on my node
-				self._cleanUp();			// close the submenu (be sure this is done _after_ focus is moved)
-				from_item._setSelected(true); // oops, _cleanUp() deselected the item
-				self.focusedChild = from_item;	// and unset focusedChild
-			},
-			onExecute: dojo.hitch(this, "_cleanUp")
-		});
-
-		this.currentPopup = popup;
-		// detect mouseovers to handle lazy mouse movements that temporarily focus other menu items
-		popup.connect(popup.domNode, "onmouseenter", dojo.hitch(self, "_onPopupHover")); // cleaned up when the popped-up widget is destroyed on close
-
-		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)
-			popup._focus_timer = setTimeout(dojo.hitch(popup, function(){
-				this._focus_timer = null;
-				this.focus();
-			}), 0);
-		}
-	},
-
-	_markActive: function(){
-		// summary:
-		//              Mark this menu's state as active.
-		//		Called when this Menu gets focus from:
-		//			1) clicking it (mouse or via space/arrow key)
-		//			2) being opened by a parent menu.
-		//		This is not called just from mouse hover.
-		//		Focusing a menu via TAB does NOT automatically set isActive
-		//		since TAB is a navigation operation and not a selection one.
-		//		For Windows apps, pressing the ALT key focuses the menubar
-		//		menus (similar to TAB navigation) but the menu is not active
-		//		(ie no dropdown) until an item is clicked.
-		this.isActive = true;
-		dojo.addClass(this.domNode, "dijitMenuActive");
-		dojo.removeClass(this.domNode, "dijitMenuPassive");
-	},
-
-	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;
-		this._markActive();
-	},
-
-	_markInactive: function(){
-		// summary:
-		//		Mark this menu's state as inactive.
-		this.isActive = false; // don't do this in _onBlur since the state is pending-close until we get here
-		dojo.removeClass(this.domNode, "dijitMenuActive");
-		dojo.addClass(this.domNode, "dijitMenuPassive");
-	},
-
-	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._stopFocusTimer();
-		this._markInactive();
-		this.isShowingNow = false;
-		this.parentMenu = null;
-	},
-
-	_closeChild: function(){
-		// summary:
-		//		Called when submenu is clicked or focus is lost.  Close hierarchy of menus.
-		// tags:
-		//		private
-		this._stopPopupTimer();
-		if(this.focusedChild){ // unhighlight the focused item
-			this.focusedChild._setSelected(false);
-			this.focusedChild._onUnhover();
-			this.focusedChild = null;
-		}
-		if(this.currentPopup){
-			// Close all popups that are open and descendants of this menu
-			dijit.popup.close(this.currentPopup);
-			this.currentPopup = null;
-		}
-	},
-
-	_onItemFocus: function(/*MenuItem*/ item){
-		// summary:
-		//		Called when child of 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.
-		if(this._hoveredChild && this._hoveredChild != item){
-			this._hoveredChild._onUnhover(); // any previous mouse movement is trumped by focus selection
-		}
-	},
-
-	_onBlur: function(){
-		// summary:
-		//		Called when focus is moved away from this Menu and it's submenus.
-		// tags:
-		//		protected
-		this._cleanUp();
-		this.inherited(arguments);
-	},
-
-	_cleanUp: function(){
-		// summary:
-		//		Called when the user is done with this menu.  Closes hierarchy of menus.
-		// tags:
-		//		private
-
-		this._closeChild(); // don't call this.onClose since that's incorrect for MenuBar's that never close
-		if(typeof this.isShowingNow == 'undefined'){ // non-popup menu doesn't call onClose
-			this._markInactive();
-		}
-	}
-});
-
-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: dojo.cache("dijit", "templates/Menu.html", "<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,
-
-	// refocus: Boolean
-	// 		When this menu closes, re-focus the element which had focus before it was opened.
-	refocus: true,
-
-	// _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{
-			// TODO: should have _setTargetNodeIds() method to handle initialization and a possible
-			// later attr('targetNodeIds', ...) call.   There's also a problem that targetNodeIds[]
-			// gets stale after calls to bindDomNode()/unBindDomNode() as it still is just the original list (see #9610)
-			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(this._iframeContentDocument(iframe_el)) ||
-			// Moz. TODO: is this available when defaultView isn't?
-			this._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);
-
-		var cn;	// Connect node
-
-		// Support context menus on iframes.   Rather than binding to the iframe itself we need
-		// to bind to the <body> node inside the iframe.
-		if(node.tagName.toLowerCase() == "iframe"){
-			var iframe = node,
-				win = this._iframeContentWindow(iframe);
-			cn = dojo.withGlobal(win, dojo.body);
-		}else{
-			
-			// To capture these events at the top level, attach to <html>, not <body>.
-			// Otherwise right-click context menu just doesn't work.
-			cn = (node == dojo.body() ? dojo.doc.documentElement : node);
-		}
-
-
-		// "binding" is the object to track our connection to the node (ie, the parameter to bindDomNode())
-		var binding = {
-			node: node,
-			iframe: iframe
-		};
-
-		// Save info about binding in _bindings[], and make node itself record index(+1) into
-		// _bindings[] array.   Prefix w/_dijitMenu to avoid setting an attribute that may
-		// start with a number, which fails on FF/safari.
-		dojo.attr(node, "_dijitMenu" + this.id, this._bindings.push(binding));
-
-		// Setup the connections to monitor click etc., unless we are connecting to an iframe which hasn't finished
-		// loading yet, in which case we need to wait for the onload event first, and then connect
-		var doConnects = dojo.hitch(this, function(cn){
-			return [
-				dojo.connect(cn, (this.leftClickToOpen)?"onclick":"oncontextmenu", this, function(evt){
-					this._openMyself(evt, cn, iframe);
-				}),
-				dojo.connect(cn, "onkeydown", this, "_contextKey"),
-				dojo.connect(cn, "onmousedown", this, "_contextMouse")
-			];
-		});
-		binding.connects = cn ? doConnects(cn) : [];
-
-		if(iframe){
-			// Setup handler to [re]bind to the iframe when the contents are initially loaded,
-			// and every time the contents change.
-			// Need to do this b/c we are actually binding to the iframe's <body> node.
-			// Note: can't use dojo.connect(), see #9609.
-
-			binding.onloadHandler = dojo.hitch(this, function(){
-				// want to remove old connections, but IE throws exceptions when trying to
-				// access the <body> node because it's already gone, or at least in a state of limbo
-
-				var win = this._iframeContentWindow(iframe);
-					cn = dojo.withGlobal(win, dojo.body);
-				binding.connects = doConnects(cn);
-			});
-			if(iframe.addEventListener){
-				iframe.addEventListener("load", binding.onloadHandler, false);
-			}else{
-				iframe.attachEvent("onload", binding.onloadHandler);
-			}
-		}
-	},
-
-	unBindDomNode: function(/*String|DomNode*/ nodeName){
-		// summary:
-		//		Detach menu from given node
-
-		var node;
-		try{
-			node = dojo.byId(nodeName);
-		}catch(e){
-			// On IE the dojo.byId() call will get an exception if the attach point was
-			// the <body> node of an <iframe> that has since been reloaded (and thus the
-			// <body> node is in a limbo state of destruction.
-			return;
-		}
-
-		// node["_dijitMenu" + this.id] contains index(+1) into my _bindings[] array
-		var attrName = "_dijitMenu" + this.id;
-		if(node && dojo.hasAttr(node, attrName)){
-			var bid = dojo.attr(node, attrName)-1, b = this._bindings[bid];
-			dojo.forEach(b.connects, dojo.disconnect);
-
-			// Remove listener for iframe onload events
-			var iframe = b.iframe;
-			if(iframe){
-				if(iframe.removeEventListener){
-					iframe.removeEventListener("load", b.onloadHandler, false);
-				}else{
-					iframe.detachEvent("onload", b.onloadHandler);
-				}
-			}
-
-			dojo.removeAttr(node, attrName);
-			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, /*DomNode?*/ node, /*DomNode?*/ iframe){
-		// summary:
-		//		Internal function for opening myself when the user
-		//		does a right-click or something similar.
-		// node:
-		//		The node that is being clicked
-		// iframe:
-		//		If an <iframe> is being clicked, iframe points to that iframe and node
-		//		points to the iframe's body.
-		// 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;
-
-			if(iframe){
-				// Event is on <body> node of an <iframe>, convert coordinates to match main document
-				var od = e.target.ownerDocument,
-					ifc = dojo.position(iframe, true),
-					win = this._iframeContentWindow(iframe),
-					scroll = dojo.withGlobal(win, "_docScroll", dojo);
-
-				var cs = dojo.getComputedStyle(iframe),
-					tp = dojo._toPixelValue,
-					left = (dojo.isIE && dojo.isQuirks ? 0 : tp(iframe, cs.paddingLeft)) + (dojo.isIE && dojo.isQuirks ? tp(iframe, cs.borderLeftWidth) : 0),
-					top = (dojo.isIE && dojo.isQuirks ? 0 : tp(iframe, cs.paddingTop)) + (dojo.isIE && dojo.isQuirks ? tp(iframe, cs.borderTopWidth) : 0);
-
-				x += ifc.x + left - scroll.x;
-				y += ifc.y + top - scroll.y;
-			}
-		}else{
-			// otherwise open near e.target
-			var coords = dojo.position(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
-			if(self.refocus){
-				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._bindings, function(b){ if(b){ this.unBindDomNode(b.node); } }, this);
- 		this.inherited(arguments);
-	}
-}
-);
-
-// Back-compat (TODO: remove in 2.0)
-
-
-
-
-
-
-}
-
-if(!dojo._hasResource["dijit.MenuBar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.MenuBar"] = true;
-dojo.provide("dijit.MenuBar");
-
-
-
-dojo.declare("dijit.MenuBar", dijit._MenuBase, {
-	// summary:
-	//		A menu bar, listing menu choices horizontally, like the "File" menu in most desktop applications
-
-	templateString: dojo.cache("dijit", "templates/MenuBar.html", "<div class=\"dijitMenuBar dijitMenuPassive\" dojoAttachPoint=\"containerNode\"  waiRole=\"menubar\" tabIndex=\"${tabIndex}\" dojoAttachEvent=\"onkeypress: _onKeyPress\"></div>\n"),
-
-	// _isMenuBar: [protected] Boolean
-	//		This is a MenuBar widget, not a (vertical) Menu widget.
-	_isMenuBar: true,
-
-	constructor: function(){
-		// summary:
-		//		Sets up local variables etc.
-		// tags:
-		//		private
-
-		// parameter to dijit.popup.open() about where to put popup (relative to this.domNode)
-		this._orient = this.isLeftToRight() ? {BL: 'TL'} : {BR: 'TR'};
-	},
-
-	postCreate: function(){
-		var k = dojo.keys, l = this.isLeftToRight();
-		this.connectKeyNavHandlers(
-			l ? [k.LEFT_ARROW] : [k.RIGHT_ARROW],
-			l ? [k.RIGHT_ARROW] : [k.LEFT_ARROW]
-		);
-	},
-
-	focusChild: function(item){
-		// overload focusChild so that whenever the focus is moved to a new item,
-		// check the previous focused whether it has its popup open, if so, after
-		// focusing the new item, open its submenu immediately
-		var prev_item = this.focusedChild,
-			showpopup = prev_item && prev_item.popup && prev_item.popup.isShowingNow;
-		this.inherited(arguments);
-		if(showpopup && item.popup && !item.disabled){
-			this._openPopup();		// TODO: on down arrow, _openPopup() is called here and in onItemClick()
-		}
-	},
-
-	_onKeyPress: function(/*Event*/ evt){
-		// summary:
-		//		Handle keyboard based menu navigation.
-		// tags:
-		//		protected
-
-		if(evt.ctrlKey || evt.altKey){ return; }
-
-		switch(evt.charOrCode){
-			case dojo.keys.DOWN_ARROW:
-				this._moveToPopup(evt);
-				dojo.stopEvent(evt);
-		}
-	},
-
-	onItemClick: function(/*dijit._Widget*/ item, /*Event*/ evt){
-		// summary:
-		//		Handle clicks on an item. Cancels a dropdown if already open.
-		// tags:
-		//		private
-		if(item.popup && item.popup.isShowingNow){
-			item.popup.onCancel();
-		}else{
-			this.inherited(arguments);
-		}
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.MenuBarItem"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.MenuBarItem"] = true;
-dojo.provide("dijit.MenuBarItem");
-
-
-
-dojo.declare("dijit._MenuBarItemMixin", null, {
-	templateString: dojo.cache("dijit", "templates/MenuBarItem.html", "<div class=\"dijitReset dijitInline dijitMenuItem dijitMenuItemLabel\" dojoAttachPoint=\"focusNode\" waiRole=\"menuitem\" tabIndex=\"-1\"'\n\t\tdojoAttachEvent=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<span dojoAttachPoint=\"containerNode\"></span>\n</div>\n"),
-
-	// overriding attributeMap because we don't have icon
-	attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-		label: { node: "containerNode", type: "innerHTML" }
-	})
-});
-
-dojo.declare("dijit.MenuBarItem", [dijit.MenuItem, dijit._MenuBarItemMixin], {
-	// summary:
-	//		Item in a MenuBar that's clickable, and doesn't spawn a submenu when pressed (or hovered)
-
-});
-
-}
-
-if(!dojo._hasResource["dijit.PopupMenuBarItem"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.PopupMenuBarItem"] = true;
-dojo.provide("dijit.PopupMenuBarItem");
-
-
-
-
-dojo.declare("dijit.PopupMenuBarItem", [dijit.PopupMenuItem, dijit._MenuBarItemMixin], {
-	// summary:
-	//		Item in a MenuBar like "File" or "Edit", that spawns a submenu when pressed (or hovered)
-});
-
-
-}
-
-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.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.  Default value is based on locale.  Overriding this property will defeat
-	//		localization.
-	//	type: String?
-	//		choose a format type based on the locale from the following:
-	//		decimal, scientific (not yet supported), 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.
-	//	locale: String?
-	//		override the locale used to determine formatting rules
-	this.pattern = pattern;
-	this.type = type;
-	this.places = places;
-	this.round = round;
-	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: Number?|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 [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
-	//		with this string.  Default value is based on locale.  Overriding this property will defeat
-	//		localization.
-	//	type: String?
-	//		choose a format type based on the locale from the following:
-	//		decimal, scientific (not yet supported), percent, currency. decimal by default.
-	//	locale: String?
-	//		override the locale used to determine formatting rules
-	//	strict: Boolean?
-	//		strict parsing, false by default.  Strict parsing requires input as produced by the format() method.
-	//		Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
-	//	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 [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
-	//		with this string.  Default value is based on locale.  Overriding this property will defeat
-	//		localization.
-	//	type: String?
-	//		choose a format type based on the locale from the following:
-	//		decimal, scientific (not yet supported), percent, currency. decimal by default.
-	//	locale: String?
-	//		override the locale used to determine formatting rules
-	//	strict: Boolean?
-	//		strict parsing, false by default.  Strict parsing requires input as produced by the format() method.
-	//		Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
-	this.pattern = pattern;
-	this.type = type;
-	this.locale = locale;
-	this.strict = strict;
-}
-=====*/
-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 used.  Can be true, false, or [true,
-	//		false].  Default is [true, false] which means optional.
-	//	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.ProgressBar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.ProgressBar"] = true;
-dojo.provide("dijit.ProgressBar");
-
-
-
-
-
-
-
-dojo.declare("dijit.ProgressBar", [dijit._Widget, dijit._Templated], {
-	// summary:
-	//		A progress indication widget, showing the amount completed
-	//		(often the percentage completed) of a task.
-	//
-	// example:
-	// |	<div dojoType="ProgressBar"
-	// |		 places="0"
-	// |		 progress="..." maximum="...">
-	// |	</div>
-	//
-	// description:
-	//		Note that the progress bar is updated via (a non-standard)
-	//		update() method, rather than via attr() like other widgets.
-
-	// progress: [const] String (Percentage or Number)
-	//		Number or percentage indicating amount of task completed.
-	// 		With "%": percentage value, 0% <= progress <= 100%, or
-	// 		without "%": absolute value, 0 <= progress <= maximum
-	// TODO: rename to value for 2.0
-	progress: "0",
-
-	// maximum: [const] Float
-	//		Max sample number
-	maximum: 100,
-
-	// places: [const] Number
-	//		Number of places to show in values; 0 by default
-	places: 0,
-
-	// indeterminate: [const] Boolean
-	// 		If false: show progress value (number or percentage).
-	// 		If true: show that a process is underway but that the amount completed is unknown.
-	indeterminate: false,
-
-	// name: String
-	//		this is the field name (for a form) if set. This needs to be set if you want to use
-	//		this widget in a dijit.form.Form widget (such as dijit.Dialog)
-	name: '',
-
-	templateString: dojo.cache("dijit", "templates/ProgressBar.html", "<div class=\"dijitProgressBar dijitProgressBarEmpty\"\n\t><div waiRole=\"progressbar\" dojoAttachPoint=\"internalProgress\" class=\"dijitProgressBarFull\"\n\t\t><div class=\"dijitProgressBarTile\"></div\n\t\t><span style=\"visibility:hidden\"> </span\n\t></div\n\t><div dojoAttachPoint=\"label\" class=\"dijitProgressBarLabel\" id=\"${id}_label\"> </div\n\t><img dojoAttachPoint=\"indeterminateHighContrastImage\"  [...]
-
-	// _indeterminateHighContrastImagePath: [private] dojo._URL
-	//		URL to image to use for indeterminate progress bar when display is in high contrast mode
-	_indeterminateHighContrastImagePath:
-		dojo.moduleUrl("dijit", "themes/a11y/indeterminate_progress.gif"),
-
-	// public functions
-	postCreate: function(){
-		this.inherited(arguments);
-		this.indeterminateHighContrastImage.setAttribute("src",
-			this._indeterminateHighContrastImagePath.toString());
-		this.update();
-	},
-
-	update: function(/*Object?*/attributes){
-		// summary:
-		//		Change attributes of ProgressBar, similar to attr(hash).
-		//
-		// attributes:
-		//		May provide progress and/or maximum properties on this parameter;
-		//		see attribute specs for details.
-		//
-		// example:
-		//	|	myProgressBar.update({'indeterminate': true});
-		//	|	myProgressBar.update({'progress': 80});
-
-		// TODO: deprecate this method and use attr() instead
-
-		dojo.mixin(this, attributes || {});
-		var tip = this.internalProgress;
-		var percent = 1, classFunc;
-		if(this.indeterminate){
-			classFunc = "addClass";
-			dijit.removeWaiState(tip, "valuenow");
-			dijit.removeWaiState(tip, "valuemin");
-			dijit.removeWaiState(tip, "valuemax");
-		}else{
-			classFunc = "removeClass";
-			if(String(this.progress).indexOf("%") != -1){
-				percent = Math.min(parseFloat(this.progress)/100, 1);
-				this.progress = percent * this.maximum;
-			}else{
-				this.progress = Math.min(this.progress, this.maximum);
-				percent = this.progress / this.maximum;
-			}
-			var text = this.report(percent);
-			this.label.firstChild.nodeValue = text;
-			dijit.setWaiState(tip, "describedby", this.label.id);
-			dijit.setWaiState(tip, "valuenow", this.progress);
-			dijit.setWaiState(tip, "valuemin", 0);
-			dijit.setWaiState(tip, "valuemax", this.maximum);
-		}
-		dojo[classFunc](this.domNode, "dijitProgressBarIndeterminate");
-		tip.style.width = (percent * 100) + "%";
-		this.onChange();
-	},
-
-	_setValueAttr: function(v){
-		if(v == Infinity){
-			this.update({indeterminate:true});
-		}else{
-			this.update({indeterminate:false, progress:v});
-		}
-	},
-
-	_getValueAttr: function(){
-		return this.progress;
-	},
-
-	report: function(/*float*/percent){
-		// summary:
-		//		Generates message to show inside progress bar (normally indicating amount of task completed).
-		//		May be overridden.
-		// tags:
-		//		extension
-
-		return dojo.number.format(percent, { type: "percent", places: this.places, locale: this.lang });
-	},
-
-	onChange: function(){
-		// summary:
-		//		Callback fired when progress updates.
-		// tags:
-		//		progress
-	}
-});
-
-}
-
-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 useful 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,
-
-	// toggleable: Boolean
-	//		Whether pane can be opened or closed by clicking the title bar.
-	toggleable: true,
-
-	// tabIndex: String
-	//		Tabindex setting for the title (so users can tab to the title then
-	//		use space/enter to open/close the title pane)
-	tabIndex: "0",
-
-	// duration: Integer
-	//		Time in milliseconds to fade in/fade out
-	duration: dijit.defaultDuration,
-
-	// baseClass: [protected] String
-	//		The root className to be placed on this widget's domNode.
-	baseClass: "dijitTitlePane",
-
-	templateString: dojo.cache("dijit", "templates/TitlePane.html", "<div class=\"${baseClass}\">\n\t<div dojoAttachEvent=\"onclick:_onTitleClick, onkeypress:_onTitleKey, onfocus:_handleFocus, onblur:_handleFocus, onmouseenter:_onTitleEnter, onmouseleave:_onTitleLeave\"\n\t\t\tclass=\"dijitTitlePaneTitle\" dojoAttachPoint=\"titleBarNode,focusNode\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" dojoAttachPoint=\"arrowNode\" class=\"dijitArrowNode\" waiRole=\"presentation\"\n\t\t><span dojoAttachP [...]
-
-	attributeMap: dojo.delegate(dijit.layout.ContentPane.prototype.attributeMap, {
-		title: { node: "titleNode", type: "innerHTML" },
-		tooltip: {node: "focusNode", type: "attribute", attribute: "title"},	// focusNode spans the entire width, titleNode doesn't
-		id:""
-	}),
-
-	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,"hidden", this.open ? "false" : "true");
-		dijit.setWaiState(this.focusNode, "pressed", this.open ? "true" : "false");
-
-		// 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(); }
-	},
-
-	_setToggleableAttr: function(/* Boolean */ canToggle){
-		// summary:
-		//		Hook to make attr("canToggle", boolean) work.
-		// canToggle: Boolean
-		//		True to allow user to open/close pane by clicking title bar.
-		this.toggleable = canToggle;
-		dijit.setWaiRole(this.focusNode, canToggle ? "button" : "heading");
-		dojo.attr(this.focusNode, "tabIndex", canToggle ? this.tabIndex : "-1");
-		if(canToggle){
-			// TODO: if canToggle is switched from true false shouldn't we remove this setting?
-			dijit.setWaiState(this.focusNode, "controls", this.id+"_pane");
-		}
-		this._setCss();
-	},
-
-	_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;
-		dijit.setWaiState(this.containerNode, "hidden", this.open ? "false" : "true");
-		dijit.setWaiState(this.focusNode, "pressed", this.open ? "true" : "false");
-
-		// 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)
-		if(this.open){
-			this._onShow();
-		}else{
-			this.onHide();
-		}
-
-		this._setCss();
-	},
-
-	_setCss: function(){
-		// summary:
-		//		Set the open/close css state for the TitlePane
-		// tags:
-		//		private
-
-		var node = this.titleBarNode || this.focusNode;
-
-		if(this._titleBarClass){
-			dojo.removeClass(node, this._titleBarClass);
-		}
-		this._titleBarClass = "dijit" + (this.toggleable ? "" : "Fixed") + (this.open ? "Open" : "Closed");
-		dojo.addClass(node, this._titleBarClass);
-		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 == ' '){
-			if(this.toggleable){
-				this.toggle();
-			}
-			dojo.stopEvent(e);
-		}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
-		if(this.toggleable){
-			dojo.addClass(this.focusNode, "dijitTitlePaneTitle-hover");
-		}
-	},
-
-	_onTitleLeave: function(){
-		// summary:
-		//		Handler when someone stops hovering over my title
-		// tags:
-		//		private
-		if(this.toggleable){
-			dojo.removeClass(this.focusNode, "dijitTitlePaneTitle-hover");
-		}
-	},
-
-	_onTitleClick: function(){
-		// summary:
-		//		Handler when user clicks the title bar
-		// tags:
-		//		private
-		if(this.toggleable){
-			this.toggle();
-		}
-	},
-
-	_handleFocus: function(/*Event*/ e){
-		// summary:
-		//		Handle blur and focus events on title bar
-		// tags:
-		//		private
-
-		dojo.toggleClass(this.focusNode, this.baseClass + "Focused", e.type == "focus");
-	},
-
-	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.attr("title", title);
-	}
-});
-
-}
-
-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: dojo.cache("dijit", "templates/Tooltip.html", "<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";
-
-			var pos = dijit.placeOnScreenAroundElement(this.domNode, aroundNode, dijit.getPopupAroundAlignment((position && position.length) ? position : dijit.Tooltip.defaultPosition, this.isLeftToRight()), 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: [],
-
-		constructor: function(){
-			// Map id's of nodes I'm connected to to a list of the this.connect() handles
-			this._nodeConnectionsById = {};
-		},
-
-		_setConnectIdAttr: function(newIds){
-			for(var oldId in this._nodeConnectionsById){
-				this.removeTarget(oldId);
-			}
-			dojo.forEach(dojo.isArrayLike(newIds) ? newIds : [newIds], this.addTarget, this);
-		},
-
-		_getConnectIdAttr: function(){
-			var ary = [];
-			for(var id in this._nodeConnectionsById){
-				ary.push(id);
-			}
-			return ary;
-		},
-
-		addTarget: function(/*DOMNODE || String*/ id){
-			// summary:
-			//		Attach tooltip to specified node, if it's not already connected
-			var node = dojo.byId(id);
-			if(!node){ return; }
-			if(node.id in this._nodeConnectionsById){ return; }//Already connected
-
-			this._nodeConnectionsById[node.id] = [
-				this.connect(node, "onmouseenter", "_onTargetMouseEnter"),
-				this.connect(node, "onmouseleave", "_onTargetMouseLeave"),
-				this.connect(node, "onfocus", "_onTargetFocus"),
-				this.connect(node, "onblur", "_onTargetBlur")
-			];
-			if(dojo.isIE && !node.style.zoom){//preserve zoom
-				// BiDi workaround
-				node.style.zoom = 1;
-			}
-		},
-
-		removeTarget: function(/*DOMNODE || String*/ node){
-			// summary:
-			//		Detach tooltip from specified node
-
-			// map from DOMNode back to plain id string
-			var id = node.id || node;
-
-			if(id in this._nodeConnectionsById){
-				dojo.forEach(this._nodeConnectionsById[id], this.disconnect, this);
-				delete this._nodeConnectionsById[id];
-			}
-		},
-
-		postCreate: function(){
-			dojo.addClass(this.domNode,"dijitTooltipData");
-		},
-
-		startup: function(){
-			this.inherited(arguments);
-
-			// If this tooltip was created in a template, or for some other reason the specified connectId[s]
-			// didn't exist during the widget's initialization, then connect now.
-			var ids = this.connectId;
-			dojo.forEach(dojo.isArrayLike(ids) ? ids : [ids], this.addTarget, this);
-		},
-
-		_onTargetMouseEnter: function(/*Event*/ e){
-			// summary:
-			//		Handler for mouseenter event on the target node
-			// tags:
-			//		private
-			this._onHover(e);
-		},
-
-		_onTargetMouseLeave: function(/*Event*/ e){
-			// summary:
-			//		Handler for mouseleave event on the target node
-			// tags:
-			//		private
-			this._onUnHover(e);
-		},
-
-		_onTargetFocus: function(/*Event*/ e){
-			// summary:
-			//		Handler for focus event on the target node
-			// tags:
-			//		private
-
-			this._focus = true;
-			this._onHover(e);
-		},
-
-		_onTargetBlur: function(/*Event*/ e){
-			// summary:
-			//		Handler for blur event on the target node
-			// tags:
-			//		private
-
-			this._focus = false;
-			this._onUnHover(e);
-		},
-
-		_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
-
-			if(this._showTimer){
-				clearTimeout(this._showTimer);
-				delete this._showTimer;
-			}
-			dijit.showTooltip(this.label || this.domNode.innerHTML, target, this.position);
-
-			this._connectNode = target;
-			this.onShow(target, this.position);
-		},
-
-		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;
-				this.onHide();
-			}
-			if(this._showTimer){
-				// if tooltip is scheduled to be shown (after a brief delay)
-				clearTimeout(this._showTimer);
-				delete this._showTimer;
-			}
-		},
-
-		onShow: function(target, position){
-			// summary:
-			//		Called when the tooltip is shown
-			// tags:
-			//		callback
-		},
-
-		onHide: function(){
-			// summary:
-			//		Called when the tooltip is hidden
-			// tags:
-			//		callback
-		},
-
-		uninitialize: function(){
-			this.close();
-			this.inherited(arguments);
-		}
-	}
-);
-
-// 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["dojo.DeferredList"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.DeferredList"] = true;
-dojo.provide("dojo.DeferredList");
-dojo.declare("dojo.DeferredList", dojo.Deferred, {
-	constructor: function(/*Array*/ list, /*Boolean?*/ fireOnOneCallback, /*Boolean?*/ fireOnOneErrback, /*Boolean?*/ consumeErrors, /*Function?*/ canceller){
-		// summary:
-		//		Provides event handling for a group of Deferred objects.
-		// description:
-		//		DeferredList takes an array of existing deferreds and returns a new deferred of its own
-		//		this new deferred will typically have its callback fired when all of the deferreds in
-		//		the given list have fired their own deferreds.  The parameters `fireOnOneCallback` and
-		//		fireOnOneErrback, will fire before all the deferreds as appropriate
-		//
-		//	list:
-		//		The list of deferreds to be synchronizied with this DeferredList
-		//	fireOnOneCallback:
-		//		Will cause the DeferredLists callback to be fired as soon as any
-		//		of the deferreds in its list have been fired instead of waiting until
-		//		the entire list has finished
-		//	fireonOneErrback:
-		//		Will cause the errback to fire upon any of the deferreds errback
-		//	canceller:
-		//		A deferred canceller function, see dojo.Deferred
-		this.list = list;
-		this.resultList = new Array(this.list.length);
-
-		// Deferred init
-		this.chain = [];
-		this.id = this._nextId();
-		this.fired = -1;
-		this.paused = 0;
-		this.results = [null, null];
-		this.canceller = canceller;
-		this.silentlyCancelled = false;
-
-		if(this.list.length === 0 && !fireOnOneCallback){
-			this.callback(this.resultList);
-		}
-
-		this.finishedCount = 0;
-		this.fireOnOneCallback = fireOnOneCallback;
-		this.fireOnOneErrback = fireOnOneErrback;
-		this.consumeErrors = consumeErrors;
-
-		dojo.forEach(this.list, function(d, index){
-			d.addCallback(this, function(r){ this._cbDeferred(index, true, r); return r; });
-			d.addErrback(this, function(r){ this._cbDeferred(index, false, r); return r; });
-		}, this);
-	},
-
-	_cbDeferred: function(index, succeeded, result){
-		// summary:
-		//	The DeferredLists' callback handler
-
-		this.resultList[index] = [succeeded, result]; this.finishedCount += 1;
-		if(this.fired !== 0){
-			if(succeeded && this.fireOnOneCallback){
-				this.callback([index, result]);
-			}else if(!succeeded && this.fireOnOneErrback){
-				this.errback(result);
-			}else if(this.finishedCount == this.list.length){
-				this.callback(this.resultList);
-			}
-		}
-		if(!succeeded && this.consumeErrors){
-			result = null;
-		}
-		return result;
-	},
-
-	gatherResults: function(deferredList){
-		// summary:	
-		//	Gathers the results of the deferreds for packaging
-		//	as the parameters to the Deferred Lists' callback
-
-		var d = new dojo.DeferredList(deferredList, false, true, false);
-		d.addCallback(function(results){
-			var ret = [];
-			dojo.forEach(results, function(result){
-				ret.push(result[1]);
-			});
-			return ret;
-		});
-		return d;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojo.cookie"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.cookie"] = true;
-dojo.provide("dojo.cookie");
-
-
-
-/*=====
-dojo.__cookieProps = function(){
-	//	expires: Date|String|Number?
-	//		If a number, the number of days from today at which the cookie
-	//		will expire. If a date, the date past which the cookie will expire.
-	//		If expires is in the past, the cookie will be deleted.
-	//		If expires is omitted or is 0, the cookie will expire when the browser closes. << FIXME: 0 seems to disappear right away? FF3.
-	//	path: String?
-	//		The path to use for the cookie.
-	//	domain: String?
-	//		The domain to use for the cookie.
-	//	secure: Boolean?
-	//		Whether to only send the cookie on secure connections
-	this.expires = expires;
-	this.path = path;
-	this.domain = domain;
-	this.secure = secure;
-}
-=====*/
-
-
-dojo.cookie = function(/*String*/name, /*String?*/value, /*dojo.__cookieProps?*/props){
-	//	summary: 
-	//		Get or set a cookie.
-	//	description:
-	// 		If one argument is passed, returns the value of the cookie
-	// 		For two or more arguments, acts as a setter.
-	//	name:
-	//		Name of the cookie
-	//	value:
-	//		Value for the cookie
-	//	props: 
-	//		Properties for the cookie
-	//	example:
-	//		set a cookie with the JSON-serialized contents of an object which
-	//		will expire 5 days from now:
-	//	|	dojo.cookie("configObj", dojo.toJson(config), { expires: 5 });
-	//	
-	//	example:
-	//		de-serialize a cookie back into a JavaScript object:
-	//	|	var config = dojo.fromJson(dojo.cookie("configObj"));
-	//	
-	//	example:
-	//		delete a cookie:
-	//	|	dojo.cookie("configObj", null, {expires: -1});
-	var c = document.cookie;
-	if(arguments.length == 1){
-		var matches = c.match(new RegExp("(?:^|; )" + dojo.regexp.escapeString(name) + "=([^;]*)"));
-		return matches ? decodeURIComponent(matches[1]) : undefined; // String or undefined
-	}else{
-		props = props || {};
-// FIXME: expires=0 seems to disappear right away, not on close? (FF3)  Change docs?
-		var exp = props.expires;
-		if(typeof exp == "number"){ 
-			var d = new Date();
-			d.setTime(d.getTime() + exp*24*60*60*1000);
-			exp = props.expires = d;
-		}
-		if(exp && exp.toUTCString){ props.expires = exp.toUTCString(); }
-
-		value = encodeURIComponent(value);
-		var updatedCookie = name + "=" + value, propName;
-		for(propName in props){
-			updatedCookie += "; " + propName;
-			var propValue = props[propName];
-			if(propValue !== true){ updatedCookie += "=" + propValue; }
-		}
-		document.cookie = updatedCookie;
-	}
-};
-
-dojo.cookie.isSupported = function(){
-	//	summary:
-	//		Use to determine if the current browser supports cookies or not.
-	//		
-	//		Returns true if user allows cookies.
-	//		Returns false if user doesn't allow cookies.
-
-	if(!("cookieEnabled" in navigator)){
-		this("__djCookieTest__", "CookiesAllowed");
-		navigator.cookieEnabled = this("__djCookieTest__") == "CookiesAllowed";
-		if(navigator.cookieEnabled){
-			this("__djCookieTest__", "", {expires: -1});
-		}
-	}
-	return navigator.cookieEnabled;
-};
-
-}
-
-if(!dojo._hasResource["dijit.tree.TreeStoreModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.tree.TreeStoreModel"] = true;
-dojo.provide("dijit.tree.TreeStoreModel");
-
-dojo.declare(
-		"dijit.tree.TreeStoreModel",
-		null,
-	{
-		// summary:
-		//		Implements dijit.Tree.model connecting to a store with a single
-		//		root item.  Any methods passed into the constructor will override
-		//		the ones defined here.
-
-		// store: dojo.data.Store
-		//		Underlying store
-		store: null,
-
-		// childrenAttrs: String[]
-		//		One or more attribute names (attributes in the dojo.data item) that specify that item's children
-		childrenAttrs: ["children"],
-
-		// newItemIdAttr: String
-		//		Name of attribute in the Object passed to newItem() that specifies the id.
-		//
-		//		If newItemIdAttr is set then it's used when newItem() is called to see if an
-		//		item with the same id already exists, and if so just links to the old item
-		//		(so that the old item ends up with two parents).
-		//
-		//		Setting this to null or "" will make every drop create a new item.
-		newItemIdAttr: "id",
-
-		// labelAttr: String
-		//		If specified, get label for tree node from this attribute, rather
-		//		than by calling store.getLabel()
-		labelAttr: "",
-
-	 	// root: [readonly] dojo.data.Item
-		//		Pointer to the root item (read only, not a parameter)
-		root: null,
-
-		// query: anything
-		//		Specifies datastore query to return the root item for the tree.
-		//		Must only return a single item.   Alternately can just pass in pointer
-		//		to root item.
-		// example:
-		//	|	{id:'ROOT'}
-		query: null,
-
-		// deferItemLoadingUntilExpand: Boolean
-		//		Setting this to true will cause the TreeStoreModel to defer calling loadItem on nodes
-		// 		until they are expanded. This allows for lazying loading where only one
-		//		loadItem (and generally one network call, consequently) per expansion
-		// 		(rather than one for each child).
-		// 		This relies on partial loading of the children items; each children item of a
-		// 		fully loaded item should contain the label and info about having children.
-		deferItemLoadingUntilExpand: false,
-
-		constructor: function(/* Object */ args){
-			// summary:
-			//		Passed the arguments listed above (store, etc)
-			// tags:
-			//		private
-
-			dojo.mixin(this, args);
-
-			this.connects = [];
-
-			var store = this.store;
-			if(!store.getFeatures()['dojo.data.api.Identity']){
-				throw new Error("dijit.Tree: store must support dojo.data.Identity");
-			}
-
-			// if the store supports Notification, subscribe to the notification events
-			if(store.getFeatures()['dojo.data.api.Notification']){
-				this.connects = this.connects.concat([
-					dojo.connect(store, "onNew", this, "onNewItem"),
-					dojo.connect(store, "onDelete", this, "onDeleteItem"),
-					dojo.connect(store, "onSet", this, "onSetItem")
-				]);
-			}
-		},
-
-		destroy: function(){
-			dojo.forEach(this.connects, dojo.disconnect);
-			// TODO: should cancel any in-progress processing of getRoot(), getChildren()
-		},
-
-		// =======================================================================
-		// Methods for traversing hierarchy
-
-		getRoot: function(onItem, onError){
-			// summary:
-			//		Calls onItem with the root item for the tree, possibly a fabricated item.
-			//		Calls onError on error.
-			if(this.root){
-				onItem(this.root);
-			}else{
-				this.store.fetch({
-					query: this.query,
-					onComplete: dojo.hitch(this, function(items){
-						if(items.length != 1){
-							throw new Error(this.declaredClass + ": query " + dojo.toJson(this.query) + " returned " + items.length +
-							 	" items, but must return exactly one item");
-						}
-						this.root = items[0];
-						onItem(this.root);
-					}),
-					onError: onError
-				});
-			}
-		},
-
-		mayHaveChildren: function(/*dojo.data.Item*/ item){
-			// summary:
-			//		Tells if an item has or may have children.  Implementing logic here
-			//		avoids showing +/- expando icon for nodes that we know don't have children.
-			//		(For efficiency reasons we may not want to check if an element actually
-			//		has children until user clicks the expando node)
-			return dojo.some(this.childrenAttrs, function(attr){
-				return this.store.hasAttribute(item, attr);
-			}, this);
-		},
-
-		getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete, /*function*/ onError){
-			// summary:
-			// 		Calls onComplete() with array of child items of given parent item, all loaded.
-
-			var store = this.store;
-			if(!store.isItemLoaded(parentItem)){
-				// The parent is not loaded yet, we must be in deferItemLoadingUntilExpand
-				// mode, so we will load it and just return the children (without loading each
-				// child item)
-				var getChildren = dojo.hitch(this, arguments.callee);
-				store.loadItem({
-					item: parentItem,
-					onItem: function(parentItem){
-						getChildren(parentItem, onComplete, onError);
-					},
-					onError: onError
-				});
-				return;
-			}
-			// get children of specified item
-			var childItems = [];
-			for(var i=0; i<this.childrenAttrs.length; i++){
-				var vals = store.getValues(parentItem, this.childrenAttrs[i]);
-				childItems = childItems.concat(vals);
-			}
-
-			// count how many items need to be loaded
-			var _waitCount = 0;
-			if(!this.deferItemLoadingUntilExpand){
-				dojo.forEach(childItems, function(item){ if(!store.isItemLoaded(item)){ _waitCount++; } });
-			}
-
-			if(_waitCount == 0){
-				// all items are already loaded (or we aren't loading them).  proceed...
-				onComplete(childItems);
-			}else{
-				// still waiting for some or all of the items to load
-				var onItem = function onItem(item){
-					if(--_waitCount == 0){
-						// all nodes have been loaded, send them to the tree
-						onComplete(childItems);
-					}
-				}
-				dojo.forEach(childItems, function(item){
-					if(!store.isItemLoaded(item)){
-						store.loadItem({
-							item: item,
-							onItem: onItem,
-							onError: onError
-						});
-					}
-				});
-			}
-		},
-
-		// =======================================================================
-		// Inspecting items
-
-		isItem: function(/* anything */ something){
-			return this.store.isItem(something);	// Boolean
-		},
-
-		fetchItemByIdentity: function(/* object */ keywordArgs){
-			this.store.fetchItemByIdentity(keywordArgs);
-		},
-
-		getIdentity: function(/* item */ item){
-			return this.store.getIdentity(item);	// Object
-		},
-
-		getLabel: function(/*dojo.data.Item*/ item){
-			// summary:
-			//		Get the label for an item
-			if(this.labelAttr){
-				return this.store.getValue(item,this.labelAttr);	// String
-			}else{
-				return this.store.getLabel(item);	// String
-			}
-		},
-
-		// =======================================================================
-		// Write interface
-
-		newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
-			// summary:
-			//		Creates a new item.   See `dojo.data.api.Write` for details on args.
-			//		Used in drag & drop when item from external source dropped onto tree.
-			// description:
-			//		Developers will need to override this method if new items get added
-			//		to parents with multiple children attributes, in order to define which
-			//		children attribute points to the new item.
-
-			var pInfo = {parent: parent, attribute: this.childrenAttrs[0], insertIndex: insertIndex};
-
-			if(this.newItemIdAttr && args[this.newItemIdAttr]){
-				// Maybe there's already a corresponding item in the store; if so, reuse it.
-				this.fetchItemByIdentity({identity: args[this.newItemIdAttr], scope: this, onItem: function(item){
-					if(item){
-						// There's already a matching item in store, use it
-						this.pasteItem(item, null, parent, true, insertIndex);
-					}else{
-						// Create new item in the tree, based on the drag source.
-						this.store.newItem(args, pInfo);
-					}
-				}});
-			}else{
-				// [as far as we know] there is no id so we must assume this is a new item
-				this.store.newItem(args, pInfo);
-			}
-		},
-
-		pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
-			// summary:
-			//		Move or copy an item from one parent item to another.
-			//		Used in drag & drop
-			var store = this.store,
-				parentAttr = this.childrenAttrs[0];	// name of "children" attr in parent item
-
-			// remove child from source item, and record the attribute that child occurred in
-			if(oldParentItem){
-				dojo.forEach(this.childrenAttrs, function(attr){
-					if(store.containsValue(oldParentItem, attr, childItem)){
-						if(!bCopy){
-							var values = dojo.filter(store.getValues(oldParentItem, attr), function(x){
-								return x != childItem;
-							});
-							store.setValues(oldParentItem, attr, values);
-						}
-						parentAttr = attr;
-					}
-				});
-			}
-
-			// modify target item's children attribute to include this item
-			if(newParentItem){
-				if(typeof insertIndex == "number"){
-					var childItems = store.getValues(newParentItem, parentAttr);
-					childItems.splice(insertIndex, 0, childItem);
-					store.setValues(newParentItem, parentAttr, childItems);
-				}else{
-				store.setValues(newParentItem, parentAttr,
-					store.getValues(newParentItem, parentAttr).concat(childItem));
-			}
-			}
-		},
-
-		// =======================================================================
-		// Callbacks
-
-		onChange: function(/*dojo.data.Item*/ item){
-			// summary:
-			//		Callback whenever an item has changed, so that Tree
-			//		can update the label, icon, etc.   Note that changes
-			//		to an item's children or parent(s) will trigger an
-			//		onChildrenChange() so you can ignore those changes here.
-			// tags:
-			//		callback
-		},
-
-		onChildrenChange: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
-			// summary:
-			//		Callback to do notifications about new, updated, or deleted items.
-			// tags:
-			//		callback
-		},
-
-		onDelete: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
-			// summary:
-			//		Callback when an item has been deleted.
-			// description:
-			//		Note that there will also be an onChildrenChange() callback for the parent
-			//		of this item.
-			// tags:
-			//		callback
-		},
-
-		// =======================================================================
-		// Events from data store
-
-		onNewItem: function(/* dojo.data.Item */ item, /* Object */ parentInfo){
-			// summary:
-			//		Handler for when new items appear in the store, either from a drop operation
-			//		or some other way.   Updates the tree view (if necessary).
-			// description:
-			//		If the new item is a child of an existing item,
-			//		calls onChildrenChange() with the new list of children
-			//		for that existing item.
-			//
-			// tags:
-			//		extension
-
-			// We only care about the new item if it has a parent that corresponds to a TreeNode
-			// we are currently displaying
-			if(!parentInfo){
-				return;
-			}
-
-			// Call onChildrenChange() on parent (ie, existing) item with new list of children
-			// In the common case, the new list of children is simply parentInfo.newValue or
-			// [ parentInfo.newValue ], although if items in the store has multiple
-			// child attributes (see `childrenAttr`), then it's a superset of parentInfo.newValue,
-			// so call getChildren() to be sure to get right answer.
-			this.getChildren(parentInfo.item, dojo.hitch(this, function(children){
-				this.onChildrenChange(parentInfo.item, children);
-			}));
-		},
-
-		onDeleteItem: function(/*Object*/ item){
-			// summary:
-			//		Handler for delete notifications from underlying store
-			this.onDelete(item);
-		},
-
-		onSetItem: function(/* item */ item,
-						/* attribute-name-string */ attribute,
-						/* object | array */ oldValue,
-						/* object | array */ newValue){
-			// summary:
-			//		Updates the tree view according to changes in the data store.
-			// description:
-			//		Handles updates to an item's children by calling onChildrenChange(), and
-			//		other updates to an item by calling onChange().
-			//
-			//		See `onNewItem` for more details on handling updates to an item's children.
-			// tags:
-			//		extension
-
-			if(dojo.indexOf(this.childrenAttrs, attribute) != -1){
-				// item's children list changed
-				this.getChildren(item, dojo.hitch(this, function(children){
-					// See comments in onNewItem() about calling getChildren()
-					this.onChildrenChange(item, children);
-				}));
-			}else{
-				// item's label/icon/etc. changed.
-				this.onChange(item);
-			}
-		}
-	});
-
-
-
-}
-
-if(!dojo._hasResource["dijit.tree.ForestStoreModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.tree.ForestStoreModel"] = true;
-dojo.provide("dijit.tree.ForestStoreModel");
-
-
-
-dojo.declare("dijit.tree.ForestStoreModel", dijit.tree.TreeStoreModel, {
-	// summary:
-	//		Interface between Tree and a dojo.store that doesn't have a root item,
-	//		i.e. has multiple "top level" items.
-	//
-	// description
-	//		Use this class to wrap a dojo.store, making all the items matching the specified query
-	//		appear as children of a fabricated "root item".  If no query is specified then all the
-	//		items returned by fetch() on the underlying store become children of the root item.
-	//		It allows dijit.Tree to assume a single root item, even if the store doesn't have one.
-
-	// Parameters to constructor
-
-	// rootId: String
-	//		ID of fabricated root item
-	rootId: "$root$",
-
-	// rootLabel: String
-	//		Label of fabricated root item
-	rootLabel: "ROOT",
-
-	// query: String
-	//		Specifies the set of children of the root item.
-	// example:
-	//	|	{type:'continent'}
-	query: null,
-
-	// End of parameters to constructor
-
-	constructor: function(params){
-		// summary:
-		//		Sets up variables, etc.
-		// tags:
-		//		private
-
-		// Make dummy root item
-		this.root = {
-			store: this,
-			root: true,
-			id: params.rootId,
-			label: params.rootLabel,
-			children: params.rootChildren	// optional param
-		};
-	},
-
-	// =======================================================================
-	// Methods for traversing hierarchy
-
-	mayHaveChildren: function(/*dojo.data.Item*/ item){
-		// summary:
-		//		Tells if an item has or may have children.  Implementing logic here
-		//		avoids showing +/- expando icon for nodes that we know don't have children.
-		//		(For efficiency reasons we may not want to check if an element actually
-		//		has children until user clicks the expando node)
-		// tags:
-		//		extension
-		return item === this.root || this.inherited(arguments);
-	},
-
-	getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ callback, /*function*/ onError){
-		// summary:
-		// 		Calls onComplete() with array of child items of given parent item, all loaded.
-		if(parentItem === this.root){
-			if(this.root.children){
-				// already loaded, just return
-				callback(this.root.children);
-			}else{
-				this.store.fetch({
-					query: this.query,
-					onComplete: dojo.hitch(this, function(items){
-						this.root.children = items;
-						callback(items);
-					}),
-					onError: onError
-				});
-			}
-		}else{
-			this.inherited(arguments);
-		}
-	},
-
-	// =======================================================================
-	// Inspecting items
-
-	isItem: function(/* anything */ something){
-		return (something === this.root) ? true : this.inherited(arguments);
-	},
-
-	fetchItemByIdentity: function(/* object */ keywordArgs){
-		if(keywordArgs.identity == this.root.id){
-			var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
-			if(keywordArgs.onItem){
-				keywordArgs.onItem.call(scope, this.root);
-			}
-		}else{
-			this.inherited(arguments);
-		}
-	},
-
-	getIdentity: function(/* item */ item){
-		return (item === this.root) ? this.root.id : this.inherited(arguments);
-	},
-
-	getLabel: function(/* item */ item){
-		return	(item === this.root) ? this.root.label : this.inherited(arguments);
-	},
-
-	// =======================================================================
-	// Write interface
-
-	newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
-		// summary:
-		//		Creates a new item.   See dojo.data.api.Write for details on args.
-		//		Used in drag & drop when item from external source dropped onto tree.
-		if(parent === this.root){
-			this.onNewRootItem(args);
-			return this.store.newItem(args);
-		}else{
-			return this.inherited(arguments);
-		}
-	},
-
-	onNewRootItem: function(args){
-		// summary:
-		//		User can override this method to modify a new element that's being
-		//		added to the root of the tree, for example to add a flag like root=true
-	},
-
-	pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
-		// summary:
-		//		Move or copy an item from one parent item to another.
-		//		Used in drag & drop
-		if(oldParentItem === this.root){
-			if(!bCopy){
-				// It's onLeaveRoot()'s responsibility to modify the item so it no longer matches
-				// this.query... thus triggering an onChildrenChange() event to notify the Tree
-				// that this element is no longer a child of the root node
-				this.onLeaveRoot(childItem);
-			}
-		}
-		dijit.tree.TreeStoreModel.prototype.pasteItem.call(this, childItem,
-			oldParentItem === this.root ? null : oldParentItem,
-			newParentItem === this.root ? null : newParentItem,
-			bCopy,
-			insertIndex
-		);
-		if(newParentItem === this.root){
-			// It's onAddToRoot()'s responsibility to modify the item so it matches
-			// this.query... thus triggering an onChildrenChange() event to notify the Tree
-			// that this element is now a child of the root node
-			this.onAddToRoot(childItem);
-		}
-	},
-
-	// =======================================================================
-	// Handling for top level children
-
-	onAddToRoot: function(/* item */ item){
-		// summary:
-		//		Called when item added to root of tree; user must override this method
-		//		to modify the item so that it matches the query for top level items
-		// example:
-		//	|	store.setValue(item, "root", true);
-		// tags:
-		//		extension
-		console.log(this, ": item ", item, " added to root");
-	},
-
-	onLeaveRoot: function(/* item */ item){
-		// summary:
-		//		Called when item removed from root of tree; user must override this method
-		//		to modify the item so it doesn't match the query for top level items
-		// example:
-		// 	|	store.unsetAttribute(item, "root");
-		// tags:
-		//		extension
-		console.log(this, ": item ", item, " removed from root");
-	},
-
-	// =======================================================================
-	// Events from data store
-
-	_requeryTop: function(){
-		// reruns the query for the children of the root node,
-		// sending out an onSet notification if those children have changed
-		var oldChildren = this.root.children || [];
-		this.store.fetch({
-			query: this.query,
-			onComplete: dojo.hitch(this, function(newChildren){
-				this.root.children = newChildren;
-
-				// If the list of children or the order of children has changed...
-				if(oldChildren.length != newChildren.length ||
-					dojo.some(oldChildren, function(item, idx){ return newChildren[idx] != item;})){
-					this.onChildrenChange(this.root, newChildren);
-				}
-			})
-		});
-	},
-
-	onNewItem: function(/* dojo.data.Item */ item, /* Object */ parentInfo){
-		// summary:
-		//		Handler for when new items appear in the store.  Developers should override this
-		//		method to be more efficient based on their app/data.
-		// description:
-		//		Note that the default implementation requeries the top level items every time
-		//		a new item is created, since any new item could be a top level item (even in
-		//		addition to being a child of another item, since items can have multiple parents).
-		//
-		//		Developers can override this function to do something more efficient if they can
-		//		detect which items are possible top level items (based on the item and the
-		//		parentInfo parameters).  Often all top level items have parentInfo==null, but
-		//		that will depend on which store you use and what your data is like.
-		// tags:
-		//		extension
-		this._requeryTop();
-
-		this.inherited(arguments);
-	},
-
-	onDeleteItem: function(/*Object*/ item){
-		// summary:
-		//		Handler for delete notifications from underlying store
-
-		// check if this was a child of root, and if so send notification that root's children
-		// have changed
-		if(dojo.indexOf(this.root.children, item) != -1){
-			this._requeryTop();
-		}
-
-		this.inherited(arguments);
-	}
-});
-
-
-
-}
-
-if(!dojo._hasResource["dijit.Tree"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.Tree"] = true;
-dojo.provide("dijit.Tree");
-
-
-
-
-
-
-
-
-
-
-dojo.declare(
-	"dijit._TreeNode",
-	[dijit._Widget, dijit._Templated, dijit._Container, dijit._Contained],
-{
-	// summary:
-	//		Single node within a tree.   This class is used internally
-	//		by Tree and should not be accessed directly.
-	// tags:
-	//		private
-
-	// item: dojo.data.Item
-	//		the dojo.data entry this tree represents
-	item: null,
-
-	// isTreeNode: [protected] Boolean
-	//		Indicates that this is a TreeNode.   Used by `dijit.Tree` only,
-	//		should not be accessed directly.
-	isTreeNode: true,
-
-	// label: String
-	//		Text of this tree node
-	label: "",
-
-	// isExpandable: [private] Boolean
-	//		This node has children, so show the expando node (+ sign)
-	isExpandable: null,
-
-	// isExpanded: [readonly] Boolean
-	//		This node is currently expanded (ie, opened)
-	isExpanded: false,
-
-	// state: [private] String
-	//		Dynamic loading-related stuff.
-	//		When an empty folder node appears, it is "UNCHECKED" first,
-	//		then after dojo.data query it becomes "LOADING" and, finally "LOADED"
-	state: "UNCHECKED",
-
-	templateString: dojo.cache("dijit", "templates/TreeNode.html", "<div class=\"dijitTreeNode\" waiRole=\"presentation\"\n\t><div dojoAttachPoint=\"rowNode\" class=\"dijitTreeRow\" waiRole=\"presentation\" dojoAttachEvent=\"onmouseenter:_onMouseEnter, onmouseleave:_onMouseLeave, onclick:_onClick, ondblclick:_onDblClick\"\n\t\t><img src=\"${_blankGif}\" alt=\"\" dojoAttachPoint=\"expandoNode\" class=\"dijitTreeExpando\" waiRole=\"presentation\"\n\t\t><span dojoAttachPoint=\"expandoNodeText\ [...]
-
-	attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-		label: {node: "labelNode", type: "innerText"},
-		tooltip: {node: "rowNode", type: "attribute", attribute: "title"}
-	}),
-
-	postCreate: function(){
-		// set expand icon for leaf
-		this._setExpando();
-
-		// set icon and label class based on item
-		this._updateItemClasses(this.item);
-
-		if(this.isExpandable){
-			dijit.setWaiState(this.labelNode, "expanded", this.isExpanded);
-		}
-	},
-
-	_setIndentAttr: function(indent){
-		// summary:
-		//		Tell this node how many levels it should be indented
-		// description:
-		//		0 for top level nodes, 1 for their children, 2 for their
-		//		grandchildren, etc.
-		this.indent = indent;
-
-		// Math.max() is to prevent negative padding on hidden root node (when indent == -1)
-		var pixels = (Math.max(indent, 0) * this.tree._nodePixelIndent) + "px";
-
-		dojo.style(this.domNode, "backgroundPosition",	pixels + " 0px");
-		dojo.style(this.rowNode, dojo._isBodyLtr() ? "paddingLeft" : "paddingRight", pixels);
-
-		dojo.forEach(this.getChildren(), function(child){
-			child.attr("indent", indent+1);
-		});
-	},
-
-	markProcessing: function(){
-		// summary:
-		//		Visually denote that tree is loading data, etc.
-		// tags:
-		//		private
-		this.state = "LOADING";
-		this._setExpando(true);
-	},
-
-	unmarkProcessing: function(){
-		// summary:
-		//		Clear markup from markProcessing() call
-		// tags:
-		//		private
-		this._setExpando(false);
-	},
-
-	_updateItemClasses: function(item){
-		// summary:
-		//		Set appropriate CSS classes for icon and label dom node
-		//		(used to allow for item updates to change respective CSS)
-		// tags:
-		//		private
-		var tree = this.tree, model = tree.model;
-		if(tree._v10Compat && item === model.root){
-			// For back-compat with 1.0, need to use null to specify root item (TODO: remove in 2.0)
-			item = null;
-		}
-		this._applyClassAndStyle(item, "icon", "Icon");
-		this._applyClassAndStyle(item, "label", "Label");
-		this._applyClassAndStyle(item, "row", "Row");
-	},
-
-	_applyClassAndStyle: function(item, lower, upper){
-		// summary:
-		//		Set the appropriate CSS classes and styles for labels, icons and rows.
-		//
-		// item:
-		//		The data item.
-		//
-		// lower:
-		//		The lower case attribute to use, e.g. 'icon', 'label' or 'row'.
-		//
-		// upper:
-		//		The upper case attribute to use, e.g. 'Icon', 'Label' or 'Row'.
-		//
-		// tags:
-		//		private
-
-		var clsName = "_" + lower + "Class";
-		var nodeName = lower + "Node";
-
-		if(this[clsName]){
-			dojo.removeClass(this[nodeName], this[clsName]);
- 		}
-		this[clsName] = this.tree["get" + upper + "Class"](item, this.isExpanded);
-		if(this[clsName]){
-			dojo.addClass(this[nodeName], this[clsName]);
- 		}
-		dojo.style(this[nodeName], this.tree["get" + upper + "Style"](item, this.isExpanded) || {});
- 	},
-
-	_updateLayout: function(){
-		// summary:
-		//		Set appropriate CSS classes for this.domNode
-		// tags:
-		//		private
-		var parent = this.getParent();
-		if(!parent || parent.rowNode.style.display == "none"){
-			/* if we are hiding the root node then make every first level child look like a root node */
-			dojo.addClass(this.domNode, "dijitTreeIsRoot");
-		}else{
-			dojo.toggleClass(this.domNode, "dijitTreeIsLast", !this.getNextSibling());
-		}
-	},
-
-	_setExpando: function(/*Boolean*/ processing){
-		// summary:
-		//		Set the right image for the expando node
-		// tags:
-		//		private
-
-		var styles = ["dijitTreeExpandoLoading", "dijitTreeExpandoOpened",
-						"dijitTreeExpandoClosed", "dijitTreeExpandoLeaf"],
-			_a11yStates = ["*","-","+","*"],
-			idx = processing ? 0 : (this.isExpandable ?	(this.isExpanded ? 1 : 2) : 3);
-
-		// apply the appropriate class to the expando node
-		dojo.removeClass(this.expandoNode, styles);
-		dojo.addClass(this.expandoNode, styles[idx]);
-
-		// provide a non-image based indicator for images-off mode
-		this.expandoNodeText.innerHTML = _a11yStates[idx];
-
-	},
-
-	expand: function(){
-		// summary:
-		//		Show my children
-		// returns:
-		//		Deferred that fires when expansion is complete
-
-		// If there's already an expand in progress or we are already expanded, just return
-		if(this._expandDeferred){
-			return this._expandDeferred;		// dojo.Deferred
-		}
-
-		// cancel in progress collapse operation
-		this._wipeOut && this._wipeOut.stop();
-
-		// All the state information for when a node is expanded, maybe this should be
-		// set when the animation completes instead
-		this.isExpanded = true;
-		dijit.setWaiState(this.labelNode, "expanded", "true");
-		dijit.setWaiRole(this.containerNode, "group");
-		dojo.addClass(this.contentNode,'dijitTreeContentExpanded');
-		this._setExpando();
-		this._updateItemClasses(this.item);
-		if(this == this.tree.rootNode){
-			dijit.setWaiState(this.tree.domNode, "expanded", "true");
-		}
-
-		var def,
-			wipeIn = dojo.fx.wipeIn({
-				node: this.containerNode, duration: dijit.defaultDuration,
-				onEnd: function(){
-					def.callback(true);
-				}
-			});
-
-		// Deferred that fires when expand is complete
-		def = (this._expandDeferred = new dojo.Deferred(function(){
-			// Canceller
-			wipeIn.stop();
-		}));
-
-		wipeIn.play();
-
-		return def;		// dojo.Deferred
-	},
-
-	collapse: function(){
-		// summary:
-		//		Collapse this node (if it's expanded)
-
-		if(!this.isExpanded){ return; }
-
-		// cancel in progress expand operation
-		if(this._expandDeferred){
-			this._expandDeferred.cancel();
-			delete this._expandDeferred;
-		}
-
-		this.isExpanded = false;
-		dijit.setWaiState(this.labelNode, "expanded", "false");
-		if(this == this.tree.rootNode){
-			dijit.setWaiState(this.tree.domNode, "expanded", "false");
-		}
-		dojo.removeClass(this.contentNode,'dijitTreeContentExpanded');
-		this._setExpando();
-		this._updateItemClasses(this.item);
-
-		if(!this._wipeOut){
-			this._wipeOut = dojo.fx.wipeOut({
-				node: this.containerNode, duration: dijit.defaultDuration
-			});
-		}
-		this._wipeOut.play();
-	},
-
-	// indent: Integer
-	//		Levels from this node to the root node
-	indent: 0,
-
-	setChildItems: function(/* Object[] */ items){
-		// summary:
-		//		Sets the child items of this node, removing/adding nodes
-		//		from current children to match specified items[] array.
-		//		Also, if this.persist == true, expands any children that were previously
-		// 		opened.
-		// returns:
-		//		Deferred object that fires after all previously opened children
-		//		have been expanded again (or fires instantly if there are no such children).
-
-		var tree = this.tree,
-			model = tree.model,
-			defs = [];	// list of deferreds that need to fire before I am complete
-
-
-		// Orphan all my existing children.
-		// If items contains some of the same items as before then we will reattach them.
-		// Don't call this.removeChild() because that will collapse the tree etc.
-		this.getChildren().forEach(function(child){
-			dijit._Container.prototype.removeChild.call(this, child);
-		}, this);
-
-		this.state = "LOADED";
-
-		if(items && items.length > 0){
-			this.isExpandable = true;
-
-			// Create _TreeNode widget for each specified tree node, unless one already
-			// exists and isn't being used (presumably it's from a DnD move and was recently
-			// released
-			dojo.forEach(items, function(item){
-				var id = model.getIdentity(item),
-					existingNodes = tree._itemNodesMap[id],
-					node;
-				if(existingNodes){
-					for(var i=0;i<existingNodes.length;i++){
-						if(existingNodes[i] && !existingNodes[i].getParent()){
-							node = existingNodes[i];
-							node.attr('indent', this.indent+1);
-							break;
-						}
-					}
-				}
-				if(!node){
-					node = this.tree._createTreeNode({
-							item: item,
-							tree: tree,
-							isExpandable: model.mayHaveChildren(item),
-							label: tree.getLabel(item),
-							tooltip: tree.getTooltip(item),
-							indent: this.indent + 1
-						});
-					if(existingNodes){
-						existingNodes.push(node);
-					}else{
-						tree._itemNodesMap[id] = [node];
-					}
-				}
-				this.addChild(node);
-
-				// If node was previously opened then open it again now (this may trigger
-				// more data store accesses, recursively)
-				if(this.tree.autoExpand || this.tree._state(item)){
-					defs.push(tree._expandNode(node));
-				}
-			}, this);
-
-			// note that updateLayout() needs to be called on each child after
-			// _all_ the children exist
-			dojo.forEach(this.getChildren(), function(child, idx){
-				child._updateLayout();
-			});
-		}else{
-			this.isExpandable=false;
-		}
-
-		if(this._setExpando){
-			// change expando to/from dot or + icon, as appropriate
-			this._setExpando(false);
-		}
-
-		// On initial tree show, make the selected TreeNode as either the root node of the tree,
-		// or the first child, if the root node is hidden
-		if(this == tree.rootNode){
-			var fc = this.tree.showRoot ? this : this.getChildren()[0];
-			if(fc){
-				fc.setSelected(true);
-				tree.lastFocused = fc;
-			}else{
-				// fallback: no nodes in tree so focus on Tree <div> itself
-				tree.domNode.setAttribute("tabIndex", "0");
-			}
-		}
-
-		return new dojo.DeferredList(defs);	// dojo.Deferred
-	},
-
-	removeChild: function(/* treeNode */ node){
-		this.inherited(arguments);
-
-		var children = this.getChildren();
-		if(children.length == 0){
-			this.isExpandable = false;
-			this.collapse();
-		}
-
-		dojo.forEach(children, function(child){
-				child._updateLayout();
-		});
-	},
-
-	makeExpandable: function(){
-		// summary:
-		//		if this node wasn't already showing the expando node,
-		//		turn it into one and call _setExpando()
-
-		// TODO: hmm this isn't called from anywhere, maybe should remove it for 2.0
-
-		this.isExpandable = true;
-		this._setExpando(false);
-	},
-
-	_onLabelFocus: function(evt){
-		// summary:
-		//		Called when this node is focused (possibly programatically)
-		// tags:
-		//		private
-		dojo.addClass(this.labelNode, "dijitTreeLabelFocused");
-		this.tree._onNodeFocus(this);
-	},
-
-	_onLabelBlur: function(evt){
-		// summary:
-		//		Called when focus was moved away from this node, either to
-		//		another TreeNode or away from the Tree entirely.
-		//		Note that we aren't using _onFocus/_onBlur builtin to dijit
-		//		because _onBlur() isn't called when focus is moved to my child TreeNode.
-		// tags:
-		//		private
-		dojo.removeClass(this.labelNode, "dijitTreeLabelFocused");
-	},
-
-	setSelected: function(/*Boolean*/ selected){
-		// summary:
-		//		A Tree has a (single) currently selected node.
-		//		Mark that this node is/isn't that currently selected node.
-		// description:
-		//		In particular, setting a node as selected involves setting tabIndex
-		//		so that when user tabs to the tree, focus will go to that node (only).
-		var labelNode = this.labelNode;
-		labelNode.setAttribute("tabIndex", selected ? "0" : "-1");
-		dijit.setWaiState(labelNode, "selected", selected);
-		dojo.toggleClass(this.rowNode, "dijitTreeNodeSelected", selected);
-	},
-
-	_onClick: function(evt){
-		// summary:
-		//		Handler for onclick event on a node
-		// tags:
-		//		private
-		this.tree._onClick(this, evt);
-	},
-	_onDblClick: function(evt){
-		// summary:
-		//		Handler for ondblclick event on a node
-		// tags:
-		//		private
-		this.tree._onDblClick(this, evt);
-	},
-
-	_onMouseEnter: function(evt){
-		// summary:
-		//		Handler for onmouseenter event on a node
-		// tags:
-		//		private
-		dojo.addClass(this.rowNode, "dijitTreeNodeHover");
-		this.tree._onNodeMouseEnter(this, evt);
-	},
-
-	_onMouseLeave: function(evt){
-		// summary:
-		//		Handler for onmouseenter event on a node
-		// tags:
-		//		private
-		dojo.removeClass(this.rowNode, "dijitTreeNodeHover");
-		this.tree._onNodeMouseLeave(this, evt);
-	}
-});
-
-dojo.declare(
-	"dijit.Tree",
-	[dijit._Widget, dijit._Templated],
-{
-	// summary:
-	//		This widget displays hierarchical data from a store.
-
-	// store: [deprecated] String||dojo.data.Store
-	//		Deprecated.  Use "model" parameter instead.
-	//		The store to get data to display in the tree.
-	store: null,
-
-	// model: dijit.Tree.model
-	//		Interface to read tree data, get notifications of changes to tree data,
-	//		and for handling drop operations (i.e drag and drop onto the tree)
-	model: null,
-
-	// query: [deprecated] anything
-	//		Deprecated.  User should specify query to the model directly instead.
-	//		Specifies datastore query to return the root item or top items for the tree.
-	query: null,
-
-	// label: [deprecated] String
-	//		Deprecated.  Use dijit.tree.ForestStoreModel directly instead.
-	//		Used in conjunction with query parameter.
-	//		If a query is specified (rather than a root node id), and a label is also specified,
-	//		then a fake root node is created and displayed, with this label.
-	label: "",
-
-	// showRoot: [const] Boolean
-	//		Should the root node be displayed, or hidden?
-	showRoot: true,
-
-	// childrenAttr: [deprecated] String[]
-	//		Deprecated.   This information should be specified in the model.
-	//		One ore more attributes that holds children of a tree node
-	childrenAttr: ["children"],
-
-	// path: String[] or Item[]
-	//		Full path from rootNode to selected node expressed as array of items or array of ids.
-	path: [],
-
-	// selectedItem: [readonly] Item
-	//		The currently selected item in this tree.
-	//		This property can only be set (via attr('selectedItem', ...)) when that item is already
-	//		visible in the tree.   (I.e. the tree has already been expanded to show that node.)
-	//		Should generally use `path` attribute to set the selected item instead.
-	selectedItem: null,
-
-	// openOnClick: Boolean
-	//		If true, clicking a folder node's label will open it, rather than calling onClick()
-	openOnClick: false,
-
-	// openOnDblClick: Boolean
-	//		If true, double-clicking a folder node's label will open it, rather than calling onDblClick()
-	openOnDblClick: false,
-
-	templateString: dojo.cache("dijit", "templates/Tree.html", "<div class=\"dijitTree dijitTreeContainer\" waiRole=\"tree\"\n\tdojoAttachEvent=\"onkeypress:_onKeyPress\">\n\t<div class=\"dijitInline dijitTreeIndent\" style=\"position: absolute; top: -9999px\" dojoAttachPoint=\"indentDetector\"></div>\n</div>\n"),
-
-	// persist: Boolean
-	//		Enables/disables use of cookies for state saving.
-	persist: true,
-
-	// autoExpand: Boolean
-	//		Fully expand the tree on load.   Overrides `persist`
-	autoExpand: false,
-
-	// dndController: [protected] String
-	//		Class name to use as as the dnd controller.  Specifying this class enables DnD.
-	//		Generally you should specify this as "dijit.tree.dndSource".
-	dndController: null,
-
-	// parameters to pull off of the tree and pass on to the dndController as its params
-	dndParams: ["onDndDrop","itemCreator","onDndCancel","checkAcceptance", "checkItemAcceptance", "dragThreshold", "betweenThreshold"],
-
-	//declare the above items so they can be pulled from the tree's markup
-
-	// onDndDrop: [protected] Function
-	//		Parameter to dndController, see `dijit.tree.dndSource.onDndDrop`.
-	//		Generally this doesn't need to be set.
-	onDndDrop: null,
-
-	/*=====
-	itemCreator: function(nodes, target, source){
-		// summary:
-		//		Returns objects passed to `Tree.model.newItem()` based on DnD nodes
-		//		dropped onto the tree.   Developer must override this method to enable
-		// 		dropping from external sources onto this Tree, unless the Tree.model's items
-		//		happen to look like {id: 123, name: "Apple" } with no other attributes.
-		// description:
-		//		For each node in nodes[], which came from source, create a hash of name/value
-		//		pairs to be passed to Tree.model.newItem().  Returns array of those hashes.
-		// nodes: DomNode[]
-		//		The DOMNodes dragged from the source container
-		// target: DomNode
-		//		The target TreeNode.rowNode
-		// source: dojo.dnd.Source
-		//		The source container the nodes were dragged from, perhaps another Tree or a plain dojo.dnd.Source
-		// returns: Object[]
-		//		Array of name/value hashes for each new item to be added to the Tree, like:
-		// |	[
-		// |		{ id: 123, label: "apple", foo: "bar" },
-		// |		{ id: 456, label: "pear", zaz: "bam" }
-		// |	]
-		// tags:
-		//		extension
-		return [{}];
-	},
-	=====*/
-	itemCreator: null,
-
-	// onDndCancel: [protected] Function
-	//		Parameter to dndController, see `dijit.tree.dndSource.onDndCancel`.
-	//		Generally this doesn't need to be set.
-	onDndCancel: null,
-
-/*=====
-	checkAcceptance: function(source, nodes){
-		// summary:
-		//		Checks if the Tree itself can accept nodes from this source
-		// source: dijit.tree._dndSource
-		//		The source which provides items
-		// nodes: DOMNode[]
-		//		Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if
-		//		source is a dijit.Tree.
-		// tags:
-		//		extension
-		return true;	// Boolean
-	},
-=====*/
-	checkAcceptance: null,
-
-/*=====
-	checkItemAcceptance: function(target, source, position){
-		// summary:
-		//		Stub function to be overridden if one wants to check for the ability to drop at the node/item level
-		// description:
-		//		In the base case, this is called to check if target can become a child of source.
-		//		When betweenThreshold is set, position="before" or "after" means that we
-		//		are asking if the source node can be dropped before/after the target node.
-		// target: DOMNode
-		//		The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to
-		//		Use dijit.getEnclosingWidget(target) to get the TreeNode.
-		// source: dijit.tree.dndSource
-		//		The (set of) nodes we are dropping
-		// position: String
-		//		"over", "before", or "after"
-		// tags:
-		//		extension
-		return true;	// Boolean
-	},
-=====*/
-	checkItemAcceptance: null,
-
-	// dragThreshold: Integer
-	//		Number of pixels mouse moves before it's considered the start of a drag operation
-	dragThreshold: 5,
-
-	// betweenThreshold: Integer
-	//		Set to a positive value to allow drag and drop "between" nodes.
-	//
-	//		If during DnD mouse is over a (target) node but less than betweenThreshold
-	//		pixels from the bottom edge, dropping the the dragged node will make it
-	//		the next sibling of the target node, rather than the child.
-	//
-	//		Similarly, if mouse is over a target node but less that betweenThreshold
-	//		pixels from the top edge, dropping the dragged node will make it
-	//		the target node's previous sibling rather than the target node's child.
-	betweenThreshold: 0,
-
-	// _nodePixelIndent: Integer
-	//		Number of pixels to indent tree nodes (relative to parent node).
-	//		Default is 19 but can be overridden by setting CSS class dijitTreeIndent
-	//		and calling resize() or startup() on tree after it's in the DOM.
-	_nodePixelIndent: 19,
-
-	_publish: function(/*String*/ topicName, /*Object*/ message){
-		// summary:
-		//		Publish a message for this widget/topic
-		dojo.publish(this.id, [dojo.mixin({tree: this, event: topicName}, message || {})]);
-	},
-
-	postMixInProperties: function(){
-		this.tree = this;
-
-		this._itemNodesMap={};
-
-		if(!this.cookieName){
-			this.cookieName = this.id + "SaveStateCookie";
-		}
-
-		this._loadDeferred = new dojo.Deferred();
-
-		this.inherited(arguments);
-	},
-
-	postCreate: function(){
-		this._initState();
-
-		// Create glue between store and Tree, if not specified directly by user
-		if(!this.model){
-			this._store2model();
-		}
-
-		// monitor changes to items
-		this.connect(this.model, "onChange", "_onItemChange");
-		this.connect(this.model, "onChildrenChange", "_onItemChildrenChange");
-		this.connect(this.model, "onDelete", "_onItemDelete");
-
-		this._load();
-
-		this.inherited(arguments);
-
-		if(this.dndController){
-			if(dojo.isString(this.dndController)){
-				this.dndController = dojo.getObject(this.dndController);
-			}
-			var params={};
-			for(var i=0; i<this.dndParams.length;i++){
-				if(this[this.dndParams[i]]){
-					params[this.dndParams[i]] = this[this.dndParams[i]];
-				}
-			}
-			this.dndController = new this.dndController(this, params);
-		}
-	},
-
-	_store2model: function(){
-		// summary:
-		//		User specified a store&query rather than model, so create model from store/query
-		this._v10Compat = true;
-		dojo.deprecated("Tree: from version 2.0, should specify a model object rather than a store/query");
-
-		var modelParams = {
-			id: this.id + "_ForestStoreModel",
-			store: this.store,
-			query: this.query,
-			childrenAttrs: this.childrenAttr
-		};
-
-		// Only override the model's mayHaveChildren() method if the user has specified an override
-		if(this.params.mayHaveChildren){
-			modelParams.mayHaveChildren = dojo.hitch(this, "mayHaveChildren");
-		}
-
-		if(this.params.getItemChildren){
-			modelParams.getChildren = dojo.hitch(this, function(item, onComplete, onError){
-				this.getItemChildren((this._v10Compat && item === this.model.root) ? null : item, onComplete, onError);
-			});
-		}
-		this.model = new dijit.tree.ForestStoreModel(modelParams);
-
-		// For backwards compatibility, the visibility of the root node is controlled by
-		// whether or not the user has specified a label
-		this.showRoot = Boolean(this.label);
-	},
-
-	onLoad: function(){
-		// summary:
-		//		Called when tree finishes loading and expanding.
-		// description:
-		//		If persist == true the loading may encompass many levels of fetches
-		//		from the data store, each asynchronous.   Waits for all to finish.
-		// tags:
-		//		callback
-	},
-
-	_load: function(){
-		// summary:
-		//		Initial load of the tree.
-		//		Load root node (possibly hidden) and it's children.
-		this.model.getRoot(
-			dojo.hitch(this, function(item){
-				var rn = (this.rootNode = this.tree._createTreeNode({
-					item: item,
-					tree: this,
-					isExpandable: true,
-					label: this.label || this.getLabel(item),
-					indent: this.showRoot ? 0 : -1
-				}));
-				if(!this.showRoot){
-					rn.rowNode.style.display="none";
-				}
-				this.domNode.appendChild(rn.domNode);
-				var identity = this.model.getIdentity(item);
-				if(this._itemNodesMap[identity]){
-					this._itemNodesMap[identity].push(rn);
-				}else{
-					this._itemNodesMap[identity] = [rn];
-				}
-
-				rn._updateLayout();		// sets "dijitTreeIsRoot" CSS classname
-
-				// load top level children and then fire onLoad() event
-				this._expandNode(rn).addCallback(dojo.hitch(this, function(){
-					this._loadDeferred.callback(true);
-					this.onLoad();
-				}));
-			}),
-			function(err){
-				console.error(this, ": error loading root: ", err);
-			}
-		);
-	},
-
-	getNodesByItem: function(/*dojo.data.Item or id*/ item){
-		// summary:
-		//		Returns all tree nodes that refer to an item
-		// returns:
-		//		Array of tree nodes that refer to passed item
-
-		if(!item){ return []; }
-		var identity = dojo.isString(item) ? item : this.model.getIdentity(item);
-		// return a copy so widget don't get messed up by changes to returned array
-		return [].concat(this._itemNodesMap[identity]);
-	},
-
-	_setSelectedItemAttr: function(/*dojo.data.Item or id*/ item){
-		// summary:
-		//		Select a tree node related to passed item.
-		//		WARNING: if model use multi-parented items or desired tree node isn't already loaded
-		//		behavior is not granted. Use 'path' attr instead for full support.
-		var oldValue = this.attr("selectedItem");
-		var identity = (!item || dojo.isString(item)) ? item : this.model.getIdentity(item);
-		if(identity == oldValue ? this.model.getIdentity(oldValue) : null){ return; }
-		var nodes = this._itemNodesMap[identity];
-		if(nodes && nodes.length){
-			//select the first item
-			this.focusNode(nodes[0]);
-		}else if(this.lastFocused){
-			// Select none so deselect current
-			this.lastFocused.setSelected(false);
-			this.lastFocused = null;
-		}
-	},
-
-	_getSelectedItemAttr: function(){
-		// summary:
-		//		Return item related to selected tree node.
-		return this.lastFocused && this.lastFocused.item;
-	},
-
-	_setPathAttr: function(/*Item[] || String[]*/ path){
-		// summary:
-		//		Select the tree node identified by passed path.
-		// path:
-		//		Array of items or item id's
-
-		if(!path || !path.length){ return; }
-
-		// If this is called during initialization, defer running until Tree has finished loading
-		this._loadDeferred.addCallback(dojo.hitch(this, function(){
-			if(!this.rootNode){
-				console.debug("!this.rootNode");
-				return;
-			}
-			if(path[0] !== this.rootNode.item && (dojo.isString(path[0]) && path[0] != this.model.getIdentity(this.rootNode.item))){
-				console.error(this, ":path[0] doesn't match this.rootNode.item.  Maybe you are using the wrong tree.");
-				return;
-			}
-			path.shift();
-
-			var node = this.rootNode;
-
-			function advance(){
-				// summary:
-				// 		Called when "node" has completed loading and expanding.   Pop the next item from the path
-				//		(which must be a child of "node") and advance to it, and then recurse.
-
-				// Set item and identity to next item in path (node is pointing to the item that was popped
-				// from the path _last_ time.
-				var item = path.shift(),
-					identity = dojo.isString(item) ? item : this.model.getIdentity(item);
-
-				// Change "node" from previous item in path to the item we just popped from path
-				dojo.some(this._itemNodesMap[identity], function(n){
-					if(n.getParent() == node){
-						node = n;
-						return true;
-					}
-					return false;
-				});
-
-				if(path.length){
-					// Need to do more expanding
-					this._expandNode(node).addCallback(dojo.hitch(this, advance));
-				}else{
-					// Final destination node, select it
-					if(this.lastFocused != node){
-						this.focusNode(node);
-					}
-				}
-			}
-
-			this._expandNode(node).addCallback(dojo.hitch(this, advance));
-		}));
-	},
-
-	_getPathAttr: function(){
-		// summary:
-		//		Return an array of items that is the path to selected tree node.
-		if(!this.lastFocused){ return; }
-		var res = [];
-		var treeNode = this.lastFocused;
-		while(treeNode && treeNode !== this.rootNode){
-			res.unshift(treeNode.item);
-			treeNode = treeNode.getParent();
-		}
-		res.unshift(this.rootNode.item);
-		return res;
-	},
-
-	////////////// Data store related functions //////////////////////
-	// These just get passed to the model; they are here for back-compat
-
-	mayHaveChildren: function(/*dojo.data.Item*/ item){
-		// summary:
-		//		Deprecated.   This should be specified on the model itself.
-		//
-		//		Overridable function to tell if an item has or may have children.
-		//		Controls whether or not +/- expando icon is shown.
-		//		(For efficiency reasons we may not want to check if an element actually
-		//		has children until user clicks the expando node)
-		// tags:
-		//		deprecated
-	},
-
-	getItemChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete){
-		// summary:
-		//		Deprecated.   This should be specified on the model itself.
-		//
-		// 		Overridable function that return array of child items of given parent item,
-		//		or if parentItem==null then return top items in tree
-		// tags:
-		//		deprecated
-	},
-
-	///////////////////////////////////////////////////////
-	// Functions for converting an item to a TreeNode
-	getLabel: function(/*dojo.data.Item*/ item){
-		// summary:
-		//		Overridable function to get the label for a tree node (given the item)
-		// tags:
-		//		extension
-		return this.model.getLabel(item);	// String
-	},
-
-	getIconClass: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-		// summary:
-		//		Overridable function to return CSS class name to display icon
-		// tags:
-		//		extension
-		return (!item || this.model.mayHaveChildren(item)) ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "dijitLeaf"
-	},
-
-	getLabelClass: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-		// summary:
-		//		Overridable function to return CSS class name to display label
-		// tags:
-		//		extension
-	},
-
-	getRowClass: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-		// summary:
-		//		Overridable function to return CSS class name to display row
-		// tags:
-		//		extension
-	},
-
-	getIconStyle: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-		// summary:
-		//		Overridable function to return CSS styles to display icon
-		// returns:
-		//		Object suitable for input to dojo.style() like {backgroundImage: "url(...)"}
-		// tags:
-		//		extension
-	},
-
-	getLabelStyle: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-		// summary:
-		//		Overridable function to return CSS styles to display label
-		// returns:
-		//		Object suitable for input to dojo.style() like {color: "red", background: "green"}
-		// tags:
-		//		extension
-	},
-
-	getRowStyle: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-		// summary:
-		//		Overridable function to return CSS styles to display row
-		// returns:
-		//		Object suitable for input to dojo.style() like {background-color: "#bbb"}
-		// tags:
-		//		extension
-	},
-
-	getTooltip: function(/*dojo.data.Item*/ item){
-		// summary:
-		//		Overridable function to get the tooltip for a tree node (given the item)
-		// tags:
-		//		extension
-		return "";	// String
-	},
-
-	/////////// Keyboard and Mouse handlers ////////////////////
-
-	_onKeyPress: function(/*Event*/ e){
-		// summary:
-		//		Translates keypress events into commands for the controller
-		if(e.altKey){ return; }
-		var dk = dojo.keys;
-		var treeNode = dijit.getEnclosingWidget(e.target);
-		if(!treeNode){ return; }
-
-		var key = e.charOrCode;
-		if(typeof key == "string"){	// handle printables (letter navigation)
-			// Check for key navigation.
-			if(!e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey){
-				this._onLetterKeyNav( { node: treeNode, key: key.toLowerCase() } );
-				dojo.stopEvent(e);
-			}
-		}else{	// handle non-printables (arrow keys)
-			// clear record of recent printables (being saved for multi-char letter navigation),
-			// because "a", down-arrow, "b" shouldn't search for "ab"
-			if(this._curSearch){
-				clearTimeout(this._curSearch.timer);
-				delete this._curSearch;
-			}
-
-			var map = this._keyHandlerMap;
-			if(!map){
-				// setup table mapping keys to events
-				map = {};
-				map[dk.ENTER]="_onEnterKey";
-				map[this.isLeftToRight() ? dk.LEFT_ARROW : dk.RIGHT_ARROW]="_onLeftArrow";
-				map[this.isLeftToRight() ? dk.RIGHT_ARROW : dk.LEFT_ARROW]="_onRightArrow";
-				map[dk.UP_ARROW]="_onUpArrow";
-				map[dk.DOWN_ARROW]="_onDownArrow";
-				map[dk.HOME]="_onHomeKey";
-				map[dk.END]="_onEndKey";
-				this._keyHandlerMap = map;
-			}
-			if(this._keyHandlerMap[key]){
-				this[this._keyHandlerMap[key]]( { node: treeNode, item: treeNode.item, evt: e } );
-				dojo.stopEvent(e);
-			}
-		}
-	},
-
-	_onEnterKey: function(/*Object*/ message, /*Event*/ evt){
-		this._publish("execute", { item: message.item, node: message.node } );
-		this.onClick(message.item, message.node, evt);
-	},
-
-	_onDownArrow: function(/*Object*/ message){
-		// summary:
-		//		down arrow pressed; get next visible node, set focus there
-		var node = this._getNextNode(message.node);
-		if(node && node.isTreeNode){
-			this.focusNode(node);
-		}
-	},
-
-	_onUpArrow: function(/*Object*/ message){
-		// summary:
-		//		Up arrow pressed; move to previous visible node
-
-		var node = message.node;
-
-		// if younger siblings
-		var previousSibling = node.getPreviousSibling();
-		if(previousSibling){
-			node = previousSibling;
-			// if the previous node is expanded, dive in deep
-			while(node.isExpandable && node.isExpanded && node.hasChildren()){
-				// move to the last child
-				var children = node.getChildren();
-				node = children[children.length-1];
-			}
-		}else{
-			// if this is the first child, return the parent
-			// unless the parent is the root of a tree with a hidden root
-			var parent = node.getParent();
-			if(!(!this.showRoot && parent === this.rootNode)){
-				node = parent;
-			}
-		}
-
-		if(node && node.isTreeNode){
-			this.focusNode(node);
-		}
-	},
-
-	_onRightArrow: function(/*Object*/ message){
-		// summary:
-		//		Right arrow pressed; go to child node
-		var node = message.node;
-
-		// if not expanded, expand, else move to 1st child
-		if(node.isExpandable && !node.isExpanded){
-			this._expandNode(node);
-		}else if(node.hasChildren()){
-			node = node.getChildren()[0];
-			if(node && node.isTreeNode){
-				this.focusNode(node);
-			}
-		}
-	},
-
-	_onLeftArrow: function(/*Object*/ message){
-		// summary:
-		//		Left arrow pressed.
-		//		If not collapsed, collapse, else move to parent.
-
-		var node = message.node;
-
-		if(node.isExpandable && node.isExpanded){
-			this._collapseNode(node);
-		}else{
-			var parent = node.getParent();
-			if(parent && parent.isTreeNode && !(!this.showRoot && parent === this.rootNode)){
-				this.focusNode(parent);
-			}
-		}
-	},
-
-	_onHomeKey: function(){
-		// summary:
-		//		Home key pressed; get first visible node, and set focus there
-		var node = this._getRootOrFirstNode();
-		if(node){
-			this.focusNode(node);
-		}
-	},
-
-	_onEndKey: function(/*Object*/ message){
-		// summary:
-		//		End key pressed; go to last visible node.
-
-		var node = this.rootNode;
-		while(node.isExpanded){
-			var c = node.getChildren();
-			node = c[c.length - 1];
-		}
-
-		if(node && node.isTreeNode){
-			this.focusNode(node);
-		}
-	},
-
-	// multiCharSearchDuration: Number
-	//		If multiple characters are typed where each keystroke happens within
-	//		multiCharSearchDuration of the previous keystroke,
-	//		search for nodes matching all the keystrokes.
-	//
-	//		For example, typing "ab" will search for entries starting with
-	//		"ab" unless the delay between "a" and "b" is greater than multiCharSearchDuration.
-	multiCharSearchDuration: 250,
-
-	_onLetterKeyNav: function(message){
-		// summary:
-		//		Called when user presses a prinatable key; search for node starting with recently typed letters.
-		// message: Object
-		//		Like { node: TreeNode, key: 'a' } where key is the key the user pressed.
-
-		// Branch depending on whether this key starts a new search, or modifies an existing search
-		var cs = this._curSearch;
-		if(cs){
-			// We are continuing a search.  Ex: user has pressed 'a', and now has pressed
-			// 'b', so we want to search for nodes starting w/"ab".
-			cs.pattern = cs.pattern + message.key;
-			clearTimeout(cs.timer);
-		}else{
-			// We are starting a new search
-			cs = this._curSearch = {
-					pattern: message.key,
-					startNode: message.node
-			};
-		}
-
-		// set/reset timer to forget recent keystrokes
-		var self = this;
-		cs.timer = setTimeout(function(){
-			delete self._curSearch;
-		}, this.multiCharSearchDuration);
-
-		// Navigate to TreeNode matching keystrokes [entered so far].
-		var node = cs.startNode;
-		do{
-			node = this._getNextNode(node);
-			//check for last node, jump to first node if necessary
-			if(!node){
-				node = this._getRootOrFirstNode();
-			}
-		}while(node !== cs.startNode && (node.label.toLowerCase().substr(0, cs.pattern.length) != cs.pattern));
-		if(node && node.isTreeNode){
-			// no need to set focus if back where we started
-			if(node !== cs.startNode){
-				this.focusNode(node);
-			}
-		}
-	},
-
-	_onClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){
-		// summary:
-		//		Translates click events into commands for the controller to process
-
-		var domElement = e.target;
-
-		if( (this.openOnClick && nodeWidget.isExpandable) ||
-			(domElement == nodeWidget.expandoNode || domElement == nodeWidget.expandoNodeText) ){
-			// expando node was clicked, or label of a folder node was clicked; open it
-			if(nodeWidget.isExpandable){
-				this._onExpandoClick({node:nodeWidget});
-			}
-		}else{
-			this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } );
-			this.onClick(nodeWidget.item, nodeWidget, e);
-			this.focusNode(nodeWidget);
-		}
-		dojo.stopEvent(e);
-	},
-	_onDblClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){
-		// summary:
-		//		Translates double-click events into commands for the controller to process
-
-		var domElement = e.target;
-
-		if( (this.openOnDblClick && nodeWidget.isExpandable) ||
-			(domElement == nodeWidget.expandoNode || domElement == nodeWidget.expandoNodeText) ){
-			// expando node was clicked, or label of a folder node was clicked; open it
-			if(nodeWidget.isExpandable){
-				this._onExpandoClick({node:nodeWidget});
-			}
-		}else{
-			this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } );
-			this.onDblClick(nodeWidget.item, nodeWidget, e);
-			this.focusNode(nodeWidget);
-		}
-		dojo.stopEvent(e);
-	},
-
-	_onExpandoClick: function(/*Object*/ message){
-		// summary:
-		//		User clicked the +/- icon; expand or collapse my children.
-		var node = message.node;
-
-		// If we are collapsing, we might be hiding the currently focused node.
-		// Also, clicking the expando node might have erased focus from the current node.
-		// For simplicity's sake just focus on the node with the expando.
-		this.focusNode(node);
-
-		if(node.isExpanded){
-			this._collapseNode(node);
-		}else{
-			this._expandNode(node);
-		}
-	},
-
-	onClick: function(/* dojo.data */ item, /*TreeNode*/ node, /*Event*/ evt){
-		// summary:
-		//		Callback when a tree node is clicked
-		// tags:
-		//		callback
-	},
-	onDblClick: function(/* dojo.data */ item, /*TreeNode*/ node, /*Event*/ evt){
-		// summary:
-		//		Callback when a tree node is double-clicked
-		// tags:
-		//		callback
-	},
-	onOpen: function(/* dojo.data */ item, /*TreeNode*/ node){
-		// summary:
-		//		Callback when a node is opened
-		// tags:
-		//		callback
-	},
-	onClose: function(/* dojo.data */ item, /*TreeNode*/ node){
-		// summary:
-		//		Callback when a node is closed
-		// tags:
-		//		callback
-	},
-
-	_getNextNode: function(node){
-		// summary:
-		//		Get next visible node
-
-		if(node.isExpandable && node.isExpanded && node.hasChildren()){
-			// if this is an expanded node, get the first child
-			return node.getChildren()[0];		// _TreeNode
-		}else{
-			// find a parent node with a sibling
-			while(node && node.isTreeNode){
-				var returnNode = node.getNextSibling();
-				if(returnNode){
-					return returnNode;		// _TreeNode
-				}
-				node = node.getParent();
-			}
-			return null;
-		}
-	},
-
-	_getRootOrFirstNode: function(){
-		// summary:
-		//		Get first visible node
-		return this.showRoot ? this.rootNode : this.rootNode.getChildren()[0];
-	},
-
-	_collapseNode: function(/*_TreeNode*/ node){
-		// summary:
-		//		Called when the user has requested to collapse the node
-
-		if(node._expandNodeDeferred){
-			delete node._expandNodeDeferred;
-		}
-
-		if(node.isExpandable){
-			if(node.state == "LOADING"){
-				// ignore clicks while we are in the process of loading data
-				return;
-			}
-
-			node.collapse();
-			this.onClose(node.item, node);
-
-			if(node.item){
-				this._state(node.item,false);
-				this._saveState();
-			}
-		}
-	},
-
-	_expandNode: function(/*_TreeNode*/ node, /*Boolean?*/ recursive){
-		// summary:
-		//		Called when the user has requested to expand the node
-		// recursive:
-		//		Internal flag used when _expandNode() calls itself, don't set.
-		// returns:
-		//		Deferred that fires when the node is loaded and opened and (if persist=true) all it's descendants
-		//		that were previously opened too
-
-		if(node._expandNodeDeferred && !recursive){
-			// there's already an expand in progress (or completed), so just return
-			return node._expandNodeDeferred;	// dojo.Deferred
-		}
-
-		var model = this.model,
-			item = node.item,
-			_this = this;
-
-		switch(node.state){
-			case "UNCHECKED":
-				// need to load all the children, and then expand
-				node.markProcessing();
-
-				// Setup deferred to signal when the load and expand are finished.
-				// Save that deferred in this._expandDeferred as a flag that operation is in progress.
-				var def = (node._expandNodeDeferred = new dojo.Deferred());
-
-				// Get the children
-				model.getChildren(
-					item,
-					function(items){
-						node.unmarkProcessing();
-
-						// Display the children and also start expanding any children that were previously expanded
-						// (if this.persist == true).   The returned Deferred will fire when those expansions finish.
-						var scid = node.setChildItems(items);
-
-						// Call _expandNode() again but this time it will just to do the animation (default branch).
-						// The returned Deferred will fire when the animation completes.
-						// TODO: seems like I can avoid recursion and just use a deferred to sequence the events?
-						var ed = _this._expandNode(node, true);
-
-						// After the above two tasks (setChildItems() and recursive _expandNode()) finish,
-						// signal that I am done.
-						scid.addCallback(function(){
-							ed.addCallback(function(){
-								def.callback();
-							})
-						});
-					},
-					function(err){
-						console.error(_this, ": error loading root children: ", err);
-					}
-				);
-				break;
-
-			default:	// "LOADED"
-				// data is already loaded; just expand node
-				def = (node._expandNodeDeferred = node.expand());
-
-				this.onOpen(node.item, node);
-
-				if(item){
-					this._state(item, true);
-					this._saveState();
-				}
-		}
-
-		return def;	// dojo.Deferred
-	},
-
-	////////////////// Miscellaneous functions ////////////////
-
-	focusNode: function(/* _tree.Node */ node){
-		// summary:
-		//		Focus on the specified node (which must be visible)
-		// tags:
-		//		protected
-
-		// set focus so that the label will be voiced using screen readers
-		dijit.focus(node.labelNode);
-	},
-
-	_onNodeFocus: function(/*dijit._Widget*/ node){
-		// summary:
-		//		Called when a TreeNode gets focus, either by user clicking
-		//		it, or programatically by arrow key handling code.
-		// description:
-		//		It marks that the current node is the selected one, and the previously
-		//		selected node no longer is.
-
-		if(node){
-			if(node != this.lastFocused && this.lastFocused && !this.lastFocused._destroyed){
-				// mark that the previously selected node is no longer the selected one
-				this.lastFocused.setSelected(false);
-			}
-
-			// mark that the new node is the currently selected one
-			node.setSelected(true);
-			this.lastFocused = node;
-		}
-	},
-
-	_onNodeMouseEnter: function(/*dijit._Widget*/ node){
-		// summary:
-		//		Called when mouse is over a node (onmouseenter event)
-	},
-
-	_onNodeMouseLeave: function(/*dijit._Widget*/ node){
-		// summary:
-		//		Called when mouse is over a node (onmouseenter event)
-	},
-
-	//////////////// Events from the model //////////////////////////
-
-	_onItemChange: function(/*Item*/ item){
-		// summary:
-		//		Processes notification of a change to an item's scalar values like label
-		var model = this.model,
-			identity = model.getIdentity(item),
-			nodes = this._itemNodesMap[identity];
-
-		if(nodes){
-			var self = this;
-			dojo.forEach(nodes,function(node){
-				node.attr({
-					label: self.getLabel(item),
-					tooltip: self.getTooltip(item)
-				});
-				node._updateItemClasses(item);
-			});
-		}
-	},
-
-	_onItemChildrenChange: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
-		// summary:
-		//		Processes notification of a change to an item's children
-		var model = this.model,
-			identity = model.getIdentity(parent),
-			parentNodes = this._itemNodesMap[identity];
-
-		if(parentNodes){
-			dojo.forEach(parentNodes,function(parentNode){
-				parentNode.setChildItems(newChildrenList);
-			});
-		}
-	},
-
-	_onItemDelete: function(/*Item*/ item){
-		// summary:
-		//		Processes notification of a deletion of an item
-		var model = this.model,
-			identity = model.getIdentity(item),
-			nodes = this._itemNodesMap[identity];
-
-		if(nodes){
-			dojo.forEach(nodes,function(node){
-				var parent = node.getParent();
-				if(parent){
-					// if node has not already been orphaned from a _onSetItem(parent, "children", ..) call...
-					parent.removeChild(node);
-				}
-				node.destroyRecursive();
-			});
-			delete this._itemNodesMap[identity];
-		}
-	},
-
-	/////////////// Miscellaneous funcs
-
-	_initState: function(){
-		// summary:
-		//		Load in which nodes should be opened automatically
-		if(this.persist){
-			var cookie = dojo.cookie(this.cookieName);
-			this._openedItemIds = {};
-			if(cookie){
-				dojo.forEach(cookie.split(','), function(item){
-					this._openedItemIds[item] = true;
-				}, this);
-			}
-		}
-	},
-	_state: function(item,expanded){
-		// summary:
-		//		Query or set expanded state for an item,
-		if(!this.persist){
-			return false;
-		}
-		var id=this.model.getIdentity(item);
-		if(arguments.length === 1){
-			return this._openedItemIds[id];
-		}
-		if(expanded){
-			this._openedItemIds[id] = true;
-		}else{
-			delete this._openedItemIds[id];
-		}
-	},
-	_saveState: function(){
-		// summary:
-		//		Create and save a cookie with the currently expanded nodes identifiers
-		if(!this.persist){
-			return;
-		}
-		var ary = [];
-		for(var id in this._openedItemIds){
-			ary.push(id);
-		}
-		dojo.cookie(this.cookieName, ary.join(","), {expires:365});
-	},
-
-	destroy: function(){
-		if(this._curSearch){
-			clearTimeout(this._curSearch.timer);
-			delete this._curSearch;
-		}
-		if(this.rootNode){
-			this.rootNode.destroyRecursive();
-		}
-		if(this.dndController && !dojo.isString(this.dndController)){
-			this.dndController.destroy();
-		}
-		this.rootNode = null;
-		this.inherited(arguments);
-	},
-
-	destroyRecursive: function(){
-		// A tree is treated as a leaf, not as a node with children (like a grid),
-		// but defining destroyRecursive for back-compat.
-		this.destroy();
-	},
-
-	resize: function(changeSize){
-		if(changeSize){
-			dojo.marginBox(this.domNode, changeSize);
-			dojo.style(this.domNode, "overflow", "auto");	// for scrollbars
-		}
-
-		// The only JS sizing involved w/tree is the indentation, which is specified
-		// in CSS and read in through this dummy indentDetector node (tree must be
-		// visible and attached to the DOM to read this)
-		this._nodePixelIndent = dojo.marginBox(this.tree.indentDetector).w;
-
-		if(this.tree.rootNode){
-			// If tree has already loaded, then reset indent for all the nodes
-			this.tree.rootNode.attr('indent', this.showRoot ? 0 : -1);
-		}
-	},
-
-	_createTreeNode: function(/*Object*/ args){
-		// summary:
-		//		creates a TreeNode
-		// description:
-		//		Developers can override this method to define their own TreeNode class;
-		//		However it will probably be removed in a future release in favor of a way
-		//		of just specifying a widget for the label, rather than one that contains
-		//		the children too.
-		return new dijit._TreeNode(args);
-	}
-});
-
-// For back-compat.  TODO: remove in 2.0
-
-
-
-}
-
-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: "",
-
-		//	selectOnClick: [const] Boolean
-		//		If true, all text will be selected when focused with mouse
-		selectOnClick: false,
-
-		templateString: dojo.cache("dijit.form", "templates/TextBox.html", "<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);
-			}
-		},
-
-		_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);
-
-			if(this._selectOnClickHandle){
-				this.disconnect(this._selectOnClickHandle);
-			}
-			if(this.selectOnClick && dojo.isMoz){
-				this.textbox.selectionStart = this.textbox.selectionEnd = undefined; // clear selection so that the next mouse click doesn't reselect
-			}
-		},
-
-		_onFocus: function(/*String*/ by){
-			if(this.disabled || this.readOnly){ return; }
-
-			// Select all text on focus via click if nothing already selected.
-			// Since mouse-up will clear the selection need to defer selection until after mouse-up.
-			// Don't do anything on focus by tabbing into the widgetm since there's no associated mouse-up event.
-			if(this.selectOnClick && by == "mouse"){
-				this._selectOnClickHandle = this.connect(this.domNode, "onmouseup", function(){
-					// Only select all text on first click; otherwise users would have no way to clear
-					// the selection.
-					this.disconnect(this._selectOnClickHandle);
-
-					// Check if the user selected some text manually (mouse-down, mouse-move, mouse-up)
-					// and if not, then select all the text
-					var textIsNotSelected;
-					if(dojo.isIE){
-						var range = dojo.doc.selection.createRange();
-						var parent = range.parentElement();
-						textIsNotSelected = parent == this.textbox && range.text.length == 0;
-					}else{
-						textIsNotSelected = this.textbox.selectionStart == this.textbox.selectionEnd;
-					}
-					if(textIsNotSelected){
-						dijit.selectInputText(this.textbox);
-					}
-				});
-			}
-
-			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; }
-	dijit.focus(element);
-	if(_document["selection"] && dojo.body()["createTextRange"]){ // IE
-		if(element.createTextRange){
-			var range = element.createTextRange();
-			with(range){
-				collapse(true);
-				moveStart("character", -99999); // move to 0
-				moveStart("character", start); // delta from 0 is the correct position
-				moveEnd("character", stop-start);
-				select();
-			}
-		}
-	}else if(_window["getSelection"]){
-		if(element.setSelectionRange){
-			element.setSelectionRange(start, stop);
-		}
-	}
-};
-
-}
-
-if(!dojo._hasResource["dijit.InlineEditBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.InlineEditBox"] = true;
-dojo.provide("dijit.InlineEditBox");
-
-
-
-
-
-
-
-
-
-
-dojo.declare("dijit.InlineEditBox",
-	dijit._Widget,
-	{
-	// summary:
-	//		An element with in-line edit capabilitites
-	//
-	// description:
-	//		Behavior for an existing node (`<p>`, `<div>`, `<span>`, etc.) so that
-	// 		when you click it, an editor shows up in place of the original
-	//		text.  Optionally, Save and Cancel button are displayed below the edit widget.
-	//		When Save is clicked, the text is pulled from the edit
-	//		widget and redisplayed and the edit widget is again hidden.
-	//		By default a plain Textarea widget is used as the editor (or for
-	//		inline values a TextBox), but you can specify an editor such as
-	//		dijit.Editor (for editing HTML) or a Slider (for adjusting a number).
-	//		An edit widget must support the following API to be used:
-	//			- displayedValue or value as initialization parameter,
-	//			and available through attr('displayedValue') / attr('value')
-	//			- void focus()
-	//			- DOM-node focusNode = node containing editable text
-
-	// editing: [readonly] Boolean
-	//		Is the node currently in edit mode?
-	editing: false,
-
-	// autoSave: Boolean
-	//		Changing the value automatically saves it; don't have to push save button
-	//		(and save button isn't even displayed)
-	autoSave: true,
-
-	// buttonSave: String
-	//		Save button label
-	buttonSave: "",
-
-	// buttonCancel: String
-	//		Cancel button label
-	buttonCancel: "",
-
-	// renderAsHtml: Boolean
-	//		Set this to true if the specified Editor's value should be interpreted as HTML
-	//		rather than plain text (ex: `dijit.Editor`)
-	renderAsHtml: false,
-
-	// editor: String
-	//		Class name for Editor widget
-	editor: "dijit.form.TextBox",
-
-	// editorWrapper: String
-	//		Class name for widget that wraps the editor widget, displaying save/cancel
-	//		buttons.
-	editorWrapper: "dijit._InlineEditor",
-
-	// editorParams: Object
-	//		Set of parameters for editor, like {required: true}
-	editorParams: {},
-
-	onChange: function(value){
-		// summary:
-		//		Set this handler to be notified of changes to value.
-		// tags:
-		//		callback
-	},
-
-	onCancel: function(){
-		// summary:
-		//		Set this handler to be notified when editing is cancelled.
-		// tags:
-		//		callback
-	},
-
-	// width: String
-	//		Width of editor.  By default it's width=100% (ie, block mode).
-	width: "100%",
-
-	// value: String
-	//		The display value of the widget in read-only mode
-	value: "",
-
-	// noValueIndicator: [const] String
-	//		The text that gets displayed when there is no value (so that the user has a place to click to edit)
-	noValueIndicator: "<span style='font-family: wingdings; text-decoration: underline;'>    &#x270d;    </span>",
-
-	constructor: function(){
-		// summary:
-		//		Sets up private arrays etc.
-		// tags:
-		//		private
-		this.editorParams = {};
-	},
-
-	postMixInProperties: function(){
-		this.inherited(arguments);
-
-		// save pointer to original source node, since Widget nulls-out srcNodeRef
-		this.displayNode = this.srcNodeRef;
-
-		// connect handlers to the display node
-		var events = {
-			ondijitclick: "_onClick",
-			onmouseover: "_onMouseOver",
-			onmouseout: "_onMouseOut",
-			onfocus: "_onMouseOver",
-			onblur: "_onMouseOut"
-		};
-		for(var name in events){
-			this.connect(this.displayNode, name, events[name]);
-		}
-		dijit.setWaiRole(this.displayNode, "button");
-		if(!this.displayNode.getAttribute("tabIndex")){
-			this.displayNode.setAttribute("tabIndex", 0);
-		}
-
-		this.attr('value', this.value || this.displayNode.innerHTML);
-	},
-
-	setDisabled: function(/*Boolean*/ disabled){
-		// summary:
-		//		Deprecated.   Use attr('disable', ...) instead.
-		// tags:
-		//		deprecated
-		dojo.deprecated("dijit.InlineEditBox.setDisabled() is deprecated.  Use attr('disabled', bool) instead.", "", "2.0");
-		this.attr('disabled', disabled);
-	},
-
-	_setDisabledAttr: function(/*Boolean*/ disabled){
-		// summary:
-		//		Hook to make attr("disabled", ...) work.
-		//		Set disabled state of widget.
-		this.disabled = disabled;
-		dijit.setWaiState(this.domNode, "disabled", disabled);
-		if(disabled){
-			this.displayNode.removeAttribute("tabIndex");
-		}else{
-			this.displayNode.setAttribute("tabIndex", 0);
-		}
-	},
-
-	_onMouseOver: function(){
-		// summary:
-		//		Handler for onmouseover event.
-		// tags:
-		//		private
-		dojo.addClass(this.displayNode, this.disabled ? "dijitDisabledClickableRegion" : "dijitClickableRegion");
-	},
-
-	_onMouseOut: function(){
-		// summary:
-		//		Handler for onmouseout event.
-		// tags:
-		//		private
-		dojo.removeClass(this.displayNode, this.disabled ? "dijitDisabledClickableRegion" : "dijitClickableRegion");
-	},
-
-	_onClick: function(/*Event*/ e){
-		// summary:
-		//		Handler for onclick event.
-		// tags:
-		//		private
-		if(this.disabled){ return; }
-		if(e){ dojo.stopEvent(e); }
-		this._onMouseOut();
-
-		// Since FF gets upset if you move a node while in an event handler for that node...
-		setTimeout(dojo.hitch(this, "edit"), 0);
-	},
-
-	edit: function(){
-		// summary:
-		//		Display the editor widget in place of the original (read only) markup.
-		// tags:
-		//		private
-
-		if(this.disabled || this.editing){ return; }
-		this.editing = true;
-
-		// save some display node values that can be restored later
-		this._savedPosition = dojo.style(this.displayNode, "position") || "static";
-		this._savedOpacity = dojo.style(this.displayNode, "opacity") || "1";
-		this._savedTabIndex = dojo.attr(this.displayNode, "tabIndex") || "0";
-
-		if(this.wrapperWidget){
-			this.wrapperWidget.editWidget.attr("displayedValue" in this.editorParams ? "displayedValue" : "value", this.value);
-		}else{
-			// Placeholder for edit widget
-			// Put place holder (and eventually editWidget) before the display node so that it's positioned correctly
-			// when Calendar dropdown appears, which happens automatically on focus.
-			var placeholder = dojo.create("span", null, this.domNode, "before");
-
-			// Create the editor wrapper (the thing that holds the editor widget and the save/cancel buttons)
-			var ewc = dojo.getObject(this.editorWrapper);
-			this.wrapperWidget = new ewc({
-				value: this.value,
-				buttonSave: this.buttonSave,
-				buttonCancel: this.buttonCancel,
-				tabIndex: this._savedTabIndex,
-				editor: this.editor,
-				inlineEditBox: this,
-				sourceStyle: dojo.getComputedStyle(this.displayNode),
-				save: dojo.hitch(this, "save"),
-				cancel: dojo.hitch(this, "cancel")
-			}, placeholder);
-		}
-		var ww = this.wrapperWidget;
-
-		if(dojo.isIE){
-			dijit.focus(dijit.getFocus()); // IE (at least 8) needs help with tab order changes
-		}
-		// to avoid screen jitter, we first create the editor with position:absolute, visibility:hidden,
-		// and then when it's finished rendering, we switch from display mode to editor
-		// position:absolute releases screen space allocated to the display node
-		// opacity:0 is the same as visibility:hidden but is still focusable
-		// visiblity:hidden removes focus outline
-
-		dojo.style(this.displayNode, { position: "absolute", opacity: "0", display: "none" }); // makes display node invisible, display style used for focus-ability
-		dojo.style(ww.domNode, { position: this._savedPosition, visibility: "visible", opacity: "1" });
-		dojo.attr(this.displayNode, "tabIndex", "-1"); // needed by WebKit for TAB from editor to skip displayNode
-
-		// Replace the display widget with edit widget, leaving them both displayed for a brief time so that
-		// focus can be shifted without incident.  (browser may needs some time to render the editor.)
-		setTimeout(dojo.hitch(this, function(){
-			ww.focus(); // both nodes are showing, so we can switch focus safely
-			ww._resetValue = ww.getValue();
-		}), 0);
-	},
-
-	_onBlur: function(){
-		// summary:
-		//		Called when focus moves outside the InlineEditBox.
-		//		Performs garbage collection.
-		// tags:
-		//		private
-
-		this.inherited(arguments);
-		if(!this.editing){
-			setTimeout(dojo.hitch(this, function(){
-				if(this.wrapperWidget){
-					this.wrapperWidget.destroy();
-					delete this.wrapperWidget;
-				}
-			}), 0);
-		}
-	},
-
-	_showText: function(/*Boolean*/ focus){
-		// summary:
-		//		Revert to display mode, and optionally focus on display node
-		// tags:
-		//		private
-
-		var ww = this.wrapperWidget;
-		dojo.style(ww.domNode, { position: "absolute", visibility: "hidden", opacity: "0" }); // hide the editor from mouse/keyboard events
-		dojo.style(this.displayNode, { position: this._savedPosition, opacity: this._savedOpacity, display: "" }); // make the original text visible
-		dojo.attr(this.displayNode, "tabIndex", this._savedTabIndex);
-		if(focus){
-			dijit.focus(this.displayNode);
-		}
-	},
-
-	save: function(/*Boolean*/ focus){
-		// summary:
-		//		Save the contents of the editor and revert to display mode.
-		// focus: Boolean
-		//		Focus on the display mode text
-		// tags:
-		//		private
-
-		if(this.disabled || !this.editing){ return; }
-		this.editing = false;
-
-		var ww = this.wrapperWidget;
-		var value = ww.getValue();
-		this.attr('value', value); // display changed, formatted value
-
-		// tell the world that we have changed
-		setTimeout(dojo.hitch(this, "onChange", value), 0); // setTimeout prevents browser freeze for long-running event handlers
-
-		this._showText(focus); // set focus as needed
-	},
-
-	setValue: function(/*String*/ val){
-		// summary:
-		//		Deprecated.   Use attr('value', ...) instead.
-		// tags:
-		//		deprecated
-		dojo.deprecated("dijit.InlineEditBox.setValue() is deprecated.  Use attr('value', ...) instead.", "", "2.0");
-		return this.attr("value", val);
-	},
-
-	_setValueAttr: function(/*String*/ val){
-		// summary:
-		// 		Hook to make attr("value", ...) work.
-		//		Inserts specified HTML value into this node, or an "input needed" character if node is blank.
-
-		this.value = val = dojo.trim(val);
-		if(!this.renderAsHtml){
-			val = val.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """).replace(/\n/g, "<br>");
-		}
-		this.displayNode.innerHTML = val || this.noValueIndicator;
-	},
-
-	getValue: function(){
-		// summary:
-		//		Deprecated.   Use attr('value') instead.
-		// tags:
-		//		deprecated
-		dojo.deprecated("dijit.InlineEditBox.getValue() is deprecated.  Use attr('value') instead.", "", "2.0");
-		return this.attr("value");
-	},
-
-	cancel: function(/*Boolean*/ focus){
-		// summary:
-		//		Revert to display mode, discarding any changes made in the editor
-		// tags:
-		//		private
-
-		if(this.disabled || !this.editing){ return; }
-		this.editing = false;
-
-		// tell the world that we have no changes
-		setTimeout(dojo.hitch(this, "onCancel"), 0); // setTimeout prevents browser freeze for long-running event handlers
-
-		this._showText(focus);
-	}
-});
-
-dojo.declare(
-	"dijit._InlineEditor",
-	 [dijit._Widget, dijit._Templated],
-{
-	// summary:
-	// 		Internal widget used by InlineEditBox, displayed when in editing mode
-	//		to display the editor and maybe save/cancel buttons.  Calling code should
-	//		connect to save/cancel methods to detect when editing is finished
-	//
-	//		Has mainly the same parameters as InlineEditBox, plus these values:
-	//
-	// style: Object
-	//		Set of CSS attributes of display node, to replicate in editor
-	//
-	// value: String
-	//		Value as an HTML string or plain text string, depending on renderAsHTML flag
-
-	templateString: dojo.cache("dijit", "templates/InlineEditBox.html", "<span dojoAttachPoint=\"editNode\" waiRole=\"presentation\" style=\"position: absolute; visibility:hidden\" class=\"dijitReset dijitInline\"\n\tdojoAttachEvent=\"onkeypress: _onKeyPress\"\n\t><span dojoAttachPoint=\"editorPlaceholder\"></span\n\t><span dojoAttachPoint=\"buttonContainer\"\n\t\t><button class='saveButton' dojoAttachPoint=\"saveButton\" dojoType=\"dijit.form.Button\" dojoAttachEvent=\"onClick:save\" label [...]
-	widgetsInTemplate: true,
-
-	postMixInProperties: function(){
-		this.inherited(arguments);
-		this.messages = dojo.i18n.getLocalization("dijit", "common", this.lang);
-		dojo.forEach(["buttonSave", "buttonCancel"], function(prop){
-			if(!this[prop]){ this[prop] = this.messages[prop]; }
-		}, this);
-	},
-
-	postCreate: function(){
-		// Create edit widget in place in the template
-		var cls = dojo.getObject(this.editor);
-
-		// Copy the style from the source
-		// Don't copy ALL properties though, just the necessary/applicable ones
-		var srcStyle = this.sourceStyle;
-		var editStyle = "line-height:" + srcStyle.lineHeight + ";";
-		dojo.forEach(["Weight","Family","Size","Style"], function(prop){
-			editStyle += "font-"+prop+":"+srcStyle["font"+prop]+";";
-		}, this);
-		dojo.forEach(["marginTop","marginBottom","marginLeft", "marginRight"], function(prop){
-			this.domNode.style[prop] = srcStyle[prop];
-		}, this);
-		var width = this.inlineEditBox.width;
-		if(width == "100%"){
-			// block mode
-			editStyle += "width:100%;";
-			this.domNode.style.display = "block";
-		}else{
-			// inline-block mode
-			editStyle += "width:" + (width + (Number(width) == width ? "px" : "")) + ";";
-		}
-		var editorParams = this.inlineEditBox.editorParams;
-		editorParams.style = editStyle;
-		editorParams[ "displayedValue" in cls.prototype ? "displayedValue" : "value"] = this.value;
-		var ew = this.editWidget = new cls(editorParams, this.editorPlaceholder);
-
-		if(this.inlineEditBox.autoSave){
-			// Hide the save/cancel buttons since saving is done by simply tabbing away or
-			// selecting a value from the drop down list
-			this.buttonContainer.style.display="none";
-
-			// Selecting a value from a drop down list causes an onChange event and then we save
-			this.connect(ew, "onChange", "_onChange");
-
-			// ESC and TAB should cancel and save.  Note that edit widgets do a stopEvent() on ESC key (to
-			// prevent Dialog from closing when the user just wants to revert the value in the edit widget),
-			// so this is the only way we can see the key press event.
-			this.connect(ew, "onKeyPress", "_onKeyPress");
-		}else{
-			// If possible, enable/disable save button based on whether the user has changed the value
-			if("intermediateChanges" in cls.prototype){
-				ew.attr("intermediateChanges", true);
-				this.connect(ew, "onChange", "_onIntermediateChange");
-				this.saveButton.attr("disabled", true);
-			}
-		}
-	},
-
-	_onIntermediateChange: function(val){
-		// summary:
-		//		Called for editor widgets that support the intermediateChanges=true flag as a way
-		//		to detect when to enable/disabled the save button
-		this.saveButton.attr("disabled", (this.getValue() == this._resetValue) || !this.enableSave());
-	},
-
-	destroy: function(){
-		this.editWidget.destroy(true); // let the parent wrapper widget clean up the DOM
-		this.inherited(arguments);
-	},
-
-	getValue: function(){
-		// summary:
-		//		Return the [display] value of the edit widget
-		var ew = this.editWidget;
-		return String(ew.attr("displayedValue" in ew ? "displayedValue" : "value"));
-	},
-
-	_onKeyPress: function(e){
-		// summary:
-		//		Handler for keypress in the edit box in autoSave mode.
-		// description:
-		//		For autoSave widgets, if Esc/Enter, call cancel/save.
-		// tags:
-		//		private
-
-		if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){
-			if(e.altKey || e.ctrlKey){ return; }
-			// If Enter/Esc pressed, treat as save/cancel.
-			if(e.charOrCode == dojo.keys.ESCAPE){
-				dojo.stopEvent(e);
-				this.cancel(true); // sets editing=false which short-circuits _onBlur processing
-			}else if(e.charOrCode == dojo.keys.ENTER && e.target.tagName == "INPUT"){
-				dojo.stopEvent(e);
-				this._onChange(); // fire _onBlur and then save
-			}
-
-			// _onBlur will handle TAB automatically by allowing
-			// the TAB to change focus before we mess with the DOM: #6227
-			// Expounding by request:
-			// 	The current focus is on the edit widget input field.
-			//	save() will hide and destroy this widget.
-			//	We want the focus to jump from the currently hidden
-			//	displayNode, but since it's hidden, it's impossible to
-			//	unhide it, focus it, and then have the browser focus
-			//	away from it to the next focusable element since each
-			//	of these events is asynchronous and the focus-to-next-element
-			//	is already queued.
-			//	So we allow the browser time to unqueue the move-focus event
-			//	before we do all the hide/show stuff.
-		}
-	},
-
-	_onBlur: function(){
-		// summary:
-		//		Called when focus moves outside the editor
-		// tags:
-		//		private
-
-		this.inherited(arguments);
-		if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){
-			if(this.getValue() == this._resetValue){
-				this.cancel(false);
-			}else if(this.enableSave()){
-				this.save(false);
-			}
-		}
-	},
-
-	_onChange: function(){
-		// summary:
-		//		Called when the underlying widget fires an onChange event,
-		//		such as when the user selects a value from the drop down list of a ComboBox,
-		//		which means that the user has finished entering the value and we should save.
-		// tags:
-		//		private
-
-		if(this.inlineEditBox.autoSave && this.inlineEditBox.editing && this.enableSave()){
-			dojo.style(this.inlineEditBox.displayNode, { display: "" });
-			dijit.focus(this.inlineEditBox.displayNode); // fires _onBlur which will save the formatted value
-		}
-	},
-
-	enableSave: function(){
-		// summary:
-		//		User overridable function returning a Boolean to indicate
-		// 		if the Save button should be enabled or not - usually due to invalid conditions
-		// tags:
-		//		extension
-		return (
-			this.editWidget.isValid
-			? this.editWidget.isValid()
-			: true
-		);
-	},
-
-	focus: function(){
-		// summary:
-		//		Focus the edit widget.
-		// tags:
-		//		protected
-
-		this.editWidget.focus();
-		setTimeout(dojo.hitch(this, function(){
-			if(this.editWidget.focusNode.tagName == "INPUT"){
-				dijit.selectInputText(this.editWidget.focusNode);
-			}
-		}), 0);
-	}
-});
-
-}
-
-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.DropDownButton"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.DropDownButton"] = true;
-dojo.provide("dijit.form.DropDownButton");
-
-
-
-}
-
-if(!dojo._hasResource["dijit.form.ComboButton"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.ComboButton"] = true;
-dojo.provide("dijit.form.ComboButton");
-
-
-}
-
-if(!dojo._hasResource["dijit.form.ToggleButton"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.ToggleButton"] = true;
-dojo.provide("dijit.form.ToggleButton");
-
-
-}
-
-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: dojo.cache("dijit.form", "templates/CheckBox.html", "<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",
-
-		// 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,
-
-		attributeMap: dojo.delegate(dijit.form.ToggleButton.prototype.attributeMap, {
-			readOnly: "focusNode"
-		}),
-
-		_setReadOnlyAttr: function(/*Boolean*/ value){
-			this.readOnly = value;
-			dojo.attr(this.focusNode, 'readOnly', value);
-			dijit.setWaiState(this.focusNode, "readonly", value);
-			this._setStateClass();
-		},
-
-		_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");
-			}
-		},
-
-		_onClick: function(/*Event*/ e){
-			// summary:
-			//		Internal function to handle click actions - need to check
-			//		readOnly, since button no longer does that check.
-			if(this.readOnly){
-				return false;
-			}
-			return this.inherited(arguments);
-		}
-	}
-);
-
-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.RadioButton"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.RadioButton"] = true;
-dojo.provide("dijit.form.RadioButton");
-
-
-// TODO: for 2.0, move the RadioButton code into this file
-
-}
-
-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: dojo.cache("dijit.form", "templates/ValidationTextBox.html", "<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\">Χ</div\n\t\t><div class=\"dijitReset dijitInputField\"\n\t\ [...]
-		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);
-			if(isEmpty){ this._maskValidSubsetError = true; }
-			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()
-			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);
-		},
-
-		_onBlur: function(){
-			this.displayMessage('');
-			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).
-			// Passing in name as markup rather than calling dojo.create() with an attrs argument
-			// to make dojo.query(input[name=...]) work on IE. (see #8660)
-			this.valueNode = dojo.place("<input type='hidden'" + (this.name ? " name='" + this.name + "'" : "") + ">", this.textbox, "after");
-		},
-
-		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
-			return	("min" in constraints? (this.compare(primitive,constraints.min) >= 0) : true) &&
-				("max" in constraints? (this.compare(primitive,constraints.max) <= 0) : 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;
-				min = this.compare(val, ((typeof min == "number") && min >= 0 && val !=0) ? 0 : min);
-				isTooLittle = (typeof min == "number") && min < 0;
-			}
-			if("max" in this.constraints){
-				var max = this.constraints.max;
-				max = this.compare(val, ((typeof max != "number") || max > 0) ? max : 0);
-				isTooMuch = (typeof max == "number") && max > 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
-			var v = this.attr('value');
-			if(v !== null && v !== '' && v !== undefined && !this.isInRange(isFocused)){ // don't check isInRange w/o a real value
-				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.cldr.monetary"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.cldr.monetary"] = true;
-dojo.provide("dojo.cldr.monetary");
-
-dojo.cldr.monetary.getData = function(/*String*/code){
-// summary: A mapping of currency code to currency-specific formatting information. Returns a unique object with properties: places, round.
-// code: an [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code
-
-// from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/currencyData/fractions
-
-	var placesData = {
-		ADP:0,BHD:3,BIF:0,BYR:0,CLF:0,CLP:0,DJF:0,ESP:0,GNF:0,
-		IQD:3,ITL:0,JOD:3,JPY:0,KMF:0,KRW:0,KWD:3,LUF:0,LYD:3,
-		MGA:0,MGF:0,OMR:3,PYG:0,RWF:0,TND:3,TRL:0,VUV:0,XAF:0,
-		XOF:0,XPF:0
-	};
-
-	var roundingData = {CHF:5};
-
-	var places = placesData[code], round = roundingData[code];
-	if(typeof places == "undefined"){ places = 2; }
-	if(typeof round == "undefined"){ round = 0; }
-
-	return {places: places, round: round}; // Object
-};
-
-}
-
-if(!dojo._hasResource["dojo.currency"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.currency"] = true;
-dojo.provide("dojo.currency");
-
-
-
-
-
-
-/*=====
-dojo.currency = {
-	// summary: localized formatting and parsing routines for currencies
-}
-=====*/
-
-dojo.currency._mixInDefaults = function(options){
-	options = options || {};
-	options.type = "currency";
-
-	// Get locale-depenent currency data, like the symbol
-	var bundle = dojo.i18n.getLocalization("dojo.cldr", "currency", options.locale) || {};
-
-	// Mixin locale-independent currency data, like # of places
-	var iso = options.currency;
-	var data = dojo.cldr.monetary.getData(iso);
-
-	dojo.forEach(["displayName","symbol","group","decimal"], function(prop){
-		data[prop] = bundle[iso+"_"+prop];
-	});
-
-	data.fractional = [true, false];
-
-	// Mixin with provided options
-	return dojo.mixin(data, options);
-}
-
-/*=====
-dojo.declare("dojo.currency.__FormatOptions", [dojo.number.__FormatOptions], {
-	//	type: String?
-	//		Should not be set.  Value is assumed to be currency.
-	//	currency: String?
-	//		an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD".
-	//		For use with dojo.currency only.
-	//	symbol: String?
-	//		localized currency symbol. The default will be looked up in table of supported currencies in `dojo.cldr`
-	//		A [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code will be used if not found.
-	//	places: Number?
-	//		number of decimal places to show.  Default is defined based on which currency is used.
-	type: "",
-	symbol: "",
-	places: "",
-	fractional: ""
-});
-=====*/
-
-dojo.currency.format = function(/*Number*/value, /*dojo.currency.__FormatOptions?*/options){
-// summary:
-//		Format a Number as a currency, using locale-specific settings
-//
-// description:
-//		Create a string from a Number using a known, localized pattern.
-//		[Formatting patterns](http://www.unicode.org/reports/tr35/#Number_Elements) appropriate to the locale are chosen from the [CLDR](http://unicode.org/cldr)
-//		as well as the appropriate symbols and delimiters.
-//
-// value:
-//		the number to be formatted.
-
-	return dojo.number.format(value, dojo.currency._mixInDefaults(options));
-}
-
-dojo.currency.regexp = function(/*dojo.number.__RegexpOptions?*/options){
-//
-// summary:
-//		Builds the regular needed to parse a currency value
-//
-// description:
-//		Returns regular expression with positive and negative match, group and decimal separators
-//		Note: the options.places default, the number of decimal places to accept, is defined by the currency type.
-	return dojo.number.regexp(dojo.currency._mixInDefaults(options)); // String
-}
-
-/*=====
-dojo.declare("dojo.currency.__ParseOptions", [dojo.number.__ParseOptions], {
-	//	type: String?
-	//		Should not be set.  Value is assumed to be currency.
-	//	currency: String?
-	//		an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD".
-	//		For use with dojo.currency only.
-	//	symbol: String?
-	//		localized currency symbol. The default will be looked up in table of supported currencies in `dojo.cldr`
-	//		A [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code will be used if not found.
-	//	places: Number?
-	//		number of decimal places to accept.  Default is defined based on which currency is used.
-	//	fractional: Boolean?|Array?
-	//		Whether to include the fractional portion, where the number of decimal places are implied by pattern
-	//		or explicit 'places' parameter.  By default for currencies, it the fractional portion is optional.
-	type: "",
-	symbol: "",
-	places: "",
-	fractional: ""
-});
-=====*/
-
-dojo.currency.parse = function(/*String*/expression, /*dojo.currency.__ParseOptions?*/options){
-	//
-	// summary:
-	//		Convert a properly formatted currency string to a primitive Number,
-	//		using locale-specific settings.
-	//
-	// description:
-	//		Create a Number from a string using a known, localized pattern.
-	//		[Formatting patterns](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) are chosen appropriate to the locale.
-	//
-	// expression: A string representation of a Number
-
-	return dojo.number.parse(expression, dojo.currency._mixInDefaults(options));
-}
-
-}
-
-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], {
-	// summary:
-	//		Specifies both the rules on valid/invalid values (minimum, maximum,
-	//		number of required decimal places), and also formatting options for
-	//		displaying the value when the field is not focused.
-	// example:
-	//		Minimum/maximum:
-	//		To specify a field between 0 and 120:
-	//	|		{min:0,max:120}
-	//		To specify a field that must be an integer:
-	//	|		{fractional:false}
-	//		To specify a field where 0 to 3 decimal places are allowed on input,
-	//		but after the field is blurred the value is displayed with 3 decimal places:
-	//	|		{places:'0,3'}
-});
-=====*/
-
-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
-		//		Despite the name, this parameter specifies both constraints on the input
-		//		(including minimum/maximum allowed values) as well as
-		//		formatting options like places (the number of digits to display after
-		//		the decimal point).   See `dijit.form.NumberTextBox.__Constraints` for details.
-		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(){
-			var places = typeof this.constraints.places == "number"? this.constraints.places : 0;
-			if(places){ places++; } // decimal rounding errors take away another digit of precision
-			if(typeof this.constraints.max != "number"){
-				this.constraints.max = 9 * Math.pow(10, 15-places);
-			}
-			if(typeof this.constraints.min != "number"){
-				this.constraints.min = -9 * Math.pow(10, 15-places);
-			}
-			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({}, constraints, this.editOptions);
-			}
-			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(this.constraints.exponent !== false && /\de[-+]?|\d/i.test(this.textbox.value) && (new RegExp("^"+dojo.number._realNumberRegexp(dojo.mixin({}, this.constraints))+"$").test(this.textbox.value))){	// check for exponential notation that parse() rejected (erroneously?)
-					var n = Number(this.textbox.value);
-					return isNaN(n) ? undefined : n; // return exponential Number or undefined for random text (may not be possible to do with the above RegExp check)
-				}else{
-					return undefined; // gibberish
-				}
-			}else{
-				return v; // Number or NaN for ''
-			}
-		},
-
-		isValid: function(/*Boolean*/ isFocused){
-			// Overrides dijit.form.RangeBoundTextBox.isValid to check that the editing-mode value is valid since
-			// it may not be formatted according to the regExp vaidation rules
-			if(!this._focused || this._isEmpty(this.textbox.value)){
-				return this.inherited(arguments);
-			}else{
-				var v = this.attr('value');
-				if(!isNaN(v) && this.rangeCheck(v, this.constraints)){
-					if(this.constraints.exponent !== false && /\de[-+]?\d/i.test(this.textbox.value)){ // exponential, parse doesn't like it
-						return true; // valid exponential number in range
-					}else{
-						return this.inherited(arguments);
-					}
-				}else{
-					return false;
-				}
-			}
-		}
-	}
-);
-
-dojo.declare("dijit.form.NumberTextBox",
-	[dijit.form.RangeBoundTextBox,dijit.form.NumberTextBoxMixin],
-	{
-		// summary:
-		//		A TextBox for entering numbers, with formatting and range checking
-		// description:
-		//		NumberTextBox is a textbox for entering and displaying numbers, supporting
-		//		the following main features:
-		//
-		//			1. Enforce minimum/maximum allowed values (as well as enforcing that the user types
-		//				a number rather than a random string)
-		//			2. NLS support (altering roles of comma and dot as "thousands-separator" and "decimal-point"
-		//				depending on locale).
-		//			3. Separate modes for editing the value and displaying it, specifically that
-		//				the thousands separator character (typically comma) disappears when editing
-		//				but reappears after the field is blurred.
-		//			4. Formatting and constraints regarding the number of places (digits after the decimal point)
-		//				allowed on input, and number of places displayed when blurred (see `constraints` parameter).
-	}
-);
-
-}
-
-if(!dojo._hasResource["dijit.form.CurrencyTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.CurrencyTextBox"] = true;
-dojo.provide("dijit.form.CurrencyTextBox");
-
-
-
-
-/*=====
-dojo.declare(
-	"dijit.form.CurrencyTextBox.__Constraints",
-	[dijit.form.NumberTextBox.__Constraints, dojo.currency.__FormatOptions, dojo.currency.__ParseOptions], {
-	// summary:
-	//		Specifies both the rules on valid/invalid values (minimum, maximum,
-	//		number of required decimal places), and also formatting options for
-	//		displaying the value when the field is not focused (currency symbol,
-	//		etc.)
-	// description:
-	//		Follows the pattern of `dijit.form.NumberTextBox.constraints`.
-	//		In general developers won't need to set this parameter
-	// example:
-	//		To ensure that the user types in the cents (for example, 1.00 instead of just 1):
-	//	|		{fractional:true}
-});
-=====*/
-
-dojo.declare(
-	"dijit.form.CurrencyTextBox",
-	dijit.form.NumberTextBox,
-	{
-		// summary:
-		//		A validating currency textbox
-		// description:
-		//		CurrencyTextBox is similar to `dijit.form.NumberTextBox` but has a few
-		//		extra features related to currency:
-		//
-		//		1. After specifying the currency type (american dollars, euros, etc.) it automatically
-		//			sets parse/format options such as how many decimal places to show.
-		//		2. The currency mark (dollar sign, euro mark, etc.) is displayed when the field is blurred
-		//			but erased during editing, so that the user can just enter a plain number.
-
-		// currency: String
-		//		the [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD"
-		currency: "",
-
-		// constraints: dijit.form.CurrencyTextBox.__Constraints
-		//		Despite the name, this parameter specifies both constraints on the input
-		//		(including minimum/maximum allowed values) as well as
-		//		formatting options.   See `dijit.form.CurrencyTextBox.__Constraints` for details.
-		/*=====
-		constraints: {},
-		======*/
-
-		// Override regExpGen ValidationTextBox.regExpGen().... we use a reg-ex generating function rather
-		// than a straight regexp to deal with locale  (plus formatting options too?)
-		regExpGen: function(constraints){
-			// if focused, accept either currency data or NumberTextBox format
-			return '(' + (this._focused? this.inherited(arguments, [ dojo.mixin({}, constraints, this.editOptions) ]) + '|' : '')
-				+ dojo.currency.regexp(constraints) + ')';
-		},
-
-		// Override NumberTextBox._formatter to deal with currencies, ex: converts "123.45" to "$123.45"
-		_formatter: dojo.currency.format,
-
-		parse: function(/* String */ value, /* Object */ constraints){
-			// summary:
-			// 		Parses string value as a Currency, according to the constraints object
-			// tags:
-			// 		protected extension
-			var v = dojo.currency.parse(value, constraints);
-			if(isNaN(v) && /\d+/.test(value)){ // currency parse failed, but it could be because they are using NumberTextBox format so try its parse
-				return this.inherited(arguments, [ value, dojo.mixin({}, constraints, this.editOptions) ]);
-			}
-			return v;
-		},
-
-
-		postMixInProperties: function(){
-			this.constraints = dojo.currency._mixInDefaults(dojo.mixin(this.constraints, { currency: this.currency, exponent: false })); // get places
-			this.inherited(arguments);
-		}
-	}
-);
-
-}
-
-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.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(+date1);
-	date2 = new Date(+(date2 || new Date()));
-
-	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(+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":
-		default:
-			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.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, options, pattern){
-		return pattern.replace(/([a-z])\1*/ig, function(match){
-			var s, pad,
-				c = match.charAt(0),
-				l = match.length,
-				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(!options.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.locale._getZone(dateObject, true, options);
-					if(s){break;}
-					l=4;
-					// fallthrough... use GMT if tz not available
-				case 'Z':
-					var offset = dojo.date.locale._getZone(dateObject, false, options);
-					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':
-//					console.log(match+" modifier unimplemented");
-				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._getZone = function(/*Date*/dateObject, /*boolean*/getName, /*dojo.date.locale.__FormatOptions?*/options){
-	// summary:
-	//		Returns the zone (or offset) for the given date and options.  This
-	//		is broken out into a separate function so that it can be overridden
-	//		by timezone-aware code.
-	//
-	// dateObject:
-	//		the date and/or time being formatted.
-	//
-	// getName:
-	//		Whether to return the timezone string (if true), or the offset (if false)
-	//
-	// options:
-	//		The options being used for formatting
-	if(getName){
-		return dojo.date.getTimezoneName(dateObject);
-	}else{
-		return dateObject.getTimezoneOffset();
-	}
-};
-
-
-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),
-		formatLength = options.formatLength || 'short',
-		bundle = dojo.date.locale._getGregorianBundle(locale),
-		str = [],
-		sauce = dojo.hitch(this, formatPattern, dateObject, bundle, options);
-	if(options.selector == "year"){
-		return _processPattern(bundle["dateFormatItem-yyyy"] || "yyyy", sauce);
-	}
-	var pattern;
-	if(options.selector != "date"){
-		pattern = options.timePattern || bundle["timeFormat-"+formatLength];
-		if(pattern){str.push(_processPattern(pattern, sauce));}
-	}
-	if(options.selector != "time"){
-		pattern = options.datePattern || bundle["dateFormat-"+formatLength];
-		if(pattern){str.push(_processPattern(pattern, sauce));}
-	}
-
-	return str.length == 1 ? str[0] : bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g,
-		function(match, key){ return str[key]; }); // 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),
-		bundle = dojo.date.locale._getGregorianBundle(locale),
-		formatLength = options.formatLength || 'short',
-		datePattern = options.datePattern || bundle["dateFormat-" + formatLength],
-		timePattern = options.timePattern || bundle["timeFormat-" + formatLength],
-		pattern;
-	if(options.selector == 'date'){
-		pattern = datePattern;
-	}else if(options.selector == 'time'){
-		pattern = timePattern;
-	}else{
-		pattern = bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g,
-			function(match, key){ return [timePattern, datePattern][key]; });
-	}
-
-	var tokens = [],
-		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),
-		tokens = info.tokens, bundle = info.bundle,
-		re = new RegExp("^" + info.regexp + "$", info.strict ? "" : "i"),
-		match = re.exec(value);
-
-	if(!match){ return null; } // null
-
-	var widthList = ['abbr', 'wide', 'narrow'],
-		result = [1970,0,1,0,0,0,0], // will get converted to a Date at the end
-		amPm = "",
-		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(),
-							century = year.substring(0, 2) * 100,
-							cutoff = Math.min(Number(year.substring(2, 4)) + 20, 99),
-							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){
-//						console.log("dojo.date.locale.parse: Could not parse month name: '" + v + "'.");
-						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){
-//					console.log("dojo.date.locale.parse: Could not parse weekday name: '" + v + "'.");
-					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){
-//					console.log("dojo.date.locale.parse: Could not parse am/pm part.");
-					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){
-//					console.log("dojo.date.locale.parse: Illegal hours value");
-					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?
-//				console.log("dojo.date.locale.parse: unsupported pattern char=" + token.charAt(0));
-		}
-		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),
-		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,
-			c = match.charAt(0),
-			l = match.length,
-			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 = ".*";
-//				console.log("parse of date format, pattern=" + pattern);
-		}
-
-		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,
-		lookup = dojo.date.locale._getGregorianBundle(locale),
-		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),
-		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(),
-		adj = (firstDayOfYear - firstDayOfWeek + 7) % 7,
-		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.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 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: dojo.cache("dijit", "templates/Calendar.html", "<table cellspacing=\"0\" cellpadding=\"0\" class=\"dijitCalendarContainer\" role=\"grid\" dojoAttachEvent=\"onkeypress: _onKeyPress\">\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\ [...]
-
-		// value: Date
-		//		The currently selected Date
-		value: new Date(),
-
-		// datePackage: String
-		//		JavaScript namespace to find Calendar routines.  Uses Gregorian Calendar routines
-		//		at dojo.date by default.
-		datePackage: "dojo.date",
-
-		// dayWidth: String
-		//		How to represent the days of the week in the calendar header. See dojo.date.locale
-		dayWidth: "narrow",
-
-		// tabIndex: Integer
-		//		Order fields are traversed when user hits the tab key
-		tabIndex: "0",
-
-		attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-			tabIndex: "domNode"
- 		}),
-
-		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(){
-			// summary:
-			//		Support getter attr('value')
-			var value = new this.dateClassObj(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 = this.dateFuncObj.add(value, "hour", 1);
-			}
-			return value;
-		},
-
-		_setValueAttr: function(/*Date*/ value){
-			// summary:
-			//		Support setter attr("value", ...)
-			// description:
-			// 		Set the current date and update the UI.  If the date is disabled, the value will
-			//		not change, but the display will change to the corresponding month.
-			// tags:
-			//      protected
-			if(!this.value || this.dateFuncObj.compare(value, this.value)){
-				value = new this.dateClassObj(value);
-				value.setHours(1); // to avoid issues when DST shift occurs at midnight, see #8521, #9366
-				this.displayMonth = new this.dateClassObj(value);
-				if(!this.isDisabledDate(value, this.lang)){
-					this.value = value;
-					this.onChange(this.attr('value'));
-				}
-				dojo.attr(this.domNode, "aria-label",
-					this.dateLocaleModule.format(value,
-						{selector:"date", formatLength:"full"}));
-				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(),
-				daysInMonth = this.dateFuncObj.getDaysInMonth(month),
-				daysInPreviousMonth = this.dateFuncObj.getDaysInMonth(this.dateFuncObj.add(month, "month", -1)),
-				today = new this.dateClassObj(),
-				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 this.dateClassObj(month),
-					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 = this.dateFuncObj.add(date, "month", adj);
-				}
-				date.setDate(number);
-
-				if(!this.dateFuncObj.compare(date, today, "date")){
-					clazz = "dijitCalendarCurrentDate " + clazz;
-				}
-
-				if(this._isSelectedDate(date, this.lang)){
-					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],
-					text = date.getDateLocalized ? date.getDateLocalized(this.lang) : date.getDate();
-				this._setText(label, text);
-			}, this);
-
-			// Fill in localized month name
-			var monthNames = this.dateLocaleModule.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 this.dateClassObj();
-			dojo.forEach(["previous", "current", "next"], function(name){
-				d.setFullYear(y++);
-				this._setText(this[name+"YearLabelNode"],
-					this.dateLocaleModule.format(d, {selector:'year', locale:this.lang}));
-			}, this);
-
-			// Set up repeating mouse behavior
-			var _this = this;
-			var typematic = function(nodeProp, dateProp, adj){
-//FIXME: leaks (collects) listeners if populateGrid is called multiple times.  Do this once?
-				_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 this.dateClassObj());
-		},
-
-		constructor: function(/*Object*/args){
-			var dateClass = (args.datePackage && (args.datePackage != "dojo.date"))? args.datePackage + ".Date" : "Date";
-			this.dateClassObj = dojo.getObject(dateClass, false);
-			this.datePackage = args.datePackage || this.datePackage;
-			this.dateFuncObj = dojo.getObject(this.datePackage, false);
-			this.dateLocaleModule = dojo.getObject(this.datePackage + ".locale", false);
-		},
-
-		postMixInProperties: function(){
-			// parser.instantiate sometimes passes in NaN for IE.  Use default value in prototype instead.
-			if(isNaN(this.value)){ delete this.value; }
-			this.inherited(arguments);
-		},
-
-		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 = this.dateLocaleModule.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/month dropdown element with all the month names (invisible) so that the maximum width will affect layout
-			var monthNames = this.dateLocaleModule.getNames('months', 'wide', 'standAlone', this.lang);
-			cloneClass(".dijitCalendarMonthLabelTemplate", monthNames.length-1);
-			dojo.query(".dijitCalendarMonthLabelTemplate", this.domNode).forEach(function(node, i){
-				dojo.attr(node, "month", i);
-				this._setText(node, monthNames[i]);
-				dojo.place(node.cloneNode(true), this.monthLabelSpacer);
-			}, this);
-
-			var value = this.value;
-			this.value = null;
-			this.attr('value', new this.dateClassObj(value));
-		},
-
-		_onMenuHover: function(e){
-			dojo.stopEvent(e);
-			dojo.toggleClass(e.target, "dijitMenuItemHover");
-		},
-
-		_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 = this.dateFuncObj.add(this.displayMonth, part, amount);
-			this._populateGrid();
-		},
-
-		_onMonthToggle: function(/*Event*/ evt){
-			// summary:
-			//      Handler for when user triggers or dismisses the month list
-			// tags:
-			//      protected
-			dojo.stopEvent(evt);
-
-			if(evt.type == "mousedown"){
-				var coords = dojo.position(this.monthLabelNode);
-//				coords.y -= dojo.position(this.domNode, true).y;
-				// Size the dropdown's width to match the label in the widget
-				// so that they are horizontally aligned
-				var dim = {
-					width: coords.w + "px",
-					top: -this.displayMonth.getMonth() * coords.h + "px"
-				};
-				if((dojo.isIE && dojo.isQuirks) || dojo.isIE < 7){
-					dim.left = -coords.w/2 + "px";
-				}
-				dojo.style(this.monthDropDown, dim);
-				this._popupHandler = this.connect(document, "onmouseup", "_onMonthToggle");
-			}else{
-				this.disconnect(this._popupHandler);
-				delete this._popupHandler;
-			}
-
-			dojo.toggleClass(this.monthDropDown, "dijitHidden");
-			dojo.toggleClass(this.monthLabelNode, "dijitVisible");
-		},
-
-		_onMonthSelect: function(/*Event*/ evt){
-			// summary:
-			//      Handler for when user selects a month from a list
-			// tags:
-			//      protected
-			this._onMonthToggle(evt);
-			this.displayMonth.setMonth(dojo.attr(evt.target, "month"));
-			this._populateGrid();
-		},
-
-		_onDayClick: function(/*Event*/ evt){
-			// summary:
-			//      Handler for day clicks, selects the date if appropriate
-			// 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 mouse over events on days, sets up hovered style
-			// 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 mouse out events on days, clears hovered style
-			// 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;
-		},
-
-//TODO: use typematic
-//TODO: skip disabled dates without ending up in a loop
-//TODO: could optimize by avoiding populate grid when month does not change
-		_onKeyPress: function(/*Event*/evt){
-			// summary:
-			//		Provides keyboard navigation of calendar
-			// tags:
-			//		protected
-			var dk = dojo.keys,
-				increment = -1,
-				interval,
-				newValue = this.value;
-			switch(evt.keyCode){
-				case dk.RIGHT_ARROW:
-					increment = 1;
-					//fallthrough...
-				case dk.LEFT_ARROW:
-					interval = "day";
-					if(!this.isLeftToRight()){ increment *= -1; }
-					break;
-				case dk.DOWN_ARROW:
-					increment = 1;
-					//fallthrough...
-				case dk.UP_ARROW:
-					interval = "week";
-					break;
-				case dk.PAGE_DOWN:
-					increment = 1;
-					//fallthrough...
-				case dk.PAGE_UP:
-					interval = evt.ctrlKey ? "year" : "month";
-					break;
-				case dk.END:
-					// go to the next month
-					newValue = this.dateFuncObj.add(newValue, "month", 1);
-					// subtract a day from the result when we're done
-					interval = "day";
-					//fallthrough...
-				case dk.HOME:
-					newValue = new Date(newValue).setDate(1);
-					break;
-				case dk.ENTER:
-					this.onValueSelected(this.attr('value'));
-					break;
-				case dk.ESCAPE:
-					//TODO
-				default:
-					return;
-			}
-			dojo.stopEvent(evt);
-
-			if(interval){
-				newValue = this.dateFuncObj.add(newValue, interval, increment);
-			}
-
-			this.attr("value", newValue);
-		},
-
-		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
-		},
-
-		_isSelectedDate: function(/*Date*/ dateObject, /*String?*/ locale){
-			// summary:
-			//		Extension point so developers can subclass Calendar to
-			//		support multiple (concurrently) selected dates
-			// tags:
-			//		protected extension
-			return !this.dateFuncObj.compare(dateObject, this.value, "date")
-		},
-
-		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["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], {
-	// summary:
-	//		Specifies both the rules on valid/invalid values (first/last date/time allowed),
-	//		and also formatting options for how the date/time is displayed.
-	// example:
-	//		To restrict to dates within 2004, displayed in a long format like "December 25, 2005":
-	//	|		{min:'2004-01-01',max:'2004-12-31', formatLength:'long'}
-});
-=====*/
-
-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
-		//		Despite the name, this parameter specifies both constraints on the input
-		//		(including starting/ending dates/times allowed) as well as
-		//		formatting options like whether the date is displayed in long (ex: December 25, 2005)
-		//		or short (ex: 12/25/2005) format.   See `dijit.form._DateTimeTextBox.__Constraints` for details.
-		/*=====
-		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,
-
-		// datePackage: String
-		//	JavaScript namespace to find calendar routines.  Uses Gregorian calendar routines
-		//	at dojo.date, by default.
-		datePackage: "dojo.date",
-
-		// 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 this.dateLocaleModule.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 this.dateLocaleModule.parse(value, constraints) || (this._isEmpty(value) ? null : undefined);	 // Date
-		},
-
-		// Overrides ValidationTextBox.serialize() to serialize a date in canonical ISO format.
-		serialize: function(/*anything*/val, /*Object?*/options){
-			if(val.toGregorian){
-				val = val.toGregorian();
-			}
-			return dojo.date.stamp.toISOString(val, options);
-		},
-
-		// 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: "",
-
-		constructor: function(/*Object*/args){
-			var dateClass = args.datePackage ? args.datePackage + ".Date" : "Date";
-			this.dateClassObj = dojo.getObject(dateClass, false);
-			this.value = new this.dateClassObj("");
-
-			this.datePackage = args.datePackage || this.datePackage;
-			this.dateLocaleModule = dojo.getObject(this.datePackage + ".locale", false);
-			this.regExpGen = this.dateLocaleModule.regexp;
-		},
-
-		postMixInProperties: function(){
-			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 popup
-			this._open();
-			this.inherited(arguments);
-		},
-
-		_setValueAttr: function(/*Date*/ value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
-			// summary:
-			//		Sets the date on this textbox.  Note that `value` must be like a Javascript Date object.
-			if(value instanceof Date && !(this.dateClassObj instanceof Date)){
-				value = new this.dateClassObj(value);
-			}
-
-			this.inherited(arguments);
-			if(this._picker){
-				// #3948: fix blank date on popup only
-				if(!value){value = new this.dateClassObj();}
-				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);
-					},
-					id: this.id + "_popup",
-					lang: textBox.lang,
-					constraints: textBox.constraints,
-
-					datePackage: textBox.datePackage,
-
-					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, textBox._selector) > 0) ||
-							(constraints.max && compare(constraints.max, date, textBox._selector) < 0));
-					}
-				});
-				this._picker.attr('value', this.attr('value') || new this.dateClassObj());
-			}
-			if(!this._opened){
-				// Open drop down.  Align left sides of input box and drop down, even in RTL mode,
-				// otherwise positioning thrown off when the drop down width is changed in marginBox call below (#10676)
-				dijit.popup.open({
-					parent: this,
-					popup: this._picker,
-					orient: {'BL':'TL', 'TL':'BL'},
-					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);
-			this.connect(this.focusNode, 'onclick', this._open);
-		},
-
-		_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 || e.metaKey)){
-				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
-		//
-		//		Example:
-		// |	new dijit.form.DateTextBox({value: new Date(2009, 0, 20)})
-		//
-		//		Example:
-		// |	<input dojotype='dijit.form.DateTextBox' value='2009-01-20'>
-
-		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.
-		//		If specified in markup, use the format specified in `dojo.date.stamp.fromISOString`
-		value: new Date("")	// value.toString()="NaN"
-	}
-);
-
-}
-
-if(!dojo._hasResource["dijit.form._Spinner"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form._Spinner"] = true;
-dojo.provide("dijit.form._Spinner");
-
-
-
-dojo.declare(
-	"dijit.form._Spinner",
-	dijit.form.RangeBoundTextBox,
-	{
-		// summary:
-		//		Mixin for validation widgets with a spinner.
-		// description:
-		//		This class basically (conceptually) extends `dijit.form.ValidationTextBox`.
-		//		It modifies the template to have up/down arrows, and provides related handling code.
-
-		// defaultTimeout: Number
-		//		Number of milliseconds before a held arrow key or up/down button becomes typematic
-		defaultTimeout: 500,
-
-		// timeoutChangeRate: Number
-		//		Fraction of time used to change the typematic timer between events.
-		//		1.0 means that each typematic event fires at defaultTimeout intervals.
-		//		< 1.0 means that each typematic event fires at an increasing faster rate.
-		timeoutChangeRate: 0.90,
-
-		// smallDelta: Number
-		//	  Adjust the value by this much when spinning using the arrow keys/buttons
-		smallDelta: 1,
-
-		// largeDelta: Number
-		//	  Adjust the value by this much when spinning using the PgUp/Dn keys
-		largeDelta: 10,
-
-		templateString: dojo.cache("dijit.form", "templates/Spinner.html", "<div class=\"dijit dijitReset dijitInlineTable dijitLeft\"\n\tid=\"widget_${id}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\" waiRole=\"presentation\"\n\t><div class=\"dijitInputLayoutContainer\"\n\t\t><div class=\"dijitReset dijitSpinnerButtonContainer\"\n\t\t\t> <div class=\"dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitUpArrowButton\"\n\t\t\t\tdojoAttachP [...]
-		baseClass: "dijitSpinner",
-
-		adjust: function(/* Object */ val, /*Number*/ delta){
-			// summary:
-			//		Overridable function used to adjust a primitive value(Number/Date/...) by the delta amount specified.
-			// 		The val is adjusted in a way that makes sense to the object type.
-			// tags:
-			//		protected extension
-			return val;
-		},
-
-		_arrowState: function(/*Node*/ node, /*Boolean*/ pressed){
-			// summary:
-			//		Called when an arrow key is pressed to update the relevant CSS classes
-			this._active = pressed;
-			this.stateModifier = node.getAttribute("stateModifier") || "";
-			this._setStateClass();
-		},
-
-		_arrowPressed: function(/*Node*/ nodePressed, /*Number*/ direction, /*Number*/ increment){
-			// summary:
-			//		Handler for arrow button or arrow key being pressed
-			if(this.disabled || this.readOnly){ return; }
-			this._arrowState(nodePressed, true);
-			this._setValueAttr(this.adjust(this.attr('value'), direction*increment), false);
-			dijit.selectInputText(this.textbox, this.textbox.value.length);
-		},
-
-		_arrowReleased: function(/*Node*/ node){
-			// summary:
-			//		Handler for arrow button or arrow key being released
-			this._wheelTimer = null;
-			if(this.disabled || this.readOnly){ return; }
-			this._arrowState(node, false);
-		},
-
-		_typematicCallback: function(/*Number*/ count, /*DOMNode*/ node, /*Event*/ evt){
-			var inc=this.smallDelta;
-			if(node == this.textbox){
-				var k=dojo.keys;
-				var key = evt.charOrCode;
-				inc = (key == k.PAGE_UP || key == k.PAGE_DOWN) ? this.largeDelta : this.smallDelta;
-				node = (key == k.UP_ARROW || key == k.PAGE_UP) ? this.upArrowNode : this.downArrowNode;
-			}
-			if(count == -1){ this._arrowReleased(node); }
-			else{ this._arrowPressed(node, (node == this.upArrowNode) ? 1 : -1, inc); }
-		},
-
-		_wheelTimer: null,
-		_mouseWheeled: function(/*Event*/ evt){
-			// summary:
-			//		Mouse wheel listener where supported
-
-			dojo.stopEvent(evt);
-			// FIXME: Safari bubbles
-
-			// be nice to DOH and scroll as much as the event says to
-			var scrollAmount = evt.detail ? (evt.detail * -1) : (evt.wheelDelta / 120);
-			if(scrollAmount !== 0){
-				var node = this[(scrollAmount > 0 ? "upArrowNode" : "downArrowNode" )];
-
-				this._arrowPressed(node, scrollAmount, this.smallDelta);
-
-				if(!this._wheelTimer){
-					clearTimeout(this._wheelTimer);
-				}
-				this._wheelTimer = setTimeout(dojo.hitch(this,"_arrowReleased",node), 50);
-			}
-
-		},
-
-		postCreate: function(){
-			this.inherited(arguments);
-
-			// extra listeners
-			this.connect(this.domNode, !dojo.isMozilla ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");
-			this._connects.push(dijit.typematic.addListener(this.upArrowNode, this.textbox, {charOrCode:dojo.keys.UP_ARROW,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout));
-			this._connects.push(dijit.typematic.addListener(this.downArrowNode, this.textbox, {charOrCode:dojo.keys.DOWN_ARROW,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout));
-			this._connects.push(dijit.typematic.addListener(this.upArrowNode, this.textbox, {charOrCode:dojo.keys.PAGE_UP,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout));
-			this._connects.push(dijit.typematic.addListener(this.downArrowNode, this.textbox, {charOrCode:dojo.keys.PAGE_DOWN,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout));
-			if(dojo.isIE){
-				var _this = this;
-				(function resize(){
-					var sz = _this.upArrowNode.parentNode.offsetHeight;
-					if(sz){
-						_this.upArrowNode.style.height = sz >> 1;
-						_this.downArrowNode.style.height = sz - (sz >> 1);
-						_this.focusNode.parentNode.style.height = sz;
-					}
-				})();
-				this.connect(this.domNode, "onresize",
-					function(){ setTimeout(
-						function(){
-							resize();
-							// cause IE to rerender when spinner is moved from hidden to visible
-							_this._setStateClass();
-						}, 0);
-					}
-				);
-				this._layoutHackIE7();
-			}
-		}
-});
-
-}
-
-if(!dojo._hasResource["dijit.form.NumberSpinner"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.NumberSpinner"] = true;
-dojo.provide("dijit.form.NumberSpinner");
-
-
-
-
-dojo.declare("dijit.form.NumberSpinner",
-	[dijit.form._Spinner, dijit.form.NumberTextBoxMixin],
-	{
-	// summary:
-	//		Extends NumberTextBox to add up/down arrows and pageup/pagedown for incremental change to the value
-	//
-	// description:
-	//		A `dijit.form.NumberTextBox` extension to provide keyboard accessible value selection
-	//		as well as icons for spinning direction. When using the keyboard, the typematic rules
-	//		apply, meaning holding the key will gradually increarease or decrease the value and
-	// 		accelerate.
-	//
-	// example:
-	//	| new dijit.form.NumberSpinner({ constraints:{ max:300, min:100 }}, "someInput");
-
-	adjust: function(/* Object */val, /* Number*/delta){
-		// summary:
-		//		Change Number val by the given amount
-		// tags:
-		//		protected
-
-		var tc = this.constraints,
-			v = isNaN(val),
-			gotMax = !isNaN(tc.max),
-			gotMin = !isNaN(tc.min)
-		;
-		if(v && delta != 0){ // blank or invalid value and they want to spin, so create defaults
-			val = (delta > 0) ?
-				gotMin ? tc.min : gotMax ? tc.max : 0 :
-				gotMax ? this.constraints.max : gotMin ? tc.min : 0
-			;
-		}
-		var newval = val + delta;
-		if(v || isNaN(newval)){ return val; }
-		if(gotMax && (newval > tc.max)){
-			newval = tc.max;
-		}
-		if(gotMin && (newval < tc.min)){
-			newval = tc.min;
-		}
-		return newval;
-	},
-
-	_onKeyPress: function(e){
-		if((e.charOrCode == dojo.keys.HOME || e.charOrCode == dojo.keys.END) && !(e.ctrlKey || e.altKey || e.metaKey)
-		&& typeof this.attr('value') != 'undefined' /* gibberish, so HOME and END are default editing keys*/){
-			var value = this.constraints[(e.charOrCode == dojo.keys.HOME ? "min" : "max")];
-			if(value){
-				this._setValueAttr(value,true);
-			}
-			// eat home or end key whether we change the value or not
-			dojo.stopEvent(e);
-		}
-	}
-
-});
-
-}
-
-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, comp, s){
-		//Passing in comp and s (comparator and store), makes this
-		//function much faster.
-		return function(itemA, itemB){
-			var a = s.getValue(itemA, attr);
-			var b = s.getValue(itemB, attr);
-			return dir * comp(a,b); //int
-		};
-	}
-	var sortAttribute;
-	var map = store.comparatorMap;
-	var bc = dojo.data.util.sorter.basicComparator;
-	for(var i = 0; i < sortSpec.length; i++){
-		sortAttribute = sortSpec[i];
-		var attr = sortAttribute.attribute;
-		if(attr){
-			var dir = (sortAttribute.descending) ? -1 : 1;
-			var comp = bc;
-			if(map){
-				if(typeof attr !== "string" && ("toString" in attr)){
-					 attr = attr.toString();
-				}
-				comp = map[attr] || bc;
-			}
-			sortFunctions.push(createSortFunction(attr, 
-				dir, comp, store));
-		}
-	}
-	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.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["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 `dijit.form.ComboBox`/`dijit.form.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 ComboBox, 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} }
-		//		To override the default queryOptions so that deep=false, do:
-		//	|	{ queryOptions: {ignoreCase: true, deep: false} }
-		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: [const] Boolean
-		//		Set this textbox to have a down arrow button, to display the drop down list.
-		//		Defaults to true.
-		hasDownArrow: true,
-
-		templateString: dojo.cache("dijit.form", "templates/ComboBox.html", "<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=\"pr [...]
-
-		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);
-		},
-
-		_abortQuery: function(){
-			// stop in-progress query
-			if(this.searchTimer){
-				clearTimeout(this.searchTimer);
-				this.searchTimer = null;
-			}
-			if(this._fetchHandle){
-				if(this._fetchHandle.abort){ this._fetchHandle.abort(); }
-				this._fetchHandle = null;
-			}
-		},
-
-		_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 || evt.metaKey) && (key != 'x' && key != 'v')) || key == dojo.keys.SHIFT){
-				return; // throw out weird key combinations and spurious events
-			}
-			var doSearch = false;
-			var searchFunction = "_startSearchFromInput";
-			var pw = this._popupWidget;
-			var dk = dojo.keys;
-			var highlighted = null;
-			this._prev_key_backspace = false;
-			this._abortQuery();
-			if(this._isShowingNow){
-				pw.handleKey(key);
-				highlighted = pw.getHighlightedOption();
-			}
-			switch(key){
-				case dk.PAGE_DOWN:
-				case dk.DOWN_ARROW:
-				case dk.PAGE_UP:
-				case dk.UP_ARROW:
-					if(!this._isShowingNow){
-						this._arrowPressed();
-						doSearch = true;
-						searchFunction = "_startSearchAll";
-					}else{
-						this._announceOption(highlighted);
-					}
-					dojo.stopEvent(evt);
-					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._setBlurValue(); // set value if needed
-						this._setCaretPos(this.focusNode, this.focusNode.value.length); // move cursor to end and cancel highlighting
-					}
-					// default case:
-					// prevent submit, but allow event to bubble
-					evt.preventDefault();
-					// fall through
-
-				case dk.TAB:
-					var newvalue = this.attr('displayedValue');
-					//	if the user had More Choices selected fall into the
-					//	_onBlur handler
-					if(pw && (
-						newvalue == pw._messages["previousMessage"] ||
-						newvalue == pw._messages["nextMessage"])
-					){
-						break;
-					}
-					if(highlighted){
-						this._selectOption();
-					}
-					if(this._isShowingNow){
-						this._lastQuery = null; // in case results come back later
-						this._hideResultList();
-					}
-					break;
-
-				case ' ':
-					if(highlighted){
-						dojo.stopEvent(evt);
-						this._selectOption();
-						this._hideResultList();
-					}else{
-						doSearch = true;
-					}
-					break;
-
-				case dk.ESCAPE:
-					if(this._isShowingNow){
-						dojo.stopEvent(evt);
-						this._hideResultList();
-					}
-					break;
-
-				case dk.DELETE:
-				case dk.BACKSPACE:
-					this._prev_key_backspace = true;
-					doSearch = true;
-					break;
-
-				default:
-					// Non char keys (F1-F12 etc..)  shouldn't open list.
-					// Ascii characters and IME input (Chinese, Japanese etc.) should.
-					// On IE and safari, IME input produces keycode == 229, and we simulate
-					// it on firefox by attaching to compositionend event (see compositionend method)
-					doSearch = typeof key == 'string' || key == 229;
-			}
-			if(doSearch){
-				// need to wait a tad before start search so that the event
-				// bubbles through DOM and we have value visible
-				this.item = undefined; // undefined means item needs to be set
-				this.searchTimer = setTimeout(dojo.hitch(this, searchFunction),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){
-			this._fetchHandle = null;
-			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.
-
-			dataObject._maxOptions = this._maxOptions;
-			var nodes = 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());
-			}else if(this.autoComplete && !this._prev_key_backspace /*&& !dataObject.direction*/
-				// 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.
-				&& !/^[*]+$/.test(dataObject.query[this.searchAttr])){
-					this._announceOption(nodes[1]); // 1st real item
-			}
-		},
-
-		_showResultList: function(){
-			this._hideResultList();
-			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)
-			});
-			
-			// If we increased the width of drop down to match the width of ComboBox.domNode,
-			// then need to reposition the drop down (wrapper) so (all of) the drop down still
-			// appears underneath the ComboBox.domNode
-			if(newwidth < this.domNode.offsetWidth){
-				this._popupWidget.domNode.parentNode.style.left = dojo.position(this.domNode).x + "px";
-			}
-
-			dijit.setWaiState(this.comboNode, "expanded", "true");
-		},
-
-		_hideResultList: function(){
-			this._abortQuery();
-			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 if(typeof this.item == "undefined"){
-				// Update 'value' (ex: KY) according to currently displayed text
-				this.item = null;
-				this.attr('displayedValue', newvalue);
-			}else{
-				if(this.value != this._lastValueReported){
-					dijit.form._FormValueWidget.prototype._setValueAttr.call(this, this.value, true);
-				}
-				this._refreshState();
-			}
-		},
-
-		_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);
-		},
-
-		_setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
-			// 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('item', value)
-			// tags:
-			//              private
-			if(!displayedValue){ displayedValue = this.labelFunc(item, this.store); }
-			this.value = this._getValueField() != this.searchAttr? this.store.getIdentity(item) : displayedValue;
-			this.item = item;
-			dijit.form.ComboBox.superclass._setValueAttr.call(this, this.value, priorityChange, displayedValue);
-		},
-
-		_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){
-				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;
-				this.item = undefined;
-				this.value = '';
-			}else{
-				newValue = this.labelFunc(node.item, this.store);
-				this.attr('item', node.item, false, newValue);
-			}
-			// get the text that the user manually entered (cut off autocompleted text)
-			this.focusNode.value = this.focusNode.value.substring(0, this._lastInput.length);
-			// 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){
-			// summary:
-			//		Menu callback function, called when an item in the menu is selected.
-			if(evt){
-				this._announceOption(evt.target);
-			}
-			this._hideResultList();
-			this._setCaretPos(this.focusNode, this.focusNode.value.length);
-			dijit.form._FormValueWidget.prototype._setValueAttr.call(this, this.value, true); // set this.value and fire onChange
-		},
-
-		_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._startSearchAll();
-			}
-		},
-
-		_startSearchAll: function(){
-			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
-			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){
-				this.searchTimer = null;
-				var fetch = {
-					queryOptions: {
-						ignoreCase: this.ignoreCase,
-						deep: true
-					},
-					query: query,
-					onBegin: dojo.hitch(this, "_setMaxOptions"),
-					onComplete: dojo.hitch(this, "_openResultList"),
-					onError: function(errText){
-						_this._fetchHandle = null;
-						console.error('dijit.form.ComboBox: ' + errText);
-						dojo.hitch(_this, "_hideResultList")();
-					},
-					start: 0,
-					count: this.pageSize
-				};
-				dojo.mixin(fetch, _this.fetchProperties);
-				this._fetchHandle = _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._fetchHandle = this.store.fetch(dataObject);
-				};
-				this._nextSearch = this._popupWidget.onPage = dojo.hitch(this, nextSearch, this._fetchHandle);
-			}, 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/safari)
-			// tags:
-			//		private
-
-			// 229 is the code produced by IE and safari while pressing keys during
-			// IME input mode
-			this._onKeyPress({charOrCode: 229});
-		},
-
-		//////////// 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){
-						var valueField = this._getValueField();
-						this.value = valueField != this.searchAttr? this.store.getValue(item, valueField) : this.labelFunc(item, this.store);
-					}
-				}
-			}
-			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._popupWidget._destroyed){
-				this._hideResultList();
-				this._popupWidget.destroy();
-			}
-			this.inherited(arguments);
-		},
-
-		_getMenuLabelFromItem: function(/*Item*/ item){
-			var label = this.labelAttr? this.store.getValue(item, this.labelAttr) : this.labelFunc(item, this.store);
-			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, "&").replace(/</gm, "<")
-				.replace(/>/gm, ">").replace(/"/gm, """);
-			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);
-		},
-
-		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
-
-			// Use toString() because XMLStore returns an XMLItem whereas this
-			// method is expected to return a String (#9354)
-			return store.getValue(item, this.searchAttr).toString(); // String
-		}
-	}
-);
-
-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 = " ";
-			}
-			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");
-			return this.domNode.childNodes;
-		},
-
-		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]);
-			}
-		},
-
-		_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, /*String?*/ displayedValue){
-			// summary:
-			//		Hook so attr('value', value) works.
-			// description:
-			//		Sets the value of the select.
-			this.item = null; // value not looked up in store
-			if(!value){ value = ''; } // null translates to blank
-			dijit.form.ValidationTextBox.prototype._setValueAttr.call(this, value, priorityChange, displayedValue);
-		}
-	}
-);
-
-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 (default) 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
-				//#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.attr('item', 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.
-			// Use this.valueNode.value which isn't always set for other MappedTextBox widgets until blur
-			return this.valueNode.value;
-		},
-
-		_getValueField: function(){
-			// Overrides ComboBox._getValueField()
-			return "value";
-		},
-
-		_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;
-			this.store.fetchItemByIdentity({
-				identity: value,
-				onItem: function(item){
-					self._callbackSetLabel([item], undefined, priorityChange);
-				}
-			});
-		},
-
-		_setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
-			// 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('item', value)
-			// tags:
-			//		private
-			this._isvalid = true;
-			this.inherited(arguments);
-			this.valueNode.value = this.value;
-			this._lastDisplayedValue = this.textbox.value;
-		},
-
-		_getDisplayQueryString: function(/*String*/ text){
-			return text.replace(/([\\\*\?])/g, "\\$1");
-		},
-
-		_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){
-				this._hideResultList();
-				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] = this._getDisplayQueryString(label);
-				// 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){
-						_this._fetchHandle = null;
-						dojo.hitch(_this, "_callbackSetLabel")(result, dataObject, priorityChange);
-					},
-					onError: function(errText){
-						_this._fetchHandle = null;
-						console.error('dijit.form.FilteringSelect: ' + errText);
-						dojo.hitch(_this, "_callbackSetLabel")([], undefined, false);
-					}
-				};
-				dojo.mixin(fetch, this.fetchProperties);
-				this._fetchHandle = 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._FormValueWidget, {
-	// 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;
-		});
-	},
-
-	multiple: 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["dijit.form.HorizontalSlider"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.HorizontalSlider"] = true;
-dojo.provide("dijit.form.HorizontalSlider");
-
-
-
-
-
-
-
-
-dojo.declare(
-	"dijit.form.HorizontalSlider",
-	[dijit.form._FormValueWidget, dijit._Container],
-{
-	// summary:
-	//		A form widget that allows one to select a value with a horizontally draggable handle
-
-	templateString: dojo.cache("dijit.form", "templates/HorizontalSlider.html", "<table class=\"dijit dijitReset dijitSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\" dojoAttachEvent=\"onkeypress:_onKeyPress,onkeyup:_onKeyUp\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td dojoAttachPoint=\"topDecoration\" class=\"dijitReset\" style=\"text-align:center;width:100%;\"></td\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t>< [...]
-
-	// Overrides FormValueWidget.value to indicate numeric value
-	value: 0,
-
-	// showButtons: Boolean
-	//		Show increment/decrement buttons at the ends of the slider?
-	showButtons: true,
-
-	// minimum:: Integer
-	//		The minimum value the slider can be set to.
-	minimum: 0,
-
-	// maximum: Integer
-	//		The maximum value the slider can be set to.
-	maximum: 100,
-
-	// discreteValues: Integer
-	//		If specified, indicates that the slider handle has only 'discreteValues' possible positions,
-	//      and that after dragging the handle, it will snap to the nearest possible position.
-	//      Thus, the slider has only 'discreteValues' possible values.
-	//
-	//		For example, if minimum=10, maxiumum=30, and discreteValues=3, then the slider handle has
-	//		three possible positions, representing values 10, 20, or 30.
-	//
-	//		If discreteValues is not specified or if it's value is higher than the number of pixels
-	//		in the slider bar, then the slider handle can be moved freely, and the slider's value will be
-	//		computed/reported based on pixel position (in this case it will likely be fractional,
-	//      such as 123.456789).
-	discreteValues: Infinity,
-
-	// pageIncrement: Integer
-	//		If discreteValues is also specified, this indicates the amount of clicks (ie, snap positions)
-	//      that the slider handle is moved via pageup/pagedown keys.
-	//	If discreteValues is not specified, it indicates the number of pixels.
-	pageIncrement: 2,
-
-	// clickSelect: Boolean
-	//		If clicking the slider bar changes the value or not
-	clickSelect: true,
-
-	// slideDuration: Number
-	//		The time in ms to take to animate the slider handle from 0% to 100%,
-	//		when clicking the slider bar to make the handle move.
-	slideDuration: dijit.defaultDuration,
-
-	// Flag to _Templated
-	widgetsInTemplate: true,
-
-	attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
-		id: ""
-	}),
-
-	baseClass: "dijitSlider",
-
-	_mousePixelCoord: "pageX",
-	_pixelCount: "w",
-	_startingPixelCoord: "x",
-	_startingPixelCount: "l",
-	_handleOffsetCoord: "left",
-	_progressPixelSize: "width",
-
-	_onKeyUp: function(/*Event*/ e){
-		if(this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey){ return; }
-		this._setValueAttr(this.value, true);
-	},
-
-	_onKeyPress: function(/*Event*/ e){
-		if(this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey){ return; }
-		switch(e.charOrCode){
-			case dojo.keys.HOME:
-				this._setValueAttr(this.minimum, false);
-				break;
-			case dojo.keys.END:
-				this._setValueAttr(this.maximum, false);
-				break;
-			// this._descending === false: if ascending vertical (min on top)
-			// (this._descending || this.isLeftToRight()): if left-to-right horizontal or descending vertical
-			case ((this._descending || this.isLeftToRight()) ? dojo.keys.RIGHT_ARROW : dojo.keys.LEFT_ARROW):
-			case (this._descending === false ? dojo.keys.DOWN_ARROW : dojo.keys.UP_ARROW):
-			case (this._descending === false ? dojo.keys.PAGE_DOWN : dojo.keys.PAGE_UP):
-				this.increment(e);
-				break;
-			case ((this._descending || this.isLeftToRight()) ? dojo.keys.LEFT_ARROW : dojo.keys.RIGHT_ARROW):
-			case (this._descending === false ? dojo.keys.UP_ARROW : dojo.keys.DOWN_ARROW):
-			case (this._descending === false ? dojo.keys.PAGE_UP : dojo.keys.PAGE_DOWN):
-				this.decrement(e);
-				break;
-			default:
-				return;
-		}
-		dojo.stopEvent(e);
-	},
-
-	_onHandleClick: function(e){
-		if(this.disabled || this.readOnly){ return; }
-		if(!dojo.isIE){
-			// make sure you get focus when dragging the handle
-			// (but don't do on IE because it causes a flicker on mouse up (due to blur then focus)
-			dijit.focus(this.sliderHandle);
-		}
-		dojo.stopEvent(e);
-	},
-
-	_isReversed: function(){
-		// summary:
-		//		Returns true if direction is from right to left
-		// tags:
-		//		protected extension
-		return !this.isLeftToRight();
-	},
-
-	_onBarClick: function(e){
-		if(this.disabled || this.readOnly || !this.clickSelect){ return; }
-		dijit.focus(this.sliderHandle);
-		dojo.stopEvent(e);
-		var abspos = dojo.position(this.sliderBarContainer, true);
-		var pixelValue = e[this._mousePixelCoord] - abspos[this._startingPixelCoord];
-		this._setPixelValue(this._isReversed() ? (abspos[this._pixelCount] - pixelValue) : pixelValue, abspos[this._pixelCount], true);
-		this._movable.onMouseDown(e);
-	},
-
-	_setPixelValue: function(/*Number*/ pixelValue, /*Number*/ maxPixels, /*Boolean, optional*/ priorityChange){
-		if(this.disabled || this.readOnly){ return; }
-		pixelValue = pixelValue < 0 ? 0 : maxPixels < pixelValue ? maxPixels : pixelValue;
-		var count = this.discreteValues;
-		if(count <= 1 || count == Infinity){ count = maxPixels; }
-		count--;
-		var pixelsPerValue = maxPixels / count;
-		var wholeIncrements = Math.round(pixelValue / pixelsPerValue);
-		this._setValueAttr((this.maximum-this.minimum)*wholeIncrements/count + this.minimum, priorityChange);
-	},
-
-	_setValueAttr: function(/*Number*/ value, /*Boolean, optional*/ priorityChange){
-		// summary:
-		//		Hook so attr('value', value) works.
-		this.valueNode.value = this.value = value;
-		dijit.setWaiState(this.focusNode, "valuenow", value);
-		this.inherited(arguments);
-		var percent = (value - this.minimum) / (this.maximum - this.minimum);
-		var progressBar = (this._descending === false) ? this.remainingBar : this.progressBar;
-		var remainingBar = (this._descending === false) ? this.progressBar : this.remainingBar;
-		if(this._inProgressAnim && this._inProgressAnim.status != "stopped"){
-			this._inProgressAnim.stop(true);
-		}
-		if(priorityChange && this.slideDuration > 0 && progressBar.style[this._progressPixelSize]){
-			// animate the slider
-			var _this = this;
-			var props = {};
-			var start = parseFloat(progressBar.style[this._progressPixelSize]);
-			var duration = this.slideDuration * (percent-start/100);
-			if(duration == 0){ return; }
-			if(duration < 0){ duration = 0 - duration; }
-			props[this._progressPixelSize] = { start: start, end: percent*100, units:"%" };
-			this._inProgressAnim = dojo.animateProperty({ node: progressBar, duration: duration,
-				onAnimate: function(v){ remainingBar.style[_this._progressPixelSize] = (100-parseFloat(v[_this._progressPixelSize])) + "%"; },
-				onEnd: function(){ delete _this._inProgressAnim; },
-				properties: props
-			})
-			this._inProgressAnim.play();
-		}
-		else{
-			progressBar.style[this._progressPixelSize] = (percent*100) + "%";
-			remainingBar.style[this._progressPixelSize] = ((1-percent)*100) + "%";
-		}
-	},
-
-	_bumpValue: function(signedChange, /*Boolean, optional*/ priorityChange){
-		if(this.disabled || this.readOnly){ return; }
-		var s = dojo.getComputedStyle(this.sliderBarContainer);
-		var c = dojo._getContentBox(this.sliderBarContainer, s);
-		var count = this.discreteValues;
-		if(count <= 1 || count == Infinity){ count = c[this._pixelCount]; }
-		count--;
-		var value = (this.value - this.minimum) * count / (this.maximum - this.minimum) + signedChange;
-		if(value < 0){ value = 0; }
-		if(value > count){ value = count; }
-		value = value * (this.maximum - this.minimum) / count + this.minimum;
-		this._setValueAttr(value, priorityChange);
-	},
-
-	_onClkBumper: function(val){
-		if(this.disabled || this.readOnly || !this.clickSelect){ return; }
-		this._setValueAttr(val, true);
-	},
-
-	_onClkIncBumper: function(){
-		this._onClkBumper(this._descending === false ? this.minimum : this.maximum);
-	},
-
-	_onClkDecBumper: function(){
-		this._onClkBumper(this._descending === false ? this.maximum : this.minimum);
-	},
-
-	decrement: function(/*Event*/ e){
-		// summary:
-		//		Decrement slider
-		// tags:
-		//		private
-		this._bumpValue(e.charOrCode == dojo.keys.PAGE_DOWN ? -this.pageIncrement : -1);
-	},
-
-	increment: function(/*Event*/ e){
-		// summary:
-		//		Increment slider
-		// tags:
-		//		private
-		this._bumpValue(e.charOrCode == dojo.keys.PAGE_UP ? this.pageIncrement : 1);
-	},
-
-	_mouseWheeled: function(/*Event*/ evt){
-		// summary:
-		//		Event handler for mousewheel where supported
-		dojo.stopEvent(evt);
-		var janky = !dojo.isMozilla;
-		var scroll = evt[(janky ? "wheelDelta" : "detail")] * (janky ? 1 : -1);
-		this._bumpValue(scroll < 0 ? -1 : 1, true); // negative scroll acts like a decrement
-	},
-
-	startup: function(){
-		dojo.forEach(this.getChildren(), function(child){
-			if(this[child.container] != this.containerNode){
-				this[child.container].appendChild(child.domNode);
-			}
-		}, this);
-	},
-
-	_typematicCallback: function(/*Number*/ count, /*Object*/ button, /*Event*/ e){
-		if(count == -1){
-			this._setValueAttr(this.value, true);
-		}else{
-			this[(button == (this._descending? this.incrementButton : this.decrementButton)) ? "decrement" : "increment"](e);
-		}
-	},
-
-	postCreate: function(){
-		if(this.showButtons){
-			this.incrementButton.style.display="";
-			this.decrementButton.style.display="";
-			this._connects.push(dijit.typematic.addMouseListener(
-				this.decrementButton, this, "_typematicCallback", 25, 500));
-			this._connects.push(dijit.typematic.addMouseListener(
-				this.incrementButton, this, "_typematicCallback", 25, 500));
-		}
-		this.connect(this.domNode, !dojo.isMozilla ? "onmousewheel" : "DOMMouseScroll", "_mouseWheeled");
-
-		// define a custom constructor for a SliderMover that points back to me
-		var mover = dojo.declare(dijit.form._SliderMover, {
-			widget: this
-		});
-
-		this._movable = new dojo.dnd.Moveable(this.sliderHandle, {mover: mover});
-		// find any associated label element and add to slider focusnode.
-		var label=dojo.query('label[for="'+this.id+'"]');
-		if(label.length){
-			label[0].id = (this.id+"_label");
-			dijit.setWaiState(this.focusNode, "labelledby", label[0].id);
-		}
-		dijit.setWaiState(this.focusNode, "valuemin", this.minimum);
-		dijit.setWaiState(this.focusNode, "valuemax", this.maximum);
-
-		this.inherited(arguments);
-		this._layoutHackIE7();
-	},
-
-	destroy: function(){
-		this._movable.destroy();
-		if(this._inProgressAnim && this._inProgressAnim.status != "stopped"){
-			this._inProgressAnim.stop(true);
-		}
-		this._supportingWidgets = dijit.findWidgets(this.domNode); // tells destroy about pseudo-child widgets (ruler/labels)
-		this.inherited(arguments);
-	}
-});
-
-dojo.declare("dijit.form._SliderMover",
-	dojo.dnd.Mover,
-{
-	onMouseMove: function(e){
-		var widget = this.widget;
-		var abspos = widget._abspos;
-		if(!abspos){
-			abspos = widget._abspos = dojo.position(widget.sliderBarContainer, true);
-			widget._setPixelValue_ = dojo.hitch(widget, "_setPixelValue");
-			widget._isReversed_ = widget._isReversed();
-		}
-		var pixelValue = e[widget._mousePixelCoord] - abspos[widget._startingPixelCoord];
-		widget._setPixelValue_(widget._isReversed_ ? (abspos[widget._pixelCount]-pixelValue) : pixelValue, abspos[widget._pixelCount], false);
-	},
-
-	destroy: function(e){
-		dojo.dnd.Mover.prototype.destroy.apply(this, arguments);
-		var widget = this.widget;
-		widget._abspos = null;
-		widget._setValueAttr(widget.value, true);
-	}
-});
-
-
-
-}
-
-if(!dojo._hasResource["dijit.form.VerticalSlider"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.VerticalSlider"] = true;
-dojo.provide("dijit.form.VerticalSlider");
-
-
-
-dojo.declare(
-	"dijit.form.VerticalSlider",
-	dijit.form.HorizontalSlider,
-{
-	// summary:
-	//		A form widget that allows one to select a value with a vertically draggable handle
-
-	templateString: dojo.cache("dijit.form", "templates/VerticalSlider.html", "<table class=\"dijitReset dijitSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\" dojoAttachEvent=\"onkeypress:_onKeyPress,onkeyup:_onKeyUp\"\n><tbody class=\"dijitReset\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV\"\n\t\t\t><div class=\"dijitSliderIncrementIconV\" tabIndex=\"-1\" style= [...]
-	_mousePixelCoord: "pageY",
-	_pixelCount: "h",
-	_startingPixelCoord: "y",
-	_startingPixelCount: "t",
-	_handleOffsetCoord: "top",
-	_progressPixelSize: "height",
-
-	// _descending: Boolean
-	//	   Specifies if the slider values go from high-on-top (true), or low-on-top (false)
-	//	TODO: expose this in 1.2 - the css progress/remaining bar classes need to be reversed
-	_descending: true,
-
-	startup: function(){
-		if(this._started){ return; }
-
-		if(!this.isLeftToRight() && dojo.isMoz){
-			if(this.leftDecoration){this._rtlRectify(this.leftDecoration);}
-			if(this.rightDecoration){this._rtlRectify(this.rightDecoration);}
-		}
-
-		this.inherited(arguments);
-	},
-
-	_isReversed: function(){
-		// summary:
-		//		Overrides HorizontalSlider._isReversed.
-		//		Indicates if values are high on top (with low numbers on the bottom).
-		return this._descending;
-	},
-
-	_rtlRectify: function(decorationNode/*NodeList*/){
-		// summary:
-		//	    Helper function on gecko.
-		//		Rectify children nodes for left/right decoration in rtl case.
-		//		Simply switch the rule and label child for each decoration node.
-		// tags:
-		//		private
-		var childNodes = [];
-		while(decorationNode.firstChild){
-				childNodes.push(decorationNode.firstChild);
-				decorationNode.removeChild(decorationNode.firstChild);
-		}
-		for(var i = childNodes.length-1; i >=0; i--){
-			if(childNodes[i]){
-				decorationNode.appendChild(childNodes[i]);
-			}
-		}
-	}
-});
-
-
-}
-
-if(!dojo._hasResource["dijit.form.HorizontalRule"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.HorizontalRule"] = true;
-dojo.provide("dijit.form.HorizontalRule");
-
-
-
-
-dojo.declare("dijit.form.HorizontalRule", [dijit._Widget, dijit._Templated],
-{
-	// summary:
-	//		Hash marks for `dijit.form.HorizontalSlider`
-
-	templateString: '<div class="dijitRuleContainer dijitRuleContainerH"></div>',
-
-	// count: Integer
-	//		Number of hash marks to generate
-	count: 3,
-
-	// container: String
-	//		For HorizontalSlider, this is either "topDecoration" or "bottomDecoration",
-	//		and indicates whether this rule goes above or below the slider.
-	container: "containerNode",
-
-	// ruleStyle: String
-	//		CSS style to apply to individual hash marks
-	ruleStyle: "",
-
-	_positionPrefix: '<div class="dijitRuleMark dijitRuleMarkH" style="left:',
-	_positionSuffix: '%;',
-	_suffix: '"></div>',
-
-	_genHTML: function(pos, ndx){
-		return this._positionPrefix + pos + this._positionSuffix + this.ruleStyle + this._suffix;
-	},
-
-	// _isHorizontal: [protected extension] Boolean
-	//		VerticalRule will override this...
-	_isHorizontal: true,
-
-	postCreate: function(){
-		var innerHTML;
-		if(this.count == 1){
-			innerHTML = this._genHTML(50, 0);
-		}else{
-			var i;
-			var interval = 100 / (this.count-1);
-			if(!this._isHorizontal || this.isLeftToRight()){
-				innerHTML = this._genHTML(0, 0);
-				for(i=1; i < this.count-1; i++){
-					innerHTML += this._genHTML(interval*i, i);
-				}
-				innerHTML += this._genHTML(100, this.count-1);
-			}else{
-				innerHTML = this._genHTML(100, 0);
-				for(i=1; i < this.count-1; i++){
-					innerHTML += this._genHTML(100-interval*i, i);
-				}
-				innerHTML += this._genHTML(0, this.count-1);
-			}
-		}
-		this.domNode.innerHTML = innerHTML;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.form.VerticalRule"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.VerticalRule"] = true;
-dojo.provide("dijit.form.VerticalRule");
-
-
-
-dojo.declare("dijit.form.VerticalRule", dijit.form.HorizontalRule,
-{
-	// summary:
-	//		Hash marks for the `dijit.form.VerticalSlider`
-
-	templateString: '<div class="dijitRuleContainer dijitRuleContainerV"></div>',
-	_positionPrefix: '<div class="dijitRuleMark dijitRuleMarkV" style="top:',
-
-/*=====
-	// container: String
-	//		This is either "leftDecoration" or "rightDecoration",
-	//		to indicate whether this rule goes to the left or to the right of the slider.
-	//		Note that on RTL system, "leftDecoration" would actually go to the right, and vice-versa.
-	container: "",
-=====*/
-
-	// Overrides HorizontalRule._isHorizontal
-	_isHorizontal: false
-
-});
-
-
-}
-
-if(!dojo._hasResource["dijit.form.HorizontalRuleLabels"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.HorizontalRuleLabels"] = true;
-dojo.provide("dijit.form.HorizontalRuleLabels");
-
-
-
-dojo.declare("dijit.form.HorizontalRuleLabels", dijit.form.HorizontalRule,
-{
-	// summary:
-	//		Labels for `dijit.form.HorizontalSlider`
-
-	templateString: '<div class="dijitRuleContainer dijitRuleContainerH dijitRuleLabelsContainer dijitRuleLabelsContainerH"></div>',
-
-	// labelStyle: String
-	//		CSS style to apply to individual text labels
-	labelStyle: "",
-
-	// labels: String[]?
-	//		Array of text labels to render - evenly spaced from left-to-right or bottom-to-top.
-	//		Alternately, minimum and maximum can be specified, to get numeric labels.
-	labels: [],
-
-	// numericMargin: Integer
-	//		Number of generated numeric labels that should be rendered as '' on the ends when labels[] are not specified
-	numericMargin: 0,
-
-	// numericMinimum: Integer
-	//		Leftmost label value for generated numeric labels when labels[] are not specified
-	minimum: 0,
-
-	// numericMaximum: Integer
-	//		Rightmost label value for generated numeric labels when labels[] are not specified
-	maximum: 1,
-
-	// constraints: Object
-	//		pattern, places, lang, et al (see dojo.number) for generated numeric labels when labels[] are not specified
-	constraints: {pattern:"#%"},
-
-	_positionPrefix: '<div class="dijitRuleLabelContainer dijitRuleLabelContainerH" style="left:',
-	_labelPrefix: '"><span class="dijitRuleLabel dijitRuleLabelH">',
-	_suffix: '</span></div>',
-
-	_calcPosition: function(pos){
-		// summary:
-		//		Returns the value to be used in HTML for the label as part of the left: attribute
-		// tags:
-		//		protected extension
-		return pos;
-	},
-
-	_genHTML: function(pos, ndx){
-		return this._positionPrefix + this._calcPosition(pos) + this._positionSuffix + this.labelStyle + this._labelPrefix + this.labels[ndx] + this._suffix;
-	},
-
-	getLabels: function(){
-		// summary:
-		//		Overridable function to return array of labels to use for this slider.
-		//		Can specify a getLabels() method instead of a labels[] array, or min/max attributes.
-		// tags:
-		//		protected extension
-
-		// if the labels array was not specified directly, then see if <li> children were
-		var labels = this.labels;
-		if(!labels.length){
-			// for markup creation, labels are specified as child elements
-			labels = dojo.query("> li", this.srcNodeRef).map(function(node){
-				return String(node.innerHTML);
-			});
-		}
-		this.srcNodeRef.innerHTML = '';
-		// if the labels were not specified directly and not as <li> children, then calculate numeric labels
-		if(!labels.length && this.count > 1){
-			var start = this.minimum;
-			var inc = (this.maximum - start) / (this.count-1);
-			for(var i=0; i < this.count; i++){
-				labels.push((i < this.numericMargin || i >= (this.count-this.numericMargin)) ? '' : dojo.number.format(start, this.constraints));
-				start += inc;
-			}
-		}
-		return labels;
-	},
-
-	postMixInProperties: function(){
-		this.inherited(arguments);
-		this.labels = this.getLabels();
-		this.count = this.labels.length;
-	}
-});
-
-
-
-}
-
-if(!dojo._hasResource["dijit.form.VerticalRuleLabels"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.VerticalRuleLabels"] = true;
-dojo.provide("dijit.form.VerticalRuleLabels");
-
-
-
-dojo.declare("dijit.form.VerticalRuleLabels", dijit.form.HorizontalRuleLabels,
-{
-	// summary:
-	//		Labels for the `dijit.form.VerticalSlider`
-
-	templateString: '<div class="dijitRuleContainer dijitRuleContainerV dijitRuleLabelsContainer dijitRuleLabelsContainerV"></div>',
-
-	_positionPrefix: '<div class="dijitRuleLabelContainer dijitRuleLabelContainerV" style="top:',
-	_labelPrefix: '"><span class="dijitRuleLabel dijitRuleLabelV">',
-
-	_calcPosition: function(pos){
-		// Overrides HorizontalRuleLabel._calcPosition()
-		return 100-pos;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.form.SimpleTextarea"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.SimpleTextarea"] = true;
-dojo.provide("dijit.form.SimpleTextarea");
-
-
-
-dojo.declare("dijit.form.SimpleTextarea",
-	dijit.form.TextBox,
-	{
-	// summary:
-	//		A simple textarea that degrades, and responds to
-	// 		minimal LayoutContainer usage, and works with dijit.form.Form.
-	//		Doesn't automatically size according to input, like Textarea.
-	//
-	// example:
-	//	|	<textarea dojoType="dijit.form.SimpleTextarea" name="foo" value="bar" rows=30 cols=40></textarea>
-	//
-	// example:
-	//	|	new dijit.form.SimpleTextarea({ rows:20, cols:30 }, "foo");
-
-	baseClass: "dijitTextArea",
-
-	attributeMap: dojo.delegate(dijit.form._FormValueWidget.prototype.attributeMap, {
-		rows:"textbox", cols: "textbox"
-	}),
-
-	// rows: Number
-	//		The number of rows of text.
-	rows: "3",
-
-	// rows: Number
-	//		The number of characters per line.
-	cols: "20",
-
-	templateString: "<textarea ${nameAttrSetting} dojoAttachPoint='focusNode,containerNode,textbox' autocomplete='off'></textarea>",
-
-	postMixInProperties: function(){
-		// Copy value from srcNodeRef, unless user specified a value explicitly (or there is no srcNodeRef)
-		if(!this.value && this.srcNodeRef){
-			this.value = this.srcNodeRef.value;
-		}
-		this.inherited(arguments);
-	},
-
-	filter: function(/*String*/ value){
-		// Override TextBox.filter to deal with newlines... specifically (IIRC) this is for IE which writes newlines
-		// as \r\n instead of just \n
-		if(value){
-			value = value.replace(/\r/g,"");
-		}
-		return this.inherited(arguments);
-	},
-
-	postCreate: function(){
-		this.inherited(arguments);
-		if(dojo.isIE && this.cols){ // attribute selectors is not supported in IE6
-			dojo.addClass(this.textbox, "dijitTextAreaCols");
-		}
-	},
-
-	_previousValue: "",
-	_onInput: function(/*Event?*/ e){
-		// Override TextBox._onInput() to enforce maxLength restriction
-		if(this.maxLength){
-			var maxLength = parseInt(this.maxLength);
-			var value = this.textbox.value.replace(/\r/g,'');
-			var overflow = value.length - maxLength;
-			if(overflow > 0){
-				if(e){ dojo.stopEvent(e); }
-				var textarea = this.textbox;
-				if(textarea.selectionStart){
-					var pos = textarea.selectionStart;
-					var cr = 0;
-					if(dojo.isOpera){
-						cr = (this.textbox.value.substring(0,pos).match(/\r/g) || []).length;
-					}
-					this.textbox.value = value.substring(0,pos-overflow-cr)+value.substring(pos-cr);
-					textarea.setSelectionRange(pos-overflow, pos-overflow);
-				}else if(dojo.doc.selection){ //IE
-					textarea.focus();
-					var range = dojo.doc.selection.createRange();
-					// delete overflow characters
-					range.moveStart("character", -overflow);
-					range.text = '';
-					// show cursor
-					range.select();
-				}
-			}
-			this._previousValue = this.textbox.value;
-		}
-		this.inherited(arguments);
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.form.Textarea"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.Textarea"] = true;
-dojo.provide("dijit.form.Textarea");
-
-
-
-dojo.declare(
-	"dijit.form.Textarea",
-	dijit.form.SimpleTextarea,
-	{
-	// summary:
-	//		A textarea widget that adjusts it's height according to the amount of data.
-	//
-	// description:
-	//		A textarea that dynamically expands/contracts (changing it's height) as
-	//		the user types, to display all the text without requiring a scroll bar.
-	//
-	//		Takes nearly all the parameters (name, value, etc.) that a vanilla textarea takes.
-	//		Rows is not supported since this widget adjusts the height.
-	//
-	// example:
-	// |	<textarea dojoType="dijit.form.TextArea">...</textarea>
-
-
-	// Override SimpleTextArea.cols to default to width:100%, for backward compatibility
-	cols: "",
-
-	_previousNewlines: 0,
-	_strictMode: (dojo.doc.compatMode != 'BackCompat'), // not the same as !dojo.isQuirks
-
-	_getHeight: function(textarea){
-		var newH = textarea.scrollHeight;
-		if(dojo.isIE){
-			newH += textarea.offsetHeight - textarea.clientHeight - ((dojo.isIE < 8 && this._strictMode) ? dojo._getPadBorderExtents(textarea).h : 0);
-		}else if(dojo.isMoz){
-			newH += textarea.offsetHeight - textarea.clientHeight; // creates room for horizontal scrollbar
-		}else if(dojo.isWebKit && !(dojo.isSafari < 4)){ // Safari 4.0 && Chrome
-			newH += dojo._getBorderExtents(textarea).h;
-		}else{ // Safari 3.x and Opera 9.6
-			newH += dojo._getPadBorderExtents(textarea).h;
-		}
-		return newH;
-	},
-
-	_estimateHeight: function(textarea){
-		// summary:
-		// 		Approximate the height when the textarea is invisible with the number of lines in the text.
-		// 		Fails when someone calls setValue with a long wrapping line, but the layout fixes itself when the user clicks inside so . . .
-		// 		In IE, the resize event is supposed to fire when the textarea becomes visible again and that will correct the size automatically.
-		//
-		textarea.style.maxHeight = "";
-		textarea.style.height = "auto";
-		// #rows = #newlines+1
-		// Note: on Moz, the following #rows appears to be 1 too many.
-		// Actually, Moz is reserving room for the scrollbar.
-		// If you increase the font size, this behavior becomes readily apparent as the last line gets cut off without the +1.
-		textarea.rows = (textarea.value.match(/\n/g) || []).length + 1;
-	},
-
-	_needsHelpShrinking: dojo.isMoz || dojo.isWebKit,
-
-	_onInput: function(){
-		// Override SimpleTextArea._onInput() to deal with height adjustment
-		this.inherited(arguments);
-		if(this._busyResizing){ return; }
-		this._busyResizing = true;
-		var textarea = this.textbox;
-		if(textarea.scrollHeight && textarea.offsetHeight && textarea.clientHeight){
-			var newH = this._getHeight(textarea) + "px";
-			if(textarea.style.height != newH){
-				textarea.style.maxHeight = textarea.style.height = newH;
-			}
-			if(this._needsHelpShrinking){
-				if(this._setTimeoutHandle){
-					clearTimeout(this._setTimeoutHandle);
-				}
-				this._setTimeoutHandle = setTimeout(dojo.hitch(this, "_shrink"), 0); // try to collapse multiple shrinks into 1
-			}
-		}else{
-			// hidden content of unknown size
-			this._estimateHeight(textarea);
-		}
-		this._busyResizing = false;
-	},
-
-	_busyResizing: false,
-	_shrink: function(){
-		// grow paddingBottom to see if scrollHeight shrinks (when it is unneccesarily big)
-		this._setTimeoutHandle = null;
-		if(this._needsHelpShrinking && !this._busyResizing){
-			this._busyResizing = true;
-			var textarea = this.textbox;
-			var empty = false;
-			if(textarea.value == ''){
-				textarea.value = ' '; // prevent collapse all the way back to 0
-				empty = true;
-			}
-			var scrollHeight = textarea.scrollHeight;
-			if(!scrollHeight){
-				this._estimateHeight(textarea);
-			}else{
-				var oldPadding = textarea.style.paddingBottom;
-				var newPadding = dojo._getPadExtents(textarea);
-				newPadding = newPadding.h - newPadding.t;
-				textarea.style.paddingBottom = newPadding + 1 + "px"; // tweak padding to see if height can be reduced
-				var newH = this._getHeight(textarea) - 1 + "px"; // see if the height changed by the 1px added
-				if(textarea.style.maxHeight != newH){ // if can be reduced, so now try a big chunk
-					textarea.style.paddingBottom = newPadding + scrollHeight + "px";
-					textarea.scrollTop = 0;
-					textarea.style.maxHeight = this._getHeight(textarea) - scrollHeight + "px"; // scrollHeight is the added padding
-				}
-				textarea.style.paddingBottom = oldPadding;
-			}
-			if(empty){
-				textarea.value = '';
-			}
-			this._busyResizing = false;
-		}
-	},
-
-	resize: function(){
-		// summary:
-		//		Resizes the textarea vertically (should be called after a style/value change)
-		this._onInput();
-	},
-
-	_setValueAttr: function(){
-		this.inherited(arguments);
-		this.resize();
-	},
-
-	postCreate: function(){
-		this.inherited(arguments);
-		// tweak textarea style to reduce browser differences
-		dojo.style(this.textbox, { overflowY: 'hidden', overflowX: 'auto', boxSizing: 'border-box', MsBoxSizing: 'border-box', WebkitBoxSizing: 'border-box', MozBoxSizing: 'border-box' });
-		this.connect(this.textbox, "onscroll", this._onInput);
-		this.connect(this.textbox, "onresize", this._onInput);
-		this.connect(this.textbox, "onfocus", this._onInput); // useful when a previous estimate was off a bit
-		setTimeout(dojo.hitch(this, "resize"), 0);
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.layout.StackController"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.StackController"] = true;
-dojo.provide("dijit.layout.StackController");
-
-
-
-
-
-
-
-dojo.declare(
-		"dijit.layout.StackController",
-		[dijit._Widget, dijit._Templated, dijit._Container],
-		{
-			// summary:
-			//		Set of buttons to select a page in a page list.
-			// description:
-			//		Monitors the specified StackContainer, and whenever a page is
-			//		added, deleted, or selected, updates itself accordingly.
-
-			templateString: "<span wairole='tablist' dojoAttachEvent='onkeypress' class='dijitStackController'></span>",
-
-			// containerId: [const] String
-			//		The id of the page container that I point to
-			containerId: "",
-
-			// buttonWidget: [const] String
-			//		The name of the button widget to create to correspond to each page
-			buttonWidget: "dijit.layout._StackButton",
-
-			postCreate: function(){
-				dijit.setWaiRole(this.domNode, "tablist");
-
-				this.pane2button = {};		// mapping from pane id to buttons
-				this.pane2handles = {};		// mapping from pane id to this.connect() handles
-
-				// Listen to notifications from StackContainer
-				this.subscribe(this.containerId+"-startup", "onStartup");
-				this.subscribe(this.containerId+"-addChild", "onAddChild");
-				this.subscribe(this.containerId+"-removeChild", "onRemoveChild");
-				this.subscribe(this.containerId+"-selectChild", "onSelectChild");
-				this.subscribe(this.containerId+"-containerKeyPress", "onContainerKeyPress");
-			},
-
-			onStartup: function(/*Object*/ info){
-				// summary:
-				//		Called after StackContainer has finished initializing
-				// tags:
-				//		private
-				dojo.forEach(info.children, this.onAddChild, this);
-				if(info.selected){
-					// Show button corresponding to selected pane (unless selected
-					// is null because there are no panes)
-					this.onSelectChild(info.selected);
-				}
-			},
-
-			destroy: function(){
-				for(var pane in this.pane2button){
-					this.onRemoveChild(dijit.byId(pane));
-				}
-				this.inherited(arguments);
-			},
-
-			onAddChild: function(/*dijit._Widget*/ page, /*Integer?*/ insertIndex){
-				// summary:
-				//		Called whenever a page is added to the container.
-				//		Create button corresponding to the page.
-				// tags:
-				//		private
-
-				// add a node that will be promoted to the button widget
-				var refNode = dojo.doc.createElement("span");
-				this.domNode.appendChild(refNode);
-				// create an instance of the button widget
-				var cls = dojo.getObject(this.buttonWidget);
-				var button = new cls({
-					id: this.id + "_" + page.id,
-					label: page.title,
-					showLabel: page.showTitle,
-					iconClass: page.iconClass,
-					closeButton: page.closable,
-					title: page.tooltip
-				}, refNode);
-				dijit.setWaiState(button.focusNode,"selected", "false");
-				this.pane2handles[page.id] = [
-					this.connect(page, 'attr', function(name, value){
-						if(arguments.length == 2){
-							var buttonAttr = {
-								title: 'label',
-								showTitle: 'showLabel',
-								iconClass: 'iconClass',
-								closable: 'closeButton',
-								tooltip: 'title'
-							}[name];
-							if(buttonAttr){
-								button.attr(buttonAttr, value);
-							}
-						}
-					}),
-					this.connect(button, 'onClick', dojo.hitch(this,"onButtonClick", page)),
-					this.connect(button, 'onClickCloseButton', dojo.hitch(this,"onCloseButtonClick", page))
-				];
-				this.addChild(button, insertIndex);
-				this.pane2button[page.id] = button;
-				page.controlButton = button;	// this value might be overwritten if two tabs point to same container
-				if(!this._currentChild){ // put the first child into the tab order
-					button.focusNode.setAttribute("tabIndex", "0");
-					dijit.setWaiState(button.focusNode, "selected", "true");
-					this._currentChild = page;
-				}
-				// make sure all tabs have the same length
-				if(!this.isLeftToRight() && dojo.isIE && this._rectifyRtlTabList){
-					this._rectifyRtlTabList();
-				}
-			},
-
-			onRemoveChild: function(/*dijit._Widget*/ page){
-				// summary:
-				//		Called whenever a page is removed from the container.
-				//		Remove the button corresponding to the page.
-				// tags:
-				//		private
-
-				if(this._currentChild === page){ this._currentChild = null; }
-				dojo.forEach(this.pane2handles[page.id], this.disconnect, this);
-				delete this.pane2handles[page.id];
-				var button = this.pane2button[page.id];
-				if(button){
-					this.removeChild(button);
-					delete this.pane2button[page.id];
-					button.destroy();
-				}
-				delete page.controlButton;
-			},
-
-			onSelectChild: function(/*dijit._Widget*/ page){
-				// summary:
-				//		Called when a page has been selected in the StackContainer, either by me or by another StackController
-				// tags:
-				//		private
-
-				if(!page){ return; }
-
-				if(this._currentChild){
-					var oldButton=this.pane2button[this._currentChild.id];
-					oldButton.attr('checked', false);
-					dijit.setWaiState(oldButton.focusNode, "selected", "false");
-					oldButton.focusNode.setAttribute("tabIndex", "-1");
-				}
-
-				var newButton=this.pane2button[page.id];
-				newButton.attr('checked', true);
-				dijit.setWaiState(newButton.focusNode, "selected", "true");
-				this._currentChild = page;
-				newButton.focusNode.setAttribute("tabIndex", "0");
-				var container = dijit.byId(this.containerId);
-				dijit.setWaiState(container.containerNode, "labelledby", newButton.id);
-			},
-
-			onButtonClick: function(/*dijit._Widget*/ page){
-				// summary:
-				//		Called whenever one of my child buttons is pressed in an attempt to select a page
-				// tags:
-				//		private
-
-				var container = dijit.byId(this.containerId);
-				container.selectChild(page);
-			},
-
-			onCloseButtonClick: function(/*dijit._Widget*/ page){
-				// summary:
-				//		Called whenever one of my child buttons [X] is pressed in an attempt to close a page
-				// tags:
-				//		private
-
-				var container = dijit.byId(this.containerId);
-				container.closeChild(page);
-				if(this._currentChild){
-					var b = this.pane2button[this._currentChild.id];
-					if(b){
-						dijit.focus(b.focusNode || b.domNode);
-					}
-				}
-			},
-
-			// TODO: this is a bit redundant with forward, back api in StackContainer
-			adjacent: function(/*Boolean*/ forward){
-				// summary:
-				//		Helper for onkeypress to find next/previous button
-				// tags:
-				//		private
-
-				if(!this.isLeftToRight() && (!this.tabPosition || /top|bottom/.test(this.tabPosition))){ forward = !forward; }
-				// find currently focused button in children array
-				var children = this.getChildren();
-				var current = dojo.indexOf(children, this.pane2button[this._currentChild.id]);
-				// pick next button to focus on
-				var offset = forward ? 1 : children.length - 1;
-				return children[ (current + offset) % children.length ]; // dijit._Widget
-			},
-
-			onkeypress: function(/*Event*/ e){
-				// summary:
-				//		Handle keystrokes on the page list, for advancing to next/previous button
-				//		and closing the current page if the page is closable.
-				// tags:
-				//		private
-
-				if(this.disabled || e.altKey ){ return; }
-				var forward = null;
-				if(e.ctrlKey || !e._djpage){
-					var k = dojo.keys;
-					switch(e.charOrCode){
-						case k.LEFT_ARROW:
-						case k.UP_ARROW:
-							if(!e._djpage){ forward = false; }
-							break;
-						case k.PAGE_UP:
-							if(e.ctrlKey){ forward = false; }
-							break;
-						case k.RIGHT_ARROW:
-						case k.DOWN_ARROW:
-							if(!e._djpage){ forward = true; }
-							break;
-						case k.PAGE_DOWN:
-							if(e.ctrlKey){ forward = true; }
-							break;
-						case k.DELETE:
-							if(this._currentChild.closable){
-								this.onCloseButtonClick(this._currentChild);
-							}
-							dojo.stopEvent(e);
-							break;
-						default:
-							if(e.ctrlKey){
-								if(e.charOrCode === k.TAB){
-									this.adjacent(!e.shiftKey).onClick();
-									dojo.stopEvent(e);
-								}else if(e.charOrCode == "w"){
-									if(this._currentChild.closable){
-										this.onCloseButtonClick(this._currentChild);
-									}
-									dojo.stopEvent(e); // avoid browser tab closing.
-								}
-							}
-					}
-					// handle page navigation
-					if(forward !== null){
-						this.adjacent(forward).onClick();
-						dojo.stopEvent(e);
-					}
-				}
-			},
-
-			onContainerKeyPress: function(/*Object*/ info){
-				// summary:
-				//		Called when there was a keypress on the container
-				// tags:
-				//		private
-				info.e._djpage = info.page;
-				this.onkeypress(info.e);
-			}
-	});
-
-
-dojo.declare("dijit.layout._StackButton",
-		dijit.form.ToggleButton,
-		{
-		// summary:
-		//		Internal widget used by StackContainer.
-		// description:
-		//		The button-like or tab-like object you click to select or delete a page
-		// tags:
-		//		private
-
-		// Override _FormWidget.tabIndex.
-		// StackContainer buttons are not in the tab order by default.
-		// Probably we should be calling this.startupKeyNavChildren() instead.
-		tabIndex: "-1",
-
-		postCreate: function(/*Event*/ evt){
-			dijit.setWaiRole((this.focusNode || this.domNode), "tab");
-			this.inherited(arguments);
-		},
-
-		onClick: function(/*Event*/ evt){
-			// summary:
-			//		This is for TabContainer where the tabs are <span> rather than button,
-			//		so need to set focus explicitly (on some browsers)
-			//		Note that you shouldn't override this method, but you can connect to it.
-			dijit.focus(this.focusNode);
-
-			// ... now let StackController catch the event and tell me what to do
-		},
-
-		onClickCloseButton: function(/*Event*/ evt){
-			// summary:
-			//		StackContainer connects to this function; if your widget contains a close button
-			//		then clicking it should call this function.
-			//		Note that you shouldn't override this method, but you can connect to it.
-			evt.stopPropagation();
-		}
-	});
-
-
-}
-
-if(!dojo._hasResource["dijit.layout.StackContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.StackContainer"] = true;
-dojo.provide("dijit.layout.StackContainer");
-
-
-
-
-
-
-dojo.declare(
-	"dijit.layout.StackContainer",
-	dijit.layout._LayoutWidget,
-	{
-	// summary:
-	//		A container that has multiple children, but shows only
-	//		one child at a time
-	//
-	// description:
-	//		A container for widgets (ContentPanes, for example) That displays
-	//		only one Widget at a time.
-	//
-	//		Publishes topics [widgetId]-addChild, [widgetId]-removeChild, and [widgetId]-selectChild
-	//
-	//		Can be base class for container, Wizard, Show, etc.
-
-	// doLayout: Boolean
-	//		If true, change the size of my currently displayed child to match my size
-	doLayout: true,
-
-	// persist: Boolean
-	//		Remembers the selected child across sessions
-	persist: false,
-
-	baseClass: "dijitStackContainer",
-
-/*=====
-	// selectedChildWidget: [readonly] dijit._Widget
-	//		References the currently selected child widget, if any.
-	//		Adjust selected child with selectChild() method.
-	selectedChildWidget: null,
-=====*/
-
-	postCreate: function(){
-		this.inherited(arguments);
-		dojo.addClass(this.domNode, "dijitLayoutContainer");
-		dijit.setWaiRole(this.containerNode, "tabpanel");
-		this.connect(this.domNode, "onkeypress", this._onKeyPress);
-	},
-
-	startup: function(){
-		if(this._started){ return; }
-
-		var children = this.getChildren();
-
-		// Setup each page panel to be initially hidden
-		dojo.forEach(children, this._setupChild, this);
-
-		// Figure out which child to initially display, defaulting to first one
-		if(this.persist){
-			this.selectedChildWidget = dijit.byId(dojo.cookie(this.id + "_selectedChild"));
-		}else{
-			dojo.some(children, function(child){
-				if(child.selected){
-					this.selectedChildWidget = child;
-				}
-				return child.selected;
-			}, this);
-		}
-		var selected = this.selectedChildWidget;
-		if(!selected && children[0]){
-			selected = this.selectedChildWidget = children[0];
-			selected.selected = true;
-		}
-
-		// Publish information about myself so any StackControllers can initialize.
-		// This needs to happen before this.inherited(arguments) so that for
-		// TabContainer, this._contentBox doesn't include the space for the tab labels.
-		dojo.publish(this.id+"-startup", [{children: children, selected: selected}]);
-
-		// Startup each child widget, and do initial layout like setting this._contentBox,
-		// then calls this.resize() which does the initial sizing on the selected child.
-		this.inherited(arguments);
-	},
-
-	resize: function(){
-		// Resize is called when we are first made visible (it's called from startup()
-		// if we are initially visible).   If this is the first time we've been made
-		// visible then show our first child.
-		var selected = this.selectedChildWidget;
-		if(selected && !this._hasBeenShown){
-			this._hasBeenShown = true;
-			this._showChild(selected);
-		}
-		this.inherited(arguments);
-	},
-
-	_setupChild: function(/*dijit._Widget*/ child){
-		// Overrides _LayoutWidget._setupChild()
-
-		this.inherited(arguments);
-
-		dojo.removeClass(child.domNode, "dijitVisible");
-		dojo.addClass(child.domNode, "dijitHidden");
-
-		// remove the title attribute so it doesn't show up when i hover
-		// over a node
-		child.domNode.title = "";
-	},
-
-	addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
-		// Overrides _Container.addChild() to do layout and publish events
-
-		this.inherited(arguments);
-
-		if(this._started){
-			dojo.publish(this.id+"-addChild", [child, insertIndex]);
-
-			// in case the tab titles have overflowed from one line to two lines
-			// (or, if this if first child, from zero lines to one line)
-			// TODO: w/ScrollingTabController this is no longer necessary, although
-			// ScrollTabController.resize() does need to get called to show/hide
-			// the navigation buttons as appropriate, but that's handled in ScrollingTabController.onAddChild()
-			this.layout();
-
-			// if this is the first child, then select it
-			if(!this.selectedChildWidget){
-				this.selectChild(child);
-			}
-		}
-	},
-
-	removeChild: function(/*dijit._Widget*/ page){
-		// Overrides _Container.removeChild() to do layout and publish events
-
-		this.inherited(arguments);
-
-		if(this._started){
-			// this will notify any tablists to remove a button; do this first because it may affect sizing
-			dojo.publish(this.id + "-removeChild", [page]);
-		}
-
-		// If we are being destroyed than don't run the code below (to select another page), because we are deleting
-		// every page one by one
-		if(this._beingDestroyed){ return; }
-
-		if(this._started){
-			// in case the tab titles now take up one line instead of two lines
-			// TODO: this is overkill in most cases since ScrollingTabController never changes size (for >= 1 tab)
-			this.layout();
-		}
-
-		if(this.selectedChildWidget === page){
-			this.selectedChildWidget = undefined;
-			if(this._started){
-				var children = this.getChildren();
-				if(children.length){
-					this.selectChild(children[0]);
-				}
-			}
-		}
-	},
-
-	selectChild: function(/*dijit._Widget|String*/ page){
-		// summary:
-		//		Show the given widget (which must be one of my children)
-		// page:
-		//		Reference to child widget or id of child widget
-
-		page = dijit.byId(page);
-
-		if(this.selectedChildWidget != page){
-			// Deselect old page and select new one
-			this._transition(page, this.selectedChildWidget);
-			this.selectedChildWidget = page;
-			dojo.publish(this.id+"-selectChild", [page]);
-
-			if(this.persist){
-				dojo.cookie(this.id + "_selectedChild", this.selectedChildWidget.id);
-			}
-		}
-	},
-
-	_transition: function(/*dijit._Widget*/newWidget, /*dijit._Widget*/oldWidget){
-		// summary:
-		//		Hide the old widget and display the new widget.
-		//		Subclasses should override this.
-		// tags:
-		//		protected extension
-		if(oldWidget){
-			this._hideChild(oldWidget);
-		}
-		this._showChild(newWidget);
-
-		// Size the new widget, in case this is the first time it's being shown,
-		// or I have been resized since the last time it was shown.
-		// Note that page must be visible for resizing to work.
-		if(newWidget.resize){
-			if(this.doLayout){
-				newWidget.resize(this._containerContentBox || this._contentBox);
-			}else{
-				// the child should pick it's own size but we still need to call resize()
-				// (with no arguments) to let the widget lay itself out
-				newWidget.resize();
-			}
-		}
-	},
-
-	_adjacent: function(/*Boolean*/ forward){
-		// summary:
-		//		Gets the next/previous child widget in this container from the current selection.
-		var children = this.getChildren();
-		var index = dojo.indexOf(children, this.selectedChildWidget);
-		index += forward ? 1 : children.length - 1;
-		return children[ index % children.length ]; // dijit._Widget
-	},
-
-	forward: function(){
-		// summary:
-		//		Advance to next page.
-		this.selectChild(this._adjacent(true));
-	},
-
-	back: function(){
-		// summary:
-		//		Go back to previous page.
-		this.selectChild(this._adjacent(false));
-	},
-
-	_onKeyPress: function(e){
-		dojo.publish(this.id+"-containerKeyPress", [{ e: e, page: this}]);
-	},
-
-	layout: function(){
-		// Implement _LayoutWidget.layout() virtual method.
-		if(this.doLayout && this.selectedChildWidget && this.selectedChildWidget.resize){
-			this.selectedChildWidget.resize(this._contentBox);
-		}
-	},
-
-	_showChild: function(/*dijit._Widget*/ page){
-		// summary:
-		//		Show the specified child by changing it's CSS, and call _onShow()/onShow() so
-		//		it can do any updates it needs regarding loading href's etc.
-		var children = this.getChildren();
-		page.isFirstChild = (page == children[0]);
-		page.isLastChild = (page == children[children.length-1]);
-		page.selected = true;
-
-		dojo.removeClass(page.domNode, "dijitHidden");
-		dojo.addClass(page.domNode, "dijitVisible");
-
-		page._onShow();
-	},
-
-	_hideChild: function(/*dijit._Widget*/ page){
-		// summary:
-		//		Hide the specified child by changing it's CSS, and call _onHide() so
-		//		it's notified.
-		page.selected=false;
-		dojo.removeClass(page.domNode, "dijitVisible");
-		dojo.addClass(page.domNode, "dijitHidden");
-
-		page.onHide();
-	},
-
-	closeChild: function(/*dijit._Widget*/ page){
-		// summary:
-		//		Callback when user clicks the [X] to remove a page.
-		//		If onClose() returns true then remove and destroy the child.
-		// tags:
-		//		private
-		var remove = page.onClose(this, page);
-		if(remove){
-			this.removeChild(page);
-			// makes sure we can clean up executeScripts in ContentPane onUnLoad
-			page.destroyRecursive();
-		}
-	},
-
-	destroyDescendants: function(/*Boolean*/preserveDom){
-		dojo.forEach(this.getChildren(), function(child){
-			this.removeChild(child);
-			child.destroyRecursive(preserveDom);
-		}, this);
-	}
-});
-
-// For back-compat, remove for 2.0
-
-
-
-// These arguments can be specified for the children of a StackContainer.
-// Since any widget can be specified as a StackContainer child, mix them
-// into the base widget class.  (This is a hack, but it's effective.)
-dojo.extend(dijit._Widget, {
-	// selected: Boolean
-	//		Parameter for children of `dijit.layout.StackContainer` or subclasses.
-	//		Specifies that this widget should be the initially displayed pane.
-	//		Note: to change the selected child use `dijit.layout.StackContainer.selectChild`
-	selected: false,
-
-	// closable: Boolean
-	//		Parameter for children of `dijit.layout.StackContainer` or subclasses.
-	//		True if user can close (destroy) this child, such as (for example) clicking the X on the tab.
-	closable: false,
-
-	// iconClass: String
-	//		Parameter for children of `dijit.layout.StackContainer` or subclasses.
-	//		CSS Class specifying icon to use in label associated with this pane.
-	iconClass: "",
-
-	// showTitle: Boolean
-	//		Parameter for children of `dijit.layout.StackContainer` or subclasses.
-	//		When true, display title of this widget as tab label etc., rather than just using
-	//		icon specified in iconClass
-	showTitle: true,
-
-	onClose: function(){
-		// summary:
-		//		Parameter for children of `dijit.layout.StackContainer` or subclasses.
-		//		Callback if a user tries to close the child.   Child will be closed if this function returns true.
-		// tags:
-		//		extension
-
-		return true;		// Boolean
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.layout.AccordionPane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.AccordionPane"] = true;
-dojo.provide("dijit.layout.AccordionPane");
-
-
-
-dojo.declare("dijit.layout.AccordionPane", dijit.layout.ContentPane, {
-	// summary:
-	//		Deprecated widget.   Use `dijit.layout.ContentPane` instead.
-	// tags:
-	//		deprecated
-
-	constructor: function(){
-		dojo.deprecated("dijit.layout.AccordionPane deprecated, use ContentPane instead", "", "2.0");
-	},
-
-	onSelected: function(){
-		// summary:
-		//		called when this pane is selected
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.layout.AccordionContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.AccordionContainer"] = true;
-dojo.provide("dijit.layout.AccordionContainer");
-
-
-
-
-
-
-
-
-	// for back compat, remove for 2.0
-
-dojo.declare(
-	"dijit.layout.AccordionContainer",
-	dijit.layout.StackContainer,
-	{
-		// summary:
-		//		Holds a set of panes where every pane's title is visible, but only one pane's content is visible at a time,
-		//		and switching between panes is visualized by sliding the other panes up/down.
-		// example:
-		//	| 	<div dojoType="dijit.layout.AccordionContainer">
-		//	|		<div dojoType="dijit.layout.ContentPane" title="pane 1">
-		//	|		</div>
-		//	|		<div dojoType="dijit.layout.ContentPane" title="pane 2">
-		//	|			<p>This is some text</p>
-		//	|		</div>
-		//	|	</div>
-
-		// duration: Integer
-		//		Amount of time (in ms) it takes to slide panes
-		duration: dijit.defaultDuration,
-
-		// buttonWidget: [const] String
-		//		The name of the widget used to display the title of each pane
-		buttonWidget: "dijit.layout._AccordionButton",
-
-		// _verticalSpace: Number
-		//		Pixels of space available for the open pane
-		//		(my content box size minus the cumulative size of all the title bars)
-		_verticalSpace: 0,
-
-		baseClass: "dijitAccordionContainer",
-
-		postCreate: function(){
-			this.domNode.style.overflow = "hidden";
-			this.inherited(arguments);
-			dijit.setWaiRole(this.domNode, "tablist");
-		},
-
-		startup: function(){
-			if(this._started){ return; }
-			this.inherited(arguments);
-			if(this.selectedChildWidget){
-				var style = this.selectedChildWidget.containerNode.style;
-				style.display = "";
-				style.overflow = "auto";
-				this.selectedChildWidget._buttonWidget._setSelectedState(true);
-			}
-		},
-
-		_getTargetHeight: function(/* Node */ node){
-			// summary:
-			//		For the given node, returns the height that should be
-			//		set to achieve our vertical space (subtract any padding
-			//		we may have).
-			//
-			//		This is used by the animations.
-			//
-			//		TODO: I don't think this works correctly in IE quirks when an elements
-			//		style.height including padding and borders
-			var cs = dojo.getComputedStyle(node);
-			return Math.max(this._verticalSpace - dojo._getPadBorderExtents(node, cs).h, 0);
-		},
-
-		layout: function(){
-			// Implement _LayoutWidget.layout() virtual method.
-			// Set the height of the open pane based on what room remains.
-
-			var openPane = this.selectedChildWidget;
-
-			// get cumulative height of all the title bars
-			var totalCollapsedHeight = 0;
-			dojo.forEach(this.getChildren(), function(child){
-				totalCollapsedHeight += child._buttonWidget.getTitleHeight();
-			});
-			var mySize = this._contentBox;
-			this._verticalSpace = mySize.h - totalCollapsedHeight;
-
-			// Memo size to make displayed child
-			this._containerContentBox = {
-				h: this._verticalSpace,
-				w: mySize.w
-			};
-
-			if(openPane){
-				openPane.resize(this._containerContentBox);
-			}
-		},
-
-		_setupChild: function(child){
-			// Overrides _LayoutWidget._setupChild().
-			// Setup clickable title to sit above the child widget,
-			// and stash pointer to it inside the widget itself.
-
-			var cls = dojo.getObject(this.buttonWidget);
-			var button = (child._buttonWidget = new cls({
-				contentWidget: child,
-				label: child.title,
-				title: child.tooltip,
-				iconClass: child.iconClass,
-				id: child.id + "_button",
-				parent: this
-			}));
-
-			child._accordionConnectHandle = this.connect(child, 'attr', function(name, value){
-				if(arguments.length == 2){
-					switch(name){
-					case 'title':
-					case 'iconClass':
-						button.attr(name, value);
-					}
-				}
-			});
-
-			dojo.place(child._buttonWidget.domNode, child.domNode, "before");
-
-			this.inherited(arguments);
-		},
-
-		removeChild: function(child){
-			// Overrides _LayoutWidget.removeChild().
-			this.disconnect(child._accordionConnectHandle);
-			delete child._accordionConnectHandle;
-
-			child._buttonWidget.destroy();
-			delete child._buttonWidget;
-
-			this.inherited(arguments);
-		},
-
-		getChildren: function(){
-			// Overrides _Container.getChildren() to ignore titles and only look at panes.
-			return dojo.filter(this.inherited(arguments), function(child){
-				return child.declaredClass != this.buttonWidget;
-			}, this);
-		},
-
-		destroy: function(){
-			dojo.forEach(this.getChildren(), function(child){
-				child._buttonWidget.destroy();
-			});
-			this.inherited(arguments);
-		},
-
-		_transition: function(/*Widget?*/newWidget, /*Widget?*/oldWidget){
-			// Overrides StackContainer._transition() to provide sliding of title bars etc.
-
-//TODO: should be able to replace this with calls to slideIn/slideOut
-			if(this._inTransition){ return; }
-			this._inTransition = true;
-			var animations = [];
-			var paneHeight = this._verticalSpace;
-			if(newWidget){
-				newWidget._buttonWidget.setSelected(true);
-
-				this._showChild(newWidget);	// prepare widget to be slid in
-
-				// Size the new widget, in case this is the first time it's being shown,
-				// or I have been resized since the last time it was shown.
-				// Note that page must be visible for resizing to work.
-				if(this.doLayout && newWidget.resize){
-					newWidget.resize(this._containerContentBox);
-				}
-
-				var newContents = newWidget.domNode;
-				dojo.addClass(newContents, "dijitVisible");
-				dojo.removeClass(newContents, "dijitHidden");
-				var newContentsOverflow = newContents.style.overflow;
-				newContents.style.overflow = "hidden";
-				animations.push(dojo.animateProperty({
-					node: newContents,
-					duration: this.duration,
-					properties: {
-						height: { start: 1, end: this._getTargetHeight(newContents) }
-					},
-					onEnd: dojo.hitch(this, function(){
-						newContents.style.overflow = newContentsOverflow;
-						delete this._inTransition;
-					})
-				}));
-			}
-			if(oldWidget){
-				oldWidget._buttonWidget.setSelected(false);
-				var oldContents = oldWidget.domNode,
-					oldContentsOverflow = oldContents.style.overflow;
-				oldContents.style.overflow = "hidden";
-				animations.push(dojo.animateProperty({
-					node: oldContents,
-					duration: this.duration,
-					properties: {
-						height: { start: this._getTargetHeight(oldContents), end: 1 }
-					},
-					onEnd: function(){
-						dojo.addClass(oldContents, "dijitHidden");
-						dojo.removeClass(oldContents, "dijitVisible");
-						oldContents.style.overflow = oldContentsOverflow;
-						if(oldWidget.onHide){
-							oldWidget.onHide();
-						}
-					}
-				}));
-			}
-
-			dojo.fx.combine(animations).play();
-		},
-
-		// note: we are treating the container as controller here
-		_onKeyPress: function(/*Event*/ e, /*dijit._Widget*/ fromTitle){
-			// summary:
-			//		Handle keypress events
-			// description:
-			//		This is called from a handler on AccordionContainer.domNode
-			//		(setup in StackContainer), and is also called directly from
-			//		the click handler for accordion labels
-			if(this._inTransition || this.disabled || e.altKey || !(fromTitle || e.ctrlKey)){
-				if(this._inTransition){
-					dojo.stopEvent(e);
-				}
-				return;
-			}
-			var k = dojo.keys,
-				c = e.charOrCode;
-			if((fromTitle && (c == k.LEFT_ARROW || c == k.UP_ARROW)) ||
-					(e.ctrlKey && c == k.PAGE_UP)){
-				this._adjacent(false)._buttonWidget._onTitleClick();
-				dojo.stopEvent(e);
-			}else if((fromTitle && (c == k.RIGHT_ARROW || c == k.DOWN_ARROW)) ||
-					(e.ctrlKey && (c == k.PAGE_DOWN || c == k.TAB))){
-				this._adjacent(true)._buttonWidget._onTitleClick();
-				dojo.stopEvent(e);
-			}
-		}
-	}
-);
-
-dojo.declare("dijit.layout._AccordionButton",
-	[dijit._Widget, dijit._Templated],
-	{
-	// summary:
-	//		The title bar to click to open up an accordion pane.
-	//		Internal widget used by AccordionContainer.
-	// tags:
-	//		private
-
-	templateString: dojo.cache("dijit.layout", "templates/AccordionButton.html", "<div dojoAttachPoint='titleNode,focusNode' dojoAttachEvent='ondijitclick:_onTitleClick,onkeypress:_onTitleKeyPress,onfocus:_handleFocus,onblur:_handleFocus,onmouseenter:_onTitleEnter,onmouseleave:_onTitleLeave'\n\t\tclass='dijitAccordionTitle' wairole=\"tab\" waiState=\"expanded-false\"\n\t\t><span class='dijitInline dijitAccordionArrow' waiRole=\"presentation\"></span\n\t\t><span class='arrowTextUp' waiRole=\ [...]
-	attributeMap: dojo.mixin(dojo.clone(dijit.layout.ContentPane.prototype.attributeMap), {
-		label: {node: "titleTextNode", type: "innerHTML" },
-		title: {node: "titleTextNode", type: "attribute", attribute: "title"},
-		iconClass: { node: "iconNode", type: "class" }
-	}),
-
-	baseClass: "dijitAccordionTitle",
-
-	getParent: function(){
-		// summary:
-		//		Returns the parent.
-		// tags:
-		//		private
-		return this.parent;
-	},
-
-	postCreate: function(){
-		this.inherited(arguments);
-		dojo.setSelectable(this.domNode, false);
-		this.setSelected(this.selected);
-		var titleTextNodeId = dojo.attr(this.domNode,'id').replace(' ','_');
-		dojo.attr(this.titleTextNode, "id", titleTextNodeId+"_title");
-		dijit.setWaiState(this.focusNode, "labelledby", dojo.attr(this.titleTextNode, "id"));
-	},
-
-	getTitleHeight: function(){
-		// summary:
-		//		Returns the height of the title dom node.
-		return dojo.marginBox(this.titleNode).h;	// Integer
-	},
-
-	_onTitleClick: function(){
-		// summary:
-		//		Callback when someone clicks my title.
-		var parent = this.getParent();
-		if(!parent._inTransition){
-			parent.selectChild(this.contentWidget);
-			dijit.focus(this.focusNode);
-		}
-	},
-
-	_onTitleEnter: function(){
-		// summary:
-		//		Callback when someone hovers over my title.
-		dojo.addClass(this.focusNode, "dijitAccordionTitle-hover");
-	},
-
-	_onTitleLeave: function(){
-		// summary:
-		//		Callback when someone stops hovering over my title.
-		dojo.removeClass(this.focusNode, "dijitAccordionTitle-hover");
-	},
-
-	_onTitleKeyPress: function(/*Event*/ evt){
-		return this.getParent()._onKeyPress(evt, this.contentWidget);
-	},
-
-	_setSelectedState: function(/*Boolean*/ isSelected){
-		this.selected = isSelected;
-		dojo[(isSelected ? "addClass" : "removeClass")](this.titleNode,"dijitAccordionTitle-selected");
-		dijit.setWaiState(this.focusNode, "expanded", isSelected);
-		dijit.setWaiState(this.focusNode, "selected", isSelected);
-		this.focusNode.setAttribute("tabIndex", isSelected ? "0" : "-1");
-	},
-
-	_handleFocus: function(/*Event*/ e){
-		// summary:
-		//		Handle the blur and focus state of this widget.
-		dojo.toggleClass(this.titleTextNode, "dijitAccordionFocused", e.type == "focus");
-	},
-
-	setSelected: function(/*Boolean*/ isSelected){
-		// summary:
-		//		Change the selected state on this pane.
-		this._setSelectedState(isSelected);
-		if(isSelected){
-			var cw = this.contentWidget;
-			if(cw.onSelected){ cw.onSelected(); }
-		}
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.layout.BorderContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.BorderContainer"] = true;
-dojo.provide("dijit.layout.BorderContainer");
-
-
-
-
-dojo.declare(
-	"dijit.layout.BorderContainer",
-	dijit.layout._LayoutWidget,
-{
-	// summary:
-	//		Provides layout in up to 5 regions, a mandatory center with optional borders along its 4 sides.
-	//
-	// description:
-	//		A BorderContainer is a box with a specified size, such as style="width: 500px; height: 500px;",
-	//		that contains a child widget marked region="center" and optionally children widgets marked
-	//		region equal to "top", "bottom", "leading", "trailing", "left" or "right".
-	//		Children along the edges will be laid out according to width or height dimensions and may
-	//		include optional splitters (splitter="true") to make them resizable by the user.  The remaining
-	//		space is designated for the center region.
-	//
-	//		NOTE: Splitters must not be more than 50 pixels in width.
-	//
-	//		The outer size must be specified on the BorderContainer node.  Width must be specified for the sides
-	//		and height for the top and bottom, respectively.  No dimensions should be specified on the center;
-	//		it will fill the remaining space.  Regions named "leading" and "trailing" may be used just like
-	//		"left" and "right" except that they will be reversed in right-to-left environments.
-	//
-	// example:
-	// |	<div dojoType="dijit.layout.BorderContainer" design="sidebar" gutters="false"
-	// |            style="width: 400px; height: 300px;">
-	// |		<div dojoType="ContentPane" region="top">header text</div>
-	// |		<div dojoType="ContentPane" region="right" splitter="true" style="width: 200px;">table of contents</div>
-	// |		<div dojoType="ContentPane" region="center">client area</div>
-	// |	</div>
-
-	// design: String
-	//		Which design is used for the layout:
-	//			- "headline" (default) where the top and bottom extend
-	//				the full width of the container
-	//			- "sidebar" where the left and right sides extend from top to bottom.
-	design: "headline",
-
-	// gutters: Boolean
-	//		Give each pane a border and margin.
-	//		Margin determined by domNode.paddingLeft.
-	//		When false, only resizable panes have a gutter (i.e. draggable splitter) for resizing.
-	gutters: true,
-
-	// liveSplitters: Boolean
-	//		Specifies whether splitters resize as you drag (true) or only upon mouseup (false)
-	liveSplitters: true,
-
-	// persist: Boolean
-	//		Save splitter positions in a cookie.
-	persist: false,
-
-	baseClass: "dijitBorderContainer",
-
-	// _splitterClass: String
-	// 		Optional hook to override the default Splitter widget used by BorderContainer
-	_splitterClass: "dijit.layout._Splitter",
-
-	postMixInProperties: function(){
-		// change class name to indicate that BorderContainer is being used purely for
-		// layout (like LayoutContainer) rather than for pretty formatting.
-		if(!this.gutters){
-			this.baseClass += "NoGutter";
-		}
-		this.inherited(arguments);
-	},
-
-	postCreate: function(){
-		this.inherited(arguments);
-
-		this._splitters = {};
-		this._splitterThickness = {};
-	},
-
-	startup: function(){
-		if(this._started){ return; }
-		dojo.forEach(this.getChildren(), this._setupChild, this);
-		this.inherited(arguments);
-	},
-
-	_setupChild: function(/*dijit._Widget*/ child){
-		// Override _LayoutWidget._setupChild().
-
-		var region = child.region;
-		if(region){
-			this.inherited(arguments);
-
-			dojo.addClass(child.domNode, this.baseClass+"Pane");
-
-			var ltr = this.isLeftToRight();
-			if(region == "leading"){ region = ltr ? "left" : "right"; }
-			if(region == "trailing"){ region = ltr ? "right" : "left"; }
-
-			//FIXME: redundant?
-			this["_"+region] = child.domNode;
-			this["_"+region+"Widget"] = child;
-
-			// Create draggable splitter for resizing pane,
-			// or alternately if splitter=false but BorderContainer.gutters=true then
-			// insert dummy div just for spacing
-			if((child.splitter || this.gutters) && !this._splitters[region]){
-				var _Splitter = dojo.getObject(child.splitter ? this._splitterClass : "dijit.layout._Gutter");
-				var splitter = new _Splitter({
-					container: this,
-					child: child,
-					region: region,
-					live: this.liveSplitters
-				});
-				splitter.isSplitter = true;
-				this._splitters[region] = splitter.domNode;
-				dojo.place(this._splitters[region], child.domNode, "after");
-
-				// Splitters arent added as Contained children, so we need to call startup explicitly
-				splitter.startup();
-			}
-			child.region = region;
-		}
-	},
-
-	_computeSplitterThickness: function(region){
-		this._splitterThickness[region] = this._splitterThickness[region] ||
-			dojo.marginBox(this._splitters[region])[(/top|bottom/.test(region) ? 'h' : 'w')];
-	},
-
-	layout: function(){
-		// Implement _LayoutWidget.layout() virtual method.
-		for(var region in this._splitters){ this._computeSplitterThickness(region); }
-		this._layoutChildren();
-	},
-
-	addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
-		// Override _LayoutWidget.addChild().
-		this.inherited(arguments);
-		if(this._started){
-			this.layout(); //OPT
-		}
-	},
-
-	removeChild: function(/*dijit._Widget*/ child){
-		// Override _LayoutWidget.removeChild().
-		var region = child.region;
-		var splitter = this._splitters[region];
-		if(splitter){
-			dijit.byNode(splitter).destroy();
-			delete this._splitters[region];
-			delete this._splitterThickness[region];
-		}
-		this.inherited(arguments);
-		delete this["_"+region];
-		delete this["_" +region+"Widget"];
-		if(this._started){
-			this._layoutChildren(child.region);
-		}
-		dojo.removeClass(child.domNode, this.baseClass+"Pane");
-	},
-
-	getChildren: function(){
-		// Override _LayoutWidget.getChildren() to only return real children, not the splitters.
-		return dojo.filter(this.inherited(arguments), function(widget){
-			return !widget.isSplitter;
-		});
-	},
-
-	getSplitter: function(/*String*/region){
-		// summary:
-		//		Returns the widget responsible for rendering the splitter associated with region
-		var splitter = this._splitters[region];
-		return splitter ? dijit.byNode(splitter) : null;
-	},
-
-	resize: function(newSize, currentSize){
-		// Overrides _LayoutWidget.resize().
-
-		// resetting potential padding to 0px to provide support for 100% width/height + padding
-		// TODO: this hack doesn't respect the box model and is a temporary fix
-		if(!this.cs || !this.pe){
-			var node = this.domNode;
-			this.cs = dojo.getComputedStyle(node);
-			this.pe = dojo._getPadExtents(node, this.cs);
-			this.pe.r = dojo._toPixelValue(node, this.cs.paddingRight);
-			this.pe.b = dojo._toPixelValue(node, this.cs.paddingBottom);
-
-			dojo.style(node, "padding", "0px");
-		}
-
-		this.inherited(arguments);
-	},
-
-	_layoutChildren: function(/*String?*/changedRegion){
-		// summary:
-		//		This is the main routine for setting size/position of each child
-
-		if(!this._borderBox || !this._borderBox.h){
-			// We are currently hidden, or we haven't been sized by our parent yet.
-			// Abort.   Someone will resize us later.
-			return;
-		}
-
-		var sidebarLayout = (this.design == "sidebar");
-		var topHeight = 0, bottomHeight = 0, leftWidth = 0, rightWidth = 0;
-		var topStyle = {}, leftStyle = {}, rightStyle = {}, bottomStyle = {},
-			centerStyle = (this._center && this._center.style) || {};
-
-		var changedSide = /left|right/.test(changedRegion);
-
-		var layoutSides = !changedRegion || (!changedSide && !sidebarLayout);
-		var layoutTopBottom = !changedRegion || (changedSide && sidebarLayout);
-
-		// Ask browser for width/height of side panes.
-		// Would be nice to cache this but height can change according to width
-		// (because words wrap around).  I don't think width will ever change though
-		// (except when the user drags a splitter).
-		if(this._top){
-			topStyle = layoutTopBottom && this._top.style;
-			topHeight = dojo.marginBox(this._top).h;
-		}
-		if(this._left){
-			leftStyle = layoutSides && this._left.style;
-			leftWidth = dojo.marginBox(this._left).w;
-		}
-		if(this._right){
-			rightStyle = layoutSides && this._right.style;
-			rightWidth = dojo.marginBox(this._right).w;
-		}
-		if(this._bottom){
-			bottomStyle = layoutTopBottom && this._bottom.style;
-			bottomHeight = dojo.marginBox(this._bottom).h;
-		}
-
-		var splitters = this._splitters;
-		var topSplitter = splitters.top, bottomSplitter = splitters.bottom,
-			leftSplitter = splitters.left, rightSplitter = splitters.right;
-		var splitterThickness = this._splitterThickness;
-		var topSplitterThickness = splitterThickness.top || 0,
-			leftSplitterThickness = splitterThickness.left || 0,
-			rightSplitterThickness = splitterThickness.right || 0,
-			bottomSplitterThickness = splitterThickness.bottom || 0;
-
-		// Check for race condition where CSS hasn't finished loading, so
-		// the splitter width == the viewport width (#5824)
-		if(leftSplitterThickness > 50 || rightSplitterThickness > 50){
-			setTimeout(dojo.hitch(this, function(){
-				// Results are invalid.  Clear them out.
-				this._splitterThickness = {};
-
-				for(var region in this._splitters){
-					this._computeSplitterThickness(region);
-				}
-				this._layoutChildren();
-			}), 50);
-			return false;
-		}
-
-		var pe = this.pe;
-
-		var splitterBounds = {
-			left: (sidebarLayout ? leftWidth + leftSplitterThickness: 0) + pe.l + "px",
-			right: (sidebarLayout ? rightWidth + rightSplitterThickness: 0) + pe.r + "px"
-		};
-
-		if(topSplitter){
-			dojo.mixin(topSplitter.style, splitterBounds);
-			topSplitter.style.top = topHeight + pe.t + "px";
-		}
-
-		if(bottomSplitter){
-			dojo.mixin(bottomSplitter.style, splitterBounds);
-			bottomSplitter.style.bottom = bottomHeight + pe.b + "px";
-		}
-
-		splitterBounds = {
-			top: (sidebarLayout ? 0 : topHeight + topSplitterThickness) + pe.t + "px",
-			bottom: (sidebarLayout ? 0 : bottomHeight + bottomSplitterThickness) + pe.b + "px"
-		};
-
-		if(leftSplitter){
-			dojo.mixin(leftSplitter.style, splitterBounds);
-			leftSplitter.style.left = leftWidth + pe.l + "px";
-		}
-
-		if(rightSplitter){
-			dojo.mixin(rightSplitter.style, splitterBounds);
-			rightSplitter.style.right = rightWidth + pe.r +	"px";
-		}
-
-		dojo.mixin(centerStyle, {
-			top: pe.t + topHeight + topSplitterThickness + "px",
-			left: pe.l + leftWidth + leftSplitterThickness + "px",
-			right: pe.r + rightWidth + rightSplitterThickness + "px",
-			bottom: pe.b + bottomHeight + bottomSplitterThickness + "px"
-		});
-
-		var bounds = {
-			top: sidebarLayout ? pe.t + "px" : centerStyle.top,
-			bottom: sidebarLayout ? pe.b + "px" : centerStyle.bottom
-		};
-		dojo.mixin(leftStyle, bounds);
-		dojo.mixin(rightStyle, bounds);
-		leftStyle.left = pe.l + "px"; rightStyle.right = pe.r + "px"; topStyle.top = pe.t + "px"; bottomStyle.bottom = pe.b + "px";
-		if(sidebarLayout){
-			topStyle.left = bottomStyle.left = leftWidth + leftSplitterThickness + pe.l + "px";
-			topStyle.right = bottomStyle.right = rightWidth + rightSplitterThickness + pe.r + "px";
-		}else{
-			topStyle.left = bottomStyle.left = pe.l + "px";
-			topStyle.right = bottomStyle.right = pe.r + "px";
-		}
-
-		// More calculations about sizes of panes
-		var containerHeight = this._borderBox.h - pe.t - pe.b,
-			middleHeight = containerHeight - ( topHeight + topSplitterThickness + bottomHeight + bottomSplitterThickness),
-			sidebarHeight = sidebarLayout ? containerHeight : middleHeight;
-
-		var containerWidth = this._borderBox.w - pe.l - pe.r,
-			middleWidth = containerWidth - (leftWidth + leftSplitterThickness + rightWidth + rightSplitterThickness),
-			sidebarWidth = sidebarLayout ? middleWidth : containerWidth;
-
-		// New margin-box size of each pane
-		var dim = {
-			top:	{ w: sidebarWidth, h: topHeight },
-			bottom: { w: sidebarWidth, h: bottomHeight },
-			left:	{ w: leftWidth, h: sidebarHeight },
-			right:	{ w: rightWidth, h: sidebarHeight },
-			center:	{ h: middleHeight, w: middleWidth }
-		};
-
-		// Nodes in IE<8 don't respond to t/l/b/r, and TEXTAREA doesn't respond in any browser
-		var janky = dojo.isIE < 8 || (dojo.isIE && dojo.isQuirks) || dojo.some(this.getChildren(), function(child){
-			return child.domNode.tagName == "TEXTAREA" || child.domNode.tagName == "INPUT";
-		});
-		if(janky){
-			// Set the size of the children the old fashioned way, by setting
-			// CSS width and height
-
-			var resizeWidget = function(widget, changes, result){
-				if(widget){
-					(widget.resize ? widget.resize(changes, result) : dojo.marginBox(widget.domNode, changes));
-				}
-			};
-
-			if(leftSplitter){ leftSplitter.style.height = sidebarHeight; }
-			if(rightSplitter){ rightSplitter.style.height = sidebarHeight; }
-			resizeWidget(this._leftWidget, {h: sidebarHeight}, dim.left);
-			resizeWidget(this._rightWidget, {h: sidebarHeight}, dim.right);
-
-			if(topSplitter){ topSplitter.style.width = sidebarWidth; }
-			if(bottomSplitter){ bottomSplitter.style.width = sidebarWidth; }
-			resizeWidget(this._topWidget, {w: sidebarWidth}, dim.top);
-			resizeWidget(this._bottomWidget, {w: sidebarWidth}, dim.bottom);
-
-			resizeWidget(this._centerWidget, dim.center);
-		}else{
-			// We've already sized the children by setting style.top/bottom/left/right...
-			// Now just need to call resize() on those children telling them their new size,
-			// so they can re-layout themselves
-
-			// Calculate which panes need a notification
-			var resizeList = {};
-			if(changedRegion){
-				resizeList[changedRegion] = resizeList.center = true;
-				if(/top|bottom/.test(changedRegion) && this.design != "sidebar"){
-					resizeList.left = resizeList.right = true;
-				}else if(/left|right/.test(changedRegion) && this.design == "sidebar"){
-					resizeList.top = resizeList.bottom = true;
-				}
-			}
-
-			dojo.forEach(this.getChildren(), function(child){
-				if(child.resize && (!changedRegion || child.region in resizeList)){
-					child.resize(null, dim[child.region]);
-				}
-			}, this);
-		}
-	},
-
-	destroy: function(){
-		for(var region in this._splitters){
-			var splitter = this._splitters[region];
-			dijit.byNode(splitter).destroy();
-			dojo.destroy(splitter);
-		}
-		delete this._splitters;
-		delete this._splitterThickness;
-		this.inherited(arguments);
-	}
-});
-
-// This argument can be specified for the children of a BorderContainer.
-// Since any widget can be specified as a LayoutContainer child, mix it
-// into the base widget class.  (This is a hack, but it's effective.)
-dojo.extend(dijit._Widget, {
-	// region: [const] String
-	//		Parameter for children of `dijit.layout.BorderContainer`.
-	//		Values: "top", "bottom", "leading", "trailing", "left", "right", "center".
-	//		See the `dijit.layout.BorderContainer` description for details.
-	region: '',
-
-	// splitter: [const] Boolean
-	//		Parameter for child of `dijit.layout.BorderContainer` where region != "center".
-	//		If true, enables user to resize the widget by putting a draggable splitter between
-	//		this widget and the region=center widget.
-	splitter: false,
-
-	// minSize: [const] Number
-	//		Parameter for children of `dijit.layout.BorderContainer`.
-	//		Specifies a minimum size (in pixels) for this widget when resized by a splitter.
-	minSize: 0,
-
-	// maxSize: [const] Number
-	//		Parameter for children of `dijit.layout.BorderContainer`.
-	//		Specifies a maximum size (in pixels) for this widget when resized by a splitter.
-	maxSize: Infinity
-});
-
-
-
-dojo.declare("dijit.layout._Splitter", [ dijit._Widget, dijit._Templated ],
-{
-	// summary:
-	//		A draggable spacer between two items in a `dijit.layout.BorderContainer`.
-	// description:
-	//		This is instantiated by `dijit.layout.BorderContainer`.  Users should not
-	//		create it directly.
-	// tags:
-	//		private
-
-/*=====
- 	// container: [const] dijit.layout.BorderContainer
- 	//		Pointer to the parent BorderContainer
-	container: null,
-
-	// child: [const] dijit.layout._LayoutWidget
-	//		Pointer to the pane associated with this splitter
-	child: null,
-
-	// region: String
-	//		Region of pane associated with this splitter.
-	//		"top", "bottom", "left", "right".
-	region: null,
-=====*/
-
-	// live: [const] Boolean
-	//		If true, the child's size changes and the child widget is redrawn as you drag the splitter;
-	//		otherwise, the size doesn't change until you drop the splitter (by mouse-up)
-	live: true,
-
-	templateString: '<div class="dijitSplitter" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_startDrag,onmouseenter:_onMouse,onmouseleave:_onMouse" tabIndex="0" waiRole="separator"><div class="dijitSplitterThumb"></div></div>',
-
-	postCreate: function(){
-		this.inherited(arguments);
-		this.horizontal = /top|bottom/.test(this.region);
-		dojo.addClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V"));
-//		dojo.addClass(this.child.domNode, "dijitSplitterPane");
-//		dojo.setSelectable(this.domNode, false); //TODO is this necessary?
-
-		this._factor = /top|left/.test(this.region) ? 1 : -1;
-
-		this._cookieName = this.container.id + "_" + this.region;
-		if(this.container.persist){
-			// restore old size
-			var persistSize = dojo.cookie(this._cookieName);
-			if(persistSize){
-				this.child.domNode.style[this.horizontal ? "height" : "width"] = persistSize;
-			}
-		}
-	},
-
-	_computeMaxSize: function(){
-		// summary:
-		//		Compute the maximum size that my corresponding pane can be set to
-
-		var dim = this.horizontal ? 'h' : 'w',
-			thickness = this.container._splitterThickness[this.region];
-			
-		// Get DOMNode of opposite pane, if an opposite pane exists.
-		// Ex: if I am the _Splitter for the left pane, then get the right pane.
-		var flip = {left:'right', right:'left', top:'bottom', bottom:'top', leading:'trailing', trailing:'leading'},
-			oppNode = this.container["_" + flip[this.region]];
-		
-		// I can expand up to the edge of the opposite pane, or if there's no opposite pane, then to
-		// edge of BorderContainer
-		var available = dojo.contentBox(this.container.domNode)[dim] -
-				(oppNode ? dojo.marginBox(oppNode)[dim] : 0) -
-				20 - thickness * 2;
-
-		return Math.min(this.child.maxSize, available);
-	},
-
-	_startDrag: function(e){
-		if(!this.cover){
-			this.cover = dojo.doc.createElement('div');
-			dojo.addClass(this.cover, "dijitSplitterCover");
-			dojo.place(this.cover, this.child.domNode, "after");
-		}
-		dojo.addClass(this.cover, "dijitSplitterCoverActive");
-
-		// Safeguard in case the stop event was missed.  Shouldn't be necessary if we always get the mouse up.
-		if(this.fake){ dojo.destroy(this.fake); }
-		if(!(this._resize = this.live)){ //TODO: disable live for IE6?
-			// create fake splitter to display at old position while we drag
-			(this.fake = this.domNode.cloneNode(true)).removeAttribute("id");
-			dojo.addClass(this.domNode, "dijitSplitterShadow");
-			dojo.place(this.fake, this.domNode, "after");
-		}
-		dojo.addClass(this.domNode, "dijitSplitterActive");
-		dojo.addClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Active");
-		if(this.fake){
-			dojo.removeClass(this.fake, "dijitSplitterHover");
-			dojo.removeClass(this.fake, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover");
-		}
-
-		//Performance: load data info local vars for onmousevent function closure
-		var factor = this._factor,
-			max = this._computeMaxSize(),
-			min = this.child.minSize || 20,
-			isHorizontal = this.horizontal,
-			axis = isHorizontal ? "pageY" : "pageX",
-			pageStart = e[axis],
-			splitterStyle = this.domNode.style,
-			dim = isHorizontal ? 'h' : 'w',
-			childStart = dojo.marginBox(this.child.domNode)[dim],
-			region = this.region,
-			splitterStart = parseInt(this.domNode.style[region], 10),
-			resize = this._resize,
-			mb = {},
-			childNode = this.child.domNode,
-			layoutFunc = dojo.hitch(this.container, this.container._layoutChildren),
-			de = dojo.doc.body;
-
-		this._handlers = (this._handlers || []).concat([
-			dojo.connect(de, "onmousemove", this._drag = function(e, forceResize){
-				var delta = e[axis] - pageStart,
-					childSize = factor * delta + childStart,
-					boundChildSize = Math.max(Math.min(childSize, max), min);
-
-				if(resize || forceResize){
-					mb[dim] = boundChildSize;
-					// TODO: inefficient; we set the marginBox here and then immediately layoutFunc() needs to query it
-					dojo.marginBox(childNode, mb);
-					layoutFunc(region);
-				}
-				splitterStyle[region] = factor * delta + splitterStart + (boundChildSize - childSize) + "px";
-			}),
-			dojo.connect(dojo.doc, "ondragstart", dojo.stopEvent),
-			dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent),
-			dojo.connect(de, "onmouseup", this, "_stopDrag")
-		]);
-		dojo.stopEvent(e);
-	},
-
-	_onMouse: function(e){
-		var o = (e.type == "mouseover" || e.type == "mouseenter");
-		dojo.toggleClass(this.domNode, "dijitSplitterHover", o);
-		dojo.toggleClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover", o);
-	},
-
-	_stopDrag: function(e){
-		try{
-			if(this.cover){
-				dojo.removeClass(this.cover, "dijitSplitterCoverActive");
-			}
-			if(this.fake){ dojo.destroy(this.fake); }
-			dojo.removeClass(this.domNode, "dijitSplitterActive");
-			dojo.removeClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Active");
-			dojo.removeClass(this.domNode, "dijitSplitterShadow");
-			this._drag(e); //TODO: redundant with onmousemove?
-			this._drag(e, true);
-		}finally{
-			this._cleanupHandlers();
-			delete this._drag;
-		}
-
-		if(this.container.persist){
-			dojo.cookie(this._cookieName, this.child.domNode.style[this.horizontal ? "height" : "width"], {expires:365});
-		}
-	},
-
-	_cleanupHandlers: function(){
-		dojo.forEach(this._handlers, dojo.disconnect);
-		delete this._handlers;
-	},
-
-	_onKeyPress: function(/*Event*/ e){
-		// should we apply typematic to this?
-		this._resize = true;
-		var horizontal = this.horizontal;
-		var tick = 1;
-		var dk = dojo.keys;
-		switch(e.charOrCode){
-			case horizontal ? dk.UP_ARROW : dk.LEFT_ARROW:
-				tick *= -1;
-//				break;
-			case horizontal ? dk.DOWN_ARROW : dk.RIGHT_ARROW:
-				break;
-			default:
-//				this.inherited(arguments);
-				return;
-		}
-		var childSize = dojo.marginBox(this.child.domNode)[ horizontal ? 'h' : 'w' ] + this._factor * tick;
-		var mb = {};
-		mb[ this.horizontal ? "h" : "w"] = Math.max(Math.min(childSize, this._computeMaxSize()), this.child.minSize);
-		dojo.marginBox(this.child.domNode, mb);
-		this.container._layoutChildren(this.region);
-		dojo.stopEvent(e);
-	},
-
-	destroy: function(){
-		this._cleanupHandlers();
-		delete this.child;
-		delete this.container;
-		delete this.cover;
-		delete this.fake;
-		this.inherited(arguments);
-	}
-});
-
-dojo.declare("dijit.layout._Gutter", [dijit._Widget, dijit._Templated ],
-{
-	// summary:
-	// 		Just a spacer div to separate side pane from center pane.
-	//		Basically a trick to lookup the gutter/splitter width from the theme.
-	// description:
-	//		Instantiated by `dijit.layout.BorderContainer`.  Users should not
-	//		create directly.
-	// tags:
-	//		private
-
-	templateString: '<div class="dijitGutter" waiRole="presentation"></div>',
-
-	postCreate: function(){
-		this.horizontal = /top|bottom/.test(this.region);
-		dojo.addClass(this.domNode, "dijitGutter" + (this.horizontal ? "H" : "V"));
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.layout.LayoutContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.LayoutContainer"] = true;
-dojo.provide("dijit.layout.LayoutContainer");
-
-
-
-dojo.declare("dijit.layout.LayoutContainer",
-	dijit.layout._LayoutWidget,
-	{
-	// summary:
-	//		Deprecated.  Use `dijit.layout.BorderContainer` instead.
-	//
-	// description:
-	//		Provides Delphi-style panel layout semantics.
-	//
-	//		A LayoutContainer is a box with a specified size (like style="width: 500px; height: 500px;"),
-	//		that contains children widgets marked with "layoutAlign" of "left", "right", "bottom", "top", and "client".
-	//		It takes it's children marked as left/top/bottom/right, and lays them out along the edges of the box,
-	//		and then it takes the child marked "client" and puts it into the remaining space in the middle.
-	//
-	//		Left/right positioning is similar to CSS's "float: left" and "float: right",
-	//		and top/bottom positioning would be similar to "float: top" and "float: bottom", if there were such
-	//		CSS.
-	//
-	//		Note that there can only be one client element, but there can be multiple left, right, top,
-	//		or bottom elements.
-	//
-	// example:
-	// |	<style>
-	// |		html, body{ height: 100%; width: 100%; }
-	// |	</style>
-	// |	<div dojoType="dijit.layout.LayoutContainer" style="width: 100%; height: 100%">
-	// |		<div dojoType="dijit.layout.ContentPane" layoutAlign="top">header text</div>
-	// |		<div dojoType="dijit.layout.ContentPane" layoutAlign="left" style="width: 200px;">table of contents</div>
-	// |		<div dojoType="dijit.layout.ContentPane" layoutAlign="client">client area</div>
-	// |	</div>
-	//
-	//		Lays out each child in the natural order the children occur in.
-	//		Basically each child is laid out into the "remaining space", where "remaining space" is initially
-	//		the content area of this widget, but is reduced to a smaller rectangle each time a child is added.
-	// tags:
-	//		deprecated
-
-	baseClass: "dijitLayoutContainer",
-
-	constructor: function(){
-		dojo.deprecated("dijit.layout.LayoutContainer is deprecated", "use BorderContainer instead", 2.0);
-	},
-
-	layout: function(){
-		dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());
-	},
-
-	addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
-		this.inherited(arguments);
-		if(this._started){
-			dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());
-		}
-	},
-
-	removeChild: function(/*dijit._Widget*/ widget){
-		this.inherited(arguments);
-		if(this._started){
-			dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());
-		}
-	}
-});
-
-// This argument can be specified for the children of a LayoutContainer.
-// Since any widget can be specified as a LayoutContainer child, mix it
-// into the base widget class.  (This is a hack, but it's effective.)
-dojo.extend(dijit._Widget, {
-	// layoutAlign: String
-	//		"none", "left", "right", "bottom", "top", and "client".
-	//		See the LayoutContainer description for details on this parameter.
-	layoutAlign: 'none'
-});
-
-}
-
-if(!dojo._hasResource["dijit.layout.LinkPane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.LinkPane"] = true;
-dojo.provide("dijit.layout.LinkPane");
-
-
-
-
-dojo.declare("dijit.layout.LinkPane",
-	[dijit.layout.ContentPane, dijit._Templated],
-	{
-	// summary:
-	//		A ContentPane with an href where (when declared in markup)
-	//		the title is specified as innerHTML rather than as a title attribute.
-	// description:
-	//		LinkPane is just a ContentPane that is declared in markup similarly
-	//		to an anchor.  The anchor's body (the words between `<a>` and `</a>`)
-	//		become the title of the widget (used for TabContainer, AccordionContainer, etc.)
-	// example:
-	//	| <a href="foo.html">my title</a>
-
-	// I'm using a template because the user may specify the input as
-	// <a href="foo.html">title</a>, in which case we need to get rid of the
-	// <a> because we don't want a link.
-	templateString: '<div class="dijitLinkPane" dojoAttachPoint="containerNode"></div>',
-
-	postMixInProperties: function(){
-		// If user has specified node contents, they become the title
-		// (the link must be plain text)
-		if(this.srcNodeRef){
-			this.title += this.srcNodeRef.innerHTML;
-		}
-		this.inherited(arguments);
-	},
-
-	_fillContent: function(/*DomNode*/ source){
-		// Overrides _Templated._fillContent().
-
-		// _Templated._fillContent() relocates srcNodeRef innerHTML to templated container node,
-		// but in our case the srcNodeRef innerHTML is the title, so shouldn't be
-		// copied
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.layout.SplitContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.SplitContainer"] = true;
-dojo.provide("dijit.layout.SplitContainer");
-
-//
-// FIXME: make it prettier
-// FIXME: active dragging upwards doesn't always shift other bars (direction calculation is wrong in this case)
-//
-
-
-
-
-dojo.declare("dijit.layout.SplitContainer",
-	dijit.layout._LayoutWidget,
-	{
-	// summary:
-	//		Deprecated.  Use `dijit.layout.BorderContainer` instead.
-	// description:
-	//		A Container widget with sizing handles in-between each child.
-	//		Contains multiple children widgets, all of which are displayed side by side
-	//		(either horizontally or vertically); there's a bar between each of the children,
-	//		and you can adjust the relative size of each child by dragging the bars.
-	//
-	//		You must specify a size (width and height) for the SplitContainer.
-	// tags:
-	//		deprecated
-
-	constructor: function(){
-		dojo.deprecated("dijit.layout.SplitContainer is deprecated", "use BorderContainer with splitter instead", 2.0);
-	},
-
-	// activeSizing: Boolean
-	//		If true, the children's size changes as you drag the bar;
-	//		otherwise, the sizes don't change until you drop the bar (by mouse-up)
-	activeSizing: false,
-
-	// sizerWidth: Integer
-	//		Size in pixels of the bar between each child
-	sizerWidth: 7, // FIXME: this should be a CSS attribute (at 7 because css wants it to be 7 until we fix to css)
-
-	// orientation: String
-	//		either 'horizontal' or vertical; indicates whether the children are
-	//		arranged side-by-side or up/down.
-	orientation: 'horizontal',
-
-	// persist: Boolean
-	//		Save splitter positions in a cookie
-	persist: true,
-
-	baseClass: "dijitSplitContainer",
-
-	postMixInProperties: function(){
-		this.inherited("postMixInProperties",arguments);
-		this.isHorizontal = (this.orientation == 'horizontal');
-	},
-
-	postCreate: function(){
-		this.inherited(arguments);
-		this.sizers = [];
-
-		// overflow has to be explicitly hidden for splitContainers using gekko (trac #1435)
-		// to keep other combined css classes from inadvertantly making the overflow visible
-		if(dojo.isMozilla){
-			this.domNode.style.overflow = '-moz-scrollbars-none'; // hidden doesn't work
-		}
-
-		// create the fake dragger
-		if(typeof this.sizerWidth == "object"){
-			try{ //FIXME: do this without a try/catch
-				this.sizerWidth = parseInt(this.sizerWidth.toString());
-			}catch(e){ this.sizerWidth = 7; }
-		}
-		var sizer = dojo.doc.createElement('div');
-		this.virtualSizer = sizer;
-		sizer.style.position = 'relative';
-
-		// #1681: work around the dreaded 'quirky percentages in IE' layout bug
-		// If the splitcontainer's dimensions are specified in percentages, it
-		// will be resized when the virtualsizer is displayed in _showSizingLine
-		// (typically expanding its bounds unnecessarily). This happens because
-		// we use position: relative for .dijitSplitContainer.
-		// The workaround: instead of changing the display style attribute,
-		// switch to changing the zIndex (bring to front/move to back)
-
-		sizer.style.zIndex = 10;
-		sizer.className = this.isHorizontal ? 'dijitSplitContainerVirtualSizerH' : 'dijitSplitContainerVirtualSizerV';
-		this.domNode.appendChild(sizer);
-		dojo.setSelectable(sizer, false);
-	},
-
-	destroy: function(){
-		delete this.virtualSizer;
-		dojo.forEach(this._ownconnects, dojo.disconnect);
-		this.inherited(arguments);
-	},
-	startup: function(){
-		if(this._started){ return; }
-
-		dojo.forEach(this.getChildren(), function(child, i, children){
-			// attach the children and create the draggers
-			this._setupChild(child);
-
-			if(i < children.length-1){
-				this._addSizer();
-			}
-		}, this);
-
-		if(this.persist){
-			this._restoreState();
-		}
-
-		this.inherited(arguments);
-	},
-
-	_setupChild: function(/*dijit._Widget*/ child){
-		this.inherited(arguments);
-		child.domNode.style.position = "absolute";
-		dojo.addClass(child.domNode, "dijitSplitPane");
-	},
-
-	_onSizerMouseDown: function(e){
-		if(e.target.id){
-			for(var i=0;i<this.sizers.length;i++){
-				if(this.sizers[i].id == e.target.id){
-					break;
-				}
-			}
-			if(i<this.sizers.length){
-				this.beginSizing(e,i);
-			}
-		}
-	},
-	_addSizer: function(index){
-		index = index === undefined ? this.sizers.length : index;
-
-		// TODO: use a template for this!!!
-		var sizer = dojo.doc.createElement('div');
-		sizer.id=dijit.getUniqueId('dijit_layout_SplitterContainer_Splitter');
-		this.sizers.splice(index,0,sizer);
-		this.domNode.appendChild(sizer);
-
-		sizer.className = this.isHorizontal ? 'dijitSplitContainerSizerH' : 'dijitSplitContainerSizerV';
-
-		// add the thumb div
-		var thumb = dojo.doc.createElement('div');
-		thumb.className = 'thumb';
-		thumb.id = sizer.id;
-		sizer.appendChild(thumb);
-
-		// FIXME: are you serious? why aren't we using mover start/stop combo?
-		this.connect(sizer, "onmousedown", '_onSizerMouseDown');
-
-		dojo.setSelectable(sizer, false);
-	},
-
-	removeChild: function(widget){
-		// summary:
-		//		Remove sizer, but only if widget is really our child and
-		// we have at least one sizer to throw away
-		if(this.sizers.length){
-			var i=dojo.indexOf(this.getChildren(), widget)
-			if(i != -1){
-				if(i == this.sizers.length){
-					i--;
-				}
-				dojo.destroy(this.sizers[i]);
-				this.sizers.splice(i,1);
-			}
-		}
-
-		// Remove widget and repaint
-		this.inherited(arguments);
-		if(this._started){
-			this.layout();
-		}
-	},
-
-	addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
-		// summary:
-		//		Add a child widget to the container
-		// child:
-		//		a widget to add
-		// insertIndex:
-		//		postion in the "stack" to add the child widget
-
-		this.inherited(arguments);
-
-		if(this._started){
-			// Do the stuff that startup() does for each widget
-			var children = this.getChildren();
-			if(children.length > 1){
-				this._addSizer(insertIndex);
-			}
-
-			// and then reposition (ie, shrink) every pane to make room for the new guy
-			this.layout();
-		}
-	},
-
-	layout: function(){
-		// summary:
-		//		Do layout of panels
-
-		// base class defines this._contentBox on initial creation and also
-		// on resize
-		this.paneWidth = this._contentBox.w;
-		this.paneHeight = this._contentBox.h;
-
-		var children = this.getChildren();
-		if(!children.length){ return; }
-
-		//
-		// calculate space
-		//
-
-		var space = this.isHorizontal ? this.paneWidth : this.paneHeight;
-		if(children.length > 1){
-			space -= this.sizerWidth * (children.length - 1);
-		}
-
-		//
-		// calculate total of SizeShare values
-		//
-		var outOf = 0;
-		dojo.forEach(children, function(child){
-			outOf += child.sizeShare;
-		});
-
-		//
-		// work out actual pixels per sizeshare unit
-		//
-		var pixPerUnit = space / outOf;
-
-		//
-		// set the SizeActual member of each pane
-		//
-		var totalSize = 0;
-		dojo.forEach(children.slice(0, children.length - 1), function(child){
-			var size = Math.round(pixPerUnit * child.sizeShare);
-			child.sizeActual = size;
-			totalSize += size;
-		});
-
-		children[children.length-1].sizeActual = space - totalSize;
-
-		//
-		// make sure the sizes are ok
-		//
-		this._checkSizes();
-
-		//
-		// now loop, positioning each pane and letting children resize themselves
-		//
-
-		var pos = 0;
-		var size = children[0].sizeActual;
-		this._movePanel(children[0], pos, size);
-		children[0].position = pos;
-		pos += size;
-
-		// if we don't have any sizers, our layout method hasn't been called yet
-		// so bail until we are called..TODO: REVISIT: need to change the startup
-		// algorithm to guaranteed the ordering of calls to layout method
-		if(!this.sizers){
-			return;
-		}
-
-		dojo.some(children.slice(1), function(child, i){
-			// error-checking
-			if(!this.sizers[i]){
-				return true;
-			}
-			// first we position the sizing handle before this pane
-			this._moveSlider(this.sizers[i], pos, this.sizerWidth);
-			this.sizers[i].position = pos;
-			pos += this.sizerWidth;
-
-			size = child.sizeActual;
-			this._movePanel(child, pos, size);
-			child.position = pos;
-			pos += size;
-		}, this);
-	},
-
-	_movePanel: function(panel, pos, size){
-		if(this.isHorizontal){
-			panel.domNode.style.left = pos + 'px';	// TODO: resize() takes l and t parameters too, don't need to set manually
-			panel.domNode.style.top = 0;
-			var box = {w: size, h: this.paneHeight};
-			if(panel.resize){
-				panel.resize(box);
-			}else{
-				dojo.marginBox(panel.domNode, box);
-			}
-		}else{
-			panel.domNode.style.left = 0;	// TODO: resize() takes l and t parameters too, don't need to set manually
-			panel.domNode.style.top = pos + 'px';
-			var box = {w: this.paneWidth, h: size};
-			if(panel.resize){
-				panel.resize(box);
-			}else{
-				dojo.marginBox(panel.domNode, box);
-			}
-		}
-	},
-
-	_moveSlider: function(slider, pos, size){
-		if(this.isHorizontal){
-			slider.style.left = pos + 'px';
-			slider.style.top = 0;
-			dojo.marginBox(slider, { w: size, h: this.paneHeight });
-		}else{
-			slider.style.left = 0;
-			slider.style.top = pos + 'px';
-			dojo.marginBox(slider, { w: this.paneWidth, h: size });
-		}
-	},
-
-	_growPane: function(growth, pane){
-		if(growth > 0){
-			if(pane.sizeActual > pane.sizeMin){
-				if((pane.sizeActual - pane.sizeMin) > growth){
-
-					// stick all the growth in this pane
-					pane.sizeActual = pane.sizeActual - growth;
-					growth = 0;
-				}else{
-					// put as much growth in here as we can
-					growth -= pane.sizeActual - pane.sizeMin;
-					pane.sizeActual = pane.sizeMin;
-				}
-			}
-		}
-		return growth;
-	},
-
-	_checkSizes: function(){
-
-		var totalMinSize = 0;
-		var totalSize = 0;
-		var children = this.getChildren();
-
-		dojo.forEach(children, function(child){
-			totalSize += child.sizeActual;
-			totalMinSize += child.sizeMin;
-		});
-
-		// only make adjustments if we have enough space for all the minimums
-
-		if(totalMinSize <= totalSize){
-
-			var growth = 0;
-
-			dojo.forEach(children, function(child){
-				if(child.sizeActual < child.sizeMin){
-					growth += child.sizeMin - child.sizeActual;
-					child.sizeActual = child.sizeMin;
-				}
-			});
-
-			if(growth > 0){
-				var list = this.isDraggingLeft ? children.reverse() : children;
-				dojo.forEach(list, function(child){
-					growth = this._growPane(growth, child);
-				}, this);
-			}
-		}else{
-			dojo.forEach(children, function(child){
-				child.sizeActual = Math.round(totalSize * (child.sizeMin / totalMinSize));
-			});
-		}
-	},
-
-	beginSizing: function(e, i){
-		var children = this.getChildren();
-		this.paneBefore = children[i];
-		this.paneAfter = children[i+1];
-
-		this.isSizing = true;
-		this.sizingSplitter = this.sizers[i];
-
-		if(!this.cover){
-			this.cover = dojo.create('div', {
-					style: {
-						position:'absolute',
-						zIndex:5,
-						top: 0,
-						left: 0,
-						width: "100%",
-						height: "100%"
-					}
-				}, this.domNode);
-		}else{
-			this.cover.style.zIndex = 5;
-		}
-		this.sizingSplitter.style.zIndex = 6;
-
-		// TODO: REVISIT - we want MARGIN_BOX and core hasn't exposed that yet (but can't we use it anyway if we pay attention? we do elsewhere.)
-		this.originPos = dojo.position(children[0].domNode, true);
-		if(this.isHorizontal){
-			var client = e.layerX || e.offsetX || 0;
-			var screen = e.pageX;
-			this.originPos = this.originPos.x;
-		}else{
-			var client = e.layerY || e.offsetY || 0;
-			var screen = e.pageY;
-			this.originPos = this.originPos.y;
-		}
-		this.startPoint = this.lastPoint = screen;
-		this.screenToClientOffset = screen - client;
-		this.dragOffset = this.lastPoint - this.paneBefore.sizeActual - this.originPos - this.paneBefore.position;
-
-		if(!this.activeSizing){
-			this._showSizingLine();
-		}
-
-		//
-		// attach mouse events
-		//
-		this._ownconnects = [];
-		this._ownconnects.push(dojo.connect(dojo.doc.documentElement, "onmousemove", this, "changeSizing"));
-		this._ownconnects.push(dojo.connect(dojo.doc.documentElement, "onmouseup", this, "endSizing"));
-
-		dojo.stopEvent(e);
-	},
-
-	changeSizing: function(e){
-		if(!this.isSizing){ return; }
-		this.lastPoint = this.isHorizontal ? e.pageX : e.pageY;
-		this.movePoint();
-		if(this.activeSizing){
-			this._updateSize();
-		}else{
-			this._moveSizingLine();
-		}
-		dojo.stopEvent(e);
-	},
-
-	endSizing: function(e){
-		if(!this.isSizing){ return; }
-		if(this.cover){
-			this.cover.style.zIndex = -1;
-		}
-		if(!this.activeSizing){
-			this._hideSizingLine();
-		}
-
-		this._updateSize();
-
-		this.isSizing = false;
-
-		if(this.persist){
-			this._saveState(this);
-		}
-
-		dojo.forEach(this._ownconnects, dojo.disconnect);
-	},
-
-	movePoint: function(){
-
-		// make sure lastPoint is a legal point to drag to
-		var p = this.lastPoint - this.screenToClientOffset;
-
-		var a = p - this.dragOffset;
-		a = this.legaliseSplitPoint(a);
-		p = a + this.dragOffset;
-
-		this.lastPoint = p + this.screenToClientOffset;
-	},
-
-	legaliseSplitPoint: function(a){
-
-		a += this.sizingSplitter.position;
-
-		this.isDraggingLeft = !!(a > 0);
-
-		if(!this.activeSizing){
-			var min = this.paneBefore.position + this.paneBefore.sizeMin;
-			if(a < min){
-				a = min;
-			}
-
-			var max = this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin));
-			if(a > max){
-				a = max;
-			}
-		}
-
-		a -= this.sizingSplitter.position;
-
-		this._checkSizes();
-
-		return a;
-	},
-
-	_updateSize: function(){
-	//FIXME: sometimes this.lastPoint is NaN
-		var pos = this.lastPoint - this.dragOffset - this.originPos;
-
-		var start_region = this.paneBefore.position;
-		var end_region = this.paneAfter.position + this.paneAfter.sizeActual;
-
-		this.paneBefore.sizeActual = pos - start_region;
-		this.paneAfter.position	= pos + this.sizerWidth;
-		this.paneAfter.sizeActual = end_region - this.paneAfter.position;
-
-		dojo.forEach(this.getChildren(), function(child){
-			child.sizeShare = child.sizeActual;
-		});
-
-		if(this._started){
-			this.layout();
-		}
-	},
-
-	_showSizingLine: function(){
-
-		this._moveSizingLine();
-
-		dojo.marginBox(this.virtualSizer,
-			this.isHorizontal ? { w: this.sizerWidth, h: this.paneHeight } : { w: this.paneWidth, h: this.sizerWidth });
-
-		this.virtualSizer.style.display = 'block';
-	},
-
-	_hideSizingLine: function(){
-		this.virtualSizer.style.display = 'none';
-	},
-
-	_moveSizingLine: function(){
-		var pos = (this.lastPoint - this.startPoint) + this.sizingSplitter.position;
-		dojo.style(this.virtualSizer,(this.isHorizontal ? "left" : "top"),pos+"px");
-		// this.virtualSizer.style[ this.isHorizontal ? "left" : "top" ] = pos + 'px'; // FIXME: remove this line if the previous is better
-	},
-
-	_getCookieName: function(i){
-		return this.id + "_" + i;
-	},
-
-	_restoreState: function(){
-		dojo.forEach(this.getChildren(), function(child, i){
-			var cookieName = this._getCookieName(i);
-			var cookieValue = dojo.cookie(cookieName);
-			if(cookieValue){
-				var pos = parseInt(cookieValue);
-				if(typeof pos == "number"){
-					child.sizeShare = pos;
-				}
-			}
-		}, this);
-	},
-
-	_saveState: function(){
-		if(!this.persist){
-			return;
-		}
-		dojo.forEach(this.getChildren(), function(child, i){
-			dojo.cookie(this._getCookieName(i), child.sizeShare, {expires:365});
-		}, this);
-	}
-});
-
-// These arguments can be specified for the children of a SplitContainer.
-// Since any widget can be specified as a SplitContainer child, mix them
-// into the base widget class.  (This is a hack, but it's effective.)
-dojo.extend(dijit._Widget, {
-	// sizeMin: [deprecated] Integer
-	//		Deprecated.  Parameter for children of `dijit.layout.SplitContainer`.
-	//		Minimum size (width or height) of a child of a SplitContainer.
-	//		The value is relative to other children's sizeShare properties.
-	sizeMin: 10,
-
-	// sizeShare: [deprecated] Integer
-	//		Deprecated.  Parameter for children of `dijit.layout.SplitContainer`.
-	//		Size (width or height) of a child of a SplitContainer.
-	//		The value is relative to other children's sizeShare properties.
-	//		For example, if there are two children and each has sizeShare=10, then
-	//		each takes up 50% of the available space.
-	sizeShare: 10
-});
-
-}
-
-if(!dojo._hasResource["dijit.layout._TabContainerBase"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout._TabContainerBase"] = true;
-dojo.provide("dijit.layout._TabContainerBase");
-
-
-
-
-dojo.declare("dijit.layout._TabContainerBase",
-	[dijit.layout.StackContainer, dijit._Templated],
-	{
-	// summary:
-	//		Abstract base class for TabContainer.   Must define _makeController() to instantiate
-	//		and return the widget that displays the tab labels
-	// description:
-	//		A TabContainer is a container that has multiple panes, but shows only
-	//		one pane at a time.  There are a set of tabs corresponding to each pane,
-	//		where each tab has the name (aka title) of the pane, and optionally a close button.
-
-	// tabPosition: String
-	//		Defines where tabs go relative to tab content.
-	//		"top", "bottom", "left-h", "right-h"
-	tabPosition: "top",
-
-	baseClass: "dijitTabContainer",
-
-	// tabStrip: Boolean
-	//		Defines whether the tablist gets an extra class for layouting, putting a border/shading
-	//		around the set of tabs.
-	tabStrip: false,
-
-	// nested: Boolean
-	//		If true, use styling for a TabContainer nested inside another TabContainer.
-	//		For tundra etc., makes tabs look like links, and hides the outer
-	//		border since the outer TabContainer already has a border.
-	nested: false,
-
-	templateString: dojo.cache("dijit.layout", "templates/TabContainer.html", "<div class=\"dijitTabContainer\">\n\t<div class=\"dijitTabListWrapper\" dojoAttachPoint=\"tablistNode\"></div>\n\t<div dojoAttachPoint=\"tablistSpacer\" class=\"dijitTabSpacer ${baseClass}-spacer\"></div>\n\t<div class=\"dijitTabPaneWrapper ${baseClass}-container\" dojoAttachPoint=\"containerNode\"></div>\n</div>\n"),
-
-	postMixInProperties: function(){
-		// set class name according to tab position, ex: dijitTabContainerTop
-		this.baseClass += this.tabPosition.charAt(0).toUpperCase() + this.tabPosition.substr(1).replace(/-.*/, "");
-
-		this.srcNodeRef && dojo.style(this.srcNodeRef, "visibility", "hidden");
-
-		this.inherited(arguments);
-	},
-
-	postCreate: function(){
-		this.inherited(arguments);
-
-		// Create the tab list that will have a tab (a.k.a. tab button) for each tab panel
-		this.tablist = this._makeController(this.tablistNode);
-
-		if(!this.doLayout){ dojo.addClass(this.domNode, "dijitTabContainerNoLayout"); }
-
-		if(this.nested){
-			/* workaround IE's lack of support for "a > b" selectors by
-			 * tagging each node in the template.
-			 */
-			dojo.addClass(this.domNode, "dijitTabContainerNested");
-			dojo.addClass(this.tablist.containerNode, "dijitTabContainerTabListNested");
-			dojo.addClass(this.tablistSpacer, "dijitTabContainerSpacerNested");
-			dojo.addClass(this.containerNode, "dijitTabPaneWrapperNested");
-		}else{
-			dojo.addClass(this.domNode, "tabStrip-" + (this.tabStrip ? "enabled" : "disabled"));
-		}
-	},
-
-	_setupChild: function(/*dijit._Widget*/ tab){
-		// Overrides StackContainer._setupChild().
-		dojo.addClass(tab.domNode, "dijitTabPane");
-		this.inherited(arguments);
-	},
-
-	startup: function(){
-		if(this._started){ return; }
-
-		// wire up the tablist and its tabs
-		this.tablist.startup();
-
-		this.inherited(arguments);
-	},
-
-	layout: function(){
-		// Overrides StackContainer.layout().
-		// Configure the content pane to take up all the space except for where the tabs are
-
-		if(!this._contentBox || typeof(this._contentBox.l) == "undefined"){return;}
-
-		var sc = this.selectedChildWidget;
-
-		if(this.doLayout){
-			// position and size the titles and the container node
-			var titleAlign = this.tabPosition.replace(/-h/, "");
-			this.tablist.layoutAlign = titleAlign;
-			var children = [this.tablist, {
-				domNode: this.tablistSpacer,
-				layoutAlign: titleAlign
-			}, {
-				domNode: this.containerNode,
-				layoutAlign: "client"
-			}];
-			dijit.layout.layoutChildren(this.domNode, this._contentBox, children);
-
-			// Compute size to make each of my children.
-			// children[2] is the margin-box size of this.containerNode, set by layoutChildren() call above
-			this._containerContentBox = dijit.layout.marginBox2contentBox(this.containerNode, children[2]);
-
-			if(sc && sc.resize){
-				sc.resize(this._containerContentBox);
-			}
-		}else{
-			// just layout the tab controller, so it can position left/right buttons etc.
-			if(this.tablist.resize){
-				this.tablist.resize({w: dojo.contentBox(this.domNode).w});
-			}
-
-			// and call resize() on the selected pane just to tell it that it's been made visible
-			if(sc && sc.resize){
-				sc.resize();
-			}
-		}
-	},
-
-	destroy: function(){
-		if(this.tablist){
-			this.tablist.destroy();
-		}
-		this.inherited(arguments);
-	}
-});
-
-
-}
-
-if(!dojo._hasResource["dijit.layout.TabController"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.TabController"] = true;
-dojo.provide("dijit.layout.TabController");
-
-
-
-// Menu is used for an accessible close button, would be nice to have a lighter-weight solution
-
-
-
-
-
-dojo.declare("dijit.layout.TabController",
-	dijit.layout.StackController,
-{
-	// summary:
-	// 		Set of tabs (the things with titles and a close button, that you click to show a tab panel).
-	//		Used internally by `dijit.layout.TabContainer`.
-	// description:
-	//		Lets the user select the currently shown pane in a TabContainer or StackContainer.
-	//		TabController also monitors the TabContainer, and whenever a pane is
-	//		added or deleted updates itself accordingly.
-	// tags:
-	//		private
-
-	templateString: "<div wairole='tablist' dojoAttachEvent='onkeypress:onkeypress'></div>",
-
-	// tabPosition: String
-	//		Defines where tabs go relative to the content.
-	//		"top", "bottom", "left-h", "right-h"
-	tabPosition: "top",
-
-	// buttonWidget: String
-	//		The name of the tab widget to create to correspond to each page
-	buttonWidget: "dijit.layout._TabButton",
-
-	_rectifyRtlTabList: function(){
-		// summary:
-		//		For left/right TabContainer when page is RTL mode, rectify the width of all tabs to be equal, otherwise the tab widths are different in IE
-
-		if(0 >= this.tabPosition.indexOf('-h')){ return; }
-		if(!this.pane2button){ return; }
-
-		var maxWidth = 0;
-		for(var pane in this.pane2button){
-			var ow = this.pane2button[pane].innerDiv.scrollWidth;
-			maxWidth = Math.max(maxWidth, ow);
-		}
-		//unify the length of all the tabs
-		for(pane in this.pane2button){
-			this.pane2button[pane].innerDiv.style.width = maxWidth + 'px';
-		}
-	}
-});
-
-dojo.declare("dijit.layout._TabButton",
-	dijit.layout._StackButton,
-	{
-	// summary:
-	//		A tab (the thing you click to select a pane).
-	// description:
-	//		Contains the title of the pane, and optionally a close-button to destroy the pane.
-	//		This is an internal widget and should not be instantiated directly.
-	// tags:
-	//		private
-
-	// baseClass: String
-	//		The CSS class applied to the domNode.
-	baseClass: "dijitTab",
-
-	templateString: dojo.cache("dijit.layout", "templates/_TabButton.html", "<div waiRole=\"presentation\" dojoAttachPoint=\"titleNode\" dojoAttachEvent='onclick:onClick,onmouseenter:_onMouse,onmouseleave:_onMouse'>\n    <div waiRole=\"presentation\" class='dijitTabInnerDiv' dojoAttachPoint='innerDiv'>\n        <div waiRole=\"presentation\" class='dijitTabContent' dojoAttachPoint='tabContent,focusNode'>\n\t        <img src=\"${_blankGif}\" alt=\"\" dojoAttachPoint='iconNode' waiRole=\"prese [...]
-
-	// Override _FormWidget.scrollOnFocus.
-	// Don't scroll the whole tab container into view when the button is focused.
-	scrollOnFocus: false,
-
-	postMixInProperties: function(){
-		// Override blank iconClass from Button to do tab height adjustment on IE6,
-		// to make sure that tabs with and w/out close icons are same height
-		if(!this.iconClass){
-			this.iconClass = "dijitTabButtonIcon";
-		}
-	},
-
-	postCreate: function(){
-		this.inherited(arguments);
-		dojo.setSelectable(this.containerNode, false);
-
-		// If a custom icon class has not been set for the
-		// tab icon, set its width to one pixel. This ensures
-		// that the height styling of the tab is maintained,
-		// as it is based on the height of the icon.
-		// TODO: I still think we can just set dijitTabButtonIcon to 1px in CSS <Bill>
-		if(this.iconNode.className == "dijitTabButtonIcon"){
-			dojo.style(this.iconNode, "width", "1px");
-		}
-	},
-
-	startup: function(){
-		this.inherited(arguments);
-		var n = this.domNode;
-
-		// Required to give IE6 a kick, as it initially hides the
-		// tabs until they are focused on.
-		setTimeout(function(){
-			n.className = n.className;
-		}, 1);
-	},
-
-	_setCloseButtonAttr: function(disp){
-		this.closeButton = disp;
-		dojo.toggleClass(this.innerDiv, "dijitClosable", disp);
-		this.closeNode.style.display = disp ? "" : "none";
-		if(disp){
-			var _nlsResources = dojo.i18n.getLocalization("dijit", "common");
-			if(this.closeNode){
-				dojo.attr(this.closeNode,"title", _nlsResources.itemClose);
-				if (dojo.isIE<8){
-					// IE<8 needs title set directly on image.  Only set for IE since alt=""
-					// for this node and WCAG 2.0 does not allow title when alt=""
-					dojo.attr(this.closeIcon, "title", _nlsResources.itemClose);
-				}
-			}
-			// add context menu onto title button
-			var _nlsResources = dojo.i18n.getLocalization("dijit", "common");
-			this._closeMenu = new dijit.Menu({
-				id: this.id+"_Menu",
-				targetNodeIds: [this.domNode]
-			});
-
-			this._closeMenu.addChild(new dijit.MenuItem({
-				label: _nlsResources.itemClose,
-				onClick: dojo.hitch(this, "onClickCloseButton")
-			}));
-		}else{
-			if(this._closeMenu){
-				this._closeMenu.destroyRecursive();
-				delete this._closeMenu;
-			}
-		}
-	},
-
-	destroy: function(){
-		if(this._closeMenu){
-			this._closeMenu.destroyRecursive();
-			delete this._closeMenu;
-		}
-		this.inherited(arguments);
-	},
-
-	_onCloseButtonEnter: function(){
-		// summary:
-		//		Handler when mouse is moved over the close icon (the X)
-		dojo.addClass(this.closeNode, "closeButton-hover");
-	},
-
-	_onCloseButtonLeave: function(){
-		// summary:
-		//		Handler when mouse is moved off the close icon (the X)
-		dojo.removeClass(this.closeNode, "closeButton-hover");
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.layout.ScrollingTabController"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.ScrollingTabController"] = true;
-dojo.provide("dijit.layout.ScrollingTabController");
-
-
-
-
-dojo.declare("dijit.layout.ScrollingTabController",
-	dijit.layout.TabController,
-	{
-	// summary:
-	//		Set of tabs with left/right arrow keys and a menu to switch between tabs not
-	//		all fitting on a single row.
-	//		Works only for horizontal tabs (either above or below the content, not to the left
-	//		or right).
-	// tags:
-	//		private
-
-	templateString: dojo.cache("dijit.layout", "templates/ScrollingTabController.html", "<div class=\"dijitTabListContainer-${tabPosition}\" style=\"visibility:hidden\">\n\t<div dojoType=\"dijit.layout._ScrollingTabControllerButton\" buttonType=\"menuBtn\" buttonClass=\"tabStripMenuButton\"\n\t\t\ttabPosition=\"${tabPosition}\" dojoAttachPoint=\"_menuBtn\" showLabel=false>↓</div>\n\t<div dojoType=\"dijit.layout._ScrollingTabControllerButton\" buttonType=\"leftBtn\" buttonClass=\"tabStr [...]
-
-	// useMenu:[const] Boolean
-	//		True if a menu should be used to select tabs when they are too
-	//		wide to fit the TabContainer, false otherwise.
-	useMenu: true,
-
-	// useSlider: [const] Boolean
-	//		True if a slider should be used to select tabs when they are too
-	//		wide to fit the TabContainer, false otherwise.
-	useSlider: true,
-
-	// tabStripClass: String
-	//		The css class to apply to the tab strip, if it is visible.
-	tabStripClass: "",
-
-	widgetsInTemplate: true,
-
-	// _minScroll: Number
-	//		The distance in pixels from the edge of the tab strip which,
-	//		if a scroll animation is less than, forces the scroll to
-	//		go all the way to the left/right.
-	_minScroll: 5,
-
-	attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-		"class": "containerNode"
-	}),
-
-	postCreate: function(){
-		this.inherited(arguments);
-		var n = this.domNode;
-
-		this.scrollNode = this.tablistWrapper;
-		this._initButtons();
-
-		if(!this.tabStripClass){
-			this.tabStripClass = "dijitTabContainer" +
-				this.tabPosition.charAt(0).toUpperCase() +
-				this.tabPosition.substr(1).replace(/-.*/, "") +
-				"None";
-			dojo.addClass(n, "tabStrip-disabled")
-		}
-
-		dojo.addClass(this.tablistWrapper, this.tabStripClass);
-	},
-
-	onStartup: function(){
-		this.inherited(arguments);
-
-		// Do not show the TabController until the related
-		// StackController has added it's children.  This gives
-		// a less visually jumpy instantiation.
-		dojo.style(this.domNode, "visibility", "visible");
-		this._postStartup = true;
-	},
-
-	onAddChild: function(page, insertIndex){
-		this.inherited(arguments);
-		var menuItem;
-		if(this.useMenu){
-			var containerId = this.containerId;
-			menuItem = new dijit.MenuItem({
-				label: page.title,
-				onClick: dojo.hitch(this, function(){
-					var container = dijit.byId(containerId);
-					container.selectChild(page);
-				})
-			});
-			this._menuChildren[page.id] = menuItem;
-			this._menu.addChild(menuItem, insertIndex);
-		}
-
-		// update the menuItem label when the button label is updated
-		this.pane2handles[page.id].push(
-			this.connect(this.pane2button[page.id], "attr", function(name, value){
-				if(this._postStartup){
-					if(arguments.length == 2 && name == "label"){
-						if(menuItem){
-							menuItem.attr(name, value);
-						}
-	
-						// The changed label will have changed the width of the
-						// buttons, so do a resize
-						if(this._dim){
-							this.resize(this._dim);
-						}
-					}
-				}
-			})
-		);
-
-		// Increment the width of the wrapper when a tab is added
-		// This makes sure that the buttons never wrap.
-		// The value 200 is chosen as it should be bigger than most
-		// Tab button widths.
-		dojo.style(this.containerNode, "width",
-			(dojo.style(this.containerNode, "width") + 200) + "px");
-	},
-
-	onRemoveChild: function(page, insertIndex){
-		// null out _selectedTab because we are about to delete that dom node
-		var button = this.pane2button[page.id];
-		if(this._selectedTab === button.domNode){
-			this._selectedTab = null;
-		}
-
-		// delete menu entry corresponding to pane that was removed from TabContainer
-		if(this.useMenu && page && page.id && this._menuChildren[page.id]){
-			this._menu.removeChild(this._menuChildren[page.id]);
-			this._menuChildren[page.id].destroy();
-			delete this._menuChildren[page.id];
-		}
-
-		this.inherited(arguments);
-	},
-
-	_initButtons: function(){
-		// summary:
-		//		Creates the buttons used to scroll to view tabs that
-		//		may not be visible if the TabContainer is too narrow.
-		this._menuChildren = {};
-
-		// Make a list of the buttons to display when the tab labels become
-		// wider than the TabContainer, and hide the other buttons.
-		// Also gets the total width of the displayed buttons.
-		this._btnWidth = 0;
-		this._buttons = dojo.query("> .tabStripButton", this.domNode).filter(function(btn){
-			if((this.useMenu && btn == this._menuBtn.domNode) ||
-				(this.useSlider && (btn == this._rightBtn.domNode || btn == this._leftBtn.domNode))){
-				this._btnWidth += dojo.marginBox(btn).w;
-				return true;
-			}else{
-				dojo.style(btn, "display", "none");
-				return false;
-			}
-		}, this);
-
-		if(this.useMenu){
-			// Create the menu that is used to select tabs.
-			this._menu = new dijit.Menu({
-				id: this.id + "_menu",
-				targetNodeIds: [this._menuBtn.domNode],
-				leftClickToOpen: true,
-				refocus: false	// selecting a menu item sets focus to a TabButton
-			});
-			this._supportingWidgets.push(this._menu);
-		}
-	},
-
-	_getTabsWidth: function(){
-		var children = this.getChildren();
-		if(children.length){
-			var leftTab = children[this.isLeftToRight() ? 0 : children.length - 1].domNode,
-				rightTab = children[this.isLeftToRight() ? children.length - 1 : 0].domNode;
-			return rightTab.offsetLeft + dojo.style(rightTab, "width") - leftTab.offsetLeft;
-		}else{
-			return 0;
-		}
-	},
-
-	_enableBtn: function(width){
-		// summary:
-		//		Determines if the tabs are wider than the width of the TabContainer, and
-		//		thus that we need to display left/right/menu navigation buttons.
-		var tabsWidth = this._getTabsWidth();
-		width = width || dojo.style(this.scrollNode, "width");
-		return tabsWidth > 0 && width < tabsWidth;
-	},
-
-	resize: function(dim){
-		// summary:
-		//		Hides or displays the buttons used to scroll the tab list and launch the menu
-		//		that selects tabs.
-
-		if(this.domNode.offsetWidth == 0){
-			return;
-		}
-		
-		// Save the dimensions to be used when a child is renamed.
-		this._dim = dim;
-
-		// Set my height to be my natural height (tall enough for one row of tab labels),
-		// and my content-box width based on margin-box width specified in dim parameter.
-		// But first reset scrollNode.height in case it was set by layoutChildren() call
-		// in a previous run of this method.
-		this.scrollNode.style.height = "auto";
-		this._contentBox = dijit.layout.marginBox2contentBox(this.domNode, {h: 0, w: dim.w});
-		this._contentBox.h = this.scrollNode.offsetHeight;
-		dojo.contentBox(this.domNode, this._contentBox);
-
-		// Show/hide the left/right/menu navigation buttons depending on whether or not they
-		// are needed.
-		var enable = this._enableBtn(this._contentBox.w);
-		this._buttons.style("display", enable ? "" : "none");
-
-		// Position and size the navigation buttons and the tablist
-		this._leftBtn.layoutAlign = "left";
-		this._rightBtn.layoutAlign = "right";
-		this._menuBtn.layoutAlign = this.isLeftToRight() ? "right" : "left";
-		dijit.layout.layoutChildren(this.domNode, this._contentBox,
-			[this._menuBtn, this._leftBtn, this._rightBtn, {domNode: this.scrollNode, layoutAlign: "client"}]);
-
-		// set proper scroll so that selected tab is visible
-		if(this._selectedTab){
-			var w = this.scrollNode,
-				sl = this._convertToScrollLeft(this._getScrollForSelectedTab());
-			w.scrollLeft = sl;
-		}
-
-		// Enable/disabled left right buttons depending on whether or not user can scroll to left or right
-		this._setButtonClass(this._getScroll());
-	},
-
-	_getScroll: function(){
-		// summary:
-		//		Returns the current scroll of the tabs where 0 means
-		//		"scrolled all the way to the left" and some positive number, based on #
-		//		of pixels of possible scroll (ex: 1000) means "scrolled all the way to the right"
-		var sl = (this.isLeftToRight() || dojo.isIE < 8 || dojo.isQuirks || dojo.isWebKit) ? this.scrollNode.scrollLeft :
-				dojo.style(this.containerNode, "width") - dojo.style(this.scrollNode, "width")
-					 + (dojo.isIE == 8 ? -1 : 1) * this.scrollNode.scrollLeft;
-		return sl;
-	},
-
-	_convertToScrollLeft: function(val){
-		// summary:
-		//		Given a scroll value where 0 means "scrolled all the way to the left"
-		//		and some positive number, based on # of pixels of possible scroll (ex: 1000)
-		//		means "scrolled all the way to the right", return value to set this.scrollNode.scrollLeft
-		//		to achieve that scroll.
-		//
-		//		This method is to adjust for RTL funniness in various browsers and versions.
-		if(this.isLeftToRight() || dojo.isIE < 8 || dojo.isQuirks || dojo.isWebKit){
-			return val;
-		}else{
-			var maxScroll = dojo.style(this.containerNode, "width") - dojo.style(this.scrollNode, "width");
-			return (dojo.isIE == 8 ? -1 : 1) * (val - maxScroll);
-		}
-	},
-
-	onSelectChild: function(/*dijit._Widget*/ page){
-		// summary:
-		//		Smoothly scrolls to a tab when it is selected.
-
-		var tab = this.pane2button[page.id];
-		if(!tab || !page){return;}
-
-		var node = tab.domNode;
-		if(node != this._selectedTab){
-			this._selectedTab = node;
-
-			var sl = this._getScroll();
-
-			if(sl > node.offsetLeft ||
-					sl + dojo.style(this.scrollNode, "width") <
-					node.offsetLeft + dojo.style(node, "width")){
-				this.createSmoothScroll().play();
-			}
-		}
-
-		this.inherited(arguments);
-	},
-
-	_getScrollBounds: function(){
-		// summary:
-		//		Returns the minimum and maximum scroll setting to show the leftmost and rightmost
-		//		tabs (respectively)
-		var children = this.getChildren(),
-			scrollNodeWidth = dojo.style(this.scrollNode, "width"),		// about 500px
-			containerWidth = dojo.style(this.containerNode, "width"),	// 50,000px
-			maxPossibleScroll = containerWidth - scrollNodeWidth,	// scrolling until right edge of containerNode visible
-			tabsWidth = this._getTabsWidth();
-
-		if(children.length && tabsWidth > scrollNodeWidth){
-			// Scrolling should happen
-			return {
-				min: this.isLeftToRight() ? 0 : children[children.length-1].domNode.offsetLeft,
-				max: this.isLeftToRight() ?
-					(children[children.length-1].domNode.offsetLeft + dojo.style(children[children.length-1].domNode, "width")) - scrollNodeWidth :
-					maxPossibleScroll
-			};
-		}else{
-			// No scrolling needed, all tabs visible, we stay either scrolled to far left or far right (depending on dir)
-			var onlyScrollPosition = this.isLeftToRight() ? 0 : maxPossibleScroll;
-			return {
-				min: onlyScrollPosition,
-				max: onlyScrollPosition
-			};
-		}
-	},
-
-	_getScrollForSelectedTab: function(){
-		// summary:
-		//		Returns the scroll value setting so that the selected tab
-		//		will appear in the center
-		var w = this.scrollNode,
-			n = this._selectedTab,
-			scrollNodeWidth = dojo.style(this.scrollNode, "width"),
-			scrollBounds = this._getScrollBounds();
-
-		// TODO: scroll minimal amount (to either right or left) so that
-		// selected tab is fully visible, and just return if it's already visible?
-		var pos = (n.offsetLeft + dojo.style(n, "width")/2) - scrollNodeWidth/2;
-		pos = Math.min(Math.max(pos, scrollBounds.min), scrollBounds.max);
-
-		// TODO:
-		// If scrolling close to the left side or right side, scroll
-		// all the way to the left or right.  See this._minScroll.
-		// (But need to make sure that doesn't scroll the tab out of view...)
-		return pos;
-	},
-
-	createSmoothScroll : function(x){
-		// summary:
-		//		Creates a dojo._Animation object that smoothly scrolls the tab list
-		//		either to a fixed horizontal pixel value, or to the selected tab.
-		// description:
-		//		If an number argument is passed to the function, that horizontal
-		//		pixel position is scrolled to.  Otherwise the currently selected
-		//		tab is scrolled to.
-		// x: Integer?
-		//		An optional pixel value to scroll to, indicating distance from left.
-
-		// Calculate position to scroll to
-		if(arguments.length > 0){
-			// position specified by caller, just make sure it's within bounds
-			var scrollBounds = this._getScrollBounds();
-			x = Math.min(Math.max(x, scrollBounds.min), scrollBounds.max);
-		}else{
-			// scroll to center the current tab
-			x = this._getScrollForSelectedTab();
-		}
-
-		if(this._anim && this._anim.status() == "playing"){
-			this._anim.stop();
-		}
-
-		var self = this,
-			w = this.scrollNode,
-			anim = new dojo._Animation({
-				beforeBegin: function(){
-					if(this.curve){ delete this.curve; }
-					var oldS = w.scrollLeft,
-						newS = self._convertToScrollLeft(x);
-					anim.curve = new dojo._Line(oldS, newS);
-				},
-				onAnimate: function(val){
-					w.scrollLeft = val;
-				}
-			});
-		this._anim = anim;
-
-		// Disable/enable left/right buttons according to new scroll position
-		this._setButtonClass(x);
-
-		return anim; // dojo._Animation
-	},
-
-	_getBtnNode: function(e){
-		// summary:
-		//		Gets a button DOM node from a mouse click event.
-		// e:
-		//		The mouse click event.
-		var n = e.target;
-		while(n && !dojo.hasClass(n, "tabStripButton")){
-			n = n.parentNode;
-		}
-		return n;
-	},
-
-	doSlideRight: function(e){
-		// summary:
-		//		Scrolls the menu to the right.
-		// e:
-		//		The mouse click event.
-		this.doSlide(1, this._getBtnNode(e));
-	},
-
-	doSlideLeft: function(e){
-		// summary:
-		//		Scrolls the menu to the left.
-		// e:
-		//		The mouse click event.
-		this.doSlide(-1,this._getBtnNode(e));
-	},
-
-	doSlide: function(direction, node){
-		// summary:
-		//		Scrolls the tab list to the left or right by 75% of the widget width.
-		// direction:
-		//		If the direction is 1, the widget scrolls to the right, if it is
-		//		-1, it scrolls to the left.
-
-		if(node && dojo.hasClass(node, "dijitTabBtnDisabled")){return;}
-
-		var sWidth = dojo.style(this.scrollNode, "width");
-		var d = (sWidth * 0.75) * direction;
-
-		var to = this._getScroll() + d;
-
-		this._setButtonClass(to);
-
-		this.createSmoothScroll(to).play();
-	},
-
-	_setButtonClass: function(scroll){
-		// summary:
-		//		Adds or removes a class to the left and right scroll buttons
-		//		to indicate whether each one is enabled/disabled.
-		// description:
-		//		If the tabs are scrolled all the way to the left, the class
-		//		'dijitTabBtnDisabled' is added to the left button.
-		//		If the tabs are scrolled all the way to the right, the class
-		//		'dijitTabBtnDisabled' is added to the right button.
-		// scroll: Integer
-		//		amount of horizontal scroll
-
-		var cls = "dijitTabBtnDisabled",
-			scrollBounds = this._getScrollBounds();
-		dojo.toggleClass(this._leftBtn.domNode, cls, scroll <= scrollBounds.min);
-		dojo.toggleClass(this._rightBtn.domNode, cls, scroll >= scrollBounds.max);
-	}
-});
-
-dojo.declare("dijit.layout._ScrollingTabControllerButton",
-	dijit.form.Button,
-	{
-		baseClass: "dijitTab",
-
-		buttonType: "",
-
-		buttonClass: "",
-
-		tabPosition: "top",
-
-		templateString: dojo.cache("dijit.layout", "templates/_ScrollingTabControllerButton.html", "<div id=\"${id}-${buttonType}\" class=\"tabStripButton dijitTab ${buttonClass} tabStripButton-${tabPosition}\"\n\t\tdojoAttachEvent=\"onclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\">\n\t<div role=\"presentation\" wairole=\"presentation\" class=\"dijitTabInnerDiv\" dojoattachpoint=\"innerDiv,focusNode\">\n\t\t<div role=\"presentation\" wairole=\"presentat [...]
-
-		// Override inherited tabIndex: 0 from dijit.form.Button, because user shouldn't be
-		// able to tab to the left/right/menu buttons
-		tabIndex: ""
-	}
-);
-
-}
-
-if(!dojo._hasResource["dijit.layout.TabContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.TabContainer"] = true;
-dojo.provide("dijit.layout.TabContainer");
-
-
-
-
-
-dojo.declare("dijit.layout.TabContainer",
-	dijit.layout._TabContainerBase,
-	{
-		// summary:
-		//		A Container with tabs to select each child (only one of which is displayed at a time).
-		// description:
-		//		A TabContainer is a container that has multiple panes, but shows only
-		//		one pane at a time.  There are a set of tabs corresponding to each pane,
-		//		where each tab has the name (aka title) of the pane, and optionally a close button.
-
-		// useMenu: [const] Boolean
-		//		True if a menu should be used to select tabs when they are too
-		//		wide to fit the TabContainer, false otherwise.
-		useMenu: true,
-
-		// useSlider: [const] Boolean
-		//		True if a slider should be used to select tabs when they are too
-		//		wide to fit the TabContainer, false otherwise.
-		useSlider: true,
-
-		// controllerWidget: String
-		//		An optional parameter to override the widget used to display the tab labels
-		controllerWidget: "",
-
-		_makeController: function(/*DomNode*/ srcNode){
-			// summary:
-			//		Instantiate tablist controller widget and return reference to it.
-			//		Callback from _TabContainerBase.postCreate().
-			// tags:
-			//		protected extension
-
-			var cls = this.baseClass + "-tabs" + (this.doLayout ? "" : " dijitTabNoLayout"),
-				TabController = dojo.getObject(this.controllerWidget);
-
-			return new TabController({
-				id: this.id + "_tablist",
-				tabPosition: this.tabPosition,
-				doLayout: this.doLayout,
-				containerId: this.id,
-				"class": cls,
-				nested: this.nested,
-				useMenu: this.useMenu,
-				useSlider: this.useSlider,
-				tabStripClass: this.tabStrip ? this.baseClass + (this.tabStrip ? "":"No") + "Strip": null
-			}, srcNode);
-		},
-
-		postMixInProperties: function(){
-			this.inherited(arguments);
-
-			// Scrolling controller only works for horizontal non-nested tabs
-			if(!this.controllerWidget){
-				this.controllerWidget = (this.tabPosition == "top" || this.tabPosition == "bottom") && !this.nested ?
-							"dijit.layout.ScrollingTabController" : "dijit.layout.TabController";
-			}
-		}
-});
-
-
-}
-
-if(!dojo._hasResource["dijit.dijit-all"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.dijit-all"] = true;
-console.warn("dijit-all may include much more code than your application actually requires. We strongly recommend that you investigate a custom build or the web build tool");
-dojo.provide("dijit.dijit-all");
-
-/*=====
-dijit["dijit-all"] = {
-	// summary:
-	//		A rollup that includes every dijit. You probably don't need this.
-};
-=====*/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Form widgets
-
-
-// Button widgets
-
-
-
-
-
-
-
-// Textbox widgets
-
-
-
-
-
-
-
-// Select widgets
-
-
-
-
-// Slider widgets
-
-
-
-
-
-
-
-// Textarea widgets
-
-
-
-// Layout widgets
-
-
-
- //deprecated
-
- //deprecated
-
-
-
-}
-
-
-dojo.i18n._preloadLocalizations("dijit.nls.dijit-all", ["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","nb","nl","nl-nl","pl","pt","pt-br","pt-pt","ru","sk","sl","sv","th","tr","xx","zh","zh-cn","zh-tw"]);
diff --git a/dijit/dijit.js b/dijit/dijit.js
index a4b0313..056141f 100644
--- a/dijit/dijit.js
+++ b/dijit/dijit.js
@@ -1,16 +1,26 @@
-/*
-	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
-*/
+dojo.provide("dijit.dijit");
 
-/*
-	This is a compiled version of Dojo, built for deployment and not for
-	development. To get an editable version, please visit:
+/*=====
+dijit.dijit = {
+	// summary:
+	//		A roll-up for common dijit methods
+	// description:
+	//	A rollup file for the build system including the core and common
+	//	dijit files.
+	//
+	// example:
+	// | <script type="text/javascript" src="js/dojo/dijit/dijit.js"></script>
+	//
+};
+=====*/
 
-		http://dojotoolkit.org
+// All the stuff in _base (these are the function that are guaranteed available without an explicit dojo.require)
+dojo.require("dijit._base");
 
-	for documentation and information on getting the source.
-*/
-
-if(!dojo._hasResource["dijit._base.manager"]){dojo._hasResource["dijit._base.manager"]=true;dojo.provide("dijit._base.manager");dojo.declare("dijit.WidgetSet",null,{constructor:function(){this._hash={};this.length=0;},add:function(_1){if(this._hash[_1.id]){throw new Error("Tried to register widget with id=="+_1.id+" but that id is already registered");}this._hash[_1.id]=_1;this.length++;},remove:function(id){if(this._hash[id]){delete this._hash[id];this.length--;}},forEach:function(_2,_3 [...]
+// And some other stuff that we tend to pull in all the time anyway
+dojo.require("dojo.parser");
+dojo.require("dijit._Widget");
+dojo.require("dijit._Templated");
+dojo.require("dijit._Container");
+dojo.require("dijit.layout._LayoutWidget");
+dojo.require("dijit.form._FormWidget");
diff --git a/dijit/dijit.js.uncompressed.js b/dijit/dijit.js.uncompressed.js
deleted file mode 100644
index 17711f7..0000000
--- a/dijit/dijit.js.uncompressed.js
+++ /dev/null
@@ -1,5596 +0,0 @@
-/*
-	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["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 = {};
-		this.length = 0;
-	},
-
-	add: function(/*dijit._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;
-		this.length++;
-	},
-
-	remove: function(/*String*/ id){
-		// summary:
-		//		Remove a widget from this WidgetSet. Does not destroy the widget; simply
-		//		removes the reference.
-		if(this._hash[id]){
-			delete this._hash[id];
-			this.length--;
-		}
-	},
-
-	forEach: function(/*Function*/ func, /* Object? */thisObj){
-		// summary:
-		//		Call specified function for each widget in this set.
-		//
-		// func:
-		//		A callback function to run for each item. Is passed the widget, the index
-		//		in the iteration, and the full hash, similar to `dojo.forEach`.
-		//
-		// thisObj:
-		//		An optional scope parameter
-		//
-		// example:
-		//		Using the default `dijit.registry` instance:
-		//		|	dijit.registry.forEach(function(widget){
-		//		|		console.log(widget.declaredClass);
-		//		|	});
-		//
-		// returns:
-		//		Returns self, in order to allow for further chaining.
-
-		thisObj = thisObj || dojo.global;
-		var i = 0, id;
-		for(id in this._hash){
-			func.call(thisObj, this._hash[id], i++, this._hash);
-		}
-		return this;	// dijit.WidgetSet
-	},
-
-	filter: function(/*Function*/ filter, /* Object? */thisObj){
-		// 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. Is passed the widget
-		//		reference and the pseudo-index in the object.
-		//
-		// thisObj: Object?
-		//		Option scope to use for the filter function.
-		//
-		// example:
-		//		Arbitrary: select the odd widgets in this list
-		//		|	dijit.registry.filter(function(w, i){
-		//		|		return i % 2 == 0;
-		//		|	}).forEach(function(w){ /* odd ones */ });
-
-		thisObj = thisObj || dojo.global;
-		var res = new dijit.WidgetSet(), i = 0, id;
-		for(id in this._hash){
-			var w = this._hash[id];
-			if(filter.call(thisObj, w, i++, this._hash)){
-				res.add(w);
-			}
-		}
-		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`
-		//
-		// cls: String
-		//		The Class to scan for. Full dot-notated string.
-		//
-		// example:
-		//		Find all `dijit.TitlePane`s in a page:
-		//		|	dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); });
-
-		var res = new dijit.WidgetSet(), id, widget;
-		for(id in this._hash){
-			widget = this._hash[id];
-			if(widget.declaredClass == cls){
-				res.add(widget);
-			}
-		 }
-		 return res; // dijit.WidgetSet
-},
-
-	toArray: function(){
-		// summary:
-		//		Convert this WidgetSet into a true Array
-		//
-		// example:
-		//		Work with the widget .domNodes in a real Array
-		//		|	dojo.map(dijit.registry.toArray(), function(w){ return w.domNode; });
-
-		var ar = [];
-		for(var id in this._hash){
-			ar.push(this._hash[id]);
-		}
-		return ar;	// dijit._Widget[]
-},
-
-	map: function(/* Function */func, /* Object? */thisObj){
-		// summary:
-		//		Create a new Array from this WidgetSet, following the same rules as `dojo.map`
-		// example:
-		//		|	var nodes = dijit.registry.map(function(w){ return w.domNode; });
-		//
-		// returns:
-		//		A new array of the returned values.
-		return dojo.map(this.toArray(), func, thisObj); // Array
-	},
-
-	every: function(func, thisObj){
-		// summary:
-		// 		A synthetic clone of `dojo.every` acting explictly on this WidgetSet
-		//
-		// func: Function
-		//		A callback function run for every widget in this list. Exits loop
-		//		when the first false return is encountered.
-		//
-		// thisObj: Object?
-		//		Optional scope parameter to use for the callback
-
-		thisObj = thisObj || dojo.global;
-		var x = 0, i;
-		for(i in this._hash){
-			if(!func.call(thisObj, this._hash[i], x++, this._hash)){
-				return false; // Boolean
-			}
-		}
-		return true; // Boolean
-	},
-
-	some: function(func, thisObj){
-		// summary:
-		// 		A synthetic clone of `dojo.some` acting explictly on this WidgetSet
-		//
-		// func: Function
-		//		A callback function run for every widget in this list. Exits loop
-		//		when the first true return is encountered.
-		//
-		// thisObj: Object?
-		//		Optional scope parameter to use for the callback
-
-		thisObj = thisObj || dojo.global;
-		var x = 0, i;
-		for(i in this._hash){
-			if(func.call(thisObj, this._hash[i], x++, this._hash)){
-				return true; // Boolean
-			}
-		}
-		return false; // Boolean
-	}
-
-});
-
-/*=====
-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 dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
-};
-
-dijit.findWidgets = function(/*DomNode*/ root){
-	// summary:
-	//		Search subtree under root returning widgets found.
-	//		Doesn't search for nested widgets (ie, widgets inside other widgets).
-
-	var outAry = [];
-
-	function getChildrenHelper(root){
-		for(var node = root.firstChild; node; node = node.nextSibling){
-			if(node.nodeType == 1){
-				var widgetId = node.getAttribute("widgetId");
-				if(widgetId){
-					var widget = dijit.byId(widgetId);
-					outAry.push(widget);
-				}else{
-					getChildrenHelper(node);
-				}
-			}
-		}
-	}
-
-	getChildrenHelper(root);
-	return outAry;
-};
-
-dijit._destroyAll = function(){
-	// summary:
-	//		Code to destroy all widgets and do other cleanup on page unload
-
-	// Clean up focus manager lingering references to widgets and nodes
-	dijit._curFocus = null;
-	dijit._prevFocus = null;
-	dijit._activeStack = [];
-
-	// Destroy all the widgets, top down
-	dojo.forEach(dijit.findWidgets(dojo.body()), function(widget){
-		// Avoid double destroy of widgets like Menu that are attached to <body>
-		// even though they are logically children of other widgets.
-		if(!widget._destroyed){
-			if(widget.destroyRecursive){
-				widget.destroyRecursive();
-			}else if(widget.destroy){
-				widget.destroy();
-			}
-		}
-	});
-};
-
-if(dojo.isIE){
-	// Only run _destroyAll() 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(){
-		dijit._destroyAll();
-	});
-}
-
-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 typeof id == "string" ? dijit.registry._hash[id] : id; // dijit._Widget
-};
-
-dijit.byNode = function(/* DOMNode */ node){
-	// summary:
-	//		Returns the widget corresponding to the given DOMNode
-	return dijit.registry.byId(node.getAttribute("widgetId")); // dijit._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){
-		var id = node.getAttribute && node.getAttribute("widgetId");
-		if(id){
-			return dijit.byId(id);
-		}
-		node = node.parentNode;
-	}
-	return null;
-};
-
-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
-
-	// TODO: convert (and rename method) to return effectivite tabIndex; will save time in _getTabNavigable()
-	if(dojo.attr(elem, "disabled")){
-		return false;
-	}else if(dojo.hasAttr(elem, "tabIndex")){
-		// Explicit tab index setting
-		return dojo.attr(elem, "tabIndex") >= 0; // boolean
-	}else{
-		// No explicit tabIndex setting, need to investigate node type
-		switch(elem.nodeName.toLowerCase()){
-			case "a":
-				// An <a> w/out a tabindex is only navigable if it has an href
-				return dojo.hasAttr(elem, "href");
-			case "area":
-			case "button":
-			case "input":
-			case "object":
-			case "select":
-			case "textarea":
-				// These are navigable by default
-				return true;
-			case "iframe":
-				// If it's an editor <iframe> then it's tab navigable.
-				if(dojo.isMoz){
-					return elem.contentDocument.designMode == "on";
-				}else if(dojo.isWebKit){
-					var doc = elem.contentDocument,
-						body = doc && doc.body;
-					return body && body.contentEditable == 'true';
-				}else{
-					// contentWindow.document isn't accessible within IE7/8
-					// if the iframe.src points to a foreign url and this
-					// page contains an element, that could get focus
-					try{
-						doc = elem.contentWindow.document;
-						body = doc && doc.body;
-						return body && body.firstChild && body.firstChild.contentEditable == 'true';
-					}catch(e){
-						return false;
-					}
-				}
-			default:
-				return elem.contentEditable == 'true';
-		}
-	}
-};
-
-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["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");
-
-	// for dijit.isTabNavigable()
-
-// summary:
-//		These functions are used to query or set the focus and selection.
-//
-//		Also, they trace when widgets become activated/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
-		return dijit.getBookmark().isCollapsed;
-	},
-
-	getBookmark: function(){
-		// summary:
-		//		Retrieves a bookmark that can be used with moveToBookmark to return to the same range
-		var bm, rg, tg, sel = dojo.doc.selection, cf = dijit._curFocus;
-
-		if(dojo.global.getSelection){
-			//W3C Range API for selections.
-			sel = dojo.global.getSelection();
-			if(sel){
-				if(sel.isCollapsed){
-					tg = cf? cf.tagName : "";
-					if(tg){
-						//Create a fake rangelike item to restore selections.
-						tg = tg.toLowerCase();
-						if(tg == "textarea" ||
-								(tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
-							sel = {
-								start: cf.selectionStart,
-								end: cf.selectionEnd,
-								node: cf,
-								pRange: true
-							};
-							return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
-						}
-					}
-					bm = {isCollapsed:true};
-				}else{
-					rg = sel.getRangeAt(0);
-					bm = {isCollapsed: false, mark: rg.cloneRange()};
-				}
-			}
-		}else if(sel){
-			// If the current focus was a input of some sort and no selection, don't bother saving
-			// a native bookmark.  This is because it causes issues with dialog/page selection restore.
-			// So, we need to create psuedo bookmarks to work with.
-			tg = cf ? cf.tagName : "";
-			tg = tg.toLowerCase();
-			if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
-				if(sel.type && sel.type.toLowerCase() == "none"){
-					return {
-						isCollapsed: true,
-						mark: null
-					}
-				}else{
-					rg = sel.createRange();
-					return {
-						isCollapsed: rg.text && rg.text.length?false:true,
-						mark: {
-							range: rg,
-							pRange: true
-						}
-					};
-				}
-			}
-			bm = {};
-
-			//'IE' way for selections.
-			try{
-				// createRange() throws exception when dojo in iframe
-				//and nothing selected, see #9632
-				rg = sel.createRange();
-				bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
-			}catch(e){
-				bm.isCollapsed = true;
-				return bm;
-			}
-			if(sel.type.toUpperCase() == 'CONTROL'){
-				if(rg.length){
-					bm.mark=[];
-					var i=0,len=rg.length;
-					while(i<len){
-						bm.mark.push(rg.item(i++));
-					}
-				}else{
-					bm.isCollapsed = true;
-					bm.mark = null;
-				}
-			}else{
-				bm.mark = rg.getBookmark();
-			}
-		}else{
-			console.warn("No idea how to store the current selection for this browser!");
-		}
-		return bm; // Object
-	},
-
-	moveToBookmark: function(/*Object*/bookmark){
-		// summary:
-		//		Moves current selection to a bookmark
-		// bookmark:
-		//		This should be a returned object from dijit.getBookmark()
-
-		var _doc = dojo.doc,
-			mark = bookmark.mark;
-		if(mark){
-			if(dojo.global.getSelection){
-				//W3C Rangi API (FF, WebKit, Opera, etc)
-				var sel = dojo.global.getSelection();
-				if(sel && sel.removeAllRanges){
-					if(mark.pRange){
-						var r = mark;
-						var n = r.node;
-						n.selectionStart = r.start;
-						n.selectionEnd = r.end;
-					}else{
-						sel.removeAllRanges();
-						sel.addRange(mark);
-					}
-				}else{
-					console.warn("No idea how to restore selection for this browser!");
-				}
-			}else if(_doc.selection && mark){
-				//'IE' way.
-				var rg;
-				if(mark.pRange){
-					rg = mark.range;
-				}else if(dojo.isArray(mark)){
-					rg = _doc.body.createControlRange();
-					//rg.addElement does not have call/apply method, so can not call it directly
-					//rg is not available in "range.addElement(item)", so can't use that either
-					dojo.forEach(mark, function(n){
-						rg.addElement(n);
-					});
-				}else{
-					rg = _doc.body.createTextRange();
-					rg.moveToBookmark(mark);
-				}
-				rg.select();
-			}
-		}
-	},
-
-	getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){
-		// summary:
-		//		Called as getFocus(), this returns an Object showing the current focus
-		//		and selected text.
-		//
-		//		Called as getFocus(widget), where widget is a (widget representing) a button
-		//		that was just pressed, it returns where focus was before that button
-		//		was pressed.   (Pressing the button may have either shifted focus to the button,
-		//		or removed focus altogether.)   In this case the selected text is not returned,
-		//		since it can't be accurately determined.
-		//
-		// menu: dijit._Widget or {domNode: DomNode} structure
-		//		The button that was just pressed.  If focus has disappeared or moved
-		//		to this button, returns the previous focus.  In this case the bookmark
-		//		information is already lost, and null is returned.
-		//
-		// openedForWindow:
-		//		iframe in which menu was opened
-		//
-		// returns:
-		//		A handle to restore focus/selection, to be passed to `dijit.focus`
-		var node = !dijit._curFocus || (menu && dojo.isDescendant(dijit._curFocus, menu.domNode)) ? dijit._prevFocus : dijit._curFocus;
-		return {
-			node: node,
-			bookmark: (node == dijit._curFocus) && dojo.withGlobal(openedForWindow || dojo.global, dijit.getBookmark),
-			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,
-			collapsed = bookmark ? bookmark.isCollapsed : false;
-
-		// 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) or if previous selection was collapsed
-		// as it may cause focus shift (Esp in IE).
-		if(bookmark && dojo.withGlobal(openedForWindow || dojo.global, dijit.isCollapsed) && !collapsed){
-			if(openedForWindow){
-				openedForWindow.focus();
-			}
-			try{
-				dojo.withGlobal(openedForWindow || dojo.global, dijit.moveToBookmark, null, [bookmark]);
-			}catch(e2){
-				/*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
-			}
-		}
-	},
-
-	// _activeStack: dijit._Widget[]
-	//		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.
-		// returns:
-		//		Handle to pass to unregisterIframe()
-		return dijit.registerWin(iframe.contentWindow, iframe);
-	},
-
-	unregisterIframe: function(/*Object*/ handle){
-		// summary:
-		//		Unregisters listeners on the specified iframe created by registerIframe.
-		//		After calling be sure to delete or null out the handle itself.
-		// handle:
-		//		Handle returned by registerIframe()
-
-		dijit.unregisterWin(handle);
-	},
-
-	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.
-		// returns:
-		//		Handle to pass to unregisterWin()
-
-		// TODO: make this function private in 2.0; Editor/users should call registerIframe(),
-
-		var mousedownListener = function(evt){
-			dijit._justMouseDowned = true;
-			setTimeout(function(){ dijit._justMouseDowned = false; }, 0);
-			dijit._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse");
-		};
-		//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.
-		// Connect to <html> (rather than document) on IE to avoid memory leaks, but document on other browsers because
-		// (at least for FF) the focus event doesn't fire on <html> or <body>.
-		var doc = dojo.isIE ? targetWindow.document.documentElement : targetWindow.document;
-		if(doc){
-			if(dojo.isIE){
-				doc.attachEvent('onmousedown', mousedownListener);
-				var activateListener = function(evt){
-					// IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
-					// Should consider those more like a mouse-click than a focus....
-					if(evt.srcElement.tagName.toLowerCase() != "#document" &&
-						dijit.isTabNavigable(evt.srcElement)){
-						dijit._onFocusNode(effectiveNode || evt.srcElement);
-					}else{
-						dijit._onTouchNode(effectiveNode || evt.srcElement);
-					}
-				};
-				doc.attachEvent('onactivate', activateListener);
-				var deactivateListener =  function(evt){
-					dijit._onBlurNode(effectiveNode || evt.srcElement);
-				};
-				doc.attachEvent('ondeactivate', deactivateListener);
-
-				return function(){
-					doc.detachEvent('onmousedown', mousedownListener);
-					doc.detachEvent('onactivate', activateListener);
-					doc.detachEvent('ondeactivate', deactivateListener);
-					doc = null;	// prevent memory leak (apparent circular reference via closure)
-				};
-			}else{
-				doc.addEventListener('mousedown', mousedownListener, true);
-				var focusListener = function(evt){
-					dijit._onFocusNode(effectiveNode || evt.target);
-				};
-				doc.addEventListener('focus', focusListener, true);
-				var blurListener = function(evt){
-					dijit._onBlurNode(effectiveNode || evt.target);
-				};
-				doc.addEventListener('blur', blurListener, true);
-
-				return function(){
-					doc.removeEventListener('mousedown', mousedownListener, true);
-					doc.removeEventListener('focus', focusListener, true);
-					doc.removeEventListener('blur', blurListener, true);
-					doc = null;	// prevent memory leak (apparent circular reference via closure)
-				};
-			}
-		}
-	},
-
-	unregisterWin: function(/*Handle*/ handle){
-		// summary:
-		//		Unregisters listeners on the specified window (either the main
-		//		window or an iframe's window) according to handle returned from registerWin().
-		//		After calling be sure to delete or null out the handle itself.
-
-		// Currently our handle is actually a function
-		handle && handle();
-	},
-
-	_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, /*String*/ by){
-		// summary:
-		//		Callback when node is focused or mouse-downed
-		// node:
-		//		The node that was touched.
-		// by:
-		//		"mouse" if the focus/touch was caused by a mouse down event
-
-		// 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){
-				var popupParent = dojo.attr(node, "dijitPopupParent");
-				if(popupParent){
-					node=dijit.byId(popupParent).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, by);
-	},
-
-	_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(/*String[]*/ newStack, /*String*/ by){
-		// summary:
-		//		The stack of active widgets has changed.  Send out appropriate events and records new stack.
-		// newStack:
-		//		array of widget id's, starting from the top (outermost) widget
-		// by:
-		//		"mouse" if the focus/touch was caused by a mouse down event
-
-		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;
-			}
-		}
-
-		var widget;
-		// for all elements that have gone out of focus, send blur event
-		for(var i=oldStack.length-1; i>=nCommon; i--){
-			widget = dijit.byId(oldStack[i]);
-			if(widget){
-				widget._focused = false;
-				widget._hasBeenBlurred = true;
-				if(widget._onBlur){
-					widget._onBlur(by);
-				}
-				if(widget._setStateClass){
-					widget._setStateClass();
-				}
-				dojo.publish("widgetBlur", [widget, by]);
-			}
-		}
-
-		// 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(by);
-				}
-				if(widget._setStateClass){
-					widget._setStateClass();
-				}
-				dojo.publish("widgetFocus", [widget, by]);
-			}
-		}
-	}
-});
-
-// register top window and all the iframes it contains
-dojo.addOnLoad(function(){
-	var handle = dijit.registerWin(window);
-	if(dojo.isIE){
-		dojo.addOnWindowUnload(function(){
-			dijit.unregisterWin(handle);
-			handle = null;
-		})
-	}
-});
-
-}
-
-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 = Math.max(view.l, corner.charAt(1) == 'L' ? pos.x : (pos.x - mb.w)),
-			startY = Math.max(view.t, corner.charAt(0) == 'T' ? pos.y : (pos.y - mb.h)),
-			endX = Math.min(view.l + view.w, corner.charAt(1) == 'L' ? (startX + mb.w) : pos.x),
-			endY = Math.min(view.t + view.h, corner.charAt(0) == 'T' ? (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 aroundNodePos = dojo.position(aroundNode, true);
-	aroundNode.style.display=oldDisplay;
-
-	// place the node around the calculated rectangle
-	return dijit._placeOnScreenAroundRect(node,
-		aroundNodePos.x, aroundNodePos.y, aroundNodePos.w, aroundNodePos.h,	// 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
-
-	this.x = x;
-	this.y = y;
-	this.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);
-};
-
-dijit.getPopupAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
-	// summary:
-	//		Transforms the passed array of preferred positions into a format suitable for passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
-	//
-	// position: String[]
-	//		This variable controls the position of the drop down.
-	//		It's an array of strings with the following values:
-	//
-	//			* before: places drop down to the left of the target node/widget, or to the right in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* after: places drop down to the right of the target node/widget, or to the left in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* above: drop down goes above target node
-	//			* below: drop down goes below target node
-	//
-	//		The list is positions is tried, in order, until a position is found where the drop down fits
-	//		within the viewport.
-	//
-	// leftToRight: Boolean
-	//		Whether the popup will be displaying in leftToRight mode.
-	//
-	var align = {};
-	dojo.forEach(position, function(pos){
-		switch(pos){
-			case "after":
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
-				break;
-			case "before":
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
-				break;
-			case "below":
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "TL" : "TR";
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "TR" : "TL";
-				break;
-			case "above":
-			default:
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "TL" : "TR"] = leftToRight ? "BL" : "BR";
-				align[leftToRight ? "TR" : "TL"] = leftToRight ? "BR" : "BL";
-				break;
-		}
-	});
-	return align;
-};
-dijit.getPopupAroundAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
-	// summary:
-	//		Transforms the passed array of preferred positions into a format suitable for passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
-	//
-	// position: String[]
-	//		This variable controls the position of the drop down.
-	//		It's an array of strings with the following values:
-	//
-	//			* before: places drop down to the left of the target node/widget, or to the right in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* after: places drop down to the right of the target node/widget, or to the left in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* above: drop down goes above target node
-	//			* below: drop down goes below target node
-	//
-	//		The list is positions is tried, in order, until a position is found where the drop down fits
-	//		within the viewport.
-	//
-	// leftToRight: Boolean
-	//		Whether the popup will be displaying in leftToRight mode.
-	//
-	var align = {};
-	dojo.forEach(position, function(pos){
-		switch(pos){
-			case "after":
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
-				break;
-			case "before":
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
-				break;
-			case "below":
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "TL" : "TR";
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "TR" : "TL";
-				break;
-			case "above":
-			default:
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "TL" : "TR"] = leftToRight ? "BL" : "BR";
-				align[leftToRight ? "TR" : "TL"] = leftToRight ? "BR" : "BL";
-				break;
-		}
-	});
-	return align;
-};
-
-}
-
-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.moveOffScreen = function(/*DomNode*/ node){
-		// summary:
-		//		Moves node offscreen without hiding it (so that all layout widgets included 
-		//		in this node can still layout properly)
-		//
-		// 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;
-}
-=====*/
-
-	// 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];
-	};
-
-	var wrappers=[];
-	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 || (
-				dojo._isBodyLtr() ?
-				{'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'} :
-				{'BR':'TR', 'BL':'TL', 'TR':'BR', '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 wrapperobj = wrappers.pop(), wrapper, iframe;
-		if(!wrapperobj){
-			wrapper = dojo.create("div",{
-				"class":"dijitPopup"
-			}, dojo.body());
-			dijit.setWaiRole(wrapper, "presentation");
-		}else{
-			// recycled a old wrapper, so that we don't need to reattach the iframe
-			// which is slow even if the iframe is empty, see #10167
-			wrapper = wrapperobj[0];
-			iframe = wrapperobj[1];
-		}
-
-		dojo.attr(wrapper,{
-			id: id,
-			style:{
-				zIndex: beginZIndex + stack.length,
-				visibility:"hidden",
-				// prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
-				top: "-9999px"
-			},
-			dijitPopupParent: args.parent ? args.parent.id : ""
-		});
-
-		var s = widget.domNode.style;
-		s.display = "";
-		s.visibility = "";
-		s.position = "";
-		s.top = "0px";
-		wrapper.appendChild(widget.domNode);
-
-		if(!iframe){
-			iframe = new dijit.BackgroundIframe(wrapper);
-		}else{
-			iframe.resize(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 = [];
-
-		// 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", args.onCancel));
-		}
-
-		handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", 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){
-			// TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here)
-			widget.onOpen(best);
-		}
-
-		return best;
-	};
-
-	this.close = function(/*dijit._Widget*/ popup){
-		// summary:
-		//		Close specified popup and any popups that it parented
-		
-		// Basically work backwards from the top of the stack closing popups
-		// until we hit the specified popup, but IIRC there was some issue where closing
-		// a popup would cause others to close too.  Thus if we are trying to close B in [A,B,C]
-		// closing C might close B indirectly and then the while() condition will run where stack==[A]...
-		// so the while condition is constructed defensively.
-		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){
-				// TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here)
-				widget.onClose();
-			}
-			dojo.forEach(top.handlers, dojo.disconnect);
-
-			// Move the widget offscreen, unless it has already been destroyed in above onClose() etc.
-			if(widget && widget.domNode){
-				this.moveOffScreen(widget.domNode);
-			}
-                        
-			// recycle the wrapper plus iframe, so we prevent reattaching iframe everytime an popup opens
-			// don't use moveOffScreen which would also reattach the wrapper to body, which causes reloading of iframe
-			wrapper.style.top = "-9999px";
-			wrapper.style.visibility = "hidden";
-			wrappers.push([wrapper,iframe]);
-
-			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";
-				dojo.style(iframe, "opacity", 0.1);
-			}
-			iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didnt work.
-		}
-		return iframe;
-	};
-
-	this.push = function(iframe){
-		iframe.style.display="none";
-		queue.push(iframe);
-	}
-}();
-
-
-dijit.BackgroundIframe = function(/* DomNode */node){
-	// summary:
-	//		For IE/FF 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 || dojo.isMoz){
-		var iframe = dijit._frames.pop();
-		node.appendChild(iframe);
-		if(dojo.isIE<7){
-			this.resize(node);
-			this._conn = dojo.connect(node, 'onresize', this, function(){
-				this.resize(node);
-			});
-		}else{
-			dojo.style(iframe, {
-				width: '100%',
-				height: '100%'
-			});
-		}
-		this.iframe = iframe;
-	}
-};
-
-dojo.extend(dijit.BackgroundIframe, {
-	resize: function(node){
-		// summary:
-		// 		resize the iframe so its the same size as node
-		// description:
-		//		this function is a no-op in all browsers except
-		//		IE6, which does not support 100% width/height 
-		//		of absolute positioned iframes
-		if(this.iframe && dojo.isIE<7){
-			dojo.style(this.iframe, {
-				width: node.offsetWidth + 'px',
-				height: node.offsetHeight + 'px'
-			});
-		}
-	},
-	destroy: function(){
-		// summary:
-		//		destroy the iframe
-		if(this._conn){
-			dojo.disconnect(this._conn);
-			this._conn = null;
-		}
-		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, /*Object?*/ pos){
-	// summary:
-	//		Scroll the passed node into view, if it is not already.
-	
-	// don't rely on that node.scrollIntoView works just because the function is there
-
-	try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
-	node = dojo.byId(node);
-	var doc = node.ownerDocument || dojo.doc,
-		body = doc.body || dojo.body(),
-		html = doc.documentElement || body.parentNode,
-		isIE = dojo.isIE, isWK = dojo.isWebKit;
-	// if an untested browser, then use the native method
-	if((!(dojo.isMoz || isIE || isWK) || node == body || node == html) && (typeof node.scrollIntoView != "undefined")){
-		node.scrollIntoView(false); // short-circuit to native if possible
-		return;
-	}
-	var backCompat = doc.compatMode == 'BackCompat',
-		clientAreaRoot = backCompat? body : html,
-		scrollRoot = isWK ? body : clientAreaRoot,
-		rootWidth = clientAreaRoot.clientWidth,
-		rootHeight = clientAreaRoot.clientHeight,
-		rtl = !dojo._isBodyLtr(),
-		nodePos = pos || dojo.position(node),
-		el = node.parentNode,
-		isFixed = function(el){
-			return ((isIE <= 6 || (isIE && backCompat))? false : (dojo.style(el, 'position').toLowerCase() == "fixed"));
-		};
-	if(isFixed(node)){ return; } // nothing to do
-	while(el){
-		if(el == body){ el = scrollRoot; }
-		var elPos = dojo.position(el),
-			fixedPos = isFixed(el);
-		with(elPos){
-			if(el == scrollRoot){
-				w = rootWidth, h = rootHeight;
-				if(scrollRoot == html && isIE && rtl){ x += scrollRoot.offsetWidth-w; } // IE workaround where scrollbar causes negative x
-				if(x < 0 || !isIE){ x = 0; } // IE can have values > 0
-				if(y < 0 || !isIE){ y = 0; }
-			}else{
-				var pb = dojo._getPadBorderExtents(el);
-				w -= pb.w; h -= pb.h; x += pb.l; y += pb.t;
-			}
-			with(el){
-				if(el != scrollRoot){ // body, html sizes already have the scrollbar removed
-					var clientSize = clientWidth,
-						scrollBarSize = w - clientSize;
-					if(clientSize > 0 && scrollBarSize > 0){
-						w = clientSize;
-						if(isIE && rtl){ x += scrollBarSize; }
-					}
-					clientSize = clientHeight;
-					scrollBarSize = h - clientSize;
-					if(clientSize > 0 && scrollBarSize > 0){
-						h = clientSize;
-					}
-				}
-				if(fixedPos){ // bounded by viewport, not parents
-					if(y < 0){
-						h += y, y = 0;
-					}
-					if(x < 0){
-						w += x, x = 0;
-					}
-					if(y + h > rootHeight){
-						h = rootHeight - y;
-					}
-					if(x + w > rootWidth){
-						w = rootWidth - x;
-					}
-				}
-				// calculate overflow in all 4 directions
-				var l = nodePos.x - x, // beyond left: < 0
-					t = nodePos.y - Math.max(y, 0), // beyond top: < 0
-					r = l + nodePos.w - w, // beyond right: > 0
-					bot = t + nodePos.h - h; // beyond bottom: > 0
-				if(r * l > 0){
-					var s = Math[l < 0? "max" : "min"](l, r);
-					nodePos.x += scrollLeft;
-					scrollLeft += (isIE >= 8 && !backCompat && rtl)? -s : s;
-					nodePos.x -= scrollLeft;
-				}
-				if(bot * t > 0){
-					nodePos.y += scrollTop;
-					scrollTop += Math[t < 0? "max" : "min"](t, bot);
-					nodePos.y -= scrollTop;
-				}
-			}
-		}
-		el = (el != scrollRoot) && !fixedPos && el.parentNode;
-	}
-	}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_ie6: maj(ie) == 6,
-			dj_ie7: maj(ie) == 7,
-			dj_ie8: maj(ie) == 8,
-			dj_iequirks: ie && d.isQuirks,
-
-			// NOTE: Opera not supported by dijit
-			dj_opera: opera,
-
-			dj_khtml: d.isKhtml,
-
-			dj_webkit: d.isWebKit,
-			dj_safari: d.isSafari,
-			dj_chrome: d.isChrome,
-
-			dj_gecko: d.isMozilla,
-			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);
-		
-		// Schedule next event, reducing the timer a little bit each iteration, bottoming-out at 10 to avoid
-		// browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup)
-		this._currentTimeout = Math.max(
-			this._currentTimeout < 0 ? this._initialDelay :
-				(this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)),
-			10);
-		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.altKey) &&
-				(keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey
-				(keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){
-					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:
-		//		Replace existing role attribute with new role.
-		//		If elem already has an XHTML role, append this role to XHTML role
-		//		and remove other ARIA roles.
-
-		var curRole = dojo.attr(elem, "role") || "";
-		if(!this._XhtmlRoles.test(curRole)){
-			dojo.attr(elem, "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 t = dojo.trim((" " + roleValue + " ").replace(" " + role + " ", " "));
-			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:
-		//		Checks for an attribute called "aria-"+state.
-		// returns:
-		//		true if elem has a value for the given state and
-		//		false if it does not.
-
-		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:
-		//		Checks 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.
-
-		return elem.getAttribute("aria-"+state) || "";
-	},
-
-	setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
-		// summary:
-		//		Sets a state on an element.
-		// description:
-		//		Sets an attribute called "aria-"+state.
-
-		elem.setAttribute("aria-"+state, value);
-	},
-
-	removeWaiState: function(/*Element*/ elem, /*String*/ state){
-		// summary:
-		//		Removes a state from an element.
-		// description:
-		//		Sets an attribute called "aria-"+state.
-
-		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["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),
-		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); //TODO: UTC defaults
-		if(match[0] < 100){
-			result.setFullYear(match[0] || 1970);
-		}
-
-		var offset = 0,
-			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 = [],
-		getter = options.zulu ? "getUTC" : "get",
-		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;
-	this._attrName = d._scopeName + "Type";
-	this._query = "[" + this._attrName + "]";
-
-	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){
-						// The user has specified some text for a function like "return x+5"
-						return new Function(value);
-					}else{
-						// The user has specified the name of a function like "myOnClick"
-						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"} }
-	};
-
-	// Widgets like BorderContainer add properties to _Widget via dojo.extend().
-	// If BorderContainer is loaded after _Widget's parameter list has been cached,
-	// we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
-	dojo.connect(dojo, "extend", function(){
-		instanceClasses = {};
-	});
-
-	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, /* Object? */args){
-		// 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.
-		// args: Object?
-		//		An object used to hold kwArgs for instantiation.
-		//		Only supports 'noStart' currently.
-		var thelist = [], dp = dojo.parser;
-		mixin = mixin||{};
-		args = args||{};
-		
-		d.forEach(nodes, function(node){
-			if(!node){ return; }
-			var type = dp._attrName in mixin?mixin[dp._attrName]:node.getAttribute(dp._attrName);
-			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 || clazz.prototype && 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
-		if(!mixin._started){
-			d.forEach(thelist, function(instance){
-				if(	!args.noStart && instance  && 
-					instance.startup &&
-					!instance._started && 
-					(!instance.getParent || !instance.getParent())
-				){
-					instance.startup();
-				}
-			});
-		}
-		return thelist;
-	};
-
-	this.parse = function(/*DomNode?*/ rootNode, /* Object? */ args){
-		// summary:
-		//		Scan the DOM for class instances, and instantiate them.
-		//
-		// description:
-		//		Search specified node (or root node) recursively for class instances,
-		//		and instantiate them Searches for
-		//		dojoType="qualified.class.name"
-		//
-		// rootNode: DomNode?
-		//		A default starting root node from which to start the parsing. Can be
-		//		omitted, defaulting to the entire document. If omitted, the `args`
-		//		object can be passed in this place. If the `args` object has a 
-		//		`rootNode` member, that is used.
-		//
-		// args:
-		//		a kwArgs object passed along to instantiate()
-		//		
-		//			* noStart: Boolean?
-		//				when set will prevent the parser from calling .startup()
-		//				when locating the nodes. 
-		//			* rootNode: DomNode?
-		//				identical to the function's `rootNode` argument, though
-		//				allowed to be passed in via this `args object. 
-		//
-		// example:
-		//		Parse all widgets on a page:
-		//	|		dojo.parser.parse();
-		//
-		// example:
-		//		Parse all classes within the node with id="foo"
-		//	|		dojo.parser.parse(dojo.byId(foo));
-		//
-		// example:
-		//		Parse all classes in a page, but do not call .startup() on any 
-		//		child
-		//	|		dojo.parser.parse({ noStart: true })
-		//
-		// example:
-		//		Parse all classes in a node, but do not call .startup()
-		//	|		dojo.parser.parse(someNode, { noStart:true });
-		//	|		// or
-		// 	|		dojo.parser.parse({ noStart:true, rootNode: someNode });
-
-		// determine the root node based on the passed arguments.
-		var root;
-		if(!args && rootNode && rootNode.rootNode){
-			args = rootNode;
-			root = args.rootNode;
-		}else{
-			root = rootNode;
-		}
-
-		var	list = d.query(this._query, root);
-			// go build the object instances
-		return this.instantiate(list, null, args); // Array
-
-	};
-}();
-
-//Register the parser callback. It should be the first callback
-//after the a11y test.
-
-(function(){
-	var parseRunner = function(){ 
-		if(dojo.config.parseOnLoad){
-			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["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" );
-
-
-// This code is to assist deferring dojo.connect() calls in widgets (connecting to events on the widgets'
-// DOM nodes) until someone actually needs to monitor that event.
-dojo.connect(dojo, "_connect",
-	function(/*dijit._Widget*/ widget, /*String*/ event){
-		if(widget && dojo.isFunction(widget._onConnect)){
-			widget._onConnect(event);
-		}
-	});
-
-dijit._connectOnUseEventHandler = function(/*Event*/ event){};
-
-// Keep track of where the last keydown event was, to help avoid generating
-// spurious ondijitclick events when:
-// 1. focus is on a <button> or <a>
-// 2. user presses then releases the ENTER key
-// 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
-// 4. onkeyup event fires, causing the ondijitclick handler to fire
-dijit._lastKeyDownNode = null;
-if(dojo.isIE){
-	(function(){
-		var keydownCallback = function(evt){
-			dijit._lastKeyDownNode = evt.srcElement;
-		};
-		dojo.doc.attachEvent('onkeydown', keydownCallback);
-		dojo.addOnWindowUnload(function(){
-			dojo.doc.detachEvent('onkeydown', keydownCallback);
-		});
-	})();
-}else{
-	dojo.doc.addEventListener('keydown', function(evt){
-		dijit._lastKeyDownNode = evt.target;
-	}, true);
-}
-
-(function(){
-
-var _attrReg = {},	// cached results from getSetterAttributes
-	getSetterAttributes = function(widget){
-		// summary:
-		//		Returns list of attributes with custom setters for specified widget
-		var dc = widget.declaredClass;
-		if(!_attrReg[dc]){
-			var r = [],
-				attrs,
-				proto = widget.constructor.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] || [];	// String[]
-	};
-
-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.
-	//
-	//		For form widgets this specifies a tooltip to display when hovering over
-	//		the widget (just like the native HTML title attribute).
-	//
-	//		For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
-	//		etc., it's used to specify the tab label, accordion pane title, etc.
-	title: "",
-
-	// tooltip: String
-	//		When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
-	//		this specifies the tooltip to appear when the mouse is hovered over that text.
-	tooltip: "",
-
-	// 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,
-
-/*=====
-	// _started: Boolean
-	//		startup() has completed.
-	_started: false,
-=====*/
-
-	// 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 innerText
-	//	|		title: { node: "titleNode", type: "innerText" }
-	//		Maps this.title to this.titleNode.innerText
-	//
-	//		- 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] String
-	//		Path to a blank 1x1 image.
-	//		Used by <img> nodes in templates that really get their image via CSS background-image.
-	_blankGif: (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")).toString(),
-
-	//////////// 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:
-		//		Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
-		//		etc.), some of which of you'll want to override. See http://docs.dojocampus.org/dijit/_Widget
-		//		for a discussion of the widget creation lifecycle.
-		//
-		//		Of course, adventurous developers could override create entirely, but this should
-		//		only be done as a last resort.
-		// 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 = [];
-
-		// For garbage collection.  An array of handles returned by Widget.subscribe()
-		// The handle returned from Widget.subscribe() is the handle returned from dojo.subscribe()
-		this._subscribes = [];
-
-		// 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]);
-			}
-		};
-
-		// Do the attributes in attributeMap
-		for(var attr in this.attributeMap){
-			condAttrApply(attr, this);
-		}
-
-		// And also any attributes with custom setters
-		dojo.forEach(getSetterAttributes(this), 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
-		// description:
-		//		Most widgets will mixin `dijit._Templated`, which implements this
-		//		method.
-		// tags:
-		//		protected
-		this.domNode = this.srcNodeRef || dojo.create('div');
-	},
-
-	postCreate: function(){
-		// summary:
-		//		Processing after the DOM fragment is created
-		// description:
-		//		Called after the DOM fragment has been created, but not necessarily
-		//		added to the document.  Do not include any operations which rely on
-		//		node dimensions or placement.
-		// tags:
-		//		protected
-	},
-
-	startup: function(){
-		// summary:
-		//		Processing after the DOM fragment is added to the document
-		// description:
-		//		Called after a widget and its children have been created and added to the page,
-		//		and all related widgets have finished their create() cycle, up through postCreate().
-		//		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 its descendants
-		// description:
-		//		This is the generic "destructor" function that all widget users
-		// 		should call to cleanly discard with a widget. Once a widget is
-		// 		destroyed, it is 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._beingDestroyed = true;
-		this.destroyDescendants(preserveDom);
-		this.destroy(preserveDom);
-	},
-
-	destroy: function(/*Boolean*/ preserveDom){
-		// summary:
-		// 		Destroy this widget, but not its descendants.
-		//		This method 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._beingDestroyed = true;
-		this.uninitialize();
-		var d = dojo,
-			dfe = d.forEach,
-			dun = d.unsubscribe;
-		dfe(this._connects, function(array){
-			dfe(array, d.disconnect);
-		});
-		dfe(this._subscribes, function(handle){
-			dun(handle);
-		});
-
-		// destroy widgets created as part of template, etc.
-		dfe(this._supportingWidgets || [], function(w){
-			if(w.destroyRecursive){
-				w.destroyRecursive();
-			}else if(w.destroy){
-				w.destroy();
-			}
-		});
-
-		this.destroyRendering(preserveDom);
-		dijit.registry.remove(this.id);
-		this._destroyed = true;
-	},
-
-	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, innerText, or attribute
-
-			switch(type){
-				case "attribute":
-					if(dojo.isFunction(value)){ // functions execute in the context of the widget
-						value = dojo.hitch(this, value);
-					}
-
-					// Get the name of the DOM node attribute; usually it's the same
-					// as the name of the attribute in the widget (attr), but can be overridden.
-					// Also maps handler names to lowercase, like onSubmit --> onsubmit
-					var attrName = command.attribute ? command.attribute :
-						(/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
-
-					dojo.attr(mapNode, attrName, value);
-					break;
-				case "innerText":
-					mapNode.innerHTML = "";
-					mapNode.appendChild(dojo.doc.createTextNode(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
-				args = dojo._toArray(arguments, 1);
-				return this[names.s].apply(this, args) || 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
-			return this[names.g] ? this[names.g]() : 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
-		// description:
-		//		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 reversible
-		//		serialization.
-		return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
-	},
-
-	getDescendants: function(){
-		// summary:
-		//		Returns all the widgets 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.
-
-		return this.containerNode ? dojo.query('[widgetId]', this.containerNode).map(dijit.byNode) : []; // dijit._Widget[]
-	},
-
-	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.
-		return this.containerNode ? dijit.findWidgets(this.containerNode) : []; // dijit._Widget[]
-	},
-
-	// 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 or enter keyup
-		// returns:
-		//		A handle that can be passed to `disconnect` in order to disconnect before
-		//		the widget is destroyed.
-		// 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(){
-		//	|		console.debug(this.toString());
-		//	|	});
-		// tags:
-		//		protected
-
-		var d = dojo,
-			dc = d._connect,
-			handles = [];
-		if(event == "ondijitclick"){
-			// add key based click activation for unsupported nodes.
-			// do all processing onkey up to prevent spurious clicks
-			// for details see comments at top of this file where _lastKeyDownNode is defined
-			if(!this.nodesWithKeyClick[obj.tagName.toLowerCase()]){
-				var m = d.hitch(this, method);
-				handles.push(
-					dc(obj, "onkeydown", this, function(e){
-						//console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
-						if((e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
-							!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
-							// needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
-							dijit._lastKeyDownNode = e.target;
-							d.stopEvent(e);		// stop event to prevent scrolling on space key in IE
-						}
-			 		}),
-					dc(obj, "onkeyup", this, function(e){
-						//console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
-						if( (e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
-							e.target === dijit._lastKeyDownNode &&
-							!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
-								//need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
-								dijit._lastKeyDownNode = null;
-								return m(e);
-						}
-					})
-				);
-			}
-			event = "onclick";
-		}
-		handles.push(dc(obj, event, this, method));
-
-		this._connects.push(handles);
-		return handles;		// _Widget.Handle
-	},
-
-	disconnect: function(/* _Widget.Handle */ handles){
-		// summary:
-		//		Disconnects handle created by `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;
-			}
-		}
-	},
-
-	subscribe: function(
-			/*String*/ topic,
-			/*String|Function*/ method){
-		// summary:
-		//		Subscribes to the specified topic and calls the specified method
-		//		of this object and registers for unsubscribe() on widget destroy.
-		// description:
-		//		Provide widget-specific analog to dojo.subscribe, except with the
-		//		implicit use of this widget as the target object.
-		// example:
-		//	|	var btn = new dijit.form.Button();
-		//	|	// when /my/topic is published, this button changes its label to
-		//	|   // be the parameter of the topic.
-		//	|	btn.subscribe("/my/topic", function(v){
-		//	|		this.attr("label", v);
-		//	|	});
-		var d = dojo,
-			handle = d.subscribe(topic, this, method);
-
-		// return handles for Any widget that may need them
-		this._subscribes.push(handle);
-		return handle;
-	},
-
-	unsubscribe: function(/*Object*/ handle){
-		// summary:
-		//		Unsubscribes handle created by this.subscribe.
-		//		Also removes handle from this widget's list of subscriptions
-		for(var i=0; i<this._subscribes.length; i++){
-			if(this._subscribes[i] == handle){
-				dojo.unsubscribe(handle);
-				this._subscribes.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){ console.log('click'); });
-		//
-		// 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;
-	},
-
-	_onShow: function(){
-		// summary:
-		//		Internal method called when this widget is made visible.
-		//		See `onShow` for details.
-		this.onShow();
-	},
-
-	onShow: function(){
-		// summary:
-		//		Called when this widget becomes the selected pane in a
-		//		`dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
-		//		`dijit.layout.AccordionContainer`, etc.
-		//
-		//		Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
-		// tags:
-		//		callback
-	},
-
-	onHide: function(){
-		// summary:
-			//		Called when another widget becomes the selected pane in a
-			//		`dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
-			//		`dijit.layout.AccordionContainer`, etc.
-			//
-			//		Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
-			// tags:
-			//		callback
-	}
-});
-
-})();
-
-}
-
-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. mylib.encodeXML
-	//	thisObject: 
-	//		where to look for optional format function; default to the global
-	//		namespace
-	//	example:
-	//		Substitutes two expressions in a string from an Array or Object
-	//	|	// returns "File 'foo.html' is not found in directory '/temp'."
-	//	|	// by providing substitution data in an Array
-	//	|	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'."
-	//	|	// but provides substitution data in an Object structure.  Dotted
-	//	|	// notation may be used to traverse the structure.
-	//	|	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 ? 
-		dojo.hitch(thisObject, transform) : function(v){ return v; };
-
-	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.cache"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.cache"] = true;
-dojo.provide("dojo.cache");
-
-/*=====
-dojo.cache = { 
-	// summary:
-	// 		A way to cache string content that is fetchable via `dojo.moduleUrl`.
-};
-=====*/
-
-(function(){
-	var cache = {};
-	dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
-		// summary:
-		// 		A getter and setter for storing the string content associated with the
-		// 		module and url arguments.
-		// description:
-		// 		module and url are used to call `dojo.moduleUrl()` to generate a module URL.
-		// 		If value is specified, the cache value for the moduleUrl will be set to
-		// 		that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
-		// 		in its internal cache and return that cached value for the URL. To clear
-		// 		a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
-		// 		the URL contents, only modules on the same domain of the page can use this capability.
-		// 		The build system can inline the cache values though, to allow for xdomain hosting.
-		// module: String||Object
-		// 		If a String, the module name to use for the base part of the URL, similar to module argument
-		// 		to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
-		// 		generates a valid path for the cache item. For example, a dojo._Url object.
-		// url: String
-		// 		The rest of the path to append to the path derived from the module argument. If
-		// 		module is an object, then this second argument should be the "value" argument instead.
-		// value: String||Object?
-		// 		If a String, the value to use in the cache for the module/url combination.
-		// 		If an Object, it can have two properties: value and sanitize. The value property
-		// 		should be the value to use in the cache, and sanitize can be set to true or false,
-		// 		to indicate if XML declarations should be removed from the value and if the HTML
-		// 		inside a body tag in the value should be extracted as the real value. The value argument
-		// 		or the value property on the value argument are usually only used by the build system
-		// 		as it inlines cache content.
-		//	example:
-		//		To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
-		// 		of call is used to avoid an issue with the build system erroneously trying to intern
-		// 		this example. To get the build system to intern your dojo.cache calls, use the
-		// 		"dojo.cache" style of call):
-		// 		|	//If template.html contains "<h1>Hello</h1>" that will be
-		// 		|	//the value for the text variable.
-		//		|	var text = dojo["cache"]("my.module", "template.html");
-		//	example:
-		//		To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
-		// 		 (the dojo["cache"] style of call is used to avoid an issue with the build system 
-		// 		erroneously trying to intern this example. To get the build system to intern your
-		// 		dojo.cache calls, use the "dojo.cache" style of call):
-		// 		|	//If template.html contains "<html><body><h1>Hello</h1></body></html>", the
-		// 		|	//text variable will contain just "<h1>Hello</h1>".
-		//		|	var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
-		//	example:
-		//		Same example as previous, but demostrates how an object can be passed in as
-		//		the first argument, then the value argument can then be the second argument.
-		// 		|	//If template.html contains "<html><body><h1>Hello</h1></body></html>", the
-		// 		|	//text variable will contain just "<h1>Hello</h1>".
-		//		|	var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
-
-		//Module could be a string, or an object that has a toString() method
-		//that will return a useful path. If it is an object, then the "url" argument
-		//will actually be the value argument.
-		if(typeof module == "string"){
-			var pathObj = dojo.moduleUrl(module, url);
-		}else{
-			pathObj = module;
-			value = url;
-		}
-		var key = pathObj.toString();
-
-		var val = value;
-		if(value !== undefined && !dojo.isString(value)){
-			val = ("value" in value ? value.value : undefined);
-		}
-
-		var sanitize = value && value.sanitize ? true : false;
-
-		if(val || val === null){
-			//We have a value, either clear or set the cache value.
-			if(val == null){
-				delete cache[key];
-			}else{
-				val = cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
-			}
-		}else{
-			//Allow cache values to be empty strings. If key property does
-			//not exist, fetch it.
-			if(!(key in cache)){
-				val = dojo._getText(key);
-				cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
-			}
-			val = cache[key];
-		}
-		return val; //String
-	};
-
-	dojo.cache._sanitize = function(/*String*/val){
-		// 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.
-		// description:
-		// 		Copied from dijit._Templated._sanitizeTemplateString.
-		if(val){
-			val = val.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
-			var matches = val.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
-			if(matches){
-				val = matches[1];
-			}
-		}else{
-			val = "";
-		}
-		return val; //String
-	};
-})();
-
-}
-
-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.
-		//
-		//		Use in conjunction with dojo.cache() to load from a file.
-		templateString: null,
-
-		// templatePath: [protected deprecated] String
-		//		Path to template (HTML file) for this widget relative to dojo.baseUrl.
-		//		Deprecated: use templateString with dojo.cache() instead.
-		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,
-
-		// _earlyTemplatedStartup: Boolean
-		//		A fallback to preserve the 1.0 - 1.3 behavior of children in
-		//		templates having their startup called before the parent widget
-		//		fires postCreate. Defaults to 'false', causing child widgets to
-		//		have their .startup() called immediately before a parent widget
-		//		.startup(), but always after the parent .postCreate(). Set to
-		//		'true' to re-enable to previous, arguably broken, behavior.
-		_earlyTemplatedStartup: false,
-
-		// _attachPoints: [private] String[]
-		//		List of widget attribute names associated with dojoAttachPoint=... in the
-		//		template, ex: ["containerNode", "labelNode"]
-/*=====
- 		_attachPoints: [],
- =====*/
-
-		constructor: function(){
-			this._attachPoints = [];
-		},
-
-		_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,"""); //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));
-				if(node.nodeType != 1){
-					// Flag common problems such as templates with multiple top level nodes (nodeType == 11)
-					throw new Error("Invalid template: " + 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){
-				// Make sure dojoType is used for parsing widgets in template.
-				// The dojo.parser.query could be changed from multiversion support.
-				var parser = dojo.parser, qry, attr;
-				if(parser._query != "[dojoType]"){
-					qry = parser._query;
-					attr = parser._attrName;
-					parser._query = "[dojoType]";
-					parser._attrName = "dojoType";
-				}
-
-				// Store widgets that we need to start at a later point in time
-				var cw = (this._startupWidgets = dojo.parser.parse(node, {
-					noStart: !this._earlyTemplatedStartup
-				}));
-
-				// Restore the query.
-				if(qry){
-					parser._query = qry;
-					parser._attrName = attr;
-				}
-
-				this._supportingWidgets = dijit.findWidgets(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;
-						}
-						this._attachPoints.push(point);
-					}
-				}
-
-				// 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]);
-						}
-					});
-				}
-			}
-		},
-
-		startup: function(){
-			dojo.forEach(this._startupWidgets, function(w){
-				if(w && !w._started && w.startup){
-					w.startup();
-				}
-			});
-			this.inherited(arguments);
-		},
-
-		destroyRendering: function(){
-			// Delete all attach points to prevent IE6 memory leaks.
-			dojo.forEach(this._attachPoints, function(point){
-				delete this[point];
-			}, this);
-			this._attachPoints = [];
-
-			this.inherited(arguments);
-		}
-	}
-);
-
-// 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||dojo.uri.Uri
-	//		The URL to get the template from.
-	// 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){
-		try{
-			// if the cached value is an innerHTML string (no ownerDocument) or a DOM tree created within the current document, then use the current cached value
-			if(!cached.ownerDocument || cached.ownerDocument == dojo.doc){
-				// string or node of the same document
-				return cached;
-			}
-		}catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded
-		dojo.destroy(cached);
-	}
-
-	// If necessary, load template string from template path
-	if(!templateString){
-		templateString = dojo.cache(templatePath, {sanitize: true});
-	}
-	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
-		var node = dojo._toDom(templateString);
-		if(node.nodeType != 1){
-			throw new Error("Invalid template: " + templateString);
-		}
-		return (tmplts[key] = node); //Node
-	}
-};
-
-if(dojo.isIE){
-	dojo.addOnWindowUnload(function(){
-		var cache = dijit._Templated._templateCache;
-		for(var key in cache){
-			var value = cache[key];
-			if(typeof value == "object"){ // value is either a string or a DOM node template
-				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._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
-		//		Indicates that this widget acts as a "parent" to the descendant widgets.
-		//		When the parent is started it will call startup() on the child widgets.
-		//		See also `isLayoutContainer`.
-		isContainer: true,
-
-		buildRendering: function(){
-			this.inherited(arguments);
-			if(!this.containerNode){
-				// all widgets with descendants must set containerNode
-	 				this.containerNode = this.domNode;
-			}
-		},
-
-		addChild: function(/*dijit._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(widget && widget.domNode){
-				var node = widget.domNode;
-				node.parentNode.removeChild(node); // detach but don't destroy
-			}
-		},
-
-		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 dojo.query("> [widgetId]", this.containerNode).length > 0;	// 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(/*dijit._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,
-				which = (dir>0 ? "nextSibling" : "previousSibling");
-			do{
-				node = node[which];
-			}while(node && (node.nodeType != 1 || !dijit.byNode(node)));
-			return node && dijit.byNode(node);	// dijit._Widget
-		},
-
-		getIndexOfChild: function(/*dijit._Widget*/ child){
-			// summary:
-			//		Gets the index of the child in this container or -1 if not found
-			return dojo.indexOf(this.getChildren(), child);	// int
-		},
-
-		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; }
-
-			// Startup all children of this widget
-			dojo.forEach(this.getChildren(), function(child){ child.startup(); });
-
-			this.inherited(arguments);
-		}
-	}
-);
-
-}
-
-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
-				//		specifies isContainer
-				var parent = dijit.getEnclosingWidget(this.domNode.parentNode);
-				return parent && parent.isContainer ? parent : null;
-			},
-
-			_getSibling: function(/*String*/ 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);
-				return node && dijit.byNode(node);	// dijit._Widget
-			},
-
-			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"); // dijit._Widget
-			},
-
-			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"); // dijit._Widget
-			},
-
-			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.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 manage placement and sizing of 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,
-		//		for example dijitTabContainer-content.
-		baseClass: "dijitLayoutContainer",
-
-		// isLayoutContainer: [protected] Boolean
-		//		Indicates that this widget is going to call resize() on its
-		//		children widgets, setting their size, when they become visible.
-		isLayoutContainer: true,
-
-		postCreate: function(){
-			dojo.addClass(this.domNode, "dijitContainer");
-			dojo.addClass(this.domNode, this.baseClass);
-
-			this.inherited(arguments);
-		},
-
-		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; }
-
-			// Need to call inherited first - so that child widgets get started
-			// up correctly
-			this.inherited(arguments);
-
-			// If I am a not being controlled by a parent layout widget...
-			var parent = this.getParent && this.getParent()
-			if(!(parent && parent.isLayoutContainer)){
-				// 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 *may be* width=height=100%
-				// or something similar (either set directly or via a CSS class),
-				// monitor when my size changes so that I can re-layout.
-				// For browsers where I can't directly monitor when my size changes,
-				// monitor when the viewport changes size, which *may* indicate a size change for me.
-				this.connect(dojo.isIE ? this.domNode : dojo.global, 'onresize', function(){
-					// Using function(){} closure to ensure no arguments to resize.
-					this.resize();
-				});
-			}
-		},
-
-		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 its 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 its 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(/*dijit._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(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
-			// Overrides _Container.addChild() to call _setupChild()
-			this.inherited(arguments);
-			if(this._started){
-				this._setupChild(child);
-			}
-		},
-
-		removeChild: function(/*dijit._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 its 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["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,
-
-	// 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",
-		id: "focusNode",
-		tabIndex: "focusNode",
-		alt: "focusNode",
-		title: "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);
-		if(this.valueNode){
-			dojo.attr(this.valueNode, '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.setAttribute('tabIndex', "-1");
-		}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){
-				if(this._onChangeHandle){
-					clearTimeout(this._onChangeHandle);
-				}
-				// setTimout allows hidden value processing to run and
-				// also the onChange handler can safely adjust focus, etc
-				this._onChangeHandle = setTimeout(dojo.hitch(this,
-					function(){
-						this._onChangeHandle = null;
-						this.onChange(newValue);
-					}), 0); // try to collapse multiple onChange's fired faster than can be processed
-			}
-		}
-	},
-
-	create: function(){
-		// Overrides _Widget.create()
-		this.inherited(arguments);
-		this._onChangeActive = true;
-		this._setStateClass();
-	},
-
-	destroy: function(){
-		if(this._onChangeHandle){ // destroy called before last onChange has fired
-			clearTimeout(this._onChangeHandle);
-			this.onChange(this._lastValueReported);
-		}
-		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');
-	}
-});
-
-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)
-
-	// 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,
-
-	attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
-		value: "",
-		readOnly: "focusNode"
-	}),
-
-	_setReadOnlyAttr: function(/*Boolean*/ value){
-		this.readOnly = value;
-		dojo.attr(this.focusNode, 'readOnly', value);
-		dijit.setWaiState(this.focusNode, "readonly", value);
-		this._setStateClass();
-	},
-
-	postCreate: function(){
-		if(dojo.isIE){ // IE won't stop the event with keypress
-			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(){
-		// 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 || e.metaKey)){
-			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);
-			}
-		}
-	},
-
-	_layoutHackIE7: function(){
-		// summary:
-		//		Work around table sizing bugs on IE7 by forcing redraw
-
-		if(dojo.isIE == 7){ // fix IE7 layout bug when the widget is scrolled out of sight
-			var domNode = this.domNode;
-			var parent = domNode.parentNode;
-			var pingNode = domNode.firstChild || domNode; // target node most unlikely to have a custom filter
-			var origFilter = pingNode.style.filter; // save custom filter, most likely nothing
-			while(parent && parent.clientHeight == 0){ // search for parents that haven't rendered yet
-				parent._disconnectHandle = this.connect(parent, "onscroll", dojo.hitch(this, function(e){
-					this.disconnect(parent._disconnectHandle); // only call once
-					parent.removeAttribute("_disconnectHandle"); // clean up DOM node
-					pingNode.style.filter = (new Date()).getMilliseconds(); // set to anything that's unique
-					setTimeout(function(){ pingNode.style.filter = origFilter }, 0); // restore custom filter, if any
-				}));
-				parent = parent.parentNode;
-			}
-		}
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.dijit"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.dijit"] = true;
-dojo.provide("dijit.dijit");
-
-/*=====
-dijit.dijit = {
-	// summary:
-	//		A roll-up for common dijit methods
-	// description:
-	//	A rollup file for the build system including the core and common
-	//	dijit files.
-	//
-	// example:
-	// | <script type="text/javascript" src="js/dojo/dijit/dijit.js"></script>
-	//
-};
-=====*/
-
-// All the stuff in _base (these are the function that are guaranteed available without an explicit dojo.require)
-
-
-// And some other stuff that we tend to pull in all the time anyway
-
-
-
-
-
-
-
-}
-
diff --git a/dijit/form/Button.js b/dijit/form/Button.js
index f38d20d..1fd7bca 100644
--- a/dijit/form/Button.js
+++ b/dijit/form/Button.js
@@ -1,157 +1,336 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.Button"]){
-dojo._hasResource["dijit.form.Button"]=true;
 dojo.provide("dijit.form.Button");
+
 dojo.require("dijit.form._FormWidget");
 dojo.require("dijit._Container");
 dojo.require("dijit._HasDropDown");
-dojo.declare("dijit.form.Button",dijit.form._FormWidget,{label:"",showLabel:true,iconClass:"",type:"button",baseClass:"dijitButton",templateString:dojo.cache("dijit.form","templates/Button.html","<span class=\"dijit dijitReset dijitLeft dijitInline\"\n\tdojoAttachEvent=\"onclick:_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 [...]
-if(this.disabled){
-return false;
-}
-this._clicked();
-return this.onClick(e);
-},_onButtonClick:function(e){
-if(this._onClick(e)===false){
-e.preventDefault();
-}else{
-if(this.type=="submit"&&!this.focusNode.form){
-for(var _1=this.domNode;_1.parentNode;_1=_1.parentNode){
-var _2=dijit.byNode(_1);
-if(_2&&typeof _2._onSubmit=="function"){
-_2._onSubmit(e);
-break;
-}
-}
-}
-}
-},_setValueAttr:function(_3){
-var _4=this.attributeMap.value||"";
-if(this[_4.node||_4||"domNode"].tagName=="BUTTON"){
-if(_3!=this.value){
-}
-}
-},_fillContent:function(_5){
-if(_5&&(!this.params||!("label" in this.params))){
-this.attr("label",_5.innerHTML);
-}
-},postCreate:function(){
-dojo.setSelectable(this.focusNode,false);
-this.inherited(arguments);
-},_setShowLabelAttr:function(_6){
-if(this.containerNode){
-dojo.toggleClass(this.containerNode,"dijitDisplayNone",!_6);
-}
-this.showLabel=_6;
-},onClick:function(e){
-return true;
-},_clicked:function(e){
-},setLabel:function(_7){
-dojo.deprecated("dijit.form.Button.setLabel() is deprecated.  Use attr('label', ...) instead.","","2.0");
-this.attr("label",_7);
-},_setLabelAttr:function(_8){
-this.containerNode.innerHTML=this.label=_8;
-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,dijit._HasDropDown],{baseClass:"dijitDropDownButton",templateString:dojo.cache("dijit.form","templates/DropDownButton.html","<span class=\"dijit dijitReset dijitLeft dijitInline\"\n\tdojoAttachPoint=\"_buttonNode\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\"\n\t><span class='dijitReset dijitRight dijitInline'\n\t\t><span class='dijitReset dijitInline dijitButtonNode'\n [...]
-if(this.srcNodeRef){
-var _9=dojo.query("*",this.srcNodeRef);
-dijit.form.DropDownButton.superclass._fillContent.call(this,_9[0]);
-this.dropDownContainer=this.srcNodeRef;
-}
-},startup:function(){
-if(this._started){
-return;
-}
-if(!this.dropDown){
-var _a=dojo.query("[widgetId]",this.dropDownContainer)[0];
-this.dropDown=dijit.byNode(_a);
-delete this.dropDownContainer;
-}
-dijit.popup.moveOffScreen(this.dropDown.domNode);
-this.inherited(arguments);
-},isLoaded:function(){
-var _b=this.dropDown;
-return (!_b.href||_b.isLoaded);
-},loadDropDown:function(){
-var _c=this.dropDown;
-if(!_c){
-return;
-}
-if(!this.isLoaded()){
-var _d=dojo.connect(_c,"onLoad",this,function(){
-dojo.disconnect(_d);
-this.openDropDown();
+
+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 DOMNode 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: dojo.cache("dijit.form", "templates/Button.html"),
+
+	attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
+		value: "valueNode",
+		iconClass: { node: "iconNode", type: "class" }
+	}),
+
+
+	_onClick: function(/*Event*/ e){
+		// summary:
+		//		Internal function to handle click actions
+		if(this.disabled){
+			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(this._onClick(e) === false){ // returning nothing is same as true
+			e.preventDefault(); // needed for checkbox
+		}else if(this.type == "submit" && !(this.valueNode||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;
+				}
+			}
+		}else if(this.valueNode){
+			this.valueNode.click();
+			e.preventDefault(); // cancel BUTTON click and continue with hidden INPUT click
+		}
+	},
+
+	_fillContent: function(/*DomNode*/ source){
+		// Overrides _Templated._fillContent().
+		// If button label is specified as srcNodeRef.innerHTML rather than
+		// this.params.label, handle it here.
+		if(source && (!this.params || !("label" in this.params))){
+			this.set('label', source.innerHTML);
+		}
+	},
+
+	postCreate: function(){
+		dojo.setSelectable(this.focusNode, false);
+		this.inherited(arguments);
+	},
+
+	_setShowLabelAttr: function(val){
+		if(this.containerNode){
+			dojo.toggleClass(this.containerNode, "dijitDisplayNone", !val);
+		}
+		this.showLabel = val;
+	},
+
+	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 set('label', ...) instead.
+		dojo.deprecated("dijit.form.Button.setLabel() is deprecated.  Use set('label', ...) instead.", "", "2.0");
+		this.set("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;
+		if(this.showLabel == false && !this.params.title){
+			this.titleNode.title = dojo.trim(this.containerNode.innerText || this.containerNode.textContent || '');
+		}
+	}
 });
-_c.refresh();
-}else{
-this.openDropDown();
-}
-},isFocusable:function(){
-return this.inherited(arguments)&&!this._mouseDown;
-}});
-dojo.declare("dijit.form.ComboButton",dijit.form.DropDownButton,{templateString:dojo.cache("dijit.form","templates/ComboButton.html","<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 dijitButtonNode\"><button id=\"${id}_button\" class=\"dijitReset dijitButtonContents\"\n\t\t\tdojoAttachEvent=\"onclick:_onButtonClick,on [...]
-this.inherited(arguments);
-this._focalNodes=[this.titleNode,this._popupStateNode];
-var _e=dojo.isIE;
-dojo.forEach(this._focalNodes,dojo.hitch(this,function(_f){
-this.connect(_f,_e?"onactivate":"onfocus",this._onNodeFocus);
-this.connect(_f,_e?"ondeactivate":"onblur",this._onNodeBlur);
-}));
-if(_e&&(_e<8||dojo.isQuirks)){
-with(this.titleNode){
-style.width=scrollWidth+"px";
-this.connect(this.titleNode,"onresize",function(){
-setTimeout(function(){
-style.width=scrollWidth+"px";
-},0);
+
+
+dojo.declare("dijit.form.DropDownButton", [dijit.form.Button, dijit._Container, dijit._HasDropDown], {
+	// 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: dojo.cache("dijit.form" , "templates/DropDownButton.html"),
+
+	_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.moveOffScreen(this.dropDown.domNode);
+
+		this.inherited(arguments);
+	},
+
+	isLoaded: function(){
+		// Returns whether or not we are loaded - if our dropdown has an href,
+		// then we want to check that.
+		var dropDown = this.dropDown;
+		return (!dropDown.href || dropDown.isLoaded);
+	},
+
+	loadDropDown: function(){
+		// Loads our dropdown
+		var dropDown = this.dropDown;
+		if(!dropDown){ return; }
+		if(!this.isLoaded()){
+			var handler = dojo.connect(dropDown, "onLoad", this, function(){
+				dojo.disconnect(handler);
+				this.openDropDown();
+			});
+			dropDown.refresh();
+		}else{
+			this.openDropDown();
+		}
+	},
+
+	isFocusable: function(){
+		// Overridden so that focus is handled by the _HasDropDown mixin, not by
+		// the _FormWidget mixin.
+		return this.inherited(arguments) && !this._mouseDown;
+	}
+});
+
+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: dojo.cache("dijit.form", "templates/ComboButton.html"),
+
+	attributeMap: dojo.mixin(dojo.clone(dijit.form.Button.prototype.attributeMap), {
+		id: "",
+		tabIndex: ["focusNode", "titleNode"],
+		title: "titleNode"
+	}),
+
+	// optionsTitle: String
+	//		Text that describes the options menu (accessibility)
+	optionsTitle: "",
+
+	baseClass: "dijitComboButton",
+
+	// Set classes like dijitButtonContentsHover or dijitArrowButtonActive depending on
+	// mouse action over specified node
+	cssStateNodes: {
+		"buttonNode": "dijitButtonNode",
+		"titleNode": "dijitButtonContents",
+		"_popupStateNode": "dijitDownArrowButton"
+	},
+
+	_focusedNode: null,
+
+	_onButtonKeyPress: function(/*Event*/ evt){
+		// summary:
+		//		Handler for right arrow key when focus is on left part of button
+		if(evt.charOrCode == dojo.keys[this.isLeftToRight() ? "RIGHT_ARROW" : "LEFT_ARROW"]){
+			dijit.focus(this._popupStateNode);
+			dojo.stopEvent(evt);
+		}
+	},
+
+	_onArrowKeyPress: function(/*Event*/ evt){
+		// summary:
+		//		Handler for left arrow key when focus is on right part of button
+		if(evt.charOrCode == dojo.keys[this.isLeftToRight() ? "LEFT_ARROW" : "RIGHT_ARROW"]){
+			dijit.focus(this.titleNode);
+			dojo.stopEvent(evt);
+		}
+	},
+	
+	focus: function(/*String*/ position){
+		// summary:
+		//		Focuses this widget to according to position, if specified,
+		//		otherwise on arrow node
+		// position:
+		//		"start" or "end"
+		
+		dijit.focus(position == "start" ? this.titleNode : this._popupStateNode);
+	}
+});
+
+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.set('checked', !this.checked);
+	},
+
+	_setCheckedAttr: function(/*Boolean*/ value, /* Boolean? */ priorityChange){
+		this.checked = value;
+		dojo.attr(this.focusNode || this.domNode, "checked", value);
+		dijit.setWaiState(this.focusNode || this.domNode, "pressed", value);
+		this._handleOnChange(value, priorityChange);
+	},
+
+	setChecked: function(/*Boolean*/ checked){
+		// summary:
+		//		Deprecated.   Use set('checked', true/false) instead.
+		dojo.deprecated("setChecked("+checked+") is deprecated. Use set('checked',"+checked+") instead.", "", "2.0");
+		this.set('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.set('checked', this.params.checked || false);
+	}
 });
-}
-}
-},_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;
-},_onButtonKeyPress:function(evt){
-if(evt.charOrCode==dojo.keys[this.isLeftToRight()?"RIGHT_ARROW":"LEFT_ARROW"]){
-dijit.focus(this._popupStateNode);
-dojo.stopEvent(evt);
-}
-},_onArrowKeyPress:function(evt){
-if(evt.charOrCode==dojo.keys[this.isLeftToRight()?"LEFT_ARROW":"RIGHT_ARROW"]){
-dijit.focus(this.titleNode);
-dojo.stopEvent(evt);
-}
-},focus:function(_10){
-dijit.focus(_10=="start"?this.titleNode:this._popupStateNode);
-}});
-dojo.declare("dijit.form.ToggleButton",dijit.form.Button,{baseClass:"dijitToggleButton",checked:false,attributeMap:dojo.mixin(dojo.clone(dijit.form.Button.prototype.attributeMap),{checked:"focusNode"}),_clicked:function(evt){
-this.attr("checked",!this.checked);
-},_setCheckedAttr:function(_11){
-this.checked=_11;
-dojo.attr(this.focusNode||this.domNode,"checked",_11);
-dijit.setWaiState(this.focusNode||this.domNode,"pressed",_11);
-this._setStateClass();
-this._handleOnChange(_11,true);
-},setChecked:function(_12){
-dojo.deprecated("setChecked("+_12+") is deprecated. Use attr('checked',"+_12+") instead.","","2.0");
-this.attr("checked",_12);
-},reset:function(){
-this._hasBeenBlurred=false;
-this.attr("checked",this.params.checked||false);
-}});
-}
diff --git a/dijit/form/CheckBox.js b/dijit/form/CheckBox.js
index 93761e1..23e580e 100644
--- a/dijit/form/CheckBox.js
+++ b/dijit/form/CheckBox.js
@@ -1,75 +1,192 @@
-/*
-	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
-*/
+dojo.provide("dijit.form.CheckBox");
 
+dojo.require("dijit.form.ToggleButton");
 
-if(!dojo._hasResource["dijit.form.CheckBox"]){
-dojo._hasResource["dijit.form.CheckBox"]=true;
-dojo.provide("dijit.form.CheckBox");
-dojo.require("dijit.form.Button");
-dojo.declare("dijit.form.CheckBox",dijit.form.ToggleButton,{templateString:dojo.cache("dijit.form","templates/CheckBox.html","<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:"checkbox",value:"o [...]
-this.readOnly=_1;
-dojo.attr(this.focusNode,"readOnly",_1);
-dijit.setWaiState(this.focusNode,"readonly",_1);
-this._setStateClass();
-},_setValueAttr:function(_2){
-if(typeof _2=="string"){
-this.value=_2;
-dojo.attr(this.focusNode,"value",_2);
-_2=true;
-}
-if(this._created){
-this.attr("checked",_2);
-}
-},_getValueAttr:function(){
-return (this.checked?this.value:false);
-},postMixInProperties:function(){
-if(this.value==""){
-this.value="on";
-}
-this.checkedAttrSetting=this.checked?"checked":"";
-this.inherited(arguments);
-},_fillContent:function(_3){
-},reset:function(){
-this._hasBeenBlurred=false;
-this.attr("checked",this.params.checked||false);
-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");
-}
-},_onClick:function(e){
-if(this.readOnly){
-return false;
-}
-return this.inherited(arguments);
-}});
-dojo.declare("dijit.form.RadioButton",dijit.form.CheckBox,{type:"radio",baseClass:"dijitRadio",_setCheckedAttr:function(_4){
-this.inherited(arguments);
-if(!this._created){
-return;
-}
-if(_4){
-var _5=this;
-dojo.query("INPUT[type=radio]",this.focusNode.form||dojo.doc).forEach(function(_6){
-if(_6.name==_5.name&&_6!=_5.focusNode&&_6.form==_5.focusNode.form){
-var _7=dijit.getEnclosingWidget(_6);
-if(_7&&_7.checked){
-_7.attr("checked",false);
-}
-}
-});
-}
-},_clicked:function(e){
-if(!this.checked){
-this.attr("checked",true);
-}
-}});
-}
+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: dojo.cache("dijit.form", "templates/CheckBox.html"),
+
+		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",
+
+		// 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,
+		
+		// the attributeMap should inherit from dijit.form._FormWidget.prototype.attributeMap 
+		// instead of ToggleButton as the icon mapping has no meaning for a CheckBox
+		attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
+			readOnly: "focusNode"
+		}),
+
+		_setReadOnlyAttr: function(/*Boolean*/ value){
+			this.readOnly = value;
+			dojo.attr(this.focusNode, 'readOnly', value);
+			dijit.setWaiState(this.focusNode, "readonly", value);
+		},
+
+		_setValueAttr: function(/*String or Boolean*/ newValue, /*Boolean*/ priorityChange){
+			// 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.set('checked', newValue, priorityChange);
+			}
+		},
+		_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);
+		},
+
+		// Override dijit.form.Button._setLabelAttr() since we don't even have a containerNode.
+		// Normally users won't try to set label, except when CheckBox or RadioButton is the child of a dojox.layout.TabContainer
+		_setLabelAttr: undefined,
+
+		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.set('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");
+			}
+			this.inherited(arguments);
+		},
+
+		_onBlur: function(){
+			if(this.id){
+				dojo.query("label[for='"+this.id+"']").removeClass("dijitFocusedLabel");
+			}
+			this.inherited(arguments);
+		},
+
+		_onClick: function(/*Event*/ e){
+			// summary:
+			//		Internal function to handle click actions - need to check
+			//		readOnly, since button no longer does that check.
+			if(this.readOnly){
+				return false;
+			}
+			return this.inherited(arguments);
+		}
+	}
+);
+
+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.set('checked', false);
+							}
+						}
+					}
+				);
+			}
+		},
+
+		_clicked: function(/*Event*/ e){
+			if(!this.checked){
+				this.set('checked', true);
+			}
+		}
+	}
+);
diff --git a/dijit/form/ComboBox.js b/dijit/form/ComboBox.js
index 5e2bff1..6073827 100644
--- a/dijit/form/ComboBox.js
+++ b/dijit/form/ComboBox.js
@@ -1,604 +1,1248 @@
-/*
-	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
-*/
+dojo.provide("dijit.form.ComboBox");
 
+dojo.require("dojo.window");
+dojo.require("dojo.regexp");
+dojo.require("dojo.data.util.simpleFetch");
+dojo.require("dojo.data.util.filter");
+dojo.require("dijit._CssStateMixin");
 
-if(!dojo._hasResource["dijit.form.ComboBox"]){
-dojo._hasResource["dijit.form.ComboBox"]=true;
-dojo.provide("dijit.form.ComboBox");
 dojo.require("dijit.form._FormWidget");
 dojo.require("dijit.form.ValidationTextBox");
-dojo.require("dojo.data.util.simpleFetch");
-dojo.require("dojo.data.util.filter");
-dojo.require("dojo.regexp");
-dojo.requireLocalization("dijit.form","ComboBox",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit.form.ComboBoxMixin",null,{item:null,pageSize:Infinity,store:null,fetchProperties:{},query:{},autoComplete:true,highlightMatch:"first",searchDelay:100,searchAttr:"name",labelAttr:"",labelType:"text",queryExpr:"${0}*",ignoreCase:true,hasDownArrow:true,templateString:dojo.cache("dijit.form","templates/ComboBox.html","<div class=\"dijit dijitReset dijitInlineTable dijitLeft\"\n\tid=\"widget_${id}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedo [...]
-var _2=0;
-if(typeof (_1.selectionStart)=="number"){
-_2=_1.selectionStart;
-}else{
-if(dojo.isIE){
-var tr=dojo.doc.selection.createRange().duplicate();
-var _3=_1.createTextRange();
-tr.move("character",0);
-_3.move("character",0);
-try{
-_3.setEndPoint("EndToEnd",tr);
-_2=String(_3.text).replace(/\r/g,"").length;
-}
-catch(e){
-}
-}
-}
-return _2;
-},_setCaretPos:function(_4,_5){
-_5=parseInt(_5);
-dijit.selectInputText(_4,_5,_5);
-},_setDisabledAttr:function(_6){
-this.inherited(arguments);
-dijit.setWaiState(this.comboNode,"disabled",_6);
-},_abortQuery:function(){
-if(this.searchTimer){
-clearTimeout(this.searchTimer);
-this.searchTimer=null;
-}
-if(this._fetchHandle){
-if(this._fetchHandle.abort){
-this._fetchHandle.abort();
-}
-this._fetchHandle=null;
-}
-},_onKeyPress:function(_7){
-var _8=_7.charOrCode;
-if(_7.altKey||((_7.ctrlKey||_7.metaKey)&&(_8!="x"&&_8!="v"))||_8==dojo.keys.SHIFT){
-return;
-}
-var _9=false;
-var _a="_startSearchFromInput";
-var pw=this._popupWidget;
-var dk=dojo.keys;
-var _b=null;
-this._prev_key_backspace=false;
-this._abortQuery();
-if(this._isShowingNow){
-pw.handleKey(_8);
-_b=pw.getHighlightedOption();
-}
-switch(_8){
-case dk.PAGE_DOWN:
-case dk.DOWN_ARROW:
-case dk.PAGE_UP:
-case dk.UP_ARROW:
-if(!this._isShowingNow){
-this._arrowPressed();
-_9=true;
-_a="_startSearchAll";
-}else{
-this._announceOption(_b);
-}
-dojo.stopEvent(_7);
-break;
-case dk.ENTER:
-if(_b){
-if(_b==pw.nextButton){
-this._nextSearch(1);
-dojo.stopEvent(_7);
-break;
-}else{
-if(_b==pw.previousButton){
-this._nextSearch(-1);
-dojo.stopEvent(_7);
-break;
-}
-}
-}else{
-this._setBlurValue();
-this._setCaretPos(this.focusNode,this.focusNode.value.length);
-}
-_7.preventDefault();
-case dk.TAB:
-var _c=this.attr("displayedValue");
-if(pw&&(_c==pw._messages["previousMessage"]||_c==pw._messages["nextMessage"])){
-break;
-}
-if(_b){
-this._selectOption();
-}
-if(this._isShowingNow){
-this._lastQuery=null;
-this._hideResultList();
-}
-break;
-case " ":
-if(_b){
-dojo.stopEvent(_7);
-this._selectOption();
-this._hideResultList();
-}else{
-_9=true;
-}
-break;
-case dk.ESCAPE:
-if(this._isShowingNow){
-dojo.stopEvent(_7);
-this._hideResultList();
-}
-break;
-case dk.DELETE:
-case dk.BACKSPACE:
-this._prev_key_backspace=true;
-_9=true;
-break;
-default:
-_9=typeof _8=="string"||_8==229;
-}
-if(_9){
-this.item=undefined;
-this.searchTimer=setTimeout(dojo.hitch(this,_a),1);
-}
-},_autoCompleteText:function(_d){
-var fn=this.focusNode;
-dijit.selectInputText(fn,fn.value.length);
-var _e=this.ignoreCase?"toLowerCase":"substr";
-if(_d[_e](0).indexOf(this.focusNode.value[_e](0))==0){
-var _f=this._getCaretPos(fn);
-if((_f+1)>fn.value.length){
-fn.value=_d;
-dijit.selectInputText(fn,_f);
-}
-}else{
-fn.value=_d;
-dijit.selectInputText(fn);
-}
-},_openResultList:function(_10,_11){
-this._fetchHandle=null;
-if(this.disabled||this.readOnly||(_11.query[this.searchAttr]!=this._lastQuery)){
-return;
-}
-this._popupWidget.clearResultList();
-if(!_10.length){
-this._hideResultList();
-return;
-}
-_11._maxOptions=this._maxOptions;
-var _12=this._popupWidget.createOptions(_10,_11,dojo.hitch(this,"_getMenuLabelFromItem"));
-this._showResultList();
-if(_11.direction){
-if(1==_11.direction){
-this._popupWidget.highlightFirstOption();
-}else{
-if(-1==_11.direction){
-this._popupWidget.highlightLastOption();
-}
-}
-this._announceOption(this._popupWidget.getHighlightedOption());
-}else{
-if(this.autoComplete&&!this._prev_key_backspace&&!/^[*]+$/.test(_11.query[this.searchAttr])){
-this._announceOption(_12[1]);
-}
-}
-},_showResultList:function(){
-this._hideResultList();
-this._arrowPressed();
-this.displayMessage("");
-dojo.style(this._popupWidget.domNode,{width:"",height:""});
-var _13=this.open();
-var _14=dojo.marginBox(this._popupWidget.domNode);
-this._popupWidget.domNode.style.overflow=((_13.h==_14.h)&&(_13.w==_14.w))?"hidden":"auto";
-var _15=_13.w;
-if(_13.h<this._popupWidget.domNode.scrollHeight){
-_15+=16;
-}
-dojo.marginBox(this._popupWidget.domNode,{h:_13.h,w:Math.max(_15,this.domNode.offsetWidth)});
-if(_15<this.domNode.offsetWidth){
-this._popupWidget.domNode.parentNode.style.left=dojo.position(this.domNode).x+"px";
-}
-dijit.setWaiState(this.comboNode,"expanded","true");
-},_hideResultList:function(){
-this._abortQuery();
-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(){
-var _16=this.attr("displayedValue");
-var pw=this._popupWidget;
-if(pw&&(_16==pw._messages["previousMessage"]||_16==pw._messages["nextMessage"])){
-this._setValueAttr(this._lastValueReported,true);
-}else{
-if(typeof this.item=="undefined"){
-this.item=null;
-this.attr("displayedValue",_16);
-}else{
-if(this.value!=this._lastValueReported){
-dijit.form._FormValueWidget.prototype._setValueAttr.call(this,this.value,true);
-}
-this._refreshState();
-}
-}
-},_onBlur:function(){
-this._hideResultList();
-this._arrowIdle();
-this.inherited(arguments);
-},_setItemAttr:function(_17,_18,_19){
-if(!_19){
-_19=this.labelFunc(_17,this.store);
-}
-this.value=this._getValueField()!=this.searchAttr?this.store.getIdentity(_17):_19;
-this.item=_17;
-dijit.form.ComboBox.superclass._setValueAttr.call(this,this.value,_18,_19);
-},_announceOption:function(_1a){
-if(!_1a){
-return;
-}
-var _1b;
-if(_1a==this._popupWidget.nextButton||_1a==this._popupWidget.previousButton){
-_1b=_1a.innerHTML;
-this.item=undefined;
-this.value="";
-}else{
-_1b=this.labelFunc(_1a.item,this.store);
-this.attr("item",_1a.item,false,_1b);
-}
-this.focusNode.value=this.focusNode.value.substring(0,this._lastInput.length);
-dijit.setWaiState(this.focusNode,"activedescendant",dojo.attr(_1a,"id"));
-this._autoCompleteText(_1b);
-},_selectOption:function(evt){
-if(evt){
-this._announceOption(evt.target);
-}
-this._hideResultList();
-this._setCaretPos(this.focusNode,this.focusNode.value.length);
-dijit.form._FormValueWidget.prototype._setValueAttr.call(this,this.value,true);
-},_onArrowMouseDown:function(evt){
-if(this.disabled||this.readOnly){
-return;
-}
-dojo.stopEvent(evt);
-this.focus();
-if(this._isShowingNow){
-this._hideResultList();
-}else{
-this._startSearchAll();
-}
-},_startSearchAll:function(){
-this._startSearch("");
-},_startSearchFromInput:function(){
-this._startSearch(this.focusNode.value.replace(/([\\\*\?])/g,"\\$1"));
-},_getQueryString:function(_1c){
-return dojo.string.substitute(this.queryExpr,[_1c]);
-},_startSearch:function(key){
-if(!this._popupWidget){
-var _1d=this.id+"_popup";
-this._popupWidget=new dijit.form._ComboBoxMenu({onChange:dojo.hitch(this,this._selectOption),id:_1d});
-dijit.removeWaiState(this.focusNode,"activedescendant");
-dijit.setWaiState(this.textbox,"owns",_1d);
-}
-var _1e=dojo.clone(this.query);
-this._lastInput=key;
-this._lastQuery=_1e[this.searchAttr]=this._getQueryString(key);
-this.searchTimer=setTimeout(dojo.hitch(this,function(_1f,_20){
-this.searchTimer=null;
-var _21={queryOptions:{ignoreCase:this.ignoreCase,deep:true},query:_1f,onBegin:dojo.hitch(this,"_setMaxOptions"),onComplete:dojo.hitch(this,"_openResultList"),onError:function(_22){
-_20._fetchHandle=null;
-console.error("dijit.form.ComboBox: "+_22);
-dojo.hitch(_20,"_hideResultList")();
-},start:0,count:this.pageSize};
-dojo.mixin(_21,_20.fetchProperties);
-this._fetchHandle=_20.store.fetch(_21);
-var _23=function(_24,_25){
-_24.start+=_24.count*_25;
-_24.direction=_25;
-this._fetchHandle=this.store.fetch(_24);
-};
-this._nextSearch=this._popupWidget.onPage=dojo.hitch(this,_23,this._fetchHandle);
-},_1e,this),this.searchDelay);
-},_setMaxOptions:function(_26,_27){
-this._maxOptions=_26;
-},_getValueField:function(){
-return this.searchAttr;
-},_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");
-}
-},compositionend:function(evt){
-this._onKeyPress({charOrCode:229});
-},constructor:function(){
-this.query={};
-this.fetchProperties={};
-},postMixInProperties:function(){
-if(!this.hasDownArrow){
-this.baseClass="dijitTextBox";
-}
-if(!this.store){
-var _28=this.srcNodeRef;
-this.store=new dijit.form._ComboBoxDataStore(_28);
-if(!this.value||((typeof _28.selectedIndex=="number")&&_28.selectedIndex.toString()===this.value)){
-var _29=this.store.fetchSelectedItem();
-if(_29){
-var _2a=this._getValueField();
-this.value=_2a!=this.searchAttr?this.store.getValue(_29,_2a):this.labelFunc(_29,this.store);
-}
-}
-}
-this.inherited(arguments);
-},postCreate:function(){
-var _2b=dojo.query("label[for=\""+this.id+"\"]");
-if(_2b.length){
-_2b[0].id=(this.id+"_label");
-var cn=this.comboNode;
-dijit.setWaiState(cn,"labelledby",_2b[0].id);
-}
-this.inherited(arguments);
-},uninitialize:function(){
-if(this._popupWidget&&!this._popupWidget._destroyed){
-this._hideResultList();
-this._popupWidget.destroy();
-}
-this.inherited(arguments);
-},_getMenuLabelFromItem:function(_2c){
-var _2d=this.labelAttr?this.store.getValue(_2c,this.labelAttr):this.labelFunc(_2c,this.store);
-var _2e=this.labelType;
-if(this.highlightMatch!="none"&&this.labelType=="text"&&this._lastInput){
-_2d=this.doHighlight(_2d,this._escapeHtml(this._lastInput));
-_2e="html";
-}
-return {html:_2e=="html",label:_2d};
-},doHighlight:function(_2f,_30){
-var _31="i"+(this.highlightMatch=="all"?"g":"");
-var _32=this._escapeHtml(_2f);
-_30=dojo.regexp.escapeString(_30);
-var ret=_32.replace(new RegExp("(^|\\s)("+_30+")",_31),"$1<span class=\"dijitComboBoxHighlightMatch\">$2</span>");
-return ret;
-},_escapeHtml:function(str){
-str=String(str).replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,""");
-return str;
-},open:function(){
-this._isShowingNow=true;
-return dijit.popup.open({popup:this._popupWidget,around:this.domNode,parent:this});
-},reset:function(){
-this.item=null;
-this.inherited(arguments);
-},labelFunc:function(_33,_34){
-return _34.getValue(_33,this.searchAttr).toString();
-}});
-dojo.declare("dijit.form._ComboBoxMenu",[dijit._Widget,dijit._Templated],{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' waiRo [...]
-this._messages=dojo.i18n.getLocalization("dijit.form","ComboBox",this.lang);
-this.inherited(arguments);
-},_setValueAttr:function(_35){
-this.value=_35;
-this.onChange(_35);
-},onChange:function(_36){
-},onPage:function(_37){
-},postCreate:function(){
-this.previousButton.innerHTML=this._messages["previousMessage"];
-this.nextButton.innerHTML=this._messages["nextMessage"];
-this.inherited(arguments);
-},onClose:function(){
-this._blurOptionNode();
-},_createOption:function(_38,_39){
-var _3a=_39(_38);
-var _3b=dojo.doc.createElement("li");
-dijit.setWaiRole(_3b,"option");
-if(_3a.html){
-_3b.innerHTML=_3a.label;
-}else{
-_3b.appendChild(dojo.doc.createTextNode(_3a.label));
-}
-if(_3b.innerHTML==""){
-_3b.innerHTML=" ";
-}
-_3b.item=_38;
-return _3b;
-},createOptions:function(_3c,_3d,_3e){
-this.previousButton.style.display=(_3d.start==0)?"none":"";
-dojo.attr(this.previousButton,"id",this.id+"_prev");
-dojo.forEach(_3c,function(_3f,i){
-var _40=this._createOption(_3f,_3e);
-_40.className="dijitReset dijitMenuItem";
-dojo.attr(_40,"id",this.id+i);
-this.domNode.insertBefore(_40,this.nextButton);
-},this);
-var _41=false;
-if(_3d._maxOptions&&_3d._maxOptions!=-1){
-if((_3d.start+_3d.count)<_3d._maxOptions){
-_41=true;
-}else{
-if((_3d.start+_3d.count)>(_3d._maxOptions-1)){
-if(_3d.count==_3c.length){
-_41=true;
-}
-}
-}
-}else{
-if(_3d.count==_3c.length){
-_41=true;
-}
-}
-this.nextButton.style.display=_41?"":"none";
-dojo.attr(this.nextButton,"id",this.id+"_next");
-return this.domNode.childNodes;
-},clearResultList:function(){
-while(this.domNode.childNodes.length>2){
-this.domNode.removeChild(this.domNode.childNodes[this.domNode.childNodes.length-2]);
-}
-},_onMouseDown:function(evt){
-dojo.stopEvent(evt);
-},_onMouseUp:function(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(!tgt.item){
-tgt=tgt.parentNode;
-}
-this._setValueAttr({target:tgt},true);
-}
-}
-}
-},_onMouseOver:function(evt){
-if(evt.target===this.domNode){
-return;
-}
-var tgt=evt.target;
-if(!(tgt==this.previousButton||tgt==this.nextButton)){
-while(!tgt.item){
-tgt=tgt.parentNode;
-}
-}
-this._focusOptionNode(tgt);
-},_onMouseOut:function(evt){
-if(evt.target===this.domNode){
-return;
-}
-this._blurOptionNode();
-},_focusOptionNode:function(_42){
-if(this._highlighted_option!=_42){
-this._blurOptionNode();
-this._highlighted_option=_42;
-dojo.addClass(this._highlighted_option,"dijitMenuItemSelected");
-}
-},_blurOptionNode:function(){
-if(this._highlighted_option){
-dojo.removeClass(this._highlighted_option,"dijitMenuItemSelected");
-this._highlighted_option=null;
-}
-},_highlightNextOption:function(){
-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);
-}
-}
-dijit.scrollIntoView(this._highlighted_option);
-},highlightFirstOption:function(){
-this._focusOptionNode(this.domNode.firstChild.nextSibling);
-dijit.scrollIntoView(this._highlighted_option);
-},highlightLastOption:function(){
-this._focusOptionNode(this.domNode.lastChild.previousSibling);
-dijit.scrollIntoView(this._highlighted_option);
-},_highlightPrevOption:function(){
-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(up){
-var _43=0;
-var _44=this.domNode.scrollTop;
-var _45=dojo.style(this.domNode,"height");
-if(!this.getHighlightedOption()){
-this._highlightNextOption();
-}
-while(_43<_45){
-if(up){
-if(!this.getHighlightedOption().previousSibling||this._highlighted_option.previousSibling.style.display=="none"){
-break;
-}
-this._highlightPrevOption();
-}else{
-if(!this.getHighlightedOption().nextSibling||this._highlighted_option.nextSibling.style.display=="none"){
-break;
-}
-this._highlightNextOption();
-}
-var _46=this.domNode.scrollTop;
-_43+=(_46-_44)*(up?-1:1);
-_44=_46;
-}
-},pageUp:function(){
-this._page(true);
-},pageDown:function(){
-this._page(false);
-},getHighlightedOption:function(){
-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],{_setValueAttr:function(_47,_48,_49){
-this.item=null;
-if(!_47){
-_47="";
-}
-dijit.form.ValidationTextBox.prototype._setValueAttr.call(this,_47,_48,_49);
-}});
-dojo.declare("dijit.form._ComboBoxDataStore",null,{constructor:function(_4a){
-this.root=_4a;
-dojo.query("> option",_4a).forEach(function(_4b){
-_4b.innerHTML=dojo.trim(_4b.innerHTML);
-});
-},getValue:function(_4c,_4d,_4e){
-return (_4d=="value")?_4c.value:(_4c.innerText||_4c.textContent||"");
-},isItemLoaded:function(_4f){
-return true;
-},getFeatures:function(){
-return {"dojo.data.api.Read":true,"dojo.data.api.Identity":true};
-},_fetchItems:function(_50,_51,_52){
-if(!_50.query){
-_50.query={};
-}
-if(!_50.query.name){
-_50.query.name="";
-}
-if(!_50.queryOptions){
-_50.queryOptions={};
-}
-var _53=dojo.data.util.filter.patternToRegExp(_50.query.name,_50.queryOptions.ignoreCase),_54=dojo.query("> option",this.root).filter(function(_55){
-return (_55.innerText||_55.textContent||"").match(_53);
+
+dojo.requireLocalization("dijit.form", "ComboBox");
+
+dojo.declare(
+	"dijit.form.ComboBoxMixin",
+	null,
+	{
+		// summary:
+		//		Implements the base functionality for `dijit.form.ComboBox`/`dijit.form.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 ComboBox, 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} }
+		//		To override the default queryOptions so that deep=false, do:
+		//	|	{ queryOptions: {ignoreCase: true, deep: false} }
+		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: [const] Boolean
+		//		Set this textbox to have a down arrow button, to display the drop down list.
+		//		Defaults to true.
+		hasDownArrow: true,
+
+		templateString: dojo.cache("dijit.form", "templates/ComboBox.html"),
+
+		baseClass: "dijitTextBox dijitComboBox",
+
+		// Set classes like dijitDownArrowButtonHover depending on
+		// mouse action over button node
+		cssStateNodes: {
+			"downArrowNode": "dijitDownArrowButton"
+		},
+
+		_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);
+		},
+
+		_abortQuery: function(){
+			// stop in-progress query
+			if(this.searchTimer){
+				clearTimeout(this.searchTimer);
+				this.searchTimer = null;
+			}
+			if(this._fetchHandle){
+				if(this._fetchHandle.abort){ this._fetchHandle.abort(); }
+				this._fetchHandle = null;
+			}
+		},
+
+		_onInput: function(/*Event*/ evt){
+			// summary:
+			//		Handles paste events
+			if(!this.searchTimer && (evt.type == 'paste'/*IE|WebKit*/ || evt.type == 'input'/*Firefox*/) && this._lastInput != this.textbox.value){
+				this.searchTimer = setTimeout(dojo.hitch(this, function(){
+					this._onKeyPress({charOrCode: 229}); // fake IME key to cause a search
+				}), 100); // long delay that will probably be preempted by keyboard input
+			}
+			this.inherited(arguments);
+		},
+
+		_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 || evt.metaKey) && (key != 'x' && key != 'v')) || key == dojo.keys.SHIFT){
+				return; // throw out weird key combinations and spurious events
+			}
+			var doSearch = false;
+			var searchFunction = "_startSearchFromInput";
+			var pw = this._popupWidget;
+			var dk = dojo.keys;
+			var highlighted = null;
+			this._prev_key_backspace = false;
+			this._abortQuery();
+			if(this._isShowingNow){
+				pw.handleKey(key);
+				highlighted = pw.getHighlightedOption();
+			}
+			switch(key){
+				case dk.PAGE_DOWN:
+				case dk.DOWN_ARROW:
+				case dk.PAGE_UP:
+				case dk.UP_ARROW:
+					if(!this._isShowingNow){
+						doSearch = true;
+						searchFunction = "_startSearchAll";
+					}else{
+						this._announceOption(highlighted);
+					}
+					dojo.stopEvent(evt);
+					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._setBlurValue(); // set value if needed
+						this._setCaretPos(this.focusNode, this.focusNode.value.length); // move cursor to end and cancel highlighting
+					}
+					// default case:
+					// prevent submit, but allow event to bubble
+					evt.preventDefault();
+					// fall through
+
+				case dk.TAB:
+					var newvalue = this.get('displayedValue');
+					//	if the user had More Choices selected fall into the
+					//	_onBlur handler
+					if(pw && (
+						newvalue == pw._messages["previousMessage"] ||
+						newvalue == pw._messages["nextMessage"])
+					){
+						break;
+					}
+					if(highlighted){
+						this._selectOption();
+					}
+					if(this._isShowingNow){
+						this._lastQuery = null; // in case results come back later
+						this._hideResultList();
+					}
+					break;
+
+				case ' ':
+					if(highlighted){
+						dojo.stopEvent(evt);
+						this._selectOption();
+						this._hideResultList();
+					}else{
+						doSearch = true;
+					}
+					break;
+
+				case dk.ESCAPE:
+					if(this._isShowingNow){
+						dojo.stopEvent(evt);
+						this._hideResultList();
+					}
+					break;
+
+				case dk.DELETE:
+				case dk.BACKSPACE:
+					this._prev_key_backspace = true;
+					doSearch = true;
+					break;
+
+				default:
+					// Non char keys (F1-F12 etc..)  shouldn't open list.
+					// Ascii characters and IME input (Chinese, Japanese etc.) should.
+					// On IE and safari, IME input produces keycode == 229, and we simulate
+					// it on firefox by attaching to compositionend event (see compositionend method)
+					doSearch = typeof key == 'string' || key == 229;
+			}
+			if(doSearch){
+				// need to wait a tad before start search so that the event
+				// bubbles through DOM and we have value visible
+				this.item = undefined; // undefined means item needs to be set
+				this.searchTimer = setTimeout(dojo.hitch(this, searchFunction),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){
+			this._fetchHandle = null;
+			if(	this.disabled ||
+				this.readOnly ||
+				(dataObject.query[this.searchAttr] != this._lastQuery)
+			){
+				return;
+			}
+			this._popupWidget.clearResultList();
+			if(!results.length && !this._maxOptions){ // this condition needs to match !this._isvalid set in FilteringSelect::_openResultList
+				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.
+
+			dataObject._maxOptions = this._maxOptions;
+			var nodes = 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());
+			}else if(this.autoComplete && !this._prev_key_backspace /*&& !dataObject.direction*/
+				// 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.
+				&& !/^[*]+$/.test(dataObject.query[this.searchAttr])){
+					this._announceOption(nodes[1]); // 1st real item
+			}
+		},
+
+		_showResultList: function(){
+			this._hideResultList();
+			// 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)
+			});
+			
+			// If we increased the width of drop down to match the width of ComboBox.domNode,
+			// then need to reposition the drop down (wrapper) so (all of) the drop down still
+			// appears underneath the ComboBox.domNode
+			if(newwidth < this.domNode.offsetWidth){
+				this._popupWidget.domNode.parentNode.style.left = dojo.position(this.domNode, true).x + "px";
+			}
+
+			dijit.setWaiState(this.comboNode, "expanded", "true");
+		},
+
+		_hideResultList: function(){
+			this._abortQuery();
+			if(this._isShowingNow){
+				dijit.popup.close(this._popupWidget);
+				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.get('displayedValue');
+			var pw = this._popupWidget;
+			if(pw && (
+				newvalue == pw._messages["previousMessage"] ||
+				newvalue == pw._messages["nextMessage"]
+				)
+			){
+				this._setValueAttr(this._lastValueReported, true);
+			}else if(typeof this.item == "undefined"){
+				// Update 'value' (ex: KY) according to currently displayed text
+				this.item = null;
+				this.set('displayedValue', newvalue);
+			}else{
+				if(this.value != this._lastValueReported){
+					dijit.form._FormValueWidget.prototype._setValueAttr.call(this, this.value, true);
+				}
+				this._refreshState();
+			}
+		},
+
+		_onBlur: function(){
+			// summary:
+			//		Called magically when focus has shifted away from this widget and it's drop down
+			this._hideResultList();
+			this.inherited(arguments);
+		},
+
+		_setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
+			// 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('item', value)
+			// tags:
+			//              private
+			if(!displayedValue){ displayedValue = this.labelFunc(item, this.store); }
+			this.value = this._getValueField() != this.searchAttr? this.store.getIdentity(item) : displayedValue;
+			this.item = item;
+			dijit.form.ComboBox.superclass._setValueAttr.call(this, this.value, priorityChange, displayedValue);
+		},
+
+		_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){
+				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;
+				this.item = undefined;
+				this.value = '';
+			}else{
+				newValue = this.labelFunc(node.item, this.store);
+				this.set('item', node.item, false, newValue);
+			}
+			// get the text that the user manually entered (cut off autocompleted text)
+			this.focusNode.value = this.focusNode.value.substring(0, this._lastInput.length);
+			// 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){
+			// summary:
+			//		Menu callback function, called when an item in the menu is selected.
+			if(evt){
+				this._announceOption(evt.target);
+			}
+			this._hideResultList();
+			this._setCaretPos(this.focusNode, this.focusNode.value.length);
+			dijit.form._FormValueWidget.prototype._setValueAttr.call(this, this.value, true); // set this.value and fire onChange
+		},
+
+		_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._startSearchAll();
+			}
+		},
+
+		_startSearchAll: function(){
+			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,
+					dir: this.dir
+				});
+				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
+			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){
+				this.searchTimer = null;
+				var fetch = {
+					queryOptions: {
+						ignoreCase: this.ignoreCase,
+						deep: true
+					},
+					query: query,
+					onBegin: dojo.hitch(this, "_setMaxOptions"),
+					onComplete: dojo.hitch(this, "_openResultList"),
+					onError: function(errText){
+						_this._fetchHandle = null;
+						console.error('dijit.form.ComboBox: ' + errText);
+						dojo.hitch(_this, "_hideResultList")();
+					},
+					start: 0,
+					count: this.pageSize
+				};
+				dojo.mixin(fetch, _this.fetchProperties);
+				this._fetchHandle = _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._fetchHandle = this.store.fetch(dataObject);
+				};
+				this._nextSearch = this._popupWidget.onPage = dojo.hitch(this, nextSearch, this._fetchHandle);
+			}, 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 /////////////////////
+
+		// 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/safari)
+			// tags:
+			//		private
+
+			// 229 is the code produced by IE and safari while pressing keys during
+			// IME input mode
+			this._onKeyPress({charOrCode: 229});
+		},
+
+		//////////// INITIALIZATION METHODS ///////////////////////////////////////
+
+		constructor: function(){
+			this.query={};
+			this.fetchProperties={};
+		},
+
+		postMixInProperties: function(){
+			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(!("value" in this.params)){
+					var item = this.store.fetchSelectedItem();
+					if(item){
+						var valueField = this._getValueField();
+						this.value = valueField != this.searchAttr? this.store.getValue(item, valueField) : this.labelFunc(item, this.store);
+					}
+				}
+			}
+			this.inherited(arguments);
+		},
+
+		postCreate: function(){
+			// summary:
+			//		Subclasses must call this method from their postCreate() methods
+			// tags:
+			//		protected
+
+			if(!this.hasDownArrow){
+				this.downArrowNode.style.display = "none";
+			}
+
+			// 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._popupWidget._destroyed){
+				this._hideResultList();
+				this._popupWidget.destroy();
+			}
+			this.inherited(arguments);
+		},
+
+		_getMenuLabelFromItem: function(/*Item*/ item){
+			var label = this.labelAttr? this.store.getValue(item, this.labelAttr) : this.labelFunc(item, this.store);
+			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, "&").replace(/</gm, "<")
+				.replace(/>/gm, ">").replace(/"/gm, """);
+			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);
+		},
+
+		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
+
+			// Use toString() because XMLStore returns an XMLItem whereas this
+			// method is expected to return a String (#9354)
+			return store.getValue(item, this.searchAttr).toString(); // String
+		}
+	}
+);
+
+dojo.declare(
+	"dijit.form._ComboBoxMenu",
+	[dijit._Widget, dijit._Templated, dijit._CssStateMixin],
+	{
+		// 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,
+		
+		baseClass: "dijitComboBoxMenu",
+
+		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 = " ";
+			}
+			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" +
+					(this.isLeftToRight() ? "" : " dijitMenuItemRtl");
+				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 && dataObject.count == results.length){
+					//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
+					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");
+			return this.domNode.childNodes;
+		},
+
+		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]);
+			}
+		},
+
+		_onMouseDown: function(/*Event*/ evt){
+			dojo.stopEvent(evt);
+		},
+
+		_onMouseUp: function(/*Event*/ evt){
+			if(evt.target === this.domNode || !this._highlighted_option){
+				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.
+			if(!this.getHighlightedOption()){
+				var fc = this.domNode.firstChild;
+				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);
+				}else{
+					this.highlightFirstOption();
+				}
+			}
+			// scrollIntoView is called outside of _focusOptionNode because in IE putting it inside causes the menu to scroll up on mouseover
+			dojo.window.scrollIntoView(this._highlighted_option);
+		},
+
+		highlightFirstOption: function(){
+			// summary:
+			// 		Highlight the first real item in the list (not Previous Choices).
+			var first = this.domNode.firstChild;
+			var second = first.nextSibling;
+			this._focusOptionNode(second.style.display == "none" ? first : second); // remotely possible that Previous Choices is the only thing in the list
+			dojo.window.scrollIntoView(this._highlighted_option);
+		},
+
+		highlightLastOption: function(){
+			// summary:
+			// 		Highlight the last real item in the list (not More Choices).
+			this._focusOptionNode(this.domNode.lastChild.previousSibling);
+			dojo.window.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).
+			if(!this.getHighlightedOption()){
+				var lc = this.domNode.lastChild;
+				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);
+				}else{
+					this.highlightLastOption();
+				}
+			}
+			dojo.window.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, /*String?*/ displayedValue){
+			// summary:
+			//		Hook so attr('value', value) works.
+			// description:
+			//		Sets the value of the select.
+			this.item = null; // value not looked up in store
+			if(!value){ value = ''; } // null translates to blank
+			dijit.form.ValidationTextBox.prototype._setValueAttr.call(this, value, priorityChange, displayedValue);
+		}
+	}
+);
+
+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;
+		if(root.tagName != "SELECT" && root.firstChild){
+			root = dojo.query("select", root);
+			if(root.length > 0){ // SELECT is a child of srcNodeRef
+				root = root[0];
+			}else{ // no select, so create 1 to parent the option tags to define selectedIndex
+				this.root.innerHTML = "<SELECT>"+this.root.innerHTML+"</SELECT>";
+				root = this.root.firstChild;
+			}
+			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 typeof si == "number"
+			? dojo.query("> option:nth-child(" + (si != -1 ? si+1 : 1) + ")", root)[0]
+			: null;	// dojo.data.Item
+	}
 });
-if(_50.sort){
-_54.sort(dojo.data.util.sorter.createSortFunction(_50.sort,this));
-}
-_51(_54,_50);
-},close:function(_56){
-return;
-},getLabel:function(_57){
-return _57.innerHTML;
-},getIdentity:function(_58){
-return dojo.attr(_58,"value");
-},fetchItemByIdentity:function(_59){
-var _5a=dojo.query("option[value='"+_59.identity+"']",this.root)[0];
-_59.onItem(_5a);
-},fetchSelectedItem:function(){
-var _5b=this.root,si=_5b.selectedIndex;
-return dojo.query("> option:nth-child("+(si!=-1?si+1:1)+")",_5b)[0];
-}});
+//Mix in the simple fetch implementation to this class.
 dojo.extend(dijit.form._ComboBoxDataStore,dojo.data.util.simpleFetch);
-}
diff --git a/dijit/form/ComboButton.js b/dijit/form/ComboButton.js
index c073e90..fc98c1b 100644
--- a/dijit/form/ComboButton.js
+++ b/dijit/form/ComboButton.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.ComboButton"]){
-dojo._hasResource["dijit.form.ComboButton"]=true;
 dojo.provide("dijit.form.ComboButton");
 dojo.require("dijit.form.Button");
-}
diff --git a/dijit/form/CurrencyTextBox.js b/dijit/form/CurrencyTextBox.js
index 412885d..6cec892 100644
--- a/dijit/form/CurrencyTextBox.js
+++ b/dijit/form/CurrencyTextBox.js
@@ -1,25 +1,83 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.CurrencyTextBox"]){
-dojo._hasResource["dijit.form.CurrencyTextBox"]=true;
 dojo.provide("dijit.form.CurrencyTextBox");
+
 dojo.require("dojo.currency");
 dojo.require("dijit.form.NumberTextBox");
-dojo.declare("dijit.form.CurrencyTextBox",dijit.form.NumberTextBox,{currency:"",regExpGen:function(_1){
-return "("+(this._focused?this.inherited(arguments,[dojo.mixin({},_1,this.editOptions)])+"|":"")+dojo.currency.regexp(_1)+")";
-},_formatter:dojo.currency.format,parse:function(_2,_3){
-var v=dojo.currency.parse(_2,_3);
-if(isNaN(v)&&/\d+/.test(_2)){
-return this.inherited(arguments,[_2,dojo.mixin({},_3,this.editOptions)]);
-}
-return v;
-},postMixInProperties:function(){
-this.constraints=dojo.currency._mixInDefaults(dojo.mixin(this.constraints,{currency:this.currency,exponent:false}));
-this.inherited(arguments);
-}});
-}
+
+/*=====
+dojo.declare(
+	"dijit.form.CurrencyTextBox.__Constraints",
+	[dijit.form.NumberTextBox.__Constraints, dojo.currency.__FormatOptions, dojo.currency.__ParseOptions], {
+	// summary:
+	//		Specifies both the rules on valid/invalid values (minimum, maximum,
+	//		number of required decimal places), and also formatting options for
+	//		displaying the value when the field is not focused (currency symbol,
+	//		etc.)
+	// description:
+	//		Follows the pattern of `dijit.form.NumberTextBox.constraints`.
+	//		In general developers won't need to set this parameter
+	// example:
+	//		To ensure that the user types in the cents (for example, 1.00 instead of just 1):
+	//	|		{fractional:true}
+});
+=====*/
+
+dojo.declare(
+	"dijit.form.CurrencyTextBox",
+	dijit.form.NumberTextBox,
+	{
+		// summary:
+		//		A validating currency textbox
+		// description:
+		//		CurrencyTextBox is similar to `dijit.form.NumberTextBox` but has a few
+		//		extra features related to currency:
+		//
+		//		1. After specifying the currency type (american dollars, euros, etc.) it automatically
+		//			sets parse/format options such as how many decimal places to show.
+		//		2. The currency mark (dollar sign, euro mark, etc.) is displayed when the field is blurred
+		//			but erased during editing, so that the user can just enter a plain number.
+
+		// currency: [const] String
+		//		the [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD"
+		currency: "",
+
+		// constraints: dijit.form.CurrencyTextBox.__Constraints
+		//		Despite the name, this parameter specifies both constraints on the input
+		//		(including minimum/maximum allowed values) as well as
+		//		formatting options.   See `dijit.form.CurrencyTextBox.__Constraints` for details.
+		/*=====
+		constraints: {},
+		======*/
+		
+		baseClass: "dijitTextBox dijitCurrencyTextBox",
+
+		// Override regExpGen ValidationTextBox.regExpGen().... we use a reg-ex generating function rather
+		// than a straight regexp to deal with locale  (plus formatting options too?)
+		regExpGen: function(constraints){
+			// if focused, accept either currency data or NumberTextBox format
+			return '(' + (this._focused? this.inherited(arguments, [ dojo.mixin({}, constraints, this.editOptions) ]) + '|' : '')
+				+ dojo.currency.regexp(constraints) + ')';
+		},
+
+		// Override NumberTextBox._formatter to deal with currencies, ex: converts "123.45" to "$123.45"
+		_formatter: dojo.currency.format,
+
+		parse: function(/* String */ value, /* Object */ constraints){
+			// summary:
+			// 		Parses string value as a Currency, according to the constraints object
+			// tags:
+			// 		protected extension
+			var v = dojo.currency.parse(value, constraints);
+			if(isNaN(v) && /\d+/.test(value)){ // currency parse failed, but it could be because they are using NumberTextBox format so try its parse
+				return this.inherited(arguments, [ value, dojo.mixin({}, constraints, this.editOptions) ]);
+			}
+			return v;
+		},
+
+		_setConstraintsAttr: function(/* Object */ constraints){
+			if(!constraints.currency && this.currency){
+				constraints.currency = this.currency;
+			}
+			this.inherited(arguments, [ dojo.currency._mixInDefaults(dojo.mixin(constraints, { exponent: false })) ]); // get places
+		}
+	}
+);
diff --git a/dijit/form/DateTextBox.js b/dijit/form/DateTextBox.js
index 95e6c42..e03e9e7 100644
--- a/dijit/form/DateTextBox.js
+++ b/dijit/form/DateTextBox.js
@@ -1,14 +1,28 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.DateTextBox"]){
-dojo._hasResource["dijit.form.DateTextBox"]=true;
 dojo.provide("dijit.form.DateTextBox");
+
 dojo.require("dijit.Calendar");
 dojo.require("dijit.form._DateTimeTextBox");
-dojo.declare("dijit.form.DateTextBox",dijit.form._DateTimeTextBox,{baseClass:"dijitTextBox dijitDateTextBox",popupClass:"dijit.Calendar",_selector:"date",value:new Date("")});
-}
+
+dojo.declare(
+	"dijit.form.DateTextBox",
+	dijit.form._DateTimeTextBox,
+	{
+		// summary:
+		//		A validating, serializable, range-bound date text box with a drop down calendar
+		//
+		//		Example:
+		// |	new dijit.form.DateTextBox({value: new Date(2009, 0, 20)})
+		//
+		//		Example:
+		// |	<input dojotype='dijit.form.DateTextBox' value='2009-01-20'>
+
+		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.
+		//		If specified in markup, use the format specified in `dojo.date.stamp.fromISOString`
+		value: new Date("")	// value.toString()="NaN"
+	}
+);
diff --git a/dijit/form/DropDownButton.js b/dijit/form/DropDownButton.js
index 187c6b4..533532f 100644
--- a/dijit/form/DropDownButton.js
+++ b/dijit/form/DropDownButton.js
@@ -1,12 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.DropDownButton"]){
-dojo._hasResource["dijit.form.DropDownButton"]=true;
 dojo.provide("dijit.form.DropDownButton");
 dojo.require("dijit.form.Button");
-}
+
diff --git a/dijit/form/FilteringSelect.js b/dijit/form/FilteringSelect.js
index 4080463..42b5d77 100644
--- a/dijit/form/FilteringSelect.js
+++ b/dijit/form/FilteringSelect.js
@@ -1,86 +1,209 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.FilteringSelect"]){
-dojo._hasResource["dijit.form.FilteringSelect"]=true;
 dojo.provide("dijit.form.FilteringSelect");
+
 dojo.require("dijit.form.ComboBox");
-dojo.declare("dijit.form.FilteringSelect",[dijit.form.MappedTextBox,dijit.form.ComboBoxMixin],{_isvalid:true,required:true,_lastDisplayedValue:"",isValid:function(){
-return this._isvalid||(!this.required&&this.attr("displayedValue")=="");
-},_callbackSetLabel:function(_1,_2,_3){
-if((_2&&_2.query[this.searchAttr]!=this._lastQuery)||(!_2&&_1.length&&this.store.getIdentity(_1[0])!=this._lastQuery)){
-return;
-}
-if(!_1.length){
-this.valueNode.value="";
-dijit.form.TextBox.superclass._setValueAttr.call(this,"",_3||(_3===undefined&&!this._focused));
-this._isvalid=false;
-this.validate(this._focused);
-this.item=null;
-}else{
-this.attr("item",_1[0],_3);
-}
-},_openResultList:function(_4,_5){
-if(_5.query[this.searchAttr]!=this._lastQuery){
-return;
-}
-this._isvalid=_4.length!=0;
-this.validate(true);
-dijit.form.ComboBoxMixin.prototype._openResultList.apply(this,arguments);
-},_getValueAttr:function(){
-return this.valueNode.value;
-},_getValueField:function(){
-return "value";
-},_setValueAttr:function(_6,_7){
-if(!this._onChangeActive){
-_7=null;
-}
-this._lastQuery=_6;
-if(_6===null||_6===""){
-this._setDisplayedValueAttr("",_7);
-return;
-}
-var _8=this;
-this.store.fetchItemByIdentity({identity:_6,onItem:function(_9){
-_8._callbackSetLabel([_9],undefined,_7);
-}});
-},_setItemAttr:function(_a,_b,_c){
-this._isvalid=true;
-this.inherited(arguments);
-this.valueNode.value=this.value;
-this._lastDisplayedValue=this.textbox.value;
-},_getDisplayQueryString:function(_d){
-return _d.replace(/([\\\*\?])/g,"\\$1");
-},_setDisplayedValueAttr:function(_e,_f){
-if(!this._created){
-_f=false;
-}
-if(this.store){
-this._hideResultList();
-var _10=dojo.clone(this.query);
-this._lastQuery=_10[this.searchAttr]=this._getDisplayQueryString(_e);
-this.textbox.value=_e;
-this._lastDisplayedValue=_e;
-var _11=this;
-var _12={query:_10,queryOptions:{ignoreCase:this.ignoreCase,deep:true},onComplete:function(_13,_14){
-_11._fetchHandle=null;
-dojo.hitch(_11,"_callbackSetLabel")(_13,_14,_f);
-},onError:function(_15){
-_11._fetchHandle=null;
-console.error("dijit.form.FilteringSelect: "+_15);
-dojo.hitch(_11,"_callbackSetLabel")([],undefined,false);
-}};
-dojo.mixin(_12,this.fetchProperties);
-this._fetchHandle=this.store.fetch(_12);
-}
-},postMixInProperties:function(){
-this.inherited(arguments);
-this._isvalid=!this.required;
-},undo:function(){
-this.attr("displayedValue",this._lastDisplayedValue);
-}});
-}
+
+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 (default) 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.get('displayedValue') == ""); // #5974
+		},
+
+		_refreshState: function(){
+			if(!this.searchTimer){ // state will be refreshed after results are returned
+				this.inherited(arguments);
+			}
+		},
+
+		_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
+				//#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.set('item', 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;
+			}
+			if(this.item === undefined){ // item == undefined for keyboard search
+				this._isvalid = results.length != 0 || this._maxOptions != 0; // result.length==0 && maxOptions != 0 implies the nextChoices item selected but then the datastore returned 0 more entries
+				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.
+			// Use this.valueNode.value which isn't always set for other MappedTextBox widgets until blur
+			return this.valueNode.value;
+		},
+
+		_getValueField: function(){
+			// Overrides ComboBox._getValueField()
+			return "value";
+		},
+
+		_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;
+			this.store.fetchItemByIdentity({
+				identity: value,
+				onItem: function(item){
+					self._callbackSetLabel(item? [item] : [], undefined, priorityChange);
+				}
+			});
+		},
+
+		_setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
+			// 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('item', value)
+			// tags:
+			//		private
+			this._isvalid = true;
+			this.inherited(arguments);
+			this.valueNode.value = this.value;
+			this._lastDisplayedValue = this.textbox.value;
+		},
+
+		_getDisplayQueryString: function(/*String*/ text){
+			return text.replace(/([\\\*\?])/g, "\\$1");
+		},
+
+		_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){
+				this._hideResultList();
+				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] = this._getDisplayQueryString(label);
+				// 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){
+						_this._fetchHandle = null;
+						dojo.hitch(_this, "_callbackSetLabel")(result, dataObject, priorityChange);
+					},
+					onError: function(errText){
+						_this._fetchHandle = null;
+						console.error('dijit.form.FilteringSelect: ' + errText);
+						dojo.hitch(_this, "_callbackSetLabel")([], undefined, false);
+					}
+				};
+				dojo.mixin(fetch, this.fetchProperties);
+				this._fetchHandle = this.store.fetch(fetch);
+			}
+		},
+
+		postMixInProperties: function(){
+			this.inherited(arguments);
+			this._isvalid = !this.required;
+		},
+
+		undo: function(){
+			this.set('displayedValue', this._lastDisplayedValue);
+		}
+	}
+);
diff --git a/dijit/form/Form.js b/dijit/form/Form.js
index d9328d3..c04b3cf 100644
--- a/dijit/form/Form.js
+++ b/dijit/form/Form.js
@@ -1,62 +1,177 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.Form"]){
-dojo._hasResource["dijit.form.Form"]=true;
 dojo.provide("dijit.form.Form");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit.form._FormMixin");
-dojo.declare("dijit.form.Form",[dijit._Widget,dijit._Templated,dijit.form._FormMixin],{name:"",action:"",method:"",encType:"","accept-charset":"",accept:"",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(){
-this.nameAttrSetting=this.name?("name='"+this.name+"'"):"";
-this.inherited(arguments);
-},execute:function(_1){
-},onExecute:function(){
-},_setEncTypeAttr:function(_2){
-this.encType=_2;
-dojo.attr(this.domNode,"encType",_2);
-if(dojo.isIE){
-this.domNode.encoding=_2;
-}
-},postCreate:function(){
-if(dojo.isIE&&this.srcNodeRef&&this.srcNodeRef.attributes){
-var _3=this.srcNodeRef.attributes.getNamedItem("encType");
-if(_3&&!_3.specified&&(typeof _3.value=="string")){
-this.attr("encType",_3.value);
-}
-}
-this.inherited(arguments);
-},onReset:function(e){
-return true;
-},_onReset:function(e){
-var _4={returnValue:true,preventDefault:function(){
-this.returnValue=false;
-},stopPropagation:function(){
-},currentTarget:e.currentTarget,target:e.target};
-if(!(this.onReset(_4)===false)&&_4.returnValue){
-this.reset();
-}
-dojo.stopEvent(e);
-return false;
-},_onSubmit:function(e){
-var fp=dijit.form.Form.prototype;
-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){
-dojo.stopEvent(e);
-}
-},onSubmit:function(e){
-return this.isValid();
-},submit:function(){
-if(!(this.onSubmit()===false)){
-this.containerNode.submit();
-}
-}});
-}
+
+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').set('value', myObj);
+		//	|
+		//	|	myObj=dijit.byId('myForm').get('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.set('encType', item.value);
+				}
+			}
+			this.inherited(arguments);
+		},
+
+		reset: function(/*Event?*/ e){
+			// summary:
+			//		restores all widget values back to their init values,
+			//		calls onReset() which can cancel the reset by returning false
+
+			// 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 ? e.target : this.domNode, 
+				target: e ? e.target : this.domNode
+			};
+			// if return value is not exactly false, and haven't called preventDefault(), then reset
+			if(!(this.onReset(faux) === false) && faux.returnValue){
+				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){
+			this.reset(e);
+			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();
+			}
+		}
+	}
+);
diff --git a/dijit/form/HorizontalRule.js b/dijit/form/HorizontalRule.js
index 29f8e97..79312aa 100644
--- a/dijit/form/HorizontalRule.js
+++ b/dijit/form/HorizontalRule.js
@@ -1,38 +1,61 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.HorizontalRule"]){
-dojo._hasResource["dijit.form.HorizontalRule"]=true;
 dojo.provide("dijit.form.HorizontalRule");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.declare("dijit.form.HorizontalRule",[dijit._Widget,dijit._Templated],{templateString:"<div class=\"dijitRuleContainer dijitRuleContainerH\"></div>",count:3,container:"containerNode",ruleStyle:"",_positionPrefix:"<div class=\"dijitRuleMark dijitRuleMarkH\" style=\"left:",_positionSuffix:"%;",_suffix:"\"></div>",_genHTML:function(_1,_2){
-return this._positionPrefix+_1+this._positionSuffix+this.ruleStyle+this._suffix;
-},_isHorizontal:true,postCreate:function(){
-var _3;
-if(this.count==1){
-_3=this._genHTML(50,0);
-}else{
-var i;
-var _4=100/(this.count-1);
-if(!this._isHorizontal||this.isLeftToRight()){
-_3=this._genHTML(0,0);
-for(i=1;i<this.count-1;i++){
-_3+=this._genHTML(_4*i,i);
-}
-_3+=this._genHTML(100,this.count-1);
-}else{
-_3=this._genHTML(100,0);
-for(i=1;i<this.count-1;i++){
-_3+=this._genHTML(100-_4*i,i);
-}
-_3+=this._genHTML(0,this.count-1);
-}
-}
-this.domNode.innerHTML=_3;
-}});
-}
+
+dojo.declare("dijit.form.HorizontalRule", [dijit._Widget, dijit._Templated],
+{
+	// summary:
+	//		Hash marks for `dijit.form.HorizontalSlider`
+
+	templateString: '<div class="dijitRuleContainer dijitRuleContainerH"></div>',
+
+	// count: Integer
+	//		Number of hash marks to generate
+	count: 3,
+
+	// container: String
+	//		For HorizontalSlider, this is either "topDecoration" or "bottomDecoration",
+	//		and indicates whether this rule goes above or below the slider.
+	container: "containerNode",
+
+	// ruleStyle: String
+	//		CSS style to apply to individual hash marks
+	ruleStyle: "",
+
+	_positionPrefix: '<div class="dijitRuleMark dijitRuleMarkH" style="left:',
+	_positionSuffix: '%;',
+	_suffix: '"></div>',
+
+	_genHTML: function(pos, ndx){
+		return this._positionPrefix + pos + this._positionSuffix + this.ruleStyle + this._suffix;
+	},
+
+	// _isHorizontal: [protected extension] Boolean
+	//		VerticalRule will override this...
+	_isHorizontal: true,
+
+	postCreate: function(){
+		var innerHTML;
+		if(this.count == 1){
+			innerHTML = this._genHTML(50, 0);
+		}else{
+			var i;
+			var interval = 100 / (this.count-1);
+			if(!this._isHorizontal || this.isLeftToRight()){
+				innerHTML = this._genHTML(0, 0);
+				for(i=1; i < this.count-1; i++){
+					innerHTML += this._genHTML(interval*i, i);
+				}
+				innerHTML += this._genHTML(100, this.count-1);
+			}else{
+				innerHTML = this._genHTML(100, 0);
+				for(i=1; i < this.count-1; i++){
+					innerHTML += this._genHTML(100-interval*i, i);
+				}
+				innerHTML += this._genHTML(0, this.count-1);
+			}
+		}
+		this.domNode.innerHTML = innerHTML;
+	}
+});
diff --git a/dijit/form/HorizontalRuleLabels.js b/dijit/form/HorizontalRuleLabels.js
index 05c2bd7..e6f3c47 100644
--- a/dijit/form/HorizontalRuleLabels.js
+++ b/dijit/form/HorizontalRuleLabels.js
@@ -1,38 +1,88 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.HorizontalRuleLabels"]){
-dojo._hasResource["dijit.form.HorizontalRuleLabels"]=true;
 dojo.provide("dijit.form.HorizontalRuleLabels");
+
 dojo.require("dijit.form.HorizontalRule");
-dojo.declare("dijit.form.HorizontalRuleLabels",dijit.form.HorizontalRule,{templateString:"<div class=\"dijitRuleContainer dijitRuleContainerH dijitRuleLabelsContainer dijitRuleLabelsContainerH\"></div>",labelStyle:"",labels:[],numericMargin:0,minimum:0,maximum:1,constraints:{pattern:"#%"},_positionPrefix:"<div class=\"dijitRuleLabelContainer dijitRuleLabelContainerH\" style=\"left:",_labelPrefix:"\"><span class=\"dijitRuleLabel dijitRuleLabelH\">",_suffix:"</span></div>",_calcPosition:fu [...]
-return _1;
-},_genHTML:function(_2,_3){
-return this._positionPrefix+this._calcPosition(_2)+this._positionSuffix+this.labelStyle+this._labelPrefix+this.labels[_3]+this._suffix;
-},getLabels:function(){
-var _4=this.labels;
-if(!_4.length){
-_4=dojo.query("> li",this.srcNodeRef).map(function(_5){
-return String(_5.innerHTML);
+
+dojo.declare("dijit.form.HorizontalRuleLabels", dijit.form.HorizontalRule,
+{
+	// summary:
+	//		Labels for `dijit.form.HorizontalSlider`
+
+	templateString: '<div class="dijitRuleContainer dijitRuleContainerH dijitRuleLabelsContainer dijitRuleLabelsContainerH"></div>',
+
+	// labelStyle: String
+	//		CSS style to apply to individual text labels
+	labelStyle: "",
+
+	// labels: String[]?
+	//		Array of text labels to render - evenly spaced from left-to-right or bottom-to-top.
+	//		Alternately, minimum and maximum can be specified, to get numeric labels.
+	labels: [],
+
+	// numericMargin: Integer
+	//		Number of generated numeric labels that should be rendered as '' on the ends when labels[] are not specified
+	numericMargin: 0,
+
+	// numericMinimum: Integer
+	//		Leftmost label value for generated numeric labels when labels[] are not specified
+	minimum: 0,
+
+	// numericMaximum: Integer
+	//		Rightmost label value for generated numeric labels when labels[] are not specified
+	maximum: 1,
+
+	// constraints: Object
+	//		pattern, places, lang, et al (see dojo.number) for generated numeric labels when labels[] are not specified
+	constraints: {pattern:"#%"},
+
+	_positionPrefix: '<div class="dijitRuleLabelContainer dijitRuleLabelContainerH" style="left:',
+	_labelPrefix: '"><div class="dijitRuleLabel dijitRuleLabelH">',
+	_suffix: '</div></div>',
+
+	_calcPosition: function(pos){
+		// summary:
+		//		Returns the value to be used in HTML for the label as part of the left: attribute
+		// tags:
+		//		protected extension
+		return pos;
+	},
+
+	_genHTML: function(pos, ndx){
+		return this._positionPrefix + this._calcPosition(pos) + this._positionSuffix + this.labelStyle + this._labelPrefix + this.labels[ndx] + this._suffix;
+	},
+
+	getLabels: function(){
+		// summary:
+		//		Overridable function to return array of labels to use for this slider.
+		//		Can specify a getLabels() method instead of a labels[] array, or min/max attributes.
+		// tags:
+		//		protected extension
+
+		// if the labels array was not specified directly, then see if <li> children were
+		var labels = this.labels;
+		if(!labels.length){
+			// for markup creation, labels are specified as child elements
+			labels = dojo.query("> li", this.srcNodeRef).map(function(node){
+				return String(node.innerHTML);
+			});
+		}
+		this.srcNodeRef.innerHTML = '';
+		// if the labels were not specified directly and not as <li> children, then calculate numeric labels
+		if(!labels.length && this.count > 1){
+			var start = this.minimum;
+			var inc = (this.maximum - start) / (this.count-1);
+			for(var i=0; i < this.count; i++){
+				labels.push((i < this.numericMargin || i >= (this.count-this.numericMargin)) ? '' : dojo.number.format(start, this.constraints));
+				start += inc;
+			}
+		}
+		return labels;
+	},
+
+	postMixInProperties: function(){
+		this.inherited(arguments);
+		this.labels = this.getLabels();
+		this.count = this.labels.length;
+	}
 });
-}
-this.srcNodeRef.innerHTML="";
-if(!_4.length&&this.count>1){
-var _6=this.minimum;
-var _7=(this.maximum-_6)/(this.count-1);
-for(var i=0;i<this.count;i++){
-_4.push((i<this.numericMargin||i>=(this.count-this.numericMargin))?"":dojo.number.format(_6,this.constraints));
-_6+=_7;
-}
-}
-return _4;
-},postMixInProperties:function(){
-this.inherited(arguments);
-this.labels=this.getLabels();
-this.count=this.labels.length;
-}});
-}
+
+
diff --git a/dijit/form/HorizontalSlider.js b/dijit/form/HorizontalSlider.js
index 6fc4e56..2d5c66d 100644
--- a/dijit/form/HorizontalSlider.js
+++ b/dijit/form/HorizontalSlider.js
@@ -1,205 +1,326 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.HorizontalSlider"]){
-dojo._hasResource["dijit.form.HorizontalSlider"]=true;
 dojo.provide("dijit.form.HorizontalSlider");
+
 dojo.require("dijit.form._FormWidget");
 dojo.require("dijit._Container");
 dojo.require("dojo.dnd.move");
 dojo.require("dijit.form.Button");
 dojo.require("dojo.number");
 dojo.require("dojo._base.fx");
-dojo.declare("dijit.form.HorizontalSlider",[dijit.form._FormValueWidget,dijit._Container],{templateString:dojo.cache("dijit.form","templates/HorizontalSlider.html","<table class=\"dijit dijitReset dijitSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\" dojoAttachEvent=\"onkeypress:_onKeyPress,onkeyup:_onKeyUp\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td dojoAttachPoint=\"topDecoration\" class=\"dijitReset\" style=\"text- [...]
-if(this.disabled||this.readOnly||e.altKey||e.ctrlKey||e.metaKey){
-return;
-}
-this._setValueAttr(this.value,true);
-},_onKeyPress:function(e){
-if(this.disabled||this.readOnly||e.altKey||e.ctrlKey||e.metaKey){
-return;
-}
-switch(e.charOrCode){
-case dojo.keys.HOME:
-this._setValueAttr(this.minimum,false);
-break;
-case dojo.keys.END:
-this._setValueAttr(this.maximum,false);
-break;
-case ((this._descending||this.isLeftToRight())?dojo.keys.RIGHT_ARROW:dojo.keys.LEFT_ARROW):
-case (this._descending===false?dojo.keys.DOWN_ARROW:dojo.keys.UP_ARROW):
-case (this._descending===false?dojo.keys.PAGE_DOWN:dojo.keys.PAGE_UP):
-this.increment(e);
-break;
-case ((this._descending||this.isLeftToRight())?dojo.keys.LEFT_ARROW:dojo.keys.RIGHT_ARROW):
-case (this._descending===false?dojo.keys.UP_ARROW:dojo.keys.DOWN_ARROW):
-case (this._descending===false?dojo.keys.PAGE_UP:dojo.keys.PAGE_DOWN):
-this.decrement(e);
-break;
-default:
-return;
-}
-dojo.stopEvent(e);
-},_onHandleClick:function(e){
-if(this.disabled||this.readOnly){
-return;
-}
-if(!dojo.isIE){
-dijit.focus(this.sliderHandle);
-}
-dojo.stopEvent(e);
-},_isReversed:function(){
-return !this.isLeftToRight();
-},_onBarClick:function(e){
-if(this.disabled||this.readOnly||!this.clickSelect){
-return;
-}
-dijit.focus(this.sliderHandle);
-dojo.stopEvent(e);
-var _1=dojo.position(this.sliderBarContainer,true);
-var _2=e[this._mousePixelCoord]-_1[this._startingPixelCoord];
-this._setPixelValue(this._isReversed()?(_1[this._pixelCount]-_2):_2,_1[this._pixelCount],true);
-this._movable.onMouseDown(e);
-},_setPixelValue:function(_3,_4,_5){
-if(this.disabled||this.readOnly){
-return;
-}
-_3=_3<0?0:_4<_3?_4:_3;
-var _6=this.discreteValues;
-if(_6<=1||_6==Infinity){
-_6=_4;
-}
-_6--;
-var _7=_4/_6;
-var _8=Math.round(_3/_7);
-this._setValueAttr((this.maximum-this.minimum)*_8/_6+this.minimum,_5);
-},_setValueAttr:function(_9,_a){
-this.valueNode.value=this.value=_9;
-dijit.setWaiState(this.focusNode,"valuenow",_9);
-this.inherited(arguments);
-var _b=(_9-this.minimum)/(this.maximum-this.minimum);
-var _c=(this._descending===false)?this.remainingBar:this.progressBar;
-var _d=(this._descending===false)?this.progressBar:this.remainingBar;
-if(this._inProgressAnim&&this._inProgressAnim.status!="stopped"){
-this._inProgressAnim.stop(true);
-}
-if(_a&&this.slideDuration>0&&_c.style[this._progressPixelSize]){
-var _e=this;
-var _f={};
-var _10=parseFloat(_c.style[this._progressPixelSize]);
-var _11=this.slideDuration*(_b-_10/100);
-if(_11==0){
-return;
-}
-if(_11<0){
-_11=0-_11;
-}
-_f[this._progressPixelSize]={start:_10,end:_b*100,units:"%"};
-this._inProgressAnim=dojo.animateProperty({node:_c,duration:_11,onAnimate:function(v){
-_d.style[_e._progressPixelSize]=(100-parseFloat(v[_e._progressPixelSize]))+"%";
-},onEnd:function(){
-delete _e._inProgressAnim;
-},properties:_f});
-this._inProgressAnim.play();
-}else{
-_c.style[this._progressPixelSize]=(_b*100)+"%";
-_d.style[this._progressPixelSize]=((1-_b)*100)+"%";
-}
-},_bumpValue:function(_12,_13){
-if(this.disabled||this.readOnly){
-return;
-}
-var s=dojo.getComputedStyle(this.sliderBarContainer);
-var c=dojo._getContentBox(this.sliderBarContainer,s);
-var _14=this.discreteValues;
-if(_14<=1||_14==Infinity){
-_14=c[this._pixelCount];
-}
-_14--;
-var _15=(this.value-this.minimum)*_14/(this.maximum-this.minimum)+_12;
-if(_15<0){
-_15=0;
-}
-if(_15>_14){
-_15=_14;
-}
-_15=_15*(this.maximum-this.minimum)/_14+this.minimum;
-this._setValueAttr(_15,_13);
-},_onClkBumper:function(val){
-if(this.disabled||this.readOnly||!this.clickSelect){
-return;
-}
-this._setValueAttr(val,true);
-},_onClkIncBumper:function(){
-this._onClkBumper(this._descending===false?this.minimum:this.maximum);
-},_onClkDecBumper:function(){
-this._onClkBumper(this._descending===false?this.maximum:this.minimum);
-},decrement:function(e){
-this._bumpValue(e.charOrCode==dojo.keys.PAGE_DOWN?-this.pageIncrement:-1);
-},increment:function(e){
-this._bumpValue(e.charOrCode==dojo.keys.PAGE_UP?this.pageIncrement:1);
-},_mouseWheeled:function(evt){
-dojo.stopEvent(evt);
-var _16=!dojo.isMozilla;
-var _17=evt[(_16?"wheelDelta":"detail")]*(_16?1:-1);
-this._bumpValue(_17<0?-1:1,true);
-},startup:function(){
-dojo.forEach(this.getChildren(),function(_18){
-if(this[_18.container]!=this.containerNode){
-this[_18.container].appendChild(_18.domNode);
-}
-},this);
-},_typematicCallback:function(_19,_1a,e){
-if(_19==-1){
-this._setValueAttr(this.value,true);
-}else{
-this[(_1a==(this._descending?this.incrementButton:this.decrementButton))?"decrement":"increment"](e);
-}
-},postCreate:function(){
-if(this.showButtons){
-this.incrementButton.style.display="";
-this.decrementButton.style.display="";
-this._connects.push(dijit.typematic.addMouseListener(this.decrementButton,this,"_typematicCallback",25,500));
-this._connects.push(dijit.typematic.addMouseListener(this.incrementButton,this,"_typematicCallback",25,500));
-}
-this.connect(this.domNode,!dojo.isMozilla?"onmousewheel":"DOMMouseScroll","_mouseWheeled");
-var _1b=dojo.declare(dijit.form._SliderMover,{widget:this});
-this._movable=new dojo.dnd.Moveable(this.sliderHandle,{mover:_1b});
-var _1c=dojo.query("label[for=\""+this.id+"\"]");
-if(_1c.length){
-_1c[0].id=(this.id+"_label");
-dijit.setWaiState(this.focusNode,"labelledby",_1c[0].id);
-}
-dijit.setWaiState(this.focusNode,"valuemin",this.minimum);
-dijit.setWaiState(this.focusNode,"valuemax",this.maximum);
-this.inherited(arguments);
-this._layoutHackIE7();
-},destroy:function(){
-this._movable.destroy();
-if(this._inProgressAnim&&this._inProgressAnim.status!="stopped"){
-this._inProgressAnim.stop(true);
-}
-this._supportingWidgets=dijit.findWidgets(this.domNode);
-this.inherited(arguments);
-}});
-dojo.declare("dijit.form._SliderMover",dojo.dnd.Mover,{onMouseMove:function(e){
-var _1d=this.widget;
-var _1e=_1d._abspos;
-if(!_1e){
-_1e=_1d._abspos=dojo.position(_1d.sliderBarContainer,true);
-_1d._setPixelValue_=dojo.hitch(_1d,"_setPixelValue");
-_1d._isReversed_=_1d._isReversed();
-}
-var _1f=e[_1d._mousePixelCoord]-_1e[_1d._startingPixelCoord];
-_1d._setPixelValue_(_1d._isReversed_?(_1e[_1d._pixelCount]-_1f):_1f,_1e[_1d._pixelCount],false);
-},destroy:function(e){
-dojo.dnd.Mover.prototype.destroy.apply(this,arguments);
-var _20=this.widget;
-_20._abspos=null;
-_20._setValueAttr(_20.value,true);
-}});
-}
+
+dojo.declare(
+	"dijit.form.HorizontalSlider",
+	[dijit.form._FormValueWidget, dijit._Container],
+{
+	// summary:
+	//		A form widget that allows one to select a value with a horizontally draggable handle
+
+	templateString: dojo.cache('dijit.form','templates/HorizontalSlider.html'),
+
+	// Overrides FormValueWidget.value to indicate numeric value
+	value: 0,
+
+	// showButtons: Boolean
+	//		Show increment/decrement buttons at the ends of the slider?
+	showButtons: true,
+
+	// minimum:: Integer
+	//		The minimum value the slider can be set to.
+	minimum: 0,
+
+	// maximum: Integer
+	//		The maximum value the slider can be set to.
+	maximum: 100,
+
+	// discreteValues: Integer
+	//		If specified, indicates that the slider handle has only 'discreteValues' possible positions,
+	//      and that after dragging the handle, it will snap to the nearest possible position.
+	//      Thus, the slider has only 'discreteValues' possible values.
+	//
+	//		For example, if minimum=10, maxiumum=30, and discreteValues=3, then the slider handle has
+	//		three possible positions, representing values 10, 20, or 30.
+	//
+	//		If discreteValues is not specified or if it's value is higher than the number of pixels
+	//		in the slider bar, then the slider handle can be moved freely, and the slider's value will be
+	//		computed/reported based on pixel position (in this case it will likely be fractional,
+	//      such as 123.456789).
+	discreteValues: Infinity,
+
+	// pageIncrement: Integer
+	//		If discreteValues is also specified, this indicates the amount of clicks (ie, snap positions)
+	//      that the slider handle is moved via pageup/pagedown keys.
+	//	If discreteValues is not specified, it indicates the number of pixels.
+	pageIncrement: 2,
+
+	// clickSelect: Boolean
+	//		If clicking the slider bar changes the value or not
+	clickSelect: true,
+
+	// slideDuration: Number
+	//		The time in ms to take to animate the slider handle from 0% to 100%,
+	//		when clicking the slider bar to make the handle move.
+	slideDuration: dijit.defaultDuration,
+
+	// Flag to _Templated  (TODO: why is this here?   I see no widgets in the template.)
+	widgetsInTemplate: true,
+
+	attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
+		id: ""
+	}),
+
+	baseClass: "dijitSlider",
+
+	// Apply CSS classes to up/down arrows and handle per mouse state
+	cssStateNodes: {
+		incrementButton: "dijitSliderIncrementButton",
+		decrementButton: "dijitSliderDecrementButton",
+		focusNode: "dijitSliderThumb"
+	},
+
+	_mousePixelCoord: "pageX",
+	_pixelCount: "w",
+	_startingPixelCoord: "x",
+	_startingPixelCount: "l",
+	_handleOffsetCoord: "left",
+	_progressPixelSize: "width",
+
+	_onKeyUp: function(/*Event*/ e){
+		if(this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey){ return; }
+		this._setValueAttr(this.value, true);
+	},
+
+	_onKeyPress: function(/*Event*/ e){
+		if(this.disabled || this.readOnly || e.altKey || e.ctrlKey || e.metaKey){ return; }
+		switch(e.charOrCode){
+			case dojo.keys.HOME:
+				this._setValueAttr(this.minimum, false);
+				break;
+			case dojo.keys.END:
+				this._setValueAttr(this.maximum, false);
+				break;
+			// this._descending === false: if ascending vertical (min on top)
+			// (this._descending || this.isLeftToRight()): if left-to-right horizontal or descending vertical
+			case ((this._descending || this.isLeftToRight()) ? dojo.keys.RIGHT_ARROW : dojo.keys.LEFT_ARROW):
+			case (this._descending === false ? dojo.keys.DOWN_ARROW : dojo.keys.UP_ARROW):
+			case (this._descending === false ? dojo.keys.PAGE_DOWN : dojo.keys.PAGE_UP):
+				this.increment(e);
+				break;
+			case ((this._descending || this.isLeftToRight()) ? dojo.keys.LEFT_ARROW : dojo.keys.RIGHT_ARROW):
+			case (this._descending === false ? dojo.keys.UP_ARROW : dojo.keys.DOWN_ARROW):
+			case (this._descending === false ? dojo.keys.PAGE_UP : dojo.keys.PAGE_DOWN):
+				this.decrement(e);
+				break;
+			default:
+				return;
+		}
+		dojo.stopEvent(e);
+	},
+
+	_onHandleClick: function(e){
+		if(this.disabled || this.readOnly){ return; }
+		if(!dojo.isIE){
+			// make sure you get focus when dragging the handle
+			// (but don't do on IE because it causes a flicker on mouse up (due to blur then focus)
+			dijit.focus(this.sliderHandle);
+		}
+		dojo.stopEvent(e);
+	},
+
+	_isReversed: function(){
+		// summary:
+		//		Returns true if direction is from right to left
+		// tags:
+		//		protected extension
+		return !this.isLeftToRight();
+	},
+
+	_onBarClick: function(e){
+		if(this.disabled || this.readOnly || !this.clickSelect){ return; }
+		dijit.focus(this.sliderHandle);
+		dojo.stopEvent(e);
+		var abspos = dojo.position(this.sliderBarContainer, true);
+		var pixelValue = e[this._mousePixelCoord] - abspos[this._startingPixelCoord];
+		this._setPixelValue(this._isReversed() ? (abspos[this._pixelCount] - pixelValue) : pixelValue, abspos[this._pixelCount], true);
+		this._movable.onMouseDown(e);
+	},
+
+	_setPixelValue: function(/*Number*/ pixelValue, /*Number*/ maxPixels, /*Boolean, optional*/ priorityChange){
+		if(this.disabled || this.readOnly){ return; }
+		pixelValue = pixelValue < 0 ? 0 : maxPixels < pixelValue ? maxPixels : pixelValue;
+		var count = this.discreteValues;
+		if(count <= 1 || count == Infinity){ count = maxPixels; }
+		count--;
+		var pixelsPerValue = maxPixels / count;
+		var wholeIncrements = Math.round(pixelValue / pixelsPerValue);
+		this._setValueAttr((this.maximum-this.minimum)*wholeIncrements/count + this.minimum, priorityChange);
+	},
+
+	_setValueAttr: function(/*Number*/ value, /*Boolean, optional*/ priorityChange){
+		// summary:
+		//		Hook so attr('value', value) works.
+		this.valueNode.value = this.value = value;
+		dijit.setWaiState(this.focusNode, "valuenow", value);
+		this.inherited(arguments);
+		var percent = (value - this.minimum) / (this.maximum - this.minimum);
+		var progressBar = (this._descending === false) ? this.remainingBar : this.progressBar;
+		var remainingBar = (this._descending === false) ? this.progressBar : this.remainingBar;
+		if(this._inProgressAnim && this._inProgressAnim.status != "stopped"){
+			this._inProgressAnim.stop(true);
+		}
+		if(priorityChange && this.slideDuration > 0 && progressBar.style[this._progressPixelSize]){
+			// animate the slider
+			var _this = this;
+			var props = {};
+			var start = parseFloat(progressBar.style[this._progressPixelSize]);
+			var duration = this.slideDuration * (percent-start/100);
+			if(duration == 0){ return; }
+			if(duration < 0){ duration = 0 - duration; }
+			props[this._progressPixelSize] = { start: start, end: percent*100, units:"%" };
+			this._inProgressAnim = dojo.animateProperty({ node: progressBar, duration: duration,
+				onAnimate: function(v){ remainingBar.style[_this._progressPixelSize] = (100-parseFloat(v[_this._progressPixelSize])) + "%"; },
+				onEnd: function(){ delete _this._inProgressAnim; },
+				properties: props
+			})
+			this._inProgressAnim.play();
+		}
+		else{
+			progressBar.style[this._progressPixelSize] = (percent*100) + "%";
+			remainingBar.style[this._progressPixelSize] = ((1-percent)*100) + "%";
+		}
+	},
+
+	_bumpValue: function(signedChange, /*Boolean, optional*/ priorityChange){
+		if(this.disabled || this.readOnly){ return; }
+		var s = dojo.getComputedStyle(this.sliderBarContainer);
+		var c = dojo._getContentBox(this.sliderBarContainer, s);
+		var count = this.discreteValues;
+		if(count <= 1 || count == Infinity){ count = c[this._pixelCount]; }
+		count--;
+		var value = (this.value - this.minimum) * count / (this.maximum - this.minimum) + signedChange;
+		if(value < 0){ value = 0; }
+		if(value > count){ value = count; }
+		value = value * (this.maximum - this.minimum) / count + this.minimum;
+		this._setValueAttr(value, priorityChange);
+	},
+
+	_onClkBumper: function(val){
+		if(this.disabled || this.readOnly || !this.clickSelect){ return; }
+		this._setValueAttr(val, true);
+	},
+
+	_onClkIncBumper: function(){
+		this._onClkBumper(this._descending === false ? this.minimum : this.maximum);
+	},
+
+	_onClkDecBumper: function(){
+		this._onClkBumper(this._descending === false ? this.maximum : this.minimum);
+	},
+
+	decrement: function(/*Event*/ e){
+		// summary:
+		//		Decrement slider
+		// tags:
+		//		private
+		this._bumpValue(e.charOrCode == dojo.keys.PAGE_DOWN ? -this.pageIncrement : -1);
+	},
+
+	increment: function(/*Event*/ e){
+		// summary:
+		//		Increment slider
+		// tags:
+		//		private
+		this._bumpValue(e.charOrCode == dojo.keys.PAGE_UP ? this.pageIncrement : 1);
+	},
+
+	_mouseWheeled: function(/*Event*/ evt){
+		// summary:
+		//		Event handler for mousewheel where supported
+		dojo.stopEvent(evt);
+		var janky = !dojo.isMozilla;
+		var scroll = evt[(janky ? "wheelDelta" : "detail")] * (janky ? 1 : -1);
+		this._bumpValue(scroll < 0 ? -1 : 1, true); // negative scroll acts like a decrement
+	},
+
+	startup: function(){
+		if(this._started){ return; }
+
+		dojo.forEach(this.getChildren(), function(child){
+			if(this[child.container] != this.containerNode){
+				this[child.container].appendChild(child.domNode);
+			}
+		}, this);
+
+		this.inherited(arguments);
+	},
+
+	_typematicCallback: function(/*Number*/ count, /*Object*/ button, /*Event*/ e){
+		if(count == -1){
+			this._setValueAttr(this.value, true);
+		}else{
+			this[(button == (this._descending? this.incrementButton : this.decrementButton)) ? "decrement" : "increment"](e);
+		}
+	},
+
+	postCreate: function(){
+		if(this.showButtons){
+			this.incrementButton.style.display="";
+			this.decrementButton.style.display="";
+			this._connects.push(dijit.typematic.addMouseListener(
+				this.decrementButton, this, "_typematicCallback", 25, 500));
+			this._connects.push(dijit.typematic.addMouseListener(
+				this.incrementButton, this, "_typematicCallback", 25, 500));
+		}
+		this.connect(this.domNode, !dojo.isMozilla ? "onmousewheel" : "DOMMouseScroll", "_mouseWheeled");
+
+		// define a custom constructor for a SliderMover that points back to me
+		var mover = dojo.declare(dijit.form._SliderMover, {
+			widget: this
+		});
+
+		this._movable = new dojo.dnd.Moveable(this.sliderHandle, {mover: mover});
+		// find any associated label element and add to slider focusnode.
+		var label=dojo.query('label[for="'+this.id+'"]');
+		if(label.length){
+			label[0].id = (this.id+"_label");
+			dijit.setWaiState(this.focusNode, "labelledby", label[0].id);
+		}
+		dijit.setWaiState(this.focusNode, "valuemin", this.minimum);
+		dijit.setWaiState(this.focusNode, "valuemax", this.maximum);
+
+		this.inherited(arguments);
+		this._layoutHackIE7();
+	},
+
+	destroy: function(){
+		this._movable.destroy();
+		if(this._inProgressAnim && this._inProgressAnim.status != "stopped"){
+			this._inProgressAnim.stop(true);
+		}
+		this._supportingWidgets = dijit.findWidgets(this.domNode); // tells destroy about pseudo-child widgets (ruler/labels)
+		this.inherited(arguments);
+	}
+});
+
+dojo.declare("dijit.form._SliderMover",
+	dojo.dnd.Mover,
+{
+	onMouseMove: function(e){
+		var widget = this.widget;
+		var abspos = widget._abspos;
+		if(!abspos){
+			abspos = widget._abspos = dojo.position(widget.sliderBarContainer, true);
+			widget._setPixelValue_ = dojo.hitch(widget, "_setPixelValue");
+			widget._isReversed_ = widget._isReversed();
+		}
+		var pixelValue = e[widget._mousePixelCoord] - abspos[widget._startingPixelCoord];
+		widget._setPixelValue_(widget._isReversed_ ? (abspos[widget._pixelCount]-pixelValue) : pixelValue, abspos[widget._pixelCount], false);
+	},
+
+	destroy: function(e){
+		dojo.dnd.Mover.prototype.destroy.apply(this, arguments);
+		var widget = this.widget;
+		widget._abspos = null;
+		widget._setValueAttr(widget.value, true);
+	}
+});
+
+
diff --git a/dijit/form/MappedTextBox.js b/dijit/form/MappedTextBox.js
index 3035ba4..6b76b8d 100644
--- a/dijit/form/MappedTextBox.js
+++ b/dijit/form/MappedTextBox.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.MappedTextBox"]){
-dojo._hasResource["dijit.form.MappedTextBox"]=true;
 dojo.provide("dijit.form.MappedTextBox");
 dojo.require("dijit.form.ValidationTextBox");
-}
diff --git a/dijit/form/MultiSelect.js b/dijit/form/MultiSelect.js
index bdd661f..77d4975 100644
--- a/dijit/form/MultiSelect.js
+++ b/dijit/form/MultiSelect.js
@@ -1,49 +1,108 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.MultiSelect"]){
-dojo._hasResource["dijit.form.MultiSelect"]=true;
 dojo.provide("dijit.form.MultiSelect");
+
 dojo.require("dijit.form._FormWidget");
-dojo.declare("dijit.form.MultiSelect",dijit.form._FormValueWidget,{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(){
-this._hasBeenBlurred=false;
-this._setValueAttr(this._resetValue,true);
-},addSelected:function(_1){
-_1.getSelected().forEach(function(n){
-this.containerNode.appendChild(n);
-this.domNode.scrollTop=this.domNode.offsetHeight;
-var _2=_1.domNode.scrollTop;
-_1.domNode.scrollTop=0;
-_1.domNode.scrollTop=_2;
-},this);
-},getSelected:function(){
-return dojo.query("option",this.containerNode).filter(function(n){
-return n.selected;
-});
-},_getValueAttr:function(){
-return this.getSelected().map(function(n){
-return n.value;
-});
-},multiple:true,_setValueAttr:function(_3){
-dojo.query("option",this.containerNode).forEach(function(n){
-n.selected=(dojo.indexOf(_3,n.value)!=-1);
-});
-},invertSelection:function(_4){
-dojo.query("option",this.containerNode).forEach(function(n){
-n.selected=!n.selected;
+
+dojo.declare("dijit.form.MultiSelect", dijit.form._FormValueWidget, {
+	// 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;
+		});
+	},
+
+	multiple: 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.get('value'), onChange == true);
+	},
+
+	_onChange: function(/*Event*/ e){
+		this._handleOnChange(this.get('value'), true);
+	},
+
+	// for layout widgets:
+	resize: function(/* Object */size){
+		if(size){
+			dojo.marginBox(this.domNode, size);
+		}
+	},
+
+	postCreate: function(){
+		this._onChange();
+	}
 });
-this._handleOnChange(this.attr("value"),_4==true);
-},_onChange:function(e){
-this._handleOnChange(this.attr("value"),true);
-},resize:function(_5){
-if(_5){
-dojo.marginBox(this.domNode,_5);
-}
-},postCreate:function(){
-this._onChange();
-}});
-}
diff --git a/dijit/form/NumberSpinner.js b/dijit/form/NumberSpinner.js
index f5a341c..2638509 100644
--- a/dijit/form/NumberSpinner.js
+++ b/dijit/form/NumberSpinner.js
@@ -1,38 +1,60 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.NumberSpinner"]){
-dojo._hasResource["dijit.form.NumberSpinner"]=true;
 dojo.provide("dijit.form.NumberSpinner");
+
 dojo.require("dijit.form._Spinner");
 dojo.require("dijit.form.NumberTextBox");
-dojo.declare("dijit.form.NumberSpinner",[dijit.form._Spinner,dijit.form.NumberTextBoxMixin],{adjust:function(_1,_2){
-var tc=this.constraints,v=isNaN(_1),_3=!isNaN(tc.max),_4=!isNaN(tc.min);
-if(v&&_2!=0){
-_1=(_2>0)?_4?tc.min:_3?tc.max:0:_3?this.constraints.max:_4?tc.min:0;
-}
-var _5=_1+_2;
-if(v||isNaN(_5)){
-return _1;
-}
-if(_3&&(_5>tc.max)){
-_5=tc.max;
-}
-if(_4&&(_5<tc.min)){
-_5=tc.min;
-}
-return _5;
-},_onKeyPress:function(e){
-if((e.charOrCode==dojo.keys.HOME||e.charOrCode==dojo.keys.END)&&!(e.ctrlKey||e.altKey||e.metaKey)&&typeof this.attr("value")!="undefined"){
-var _6=this.constraints[(e.charOrCode==dojo.keys.HOME?"min":"max")];
-if(_6){
-this._setValueAttr(_6,true);
-}
-dojo.stopEvent(e);
-}
-}});
-}
+
+dojo.declare("dijit.form.NumberSpinner",
+	[dijit.form._Spinner, dijit.form.NumberTextBoxMixin],
+	{
+	// summary:
+	//		Extends NumberTextBox to add up/down arrows and pageup/pagedown for incremental change to the value
+	//
+	// description:
+	//		A `dijit.form.NumberTextBox` extension to provide keyboard accessible value selection
+	//		as well as icons for spinning direction. When using the keyboard, the typematic rules
+	//		apply, meaning holding the key will gradually increase or decrease the value and
+	// 		accelerate.
+	//
+	// example:
+	//	| new dijit.form.NumberSpinner({ constraints:{ max:300, min:100 }}, "someInput");
+
+	adjust: function(/* Object */val, /* Number*/delta){
+		// summary:
+		//		Change Number val by the given amount
+		// tags:
+		//		protected
+
+		var tc = this.constraints,
+			v = isNaN(val),
+			gotMax = !isNaN(tc.max),
+			gotMin = !isNaN(tc.min)
+		;
+		if(v && delta != 0){ // blank or invalid value and they want to spin, so create defaults
+			val = (delta > 0) ?
+				gotMin ? tc.min : gotMax ? tc.max : 0 :
+				gotMax ? this.constraints.max : gotMin ? tc.min : 0
+			;
+		}
+		var newval = val + delta;
+		if(v || isNaN(newval)){ return val; }
+		if(gotMax && (newval > tc.max)){
+			newval = tc.max;
+		}
+		if(gotMin && (newval < tc.min)){
+			newval = tc.min;
+		}
+		return newval;
+	},
+
+	_onKeyPress: function(e){
+		if((e.charOrCode == dojo.keys.HOME || e.charOrCode == dojo.keys.END) && !(e.ctrlKey || e.altKey || e.metaKey)
+		&& typeof this.get('value') != 'undefined' /* gibberish, so HOME and END are default editing keys*/){
+			var value = this.constraints[(e.charOrCode == dojo.keys.HOME ? "min" : "max")];
+			if(typeof value == "number"){
+				this._setValueAttr(value, false);
+			}
+			// eat home or end key whether we change the value or not
+			dojo.stopEvent(e);
+		}
+	}
+});
diff --git a/dijit/form/NumberTextBox.js b/dijit/form/NumberTextBox.js
index 9c5cf06..ab95619 100644
--- a/dijit/form/NumberTextBox.js
+++ b/dijit/form/NumberTextBox.js
@@ -1,108 +1,248 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.NumberTextBox"]){
-dojo._hasResource["dijit.form.NumberTextBox"]=true;
 dojo.provide("dijit.form.NumberTextBox");
+
 dojo.require("dijit.form.ValidationTextBox");
 dojo.require("dojo.number");
-dojo.declare("dijit.form.NumberTextBoxMixin",null,{regExpGen:dojo.number.regexp,value:NaN,editOptions:{pattern:"#.######"},_formatter:dojo.number.format,postMixInProperties:function(){
-var _1=typeof this.constraints.places=="number"?this.constraints.places:0;
-if(_1){
-_1++;
-}
-if(typeof this.constraints.max!="number"){
-this.constraints.max=9*Math.pow(10,15-_1);
-}
-if(typeof this.constraints.min!="number"){
-this.constraints.min=-9*Math.pow(10,15-_1);
-}
-this.inherited(arguments);
-},_onFocus:function(){
-if(this.disabled){
-return;
-}
-var _2=this.attr("value");
-if(typeof _2=="number"&&!isNaN(_2)){
-var _3=this.format(_2,this.constraints);
-if(_3!==undefined){
-this.textbox.value=_3;
-}
-}
-this.inherited(arguments);
-},format:function(_4,_5){
-if(typeof _4!="number"){
-return String(_4);
-}
-if(isNaN(_4)){
-return "";
-}
-if(("rangeCheck" in this)&&!this.rangeCheck(_4,_5)){
-return String(_4);
-}
-if(this.editOptions&&this._focused){
-_5=dojo.mixin({},_5,this.editOptions);
-}
-return this._formatter(_4,_5);
-},parse:dojo.number.parse,_getDisplayedValueAttr:function(){
-var v=this.inherited(arguments);
-return isNaN(v)?this.textbox.value:v;
-},filter:function(_6){
-return (_6===null||_6===""||_6===undefined)?NaN:this.inherited(arguments);
-},serialize:function(_7,_8){
-return (typeof _7!="number"||isNaN(_7))?"":this.inherited(arguments);
-},_setValueAttr:function(_9,_a,_b){
-if(_9!==undefined&&_b===undefined){
-if(typeof _9=="number"){
-if(isNaN(_9)){
-_b="";
-}else{
-if(("rangeCheck" in this)&&!this.rangeCheck(_9,this.constraints)){
-_b=String(_9);
-}
-}
-}else{
-if(!_9){
-_b="";
-_9=NaN;
-}else{
-_b=String(_9);
-_9=undefined;
-}
-}
-}
-this.inherited(arguments,[_9,_a,_b]);
-},_getValueAttr:function(){
-var v=this.inherited(arguments);
-if(isNaN(v)&&this.textbox.value!==""){
-if(this.constraints.exponent!==false&&/\de[-+]?|\d/i.test(this.textbox.value)&&(new RegExp("^"+dojo.number._realNumberRegexp(dojo.mixin({},this.constraints))+"$").test(this.textbox.value))){
-var n=Number(this.textbox.value);
-return isNaN(n)?undefined:n;
-}else{
-return undefined;
-}
-}else{
-return v;
-}
-},isValid:function(_c){
-if(!this._focused||this._isEmpty(this.textbox.value)){
-return this.inherited(arguments);
-}else{
-var v=this.attr("value");
-if(!isNaN(v)&&this.rangeCheck(v,this.constraints)){
-if(this.constraints.exponent!==false&&/\de[-+]?\d/i.test(this.textbox.value)){
-return true;
-}else{
-return this.inherited(arguments);
-}
-}else{
-return false;
-}
-}
-}});
-dojo.declare("dijit.form.NumberTextBox",[dijit.form.RangeBoundTextBox,dijit.form.NumberTextBoxMixin],{});
-}
+
+/*=====
+dojo.declare(
+	"dijit.form.NumberTextBox.__Constraints",
+	[dijit.form.RangeBoundTextBox.__Constraints, dojo.number.__FormatOptions, dojo.number.__ParseOptions], {
+	// summary:
+	//		Specifies both the rules on valid/invalid values (minimum, maximum,
+	//		number of required decimal places), and also formatting options for
+	//		displaying the value when the field is not focused.
+	// example:
+	//		Minimum/maximum:
+	//		To specify a field between 0 and 120:
+	//	|		{min:0,max:120}
+	//		To specify a field that must be an integer:
+	//	|		{fractional:false}
+	//		To specify a field where 0 to 3 decimal places are allowed on input,
+	//		but after the field is blurred the value is displayed with 3 decimal places:
+	//	|		{places:'0,3'}
+});
+=====*/
+
+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
+		//		Despite the name, this parameter specifies both constraints on the input
+		//		(including minimum/maximum allowed values) as well as
+		//		formatting options like places (the number of digits to display after
+		//		the decimal point).   See `dijit.form.NumberTextBox.__Constraints` for details.
+		constraints: {},
+		======*/
+
+		// value: Number
+		//		The value of this NumberTextBox as a Javascript Number (i.e., 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).
+		//
+		//		Symmetrically, 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,
+
+		_setConstraintsAttr: function(/* Object */ constraints){
+			var places = typeof constraints.places == "number"? constraints.places : 0;
+			if(places){ places++; } // decimal rounding errors take away another digit of precision
+			if(typeof constraints.max != "number"){
+				constraints.max = 9 * Math.pow(10, 15-places);
+			}
+			if(typeof constraints.min != "number"){
+				constraints.min = -9 * Math.pow(10, 15-places);
+			}
+			this.inherited(arguments, [ constraints ]);
+			if(this.focusNode && this.focusNode.value && !isNaN(this.value)){
+				this.set('value', this.value);
+			}
+		},
+
+		_onFocus: function(){
+			if(this.disabled){ return; }
+			var val = this.get('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
+
+			var formattedValue = String(value);
+			if(typeof value != "number"){ return formattedValue; }
+			if(isNaN(value)){ return ""; }
+			// check for exponential notation that dojo.number.format chokes on
+			if(!("rangeCheck" in this && this.rangeCheck(value, constraints)) && constraints.exponent !== false && /\de[-+]?\d/i.test(formattedValue)){
+				return formattedValue;
+			}
+			if(this.editOptions && this._focused){
+				constraints = dojo.mixin({}, constraints, this.editOptions);
+			}
+			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){
+				formattedValue = String(value);
+				if(typeof value == "number"){
+					if(isNaN(value)){ formattedValue = '' }
+					// check for exponential notation that dojo.number.format chokes on
+					else if(("rangeCheck" in this && this.rangeCheck(value, this.constraints)) || this.constraints.exponent === false || !/\de[-+]?\d/i.test(formattedValue)){
+						formattedValue = undefined; // lets format comnpute a real string value
+					}
+				}else if(!value){ // 0 processed in if branch above, ''|null|undefined flow thru here
+					formattedValue = '';
+					value = NaN;
+				}else{ // non-numeric values
+					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(this.constraints.exponent !== false && /\de[-+]?\d/i.test(this.textbox.value) && (new RegExp("^"+dojo.number._realNumberRegexp(dojo.mixin({}, this.constraints))+"$").test(this.textbox.value))){	// check for exponential notation that parse() rejected (erroneously?)
+					var n = Number(this.textbox.value);
+					return isNaN(n) ? undefined : n; // return exponential Number or undefined for random text (may not be possible to do with the above RegExp check)
+				}else{
+					return undefined; // gibberish
+				}
+			}else{
+				return v; // Number or NaN for ''
+			}
+		},
+
+		isValid: function(/*Boolean*/ isFocused){
+			// Overrides dijit.form.RangeBoundTextBox.isValid to check that the editing-mode value is valid since
+			// it may not be formatted according to the regExp vaidation rules
+			if(!this._focused || this._isEmpty(this.textbox.value)){
+				return this.inherited(arguments);
+			}else{
+				var v = this.get('value');
+				if(!isNaN(v) && this.rangeCheck(v, this.constraints)){
+					if(this.constraints.exponent !== false && /\de[-+]?\d/i.test(this.textbox.value)){ // exponential, parse doesn't like it
+						return true; // valid exponential number in range
+					}else{
+						return this.inherited(arguments);
+					}
+				}else{
+					return false;
+				}
+			}
+		}
+	}
+);
+
+dojo.declare("dijit.form.NumberTextBox",
+	[dijit.form.RangeBoundTextBox,dijit.form.NumberTextBoxMixin],
+	{
+		// summary:
+		//		A TextBox for entering numbers, with formatting and range checking
+		// description:
+		//		NumberTextBox is a textbox for entering and displaying numbers, supporting
+		//		the following main features:
+		//
+		//			1. Enforce minimum/maximum allowed values (as well as enforcing that the user types
+		//				a number rather than a random string)
+		//			2. NLS support (altering roles of comma and dot as "thousands-separator" and "decimal-point"
+		//				depending on locale).
+		//			3. Separate modes for editing the value and displaying it, specifically that
+		//				the thousands separator character (typically comma) disappears when editing
+		//				but reappears after the field is blurred.
+		//			4. Formatting and constraints regarding the number of places (digits after the decimal point)
+		//				allowed on input, and number of places displayed when blurred (see `constraints` parameter).
+	}
+);
diff --git a/dijit/form/RadioButton.js b/dijit/form/RadioButton.js
index f355fab..ad1e033 100644
--- a/dijit/form/RadioButton.js
+++ b/dijit/form/RadioButton.js
@@ -1,12 +1,4 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.RadioButton"]){
-dojo._hasResource["dijit.form.RadioButton"]=true;
 dojo.provide("dijit.form.RadioButton");
 dojo.require("dijit.form.CheckBox");
-}
+
+// TODO: for 2.0, move the RadioButton code into this file
diff --git a/dijit/form/RangeBoundTextBox.js b/dijit/form/RangeBoundTextBox.js
index c0dd0d2..e0667f7 100644
--- a/dijit/form/RangeBoundTextBox.js
+++ b/dijit/form/RangeBoundTextBox.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.RangeBoundTextBox"]){
-dojo._hasResource["dijit.form.RangeBoundTextBox"]=true;
 dojo.provide("dijit.form.RangeBoundTextBox");
 dojo.require("dijit.form.ValidationTextBox");
-}
diff --git a/dijit/form/Select.js b/dijit/form/Select.js
index edc49b5..b2b2e22 100644
--- a/dijit/form/Select.js
+++ b/dijit/form/Select.js
@@ -1,141 +1,278 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.Select"]){
-dojo._hasResource["dijit.form.Select"]=true;
 dojo.provide("dijit.form.Select");
+
 dojo.require("dijit.form._FormSelectWidget");
 dojo.require("dijit._HasDropDown");
 dojo.require("dijit.Menu");
-dojo.requireLocalization("dijit.form","validate",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit.form._SelectMenu",dijit.Menu,{buildRendering:function(){
-this.inherited(arguments);
-var o=(this.menuTableNode=this.domNode);
-var n=(this.domNode=dojo.doc.createElement("div"));
-if(o.parentNode){
-o.parentNode.replaceChild(n,o);
-}
-dojo.removeClass(o,"dijitMenuTable");
-n.className=o.className+" dijitSelectMenu";
-o.className="dijitReset dijitMenuTable";
-dijit.setWaiRole(o,"listbox");
-dijit.setWaiRole(n,"presentation");
-n.appendChild(o);
-this.tabIndex=null;
-},resize:function(mb){
-if(mb){
-dojo.marginBox(this.domNode,mb);
-var w=dojo.contentBox(this.domNode).w;
-if(dojo.isMoz&&this.domNode.scrollHeight>this.domNode.clientHeight){
-w--;
-}else{
-if(dojo.isIE<8||(dojo.isIE&&dojo.isQuirks)){
-w-=16;
-}
-}
-dojo.marginBox(this.menuTableNode,{w:w});
-}
-}});
-dojo.declare("dijit.form.Select",[dijit.form._FormSelectWidget,dijit._HasDropDown],{baseClass:"dijitSelect",templateString:dojo.cache("dijit.form","templates/Select.html","<table class='dijit dijitReset dijitInline dijitLeft'\n\tdojoAttachPoint=\"_buttonNode,tableNode\" cellspacing='0' cellpadding='0' waiRole=\"presentation\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\"\n\t><tbody waiRole=\"presentation\"><tr waiRole=\"presentation\"\n\t\t><td c [...]
-this.inherited(arguments);
-if(this.options.length&&!this.value&&this.srcNodeRef){
-var si=this.srcNodeRef.selectedIndex;
-this.value=this.options[si!=-1?si:0].value;
-}
-this.dropDown=new dijit.form._SelectMenu();
-dojo.addClass(this.dropDown.domNode,this.baseClass+"Menu");
-},_getMenuItemForOption:function(_1){
-if(!_1.value){
-return new dijit.MenuSeparator();
-}else{
-var _2=dojo.hitch(this,"_setValueAttr",_1);
-var _3=new dijit.MenuItem({option:_1,label:_1.label,onClick:_2,disabled:_1.disabled||false});
-dijit.setWaiRole(_3.focusNode,"listitem");
-return _3;
-}
-},_addOptionItem:function(_4){
-if(this.dropDown){
-this.dropDown.addChild(this._getMenuItemForOption(_4));
-}
-},_getChildren:function(){
-if(!this.dropDown){
-return [];
-}
-return this.dropDown.getChildren();
-},_loadChildren:function(_5){
-if(_5===true){
-if(this.dropDown){
-delete this.dropDown.focusedChild;
-}
-if(this.options.length){
-this.inherited(arguments);
-}else{
-dojo.forEach(this._getChildren(),function(_6){
-_6.destroyRecursive();
+dojo.require("dijit.Tooltip");
+
+dojo.requireLocalization("dijit.form", "validate");
+
+dojo.declare("dijit.form._SelectMenu", dijit.Menu, {
+	// summary:
+	//		An internally-used menu for dropdown that allows us a vertical scrollbar
+	buildRendering: function(){
+		// summary:
+		//		Stub in our own changes, so that our domNode is not a table
+		//		otherwise, we won't respond correctly to heights/overflows
+		this.inherited(arguments);
+		var o = (this.menuTableNode = this.domNode);
+		var n = (this.domNode = dojo.create("div", {style: {overflowX: "hidden", overflowY: "scroll"}}));
+		if(o.parentNode){
+			o.parentNode.replaceChild(n, o);
+		}
+		dojo.removeClass(o, "dijitMenuTable");
+		n.className = o.className + " dijitSelectMenu";
+		o.className = "dijitReset dijitMenuTable";
+		dijit.setWaiRole(o,"listbox");
+		dijit.setWaiRole(n,"presentation");
+		n.appendChild(o);
+	},
+	resize: function(/*Object*/ mb){
+		// summary:
+		//		Overridden so that we are able to handle resizing our
+		//		internal widget.  Note that this is not a "full" resize
+		//		implementation - it only works correctly if you pass it a
+		//		marginBox.
+		//
+		// mb: Object
+		//		The margin box to set this dropdown to.
+		if(mb){
+			dojo.marginBox(this.domNode, mb);
+			if("w" in mb){
+				// We've explicitly set the wrapper <div>'s width, so set <table> width to match.
+				// 100% is safer than a pixel value because there may be a scroll bar with
+				// browser/OS specific width.
+				this.menuTableNode.style.width = "100%";
+			}
+		}
+	}
+});
+
+dojo.declare("dijit.form.Select", [dijit.form._FormSelectWidget, dijit._HasDropDown], {
+	// summary:
+	//		This is a "styleable" select box - it is basically a DropDownButton which
+	//		can take a <select> as its input.
+
+	baseClass: "dijitSelect",
+
+	templateString: dojo.cache("dijit.form", "templates/Select.html"),
+
+	// attributeMap: Object
+	//		Add in our style to be applied to the focus node
+	attributeMap: dojo.mixin(dojo.clone(dijit.form._FormSelectWidget.prototype.attributeMap),{style:"tableNode"}),
+
+	// required: Boolean
+	//		Can be true or false, default is false.
+	required: false,
+
+	// state: 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: [],
+
+	// emptyLabel: string
+	//		What to display in an "empty" dropdown
+	emptyLabel: "",
+
+	// _isLoaded: Boolean
+	//		Whether or not we have been loaded
+	_isLoaded: false,
+
+	// _childrenLoaded: Boolean
+	//		Whether or not our children have been loaded
+	_childrenLoaded: false,
+
+	_fillContent: function(){
+		// summary:
+		//		Set the value to be the first, or the selected index
+		this.inherited(arguments);
+		if(this.options.length && !this.value && this.srcNodeRef){
+			var si = this.srcNodeRef.selectedIndex;
+			this.value = this.options[si != -1 ? si : 0].value;
+		}
+
+		// Create the dropDown widget
+		this.dropDown = new dijit.form._SelectMenu({id: this.id + "_menu"});
+		dojo.addClass(this.dropDown.domNode, this.baseClass + "Menu");
+	},
+
+	_getMenuItemForOption: function(/*dijit.form.__SelectOption*/ option){
+		// summary:
+		//		For the given option, return the menu item that should be
+		//		used to display it.  This can be overridden as needed
+		if(!option.value){
+			// We are a separator (no label set for it)
+			return new dijit.MenuSeparator();
+		}else{
+			// Just a regular menu option
+			var click = dojo.hitch(this, "_setValueAttr", option);
+			var item = new dijit.MenuItem({
+				option: option,
+				label: option.label,
+				onClick: click,
+				disabled: option.disabled || false
+			});
+			dijit.setWaiRole(item.focusNode, "listitem");
+			return item;
+		}
+	},
+
+	_addOptionItem: function(/*dijit.form.__SelectOption*/ option){
+		// summary:
+		//		For the given option, add an option to our dropdown.
+		//		If the option doesn't have a value, then a separator is added
+		//		in that place.
+		if(this.dropDown){
+			this.dropDown.addChild(this._getMenuItemForOption(option));
+		}
+	},
+
+	_getChildren: function(){
+		if(!this.dropDown){
+			return [];
+		}
+		return this.dropDown.getChildren();
+	},
+
+	_loadChildren: function(/*Boolean*/ loadMenuItems){
+		// summary:
+		//		Resets the menu and the length attribute of the button - and
+		//		ensures that the label is appropriately set.
+		//	loadMenuItems: Boolean
+		//		actually loads the child menu items - we only do this when we are
+		//		populating for showing the dropdown.
+
+		if(loadMenuItems === true){
+			// this.inherited destroys this.dropDown's child widgets (MenuItems).
+			// Avoid this.dropDown (Menu widget) having a pointer to a destroyed widget (which will cause
+			// issues later in _setSelected). (see #10296)
+			if(this.dropDown){
+				delete this.dropDown.focusedChild;
+			}
+			if(this.options.length){
+				this.inherited(arguments);
+			}else{
+				// Drop down menu is blank but add one blank entry just so something appears on the screen
+				// to let users know that they are no choices (mimicing native select behavior)
+				dojo.forEach(this._getChildren(), function(child){ child.destroyRecursive(); });
+				var item = new dijit.MenuItem({label: " "});
+				this.dropDown.addChild(item);
+			}
+		}else{
+			this._updateSelection();
+		}
+
+		var len = this.options.length;
+		this._isLoaded = false;
+		this._childrenLoaded = true;
+
+		if(!this._loadingStore){
+			// Don't call this if we are loading - since we will handle it later
+			this._setValueAttr(this.value);
+		}
+	},
+
+	_setValueAttr: function(value){
+		this.inherited(arguments);
+		dojo.attr(this.valueNode, "value", this.get("value"));
+	},
+
+	_setDisplay: function(/*String*/ newDisplay){
+		// summary:
+		//		sets the display for the given value (or values)
+		this.containerNode.innerHTML = '<span class="dijitReset dijitInline ' + this.baseClass + 'Label">' +
+					(newDisplay || this.emptyLabel || " ") +
+					'</span>';
+		dijit.setWaiState(this.focusNode, "valuetext", (newDisplay || this.emptyLabel || " ") );
+	},
+
+	validate: function(/*Boolean*/ isFocused){
+		// summary:
+		//		Called by oninit, onblur, and onkeypress.
+		// description:
+		//		Show missing or invalid messages if appropriate, and highlight textbox field.
+		//		Used when a select is initially set to no value and the user is required to
+		//		set the value.
+		
+		var isValid = this.isValid(isFocused);
+		this.state = isValid ? "" : "Error";
+		this._setStateClass();
+		dijit.setWaiState(this.focusNode, "invalid", isValid ? "false" : "true");
+		var message = isValid ? "" : this._missingMsg;
+		if(this._message !== message){
+			this._message = message;
+			dijit.hideTooltip(this.domNode);
+			if(message){
+				dijit.showTooltip(message, this.domNode, this.tooltipPosition, !this.isLeftToRight());
+			}
+		}
+		return isValid;
+	},
+
+	isValid: function(/*Boolean*/ isFocused){
+		// summary:
+		//		Whether or not this is a valid value.   The only way a Select
+		//		can be invalid is when it's required but nothing is selected.
+		return (!this.required || !(/^\s*$/.test(this.value)));
+	},
+
+	reset: function(){
+		// summary:
+		//		Overridden so that the state will be cleared.
+		this.inherited(arguments);
+		dijit.hideTooltip(this.domNode);
+		this.state = "";
+		this._setStateClass();
+		delete this._message;
+	},
+
+	postMixInProperties: function(){
+		// summary:
+		//		set the missing message
+		this.inherited(arguments);
+		this._missingMsg = dojo.i18n.getLocalization("dijit.form", "validate",
+									this.lang).missingMessage;
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+		if(this.tableNode.style.width){
+			dojo.addClass(this.domNode, this.baseClass + "FixedWidth");
+		}
+	},
+
+	isLoaded: function(){
+		return this._isLoaded;
+	},
+
+	loadDropDown: function(/*Function*/ loadCallback){
+		// summary:
+		//		populates the menu
+		this._loadChildren(true);
+		this._isLoaded = true;
+		loadCallback();
+	},
+
+	closeDropDown: function(){
+		// overriding _HasDropDown.closeDropDown()
+		this.inherited(arguments);
+
+		if(this.dropDown && this.dropDown.menuTableNode){
+			// Erase possible width: 100% setting from _SelectMenu.resize().
+			// Leaving it would interfere with the next openDropDown() call, which
+			// queries the natural size of the drop down.
+			this.dropDown.menuTableNode.style.width = "";
+		}
+	},
+
+	uninitialize: function(preserveDom){
+		if(this.dropDown && !this.dropDown._destroyed){
+			this.dropDown.destroyRecursive(preserveDom);
+			delete this.dropDown;
+		}
+		this.inherited(arguments);
+	}
 });
-var _7=new dijit.MenuItem({label:" "});
-this.dropDown.addChild(_7);
-}
-}else{
-this._updateSelection();
-}
-var _8=this.options.length;
-this._isLoaded=false;
-this._childrenLoaded=true;
-if(!this._loadingStore){
-this._setValueAttr(this.value);
-}
-},_setValueAttr:function(_9){
-this.inherited(arguments);
-dojo.attr(this.valueNode,"value",this.attr("value"));
-},_setDisplay:function(_a){
-this.containerNode.innerHTML="<span class=\"dijitReset dijitInline "+this.baseClass+"Label\">"+(_a||this.emptyLabel||" ")+"</span>";
-dijit.setWaiState(this.focusNode,"valuenow",(_a||this.emptyLabel||" "));
-},validate:function(_b){
-var _c=this.isValid(_b);
-this.state=_c?"":"Error";
-this._setStateClass();
-dijit.setWaiState(this.focusNode,"invalid",_c?"false":"true");
-var _d=_c?"":this._missingMsg;
-if(this._message!==_d){
-this._message=_d;
-dijit.hideTooltip(this.domNode);
-if(_d){
-dijit.showTooltip(_d,this.domNode,this.tooltipPosition);
-}
-}
-return _c;
-},isValid:function(_e){
-return (!this.required||!(/^\s*$/.test(this.value)));
-},reset:function(){
-this.inherited(arguments);
-dijit.hideTooltip(this.domNode);
-this.state="";
-this._setStateClass();
-delete this._message;
-},postMixInProperties:function(){
-this.inherited(arguments);
-this._missingMsg=dojo.i18n.getLocalization("dijit.form","validate",this.lang).missingMessage;
-},postCreate:function(){
-this.inherited(arguments);
-if(this.tableNode.style.width){
-dojo.addClass(this.domNode,this.baseClass+"FixedWidth");
-}
-},isLoaded:function(){
-return this._isLoaded;
-},loadDropDown:function(_f){
-this._loadChildren(true);
-this._isLoaded=true;
-_f();
-},uninitialize:function(_10){
-if(this.dropDown&&!this.dropDown._destroyed){
-this.dropDown.destroyRecursive(_10);
-delete this.dropDown;
-}
-this.inherited(arguments);
-}});
-}
diff --git a/dijit/form/SimpleTextarea.js b/dijit/form/SimpleTextarea.js
index ac2495d..abcdcaf 100644
--- a/dijit/form/SimpleTextarea.js
+++ b/dijit/form/SimpleTextarea.js
@@ -1,59 +1,91 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.SimpleTextarea"]){
-dojo._hasResource["dijit.form.SimpleTextarea"]=true;
 dojo.provide("dijit.form.SimpleTextarea");
+
 dojo.require("dijit.form.TextBox");
-dojo.declare("dijit.form.SimpleTextarea",dijit.form.TextBox,{baseClass:"dijitTextArea",attributeMap:dojo.delegate(dijit.form._FormValueWidget.prototype.attributeMap,{rows:"textbox",cols:"textbox"}),rows:"3",cols:"20",templateString:"<textarea ${nameAttrSetting} dojoAttachPoint='focusNode,containerNode,textbox' autocomplete='off'></textarea>",postMixInProperties:function(){
-if(!this.value&&this.srcNodeRef){
-this.value=this.srcNodeRef.value;
-}
-this.inherited(arguments);
-},filter:function(_1){
-if(_1){
-_1=_1.replace(/\r/g,"");
-}
-return this.inherited(arguments);
-},postCreate:function(){
-this.inherited(arguments);
-if(dojo.isIE&&this.cols){
-dojo.addClass(this.textbox,"dijitTextAreaCols");
-}
-},_previousValue:"",_onInput:function(e){
-if(this.maxLength){
-var _2=parseInt(this.maxLength);
-var _3=this.textbox.value.replace(/\r/g,"");
-var _4=_3.length-_2;
-if(_4>0){
-if(e){
-dojo.stopEvent(e);
-}
-var _5=this.textbox;
-if(_5.selectionStart){
-var _6=_5.selectionStart;
-var cr=0;
-if(dojo.isOpera){
-cr=(this.textbox.value.substring(0,_6).match(/\r/g)||[]).length;
-}
-this.textbox.value=_3.substring(0,_6-_4-cr)+_3.substring(_6-cr);
-_5.setSelectionRange(_6-_4,_6-_4);
-}else{
-if(dojo.doc.selection){
-_5.focus();
-var _7=dojo.doc.selection.createRange();
-_7.moveStart("character",-_4);
-_7.text="";
-_7.select();
-}
-}
-}
-this._previousValue=this.textbox.value;
-}
-this.inherited(arguments);
-}});
-}
+
+dojo.declare("dijit.form.SimpleTextarea",
+	dijit.form.TextBox,
+	{
+	// summary:
+	//		A simple textarea that degrades, and responds to
+	// 		minimal LayoutContainer usage, and works with dijit.form.Form.
+	//		Doesn't automatically size according to input, like Textarea.
+	//
+	// example:
+	//	|	<textarea dojoType="dijit.form.SimpleTextarea" name="foo" value="bar" rows=30 cols=40></textarea>
+	//
+	// example:
+	//	|	new dijit.form.SimpleTextarea({ rows:20, cols:30 }, "foo");
+
+	baseClass: "dijitTextBox dijitTextArea",
+
+	attributeMap: dojo.delegate(dijit.form._FormValueWidget.prototype.attributeMap, {
+		rows:"textbox", cols: "textbox"
+	}),
+
+	// rows: Number
+	//		The number of rows of text.
+	rows: "3",
+
+	// rows: Number
+	//		The number of characters per line.
+	cols: "20",
+
+	templateString: "<textarea ${!nameAttrSetting} dojoAttachPoint='focusNode,containerNode,textbox' autocomplete='off'></textarea>",
+
+	postMixInProperties: function(){
+		// Copy value from srcNodeRef, unless user specified a value explicitly (or there is no srcNodeRef)
+		if(!this.value && this.srcNodeRef){
+			this.value = this.srcNodeRef.value;
+		}
+		this.inherited(arguments);
+	},
+
+	filter: function(/*String*/ value){
+		// Override TextBox.filter to deal with newlines... specifically (IIRC) this is for IE which writes newlines
+		// as \r\n instead of just \n
+		if(value){
+			value = value.replace(/\r/g,"");
+		}
+		return this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+		if(dojo.isIE && this.cols){ // attribute selectors is not supported in IE6
+			dojo.addClass(this.textbox, "dijitTextAreaCols");
+		}
+	},
+
+	_previousValue: "",
+	_onInput: function(/*Event?*/ e){
+		// Override TextBox._onInput() to enforce maxLength restriction
+		if(this.maxLength){
+			var maxLength = parseInt(this.maxLength);
+			var value = this.textbox.value.replace(/\r/g,'');
+			var overflow = value.length - maxLength;
+			if(overflow > 0){
+				if(e){ dojo.stopEvent(e); }
+				var textarea = this.textbox;
+				if(textarea.selectionStart){
+					var pos = textarea.selectionStart;
+					var cr = 0;
+					if(dojo.isOpera){
+						cr = (this.textbox.value.substring(0,pos).match(/\r/g) || []).length;
+					}
+					this.textbox.value = value.substring(0,pos-overflow-cr)+value.substring(pos-cr);
+					textarea.setSelectionRange(pos-overflow, pos-overflow);
+				}else if(dojo.doc.selection){ //IE
+					textarea.focus();
+					var range = dojo.doc.selection.createRange();
+					// delete overflow characters
+					range.moveStart("character", -overflow);
+					range.text = '';
+					// show cursor
+					range.select();
+				}
+			}
+			this._previousValue = this.textbox.value;
+		}
+		this.inherited(arguments);
+	}
+});
diff --git a/dijit/form/Slider.js b/dijit/form/Slider.js
index a2b3376..090b7d8 100644
--- a/dijit/form/Slider.js
+++ b/dijit/form/Slider.js
@@ -1,18 +1,12 @@
-/*
-	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
-*/
+dojo.provide("dijit.form.Slider");
 
+dojo.deprecated("Call require() for HorizontalSlider / VerticalRule, explicitly rather than 'dijit.form.Slider' itself", "", "2.0");
 
-if(!dojo._hasResource["dijit.form.Slider"]){
-dojo._hasResource["dijit.form.Slider"]=true;
-dojo.provide("dijit.form.Slider");
-dojo.deprecated("Call require() for HorizontalSlider / VerticalRule, explicitly rather than 'dijit.form.Slider' itself","","2.0");
+// For back-compat, remove for 2.0
 dojo.require("dijit.form.HorizontalSlider");
 dojo.require("dijit.form.VerticalSlider");
 dojo.require("dijit.form.HorizontalRule");
 dojo.require("dijit.form.VerticalRule");
 dojo.require("dijit.form.HorizontalRuleLabels");
 dojo.require("dijit.form.VerticalRuleLabels");
-}
+
diff --git a/dijit/form/TextBox.js b/dijit/form/TextBox.js
index 7291351..bd2fe3f 100644
--- a/dijit/form/TextBox.js
+++ b/dijit/form/TextBox.js
@@ -1,173 +1,395 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.TextBox"]){
-dojo._hasResource["dijit.form.TextBox"]=true;
 dojo.provide("dijit.form.TextBox");
+
 dojo.require("dijit.form._FormWidget");
-dojo.declare("dijit.form.TextBox",dijit.form._FormValueWidget,{trim:false,uppercase:false,lowercase:false,propercase:false,maxLength:"",selectOnClick:false,templateString:dojo.cache("dijit.form","templates/TextBox.html","<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(diji [...]
-return this.parse(this.attr("displayedValue"),this.constraints);
-},_setValueAttr:function(_1,_2,_3){
-var _4;
-if(_1!==undefined){
-_4=this.filter(_1);
-if(typeof _3!="string"){
-if(_4!==null&&((typeof _4!="number")||!isNaN(_4))){
-_3=this.filter(this.format(_4,this.constraints));
-}else{
-_3="";
-}
-}
-}
-if(_3!=null&&_3!=undefined&&((typeof _3)!="number"||!isNaN(_3))&&this.textbox.value!=_3){
-this.textbox.value=_3;
-}
-this.inherited(arguments,[_4,_2]);
-},displayedValue:"",getDisplayedValue:function(){
-dojo.deprecated(this.declaredClass+"::getDisplayedValue() is deprecated. Use attr('displayedValue') instead.","","2.0");
-return this.attr("displayedValue");
-},_getDisplayedValueAttr:function(){
-return this.filter(this.textbox.value);
-},setDisplayedValue:function(_5){
-dojo.deprecated(this.declaredClass+"::setDisplayedValue() is deprecated. Use attr('displayedValue', ...) instead.","","2.0");
-this.attr("displayedValue",_5);
-},_setDisplayedValueAttr:function(_6){
-if(_6===null||_6===undefined){
-_6="";
-}else{
-if(typeof _6!="string"){
-_6=String(_6);
-}
-}
-this.textbox.value=_6;
-this._setValueAttr(this.attr("value"),undefined,_6);
-},format:function(_7,_8){
-return ((_7==null||_7==undefined)?"":(_7.toString?_7.toString():_7));
-},parse:function(_9,_a){
-return _9;
-},_refreshState:function(){
-},_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 _b=this;
-setTimeout(function(){
-_b._handleOnChange(_b.attr("value"),false);
-},0);
-}
-this._refreshState();
-},postCreate:function(){
-this.textbox.setAttribute("value",this.textbox.value);
-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);
-}
-},_blankValue:"",filter:function(_c){
-if(_c===null){
-return this._blankValue;
-}
-if(typeof _c!="string"){
-return _c;
-}
-if(this.trim){
-_c=dojo.trim(_c);
-}
-if(this.uppercase){
-_c=_c.toUpperCase();
-}
-if(this.lowercase){
-_c=_c.toLowerCase();
-}
-if(this.propercase){
-_c=_c.replace(/[^\s]+/g,function(_d){
-return _d.substring(0,1).toUpperCase()+_d.substring(1);
-});
-}
-return _c;
-},_setBlurValue:function(){
-this._setValueAttr(this.attr("value"),true);
-},_onBlur:function(e){
-if(this.disabled){
-return;
-}
-this._setBlurValue();
-this.inherited(arguments);
-if(this._selectOnClickHandle){
-this.disconnect(this._selectOnClickHandle);
-}
-if(this.selectOnClick&&dojo.isMoz){
-this.textbox.selectionStart=this.textbox.selectionEnd=undefined;
-}
-},_onFocus:function(by){
-if(this.disabled||this.readOnly){
-return;
-}
-if(this.selectOnClick&&by=="mouse"){
-this._selectOnClickHandle=this.connect(this.domNode,"onmouseup",function(){
-this.disconnect(this._selectOnClickHandle);
-var _e;
-if(dojo.isIE){
-var _f=dojo.doc.selection.createRange();
-var _10=_f.parentElement();
-_e=_10==this.textbox&&_f.text.length==0;
-}else{
-_e=this.textbox.selectionStart==this.textbox.selectionEnd;
-}
-if(_e){
-dijit.selectInputText(this.textbox);
-}
-});
-}
-this._refreshState();
-this.inherited(arguments);
-},reset:function(){
-this.textbox.value="";
-this.inherited(arguments);
-}});
-dijit.selectInputText=function(_11,_12,_13){
-var _14=dojo.global;
-var _15=dojo.doc;
-_11=dojo.byId(_11);
-if(isNaN(_12)){
-_12=0;
-}
-if(isNaN(_13)){
-_13=_11.value?_11.value.length:0;
-}
-dijit.focus(_11);
-if(_15["selection"]&&dojo.body()["createTextRange"]){
-if(_11.createTextRange){
-var _16=_11.createTextRange();
-with(_16){
-collapse(true);
-moveStart("character",-99999);
-moveStart("character",_12);
-moveEnd("character",_13-_12);
-select();
-}
-}
-}else{
-if(_14["getSelection"]){
-if(_11.setSelectionRange){
-_11.setSelectionRange(_12,_13);
-}
-}
-}
+
+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: "",
+
+		//	selectOnClick: [const] Boolean
+		//		If true, all text will be selected when focused with mouse
+		selectOnClick: false,
+
+		//	placeHolder: String
+		//		Defines a hint to help users fill out the input field (as defined in HTML 5).
+		//		This should only contain plain text (no html markup).
+		placeHolder: "",
+		
+		templateString: dojo.cache("dijit.form", "templates/TextBox.html"),
+		_singleNodeTemplate: '<input class="dijit dijitReset dijitLeft dijitInputField" dojoAttachPoint="textbox,focusNode" autocomplete="off" type="${type}" ${!nameAttrSetting} />',
+
+		_buttonInputDisabled: dojo.isIE ? "disabled" : "", // allows IE to disallow focus, but Firefox cannot be disabled for mousedown events
+
+		baseClass: "dijitTextBox",
+
+		attributeMap: dojo.delegate(dijit.form._FormValueWidget.prototype.attributeMap, {
+			maxLength: "focusNode"
+		}),
+		
+		postMixInProperties: function(){
+			var type = this.type.toLowerCase();
+			if(this.templateString.toLowerCase() == "input" || ((type == "hidden" || type == "file") && this.templateString == dijit.form.TextBox.prototype.templateString)){
+				this.templateString = this._singleNodeTemplate;
+			}
+			this.inherited(arguments);
+		},
+
+		_setPlaceHolderAttr: function(v){
+			this.placeHolder = v;
+			if(!this._phspan){
+				this._attachPoints.push('_phspan');
+				/* dijitInputField class gives placeHolder same padding as the input field
+				 * parent node already has dijitInputField class but it doesn't affect this <span>
+				 * since it's position: absolute.
+				 */
+				this._phspan = dojo.create('span',{className:'dijitPlaceHolder dijitInputField'},this.textbox,'after');
+			}
+			this._phspan.innerHTML="";
+			this._phspan.appendChild(document.createTextNode(v));
+			
+			this._updatePlaceHolder();
+		},
+		
+		_updatePlaceHolder: function(){
+			if(this._phspan){
+				this._phspan.style.display=(this.placeHolder&&!this._focused&&!this.textbox.value)?"":"none";
+			}
+		},
+
+		_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.get('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._updatePlaceHolder();
+
+			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.  Otherwise '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 set('displayedValue') instead.
+			// tags:
+			//		deprecated
+			dojo.deprecated(this.declaredClass+"::getDisplayedValue() is deprecated. Use set('displayedValue') instead.", "", "2.0");
+			return this.get('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 set('displayedValue', ...) instead.
+			// tags:
+			//		deprecated
+			dojo.deprecated(this.declaredClass+"::setDisplayedValue() is deprecated. Use set('displayedValue', ...) instead.", "", "2.0");
+			this.set('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.get('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.get('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
+			if(dojo.isIE){ // IE INPUT tag fontFamily has to be set directly using STYLE
+				var s = dojo.getComputedStyle(this.domNode);
+				if(s){
+					var ff = s.fontFamily;
+					if(ff){
+						var inputs = this.domNode.getElementsByTagName("INPUT");
+						if(inputs){
+							for(var i=0; i < inputs.length; i++){
+								inputs[i].style.fontFamily = ff;
+							}
+						}
+					}
+				}
+			}
+			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);
+			}
+		},
+
+		_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.get('value'), true);
+		},
+
+		_onBlur: function(e){
+			if(this.disabled){ return; }
+			this._setBlurValue();
+			this.inherited(arguments);
+
+			if(this._selectOnClickHandle){
+				this.disconnect(this._selectOnClickHandle);
+			}
+			if(this.selectOnClick && dojo.isMoz){
+				this.textbox.selectionStart = this.textbox.selectionEnd = undefined; // clear selection so that the next mouse click doesn't reselect
+			}
+			
+			this._updatePlaceHolder();
+		},
+
+		_onFocus: function(/*String*/ by){
+			if(this.disabled || this.readOnly){ return; }
+
+			// Select all text on focus via click if nothing already selected.
+			// Since mouse-up will clear the selection need to defer selection until after mouse-up.
+			// Don't do anything on focus by tabbing into the widget since there's no associated mouse-up event.
+			if(this.selectOnClick && by == "mouse"){
+				this._selectOnClickHandle = this.connect(this.domNode, "onmouseup", function(){
+					// Only select all text on first click; otherwise users would have no way to clear
+					// the selection.
+					this.disconnect(this._selectOnClickHandle);
+
+					// Check if the user selected some text manually (mouse-down, mouse-move, mouse-up)
+					// and if not, then select all the text
+					var textIsNotSelected;
+					if(dojo.isIE){
+						var range = dojo.doc.selection.createRange();
+						var parent = range.parentElement();
+						textIsNotSelected = parent == this.textbox && range.text.length == 0;
+					}else{
+						textIsNotSelected = this.textbox.selectionStart == this.textbox.selectionEnd;
+					}
+					if(textIsNotSelected){
+						dijit.selectInputText(this.textbox);
+					}
+				});
+			}
+
+			this._updatePlaceHolder();
+			
+			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; }
+	dijit.focus(element);
+	if(_document["selection"] && dojo.body()["createTextRange"]){ // IE
+		if(element.createTextRange){
+			var range = element.createTextRange();
+			with(range){
+				collapse(true);
+				moveStart("character", -99999); // move to 0
+				moveStart("character", start); // delta from 0 is the correct position
+				moveEnd("character", stop-start);
+				select();
+			}
+		}
+	}else if(_window["getSelection"]){
+		if(element.setSelectionRange){
+			element.setSelectionRange(start, stop);
+		}
+	}
 };
-}
diff --git a/dijit/form/Textarea.js b/dijit/form/Textarea.js
index 5f267aa..172f206 100644
--- a/dijit/form/Textarea.js
+++ b/dijit/form/Textarea.js
@@ -1,98 +1,146 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.Textarea"]){
-dojo._hasResource["dijit.form.Textarea"]=true;
 dojo.provide("dijit.form.Textarea");
+
 dojo.require("dijit.form.SimpleTextarea");
-dojo.declare("dijit.form.Textarea",dijit.form.SimpleTextarea,{cols:"",_previousNewlines:0,_strictMode:(dojo.doc.compatMode!="BackCompat"),_getHeight:function(_1){
-var _2=_1.scrollHeight;
-if(dojo.isIE){
-_2+=_1.offsetHeight-_1.clientHeight-((dojo.isIE<8&&this._strictMode)?dojo._getPadBorderExtents(_1).h:0);
-}else{
-if(dojo.isMoz){
-_2+=_1.offsetHeight-_1.clientHeight;
-}else{
-if(dojo.isWebKit&&!(dojo.isSafari<4)){
-_2+=dojo._getBorderExtents(_1).h;
-}else{
-_2+=dojo._getPadBorderExtents(_1).h;
-}
-}
-}
-return _2;
-},_estimateHeight:function(_3){
-_3.style.maxHeight="";
-_3.style.height="auto";
-_3.rows=(_3.value.match(/\n/g)||[]).length+1;
-},_needsHelpShrinking:dojo.isMoz||dojo.isWebKit,_onInput:function(){
-this.inherited(arguments);
-if(this._busyResizing){
-return;
-}
-this._busyResizing=true;
-var _4=this.textbox;
-if(_4.scrollHeight&&_4.offsetHeight&&_4.clientHeight){
-var _5=this._getHeight(_4)+"px";
-if(_4.style.height!=_5){
-_4.style.maxHeight=_4.style.height=_5;
-}
-if(this._needsHelpShrinking){
-if(this._setTimeoutHandle){
-clearTimeout(this._setTimeoutHandle);
-}
-this._setTimeoutHandle=setTimeout(dojo.hitch(this,"_shrink"),0);
-}
-}else{
-this._estimateHeight(_4);
-}
-this._busyResizing=false;
-},_busyResizing:false,_shrink:function(){
-this._setTimeoutHandle=null;
-if(this._needsHelpShrinking&&!this._busyResizing){
-this._busyResizing=true;
-var _6=this.textbox;
-var _7=false;
-if(_6.value==""){
-_6.value=" ";
-_7=true;
-}
-var _8=_6.scrollHeight;
-if(!_8){
-this._estimateHeight(_6);
-}else{
-var _9=_6.style.paddingBottom;
-var _a=dojo._getPadExtents(_6);
-_a=_a.h-_a.t;
-_6.style.paddingBottom=_a+1+"px";
-var _b=this._getHeight(_6)-1+"px";
-if(_6.style.maxHeight!=_b){
-_6.style.paddingBottom=_a+_8+"px";
-_6.scrollTop=0;
-_6.style.maxHeight=this._getHeight(_6)-_8+"px";
-}
-_6.style.paddingBottom=_9;
-}
-if(_7){
-_6.value="";
-}
-this._busyResizing=false;
-}
-},resize:function(){
-this._onInput();
-},_setValueAttr:function(){
-this.inherited(arguments);
-this.resize();
-},postCreate:function(){
-this.inherited(arguments);
-dojo.style(this.textbox,{overflowY:"hidden",overflowX:"auto",boxSizing:"border-box",MsBoxSizing:"border-box",WebkitBoxSizing:"border-box",MozBoxSizing:"border-box"});
-this.connect(this.textbox,"onscroll",this._onInput);
-this.connect(this.textbox,"onresize",this._onInput);
-this.connect(this.textbox,"onfocus",this._onInput);
-setTimeout(dojo.hitch(this,"resize"),0);
-}});
-}
+
+dojo.declare(
+	"dijit.form.Textarea",
+	dijit.form.SimpleTextarea,
+	{
+	// summary:
+	//		A textarea widget that adjusts it's height according to the amount of data.
+	//
+	// description:
+	//		A textarea that dynamically expands/contracts (changing it's height) as
+	//		the user types, to display all the text without requiring a scroll bar.
+	//
+	//		Takes nearly all the parameters (name, value, etc.) that a vanilla textarea takes.
+	//		Rows is not supported since this widget adjusts the height.
+	//
+	// example:
+	// |	<textarea dojoType="dijit.form.TextArea">...</textarea>
+
+
+	// Override SimpleTextArea.cols to default to width:100%, for backward compatibility
+	cols: "",
+
+	_previousNewlines: 0,
+	_strictMode: (dojo.doc.compatMode != 'BackCompat'), // not the same as !dojo.isQuirks
+
+	_getHeight: function(textarea){
+		var newH = textarea.scrollHeight;
+		if(dojo.isIE){
+			newH += textarea.offsetHeight - textarea.clientHeight - ((dojo.isIE < 8 && this._strictMode) ? dojo._getPadBorderExtents(textarea).h : 0);
+		}else if(dojo.isMoz){
+			newH += textarea.offsetHeight - textarea.clientHeight; // creates room for horizontal scrollbar
+		}else if(dojo.isWebKit && !(dojo.isSafari < 4)){ // Safari 4.0 && Chrome
+			newH += dojo._getBorderExtents(textarea).h;
+		}else{ // Safari 3.x and Opera 9.6
+			newH += dojo._getPadBorderExtents(textarea).h;
+		}
+		return newH;
+	},
+
+	_estimateHeight: function(textarea){
+		// summary:
+		// 		Approximate the height when the textarea is invisible with the number of lines in the text.
+		// 		Fails when someone calls setValue with a long wrapping line, but the layout fixes itself when the user clicks inside so . . .
+		// 		In IE, the resize event is supposed to fire when the textarea becomes visible again and that will correct the size automatically.
+		//
+		textarea.style.maxHeight = "";
+		textarea.style.height = "auto";
+		// #rows = #newlines+1
+		// Note: on Moz, the following #rows appears to be 1 too many.
+		// Actually, Moz is reserving room for the scrollbar.
+		// If you increase the font size, this behavior becomes readily apparent as the last line gets cut off without the +1.
+		textarea.rows = (textarea.value.match(/\n/g) || []).length + 1;
+	},
+
+	_needsHelpShrinking: dojo.isMoz || dojo.isWebKit,
+
+	_onInput: function(){
+		// Override SimpleTextArea._onInput() to deal with height adjustment
+		this.inherited(arguments);
+		if(this._busyResizing){ return; }
+		this._busyResizing = true;
+		var textarea = this.textbox;
+		if(textarea.scrollHeight && textarea.offsetHeight && textarea.clientHeight){
+			var newH = this._getHeight(textarea) + "px";
+			if(textarea.style.height != newH){
+				textarea.style.maxHeight = textarea.style.height = newH;
+			}
+			if(this._needsHelpShrinking){
+				if(this._setTimeoutHandle){
+					clearTimeout(this._setTimeoutHandle);
+				}
+				this._setTimeoutHandle = setTimeout(dojo.hitch(this, "_shrink"), 0); // try to collapse multiple shrinks into 1
+			}
+		}else{
+			// hidden content of unknown size
+			this._estimateHeight(textarea);
+		}
+		this._busyResizing = false;
+	},
+
+	_busyResizing: false,
+	_shrink: function(){
+		// grow paddingBottom to see if scrollHeight shrinks (when it is unneccesarily big)
+		this._setTimeoutHandle = null;
+		if(this._needsHelpShrinking && !this._busyResizing){
+			this._busyResizing = true;
+			var textarea = this.textbox;
+			var empty = false;
+			if(textarea.value == ''){
+				textarea.value = ' '; // prevent collapse all the way back to 0
+				empty = true;
+			}
+			var scrollHeight = textarea.scrollHeight;
+			if(!scrollHeight){
+				this._estimateHeight(textarea);
+			}else{
+				var oldPadding = textarea.style.paddingBottom;
+				var newPadding = dojo._getPadExtents(textarea);
+				newPadding = newPadding.h - newPadding.t;
+				textarea.style.paddingBottom = newPadding + 1 + "px"; // tweak padding to see if height can be reduced
+				var newH = this._getHeight(textarea) - 1 + "px"; // see if the height changed by the 1px added
+				if(textarea.style.maxHeight != newH){ // if can be reduced, so now try a big chunk
+					textarea.style.paddingBottom = newPadding + scrollHeight + "px";
+					textarea.scrollTop = 0;
+					textarea.style.maxHeight = this._getHeight(textarea) - scrollHeight + "px"; // scrollHeight is the added padding
+				}
+				textarea.style.paddingBottom = oldPadding;
+			}
+			if(empty){
+				textarea.value = '';
+			}
+			this._busyResizing = false;
+		}
+	},
+
+	resize: function(){
+		// summary:
+		//		Resizes the textarea vertically (should be called after a style/value change)
+		this._onInput();
+	},
+
+	_setValueAttr: function(){
+		this.inherited(arguments);
+		this.resize();
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+		// tweak textarea style to reduce browser differences
+		dojo.style(this.textbox, { overflowY: 'hidden', overflowX: 'auto', boxSizing: 'border-box', MsBoxSizing: 'border-box', WebkitBoxSizing: 'border-box', MozBoxSizing: 'border-box' });
+		this.connect(this.textbox, "onscroll", this._onInput);
+		this.connect(this.textbox, "onresize", this._onInput);
+		this.connect(this.textbox, "onfocus", this._onInput); // useful when a previous estimate was off a bit
+		this._setTimeoutHandle = setTimeout(dojo.hitch(this, "resize"), 0);
+	},
+
+	uninitialize: function(){
+		if(this._setTimeoutHandle){
+			clearTimeout(this._setTimeoutHandle);
+		}
+		this.inherited(arguments);
+	}
+});
diff --git a/dijit/form/TimeTextBox.js b/dijit/form/TimeTextBox.js
index e9c46f9..8f9d807 100644
--- a/dijit/form/TimeTextBox.js
+++ b/dijit/form/TimeTextBox.js
@@ -1,14 +1,43 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.TimeTextBox"]){
-dojo._hasResource["dijit.form.TimeTextBox"]=true;
 dojo.provide("dijit.form.TimeTextBox");
+
 dojo.require("dijit._TimePicker");
 dojo.require("dijit.form._DateTimeTextBox");
-dojo.declare("dijit.form.TimeTextBox",dijit.form._DateTimeTextBox,{baseClass:"dijitTextBox dijitTimeTextBox",popupClass:"dijit._TimePicker",_selector:"time",value:new Date("")});
-}
+
+/*=====
+dojo.declare(
+	"dijit.form.TimeTextBox.__Constraints",
+	[dijit.form._DateTimeTextBox.__Constraints, dijit._TimePicker.__Constraints]
+);
+=====*/
+
+dojo.declare(
+	"dijit.form.TimeTextBox",
+	dijit.form._DateTimeTextBox,
+	{
+		// summary:
+		//		A validating, serializable, range-bound time text box with a drop down time picker
+
+		baseClass: "dijitTextBox dijitTimeTextBox",
+		popupClass: "dijit._TimePicker",
+		_selector: "time",
+
+/*=====
+		// constraints: dijit.form.TimeTextBox.__Constraints
+		constraints:{},
+=====*/
+
+		// value: Date
+		//		The value of this widget as a JavaScript Date object.  Note that the date portion implies time zone and daylight savings rules.
+		//
+		//		Example:
+		// |	new dijit.form.TimeTextBox({value: dojo.date.stamp.fromISOString("T12:59:59", new Date())})
+		//
+		//		When passed to the parser in markup, must be specified according to locale-independent
+		//		`dojo.date.stamp.fromISOString` format.
+		//
+		//		Example:
+		// |	<input dojotype='dijit.form.TimeTextBox' value='T12:34:00'>
+		value: new Date("")		// value.toString()="NaN"
+		//FIXME: in markup, you have no control over daylight savings
+	}
+);
diff --git a/dijit/form/ToggleButton.js b/dijit/form/ToggleButton.js
index f05d314..c687449 100644
--- a/dijit/form/ToggleButton.js
+++ b/dijit/form/ToggleButton.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.ToggleButton"]){
-dojo._hasResource["dijit.form.ToggleButton"]=true;
 dojo.provide("dijit.form.ToggleButton");
 dojo.require("dijit.form.Button");
-}
diff --git a/dijit/form/ValidationTextBox.js b/dijit/form/ValidationTextBox.js
index 5a41300..d4f60de 100644
--- a/dijit/form/ValidationTextBox.js
+++ b/dijit/form/ValidationTextBox.js
@@ -1,203 +1,467 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.ValidationTextBox"]){
-dojo._hasResource["dijit.form.ValidationTextBox"]=true;
 dojo.provide("dijit.form.ValidationTextBox");
+
 dojo.require("dojo.i18n");
+
 dojo.require("dijit.form.TextBox");
 dojo.require("dijit.Tooltip");
-dojo.requireLocalization("dijit.form","validate",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit.form.ValidationTextBox",dijit.form.TextBox,{templateString:dojo.cache("dijit.form","templates/ValidationTextBox.html","<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 [...]
-return this.regExp;
-},state:"",tooltipPosition:[],_setValueAttr:function(){
-this.inherited(arguments);
-this.validate(this._focused);
-},validator:function(_2,_3){
-return (new RegExp("^(?:"+this.regExpGen(_3)+")"+(this.required?"":"?")+"$")).test(_2)&&(!this.required||!this._isEmpty(_2))&&(this._isEmpty(_2)||this.parse(_2,_3)!==undefined);
-},_isValidSubset:function(){
-return this.textbox.value.search(this._partialre)==0;
-},isValid:function(_4){
-return this.validator(this.textbox.value,this.constraints);
-},_isEmpty:function(_5){
-return /^\s*$/.test(_5);
-},getErrorMessage:function(_6){
-return this.invalidMessage;
-},getPromptMessage:function(_7){
-return this.promptMessage;
-},_maskValidSubsetError:true,validate:function(_8){
-var _9="";
-var _a=this.disabled||this.isValid(_8);
-if(_a){
-this._maskValidSubsetError=true;
-}
-var _b=!_a&&_8&&this._isValidSubset();
-var _c=this._isEmpty(this.textbox.value);
-if(_c){
-this._maskValidSubsetError=true;
-}
-this.state=(_a||(!this._hasBeenBlurred&&_c)||_b)?"":"Error";
-if(this.state=="Error"){
-this._maskValidSubsetError=false;
-}
-this._setStateClass();
-dijit.setWaiState(this.focusNode,"invalid",_a?"false":"true");
-if(_8){
-if(_c){
-_9=this.getPromptMessage(true);
-}
-if(!_9&&(this.state=="Error"||(_b&&!this._maskValidSubsetError))){
-_9=this.getErrorMessage(true);
-}
-}
-this.displayMessage(_9);
-return _a;
-},_message:"",displayMessage:function(_d){
-if(this._message==_d){
-return;
-}
-this._message=_d;
-dijit.hideTooltip(this.domNode);
-if(_d){
-dijit.showTooltip(_d,this.domNode,this.tooltipPosition);
-}
-},_refreshState:function(){
-this.validate(this._focused);
-this.inherited(arguments);
-},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 _e="";
-if(p!=".*"){
-this.regExp.replace(/\\.|\[\]|\[.*?[^\\]{1}\]|\{.*?\}|\(\?[=:!]|./g,function(re){
-switch(re.charAt(0)){
-case "{":
-case "+":
-case "?":
-case "*":
-case "^":
-case "$":
-case "|":
-case "(":
-_e+=re;
-break;
-case ")":
-_e+="|$)";
-break;
-default:
-_e+="(?:"+re+"|$)";
-break;
-}
-});
-}
-try{
-"".search(_e);
-}
-catch(e){
-_e=this.regExp;
-console.warn("RegExp error in "+this.declaredClass+": "+this.regExp);
-}
-this._partialre="^(?:"+_e+")$";
-},_setDisabledAttr:function(_f){
-this.inherited(arguments);
-this._refreshState();
-},_setRequiredAttr:function(_10){
-this.required=_10;
-dijit.setWaiState(this.focusNode,"required",_10);
-this._refreshState();
-},postCreate:function(){
-if(dojo.isIE){
-var s=dojo.getComputedStyle(this.focusNode);
-if(s){
-var ff=s.fontFamily;
-if(ff){
-this.focusNode.style.fontFamily=ff;
-}
-}
-}
-this.inherited(arguments);
-},reset:function(){
-this._maskValidSubsetError=true;
-this.inherited(arguments);
-},_onBlur:function(){
-this.displayMessage("");
-this.inherited(arguments);
-}});
-dojo.declare("dijit.form.MappedTextBox",dijit.form.ValidationTextBox,{postMixInProperties:function(){
-this.inherited(arguments);
-this.nameAttrSetting="";
-},serialize:function(val,_11){
-return val.toString?val.toString():"";
-},toString:function(){
-var val=this.filter(this.attr("value"));
-return val!=null?(typeof val=="string"?val:this.serialize(val,this.constraints)):"";
-},validate:function(){
-this.valueNode.value=this.toString();
-return this.inherited(arguments);
-},buildRendering:function(){
-this.inherited(arguments);
-this.valueNode=dojo.place("<input type='hidden'"+(this.name?" name='"+this.name+"'":"")+">",this.textbox,"after");
-},reset:function(){
-this.valueNode.value="";
-this.inherited(arguments);
-}});
-dojo.declare("dijit.form.RangeBoundTextBox",dijit.form.MappedTextBox,{rangeMessage:"",rangeCheck:function(_12,_13){
-return ("min" in _13?(this.compare(_12,_13.min)>=0):true)&&("max" in _13?(this.compare(_12,_13.max)<=0):true);
-},isInRange:function(_14){
-return this.rangeCheck(this.attr("value"),this.constraints);
-},_isDefinitelyOutOfRange:function(){
-var val=this.attr("value");
-var _15=false;
-var _16=false;
-if("min" in this.constraints){
-var min=this.constraints.min;
-min=this.compare(val,((typeof min=="number")&&min>=0&&val!=0)?0:min);
-_15=(typeof min=="number")&&min<0;
-}
-if("max" in this.constraints){
-var max=this.constraints.max;
-max=this.compare(val,((typeof max!="number")||max>0)?max:0);
-_16=(typeof max=="number")&&max>0;
-}
-return _15||_16;
-},_isValidSubset:function(){
-return this.inherited(arguments)&&!this._isDefinitelyOutOfRange();
-},isValid:function(_17){
-return this.inherited(arguments)&&((this._isEmpty(this.textbox.value)&&!this.required)||this.isInRange(_17));
-},getErrorMessage:function(_18){
-var v=this.attr("value");
-if(v!==null&&v!==""&&v!==undefined&&!this.isInRange(_18)){
-return this.rangeMessage;
-}
-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(_19,_1a){
-dijit.setWaiState(this.focusNode,"valuenow",_19);
-this.inherited(arguments);
-}});
-}
+
+dojo.requireLocalization("dijit.form", "validate");
+
+/*=====
+	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: dojo.cache("dijit.form", "templates/ValidationTextBox.html"),
+		baseClass: "dijitTextBox dijitValidationTextBox",
+
+		// 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.
+		//		The translated string value is read from the message file by default.
+		// 		Set to "" to use the promptMessage instead.
+		invalidMessage: "$_unset_$",
+
+		// missingMessage: String
+		// 		The message to display if value is empty and the field is required.
+		//		The translated string value is read from the message file by default.
+		// 		Set to "" to use the invalidMessage instead.
+		missingMessage: "$_unset_$",
+
+		// 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.required && this._isEmpty(this.textbox.value)) ? this.missingMessage : 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 isEmpty = this._isEmpty(this.textbox.value);
+			var isValidSubset = !isValid && !isEmpty && isFocused && this._isValidSubset();
+			this.state = ((isValid || ((!this._hasBeenBlurred || isFocused) && isEmpty) || isValidSubset) && this._maskValidSubsetError) ? "" : "Error";
+			if(this.state == "Error"){ this._maskValidSubsetError = isFocused; } // we want the error to show up afer a blur and refocus
+			this._setStateClass();
+			dijit.setWaiState(this.focusNode, "invalid", isValid ? "false" : "true");
+			if(isFocused){
+				if(this.state == "Error"){
+					message = this.getErrorMessage(true);
+				}else{
+					message = this.getPromptMessage(true); // show the prompt whever there's no error
+				}
+				this._maskValidSubsetError = true; // since we're focused, always mask warnings
+			}
+			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, !this.isLeftToRight());
+			}
+		},
+
+		_refreshState: function(){
+			// Overrides TextBox._refreshState()
+			this.validate(this._focused);
+			this.inherited(arguments);
+		},
+
+		//////////// INITIALIZATION METHODS ///////////////////////////////////////
+
+		constructor: function(){
+			this.constraints = {};
+		},
+
+		_setConstraintsAttr: function(/* Object */ constraints){
+			if(!constraints.locale && this.lang){
+				constraints.locale = this.lang;
+			}
+			this.constraints = constraints;
+			this._computePartialRE();
+		},
+
+		_computePartialRE: function(){
+			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 + ")$";
+		},
+
+		postMixInProperties: function(){
+			this.inherited(arguments);
+			this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
+			if(this.invalidMessage == "$_unset_$"){ this.invalidMessage = this.messages.invalidMessage; }
+			if(!this.invalidMessage){ this.invalidMessage = this.promptMessage; }
+			if(this.missingMessage == "$_unset_$"){ this.missingMessage = this.messages.missingMessage; }
+			if(!this.missingMessage){ this.missingMessage = this.invalidMessage; }
+			this._setConstraintsAttr(this.constraints); // this needs to happen now (and later) due to codependency on _set*Attr calls attachPoints
+		},
+
+		_setDisabledAttr: function(/*Boolean*/ value){
+			this.inherited(arguments);	// call FormValueWidget._setDisabledAttr()
+			this._refreshState();
+		},
+
+		_setRequiredAttr: function(/*Boolean*/ value){
+			this.required = value;
+			dijit.setWaiState(this.focusNode, "required", value);
+			this._refreshState();
+		},
+
+		reset:function(){
+			// Overrides dijit.form.TextBox.reset() by also
+			// hiding errors about partial matches
+			this._maskValidSubsetError = true;
+			this.inherited(arguments);
+		},
+
+		_onBlur: function(){
+			this.displayMessage('');
+			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.get('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).
+			// Passing in name as markup rather than calling dojo.create() with an attrs argument
+			// to make dojo.query(input[name=...]) work on IE. (see #8660)
+			this.valueNode = dojo.place("<input type='hidden'" + (this.name ? " name='" + this.name + "'" : "") + ">", this.textbox, "after");
+		},
+
+		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
+			return	("min" in constraints? (this.compare(primitive,constraints.min) >= 0) : true) &&
+				("max" in constraints? (this.compare(primitive,constraints.max) <= 0) : 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.get('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.get('value');
+			var isTooLittle = false;
+			var isTooMuch = false;
+			if("min" in this.constraints){
+				var min = this.constraints.min;
+				min = this.compare(val, ((typeof min == "number") && min >= 0 && val !=0) ? 0 : min);
+				isTooLittle = (typeof min == "number") && min < 0;
+			}
+			if("max" in this.constraints){
+				var max = this.constraints.max;
+				max = this.compare(val, ((typeof max != "number") || max > 0) ? max : 0);
+				isTooMuch = (typeof max == "number") && max > 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
+			var v = this.get('value');
+			if(v !== null && v !== '' && v !== undefined && (typeof v != "number" || !isNaN(v)) && !this.isInRange(isFocused)){ // don't check isInRange w/o a real value
+				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;
+			}
+		},
+
+		_setConstraintsAttr: function(/* Object */ constraints){
+			this.inherited(arguments);
+			if(this.focusNode){ // not set when called from postMixInProperties
+				if(this.constraints.min !== undefined){
+					dijit.setWaiState(this.focusNode, "valuemin", this.constraints.min);
+				}else{
+					dijit.removeWaiState(this.focusNode, "valuemin");
+				}
+				if(this.constraints.max !== undefined){
+					dijit.setWaiState(this.focusNode, "valuemax", this.constraints.max);
+				}else{
+					dijit.removeWaiState(this.focusNode, "valuemax");
+				}
+			}
+		},
+
+		_setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange){
+			// summary:
+			//		Hook so attr('value', ...) works.
+
+			dijit.setWaiState(this.focusNode, "valuenow", value);
+			this.inherited(arguments);
+		}
+	}
+);
diff --git a/dijit/form/VerticalRule.js b/dijit/form/VerticalRule.js
index b8b89e0..2173220 100644
--- a/dijit/form/VerticalRule.js
+++ b/dijit/form/VerticalRule.js
@@ -1,13 +1,25 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.VerticalRule"]){
-dojo._hasResource["dijit.form.VerticalRule"]=true;
 dojo.provide("dijit.form.VerticalRule");
+
 dojo.require("dijit.form.HorizontalRule");
-dojo.declare("dijit.form.VerticalRule",dijit.form.HorizontalRule,{templateString:"<div class=\"dijitRuleContainer dijitRuleContainerV\"></div>",_positionPrefix:"<div class=\"dijitRuleMark dijitRuleMarkV\" style=\"top:",_isHorizontal:false});
-}
+
+dojo.declare("dijit.form.VerticalRule", dijit.form.HorizontalRule,
+{
+	// summary:
+	//		Hash marks for the `dijit.form.VerticalSlider`
+
+	templateString: '<div class="dijitRuleContainer dijitRuleContainerV"></div>',
+	_positionPrefix: '<div class="dijitRuleMark dijitRuleMarkV" style="top:',
+
+/*=====
+	// container: String
+	//		This is either "leftDecoration" or "rightDecoration",
+	//		to indicate whether this rule goes to the left or to the right of the slider.
+	//		Note that on RTL system, "leftDecoration" would actually go to the right, and vice-versa.
+	container: "",
+=====*/
+
+	// Overrides HorizontalRule._isHorizontal
+	_isHorizontal: false
+
+});
+
diff --git a/dijit/form/VerticalRuleLabels.js b/dijit/form/VerticalRuleLabels.js
index 5d829af..d74bf65 100644
--- a/dijit/form/VerticalRuleLabels.js
+++ b/dijit/form/VerticalRuleLabels.js
@@ -1,15 +1,22 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.VerticalRuleLabels"]){
-dojo._hasResource["dijit.form.VerticalRuleLabels"]=true;
 dojo.provide("dijit.form.VerticalRuleLabels");
+
 dojo.require("dijit.form.HorizontalRuleLabels");
-dojo.declare("dijit.form.VerticalRuleLabels",dijit.form.HorizontalRuleLabels,{templateString:"<div class=\"dijitRuleContainer dijitRuleContainerV dijitRuleLabelsContainer dijitRuleLabelsContainerV\"></div>",_positionPrefix:"<div class=\"dijitRuleLabelContainer dijitRuleLabelContainerV\" style=\"top:",_labelPrefix:"\"><span class=\"dijitRuleLabel dijitRuleLabelV\">",_calcPosition:function(_1){
-return 100-_1;
-}});
-}
+
+dojo.declare("dijit.form.VerticalRuleLabels", dijit.form.HorizontalRuleLabels,
+{
+	// summary:
+	//		Labels for the `dijit.form.VerticalSlider`
+
+	templateString: '<div class="dijitRuleContainer dijitRuleContainerV dijitRuleLabelsContainer dijitRuleLabelsContainerV"></div>',
+
+	_positionPrefix: '<div class="dijitRuleLabelContainer dijitRuleLabelContainerV" style="top:',
+	_labelPrefix: '"><span class="dijitRuleLabel dijitRuleLabelV">',
+
+	_calcPosition: function(pos){
+		// Overrides HorizontalRuleLabel._calcPosition()
+		return 100-pos;
+	},
+
+	// needed to prevent labels from being reversed in RTL mode
+	_isHorizontal: false
+});
\ No newline at end of file
diff --git a/dijit/form/VerticalSlider.js b/dijit/form/VerticalSlider.js
index 292c8b6..517f702 100644
--- a/dijit/form/VerticalSlider.js
+++ b/dijit/form/VerticalSlider.js
@@ -1,39 +1,32 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form.VerticalSlider"]){
-dojo._hasResource["dijit.form.VerticalSlider"]=true;
 dojo.provide("dijit.form.VerticalSlider");
+
 dojo.require("dijit.form.HorizontalSlider");
-dojo.declare("dijit.form.VerticalSlider",dijit.form.HorizontalSlider,{templateString:dojo.cache("dijit.form","templates/VerticalSlider.html","<table class=\"dijitReset dijitSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\" dojoAttachEvent=\"onkeypress:_onKeyPress,onkeyup:_onKeyUp\"\n><tbody class=\"dijitReset\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV\"\n\t\t [...]
-if(this._started){
-return;
-}
-if(!this.isLeftToRight()&&dojo.isMoz){
-if(this.leftDecoration){
-this._rtlRectify(this.leftDecoration);
-}
-if(this.rightDecoration){
-this._rtlRectify(this.rightDecoration);
-}
-}
-this.inherited(arguments);
-},_isReversed:function(){
-return this._descending;
-},_rtlRectify:function(_1){
-var _2=[];
-while(_1.firstChild){
-_2.push(_1.firstChild);
-_1.removeChild(_1.firstChild);
-}
-for(var i=_2.length-1;i>=0;i--){
-if(_2[i]){
-_1.appendChild(_2[i]);
-}
-}
-}});
-}
+
+dojo.declare(
+	"dijit.form.VerticalSlider",
+	dijit.form.HorizontalSlider,
+{
+	// summary:
+	//		A form widget that allows one to select a value with a vertically draggable handle
+
+	templateString: dojo.cache('dijit.form','templates/VerticalSlider.html'),
+	_mousePixelCoord: "pageY",
+	_pixelCount: "h",
+	_startingPixelCoord: "y",
+	_startingPixelCount: "t",
+	_handleOffsetCoord: "top",
+	_progressPixelSize: "height",
+
+	// _descending: Boolean
+	//	   Specifies if the slider values go from high-on-top (true), or low-on-top (false)
+	//	TODO: expose this in 1.2 - the css progress/remaining bar classes need to be reversed
+	_descending: true,
+
+	_isReversed: function(){
+		// summary:
+		//		Overrides HorizontalSlider._isReversed.
+		//		Indicates if values are high on top (with low numbers on the bottom).
+		return this._descending;
+	}
+});
+
diff --git a/dijit/form/_DateTimeTextBox.js b/dijit/form/_DateTimeTextBox.js
index c4c55ae..eb81515 100644
--- a/dijit/form/_DateTimeTextBox.js
+++ b/dijit/form/_DateTimeTextBox.js
@@ -1,145 +1,270 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form._DateTimeTextBox"]){
-dojo._hasResource["dijit.form._DateTimeTextBox"]=true;
 dojo.provide("dijit.form._DateTimeTextBox");
+
 dojo.require("dojo.date");
 dojo.require("dojo.date.locale");
 dojo.require("dojo.date.stamp");
 dojo.require("dijit.form.ValidationTextBox");
-dojo.declare("dijit.form._DateTimeTextBox",dijit.form.RangeBoundTextBox,{regExpGen:dojo.date.locale.regexp,datePackage:"dojo.date",compare:dojo.date.compare,format:function(_1,_2){
-if(!_1){
-return "";
-}
-return this.dateLocaleModule.format(_1,_2);
-},parse:function(_3,_4){
-return this.dateLocaleModule.parse(_3,_4)||(this._isEmpty(_3)?null:undefined);
-},serialize:function(_5,_6){
-if(_5.toGregorian){
-_5=_5.toGregorian();
-}
-return dojo.date.stamp.toISOString(_5,_6);
-},value:new Date(""),_blankValue:null,popupClass:"",_selector:"",constructor:function(_7){
-var _8=_7.datePackage?_7.datePackage+".Date":"Date";
-this.dateClassObj=dojo.getObject(_8,false);
-this.value=new this.dateClassObj("");
-this.datePackage=_7.datePackage||this.datePackage;
-this.dateLocaleModule=dojo.getObject(this.datePackage+".locale",false);
-this.regExpGen=this.dateLocaleModule.regexp;
-},postMixInProperties:function(){
-this.inherited(arguments);
-if(!this.value||this.value.toString()==dijit.form._DateTimeTextBox.prototype.value.toString()){
-this.value=null;
-}
-var _9=this.constraints;
-_9.selector=this._selector;
-_9.fullYear=true;
-var _a=dojo.date.stamp.fromISOString;
-if(typeof _9.min=="string"){
-_9.min=_a(_9.min);
-}
-if(typeof _9.max=="string"){
-_9.max=_a(_9.max);
-}
-},_onFocus:function(_b){
-this._open();
-this.inherited(arguments);
-},_setValueAttr:function(_c,_d,_e){
-if(_c instanceof Date&&!(this.dateClassObj instanceof Date)){
-_c=new this.dateClassObj(_c);
-}
-this.inherited(arguments);
-if(this._picker){
-if(!_c){
-_c=new this.dateClassObj();
-}
-this._picker.attr("value",_c);
-}
-},_open:function(){
-if(this.disabled||this.readOnly||!this.popupClass){
-return;
-}
-var _f=this;
-if(!this._picker){
-var _10=dojo.getObject(this.popupClass,false);
-this._picker=new _10({onValueSelected:function(_11){
-if(_f._tabbingAway){
-delete _f._tabbingAway;
-}else{
-_f.focus();
-}
-setTimeout(dojo.hitch(_f,"_close"),1);
-dijit.form._DateTimeTextBox.superclass._setValueAttr.call(_f,_11,true);
-},id:this.id+"_popup",lang:_f.lang,constraints:_f.constraints,datePackage:_f.datePackage,isDisabledDate:function(_12){
-var _13=dojo.date.compare;
-var _14=_f.constraints;
-return _14&&(_14.min&&(_13(_14.min,_12,_f._selector)>0)||(_14.max&&_13(_14.max,_12,_f._selector)<0));
-}});
-this._picker.attr("value",this.attr("value")||new this.dateClassObj());
-}
-if(!this._opened){
-dijit.popup.open({parent:this,popup:this._picker,orient:{"BL":"TL","TL":"BL"},around:this.domNode,onCancel:dojo.hitch(this,this._close),onClose:function(){
-_f._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(){
-this._close();
-if(this._picker){
-this._picker.destroy();
-delete this._picker;
-}
-this.inherited(arguments);
-},_getDisplayedValueAttr:function(){
-return this.textbox.value;
-},_setDisplayedValueAttr:function(_15,_16){
-this._setValueAttr(this.parse(_15,this.constraints),_16,_15);
-},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);
-this.connect(this.focusNode,"onclick",this._open);
-},_onKeyPress:function(e){
-var p=this._picker,dk=dojo.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||e.metaKey)){
-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)){
-setTimeout(dojo.hitch(this,function(){
-dijit.placeOnScreenAroundElement(p.domNode.parentNode,this.domNode,{"BL":"TL","TL":"BL"},p.orient?dojo.hitch(p,"orient"):null);
-}),1);
-}
-}
-}
-}
-}});
-}
+
+new Date("X"); // workaround for #11279, new Date("") == NaN
+
+/*=====
+dojo.declare(
+	"dijit.form._DateTimeTextBox.__Constraints",
+	[dijit.form.RangeBoundTextBox.__Constraints, dojo.date.locale.__FormatOptions], {
+	// summary:
+	//		Specifies both the rules on valid/invalid values (first/last date/time allowed),
+	//		and also formatting options for how the date/time is displayed.
+	// example:
+	//		To restrict to dates within 2004, displayed in a long format like "December 25, 2005":
+	//	|		{min:'2004-01-01',max:'2004-12-31', formatLength:'long'}
+});
+=====*/
+
+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
+		//		Despite the name, this parameter specifies both constraints on the input
+		//		(including starting/ending dates/times allowed) as well as
+		//		formatting options like whether the date is displayed in long (ex: December 25, 2005)
+		//		or short (ex: 12/25/2005) format.   See `dijit.form._DateTimeTextBox.__Constraints` for details.
+		/*=====
+		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,
+
+		// datePackage: String
+		//	JavaScript namespace to find calendar routines.  Uses Gregorian calendar routines
+		//	at dojo.date, by default.
+		datePackage: "dojo.date",
+
+		// 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 this.dateLocaleModule.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 this.dateLocaleModule.parse(value, constraints) || (this._isEmpty(value) ? null : undefined);	 // Date
+		},
+
+		// Overrides ValidationTextBox.serialize() to serialize a date in canonical ISO format.
+		serialize: function(/*anything*/val, /*Object?*/options){
+			if(val.toGregorian){
+				val = val.toGregorian();
+			}
+			return dojo.date.stamp.toISOString(val, options);
+		},
+
+		// value: Date
+		//		The value of this widget as a JavaScript Date object.  Use get("value") / set("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: "",
+
+		constructor: function(/*Object*/args){
+			var dateClass = args.datePackage ? args.datePackage + ".Date" : "Date";
+			this.dateClassObj = dojo.getObject(dateClass, false);
+			this.value = new this.dateClassObj("");
+
+			this.datePackage = args.datePackage || this.datePackage;
+			this.dateLocaleModule = dojo.getObject(this.datePackage + ".locale", false);
+			this.regExpGen = this.dateLocaleModule.regexp;
+		},
+
+		_setConstraintsAttr: function(/* Object */ 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); }
+			this.inherited(arguments, [constraints]);
+		},
+
+		_onFocus: function(/*Event*/ evt){
+			// summary:
+			//		open the popup
+			this._open();
+			this.inherited(arguments);
+		},
+
+		_setValueAttr: function(/*Date*/ value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
+			// summary:
+			//		Sets the date on this textbox.  Note that `value` must be like a Javascript Date object.
+			if(value !== undefined){
+				if(!value || value.toString() == dijit.form._DateTimeTextBox.prototype.value.toString()){
+					value = null;
+				}
+				if(value instanceof Date && !(this.dateClassObj instanceof Date)){
+					value = new this.dateClassObj(value);
+				}
+			}
+			this.inherited(arguments, [value, priorityChange, formattedValue]);
+			if(this._picker){
+				// #3948: fix blank date on popup only
+				if(!value){value = new this.dateClassObj();}
+				this._picker.set('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);
+					},
+					id: this.id + "_popup",
+					dir: textBox.dir,
+					lang: textBox.lang,
+					value: this.get('value') || new this.dateClassObj(),
+					constraints: textBox.constraints,
+
+					datePackage: textBox.datePackage,
+
+					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, textBox._selector) > 0) ||
+							(constraints.max && compare(constraints.max, date, textBox._selector) < 0)
+						);
+					}
+				});
+			}
+			if(!this._opened){
+				// Open drop down.  Align left sides of input box and drop down, even in RTL mode,
+				// otherwise positioning thrown off when the drop down width is changed in marginBox call below (#10676)
+				dijit.popup.open({
+					parent: this,
+					popup: this._picker,
+					orient: {'BL':'TL', 'TL':'BL'},
+					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);
+			this.connect(this.focusNode, 'onclick', this._open);
+		},
+
+		_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 || e.metaKey)){
+				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(){
+					if(this._picker && this._opened){
+						dijit.placeOnScreenAroundElement(p.domNode.parentNode, this.domNode, {'BL':'TL', 'TL':'BL'}, p.orient ? dojo.hitch(p, "orient") : null);
+					}
+				}), 1);
+			}
+		}
+	}
+);
diff --git a/dijit/form/_FormMixin.js b/dijit/form/_FormMixin.js
index fe51939..e2e74c0 100644
--- a/dijit/form/_FormMixin.js
+++ b/dijit/form/_FormMixin.js
@@ -1,157 +1,407 @@
-/*
-	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
-*/
+dojo.provide("dijit.form._FormMixin");
 
+dojo.require("dojo.window");
 
-if(!dojo._hasResource["dijit.form._FormMixin"]){
-dojo._hasResource["dijit.form._FormMixin"]=true;
-dojo.provide("dijit.form._FormMixin");
-dojo.declare("dijit.form._FormMixin",null,{reset:function(){
-dojo.forEach(this.getDescendants(),function(_1){
-if(_1.reset){
-_1.reset();
-}
-});
-},validate:function(){
-var _2=false;
-return dojo.every(dojo.map(this.getDescendants(),function(_3){
-_3._hasBeenBlurred=true;
-var _4=_3.disabled||!_3.validate||_3.validate();
-if(!_4&&!_2){
-dijit.scrollIntoView(_3.containerNode||_3.domNode);
-_3.focus();
-_2=true;
-}
-return _4;
-}),function(_5){
-return _5;
-});
-},setValues:function(_6){
-dojo.deprecated(this.declaredClass+"::setValues() is deprecated. Use attr('value', val) instead.","","2.0");
-return this.attr("value",_6);
-},_setValueAttr:function(_7){
-var _8={};
-dojo.forEach(this.getDescendants(),function(_9){
-if(!_9.name){
-return;
-}
-var _a=_8[_9.name]||(_8[_9.name]=[]);
-_a.push(_9);
-});
-for(var _b in _8){
-if(!_8.hasOwnProperty(_b)){
-continue;
-}
-var _c=_8[_b],_d=dojo.getObject(_b,false,_7);
-if(_d===undefined){
-continue;
-}
-if(!dojo.isArray(_d)){
-_d=[_d];
-}
-if(typeof _c[0].checked=="boolean"){
-dojo.forEach(_c,function(w,i){
-w.attr("value",dojo.indexOf(_d,w.value)!=-1);
-});
-}else{
-if(_c[0].multiple){
-_c[0].attr("value",_d);
-}else{
-dojo.forEach(_c,function(w,i){
-w.attr("value",_d[i]);
-});
-}
-}
-}
-},getValues:function(){
-dojo.deprecated(this.declaredClass+"::getValues() is deprecated. Use attr('value') instead.","","2.0");
-return this.attr("value");
-},_getValueAttr:function(){
-var _e={};
-dojo.forEach(this.getDescendants(),function(_f){
-var _10=_f.name;
-if(!_10||_f.disabled){
-return;
-}
-var _11=_f.attr("value");
-if(typeof _f.checked=="boolean"){
-if(/Radio/.test(_f.declaredClass)){
-if(_11!==false){
-dojo.setObject(_10,_11,_e);
-}else{
-_11=dojo.getObject(_10,false,_e);
-if(_11===undefined){
-dojo.setObject(_10,null,_e);
-}
-}
-}else{
-var ary=dojo.getObject(_10,false,_e);
-if(!ary){
-ary=[];
-dojo.setObject(_10,ary,_e);
-}
-if(_11!==false){
-ary.push(_11);
-}
-}
-}else{
-var _12=dojo.getObject(_10,false,_e);
-if(typeof _12!="undefined"){
-if(dojo.isArray(_12)){
-_12.push(_11);
-}else{
-dojo.setObject(_10,[_12,_11],_e);
-}
-}else{
-dojo.setObject(_10,_11,_e);
-}
-}
-});
-return _e;
-},isValid:function(){
-this._invalidWidgets=dojo.filter(this.getDescendants(),function(_13){
-return !_13.disabled&&_13.isValid&&!_13.isValid();
-});
-return !this._invalidWidgets.length;
-},onValidStateChange:function(_14){
-},_widgetChange:function(_15){
-var _16=this._lastValidState;
-if(!_15||this._lastValidState===undefined){
-_16=this.isValid();
-if(this._lastValidState===undefined){
-this._lastValidState=_16;
-}
-}else{
-if(_15.isValid){
-this._invalidWidgets=dojo.filter(this._invalidWidgets||[],function(w){
-return (w!=_15);
-},this);
-if(!_15.isValid()&&!_15.attr("disabled")){
-this._invalidWidgets.push(_15);
-}
-_16=(this._invalidWidgets.length===0);
-}
-}
-if(_16!==this._lastValidState){
-this._lastValidState=_16;
-this.onValidStateChange(_16);
-}
-},connectChildren:function(){
-dojo.forEach(this._changeConnections,dojo.hitch(this,"disconnect"));
-var _17=this;
-var _18=this._changeConnections=[];
-dojo.forEach(dojo.filter(this.getDescendants(),function(_19){
-return _19.validate;
-}),function(_1a){
-_18.push(_17.connect(_1a,"validate",dojo.hitch(_17,"_widgetChange",_1a)));
-_18.push(_17.connect(_1a,"_setDisabledAttr",dojo.hitch(_17,"_widgetChange",_1a)));
-});
-this._widgetChange(null);
-},startup:function(){
-this.inherited(arguments);
-this._changeConnections=[];
-this.connectChildren();
-}});
-}
+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 child widget with a name and value.
+	//		Child widgets without names are not part of the hash.
+	// 
+	//		If there are multiple child widgets w/the same name, value is an array,
+	//		unless they are radio buttons in which case value is a scalar (since only
+	//		one radio button can be checked at a time).
+	//
+	//		If a child widget's name is a dot separated list (like a.b.c.d), it's a nested structure.
+	//
+	//		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
+					dojo.window.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 set('value', val) instead.", "", "2.0");
+			return this.set('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.set('value', dojo.indexOf(values, w.value) != -1);
+					});
+				}else if(widgets[0].multiple){
+					// it takes an array (e.g. multi-select)
+					widgets[0].set('value', values);
+				}else{
+					// otherwise, values is a list of values to be assigned sequentially to each widget
+					dojo.forEach(widgets, function(w, i){
+						w.set('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)
+
+				// TODO: maybe should call dojo.getNodeProp() instead
+				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 get('value') instead.", "", "2.0");
+			return this.get('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.get('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{
+					var prev=dojo.getObject(name, false, obj);
+					if(typeof prev != "undefined"){
+						if(dojo.isArray(prev)){
+							prev.push(value);
+						}else{
+							dojo.setObject(name, [prev, value], obj);
+						}
+					}else{
+						// unique name
+						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.get("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();
+		}
+	});
diff --git a/dijit/form/_FormSelectWidget.js b/dijit/form/_FormSelectWidget.js
index 8dfae78..13edee1 100644
--- a/dijit/form/_FormSelectWidget.js
+++ b/dijit/form/_FormSelectWidget.js
@@ -1,307 +1,572 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form._FormSelectWidget"]){
-dojo._hasResource["dijit.form._FormSelectWidget"]=true;
 dojo.provide("dijit.form._FormSelectWidget");
+
 dojo.require("dijit.form._FormWidget");
 dojo.require("dojo.data.util.sorter");
-dojo.declare("dijit.form._FormSelectWidget",dijit.form._FormValueWidget,{multiple:false,options:null,store:null,query:null,queryOptions:null,onFetch:null,sortByLabel:true,loadChildrenOnOpen:false,getOptions:function(_1){
-var _2=_1,_3=this.options||[],l=_3.length;
-if(_2===undefined){
-return _3;
-}
-if(dojo.isArray(_2)){
-return dojo.map(_2,"return this.getOptions(item);",this);
-}
-if(dojo.isObject(_1)){
-if(!dojo.some(this.options,function(o,_4){
-if(o===_2||(o.value&&o.value===_2.value)){
-_2=_4;
-return true;
-}
-return false;
-})){
-_2=-1;
-}
-}
-if(typeof _2=="string"){
-for(var i=0;i<l;i++){
-if(_3[i].value===_2){
-_2=i;
-break;
-}
-}
-}
-if(typeof _2=="number"&&_2>=0&&_2<l){
-return this.options[_2];
-}
-return null;
-},addOption:function(_5){
-if(!dojo.isArray(_5)){
-_5=[_5];
-}
-dojo.forEach(_5,function(i){
-if(i&&dojo.isObject(i)){
-this.options.push(i);
-}
-},this);
-this._loadChildren();
-},removeOption:function(_6){
-if(!dojo.isArray(_6)){
-_6=[_6];
-}
-var _7=this.getOptions(_6);
-dojo.forEach(_7,function(i){
-if(i){
-this.options=dojo.filter(this.options,function(_8,_9){
-return (_8.value!==i.value);
-});
-this._removeOptionItem(i);
-}
-},this);
-this._loadChildren();
-},updateOption:function(_a){
-if(!dojo.isArray(_a)){
-_a=[_a];
-}
-dojo.forEach(_a,function(i){
-var _b=this.getOptions(i),k;
-if(_b){
-for(k in i){
-_b[k]=i[k];
-}
-}
-},this);
-this._loadChildren();
-},setStore:function(_c,_d,_e){
-var _f=this.store;
-_e=_e||{};
-if(_f!==_c){
-dojo.forEach(this._notifyConnections||[],dojo.disconnect);
-delete this._notifyConnections;
-if(_c&&_c.getFeatures()["dojo.data.api.Notification"]){
-this._notifyConnections=[dojo.connect(_c,"onNew",this,"_onNewItem"),dojo.connect(_c,"onDelete",this,"_onDeleteItem"),dojo.connect(_c,"onSet",this,"_onSetItem")];
-}
-this.store=_c;
-}
-this._onChangeActive=false;
-if(this.options&&this.options.length){
-this.removeOption(this.options);
-}
-if(_c){
-var cb=function(_10){
-if(this.sortByLabel&&!_e.sort&&_10.length){
-_10.sort(dojo.data.util.sorter.createSortFunction([{attribute:_c.getLabelAttributes(_10[0])[0]}],_c));
-}
-if(_e.onFetch){
-_10=_e.onFetch(_10);
-}
-dojo.forEach(_10,function(i){
-this._addOptionForItem(i);
-},this);
-this._loadingStore=false;
-this.attr("value",(("_pendingValue" in this)?this._pendingValue:_d));
-delete this._pendingValue;
-if(!this.loadChildrenOnOpen){
-this._loadChildren();
-}else{
-this._pseudoLoadChildren(_10);
-}
-this._fetchedWith=_11;
-this._lastValueReported=this.multiple?[]:null;
-this._onChangeActive=true;
-this.onSetStore();
-this._handleOnChange(this.value);
-};
-var _11=dojo.mixin({onComplete:cb,scope:this},_e);
-this._loadingStore=true;
-_c.fetch(_11);
-}else{
-delete this._fetchedWith;
-}
-return _f;
-},_setValueAttr:function(_12,_13){
-if(this._loadingStore){
-this._pendingValue=_12;
-return;
-}
-var _14=this.getOptions()||[];
-if(!dojo.isArray(_12)){
-_12=[_12];
-}
-dojo.forEach(_12,function(i,idx){
-if(!dojo.isObject(i)){
-i=i+"";
-}
-if(typeof i==="string"){
-_12[idx]=dojo.filter(_14,function(_15){
-return _15.value===i;
-})[0]||{value:"",label:""};
-}
-},this);
-_12=dojo.filter(_12,function(i){
-return i&&i.value;
-});
-if(!this.multiple&&(!_12[0]||!_12[0].value)&&_14.length){
-_12[0]=_14[0];
-}
-dojo.forEach(_14,function(i){
-i.selected=dojo.some(_12,function(v){
-return v.value===i.value;
-});
-});
-var val=dojo.map(_12,function(i){
-return i.value;
-}),_16=dojo.map(_12,function(i){
-return i.label;
-});
-this.value=this.multiple?val:val[0];
-this._setDisplay(this.multiple?_16:_16[0]);
-this._updateSelection();
-this._handleOnChange(this.value,_13);
-},_getDisplayedValueAttr:function(){
-var val=this.attr("value");
-if(!dojo.isArray(val)){
-val=[val];
-}
-var ret=dojo.map(this.getOptions(val),function(v){
-if(v&&"label" in v){
-return v.label;
-}else{
-if(v){
-return v.value;
-}
-}
-return null;
-},this);
-return this.multiple?ret:ret[0];
-},_getValueDeprecated:false,getValue:function(){
-return this._lastValue;
-},undo:function(){
-this._setValueAttr(this._lastValueReported,false);
-},_loadChildren:function(){
-if(this._loadingStore){
-return;
-}
-dojo.forEach(this._getChildren(),function(_17){
-_17.destroyRecursive();
-});
-dojo.forEach(this.options,this._addOptionItem,this);
-this._updateSelection();
-},_updateSelection:function(){
-this.value=this._getValueFromOpts();
-var val=this.value;
-if(!dojo.isArray(val)){
-val=[val];
-}
-if(val&&val[0]){
-dojo.forEach(this._getChildren(),function(_18){
-var _19=dojo.some(val,function(v){
-return _18.option&&(v===_18.option.value);
+
+/*=====
+dijit.form.__SelectOption = function(){
+	// value: String
+	//		The value of the option.  Setting to empty (or missing) will
+	//		place a separator at that location
+	// label: String
+	//		The label for our option.  It can contain html tags.
+	//  selected: Boolean
+	//		Whether or not we are a selected option
+	// disabled: Boolean
+	//		Whether or not this specific option is disabled
+	this.value = value;
+	this.label = label;
+	this.selected = selected;
+	this.disabled = disabled;
+}
+=====*/
+
+dojo.declare("dijit.form._FormSelectWidget", dijit.form._FormValueWidget, {
+	// summary:
+	//		Extends _FormValueWidget in order to provide "select-specific"
+	//		values - i.e., those values that are unique to <select> elements.
+	//		This also provides the mechanism for reading the elements from
+	//		a store, if desired.
+
+	// multiple: Boolean
+	//		Whether or not we are multi-valued
+	multiple: false,
+
+	// options: dijit.form.__SelectOption[]
+	//		The set of options for our select item.  Roughly corresponds to
+	//      the html <option> tag.
+	options: null,
+
+	// store: dojo.data.api.Identity
+	//		A store which, at the very least impelements dojo.data.api.Identity
+	//		to use for getting our list of options - rather than reading them
+	//		from the <option> html tags.
+	store: null,
+
+	// query: object
+	//		A query to use when fetching items from our store
+	query: null,
+
+	// queryOptions: object
+	//		Query options to use when fetching from the store
+	queryOptions: null,
+
+	// onFetch: Function
+	//		A callback to do with an onFetch - but before any items are actually
+	//		iterated over (i.e. to filter even futher what you want to add)
+	onFetch: null,
+
+	// sortByLabel: boolean
+	//		Flag to sort the options returned from a store by the label of
+	//		the store.
+	sortByLabel: true,
+
+
+	// loadChildrenOnOpen: boolean
+	//		By default loadChildren is called when the items are fetched from the
+	//		store.  This property allows delaying loadChildren (and the creation
+	//		of the options/menuitems) until the user opens the click the button.
+	//		dropdown
+	loadChildrenOnOpen: false,
+
+	getOptions: function(/* anything */ valueOrIdx){
+		// summary:
+		//		Returns a given option (or options).
+		// valueOrIdx:
+		//		If passed in as a string, that string is used to look up the option
+		//		in the array of options - based on the value property.
+		//		(See dijit.form.__SelectOption).
+		//
+		//		If passed in a number, then the option with the given index (0-based)
+		//		within this select will be returned.
+		//
+		//		If passed in a dijit.form.__SelectOption, the same option will be
+		//		returned if and only if it exists within this select.
+		//
+		//		If passed an array, then an array will be returned with each element
+		//		in the array being looked up.
+		//
+		//		If not passed a value, then all options will be returned
+		//
+		// returns:
+		//		The option corresponding with the given value or index.  null
+		//		is returned if any of the following are true:
+		//			- A string value is passed in which doesn't exist
+		//			- An index is passed in which is outside the bounds of the array of options
+		//			- A dijit.form.__SelectOption is passed in which is not a part of the select
+
+		// NOTE: the compare for passing in a dijit.form.__SelectOption checks
+		//		if the value property matches - NOT if the exact option exists
+		// NOTE: if passing in an array, null elements will be placed in the returned
+		//		array when a value is not found.
+		var lookupValue = valueOrIdx, opts = this.options || [], l = opts.length;
+
+		if(lookupValue === undefined){
+			return opts; // dijit.form.__SelectOption[]
+		}
+		if(dojo.isArray(lookupValue)){
+			return dojo.map(lookupValue, "return this.getOptions(item);", this); // dijit.form.__SelectOption[]
+		}
+		if(dojo.isObject(valueOrIdx)){
+			// We were passed an option - so see if it's in our array (directly),
+			// and if it's not, try and find it by value.
+			if(!dojo.some(this.options, function(o, idx){
+				if(o === lookupValue ||
+					(o.value && o.value === lookupValue.value)){
+					lookupValue = idx;
+					return true;
+				}
+				return false;
+			})){
+				lookupValue = -1;
+			}
+		}
+		if(typeof lookupValue == "string"){
+			for(var i=0; i<l; i++){
+				if(opts[i].value === lookupValue){
+					lookupValue = i;
+					break;
+				}
+			}
+		}
+		if(typeof lookupValue == "number" && lookupValue >= 0 && lookupValue < l){
+			return this.options[lookupValue] // dijit.form.__SelectOption
+		}
+		return null; // null
+	},
+
+	addOption: function(/* dijit.form.__SelectOption, dijit.form.__SelectOption[] */ option){
+		// summary:
+		//		Adds an option or options to the end of the select.  If value
+		//		of the option is empty or missing, a separator is created instead.
+		//		Passing in an array of options will yield slightly better performance
+		//		since the children are only loaded once.
+		if(!dojo.isArray(option)){ option = [option]; }
+		dojo.forEach(option, function(i){
+			if(i && dojo.isObject(i)){
+				this.options.push(i);
+			}
+		}, this);
+		this._loadChildren();
+	},
+
+	removeOption: function(/* string, dijit.form.__SelectOption, number, or array */ valueOrIdx){
+		// summary:
+		//		Removes the given option or options.  You can remove by string
+		//		(in which case the value is removed), number (in which case the
+		//		index in the options array is removed), or select option (in
+		//		which case, the select option with a matching value is removed).
+		//		You can also pass in an array of those values for a slightly
+		//		better performance since the children are only loaded once.
+		if(!dojo.isArray(valueOrIdx)){ valueOrIdx = [valueOrIdx]; }
+		var oldOpts = this.getOptions(valueOrIdx);
+		dojo.forEach(oldOpts, function(i){
+			// We can get null back in our array - if our option was not found.  In
+			// that case, we don't want to blow up...
+			if(i){
+				this.options = dojo.filter(this.options, function(node, idx){
+					return (node.value !== i.value);
+				});
+				this._removeOptionItem(i);
+			}
+		}, this);
+		this._loadChildren();
+	},
+
+	updateOption: function(/* dijit.form.__SelectOption, dijit.form.__SelectOption[] */ newOption){
+		// summary:
+		//		Updates the values of the given option.  The option to update
+		//		is matched based on the value of the entered option.  Passing
+		//		in an array of new options will yeild better performance since
+		//		the children will only be loaded once.
+		if(!dojo.isArray(newOption)){ newOption = [newOption]; }
+		dojo.forEach(newOption, function(i){
+			var oldOpt = this.getOptions(i), k;
+			if(oldOpt){
+				for(k in i){ oldOpt[k] = i[k]; }
+			}
+		}, this);
+		this._loadChildren();
+	},
+
+	setStore: function(/* dojo.data.api.Identity */ store,
+						/* anything? */ selectedValue,
+						/* Object? */ fetchArgs){
+		// summary:
+		//		Sets the store you would like to use with this select widget.
+		//		The selected value is the value of the new store to set.  This
+		//		function returns the original store, in case you want to reuse
+		//		it or something.
+		// store: dojo.data.api.Identity
+		//		The store you would like to use - it MUST implement Identity,
+		//		and MAY implement Notification.
+		// selectedValue: anything?
+		//		The value that this widget should set itself to *after* the store
+		//		has been loaded
+		// fetchArgs: Object?
+		//		The arguments that will be passed to the store's fetch() function
+		var oStore = this.store;
+		fetchArgs = fetchArgs || {};
+		if(oStore !== store){
+			// Our store has changed, so update our notifications
+			dojo.forEach(this._notifyConnections || [], dojo.disconnect);
+			delete this._notifyConnections;
+			if(store && store.getFeatures()["dojo.data.api.Notification"]){
+				this._notifyConnections = [
+					dojo.connect(store, "onNew", this, "_onNewItem"),
+					dojo.connect(store, "onDelete", this, "_onDeleteItem"),
+					dojo.connect(store, "onSet", this, "_onSetItem")
+				];
+			}
+			this.store = store;
+		}
+
+		// Turn off change notifications while we make all these changes
+		this._onChangeActive = false;
+
+		// Remove existing options (if there are any)
+		if(this.options && this.options.length){
+			this.removeOption(this.options);
+		}
+
+		// Add our new options
+		if(store){
+			var cb = function(items){
+				if(this.sortByLabel && !fetchArgs.sort && items.length){
+					items.sort(dojo.data.util.sorter.createSortFunction([{
+						attribute: store.getLabelAttributes(items[0])[0]
+					}], store));
+				}
+
+				if(fetchArgs.onFetch){
+					items = fetchArgs.onFetch(items);
+				}
+				// TODO: Add these guys as a batch, instead of separately
+				dojo.forEach(items, function(i){
+					this._addOptionForItem(i);
+				}, this);
+
+				// Set our value (which might be undefined), and then tweak
+				// it to send a change event with the real value
+				this._loadingStore = false;
+				this.set("value", (("_pendingValue" in this) ? this._pendingValue : selectedValue));
+				delete this._pendingValue;
+
+				if(!this.loadChildrenOnOpen){
+					this._loadChildren();
+				}else{
+					this._pseudoLoadChildren(items);
+				}
+				this._fetchedWith = opts;
+				this._lastValueReported = this.multiple ? [] : null;
+				this._onChangeActive = true;
+				this.onSetStore();
+				this._handleOnChange(this.value);
+			};
+			var opts = dojo.mixin({onComplete:cb, scope: this}, fetchArgs);
+			this._loadingStore = true;
+			store.fetch(opts);
+		}else{
+			delete this._fetchedWith;
+		}
+		return oStore;	// dojo.data.api.Identity
+	},
+
+	_setValueAttr: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){
+		// summary:
+		//		set the value of the widget.
+		//		If a string is passed, then we set our value from looking it up.
+		if(this._loadingStore){
+			// Our store is loading - so save our value, and we'll set it when
+			// we're done
+			this._pendingValue = newValue;
+			return;
+		}
+		var opts = this.getOptions() || [];
+		if(!dojo.isArray(newValue)){
+			newValue = [newValue];
+		}
+		dojo.forEach(newValue, function(i, idx){
+			if(!dojo.isObject(i)){
+				i = i + "";
+			}
+			if(typeof i === "string"){
+				newValue[idx] = dojo.filter(opts, function(node){
+					return node.value === i;
+				})[0] || {value: "", label: ""};
+			}
+		}, this);
+
+		// Make sure some sane default is set
+		newValue = dojo.filter(newValue, function(i){ return i && i.value; });
+		if(!this.multiple && (!newValue[0] || !newValue[0].value) && opts.length){
+			newValue[0] = opts[0];
+		}
+		dojo.forEach(opts, function(i){
+			i.selected = dojo.some(newValue, function(v){ return v.value === i.value; });
+		});
+		var val = dojo.map(newValue, function(i){ return i.value; }),
+			disp = dojo.map(newValue, function(i){ return i.label; });
+
+		this.value = this.multiple ? val : val[0];
+		this._setDisplay(this.multiple ? disp : disp[0]);
+		this._updateSelection();
+		this._handleOnChange(this.value, priorityChange);
+	},
+
+	_getDisplayedValueAttr: function(){
+		// summary:
+		//		returns the displayed value of the widget
+		var val = this.get("value");
+		if(!dojo.isArray(val)){
+			val = [val];
+		}
+		var ret = dojo.map(this.getOptions(val), function(v){
+			if(v && "label" in v){
+				return v.label;
+			}else if(v){
+				return v.value;
+			}
+			return null;
+		}, this);
+		return this.multiple ? ret : ret[0];
+	},
+
+	_getValueDeprecated: false, // remove when _FormWidget:getValue is removed
+	getValue: function(){
+		// summary:
+		//		get the value of the widget.
+		return this._lastValue;
+	},
+
+	undo: function(){
+		// summary:
+		//		restore the value to the last value passed to onChange
+		this._setValueAttr(this._lastValueReported, false);
+	},
+
+	_loadChildren: function(){
+		// summary:
+		//		Loads the children represented by this widget's options.
+		//		reset the menu to make it "populatable on the next click
+		if(this._loadingStore){ return; }
+		dojo.forEach(this._getChildren(), function(child){
+			child.destroyRecursive();
+		});
+		// Add each menu item
+		dojo.forEach(this.options, this._addOptionItem, this);
+
+		// Update states
+		this._updateSelection();
+	},
+
+	_updateSelection: function(){
+		// summary:
+		//		Sets the "selected" class on the item for styling purposes
+		this.value = this._getValueFromOpts();
+		var val = this.value;
+		if(!dojo.isArray(val)){
+			val = [val];
+		}
+		if(val && val[0]){
+			dojo.forEach(this._getChildren(), function(child){
+				var isSelected = dojo.some(val, function(v){
+					return child.option && (v === child.option.value);
+				});
+				dojo.toggleClass(child.domNode, this.baseClass + "SelectedOption", isSelected);
+				dijit.setWaiState(child.domNode, "selected", isSelected);
+			}, this);
+		}
+		this._handleOnChange(this.value);
+	},
+
+	_getValueFromOpts: function(){
+		// summary:
+		//		Returns the value of the widget by reading the options for
+		//		the selected flag
+		var opts = this.getOptions() || [];
+		if(!this.multiple && opts.length){
+			// Mirror what a select does - choose the first one
+			var opt = dojo.filter(opts, function(i){
+				return i.selected;
+			})[0];
+			if(opt && opt.value){
+				return opt.value
+			}else{
+				opts[0].selected = true;
+				return opts[0].value;
+			}
+		}else if(this.multiple){
+			// Set value to be the sum of all selected
+			return dojo.map(dojo.filter(opts, function(i){
+				return i.selected;
+			}), function(i){
+				return i.value;
+			}) || [];
+		}
+		return "";
+	},
+
+	// Internal functions to call when we have store notifications come in
+	_onNewItem: function(/* item */ item, /* Object? */ parentInfo){
+		if(!parentInfo || !parentInfo.parent){
+			// Only add it if we are top-level
+			this._addOptionForItem(item);
+		}
+	},
+	_onDeleteItem: function(/* item */ item){
+		var store = this.store;
+		this.removeOption(store.getIdentity(item));
+	},
+	_onSetItem: function(/* item */ item){
+		this.updateOption(this._getOptionObjForItem(item));
+	},
+
+	_getOptionObjForItem: function(item){
+		// summary:
+		//		Returns an option object based off the given item.  The "value"
+		//		of the option item will be the identity of the item, the "label"
+		//		of the option will be the label of the item.  If the item contains
+		//		children, the children value of the item will be set
+		var store = this.store, label = store.getLabel(item),
+			value = (label ? store.getIdentity(item) : null);
+		return {value: value, label: label, item:item}; // dijit.form.__SelectOption
+	},
+
+	_addOptionForItem: function(/* item */ item){
+		// summary:
+		//		Creates (and adds) the option for the given item
+		var store = this.store;
+		if(!store.isItemLoaded(item)){
+			// We are not loaded - so let's load it and add later
+			store.loadItem({item: item, onComplete: function(i){
+				this._addOptionForItem(item);
+			},
+			scope: this});
+			return;
+		}
+		var newOpt = this._getOptionObjForItem(item);
+		this.addOption(newOpt);
+	},
+
+	constructor: function(/* Object */ keywordArgs){
+		// summary:
+		//		Saves off our value, if we have an initial one set so we
+		//		can use it if we have a store as well (see startup())
+		this._oValue = (keywordArgs || {}).value || null;
+	},
+
+	_fillContent: function(){
+		// summary:
+		//		Loads our options and sets up our dropdown correctly.  We
+		//		don't want any content, so we don't call any inherit chain
+		//		function.
+		var opts = this.options;
+		if(!opts){
+			opts = this.options = this.srcNodeRef ? dojo.query(">",
+						this.srcNodeRef).map(function(node){
+							if(node.getAttribute("type") === "separator"){
+								return { value: "", label: "", selected: false, disabled: false };
+							}
+							return { value: node.getAttribute("value"),
+										label: String(node.innerHTML),
+										selected: node.getAttribute("selected") || false,
+										disabled: node.getAttribute("disabled") || false };
+						}, this) : [];
+		}
+		if(!this.value){
+			this.value = this._getValueFromOpts();
+		}else if(this.multiple && typeof this.value == "string"){
+			this.value = this.value.split(",");
+		}
+	},
+
+	postCreate: function(){
+		// summary:
+		//		sets up our event handling that we need for functioning
+		//		as a select
+		dojo.setSelectable(this.focusNode, false);
+		this.inherited(arguments);
+
+		// Make our event connections for updating state
+		this.connect(this, "onChange", "_updateSelection");
+		this.connect(this, "startup", "_loadChildren");
+
+		this._setValueAttr(this.value, null);
+	},
+
+	startup: function(){
+		// summary:
+		//		Connects in our store, if we have one defined
+		this.inherited(arguments);
+		var store = this.store, fetchArgs = {};
+		dojo.forEach(["query", "queryOptions", "onFetch"], function(i){
+			if(this[i]){
+				fetchArgs[i] = this[i];
+			}
+			delete this[i];
+		}, this);
+		if(store && store.getFeatures()["dojo.data.api.Identity"]){
+			// Temporarily set our store to null so that it will get set
+			// and connected appropriately
+			this.store = null;
+			this.setStore(store, this._oValue, fetchArgs);
+		}
+	},
+
+	destroy: function(){
+		// summary:
+		//		Clean up our connections
+		dojo.forEach(this._notifyConnections || [], dojo.disconnect);
+		this.inherited(arguments);
+	},
+
+	_addOptionItem: function(/* dijit.form.__SelectOption */ option){
+		// summary:
+		//		User-overridable function which, for the given option, adds an
+		//		item to the select.  If the option doesn't have a value, then a
+		//		separator is added in that place.  Make sure to store the option
+		//		in the created option widget.
+	},
+
+	_removeOptionItem: function(/* dijit.form.__SelectOption */ option){
+		// summary:
+		//		User-overridable function which, for the given option, removes
+		//		its item from the select.
+	},
+
+	_setDisplay: function(/*String or String[]*/ newDisplay){
+		// summary:
+		//		Overridable function which will set the display for the
+		//		widget.  newDisplay is either a string (in the case of
+		//		single selects) or array of strings (in the case of multi-selects)
+	},
+
+	_getChildren: function(){
+		// summary:
+		//		Overridable function to return the children that this widget contains.
+		return [];
+	},
+
+	_getSelectedOptionsAttr: function(){
+		// summary:
+		//		hooks into this.attr to provide a mechanism for getting the
+		//		option items for the current value of the widget.
+		return this.getOptions(this.get("value"));
+	},
+
+	_pseudoLoadChildren: function(/* item[] */ items){
+		// summary:
+		//		a function that will "fake" loading children, if needed, and
+		//		if we have set to not load children until the widget opens.
+		// items:
+		//		An array of items that will be loaded, when needed
+	},
+
+	onSetStore: function(){
+		// summary:
+		//		a function that can be connected to in order to receive a
+		//		notification that the store has finished loading and all options
+		//		from that store are available
+	}
 });
-dojo.toggleClass(_18.domNode,this.baseClass+"SelectedOption",_19);
-dijit.setWaiState(_18.domNode,"selected",_19);
-},this);
-}
-this._handleOnChange(this.value);
-},_getValueFromOpts:function(){
-var _1a=this.getOptions()||[];
-if(!this.multiple&&_1a.length){
-var opt=dojo.filter(_1a,function(i){
-return i.selected;
-})[0];
-if(opt&&opt.value){
-return opt.value;
-}else{
-_1a[0].selected=true;
-return _1a[0].value;
-}
-}else{
-if(this.multiple){
-return dojo.map(dojo.filter(_1a,function(i){
-return i.selected;
-}),function(i){
-return i.value;
-})||[];
-}
-}
-return "";
-},_onNewItem:function(_1b,_1c){
-if(!_1c||!_1c.parent){
-this._addOptionForItem(_1b);
-}
-},_onDeleteItem:function(_1d){
-var _1e=this.store;
-this.removeOption(_1e.getIdentity(_1d));
-},_onSetItem:function(_1f){
-this.updateOption(this._getOptionObjForItem(_1f));
-},_getOptionObjForItem:function(_20){
-var _21=this.store,_22=_21.getLabel(_20),_23=(_22?_21.getIdentity(_20):null);
-return {value:_23,label:_22,item:_20};
-},_addOptionForItem:function(_24){
-var _25=this.store;
-if(!_25.isItemLoaded(_24)){
-_25.loadItem({item:_24,onComplete:function(i){
-this._addOptionForItem(_24);
-},scope:this});
-return;
-}
-var _26=this._getOptionObjForItem(_24);
-this.addOption(_26);
-},constructor:function(_27){
-this._oValue=(_27||{}).value||null;
-},_fillContent:function(){
-var _28=this.options;
-if(!_28){
-_28=this.options=this.srcNodeRef?dojo.query(">",this.srcNodeRef).map(function(_29){
-if(_29.getAttribute("type")==="separator"){
-return {value:"",label:"",selected:false,disabled:false};
-}
-return {value:_29.getAttribute("value"),label:String(_29.innerHTML),selected:_29.getAttribute("selected")||false,disabled:_29.getAttribute("disabled")||false};
-},this):[];
-}
-if(!this.value){
-this.value=this._getValueFromOpts();
-}else{
-if(this.multiple&&typeof this.value=="string"){
-this.value=this.value.split(",");
-}
-}
-},postCreate:function(){
-dojo.setSelectable(this.focusNode,false);
-this.inherited(arguments);
-this.connect(this,"onChange","_updateSelection");
-this.connect(this,"startup","_loadChildren");
-this._setValueAttr(this.value,null);
-},startup:function(){
-this.inherited(arguments);
-var _2a=this.store,_2b={};
-dojo.forEach(["query","queryOptions","onFetch"],function(i){
-if(this[i]){
-_2b[i]=this[i];
-}
-delete this[i];
-},this);
-if(_2a&&_2a.getFeatures()["dojo.data.api.Identity"]){
-this.store=null;
-this.setStore(_2a,this._oValue,_2b);
-}
-},destroy:function(){
-dojo.forEach(this._notifyConnections||[],dojo.disconnect);
-this.inherited(arguments);
-},_addOptionItem:function(_2c){
-},_removeOptionItem:function(_2d){
-},_setDisplay:function(_2e){
-},_getChildren:function(){
-return [];
-},_getSelectedOptionsAttr:function(){
-return this.getOptions(this.attr("value"));
-},_pseudoLoadChildren:function(_2f){
-},onSetStore:function(){
-}});
-}
diff --git a/dijit/form/_FormWidget.js b/dijit/form/_FormWidget.js
index 6be034f..d1f3074 100644
--- a/dijit/form/_FormWidget.js
+++ b/dijit/form/_FormWidget.js
@@ -1,229 +1,361 @@
-/*
-	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
-*/
+dojo.provide("dijit.form._FormWidget");
 
+dojo.require("dojo.window");
 
-if(!dojo._hasResource["dijit.form._FormWidget"]){
-dojo._hasResource["dijit.form._FormWidget"]=true;
-dojo.provide("dijit.form._FormWidget");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.declare("dijit.form._FormWidget",[dijit._Widget,dijit._Templated],{baseClass:"",name:"",alt:"",value:"",type:"text",tabIndex:"0",disabled:false,intermediateChanges:false,scrollOnFocus:true,attributeMap:dojo.delegate(dijit._Widget.prototype.attributeMap,{value:"focusNode",id:"focusNode",tabIndex:"focusNode",alt:"focusNode",title:"focusNode"}),postMixInProperties:function(){
-this.nameAttrSetting=this.name?("name='"+this.name+"'"):"";
-this.inherited(arguments);
-},_setDisabledAttr:function(_1){
-this.disabled=_1;
-dojo.attr(this.focusNode,"disabled",_1);
-if(this.valueNode){
-dojo.attr(this.valueNode,"disabled",_1);
-}
-dijit.setWaiState(this.focusNode,"disabled",_1);
-if(_1){
-this._hovering=false;
-this._active=false;
-this.focusNode.setAttribute("tabIndex","-1");
-}else{
-this.focusNode.setAttribute("tabIndex",this.tabIndex);
-}
-this._setStateClass();
-},setDisabled:function(_2){
-dojo.deprecated("setDisabled("+_2+") is deprecated. Use attr('disabled',"+_2+") instead.","","2.0");
-this.attr("disabled",_2);
-},_onFocus:function(e){
-if(this.scrollOnFocus){
-dijit.scrollIntoView(this.domNode);
-}
-this.inherited(arguments);
-},_onMouse:function(_3){
-var _4=_3.currentTarget;
-if(_4&&_4.getAttribute){
-this.stateModifier=_4.getAttribute("stateModifier")||"";
-}
-if(!this.disabled){
-switch(_3.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;
-var _5=this.connect(dojo.body(),"onmouseup",function(){
-if(this._mouseDown&&this.isFocusable()){
-this.focus();
-}
-this._active=false;
-this._mouseDown=false;
-this._setStateClass();
-this.disconnect(_5);
-});
-break;
-}
-this._setStateClass();
-}
-},isFocusable:function(){
-return !this.disabled&&!this.readOnly&&this.focusNode&&(dojo.style(this.domNode,"display")!="none");
-},focus:function(){
-dijit.focus(this.focusNode);
-},_setStateClass:function(){
-var _6=this.baseClass.split(" ");
-function _7(_8){
-_6=_6.concat(dojo.map(_6,function(c){
-return c+_8;
-}),"dijit"+_8);
-};
-if(this.checked){
-_7("Checked");
-}
-if(this.state){
-_7(this.state);
-}
-if(this.selected){
-_7("Selected");
-}
-if(this.disabled){
-_7("Disabled");
-}else{
-if(this.readOnly){
-_7("ReadOnly");
-}else{
-if(this._active){
-_7(this.stateModifier+"Active");
-}else{
-if(this._focused){
-_7("Focused");
-}
-if(this._hovering){
-_7(this.stateModifier+"Hover");
-}
-}
-}
-}
-var tn=this.stateNode||this.domNode,_9={};
-dojo.forEach(tn.className.split(" "),function(c){
-_9[c]=true;
-});
-if("_stateClasses" in this){
-dojo.forEach(this._stateClasses,function(c){
-delete _9[c];
+dojo.require("dijit._CssStateMixin");
+
+dojo.declare("dijit.form._FormWidget", [dijit._Widget, dijit._Templated, dijit._CssStateMixin],
+	{
+	// 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.
+
+	// 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,
+
+	// 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",
+		id: "focusNode",
+		tabIndex: "focusNode",
+		alt: "focusNode",
+		title: "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
+		// Regarding escaping, see heading "Attribute values" in
+		// http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
+		this.nameAttrSetting = this.name ? ('name="' + this.name.replace(/'/g, """) + '"') : '';
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+		this.connect(this.domNode, "onmousedown", "_onMouseDown");
+	},
+
+	_setDisabledAttr: function(/*Boolean*/ value){
+		this.disabled = value;
+		dojo.attr(this.focusNode, 'disabled', value);
+		if(this.valueNode){
+			dojo.attr(this.valueNode, 'disabled', value);
+		}
+		dijit.setWaiState(this.focusNode, "disabled", value);
+
+		if(value){
+			// reset these, because after the domNode is disabled, we can no longer receive
+			// mouse related events, see #4200
+			this._hovering = false;
+			this._active = false;
+
+			// clear tab stop(s) on this widget's focusable node(s)  (ComboBox has two focusable nodes)
+			var attachPointNames = "tabIndex" in this.attributeMap ? this.attributeMap.tabIndex : "focusNode";
+			dojo.forEach(dojo.isArray(attachPointNames) ? attachPointNames : [attachPointNames], function(attachPointName){
+				var node = this[attachPointName];
+				// complex code because tabIndex=-1 on a <div> doesn't work on FF
+				if(dojo.isWebKit || dijit.hasDefaultTabStop(node)){	// see #11064 about webkit bug
+					node.setAttribute('tabIndex', "-1");
+				}else{
+					node.removeAttribute('tabIndex');				
+				}
+			}, this);
+		}else{
+			this.focusNode.setAttribute('tabIndex', this.tabIndex);
+		}
+	},
+
+	setDisabled: function(/*Boolean*/ disabled){
+		// summary:
+		//		Deprecated.   Use set('disabled', ...) instead.
+		dojo.deprecated("setDisabled("+disabled+") is deprecated. Use set('disabled',"+disabled+") instead.", "", "2.0");
+		this.set('disabled', disabled);
+	},
+
+	_onFocus: function(e){
+		if(this.scrollOnFocus){
+			dojo.window.scrollIntoView(this.domNode);
+		}
+		this.inherited(arguments);
+	},
+
+	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);
+	},
+
+	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){
+				if(this._onChangeHandle){
+					clearTimeout(this._onChangeHandle);
+				}
+				// setTimout allows hidden value processing to run and
+				// also the onChange handler can safely adjust focus, etc
+				this._onChangeHandle = setTimeout(dojo.hitch(this,
+					function(){
+						this._onChangeHandle = null;
+						this.onChange(newValue);
+					}), 0); // try to collapse multiple onChange's fired faster than can be processed
+			}
+		}
+	},
+
+	create: function(){
+		// Overrides _Widget.create()
+		this.inherited(arguments);
+		this._onChangeActive = true;
+	},
+
+	destroy: function(){
+		if(this._onChangeHandle){ // destroy called before last onChange has fired
+			clearTimeout(this._onChangeHandle);
+			this.onChange(this._lastValueReported);
+		}
+		this.inherited(arguments);
+	},
+
+	setValue: function(/*String*/ value){
+		// summary:
+		//		Deprecated.   Use set('value', ...) instead.
+		dojo.deprecated("dijit.form._FormWidget:setValue("+value+") is deprecated.  Use set('value',"+value+") instead.", "", "2.0");
+		this.set('value', value);
+	},
+
+	getValue: function(){
+		// summary:
+		//		Deprecated.   Use get('value') instead.
+		dojo.deprecated(this.declaredClass+"::getValue() is deprecated. Use get('value') instead.", "", "2.0");
+		return this.get('value');
+	},
+	
+	_onMouseDown: function(e){
+		// If user clicks on the button, even if the mouse is released outside of it,
+		// this button should get focus (to mimics native browser buttons).
+		// This is also needed on chrome because otherwise buttons won't get focus at all,
+		// which leads to bizarre focus restore on Dialog close etc.
+		if(!e.ctrlKey && this.isFocusable()){ // !e.ctrlKey to ignore right-click on mac
+			// Set a global event to handle mouseup, so it fires properly
+			// even if the cursor leaves this.domNode before the mouse up event.
+			var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
+				if (this.isFocusable()) {
+					this.focus();
+				}
+				this.disconnect(mouseUpConnector);
+			});
+		}
+	}
 });
-}
-dojo.forEach(_6,function(c){
-_9[c]=true;
+
+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)
+
+	// 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,
+
+	attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
+		value: "",
+		readOnly: "focusNode"
+	}),
+
+	_setReadOnlyAttr: function(/*Boolean*/ value){
+		this.readOnly = value;
+		dojo.attr(this.focusNode, 'readOnly', value);
+		dijit.setWaiState(this.focusNode, "readonly", value);
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+
+		if(dojo.isIE){ // IE won't stop the event with keypress
+			this.connect(this.focusNode || this.domNode, "onkeydown", this._onKeyDown);
+		}
+		// Update our reset value if it hasn't yet been set (because this.set()
+		// 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(){
+		// 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 || e.metaKey)){
+			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);
+			}
+		}
+	},
+
+	_layoutHackIE7: function(){
+		// summary:
+		//		Work around table sizing bugs on IE7 by forcing redraw
+
+		if(dojo.isIE == 7){ // fix IE7 layout bug when the widget is scrolled out of sight
+			var domNode = this.domNode;
+			var parent = domNode.parentNode;
+			var pingNode = domNode.firstChild || domNode; // target node most unlikely to have a custom filter
+			var origFilter = pingNode.style.filter; // save custom filter, most likely nothing
+			var _this = this;
+			while(parent && parent.clientHeight == 0){ // search for parents that haven't rendered yet
+				(function ping(){
+					var disconnectHandle = _this.connect(parent, "onscroll",
+						function(e){
+							_this.disconnect(disconnectHandle); // only call once
+							pingNode.style.filter = (new Date()).getMilliseconds(); // set to anything that's unique
+							setTimeout(function(){ pingNode.style.filter = origFilter }, 0); // restore custom filter, if any
+						}
+					);
+				})();
+				parent = parent.parentNode;
+			}
+		}
+	}
 });
-var _a=[];
-for(var c in _9){
-_a.push(c);
-}
-tn.className=_a.join(" ");
-this._stateClasses=_6;
-},compare:function(_b,_c){
-if(typeof _b=="number"&&typeof _c=="number"){
-return (isNaN(_b)&&isNaN(_c))?0:_b-_c;
-}else{
-if(_b>_c){
-return 1;
-}else{
-if(_b<_c){
-return -1;
-}else{
-return 0;
-}
-}
-}
-},onChange:function(_d){
-},_onChangeActive:false,_handleOnChange:function(_e,_f){
-this._lastValue=_e;
-if(this._lastValueReported==undefined&&(_f===null||!this._onChangeActive)){
-this._resetValue=this._lastValueReported=_e;
-}
-if((this.intermediateChanges||_f||_f===undefined)&&((typeof _e!=typeof this._lastValueReported)||this.compare(_e,this._lastValueReported)!=0)){
-this._lastValueReported=_e;
-if(this._onChangeActive){
-if(this._onChangeHandle){
-clearTimeout(this._onChangeHandle);
-}
-this._onChangeHandle=setTimeout(dojo.hitch(this,function(){
-this._onChangeHandle=null;
-this.onChange(_e);
-}),0);
-}
-}
-},create:function(){
-this.inherited(arguments);
-this._onChangeActive=true;
-this._setStateClass();
-},destroy:function(){
-if(this._onChangeHandle){
-clearTimeout(this._onChangeHandle);
-this.onChange(this._lastValueReported);
-}
-this.inherited(arguments);
-},setValue:function(_10){
-dojo.deprecated("dijit.form._FormWidget:setValue("+_10+") is deprecated.  Use attr('value',"+_10+") instead.","","2.0");
-this.attr("value",_10);
-},getValue:function(){
-dojo.deprecated(this.declaredClass+"::getValue() is deprecated. Use attr('value') instead.","","2.0");
-return this.attr("value");
-}});
-dojo.declare("dijit.form._FormValueWidget",dijit.form._FormWidget,{readOnly:false,attributeMap:dojo.delegate(dijit.form._FormWidget.prototype.attributeMap,{value:"",readOnly:"focusNode"}),_setReadOnlyAttr:function(_11){
-this.readOnly=_11;
-dojo.attr(this.focusNode,"readOnly",_11);
-dijit.setWaiState(this.focusNode,"readonly",_11);
-this._setStateClass();
-},postCreate:function(){
-if(dojo.isIE){
-this.connect(this.focusNode||this.domNode,"onkeydown",this._onKeyDown);
-}
-if(this._resetValue===undefined){
-this._resetValue=this.value;
-}
-},_setValueAttr:function(_12,_13){
-this.value=_12;
-this._handleOnChange(_12,_13);
-},_getValueAttr:function(){
-return this._lastValue;
-},undo:function(){
-this._setValueAttr(this._lastValueReported,false);
-},reset:function(){
-this._hasBeenBlurred=false;
-this._setValueAttr(this._resetValue,true);
-},_onKeyDown:function(e){
-if(e.keyCode==dojo.keys.ESCAPE&&!(e.ctrlKey||e.altKey||e.metaKey)){
-var te;
-if(dojo.isIE){
-e.preventDefault();
-te=document.createEventObject();
-te.keyCode=dojo.keys.ESCAPE;
-te.shiftKey=e.shiftKey;
-e.srcElement.fireEvent("onkeypress",te);
-}
-}
-},_layoutHackIE7:function(){
-if(dojo.isIE==7){
-var _14=this.domNode;
-var _15=_14.parentNode;
-var _16=_14.firstChild||_14;
-var _17=_16.style.filter;
-while(_15&&_15.clientHeight==0){
-_15._disconnectHandle=this.connect(_15,"onscroll",dojo.hitch(this,function(e){
-this.disconnect(_15._disconnectHandle);
-_15.removeAttribute("_disconnectHandle");
-_16.style.filter=(new Date()).getMilliseconds();
-setTimeout(function(){
-_16.style.filter=_17;
-},0);
-}));
-_15=_15.parentNode;
-}
-}
-}});
-}
diff --git a/dijit/form/_Spinner.js b/dijit/form/_Spinner.js
index f305a13..527d79c 100644
--- a/dijit/form/_Spinner.js
+++ b/dijit/form/_Spinner.js
@@ -1,81 +1,117 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.form._Spinner"]){
-dojo._hasResource["dijit.form._Spinner"]=true;
 dojo.provide("dijit.form._Spinner");
+
 dojo.require("dijit.form.ValidationTextBox");
-dojo.declare("dijit.form._Spinner",dijit.form.RangeBoundTextBox,{defaultTimeout:500,timeoutChangeRate:0.9,smallDelta:1,largeDelta:10,templateString:dojo.cache("dijit.form","templates/Spinner.html","<div class=\"dijit dijitReset dijitInlineTable dijitLeft\"\n\tid=\"widget_${id}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\" waiRole=\"presentation\"\n\t><div class=\"dijitInputLayoutContainer\"\n\t\t><div class=\"dijitReset dijitSpinnerButtonContai [...]
-return _1;
-},_arrowState:function(_3,_4){
-this._active=_4;
-this.stateModifier=_3.getAttribute("stateModifier")||"";
-this._setStateClass();
-},_arrowPressed:function(_5,_6,_7){
-if(this.disabled||this.readOnly){
-return;
-}
-this._arrowState(_5,true);
-this._setValueAttr(this.adjust(this.attr("value"),_6*_7),false);
-dijit.selectInputText(this.textbox,this.textbox.value.length);
-},_arrowReleased:function(_8){
-this._wheelTimer=null;
-if(this.disabled||this.readOnly){
-return;
-}
-this._arrowState(_8,false);
-},_typematicCallback:function(_9,_a,_b){
-var _c=this.smallDelta;
-if(_a==this.textbox){
-var k=dojo.keys;
-var _d=_b.charOrCode;
-_c=(_d==k.PAGE_UP||_d==k.PAGE_DOWN)?this.largeDelta:this.smallDelta;
-_a=(_d==k.UP_ARROW||_d==k.PAGE_UP)?this.upArrowNode:this.downArrowNode;
-}
-if(_9==-1){
-this._arrowReleased(_a);
-}else{
-this._arrowPressed(_a,(_a==this.upArrowNode)?1:-1,_c);
-}
-},_wheelTimer:null,_mouseWheeled:function(_e){
-dojo.stopEvent(_e);
-var _f=_e.detail?(_e.detail*-1):(_e.wheelDelta/120);
-if(_f!==0){
-var _10=this[(_f>0?"upArrowNode":"downArrowNode")];
-this._arrowPressed(_10,_f,this.smallDelta);
-if(!this._wheelTimer){
-clearTimeout(this._wheelTimer);
-}
-this._wheelTimer=setTimeout(dojo.hitch(this,"_arrowReleased",_10),50);
-}
-},postCreate:function(){
-this.inherited(arguments);
-this.connect(this.domNode,!dojo.isMozilla?"onmousewheel":"DOMMouseScroll","_mouseWheeled");
-this._connects.push(dijit.typematic.addListener(this.upArrowNode,this.textbox,{charOrCode:dojo.keys.UP_ARROW,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false},this,"_typematicCallback",this.timeoutChangeRate,this.defaultTimeout));
-this._connects.push(dijit.typematic.addListener(this.downArrowNode,this.textbox,{charOrCode:dojo.keys.DOWN_ARROW,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false},this,"_typematicCallback",this.timeoutChangeRate,this.defaultTimeout));
-this._connects.push(dijit.typematic.addListener(this.upArrowNode,this.textbox,{charOrCode:dojo.keys.PAGE_UP,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false},this,"_typematicCallback",this.timeoutChangeRate,this.defaultTimeout));
-this._connects.push(dijit.typematic.addListener(this.downArrowNode,this.textbox,{charOrCode:dojo.keys.PAGE_DOWN,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false},this,"_typematicCallback",this.timeoutChangeRate,this.defaultTimeout));
-if(dojo.isIE){
-var _11=this;
-(function resize(){
-var sz=_11.upArrowNode.parentNode.offsetHeight;
-if(sz){
-_11.upArrowNode.style.height=sz>>1;
-_11.downArrowNode.style.height=sz-(sz>>1);
-_11.focusNode.parentNode.style.height=sz;
-}
-})();
-this.connect(this.domNode,"onresize",function(){
-setTimeout(function(){
-resize();
-_11._setStateClass();
-},0);
+
+dojo.declare(
+	"dijit.form._Spinner",
+	dijit.form.RangeBoundTextBox,
+	{
+		// summary:
+		//		Mixin for validation widgets with a spinner.
+		// description:
+		//		This class basically (conceptually) extends `dijit.form.ValidationTextBox`.
+		//		It modifies the template to have up/down arrows, and provides related handling code.
+
+		// defaultTimeout: Number
+		//		Number of milliseconds before a held arrow key or up/down button becomes typematic
+		defaultTimeout: 500,
+
+		// minimumTimeout: Number
+		//       minimum number of milliseconds that typematic event fires when held key or button is held
+		minimumTimeout: 10,
+
+		// timeoutChangeRate: Number
+		//		Fraction of time used to change the typematic timer between events.
+		//		1.0 means that each typematic event fires at defaultTimeout intervals.
+		//		< 1.0 means that each typematic event fires at an increasing faster rate.
+		timeoutChangeRate: 0.90,
+
+		// smallDelta: Number
+		//	  Adjust the value by this much when spinning using the arrow keys/buttons
+		smallDelta: 1,
+
+		// largeDelta: Number
+		//	  Adjust the value by this much when spinning using the PgUp/Dn keys
+		largeDelta: 10,
+
+		templateString: dojo.cache("dijit.form", "templates/Spinner.html"),
+
+		baseClass: "dijitTextBox dijitSpinner",
+
+		// Set classes like dijitUpArrowButtonHover or dijitDownArrowButtonActive depending on
+		// mouse action over specified node
+		cssStateNodes: {
+			"upArrowNode": "dijitUpArrowButton",
+			"downArrowNode": "dijitDownArrowButton"
+		},
+
+		adjust: function(/* Object */ val, /*Number*/ delta){
+			// summary:
+			//		Overridable function used to adjust a primitive value(Number/Date/...) by the delta amount specified.
+			// 		The val is adjusted in a way that makes sense to the object type.
+			// tags:
+			//		protected extension
+			return val;
+		},
+
+		_arrowPressed: function(/*Node*/ nodePressed, /*Number*/ direction, /*Number*/ increment){
+			// summary:
+			//		Handler for arrow button or arrow key being pressed
+			if(this.disabled || this.readOnly){ return; }
+			this._setValueAttr(this.adjust(this.get('value'), direction*increment), false);
+			dijit.selectInputText(this.textbox, this.textbox.value.length);
+		},
+
+		_arrowReleased: function(/*Node*/ node){
+			// summary:
+			//		Handler for arrow button or arrow key being released
+			this._wheelTimer = null;
+			if(this.disabled || this.readOnly){ return; }
+		},
+
+		_typematicCallback: function(/*Number*/ count, /*DOMNode*/ node, /*Event*/ evt){
+			var inc=this.smallDelta;
+			if(node == this.textbox){
+				var k=dojo.keys;
+				var key = evt.charOrCode;
+				inc = (key == k.PAGE_UP || key == k.PAGE_DOWN) ? this.largeDelta : this.smallDelta;
+				node = (key == k.UP_ARROW || key == k.PAGE_UP) ? this.upArrowNode : this.downArrowNode;
+			}
+			if(count == -1){ this._arrowReleased(node); }
+			else{ this._arrowPressed(node, (node == this.upArrowNode) ? 1 : -1, inc); }
+		},
+
+		_wheelTimer: null,
+		_mouseWheeled: function(/*Event*/ evt){
+			// summary:
+			//		Mouse wheel listener where supported
+
+			dojo.stopEvent(evt);
+			// FIXME: Safari bubbles
+
+			// be nice to DOH and scroll as much as the event says to
+			var scrollAmount = evt.detail ? (evt.detail * -1) : (evt.wheelDelta / 120);
+			if(scrollAmount !== 0){
+				var node = this[(scrollAmount > 0 ? "upArrowNode" : "downArrowNode" )];
+
+				this._arrowPressed(node, scrollAmount, this.smallDelta);
+
+				if(!this._wheelTimer){
+					clearTimeout(this._wheelTimer);
+				}
+				this._wheelTimer = setTimeout(dojo.hitch(this,"_arrowReleased",node), 50);
+			}
+
+		},
+
+		postCreate: function(){
+			this.inherited(arguments);
+
+			// extra listeners
+			this.connect(this.domNode, !dojo.isMozilla ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");
+			this._connects.push(dijit.typematic.addListener(this.upArrowNode, this.textbox, {charOrCode:dojo.keys.UP_ARROW,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout));
+			this._connects.push(dijit.typematic.addListener(this.downArrowNode, this.textbox, {charOrCode:dojo.keys.DOWN_ARROW,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout));
+			this._connects.push(dijit.typematic.addListener(this.upArrowNode, this.textbox, {charOrCode:dojo.keys.PAGE_UP,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout));
+			this._connects.push(dijit.typematic.addListener(this.downArrowNode, this.textbox, {charOrCode:dojo.keys.PAGE_DOWN,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout, this.minimumTimeout));
+		}
 });
-this._layoutHackIE7();
-}
-}});
-}
diff --git a/dijit/form/nls/ComboBox.js b/dijit/form/nls/ComboBox.js
index 49bba39..7843596 100644
--- a/dijit/form/nls/ComboBox.js
+++ b/dijit/form/nls/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Previous choices","nextMessage":"More choices"})
\ No newline at end of file
+({
+		previousMessage: "Previous choices",
+		nextMessage: "More choices"
+})
diff --git a/dijit/form/nls/Textarea.js b/dijit/form/nls/Textarea.js
index 4b0e996..87867f0 100644
--- a/dijit/form/nls/Textarea.js
+++ b/dijit/form/nls/Textarea.js
@@ -1 +1,7 @@
-({"iframeEditTitle":"edit area","iframeFocusTitle":"edit area frame"})
\ No newline at end of file
+/* used by both the editor and textarea widgets to provide information to screen reader users */
+({
+	iframeEditTitle: 'edit area',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'edit area frame'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/ar/ComboBox.js b/dijit/form/nls/ar/ComboBox.js
index 6a84531..4ebc65a 100644
--- a/dijit/form/nls/ar/ComboBox.js
+++ b/dijit/form/nls/ar/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"الاختيارات السابقة","nextMessage":"مزيد من الاختيارات"})
\ No newline at end of file
+({
+		previousMessage: "الاختيارات السابقة",
+		nextMessage: "مزيد من الاختيارات"
+})
diff --git a/dijit/form/nls/ar/Textarea.js b/dijit/form/nls/ar/Textarea.js
index fe623c6..5a679b7 100644
--- a/dijit/form/nls/ar/Textarea.js
+++ b/dijit/form/nls/ar/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"مساحة التحرير","iframeFocusTitle":"اطار مساحة التحرير"})
\ No newline at end of file
+({
+	iframeEditTitle: 'مساحة التحرير',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'اطار مساحة التحرير'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/ar/validate.js b/dijit/form/nls/ar/validate.js
index 615e56b..f146dd2 100644
--- a/dijit/form/nls/ar/validate.js
+++ b/dijit/form/nls/ar/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"هذه القيمة ليس بالمدى الصحيح.","invalidMessage":"القيمة التي تم ادخالها غير صحيحة.","missingMessage":"يجب ادخال هذه القيمة."})
\ No newline at end of file
+({
+	invalidMessage: "القيمة التي تم ادخالها غير صحيحة.",
+	missingMessage: "يجب ادخال هذه القيمة.",
+	rangeMessage: "هذه القيمة ليس بالمدى الصحيح."
+})
diff --git a/dijit/form/nls/ca/ComboBox.js b/dijit/form/nls/ca/ComboBox.js
index 1a37868..02456e5 100644
--- a/dijit/form/nls/ca/ComboBox.js
+++ b/dijit/form/nls/ca/ComboBox.js
@@ -1 +1,5 @@
-({"previousMessage":"Opcions anteriors","nextMessage":"Més opcions"})
\ No newline at end of file
+({
+		previousMessage: "Opcions anteriors",
+		nextMessage: "Més opcions"
+})
+
diff --git a/dijit/form/nls/ca/Textarea.js b/dijit/form/nls/ca/Textarea.js
index 357f923..b8a7429 100644
--- a/dijit/form/nls/ca/Textarea.js
+++ b/dijit/form/nls/ca/Textarea.js
@@ -1 +1,8 @@
-({"iframeEditTitle":"àrea d'edició","iframeFocusTitle":"Marc de l'àrea d'edició"})
\ No newline at end of file
+/* used by both the editor and textarea widgets to provide information to screen reader users */
+({
+	iframeEditTitle: 'àrea d\'edició',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'Marc de l\'àrea d\'edició'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
+
diff --git a/dijit/form/nls/ca/validate.js b/dijit/form/nls/ca/validate.js
index a0a592e..fb301c0 100644
--- a/dijit/form/nls/ca/validate.js
+++ b/dijit/form/nls/ca/validate.js
@@ -1 +1,6 @@
-({"rangeMessage":"Aquest valor és fora de l'interval","invalidMessage":"El valor introduït no és vàlid","missingMessage":"Aquest valor és necessari"})
\ No newline at end of file
+({
+	invalidMessage: "El valor introduït no és vàlid",
+	missingMessage: "Aquest valor és necessari",
+	rangeMessage: "Aquest valor és fora de l'interval"
+})
+
diff --git a/dijit/form/nls/cs/ComboBox.js b/dijit/form/nls/cs/ComboBox.js
index 84e0841..9d0eaad 100644
--- a/dijit/form/nls/cs/ComboBox.js
+++ b/dijit/form/nls/cs/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Předchozí volby","nextMessage":"Další volby"})
\ No newline at end of file
+({
+		previousMessage: "Předchozí volby",
+		nextMessage: "Další volby"
+})
diff --git a/dijit/form/nls/cs/Textarea.js b/dijit/form/nls/cs/Textarea.js
index 8a75ddc..db754be 100644
--- a/dijit/form/nls/cs/Textarea.js
+++ b/dijit/form/nls/cs/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"oblast úprav","iframeFocusTitle":"rámec oblasti úprav"})
\ No newline at end of file
+({
+	iframeEditTitle: 'oblast úprav',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'rámec oblasti úprav'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/cs/validate.js b/dijit/form/nls/cs/validate.js
index 7bb7b9e..fc95d3a 100644
--- a/dijit/form/nls/cs/validate.js
+++ b/dijit/form/nls/cs/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Tato hodnota je mimo rozsah.","invalidMessage":"Zadaná hodnota není platná.","missingMessage":"Tato hodnota je vyžadována."})
\ No newline at end of file
+({
+	invalidMessage: "Zadaná hodnota není platná.",
+	missingMessage: "Tato hodnota je vyžadována.",
+	rangeMessage: "Tato hodnota je mimo rozsah."
+})
diff --git a/dijit/form/nls/da/ComboBox.js b/dijit/form/nls/da/ComboBox.js
index 4ddc10d..520cfdf 100644
--- a/dijit/form/nls/da/ComboBox.js
+++ b/dijit/form/nls/da/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Forrige valg","nextMessage":"Flere valg"})
\ No newline at end of file
+({
+		previousMessage: "Forrige valg",
+		nextMessage: "Flere valg"
+})
diff --git a/dijit/form/nls/da/Textarea.js b/dijit/form/nls/da/Textarea.js
index 244c210..9237b1c 100644
--- a/dijit/form/nls/da/Textarea.js
+++ b/dijit/form/nls/da/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"redigeringsområde","iframeFocusTitle":"ramme om redigeringsområde"})
\ No newline at end of file
+({
+	iframeEditTitle: 'redigeringsområde',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'ramme om redigeringsområde'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/da/validate.js b/dijit/form/nls/da/validate.js
index 2874dd8..1707a09 100644
--- a/dijit/form/nls/da/validate.js
+++ b/dijit/form/nls/da/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Værdien er uden for intervallet.","invalidMessage":"Den angivne værdi er ugyldig.","missingMessage":"Værdien er påkrævet."})
\ No newline at end of file
+({
+	invalidMessage: "Den angivne værdi er ugyldig.",
+	missingMessage: "Værdien er påkrævet.",
+	rangeMessage: "Værdien er uden for intervallet."
+})
diff --git a/dijit/form/nls/de/ComboBox.js b/dijit/form/nls/de/ComboBox.js
index 6cce34b..ac984af 100644
--- a/dijit/form/nls/de/ComboBox.js
+++ b/dijit/form/nls/de/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Vorherige Auswahl","nextMessage":"Weitere Auswahlmöglichkeiten"})
\ No newline at end of file
+({
+		previousMessage: "Vorherige Auswahl",
+		nextMessage: "Weitere Auswahlmöglichkeiten"
+})
diff --git a/dijit/form/nls/de/Textarea.js b/dijit/form/nls/de/Textarea.js
index 2cf75db..9421712 100644
--- a/dijit/form/nls/de/Textarea.js
+++ b/dijit/form/nls/de/Textarea.js
@@ -1 +1,7 @@
-({"iframeEditTitle":"Editierbereich","iframeFocusTitle":"Rahmen für Editierbereich"})
\ No newline at end of file
+/* used by both the editor and textarea widgets to provide information to screen reader users */
+({
+	iframeEditTitle: 'Editierbereich',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'Rahmen für Editierbereich'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/de/validate.js b/dijit/form/nls/de/validate.js
old mode 100644
new mode 100755
index 597796d..07670e3
--- a/dijit/form/nls/de/validate.js
+++ b/dijit/form/nls/de/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Dieser Wert liegt außerhalb des gültigen Bereichs. ","invalidMessage":"Der eingegebene Wert ist ungültig. ","missingMessage":"Dieser Wert ist erforderlich."})
\ No newline at end of file
+({
+	invalidMessage: "Der eingegebene Wert ist ungültig. ",
+	missingMessage: "Dieser Wert ist erforderlich.",
+	rangeMessage: "Dieser Wert liegt außerhalb des gültigen Bereichs. "
+})
diff --git a/dijit/form/nls/el/ComboBox.js b/dijit/form/nls/el/ComboBox.js
index ec294d1..2d13c2c 100644
--- a/dijit/form/nls/el/ComboBox.js
+++ b/dijit/form/nls/el/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Προηγούμενες επιλογές","nextMessage":"Περισσότερες επιλογές"})
\ No newline at end of file
+({
+		previousMessage: "Προηγούμενες επιλογές",
+		nextMessage: "Περισσότερες επιλογές"
+})
diff --git a/dijit/form/nls/el/Textarea.js b/dijit/form/nls/el/Textarea.js
index 9ce37a9..da96a69 100644
--- a/dijit/form/nls/el/Textarea.js
+++ b/dijit/form/nls/el/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"περιοχή επεξεργασίας","iframeFocusTitle":"πλαίσιο περιοχής επεξεργασίας"})
\ No newline at end of file
+({
+	iframeEditTitle: 'περιοχή επεξεργασίας',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'πλαίσιο περιοχής επεξεργασίας'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/el/validate.js b/dijit/form/nls/el/validate.js
index cc57d55..25eedb6 100644
--- a/dijit/form/nls/el/validate.js
+++ b/dijit/form/nls/el/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Η τιμή αυτή δεν ανήκει στο εύρος έγκυρων τιμών.","invalidMessage":"Η τιμή που καταχωρήσατε δεν είναι έγκυρη.","missingMessage":"Η τιμή αυτή πρέπει απαραίτητα να καθοριστεί."})
\ No newline at end of file
+({
+	invalidMessage: "Η τιμή που καταχωρήσατε δεν είναι έγκυρη.",
+	missingMessage: "Η τιμή αυτή πρέπει απαραίτητα να καθοριστεί.",
+	rangeMessage: "Η τιμή αυτή δεν ανήκει στο εύρος έγκυρων τιμών."
+})
diff --git a/dijit/form/nls/es/ComboBox.js b/dijit/form/nls/es/ComboBox.js
index 5bf69f9..0cc1343 100644
--- a/dijit/form/nls/es/ComboBox.js
+++ b/dijit/form/nls/es/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Opciones anteriores","nextMessage":"Más opciones"})
\ No newline at end of file
+({
+		previousMessage: "Opciones anteriores",
+		nextMessage: "Más opciones"
+})
diff --git a/dijit/form/nls/es/Textarea.js b/dijit/form/nls/es/Textarea.js
index f92a50f..e6dd4fe 100644
--- a/dijit/form/nls/es/Textarea.js
+++ b/dijit/form/nls/es/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"área de edición","iframeFocusTitle":"marco del área de edición"})
\ No newline at end of file
+({
+	iframeEditTitle: 'área de edición',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'marco del área de edición'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/es/validate.js b/dijit/form/nls/es/validate.js
index 65e190e..a07f31c 100644
--- a/dijit/form/nls/es/validate.js
+++ b/dijit/form/nls/es/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Este valor está fuera del intervalo.","invalidMessage":"El valor especificado no es válido.","missingMessage":"Este valor es necesario."})
\ No newline at end of file
+({
+	invalidMessage: "El valor especificado no es válido.",
+	missingMessage: "Este valor es necesario.",
+	rangeMessage: "Este valor está fuera del intervalo."
+})
diff --git a/dijit/form/nls/fi/ComboBox.js b/dijit/form/nls/fi/ComboBox.js
index 6d9b830..88c460b 100644
--- a/dijit/form/nls/fi/ComboBox.js
+++ b/dijit/form/nls/fi/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Edelliset valinnat","nextMessage":"Lisää valintoja"})
\ No newline at end of file
+({
+		previousMessage: "Edelliset valinnat",
+		nextMessage: "Lisää valintoja"
+})
diff --git a/dijit/form/nls/fi/Textarea.js b/dijit/form/nls/fi/Textarea.js
index 5efaee9..28e675b 100644
--- a/dijit/form/nls/fi/Textarea.js
+++ b/dijit/form/nls/fi/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"muokkausalue","iframeFocusTitle":"muokkausalueen kehys"})
\ No newline at end of file
+({
+	iframeEditTitle: 'muokkausalue',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'muokkausalueen kehys'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/fi/validate.js b/dijit/form/nls/fi/validate.js
index 276efcd..b08e2b1 100644
--- a/dijit/form/nls/fi/validate.js
+++ b/dijit/form/nls/fi/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Tämä arvo on sallitun alueen ulkopuolella.","invalidMessage":"Annettu arvo ei kelpaa.","missingMessage":"Tämä arvo on pakollinen."})
\ No newline at end of file
+({
+	invalidMessage: "Annettu arvo ei kelpaa.",
+	missingMessage: "Tämä arvo on pakollinen.",
+	rangeMessage: "Tämä arvo on sallitun alueen ulkopuolella."
+})
diff --git a/dijit/form/nls/fr/ComboBox.js b/dijit/form/nls/fr/ComboBox.js
index 14b3976..ddba994 100644
--- a/dijit/form/nls/fr/ComboBox.js
+++ b/dijit/form/nls/fr/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Choix précédents","nextMessage":"Plus de choix"})
\ No newline at end of file
+({
+		previousMessage: "Choix précédents",
+		nextMessage: "Plus de choix"
+})
diff --git a/dijit/form/nls/fr/Textarea.js b/dijit/form/nls/fr/Textarea.js
index 4abb6c3..8c8390d 100644
--- a/dijit/form/nls/fr/Textarea.js
+++ b/dijit/form/nls/fr/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"zone d'édition","iframeFocusTitle":"cadre de la zone d'édition"})
\ No newline at end of file
+({
+	iframeEditTitle: 'zone d\'édition',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'cadre de la zone d\'édition'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/fr/validate.js b/dijit/form/nls/fr/validate.js
index 95a0169..73cbba3 100644
--- a/dijit/form/nls/fr/validate.js
+++ b/dijit/form/nls/fr/validate.js
@@ -1 +1,5 @@
-({"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."})
\ No newline at end of file
+({
+	invalidMessage: "La valeur indiquée n'est pas correcte.",
+	missingMessage: "Cette valeur est requise.",
+	rangeMessage: "Cette valeur n'est pas comprise dans la plage autorisée."
+})
diff --git a/dijit/form/nls/he/ComboBox.js b/dijit/form/nls/he/ComboBox.js
index 169d0f5..a4f9d32 100644
--- a/dijit/form/nls/he/ComboBox.js
+++ b/dijit/form/nls/he/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"האפשרויות הקודמות","nextMessage":"אפשרויות נוספות"})
\ No newline at end of file
+({
+		previousMessage: "האפשרויות הקודמות",
+		nextMessage: "אפשרויות נוספות"
+})
diff --git a/dijit/form/nls/he/Textarea.js b/dijit/form/nls/he/Textarea.js
index 809eadf..3c4b349 100644
--- a/dijit/form/nls/he/Textarea.js
+++ b/dijit/form/nls/he/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"אזור עריכה","iframeFocusTitle":"מסגרת אזור עריכה"})
\ No newline at end of file
+({
+	iframeEditTitle: 'אזור עריכה',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'מסגרת אזור עריכה'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/he/validate.js b/dijit/form/nls/he/validate.js
index 3d778e2..343d904 100644
--- a/dijit/form/nls/he/validate.js
+++ b/dijit/form/nls/he/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"הערך מחוץ לטווח.","invalidMessage":"הערך שצוין אינו חוקי.","missingMessage":"זהו ערך דרוש."})
\ No newline at end of file
+({
+	invalidMessage: "הערך שצוין אינו חוקי.",
+	missingMessage: "זהו ערך דרוש.",
+	rangeMessage: "הערך מחוץ לטווח."
+})
diff --git a/dijit/form/nls/hu/ComboBox.js b/dijit/form/nls/hu/ComboBox.js
index 4b6a620..8109a9e 100644
--- a/dijit/form/nls/hu/ComboBox.js
+++ b/dijit/form/nls/hu/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Előző menüpontok","nextMessage":"További menüpontok"})
\ No newline at end of file
+({
+		previousMessage: "Előző menüpontok",
+		nextMessage: "További menüpontok"
+})
diff --git a/dijit/form/nls/hu/Textarea.js b/dijit/form/nls/hu/Textarea.js
index 9b4ca01..2167170 100644
--- a/dijit/form/nls/hu/Textarea.js
+++ b/dijit/form/nls/hu/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"szerkesztési terület","iframeFocusTitle":"szerkesztési terület keret"})
\ No newline at end of file
+({
+	iframeEditTitle: 'szerkesztési terület',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'szerkesztési terület keret'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/hu/validate.js b/dijit/form/nls/hu/validate.js
index b6d7996..4addd49 100644
--- a/dijit/form/nls/hu/validate.js
+++ b/dijit/form/nls/hu/validate.js
@@ -1 +1,5 @@
-({"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."})
\ No newline at end of file
+({
+	invalidMessage: "A megadott érték érvénytelen.",
+	missingMessage: "Meg kell adni egy értéket.",
+	rangeMessage: "Az érték kívül van a megengedett tartományon."
+})
diff --git a/dijit/form/nls/it/ComboBox.js b/dijit/form/nls/it/ComboBox.js
index 9f67072..6a27e72 100644
--- a/dijit/form/nls/it/ComboBox.js
+++ b/dijit/form/nls/it/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Scelte precedenti","nextMessage":"Altre scelte"})
\ No newline at end of file
+({
+		previousMessage: "Scelte precedenti",
+		nextMessage: "Altre scelte"
+})
diff --git a/dijit/form/nls/it/Textarea.js b/dijit/form/nls/it/Textarea.js
index 1b14ecc..2f9bd4a 100644
--- a/dijit/form/nls/it/Textarea.js
+++ b/dijit/form/nls/it/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"modifica area","iframeFocusTitle":"modifica frame area"})
\ No newline at end of file
+({
+	iframeEditTitle: 'modifica area',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'modifica frame area'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/it/validate.js b/dijit/form/nls/it/validate.js
index af7227f..8931cf0 100644
--- a/dijit/form/nls/it/validate.js
+++ b/dijit/form/nls/it/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Questo valore non è compreso nell'intervallo.","invalidMessage":"Il valore immesso non è valido.","missingMessage":"Questo valore è obbligatorio."})
\ No newline at end of file
+({
+	invalidMessage: "Il valore immesso non è valido.",
+	missingMessage: "Questo valore è obbligatorio.",
+	rangeMessage: "Questo valore non è compreso nell'intervallo."
+})
diff --git a/dijit/form/nls/ja/ComboBox.js b/dijit/form/nls/ja/ComboBox.js
index 6b34170..f362cd2 100644
--- a/dijit/form/nls/ja/ComboBox.js
+++ b/dijit/form/nls/ja/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"以前の選択項目","nextMessage":"追加の選択項目"})
\ No newline at end of file
+({
+		previousMessage: "以前の選択項目",
+		nextMessage: "追加の選択項目"
+})
diff --git a/dijit/form/nls/ja/Textarea.js b/dijit/form/nls/ja/Textarea.js
index 8a52f4a..b27aa7d 100644
--- a/dijit/form/nls/ja/Textarea.js
+++ b/dijit/form/nls/ja/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"編集域","iframeFocusTitle":"編集域フレーム"})
\ No newline at end of file
+({
+	iframeEditTitle: '編集域',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: '編集域フレーム'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/ja/validate.js b/dijit/form/nls/ja/validate.js
index 450cd7e..28bd9b0 100644
--- a/dijit/form/nls/ja/validate.js
+++ b/dijit/form/nls/ja/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"この値は範囲外です。","invalidMessage":"入力した値は無効です。","missingMessage":"この値は必須です。"})
\ No newline at end of file
+({
+	invalidMessage: "入力した値は無効です。",
+	missingMessage: "この値は必須です。",
+	rangeMessage: "この値は範囲外です。"
+})
diff --git a/dijit/form/nls/ko/ComboBox.js b/dijit/form/nls/ko/ComboBox.js
index 87d0f06..7d8b668 100644
--- a/dijit/form/nls/ko/ComboBox.js
+++ b/dijit/form/nls/ko/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"이전 선택사항","nextMessage":"기타 선택사항"})
\ No newline at end of file
+({
+		previousMessage: "이전 선택사항",
+		nextMessage: "기타 선택사항"
+})
diff --git a/dijit/form/nls/ko/Textarea.js b/dijit/form/nls/ko/Textarea.js
index 5c4e916..e6b1266 100644
--- a/dijit/form/nls/ko/Textarea.js
+++ b/dijit/form/nls/ko/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"편집 영역","iframeFocusTitle":"편집 영역 프레임"})
\ No newline at end of file
+({
+	iframeEditTitle: '편집 영역',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: '편집 영역 프레임'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/ko/validate.js b/dijit/form/nls/ko/validate.js
index c76c676..d23627d 100644
--- a/dijit/form/nls/ko/validate.js
+++ b/dijit/form/nls/ko/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"이 값은 범위를 벗어납니다.","invalidMessage":"입력된 값이 올바르지 않습니다.","missingMessage":"이 값은 필수입니다."})
\ No newline at end of file
+({
+	invalidMessage: "입력된 값이 올바르지 않습니다.",
+	missingMessage: "이 값은 필수입니다.",
+	rangeMessage: "이 값은 범위를 벗어납니다."
+})
diff --git a/dijit/form/nls/nb/ComboBox.js b/dijit/form/nls/nb/ComboBox.js
index de14554..3c65d2e 100644
--- a/dijit/form/nls/nb/ComboBox.js
+++ b/dijit/form/nls/nb/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Tidligere valg","nextMessage":"Flere valg"})
\ No newline at end of file
+({
+		previousMessage: "Tidligere valg",
+		nextMessage: "Flere valg"
+})
diff --git a/dijit/form/nls/nb/Textarea.js b/dijit/form/nls/nb/Textarea.js
index 16fadf5..894c98e 100644
--- a/dijit/form/nls/nb/Textarea.js
+++ b/dijit/form/nls/nb/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"redigeringsområde","iframeFocusTitle":"ramme for redigeringsområde"})
\ No newline at end of file
+({
+	iframeEditTitle: 'redigeringsområde',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'ramme for redigeringsområde'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/nb/validate.js b/dijit/form/nls/nb/validate.js
index 2fe96f2..6257674 100644
--- a/dijit/form/nls/nb/validate.js
+++ b/dijit/form/nls/nb/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Denne verdien er utenfor gyldig område.","invalidMessage":"Den angitte verdien er ikke gyldig.","missingMessage":"Denne verdien er obligatorisk."})
\ No newline at end of file
+({
+	invalidMessage: "Den angitte verdien er ikke gyldig.",
+	missingMessage: "Denne verdien er obligatorisk.",
+	rangeMessage: "Denne verdien er utenfor gyldig område."
+})
diff --git a/dijit/form/nls/nl/ComboBox.js b/dijit/form/nls/nl/ComboBox.js
index b5885d7..3c9369f 100644
--- a/dijit/form/nls/nl/ComboBox.js
+++ b/dijit/form/nls/nl/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Eerdere opties","nextMessage":"Meer opties"})
\ No newline at end of file
+({
+		previousMessage: "Eerdere opties",
+		nextMessage: "Meer opties"
+})
diff --git a/dijit/form/nls/nl/Textarea.js b/dijit/form/nls/nl/Textarea.js
index d13c3a6..1f98573 100644
--- a/dijit/form/nls/nl/Textarea.js
+++ b/dijit/form/nls/nl/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"veld bewerken","iframeFocusTitle":"veldkader bewerken"})
\ No newline at end of file
+({
+	iframeEditTitle: 'veld bewerken',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'veldkader bewerken'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/nl/validate.js b/dijit/form/nls/nl/validate.js
index b3062c1..d83a8b4 100644
--- a/dijit/form/nls/nl/validate.js
+++ b/dijit/form/nls/nl/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Deze waarde is niet toegestaan.","invalidMessage":"De opgegeven waarde is ongeldig.","missingMessage":"Deze waarde is verplicht."})
\ No newline at end of file
+({
+	invalidMessage: "De opgegeven waarde is ongeldig.",
+	missingMessage: "Deze waarde is verplicht.",
+	rangeMessage: "Deze waarde is niet toegestaan."
+})
diff --git a/dijit/form/nls/pl/ComboBox.js b/dijit/form/nls/pl/ComboBox.js
index f2b4b08..2e7bf87 100644
--- a/dijit/form/nls/pl/ComboBox.js
+++ b/dijit/form/nls/pl/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Poprzednie wybory","nextMessage":"Więcej wyborów"})
\ No newline at end of file
+({
+		previousMessage: "Poprzednie wybory",
+		nextMessage: "Więcej wyborów"
+})
diff --git a/dijit/form/nls/pl/Textarea.js b/dijit/form/nls/pl/Textarea.js
index d918f59..129d7d0 100644
--- a/dijit/form/nls/pl/Textarea.js
+++ b/dijit/form/nls/pl/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"Obszar edycji","iframeFocusTitle":"Ramka obszaru edycji"})
\ No newline at end of file
+({
+	iframeEditTitle: 'Obszar edycji',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'Ramka obszaru edycji'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/pl/validate.js b/dijit/form/nls/pl/validate.js
index cf05d2f..46f0bfb 100644
--- a/dijit/form/nls/pl/validate.js
+++ b/dijit/form/nls/pl/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Ta wartość jest spoza zakresu.","invalidMessage":"Wprowadzona wartość jest niepoprawna.","missingMessage":"Ta wartość jest wymagana."})
\ No newline at end of file
+({
+	invalidMessage: "Wprowadzona wartość jest niepoprawna.",
+	missingMessage: "Ta wartość jest wymagana.",
+	rangeMessage: "Ta wartość jest spoza zakresu."
+})
diff --git a/dijit/form/nls/pt-pt/ComboBox.js b/dijit/form/nls/pt-pt/ComboBox.js
index 2540542..f03c359 100644
--- a/dijit/form/nls/pt-pt/ComboBox.js
+++ b/dijit/form/nls/pt-pt/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Opções anteriores","nextMessage":"Mais opções"})
\ No newline at end of file
+({
+		previousMessage: "Opções anteriores",
+		nextMessage: "Mais opções"
+})
diff --git a/dijit/form/nls/pt-pt/Textarea.js b/dijit/form/nls/pt-pt/Textarea.js
index bcd75e7..f40fc3d 100644
--- a/dijit/form/nls/pt-pt/Textarea.js
+++ b/dijit/form/nls/pt-pt/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"área de edição","iframeFocusTitle":"painel da área de edição"})
\ No newline at end of file
+({
+	iframeEditTitle: 'área de edição',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'painel da área de edição'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/pt-pt/validate.js b/dijit/form/nls/pt-pt/validate.js
index 3d92170..8fbb734 100644
--- a/dijit/form/nls/pt-pt/validate.js
+++ b/dijit/form/nls/pt-pt/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Este valor encontra-se fora do intervalo.","invalidMessage":"O valor introduzido não é válido.","missingMessage":"Este valor é requerido."})
\ No newline at end of file
+({
+	invalidMessage: "O valor introduzido não é válido.",
+	missingMessage: "Este valor é requerido.",
+	rangeMessage: "Este valor encontra-se fora do intervalo."
+})
diff --git a/dijit/form/nls/pt/ComboBox.js b/dijit/form/nls/pt/ComboBox.js
index 2540542..f03c359 100644
--- a/dijit/form/nls/pt/ComboBox.js
+++ b/dijit/form/nls/pt/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Opções anteriores","nextMessage":"Mais opções"})
\ No newline at end of file
+({
+		previousMessage: "Opções anteriores",
+		nextMessage: "Mais opções"
+})
diff --git a/dijit/form/nls/pt/Textarea.js b/dijit/form/nls/pt/Textarea.js
index b4a0b0f..1a6077e 100644
--- a/dijit/form/nls/pt/Textarea.js
+++ b/dijit/form/nls/pt/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"editar área","iframeFocusTitle":"editar quadro da área"})
\ No newline at end of file
+({
+	iframeEditTitle: 'editar área',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'editar quadro da área'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/pt/validate.js b/dijit/form/nls/pt/validate.js
index 3b43579..46ffabb 100644
--- a/dijit/form/nls/pt/validate.js
+++ b/dijit/form/nls/pt/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Este valor está fora do intervalo. ","invalidMessage":"O valor inserido não é válido.","missingMessage":"Este valor é necessário."})
\ No newline at end of file
+({
+	invalidMessage: "O valor inserido não é válido.",
+	missingMessage: "Este valor é necessário.",
+	rangeMessage: "Este valor está fora do intervalo. "
+})
diff --git a/dijit/form/nls/ro/ComboBox.js b/dijit/form/nls/ro/ComboBox.js
new file mode 100644
index 0000000..303c832
--- /dev/null
+++ b/dijit/form/nls/ro/ComboBox.js
@@ -0,0 +1,5 @@
+({
+		previousMessage: "Alegeri anterioare",
+		nextMessage: "Mai multe alegeri"
+})
+
diff --git a/dijit/form/nls/ro/Textarea.js b/dijit/form/nls/ro/Textarea.js
new file mode 100644
index 0000000..98a19c6
--- /dev/null
+++ b/dijit/form/nls/ro/Textarea.js
@@ -0,0 +1,8 @@
+/* used by both the editor and textarea widgets to provide information to screen reader users */
+({
+	iframeEditTitle: 'zonă de editare',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'cadru zonă de editare'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
+
diff --git a/dijit/form/nls/ro/validate.js b/dijit/form/nls/ro/validate.js
new file mode 100644
index 0000000..17132f7
--- /dev/null
+++ b/dijit/form/nls/ro/validate.js
@@ -0,0 +1,6 @@
+({
+	invalidMessage: "Valoarea introdusă nu este validă.",
+	missingMessage: "Această valoare este necesară.",
+	rangeMessage: "Această valoare este în afara intervalului. "
+})
+
diff --git a/dijit/form/nls/ru/ComboBox.js b/dijit/form/nls/ru/ComboBox.js
index 193f4ee..8ef55f7 100644
--- a/dijit/form/nls/ru/ComboBox.js
+++ b/dijit/form/nls/ru/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Предыдущие варианты","nextMessage":"Следующие варианты"})
\ No newline at end of file
+({
+		previousMessage: "Предыдущие варианты",
+		nextMessage: "Следующие варианты"
+})
diff --git a/dijit/form/nls/ru/Textarea.js b/dijit/form/nls/ru/Textarea.js
index ad7ad22..56b7fc2 100644
--- a/dijit/form/nls/ru/Textarea.js
+++ b/dijit/form/nls/ru/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"область редактирования","iframeFocusTitle":"фрейм области редактирования"})
\ No newline at end of file
+({
+	iframeEditTitle: 'область редактирования',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'фрейм области редактирования'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/ru/validate.js b/dijit/form/nls/ru/validate.js
index 35fb5ca..93bbaaa 100644
--- a/dijit/form/nls/ru/validate.js
+++ b/dijit/form/nls/ru/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Это значение вне диапазона.","invalidMessage":"Указано недопустимое значение.","missingMessage":"Это обязательное значение."})
\ No newline at end of file
+({
+	invalidMessage: "Указано недопустимое значение.",
+	missingMessage: "Это обязательное значение.",
+	rangeMessage: "Это значение вне диапазона."
+})
diff --git a/dijit/form/nls/sk/ComboBox.js b/dijit/form/nls/sk/ComboBox.js
index a45c7f2..e003b1b 100644
--- a/dijit/form/nls/sk/ComboBox.js
+++ b/dijit/form/nls/sk/ComboBox.js
@@ -1 +1,5 @@
-({"previousMessage":"Predchádzajúce voľby","nextMessage":"Ďalšie voľby"})
\ No newline at end of file
+({
+		previousMessage: "Predchádzajúce voľby",
+		nextMessage: "Ďalšie voľby"
+})
+
diff --git a/dijit/form/nls/sk/Textarea.js b/dijit/form/nls/sk/Textarea.js
index 3ee98c3..8a6c633 100644
--- a/dijit/form/nls/sk/Textarea.js
+++ b/dijit/form/nls/sk/Textarea.js
@@ -1 +1,8 @@
-({"iframeEditTitle":"upraviť oblasť","iframeFocusTitle":"upraviť rám oblasti"})
\ No newline at end of file
+/* used by both the editor and textarea widgets to provide information to screen reader users */
+({
+	iframeEditTitle: 'upraviť oblasť',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'upraviť rám oblasti'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
+
diff --git a/dijit/form/nls/sk/validate.js b/dijit/form/nls/sk/validate.js
index 612dab5..a5e1f4c 100644
--- a/dijit/form/nls/sk/validate.js
+++ b/dijit/form/nls/sk/validate.js
@@ -1 +1,6 @@
-({"rangeMessage":"Táto hodnota je mimo rozsah.","invalidMessage":"Zadaná hodnota nie je platná.","missingMessage":"Táto hodnota je vyžadovaná."})
\ No newline at end of file
+({
+	invalidMessage: "Zadaná hodnota nie je platná.",
+	missingMessage: "Táto hodnota je vyžadovaná.",
+	rangeMessage: "Táto hodnota je mimo rozsah."
+})
+
diff --git a/dijit/form/nls/sl/ComboBox.js b/dijit/form/nls/sl/ComboBox.js
index e955688..5537951 100644
--- a/dijit/form/nls/sl/ComboBox.js
+++ b/dijit/form/nls/sl/ComboBox.js
@@ -1 +1,5 @@
-({"previousMessage":"Prejšnje možnosti","nextMessage":"Dodatne možnosti"})
\ No newline at end of file
+({
+		previousMessage: "Prejšnje možnosti",
+		nextMessage: "Dodatne možnosti"
+})
+
diff --git a/dijit/form/nls/sl/Textarea.js b/dijit/form/nls/sl/Textarea.js
index 912ee39..26ffbda 100644
--- a/dijit/form/nls/sl/Textarea.js
+++ b/dijit/form/nls/sl/Textarea.js
@@ -1 +1,8 @@
-({"iframeEditTitle":"urejanje področja","iframeFocusTitle":"urejanje področja okvirja"})
\ No newline at end of file
+/* used by both the editor and textarea widgets to provide information to screen reader users */
+({
+	iframeEditTitle: 'urejanje področja',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'urejanje področja okvirja'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
+
diff --git a/dijit/form/nls/sl/validate.js b/dijit/form/nls/sl/validate.js
index 7635724..eda6ec8 100644
--- a/dijit/form/nls/sl/validate.js
+++ b/dijit/form/nls/sl/validate.js
@@ -1 +1,6 @@
-({"rangeMessage":"Ta vrednost je zunaj obsega. ","invalidMessage":"Vnesena vrednost ni veljavna.","missingMessage":"Ta vrednost je zahtevana."})
\ No newline at end of file
+({
+	invalidMessage: "Vnesena vrednost ni veljavna.",
+	missingMessage: "Ta vrednost je zahtevana.",
+	rangeMessage: "Ta vrednost je zunaj obsega. "
+})
+
diff --git a/dijit/form/nls/sv/ComboBox.js b/dijit/form/nls/sv/ComboBox.js
index 860bf75..cc822ce 100644
--- a/dijit/form/nls/sv/ComboBox.js
+++ b/dijit/form/nls/sv/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Föregående alternativ","nextMessage":"Fler alternativ"})
\ No newline at end of file
+({
+		previousMessage: "Föregående alternativ",
+		nextMessage: "Fler alternativ"
+})
diff --git a/dijit/form/nls/sv/Textarea.js b/dijit/form/nls/sv/Textarea.js
index 9e508ac..52263a0 100644
--- a/dijit/form/nls/sv/Textarea.js
+++ b/dijit/form/nls/sv/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"redigeringsområde","iframeFocusTitle":"redigeringsområdesram"})
\ No newline at end of file
+({
+	iframeEditTitle: 'redigeringsområde',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'redigeringsområdesram'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/sv/validate.js b/dijit/form/nls/sv/validate.js
index 8c1b537..2e0346f 100644
--- a/dijit/form/nls/sv/validate.js
+++ b/dijit/form/nls/sv/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Värdet är utanför intervallet.","invalidMessage":"Det angivna värdet är ogiltigt.","missingMessage":"Värdet är obligatoriskt."})
\ No newline at end of file
+({
+	invalidMessage: "Det angivna värdet är ogiltigt.",
+	missingMessage: "Värdet är obligatoriskt.",
+	rangeMessage: "Värdet är utanför intervallet."
+})
diff --git a/dijit/form/nls/th/ComboBox.js b/dijit/form/nls/th/ComboBox.js
index ff32a4f..bbcae92 100644
--- a/dijit/form/nls/th/ComboBox.js
+++ b/dijit/form/nls/th/ComboBox.js
@@ -1 +1,5 @@
-({"previousMessage":"การเลือกก่อนหน้า","nextMessage":"การเลือกเพิ่มเติม"})
\ No newline at end of file
+({
+		previousMessage: "การเลือกก่อนหน้า",
+		nextMessage: "การเลือกเพิ่มเติม"
+})
+
diff --git a/dijit/form/nls/th/Textarea.js b/dijit/form/nls/th/Textarea.js
index 4361183..2c51dfc 100644
--- a/dijit/form/nls/th/Textarea.js
+++ b/dijit/form/nls/th/Textarea.js
@@ -1 +1,8 @@
-({"iframeEditTitle":"แก้ไขพื้นที่","iframeFocusTitle":"แก้ไขกรอบพื้นที่"})
\ No newline at end of file
+/* used by both the editor and textarea widgets to provide information to screen reader users */
+({
+	iframeEditTitle: 'แก้ไขพื้นที่',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'แก้ไขกรอบพื้นที่'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
+
diff --git a/dijit/form/nls/th/validate.js b/dijit/form/nls/th/validate.js
index 86606b7..68ce684 100644
--- a/dijit/form/nls/th/validate.js
+++ b/dijit/form/nls/th/validate.js
@@ -1 +1,6 @@
-({"rangeMessage":"ค่านี้เกินช่วง","invalidMessage":"ค่าที่ป้อนไม่ถูกต้อง","missingMessage":"จำเป็นต้องมีค่านี้"})
\ No newline at end of file
+({
+	invalidMessage: "ค่าที่ป้อนไม่ถูกต้อง",
+	missingMessage: "จำเป็นต้องมีค่านี้",
+	rangeMessage: "ค่านี้เกินช่วง"
+})
+
diff --git a/dijit/form/nls/tr/ComboBox.js b/dijit/form/nls/tr/ComboBox.js
index 46f71dc..5a1453e 100644
--- a/dijit/form/nls/tr/ComboBox.js
+++ b/dijit/form/nls/tr/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"Önceki seçenekler","nextMessage":"Diğer seçenekler"})
\ No newline at end of file
+({
+		previousMessage: "Önceki seçenekler",
+		nextMessage: "Diğer seçenekler"
+})
diff --git a/dijit/form/nls/tr/Textarea.js b/dijit/form/nls/tr/Textarea.js
index 3f2b5e7..22982eb 100644
--- a/dijit/form/nls/tr/Textarea.js
+++ b/dijit/form/nls/tr/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"düzenleme alanı","iframeFocusTitle":"düzenleme alanı çerçevesi"})
\ No newline at end of file
+({
+	iframeEditTitle: 'düzenleme alanı',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: 'düzenleme alanı çerçevesi'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/tr/validate.js b/dijit/form/nls/tr/validate.js
index 838dbda..7c1f178 100644
--- a/dijit/form/nls/tr/validate.js
+++ b/dijit/form/nls/tr/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"Bu değer aralık dışında.","invalidMessage":"Girilen değer geçersiz.","missingMessage":"Bu değer gerekli."})
\ No newline at end of file
+({
+	invalidMessage: "Girilen değer geçersiz.",
+	missingMessage: "Bu değer gerekli.",
+	rangeMessage: "Bu değer aralık dışında."
+})
diff --git a/dijit/form/nls/validate.js b/dijit/form/nls/validate.js
index 29a1a47..d63a297 100644
--- a/dijit/form/nls/validate.js
+++ b/dijit/form/nls/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"This value is out of range.","invalidMessage":"The value entered is not valid.","missingMessage":"This value is required."})
\ No newline at end of file
+({
+	invalidMessage: "The value entered is not valid.",
+	missingMessage: "This value is required.",
+	rangeMessage: "This value is out of range."
+})
diff --git a/dijit/form/nls/zh-tw/ComboBox.js b/dijit/form/nls/zh-tw/ComboBox.js
index ead5fa6..35266ae 100644
--- a/dijit/form/nls/zh-tw/ComboBox.js
+++ b/dijit/form/nls/zh-tw/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"前一個選擇項","nextMessage":"其他選擇項"})
\ No newline at end of file
+({
+		previousMessage: "前一個選擇項",
+		nextMessage: "其他選擇項"
+})
diff --git a/dijit/form/nls/zh-tw/Textarea.js b/dijit/form/nls/zh-tw/Textarea.js
index cb7abda..e7b0dec 100644
--- a/dijit/form/nls/zh-tw/Textarea.js
+++ b/dijit/form/nls/zh-tw/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"編輯區","iframeFocusTitle":"編輯區框"})
\ No newline at end of file
+({
+	iframeEditTitle: '編輯區',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: '編輯區框'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/zh-tw/validate.js b/dijit/form/nls/zh-tw/validate.js
index b398a31..7ab6fb3 100644
--- a/dijit/form/nls/zh-tw/validate.js
+++ b/dijit/form/nls/zh-tw/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"此值超出範圍。","invalidMessage":"輸入的值無效。","missingMessage":"必須提供此值。"})
\ No newline at end of file
+({
+	invalidMessage: "輸入的值無效。",
+	missingMessage: "必須提供此值。",
+	rangeMessage: "此值超出範圍。"
+})
diff --git a/dijit/form/nls/zh/ComboBox.js b/dijit/form/nls/zh/ComboBox.js
index 7cc92cf..532cf89 100644
--- a/dijit/form/nls/zh/ComboBox.js
+++ b/dijit/form/nls/zh/ComboBox.js
@@ -1 +1,4 @@
-({"previousMessage":"先前选项","nextMessage":"更多选项"})
\ No newline at end of file
+({
+		previousMessage: "先前选项",
+		nextMessage: "更多选项"
+})
diff --git a/dijit/form/nls/zh/Textarea.js b/dijit/form/nls/zh/Textarea.js
index e1cf172..e6c5be1 100644
--- a/dijit/form/nls/zh/Textarea.js
+++ b/dijit/form/nls/zh/Textarea.js
@@ -1 +1,6 @@
-({"iframeEditTitle":"编辑区","iframeFocusTitle":"编辑区框架"})
\ No newline at end of file
+({
+	iframeEditTitle: '编辑区',  // primary title for editable IFRAME, for screen readers when focus is in the editing area
+	iframeFocusTitle: '编辑区框架'  // secondary title for editable IFRAME when focus is on outer container
+									 //  to let user know that focus has moved out of editing area and to the
+									 //  parent element of the editing area
+})
diff --git a/dijit/form/nls/zh/validate.js b/dijit/form/nls/zh/validate.js
index e2c01f5..05b770b 100644
--- a/dijit/form/nls/zh/validate.js
+++ b/dijit/form/nls/zh/validate.js
@@ -1 +1,5 @@
-({"rangeMessage":"此值超出范围。","invalidMessage":"输入的值无效。","missingMessage":"此值是必需值。"})
\ No newline at end of file
+({
+	invalidMessage: "输入的值无效。",
+	missingMessage: "此值是必需值。",
+	rangeMessage: "此值超出范围。"
+})
diff --git a/dijit/form/templates/Button.html b/dijit/form/templates/Button.html
new file mode 100644
index 0000000..e60858c
--- /dev/null
+++ b/dijit/form/templates/Button.html
@@ -0,0 +1,17 @@
+<span class="dijit dijitReset dijitInline"
+	><span class="dijitReset dijitInline dijitButtonNode"
+		dojoAttachEvent="ondijitclick:_onButtonClick"
+		><span class="dijitReset dijitStretch dijitButtonContents"
+			dojoAttachPoint="titleNode,focusNode"
+			waiRole="button" waiState="labelledby-${id}_label"
+			><span class="dijitReset dijitInline dijitIcon" dojoAttachPoint="iconNode"></span
+			><span class="dijitReset dijitToggleButtonIconChar">&#x25CF;</span
+			><span class="dijitReset dijitInline dijitButtonText"
+				id="${id}_label"
+				dojoAttachPoint="containerNode"
+			></span
+		></span
+	></span
+	><input ${!nameAttrSetting} type="${type}" value="${value}" class="dijitOffScreen"
+		dojoAttachPoint="valueNode"
+/></span>
\ No newline at end of file
diff --git a/dijit/form/templates/CheckBox.html b/dijit/form/templates/CheckBox.html
new file mode 100644
index 0000000..908a5d9
--- /dev/null
+++ b/dijit/form/templates/CheckBox.html
@@ -0,0 +1,7 @@
+<div class="dijit dijitReset dijitInline" waiRole="presentation"
+	><input
+	 	${!nameAttrSetting} type="${type}" ${checkedAttrSetting}
+		class="dijitReset dijitCheckBoxInput"
+		dojoAttachPoint="focusNode"
+	 	dojoAttachEvent="onclick:_onClick"
+/></div>
diff --git a/dijit/form/templates/ComboBox.html b/dijit/form/templates/ComboBox.html
new file mode 100644
index 0000000..905e69b
--- /dev/null
+++ b/dijit/form/templates/ComboBox.html
@@ -0,0 +1,18 @@
+<div class="dijit dijitReset dijitInlineTable dijitLeft"
+	id="widget_${id}"
+	dojoAttachPoint="comboNode" waiRole="combobox"
+	><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer'
+		dojoAttachPoint="downArrowNode" waiRole="presentation"
+		dojoAttachEvent="onmousedown:_onArrowMouseDown"
+		><input class="dijitReset dijitInputField dijitArrowButtonInner" value="▼ " type="text" tabIndex="-1" readOnly waiRole="presentation"
+			${_buttonInputDisabled}
+	/></div
+	><div class='dijitReset dijitValidationContainer'
+		><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabIndex="-1" readOnly waiRole="presentation"
+	/></div
+	><div class="dijitReset dijitInputField dijitInputContainer"
+		><input class='dijitReset dijitInputInner' ${!nameAttrSetting} type="text" autocomplete="off"
+			dojoAttachEvent="onkeypress:_onKeyPress,compositionend"
+			dojoAttachPoint="textbox,focusNode" waiRole="textbox" waiState="haspopup-true,autocomplete-list"
+	/></div
+></div>
diff --git a/dijit/form/templates/ComboButton.html b/dijit/form/templates/ComboButton.html
new file mode 100644
index 0000000..1c3949c
--- /dev/null
+++ b/dijit/form/templates/ComboButton.html
@@ -0,0 +1,23 @@
+<table class="dijit dijitReset dijitInline dijitLeft"
+	cellspacing='0' cellpadding='0' waiRole="presentation"
+	><tbody waiRole="presentation"><tr waiRole="presentation"
+		><td class="dijitReset dijitStretch dijitButtonNode" dojoAttachPoint="buttonNode" dojoAttachEvent="ondijitclick:_onButtonClick,onkeypress:_onButtonKeyPress"
+		><div id="${id}_button" class="dijitReset dijitButtonContents"
+			dojoAttachPoint="titleNode"
+			waiRole="button" waiState="labelledby-${id}_label"
+			><div class="dijitReset dijitInline dijitIcon" dojoAttachPoint="iconNode" waiRole="presentation"></div
+			><div class="dijitReset dijitInline dijitButtonText" id="${id}_label" dojoAttachPoint="containerNode" waiRole="presentation"></div
+		></div
+		></td
+		><td id="${id}_arrow" class='dijitReset dijitRight dijitButtonNode dijitArrowButton'
+			dojoAttachPoint="_popupStateNode,focusNode,_buttonNode"
+			dojoAttachEvent="onkeypress:_onArrowKeyPress"
+			title="${optionsTitle}"
+			waiRole="button" waiState="haspopup-true"
+			><div class="dijitReset dijitArrowButtonInner" waiRole="presentation"></div
+			><div class="dijitReset dijitArrowButtonChar" waiRole="presentation">▼</div
+		></td
+		><td style="display:none !important;"
+			><input ${!nameAttrSetting} type="${type}" value="${value}" dojoAttachPoint="valueNode"
+		/></td></tr></tbody
+></table>
diff --git a/dijit/form/templates/DropDownButton.html b/dijit/form/templates/DropDownButton.html
new file mode 100644
index 0000000..d350ff4
--- /dev/null
+++ b/dijit/form/templates/DropDownButton.html
@@ -0,0 +1,20 @@
+<span class="dijit dijitReset dijitInline"
+	><span class='dijitReset dijitInline dijitButtonNode'
+		dojoAttachEvent="ondijitclick:_onButtonClick" dojoAttachPoint="_buttonNode"
+		><span class="dijitReset dijitStretch dijitButtonContents"
+			dojoAttachPoint="focusNode,titleNode,_arrowWrapperNode"
+			waiRole="button" waiState="haspopup-true,labelledby-${id}_label"
+			><span class="dijitReset dijitInline dijitIcon"
+				dojoAttachPoint="iconNode"
+			></span
+			><span class="dijitReset dijitInline dijitButtonText"
+				dojoAttachPoint="containerNode,_popupStateNode"
+				id="${id}_label"
+			></span
+			><span class="dijitReset dijitInline dijitArrowButtonInner"></span
+			><span class="dijitReset dijitInline dijitArrowButtonChar">▼</span
+		></span
+	></span
+	><input ${!nameAttrSetting} type="${type}" value="${value}" class="dijitOffScreen"
+		dojoAttachPoint="valueNode"
+/></span>
diff --git a/dijit/form/templates/HorizontalSlider.html b/dijit/form/templates/HorizontalSlider.html
new file mode 100644
index 0000000..2fff79e
--- /dev/null
+++ b/dijit/form/templates/HorizontalSlider.html
@@ -0,0 +1,37 @@
+<table class="dijit dijitReset dijitSlider dijitSliderH" cellspacing="0" cellpadding="0" border="0" rules="none" dojoAttachEvent="onkeypress:_onKeyPress,onkeyup:_onKeyUp"
+	><tr class="dijitReset"
+		><td class="dijitReset" colspan="2"></td
+		><td dojoAttachPoint="topDecoration" class="dijitReset dijitSliderDecoration dijitSliderDecorationT dijitSliderDecorationH"></td
+		><td class="dijitReset" colspan="2"></td
+	></tr
+	><tr class="dijitReset"
+		><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH"
+			><div class="dijitSliderDecrementIconH" tabIndex="-1" style="display:none" dojoAttachPoint="decrementButton"><span class="dijitSliderButtonInner">-</span></div
+		></td
+		><td class="dijitReset"
+			><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderLeftBumper" dojoAttachEvent="onmousedown:_onClkDecBumper"></div
+		></td
+		><td class="dijitReset"
+			><input dojoAttachPoint="valueNode" type="hidden" ${!nameAttrSetting}
+			/><div class="dijitReset dijitSliderBarContainerH" waiRole="presentation" dojoAttachPoint="sliderBarContainer"
+				><div waiRole="presentation" dojoAttachPoint="progressBar" class="dijitSliderBar dijitSliderBarH dijitSliderProgressBar dijitSliderProgressBarH" dojoAttachEvent="onmousedown:_onBarClick"
+					><div class="dijitSliderMoveable dijitSliderMoveableH"
+						><div dojoAttachPoint="sliderHandle,focusNode" class="dijitSliderImageHandle dijitSliderImageHandleH" dojoAttachEvent="onmousedown:_onHandleClick" waiRole="slider" valuemin="${minimum}" valuemax="${maximum}"></div
+					></div
+				></div
+				><div waiRole="presentation" dojoAttachPoint="remainingBar" class="dijitSliderBar dijitSliderBarH dijitSliderRemainingBar dijitSliderRemainingBarH" dojoAttachEvent="onmousedown:_onBarClick"></div
+			></div
+		></td
+		><td class="dijitReset"
+			><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderRightBumper" dojoAttachEvent="onmousedown:_onClkIncBumper"></div
+		></td
+		><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH"
+			><div class="dijitSliderIncrementIconH" tabIndex="-1" style="display:none" dojoAttachPoint="incrementButton"><span class="dijitSliderButtonInner">+</span></div
+		></td
+	></tr
+	><tr class="dijitReset"
+		><td class="dijitReset" colspan="2"></td
+		><td dojoAttachPoint="containerNode,bottomDecoration" class="dijitReset dijitSliderDecoration dijitSliderDecorationB dijitSliderDecorationH"></td
+		><td class="dijitReset" colspan="2"></td
+	></tr
+></table>
diff --git a/dijit/form/templates/Select.html b/dijit/form/templates/Select.html
new file mode 100644
index 0000000..1e59b59
--- /dev/null
+++ b/dijit/form/templates/Select.html
@@ -0,0 +1,14 @@
+<table class="dijit dijitReset dijitInline dijitLeft"
+	dojoAttachPoint="_buttonNode,tableNode,focusNode" cellspacing='0' cellpadding='0'
+	waiRole="combobox" waiState="haspopup-true"
+	><tbody waiRole="presentation"><tr waiRole="presentation"
+		><td class="dijitReset dijitStretch dijitButtonContents dijitButtonNode" waiRole="presentation"
+			><span class="dijitReset dijitInline dijitButtonText"  dojoAttachPoint="containerNode,_popupStateNode"></span
+			><input type="hidden" ${!nameAttrSetting} dojoAttachPoint="valueNode" value="${value}" waiState="hidden-true"
+		/></td><td class="dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton"
+				dojoAttachPoint="titleNode" waiRole="presentation"
+			><div class="dijitReset dijitArrowButtonInner" waiRole="presentation"></div
+			><div class="dijitReset dijitArrowButtonChar" waiRole="presentation">▼</div
+		></td
+	></tr></tbody
+></table>
diff --git a/dijit/form/templates/Spinner.html b/dijit/form/templates/Spinner.html
new file mode 100644
index 0000000..75fe79f
--- /dev/null
+++ b/dijit/form/templates/Spinner.html
@@ -0,0 +1,27 @@
+<div class="dijit dijitReset dijitInlineTable dijitLeft"
+	id="widget_${id}" waiRole="presentation"
+	><div class="dijitReset dijitButtonNode dijitSpinnerButtonContainer"
+		><input class="dijitReset dijitInputField dijitSpinnerButtonInner" type="text" tabIndex="-1" readOnly waiRole="presentation"
+		/><div class="dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitUpArrowButton"
+			dojoAttachPoint="upArrowNode"
+			><div class="dijitArrowButtonInner"
+				><input class="dijitReset dijitInputField" value="▲" type="text" tabIndex="-1" readOnly waiRole="presentation"
+					${_buttonInputDisabled}
+			/></div
+		></div
+		><div class="dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitDownArrowButton"
+			dojoAttachPoint="downArrowNode"
+			><div class="dijitArrowButtonInner"
+				><input class="dijitReset dijitInputField" value="▼" type="text" tabIndex="-1" readOnly waiRole="presentation"
+					${_buttonInputDisabled}
+			/></div
+		></div
+	></div
+	><div class='dijitReset dijitValidationContainer'
+		><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabIndex="-1" readOnly waiRole="presentation"
+	/></div
+	><div class="dijitReset dijitInputField dijitInputContainer"
+		><input class='dijitReset dijitInputInner' dojoAttachPoint="textbox,focusNode" type="${type}" dojoAttachEvent="onkeypress:_onKeyPress"
+			waiRole="spinbutton" autocomplete="off" ${!nameAttrSetting}
+	/></div
+></div>
diff --git a/dijit/form/templates/TextBox.html b/dijit/form/templates/TextBox.html
new file mode 100644
index 0000000..c57d876
--- /dev/null
+++ b/dijit/form/templates/TextBox.html
@@ -0,0 +1,6 @@
+<div class="dijit dijitReset dijitInline dijitLeft" id="widget_${id}" waiRole="presentation"
+	><div class="dijitReset dijitInputField dijitInputContainer"
+		><input class="dijitReset dijitInputInner" dojoAttachPoint='textbox,focusNode' autocomplete="off"
+			${!nameAttrSetting} type='${type}'
+	/></div
+></div>
diff --git a/dijit/form/templates/ValidationTextBox.html b/dijit/form/templates/ValidationTextBox.html
new file mode 100644
index 0000000..64b0683
--- /dev/null
+++ b/dijit/form/templates/ValidationTextBox.html
@@ -0,0 +1,10 @@
+<div class="dijit dijitReset dijitInlineTable dijitLeft"
+	id="widget_${id}" waiRole="presentation"
+	><div class='dijitReset dijitValidationContainer'
+		><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabIndex="-1" readOnly waiRole="presentation"
+	/></div
+	><div class="dijitReset dijitInputField dijitInputContainer"
+		><input class="dijitReset dijitInputInner" dojoAttachPoint='textbox,focusNode' autocomplete="off"
+			${!nameAttrSetting} type='${type}'
+	/></div
+></div>
diff --git a/dijit/form/templates/VerticalSlider.html b/dijit/form/templates/VerticalSlider.html
new file mode 100644
index 0000000..751912c
--- /dev/null
+++ b/dijit/form/templates/VerticalSlider.html
@@ -0,0 +1,45 @@
+<table class="dijit dijitReset dijitSlider dijitSliderV" cellspacing="0" cellpadding="0" border="0" rules="none" dojoAttachEvent="onkeypress:_onKeyPress,onkeyup:_onKeyUp"
+	><tr class="dijitReset"
+		><td class="dijitReset"></td
+		><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV"
+			><div class="dijitSliderIncrementIconV" tabIndex="-1" style="display:none" dojoAttachPoint="decrementButton"><span class="dijitSliderButtonInner">+</span></div
+		></td
+		><td class="dijitReset"></td
+	></tr
+	><tr class="dijitReset"
+		><td class="dijitReset"></td
+		><td class="dijitReset"
+			><center><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperV dijitSliderTopBumper" dojoAttachEvent="onmousedown:_onClkIncBumper"></div></center
+		></td
+		><td class="dijitReset"></td
+	></tr
+	><tr class="dijitReset"
+		><td dojoAttachPoint="leftDecoration" class="dijitReset dijitSliderDecoration dijitSliderDecorationL dijitSliderDecorationV"></td
+		><td class="dijitReset" style="height:100%;"
+			><input dojoAttachPoint="valueNode" type="hidden" ${!nameAttrSetting}
+			/><center class="dijitReset dijitSliderBarContainerV" waiRole="presentation" dojoAttachPoint="sliderBarContainer"
+				><div waiRole="presentation" dojoAttachPoint="remainingBar" class="dijitSliderBar dijitSliderBarV dijitSliderRemainingBar dijitSliderRemainingBarV" dojoAttachEvent="onmousedown:_onBarClick"><!--#5629--></div
+				><div waiRole="presentation" dojoAttachPoint="progressBar" class="dijitSliderBar dijitSliderBarV dijitSliderProgressBar dijitSliderProgressBarV" dojoAttachEvent="onmousedown:_onBarClick"
+					><div class="dijitSliderMoveable dijitSliderMoveableV" style="vertical-align:top;"
+						><div dojoAttachPoint="sliderHandle,focusNode" class="dijitSliderImageHandle dijitSliderImageHandleV" dojoAttachEvent="onmousedown:_onHandleClick" waiRole="slider" valuemin="${minimum}" valuemax="${maximum}"></div
+					></div
+				></div
+			></center
+		></td
+		><td dojoAttachPoint="containerNode,rightDecoration" class="dijitReset dijitSliderDecoration dijitSliderDecorationR dijitSliderDecorationV"></td
+	></tr
+	><tr class="dijitReset"
+		><td class="dijitReset"></td
+		><td class="dijitReset"
+			><center><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperV dijitSliderBottomBumper" dojoAttachEvent="onmousedown:_onClkDecBumper"></div></center
+		></td
+		><td class="dijitReset"></td
+	></tr
+	><tr class="dijitReset"
+		><td class="dijitReset"></td
+		><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV"
+			><div class="dijitSliderDecrementIconV" tabIndex="-1" style="display:none" dojoAttachPoint="incrementButton"><span class="dijitSliderButtonInner">-</span></div
+		></td
+		><td class="dijitReset"></td
+	></tr
+></table>
diff --git a/dijit/icons/commonIcons.css b/dijit/icons/commonIcons.css
new file mode 100644
index 0000000..6f27492
--- /dev/null
+++ b/dijit/icons/commonIcons.css
@@ -0,0 +1,164 @@
+/* Dijit widget common icons*/
+
+/*commonIcons.css is located in dijit/icons
+
+commonIconsRtl.css is TBD. This needs to be reviewed to determine in Rtl is reqd. 
+
+The 16 x 16px icons in these sprites are action and object type images which can be used in the following widgets: accordionContainer, menu, tab, titlepane, tree, and all button widgets and error validation contexts. */
+
+.dijitIconSave,
+.dijitIconPrint,
+.dijitIconCut,
+.dijitIconCopy,
+.dijitIconClear,
+.dijitIconDelete,
+.dijitIconUndo,
+.dijitIconEdit,
+.dijitIconNewTask,
+.dijitIconEditTask,
+.dijitIconEditProperty,
+.dijitIconTask,
+.dijitIconFilter,
+.dijitIconConfigure,
+.dijitIconSearch,
+.dijitIconApplication,
+.dijitIconBookmark,
+.dijitIconChart,
+.dijitIconConnector,
+.dijitIconDatabase,
+.dijitIconDocuments,
+.dijitIconMail,
+.dijitLeaf,
+.dijitIconFile,
+.dijitIconFunction,
+.dijitIconKey,
+.dijitIconPackage,
+.dijitIconSample,
+.dijitIconTable,
+.dijitIconUsers,
+.dijitFolderClosed,
+.dijitIconFolderClosed,
+.dijitFolderOpened,
+.dijitIconFolderOpen,
+.dijitIconError {
+	background-image: url('images/commonIconsObjActEnabled.png'); /* Contains both object and action icons in a sprite image for the enabled state.  */
+	width: 16px;
+	height: 16px;
+}
+
+.dj_ie6 .dijitIconSave,
+.dj_ie6 .dijitIconPrint,
+.dj_ie6 .dijitIconCut,
+.dj_ie6 .dijitIconCopy,
+.dj_ie6 .dijitIconClear,
+.dj_ie6 .dijitIconDelete,
+.dj_ie6 .dijitIconUndo,
+.dj_ie6 .dijitIconEdit,
+.dj_ie6 .dijitIconNewTask,
+.dj_ie6 .dijitIconEditTask,
+.dj_ie6 .dijitIconEditProperty,
+.dj_ie6 .dijitIconTask,
+.dj_ie6 .dijitIconFilter,
+.dj_ie6 .dijitIconConfigure,
+.dj_ie6 .dijitIconSearch,
+.dj_ie6 .dijitIconApplication,
+.dj_ie6 .dijitIconBookmark,
+.dj_ie6 .dijitIconChart,
+.dj_ie6 .dijitIconConnector,
+.dj_ie6 .dijitIconDatabase,
+.dj_ie6 .dijitIconDocuments,
+.dj_ie6 .dijitIconMail,
+.dj_ie6 .dijitLeaf,
+.dj_ie6 .dijitIconFile,
+.dj_ie6 .dijitIconFunction,
+.dj_ie6 .dijitIconKey,
+.dj_ie6 .dijitIconPackage,
+.dj_ie6 .dijitIconSample,
+.dj_ie6 .dijitIconTable,
+.dj_ie6 .dijitIconUsers,
+.dj_ie6 .dijitFolderClosed,
+.dj_ie6 .dijitIconFolderClosed,
+.dj_ie6 .dijitFolderOpened,
+.dj_ie6 .dijitIconFolderOpen,
+.dj_ie6 .dijitIconError {
+	background-image: url('images/commonIconsObjActEnabled8bit.png');
+}
+
+.dijitDisabled .dijitIconSave,
+.dijitDisabled .dijitIconPrint,
+.dijitDisabled .dijitIconCut,
+.dijitDisabled .dijitIconCopy,
+.dijitDisabled .dijitIconClear,
+.dijitDisabled .dijitIconDelete,
+.dijitDisabled .dijitIconUndo,
+.dijitDisabled .dijitIconEdit,
+.dijitDisabled .dijitIconNewTask,
+.dijitDisabled .dijitIconEditTask,
+.dijitDisabled .dijitIconEditProperty,
+.dijitDisabled .dijitIconTask,
+.dijitDisabled .dijitIconFilter,
+.dijitDisabled .dijitIconConfigure,
+.dijitDisabled .dijitIconSearch,
+.dijitDisabled .dijitIconApplication,
+.dijitDisabled .dijitIconBookmark,
+.dijitDisabled .dijitIconChart,
+.dijitDisabled .dijitIconConnector,
+.dijitDisabled .dijitIconDatabase,
+.dijitDisabled .dijitIconDocuments,
+.dijitDisabled .dijitIconMail,
+.dijitDisabled .dijitLeaf,
+.dijitDisabled .dijitIconFile,
+.dijitDisabled .dijitIconFunction,
+.dijitDisabled .dijitIconKey,
+.dijitDisabled .dijitIconPackage,
+.dijitDisabled .dijitIconSample,
+.dijitDisabled .dijitIconTable,
+.dijitDisabled .dijitIconUsers,
+.dijitDisabled .dijitFolderClosed,
+.dijitDisabled .dijitIconFolderClosed,
+.dijitDisabled .dijitFolderOpened,
+.dijitDisabled .dijitIconFolderOpen,
+.dijitDisabled .dijitIconError {
+	background-image: url('images/commonIconsObjActDisabled.png'); /* Contains both object and action icons as a sprite image for the disabled state. These would be used by buttons and menus.   */
+}
+
+/*Action icons*/
+.dijitIconSave { background-position: 0px; }
+.dijitIconPrint { background-position: -16px; }
+.dijitIconCut { background-position: -32px; }
+.dijitIconCopy { background-position: -48px; }
+.dijitIconClear { background-position: -64px; }
+.dijitIconDelete { background-position: -80px; }
+.dijitIconUndo { background-position: -96px; }
+.dijitIconEdit { background-position: -112px; }
+.dijitIconNewTask { background-position: -128px; }
+.dijitIconEditTask { background-position: -144px; }
+.dijitIconEditProperty { background-position: -166px; }
+.dijitIconTask { background-position: -176px; }
+.dijitIconFilter { background-position: -192px; }
+.dijitIconConfigure { background-position: -208px; }
+.dijitIconSearch { background-position: -224px; }
+.dijitIconError { background-position: -496px; } 
+/* .dijitIconError is also called .dijitContentPaneError icon in the claro/common.css and is applied to HREF url errors that render in a dialog box with the error messsage */
+
+/*Object icons*/
+.dijitIconApplication { background-position: -240px; }
+.dijitIconBookmark { background-position: -256px; }
+.dijitIconChart { background-position: -272px; }
+.dijitIconConnector { background-position: -288px; }
+.dijitIconDatabase { background-position: -304px; }
+.dijitIconDocuments { background-position: -320px; }
+.dijitIconMail { background-position: -336px; }
+.dijitIconFile, .dijitLeaf { background-position: -352px; }
+.dijitIconFunction { background-position: -368px; }
+.dijitIconKey { background-position: -384px; }
+.dijitIconPackage{ background-position: -400px; }
+.dijitIconSample { background-position: -416px; }
+.dijitIconTable { background-position: -432px; }
+.dijitIconUsers { background-position: -448px; }
+
+
+/*Tree folder icons*/
+.dijitIconFolderClosed, .dijitFolderClosed { background-position: -464px; }
+.dijitIconFolderOpen, .dijitFolderOpened { background-position: -480px; }
+
diff --git a/dijit/icons/commonIcons_rtl.css b/dijit/icons/commonIcons_rtl.css
new file mode 100644
index 0000000..4d4c26f
--- /dev/null
+++ b/dijit/icons/commonIcons_rtl.css
@@ -0,0 +1,127 @@
+/* Dijit widget common icons*/
+
+/*commonIcons_rtl.css is located in dijit/icons
+
+The 16 x 16px icons in these sprites are action and object type images which can be used in the following widgets: accordionContainer, menu, tab, titlepane, tree, and all button widgets and error validation contexts. */
+
+.dijitRtl .dijitIconSave,
+.dijitRtl .dijitIconPrint,
+.dijitRtl .dijitIconCut,
+.dijitRtl .dijitIconCopy,
+.dijitRtl .dijitIconClear,
+.dijitRtl .dijitIconDelete,
+.dijitRtl .dijitIconUndo,
+.dijitRtl .dijitIconEdit,
+.dijitRtl .dijitIconNewTask,
+.dijitRtl .dijitIconEditTask,
+.dijitRtl .dijitIconEditProperty,
+.dijitRtl .dijitIconTask,
+.dijitRtl .dijitIconFilter,
+.dijitRtl .dijitIconConfigure,
+.dijitRtl .dijitIconSearch,
+.dijitRtl .dijitIconApplication,
+.dijitRtl .dijitIconBookmark,
+.dijitRtl .dijitIconChart,
+.dijitRtl .dijitIconConnector,
+.dijitRtl .dijitIconDatabase,
+.dijitRtl .dijitIconDocuments,
+.dijitRtl .dijitIconMail,
+.dijitRtl .dijitLeaf,
+.dijitRtl .dijitIconFile,
+.dijitRtl .dijitIconFunction,
+.dijitRtl .dijitIconKey,
+.dijitRtl .dijitIconPackage,
+.dijitRtl .dijitIconSample,
+.dijitRtl .dijitIconTable,
+.dijitRtl .dijitIconUsers,
+.dijitRtl .dijitFolderClosed,
+.dijitRtl .dijitIconFolderClosed,
+.dijitRtl .dijitFolderOpened,
+.dijitRtl .dijitIconFolderOpen,
+.dijitRtl .dijitIconError, .dijitRtl .dijitContentPaneError { 
+	background-image: url('images/commonIconsObjActEnabled_rtl.png'); /* Contains both object and action icons in a sprite image for the enabled state.  */
+	width: 16px;
+	height: 16px;
+}
+
+.dj_ie6 .dijitRtl .dijitIconSave,
+.dj_ie6 .dijitRtl .dijitIconPrint,
+.dj_ie6 .dijitRtl .dijitIconCut,
+.dj_ie6 .dijitRtl .dijitIconCopy,
+.dj_ie6 .dijitRtl .dijitIconClear,
+.dj_ie6 .dijitRtl .dijitIconDelete,
+.dj_ie6 .dijitRtl .dijitIconUndo,
+.dj_ie6 .dijitRtl .dijitIconEdit,
+.dj_ie6 .dijitRtl .dijitIconNewTask,
+.dj_ie6 .dijitRtl .dijitIconEditTask,
+.dj_ie6 .dijitRtl .dijitIconEditProperty,
+.dj_ie6 .dijitRtl .dijitIconTask,
+.dj_ie6 .dijitRtl .dijitIconFilter,
+.dj_ie6 .dijitRtl .dijitIconConfigure,
+.dj_ie6 .dijitRtl .dijitIconSearch,
+.dj_ie6 .dijitRtl .dijitIconApplication,
+.dj_ie6 .dijitRtl .dijitIconBookmark,
+.dj_ie6 .dijitRtl .dijitIconChart,
+.dj_ie6 .dijitRtl .dijitIconConnector,
+.dj_ie6 .dijitRtl .dijitIconDatabase,
+.dj_ie6 .dijitRtl .dijitIconDocuments,
+.dj_ie6 .dijitRtl .dijitIconMail,
+.dj_ie6 .dijitRtl .dijitLeaf,
+.dj_ie6 .dijitRtl .dijitIconFile,
+.dj_ie6 .dijitRtl .dijitIconFunction,
+.dj_ie6 .dijitRtl .dijitIconKey,
+.dj_ie6 .dijitRtl .dijitIconPackage,
+.dj_ie6 .dijitRtl .dijitIconSample,
+.dj_ie6 .dijitRtl .dijitIconTable,
+.dj_ie6 .dijitRtl .dijitIconUsers,
+.dj_ie6 .dijitRtl .dijitFolderClosed,
+.dj_ie6 .dijitRtl .dijitIconFolderClosed,
+.dj_ie6 .dijitRtl .dijitFolderOpened,
+.dj_ie6 .dijitRtl .dijitIconFolderOpen,
+.dj_ie6 .dijitRtl .dijitIconError, .dj_ie6 .dijitRtl .dijitContentPaneError {
+	background-image: url('images/commonIconsObjActEnabled8bit_rtl.png');
+}
+
+.dijitRtl .dijitDisabled .dijitIconSave,
+.dijitRtl .dijitDisabled .dijitIconPrint,
+.dijitRtl .dijitDisabled .dijitIconCut,
+.dijitRtl .dijitDisabled .dijitIconCopy,
+.dijitRtl .dijitDisabled .dijitIconClear,
+.dijitRtl .dijitDisabled .dijitIconDelete,
+.dijitRtl .dijitDisabled .dijitIconUndo,
+.dijitRtl .dijitDisabled .dijitIconEdit,
+.dijitRtl .dijitDisabled .dijitIconNewTask,
+.dijitRtl .dijitDisabled .dijitIconEditTask,
+.dijitRtl .dijitDisabled .dijitIconEditProperty,
+.dijitRtl .dijitDisabled .dijitIconTask,
+.dijitRtl .dijitDisabled .dijitIconFilter,
+.dijitRtl .dijitDisabled .dijitIconConfigure,
+.dijitRtl .dijitDisabled .dijitIconSearch,
+.dijitRtl .dijitDisabled .dijitIconApplication,
+.dijitRtl .dijitDisabled .dijitIconBookmark,
+.dijitRtl .dijitDisabled .dijitIconChart,
+.dijitRtl .dijitDisabled .dijitIconConnector,
+.dijitRtl .dijitDisabled .dijitIconDatabase,
+.dijitRtl .dijitDisabled .dijitIconDocuments,
+.dijitRtl .dijitDisabled .dijitIconMail,
+.dijitRtl .dijitDisabled .dijitLeaf,
+.dijitRtl .dijitDisabled .dijitIconFile,
+.dijitRtl .dijitDisabled .dijitIconFunction,
+.dijitRtl .dijitDisabled .dijitIconKey,
+.dijitRtl .dijitDisabled .dijitIconPackage,
+.dijitRtl .dijitDisabled .dijitIconSample,
+.dijitRtl .dijitDisabled .dijitIconTable,
+.dijitRtl .dijitDisabled .dijitIconUsers,
+.dijitRtl .dijitDisabled .dijitFolderClosed,
+.dijitRtl .dijitDisabled .dijitIconFolderClosed,
+.dijitRtl .dijitDisabled .dijitFolderOpened,
+.dijitRtl .dijitDisabled .dijitIconFolderOpen,
+.dijitRtl .dijitDisabled .dijitIconError, .dijitRtl .dijitDisabled .dijitContentPaneError {
+	background-image: url('images/commonIconsObjActDisabled_rtl.png'); /* Contains both object and action icons as a sprite image for the disabled state. These would be used by buttons and menus.   */
+}
+
+
+/*For Claro and future themes.*/
+.dijitRtl .dijitContentPaneLoading {
+	background:url('images/loadingAnimation_rtl.gif') no-repeat;
+}
diff --git a/dijit/icons/editorIcons.css b/dijit/icons/editorIcons.css
new file mode 100644
index 0000000..8c667ac
--- /dev/null
+++ b/dijit/icons/editorIcons.css
@@ -0,0 +1,78 @@
+/* Dijit Editor icons*/
+
+/*editorIcons.css  is located in dijit/images 
+
+editorIcons.css contains references to the dijit editor widget icons. There are 46 icons used to map to the related editor funtionality in the editor's toolbar.
+
+*/
+
+
+.dijitEditorIcon {
+	background-image: url('images/editorIconsEnabled.png'); /* editor icons sprite image for the enabled state */
+	background-repeat: no-repeat;
+	width: 18px;
+	height: 18px;
+	text-align: center;
+}
+.dijitDisabled .dijitEditorIcon {
+	background-image: url('images/editorIconsDisabled.png'); /* editor icons sprite image for the disabled state */
+}
+
+
+.dijitEditorIconSep { background-position: 0px; }
+.dijitEditorIconSave { background-position: -18px; }
+.dijitEditorIconPrint { background-position: -36px; }
+.dijitEditorIconCut { background-position: -54px; }
+.dijitEditorIconCopy { background-position: -72px; }
+.dijitEditorIconPaste { background-position: -90px; }
+.dijitEditorIconDelete { background-position: -108px; }
+.dijitEditorIconCancel { background-position: -126px; }
+.dijitEditorIconUndo { background-position: -144px; }
+.dijitEditorIconRedo { background-position: -162px; }
+.dijitEditorIconSelectAll { background-position: -180px; }
+.dijitEditorIconBold { background-position: -198px; }
+.dijitEditorIconItalic { background-position: -216px; }
+.dijitEditorIconUnderline { background-position: -234px; }
+.dijitEditorIconStrikethrough { background-position: -252px; }
+.dijitEditorIconSuperscript { background-position: -270px; }
+.dijitEditorIconSubscript { background-position: -288px; }
+.dijitEditorIconJustifyCenter { background-position: -306px; }
+.dijitEditorIconJustifyFull { background-position: -324px; }
+.dijitEditorIconJustifyLeft { background-position: -342px; }
+.dijitEditorIconJustifyRight { background-position: -360px; }
+.dijitEditorIconIndent { background-position: -378px; }
+.dijitEditorIconOutdent { background-position: -396px; }
+.dijitEditorIconListBulletIndent { background-position: -414px; }
+.dijitEditorIconListBulletOutdent { background-position: -432px; }
+.dijitEditorIconListNumIndent { background-position: -450px; }
+.dijitEditorIconListNumOutdent { background-position: -468px; }
+.dijitEditorIconTabIndent { background-position: -486px; }
+.dijitEditorIconLeftToRight { background-position: -504px; }
+.dijitEditorIconRightToLeft, .dijitEditorIconToggleDir { background-position: -522px; }
+.dijitEditorIconBackColor { background-position: -540px; }
+.dijitEditorIconForeColor { background-position: -558px; }
+.dijitEditorIconHiliteColor { background-position: -576px; }
+.dijitEditorIconNewPage { background-position: -594px; }
+.dijitEditorIconInsertImage { background-position: -612px; }
+.dijitEditorIconInsertTable { background-position: -630px; }
+.dijitEditorIconSpace { background-position: -648px; }
+.dijitEditorIconInsertHorizontalRule { background-position: -666px; }
+.dijitEditorIconInsertOrderedList { background-position: -684px; }
+.dijitEditorIconInsertUnorderedList { background-position: -702px; }
+.dijitEditorIconCreateLink { background-position: -720px; }
+.dijitEditorIconUnlink { background-position: -738px; }
+.dijitEditorIconViewSource { background-position: -756px; }
+.dijitEditorIconRemoveFormat { background-position: -774px; }
+.dijitEditorIconFullScreen { background-position: -792px; }
+.dijitEditorIconWikiword { background-position: -810px; }
+/* .dijitEditorIconToggleDir { background-position: -540px; ;} - 03172010: This icon was not in dijit.editor but is in dojox.editor. */
+
+/* no longer in the editor toolbar:  .dijitEditorIconToggleDir { background-position: -540px;  padding: 0; margin: 0; color:#555555;
+									font-family:verdana,arial,sans-serif; font-weight: 800; font-size: 70%; */
+
+
+
+
+
+
+
diff --git a/dijit/icons/editorIcons_rtl.css b/dijit/icons/editorIcons_rtl.css
new file mode 100644
index 0000000..4d8cb71
--- /dev/null
+++ b/dijit/icons/editorIcons_rtl.css
@@ -0,0 +1,23 @@
+/* Dijit Editor RTL icons*/
+
+/*editorIcons_rtl.css is located in dijit/images 
+
+editorIcons_rtl.css contains references to the dijit editor widget icons. There are 46 icons used to map to the related editor funtionality in the editor's toolbar.
+
+*/
+
+
+/* Editor */
+.dijitEditorRtl .dijitEditorIcon {
+	background-image: url('images/editorIconsEnabled_rtl.png'); /* editor icons sprite image for the enabled right to left state */
+}
+.dijitEditorRtlDisabled .dijitEditorIcon {
+	background-image: url('images/editorIconsDisabled_rtl.png'); /* editor icons sprite image for the disabled right to left state */
+}
+
+/* Toolbar */
+.dijitToolbarRtl .dijitToolbarSeparator {
+	background-image: url('images/editorIconsEnabled_rtl.png');
+}
+
+/* took this information above from editorRtl.css - good or bad? */
\ No newline at end of file
diff --git a/dijit/icons/images/commonIconsObjActDisabled.png b/dijit/icons/images/commonIconsObjActDisabled.png
new file mode 100644
index 0000000..a348e3c
Binary files /dev/null and b/dijit/icons/images/commonIconsObjActDisabled.png differ
diff --git a/dijit/icons/images/commonIconsObjActDisabled_rtl.png b/dijit/icons/images/commonIconsObjActDisabled_rtl.png
new file mode 100644
index 0000000..ea070eb
Binary files /dev/null and b/dijit/icons/images/commonIconsObjActDisabled_rtl.png differ
diff --git a/dijit/icons/images/commonIconsObjActEnabled.png b/dijit/icons/images/commonIconsObjActEnabled.png
new file mode 100644
index 0000000..bd32452
Binary files /dev/null and b/dijit/icons/images/commonIconsObjActEnabled.png differ
diff --git a/dijit/icons/images/commonIconsObjActEnabled8bit.png b/dijit/icons/images/commonIconsObjActEnabled8bit.png
new file mode 100644
index 0000000..d453ea1
Binary files /dev/null and b/dijit/icons/images/commonIconsObjActEnabled8bit.png differ
diff --git a/dijit/icons/images/commonIconsObjActEnabled8bit_rtl.png b/dijit/icons/images/commonIconsObjActEnabled8bit_rtl.png
new file mode 100644
index 0000000..fe5afd2
Binary files /dev/null and b/dijit/icons/images/commonIconsObjActEnabled8bit_rtl.png differ
diff --git a/dijit/icons/images/commonIconsObjActEnabled_rtl.png b/dijit/icons/images/commonIconsObjActEnabled_rtl.png
new file mode 100644
index 0000000..fbe891a
Binary files /dev/null and b/dijit/icons/images/commonIconsObjActEnabled_rtl.png differ
diff --git a/dijit/icons/images/editorIconsDisabled.png b/dijit/icons/images/editorIconsDisabled.png
new file mode 100644
index 0000000..3a68d7a
Binary files /dev/null and b/dijit/icons/images/editorIconsDisabled.png differ
diff --git a/dijit/icons/images/editorIconsDisabled_rtl.png b/dijit/icons/images/editorIconsDisabled_rtl.png
new file mode 100644
index 0000000..9f16646
Binary files /dev/null and b/dijit/icons/images/editorIconsDisabled_rtl.png differ
diff --git a/dijit/icons/images/editorIconsEnabled.png b/dijit/icons/images/editorIconsEnabled.png
new file mode 100644
index 0000000..ca9989a
Binary files /dev/null and b/dijit/icons/images/editorIconsEnabled.png differ
diff --git a/dijit/icons/images/editorIconsEnabled_rtl.png b/dijit/icons/images/editorIconsEnabled_rtl.png
new file mode 100644
index 0000000..064def3
Binary files /dev/null and b/dijit/icons/images/editorIconsEnabled_rtl.png differ
diff --git a/dijit/icons/images/loadingAnimation_rtl.gif b/dijit/icons/images/loadingAnimation_rtl.gif
new file mode 100644
index 0000000..35b472c
Binary files /dev/null and b/dijit/icons/images/loadingAnimation_rtl.gif differ
diff --git a/dijit/layout/AccordionContainer.js b/dijit/layout/AccordionContainer.js
index 01433ad..86f5386 100644
--- a/dijit/layout/AccordionContainer.js
+++ b/dijit/layout/AccordionContainer.js
@@ -1,171 +1,445 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout.AccordionContainer"]){
-dojo._hasResource["dijit.layout.AccordionContainer"]=true;
 dojo.provide("dijit.layout.AccordionContainer");
+
 dojo.require("dojo.fx");
+
 dojo.require("dijit._Container");
 dojo.require("dijit._Templated");
+dojo.require("dijit._CssStateMixin");
 dojo.require("dijit.layout.StackContainer");
 dojo.require("dijit.layout.ContentPane");
-dojo.require("dijit.layout.AccordionPane");
-dojo.declare("dijit.layout.AccordionContainer",dijit.layout.StackContainer,{duration:dijit.defaultDuration,buttonWidget:"dijit.layout._AccordionButton",_verticalSpace:0,baseClass:"dijitAccordionContainer",postCreate:function(){
-this.domNode.style.overflow="hidden";
-this.inherited(arguments);
-dijit.setWaiRole(this.domNode,"tablist");
-},startup:function(){
-if(this._started){
-return;
-}
-this.inherited(arguments);
-if(this.selectedChildWidget){
-var _1=this.selectedChildWidget.containerNode.style;
-_1.display="";
-_1.overflow="auto";
-this.selectedChildWidget._buttonWidget._setSelectedState(true);
-}
-},_getTargetHeight:function(_2){
-var cs=dojo.getComputedStyle(_2);
-return Math.max(this._verticalSpace-dojo._getPadBorderExtents(_2,cs).h,0);
-},layout:function(){
-var _3=this.selectedChildWidget;
-var _4=0;
-dojo.forEach(this.getChildren(),function(_5){
-_4+=_5._buttonWidget.getTitleHeight();
-});
-var _6=this._contentBox;
-this._verticalSpace=_6.h-_4;
-this._containerContentBox={h:this._verticalSpace,w:_6.w};
-if(_3){
-_3.resize(this._containerContentBox);
-}
-},_setupChild:function(_7){
-var _8=dojo.getObject(this.buttonWidget);
-var _9=(_7._buttonWidget=new _8({contentWidget:_7,label:_7.title,title:_7.tooltip,iconClass:_7.iconClass,id:_7.id+"_button",parent:this}));
-_7._accordionConnectHandle=this.connect(_7,"attr",function(_a,_b){
-if(arguments.length==2){
-switch(_a){
-case "title":
-case "iconClass":
-_9.attr(_a,_b);
-}
-}
+
+dojo.require("dijit.layout.AccordionPane");	// for back compat, remove for 2.0
+
+dojo.declare(
+	"dijit.layout.AccordionContainer",
+	dijit.layout.StackContainer,
+	{
+		// summary:
+		//		Holds a set of panes where every pane's title is visible, but only one pane's content is visible at a time,
+		//		and switching between panes is visualized by sliding the other panes up/down.
+		// example:
+		//	| 	<div dojoType="dijit.layout.AccordionContainer">
+		//	|		<div dojoType="dijit.layout.ContentPane" title="pane 1">
+		//	|		</div>
+		//	|		<div dojoType="dijit.layout.ContentPane" title="pane 2">
+		//	|			<p>This is some text</p>
+		//	|		</div>
+		//	|	</div>
+
+		// duration: Integer
+		//		Amount of time (in ms) it takes to slide panes
+		duration: dijit.defaultDuration,
+
+		// buttonWidget: [const] String
+		//		The name of the widget used to display the title of each pane
+		buttonWidget: "dijit.layout._AccordionButton",
+
+		// _verticalSpace: Number
+		//		Pixels of space available for the open pane
+		//		(my content box size minus the cumulative size of all the title bars)
+		_verticalSpace: 0,
+
+		baseClass: "dijitAccordionContainer",
+
+		postCreate: function(){
+			this.domNode.style.overflow = "hidden";
+			this.inherited(arguments);
+			dijit.setWaiRole(this.domNode, "tablist");
+		},
+
+		startup: function(){
+			if(this._started){ return; }
+			this.inherited(arguments);
+			if(this.selectedChildWidget){
+				var style = this.selectedChildWidget.containerNode.style;
+				style.display = "";
+				style.overflow = "auto";
+				this.selectedChildWidget._wrapperWidget.set("selected", true);
+			}
+		},
+
+		_getTargetHeight: function(/* Node */ node){
+			// summary:
+			//		For the given node, returns the height that should be
+			//		set to achieve our vertical space (subtract any padding
+			//		we may have).
+			//
+			//		This is used by the animations.
+			//
+			//		TODO: I don't think this works correctly in IE quirks when an elements
+			//		style.height including padding and borders
+			var cs = dojo.getComputedStyle(node);
+			return Math.max(this._verticalSpace - dojo._getPadBorderExtents(node, cs).h - dojo._getMarginExtents(node, cs).h, 0);
+		},
+
+		layout: function(){
+			// Implement _LayoutWidget.layout() virtual method.
+			// Set the height of the open pane based on what room remains.
+
+			var openPane = this.selectedChildWidget;
+			
+			if(!openPane){ return;}
+
+			var openPaneContainer = openPane._wrapperWidget.domNode,
+				openPaneContainerMargin = dojo._getMarginExtents(openPaneContainer),
+				openPaneContainerPadBorder = dojo._getPadBorderExtents(openPaneContainer),
+				mySize = this._contentBox;
+
+			// get cumulative height of all the unselected title bars
+			var totalCollapsedHeight = 0;
+			dojo.forEach(this.getChildren(), function(child){
+	            if(child != openPane){
+					totalCollapsedHeight += dojo.marginBox(child._wrapperWidget.domNode).h;
+				}
+			});
+			this._verticalSpace = mySize.h - totalCollapsedHeight - openPaneContainerMargin.h 
+			 	- openPaneContainerPadBorder.h - openPane._buttonWidget.getTitleHeight();
+
+			// Memo size to make displayed child
+			this._containerContentBox = {
+				h: this._verticalSpace,
+				w: this._contentBox.w - openPaneContainerMargin.w - openPaneContainerPadBorder.w
+			};
+
+			if(openPane){
+				openPane.resize(this._containerContentBox);
+			}
+		},
+
+		_setupChild: function(child){
+			// Overrides _LayoutWidget._setupChild().
+			// Put wrapper widget around the child widget, showing title
+
+			child._wrapperWidget = new dijit.layout._AccordionInnerContainer({
+				contentWidget: child,
+				buttonWidget: this.buttonWidget,
+				id: child.id + "_wrapper",
+				dir: child.dir,
+				lang: child.lang,
+				parent: this
+			});
+
+			this.inherited(arguments);
+		},
+
+		addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){	
+			if(this._started){
+				// Adding a child to a started Accordion is complicated because children have
+				// wrapper widgets.  Default code path (calling this.inherited()) would add
+				// the new child inside another child's wrapper.
+
+				// First add in child as a direct child of this AccordionContainer
+				dojo.place(child.domNode, this.containerNode, insertIndex);
+
+				if(!child._started){
+					child.startup();
+				}
+				
+				// Then stick the wrapper widget around the child widget
+				this._setupChild(child);
+
+				// Code below copied from StackContainer	
+				dojo.publish(this.id+"-addChild", [child, insertIndex]);
+				this.layout();
+				if(!this.selectedChildWidget){
+					this.selectChild(child);
+				}
+			}else{
+				// We haven't been started yet so just add in the child widget directly,
+				// and the wrapper will be created on startup()
+				this.inherited(arguments);
+			}
+		},
+
+		removeChild: function(child){
+			// Overrides _LayoutWidget.removeChild().
+
+			// destroy wrapper widget first, before StackContainer.getChildren() call
+			child._wrapperWidget.destroy();
+			delete child._wrapperWidget;
+			dojo.removeClass(child.domNode, "dijitHidden");
+
+			this.inherited(arguments);
+		},
+
+		getChildren: function(){
+			// Overrides _Container.getChildren() to return content panes rather than internal AccordionInnerContainer panes
+			return dojo.map(this.inherited(arguments), function(child){
+				return child.declaredClass == "dijit.layout._AccordionInnerContainer" ? child.contentWidget : child;
+			}, this);
+		},
+
+		destroy: function(){
+			dojo.forEach(this.getChildren(), function(child){
+				child._wrapperWidget.destroy();
+			});
+			this.inherited(arguments);
+		},
+
+		_transition: function(/*dijit._Widget?*/newWidget, /*dijit._Widget?*/oldWidget, /*Boolean*/ animate){
+			// Overrides StackContainer._transition() to provide sliding of title bars etc.
+
+//TODO: should be able to replace this with calls to slideIn/slideOut
+			if(this._inTransition){ return; }
+			var animations = [];
+			var paneHeight = this._verticalSpace;
+			if(newWidget){
+				newWidget._wrapperWidget.set("selected", true);
+
+				this._showChild(newWidget);	// prepare widget to be slid in
+
+				// Size the new widget, in case this is the first time it's being shown,
+				// or I have been resized since the last time it was shown.
+				// Note that page must be visible for resizing to work.
+				if(this.doLayout && newWidget.resize){
+					newWidget.resize(this._containerContentBox);
+				}
+
+				var newContents = newWidget.domNode;
+				dojo.addClass(newContents, "dijitVisible");
+				dojo.removeClass(newContents, "dijitHidden");
+				
+				if(animate){
+					var newContentsOverflow = newContents.style.overflow;
+					newContents.style.overflow = "hidden";
+					animations.push(dojo.animateProperty({
+						node: newContents,
+						duration: this.duration,
+						properties: {
+							height: { start: 1, end: this._getTargetHeight(newContents) }
+						},
+						onEnd: function(){
+							newContents.style.overflow = newContentsOverflow;
+
+							// Kick IE to workaround layout bug, see #11415
+							if(dojo.isIE){
+								setTimeout(function(){
+									dojo.removeClass(newContents.parentNode, "dijitAccordionInnerContainerFocused");
+									setTimeout(function(){
+										dojo.addClass(newContents.parentNode, "dijitAccordionInnerContainerFocused");
+									}, 0);
+								}, 0);
+							}
+						}
+					}));
+				}
+			}
+			if(oldWidget){
+				oldWidget._wrapperWidget.set("selected", false);
+				var oldContents = oldWidget.domNode;
+				if(animate){
+					var oldContentsOverflow = oldContents.style.overflow;
+					oldContents.style.overflow = "hidden";
+					animations.push(dojo.animateProperty({
+						node: oldContents,
+						duration: this.duration,
+						properties: {
+							height: { start: this._getTargetHeight(oldContents), end: 1 }
+						},
+						onEnd: function(){
+							dojo.addClass(oldContents, "dijitHidden");
+							dojo.removeClass(oldContents, "dijitVisible");
+							oldContents.style.overflow = oldContentsOverflow;
+							if(oldWidget.onHide){
+								oldWidget.onHide();
+							}
+						}
+					}));
+				}else{
+					dojo.addClass(oldContents, "dijitHidden");
+					dojo.removeClass(oldContents, "dijitVisible");
+					if(oldWidget.onHide){
+						oldWidget.onHide();
+					}
+				}
+			}
+
+			if(animate){
+				this._inTransition = true;
+				var combined = dojo.fx.combine(animations);
+				combined.onEnd = dojo.hitch(this, function(){
+					delete this._inTransition;
+				});
+				combined.play();
+			}			
+		},
+
+		// note: we are treating the container as controller here
+		_onKeyPress: function(/*Event*/ e, /*dijit._Widget*/ fromTitle){
+			// summary:
+			//		Handle keypress events
+			// description:
+			//		This is called from a handler on AccordionContainer.domNode
+			//		(setup in StackContainer), and is also called directly from
+			//		the click handler for accordion labels
+			if(this._inTransition || this.disabled || e.altKey || !(fromTitle || e.ctrlKey)){
+				if(this._inTransition){
+					dojo.stopEvent(e);
+				}
+				return;
+			}
+			var k = dojo.keys,
+				c = e.charOrCode;
+			if((fromTitle && (c == k.LEFT_ARROW || c == k.UP_ARROW)) ||
+					(e.ctrlKey && c == k.PAGE_UP)){
+				this._adjacent(false)._buttonWidget._onTitleClick();
+				dojo.stopEvent(e);
+			}else if((fromTitle && (c == k.RIGHT_ARROW || c == k.DOWN_ARROW)) ||
+					(e.ctrlKey && (c == k.PAGE_DOWN || c == k.TAB))){
+				this._adjacent(true)._buttonWidget._onTitleClick();
+				dojo.stopEvent(e);
+			}
+		}
+	}
+);
+
+dojo.declare("dijit.layout._AccordionInnerContainer",
+	[dijit._Widget, dijit._CssStateMixin], {
+		// summary:
+		//		Internal widget placed as direct child of AccordionContainer.containerNode.
+		//		When other widgets are added as children to an AccordionContainer they are wrapped in
+		//		this widget.
+		
+		// buttonWidget: String
+		//		Name of class to use to instantiate title
+		//		(Wish we didn't have a separate widget for just the title but maintaining it
+		//		for backwards compatibility, is it worth it?)
+/*=====
+		 buttonWidget: null,
+=====*/
+		// contentWidget: dijit._Widget
+		//		Pointer to the real child widget
+/*=====
+	 	contentWidget: null,
+=====*/
+
+		baseClass: "dijitAccordionInnerContainer",
+
+		// tell nested layout widget that we will take care of sizing
+		isContainer: true,
+		isLayoutContainer: true,
+
+		buildRendering: function(){			
+			// Create wrapper div, placed where the child is now
+			this.domNode = dojo.place("<div class='" + this.baseClass + "'>", this.contentWidget.domNode, "after");
+			
+			// wrapper div's first child is the button widget (ie, the title bar)
+			var child = this.contentWidget,
+				cls = dojo.getObject(this.buttonWidget);
+			this.button = child._buttonWidget = (new cls({
+				contentWidget: child,
+				label: child.title,
+				title: child.tooltip,
+				dir: child.dir,
+				lang: child.lang,
+				iconClass: child.iconClass,
+				id: child.id + "_button",
+				parent: this.parent
+			})).placeAt(this.domNode);
+			
+			// and then the actual content widget (changing it from prior-sibling to last-child)
+			dojo.place(this.contentWidget.domNode, this.domNode);
+		},
+
+		postCreate: function(){
+			this.inherited(arguments);
+			this.connect(this.contentWidget, 'set', function(name, value){
+				var mappedName = {title: "label", tooltip: "title", iconClass: "iconClass"}[name];
+				if(mappedName){
+					this.button.set(mappedName, value);
+				}
+			}, this);
+		},
+
+		_setSelectedAttr: function(/*Boolean*/ isSelected){
+			this.selected = isSelected;
+			this.button.set("selected", isSelected);
+			if(isSelected){
+				var cw = this.contentWidget;
+				if(cw.onSelected){ cw.onSelected(); }
+			}
+		},
+
+		startup: function(){
+			// Called by _Container.addChild()
+			this.contentWidget.startup();
+		},
+
+		destroy: function(){
+			this.button.destroyRecursive();
+			
+			delete this.contentWidget._buttonWidget;
+			delete this.contentWidget._wrapperWidget;
+
+			this.inherited(arguments);
+		},
+		
+		destroyDescendants: function(){
+			// since getChildren isn't working for me, have to code this manually
+			this.contentWidget.destroyRecursive();
+		}
 });
-dojo.place(_7._buttonWidget.domNode,_7.domNode,"before");
-this.inherited(arguments);
-},removeChild:function(_c){
-this.disconnect(_c._accordionConnectHandle);
-delete _c._accordionConnectHandle;
-_c._buttonWidget.destroy();
-delete _c._buttonWidget;
-this.inherited(arguments);
-},getChildren:function(){
-return dojo.filter(this.inherited(arguments),function(_d){
-return _d.declaredClass!=this.buttonWidget;
-},this);
-},destroy:function(){
-dojo.forEach(this.getChildren(),function(_e){
-_e._buttonWidget.destroy();
+
+dojo.declare("dijit.layout._AccordionButton",
+	[dijit._Widget, dijit._Templated, dijit._CssStateMixin],
+	{
+	// summary:
+	//		The title bar to click to open up an accordion pane.
+	//		Internal widget used by AccordionContainer.
+	// tags:
+	//		private
+
+	templateString: dojo.cache("dijit.layout", "templates/AccordionButton.html"),
+	attributeMap: dojo.mixin(dojo.clone(dijit.layout.ContentPane.prototype.attributeMap), {
+		label: {node: "titleTextNode", type: "innerHTML" },
+		title: {node: "titleTextNode", type: "attribute", attribute: "title"},
+		iconClass: { node: "iconNode", type: "class" }
+	}),
+
+	baseClass: "dijitAccordionTitle",
+
+	getParent: function(){
+		// summary:
+		//		Returns the AccordionContainer parent.
+		// tags:
+		//		private
+		return this.parent;
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+		dojo.setSelectable(this.domNode, false);
+		var titleTextNodeId = dojo.attr(this.domNode,'id').replace(' ','_');
+		dojo.attr(this.titleTextNode, "id", titleTextNodeId+"_title");
+		dijit.setWaiState(this.focusNode, "labelledby", dojo.attr(this.titleTextNode, "id"));
+	},
+
+	getTitleHeight: function(){
+		// summary:
+		//		Returns the height of the title dom node.
+		return dojo.marginBox(this.domNode).h;	// Integer
+	},
+
+	// TODO: maybe the parent should set these methods directly rather than forcing the code
+	// into the button widget?
+	_onTitleClick: function(){
+		// summary:
+		//		Callback when someone clicks my title.
+		var parent = this.getParent();
+		if(!parent._inTransition){
+			parent.selectChild(this.contentWidget, true);
+			dijit.focus(this.focusNode);
+		}
+	},
+
+	_onTitleKeyPress: function(/*Event*/ evt){
+		return this.getParent()._onKeyPress(evt, this.contentWidget);
+	},
+
+	_setSelectedAttr: function(/*Boolean*/ isSelected){
+		this.selected = isSelected;
+		dijit.setWaiState(this.focusNode, "expanded", isSelected);
+		dijit.setWaiState(this.focusNode, "selected", isSelected);
+		this.focusNode.setAttribute("tabIndex", isSelected ? "0" : "-1");
+	}
 });
-this.inherited(arguments);
-},_transition:function(_f,_10){
-if(this._inTransition){
-return;
-}
-this._inTransition=true;
-var _11=[];
-var _12=this._verticalSpace;
-if(_f){
-_f._buttonWidget.setSelected(true);
-this._showChild(_f);
-if(this.doLayout&&_f.resize){
-_f.resize(this._containerContentBox);
-}
-var _13=_f.domNode;
-dojo.addClass(_13,"dijitVisible");
-dojo.removeClass(_13,"dijitHidden");
-var _14=_13.style.overflow;
-_13.style.overflow="hidden";
-_11.push(dojo.animateProperty({node:_13,duration:this.duration,properties:{height:{start:1,end:this._getTargetHeight(_13)}},onEnd:dojo.hitch(this,function(){
-_13.style.overflow=_14;
-delete this._inTransition;
-})}));
-}
-if(_10){
-_10._buttonWidget.setSelected(false);
-var _15=_10.domNode,_16=_15.style.overflow;
-_15.style.overflow="hidden";
-_11.push(dojo.animateProperty({node:_15,duration:this.duration,properties:{height:{start:this._getTargetHeight(_15),end:1}},onEnd:function(){
-dojo.addClass(_15,"dijitHidden");
-dojo.removeClass(_15,"dijitVisible");
-_15.style.overflow=_16;
-if(_10.onHide){
-_10.onHide();
-}
-}}));
-}
-dojo.fx.combine(_11).play();
-},_onKeyPress:function(e,_17){
-if(this._inTransition||this.disabled||e.altKey||!(_17||e.ctrlKey)){
-if(this._inTransition){
-dojo.stopEvent(e);
-}
-return;
-}
-var k=dojo.keys,c=e.charOrCode;
-if((_17&&(c==k.LEFT_ARROW||c==k.UP_ARROW))||(e.ctrlKey&&c==k.PAGE_UP)){
-this._adjacent(false)._buttonWidget._onTitleClick();
-dojo.stopEvent(e);
-}else{
-if((_17&&(c==k.RIGHT_ARROW||c==k.DOWN_ARROW))||(e.ctrlKey&&(c==k.PAGE_DOWN||c==k.TAB))){
-this._adjacent(true)._buttonWidget._onTitleClick();
-dojo.stopEvent(e);
-}
-}
-}});
-dojo.declare("dijit.layout._AccordionButton",[dijit._Widget,dijit._Templated],{templateString:dojo.cache("dijit.layout","templates/AccordionButton.html","<div dojoAttachPoint='titleNode,focusNode' dojoAttachEvent='ondijitclick:_onTitleClick,onkeypress:_onTitleKeyPress,onfocus:_handleFocus,onblur:_handleFocus,onmouseenter:_onTitleEnter,onmouseleave:_onTitleLeave'\n\t\tclass='dijitAccordionTitle' wairole=\"tab\" waiState=\"expanded-false\"\n\t\t><span class='dijitInline dijitAccordionArrow [...]
-return this.parent;
-},postCreate:function(){
-this.inherited(arguments);
-dojo.setSelectable(this.domNode,false);
-this.setSelected(this.selected);
-var _18=dojo.attr(this.domNode,"id").replace(" ","_");
-dojo.attr(this.titleTextNode,"id",_18+"_title");
-dijit.setWaiState(this.focusNode,"labelledby",dojo.attr(this.titleTextNode,"id"));
-},getTitleHeight:function(){
-return dojo.marginBox(this.titleNode).h;
-},_onTitleClick:function(){
-var _19=this.getParent();
-if(!_19._inTransition){
-_19.selectChild(this.contentWidget);
-dijit.focus(this.focusNode);
-}
-},_onTitleEnter:function(){
-dojo.addClass(this.focusNode,"dijitAccordionTitle-hover");
-},_onTitleLeave:function(){
-dojo.removeClass(this.focusNode,"dijitAccordionTitle-hover");
-},_onTitleKeyPress:function(evt){
-return this.getParent()._onKeyPress(evt,this.contentWidget);
-},_setSelectedState:function(_1a){
-this.selected=_1a;
-dojo[(_1a?"addClass":"removeClass")](this.titleNode,"dijitAccordionTitle-selected");
-dijit.setWaiState(this.focusNode,"expanded",_1a);
-dijit.setWaiState(this.focusNode,"selected",_1a);
-this.focusNode.setAttribute("tabIndex",_1a?"0":"-1");
-},_handleFocus:function(e){
-dojo.toggleClass(this.titleTextNode,"dijitAccordionFocused",e.type=="focus");
-},setSelected:function(_1b){
-this._setSelectedState(_1b);
-if(_1b){
-var cw=this.contentWidget;
-if(cw.onSelected){
-cw.onSelected();
-}
-}
-}});
-}
diff --git a/dijit/layout/AccordionPane.js b/dijit/layout/AccordionPane.js
index 4804c41..e44fca1 100644
--- a/dijit/layout/AccordionPane.js
+++ b/dijit/layout/AccordionPane.js
@@ -1,16 +1,19 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout.AccordionPane"]){
-dojo._hasResource["dijit.layout.AccordionPane"]=true;
 dojo.provide("dijit.layout.AccordionPane");
+
 dojo.require("dijit.layout.ContentPane");
-dojo.declare("dijit.layout.AccordionPane",dijit.layout.ContentPane,{constructor:function(){
-dojo.deprecated("dijit.layout.AccordionPane deprecated, use ContentPane instead","","2.0");
-},onSelected:function(){
-}});
-}
+
+dojo.declare("dijit.layout.AccordionPane", dijit.layout.ContentPane, {
+	// summary:
+	//		Deprecated widget.   Use `dijit.layout.ContentPane` instead.
+	// tags:
+	//		deprecated
+
+	constructor: function(){
+		dojo.deprecated("dijit.layout.AccordionPane deprecated, use ContentPane instead", "", "2.0");
+	},
+
+	onSelected: function(){
+		// summary:
+		//		called when this pane is selected
+	}
+});
diff --git a/dijit/layout/BorderContainer.js b/dijit/layout/BorderContainer.js
index ffb0838..f2b8368 100644
--- a/dijit/layout/BorderContainer.js
+++ b/dijit/layout/BorderContainer.js
@@ -1,337 +1,649 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout.BorderContainer"]){
-dojo._hasResource["dijit.layout.BorderContainer"]=true;
 dojo.provide("dijit.layout.BorderContainer");
+
 dojo.require("dijit.layout._LayoutWidget");
 dojo.require("dojo.cookie");
-dojo.declare("dijit.layout.BorderContainer",dijit.layout._LayoutWidget,{design:"headline",gutters:true,liveSplitters:true,persist:false,baseClass:"dijitBorderContainer",_splitterClass:"dijit.layout._Splitter",postMixInProperties:function(){
-if(!this.gutters){
-this.baseClass+="NoGutter";
-}
-this.inherited(arguments);
-},postCreate:function(){
-this.inherited(arguments);
-this._splitters={};
-this._splitterThickness={};
-},startup:function(){
-if(this._started){
-return;
-}
-dojo.forEach(this.getChildren(),this._setupChild,this);
-this.inherited(arguments);
-},_setupChild:function(_1){
-var _2=_1.region;
-if(_2){
-this.inherited(arguments);
-dojo.addClass(_1.domNode,this.baseClass+"Pane");
-var _3=this.isLeftToRight();
-if(_2=="leading"){
-_2=_3?"left":"right";
-}
-if(_2=="trailing"){
-_2=_3?"right":"left";
-}
-this["_"+_2]=_1.domNode;
-this["_"+_2+"Widget"]=_1;
-if((_1.splitter||this.gutters)&&!this._splitters[_2]){
-var _4=dojo.getObject(_1.splitter?this._splitterClass:"dijit.layout._Gutter");
-var _5=new _4({container:this,child:_1,region:_2,live:this.liveSplitters});
-_5.isSplitter=true;
-this._splitters[_2]=_5.domNode;
-dojo.place(this._splitters[_2],_1.domNode,"after");
-_5.startup();
-}
-_1.region=_2;
-}
-},_computeSplitterThickness:function(_6){
-this._splitterThickness[_6]=this._splitterThickness[_6]||dojo.marginBox(this._splitters[_6])[(/top|bottom/.test(_6)?"h":"w")];
-},layout:function(){
-for(var _7 in this._splitters){
-this._computeSplitterThickness(_7);
-}
-this._layoutChildren();
-},addChild:function(_8,_9){
-this.inherited(arguments);
-if(this._started){
-this.layout();
-}
-},removeChild:function(_a){
-var _b=_a.region;
-var _c=this._splitters[_b];
-if(_c){
-dijit.byNode(_c).destroy();
-delete this._splitters[_b];
-delete this._splitterThickness[_b];
-}
-this.inherited(arguments);
-delete this["_"+_b];
-delete this["_"+_b+"Widget"];
-if(this._started){
-this._layoutChildren(_a.region);
-}
-dojo.removeClass(_a.domNode,this.baseClass+"Pane");
-},getChildren:function(){
-return dojo.filter(this.inherited(arguments),function(_d){
-return !_d.isSplitter;
+
+dojo.declare(
+	"dijit.layout.BorderContainer",
+	dijit.layout._LayoutWidget,
+{
+	// summary:
+	//		Provides layout in up to 5 regions, a mandatory center with optional borders along its 4 sides.
+	//
+	// description:
+	//		A BorderContainer is a box with a specified size, such as style="width: 500px; height: 500px;",
+	//		that contains a child widget marked region="center" and optionally children widgets marked
+	//		region equal to "top", "bottom", "leading", "trailing", "left" or "right".
+	//		Children along the edges will be laid out according to width or height dimensions and may
+	//		include optional splitters (splitter="true") to make them resizable by the user.  The remaining
+	//		space is designated for the center region.
+	//
+	//		NOTE: Splitters must not be more than 50 pixels in width.
+	//
+	//		The outer size must be specified on the BorderContainer node.  Width must be specified for the sides
+	//		and height for the top and bottom, respectively.  No dimensions should be specified on the center;
+	//		it will fill the remaining space.  Regions named "leading" and "trailing" may be used just like
+	//		"left" and "right" except that they will be reversed in right-to-left environments.
+	//
+	// example:
+	// |	<div dojoType="dijit.layout.BorderContainer" design="sidebar" gutters="false"
+	// |            style="width: 400px; height: 300px;">
+	// |		<div dojoType="ContentPane" region="top">header text</div>
+	// |		<div dojoType="ContentPane" region="right" splitter="true" style="width: 200px;">table of contents</div>
+	// |		<div dojoType="ContentPane" region="center">client area</div>
+	// |	</div>
+
+	// design: String
+	//		Which design is used for the layout:
+	//			- "headline" (default) where the top and bottom extend
+	//				the full width of the container
+	//			- "sidebar" where the left and right sides extend from top to bottom.
+	design: "headline",
+
+	// gutters: Boolean
+	//		Give each pane a border and margin.
+	//		Margin determined by domNode.paddingLeft.
+	//		When false, only resizable panes have a gutter (i.e. draggable splitter) for resizing.
+	gutters: true,
+
+	// liveSplitters: Boolean
+	//		Specifies whether splitters resize as you drag (true) or only upon mouseup (false)
+	liveSplitters: true,
+
+	// persist: Boolean
+	//		Save splitter positions in a cookie.
+	persist: false,
+
+	baseClass: "dijitBorderContainer",
+
+	// _splitterClass: String
+	// 		Optional hook to override the default Splitter widget used by BorderContainer
+	_splitterClass: "dijit.layout._Splitter",
+
+	postMixInProperties: function(){
+		// change class name to indicate that BorderContainer is being used purely for
+		// layout (like LayoutContainer) rather than for pretty formatting.
+		if(!this.gutters){
+			this.baseClass += "NoGutter";
+		}
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+
+		this._splitters = {};
+		this._splitterThickness = {};
+	},
+
+	startup: function(){
+		if(this._started){ return; }
+		dojo.forEach(this.getChildren(), this._setupChild, this);
+		this.inherited(arguments);
+	},
+
+	_setupChild: function(/*dijit._Widget*/ child){
+		// Override _LayoutWidget._setupChild().
+
+		var region = child.region;
+		if(region){
+			this.inherited(arguments);
+
+			dojo.addClass(child.domNode, this.baseClass+"Pane");
+
+			var ltr = this.isLeftToRight();
+			if(region == "leading"){ region = ltr ? "left" : "right"; }
+			if(region == "trailing"){ region = ltr ? "right" : "left"; }
+
+			//FIXME: redundant?
+			this["_"+region] = child.domNode;
+			this["_"+region+"Widget"] = child;
+
+			// Create draggable splitter for resizing pane,
+			// or alternately if splitter=false but BorderContainer.gutters=true then
+			// insert dummy div just for spacing
+			if((child.splitter || this.gutters) && !this._splitters[region]){
+				var _Splitter = dojo.getObject(child.splitter ? this._splitterClass : "dijit.layout._Gutter");
+				var splitter = new _Splitter({
+					id: child.id + "_splitter",
+					container: this,
+					child: child,
+					region: region,
+					live: this.liveSplitters
+				});
+				splitter.isSplitter = true;
+				this._splitters[region] = splitter.domNode;
+				dojo.place(this._splitters[region], child.domNode, "after");
+
+				// Splitters arent added as Contained children, so we need to call startup explicitly
+				splitter.startup();
+			}
+			child.region = region;
+		}
+	},
+
+	_computeSplitterThickness: function(region){
+		this._splitterThickness[region] = this._splitterThickness[region] ||
+			dojo.marginBox(this._splitters[region])[(/top|bottom/.test(region) ? 'h' : 'w')];
+	},
+
+	layout: function(){
+		// Implement _LayoutWidget.layout() virtual method.
+		for(var region in this._splitters){ this._computeSplitterThickness(region); }
+		this._layoutChildren();
+	},
+
+	addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+		// Override _LayoutWidget.addChild().
+		this.inherited(arguments);
+		if(this._started){
+			this.layout(); //OPT
+		}
+	},
+
+	removeChild: function(/*dijit._Widget*/ child){
+		// Override _LayoutWidget.removeChild().
+		var region = child.region;
+		var splitter = this._splitters[region];
+		if(splitter){
+			dijit.byNode(splitter).destroy();
+			delete this._splitters[region];
+			delete this._splitterThickness[region];
+		}
+		this.inherited(arguments);
+		delete this["_"+region];
+		delete this["_" +region+"Widget"];
+		if(this._started){
+			this._layoutChildren();
+		}
+		dojo.removeClass(child.domNode, this.baseClass+"Pane");
+	},
+
+	getChildren: function(){
+		// Override _LayoutWidget.getChildren() to only return real children, not the splitters.
+		return dojo.filter(this.inherited(arguments), function(widget){
+			return !widget.isSplitter;
+		});
+	},
+
+	getSplitter: function(/*String*/region){
+		// summary:
+		//		Returns the widget responsible for rendering the splitter associated with region
+		var splitter = this._splitters[region];
+		return splitter ? dijit.byNode(splitter) : null;
+	},
+
+	resize: function(newSize, currentSize){
+		// Overrides _LayoutWidget.resize().
+
+		// resetting potential padding to 0px to provide support for 100% width/height + padding
+		// TODO: this hack doesn't respect the box model and is a temporary fix
+		if(!this.cs || !this.pe){
+			var node = this.domNode;
+			this.cs = dojo.getComputedStyle(node);
+			this.pe = dojo._getPadExtents(node, this.cs);
+			this.pe.r = dojo._toPixelValue(node, this.cs.paddingRight);
+			this.pe.b = dojo._toPixelValue(node, this.cs.paddingBottom);
+
+			dojo.style(node, "padding", "0px");
+		}
+
+		this.inherited(arguments);
+	},
+
+	_layoutChildren: function(/*String?*/changedRegion, /*Number?*/ changedRegionSize){
+		// summary:
+		//		This is the main routine for setting size/position of each child.
+		// description:
+		//		With no arguments, measures the height of top/bottom panes, the width
+		//		of left/right panes, and then sizes all panes accordingly.
+		//
+		//		With changedRegion specified (as "left", "top", "bottom", or "right"),
+		//		it changes that region's width/height to changedRegionSize and
+		//		then resizes other regions that were affected.
+		// changedRegion:
+		//		The region should be changed because splitter was dragged.
+		//		"left", "right", "top", or "bottom".
+		// changedRegionSize:
+		//		The new width/height (in pixels) to make changedRegion
+
+		if(!this._borderBox || !this._borderBox.h){
+			// We are currently hidden, or we haven't been sized by our parent yet.
+			// Abort.   Someone will resize us later.
+			return;
+		}
+
+		var sidebarLayout = (this.design == "sidebar");
+		var topHeight = 0, bottomHeight = 0, leftWidth = 0, rightWidth = 0;
+		var topStyle = {}, leftStyle = {}, rightStyle = {}, bottomStyle = {},
+			centerStyle = (this._center && this._center.style) || {};
+
+		var changedSide = /left|right/.test(changedRegion);
+
+		var layoutSides = !changedRegion || (!changedSide && !sidebarLayout);
+		var layoutTopBottom = !changedRegion || (changedSide && sidebarLayout);
+
+		// Ask browser for width/height of side panes.
+		// Would be nice to cache this but height can change according to width
+		// (because words wrap around).  I don't think width will ever change though
+		// (except when the user drags a splitter).
+		if(this._top){
+			topStyle = (changedRegion == "top" || layoutTopBottom) && this._top.style;
+			topHeight = changedRegion == "top" ? changedRegionSize : dojo.marginBox(this._top).h;
+		}
+		if(this._left){
+			leftStyle = (changedRegion == "left" || layoutSides) && this._left.style;
+			leftWidth = changedRegion == "left" ? changedRegionSize : dojo.marginBox(this._left).w;
+		}
+		if(this._right){
+			rightStyle = (changedRegion == "right" || layoutSides) && this._right.style;
+			rightWidth = changedRegion == "right" ? changedRegionSize : dojo.marginBox(this._right).w;
+		}
+		if(this._bottom){
+			bottomStyle = (changedRegion == "bottom" || layoutTopBottom) && this._bottom.style;
+			bottomHeight = changedRegion == "bottom" ? changedRegionSize : dojo.marginBox(this._bottom).h;
+		}
+
+		var splitters = this._splitters;
+		var topSplitter = splitters.top, bottomSplitter = splitters.bottom,
+			leftSplitter = splitters.left, rightSplitter = splitters.right;
+		var splitterThickness = this._splitterThickness;
+		var topSplitterThickness = splitterThickness.top || 0,
+			leftSplitterThickness = splitterThickness.left || 0,
+			rightSplitterThickness = splitterThickness.right || 0,
+			bottomSplitterThickness = splitterThickness.bottom || 0;
+
+		// Check for race condition where CSS hasn't finished loading, so
+		// the splitter width == the viewport width (#5824)
+		if(leftSplitterThickness > 50 || rightSplitterThickness > 50){
+			setTimeout(dojo.hitch(this, function(){
+				// Results are invalid.  Clear them out.
+				this._splitterThickness = {};
+
+				for(var region in this._splitters){
+					this._computeSplitterThickness(region);
+				}
+				this._layoutChildren();
+			}), 50);
+			return false;
+		}
+
+		var pe = this.pe;
+
+		var splitterBounds = {
+			left: (sidebarLayout ? leftWidth + leftSplitterThickness: 0) + pe.l + "px",
+			right: (sidebarLayout ? rightWidth + rightSplitterThickness: 0) + pe.r + "px"
+		};
+
+		if(topSplitter){
+			dojo.mixin(topSplitter.style, splitterBounds);
+			topSplitter.style.top = topHeight + pe.t + "px";
+		}
+
+		if(bottomSplitter){
+			dojo.mixin(bottomSplitter.style, splitterBounds);
+			bottomSplitter.style.bottom = bottomHeight + pe.b + "px";
+		}
+
+		splitterBounds = {
+			top: (sidebarLayout ? 0 : topHeight + topSplitterThickness) + pe.t + "px",
+			bottom: (sidebarLayout ? 0 : bottomHeight + bottomSplitterThickness) + pe.b + "px"
+		};
+
+		if(leftSplitter){
+			dojo.mixin(leftSplitter.style, splitterBounds);
+			leftSplitter.style.left = leftWidth + pe.l + "px";
+		}
+
+		if(rightSplitter){
+			dojo.mixin(rightSplitter.style, splitterBounds);
+			rightSplitter.style.right = rightWidth + pe.r +	"px";
+		}
+
+		dojo.mixin(centerStyle, {
+			top: pe.t + topHeight + topSplitterThickness + "px",
+			left: pe.l + leftWidth + leftSplitterThickness + "px",
+			right: pe.r + rightWidth + rightSplitterThickness + "px",
+			bottom: pe.b + bottomHeight + bottomSplitterThickness + "px"
+		});
+
+		var bounds = {
+			top: sidebarLayout ? pe.t + "px" : centerStyle.top,
+			bottom: sidebarLayout ? pe.b + "px" : centerStyle.bottom
+		};
+		dojo.mixin(leftStyle, bounds);
+		dojo.mixin(rightStyle, bounds);
+		leftStyle.left = pe.l + "px"; rightStyle.right = pe.r + "px"; topStyle.top = pe.t + "px"; bottomStyle.bottom = pe.b + "px";
+		if(sidebarLayout){
+			topStyle.left = bottomStyle.left = leftWidth + leftSplitterThickness + pe.l + "px";
+			topStyle.right = bottomStyle.right = rightWidth + rightSplitterThickness + pe.r + "px";
+		}else{
+			topStyle.left = bottomStyle.left = pe.l + "px";
+			topStyle.right = bottomStyle.right = pe.r + "px";
+		}
+
+		// More calculations about sizes of panes
+		var containerHeight = this._borderBox.h - pe.t - pe.b,
+			middleHeight = containerHeight - ( topHeight + topSplitterThickness + bottomHeight + bottomSplitterThickness),
+			sidebarHeight = sidebarLayout ? containerHeight : middleHeight;
+
+		var containerWidth = this._borderBox.w - pe.l - pe.r,
+			middleWidth = containerWidth - (leftWidth + leftSplitterThickness + rightWidth + rightSplitterThickness),
+			sidebarWidth = sidebarLayout ? middleWidth : containerWidth;
+
+		// New margin-box size of each pane
+		var dim = {
+			top:	{ w: sidebarWidth, h: topHeight },
+			bottom: { w: sidebarWidth, h: bottomHeight },
+			left:	{ w: leftWidth, h: sidebarHeight },
+			right:	{ w: rightWidth, h: sidebarHeight },
+			center:	{ h: middleHeight, w: middleWidth }
+		};
+
+		if(changedRegion){
+			// Respond to splitter drag event by changing changedRegion's width or height
+			var child = this["_" + changedRegion + "Widget"],
+				mb = {};
+				mb[ /top|bottom/.test(changedRegion) ? "h" : "w"] = changedRegionSize;
+			child.resize ? child.resize(mb, dim[child.region]) : dojo.marginBox(child.domNode, mb);
+		}
+
+		// Nodes in IE<8 don't respond to t/l/b/r, and TEXTAREA doesn't respond in any browser
+		var janky = dojo.isIE < 8 || (dojo.isIE && dojo.isQuirks) || dojo.some(this.getChildren(), function(child){
+			return child.domNode.tagName == "TEXTAREA" || child.domNode.tagName == "INPUT";
+		});
+		if(janky){
+			// Set the size of the children the old fashioned way, by setting
+			// CSS width and height
+
+			var resizeWidget = function(widget, changes, result){
+				if(widget){
+					(widget.resize ? widget.resize(changes, result) : dojo.marginBox(widget.domNode, changes));
+				}
+			};
+
+			if(leftSplitter){ leftSplitter.style.height = sidebarHeight; }
+			if(rightSplitter){ rightSplitter.style.height = sidebarHeight; }
+			resizeWidget(this._leftWidget, {h: sidebarHeight}, dim.left);
+			resizeWidget(this._rightWidget, {h: sidebarHeight}, dim.right);
+
+			if(topSplitter){ topSplitter.style.width = sidebarWidth; }
+			if(bottomSplitter){ bottomSplitter.style.width = sidebarWidth; }
+			resizeWidget(this._topWidget, {w: sidebarWidth}, dim.top);
+			resizeWidget(this._bottomWidget, {w: sidebarWidth}, dim.bottom);
+
+			resizeWidget(this._centerWidget, dim.center);
+		}else{
+			// Calculate which panes need a notification that their size has been changed
+			// (we've already set style.top/bottom/left/right on those other panes).
+			var notifySides = !changedRegion || (/top|bottom/.test(changedRegion) && this.design != "sidebar"),
+				notifyTopBottom = !changedRegion || (/left|right/.test(changedRegion) && this.design == "sidebar"),
+				notifyList = {
+					center: true,
+					left: notifySides,
+					right: notifySides,
+					top: notifyTopBottom,
+					bottom: notifyTopBottom
+				};
+			
+			// Send notification to those panes that have changed size
+			dojo.forEach(this.getChildren(), function(child){
+				if(child.resize && notifyList[child.region]){
+					child.resize(null, dim[child.region]);
+				}
+			}, this);
+		}
+	},
+
+	destroy: function(){
+		for(var region in this._splitters){
+			var splitter = this._splitters[region];
+			dijit.byNode(splitter).destroy();
+			dojo.destroy(splitter);
+		}
+		delete this._splitters;
+		delete this._splitterThickness;
+		this.inherited(arguments);
+	}
 });
-},getSplitter:function(_e){
-var _f=this._splitters[_e];
-return _f?dijit.byNode(_f):null;
-},resize:function(_10,_11){
-if(!this.cs||!this.pe){
-var _12=this.domNode;
-this.cs=dojo.getComputedStyle(_12);
-this.pe=dojo._getPadExtents(_12,this.cs);
-this.pe.r=dojo._toPixelValue(_12,this.cs.paddingRight);
-this.pe.b=dojo._toPixelValue(_12,this.cs.paddingBottom);
-dojo.style(_12,"padding","0px");
-}
-this.inherited(arguments);
-},_layoutChildren:function(_13){
-if(!this._borderBox||!this._borderBox.h){
-return;
-}
-var _14=(this.design=="sidebar");
-var _15=0,_16=0,_17=0,_18=0;
-var _19={},_1a={},_1b={},_1c={},_1d=(this._center&&this._center.style)||{};
-var _1e=/left|right/.test(_13);
-var _1f=!_13||(!_1e&&!_14);
-var _20=!_13||(_1e&&_14);
-if(this._top){
-_19=_20&&this._top.style;
-_15=dojo.marginBox(this._top).h;
-}
-if(this._left){
-_1a=_1f&&this._left.style;
-_17=dojo.marginBox(this._left).w;
-}
-if(this._right){
-_1b=_1f&&this._right.style;
-_18=dojo.marginBox(this._right).w;
-}
-if(this._bottom){
-_1c=_20&&this._bottom.style;
-_16=dojo.marginBox(this._bottom).h;
-}
-var _21=this._splitters;
-var _22=_21.top,_23=_21.bottom,_24=_21.left,_25=_21.right;
-var _26=this._splitterThickness;
-var _27=_26.top||0,_28=_26.left||0,_29=_26.right||0,_2a=_26.bottom||0;
-if(_28>50||_29>50){
-setTimeout(dojo.hitch(this,function(){
-this._splitterThickness={};
-for(var _2b in this._splitters){
-this._computeSplitterThickness(_2b);
-}
-this._layoutChildren();
-}),50);
-return false;
-}
-var pe=this.pe;
-var _2c={left:(_14?_17+_28:0)+pe.l+"px",right:(_14?_18+_29:0)+pe.r+"px"};
-if(_22){
-dojo.mixin(_22.style,_2c);
-_22.style.top=_15+pe.t+"px";
-}
-if(_23){
-dojo.mixin(_23.style,_2c);
-_23.style.bottom=_16+pe.b+"px";
-}
-_2c={top:(_14?0:_15+_27)+pe.t+"px",bottom:(_14?0:_16+_2a)+pe.b+"px"};
-if(_24){
-dojo.mixin(_24.style,_2c);
-_24.style.left=_17+pe.l+"px";
-}
-if(_25){
-dojo.mixin(_25.style,_2c);
-_25.style.right=_18+pe.r+"px";
-}
-dojo.mixin(_1d,{top:pe.t+_15+_27+"px",left:pe.l+_17+_28+"px",right:pe.r+_18+_29+"px",bottom:pe.b+_16+_2a+"px"});
-var _2d={top:_14?pe.t+"px":_1d.top,bottom:_14?pe.b+"px":_1d.bottom};
-dojo.mixin(_1a,_2d);
-dojo.mixin(_1b,_2d);
-_1a.left=pe.l+"px";
-_1b.right=pe.r+"px";
-_19.top=pe.t+"px";
-_1c.bottom=pe.b+"px";
-if(_14){
-_19.left=_1c.left=_17+_28+pe.l+"px";
-_19.right=_1c.right=_18+_29+pe.r+"px";
-}else{
-_19.left=_1c.left=pe.l+"px";
-_19.right=_1c.right=pe.r+"px";
-}
-var _2e=this._borderBox.h-pe.t-pe.b,_2f=_2e-(_15+_27+_16+_2a),_30=_14?_2e:_2f;
-var _31=this._borderBox.w-pe.l-pe.r,_32=_31-(_17+_28+_18+_29),_33=_14?_32:_31;
-var dim={top:{w:_33,h:_15},bottom:{w:_33,h:_16},left:{w:_17,h:_30},right:{w:_18,h:_30},center:{h:_2f,w:_32}};
-var _34=dojo.isIE<8||(dojo.isIE&&dojo.isQuirks)||dojo.some(this.getChildren(),function(_35){
-return _35.domNode.tagName=="TEXTAREA"||_35.domNode.tagName=="INPUT";
+
+// This argument can be specified for the children of a BorderContainer.
+// Since any widget can be specified as a LayoutContainer child, mix it
+// into the base widget class.  (This is a hack, but it's effective.)
+dojo.extend(dijit._Widget, {
+	// region: [const] String
+	//		Parameter for children of `dijit.layout.BorderContainer`.
+	//		Values: "top", "bottom", "leading", "trailing", "left", "right", "center".
+	//		See the `dijit.layout.BorderContainer` description for details.
+	region: '',
+
+	// splitter: [const] Boolean
+	//		Parameter for child of `dijit.layout.BorderContainer` where region != "center".
+	//		If true, enables user to resize the widget by putting a draggable splitter between
+	//		this widget and the region=center widget.
+	splitter: false,
+
+	// minSize: [const] Number
+	//		Parameter for children of `dijit.layout.BorderContainer`.
+	//		Specifies a minimum size (in pixels) for this widget when resized by a splitter.
+	minSize: 0,
+
+	// maxSize: [const] Number
+	//		Parameter for children of `dijit.layout.BorderContainer`.
+	//		Specifies a maximum size (in pixels) for this widget when resized by a splitter.
+	maxSize: Infinity
 });
-if(_34){
-var _36=function(_37,_38,_39){
-if(_37){
-(_37.resize?_37.resize(_38,_39):dojo.marginBox(_37.domNode,_38));
-}
-};
-if(_24){
-_24.style.height=_30;
-}
-if(_25){
-_25.style.height=_30;
-}
-_36(this._leftWidget,{h:_30},dim.left);
-_36(this._rightWidget,{h:_30},dim.right);
-if(_22){
-_22.style.width=_33;
-}
-if(_23){
-_23.style.width=_33;
-}
-_36(this._topWidget,{w:_33},dim.top);
-_36(this._bottomWidget,{w:_33},dim.bottom);
-_36(this._centerWidget,dim.center);
-}else{
-var _3a={};
-if(_13){
-_3a[_13]=_3a.center=true;
-if(/top|bottom/.test(_13)&&this.design!="sidebar"){
-_3a.left=_3a.right=true;
-}else{
-if(/left|right/.test(_13)&&this.design=="sidebar"){
-_3a.top=_3a.bottom=true;
-}
-}
-}
-dojo.forEach(this.getChildren(),function(_3b){
-if(_3b.resize&&(!_13||_3b.region in _3a)){
-_3b.resize(null,dim[_3b.region]);
-}
-},this);
-}
-},destroy:function(){
-for(var _3c in this._splitters){
-var _3d=this._splitters[_3c];
-dijit.byNode(_3d).destroy();
-dojo.destroy(_3d);
-}
-delete this._splitters;
-delete this._splitterThickness;
-this.inherited(arguments);
-}});
-dojo.extend(dijit._Widget,{region:"",splitter:false,minSize:0,maxSize:Infinity});
+
 dojo.require("dijit._Templated");
-dojo.declare("dijit.layout._Splitter",[dijit._Widget,dijit._Templated],{live:true,templateString:"<div class=\"dijitSplitter\" dojoAttachEvent=\"onkeypress:_onKeyPress,onmousedown:_startDrag,onmouseenter:_onMouse,onmouseleave:_onMouse\" tabIndex=\"0\" waiRole=\"separator\"><div class=\"dijitSplitterThumb\"></div></div>",postCreate:function(){
-this.inherited(arguments);
-this.horizontal=/top|bottom/.test(this.region);
-dojo.addClass(this.domNode,"dijitSplitter"+(this.horizontal?"H":"V"));
-this._factor=/top|left/.test(this.region)?1:-1;
-this._cookieName=this.container.id+"_"+this.region;
-if(this.container.persist){
-var _3e=dojo.cookie(this._cookieName);
-if(_3e){
-this.child.domNode.style[this.horizontal?"height":"width"]=_3e;
-}
-}
-},_computeMaxSize:function(){
-var dim=this.horizontal?"h":"w",_3f=this.container._splitterThickness[this.region];
-var _40={left:"right",right:"left",top:"bottom",bottom:"top",leading:"trailing",trailing:"leading"},_41=this.container["_"+_40[this.region]];
-var _42=dojo.contentBox(this.container.domNode)[dim]-(_41?dojo.marginBox(_41)[dim]:0)-20-_3f*2;
-return Math.min(this.child.maxSize,_42);
-},_startDrag:function(e){
-if(!this.cover){
-this.cover=dojo.doc.createElement("div");
-dojo.addClass(this.cover,"dijitSplitterCover");
-dojo.place(this.cover,this.child.domNode,"after");
-}
-dojo.addClass(this.cover,"dijitSplitterCoverActive");
-if(this.fake){
-dojo.destroy(this.fake);
-}
-if(!(this._resize=this.live)){
-(this.fake=this.domNode.cloneNode(true)).removeAttribute("id");
-dojo.addClass(this.domNode,"dijitSplitterShadow");
-dojo.place(this.fake,this.domNode,"after");
-}
-dojo.addClass(this.domNode,"dijitSplitterActive");
-dojo.addClass(this.domNode,"dijitSplitter"+(this.horizontal?"H":"V")+"Active");
-if(this.fake){
-dojo.removeClass(this.fake,"dijitSplitterHover");
-dojo.removeClass(this.fake,"dijitSplitter"+(this.horizontal?"H":"V")+"Hover");
-}
-var _43=this._factor,max=this._computeMaxSize(),min=this.child.minSize||20,_44=this.horizontal,_45=_44?"pageY":"pageX",_46=e[_45],_47=this.domNode.style,dim=_44?"h":"w",_48=dojo.marginBox(this.child.domNode)[dim],_49=this.region,_4a=parseInt(this.domNode.style[_49],10),_4b=this._resize,mb={},_4c=this.child.domNode,_4d=dojo.hitch(this.container,this.container._layoutChildren),de=dojo.doc.body;
-this._handlers=(this._handlers||[]).concat([dojo.connect(de,"onmousemove",this._drag=function(e,_4e){
-var _4f=e[_45]-_46,_50=_43*_4f+_48,_51=Math.max(Math.min(_50,max),min);
-if(_4b||_4e){
-mb[dim]=_51;
-dojo.marginBox(_4c,mb);
-_4d(_49);
-}
-_47[_49]=_43*_4f+_4a+(_51-_50)+"px";
-}),dojo.connect(dojo.doc,"ondragstart",dojo.stopEvent),dojo.connect(dojo.body(),"onselectstart",dojo.stopEvent),dojo.connect(de,"onmouseup",this,"_stopDrag")]);
-dojo.stopEvent(e);
-},_onMouse:function(e){
-var o=(e.type=="mouseover"||e.type=="mouseenter");
-dojo.toggleClass(this.domNode,"dijitSplitterHover",o);
-dojo.toggleClass(this.domNode,"dijitSplitter"+(this.horizontal?"H":"V")+"Hover",o);
-},_stopDrag:function(e){
-try{
-if(this.cover){
-dojo.removeClass(this.cover,"dijitSplitterCoverActive");
-}
-if(this.fake){
-dojo.destroy(this.fake);
-}
-dojo.removeClass(this.domNode,"dijitSplitterActive");
-dojo.removeClass(this.domNode,"dijitSplitter"+(this.horizontal?"H":"V")+"Active");
-dojo.removeClass(this.domNode,"dijitSplitterShadow");
-this._drag(e);
-this._drag(e,true);
-}
-finally{
-this._cleanupHandlers();
-delete this._drag;
-}
-if(this.container.persist){
-dojo.cookie(this._cookieName,this.child.domNode.style[this.horizontal?"height":"width"],{expires:365});
-}
-},_cleanupHandlers:function(){
-dojo.forEach(this._handlers,dojo.disconnect);
-delete this._handlers;
-},_onKeyPress:function(e){
-this._resize=true;
-var _52=this.horizontal;
-var _53=1;
-var dk=dojo.keys;
-switch(e.charOrCode){
-case _52?dk.UP_ARROW:dk.LEFT_ARROW:
-_53*=-1;
-case _52?dk.DOWN_ARROW:dk.RIGHT_ARROW:
-break;
-default:
-return;
-}
-var _54=dojo.marginBox(this.child.domNode)[_52?"h":"w"]+this._factor*_53;
-var mb={};
-mb[this.horizontal?"h":"w"]=Math.max(Math.min(_54,this._computeMaxSize()),this.child.minSize);
-dojo.marginBox(this.child.domNode,mb);
-this.container._layoutChildren(this.region);
-dojo.stopEvent(e);
-},destroy:function(){
-this._cleanupHandlers();
-delete this.child;
-delete this.container;
-delete this.cover;
-delete this.fake;
-this.inherited(arguments);
-}});
-dojo.declare("dijit.layout._Gutter",[dijit._Widget,dijit._Templated],{templateString:"<div class=\"dijitGutter\" waiRole=\"presentation\"></div>",postCreate:function(){
-this.horizontal=/top|bottom/.test(this.region);
-dojo.addClass(this.domNode,"dijitGutter"+(this.horizontal?"H":"V"));
-}});
-}
+
+dojo.declare("dijit.layout._Splitter", [ dijit._Widget, dijit._Templated ],
+{
+	// summary:
+	//		A draggable spacer between two items in a `dijit.layout.BorderContainer`.
+	// description:
+	//		This is instantiated by `dijit.layout.BorderContainer`.  Users should not
+	//		create it directly.
+	// tags:
+	//		private
+
+/*=====
+ 	// container: [const] dijit.layout.BorderContainer
+ 	//		Pointer to the parent BorderContainer
+	container: null,
+
+	// child: [const] dijit.layout._LayoutWidget
+	//		Pointer to the pane associated with this splitter
+	child: null,
+
+	// region: String
+	//		Region of pane associated with this splitter.
+	//		"top", "bottom", "left", "right".
+	region: null,
+=====*/
+
+	// live: [const] Boolean
+	//		If true, the child's size changes and the child widget is redrawn as you drag the splitter;
+	//		otherwise, the size doesn't change until you drop the splitter (by mouse-up)
+	live: true,
+
+	templateString: '<div class="dijitSplitter" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_startDrag,onmouseenter:_onMouse,onmouseleave:_onMouse" tabIndex="0" waiRole="separator"><div class="dijitSplitterThumb"></div></div>',
+
+	postCreate: function(){
+		this.inherited(arguments);
+		this.horizontal = /top|bottom/.test(this.region);
+		dojo.addClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V"));
+//		dojo.addClass(this.child.domNode, "dijitSplitterPane");
+//		dojo.setSelectable(this.domNode, false); //TODO is this necessary?
+
+		this._factor = /top|left/.test(this.region) ? 1 : -1;
+
+		this._cookieName = this.container.id + "_" + this.region;
+		if(this.container.persist){
+			// restore old size
+			var persistSize = dojo.cookie(this._cookieName);
+			if(persistSize){
+				this.child.domNode.style[this.horizontal ? "height" : "width"] = persistSize;
+			}
+		}
+	},
+
+	_computeMaxSize: function(){
+		// summary:
+		//		Compute the maximum size that my corresponding pane can be set to
+
+		var dim = this.horizontal ? 'h' : 'w',
+			thickness = this.container._splitterThickness[this.region];
+			
+		// Get DOMNode of opposite pane, if an opposite pane exists.
+		// Ex: if I am the _Splitter for the left pane, then get the right pane.
+		var flip = {left:'right', right:'left', top:'bottom', bottom:'top', leading:'trailing', trailing:'leading'},
+			oppNode = this.container["_" + flip[this.region]];
+		
+		// I can expand up to the edge of the opposite pane, or if there's no opposite pane, then to
+		// edge of BorderContainer
+		var available = dojo.contentBox(this.container.domNode)[dim] -
+				(oppNode ? dojo.marginBox(oppNode)[dim] : 0) -
+				20 - thickness * 2;
+
+		return Math.min(this.child.maxSize, available);
+	},
+
+	_startDrag: function(e){
+		if(!this.cover){
+			this.cover = dojo.doc.createElement('div');
+			dojo.addClass(this.cover, "dijitSplitterCover");
+			dojo.place(this.cover, this.child.domNode, "after");
+		}
+		dojo.addClass(this.cover, "dijitSplitterCoverActive");
+
+		// Safeguard in case the stop event was missed.  Shouldn't be necessary if we always get the mouse up.
+		if(this.fake){ dojo.destroy(this.fake); }
+		if(!(this._resize = this.live)){ //TODO: disable live for IE6?
+			// create fake splitter to display at old position while we drag
+			(this.fake = this.domNode.cloneNode(true)).removeAttribute("id");
+			dojo.addClass(this.domNode, "dijitSplitterShadow");
+			dojo.place(this.fake, this.domNode, "after");
+		}
+		dojo.addClass(this.domNode, "dijitSplitterActive");
+		dojo.addClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Active");
+		if(this.fake){
+			dojo.removeClass(this.fake, "dijitSplitterHover");
+			dojo.removeClass(this.fake, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover");
+		}
+
+		//Performance: load data info local vars for onmousevent function closure
+		var factor = this._factor,
+			max = this._computeMaxSize(),
+			min = this.child.minSize || 20,
+			isHorizontal = this.horizontal,
+			axis = isHorizontal ? "pageY" : "pageX",
+			pageStart = e[axis],
+			splitterStyle = this.domNode.style,
+			dim = isHorizontal ? 'h' : 'w',
+			childStart = dojo.marginBox(this.child.domNode)[dim],
+			region = this.region,
+			splitterStart = parseInt(this.domNode.style[region], 10),
+			resize = this._resize,
+			childNode = this.child.domNode,
+			layoutFunc = dojo.hitch(this.container, this.container._layoutChildren),
+			de = dojo.doc;
+
+		this._handlers = (this._handlers || []).concat([
+			dojo.connect(de, "onmousemove", this._drag = function(e, forceResize){
+				var delta = e[axis] - pageStart,
+					childSize = factor * delta + childStart,
+					boundChildSize = Math.max(Math.min(childSize, max), min);
+
+				if(resize || forceResize){
+					layoutFunc(region, boundChildSize);
+				}
+				splitterStyle[region] = factor * delta + splitterStart + (boundChildSize - childSize) + "px";
+			}),
+			dojo.connect(de, "ondragstart", dojo.stopEvent),
+			dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent),
+			dojo.connect(de, "onmouseup", this, "_stopDrag")
+		]);
+		dojo.stopEvent(e);
+	},
+
+	_onMouse: function(e){
+		var o = (e.type == "mouseover" || e.type == "mouseenter");
+		dojo.toggleClass(this.domNode, "dijitSplitterHover", o);
+		dojo.toggleClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover", o);
+	},
+
+	_stopDrag: function(e){
+		try{
+			if(this.cover){
+				dojo.removeClass(this.cover, "dijitSplitterCoverActive");
+			}
+			if(this.fake){ dojo.destroy(this.fake); }
+			dojo.removeClass(this.domNode, "dijitSplitterActive");
+			dojo.removeClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Active");
+			dojo.removeClass(this.domNode, "dijitSplitterShadow");
+			this._drag(e); //TODO: redundant with onmousemove?
+			this._drag(e, true);
+		}finally{
+			this._cleanupHandlers();
+			delete this._drag;
+		}
+
+		if(this.container.persist){
+			dojo.cookie(this._cookieName, this.child.domNode.style[this.horizontal ? "height" : "width"], {expires:365});
+		}
+	},
+
+	_cleanupHandlers: function(){
+		dojo.forEach(this._handlers, dojo.disconnect);
+		delete this._handlers;
+	},
+
+	_onKeyPress: function(/*Event*/ e){
+		// should we apply typematic to this?
+		this._resize = true;
+		var horizontal = this.horizontal;
+		var tick = 1;
+		var dk = dojo.keys;
+		switch(e.charOrCode){
+			case horizontal ? dk.UP_ARROW : dk.LEFT_ARROW:
+				tick *= -1;
+//				break;
+			case horizontal ? dk.DOWN_ARROW : dk.RIGHT_ARROW:
+				break;
+			default:
+//				this.inherited(arguments);
+				return;
+		}
+		var childSize = dojo.marginBox(this.child.domNode)[ horizontal ? 'h' : 'w' ] + this._factor * tick;
+		this.container._layoutChildren(this.region, Math.max(Math.min(childSize, this._computeMaxSize()), this.child.minSize));
+		dojo.stopEvent(e);
+	},
+
+	destroy: function(){
+		this._cleanupHandlers();
+		delete this.child;
+		delete this.container;
+		delete this.cover;
+		delete this.fake;
+		this.inherited(arguments);
+	}
+});
+
+dojo.declare("dijit.layout._Gutter", [dijit._Widget, dijit._Templated ],
+{
+	// summary:
+	// 		Just a spacer div to separate side pane from center pane.
+	//		Basically a trick to lookup the gutter/splitter width from the theme.
+	// description:
+	//		Instantiated by `dijit.layout.BorderContainer`.  Users should not
+	//		create directly.
+	// tags:
+	//		private
+
+	templateString: '<div class="dijitGutter" waiRole="presentation"></div>',
+
+	postCreate: function(){
+		this.horizontal = /top|bottom/.test(this.region);
+		dojo.addClass(this.domNode, "dijitGutter" + (this.horizontal ? "H" : "V"));
+	}
+});
diff --git a/dijit/layout/ContentPane.js b/dijit/layout/ContentPane.js
index b674f4f..197853d 100644
--- a/dijit/layout/ContentPane.js
+++ b/dijit/layout/ContentPane.js
@@ -1,291 +1,723 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout.ContentPane"]){
-dojo._hasResource["dijit.layout.ContentPane"]=true;
 dojo.provide("dijit.layout.ContentPane");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Contained");
-dojo.require("dijit.layout._LayoutWidget");
+dojo.require("dijit.layout._LayoutWidget");	// for dijit.layout.marginBox2contentBox()
+
 dojo.require("dojo.parser");
 dojo.require("dojo.string");
 dojo.require("dojo.html");
-dojo.requireLocalization("dijit","loading",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit.layout.ContentPane",dijit._Widget,{href:"",extractContent:false,parseOnLoad:true,preventCache:false,preload:false,refreshOnShow:false,loadingMessage:"<span class='dijitContentPaneLoading'>${loadingState}</span>",errorMessage:"<span class='dijitContentPaneError'>${errorState}</span>",isLoaded:false,baseClass:"dijitContentPane",doLayout:true,ioArgs:{},isContainer:true,isLayoutContainer:true,onLoadDeferred:null,attributeMap:dojo.delegate(dijit._Widget.prototype.attribute [...]
-this.inherited(arguments);
-var _1=dojo.i18n.getLocalization("dijit","loading",this.lang);
-this.loadingMessage=dojo.string.substitute(this.loadingMessage,_1);
-this.errorMessage=dojo.string.substitute(this.errorMessage,_1);
-if(!this.href&&this.srcNodeRef&&this.srcNodeRef.innerHTML){
-this.isLoaded=true;
-}
-},buildRendering:function(){
-this.inherited(arguments);
-if(!this.containerNode){
-this.containerNode=this.domNode;
-}
-},postCreate:function(){
-this.domNode.title="";
-if(!dojo.attr(this.domNode,"role")){
-dijit.setWaiRole(this.domNode,"group");
-}
-dojo.addClass(this.domNode,this.baseClass);
-},startup:function(){
-if(this._started){
-return;
-}
-var _2=dijit._Contained.prototype.getParent.call(this);
-this._childOfLayoutWidget=_2&&_2.isLayoutContainer;
-this._needLayout=!this._childOfLayoutWidget;
-if(this.isLoaded){
-dojo.forEach(this.getChildren(),function(_3){
-_3.startup();
-});
-}
-if(this._isShown()||this.preload){
-this._onShow();
-}
-this.inherited(arguments);
-},_checkIfSingleChild:function(){
-var _4=dojo.query("> *",this.containerNode).filter(function(_5){
-return _5.tagName!=="SCRIPT";
-}),_6=_4.filter(function(_7){
-return dojo.hasAttr(_7,"dojoType")||dojo.hasAttr(_7,"widgetId");
-}),_8=dojo.filter(_6.map(dijit.byNode),function(_9){
-return _9&&_9.domNode&&_9.resize;
-});
-if(_4.length==_6.length&&_8.length==1){
-this._singleChild=_8[0];
-}else{
-delete this._singleChild;
-}
-dojo.toggleClass(this.containerNode,this.baseClass+"SingleChild",!!this._singleChild);
-},setHref:function(_a){
-dojo.deprecated("dijit.layout.ContentPane.setHref() is deprecated. Use attr('href', ...) instead.","","2.0");
-return this.attr("href",_a);
-},_setHrefAttr:function(_b){
-this.cancel();
-this.onLoadDeferred=new dojo.Deferred(dojo.hitch(this,"cancel"));
-this.href=_b;
-if(this._created&&(this.preload||this._isShown())){
-this._load();
-}else{
-this._hrefChanged=true;
-}
-return this.onLoadDeferred;
-},setContent:function(_c){
-dojo.deprecated("dijit.layout.ContentPane.setContent() is deprecated.  Use attr('content', ...) instead.","","2.0");
-this.attr("content",_c);
-},_setContentAttr:function(_d){
-this.href="";
-this.cancel();
-this.onLoadDeferred=new dojo.Deferred(dojo.hitch(this,"cancel"));
-this._setContent(_d||"");
-this._isDownloaded=false;
-return this.onLoadDeferred;
-},_getContentAttr:function(){
-return this.containerNode.innerHTML;
-},cancel:function(){
-if(this._xhrDfd&&(this._xhrDfd.fired==-1)){
-this._xhrDfd.cancel();
-}
-delete this._xhrDfd;
-this.onLoadDeferred=null;
-},uninitialize:function(){
-if(this._beingDestroyed){
-this.cancel();
-}
-this.inherited(arguments);
-},destroyRecursive:function(_e){
-if(this._beingDestroyed){
-return;
-}
-this.inherited(arguments);
-},resize:function(_f,_10){
-if(!this._wasShown){
-this._onShow();
-}
-this._resizeCalled=true;
-if(_f){
-dojo.marginBox(this.domNode,_f);
-}
-var cn=this.containerNode;
-if(cn===this.domNode){
-var mb=_10||{};
-dojo.mixin(mb,_f||{});
-if(!("h" in mb)||!("w" in mb)){
-mb=dojo.mixin(dojo.marginBox(cn),mb);
-}
-this._contentBox=dijit.layout.marginBox2contentBox(cn,mb);
-}else{
-this._contentBox=dojo.contentBox(cn);
-}
-this._layoutChildren();
-},_isShown:function(){
-if(this._childOfLayoutWidget){
-if(this._resizeCalled&&"open" in this){
-return this.open;
-}
-return this._resizeCalled;
-}else{
-if("open" in this){
-return this.open;
-}else{
-var _11=this.domNode;
-return (_11.style.display!="none")&&(_11.style.visibility!="hidden")&&!dojo.hasClass(_11,"dijitHidden");
-}
-}
-},_onShow:function(){
-if(this.href){
-if(!this._xhrDfd&&(!this.isLoaded||this._hrefChanged||this.refreshOnShow)){
-this.refresh();
-}
-}else{
-if(!this._childOfLayoutWidget&&this._needLayout){
-this._layoutChildren();
-}
-}
-this.inherited(arguments);
-this._wasShown=true;
-},refresh:function(){
-this.cancel();
-this.onLoadDeferred=new dojo.Deferred(dojo.hitch(this,"cancel"));
-this._load();
-return this.onLoadDeferred;
-},_load:function(){
-this._setContent(this.onDownloadStart(),true);
-var _12=this;
-var _13={preventCache:(this.preventCache||this.refreshOnShow),url:this.href,handleAs:"text"};
-if(dojo.isObject(this.ioArgs)){
-dojo.mixin(_13,this.ioArgs);
-}
-var _14=(this._xhrDfd=(this.ioMethod||dojo.xhrGet)(_13));
-_14.addCallback(function(_15){
-try{
-_12._isDownloaded=true;
-_12._setContent(_15,false);
-_12.onDownloadEnd();
-}
-catch(err){
-_12._onError("Content",err);
-}
-delete _12._xhrDfd;
-return _15;
-});
-_14.addErrback(function(err){
-if(!_14.canceled){
-_12._onError("Download",err);
-}
-delete _12._xhrDfd;
-return err;
-});
-delete this._hrefChanged;
-},_onLoadHandler:function(_16){
-this.isLoaded=true;
-try{
-this.onLoadDeferred.callback(_16);
-this.onLoad(_16);
-}
-catch(e){
-console.error("Error "+this.widgetId+" running custom onLoad code: "+e.message);
-}
-},_onUnloadHandler:function(){
-this.isLoaded=false;
-try{
-this.onUnload();
-}
-catch(e){
-console.error("Error "+this.widgetId+" running custom onUnload code: "+e.message);
-}
-},destroyDescendants:function(){
-if(this.isLoaded){
-this._onUnloadHandler();
-}
-var _17=this._contentSetter;
-dojo.forEach(this.getChildren(),function(_18){
-if(_18.destroyRecursive){
-_18.destroyRecursive();
-}
-});
-if(_17){
-dojo.forEach(_17.parseResults,function(_19){
-if(_19.destroyRecursive&&_19.domNode&&_19.domNode.parentNode==dojo.body()){
-_19.destroyRecursive();
-}
-});
-delete _17.parseResults;
-}
-dojo.html._emptyNode(this.containerNode);
-delete this._singleChild;
-},_setContent:function(_1a,_1b){
-this.destroyDescendants();
-var _1c=this._contentSetter;
-if(!(_1c&&_1c instanceof dojo.html._ContentSetter)){
-_1c=this._contentSetter=new dojo.html._ContentSetter({node:this.containerNode,_onError:dojo.hitch(this,this._onError),onContentError:dojo.hitch(this,function(e){
-var _1d=this.onContentError(e);
-try{
-this.containerNode.innerHTML=_1d;
-}
-catch(e){
-console.error("Fatal "+this.id+" could not change content due to "+e.message,e);
-}
-})});
-}
-var _1e=dojo.mixin({cleanContent:this.cleanContent,extractContent:this.extractContent,parseContent:this.parseOnLoad},this._contentSetterParams||{});
-dojo.mixin(_1c,_1e);
-_1c.set((dojo.isObject(_1a)&&_1a.domNode)?_1a.domNode:_1a);
-delete this._contentSetterParams;
-if(!_1b){
-dojo.forEach(this.getChildren(),function(_1f){
-if(!this.parseOnLoad||_1f.getParent){
-_1f.startup();
-}
-},this);
-this._scheduleLayout();
-this._onLoadHandler(_1a);
-}
-},_onError:function(_20,err,_21){
-this.onLoadDeferred.errback(err);
-var _22=this["on"+_20+"Error"].call(this,err);
-if(_21){
-console.error(_21,err);
-}else{
-if(_22){
-this._setContent(_22,true);
-}
-}
-},_scheduleLayout:function(){
-if(this._isShown()){
-this._layoutChildren();
-}else{
-this._needLayout=true;
-}
-},_layoutChildren:function(){
-if(this.doLayout){
-this._checkIfSingleChild();
-}
-if(this._singleChild&&this._singleChild.resize){
-var cb=this._contentBox||dojo.contentBox(this.containerNode);
-this._singleChild.resize({w:cb.w,h:cb.h});
-}else{
-dojo.forEach(this.getChildren(),function(_23){
-if(_23.resize){
-_23.resize();
-}
+dojo.requireLocalization("dijit", "loading");
+
+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 stand alone widget
+	//		or as a base class 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 .set('content', '<b>new content</b>')
+	//
+	//		Or you can send it a NodeList, .set('content', dojo.query('div [class=selected]', userSelection))
+	//		please note that the nodes in NodeList will copied, not moved
+	//
+	//		To do a ajax update use .set('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 set('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
+	//		Indicates that this widget acts as a "parent" to the descendant widgets.
+	//		When the parent is started it will call startup() on the child widgets.
+	//		See also `isLayoutContainer`.
+	isContainer: true,
+
+	// isLayoutContainer: [protected] Boolean
+	//		Indicates that this widget will call resize() on it's child widgets
+	//		when they become visible.
+	isLayoutContainer: true,
+
+	// onLoadDeferred: [readonly] dojo.Deferred
+	//		This is the `dojo.Deferred` returned by attr('href', ...) and refresh().
+	//		Calling onLoadDeferred.addCallback() or addErrback() registers your
+	//		callback to be called only once, when the prior attr('href', ...) call or
+	//		the initial href parameter to the constructor finishes loading.
+	//
+	//		This is different than an onLoad() handler which gets called any time any href is loaded.
+	onLoadDeferred: null,
+
+	// Override _Widget's attributeMap because we don't want the title attribute (used to specify
+	// tab labels) to be copied to ContentPane.domNode... otherwise a tooltip shows up over the
+	// entire pane.
+	attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+		title: []
+	}),
+
+	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; }
+
+		var parent = dijit._Contained.prototype.getParent.call(this);
+		this._childOfLayoutWidget = parent && parent.isLayoutContainer;
+
+		// I need to call resize() on my child/children (when I become visible), unless
+		// I'm the child of a layout widget in which case my parent will call resize() on me and I'll do it then.
+		this._needLayout = !this._childOfLayoutWidget;
+
+		if(this.isLoaded){
+			dojo.forEach(this.getChildren(), function(child){
+				child.startup();
+			});
+		}
+
+		if(this._isShown() || this.preload){
+			this._onShow();
+		}
+
+		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).filter(function(node){
+				return node.tagName !== "SCRIPT"; // or a regexp for hidden elements like script|area|map|etc..
+			}),
+			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;
+		}
+
+		// So we can set overflow: hidden to avoid a safari bug w/scrollbars showing up (#9449)
+		dojo.toggleClass(this.containerNode, this.baseClass + "SingleChild", !!this._singleChild);
+	},
+
+	setHref: function(/*String|Uri*/ href){
+		// summary:
+		//		Deprecated.   Use set('href', ...) instead.
+		dojo.deprecated("dijit.layout.ContentPane.setHref() is deprecated. Use set('href', ...) instead.", "", "2.0");
+		return this.set("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.onLoadDeferred = new dojo.Deferred(dojo.hitch(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())){
+			this._load();
+		}else{
+			// Set flag to indicate that href needs to be loaded the next time the
+			// ContentPane is made visible
+			this._hrefChanged = true;
+		}
+
+		return this.onLoadDeferred;		// dojo.Deferred
+	},
+
+	setContent: function(/*String|DomNode|Nodelist*/data){
+		// summary:
+		//		Deprecated.   Use set('content', ...) instead.
+		dojo.deprecated("dijit.layout.ContentPane.setContent() is deprecated.  Use set('content', ...) instead.", "", "2.0");
+		this.set("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();
+
+		// Even though user is just setting content directly, still need to define an onLoadDeferred
+		// because the _onLoadHandler() handler is still getting called from setContent()
+		this.onLoadDeferred = new dojo.Deferred(dojo.hitch(this, "cancel"));
+
+		this._setContent(data || "");
+
+		this._isDownloaded = false; // mark that content is from a attr('content') not an attr('href')
+
+		return this.onLoadDeferred; 	// dojo.Deferred
+	},
+	_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
+
+		this.onLoadDeferred = null;
+	},
+
+	uninitialize: function(){
+		if(this._beingDestroyed){
+			this.cancel();
+		}
+		this.inherited(arguments);
+	},
+
+	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.inherited(arguments);
+	},
+
+	resize: function(changeSize, resultSize){
+		// summary:
+		//		See `dijit.layout._LayoutWidget.resize` for description.
+		//		Although ContentPane doesn't extend _LayoutWidget, it does implement
+		//		the same API.
+
+		// For the TabContainer --> BorderContainer --> ContentPane case, _onShow() is
+		// never called, so resize() is our trigger to do the initial href download.
+		if(!this._wasShown){
+			this._onShow();
+		}
+
+		this._resizeCalled = true;
+
+		// Set margin box size, unless it wasn't specified, in which case use current size.
+		if(changeSize){
+			dojo.marginBox(this.domNode, changeSize);
+		}
+
+		// Compute content box size of containerNode in case we [later] need to size our single child.
+		var cn = this.containerNode;
+		if(cn === this.domNode){
+			// If changeSize or resultSize was passed to this method and this.containerNode ==
+			// this.domNode then we can compute the content-box size without querying the node,
+			// which is more reliable (similar to LayoutWidget.resize) (see for example #9449).
+			var mb = resultSize || {};
+			dojo.mixin(mb, changeSize || {}); // changeSize overrides resultSize
+			if(!("h" in mb) || !("w" in mb)){
+				mb = dojo.mixin(dojo.marginBox(cn), mb); // just use dojo.marginBox() to fill in missing values
+			}
+			this._contentBox = dijit.layout.marginBox2contentBox(cn, mb);
+		}else{
+			this._contentBox = dojo.contentBox(cn);
+		}
+
+		// Make my children layout, or size my single child widget
+		this._layoutChildren();
+	},
+
+	_isShown: function(){
+		// summary:
+		//		Returns true if the content is currently shown.
+		// description:
+		//		If I am a child of a layout widget then it actually returns true if I've ever been visible,
+		//		not whether I'm currently visible, since that's much faster than tracing up the DOM/widget
+		//		tree every call, and at least solves the performance problem on page load by deferring loading
+		//		hidden ContentPanes until they are first shown
+
+		if(this._childOfLayoutWidget){
+			// If we are TitlePane, etc - we return that only *IF* we've been resized
+			if(this._resizeCalled && "open" in this){
+				return this.open;
+			}
+			return this._resizeCalled;
+		}else if("open" in this){
+			return this.open;		// for TitlePane, etc.
+		}else{
+			// TODO: with _childOfLayoutWidget check maybe this branch no longer necessary?
+			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 whenever the pane is made visible.
+		//
+		//		Does necessary processing, including href download and layout/resize of
+		//		child widget(s)
+
+		if(this.href){
+			if(!this._xhrDfd && // if there's an href that isn't already being loaded
+				(!this.isLoaded || this._hrefChanged || this.refreshOnShow)
+			){
+				this.refresh();
+			}
+		}else{
+			// If we are the child of a layout widget then the layout widget will call resize() on
+			// us, and then we will size our child/children.   Otherwise, we need to do it now.
+			if(!this._childOfLayoutWidget && this._needLayout){
+				// If a layout has been scheduled for when we become visible, do it now
+				this._layoutChildren();
+			}
+		}
+
+		this.inherited(arguments);
+
+		// Need to keep track of whether ContentPane has been shown (which is different than
+		// whether or not it's currently visible).
+		this._wasShown = true;
+	},
+
+	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 in-flight request
+		this.cancel();
+
+		this.onLoadDeferred = new dojo.Deferred(dojo.hitch(this, "cancel"));
+		this._load();
+		return this.onLoadDeferred;
+	},
+
+	_load: function(){
+		// summary:
+		//		Load/reload the href specified in this.href
+
+		// 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;
+		});
+
+		// Remove flag saying that a load is needed
+		delete this._hrefChanged;
+	},
+
+	_onLoadHandler: function(data){
+		// summary:
+		//		This is called whenever new content is being loaded
+		this.isLoaded = true;
+		try{
+			this.onLoadDeferred.callback(data);
+			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);
+
+		// Delete any state information we have about current contents
+		delete this._singleChild;
+	},
+
+	_setContent: function(cont, isFakeContent){
+		// summary:
+		//		Insert the content into the container node
+
+		// first get rid of child widgets
+		this.destroyDescendants();
+
+		// dojo.html.set will take care of the rest of the details
+		// we provide an override 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,
+			dir: this.dir,
+			lang: this.lang
+		}, 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){
+			// Startup each top level child widget (and they will start their children, recursively)
+			dojo.forEach(this.getChildren(), function(child){
+				// The parser has already called startup on all widgets *without* a getParent() method
+				if(!this.parseOnLoad || child.getParent){
+					child.startup();
+				}
+			}, this);
+
+			// 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){
+		this.onLoadDeferred.errback(err);
+
+		// 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.doLayout){
+			this._checkIfSingleChild();
+		}
+
+		if(this._singleChild && this._singleChild.resize){
+			var cb = this._contentBox || dojo.contentBox(this.containerNode);
+
+			// 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});
+		}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
+	}
 });
-}
-delete this._needLayout;
-},onLoad:function(_24){
-},onUnload:function(){
-},onDownloadStart:function(){
-return this.loadingMessage;
-},onContentError:function(_25){
-},onDownloadError:function(_26){
-return this.errorMessage;
-},onDownloadEnd:function(){
-}});
-}
diff --git a/dijit/layout/LayoutContainer.js b/dijit/layout/LayoutContainer.js
index d949a68..7d63538 100644
--- a/dijit/layout/LayoutContainer.js
+++ b/dijit/layout/LayoutContainer.js
@@ -1,28 +1,75 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout.LayoutContainer"]){
-dojo._hasResource["dijit.layout.LayoutContainer"]=true;
 dojo.provide("dijit.layout.LayoutContainer");
+
 dojo.require("dijit.layout._LayoutWidget");
-dojo.declare("dijit.layout.LayoutContainer",dijit.layout._LayoutWidget,{baseClass:"dijitLayoutContainer",constructor:function(){
-dojo.deprecated("dijit.layout.LayoutContainer is deprecated","use BorderContainer instead",2);
-},layout:function(){
-dijit.layout.layoutChildren(this.domNode,this._contentBox,this.getChildren());
-},addChild:function(_1,_2){
-this.inherited(arguments);
-if(this._started){
-dijit.layout.layoutChildren(this.domNode,this._contentBox,this.getChildren());
-}
-},removeChild:function(_3){
-this.inherited(arguments);
-if(this._started){
-dijit.layout.layoutChildren(this.domNode,this._contentBox,this.getChildren());
-}
-}});
-dojo.extend(dijit._Widget,{layoutAlign:"none"});
-}
+
+dojo.declare("dijit.layout.LayoutContainer",
+	dijit.layout._LayoutWidget,
+	{
+	// summary:
+	//		Deprecated.  Use `dijit.layout.BorderContainer` instead.
+	//
+	// description:
+	//		Provides Delphi-style panel layout semantics.
+	//
+	//		A LayoutContainer is a box with a specified size (like style="width: 500px; height: 500px;"),
+	//		that contains children widgets marked with "layoutAlign" of "left", "right", "bottom", "top", and "client".
+	//		It takes it's children marked as left/top/bottom/right, and lays them out along the edges of the box,
+	//		and then it takes the child marked "client" and puts it into the remaining space in the middle.
+	//
+	//		Left/right positioning is similar to CSS's "float: left" and "float: right",
+	//		and top/bottom positioning would be similar to "float: top" and "float: bottom", if there were such
+	//		CSS.
+	//
+	//		Note that there can only be one client element, but there can be multiple left, right, top,
+	//		or bottom elements.
+	//
+	// example:
+	// |	<style>
+	// |		html, body{ height: 100%; width: 100%; }
+	// |	</style>
+	// |	<div dojoType="dijit.layout.LayoutContainer" style="width: 100%; height: 100%">
+	// |		<div dojoType="dijit.layout.ContentPane" layoutAlign="top">header text</div>
+	// |		<div dojoType="dijit.layout.ContentPane" layoutAlign="left" style="width: 200px;">table of contents</div>
+	// |		<div dojoType="dijit.layout.ContentPane" layoutAlign="client">client area</div>
+	// |	</div>
+	//
+	//		Lays out each child in the natural order the children occur in.
+	//		Basically each child is laid out into the "remaining space", where "remaining space" is initially
+	//		the content area of this widget, but is reduced to a smaller rectangle each time a child is added.
+	// tags:
+	//		deprecated
+
+	baseClass: "dijitLayoutContainer",
+
+	constructor: function(){
+		dojo.deprecated("dijit.layout.LayoutContainer is deprecated", "use BorderContainer instead", 2.0);
+	},
+
+	layout: function(){
+		dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());
+	},
+
+	addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+		this.inherited(arguments);
+		if(this._started){
+			dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());
+		}
+	},
+
+	removeChild: function(/*dijit._Widget*/ widget){
+		this.inherited(arguments);
+		if(this._started){
+			dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());
+		}
+	}
+});
+
+// This argument can be specified for the children of a LayoutContainer.
+// Since any widget can be specified as a LayoutContainer child, mix it
+// into the base widget class.  (This is a hack, but it's effective.)
+dojo.extend(dijit._Widget, {
+	// layoutAlign: String
+	//		"none", "left", "right", "bottom", "top", and "client".
+	//		See the LayoutContainer description for details on this parameter.
+	layoutAlign: 'none'
+});
diff --git a/dijit/layout/LinkPane.js b/dijit/layout/LinkPane.js
index 855f283..b5c4634 100644
--- a/dijit/layout/LinkPane.js
+++ b/dijit/layout/LinkPane.js
@@ -1,20 +1,40 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout.LinkPane"]){
-dojo._hasResource["dijit.layout.LinkPane"]=true;
 dojo.provide("dijit.layout.LinkPane");
+
 dojo.require("dijit.layout.ContentPane");
 dojo.require("dijit._Templated");
-dojo.declare("dijit.layout.LinkPane",[dijit.layout.ContentPane,dijit._Templated],{templateString:"<div class=\"dijitLinkPane\" dojoAttachPoint=\"containerNode\"></div>",postMixInProperties:function(){
-if(this.srcNodeRef){
-this.title+=this.srcNodeRef.innerHTML;
-}
-this.inherited(arguments);
-},_fillContent:function(_1){
-}});
-}
+
+dojo.declare("dijit.layout.LinkPane",
+	[dijit.layout.ContentPane, dijit._Templated],
+	{
+	// summary:
+	//		A ContentPane with an href where (when declared in markup)
+	//		the title is specified as innerHTML rather than as a title attribute.
+	// description:
+	//		LinkPane is just a ContentPane that is declared in markup similarly
+	//		to an anchor.  The anchor's body (the words between `<a>` and `</a>`)
+	//		become the title of the widget (used for TabContainer, AccordionContainer, etc.)
+	// example:
+	//	| <a href="foo.html">my title</a>
+
+	// I'm using a template because the user may specify the input as
+	// <a href="foo.html">title</a>, in which case we need to get rid of the
+	// <a> because we don't want a link.
+	templateString: '<div class="dijitLinkPane" dojoAttachPoint="containerNode"></div>',
+
+	postMixInProperties: function(){
+		// If user has specified node contents, they become the title
+		// (the link must be plain text)
+		if(this.srcNodeRef){
+			this.title += this.srcNodeRef.innerHTML;
+		}
+		this.inherited(arguments);
+	},
+
+	_fillContent: function(/*DomNode*/ source){
+		// Overrides _Templated._fillContent().
+
+		// _Templated._fillContent() relocates srcNodeRef innerHTML to templated container node,
+		// but in our case the srcNodeRef innerHTML is the title, so shouldn't be
+		// copied
+	}
+});
diff --git a/dijit/layout/ScrollingTabController.js b/dijit/layout/ScrollingTabController.js
index 4d146c5..b7ab54e 100644
--- a/dijit/layout/ScrollingTabController.js
+++ b/dijit/layout/ScrollingTabController.js
@@ -1,195 +1,457 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout.ScrollingTabController"]){
-dojo._hasResource["dijit.layout.ScrollingTabController"]=true;
 dojo.provide("dijit.layout.ScrollingTabController");
+
 dojo.require("dijit.layout.TabController");
 dojo.require("dijit.Menu");
-dojo.declare("dijit.layout.ScrollingTabController",dijit.layout.TabController,{templateString:dojo.cache("dijit.layout","templates/ScrollingTabController.html","<div class=\"dijitTabListContainer-${tabPosition}\" style=\"visibility:hidden\">\n\t<div dojoType=\"dijit.layout._ScrollingTabControllerButton\" buttonType=\"menuBtn\" buttonClass=\"tabStripMenuButton\"\n\t\t\ttabPosition=\"${tabPosition}\" dojoAttachPoint=\"_menuBtn\" showLabel=false>↓</div>\n\t<div dojoType=\"dijit.layout. [...]
-this.inherited(arguments);
-var n=this.domNode;
-this.scrollNode=this.tablistWrapper;
-this._initButtons();
-if(!this.tabStripClass){
-this.tabStripClass="dijitTabContainer"+this.tabPosition.charAt(0).toUpperCase()+this.tabPosition.substr(1).replace(/-.*/,"")+"None";
-dojo.addClass(n,"tabStrip-disabled");
-}
-dojo.addClass(this.tablistWrapper,this.tabStripClass);
-},onStartup:function(){
-this.inherited(arguments);
-dojo.style(this.domNode,"visibility","visible");
-this._postStartup=true;
-},onAddChild:function(_1,_2){
-this.inherited(arguments);
-var _3;
-if(this.useMenu){
-var _4=this.containerId;
-_3=new dijit.MenuItem({label:_1.title,onClick:dojo.hitch(this,function(){
-var _5=dijit.byId(_4);
-_5.selectChild(_1);
-})});
-this._menuChildren[_1.id]=_3;
-this._menu.addChild(_3,_2);
-}
-this.pane2handles[_1.id].push(this.connect(this.pane2button[_1.id],"attr",function(_6,_7){
-if(this._postStartup){
-if(arguments.length==2&&_6=="label"){
-if(_3){
-_3.attr(_6,_7);
-}
-if(this._dim){
-this.resize(this._dim);
-}
-}
-}
-}));
-dojo.style(this.containerNode,"width",(dojo.style(this.containerNode,"width")+200)+"px");
-},onRemoveChild:function(_8,_9){
-var _a=this.pane2button[_8.id];
-if(this._selectedTab===_a.domNode){
-this._selectedTab=null;
-}
-if(this.useMenu&&_8&&_8.id&&this._menuChildren[_8.id]){
-this._menu.removeChild(this._menuChildren[_8.id]);
-this._menuChildren[_8.id].destroy();
-delete this._menuChildren[_8.id];
-}
-this.inherited(arguments);
-},_initButtons:function(){
-this._menuChildren={};
-this._btnWidth=0;
-this._buttons=dojo.query("> .tabStripButton",this.domNode).filter(function(_b){
-if((this.useMenu&&_b==this._menuBtn.domNode)||(this.useSlider&&(_b==this._rightBtn.domNode||_b==this._leftBtn.domNode))){
-this._btnWidth+=dojo.marginBox(_b).w;
-return true;
-}else{
-dojo.style(_b,"display","none");
-return false;
-}
-},this);
-if(this.useMenu){
-this._menu=new dijit.Menu({id:this.id+"_menu",targetNodeIds:[this._menuBtn.domNode],leftClickToOpen:true,refocus:false});
-this._supportingWidgets.push(this._menu);
-}
-},_getTabsWidth:function(){
-var _c=this.getChildren();
-if(_c.length){
-var _d=_c[this.isLeftToRight()?0:_c.length-1].domNode,_e=_c[this.isLeftToRight()?_c.length-1:0].domNode;
-return _e.offsetLeft+dojo.style(_e,"width")-_d.offsetLeft;
-}else{
-return 0;
-}
-},_enableBtn:function(_f){
-var _10=this._getTabsWidth();
-_f=_f||dojo.style(this.scrollNode,"width");
-return _10>0&&_f<_10;
-},resize:function(dim){
-if(this.domNode.offsetWidth==0){
-return;
-}
-this._dim=dim;
-this.scrollNode.style.height="auto";
-this._contentBox=dijit.layout.marginBox2contentBox(this.domNode,{h:0,w:dim.w});
-this._contentBox.h=this.scrollNode.offsetHeight;
-dojo.contentBox(this.domNode,this._contentBox);
-var _11=this._enableBtn(this._contentBox.w);
-this._buttons.style("display",_11?"":"none");
-this._leftBtn.layoutAlign="left";
-this._rightBtn.layoutAlign="right";
-this._menuBtn.layoutAlign=this.isLeftToRight()?"right":"left";
-dijit.layout.layoutChildren(this.domNode,this._contentBox,[this._menuBtn,this._leftBtn,this._rightBtn,{domNode:this.scrollNode,layoutAlign:"client"}]);
-if(this._selectedTab){
-var w=this.scrollNode,sl=this._convertToScrollLeft(this._getScrollForSelectedTab());
-w.scrollLeft=sl;
-}
-this._setButtonClass(this._getScroll());
-},_getScroll:function(){
-var sl=(this.isLeftToRight()||dojo.isIE<8||dojo.isQuirks||dojo.isWebKit)?this.scrollNode.scrollLeft:dojo.style(this.containerNode,"width")-dojo.style(this.scrollNode,"width")+(dojo.isIE==8?-1:1)*this.scrollNode.scrollLeft;
-return sl;
-},_convertToScrollLeft:function(val){
-if(this.isLeftToRight()||dojo.isIE<8||dojo.isQuirks||dojo.isWebKit){
-return val;
-}else{
-var _12=dojo.style(this.containerNode,"width")-dojo.style(this.scrollNode,"width");
-return (dojo.isIE==8?-1:1)*(val-_12);
-}
-},onSelectChild:function(_13){
-var tab=this.pane2button[_13.id];
-if(!tab||!_13){
-return;
-}
-var _14=tab.domNode;
-if(_14!=this._selectedTab){
-this._selectedTab=_14;
-var sl=this._getScroll();
-if(sl>_14.offsetLeft||sl+dojo.style(this.scrollNode,"width")<_14.offsetLeft+dojo.style(_14,"width")){
-this.createSmoothScroll().play();
-}
-}
-this.inherited(arguments);
-},_getScrollBounds:function(){
-var _15=this.getChildren(),_16=dojo.style(this.scrollNode,"width"),_17=dojo.style(this.containerNode,"width"),_18=_17-_16,_19=this._getTabsWidth();
-if(_15.length&&_19>_16){
-return {min:this.isLeftToRight()?0:_15[_15.length-1].domNode.offsetLeft,max:this.isLeftToRight()?(_15[_15.length-1].domNode.offsetLeft+dojo.style(_15[_15.length-1].domNode,"width"))-_16:_18};
-}else{
-var _1a=this.isLeftToRight()?0:_18;
-return {min:_1a,max:_1a};
-}
-},_getScrollForSelectedTab:function(){
-var w=this.scrollNode,n=this._selectedTab,_1b=dojo.style(this.scrollNode,"width"),_1c=this._getScrollBounds();
-var pos=(n.offsetLeft+dojo.style(n,"width")/2)-_1b/2;
-pos=Math.min(Math.max(pos,_1c.min),_1c.max);
-return pos;
-},createSmoothScroll:function(x){
-if(arguments.length>0){
-var _1d=this._getScrollBounds();
-x=Math.min(Math.max(x,_1d.min),_1d.max);
-}else{
-x=this._getScrollForSelectedTab();
-}
-if(this._anim&&this._anim.status()=="playing"){
-this._anim.stop();
-}
-var _1e=this,w=this.scrollNode,_1f=new dojo._Animation({beforeBegin:function(){
-if(this.curve){
-delete this.curve;
-}
-var _20=w.scrollLeft,_21=_1e._convertToScrollLeft(x);
-_1f.curve=new dojo._Line(_20,_21);
-},onAnimate:function(val){
-w.scrollLeft=val;
-}});
-this._anim=_1f;
-this._setButtonClass(x);
-return _1f;
-},_getBtnNode:function(e){
-var n=e.target;
-while(n&&!dojo.hasClass(n,"tabStripButton")){
-n=n.parentNode;
-}
-return n;
-},doSlideRight:function(e){
-this.doSlide(1,this._getBtnNode(e));
-},doSlideLeft:function(e){
-this.doSlide(-1,this._getBtnNode(e));
-},doSlide:function(_22,_23){
-if(_23&&dojo.hasClass(_23,"dijitTabBtnDisabled")){
-return;
-}
-var _24=dojo.style(this.scrollNode,"width");
-var d=(_24*0.75)*_22;
-var to=this._getScroll()+d;
-this._setButtonClass(to);
-this.createSmoothScroll(to).play();
-},_setButtonClass:function(_25){
-var cls="dijitTabBtnDisabled",_26=this._getScrollBounds();
-dojo.toggleClass(this._leftBtn.domNode,cls,_25<=_26.min);
-dojo.toggleClass(this._rightBtn.domNode,cls,_25>=_26.max);
-}});
-dojo.declare("dijit.layout._ScrollingTabControllerButton",dijit.form.Button,{baseClass:"dijitTab",buttonType:"",buttonClass:"",tabPosition:"top",templateString:dojo.cache("dijit.layout","templates/_ScrollingTabControllerButton.html","<div id=\"${id}-${buttonType}\" class=\"tabStripButton dijitTab ${buttonClass} tabStripButton-${tabPosition}\"\n\t\tdojoAttachEvent=\"onclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\">\n\t<div role=\"presentation\" wai [...]
-}
+
+dojo.declare("dijit.layout.ScrollingTabController",
+	dijit.layout.TabController,
+	{
+	// summary:
+	//		Set of tabs with left/right arrow keys and a menu to switch between tabs not
+	//		all fitting on a single row.
+	//		Works only for horizontal tabs (either above or below the content, not to the left
+	//		or right).
+	// tags:
+	//		private
+
+	templateString: dojo.cache("dijit.layout", "templates/ScrollingTabController.html"),
+
+	// useMenu:[const] Boolean
+	//		True if a menu should be used to select tabs when they are too
+	//		wide to fit the TabContainer, false otherwise.
+	useMenu: true,
+
+	// useSlider: [const] Boolean
+	//		True if a slider should be used to select tabs when they are too
+	//		wide to fit the TabContainer, false otherwise.
+	useSlider: true,
+
+	// tabStripClass: String
+	//		The css class to apply to the tab strip, if it is visible.
+	tabStripClass: "",
+
+	widgetsInTemplate: true,
+
+	// _minScroll: Number
+	//		The distance in pixels from the edge of the tab strip which,
+	//		if a scroll animation is less than, forces the scroll to
+	//		go all the way to the left/right.
+	_minScroll: 5,
+
+	attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+		"class": "containerNode"
+	}),
+
+	postCreate: function(){
+		this.inherited(arguments);
+		var n = this.domNode;
+
+		this.scrollNode = this.tablistWrapper;
+		this._initButtons();
+
+		if(!this.tabStripClass){
+			this.tabStripClass = "dijitTabContainer" +
+				this.tabPosition.charAt(0).toUpperCase() +
+				this.tabPosition.substr(1).replace(/-.*/, "") +
+				"None";
+			dojo.addClass(n, "tabStrip-disabled")
+		}
+
+		dojo.addClass(this.tablistWrapper, this.tabStripClass);
+	},
+
+	onStartup: function(){
+		this.inherited(arguments);
+
+		// Do not show the TabController until the related
+		// StackController has added it's children.  This gives
+		// a less visually jumpy instantiation.
+		dojo.style(this.domNode, "visibility", "visible");
+		this._postStartup = true;
+	},
+
+	onAddChild: function(page, insertIndex){
+		this.inherited(arguments);
+		var menuItem;
+		if(this.useMenu){
+			var containerId = this.containerId;
+			menuItem = new dijit.MenuItem({
+				id: page.id + "_stcMi",
+				label: page.title,
+				dir: page.dir,
+				lang: page.lang,
+				onClick: dojo.hitch(this, function(){
+					var container = dijit.byId(containerId);
+					container.selectChild(page);
+				})
+			});
+			this._menuChildren[page.id] = menuItem;
+			this._menu.addChild(menuItem, insertIndex);
+		}
+
+		// update the menuItem label when the button label is updated
+		this.pane2handles[page.id].push(
+			this.connect(this.pane2button[page.id], "set", function(name, value){
+				if(this._postStartup){
+					if(name == "label"){
+						if(menuItem){
+							menuItem.set(name, value);
+						}
+	
+						// The changed label will have changed the width of the
+						// buttons, so do a resize
+						if(this._dim){
+							this.resize(this._dim);
+						}
+					}
+				}
+			})
+		);
+
+		// Increment the width of the wrapper when a tab is added
+		// This makes sure that the buttons never wrap.
+		// The value 200 is chosen as it should be bigger than most
+		// Tab button widths.
+		dojo.style(this.containerNode, "width",
+			(dojo.style(this.containerNode, "width") + 200) + "px");
+	},
+
+	onRemoveChild: function(page, insertIndex){
+		// null out _selectedTab because we are about to delete that dom node
+		var button = this.pane2button[page.id];
+		if(this._selectedTab === button.domNode){
+			this._selectedTab = null;
+		}
+
+		// delete menu entry corresponding to pane that was removed from TabContainer
+		if(this.useMenu && page && page.id && this._menuChildren[page.id]){
+			this._menu.removeChild(this._menuChildren[page.id]);
+			this._menuChildren[page.id].destroy();
+			delete this._menuChildren[page.id];
+		}
+
+		this.inherited(arguments);
+	},
+
+	_initButtons: function(){
+		// summary:
+		//		Creates the buttons used to scroll to view tabs that
+		//		may not be visible if the TabContainer is too narrow.
+		this._menuChildren = {};
+
+		// Make a list of the buttons to display when the tab labels become
+		// wider than the TabContainer, and hide the other buttons.
+		// Also gets the total width of the displayed buttons.
+		this._btnWidth = 0;
+		this._buttons = dojo.query("> .tabStripButton", this.domNode).filter(function(btn){
+			if((this.useMenu && btn == this._menuBtn.domNode) ||
+				(this.useSlider && (btn == this._rightBtn.domNode || btn == this._leftBtn.domNode))){
+				this._btnWidth += dojo.marginBox(btn).w;
+				return true;
+			}else{
+				dojo.style(btn, "display", "none");
+				return false;
+			}
+		}, this);
+
+		if(this.useMenu){
+			// Create the menu that is used to select tabs.
+			this._menu = new dijit.Menu({
+				id: this.id + "_menu",
+				dir: this.dir,
+				lang: this.lang,
+				targetNodeIds: [this._menuBtn.domNode],
+				leftClickToOpen: true,
+				refocus: false	// selecting a menu item sets focus to a TabButton
+			});
+			this._supportingWidgets.push(this._menu);
+		}
+	},
+
+	_getTabsWidth: function(){
+		var children = this.getChildren();
+		if(children.length){
+			var leftTab = children[this.isLeftToRight() ? 0 : children.length - 1].domNode,
+				rightTab = children[this.isLeftToRight() ? children.length - 1 : 0].domNode;
+			return rightTab.offsetLeft + dojo.style(rightTab, "width") - leftTab.offsetLeft;
+		}else{
+			return 0;
+		}
+	},
+
+	_enableBtn: function(width){
+		// summary:
+		//		Determines if the tabs are wider than the width of the TabContainer, and
+		//		thus that we need to display left/right/menu navigation buttons.
+		var tabsWidth = this._getTabsWidth();
+		width = width || dojo.style(this.scrollNode, "width");
+		return tabsWidth > 0 && width < tabsWidth;
+	},
+
+	resize: function(dim){
+		// summary:
+		//		Hides or displays the buttons used to scroll the tab list and launch the menu
+		//		that selects tabs.
+
+		if(this.domNode.offsetWidth == 0){
+			return;
+		}
+
+		// Save the dimensions to be used when a child is renamed.
+		this._dim = dim;
+
+		// Set my height to be my natural height (tall enough for one row of tab labels),
+		// and my content-box width based on margin-box width specified in dim parameter.
+		// But first reset scrollNode.height in case it was set by layoutChildren() call
+		// in a previous run of this method.
+		this.scrollNode.style.height = "auto";
+		this._contentBox = dijit.layout.marginBox2contentBox(this.domNode, {h: 0, w: dim.w});
+		this._contentBox.h = this.scrollNode.offsetHeight;
+		dojo.contentBox(this.domNode, this._contentBox);
+
+		// Show/hide the left/right/menu navigation buttons depending on whether or not they
+		// are needed.
+		var enable = this._enableBtn(this._contentBox.w);
+		this._buttons.style("display", enable ? "" : "none");
+
+		// Position and size the navigation buttons and the tablist
+		this._leftBtn.layoutAlign = "left";
+		this._rightBtn.layoutAlign = "right";
+		this._menuBtn.layoutAlign = this.isLeftToRight() ? "right" : "left";
+		dijit.layout.layoutChildren(this.domNode, this._contentBox,
+			[this._menuBtn, this._leftBtn, this._rightBtn, {domNode: this.scrollNode, layoutAlign: "client"}]);
+
+		// set proper scroll so that selected tab is visible
+		if(this._selectedTab){
+			if(this._anim && this._anim.status() == "playing"){
+				this._anim.stop();
+			}
+			var w = this.scrollNode,
+				sl = this._convertToScrollLeft(this._getScrollForSelectedTab());
+			w.scrollLeft = sl;
+		}
+
+		// Enable/disabled left right buttons depending on whether or not user can scroll to left or right
+		this._setButtonClass(this._getScroll());
+		
+		this._postResize = true;
+	},
+
+	_getScroll: function(){
+		// summary:
+		//		Returns the current scroll of the tabs where 0 means
+		//		"scrolled all the way to the left" and some positive number, based on #
+		//		of pixels of possible scroll (ex: 1000) means "scrolled all the way to the right"
+		var sl = (this.isLeftToRight() || dojo.isIE < 8 || (dojo.isIE && dojo.isQuirks) || dojo.isWebKit) ? this.scrollNode.scrollLeft :
+				dojo.style(this.containerNode, "width") - dojo.style(this.scrollNode, "width")
+					 + (dojo.isIE == 8 ? -1 : 1) * this.scrollNode.scrollLeft;
+		return sl;
+	},
+
+	_convertToScrollLeft: function(val){
+		// summary:
+		//		Given a scroll value where 0 means "scrolled all the way to the left"
+		//		and some positive number, based on # of pixels of possible scroll (ex: 1000)
+		//		means "scrolled all the way to the right", return value to set this.scrollNode.scrollLeft
+		//		to achieve that scroll.
+		//
+		//		This method is to adjust for RTL funniness in various browsers and versions.
+		if(this.isLeftToRight() || dojo.isIE < 8 || (dojo.isIE && dojo.isQuirks) || dojo.isWebKit){
+			return val;
+		}else{
+			var maxScroll = dojo.style(this.containerNode, "width") - dojo.style(this.scrollNode, "width");
+			return (dojo.isIE == 8 ? -1 : 1) * (val - maxScroll);
+		}
+	},
+
+	onSelectChild: function(/*dijit._Widget*/ page){
+		// summary:
+		//		Smoothly scrolls to a tab when it is selected.
+
+		var tab = this.pane2button[page.id];
+		if(!tab || !page){return;}
+
+		// Scroll to the selected tab, except on startup, when scrolling is handled in resize()
+		var node = tab.domNode;
+		if(this._postResize && node != this._selectedTab){
+			this._selectedTab = node;
+
+			var sl = this._getScroll();
+
+			if(sl > node.offsetLeft ||
+					sl + dojo.style(this.scrollNode, "width") <
+					node.offsetLeft + dojo.style(node, "width")){
+				this.createSmoothScroll().play();
+			}
+		}
+
+		this.inherited(arguments);
+	},
+
+	_getScrollBounds: function(){
+		// summary:
+		//		Returns the minimum and maximum scroll setting to show the leftmost and rightmost
+		//		tabs (respectively)
+		var children = this.getChildren(),
+			scrollNodeWidth = dojo.style(this.scrollNode, "width"),		// about 500px
+			containerWidth = dojo.style(this.containerNode, "width"),	// 50,000px
+			maxPossibleScroll = containerWidth - scrollNodeWidth,	// scrolling until right edge of containerNode visible
+			tabsWidth = this._getTabsWidth();
+
+		if(children.length && tabsWidth > scrollNodeWidth){
+			// Scrolling should happen
+			return {
+				min: this.isLeftToRight() ? 0 : children[children.length-1].domNode.offsetLeft,
+				max: this.isLeftToRight() ?
+					(children[children.length-1].domNode.offsetLeft + dojo.style(children[children.length-1].domNode, "width")) - scrollNodeWidth :
+					maxPossibleScroll
+			};
+		}else{
+			// No scrolling needed, all tabs visible, we stay either scrolled to far left or far right (depending on dir)
+			var onlyScrollPosition = this.isLeftToRight() ? 0 : maxPossibleScroll;
+			return {
+				min: onlyScrollPosition,
+				max: onlyScrollPosition
+			};
+		}
+	},
+
+	_getScrollForSelectedTab: function(){
+		// summary:
+		//		Returns the scroll value setting so that the selected tab
+		//		will appear in the center
+		var w = this.scrollNode,
+			n = this._selectedTab,
+			scrollNodeWidth = dojo.style(this.scrollNode, "width"),
+			scrollBounds = this._getScrollBounds();
+
+		// TODO: scroll minimal amount (to either right or left) so that
+		// selected tab is fully visible, and just return if it's already visible?
+		var pos = (n.offsetLeft + dojo.style(n, "width")/2) - scrollNodeWidth/2;
+		pos = Math.min(Math.max(pos, scrollBounds.min), scrollBounds.max);
+
+		// TODO:
+		// If scrolling close to the left side or right side, scroll
+		// all the way to the left or right.  See this._minScroll.
+		// (But need to make sure that doesn't scroll the tab out of view...)
+		return pos;
+	},
+
+	createSmoothScroll : function(x){
+		// summary:
+		//		Creates a dojo._Animation object that smoothly scrolls the tab list
+		//		either to a fixed horizontal pixel value, or to the selected tab.
+		// description:
+		//		If an number argument is passed to the function, that horizontal
+		//		pixel position is scrolled to.  Otherwise the currently selected
+		//		tab is scrolled to.
+		// x: Integer?
+		//		An optional pixel value to scroll to, indicating distance from left.
+
+		// Calculate position to scroll to
+		if(arguments.length > 0){
+			// position specified by caller, just make sure it's within bounds
+			var scrollBounds = this._getScrollBounds();
+			x = Math.min(Math.max(x, scrollBounds.min), scrollBounds.max);
+		}else{
+			// scroll to center the current tab
+			x = this._getScrollForSelectedTab();
+		}
+
+		if(this._anim && this._anim.status() == "playing"){
+			this._anim.stop();
+		}
+
+		var self = this,
+			w = this.scrollNode,
+			anim = new dojo._Animation({
+				beforeBegin: function(){
+					if(this.curve){ delete this.curve; }
+					var oldS = w.scrollLeft,
+						newS = self._convertToScrollLeft(x);
+					anim.curve = new dojo._Line(oldS, newS);
+				},
+				onAnimate: function(val){
+					w.scrollLeft = val;
+				}
+			});
+		this._anim = anim;
+
+		// Disable/enable left/right buttons according to new scroll position
+		this._setButtonClass(x);
+
+		return anim; // dojo._Animation
+	},
+
+	_getBtnNode: function(e){
+		// summary:
+		//		Gets a button DOM node from a mouse click event.
+		// e:
+		//		The mouse click event.
+		var n = e.target;
+		while(n && !dojo.hasClass(n, "tabStripButton")){
+			n = n.parentNode;
+		}
+		return n;
+	},
+
+	doSlideRight: function(e){
+		// summary:
+		//		Scrolls the menu to the right.
+		// e:
+		//		The mouse click event.
+		this.doSlide(1, this._getBtnNode(e));
+	},
+
+	doSlideLeft: function(e){
+		// summary:
+		//		Scrolls the menu to the left.
+		// e:
+		//		The mouse click event.
+		this.doSlide(-1,this._getBtnNode(e));
+	},
+
+	doSlide: function(direction, node){
+		// summary:
+		//		Scrolls the tab list to the left or right by 75% of the widget width.
+		// direction:
+		//		If the direction is 1, the widget scrolls to the right, if it is
+		//		-1, it scrolls to the left.
+
+		if(node && dojo.hasClass(node, "dijitTabDisabled")){return;}
+
+		var sWidth = dojo.style(this.scrollNode, "width");
+		var d = (sWidth * 0.75) * direction;
+
+		var to = this._getScroll() + d;
+
+		this._setButtonClass(to);
+
+		this.createSmoothScroll(to).play();
+	},
+
+	_setButtonClass: function(scroll){
+		// summary:
+		//		Disables the left scroll button if the tabs are scrolled all the way to the left,
+		//		or the right scroll button in the opposite case.
+		// scroll: Integer
+		//		amount of horizontal scroll
+
+		var scrollBounds = this._getScrollBounds();
+		this._leftBtn.set("disabled", scroll <= scrollBounds.min);
+		this._rightBtn.set("disabled", scroll >= scrollBounds.max);
+	}
+});
+
+dojo.declare("dijit.layout._ScrollingTabControllerButton",
+	dijit.form.Button,
+	{
+		baseClass: "dijitTab tabStripButton",
+
+		templateString: dojo.cache("dijit.layout","templates/_ScrollingTabControllerButton.html"),
+
+		// Override inherited tabIndex: 0 from dijit.form.Button, because user shouldn't be
+		// able to tab to the left/right/menu buttons
+		tabIndex: "-1"
+	}
+);
diff --git a/dijit/layout/SplitContainer.js b/dijit/layout/SplitContainer.js
index 4fa6aee..4641eda 100644
--- a/dijit/layout/SplitContainer.js
+++ b/dijit/layout/SplitContainer.js
@@ -1,349 +1,577 @@
-/*
-	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
-*/
+dojo.provide("dijit.layout.SplitContainer");
 
+//
+// FIXME: make it prettier
+// FIXME: active dragging upwards doesn't always shift other bars (direction calculation is wrong in this case)
+//
 
-if(!dojo._hasResource["dijit.layout.SplitContainer"]){
-dojo._hasResource["dijit.layout.SplitContainer"]=true;
-dojo.provide("dijit.layout.SplitContainer");
 dojo.require("dojo.cookie");
 dojo.require("dijit.layout._LayoutWidget");
-dojo.declare("dijit.layout.SplitContainer",dijit.layout._LayoutWidget,{constructor:function(){
-dojo.deprecated("dijit.layout.SplitContainer is deprecated","use BorderContainer with splitter instead",2);
-},activeSizing:false,sizerWidth:7,orientation:"horizontal",persist:true,baseClass:"dijitSplitContainer",postMixInProperties:function(){
-this.inherited("postMixInProperties",arguments);
-this.isHorizontal=(this.orientation=="horizontal");
-},postCreate:function(){
-this.inherited(arguments);
-this.sizers=[];
-if(dojo.isMozilla){
-this.domNode.style.overflow="-moz-scrollbars-none";
-}
-if(typeof this.sizerWidth=="object"){
-try{
-this.sizerWidth=parseInt(this.sizerWidth.toString());
-}
-catch(e){
-this.sizerWidth=7;
-}
-}
-var _1=dojo.doc.createElement("div");
-this.virtualSizer=_1;
-_1.style.position="relative";
-_1.style.zIndex=10;
-_1.className=this.isHorizontal?"dijitSplitContainerVirtualSizerH":"dijitSplitContainerVirtualSizerV";
-this.domNode.appendChild(_1);
-dojo.setSelectable(_1,false);
-},destroy:function(){
-delete this.virtualSizer;
-dojo.forEach(this._ownconnects,dojo.disconnect);
-this.inherited(arguments);
-},startup:function(){
-if(this._started){
-return;
-}
-dojo.forEach(this.getChildren(),function(_2,i,_3){
-this._setupChild(_2);
-if(i<_3.length-1){
-this._addSizer();
-}
-},this);
-if(this.persist){
-this._restoreState();
-}
-this.inherited(arguments);
-},_setupChild:function(_4){
-this.inherited(arguments);
-_4.domNode.style.position="absolute";
-dojo.addClass(_4.domNode,"dijitSplitPane");
-},_onSizerMouseDown:function(e){
-if(e.target.id){
-for(var i=0;i<this.sizers.length;i++){
-if(this.sizers[i].id==e.target.id){
-break;
-}
-}
-if(i<this.sizers.length){
-this.beginSizing(e,i);
-}
-}
-},_addSizer:function(_5){
-_5=_5===undefined?this.sizers.length:_5;
-var _6=dojo.doc.createElement("div");
-_6.id=dijit.getUniqueId("dijit_layout_SplitterContainer_Splitter");
-this.sizers.splice(_5,0,_6);
-this.domNode.appendChild(_6);
-_6.className=this.isHorizontal?"dijitSplitContainerSizerH":"dijitSplitContainerSizerV";
-var _7=dojo.doc.createElement("div");
-_7.className="thumb";
-_7.id=_6.id;
-_6.appendChild(_7);
-this.connect(_6,"onmousedown","_onSizerMouseDown");
-dojo.setSelectable(_6,false);
-},removeChild:function(_8){
-if(this.sizers.length){
-var i=dojo.indexOf(this.getChildren(),_8);
-if(i!=-1){
-if(i==this.sizers.length){
-i--;
-}
-dojo.destroy(this.sizers[i]);
-this.sizers.splice(i,1);
-}
-}
-this.inherited(arguments);
-if(this._started){
-this.layout();
-}
-},addChild:function(_9,_a){
-this.inherited(arguments);
-if(this._started){
-var _b=this.getChildren();
-if(_b.length>1){
-this._addSizer(_a);
-}
-this.layout();
-}
-},layout:function(){
-this.paneWidth=this._contentBox.w;
-this.paneHeight=this._contentBox.h;
-var _c=this.getChildren();
-if(!_c.length){
-return;
-}
-var _d=this.isHorizontal?this.paneWidth:this.paneHeight;
-if(_c.length>1){
-_d-=this.sizerWidth*(_c.length-1);
-}
-var _e=0;
-dojo.forEach(_c,function(_f){
-_e+=_f.sizeShare;
-});
-var _10=_d/_e;
-var _11=0;
-dojo.forEach(_c.slice(0,_c.length-1),function(_12){
-var _13=Math.round(_10*_12.sizeShare);
-_12.sizeActual=_13;
-_11+=_13;
-});
-_c[_c.length-1].sizeActual=_d-_11;
-this._checkSizes();
-var pos=0;
-var _14=_c[0].sizeActual;
-this._movePanel(_c[0],pos,_14);
-_c[0].position=pos;
-pos+=_14;
-if(!this.sizers){
-return;
-}
-dojo.some(_c.slice(1),function(_15,i){
-if(!this.sizers[i]){
-return true;
-}
-this._moveSlider(this.sizers[i],pos,this.sizerWidth);
-this.sizers[i].position=pos;
-pos+=this.sizerWidth;
-_14=_15.sizeActual;
-this._movePanel(_15,pos,_14);
-_15.position=pos;
-pos+=_14;
-},this);
-},_movePanel:function(_16,pos,_17){
-if(this.isHorizontal){
-_16.domNode.style.left=pos+"px";
-_16.domNode.style.top=0;
-var box={w:_17,h:this.paneHeight};
-if(_16.resize){
-_16.resize(box);
-}else{
-dojo.marginBox(_16.domNode,box);
-}
-}else{
-_16.domNode.style.left=0;
-_16.domNode.style.top=pos+"px";
-var box={w:this.paneWidth,h:_17};
-if(_16.resize){
-_16.resize(box);
-}else{
-dojo.marginBox(_16.domNode,box);
-}
-}
-},_moveSlider:function(_18,pos,_19){
-if(this.isHorizontal){
-_18.style.left=pos+"px";
-_18.style.top=0;
-dojo.marginBox(_18,{w:_19,h:this.paneHeight});
-}else{
-_18.style.left=0;
-_18.style.top=pos+"px";
-dojo.marginBox(_18,{w:this.paneWidth,h:_19});
-}
-},_growPane:function(_1a,_1b){
-if(_1a>0){
-if(_1b.sizeActual>_1b.sizeMin){
-if((_1b.sizeActual-_1b.sizeMin)>_1a){
-_1b.sizeActual=_1b.sizeActual-_1a;
-_1a=0;
-}else{
-_1a-=_1b.sizeActual-_1b.sizeMin;
-_1b.sizeActual=_1b.sizeMin;
-}
-}
-}
-return _1a;
-},_checkSizes:function(){
-var _1c=0;
-var _1d=0;
-var _1e=this.getChildren();
-dojo.forEach(_1e,function(_1f){
-_1d+=_1f.sizeActual;
-_1c+=_1f.sizeMin;
-});
-if(_1c<=_1d){
-var _20=0;
-dojo.forEach(_1e,function(_21){
-if(_21.sizeActual<_21.sizeMin){
-_20+=_21.sizeMin-_21.sizeActual;
-_21.sizeActual=_21.sizeMin;
-}
-});
-if(_20>0){
-var _22=this.isDraggingLeft?_1e.reverse():_1e;
-dojo.forEach(_22,function(_23){
-_20=this._growPane(_20,_23);
-},this);
-}
-}else{
-dojo.forEach(_1e,function(_24){
-_24.sizeActual=Math.round(_1d*(_24.sizeMin/_1c));
+
+dojo.declare("dijit.layout.SplitContainer",
+	dijit.layout._LayoutWidget,
+	{
+	// summary:
+	//		Deprecated.  Use `dijit.layout.BorderContainer` instead.
+	// description:
+	//		A Container widget with sizing handles in-between each child.
+	//		Contains multiple children widgets, all of which are displayed side by side
+	//		(either horizontally or vertically); there's a bar between each of the children,
+	//		and you can adjust the relative size of each child by dragging the bars.
+	//
+	//		You must specify a size (width and height) for the SplitContainer.
+	// tags:
+	//		deprecated
+
+	constructor: function(){
+		dojo.deprecated("dijit.layout.SplitContainer is deprecated", "use BorderContainer with splitter instead", 2.0);
+	},
+
+	// activeSizing: Boolean
+	//		If true, the children's size changes as you drag the bar;
+	//		otherwise, the sizes don't change until you drop the bar (by mouse-up)
+	activeSizing: false,
+
+	// sizerWidth: Integer
+	//		Size in pixels of the bar between each child
+	sizerWidth: 7, // FIXME: this should be a CSS attribute (at 7 because css wants it to be 7 until we fix to css)
+
+	// orientation: String
+	//		either 'horizontal' or vertical; indicates whether the children are
+	//		arranged side-by-side or up/down.
+	orientation: 'horizontal',
+
+	// persist: Boolean
+	//		Save splitter positions in a cookie
+	persist: true,
+
+	baseClass: "dijitSplitContainer",
+
+	postMixInProperties: function(){
+		this.inherited("postMixInProperties",arguments);
+		this.isHorizontal = (this.orientation == 'horizontal');
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+		this.sizers = [];
+
+		// overflow has to be explicitly hidden for splitContainers using gekko (trac #1435)
+		// to keep other combined css classes from inadvertantly making the overflow visible
+		if(dojo.isMozilla){
+			this.domNode.style.overflow = '-moz-scrollbars-none'; // hidden doesn't work
+		}
+
+		// create the fake dragger
+		if(typeof this.sizerWidth == "object"){
+			try{ //FIXME: do this without a try/catch
+				this.sizerWidth = parseInt(this.sizerWidth.toString());
+			}catch(e){ this.sizerWidth = 7; }
+		}
+		var sizer = dojo.doc.createElement('div');
+		this.virtualSizer = sizer;
+		sizer.style.position = 'relative';
+
+		// #1681: work around the dreaded 'quirky percentages in IE' layout bug
+		// If the splitcontainer's dimensions are specified in percentages, it
+		// will be resized when the virtualsizer is displayed in _showSizingLine
+		// (typically expanding its bounds unnecessarily). This happens because
+		// we use position: relative for .dijitSplitContainer.
+		// The workaround: instead of changing the display style attribute,
+		// switch to changing the zIndex (bring to front/move to back)
+
+		sizer.style.zIndex = 10;
+		sizer.className = this.isHorizontal ? 'dijitSplitContainerVirtualSizerH' : 'dijitSplitContainerVirtualSizerV';
+		this.domNode.appendChild(sizer);
+		dojo.setSelectable(sizer, false);
+	},
+
+	destroy: function(){
+		delete this.virtualSizer;
+		dojo.forEach(this._ownconnects, dojo.disconnect);
+		this.inherited(arguments);
+	},
+	startup: function(){
+		if(this._started){ return; }
+
+		dojo.forEach(this.getChildren(), function(child, i, children){
+			// attach the children and create the draggers
+			this._setupChild(child);
+
+			if(i < children.length-1){
+				this._addSizer();
+			}
+		}, this);
+
+		if(this.persist){
+			this._restoreState();
+		}
+
+		this.inherited(arguments);
+	},
+
+	_setupChild: function(/*dijit._Widget*/ child){
+		this.inherited(arguments);
+		child.domNode.style.position = "absolute";
+		dojo.addClass(child.domNode, "dijitSplitPane");
+	},
+
+	_onSizerMouseDown: function(e){
+		if(e.target.id){
+			for(var i=0;i<this.sizers.length;i++){
+				if(this.sizers[i].id == e.target.id){
+					break;
+				}
+			}
+			if(i<this.sizers.length){
+				this.beginSizing(e,i);
+			}
+		}
+	},
+	_addSizer: function(index){
+		index = index === undefined ? this.sizers.length : index;
+
+		// TODO: use a template for this!!!
+		var sizer = dojo.doc.createElement('div');
+		sizer.id=dijit.getUniqueId('dijit_layout_SplitterContainer_Splitter');
+		this.sizers.splice(index,0,sizer);
+		this.domNode.appendChild(sizer);
+
+		sizer.className = this.isHorizontal ? 'dijitSplitContainerSizerH' : 'dijitSplitContainerSizerV';
+
+		// add the thumb div
+		var thumb = dojo.doc.createElement('div');
+		thumb.className = 'thumb';
+		sizer.appendChild(thumb);
+
+		// FIXME: are you serious? why aren't we using mover start/stop combo?
+		this.connect(sizer, "onmousedown", '_onSizerMouseDown');
+
+		dojo.setSelectable(sizer, false);
+	},
+
+	removeChild: function(widget){
+		// summary:
+		//		Remove sizer, but only if widget is really our child and
+		// we have at least one sizer to throw away
+		if(this.sizers.length){
+			var i=dojo.indexOf(this.getChildren(), widget)
+			if(i != -1){
+				if(i == this.sizers.length){
+					i--;
+				}
+				dojo.destroy(this.sizers[i]);
+				this.sizers.splice(i,1);
+			}
+		}
+
+		// Remove widget and repaint
+		this.inherited(arguments);
+		if(this._started){
+			this.layout();
+		}
+	},
+
+	addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+		// summary:
+		//		Add a child widget to the container
+		// child:
+		//		a widget to add
+		// insertIndex:
+		//		postion in the "stack" to add the child widget
+
+		this.inherited(arguments);
+
+		if(this._started){
+			// Do the stuff that startup() does for each widget
+			var children = this.getChildren();
+			if(children.length > 1){
+				this._addSizer(insertIndex);
+			}
+
+			// and then reposition (ie, shrink) every pane to make room for the new guy
+			this.layout();
+		}
+	},
+
+	layout: function(){
+		// summary:
+		//		Do layout of panels
+
+		// base class defines this._contentBox on initial creation and also
+		// on resize
+		this.paneWidth = this._contentBox.w;
+		this.paneHeight = this._contentBox.h;
+
+		var children = this.getChildren();
+		if(!children.length){ return; }
+
+		//
+		// calculate space
+		//
+
+		var space = this.isHorizontal ? this.paneWidth : this.paneHeight;
+		if(children.length > 1){
+			space -= this.sizerWidth * (children.length - 1);
+		}
+
+		//
+		// calculate total of SizeShare values
+		//
+		var outOf = 0;
+		dojo.forEach(children, function(child){
+			outOf += child.sizeShare;
+		});
+
+		//
+		// work out actual pixels per sizeshare unit
+		//
+		var pixPerUnit = space / outOf;
+
+		//
+		// set the SizeActual member of each pane
+		//
+		var totalSize = 0;
+		dojo.forEach(children.slice(0, children.length - 1), function(child){
+			var size = Math.round(pixPerUnit * child.sizeShare);
+			child.sizeActual = size;
+			totalSize += size;
+		});
+
+		children[children.length-1].sizeActual = space - totalSize;
+
+		//
+		// make sure the sizes are ok
+		//
+		this._checkSizes();
+
+		//
+		// now loop, positioning each pane and letting children resize themselves
+		//
+
+		var pos = 0;
+		var size = children[0].sizeActual;
+		this._movePanel(children[0], pos, size);
+		children[0].position = pos;
+		pos += size;
+
+		// if we don't have any sizers, our layout method hasn't been called yet
+		// so bail until we are called..TODO: REVISIT: need to change the startup
+		// algorithm to guaranteed the ordering of calls to layout method
+		if(!this.sizers){
+			return;
+		}
+
+		dojo.some(children.slice(1), function(child, i){
+			// error-checking
+			if(!this.sizers[i]){
+				return true;
+			}
+			// first we position the sizing handle before this pane
+			this._moveSlider(this.sizers[i], pos, this.sizerWidth);
+			this.sizers[i].position = pos;
+			pos += this.sizerWidth;
+
+			size = child.sizeActual;
+			this._movePanel(child, pos, size);
+			child.position = pos;
+			pos += size;
+		}, this);
+	},
+
+	_movePanel: function(panel, pos, size){
+		if(this.isHorizontal){
+			panel.domNode.style.left = pos + 'px';	// TODO: resize() takes l and t parameters too, don't need to set manually
+			panel.domNode.style.top = 0;
+			var box = {w: size, h: this.paneHeight};
+			if(panel.resize){
+				panel.resize(box);
+			}else{
+				dojo.marginBox(panel.domNode, box);
+			}
+		}else{
+			panel.domNode.style.left = 0;	// TODO: resize() takes l and t parameters too, don't need to set manually
+			panel.domNode.style.top = pos + 'px';
+			var box = {w: this.paneWidth, h: size};
+			if(panel.resize){
+				panel.resize(box);
+			}else{
+				dojo.marginBox(panel.domNode, box);
+			}
+		}
+	},
+
+	_moveSlider: function(slider, pos, size){
+		if(this.isHorizontal){
+			slider.style.left = pos + 'px';
+			slider.style.top = 0;
+			dojo.marginBox(slider, { w: size, h: this.paneHeight });
+		}else{
+			slider.style.left = 0;
+			slider.style.top = pos + 'px';
+			dojo.marginBox(slider, { w: this.paneWidth, h: size });
+		}
+	},
+
+	_growPane: function(growth, pane){
+		if(growth > 0){
+			if(pane.sizeActual > pane.sizeMin){
+				if((pane.sizeActual - pane.sizeMin) > growth){
+
+					// stick all the growth in this pane
+					pane.sizeActual = pane.sizeActual - growth;
+					growth = 0;
+				}else{
+					// put as much growth in here as we can
+					growth -= pane.sizeActual - pane.sizeMin;
+					pane.sizeActual = pane.sizeMin;
+				}
+			}
+		}
+		return growth;
+	},
+
+	_checkSizes: function(){
+
+		var totalMinSize = 0;
+		var totalSize = 0;
+		var children = this.getChildren();
+
+		dojo.forEach(children, function(child){
+			totalSize += child.sizeActual;
+			totalMinSize += child.sizeMin;
+		});
+
+		// only make adjustments if we have enough space for all the minimums
+
+		if(totalMinSize <= totalSize){
+
+			var growth = 0;
+
+			dojo.forEach(children, function(child){
+				if(child.sizeActual < child.sizeMin){
+					growth += child.sizeMin - child.sizeActual;
+					child.sizeActual = child.sizeMin;
+				}
+			});
+
+			if(growth > 0){
+				var list = this.isDraggingLeft ? children.reverse() : children;
+				dojo.forEach(list, function(child){
+					growth = this._growPane(growth, child);
+				}, this);
+			}
+		}else{
+			dojo.forEach(children, function(child){
+				child.sizeActual = Math.round(totalSize * (child.sizeMin / totalMinSize));
+			});
+		}
+	},
+
+	beginSizing: function(e, i){
+		var children = this.getChildren();
+		this.paneBefore = children[i];
+		this.paneAfter = children[i+1];
+
+		this.isSizing = true;
+		this.sizingSplitter = this.sizers[i];
+
+		if(!this.cover){
+			this.cover = dojo.create('div', {
+					style: {
+						position:'absolute',
+						zIndex:5,
+						top: 0,
+						left: 0,
+						width: "100%",
+						height: "100%"
+					}
+				}, this.domNode);
+		}else{
+			this.cover.style.zIndex = 5;
+		}
+		this.sizingSplitter.style.zIndex = 6;
+
+		// TODO: REVISIT - we want MARGIN_BOX and core hasn't exposed that yet (but can't we use it anyway if we pay attention? we do elsewhere.)
+		this.originPos = dojo.position(children[0].domNode, true);
+		if(this.isHorizontal){
+			var client = e.layerX || e.offsetX || 0;
+			var screen = e.pageX;
+			this.originPos = this.originPos.x;
+		}else{
+			var client = e.layerY || e.offsetY || 0;
+			var screen = e.pageY;
+			this.originPos = this.originPos.y;
+		}
+		this.startPoint = this.lastPoint = screen;
+		this.screenToClientOffset = screen - client;
+		this.dragOffset = this.lastPoint - this.paneBefore.sizeActual - this.originPos - this.paneBefore.position;
+
+		if(!this.activeSizing){
+			this._showSizingLine();
+		}
+
+		//
+		// attach mouse events
+		//
+		this._ownconnects = [];
+		this._ownconnects.push(dojo.connect(dojo.doc.documentElement, "onmousemove", this, "changeSizing"));
+		this._ownconnects.push(dojo.connect(dojo.doc.documentElement, "onmouseup", this, "endSizing"));
+
+		dojo.stopEvent(e);
+	},
+
+	changeSizing: function(e){
+		if(!this.isSizing){ return; }
+		this.lastPoint = this.isHorizontal ? e.pageX : e.pageY;
+		this.movePoint();
+		if(this.activeSizing){
+			this._updateSize();
+		}else{
+			this._moveSizingLine();
+		}
+		dojo.stopEvent(e);
+	},
+
+	endSizing: function(e){
+		if(!this.isSizing){ return; }
+		if(this.cover){
+			this.cover.style.zIndex = -1;
+		}
+		if(!this.activeSizing){
+			this._hideSizingLine();
+		}
+
+		this._updateSize();
+
+		this.isSizing = false;
+
+		if(this.persist){
+			this._saveState(this);
+		}
+
+		dojo.forEach(this._ownconnects, dojo.disconnect);
+	},
+
+	movePoint: function(){
+
+		// make sure lastPoint is a legal point to drag to
+		var p = this.lastPoint - this.screenToClientOffset;
+
+		var a = p - this.dragOffset;
+		a = this.legaliseSplitPoint(a);
+		p = a + this.dragOffset;
+
+		this.lastPoint = p + this.screenToClientOffset;
+	},
+
+	legaliseSplitPoint: function(a){
+
+		a += this.sizingSplitter.position;
+
+		this.isDraggingLeft = !!(a > 0);
+
+		if(!this.activeSizing){
+			var min = this.paneBefore.position + this.paneBefore.sizeMin;
+			if(a < min){
+				a = min;
+			}
+
+			var max = this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin));
+			if(a > max){
+				a = max;
+			}
+		}
+
+		a -= this.sizingSplitter.position;
+
+		this._checkSizes();
+
+		return a;
+	},
+
+	_updateSize: function(){
+	//FIXME: sometimes this.lastPoint is NaN
+		var pos = this.lastPoint - this.dragOffset - this.originPos;
+
+		var start_region = this.paneBefore.position;
+		var end_region = this.paneAfter.position + this.paneAfter.sizeActual;
+
+		this.paneBefore.sizeActual = pos - start_region;
+		this.paneAfter.position	= pos + this.sizerWidth;
+		this.paneAfter.sizeActual = end_region - this.paneAfter.position;
+
+		dojo.forEach(this.getChildren(), function(child){
+			child.sizeShare = child.sizeActual;
+		});
+
+		if(this._started){
+			this.layout();
+		}
+	},
+
+	_showSizingLine: function(){
+
+		this._moveSizingLine();
+
+		dojo.marginBox(this.virtualSizer,
+			this.isHorizontal ? { w: this.sizerWidth, h: this.paneHeight } : { w: this.paneWidth, h: this.sizerWidth });
+
+		this.virtualSizer.style.display = 'block';
+	},
+
+	_hideSizingLine: function(){
+		this.virtualSizer.style.display = 'none';
+	},
+
+	_moveSizingLine: function(){
+		var pos = (this.lastPoint - this.startPoint) + this.sizingSplitter.position;
+		dojo.style(this.virtualSizer,(this.isHorizontal ? "left" : "top"),pos+"px");
+		// this.virtualSizer.style[ this.isHorizontal ? "left" : "top" ] = pos + 'px'; // FIXME: remove this line if the previous is better
+	},
+
+	_getCookieName: function(i){
+		return this.id + "_" + i;
+	},
+
+	_restoreState: function(){
+		dojo.forEach(this.getChildren(), function(child, i){
+			var cookieName = this._getCookieName(i);
+			var cookieValue = dojo.cookie(cookieName);
+			if(cookieValue){
+				var pos = parseInt(cookieValue);
+				if(typeof pos == "number"){
+					child.sizeShare = pos;
+				}
+			}
+		}, this);
+	},
+
+	_saveState: function(){
+		if(!this.persist){
+			return;
+		}
+		dojo.forEach(this.getChildren(), function(child, i){
+			dojo.cookie(this._getCookieName(i), child.sizeShare, {expires:365});
+		}, this);
+	}
 });
-}
-},beginSizing:function(e,i){
-var _25=this.getChildren();
-this.paneBefore=_25[i];
-this.paneAfter=_25[i+1];
-this.isSizing=true;
-this.sizingSplitter=this.sizers[i];
-if(!this.cover){
-this.cover=dojo.create("div",{style:{position:"absolute",zIndex:5,top:0,left:0,width:"100%",height:"100%"}},this.domNode);
-}else{
-this.cover.style.zIndex=5;
-}
-this.sizingSplitter.style.zIndex=6;
-this.originPos=dojo.position(_25[0].domNode,true);
-if(this.isHorizontal){
-var _26=e.layerX||e.offsetX||0;
-var _27=e.pageX;
-this.originPos=this.originPos.x;
-}else{
-var _26=e.layerY||e.offsetY||0;
-var _27=e.pageY;
-this.originPos=this.originPos.y;
-}
-this.startPoint=this.lastPoint=_27;
-this.screenToClientOffset=_27-_26;
-this.dragOffset=this.lastPoint-this.paneBefore.sizeActual-this.originPos-this.paneBefore.position;
-if(!this.activeSizing){
-this._showSizingLine();
-}
-this._ownconnects=[];
-this._ownconnects.push(dojo.connect(dojo.doc.documentElement,"onmousemove",this,"changeSizing"));
-this._ownconnects.push(dojo.connect(dojo.doc.documentElement,"onmouseup",this,"endSizing"));
-dojo.stopEvent(e);
-},changeSizing:function(e){
-if(!this.isSizing){
-return;
-}
-this.lastPoint=this.isHorizontal?e.pageX:e.pageY;
-this.movePoint();
-if(this.activeSizing){
-this._updateSize();
-}else{
-this._moveSizingLine();
-}
-dojo.stopEvent(e);
-},endSizing:function(e){
-if(!this.isSizing){
-return;
-}
-if(this.cover){
-this.cover.style.zIndex=-1;
-}
-if(!this.activeSizing){
-this._hideSizingLine();
-}
-this._updateSize();
-this.isSizing=false;
-if(this.persist){
-this._saveState(this);
-}
-dojo.forEach(this._ownconnects,dojo.disconnect);
-},movePoint:function(){
-var p=this.lastPoint-this.screenToClientOffset;
-var a=p-this.dragOffset;
-a=this.legaliseSplitPoint(a);
-p=a+this.dragOffset;
-this.lastPoint=p+this.screenToClientOffset;
-},legaliseSplitPoint:function(a){
-a+=this.sizingSplitter.position;
-this.isDraggingLeft=!!(a>0);
-if(!this.activeSizing){
-var min=this.paneBefore.position+this.paneBefore.sizeMin;
-if(a<min){
-a=min;
-}
-var max=this.paneAfter.position+(this.paneAfter.sizeActual-(this.sizerWidth+this.paneAfter.sizeMin));
-if(a>max){
-a=max;
-}
-}
-a-=this.sizingSplitter.position;
-this._checkSizes();
-return a;
-},_updateSize:function(){
-var pos=this.lastPoint-this.dragOffset-this.originPos;
-var _28=this.paneBefore.position;
-var _29=this.paneAfter.position+this.paneAfter.sizeActual;
-this.paneBefore.sizeActual=pos-_28;
-this.paneAfter.position=pos+this.sizerWidth;
-this.paneAfter.sizeActual=_29-this.paneAfter.position;
-dojo.forEach(this.getChildren(),function(_2a){
-_2a.sizeShare=_2a.sizeActual;
+
+// These arguments can be specified for the children of a SplitContainer.
+// Since any widget can be specified as a SplitContainer child, mix them
+// into the base widget class.  (This is a hack, but it's effective.)
+dojo.extend(dijit._Widget, {
+	// sizeMin: [deprecated] Integer
+	//		Deprecated.  Parameter for children of `dijit.layout.SplitContainer`.
+	//		Minimum size (width or height) of a child of a SplitContainer.
+	//		The value is relative to other children's sizeShare properties.
+	sizeMin: 10,
+
+	// sizeShare: [deprecated] Integer
+	//		Deprecated.  Parameter for children of `dijit.layout.SplitContainer`.
+	//		Size (width or height) of a child of a SplitContainer.
+	//		The value is relative to other children's sizeShare properties.
+	//		For example, if there are two children and each has sizeShare=10, then
+	//		each takes up 50% of the available space.
+	sizeShare: 10
 });
-if(this._started){
-this.layout();
-}
-},_showSizingLine:function(){
-this._moveSizingLine();
-dojo.marginBox(this.virtualSizer,this.isHorizontal?{w:this.sizerWidth,h:this.paneHeight}:{w:this.paneWidth,h:this.sizerWidth});
-this.virtualSizer.style.display="block";
-},_hideSizingLine:function(){
-this.virtualSizer.style.display="none";
-},_moveSizingLine:function(){
-var pos=(this.lastPoint-this.startPoint)+this.sizingSplitter.position;
-dojo.style(this.virtualSizer,(this.isHorizontal?"left":"top"),pos+"px");
-},_getCookieName:function(i){
-return this.id+"_"+i;
-},_restoreState:function(){
-dojo.forEach(this.getChildren(),function(_2b,i){
-var _2c=this._getCookieName(i);
-var _2d=dojo.cookie(_2c);
-if(_2d){
-var pos=parseInt(_2d);
-if(typeof pos=="number"){
-_2b.sizeShare=pos;
-}
-}
-},this);
-},_saveState:function(){
-if(!this.persist){
-return;
-}
-dojo.forEach(this.getChildren(),function(_2e,i){
-dojo.cookie(this._getCookieName(i),_2e.sizeShare,{expires:365});
-},this);
-}});
-dojo.extend(dijit._Widget,{sizeMin:10,sizeShare:10});
-}
diff --git a/dijit/layout/StackContainer.js b/dijit/layout/StackContainer.js
index 8c33481..6c0bb26 100644
--- a/dijit/layout/StackContainer.js
+++ b/dijit/layout/StackContainer.js
@@ -1,150 +1,318 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout.StackContainer"]){
-dojo._hasResource["dijit.layout.StackContainer"]=true;
 dojo.provide("dijit.layout.StackContainer");
+
 dojo.require("dijit._Templated");
 dojo.require("dijit.layout._LayoutWidget");
-dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
+dojo.requireLocalization("dijit", "common");
 dojo.require("dojo.cookie");
-dojo.declare("dijit.layout.StackContainer",dijit.layout._LayoutWidget,{doLayout:true,persist:false,baseClass:"dijitStackContainer",postCreate:function(){
-this.inherited(arguments);
-dojo.addClass(this.domNode,"dijitLayoutContainer");
-dijit.setWaiRole(this.containerNode,"tabpanel");
-this.connect(this.domNode,"onkeypress",this._onKeyPress);
-},startup:function(){
-if(this._started){
-return;
-}
-var _1=this.getChildren();
-dojo.forEach(_1,this._setupChild,this);
-if(this.persist){
-this.selectedChildWidget=dijit.byId(dojo.cookie(this.id+"_selectedChild"));
-}else{
-dojo.some(_1,function(_2){
-if(_2.selected){
-this.selectedChildWidget=_2;
-}
-return _2.selected;
-},this);
-}
-var _3=this.selectedChildWidget;
-if(!_3&&_1[0]){
-_3=this.selectedChildWidget=_1[0];
-_3.selected=true;
-}
-dojo.publish(this.id+"-startup",[{children:_1,selected:_3}]);
-this.inherited(arguments);
-},resize:function(){
-var _4=this.selectedChildWidget;
-if(_4&&!this._hasBeenShown){
-this._hasBeenShown=true;
-this._showChild(_4);
-}
-this.inherited(arguments);
-},_setupChild:function(_5){
-this.inherited(arguments);
-dojo.removeClass(_5.domNode,"dijitVisible");
-dojo.addClass(_5.domNode,"dijitHidden");
-_5.domNode.title="";
-},addChild:function(_6,_7){
-this.inherited(arguments);
-if(this._started){
-dojo.publish(this.id+"-addChild",[_6,_7]);
-this.layout();
-if(!this.selectedChildWidget){
-this.selectChild(_6);
-}
-}
-},removeChild:function(_8){
-this.inherited(arguments);
-if(this._started){
-dojo.publish(this.id+"-removeChild",[_8]);
-}
-if(this._beingDestroyed){
-return;
-}
-if(this._started){
-this.layout();
-}
-if(this.selectedChildWidget===_8){
-this.selectedChildWidget=undefined;
-if(this._started){
-var _9=this.getChildren();
-if(_9.length){
-this.selectChild(_9[0]);
-}
-}
-}
-},selectChild:function(_a){
-_a=dijit.byId(_a);
-if(this.selectedChildWidget!=_a){
-this._transition(_a,this.selectedChildWidget);
-this.selectedChildWidget=_a;
-dojo.publish(this.id+"-selectChild",[_a]);
-if(this.persist){
-dojo.cookie(this.id+"_selectedChild",this.selectedChildWidget.id);
-}
-}
-},_transition:function(_b,_c){
-if(_c){
-this._hideChild(_c);
-}
-this._showChild(_b);
-if(_b.resize){
-if(this.doLayout){
-_b.resize(this._containerContentBox||this._contentBox);
-}else{
-_b.resize();
-}
-}
-},_adjacent:function(_d){
-var _e=this.getChildren();
-var _f=dojo.indexOf(_e,this.selectedChildWidget);
-_f+=_d?1:_e.length-1;
-return _e[_f%_e.length];
-},forward:function(){
-this.selectChild(this._adjacent(true));
-},back:function(){
-this.selectChild(this._adjacent(false));
-},_onKeyPress:function(e){
-dojo.publish(this.id+"-containerKeyPress",[{e:e,page:this}]);
-},layout:function(){
-if(this.doLayout&&this.selectedChildWidget&&this.selectedChildWidget.resize){
-this.selectedChildWidget.resize(this._contentBox);
-}
-},_showChild:function(_10){
-var _11=this.getChildren();
-_10.isFirstChild=(_10==_11[0]);
-_10.isLastChild=(_10==_11[_11.length-1]);
-_10.selected=true;
-dojo.removeClass(_10.domNode,"dijitHidden");
-dojo.addClass(_10.domNode,"dijitVisible");
-_10._onShow();
-},_hideChild:function(_12){
-_12.selected=false;
-dojo.removeClass(_12.domNode,"dijitVisible");
-dojo.addClass(_12.domNode,"dijitHidden");
-_12.onHide();
-},closeChild:function(_13){
-var _14=_13.onClose(this,_13);
-if(_14){
-this.removeChild(_13);
-_13.destroyRecursive();
-}
-},destroyDescendants:function(_15){
-dojo.forEach(this.getChildren(),function(_16){
-this.removeChild(_16);
-_16.destroyRecursive(_15);
-},this);
-}});
+
+dojo.declare(
+	"dijit.layout.StackContainer",
+	dijit.layout._LayoutWidget,
+	{
+	// summary:
+	//		A container that has multiple children, but shows only
+	//		one child at a time
+	//
+	// description:
+	//		A container for widgets (ContentPanes, for example) That displays
+	//		only one Widget at a time.
+	//
+	//		Publishes topics [widgetId]-addChild, [widgetId]-removeChild, and [widgetId]-selectChild
+	//
+	//		Can be base class for container, Wizard, Show, etc.
+
+	// doLayout: Boolean
+	//		If true, change the size of my currently displayed child to match my size
+	doLayout: true,
+
+	// persist: Boolean
+	//		Remembers the selected child across sessions
+	persist: false,
+
+	baseClass: "dijitStackContainer",
+
+/*=====
+	// selectedChildWidget: [readonly] dijit._Widget
+	//		References the currently selected child widget, if any.
+	//		Adjust selected child with selectChild() method.
+	selectedChildWidget: null,
+=====*/
+
+	postCreate: function(){
+		this.inherited(arguments);
+		dojo.addClass(this.domNode, "dijitLayoutContainer");
+		dijit.setWaiRole(this.containerNode, "tabpanel");
+		this.connect(this.domNode, "onkeypress", this._onKeyPress);
+	},
+
+	startup: function(){
+		if(this._started){ return; }
+
+		var children = this.getChildren();
+
+		// Setup each page panel to be initially hidden
+		dojo.forEach(children, this._setupChild, this);
+
+		// Figure out which child to initially display, defaulting to first one
+		if(this.persist){
+			this.selectedChildWidget = dijit.byId(dojo.cookie(this.id + "_selectedChild"));
+		}else{
+			dojo.some(children, function(child){
+				if(child.selected){
+					this.selectedChildWidget = child;
+				}
+				return child.selected;
+			}, this);
+		}
+		var selected = this.selectedChildWidget;
+		if(!selected && children[0]){
+			selected = this.selectedChildWidget = children[0];
+			selected.selected = true;
+		}
+
+		// Publish information about myself so any StackControllers can initialize.
+		// This needs to happen before this.inherited(arguments) so that for
+		// TabContainer, this._contentBox doesn't include the space for the tab labels.
+		dojo.publish(this.id+"-startup", [{children: children, selected: selected}]);
+
+		// Startup each child widget, and do initial layout like setting this._contentBox,
+		// then calls this.resize() which does the initial sizing on the selected child.
+		this.inherited(arguments);
+	},
+
+	resize: function(){
+		// Resize is called when we are first made visible (it's called from startup()
+		// if we are initially visible).   If this is the first time we've been made
+		// visible then show our first child.
+		var selected = this.selectedChildWidget;
+		if(selected && !this._hasBeenShown){
+			this._hasBeenShown = true;
+			this._showChild(selected);
+		}
+		this.inherited(arguments);
+	},
+
+	_setupChild: function(/*dijit._Widget*/ child){
+		// Overrides _LayoutWidget._setupChild()
+
+		this.inherited(arguments);
+
+		dojo.removeClass(child.domNode, "dijitVisible");
+		dojo.addClass(child.domNode, "dijitHidden");
+
+		// remove the title attribute so it doesn't show up when i hover
+		// over a node
+		child.domNode.title = "";
+	},
+
+	addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+		// Overrides _Container.addChild() to do layout and publish events
+
+		this.inherited(arguments);
+
+		if(this._started){
+			dojo.publish(this.id+"-addChild", [child, insertIndex]);
+
+			// in case the tab titles have overflowed from one line to two lines
+			// (or, if this if first child, from zero lines to one line)
+			// TODO: w/ScrollingTabController this is no longer necessary, although
+			// ScrollTabController.resize() does need to get called to show/hide
+			// the navigation buttons as appropriate, but that's handled in ScrollingTabController.onAddChild()
+			this.layout();
+
+			// if this is the first child, then select it
+			if(!this.selectedChildWidget){
+				this.selectChild(child);
+			}
+		}
+	},
+
+	removeChild: function(/*dijit._Widget*/ page){
+		// Overrides _Container.removeChild() to do layout and publish events
+
+		this.inherited(arguments);
+
+		if(this._started){
+			// this will notify any tablists to remove a button; do this first because it may affect sizing
+			dojo.publish(this.id + "-removeChild", [page]);
+		}
+
+		// If we are being destroyed than don't run the code below (to select another page), because we are deleting
+		// every page one by one
+		if(this._beingDestroyed){ return; }
+
+		// Select new page to display, also updating TabController to show the respective tab.
+		// Do this before layout call because it can affect the height of the TabController.
+		if(this.selectedChildWidget === page){
+			this.selectedChildWidget = undefined;
+			if(this._started){
+				var children = this.getChildren();
+				if(children.length){
+					this.selectChild(children[0]);
+				}
+			}
+		}
+
+		if(this._started){
+			// In case the tab titles now take up one line instead of two lines
+			// (note though that ScrollingTabController never overflows to multiple lines),
+			// or the height has changed slightly because of addition/removal of tab which close icon
+			this.layout();
+		}
+	},
+
+	selectChild: function(/*dijit._Widget|String*/ page, /*Boolean*/ animate){
+		// summary:
+		//		Show the given widget (which must be one of my children)
+		// page:
+		//		Reference to child widget or id of child widget
+
+		page = dijit.byId(page);
+
+		if(this.selectedChildWidget != page){
+			// Deselect old page and select new one
+			this._transition(page, this.selectedChildWidget, animate);
+			this.selectedChildWidget = page;
+			dojo.publish(this.id+"-selectChild", [page]);
+
+			if(this.persist){
+				dojo.cookie(this.id + "_selectedChild", this.selectedChildWidget.id);
+			}
+		}
+	},
+
+	_transition: function(/*dijit._Widget*/newWidget, /*dijit._Widget*/oldWidget){
+		// summary:
+		//		Hide the old widget and display the new widget.
+		//		Subclasses should override this.
+		// tags:
+		//		protected extension
+		if(oldWidget){
+			this._hideChild(oldWidget);
+		}
+		this._showChild(newWidget);
+
+		// Size the new widget, in case this is the first time it's being shown,
+		// or I have been resized since the last time it was shown.
+		// Note that page must be visible for resizing to work.
+		if(newWidget.resize){
+			if(this.doLayout){
+				newWidget.resize(this._containerContentBox || this._contentBox);
+			}else{
+				// the child should pick it's own size but we still need to call resize()
+				// (with no arguments) to let the widget lay itself out
+				newWidget.resize();
+			}
+		}
+	},
+
+	_adjacent: function(/*Boolean*/ forward){
+		// summary:
+		//		Gets the next/previous child widget in this container from the current selection.
+		var children = this.getChildren();
+		var index = dojo.indexOf(children, this.selectedChildWidget);
+		index += forward ? 1 : children.length - 1;
+		return children[ index % children.length ]; // dijit._Widget
+	},
+
+	forward: function(){
+		// summary:
+		//		Advance to next page.
+		this.selectChild(this._adjacent(true), true);
+	},
+
+	back: function(){
+		// summary:
+		//		Go back to previous page.
+		this.selectChild(this._adjacent(false), true);
+	},
+
+	_onKeyPress: function(e){
+		dojo.publish(this.id+"-containerKeyPress", [{ e: e, page: this}]);
+	},
+
+	layout: function(){
+		// Implement _LayoutWidget.layout() virtual method.
+		if(this.doLayout && this.selectedChildWidget && this.selectedChildWidget.resize){
+			this.selectedChildWidget.resize(this._containerContentBox || this._contentBox);
+		}
+	},
+
+	_showChild: function(/*dijit._Widget*/ page){
+		// summary:
+		//		Show the specified child by changing it's CSS, and call _onShow()/onShow() so
+		//		it can do any updates it needs regarding loading href's etc.
+		var children = this.getChildren();
+		page.isFirstChild = (page == children[0]);
+		page.isLastChild = (page == children[children.length-1]);
+		page.selected = true;
+
+		dojo.removeClass(page.domNode, "dijitHidden");
+		dojo.addClass(page.domNode, "dijitVisible");
+
+		page._onShow();
+	},
+
+	_hideChild: function(/*dijit._Widget*/ page){
+		// summary:
+		//		Hide the specified child by changing it's CSS, and call _onHide() so
+		//		it's notified.
+		page.selected=false;
+		dojo.removeClass(page.domNode, "dijitVisible");
+		dojo.addClass(page.domNode, "dijitHidden");
+
+		page.onHide();
+	},
+
+	closeChild: function(/*dijit._Widget*/ page){
+		// summary:
+		//		Callback when user clicks the [X] to remove a page.
+		//		If onClose() returns true then remove and destroy the child.
+		// tags:
+		//		private
+		var remove = page.onClose(this, page);
+		if(remove){
+			this.removeChild(page);
+			// makes sure we can clean up executeScripts in ContentPane onUnLoad
+			page.destroyRecursive();
+		}
+	},
+
+	destroyDescendants: function(/*Boolean*/preserveDom){
+		dojo.forEach(this.getChildren(), function(child){
+			this.removeChild(child);
+			child.destroyRecursive(preserveDom);
+		}, this);
+	}
+});
+
+// For back-compat, remove for 2.0
 dojo.require("dijit.layout.StackController");
-dojo.extend(dijit._Widget,{selected:false,closable:false,iconClass:"",showTitle:true,onClose:function(){
-return true;
-}});
-}
+
+
+// These arguments can be specified for the children of a StackContainer.
+// Since any widget can be specified as a StackContainer child, mix them
+// into the base widget class.  (This is a hack, but it's effective.)
+dojo.extend(dijit._Widget, {
+	// selected: Boolean
+	//		Parameter for children of `dijit.layout.StackContainer` or subclasses.
+	//		Specifies that this widget should be the initially displayed pane.
+	//		Note: to change the selected child use `dijit.layout.StackContainer.selectChild`
+	selected: false,
+
+	// closable: Boolean
+	//		Parameter for children of `dijit.layout.StackContainer` or subclasses.
+	//		True if user can close (destroy) this child, such as (for example) clicking the X on the tab.
+	closable: false,
+
+	// iconClass: String
+	//		Parameter for children of `dijit.layout.StackContainer` or subclasses.
+	//		CSS Class specifying icon to use in label associated with this pane.
+	iconClass: "",
+
+	// showTitle: Boolean
+	//		Parameter for children of `dijit.layout.StackContainer` or subclasses.
+	//		When true, display title of this widget as tab label etc., rather than just using
+	//		icon specified in iconClass
+	showTitle: true
+});
diff --git a/dijit/layout/StackController.js b/dijit/layout/StackController.js
index 52e98af..c8bc1a6 100644
--- a/dijit/layout/StackController.js
+++ b/dijit/layout/StackController.js
@@ -1,178 +1,300 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout.StackController"]){
-dojo._hasResource["dijit.layout.StackController"]=true;
 dojo.provide("dijit.layout.StackController");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Container");
 dojo.require("dijit.form.ToggleButton");
-dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit.layout.StackController",[dijit._Widget,dijit._Templated,dijit._Container],{templateString:"<span wairole='tablist' dojoAttachEvent='onkeypress' class='dijitStackController'></span>",containerId:"",buttonWidget:"dijit.layout._StackButton",postCreate:function(){
-dijit.setWaiRole(this.domNode,"tablist");
-this.pane2button={};
-this.pane2handles={};
-this.subscribe(this.containerId+"-startup","onStartup");
-this.subscribe(this.containerId+"-addChild","onAddChild");
-this.subscribe(this.containerId+"-removeChild","onRemoveChild");
-this.subscribe(this.containerId+"-selectChild","onSelectChild");
-this.subscribe(this.containerId+"-containerKeyPress","onContainerKeyPress");
-},onStartup:function(_1){
-dojo.forEach(_1.children,this.onAddChild,this);
-if(_1.selected){
-this.onSelectChild(_1.selected);
-}
-},destroy:function(){
-for(var _2 in this.pane2button){
-this.onRemoveChild(dijit.byId(_2));
-}
-this.inherited(arguments);
-},onAddChild:function(_3,_4){
-var _5=dojo.doc.createElement("span");
-this.domNode.appendChild(_5);
-var _6=dojo.getObject(this.buttonWidget);
-var _7=new _6({id:this.id+"_"+_3.id,label:_3.title,showLabel:_3.showTitle,iconClass:_3.iconClass,closeButton:_3.closable,title:_3.tooltip},_5);
-dijit.setWaiState(_7.focusNode,"selected","false");
-this.pane2handles[_3.id]=[this.connect(_3,"attr",function(_8,_9){
-if(arguments.length==2){
-var _a={title:"label",showTitle:"showLabel",iconClass:"iconClass",closable:"closeButton",tooltip:"title"}[_8];
-if(_a){
-_7.attr(_a,_9);
-}
-}
-}),this.connect(_7,"onClick",dojo.hitch(this,"onButtonClick",_3)),this.connect(_7,"onClickCloseButton",dojo.hitch(this,"onCloseButtonClick",_3))];
-this.addChild(_7,_4);
-this.pane2button[_3.id]=_7;
-_3.controlButton=_7;
-if(!this._currentChild){
-_7.focusNode.setAttribute("tabIndex","0");
-dijit.setWaiState(_7.focusNode,"selected","true");
-this._currentChild=_3;
-}
-if(!this.isLeftToRight()&&dojo.isIE&&this._rectifyRtlTabList){
-this._rectifyRtlTabList();
-}
-},onRemoveChild:function(_b){
-if(this._currentChild===_b){
-this._currentChild=null;
-}
-dojo.forEach(this.pane2handles[_b.id],this.disconnect,this);
-delete this.pane2handles[_b.id];
-var _c=this.pane2button[_b.id];
-if(_c){
-this.removeChild(_c);
-delete this.pane2button[_b.id];
-_c.destroy();
-}
-delete _b.controlButton;
-},onSelectChild:function(_d){
-if(!_d){
-return;
-}
-if(this._currentChild){
-var _e=this.pane2button[this._currentChild.id];
-_e.attr("checked",false);
-dijit.setWaiState(_e.focusNode,"selected","false");
-_e.focusNode.setAttribute("tabIndex","-1");
-}
-var _f=this.pane2button[_d.id];
-_f.attr("checked",true);
-dijit.setWaiState(_f.focusNode,"selected","true");
-this._currentChild=_d;
-_f.focusNode.setAttribute("tabIndex","0");
-var _10=dijit.byId(this.containerId);
-dijit.setWaiState(_10.containerNode,"labelledby",_f.id);
-},onButtonClick:function(_11){
-var _12=dijit.byId(this.containerId);
-_12.selectChild(_11);
-},onCloseButtonClick:function(_13){
-var _14=dijit.byId(this.containerId);
-_14.closeChild(_13);
-if(this._currentChild){
-var b=this.pane2button[this._currentChild.id];
-if(b){
-dijit.focus(b.focusNode||b.domNode);
-}
-}
-},adjacent:function(_15){
-if(!this.isLeftToRight()&&(!this.tabPosition||/top|bottom/.test(this.tabPosition))){
-_15=!_15;
-}
-var _16=this.getChildren();
-var _17=dojo.indexOf(_16,this.pane2button[this._currentChild.id]);
-var _18=_15?1:_16.length-1;
-return _16[(_17+_18)%_16.length];
-},onkeypress:function(e){
-if(this.disabled||e.altKey){
-return;
-}
-var _19=null;
-if(e.ctrlKey||!e._djpage){
-var k=dojo.keys;
-switch(e.charOrCode){
-case k.LEFT_ARROW:
-case k.UP_ARROW:
-if(!e._djpage){
-_19=false;
-}
-break;
-case k.PAGE_UP:
-if(e.ctrlKey){
-_19=false;
-}
-break;
-case k.RIGHT_ARROW:
-case k.DOWN_ARROW:
-if(!e._djpage){
-_19=true;
-}
-break;
-case k.PAGE_DOWN:
-if(e.ctrlKey){
-_19=true;
-}
-break;
-case k.DELETE:
-if(this._currentChild.closable){
-this.onCloseButtonClick(this._currentChild);
-}
-dojo.stopEvent(e);
-break;
-default:
-if(e.ctrlKey){
-if(e.charOrCode===k.TAB){
-this.adjacent(!e.shiftKey).onClick();
-dojo.stopEvent(e);
-}else{
-if(e.charOrCode=="w"){
-if(this._currentChild.closable){
-this.onCloseButtonClick(this._currentChild);
-}
-dojo.stopEvent(e);
-}
-}
-}
-}
-if(_19!==null){
-this.adjacent(_19).onClick();
-dojo.stopEvent(e);
-}
-}
-},onContainerKeyPress:function(_1a){
-_1a.e._djpage=_1a.page;
-this.onkeypress(_1a.e);
-}});
-dojo.declare("dijit.layout._StackButton",dijit.form.ToggleButton,{tabIndex:"-1",postCreate:function(evt){
-dijit.setWaiRole((this.focusNode||this.domNode),"tab");
-this.inherited(arguments);
-},onClick:function(evt){
-dijit.focus(this.focusNode);
-},onClickCloseButton:function(evt){
-evt.stopPropagation();
-}});
-}
+dojo.requireLocalization("dijit", "common");
+
+dojo.declare(
+		"dijit.layout.StackController",
+		[dijit._Widget, dijit._Templated, dijit._Container],
+		{
+			// summary:
+			//		Set of buttons to select a page in a page list.
+			// description:
+			//		Monitors the specified StackContainer, and whenever a page is
+			//		added, deleted, or selected, updates itself accordingly.
+
+			templateString: "<span wairole='tablist' dojoAttachEvent='onkeypress' class='dijitStackController'></span>",
+
+			// containerId: [const] String
+			//		The id of the page container that I point to
+			containerId: "",
+
+			// buttonWidget: [const] String
+			//		The name of the button widget to create to correspond to each page
+			buttonWidget: "dijit.layout._StackButton",
+
+			postCreate: function(){
+				dijit.setWaiRole(this.domNode, "tablist");
+
+				this.pane2button = {};		// mapping from pane id to buttons
+				this.pane2handles = {};		// mapping from pane id to this.connect() handles
+
+				// Listen to notifications from StackContainer
+				this.subscribe(this.containerId+"-startup", "onStartup");
+				this.subscribe(this.containerId+"-addChild", "onAddChild");
+				this.subscribe(this.containerId+"-removeChild", "onRemoveChild");
+				this.subscribe(this.containerId+"-selectChild", "onSelectChild");
+				this.subscribe(this.containerId+"-containerKeyPress", "onContainerKeyPress");
+			},
+
+			onStartup: function(/*Object*/ info){
+				// summary:
+				//		Called after StackContainer has finished initializing
+				// tags:
+				//		private
+				dojo.forEach(info.children, this.onAddChild, this);
+				if(info.selected){
+					// Show button corresponding to selected pane (unless selected
+					// is null because there are no panes)
+					this.onSelectChild(info.selected);
+				}
+			},
+
+			destroy: function(){
+				for(var pane in this.pane2button){
+					this.onRemoveChild(dijit.byId(pane));
+				}
+				this.inherited(arguments);
+			},
+
+			onAddChild: function(/*dijit._Widget*/ page, /*Integer?*/ insertIndex){
+				// summary:
+				//		Called whenever a page is added to the container.
+				//		Create button corresponding to the page.
+				// tags:
+				//		private
+
+				// create an instance of the button widget
+				var cls = dojo.getObject(this.buttonWidget);
+				var button = new cls({
+					id: this.id + "_" + page.id,
+					label: page.title,
+					dir: page.dir,
+					lang: page.lang,
+					showLabel: page.showTitle,
+					iconClass: page.iconClass,
+					closeButton: page.closable,
+					title: page.tooltip
+				});
+				dijit.setWaiState(button.focusNode,"selected", "false");
+				this.pane2handles[page.id] = [
+					this.connect(page, 'set', function(name, value){
+						var buttonAttr = {
+							title: 'label',
+							showTitle: 'showLabel',
+							iconClass: 'iconClass',
+							closable: 'closeButton',
+							tooltip: 'title'
+						}[name];
+						if(buttonAttr){
+							button.set(buttonAttr, value);
+						}
+					}),
+					this.connect(button, 'onClick', dojo.hitch(this,"onButtonClick", page)),
+					this.connect(button, 'onClickCloseButton', dojo.hitch(this,"onCloseButtonClick", page))
+				];
+				this.addChild(button, insertIndex);
+				this.pane2button[page.id] = button;
+				page.controlButton = button;	// this value might be overwritten if two tabs point to same container
+				if(!this._currentChild){ // put the first child into the tab order
+					button.focusNode.setAttribute("tabIndex", "0");
+					dijit.setWaiState(button.focusNode, "selected", "true");
+					this._currentChild = page;
+				}
+				// make sure all tabs have the same length
+				if(!this.isLeftToRight() && dojo.isIE && this._rectifyRtlTabList){
+					this._rectifyRtlTabList();
+				}
+			},
+
+			onRemoveChild: function(/*dijit._Widget*/ page){
+				// summary:
+				//		Called whenever a page is removed from the container.
+				//		Remove the button corresponding to the page.
+				// tags:
+				//		private
+
+				if(this._currentChild === page){ this._currentChild = null; }
+				dojo.forEach(this.pane2handles[page.id], this.disconnect, this);
+				delete this.pane2handles[page.id];
+				var button = this.pane2button[page.id];
+				if(button){
+					this.removeChild(button);
+					delete this.pane2button[page.id];
+					button.destroy();
+				}
+				delete page.controlButton;
+			},
+
+			onSelectChild: function(/*dijit._Widget*/ page){
+				// summary:
+				//		Called when a page has been selected in the StackContainer, either by me or by another StackController
+				// tags:
+				//		private
+
+				if(!page){ return; }
+
+				if(this._currentChild){
+					var oldButton=this.pane2button[this._currentChild.id];
+					oldButton.set('checked', false);
+					dijit.setWaiState(oldButton.focusNode, "selected", "false");
+					oldButton.focusNode.setAttribute("tabIndex", "-1");
+				}
+
+				var newButton=this.pane2button[page.id];
+				newButton.set('checked', true);
+				dijit.setWaiState(newButton.focusNode, "selected", "true");
+				this._currentChild = page;
+				newButton.focusNode.setAttribute("tabIndex", "0");
+				var container = dijit.byId(this.containerId);
+				dijit.setWaiState(container.containerNode, "labelledby", newButton.id);
+			},
+
+			onButtonClick: function(/*dijit._Widget*/ page){
+				// summary:
+				//		Called whenever one of my child buttons is pressed in an attempt to select a page
+				// tags:
+				//		private
+
+				var container = dijit.byId(this.containerId);
+				container.selectChild(page);
+			},
+
+			onCloseButtonClick: function(/*dijit._Widget*/ page){
+				// summary:
+				//		Called whenever one of my child buttons [X] is pressed in an attempt to close a page
+				// tags:
+				//		private
+
+				var container = dijit.byId(this.containerId);
+				container.closeChild(page);
+				if(this._currentChild){
+					var b = this.pane2button[this._currentChild.id];
+					if(b){
+						dijit.focus(b.focusNode || b.domNode);
+					}
+				}
+			},
+
+			// TODO: this is a bit redundant with forward, back api in StackContainer
+			adjacent: function(/*Boolean*/ forward){
+				// summary:
+				//		Helper for onkeypress to find next/previous button
+				// tags:
+				//		private
+
+				if(!this.isLeftToRight() && (!this.tabPosition || /top|bottom/.test(this.tabPosition))){ forward = !forward; }
+				// find currently focused button in children array
+				var children = this.getChildren();
+				var current = dojo.indexOf(children, this.pane2button[this._currentChild.id]);
+				// pick next button to focus on
+				var offset = forward ? 1 : children.length - 1;
+				return children[ (current + offset) % children.length ]; // dijit._Widget
+			},
+
+			onkeypress: function(/*Event*/ e){
+				// summary:
+				//		Handle keystrokes on the page list, for advancing to next/previous button
+				//		and closing the current page if the page is closable.
+				// tags:
+				//		private
+
+				if(this.disabled || e.altKey ){ return; }
+				var forward = null;
+				if(e.ctrlKey || !e._djpage){
+					var k = dojo.keys;
+					switch(e.charOrCode){
+						case k.LEFT_ARROW:
+						case k.UP_ARROW:
+							if(!e._djpage){ forward = false; }
+							break;
+						case k.PAGE_UP:
+							if(e.ctrlKey){ forward = false; }
+							break;
+						case k.RIGHT_ARROW:
+						case k.DOWN_ARROW:
+							if(!e._djpage){ forward = true; }
+							break;
+						case k.PAGE_DOWN:
+							if(e.ctrlKey){ forward = true; }
+							break;
+						case k.DELETE:
+							if(this._currentChild.closable){
+								this.onCloseButtonClick(this._currentChild);
+							}
+							dojo.stopEvent(e);
+							break;
+						default:
+							if(e.ctrlKey){
+								if(e.charOrCode === k.TAB){
+									this.adjacent(!e.shiftKey).onClick();
+									dojo.stopEvent(e);
+								}else if(e.charOrCode == "w"){
+									if(this._currentChild.closable){
+										this.onCloseButtonClick(this._currentChild);
+									}
+									dojo.stopEvent(e); // avoid browser tab closing.
+								}
+							}
+					}
+					// handle page navigation
+					if(forward !== null){
+						this.adjacent(forward).onClick();
+						dojo.stopEvent(e);
+					}
+				}
+			},
+
+			onContainerKeyPress: function(/*Object*/ info){
+				// summary:
+				//		Called when there was a keypress on the container
+				// tags:
+				//		private
+				info.e._djpage = info.page;
+				this.onkeypress(info.e);
+			}
+	});
+
+
+dojo.declare("dijit.layout._StackButton",
+		dijit.form.ToggleButton,
+		{
+		// summary:
+		//		Internal widget used by StackContainer.
+		// description:
+		//		The button-like or tab-like object you click to select or delete a page
+		// tags:
+		//		private
+
+		// Override _FormWidget.tabIndex.
+		// StackContainer buttons are not in the tab order by default.
+		// Probably we should be calling this.startupKeyNavChildren() instead.
+		tabIndex: "-1",
+
+		postCreate: function(/*Event*/ evt){
+			dijit.setWaiRole((this.focusNode || this.domNode), "tab");
+			this.inherited(arguments);
+		},
+
+		onClick: function(/*Event*/ evt){
+			// summary:
+			//		This is for TabContainer where the tabs are <span> rather than button,
+			//		so need to set focus explicitly (on some browsers)
+			//		Note that you shouldn't override this method, but you can connect to it.
+			dijit.focus(this.focusNode);
+
+			// ... now let StackController catch the event and tell me what to do
+		},
+
+		onClickCloseButton: function(/*Event*/ evt){
+			// summary:
+			//		StackContainer connects to this function; if your widget contains a close button
+			//		then clicking it should call this function.
+			//		Note that you shouldn't override this method, but you can connect to it.
+			evt.stopPropagation();
+		}
+	});
+
diff --git a/dijit/layout/TabContainer.js b/dijit/layout/TabContainer.js
index 030a4ac..cefa134 100644
--- a/dijit/layout/TabContainer.js
+++ b/dijit/layout/TabContainer.js
@@ -1,23 +1,66 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout.TabContainer"]){
-dojo._hasResource["dijit.layout.TabContainer"]=true;
 dojo.provide("dijit.layout.TabContainer");
+
 dojo.require("dijit.layout._TabContainerBase");
 dojo.require("dijit.layout.TabController");
 dojo.require("dijit.layout.ScrollingTabController");
-dojo.declare("dijit.layout.TabContainer",dijit.layout._TabContainerBase,{useMenu:true,useSlider:true,controllerWidget:"",_makeController:function(_1){
-var _2=this.baseClass+"-tabs"+(this.doLayout?"":" dijitTabNoLayout"),_3=dojo.getObject(this.controllerWidget);
-return new _3({id:this.id+"_tablist",tabPosition:this.tabPosition,doLayout:this.doLayout,containerId:this.id,"class":_2,nested:this.nested,useMenu:this.useMenu,useSlider:this.useSlider,tabStripClass:this.tabStrip?this.baseClass+(this.tabStrip?"":"No")+"Strip":null},_1);
-},postMixInProperties:function(){
-this.inherited(arguments);
-if(!this.controllerWidget){
-this.controllerWidget=(this.tabPosition=="top"||this.tabPosition=="bottom")&&!this.nested?"dijit.layout.ScrollingTabController":"dijit.layout.TabController";
-}
-}});
-}
+
+dojo.declare("dijit.layout.TabContainer",
+	dijit.layout._TabContainerBase,
+	{
+		// summary:
+		//		A Container with tabs to select each child (only one of which is displayed at a time).
+		// description:
+		//		A TabContainer is a container that has multiple panes, but shows only
+		//		one pane at a time.  There are a set of tabs corresponding to each pane,
+		//		where each tab has the name (aka title) of the pane, and optionally a close button.
+
+		// useMenu: [const] Boolean
+		//		True if a menu should be used to select tabs when they are too
+		//		wide to fit the TabContainer, false otherwise.
+		useMenu: true,
+
+		// useSlider: [const] Boolean
+		//		True if a slider should be used to select tabs when they are too
+		//		wide to fit the TabContainer, false otherwise.
+		useSlider: true,
+
+		// controllerWidget: String
+		//		An optional parameter to override the widget used to display the tab labels
+		controllerWidget: "",
+
+		_makeController: function(/*DomNode*/ srcNode){
+			// summary:
+			//		Instantiate tablist controller widget and return reference to it.
+			//		Callback from _TabContainerBase.postCreate().
+			// tags:
+			//		protected extension
+
+			var cls = this.baseClass + "-tabs" + (this.doLayout ? "" : " dijitTabNoLayout"),
+				TabController = dojo.getObject(this.controllerWidget);
+
+			return new TabController({
+				id: this.id + "_tablist",
+				dir: this.dir,
+				lang: this.lang,
+				tabPosition: this.tabPosition,
+				doLayout: this.doLayout,
+				containerId: this.id,
+				"class": cls,
+				nested: this.nested,
+				useMenu: this.useMenu,
+				useSlider: this.useSlider,
+				tabStripClass: this.tabStrip ? this.baseClass + (this.tabStrip ? "":"No") + "Strip": null
+			}, srcNode);
+		},
+
+		postMixInProperties: function(){
+			this.inherited(arguments);
+
+			// Scrolling controller only works for horizontal non-nested tabs
+			if(!this.controllerWidget){
+				this.controllerWidget = (this.tabPosition == "top" || this.tabPosition == "bottom") && !this.nested ?
+							"dijit.layout.ScrollingTabController" : "dijit.layout.TabController";
+			}
+		}
+});
+
diff --git a/dijit/layout/TabController.js b/dijit/layout/TabController.js
index 119dd35..0ae654c 100644
--- a/dijit/layout/TabController.js
+++ b/dijit/layout/TabController.js
@@ -1,79 +1,164 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout.TabController"]){
-dojo._hasResource["dijit.layout.TabController"]=true;
 dojo.provide("dijit.layout.TabController");
+
 dojo.require("dijit.layout.StackController");
+
+// Menu is used for an accessible close button, would be nice to have a lighter-weight solution
 dojo.require("dijit.Menu");
 dojo.require("dijit.MenuItem");
-dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dijit.layout.TabController",dijit.layout.StackController,{templateString:"<div wairole='tablist' dojoAttachEvent='onkeypress:onkeypress'></div>",tabPosition:"top",buttonWidget:"dijit.layout._TabButton",_rectifyRtlTabList:function(){
-if(0>=this.tabPosition.indexOf("-h")){
-return;
-}
-if(!this.pane2button){
-return;
-}
-var _1=0;
-for(var _2 in this.pane2button){
-var ow=this.pane2button[_2].innerDiv.scrollWidth;
-_1=Math.max(_1,ow);
-}
-for(_2 in this.pane2button){
-this.pane2button[_2].innerDiv.style.width=_1+"px";
-}
-}});
-dojo.declare("dijit.layout._TabButton",dijit.layout._StackButton,{baseClass:"dijitTab",templateString:dojo.cache("dijit.layout","templates/_TabButton.html","<div waiRole=\"presentation\" dojoAttachPoint=\"titleNode\" dojoAttachEvent='onclick:onClick,onmouseenter:_onMouse,onmouseleave:_onMouse'>\n    <div waiRole=\"presentation\" class='dijitTabInnerDiv' dojoAttachPoint='innerDiv'>\n        <div waiRole=\"presentation\" class='dijitTabContent' dojoAttachPoint='tabContent,focusNode'>\n\t   [...]
-if(!this.iconClass){
-this.iconClass="dijitTabButtonIcon";
-}
-},postCreate:function(){
-this.inherited(arguments);
-dojo.setSelectable(this.containerNode,false);
-if(this.iconNode.className=="dijitTabButtonIcon"){
-dojo.style(this.iconNode,"width","1px");
-}
-},startup:function(){
-this.inherited(arguments);
-var n=this.domNode;
-setTimeout(function(){
-n.className=n.className;
-},1);
-},_setCloseButtonAttr:function(_3){
-this.closeButton=_3;
-dojo.toggleClass(this.innerDiv,"dijitClosable",_3);
-this.closeNode.style.display=_3?"":"none";
-if(_3){
-var _4=dojo.i18n.getLocalization("dijit","common");
-if(this.closeNode){
-dojo.attr(this.closeNode,"title",_4.itemClose);
-if(dojo.isIE<8){
-dojo.attr(this.closeIcon,"title",_4.itemClose);
-}
-}
-var _4=dojo.i18n.getLocalization("dijit","common");
-this._closeMenu=new dijit.Menu({id:this.id+"_Menu",targetNodeIds:[this.domNode]});
-this._closeMenu.addChild(new dijit.MenuItem({label:_4.itemClose,onClick:dojo.hitch(this,"onClickCloseButton")}));
-}else{
-if(this._closeMenu){
-this._closeMenu.destroyRecursive();
-delete this._closeMenu;
-}
-}
-},destroy:function(){
-if(this._closeMenu){
-this._closeMenu.destroyRecursive();
-delete this._closeMenu;
-}
-this.inherited(arguments);
-},_onCloseButtonEnter:function(){
-dojo.addClass(this.closeNode,"closeButton-hover");
-},_onCloseButtonLeave:function(){
-dojo.removeClass(this.closeNode,"closeButton-hover");
-}});
-}
+
+dojo.requireLocalization("dijit", "common");
+
+dojo.declare("dijit.layout.TabController",
+	dijit.layout.StackController,
+{
+	// summary:
+	// 		Set of tabs (the things with titles and a close button, that you click to show a tab panel).
+	//		Used internally by `dijit.layout.TabContainer`.
+	// description:
+	//		Lets the user select the currently shown pane in a TabContainer or StackContainer.
+	//		TabController also monitors the TabContainer, and whenever a pane is
+	//		added or deleted updates itself accordingly.
+	// tags:
+	//		private
+
+	templateString: "<div wairole='tablist' dojoAttachEvent='onkeypress:onkeypress'></div>",
+
+	// tabPosition: String
+	//		Defines where tabs go relative to the content.
+	//		"top", "bottom", "left-h", "right-h"
+	tabPosition: "top",
+
+	// buttonWidget: String
+	//		The name of the tab widget to create to correspond to each page
+	buttonWidget: "dijit.layout._TabButton",
+
+	_rectifyRtlTabList: function(){
+		// summary:
+		//		For left/right TabContainer when page is RTL mode, rectify the width of all tabs to be equal, otherwise the tab widths are different in IE
+
+		if(0 >= this.tabPosition.indexOf('-h')){ return; }
+		if(!this.pane2button){ return; }
+
+		var maxWidth = 0;
+		for(var pane in this.pane2button){
+			var ow = this.pane2button[pane].innerDiv.scrollWidth;
+			maxWidth = Math.max(maxWidth, ow);
+		}
+		//unify the length of all the tabs
+		for(pane in this.pane2button){
+			this.pane2button[pane].innerDiv.style.width = maxWidth + 'px';
+		}
+	}
+});
+
+dojo.declare("dijit.layout._TabButton",
+	dijit.layout._StackButton,
+	{
+	// summary:
+	//		A tab (the thing you click to select a pane).
+	// description:
+	//		Contains the title of the pane, and optionally a close-button to destroy the pane.
+	//		This is an internal widget and should not be instantiated directly.
+	// tags:
+	//		private
+
+	// baseClass: String
+	//		The CSS class applied to the domNode.
+	baseClass: "dijitTab",
+
+	// Apply dijitTabCloseButtonHover when close button is hovered
+	cssStateNodes: {
+		closeNode: "dijitTabCloseButton"
+	},
+
+	templateString: dojo.cache("dijit.layout","templates/_TabButton.html"),
+
+	// Override _FormWidget.scrollOnFocus.
+	// Don't scroll the whole tab container into view when the button is focused.
+	scrollOnFocus: false,
+
+	postMixInProperties: function(){
+		// Override blank iconClass from Button to do tab height adjustment on IE6,
+		// to make sure that tabs with and w/out close icons are same height
+		if(!this.iconClass){
+			this.iconClass = "dijitTabButtonIcon";
+		}
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+		dojo.setSelectable(this.containerNode, false);
+
+		// If a custom icon class has not been set for the
+		// tab icon, set its width to one pixel. This ensures
+		// that the height styling of the tab is maintained,
+		// as it is based on the height of the icon.
+		// TODO: I still think we can just set dijitTabButtonIcon to 1px in CSS <Bill>
+		if(this.iconNode.className == "dijitTabButtonIcon"){
+			dojo.style(this.iconNode, "width", "1px");
+		}
+	},
+
+	startup: function(){
+		this.inherited(arguments);
+		var n = this.domNode;
+
+		// Required to give IE6 a kick, as it initially hides the
+		// tabs until they are focused on.
+		setTimeout(function(){
+			n.className = n.className;
+		}, 1);
+	},
+
+	_setCloseButtonAttr: function(disp){
+		this.closeButton = disp;
+		dojo.toggleClass(this.innerDiv, "dijitClosable", disp);
+		this.closeNode.style.display = disp ? "" : "none";
+		if(disp){
+			var _nlsResources = dojo.i18n.getLocalization("dijit", "common");
+			if(this.closeNode){
+				dojo.attr(this.closeNode,"title", _nlsResources.itemClose);
+			}
+			// add context menu onto title button
+			var _nlsResources = dojo.i18n.getLocalization("dijit", "common");
+			this._closeMenu = new dijit.Menu({
+				id: this.id+"_Menu",
+				dir: this.dir,
+				lang: this.lang,
+				targetNodeIds: [this.domNode]
+			});
+
+			this._closeMenu.addChild(new dijit.MenuItem({
+				label: _nlsResources.itemClose,
+				dir: this.dir,
+				lang: this.lang,
+				onClick: dojo.hitch(this, "onClickCloseButton")
+			}));
+		}else{
+			if(this._closeMenu){
+				this._closeMenu.destroyRecursive();
+				delete this._closeMenu;
+			}
+		}
+	},
+	_setLabelAttr: function(/*String*/ content){
+		// summary:
+		//		Hook for attr('label', ...) to work.
+		// description:
+		//		takes an HTML string.
+		//		Inherited ToggleButton implementation will Set the label (text) of the button; 
+		//		Need to set the alt attribute of icon on tab buttons if no label displayed
+			this.inherited(arguments);
+			if(this.showLabel == false && !this.params.title){
+				this.iconNode.alt = dojo.trim(this.containerNode.innerText || this.containerNode.textContent || '');
+			}
+		},
+
+	destroy: function(){
+		if(this._closeMenu){
+			this._closeMenu.destroyRecursive();
+			delete this._closeMenu;
+		}
+		this.inherited(arguments);
+	}
+});
diff --git a/dijit/layout/_LayoutWidget.js b/dijit/layout/_LayoutWidget.js
index 507c9f5..5444070 100644
--- a/dijit/layout/_LayoutWidget.js
+++ b/dijit/layout/_LayoutWidget.js
@@ -1,127 +1,276 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout._LayoutWidget"]){
-dojo._hasResource["dijit.layout._LayoutWidget"]=true;
 dojo.provide("dijit.layout._LayoutWidget");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Container");
 dojo.require("dijit._Contained");
-dojo.declare("dijit.layout._LayoutWidget",[dijit._Widget,dijit._Container,dijit._Contained],{baseClass:"dijitLayoutContainer",isLayoutContainer:true,postCreate:function(){
-dojo.addClass(this.domNode,"dijitContainer");
-dojo.addClass(this.domNode,this.baseClass);
-this.inherited(arguments);
-},startup:function(){
-if(this._started){
-return;
-}
-this.inherited(arguments);
-var _1=this.getParent&&this.getParent();
-if(!(_1&&_1.isLayoutContainer)){
-this.resize();
-this.connect(dojo.isIE?this.domNode:dojo.global,"onresize",function(){
-this.resize();
-});
-}
-},resize:function(_2,_3){
-var _4=this.domNode;
-if(_2){
-dojo.marginBox(_4,_2);
-if(_2.t){
-_4.style.top=_2.t+"px";
-}
-if(_2.l){
-_4.style.left=_2.l+"px";
-}
-}
-var mb=_3||{};
-dojo.mixin(mb,_2||{});
-if(!("h" in mb)||!("w" in mb)){
-mb=dojo.mixin(dojo.marginBox(_4),mb);
-}
-var cs=dojo.getComputedStyle(_4);
-var me=dojo._getMarginExtents(_4,cs);
-var be=dojo._getBorderExtents(_4,cs);
-var bb=(this._borderBox={w:mb.w-(me.w+be.w),h:mb.h-(me.h+be.h)});
-var pe=dojo._getPadExtents(_4,cs);
-this._contentBox={l:dojo._toPixelValue(_4,cs.paddingLeft),t:dojo._toPixelValue(_4,cs.paddingTop),w:bb.w-pe.w,h:bb.h-pe.h};
-this.layout();
-},layout:function(){
-},_setupChild:function(_5){
-dojo.addClass(_5.domNode,this.baseClass+"-child");
-if(_5.baseClass){
-dojo.addClass(_5.domNode,this.baseClass+"-"+_5.baseClass);
-}
-},addChild:function(_6,_7){
-this.inherited(arguments);
-if(this._started){
-this._setupChild(_6);
-}
-},removeChild:function(_8){
-dojo.removeClass(_8.domNode,this.baseClass+"-child");
-if(_8.baseClass){
-dojo.removeClass(_8.domNode,this.baseClass+"-"+_8.baseClass);
-}
-this.inherited(arguments);
-}});
-dijit.layout.marginBox2contentBox=function(_9,mb){
-var cs=dojo.getComputedStyle(_9);
-var me=dojo._getMarginExtents(_9,cs);
-var pb=dojo._getPadBorderExtents(_9,cs);
-return {l:dojo._toPixelValue(_9,cs.paddingLeft),t:dojo._toPixelValue(_9,cs.paddingTop),w:mb.w-(me.w+pb.w),h:mb.h-(me.h+pb.h)};
+
+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 manage placement and sizing of 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,
+		//		for example dijitTabContainer-content.
+		baseClass: "dijitLayoutContainer",
+
+		// isLayoutContainer: [protected] Boolean
+		//		Indicates that this widget is going to call resize() on its
+		//		children widgets, setting their size, when they become visible.
+		isLayoutContainer: true,
+
+		postCreate: function(){
+			dojo.addClass(this.domNode, "dijitContainer");
+
+			this.inherited(arguments);
+		},
+
+		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; }
+
+			// Need to call inherited first - so that child widgets get started
+			// up correctly
+			this.inherited(arguments);
+
+			// If I am a not being controlled by a parent layout widget...
+			var parent = this.getParent && this.getParent()
+			if(!(parent && parent.isLayoutContainer)){
+				// 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 *may be* width=height=100%
+				// or something similar (either set directly or via a CSS class),
+				// monitor when my size changes so that I can re-layout.
+				// For browsers where I can't directly monitor when my size changes,
+				// monitor when the viewport changes size, which *may* indicate a size change for me.
+				this.connect(dojo.isIE ? this.domNode : dojo.global, 'onresize', function(){
+					// Using function(){} closure to ensure no arguments to resize.
+					this.resize();
+				});
+			}
+		},
+
+		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 its 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 its 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(/*dijit._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(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+			// Overrides _Container.addChild() to call _setupChild()
+			this.inherited(arguments);
+			if(this._started){
+				this._setupChild(child);
+			}
+		},
+
+		removeChild: function(/*dijit._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 _a=function(_b){
-return _b.substring(0,1).toUpperCase()+_b.substring(1);
-};
-var _c=function(_d,_e){
-_d.resize?_d.resize(_e):dojo.marginBox(_d.domNode,_e);
-dojo.mixin(_d,dojo.marginBox(_d.domNode));
-dojo.mixin(_d,_e);
-};
-dijit.layout.layoutChildren=function(_f,dim,_10){
-dim=dojo.mixin({},dim);
-dojo.addClass(_f,"dijitLayoutContainer");
-_10=dojo.filter(_10,function(_11){
-return _11.layoutAlign!="client";
-}).concat(dojo.filter(_10,function(_12){
-return _12.layoutAlign=="client";
-}));
-dojo.forEach(_10,function(_13){
-var elm=_13.domNode,pos=_13.layoutAlign;
-var _14=elm.style;
-_14.left=dim.l+"px";
-_14.top=dim.t+"px";
-_14.bottom=_14.right="auto";
-dojo.addClass(elm,"dijitAlign"+_a(pos));
-if(pos=="top"||pos=="bottom"){
-_c(_13,{w:dim.w});
-dim.h-=_13.h;
-if(pos=="top"){
-dim.t+=_13.h;
-}else{
-_14.top=dim.t+dim.h+"px";
-}
-}else{
-if(pos=="left"||pos=="right"){
-_c(_13,{h:dim.h});
-dim.w-=_13.w;
-if(pos=="left"){
-dim.l+=_13.w;
-}else{
-_14.left=dim.l+dim.w+"px";
-}
-}else{
-if(pos=="client"){
-_c(_13,dim);
-}
-}
-}
-});
-};
+	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 its 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);
+			}
+		});
+	};
+
 })();
-}
diff --git a/dijit/layout/_TabContainerBase.js b/dijit/layout/_TabContainerBase.js
index 255fdfb..f8bc174 100644
--- a/dijit/layout/_TabContainerBase.js
+++ b/dijit/layout/_TabContainerBase.js
@@ -1,68 +1,130 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.layout._TabContainerBase"]){
-dojo._hasResource["dijit.layout._TabContainerBase"]=true;
 dojo.provide("dijit.layout._TabContainerBase");
+
 dojo.require("dijit.layout.StackContainer");
 dojo.require("dijit._Templated");
-dojo.declare("dijit.layout._TabContainerBase",[dijit.layout.StackContainer,dijit._Templated],{tabPosition:"top",baseClass:"dijitTabContainer",tabStrip:false,nested:false,templateString:dojo.cache("dijit.layout","templates/TabContainer.html","<div class=\"dijitTabContainer\">\n\t<div class=\"dijitTabListWrapper\" dojoAttachPoint=\"tablistNode\"></div>\n\t<div dojoAttachPoint=\"tablistSpacer\" class=\"dijitTabSpacer ${baseClass}-spacer\"></div>\n\t<div class=\"dijitTabPaneWrapper ${baseCla [...]
-this.baseClass+=this.tabPosition.charAt(0).toUpperCase()+this.tabPosition.substr(1).replace(/-.*/,"");
-this.srcNodeRef&&dojo.style(this.srcNodeRef,"visibility","hidden");
-this.inherited(arguments);
-},postCreate:function(){
-this.inherited(arguments);
-this.tablist=this._makeController(this.tablistNode);
-if(!this.doLayout){
-dojo.addClass(this.domNode,"dijitTabContainerNoLayout");
-}
-if(this.nested){
-dojo.addClass(this.domNode,"dijitTabContainerNested");
-dojo.addClass(this.tablist.containerNode,"dijitTabContainerTabListNested");
-dojo.addClass(this.tablistSpacer,"dijitTabContainerSpacerNested");
-dojo.addClass(this.containerNode,"dijitTabPaneWrapperNested");
-}else{
-dojo.addClass(this.domNode,"tabStrip-"+(this.tabStrip?"enabled":"disabled"));
-}
-},_setupChild:function(_1){
-dojo.addClass(_1.domNode,"dijitTabPane");
-this.inherited(arguments);
-},startup:function(){
-if(this._started){
-return;
-}
-this.tablist.startup();
-this.inherited(arguments);
-},layout:function(){
-if(!this._contentBox||typeof (this._contentBox.l)=="undefined"){
-return;
-}
-var sc=this.selectedChildWidget;
-if(this.doLayout){
-var _2=this.tabPosition.replace(/-h/,"");
-this.tablist.layoutAlign=_2;
-var _3=[this.tablist,{domNode:this.tablistSpacer,layoutAlign:_2},{domNode:this.containerNode,layoutAlign:"client"}];
-dijit.layout.layoutChildren(this.domNode,this._contentBox,_3);
-this._containerContentBox=dijit.layout.marginBox2contentBox(this.containerNode,_3[2]);
-if(sc&&sc.resize){
-sc.resize(this._containerContentBox);
-}
-}else{
-if(this.tablist.resize){
-this.tablist.resize({w:dojo.contentBox(this.domNode).w});
-}
-if(sc&&sc.resize){
-sc.resize();
-}
-}
-},destroy:function(){
-if(this.tablist){
-this.tablist.destroy();
-}
-this.inherited(arguments);
-}});
-}
+
+dojo.declare("dijit.layout._TabContainerBase",
+	[dijit.layout.StackContainer, dijit._Templated],
+	{
+	// summary:
+	//		Abstract base class for TabContainer.   Must define _makeController() to instantiate
+	//		and return the widget that displays the tab labels
+	// description:
+	//		A TabContainer is a container that has multiple panes, but shows only
+	//		one pane at a time.  There are a set of tabs corresponding to each pane,
+	//		where each tab has the name (aka title) of the pane, and optionally a close button.
+
+	// tabPosition: String
+	//		Defines where tabs go relative to tab content.
+	//		"top", "bottom", "left-h", "right-h"
+	tabPosition: "top",
+
+	baseClass: "dijitTabContainer",
+
+	// tabStrip: Boolean
+	//		Defines whether the tablist gets an extra class for layouting, putting a border/shading
+	//		around the set of tabs.
+	tabStrip: false,
+
+	// nested: Boolean
+	//		If true, use styling for a TabContainer nested inside another TabContainer.
+	//		For tundra etc., makes tabs look like links, and hides the outer
+	//		border since the outer TabContainer already has a border.
+	nested: false,
+
+	templateString: dojo.cache("dijit.layout", "templates/TabContainer.html"),
+
+	postMixInProperties: function(){
+		// set class name according to tab position, ex: dijitTabContainerTop
+		this.baseClass += this.tabPosition.charAt(0).toUpperCase() + this.tabPosition.substr(1).replace(/-.*/, "");
+
+		this.srcNodeRef && dojo.style(this.srcNodeRef, "visibility", "hidden");
+
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+
+		// Create the tab list that will have a tab (a.k.a. tab button) for each tab panel
+		this.tablist = this._makeController(this.tablistNode);
+
+		if(!this.doLayout){ dojo.addClass(this.domNode, "dijitTabContainerNoLayout"); }
+
+		if(this.nested){
+			/* workaround IE's lack of support for "a > b" selectors by
+			 * tagging each node in the template.
+			 */
+			dojo.addClass(this.domNode, "dijitTabContainerNested");
+			dojo.addClass(this.tablist.containerNode, "dijitTabContainerTabListNested");
+			dojo.addClass(this.tablistSpacer, "dijitTabContainerSpacerNested");
+			dojo.addClass(this.containerNode, "dijitTabPaneWrapperNested");
+		}else{
+			dojo.addClass(this.domNode, "tabStrip-" + (this.tabStrip ? "enabled" : "disabled"));
+		}
+	},
+
+	_setupChild: function(/*dijit._Widget*/ tab){
+		// Overrides StackContainer._setupChild().
+		dojo.addClass(tab.domNode, "dijitTabPane");
+		this.inherited(arguments);
+	},
+
+	startup: function(){
+		if(this._started){ return; }
+
+		// wire up the tablist and its tabs
+		this.tablist.startup();
+
+		this.inherited(arguments);
+	},
+
+	layout: function(){
+		// Overrides StackContainer.layout().
+		// Configure the content pane to take up all the space except for where the tabs are
+
+		if(!this._contentBox || typeof(this._contentBox.l) == "undefined"){return;}
+
+		var sc = this.selectedChildWidget;
+
+		if(this.doLayout){
+			// position and size the titles and the container node
+			var titleAlign = this.tabPosition.replace(/-h/, "");
+			this.tablist.layoutAlign = titleAlign;
+			var children = [this.tablist, {
+				domNode: this.tablistSpacer,
+				layoutAlign: titleAlign
+			}, {
+				domNode: this.containerNode,
+				layoutAlign: "client"
+			}];
+			dijit.layout.layoutChildren(this.domNode, this._contentBox, children);
+
+			// Compute size to make each of my children.
+			// children[2] is the margin-box size of this.containerNode, set by layoutChildren() call above
+			this._containerContentBox = dijit.layout.marginBox2contentBox(this.containerNode, children[2]);
+
+			if(sc && sc.resize){
+				sc.resize(this._containerContentBox);
+			}
+		}else{
+			// just layout the tab controller, so it can position left/right buttons etc.
+			if(this.tablist.resize){
+				this.tablist.resize({w: dojo.contentBox(this.domNode).w});
+			}
+
+			// and call resize() on the selected pane just to tell it that it's been made visible
+			if(sc && sc.resize){
+				sc.resize();
+			}
+		}
+	},
+
+	destroy: function(){
+		if(this.tablist){
+			this.tablist.destroy();
+		}
+		this.inherited(arguments);
+	}
+});
+
diff --git a/dijit/layout/templates/AccordionButton.html b/dijit/layout/templates/AccordionButton.html
new file mode 100644
index 0000000..ca8c413
--- /dev/null
+++ b/dijit/layout/templates/AccordionButton.html
@@ -0,0 +1,10 @@
+<div dojoAttachEvent='onclick:_onTitleClick' class='dijitAccordionTitle'>
+	<div dojoAttachPoint='titleNode,focusNode' dojoAttachEvent='onkeypress:_onTitleKeyPress'
+			class='dijitAccordionTitleFocus' wairole="tab" waiState="expanded-false"
+		><span class='dijitInline dijitAccordionArrow' waiRole="presentation"></span
+		><span class='arrowTextUp' waiRole="presentation">+</span
+		><span class='arrowTextDown' waiRole="presentation">-</span
+		><img src="${_blankGif}" alt="" class="dijitIcon" dojoAttachPoint='iconNode' style="vertical-align: middle" waiRole="presentation"/>
+		<span waiRole="presentation" dojoAttachPoint='titleTextNode' class='dijitAccordionText'></span>
+	</div>
+</div>
diff --git a/dijit/layout/templates/ScrollingTabController.html b/dijit/layout/templates/ScrollingTabController.html
new file mode 100644
index 0000000..313f76b
--- /dev/null
+++ b/dijit/layout/templates/ScrollingTabController.html
@@ -0,0 +1,18 @@
+<div class="dijitTabListContainer-${tabPosition}" style="visibility:hidden">
+	<div dojoType="dijit.layout._ScrollingTabControllerButton"
+			class="tabStripButton-${tabPosition}"
+			id="${id}_menuBtn" iconClass="dijitTabStripMenuIcon"
+			dojoAttachPoint="_menuBtn" showLabel=false>▼</div>
+	<div dojoType="dijit.layout._ScrollingTabControllerButton"
+			class="tabStripButton-${tabPosition}"
+			id="${id}_leftBtn" iconClass="dijitTabStripSlideLeftIcon"
+			dojoAttachPoint="_leftBtn" dojoAttachEvent="onClick: doSlideLeft" showLabel=false>◀</div>
+	<div dojoType="dijit.layout._ScrollingTabControllerButton"
+			class="tabStripButton-${tabPosition}"
+			id="${id}_rightBtn" iconClass="dijitTabStripSlideRightIcon"
+			dojoAttachPoint="_rightBtn" dojoAttachEvent="onClick: doSlideRight" showLabel=false>▶</div>
+	<div class='dijitTabListWrapper' dojoAttachPoint='tablistWrapper'>
+		<div wairole='tablist' dojoAttachEvent='onkeypress:onkeypress'
+				dojoAttachPoint='containerNode' class='nowrapTabStrip'></div>
+	</div>
+</div>
\ No newline at end of file
diff --git a/dijit/layout/templates/TabContainer.html b/dijit/layout/templates/TabContainer.html
new file mode 100644
index 0000000..d6dcf69
--- /dev/null
+++ b/dijit/layout/templates/TabContainer.html
@@ -0,0 +1,5 @@
+<div class="dijitTabContainer">
+	<div class="dijitTabListWrapper" dojoAttachPoint="tablistNode"></div>
+	<div dojoAttachPoint="tablistSpacer" class="dijitTabSpacer ${baseClass}-spacer"></div>
+	<div class="dijitTabPaneWrapper ${baseClass}-container" dojoAttachPoint="containerNode"></div>
+</div>
diff --git a/dijit/layout/templates/_ScrollingTabControllerButton.html b/dijit/layout/templates/_ScrollingTabControllerButton.html
new file mode 100644
index 0000000..2846c18
--- /dev/null
+++ b/dijit/layout/templates/_ScrollingTabControllerButton.html
@@ -0,0 +1,8 @@
+<div dojoAttachEvent="onclick:_onButtonClick">
+	<div waiRole="presentation" class="dijitTabInnerDiv" dojoattachpoint="innerDiv,focusNode">
+		<div waiRole="presentation" class="dijitTabContent dijitButtonContents" dojoattachpoint="tabContent">
+			<img waiRole="presentation" alt="" src="${_blankGif}" class="dijitTabStripIcon" dojoAttachPoint="iconNode"/>
+			<span dojoAttachPoint="containerNode,titleNode" class="dijitButtonText"></span>
+		</div>
+	</div>
+</div>
\ No newline at end of file
diff --git a/dijit/layout/templates/_TabButton.html b/dijit/layout/templates/_TabButton.html
new file mode 100644
index 0000000..42b968c
--- /dev/null
+++ b/dijit/layout/templates/_TabButton.html
@@ -0,0 +1,14 @@
+<div waiRole="presentation" dojoAttachPoint="titleNode" dojoAttachEvent='onclick:onClick'>
+    <div waiRole="presentation" class='dijitTabInnerDiv' dojoAttachPoint='innerDiv'>
+        <div waiRole="presentation" class='dijitTabContent' dojoAttachPoint='tabContent'>
+        	<div waiRole="presentation" dojoAttachPoint='focusNode'>
+		        <img src="${_blankGif}" alt="" class="dijitIcon" dojoAttachPoint='iconNode' />
+		        <span dojoAttachPoint='containerNode' class='tabLabel'></span>
+		        <span class="dijitInline dijitTabCloseButton dijitTabCloseIcon" dojoAttachPoint='closeNode'
+		        		dojoAttachEvent='onclick: onClickCloseButton' waiRole="presentation">
+		            <span dojoAttachPoint='closeText' class='dijitTabCloseText'>x</span
+		        ></span>
+			</div>
+        </div>
+    </div>
+</div>
diff --git a/dijit/nls/ar/common.js b/dijit/nls/ar/common.js
index 99af508..fd6eb5b 100644
--- a/dijit/nls/ar/common.js
+++ b/dijit/nls/ar/common.js
@@ -1 +1,6 @@
-({"buttonOk":"حسنا","buttonCancel":"الغاء","buttonSave":"حفظ","itemClose":"اغلاق"})
\ No newline at end of file
+({
+	buttonOk: "حسنا",
+	buttonCancel: "الغاء",
+	buttonSave: "حفظ",
+	itemClose: "اغلاق"
+})
diff --git a/dijit/nls/ar/loading.js b/dijit/nls/ar/loading.js
index f8bb535..e910036 100644
--- a/dijit/nls/ar/loading.js
+++ b/dijit/nls/ar/loading.js
@@ -1 +1,4 @@
-({"loadingState":"جاري التحميل...","errorState":"عفوا، حدث خطأ"})
\ No newline at end of file
+({
+	loadingState: "جاري التحميل...",
+	errorState: "عفوا، حدث خطأ"
+})
diff --git a/dijit/nls/ca/common.js b/dijit/nls/ca/common.js
index b9cd065..6c556d8 100644
--- a/dijit/nls/ca/common.js
+++ b/dijit/nls/ca/common.js
@@ -1 +1,7 @@
-({"buttonOk":"D'acord","buttonCancel":"Cancel·la","buttonSave":"Desa","itemClose":"Tanca"})
\ No newline at end of file
+({
+	buttonOk: "D'acord",
+	buttonCancel: "Cancel·la",
+	buttonSave: "Desa",
+	itemClose: "Tanca"
+})
+
diff --git a/dijit/nls/ca/loading.js b/dijit/nls/ca/loading.js
index cd368cc..4399fa2 100644
--- a/dijit/nls/ca/loading.js
+++ b/dijit/nls/ca/loading.js
@@ -1 +1,5 @@
-({"loadingState":"S'està carregant...","errorState":"Ens sap greu. S'ha produït un error."})
\ No newline at end of file
+({
+	loadingState: "S'està carregant...",
+	errorState: "Ens sap greu. S'ha produït un error."
+})
+
diff --git a/dijit/nls/common.js b/dijit/nls/common.js
index 6573dcd..4625cca 100644
--- a/dijit/nls/common.js
+++ b/dijit/nls/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Cancel","buttonSave":"Save","itemClose":"Close"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Cancel",
+	buttonSave: "Save",
+	itemClose: "Close"
+})
diff --git a/dijit/nls/cs/common.js b/dijit/nls/cs/common.js
index 83b3682..6ca9673 100644
--- a/dijit/nls/cs/common.js
+++ b/dijit/nls/cs/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Storno","buttonSave":"Uložit","itemClose":"Zavřít"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Storno",
+	buttonSave: "Uložit",
+	itemClose: "Zavřít"
+})
diff --git a/dijit/nls/cs/loading.js b/dijit/nls/cs/loading.js
index c611926..bcd5e96 100644
--- a/dijit/nls/cs/loading.js
+++ b/dijit/nls/cs/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Probíhá načítání...","errorState":"Omlouváme se, došlo k chybě"})
\ No newline at end of file
+({
+	loadingState: "Probíhá načítání...",
+	errorState: "Omlouváme se, došlo k chybě"
+})
diff --git a/dijit/nls/da/common.js b/dijit/nls/da/common.js
index 8c51ed8..ca4787f 100644
--- a/dijit/nls/da/common.js
+++ b/dijit/nls/da/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Annullér","buttonSave":"Gem","itemClose":"Luk"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Annullér",
+	buttonSave: "Gem",
+	itemClose: "Luk"
+})
diff --git a/dijit/nls/da/loading.js b/dijit/nls/da/loading.js
index 5088eaf..f00490e 100644
--- a/dijit/nls/da/loading.js
+++ b/dijit/nls/da/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Indlæser...","errorState":"Der er opstået en fejl"})
\ No newline at end of file
+({
+	loadingState: "Indlæser...",
+	errorState: "Der er opstået en fejl"
+})
diff --git a/dijit/nls/de/common.js b/dijit/nls/de/common.js
old mode 100644
new mode 100755
index cd60c45..9830c21
--- a/dijit/nls/de/common.js
+++ b/dijit/nls/de/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Abbrechen","buttonSave":"Speichern","itemClose":"Schließen"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Abbrechen",
+	buttonSave: "Speichern",
+	itemClose: "Schließen"
+})
diff --git a/dijit/nls/de/loading.js b/dijit/nls/de/loading.js
index 4989983..3945c4f 100644
--- a/dijit/nls/de/loading.js
+++ b/dijit/nls/de/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Wird geladen...","errorState":"Es ist ein Fehler aufgetreten."})
\ No newline at end of file
+({
+	loadingState: "Wird geladen...",
+	errorState: "Es ist ein Fehler aufgetreten."
+})
diff --git a/dijit/nls/dijit-all_ROOT.js b/dijit/nls/dijit-all_ROOT.js
deleted file mode 100644
index 68fec9e..0000000
--- a/dijit/nls/dijit-all_ROOT.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_ROOT");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.ROOT");dojo.nls.colors.ROOT={"lightsteelblue":"light steel blue","orangered":"orange red","midnightblue":"midnight blue","cadetblue":"cadet blue","seashell":"seashell","slategrey":"slate gray","coral":"coral","darkturquoise":"dark turquoise","antiquewhite":"antique white","mediumspringgreen":"medium spring green","salmon":"salmon","darkgrey":"dark gray","ivor [...]
diff --git a/dijit/nls/dijit-all_ar.js b/dijit/nls/dijit-all_ar.js
deleted file mode 100644
index e09c642..0000000
--- a/dijit/nls/dijit-all_ar.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_ar");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.ar");dojo.nls.colors.ar={"lightsteelblue":"أزرق معدني فاتح","orangered":"أحمر مائل للبرتقالي","midnightblue":"أزرق بحري","cadetblue":"أزرق ملون بالرمادي","seashell":"أبيض مائل للأصفر فاتح","slategrey":"رمادي اردوازي","coral":"مرجاني","darkturquoise":"تركواز داكن","antiquewhite":"أبيض عتيق","mediumspringgreen":"أخضر ربيعي متوسط","salmon":"برتقالي وردي شاحب","dar [...]
diff --git a/dijit/nls/dijit-all_ca.js b/dijit/nls/dijit-all_ca.js
deleted file mode 100644
index 43c19b4..0000000
--- a/dijit/nls/dijit-all_ca.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_ca");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.ca");dojo.nls.colors.ca={"lightsteelblue":"blau acer clar","orangered":"taronja vermellós","midnightblue":"blau mitjanit","cadetblue":"blau marí","seashell":"petxina marina","slategrey":"gris pissarra","coral":"corall","darkturquoise":"turquesa fosc","antiquewhite":"blanc antic","mediumspringgreen":"verd primavera mitjà","salmon":"salmó","darkgrey":"gris fosc", [...]
diff --git a/dijit/nls/dijit-all_cs.js b/dijit/nls/dijit-all_cs.js
deleted file mode 100644
index e23f7e9..0000000
--- a/dijit/nls/dijit-all_cs.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_cs");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.cs");dojo.nls.colors.cs={"lightsteelblue":"světlá ocelová modrá","orangered":"oranžovočervená","midnightblue":"temně modrá","cadetblue":"šedomodrá","seashell":"lasturová","slategrey":"břidlicová šedá","coral":"korálová červená","darkturquoise":"tmavě tyrkysová","antiquewhite":"krémově bílá","mediumspringgreen":"střední jarní zelená","salmon":"lososová","darkgre [...]
diff --git a/dijit/nls/dijit-all_da.js b/dijit/nls/dijit-all_da.js
deleted file mode 100644
index d0e570e..0000000
--- a/dijit/nls/dijit-all_da.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_da");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.da");dojo.nls.colors.da={"lightsteelblue":"lys stålblå","orangered":"orangerød","midnightblue":"midnatsblå","cadetblue":"kadetblå","seashell":"muslingeskal","slategrey":"skifergrå","coral":"koralrød","darkturquoise":"mørk turkis","antiquewhite":"antikhvid","mediumspringgreen":"mellemforårsgrøn","salmon":"laksefarvet","darkgrey":"mørkegrå","ivory":"elfenben","gr [...]
diff --git a/dijit/nls/dijit-all_de-de.js b/dijit/nls/dijit-all_de-de.js
deleted file mode 100644
index 940b38d..0000000
--- a/dijit/nls/dijit-all_de-de.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_de-de");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.de_de");dojo.nls.colors.de_de={"lightsteelblue":"Helles Stahlblau","orangered":"Orangerot","midnightblue":"Mitternachtblau","cadetblue":"Kadettenblau","seashell":"Muschelweiß","slategrey":"Schiefergrau","coral":"Koralle","darkturquoise":"Dunkeltürkis","antiquewhite":"Antikweiß","mediumspringgreen":"Mittelfrühlingsgrün","salmon":"Lachs","darkgrey":"Dunkelgrau [...]
diff --git a/dijit/nls/dijit-all_de.js b/dijit/nls/dijit-all_de.js
deleted file mode 100644
index aaeeaae..0000000
--- a/dijit/nls/dijit-all_de.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_de");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.de");dojo.nls.colors.de={"lightsteelblue":"Helles Stahlblau","orangered":"Orangerot","midnightblue":"Mitternachtblau","cadetblue":"Kadettenblau","seashell":"Muschelweiß","slategrey":"Schiefergrau","coral":"Koralle","darkturquoise":"Dunkeltürkis","antiquewhite":"Antikweiß","mediumspringgreen":"Mittelfrühlingsgrün","salmon":"Lachs","darkgrey":"Dunkelgrau","ivory" [...]
diff --git a/dijit/nls/dijit-all_el.js b/dijit/nls/dijit-all_el.js
deleted file mode 100644
index 9ecdc94..0000000
--- a/dijit/nls/dijit-all_el.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_el");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.el");dojo.nls.colors.el={"lightsteelblue":"ανοιχτό μπλε ατσαλιού","orangered":"πορτοκαλοκόκκινο","midnightblue":"πολύ σκούρο μπλε","cadetblue":"μπλε του στρατού","seashell":"κοχύλι","slategrey":"μεταλλικό γκρι","coral":"κοραλί","darkturquoise":"σκούρο τυρκουάζ","antiquewhite":"ξεθωριασμένο λευκό","mediumspringgreen":"μεσαίο πράσινο της άνοιξης","salmon":"σομόν" [...]
diff --git a/dijit/nls/dijit-all_en-gb.js b/dijit/nls/dijit-all_en-gb.js
deleted file mode 100644
index 2d84e28..0000000
--- a/dijit/nls/dijit-all_en-gb.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_en-gb");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.en_gb");dojo.nls.colors.en_gb={"lightsteelblue":"light steel blue","orangered":"orange red","midnightblue":"midnight blue","cadetblue":"cadet blue","seashell":"seashell","slategrey":"slate gray","coral":"coral","darkturquoise":"dark turquoise","antiquewhite":"antique white","mediumspringgreen":"medium spring green","salmon":"salmon","darkgrey":"dark gray","i [...]
diff --git a/dijit/nls/dijit-all_en-us.js b/dijit/nls/dijit-all_en-us.js
deleted file mode 100644
index ace1591..0000000
--- a/dijit/nls/dijit-all_en-us.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_en-us");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.en_us");dojo.nls.colors.en_us={"lightsteelblue":"light steel blue","orangered":"orange red","midnightblue":"midnight blue","cadetblue":"cadet blue","seashell":"seashell","slategrey":"slate gray","coral":"coral","darkturquoise":"dark turquoise","antiquewhite":"antique white","mediumspringgreen":"medium spring green","salmon":"salmon","darkgrey":"dark gray","i [...]
diff --git a/dijit/nls/dijit-all_en.js b/dijit/nls/dijit-all_en.js
deleted file mode 100644
index c4e2f4d..0000000
--- a/dijit/nls/dijit-all_en.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_en");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.en");dojo.nls.colors.en={"lightsteelblue":"light steel blue","orangered":"orange red","midnightblue":"midnight blue","cadetblue":"cadet blue","seashell":"seashell","slategrey":"slate gray","coral":"coral","darkturquoise":"dark turquoise","antiquewhite":"antique white","mediumspringgreen":"medium spring green","salmon":"salmon","darkgrey":"dark gray","ivory":"iv [...]
diff --git a/dijit/nls/dijit-all_es-es.js b/dijit/nls/dijit-all_es-es.js
deleted file mode 100644
index e0eb71a..0000000
--- a/dijit/nls/dijit-all_es-es.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_es-es");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.es_es");dojo.nls.colors.es_es={"lightsteelblue":"azul acero claro","orangered":"rojo anaranjado","midnightblue":"azul medianoche","cadetblue":"azul cadete","seashell":"blanco marfil","slategrey":"gris pizarra","coral":"coral","darkturquoise":"turquesa oscuro","antiquewhite":"blanco antiguo","mediumspringgreen":"verde primavera medio","salmon":"salmón","darkg [...]
diff --git a/dijit/nls/dijit-all_es.js b/dijit/nls/dijit-all_es.js
deleted file mode 100644
index ff7f2f1..0000000
--- a/dijit/nls/dijit-all_es.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_es");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.es");dojo.nls.colors.es={"lightsteelblue":"azul acero claro","orangered":"rojo anaranjado","midnightblue":"azul medianoche","cadetblue":"azul cadete","seashell":"blanco marfil","slategrey":"gris pizarra","coral":"coral","darkturquoise":"turquesa oscuro","antiquewhite":"blanco antiguo","mediumspringgreen":"verde primavera medio","salmon":"salmón","darkgrey":"gri [...]
diff --git a/dijit/nls/dijit-all_fi-fi.js b/dijit/nls/dijit-all_fi-fi.js
deleted file mode 100644
index 17a0507..0000000
--- a/dijit/nls/dijit-all_fi-fi.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_fi-fi");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.fi_fi");dojo.nls.colors.fi_fi={"lightsteelblue":"light steel blue","orangered":"orange red","midnightblue":"midnight blue","cadetblue":"cadet blue","seashell":"seashell","slategrey":"slate gray","coral":"coral","darkturquoise":"dark turquoise","antiquewhite":"antique white","mediumspringgreen":"medium spring green","salmon":"salmon","darkgrey":"dark gray","i [...]
diff --git a/dijit/nls/dijit-all_fi.js b/dijit/nls/dijit-all_fi.js
deleted file mode 100644
index c9b83e8..0000000
--- a/dijit/nls/dijit-all_fi.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_fi");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.fi");dojo.nls.colors.fi={"lightsteelblue":"light steel blue","orangered":"orange red","midnightblue":"midnight blue","cadetblue":"cadet blue","seashell":"seashell","slategrey":"slate gray","coral":"coral","darkturquoise":"dark turquoise","antiquewhite":"antique white","mediumspringgreen":"medium spring green","salmon":"salmon","darkgrey":"dark gray","ivory":"iv [...]
diff --git a/dijit/nls/dijit-all_fr-fr.js b/dijit/nls/dijit-all_fr-fr.js
deleted file mode 100644
index c992592..0000000
--- a/dijit/nls/dijit-all_fr-fr.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_fr-fr");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.fr_fr");dojo.nls.colors.fr_fr={"lightsteelblue":"bleu acier clair","orangered":"rouge orangé","midnightblue":"bleu nuit","cadetblue":"bleu pétrole","seashell":"coquillage","slategrey":"gris ardoise","coral":"corail","darkturquoise":"turquoise foncé","antiquewhite":"blanc antique","mediumspringgreen":"vert printemps moyen","salmon":"saumon","darkgrey":"gris f [...]
diff --git a/dijit/nls/dijit-all_fr.js b/dijit/nls/dijit-all_fr.js
deleted file mode 100644
index c9afe60..0000000
--- a/dijit/nls/dijit-all_fr.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_fr");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.fr");dojo.nls.colors.fr={"lightsteelblue":"bleu acier clair","orangered":"rouge orangé","midnightblue":"bleu nuit","cadetblue":"bleu pétrole","seashell":"coquillage","slategrey":"gris ardoise","coral":"corail","darkturquoise":"turquoise foncé","antiquewhite":"blanc antique","mediumspringgreen":"vert printemps moyen","salmon":"saumon","darkgrey":"gris foncé","iv [...]
diff --git a/dijit/nls/dijit-all_he-il.js b/dijit/nls/dijit-all_he-il.js
deleted file mode 100644
index 19f78a6..0000000
--- a/dijit/nls/dijit-all_he-il.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_he-il");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.he_il");dojo.nls.colors.he_il={"lightsteelblue":"כחול פלדה בהיר","orangered":"כתום אדום","midnightblue":"כחול כהה","cadetblue":"כחול ים","seashell":"צדף","slategrey":"אפור צפחה","coral":"אלמוג","darkturquoise":"טורקיז כהה","antiquewhite":"לבן עתיק","mediumspringgreen":"ירוק אביב בינוני","salmon":"סלמון","darkgrey":"אפור כהה","ivory":"שנהב","greenyellow":"ירו [...]
diff --git a/dijit/nls/dijit-all_he.js b/dijit/nls/dijit-all_he.js
deleted file mode 100644
index b3505a4..0000000
--- a/dijit/nls/dijit-all_he.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_he");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.he");dojo.nls.colors.he={"lightsteelblue":"כחול פלדה בהיר","orangered":"כתום אדום","midnightblue":"כחול כהה","cadetblue":"כחול ים","seashell":"צדף","slategrey":"אפור צפחה","coral":"אלמוג","darkturquoise":"טורקיז כהה","antiquewhite":"לבן עתיק","mediumspringgreen":"ירוק אביב בינוני","salmon":"סלמון","darkgrey":"אפור כהה","ivory":"שנהב","greenyellow":"ירוק-צהוב"," [...]
diff --git a/dijit/nls/dijit-all_hu.js b/dijit/nls/dijit-all_hu.js
deleted file mode 100644
index 10e395f..0000000
--- a/dijit/nls/dijit-all_hu.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_hu");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.hu");dojo.nls.colors.hu={"lightsteelblue":"világos acélkék","orangered":"narancsvörös","midnightblue":"éjkék","cadetblue":"kadétkék","seashell":"kagyló","slategrey":"palaszürke","coral":"korall","darkturquoise":"sötét türkizkék","antiquewhite":"antik fehér","mediumspringgreen":"közepes tavaszzöld","salmon":"lazacszín","darkgrey":"sötétszürke","ivory":"elefántcs [...]
diff --git a/dijit/nls/dijit-all_it-it.js b/dijit/nls/dijit-all_it-it.js
deleted file mode 100644
index 5321ffd..0000000
--- a/dijit/nls/dijit-all_it-it.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_it-it");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.it_it");dojo.nls.colors.it_it={"lightsteelblue":"blu acciao chiaro","orangered":"vermiglio","midnightblue":"blu melanzana scuro","cadetblue":"verde acqua","seashell":"sabbia rosa","slategrey":"grigio ardesia","coral":"corallo","darkturquoise":"turchese scuro","antiquewhite":"bianco antico","mediumspringgreen":"verde primavera medio","salmon":"salmone","darkg [...]
diff --git a/dijit/nls/dijit-all_it.js b/dijit/nls/dijit-all_it.js
deleted file mode 100644
index ec68ba4..0000000
--- a/dijit/nls/dijit-all_it.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_it");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.it");dojo.nls.colors.it={"lightsteelblue":"blu acciao chiaro","orangered":"vermiglio","midnightblue":"blu melanzana scuro","cadetblue":"verde acqua","seashell":"sabbia rosa","slategrey":"grigio ardesia","coral":"corallo","darkturquoise":"turchese scuro","antiquewhite":"bianco antico","mediumspringgreen":"verde primavera medio","salmon":"salmone","darkgrey":"gri [...]
diff --git a/dijit/nls/dijit-all_ja-jp.js b/dijit/nls/dijit-all_ja-jp.js
deleted file mode 100644
index 44ed3d7..0000000
--- a/dijit/nls/dijit-all_ja-jp.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_ja-jp");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.ja_jp");dojo.nls.colors.ja_jp={"lightsteelblue":"ライト・スチール・ブルー","orangered":"オレンジ・レッド","midnightblue":"ミッドナイト・ブルー","cadetblue":"くすんだ青","seashell":"シーシェル","slategrey":"スレート・グレイ","coral":"珊瑚","darkturquoise":"ダーク・ターコイズ","antiquewhite":"アンティーク・ホワイト","mediumspringgreen":"ミディアム・スプリング・グリーン","salmon":"サーモン","darkgrey":"ダーク・グレイ","ivory":"アイボリー","greenyellow":"緑黄色","m [...]
diff --git a/dijit/nls/dijit-all_ja.js b/dijit/nls/dijit-all_ja.js
deleted file mode 100644
index 913c2bb..0000000
--- a/dijit/nls/dijit-all_ja.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_ja");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.ja");dojo.nls.colors.ja={"lightsteelblue":"ライト・スチール・ブルー","orangered":"オレンジ・レッド","midnightblue":"ミッドナイト・ブルー","cadetblue":"くすんだ青","seashell":"シーシェル","slategrey":"スレート・グレイ","coral":"珊瑚","darkturquoise":"ダーク・ターコイズ","antiquewhite":"アンティーク・ホワイト","mediumspringgreen":"ミディアム・スプリング・グリーン","salmon":"サーモン","darkgrey":"ダーク・グレイ","ivory":"アイボリー","greenyellow":"緑黄色","mistyrose" [...]
diff --git a/dijit/nls/dijit-all_ko-kr.js b/dijit/nls/dijit-all_ko-kr.js
deleted file mode 100644
index f8c8a2a..0000000
--- a/dijit/nls/dijit-all_ko-kr.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_ko-kr");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.ko_kr");dojo.nls.colors.ko_kr={"lightsteelblue":"라이트 스틸 블루(light steel blue)","orangered":"오렌지 레드(orange red)","midnightblue":"미드나잇 블루(midnight blue)","cadetblue":"카뎃 블루(cadet blue)","seashell":"씨쉘(seashell)","slategrey":"슬레이트 그레이(slate gray)","coral":"코랄(coral)","darkturquoise":"다크 터콰즈(dark turquoise)","antiquewhite":"앤틱 화이트(antique white)","mediumspringgre [...]
diff --git a/dijit/nls/dijit-all_ko.js b/dijit/nls/dijit-all_ko.js
deleted file mode 100644
index 910e2ff..0000000
--- a/dijit/nls/dijit-all_ko.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_ko");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.ko");dojo.nls.colors.ko={"lightsteelblue":"라이트 스틸 블루(light steel blue)","orangered":"오렌지 레드(orange red)","midnightblue":"미드나잇 블루(midnight blue)","cadetblue":"카뎃 블루(cadet blue)","seashell":"씨쉘(seashell)","slategrey":"슬레이트 그레이(slate gray)","coral":"코랄(coral)","darkturquoise":"다크 터콰즈(dark turquoise)","antiquewhite":"앤틱 화이트(antique white)","mediumspringgreen":"미디엄  [...]
diff --git a/dijit/nls/dijit-all_nb.js b/dijit/nls/dijit-all_nb.js
deleted file mode 100644
index 49ac970..0000000
--- a/dijit/nls/dijit-all_nb.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_nb");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.nb");dojo.nls.colors.nb={"lightsteelblue":"lys stålblå","orangered":"rødoransje","midnightblue":"midnattsblå","cadetblue":"mørk grønnblå","seashell":"skjellhvit","slategrey":"skifergrå","coral":"korall","darkturquoise":"mørk turkis","antiquewhite":"antikk hvit","mediumspringgreen":"middels vårgrønn","salmon":"lakserosa","darkgrey":"mørk grå","ivory":"elfenbensh [...]
diff --git a/dijit/nls/dijit-all_nl-nl.js b/dijit/nls/dijit-all_nl-nl.js
deleted file mode 100644
index 2c3d26b..0000000
--- a/dijit/nls/dijit-all_nl-nl.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_nl-nl");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.nl_nl");dojo.nls.colors.nl_nl={"lightsteelblue":"lichtstaalblauw","orangered":"oranjerood","midnightblue":"nachtblauw","cadetblue":"donkerstaalblauw","seashell":"schelp","slategrey":"leigrijs","coral":"koraalrood","darkturquoise":"donkerturquoise","antiquewhite":"antiekwit","mediumspringgreen":"midlentegroen","salmon":"zalm","darkgrey":"donkergrijs","ivory": [...]
diff --git a/dijit/nls/dijit-all_nl.js b/dijit/nls/dijit-all_nl.js
deleted file mode 100644
index 2234289..0000000
--- a/dijit/nls/dijit-all_nl.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_nl");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.nl");dojo.nls.colors.nl={"lightsteelblue":"lichtstaalblauw","orangered":"oranjerood","midnightblue":"nachtblauw","cadetblue":"donkerstaalblauw","seashell":"schelp","slategrey":"leigrijs","coral":"koraalrood","darkturquoise":"donkerturquoise","antiquewhite":"antiekwit","mediumspringgreen":"midlentegroen","salmon":"zalm","darkgrey":"donkergrijs","ivory":"ivoorwit [...]
diff --git a/dijit/nls/dijit-all_pl.js b/dijit/nls/dijit-all_pl.js
deleted file mode 100644
index dba9a3b..0000000
--- a/dijit/nls/dijit-all_pl.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_pl");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.pl");dojo.nls.colors.pl={"lightsteelblue":"jasny stalowoniebieski","orangered":"pomarańczowoczerwony","midnightblue":"ciemnogranatowy","cadetblue":"niebieskoszary","seashell":"muszla","slategrey":"łupkowy szary","coral":"koralowy","darkturquoise":"ciemnoturkusowy","antiquewhite":"biel antyczna","mediumspringgreen":"średnia wiosenna zieleń","salmon":"łososiowy", [...]
diff --git a/dijit/nls/dijit-all_pt-br.js b/dijit/nls/dijit-all_pt-br.js
deleted file mode 100644
index d448c14..0000000
--- a/dijit/nls/dijit-all_pt-br.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_pt-br");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.pt_br");dojo.nls.colors.pt_br={"lightsteelblue":"azul-aço claro","orangered":"vermelho alaranjado","midnightblue":"azul meia-noite","cadetblue":"azul cadet","seashell":"seashell","slategrey":"cinza-ardósia","coral":"coral","darkturquoise":"turquesa escuro","antiquewhite":"branco antigo","mediumspringgreen":"verde-primavera médio","salmon":"salmão","darkgrey" [...]
diff --git a/dijit/nls/dijit-all_pt-pt.js b/dijit/nls/dijit-all_pt-pt.js
deleted file mode 100644
index a3ffb19..0000000
--- a/dijit/nls/dijit-all_pt-pt.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_pt-pt");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.pt_pt");dojo.nls.colors.pt_pt={"lightsteelblue":"azul-aço claro","orangered":"vermelho alaranjado","midnightblue":"azul meia-noite","cadetblue":"azul cadete","seashell":"concha","slategrey":"cinzento ardósia","coral":"coral","darkturquoise":"turquesa escuro","antiquewhite":"branco antigo","mediumspringgreen":"verde primavera médio","salmon":"salmão","darkgre [...]
diff --git a/dijit/nls/dijit-all_pt.js b/dijit/nls/dijit-all_pt.js
deleted file mode 100644
index 43df341..0000000
--- a/dijit/nls/dijit-all_pt.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_pt");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.pt");dojo.nls.colors.pt={"lightsteelblue":"azul-aço claro","orangered":"vermelho alaranjado","midnightblue":"azul meia-noite","cadetblue":"azul cadet","seashell":"seashell","slategrey":"cinza-ardósia","coral":"coral","darkturquoise":"turquesa escuro","antiquewhite":"branco antigo","mediumspringgreen":"verde-primavera médio","salmon":"salmão","darkgrey":"cinza e [...]
diff --git a/dijit/nls/dijit-all_ru.js b/dijit/nls/dijit-all_ru.js
deleted file mode 100644
index 1a86051..0000000
--- a/dijit/nls/dijit-all_ru.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_ru");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.ru");dojo.nls.colors.ru={"lightsteelblue":"светлый стальной","orangered":"оранжево-красный","midnightblue":"полуночно-синий","cadetblue":"серо-синий","seashell":"морская раковина","slategrey":"грифельно-серый","coral":"коралловый","darkturquoise":"темный бирюзовый","antiquewhite":"белый антик","mediumspringgreen":"нейтральный весенне-зеленый","salmon":"лососевы [...]
diff --git a/dijit/nls/dijit-all_sk.js b/dijit/nls/dijit-all_sk.js
deleted file mode 100644
index 2539608..0000000
--- a/dijit/nls/dijit-all_sk.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_sk");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.sk");dojo.nls.colors.sk={"lightsteelblue":"oceľovo modrá svetlá","orangered":"oranžovo červená","midnightblue":"nočná modrá","cadetblue":"sivomodrá","seashell":"lastúrová","slategrey":"bridlicová sivá","coral":"koralová","darkturquoise":"tyrkysová tmavá","antiquewhite":"antická biela","mediumspringgreen":"jarná zelená stredná","salmon":"lososovo ružová","darkgr [...]
diff --git a/dijit/nls/dijit-all_sl.js b/dijit/nls/dijit-all_sl.js
deleted file mode 100644
index 9169d1b..0000000
--- a/dijit/nls/dijit-all_sl.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_sl");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.sl");dojo.nls.colors.sl={"lightsteelblue":"svetlo jeklena modra","orangered":"oranžno-rdeča","midnightblue":"polnočno modra","cadetblue":"zelenkasto modra","seashell":"morska školjka","slategrey":"skrilasto siva","coral":"koralna","darkturquoise":"temno turkizna","antiquewhite":"antično bela","mediumspringgreen":"srednje pomladno zelena","salmon":"lososova","da [...]
diff --git a/dijit/nls/dijit-all_sv.js b/dijit/nls/dijit-all_sv.js
deleted file mode 100644
index 6c81e26..0000000
--- a/dijit/nls/dijit-all_sv.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_sv");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.sv");dojo.nls.colors.sv={"lightsteelblue":"ljust stålblått","orangered":"orangerött","midnightblue":"midnattsblått","cadetblue":"kadettblått","seashell":"snäckskal","slategrey":"skiffergrått","coral":"korall","darkturquoise":"mörkturkost","antiquewhite":"antikvitt","mediumspringgreen":"mellanvårgrönt","salmon":"laxfärgat","darkgrey":"mörkgrått","ivory":"elfenbe [...]
diff --git a/dijit/nls/dijit-all_th.js b/dijit/nls/dijit-all_th.js
deleted file mode 100644
index 594ebdd..0000000
--- a/dijit/nls/dijit-all_th.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_th");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.th");dojo.nls.colors.th={"lightsteelblue":"light steel blue","orangered":"ส้มแกมแดง","midnightblue":"midnight blue","cadetblue":"cadet blue","seashell":"seashell","slategrey":"slate gray","coral":"coral","darkturquoise":"dark turquoise","antiquewhite":"antique white","mediumspringgreen":"medium spring green","salmon":"salmon","darkgrey":"เทาเข้ม","ivory":"งาช้า [...]
diff --git a/dijit/nls/dijit-all_tr.js b/dijit/nls/dijit-all_tr.js
deleted file mode 100644
index 8cd5efe..0000000
--- a/dijit/nls/dijit-all_tr.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_tr");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.tr");dojo.nls.colors.tr={"lightsteelblue":"açık metalik mavi","orangered":"turuncu kırmızı","midnightblue":"gece mavisi","cadetblue":"denizci mavisi","seashell":"deniz kabuğu","slategrey":"arduvaz grisi","coral":"mercan","darkturquoise":"koyu turkuaz","antiquewhite":"antik beyaz","mediumspringgreen":"orta bahar yeşili","salmon":"somon","darkgrey":"koyu gri","iv [...]
diff --git a/dijit/nls/dijit-all_xx.js b/dijit/nls/dijit-all_xx.js
deleted file mode 100644
index 549bf3e..0000000
--- a/dijit/nls/dijit-all_xx.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_xx");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.xx");dojo.nls.colors.xx={"lightsteelblue":"light steel blue","orangered":"orange red","midnightblue":"midnight blue","cadetblue":"cadet blue","seashell":"seashell","slategrey":"slate gray","coral":"coral","darkturquoise":"dark turquoise","antiquewhite":"antique white","mediumspringgreen":"medium spring green","salmon":"salmon","darkgrey":"dark gray","ivory":"iv [...]
diff --git a/dijit/nls/dijit-all_zh-cn.js b/dijit/nls/dijit-all_zh-cn.js
deleted file mode 100644
index aa00dec..0000000
--- a/dijit/nls/dijit-all_zh-cn.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_zh-cn");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.zh_cn");dojo.nls.colors.zh_cn={"lightsteelblue":"浅钢蓝色","orangered":"橙红色","midnightblue":"深蓝色","cadetblue":"灰蓝色","seashell":"海贝色","slategrey":"灰石色","coral":"珊瑚色","darkturquoise":"深粉蓝","antiquewhite":"古董白","mediumspringgreen":"间春绿色","salmon":"橙红","darkgrey":"深灰色","ivory":"象牙色","greenyellow":"绿黄色","mistyrose":"浅玫瑰色","lightsalmon":"淡橙色","silver":"银白色","dimgrey": [...]
diff --git a/dijit/nls/dijit-all_zh-tw.js b/dijit/nls/dijit-all_zh-tw.js
deleted file mode 100644
index 9136376..0000000
--- a/dijit/nls/dijit-all_zh-tw.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_zh-tw");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.zh_tw");dojo.nls.colors.zh_tw={"lightsteelblue":"淡鐵藍色","orangered":"橙紅色","midnightblue":"午夜藍","cadetblue":"軍服藍","seashell":"海貝色","slategrey":"岩灰色","coral":"珊瑚紅","darkturquoise":"暗松石綠","antiquewhite":"米白色","mediumspringgreen":"中春綠色","salmon":"鮭紅色","darkgrey":"暗灰色","ivory":"象牙色","greenyellow":"綠黃色","mistyrose":"霧玫瑰色","lightsalmon":"淡鮭紅","silver":"銀色","dimgrey" [...]
diff --git a/dijit/nls/dijit-all_zh.js b/dijit/nls/dijit-all_zh.js
deleted file mode 100644
index f0517ed..0000000
--- a/dijit/nls/dijit-all_zh.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dijit.nls.dijit-all_zh");dojo.provide("dojo.nls.colors");dojo.nls.colors._built=true;dojo.provide("dojo.nls.colors.zh");dojo.nls.colors.zh={"lightsteelblue":"浅钢蓝色","orangered":"橙红色","midnightblue":"深蓝色","cadetblue":"灰蓝色","seashell":"海贝色","slategrey":"灰石色","coral":"珊瑚色","darkturquoise":"深粉蓝","antiquewhite":"古董白","mediumspringgreen":"间春绿色","salmon":"橙红","darkgrey":"深灰色","ivory":"象牙色","greenyellow":"绿黄色","mistyrose":"浅玫瑰色","lightsalmon":"淡橙色","silver":"银白色","dimgrey":"暗灰色","or [...]
diff --git a/dijit/nls/el/common.js b/dijit/nls/el/common.js
index 8e7a36a..48a8e18 100644
--- a/dijit/nls/el/common.js
+++ b/dijit/nls/el/common.js
@@ -1 +1,6 @@
-({"buttonOk":"ΟΚ","buttonCancel":"Ακύρωση","buttonSave":"Αποθήκευση","itemClose":"Κλείσιμο"})
\ No newline at end of file
+({
+	buttonOk: "ΟΚ",
+	buttonCancel: "Ακύρωση",
+	buttonSave: "Αποθήκευση",
+	itemClose: "Κλείσιμο"
+})
diff --git a/dijit/nls/el/loading.js b/dijit/nls/el/loading.js
index 9567b3c..06640e7 100644
--- a/dijit/nls/el/loading.js
+++ b/dijit/nls/el/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Φόρτωση...","errorState":"Σας ζητούμε συγνώμη, παρουσιάστηκε σφάλμα"})
\ No newline at end of file
+({
+	loadingState: "Φόρτωση...",
+	errorState: "Σας ζητούμε συγνώμη, παρουσιάστηκε σφάλμα"
+})
diff --git a/dijit/nls/es/common.js b/dijit/nls/es/common.js
index b4feef9..5bf0cc4 100644
--- a/dijit/nls/es/common.js
+++ b/dijit/nls/es/common.js
@@ -1 +1,6 @@
-({"buttonOk":"Aceptar","buttonCancel":"Cancelar","buttonSave":"Guardar","itemClose":"Cerrar"})
\ No newline at end of file
+({
+	buttonOk: "Aceptar",
+	buttonCancel: "Cancelar",
+	buttonSave: "Guardar",
+	itemClose: "Cerrar"
+})
diff --git a/dijit/nls/es/loading.js b/dijit/nls/es/loading.js
index dc969a3..5dd2144 100644
--- a/dijit/nls/es/loading.js
+++ b/dijit/nls/es/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Cargando...","errorState":"Lo siento, se ha producido un error"})
\ No newline at end of file
+({
+	loadingState: "Cargando...",
+	errorState: "Lo siento, se ha producido un error"
+})
diff --git a/dijit/nls/fi/common.js b/dijit/nls/fi/common.js
index 8b2fc26..3b7e0c4 100644
--- a/dijit/nls/fi/common.js
+++ b/dijit/nls/fi/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Peruuta","buttonSave":"Tallenna","itemClose":"Sulje"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Peruuta",
+	buttonSave: "Tallenna",
+	itemClose: "Sulje"
+})
diff --git a/dijit/nls/fi/loading.js b/dijit/nls/fi/loading.js
index 73e10a1..d30e1b0 100644
--- a/dijit/nls/fi/loading.js
+++ b/dijit/nls/fi/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Lataus on meneillään...","errorState":"On ilmennyt virhe."})
\ No newline at end of file
+({
+	loadingState: "Lataus on meneillään...",
+	errorState: "On ilmennyt virhe."
+})
diff --git a/dijit/nls/fr/common.js b/dijit/nls/fr/common.js
index 9f6aabe..3a45bcb 100644
--- a/dijit/nls/fr/common.js
+++ b/dijit/nls/fr/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Annuler","buttonSave":"Sauvegarder","itemClose":"Fermer"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Annuler",
+	buttonSave: "Sauvegarder",
+	itemClose: "Fermer"
+})
diff --git a/dijit/nls/fr/loading.js b/dijit/nls/fr/loading.js
index ec7192b..116c5ad 100644
--- a/dijit/nls/fr/loading.js
+++ b/dijit/nls/fr/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Chargement...","errorState":"Une erreur est survenue"})
\ No newline at end of file
+({
+	loadingState: "Chargement...",
+	errorState: "Une erreur est survenue"
+})
diff --git a/dijit/nls/he/common.js b/dijit/nls/he/common.js
index b04d1cc..884a6d1 100644
--- a/dijit/nls/he/common.js
+++ b/dijit/nls/he/common.js
@@ -1 +1,6 @@
-({"buttonOk":"אישור","buttonCancel":"ביטול","buttonSave":"שמירה","itemClose":"סגירה"})
\ No newline at end of file
+({
+	buttonOk: "אישור",
+	buttonCancel: "ביטול",
+	buttonSave: "שמירה",
+	itemClose: "סגירה"
+})
diff --git a/dijit/nls/he/loading.js b/dijit/nls/he/loading.js
index 7b1d5f3..1977ce4 100644
--- a/dijit/nls/he/loading.js
+++ b/dijit/nls/he/loading.js
@@ -1 +1,4 @@
-({"loadingState":"טעינה...‏","errorState":"אירעה שגיאה"})
\ No newline at end of file
+({
+	loadingState: "טעינה...‏",
+	errorState: "אירעה שגיאה"
+})
diff --git a/dijit/nls/hu/common.js b/dijit/nls/hu/common.js
index 21a773f..d20276c 100644
--- a/dijit/nls/hu/common.js
+++ b/dijit/nls/hu/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Mégse","buttonSave":"Mentés","itemClose":"Bezárás"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Mégse",
+	buttonSave: "Mentés",
+	itemClose: "Bezárás"
+})
diff --git a/dijit/nls/hu/loading.js b/dijit/nls/hu/loading.js
index d61e9a2..8128f82 100644
--- a/dijit/nls/hu/loading.js
+++ b/dijit/nls/hu/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Betöltés...","errorState":"Sajnálom, hiba történt"})
\ No newline at end of file
+({
+	loadingState: "Betöltés...",
+	errorState: "Sajnálom, hiba történt"
+})
diff --git a/dijit/nls/it/common.js b/dijit/nls/it/common.js
index 6b3dc74..ba275de 100644
--- a/dijit/nls/it/common.js
+++ b/dijit/nls/it/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Annulla","buttonSave":"Salva","itemClose":"Chiudi"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Annulla",
+	buttonSave: "Salva",
+	itemClose: "Chiudi"
+})
diff --git a/dijit/nls/it/loading.js b/dijit/nls/it/loading.js
index 60d05e0..6970086 100644
--- a/dijit/nls/it/loading.js
+++ b/dijit/nls/it/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Caricamento in corso...","errorState":"Si è verificato un errore"})
\ No newline at end of file
+({
+	loadingState: "Caricamento in corso...",
+	errorState: "Si è verificato un errore"
+})
diff --git a/dijit/nls/ja/common.js b/dijit/nls/ja/common.js
index b0b48c6..32c4436 100644
--- a/dijit/nls/ja/common.js
+++ b/dijit/nls/ja/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"キャンセル","buttonSave":"保存","itemClose":"閉じる"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "キャンセル",
+	buttonSave: "保存",
+	itemClose: "閉じる"
+})
diff --git a/dijit/nls/ja/loading.js b/dijit/nls/ja/loading.js
index fa67d67..b353f63 100644
--- a/dijit/nls/ja/loading.js
+++ b/dijit/nls/ja/loading.js
@@ -1 +1,4 @@
-({"loadingState":"ロード中...","errorState":"エラーが発生しました。"})
\ No newline at end of file
+({
+	loadingState: "ロード中...",
+	errorState: "エラーが発生しました。"
+})
diff --git a/dijit/nls/ko/common.js b/dijit/nls/ko/common.js
index 8e12bbf..d04333e 100644
--- a/dijit/nls/ko/common.js
+++ b/dijit/nls/ko/common.js
@@ -1 +1,6 @@
-({"buttonOk":"확인","buttonCancel":"취소","buttonSave":"저장","itemClose":"닫기"})
\ No newline at end of file
+({
+	buttonOk: "확인",
+	buttonCancel: "취소",
+	buttonSave: "저장",
+	itemClose: "닫기"
+})
diff --git a/dijit/nls/ko/loading.js b/dijit/nls/ko/loading.js
index 5d1ca12..5e9a2a6 100644
--- a/dijit/nls/ko/loading.js
+++ b/dijit/nls/ko/loading.js
@@ -1 +1,4 @@
-({"loadingState":"로드 중...","errorState":"죄송합니다. 오류가 발생했습니다."})
\ No newline at end of file
+({
+	loadingState: "로드 중...",
+	errorState: "죄송합니다. 오류가 발생했습니다."
+})
diff --git a/dijit/nls/loading.js b/dijit/nls/loading.js
index 1d6fa9b..fe85bad 100644
--- a/dijit/nls/loading.js
+++ b/dijit/nls/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Loading...","errorState":"Sorry, an error occurred"})
\ No newline at end of file
+({
+	loadingState: "Loading...",
+	errorState: "Sorry, an error occurred"
+})
diff --git a/dijit/nls/nb/common.js b/dijit/nls/nb/common.js
index 73e38c7..3768a74 100644
--- a/dijit/nls/nb/common.js
+++ b/dijit/nls/nb/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Avbryt","buttonSave":"Lagre","itemClose":"Lukk"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Avbryt",
+	buttonSave: "Lagre",
+	itemClose: "Lukk"
+})
diff --git a/dijit/nls/nb/loading.js b/dijit/nls/nb/loading.js
index dbc314d..13d5722 100644
--- a/dijit/nls/nb/loading.js
+++ b/dijit/nls/nb/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Laster inn...","errorState":"Det oppsto en feil"})
\ No newline at end of file
+({
+	loadingState: "Laster inn...",
+	errorState: "Det oppsto en feil"
+})
diff --git a/dijit/nls/nl/common.js b/dijit/nls/nl/common.js
index fa4c66e..93f39f9 100644
--- a/dijit/nls/nl/common.js
+++ b/dijit/nls/nl/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Annuleren","buttonSave":"Opslaan","itemClose":"Sluiten"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Annuleren",
+	buttonSave: "Opslaan",
+	itemClose: "Sluiten"
+})
diff --git a/dijit/nls/nl/loading.js b/dijit/nls/nl/loading.js
index c9870fd..f8dc69f 100644
--- a/dijit/nls/nl/loading.js
+++ b/dijit/nls/nl/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Bezig met laden...","errorState":"Er is een fout opgetreden"})
\ No newline at end of file
+({
+	loadingState: "Bezig met laden...",
+	errorState: "Er is een fout opgetreden"
+})
diff --git a/dijit/nls/pl/common.js b/dijit/nls/pl/common.js
index c84e539..85a8629 100644
--- a/dijit/nls/pl/common.js
+++ b/dijit/nls/pl/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Anuluj","buttonSave":"Zapisz","itemClose":"Zamknij"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Anuluj",
+	buttonSave: "Zapisz",
+	itemClose: "Zamknij"
+})
diff --git a/dijit/nls/pl/loading.js b/dijit/nls/pl/loading.js
index eed3c3e..8b70948 100644
--- a/dijit/nls/pl/loading.js
+++ b/dijit/nls/pl/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Ładowanie...","errorState":"Niestety, wystąpił błąd"})
\ No newline at end of file
+({
+	loadingState: "Ładowanie...",
+	errorState: "Niestety, wystąpił błąd"
+})
diff --git a/dijit/nls/pt-pt/common.js b/dijit/nls/pt-pt/common.js
index 7992705..b043944 100644
--- a/dijit/nls/pt-pt/common.js
+++ b/dijit/nls/pt-pt/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Cancelar","buttonSave":"Guardar","itemClose":"Fechar"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Cancelar",
+	buttonSave: "Guardar",
+	itemClose: "Fechar"
+})
\ No newline at end of file
diff --git a/dijit/nls/pt-pt/loading.js b/dijit/nls/pt-pt/loading.js
index 80257d3..07be3ca 100644
--- a/dijit/nls/pt-pt/loading.js
+++ b/dijit/nls/pt-pt/loading.js
@@ -1 +1,4 @@
-({"loadingState":"A carregar...","errorState":"Lamentamos, mas ocorreu um erro"})
\ No newline at end of file
+({
+	loadingState: "A carregar...",
+	errorState: "Lamentamos, mas ocorreu um erro"
+})
\ No newline at end of file
diff --git a/dijit/nls/pt/common.js b/dijit/nls/pt/common.js
index b94e6bc..9b0576a 100644
--- a/dijit/nls/pt/common.js
+++ b/dijit/nls/pt/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Cancelar","buttonSave":"Salvar","itemClose":"Fechar"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Cancelar",
+	buttonSave: "Salvar",
+	itemClose: "Fechar"
+})
diff --git a/dijit/nls/pt/loading.js b/dijit/nls/pt/loading.js
index 88cda7a..418f8ee 100644
--- a/dijit/nls/pt/loading.js
+++ b/dijit/nls/pt/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Carregando...","errorState":"Desculpe, ocorreu um erro"})
\ No newline at end of file
+({
+	loadingState: "Carregando...",
+	errorState: "Desculpe, ocorreu um erro"
+})
diff --git a/dijit/nls/ro/common.js b/dijit/nls/ro/common.js
new file mode 100644
index 0000000..9468897
--- /dev/null
+++ b/dijit/nls/ro/common.js
@@ -0,0 +1,7 @@
+({
+	buttonOk: "OK",
+	buttonCancel: "Anulare",
+	buttonSave: "Salvare",
+	itemClose: "Închidere"
+})
+
diff --git a/dijit/nls/ro/loading.js b/dijit/nls/ro/loading.js
new file mode 100644
index 0000000..6a956f4
--- /dev/null
+++ b/dijit/nls/ro/loading.js
@@ -0,0 +1,5 @@
+({
+	loadingState: "Încărcare...",
+	errorState: "Ne pare rău, a apărut o eroare "
+})
+
diff --git a/dijit/nls/ru/common.js b/dijit/nls/ru/common.js
index 9a76d09..10d71ab 100644
--- a/dijit/nls/ru/common.js
+++ b/dijit/nls/ru/common.js
@@ -1 +1,6 @@
-({"buttonOk":"ОК","buttonCancel":"Отмена","buttonSave":"Сохранить","itemClose":"Закрыть"})
\ No newline at end of file
+({
+	buttonOk: "ОК",
+	buttonCancel: "Отмена",
+	buttonSave: "Сохранить",
+	itemClose: "Закрыть"
+})
diff --git a/dijit/nls/ru/loading.js b/dijit/nls/ru/loading.js
index 55cd03b..d7d7dc9 100644
--- a/dijit/nls/ru/loading.js
+++ b/dijit/nls/ru/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Загрузка...","errorState":"Извините, возникла ошибка"})
\ No newline at end of file
+({
+	loadingState: "Загрузка...",
+	errorState: "Извините, возникла ошибка"
+})
diff --git a/dijit/nls/sk/common.js b/dijit/nls/sk/common.js
index 59a12d1..bc2fe93 100644
--- a/dijit/nls/sk/common.js
+++ b/dijit/nls/sk/common.js
@@ -1 +1,7 @@
-({"buttonOk":"OK","buttonCancel":"Zrušiť","buttonSave":"Uložiť","itemClose":"Zatvoriť"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Zrušiť",
+	buttonSave: "Uložiť",
+	itemClose: "Zatvoriť"
+})
+
diff --git a/dijit/nls/sk/loading.js b/dijit/nls/sk/loading.js
index e805bd8..e7853dd 100644
--- a/dijit/nls/sk/loading.js
+++ b/dijit/nls/sk/loading.js
@@ -1 +1,5 @@
-({"loadingState":"Zavádzanie...","errorState":"Nastala chyba"})
\ No newline at end of file
+({
+	loadingState: "Zavádzanie...",
+	errorState: "Nastala chyba"
+})
+
diff --git a/dijit/nls/sl/common.js b/dijit/nls/sl/common.js
index 4704cc5..fdd260b 100644
--- a/dijit/nls/sl/common.js
+++ b/dijit/nls/sl/common.js
@@ -1 +1,7 @@
-({"buttonOk":"V redu","buttonCancel":"Prekliči","buttonSave":"Shrani","itemClose":"Zapri"})
\ No newline at end of file
+({
+	buttonOk: "V redu",
+	buttonCancel: "Prekliči",
+	buttonSave: "Shrani",
+	itemClose: "Zapri"
+})
+
diff --git a/dijit/nls/sl/loading.js b/dijit/nls/sl/loading.js
index 4100866..86bd4db 100644
--- a/dijit/nls/sl/loading.js
+++ b/dijit/nls/sl/loading.js
@@ -1 +1,5 @@
-({"loadingState":"Nalaganje...","errorState":"Oprostite, prišlo je do napake."})
\ No newline at end of file
+({
+	loadingState: "Nalaganje...",
+	errorState: "Oprostite, prišlo je do napake."
+})
+
diff --git a/dijit/nls/sv/common.js b/dijit/nls/sv/common.js
index cd3444f..1ad8253 100644
--- a/dijit/nls/sv/common.js
+++ b/dijit/nls/sv/common.js
@@ -1 +1,6 @@
-({"buttonOk":"OK","buttonCancel":"Avbryt","buttonSave":"Spara","itemClose":"Stäng"})
\ No newline at end of file
+({
+	buttonOk: "OK",
+	buttonCancel: "Avbryt",
+	buttonSave: "Spara",
+	itemClose: "Stäng"
+})
diff --git a/dijit/nls/sv/loading.js b/dijit/nls/sv/loading.js
index 95b90d2..cc47058 100644
--- a/dijit/nls/sv/loading.js
+++ b/dijit/nls/sv/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Läser in...","errorState":"Det uppstod ett fel."})
\ No newline at end of file
+({
+	loadingState: "Läser in...",
+	errorState: "Det uppstod ett fel."
+})
diff --git a/dijit/nls/th/common.js b/dijit/nls/th/common.js
index be06dd0..aefd2de 100644
--- a/dijit/nls/th/common.js
+++ b/dijit/nls/th/common.js
@@ -1 +1,7 @@
-({"buttonOk":"ตกลง","buttonCancel":"ยกเลิก","buttonSave":"บันทึก","itemClose":"ปิด"})
\ No newline at end of file
+({
+	buttonOk: "ตกลง",
+	buttonCancel: "ยกเลิก",
+	buttonSave: "บันทึก",
+	itemClose: "ปิด"
+})
+
diff --git a/dijit/nls/th/loading.js b/dijit/nls/th/loading.js
index bb6b75d..695bac2 100644
--- a/dijit/nls/th/loading.js
+++ b/dijit/nls/th/loading.js
@@ -1 +1,5 @@
-({"loadingState":"กำลังโหลด...","errorState":"ขออภัย เกิดข้อผิดพลาด"})
\ No newline at end of file
+({
+	loadingState: "กำลังโหลด...",
+	errorState: "ขออภัย เกิดข้อผิดพลาด"
+})
+
diff --git a/dijit/nls/tr/common.js b/dijit/nls/tr/common.js
index e89e645..21990ee 100644
--- a/dijit/nls/tr/common.js
+++ b/dijit/nls/tr/common.js
@@ -1 +1,6 @@
-({"buttonOk":"Tamam","buttonCancel":"İptal","buttonSave":"Kaydet","itemClose":"Kapat"})
\ No newline at end of file
+({
+	buttonOk: "Tamam",
+	buttonCancel: "İptal",
+	buttonSave: "Kaydet",
+	itemClose: "Kapat"
+})
diff --git a/dijit/nls/tr/loading.js b/dijit/nls/tr/loading.js
index b0ed738..f714438 100644
--- a/dijit/nls/tr/loading.js
+++ b/dijit/nls/tr/loading.js
@@ -1 +1,4 @@
-({"loadingState":"Yükleniyor...","errorState":"Üzgünüz, bir hata oluştu"})
\ No newline at end of file
+({
+	loadingState: "Yükleniyor...",
+	errorState: "Üzgünüz, bir hata oluştu"
+})
diff --git a/dijit/nls/zh-tw/common.js b/dijit/nls/zh-tw/common.js
index 5d3fee0..8db6f95 100644
--- a/dijit/nls/zh-tw/common.js
+++ b/dijit/nls/zh-tw/common.js
@@ -1 +1,6 @@
-({"buttonOk":"確定","buttonCancel":"取消","buttonSave":"儲存","itemClose":"關閉"})
\ No newline at end of file
+({
+	buttonOk: "確定",
+	buttonCancel: "取消",
+	buttonSave: "儲存",
+	itemClose: "關閉"
+})
diff --git a/dijit/nls/zh-tw/loading.js b/dijit/nls/zh-tw/loading.js
index 0078541..177bc82 100644
--- a/dijit/nls/zh-tw/loading.js
+++ b/dijit/nls/zh-tw/loading.js
@@ -1 +1,4 @@
-({"loadingState":"載入中...","errorState":"抱歉,發生錯誤"})
\ No newline at end of file
+({
+	loadingState: "載入中...",
+	errorState: "抱歉,發生錯誤"
+})
diff --git a/dijit/nls/zh/common.js b/dijit/nls/zh/common.js
index 0bb6267..5a7aeb2 100644
--- a/dijit/nls/zh/common.js
+++ b/dijit/nls/zh/common.js
@@ -1 +1,6 @@
-({"buttonOk":"确定","buttonCancel":"取消","buttonSave":"保存","itemClose":"关闭"})
\ No newline at end of file
+({
+	buttonOk: "确定",
+	buttonCancel: "取消",
+	buttonSave: "保存",
+	itemClose: "关闭"
+})
diff --git a/dijit/nls/zh/loading.js b/dijit/nls/zh/loading.js
index c4b6fd7..a367413 100644
--- a/dijit/nls/zh/loading.js
+++ b/dijit/nls/zh/loading.js
@@ -1 +1,4 @@
-({"loadingState":"正在加载...","errorState":"对不起,发生了错误"})
\ No newline at end of file
+({
+	loadingState: "正在加载...",
+	errorState: "对不起,发生了错误"
+})
diff --git a/dijit/resources/_modules.js b/dijit/resources/_modules.js
index 0b276e5..e75636f 100644
--- a/dijit/resources/_modules.js
+++ b/dijit/resources/_modules.js
@@ -1,7 +1,18 @@
-/*
-	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
-*/
+/*=====
+// dijit fallback for key summaries otherwise not covered by the doc parser
 
+dijit.demos = {
+	// summary:
+	//		Home of the official dijit demo code
+};
 
+dijit.form = {
+	// summary:
+	//		Form and input related widgets
+};
+
+dijit.layout = {
+	// summary:
+	//		Layout related widgets
+};
+=====*/
diff --git a/dijit/robot.js b/dijit/robot.js
index 82dcfed..83338db 100644
--- a/dijit/robot.js
+++ b/dijit/robot.js
@@ -1,64 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.robot"]){
-dojo._hasResource["dijit.robot"]=true;
 dojo.provide("dijit.robot");
 dojo.require("dojo.robot");
-dojo.provide("dijit._base.place");
-dojo.require("dijit._base.scroll");
-dojo.require("dijit._base.window");
-dojo.mixin(doh.robot,{_position:function(n){
-var d=dojo,p=null,M=Math.max,m=Math.min;
-d.forEach(doh.robot._getWindowChain(n),function(w){
-d.withGlobal(w,function(){
-var p2=d.position(n,false),b=d._getPadBorderExtents(n);
-if(!p){
-p=p2;
-}else{
-var _1;
-d.withGlobal(n.contentWindow,function(){
-_1=dijit.getViewport();
-});
-p2.r=p2.x+_1.w;
-p2.b=p2.y+_1.h;
-p={x:M(p.x+p2.x,p2.x)+b.l,y:M(p.y+p2.y,p2.y)+b.t,r:m(p.x+p2.x+p.w,p2.r)+b.l,b:m(p.y+p2.y+p.h,p2.b)+b.t};
-p.w=p.r-p.x;
-p.h=p.b-p.y;
-}
-n=w.frameElement;
-});
-});
-return p;
-},_scrollIntoView:function(n){
-var d=dojo,dr=doh.robot,p=null;
-d.forEach(dr._getWindowChain(n),function(w){
-d.withGlobal(w,function(){
-var p2=d.position(n,false),b=d._getPadBorderExtents(n),_2=null;
-if(!p){
-p=p2;
-}else{
-_2=p;
-p={x:p.x+p2.x+b.l,y:p.y+p2.y+b.t,w:p.w,h:p.h};
-}
-dijit.scrollIntoView(n,p);
-p2=d.position(n,false);
-if(!_2){
-p=p2;
-}else{
-p={x:_2.x+p2.x+b.l,y:_2.y+p2.y+b.t,w:p.w,h:p.h};
-}
-n=w.frameElement;
-});
-});
-},_getWindowChain:function(n){
-var cW=dijit.getDocumentWindow(n.ownerDocument);
-var _3=[cW];
-var f=cW.frameElement;
-return (cW==dojo.global||f==null)?_3:_3.concat(doh.robot._getWindowChain(f));
-}});
-}
diff --git a/dijit/robotx.js b/dijit/robotx.js
index 5f86f8c..8fb1eec 100644
--- a/dijit/robotx.js
+++ b/dijit/robotx.js
@@ -1,24 +1,18 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.robotx"]){
-dojo._hasResource["dijit.robotx"]=true;
 dojo.provide("dijit.robotx");
 dojo.require("dijit.robot");
 dojo.require("dojo.robotx");
 dojo.experimental("dijit.robotx");
 (function(){
-var _1=doh.robot._updateDocument;
-dojo.mixin(doh.robot,{_updateDocument:function(){
-_1();
-var _2=dojo.global;
-if(_2["dijit"]){
-dijit.registry=_2.dijit.registry;
-}
-}});
+var __updateDocument = doh.robot._updateDocument;
+
+dojo.mixin(doh.robot,{
+	_updateDocument: function(){
+		__updateDocument();
+		var win = dojo.global;
+		if(win["dijit"]){
+			dijit = win.dijit;
+		}
+	}
+});
+
 })();
-}
diff --git a/dijit/templates/Calendar.html b/dijit/templates/Calendar.html
new file mode 100644
index 0000000..680c495
--- /dev/null
+++ b/dijit/templates/Calendar.html
@@ -0,0 +1,42 @@
+<table cellspacing="0" cellpadding="0" class="dijitCalendarContainer" role="grid" dojoAttachEvent="onkeypress: _onKeyPress">
+	<thead>
+		<tr class="dijitReset dijitCalendarMonthContainer" valign="top">
+			<th class='dijitReset dijitCalendarArrow' dojoAttachPoint="decrementMonth">
+				<img src="${_blankGif}" alt="" class="dijitCalendarIncrementControl dijitCalendarDecrease" waiRole="presentation"/>
+				<span dojoAttachPoint="decreaseArrowNode" class="dijitA11ySideArrow">-</span>
+			</th>
+			<th class='dijitReset' colspan="5">
+				<div class="dijitVisible">
+					<div class="dijitPopup dijitMenu dijitMenuPassive dijitHidden" dojoAttachPoint="monthDropDown" dojoAttachEvent="onmouseup: _onMonthSelect, onmouseover: _onMenuHover, onmouseout: _onMenuHover">
+						<div class="dijitCalendarMonthLabelTemplate dijitCalendarMonthLabel"></div>
+					</div>
+				</div>
+				<div dojoAttachPoint="monthLabelSpacer" class="dijitSpacer"></div>
+				<div dojoAttachPoint="monthLabelNode" class="dijitCalendarMonthLabel dijitInline dijitVisible" dojoAttachEvent="onmousedown: _onMonthToggle"></div>
+			</th>
+			<th class='dijitReset dijitCalendarArrow' dojoAttachPoint="incrementMonth">
+				<img src="${_blankGif}" alt="" class="dijitCalendarIncrementControl dijitCalendarIncrease" waiRole="presentation"/>
+				<span dojoAttachPoint="increaseArrowNode" class="dijitA11ySideArrow">+</span>
+			</th>
+		</tr>
+		<tr>
+			<th class="dijitReset dijitCalendarDayLabelTemplate" role="columnheader"><span class="dijitCalendarDayLabel"></span></th>
+		</tr>
+	</thead>
+	<tbody dojoAttachEvent="onclick: _onDayClick, onmouseover: _onDayMouseOver, onmouseout: _onDayMouseOut, onmousedown: _onDayMouseDown, onmouseup: _onDayMouseUp" class="dijitReset dijitCalendarBodyContainer">
+		<tr class="dijitReset dijitCalendarWeekTemplate" role="row">
+			<td class="dijitReset dijitCalendarDateTemplate" role="gridcell"><span class="dijitCalendarDateLabel"></span></td>
+		</tr>
+	</tbody>
+	<tfoot class="dijitReset dijitCalendarYearContainer">
+		<tr>
+			<td class='dijitReset' valign="top" colspan="7">
+				<h3 class="dijitCalendarYearLabel">
+					<span dojoAttachPoint="previousYearLabelNode" class="dijitInline dijitCalendarPreviousYear"></span>
+					<span dojoAttachPoint="currentYearLabelNode" class="dijitInline dijitCalendarSelectedYear"></span>
+					<span dojoAttachPoint="nextYearLabelNode" class="dijitInline dijitCalendarNextYear"></span>
+				</h3>
+			</td>
+		</tr>
+	</tfoot>
+</table>
\ No newline at end of file
diff --git a/dijit/templates/CheckedMenuItem.html b/dijit/templates/CheckedMenuItem.html
new file mode 100644
index 0000000..a0b6146
--- /dev/null
+++ b/dijit/templates/CheckedMenuItem.html
@@ -0,0 +1,10 @@
+<tr class="dijitReset dijitMenuItem" dojoAttachPoint="focusNode" waiRole="menuitemcheckbox" tabIndex="-1"
+		dojoAttachEvent="onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick">
+	<td class="dijitReset dijitMenuItemIconCell" waiRole="presentation">
+		<img src="${_blankGif}" alt="" class="dijitMenuItemIcon dijitCheckedMenuItemIcon" dojoAttachPoint="iconNode"/>
+		<span class="dijitCheckedMenuItemIconChar">✓</span>
+	</td>
+	<td class="dijitReset dijitMenuItemLabel" colspan="2" dojoAttachPoint="containerNode,labelNode"></td>
+	<td class="dijitReset dijitMenuItemAccelKey" style="display: none" dojoAttachPoint="accelKeyNode"></td>
+	<td class="dijitReset dijitMenuArrowCell" waiRole="presentation"> </td>
+</tr>
diff --git a/dijit/templates/ColorPalette.html b/dijit/templates/ColorPalette.html
new file mode 100644
index 0000000..aa35a15
--- /dev/null
+++ b/dijit/templates/ColorPalette.html
@@ -0,0 +1,6 @@
+<div class="dijitInline dijitColorPalette">
+	<img class="dijitColorPaletteUnder" dojoAttachPoint="imageNode" waiRole="presentation" alt=""/>
+	<table class="dijitPaletteTable" cellSpacing="0" cellPadding="0">
+		<tbody dojoAttachPoint="gridNode"></tbody>
+	</table>
+</div>
diff --git a/dijit/templates/Dialog.html b/dijit/templates/Dialog.html
new file mode 100644
index 0000000..26357cd
--- /dev/null
+++ b/dijit/templates/Dialog.html
@@ -0,0 +1,9 @@
+<div class="dijitDialog" tabindex="-1" waiRole="dialog" waiState="labelledby-${id}_title">
+	<div dojoAttachPoint="titleBar" class="dijitDialogTitleBar">
+	<span dojoAttachPoint="titleNode" class="dijitDialogTitle" id="${id}_title"></span>
+	<span dojoAttachPoint="closeButtonNode" class="dijitDialogCloseIcon" dojoAttachEvent="onclick: onCancel" title="${buttonCancel}">
+		<span dojoAttachPoint="closeText" class="closeText" title="${buttonCancel}">x</span>
+	</span>
+	</div>
+		<div dojoAttachPoint="containerNode" class="dijitDialogPaneContent"></div>
+</div>
diff --git a/dijit/templates/InlineEditBox.html b/dijit/templates/InlineEditBox.html
new file mode 100644
index 0000000..5d0a609
--- /dev/null
+++ b/dijit/templates/InlineEditBox.html
@@ -0,0 +1,8 @@
+<span dojoAttachPoint="editNode" waiRole="presentation" style="position: absolute; visibility:hidden" class="dijitReset dijitInline"
+	dojoAttachEvent="onkeypress: _onKeyPress"
+	><span dojoAttachPoint="editorPlaceholder"></span
+	><span dojoAttachPoint="buttonContainer"
+		><button class='saveButton' dojoAttachPoint="saveButton" dojoType="dijit.form.Button" dojoAttachEvent="onClick:save" label="${buttonSave}"></button
+		><button class='cancelButton' dojoAttachPoint="cancelButton" dojoType="dijit.form.Button" dojoAttachEvent="onClick:cancel" label="${buttonCancel}"></button
+	></span
+></span>
diff --git a/dijit/templates/Menu.html b/dijit/templates/Menu.html
new file mode 100644
index 0000000..eac5faa
--- /dev/null
+++ b/dijit/templates/Menu.html
@@ -0,0 +1,3 @@
+<table class="dijit dijitMenu dijitMenuPassive dijitReset dijitMenuTable" waiRole="menu" tabIndex="${tabIndex}" dojoAttachEvent="onkeypress:_onKeyPress" cellspacing=0>
+	<tbody class="dijitReset" dojoAttachPoint="containerNode"></tbody>
+</table>
diff --git a/dijit/templates/MenuBar.html b/dijit/templates/MenuBar.html
new file mode 100644
index 0000000..4c6ad33
--- /dev/null
+++ b/dijit/templates/MenuBar.html
@@ -0,0 +1 @@
+<div class="dijitMenuBar dijitMenuPassive" dojoAttachPoint="containerNode"  waiRole="menubar" tabIndex="${tabIndex}" dojoAttachEvent="onkeypress: _onKeyPress"></div>
diff --git a/dijit/templates/MenuBarItem.html b/dijit/templates/MenuBarItem.html
new file mode 100644
index 0000000..8a89132
--- /dev/null
+++ b/dijit/templates/MenuBarItem.html
@@ -0,0 +1,4 @@
+<div class="dijitReset dijitInline dijitMenuItem dijitMenuItemLabel" dojoAttachPoint="focusNode" waiRole="menuitem" tabIndex="-1"
+		dojoAttachEvent="onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick">
+	<span dojoAttachPoint="containerNode"></span>
+</div>
diff --git a/dijit/templates/MenuItem.html b/dijit/templates/MenuItem.html
new file mode 100644
index 0000000..e13c3fb
--- /dev/null
+++ b/dijit/templates/MenuItem.html
@@ -0,0 +1,14 @@
+<tr class="dijitReset dijitMenuItem" dojoAttachPoint="focusNode" waiRole="menuitem" tabIndex="-1"
+		dojoAttachEvent="onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick">
+	<td class="dijitReset dijitMenuItemIconCell" waiRole="presentation">
+		<img src="${_blankGif}" alt="" class="dijitIcon dijitMenuItemIcon" dojoAttachPoint="iconNode"/>
+	</td>
+	<td class="dijitReset dijitMenuItemLabel" colspan="2" dojoAttachPoint="containerNode"></td>
+	<td class="dijitReset dijitMenuItemAccelKey" style="display: none" dojoAttachPoint="accelKeyNode"></td>
+	<td class="dijitReset dijitMenuArrowCell" waiRole="presentation">
+		<div dojoAttachPoint="arrowWrapper" style="visibility: hidden">
+			<img src="${_blankGif}" alt="" class="dijitMenuExpand"/>
+			<span class="dijitMenuExpandA11y">+</span>
+		</div>
+	</td>
+</tr>
diff --git a/dijit/templates/MenuSeparator.html b/dijit/templates/MenuSeparator.html
new file mode 100644
index 0000000..77d1d05
--- /dev/null
+++ b/dijit/templates/MenuSeparator.html
@@ -0,0 +1,10 @@
+<tr class="dijitMenuSeparator">
+	<td class="dijitMenuSeparatorIconCell">
+		<div class="dijitMenuSeparatorTop"></div>
+		<div class="dijitMenuSeparatorBottom"></div>
+	</td>
+	<td colspan="3" class="dijitMenuSeparatorLabelCell">
+		<div class="dijitMenuSeparatorTop dijitMenuSeparatorLabel"></div>
+		<div class="dijitMenuSeparatorBottom"></div>
+	</td>
+</tr>
\ No newline at end of file
diff --git a/dijit/templates/ProgressBar.html b/dijit/templates/ProgressBar.html
new file mode 100644
index 0000000..7eeb733
--- /dev/null
+++ b/dijit/templates/ProgressBar.html
@@ -0,0 +1,8 @@
+<div class="dijitProgressBar dijitProgressBarEmpty"
+	><div waiRole="progressbar" dojoAttachPoint="internalProgress" class="dijitProgressBarFull"
+		><div class="dijitProgressBarTile"></div
+		><span style="visibility:hidden"> </span
+	></div
+	><div dojoAttachPoint="label" class="dijitProgressBarLabel" id="${id}_label"> </div
+	><img dojoAttachPoint="indeterminateHighContrastImage" class="dijitProgressBarIndeterminateHighContrastImage" alt=""
+/></div>
diff --git a/dijit/templates/TimePicker.html b/dijit/templates/TimePicker.html
new file mode 100644
index 0000000..e94d957
--- /dev/null
+++ b/dijit/templates/TimePicker.html
@@ -0,0 +1,9 @@
+<div id="widget_${id}" class="dijitMenu"
+    ><div dojoAttachPoint="upArrow" class="dijitButtonNode dijitUpArrowButton" dojoAttachEvent="onmouseenter:_buttonMouse,onmouseleave:_buttonMouse"
+		><div class="dijitReset dijitInline dijitArrowButtonInner" wairole="presentation" role="presentation"> </div
+		><div class="dijitArrowButtonChar">▲</div></div
+    ><div dojoAttachPoint="timeMenu,focusNode" dojoAttachEvent="onclick:_onOptionSelected,onmouseover,onmouseout"></div
+    ><div dojoAttachPoint="downArrow" class="dijitButtonNode dijitDownArrowButton" dojoAttachEvent="onmouseenter:_buttonMouse,onmouseleave:_buttonMouse"
+		><div class="dijitReset dijitInline dijitArrowButtonInner" wairole="presentation" role="presentation"> </div
+		><div class="dijitArrowButtonChar">▼</div></div
+></div>
diff --git a/dijit/templates/TitlePane.html b/dijit/templates/TitlePane.html
new file mode 100644
index 0000000..c272d65
--- /dev/null
+++ b/dijit/templates/TitlePane.html
@@ -0,0 +1,17 @@
+<div>
+	<div dojoAttachEvent="onclick:_onTitleClick, onkeypress:_onTitleKey"
+			class="dijitTitlePaneTitle" dojoAttachPoint="titleBarNode">
+		<div class="dijitTitlePaneTitleFocus" dojoAttachPoint="focusNode">
+			<img src="${_blankGif}" alt="" dojoAttachPoint="arrowNode" class="dijitArrowNode" waiRole="presentation"
+			/><span dojoAttachPoint="arrowNodeInner" class="dijitArrowNodeInner"></span
+			><span dojoAttachPoint="titleNode" class="dijitTitlePaneTextNode"></span>
+		</div>
+	</div>
+	<div class="dijitTitlePaneContentOuter" dojoAttachPoint="hideNode" waiRole="presentation">
+		<div class="dijitReset" dojoAttachPoint="wipeNode" waiRole="presentation">
+			<div class="dijitTitlePaneContentInner" dojoAttachPoint="containerNode" waiRole="region" tabindex="-1" id="${id}_pane">
+				<!-- nested divs because wipeIn()/wipeOut() doesn't work right on node w/padding etc.  Put padding on inner div. -->
+			</div>
+		</div>
+	</div>
+</div>
diff --git a/dijit/templates/Tooltip.html b/dijit/templates/Tooltip.html
new file mode 100644
index 0000000..8739648
--- /dev/null
+++ b/dijit/templates/Tooltip.html
@@ -0,0 +1,4 @@
+<div class="dijitTooltip dijitTooltipLeft" id="dojoTooltip">
+	<div class="dijitTooltipContainer dijitTooltipContents" dojoAttachPoint="containerNode" waiRole='alert'></div>
+	<div class="dijitTooltipConnector"></div>
+</div>
diff --git a/dijit/templates/TooltipDialog.html b/dijit/templates/TooltipDialog.html
new file mode 100644
index 0000000..d8cbaee
--- /dev/null
+++ b/dijit/templates/TooltipDialog.html
@@ -0,0 +1,6 @@
+<div waiRole="presentation">
+	<div class="dijitTooltipContainer" waiRole="presentation">
+		<div class ="dijitTooltipContents dijitTooltipFocusNode" dojoAttachPoint="containerNode" tabindex="-1" waiRole="dialog"></div>
+	</div>
+	<div class="dijitTooltipConnector" waiRole="presentation"></div>
+</div>
diff --git a/dijit/templates/Tree.html b/dijit/templates/Tree.html
new file mode 100644
index 0000000..ee331d1
--- /dev/null
+++ b/dijit/templates/Tree.html
@@ -0,0 +1,4 @@
+<div class="dijitTree dijitTreeContainer" waiRole="tree"
+	dojoAttachEvent="onkeypress:_onKeyPress">
+	<div class="dijitInline dijitTreeIndent" style="position: absolute; top: -9999px" dojoAttachPoint="indentDetector"></div>
+</div>
diff --git a/dijit/templates/TreeNode.html b/dijit/templates/TreeNode.html
new file mode 100644
index 0000000..47df19a
--- /dev/null
+++ b/dijit/templates/TreeNode.html
@@ -0,0 +1,13 @@
+<div class="dijitTreeNode" waiRole="presentation"
+	><div dojoAttachPoint="rowNode" class="dijitTreeRow" waiRole="presentation" dojoAttachEvent="onmouseenter:_onMouseEnter, onmouseleave:_onMouseLeave, onclick:_onClick, ondblclick:_onDblClick"
+		><img src="${_blankGif}" alt="" dojoAttachPoint="expandoNode" class="dijitTreeExpando" waiRole="presentation"
+		/><span dojoAttachPoint="expandoNodeText" class="dijitExpandoText" waiRole="presentation"
+		></span
+		><span dojoAttachPoint="contentNode"
+			class="dijitTreeContent" waiRole="presentation">
+			<img src="${_blankGif}" alt="" dojoAttachPoint="iconNode" class="dijitIcon dijitTreeIcon" waiRole="presentation"
+			/><span dojoAttachPoint="labelNode" class="dijitTreeLabel" wairole="treeitem" tabindex="-1" waiState="selected-false" dojoAttachEvent="onfocus:_onLabelFocus"></span>
+		</span
+	></div>
+	<div dojoAttachPoint="containerNode" class="dijitTreeContainer" waiRole="presentation" style="display: none;"></div>
+</div>
diff --git a/dijit/tests/Tree.html b/dijit/tests/Tree.html
new file mode 100644
index 0000000..9b0de99
--- /dev/null
+++ b/dijit/tests/Tree.html
@@ -0,0 +1,249 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.Tree Automatic Tests</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "../../dojo/resources/dnd.css";
+		@import "../../dojo/tests/dnd/dndDefault.css";
+		@import "css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script type="text/javascript" src="helpers.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+		dojo.require("dijit.tree.dndSource");
+
+		dojo.addOnLoad(function(){
+			doh.register("Tree tests",
+				[
+					function create(){
+						var d = new doh.Deferred;
+			 			myStore = new dojo.data.ItemFileWriteStore({url:'_data/countries.json'});
+			 			doh.t(myStore, "store created");
+
+						myModel = new dijit.tree.ForestStoreModel({
+							store: myStore,
+							query: {type:'continent'},
+							rootId: "earth",
+							rootLabel: "Earth",
+							childrenAttrs: ["children"]
+						});
+						doh.t(myModel, "model created");
+
+						myTree = new dijit.Tree({
+							id: "myTree",
+							model: myModel,
+							persist: false,		// persist==true is too hard to test
+							dndController: "dijit.tree.dndSource"
+						});
+						doh.t(myTree, "tree created");
+
+						dojo.byId("container").appendChild(myTree.domNode);
+						myTree.startup();
+
+						setTimeout(d.getTestCallback(function(){
+							// Give the tree time to load, and the do checks that it
+							// loaded correctly
+							doh.t(myTree.rootNode, "root node exists");
+							doh.t(myTree.rootNode.isExpanded, "root node is expanded");
+
+							var children = myTree.rootNode.getChildren();
+							doh.is(6, children.length, "six children");
+							doh.is("Africa", children[0].label, "first child");
+							doh.f(children[0].isExpanded, "first child not expanded");
+							doh.is("South America", children[5].label, "last child");
+
+							// Last child has special CSS for drawing the grid lines
+							doh.f(dojo.hasClass(children[3].domNode, "dijitTreeIsLast"), "middle node doesn't have dijitTreeIsLast");
+							doh.t(dojo.hasClass(children[5].domNode, "dijitTreeIsLast"), "last node has dijitTreeIsLast");
+						}), 750);
+						return d;
+					},
+
+					function createWithPath(){
+						var d = new doh.Deferred;
+						myTree2 = new dijit.Tree({
+							id: "myTree2",
+							model: myModel,
+							persist: false,		// persist==true is too hard to test
+							dndController: "dijit.tree.dndSource",
+							path: ["earth", "EU", "IT"]
+						});
+						doh.t(myTree2, "myTree2 created");
+
+						dojo.byId("container2").appendChild(myTree2.domNode);
+						myTree2.startup();
+
+						setTimeout(d.getTestCallback(function(){
+							// Give the tree time to load, and the do checks that it
+							// loaded correctly
+
+							doh.t(myTree2.rootNode, "root node exists");
+							doh.t(myTree2.rootNode.isExpanded, "root node is expanded");
+							doh.t(myTree2.rootNode.getChildren()[3].isExpanded, "europe node is expanded");
+							doh.is(myTree2.rootNode.getChildren()[3].getChildren()[3], myTree2.selectedNode, "selected correct node");
+						}), 750);
+						return d;
+					},
+
+					function copyPath(){
+						var d = new doh.Deferred;
+
+						myTree.set("path", myTree2.get("path")).then(d.getTestCallback(function(){
+							doh.t(myTree.rootNode.isExpanded, "root node is expanded");
+							doh.t(myTree.rootNode.getChildren()[3].isExpanded, "europe node is expanded");
+							doh.is(myTree.rootNode.getChildren()[3].getChildren()[3], myTree.selectedNode, "selected correct node");
+						}));
+
+						return d;
+					},
+
+					{
+						name: "copyPathByIds",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred;
+
+							myTree.set("path", ["earth", "NA", "CA", "Ottawa"]).then(d.getTestErrback(function(){
+								var path = dojo.map(myTree.get("path"), function(item){ return myTree.model.getIdentity(item); });
+								doh.is(["earth", "NA", "CA", "Ottawa"], path, "path got set on myTree");
+
+								myTree2.set("path", path).then(d.getTestCallback(function(){
+									doh.t(myTree2.rootNode.isExpanded, "root node is expanded");
+									doh.t(myTree2.rootNode.getChildren()[4].isExpanded, "north america node is expanded");
+									doh.t(myTree2.rootNode.getChildren()[4].getChildren()[1].isExpanded, "canada node is expanded");
+									doh.is(myTree2.rootNode.getChildren()[4].getChildren()[1].getChildren()[0], myTree2.selectedNode, "selected correct node");
+								}));
+							}));
+
+							return d;
+						}
+					},
+
+					function itemUpdate(){
+						// Test that Tree noticed when data store items change, and updates accordingly
+
+						var item = myTree.rootNode.getChildren()[3].item;
+						myStore.setValue(item, "name", "EU");
+
+						doh.is("EU", innerText(myTree.rootNode.getChildren()[3].labelNode), "label changed");
+					},
+
+					function topLevelItemDelete(){
+						// Delete a top level item.   ForestStoreModel needs to realize that the top level
+						// children have changed and notify Tree
+
+						// Remove "South America"
+						var item = myTree.rootNode.getChildren()[5].item;
+						myStore.deleteItem(item);
+
+						var children = myTree.rootNode.getChildren();
+						doh.is(5, children.length, "five children");
+						doh.is("North America", children[4].label, "last child");
+						doh.t(dojo.hasClass(children[4].domNode, "dijitTreeIsLast"),
+								"North america has become the last node so it gets the CSS class for that");
+					},
+
+					function openANode(){
+						var d = new doh.Deferred;
+
+						var asia = myTree.rootNode.getChildren()[1];
+
+						doh.is(0, asia.getChildren().length, "no children loaded yet");
+
+						myTree._onExpandoClick({node: asia});
+
+						setTimeout(d.getTestCallback(function(){
+							// Give the tree time to load the children, and the do checks that it
+							// loaded correctly
+
+							var children = asia.getChildren();
+							doh.is(4, children.length, "four children");
+							doh.is("China", children[0].label, "first child");
+							doh.is("Mongolia", children[3].label, "last child");
+						}), 750);
+						return d;
+					},
+
+					function selectAnItem(){
+						myTree.set('selectedItem','CN');
+						doh.is('CN',myTree.model.getIdentity(myTree.get('selectedItem')));
+					},
+
+					function nestedItemDelete(){
+						// Delete a nested item
+
+						// Remove "China"
+						var asia = myTree.rootNode.getChildren()[1],
+							china = asia.getChildren()[0];
+						myStore.deleteItem(china.item);
+
+						var children = asia.getChildren();
+						doh.is(3, children.length, "three children");
+					},
+
+					function topLevelItemInsert(){
+						// Create a new top level item as last child.
+						// ForestStoreModel needs to realize that the top level children have changed and notify Tree.
+
+						myStore.newItem({
+							id: 'PA',
+							name:'Pacifica',
+							type:'continent',
+			        		children: []
+						});
+
+						var children = myTree.rootNode.getChildren();
+						doh.is(6, children.length, "six children");
+						doh.is("Pacifica", children[5].label, "last child");
+						doh.f(dojo.hasClass(children[4].domNode, "dijitTreeIsLast"),
+							"North America no longer last child");
+						doh.t(dojo.hasClass(children[5].domNode, "dijitTreeIsLast"),
+							"Pacifica is last child");
+					},
+
+
+					function destroyTree(){
+						// Just running this to make sure we don't get an exception
+						console.log("destroying tree");
+						myTree.destroy();
+ 						myTree2.destroy();
+					}
+
+				]
+			);
+
+			doh.run();
+		});
+	</script>
+
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit.Tree automated tests</h1>
+	<div id="container"> <!--  tree will go here --></div>
+	<div id="container2"> <!--  tree2 will go here --></div>
+</body>
+</html>
+
+
+
+
diff --git a/dijit/tests/Tree_with_JRS.html b/dijit/tests/Tree_with_JRS.html
new file mode 100644
index 0000000..5e1db3b
--- /dev/null
+++ b/dijit/tests/Tree_with_JRS.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.Tree Automatic Tests</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "../../dojo/resources/dnd.css";
+		@import "../../dojo/tests/dnd/dndDefault.css";
+		@import "css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+	
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script type="text/javascript" src="helpers.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojox.data.JsonRestStore");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+		dojo.require("dijit.tree.dndSource");
+
+		dojo.addOnLoad(function(){
+			doh.register("Tree tests",
+				[
+					function create(){
+						var d = new doh.Deferred;
+			 			myStore = new dojox.data.JsonRestStore({target:"tree/", labelAttribute:"name"});
+
+			 			doh.t(myStore, "store created");
+
+						myModel = new dijit.tree.ForestStoreModel({
+							store: myStore,
+							deferItemLoadingUntilExpand: true,
+							query: "treeTestRoot",
+							childrenAttrs: ["children"]
+						});
+						doh.t(myModel, "model created");
+
+						myTree = new dijit.Tree({
+							id: "myTree",
+							model: myModel,
+							"label": "Example",
+							persist: false,		// persist==true is too hard to test
+							dndController: "dijit.tree.dndSource" 
+						});
+						doh.t(myTree, "tree created");
+
+						dojo.byId("container").appendChild(myTree.domNode);
+						myTree.startup();
+
+						setTimeout(d.getTestCallback(function(){
+							// Give the tree time to load, and the do checks that it
+							// loaded correctly
+							doh.t(myTree.rootNode, "root node exists");
+							doh.t(myTree.rootNode.isExpanded, "root node is expanded");
+
+							var children = myTree.rootNode.getChildren();
+							doh.is(5, children.length, "six children");
+							doh.is("node1", children[0].label, "first child");
+							doh.f(children[0].isExpanded, "first child not expanded");
+						}), 500);
+						return d;
+					},
+
+					{
+						runTest: function openANode(){
+							var d = new doh.Deferred;
+							
+							var first = myTree.rootNode.getChildren()[0];
+							
+							myTree._onExpandoClick({
+								node: first
+							});
+							setTimeout(function(){
+								var firstFirst = first.getChildren()[0];
+								myTree._onExpandoClick({
+									node: firstFirst
+								});
+								
+								setTimeout(d.getTestCallback(function(){
+									// Give the tree time to load the children, and the do checks that it
+									// loaded correctly
+									
+									var children = firstFirst.getChildren();
+									doh.is(2, children.length, "two children");
+									doh.is("node1.1.1", children[0].label, "first child");
+								}), 500);
+							}, 500);
+							return d;
+						},
+						timeout: 2000
+					}
+				]
+			);
+
+			doh.run();
+		});
+	</script>
+
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit.Tree automated tests</h1>
+	<div id="container"> <!--  tree will go here --></div>
+	<div id="container2"> <!--  tree2 will go here --></div>
+</body>
+</html>
diff --git a/dijit/tests/Widget-placeAt.html b/dijit/tests/Widget-placeAt.html
new file mode 100644
index 0000000..df4a961
--- /dev/null
+++ b/dijit/tests/Widget-placeAt.html
@@ -0,0 +1,152 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>_Widget.placeAt tests</title>
+
+	<!-- test decoration styles -->
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: load the dojo base -->
+	<script type="text/javascript" src="../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+	<!-- for theme-switching, only for dijit -->
+	<script type="text/javascript" src="../../dijit/tests/_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+
+		// load componenets need for this test
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.BorderContainer");
+
+		// run all the tests onload
+		dojo.addOnLoad(function(){
+
+			var pane1, pane2, tc;
+
+			doh.register("dijit.tests.placeAt",
+				[
+					function placeAsDOMNodeChild(){
+						// create a tabcontainer
+						tc = new dijit.layout.TabContainer({
+							style: "height:200px; width:200px"
+						}, "tabContainerThinger").placeAt("container");
+
+						doh.is(dojo.byId("container"), tc.domNode.parentNode, "TabContainer is child of container");
+					},
+
+					function placeAsWidgetChild(){
+						// add the child to the tabcontainer now:
+						pane1 = new dijit.layout.ContentPane({ title:"empty" }).placeAt(tc);
+
+						doh.is(pane1, tc.getChildren()[0], "pane1 is child of TabContainer");
+					},
+
+					function placeAsWidgetChildOrdered(){
+						// add this child (created second) as the first tab:
+						pane2 = new dijit.layout.ContentPane({ title:"first" }).placeAt(tc, 0);
+
+						doh.is(pane2, tc.getChildren()[0], "pane2 is new first child of TabContainer");
+						doh.is(pane1, tc.getChildren()[1], "pane1 is now second child of TabContainer");
+					},
+
+					function startup(){
+						// just starting the TabContainer so we can do some more tests
+						tc.startup();
+						tc.selectChild(pane2);
+					},
+
+					function placeAsFirst(){
+						pane2.set("content","button should appear BEFORE this text");
+
+						// create a button, and add it to pane2 before the above text
+						var button = new dijit.form.Button({
+							label:"alert",
+							onClick: function(){
+								alert('woot');
+							}
+						}).placeAt(pane2.containerNode, "first");
+
+						doh.is(button.domNode, pane2.containerNode.firstChild, "button is first child");
+						doh.is(3, button.domNode.nextSibling.nodeType, "button went before other content");
+					},
+
+					function placeBefore(){
+						// and a button, this time we'll place it before the tabcontainer's dom
+						var otherButton = new dijit.form.Button({
+							label:"destroy tabContainer",
+							onClick:function(){
+								tc.destroyRecursive();
+							}
+						}).placeAt(tc.domNode, "before");
+
+						doh.is(tc.domNode, otherButton.domNode.nextSibling, "otherButton is before tab container");
+					}
+				]
+			);
+			doh.register("dijit.tests.placeAt BorderContainer",
+				[
+					function addPanes(){
+						// Add top and left pane
+						dijit.byId("addStuff").onClick();
+
+						var bc = dijit.byId("bc1");
+						doh.is("<p>wowzers</p>", bc._left.innerHTML.toLowerCase(), "left pane");
+						doh.is("<div>some html text</div>", bc._top.innerHTML.toLowerCase(), "top pane");
+					}
+				]
+			);
+			doh.run();
+		});
+	</script>
+</head>
+<body class="claro">
+	<h1 class="testTitle">_Widget.placeAt tests</h1>
+
+	<div id="container">
+
+	</div>
+
+	<h2>Node2</h2>
+	<p>This is where the tab srcNodeRef is, but it gets moved above us into the id="container" div.  (Should be there already.)</p>
+	<div id="otherContainer">
+		<div id="tabContainerThinger"></div>
+	</div>
+
+	<h2>BorderContainer sample</h2>
+	<div id="bc1" dojoType="dijit.layout.BorderContainer" style="width:600px; height:400px">
+		<div dojoType="dijit.layout.ContentPane" region="center">
+			<button id="addStuff" dojoType="dijit.form.Button">
+				Add Stuff
+				<script type="dojo/method" event="onClick">
+					this.set("disabled", true);
+					var bc = dijit.byId("bc1");
+
+					// add a left pane and add content
+					new dijit.layout.ContentPane({
+						region:"left",
+						style:"width:100px"
+					}).placeAt(bc).set("content","<p>wowzers</p>");
+
+					// add a top pane, and add content
+					new dijit.layout.ContentPane({
+						region:"top",
+						style:"height:100px"
+					}).placeAt(bc).set("content","<div>some HTML text</div>");
+
+				</script>
+			</button>
+		</div>
+	</div>
+
+</body>
+</html>
diff --git a/dijit/tests/_Container.html b/dijit/tests/_Container.html
new file mode 100644
index 0000000..a6b1d68
--- /dev/null
+++ b/dijit/tests/_Container.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Container</title>
+
+	<script type="text/javascript" src="../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit._Widget");
+		dojo.require("dijit._Container");
+		dojo.require("dijit._Contained");
+
+		dojo.declare("dijit.TestContainer",
+			[dijit._Widget, dijit._Container], { }
+		);
+
+		dojo.declare("dijit.TestContained",
+			[dijit._Widget, dijit._Contained], {}
+		);
+
+		dojo.require("dojo.parser");
+
+		dojo.addOnLoad(function(){
+			doh.register("dijit._Container",
+				[
+					{
+						name: "getChildren",
+						runTest: function(t){
+							console.log("getChildren test");
+							var c = dijit.byId("container");
+							var children = c.getChildren();
+							t.is(4, children.length);
+							t.is("zero", children[0].id);
+							t.is("one", children[1].id);
+							t.is("two", children[2].id);
+							t.is("three", children[3].id);
+						}
+					},
+					{
+						name: "_getSiblingOfChild",
+						runTest: function(t){
+							var c = dijit.byId("container");
+							var children = c.getChildren();
+							t.is("one", c._getSiblingOfChild(children[0], 1).id);
+							t.is("two", c._getSiblingOfChild(children[1], 1).id);
+							t.is("three", c._getSiblingOfChild(children[2], 1).id);
+							t.is(null, c._getSiblingOfChild(children[3], 1));
+							t.is(null, c._getSiblingOfChild(children[0], -1));
+							t.is("zero", c._getSiblingOfChild(children[1], -1).id);
+							t.is("one", c._getSiblingOfChild(children[2], -1).id);
+							t.is("two", c._getSiblingOfChild(children[3], -1).id);
+						}
+					},
+					{
+						name: "getIndexOfChild",
+						runTest: function(t){
+							var c = dijit.byId("container");
+							t.is(0, c.getIndexOfChild(dijit.byId("zero")));
+							t.is(1, c.getIndexOfChild(dijit.byId("one")));
+							t.is(2, c.getIndexOfChild(dijit.byId("two")));
+							t.is(3, c.getIndexOfChild(dijit.byId("three")));
+							t.is(-1, c.getIndexOfChild(dijit.byId("outside")));
+							t.is(-1, c.getIndexOfChild(dijit.byId("outsideCont")));
+						}
+					},
+					{
+						name: "getIndexInParent",
+						runTest: function(t){
+							t.is(0, dijit.byId("zero").getIndexInParent());
+							t.is(1, dijit.byId("one").getIndexInParent());
+							t.is(2, dijit.byId("two").getIndexInParent());
+							t.is(-1, dijit.byId("outsideCont").getIndexInParent());
+						}
+					},
+					{
+						name: "removeChild",
+						runTest: function(t){
+							var c = dijit.byId("container");
+							var children = c.getChildren();
+							t.is(4, children.length);
+							c.removeChild(dijit.byId("zero"));
+							c.removeChild(1); // should remove "two" - because zero is already removed
+							children = c.getChildren();
+							t.is(2, children.length);
+							t.is("one", children[0].id);
+							t.is("three", children[1].id);
+						}
+					}
+				]
+			);
+			doh.run();
+		});
+
+	</script>
+</head>
+<body class="claro">
+
+	<div id="container" dojoType="dijit.TestContainer">
+		<div id="zero" dojoType="dijit.TestContained"></div>
+		<div id="one" dojoType="dijit.TestContained"></div>
+		<div id="two" dojoType="dijit.TestContained"></div>
+		<div id="three" dojoType="dijit._Widget"></div>
+	</div>
+	<div id="outside" dojoType="dijit._Widget"></div>
+	<div id="outsideCont" dojoType="dijit.TestContained"></div>
+</body>
+</html>
diff --git a/dijit/tests/_Templated-widgetsInTemplate.html b/dijit/tests/_Templated-widgetsInTemplate.html
new file mode 100644
index 0000000..867c0c5
--- /dev/null
+++ b/dijit/tests/_Templated-widgetsInTemplate.html
@@ -0,0 +1,473 @@
+<html>
+	<head>
+		<title>testing widgetsInTemplate support</title>
+		<script type="text/javascript" src="../../dojo/dojo.js"
+			djConfig="parseOnLoad: true, isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.form.CheckBox");
+			dojo.require("dijit.ProgressBar");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dijit.layout.TabContainer");
+			dojo.require("dijit._Container");
+			dojo.require("dijit._Contained");
+			dojo.require("dijit.layout._LayoutWidget");
+
+			dojo.addOnLoad(function(){
+				var testW;
+				doh.register("t",
+					[
+						{
+							name: "dojoAttachPoint",
+							runTest: function(t){
+								var testW = dijit.byId("test1Widget");
+								t.t(testW.normalNode, "normalNode");
+								t.f(isNaN(testW.normalNode.nodeType), "normalNode.nodeType");
+								t.t(testW.buttonWidget instanceof dijit.form.Button, "buttonWidget is Button");
+								t.t(testW.checkboxWidget instanceof dijit.form.CheckBox, "checkboxWidget is CheckBox");
+								t.t(testW.progressBarWidget instanceof dijit.ProgressBar, "progressBarWidget is ProgressBar");
+								testW = dijit.byId("test2Widget");
+								t.t(testW.containerNode, "containerNode");
+								t.f(isNaN(testW.containerNode.nodeType), "containerNode nodeType");
+								t.is(undefined,testW.buttonWidget, "buttonWidget undefined");
+								t.t(testW.checkboxWidget instanceof dijit.form.CheckBox, "checkboxWidget is still CheckBox");
+							}
+						},
+						{
+							name: "dojoAttachEvent",
+							runTest: function(t){
+								var testW = dijit.byId("test1Widget");
+								testW.buttonWidget._counter=0;
+								testW.buttonWidget.onClick(testW.buttonWidget);
+								testW.checkboxWidget._counter=0;
+								testW.checkboxWidget.onClick(testW.checkboxWidget);
+								testW.progressBarWidget._counter=0;
+								testW.progressBarWidget.onChange(testW.progressBarWidget);
+								t.is(1,testW.buttonWidget._counter, "buttonWidget._counter");
+								t.is(1,testW.checkboxWidget._counter, "checkboxWidget._counter");
+								t.is(1,testW.progressBarWidget._counter, "progressBarWidget._counter");
+							}
+						},
+						{
+							// Test that getDescendants ()
+							// finds direct descendants but skips widgetsInTemplates
+							// and also nested widgets (if direct==true)
+							name: "destruction",
+							runTest: function(t){
+								var testW = dijit.byId("test3Widget");
+
+
+/*** performance tests
+								var start = new Date();
+								for(var i=0; i<1000; i++)
+									testW.getChildren();
+								console.log("*** time for getChildren(): " + (new Date()-start));
+								var start = new Date();
+								for(var i=0; i<1000; i++)
+									testW.getDescendants();
+								console.log("*** time for getDescendants(false): " + (new Date()-start));
+***/
+								var desc = testW.getChildren();
+								t.is(5, desc.length, "number of direct descendants");
+								t.is(desc[0].id, "3.1");
+								t.is(desc[1].id, "3.2");
+								t.is(desc[2].id, "3.3");
+								t.is(desc[3].id, "3.4");
+								t.is(desc[4].id, "3.5");
+
+								var desc = testW.getDescendants();
+								t.is(7, desc.length, "number of descendants (including nested ones)");
+								t.is(desc[0].id, "3.1");
+								t.is(desc[1].id, "3.2");
+								t.is(desc[2].id, "3.3");
+								t.is(desc[3].id, "3.nested");
+								t.is(desc[4].id, "3.nested2");
+								t.is(desc[5].id, "3.4");
+								t.is(desc[6].id, "3.5");
+							}
+						},
+						{
+							// Check that declarative widget with layout widgets in template is correctly created and rendered
+							name: "declarative widget with layout widgets",
+							runTest: function(t){
+								validateTest4Widget(t, dijit.byId("test4Widget"));
+							}
+						},
+						{
+							// Check that programmatic widget with layout widgets in template is correctly created and rendered
+							name: "programmatic widget with layout widgets",
+							runTest: function(t){
+								validateTest4Widget(t, test4WidgetProgrammatic);
+							}
+						},
+						{
+							// Compare programmatic and declaratively created widget with layout widgets in template
+							name: "programmatic vs declarative with layout widgets",
+							runTest: function(t){
+								// Focus the body, so that we don't have different classes on our
+								// two widgets
+								dijit.focus(dojo.body());
+								var declW = dijit.byId("test4Widget");
+								var progW = test4WidgetProgrammatic;
+
+								// Check that generated HTML in DOM is same
+								var declNeutralHtml = declW.domNode.innerHTML.replace(/_\d+/g, "");
+								var progNeutralHtml = progW.domNode.innerHTML.replace(/_\d+/g, "");
+								t.is(declNeutralHtml, progNeutralHtml, "progNeutralHtml");
+
+								// Check that dimensions are same
+								var declBox = dojo.contentBox(declW.domNode);
+								var progBox = dojo.contentBox(progW.domNode);
+								t.is(declBox.h, progBox.h, "progBox.h");
+								t.is(declBox.w, progBox.w, "progBox.w");
+							}
+						},
+						{
+							// Check that declarative widget with other widgets in template is correctly started
+							name: "declarative widget with many child widgets",
+							runTest: function(t){
+								validateTest5Widget(t, dijit.byId("test5Widget"));
+							}
+						},
+						{
+							// Check that programmatic widget with other widgets in template is correctly started
+							name: "programmatic widget with many child widgets",
+							runTest: function(t){
+								validateTest5Widget(t, test5WidgetProgrammatic);
+							}
+						},
+						{
+							// Check that destroying our declarative widget works correctly
+							name: "declarative widget destruction",
+							runTest: function(t){
+								validateTest5WidgetDestroy(t, dijit.byId("test5Widget"));
+							}
+						},
+						{
+							// Check that destroying our programmatic widget works correctly
+							name: "programmatic widget destruction",
+							runTest: function(t){
+								validateTest5WidgetDestroy(t, test5WidgetProgrammatic);
+							}
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "../themes/tundra/tundra.css";
+	</style>
+	</head>
+	<body class="claro">
+		<h1>testing widgetsInTemplate support</h1>
+		<xmp id="Test1Template" style="display:none;">
+			<div>
+				<div dojoAttachPoint="normalNode" >normal node</div>
+				<button dojoAttachPoint="buttonWidget" dojoAttachEvent="onClick:onClick" dojoType="dijit.form.Button">button #1</button>
+				<div dojoAttachPoint="checkboxWidget" dojoAttachEvent="onClick:onClick" dojoType="dijit.form.CheckBox"></div> checkbox #1
+				<div dojoAttachPoint="progressBarWidget" dojoAttachEvent="onChange:onClick" style="width:400px"
+					maximum="200" progress="20" dojoType="dijit.ProgressBar"></div>
+			</div>
+		</xmp>
+		<script>
+			dojo.declare('Test1Widget',
+				[dijit._Widget, dijit._Templated],
+			{
+				widgetsInTemplate: true,
+		//		isContainer: true,
+
+				templateString: dojo.byId('Test1Template').textContent || dojo.byId('Test1Template').innerText,
+				onClick: function(e){
+					if(e.target){
+						alert('onClick widgetId='+e.target.id);
+					}else{
+						if(e._counter == undefined){
+							e._counter = 1;
+						}else{
+							e._counter++;
+						}
+					}
+				}
+			});
+		</script>
+	<!-- can use widget immediately in markup - no parsing occurs until document loaded and scripts run -->
+	<div dojoType="Test1Widget" id="test1Widget" ></div>
+
+	<!-- TODO: this is a strange test; the containerNode shouldn't have any contents as they will be overwritten -->
+	<xmp id="Test2Template" style="display:none;">
+		<div>
+			<div dojoAttachPoint="containerNode" >
+				<div dojoAttachPoint="checkboxWidget" dojoType="dijit.form.CheckBox"></div>
+				checkbox #2
+			</div>
+		</div>
+	</xmp>
+		<script>
+			dojo.declare('Test2Widget',
+				[dijit._Widget, dijit._Templated],
+			{
+				widgetsInTemplate: true,
+
+				templateString: dojo.byId('Test2Template').textContent || dojo.byId('Test2Template').innerText
+			});
+		</script>
+	<div dojoType="Test2Widget" id="test2Widget" ><button dojoAttachPoint="buttonWidget" dojoType="dijit.form.Button">button #2</button></div>
+
+
+	<xmp id="Test3Template" style="display:none;">
+		<div>
+			<div dojoAttachPoint="checkboxWidget" dojoType="dijit.form.CheckBox"></div> checkbox #3
+			<div dojoAttachPoint="containerNode" ></div>
+		</div>
+	</xmp>
+		<script>
+			dojo.declare('Test3Widget',
+				[dijit._Widget, dijit._Templated],
+			{
+				widgetsInTemplate: true,
+
+				templateString: dojo.byId('Test3Template').textContent || dojo.byId('Test3Template').innerText
+			});
+		</script>
+	<div dojoType="Test3Widget" id="test3Widget" >
+		<span>hello world</span>
+		<b style="border: 1px solid blue;">this is my
+			<button dojoType="dijit.form.Button" id="3.1">first button</button>
+		</b>
+		<button dojoType="dijit.form.Button" id="3.2">another button</button>
+		<i>and some more</i>
+		<div style="border: 1px solid red;">
+			<div dojoType="dijit.layout.ContentPane" style="border: 1px solid gray;" id="3.3">
+				<button dojoType="dijit.form.Button" id="3.nested">a nested button</button>
+				<button dojoType="dijit.form.Button" id="3.nested2">another nested button</button>
+			</div>
+			<button dojoType="dijit.form.Button" id="3.4">yet another button</button>
+			<button dojoType="dijit.form.Button" id="3.5">yet yet another button</button>
+		</div>
+	</div>
+
+	<!-- Test templated widget containing layout widgets in template -->
+	<xmp id="Test4Template" style="display:none;">
+		<div>
+			<div dojoType="dijit.layout.TabContainer" dojoAttachPoint="tabCont" style="height: 5em;">
+				<div dojoType="dijit.layout.ContentPane" dojoAttachPoint="tab1" title="Tab 1">
+					pane 1
+				</div>
+				<div dojoType="dijit.layout.ContentPane" dojoAttachPoint="tab2" title="Tab 2">
+					pane 2
+				</div>
+			</div>
+		</div>
+	</xmp>
+	<script>
+		dojo.declare('Test4Widget',
+			[dijit._Widget, dijit._Templated],
+		{
+			widgetsInTemplate: true,
+
+			templateString: dojo.byId('Test4Template').textContent || dojo.byId('Test4Template').innerText
+		});
+
+		var test4WidgetProgrammatic;
+		dojo.addOnLoad(function(){
+			test4WidgetProgrammatic = new Test4Widget({dir: "ltr"}).placeAt("test4Widget", "after");
+			test4WidgetProgrammatic.startup();
+		});
+
+		function validateTest4Widget(t, testW) {
+			var selectedTab = dojo.query(".dijitTabChecked", testW.domNode)[0];
+			var selectedPane = dojo.query(".dijitTabPane.dijitVisible", testW.domNode)[0];
+			var tabBox = selectedTab ? dojo.contentBox(selectedTab) : null;
+			var paneBox = selectedPane ? dojo.contentBox(selectedPane) : null;
+			t.t(tabBox && tabBox.w > 0 && tabBox.h > 0, "tabBox && tabBox.w > 0 && tabBox.h > 0");
+			t.t(paneBox && paneBox.w > 0 && paneBox.h > 0, "paneBox && paneBox.w > 0 && paneBox.h");
+			// Check that everything got started
+			t.t(testW._started, "testW._started");
+			t.t(testW.tabCont._started, "tabCont._started");
+			t.t(testW.tab1._started, "tab1._started");
+			t.t(testW.tab2._started, "tab2._started");
+		}
+	</script>
+	<div dojoType="Test4Widget" id="test4Widget" ></div>
+
+	<!-- Test templated widget containing container and nested widgets in template -->
+	<xmp id="Test5Template" style="display:none;">
+		<div>
+			<div dojoType="TestLayoutWidget" dojoAttachPoint="layout">
+				<div dojoType="TestCtndWidget" dojoAttachPoint="layChild1"></div>
+				<div dojoType="TestCtndWidget" dojoAttachPoint="layChild2"></div>
+			</div>
+			<div dojoType="TestCtnrWidget" dojoAttachPoint="container">
+				<div dojoType="TestCtndWidget" dojoAttachPoint="contained1"></div>
+				<div dojoType="TestCtndWidget" dojoAttachPoint="contained2"></div>
+			</div>
+			<div dojoType="TestStubWidget" dojoAttachPoint="stub1"></div>
+			<div dojoType="TestNonCtnrWidget" dojoAttachPoint="nonContainer">
+				<div dojoType="TestStubWidget" dojoAttachPoint="nonContained1"></div>
+				<div dojoType="TestStubWidget" dojoAttachPoint="nonContained2"></div>
+			</div>
+			<div dojoType="TestCtnrWidget" dojoAttachPoint="threeLevel">
+				<div dojoType="TestNonCtnrWidget" dojoAttachPoint="secondLevel">
+					<div dojoType="TestStubWidget" dojoAttachPoint="bottomLevel"></div>
+				</div>
+			</div>
+			<div dojoType="TestNonCtnrWidget" dojoAttachPoint="anotherThree">
+				<div dojoType="TestCtnrWidget" dojoAttachPoint="anotherSecond">
+					<div dojoType="TestCtndWidget" dojoAttachPoint="anotherBottom"></div>
+				</div>
+			</div>
+		</div>
+	</xmp>
+	<script>
+		dojo.declare('TestLayoutWidget', dijit.layout._LayoutWidget, {
+			startup: function(){
+				if(this._started){
+					this._doubleStarted = true;
+				}
+				this.inherited(arguments);
+			},
+			destroy: function(){
+				if(this._destroyed){
+					this._doubleDestroyed = true;
+				}
+				this.inherited(arguments);
+				this._destroyed = true;
+			}
+		});
+		dojo.declare('TestCtnrWidget', [dijit._Widget, dijit._Container], {
+			startup: function(){
+				if(this._started){
+					this._doubleStarted = true;
+				}
+				this.inherited(arguments);
+			},
+			destroy: function(){
+				if(this._destroyed){
+					this._doubleDestroyed = true;
+				}
+				this.inherited(arguments);
+				this._destroyed = true;
+			}
+		});
+		dojo.declare('TestCtndWidget', [dijit._Widget, dijit._Contained], {
+			startup: function(){
+				if(this._started){
+					this._doubleStarted = true;
+				}
+				this.inherited(arguments);
+			},
+			destroy: function(){
+				if(this._destroyed){
+					this._doubleDestroyed = true;
+				}
+				this.inherited(arguments);
+				this._destroyed = true;
+			}
+		});
+		dojo.declare('TestNonCtnrWidget', [dijit._Widget, dijit._Templated], {
+			templateString: "<div dojoAttachPoint=containerNode></div>",
+			startup: function(){
+				if(this._started){
+					this._doubleStarted = true;
+				}
+				this.inherited(arguments);
+			},
+			destroy: function(){
+				if(this._destroyed){
+					this._doubleDestroyed = true;
+				}
+				this.inherited(arguments);
+				this._destroyed = true;
+			}
+		});
+		dojo.declare('TestStubWidget', dijit._Widget, {
+			startup: function(){
+				if(this._started){
+					this._doubleStarted = true;
+				}
+				this.inherited(arguments);
+			},
+			destroy: function(){
+				if(this._destroyed){
+					this._doubleDestroyed = true;
+				}
+				this.inherited(arguments);
+				this._destroyed = true;
+			}
+		});
+
+		dojo.declare('Test5Widget',
+			[dijit._Widget, dijit._Templated],
+		{
+			widgetsInTemplate: true,
+
+			templateString: dojo.byId('Test5Template').textContent || dojo.byId('Test5Template').innerText,
+			startup: function(){
+				if(this._started){
+					this._doubleStarted = true;
+				}
+				this.inherited(arguments);
+			},
+			destroy: function(){
+				if(this._destroyed){
+					this._doubleDestroyed = true;
+				}
+				this.inherited(arguments);
+				this._destroyed = true;
+			}
+		});
+
+		var test5WidgetProgrammatic;
+		dojo.addOnLoad(function(){
+			test5WidgetProgrammatic = new Test5Widget().placeAt("test5Widget", "after");
+			test5WidgetProgrammatic.startup();
+		});
+
+		function getTestWidgets(testW){
+			return [
+				testW,
+				testW.layout,
+				testW.layChild1,
+				testW.layChild2,
+				testW.container,
+				testW.contained1,
+				testW.contained2,
+				testW.nonContainer,
+				testW.nonContained1,
+				testW.nonContained2,
+				testW.threeLevel,
+				testW.secondLevel,
+				testW.bottomLevel,
+				testW.anotherThree,
+				testW.anotherSecond,
+				testW.anotherBottom,
+				testW.stub1
+			];
+		}
+
+		function validateTest5Widget(t, testW) {
+			// Check that everything got started, but not double-started
+			dojo.forEach(getTestWidgets(testW), function(w){
+				t.t(w._started, "w._started: " + w);
+				t.is(undefined, w._doubleStarted, "w._doubleStarted: " + w);
+			});
+		}
+
+		function validateTest5WidgetDestroy(t, testW) {
+			var savedWidgets = getTestWidgets(testW);
+			testW.destroy();
+			dojo.forEach(savedWidgets, function(w, idx){
+				t.t(w._destroyed, "w._destroyed: " + w);
+				t.is(undefined, w._doubleDestroyed, "w._doubleDestroyed: " + w);
+			});
+		}
+	</script>
+	<div dojoType="Test5Widget" id="test5Widget" ></div>
+
+	</body>
+</html>
+
diff --git a/dijit/tests/_Templated.html b/dijit/tests/_Templated.html
new file mode 100644
index 0000000..055fd15
--- /dev/null
+++ b/dijit/tests/_Templated.html
@@ -0,0 +1,220 @@
+<html>
+	<head>
+		<title>_Templated tests</title>
+		<script type="text/javascript" src="../../dojo/dojo.js"
+			djConfig="parseOnLoad: true, isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+
+			dojo.require("dijit._Widget");
+			dojo.require("dijit._Templated");
+
+			dojo.require("dijit.layout.LayoutContainer");
+
+			function getOuterHTML(/*DomNode*/ node){
+				var wrapper = dojo.doc.createElement("div");
+				wrapper.appendChild(node);
+				return wrapper.innerHTML.toLowerCase();		// IE prints <BUTTON> rather than <button>; normalize it.
+			}
+
+			dojo.addOnLoad(function(){
+				// Template with no variables (should be cached as a DOM tree)
+				dojo.declare("SimpleTemplate", [dijit._Widget, dijit._Templated], {
+					attributeMap: {},
+					id: "test1",
+					templateString: "<button><span>hello < world</span></button>"
+				});
+
+				// Template with variables
+				dojo.declare("VariableTemplate", [dijit._Widget, dijit._Templated], {
+					attributeMap: {},
+					id: "test2",
+					num: 5,
+					bool: false,
+					text: "hello <\"' world",
+
+					templateString: "<button><span num=\"${num}\" value=\"${bool}\">${text}</span></button>"
+				});
+
+				// Template with ! variables (for literal substitution)
+				dojo.declare("ExclamationVariableTemplate", [dijit._Widget, dijit._Templated], {
+					attributeMap: {},
+					markup: "<span>hello world</span>",
+
+					templateString: "<div>${!markup}</div>"
+				});
+
+				// Template that starts with special node (has to be constructed inside a <tbody>)
+				dojo.declare("TableRowTemplate", [dijit._Widget, dijit._Templated], {
+					attributeMap: {},
+					id: "test3",
+					text: "bar",
+					templateString: "<tr><td>${text}</td></tr>"
+				});
+
+				// Illegal subsitition variable name
+				dojo.declare("IllegalSubstitution", [dijit._Widget, dijit._Templated], {
+					templateString: "<tr><td>${fake}</td></tr>"
+				});
+
+				// dojoAttachPoint
+				dojo.declare("AttachPoint", [dijit._Widget, dijit._Templated], {
+					attributeMap: {foo: "", style: "", bar: "buttonNode"},
+					templateString: "<div style='border: 1px solid red'>" +
+										"<button dojoAttachPoint='buttonNode,focusNode'>hi</button>" +
+										'<span><input dojoAttachPoint="inputNode" value="input"></span>' +
+										"<span dojoAttachPoint='containerNode'></span>" +
+									"</div>"
+				});
+
+				// dojoAttachEvent
+				dojo.declare("AttachEvent", [dijit._Widget, dijit._Templated], {
+					click: function(){ this.clickCalled=true; },
+					onfocus: function(){ this.focusCalled=true; },
+					focus2: function(){ this.focus2Called=true; },
+					templateString: "<table style='border: 1px solid blue'><tr>" +
+										"<td><button dojoAttachPoint='left' dojoAttachEvent='onclick: click, onfocus'>left</button></td>" +
+										"<td><button dojoAttachPoint='right' dojoAttachEvent='onclick: click, onfocus: focus2'>right</button></td>" +
+									"</tr></table>"
+				});
+
+				var testW;
+				doh.register("dijit.tests._Templated.html",
+					[
+						function simple(t){
+							var widget=new SimpleTemplate();
+							var wrapper=dojo.byId("simpleWrapper");
+							wrapper.appendChild(widget.domNode);
+							t.is('<button widgetid=\"test1\"><span>hello < world</span></button>', wrapper.innerHTML.toLowerCase());
+						},
+
+						function variables(t){
+							var widget=new VariableTemplate();
+							var span = widget.domNode.getElementsByTagName("span")[0];
+							var text = span.innerHTML;
+							t.is("5", span.getAttribute("num"));
+							t.is("false", span.getAttribute("value"));
+							t.is("hello <\"' world", text);
+						},
+						function variables2(t){
+							var widget = new VariableTemplate({id: "myid", num: -5, bool: true, text: ""});
+							var span = widget.domNode.getElementsByTagName("span")[0];
+							var text = span.innerHTML;
+							t.is("-5", span.getAttribute("num"));
+							t.is("true", span.getAttribute("value"));
+							t.is("", text);
+						},
+						function variablesWithExclamation(t){
+							var widget=new ExclamationVariableTemplate();
+
+							// ExclamationVariableTemplate should create markup like
+							//		<div><span>hello world</span></div>
+							// The <span> comes from the ${!markup} variable.
+							var span = dojo.query(">", widget.domNode);
+							t.is(1, span.length, "dom node has one child");
+							t.is("SPAN", span[0].nodeName.toUpperCase(), "which is a span");
+							t.is("hello world", span[0].innerHTML, "and the text is set correctly too");
+						},
+
+						function table(t){
+							var widget=new TableRowTemplate({text: "hello"});
+							var wrapper = dojo.byId("trWrapper");
+							wrapper.appendChild(widget.domNode);
+							var actual = wrapper.innerHTML.toLowerCase().replace(/\r/g, "").replace(/\n/g, "");
+							t.is('<tr widgetid="test3"><td>hello</td></tr>', actual);
+						},
+						function illegal(t){
+							var hadException=false;
+							try{
+								var widget=new IllegalSubstitution();
+							}catch(e){
+								console.log(e);
+								hadException=true;
+							}
+							t.t(hadException);
+						},
+						function attachPoint(t){
+							var widget=new AttachPoint();
+							var wrapper = dojo.byId("attachPointWrapper");
+							wrapper.appendChild(widget.domNode);
+							t.is(widget.containerNode.tagName.toLowerCase(), "span");
+							t.is(widget.buttonNode.tagName.toLowerCase(), "button");
+							t.is(widget.focusNode.tagName.toLowerCase(), "button");
+							t.is(widget.inputNode.tagName.toLowerCase(), "input");
+						},
+						function attachEvent(t){
+							var deferred = new doh.Deferred();
+							var widget = new AttachEvent();
+							var wrapper = dojo.byId("attachEventWrapper");
+							wrapper.appendChild(widget.domNode);
+							widget.left.focus();
+							widget.right.focus();
+							setTimeout(deferred.getTestCallback(function(){
+								t.t(widget.focusCalled, "left focused");
+								t.t(widget.focus2Called, "right focused");
+							}), 50);
+							return deferred;
+						},
+
+						function widgetsInTemplateLifecycle(t){
+
+							var result = [], expected = [1,1,0,2,2,3];
+
+							// widgetsInTemplateLifecycle
+							dojo.declare("SubThing", dijit._Widget, {
+								postCreate:function(){
+									this.inherited(arguments);
+									result.push(1);
+								},
+								startup:function(){
+									this.inherited(arguments);
+									result.push(2);
+								}
+							});
+
+							dojo.declare("ParentThing", [dijit._Widget, dijit._Templated], {
+								widgetsInTemplate:true,
+								templateString: "<div>" +
+													"<span dojoType='SubThing'>a</span>" +
+													"<div dojoType='dijit.layout.LayoutContainer'>" +
+														"<span dojoType='SubThing'>b</span>" +
+													"</div>" +
+												"</div>",
+								postCreate:function(){
+									// children postcreate (x2) called before this postCreate
+									this.inherited(arguments);
+									result.push(0);
+								},
+								startup: function(){
+									// then children startup (x2) then our startup
+									// (we can call inherited after push(), and change the order)
+									this.inherited(arguments);
+									result.push(3);
+								}
+							});
+
+							new ParentThing().startup();
+
+							t.is(expected.length, result.length);
+							dojo.forEach(expected, function(r){
+								t.is(r, result.shift());
+							});
+
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	<style type="text/css">
+		@import "../themes/tundra/tundra.css";
+	</style>
+	</head>
+	<body>
+		<h1>_Templated test</h1>
+		<div id="simpleWrapper"></div>
+		<table><tbody id="trWrapper"></tbody></table>
+		<div id="attachPointWrapper"></div>
+		<div id="attachEventWrapper"></div>
+	</body>
+</html>
diff --git a/dijit/tests/_Widget-attr.html b/dijit/tests/_Widget-attr.html
new file mode 100644
index 0000000..287db8d
--- /dev/null
+++ b/dijit/tests/_Widget-attr.html
@@ -0,0 +1,156 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Widget.get()/set() unit test</title>
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit.dijit");
+
+		dojo.declare("Baz",
+			[ dijit._Widget, dijit._Templated ],
+			{
+				templateString: "<div><div dojoAttachPoint='nameNode'></div><span>${attr1}</span></div>",
+
+				attributeMap: {
+					name: {node: "nameNode", type: "innerHTML" }
+				},
+
+				name: "howdy!",
+
+				attr1: 0,
+				_setAttr1Attr: function(value){
+					this.domNode.lastChild.innerHTML = value;
+					this.attr1 = value;
+				},
+
+				attr2: 0,
+				_getAttr2Attr: function(){
+				}
+			}
+		);
+		dojo.declare("Textbox",
+			[ dijit._Widget, dijit._Templated ],
+			{
+				attributeMap: {id:"", dir:"", lang:"", "class":"", style:"", title:"", disabled: "", readonly: ""},
+				templateString: "<input>"
+			}
+		);
+
+		dojo.declare("Thud", Baz, {
+			get: function(name){
+				// default getter
+			},
+			set: function(name, value){
+				// default setter
+			}
+		});
+
+		dojo.declare("AttrMap", [dijit._Widget, dijit._Templated], {
+			attributeMap: {foo: "", bar: "buttonNode", plainText: {node: "plainTextNode", type: "innerText"}},
+			templateString: "<div class='class1' style='border: 1px solid red; width: 456px'>" +
+								"<button dojoAttachPoint='buttonNode,focusNode'>hi</button>" +
+								'<span><input dojoAttachPoint="inputNode" value="input"></span>' +
+								"<span dojoAttachPoint='containerNode'></span>" +
+								"<span dojoAttachPoint='plainTextNode'>original plain text</span>" +
+							"</div>"
+		});
+
+		dojo.addOnLoad(function(){
+			doh.register("dijit.attr",
+				[
+					function attr(){
+						var b = new Baz();
+
+						// widget attribute mapped to DOM node innerHTML
+						dojo.body().appendChild(b.domNode);
+						doh.is("howdy!", b.attr("name"));
+						doh.is("howdy!", b.nameNode.innerHTML);
+						b.attr("name", "thinger");
+						doh.is(b.attr("name"), "thinger");
+						doh.is(b.nameNode.innerHTML, "thinger");
+
+						// hash setting
+						b.attr({
+							name: "bang",
+							foo: "zap"
+						});
+						doh.is("bang", b.attr("name"));
+						doh.is("zap", b.attr("foo"));
+					},
+					function setGet(){
+						var b = new Baz();
+
+						// widget attribute mapped to DOM node innerHTML
+						dojo.body().appendChild(b.domNode);
+						doh.is("howdy!", b.get("name"));
+						doh.is("howdy!", b.nameNode.innerHTML);
+						b.set("name", "thinger");
+						doh.is(b.get("name"), "thinger");
+						doh.is(b.nameNode.innerHTML, "thinger");
+
+						// hash setting
+						b.set({
+							name: "bang",
+							foo: "zap"
+						});
+						doh.is("bang", b.get("name"));
+						doh.is("zap", b.get("foo"));
+					},
+
+					function domSetGet(){
+						// test setting widget attributes corresponding to DOM node attributes
+						var t = new Textbox();
+						doh.assertFalse(t.get("disabled"));
+						t.set("disabled", true);
+						doh.assertTrue(dojo.attr(t.domNode, "disabled"));
+						doh.assertTrue(t.get("disabled"));
+					},
+
+					function domInnerHTML(){
+						// test initializing widget attributes corresponding to DOM node innerHTML
+						var b2 = new Baz({
+							foo: "blah",
+							name: "whatever"
+						});
+						doh.is("whatever", b2.get("name"));
+						doh.is("whatever", b2.nameNode.innerHTML);
+					},
+					function attributeMap(){
+						var widget = new AttrMap({
+							foo:"value1",
+							bar:"value2",
+							"class":"class2",
+							style:"height: 123px",
+							plainText: "hello world <>&;"
+						});
+						var wrapper = dojo.byId("attributeMapWrapper");
+						wrapper.appendChild(widget.domNode);
+						doh.is("value1", widget.domNode.getAttribute("foo"));
+						doh.is("value2", widget.buttonNode.getAttribute("bar"));
+						doh.assertTrue(dojo.hasClass(widget.domNode, "class1"));
+						doh.assertTrue(dojo.hasClass(widget.domNode, "class2"));
+						doh.is("123px", dojo.style(widget.domNode).height);
+						doh.is("456px", dojo.style(widget.domNode).width);
+						doh.is("hello world <>&;", widget.plainTextNode.innerHTML);
+					}
+				]
+			);
+			doh.run();
+		});
+
+	</script>
+</head>
+<body>
+	<h1>Dijit Widget.get()/set() Unit Test</h1>
+	<div id="attributeMapWrapper"></div>
+</body>
+</html>
diff --git a/dijit/tests/_Widget-connect-performance.html b/dijit/tests/_Widget-connect-performance.html
new file mode 100644
index 0000000..17e5297
--- /dev/null
+++ b/dijit/tests/_Widget-connect-performance.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Test Dijit Internal Event: "ondijitclick"</title>
+
+	<script type="text/javascript" src="../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit._Widget");
+		dojo.require("dojo.parser");
+
+		dojo.declare("dijit.MyWidget", dijit._Widget, {
+			_eventHandler: function(){}
+		});
+
+		dojo.addOnLoad(function(){
+			var connects = [];
+			doh.register("_widgetConnect",
+				[
+					{
+						name: "_Widget.connect x 100",
+						runTest: function(t){
+							var w = dijit.byId("widget1");
+							var n = dojo.byId("externalNode");
+							var sLen = w._connects.length;
+							for(var i = 0; i < 100; i++){
+								connects.push(w.connect(n, "onblur", "_eventHandler"));
+							}
+							t.is(100, w._connects.length - sLen);
+						}
+					},
+					{
+						name: "_Widget.connect - ondijitclick x 100",
+						runTest: function(t){
+							var w = dijit.byId("widget1");
+							var n = dojo.byId("externalNode");
+							var sLen = w._connects.length;
+							for(var i = 0; i < 100; i++){
+								connects.push(w.connect(n, "ondijitclick", "_eventHandler"));
+							}
+							t.is(100, w._connects.length - sLen);
+						}
+					},
+					{
+						name: "_Widget.disconnect x 200",
+						runTest: function(t){
+							var w = dijit.byId("widget1");
+							var n = dojo.byId("externalNode");
+							var sLen = w._connects.length;
+							for(var i = 0; i < 200; i++){
+								w.disconnect(connects[i]);
+							}
+							connects = [];
+							t.is(200, sLen - w._connects.length);
+						}
+					}
+				]
+			);
+			doh.run();
+		});
+
+	</script>
+</head>
+<body class="claro">
+	<div id="externalNode"></div>
+	<div id="widget1" dojoType="dijit.MyWidget"></div>
+</body>
+</html>
diff --git a/dijit/tests/_Widget-deferredConnect.html b/dijit/tests/_Widget-deferredConnect.html
new file mode 100644
index 0000000..271378b
--- /dev/null
+++ b/dijit/tests/_Widget-deferredConnect.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>_Widget deferred connection test</title>
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "../themes/tundra/tundra.css";
+		@import "css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script>
+		dojo.require("dijit.form.Button");
+
+		overrodeMouseMoved = false;
+		bothOverrodeMouseMoved = false;
+		connectedMouseMoved = false;
+		bothConnectedMouseMoved = false;
+
+		function bothHandler(){
+			if(!bothOverrodeMouseMoved){
+				console.log("'both' button: overrode handler called");
+			}
+			bothOverrodeMouseMoved = true;
+		}
+
+		dojo.addOnLoad(function(){
+			dojo.connect(dijit.byId("connect"), "onMouseMove", function(){
+				if(!connectedMouseMoved){
+					console.log("'connect' button: mouse moved");
+				}
+				connectedMouseMoved = true;
+			});
+
+			dojo.connect(dijit.byId("both"), "onMouseMove", function(){
+				if(!bothConnectedMouseMoved){
+					console.log("'both' button: connected handler");
+				}
+				bothConnectedMouseMoved = true;
+			});
+		});
+
+	</script>
+</head>
+<body class="claro">
+	<h1>Test deferred connections</h1>
+	<p>
+		OnMouseMove is a deferred connection, _Widget only call dojo.connect()
+		(dojoAttachEvent) to connect the onmousemove event on the focusNode to
+		the widget method if needed.
+	</p>
+	<p>
+		Mousing over the three buttons below should call the user-defined mouse-move
+		handlers.  The "both" button has two handlers, and they should both be called.
+	</p>
+
+	<!--
+		"overrode" button specifies an onmousemove handler on initialization.
+	-->
+	<button id="overrode" dojoType="dijit.form.Button"
+		onMouseMove="if(!overrodeMouseMoved){ console.log('\'overrode\' button: mouse moved'); } overrodeMouseMoved = true;">
+		overrode
+	</button>
+
+	<!--
+		"connect" button essentially is doing a dojo.connect("connect", "onMouseMove", myFunc).
+		This should trigger an additional dojo.connect() call from Button.focusNode.onmousemove
+		to the Button.onMouseMove empty function.
+	-->
+	<button id="connect" dojoType="dijit.form.Button">
+		connected
+	</button>
+
+	<button id="both" dojoType="dijit.form.Button" onMouseMove="bothHandler">
+		both
+	</button>
+</body>
+</html>
diff --git a/dijit/tests/_Widget-lifecycle.html b/dijit/tests/_Widget-lifecycle.html
new file mode 100644
index 0000000..794df16
--- /dev/null
+++ b/dijit/tests/_Widget-lifecycle.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>_Widget.destroy() unit test</title>
+
+	<script type="text/javascript" src="../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit._Widget");
+
+		var obj = {
+			foo: function(){
+				// summary: empty function that we connect to
+			}
+		};
+
+		// Number of times foo was called while TestWidget existed
+		var calls = 0;
+
+		dojo.declare("dijit.TestWidget", dijit._Widget, {
+			postCreate: function(){
+				// Rather odd call to this.connect() For testing the connections are dropped on destroy()
+				this.connect(obj, "foo", function(){
+					calls++;
+				});
+			}
+		});
+
+		var w;
+
+		dojo.addOnLoad(function(){
+			doh.register("dijit._Widget",
+				[
+					{
+						name: "create",
+						runTest: function(t){
+							w = new dijit.TestWidget({id: "w1"}, "w1");
+
+							doh.t(dijit.byId("w1"), "widget in registry");
+
+							// since there's no template, the widget just points to the srcNodeRef
+							doh.is(w.domNode, dojo.byId("w1"), "srcNodeRef read in");
+
+							// test the connection
+							doh.is(0, calls, "foo() not called yet");
+							obj.foo();
+							doh.is(1, calls, "foo() called");
+						}
+					},
+					{
+						name: "destroy",
+						runTest: function(t){
+							w.destroy();
+
+							doh.f(dijit.byId("w1"), "widget no longer in registry");
+
+							// test the connection was destroyed
+							calls = 0;
+							obj.foo();
+							doh.is(0, calls, "connection was deleted");
+
+							// test the DOM node was removed
+							doh.f(dojo.byId("w1"), "DOM Node removed");
+						}
+					},
+					{
+						name: "destroy(true)  (preserving DOM node)",
+						runTest: function(t){
+							w = new dijit.TestWidget({id: "w2"}, "w2");
+
+							doh.t(dijit.byId("w2"), "widget in registry");
+							w.destroy(true);
+
+							doh.f(dijit.byId("w2"), "widget no longer in registry");
+
+							// test the DOM node *wasn't* removed
+							doh.t(dojo.byId("w2"), "DOM Node left");
+						}
+					}
+
+				]
+			);
+			doh.run();
+		});
+
+	</script>
+</head>
+<body class="claro">
+
+	<div id="w1"></div>
+	<div id="w2"></div>
+</body>
+</html>
diff --git a/dijit/tests/_Widget-ondijitclick.html b/dijit/tests/_Widget-ondijitclick.html
new file mode 100644
index 0000000..eaf6e9e
--- /dev/null
+++ b/dijit/tests/_Widget-ondijitclick.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Test Dijit Internal Event: "ondijitclick"</title>
+
+	<script type="text/javascript" src="../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit._Widget");
+		dojo.require("dojo.parser");
+
+		dojo.declare("dijit.WidgetWithOndijitclick",
+			dijit._Widget,
+			{
+				clickCount: 0,
+				onClick: function(){
+				},
+				_onClick: function() {
+					console.log(this.id + ": ondijitclick");
+					this.onClick();
+				},
+				postCreate: function() {
+					this.connect(this.domNode, "ondijitclick", "_onClick");
+				}
+			}
+		);
+	</script>
+	<style>
+		div {
+			border: 1px solid blue;
+			margin-top: 1em;
+		}
+	</style>
+</head>
+<body class="claro">
+	<h1>_Widget.ondijitclick test</h1>
+	<p>
+		This tests dijit's infrastructure for catching SPACE and ENTER key clicks on nodes
+		that aren't <button> or <a>, and therefore don't normally respond to keyboard
+		"click events".
+	</p>
+	<p>
+		Clicking the first widget moves focus to the plain button,
+		but that button itself shouldn't get a click event.   (There are some subtleties about
+		whether catch clicks on key-down or key-up so this tests to make sure we are doing
+		the right one.)
+	</p>
+	<div id="first" dojoType="dijit.WidgetWithOndijitclick" tabIndex=0
+			onClick="dojo.byId('plainbutton').focus();">
+		click me using space or enter, to focus button below
+	</div>
+	<button id="plainbutton" onclick="console.log('plain button clicked'); window.clicked = true;" type="button" >plain button</button>
+
+	<div id="second" dojoType="dijit.WidgetWithOndijitclick" tabIndex=0
+			onClick="dojo.byId('textarea').focus();">
+		click me using space or enter, to focus textarea below
+	</div>
+	<textarea id="textarea">hello world</textarea>
+
+	<br>
+	<button id="button2" style="margin-top: 2em;" type="button"
+			onClick="dojo.byId('third').focus();">
+		click me using space or enter, to focus ondijitclick widget below
+	</button>
+	<div id="third" dojoType="dijit.WidgetWithOndijitclick" tabIndex=0 style="margin-top: 0px;"
+			onfocus="console.log('onfocus on third'); window.onDijitClickFocus = true;"
+			onClick="console.log('onclick on third'); window.spuriousOnDijitClick = true;">
+		clicking the button above shouldn't cause my ondijitclick handler to fire
+	</div>
+	<br>
+	<div id="fourth" dojoType="dijit.WidgetWithOndijitclick" tabIndex=0 style="margin-top: 0px;"
+			onClick='alert("make sure can close this alert via keyboard");'>
+		Manual Test: Click me using space or enter to launch a JavaScript alert() from element using ondijitclick
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/_Widget-subscribe.html b/dijit/tests/_Widget-subscribe.html
new file mode 100644
index 0000000..269d74b
--- /dev/null
+++ b/dijit/tests/_Widget-subscribe.html
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Test Dijit Subscribe</title>
+
+	<script type="text/javascript" src="../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit._Widget");
+		dojo.require("dojo.parser");
+
+		var numCallsInternal = 0;
+		var numCallsExternal = 0;
+		var externalString = "";
+		var internalSubscribe = null;
+
+		dojo.declare("dijit.MyWidget", dijit._Widget, {
+			_subscribeHandlerInternal: function(){ numCallsInternal++; }
+		});
+
+		dojo.addOnLoad(function(){
+			doh.register("_widgetSubscribe",
+				[
+					{
+						name: "_Widget.subscribe - set up subscriptions",
+						runTest: function(t){
+							var w = dijit.byId("widget1");
+							internalSubscribe = w.subscribe("/custom/event",
+													"_subscribeHandlerInternal");
+							w.subscribe("/custom/event", function(){
+								if(this == w){
+									numCallsExternal++;
+								}
+							});
+							w.subscribe("/custom/setString", function(str){
+								if(this == w){
+									externalString = str;
+								}
+							});
+							doh.is(0, numCallsInternal);
+							doh.is(0, numCallsExternal);
+							doh.is("", externalString);
+							doh.isNot(null, internalSubscribe);
+						}
+					},
+					{
+						name: "_Widget.subscribe - publish events",
+						runTest: function(t){
+							var w = dijit.byId("widget1");
+							dojo.publish("/custom/event", []);
+							doh.is(1, numCallsInternal);
+							doh.is(1, numCallsExternal);
+							dojo.publish("/custom/setString", ["myString"]);
+							doh.is("myString", externalString);
+							dojo.publish("/custom/setString", ["anotherString"]);
+							doh.is("anotherString", externalString);
+						}
+					},
+					{
+						name: "_Widget.unsubscribe",
+						runTest: function(t){
+							var w = dijit.byId("widget1");
+							dojo.publish("/custom/event", []);
+							doh.is(2, numCallsInternal);
+							doh.is(2, numCallsExternal);
+							w.unsubscribe(internalSubscribe);
+							dojo.publish("/custom/event", []);
+							doh.is(2, numCallsInternal);
+							doh.is(3, numCallsExternal);
+						}
+					},
+					{
+						name: "_Widget.destroy",
+						runTest: function(t){
+							var w = dijit.byId("widget1");
+							w.destroy();
+							dojo.publish("/custom/event", []);
+							doh.is(2, numCallsInternal);
+							doh.is(3, numCallsExternal);
+							dojo.publish("/custom/setString", ["myString"]);
+							doh.is("anotherString", externalString);
+						}
+					}
+				]
+			);
+			doh.run();
+		});
+
+	</script>
+</head>
+<body class="claro">
+	<div id="widget1" dojoType="dijit.MyWidget"></div>
+</body>
+</html>
diff --git a/dijit/tests/_altCalendar.html b/dijit/tests/_altCalendar.html
new file mode 100644
index 0000000..d4b6730
--- /dev/null
+++ b/dijit/tests/_altCalendar.html
@@ -0,0 +1,44 @@
+<table cellspacing="0" cellpadding="0" class="dijitCalendarContainer" role="grid" dojoAttachEvent="onkeypress: _onKeyPress">
+	<thead>
+		<tr class="dijitReset dijitCalendarMonthContainer" valign="top">
+			<th>			
+			<span class='dijitReset dijitCalendarArrow' dojoAttachPoint="decrementMonth">
+				<img src="${_blankGif}" alt="" class="dijitCalendarIncrementControl dijitCalendarDecrease" role="presentation">
+				<span dojoAttachPoint="decreaseArrowNode" class="dijitA11ySideArrow">-</span>
+			</span>
+			<span dojoAttachEvent="onclick: goToToday" style="cursor: pointer; cursor: hand;">ࣻ</span>
+			<span class='dijitReset dijitCalendarArrow' dojoAttachPoint="incrementMonth">
+				<img src="${_blankGif}" alt="" class="dijitCalendarIncrementControl dijitCalendarIncrease" role="presentation"/>
+				<span dojoAttachPoint="increaseArrowNode" class="dijitA11ySideArrow">+</span>
+			</span></th>
+			<th class='dijitReset' colspan="6">
+				<div class="dijitVisible">
+					<div class="dijitPopup dijitMenu dijitMenuPassive dijitHidden" dojoAttachPoint="monthDropDown" dojoAttachEvent="onmouseup: _onMonthSelect, onmouseover: _onMenuHover, onmouseout: _onMenuHover">
+						<div class="dijitCalendarMonthLabelTemplate dijitCalendarMonthLabel"></div>
+					</div>
+				</div>
+				<div dojoAttachPoint="monthLabelSpacer" class="dijitSpacer"></div>
+				<div dojoAttachPoint="monthLabelNode" class="dijitCalendarMonthLabel dijitInline dijitVisible" dojoAttachEvent="onmousedown: _onMonthToggle"></div>
+			</th>
+		</tr>
+		<tr>
+			<th class="dijitReset dijitCalendarDayLabelTemplate" role="columnheader"><span class="dijitCalendarDayLabel"></span></th>
+		</tr>
+	</thead>
+	<tbody dojoAttachEvent="onclick: _onDayClick, onmouseover: _onDayMouseOver, onmouseout: _onDayMouseOut, onmousedown: _onDayMouseDown, onmouseup: _onDayMouseUp" class="dijitReset dijitCalendarBodyContainer">
+		<tr class="dijitReset dijitCalendarWeekTemplate" role="row">
+			<td class="dijitReset dijitCalendarDateTemplate" role="gridcell"><span class="dijitCalendarDateLabel"></span><span class="dijitCalendarDateDescription"></span></td>
+		</tr>
+	</tbody>
+	<tfoot class="dijitReset dijitCalendarYearContainer">
+		<tr>
+			<td class='dijitReset' valign="top" colspan="7">
+				<h3 class="dijitCalendarYearLabel">
+					<span dojoAttachPoint="previousYearLabelNode" class="dijitInline dijitCalendarPreviousYear"></span>
+					«<span dojoAttachPoint="currentYearLabelNode" class="dijitInline dijitCalendarSelectedYear"></span>»
+					<span dojoAttachPoint="nextYearLabelNode" class="dijitInline dijitCalendarNextYear"></span>
+				</h3>
+			</td>
+		</tr>
+	</tfoot>
+</table>
diff --git a/dijit/tests/_base/manager.html b/dijit/tests/_base/manager.html
new file mode 100644
index 0000000..9a79d59
--- /dev/null
+++ b/dijit/tests/_base/manager.html
@@ -0,0 +1,258 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit manager unit test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit.dijit");
+
+		dojo.declare("foo", dijit._Widget, {
+			name: "",
+			attr1: 0,
+			attr2: 0
+		});
+
+		dojo.declare("bar", dijit._Widget, {
+			name: "",
+			attr1: 0,
+			attr2: 0
+		});
+
+		dojo.declare("Baz", dijit._Widget, {
+			name: "",
+			attr1: 1,
+			attr2: 1
+		});
+
+		dojo.addOnLoad(function(){
+			doh.register("dijit._base.manager",
+				[
+					function forEachTest(t){
+						var names=[];
+						dijit.registry.forEach(function(widget){ names.push(widget.name); });
+						t.is(names.join(" "), "bob is your uncle");
+					},
+					function filterTest(t){
+						var names=[];
+						dijit.registry.
+							filter(function(widget){ return widget.attr1==10; }).
+							forEach(function(widget){ names.push(widget.name); });
+						t.is(names.join(" "), "bob uncle");
+					},
+					function filterScope(t){
+						// testing filter with a forced 'this' in the cb function
+						var names = [],
+							obj = {
+								check: function(widget, val){
+									// same as previous unit test
+									return widget.attr1 == val;
+								}
+							};
+						dijit.registry
+							.filter(function(w){ return this.check(w, 10); }, obj)
+							.forEach(function(w){ names.push(w.name) })
+						;
+						t.is(names.join(" "), "bob uncle");
+					},
+					function byId(t){
+						t.is(dijit.byId("three").name, "your");
+						t.f(dijit.byId("nonexistant"));
+					},
+					function byClass(t){
+						var names=[];
+						dijit.registry.
+							byClass("bar").
+							forEach(function(widget){ names.push(widget.name); });
+						t.is(names.join(" "), "your uncle");
+					},
+					function lengthTest(t){
+						// test existing length
+						t.is(dijit.registry.byClass("bar").length, 2);
+						// test adding:
+						var n = new Baz();
+						t.is(dijit.registry.byClass("Baz").length, 1);
+						// test destroying:
+						n.destroy();
+						t.is(dijit.registry.byClass("Baz").length, 0);
+					},
+					function nullLengthTest(t){
+						var ws = new dijit.WidgetSet();
+						var count = 0;
+
+						var b = [new Baz(), new Baz()];
+						ws.add(b[0]);
+						ws.add(b[1]);
+
+						t.is(2, ws.length);
+
+						ws.remove(b[0].id);
+						t.is(1, ws.length);
+
+						ws.remove(b[1].id);
+						t.is(0, ws.length);
+
+						// ensure we don't ever go below 0
+						ws.remove("invalidId");
+						t.is(0, ws.length);
+
+						dojo.forEach(b, function(w){ w.destroy() });
+
+					},
+					function forEachScope(t){
+						var obj = {
+							getIt: function(widget){
+								return widget.id;
+							}
+						};
+
+						dijit.registry.forEach(function(w){
+							t.is(w.id, this.getIt(w));
+						}, obj);
+					},
+					function forEachReturn(t){
+						// also tests WidgetSet.map
+						var ws = dijit.registry.forEach(function(){}).map(function(w){
+							return w.declaredClass.toUpperCase();
+						});
+						t.t(dojo.isArray(ws));
+						t.is(ws.length, dijit.registry.length);
+					},
+					function forEachInc(t){
+						var x = 0;
+						dijit.registry.forEach(function(w, i){
+							t.is(i, x++);
+						});
+					},
+					function toArrayTest(t){
+						var ws = dijit.registry.byClass("bar");
+						var wa = ws.toArray();
+
+						t.t(dojo.isArray(wa));
+						t.is(ws.length, wa.length);
+
+						var wda = dojo.map(wa, function(w){
+							return w.domNode;
+						});
+
+						t.is(wda.length, ws.length);
+						var wdas = wda.slice(-1);
+
+						t.is(1, wdas.length);
+
+						var w = dijit.byNode(wdas[0]);
+						t.is(w.declaredClass, "bar");
+					},
+					function mapTest(t){
+						var ids = dijit.registry.map(function(w){
+							return w.id;
+						});
+						t.is(ids.length, dijit.registry.length);
+						dijit.registry.forEach(function(id){
+							t.t(dijit.byId(id));
+						});
+					},
+					function everyTest(t){
+
+						var a = new Baz();
+						var b = new Baz();
+
+						var hasid = dijit.registry.every(function(w){
+							return w.id;
+						});
+
+						t.t(hasid);
+
+						var hasattr1 = dijit.registry.every(function(w){
+							return w.attr1 > 0;
+						});
+
+						t.t(hasattr1);
+
+						var x = 0;
+						var once = dijit.registry.every(function(w){
+							x++;
+							return false;
+						});
+						t.is(1, x);
+						t.f(once);
+
+						a.destroy();
+						b.destroy();
+
+					},
+					function someTest(t){
+
+						var a = new Baz();
+						var b = new Baz();
+
+						var x = 0;
+						var hasid = dijit.registry.some(function(w){
+							x++;
+							return w.id;
+						});
+
+						t.is(1, x);
+						t.t(hasid);
+
+						var n = 0;
+						var hasattr1 = dijit.registry.some(function(w){
+							n++;
+							return false;
+						});
+						t.is(n, dijit.registry.length);
+						t.f(hasattr1);
+
+						var l = 0;
+						var once = dijit.registry.some(function(w){
+							l++;
+							return true;
+						});
+						t.is(1, l);
+						t.t(once);
+
+						a.destroy();
+						b.destroy();
+
+					},
+					function deleteTest(t){
+						var names=[];
+						dijit.byId("two").destroy();
+						dijit.byId("four").destroy();
+						dijit.registry.forEach(function(widget){ names.push(widget.name); });
+						t.is(names.join(" "), "bob your");
+					},
+					function getEnclosingWidgetTest(t){
+						t.is(dijit.getEnclosingWidget(dojo.byId("not-a-widget")), null);
+						t.is(dijit.getEnclosingWidget(dojo.byId("three")).name, "your");
+						t.is(dijit.getEnclosingWidget(dojo.byId("three.one")).name, "your");
+						t.is(dijit.getEnclosingWidget(dojo.byId("three.one.one")).name, "your");
+					}
+				]
+			);
+			doh.run();
+		});
+
+	</script>
+</head>
+<body>
+	<h1>Dijit Manager Unit Test</h1>
+	<div dojoType="foo" id="one" name="bob" attr1="10" attr2="10"></div>
+	<div dojoType="foo" id="two" name="is" attr1="5" attr2="10"></div>
+	<div dojoType="bar" id="three" name="your" attr1="5" attr2="5">
+		<div id="three.one">
+			<div id="three.one.one"></div>
+		</div>
+	</div>
+	<div dojoType="bar" id="four" name="uncle" attr1="10" attr2="5"></div>
+	<div id="not-a-widget"></div>
+</body>
+</html>
diff --git a/dijit/tests/_base/module.js b/dijit/tests/_base/module.js
new file mode 100644
index 0000000..07a8c17
--- /dev/null
+++ b/dijit/tests/_base/module.js
@@ -0,0 +1,19 @@
+dojo.provide("dijit.tests._base.module");
+
+try{
+	var userArgs = window.location.search.replace(/[\?&](dojoUrl|testUrl|testModule)=[^&]*/g,"").replace(/^&/,"?"),
+		test_robot = true;
+
+	doh.registerUrl("dijit.tests._base.manager", dojo.moduleUrl("dijit", "tests/_base/manager.html"), 99999999);
+	doh.registerUrl("dijit.tests._base.tabindex", dojo.moduleUrl("dijit", "tests/_base/tabindex.html"), 99999999);
+	doh.registerUrl("dijit.tests._base.wai", dojo.moduleUrl("dijit", "tests/_base/wai.html"), 99999999);
+	doh.registerUrl("dijit.tests._base.place", dojo.moduleUrl("dijit", "tests/_base/place.html"), 99999999);
+	if(test_robot){
+		doh.registerUrl("dijit.tests._base.robot.FocusManager", dojo.moduleUrl("dijit","tests/_base/robot/FocusManager.html"), 99999999);
+		doh.registerUrl("dijit.tests._base.robot.focus_mouse", dojo.moduleUrl("dijit","tests/_base/robot/focus_mouse.html"), 99999999);
+		doh.registerUrl("dijit.tests._base.robot.typematic", dojo.moduleUrl("dijit","tests/_base/robot/typematic.html"), 99999999);
+	}
+
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dijit/tests/_base/multiversion.html b/dijit/tests/_base/multiversion.html
new file mode 100644
index 0000000..ca5d7a9
--- /dev/null
+++ b/dijit/tests/_base/multiversion.html
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+	<!--
+		Tests that generated widget id's are unique according to scopeMap.
+		The created widgets should get the non-conflicting generated names 
+			- dijit1_dijit_layout_ContentPane_0
+			- dijit2_dijit_layout_ContentPane_0
+
+		Before running this tests, Dojo XD must be built via:
+			$ cd util/buildscripts
+			$ ./build.sh action=release loader=xdomain profile=standard optimize=comments
+	-->
+	<title>Multi-version test</title>
+	<script type="text/javascript">
+		djConfig = {
+			baseUrl:'../../../release/dojo/dojo/',
+			scopeMap:[
+				['dojo','dojo1'],
+				['dijit','dijit1'],
+				['dojox','dojox1']
+			],
+			afterOnLoad: true
+		};
+	</script>
+	<script type="text/javascript" src="../../../release/dojo/dojo/dojo.xd.js"></script>
+	<script type="text/javascript">
+		dojo1.require("dijit.layout.ContentPane");
+		var cp1, cp2;
+		dojo1.ready(function(){
+			cp1 = new dijit1.layout.ContentPane({ content: 'one' });
+			cp1.placeAt(dojo1.body());
+			cp1.startup();
+
+			var sc = dojo1.doc.createElement('script');
+			sc.type = 'text/javascript';
+			djConfig = {
+				baseUrl:'../../../release/dojo/dojo/',
+				scopeMap:[
+					['dojo','dojo2'],
+					['dijit','dijit2'],
+					['dojox','dojox2']
+				],
+				afterOnLoad: true
+			};
+			sc.src = '../../../release/dojo/dojo/dojo.xd.js';
+			function onScriptLoad(){
+				dojo2.require("dijit.layout.ContentPane");
+				dojo2.ready(function(){
+					cp2 = new dijit2.layout.ContentPane({ content: 'two' });
+					cp2.placeAt(dojo2.body());
+					cp2.startup();
+
+					var widgets1 = dijit1.findWidgets(dojo1.body());
+					var widgets2 = dijit2.findWidgets(dojo2.body());
+
+					dojo1.query('[widgetId='+cp1.id+']').forEach(function(n){
+						var w = dijit1.byNode(n);
+						if(w.domNode === n){
+							console.log(w + ' matches');
+						}else{
+							console.log(w + ' doesn\'t match');
+						}
+					});
+					dojo2.query('[widgetId='+cp2.id+']').forEach(function(n){
+						var w = dijit2.byNode(n);
+						if(w.domNode === n){
+							console.log(w + ' matches');
+						}else{
+							console.log(w + ' doesn\'t match');
+						}
+					});
+				});
+			}
+			if(typeof sc['addEventListener'] != 'undefined'){
+				sc.addEventListener('load', onScriptLoad, false);
+			}else{
+				sc.attachEvent('onreadystatechange', onScriptLoad);
+			}
+			dojo1.doc.getElementsByTagName('head')[0].appendChild(sc);
+		});
+	</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/dijit/tests/_base/place.html b/dijit/tests/_base/place.html
new file mode 100644
index 0000000..60e9888
--- /dev/null
+++ b/dijit/tests/_base/place.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit.place unit test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+
+		body {
+			height: 100%;
+			padding: 0px;
+			margin: 0px;
+		}
+
+		.aroundNode {
+			position: absolute;
+			width: 20px;
+			height: 20px;
+			background: yellow;
+		}
+
+		#popup {
+			position: absolute;
+			width: 75px;
+			background: blue;
+			color: white;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: false"></script>
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojo.window");
+		dojo.require("dijit.dijit");
+
+
+		dojo.addOnLoad(function(){
+
+			// The around nodes
+			var aroundTop = dojo.byId("aroundTop"),
+				aroundBottom = dojo.byId("aroundBottom"),
+				aroundLeft = dojo.byId("aroundLeft"),
+				aroundRight = dojo.byId("aroundRight");
+
+			// The popup (aka dropdown)
+			var popup = dojo.byId("popup");
+
+			doh.register("dijit._base.place",
+				[
+					function placeOnScreenTL(t){
+						// Place popup at (10,7)... dijit.placeOnScreen() should choose the top-left corner, because
+						// any of the other corner would make the popup go partially off the screen
+						var ret = dijit.placeOnScreen(popup, {x: 10, y:7}, ["TR", "BR", "BL", "TL"]);
+
+						doh.is("TL", ret.corner, "top left corner chosen");
+						doh.is("10px", popup.style.left, "x coord");
+						doh.is("7px", popup.style.top, "y coord");
+						doh.is(75, ret.w, "it's 75px wide");
+					},
+					function placeOnScreenTR(t){
+						// Place popup at top right... dijit.placeOnScreen() should choose the top-right corner, because
+						// any of the other corner would make the popup go partially off the screen
+						var viewport = dojo.window.getBox(),
+							ret = dijit.placeOnScreen(popup, {x: viewport.w-10, y:7}, ["TL", "BR", "TR", "BL"]),
+							popupCoords = dojo.position(popup);
+
+						doh.is("TR", ret.corner, "top left corner chosen");
+						doh.is(viewport.w-10, popupCoords.x + popupCoords.w, "x coord");
+						doh.is("7px", popup.style.top, "y coord");
+						doh.is(75, ret.w, "it's 75px wide");
+					},
+					function placeOnScreenAroundNodeT(t){
+						// Dropdown from "aroundTop" node. Should pick the second choice, since the first
+						// goes offscreen.
+						var ret = dijit.placeOnScreenAroundNode(popup, aroundTop, {
+							"TL": "BL",	// aroundTop's top-left corner with the popup's bottom-left corner (fails)
+							"BL": "TL",	// aroundTop's bottom-left corner with the popup's top-left corner (works)
+							"BR": "TR"	// aroundTop's bottom-left corner with the popup's top-left corner (works)
+						});
+
+						doh.is("BL", ret.aroundCorner, "around corner");
+						doh.is("TL", ret.corner, "popup's corner");
+						doh.is("20px", popup.style.top, "underneath around node");
+						doh.is(dojo.position(aroundTop).x+"px", popup.style.left, "left sides aligned");
+					},
+					function placeOnScreenAroundNodeTooltip(t){
+						// Same as above test except that shape of drop down changes depending on where it's positioned.
+						// Simulates tooltip placement (tooltip shape changes b/c of the arrow).
+						// Should pick the third choice this time
+
+						function layoutNode(node, aroundCorner, nodeCorner){
+							node.style.width = (nodeCorner == "TL" ? "5000px" : "75px");
+						}
+						var ret = dijit.placeOnScreenAroundNode(popup, aroundTop, {
+							"TL": "BL",	// aroundTop's top-left corner with the popup's bottom-left corner (fails)
+							"BL": "TL",	// aroundTop's bottom-left corner with the popup's top-left corner (works)
+							"BR": "TR"	// aroundTop's bottom-left corner with the popup's top-left corner (works)
+						}, layoutNode);
+
+						doh.is("BR", ret.aroundCorner, "around corner");
+						doh.is("TR", ret.corner, "popup's corner");
+						doh.is("20px", popup.style.top, "underneath around node");
+						doh.is(dojo.position(aroundTop).x+dojo.position(aroundTop).w,
+							dojo.position(popup).x+dojo.position(popup).w,
+							"right sides aligned");
+					},
+					function placeOnScreenAroundNodeB(t){
+						// Dropdown from "aroundBottom" node. Should go above aroundNode so that
+						// popup doesn't go offscreen
+						var ret = dijit.placeOnScreenAroundNode(popup, aroundBottom, {
+							"BL": "TL",	// aroundBottom's bottom-left corner with the popup's top-left corner (fails)
+							"TL": "BL",	// aroundBottom's top-left corner with the popup's bottom-left corner (works)
+							"BR": "TR"	// aroundBottom's bottom-left corner with the popup's top-left corner (fails)
+						});
+
+						doh.is("TL", ret.aroundCorner, "around corner");
+						doh.is("BL", ret.corner, "popup's corner");
+						doh.is(dojo.position(aroundBottom).y, dojo.position(popup).y + dojo.position(popup).h, "above around node");
+					}
+				]
+			);
+			doh.run();
+		});
+
+	</script>
+</head>
+<body>
+	<h1>Dijit Place Unit Test</h1>
+	<div id="aroundTop" class="aroundNode" style="top: 0px; left: 50%;">T</div>
+	<div id="aroundLeft" class="aroundNode" style="top: 200px; left: 0;">L</div>
+	<div id="aroundRight" class="aroundNode" style="top: 200px; right: 1px;">R</div>
+	<div id="aroundBottom" class="aroundNode" style="bottom: 5px; left: 50%;">B</div>
+
+	<div id="popup">
+		I'm a drop down, wider and taller than the around nodes I'm placed next to.
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/_base/robot/FocusManager.html b/dijit/tests/_base/robot/FocusManager.html
new file mode 100644
index 0000000..d0875c7
--- /dev/null
+++ b/dijit/tests/_base/robot/FocusManager.html
@@ -0,0 +1,164 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Dijit focus manager DOH Robot test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_FocusManager.html');
+
+				doh.register("Dijit focus manager low level tests", [
+					{
+						name: "set timer to save focus and selection",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.sequence(function(){
+								dojo.byId("delay_save").focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys.ENTER, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// This is just here to tell DOH that test is finished
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "focus textarea and select some text",
+						timeout: 8000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dojo.byId("textarea").focus();
+
+							// Position caret at " there!"
+							if(dojo.isMac){
+								doh.robot.keyPress(dojo.keys.LEFT_ARROW, 20, {meta: true});
+							}else{
+								doh.robot.keyPress(dojo.keys.HOME, 20, {});
+							}
+							for(var i=0; i<5; i++){
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 20, {});
+							}
+
+							// select " there"
+							for(i=0; i<6; i++){
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 20, {shift: true});
+							}
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Wait for selection and focus to be copied
+							}), 3000);
+
+							return d;
+						}
+					},
+					{
+						name: "restore focus and selection",
+						timeout: 8000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Focus somewhere else
+							doh.robot.sequence(function(){
+								dojo.byId("input1").focus();
+							}, 500);
+
+							// Press restore button
+							doh.robot.sequence(function(){
+								dojo.byId("restore").focus();
+							}, 500);
+
+							doh.robot.keyPress(dojo.keys.SPACE, 500);
+
+							//Move cursor to unselect the text
+							for(i=0; i<2; i++){
+								doh.robot.keyPress(dojo.keys.LEFT_ARROW, 20, {shift: false});
+							}
+
+							// Press restore button again, should restore previous selection.
+							doh.robot.sequence(function(){
+								dojo.byId("restore").focus();
+							}, 500);
+
+							doh.robot.keyPress(dojo.keys.SPACE, 500);
+
+							// Focus should have been moved back to textarea, and
+							// " there" should be selected through the focus restorel
+							// by deleting the selection
+							doh.robot.keyPress(dojo.keys.BACKSPACE, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Check that focus was returned to the textarea
+								doh.t(dojo.global.dijit._curFocus, "curFocus defined");
+								doh.is("textarea", dojo.global.dijit._curFocus.id, "focused on textarea");
+
+								// And that " there" was selected then deleted
+								doh.is("hello!", dojo.byId("textarea").value);
+							}), 500);
+							return d;
+						}
+					},
+					{
+						name: "Test select text, clear, and restore",
+						timeout: 8000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							//Select the text in the p tag.
+							var p = dojo.byId("selectableText");
+							dijit._editor.selection.selectElementChildren(p);
+							var value = dijit._editor.selection.getSelectedText();
+							value = dojo.trim(value);
+							try{
+								doh.assertEqual(
+									"This paragraph contains text to select for testing purposes.",
+								value, "Original Text Selection");
+
+								//Get the current focus, which saves the selections too.
+								var curFocus = dijit.getFocus();
+
+								//Clear current selection.
+								dijit._editor.selection.collapse(true);
+
+								//Check it's cleared.
+								value = dijit._editor.selection.getSelectedText();
+								doh.assertEqual("",value);
+
+								//Restore it and check again.
+								dijit.focus(curFocus);
+								value = dijit._editor.selection.getSelectedText();
+								doh.assertEqual(
+									"This paragraph contains text to select for testing purposes.",
+								value, "Restored Text Selection");
+
+								//Clear the selection, we're complete.
+								dijit._editor.selection.collapse(true);
+								d.callback(true);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/_base/robot/focus_mouse.html b/dijit/tests/_base/robot/focus_mouse.html
new file mode 100644
index 0000000..5fadfcc
--- /dev/null
+++ b/dijit/tests/_base/robot/focus_mouse.html
@@ -0,0 +1,228 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Dijit focus manager DOH Robot test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_focusWidget.html?animate=false');
+
+				// These are objects used to track calls to _onFocus and _onBlur in various widgets
+				function resetEvents(){
+					focusEvents = {};
+					blurEvents = {};
+				}
+				resetEvents();
+
+				doh.register("Dijit focus manager tests", [
+
+					function setUp(){
+						dojo.forEach(["form", "fieldset1", "fieldset2", "select", "editor"], function(id){
+							dojo.connect(dijit.byId(id), "_onFocus", function(){
+								focusEvents[id] = true;
+							});
+							dojo.connect(dijit.byId(id), "_onBlur", function(){
+								blurEvents[id] = true;
+							});
+						});
+					},
+
+					{
+						name: "focus simple input",
+						timeout: 4000,
+						setUp: function(){
+							resetEvents();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Focus the simple input
+							//dojo.byId("first").focus();
+							doh.robot.mouseMoveAt("first");
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Make sure that focus manager caught the focus event
+								doh.is(dojo.byId("first"), dojo.global.dijit._curFocus);
+
+								// And that the dijit.form.Form widget is marked as
+								// being "in focus"
+								doh.t(focusEvents["form"], "form focused");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "focus combobox",
+						timeout: 4000,
+						setUp: function(){
+							resetEvents();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dijit.byId("select").focus();
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Focus goes to an <input> node deep inside of select.domNode,
+								// but that <input> node has the id of the widget
+								doh.is(dojo.byId("select"), dojo.global.dijit._curFocus);
+
+								// The focus stack should show the ComboBox plus all parent widgets
+								var stack = dojo.global.dijit._activeStack;
+								doh.is(3, stack.length, "3 active widgets in stack");
+								doh.is("form", stack[0], "grandparent of combobox");
+								doh.is("fieldset1", stack[1], "parent of combobox");
+								doh.is("select", stack[2], "combobox itself (last in stack)");
+
+								// _onFocus()/_onBlur was called appropriately
+								doh.f(focusEvents["form"], "form was already focused, no duplicate event");
+								doh.f(blurEvents["form"], "form wasn't blurred");
+								doh.t(focusEvents["fieldset1"], "fieldset1 focused");
+								doh.t(focusEvents["select"], "select focused");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "focus editor",
+						timeout: 4000,
+						setUp: function(){
+							resetEvents();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dijit.byId("editor").focus();
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// The focus stack should show the Editor plus all parent widgets
+								var stack = dojo.global.dijit._activeStack;
+								doh.is(2, stack.length, "2 active widgets in stack");
+								doh.is("form", stack[0], "parent of editor");
+								doh.is("editor", stack[1], "editor itself (last in stack)");
+
+								// _onFocus()/_onBlur was called appropriately
+								doh.f(focusEvents["form"], "form was already focused, no duplicate event");
+								doh.f(blurEvents["form"], "form wasn't blurred");
+								doh.t(blurEvents["fieldset1"], "fieldset no longer focused");
+								doh.t(focusEvents["editor"], "editor focused");
+							}), 500);
+
+							return d;
+						}
+					},
+
+					// clicking spinner buttons should activate the spinner, even
+					// though there's no actual DOM focus event
+					{
+						name: "spinner",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var upArrow = dojo.query(".dijitSpinner .dijitUpArrowButton")[0];
+							doh.t(upArrow, "found the up arrow");
+
+							doh.robot.mouseMoveAt(upArrow);
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// The focus stack should show the Spinner plus all parent widgets
+								var stack = dojo.global.dijit._activeStack;
+								doh.is(3, stack.length, "3 active widgets in stack");
+								doh.is("form", stack[0], "grandparent of spinner");
+								doh.is("fieldset2", stack[1], "parent of spinner");
+								doh.is("spinner", stack[2], "spinner itself (last in stack)");
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "combo button menu",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var button = dojo.query("#button .dijitDownArrowButton")[0];
+							doh.t(button, "found drop down button");
+
+							doh.robot.mouseMoveAt(button);
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Focus goes to an first item in the drop down menu
+								doh.is(dojo.byId("mi1"), dojo.global.dijit._curFocus);
+
+								// The focus stack should show the ComboBox plus all parent widgets
+								var stack = dojo.global.dijit._activeStack;
+								console.log("menu stack is ", stack);
+								doh.is(5, stack.length, "5 active widgets in stack");
+								doh.is("form", stack[0], "grandparent of combobutton");
+								doh.is("fieldset2", stack[1], "parent of combobutton");
+								doh.is("button", stack[2], "combobutton");
+								doh.is("menu", stack[3], "menu");
+								doh.is("mi1", stack[4], "menuitem");
+							}), 1000);
+
+							return d;
+						}
+					}
+
+/*
+					// Commented out because
+					// 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
+					{
+						name: "nested menu",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMoveAt("popupMenuItem");
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Focus goes to an first item in the sub menu
+								doh.is(dojo.byId("smi1"), dojo.global.dijit._curFocus);
+
+								// The focus stack should show the two submenus and then upwards
+								// to the ComboButton, and the rest
+								var stack = dojo.global.dijit._activeStack;
+								console.log("menu stack is ", stack);
+								doh.is(7, stack.length, "7 active widgets in stack");
+								doh.is("form", stack[0], "grandparent of combobutton");
+								doh.is("fieldset2", stack[1], "parent of combobutton");
+								doh.is("button", stack[2], "combobutton");
+								doh.is("menu", stack[3], "menu");
+								doh.is("mi1", stack[4], "menuitem");
+								doh.is("submenu", stack[5], "menu");
+								doh.is("smi1", stack[6], "menuitem");
+							}), 1000);
+
+							return d;
+						}
+					}
+*/
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/_base/robot/popup.html b/dijit/tests/_base/robot/popup.html
new file mode 100644
index 0000000..f123897
--- /dev/null
+++ b/dijit/tests/_base/robot/popup.html
@@ -0,0 +1,208 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot popup/BackgroundIFrame Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_popup.html');
+
+			doh.register("simple open and close",
+				[
+					function initialConditions(t){
+						// If the popup code has cached any iframes, make sure they are hidden
+						dojo.query("iframe").forEach(function(node){
+							console.log("found iframe", node);
+							doh.is("none", node.style.display, "background iframe is hidden");
+						});
+					},
+
+					// Create popup on the edge of another widget
+					function openAround(){
+						var d = new doh.Deferred();
+
+						var around = dojo.global.choiceDropDownButton,
+							popup = dojo.global.choiceDropDown;
+
+						around.openPopup();
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.t(isVisible(popup.domNode), "popup is visible");
+
+							if(dojo.isIE <= 6){
+								// Test the BackgroundIFrame
+								var iframes = dojo.query("iframe");
+								doh.is(1, iframes.length, "one background iframe on IE6");
+
+								var popupCoords = dojo.position(popup.domNode),
+									iframeCoords = dojo.position(iframes[0]);
+								doh.is(popupCoords.x, iframeCoords.x, "x is same: " + popupCoords.x);
+								doh.is(popupCoords.y, iframeCoords.y, "y is same: " + popupCoords.y);
+								doh.is(popupCoords.w, iframeCoords.w, "w is same: " + popupCoords.w);
+								doh.is(popupCoords.h, iframeCoords.h, "h is same: " + popupCoords.h);
+								doh.is("", iframes[0].style.display, "not display:none");
+							}
+							// TODO: test stack
+						}), 500);
+
+						return d;
+					},
+
+					function closeAround(){
+						// Close the popup
+						var around = dojo.global.choiceDropDownButton,
+							popup = dojo.global.choiceDropDown;
+
+						around.closePopup();
+
+						// Make sure the popup is hidden
+						// (in a future release this might change to display:none etc but currently it's visibility:hidden)
+						doh.is("hidden", popup.domNode.style.visibility, "popup is hidden");
+
+						// If the popup code has cached the iframe for later use, make sure it's hidden
+						dojo.query("iframe").forEach(function(node){
+							doh.is("none", node.style.display, "background iframe is hidden");
+						});
+					}
+				]);
+
+			doh.register("nested open and close",
+				[
+					function initialConditions(t){
+						// If the popup code has cached any iframes, make sure they are hidden
+						dojo.query("iframe").forEach(function(node){
+							console.log("found iframe", node);
+							doh.is("none", node.style.display, "background iframe is hidden");
+						});
+					},
+
+					// Open first level
+					function openAround(){
+						var d = new doh.Deferred();
+
+						var around = dojo.global.nestedDropDownButton,
+							popup = dojo.global.nestedOpener,
+							nestedPopup = dojo.global.nestedChoice1;
+
+						around.openPopup();
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.t(isVisible(popup.domNode), "popup is visible");
+
+							if(dojo.isIE <= 6){
+								// Test the BackgroundIFrame
+								var iframes = dojo.query("iframe");
+								doh.is(1, iframes.length, "one background iframe on IE6");
+
+								var popupCoords = dojo.position(popup.domNode),
+									iframeCoords = dojo.position(iframes[0]);
+								doh.is(popupCoords.x, iframeCoords.x, "x is same: " + popupCoords.x);
+								doh.is(popupCoords.y, iframeCoords.y, "y is same: " + popupCoords.y);
+								doh.is(popupCoords.w, iframeCoords.w, "w is same: " + popupCoords.w);
+								doh.is(popupCoords.h, iframeCoords.h, "h is same: " + popupCoords.h);
+								doh.is("", iframes[0].style.display, "not display:none");
+							}
+							// TODO: test stack
+						}), 500);
+
+						return d;
+					},
+
+					function openNested(){
+						var d = new doh.Deferred();
+
+						var around = dojo.global.nestedDropDownButton,
+							popup = dojo.global.nestedOpener,
+							nestedPopup = dojo.global.nestedChoice1;
+
+						popup.openPopup(nestedPopup);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.t(isVisible(nestedPopup.domNode), "nested popup is visible");
+
+							if(dojo.isIE <= 6){
+								// Test the BackgroundIFrame
+								var iframes = dojo.query("iframe");
+								doh.is(2, iframes.length, "two background iframe on IE6");
+
+								var popupCoords = dojo.position(nestedPopup.domNode),
+									iframeCoords = dojo.position(iframes[1]);
+								doh.is(popupCoords.x, iframeCoords.x, "x is same: " + popupCoords.x);
+								doh.is(popupCoords.y, iframeCoords.y, "y is same: " + popupCoords.y);
+								doh.is(popupCoords.w, iframeCoords.w, "w is same: " + popupCoords.w);
+								doh.is(popupCoords.h, iframeCoords.h, "h is same: " + popupCoords.h);
+								doh.is("", iframes[0].style.display, "not display:none");
+							}
+							// TODO: test stack
+						}), 500);
+
+						return d;
+					},
+
+					function closeAround(){
+						// Close the layer of popups
+						var around = dojo.global.choiceDropDownButton,
+							popup = dojo.global.choiceDropDown;
+
+						var around = dojo.global.nestedDropDownButton,
+							popup = dojo.global.nestedOpener,
+							nestedPopup = dojo.global.nestedChoice1;
+
+						around.closePopup();
+
+						// Make sure the popups are both hidden
+						// (in a future release this might change to display:none etc but currently it's visibility:hidden)
+						doh.is("hidden", popup.domNode.style.visibility, "popup is hidden");
+						doh.is("hidden", nestedPopup.domNode.style.visibility, "nested popup is hidden");
+
+						// If the popup code has cached the iframes for later use, make sure they are hidden
+						dojo.query("iframe").forEach(function(node){
+							doh.is("none", node.style.display, "background iframe is hidden");
+						});
+					}
+				]);
+
+				// TODO: test x/y placement
+
+				// Test that onCancel goes back one level.
+				// Call nestedChoice2.onCancel() and that should trigger nestedChoice2 to close
+				// but nestedOpener stays open.
+				// (TODO)
+
+				// Test that onChange/onExecute goes back to top of popup chain.
+				// Call dialogNestedChoice2.onChange() and that should trigger dialogNestedChoice2
+				// and dialogNestedPopupOpener to close, but not dialogWithNestedPopup.
+				// (TODO)
+
+				// ---------------------
+				// a11y tests
+
+				// Test that ESC key closes one level of a popup chain.
+				// Focus nestedChoice2 and type ESC, and that should trigger nestedChoice2 to close
+				// but nestedOpener stays open.
+				// (TODO)
+
+				// Test that TAB key cancels back to top of popup chain.
+				// Focus nestedChoice2 and type TAB, and that should trigger dialogNestedChoice2
+				// and dialogNestedPopupOpener to close, but not dialogWithNestedPopup.
+				// (TODO)
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/_base/robot/typematic.html b/dijit/tests/_base/robot/typematic.html
new file mode 100644
index 0000000..b91a62d
--- /dev/null
+++ b/dijit/tests/_base/robot/typematic.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>typematic DOH Robot test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_typematic.html');
+
+				doh.register("press and hold test", [
+					{
+						name: "keyboard",
+						timeout: 9000,
+						runTest: function(){
+							var input = dojo.byId("typematicInput");
+							input.value = "";
+							input.focus();
+							var d = new doh.Deferred();
+
+							doh.robot.keyDown(dojo.keys.CTRL, 1000);
+							doh.robot.keyDown(dojo.keys.F11, 200);
+							doh.robot.keyUp(dojo.keys.F11, 2000);
+							doh.robot.keyUp(dojo.keys.CTRL, 200);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var v = input.value;
+								// allow off by 1
+								doh.t(v=="aaaaaaaaa"||v=="aaaaaaaaaa"||v=="aaaaaaaaaaa", "a letters typed");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "mouse",
+						timeout: 9000,
+						runTest: function(){
+							var input = dojo.byId("typematicInput");
+							input.value = "";
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMoveAt("typematicButton", 1000, 1000);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseRelease({left: true}, 1000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var v = input.value;
+								// allow off by 1
+								doh.t(v=="bbbbbb"||v=="bbbbbbb"||v=="bbbbbbbb", "b letters typed");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/_base/tabindex.html b/dijit/tests/_base/tabindex.html
new file mode 100644
index 0000000..f4ad8bf
--- /dev/null
+++ b/dijit/tests/_base/tabindex.html
@@ -0,0 +1,290 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit tabindex related functions unit test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+		@import "../../themes/tundra/tundra.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit.dijit");
+		dojo.require("dijit.Editor");
+
+		dojo.addOnLoad(function(){
+			doh.register("dijit.tabindex",
+				[
+					function isTabNavigable(t){
+						var d = new doh.Deferred();
+						t.t(dijit.isTabNavigable(dojo.byId("a-with-href")), "a-with-href");
+						t.f(dijit.isTabNavigable(dojo.byId("a-without-href")), "a-without-href");
+						t.t(dijit.isTabNavigable(dojo.byId("area")), "area");
+						t.t(dijit.isTabNavigable(dojo.byId("button")), "button");
+						t.t(dijit.isTabNavigable(dojo.byId("input")), "input");
+						t.t(dijit.isTabNavigable(dojo.byId("object")), "object");
+						t.t(dijit.isTabNavigable(dojo.byId("select")), "select");
+						t.t(dijit.isTabNavigable(dojo.byId("textarea")), "textarea");
+						t.f(dijit.isTabNavigable(dojo.byId("empty")), "empty");
+						t.t(dijit.isTabNavigable(dojo.byId("zero-tabindex-div")), "zero-tabindex-div");
+						t.f(dijit.isTabNavigable(dojo.byId("no-tabindex-div")), "no-tabindex-div");
+						t.f(dijit.isTabNavigable(dojo.byId("iframe")), "iframe");
+
+						dijit.byId("editor").onLoadDeferred.addCallback(d.getTestCallback(function(){
+							t.t(dijit.isTabNavigable(dojo.byId("editor_iframe")), "editor_iframe");
+						}));
+
+						return d;
+					},
+					function findTabNullOnEmpty(t){
+						t.is(null, dijit.getFirstInTabbingOrder("empty"));
+						t.is(null, dijit.getLastInTabbingOrder("empty"));
+					},
+					function findTabElements(t){
+						t.is(null, dijit.getFirstInTabbingOrder("div-container"));
+						t.is(null, dijit.getFirstInTabbingOrder("a-without-href-container"));
+						t.is("a-with-href", dijit.getFirstInTabbingOrder("a-with-href-container").id);
+
+						// in WebKit area elements are not in the tab order
+						// and their display style property is "none";
+						// therefore it is expected that this test will fail
+						if(!dojo.isWebKit){
+							// TODO: failing on FF3.0/mac; I think there's a race condition waiting
+							// for the image to load
+							t.is("area", dijit.getFirstInTabbingOrder("area-map").id);
+						}
+
+						t.is("button", dijit.getFirstInTabbingOrder("button-container").id);
+						t.is("input", dijit.getFirstInTabbingOrder("input-container").id);
+						t.is("object", dijit.getFirstInTabbingOrder("object-container").id);
+						t.is("select", dijit.getFirstInTabbingOrder("select-container").id);
+						t.is("textarea", dijit.getFirstInTabbingOrder("textarea-container").id);
+						t.is(null, dijit.getLastInTabbingOrder("div-container"));
+						t.is(null, dijit.getLastInTabbingOrder("a-without-href-container"));
+						t.is("a-with-href", dijit.getLastInTabbingOrder("a-with-href-container").id);
+
+						// in WebKit area elements are not in the tab order
+						// and their display style property is "none";
+						// therefore it is expected that this test will fail
+						if(!dojo.isWebKit){
+							t.is("area", dijit.getLastInTabbingOrder("area-map").id);
+						}
+
+						t.is("button", dijit.getLastInTabbingOrder("button-container").id);
+						t.is("input", dijit.getLastInTabbingOrder("input-container").id);
+						t.is("object", dijit.getLastInTabbingOrder("object-container").id);
+						t.is("select", dijit.getLastInTabbingOrder("select-container").id);
+						t.is("textarea", dijit.getLastInTabbingOrder("textarea-container").id);
+					},
+					function findTabOnElementRatherThanString(t){
+						t.is("a-with-href", dijit.getFirstInTabbingOrder(dojo.byId("a-with-href-container")).id);
+						t.is("a-with-href", dijit.getLastInTabbingOrder(dojo.byId("a-with-href-container")).id);
+					},
+					function findTabSkipDisabled(t){
+						t.is("not-disabled-input", dijit.getFirstInTabbingOrder("skip-disabled").id);
+						t.is("not-disabled-input", dijit.getLastInTabbingOrder("skip-disabled").id);
+					},
+					function findTabZeroTabindex(t){
+						t.is("zero-tabindex-div", dijit.getFirstInTabbingOrder("zero-tabindex-div-container").id);
+						t.is("zero-tabindex-input", dijit.getFirstInTabbingOrder("zero-tabindex-input-container").id);
+						t.is("zero-tabindex-div", dijit.getLastInTabbingOrder("zero-tabindex-div-container").id);
+						t.is("zero-tabindex-input", dijit.getLastInTabbingOrder("zero-tabindex-input-container").id);
+					},
+					function findTabPositiveTabindex(t){
+						t.is("positive-tabindex-input1a", dijit.getFirstInTabbingOrder("positive-tabindex-mixed-with-no-tabindex").id);
+						t.is("positive-tabindex-input3a", dijit.getFirstInTabbingOrder("positive-tabindex").id);
+						t.is("no-tabindex-input2", dijit.getLastInTabbingOrder("positive-tabindex-mixed-with-no-tabindex").id);
+						t.is("positive-tabindex-input4b", dijit.getLastInTabbingOrder("positive-tabindex").id);
+					},
+					function findTabSkipMinusOneTabindex(t){
+						t.is("not-minus-one-input", dijit.getFirstInTabbingOrder("skip-minus-one").id);
+						t.is("not-minus-one-input", dijit.getLastInTabbingOrder("skip-minus-one").id);
+					},
+					function findTabDescend(t){
+						t.is("child-input1", dijit.getFirstInTabbingOrder("descend").id);
+						t.is("child-input2", dijit.getLastInTabbingOrder("descend").id);
+					},
+					function findTabOuterInner(t){
+						t.is("outer1", dijit.getFirstInTabbingOrder("outer-inner-container").id);
+						t.is("inner2", dijit.getLastInTabbingOrder("outer-inner-container").id);
+					},
+					function skipNotShown(t){
+						t.is(null, dijit.getFirstInTabbingOrder("hidden-element-container"));
+						t.is(null, dijit.getFirstInTabbingOrder("hidden-container-tabindex-zero"));
+						t.is(null, dijit.getFirstInTabbingOrder("hidden-container-no-tabindex"));
+						t.is(null, dijit.getFirstInTabbingOrder("container-with-hidden-containers"));
+
+						t.is(null, dijit.getFirstInTabbingOrder("display-none-element-container"));
+						t.is(null, dijit.getFirstInTabbingOrder("display-none-container-tabindex-zero"));
+						t.is(null, dijit.getFirstInTabbingOrder("display-none-container-no-tabindex"));
+						t.is(null, dijit.getFirstInTabbingOrder("container-with-display-none-containers"));
+					}
+				]
+			);
+			doh.run();
+		});
+
+	</script>
+</head>
+<body class="claro">
+	<h1>Dijit TabIndex Related Functions Unit Test</h1>
+
+	<div id="empty"></div>
+
+	<div id="div-container">
+		<div id="div"></div>
+	</div>
+	<div id="a-without-href-container">
+		<a id="a-without-href" name="named-link-anchor"></a>
+	</div>
+	<div id="a-with-href-container">
+		<a id="a-with-href" href="#named-link-anchor"></a>
+	</div>
+
+	<div><img src="../images/flatScreen.gif" alt="picture of a flat-screen monitor" usemap="#area-map"></div>
+	<map id="area-map" name="area-map">
+		<area id="area" href="#" alt="example area" shape="rect" coords="0,0,8,8">
+	</map>
+
+	<div id="button-container">
+		<button id="button"></button>
+	</div>
+	<div id="input-container">
+		<input id="input">
+	</div>
+	<div id="object-container">
+		<object id="object"></object>
+	</div>
+	<div id="select-container">
+		<select id="select"></select>
+	</div>
+	<div id="textarea-container">
+		<textarea id="textarea"></textarea>
+	</div>
+
+	<div id="skip-disabled">
+		<input id="disabled-input1" disabled="disabled">
+		<input id="not-disabled-input">
+		<input id="disabled-input2" disabled="disabled">
+	</div>
+
+	<div id="zero-tabindex-div-container">
+		<div id="zero-tabindex-div" tabindex="0"></div>
+	</div>
+
+	<div id="no-tabindex-div-container">
+		<div id="no-tabindex-div"></div>
+	</div>
+
+	<div id="zero-tabindex-input-container">
+		<input id="zero-tabindex-input" tabindex="0">
+	</div>
+
+	<div id="iframe-container">
+		<div id="iframe"></div>
+	</div>
+
+	<div id="editor-container">
+		<div id="editor" dojoType="dijit.Editor"></div>
+	</div>
+
+	<div id="positive-tabindex-mixed-with-no-tabindex">
+		<input id="no-tabindex-input1">
+		<input id="no-tabindex-input2">
+		<input id="positive-tabindex-input1a" tabindex="1">
+		<input id="positive-tabindex-input1b" tabindex="1">
+		<input id="positive-tabindex-input2a" tabindex="2">
+		<input id="positive-tabindex-input2b" tabindex="2">
+	</div>
+
+	<div id="positive-tabindex">
+		<input id="positive-tabindex-input3a" tabindex="3">
+		<input id="positive-tabindex-input3b" tabindex="3">
+		<input id="positive-tabindex-input4a" tabindex="4">
+		<input id="positive-tabindex-input4b" tabindex="4">
+	</div>
+
+	<div id="skip-minus-one">
+		<input id="minus-one-input1" tabindex="-1">
+		<input id="not-minus-one-input">
+		<input id="minus-one-input2" tabindex="-1">
+	</div>
+
+	<div id="descend">
+		<input disabled="disabled">
+		<div>
+			<input disabled="disabled">
+			<div>
+				<input disabled="disabled">
+			</div>
+		</div>
+		<div>
+			<input disabled="disabled">
+			<div>
+				<input disabled="disabled">
+			</div>
+			<div>
+				<input id="child-input1">
+			</div>
+			<div>
+				<input id="child-input2">
+			</div>
+		</div>
+		<div>
+			<div>
+				<input disabled="disabled">
+			</div>
+			<input disabled="disabled">
+		</div>
+		<input disabled="disabled">
+	</div>
+
+	<div id="outer-inner-container">
+		<div id="outer1" tabindex="0">
+			<div id="inner1" tabindex="0"></div>
+		</div>
+		<div id="outer2" tabindex="0">
+			<div id="inner2" tabindex="0"></div>
+		</div>
+	</div>
+
+	<div id="hidden-element-container">
+		<div id="hidden-element" tabindex="0" style="visibility: hidden;">
+		</div>
+	</div>
+
+	<div id="container-with-hidden-containers">
+		<div id="hidden-container-tabindex-zero" tabindex="0" style="visibility: hidden;">
+			<div id="inside-hidden-container-tabindex-zero" tabindex="0">
+			</div>
+		</div>
+
+		<div id="hidden-container-no-tabindex" style="visibility: hidden;">
+			<div id="inside-hidden-container-no-tabindex" tabindex="0">
+			</div>
+		</div>
+	</div>
+
+	<div id="display-none-element-container">
+		<div id="display-none-element" tabindex="0" style="display: none;">
+		</div>
+	</div>
+
+	<div id="container-with-display-none-containers">
+		<div id="display-none-container-tabindex-zero" tabindex="0" style="display: none;">
+			<div id="inside-display-none-container-tabindex-zero" tabindex="0">
+			</div>
+		</div>
+
+		<div id="display-none-container-no-tabindex" style="display: none;">
+			<div id="inside-display-none-container-no-tabindex" tabindex="0">
+			</div>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/_base/test_CrossWindow.html b/dijit/tests/_base/test_CrossWindow.html
new file mode 100644
index 0000000..fe1fd74
--- /dev/null
+++ b/dijit/tests/_base/test_CrossWindow.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+	<head>
+		<title>Templated in IE Popup Test</title>
+		<style>
+			body{
+			font-family:Arial, Helvetica, sans-serif;
+			font-size:12px;
+			}
+		</style>
+		<script type="text/javascript"
+			src="../../../dojo/dojo.js"
+			debugAtAllCosts="false"
+			djConfig="isDebug:true, popup:false, parseOnLoad:false">
+		</script>
+		<script type="text/javascript">
+
+			dojo.require("dijit._Widget");
+			dojo.require("dijit._Templated");
+			dojo.require("dojo.parser");
+
+			var w;
+			var popup;
+			var widgetClass;
+			var popwin;
+			var globalDocument;
+			var mainwin = this;
+
+			onPopClose = function(){
+				console.log("setting context back to main window...");
+				dojo.setContext(dojo.global, globalDocument);
+				console.log("Now building the wdiget in the main window...");
+				var div = dojo.doc.createElement("div");
+				dojo.byId("main").appendChild(div);
+				new widgetClass({}, div);
+				console.log("There should now be two widgets at the top of the page.");
+			}
+
+			onPopLoad = function(){
+				popwin.onunload = onPopClose;
+
+				console.log("popwin:", popwin);
+				console.log("popwin.onunload :", popwin.onunload );
+
+				globalDocument = dojo.doc;
+				dojo.setContext(dojo.global, popwin.document);
+
+				console.log("rendering one widget in popup...");
+
+				var div = dojo.doc.createElement("div");
+				dojo.byId("main").appendChild(div);
+				new widgetClass({}, div);
+
+				console.log("The widget should have appeared in the popup window.");
+
+				onPopClose();
+			}
+
+			openPopup = function(){
+				popup = window.open ('',"mywin","width=240,height=180");
+				var doc=popup.document;
+
+				var newbcolor = '#FFFFFF';
+				var newfcolor = '$FF0000';
+				var word = "";
+				var HTMLstring=	'<HTML><HEAD><TITLE>IE Cross Window</TITLE></HEAD>\n' +
+								'<BODY id="popup" bgColor="'+newbcolor+'" onload = function(){popup.opener.onPopLoad();}>\n'+
+								'<div><div id="main"></div></div>\n'+
+								'</BODY></HTML>';
+
+				doc.write(HTMLstring);
+				doc.close();
+				popup.console = window.console;
+
+
+				// The onload event for IE is written into the above body tag.
+				// This is the onload for Firefox
+				if(dojo.isMoz){
+					popup.onload = onPopLoad
+				}else{
+					setTimeout(function(){
+						onPopLoad()
+					}, 200);
+				}
+
+				return popup;
+			}
+
+			speedTest = function(){
+				console.log("Speed Test");
+
+				var start = new Date();
+				var amt = 1000;
+
+				var div = dojo.doc.createElement("div");
+				dojo.byId("main").appendChild(div);
+
+				for(var i =0; i<amt; i++){
+					new widgetClass({}, div);
+				}
+				console.log("Time to render ", amt, " widgets:",  (new Date() - start) );
+			}
+
+			dojo.addOnLoad(function(){
+				widgetClass = dojo.declare(
+					"Simple",
+					[dijit._Widget, dijit._Templated], {
+						templateString: '<div> - Widget created -</div>'
+					}
+				);
+
+				speedTest();
+
+				console.log("Opening popup window...");
+				setTimeout(function(){
+					popwin = openPopup();
+				}, 0);
+			});
+		</script>
+	</head>
+	<body id="mainpage">
+		<h2>Test for cross window widget building</h2>
+		<p>
+			This test will create a widget in the main window, then in a popup, then another in the main window.
+			Tests issues on IE, namely making sure that nodes are created in the right document, see
+			<a href="http://trac.dojotoolkit.org/ticket/6791">#6791</a>.
+		</p>
+		<p>
+			You must allow popup before running this test.
+			Check console for results.
+		</p>
+		<div id="main"></div>
+	</body>
+</html>
diff --git a/dijit/tests/_base/test_FocusManager.html b/dijit/tests/_base/test_FocusManager.html
new file mode 100644
index 0000000..1bfe546
--- /dev/null
+++ b/dijit/tests/_base/test_FocusManager.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.focus Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../themes/tundra/tundra.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit._base.focus");
+		dojo.require("dijit._editor.selection");	// accessed by robot test
+		var savedFocus, fakeWidget;
+		dojo.addOnLoad(function(){
+			fakeWidget = { domNode: dojo.byId("save") };
+			dojo.subscribe("focusNode", function(node){ console.log("focused on " + (node?(node.id||node.tagName):"nothing"));});
+		});
+		function save(){
+			savedFocus = dijit.getFocus(fakeWidget);
+			console.debug("saved focus: ", savedFocus);
+
+		}
+		function restore(){
+			dijit.focus(savedFocus);
+			console.log("restored focus to: ", savedFocus);
+		}
+	</script>
+</head>
+<body style="background-color: #fff; color: black; padding: 0; margin: 0" class="claro">
+
+	<h3>Focus/Selection Save/Restore Test</h3>
+	<p>This is for testing whether focus and selection can be saved and restored by the focus manager.</p>
+	<p>
+		If you press the "Save focus" button, it should save the focus, but not the selection.
+		This is because merely pressing that button makes the focused textarea/input lose focus,
+		which also loses the selection.  (We fudge things by saving the previously focused element rather
+		than the currently focused one.)
+	</p>
+	<p>
+		If you press the "Save focus/selection state after 3 seconds" button, and then focus an input/textarea
+		and select some text, it should (after three seconds) save both the focused element and the selection.
+	</p>
+	<p id="selectableText" style="color: darkred">This paragraph contains text to select for testing purposes.</p>
+	<form style="border: 2px solid blue;">
+		<input id=input1 value=tom autocomplete=off><br>
+		<input id=input2 value=jones autocomplete=off><br>
+		<textarea id=textarea autocomplete=off>hello there!</textarea><br>
+		<button id=button>push me</button>
+	</form>
+
+	<button id="save" onclick="save();">Save focus</button>
+	<button id="delay_save" onclick="console.log('set timer for func'); setTimeout(save, 3000);">Save focus/selection state after 3 seconds</button>
+	<button id="restore" onclick="restore();">Restore focus/selection state</button>
+
+</body>
+</html>
diff --git a/dijit/tests/_base/test_focusWidget.html b/dijit/tests/_base/test_focusWidget.html
new file mode 100644
index 0000000..658d114
--- /dev/null
+++ b/dijit/tests/_base/test_focusWidget.html
@@ -0,0 +1,144 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.focus Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../themes/tundra/tundra.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.form.DateTextBox");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.NumberSpinner");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.Menu");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.Editor");
+
+		// This code does animation to change border color and width to show
+		// active vs. non-active widgets.
+		var queue=[];
+		var animation;
+		function animateBorderColor(widget, color, startWidth, endWidth){
+			if(animation){
+				queue.push(arguments);
+				return;
+			}
+			with(widget.domNode.style){
+				borderStyle="solid";
+				outlineStyle="solid";
+
+			}
+			animation = dojo.animateProperty({
+				node: widget.domNode,
+				duration: 50,
+				properties: {
+					// depending on browser and node type, sometimes border or outline is ineffective.
+					// doing both seems to work in all cases though (for at least one of them)
+					borderColor: { end: color },
+					borderWidth: { start: startWidth, end: endWidth },
+					outlineColor: { end: color },
+					outlineWidth: { start: startWidth, end: endWidth }
+				},
+				onEnd: function(){
+					animation=null;
+					if(queue.length){
+						animateBorderColor.apply(null, queue.shift());
+					}
+				}
+			});
+			animation.play();
+		}
+
+		// This flag controls animation and can be disabled by the test harness in robot/focus_mouse.html
+		animate = !window.location.search.match("animate=false");
+
+		dojo.addOnLoad(function(){
+			dojo.subscribe("widgetFocus", function(widget){
+				console.log("focused on widget " + (widget?widget:"nothing"));
+				if(animate){
+					animateBorderColor(widget, "#ff0000", 1, 3);
+				}
+			});
+			dojo.subscribe("widgetBlur", function(widget){
+				console.log("blurred widget " + (widget?widget:"nothing"));
+				if(animate){
+					animateBorderColor(widget, "#0000ff", 3, 1);
+				}
+			});
+			dojo.subscribe("focusNode", function(node){ console.log("focused on node " + (node?(node.id||node.tagName):"nothing"));});
+		});
+	</script>
+	<style>
+		div, fieldset, form, input {
+			padding: 3px;
+			margin: 3px;
+			border: 1px solid blue;
+		}
+	</style>
+</head>
+<body style="background-color: #fff; color: black; padding: 0; margin: 0" class="claro">
+
+	<h3>Widget Focus Test</h3>
+	<p>
+		This is for testing code to detect onBlur and onFocus on a widget level.<br>
+		Focused widgets' borders will turn red.<br>
+		Also, check the console log for focus and blur events on widgets.
+	</p>
+
+	<label for="fieldset1">a form ContentPane widget:</label><br>
+	<form dojoType="dijit.layout.ContentPane" id="form">
+		<label for="first">simple input: </label><input id=first><br>
+
+		<label for="fieldset1">a fieldset ContentPane widget:</label><br>
+		<fieldset id=fieldset1 dojoType="dijit.layout.ContentPane">
+			<label for="select">a ComboBox widget:</label>
+			<select id=select dojoType="dijit.form.ComboBox">
+				<option>this</option>
+				<option>is</option>
+				<option>a</option>
+				<option>list</option>
+			</select>
+			<label for="plain">a plain input:</label>
+			<input id=plain value=plain>
+		</fieldset>
+		<div dojoType="dijit.Editor" id=editor>
+			Hello world, this is an <i>editor</i>
+		</div>
+		<br>
+		<label for="fieldset1">another fieldset ContentPane:</label><br>
+		<fieldset id=fieldset2 dojoType="dijit.layout.ContentPane">
+			<label for="date">a DateTextBox widget:</label>
+			<input id=date dojoType="dijit.form.DateTextBox"><br>
+
+			<label for="textarea">a plain textarea:</label><br>
+			<textarea id=textarea>hello there!</textarea><br>
+
+			<label for="spinner">a Spinner widget:</label>
+			<input id=spinner dojoType="dijit.form.NumberSpinner" value=100><br>
+
+			<label for="button">a Combobutton widget:</label>
+			<div id=button dojoType="dijit.form.ComboButton" tabIndex=0>
+				<span>push me</span>
+				<div id=menu dojoType="dijit.Menu">
+					<div id=mi1 dojoType="dijit.MenuItem">menu item 1</div>
+					<div id=mi2 dojoType="dijit.MenuItem">menu item 2</div>
+					<div id=popupMenuItem dojoType="dijit.PopupMenuItem">
+						<span>submenu</span>
+						<div id=submenu dojoType="dijit.Menu">
+							<div id=smi1 dojoType="dijit.MenuItem">submenu item 1</div>
+							<div id=smi2 dojoType="dijit.MenuItem">submenu item 2</div>
+						</div>
+					</div>
+				</div>
+			</div>
+		</fieldset>
+	</form>
+</body>
+</html>
diff --git a/dijit/tests/_base/test_popup.html b/dijit/tests/_base/test_popup.html
new file mode 100644
index 0000000..39827df
--- /dev/null
+++ b/dijit/tests/_base/test_popup.html
@@ -0,0 +1,270 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit.popup and BackgroundIFrame unit test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../themes/dijit.css";
+		@import "../css/dijitTests.css";
+
+		body {
+			height: 100%;
+			padding: 0px;
+			margin: 0px;
+		}
+
+		div {
+			background: white;
+			border: solid 1px gray;
+		}
+
+		/* the menu type test widgets */
+		.choice div {
+			width: 200px;
+			cursor: pointer;
+		}
+		.choice div:hover {
+			background: #ccc;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: false"></script>
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+
+		function log(str){
+			console.log(str);
+		}
+
+		dojo.addOnLoad(function(){
+
+			dojo.declare("SimpleDropDownButton", [dijit._Widget, dijit._Templated], {
+				// summary:
+				//		A button that shows a popup.
+				//		Supply popup as parameter when instantiating this widget.
+
+				label: "show popup",
+				orient: {'BL': 'TL', 'BR': 'TR'},
+
+				templateString: "<button dojoAttachEvent='onclick: openPopup'>${label}</button>",
+
+				openPopup: function(){
+					var self = this;
+
+					dijit.popup.open({
+						popup: this.popup,
+						parent: this,
+						around: this.domNode,
+						orient: this.orient,
+						onCancel: function(){
+							log(self.id + ": cancel of child");
+						},
+						onExecute: function(){
+							log(self.id + ": execute of child");
+							dijit.popup.close(self.popup);
+							self.open = false;
+						}
+					});
+
+					this.open = true;
+				},
+
+				closePopup: function(){
+					if(this.open){
+						log(this.id + ": close popup due to blur");
+						dijit.popup.close(this.popup);
+						this.open = false;
+					}
+				},
+
+				_onBlur: function(){
+					// summary:
+					//		This is called from focus manager and when we get the signal we
+					//		need to close the drop down
+					this.closePopup();
+				}
+			});
+
+			dojo.declare("SimpleChoiceWidget",  [dijit._Widget, dijit._Templated], {
+				// summary:
+				//		A list of values; select a value by pressing an entry in the list.
+
+				choice1: "1",
+				choice2: "2",
+				choice3: "3",
+
+				templateString:
+					"<div class='choice'>" +
+						"<div dojoAttachEvent='onclick: onClick'>${choice1}</div>" +
+						"<div dojoAttachEvent='onclick: onClick'>${choice2}</div>" +
+						"<div dojoAttachEvent='onclick: onClick'>${choice3}</div>" +
+					"</div>",
+
+				onClick: function(e){
+					this.onChange(e.target.innerHTML);
+				},
+
+				onChange: function(val){
+					// summary:
+					//		When this widget is used as a popup, dijit.popup monitors calls
+					//		to onChange and then closes the popup
+					log(this.id + ": selected " + val);
+				}
+			});
+
+			// Create a button that displays a simple drop down
+			choiceDropDown = new SimpleChoiceWidget();
+			choiceDropDownButton = new SimpleDropDownButton({
+				id: "choiceDropDownButton",
+				label: "show choice drop down",
+				popup: choiceDropDown
+			}).placeAt(dojo.body());
+
+			dojo.declare("DialogWithPopupWidget",  [dijit._Widget, dijit._Templated], {
+				// summary:
+				//		This is a dialog that contains a button that spawns a drop down.
+				//		Supply popup as an argument to this widget.
+
+				title: "I'm a dialog",
+				label: "click me",
+
+				templateString:
+					"<div style='width: 300px'>" +
+						"<div>${title}</div>" +
+						"<input><br>" +
+						"<button dojoAttachPoint='button'>${label}</button><br>" +
+						"<button dojoAttachEvent='onclick: onExecute'>OK</button>" +
+					"</div>",
+
+				postCreate: function(){
+					// Convert the plain button into a SimpleDropDownButton widget.
+					// Having it be a widget is important because that's how the popup
+					// code knows where a stack of nested popups (typically menus) ends.
+					// (In this case closing a stack of menus shouldn't close the dialog.)
+
+					new SimpleDropDownButton({
+						id: this.id + "PopupButton",
+						label: this.label,
+						popup: this.popup,
+						orient: {'BR': 'BL', 'TR': 'tL'}	// so popup doesn't cover OK button
+					}, this.button);
+				},
+
+				onExecute: function(){
+					// summary:
+					//		Called when OK button is pressed.
+					//		If this is used as a popup this signals to the parent that
+					//		Dialog can be closed.
+					console.log(this.id + ": executed");
+				}
+			});
+
+			// Create a button that displays a dialog that displays a choice widget
+			dialogDropDownButton = new SimpleDropDownButton({
+				id: "showSimpleDialogButton",
+				label: "show dialog",
+				popup: new DialogWithPopupWidget({
+					id: "simpleDialog",
+					label: 'show simple choice drop down',
+					popup: new SimpleChoiceWidget({
+						id: "choiceFromDialog"
+					})
+				})
+			}).placeAt(dojo.body());
+
+			dojo.declare("NestedPopupOpener",  [dijit._Widget, dijit._Templated], {
+				// summary:
+				//		Clicking a value in this list will open a nested popup.
+				//		Specify popup1 and popup2 as parameters to this widget.
+
+				templateString:
+					"<div class='choice'>" +
+						"<div dojoAttachEvent='onclick: onClick'>popup1</div>" +
+						"<div dojoAttachEvent='onclick: onClick'>popup2</div>" +
+					"</div>",
+
+				onClick: function(e){
+					var id = this.id,
+						popup = this[e.target.innerHTML];
+					log(id + ": opening popup " + popup.id);
+					this.openPopup(popup);
+				},
+
+				openPopup: function(popup){
+					dijit.popup.open({
+						popup: popup,
+						parent: this,
+						around: this.domNode,
+						orient: {'TR': 'TL', 'TL': 'TR'},
+						onCancel: function(){
+							log(id + ": cancel of child " + popup.id);
+						},
+						onExecute: function(){
+							log(id + ": execute of child " + popup.id);
+							dijit.popup.close(popup);
+						}
+					})
+				},
+
+				closePopup: function(popup){
+					dijit.popup.close(popup);
+				}
+			});
+
+			// Create a button that displays a nested drop down.
+			nestedOpener = new NestedPopupOpener({
+				id: 'nestedPopupOpener',
+				popup1: (nestedChoice1 = new SimpleChoiceWidget({
+					id: "nestedChoice1"
+				})),
+				popup2: (nestedChoice2 = new SimpleChoiceWidget({
+					id: "nestedChoice2",
+					choice1: "4",
+					choice2: "5",
+					choice3: "6"
+				}))
+			});
+			nestedDropDownButton = new SimpleDropDownButton({
+				id: "showNestedMenuButton",
+				label: "show nested drop down",
+				popup: nestedOpener
+			}).placeAt(dojo.body());
+
+			// Create a button that displays a dialog that displays a nested drop down
+			dialogNestedChoice1 = new SimpleChoiceWidget({
+				id: "dialogNestedChoice1"
+			});
+			dialogNestedChoice2 = new SimpleChoiceWidget({
+				id: "dialogNestedChoice2",
+				choice1: "4",
+				choice2: "5",
+				choice3: "6"
+			});
+			dialogNestedPopupOpener = new NestedPopupOpener({
+				id: "nestedPopupOpenerFromDialog",
+				popup1: dialogNestedChoice1,
+				popup2: dialogNestedChoice2
+			});
+			dialogWithNestedPopup = new DialogWithPopupWidget({
+				id: "buttonInComplexDialog",
+				label: 'show nested menu',
+				popup: dialogNestedPopupOpener
+			});
+			dialogDropDownButton = new SimpleDropDownButton({
+				id: "showComplexDialogButton",
+				label: "show dialog w/nested menu",
+				popup: dialogWithNestedPopup
+			}).placeAt(dojo.body());
+
+		});
+
+	</script>
+</head>
+<body>
+	<h1>dijit.popup and BackgroundIFrame Unit Test</h1>
+	<button>simple button</button>
+</body>
+</html>
diff --git a/dijit/tests/_base/test_typematic.html b/dijit/tests/_base/test_typematic.html
new file mode 100644
index 0000000..e72baac
--- /dev/null
+++ b/dijit/tests/_base/test_typematic.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Typematic Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../themes/tundra/tundra.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, debugAtAllCosts: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit._base.typematic");
+
+		var lastCount = 0;
+		function typematicCallBack(count, node, evt){
+			var inputNode = dojo.byId('typematicInput');
+			if (node == inputNode){
+				key = "a";
+			}else{
+				key = "b";
+			}
+			if(-1 == count){
+				console.debug((lastCount+1) + ' ' + key + ' events');
+			}else{
+				lastCount = count;
+				inputNode.value += key;
+			}
+				inputNode.focus();
+		}
+		dojo.addOnLoad(function(){
+			var keyNode = dojo.byId('typematicInput');
+			var mouseNode = dojo.byId('typematicButton');
+			dijit.typematic.addKeyListener(keyNode,
+				{
+					charOrCode:dojo.keys.F11,
+					shiftKey:false,
+					metaKey:false,
+					ctrlKey:true // ALT is optional since its unspecified
+				},
+				this, typematicCallBack, 200, 200);
+			dijit.typematic.addMouseListener(mouseNode,
+				this, typematicCallBack, 0.9, 200);
+
+			try {
+				// Focus the input so it's easier for user to start typing.
+				// Doesn't work well in IE6 though, when this test is loaded from robot/typematic.html,
+				// Apparently the robot code sets up a cover <div> over this page and IE doesn't want to focus
+				// the input since it's hidden.
+				keyNode.focus();
+			}catch(e){}
+		});
+	</script>
+</head>
+<body class="claro">
+
+	<h2>Dijit typematic tests</h2>
+	Press and hold the <b>ctrl+F11</b> keys (ALT optional, but not Shift or Meta) to see a's typed (constant rate) in the input field,<br>
+	or left-mouse click the button and hold down to see b's typed (increasing rate) in the input field.<br>
+	<input id="typematicInput" size="500"><button id="typematicButton">to B or not to B</button>
+
+</body>
+</html>
diff --git a/dijit/tests/_base/wai.html b/dijit/tests/_base/wai.html
new file mode 100644
index 0000000..8a4860a
--- /dev/null
+++ b/dijit/tests/_base/wai.html
@@ -0,0 +1,194 @@
+<html>
+<head>
+	<title>Dijit wai unit test</title>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit.dijit");
+
+		dojo.addOnLoad(function(){
+			doh.register("dijit.tests._base.wai",
+				[
+					function getWaiRoleOnElementWithNoRole(){
+						var elem = dojo.byId("no-role-or-states");
+						doh.assertFalse(dijit.hasWaiRole(elem));
+						doh.assertEqual("", dijit.getWaiRole(elem));
+					},
+
+					function getEmptyWairoleRole(){
+						var elem = dojo.byId("empty-wairole");
+						doh.assertFalse(dijit.hasWaiRole(elem));
+						doh.assertEqual("", dijit.getWaiRole(elem));
+					},
+
+					function getWairoleRole(){
+						var elem = dojo.byId("wairole");
+						doh.assertTrue(dijit.hasWaiRole(elem));
+						doh.assertEqual("menuitem", dijit.getWaiRole(elem));
+					},
+
+					function getUnprefixedRole(){
+						var elem = dojo.byId("unprefixed-role");
+						doh.assertTrue(dijit.hasWaiRole(elem));
+						doh.assertEqual("menuitem", dijit.getWaiRole(elem));
+					},
+
+					function getOnlyXHTMLRole(){
+						var elem=dojo.byId("navigation-role");
+						doh.assertFalse(dijit.hasWaiRole(elem, "contentinfo"));
+						doh.assertEqual("", dijit.getWaiRole(elem));
+					},
+
+					function getWaiRoleFromMultiple(){
+						var elem=dojo.byId("multiple-role-wairole");
+						doh.assertTrue(dijit.hasWaiRole(elem, "menuitem"));
+						doh.assertEqual("menuitem", dijit.getWaiRole(elem));
+					},
+
+					function getUnprefixedFromMultiple(){
+						var elem=dojo.byId("multiple-role");
+						doh.assertTrue(dijit.hasWaiRole(elem, "menuitem"));
+						doh.assertEqual("menuitem", dijit.getWaiRole(elem));
+					},
+
+					function getReverseWairoleFromMultiple(){
+						var elem=dojo.byId("reverse-order-wairole");
+						doh.assertTrue(dijit.hasWaiRole(elem, "menuitem"));
+						doh.assertEqual("menuitem", dijit.getWaiRole(elem));
+					},
+
+					function getReverseUnprefixedFromMultiple(){
+						var elem=dojo.byId("reverse-order-noprefix");
+						doh.assertTrue(dijit.hasWaiRole(elem, "menuitem"));
+						doh.assertEqual("menuitem", dijit.getWaiRole(elem));
+					},
+
+					function hasWaiRoleMixedRole(){
+						var elem=dojo.byId("multiple-role");
+						doh.assertTrue(dijit.hasWaiRole(elem, "menuitem"));
+					},
+
+					function hasWaiRoleXHTMLRole(){
+						var elem=dojo.byId("navigation-role");
+						doh.assertFalse(dijit.hasWaiRole(elem));
+					},
+
+
+					function setWaiRole(){
+						var div = document.createElement("div");
+						dijit.setWaiRole(div, "menuitem");
+						doh.assertEqual("menuitem", div.getAttribute("role"));
+					},
+
+					function setWaiRoleToExistingXHTML() {
+						var elem=dojo.byId("navigation-role");
+						dijit.setWaiRole(elem, "treeitem");
+						doh.assertEqual("contentinfo treeitem", elem.getAttribute("role"));
+					},
+
+					function setWaiRoleToExistingWaiRole() {
+						var div= document.createElement("div");
+						dijit.setWaiRole(div, "menuitem");
+						doh.assertTrue(dijit.hasWaiRole(div, "menuitem"));
+						dijit.setWaiRole(div, "treeitem");
+						doh.assertEqual("treeitem", div.getAttribute("role"));
+					},
+
+					function setWaiRoleToExistingWaiAndXHTMLRole() {
+						var div= dojo.byId("navigation-role");
+						dijit.setWaiRole(div, "menuitem");
+						doh.assertTrue(dijit.hasWaiRole(div, "menuitem"));
+						dijit.setWaiRole(div, "treeitem");
+						doh.assertEqual("contentinfo treeitem", div.getAttribute("role"));
+					},
+
+					function removeAllWaiRole(){
+						var div = document.createElement("div");
+						dijit.setWaiRole(div, "menuitem");
+						doh.assertTrue(dijit.hasWaiRole(div, "menuitem"));
+						dijit.removeWaiRole(div);
+						if(div.hasAttribute){
+							doh.assertFalse(div.hasAttribute("role"));
+						}else{
+							doh.assertTrue(div.getAttribute("role") == null
+								|| div.getAttribute("role") == "");
+						}
+					},
+
+					function removeAllRoleMultiple(){
+						var elem=dojo.byId("multiple-role");
+						dijit.removeWaiRole(elem);
+						if(elem.hasAttribute){
+							doh.assertFalse(elem.hasAttribute("role"));
+						}else{
+							doh.assertTrue(elem.getAttribute("role") == null
+								|| elem.getAttribute("role") == "");
+						}
+					},
+
+					function removeSingleRoleMultiple(){
+						var div= dojo.byId("navigation-role");
+						dijit.setWaiRole(div, "menuitem");
+						doh.assertTrue(dijit.hasWaiRole(div, "menuitem"));
+						dijit.removeWaiRole(div, "menuitem");
+						doh.assertFalse(dijit.hasWaiRole(div, "menuitem"));
+						doh.assertEqual("contentinfo", div.getAttribute("role"));
+					},
+
+					function removeSingleReversedRoleMultiple(){
+						var div= document.createElement("div");
+						dijit.setWaiRole(div, "menuitem");
+						var curRole = dojo.attr(div, "role");
+						dojo.attr(div, "role", curRole += " contentinfo");
+						dijit.removeWaiRole(div, "menuitem");
+						doh.assertEqual("contentinfo", div.getAttribute("role"));
+					},
+
+					function getWaiStateOnElementWithNoState(){
+						var elem = dojo.byId("no-role-or-states");
+						doh.assertFalse(dijit.hasWaiState(elem, "checked"));
+						doh.assertEqual("", dijit.getWaiState(elem, "checked"));
+					},
+
+					function getWaiState(){
+						var elem = dojo.byId("checked");
+						doh.assertTrue(dijit.hasWaiState(elem, "checked"));
+						doh.assertEqual("true",
+							dijit.getWaiState(elem, "checked"));
+					},
+
+					function setWaiState(){
+						var div = document.createElement("div");
+						dijit.setWaiState(div, "checked", "true");
+						doh.assertEqual("true",
+							div.getAttribute("aria-checked"));
+					},
+
+					function removeWaiState(){
+						var div = document.createElement("div");
+						dijit.setWaiState(div, "checked", "true");
+						dijit.removeWaiState(div, "checked");
+						doh.assertEqual("", dijit.getWaiState(div, "checked"));
+					}
+				]
+			);
+			doh.run();
+		});
+	</script>
+</head>
+<body>
+	<div id="no-role-or-states"></div>
+	<div id="empty-wairole" role="wairole:"></div>
+	<div id="wairole" role="wairole:menuitem"></div>
+	<div id="unprefixed-role" role="menuitem"></div>
+	<div id="navigation-role" role="contentinfo"></div>
+	<div id="single-role" role="contentinfo"></div>
+	<div id="multiple-role-wairole" role="contentinfo wairole:menuitem"></div>
+	<div id="multiple-role" role="contentinfo menuitem"></div>
+	<div id="reverse-order-wairole" role="wairole:menuitem contentinfo"></div>
+	<div id="reverse-order-noprefix" role="menuitem contentinfo"></div>
+	<div id="checked" aria-checked="true"></div>
+
+</body>
+</html>
diff --git a/dijit/tests/_data/SlowStore.js b/dijit/tests/_data/SlowStore.js
new file mode 100644
index 0000000..480da92
--- /dev/null
+++ b/dijit/tests/_data/SlowStore.js
@@ -0,0 +1,92 @@
+dojo.provide("dijit.tests._data.SlowStore");
+
+dojo.require("dojo.data.ItemFileReadStore");
+
+dojo.declare("dijit.tests._data.SlowStore", dojo.data.ItemFileReadStore, {
+	// summary:
+	//		This wrapper decorates an ItemFileReadStorere by delaying queries issued according to the
+	//		length of the query:
+	//
+	//			empty query: 2000ms,
+	//			1 or 2 characters: 1000ms,
+	//			3 characters: 500ms,
+	//			4 or more characters: 100ms.
+	//
+
+	constructor: function(){
+		this.log = [];
+	},
+
+	fetch: function(/* Object */ keywordArgs){
+		// Get the query phrase (store into first), and the # of chars it has
+		var count = 0;
+		var first;
+		if("query" in keywordArgs){
+			var query = keywordArgs.query;
+			for(var attr in query){
+				first = query[attr];
+				break;
+			}
+			if(dojo.isString(first)){
+					count = first.length;
+			}
+		}
+
+		var delay = 100;
+		switch(count || 0){
+			case 0:
+				delay = 2000;
+				break;
+			case 1:
+			case 2:
+				delay = 1000;
+				break;
+			case 3:
+				delay = 500;
+				break;
+			case 4:
+				delay = 100;
+				break;
+		}
+
+		this.log.push({
+			type: "start",
+			date: new Date(),
+			query: query,
+			count: count,
+			delay: delay
+		});
+		console.log("START query on " + (first || "{}") + " (" + count + " chars), delay = " + delay);
+
+		var that = this,
+			thatArgs = arguments;
+		var handle = setTimeout(function(){
+			that.log.push({
+				type: "end",
+				date: new Date(),
+				query: query,
+				count: count,
+				delay: delay
+			});
+			console.log("END query on " + (first || "{}") + " (" + count + " chars), delay = " + delay);
+			dojo.data.ItemFileReadStore.prototype.fetch.apply(that, thatArgs);
+		}, delay);
+
+		// This abort() method cancels a request before it has even been sent to ItemFileReadStore.
+		// (Since ItemFileReadStore has already loaded the data (as per code in the test file),
+		// it operates synchronously; there is never a case to send the cancel request to that object)
+		keywordArgs.abort = function(){
+			clearTimeout(handle);
+			that.log.push({
+				type: "cancel",
+				date: new Date(),
+				query: query,
+				count: count,
+				delay: delay
+			});
+			console.log("CANCEL query on " + (first || "{}") + " (" + count + " chars), delay = " + delay);
+		};
+
+		return keywordArgs;
+	}
+});
diff --git a/dijit/tests/_data/categories.json b/dijit/tests/_data/categories.json
new file mode 100644
index 0000000..ff5ffe1
--- /dev/null
+++ b/dijit/tests/_data/categories.json
@@ -0,0 +1,12 @@
+{
+	identifier: 'id',
+	label: 'name',
+	items: [
+		{ id: '0', name:'Foods', numberOfItems:1, children:[ {_reference: '1'},  {_reference: '2'},  {_reference: '3'} ] },
+			{ id: '1', name:'Fruits', numberOfItems:1, children:[ {_reference: '4'} ] },
+				{ id: '4',name:'Citrus', numberOfItems:1, items:[ {_reference: '5'} ] },
+					{ id: '5', name:'Orange'},
+		{ id: '2', name:'Vegetables', numberOfItems:0},
+		{ id: '3', name:'Cereals', numberOfItems:0}
+	]
+}
diff --git a/dijit/tests/_data/categoriesNested.json b/dijit/tests/_data/categoriesNested.json
new file mode 100644
index 0000000..f130ae5
--- /dev/null
+++ b/dijit/tests/_data/categoriesNested.json
@@ -0,0 +1,13 @@
+{
+	identifier: 'id',
+	label: 'name',
+	items: [
+		{ id: '0', name:'Fruits', numberOfItems:1, children:[
+			{ id: '1',name:'Citrus', numberOfItems:1, items:[
+				{ id: '4', name:'Orange'}
+			]}
+		]},
+		{ id: '2', name:'Vegetables', numberOfItems:0},
+		{ id: '3', name:'Cereals', numberOfItems:0}
+	]
+}
diff --git a/dijit/tests/_data/countries.json b/dijit/tests/_data/countries.json
new file mode 100644
index 0000000..155b93c
--- /dev/null
+++ b/dijit/tests/_data/countries.json
@@ -0,0 +1,46 @@
+{
+	identifier: 'id',
+	label: 'name',
+	items: [
+	        { id: 'AF', name:'Africa', type:'continent', population:'900 million', area: '30,221,532 sq km',
+	        		timezone: '-1 UTC to +4 UTC',
+	        		children:[{_reference:'EG'}, {_reference:'KE'}, {_reference:'SD'}] },
+	        	{ id: 'EG', name:'Egypt', type:'country' },
+	        	{ id: 'KE', name:'Kenya', type:'country',
+	        			children:[{_reference:'Nairobi'}, {_reference:'Mombasa'}] },
+	        		{ id: 'Nairobi', name:'Nairobi', type:'city' },
+	        		{ id: 'Mombasa', name:'Mombasa', type:'city' },
+	        	{ id: 'SD', name:'Sudan', type:'country',
+	        			children:{_reference:'Khartoum'} },
+	        		{ id: 'Khartoum', name:'Khartoum', type:'city' },
+	        	{ id: 'AS', name:'Asia', type:'continent',
+	        			children:[{_reference:'CN'}, {_reference:'IN'}, {_reference:'RU'}, {_reference:'MN'}] },
+	        		{ id: 'CN', name:'China', type:'country' },
+	        		{ id: 'IN', name:'India', type:'country' },
+	        		{ id: 'RU', name:'Russia', type:'country' },
+	        		{ id: 'MN', name:'Mongolia', type:'country' },
+	        	{ id: 'OC', name:'Oceania', type:'continent', population:'21 million',
+	        			children:{_reference:'AU'}},
+	        	{ id: 'AU', name:'Australia', type:'country', population:'21 million'},
+	        	{ id: 'EU', name:'Europe', type:'continent',
+	        			children:[{_reference:'DE'}, {_reference:'FR'}, {_reference:'ES'}, {_reference:'IT'}] },
+	        	{ id: 'DE', name:'Germany', type:'country' },
+	        	{ id: 'FR', name:'France', type:'country' },
+	        	{ id: 'ES', name:'Spain', type:'country' },
+	        	{ id: 'IT', name:'Italy', type:'country' },
+	        { id: 'NA', name:'North America', type:'continent',
+	        		children:[{_reference:'MX'}, {_reference:'CA'}, {_reference:'US'}] },
+	        	{ id: 'MX', name:'Mexico', type:'country',  population:'108 million', area:'1,972,550 sq km',
+	        			children:[{_reference:'Mexico City'}, {_reference:'Guadalajara'}] },
+	        		{ id: 'Mexico City', name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
+	        		{ id: 'Guadalajara', name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' },
+	        	{ id: 'CA', name:'Canada', type:'country',  population:'33 million', area:'9,984,670 sq km',
+	        			children:[{_reference:'Ottawa'}, {_reference:'Toronto'}] },
+	        		{ id: 'Ottawa', name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
+	        		{ id: 'Toronto', name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' },
+	        	{ id: 'US', name:'United States of America', type:'country' },
+	        { id: 'SA', name:'South America', type:'continent',
+	        		children:[{_reference:'BR'}, {_reference:'AR'}] },
+	        	{ id: 'BR', name:'Brazil', type:'country', population:'186 million' },
+	        	{ id: 'AR', name:'Argentina', type:'country', population:'40 million' }
+]}
diff --git a/dijit/tests/_data/dijits.json b/dijit/tests/_data/dijits.json
new file mode 100644
index 0000000..160581b
--- /dev/null
+++ b/dijit/tests/_data/dijits.json
@@ -0,0 +1 @@
+{"timestamp":1193692111,"items":[{"namespace":"dijit","className":"dijit.ColorPalette","summary":"Grid showing various colors, so the user can pick a certain color","description":null,"examples":null},{"namespace":"dijit","className":"dijit.Declaration","summary":"The Declaration widget allows a user to declare new widget\nclasses directly from a snippet of markup.","description":null,"examples":null},{"namespace":"dijit","className":"dijit.DialogUnderlay","summary":"the thing that grays [...]
\ No newline at end of file
diff --git a/dijit/tests/_data/states.json b/dijit/tests/_data/states.json
new file mode 100644
index 0000000..9f29108
--- /dev/null
+++ b/dijit/tests/_data/states.json
@@ -0,0 +1,67 @@
+{
+  identifier:"abbreviation",
+  label: "name",
+  items: [
+	{name:"Alabama", label:"<img width='97px' height='127px' src='images/Alabama.jpg'/>Alabama",abbreviation:"AL"},
+	{name:"Alaska", label:"Alaska",abbreviation:"AK"},
+	{name:"American Samoa", label:"American Samoa",abbreviation:"AS"},
+	{name:"Arizona", label:"Arizona",abbreviation:"AZ"},
+	{name:"Arkansas", label:"Arkansas",abbreviation:"AR"},
+	{name:"Armed Forces Europe", label:"Armed Forces Europe",abbreviation:"AE"},
+	{name:"Armed Forces Pacific", label:"Armed Forces Pacific",abbreviation:"AP"},
+	{name:"Armed Forces the Americas", label:"Armed Forces the Americas",abbreviation:"AA"},
+	{name:"California", label:"California",abbreviation:"CA"},
+	{name:"Colorado", label:"Colorado",abbreviation:"CO"},
+	{name:"Connecticut", label:"Connecticut",abbreviation:"CT"},
+	{name:"Delaware", label:"Delaware",abbreviation:"DE"},
+	{name:"District of Columbia", label:"District of Columbia",abbreviation:"DC"},
+	{name:"Federated States of Micronesia", label:"Federated States of Micronesia",abbreviation:"FM"},
+	{name:"Florida", label:"Florida",abbreviation:"FL"},
+	{name:"Georgia", label:"Georgia",abbreviation:"GA"},
+	{name:"Guam", label:"Guam",abbreviation:"GU"},
+	{name:"Hawaii", label:"Hawaii",abbreviation:"HI"},
+	{name:"Idaho", label:"Idaho",abbreviation:"ID"},
+	{name:"Illinois", label:"Illinois",abbreviation:"IL"},
+	{name:"Indiana", label:"Indiana",abbreviation:"IN"},
+	{name:"Iowa", label:"Iowa",abbreviation:"IA"},
+	{name:"Kansas", label:"Kansas",abbreviation:"KS"},
+	{name:"Kentucky", label:"Kentucky",abbreviation:"KY"},
+	{name:"Louisiana", label:"Louisiana",abbreviation:"LA"},
+	{name:"Maine", label:"Maine",abbreviation:"ME"},
+	{name:"Marshall Islands", label:"Marshall Islands",abbreviation:"MH"},
+	{name:"Maryland", label:"Maryland",abbreviation:"MD"},
+	{name:"Massachusetts", label:"Massachusetts",abbreviation:"MA"},
+	{name:"Michigan", label:"Michigan",abbreviation:"MI"},
+	{name:"Minnesota", label:"Minnesota",abbreviation:"MN"},
+	{name:"Mississippi", label:"Mississippi",abbreviation:"MS"},
+	{name:"Missouri", label:"Missouri",abbreviation:"MO"},
+	{name:"Montana", label:"Montana",abbreviation:"MT"},
+	{name:"Nebraska", label:"Nebraska",abbreviation:"NE"},
+	{name:"Nevada", label:"Nevada",abbreviation:"NV"},
+	{name:"New Hampshire", label:"New Hampshire",abbreviation:"NH"},
+	{name:"New Jersey", label:"New Jersey",abbreviation:"NJ"},
+	{name:"New Mexico", label:"New Mexico",abbreviation:"NM"},
+	{name:"New York", label:"New York",abbreviation:"NY"},
+	{name:"North Carolina", label:"North Carolina",abbreviation:"NC"},
+	{name:"North Dakota", label:"North Dakota",abbreviation:"ND"},
+	{name:"Northern Mariana Islands", label:"Northern Mariana Islands",abbreviation:"MP"},
+	{name:"Ohio", label:"Ohio",abbreviation:"OH"},
+	{name:"Oklahoma", label:"Oklahoma",abbreviation:"OK"},
+	{name:"Oregon", label:"Oregon",abbreviation:"OR"},
+	{name:"Pennsylvania", label:"Pennsylvania",abbreviation:"PA"},
+	{name:"Puerto Rico", label:"Puerto Rico",abbreviation:"PR"},
+	{name:"Rhode Island", label:"Rhode Island",abbreviation:"RI"},
+	{name:"South Carolina", label:"South Carolina",abbreviation:"SC"},
+	{name:"South Dakota", label:"South Dakota",abbreviation:"SD"},
+	{name:"Tennessee", label:"Tennessee",abbreviation:"TN"},
+	{name:"Texas", label:"Texas",abbreviation:"TX"},
+	{name:"Utah", label:"Utah",abbreviation:"UT"},
+	{name:"Vermont", label:"Vermont",abbreviation:"VT"},
+	{name: "Virgin Islands, U.S.",label:"Virgin Islands, U.S.",abbreviation:"VI"},
+	{name:"Virginia", label:"Virginia",abbreviation:"VA"},
+	{name:"Washington", label:"Washington",abbreviation:"WA"},
+	{name:"West Virginia", label:"West Virginia",abbreviation:"WV"},
+	{name:"Wisconsin", label:"Wisconsin",abbreviation:"WI"},
+	{name:"Wyoming", label:"Wyoming",abbreviation:"WY"}
+  ]
+}
\ No newline at end of file
diff --git a/dijit/tests/_data/treeTest.json b/dijit/tests/_data/treeTest.json
new file mode 100644
index 0000000..a6ad3d0
--- /dev/null
+++ b/dijit/tests/_data/treeTest.json
@@ -0,0 +1,22 @@
+{
+	identifier: 'id',
+	label: 'name',
+	items: [
+		{ id: 'root', name:'root', someProperty:'root property', children: [
+			{_reference:'node1'},
+			{_reference:'node2'},
+			{_reference:'node3'},
+			{_reference:'node4'},
+			{_reference:'node5'}
+		]},
+			{ id: 'node1', name:'node1', someProperty:'somePropertyA', children: [
+				{_reference:'node1.1'}, {_reference:'node1.2'}
+			]},
+				{ id: 'node1.1',name:'node1.1', someProperty:'somePropertyA1'},
+				{ id: 'node1.2',name:'node1.2', someProperty:'somePropertyA2'},
+			{ id: 'node2', name:'node2', someProperty:'somePropertyB'},
+			{ id: 'node3', name:'node3', someProperty:'somePropertyC'},
+			{ id: 'node4', name:'node4', someProperty:'somePropertyA'},
+			{ id: 'node5', name:'node5', someProperty:'somePropertyB'}
+	]
+}
diff --git a/dijit/tests/_loadTest.js b/dijit/tests/_loadTest.js
new file mode 100644
index 0000000..917d6a6
--- /dev/null
+++ b/dijit/tests/_loadTest.js
@@ -0,0 +1,87 @@
+document.write(function(){
+var file;
+var head = document.documentElement.firstChild;
+while(head && head.tagName != "HEAD"){
+	head = head.nextSibling;
+}
+var script = head.lastChild;
+while(script){
+	if(script.tagName == "SCRIPT"){
+		if((script.getAttribute('src')||'').search('_loadTest') >= 0 && (!script.readyState || script.readyState == "interactive")){
+			file = script.getAttribute('file');
+			break;
+		}
+	}
+	script = script.previousSibling;
+}
+if(!file && window.location.href.search(/[?&]file[=]/i) > 0){
+	file = window.location.href.replace(/.*[?&]file=(([^&?]*)).*/i, "$2");
+}
+var readFile = function(file){
+	var xhr = null;
+	try{ xhr = new XMLHttpRequest() }catch(e0){
+	try{ xhr = new ActiveXObject('Msxml2.XMLHTTP') }catch(e1){
+	try{ xhr = new ActiveXObject('Microsoft.XMLHTTP') }catch(e2){
+	try{ xhr = new ActiveXObject('Msxml2.XMLHTTP.4.0') }catch(e3){}}}}
+	try{
+		xhr.open("GET", file, false);
+		xhr.send(null);
+	}catch(e){ return null } // file not found
+	return xhr.responseText;
+}
+var text = readFile(file) || (file + " not found");
+var baseHref = file.replace(/^(.*\/)?[^\/]+$/, "$1");
+if(baseHref){
+	baseHref = window.location.href.replace(/[?].*/, "").replace(/[^\/]*$/, "")+baseHref;
+	text = text.replace(/(<HEAD\b([^>]|\s)*>)/i, "$1" + "<BASE href='" + baseHref + "'><\/BASE>");
+}
+// strip DOCTYPE and HTML tag
+text = text.replace(/^(.|\s)*?<html\b\S*\s*(([^>]|\s)*)\s*>((.|\s)*)<\/html\b([^>]|\s)*>(.|\s)*?$/i,
+	function(s,a1,htmlAttrs,a3,content){
+		// add attributes from target file's HTML tag - may not be necessary but we'll do it anyway for completeness
+		htmlAttrs = htmlAttrs.replace(/((\w+)\s*=\s*(['"]?)(.*?)(\3)?(\s+|$))/g,
+			function(s, all, attr, quote, val){
+				document.documentElement.setAttribute(attr, val);
+				return "";
+			});
+		return content;
+	});
+if(/MSIE/.test(navigator.userAgent)){ // need to load scripts serially
+	document._oldgetElementsByTagName_ = document.getElementsByTagName;
+	document.getElementsByTagName = function(tag){
+		// take over getElementsByTagName so I can take over script.getAttribute('src')
+		if(/^script$/i.test(tag)){
+			var scripts = document.scripts;
+			for(var i=0; i <scripts.length; i++){
+				var script = scripts[i];
+				if(!script['_oldGetAttribute']){
+					var src = script.getAttribute('_oldsrc');
+					if(src){
+						script._oldGetAttribute = script.getAttribute;
+						script.getAttribute = function(attr){ if(/^src$/i.test(attr))attr='_oldsrc';return script._oldGetAttribute(attr) };
+					}
+				}
+			}
+			return scripts;
+		}
+		return document._oldgetElementsByTagName_(tag);
+	};
+	document._oldwrite_ = document.write;
+	document.write = function(text){
+		text = text.replace(/<[!][-][-](.|\s){5,}?[-][-]>/g, "<!--?-->" // shorten long comments that may contain script tags
+			).replace(/(<script\s[^>]*)\bsrc\s*=\s*([^>]*>)/ig,
+		function(s,pre,post){
+			if(s.search(/\sdefer\b/i) > 0){ return s; }
+			var file = post.substr(0, post.search(/\s|>/)).replace(/['"]/g, "");
+			var scriptText = readFile(baseHref+file);
+			if(!scriptText){
+				scriptText = readFile(file);
+				if(!scriptText){ return s; }
+			}
+			return pre + "  _oldsrc=" + post + "eval(unescape('"+escape(scriptText)+"'))";
+		});
+		document._oldwrite_(text);
+	};
+}
+return text;
+}());
diff --git a/dijit/tests/_testCommon.js b/dijit/tests/_testCommon.js
new file mode 100644
index 0000000..e7cf772
--- /dev/null
+++ b/dijit/tests/_testCommon.js
@@ -0,0 +1,101 @@
+/*
+	_testCommon.js - a simple module to be included in dijit test pages to allow
+	for easy switching between the many many points of the test-matrix.
+
+	in your test browser, provides a way to switch between available themes,
+	and optionally enable RTL (right to left) mode, and/or dijit_a11y (high-
+	constrast/image off emulation) ... probably not a genuine test for a11y.
+
+	usage: on any dijit test_* page, press ctrl-f9 to popup links.
+
+	there are currently (3 themes * 4 tests) * (10 variations of supported browsers)
+	not including testing individual locale-strings
+
+	you should NOT be using this in a production environment. include
+	your css and set your classes manually. for test purposes only ...
+*/
+
+(function(){
+	var d = dojo,
+		theme = false,
+		testMode = null,
+		defTheme = "claro";
+
+	if(window.location.href.indexOf("?") > -1){
+		var str = window.location.href.substr(window.location.href.indexOf("?")+1).split(/#/);
+		var ary  = str[0].split(/&/);
+		for(var i=0; i<ary.length; i++){
+			var split = ary[i].split("="),
+				key = split[0],
+				value = split[1].replace(/[^\w]/g, "");	// replace() to prevent XSS attack
+			switch(key){
+				case "locale":
+					// locale string | null
+					dojo.locale = dojo.config.locale = locale = value;
+					break;
+				case "dir":
+					// rtl | null
+					document.getElementsByTagName("html")[0].dir = value;
+					break;
+				case "theme":
+					// tundra | soria | nihilo | claro | null
+					theme = value;
+					break;
+				case "a11y":
+					if(value){ testMode = "dijit_a11y"; }
+			}
+		}
+	}
+
+	// If URL specifies a non-claro theme then pull in those theme CSS files and modify
+	// <body> to point to that new theme instead of claro.
+	//
+	// Also defer parsing and any dojo.addOnLoad() calls that the test file makes
+	// until the CSS has finished loading.
+	if(theme || testMode){
+
+		if(theme){
+			var themeCss = d.moduleUrl("dijit.themes",theme+"/"+theme+".css");
+			var themeCssRtl = d.moduleUrl("dijit.themes",theme+"/"+theme+"_rtl.css");
+			document.write('<link rel="stylesheet" type="text/css" href="'+themeCss+'">');
+			document.write('<link rel="stylesheet" type="text/css" href="'+themeCssRtl+'">');
+		}
+
+		if(dojo.config.parseOnLoad){
+			dojo.config.parseOnLoad = false;
+			dojo.config._deferParsing = true;
+			
+			// Capture any dojo.addOnLoad() calls the test makes and defer them until after
+			// the new CSS loads.   (TODO: would be more straightforward to just make a
+			// testAddOnLoad() function and call that from the test files)
+			var originalOnLoad = dojo.addOnLoad,
+				loadFuncs = [];
+			dojo.addOnLoad = function(f){ loadFuncs.push(f); };
+		}
+
+		(originalOnLoad || dojo.addOnLoad)(function(){
+			// Reset <body> to point to the specified theme
+			var b = dojo.body();
+			if(theme){
+					dojo.removeClass(b, defTheme);
+					if(!d.hasClass(b, theme)){ d.addClass(b, theme); }
+					var n = d.byId("themeStyles");
+					if(n){ d.destroy(n); }
+			}
+			if(testMode){ d.addClass(b, testMode); }
+
+			// Defer parsing and addOnLoad() execution until the specified CSS loads.
+			if(dojo.config._deferParsing){
+				setTimeout(function(){
+					dojo.addOnLoad = originalOnLoad;
+					dojo.parser.parse(b);
+					for(var i=0; i<loadFuncs.length; i++){
+						loadFuncs[i]();
+					}
+				}, 320);
+			}
+
+		});
+	}
+
+})();
diff --git a/dijit/tests/_testMatrix.php b/dijit/tests/_testMatrix.php
new file mode 100644
index 0000000..dfd7507
--- /dev/null
+++ b/dijit/tests/_testMatrix.php
@@ -0,0 +1,75 @@
+<?php // IF you don't have PHP5 installed, you can't use this index! ?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo Toolkit - Every Dijit Test + Theme</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+	</style>
+
+</head>
+<body>
+
+	<h1 class="testTitle">Dijit Test Matrix Table</h1>
+
+	<table id="testMatrix">
+		<thead>
+			<tr class="top"><th rowspan="2">Test</th><th colspan="4">Tundra</th><th colspan="4">Nihilo</th><th colspan="4">Soria</th></tr>
+			<tr class="tests"><th>Normal</th><th>a11y</th><th>rtl</th><th>a11y + rtl<th>Normal</th><th>a11y</th><th>rtl</th><th>a11y + rtl<th>Normal</th><th>a11y</th><th>rtl</th><th>a11y + rtl</tr>
+		</thead>
+		<tbody><?php
+
+			printLinks(".", "Base Dijit Tests");
+			printLinks("./form", "Dijit Form Widget Tests");
+			printLinks("./layout", "Dijit Layout Widget Tests");
+			printLinks("./tree","Dijit Tree Tests");
+
+		?>
+		</tbody>
+	</table>
+
+</body>
+</html>
+<?php
+
+function printLinks($path, $group){
+	$handle = opendir($path);
+	$i = 0;
+	print "<tr class='spacer'><td colspan='13'>".$group."</td></tr>";
+	while(false !== ($file = readdir($handle))){
+		if(preg_match("/(test_|demo_)(.*)\.html/", $file, $matches)){
+			$base = $matches[0];
+			$link = $path."/".$matches[0];
+			print
+			"<tr class='testRow ". (++$i % 2 ==0 ? "alt" : "")   ."'>" .
+
+				"<td class='label'>" . $base . "</td>" .
+
+			    // standard / tundra:
+				"<td><a href='".$link."'>run</a></td>" .
+				"<td><a href='".$link."?a11y=true'>run</a></td>" .
+				"<td><a href='".$link."?dir=rtl'>run</a></td>" .
+				"<td><a href='".$link."?dir=rtl&a11y=true'>run</a></td>" .
+
+				// nihilo
+				"<td><a href='".$link."?theme=nihilo'>run</a></td>" .
+				"<td><a href='".$link."?theme=nihilo&a11y=true'>run</a></td>" .
+				"<td><a href='".$link."?theme=nihilo&dir=rtl'>run</a></td>" .
+				"<td><a href='".$link."?theme=nihilo&dir=rtl&a11y=true'>run</a></td>" .
+
+				// soria
+				"<td><a href='".$link."?theme=soria'>run</a></td>" .
+				"<td><a href='".$link."?theme=soria&a11y=true'>run</a></td>" .
+				"<td><a href='".$link."?theme=soria&dir=rtl'>run</a></td>" .
+				"<td><a href='".$link."?theme=soria&dir=rtl&a11y=true'>run</a></td>" .
+
+			 "</tr>";
+		}
+	}
+}
+
+
+?>
diff --git a/dijit/tests/bidi.html b/dijit/tests/bidi.html
new file mode 100755
index 0000000..0f78cee
--- /dev/null
+++ b/dijit/tests/bidi.html
@@ -0,0 +1,188 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Multi-directional document test</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, extraLocale: ['en','ar','he'], isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dojo.data.ItemFileReadStore");
+
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+
+		dojo.require("dijit.Menu");
+		dojo.require("dijit.MenuItem");
+		dojo.require("dijit.PopupMenuItem");
+
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.DropDownButton");
+		dojo.require("dijit.form.ComboButton");
+		dojo.require("dijit.form.ToggleButton");
+
+		dojo.require("dijit.ColorPalette");
+		dojo.require("dijit.Toolbar");
+		dojo.require("dijit.TooltipDialog");
+
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.DateTextBox");
+		dojo.require("dijit.form.NumberSpinner");
+		dojo.require("dijit.form.ComboBox");
+
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.ContentPane");
+
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Multi-directional document test</h1>
+
+	<div dojoType="dojo.data.ItemFileReadStore" jsId="continentStore"
+		url="_data/countries.json"></div>
+	<div dojoType="dijit.tree.ForestStoreModel" jsId="continentModel"
+		store="continentStore" query="{type:'continent'}"
+		rootId="continentRoot" rootLabel="Continents" childrenAttrs="children"></div>
+
+	<div id="right" dir="rtl" lang="ar-eg" style="float: right; width: 500px;">
+		<h2>RTL</h2>
+
+		<div dojoType="dijit.Toolbar"
+				><div dojoType="dijit.form.Button" iconClass="dijitEditorIcon dijitEditorIconCut" showLabel="false">Cut</div
+				><div dojoType="dijit.form.DropDownButton" iconClass="plusIcon" showLabel="true">
+					<span>שיח</span>
+					<div dojoType="dijit.TooltipDialog" title="Enter Login information">
+						<table>
+							<tr>
+								<td><label for="user">שם:</label></td>
+								<td><input dojoType=dijit.form.TextBox></td>
+							</tr>
+							<tr>
+								<td><label for="pwd">תאריך:</label></td>
+								<td><input dojoType=dijit.form.DateTextBox></td>
+							</tr>
+							<tr>
+								<td><label for="pwd">גיל:</label></td>
+								<td><input dojoType=dijit.form.NumberSpinner></td>
+							</tr>
+							<tr>
+								<td colspan="2" align="center">
+									<button dojoType=dijit.form.Button type="submit" name="submit">כניסה</button></td>
+							</tr>
+						</table>
+					</div
+				></div
+				><div dojoType="dijit.form.DropDownButton" iconClass="dijitEditorIcon dijitEditorIconBackColor" showLabel="true">
+					<span>لوحة الألوان</span>
+					<div dojoType="dijit.ColorPalette" style="display: none" palette="7x10" onChange="console.log(this.value);"></div>
+				</div
+				><div dojoType="dijit.form.ComboButton" optionsTitle='save options' iconClass="plusIcon" showLabel="true">
+					<span>القائمة</span>
+					<div dojoType="dijit.Menu" style="display: none;">
+						<div dojoType="dijit.MenuItem"  iconClass="dijitEditorIcon dijitEditorIconSave">حفظ</div>
+						<div dojoType="dijit.MenuItem">حفظ ك</div>
+						<div dojoType="dijit.PopupMenuItem">
+							<span>فرعية</span>
+							<div dojoType="dijit.Menu">
+								<div dojoType="dijit.MenuItem">Submenu Item One</div>
+								<div dojoType="dijit.MenuItem">Submenu Item Two</div>
+								<div dojoType="dijit.PopupMenuItem">
+									<span>Deeper Submenu</span>
+									<div dojoType="dijit.Menu">
+										<div dojoType="dijit.MenuItem">Sub-sub-menu Item One</div>
+										<div dojoType="dijit.MenuItem">Sub-sub-menu Item Two</div>
+									</div>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div
+		></div>
+		<div dojoType="dijit.layout.TabContainer" style="width: 450px; height: 300px; margin-top: 1em;">
+			<div dojoType="dijit.layout.ContentPane" title="رابط" closable="true" href="layout/doc0.html"></div>
+			<div dojoType="dijit.Tree" model="continentModel" openOnClick="true" title="עץ" closable="true"></div>
+		</div>
+	</div>
+
+	<div id="left" dir="ltr" lang="en-us" style="width: 500px; float: left;">
+		<h2>LTR</h2>
+
+		<div dojoType="dijit.Toolbar"
+				><div dojoType="dijit.form.Button" iconClass="dijitEditorIcon dijitEditorIconCut" showLabel="false">Cut</div
+				><div dojoType="dijit.form.DropDownButton" iconClass="plusIcon" showLabel="true">
+					<span>TooltipDialog</span>
+					<div dojoType="dijit.TooltipDialog" title="Enter Login information">
+						<table>
+							<tr>
+								<td><label for="user">Name:</label></td>
+								<td><input dojoType=dijit.form.TextBox></td>
+							</tr>
+							<tr>
+								<td><label for="pwd">Date:</label></td>
+								<td><input dojoType=dijit.form.DateTextBox></td>
+							</tr>
+							<tr>
+								<td><label for="pwd">Age:</label></td>
+								<td><input dojoType=dijit.form.NumberSpinner></td>
+							</tr>
+							<tr>
+								<td colspan="2" align="center">
+									<button dojoType=dijit.form.Button type="submit" name="submit">Login</button></td>
+							</tr>
+						</table>
+					</div
+				></div
+				><div dojoType="dijit.form.DropDownButton" iconClass="dijitEditorIcon dijitEditorIconBackColor" showLabel="true">
+					<span>ColorPalette</span>
+					<div dojoType="dijit.ColorPalette" style="display: none" palette="7x10" onChange="console.log(this.value);"></div>
+				</div
+				><div dojoType="dijit.form.ComboButton" optionsTitle='save options' iconClass="plusIcon" showLabel="true">
+					<span>Menu</span>
+					<div dojoType="dijit.Menu" style="display: none;">
+						<div dojoType="dijit.MenuItem"  iconClass="dijitEditorIcon dijitEditorIconSave">Save</div>
+						<div dojoType="dijit.MenuItem">Save As</div>
+						<div dojoType="dijit.PopupMenuItem">
+							<span>Enabled Submenu</span>
+							<div dojoType="dijit.Menu">
+								<div dojoType="dijit.MenuItem">Submenu Item One</div>
+								<div dojoType="dijit.MenuItem">Submenu Item Two</div>
+								<div dojoType="dijit.PopupMenuItem">
+									<span>Deeper Submenu</span>
+									<div dojoType="dijit.Menu">
+										<div dojoType="dijit.MenuItem">Sub-sub-menu Item One</div>
+										<div dojoType="dijit.MenuItem">Sub-sub-menu Item Two</div>
+									</div>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div
+		></div>
+
+		<div dojoType="dijit.layout.TabContainer" style="width: 450px; height: 300px; margin-top: 1em;">
+			<div dojoType="dijit.layout.ContentPane" title="Href" closable="true" href="layout/doc0.html"></div>
+			<div dojoType="dijit.Tree" model="continentModel" openOnClick="true" title="Tree" closable="true"></div>
+		</div>
+
+	</div>
+
+</body>
+</html>
diff --git a/dijit/tests/css/dijitTests.css b/dijit/tests/css/dijitTests.css
new file mode 100644
index 0000000..33efb89
--- /dev/null
+++ b/dijit/tests/css/dijitTests.css
@@ -0,0 +1,116 @@
+/* Test file styles for Dijit widgets */
+
+body {
+	background:#fff url("../images/testsBodyBg.gif") repeat-x top left;
+	padding:2em 2em 2em 2em;
+}
+
+h1.testTitle {
+	font-size:2em;
+	margin:0 0 1em 0;
+}
+
+/* Icons used in the tests */
+
+.plusIcon, .plusBlockIcon {
+	background-image: url(../images/plus.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 18px;
+	height: 18px;
+}
+.plusBlockIcon {
+	display: block !important;
+}
+.noteIcon {
+	background-image: url(../images/note.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 18px;
+	height: 18px;
+}
+.flatScreenIcon {
+	background-image: url(../images/flatScreen.gif);
+	background-repeat: no-repeat;
+	width: 32px;
+	height: 32px;
+}
+.dijitTestNodeDialog {
+	position:absolute;
+	top:5px;
+	right:5px;
+	display:block;
+	width:200px;
+	visibility:hidden;
+	background-color:#fff !important;
+	color:#000 !important;
+	border:1px solid #000;
+	padding:5px;
+}
+.dijitTestNodeDialog table {
+	background-color:#fff !important;
+}
+.dijitTestNodeDialog td {
+	padding:3px;
+}
+.dijitTestNodeShowing {
+	visibility:visible;
+}
+
+body .customFolderOpenedIcon, body .customFolderClosedIcon {
+	background-image: url('../images/folderIcons.png'); /* mail icons sprite image */
+	background-repeat: no-repeat;
+	width: 18px;
+	height: 18px;
+    background-position: -44px;
+}
+
+.dj_ie6 .customFolderOpenedIcon, .dj_ie6 .customFolderClosedIcon {
+	background-image: url('../images/folderIcons.gif');
+}
+
+.customFolderClosedIcon {
+    background-position: -154px;
+}
+
+#testMatrix {
+	width:100%;
+	text-align:center;
+}
+#testMatrix tr > td {
+	text-align:left;
+}
+#testMatrix tr.top {
+	background:blue;
+	color:#fff;
+}
+#testMatrix tr.top th {
+	padding:6px;
+}
+#testMatrix tr.tests {
+	background:#666;
+	padding:3px;
+	padding-left:6px;
+	padding-right:6px;
+	color:#fff;
+}
+#testMatrix tr.tests th {
+	text-align:center;
+}
+#testMatrix tr.spacer {
+	background:#dedede;
+	color:#666;
+}
+#testMatrix tr.spacer td {
+	padding:6px;
+}
+#testMatrix tr.testRow td {
+	text-align:center;
+}
+#testMatrix tr.testRow td.label {
+	text-align:left;
+	padding-left:15px;
+}
+#testMatrix tr.alt {
+	background:#ededed;
+}
diff --git a/dijit/tests/editor/BackForwardState.html b/dijit/tests/editor/BackForwardState.html
new file mode 100644
index 0000000..5879497
--- /dev/null
+++ b/dijit/tests/editor/BackForwardState.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Back/Forward Button Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+
+<body class="claro">
+	<h1>Editor back/forward button value restore tests</h1>
+	<p>
+		Try typing something into the editors below, and then click the page refrsh link or the back then forward buttons.
+		The editor should not lose the value.
+	</p>
+	<p>Notes:</p>
+	<ol>
+		<li>Editor must have a "name" attribute for this to work (not sure why)
+		<li>If in XD mode must set dojo.config.allowXdRichTextSave or manually create the hidden
+			<textarea> node used to preserve the data.
+	</ol>
+	<p><a href="BackForwardStateHelper.html" id="away">Navigate to another page</a></p>
+
+	<div dojoType="dijit.Editor" id="editor0" name="editor0" name="editor0" height="100" plugins="[]">editor0 original contents</div>
+	<div dojoType="dijit.Editor" id="editor1" name="editor1" name="editor1" height="100" plugins="[]">editor1 original contents</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/BackForwardStateHelper.html b/dijit/tests/editor/BackForwardStateHelper.html
new file mode 100644
index 0000000..dcd034a
--- /dev/null
+++ b/dijit/tests/editor/BackForwardStateHelper.html
@@ -0,0 +1,11 @@
+<h1>Back/forward test helper page</h1>
+<p>
+	You've navigated to this page from <a href="BackForwardState.html">backForward.html</a>.
+	Press the "Go back" link below to return, or your browser's back button,
+	and check that the editors' values were restored to the test data you entered.
+</p>
+<p>
+	Note that pressing the link above will not work, since the browser doesn't consider it
+	as "returning" to the previous page.
+</p>
+<a href="javascript:history.go(-1)" id="back">Go Back</a>
\ No newline at end of file
diff --git a/dijit/tests/editor/EnterKeyHandling.html b/dijit/tests/editor/EnterKeyHandling.html
new file mode 100644
index 0000000..4049565
--- /dev/null
+++ b/dijit/tests/editor/EnterKeyHandling.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.ViewSource");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		// Make editor indent work for paragraphs in addition to lists
+		var oldQCE = dijit._editor.RichText.prototype.queryCommandEnabled;
+		dijit._editor.RichText.prototype.queryCommandEnabled = function(command){
+			return command == 'indent' || command == 'outdent' || oldQCE.call(this, command);
+		};
+	</script>
+</head>
+
+<body class="claro">
+	<h1>Test file for Editor EnterKeyHandling plugin</h1>
+
+	<h2>blockNodeforEnter='BR'</h2>
+	<div dojoType="dijit.Editor" id="br"
+			plugins="[{name:'dijit._editor.plugins.EnterKeyHandling', blockNodeForEnter:'BR'}, 'viewsource']"
+		><p>para 1<br>line 2</p>
+		<p>para 2<br>line 2</p>
+ 	</div>
+
+ 	<h2>blockNodeforEnter='DIV'</h2>
+	<div dojoType="dijit.Editor" id="div"
+			plugins="[{name:'dijit._editor.plugins.EnterKeyHandling', blockNodeForEnter:'DIV'}, 'viewsource']"
+		><p>para 1<br>line 2</p>
+		<p>para 2<br>line 2</p>
+ 	</div>
+
+ 	<h2>blockNodeforEnter='DIV' split test</h2>
+	<div dojoType="dijit.Editor" id="div2"
+			plugins="[{name:'dijit._editor.plugins.EnterKeyHandling', blockNodeForEnter:'DIV'}, 'viewsource']">
+		<div> </div>
+		<div id="lineOne">this is a line of text.  It <b id="boldLine0">is</b> intended to be split up by pressing enter.</div>
+		<div> </div>
+ 	</div>
+
+ 	<h2>blockNodeforEnter='DIV' split test style clone</h2>
+	<div dojoType="dijit.Editor" id="div3"
+			plugins="[{name:'dijit._editor.plugins.EnterKeyHandling', blockNodeForEnter:'DIV'}, 'viewsource']">
+		<div> </div>
+		<div id="lineOne">this is a line of text.  It <b id="boldLine1" style="font-size: 4em">is</b> intended to be split up by pressing enter.</div>
+		<div> </div>
+ 	</div>
+
+ 	<h2>blockNodeforEnter='P'</h2>
+	<div dojoType="dijit.Editor" id="p"
+			plugins="[{name:'dijit._editor.plugins.EnterKeyHandling', blockNodeForEnter:'P'}, 'viewsource']"
+		><p>para 1<br>line 2</p>
+		<p>para 2<br>line 2</p>
+ 	</div>
+ 	
+	<h2>blockNodeforEnter='P' split test</h2>
+	<div dojoType="dijit.Editor" id="p2"
+			plugins="[{name:'dijit._editor.plugins.EnterKeyHandling', blockNodeForEnter:'P'}, 'viewsource']">
+		<p> </p>
+		<p id="lineOne">this is a line of text.  It <b id="boldLine2">is</b> intended to be split up by pressing enter.</p>
+		<p> </p>
+ 	</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/_Editor.html b/dijit/tests/editor/_Editor.html
new file mode 100644
index 0000000..3a4299f
--- /dev/null
+++ b/dijit/tests/editor/_Editor.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+
+	<script type="text/javascript">
+		dojo.require("dojo.window");
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.AlwaysShowToolbar");
+		dojo.require("dijit._editor.plugins.FontChoice");  // 'fontName','fontSize','formatBlock'
+		dojo.require("dijit._editor.plugins.TextColor");
+		dojo.require("dijit._editor.plugins.LinkDialog");
+		if(!window.parent.dijit.robot){
+			dojo.require("dijit.robot"); // test kludge, we just want the robot's cool scrollIntoView for the bold text test below and not the applet
+		}else{
+			doh=window.parent.doh;
+		}
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+
+<body class="claro">
+<div>some content
+<div>more contentmargin:50px;border:50px solid red; padding:50px;
+<iframe src="test_Editor.html" id="iframe" style="width:100px; height:50px; overflow:hidden;">
+</iframe>
+<input type="button" dojoType="dijit.form.Button" onClick="var frame=dojo.byId('iframe');dojo.withGlobal(frame.contentWindow, function(){frame.contentWindow.dojo.window.scrollIntoView(frame.contentWindow.dijit.byId('editor1').toolbar.getChildren()[7].domNode);});alert('expected Bold, got: '+frame.contentWindow.dijit.byId('editor1').toolbar.getChildren()[7].titleNode.getAttribute('title'))">Scroll bold into view</input>
+<input type="button" dojoType="dijit.form.Button" onClick="var frame=dojo.byId('iframe');doh.robot.scrollIntoView(dojo.query(dojo.isIE?'strong':'b',frame.contentWindow.dijit.byId('editor1').document.body)[0]);">Scroll bold text into view</input>
+<input type="button" dojoType="dijit.form.Button" onClick="var frame=dojo.byId('iframe');dojo.withGlobal(frame.contentWindow, function(){frame.contentWindow.dojo.window.scrollIntoView(frame.contentWindow.dijit.byId('editor1').toolbar.getChildren()[8].domNode);});alert('expected Italic, got: '+frame.contentWindow.dijit.byId('editor1').toolbar.getChildren()[8].titleNode.getAttribute('title'))">Scroll italics into view</input>
+</div>
+</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/customIcon.gif b/dijit/tests/editor/customIcon.gif
new file mode 100755
index 0000000..5fd50d2
Binary files /dev/null and b/dijit/tests/editor/customIcon.gif differ
diff --git a/dijit/tests/editor/module.js b/dijit/tests/editor/module.js
new file mode 100755
index 0000000..40468f7
--- /dev/null
+++ b/dijit/tests/editor/module.js
@@ -0,0 +1,29 @@
+dojo.provide("dijit.tests.editor.module");
+
+try{
+	var userArgs = window.location.search.replace(/[\?&](dojoUrl|testUrl|testModule)=[^&]*/g,"").replace(/^&/,"?");
+
+	// Base editor functionality
+	doh.registerUrl("dijit.tests.editor.robot.Editor_mouse", dojo.moduleUrl("dijit","tests/editor/robot/Editor_mouse.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.editor.robot.Editor_a11y", dojo.moduleUrl("dijit","tests/editor/robot/Editor_a11y.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.editor.robot.Misc", dojo.moduleUrl("dijit","tests/editor/robot/Editor_misc.html"+userArgs), 99999999);
+
+	// Plugins
+	doh.registerUrl("dijit.tests.editor.robot.EnterKeyHandling", dojo.moduleUrl("dijit","tests/editor/robot/EnterKeyHandling.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.editor.robot.FullScreen", dojo.moduleUrl("dijit","tests/editor/robot/Editor_FullScreen.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.editor.robot.ViewSource", dojo.moduleUrl("dijit","tests/editor/robot/Editor_ViewSource.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.editor.robot.NewPage", dojo.moduleUrl("dijit","tests/editor/robot/Editor_NewPage.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.editor.robot.LinkDialog", dojo.moduleUrl("dijit","tests/editor/robot/Editor_LinkDialog.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.editor.robot.FontChoice", dojo.moduleUrl("dijit","tests/editor/robot/Editor_FontChoice.html"+userArgs), 99999999);
+	if(!dojo.isWebKit){
+		// The back button on webkit is URL for the browser itself, restarting the entire test suite,
+		// rather than just for the iframe holding the test file (BackForwardState.html and BackForwardStateHelper.html)
+		doh.registerUrl("dijit.tests.editor.robot.BackForwardState", dojo.moduleUrl("dijit","tests/editor/robot/BackForwardState.html"+userArgs), 99999999);
+	}
+
+}catch(e){
+	doh.debug(e);
+}
+
+
+
diff --git a/dijit/tests/editor/nls_8859-2.html b/dijit/tests/editor/nls_8859-2.html
new file mode 100644
index 0000000..da9996a
--- /dev/null
+++ b/dijit/tests/editor/nls_8859-2.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-2">
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dijit.Editor");
+		dojo.require("dojo.parser");
+	</script>
+</head>
+<body class="claro">
+<form method="post">
+<p>
+Plain text: �󱶳�����ӣ�������
+</p>
+
+<p>
+Same text should show up in the Editor:
+</p>
+<div name="field" id="editor" dojoType="dijit.Editor">
+�󱶳�����ӣ�������
+</div>
+<input type="submit" value="Save" />
+<button type=button onclick="console.log(dijit.byId('editor').attr('value'))">getValue</button>
+<button type=button onclick="dijit.byId('editor').attr('value', '\u65e5\u672c\u8a9e')">set value to &#x65e5;&#x672c;&#x8a9e;</button>
+
+</form>
+</body>
+</html>
diff --git a/dijit/tests/editor/nls_sjis.html b/dijit/tests/editor/nls_sjis.html
new file mode 100644
index 0000000..f0e291a
--- /dev/null
+++ b/dijit/tests/editor/nls_sjis.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=Shift-JIS">
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dijit.Editor");
+		dojo.require("dojo.parser");
+	</script>
+</head>
+<body class="claro">
+<form method="get">
+<p>
+Plain text: ��{��
+</p>
+
+<p>
+Same text should show up in the Editor:
+</p>
+<div name="field" id="editor" dojoType="dijit.Editor">
+  ��{��
+</div>
+<input type="submit" value="Save" />
+<button type=button onclick="console.log(dijit.byId('editor').attr('value'))">getValue</button>
+<button type=button onclick="dijit.byId('editor').attr('value', '����ɂ���')">set value to ����ɂ���</button>
+
+</form>
+</body>
+</html>
diff --git a/dijit/tests/editor/nls_utf8.html b/dijit/tests/editor/nls_utf8.html
new file mode 100644
index 0000000..1dff50f
--- /dev/null
+++ b/dijit/tests/editor/nls_utf8.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dijit.Editor");
+		dojo.require("dojo.parser");
+	</script>
+</head>
+<body class="claro">
+<form method="get">
+<p>
+Plain text: 日本語
+</p>
+
+<p>
+Same text should show up in the Editor:
+</p>
+<div name="field" id="editor" name="text" dojoType="dijit.Editor">
+  日本語
+</div>
+<input type="submit" value="Save" />
+<button type=button onclick="console.log(dijit.byId('editor').attr('value'))">getValue</button>
+<button type=button onclick="dijit.byId('editor').attr('value', 'こんにちは')">set value to こんにちは</button>
+
+</form>
+</body>
+</html>
diff --git a/dijit/tests/editor/robot/BackForwardState.html b/dijit/tests/editor/robot/BackForwardState.html
new file mode 100644
index 0000000..67334e3
--- /dev/null
+++ b/dijit/tests/editor/robot/BackForwardState.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Editor/Back Button Restore Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			// This page tests that the editor's value won't be lost if the user
+			// accidentlly navigates to a different page, and then returns to the
+			// page w/the editor by pressing the back button.
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../BackForwardState.html');
+
+				doh.register("back button restore", [
+					{
+						name: "set editor value",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var editor0 = dijit.byId("editor0"),
+								editor1 = dijit.byId("editor1");
+
+							doh.is("editor0 original contents", editor0.get('value'));
+							doh.is("editor1 original contents", editor1.get('value'));
+
+							editor0.set('value', 'hello');
+							editor1.set('value', 'goodbye');
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("hello", editor0.get('value'));
+								doh.is("goodbye", editor1.get('value'));
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "navigate away",
+						timeout: 10000,
+						runTest: function(){
+							return doh.robot.waitForPageToLoad(function(){
+								// On most browsers just focusing causes navigation.  On safari
+								// need to click...
+								var away = dojo.byId("away");
+								dojo.byId("away").focus();
+								doh.robot.keyPress(dojo.keys.ENTER, 500);
+							});
+						}
+					},
+					{
+						name: "confirm navigation to new page worked",
+						runTest: function(){
+							// Confirm that we successfully navigated away
+							doh.is("Back/forward test helper page", (dojo.query("h1")[0]||{}).innerHTML);
+						}
+					},
+
+					{
+						name: "go back to original page",
+						timeout: 10000,
+						runTest: function(){
+							return doh.robot.waitForPageToLoad(function(){
+								// On most browsers just focusing causes navigation.  On safari
+								// need to click...
+								var back = dojo.byId("back");
+								back.focus();
+								doh.robot.keyPress(dojo.keys.ENTER, 500);
+							});
+						}
+					},
+
+					{
+						name: "check that editor values restored",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var editor0 = dijit.byId("editor0"),
+									editor1 = dijit.byId("editor1");
+
+								doh.t(editor0, "editor0 found");
+								doh.is("hello", editor0.get('value'));
+
+								doh.t(editor1, "editor1 found");
+								doh.is("goodbye", editor1.get('value'));
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
\ No newline at end of file
diff --git a/dijit/tests/editor/robot/Editor_FontChoice.html b/dijit/tests/editor/robot/Editor_FontChoice.html
new file mode 100755
index 0000000..ca81c5c
--- /dev/null
+++ b/dijit/tests/editor/robot/Editor_FontChoice.html
@@ -0,0 +1,616 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Editor FontChoice Plugin Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_FontChoice.html');
+
+				var editor;		// points to one of the editors (editor0, editor1, etc.)
+				var fcPlugin;	// formatBlock, fontSize, or fontName plugin
+				var value;		// HTML value of editor
+
+				function getPlugin(/*String*/ command){
+					var editor = dijit.byId("editor0");
+					var edPlugins = editor._plugins, i;
+					for(i = 0; i < edPlugins.length; i++){
+						var p = edPlugins[i];
+						if (p.declaredClass === "dijit._editor.plugins.FontChoice" && p.command == command) {
+							return p;
+						}
+					}
+					doh.f(true, "didn't find plugin " + command);
+				}
+				// Verify that the formatBlock, fontSize, and fontName
+				// plugins correctly display the format / font-size / font-name of the selected text.
+				doh.register("FontChoice: verify current format/font-size/font-name",
+					dojo.map(
+						[
+							{id: "para0", format: "p"},
+							{id: "pre0", format: "pre"},
+							{id: "h10", format: "h1"},
+							{id: "h20", format: "h2"},
+							{id: "h30", format: "h3"},
+							{id: "sizedText1", size: "1"},
+							{id: "sizedText4", size: "4"},
+							{id: "sizedText7", size: "7"},
+							{id: "comicText", name: "Comic Sans MS"}
+						],
+						function(params){
+							return {
+								name: [
+										"Verify",
+										params.format ? "format " + params.format.toUpperCase() : "",
+										params.size ? "font size " + params.size : "",
+										params.name ? "font name " + params.name : "",
+										"Identified"
+									].join(" ").replace(/ +/g, " "),
+								timeout: 20000,
+								setUp: function(){
+									editor = dijit.byId("editor0");
+									value = editor.get("value");
+								},
+								runTest: function(){
+									var d = new doh.Deferred();
+		
+									try{
+										// Focus on the editor window
+										dojo.window.scrollIntoView(editor.domNode);
+										editor.focus();
+										doh.robot.mouseMoveAt(editor.iframe, 1000);
+										doh.robot.mouseClick({left:true}, 1000);
+		
+										doh.robot.sequence(function() {
+											// Find node w/specified id
+											var node = dojo.withGlobal(editor.window, function() { return dojo.byId(params.id); });
+											doh.is(params.id, node && node.id, "found " + params.id);
+
+											// Select the text, collapse to the start of it
+											// Using "dojo.global.dojo" to access the inner dojo, in test_FontChoice.html
+											// (not the one in this file), since that's the one that dijit is referencing.
+											dojo.global.dojo.withGlobal(editor.window, function() {
+												dijit._editor.selection.selectElementChildren(node);
+												dijit._editor.selection.collapse(true);
+											});
+										},1000);
+						                doh.robot.sequence(function(){
+											// Make sure states update.
+											editor.onDisplayChanged();
+										}, 1000);
+										doh.robot.sequence(d.getTestCallback(function(){
+											if(params.format){
+												doh.assertEqual(params.format, getPlugin("formatBlock").button.get("value"), "format " + params.format + " identified.");
+											}
+											if(params.size){
+												doh.assertEqual(params.size, getPlugin("fontSize").button.get("value"), "font size " + params.size + " identified.");
+											}
+											if(params.name){
+												doh.assertEqual(params.name, getPlugin("fontName").button.get("value"), "font name" + params.name + " identified.");
+											}
+										}), 2000);
+									}catch(e){
+										d.errback(e);
+									}
+									return d;
+								},
+								tearDown: function(){
+									if(editor){editor.set("value", value);}
+								}
+							};	// end of return { ...
+						}	// end of function()
+					)	// end of dojo.map()
+				);	// end of dojo.register()
+
+				// Test changing format/font-size/font-name (ex: changing an <h1> to an <h2>)
+				doh.register("FontChoice: change format/font-size/font",
+					dojo.map(
+						[
+							{id: "text", type: "formatBlock", from: "p", to: "pre"},
+							{id: "text", type: "formatBlock", from: "pre", to: "h1"},
+							{id: "text", type: "formatBlock", from: "h1", to: "h2"},
+							{id: "text", type: "formatBlock", from: "h2", to: "h3"},
+							{id: "sizedText7", type: "fontSize", from: "7", to: "3"},
+							{id: "comicText", type: "fontName", from: "Comic Sans MS", to: "Times New Roman"}
+						],
+						function(params){
+							return {
+								name: "formatBlock: Verify can change " + params.type + " " +
+									params.from.toUpperCase() + " to " + params.to.toUpperCase(),
+								timeout: 20000,
+								setUp: function(){
+									fcPlugin = getPlugin(params.type);
+									value = editor.get("value");
+								},
+								runTest: function(){
+									var d = new doh.Deferred();
+									try{
+										// Focus on the editor window
+										dojo.window.scrollIntoView(editor.domNode);
+										editor.focus();
+										doh.robot.mouseMoveAt(editor.iframe, 1000);
+										doh.robot.mouseClick({left:true}, 1000);
+		
+										doh.robot.sequence(d.getTestErrback(function(){
+											// Find node
+											var p = dojo.withGlobal(editor.window, function() { return dojo.byId(params.id); });
+											doh.is(params.id, p && p.id, "found node");
+		
+											dojo.global.dojo.withGlobal(editor.window, function() {
+												// Select the text, collapse to the start of it
+												dijit._editor.selection.selectElementChildren(p);
+												dijit._editor.selection.collapse(true);
+												
+												// Set the format / font-size / font-name plugin to the new value
+												// TODO: use mouse/keyboard to set the value
+												fcPlugin.button.set("value", params.to);
+											});
+										}),1000);
+						                doh.robot.sequence(function(){
+											// Make sure states update.
+											editor.onDisplayChanged();
+										}, 1000);
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.assertEqual(params.to, fcPlugin.button.get("value"), "verify converted");
+
+											// TODO: check that it actually changed the format / font-size / font-name (in the editor contents)
+										}), 2000);
+									}catch(e){
+										d.errback(e);
+									}
+									return d;
+								},
+								tearDown: function(){
+									if(editor){editor.set("value", value);}
+								}
+							};	// end of return { ...
+						}	// end of function()
+					)	// end of dojo.map()
+				);	// end of dojo.register()
+
+				doh.register("formatBlock: multiple changes",
+					{
+						name: "formatBlock: Verify changing multiple nodes to h3",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor0");
+							fcPlugin = getPlugin("formatBlock");
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 1000);
+								doh.robot.mouseClick({left:true}, 1000);
+
+								// Verify the formatBlock plugin was found
+								doh.assertTrue(fcPlugin !== null, "formatBlock was found");
+
+								doh.robot.sequence(d.getTestErrback(function(){
+									var p = dojo.withGlobal(editor.window, function() { return dojo.byId("text"); });
+									doh.is("text", p && p.id, "found text");
+
+									dojo.global.dojo.withGlobal(editor.window, function() {
+										// Select the text, collapse to the start of it
+										dijit._editor.selection.selectElementChildren(p);
+										dijit._editor.selection.collapse(true);
+
+										// Set the format / font-size / font-name plugin to the new value
+										// TODO: use mouse/keyboard to set the value
+										fcPlugin.button.set("value", "h3");
+									});
+								}),1000);
+								doh.robot.sequence(function(){
+									// Make sure states update.
+									editor.onDisplayChanged();
+								}, 1000);
+								doh.robot.sequence(function(){
+									doh.assertEqual("h3", fcPlugin.button.get("value"), "Verify first P converted to H3.");
+									// TODO: check that it actually changed the format (in the editor contents)
+								}, 2000);
+
+								// Move to the next block and try to change it to h3 too.
+								doh.robot.sequence(d.getTestErrback(function(){
+									var p = dojo.withGlobal(editor.window, function() { return dojo.byId("text1"); });
+									doh.is("text1", p && p.id, "found text1");
+
+									dojo.global.dojo.withGlobal(editor.window, function() {
+										// Select the text, collapse to the start of it
+										dijit._editor.selection.selectElementChildren(p);
+										dijit._editor.selection.collapse(true);
+
+										// Set the format / font-size / font-name plugin to the new value
+										// TODO: use mouse/keyboard to set the value
+										fcPlugin.button.set("value", "h3");
+									});
+								}),1000);
+								doh.robot.sequence(function(){
+									// Make sure states update.
+									editor.onDisplayChanged();
+								}, 1000);
+								doh.robot.sequence(function(){
+									// state should have updated, so, now set value.
+									// TODO: use mouse/keyboard to set the value
+									fcPlugin.button.set("value", "h3");
+								},1000);
+								doh.robot.sequence(function(){
+									// Make sure states update.
+									editor.onDisplayChanged();
+								}, 1000);
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.assertEqual("h3", fcPlugin.button.get("value"), "Verify second P converted to H3.");
+									// TODO: check that it actually changed the format (in the editor contents)
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					}
+				);
+
+				doh.register("FontChoice: Format Removal Tests", [
+					{
+						name: "formatBlock: Verify single level format is removed (inside format block).",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor0");
+							fcPlugin = getPlugin("formatBlock");
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 1000);
+								doh.robot.mouseClick({left:true}, 1000);
+
+								// Verify the formatBlock plugin was found
+								doh.assertTrue(fcPlugin !== null, "formatBlock was found");
+
+								doh.robot.sequence(d.getTestErrback(function(){
+									var p = dojo.withGlobal(editor.window, function() { return dojo.byId("text"); });
+									doh.is("text", p && p.id, "found text");
+									dojo.global.dojo.withGlobal(editor.window, function() {
+										// Select the text, collapse to the start of it
+										dijit._editor.selection.selectElementChildren(p);
+										dijit._editor.selection.collapse(true);
+									});
+								}),1000);
+								doh.robot.sequence(function(){
+									// Make sure states update.
+									editor.onDisplayChanged();
+								}, 1000);
+								doh.robot.sequence(function(){
+									fcPlugin.button.set("value", "noFormat");
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Make sure states update.
+									// If change occurred, then the value should 
+									// still be noFormat.
+									editor.onDisplayChanged();
+								}, 1000);
+								doh.robot.sequence(d.getTestCallback(function(){
+                                    doh.assertEqual("noFormat", fcPlugin.button.get("value"), 
+										"Validating current cursor point format is noFormat");
+								}), 1000);
+							 }catch(e){
+								 d.errback(e);
+							 }
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "formatBlock: Verify multiple format removal via selection",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor0");
+							fcPlugin = getPlugin("formatBlock");
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 1000);
+								doh.robot.mouseClick({left:true}, 1000);
+
+								// Verify the formatBlock plugin was found
+								doh.assertTrue(fcPlugin !== null, "formatBlock was found");
+
+								doh.robot.sequence(d.getTestErrback(function(){
+									var p = dojo.withGlobal(editor.window, function() { return dojo.byId("text"); });
+									doh.is("text", p && p.id, "found text");
+									dojo.global.dojo.withGlobal(editor.window, function() {
+										// Select the text, collapse to the start of it
+										dijit._editor.selection.selectElementChildren(p);
+										dijit._editor.selection.collapse(true);
+									});
+								}),1000);
+								doh.robot.sequence(function(){
+									// Make sure states update.
+									editor.onDisplayChanged();
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Select the children of the block and try to flatten the formatting.
+
+									var selection = dojo.withDoc(editor.document, function() { return dojo.byId("selectionContainer"); });
+									dojo.global.dojo.withGlobal(editor.window, function() {
+										dojo.window.scrollIntoView(selection);
+										dijit._editor.selection.selectElementChildren(selection);
+									});
+									fcPlugin.button.set("value", "noFormat");
+								}, 1000);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check that the elements are all gone.
+									var selection = dojo.withDoc(editor.document, function() { return dojo.byId("selectionContainer"); });
+									doh.assertTrue(selection.childNodes.length > 0, "Checking that there are still child nodes.");
+
+									var i;
+									var nodes = selection.childNodes;
+									for(i = 0; i < nodes.length; i++){
+										var n = nodes[i];
+										if(n.nodeType == 1){
+											var tag = n.nodeName? n.nodeName.toLowerCase() : "";
+											doh.assertTrue(tag != "p");
+											doh.assertTrue(tag != "h3");
+											doh.assertTrue(tag != "pre");
+										}
+									}
+								}), 1000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					}
+				]);
+
+				doh.register("FontChoice: miscellaneous tests", [
+					{
+						name: "FontChoice: Plain Text labels",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor1");
+							fcPlugin = [];
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FontChoice"){
+									fcPlugin.push(p);
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							// summary:
+							//		This test goes through all the registered FontChoice plugins
+							//		and verifies that they're all using plain text labels in the dropdown.
+							var d = new doh.Deferred();
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 1000);
+								doh.robot.mouseClick({left:true}, 1000);
+								doh.robot.sequence(function(){
+									var i, passed = true, processed = 0;
+									for(i = 0; i < fcPlugin.length; i++){
+										var p = fcPlugin[i];
+										var store = p.button.select.store;
+										var onComplete = function(items){
+											try{
+												var j;
+												processed++;
+												for(j = 0; j < items.length; j++){
+													var item = items[j];
+													if(store.getValue(item, "name").indexOf("<") === 0){
+														console.log("failed on: " + store.getValue(item, "name"));
+														passed = false;
+													}
+												}
+												if(processed === fcPlugin.length){
+													if(passed){
+														d.callback(true);
+													}else{
+														d.errback(new Error("Non-plain text label!"));
+													}
+												}
+											}catch(e){
+												d.errback(e);
+											}
+										};
+										var onError = function(err){
+											d.errback(err);
+										}
+										store.fetch({query: {name: "*"}, onComplete: onComplete, onError: onError});
+									}
+								}, 1000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "FontChoice: Validate usage of generic names",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("generic");
+							fcPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FontChoice" && p.command === "fontName" && p.generic){
+									fcPlugin = p;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							// summary:
+							//		This test goes through the font choice plugin registered as generic font names and validates
+							//		the font names in the values are the generic map.
+							var d = new doh.Deferred();
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 1000);
+								doh.robot.mouseClick({left:true}, 1000);
+								doh.robot.sequence(function(){
+									var i, passed = true;
+									var map = {
+										"sans-serif": false,
+										"serif": false,
+										"cursive": false,
+										"monospace": false,
+										"fantasy": false
+									}
+									var store = fcPlugin.button.select.store;
+									var onComplete = function(items){
+										try{
+											var j;
+											for(j = 0; j < items.length; j++){
+												var item = items[j];
+												map[store.getValue(item, "value")] = true;
+											}
+											for(j in map){
+												if(!map[j]){
+													passed = false;
+													break;
+												}
+											}
+											if(passed){
+												d.callback(true);
+											}else{
+												d.errback(new Error("Did not find all the generic names in the store."));
+											}
+										}catch(e){
+											d.errback(e);
+										}
+									};
+									var onError = function(err){
+										d.errback(err);
+									}
+									store.fetch({query: {value: "*"}, onComplete: onComplete, onError: onError});
+								}, 1000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "FontChoice: Validate custom font names",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("custom");
+							fcPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FontChoice" && p.command === "fontName" && p.custom){
+									fcPlugin = p;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							// summary:
+							//		This test goes through the font choice plugin registered as custom font names and validates
+							//		the font names in the values are the provided names.
+							var d = new doh.Deferred();
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 1000);
+								doh.robot.mouseClick({left:true}, 1000);
+								doh.robot.sequence(function(){
+									var i, passed = true;
+									var map = {
+										"Verdana": false,
+										"Myriad": false,
+										"Garamond": false
+									}
+									var store = fcPlugin.button.select.store;
+									var onComplete = function(items){
+										try{
+											var j;
+											for(j = 0; j < items.length; j++){
+												var item = items[j];
+												map[store.getValue(item, "value")] = true;
+											}
+											for(j in map){
+												if(!map[j]){
+													passed = false;
+													break;
+												}
+											}
+											if(passed){
+												d.callback(true);
+											}else{
+												d.errback(new Error("Did not find all the generic names in the store."));
+											}
+										}catch(e){
+											d.errback(e);
+										}
+									};
+									var onError = function(err){
+										d.errback(err);
+									}
+									store.fetch({query: {value: "*"}, onComplete: onComplete, onError: onError});
+								}, 1000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					}
+				]);
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/editor/robot/Editor_FullScreen.html b/dijit/tests/editor/robot/Editor_FullScreen.html
new file mode 100644
index 0000000..c3cfcbd
--- /dev/null
+++ b/dijit/tests/editor/robot/Editor_FullScreen.html
@@ -0,0 +1,800 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Editor FullScreen Plugin Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_FullScreen.html');
+
+				var editor0;
+				var fsPlugin;
+
+				doh.register("FullScreen_tests", [
+					{
+						name: "Keyboard: Go to Fullscreen (CTRL-SHIFT-F11)",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor0.domNode);
+								editor0.focus();
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(fsPlugin != null);
+								doh.robot.keyPress(dojo.keys.F11, 500, {ctrl:true,shift:true});
+
+								doh.robot.sequence(d.getTestCallback(function(){
+									//Now check the state!
+									doh.assertTrue(fsPlugin.isFullscreen);
+									var vp = dojo.window.getBox();
+									var edPos = dojo.position(editor0.domNode);
+									doh.assertEqual("absolute", dojo.style(editor0.domNode, "position"));
+									doh.assertEqual("0", dojo.style(editor0.domNode, "top"), "Top position check");
+									doh.assertEqual("0", dojo.style(editor0.domNode, "left"), "Left position check");
+
+									//There may be a difference of a pixel or two, so check that the editor is real close
+									//to the viewport size.
+									doh.assertTrue(edPos.h >= vp.h && edPos.h < (vp.h + 5), "Height check");
+									doh.assertTrue(edPos.w >= vp.w && edPos.w < (vp.w + 5), "Width check");
+								}), 1000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						}
+					},
+					{
+						name: "Keyboard: Go to fullscreen and back",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor0.domNode);
+								editor0.focus();
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(fsPlugin != null);
+								doh.robot.keyPress(dojo.keys.F11, 500, {ctrl:true,shift:true});
+								doh.robot.keyPress(dojo.keys.F11, 1000, {ctrl:true,shift:true});
+
+								doh.robot.sequence(d.getTestCallback(function(){
+									//Now check the state!
+									doh.assertFalse(fsPlugin.isFullscreen);
+									var edPos = dojo.position(editor0.domNode);
+									doh.assertTrue( "absolute" !== dojo.style(editor0.domNode, "position"));
+
+									//There may be a difference of a pixel or two depending on how the browser sizes
+									//so check that the editor is real close to the expected size defined in the test doc.
+									doh.assertTrue(edPos.h >= 400 && (edPos.h < 405), "Restored height check.");
+									doh.assertTrue(edPos.w >= 800 && (edPos.w < 805), "Restored width check.");
+								}), 2000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						}
+					},
+					{
+						name: "Mouse Click: Go to Fullscreen",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor0.domNode);
+								editor0.focus();
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(fsPlugin != null);
+								doh.robot.mouseMoveAt(fsPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left: true}, 750);
+
+								doh.robot.sequence(d.getTestCallback(function(){
+									//Now check the state!
+									doh.assertTrue(fsPlugin.isFullscreen);
+									var vp = dojo.window.getBox();
+									var edPos = dojo.position(editor0.domNode);
+									doh.assertEqual("absolute", dojo.style(editor0.domNode, "position"));
+									doh.assertEqual("0", dojo.style(editor0.domNode, "top"), "Top position check");
+									doh.assertEqual("0", dojo.style(editor0.domNode, "left"), "Left position check");
+
+									//There may be a difference of a pixel or two, so check that the editor is real close
+									//to the viewport size.
+									doh.assertTrue(edPos.h >= vp.h && edPos.h < (vp.h + 5), "Height check");
+									doh.assertTrue(edPos.w >= vp.w && edPos.w < (vp.w + 5), "Width check");
+								}), 1000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						}
+					},
+					{
+						name: "Mouse Click: Go to fullscreen and back",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor0.domNode);
+								editor0.focus();
+								doh.assertTrue(fsPlugin != null);
+								//Click it, then click it again!
+								doh.robot.mouseMoveAt(fsPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left: true}, 750);
+								doh.robot.mouseMoveAt(fsPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left: true}, 750);
+
+								doh.robot.sequence(d.getTestCallback(function(){
+									//Now check the state!
+									doh.assertFalse(fsPlugin.isFullscreen);
+									var edPos = dojo.position(editor0.domNode);
+									doh.assertTrue( "absolute" !== dojo.style(editor0.domNode, "position"));
+
+									//There may be a difference of a pixel or two depending on how the browser sizes
+									//so check that the editor is real close to the expected size defined in the test doc.
+									doh.assertTrue(edPos.h >= 400 && (edPos.h < 405), "Restored height check.");
+									doh.assertTrue(edPos.w >= 800 && (edPos.w < 805), "Restored width check.");
+								}), 2000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						}
+					},
+					{
+						name: "BorderContainer:  Go Fullscreen, Reduce BorderContainer, Exit FullScreen, Validate Resize",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor1");
+							container = dijit.byId("bc");
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+
+								var origEditorSize = dojo.marginBox(editor.domNode);
+								var origContainerSize = dojo.marginBox(container.domNode);
+								os = {w: origContainerSize.w, h: origContainerSize.h}
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(fsPlugin != null);
+
+								doh.robot.sequence(function(){
+									// Engage FullScreen Mode
+									fsPlugin.button.set("checked", true);
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Resize the container
+									container.resize({w: 400, h: 400});
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Disengage FullScreen Mode
+									fsPlugin.button.set("checked", false);
+								}, 1000);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now validate the editor resized when it returned since
+									// the Container was resized.
+									var curEditorSize = dojo.marginBox(editor.domNode);
+									var curContainerSize = dojo.marginBox(container.domNode);
+									var containerWdiff = origContainerSize.w - curContainerSize.w;
+									var containerHdiff = origContainerSize.h - curContainerSize.h;
+									var eWdiff= origEditorSize.w - curEditorSize.w;
+									var eHdiff= origEditorSize.h - curEditorSize.h;
+									
+									doh.assertTrue(origEditorSize.w > curEditorSize.w, "Validating new width is less that the original size");
+									doh.assertTrue(origEditorSize.h > curEditorSize.h, "Validating new height is less that the original size");
+									doh.assertTrue((eWdiff < (containerWdiff + 5)) && (eWdiff > (containerWdiff - 5)), "Doing a rouch check that the editor width resized roughly to the Container difference");
+									doh.assertTrue((eHdiff < (containerHdiff + 5)) && (eHdiff > (containerHdiff - 5)), "Doing a rouch check that the editor height resized roughly to the Container difference");
+								}), 1000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+							 if(container && os){container.resize(os);}
+						}
+					},
+					{
+						name: "BorderContainer:  Go Fullscreen, Increase BorderContainer, Exit FullScreen, Validate Resize",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor1");
+							container = dijit.byId("bc");
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+
+								var origEditorSize = dojo.marginBox(editor.domNode);
+								var origContainerSize = dojo.marginBox(container.domNode);
+								os = {w: origContainerSize.w, h: origContainerSize.h}
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(fsPlugin != null);
+
+								doh.robot.sequence(function(){
+									// Engage FullScreen Mode
+									fsPlugin.button.set("checked", true);
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Resize the container
+									container.resize({w: 800, h: 800});
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Disengage FullScreen Mode
+									fsPlugin.button.set("checked", false);
+								}, 1000);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now validate the editor resized when it returned since
+									// the Container was resized.
+									var curEditorSize = dojo.marginBox(editor.domNode);
+									var curContainerSize = dojo.marginBox(container.domNode);
+									var containerWdiff = -(origContainerSize.w - curContainerSize.w);
+									var containerHdiff = -(origContainerSize.h - curContainerSize.h);
+									var eWdiff= -(origEditorSize.w - curEditorSize.w);
+									var eHdiff= -(origEditorSize.h - curEditorSize.h);
+									
+									doh.assertTrue(origEditorSize.w < curEditorSize.w, "Validating new width is less that the original size");
+									doh.assertTrue(origEditorSize.h < curEditorSize.h, "Validating new height is less that the original size");
+									doh.assertTrue((eWdiff < (containerWdiff + 5)) && (eWdiff > (containerWdiff - 5)), "Doing a rouch check that the editor width resized roughly to the Container difference");
+									doh.assertTrue((eHdiff < (containerHdiff + 5)) && (eHdiff > (containerHdiff - 5)), "Doing a rouch check that the editor height resized roughly to the Container difference");
+								}), 1000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+							 if(container && os){container.resize(os);}
+						}
+					},
+					{
+						name: "TabContainer:  Go Fullscreen, Reduce TabContainer, Exit FullScreen, Validate Resize",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor2");
+							container = dijit.byId("tc");
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+
+								var origEditorSize = dojo.marginBox(editor.domNode);
+								var origContainerSize = dojo.marginBox(container.domNode);
+								os = {w: origContainerSize.w, h: origContainerSize.h}
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(fsPlugin != null);
+
+								doh.robot.sequence(function(){
+									// Engage FullScreen Mode
+									fsPlugin.button.set("checked", true);
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Resize the container
+									container.resize({w: 400, h: 400});
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Disengage FullScreen Mode
+									fsPlugin.button.set("checked", false);
+								}, 1000);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now validate the editor resized when it returned since
+									// the Container was resized.
+									var curEditorSize = dojo.marginBox(editor.domNode);
+									var curContainerSize = dojo.marginBox(container.domNode);
+									var containerWdiff = origContainerSize.w - curContainerSize.w;
+									var containerHdiff = origContainerSize.h - curContainerSize.h;
+									var eWdiff= origEditorSize.w - curEditorSize.w;
+									var eHdiff= origEditorSize.h - curEditorSize.h;
+									
+									doh.assertTrue(origEditorSize.w > curEditorSize.w, "Validating new width is less that the original size");
+									doh.assertTrue(origEditorSize.h > curEditorSize.h, "Validating new height is less that the original size");
+									doh.assertTrue((eWdiff < (containerWdiff + 5)) && (eWdiff > (containerWdiff - 5)), "Doing a rouch check that the editor width resized roughly to the Container difference");
+									doh.assertTrue((eHdiff < (containerHdiff + 5)) && (eHdiff > (containerHdiff - 5)), "Doing a rouch check that the editor height resized roughly to the Container difference");
+								}), 1000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+							 if(container && os){container.resize(os);}
+						}
+					},
+					{
+						name: "TabContainer:  Go Fullscreen, Increase TabContainer, Exit FullScreen, Validate Resize",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor2");
+							container = dijit.byId("tc");
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+
+								var origEditorSize = dojo.marginBox(editor.domNode);
+								var origContainerSize = dojo.marginBox(container.domNode);
+								os = {w: origContainerSize.w, h: origContainerSize.h}
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(fsPlugin != null);
+
+								doh.robot.sequence(function(){
+									// Engage FullScreen Mode
+									fsPlugin.button.set("checked", true);
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Resize the container
+									container.resize({w: 800, h: 800});
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Disengage FullScreen Mode
+									fsPlugin.button.set("checked", false);
+								}, 1000);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now validate the editor resized when it returned since
+									// the Container was resized.
+									var curEditorSize = dojo.marginBox(editor.domNode);
+									var curContainerSize = dojo.marginBox(container.domNode);
+									var containerWdiff = -(origContainerSize.w - curContainerSize.w);
+									var containerHdiff = -(origContainerSize.h - curContainerSize.h);
+									var eWdiff= -(origEditorSize.w - curEditorSize.w);
+									var eHdiff= -(origEditorSize.h - curEditorSize.h);
+									
+									doh.assertTrue(origEditorSize.w < curEditorSize.w, "Validating new width is less that the original size");
+									doh.assertTrue(origEditorSize.h < curEditorSize.h, "Validating new height is less that the original size");
+									doh.assertTrue((eWdiff < (containerWdiff + 5)) && (eWdiff > (containerWdiff - 5)), "Doing a rouch check that the editor width resized roughly to the Container difference");
+									doh.assertTrue((eHdiff < (containerHdiff + 5)) && (eHdiff > (containerHdiff - 5)), "Doing a rouch check that the editor height resized roughly to the Container difference");
+								}), 1000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+							 if(container && os){container.resize(os);}
+						}
+					},
+					{
+						name: "AccordionContainer:  Go Fullscreen, Reduce AccordionContainer, Exit FullScreen, Validate Resize",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor3");
+							container = dijit.byId("ac");
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+
+								var origEditorSize = dojo.marginBox(editor.domNode);
+								var origContainerSize = dojo.marginBox(container.domNode);
+								os = {w: origContainerSize.w, h: origContainerSize.h}
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(fsPlugin != null);
+
+								doh.robot.sequence(function(){
+									// Engage FullScreen Mode
+									fsPlugin.button.set("checked", true);
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Resize the container
+									container.resize({w: 400, h: 400});
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Disengage FullScreen Mode
+									fsPlugin.button.set("checked", false);
+								}, 1000);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now validate the editor resized when it returned since
+									// the Container was resized.
+									var curEditorSize = dojo.marginBox(editor.domNode);
+									var curContainerSize = dojo.marginBox(container.domNode);
+									var containerWdiff = origContainerSize.w - curContainerSize.w;
+									var containerHdiff = origContainerSize.h - curContainerSize.h;
+									var eWdiff= origEditorSize.w - curEditorSize.w;
+									var eHdiff= origEditorSize.h - curEditorSize.h;
+									
+									doh.assertTrue(origEditorSize.w > curEditorSize.w, "Validating new width is less that the original size");
+									doh.assertTrue(origEditorSize.h > curEditorSize.h, "Validating new height is less that the original size");
+									doh.assertTrue((eWdiff < (containerWdiff + 5)) && (eWdiff > (containerWdiff - 5)), "Doing a rouch check that the editor width resized roughly to the Container difference");
+									doh.assertTrue((eHdiff < (containerHdiff + 5)) && (eHdiff > (containerHdiff - 5)), "Doing a rouch check that the editor height resized roughly to the Container difference");
+								}), 1000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+							 if(container && os){container.resize(os);}
+						}
+					},
+					{
+						name: "AccordionContainer:  Go Fullscreen, Increase AccordionContainer, Exit FullScreen, Validate Resize",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor3");
+							container = dijit.byId("ac");
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+
+								var origEditorSize = dojo.marginBox(editor.domNode);
+								var origContainerSize = dojo.marginBox(container.domNode);
+								os = {w: origContainerSize.w, h: origContainerSize.h}
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(fsPlugin != null);
+
+								doh.robot.sequence(function(){
+									// Engage FullScreen Mode
+									fsPlugin.button.set("checked", true);
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Resize the container
+									container.resize({w: 800, h: 800});
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Disengage FullScreen Mode
+									fsPlugin.button.set("checked", false);
+								}, 1000);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now validate the editor resized when it returned since
+									// the Container was resized.
+									var curEditorSize = dojo.marginBox(editor.domNode);
+									var curContainerSize = dojo.marginBox(container.domNode);
+									var containerWdiff = -(origContainerSize.w - curContainerSize.w);
+									var containerHdiff = -(origContainerSize.h - curContainerSize.h);
+									var eWdiff= -(origEditorSize.w - curEditorSize.w);
+									var eHdiff= -(origEditorSize.h - curEditorSize.h);
+									
+									doh.assertTrue(origEditorSize.w < curEditorSize.w, "Validating new width is less that the original size");
+									doh.assertTrue(origEditorSize.h < curEditorSize.h, "Validating new height is less that the original size");
+									doh.assertTrue((eWdiff < (containerWdiff + 5)) && (eWdiff > (containerWdiff - 5)), "Doing a rouch check that the editor width resized roughly to the Container difference");
+									doh.assertTrue((eHdiff < (containerHdiff + 5)) && (eHdiff > (containerHdiff - 5)), "Doing a rouch check that the editor height resized roughly to the Container difference");
+								}), 1000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+							 if(container && os){container.resize(os);}
+						}
+					},
+					{
+						name: "StackContainer:  Go Fullscreen, Reduce StackContainer, Exit FullScreen, Validate Resize",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor4");
+							container = dijit.byId("sc");
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+
+								var origEditorSize = dojo.marginBox(editor.domNode);
+								var origContainerSize = dojo.marginBox(container.domNode);
+								os = {w: origContainerSize.w, h: origContainerSize.h}
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(fsPlugin != null);
+
+								doh.robot.sequence(function(){
+									// Engage FullScreen Mode
+									fsPlugin.button.set("checked", true);
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Resize the container
+									container.resize({w: 400, h: 400});
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Disengage FullScreen Mode
+									fsPlugin.button.set("checked", false);
+								}, 1000);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now validate the editor resized when it returned since
+									// the Container was resized.
+									var curEditorSize = dojo.marginBox(editor.domNode);
+									var curContainerSize = dojo.marginBox(container.domNode);
+									var containerWdiff = origContainerSize.w - curContainerSize.w;
+									var containerHdiff = origContainerSize.h - curContainerSize.h;
+									var eWdiff= origEditorSize.w - curEditorSize.w;
+									var eHdiff= origEditorSize.h - curEditorSize.h;
+									
+									doh.assertTrue(origEditorSize.w > curEditorSize.w, "Validating new width is less that the original size");
+									doh.assertTrue(origEditorSize.h > curEditorSize.h, "Validating new height is less that the original size");
+									doh.assertTrue((eWdiff < (containerWdiff + 5)) && (eWdiff > (containerWdiff - 5)), "Doing a rouch check that the editor width resized roughly to the Container difference");
+									doh.assertTrue((eHdiff < (containerHdiff + 5)) && (eHdiff > (containerHdiff - 5)), "Doing a rouch check that the editor height resized roughly to the Container difference");
+								}), 1000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+							 if(container && os){container.resize(os);}
+						}
+					},
+					{
+						name: "StackContainer:  Go Fullscreen, Increase StackContainer, Exit FullScreen, Validate Resize",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor4");
+							container = dijit.byId("sc");
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+
+								var origEditorSize = dojo.marginBox(editor.domNode);
+								var origContainerSize = dojo.marginBox(container.domNode);
+								os = {w: origContainerSize.w, h: origContainerSize.h}
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(fsPlugin != null);
+
+								doh.robot.sequence(function(){
+									// Engage FullScreen Mode
+									fsPlugin.button.set("checked", true);
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Resize the container
+									container.resize({w: 800, h: 800});
+								}, 1000);
+								doh.robot.sequence(function(){
+									// Disengage FullScreen Mode
+									fsPlugin.button.set("checked", false);
+								}, 1000);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now validate the editor resized when it returned since
+									// the Container was resized.
+									var curEditorSize = dojo.marginBox(editor.domNode);
+									var curContainerSize = dojo.marginBox(container.domNode);
+									var containerWdiff = -(origContainerSize.w - curContainerSize.w);
+									var containerHdiff = -(origContainerSize.h - curContainerSize.h);
+									var eWdiff= -(origEditorSize.w - curEditorSize.w);
+									var eHdiff= -(origEditorSize.h - curEditorSize.h);
+									
+									doh.assertTrue(origEditorSize.w < curEditorSize.w, "Validating new width is less that the original size");
+									doh.assertTrue(origEditorSize.h < curEditorSize.h, "Validating new height is less that the original size");
+									doh.assertTrue((eWdiff < (containerWdiff + 5)) && (eWdiff > (containerWdiff - 5)), "Doing a rouch check that the editor width resized roughly to the Container difference");
+									doh.assertTrue((eHdiff < (containerHdiff + 5)) && (eHdiff > (containerHdiff - 5)), "Doing a rouch check that the editor height resized roughly to the Container difference");
+								}), 1000);
+
+
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+							 if(container && os){container.resize(os);}
+						}
+					}
+				]);
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/editor/robot/Editor_LinkDialog.html b/dijit/tests/editor/robot/Editor_LinkDialog.html
new file mode 100644
index 0000000..9a91ca7
--- /dev/null
+++ b/dijit/tests/editor/robot/Editor_LinkDialog.html
@@ -0,0 +1,1113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Editor LinkDialog Plugin Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_LinkDialog.html');
+
+				var editor;
+				var ldPlugin;
+				var value;
+				var node;
+
+				doh.register("LinkDialog_tests", [
+					{
+						name: "Anchor Tag: Create a new link",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.LinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								var value = editor.get("value");
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								var url, desc;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									url.set("value", "http://example.com/");
+									desc.set("value", "This is my example link.");
+								},2000);
+								doh.robot.mouseMoveAt(function(){return dijit.byId(ldPlugin._uniqueId + "_setButton").domNode;}, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal !== value, "Verify the contents have changed.");
+									doh.assertTrue(new RegExp("href=(\"|\')http://example.com/(\"|\')").test(newVal), "Verifying URL has been inserted.");
+									doh.assertFalse(new RegExp("<li><a").test(newVal), "Verifying insert did not occur in the top li (IE test for selection restore.)");
+									doh.assertTrue(new RegExp("target=(\"|\')_self(\"|\')").test(newVal), "Verifying target has been inserted.");
+									doh.assertTrue(new RegExp(">This is my example link.<").test(newVal), "Verifying description has been inserted.");
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Anchor Tag: Create a new link with alternate target",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.LinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								var value = editor.get("value");
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								var url, target, desc;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									target = dijit.byId(ldPlugin._uniqueId + "_targetSelect");
+									url.set("value", "http://example.com/");
+									desc.set("value", "This is my example link.");
+									target.set("value", "_blank");
+								},2000);
+								doh.robot.mouseMoveAt(function(){return dijit.byId(ldPlugin._uniqueId + "_setButton").domNode;}, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal !== value, "Verify the contents have changed.");
+									doh.assertFalse(new RegExp("<li><a").test(newVal), "Verifying insert did not occur in the top li (IE test for selection restore.)");
+									doh.assertTrue(new RegExp("href=(\"|\')http://example.com/(\"|\')").test(newVal), "Verifying URL has been inserted.");
+									doh.assertTrue(new RegExp("target=(\"|\')_blank(\"|\')").test(newVal), "Verifying target has been inserted.");
+									doh.assertTrue(new RegExp(">This is my example link.<").test(newVal), "Verifying description has been inserted.");
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Anchor Tag: Test auto insertion of http:// for urls.",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.LinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								var value = editor.get("value");
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								var url, desc, target;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									target = dijit.byId(ldPlugin._uniqueId + "_targetSelect");
+									url.set("value", "example.com/");
+									desc.set("value", "This is my example link.");
+									target.set("value", "_blank");
+								},2000);
+								doh.robot.mouseMoveAt(function(){return dijit.byId(ldPlugin._uniqueId + "_setButton").domNode;}, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal !== value, "Verify the contents have changed.");
+									doh.assertFalse(new RegExp("<li><a").test(newVal), "Verifying insert did not occur in the top li (IE test for selection restore.)");
+									doh.assertTrue(new RegExp("href=(\"|\')http://example.com/(\"|\')").test(newVal), "Verifying URL has been inserted.");
+									doh.assertTrue(new RegExp("target=(\"|\')_blank(\"|\')").test(newVal), "Verifying target has been inserted.");
+									doh.assertTrue(new RegExp(">This is my example link.<").test(newVal), "Verifying description has been inserted.");
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Anchor Tag: Test insertion 'relative' urls.",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.LinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								var value = editor.get("value");
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								var url, desc, target;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									target = dijit.byId(ldPlugin._uniqueId + "_targetSelect");
+									url.set("value", "./myDirectory/myfile.html");
+									desc.set("value", "This is my example relative link.");
+									target.set("value", "_blank");
+								},2000);
+								doh.robot.mouseMoveAt(function(){return dijit.byId(ldPlugin._uniqueId + "_setButton").domNode;}, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal !== value, "Verify the contents have changed.");
+									doh.assertFalse(new RegExp("<li><a").test(newVal), "Verifying insert did not occur in the top li (IE test for selection restore.)");
+									doh.assertTrue(new RegExp("href=(\"|\')./myDirectory/myfile.html(\"|\')").test(newVal), "Verifying URL has been inserted.");
+									doh.assertTrue(new RegExp("target=(\"|\')_blank(\"|\')").test(newVal), "Verifying target has been inserted.");
+									doh.assertTrue(new RegExp(">This is my example relative link.<").test(newVal), "Verifying description has been inserted.");
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Anchor Tag: Update existing anchor tag",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.LinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							dojo.withGlobal(editor.window, function(){
+								node = dojo.byId("exampleLink");
+							});
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								var value = editor.get("value");
+
+								doh.robot.sequence(function(){
+									// Okay, select the text of the hyperlink so we can then perform an edit on it.
+									editor._sCall("selectElement", [node]);
+								},500);
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								var url, desc, target, oldUrl, oldDesc;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									target = dijit.byId(ldPlugin._uniqueId + "_targetSelect");
+
+									oldUrl = url.get("value");
+									oldDesc = desc.get("value");
+
+									url.set("value", oldUrl + "_2");
+									desc.set("value", oldDesc + "_2");
+									target.set("value", "_blank");
+								}, 2000);
+								doh.robot.mouseMoveAt(function(){ return dijit.byId(ldPlugin._uniqueId + "_setButton").domNode; }, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal !== value, "Verify the contents have changed.");
+									doh.assertTrue(new RegExp("href=(\"|\')"+ oldUrl + "_2" + "(\"|\')").test(newVal), "Verifying URL has been inserted.");
+									doh.assertFalse(new RegExp("href=(\"|\')"+ oldUrl + "(\"|\')").test(newVal), "Verifying old URL is gone.");
+									doh.assertFalse(new RegExp("<li><a").test(newVal), "Verifying insert did not occur in the top li (IE test for selection restore.)");
+									doh.assertTrue(new RegExp("target=(\"|\')_blank(\"|\')").test(newVal), "Verifying target has been inserted.");
+									doh.assertFalse(new RegExp("target=(\"|\')_self(\"|\')").test(newVal), "Verifying old target is removed.");
+									doh.assertTrue(new RegExp(">" + oldDesc + "_2<").test(newVal), "Verifying description has been inserted.");
+									doh.assertFalse(new RegExp(">" + oldDesc + "<").test(newVal), "Verifying old desc is gone.");
+								}), 2000);
+							}catch(e){
+									d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Anchor Tag: Blank description invalid.",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.LinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							dojo.withGlobal(editor.window, function(){
+								node = dojo.byId("exampleLink");
+							});
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								var value = editor.get("value");
+
+								doh.robot.sequence(function(){
+									// Okay, select the text of the hyperlink so we can then perform an edit on it.
+									editor._sCall("selectElement", [node]);
+								},500);
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								var url, desc, target, oldDesc;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									target = dijit.byId(ldPlugin._uniqueId + "_targetSelect");
+									oldDesc = desc.get("value");
+									desc.set("value", "");
+									target.set("value", "_blank");
+								}, 2000);
+								doh.robot.sequence(function(){
+									// Verify setting the content is disabled.
+									var setButton = dijit.byId(ldPlugin._uniqueId + "_setButton");
+									doh.assertTrue(setButton.get("disabled"));
+								}, 500);
+								doh.robot.mouseMoveAt(function(){ return dijit.byId(ldPlugin._uniqueId + "_cancelButton").domNode; }, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal === value, "Verify the contents have not changed.");
+								}), 2000);
+							}catch(e){
+									d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Anchor Tag: Test invalid url.",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.LinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								var url, desc, target;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									target = dijit.byId(ldPlugin._uniqueId + "_targetSelect");
+									url.set("value", "http://this is not/valid/bad.html");
+									desc.set("value", "This is my example relative link.");
+									target.set("value", "_blank");
+									url.validate();
+								},2000);
+								doh.robot.sequence(function(){
+									var setButton = dijit.byId(ldPlugin._uniqueId + "_setButton");
+									doh.assertTrue(setButton.get("disabled"));
+								}, 500);
+								doh.robot.mouseMoveAt(function(){ return dijit.byId(ldPlugin._uniqueId + "_cancelButton").domNode; }, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.mouseMoveAt(editor.iframe, 500, null, 0, 0);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal === value, "Verify the contents have not changed.");
+									doh.assertFalse(url.isValid());
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Anchor Tag: Test mailto url.",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.LinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								var url, desc, target;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									target = dijit.byId(ldPlugin._uniqueId + "_targetSelect");
+									url.set("value", "mailto:johndoe at example.com");
+									desc.set("value", "Send a message to John.");
+									target.set("value", "_blank");
+									url.isValid();
+								},2000);
+								doh.robot.sequence(function(){
+									var setButton = dijit.byId(ldPlugin._uniqueId + "_setButton");
+									doh.assertTrue(!setButton.get("disabled"));
+								}, 500);
+								doh.robot.mouseMoveAt(function(){ return dijit.byId(ldPlugin._uniqueId + "_setButton").domNode; }, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.mouseMoveAt(editor.iframe, 500, null, 0, 0);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue((newVal.indexOf("mailto:johndoe at example.com") > -1), "Verify the contents have the mailto url present.");
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Anchor Tag: Test mailto url prepend.",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.LinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								var url, desc, target;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									target = dijit.byId(ldPlugin._uniqueId + "_targetSelect");
+									url.set("value", "johndoe at example.com");
+									desc.set("value", "Send a message to John.");
+									target.set("value", "_blank");
+									url.isValid();
+								},2000);
+								doh.robot.sequence(function(){
+									var setButton = dijit.byId(ldPlugin._uniqueId + "_setButton");
+									doh.assertTrue(!setButton.get("disabled"));
+								}, 500);
+								doh.robot.mouseMoveAt(function(){ return dijit.byId(ldPlugin._uniqueId + "_setButton").domNode; }, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.mouseMoveAt(editor.iframe, 500, null, 0, 0);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue((newVal.indexOf("mailto:johndoe at example.com") > -1), "Verify the contents have the mailto url present.");
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Anchor Tag: Test invalid mailto url.",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.LinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								var url, desc, target;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									target = dijit.byId(ldPlugin._uniqueId + "_targetSelect");
+									url.set("value", "mailto:john doe at example.com");
+									desc.set("value", "Send a message to John.");
+									target.set("value", "_blank");
+									url.isValid();
+								},2000);
+								doh.robot.sequence(function(){
+									var setButton = dijit.byId(ldPlugin._uniqueId + "_setButton");
+									doh.assertTrue(setButton.get("disabled"));
+								}, 500);
+								doh.robot.mouseMoveAt(function(){ return dijit.byId(ldPlugin._uniqueId + "_cancelButton").domNode; }, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.mouseMoveAt(editor.iframe, 500, null, 0, 0);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal === value, "Verify the contents have not changed.");
+									doh.assertFalse(url.isValid());
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Anchor Tag: Double-Click opens TooltipDialog.",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.LinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							dojo.withGlobal(editor.window, function(){
+								node = dojo.byId("exampleLink");
+							});
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								var value = editor.get("value");
+
+								doh.robot.sequence(d.getTestErrback(function(){
+									doh.assertTrue(ldPlugin && ldPlugin.dropDown && ldPlugin.dropDown.domNode, "found TooltipDialog");
+									doh.assertTrue(isHidden(ldPlugin.dropDown.domNode),  "tooltip dialog is hidden");
+								}));
+
+								// Double click
+								doh.robot.mouseMoveAt(node, 500);
+								doh.robot.mouseClick({left:true}, 100);
+								doh.robot.mouseClick({left:true}, 100);
+
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.assertTrue(isVisible(ldPlugin.dropDown.domNode),  "tooltip dialog is visible");
+
+									var f = dijit.getFocus();
+									if(f.node){
+										var w = dijit.getEnclosingWidget(f.node);
+										if(w){
+											var val = w.get("value");
+											doh.assertTrue(new RegExp("http://www.example.com/example.html").test(val), "Verifying the contents contained link url");
+										}else{
+											doh.assertTrue(false, "Failed to enclosing textbox widget.");
+										}
+									}else{
+										doh.assertTrue(false, "Failed to get focus.");	
+									}
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					}
+				]);
+
+				doh.register("ImgDialog_tests", [
+					{
+						name: "Image Tag: Create a new image",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ImgLinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the image dialog.");
+								var value = editor.get("value");
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								var url, desc;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									url.set("value", "./sample2.jpg");
+									desc.set("value", "This is my example image 2.");
+								},2000);
+								doh.robot.mouseMoveAt(function(){ return dijit.byId(ldPlugin._uniqueId + "_setButton").domNode; }, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal !== value, "Verify the contents have changed.");
+									doh.assertFalse(new RegExp("<li><img").test(newVal), "Verifying insert did not occur in the top li (IE test for selection restore.)");
+									doh.assertTrue(new RegExp("src=(\"|\').*/sample2.jpg(\"|\')").test(newVal), "Verifying URL has been inserted.");
+									doh.assertTrue(new RegExp("alt=(\"|\')This is my example image 2.(\"|\')").test(newVal), "Verifying alt description has been inserted.");
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Image Tag: Verify http:// is prepended",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ImgLinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the image dialog.");
+								var value = editor.get("value");
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								var url, desc;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									url.set("value", "example.com/example.jpg");
+									desc.set("value", "This is my example image.");
+								},2000);
+								doh.robot.mouseMoveAt(function(){ return dijit.byId(ldPlugin._uniqueId + "_setButton").domNode; }, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal !== value, "Verify the contents have changed.");
+									doh.assertFalse(new RegExp("<li><img").test(newVal), "Verifying insert did not occur in the top li (IE test for selection restore.)");
+									doh.assertTrue(new RegExp("src=(\"|\')http://example.com/example.jpg(\"|\')").test(newVal), "Verifying URL has been inserted.");
+									doh.assertTrue(new RegExp("alt=(\"|\')This is my example image.(\"|\')").test(newVal), "Verifying alt description has been inserted.");
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Image Tag: Update existing image tag",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ImgLinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							dojo.withGlobal(editor.window, function(){
+								node = dojo.byId("exampleImage");
+							});
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								var value = editor.get("value");
+
+								doh.robot.sequence(function(){editor._sCall("selectElement", [node]);}, 500);
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								var url, desc, oldDesc;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									oldDesc = desc.get("value");
+									url.set("value", "./sample2.jpg");
+									desc.set("value", oldDesc + "_2");
+								}, 2000);
+								doh.robot.mouseMoveAt(function(){ return dijit.byId(ldPlugin._uniqueId + "_setButton").domNode; }, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal !== value, "Verify the contents have changed.");
+									doh.assertFalse(new RegExp("<li><img").test(newVal), "Verifying insert did not occur in the top li (IE test for selection restore.)");
+									doh.assertTrue(new RegExp("src=(\"|\')"+ ".*/sample2.jpg" + "(\"|\')").test(newVal), "Verifying URL has been inserted.");
+									doh.assertFalse(new RegExp("src=(\"|\')"+ ".*/sample.jpg" + "(\"|\')").test(newVal), "Verifying old URL is gone.");
+									doh.assertTrue(new RegExp("alt=(\"|\")" + oldDesc + "_2" + "(\"|\')").test(newVal), "Verifying description has been inserted.");
+									doh.assertFalse(new RegExp("alt=(\"|\")" + oldDesc + "(\"|\')").test(newVal), "Verifying old desc is gone.");
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Image Tag: Blank description valid.",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ImgLinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							dojo.withGlobal(editor.window, function(){
+								node = dojo.byId("exampleImage");
+							});
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								var value = editor.get("value");
+
+								doh.robot.sequence(function(){editor._sCall("selectElement", [node]);}, 500);
+								doh.robot.mouseMoveAt(ldPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								var url, desc, oldDesc;
+								doh.robot.sequence(function(){
+									url = dijit.byId(ldPlugin._uniqueId + "_urlInput");
+									desc = dijit.byId(ldPlugin._uniqueId + "_textInput");
+									oldDesc = desc.get("value");
+									url.set("value", "./sample2.jpg");
+									desc.set("value", "");
+								}, 2000);
+								doh.robot.sequence(function(){
+									// Verify setting the content is disabled.
+									var setButton = dijit.byId(ldPlugin._uniqueId + "_setButton");
+									doh.assertFalse(setButton.get("disabled"));
+								}, 500);
+								doh.robot.mouseMoveAt(function(){ return dijit.byId(ldPlugin._uniqueId + "_setButton").domNode; }, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// Now check the state!
+									var newVal = editor.get("value");
+									doh.assertTrue(newVal !== value, "Verify the contents have changed.");
+									doh.assertFalse(new RegExp("<li><img").test(newVal), "Verifying insert did not occur in the top li (IE test for selection restore.)");
+									doh.assertTrue(new RegExp("src=(\"|\')"+ ".*/sample2.jpg" + "(\"|\')").test(newVal), "Verifying URL has been inserted.");
+									doh.assertFalse(new RegExp("src=(\"|\')"+ ".*/sample.jpg" + "(\"|\')").test(newVal), "Verifying old URL is gone.");
+									doh.assertTrue(new RegExp("alt=(\"|\")(\"|\')").test(newVal), "Verifying description has been cleared.");
+									doh.assertFalse(new RegExp("alt=(\"|\")" + oldDesc + "(\"|\')").test(newVal), "Verifying old desc is gone.");
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Image Tag: Single click selects image.",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ImgLinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							dojo.withGlobal(editor.window, function(){
+								node = dojo.byId("exampleImage");
+							});
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								var value = editor.get("value");
+
+								doh.robot.mouseMoveAt(node, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									var selectedElement = editor._sCall("getSelectedElement", [null]);
+									doh.assertTrue(selectedElement != null);
+									var tag = selectedElement.tagName? selectedElement.tagName.toLowerCase() : "";
+									doh.assertTrue(tag === "img");
+									doh.assertTrue(selectedElement.getAttribute("id") === "exampleImage");
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					},
+					{
+						name: "Image Tag: Double-Click opens TooltipDialog.",
+						timeout: 20000,
+						setUp: function(){
+							editor = dijit.byId("editor");
+							ldPlugin = null;
+							var edPlugins = editor._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ImgLinkDialog"){
+									ldPlugin = p;
+									break;
+								}
+							}
+							dojo.withGlobal(editor.window, function(){
+								node = dojo.byId("exampleImage");
+							});
+							value = editor.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								// Focus on the editor window
+								dojo.window.scrollIntoView(editor.domNode);
+								editor.focus();
+								doh.robot.mouseMoveAt(editor.iframe, 500);
+								doh.robot.mouseClick({left:true}, 500);
+								
+
+								// Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(ldPlugin !== null, "Verifying the link dialog.");
+								var value = editor.get("value");
+
+								doh.robot.sequence(d.getTestErrback(function(){
+									doh.assertTrue(ldPlugin && ldPlugin.dropDown && ldPlugin.dropDown.domNode, "found TooltipDialog");
+									doh.assertTrue(isHidden(ldPlugin.dropDown.domNode),  "tooltip dialog is hidden");
+								}));
+
+								// Double click
+								doh.robot.mouseMoveAt(node, 500);
+								doh.robot.mouseClick({left:true}, 100);
+								doh.robot.mouseClick({left:true}, 100);
+
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.assertTrue(isVisible(ldPlugin.dropDown.domNode),  "tooltip dialog is visible");
+
+									var f = dijit.getFocus();
+									if(f.node){
+										var w = dijit.getEnclosingWidget(f.node);
+										if(w){
+											var val = w.get("value");
+											doh.assertTrue(new RegExp(".*/sample.jpg").test(val), "Verifying the contents contained image name");
+										}else{
+											doh.assertTrue(false, "Failed to enclosing textbox widget.");
+										}
+									}else{
+										doh.assertTrue(false, "Failed to get focus.");	
+									}
+								}), 2000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.set("value", value);}
+						}
+					}
+				]);
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/editor/robot/Editor_NewPage.html b/dijit/tests/editor/robot/Editor_NewPage.html
new file mode 100755
index 0000000..569f65b
--- /dev/null
+++ b/dijit/tests/editor/robot/Editor_NewPage.html
@@ -0,0 +1,128 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Editor NewPage Plugin Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_NewPage.html');
+
+				var editor0;
+				var npPlugin;
+				var value;
+
+				doh.register("NewPage_tests", [
+					{
+						name: "Mouse: Click new page clears editor",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.NewPage"){
+									npPlugin = p;
+									break;
+								}
+							}
+							value = editor0.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor0.domNode);
+								editor0.focus();
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(npPlugin != null);
+								var value = editor0.get("value");
+								doh.robot.mouseMoveAt(npPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								doh.robot.sequence(d.getTestCallback(function(){
+									//Now check the state!
+									var newVal = editor0.get("value");
+									doh.assertTrue(newVal !== value, "Verify the contents have changed.");
+									newVal = dojo.trim(newVal);
+									newVal = newVal.replace("/>", ">");
+									newVal = newVal.replace(" >", ">");
+									newVal = newVal.toLowerCase();
+									doh.assertEqual("<br>", newVal, "Validate the contents are a single br");
+								}), 1000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor0){editor0.set("value", value);}
+						}
+					},
+					{
+						name: "Mouse: Click new page sets editor with default content.",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("editor1");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.NewPage"){
+									npPlugin = p;
+									break;
+								}
+							}
+							value = editor0.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor0.domNode);
+								editor0.focus();
+
+								//Find the fullscreen plugin, we'll need it.
+								doh.assertTrue(npPlugin != null);
+								var value = editor0.get("value");
+								doh.robot.mouseMoveAt(npPlugin.button.domNode, 500);
+								doh.robot.mouseClick({left:true}, 500);
+
+								doh.robot.sequence(d.getTestCallback(function(){
+									//Now check the state!
+									var newVal = editor0.get("value");
+									doh.assertTrue(newVal !== value, "Verify the contents have changed.");
+									newVal = dojo.trim(newVal);
+									doh.assertEqual("<p>This page intentionally left blank</p>", newVal, "Validate the contents are the defined default content");
+								}), 1000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor0){editor0.set("value", value);}
+						}
+					}
+				]);
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/editor/robot/Editor_ViewSource.html b/dijit/tests/editor/robot/Editor_ViewSource.html
new file mode 100755
index 0000000..254ed07
--- /dev/null
+++ b/dijit/tests/editor/robot/Editor_ViewSource.html
@@ -0,0 +1,787 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Editor View Source Plugin Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_ViewSource.html');
+
+				var editor0, editor1, editor2, editor3;
+				var fsPlugin;
+				var vsPlugin;
+
+				doh.register("ViewSource_Tests", [
+					{
+						name: "Keyboard: Go to view source (CTRL-SHIFT-F12)",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+								}
+								if(vsPlugin){
+									break;
+								}
+							}
+							if(vsPlugin) { vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							editor0.onLoadDeferred.addCallback(function(){
+								//Timing gets wonky here, so we need to do this on a timeout
+								//so the browser has time  to shift focus.
+								setTimeout(function(){
+									try{
+										//Focus on the editor window
+										editor0.focus();
+
+										//Find the ViewSource plugin, we'll need it.
+										doh.assertTrue(vsPlugin != null, "Checking for VS plugin.");
+										doh.robot.keyPress(dojo.keys.F12, 1000, {ctrl:true,shift:true});
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											//Now check the state!
+											doh.assertTrue(vsPlugin._sourceShown, "Verifying the plugin believes the source is shown.");
+											doh.assertEqual("none", dojo.style(editor0.iframe, "display"), "Verifying iframe is invisible");
+											doh.assertEqual("block", dojo.style(vsPlugin.sourceArea, "display"), "Verifying source view node is visible");
+											doh.assertEqual(vsPlugin.sourceArea.nextSibling, editor0.iframe, "Verifying source view node's next sibling is the hidden iframe node.");
+										}), 3000);
+									}catch(e){
+										d.errback(e);
+									}
+								}, 500);
+							});
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					},
+					{
+						name: "Keyboard: Go to source mode and back",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+								}
+								if(vsPlugin){
+									break;
+								}
+							}
+							if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							setTimeout(function(){
+								try{
+									//Focus on the editor window
+									editor0.focus();
+
+									//Find the view source plugin, we'll need it.
+									doh.assertTrue(vsPlugin != null, "Checking that the view source plugin was found.");
+									doh.robot.keyPress(dojo.keys.F12, 500, {ctrl:true,shift:true});
+									doh.robot.keyPress(dojo.keys.F12, 1000, {ctrl:true,shift:true});
+
+									doh.robot.sequence(d.getTestCallback(function(){
+										//Now check the state!
+										doh.assertFalse(vsPlugin._sourceShown, "Verifying the plugin states the source is not shown.");
+										doh.assertEqual("block", dojo.style(editor0.iframe, "display"), "Verifying iframe is visible");
+										doh.assertEqual("none", dojo.style(vsPlugin.sourceArea, "display"), "Verifying source view node is invisible");
+										doh.assertEqual(vsPlugin.sourceArea.nextSibling, editor0.iframe, "Verifying source view node's next sibling is the hidden iframe node.");
+									}), 2000);
+								}catch(e){
+									d.errback(e);
+								}
+							}, 1000);
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						}
+					},
+					{
+						name: "Mouse Click: Go to View Source",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+									break;
+								}
+							}
+							if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							setTimeout(function(){
+								try{
+									//Focus on the editor window
+									editor0.focus();
+
+									doh.assertTrue(vsPlugin != null);
+									doh.robot.mouseMoveAt(vsPlugin.button.domNode, 500);
+									doh.robot.mouseClick({left: true}, 750);
+
+									doh.robot.sequence(d.getTestCallback(function(){
+										//Now check the state!
+										doh.assertTrue(vsPlugin._sourceShown, "Verifying the plugin believes the source is shown.");
+										doh.assertEqual("none", dojo.style(editor0.iframe, "display"), "Verifying iframe is invisible");
+										doh.assertEqual("block", dojo.style(vsPlugin.sourceArea, "display"), "Verifying source view node is visible");
+										doh.assertEqual(vsPlugin.sourceArea.nextSibling, editor0.iframe, "Verifying source view node's next sibling is the hidden iframe node.");
+									}), 1000);
+								}catch(e){
+									d.errback(e);
+								}
+							}, 1000);
+
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					},
+					{
+						name: "Mouse Click: Go to View Source, then mouseclick twice (open/close sourceview)",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+									break;
+								}
+							}
+							if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							setTimeout(function(){
+								try{
+									//Focus on the editor window
+									editor0.focus();
+
+									doh.assertTrue(vsPlugin != null);
+									doh.robot.mouseMoveAt(vsPlugin.button.domNode, 500);
+									doh.robot.mouseClick({left: true}, 750);
+									doh.robot.mouseMoveAt(vsPlugin.button.domNode, 500);
+									doh.robot.mouseClick({left: true}, 750);
+
+									doh.robot.sequence(d.getTestCallback(function(){
+										//Now check the state!
+										doh.assertTrue(!vsPlugin._sourceShown, "Verifying the plugin believes the source is not shown.");
+										doh.assertEqual("block", dojo.style(editor0.iframe, "display"), "Verifying iframe is visible");
+										doh.assertEqual("none", dojo.style(vsPlugin.sourceArea, "display"), "Verifying source view node is invisible");
+										doh.assertEqual(vsPlugin.sourceArea.nextSibling, editor0.iframe, "Verifying source view node's next sibling is the hidden iframe node.");
+									}), 1000);
+								}catch(e){
+									d.errback(e);
+								}
+							}, 500);
+
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					},
+					{
+						name: "Combination Test:  FullScreen + ViewSource (Verify view source works in fullscreen mode)",
+						timeout: 20000,
+						setUp: function(){
+							editor1 = dijit.byId("editor1");
+							var edPlugins = editor1._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+								}
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+								}
+								if(vsPlugin && fsPlugin){
+									break;
+								}
+							}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+							if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							setTimeout(function(){
+								try{
+									//Focus on the editor window
+									editor1.focus();
+
+									doh.assertTrue(vsPlugin != null, "Checking for viewSource plugin.");
+									doh.assertTrue(fsPlugin != null, "Checking for fullScreen plugin.");
+									doh.robot.mouseMoveAt(fsPlugin.button.domNode, 1000);
+									doh.robot.mouseClick({left: true}, 500);
+									doh.robot.mouseMoveAt(vsPlugin.button.domNode, 1000);
+									doh.robot.mouseClick({left: true}, 500);
+
+									doh.robot.sequence(d.getTestCallback(function(){
+										//Now check the state!
+										doh.assertTrue(fsPlugin.isFullscreen, "Verifying the plugin believes the editor is in full screen mode.");
+										doh.assertTrue(vsPlugin._sourceShown, "Verifying the plugin believes the source is shown.");
+										doh.assertEqual("none", dojo.style(editor1.iframe, "display"), "Verifying iframe is invisible");
+										doh.assertEqual("block", dojo.style(vsPlugin.sourceArea, "display"), "Verifying source view node is visible");
+										doh.assertEqual(vsPlugin.sourceArea.nextSibling, editor1.iframe, "Verifying source view node's next sibling is the hidden iframe node.");
+									}), 2000);
+								}catch(e){
+									d.errback(e);
+								}
+							}, 1000);
+							return d;
+						},
+						tearDown: function(){
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					},
+					{
+						name: "Combination Test:  FullScreen + ViewSource (toggle on and off)",
+						timeout: 20000,
+						setUp: function(){
+							editor1 = dijit.byId("editor1");
+							var edPlugins = editor1._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.FullScreen"){
+									fsPlugin = p;
+								}
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+								}
+								if(vsPlugin && fsPlugin){
+									break;
+								}
+							}
+							if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							if(fsPlugin) {fsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							setTimeout(function(){
+								try{
+									//Focus on the editor window
+									dojo.window.scrollIntoView(editor1.domNode);
+									editor1.focus();
+
+									doh.assertTrue(vsPlugin != null, "Checking for viewSource plugin.");
+									doh.assertTrue(fsPlugin != null, "Checking for fullScreen plugin.");
+
+									//Toggle fs on, the source on.
+									doh.robot.mouseMoveAt(fsPlugin.button.domNode, 500);
+									doh.robot.mouseClick({left: true}, 750);
+									doh.robot.mouseMoveAt(vsPlugin.button.domNode, 1000);
+									doh.robot.mouseClick({left: true}, 1000);
+									doh.robot.mouseMoveAt(vsPlugin.button.domNode, 500);
+									doh.robot.mouseClick({left: true}, 1000);
+									doh.robot.mouseMoveAt(fsPlugin.button.domNode, 500);
+									doh.robot.mouseClick({left: true}, 1000);
+									doh.robot.sequence(d.getTestCallback(function(){
+										//Now check the state!
+										doh.assertTrue(!fsPlugin.isFullscreen, "Verifying the plugin believes the editor is not in full screen mode.");
+										doh.assertTrue(!vsPlugin._sourceShown, "Verifying the plugin believes the source is not shown.");
+										doh.assertEqual("block", dojo.style(editor1.iframe, "display"), "Verifying iframe is visible");
+										doh.assertEqual("none", dojo.style(vsPlugin.sourceArea, "display"), "Verifying source view node is invisible");
+										doh.assertEqual(vsPlugin.sourceArea.nextSibling, editor1.iframe, "Verifying source view node's next sibling is the hidden iframe node.");
+									}), 1000);
+								}catch(e){
+									d.errback(e);
+								}
+							}, 1000);
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 if(fsPlugin) {fsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					},
+					{
+						name: "XSS: Verify simple script tags get stripped.",
+						timeout: 30000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+								}
+								if(vsPlugin){
+									break;
+								}
+							}
+							if(vsPlugin) { vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							editor0.onLoadDeferred.addCallback(function(){
+								//Timing gets wonky here, so we need to do this on a timeout
+								//so the browser has time  to shift focus.
+								var oldValue = editor0.get("value");
+								setTimeout(function(){
+									try{
+										//Focus on the editor window
+										editor0.focus();
+										dojo.window.scrollIntoView(editor0.domNode);
+
+										var simpleScript0 = '<scr' + 'ipt type="text/javascript">var foo = "Hack!"</scr' + 'ipt>';
+										var simpleScript1 = '<scr' + 'ipt type="text/javascript" src="http://example.com/hack.js"></scr' + 'ipt>';
+
+										//Type in some script stuff.
+										doh.assertTrue(vsPlugin != null, "Checking for VS plugin.");
+
+										doh.robot.keyPress(dojo.keys.F12, 1000, {ctrl:true,shift:true});
+										doh.robot.sequence(function(){
+											var val = "\n\n" +
+												simpleScript0 +
+												"\n\n" +
+												simpleScript1 +
+												"\n" +
+												vsPlugin.sourceArea.value;
+											vsPlugin.sourceArea.value = val;
+										}, 1000);
+										doh.robot.keyPress(dojo.keys.F12, 1000, {ctrl:true,shift:true});
+										doh.robot.sequence(d.getTestCallback(function(){
+											//Now check the state!
+											var val = editor0.get("value");
+											doh.assertEqual(-1, val.indexOf("Hack!"), "Validating inline script tag was stripped");
+											doh.assertEqual(-1, val.indexOf("hack.js"), "Validating import script tag was stripped");
+											editor0.set("value", oldValue);
+										}), 2000);
+									}catch(e){
+										d.errback(e);
+									}
+								}, 500);
+							});
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					},
+					{
+						name: "XSS: Verify complex/odd script tags get stripped.",
+						timeout: 30000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+								}
+								if(vsPlugin){
+									break;
+								}
+							}
+							if(vsPlugin) { vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							editor0.onLoadDeferred.addCallback(function(){
+								//Timing gets wonky here, so we need to do this on a timeout
+								//so the browser has time  to shift focus.
+								var oldValue = editor0.get("value");
+								setTimeout(function(){
+									try{
+										//Focus on the editor window
+										editor0.focus();
+										dojo.window.scrollIntoView(editor0.domNode);
+
+										var complexScript = '< scr' + 'IPt type="text/javascript"            \n>\n   var foo = "Hack!"  \n</SCr' + 'ipt  >';
+										doh.assertTrue(vsPlugin != null, "Checking for VS plugin.");
+										doh.robot.keyPress(dojo.keys.F12, 500, {ctrl:true,shift:true});
+										doh.robot.sequence(function(){
+											var val = "\n\n" +
+												complexScript +
+												"\n\n" +
+												vsPlugin.sourceArea.value;
+											vsPlugin.sourceArea.value = val;
+										}, 1000);
+										doh.robot.keyPress(dojo.keys.F12, 500, {ctrl:true,shift:true});
+										doh.robot.sequence(d.getTestCallback(function(){
+											//Now check the state!
+											var val = editor0.get("value");
+											doh.assertEqual(-1, val.indexOf("< scrIPt "), "Validating script tag was stripped");
+											editor0.set("value", oldValue);
+										}), 2000);
+									}catch(e){
+										d.errback(e);
+									}
+								}, 500);
+							});
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					},
+					{
+						name: "XSS: Verify single line comment blocks are stripped.",
+						timeout: 30000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+								}
+								if(vsPlugin){
+									break;
+								}
+							}
+							if(vsPlugin) { vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							editor0.onLoadDeferred.addCallback(function(){
+								//Timing gets wonky here, so we need to do this on a timeout
+								//so the browser has time  to shift focus.
+								var oldValue = editor0.get("value");
+								setTimeout(function(){
+									try{
+										//Focus on the editor window
+										editor0.focus();
+										dojo.window.scrollIntoView(editor0.domNode);
+
+										var simpleComment = '<!--  Hello, this is a comment! -->';
+
+										//Type in some script stuff.
+										doh.assertTrue(vsPlugin != null, "Checking for VS plugin.");
+										doh.robot.keyPress(dojo.keys.F12, 500, {ctrl:true,shift:true});
+										doh.robot.sequence(function(){
+											var val = "\n\n" +
+												simpleComment +
+												"\n\n" +
+												vsPlugin.sourceArea.value;
+											vsPlugin.sourceArea.value = val;
+										}, 1000);
+										doh.robot.keyPress(dojo.keys.F12, 500, {ctrl:true,shift:true});
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											//Now check the state!
+											var val = editor0.get("value");
+											doh.assertEqual(-1, val.indexOf("Hello, this is a comment!"), "Validating comment block was stripped");
+											editor0.set("value", oldValue);
+										}), 2000);
+									}catch(e){
+										d.errback(e);
+									}
+								}, 500);
+							});
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					},
+					{
+						name: "XSS: Verify multi line comment blocks are stripped.",
+						timeout: 30000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+								}
+								if(vsPlugin){
+									break;
+								}
+							}
+							if(vsPlugin) { vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							editor0.onLoadDeferred.addCallback(function(){
+								//Timing gets wonky here, so we need to do this on a timeout
+								//so the browser has time  to shift focus.
+								var oldValue = editor0.get("value");
+								setTimeout(function(){
+									try{
+										//Focus on the editor window
+										editor0.focus();
+										dojo.window.scrollIntoView(editor0.domNode);
+
+										//Type in some script stuff.
+										doh.assertTrue(vsPlugin != null, "Checking for VS plugin.");
+										doh.robot.keyPress(dojo.keys.F12, 1000, {ctrl:true,shift:true});
+										doh.robot.sequence(function(){
+											var val = "\n\n" +
+												"<!--\n" +
+												"Hello, this is a comment!\n" +
+												"-->\n" +
+												"\n\n" +
+												vsPlugin.sourceArea.value;
+											vsPlugin.sourceArea.value = val;
+										}, 1000);
+										doh.robot.keyPress(dojo.keys.F12, 1000, {ctrl:true,shift:true});
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											//Now check the state!
+											var val = editor0.get("value");
+											doh.assertEqual(-1, val.indexOf("Hello, this is a comment!"), "Validating multiline comment block was stripped");
+											editor0.set("value", oldValue);
+										}), 2000);
+									}catch(e){
+										d.errback(e);
+									}
+								}, 500);
+							});
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					},
+					{
+						//This is probably paranoia, but I think there's a chance iframes
+						//can be used to pull in hack scripts, so check that we can strip those too.
+						name: "XSS: Verify iframe tags are stripped.",
+						timeout: 30000,
+						setUp: function(){
+							editor0 = dijit.byId("editor0");
+							var edPlugins = editor0._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+								}
+								if(vsPlugin){
+									break;
+								}
+							}
+							if(vsPlugin) { vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							 var d = new doh.Deferred();
+							 editor0.onLoadDeferred.addCallback(function(){
+								//Timing gets wonky here, so we need to do this on a timeout
+								//so the browser has time  to shift focus.
+								var oldValue = editor0.get("value");
+								setTimeout(function(){
+									try{
+										//Focus on the editor window
+										editor0.focus();
+
+										var simpleiFrame = '<iframe src="http://example.com/hack.html" width=0 height=0 style="display: none;"></iframe>';
+
+										//Type in some script stuff.
+										doh.assertTrue(vsPlugin != null, "Checking for VS plugin.");
+										doh.robot.keyPress(dojo.keys.F12, 1000, {ctrl:true,shift:true});
+										doh.robot.sequence(function(){
+											var val = "\n\n" +
+												simpleiFrame +
+												"\n\n" +
+												vsPlugin.sourceArea.value;
+											vsPlugin.sourceArea.value = val;
+										}, 1000);
+										doh.robot.keyPress(dojo.keys.F12, 1000, {ctrl:true,shift:true});
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											//Now check the state!
+											var val = editor0.get("value");
+											doh.assertEqual(-1, val.indexOf("<iframe"), "Validating iframe tag was stripped stripped");
+											editor0.set("value", oldValue);
+										}), 2000);
+									}catch(e){
+										d.errback(e);
+									}
+								}, 500);
+							});
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					},
+					{
+						name: "XSS Disabled: Verify script, comment, and iframes are not stripped.",
+						timeout: 30000,
+						setUp: function(){
+							editor3 = dijit.byId("editor3");
+							var edPlugins = editor3._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+								}
+								if(vsPlugin){
+									break;
+								}
+							}
+							if(vsPlugin) { vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							editor3.onLoadDeferred.addCallback(function(){
+								//Timing gets wonky here, so we need to do this on a timeout
+								//so the browser has time  to shift focus.
+								var oldValue = editor3.get("value");
+								setTimeout(function(){
+									try{
+										//Focus on the editor window
+										editor3.focus();
+										dojo.window.scrollIntoView(editor3.domNode);
+
+										var simpleScript0 = '<scr' + 'ipt type="text/javascript">var foo = "Hack!"</scr' + 'ipt>';
+										var simpleScript1 = '<scr' + 'ipt type="text/javascript" src="http://example.com/hack.js"></scr' + 'ipt>';
+										var simpleiFrame = '<iframe src="http://example.com/hack.html" width=0 height=0 style="display: none;"></iframe>';
+										var simpleComment = '<!--  Hello, this is a comment! -->';
+
+										//Type in some script stuff.
+										doh.assertTrue(vsPlugin != null, "Checking for VS plugin.");
+										doh.robot.keyPress(dojo.keys.F12, 1000, {ctrl:true,shift:true});
+
+										doh.robot.sequence(function(){
+											var val = "\n\n" +
+												"<div>\n" +
+												simpleScript0 +
+												"\n\n" +
+												simpleScript1 +
+												"\n" +
+												"</div>" +
+												"\n\n" +
+												simpleiFrame +
+												"\n\n" +
+												simpleComment +
+												"\n\n" +
+												vsPlugin.sourceArea.value;
+											vsPlugin.sourceArea.value = val;
+										}, 1000);
+										doh.robot.keyPress(dojo.keys.F12, 1000, {ctrl:true,shift:true});
+										doh.robot.sequence(d.getTestCallback(function(){
+											//Now check the state!
+											var val = editor3.get("value");
+											// IE strips scripts anyway, need to look more at this sometime.
+											// It's not the plugin doing it.
+											doh.assertTrue((0 <= val.indexOf("Hack!")) || dojo.isIE, "Validating inline script tag was left");
+											doh.assertTrue((0 <= val.indexOf("hack.js") || dojo.isIE), "Validating import script tag was left");
+											doh.assertTrue(0 <= val.indexOf("<iframe"), "Validating iframe tag was left");
+											doh.assertTrue(0 <= val.indexOf("Hello, this is a comment!"), "Validating comment was left");
+											editor3.set("value", oldValue);
+										}), 2000);
+									}catch(e){
+										d.errback(e);
+									}
+								}, 500);
+							});
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					},
+					{
+						name: "ReadOnly:  Verify View Source can be put in ReadOnly mode.",
+						timeout: 30000,
+						setUp: function(){
+							editor2 = dijit.byId("editor2");
+							var edPlugins = editor2._plugins, i;
+							for(i = 0; i < edPlugins.length; i++){
+								var p = edPlugins[i];
+								if(p.declaredClass === "dijit._editor.plugins.ViewSource"){
+									vsPlugin = p;
+								}
+								if(vsPlugin){
+									break;
+								}
+							}
+							if(vsPlugin) { vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+						},
+						runTest: function(){
+							 var d = new doh.Deferred();
+							 editor2.onLoadDeferred.addCallback(function(){
+								//Timing gets wonky here, so we need to do this on a timeout
+								//so the browser has time  to shift focus.
+								editor2.focus();
+								dojo.window.scrollIntoView(editor2.domNode);
+								setTimeout(function(){
+									try{
+										//Focus on the editor window
+										doh.robot.mouseMoveAt(vsPlugin.button.domNode, 500);
+										doh.robot.mouseClick({left: true}, 750);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											//Now check the state!
+											doh.assertEqual(true, dojo.attr(vsPlugin.sourceArea, "readOnly"), "Verify the source area is read only.");
+										}), 2000);
+									}catch(e){
+										d.errback(e);
+									}
+								}, 500);
+							});
+							return d;
+						},
+						tearDown: function(){
+							 if(vsPlugin) {vsPlugin.button.focus(); vsPlugin.button.set("checked", false);}
+							 fsPlugin = null;
+							 vsPlugin = null;
+						}
+					}
+				]);
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/editor/robot/Editor_a11y.html b/dijit/tests/editor/robot/Editor_a11y.html
new file mode 100644
index 0000000..7adb0de
--- /dev/null
+++ b/dijit/tests/editor/robot/Editor_a11y.html
@@ -0,0 +1,332 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Editor A11Y Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			function normalize(str){
+				// try to do some normalization to make all browsers look
+				// the same.   Would be nice if we didn't need this, the normalization should
+				// probably happen as pre and post filters on the editor
+				return str.
+					replace('<br />', '').		// FF.  Because of EnterKeyHandling plugin?
+					replace(/^<p>/, '').replace(/<\/p>$/, '').		// Safari.  Because of EnterKeyHandling plugin?
+					replace(new RegExp(String.fromCharCode(160), "g"), " ");	// Safari: nbsp (char code 160) to normal space (char code 32)
+			}
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Editor.html');
+
+				// For some reason the meta key (meta-a for selection, meta-b for bold, etc) isn't working
+				// on mac... use ctrl- instead, just like on windows. (#9553)
+				var metaKey = {ctrl: true}
+
+				var editor0, editor1;
+
+				doh.register("setup", function setup(){
+					editor0 = dijit.byId("editor0");
+					editor1 = dijit.byId("editor1");
+				});
+
+				doh.register("keyboard shortcuts", [
+					{
+						name: "bold/italic",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dojo.window.scrollIntoView(editor1.domNode);
+
+							// Set contents of editor1
+							doh.robot.sequence(function(){
+								editor1.focus();
+							}, 500);
+							doh.robot.keyPress("a", 500, metaKey);	// select all
+							doh.robot.typeKeys("hello ", 500);		// and erase (by typing something new)
+							doh.robot.keyPress("b", 500, metaKey);	// start bold
+							doh.robot.typeKeys("bold", 500);
+							doh.robot.keyPress("b", 500, metaKey);	// stop bold
+							doh.robot.typeKeys(" and ", 500);
+							doh.robot.keyPress("i", 500, metaKey);	// start italic
+							doh.robot.typeKeys("exciting", 500);
+							doh.robot.keyPress("i", 500, metaKey);	// stop italic
+							doh.robot.typeKeys(" new world.", 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var val = normalize(editor1.get('value'));
+								doh.is("hello <b>bold</b> and <i>exciting</i> new world.", val);
+							}), 1500);
+
+							return d;
+						}
+					}
+				]);
+
+				// Check that toolbar buttons are highlighted/not highlighted (etc.) based on
+				// where caret is in document
+				doh.register("toolbar state", [
+					{
+						name: "setup",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dojo.window.scrollIntoView(editor1.domNode);
+
+							// strange things happen if you alter an editor's value while it is focused,
+							// so temporarily move to the toolbar while setting content
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});	// go to toolbar
+							doh.robot.sequence(function(){
+								editor1.set("value", "toolbar <b>state</b> <i>test</i>.")
+							}, 500);
+							doh.robot.keyPress(dojo.keys.TAB, 500);	// goes to content
+
+
+							doh.robot.keyPress(dojo.keys.HOME, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var toolbar = editor1.toolbar;
+								doh.t(toolbar, "found toolbar");
+
+								var boldButton = toolbar.getChildren()[7];
+								doh.t(boldButton, "found bold button");
+								doh.f(boldButton.get("checked"), "bold button not depressed");
+
+								var italicButton = toolbar.getChildren()[8];
+								doh.t(italicButton, "found italic button");
+								doh.f(italicButton.get("checked"), "italic button not depressed");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "bold higlighted",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							doh.robot.sequence(function(){
+								editor1.placeCursorAtStart();
+							}, 500);
+							var i;
+							for(i = 0; i < 9; i++){
+								// Move to second letter of second word.
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500);
+							}
+							doh.robot.sequence(d.getTestCallback(function(){
+								var toolbar = editor1.toolbar;
+								doh.t(toolbar, "found toolbar");
+
+								var boldButton = toolbar.getChildren()[7];
+								doh.t(boldButton, "found bold button");
+								doh.t(boldButton.get("checked"), "bold button depressed");
+
+								var italicButton = toolbar.getChildren()[8];
+								doh.t(italicButton, "found italic button");
+								doh.f(italicButton.get("checked"), "italic button not depressed");
+							}), 1000);
+
+							return d;
+						}
+					},
+					{
+						name: "italic higlighted",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.sequence(function(){
+								editor1.placeCursorAtStart();
+							}, 500);
+							var i;
+							for(i = 0; i < 15; i++){
+								// Move to second letter of third word.
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500);
+							}
+							doh.robot.sequence(d.getTestCallback(function(){
+								var toolbar = editor1.toolbar;
+								doh.t(toolbar, "found toolbar");
+
+								var boldButton = toolbar.getChildren()[7];
+								doh.t(boldButton, "found bold button");
+								doh.f(boldButton.get("checked"), "bold button not depressed");
+
+								var italicButton = toolbar.getChildren()[8];
+								doh.t(italicButton, "found italic button");
+								doh.t(italicButton.get("checked"), "italic button depressed");
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("toolbar navigation", [
+					{
+						name: "bold",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dojo.window.scrollIntoView(editor1.domNode);
+
+							doh.robot.sequence(function(){
+								editor1.focus();
+							}, 500);
+							doh.robot.keyPress("a", 500, metaKey);	// select all
+							doh.robot.typeKeys("hello ", 500);		// and erase (by typing something new)
+
+							// Go to toolbar and turn on bold.
+							// We only have to right-arrow twice because it skips the vertical divider bars
+							// and also skips cut and copy (they are disabled b/c nothing is selected)
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500);
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500);
+							doh.robot.keyPress(dojo.keys.SPACE, 500);
+
+							doh.robot.typeKeys("world", 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Get the value and try to do some normalization to make all browsers look
+								// the same.   Would be nice if we didn't need this, the normalization should
+								// probably happen as pre and post filters on the editor
+								var val = normalize(editor1.get('value'));
+								doh.is("hello <b>world</b>", val);
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("tabbing", [
+					{
+						name: "into editor1 toolbar",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dojo.window.scrollIntoView(editor1.domNode);
+
+							// Focus on link before editor
+							doh.robot.sequence(function(){
+								dojo.byId("focusBefore").focus();
+							}, 500);
+
+							// Go to toolbar of editor1
+							doh.robot.keyPress(dojo.keys.TAB, 500);
+
+							// We should get focus on one of the toolbar buttons, although which one depends
+							// on whether the editor's contents have been modified (undo button enabled), and
+							// whether there is something in the browser's paste buffer, etc.)
+							doh.robot.sequence(d.getTestCallback(function(){
+								var curFocus = dijit.getEnclosingWidget(dojo.global.dijit._curFocus);
+								doh.isNot(-1, dojo.indexOf(editor1.toolbar.getChildren(), curFocus), "focused on button of editor1 toolbar");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "into editor1",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Go to content of editor1
+							doh.robot.keyPress(dojo.keys.TAB, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("editor1_iframe", dojo.global.dijit._curFocus.id, "focused on editor content");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "out of editor1",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Go to link after editor1
+							doh.robot.keyPress(dojo.keys.TAB, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("focusAfter", dojo.global.dijit._curFocus.id, "focused after editor1");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "shift-tab back into editor1",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Go to content of editor1
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("editor1_iframe", dojo.global.dijit._curFocus.id, "focused on editor content");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "shift-tab back to toolbar",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var curFocus = dijit.getEnclosingWidget(dojo.global.dijit._curFocus);
+								doh.isNot(-1, dojo.indexOf(editor1.toolbar.getChildren(), curFocus), "focused on button of editor1 toolbar");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "shift-tab to before editor",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("focusBefore", dojo.global.dijit._curFocus.id, "focused before editor1");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+
+
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/editor/robot/Editor_misc.html b/dijit/tests/editor/robot/Editor_misc.html
new file mode 100755
index 0000000..c032845
--- /dev/null
+++ b/dijit/tests/editor/robot/Editor_misc.html
@@ -0,0 +1,186 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Editor Miscellaneous Tests</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Editor.html');
+				var editor0;
+				var height;
+				var value;
+				doh.register("Miscellaneous_tests", [
+					{
+						name: "Test AutoExpanding Edtor",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("thud");
+							height = dojo.style(editor0.domNode, "height");
+							value = editor0.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor0.domNode);
+								doh.robot.mouseMoveAt(editor0.iframe, 500, null, 10, 10);
+								doh.robot.mouseClick({left:true}, 500);
+								doh.robot.keyPress(dojo.keys.ENTER, 500);
+								doh.robot.keyPress(dojo.keys.ENTER, 500);
+								doh.robot.keyPress(dojo.keys.ENTER, 500);
+								doh.robot.keyPress(dojo.keys.ENTER, 500);
+								doh.robot.keyPress(dojo.keys.ENTER, 500);
+								doh.robot.keyPress(dojo.keys.ENTER, 500);
+								doh.robot.keyPress(dojo.keys.ENTER, 500);
+								doh.robot.keyPress(dojo.keys.ENTER, 500);
+ 								doh.robot.sequence(d.getTestCallback(function(){
+									//Now check the state!
+									var newHeight = dojo.style(editor0.domNode, "height");
+									doh.assertTrue(height < newHeight);
+								}), 1000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor0){editor0.set("value", value);}
+						}
+					},
+					{
+						name: "Test font-size style migrated to editor body",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("fontSizedEditor");
+							value = editor0.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor0.domNode);
+								doh.robot.mouseMoveAt(editor0.iframe, 500, null, 10, 10);
+								doh.robot.mouseClick({left:true}, 500);
+
+ 								doh.robot.sequence(d.getTestCallback(function(){
+									//Now check the state!
+									var bStyle = editor0.document.body.style["fontSize"];
+									doh.assertTrue(bStyle != null);
+									doh.assertTrue(bStyle.toLowerCase() === "30pt");
+								}), 500);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor0){editor0.set("value", value);}
+						}
+					},
+					{
+						name: "Test prefilters do process initial content",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("filteredEditor");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor0.domNode);
+								doh.robot.mouseMoveAt(editor0.iframe, 500, null, 10, 10);
+								doh.robot.mouseClick({left:true}, 500);
+
+ 								doh.robot.sequence(d.getTestCallback(function(){
+									//Now check the state!
+									var val = editor0.get("value");
+									doh.assertTrue(val.indexOf("DOJO") >= 0);
+									doh.assertTrue(val.indexOf("notdojo") < 0)
+								}), 500);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						}
+					},
+					{
+						name: "Test placeCurorAtStart (br tag) moves input before br, not inside.",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("brEditor");
+							value = editor0.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor0.domNode);
+								doh.robot.mouseMoveAt(editor0.iframe, 500, null, 10, 10);
+								doh.robot.mouseClick({left:true}, 500);
+ 								doh.robot.sequence(function(){
+									editor0.placeCursorAtStart();
+								}, 500);
+								doh.robot.typeKeys("abc", 500);
+ 								doh.robot.sequence(d.getTestCallback(function(){
+									//Now check the state!
+									var content = editor0.get("value");
+									doh.assertTrue(content.indexOf("abc<br") >= 0);
+								}), 1000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor0){editor0.set("value", value);}
+						}
+					},
+					{
+						name: "Test custom editor content (programmatic creation).",
+						timeout: 20000,
+						setUp: function(){
+							editor0 = dijit.byId("programmatic3");
+							value = editor0.get("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								//Focus on the editor window
+								dojo.window.scrollIntoView(editor0.domNode);
+								doh.robot.mouseMoveAt(editor0.iframe, 500, null, 10, 10);
+								doh.robot.mouseClick({left:true}, 500);
+ 								doh.robot.sequence(d.getTestCallback(function(){
+									//Now check the state!
+									var content = editor0.get("value");
+									doh.assertTrue(content.indexOf("Custom Initial Content.") >= 0);
+								}), 1000);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor0){editor0.set("value", value);}
+						}
+					}
+				]);
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/editor/robot/Editor_mouse.html b/dijit/tests/editor/robot/Editor_mouse.html
new file mode 100644
index 0000000..191e1d2
--- /dev/null
+++ b/dijit/tests/editor/robot/Editor_mouse.html
@@ -0,0 +1,143 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Editor Mouse Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			function normalize(str){
+				// try to do some normalization to make all browsers look
+				// the same.   Would be nice if we didn't need this, the normalization should
+				// probably happen as pre and post filters on the editor
+				return str.
+					replace(/<br \/>$/, '').		// FF.  Because of EnterKeyHandling plugin?
+					replace(/^<p>/, '').replace(/<\/p>$/, '').		// Safari.  Because of EnterKeyHandling plugin?
+					replace(new RegExp(String.fromCharCode(160), "g"), " ");	// Safari: nbsp (char code 160) to normal space (char code 32)
+			}
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Editor.html');
+
+				// For some reason the meta key (meta-a for selection, meta-b for bold, etc) isn't working
+				// on mac... use ctrl- instead, just like on windows. (#9553)
+				var metaKey = {ctrl: true}
+
+				var editor0, editor1;
+
+				doh.register("setup", function setup(){
+					editor0 = dijit.byId("editor0");
+					editor1 = dijit.byId("editor1");
+				});
+
+				doh.register("toolbar buttons", [
+					{
+						name: "bold/italic",
+						timeout: 20000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var toolbar = editor1.toolbar,
+								boldButton = toolbar.getChildren()[7],
+								italicButton = toolbar.getChildren()[8];
+
+							dojo.window.scrollIntoView(editor1.domNode);
+
+							// Focus the editor
+							doh.robot.mouseMoveAt(editor1.editNode, 500);
+							doh.robot.mouseClick({left: true}, 500);
+							// select all
+							doh.robot.sequence(function(){
+								editor1.execCommand("SelectAll");
+							},500);
+
+							doh.robot.typeKeys("hello ", 1000);		// and erase (by typing something new)
+
+							// turn on bold
+							doh.robot.mouseMoveAt(boldButton.domNode, 500);
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.typeKeys("world", 1000);
+
+							// turn off bold
+							doh.robot.mouseMoveAt(boldButton.domNode, 500);
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.typeKeys(". ", 1000);
+
+							// turn on italic
+							doh.robot.mouseMoveAt(italicButton.domNode, 500);
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.typeKeys("how are you", 1000);
+
+							// turn off italic
+							doh.robot.mouseMoveAt(italicButton.domNode, 500);
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.typeKeys("?", 1000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Get the value and try to do some normalization to make all browsers look
+								// the same.   Would be nice if we didn't need this, the normalization should
+								// probably happen as pre and post filters on the editor
+								var val = normalize(editor1.get("value"));
+								doh.is("hello <b>world</b>. <i>how are you</i>?", val);
+							}), 5000);
+
+							return d;
+						}
+					},
+					{
+						name: "delete bold tag",
+						timeout: 20000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							
+							// Find the bolded "world" word in the editor
+							var bold=dojo.query('b',editor1.editNode);
+							if(!bold.length){
+								bold=dojo.query('strong',editor1.editNode)
+							}
+							
+							// Double-click "world" to select it
+							doh.robot.mouseMoveAt(bold[0],500,100,5,5);
+							doh.robot.mouseClick({left: true}, 500);
+							doh.robot.mouseClick({left: true}, 50);
+
+							// Delete "world" and the space before it
+							doh.robot.keyPress(dojo.keys.DELETE,500);
+							if(!dojo.isSafari&&!dojo.isChrome){
+								// they delete the space too?
+								doh.robot.keyPress(dojo.keys.BACKSPACE,500);
+							}
+	
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("hello. <i>how are you</i>?", normalize(editor1.get("value")));
+							}),500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+
+
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/editor/robot/EnterKeyHandling.html b/dijit/tests/editor/robot/EnterKeyHandling.html
new file mode 100644
index 0000000..882d92d
--- /dev/null
+++ b/dijit/tests/editor/robot/EnterKeyHandling.html
@@ -0,0 +1,269 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Editor/EnterKeyHandling Plugin Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			function dom2string(root){
+				// summary:
+				//		Simple dump of the HTML inside an editor, skipping
+				//		attributes altogether.   Similar to `dijit._editor.getNodeHtml`
+				//		(maybe want to switch to using that).
+				var out = [];
+
+				function recurse(children){
+					var i=0, node = children[i++];
+					while(node){
+						switch(node.nodeType){
+						case 1:	// normal node
+							if(node.childNodes.length){
+								out.push("<" + node.tagName.toLowerCase() + ">");
+								recurse(node.childNodes);
+								out.push("</" + node.tagName.toLowerCase() + ">");
+							}else{
+								out.push("<" + node.tagName.toLowerCase() + "/>");
+							}
+							break;
+						case 3:	// text
+							var text = dojo.trim(node.textContent || node.data).
+										replace('\u00a0', " ");
+							if(text){
+								out.push(text);
+							}
+							break;
+						}
+						node = children[i++];
+					}
+				}
+
+				recurse(root.childNodes);
+				return out.join("");
+			}
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../EnterKeyHandling.html');
+
+				// Tests for BR mode
+				if(dojo.isIE){
+					doh.register("blockNodeForEnter=BR / IE tests", [
+						{
+							name: "initial input",
+							timeout: 4000,
+							runTest: function(){
+								// The initial input was <p>para 1<br>line 2</p>  <p>para 2<br>line 2</p>,
+								// but the pre-filter should internally convert it to have a <p> for each line
+								// of text.
+								doh.is('<p>para 1</p><p>line 2</p><p> </p><p>para 2</p><p>line 2</p>',
+										dom2string(dijit.byId("br").editNode),
+										"innerHTML of editor (should have converted each line of text to a separate <p>)");
+
+								// getValue() should call the post-filter which recombines the separate <p> nodes into bigger
+								// paragraphs.
+								doh.is('<p>para 1<br />line 2</p><p>para 2<br />line 2</p>',
+										dijit.byId("br").get('value'),
+										"get('value')");
+
+								// Make sure that the post-filter didn't corrupt the data inside the editor
+								doh.is('<p>para 1</p><p>line 2</p><p> </p><p>para 2</p><p>line 2</p>',
+										dom2string(dijit.byId("br").editNode),
+										'innerHTML of editor DOM after getValue() call');
+
+								// Make sure that the margin:0 style was applied to the <p> nodes
+								var sampleP = dijit.byId("br").editNode.childNodes[0];
+								doh.is('P', sampleP.tagName, "found a P node");
+								doh.is(0, dojo.style(sampleP, "margin-top"));
+								doh.is(0, dojo.style(sampleP, "margin-bottom"));
+							}
+						},
+						/*******
+						Not currently working, see #9462
+						{
+							name: "text nodes at top level",
+							timeout: 4000,
+							runTest: function(){
+
+								var br = dijit.byId("br");
+
+								br.set("value", "<p>ab345<br>ab345<br>ab345<br>ab345<br></p>");
+
+								// Pre-filter should internally convert it to have a <p> for each line
+								// of text.
+								console.log(br.get("value"));
+								doh.is('<p>ab345</p><p>ab345</p><p>ab345</p><p>ab345</p>',
+										dom2string(dijit.byId("br").editNode),
+										"innerHTML of editor (should have converted each line of text to a separate <p>)");
+								// getValue() should call the post-filter which recombines the separate <p> nodes into bigger
+								// paragraphs.
+								doh.is('<p>ab345<br/>ab345<br/>ab345<br/>ab345</p>',
+										dijit.byId("br").get('value'),
+										"get('value')");
+							}
+						},
+						********/
+						{
+							name: "type in some text",
+							timeout: 10000,
+							runTest: function(){
+								var d = new doh.Deferred();
+
+								var br = dijit.byId("br");
+								br.set("value", "");
+								br.focus();
+
+								// tab to the MenuBar... then focus should automatically shift to "File" menu,
+								for(var i=0; i<4; i++){
+									doh.robot.typeKeys("ab345", 500);
+									i<3 && doh.robot.keyPress(dojo.keys.ENTER, 100, {});
+								}
+
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is('<p>ab345</p><p>ab345</p><p>ab345</p><p>ab345</p>',
+											dom2string(br.editNode),
+											"innerHTML of editor (should have converted each line of text to a separate <p>)");
+
+									// get('value') should call the post-filter which recombines the separate <p> nodes into bigger
+									// paragraphs.
+									doh.is('<p>ab345<br />ab345<br />ab345<br />ab345</p>',
+											br.get('value'),
+											"get('value')");
+								}), 500);
+
+								return d;
+							}
+						}
+					]);
+				}
+
+				doh.register("Split tests", [
+					{
+						name: "Test div line split",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							// The initial input was a div with a line of text with a bold tag in the middle.
+							// we want to focus on the bold and enter there, splitting it.
+							var editor = dijit.byId("div2");
+							dojo.window.scrollIntoView(editor.iframe);
+							var node = dojo.withGlobal(editor.window, function(){
+								return dojo.byId("boldLine0");
+							});
+							
+							doh.robot.mouseMoveAt(editor.iframe, 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(function(){
+                                editor._sCall("selectElementChildren", [node]);
+							}, 500);
+							
+							//Keyboard kill the selection and shift position between i and s.
+							if(!dojo.isMoz) {doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 100, {}); }
+							doh.robot.keyPress(dojo.keys.LEFT_ARROW, 100, {});
+							doh.robot.keyPress(dojo.keys.ENTER, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Do tests here.
+								var val = editor.get("value");
+								// Check that it split the is into two and that the bold and div were properly split.
+								doh.assertTrue(val.indexOf("It <b id=\"boldLine0\">i</b></div>") > 0);
+								doh.assertTrue(val.indexOf("<div><b>s</b>") > 0);
+							}), 500);
+
+							return d;
+						}
+
+					},
+					{
+						name: "Test div line split style clone",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							// The initial input was a div with a line of text with a bold tag in the middle.
+							// we want to focus on the bold and enter there, splitting it.
+							var editor = dijit.byId("div3");
+							dojo.window.scrollIntoView(editor.iframe);
+							var node = dojo.withGlobal(editor.window, function(){
+								return dojo.byId("boldLine1");
+							});
+							
+							doh.robot.mouseMoveAt(editor.iframe, 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(function(){
+                                editor._sCall("selectElementChildren", [node]);
+							}, 500);
+							
+							//Keyboard kill the selection and shift position between i and s.
+							if(!dojo.isMoz) {doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 100, {}); }
+							doh.robot.keyPress(dojo.keys.LEFT_ARROW, 100, {});
+							doh.robot.keyPress(dojo.keys.ENTER, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Do tests here.
+								var val = editor.get("value");
+								// Check that it split the is into two and that the bold and div were properly split.
+								val = val.toLowerCase();
+								doh.assertTrue(/it <b\s+id="boldline1"\s+style\s*=\s*"\s*font-size:\s*4em;?\s*">i<\/b><\/div>/.test(val));
+								doh.assertTrue(/<div><b\s+style\s*=\s*"\s*font-size:\s*4em;?\s*">s<\/b>/.test(val));
+							}), 500);
+
+							return d;
+						}
+
+					},
+					{
+						name: "Test p line split",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							// The initial input was a div with a line of text with a bold tag in the middle.
+							// we want to focus on the bold and enter there, splitting it.
+							var editor = dijit.byId("p2");
+							dojo.window.scrollIntoView(editor.iframe);
+							var node = dojo.withGlobal(editor.window, function(){
+								return dojo.byId("boldLine2");
+							});
+							
+							doh.robot.mouseMoveAt(editor.iframe, 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(function(){
+                                editor._sCall("selectElementChildren", [node]);
+							}, 500);
+							
+							//Keyboard kill the selection and shift position between i and s.
+							if(!dojo.isMoz) {doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 100, {}); }
+							doh.robot.keyPress(dojo.keys.LEFT_ARROW, 100, {});
+							doh.robot.keyPress(dojo.keys.ENTER, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Do tests here.
+								var val = editor.get("value");
+								// Check that it split the is into two and that the bold and div were properly split.
+								doh.assertTrue(val.indexOf("It <b id=\"boldLine2\">i</b></p>") > 0);
+								doh.assertTrue(val.indexOf("<p><b>s</b>") > 0);
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/editor/runTests.html b/dijit/tests/editor/runTests.html
new file mode 100755
index 0000000..932a6e9
--- /dev/null
+++ b/dijit/tests/editor/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+	<head>
+	<title>Dijit Unit Test Runner</title>
+	<meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dijit.tests.editor.module"></HEAD>
+	<BODY>
+		Redirecting to D.O.H runner.
+	</BODY>
+</HTML>
diff --git a/dijit/tests/editor/sample.jpg b/dijit/tests/editor/sample.jpg
new file mode 100755
index 0000000..53422b3
Binary files /dev/null and b/dijit/tests/editor/sample.jpg differ
diff --git a/dijit/tests/editor/sample2.jpg b/dijit/tests/editor/sample2.jpg
new file mode 100755
index 0000000..2767c0a
Binary files /dev/null and b/dijit/tests/editor/sample2.jpg differ
diff --git a/dijit/tests/editor/test_CustomPlugin.html b/dijit/tests/editor/test_CustomPlugin.html
new file mode 100644
index 0000000..dec73f3
--- /dev/null
+++ b/dijit/tests/editor/test_CustomPlugin.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Custom Plugin Test/Tutorial</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<style>
+		.customIconHtmlToggle {
+			background-image: url('customIcon.gif'); /* custom editor icons sprite image */
+			background-repeat: no-repeat;
+			width: 18px;
+			height: 18px;
+			text-align: center;
+		}
+	</style>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		dojo.require("dijit._Widget");
+		dojo.require("dijit._Templated");
+		dojo.require("dijit._editor._Plugin");
+		dojo.require("dojo.string");
+
+		dojo.declare("MyPlugin",
+			dijit._editor._Plugin,
+			{
+				buttonClass: dijit.form.ToggleButton,
+				useDefaultCommand: false,
+
+				_initButton: function(){
+					this.command = "htmlToggle";
+					this.editor.commands[this.command] = "View HTML source"; // note: should be localized
+					this.iconClassPrefix = "customIcon";
+					this.inherited(arguments);
+					delete this.command; // kludge so setEditor doesn't make the button invisible
+					this.connect(this.button, "onClick", this._toggleSource);
+				},
+
+				destroy: function(f){
+					this.inherited(arguments);
+					if(this.sourceArea){ dojo.destroy(this.sourceArea); }
+				},
+
+				_toggleSource: function(){
+					this.source = !this.source;
+					if(!this.sourceArea){
+						this.sourceArea = dojo.doc.createElement('textarea');
+						this.sourceArea.style.position = 'absolute';
+						dojo.place(this.sourceArea, this.editor.domNode, "last");
+					}
+					if(this.source){
+						this.sourceArea.value = this.editor.getValue();
+						dojo.marginBox(this.sourceArea, dojo.marginBox(this.editor.editingArea));
+					}else{
+						this.editor.setValue(this.sourceArea.value);
+						this.sourceArea.style.top = "-999px";
+					}
+
+					this.editor.set('disabled', this.source); // conditionally disable toolbar -- FIXME. Doesn't work.
+					this.button.set('label', this.source ? "View WYSIWYG" : this.editor.commands[this.command]); // note: should be localized
+				}
+			}
+		);
+
+		/* the following code registers my plugin */
+		dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+			if(o.plugin){ return; }
+			if(o.args.name == "MyPlugin"){
+				return new MyPlugin({});
+			}
+		});
+	</script>
+</head>
+<body class="claro">
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['MyPlugin']"><p>
+	This editor should have my custom plugin
+	</p></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/dijit/tests/editor/test_Editor.html b/dijit/tests/editor/test_Editor.html
new file mode 100644
index 0000000..b1fe5b9
--- /dev/null
+++ b/dijit/tests/editor/test_Editor.html
@@ -0,0 +1,208 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor._Plugin");
+		dojo.require("dijit._editor.plugins.AlwaysShowToolbar");
+		dojo.require("dijit._editor.plugins.FontChoice");  // 'fontName','fontSize','formatBlock'
+		dojo.require("dijit._editor.plugins.TextColor");
+		dojo.require("dijit._editor.plugins.LinkDialog");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		// Dummy simple plugin for testing that filters registered this way work
+		// properly with content setting on load.
+		dojo.declare("dijit.tests.editor.TestFilter", [dijit._editor._Plugin], {
+			setEditor: function(editor){
+				this.editor = editor;
+				this.editor.contentPreFilters.push(function(val){
+					if(val){
+						val = val.replace("notdojo", "DOJO");
+					}
+					return val;
+				});
+			}
+		});
+
+		dojo.addOnLoad(function(){
+			var progEditor = new dijit.Editor({
+				value: "Custom Initial Content."
+			}, "programmatic3");
+
+		});
+
+	</script>
+</head>
+
+<body class="claro">
+	<div dojoType="dijit.Editor" id="automated" height="1.5em" plugins="[]" focusOnLoad="true" style="border:0px;"
+	>Automated Test - all check boxes should be checked<script type='dojo/method' event='onFocus'>
+			if(!document.getElementById('onFocusFired').checked){
+				document.getElementById('onFocusFired').checked=true;
+				document.getElementById('initialValueOK').checked = (dijit.byId('automated').getValue() == 'Automated Test - all check boxes should be checked');
+				dijit.byId('automated').document.execCommand('selectall', false, false);
+				document.getElementById('onChangeOKnow').checked=true;
+				dijit.byId('automated').document.execCommand('underline', false, false);
+				setTimeout(dojo.hitch(dijit.byId('editor0'),"focus",0));
+			}
+		</script
+		><script type='dojo/method' event='onBlur'>
+			if(!document.getElementById('onBlurFired').checked){
+				document.getElementById('onBlurFired').checked=true;
+				dijit.byId('automated').set('disabled', true);
+				setTimeout(function(){ try {
+					dijit.byId('automated').document.execCommand('bold', false, false);
+					document.getElementById('disabledOK').checked = (dijit.byId('automated').document.queryCommandState('bold') == false);
+				} catch(e) { document.getElementById('disabledOK').checked = true; }}, 0);
+			}
+		</script
+		><script type='dojo/method' event='onChange'>
+			if(document.getElementById('onChangeOKnow').checked && !document.getElementById('onChangeFired').checked){
+				document.getElementById('onChangeFired').checked=true;
+			}
+		</script
+	></div>
+	Focus:<input type="checkbox" id="onFocusFired" disabled autoComplete="off">
+	Value:<input type="checkbox" id="initialValueOK" disabled autoComplete="off">
+	<input type="checkbox" id="onChangeOKnow" disabled autoComplete="off" style="display:none;">
+	Change:<input type="checkbox" id="onChangeFired" disabled autoComplete="off">
+	Blur:<input type="checkbox" id="onBlurFired" disabled autoComplete="off">
+	Disabled:<input type="checkbox" id="disabledOK" disabled autoComplete="off">
+	<br>
+	<br>
+
+	<h1 class="testTitle"><label for="editor1">Editor + Plugins Test</label></h1>
+
+	<h2>No plugins, initially empty</h2>
+	<div dojoType="dijit.Editor" id="editor0" height="100" plugins="[]"></div>
+
+	<h2>Created from div</h2>
+	<input id="focusBefore" value="input before editor1">
+	<div dojoType="dijit.Editor" id="editor1" disableSpellCheck="true"
+		onChange="console.log('editor1 onChange handler: ' + arguments[0])"
+	><p>This instance is created from a div directly with default toolbar and plugins</p>
+	The following HTML should appear as source: <INPUT TYPE="IMAGE" SRC="javascript:alert('no scripting attacks')">
+	</div>
+	<input id="focusAfter" value="input after editor1">
+	<button onClick="dijit.byId('editor1').destroy()">destroy</button>
+	<button onClick="dijit.byId('editor1').set('disableSpellCheck', !dijit.byId('editor1').get('disableSpellCheck'))">toggle spell check</button>
+	<button onclick="console.log(dijit.byId('editor1').get('value'))">getValue</button>
+	<hr/>
+
+	<h2>Created from div, auto-expanding</h2>
+	<h3><label for="thud">label for editor:</label></h3>
+	<div dojoType="dijit.Editor" height="" minHeight="75px"
+		onChange="console.log('thud onChange handler: ' + arguments[0])"
+		extraPlugins="['dijit._editor.plugins.AlwaysShowToolbar']"
+		styleSheets="../../../dojo/resources/dojo.css" id="thud">
+		Extra text
+		<p>
+			This editor is created from a div with AlwaysShowToolbar plugin (do not forget to set height="").
+		</p>
+		<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+			porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+			Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+			Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+			risus.
+		</p>
+		The following HTML should appear as source: <INPUT TYPE="IMAGE" SRC="javascript:alert('no scripting attacks')">
+	</div>
+	<h3>..after</h3>
+	<hr/>
+
+	<h2>Optional toolbar buttons</h2>
+	<h3><label for="blah">blah entry</label></h3>
+	<div dojoType="dijit.Editor"
+		plugins="['bold','italic','|','createLink','foreColor','hiliteColor',{name:'dijit._editor.plugins.FontChoice', command:'fontName', generic:true},'fontSize','formatBlock','insertImage','insertHorizontalRule']"
+		styleSheets="../../../dojo/resources/dojo.css" id="blah">
+		This instance includes optional toolbar buttons which pull in additional ui (dijit) code.
+		Note the dojo.require() statements required to pull in the associated editor plugins to make
+		this work.
+		<br>
+		<span style="font-family: serif">This is serif.</span>
+		<br>
+		<span style="font-family: sans-serif">This is sans-serif.</span>
+		<br>
+		<span style="font-family: monospace">This is monospace.</span>
+		<br>
+		<span style="font-family: cursive">This is cursive.</span>
+		<br>
+		<span style="font-family: fantasy">This is fantasy.</span>
+		<br>
+	</div>
+	<h3>..after</h3>
+	<button onclick="alert(dijit.byId('blah').get('value'));">getValue</button>
+	<hr/>
+
+	<h2>Plugins specified</h2>
+	<h3><label for="blah2">Another blah entry</label></h3>
+	<div dojoType="dijit.Editor"
+		plugins="['bold','italic','|',{name:'dijit._editor.plugins.FontChoice', command:'fontName', custom:['Verdana','Myriad','Garamond','Apple Chancery','Hiragino Mincho Pro']}, {name:'dijit._editor.plugins.FontChoice', command:'fontSize', custom:[3,4,5]}, {name:'dijit._editor.plugins.EnterKeyHandling', blockNodeForEnter:'DIV'}]"
+		styleSheets="../../../dojo/resources/dojo.css" id="blah2">
+		This instance demos how to:
+		<ol>
+			<li>specify which plugins to load (see the plugins property): this instance loads FontChoice plugin, among others;</li>
+			<li>specify options for a plugin (see the last item in the plugins array)</li>
+		</ol>
+	</div>
+	<h3>..after</h3>
+	<hr/>
+
+	<h2>Font sizing via style</h2> 
+	<div dojoType="dijit.Editor" style="text-align:left; font-size:30pt" id="fontSizedEditor"> 
+		Hello World! 
+	</div> 
+
+	<h2>Checking pre-filter application</h2> 
+	<div dojoType="dijit.Editor" id="filteredEditor" extraPlugins="[{name: 'dijit.tests.editor.TestFilter'}]"> 
+		notdojo 
+	</div> 
+
+	<h2>Checking editor starting with br</h2> 
+	<div dojoType="dijit.Editor" id="brEditor"> 
+		<br>
+		some stuff
+		<br>
+		some other stuff. 
+	</div> 
+
+	<h2>Programmatic creation</h2>
+	<div id="programmatic">This div will become an editor.</div>
+	<button
+		id="create"
+		onclick="new dijit.Editor({}, dojo.byId('programmatic')); dojo.query('#create').orphan();">
+	create static editor
+	</button>
+	<div id="programmatic2">This div will become an auto-expanding editor.</div>
+	<button
+		id="create2"
+		onclick="new dijit.Editor({height: '', extraPlugins: ['dijit._editor.plugins.AlwaysShowToolbar']}, dojo.byId('programmatic2')); dojo.query('#create2').orphan();">
+	create expanding editor
+	</button>
+
+	<br><br>    
+	<div id="programmatic3">This div will become a programmatic editor in addOnLoad with creation-defined default content.</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/test_FontChoice.html b/dijit/tests/editor/test_FontChoice.html
new file mode 100755
index 0000000..bb302a3
--- /dev/null
+++ b/dijit/tests/editor/test_FontChoice.html
@@ -0,0 +1,144 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test: FontChoice Plugin</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.FontChoice");
+		dojo.require("dijit._editor.plugins.ViewSource");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro">
+	<br>
+	<br>
+	<div>Content before the editor.</div>
+	<br>
+	<br>
+	<p>Editor with default drop down lists:</p>
+	<div dojoType="dijit.Editor"
+		extraPlugins="['fontName', 'fontSize', 'formatBlock', 'viewSource']" style="background-color: white; width: 100% height: 400px;" id="editor0">
+		<h1>Font Choice Plugin details</h1>
+		<ol>
+			<li>The Fontchoice plugin provides three dropdown menus for manipulating font information, such as
+				font name, font size, and the format of the block containing the text (such as P, PRE, H1, and so on)</li>
+			<li>It auto-updates itself based on the caret and selection position in the document.</li>
+		</ol>
+
+		<h2>Things to test:</h2>
+		<ol>
+			<li>Verify clicking in a P tag shows Paragraph in the dropdown.</li>
+			<li>Verify clicking in a a font-sized tag that the size dropdown indicates the current size (via a name).</li>
+			<li>Verify clicking in a a font-nameed tag that the name dropdown indicates the current font name.</li>
+			<li>Verify that you can set/manipulate all the above via the menu.</li>
+		</ol>
+		<br>
+		<p id="para0">
+			This is a pararaph.
+		</p>
+		<br>
+		<pre id="pre0">
+			This is preformatted text.
+		</pre>
+		<br>
+		<h1 id="h10">
+			This is a heading.
+		</h1>
+		<h2 id="h20">
+			This is a sub-heading.
+		</h2>
+		<h3 id="h30">
+			This is a sub-sub-heading.
+		</h3>
+        <br>
+		<p id="text">This is some text in a 'p' for styling.</p>
+		<p id="text1">This is some more text in a 'p' for styling.</p>
+		<br>
+		<font id="sizedText1" size="1">This is some small text.</font>
+		<br>
+		<font id="sizedText4" size="4">This is some mediumish text.</font>
+		<br>
+		<font id="sizedText7" size="7">This is some xx-large text.</font>
+		<br>
+		<font face="'Comic Sans MS'" id="comicText">This is some text in 'Comic Sans MS'</font>.
+		<br>
+		<br>
+		<br>
+		<h1 style="background-color: lightgray">Selection format removal test</h1>
+		<div id="selectionContainer">
+			<h3>
+				Some H3 formatted content.
+			</h3>
+			<pre>
+				Some PRE formatted content.
+			</pre>
+			<p>
+				Some P formatted content.
+			</p>
+		</div>
+
+	</div>
+	<br>
+	<br>
+	<div>Content after the editor.</div>
+	<br>
+	<br>
+	<div>Content before the editor.</div>
+	<br>
+	<br>
+	<p>Editor w/ plain text dropdown values:</p>
+	<div dojoType="dijit.Editor"
+		extraPlugins="[{name: 'fontName', plainText: true}, {name: 'fontSize', plainText: true}, {name: 'formatBlock', plainText: true}, 'viewSource']" style="background-color: white; width: 100%; height: 400px;" id="editor1">
+		<h1>Font Choice Plugin details</h1>
+		<ol>
+			<li>This instance of the FontChoice plugin just turns off formatted content in the dropdowns.  Everything should be the same font and size.</li>
+		</ol>
+
+		<h2>Things to test:</h2>
+		<ol>
+			<li>Verify that each of the dropdowns have values that are all the same size and font.</li>
+		</ol>
+	</div>
+	<br>
+	<br>
+	<div>Content after the editor.</div>
+	<br>
+	<br>
+	<p>Editor w/ generic (web font names) font selector, traditional font name selector, font size selector, and format block selector:</p>
+	<div dojoType="dijit.Editor" id="generic" height="10em"
+		plugins="['bold', 'italic', 'underline', {name: 'dijit._editor.plugins.FontChoice', command: 'fontName', generic: true}, 'fontName', 'fontSize', 'formatBlock']">hello world</div>
+	<br>
+	<br>
+	<div>Content after the editor.</div>
+	<br>
+	<br>
+	<div>Content before the editor.</div>
+	<br>
+	<br>
+	<p>Editor w/ custom font drop down list:</p>
+	<div dojoType="dijit.Editor" id="custom" height="10em"
+		plugins="['bold', 'italic', 'underline', {name: 'dijit._editor.plugins.FontChoice', command: 'fontName', custom:['Verdana','Myriad','Garamond']}]">
+			This editor should let you set the fonts to
+			<font face="Verdana">Verdana</font>, <font face="Myriad">Myriad</font>, and <font face="Garamond">Garamond</font>.
+	</div>
+	<br>
+	<br>
+	<div>Content after the editor.</div>
+	<br>
+	<br>
+</body>
+</html>
diff --git a/dijit/tests/editor/test_FullScreen.html b/dijit/tests/editor/test_FullScreen.html
new file mode 100755
index 0000000..c2cb827
--- /dev/null
+++ b/dijit/tests/editor/test_FullScreen.html
@@ -0,0 +1,208 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test: FullScreen Plugin</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.FullScreen");
+		dojo.require("dijit._editor.plugins.ViewSource");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.StackContainer");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro">
+	<br>
+	<br>
+	<div>Content before the editor.</div>
+	<br>
+	<br>
+	<div dojoType="dijit.Editor"
+		extraPlugins="['fullscreen']" style="background-color: white; width: 800px; height: 400px;" id="editor0">
+		<h1>Full Screen Plugin details</h1>
+		<ol>
+			<li>The Fullscreen plugin provides an extra button on the toolbar to allow switching the
+				editor into 'full screen' mode, meaning the editor takes over the viewport of the
+				browser.   This plugin is particularly useful when editing large documents.</li>
+			<li>The mode can also be toggled by entering the key command: CTRL-SHIFT-F11
+				in the editor pane.</li>
+			<li>When it toggled to full screen, it makes
+				the editor text pane opaque white so that the contents behind it are not visible.</li>
+			<li>When in full screen mode, the plugin attempts to capture the TAB key and allow navigation only between
+				the editor toolbar and the editing area, as when in full screen mode, the rest of the page is hidden
+				behind the editor.</li>
+		</ol>
+
+		<h2>Things to test:</h2>
+		<ol>
+			<li>Verify that clicking the full screen icon highlights the button appropriately and toggles the full screen mode on.</li>
+			<li>Verify that clicking the full screen icon again dehighlites the button and toggles the full screen mode off.</li>
+			<li>Click in the editing pane and verify that CTRL-SHIFT-F11 toggles the full screen mode on and off.</li>
+			<li>Verify while in full screen mode that TAB seems to behave appropriately.  Please note that FireFox and Internet
+				Explorer work the best here.  There are still a few tab control issues in Safari and Chrome.</li>
+		</ol>
+	</div>
+	<br>
+	<br>
+	<div>Content after the editor.</div>
+	<br>
+	<h1>BorderContainer with center region containing editor.</h1>
+	<div dojoType="dijit.layout.BorderContainer" id="bc" style="width: 600px; height: 500px;">
+		<div dojoType="dijit.layout.ContentPane" region="left" style="width: 50px;">left</div>
+		<div dojoType="dijit.layout.ContentPane" region="top" style="height: 50px;">top</div>
+		<div dojoType="dijit.layout.ContentPane" region="right" style="width: 50px;">right</div>
+		<div dojoType="dijit.layout.ContentPane" region="bottom" style="height: 50px;">bottom</div>
+		<div dojoType="dijit.layout.ContentPane" region="center">
+			<div dojoType="dijit.Editor" extraPlugins="['fullscreen','viewsource']" id="editor1" height="100%">
+				<h1>Full Screen Plugin details</h1>
+				<ol>
+					<li>The Fullscreen plugin provides an extra button on the toolbar to allow switching the
+						editor into 'full screen' mode, meaning the editor takes over the viewport of the
+						browser.   This plugin is particularly useful when editing large documents.</li>
+					<li>The mode can also be toggled by entering the key command: CTRL-SHIFT-F11
+						in the editor pane.</li>
+					<li>When it toggled to full screen, it makes
+						the editor text pane opaque white so that the contents behind it are not visible.</li>
+					<li>When in full screen mode, the plugin attempts to capture the TAB key and allow navigation only between
+						the editor toolbar and the editing area, as when in full screen mode, the rest of the page is hidden
+						behind the editor.</li>
+				</ol>
+		
+				<h2>Things to test:</h2>
+				<ol>
+					<li>Verify that clicking the full screen icon highlights the button appropriately and toggles the full screen mode on.</li>
+					<li>Verify that clicking the full screen icon again dehighlites the button and toggles the full screen mode off.</li>
+					<li>Click in the editing pane and verify that CTRL-SHIFT-F11 toggles the full screen mode on and off.</li>
+					<li>Verify while in full screen mode that TAB seems to behave appropriately.  Please note that FireFox and Internet
+						Explorer work the best here.  There are still a few tab control issues in Safari and Chrome.</li>
+				</ol>
+			</div>
+		</div>
+	</div>
+	<br>
+	<h1>TabContainer with tab containing editor.</h1>
+	<div dojoType="dijit.layout.TabContainer" id="tc" style="width: 600px; height: 500px; border-style: solid; border-width: 1px; padding: 0px; margin: 0px;">
+		<div dojoType="dijit.layout.ContentPane" title="Editor Tab">
+			<div dojoType="dijit.Editor" extraPlugins="['fullscreen','viewsource']" id="editor2" height="100%">
+				<h1>Full Screen Plugin details</h1>
+				<ol>
+					<li>The Fullscreen plugin provides an extra button on the toolbar to allow switching the
+						editor into 'full screen' mode, meaning the editor takes over the viewport of the
+						browser.   This plugin is particularly useful when editing large documents.</li>
+					<li>The mode can also be toggled by entering the key command: CTRL-SHIFT-F11
+						in the editor pane.</li>
+					<li>When it toggled to full screen, it makes
+						the editor text pane opaque white so that the contents behind it are not visible.</li>
+					<li>When in full screen mode, the plugin attempts to capture the TAB key and allow navigation only between
+						the editor toolbar and the editing area, as when in full screen mode, the rest of the page is hidden
+						behind the editor.</li>
+				</ol>
+		
+				<h2>Things to test:</h2>
+				<ol>
+					<li>Verify that clicking the full screen icon highlights the button appropriately and toggles the full screen mode on.</li>
+					<li>Verify that clicking the full screen icon again dehighlites the button and toggles the full screen mode off.</li>
+					<li>Click in the editing pane and verify that CTRL-SHIFT-F11 toggles the full screen mode on and off.</li>
+					<li>Verify while in full screen mode that TAB seems to behave appropriately.  Please note that FireFox and Internet
+						Explorer work the best here.  There are still a few tab control issues in Safari and Chrome.</li>
+				</ol>
+			</div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Blank Tab 1">
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Blank Tab 2">
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Blank Tab 3">
+		</div>
+	</div>
+	<br>
+	<h1>AccordionContainer with pane containing editor.</h1>
+	<div dojoType="dijit.layout.AccordionContainer" id="ac" style="width: 600px; height: 500px; border-style: solid; border-width: 1px; padding: 0px; margin: 0px;">
+		<div dojoType="dijit.layout.ContentPane" title="Editor Pane">
+			<div dojoType="dijit.Editor" extraPlugins="['fullscreen','viewsource']" id="editor3" height="100%">
+				<h1>Full Screen Plugin details</h1>
+				<ol>
+					<li>The Fullscreen plugin provides an extra button on the toolbar to allow switching the
+						editor into 'full screen' mode, meaning the editor takes over the viewport of the
+						browser.   This plugin is particularly useful when editing large documents.</li>
+					<li>The mode can also be toggled by entering the key command: CTRL-SHIFT-F11
+						in the editor pane.</li>
+					<li>When it toggled to full screen, it makes
+						the editor text pane opaque white so that the contents behind it are not visible.</li>
+					<li>When in full screen mode, the plugin attempts to capture the TAB key and allow navigation only between
+						the editor toolbar and the editing area, as when in full screen mode, the rest of the page is hidden
+						behind the editor.</li>
+				</ol>
+		
+				<h2>Things to test:</h2>
+				<ol>
+					<li>Verify that clicking the full screen icon highlights the button appropriately and toggles the full screen mode on.</li>
+					<li>Verify that clicking the full screen icon again dehighlites the button and toggles the full screen mode off.</li>
+					<li>Click in the editing pane and verify that CTRL-SHIFT-F11 toggles the full screen mode on and off.</li>
+					<li>Verify while in full screen mode that TAB seems to behave appropriately.  Please note that FireFox and Internet
+						Explorer work the best here.  There are still a few tab control issues in Safari and Chrome.</li>
+				</ol>
+			</div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Blank Pane 1">
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Blank Pane 2">
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Blank Pane 3">
+		</div>
+	</div>
+	<br>
+	<h1>StackContainer with pane containing editor.</h1>
+	<div dojoType="dijit.layout.StackContainer" id="sc" style="width: 600px; height: 500px; border-style: solid; border-width: 1px; padding: 0px; margin: 0px;">
+		<div dojoType="dijit.layout.ContentPane" title="Editor Pane">
+			<div dojoType="dijit.Editor" extraPlugins="['fullscreen','viewsource']" id="editor4" height="100%">
+				<h1>Full Screen Plugin details</h1>
+				<ol>
+					<li>The Fullscreen plugin provides an extra button on the toolbar to allow switching the
+						editor into 'full screen' mode, meaning the editor takes over the viewport of the
+						browser.   This plugin is particularly useful when editing large documents.</li>
+					<li>The mode can also be toggled by entering the key command: CTRL-SHIFT-F11
+						in the editor pane.</li>
+					<li>When it toggled to full screen, it makes
+						the editor text pane opaque white so that the contents behind it are not visible.</li>
+					<li>When in full screen mode, the plugin attempts to capture the TAB key and allow navigation only between
+						the editor toolbar and the editing area, as when in full screen mode, the rest of the page is hidden
+						behind the editor.</li>
+				</ol>
+		
+				<h2>Things to test:</h2>
+				<ol>
+					<li>Verify that clicking the full screen icon highlights the button appropriately and toggles the full screen mode on.</li>
+					<li>Verify that clicking the full screen icon again dehighlites the button and toggles the full screen mode off.</li>
+					<li>Click in the editing pane and verify that CTRL-SHIFT-F11 toggles the full screen mode on and off.</li>
+					<li>Verify while in full screen mode that TAB seems to behave appropriately.  Please note that FireFox and Internet
+						Explorer work the best here.  There are still a few tab control issues in Safari and Chrome.</li>
+				</ol>
+			</div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Blank Pane 1">
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Blank Pane 2">
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Blank Pane 3">
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/test_LinkDialog.html b/dijit/tests/editor/test_LinkDialog.html
new file mode 100755
index 0000000..02b8e0e
--- /dev/null
+++ b/dijit/tests/editor/test_LinkDialog.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test: LinkDialog Plugin</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.LinkDialog");
+		dojo.require("dijit._editor.plugins.ViewSource");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro">
+	<div style="border: 1px dotted black;">
+		<div dojoType="dijit.Editor" id="editor"
+			extraPlugins="['createLink', 'insertImage', 'viewSource']">
+			<ol>
+				<li>The LinkDialog plugin is an 'example' style plugin that shows how to insert basic web links as well as
+				image tags.  This plugin is intended to guide users in qriting their own, more complex, link and image handlers
+				while still providing useful function.</li>
+			</ol>
+			<br>
+			<div><a href="http://www.example.com/example.html" target="_top" id="exampleLink">This is an example link in the page.</a></div>
+			<br>
+			<br>
+			<div><img src="./sample.jpg" alt="Sample Image" id="exampleImage" /></div>
+			<br>
+			<br>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/test_NewPage.html b/dijit/tests/editor/test_NewPage.html
new file mode 100755
index 0000000..96d0af4
--- /dev/null
+++ b/dijit/tests/editor/test_NewPage.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test: New Page Plugin</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.NewPage");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro">
+	<br>
+	<br>
+	<div>Content before the editor.</div>
+	<br>
+	<br>
+	<div dojoType="dijit.Editor"
+		extraPlugins="['newpage']" style="background-color: white; width: 800px;" height="400px" id="editor0">
+		<h1>New Page Plugin details</h1>
+		<ol>
+			<li>The new page plugin is a small plugin that adds the capability of making a 'new page'.  In other words
+			replacing all the content of the editor with some default text.  This also usually kills any undo that had been saved.</li>
+		</ol>
+
+		<h2>Things to test:</h2>
+		<ol>
+			<li>Verify that clicking the new page button clears the editor contents.</li>
+		</ol>
+	</div>
+	<br>
+	<br>
+	<div dojoType="dijit.Editor"
+		extraPlugins="[{name: 'newpage', content: '<p>This page intentionally left blank</p>'}]" style="background-color: white; width: 800px;" height="400px" id="editor1">
+		<h1>New Page Plugin details</h1>
+		<ol>
+			<li>The new page plugin is a small plugin that adds the capability of making a 'new page'.  In other words
+			replacing all the content of the editor with some default text.  This also usually kills any undo that had been saved.</li>
+		</ol>
+
+		<h2>Things to test:</h2>
+		<ol>
+			<li>Verify that clicking the new page button sets the content to: <p>This page intentionally left blank</p></li>
+		</ol>
+	</div>
+	<br>
+	<br>
+	<div>Content after the editor.</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/test_Print.html b/dijit/tests/editor/test_Print.html
new file mode 100755
index 0000000..c2d6a89
--- /dev/null
+++ b/dijit/tests/editor/test_Print.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test: Print  Plugin</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.Print");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro">
+	<br>
+	<br>
+	<div>Content before the editor.</div>
+	<br>
+	<br>
+	<div dojoType="dijit.Editor"
+		extraPlugins="['print']" style="background-color: white; width: 800px; height: 400px;" id="editor0">
+		<h1>Print Plugin details</h1>
+		<ol>
+			<li>The print plugin is a small plugin that adds the capability of printing the document in the editor</li>
+			<li>If the underlying browser doesn't support print, then the button will be disabled by default</li>
+		</ol>
+
+		<h2>Things to test (manually, because of the print dialog, the function test cannot be automated):</h2>
+		<ol>
+			<li>Verify that clicking the print button opns the browser print dialog and the document will print.</li>
+			<li>Verify that the printed document is only the document in the editor, not the whole page.</li>
+		</ol>
+	</div>
+	<br>
+	<br>
+	<div>Content after the editor.</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/test_RichText.html b/dijit/tests/editor/test_RichText.html
new file mode 100644
index 0000000..51b1948
--- /dev/null
+++ b/dijit/tests/editor/test_RichText.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Rich Text System Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript" src="../../_editor/selection.js"></script>
+	<script type="text/javascript" src="../../_editor/RichText.js"></script>
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit._editor.RichText");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+
+</head>
+<body>
+
+	<h1 class="testTitle">Rich Text Test</h1>
+
+	<div style="border: 1px dotted black;">
+		<h3>thud</h3>
+		<textarea dojoType="dijit._editor.RichText" id="editor1"
+			styleSheets="../../../dojo/resources/dojo.css">
+			<h1>header one</h1>
+			<ul>
+				<li>Right click on the client area of the page (ctrl-click for Macintosh). Menu should open.</li>
+				<li>Right click on each of the form controls above. Menu should open.</li>
+				<li>Right click near the righthand window border. Menu should open to the left of the pointer.</li>
+				<li>Right click near the bottom window border. Menu should open above the pointer.</li>
+			</ul>
+		</textarea>
+		<button onclick="dijit.byId('editor1').addStyleSheet('test_richtext.css')">add stylesheet</button>
+		<button onclick="dijit.byId('editor1').removeStyleSheet('test_richtext.css')">remove stylesheet</button>
+	</div>
+
+	<div style="border: 1px dotted black;">
+		<h3>blah</h3>
+		<div dojoType="dijit._editor.RichText"
+			styleSheets="../../dojo/resources/dojo.css">
+			<ul>
+				<li>Right click on the client area of the page (ctrl-click for Macintosh). Menu should open.</li>
+				<li>Right click on each of the form controls above. Menu should open.</li>
+				<li>Right click near the righthand window border. Menu should open to the left of the pointer.</li>
+				<li>Right click near the bottom window border. Menu should open above the pointer.</li>
+			</ul>
+		</div>
+		<h3>..after</h3>
+	</div>
+
+</body>
+</html>
diff --git a/dijit/tests/editor/test_TabIndent.html b/dijit/tests/editor/test_TabIndent.html
new file mode 100644
index 0000000..dcf22b5
--- /dev/null
+++ b/dijit/tests/editor/test_TabIndent.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor TabIndent Plugin Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<script type="text/javascript" src="../_testCommon.js"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.TabIndent");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro">
+	<p>Paragraph with focusable <span tabindex="0" style="color:blue">item </span>before editor. </p>
+	<label for="tiTest">Test TabIndent Plugin</label>
+	<div style="border: 1px dotted black;">
+	
+		<div id="tiTest" dojoType="dijit.Editor"
+			extraPlugins="['tabIndent','|','dijit._editor.plugins.TabIndent','|',{name:'dijit._editor.plugins.TabIndent'}]">
+			<p>
+				<ol>
+				<li>the tabIndent plugin allows the use of the tab and shift-tab keys to
+indent list items.</li>
+				<li>another list element</li>
+				<li>and another</li>
+				<li>still one more</li>
+				</ol>
+			</p>
+			<p>
+				Ctrl-M also turns tab indent on/off.
+				(The buttons should change checked status when the user types
+				Ctrl-M, to indicate whether tab and shift-tab is enabled.)
+			</p>
+		</div>
+	</div>
+	<p>Paragraph with focusable <span tabindex="0" style="color:blue">item </span>after editor. </p>
+</body>
+</html>
diff --git a/dijit/tests/editor/test_ToggleDir.html b/dijit/tests/editor/test_ToggleDir.html
new file mode 100644
index 0000000..6200b7a
--- /dev/null
+++ b/dijit/tests/editor/test_ToggleDir.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test: ToggleDir Plugin</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.ToggleDir");
+		dojo.require("dijit._editor.plugins.TabIndent");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro">
+	<div style="border: 1px dotted black;">
+		<div dojoType="dijit.Editor"
+			extraPlugins="['toggleDir','|','dijit._editor.plugins.ToggleDir','|',{name:'dijit._editor.plugins.ToggleDir'}]">
+			<ol>
+				<li>the toggleDir plugin provides an extra button on the toolbar to switch text direction (BiDi) of the
+					edited document.  Useful when right-to-left languages like Hebrew and Arabic are combined with
+					left-to-right languages like English.</li>
+			</ol>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/test_ToggleDir_rtl.html b/dijit/tests/editor/test_ToggleDir_rtl.html
new file mode 100755
index 0000000..66483bb
--- /dev/null
+++ b/dijit/tests/editor/test_ToggleDir_rtl.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test: ToggleDir Plugin (page in RTL)</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.ToggleDir");
+		dojo.require("dijit._editor.plugins.TabIndent");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro" dir="rtl">
+	<div style="border: 1px dotted black;">
+		<div dojoType="dijit.Editor"
+			extraPlugins="['toggleDir','|','dijit._editor.plugins.ToggleDir','|',{name:'dijit._editor.plugins.ToggleDir'}]">
+			<ol>
+				<li>the toggleDir plugin provides an extra button on the toolbar to switch text direction (BiDi) of the
+					edited document.  Useful when right-to-left languages like Hebrew and Arabic are combined with
+					left-to-right languages like English.</li>
+			</ol>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/test_ViewSource.html b/dijit/tests/editor/test_ViewSource.html
new file mode 100755
index 0000000..14e6790
--- /dev/null
+++ b/dijit/tests/editor/test_ViewSource.html
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Test: ViewSource Plugin</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!--<script type="text/javascript" src="../_testCommon.js"></script>-->
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.ViewSource");
+		dojo.require("dijit._editor.plugins.FullScreen");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro">
+	<br>
+	<br>
+	<div>Content before the editors.</div>
+	<br>
+	<br>
+	<div>
+		<div dojoType="dijit.Editor"
+			extraPlugins="['viewsource']" style="background-color: white; width: 800px;" height="400px" id="editor0">
+			<h1>ViewSource Plugin details</h1>
+			<ol>
+				<li>The ViewSource plugin provides an extra button on the toolbar to allow switching the
+					editor from WSYIWYG editing to into HTML source mode editing in the browser.
+					This plugin is particularly useful when needing to tweak generated HTML source.</li>
+				<li>The mode can also be toggled by entering the key command: CTRL-SHIFT-F12
+					in the editor pane.</li>
+				<li>When it toggled it makes the edit area either a textarea if editing is enabled, or a readonly TEXTAREA node
+					if it is not editable.</li>
+				<li>The plugin is aware of the FullScreen plugin, and when present will make sure that FullScreen knows which
+					node to make 'full'.</li>
+				<li>The View Source adds in basic comment and script tag stripping by default (to help avoid XSS) attacks in code.
+					These can be disabled, but it is not recommended.</li>
+				<li>While in view source mode, all other menu bar plugins are disabled.</li>
+			</ol>
+
+			<h2>Things to test:</h2>
+			<ol>
+				<li>Verify that clicking the View Source icon highlights the button appropriately and toggles the view source mode on.</li>
+				<li>Verify that clicking the View Source icon again dehighlites the button and toggles the view source mode off.</li>
+				<li>Click in the editing pane and verify that CTRL-SHIFT-F12 toggles the view source mode on and off.</li>
+	   			<li>Verify that when in View Source mode and comment and script tag stripping is enabled, that both inputs are removed when
+					toggled off.</li>
+			</ol>
+		</div>
+	<div>
+	<br>
+	<br>
+	<div>
+		<div dojoType="dijit.Editor"
+			extraPlugins="['fullscreen','viewsource']" style="background-color: white; width: 800px;" height="300px" id="editor1">
+			<h1>ViewSource Plugin with FullScreen Plugin details</h1>
+			<ol>
+				<li>The ViewSource plugin is FullScreen aware.  It will  should work appropriately when in full screen mode.</li>
+			</ol>
+
+			<h2>Things to test:</h2>
+			<ol>
+				<li>Verify that while in Full Screen mode clicking the View Source icon highlights the button appropriately and toggles the
+					view source mode on and scales appropriately.</li>
+			</ol>
+		</div>
+	<div>
+	<br>
+	<br>
+	<div>
+		<div dojoType="dijit.Editor"
+			extraPlugins="['fullscreen',{name: 'viewsource', readOnly: true}]" style="background-color: white; width: 800px;" height="300px" id="editor2">
+			<h1>ViewSource Plugin with readOnly enabled details</h1>
+			<ol>
+				<li>The ViewSource plugin supports a readonly mode.  This should display the content but not allow any edits..</li>
+			</ol>
+
+			<h2>Things to test:</h2>
+			<ol>
+				<li>Verify that while in View Source mode, the source cannot be edited.</li>
+			</ol>
+		</div>
+	<div>
+	<br>
+	<br>
+	<div>
+		<div dojoType="dijit.Editor"
+			extraPlugins="['fullscreen',{name: 'viewsource', stripScripts: false, stripComments: false, stripIFrames: false}]"
+			style="background-color: white; width: 800px;" height="300px" id="editor3">
+			<h1>ViewSource Plugin with script* disabled</h1>
+			<ol>
+				<li>The ViewSource plugin supports disabling the script stripping, comment stripping, etc.  This can be dangerous, but sometimes it is desirable.</li>
+			</ol>
+
+			<h2>Things to test:</h2>
+			<ol>
+				<li>Verify that typed in script tags, comments, and iframes are left in the content when view switched.</li>
+			</ol>
+		</div>
+	<div>
+	<br>
+	<br>
+	<div>Content after the editors.</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/test_resize.html b/dijit/tests/editor/test_resize.html
new file mode 100755
index 0000000..97db52d
--- /dev/null
+++ b/dijit/tests/editor/test_resize.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor in a BorderContainer</title>
+
+	<link rel="stylesheet" href="../../themes/tundra/tundra.css">
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.AlwaysShowToolbar");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro">
+	<h1>Editor in a BorderContainer</h1>
+	<p>Tests that a BorderContainer can correctly size the Editor (by calling Editor.resize()).</p>
+	<div dojoType="dijit.layout.BorderContainer" style="height: 400px;border:1px solid black;">
+		<div dojoType="dijit.layout.ContentPane" region="top" splitter="true" style="height: 100px">
+			Top pane
+		</div>
+		<div dojoType="dijit.Editor" id="editor1" region="center" height="100%">
+			Editor (center pane)
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/editor/test_richtext.css b/dijit/tests/editor/test_richtext.css
new file mode 100644
index 0000000..6b4d4ec
--- /dev/null
+++ b/dijit/tests/editor/test_richtext.css
@@ -0,0 +1,4 @@
+h1 {
+	border: 1px solid black;
+	background-color:red;
+}
\ No newline at end of file
diff --git a/dijit/tests/form/Form.html b/dijit/tests/form/Form.html
new file mode 100644
index 0000000..c82c1ff
--- /dev/null
+++ b/dijit/tests/form/Form.html
@@ -0,0 +1,551 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Form unit test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojo.date");
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.form.Form");
+		dojo.require("dijit.layout.LayoutContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.CheckBox");
+		dojo.require("dijit.form.DateTextBox");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.MultiSelect");
+		dojo.require("dijit.form.Textarea");
+		dojo.require("dijit.form.SimpleTextarea");
+		dojo.require("dijit.Editor");
+
+		var obj;
+		function getValues(){
+			obj = dijit.byId('myForm').get('value');
+			console.log("Object is: " + dojo.toJson(obj, true));
+		}
+
+		function setValues(){
+			if(!obj){
+		 		obj = {testF: 'testi'};
+			}
+			console.log("Object is: " + dojo.toJson(obj, true));
+			dijit.byId('myForm').set('value', obj);
+		}
+
+		function validate(){
+			console.log(dijit.byId('myForm').validate());
+		}
+
+		function defaultSubmitHandler(values){
+			console.log('actual submitted values: ' + dojo.toJson(values));
+		}
+		submittedValues = defaultSubmitHandler;
+		// make dojo.toJson() print dates correctly (this feels a bit dirty)
+		Date.prototype.json = function(){ return dojo.date.stamp.toISOString(this, {selector: 'date'});};
+
+		var d = dojo.date.stamp.fromISOString;
+
+		// These are the values assigned to the widgets in the page's HTML
+		var original =	{
+							foo: {bar: {baz: {quux: d("2007-12-30")} } },
+							available: {from: d("2005-01-02"), to: d("2006-01-02")},
+							plop: {combo: "one"},
+							cb2: ["2", "3"],
+							r2: "2",
+							ms1: ["VA", "WA"],
+							h1: "hidden",
+							t1: "line 1\nline 2",
+							st1: "simple line 1\nsimple line 2",
+							richtext: "<h1>original</h1><p>This is the default content</p>",
+							filename: "",
+							readOnlyWidget: "Should be returned",
+							duplicate: ["first", "second", "third"]
+						};
+
+		// we change the form to these values
+		var changed =	{
+							foo: {bar: {baz: {quux: d("2005-01-01")} } },
+							available: {from: d("2005-11-02"), to: d("2006-11-02")},
+							plop: {combo: "three"},
+							cb2: ["4"],
+							r2: "1",
+							ms1: ["FL", "CA"],
+							h1: "still hidden",
+							t1: "new line 1\nnew line 2",
+							st1: "new simple line 1\nnew simple line 2",
+							richtext: "<h1>changed</h1><p>This is the changed content set by set('value', ...')</p>",
+							filename: "",
+							readOnlyWidget: "Should be returned",
+							duplicate: ["1", "2", "3"]
+						};
+		var particalchanged = {
+							foo: {bar: {baz: {quux: d("2006-01-01")} } },
+							available: {from: d("2006-11-02"), to: d("2007-11-02")},
+							plop: {combo: "two"},
+							cb2: ["2"]
+		};
+		// we reset the form to these values
+		var reset =	{
+							foo: {bar: {baz: {quux: d("2007-12-30")} } },
+							available: {from: d("2005-01-02"), to: d("2006-01-02")},
+							plop: {combo: "one"},
+							cb2: ["2", "3"],
+							r2: "2",
+							ms1: ["VA", "WA"],
+							h1: "hidden",
+							t1: "line 1\nline 2",
+							st1: "simple line 1\nsimple line 2",
+							richtext: "<h1>changed</h1><p>This is the changed content set by set('value', ...')</p>", // not a form element, so not reset
+							filename: "",
+							readOnlyWidget: "Should be returned",
+							duplicate: ["first", "second", "third"]
+						};
+
+		dojo.addOnLoad(function(){
+
+			// should be able to query for all of the inputs, including hidden ones
+			doh.register("query input by checked state", [
+				{
+					name: "all",
+					runTest: function(){
+						var queried=dojo.query("input[checked]");
+						doh.t(queried.length>0,"dojo.query could not find checked widgets.");
+						doh.is(3,queried.length,"expected: 3 checked widgets, got: "+queried.length);
+						doh.is(dojo.byId('dijit_form_CheckBox_1'),queried[0],"Expected 2nd checkbox.");
+						doh.is(dojo.byId('dijit_form_CheckBox_2'),queried[1],"Expected 3rd checkbox.");
+						doh.is(dojo.byId('dijit_form_RadioButton_1'),queried[2],"Expected 2nd radio button.");
+					}
+				}
+			]);
+
+			doh.register("query input by name",
+				dojo.map(
+					[
+						"foo.bar.baz.quux","available.from","available.to", // DateTextBox
+						"plop.combo", // ComboBox
+						"cb2", // CheckBox
+						"r2", // RadioButton
+						//"ms1", // MultiSelect
+						"h1", // plain hidden input
+						//"t1", "st1", // TextArea
+						//"richtext", // Editor
+						"filename", // TextBox set to file input
+						"disabledWidget" // disabled TextBox
+					],
+					function(name){
+						return {
+							name: name,
+							widgetName: name,
+							runTest: function(){
+								var queried = dojo.query("input[name="+this.widgetName+"]");
+								doh.t(queried.length > 0, "dojo.query could not find form widget: '"+this.widgetName+"'");
+							}
+						};
+					}
+				)
+			);
+
+			var resetready=false;
+			var formWidget = dijit.byId("myForm");
+			var testSubmittedValues = function(deferred, testValues, formValues){
+				deferred.getTestCallback(function(){
+					doh.is(testValues.foo.bar.baz.quux.json(), formValues['foo.bar.baz.quux']);
+					doh.is(testValues.available.from.json(), formValues['available.from']);
+					doh.is(testValues.available.to.json(), formValues['available.to']);
+					doh.is(testValues.plop.combo, formValues['plop.combo']);
+					doh.is(testValues.cb2, formValues.cb2);
+					doh.is(testValues.r2, formValues.r2);
+					doh.is(testValues.ms1, formValues.ms1);
+					doh.is(testValues.h1, formValues.h1);
+					doh.is(testValues.t1, formValues.t1);
+					doh.is(testValues.st1, formValues.st1);
+					doh.is(testValues.filename, formValues.filename || '');
+					doh.is(testValues.readOnlyWidget, formValues.readOnlyWidget);
+				})();
+			};
+			doh.register("dijit.form.Form",
+				[
+					{
+						name: "setUp",
+						timeout: 5000,
+						runTest: function(){
+							var d=new doh.Deferred();
+
+							var defer=function(){
+								if(dijit.byId('t1')._resetValue!==undefined &&
+									!dijit.byId('editor').disabled){
+									doh.t(true);
+									d.callback(true);
+								}else{
+									setTimeout(defer,100);
+								}
+							};
+							setTimeout(defer,1000);
+							return d;
+						}
+					},
+					function getValues(){
+						var values = formWidget.get('value');
+
+						// FF3 sticks in some tabs and newlines that mess up the equality check
+						// Need better way to compare two HTML trees but for now do this.
+						values.richtext = values.richtext.replace(/[\n\t]/, "", "g");
+
+						doh.is( dojo.toJson(original), dojo.toJson(values) );
+					},
+					{
+						name:"testSubmit",
+					        timeout:10000,
+					        runTest:function(){
+							var d=new doh.Deferred();
+							submittedValues = function(values){
+								testSubmittedValues(d, original, values);
+								submittedValues = defaultSubmitHandler;
+							};
+							formWidget.containerNode.submit();
+							return d;
+						}
+					},
+					function setValues(){
+						formWidget.set('value', changed);
+						doh.is( dojo.toJson(changed), dojo.toJson(formWidget.get('value')) );
+
+						formWidget.set('value', particalchanged);
+						doh.is( dojo.toJson(dojo.mixin(changed,particalchanged)), dojo.toJson(formWidget.get('value')) );
+					},
+					function nameAttributeSurvived(){  // ticket:4753
+						var radios = dojo.query("INPUT[type=radio]", "radio-cells").forEach(
+							function(r) {
+								doh.is( r.name, "r2" );
+							});
+					},
+					{
+					        name:"postSubmit",
+					        timeout:10000,
+					        runTest:function(){
+							var d=new doh.Deferred();
+							submittedValues = function(values){
+								testSubmittedValues(d, dojo.mixin(changed,particalchanged), values);
+								submittedValues = defaultSubmitHandler;
+							};
+							formWidget.containerNode.submit();
+							return d;
+						}
+					},
+					function resetTest(){
+						formWidget._onResetReturn = false;
+						formWidget.reset();
+						doh.isNot( dojo.toJson(reset), dojo.toJson(formWidget.get('value')), "reset stopped");
+						formWidget._onResetReturn = true;
+						formWidget.reset();
+						delete formWidget._onResetReturn;
+						doh.is( dojo.toJson(reset), dojo.toJson(formWidget.get('value')), "reset permitted" );
+					},
+					function testValidate(){
+						doh.is(formWidget.validate(), true);
+					},
+					function resetEditor(){ // reset editor so that refresh will pass all tests
+						dijit.byId('editor').set('value', original.richtext);
+						// FF3 sticks in some tabs and newlines that mess up the equality check
+						// Need better way to compare two HTML trees but for now do this.
+						var values = formWidget.get('value');
+						values.richtext = values.richtext.replace(/[\n\t]/, "", "g");
+						doh.is( dojo.toJson(original), dojo.toJson(values) );
+					}
+				]
+			);
+
+			doh.run();
+		});
+
+	</script>
+</head>
+<body class="claro">
+	<h1>Form Widget Unit Test</h1>
+	<p>
+		The form widget takes data in a form and serializes/deserializes it, so
+		it can be submitted as a JSON string of nested objects.
+	</p>
+	<div style="color:red">Currently only widgets are supported, not raw elements.</div>
+	<!--    to test form submission, you'll need to create an action handler similar to
+			http://www.utexas.edu/teamweb/cgi-bin/generic.cgi
+		http://www.tipjar.com/cgi-bin/test -->
+	<form dojoType="dijit.form.Form" id="myForm"
+		encType="multipart/form-data" action="../formAction.html" method="" target="_formSubmitIframe">
+		<script type="dojo/method" event="onReset">
+			return ("_onResetReturn" in this)? this._onResetReturn : confirm('Press OK to reset widget values');
+		</script>
+		<script type="dojo/method" event="onSubmit">
+			console.debug('Attempting to submit form w/values:\n',
+				dojo.toJson(this.get('value'),true)
+			);
+			if(this.validate()){
+				return confirm('Form is valid, press OK to submit');
+			}else{
+				alert('Form contains invalid data.  Please correct first');
+				return false;
+			}
+			return true;
+		</script>
+		<p>Just HTML text</p>
+		<table style="border: 1px solid #9f9f9f;" cellspacing="10">
+			<thead>
+				<tr>
+					<th>Description</th>
+					<th>Name</th>
+					<th>Form node/widget</th>
+				</tr>
+			</thead>
+			<tbody>
+				<!--
+				<tr><td>text</td><td>testF</td><td><input type="text" name="testF" value="bar1" /></td></tr>
+				<tr><td>password</td><td>passwordF</td><td><input type="password" name="passwordF" value="bar4" /></td></tr>
+				<tr><td>hidden</td><td>hiddenF</td><td><input type="hidden" name="hiddenF" value="bar4" /></td></tr>
+				<tr><td>select</td><td>plop.noncombo</td><td>
+				<div class="group">
+					<select name="plop.noncombo">
+					 <option value="1">one</option>
+					 <option value="2">two</option>
+					 <option value="3">three</option>
+					</select>
+				</div>
+
+				</td></tr>
+				-->
+
+				<tr>
+					<td>DateTextBox inside contentpane</td>
+					<td>foo.bar.baz.quux</td>
+					<td>
+						<div dojoType="dijit.layout.ContentPane">
+						<input type="text" name="foo.bar.baz.quux" dojoType="dijit.form.DateTextBox" value="2007-12-30" />
+						</div>
+					</td>
+				</tr>
+				<tr>
+					<td>Layoutcontainer</td>
+					<td>
+						<div dojoType="dijit.layout.LayoutContainer"></div>
+					</td>
+				</tr>
+				<tr>
+					<td>DateTextBox 1</td>
+					<td>available.from</td>
+					<td>
+						<input type="text" name="available.from" dojoType="dijit.form.DateTextBox" value="2005-01-02" />
+					</td>
+				</tr>
+				<tr>
+					<td>DateTextBox 2</td>
+					<td>available.to</td>
+					<td>
+						<input type="text" name="available.to" dojoType="dijit.form.DateTextBox" value="2006-01-02" />
+					</td>
+				</tr>
+				<tr>
+					<td>ComboBox</td>
+					<td>plop.combo</td>
+					<td>
+						<select name="plop.combo" dojoType="dijit.form.ComboBox">
+							<option value="one">one</option>
+							<option value="two">two</option>
+							<option value="three">three</option>
+						</select>
+					</td>
+				</tr>
+
+				<!--
+				<tr>
+					<td>textarea</td>
+					<td>myTextArea</td>
+					<td>
+						<textarea name="myTextArea">
+							text text text """ \\\/
+						</textarea>
+					</td>
+				</tr>
+				-->
+
+				<!--
+				<tr>
+					<td>CheckBox</td>
+					<td>cb1</td>
+					<td>
+						<input type="checkbox" name="cb1" value="1" /> 1
+						<input type="checkbox" name="cb1" value="2" checked="checked" /> 2
+						<input type="checkbox" name="cb1" value="3" checked="checked" /> 3
+						<input type="checkbox" name="cb1" value="4" /> 4
+					</td>
+				</tr>
+				-->
+
+				<tr>
+					<td>CheckBox widget</td>
+					<td>cb2</td>
+					<td>
+						<input dojoType="dijit.form.CheckBox" type="checkbox" name="cb2" value="1" /> 1
+						<input dojoType="dijit.form.CheckBox" type="checkbox" name="cb2" value="2" checked="checked" /> 2
+						<input dojoType="dijit.form.CheckBox" type="checkbox" name="cb2" value="3" checked="checked" /> 3
+						<input dojoType="dijit.form.CheckBox" type="checkbox" name="cb2" value="4" /> 4
+					</td>
+				</tr>
+
+				<!--
+				<tr>
+					<td>radio</td>
+					<td>r1</td>
+					<td>
+						<input type="radio" name="r1" value="1" /> 1
+						<input type="radio" name="r1" value="2" /> 2
+						<input type="radio" name="r1" value="3" /> 3
+						<input type="radio" name="r1" value="4" /> 4
+					</td>
+				</tr>
+				-->
+
+				<tr>
+				<td>Radio widget</td><td>r2</td>
+				<td id="radio-cells">
+				<input dojoType="dijit.form.RadioButton" type="radio" name="r2" value="1" /> 1
+				<input dojoType="dijit.form.RadioButton" type="radio" name="r2" value="2" checked="checked" /> 2
+				<input dojoType="dijit.form.RadioButton" type="radio" name="r2" value="3"/> 3
+				<input dojoType="dijit.form.RadioButton" type="radio" name="r2" value="4" /> 4
+				<input type="button" onclick="dojo.query('INPUT[type=radio]','radio-cells').forEach(function(n){dijit.getEnclosingWidget(n).set('checked',false);});return true;" value="Unset all radio buttons"/>
+				</td>
+				</tr>
+
+				<tr>
+					<td>Multi-select</td><td>ms1</td>
+					<td>
+						<select id="ms1" multiple="true" name="ms1"
+							dojoType="dijit.form.MultiSelect"
+							style="height:100px; width:175px; border:5px solid #ededed;">
+
+							<option value="TN">Tennessee</option>
+							<option value="VA" selected="true">Virginia</option>
+							<option value="WA" selected="true">Washington</option>
+							<option value="FL">Florida</option>
+							<option value="CA">California</option>
+
+						</select>
+					</td>
+				</tr>
+
+				<tr>
+					<td>Hidden input</td>
+					<td>h1</td>
+					<td>
+						<input id="h1" name="h1" dojoType="dijit.form.TextBox" type="hidden" value="hidden">
+					</td>
+				</tr>
+
+				<tr>
+					<td>Auto-sizing textarea</td>
+					<td>t1</td>
+					<td>
+						<textarea id="t1" name="t1"
+	dojoType="dijit.form.Textarea">line 1
+line 2</textarea>
+					</td>
+				</tr>
+
+				<tr>
+					<td>Fixed size textarea</td>
+					<td>st1</td>
+					<td>
+						<textarea id="st1" name="st1" dojoType="dijit.form.SimpleTextarea" rows=5 cols=50>
+simple line 1
+simple line 2</textarea>
+					</td>
+				</tr>
+
+				<tr>
+					<td>Editor widget</td>
+					<td>richtext</td>
+					<td>
+						<div dojoType="dijit.Editor" id="editor" name="richtext" pluginsConfig="[{items:['bold','italic']}]"><h1>original</h1><p>This is the default content</p></div>
+					</td>
+				</tr>
+
+				<tr>
+					<td>File upload</td>
+					<td>filename</td>
+					<td>
+						<input dojoType="dijit.form.TextBox" name="filename" type="file">
+					</td>
+				</tr>
+				<tr>
+					<td>Disabled Widget</td>
+					<td>disabledWidget</td>
+					<td>
+						<input dojoType="dijit.form.TextBox" name="disabledWidget" disabled="disabled" value="Should not be returned">
+					</td>
+				</tr>
+				<tr>
+					<td>Disabled Required Widget</td>
+					<td>disabledRequiredWidget</td>
+					<td>
+						<input dojoType="dijit.form.ValidationTextBox" name="disabledRequiredWidget" disabled="disabled" required="true" value="">
+					</td>
+				</tr>
+				<tr>
+					<td>Read-only Widget</td>
+					<td>readOnlyWidget</td>
+					<td>
+						<input dojoType="dijit.form.TextBox" name="readOnlyWidget" readOnly value="Should be returned">
+					</td>
+				</tr>
+				<tr>
+					<td>Duplicate named TextBox 1</td>
+					<td>duplicate</td>
+					<td>
+						<input dojoType="dijit.form.TextBox" name="duplicate" value="first">
+					</td>
+				</tr>
+				<tr>
+					<td>Duplicate named TextBox 2</td>
+					<td>duplicate</td>
+					<td>
+						<input dojoType="dijit.form.TextBox" name="duplicate" value="second">
+					</td>
+				</tr>
+				<tr>
+					<td>Duplicate named TextBox 3</td>
+					<td>duplicate</td>
+					<td>
+						<input dojoType="dijit.form.TextBox" name="duplicate" value="third">
+					</td>
+				</tr>
+			</tbody>
+		</table>
+
+		<button dojoType="dijit.form.Button" onClick="getValues();">Get Values from form!</button>
+		<button dojoType="dijit.form.Button" onClick="setValues();">Set Values to form!</button>
+		<button dojoType="dijit.form.Button" onClick="validate();">Validate form!</button>
+		<button dojoType="dijit.form.Button" type="submit" value="Submit">Submit</button>
+		<button dojoType="dijit.form.Button" type="reset">HTML Reset</button>
+		<button dojoType="dijit.form.Button" type="button" onClick="dijit.byId('myForm').reset()">reset()</button>
+	</form>
+<button dojoType="dijit.form.Button" type="button"
+onclick="dijit.byId('myForm').submit()">Submit programmatically</button>
+
+<iframe name="_formSubmitIframe" src="about:blank" onload="if(this.values)submittedValues(this.values)" style="display:none;"></iframe>
+</body>
+</html>
diff --git a/dijit/tests/form/FormInvalid.html b/dijit/tests/form/FormInvalid.html
new file mode 100644
index 0000000..90f2309
--- /dev/null
+++ b/dijit/tests/form/FormInvalid.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+        <title>Form unit test</title>
+        <style type="text/css">
+            @import "../../../dojo/resources/dojo.css";
+            @import "../css/dijitTests.css";
+        </style>
+        <!-- required: the default dijit theme: -->
+        <link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+        <!-- required: dojo.js -->
+        <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true">
+        </script>
+        <!-- only needed for alternate theme testing: -->
+        <script type="text/javascript" src="../_testCommon.js">
+        </script>
+        <script type="text/javascript">
+            dojo.require("dojo.date");
+            dojo.require("dijit.dijit"); // optimize: load dijit layer
+            dojo.require("dijit.form.Form");
+            dojo.require("dijit.form.ValidationTextBox");
+            dojo.require("dijit.form.Button");
+
+            function foo(isValid){
+                var form = dijit.byId("myForm1");
+                var btn = dijit.byId("submitBtn");
+                btn.set("disabled", !isValid);
+            }
+
+            dojo.addOnLoad(function(){
+                var form = dijit.byId("myForm1");
+                dojo.connect(form, "onValidStateChange", null, foo);
+                dijit.byId("submitBtn").set("disabled", true);
+            })
+        </script>
+    </head>
+    <body class="claro">
+        <h1 class="testTitle">Form Widget Unit Test</h1>
+        <form dojoType="dijit.form.Form" id="myForm1" onSubmit="dojo.stopEvent(arguments[0])">
+            <h3>This form's submit button should become enabled ONLY when all fields are valid</h3>
+            <p>
+            	This is a test case for <a href="http://bugs.dojotoolkit.org/ticket/8966">#8966</a>.
+            </p>
+            <input dojoType="dijit.form.ValidationTextBox" required="true" name="field1" id="field1" />Foo*
+            <br/>
+            <input dojoType="dijit.form.ValidationTextBox" required="true" name="field2" id="field2" />Bar*
+            <br/>
+            <button dojoType="dijit.form.Button" id="submitBtn" type="submit">
+                Submit
+            </button>
+			<br/><em>*Required</em>
+        </form>
+    </body>
+</html>
diff --git a/dijit/tests/form/TextBox_sizes.html b/dijit/tests/form/TextBox_sizes.html
new file mode 100644
index 0000000..ef0bea7
--- /dev/null
+++ b/dijit/tests/form/TextBox_sizes.html
@@ -0,0 +1,532 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html dir="ltr">
+<head>
+	<title>dijit.form.TextBox size tests</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../themes/dijit.css";
+		@import "../../themes/dijit_rtl.css";
+		@import "../../themes/tundra/Common.css";
+		@import "../../themes/tundra/Common_rtl.css";
+		@import "../../themes/tundra/form/Button.css";
+		@import "../../themes/tundra/form/Button_rtl.css";
+		@import "../../themes/tundra/form/Common.css";
+		@import "../../themes/tundra/form/Common_rtl.css";
+		@import "../../themes/claro/Common.css";
+		@import "../../themes/claro/Common_rtl.css";
+		@import "../../themes/claro/form/Button.css";
+		@import "../../themes/claro/form/Button_rtl.css";
+		@import "../../themes/claro/form/Common.css";
+		@import "../../themes/claro/form/Common_rtl.css";
+		@import "../../themes/claro/form/NumberSpinner.css";
+		@import "../../themes/claro/form/NumberSpinner_rtl.css";
+		@import "../../themes/soria/Common.css";
+		@import "../../themes/soria/Common_rtl.css";
+		@import "../../themes/soria/form/Button.css";
+		@import "../../themes/soria/form/Button_rtl.css";
+		@import "../../themes/soria/form/Common.css";
+		@import "../../themes/soria/form/Common_rtl.css";
+		@import "../../themes/nihilo/Common.css";
+		@import "../../themes/nihilo/Common_rtl.css";
+		@import "../../themes/nihilo/form/Button.css";
+		@import "../../themes/nihilo/form/Button_rtl.css";
+		@import "../../themes/nihilo/form/Common.css";
+		@import "../../themes/nihilo/form/Common_rtl.css";
+
+		#table TD {
+			padding: 1px;
+			background-color: pink;
+			font-size: 100%;
+		}
+		TABLE#table, #table TD, #table .dijit {
+			border-color: black !important;
+			margin: 0px !important;
+		}
+		.dj_ie8 #table .dijit {
+			vertical-align: top; /* needed for IE8 strict */
+		}
+		.dj_iequirks #table .dijit {
+			vertical-align: auto; /* needed for IE8 quirks */
+		}
+		.padded .dijitInputField {
+			padding: 10px !important;
+		}
+		.unPadded .dijitInputField {
+			padding: 0px !important;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.NumberTextBox");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dijit.form.NumberSpinner");
+		dojo.require("dijit.form.Button");
+
+		dojo.addOnLoad(function(){
+
+			var padding = "padded";
+			var theme = "tundra";
+			var direction = "ltr";
+			var fontSize = "12pt";
+			var fontFamily = "monospace";
+
+			dijit.byId("theme").isRealA11y = dojo.hasClass(dojo.body(), "dijit_a11y");
+
+			var str = window.location.href.substr(window.location.href.indexOf("?")+1).split(/#/);
+			var ary  = str[0].split(/&/);
+			if(window.location.href.indexOf("?") > -1){
+				for(var i=0; i<ary.length; i++){
+					var split = ary[i].split("="),
+						key = split[0],
+						value = split[1].replace(/[^\w]/g, "");	// replace() to prevent XSS attack
+					switch(key){
+						case "locale":
+							// locale string | null
+							dojo.locale = dojo.config.locale = locale = value;
+							break;
+						case "dir":
+						case "direction":
+							// rtl | ltr
+							direction = value;
+							break;
+						case "theme":
+							// tundra | soria | nihilo | claro | a11y
+							theme = value;
+							break;
+						case "a11y": // included for backward compat
+							theme = "a11y";
+							break;
+						case "size":
+						case "fontsize":
+						case "fontSize":
+							// size string (e.g 12px)
+							fontSize = value;
+							break;
+						case "family":
+						case "fontfamily":
+						case "fontFamily":
+							// family string (e.g Courier)
+							fontFamily = value;
+							break;
+						case "padding":
+							// padded | unPadded | default
+							padding = value;
+							break;
+					}
+				}
+			}
+
+			dijit.byId('padding').set('value', padding, true);
+			dijit.byId('theme').set('value', theme, true);
+			dijit.byId('direction').set('value', direction, true);
+			dijit.byId('fontSize').set('value', fontSize, true);
+			dijit.byId('fontFamily').set('value', fontFamily, true);
+
+			var textbox = dijit.byId("textbox");
+			var validation = dijit.byId("validation");
+			var combobox = dijit.byId("combobox");
+			var spinner = dijit.byId("spinner");
+			var table = dojo.byId("table");
+
+			var compareToTextBox = function(attr){
+				try{
+					var textboxPos = dojo.position(textbox.domNode);
+					var validationPos = dojo.position(validation.domNode);
+					var comboboxPos = dojo.position(combobox.domNode);
+					var spinnerPos = dojo.position(spinner.domNode);
+					doh.t(Math.round(textboxPos[attr]) == Math.round(validationPos[attr]) &&
+						Math.round(textboxPos[attr]) == Math.round(comboboxPos[attr]) &&
+						Math.round(textboxPos[attr]) == Math.round(spinnerPos[attr]),
+						"Expected same " + attr + ":" + textboxPos[attr] + '/' + validationPos[attr] + '/' + comboboxPos[attr] + '/' + spinnerPos[attr]
+					);
+				}catch(e){
+					throw e; // prevent consoles from including entire function text in output
+				}
+			};
+
+			var compareToTextBoxParent = function(attr){
+				try{
+					var textboxPos = dojo.position(textbox.domNode.parentNode);
+					var validationPos = dojo.position(validation.domNode.parentNode);
+					var comboboxPos = dojo.position(combobox.domNode.parentNode);
+					var spinnerPos = dojo.position(spinner.domNode.parentNode);
+					doh.t(Math.round(textboxPos[attr]) == Math.round(validationPos[attr]) &&
+						Math.round(textboxPos[attr]) == Math.round(comboboxPos[attr]) &&
+						Math.round(textboxPos[attr]) == Math.round(spinnerPos[attr]),
+						"Expected same parent " + attr + ":" + textboxPos[attr] + '/' + validationPos[attr] + '/' + comboboxPos[attr] + '/' + spinnerPos[attr]
+					);
+				}catch(e){
+					throw e; // prevent consoles from including entire function text in output
+				}
+			};
+
+			var runTest = [
+				{
+						name: "x",
+						runTest: function(){ compareToTextBox("x"); }
+				},
+				{
+						name: "y",
+						runTest: function(){ compareToTextBoxParent("h"); }
+				},
+				{
+						name: "h",
+						runTest: function(){ compareToTextBox("h"); }
+				},
+				{
+						name: "w",
+						runTest: function(){ compareToTextBox("w"); }
+				}
+			];
+
+			var createErrors = function(){
+				textbox._hasBeenBlurred = true;
+				textbox.set('value', "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz");
+				validation._hasBeenBlurred = true;
+				validation.set('displayedValue', "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz");
+				combobox._hasBeenBlurred = true;
+				combobox.set('displayedValue', "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz");
+				spinner._hasBeenBlurred = true;
+				spinner.set('displayedValue', "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz");
+			};
+
+			doh.register("create normal boxes", {
+				name: "setup",
+				timeout: 9000,
+				runTest: function(){
+					var d = new doh.Deferred();
+					/* create errors, then insert good values to exercise the widget rendering */
+					createErrors();
+					validation.set('value', 23);
+					spinner.set('value', 32);
+					combobox.onChange = function(v){ if(v == "KY"){ d.callback(true); combobox.onChange = function(){}; }};
+					combobox.set('value', "KY");
+					return d;
+				}
+ 			});
+
+			doh.register("check normal sizes", runTest);
+
+			dojo.forEach([textbox, validation, combobox, spinner], function(widget){
+				var widgetName = widget.baseClass.replace(/^.* /, "");
+				doh.register("valid internal offsets", [
+					{
+						name: "textbox: " + widgetName,
+						timeout: 1000,
+						runTest: function(){
+							var paddedBoxPos = dojo.position(widget.focusNode.parentNode);
+							var inputPos = dojo.position(widget.focusNode);
+							var paddingLeft = Math.abs(inputPos.x - paddedBoxPos.x);
+							var paddingRight = Math.abs(inputPos.w - paddedBoxPos.w) - paddingLeft;
+							var paddingTop = Math.abs(inputPos.y - paddedBoxPos.y);
+							var paddingBottom = Math.abs(inputPos.h - paddedBoxPos.h) - paddingTop;
+							var pad = undefined;
+							if(dojo.hasClass(table, "padded")){
+								pad = 10;
+							}else if(dojo.hasClass(table, "unPadded")){
+								pad = 0;
+							}else{
+								return;
+							}
+							doh.t(Math.abs(paddingLeft-pad) <= 1, "left padding("+paddingLeft+") should be "+pad);
+							doh.t(Math.abs(paddingRight-pad) <= 1, "right padding("+paddingRight+") should be "+pad);
+							doh.t(Math.abs(paddingTop-pad) <= 1, "top padding("+paddingTop+") should be "+pad);
+							doh.t(Math.abs(paddingBottom-pad) <= 1, "bottom padding("+paddingBottom+") should be "+pad);
+						}
+					},
+					{
+						name: "padded box: " + widgetName,
+						timeout: 1000,
+						runTest: function(){
+							var domNodePos = dojo.position(widget.domNode);
+							var paddedBoxPos = dojo.position(widget.focusNode.parentNode);
+							var clientHeight = widget.domNode.clientHeight;
+							var clientWidth = widget.domNode.clientWidth;
+							doh.t(Math.abs(clientHeight-paddedBoxPos.h) <= 1, "padded textbox height: " + clientHeight + " vs " + paddedBoxPos.h);
+							var border = (domNodePos.w - clientWidth) >> 1; // average border width
+							var offset = Math.min(Math.abs(domNodePos.x + border - paddedBoxPos.x), Math.abs(domNodePos.x + domNodePos.w - border - paddedBoxPos.x - paddedBoxPos.w));
+							doh.t(offset <= 1, "padded textbox horizontally just left or right (" + offset + ") of domNode: domNode x/w/b = " + domNodePos.x+"/"+domNodePos.w+"/"+border + ", pad box x/w = " + paddedBoxPos.x+"/"+paddedBoxPos.w);
+						}
+					},
+					{
+						name: "button: " + widgetName,
+						timeout: 1000,
+						runTest: function(){
+							if(widgetName == "dijitTextBox" || widgetName == "dijitValidationTextBox"){ return; }
+							var paddedBoxPos = dojo.position(widget.focusNode.parentNode);
+							var buttonNode = dojo.query(".dijitValidationContainer", widget.domNode)[0].previousSibling;
+							var buttonPos = dojo.position(buttonNode);
+							var offset = Math.min(Math.abs(paddedBoxPos.x + paddedBoxPos.w - buttonPos.x), Math.abs(buttonPos.x + buttonPos.w - paddedBoxPos.x));
+							// IE 6 float bug(s) causes a known 3px margin between input field & validation icon 
+							// Fix could be .dj_ie .dijitInputField { float:right; }
+							// But this breaks even more the tests, dojo.position() bug?
+							if(dojo.isIE < 7 || dojo.isQuirks)
+								doh.t(offset <= 3, "button node horizontally just left or right (" + offset + ") of padded input node: input x/w = " + paddedBoxPos.x+"/"+paddedBoxPos.w + ", button x/w = " + buttonPos.x+"/"+buttonPos.w);
+							else
+								doh.t(offset <= 1, "button node horizontally just left or right (" + offset + ") of padded input node: input x/w = " + paddedBoxPos.x+"/"+paddedBoxPos.w + ", button x/w = " + buttonPos.x+"/"+buttonPos.w);
+						}
+					}
+				]);
+			});
+
+			doh.register("create errors", {
+				name: "setup",
+				timeout: 9000,
+				runTest: function(){
+					var d = new doh.Deferred();
+					createErrors();
+					textbox.onChange = function(v){ d.callback(true); textbox.onChange = function(){}; };
+					textbox.set('value', textbox.get('value')+' ');
+					return d;
+				}
+			});
+
+			doh.register("check error sizes", runTest);
+
+			doh.register("check button sizes", [
+				{
+					name: "ComboBox",
+					timeout: 1000,
+					runTest: function(){
+						var inputPos = dojo.position(combobox.focusNode.parentNode);
+						var arrowPos = dojo.position(combobox.downArrowNode);
+						doh.t(Math.abs(inputPos.h-arrowPos.h) <= 1, "ComboBox button height (" + arrowPos.h + ") is same as input height (" + inputPos.h + ")");
+					}
+				},
+				{
+					name: "Spinner",
+					timeout: 1000,
+					runTest: function(){
+						// use offsetHeight since the buttons could be truncated by overflow:hidden
+						var inputHeight = spinner.focusNode.parentNode.offsetHeight;
+						var downArrowHeight = spinner.downArrowNode.offsetHeight;
+						var upArrowHeight = spinner.upArrowNode.offsetHeight;
+						doh.t((inputHeight-downArrowHeight-upArrowHeight) <= 1, "Spinner button heights (" + upArrowHeight + "," + downArrowHeight + ") are equal to the input height (" + inputHeight + ")");
+						doh.t(Math.abs(upArrowHeight - downArrowHeight) <= 1, "Spinner UP button height (" + upArrowHeight + ") is equal to the DOWN button height (" + downArrowHeight + ")");
+					}
+				}
+  			]);
+
+			dojo.forEach([validation, combobox, spinner], function(widget){
+				var widgetName = widget.baseClass.replace(/^.* /, "");
+				doh.register("error internal offsets", [
+					{
+						name: "textbox: " + widgetName,
+						timeout: 1000,
+						runTest: function(){
+							var paddedBoxPos = dojo.position(widget.focusNode.parentNode);
+							var inputPos = dojo.position(widget.focusNode);
+							var paddingLeft = Math.abs(inputPos.x - paddedBoxPos.x);
+							var paddingRight = Math.abs(inputPos.w - paddedBoxPos.w) - paddingLeft;
+							var paddingTop = Math.abs(inputPos.y - paddedBoxPos.y);
+							var paddingBottom = Math.abs(inputPos.h - paddedBoxPos.h) - paddingTop;
+							var pad = undefined;
+							if(dojo.hasClass(table, "padded")){
+								pad = 10;
+							}else if(dojo.hasClass(table, "unPadded")){
+								pad = 0;
+							}else{
+								return;
+							}
+							doh.t(Math.abs(paddingLeft-pad) <= 1, "left padding("+paddingLeft+") should be "+pad);
+							doh.t(Math.abs(paddingRight-pad) <= 1, "right padding("+paddingRight+") should be "+pad);
+							doh.t(Math.abs(paddingTop-pad) <= 1, "top padding("+paddingTop+") should be "+pad);
+							doh.t(Math.abs(paddingBottom-pad) <= 1, "bottom padding("+paddingBottom+") should be "+pad);
+						}
+					},
+					{
+						name: "padded box: " + widgetName,
+						timeout: 1000,
+						runTest: function(){
+							var domNodePos = dojo.position(widget.domNode);
+							var paddedBoxPos = dojo.position(widget.focusNode.parentNode);
+							var clientHeight = widget.domNode.clientHeight;
+							var clientWidth = widget.domNode.clientWidth;
+							doh.t(Math.abs(clientHeight-paddedBoxPos.h) <= 1, "padded textbox height: " + clientHeight + " vs " + paddedBoxPos.h);
+							var border = (domNodePos.w - clientWidth) >> 1; // average border width
+							var offset = Math.min(Math.abs(domNodePos.x + border - paddedBoxPos.x), Math.abs(domNodePos.x + domNodePos.w - border - paddedBoxPos.x - paddedBoxPos.w));
+							doh.t(offset <= 1, "padded textbox horizontally just left or right (" + offset + ") of domNode: domNode x/w/b = " + domNodePos.x+"/"+domNodePos.w+"/"+border + ", pad box x/w = " + paddedBoxPos.x+"/"+paddedBoxPos.w);
+						}
+					},
+					{
+						name: "validation node: " + widgetName,
+						timeout: 1000,
+						runTest: function(){
+							if(widget.state != "Error"){ return; }
+							var validationNode = dojo.query(".dijitValidationContainer", widget.domNode)[0];
+							var validationPos = dojo.position(validationNode);
+							var paddedBoxPos = dojo.position(widget.focusNode.parentNode);
+							var offset = Math.min(Math.abs(paddedBoxPos.x + paddedBoxPos.w - validationPos.x), Math.abs(validationPos.x + validationPos.w - paddedBoxPos.x));
+
+							// IE 6 float bug(s) causes a known 3px margin between input field & validation icon 
+							// Fix could be .dj_ie .dijitInputField { float:right; /* get rid of 3px margin */ }
+							// But this breaks even more the tests, dojo.position() bug?
+							if(dojo.isIE < 7 || dojo.isQuirks)
+								doh.t(offset <= 3, "padded textbox horizontally just left or right (" + offset + ") of validation node: valiation node x/w = " + validationPos.x+"/"+validationPos.w + ", pad box x/w = " + paddedBoxPos.x+"/"+paddedBoxPos.w);
+							else
+								doh.t(offset <= 1, "padded textbox horizontally just left or right (" + offset + ") of validation node: valiation node x/w = " + validationPos.x+"/"+validationPos.w + ", pad box x/w = " + paddedBoxPos.x+"/"+paddedBoxPos.w);
+						}
+					},
+					{
+						name: "button: " + widgetName,
+						timeout: 1000,
+						runTest: function(){
+							if(widget.state != "Error" || widgetName == "dijitValidationTextBox"){ return; }
+							var validationNode = dojo.query(".dijitValidationContainer", widget.domNode)[0];
+							var buttonNode = dojo.query(".dijitValidationContainer", widget.domNode)[0].previousSibling;
+							var validationPos = dojo.position(validationNode);
+							var buttonPos = dojo.position(buttonNode);
+							var offset = Math.min(Math.abs(validationPos.x + validationPos.w - buttonPos.x), Math.abs(buttonPos.x + buttonPos.w - validationPos.x));
+							doh.t(offset <= 1, "button node horizontally just left or right (" + offset + ") of validation node: valiation node x/w = " + validationPos.x+"/"+validationPos.w + ", button x/w = " + buttonPos.x+"/"+buttonPos.w);
+						}
+					}
+				]);
+			});
+
+			doh.run();
+		});
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">dijit.form.TextBox size tests</h1>
+
+	<table class="padded" id="table" rules="all" cellpadding="0" cellspacing="0" border="2" frame="border" style="font-family:monospace;font-size:12pt;">
+		<tr>
+			<td style="font-size:1px;overflow:hidden;"> </td>
+			<td style="font-size:1px;overflow:hidden;"> </td>
+			<td></td>
+			<td style="font-size:1px;overflow:hidden;"> </td>
+		</tr>
+		<tr>
+			<td>TextBox</td>
+			<td></td>
+			<td><input dojoType="dijit.form.TextBox" type="text" id="textbox" value="text"></td>
+			<td></td>
+		</tr>
+		<tr>
+			<td>NumberTextBox</td>
+			<td></td>
+			<td><input dojoType="dijit.form.NumberTextBox" type="text" id="validation" value="54" required="true"></td>
+			<td></td>
+		</tr>
+		<tr>
+			<td>FilteringSelect</td>
+			<td></td>
+			<td><select dojoType="dijit.form.FilteringSelect" id="combobox" required="true">
+				<option value="KY">Kentucky</option>
+			</select></td>
+			<td></td>
+		</tr>
+		<tr>
+			<td>NumberSpinner</td>
+			<td></td>
+			<td><div dojoType="dijit.form.NumberSpinner" type="text" id="spinner" value="45" required="true"></div></td>
+			<td></td>
+		</tr>
+		<tr>
+			<td>INPUT type=file</td>
+			<td></td>
+			<td><input dojoType="dijit.form.TextBox" type="file" id="file"></td>
+			<td></td>
+		</tr>
+		<tr>
+			<td style="font-size:1px;overflow:hidden;"> </td>
+			<td></td>
+			<td></td>
+			<td></td>
+		</tr>
+	</table><br>
+	<table style="display:block;">
+	<tr><td style="text-align:right;">Font family:
+	<select dojoType="dijit.form.ComboBox" id="fontFamily" style="font-size:14pt;" value="">
+		<script type="dojo/method" event="onChange" args="fontFamily">
+			var table = dojo.byId('table');
+			table.style.fontFamily = fontFamily;
+			if(dojo.isIE){
+				dojo.query('INPUT', table).forEach(function(node){
+					node.style.fontFamily = fontFamily;
+				});
+			}
+		</script>
+		<option>monospace</option>
+		<option selected>Courier</option>
+		<option>Helvetica</option>
+		<option>Times</option>
+		<option>system,fixed</option>
+	</select></td></tr>
+	<tr><td style="text-align:right;">Font size:
+	<select dojoType="dijit.form.ComboBox" id="fontSize" style="font-size:14pt;" value="">
+		<script type="dojo/method" event="onChange" args="fontSize">
+			var table = dojo.byId('table');
+			table.style.fontSize = fontSize;
+		</script>
+		<option>small</option>
+		<option>medium</option>
+		<option>xx-large</option>
+		<option>8pt</option>
+		<option>21px</option>
+		<option>1cm</option>
+		<option>1em</option>
+		<option>200%</option>
+	</select></td></tr>
+	<tr><td style="text-align:right;">Padding:
+	<select dojoType="dijit.form.FilteringSelect" id="padding" style="font-size:14pt;" required="false" value="">
+		<script type="dojo/method" event="onChange" args="padding">
+			dojo.byId('table').className = padding;
+		</script>
+		<option value="default">default</option>
+		<option value="padded">padded</option>
+		<option value="unPadded">unPadded</option>
+	</select></td></tr>
+	<tr><td style="text-align:right;">Direction:
+	<select dojoType="dijit.form.FilteringSelect" id="direction" style="font-size:14pt;" required="false" value="">
+		<script type="dojo/method" event="onChange" args="direction">
+			var table = dojo.byId('table');
+			dojo.query('.dijitTextBox', table).forEach(function(node){
+				node.style.direction = direction;
+				node.parentNode.style.direction = direction;
+				dojo.forEach(node.className.split(' '), function(cls){
+					if(cls.indexOf('Rtl') > 0){
+						dojo.removeClass(node, cls);
+					}
+				});
+				if(direction == "rtl"){
+					dojo.forEach(node.className.split(' '), function(cls){
+						if(cls.indexOf('Box') > 0){
+							cls = cls.substr(0, cls.indexOf('Box')+3) + "Rtl" + cls.substr(cls.indexOf('Box')+3);
+						}else{
+							cls = cls + "Rtl";
+						}
+						dojo.addClass(node, cls);
+					});
+				}
+			});
+		</script>
+		<option value="ltr">left-to-right</option>
+		<option value="rtl">right-to-left</option>
+	</select></td></tr>
+	<tr><td style="text-align:right;">Theme:
+	<select dojoType="dijit.form.FilteringSelect" id="theme" style="font-size:14pt;" required="false" value="">
+		<script type="dojo/method" event="onChange" args="theme">
+			if(theme == "a11y"){ theme="dijit_a11y"; }
+			dojo.body().className = theme + ((this.isRealA11y && theme != "dijit_a11y") ? " dijit_a11y" : "");
+		</script>
+		<option value="tundra">tundra</option>
+		<option value="soria">soria</option>
+		<option value="nihilo">nihilo</option>
+		<option value="claro">claro</option>
+		<option value="a11y">a11y</option>
+	</select></td></tr>
+	</table>
+	<button dojoType="dijit.form.Button" onclick="doh.run()">Run tests</button>
+</body>
+</html>
diff --git a/dijit/tests/form/TextBox_sizes.js b/dijit/tests/form/TextBox_sizes.js
new file mode 100644
index 0000000..a051c6a
--- /dev/null
+++ b/dijit/tests/form/TextBox_sizes.js
@@ -0,0 +1,456 @@
+dojo.provide("dijit.tests.form.TextBox_sizes");
+
+try{
+	var userArgs = window.location.search.replace(/[\?&](dojoUrl|testUrl|testModule)=[^&]*/g,"").replace(/^&/,"?");
+
+doh.registerUrl('t.monospace.small.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.Courier.small.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.system.small.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+}catch(e){
+	doh.debug(e);
+}
+dojo.provide("dijit.tests.form.TextBox_sizes");
+
+try{
+	var userArgs = window.location.search.replace(/[\?&](dojoUrl|testUrl|testModule)=[^&]*/g,"").replace(/^&/,"?");
+
+doh.registerUrl('t.monospace.small.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.Courier.small.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.system.small.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+}catch(e){
+	doh.debug(e);
+}
+dojo.provide("dijit.tests.form.TextBox_sizes");
+
+try{
+	var userArgs = window.location.search.replace(/[\?&](dojoUrl|testUrl|testModule)=[^&]*/g,"").replace(/^&/,"?");
+
+doh.registerUrl('t.monospace.small.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.small.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=small&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.large.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=large&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.1em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.monospace.2em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=monospace'), 999999);
+doh.registerUrl('t.Courier.small.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.small.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=small&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.large.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=large&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.1em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.Courier.2em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=Courier'), 999999);
+doh.registerUrl('t.system.small.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.small.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=small&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.large.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=large&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.1em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=1em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.padded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=padded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.ltr.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.ltr.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.ltr.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=ltr&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.rtl.claro',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=claro&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.rtl.tundra',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=tundra&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+doh.registerUrl('t.system.2em.unPadded.rtl.a11y',dojo.moduleUrl('dijit', 'tests/form/TextBox_sizes.html?theme=a11y&dir=rtl&padding=unPadded&fontSize=2em&fontFamily=system'), 999999);
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dijit/tests/form/_autoComplete.html b/dijit/tests/form/_autoComplete.html
new file mode 100644
index 0000000..e02dedc
--- /dev/null
+++ b/dijit/tests/form/_autoComplete.html
@@ -0,0 +1,546 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.form.ComboBox Unit Test</title>
+
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../util/doh/robot/robot.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: false"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		var testWidget = "dijit.form.ComboBox";
+		var qstr = window.location.search.substr(1);
+		if(qstr.length){
+		        var qparts = qstr.split("&");
+		        for(var x=0; x<qparts.length; x++){
+		                var tp = qparts[x].split("=");
+		                if(tp[0] == "testWidget"){
+		                        testWidget = tp[1];
+					document.title = testWidget + " Unit Test";
+		                }
+		        }
+		}
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dijit.tests._data.SlowStore");
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require(testWidget);
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		function setVal2(val){
+			dojo.byId('value2').value=val;
+			var w = dijit.byId('datatest');
+			var item = w.item;
+			console.debug("Value changed to ["+val+"] in second box (#1652): datastore item label = " + (item?w.store.getLabel(item):'no item'));
+		}
+		function setVal3(val){
+			dojo.byId('value3').value=val;
+		}
+		function setVal4(val){
+			dojo.byId('value4').value=val;
+		}
+		var combo;
+		function myLabelFunc(item, store){
+			var label=store.getValue(item, 'name');
+			// DEMO: uncomment to chop off a character
+			//label=label.substr(0, label.length-1);
+			// DEMO: uncomment to set to lower case
+			label = label.toLowerCase();
+			return label;
+		}
+
+		function init(){
+			var testClass = dojo.getObject(testWidget);
+			// substitute testWidget for each dojoType=$testWidget
+			dojo.query('[dojoType="$testWidget"]').forEach(function(node){
+				node.setAttribute('dojoType', testWidget);
+			});
+			// substitute value=$-id-val by locating <select id="id"><option value="val">val</option></select>
+			dojo.query('*[value|="$"]').forEach(function(node){
+				var attrs = node.getAttribute('value').split("-");
+				var id = attrs[1];
+				var val = attrs[2];
+				if(testWidget == "dijit.form.ComboBox"){
+					val = dojo.query("> option[value='"+val+"']", id)[0].innerHTML;
+				}
+				node.setAttribute('value', val);
+			});
+			dojo.parser.parse(dojo.body());
+			store = new dojo.data.ItemFileReadStore({url: dojo.moduleUrl("dijit.tests._data", "states.json")});
+			combo = new testClass({
+				name:"prog",
+				title: "title attribute used for label",
+				autoComplete:false,
+				store: store,
+				searchAttr:"name"
+			}, dojo.byId("progCombo"));
+			store2 = new dojo.data.ItemFileReadStore({url: dojo.moduleUrl("dijit.tests._data", "countries.json")});
+			combo = new testClass({
+				name:"prog2",
+				autoComplete:false,
+				store:store2,
+				query:{type:'country'},
+				searchAttr:"name"
+			}, dojo.byId("progCombo2"));
+
+			new testClass({
+				name:"prog3",
+				autoComplete:false,
+				store:store2,
+				query:{type:'country'},
+				searchAttr:"name",
+				fetchProperties: {sort:[{attribute: 'name', descending: true}]}
+			}, dojo.byId("progCombo3"));
+		}
+		dojo.addOnLoad(init);
+
+		function toggleDisabled(button, widget){
+			widget = dijit.byId(widget);
+			button = dojo.byId(button);
+			widget.set('disabled',!widget.disabled);
+			button.innerHTML= widget.disabled ? "Enable" : "Disable";
+		}
+	</script>
+</head>
+
+<body class="claro">
+
+	<h1 class="testTitle" id="title"></h1>
+	<script>dojo.byId('title').appendChild(document.createTextNode(testWidget+" Unit Test"))</script>
+	<form id="form1" action="#" method="GET">
+
+		<p>Option tags, autoComplete=false, selectOnClick=true, default value of California, pageSize=30, custom labelFunc method</p>
+		<label for="setvaluetest">US State test 1</label> (200% Courier font):
+		<select id="setvaluetest"
+				name="state1"
+				dojoType="$testWidget"
+				style="width:50%;font-size:200%;font-family:Courier;"
+				autoComplete="false"
+				selectOnClick="true"
+				onBlur="dojo.byId('b1').value=dijit.byId('setvaluetest').value"
+				pageSize="30"
+		>
+			<script type="dojo/method" event="onChange">
+				if(this.lastlabelFuncMsg){
+					console.info(this.lastlabelFuncMsg);
+					this.lastlabelFuncMsg = '';
+				}
+				var newValue = arguments[0];
+				dojo.byId('oc1').value = newValue;
+				var itemLabel;
+				if(this.item === null){
+					itemLabel = "null";
+					if(testWidget != "dijit.form.ComboBox" && this.isValid() && this.textbox.value != ''){
+						console.error(this.id + ' has a null item, onChange value = ' + newValue + ', widget value = ' + this.value + ', displayed Value = ' + this.textbox.value);
+						this.itemError = true;
+					}
+				}else if(typeof this.item === "undefined"){
+					itemLabel = "undefined";
+					console.error(this.id + ' has an undefined item, onChange value = ' + newValue + ', widget value = ' + this.value + ', displayed Value = ' + this.textbox.value);
+					this.itemError = true;
+				}else{
+					itemLabel = this.labelFunc(this.item, this.store);
+					if(this.textbox.value != itemLabel){
+						console.error(this.id + ' has an inconsistent item value, item label = ' + itemLabel + ', onChange value = ' + newValue + ', widget value = ' + this.value + ', displayed Value = ' + this.textbox.value);
+						this.itemError = true;
+					}
+				}
+				dojo.byId('i1').value = itemLabel;
+			</script>
+			<script type="dojo/method" event="labelFunc">
+				var item = arguments[0];
+				var store = arguments[1];
+				var label = store.getValue(item, this.searchAttr);
+				var value = store.getValue(item, 'value');
+				if(!this.labelFuncCount){ this.labelFuncCount = 0; }
+				if(!this.labelFuncCounts){ this.labelFuncCounts = []; }
+				if(!this.labelFuncCounts[value]){ this.labelFuncCounts[value] = 0; }
+				this.labelFuncCount++;
+				this.labelFuncCounts[value]++;
+				this.lastlabelFuncMsg = 'my labelfunc ' + label + ' (' + value + '), count = ' + this.labelFuncCounts[value];
+				return label + ' (' + value + ')';
+			</script>
+			<option value="AL">Alabama</option>
+			<option value="AK">Alaska</option>
+			<option value="AS">American Samoa</option>
+			<option value="AZ">Arizona</option>
+			<option value="AR">Arkansas</option>
+			<option value="AE">Armed Forces Europe</option>
+			<option value="AP">Armed Forces Pacific</option>
+			<option value="AA">Armed Forces the Americas</option>
+			<option value="CA" selected>California</option>
+			<option value="CO">Colorado</option>
+			<option value="CT">Connecticut</option>
+			<option value="DE">Delaware</option>
+			<option value="DC">District of Columbia</option>
+			<option value="FM">Federated States of Micronesia</option>
+			<option value="FL">Florida</option>
+			<option value="GA">Georgia</option>
+			<option value="GU">Guam</option>
+			<option value="HI">Hawaii</option>
+			<option value="ID">Idaho</option>
+			<option value="IL">Illinois</option>
+			<option value="IN">Indiana</option>
+			<option value="IA">Iowa</option>
+			<option value="KS">Kansas</option>
+			<option value="KY">Kentucky</option>
+			<option value="LA">Louisiana</option>
+			<option value="ME">Maine</option>
+			<option value="MH">Marshall Islands</option>
+			<option value="MD">Maryland</option>
+			<option value="MA">Massachusetts</option>
+			<option value="MI">Michigan</option>
+			<option value="MN">Minnesota</option>
+			<option value="MS">Mississippi</option>
+			<option value="MO">Missouri</option>
+			<option value="MT">Montana</option>
+			<option value="NE">Nebraska</option>
+			<option value="NV">Nevada</option>
+			<option value="NH">New Hampshire</option>
+			<option value="NJ">New Jersey</option>
+			<option value="NM">New Mexico</option>
+			<option value="NY">New York</option>
+			<option value="NC">North Carolina</option>
+			<option value="ND">North Dakota</option>
+			<option value="MP">Northern Mariana Islands</option>
+			<option value="OH">Ohio</option>
+			<option value="OK">Oklahoma</option>
+			<option value="OR">Oregon</option>
+			<option value="PA">Pennsylvania</option>
+			<option value="PR">Puerto Rico</option>
+			<option value="RI">Rhode Island</option>
+			<option value="SC">South Carolina</option>
+			<option value="SD">South Dakota</option>
+			<option value="TN">Tennessee</option>
+			<option value="TX">Texas</option>
+			<option value="UT">Utah</option>
+			<option value="VT">Vermont</option>
+			<option value="VI">Virgin Islands, U.S.</option>
+			<option value="VA">Virginia</option>
+			<option value="WA">Washington</option>
+			<option value="WV">West Virginia</option>
+			<option value="WI">Wisconsin</option>
+			<option value="WY">Wyoming</option>
+		</select>
+		<br>onChange:<input id="oc1" disabled value="not fired yet!" autocomplete="off">
+		<br>value:<input id="v1" disabled value="not fired yet!" autocomplete="off">
+		<br>blur:<input id="b1" disabled value="not fired yet!" autocomplete="off">
+		<br>this.item:<input id="i1" disabled value="no onChange yet!" autocomplete="off">
+		<input type="button" id="sv1_1" value="Set displayed value to Kentucky" onClick="dijit.byId('setvaluetest').set('displayedValue', 'Kentucky')">
+	        <input type="button" id="sv1_2" value="Set displayed value to Canada" onClick="dijit.byId('setvaluetest').set('displayedValue', 'Canada')">
+	        <input type="button" id="sv1_3" value="Set value to null" onClick="dijit.byId('setvaluetest').set('value', null)">
+	        <input type="button" id="sv1_4" value="Get value" onClick="dojo.byId('v1').value=dijit.byId('setvaluetest').get('value')">
+
+		<hr>
+
+		<div dojoType="dojo.data.ItemFileReadStore" jsId="stateStore"
+			url="../_data/states.json"></div>
+		<div dojoType="dijit.tests._data.SlowStore" jsId="slowStateStore"
+			url="../_data/states.json"></div>
+
+		<div dojoType="dojo.data.ItemFileReadStore" jsId="dijitStore"
+			url="../_data/dijits.json"></div>
+
+		<p>Data store, autoComplete=true:</p>
+		<label for="datatest">US State test 2</label> (8pt font):
+		<input dojoType="$testWidget"
+				value="$-setvaluetest-CA"
+				store="stateStore"
+				searchAttr="name"
+				style="width: 200px; font-size: 8pt;"
+				name="state2"
+				onChange="setVal2"
+				id="datatest"
+		>
+		<br>onChange:<input id="value2" disabled value="not fired yet!" autocomplete="off">
+		<hr>
+		<p>Artificially slowed-down data store, autoComplete=true:</p>
+		<label for="slow">US State test slow</label>:
+		<input dojoType="$testWidget"
+				value="$-setvaluetest-CA"
+				store="slowStateStore"
+				searchAttr="name"
+				name="stateSlow"
+				onChange="dojo.byId('ocSlow').value=arguments[0]"
+				id="slow"
+		>
+		<br>onChange:<input id="ocSlow" disabled value="not fired yet!" autocomplete="off">
+		<button id="slowDestroy" onclick="dijit.byId('slow').destroy();return false">Destroy widget to test in-flight query cancel</button>
+		<hr>
+
+		<label for="datatestDijit">Dijit List test #1</label> (150% font):
+		<input dojoType="$testWidget"
+				value="dijit.Editor"
+				store="dijitStore"
+				searchAttr="className"
+				style="width: 200px; font-size: 150%;"
+				name="dijitList1"
+				id="datatestDijit"
+		>
+		<span>Hey look, this one is kind of useful.</span>
+		<hr>
+
+		<p>Initially disabled, url, autoComplete=false:</p>
+		<label for="combo3">US State test 3: </label>
+	 	<input id="combo3"
+	 			dojoType="$testWidget"
+	 			value="$-setvaluetest-CA"
+				store="stateStore"
+				searchAttr="name"
+				style="width: 300px;"
+				name="state3"
+				autoComplete="false"
+				onChange="setVal3"
+				disabled
+		>
+		<br>onChange:<input id="value3" disabled value="not fired yet!" autocomplete="off">
+		<div>
+			<button id="combo3_disable" onclick='toggleDisabled("combo3_disable", "combo3"); return false;' tabIndex="-1">Enable</button>
+		</div>
+		<hr>
+		<p>Data store, autoComplete=false required=true and highlightMatch="none"</p>
+		<label for="combobox4">US State test 4: </label>
+		<input dojoType="$testWidget"
+				value=""
+				store="stateStore"
+				searchAttr="name"
+				style="width: 300px;"
+				name="state4"
+				onChange="setVal4"
+				autoComplete="false"
+				id="combobox4"
+				required="true"
+				highlightMatch="none"
+		>
+		<br>onChange:<input id="value4" disabled value="not fired yet!" autocomplete="off">
+		<hr>
+		<p>test that title used as label is preserved on input</p>
+		<select id="preservetitletest"
+				name="titletest"
+				dojoType="$testWidget"
+				style="width:50%;font-family:Courier;"
+				autoComplete="false"
+				selectOnClick="true"
+				pageSize="5"
+				title="New England States"
+		>
+			<option value="ct">Connecticut</option>
+			<option value="me">Maine</option>
+			<option value="ma">Massachusetts</option>
+			<option value="nh">New Hampshire</option>
+			<option value="vt">Vermont</option>
+		</select>
+		<hr>
+		<p>No arrow, data store which searches and highlights matches anywhere in the string</p>
+	 	<input dojoType="$testWidget"
+				id="arrowless"
+	 			value="$-setvaluetest-CA"
+				store="stateStore"
+				searchAttr="name"
+				queryExpr="*${0}*"
+				name="state5"
+				autoComplete="false"
+				hasDownArrow="false"
+				highlightMatch="all"
+		>
+		<hr>
+		<p>Created programmatically</p>
+		<input id="progCombo">
+		<hr>
+		<p>Created programmatically with an initial query.  (Limits list to items with type = country.)</p>
+		<input id="progCombo2">
+		<hr>
+		<p>Created programmatically with an ItemFileReadStore and a descending sort.  (Limits list to items with type = country.)</p>
+		<input id="progCombo3">
+		<hr>
+		<p>With option tags, autoComplete=true, pageSize=30, and a descending sort.</p>
+		<select
+				name="descending"
+				id="descending"
+				dojoType="$testWidget"
+				style="width:50%;font-size:200%;font-family:Courier;"
+				autoComplete="true"
+				onChange="dojo.byId('oc1').value=arguments[0]"
+				pageSize="30"
+				fetchProperties="{sort:[{attribute: 'name', descending: true}]}"
+		>
+			<option value="AL">Alabama</option>
+			<option value="AK">Alaska</option>
+			<option value="AS">American Samoa</option>
+			<option value="AZ">Arizona</option>
+			<option value="AR">Arkansas</option>
+			<option value="AE">Armed Forces Europe</option>
+			<option value="AP">Armed Forces Pacific</option>
+			<option value="AA">Armed Forces the Americas</option>
+			<option value="CA" selected>California</option>
+			<option value="CO">Colorado</option>
+			<option value="CT">Connecticut</option>
+			<option value="DE">Delaware</option>
+			<option value="DC">District of Columbia</option>
+			<option value="FM">Federated States of Micronesia</option>
+			<option value="FL">Florida</option>
+			<option value="GA">Georgia</option>
+			<option value="GU">Guam</option>
+			<option value="HI">Hawaii</option>
+			<option value="ID">Idaho</option>
+			<option value="IL">Illinois</option>
+			<option value="IN">Indiana</option>
+			<option value="IA">Iowa</option>
+			<option value="KS">Kansas</option>
+			<option value="KY">Kentucky</option>
+			<option value="LA">Louisiana</option>
+			<option value="ME">Maine</option>
+			<option value="MH">Marshall Islands</option>
+			<option value="MD">Maryland</option>
+			<option value="MA">Massachusetts</option>
+			<option value="MI">Michigan</option>
+			<option value="MN">Minnesota</option>
+			<option value="MS">Mississippi</option>
+			<option value="MO">Missouri</option>
+			<option value="MT">Montana</option>
+			<option value="NE">Nebraska</option>
+			<option value="NV">Nevada</option>
+			<option value="NH">New Hampshire</option>
+			<option value="NJ">New Jersey</option>
+			<option value="NM">New Mexico</option>
+			<option value="NY">New York</option>
+			<option value="NC">North Carolina</option>
+			<option value="ND">North Dakota</option>
+			<option value="MP">Northern Mariana Islands</option>
+			<option value="OH">Ohio</option>
+			<option value="OK">Oklahoma</option>
+			<option value="OR">Oregon</option>
+			<option value="PA">Pennsylvania</option>
+			<option value="PR">Puerto Rico</option>
+			<option value="RI">Rhode Island</option>
+			<option value="SC">South Carolina</option>
+			<option value="SD">South Dakota</option>
+			<option value="TN">Tennessee</option>
+			<option value="TX">Texas</option>
+			<option value="UT">Utah</option>
+			<option value="VT">Vermont</option>
+			<option value="VI">Virgin Islands, U.S.</option>
+			<option value="VA">Virginia</option>
+			<option value="WA">Washington</option>
+			<option value="WV">West Virginia</option>
+			<option value="WI">Wisconsin</option>
+			<option value="WY">Wyoming</option>
+		</select>
+		<hr>
+		<p>Special characters</p>
+		<p>The drop down list should be:</p>
+		<ul>
+		   <li>sticks & stones</li>
+		   <li>rags --> riches</li>
+		   <li>more\less</li>
+		   <li>3 * 5</li>
+		</ul>
+		<label for="specialchars">Special chars:</label>
+		<select dojoType="$testWidget"
+			name="specialchars"
+			id="specialchars"
+		>
+			<option value="sticks" selected>sticks & stones</option>
+			<option value="rags">rags --> riches</option>
+			<option value="more">more\less</option>
+			<option value="times">3 * 5</option>
+		</select>
+		<hr>
+		<p>Japanese</p>
+		<p>Try typing &#x6771;&#x533A; (East), &#x897F;&#x533A; (West), &#x5317;&#x533A; (North), &#x5357;&#x533A; (South) and a few choices will pop up.</p>
+		<label for="japanese">Japanese list:</label>
+		<select name="japanese" id="japanese" dojoType="$testWidget" style="width: 300px;" autoComplete="true" required="true" value="">
+			<option value="nanboku">&#x5357;&#x5317; (Nanboku)</option>
+			<option value="touzai">&#x6771;&#x897F; (Touzai)</option>
+			<option value="toukyou">&#x6771;&#x4EAC; (Tokyo)</option>
+			<option value="higashiku">&#x6771;&#x533A; (East)</option>
+			<option value="nishiku">&#x897F;&#x533A; (West)</option>
+			<option value="minamiku">&#x5357;&#x533A; (South)</option>
+			<option value="kitaku">&#x5317;&#x533A; (North)</option>
+		</select>
+		<hr>
+		<p>Custom labelFunc (value in textbox should be lower case when onChange is called), autoComplete=true, prompt message when field is blank:</p>
+		<label for="labelFunc">custom label function</label>
+		<input
+				id="labelFunc"
+				dojoType="$testWidget"
+				value="$-setvaluetest-OR"
+				labelFunc="myLabelFunc"
+				store="stateStore"
+				name="labelFunc"
+				autoComplete="true"
+				labelAttr="label"
+				labelType="html"
+				promptMessage="Please enter a state"
+				invalidMessage="Invalid state name."
+		>
+		<input type="button" onclick="dijit.byId('labelFunc').set('readOnly',false);" value="Remove readOnly">
+		<input type="button" onclick="dijit.byId('labelFunc').set('readOnly',true);" value="Set readOnly">
+		<input type="button" onclick="dijit.byId('labelFunc').set('disabled',false);" value="Remove disabled">
+		<input type="button" onclick="dijit.byId('labelFunc').set('disabled',true);" value="Set disabled">
+		<hr>
+		<input type="button" value="Create one in a window" onclick="var win=window.open(window.location);">
+		<input type="submit">
+		<script>
+			// so robot can get to it easily
+			document.displayData=function() {
+				var f = document.getElementById("form1");
+				var s = "";
+				for (var i = 0; i < f.elements.length; i++) {
+					var elem = f.elements[i];
+					if (elem.nodeName.toLowerCase() == "button" || elem.type=="submit" || elem.type=="button")  { continue; }
+					s += elem.name + ": " + elem.value + "\n";
+				}
+				return s;
+			}
+		</script>
+		<button name="button" onclick="alert(document.displayData()); return false;">view data</button>
+
+	</form>
+	
+	<hr>
+	<p>test placeholder</p>
+	<select id="placeholdertest"
+			name="placetest"
+			dojoType="$testWidget"
+			style="width:50%;font-family:Courier;"
+			autoComplete="false"
+			selectOnClick="true"
+			pageSize="5"
+			placeHolder="Select a New England State"
+			value=""
+	>
+		<option value="ct">Connecticut</option>
+		<option value="me">Maine</option>
+		<option value="ma">Massachusetts</option>
+		<option value="nh">New Hampshire</option>
+		<option value="vt">Vermont</option>
+	</select>
+	<p>
+	This is some text below the boxes. It shouldn't get pushed out of the way when search results get returned.
+	A native select tag to test IE bleed through problem:
+	</p>
+
+	<select id="native">
+	  <option>test for</option>
+	  <option>IE bleed through</option>
+	  <option>problem</option>
+	</select>
+
+	<div id="debugbox"></div>
+	<!-- maintain state of combo box if user presses back/forward button -->
+	<form name="_dojo_form" style="display:none" disabled="true"><textarea name="stabile" cols="80" rows="10"></textarea></form>
+</body>
+</html>
diff --git a/dijit/tests/form/images/Alabama.jpg b/dijit/tests/form/images/Alabama.jpg
new file mode 100644
index 0000000..f2018e6
Binary files /dev/null and b/dijit/tests/form/images/Alabama.jpg differ
diff --git a/dijit/tests/form/module.js b/dijit/tests/form/module.js
new file mode 100644
index 0000000..2fc3f2e
--- /dev/null
+++ b/dijit/tests/form/module.js
@@ -0,0 +1,55 @@
+dojo.provide("dijit.tests.form.module");
+
+try{
+	var userArgs = window.location.search.replace(/[\?&](dojoUrl|testUrl|testModule)=[^&]*/g,"").replace(/^&/,"?");
+
+	doh.registerUrl("dijit.tests.form.robot.Button_mouse", dojo.moduleUrl("dijit","tests/form/robot/Button_mouse.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.form.robot.Button_a11y", dojo.moduleUrl("dijit","tests/form/robot/Button_a11y.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.form.robot.test_validate", dojo.moduleUrl("dijit","tests/form/robot/test_validate.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.form.robot.DateTextBox", dojo.moduleUrl("dijit","tests/form/robot/DateTextBox.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.form.robot.TimeTextBox", dojo.moduleUrl("dijit","tests/form/robot/TimeTextBox.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.form.Form", dojo.moduleUrl("dijit", "tests/form/Form.html"), 99999999);
+	doh.registerUrl("dijit.tests.form.robot.Form", dojo.moduleUrl("dijit","tests/form/robot/Form.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.form.Select", dojo.moduleUrl("dijit", "tests/form/test_Select.html?mode=test"), 99999999);
+	doh.registerUrl("dijit.tests.form.robot.Select", dojo.moduleUrl("dijit", "tests/form/robot/Select.html"), 99999999);
+
+	doh.registerUrl("dijit.tests.form.robot.ComboBox_mouse", dojo.moduleUrl("dijit","tests/form/robot/_autoComplete_mouse.html"+(userArgs+"&testWidget=dijit.form.ComboBox").replace(/^&/,"?")), 99999999);
+	doh.registerUrl("dijit.tests.form.robot.ComboBox_a11y", dojo.moduleUrl("dijit","tests/form/robot/_autoComplete_a11y.html"+(userArgs+"&testWidget=dijit.form.ComboBox").replace(/^&/,"?")), 99999999);
+
+	doh.registerUrl("dijit.tests.form.robot.FilteringSelect_mouse", dojo.moduleUrl("dijit","tests/form/robot/_autoComplete_mouse.html"+(userArgs+"&testWidget=dijit.form.FilteringSelect").replace(/^&/,"?")), 99999999);
+	doh.registerUrl("dijit.tests.form.robot.FilteringSelect_a11y", dojo.moduleUrl("dijit","tests/form/robot/_autoComplete_a11y.html"+(userArgs+"&testWidget=dijit.form.FilteringSelect").replace(/^&/,"?")), 99999999);
+
+	doh.registerUrl("dijit.tests.form.robot.Slider_mouse", dojo.moduleUrl("dijit","tests/form/robot/Slider_mouse.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.form.robot.Slider_a11y", dojo.moduleUrl("dijit","tests/form/robot/Slider_a11y.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.form.robot.Spinner_mouse", dojo.moduleUrl("dijit","tests/form/robot/Spinner_mouse.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.form.robot.Spinner_a11y", dojo.moduleUrl("dijit","tests/form/robot/Spinner_a11y.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.form.CheckBox", dojo.moduleUrl("dijit", "tests/form/test_CheckBox.html"), 99999999);
+
+	doh.registerUrl("dijit.tests.form.robot.Textarea", dojo.moduleUrl("dijit","tests/form/robot/Textarea.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.form.robot.validationMessages", dojo.moduleUrl("dijit","tests/form/robot/validationMessages.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.tundra.ltr", dojo.moduleUrl("dijit", "tests/form/TextBox_sizes.html?theme=tundra&dir=ltr"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.tundra.rtl", dojo.moduleUrl("dijit", "tests/form/TextBox_sizes.html?theme=tundra&dir=rtl"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.tundra.quirks", dojo.moduleUrl("dijit", "tests/quirks.html?file=form/TextBox_sizes.html&theme=tundra&dir=ltr"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.claro.ltr", dojo.moduleUrl("dijit", "tests/form/TextBox_sizes.html?theme=claro&dir=ltr"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.claro.rtl", dojo.moduleUrl("dijit", "tests/form/TextBox_sizes.html?theme=claro&dir=rtl"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.claro.quirks", dojo.moduleUrl("dijit", "tests/quirks.html?file=form/TextBox_sizes.html&theme=claro&dir=ltr"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.soria.ltr", dojo.moduleUrl("dijit", "tests/form/TextBox_sizes.html?theme=soria&dir=ltr"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.soria.rtl", dojo.moduleUrl("dijit", "tests/form/TextBox_sizes.html?theme=soria&dir=rtl"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.soria.quirks", dojo.moduleUrl("dijit", "tests/quirks.html?file=form/TextBox_sizes.html&theme=soria&dir=rtl"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.nihilo.ltr", dojo.moduleUrl("dijit", "tests/form/TextBox_sizes.html?theme=nihilo&dir=ltr"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.nihilo.rtl", dojo.moduleUrl("dijit", "tests/form/TextBox_sizes.html?theme=nihilo&dir=rtl"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.nihilo.quirks", dojo.moduleUrl("dijit", "tests/quirks.html?file=form/TextBox_sizes.html&theme=nihilo&dir=rtl"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.a11y.ltr", dojo.moduleUrl("dijit", "tests/form/TextBox_sizes.html?a11y=1&dir=ltr"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.a11y.rtl", dojo.moduleUrl("dijit", "tests/form/TextBox_sizes.html?a11y=1&dir=rtl"), 99999999);
+	doh.registerUrl("dijit.tests.form.TextBox_sizes.a11y.quirks", dojo.moduleUrl("dijit", "tests/quirks.html?file=form/TextBox_sizes.html&a11y=1&dir=ltr"), 99999999);
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dijit/tests/form/robot/Button_a11y.html b/dijit/tests/form/robot/Button_a11y.html
new file mode 100644
index 0000000..7b743ae
--- /dev/null
+++ b/dijit/tests/form/robot/Button_a11y.html
@@ -0,0 +1,468 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Button Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Button.html');
+
+				var submitCount = 0, resetCount = 0;
+
+
+				doh.register("setup", function(){
+					doh.robot.sequence(function(){
+						dojo.connect(dijit.byId("testForm"), "onSubmit", function(){
+							submitCount++;
+						});
+						dojo.connect(dijit.byId("testForm"), "onReset", function(){
+							resetCount++;
+						})
+					});
+				});
+
+				doh.register("dijit.form.Button", [
+					{
+						name: "enabled",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.sequence(function(){ dojo.byId("input").focus(); });
+
+							var clicks = 0;
+							dijit.byId("1465").set("onClick", function(){ clicks++; });
+
+
+							// tab into button to get focus
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							// and activate	with space / enter
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(2, clicks, "both space and enter click the button");
+							}), 500);
+							return d;
+						}
+					},
+					{
+						name: "disabled no focus",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.is("1465", dijit.getEnclosingWidget(dojo.global.dijit._curFocus).id, "focus starting on 1465");
+
+							dijit.byId("1467").set("disabled", true);
+
+							// tab over disabled "View" button to "Create" combo-button
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								console.log("current focus is ", dojo.global.dijit._curFocus);
+								doh.is("comboCreate", dijit.getEnclosingWidget(dojo.global.dijit._curFocus).id, "focus jumped to combo create (left part of button)");
+							}), 500);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("dijit.form.DropDownButton", [
+					{
+						name: "down arrow opens menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dijit.byId("edit").focus();
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("editMenu"), "edit menu is visible: " + dijit.byId("editMenu").domNode.style.cssText);
+								doh.is("cut", dojo.global.dijit._curFocus.id, "focus is on menu");
+							}), 500);
+							return d;
+						}
+					},
+
+					{
+						name: "esc closes menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("editMenu"), "edit menu is hidden: " + dijit.byId("editMenu").domNode.style.cssText);
+								doh.is("edit", dojo.global.dijit._curFocus.id, "focus is back on button");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "space opens menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dijit.byId("edit").focus();
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("editMenu"), "edit menu is visible: " + dijit.byId("editMenu").domNode.style.cssText);
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "space executes menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("editMenu"), "edit menu is hidden: " + dijit.byId("editMenu").domNode.style.cssText);
+								doh.is("edit", dojo.global.dijit._curFocus.id, "focus is back on button");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "enter opens menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dijit.byId("edit").focus();
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("editMenu"), "edit menu is visible: " + dijit.byId("editMenu").domNode.style.cssText);
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "tab key closes popup, goes back to button",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("editMenu"), "edit menu is hidden: " + dijit.byId("editMenu").domNode.style.cssText);
+								doh.is("edit", dojo.global.dijit._curFocus.id, "focus is back on button");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "enter opens menu again",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dijit.byId("edit").focus();
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("editMenu"), "edit menu is visible: " + dijit.byId("editMenu").domNode.style.cssText);
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "enter closes menu (#4772)",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("editMenu"), "edit menu is hidden: " + dijit.byId("editMenu").domNode.style.cssText);
+								doh.is("edit", dojo.global.dijit._curFocus.id, "focus is back on button");
+							}), 1000);
+							return d;
+						}
+					}
+
+				]);
+
+				doh.register("dijit.form.ComboButton", [
+					{
+						name: "tab to button",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.sequence(function(){
+								dijit.byId("color").focus();
+							});
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							var leftPart = dojo.query(".dijitButtonContents", dojo.byId("save"))[0];
+							doh.t(leftPart, "found left part of button");
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(leftPart, dojo.global.dijit._curFocus, "focused on left part");
+								console.log("cur focus: ",  dojo.global.dijit._curFocus);
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "click button",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var clicked = false;
+							dijit.byId("save").set("onClick", function(){ clicked = true; });
+
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(clicked, "button was clicked");
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "tab to drop down arrow",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var rightPart = dojo.query(".dijitDownArrowButton", dojo.byId("save"))[0];
+							doh.t(rightPart, "found right part of button");
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(rightPart, dojo.global.dijit._curFocus, "focused on right part of combo");
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "down arrow opens menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var rightPart = dojo.query(".dijitDownArrowButton", dojo.byId("save"))[0];
+							doh.t(rightPart, "found right part of button");
+
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("saveMenu"), "save menu is visible: " + dijit.byId("saveMenu").domNode.style.cssText);
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "esc closes menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var rightPart = dojo.query(".dijitDownArrowButton", dojo.byId("save"))[0];
+							doh.t(rightPart, "found right part of button");
+
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("saveMenu"), "save menu was closed: " + dijit.byId("saveMenu").domNode.style.cssText);
+								doh.is(rightPart, dojo.global.dijit._curFocus, "refocused on right part of combo");
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "enter key opens menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("saveMenu"), "save menu is visible: " + dijit.byId("saveMenu").domNode.style.cssText);
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "tab closes menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var rightPart = dojo.query(".dijitDownArrowButton", dojo.byId("save"))[0];
+							doh.t(rightPart, "found right part of button");
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("saveMenu"), "save menu was closed: " + dijit.byId("saveMenu").domNode.style.cssText);
+								doh.is(rightPart, dojo.global.dijit._curFocus, "refocused on right part of combo");
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "tab closes menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.sequence(function(){
+								// Focus element before "save" ComboButton
+								dijit.byId("color").focus();
+
+								// And disable the ComboButton
+								dijit.byId("save").set("disabled", true);
+							});
+
+							// Tab should skip over the ComboButton entirely
+							doh.robot.keyPress(dojo.keys.TAB, 100, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var focusedWidget = dijit.getEnclosingWidget(dojo.global.dijit._curFocus);
+								doh.isNot("save", focusedWidget && focusedWidget.id, "didn't focus on combo");
+							}), 500);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("dijit.form.ToggleButton", [
+					{
+						name: "change value",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var checked = dijit.byId("toggle1").get("checked");
+							dijit.byId("toggle1").set("onChange", function(v){ checked = v; });
+							doh.t(checked, "toggle1 initially checked");
+
+							doh.robot.sequence(function(){
+								dijit.byId("toggle1").focus();
+							});
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(checked, "toggle1 unchecked");
+							}), 1000);
+							return d;
+						}
+					}
+				]);
+
+				dojo.forEach(["SPACE", "ENTER"], function(key){
+					doh.register("Invoke Submit and Reset Buttons by " + key, [
+					{
+						name: "click Submit",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							submitCount = 0;
+							doh.robot.sequence(function(){
+								dijit.byId("bSubmit").focus();
+							});
+							doh.robot.keyPress(dojo.keys[key], 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(1, submitCount, (key + ": # of times submit invoked " + submitCount));
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "click Reset",
+						timeout: 7000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							resetCount = 0;
+							dijit.byId("testName").value = "";
+
+
+							doh.robot.sequence(function(){
+								dijit.byId("testName").focus();
+							},500);
+							doh.robot.typeKeys("test", 500, 2000);
+
+							doh.robot.sequence(function(){
+								dijit.byId("bReset").focus();
+							},500);
+							doh.robot.keyPress(dojo.keys[key], 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(1, resetCount, (key + ": reset should be invoked 1 time. actual count = " + resetCount));
+								doh.is("",dijit.byId("testName").value, "Name field has been reset");
+							}), 1000);
+							return d;
+						}
+					}
+				]);
+				});
+
+				doh.register("Submit via ENTER key on input", {
+					name: "enter on input",
+					timeout: 5000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						submitCount = 0;
+						doh.robot.sequence(function(){
+							dijit.byId("testName").focus();
+						});
+						doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.is(1, submitCount, "submitted via enter key on input");
+						}), 500);
+
+						return d;
+					}
+				});
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/form/robot/Button_mouse.html b/dijit/tests/form/robot/Button_mouse.html
new file mode 100644
index 0000000..0333284
--- /dev/null
+++ b/dijit/tests/form/robot/Button_mouse.html
@@ -0,0 +1,689 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Button Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Button.html');
+
+				doh.register("dijit.form.Button", [
+					{
+						name: "enabled",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var clicked = false;
+							dijit.byId("1467").set("onClick", function(){ clicked = true; });
+
+							doh.robot.mouseMoveAt("1467", 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(clicked, "click event was fired");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "disabled",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var clicked = false;
+							dijit.byId("disabled").set("onClick", function(){ clicked = true; });
+
+							doh.robot.mouseMoveAt("disabled", 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								if(!dojo.isWebKit){		// webkit bug, see #11064
+									doh.f(dojo.isDescendant(dojo.global.dijit._curFocus, dijit.byId("disabled").domNode), "not focused on button")
+								}
+								doh.f(clicked, "click event wasn't fired");
+							}), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("dijit.form.DropDownButton", [
+					{
+						name: "click button",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMoveAt("edit", 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("editMenu"), "edit menu is visible: " + dijit.byId("editMenu").domNode.style.cssText);
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "click menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMoveAt("copy", 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("editMenu"), "edit menu was closed: " + dijit.byId("editMenu").domNode.style.cssText);
+							}), 1000);
+							return d;
+						}
+					}
+
+				]);
+
+				doh.register("dijit.form.ComboButton", [
+					{
+						name: "click button",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var leftPart = dojo.query(".dijitButtonContents", dojo.byId("save"))[0];
+							doh.t(leftPart, "found left part of button");
+
+							var clicked = false;
+							dijit.byId("save").set("onClick", function(){ clicked = true; });
+
+							doh.robot.mouseMoveAt(leftPart, 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(clicked, "click event was fired");
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "click drop down button",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var rightPart = dojo.query(".dijitDownArrowButton", dojo.byId("save"))[0];
+							doh.t(rightPart, "found right part of button");
+
+							doh.robot.mouseMoveAt(rightPart, 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("saveMenu"), "save menu is visible: " + dijit.byId("saveMenu").domNode.style.cssText);
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "click menu",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMoveAt("saveAs", 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("saveMenu"), "save menu was closed: " + dijit.byId("saveMenu").domNode.style.cssText);
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "disabled click button",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var leftPart = dojo.query(".dijitButtonContents", dojo.byId("save"))[0];
+							doh.t(leftPart, "found left part of button");
+
+							var clicked = false;
+							dijit.byId("save").set("onClick", function(){ clicked = true; });
+
+							dijit.byId("save").set("disabled", true);
+
+							doh.robot.mouseMoveAt(leftPart, 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								if(!dojo.isWebKit){ // webkit bug, see #11064
+									doh.f(dojo.isDescendant(dojo.global.dijit._curFocus, dijit.byId("save").domNode), "not focused on button")
+								}
+								doh.f(clicked, "click event wasn't fired");
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "disabled click drop down button",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var rightPart = dojo.query(".dijitDownArrowButton", dojo.byId("save"))[0];
+							doh.t(rightPart, "found right part of button");
+
+							doh.robot.mouseMoveAt(rightPart, 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								if(!dojo.isWebKit){		// webkit bug, see #11064
+									doh.f(dojo.isDescendant(dojo.global.dijit._curFocus, dijit.byId("save").domNode), "not focused on button")
+								}
+								doh.t(isHidden("saveMenu"), "save menu is still hidden: " + dijit.byId("saveMenu").domNode.style.cssText);
+							}), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("dijit.form.ToggleButton", [
+					{
+						name: "initially checked",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var checked = dijit.byId("toggle1").get("checked");
+							dijit.byId("toggle1").set("onChange", function(v){ checked = v; });
+							doh.t(checked, "toggle1 initially checked");
+
+							doh.robot.mouseMoveAt("toggle1", 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(checked, "toggle1 unchecked");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "initially unchecked",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var checked = dijit.byId("toggle2").get("checked");
+							dijit.byId("toggle2").set("onChange", function(v){ checked = v; });
+							doh.f(checked, "toggle2 initially unchecked");
+
+							doh.robot.mouseMoveAt("toggle2", 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(checked, "toggle2 checked");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "disabled",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dijit.byId("toggle1").set("disabled", true);
+
+							var changed = false;
+							dijit.byId("toggle1").set("onChange", function(v){ changed = true; });
+
+							doh.robot.mouseMoveAt("toggle1", 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								if(!dojo.isWebKit){		// webkit bug, see #11064
+									doh.f(dojo.isDescendant(dojo.global.dijit._curFocus, dijit.byId("toggle1").domNode), "not focused on button")
+								}
+								doh.f(changed, "value didn't change");
+							}), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("get/set", [
+					{
+						name: "change label",
+						runTest: function(){
+							dijit.byId("edit").set("label", "hi!");
+							doh.is("hi!", dijit.byId("edit").containerNode.innerHTML);
+						}
+					},
+
+					{
+						name: "icon",
+						runTest: function(){
+							doh.f(dojo.hasClass(dijit.byId("1467").iconNode, "plusIcon"), "doesn't plus icon class");
+							dijit.byId("1467").set("iconClass", "plusIcon");
+							doh.t(dojo.hasClass(dijit.byId("1467").iconNode, "plusIcon"), "has plus icon class");
+
+							// switching icon erases old one
+							dijit.byId("1467").set("iconClass", "noteIcon");
+							doh.f(dojo.hasClass(dijit.byId("1467").iconNode, "plusIcon"), "doesn't plus icon class");
+						}
+					},
+
+					{
+						name: "disable",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dijit.byId("save").set("disabled", true);
+
+							var d = new doh.Deferred();
+
+							// click left side of button
+							var leftPart = dojo.query(".dijitButtonContents", dojo.byId("save"))[0];
+							doh.t(leftPart, "found left part of button");
+							var clicked = false;
+							dijit.byId("save").set("onClick", function(){ clicked = true; });
+							doh.robot.mouseMoveAt(leftPart, 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							// click right side of button
+							var rightPart = dojo.query(".dijitDownArrowButton", dojo.byId("save"))[0];
+							doh.t(rightPart, "found right part of button");
+							doh.robot.mouseMoveAt(rightPart, 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(clicked, "click event was not fired");
+								doh.f(isVisible("saveMenu"), "save menu is hidden: " + dijit.byId("saveMenu").domNode.style.cssText);
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("submit", [
+					{
+						name: "plain",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var nameBox = dojo.byId("buttonName");
+							var valueBox = dojo.byId("buttonValue");
+							nameBox.value = 'INIT';
+							valueBox.value = 'INIT';
+
+							doh.robot.mouseMoveAt('Plain', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(nameBox.value, "Plain", "Plain name");
+								doh.is(valueBox.value, "Plain Submit", "Plain value");
+							}), 1000);
+
+							return d;
+						}
+					},
+					{
+						name: "combo left",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var nameBox = dojo.byId("buttonName");
+							var valueBox = dojo.byId("buttonValue");
+							nameBox.value = 'INIT';
+							valueBox.value = 'INIT';
+
+							doh.robot.mouseMoveAt('Combo', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(nameBox.value, "Combo", "Combo name");
+								doh.is(valueBox.value, "Combo Submit", "Combo value");
+							}), 1000);
+
+							return d;
+						}
+					},
+					{
+						name: "combo right",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var nameBox = dojo.byId("buttonName");
+							var valueBox = dojo.byId("buttonValue");
+							nameBox.value = 'INIT';
+							valueBox.value = 'INIT';
+
+							var downArrowNode = dojo.query(".dijitDownArrowButton", dojo.byId("Combo"))[0];
+
+							doh.robot.mouseMoveAt(downArrowNode, 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(nameBox.value, "INIT", "Combo Down Arrow name");
+								doh.is(valueBox.value, "INIT", "Combo Down Arrow value");
+							}), 1000);
+
+							return d;
+						}
+					},
+					{
+						name: "combo menu",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var nameBox = dojo.byId("buttonName");
+							var valueBox = dojo.byId("buttonValue");
+							nameBox.value = 'INIT';
+							valueBox.value = 'INIT';
+
+							doh.robot.mouseMoveAt("ComboMenuItem", 1000);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(nameBox.value, "", "Combo Arrow name");
+								doh.is(valueBox.value, "", "Combo Arrow value");
+							}), 1000);
+
+							return d;
+						}
+					},
+					{
+						name: "drop down",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var nameBox = dojo.byId("buttonName");
+							var valueBox = dojo.byId("buttonValue");
+							nameBox.value = 'INIT';
+							valueBox.value = 'INIT';
+
+							doh.robot.mouseMoveAt('DropDown', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(nameBox.value, "DropDown", "DropDown name");
+								doh.is(valueBox.value, "DropDown Submit", "DropDown value");
+							}), 1000);
+
+							return d;
+						}
+					},
+					{
+						name: "drop down menu",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var nameBox = dojo.byId("buttonName");
+							var valueBox = dojo.byId("buttonValue");
+							nameBox.value = 'INIT';
+							valueBox.value = 'INIT';
+
+							doh.robot.mouseMoveAt("DropDownMenuItem", 1000);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(nameBox.value, "", "DropDown Arrow name");
+								doh.is(valueBox.value, "", "DropDown Arrow value");
+							}), 1000);
+
+							return d;
+						}
+					},
+					{
+						name: "disabled",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var nameBox = dojo.byId("buttonName");
+							var valueBox = dojo.byId("buttonValue");
+							nameBox.value = 'INIT';
+							valueBox.value = 'INIT';
+
+							doh.robot.mouseMoveAt('Disabled', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(nameBox.value, "INIT", "Disabled name");
+								doh.is(valueBox.value, "INIT", "Disabled value");
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("onClick", [
+					{
+						name: "reset: none",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var valueBox = dojo.byId("onClickName");
+							valueBox.value = '1';
+							doh.robot.mouseMoveAt('reset1', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(dojo.byId('onClickName').value, "RESET");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "reset native: none",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var valueBox = dojo.byId("onClickName");
+							valueBox.value = '1';
+							doh.robot.mouseMoveAt('reset1N', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(dojo.byId('onClickName').value, "RESET");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "reset: return false",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var valueBox = dojo.byId("onClickName");
+							valueBox.value = '2';
+							doh.robot.mouseMoveAt('reset2', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(dojo.byId('onClickName').value, "2");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "reset native: return false",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var valueBox = dojo.byId("onClickName");
+							valueBox.value = '2';
+							doh.robot.mouseMoveAt('reset2N', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(dojo.byId('onClickName').value, "2");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "reset: return true",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var valueBox = dojo.byId("onClickName");
+							valueBox.value = '3';
+							doh.robot.mouseMoveAt('reset3', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(dojo.byId('onClickName').value, "RESET");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "reset native: return true",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var valueBox = dojo.byId("onClickName");
+							valueBox.value = '3';
+							doh.robot.mouseMoveAt('reset3N', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(dojo.byId('onClickName').value, "RESET");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "reset: return",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var valueBox = dojo.byId("onClickName");
+							valueBox.value = '4';
+							doh.robot.mouseMoveAt('reset4', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(dojo.byId('onClickName').value, "RESET");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "reset native: return",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var valueBox = dojo.byId("onClickName");
+							valueBox.value = '4';
+							doh.robot.mouseMoveAt('reset4N', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(dojo.byId('onClickName').value, "RESET");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "reset: empty",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var valueBox = dojo.byId("onClickName");
+							valueBox.value = '5';
+							doh.robot.mouseMoveAt('reset5', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(dojo.byId('onClickName').value, "RESET");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "reset native: empty",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var valueBox = dojo.byId("onClickName");
+							valueBox.value = '5';
+							doh.robot.mouseMoveAt('reset5N', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(dojo.byId('onClickName').value, "RESET");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("resize", [
+					{
+						name: "ComboButton",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var combo = dijit.byId('combo_default');
+							var origSize = combo.domNode.scrollWidth;
+
+							doh.robot.mouseMoveAt('changeLabels', 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.isNot(origSize, combo.domNode.scrollWidth, "ComboButton size");
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/form/robot/ComboBox_a11y.html b/dijit/tests/form/robot/ComboBox_a11y.html
new file mode 100644
index 0000000..8c04f69
--- /dev/null
+++ b/dijit/tests/form/robot/ComboBox_a11y.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+	<HEAD>
+		<TITLE>ComboBox General/Keyboard Robot Test</TITLE>
+	</HEAD>
+	<BODY>
+		Loading ComboBox a11y robot test.
+		<SCRIPT>
+			window.location.replace("_autoComplete_a11y.html?testWidget=dijit.form.ComboBox"+window.location.search.replace(/^\?/,"&"));
+		</SCRIPT>
+	</BODY>
+</HTML>
diff --git a/dijit/tests/form/robot/ComboBox_mouse.html b/dijit/tests/form/robot/ComboBox_mouse.html
new file mode 100644
index 0000000..7bb349c
--- /dev/null
+++ b/dijit/tests/form/robot/ComboBox_mouse.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+	<HEAD>
+		<TITLE>ComboBox Mouse Robot Test</TITLE>
+	</HEAD>
+	<BODY>
+		Loading ComboBox mouse robot test.
+		<SCRIPT>
+			window.location.replace("_autoComplete_mouse.html?testWidget=dijit.form.ComboBox"+window.location.search.replace(/^\?/,"&"));
+		</SCRIPT>
+	</BODY>
+</HTML>
diff --git a/dijit/tests/form/robot/DateTextBox.html b/dijit/tests/form/robot/DateTextBox.html
new file mode 100644
index 0000000..1bc5ccd
--- /dev/null
+++ b/dijit/tests/form/robot/DateTextBox.html
@@ -0,0 +1,446 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>doh.robot DateTextBox Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+			dojo.require("dojo.date");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_DateTextBox.html');
+
+				// refs to DateTextBox widgets
+				var american, german;
+
+				// log of calls to onChange handler
+				var changes = [];
+
+				doh.register("setup",
+					function setUp(){
+						// refs to DateTextBox widgets
+				    	american = dijit.byId('american');
+				    	german = dijit.byId('german');
+
+				    	// setup onChange handler to monitor onChange calls on american textbox
+						dojo.connect(american, 'onChange', function(val){
+							console.log('onchange w/value: ', val);
+							changes.push(val);
+						});
+				    }
+				);
+
+				doh.register("API", [
+					function initial(){
+						// initial conditions
+						doh.is(0, dojo.date.compare(new Date(2005,11,30), american.get('value')), 'wire value of american: ' + american.get('value'));
+						doh.is('12/30/2005', american.get('displayedValue'), 'displayed value of american');
+					},
+
+					function setValue(){
+						american.set('value', new Date(2004,9,20));
+						doh.is(0, dojo.date.compare(new Date(2004,9,20), american.get('value')),
+								'wire value of american is: ' + american.get('value') +
+								' but should be: ' + new Date(2004,9,20));
+						doh.is('10/20/2004', american.get('displayedValue'), 'displayed value of american');
+						doh.t(american.isValid(), 'marked as valid');
+					},
+
+					function setDisplayedValue(){
+						american.set('displayedValue', '11/12/2006');
+						doh.is(0, dojo.date.compare(new Date(2006, 10, 12), american.get('value')), 'wire value of american');
+						doh.is('11/12/2006', american.get('displayedValue'), 'displayed value of american');
+						doh.t(american.isValid(), 'marked as valid');
+					},
+
+					function setInvalidDisplayedValue(){
+						american.set('displayedValue', 'foo');
+						doh.t(american.get('value') === undefined, 'value is undefined if displayedValue is garbage');
+						doh.f(american.isValid(), 'marked as invalid');
+
+						// setting the value to get('value') should never change anything, so
+						// therefore setting the value to undefined shouldn't affect the displayed value
+						american.set('value', undefined);
+						doh.is(american.get('displayedValue'), 'foo');
+					},
+
+					function setOutOfRange(){
+						// This widget is set to be valid between 2004 and 2006 only
+						american.set('displayedValue', '12/1/2008');
+						doh.f(american.isValid(), 'marked as invalid since out of range');
+						doh.is('12/1/2008', american.get('displayedValue'), 'displayed value of american');
+					}
+				]);
+
+				doh.register("direct input", {
+					name: "direct input",
+					timeout: 60000,
+					setUp: function(){
+						// clear the field
+						american.set('value', null);
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						doh.robot.sequence(function(){
+							// monitor onchange events
+							changes = [];
+							american.focus();
+						}, 500);
+						doh.robot.typeKeys('1/3/2005', 500, 1600);
+						doh.robot.keyPress(dojo.keys.TAB, 500, {});
+						doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+							var value = american.get('value');
+							doh.is(0, dojo.date.compare(new Date(2005, 0, 3), value), 'actual value is ' + value);
+							doh.is(1, changes.length, 'one onchange event');	// #9018
+							doh.is(0, dojo.date.compare(new Date(2005, 0, 3), changes[0]),
+									'value reported by onchange: ' + changes[0] +
+									', should be ' + new Date(2005, 0, 3));
+						})), 1000);
+						return d;
+					}
+				});
+
+				doh.register("drop down", [
+					function setUp(){
+						// clear the field
+						american.set('value', new Date(2005, 4, 10));
+					},
+
+					{
+						name: "initial popup display",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							doh.robot.sequence(function(){
+								changes = [];
+								american.focus();
+							}, 500);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								var calendar = dojo.byId("american_popup");
+
+								// Calendar exists and is shown
+								doh.t(calendar, "calendar popup exists");
+								doh.t(isVisible(calendar), "calendar is visible");
+
+								// Calendar is on the right month
+								doh.is("May", innerText(dijit.byNode(calendar).monthLabelNode), "calendar starts on month selected in input box");
+
+								// And the right year
+								var selectedYearButtons = dojo.query(".dijitCalendarSelectedYear", calendar.domNode);
+								doh.is(1, selectedYearButtons.length, "current year is shown");
+								doh.is("2005", innerText(selectedYearButtons[0]), "current year is 2005");
+
+								// And the currently selected date is right too
+								var selectedDays = dojo.query(".dijitCalendarSelectedDate", calendar.domNode);
+								doh.is(1, selectedDays.length, "one day selected");
+								doh.is("10", innerText(selectedDays[0]), "correct day is selected");
+							})), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "advance a month",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var calendar = dojo.byId("american_popup"),
+								nextMonthButtons = dojo.query(".dijitCalendarIncrease", calendar.domNode);
+
+							doh.is(1, nextMonthButtons.length, "found next month button");
+
+							doh.robot.mouseMoveAt(nextMonthButtons[0], 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								// Calendar still exists and is shown
+								doh.t(calendar, "calendar popup exists");
+								doh.t(isVisible(calendar), "calendar is visible");
+
+								// Calendar moved to the next month
+								doh.is("June", innerText(dijit.byNode(calendar).monthLabelNode), "moved from may to june");
+							})), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "advance a month with the menu dropdown",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var calendar = dojo.byId("american_popup"),
+								calendarWidget = dijit.byNode(calendar);
+
+							doh.t("monthLabelNode" in calendarWidget, "found month label");
+							doh.t(calendarWidget.monthDropDown, "month dropdown exists");
+							doh.f(isVisible(calendarWidget.monthDropDown), "month dropdown is not visible");
+
+							doh.robot.mouseMoveAt(calendarWidget.monthLabelNode, 500);
+							doh.robot.mousePress({left:true}, 500);
+							var july = dojo.query("[month=6]", calendarWidget.monthDropDown)[0];
+							doh.robot.mouseMoveAt(july, 500);
+							doh.robot.mouseRelease({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								// Calendar still exists and is shown
+								doh.t(calendar, "calendar popup exists");
+								doh.t(isVisible(calendar), "calendar is visible");
+
+								// Calendar moved to the next month
+								doh.is("July", innerText(calendarWidget.monthLabelNode), "moved from june to july");
+								var rows = dojo.query("TR.dijitCalendarWeekTemplate", calendar.domNode),
+									firstRowDays = dojo.query("TD", rows[0]);
+								doh.is(7, firstRowDays.length, "7 days in first row");
+								doh.t(dojo.hasClass(firstRowDays[0], "dijitCalendarPreviousMonth"), "previous month class applied");
+								doh.is("26", innerText(firstRowDays[0]), "first day is june 26");
+								doh.is("1", innerText(firstRowDays[5]), "sixth day is june 1");
+
+								calendarWidget._adjustDisplay("month", -1);
+							})), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "advance a year",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var calendar = dojo.byId("american_popup"),
+								nextYearButtons = dojo.query(".dijitCalendarNextYear", calendar.domNode);
+
+							doh.is(1, nextYearButtons.length, "found next year button");
+
+							doh.robot.mouseMoveAt(nextYearButtons[0], 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								// Calendar still exists and is shown
+								doh.t(calendar, "calendar popup exists");
+								doh.t(isVisible(calendar), "calendar is visible");
+
+								// Calendar moved to the next year
+								var yearNodes = dojo.query(".dijitCalendarSelectedYear", calendar.domNode);
+								doh.is(1, yearNodes.length, "found year node");
+								doh.is("2006", innerText(yearNodes[0]), "moved from 2005 to 2006");
+							})), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "check disabled dates",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Move forward another year, to see disabled days (this date text box is valid only to 2006)
+							var calendar = dojo.byId("american_popup"),
+								nextYearButtons = dojo.query(".dijitCalendarNextYear", calendar.domNode);
+
+							doh.is(1, nextYearButtons.length, "found next year button");
+
+							doh.robot.mouseMoveAt(nextYearButtons[0], 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								dojo.query(".dijitCalendarDateTemplate", calendar.domNode).forEach(function(node){
+									doh.t(dojo.hasClass(node, 'dijitCalendarDisabledDate'), 'every day in 2007 is disabled');
+								});
+							})), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "check enabled dates",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Move back another year, dates should be enabled again
+							var calendar = dojo.byId("american_popup"),
+								previousYearButtons = dojo.query(".dijitCalendarPreviousYear", calendar.domNode);
+
+							doh.is(1, previousYearButtons.length, "found previous year button");
+
+							doh.robot.mouseMoveAt(previousYearButtons[0], 500);
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								dojo.query(".dijitCalendarDateTemplate", calendar.domNode).forEach(function(node){
+									doh.f(dojo.hasClass(node, 'dijitCalendarDisabledDate'), "every day in 2006 is enabled");
+								});
+							})), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "check calendar display",
+						timeout: 60000,
+						runTest: function(){
+							var calendar = dojo.byId("american_popup"),
+								rows = dojo.query("TR.dijitCalendarWeekTemplate", calendar.domNode);
+
+							doh.is(6, rows.length, "six weeks shown");
+							var firstRowDays = dojo.query("TD", rows[0]);
+							doh.is(7, firstRowDays.length, "7 days in first row");
+							doh.t(dojo.hasClass(firstRowDays[0], "dijitCalendarPreviousMonth"), "previous month class applied");
+							doh.is("28", innerText(firstRowDays[0]), "first day is may 28");
+							doh.is("1", innerText(firstRowDays[4]), "fifth day is june 1");
+
+							dojo.query("TD", rows[5]).forEach(function(node){
+								doh.t(dojo.hasClass(node, 'dijitCalendarNextMonth'), "last row is for next month");
+							});
+						}
+					},
+
+					{
+						name: "hover a date",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var calendar = dojo.byId("american_popup"),
+								rows = dojo.query("TR.dijitCalendarWeekTemplate", calendar.domNode),
+								thirdRowDays = dojo.query("TD", rows[2]),
+								day = thirdRowDays[4];
+
+							// Hover June 15
+							doh.is("15", innerText(day), "found june 15");
+							doh.robot.mouseMoveAt(day, 500);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.t(dojo.hasClass(day, 'dijitCalendarHoveredDate'), "hovered date has hover class");
+							})), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "select a date",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.is(0, changes.length, "no onchange events yet");
+
+							// Select June 15
+							doh.robot.mouseClick({left:true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('6/15/2006', american.get('displayedValue'), 'displayed value of american');
+
+								var expectedVal = new Date(2006, 5, 15);	// 6/15/2006
+								doh.is(0, dojo.date.compare(expectedVal, american.get('value')), 'wire value of american: ' + american.get('value'));
+
+								doh.is(1, changes.length, "onchange event fired");
+								doh.is(0, dojo.date.compare(expectedVal, changes[0]), 'onchange of american: ' + changes[0]);
+							})), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "tab away",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is(1, changes.length, "no new onchange events");	// #9018
+							})), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("localization", [
+					function initialGerman(){
+						doh.is(0, dojo.date.compare(new Date(2006,10,29), german.get('value')), 'wire value of german: ' + german.get('value'));
+						doh.is('29.11.2006', german.get('displayedValue'), 'displayed value of german');
+					},
+
+					function setValueGerman(){
+						german.set('value', new Date(2004,9,20));
+						doh.is(0, dojo.date.compare(new Date(2004,9,20), german.get('value')),
+								'wire value of german is: ' + german.get('value') +
+								' but should be: ' + new Date(2004,9,20));
+						doh.is('20.10.2004', german.get('displayedValue'), 'displayed value of german');
+						doh.t(german.isValid(), 'marked as valid');
+					},
+
+					function setDisplayedValueGerman(){
+						german.set('displayedValue', '12.11.2006');
+						doh.is(0, dojo.date.compare(new Date(2006, 10, 12), german.get('value')), 'wire value of german');
+						doh.is('12.11.2006', german.get('displayedValue'), 'displayed value of german');
+						doh.t(german.isValid(), 'marked as valid');
+					},
+
+					{
+						name: "calendar",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							doh.robot.sequence(function(){
+								german.set('value', new Date(2006, 9, 15));	// 10/15/2006
+								german.focus();
+							}, 500);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								var calendar = dojo.byId("german_popup");
+
+								// Calendar exists and is shown
+								doh.t(calendar, "calendar popup exists");
+								doh.t(isVisible(calendar), "calendar is visible");
+
+								// Month label
+								doh.is("Oktober", innerText(dijit.byNode(calendar).monthLabelNode));
+
+								// Day labels
+								var dayLabels = dojo.query(".dijitCalendarDayLabelTemplate", calendar.domNode);
+								doh.is(7, dayLabels.length, "7 day labels");
+								doh.is("M", innerText(dayLabels[0]), "day 0");
+								doh.is("D", innerText(dayLabels[1]), "day 1");
+								doh.is("M", innerText(dayLabels[2]), "day 2");
+								doh.is("D", innerText(dayLabels[3]), "day 3");
+								doh.is("F", innerText(dayLabels[4]), "day 4");
+								doh.is("S", innerText(dayLabels[5]), "day 5");
+								doh.is("S", innerText(dayLabels[6]), "day 6");
+							})), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/form/robot/FilteringSelect_a11y.html b/dijit/tests/form/robot/FilteringSelect_a11y.html
new file mode 100644
index 0000000..0c135ae
--- /dev/null
+++ b/dijit/tests/form/robot/FilteringSelect_a11y.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+	<HEAD>
+		<TITLE>FilteringSelect General/Keyboard Robot Test</TITLE>
+	</HEAD>
+	<BODY>
+		Loading FilteringSelect a11y robot test.
+		<SCRIPT>
+			window.location.replace("_autoComplete_a11y.html?testWidget=dijit.form.FilteringSelect"+window.location.search.replace(/^\?/,"&"));
+		</SCRIPT>
+	</BODY>
+</HTML>
diff --git a/dijit/tests/form/robot/FilteringSelect_mouse.html b/dijit/tests/form/robot/FilteringSelect_mouse.html
new file mode 100644
index 0000000..725b817
--- /dev/null
+++ b/dijit/tests/form/robot/FilteringSelect_mouse.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+	<HEAD>
+		<TITLE>FilteringSelect Mouse Robot Test</TITLE>
+	</HEAD>
+	<BODY>
+		Loading FilteringSelect mouse robot test.
+		<SCRIPT>
+			window.location.replace("_autoComplete_mouse.html?testWidget=dijit.form.FilteringSelect"+window.location.search.replace(/^\?/,"&"));
+		</SCRIPT>
+	</BODY>
+</HTML>
diff --git a/dijit/tests/form/robot/Form.html b/dijit/tests/form/robot/Form.html
new file mode 100644
index 0000000..1186e65
--- /dev/null
+++ b/dijit/tests/form/robot/Form.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Button Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../FormInvalid.html');
+
+				doh.register("dijit.form.Form", [
+					{
+						name: "initial",
+						timeout: 15000,
+						runTest: function(){
+							// Submit button is initially disabled
+							doh.t(dijit.byId("submitBtn").get("disabled"));
+						}
+					},
+					{
+						name: "filling in first field doesn't change disabled state",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.sequence(function(){
+								dijit.byId("field1").focus();
+							});
+							doh.robot.typeKeys("hello", 500, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(dijit.byId("submitBtn").get("disabled"));
+							}), 500);
+							return d;
+						}
+					},
+					{
+						name: "filling in second field enables form",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.sequence(function(){
+								dijit.byId("field2").focus();
+							}, 500);
+							doh.robot.typeKeys("world", 500, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(dijit.byId("submitBtn").get("disabled"));
+							}), 500);
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/form/robot/Select.html b/dijit/tests/form/robot/Select.html
new file mode 100644
index 0000000..0fd6bdb
--- /dev/null
+++ b/dijit/tests/form/robot/Select.html
@@ -0,0 +1,410 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>doh.robot Select Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+			dojo.require("dojo.date");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Select.html');
+
+				// refs to parts of s1 Select
+				var s1, s1menu, Tenessee, Virginia, Washington,	// s1 select
+					s8a, s8a_menu, s8b, s8b_menu;				// long list selects
+
+				// log of calls to onChange handler
+				var changes = [];
+
+				doh.register("setup",
+					function setUp(){
+				    	s1 = dijit.byId('s1');
+						s1_menu = dijit.byId('s1_menu');
+						doh.t(s1, "s1 select exists");
+						doh.t(s1_menu, "s1 menu exists");
+						
+						s8a = dijit.byId('s8a');
+						s8a_menu = dijit.byId('s8a_menu');
+						s8b = dijit.byId('s8b');
+						s8b_menu = dijit.byId('s8b_menu');
+				    }
+				);
+
+				doh.register("mouse", [
+					{
+						name: "two clicks to select",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// click to open drop down
+							doh.robot.mouseMoveAt(s1.domNode, 500);
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible(s1_menu), "drop down menu displayed after click");
+								doh.is(5, dojo.query("tr", s1_menu.domNode).length, "5 options in menu")
+								
+								var selectedOptions = dojo.query(".dijitSelectSelectedOption .dijitMenuItemLabel", s1_menu.domNode);
+								doh.is(1, selectedOptions.length, "one selected option");
+								doh.is("Virginia", innerText(selectedOptions[0]), "Virginia highlighted");
+
+								Washington = dojo.query("tr", s1_menu.domNode)[2];
+								doh.t(Washington, "Washington is another menu choice");
+							}), 500);
+
+							// select an option in the drop down
+							doh.robot.mouseMoveAt(function(){
+								// function wrapper because Washington isn't defined until about sequence() runs
+								return Washington;
+							}, 500);
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden(s1_menu), "clicking choice hides menu");
+								
+								doh.is("Washington", innerText(s1.containerNode), "select shows selected option");
+								doh.is("WA", s1.get("value"), "get(value) after selecting Washington");
+							}), 500);
+
+							// click to open drop down again
+							doh.robot.mouseMoveAt(s1.domNode, 500);
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible(s1_menu), "drop down menu displayed after third click");
+								
+								var selectedOptions = dojo.query(".dijitSelectSelectedOption .dijitMenuItemLabel", s1_menu.domNode);
+								doh.is(1, selectedOptions.length, "one selected option");
+								doh.is("Washington", innerText(selectedOptions[0]), "Washington highlighted");
+							}), 500);
+
+							// clicking away should close the drop down
+							doh.robot.mouseMove(10, 10, 500)
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden(s1_menu), "clicking away hides menu");
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "mouse down, slide, mouse up",
+						timeout: 60000,
+						setUp: function(){
+							s1.set("value", "VA");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// mouse-down to open drop down
+							doh.robot.mouseMoveAt(s1.domNode, 500);
+							doh.robot.mousePress({left:true}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible(s1_menu), "drop down menu displayed after mouse down");
+								doh.is(5, dojo.query("tr", s1_menu.domNode).length, "5 options in menu")
+								
+								var selectedOptions = dojo.query(".dijitSelectSelectedOption .dijitMenuItemLabel", s1_menu.domNode);
+								doh.is(1, selectedOptions.length, "one selected option");
+								doh.is("Virginia", innerText(selectedOptions[0]), "Virginia highlighted");
+
+								Washington = dojo.query("tr", s1_menu.domNode)[2];
+								doh.t(Washington, "Washington is another menu choice");
+							}), 500);
+
+							// select an option in the drop down
+							doh.robot.mouseMoveAt(function(){
+								// function wrapper because Washington isn't defined until about sequence() runs
+								return Washington;
+							}, 500);
+							doh.robot.mouseRelease({left:true}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden(s1_menu), "clicking choice hides menu");
+								
+								doh.is("Washington", innerText(s1.containerNode), "select shows selected option");
+								doh.is("WA", s1.get("value"), "get(value) after selecting Washington");
+							}), 500);
+
+							// mouse down to open drop down again
+							doh.robot.mouseMoveAt(s1.domNode, 500);
+							doh.robot.mousePress({left:true}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible(s1_menu), "drop down menu displayed after second mouse down");
+								
+								var selectedOptions = dojo.query(".dijitSelectSelectedOption .dijitMenuItemLabel", s1_menu.domNode);
+								doh.is(1, selectedOptions.length, "one selected option");
+								doh.is("Washington", innerText(selectedOptions[0]), "Washington highlighted");
+							}), 500);
+
+							// mouse up away from node should leave drop down open
+							doh.robot.mouseMove(10, 10, 500)
+							doh.robot.mouseRelease({left:true}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible(s1_menu), "mouse up away from menu leaves menu open");
+							}), 500);
+
+							// then another mouse click should close it
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden(s1_menu), "clicking on blank screen hides menu");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "maxHeight",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// open drop down
+							doh.robot.mouseMoveAt(s8a.domNode, 500);
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible(s8a_menu.domNode), "drop down menu displayed after mouse down");
+								
+								var pos = dojo.position(s8a_menu.domNode);
+								doh.t(pos.h >= 200, "height at least 200: " + pos.h);
+								doh.t(pos.h < 220, "height including borders not much more than 200: " + pos.h);
+							}), 500);
+
+							// close drop down
+							doh.robot.mouseMove(10, 10, 500)
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden(s8a_menu), "clicking on blank screen hides menu");
+							}), 500);
+
+							return d;
+						}
+					},
+
+					// Not sure if this is good or not, but sometimes menu can overlap
+					// the select itself.  In this case, mouse up should leave the menu open						
+					{
+						name: "menu overlaps select",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// open drop down
+							doh.robot.mouseMoveAt(s8b.domNode, 500);
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible(s8b_menu.domNode), "drop down menu displayed after mouse click");
+
+								var select = dojo.position(s8b.domNode),
+									menu = dojo.position(s8b_menu.domNode);
+								doh.t(menu.h >= 220, "menu has big height: " + menu.h);
+								doh.t(menu.y < select.y && menu.y+menu.h > select.y+select.h,
+									"menu overlaps select, select = " + dojo.toJson(select) + ", menu = " + dojo.toJson(menu));
+							}), 500);
+
+							// clicking again should select the option from the menu
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden(s8b_menu), "clicking again selects something from menu");
+							}), 500);
+
+							return d;
+						}
+					}
+
+				]);
+
+				doh.register("keyboard", [
+					{
+						name: "tabIndex",
+						timeout: 60000,
+						setUp: function(){
+							dojo.byId("htmlSelect2").focus();
+							dijit.byId("s2").set("disabled", true);
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// tab to s1
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("s1", dojo.global.dijit._curFocus.id)
+							}), 500);
+
+							// tab to button after s1
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("s1button", dojo.global.dijit._curFocus.id)
+							}), 500);
+
+							// tab again should skip disabled s2, and go to s3
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("s3", dojo.global.dijit._curFocus.id)
+							}), 500);
+
+							return d;
+						},
+						tearDown: function(){
+							dijit.byId("s2").set("disabled", false);
+						}
+					},
+					{
+						name: "selecting",
+						timeout: 60000,
+						setUp: function(){
+							dojo.byId("htmlSelect2").focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// tab to s1
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("s1", dojo.global.dijit._curFocus.id)
+							}), 500);
+
+							// down arrow to open drop down and focus first item
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible(s1_menu), "drop down menu displayed after down arrow");
+								Tenessee = dojo.query("tr", s1_menu.domNode)[0];
+								doh.is(Tenessee, dojo.global.dijit._curFocus, "focused on first menu item")
+							}), 500);
+
+							// down arrow to next menu choice
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible(s1_menu), "drop down menu still displayed");
+								Virginia = dojo.query("tr", s1_menu.domNode)[1];
+								doh.is(Virginia, dojo.global.dijit._curFocus, "focused on second menu item")
+							}), 500);
+
+							// ENTER to select option
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden(s1_menu), "drop down menu closes after ENTER key");
+								doh.is("VA", s1.get("value"));
+							}), 500);
+
+							return d;
+						},
+						tearDown: function(){
+							dijit.byId("s1").set("value", "VA");
+						}
+					},
+					{
+						name: "ESC to close menu",
+						timeout: 60000,
+						setUp: function(){
+							dojo.byId("htmlSelect2").focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// tab to s1
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("s1", dojo.global.dijit._curFocus.id)
+							}), 500);
+
+							// down arrow to open drop down and focus first item
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible(s1_menu), "drop down menu displayed after down arrow");
+								Tenessee = dojo.query("tr", s1_menu.domNode)[0];
+								doh.is(Tenessee, dojo.global.dijit._curFocus, "focused on first menu item")
+							}), 500);
+
+							// ESC to close menu
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden(s1_menu), "drop down menu closes after ENTER key");
+								doh.is("VA", s1.get("value"), "value hasn't changed");
+							}), 500);
+
+							return d;
+						},
+						tearDown: function(){
+							dijit.byId("s1").set("value", "VA");
+						}
+					}
+				]);
+
+				doh.register("display", [
+					{
+						name: "empty drop down",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Open widget w/no choices
+							var s6 = dijit.byId("s6");
+							doh.robot.mouseMoveAt(s6.domNode, 500);
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								var menu = dijit.byId("s6_menu"),
+									trs = dojo.query("tr", menu.domNode);
+								doh.is(1, trs.length, "one entry in menu");
+								doh.is("", innerText(dojo.query(".dijitMenuItemLabel", trs[0])), "blank");
+							}), 500);
+
+							return d;
+						}
+					},
+
+					// Currently (for better or worse) the select's width changes based on which option
+					// is selected.   Make sure that the drop down is wide enough to show all entries,
+					// even when a narrow entry is selected.
+					{
+						name: "width",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var s5 = dijit.byId("s5"),
+								s5_menu = dijit.byId("s5_menu"),
+								menuSize;
+
+							// originally s5 is narrow
+							var s5origSize = dojo.position(s5.domNode);
+
+							// Open drop down menu and make sure it's wider than the select
+							// (to display "no move" and "no copy" choices)
+							doh.robot.mouseMoveAt(s5.domNode, 500);
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								menuSize = dojo.position(s5_menu.domNode);
+								doh.t(menuSize.w > s5origSize.w, "menu (" + menuSize.w + ") wider than select (" + s5origSize.w + ")");
+							}), 500);
+
+							// Select last entry in the drop down.   Should make the select wider.
+							doh.robot.mouseMoveAt(function(){
+								return dojo.query("tr", s5_menu.domNode)[4];
+							}, 500);
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								var s5newSize = dojo.position(s5.domNode);
+								doh.t(s5newSize.w > s5origSize.w, "select changed width from " + s5origSize.w + " to " + s5newSize.w);
+							}), 500);
+				
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/form/robot/Slider_a11y.html b/dijit/tests/form/robot/Slider_a11y.html
new file mode 100644
index 0000000..5b447d9
--- /dev/null
+++ b/dijit/tests/form/robot/Slider_a11y.html
@@ -0,0 +1,344 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>doh.robot Slider Test</title>
+
+	<style>
+		@import "../../../../util/doh/robot/robot.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");
+
+		// These are the sliders with arrow buttons
+		// (not sure why that's important for an a11y test???)
+		var arrowSliders = ['slider1','slider2','programaticSlider'];
+		var arrowSliderInit_min = [0.2,10,1200];		// One value above the minimum value
+		var arrowSliderInit_max = [99.8,90,2800];		// One value below the maximum value
+
+		// These are all the sliders
+		var accessibleSliders = ['slider1','slider2','slider3','programaticSlider'];
+		var accessibleSliderInit_min = [0.2,10,2,1200];
+		var accessibleSliderInit_max = [99.8,90,2,2800];
+		var sliderIds = ["slider1", "slider2", "slider3", "sliderH2", "programaticSlider"];
+		var sliderNames = ["horizontal1","vertical1","horizontal2","horizontalH2","programaticSlider"];
+		onChange = {slider1: 'slider1input', slider2: 'slider2input', programaticSlider: 'sliderProgInput'};
+
+		var a11yBoundaryTest = function(slider, initValue, finalValue){
+			// summary:
+			//		Sets slider to initValue, which should be either one below the
+			//		max, or one above the min.
+			//
+			//		Use the arrow key once to get to the final value, and
+			//		then use the arrow key again (value shouldn't change second time)
+
+			var d = new doh.Deferred();
+			var key = initValue < finalValue ? dojo.keys.RIGHT_ARROW : dojo.keys.LEFT_ARROW;
+
+			// Set slider to initial value, one value away from the min or max
+			slider.set('value', initValue, false);
+
+			// Focus the slider
+			slider.focus();
+
+			// First key press moves to either min or max
+			doh.robot.keyPress(key, 500);
+			doh.robot.sequence(d.getTestErrback(function(){
+				doh.is(finalValue, new Number(slider.get('value')).toFixed(1),
+						"value after first " + (key == dojo.keys.RIGHT_ARROW ? "right arrow" : "left arrow"));
+				if(onChange[slider.id]){
+					doh.is(finalValue,parseFloat(dojo.byId(onChange[slider.id]).value),
+						"onchange after first " + (key == dojo.keys.RIGHT_ARROW ? "right arrow" : "left arrow"));
+				}
+
+				// Second key press should have no effect, but confirm it
+				doh.robot.keyPress(key, 500);
+				doh.robot.sequence(d.getTestCallback(function(){
+					doh.is(finalValue, new Number(slider.get('value')).toFixed(1),
+						"value after second " + (key == dojo.keys.RIGHT_ARROW ? "right arrow" : "left arrow"));
+					if(onChange[slider.id]){
+						doh.is(finalValue, parseFloat(dojo.byId(onChange[slider.id]).value),
+						"onchange after second " + (key == dojo.keys.RIGHT_ARROW ? "right arrow" : "left arrow"));
+					}
+				}), 500);
+			}), 500);
+			return d;
+		};
+
+		// machinery for testing keyboard manipulation of sliders
+		var eaVals = [];	// array holding expected values and actual values after arrow etc. keypresses
+		var strokeIndex = 0;
+		var noteChanges;
+
+		var keyStrokeSetup = function(inSliderId){
+			// summary:
+			//		Populates eaVals[] with expected slider values after each keystroke (in this test),
+			//		and sets up listener to record actual value into same eaVals[] array.
+
+			var slider = dijit.byId(inSliderId);
+			eaVals = populateExpected(slider);
+			strokeIndex = 0;
+			noteChanges = dojo.global.dojo.connect(slider, "onChange", function(){
+				eaVals[strokeIndex++].actual = slider.get('value');
+			});
+		}
+
+		var populateExpected = function(/*Slider Widget*/inSlider){
+			// summary:
+			//		Returns array of expected slider values after each keystroke (in this test)
+
+			var initVal = inSlider.get('value');
+			var eVals = [];
+
+			// The values expected by pressing HOME, right arrow five times,
+			// PgUp twice, PgDn, up arrow twice, down arrow once,
+			// left arrow once, and END.
+			inSlider.set('value', inSlider.minimum, false);
+			eVals.push({stroke: "HOME", expected: inSlider.get('value')});
+			for(var i = 0; i < 5; i++){
+				inSlider._bumpValue(1, false);
+				eVals.push({stroke: "RIGHT", expected: inSlider.get('value')});
+			}
+			for(i = 0; i < 2; i++){
+				inSlider._bumpValue(inSlider.pageIncrement, false);
+				eVals.push({stroke: "PgUp", expected: inSlider.get('value')});
+			}
+			inSlider._bumpValue(-inSlider.pageIncrement, false);
+			eVals.push({stroke: "PgDn", expected: inSlider.get('value')});
+			for(i = 0; i < 2; i++){
+				inSlider._bumpValue(1, false);
+				eVals.push({stroke: "UP", expected: inSlider.get('value')});
+			}
+			inSlider._bumpValue(-1, false);
+			eVals.push({stroke: "DOWN", expected: inSlider.get('value')});
+			inSlider._bumpValue(-1, false);
+			eVals.push({stroke: "LEFT", expected: inSlider.get('value')});
+			inSlider.set('value', inSlider.maximum, false)
+			eVals.push({stroke: "END", expected: inSlider.get('value')});
+
+			// reset <inSlider> back to its initial value, and return
+			inSlider.set('value', initVal, false);
+			return eVals;
+		}
+
+		var a11yTabFocusTest = function(inSliderId){
+			var d = new doh.Deferred();
+			var slider = dijit.byId(inSliderId);
+			var focusCount = 0;
+			var blurCount = 0;
+			var gotFocus = function(){
+				focusCount++;
+			}
+			var lostFocus = function(){
+				blurCount++;
+			}
+			var focusFunc = dojo.global.dojo.connect(slider.focusNode, "onfocus", gotFocus);
+			var blurFunc = dojo.global.dojo.connect(slider.focusNode, "onblur", lostFocus);
+
+			// insure a known focus starting point -- the slider to test.
+			slider.focus();
+
+			// Shift-tab away, tab to, tab away, shift-tab back.
+			doh.robot.keyPress(dojo.keys.TAB, 1000, {
+				shift: true
+			});
+			doh.robot.keyPress(dojo.keys.TAB, 500);
+			doh.robot.keyPress(dojo.keys.TAB, 500);
+			doh.robot.keyPress(dojo.keys.TAB, 500, {
+				shift: true
+			});
+			var checkGotFocus = function(){
+				doh.assertEqual(3, focusCount, slider.id + ": # of times focussed");
+				doh.assertEqual(2, blurCount, slider.id + ": # of times lost focus");
+				dojo.disconnect(focusFunc);
+				dojo.disconnect(blurFunc);
+			};
+			doh.robot.sequence(d.getTestCallback(checkGotFocus), 1000, 500);
+			return d;
+		}
+
+		var a11yKeystrokeTest = function(inSliderId){
+			var d = new doh.Deferred();
+			var slider = dijit.byId(inSliderId);
+			var initVal = slider.get('value');
+			// get focus on slider thumb before pressing keys.
+			slider.focus();
+			doh.robot.sequence(function(){ strokeIndex = 0; }, 1000); // insure onChange events have stopped
+			doh.robot.keyPress(dojo.keys.HOME, 200);
+			doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 1000);
+			doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 200);
+			doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 200);
+			doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 200);
+			doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 200);
+			doh.robot.keyPress(dojo.keys.PAGE_UP, 200);
+			doh.robot.keyPress(dojo.keys.PAGE_UP, 500);
+			doh.robot.keyPress(dojo.keys.PAGE_DOWN, 500);
+			doh.robot.keyPress(dojo.keys.UP_ARROW, 500);
+			doh.robot.keyPress(dojo.keys.UP_ARROW, 200);
+			doh.robot.keyPress(dojo.keys.DOWN_ARROW, 200);
+			doh.robot.keyPress(dojo.keys.LEFT_ARROW, 200);
+			doh.robot.keyPress(dojo.keys.END, 200);
+			var testPresses = function(){
+				dojo.disconnect(noteChanges);
+				slider.set('value', initVal, false);
+				for(var i = 0; i < eaVals.length; i++){
+					doh.assertEqual(eaVals[i].expected, eaVals[i].actual, eaVals[i].stroke + " (" + slider.id + ")");
+				}
+			};
+			doh.robot.sequence(d.getTestCallback(testPresses), 1000, 500);
+			return d;
+		}
+
+		dojo.addOnLoad(function(){
+			doh.robot.initRobot('../test_Slider.html');
+
+			// This tests that Slider is structured so that dojo.query can find the hidden input.
+			doh.register("dojo.query() by name",
+				function slider1(){
+					var slider = dijit.byId("slider1"),
+						queried = dojo.query("input[name=horizontal1]");
+					doh.is(1, queried.length, "Expected 1 slider with name horizontal1");
+					doh.is(slider.valueNode, queried[0], "Slider's valueNode did not match the one found by dojo.query.");
+				}
+			);
+
+			// This tests that pressing the arrow keys has no effect on a disabled slider
+			// TODO: this doesn't make sense, should just be testing that slider can't get
+			// focus.  (And if it doesn't have focus then testing keystrokes is meaningless)
+			doh.register("disabledTest",{
+				name: arrowSliders[0]+'_a11y_min',
+				slider: arrowSliders[0],
+				value: arrowSliderInit_min[0],
+				timeout: 30000,
+				runTest: function(){
+					this.slider = dijit.byId(this.slider);
+					this.slider.set('disabled', true);
+					return a11yBoundaryTest(this.slider, this.value, this.value);
+				}
+			});
+
+			// This tests to make sure that the error keys don't go beyond the min or max values
+			doh.register("a11yBoundaryTest - min", {
+				name: accessibleSliders[0]+'_a11y_min',
+				slider: accessibleSliders[0],
+				value: accessibleSliderInit_min[0],
+				timeout: 30000,
+				runTest: function(){
+					this.slider = dijit.byId(this.slider);
+					this.slider.set('disabled', false);
+					return a11yBoundaryTest(this.slider, this.value, this.slider.minimum);
+				}
+			});
+			doh.register("a11yBoundaryTest",{
+				name: accessibleSliders[0]+'_a11y_max',
+				slider: accessibleSliders[0],
+				value: accessibleSliderInit_max[0],
+				timeout: 30000,
+				runTest: function(){
+					this.slider = dijit.byId(this.slider);
+					return a11yBoundaryTest(this.slider, this.value, this.slider.maximum);
+				}
+			});
+
+			// aria role and properties tests.
+			doh.register("a11yAria",
+			[
+				function ariaRole(){
+					var slider = dijit.byId(sliderIds[0]);
+					doh.is(dijit.getWaiRole(slider.focusNode), "slider", "aria role (slider)");
+				},
+
+				// test aria valuemin, valuemax, valuenow.
+				function ariaValue(){
+					var slider = dijit.byId(sliderIds[0]);
+					doh.is(dijit.getWaiState(slider.focusNode, "valuemin"), slider.minimum, "aria-valuemin");
+					doh.is(dijit.getWaiState(slider.focusNode, "valuemax"), slider.maximum, "aria-valuemax");
+					doh.is(dijit.getWaiState(slider.focusNode, "valuenow"), slider.get('value'), "aria-valuenow");
+				}
+			]);
+
+			// keyboard a11y tests (robot) -- tab focus
+			doh.register("a11yTabFocus",
+			[
+				{
+					name: "slider2TabFocus",
+					timeout: 9000,
+					runTest: function(){
+						return a11yTabFocusTest("slider2");
+					}
+				},
+				{
+					name: "slider3TabFocus",
+					timeout: 9000,
+					runTest: function(){
+						return a11yTabFocusTest("slider3");
+					}
+				}
+			]);
+
+			// keyboard a11y tests (robot) -- manipulate slider via keystrokes
+			doh.register("a11yKeystrokes",
+			[
+				{
+					name: "slider1Keystrokes",
+					timeout: 9000,
+					setUp: function(){
+						keyStrokeSetup("slider1");
+					},
+					runTest: function(){
+						return a11yKeystrokeTest("slider1");
+					}
+				},
+				{
+					name: "slider2Keystrokes",
+					timeout: 9000,
+					setUp: function(){
+						keyStrokeSetup("slider2");
+					},
+					runTest: function(){
+						return a11yKeystrokeTest("slider2");
+					}
+				},
+				{
+					name: "programaticSliderKeystrokes",
+					timeout: 9000,
+					setUp: function(){
+						keyStrokeSetup("programaticSlider");
+					},
+					runTest: function(){
+						return a11yKeystrokeTest("programaticSlider");
+					}
+				},
+				{
+					name: "disabledTabStop",
+					timeout: 9000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						var slider = dijit.byId("programaticSlider");
+						var target = dijit.byId("slider3");
+						target.set('value', 1);
+						var initValue = target.get('value');
+						// get focus on slider thumb before pressing keys.
+						slider.focus();
+						// jump to slider3 (hopefully)
+						doh.robot.keyPress(dojo.keys.TAB, 1000, {
+							shift: true
+						});
+						doh.robot.keyPress(dojo.keys.END, 1000);
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.f(initValue == target.get('value'), "disabled tab stop should be skipped");
+						}), 500);
+						return d;
+					}
+				}
+			]);
+			doh.run();
+		});
+	</script>
+</head>
+</html>
diff --git a/dijit/tests/form/robot/Slider_mouse.html b/dijit/tests/form/robot/Slider_mouse.html
new file mode 100644
index 0000000..4f7e3fd
--- /dev/null
+++ b/dijit/tests/form/robot/Slider_mouse.html
@@ -0,0 +1,339 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>doh.robot Slider Test</title>
+
+	<style>
+		@import "../../../../util/doh/robot/robot.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojo.window");
+		dojo.require("dijit.robotx");
+
+		var arrowSliders = ['slider1','slider2','programaticSlider'];
+		var arrowSliderInit_min = [0.2,10,1200];
+		var arrowSliderInit_max = [99.8,90,2800];
+		var accessibleSliders = ['slider1','slider2','slider3','programaticSlider']
+		var accessibleSliderInit_min = [0.2,10,2,1200];
+		var accessibleSliderInit_max = [99.8,90,2,2800];
+		var sliderIds = ["slider1", "slider2", "slider3", "sliderH2", "programaticSlider"];
+
+		onChange = {slider1: 'slider1input', slider2: 'slider2input', programaticSlider: 'sliderProgInput'};
+
+		var boundaryTest = function(slider, initValue, finalValue){
+			// summary:
+			//		Sets slider to initValue, which should be either one below the
+			//		max, or one above the min.
+			//
+			//		Click the arrow button once to get to the final value, and
+			//		then click the arrow button again (value shouldn't change second time)
+			var d = new doh.Deferred();
+			slider.set('value', initValue);
+			var button = slider._descending ?
+				(initValue<finalValue?slider.decrementButton: slider.incrementButton) :
+				(initValue<finalValue?slider.incrementButton: slider.decrementButton);
+			doh.robot.sequence(function(){
+				dojo.window.scrollIntoView(slider.domNode);
+			},500);
+			doh.robot.mouseMoveAt(button, 500);
+			doh.robot.mouseClick({left: true}, 500);
+			doh.robot.sequence(d.getTestErrback(function(){
+				doh.is(finalValue, new Number(slider.get('value')).toFixed(1));
+				if(onChange[slider.id]){
+					doh.is(finalValue, parseFloat(dojo.byId(onChange[slider.id]).value));
+				}
+				doh.robot.mouseMoveAt(button, 500);
+				doh.robot.mouseClick({left: true}, 500);
+				doh.robot.sequence(d.getTestCallback(function(){
+					doh.is(finalValue, new Number(slider.get('value')).toFixed(1));
+					if(onChange[slider.id]){
+						doh.is(finalValue, parseFloat(dojo.byId(onChange[slider.id]).value));
+					}
+				}), 500);
+			}), 500);
+			return d;
+		};
+
+		var buttonHeldTest = function(slider, initValue, finalValue){
+			var d = new doh.Deferred();
+			slider.set('value', initValue);
+			var button = slider._descending?(initValue<finalValue?slider.decrementButton: slider.incrementButton): (initValue<finalValue?slider.incrementButton: slider.decrementButton);
+			doh.robot.sequence(function(){
+				dojo.window.scrollIntoView(slider.domNode);
+			},500);
+			doh.robot.mouseMoveAt(button, 500);
+			doh.robot.mousePress({left: true}, 500);
+			doh.robot.mouseRelease({left: true}, 5000);
+			doh.robot.sequence(d.getTestCallback(function(){
+				doh.is(finalValue, new Number(slider.get('value')).toFixed(1));
+				if(onChange[slider.id]){
+					doh.is(finalValue, parseFloat(dojo.byId(onChange[slider.id]).value));
+				}
+			}), 500);
+			return d;
+		};
+
+		var mouseWheelTest = function(slider, initValue, finalValue){
+			if(slider.discreteValues != Infinity){
+				var d = new doh.Deferred();
+				slider.set('value', initValue);
+				var direction = (finalValue-initValue)/Math.abs(finalValue-initValue);
+				var delta = Math.ceil((slider.discreteValues-1)*Math.abs(doh.robot.mouseWheelSize)/doh.robot.mouseWheelSize);
+				doh.robot.sequence(function(){
+					dojo.window.scrollIntoView(slider.domNode);
+				},500);
+				doh.robot.mouseMoveAt(slider.focusNode, 500);
+				doh.robot.mouseClick({left: true}, 500);
+				doh.robot.mouseWheel(delta*direction, 500, Math.abs(delta)*200);
+				doh.robot.sequence(d.getTestCallback(function(){
+					doh.is(finalValue, new Number(slider.get('value')).toFixed(1));
+					if(onChange[slider.id]){
+						doh.is(finalValue, parseFloat(dojo.byId(onChange[slider.id]).value));
+					}
+				}), 500);
+				return d;
+			}
+		};
+
+		dojo.addOnLoad(function(){
+			doh.robot.initRobot('../test_Slider.html');
+
+			// Test initial values
+			doh.register("initial values", function initialValues(){
+				doh.is(10, dijit.byId("slider1").get("value"), "horizontal1");
+				doh.is(10, dijit.byId("slider2").get("value"), "vertical1");
+				doh.is(2, dijit.byId("slider3").get("value"), "horizontal2");
+				doh.is(10, dijit.byId("sliderH2").get("value"), "sliderH2");
+				doh.is(1400, dijit.byId("programaticSlider").get("value"), "programaticSlider");
+			});
+
+			doh.register("set('value', ...)", [
+				function valid(){
+					var slider = dijit.byId(arrowSliders[0]);
+					slider.set('value', 50);
+					var d = new doh.Deferred();
+					doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+						doh.is(50, parseFloat(dojo.byId(onChange[slider.id]).value));
+					})), 500);
+					return d;
+				},
+				function setToNull(){
+					// No idea why setting to null makes it go to 0 but apparently that's expected behavior
+					var slider = dijit.byId(arrowSliders[0]);
+					slider.set('value', null);
+					var d = new doh.Deferred();
+					doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+						doh.is(0, parseFloat(dojo.byId(onChange[slider.id]).value));
+					})), 500);
+					return d;
+				}
+			]);
+
+			// Test that disabled sliders don't respond to mouse clicks (or at least,
+			// the left/right arrow buttons don't)
+			doh.register("disabledTest", [
+				{
+					name: arrowSliders[0]+'_setUp',
+					slider: arrowSliders[0],
+					timeout: 30000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						doh.robot.mouseMoveAt('disableButton',500);
+						doh.robot.mouseClick({left: true}, 500);
+						if(dojo.isMac){
+							// Workaround mac/FF bug where first click doesn't register
+							doh.robot.mouseClick({
+								left: true
+							}, 500);
+						}
+						doh.robot.sequence(function(){ d.callback(true); },500);
+						return d;
+					}
+				},
+				{
+					name: arrowSliders[0]+'_min',
+					slider: arrowSliders[0],
+					value: arrowSliderInit_min[0],
+					timeout: 30000,
+					runTest: function(){
+						this.slider = dijit.byId(this.slider);
+						return boundaryTest(this.slider, this.value, this.value);
+					}
+				},
+				{
+					name: arrowSliders[0]+'_tearDown',
+					slider: arrowSliders[0],
+					timeout: 30000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						doh.robot.mouseMoveAt('enableButton',500);
+						doh.robot.mouseClick({left: true}, 500);
+						doh.robot.sequence(function(){ d.callback(true); },500);
+						return d;
+					}
+				}
+			]);
+
+			doh.register("buttonBoundaryTest", [
+				{
+					name: arrowSliders[0]+'_min',
+					slider: arrowSliders[0],
+					value: arrowSliderInit_min[0],
+					timeout: 30000,
+					runTest: function(){
+						this.slider = dijit.byId(this.slider);
+						return boundaryTest(this.slider, this.value, this.slider.minimum);
+					}
+				},
+				{
+					name: arrowSliders[0]+'_max',
+					slider: arrowSliders[0],
+					value: arrowSliderInit_max[0],
+					timeout: 30000,
+					runTest: function(){
+						this.slider = dijit.byId(this.slider);
+						return boundaryTest(this.slider, this.value, this.slider.maximum);
+					}
+				}
+			]);
+
+			doh.register("buttonHeldTest", [
+				{
+					name: arrowSliders[1]+'_minToMax',
+					slider: arrowSliders[1],
+					timeout: 30000,
+					runTest: function(){
+						this.slider = dijit.byId(this.slider);
+						return buttonHeldTest(this.slider, this.slider.minimum, this.slider.maximum);
+					}
+				},
+				{
+					name: arrowSliders[1]+'_maxToMin',
+					slider: arrowSliders[1],
+					timeout: 30000,
+					runTest: function(){
+						this.slider = dijit.byId(this.slider);
+						return buttonHeldTest(this.slider, this.slider.maximum, this.slider.minimum);
+					}
+				}
+			]);
+
+			doh.register("mouseWheelTest", [
+				{
+					name: accessibleSliders[1]+'_minToMax',
+					slider: accessibleSliders[1],
+					timeout: 30000,
+					runTest: function(){
+						this.slider = dijit.byId(this.slider);
+						return mouseWheelTest(this.slider, this.slider.minimum, this.slider.maximum);
+					}
+				},
+				{
+					name: accessibleSliders[1]+'_maxToMin',
+					slider: accessibleSliders[1],
+					timeout: 30000,
+					runTest: function(){
+						this.slider = dijit.byId(this.slider);
+						return mouseWheelTest(this.slider, this.slider.maximum, this.slider.minimum);
+					}
+				}
+			]);
+
+			doh.register("general tests", [
+				{
+					name: "slider1",
+					setUp: function(){
+						dijit.byId("slider1").set('value',10);
+					},
+					timeout: 4000, // this is the animated slider so there is a 500ms delay
+					runTest: function(){
+						var d = new doh.Deferred();
+						var slider = dijit.byId("slider1");
+						dojo.window.scrollIntoView(slider.domNode);
+						doh.robot.mouseMoveAt(slider.focusNode, 500);
+						doh.robot.mousePress({left: true}, 500);
+						// drag to 20% marker
+						doh.robot.mouseMoveAt(dojo.query("div[style*='20%']", dojo.byId('dijit_form_HorizontalRule_0'))[0], 500);
+						doh.robot.mouseRelease({left: true}, 500);
+						doh.robot.sequence(function(){
+							var value = slider.get('value');
+							if(value >= 19 && value <= 21){
+								d.callback(true);
+							}else{
+								d.errback("slider1 failed. Expected ~20, got " + value);
+							}
+						}, 1400);
+						return d;
+					},
+					tearDown: function(){
+						dijit.byId("slider1").set('value',20);
+					}
+				},
+
+				{
+					name: "slider2",
+					timeout: 3500,
+					setUp: function(){
+						dijit.byId("slider2").set('value',10);
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						var slider = dijit.byId("slider2");
+						dojo.window.scrollIntoView(slider.domNode);
+						doh.robot.mouseMoveAt(slider.focusNode, 500);
+						doh.robot.mousePress({left: true}, 500);
+						// drag to 20% marker (Slider is in descending order so it's 100-20=80%)
+						var marker = dojo.query("div[style*='80%']", dojo.byId('dijit_form_VerticalRule_1'))[0];
+						doh.robot.mouseMoveAt(marker, 500, 100, 0, 0);
+						doh.robot.mouseRelease({left: true}, 500);
+						doh.robot.sequence(function(){
+							var value = slider.get('value');
+							if(value == 20){
+								d.callback(true);
+							}else{
+								d.errback("slider2 failed. Expected 20, got "+value);
+							}
+						}, 900);
+						return d;
+					}
+				},
+
+				{
+					name: "slider3",
+					timeout: 3500,
+					setUp: function(){
+						dijit.byId("programaticSlider").set('value',1000);
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						var slider = dijit.byId("programaticSlider");
+						dojo.window.scrollIntoView(slider.domNode);
+						doh.robot.mouseMoveAt(slider.focusNode, 500);
+						doh.robot.mousePress({left: true}, 500);
+						// drag to the top
+						doh.robot.mouseMoveAt(dojo.query("div[style*='0%']", dojo.byId('dijit_form_VerticalRule_2'))[0], 500, 100, 0, 0);
+						doh.robot.mouseRelease({left: true}, 500);
+						doh.robot.sequence(function(){
+							var value = slider.get('value');
+							if(value == 3000){
+								d.callback(true);
+							}else{
+								d.errback("slider3 failed. Expected 3000, got "+value);
+							}
+						}, 900);
+						return d;
+					}
+				}
+			]);
+
+			doh.run();
+		});
+	</script>
+</head>
+</html>
diff --git a/dijit/tests/form/robot/Spinner_a11y.html b/dijit/tests/form/robot/Spinner_a11y.html
new file mode 100644
index 0000000..ed5fb1e
--- /dev/null
+++ b/dijit/tests/form/robot/Spinner_a11y.html
@@ -0,0 +1,682 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Spinner Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				var spin1;
+				var spin2;
+				var spin3;
+				var spinnerIds = ["integerspinner1", "integerspinner2", "integertextbox3", "realspinner1"];
+				doh.robot.initRobot('../test_Spinner.html');
+
+				// focus handlers for noticing tab/shift+tab navigation
+				var focusCountZ = 0;
+				var blurCountZ = 0;
+				var countFocus = function(){
+					focusCountZ++;
+				}
+				var countBlur = function(){
+					blurCountZ++;
+				}
+				var focusConnect;
+				var blurConnect;
+				var tabFocusSetup = function(inSpinnerId){
+					var spinner = dijit.byId(inSpinnerId);
+					dijit.byId('integerspinner1').focus();
+					focusCountZ = 0;
+					blurCountZ = 0;
+					focusConnect = spinner.connect(spinner.focusNode, "onfocus", countFocus);
+					blurConnect = spinner.connect(spinner.focusNode, "onblur", countBlur);
+				}
+
+				// Setup to test manipulation of spinner via keystrokes.
+				var results;	// array holding both expected value and actual value after each keypress
+				var strokeIndex = 0;
+				var noteConnect;
+				function keyStrokeSetup(inSpinnerId){
+					// summary:
+					//		Populates results[] with expected values after each keypress.
+					//		Also sets up listener to every keyboard event (arrow key etc) on a spinner and
+					//		records to record the actual spinner values into results[].
+					var spinner = dijit.byId(inSpinnerId);
+					results = populateExpected(spinner);
+					strokeIndex = 0;
+					noteConnect = spinner.connect(spinner.focusNode, "onkeypress", function(){
+						results[strokeIndex].actual = spinner.get('value');
+						strokeIndex++;
+					});
+				}
+
+				// Use spinner api to calculate values for a set of keystrokes.
+				// Returns array of expected values.
+				var populateExpected = function(/*Spinner Widget*/inSpinner){
+					var initVal = inSpinner.get('value');
+					var eVals = [];
+					var newVal;
+
+					// The values expected by pressing HOME, right arrow five times,
+					// PgUp twice, PgDn, up arrow twice, down arrow once,
+					// left arrow once, and END.
+					if(inSpinner.constraints.min){
+						inSpinner.set('value', inSpinner.constraints.min);
+					}
+					newVal = inSpinner.get('value');
+					eVals.push({stroke: "HOME", expected: newVal});
+					// UP 5 times
+					for(var i = 0; i < 5; i++){
+						newVal = inSpinner.adjust(newVal, inSpinner.smallDelta);
+						inSpinner.set('value', newVal);
+						newVal = inSpinner.get('value');
+						eVals.push({stroke: "UP", expected: newVal});
+					}
+					// PgUp twice
+					for(var i = 0; i < 2; i++){
+						newVal = inSpinner.adjust(newVal, inSpinner.largeDelta);
+						inSpinner.set('value', newVal);
+						newVal = inSpinner.get('value');
+						eVals.push({stroke: "PgUp", expected: newVal});
+					}
+					// PgDn once.
+					newVal = inSpinner.adjust(newVal, -inSpinner.largeDelta);
+					inSpinner.set('value', newVal);
+					newVal = inSpinner.get('value');
+					eVals.push({stroke: "PgDn", expected: newVal});
+					// DOWN
+					newVal = inSpinner.adjust(newVal, -inSpinner.smallDelta);
+					inSpinner.set('value', newVal);
+					newVal = inSpinner.get('value');
+					eVals.push({stroke: "DOWN", expected: newVal});
+					// END
+					if(inSpinner.constraints.max){
+						inSpinner.set('value', inSpinner.constraints.max);
+						newVal = inSpinner.get('value');
+					}else{
+						newVal = inSpinner.get('value');
+					}
+					eVals.push({stroke: "END", expected: newVal});
+
+					// reset <inSpinner> back to its initial value, and return
+					inSpinner.set('value', initVal);
+					return eVals;
+				}
+
+				// common robot TAB-focus test function.
+				var a11yTabFocus = function(inSpinnerId){
+					var d = new doh.Deferred();
+					var spinner = dijit.byId(inSpinnerId);
+					// insure a known focus starting point within document before key presses.
+					spinner.focus();
+					// Shift-tab away, tab to, tab away, shift-tab back.
+					doh.robot.keyPress(dojo.keys.TAB, 1000, {shift:true});
+					doh.robot.keyPress(dojo.keys.TAB, 1000);
+					doh.robot.keyPress(dojo.keys.TAB, 1000);
+					doh.robot.keyPress(dojo.keys.TAB, 1000, {shift:true});
+
+					// TODO: this doesn't seem thorough... after TAB or shift TAB
+					// should be checking that we ended up at the right place, i.e.
+					// make sure that we don't have extra tab stops within the Spinner itself.
+
+					var checkGotFocus = function(){
+						spinner.disconnect(focusConnect);
+						spinner.disconnect(blurConnect);
+						doh.assertEqual(3, focusCountZ, "# of times focused (" + spinner.id + ")");
+						doh.assertEqual(2, blurCountZ, "# of times lost focus (" + spinner.id + ")");
+					};
+					doh.robot.sequence(d.getTestCallback(checkGotFocus), 1000, 1000);
+					return d;
+				}
+
+				// common robot keystroke test function.
+				var a11yKeystrokeTest = function(inSpinnerId){
+					var d = new doh.Deferred();
+					var spinner = dijit.byId(inSpinnerId);
+					var initVal = spinner.get('value');
+
+					spinner.focus();
+
+					doh.robot.keyPress(dojo.keys.HOME, 1000);
+					doh.robot.keyPress(dojo.keys.UP_ARROW, 200);
+					doh.robot.keyPress(dojo.keys.UP_ARROW, 200);
+					doh.robot.keyPress(dojo.keys.UP_ARROW, 200);
+					doh.robot.keyPress(dojo.keys.UP_ARROW, 200);
+					doh.robot.keyPress(dojo.keys.UP_ARROW, 200);
+					doh.robot.keyPress(dojo.keys.PAGE_UP, 200);
+					doh.robot.keyPress(dojo.keys.PAGE_UP, 200);
+					doh.robot.keyPress(dojo.keys.PAGE_DOWN, 200);
+					doh.robot.keyPress(dojo.keys.DOWN_ARROW, 200);
+					doh.robot.keyPress(dojo.keys.END, 200);
+					var testPresses = function(){
+						spinner.disconnect(noteConnect);
+						spinner.set('value', initVal);
+						for(var i = 0; i < results.length; i++){
+							var aResult = results[i];
+							if(!(isNaN(aResult.expected) && isNaN(aResult.actual))) {
+								doh.is(aResult.expected, aResult.actual, aResult.stroke);
+							}
+						}
+					};
+					doh.robot.sequence(d.getTestCallback(testPresses), 1000, 1000);
+					return d;
+				}
+
+				doh.register("setUp",{
+					name: "setUp",
+					timeout: 15000,
+					setUp:function(){
+						spin1 = dijit.byId('integerspinner1');
+						spin2 = dijit.byId('integerspinner2');
+						spin3 = dijit.byId('realspinner1');
+						spin4 = dijit.byId('spinnerMinOnly');
+						safeClick = dojo.byId('form1');
+					},
+					runTest: function(){
+						// assert onChange not fired
+						doh.is("not fired yet!", dojo.byId('oc1').value);
+
+						// make sure initial values are what we expect
+						doh.is(1, spin1.smallDelta);
+						doh.is(900, spin1.get('value'), "integerspinner1");
+						doh.is(1000, spin2.get('value'), "integerspinner2");
+						doh.is(1.0, spin3.get('value'), "realspinner1");
+						doh.is(1.0, spin4.get('value'), "spinnerMinOnly");
+					}
+				});
+
+				doh.register("dojo.query() input by name",
+					dojo.map(spinnerIds, function(id){
+						return {
+							name: id,
+							spinner: id,
+							spinnerName: id,
+							runTest:function(){
+								this.spinner = dijit.byId(this.spinner);
+								var queried=dojo.query("input[name="+this.spinnerName+"]");
+								doh.is(1, queried.length,"Expected 1 spinner with name "+this.spinnerName+", found "+queried.length);
+								doh.is(this.spinner.valueNode, queried[0],"Spinner's valueNode did not match the one found by dojo.query.");
+							}
+						};
+					})
+				);
+
+				doh.register("a11y", [
+					{
+						name: "spinner2_typematic",
+						timeout: 15000,
+						setUp:function(){
+							spin2.set('value', 900);
+							spin2.focus();
+						},
+						runTest: function(){
+							// test typematic
+							var d=new doh.Deferred();
+							doh.robot.keyDown(dojo.keys.DOWN_ARROW, 1000);
+							doh.robot.keyUp(dojo.keys.DOWN_ARROW, 5000);
+							doh.robot.sequence(function(){
+								if(spin2.get('value')<=800){
+									d.callback(true);
+								}else{
+									d.errback(new Error('Error in typematic test. Expected <=800, got '+spin2.get('value')));
+								}
+							}, 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "spinner2_max",
+						timeout: 15000,
+						setUp:function(){
+							spin2.set('value', 1549);
+							spin2.focus();
+						},
+						runTest: function(){
+							// test max with arrow key
+							var d=new doh.Deferred();
+							// press once: should move up
+							doh.robot.keyPress(dojo.keys.UP_ARROW, 1000);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is(1550, spin2.get('value'));
+								doh.is("1550", spin2.focusNode.value);
+								doh.is(true, spin2.isValid());
+								// press again: shouldn't move
+								doh.robot.keyPress(dojo.keys.UP_ARROW, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is(1550, spin2.get('value'));
+									doh.is("1550", spin2.focusNode.value);
+									doh.is(true, spin2.isValid());
+								}), 500);
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "spinner2_min",
+						timeout: 15000,
+						setUp:function(){
+							spin2.set('value', 10);
+							spin2.focus();
+						},
+						runTest: function(){
+							// test min with arrow key
+							var d=new doh.Deferred();
+							// press once: should move up
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 1000);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is(9, spin2.get('value'));
+								doh.is("9", spin2.focusNode.value);
+								doh.is(true, spin2.isValid());
+								// press again: shouldn't move
+								doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is(9, spin2.get('value'));
+									doh.is("9", spin2.focusNode.value);
+									doh.is(true, spin2.isValid());
+								}), 500);
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "spinner2_invalid",
+						timeout: 15000,
+						setUp:function(){
+							spin2.focusNode.value="";
+							spin2.focus();
+						},
+						runTest: function(){
+							// assert invalid works
+							var d=new doh.Deferred();
+							doh.robot.typeKeys("0.5", 1000, 600);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(false, spin2.isValid());
+							}), 500);
+							return d;
+						}
+					}
+				]);
+
+				// Test ARIA role.  Since role attribute is set in template,
+				// checking one should be sufficient.
+				doh.register("a11yAriaRole",
+					function spinnerRole(){
+						var spinner = dijit.byId("integerspinner1");
+						doh.isNot(spinner, null, "can't find 'integerspinner1'");
+						doh.is(dijit.getWaiRole(spinner.focusNode), "spinbutton", spinner.id + ": aria role (spinbutton)");
+					}
+				);
+
+				// Check ARIA min/max values.
+				// - both min and max.
+				// - min, no max.
+				// - max, no min.
+				// - neither.
+				doh.register("a11yMinMaxValues",
+					[
+						function minAndMax(){
+							var spinner = dijit.byId("integerspinner2");
+							doh.isNot(spinner, null, "can't find 'integerspinner2'");
+							doh.is(dijit.getWaiState(spinner.focusNode, "valuemin"), spinner.constraints.min, spinner.id + ": aria-valuemin");
+							doh.is(dijit.getWaiState(spinner.focusNode, "valuemax"), spinner.constraints.max, spinner.id + ": aria-valuemax");
+						},
+						function minOnly(){
+							var spinner = dijit.byId("spinnerMinOnly");
+							doh.isNot(spinner, null, "can't find 'spinnerMinOnly'");
+							doh.is(dijit.getWaiState(spinner.focusNode, "valuemin"), spinner.constraints.min, spinner.id + ": aria-valuemin");
+							if(spinner.constraints.max){
+								doh.is(dijit.getWaiState(spinner.focusNode, "valuemax"), spinner.constraints.max, spinner.id + ": aria-valuemax");
+							} else {
+								doh.f(dijit.hasWaiState(spinner.focusNode, "valuemax"), spinner.id + ": aria-valuemax");
+							}
+						},
+						function maxOnly(){
+							var spinner = dijit.byId("integertextbox3");
+							doh.isNot(spinner, null, "can't find 'integertextbox3'");
+							doh.is(dijit.getWaiState(spinner.focusNode, "valuemax"), spinner.constraints.max, spinner.id + ": aria-valuemax");
+							if(spinner.constraints.min){
+								doh.is(dijit.getWaiState(spinner.focusNode, "valuemin"), spinner.constraints.min, spinner.id + ": aria-valuemin");
+							} else {
+								doh.f(dijit.hasWaiState(spinner.focusNode, "valuemin"), spinner.id + ": aria-valuemin");
+							}
+						},
+						function neitherMinNorMax(){
+							var spinner = dijit.byId("integertextbox3");
+							doh.isNot(spinner, null, "can't find 'integertextbox3'");
+							if(spinner.constraints.min){
+								doh.is(dijit.getWaiState(spinner.focusNode, "valuemin"), spinner.constraints.min, spinner.id + ": aria-valuemin");
+							} else {
+								doh.f(dijit.hasWaiState(spinner.focusNode, "valuemin"), spinner.id + ": aria-valuemin");
+							}
+							if(spinner.constraints.max){
+								doh.is(dijit.getWaiState(spinner.focusNode, "valuemax"), spinner.constraints.max, spinner.id + ": aria-valuemax");
+							} else {
+								doh.f(dijit.hasWaiState(spinner.focusNode, "valuemax"), spinner.id + ": aria-valuemax");
+							}
+						}
+					]
+				);
+
+				// Loop to test each spinner for aria-valuenow
+				// TODO:
+				//		Is testing one spinner sufficient?
+				//
+				// test aria valuemin, valuemax, valuenow.
+				doh.register("a11yValueNow",
+					dojo.map(spinnerIds, function(id){
+						return {
+							name: id+"_value",
+							spinnerId: id,
+							runTest:function(){
+								var spinner = dijit.byId(this.spinnerId);
+								spinner.set('value', 100);
+								var ariaVal = dijit.getWaiState(spinner.focusNode, "valuenow");
+								doh.is(100, ariaVal, spinner.id + ": aria-valuenow");
+							}
+						};
+					})
+				);
+
+
+					// test "null" aria-valuenow
+/* Remove null aria-valuenow test until #7866 is resolved
+					doh.register("a11yNullValuenow", {
+						name:spinnerIds[i]+"_nullValueNow",
+						spinnerId:spinnerIds[i],
+						runTest:function(){
+							var spinner = dijit.byId(this.spinnerId);
+							var initVal = spinner.get('value');
+							spinner.set('value', null);
+							var spinnerVal = spinner.get('value');
+							var nowVal = dijit.getWaiState(spinner.focusNode, "valuenow");
+							var invalid = dijit.getWaiState(spinner.focusNode, "invalid");
+							spinner.set('value', initVal);
+							doh.t(invalid, spinner.id + ": aria-invalid");
+							if(!(isNaN(spinnerVal) && isNaN(nowVal))){
+								doh.is(spinnerVal, nowVal, spinner.id + ": null aria-valuenow");
+							}
+						}
+					});
+*/
+
+				// a11y tab focus tests (robot)
+				doh.register("a11yTabFocus",
+				[
+					// don't test integerspinner1 since shift-tab from there goes to address bar and the robot doesn't like that at all
+					{
+						name:"integertextbox3TabFocus",
+						timeout:9000,
+						setUp:function(){
+							tabFocusSetup("integertextbox3");
+						},
+						runTest:function(){
+							return a11yTabFocus("integertextbox3");
+						}
+					},
+					{ // test integerspinner2 second since the previous test group already had it focused
+						name:"integerspinner2TabFocus",
+						timeout:9000,
+						setUp:function(){
+							tabFocusSetup("integerspinner2");
+						},
+						runTest:function(){
+							return a11yTabFocus("integerspinner2");
+						}
+					},
+					{
+						name:"realspinner1TabFocus",
+						timeout:9000,
+						setUp:function(){
+							tabFocusSetup("realspinner1");
+						},
+						runTest:function(){
+							return a11yTabFocus("realspinner1");
+						}
+					}
+				]);
+
+				// a11y keystroke tests
+				doh.register("a11yKeystrokes",
+				[
+					{
+						name:"integerspinner1Keystrokes",
+						timeout:9000,
+						setUp:function(){
+							keyStrokeSetup("integerspinner1");
+						},
+						runTest:function(){
+							return a11yKeystrokeTest("integerspinner1");
+						}
+					},
+					{
+						name:"integerspinner2Keystrokes",
+						timeout:9000,
+						setUp:function(){
+							keyStrokeSetup("integerspinner2");
+						},
+						runTest:function(){
+							return a11yKeystrokeTest("integerspinner2");
+						}
+					},
+					{
+						name:"integertextbox3Keystrokes",
+						timeout:9000,
+						setUp:function(){
+							keyStrokeSetup("integertextbox3");
+						},
+						runTest:function(){
+							return a11yKeystrokeTest("integertextbox3");
+						}
+					},
+					{
+						name:"realspinner1Keystrokes",
+						timeout:9000,
+						setUp:function(){
+							keyStrokeSetup("realspinner1");
+						},
+						runTest:function(){
+							return a11yKeystrokeTest("realspinner1");
+						}
+					}
+				]);
+
+				// exponential value keystroke tests
+				doh.register("exponential",
+				[
+					{
+						name: "spinnerMinOnly large exp",
+						timeout: 15000,
+						setUp:function(){
+							spin4.focusNode.value="";
+							spin4.focus();
+						},
+						runTest: function(){
+							var d=new doh.Deferred();
+							doh.robot.typeKeys("0.5e99", 1000, 1200);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(spin4.isValid(false), "large exponential is invalid");
+								doh.f(spin4.isInRange(false), "large exponential is out of range");
+								doh.is(spin4.getErrorMessage(true), spin4.rangeMessage, "large exponential showing out of range message");
+								doh.is("5e+98", spin4.get('displayedValue'), "large exponential reformatted to standard form");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "spinnerMinOnly adjust small exp",
+						timeout: 15000,
+						setUp:function(){
+							spin4.focusNode.value="";
+							spin4.focus();
+						},
+						runTest: function(){
+							var d=new doh.Deferred();
+							doh.robot.typeKeys("0.5e9", 1000, 1000);
+							doh.robot.keyPress(dojo.keys.UP_ARROW, 500);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(spin4.isValid(false), "small exponential is valid");
+								doh.t(spin4.isInRange(false), "small exponential is in range");
+								doh.is(500000000.1, spin4.get('value'), "small exponential converted to whole number");
+								doh.is("500,000,000.1", spin4.get('displayedValue'), "small exponential converted to whole number with formatting");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "spinnerMinOnly adjust max exp",
+						timeout: 15000,
+						setUp:function(){
+							spin4.focusNode.value="";
+							spin4.focus();
+						},
+						runTest: function(){
+							var d=new doh.Deferred();
+							doh.robot.typeKeys("0.5e99", 1000, 1200);
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500); // convert to max
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(spin4.isValid(false), "large exponential converted to max is valid");
+								doh.t(spin4.isInRange(false), "max value is in range");
+								doh.is(89999999999999.9, spin4.get('value'), "max value (-.1)");
+								doh.is("89,999,999,999,999.9", spin4.get('displayedValue'), "max value (-.1) with formatting");
+							}), 1000);
+							return d;
+						}
+					}
+				]);
+
+				// invalid editing keystroke tests
+				doh.register("invalid editing",
+				[
+					{
+						name: "HOME key, out of range",
+						timeout: 15000,
+						setUp:function(){
+							spin4.focusNode.value="";
+							spin4.focus();
+						},
+						runTest: function(){
+							var d=new doh.Deferred();
+							doh.robot.typeKeys("0.5e99", 1000, 1200);
+							doh.robot.keyPress(dojo.keys.HOME, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(spin4.isValid(true), "HOME changed large exponential to valid min, value is instead: "+spin4.focusNode.value);
+								doh.t(spin4.isInRange(true), "HOME changed large exponential to in range");
+								doh.is(-10.9, spin4.get('value'), "HOME changed large exponential to min value");
+								doh.is("-10.9", spin4.get('displayedValue'), "HOME changed large exponential to min display");
+							}), 500);
+							return d;
+						}
+					},
+					{
+						name: "HOME key, invalid",
+						timeout: 15000,
+						setUp:function(){
+							spin4.focusNode.value="";
+							spin4.focus();
+						},
+						runTest: function(){
+							var d=new doh.Deferred();
+							doh.robot.typeKeys(".5e9a", 1000, 1000);
+							doh.robot.keyPress(dojo.keys.HOME, 500);
+							if(dojo.isMac){
+								doh.robot.keyPress(dojo.keys.LEFT_ARROW, 500, {meta:true});
+							}
+							doh.robot.typeKeys("1", 500, 200);
+							doh.robot.keyPress(dojo.keys.END, 500);
+							if(dojo.isMac){
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {meta:true});
+							}
+							doh.robot.keyPress(dojo.keys.BACKSPACE, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(spin4.isValid(true), "edited exponential is now valid");
+								doh.is(1.5e+9, spin4.get('value'), "edited exponential");
+							}), 500);
+							return d;
+						}
+					},
+					{
+						name: "out-of-range formatting",
+						timeout: 15000,
+						setUp:function(){
+							spin3.focusNode.value="";
+							spin3.focus();
+						},
+						runTest: function(){
+							var d=new doh.Deferred();
+							doh.robot.typeKeys("156.0", 1000, 1000);
+							doh.robot.keyPress(dojo.keys.TAB, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(spin3.isValid(), "out-of-range is invalid");
+								doh.is('156.0', spin3.get('displayedValue'), "fraction not removed from out-of-range");
+								doh.is(156, spin3.get('value'), "out-of-range number returns number");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "improper fraction",
+						timeout: 15000,
+						setUp:function(){
+							spin4.focusNode.value="";
+							spin4.focus();
+						},
+						runTest: function(){
+							var d=new doh.Deferred();
+							doh.robot.typeKeys("99", 1000, 400);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(spin4.isValid(), "missing fraction is invalid");
+								doh.is('99', spin4.get('displayedValue'), "fraction not added to unparsable number");
+								doh.t(isNaN(spin4.get('value')), "unparsable number causes no value");
+							}), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("rounding",
+				[
+					{
+						name: "simple",
+						timeout: 15000,
+						runTest: function(){
+							var d=new doh.Deferred();
+							var spinner = dijit.byId("integertextbox3");
+							spinner.set('value', '');
+							spinner.focus();
+							doh.robot.typeKeys("1.2339", 1000, 1200);
+							doh.robot.keyPress(dojo.keys.TAB, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(spinner.isValid(false), "no error when rounding");
+								doh.is(1.234, spinner.get('value'), "value is rounded");
+								doh.is("1.234", spinner.get('displayedValue'), "rounded value correctly displayed");
+							}), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/form/robot/Spinner_mouse.html b/dijit/tests/form/robot/Spinner_mouse.html
new file mode 100644
index 0000000..ed40d26
--- /dev/null
+++ b/dijit/tests/form/robot/Spinner_mouse.html
@@ -0,0 +1,397 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Spinner Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				var spin1;
+				var spin2;
+				var spin3;
+				var delta=1; // redefine with doh.robot.mouseWheelSize when it is available
+				doh.robot.initRobot('../test_Spinner.html');
+
+				doh.register("setUp",{
+					name: "setUp",
+					timeout: 15000,
+					setUp:function(){
+						spin1=dijit.byId('integerspinner1');
+						spin2=dijit.byId('integerspinner2');
+						spin3=dijit.byId('realspinner1');
+					},
+					runTest: function(){
+						// assert onChange not fired
+						doh.is("not fired yet!", dojo.byId('oc1').value);
+
+						// make sure initial values are what we expect
+						doh.is(1, spin1.smallDelta);
+						doh.is(900, spin1.get('value'), "integerspinner1");
+						doh.is(1000, spin2.get('value'), "integerspinner2");
+						doh.is(1.0, spin3.get('value'), "realspinner1");
+					}
+				});
+
+				doh.register("setvaluetest", [
+					{
+						name: "valid",
+						runTest:function(){
+							spin1.set('value', 400);
+							doh.is(400, spin1.focusNode.value);
+							doh.is(true, spin1.isValid());
+
+						}
+					},
+
+					{
+						name: "null_notrequired",
+						runTest:function(){
+							spin1.set('value', null);
+							spin1.set('required',false);
+							doh.is('', spin1.focusNode.value);
+							doh.is(true, spin1.isValid());
+							doh.is(true, isNaN(spin1.get('value')));
+						},
+						tearDown:function(){
+							spin1.set('required',true);
+							spin1.set('value', 900);
+						}
+					},
+
+					{
+						name: "null_required",
+						runTest:function(){
+							spin1.set('value', null);
+							doh.is('', spin1.focusNode.value);
+							doh.is(false, spin1.isValid());
+							doh.is(true, isNaN(spin1.get('value')));
+						}
+					},
+
+					{
+						name: "spinner1_invalid",
+						timeout: 15000,
+						runTest: function(){
+							// assert invalid works
+							var d=new doh.Deferred();
+							doh.robot.mouseMoveAt(spin1.focusNode, 500);
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(function(){
+								spin1.focusNode.value="";
+							}, 500);
+							doh.robot.typeKeys("0.5", 500, 600);
+							doh.robot.sequence(function(){
+								try{
+								// test before user clicks away
+								doh.f(spin1.isValid(), "spin1 is marked as error");
+								doh.robot.keyPress(dojo.keys.TAB, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// also test after user clicks away
+									doh.f(spin1.isValid(), "spin1 is marked as error");
+								}), 500);
+								}catch(e){d.callback(e);}
+							}, 500);
+							return d;
+						},
+						tearDown:function(){
+							spin1.set('value', 1);
+						}
+					},
+
+					{
+						name: "spinner3_invalid",
+						timeout: 15000,
+						runTest: function(){
+							// assert invalid works
+							var d=new doh.Deferred();
+							doh.robot.mouseMoveAt(spin3.focusNode, 500);
+							doh.robot.mouseClick({left:true}, 500);
+							doh.robot.sequence(function(){
+								spin3.focusNode.value="";
+							}, 500);
+							doh.robot.typeKeys("0.a", 500, 600); // vs 0.5 in spinner1_invalid, spin3 would accept that
+							doh.robot.sequence(function(){
+								try{
+								// test before user clicks away
+								doh.f(spin3.isValid(), "spin3 is marked as error");
+								doh.robot.keyPress(dojo.keys.TAB, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									// also test after user clicks away
+									doh.f(spin3.isValid(), "spin3 is marked as error");
+								}), 500);
+								}catch(e){d.callback(e);}
+							}, 500);
+							return d;
+						},
+						tearDown:function(){
+							spin3.set('value', 1);
+						}
+					}
+				]);
+
+				doh.register("arrowButton", [
+					{
+						name: "spinner1_typematic",
+						timeout: 20000,
+						setUp:function(){
+							spin1.set('value', 900);
+						},
+						runTest: function(){
+							// test typematic
+							var d=new doh.Deferred();
+							doh.robot.mouseMoveAt(spin1.downArrowNode, 500);
+							doh.robot.mousePress({left:true,  middle:false,  right:false}, 500);
+							doh.robot.mouseRelease({left:true,  middle:false,  right:false}, 5000); // going too fast overwhelms the CPU and starves the robot thread
+							doh.robot.mousePress({left:true,  middle:false,  right:false}, 500);
+							doh.robot.mouseRelease({left:true,  middle:false,  right:false}, 5000);
+							doh.robot.sequence(function(){
+								var v = spin1.get('value');
+								if(v <= 875){
+									d.callback(true);
+								}else{
+									d.errback(new Error('Error in typematic test. Expected <= 875, got ' + v));
+								}
+							}, 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "spinner1_max",
+						timeout: 15000,
+						setUp:function(){
+							spin1.set('value', 1549);
+						},
+						runTest: function(){
+							// test max with arrow button
+							var d=new doh.Deferred();
+							// press once: should move up
+							doh.robot.mouseMoveAt(spin1.upArrowNode, 500);
+							doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+							doh.robot.mouseMoveAt('sv1_4', 500);
+							doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is(1550, spin1.get('value'));
+								doh.is("1,550", spin1.focusNode.value);
+								doh.is("1550", dojo.byId('oc1').value);
+								doh.is(true, spin1.isValid());
+								// press again: shouldn't move
+								doh.robot.mouseMoveAt(spin1.upArrowNode, 500);
+								doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+								doh.robot.mouseMoveAt('sv1_4', 500);
+								doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is(1550, spin1.get('value'));
+									doh.is("1,550", spin1.focusNode.value);
+									doh.is("1550", dojo.byId('oc1').value);
+									doh.is(true, spin1.isValid());
+								}), 500);
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "spinner1_min",
+						timeout: 15000,
+						setUp:function(){
+							spin1.set('value', 1);
+						},
+						runTest: function(){
+							// test min with arrow button
+							var d=new doh.Deferred();
+							// press once: should move up
+							doh.robot.mouseMoveAt(spin1.downArrowNode, 500);
+							doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+							doh.robot.mouseMoveAt('sv1_4', 500);
+							doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is(0, spin1.get('value'));
+								doh.is("0", spin1.focusNode.value);
+								doh.is("0", dojo.byId('oc1').value);
+								doh.is(true, spin1.isValid());
+								// press again: can move since no min
+								doh.robot.mouseMoveAt(spin1.downArrowNode, 500);
+								doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+								doh.robot.mouseMoveAt('sv1_4', 500);
+								doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is(-1, spin1.get('value'));
+									doh.is("-1", spin1.focusNode.value);
+									doh.is("-1", dojo.byId('oc1').value);
+									doh.is(true, spin1.isValid());
+								}), 500);
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("mouseWheel", [
+					{
+						name:"spinner1",
+						timeout:5500,
+						setUp:function(){
+							spin1.set('value', 900);
+						},
+						runTest:function(){
+							// get the mouse's delta
+							// note that Spinner spins backwards!
+							delta=-doh.robot.mouseWheelSize;
+							var d=new doh.Deferred();
+							doh.robot.mouseMoveAt(spin1.domNode, 1000);
+							doh.robot.mouseClick({left:true}, 500);
+							// wheel up 10 times
+							// this should increase the value by 10
+							// takes 100ms/click
+							doh.robot.mouseWheel(-10, 1000, 1000);
+							doh.robot.sequence(function(){
+								var v=spin1.get('value');
+								if(v==(900+10*delta)){
+									d.callback(true);
+								}else{
+									d.errback(new Error("spinner 1: wrong value, expected "+(900+10*delta)+", got "+spin1.get('value')));							}
+							}, 1000);
+							return d;
+						}
+					},
+
+					{
+						name:"spinner2",
+						timeout:5500,
+						setUp:function(){
+							spin2.set('value', 1000);
+						},
+						runTest:function(){
+							// test custom delta with mouse wheel
+							// it should increment 10 per mouse wheel
+							var d=new doh.Deferred();
+							doh.robot.mouseMoveAt(spin2.domNode, 1000);
+							doh.robot.mouseClick({left:true}, 500);
+							// wheel down 9 times
+							// this should decrease the value by 90
+							// takes 100ms/click
+							doh.robot.mouseWheel(9, 1000, 900);
+							doh.robot.sequence(function(){
+								if(spin2.get('value')==(1000-90*delta)){
+									d.callback(true);
+								}else{
+									d.errback(new Error("spinner 2: wrong value, expected "+(1000-90*delta)+", got "+spin2.get('value')));
+								}
+							}, 1000);
+							return d;
+						}
+					},
+
+					{
+						name:"spinner3",
+						timeout:5500,
+						setUp:function(){
+							spin3.set('value', 1.0);
+						},
+						runTest:function(){
+							// test real number spinner with mouse wheel
+							// it should increment 0.1 per mouse wheel
+							var d=new doh.Deferred();
+							doh.robot.mouseMoveAt(spin3.domNode, 1000);
+							doh.robot.mouseClick({left:true}, 500);
+							// wheel up 10
+							// this should increase the value by 1.0
+							// takes 100ms/click
+							doh.robot.mouseWheel(-10, 1000, 1000);
+							doh.robot.sequence(function(){
+								if(spin3.get('value')==(1.0+1.0*delta)){
+									d.callback(true);
+								}else{
+									d.errback(new Error("spinner 3: wrong value, expected "+(1.0+1.0*delta)+", got "+spin3.get('value')));
+								}
+							}, 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "spinner3_max",
+						timeout: 15000,
+						setUp:function(){
+							spin3.set('value', 155-0.1*delta);
+						},
+						runTest: function(){
+							// test max with arrow key
+							var d=new doh.Deferred();
+							// press once: should move up
+							doh.robot.mouseMoveAt(spin3.focusNode, 500);
+							doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+							// wheel up 1; this will increase the value by delta
+							doh.robot.mouseWheel(-1, 500, 1);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is(155.0, spin3.get('value'));
+								doh.is("155.0", spin3.focusNode.value);
+								doh.is(true, spin3.isValid());
+								// press again: shouldn't move
+								doh.robot.mouseMoveAt(spin3.focusNode, 500);
+								doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+								// wheel up 1; this will increase the value by delta
+								doh.robot.mouseWheel(-1, 500, 1);
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is(155.0, spin3.get('value'));
+									doh.is("155.0", spin3.focusNode.value);
+									doh.is(true, spin3.isValid());
+								}), 500);
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "spinner3_min",
+						timeout: 15000,
+						setUp:function(){
+							spin3.set('value', -10.9+0.1*delta);
+						},
+						runTest: function(){
+							// test min with arrow key
+							var d=new doh.Deferred();
+							// press once: should move up
+							doh.robot.mouseMoveAt(spin3.focusNode, 500);
+							doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500);
+							doh.robot.mouseWheel(1, 500, 1);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is(-10.9, spin3.get('value'));
+								doh.is("-10.9", spin3.focusNode.value);
+								doh.is(true, spin3.isValid());
+								// press again: shouldn't move
+								doh.robot.mouseMoveAt(spin3.focusNode, 500);
+								doh.robot.mouseClick({left:true,  middle:false,  right:false}, 500);
+								doh.robot.mouseWheel(1, 500, 1);
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is(-10.9, spin3.get('value'));
+									doh.is("-10.9", spin3.focusNode.value);
+									doh.is(true, spin3.isValid());
+								}), 500);
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/form/robot/Textarea.html b/dijit/tests/form/robot/Textarea.html
new file mode 100644
index 0000000..a48b392
--- /dev/null
+++ b/dijit/tests/form/robot/Textarea.html
@@ -0,0 +1,178 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>doh.robot Textarea Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Textarea.html');
+
+				doh.register("height tests", [
+					{
+						name: "initial height",
+						runTest: function(){
+							doh.t(dojo.marginBox("largeTextArea").h > dojo.marginBox("blank").h);
+						}
+					},
+					{
+						name: "expansion/contraction by newline",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							
+							var height1 = dojo.marginBox("blank").h;
+
+							dijit.byId("blank").focus();
+
+							// Test expand on newline
+							doh.robot.typeKeys('Row of text.', 500, 500);
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								var height2 = dojo.marginBox("blank").h;
+								doh.t(height2 > height1, "height went from " + height1 + " to " + height2);
+							}), 500);
+
+							// Test shrink on delete of newline
+							doh.robot.keyPress(dojo.keys.DELETE, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								var height2 = dojo.marginBox("blank").h;
+								doh.t(height2 > height1, "height went from " + height1 + " to " + height2);
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "expansion/contraction by word wrap",
+						timeout: 30000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var height1 = dojo.marginBox("blank").h,
+								height2,
+								height3;
+
+							dijit.byId("blank").focus();
+
+
+							// Test expand by wordwrap
+							var text = 'The quick brown fox jumped over the lazy dog.';
+							for(var i=0; i<5; i++){
+								doh.robot.typeKeys(text, 500, 500);
+							}
+							doh.robot.sequence(d.getTestErrback(function(){
+								height2 = dojo.marginBox("blank").h;
+								doh.t(height2 > height1, "height went from " + height1 + " to " + height2);
+								console.log("height went from " + height1 + " to " + height2);
+							}), 7000);
+
+							// Test shrink on delete (backspace) of text.   delete seems to delete the next character
+							// rather than the previous character, hence the LEFT_ARROW.
+							for(var i=0; i<text.length*5; i++){
+								doh.robot.keyPress(dojo.keys.LEFT_ARROW, 30, {});
+								doh.robot.keyPress(dojo.keys.DELETE, 30, {});
+							}
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								height3 = dojo.marginBox("blank").h;
+								doh.t(height3 < height2, "height went from " + height2 + " to " + height3);
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "expansion/contraction by cut/paste",
+						timeout: 30000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var modifier = dojo.isMac ? {meta: true} : {ctrl: true};
+
+							var height1 = dojo.marginBox("blank").h,
+								height2,
+								height3;
+
+							dijit.byId("blank").focus();
+
+							// Cut text, height should decrease
+							doh.robot.keyPress("a", 500, modifier);
+							doh.robot.keyPress("x", 500, modifier);
+							doh.robot.sequence(d.getTestErrback(function(){
+								height2 = dojo.marginBox("blank").h;
+								doh.t(height2 < height1, "height went from " + height1 + " to " + height2);
+								console.log("height went from " + height1 + " to " + height2);
+							}), 500);
+
+							// Paste text, height should increase
+							doh.robot.keyPress("v", 500, modifier);
+							doh.robot.keyPress("v", 500, modifier);
+							doh.robot.sequence(d.getTestCallback(function(){
+								height3 = dojo.marginBox("blank").h;
+								doh.t(height3 > height2, "height went from " + height2 + " to " + height3);
+							}), 500);
+
+							return d;
+						}
+					}
+
+				]);
+
+				doh.register("miscellaneous", [
+					{
+						name: "maxLength",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							
+							var ta = dijit.byId("simple");
+							
+							ta.focus();
+
+							// Limit is 50, and there's text there already, so not all of
+							// these characters will fit; some should be rejected.
+							doh.robot.typeKeys('0123456789', 500, 500);	
+							doh.robot.sequence(d.getTestErrback(function(){
+								var value = ta.get("value");
+								doh.is(50, value.length, "should have stopped at 50, value is " + value);
+							}), 500);
+
+							// Erase a character
+							doh.robot.keyPress(dojo.keys.LEFT_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.DELETE, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								value = ta.get("value");
+								doh.is(49, value.length, "erased a char, value is " + value);
+							}), 500);
+
+							// And try to type a new character, there should be room now,
+							// but just for one character
+							doh.robot.typeKeys('AB', 500, 500);	
+							doh.robot.sequence(d.getTestCallback(function(){
+								value = ta.get("value");
+								doh.is(50, value.length, "tried to type 2 chars but only 1 should fit, value is " + value);
+							}), 500);
+
+							return d;
+						}
+					}
+
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/form/robot/TimeTextBox.html b/dijit/tests/form/robot/TimeTextBox.html
new file mode 100644
index 0000000..bffc26c
--- /dev/null
+++ b/dijit/tests/form/robot/TimeTextBox.html
@@ -0,0 +1,81 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>doh.robot TimeTextBox Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+			dojo.require("dojo.date.stamp");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_TimeTextBox.html');
+
+				doh.register("TimeTextBox", [
+					{
+						name: "keyboard",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								w = dijit.byId('q1');
+	
+							// focus field, thus opening drop down		
+							w.focus();
+	
+							// advance from 5:45PM to 6PM, and select
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 1000, {});
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+							
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								var val = dojo.date.stamp.toISOString(w.get('value'), {selector: "time"});	
+								doh.is(val, "T18:00:00", "should be 6PM");
+							})), 500);
+							return d;
+						}
+					},
+					{
+						name: "partial input",
+						timeout: 60000,
+						setUp: function(){
+							// clear the field
+							var w = dijit.byId('q2');
+							w.set('value', null, false);
+						},
+						runTest: function(){
+							var d = new doh.Deferred(),
+								w = dijit.byId('q2');
+	
+							// focus field, thus opening drop down		
+							w.focus();
+	
+							// close drop down
+							doh.robot.keyPress(dojo.keys.ESCAPE, 1500, {});
+							
+							// do partial input
+							doh.robot.typeKeys('12:', 1000, 600);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.f(w.isValid(), 'fully invalid');
+								doh.t(w._isValidSubset(), 'partially valid');
+								doh.f(this.state == "Error", 'no error shown');
+							})), 500);
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/form/robot/_autoComplete_a11y.html b/dijit/tests/form/robot/_autoComplete_a11y.html
new file mode 100644
index 0000000..a389c1e
--- /dev/null
+++ b/dijit/tests/form/robot/_autoComplete_a11y.html
@@ -0,0 +1,941 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>doh.robot ComboBox/FilteringSelect General and A11Y Tests</title>
+
+	<style>
+		@import "../../../../util/doh/robot/robot.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../../helpers.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");
+
+		// TODO: provide URL toggle for FilteringSelect
+		var testWidget = "dijit.form.ComboBox";
+		var qstr = window.location.search.substr(1);
+		if(qstr.length){
+		        var qparts = qstr.split("&");
+		        for(var x=0; x<qparts.length; x++){
+		                var tp = qparts[x].split("=");
+		                if(tp[0] == "testWidget"){
+		                        testWidget = tp[1];
+		                }
+		        }
+		}
+		isComboBox = testWidget=="dijit.form.ComboBox";
+		dojo.addOnLoad(function(){
+
+			doh.robot.initRobot('../_autoComplete.html?testWidget='+testWidget);
+
+			var arrowlessComboBoxes=['arrowless'];
+
+			var robot_typeValue = function(combo, text, value, expectedText){
+				if(!value) value = text;
+				if(!expectedText) expectedText = text;
+				var d = new doh.Deferred();
+				combo.focusNode.focus();
+				combo.itemError = false;
+				doh.robot.sequence(function(){ combo.set("value", null); }, 500);
+				doh.robot.typeKeys(text.replace(/^(.).*$/, "$1"), 500);
+				doh.robot.typeKeys(text.replace(/^./, ""), 1500);
+				doh.robot.keyPress(dojo.keys.ENTER, 1500);
+				doh.robot.sequence(function(){
+					if(combo.get("value") == value && combo.focusNode.value == expectedText && !combo._isShowingNow && !combo.itemError){
+						d.callback(true);
+					}else{
+						if(combo._isShowingNow){
+							// menu could arrive after Enter keypress if it is not thrown out
+							// TODO: is this still needed?   I've got explicit tests in the "race condition"
+							// section to make sure this doesn't happen, and it doesn't seem to be.
+							combo._hideResultList();
+							d.errback(combo.id+" had a menu that did not close after an Enter keypress.");
+						}else{
+							d.errback(combo.id+" was supposed to have a value of "+value+" (actually "+combo.get("value")+"). Text is "+combo.focusNode.value+" (expected "+expectedText+")");
+						}
+					}
+				}, 2000);
+				return d;
+			};
+
+			var findMenuItem = function(combo, text){
+				var node = combo._popupWidget.domNode.firstChild;
+				while(((node.innerText || node.textContent).indexOf(text)<0) && node.nextSibling){
+					node = node.nextSibling;
+				}
+				return node;
+			}
+
+			// Select a value from the drop down using the keyboard, using "more choices" button to page as necessary
+			var robot_a11ySelectValue = function(combo, text, value, expectedText){
+				if(!value) value = text;
+				if(!expectedText) expectedText = text;
+				var d = new doh.Deferred();
+
+				combo.focusNode.focus();
+				combo.itemError = false;
+				doh.robot.sequence(function(){ combo.set("value", null); }, 1000);
+
+				doh.robot.mouseMoveAt(combo.focusNode, 0); // get cursor out of the way so that wiggling doesn't mess up test
+				doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500);
+				var repeat = function(){
+					var node = findMenuItem(combo, text);
+					var isMoreChoices = node == combo._popupWidget.nextButton;
+					var selected = combo._popupWidget.getHighlightedOption() || combo._popupWidget.domNode.firstChild;
+					while(selected != node){
+						doh.robot.keyPress(dojo.keys.DOWN_ARROW, 300);
+						selected = selected.nextSibling;
+					}
+					doh.robot.keyPress(dojo.keys.ENTER, 500);
+					if(isMoreChoices){
+						// can go faster since the data will have loaded by now
+						doh.robot.sequence(repeat, 1000);
+					}else{
+						doh.robot.sequence(function(){
+							if(combo.get("value") == value && combo.focusNode.value == expectedText && !combo.itemError){
+								d.callback(true);
+							}else{
+								d.errback(combo.id+" was supposed to have a value of "+value+" (actually "+combo.get("value")+"). Text is "+combo.focusNode.value+" (expected "+expectedText+")");
+							}
+						}, 500);
+					}
+
+				};
+				// first time, wait for the data to come in
+				doh.robot.sequence(repeat, 3000);
+				return d;
+			};
+
+			// Enter an invalid value into the ComboBox/FilteringSelect, and test
+			// that FilteringSelect flags it as an error (but ComboBox allows it)
+			var errorTest = function(){
+				robot_typeValue((this.combo = dijit.byId(this.combo)), "zxcxarax");
+				var d = new doh.Deferred();
+				doh.robot.sequence(dojo.hitch(this, function(){
+					if(isComboBox){
+						if(this.combo.isValid() && this.combo.get("value") == "zxcxarax" && !this.combo.itemError){
+							d.callback(true);
+						}else{
+							d.errback(new Error("Good value flagged as bad in ComboBox"));
+						}
+					}else{
+						if(!this.combo.isValid() && this.combo.get("value") == "" && !this.combo.itemError){
+							d.callback(true);
+						}else{
+							if(this.combo.isValid()){
+								d.errback(new Error("Bad value permitted in FilteringSelect. Value is: "+this.combo.get("value")+", text is:"+this.combo.focusNode.value));
+							}else{
+								d.errback(new Error("Expected value of '', got "+this.combo.get("value")));
+							}
+						}
+					}
+				}), 2000);
+				return d;
+			};
+
+			// Wait for data stores to finish loading before starting tests
+			doh.register("wait for data store load",
+				dojo.map(["store", "store2", "stateStore", "dijitStore"], function(name){
+					return {
+							name: "wait for " + name,
+							timeout: 5000,
+							runTest: function(){
+								var d = new doh.Deferred();
+								dojo.global[name].fetch({
+									onComplete: function(){
+										d.callback(true);
+									},
+									onError: function(e){
+										d.errback(e);
+									}
+								});
+								return d;
+							}
+						};
+				})
+			 );
+
+			// Verify that all of the form values are correct at init
+			doh.register("verify values",
+				{
+					name:"verifyValues",
+					runTest:function(){
+						// Spot check of initial conditions of widgets and DOM nodes
+
+						doh.is("California (CA)", dijit.byId("setvaluetest").get("displayedValue"), "state1 displayed value");
+						doh.is(isComboBox ? "California (CA)" : "CA", dijit.byId("setvaluetest").get("value"), "state1 value");
+						doh.is("not fired yet!", dojo.byId("oc1").value, "state1 onChange hasn't fired");
+
+						// Test that dojo.query() finds hidden field, see #8660
+						var elems = dojo.doc.getElementsByName("state2");
+						doh.is(1, elems.length, "exactly one node with name=state2");
+						doh.is(isComboBox ? "California" : "CA", elems[0].value, "state2 submit value");
+						var qelems = dojo.query("input[name=state2]");
+						doh.is(1, qelems.length, "dojo.query() returns exactly one node with name=state2");
+						doh.is(isComboBox ? "California" : "CA", qelems[0].value, "state2 dojo.query value");
+
+						doh.is(1, dojo.query("input[name=state3]").length,
+							"Just one input inside of " + testWidget + " w/name specified");
+						if(!isComboBox){
+							// Filtering select should have two inputs, but the displayed one is hidden
+							doh.is(2, dojo.query("input", dijit.byId("combo3").domNode).length-dojo.query("input[readOnly]", dijit.byId("combo3").domNode).length,
+								"Two inputs inside of filteringSelect");
+						}
+
+						doh.is("sticks & stones", dijit.byId("specialchars").get("displayedValue"), "specialchars get('displayValue')");
+						doh.is(isComboBox ? "sticks & stones" : "sticks", dijit.byId("specialchars").get("value"), "specialchars value");
+						doh.is("sticks & stones", dojo.query("input[id=specialchars]")[0].value, "specialchars display value via DOMNode");
+						doh.is(isComboBox ? "sticks & stones" : "sticks", dojo.query("input[name=specialchars]")[0].value, "specialchars submit value via DOMNode");
+					}
+				}
+			);
+			var comboIds=['setvaluetest','datatest','combo3','combobox4','arrowless','descending'];
+			for(var i=0; i<comboIds.length; i++){
+				doh.register("query input by name",{
+					name:comboIds[i],
+					combo:comboIds[i],
+					runTest:function(){
+						this.combo = dijit.byId(this.combo);
+						var queried=dojo.query("input[name="+(this.combo.valueNode||this.combo.focusNode).name+"]");
+						doh.is(1,queried.length,"Expected 1 combo with name "+(this.combo.valueNode||this.combo.focusNode).name+", found "+queried.length);
+						doh.is(this.combo.valueNode||this.combo.focusNode,queried[0],"Combo's valueNode did not match the one found by dojo.query.");
+					}
+				});
+			}
+
+			doh.register("set('displayedValue', ...)", [
+				// Set displayedValue to Kentucky.
+				// This should be a valid assignment.
+				{
+					timeout:5000,
+					name:"valid",
+					runTest:function(){
+						var d = new doh.Deferred(),
+							combo = dijit.byId("setvaluetest");
+						combo.set('displayedValue', 'Kentucky');
+						doh.robot.sequence(d.getTestCallback(function(){
+							var oc1=dojo.byId('oc1');
+							doh.is(isComboBox ? "Kentucky" : "KY", combo.get("value"), "get('value')");
+							doh.is(isComboBox ? "Kentucky" : "KY", oc1.value, "onChange");
+							if(!isComboBox){
+								doh.t(combo.isValid(), "isValid()");
+							}
+						}), 900);
+						return d;
+					}
+				},
+
+				// Set displayedValue to Canada.
+				// This should be an invalid assignment for FilteringSelect, but ok for ComboBox.
+				{
+					timeout:5000,
+					name:"invalid",
+					runTest:function(){
+						var d = new doh.Deferred(),
+							combo = dijit.byId("setvaluetest");
+						combo.set('displayedValue', 'Canada');
+						doh.robot.sequence(d.getTestCallback(function(){
+							var oc1=dojo.byId('oc1');
+							doh.is(isComboBox ? "Canada" : "", combo.get("value"), "get('value')");
+							doh.is(isComboBox ? "Canada" : "", oc1.value, "onChange");
+							if(!isComboBox){
+								doh.f(combo.isValid(), "isValid()");
+							}
+						}), 900);
+						return d;
+					}
+				}
+			]);
+
+			doh.register("set('value', ...)", [
+				// Set value to null.
+				// This should be an invalid assignment for FilteringSelect, but ok for ComboBox.
+				{
+					timeout:5000,
+					name:"nullvalue",
+					runTest:function(){
+						var d = new doh.Deferred(),
+							combo = dijit.byId("setvaluetest");
+						combo.set("value", null);
+						doh.robot.sequence(d.getTestCallback(function(){
+							var oc1=dojo.byId('oc1');
+							doh.is("", combo.get("value"), "get('value')");
+							doh.is("", oc1.value, "onChange");
+							if(!isComboBox){
+								doh.f(combo.isValid(), "isValid()");
+							}
+						}), 900);
+						return d;
+					}
+				}
+
+				// TODO: test some other get("value") calls
+			]);
+
+			doh.register("direct input", [
+				// Type a valid value and press Enter
+				{
+					timeout:60000,
+					name:"valid value",
+					combo:"setvaluetest",
+					runTest:function(){
+						return robot_typeValue(dijit.byId(this.combo), "California", isComboBox? undefined : "CA", isComboBox? undefined : "California (CA)");
+					}
+				},
+
+				// Type an invalid value and press Enter
+				{
+					timeout:60000,
+					name:"invalid value",
+					combo:"setvaluetest",
+					runTest:function(){
+						return (dojo.hitch(this, errorTest))();
+					},
+					tearDown:function(){
+						this.combo.set("value", isComboBox?"Alaska":"AK");
+					}
+				}
+			]);
+
+
+			doh.register("drop down navigation / keyboard", [
+				// Select a value from the drop down using the keyboard,
+				// used "more choices" button to page as necessary
+				{
+					timeout:60000,
+					name:"setvaluetest_a11y",
+					combo:"setvaluetest",
+					runTest:function(){
+						return robot_a11ySelectValue(dijit.byId(this.combo), "Texas", isComboBox? "Texas (TX)" : "TX", "Texas (TX)");
+					}
+				}
+			]);
+
+			// Test that drop down choices are filtered to values matching what user has typed
+			doh.register("filtering of drop down", [
+				{
+					timeout:60000,
+					name:"type C",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("setvaluetest");
+						combo.itemError = false;
+
+						combo.focusNode.focus();
+
+						// Filter drop down list to entries starting with "C"
+						doh.robot.sequence(function(){ combo.set("value", null); }, 1000);
+						doh.robot.keyPress("C", 100);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							// Check that drop down list has appeared, and contains California, Colorado, Connecticut
+							var list = dojo.byId("setvaluetest_popup");
+							doh.t(list, "drop down exists");
+							doh.t(isVisible(list), "drop down is visible");
+
+							var entries = dojo.query("li", list).filter(isVisible);
+							doh.is(3, entries.length, "three entries in drop down: " + list.innerHTML);
+							doh.is("California (CA)", innerText(entries[0]), "list #1");
+							doh.is("Colorado (CO)", innerText(entries[1]), "list #2");
+							doh.is("Connecticut (CT)", innerText(entries[2]), "list #3");
+
+							// Check that search-string highlighting is working
+							doh.is('<span class=dijitcomboboxhighlightmatch>c</span>onnecticut (ct)', entries[2].innerHTML.toLowerCase().replace(/"/g, ""), //balanced"
+								"highlighting is working");
+							doh.f(combo.itemError, testWidget + " item mismatch");
+						}), 900);
+
+						return d;
+					}
+				},
+				{
+					timeout:60000,
+					name:"type 'o' after 'C'",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("setvaluetest");
+						combo.itemError = false;
+
+						// Filter drop down list to entries starting with "Co"
+						doh.robot.keyPress("o", 100);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							// Check that drop down list is still there, and California has disappeared
+							var list = dojo.byId("setvaluetest_popup");
+							doh.t(list, "drop down exists");
+							doh.t(isVisible(list), "drop down is visible");
+
+							var entries = dojo.query("li", list).filter(isVisible);
+							doh.is(2, entries.length, "three entries in drop down: " + list.innerHTML);
+							doh.is("Colorado (CO)", innerText(entries[0]), "list #1");
+							doh.is("Connecticut (CT)", innerText(entries[1]), "list #2");
+							doh.f(combo.itemError, testWidget + " item mismatch");
+						}), 900);
+
+						return d;
+					}
+				},
+				{
+					timeout:60000,
+					name:"type backspace",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("setvaluetest");
+						combo.itemError = false;
+
+						doh.robot.keyPress(dojo.keys.BACKSPACE, 100);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							// List should again contain California
+							var list = dojo.byId("setvaluetest_popup");
+							doh.t(list, "drop down exists");
+							doh.t(isVisible(list), "drop down is visible");
+
+							var entries = dojo.query("li", list).filter(isVisible);
+							doh.is(3, entries.length, "three entries in drop down: " + list.innerHTML);
+							doh.is("California (CA)", innerText(entries[0]), "list #1");
+							doh.is("Colorado (CO)", innerText(entries[1]), "list #2");
+							doh.is("Connecticut (CT)", innerText(entries[2]), "list #3");
+							doh.f(combo.itemError, testWidget + " item mismatch");
+						}), 900);
+
+						return d;
+					}
+				}
+
+				// TODO: make separate test group for testing highlighting, and then check
+				//     - matching of anywhere in string (id=arrowless)
+				//     - highlightmatch=none (combobox4)
+			]);
+
+			// Test auto complete
+			doh.register("auto-complete", [
+				{
+					timeout:60000,
+					name:"no auto-complete",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("setvaluetest");
+
+						combo.focusNode.focus();
+						doh.robot.sequence(function(){ combo.set("value", null); }, 1000);
+
+						// Filter drop down list to entries starting with "C"
+						doh.robot.keyPress("C", 100);
+
+						// Then tab away
+						doh.robot.keyPress(dojo.keys.TAB, 500);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							// Check that drop down list has disappeared
+							var list = dojo.byId("setvaluetest_popup");
+							doh.t(!list || isHidden(list), "drop down is visible");
+
+							// Since autocomplete=false the contents should just be what the user typed
+							doh.is('C', combo.focusNode.value);
+							if(!isComboBox){
+								doh.f(dijit.byId("setvaluetest").isValid(), "FilteringSelect shouldn't be valid");
+							}
+							doh.f(dijit.byId("setvaluetest").itemError, testWidget + " item mismatch");
+						}), 900);
+
+						return d;
+					}
+				},
+				{
+					timeout:60000,
+					name:"auto-complete writes suggested letters in input box",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("datatest");	// auto-complete = true
+
+						combo.focusNode.focus();
+						doh.robot.sequence(function(){ combo.set("value", null); }, 1000);
+
+						// Filter drop down list to entries starting with "C"
+						doh.robot.keyPress("C", 100);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							var list = dojo.byId("datatest_popup");
+							doh.t(isVisible(list), "drop down is visible");
+
+							doh.is('California', combo.focusNode.value, "'alifornia' automatically appended to user input");
+						}), 900);
+
+						return d;
+					}
+				},
+				{
+					timeout:60000,
+					name:"auto-complete changes suggestion based on more typed letters",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("datatest");
+
+						// Further filter drop down to entries starting with "Co" (Colorado and Connectictut).
+						// Note that this depends on (and tests that) "alifornia" is selected (aka highlighted),
+						// so that the "o" keypress erases it and replaces the input box text with "Co"
+						doh.robot.keyPress("o", 100);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.is('Colorado', combo.focusNode.value, "suggestion changed from California to Colorado");
+						}), 900);
+
+						return d;
+					}
+				},
+				{
+					timeout:60000,
+					name:"tab-away auto-selects value",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("datatest");
+
+						// Then tab away
+						doh.robot.keyPress(dojo.keys.TAB, 500);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							// Check that drop down list has disappeared
+							var list = dojo.byId("datatest_popup");
+							doh.t(!list || isHidden(list), "drop down is hidden");
+
+							doh.is(isComboBox ? "Colorado" : "CO", combo.get("value"));
+							if(!isComboBox){
+								doh.t(combo.isValid(), "FilteringSelect should be valid");
+							}
+						}), 900);
+
+						return d;
+					}
+				}
+			]);
+
+			// TODO: test ESC key or click on screen background or click on another widget to close drop down
+
+			// TODO: click test for arrowless
+
+			// Race condition tests based on slow store:
+			// Test that drop down choices are filtered to values matching what user has typed
+			doh.register("race conditions", [
+				// Test when queries return in different order than issued
+				{
+					timeout:60000,
+					name:"query canceling on new input (#8950)",
+					runTest: function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("slow");
+
+						combo.focusNode.focus();
+						// this test is very timing-sensitive
+						// preload states.json for slow networks
+						doh.robot.keyPress(dojo.keys.DOWN_ARROW, 1000);
+						doh.robot.sequence(function(){ dojo.global.slowStateStore.log = []; }, 2000, 100); // clear log of query on * messages
+
+						// Filter drop down list to entries starting with "C"
+						doh.robot.typeKeys("c", 500, 100);
+						doh.robot.typeKeys("o", 300, 100); // 300ms > searchDelay, so C* query has been sent (but not yet returned results) when the o is typed
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							// The query "C*" should be canceled when "Co*" is started
+							var log = dojo.global.slowStateStore.log;
+							doh.is(4, log.length, "4 events on data store");
+							doh.is("start c*", log[0].type + " " + log[0].query.name);
+							doh.is("cancel c*", log[1].type + " " + log[1].query.name);
+							doh.is("start co*", log[2].type + " " + log[2].query.name);
+							doh.is("end co*", log[3].type + " " + log[3].query.name);
+
+							// Check that drop down list has appeared, and contains only Colorado and Connecticut (not California)
+							var list = dojo.byId("slow_popup");
+							doh.t(list, "drop down exists");
+							doh.t(isVisible(list), "drop down is visible");
+
+							var entries = dojo.query("li", list).filter(isVisible);
+							doh.is(2, entries.length, "two entries in drop down: " + list.innerHTML);
+							doh.is("Colorado", innerText(entries[0]), "list #1");
+							doh.is("Connecticut", innerText(entries[1]), "list #2");
+						}), 1000);
+
+						return d;
+					}
+				},
+
+				// Test that drop down doesn't show up after ENTER keypress, and also that
+				// searchDelay is preventing intemediate queries.
+				{
+					timeout:60000,
+					name:"pressing enter before search returns",
+					setUp: function(){
+						dojo.global.slowStateStore.log = [];
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("slow");
+
+						combo.focusNode.focus();
+						doh.robot.sequence(function(){ combo.set("value", null); }, 1000, 100); // wait for focus
+
+						// Start to filter drop down list to entries starting with "Co"
+						doh.robot.typeKeys("Co", 500, 100);
+
+						// But then hit ENTER after we've started the query to the data store, but
+						// before the data store returns query results... that should cancel the query.
+						doh.robot.keyPress(dojo.keys.ENTER, 300);	// 300ms > searchDelay
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							var log = dojo.global.slowStateStore.log;
+							var len = log.length;
+							if(!isComboBox){
+								doh.is(6, len, "query was issued for 'Co' but canceled");
+								doh.is("cancel ", log[1].type + " " + log[1].query.name);
+								doh.is("cancel Co*", log[3].type + " " + log[3].query.name);
+								doh.is("end Co", log[5].type + " " + log[5].query.name);
+							}else{ // this will look more like the IF block above once #6022 is committed
+								doh.is(2, len, "query was issued for 'Co' but canceled");
+								doh.is("cancel Co*", log[1].type + " " + log[1].query.name);
+							}
+
+							var list = dojo.byId("slow_popup");
+							doh.t(!list || isHidden(list), "drop down is *not* visible");
+
+							doh.is("Co", combo.get('displayedValue'), "auto-complete didn't fire");
+						}), 2000);
+
+						return d;
+					}
+				}
+			]);
+
+			// disabled tests+standard tests
+			doh.register("disabled", [
+
+				// Test that correct styling is applied
+				{
+					timeout:1000,
+					name:"disabled styling",
+					combo:"combo3",
+					runTest:function(){
+						this.combo = dijit.byId(this.combo);
+						doh.is(true, this.combo.get('disabled'));
+						doh.is(true, this.combo.focusNode.disabled);
+					}
+				},
+
+				// Test that you can't focus a disabled combobox
+				{
+					timeout:60000,
+					name:"tab over disabled elements",
+					runTest: function(){
+						var d = new doh.Deferred();
+
+						dojo.byId("datatestDijit").focus();
+						doh.is("datatestDijit", dojo.global.dijit._curFocus.id, "focused on elem before disabled combo");
+
+						// Tab over the disabled ComboBox
+						doh.robot.keyPress(dojo.keys.TAB, 1000);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.is("combobox4", dojo.global.dijit._curFocus.id, "focused on 'enable' button after disabled combo");
+						}), 1000);
+
+						return d;
+					}
+				}
+			]);
+
+			// now enable it and test that it can be used
+			doh.register("enabled", [
+				{
+					timeout:30000,
+					name:"combo3_enabledStyle",
+					setUp: function(){
+						dijit.byId("combo3").set("disabled", false);
+					},
+					runTest:function(){
+						var combo = dijit.byId("combo3");
+						doh.is(false, combo.get('disabled'));
+						doh.is(false, combo.focusNode.disabled);
+					}
+				}
+			]);
+
+			doh.register("specialchars", [
+				{
+					timeout:60000,
+					name:"specialchars_type",
+					combo:"specialchars",
+					runTest:function(){
+						return robot_typeValue(dijit.byId(this.combo), "sticks & stones", isComboBox? undefined : "sticks");
+					}
+				},
+
+				{
+					timeout:60000,
+					name:"specialchars_a11y",
+					combo:"specialchars",
+					runTest:function(){
+						return robot_a11ySelectValue(dijit.byId(this.combo), "more\\less", isComboBox? undefined : "more");
+					}
+				}
+			]);
+
+			doh.register("japanese", [
+				{
+					timeout:60000,
+					name:"japanese_a11y",
+					combo:"japanese",
+					runTest:function(){
+						return robot_a11ySelectValue((this.combo = dijit.byId(this.combo)), "\u6771\u533A (East)", isComboBox? undefined : "higashiku");
+					},
+					tearDown:function(){
+						this.combo.set("value", isComboBox?"\u6771\u533A (East)":"higashiku");
+					}
+				},
+
+				{
+					timeout:60000,
+					name:"japanese_type",
+					runTest:function(){
+						var d = new doh.Deferred(),
+							combo = dijit.byId("japanese");
+
+						combo.focusNode.focus();
+
+						doh.robot.keyPress(dojo.keys.END, 1000);
+						doh.robot.keyPress(dojo.keys.BACKSPACE, 500);
+						doh.robot.keyPress(dojo.keys.BACKSPACE, 500);
+						doh.robot.keyPress(dojo.keys.BACKSPACE, 500);
+						doh.robot.keyPress(dojo.keys.BACKSPACE, 500);
+						doh.robot.keyPress(dojo.keys.BACKSPACE, 500);
+						doh.robot.keyPress(dojo.keys.BACKSPACE, 500);
+						doh.robot.keyPress(dojo.keys.BACKSPACE, 500);
+						doh.robot.keyPress(dojo.keys.BACKSPACE, 500);
+						doh.robot.keyPress('x', 500, {ctrl:true});
+						doh.robot.keyPress(dojo.keys.ENTER, 500);
+						doh.robot.sequence(dojo.hitch(this, function(){
+							if(combo.get("value") == (isComboBox?"\u6771\u897F (Touzai)":"touzai") && combo.focusNode.value=="\u6771\u897F (Touzai)"){
+								d.callback(true);
+							}else{
+								d.errback(combo.id+" was supposed to have a value of "+(isComboBox?"\u6771\u897F (Touzai)":"touzai")+". Text is "+combo.focusNode.value+", value is "+combo.get("value"));
+							}
+						}), 900);
+						return d;
+					}
+				}
+			]);
+
+			doh.register("labelFunc", [
+				{
+					timeout:60000,
+					name:"labelFunc_a11y",
+					combo:"labelFunc",
+					runTest:function(){
+						// labelFunc makes Texas texas
+						return robot_a11ySelectValue((this.combo = dijit.byId(this.combo)), "Texas", isComboBox? "texas" : "TX", "texas");
+					},
+					tearDown:function(){
+						this.combo.set("value", isComboBox? "Texas" : "TX");
+					}
+				},
+
+				{
+					timeout:60000,
+					name:"labelFunc_type",
+					combo:"labelFunc",
+					runTest:function(){
+						var d = robot_typeValue((this.combo = dijit.byId(this.combo)), "Alabama", isComboBox? "alabama" : "AL", "alabama");
+						return d;
+					}
+				}
+			]);
+
+			// The specifying a sort order and an initial filter to ComboBox
+			doh.register("filter and sort params", [
+				{
+					timeout:60000,
+					name:"sort order",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("progCombo3");
+
+						combo.focusNode.focus();
+						doh.robot.sequence(function(){ combo.set("value", null); }, 1000);
+
+						// Show list, should be in reverse order
+						doh.robot.keyPress(dojo.keys.DOWN_ARROW, 100);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							var list = dojo.byId("progCombo3_popup");
+							doh.t(list, "drop down exists");
+							doh.t(isVisible(list), "drop down is visible");
+
+							var entries = dojo.query("li", list).filter(isVisible);
+							doh.is("United States of America", innerText(entries[0]), "list #1");
+						}), 900);
+
+						return d;
+					}
+				},
+				{
+					timeout:60000,
+					name:"initial filter, descending sort",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("progCombo3");
+
+						// Filter drop down list to entries starting with "A"
+						doh.robot.keyPress("A", 100);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							// Check that drop down list *doesn't* contain Africa (since it's a continent),
+							// just Argentina and Australia, in descending sort order
+							var list = dojo.byId("progCombo3_popup");
+							doh.t(list, "drop down exists");
+							doh.t(isVisible(list), "drop down is visible");
+
+							var entries = dojo.query("li", list).filter(isVisible);
+							doh.is(2, entries.length, "two countries (but no continents) in drop down: " + list.innerHTML);
+							doh.is("Australia", innerText(entries[0]), "list #1");
+							doh.is("Argentina", innerText(entries[1]), "list #2");
+						}), 900);
+
+						return d;
+					}
+				}
+			]);
+
+			// The specifying a sort order and an initial filter to ComboBox
+			doh.register("blur", [
+				{
+					timeout:60000,
+					name:"tooltip prompt",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("labelFunc");
+
+						combo.set("value", null);
+						combo.focusNode.focus();
+
+						// blur
+						doh.robot.keyPress(dojo.keys.TAB, 1000);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.t(!combo._message, "no tooltip on blur");
+						}), 1000);
+
+						return d;
+					}
+				},
+				{
+					timeout:60000,
+					name:"empty but required",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("combobox4");
+
+						combo.set("value", null);
+						combo.focusNode.focus();
+
+						// blur
+						doh.robot.keyPress(dojo.keys.TAB, 1000);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.t(combo.state == "Error", "required field has error on blur");
+						}), 1000);
+
+						return d;
+					}
+				}
+			]);
+
+			doh.register("wrap", [
+				{
+					timeout:10000,
+					name:"wrap without More choices",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("preservetitletest");
+
+						combo.set('pageSize', 5); // remove More choices
+						combo.focusNode.focus();
+
+						// Show list, should be in reverse order
+						doh.robot.keyPress(dojo.keys.DOWN_ARROW, 1000);
+						for(var i=0; i < 14; i++){
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 200); // down arrow and wrap twice
+						}
+						for(i=0; i < 4; i++){
+							doh.robot.keyPress(dojo.keys.UP_ARROW, 200); // up arrow and wrap at most once
+						}
+						doh.robot.keyPress(dojo.keys.ENTER, 500); // select current item
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.is(isComboBox ? "Vermont" : "vt", combo.get("value"), "wrap get('value')");
+						}), 1000);
+
+						return d;
+					}
+				},
+				{
+					timeout:10000,
+					name:"wrap with More choices",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("preservetitletest");
+
+						combo.set('pageSize', 4); // add More choices
+						combo.focusNode.focus();
+
+						// Show list, should be in reverse order
+						doh.robot.keyPress(dojo.keys.DOWN_ARROW, 1000);
+						for(var i=0; i < 14; i++){
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 200); // down arrow and wrap twice
+						}
+						for(i=0; i < 5; i++){
+							doh.robot.keyPress(dojo.keys.UP_ARROW, 200); // up arrow and wrap at most once
+						}
+						doh.robot.keyPress(dojo.keys.ENTER, 500); // select current item
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.is(isComboBox ? "Massachusetts" : "ma", combo.get("value"), "wrap get('value')");
+						}), 1000);
+
+						return d;
+					}
+				},
+				{
+					timeout:10000,
+					name:"wrap and TAB from Prev choices",
+					runTest:function(){
+						var d = new doh.Deferred();
+						var combo = dijit.byId("preservetitletest");
+
+						combo.set('pageSize', 4); // add More choices
+						combo.set("value", isComboBox ? "Maine" : "me", true); // fires onChange
+						combo.set("value", isComboBox ? "Connecticut" : "ct", false); // temporary value
+						combo.focusNode.focus();
+
+						// Show list, should be in reverse order
+						doh.robot.keyPress(dojo.keys.DOWN_ARROW, 1000);
+						for(var i=0; i < 5; i++){
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 200); // down arrow to More choices
+						}
+						doh.robot.keyPress(dojo.keys.ENTER, 500); // select More choices
+						doh.robot.keyPress(dojo.keys.UP_ARROW, 1000); // up arrow to Previous choices
+						doh.robot.keyPress(dojo.keys.TAB, 500); // select current item
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.is(isComboBox ? "Maine" : "me", combo.get("value"), "Previous choice reverts value");
+						}), 1000);
+
+						return d;
+					}
+				}
+			]);
+
+			doh.run();
+		});
+	</script>
+</head>
+</html>
diff --git a/dijit/tests/form/robot/_autoComplete_mouse.html b/dijit/tests/form/robot/_autoComplete_mouse.html
new file mode 100644
index 0000000..e9fcf66
--- /dev/null
+++ b/dijit/tests/form/robot/_autoComplete_mouse.html
@@ -0,0 +1,399 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>doh.robot ComboBox/FilteringSelect Mouse Tests</title>
+
+	<style>
+		@import "../../../../util/doh/robot/robot.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../../helpers.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");
+
+		// TODO: provide URL toggle for FilteringSelect
+		var testWidget = "dijit.form.ComboBox";
+		var qstr = window.location.search.substr(1);
+		if(qstr.length){
+		        var qparts = qstr.split("&");
+		        for(var x=0; x<qparts.length; x++){
+		                var tp = qparts[x].split("=");
+		                if(tp[0] == "testWidget"){
+		                        testWidget = tp[1];
+		                }
+		        }
+		}
+		isComboBox = testWidget=="dijit.form.ComboBox";
+		dojo.addOnLoad(function(){
+
+			doh.robot.initRobot('../_autoComplete.html?testWidget='+testWidget);
+
+			// Wait for data stores to finish loading before starting tests
+			doh.register("wait for data store load",
+				dojo.map(["store", "store2", "stateStore", "dijitStore"], function(name){
+					return {
+							name: "wait for " + name,
+							timeout: 5000,
+							runTest: function(){
+								var d = new doh.Deferred();
+								dojo.global[name].fetch({
+									onComplete: function(){
+										d.callback(true);
+									},
+									onError: function(e){
+										d.errback(e);
+									}
+								});
+								return d;
+							}
+						};
+				})
+			);
+
+			doh.register("drop down navigation / mouse", [
+				{
+					timeout:6000,
+					name:"open drop down",
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var combo = dijit.byId("setvaluetest");
+
+						// Open drop down
+						doh.robot.mouseMoveAt(combo.downArrowNode, 500, 500);
+						doh.robot.mouseClick({left:true}, 500);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							var list = dojo.byId("setvaluetest_popup"),
+								entries = dojo.query("li", list).filter(isVisible);
+							doh.t(isVisible(list), "list is visible");
+							doh.is(31, entries.length, "30 elements plus next button");
+						}), 1000, 500);
+
+						return d;
+					}
+				},
+
+				{
+					timeout:6000,
+					name:"next page",
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var list = dojo.byId("setvaluetest_popup"),
+							moreEntriesButton = dojo.query(":last-child", list)[0];
+
+						doh.t(isVisible(list), "list is still visible");
+						doh.t(moreEntriesButton, "found more entries button");
+
+						doh.robot.mouseMoveAt(moreEntriesButton, 500, 500);
+						doh.robot.mouseClick({left:true}, 500);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							var list = dojo.byId("setvaluetest_popup"),
+								entries = dojo.query("li", list).filter(isVisible);
+								doh.is("Minnesota (MN)", innerText(entries[1]));
+						}), 1000, 500);
+
+						return d;
+					}
+				},
+
+				{
+					timeout:6000,
+					name:"last page",
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var moreEntriesButton = dojo.query(":last-child", dojo.byId("setvaluetest_popup"))[0];
+
+						doh.robot.mouseMoveAt(moreEntriesButton, 500, 500);
+						doh.robot.mouseClick({left:true}, 500);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							var list = dojo.byId("setvaluetest_popup"),
+								entries = dojo.query("li", list).filter(isVisible);
+								doh.is(2, entries.length, "previous choices + wyoming");
+								doh.is("Wyoming (WY)", innerText(entries[1]));
+						}), 1000, 500);
+
+						return d;
+					}
+				},
+
+				{
+					timeout:6000,
+					name:"previous page",
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var previousEntriesButton = dojo.query(":first-child", dojo.byId("setvaluetest_popup"))[0];
+
+						doh.robot.mouseMoveAt(previousEntriesButton, 500, 500);
+						doh.robot.mouseClick({left:true}, 500);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							var list = dojo.byId("setvaluetest_popup"),
+								entries = dojo.query("li", list);
+								doh.is(32, entries.length, "30 states, plus next and previous button");
+								doh.is("Minnesota (MN)", innerText(entries[1]));
+								doh.is("Wisconsin (WI)", innerText(entries[30]));
+						}), 1000, 500);
+
+						return d;
+					}
+				},
+
+				{
+					timeout:6000,
+					name:"select value",
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var list = dojo.byId("setvaluetest_popup"),
+							entries = dojo.query("li", list),
+							nj = entries[8];
+
+						doh.robot.mouseMoveAt(nj, 500, 500);
+						doh.robot.mouseClick({left:true}, 500);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.is(isComboBox ? "New Jersey (NJ)" : "NJ", dijit.byId("setvaluetest").get("value"),
+								"selected New Jersey from drop down");
+							var count = dijit.byId("setvaluetest").labelFuncCounts['NJ'];
+							doh.is(4, count, "custom labelFunc was called " + count + " times (expected 4)");
+						}), 1000, 500);
+
+						return d;
+					}
+				},
+
+				{
+					timeout:6000,
+					name:"blur value",
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var combo = dijit.byId("setvaluetest");
+						// focus combo
+						doh.robot.mouseMoveAt(combo.focusNode, 500, 500);
+						doh.robot.mouseClick({left:true}, 500);
+						// blur
+						doh.robot.mouseMoveAt('sv1_4', 500, 500);
+						doh.robot.mouseClick({left:true}, 500);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.is(isComboBox ? "New Jersey (NJ)" : "NJ", dijit.byId("setvaluetest").get("value"),
+								"New Jersey still set after blur");
+							var count = dijit.byId("setvaluetest").labelFuncCounts['NJ'];
+							doh.is(4, count, "custom labelFunc was called " + count + " times (expected 4, unchanged after blur)");
+						}), 1000, 500);
+
+						return d;
+					}
+				}
+			]);
+
+
+			// disabled tests+standard tests
+			doh.register("disabled", [
+				{
+					timeout:6000,
+					name: "focus by mouse",
+					runTest:function(){
+						var d = new doh.Deferred(),
+							combo = dijit.byId("combo3");
+
+						doh.robot.mouseMoveAt(combo.focusNode, 500, 500);
+						doh.robot.mouseClick({left:true}, 500);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							if(!dojo.isWebKit){		// webkit bug, see #11064 - TODO: verify this is fixed now
+								doh.isNot(combo, dijit.getEnclosingWidget(dojo.global.dijit._curFocus), "click doesn't focus disabled combo");
+							}
+						}), 1000, 500);
+
+						return d;
+					}
+				},
+				{
+					timeout:6000,
+					name:"dropdown button",
+					runTest:function(){
+						var d = new doh.Deferred(),
+							combo = dijit.byId("combo3");
+
+						// Press Arrow Button
+						doh.robot.mouseMoveAt(combo.downArrowNode, 500, 500);
+						doh.robot.mouseClick({left:true}, 500);
+
+						// Assert that nothing happened
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.f(combo._popupWidget, "User was able to open the menu on a disabled ComboBox!");
+
+							// Testcase for #8923, uncomment when that bug is fixed
+							//doh.isNot(combo, dijit.getEnclosingWidget(dojo.global.dijit._curFocus), "button-click doesn't focus disabled combo");
+						}), 1000, 500);
+						return d;
+					}
+				}
+			]);
+
+			doh.register("9898", [
+				{
+					timeout: 9000,
+					name: "firefox mouse problem",
+					combo: "labelFunc",
+					handle: null,
+					setUp: function(){
+						this.combo = dijit.byId(this.combo);
+					},
+					runTest: function(){ // very hard to hit due to timing
+						var d = new doh.Deferred();
+						dojo.byId("native").scrollIntoView(false); // force to bottom of screen
+						// jump through hoops to increase the odds of hitting the problem
+						handle = this.combo.connect(this.combo, 'open', // when this.open() is called, set up 1 time event handlers
+							function(){
+								var popup = dijit.byId("labelFunc_popup"); // combobox results
+								var old = dojo.global.dojo._setMarginBox; // menu is about to be shrunk to fit the viewport, so stop this
+								dojo.global.dojo._setMarginBox = dojo.hitch(dojo.global,
+									function(){
+										dojo.global.dojo._setMarginBox = old; // restore original _setMarginBox
+									});
+								var old2 = popup._focusOptionNode;
+								popup._focusOptionNode = // LI option is about to be highlighted, so stop that as well
+									function(node){
+										popup._focusOptionNode = old2; // restore original _focusOptionNode
+									};
+								doh.robot.mouseRelease({left:true}, 0); // invoke popup._onMouseUp
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.t(isVisible(popup.domNode), "list is visible");
+								}), 1000, 500);
+							}
+						);
+						doh.robot.mouseMoveAt(this.combo.downArrowNode, 1000, 500);
+						doh.robot.mousePress({left:true}, 500) // mousedown on the arrow image
+
+						return d;
+					},
+					tearDown: function(){
+						this.combo.disconnect(handle);
+						this.combo._hideResultList();
+					}
+				}
+			]);
+
+			doh.register("10431", [
+				{
+					timeout: 9000,
+					name: "untouched blank value and required",
+					combo: "japanese",
+					setUp: function(){
+						this.combo = dijit.byId(this.combo);
+					},
+					runTest: function(){
+						doh.is("", this.combo.get("value"), "value");
+						doh.is("", this.combo.get('displayedValue'), "displayedValue");
+						doh.f(this.combo.isValid(), "isValid");
+						doh.is("", this.combo.state, "state");
+					},
+					tearDown: function(){
+						this.combo._hideResultList();
+					}
+				},
+				{
+					timeout: 9000,
+					name: "blurred blank value and required",
+					combo: "japanese",
+					setUp: function(){
+						this.combo = dijit.byId(this.combo);
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						doh.robot.mouseMoveAt(this.combo.focusNode, 500, 500);
+						doh.robot.mouseClick({left:true}, 500);
+						doh.robot.keyPress(dojo.keys.TAB, 1000);
+
+						doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+							doh.is("", this.combo.get("value"), "value");
+							doh.is("", this.combo.get('displayedValue'), "displayedValue");
+							doh.f(this.combo.isValid(), "isValid");
+							doh.is("Error", this.combo.state, "state");
+						})), 1000, 500);
+						return d;
+					},
+					tearDown: function(){
+						this.combo._hideResultList();
+					}
+				}
+			]);
+			
+			doh.register("placeHolder", [
+				{
+					timeout: 3000,
+					name: "focus/blur",
+					combo: "placeholdertest",
+					setUp: function(){
+						this.combo = dijit.byId(this.combo);
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						doh.is("", this.combo.get("value"), "value");
+						doh.is("", this.combo.get('displayedValue'), "displayedValue");
+						doh.is("Select a New England State", this.combo._phspan.innerHTML, "_phspan.innerHTML");
+						doh.isNot("none", this.combo._phspan.style.display, "_phspan.style.display");
+
+						this.combo.focus();
+						doh.is("none", this.combo._phspan.style.display, "_phspan.style.display");
+						
+						doh.robot.keyPress(dojo.keys.TAB, 500, {});
+						doh.robot.sequence(d.getTestCallback(dojo.hitch(this,function(){
+							doh.is("", this.combo.get("value"), "value");
+							doh.is("", this.combo.get('displayedValue'), "displayedValue");
+							doh.isNot("none", this.combo._phspan.style.display, "_phspan.style.display");
+						})), 500);
+						return d;
+					},
+					tearDown: function(){
+						this.combo._hideResultList();
+					}
+				},
+				{
+					timeout: 6000,
+					name: "select a value",
+					combo: "placeholdertest",
+					setUp: function(){
+						this.combo = dijit.byId(this.combo);
+					},
+					runTest: function(){
+						var d = new doh.Deferred(), value = isComboBox?'Connecticut':'ct';
+						this.combo.set("value",value);
+						doh.is(value, this.combo.get("value"), "selected Connecticut from drop down");
+
+						this.combo.focus();
+						doh.is("none", this.combo._phspan.style.display, "_phspan.style.display 1");
+						
+						doh.robot.keyPress(dojo.keys.TAB, 500, {});
+						doh.robot.sequence(d.getTestCallback(dojo.hitch(this,function(){
+							doh.is(value, this.combo.get("value"), "value");
+							doh.is("none", this.combo._phspan.style.display, "_phspan.style.display 2");
+							doh.is('Connecticut', this.combo.textbox.value, "textbox.value 2");
+						})), 500);
+						return d;
+					},
+					tearDown: function(){
+						this.combo._hideResultList();
+					}
+				}
+			]);
+
+			doh.run();
+		});
+	</script>
+</head>
+</html>
diff --git a/dijit/tests/form/robot/test_validate.html b/dijit/tests/form/robot/test_validate.html
new file mode 100644
index 0000000..085b320
--- /dev/null
+++ b/dijit/tests/form/robot/test_validate.html
@@ -0,0 +1,1113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>doh.robot Validation Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_validate.html');
+
+				// Test initial conditions
+				doh.register("initial conditions", {
+					name: "initial conditions",
+					runTest: function(){
+						var form1 = dojo.byId("form1");
+						
+						doh.is("Testing Testing", form1.firstname.value, "firstname");
+						doh.is("not fired yet!", dojo.byId("oc1").value, "firstname onchange");
+
+						doh.is("TESTING TESTING", form1.lastname.value, "lastname");
+						
+						doh.is("", form1.age.value, "age");
+						doh.is("not fired yet!", dojo.byId("oc3").value, "age onchange");
+						
+						doh.is("", form1.occupation.value, "occupation");
+						
+						doh.is("3000", form1.elevation.value, "elevation");
+						doh.is("3,000", dojo.byId("q05").value, "elevation display value");
+						doh.is("not fired yet!", dojo.byId("oc5").value, "elevation onchange");
+						
+						doh.is("54775.53", form1.income1.value, "income1");
+						doh.is("$54,775.53", dojo.byId("q08").value, "income1 display value");
+						doh.is("not fired yet!", dojo.byId("oc8").value, "income1 onchange");
+
+						doh.is("54775.53", form1.income2.value, "income2");
+						doh.is("€54,775.53", dojo.byId("q08eur").value, "income2 display value");
+
+						doh.is("someTestString", form1.phone.value, "phone");
+						doh.is("", form1.password.value, "password");
+						doh.is("", form1.ticket1651.value, "ticket1651");
+						doh.is("cannot type here", form1.readOnly.value, "readonly");
+						doh.is("cannot type here", form1.disabled.value, "disabled");
+					}
+				});
+
+				var _setvaluetest = function(textbox, setVal, focusVal, attrVal, isValid, chgVal, required){
+					textbox = dijit.byId(textbox);
+					if(required !== undefined){
+						textbox.set('required', required);
+					}
+					textbox.set('value', setVal);
+					doh.is(focusVal, textbox.focusNode.value, "focusNode.value");
+					doh.is(attrVal, textbox.get('value'), "get('value')");
+					doh.is(typeof attrVal, typeof textbox.get('value'), "typeof get('value')");
+					doh.is(isValid, textbox.isValid(), "isValid()");
+					var d = new doh.Deferred();
+					var onChange = dojo.byId('oc3');
+					doh.robot.sequence(d.getTestCallback(function(){
+						doh.is(chgVal.toString(), onChange.value, "onChange.value");
+					}), 500);
+					return d;
+				};
+
+				doh.register("setvaluetest", [
+					{
+						name: "valid_max",
+						timeout: 1000,
+						runTest: function(){ return _setvaluetest('q03', 120, 120, 120, true, 120); }
+					},
+
+					{
+						name: "out_of_range_max",
+						timeout: 1000,
+						runTest: function(){ return _setvaluetest('q03', 121, 121, 121, false, 121); }
+					},
+
+					{
+						name: "valid_min",
+						timeout: 1000,
+						runTest: function(){ return _setvaluetest('q03', 0, 0, 0, true, 0); }
+					},
+
+					{
+						name: "out_of_range_min",
+						timeout: 1000,
+						runTest: function(){ return _setvaluetest('q03', -1, -1, -1, false, -1); }
+					},
+
+					{
+						name: "invalid",
+						timeout: 1000,
+						runTest: function(){ return _setvaluetest('q03', 'two', 'two', undefined, false, 'undefined'); }
+					},
+
+					{
+						name: "null_required",
+						timeout: 1000,
+						runTest: function(){ return _setvaluetest('q03', null, '', NaN, false, NaN, true); }
+					},
+
+					{
+						name: "null_notrequired",
+						timeout: 1000,
+						runTest: function(){ return _setvaluetest('q03', null, '', NaN, true, NaN, false); }
+					}
+				]);
+
+				doh.register("intermediatechanges", {
+					name: "valid",
+					textbox: "q01",
+					timeout: 60000,
+					setUp: function(){
+						this.textbox = dijit.byId(this.textbox);
+						this.textbox.set('value', '');
+						this.textbox.focusNode.focus();
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						var onChange = dojo.byId('oc1');
+						doh.robot.typeKeys('Testing', 1000, 1400);
+						doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+							// test that value changed while typing since intermediateChanges = true
+							doh.is('Testing', this.textbox.focusNode.value, "focusNode value");
+							doh.is('Testing', this.textbox.get('value'), "attr value");
+							doh.is('Testing', onChange.value, "onChange.value");
+						})), 1000);
+						return d;
+					}
+				});
+
+				doh.register("allcaps", {
+					name: "valid",
+					textbox: "q02",
+					timeout: 60000,
+					setUp: function(){
+						this.textbox = dijit.byId(this.textbox);
+						this.textbox.set('value', '');
+						this.textbox.focusNode.focus();
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						doh.robot.typeKeys('Testing', 1000, 1400);
+						doh.robot.sequence(function(){
+							dojo.byId("q01").focus();
+						}, 500);
+						doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+							doh.is('TESTING', this.textbox.focusNode.value, "focusNode.value");
+							doh.is('TESTING', this.textbox.get('value'), "get('value')");
+						})), 1000);
+						return d;
+					}
+				});
+
+				doh.register("maxlength", [
+					{
+						name: "3chars",
+						textbox: "fav",
+						timeout: 60000,
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							doh.robot.typeKeys('100', 1000, 600);
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								// test that value changed while typing since intermediateChanges = true
+								doh.is('100', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(100, this.textbox.get('value'), "get('value')");
+							})), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "4chars",
+						textbox: "fav",
+						timeout: 60000,
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							doh.robot.typeKeys('1001', 1000, 800);
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								// test that value changed while typing since intermediateChanges = true
+								doh.is('100', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(100, this.textbox.get('value'), "get('value')");
+								doh.robot.typeKeys('1', 500, 200);
+								doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+									doh.is('100', this.textbox.focusNode.value, "focusNode.value");
+									doh.is(100, this.textbox.get('value'), "get('value')");
+								})), 500);
+							})), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("errorStyle", [
+					{
+						name: "beforeClick",
+						textbox: "q04",
+						runTest: function(){
+							this.textbox = dijit.byId(this.textbox);
+							doh.is('', this.textbox.get('state'));
+							doh.is(false, this.textbox.isValid(), "isValid()");
+						}
+					},
+
+					{
+						name: "afterClick",
+						textbox: "q04",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							this.textbox = dijit.byId(this.textbox);
+							doh.robot.sequence(dojo.hitch(this, function(){
+								this.textbox.focusNode.focus();
+							}), 500);
+							doh.robot.sequence(dojo.hitch(this, function(){
+								dojo.byId("q01").focus();
+							}), 1000);	// time for promptMessage to appear on q04 (IE6 takes a while due to iframe)
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('Error', this.textbox.get('state'));
+								doh.is(false, this.textbox.isValid(), "isValid()");
+							})), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "valid",
+						textbox: "q04",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.focusNode.focus();
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is('Error', this.textbox.get('state'));
+								doh.is(false, this.textbox.isValid(), "isValid()");
+								doh.robot.typeKeys('a', 500, 200);
+								doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+									doh.is('a', this.textbox.get('value'), "get('value')");
+									doh.is('', this.textbox.get('state'), "state 1");
+									doh.is(true, this.textbox.isValid(), "isValid() 1");
+									dojo.byId("q01").focus();
+									doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+										doh.is('', this.textbox.get('state'), "state 2");
+										doh.is(true, this.textbox.isValid(), "isValid() 2");
+									})), 1000);
+								})), 500);
+							})), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("commaformat", [
+					{
+						name: "beforeClick",
+						textbox: "q05",
+						runTest: function(){
+							this.textbox = dijit.byId(this.textbox);
+							doh.is('3,000', this.textbox.focusNode.value, "focusNode.value");
+							doh.is('3000', this.textbox.get('value'), "get('value')");
+							doh.is(true, this.textbox.isValid(), "isValid()");
+						}
+					},
+
+					{
+						name: "click",
+						timeout: 60000,
+						textbox: "q05",
+						runTest: function(){
+							var d = new doh.Deferred();
+							this.textbox = dijit.byId(this.textbox);
+							var onChange = dojo.byId('oc5');
+							doh.robot.sequence(dojo.hitch(this, function(){
+								this.textbox.focusNode.focus();
+							}), 500);
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								// comma should disappear on click, value shouldn't change
+								doh.is('3,000', this.textbox.focusNode.value, "focusNode.value");
+								doh.is('3000', this.textbox.get('value'), "get('value')");
+								doh.is(true, this.textbox.isValid(), "isValid()");
+								doh.is('not fired yet!', onChange.value);
+							})), 500);
+							return d;
+						}
+					},
+
+					{
+						name: "type_valid_nocomma",
+						timeout: 60000,
+						textbox: "q05",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc5');
+							doh.robot.typeKeys('3000', 1000, 800);
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is('3000', this.textbox.focusNode.value, "focusNode.value");
+								doh.is('3000', this.textbox.get('value'), "get('value')");
+								doh.is(true, this.textbox.isValid(), "isValid()");
+								doh.is('NaN', onChange.value);
+								dojo.byId("q01").focus();
+								doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+									doh.is('3,000', this.textbox.focusNode.value, "focusNode.value");
+									doh.is('3000', this.textbox.get('value'), "get('value')");
+									doh.is(true, this.textbox.isValid(), "isValid()");
+									doh.is('3000', onChange.value);
+								})), 1000);
+							})), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "type_valid_comma",
+						timeout: 60000,
+						textbox: "q05",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc5');
+							doh.robot.typeKeys('3,000', 1000, 1000);
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is('3,000', this.textbox.focusNode.value, "focusNode.value");
+								doh.is('3000', this.textbox.get('value'), "get('value')");
+								doh.is(true, this.textbox.isValid(), "isValid()");
+								doh.is('NaN', onChange.value);
+								dojo.byId("q01").focus();
+								doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+									doh.is('3,000', this.textbox.focusNode.value, "focusNode.value");
+									doh.is('3000', this.textbox.get('value'), "get('value')");
+									doh.is(true, this.textbox.isValid(), "isValid()");
+									doh.is('3000', onChange.value);
+								})), 1000);
+							})), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "type_invalid_comma",
+						timeout: 60000,
+						textbox: "q05",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc5');
+							doh.robot.typeKeys('300,0', 1000, 1000);
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is('300,0', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(undefined, this.textbox.get('value'), "get('value')");
+								doh.is(false, this.textbox.isValid(), "isValid()");
+								doh.is('NaN', onChange.value);
+								dojo.byId("q01").focus();
+								doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+									doh.is('300,0', this.textbox.focusNode.value, "focusNode.value");
+									doh.is(undefined, this.textbox.get('value'), "get('value')");
+									doh.is(false, this.textbox.isValid(), "isValid()");
+									doh.is('undefined', onChange.value);
+								})), 1000);
+							})), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("currencyFormat", [
+					{
+						name: "beforeClick",
+						textbox: "q08",
+						runTest: function(){
+							this.textbox = dijit.byId(this.textbox);
+							doh.is('$54,775.53', this.textbox.focusNode.value, "focusNode.value");
+							doh.is('54775.53', this.textbox.get('value'), "get('value')");
+							doh.is(true, this.textbox.isValid(), "isValid()");
+						}
+					},
+
+					{
+						name: "click",
+						timeout: 60000,
+						textbox: "q08",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc8');
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								// comma should disappear on click, value shouldn't change
+								doh.is('54775.53', this.textbox.focusNode.value, "focusNode.value");
+								doh.is('54775.53', this.textbox.get('value'), "get('value')");
+								doh.is(true, this.textbox.isValid(), "isValid()");
+								doh.is('not fired yet!', onChange.value);
+							})), 500);
+							return d;
+						}
+					},
+
+					{
+						name: "type_valid_number",
+						timeout: 60000,
+						textbox: "q08",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc8');
+							doh.robot.typeKeys('10000.01', 1000, 1600);
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is('10000.01', this.textbox.focusNode.value, "focusNode.value");
+								doh.is('10000.01', this.textbox.get('value'), "get('value')");
+								doh.is(true, this.textbox.isValid(), "isValid()");
+								doh.is('NaN', onChange.value);
+								dojo.byId("q01").focus();
+								doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+									doh.is('$10,000.01', this.textbox.focusNode.value, "focusNode.value");
+									doh.is('10000.01', this.textbox.get('value'), "get('value')");
+									doh.is(true, this.textbox.isValid(), "isValid()");
+									doh.is('10000.01', onChange.value);
+								})), 1000);
+							})), 1000);
+							return d;
+						}
+					},
+					{
+						name: "type_valid_dollarsign",
+						timeout: 60000,
+						textbox: "q08",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc8');
+							doh.robot.typeKeys('$20000.01', 1000, 1800);
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is('$20000.01', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(20000.01, this.textbox.get('value'), "get('value')");
+								doh.is(true, this.textbox.isValid(), "isValid()");
+								doh.is('NaN', onChange.value);
+								dojo.byId("q01").focus();
+								doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+									doh.is('$20,000.01', this.textbox.focusNode.value, "focusNode.value");
+									doh.is(20000.01, this.textbox.get('value'), "get('value')");
+									doh.is(true, this.textbox.isValid(), "isValid()");
+									doh.is('20000.01', onChange.value);
+								})), 1000);
+							})), 1000);
+							return d;
+						}
+					},
+					{
+						name: "missing required decimal",
+						timeout: 6000,
+						textbox: "q08",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc8');
+							doh.robot.typeKeys('123', 1000, 600);
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('123', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(undefined, this.textbox.get('value'), "get('value')");
+								doh.f(this.textbox.isValid(), "!isValid()");
+							})), 1000);
+							return d;
+						}
+					},
+					{
+						name: "too few decimal digits",
+						timeout: 6000,
+						textbox: "q08",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc8');
+							doh.robot.typeKeys('123.0', 1000, 1000);
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('123.0', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(undefined, this.textbox.get('value'), "get('value')");
+								doh.f(this.textbox.isValid(), "!isValid()");
+							})), 1000);
+							return d;
+						}
+					},
+					{
+						name: "too many decimal digits",
+						timeout: 6000,
+						textbox: "q08",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc8');
+							doh.robot.typeKeys('123.000', 1000, 1400);
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('123.000', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(undefined, this.textbox.get('value'), "get('value')");
+								doh.f(this.textbox.isValid(), "!isValid()");
+							})), 1000);
+							return d;
+						}
+					},
+					{
+						name: "negative decimal",
+						timeout: 6000,
+						textbox: "q08",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc8');
+							doh.robot.typeKeys('-123.00', 1000, 1400);
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('-123.00', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(-123, this.textbox.get('value'), "get('value')");
+								doh.t(this.textbox.isValid(), "isValid()");
+							})), 1000);
+							return d;
+						}
+					},
+					{
+						name: "negative currency",
+						timeout: 6000,
+						textbox: "q08",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc8');
+							doh.robot.typeKeys('($123.00)', 1000, 1600);
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('($123.00)', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(-123, this.textbox.get('value'), "get('value')");
+								doh.t(this.textbox.isValid(), "isValid()");
+							})), 1000);
+							return d;
+						}
+					},
+					{
+						name: "convert negative decimal to negative currency",
+						timeout: 6000,
+						textbox: "q08",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc8');
+							doh.robot.typeKeys('-123.45', 1000, 1400);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('($123.45)', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(-123.45, this.textbox.get('value'), "get('value')");
+								doh.t(this.textbox.isValid(), "isValid()");
+							})), 1000);
+							return d;
+						}
+					},
+					{
+						name: "convert negative negative currency to negative decimal",
+						timeout: 6000,
+						textbox: "q08",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc8');
+							doh.robot.typeKeys('($123.45)', 1000, 1800);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('-123.45', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(-123.45, this.textbox.get('value'), "get('value')");
+								doh.t(this.textbox.isValid(), "isValid()");
+							})), 1000);
+							return d;
+						}
+					},
+					{
+						name: "exponent not allowed",
+						timeout: 6000,
+						textbox: "q08",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var onChange = dojo.byId('oc8');
+							doh.robot.typeKeys('1.23e0', 1000, 1200);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('1.23e0', this.textbox.focusNode.value, "focusNode.value");
+								doh.is(undefined, this.textbox.get('value'), "get('value')");
+								doh.f(this.textbox.isValid(), "!isValid()");
+							})), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("euroformat", {
+					name: "type_1",
+					timeout: 60000,
+					textbox: "q08eur",
+					setUp: function(){
+						this.textbox = dijit.byId(this.textbox);
+						this.textbox.set('value', '');
+						this.textbox.focusNode.focus();
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						doh.robot.typeKeys('1', 1000, 200);
+						doh.robot.sequence(dojo.hitch(this, function(){
+							dijit.byId('q01').focusNode.focus();
+						}), 500);
+						doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+							doh.is('€1.00', this.textbox.focusNode.value, "focusNode.value");
+							doh.is('1', this.textbox.get('value'), "get('value')");
+							doh.is(true, this.textbox.isValid(), "isValid()");
+						})), 1000);
+						return d;
+					}
+				});
+
+				doh.register("regexp", [
+					{
+						name: "valid",
+						timeout: 60000,
+						textbox: "q22",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							doh.robot.typeKeys('a', 1000, 200);
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('a', this.textbox.focusNode.value, "focusNode.value");
+								doh.is('a', this.textbox.get('value'), "get('value')");
+								doh.is(true, this.textbox.isValid(), "isValid()");
+							})), 500);
+							return d;
+						}
+					},
+
+					{
+						name: "invalid",
+						timeout: 60000,
+						textbox: "q22",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							doh.robot.typeKeys('a ', 1000, 400);
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('a ', this.textbox.focusNode.value, "focusNode.value");
+								doh.is('a ', this.textbox.get('value'), "get('value')");
+								doh.is(false, this.textbox.isValid(), "isValid()");
+							})), 500);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("password", {
+					name: "type",
+					timeout: 60000,
+					textbox: "q23",
+					setUp: function(){
+						this.textbox = dijit.byId(this.textbox);
+						this.textbox.set('value', '');
+						this.textbox.focusNode.focus();
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						doh.robot.typeKeys('abcdef', 1000, 1200);
+						doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+							doh.is('abcdef', this.textbox.focusNode.value, "focusNode.value");
+							doh.is('abcdef', this.textbox.get('value'), "get('value')");
+						})), 1000);
+						return d;
+					}
+				});
+
+				doh.register("readonly", [
+					{
+						name: "readonly",
+						timeout: 60000,
+						textbox: "q24",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							dojo.byId("mname").focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Tab into element (readonly *can* be focused, although disabled can't)
+							doh.robot.keyPress(dojo.keys.TAB, 1000, {shift: true});
+
+							// typing on a disabled element should have no effect
+							doh.robot.typeKeys('abc', 500, 600);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('cannot type here', this.textbox.focusNode.value, "focusNode.value");
+								doh.is('cannot type here', this.textbox.get('value'), "get('value')");
+							})), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "write",
+						timeout: 60000,
+						textbox: "q24",
+						setUp: function(){
+							this.textbox = dijit.byId(this.textbox);
+							this.textbox.set('value', '');
+							this.textbox.set('readOnly', false);
+							this.textbox.focusNode.focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							doh.robot.typeKeys('abc', 1000, 600);
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is('abc', this.textbox.focusNode.value, "focusNode.value");
+								doh.is('abc', this.textbox.get('value'), "get('value')");
+							})), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("disabled", [
+					{
+						name: "click doesn't focus",
+						timeout: 60000,
+						setUp: function(){
+							var textbox = dijit.byId("q24");
+							dojo.byId("mname").focus();
+							textbox.set('disabled', true);
+						},
+						runTest: function(){
+							var d = new doh.Deferred(),
+								textbox = dijit.byId("q24");
+
+							//  Clicking shouldn't have any effect since it's disabled
+							doh.robot.mouseMoveAt(textbox.focusNode, 500, 500);
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.isNot("q24", (dojo.global.dijit._curFocus||{}).id, "didn't focus");
+							})), 500);
+							return d;
+						}
+					},
+
+					{
+						name: "tab jumps over",
+						timeout: 60000,
+
+						setUp: function(){
+							var textbox = dijit.byId("q24");
+							dojo.byId("mname").focus();
+							textbox.set('disabled', true);
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.TAB, 500);
+
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is("q26", dojo.global.dijit._curFocus.id,
+										"tabbed past input, to the button after it");
+							})), 500);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("selectOnClick", [
+					{
+						name: "1 click does highlight",
+						timeout: 9000,
+						setUp: function(){
+							dijit.byId("q02").focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred(),
+								textbox = dijit.byId("q01");
+
+							textbox.set('value', 'Testing');
+							//  Clicking shouldn't have any effect since it's disabled
+							doh.robot.mouseMoveAt(textbox.focusNode, 500, 500);
+							doh.robot.mouseClick({left: true}, 500);
+							doh.robot.typeKeys("abc", 1000, 600);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("Abc", textbox.get('value'), "was highlighted");
+							}), 500);
+							return d;
+						}
+					},
+					{
+						name: "2 clicks doesn't highlight",
+						timeout: 9000,
+						setUp: function(){
+							dijit.byId("q02").focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred(),
+								textbox = dijit.byId("q01");
+
+							textbox.set('value', 'Testing');
+							//  Clicking shouldn't have any effect since it's disabled
+							doh.robot.mouseMoveAt(textbox.focusNode, 500, 500);
+							doh.robot.mouseClick({left: true}, 500);
+							doh.robot.mouseClick({left: true}, 1000);
+							var oldValue = textbox.get('value');
+							doh.robot.typeKeys("abc", 500, 600);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.isNot(oldValue, textbox.get('value'), "didn't change at all");
+								doh.isNot("Abc", textbox.get('value'), "was highlighted");
+							}), 500);
+							return d;
+						}
+					},
+					{
+						name: "TAB focus still highlights a selectOnFocus textbox",
+						timeout: 9000,
+						setUp: function(){
+							dijit.byId("q02").focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred(),
+								textbox = dijit.byId("q01");
+
+							textbox.set('value', 'Testing');
+							//  Clicking shouldn't have any effect since it's disabled
+							doh.robot.mouseMoveAt(textbox.focusNode, 500, 500);
+							doh.robot.mouseClick({left: true}, 500);
+							doh.robot.mouseClick({left: true}, 1000);
+							doh.robot.keyPress(dojo.keys.TAB, 1000);
+							doh.robot.keyPress(dojo.keys.TAB, 1000, {shift:true});
+							doh.robot.typeKeys("abc", 500, 600);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("Abc", textbox.get('value'), "was not highlighted");
+							}), 500);
+							return d;
+						}
+					},
+					{
+						name: "click doesn't highlight after TAB focus",
+						timeout: 9000,
+						setUp: function(){
+							dijit.byId("q02").focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred(),
+								textbox = dijit.byId("q01");
+
+							textbox.set('value', 'Testing');
+							//  Clicking shouldn't have any effect since it's disabled
+							doh.robot.mouseMoveAt(textbox.focusNode, 500, 500);
+							doh.robot.mouseClick({left: true}, 500);
+							doh.robot.mouseClick({left: true}, 1000);
+							doh.robot.keyPress(dojo.keys.TAB, 1000);
+							doh.robot.keyPress(dojo.keys.TAB, 1000, {shift:true});
+							doh.robot.mouseClick({left: true}, 1000);
+							var oldValue = textbox.get('value');
+							doh.robot.typeKeys("abc", 500, 600);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.isNot(oldValue, textbox.get('value'), "didn't change at all");
+								doh.isNot("Abc", textbox.get('value'), "was highlighted");
+							}), 500);
+							return d;
+						}
+					},
+					{
+						name: "mouse selection still works",
+						timeout: 9000,
+						setUp: function(){
+							dijit.byId("q02").focus();
+						},
+						runTest: function(){
+							var d = new doh.Deferred(),
+								textbox = dijit.byId("q01");
+
+							textbox.set('value', 'MMMMMMM');
+							//  Clicking shouldn't have any effect since it's disabled
+							doh.robot.mouseMoveAt(textbox.focusNode, 500, 500, 3, 6);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt(textbox.focusNode, 500, 500, 10, 6);
+							doh.robot.mouseRelease({left: true}, 500);
+							doh.robot.typeKeys("abc", 500, 600);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("AbcMMMMMM", textbox.get('value'), "could not select text");
+							}), 500);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("set constraints", [
+					{
+						name: "number",
+						timeout: 6000,
+						runTest: function(){
+							var textWidget = dijit.byId("q05");
+							textWidget.set('value', 12345);
+							doh.is("12,345", textWidget.get('displayedValue'), "default value");
+							textWidget.set('constraints', {places:2});
+							doh.is("12,345.00", textWidget.get('displayedValue'), "decimal value");
+						}
+					},
+					{
+						name: "currency",
+						timeout: 6000,
+						runTest: function(){
+							var textWidget = dijit.byId("q08eurde");
+							textWidget.set('value', 12345.25);
+							doh.is("12.345,25\xa0€", textWidget.get('displayedValue'), "EUR value");
+							textWidget.set('constraints', {currency:'USD', locale:'en-us'});
+							doh.is("$12,345.25", textWidget.get('displayedValue'), "USD value");
+						}
+					}
+				]);
+				
+				doh.register("placeholder", [
+					{
+						name: "textbox",
+						runTest: function(){
+							var textWidget = dijit.byId("q26");
+							doh.is('', textWidget.get('value'),'initial value is empty');
+							doh.is('placeholder is here', textWidget._phspan.innerHTML, '_phspan.innerHTML');
+							textWidget.set('value','abc');
+							doh.is('abc', textWidget.get('value'));
+							textWidget.set('placeHolder','new placholder');
+							doh.is('abc', textWidget.get('value'));
+							textWidget.set('value','');
+							doh.is('new placholder', textWidget._phspan.innerHTML, '_phspan.innerHTML 1');
+							doh.is('', textWidget.get('value'));
+						}
+					},
+					{
+						name: "focus/blur textbox",
+						timeout: 6000,
+						runTest: function(){
+							var d = new doh.Deferred(), textWidget = dijit.byId("q26");
+							textWidget.set('placeHolder','placeholder is here');
+							textWidget.set('value','');
+							
+							//  Clicking into the input should hide _phspan
+							doh.robot.mouseMoveAt(textWidget.focusNode, 500, 500);
+							doh.robot.mouseClick({left: true}, 500);
+							
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("", textWidget.get('value'), "get('value')");
+								doh.is("none", textWidget._phspan.style.display, "_phspan.style.display");
+								
+								doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is("", textWidget.get('value'), "get('value')");
+									doh.isNot("none", textWidget._phspan.style.display, "_phspan.style.display 1");
+								}), 1000);
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "type in textbox",
+						timeout: 6000,
+						runTest: function(){
+							var d = new doh.Deferred(), textWidget = dijit.byId("q26");
+							textWidget.set('placeHolder','placeholder is here');
+							textWidget.set('value','');
+							
+							//  Clicking into the input should hide _phspan
+							doh.robot.mouseMoveAt(textWidget.focusNode, 500, 500);
+							doh.robot.mouseClick({left: true}, 500);
+							
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("", textWidget.get('value'), "get('value')");
+								doh.is("none", textWidget._phspan.style.display, "_phspan.style.display 1");
+								
+								doh.robot.typeKeys('new', 0, 600);
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is("new", textWidget.get('value'), "get('value')");
+									doh.is("none", textWidget._phspan.style.display, "_phspan.style.display 2");
+								}), 500);
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "reset textbox",
+						timeout: 6000,
+						runTest: function(){
+							var textWidget = dijit.byId("q26"), d = new doh.Deferred();
+							textWidget.focus();
+							textWidget.set('placeHolder','placeholder is here');
+							textWidget.set('value','');
+							
+							doh.is("", textWidget.get('value'), "get('value') 1");
+							doh.is("none", textWidget._phspan.style.display, "_phspan.style.display");
+							
+							textWidget.set('value','abc');
+							textWidget.reset();
+							
+							doh.is("", textWidget.get('value'), "get('value') 2");
+							doh.is("none", textWidget._phspan.style.display, "_phspan.style.display 1");
+							
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(function(){
+								textWidget.set('value','xyz');
+								textWidget.reset();
+							}, 1000, 1000);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("", textWidget.get('value'), "get('value')");
+								doh.isNot("none", textWidget._phspan.style.display, "_phspan.style.display 2");
+							}), 500);
+							
+							return d;
+						}
+					},
+					{
+						name: "set textbox value",
+						runTest: function(){
+							var textWidget = dijit.byId("q26");
+							textWidget.set('placeHolder','placeholder is here');
+							textWidget.set('value','value');
+							doh.is("none", textWidget._phspan.style.display, "_phspan.style.display");
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/form/robot/validationMessages.html b/dijit/tests/form/robot/validationMessages.html
new file mode 100644
index 0000000..65c7035
--- /dev/null
+++ b/dijit/tests/form/robot/validationMessages.html
@@ -0,0 +1,470 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>Validation Message Test</title>
+
+		<style>
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../css/dijitTests.css";
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+		<link id="themeStyles" rel="stylesheet" href="../../../themes/tundra/tundra.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.form.NumberTextBox");
+			dojo.require("dijit.robot");
+
+			dojo.addOnLoad(function(){
+
+			dojo.forEach([false, true], function(rangeBound){
+				dojo.forEach([false, true], function(required){
+					dojo.forEach(["", "p"], function(promptMessage){
+						dojo.forEach(["", "i"], function(invalidMessage){
+							dojo.forEach(["", "m"], function(missingMessage){
+								var name = "t" + (rangeBound?1:0) + (required?1:0) + (promptMessage?1:0) + (invalidMessage?1:0) + (missingMessage?1:0);
+								var textbox = dijit.byId(name);
+								doh.register(name, [
+								{
+									name: name + " first focus, empty value",
+									timeout: 5000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.mouseMoveAt(textbox.focusNode, 0, 1000);
+										doh.robot.mouseClick({left: true}, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!required, textbox.isValid(false), "isValid");
+											doh.is("", textbox.state, "state");
+											doh.is(promptMessage, textbox._message, "tooltip");
+										}), 1000);
+
+										return d;
+									}
+								},
+								{
+									name: name + " first valid character",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.typeKeys("1", 200, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!rangeBound, textbox.isValid(false), "isValid");
+											doh.is("", textbox.state, "state");
+											doh.is(promptMessage, textbox._message, "tooltip");
+										}), 200);
+
+										return d;
+									}
+								},
+								{
+									name: name + " second valid character",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.typeKeys("2", 200, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(true, textbox.isValid(false), "isValid");
+											doh.is("", textbox.state, "state");
+											doh.is(promptMessage, textbox._message, "tooltip");
+										}), 200);
+
+										return d;
+									}
+								},
+								{
+									name: name + " first invalid character",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.typeKeys("a", 200, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(false, textbox.isValid(false), "isValid");
+											doh.is("Error", textbox.state, "state");
+											doh.is(invalidMessage||promptMessage, textbox._message, "tooltip");
+										}), 200);
+
+										return d;
+									}
+								},
+								{
+									name: name + " delete invalid character",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.keyPress(dojo.keys.BACKSPACE, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(true, textbox.isValid(false), "isValid");
+											doh.is("", textbox.state, "state");
+											doh.is(promptMessage, textbox._message, "tooltip");
+										}), 200);
+
+										return d;
+									}
+								},
+								{
+									name: name + " delete last valid character",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.keyPress(dojo.keys.BACKSPACE, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!rangeBound, textbox.isValid(false), "isValid");
+											doh.is("", textbox.state, "state");
+											doh.is(promptMessage, textbox._message, "tooltip");
+										}), 200);
+
+										return d;
+									}
+								},
+								{
+									name: name + " delete first valid character",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.keyPress(dojo.keys.BACKSPACE, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!required, textbox.isValid(false), "isValid");
+											doh.is("", textbox.state, "state");
+											doh.is(promptMessage, textbox._message, "tooltip");
+										}), 200);
+
+										return d;
+									}
+								},
+								{
+									name: name + " tab from empty",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.keyPress(dojo.keys.TAB, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!required, textbox.isValid(false), "isValid");
+											doh.is(!required, !textbox.state, "state");
+											doh.is("", textbox._message, "tooltip");
+										}), 500);
+
+										return d;
+									}
+								},
+								{
+									name: name + " tab back to empty",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.keyPress(dojo.keys.TAB, 200, { shift:true });
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!required, textbox.isValid(false), "isValid");
+											doh.is(!required, !textbox.state, "state");
+											doh.is(required? (missingMessage||invalidMessage||promptMessage) : promptMessage, textbox._message, "tooltip");
+										}), 500);
+
+										return d;
+									}
+								},
+								{
+									name: name + " first valid character after refocus",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.typeKeys("1", 200, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!rangeBound, textbox.isValid(false), "isValid");
+											doh.is("", textbox.state, "state");
+											doh.is(promptMessage, textbox._message, "tooltip");
+										}), 200);
+
+										return d;
+									}
+								},
+								{
+									name: name + " out of range after refocus",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.typeKeys("2", 200, 200);
+										doh.robot.typeKeys("3", 200, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!rangeBound, textbox.isValid(false), "isValid");
+											doh.is(!rangeBound, !textbox.state, "state");
+											doh.is(rangeBound? textbox.rangeMessage : promptMessage, textbox._message, "tooltip");
+										}), 200);
+
+										return d;
+									}
+								},
+								{
+									name: name + " tab from out of range",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.keyPress(dojo.keys.TAB, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!rangeBound, textbox.isValid(false), "isValid");
+											doh.is(!rangeBound, !textbox.state, "state");
+											doh.is("", textbox._message, "tooltip");
+										}), 500);
+
+										return d;
+									}
+								},
+								{
+									name: name + " tab back to out of range",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.keyPress(dojo.keys.TAB, 200, { shift:true });
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!rangeBound, textbox.isValid(false), "isValid");
+											doh.is(!rangeBound, !textbox.state, "state");
+											doh.is(rangeBound? textbox.rangeMessage : promptMessage, textbox._message, "tooltip");
+										}), 500);
+
+										return d;
+									}
+								},
+								{
+									name: name + " delete out of range character",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										if(dojo.isMac){
+											doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 200, {meta:true});
+										}else{
+											doh.robot.keyPress(dojo.keys.END, 200);
+										}
+										doh.robot.keyPress(dojo.keys.BACKSPACE, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(true, textbox.isValid(false), "isValid");
+											doh.is("", textbox.state, "state");
+											doh.is(promptMessage, textbox._message, "tooltip");
+										}), 200);
+
+										return d;
+									}
+								},
+								{
+									name: name + " delete remaining characters",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.keyPress(dojo.keys.BACKSPACE, 200);
+										doh.robot.keyPress(dojo.keys.BACKSPACE, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!required, textbox.isValid(false), "isValid");
+											doh.is("", textbox.state, "state");
+											doh.is(promptMessage, textbox._message, "tooltip");
+										}), 200);
+
+										return d;
+									}
+								},
+								{
+									name: name + " tab from empty 2",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.keyPress(dojo.keys.TAB, 200);
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!required, textbox.isValid(false), "isValid");
+											doh.is(!required, !textbox.state, "state");
+											doh.is("", textbox._message, "tooltip");
+										}), 500);
+
+										return d;
+									}
+								},
+								{
+									name: name + " tab back to empty 2",
+									timeout: 2000,
+									runTest: function(){
+										var d = new doh.Deferred();
+
+										doh.robot.keyPress(dojo.keys.TAB, 200, { shift:true });
+
+										doh.robot.sequence(d.getTestCallback(function(){
+											doh.is(!required, textbox.isValid(false), "isValid");
+											doh.is(!required, !textbox.state, "state");
+											doh.is(required? (missingMessage||invalidMessage||promptMessage) : promptMessage, textbox._message, "tooltip");
+										}), 500, 1000);
+
+										return d;
+									}
+								}]);
+							});
+						});
+					});
+				});
+			});
+
+			doh.run();
+			});
+		</script>
+	</head>
+	<body class="claro">
+		<label for="t00000">not required, no min/max, no prompt message, no invalid message, no missing message</label><br>
+		<input  id="t00000" dojoType="dijit.form.NumberTextBox" required="false" promptMessage="" invalidMessage="" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t00000"><br>
+
+		<label for="t00001">not required, no min/max, no prompt message, no invalid message, missing message</label><br>
+		<input  id="t00001" dojoType="dijit.form.NumberTextBox" required="false" promptMessage="" invalidMessage="" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t00001"><br>
+
+		<label for="t00010">not required, no min/max, no prompt message, invalid message, no missing message</label><br>
+		<input  id="t00010" dojoType="dijit.form.NumberTextBox" required="false" promptMessage="" invalidMessage="i" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t00010"><br>
+
+		<label for="t00011">not required, no min/max, no prompt message, invalid message, missing message</label><br>
+		<input  id="t00011" dojoType="dijit.form.NumberTextBox" required="false" promptMessage="" invalidMessage="i" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t00011"><br>
+
+		<label for="t00100">not required, no min/max, prompt message, no invalid message, no missing message</label><br>
+		<input  id="t00100" dojoType="dijit.form.NumberTextBox" required="false" promptMessage="p" invalidMessage="" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t00100"><br>
+
+		<label for="t00101">not required, no min/max, prompt message, no invalid message, missing message</label><br>
+		<input  id="t00101" dojoType="dijit.form.NumberTextBox" required="false" promptMessage="p" invalidMessage="" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t00101"><br>
+
+		<label for="t00110">not required, no min/max, prompt message, invalid message, no missing message</label><br>
+		<input  id="t00110" dojoType="dijit.form.NumberTextBox" required="false" promptMessage="p" invalidMessage="i" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t00110"><br>
+
+		<label for="t00111">not required, no min/max, prompt message, invalid message, missing message</label><br>
+		<input  id="t00111" dojoType="dijit.form.NumberTextBox" required="false" promptMessage="p" invalidMessage="i" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t00111"><br>
+
+		<label for="t01000">required, no min/max, no prompt message, no invalid message, no missing message</label><br>
+		<input  id="t01000" dojoType="dijit.form.NumberTextBox" required="true" promptMessage="" invalidMessage="" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t01000"><br>
+
+		<label for="t01001">required, no min/max, no prompt message, no invalid message, missing message</label><br>
+		<input  id="t01001" dojoType="dijit.form.NumberTextBox" required="true" promptMessage="" invalidMessage="" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t01001"><br>
+
+		<label for="t01010">required, no min/max, no prompt message, invalid message, no missing message</label><br>
+		<input  id="t01010" dojoType="dijit.form.NumberTextBox" required="true" promptMessage="" invalidMessage="i" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t01010"><br>
+
+		<label for="t01011">required, no min/max, no prompt message, invalid message, missing message</label><br>
+		<input  id="t01011" dojoType="dijit.form.NumberTextBox" required="true" promptMessage="" invalidMessage="i" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t01011"><br>
+
+		<label for="t01100">required, no min/max, prompt message, no invalid message, no missing message</label><br>
+		<input  id="t01100" dojoType="dijit.form.NumberTextBox" required="true" promptMessage="p" invalidMessage="" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t01100"><br>
+
+		<label for="t01101">required, no min/max, prompt message, no invalid message, missing message</label><br>
+		<input  id="t01101" dojoType="dijit.form.NumberTextBox" required="true" promptMessage="p" invalidMessage="" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t01101"><br>
+
+		<label for="t01110">required, no min/max, prompt message, invalid message, no missing message</label><br>
+		<input  id="t01110" dojoType="dijit.form.NumberTextBox" required="true" promptMessage="p" invalidMessage="i" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t01110"><br>
+
+		<label for="t01111">required, no min/max, prompt message, invalid message, missing message</label><br>
+		<input  id="t01111" dojoType="dijit.form.NumberTextBox" required="true" promptMessage="p" invalidMessage="i" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t01111"><br>
+
+		<label for="t10000">not required, min=10, max=100, no prompt message, no invalid message, no missing message</label><br>
+		<input  id="t10000" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="false" promptMessage="" invalidMessage="" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t10000"><br>
+
+		<label for="t10001">not required, min=10, max=100, no prompt message, no invalid message, missing message</label><br>
+		<input  id="t10001" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="false" promptMessage="" invalidMessage="" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t10001"><br>
+
+		<label for="t10010">not required, min=10, max=100, no prompt message, invalid message, no missing message</label><br>
+		<input  id="t10010" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="false" promptMessage="" invalidMessage="i" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t10010"><br>
+
+		<label for="t10011">not required, min=10, max=100, no prompt message, invalid message, missing message</label><br>
+		<input  id="t10011" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="false" promptMessage="" invalidMessage="i" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t10011"><br>
+
+		<label for="t10100">not required, min=10, max=100, prompt message, no invalid message, no missing message</label><br>
+		<input  id="t10100" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="false" promptMessage="p" invalidMessage="" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t10100"><br>
+
+		<label for="t10101">not required, min=10, max=100, prompt message, no invalid message, missing message</label><br>
+		<input  id="t10101" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="false" promptMessage="p" invalidMessage="" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t10101"><br>
+
+		<label for="t10110">not required, min=10, max=100, prompt message, invalid message, no missing message</label><br>
+		<input  id="t10110" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="false" promptMessage="p" invalidMessage="i" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t10110"><br>
+
+		<label for="t10111">not required, min=10, max=100, prompt message, invalid message, missing message</label><br>
+		<input  id="t10111" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="false" promptMessage="p" invalidMessage="i" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t10111"><br>
+
+		<label for="t11000">required, min=10, max=100, no prompt message, no invalid message, no missing message</label><br>
+		<input  id="t11000" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="true" promptMessage="" invalidMessage="" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t11000"><br>
+
+		<label for="t11001">required, min=10, max=100, no prompt message, no invalid message, missing message</label><br>
+		<input  id="t11001" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="true" promptMessage="" invalidMessage="" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t11001"><br>
+
+		<label for="t11010">required, min=10, max=100, no prompt message, invalid message, no missing message</label><br>
+		<input  id="t11010" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="true" promptMessage="" invalidMessage="i" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t11010"><br>
+
+		<label for="t11011">required, min=10, max=100, no prompt message, invalid message, missing message</label><br>
+		<input  id="t11011" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="true" promptMessage="" invalidMessage="i" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t11011"><br>
+
+		<label for="t11100">required, min=10, max=100, prompt message, no invalid message, no missing message</label><br>
+		<input  id="t11100" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="true" promptMessage="p" invalidMessage="" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t11100"><br>
+
+		<label for="t11101">required, min=10, max=100, prompt message, no invalid message, missing message</label><br>
+		<input  id="t11101" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="true" promptMessage="p" invalidMessage="" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t11101"><br>
+
+		<label for="t11110">required, min=10, max=100, prompt message, invalid message, no missing message</label><br>
+		<input  id="t11110" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="true" promptMessage="p" invalidMessage="i" missingMessage="" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t11110"><br>
+
+		<label for="t11111">required, min=10, max=100, prompt message, invalid message, missing message</label><br>
+		<input  id="t11111" dojoType="dijit.form.NumberTextBox" constraints="{min:10, max:100}" required="true" promptMessage="p" invalidMessage="i" missingMessage="m" rangeMessage="r" value="">
+		<input style="border:0px;" size="6" value="t11111"><br>
+
+	</body>
+</html>
diff --git a/dijit/tests/form/runTests.html b/dijit/tests/form/runTests.html
new file mode 100644
index 0000000..71677dd
--- /dev/null
+++ b/dijit/tests/form/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+	<head>
+	<title>Dijit Unit Test Runner</title>
+	<meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dijit.tests.form.module"></HEAD>
+	<BODY>
+		Redirecting to D.O.H runner.
+	</BODY>
+</HTML>
diff --git a/dijit/tests/form/test_Button.html b/dijit/tests/form/test_Button.html
new file mode 100644
index 0000000..151dcfb
--- /dev/null
+++ b/dijit/tests/form/test_Button.html
@@ -0,0 +1,451 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Dojo Button Widget Test</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+
+			/* group multiple buttons in a row */
+			.box {
+				display: block;
+				text-align: center;
+			}
+			.box .dijit {
+				margin-right: 10px;
+			}
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.ColorPalette");
+			dojo.require("dijit.Menu");
+			dojo.require("dijit.Tooltip");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.form.Form");
+			dojo.require("dijit.form.TextBox");
+			dojo.require("dojo.parser");
+		</script>
+	</head>
+<body class="claro">
+	<h1 class="testTitle">Dijit Button Test</h1>
+	<h2>Simple, drop down & combo buttons</h2>
+	<p>
+	Buttons can do an action, display a menu, or both:
+	</p>
+	<p class="box">
+		<button id="button" onclick="console.log('clicked native button');"><button></button>
+		<input id="input" type="button" value="<input type='button'>" onclick="console.log('clicked native input button');">
+		<button id="1465" dojoType="dijit.form.Button" onClick='console.log("clicked simple");' iconClass="plusIcon" value="Create">
+			Create
+		</button>
+		<span dojoType="dijit.Tooltip" connectId="1465">tooltip on button</span>
+		<button id="1467" dojoType="dijit.form.Button" title="view title" onClick='console.log("clicked simple")'>
+			View
+		</button>
+		<span dojoType="dijit.Tooltip" connectId="1466">tooltip on button</span>
+		<button dojoType="dijit.form.ComboButton" id="comboCreate" optionsTitle='save options' onClick='console.log("clicked combo save")'
+				iconClass="plusIcon" title="creative title">
+			<span>Create</span>
+			<div dojoType="dijit.Menu" id="createMenu" style="display: none;">
+				<div dojoType="dijit.MenuItem"  iconClass="dijitEditorIcon dijitEditorIconSave"
+					onClick="console.log('not actually saving anything, just a test!')">Create blank</div>
+				<div dojoType="dijit.MenuItem"
+					onClick="console.log('not actually saving anything, just a test!')">Create from template</div>
+			</div>
+		</button>
+		<button dojoType="dijit.form.DropDownButton" id="edit" iconClass="noteIcon" title="edit title" value="Edit">
+			<span>Edit<b>!</b></span>
+			<div dojoType="dijit.Menu" id="editMenu">
+				<div dojoType="dijit.MenuItem" id="cut" iconClass="dijitEditorIcon dijitEditorIconCut"
+					onClick="console.log('not actually cutting anything, just a test!')">Cut</div>
+				<div dojoType="dijit.MenuItem" id="copy" iconClass="dijitEditorIcon dijitEditorIconCopy"
+					onClick="console.log('not actually copying anything, just a test!')">Copy</div>
+				<div dojoType="dijit.MenuItem" id="paste" iconClass="dijitEditorIcon dijitEditorIconPaste"
+					onClick="console.log('not actually pasting anything, just a test!')">Paste</div>
+				<div dojoType="dijit.MenuSeparator"></div>
+				<div dojoType="dijit.PopupMenuItem">
+					<span>Submenu</span>
+					<div dojoType="dijit.Menu" id="submenu2">
+						<div dojoType="dijit.MenuItem" onClick="console.log('Submenu 1!')">Submenu Item One</div>
+						<div dojoType="dijit.MenuItem" onClick="console.log('Submenu 2!')">Submenu Item Two</div>
+						<div dojoType="dijit.PopupMenuItem">
+							<span>Deeper Submenu</span>
+							<div dojoType="dijit.Menu" id="submenu4">
+								<div dojoType="dijit.MenuItem" onClick="console.log('Sub-submenu 1!')">Sub-sub-menu Item One</div>
+								<div dojoType="dijit.MenuItem" onClick="console.log('Sub-submenu 2!')">Sub-sub-menu Item Two</div>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+		</button>
+		<button dojoType="dijit.form.DropDownButton" id="color" iconClass="noteIcon" value="color">
+			<span>Color</span>
+			<div dojoType="dijit.ColorPalette" id="colorPalette" style="display: none" palette="3x4"
+				onChange="console.log(this.value);"></div>
+		</button>
+		<button dojoType="dijit.form.ComboButton" id="save" optionsTitle='save options' onClick='console.log("clicked combo save")'
+				iconClass="plusBlockIcon">
+			<span>Save</span>
+			<div dojoType="dijit.Menu" id="saveMenu" style="display: none;">
+				<div dojoType="dijit.MenuItem" id="saveMenuItem" iconClass="dijitEditorIcon dijitEditorIconSave"
+					onClick="console.log('not actually saving anything, just a test!')">Save</div>
+				<div dojoType="dijit.MenuItem" id="saveAs"
+					onClick="console.log('not actually saving anything, just a test!')">Save As</div>
+			</div>
+		</button>
+		<button dojoType="dijit.form.Button" id="disabled" onClick='console.log("clicked simple")' disabled='true' iconClass="plusIcon">
+			Disabled
+		</button>
+	</p>
+	<br clear="all">
+	<h2>DropDownButtons with different drop down positions</h2>
+	<button dojoType="dijit.form.DropDownButton" id="dropdown_default" iconClass="noteIcon" value="color">
+		<span>Default (below)</span>
+		<div dojoType="dijit.ColorPalette" style="display: none" palette="3x4"
+			onChange="console.log(this.value);"></div>
+	</button>
+	<button dojoType="dijit.form.DropDownButton" id="dropdown_up" dropDownPosition="above" iconClass="noteIcon" value="color">
+		<span>Above</span>
+		<div dojoType="dijit.ColorPalette" style="display: none" palette="3x4"
+			onChange="console.log(this.value);"></div>
+	</button>
+	<button dojoType="dijit.form.DropDownButton" id="dropdown_before" dropDownPosition="before" iconClass="noteIcon" value="color">
+		<span>Before</span>
+		<div dojoType="dijit.ColorPalette" style="display: none" palette="3x4"
+			onChange="console.log(this.value);"></div>
+	</button>
+	<button dojoType="dijit.form.DropDownButton" id="dropdown_after" dropDownPosition="after" iconClass="noteIcon" value="color">
+		<span>After</span>
+		<div dojoType="dijit.ColorPalette" style="display: none" palette="3x4"
+			onChange="console.log(this.value);"></div>
+	</button>
+	<h2>ComboButtons with different drop down positions</h2>
+	<button dojoType="dijit.form.ComboButton" id="combo_default" optionsTitle='save options' onClick='console.log("clicked combo save")'
+			iconClass="plusBlockIcon">
+		<span>Default (below)</span>
+		<div dojoType="dijit.Menu" tyle="display: none;">
+			<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconSave"
+				onClick="console.log('not actually saving anything, just a test!')">Save</div>
+			<div dojoType="dijit.MenuItem"
+				onClick="console.log('not actually saving anything, just a test!')">Save As</div>
+		</div>
+	</button>
+	<button dojoType="dijit.form.ComboButton" id="combo_above" dropDownPosition="above" optionsTitle='save options' onClick='console.log("clicked combo save")'
+			iconClass="plusBlockIcon">
+		<span>Up</span>
+		<div dojoType="dijit.Menu" style="display: none;">
+			<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconSave"
+				onClick="console.log('not actually saving anything, just a test!')">Save</div>
+			<div dojoType="dijit.MenuItem"
+				onClick="console.log('not actually saving anything, just a test!')">Save As</div>
+		</div>
+	</button>
+	<button dojoType="dijit.form.ComboButton" id="combo_before" dropDownPosition="before" optionsTitle='save options' onClick='console.log("clicked combo save")'
+			iconClass="plusBlockIcon">
+		<span>Before</span>
+		<div dojoType="dijit.Menu" style="display: none;">
+			<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconSave"
+				onClick="console.log('not actually saving anything, just a test!')">Save</div>
+			<div dojoType="dijit.MenuItem"
+				onClick="console.log('not actually saving anything, just a test!')">Save As</div>
+		</div>
+	</button>
+	<button dojoType="dijit.form.ComboButton" id="combo_after" dropDownPosition="after" optionsTitle='save options' onClick='console.log("clicked combo save")'
+			iconClass="plusBlockIcon">
+		<span>After</span>
+		<div dojoType="dijit.Menu" style="display: none;">
+			<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconSave"
+				onClick="console.log('not actually saving anything, just a test!')">Save</div>
+			<div dojoType="dijit.MenuItem"
+				onClick="console.log('not actually saving anything, just a test!')">Save As</div>
+		</div>
+	</button>
+	<h2>Buttons with no text label</h2>
+	<p>Buttons have showLabel=false so text is not displayed.  If no title attribute supplied, Should have label as title attribute displayed on mouse over</p>
+	<div class="box">
+		<button id="1466" dojoType="dijit.form.Button" title="title attrib rather than label" onClick='console.log("clicked simple button with no text label")'
+		iconClass="plusIcon" showLabel="false">
+		<span><b>Rich</b><i> Text</i> Test!</span>
+		</button>
+				<div dojoType="dijit.form.DropDownButton" iconClass="noteIcon" showLabel="false" title="color title">
+			<span>Color</span>
+			<div dojoType="dijit.ColorPalette" id="colorPalette2" style="display: none" palette="3x4"
+				onChange="console.log(this.value);">
+			</div>
+	</div>
+	<div dojoType="dijit.form.ComboButton" optionsTitle='save options' title="save title" onClick='console.log("clicked combo save")'
+				iconClass="plusBlockIcon" showLabel="false">
+			<span>Save</span>
+			<div dojoType="dijit.Menu" id="saveMenu2" style="display: none;">
+				<div dojoType="dijit.MenuItem"  iconClass="dijitEditorIcon dijitEditorIconSave"
+					onClick="console.log('not actually saving anything, just a test!')">Save</div>
+				<div dojoType="dijit.MenuItem"
+					onClick="console.log('not actually saving anything, just a test!')">Save As</div>
+			</div>
+		</div>
+	</div>
+	<br clear="all">
+	<h2>Toggle buttons</h2>
+	<p>The button CSS as well as the icon CSS can change on toggle </p>
+	<div class="box">
+		<button dojoType="dijit.form.ToggleButton" id="toggle1" checked onChange="console.log('toggled button checked='+arguments[0]);this.set('label',arguments[0] ==
+		true ? 'toggle me off' : 'toggle me on');" iconClass="dijitCheckBoxIcon">
+			Toggle me off
+		</button>
+		<button dojoType="dijit.form.ToggleButton" id="toggle2" onChange="console.log('toggled button checked='+arguments[0]);" iconClass="dijitRadioIcon">
+			Toggle me
+		</button>
+	</div>
+	<br clear="all">
+	<h2>Sizing</h2>
+	<p>Short button, tall buttons, big buttons, small buttons...
+	These buttons size to their content (just like <button>).</p>
+	<div class="box">
+		<button dojoType="dijit.form.Button" onclick='console.log("big");' iconClass="flatScreenIcon">
+			<span style="font-size:xx-large">big</span>
+		</button>
+		<button id="smallButton1" dojoType="dijit.form.Button" onclick='console.log("small");'>
+			<img src="../images/arrowSmall.gif" width="15" height="5">
+			<span style="font-size:x-small">small</span>
+		</button>
+		<button dojoType="dijit.form.Button" onclick='console.log("long");'>
+			<img src="../images/tube.gif" width="150" height="16">
+			long
+		</button>
+		<button dojoType="dijit.form.Button" onclick='console.log("tall");' width2height="0.1">
+			<img src="../images/tubeTall.gif" height="75" width="35"><br>
+			<span style="font-size:medium">tall</span>
+		</button>
+		<div style="clear: both;"></div>
+	</div>
+	<br clear="all">
+	<h2>Customized buttons</h2>
+	<p>Dojo users can customize styles.  Here's an example:</p>
+	<style type="text/css">
+		.acmeButton .dijitButtonNode {
+			background: rgb(96,96,96) !important;
+			color: white !important;
+			padding: 10px !important;
+			font-size: x-large !important;
+			padding-top: 10px !important;
+			padding-bottom: 10px !important;
+			border: 2px inset rgb(96,96,96);
+		}
+		.acmeButtonHover .dijitButtonNode {
+			background-color: rgb(89,94,111) !important;
+			color: cyan !important;
+		}
+		.acmeButtonFocused .dijitButtonNode {
+			border: yellow inset 2px;
+		}
+		.acmeButtonActive .dijitButtonNode {
+			background-color: white !important;
+			color: black !important;
+			border: 2px solid black !important;
+		}
+	</style>
+	<div class="box">
+		<button baseClass="acmeButton" dojoType="dijit.form.Button" onclick='console.log("short");'>
+			short
+		</button>
+		<button baseClass="acmeButton" dojoType="dijit.form.Button" onclick='console.log("longer");'>
+			bit longer
+		</button>
+		<button baseClass="acmeButton" dojoType="dijit.form.Button" onclick='console.log("longer yet");'>
+			ridiculously long
+		</button>
+		<div style="clear: both;"></div>
+	</div>
+		<h2>Toggling the display test</h2>
+	<p>
+	(Ticket <a href="http://trac.dojotoolkit.org/ticket/403">#403</a>)
+	</p>
+	<div class="box">
+		<button dojoType="dijit.form.Button" onclick='dojo.byId("hiddenNode").style.display="inline";'>
+			Show Hidden Buttons
+		</button>
+	</div>
+	<div class="box" style="display:none;" id="hiddenNode">
+		<button dojoType="dijit.form.Button" onclick='console.log("clicked simple")' iconClass="plusIcon">
+			Create
+		</button>
+		<button dojoType="dijit.form.Button" onclick='console.log("clicked simple")' iconClass="plusIcon">
+			Create
+		</button>
+	</div>
+	<div style="clear: both;"></div>
+	<h2>Programatically changing buttons</h2>
+	<p>clicking the buttons below will change the buttons above</p>
+	<script type="text/javascript">
+		// FIXME: doesn't the manager have a function for filtering by type?
+		function forEachButton(func){
+			dijit.registry.filter(function(widget){ return widget instanceof dijit.form.Button; }).forEach(func);
+		}
+		var disabled = false;
+		function toggleDisabled(){
+			disabled =! disabled;
+			forEachButton(function(widget){ widget.set('disabled',disabled); });
+			dojo.byId("toggle").innerHTML= disabled ? "Enable all" : "Disable all";
+		}
+		var labels=["<img src='../images/note.gif' width='20' height='20'>All", "<i>work</i>", "and no", "<span style='font-size: 40pt;'>play</span>",
+					 "<span style='color: red'>makes</span>", "Jack", "<span style='font-size: 20pt;'>a</a>", "dull",
+					 "<img src='../images/plus.gif' width='16' height='16'>boy"];
+		var idx = 0;
+		function changeLabels(){
+			forEachButton(function(widget){
+				widget.set('label', labels[idx++ % labels.length]);
+			});
+		}
+		function getLabels(){
+			forEachButton(function(widget){
+				console.log(widget.get('label'));
+			});
+		}
+	</script>
+	<div>
+		<button id="toggle" onclick='toggleDisabled()'>Disable all</button>
+		<button id="changeLabels" onclick='changeLabels()'>Change labels</button>
+		<button onclick='getLabels()'>Get labels</button>
+		<button onclick='location.reload()'>Revert</button>
+	</div>
+	<h3>Button instantiated via javacript:</h3>
+	<p id="buttonContainer" style="display: none;"></p>
+	<script type="text/javascript">
+		// See if we can make a button in script and attach it to the DOM ourselves.
+		dojo.addOnLoad(function(){
+			var widget = new dijit.form.Button({
+				label: "hello!",
+				name: "programmatic"
+			});
+			widget.placeAt("buttonContainer");	// place in page
+
+			var widget2 = new dijit.form.Button({
+				label: "hello!",
+				name: "programmatic"
+			});
+			widget2.set("label", "i'm programmatic too");	// change label (for testing)
+			widget2.placeAt("buttonContainer");	// place in page
+		});
+	</script>
+    <h3>DropDownButton instantiated via javacript:</h3>
+	<div id="dropdownButtonContainer"></div>
+	<script type="text/javascript">
+	    // See if we can make a drop down button in script and attach it to the DOM ourselves.
+        function createButton(){
+            var menu = new dijit.Menu({ });
+            menu.domNode.style.display="none";
+            var menuItem1 = new dijit.MenuItem({
+                label: "Save",
+                iconClass:"dijitEditorIcon dijitEditorIconSave",
+                onClick: function(){ alert('save'); }
+            });
+            menu.addChild(menuItem1);
+
+            var menuItem2 = new dijit.MenuItem({
+                label: "Cut",
+                iconClass:"dijitEditorIcon dijitEditorIconCut",
+                onClick: function(){ alert('cut'); }
+            });
+            menu.addChild(menuItem2);
+
+            var params = {
+                label: "hello!",
+                name: "programmatic2",
+                dropDown: menu,
+                id: "progButton"
+            };
+            var widget = new dijit.form.DropDownButton(params);
+            dojo.byId("dropdownButtonContainer").appendChild(widget.domNode);
+            dojo.byId("createButton").disabled = true;
+            dojo.byId("destroyButton").disabled = false;
+	    }
+        function destroyButton(){
+            var button = dijit.byId("progButton");
+            button.destroyRecursive();
+            dojo.byId("createButton").disabled = false;
+            dojo.byId("destroyButton").disabled = true;
+        }
+    </script>
+    <button id="createButton" onclick="createButton();">create dropdown button</button>
+    <button id="destroyButton" onclick="destroyButton();">destroy dropdown button</button>
+
+	<h3>Submit and Reset Buttons</h3>
+	<div>Testing that submit and reset buttons work properly.  OnSubmit and OnReset handlers
+		for the form just output to the console.
+	</div>
+	<form dojoType="dijit.form.Form" id="testForm" name="testForm"
+		encType="multipart/form-data" action="../formAction.html" method="" >
+		<script type="dojo/method" event="onReset">
+			console.log("testForm onReset invoked");
+		</script>
+		<script type="dojo/method" event="onSubmit">
+			console.log("testForm onSubmit invoked - not really submitting");
+			return false;
+		</script>
+		<label for="testName">Name: </label><input dojoType="dijit.form.TextBox" id="testName" name="testName" value=""><br>
+		<button dojoType="dijit.form.Button" type="submit" id="bSubmit">Submit</button>  
+		<button dojoType="dijit.form.Button" type="reset" id="bReset">Reset</button>
+	</form>
+
+	<h3>onClick Tests</h3>
+	<div>Testing that onClick works properly
+	</div>
+	<form>
+		<label for="onClickName">Value: </label><input id="onClickName" name="onClickName" value="RESET"><br>
+		<button dojoType="dijit.form.Button" type="reset" id="reset1">Reset with no onClick handler should reset</button>
+		<button type="reset" id="reset1N">Native Reset with no onClick handler should reset</button><br>
+		<button dojoType="dijit.form.Button" type="reset" id="reset2" onClick="return false">Reset with "return false" onClick handler should not reset</button>
+		<button type="reset" id="reset2N" onClick="return false">Native Reset with "return false" onClick handler should not reset</button><br>
+		<button dojoType="dijit.form.Button" type="reset" id="reset3" onClick="return true">Reset with "return true" onClick handler should reset</button>
+		<button type="reset" id="reset3N" onClick="return true">Native Reset with "return true" onClick handler should reset</button><br>
+		<button dojoType="dijit.form.Button" type="reset" id="reset4" onClick="return">Reset with "return" onClick handler should reset</button>
+		<button type="reset" id="reset4N" onClick="return">Native Reset with "return" onClick handler should reset</button><br>
+		<button dojoType="dijit.form.Button" type="reset" id="reset5" onClick="">Reset with "" onClick handler should reset</button>
+		<button type="reset" id="reset5N" onClick="">Native Reset with "" onClick handler should reset</button><br>
+	</form>
+
+	<h3>Submit/value test</h3>
+	<script>
+		submittedValues = function(values){
+			for(var i in values){
+				document.getElementById('buttonName').value = i;
+				document.getElementById('buttonValue').value = values[i];
+			}
+		};
+	</script>
+	<form dojoType="dijit.form.Form" id="myForm"
+		encType="multipart/form-data" action="../formAction.html" method="" target="_formSubmitIframe">
+		<button id="Plain" name="Plain" type="submit" dojoType="dijit.form.Button" value="Plain Submit" label="Plain Submit"></button>
+		<button id="Combo" name="Combo" type="submit" dojoType="dijit.form.ComboButton" value="Combo Submit" label="Combo Submit">
+			<div dojoType="dijit.Menu" style="display:none;">
+				<div id="ComboMenuItem" dojoType="dijit.MenuItem" onclick="dijit.byId('myForm').submit()">Combo MenuItem Submit</div>
+			</div>
+		</button>
+		<button id="DropDown" name="DropDown" type="submit" dojoType="dijit.form.DropDownButton" value="DropDown Submit" label="DropDown Submit">
+			<div dojoType="dijit.Menu" style="display:none;">
+				<div id="DropDownMenuItem" dojoType="dijit.MenuItem" onclick="dijit.byId('myForm').submit()">DropDown MenuItem Submit</div>
+			</div>
+		</button>
+		<button id="Disabled" name="Disabled" type="submit" dojoType="dijit.form.Button" disabled value="Disabled Submit" label="Disabled Submit"></button>
+	</form>
+	<br>
+	<label for="buttonName">Submitted name:</label><input id="buttonName"><br>
+	<nobr style="width:100%;"><label for="buttonValue">Submitted value:</label><input id="buttonValue" style="width:100%;overflow:hidden;"></nobr>
+<iframe name="_formSubmitIframe" src="about:blank" onload="if(this.values)submittedValues(this.values)" style="display:none;"></iframe>
+
+</body>
+</html>
diff --git a/dijit/tests/form/test_CheckBox.html b/dijit/tests/form/test_CheckBox.html
new file mode 100644
index 0000000..f393126
--- /dev/null
+++ b/dijit/tests/form/test_CheckBox.html
@@ -0,0 +1,311 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>CheckBox Widget Demo</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+
+		label { margin-right: 0.80em; }
+	</style>
+
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner"); // optimize: load dijit layer
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.form.CheckBox");
+		dojo.require("dijit.form.RadioButton");
+		dojo.require("dijit.form.Form");
+
+		function defaultSubmitHandler(values){
+			console.debug('actual submitted values: ' + dojo.toJson(values));
+		}
+		submittedValues = defaultSubmitHandler;
+
+		function reportChecked(checked) {
+			dojo.byId("oncheckedoutput").innerHTML = checked;
+		}
+
+		function reportValueChanged(value) {
+			dojo.byId("onvaluechangedoutput").innerHTML = value;
+		}
+
+		// These are the values assigned to the widgets in the page's HTML
+		var originalGet = {
+			cb1: [],
+			cb2: ["on"],
+			cb4: ["on"],
+			cb5: [],
+			cb6: ["on"],
+			cb7: [],
+			'g[1]': "talk",
+			g2: null
+		};
+
+		var originalSubmit = {
+			cb2: "on",
+			cb4: "on",
+			cb6: "on",
+			'g[1]': "talk"
+		};
+
+		// attempt to change these values
+		var change = {
+			cb1: ["foo"],
+			cb2: [],
+			cb3: ["on"],
+			cb4: [],
+			cb5: ["on"],
+			cb6: ["foo"],
+			'g[1]': "weather",
+			g2: "country"
+		};
+
+		// changed values
+		var changedGet = {
+			cb1: ["foo"],
+			cb2: [],
+			cb4: [],
+			cb5: ["on"],
+			cb6: [],
+			cb7: [],
+			'g[1]': null,
+			g2: "country"
+		};
+
+		var changedSubmit = {
+			cb1: "foo",
+			cb5: "on",
+			g2: "country"
+		};
+
+		dojo.addOnLoad(function(){
+			var params = {id: "cb6", name: "cb6", checked: true };
+			var widget = new dijit.form.CheckBox(params, dojo.byId("checkboxContainer"));
+
+			// should be able to query for all of the inputs, including hidden ones
+			doh.register("query input by checked state", [
+				{
+					name: "query checked",
+					runTest: function(){
+						var queried=dojo.query("input[checked]", dojo.byId('myForm'));
+						doh.is(5,queried.length,"expected: 5 checked widgets, got: "+queried.length);
+					}
+				}
+			]);
+
+			doh.register("query input by name", [
+				{
+					name: "query name",
+					runTest: function(){
+						var queried=dojo.query("input[name]", dojo.byId('myForm'));
+						doh.is(13,queried.length,"expected: 13 named widgets, got: "+queried.length);
+					}
+				}
+			]);
+
+			var formWidget = dijit.byId("myForm");
+
+			var submitForm = function(name, testValues){
+				return {
+					name: name,
+					timeout: 5000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						submittedValues = function(formValues){
+							d.getTestCallback(function(){
+								for(var i in originalGet){ doh.is(testValues[i], formValues[i], i); }
+							})();
+						};
+						formWidget.submit();
+						return d;
+					},
+					tearDown: function(){
+						submittedValues = defaultSubmitHandler;
+					}
+				};
+			};
+
+			// delay produces a "test" which simply waits for ms milliseconds.
+			// this is necessary for IE, which gets confused by multiple quick submits.
+			var delay = function(ms){
+				return {
+					name: "delay for IE's sake",
+					timeout: 50000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						setTimeout(function(){
+							d.callback(true);
+						}, ms);
+						console.log("set timeout");
+						return d;
+					}
+				};
+			};
+
+			doh.register("CheckBox values",
+				[
+					function getValues(){
+						doh.is( dojo.toJson(originalGet), dojo.toJson(formWidget.get('value')) );
+					},
+					submitForm("original submit", originalSubmit),
+					delay(500),
+					function setValues(){
+						formWidget.set('value', change);
+						doh.is( dojo.toJson(changedGet), dojo.toJson(formWidget.get('value')) );
+					},
+					submitForm("changed submit", changedSubmit),
+					delay(500),
+					function resetValues(){
+						formWidget.reset();
+						doh.is( dojo.toJson(originalGet), dojo.toJson(formWidget.get('value')), "reset to original values" );
+					},
+					submitForm("reset submit", originalSubmit)
+				]
+			);
+
+			doh.register("CheckBox onChange",
+				[
+					function fireOnChange(){
+						var d = new doh.Deferred();
+						var cb = dijit.byId('cb2');
+						var lastOnChange = dojo.byId('oncheckedoutput').innerHTML;
+						cb.set('checked', !cb.get('checked'));
+						setTimeout(d.getTestCallback(function(){
+							doh.isNot(lastOnChange, dojo.byId('oncheckedoutput').innerHTML);
+						}), 0);
+						return d;
+					},
+
+					function skipOnChange(){
+						var d = new doh.Deferred();
+						var cb = dijit.byId('cb2');
+						var lastOnChange = dojo.byId('oncheckedoutput').innerHTML;
+						cb.set('checked', !cb.get('checked'), false);
+						setTimeout(d.getTestCallback(function(){
+							doh.is(lastOnChange, dojo.byId('oncheckedoutput').innerHTML);
+						}), 0);
+						return d;
+					}
+				]
+			);
+
+			doh.run();
+		});
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit CheckBox Test</h1>
+	<p>
+	Here are some checkboxes.  Try clicking, and hovering, tabbing, and using the space bar to select:
+	</p>
+	<!--    to test form submission, you'll need to create an action handler similar to
+		http://www.utexas.edu/teamweb/cgi-bin/generic.cgi -->
+	<form dojoType="dijit.form.Form" id="myForm"
+			action="../formAction.html" method="" target="_formSubmitIframe">
+		<input type="checkbox" id="cb0" checked/>
+			<label for="cb0">cb0: Vanilla (non-dojo) checkbox (for comparison purposes)</label>
+		<br>
+		<input name="cb1" id="cb1" jsid="cb1" value="foo" dojoType="dijit.form.CheckBox" onClick="console.log('clicked cb1')">
+			<label for="cb1">cb1: normal checkbox, with value=foo, clicking generates console log messages</label>
+			<button type=button onclick="alert(dijit.byId('cb1').get('value'));">get('value')</button>
+		<br>
+		<input onChange="reportChecked" name="cb2" id="cb2" dojoType="dijit.form.CheckBox" checked="checked"/>
+			<label for="cb2">cb2: normal checkbox, with default value, initially turned on.</label>
+			<span>"onChange" handler updates: [<span id="oncheckedoutput"></span>]</span>
+			<button type=button onclick="alert(dijit.byId('cb2').get('value'));">get('value')</button>
+		<br>
+		<input name="cb3" id="cb3" dojoType="dijit.form.CheckBox" disabled>
+			<label for="cb3">cb3: disabled checkbox</label>
+		<br>
+		<input name="cb4" id="cb4" dojoType="dijit.form.CheckBox" readOnly checked/>
+			<label for="cb4">cb4: readOnly checkbox, turned on</label>
+		<br>
+		<input name="cb5" id="cb5" type="checkbox" value="" dojoType="dijit.form.CheckBox" onClick="console.log('clicked cb5')">
+			<label for="cb5">cb5: normal checkbox, with specified value="", clicking generates console log messages</label>
+			<button type=button onclick="alert(dijit.byId('cb5').get('value'));">get('value')</button>
+		<br>
+		<div id="checkboxContainer"></div>
+			<label for="cb6">cb6: instantiated from script</label>
+		<br>
+		<input onChange="reportValueChanged" name="cb7" id="cb7" dojoType="dijit.form.CheckBox">
+			<label for="cb7">cb7: normal checkbox.</label>
+			<input type="button" onclick='dijit.byId("cb7").set("disabled",true);' value="disable" />
+			<input type="button" onclick='dijit.byId("cb7").set("disabled",false);' value="enable" />
+			<input type="button" onclick='dijit.byId("cb7").set("value", "fish");' value='set value to "fish"' />
+			<input type="button" onclick='dijit.byId("cb7").reset();' value='Reset value+checked' />
+			<span>"onChange" handler updates: [<span id="onvaluechangedoutput"></span>]</span>
+		<br>
+	<p>
+	Here are some radio buttons.  Try clicking, and hovering, tabbing, and arrowing
+	</p>
+		<p>
+			<span>Radio group #1:</span>
+			<input type="radio" name="g[1]" id="g1rb1" value="news" dojoType="dijit.form.RadioButton">
+			<label for="g1rb1">news</label>
+			<input type="radio" name="g[1]" id="g1rb2" value="talk" dojoType="dijit.form.RadioButton" checked="checked"/>
+			<label for="g1rb2">talk</label>
+			<input type="radio" name="g[1]" id="g1rb3" value="weather" dojoType="dijit.form.RadioButton" disabled="disabled"/>
+			<label for="g1rb3">weather</label>
+			<input type="button" onclick='dijit.byId("g1rb3").set("disabled",false);' value="enable weather" />
+			<input type="button" onclick='dijit.byId("g1rb3").set("disabled",true);' value="disable weather" />
+		</p>
+		<p>
+			<span>Radio group #2: (no default value, and has breaks)</span><br>
+			<input type="radio" name="g2" id="g2rb1" value="top40" dojoType="dijit.form.RadioButton"/>
+			<label for="g2rb1">top 40</label><br>
+			<input type="radio" name="g2" id="g2rb2" value="oldies" dojoType="dijit.form.RadioButton"/>
+			<label for="g2rb2">oldies</label><br>
+			<input type="radio" name="g2" id="g2rb3" value="country" dojoType="dijit.form.RadioButton"/>
+			<label for="g2rb3">country</label><br>
+			(Note if using keyboard: tab to navigate, and use arrow or space to select)
+		</p>
+		<button dojoType="dijit.form.Button" type="submit" value="Submit">Submit</button>
+		<button dojoType="dijit.form.Button" type="reset">HTML Reset</button>
+	</form>
+
+	<p>
+		<span>Radio group #3 (native radio buttons):</span>
+		<input type="radio" name="g3" id="g3rb1" value="rock"/>
+		<label for="g3rb1">rock</label>
+		<input type="radio" name="g3" id="g3rb2" value="jazz" disabled="disabled"/>
+		<label for="g3rb2">jazz</label>
+		<input type="radio" name="g3" id="g3rb3" value="classical" checked="checked"/>
+		<label for="g3rb3">classical</label>
+	</p>
+
+	<div style='border:1px solid gray;'>
+		These 6 radio buttons have the same name but are in separate forms so they can be selected independently.
+		<form>
+			1:
+			<input dojoType="dijit.form.RadioButton" type=radio name='a1' id='b1' value="1"/><label for='b1'>b1</label>
+			<input dojoType="dijit.form.RadioButton" type=radio name='a1' id='b2' value="2"/><label for='b2'>b2</label>
+		</form>
+		<form>
+			2:
+			<input dojoType="dijit.form.RadioButton" type=radio name='a1' id='c1' value="1"/><label for='c1'>c1</label>
+			<input dojoType="dijit.form.RadioButton" type=radio name='a1' id='c2' value="2"/><label for='c2'>c2</label>
+		</form>
+		<div>
+			3:
+			<input dojoType="dijit.form.RadioButton" type=radio name='a1' id='d1' value="1"/><label for='d1'>d1</label>
+			<input dojoType="dijit.form.RadioButton" type=radio name='a1' id='d2' value="2"/><label for='d2'>d2</label>
+		</div>
+	</div>
+
+<iframe name="_formSubmitIframe" src="about:blank" onload="if(this.values)submittedValues(this.values)" style="display:none;"></iframe>
+</body>
+</html>
diff --git a/dijit/tests/form/test_ComboBox.html b/dijit/tests/form/test_ComboBox.html
new file mode 100644
index 0000000..a0635ca
--- /dev/null
+++ b/dijit/tests/form/test_ComboBox.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+	<HEAD>
+		<TITLE>ComboBox Unit Test</TITLE>
+	</HEAD>
+	<BODY>
+		Loading ComboBox unit test.
+		<SCRIPT>
+			window.location.replace("_autoComplete.html?testWidget=dijit.form.ComboBox"+window.location.search.replace(/^\?/,"&"));
+		</SCRIPT>
+	</BODY>
+</HTML>
diff --git a/dijit/tests/form/test_ComboBox_destroy.html b/dijit/tests/form/test_ComboBox_destroy.html
new file mode 100644
index 0000000..b47e75f
--- /dev/null
+++ b/dijit/tests/form/test_ComboBox_destroy.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Dojo ComboBox Widget Destruction Issue</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.ComboBox");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+			dojo.addOnLoad(function(){
+				dojo.connect(dojo.byId("killit"), "onclick", function(){
+					dijit.byId("combo_01").destroy();
+				});
+			});
+		</script>
+	</head>
+	<body class="claro">
+
+		<h1 class="testTitle">Dojo ComboBox Widget Destruction Issue</h1>
+		<p>
+			<tt>ComboBox</tt> does not destroy itself properly, leading to a
+			JavaScript error.  Could it have something to do with not disconnecting
+			events?
+		</p>
+		<p></p>
+		Steps:
+		<ol>
+			<li>Pick a state from the combo box below.</li>
+			<li>Click the "killit" button, which calls <tt>destroy</tt> on the widget.</li>
+			<li>Observe the JavaScript error.</li>
+		</ol>
+		<p></p>
+		<form action="#" method="GET">
+		   <input type="button" id="killit" name="killit" value="killit" />
+			<select name="state" searchField="name" keyField="abbreviation"
+				id="combo_01" dojoType="dijit.form.ComboBox" style="width: 300px;"
+				name="foo.bar1" autoComplete="false">
+				<option value="AL">Alabama</option>
+
+				<option value="AK">Alaska</option>
+				<option value="AS">American Samoa</option>
+				<option value="AZ">Arizona</option>
+				<option value="AR">Arkansas</option>
+				<option value="AE">Armed Forces Europe</option>
+				<option value="AP">Armed Forces Pacific</option>
+			</select>
+		</form>
+	</body>
+</html>
diff --git a/dijit/tests/form/test_DateTextBox.html b/dijit/tests/form/test_DateTextBox.html
new file mode 100644
index 0000000..32ac67a
--- /dev/null
+++ b/dijit/tests/form/test_DateTextBox.html
@@ -0,0 +1,216 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Test DateTextBox Widget</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			.noticeMessage {
+				color:#093669;
+				font-size:0.95em;
+				margin-left:0.5em;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true, extraLocale: ['de-de', 'en-us']"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dijit.form.Form");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+			function eventHandler(e){
+				// use this.domNode.getAttribute('widgetId') to show "this" is the widget
+				// mouseleave/enter map to mouseout/over in all browsers except IE
+				console.log(this.domNode.getAttribute('widgetId') + ' ' + arguments[0].type);
+			}
+			dojo.addOnLoad(function(){
+				dijit.byId("localLong").parse = function(value,constraints){
+					return this.dateLocaleModule.parse(value, (constraints.formatLength="long") && constraints) ||
+						 this.dateLocaleModule.parse(value, (constraints.formatLength="short") && constraints) ||
+						(this._isEmpty(value) ? null : undefined);	 // Date
+				};
+			});
+		</script>
+	</head>
+
+	<body class="claro">
+
+		<h1 class="testTitle">Test DateTextBox Widget</h1>
+		<!--	to test form submission, you'll need to create an action handler similar to
+			http://www.utexas.edu/teamweb/cgi-bin/generic.cgi -->
+		<form id="form1" dojoType='dijit.form.Form' action="" name="example" method="" onSubmit="return this.validate()">
+			<div class="dojoTitlePaneLabel">
+				<label for="local"> Date (local format) </label>
+				<span class="noticeMessage">DateTextBox class, no attributes</span>
+			</div>
+			<div class="testExample">
+				<input id="local" name="noDOMvalue" value="2008-12-31" type="text" dojoType="dijit.form.DateTextBox"
+					onMouseEnter="eventHandler"
+					onMouseLeave="eventHandler"
+					onKeyDown="eventHandler"
+					onChange="dojo.byId('oc1').value=''+arguments[0]"
+				>
+				onChange:<input id="oc1" size="34" disabled value="not fired yet!" autocomplete="off">
+				<nobr>
+				<button type="button" onclick="dijit.byId('local').set('value', null);">set('value',null)</button>
+				<button type="button" onclick="dojo.byId('gv1').value=''+dijit.byId('local').get('value');">get('value')</button>
+				<button type="button" onclick="dojo.byId('gv1').value=''+dijit.byId('local').value;">.value</button>
+				<input id="gv1" size="34" disabled value="not called yet!" autocomplete="off">
+				</nobr>
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<label for="localLong"> Date (local format - long) </label>
+				<span class="noticeMessage">DateTextBox class,
+					Attributes: required="true", trim="true", constraints={min:'2004-01-01',max:'2006-12-31',formatLength:'long'}. Works for leap years</span>
+			</div>
+			<div class="testExample">
+				<div id="localLong" jsid="localLong" type="text" name="date1" value="2005-12-30"
+					dojoType="dijit.form.DateTextBox"
+					constraints="{min:'2004-01-01',max:'2006-12-31',formatLength:'long'}"
+					required="true"
+					trim="true"
+					onChange="dojo.byId('oc2').value=arguments[0]"
+					invalidMessage="Invalid date." >
+					<script type="dojo/connect" event="onMouseEnter">eventHandler.apply(this, arguments)</script>
+					<script type="dojo/connect" event="onMouseLeave">eventHandler.apply(this, arguments)</script>
+					<script type="dojo/connect" event="onKeyDown">eventHandler.apply(this, arguments)</script>
+				</div>
+ 				onChange:<input id="oc2" size="34" disabled value="not fired yet!" autocomplete="off">
+				<input type="button" value="Destroy" onClick="dijit.byId('localLong').destroy(); return false;">
+				<input type="button" value="set max to 2007-12-31" onClick="dijit.byId('localLong').constraints.max = new Date(2007,11,31); dijit.byId('localLong').validate(false); return false;">
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<label for="american"> Date (American format) </label>
+				<span class="noticeMessage">DateTextBox class,
+					Attributes: lang="en-us", required="true", constraints={min:'2004-01-01',max:'2006-12-31'}. Works for leap years.
+					Prompt message whenever field is blank.
+				</span>
+			</div>
+			<div class="testExample">
+				<div id="american" type="text" name="date2" value="2005-12-30"
+					dojoType="dijit.form.DateTextBox"
+					constraints="{min:'2004-01-01',max:'2006-12-31'}"
+					lang="en-us"
+					required="true"
+					promptMessage="mm/dd/yyyy"
+					invalidMessage="Invalid date. Use mm/dd/yyyy format.">
+					<script type="dojo/method" event="onMouseEnter">eventHandler.call(this, arguments[0])</script>
+					<script type="dojo/method" event="onMouseLeave">eventHandler.call(this, arguments[0])</script>
+					<script type="dojo/method" event="onKeyDown">eventHandler.call(this, arguments[0])</script>
+				</div>
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<label for="german"> Date (German format)</label>
+				<span class="noticeMessage">DateTextBox class,
+					Attributes: lang="de-de", constraints={min:2004-01-01, max:2006-12-31}. Works for leap years.
+					Prompt message whenever field is blank.
+				</span>
+			</div>
+			<div class="testExample">
+				<input id="german"/>
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="pattern"> Date, overriding pattern</label>
+				<span class="noticeMessage">Date, overriding pattern with dd-MM-yyyy</span>
+			</div>
+			<div class="testExample">
+				<input id="pattern" name="noDOMvalue" type="text" dojoType="dijit.form.DateTextBox" constraints="{datePattern:'dd-MM-yyyy', strict:true}">
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<strong>Using title attrib for label</strong>
+				<span class="noticeMessage">DateTextBox class,
+					Attributes: lang="en-us", required="true", prompt meessage, invalid message
+					Prompt message whenever field is blank.
+				</span>
+			</div>
+			<div class="testExample">
+				<div id="american2" type="text" name="date20" value="2008-12-30"
+					dojoType="dijit.form.DateTextBox"
+					title="Date in month, day, year format"
+					lang="en-us"
+					required="true"
+					promptMessage="mm/dd/yyyy"
+					invalidMessage="Invalid date. Use mm/dd/yyyy format.">
+				</div>
+			</div>
+
+			<script>
+			// See if we can make a widget in script and attach it to the DOM ourselves.
+			dojo.addOnLoad(function(){
+				dojo.connect(dijit.byId('pattern'), "onMouseEnter", eventHandler);
+				dojo.connect(dijit.byId('pattern'), "onMouseLeave", eventHandler);
+				dojo.connect(dijit.byId('pattern'), "onKeyDown", eventHandler);
+
+				var props = {
+					name: "date4",
+					value: new Date(2006,10,29),
+					constraints: {min:new Date(2004,0,1),max:new Date(2006,11,31)},
+					lang: "de-de",
+					onMouseEnter: eventHandler,
+					onMouseLeave: eventHandler,
+					onKeyDown: eventHandler,
+					promptMessage: "dd.mm.yy",
+					rangeMessage: "Enter a date in the year range 2004-2006.",
+					invalidMessage: "Invalid date. Use dd.mm.yy format."
+				};
+				var w = new dijit.form.DateTextBox(props, "german");
+			});
+			</script>
+
+			<script>
+				function displayData() {
+					var f = document.getElementById("form1");
+					var s = "";
+					for (var i = 0; i < f.elements.length; i++) {
+						var elem = f.elements[i];
+						if (elem.name == "button")  { continue; }
+						s += elem.name + ": " + elem.value + "\n";
+					}
+					alert(s);
+				}
+			</script>
+
+			<div class="dojoTitlePaneLabel">
+				 Date pairs, from/to (won't submit unless from/to fields filled in correctly):
+			</div>
+			<div class="testExample">
+				<label for="fromDate">From:</label> <input id="fromDate" type="text" name="fromDate" dojoType="dijit.form.DateTextBox"
+					required="true"
+					onChange="dijit.byId('toDate').constraints.min = this.get('value');" />
+				<label for="toDate">To:</label> <input id="toDate" type="text" name="toDate" dojoType="dijit.form.DateTextBox"
+					required="true"
+					onChange="dijit.byId('fromDate').constraints.max = this.get('value');" />
+
+				<button type="button" name="button" onclick="displayData(); return false;">view data</button>
+				<input type="submit" name="submit" />
+				<input type="reset" name="reset" />
+			</div>
+		</form>
+	</body>
+</html>
diff --git a/dijit/tests/form/test_DateTextBox_iframe.html b/dijit/tests/form/test_DateTextBox_iframe.html
new file mode 100644
index 0000000..a09fbcf
--- /dev/null
+++ b/dijit/tests/form/test_DateTextBox_iframe.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<iframe src="test_DateTextBox.html" width="100%" height="100%" onclick="console.log('iframe click')">
+</body>
+</html>
\ No newline at end of file
diff --git a/dijit/tests/form/test_FilteringSelect.html b/dijit/tests/form/test_FilteringSelect.html
new file mode 100644
index 0000000..241de29
--- /dev/null
+++ b/dijit/tests/form/test_FilteringSelect.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+	<HEAD>
+		<TITLE>FilteringSelect Unit Test</TITLE>
+	</HEAD>
+	<BODY>
+		Loading FilteringSelect unit test.
+		<SCRIPT>
+			window.location.replace("_autoComplete.html?testWidget=dijit.form.FilteringSelect"+window.location.search.replace(/^\?/,"&"));
+		</SCRIPT>
+	</BODY>
+</HTML>
diff --git a/dijit/tests/form/test_Form_onsubmit.html b/dijit/tests/form/test_Form_onsubmit.html
new file mode 100644
index 0000000..57d3ffe
--- /dev/null
+++ b/dijit/tests/form/test_Form_onsubmit.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Form unit test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojo.date");
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.form.Form");
+		dojo.require("dijit.layout.LayoutContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.CheckBox");
+		dojo.require("dijit.form.DateTextBox");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.MultiSelect");
+		dojo.require("dijit.form.Textarea");
+		dojo.require("dijit.form.SimpleTextarea");
+		dojo.require("dijit.Editor");
+	</script>
+
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Form Widget Unit Test</h1>
+	<form dojoType="dijit.form.Form" id="myForm1"
+		encType="multipart/form-data" action="" method="GET"
+		onSubmit="dojo.stopEvent(arguments[0]);"
+		onReset="dojo.stopEvent(arguments[0]);">
+		<h3>This form shouldn't submit, nor reset</h3>
+		<select name="plop.combo" dojoType="dijit.form.ComboBox">
+			<option value="one">one</option>
+			<option value="two">two</option>
+			<option value="three">three</option>
+		</select>
+		<button dojoType=dijit.form.Button type="submit">Submit</button>
+		<button dojoType=dijit.form.Button type="reset">Reset</button>
+	</form>
+
+	<form dojoType="dijit.form.Form" id="myForm2"
+		encType="multipart/form-data" action="" method="GET"
+		onSubmit="return false;"
+		onReset="return false;">
+		<h3>This form shouldn't submit, nor reset</h3>
+		<select name="plop.combo" dojoType="dijit.form.ComboBox">
+			<option value="one">one</option>
+			<option value="two">two</option>
+			<option value="three">three</option>
+		</select>
+		<button dojoType=dijit.form.Button type="submit">Submit</button>
+		<button dojoType=dijit.form.Button type="reset">Reset</button>
+	</form>
+
+	<form dojoType="dijit.form.Form" id="myForm3"
+		encType="multipart/form-data" action="" method="GET"
+		onSubmit="return true;"
+		onReset="return true;">
+		<h3>This form <em>should</em> submit and reset</h3>
+		<select name="plop.combo" dojoType="dijit.form.ComboBox">
+			<option value="one">one</option>
+			<option value="two">two</option>
+			<option value="three">three</option>
+		</select>
+		<button dojoType=dijit.form.Button type="submit">Submit</button>
+		<button dojoType=dijit.form.Button type="reset">Reset</button>
+	</form>
+
+	<form dojoType="dijit.form.Form" id="myForm4"
+		encType="multipart/form-data" action="" method="GET"
+		onSubmit="void(0)"
+		onReset="void(0)">
+		<h3>This form <em>should</em> submit and reset</h3>
+		<select name="plop.combo" dojoType="dijit.form.ComboBox">
+			<option value="one">one</option>
+			<option value="two">two</option>
+			<option value="three">three</option>
+		</select>
+		<button dojoType=dijit.form.Button type="submit">Submit</button>
+		<button dojoType=dijit.form.Button type="reset">Reset</button>
+	</form>
+</body>
+</html>
diff --git a/dijit/tests/form/test_MultiSelect.html b/dijit/tests/form/test_MultiSelect.html
new file mode 100644
index 0000000..8771867
--- /dev/null
+++ b/dijit/tests/form/test_MultiSelect.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Testing MultiSelect form widget | The Dojo Toolkit</title>
+
+	<style type="text/css">
+	@import "../../../dijit/tests/css/dijitTests.css";
+	#select, #select2 {
+		width:255px;
+		height:300px;
+		overflow:auto;
+	}
+	div#sel1, div#sel2 {
+		float: left;
+	}
+	div#leftRightButtons {
+		float: left;
+		padding: 10em 0.5em 0 0.5em;
+	}
+	</style>
+
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		var globalVals = null;
+
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.form.MultiSelect");
+
+		// needed for tests:
+		dojo.require("dijit.form.Form");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.layout.SplitContainer");
+
+		dojo.addOnLoad(function(){
+
+			// ref a clonable node, then split it between two selects
+			var c = dojo.query(".clone")[0];
+			var l = -1;
+			opt = function(){
+				return dojo.byId((++l%2 == 0 ? "select":"select2" ));
+			}
+			// based on the the 'dijit' object
+			for(var i in dijit){
+				var n = opt().appendChild(dojo.clone(c));
+				n.value = n.innerHTML = i;
+			}
+
+			// turn any non-dojoType selects into widgets programatically:
+			dojo.query("select").forEach(function(n){
+				if(!dijit.byNode(n)){
+					var foo = new dijit.form.MultiSelect({ name: n.name }, n);
+				}
+			});
+
+			// listen to the "move items" buttons
+			dojo.query("button.switch")
+				.connect("onclick",function(e){
+					switch(e.target.id.toString()){
+						case "left" : dijit.byId("select").addSelected(dijit.byId("select2")); break;
+						case "right" : dijit.byId("select2").addSelected(dijit.byId("select")); break;
+					}
+			});
+
+			// listen to the invert buttons
+			dojo.query("button.invert")
+				.connect("onclick",function(e){
+					switch(e.target.id.toString()){
+						case "i1" : dijit.byId("select").invertSelection(); break;
+						case "i2" : dijit.byId("select2").invertSelection(); break;
+						case "i3" : dijit.byId("select3").invertSelection(); break;
+					}
+			});
+
+			// there is only one debug button
+			dojo.query(".debug").connect("onclick",function(e){
+				console.log('select value:',dijit.byId("select").get('value'));
+				console.log('select2 value:',dijit.byId("select2").get('value'));
+				console.log('select3 value:',dijit.byId("select3").get('value'));
+			});
+
+			// natural form reaction:
+			dojo.connect(dojo.byId("test"),"onsubmit",function(e){
+				e.preventDefault();
+			});
+			dojo.connect(dojo.byId("formSubmit"),"onclick",function(e){
+				// see what the real form says about our widgets:
+				var vals = dojo.formToJson("test");
+				console.log(vals);
+			});
+		});
+	</script>
+</head>
+<body class="claro" style="padding:20px">
+
+		<h1 class="testTitle" tabindex="0">dijit.form.MultiSelect:</h1>
+		<p>Select one or more items in First or Second list and move them between lists using the buttons provided.</p>
+		<form action="#" method="get" id="test">
+
+			<div>
+				<div id="sel1" role="presentation">
+					<label for="select">First list:</label><br>
+					<select id="select" multiple="true" size="7" name="easing">
+						<option class="clone" value="dojo._defaultEasing">dojo._defaultEasing</option>
+					</select>
+				</div>
+				<div id="leftRightButtons" role="presentation">
+					<span>
+						<button class="switch" id="left" title="Move Items to First list"><</button>
+						<button class="switch" id="right" title="Move Items to Second list">></button>
+					</span>
+				</div>
+				<div id="sel2" role="presentation">
+					<label for="select2">Second list:</label><br>
+					<select id="select2" multiple="true" size="7" name="second">
+					</select>
+				</div>
+			</div>
+
+			<br style="clear: both;"><br>
+
+			<button class='invert' id="i1">invert first list</button>
+			<button class="invert" id="i2">invert second list</button>
+			<button id="formSubmit">Submit</button>
+
+		</form>
+
+		<button class="debug">call get('value')</button>
+
+		<h3><label for="select3">markup:</label></h3>
+
+		<select id="select3" multiple="true" name="select3"
+			dojoType="dijit.form.MultiSelect"
+			style="height:200px; width:175px; border:5px solid #ededed;">
+
+			<option value="TN" selected="true">Tennessee</option>
+			<option value="VA">Virginia</option>
+			<option value="WA">Washington</option>
+			<option value="FL">Florida</option>
+			<option value="CA">California</option>
+
+		</select>
+
+		<br><br>
+		<button class='invert' id="i3">invert markup list</button>
+		<button class='set' id="s1" onclick="dijit.byId('select3').set('value', ['VA', 'WA']);">set markup list to [VA, WA]</button>
+</body>
+</html>
diff --git a/dijit/tests/form/test_Select.html b/dijit/tests/form/test_Select.html
new file mode 100644
index 0000000..6bec1b7
--- /dev/null
+++ b/dijit/tests/form/test_Select.html
@@ -0,0 +1,573 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>dijit.form.Select test</title>
+
+		<style>
+			@import url(../../../dojo/resources/dojo.css);
+			@import url(../../themes/tundra/tundra.css);
+			@import url(../css/dijitTests.css);
+			.ark { text-decoration: underline; }
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+	
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+	
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript" src="../helpers.js"></script>
+
+	    <script type="text/javascript">
+			dojo.require("doh.runner");
+	        dojo.require("dojo.parser");
+			dojo.require("dijit.form.Select");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.form.Form");
+			dojo.require("dojo.data.ItemFileWriteStore");
+
+			var numOptions = 0;
+			var numChanges = 0;
+			var addNum = 10;
+
+			// Add test=true to the URL to run unit tests.
+			// Add testPerformance=true to the URL to run performance tests - note SLOW to run
+			var test = /mode=test/i.test(window.location.href),
+				testPerformance = /mode=benchmark/i.test(window.location.href);
+
+			// Data and stores here for store-based selects
+			var data = {
+				identifier: "value",
+				label: "label",
+				items: [
+					{value: "AL", label: "Alabama"},
+					{value: "AK", label: "Alaska"},
+					{value: "AZ", label: "Arizona"},
+					{value: "AR", label: "Arkansas"},
+					{value: "CA", label: "California"},
+					{value: "CO", label: "Colorado"},
+					{value: "CT", label: "Connecticut"}
+				]
+			};
+			var data2 = {
+				identifier: "value",
+				label: "label",
+				items: [
+					{value: "DE", label: "Delaware"},
+					{value: "FL", label: "Florida"},
+					{value: "GA", label: "Georgia"},
+					{value: "HI", label: "Hawaii"},
+					{value: "ID", label: "Idaho"},
+					{value: "IL", label: "Illinois"},
+					{value: "IN", label: "Indiana"}
+				]
+			};
+
+			var readStore = new dojo.data.ItemFileReadStore({data:dojo.clone(data)});
+			var store2 = new dojo.data.ItemFileReadStore({data:dojo.clone(data2)});
+			var writeStore = new dojo.data.ItemFileWriteStore({data:dojo.clone(data)});
+
+			function wrapLabel(expected){
+				return ("<span class=\"dijitReset dijitInline dijitSelectLabel\">" + expected + "</span>").toLowerCase().replace(/ */g, "");
+			}
+
+			dojo.addOnLoad(function(){
+				dojo.connect(s1, "onChange", function(val){
+					console.log("First Select Changed to " + val);
+					numChanges++;
+				});
+
+				var programmatic = new dijit.form.Select({
+					options: [
+						{ label: 'foo', value: 'foo', selected: true },
+						{ label: 'bar', value: 'bar' }
+					]
+				});
+				programmatic.placeAt('testProgramatic');
+
+				var programmaticDisabled = new dijit.form.Select({
+					disabled: true,
+					options: [
+						{ label: 'foo', value: 'foo', selected: true },
+						{ label: 'bar', value: 'bar' }
+					]
+				});
+				programmaticDisabled.placeAt('testProgramatic');
+
+				if(test){
+					doh.register("API", [
+						{
+							name: "test_set",
+							timeout: 5000,
+							runTest: function(t){
+								var d = new doh.Deferred();
+								t.is(dojo.toJson({s1:"VA", s2:"CA", s3:"AL", s4: "AK", s5: "move", s6: "", s7:"NY", s8a:"AL", s8b:"AL",
+									s9:"CT", s10:"AL", s11:"AL", s12: "AL"}), dojo.toJson(form.get("value")));
+									
+								// set s1 to a valid value
+								s1.set("value", "WA");
+								t.is("WA", s1.value);
+
+								setTimeout(function(){ try{ // allow onChange to fire
+
+									// set s1 to non-existing value, which (currently) makes the Select pick
+									// the first option in the drop down
+									s1.set("value", "UT");
+									t.is("TN", s1.value);
+
+									setTimeout(function(){ try{ // allow onChange to fire
+										t.is(2, numChanges);
+										d.callback(true);
+									}catch(e){ d.errback(e); }}, 0);
+								}catch(e){ d.errback(e); }}, 0);
+								return d;
+							}
+						},
+						{
+							name: 'test_disabled',
+							runTest: function(t){
+								t.is(testDisabled.disabled, true);
+							}
+						},
+						{
+							name: 'test_programmatic',
+							runTest: function(t){
+								t.is(programmatic.options.length, 2);
+								t.is(programmaticDisabled.options.length, 2);
+								t.is(programmaticDisabled.disabled, true);
+							}
+						},
+
+						// Test that destroying a Select destroys the internal Menu and MenuItems too
+						{
+							name: "test_destroy",
+							timeout: 5000,
+							runTest: function(t){
+								var oldCnt = dijit.registry.length;
+									
+								s1.destroy();
+
+								var newCnt = dijit.registry.length;
+								t.t(newCnt < oldCnt + 3, "should have destroyed many widgets, went from " + oldCnt + " to " + newCnt);
+							}
+						}
+					]);
+
+					doh.register("data store", [
+						// Tests that when the currently selected item is changed in the data store,
+						// the change is reflected in the Select widget
+						function test_changeSelected(t){
+							t.is("AL", s11.value);
+							t.is(wrapLabel("Alabama"), s11.containerNode.innerHTML.toLowerCase().replace(/ */g, ""));
+							s11.set("value", "AK");
+							t.is("AK", s11.value);
+							t.is(wrapLabel("Alaska"), s11.containerNode.innerHTML.toLowerCase().replace(/ */g, ""));
+							var d = new doh.Deferred();
+							writeStore.fetchItemByIdentity({
+								identity: "AK",
+								onItem: d.getTestCallback(function(item){
+									writeStore.setValue(item, "label", "North Pole");
+									t.is(wrapLabel("North Pole"), s11.containerNode.innerHTML.toLowerCase().replace(/ */g, ""), "select displayed value updated");
+								})
+							});
+							return d;
+						},
+
+						// Test that a delete of the non-selected item will remove that item from the Select's
+						// list of options.
+						function test_deleteNonSelected(t){
+							t.is(7, s11.getOptions().length);
+							t.is("AK", s11.value);
+							var d = new doh.Deferred();
+							writeStore.fetchItemByIdentity({
+								identity: "AZ",
+								onItem: d.getTestCallback(function(item){
+									writeStore.deleteItem(item);
+									t.is(6, s11.getOptions().length);
+								})
+							});
+							return d;
+						},
+
+						// Test that a delete of the selected item will remove that item from the Select's
+						// list of options, and switch to a new selected item
+						function test_deleteSelected(t){
+							t.is(6, s11.getOptions().length);
+							t.is("AK", s11.value);
+							var d = new doh.Deferred();
+							writeStore.fetchItemByIdentity({
+								identity: "AK",
+								onItem: d.getTestCallback(function(item){
+									writeStore.deleteItem(item);
+									t.is("AL", s11.value);
+									t.is(5, s11.getOptions().length);
+								})
+							});
+							return d;
+						},
+
+						// Test that new items added to the data store appear in the select's options
+						function test_newItem(t){
+							t.is(5, s11.getOptions().length);
+							t.is("AL", s11.value);	
+
+							var d = new doh.Deferred();
+							writeStore.newItem({value: "NY", label: "New York"});
+							setTimeout(d.getTestCallback(function(){
+									t.is(6, s11.getOptions().length);
+									s11.set("value", "NY");
+									t.is("NY", s11.value);
+							}), 100);
+
+							return d;
+						},
+
+						// Test that a Select's store can be changed
+						// TODO: should be supported/tested through set("store", ...), although
+						// I guess that wouldn't allow setting the selected item at the same time.
+						function test_setStore(t){
+							t.is("AL", s12.value);
+							s12.setStore(store2, "FL");
+							t.is("FL", s12.value);
+							s12.setStore(readStore, "CA");
+							t.is("CA", s12.value);
+							s12.setStore(store2);
+							t.is("DE", s12.value);
+							t.is(7, s12.getOptions().length);
+						}
+					]);
+				}
+
+				if(testPerformance){			
+					doh.register("performance", [
+						{
+							name: "test_performance_single",
+							testType: "perf",
+							trialDuration: 100,
+							trialIterations: 100,
+							trialDelay: 100,
+							runTest: function(t){
+								var opt = {value: "Test", label: "Test Option"};
+								s6.addOption(opt);
+								s6.removeOption(opt);
+							}
+						},
+						{
+							name: "test_performance_separate",
+							testType: "perf",
+							trialDuration: 100,
+							trialIterations: 100,
+							trialDelay: 100,
+							setUp: function(t){
+								var opts = (t.options = []);
+								for(var i = 0; i < addNum; i++){
+									opts.push({value: i + "", label: "Option " + (i + 1)});
+								}
+							},
+							runTest: function(t){
+								dojo.forEach(t.options, function(opt){
+									s6.addOption(opt);
+								});
+								dojo.forEach(t.options, function(opt){
+									s6.removeOption(opt);
+								});
+							},
+							tearDown: function(t){
+								delete t.options;
+							}
+						},
+						{
+							name: "test_performance_batch",
+							testType: "perf",
+							trialDuration: 100,
+							trialIterations: 100,
+							trialDelay: 100,
+							setUp: function(t){
+								var opts = (t.options = []);
+								for(var i = 0; i < addNum; i++){
+									opts.push({value: i + "", label: "Option " + (i + 1)});
+								}
+							},
+							runTest: function(t){
+								s6.addOption(t.options);
+								s6.removeOption(t.options);
+							},
+							tearDown: function(t){
+								delete t.options;
+							}
+						}
+					]);
+				}
+
+				if(test || testPerformance){
+					doh.run();
+				}
+			});
+		</script>
+	</head>
+	<body class="claro">
+		<h1 class="testTitle">Test: dijit.form.Select</h1>
+
+		<p>
+			Note: load <a href="test_Select.html?mode=test">test_Select.html?mode=test</a> to run unit tests, or
+			<a href="test_Select.html?mode=benchmark">test_Select.html?mode=benchmark</a> to run performance tests.
+		</p>
+
+		<h2>HTML select for comparison</h2>
+		<form method="get" id="htmlForm" action="get">
+			<label for="htmlSelect">Four options:</label>
+			<select id="htmlSelect">
+				<option value="one">one</option>
+				<option value="two">two</option>
+				<option value="three">three</option>
+				<option value="four">four</option>
+			</select>
+			<label for="htmlSelect2">Empty:</label>
+			<select id="htmlSelect2">
+			</select>
+		</form>
+		<h2>dijit.form.Select</h2>
+		<form dojoType="dijit.form.Form" jsId="form" method="get">
+			<h4 class="testSubtitle">Setting Defaults</h4>
+			<label for="s1">Test One: </label>
+			<select jsId="s1" name="s1" id="s1" dojoType="dijit.form.Select" >
+				<option value="TN">Tennessee</option>
+				<option value="VA" selected="selected">Virginia</option>
+				<option value="WA">Washington</option>
+				<option value="FL">Florida</option>
+				<option value="CA">California</option>
+			</select>
+			<button id="s1button" dojoType="dijit.form.Button" type="button">
+				<script type="dojo/method" event="onClick">
+					console.log(s1.get("displayedValue"));
+				</script>
+				Get Displayed Value
+			</button>
+			<label for="s2">Test Two: </label>
+			<select jsId="s2" name="s2" id="s2" value="CA" dojoType="dijit.form.Select">
+				<option value="AL">Alabama</option>
+				<option value="AK">Alaska</option>
+				<option value="AZ">Arizona</option>
+				<option value="AR">Arkansas</option>
+				<option value="CA">California</option>
+			</select>
+			<label for="s3">Test Three: </label>
+			<select jsId="s3" name="s3" id="s3" style="width: 150px;" dojoType="dijit.form.Select">
+				<option value="AL">Alabama</option>
+				<option value="AK">Alaska</option>
+				<option type="separator"></option>
+				<option value="AZ">Arizona</option>
+				<option value="AR">Arkansas</option>
+				<option type="separator"></option>
+				<option value="CA">California</option>
+			</select>
+		<hr>
+			<h4 class="testSubtitle">Rich Text (Need to use divs and spans - since browsers hack selects to pieces)</h4>
+			<label for="s4">Rich text One: </label>
+			<div jsId="s4" name="s4" id="s4" value="AK" dojoType="dijit.form.Select">
+				<span value="AL"><b>Alabama</b></span>
+				<span value="AK"><font color="red">A</font><font color="orange">l</font><font color="yellow">a</font><font color="green">s</font><font color="blue">k</font><font color="purple">a</font></span>
+				<span value="AZ"><i>Arizona</i></span>
+				<span value="AR"><span class="ark">Arkansas</span></span>
+				<span value="CA"><span style="font-size:25%">C</span><span style="font-size:50%">a</span><span style="font-size:75%">l</span><span style="font-size:90%">i</span><span style="font-size:100%">f</span><span style="font-size:125%">o</span><span style="font-size:133%">r</span><span style="font-size:150%">n</span><span style="font-size:175%">i</span><span style="font-size:200%">a</span></span>
+				<span value="NM" disabled="disabled">New<br>  Mexico</span>
+			</div>
+			<button dojoType="dijit.form.Button" type="button">
+				<script type="dojo/method" event="onClick">
+					s4.set("disabled", !s4.get("disabled"));
+				</script>
+				Toggle Disabled
+			</button>
+			<label for="s5">Rich text two: </label>
+			<div jsId="s5" name="s5" id="s5" value="move" dojoType="dijit.form.Select">
+				<span value="copy"><img style="vertical-align: middle;margin-top: 1px;margin-bottom:1px;" src="../../../dijit/themes/tundra/images/dndCopy.png" /> Copy</span>
+				<span value="move"><img  style="vertical-align: middle;margin-top: 1px;margin-bottom:1px;" src="../../../dijit/themes/tundra/images/dndMove.png" /> Move</span>
+				<span value="nocopy"><img  style="vertical-align: middle;margin-top: 1px;margin-bottom:1px;" src="../../../dijit/themes/tundra/images/dndNoCopy.png" /> No Copy</span>
+				<span value="nomove"><img  style="vertical-align: middle;margin-top: 1px;margin-bottom:1px;" src="../../../dijit/themes/tundra/images/dndNoMove.png" /> No Move</span>
+				<span value="long"><img  style="vertical-align: middle;margin-top: 1px;margin-bottom:1px;" src="../../../dijit/themes/tundra/images/dndNoMove.png" /> Very Long Menu Entry</span>
+			</div>
+		<hr>
+			<h4 class="testSubtitle"><label for="s6">Initially Empty</label></h4>
+			<select jsId="s6" name="s6" id="s6" maxHeight="100" dojoType="dijit.form.Select">
+			</select>
+			<button dojoType="dijit.form.Button" type="button">
+				<script type="dojo/method" event="onClick">
+					numOptions++;
+					s6.addOption({value: numOptions + "", label: "Option " + numOptions});
+				</script>
+				Add Option
+			</button>
+			<button dojoType="dijit.form.Button" type="button">
+				<script type="dojo/method" event="onClick">
+					s6.removeOption(0);
+				</script>
+				Remove Top Option
+			</button>
+			<button dojoType="dijit.form.Button" type="button">
+				<script type="dojo/method" event="onClick">
+					s6.set("disabled", !s6.get("disabled"));
+				</script>
+				Toggle Disabled
+			</button>
+			<hr>
+		<h4 class="testSubtitle"><label for="s7">Single Item</label></h4>
+			<select jsId="s7" name="s7" id="s7" dojoType="dijit.form.Select">
+				<option value="NY">New York</option>
+			</select>
+		<hr>
+		<h4 class="testSubtitle">Long lists</h4>
+			<label for="s8a">maxHeight=200:</label>
+			<select jsId="s8a" name="s8a" id="s8a" maxHeight="200" dojoType="dijit.form.Select">
+				<option value="AL">Alabama</option>
+				<option value="AK">Alaska</option>
+				<option value="AZ">Arizona</option>
+				<option value="AR">Arkansas</option>
+				<option value="CA">California</option>
+				<option value="CO">Colorado</option>
+				<option value="CT">Connecticut</option>
+				<option value="DE">Delaware</option>
+				<option value="DC">Dist of Columbia</option>
+				<option value="FL">Florida</option>
+				<option value="GA">Georgia</option>
+				<option value="HI">Hawaii</option>
+				<option value="ID">Idaho</option>
+				<option value="IL">Illinois</option>
+				<option value="IN">Indiana</option>
+				<option value="IA">Iowa</option>
+				<option value="KS">Kansas</option>
+				<option value="KY">Kentucky</option>
+				<option value="LA">Louisiana</option>
+				<option value="ME">Maine</option>
+				<option value="MD">Maryland</option>
+				<option value="MA">Massachusetts</option>
+				<option value="MI">Michigan</option>
+				<option value="MN">Minnesota</option>
+				<option value="MS">Mississippi</option>
+				<option value="MO">Missouri</option>
+				<option value="MT">Montana</option>
+				<option value="NE">Nebraska</option>
+				<option value="NV">Nevada</option>
+				<option value="NH">New Hampshire</option>
+				<option value="NJ">New Jersey</option>
+				<option value="NM">New Mexico</option>
+				<option value="NY">New York</option>
+				<option value="NC">North Carolina</option>
+				<option value="ND">North Dakota</option>
+				<option value="OH">Ohio</option>
+				<option value="OK">Oklahoma</option>
+				<option value="OR">Oregon</option>
+				<option value="PA">Pennsylvania</option>
+				<option value="RI">Rhode Island</option>
+				<option value="SC">South Carolina</option>
+				<option value="SD">South Dakota</option>
+				<option value="TN">Tennessee</option>
+				<option value="TX">Texas</option>
+				<option value="UT">Utah</option>
+				<option value="VT">Vermont</option>
+				<option value="VA">Virginia</option>
+				<option value="WA">Washington</option>
+				<option value="WV">West Virginia</option>
+				<option value="WI">Wisconsin</option>
+				<option value="WY">Wyoming</option>
+			</select>
+			<label for="s8b">no maxHeight:</label>
+			<select jsId="s8b" name="s8b" id="s8b" dojoType="dijit.form.Select">
+				<option value="AL">Alabama</option>
+				<option value="AK">Alaska</option>
+				<option value="AZ">Arizona</option>
+				<option value="AR">Arkansas</option>
+				<option value="CA">California</option>
+				<option value="CO">Colorado</option>
+				<option value="CT">Connecticut</option>
+				<option value="DE">Delaware</option>
+				<option value="DC">Dist of Columbia</option>
+				<option value="FL">Florida</option>
+				<option value="GA">Georgia</option>
+				<option value="HI">Hawaii</option>
+				<option value="ID">Idaho</option>
+				<option value="IL">Illinois</option>
+				<option value="IN">Indiana</option>
+				<option value="IA">Iowa</option>
+				<option value="KS">Kansas</option>
+				<option value="KY">Kentucky</option>
+				<option value="LA">Louisiana</option>
+				<option value="ME">Maine</option>
+				<option value="MD">Maryland</option>
+				<option value="MA">Massachusetts</option>
+				<option value="MI">Michigan</option>
+				<option value="MN">Minnesota</option>
+				<option value="MS">Mississippi</option>
+				<option value="MO">Missouri</option>
+				<option value="MT">Montana</option>
+				<option value="NE">Nebraska</option>
+				<option value="NV">Nevada</option>
+				<option value="NH">New Hampshire</option>
+				<option value="NJ">New Jersey</option>
+				<option value="NM">New Mexico</option>
+				<option value="NY">New York</option>
+				<option value="NC">North Carolina</option>
+				<option value="ND">North Dakota</option>
+				<option value="OH">Ohio</option>
+				<option value="OK">Oklahoma</option>
+				<option value="OR">Oregon</option>
+				<option value="PA">Pennsylvania</option>
+				<option value="RI">Rhode Island</option>
+				<option value="SC">South Carolina</option>
+				<option value="SD">South Dakota</option>
+				<option value="TN">Tennessee</option>
+				<option value="TX">Texas</option>
+				<option value="UT">Utah</option>
+				<option value="VT">Vermont</option>
+				<option value="VA">Virginia</option>
+				<option value="WA">Washington</option>
+				<option value="WV">West Virginia</option>
+				<option value="WI">Wisconsin</option>
+				<option value="WY">Wyoming</option>
+			</select>
+			<hr>
+			<h4 class="testSubtitle">Store-based</h4>
+			<label for="s9">Example 1</label>
+			<select jsId="s9" name="s9" id="s9" store="readStore" value="CT" dojoType="dijit.form.Select">
+			</select>
+			<label for="s10">Example 2</label>
+			<select jsId="s10" name="s10" id="s10" store="readStore" dojoType="dijit.form.Select">
+			</select>
+			<label for="s11">Example 3</label>
+			<select jsId="s11" name="s11" id="s11" store="writeStore" dojoType="dijit.form.Select">
+			</select>
+			<label for="s12">Example 4</label>
+			<select jsId="s12" name="s12" id="s12" store="readStore" dojoType="dijit.form.Select">
+			</select>
+			<hr>
+			<h4 class="testSubtitle">Inlined with text (all IE modes except for IE8 Standards)</h4>
+			<label for="txtPrompt">Text Prompt:</label>
+			<select dojoType="dijit.form.Select" id="txtPrompt">
+				<option value="SEL" selected="selected">Select</option>
+				<option value="OTHER">Other</option>
+			</select>
+			<hr>
+			<button dojoType="dijit.form.Button" type="button">
+				<script type="dojo/method" event="onClick">
+					console.dir(form.getValues());
+				</script>
+				Get Values
+			</button>
+			<button dojoType="dijit.form.Button" type="submit">Submit</button>
+		</form>
+		<hr>
+		<h4 class="testSubtitle">Disabled</h4>
+		<label for="testDisabled">Disabled:</label>
+		<select dojoType="dijit.form.Select" disabled="disabled" jsId='testDisabled' name='testDisabled' id='testDisabled'>
+			<option value="foo">foo</option>
+			<option value="bar">bar</option>
+		</select>
+		<hr>
+		<h4 class="testSubtitle">Programmatic and other tests</h4>
+		<div id="testProgramatic"></div>
+	</body>
+</html>
diff --git a/dijit/tests/form/test_SimpleTextarea.html b/dijit/tests/form/test_SimpleTextarea.html
new file mode 100644
index 0000000..2e8d3ff
--- /dev/null
+++ b/dijit/tests/form/test_SimpleTextarea.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Testing SimpleTextArea | The Dojo Toolkit</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+		</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.form.SimpleTextarea");
+
+		// needed for tests
+		dojo.require("dijit.layout.BorderContainer");
+	</script>
+</head>
+
+<body class="claro" style="padding:20px">
+
+		<h1 class="testTitle">SimpleTextarea</h1>
+
+		<p>
+			This is a simple text area that doesn't automatically size itself according to it's content.
+			It can be used inside layout containers.
+		</p>
+
+		<h2>Plain textarea (rows=5, cols=50), selectOnClick=true</h2>
+		<textarea id="ta1" dojoType="dijit.form.SimpleTextarea" name="ta1" rows="5" cols="50"
+			onFocus="console.log('user focus handler')"
+			onBlur="console.log('user blur handler')"
+		        onChange="dojo.byId('oc1').value=''+arguments[0]"
+			selectOnClick="true"
+		>
+			shichashaw, textarea text baw.
+		</textarea>
+		onChange:<textarea id="oc1" rows="6" cols="50" disabled autocomplete="off">not fired yet!</textarea>
+		<nobr>
+		<button onclick="dijit.byId('q1').reset();">reset</button>
+		<button onclick="dijit.byId('q1').set('value', null);">set value to null</button>
+		<button onclick="dojo.byId('gv1').value=''+dijit.byId('q1').get('value');">get value</button>
+		<textarea id="gv1" rows="6" cols="50" disabled autocomplete="off">no value yet!</textarea>
+		</nobr>
+
+
+		<h2>Plain textarea with style="height: 300px; width: 300px" rows="" cols=""</h2>
+		<textarea id="ta2" dojoType="dijit.form.SimpleTextarea" name="ta2"
+			style="height: 300px; width: 300px" rows="" cols="">I have a style setting rather than rows/cols setting</textarea>
+
+		<h2>In a BorderContainer</h2>
+
+		<div id="container" dojoType="dijit.layout.BorderContainer" style="width:500px; height:400px; border: inset gray 3px;">
+			<textarea id="top" name="top" dojoType="dijit.form.SimpleTextarea" region="top" splitter="true" style="height: 100px;">
+				This is just some text in the top region.
+			</textarea>
+			<textarea id="left" name="left" dojoType="dijit.form.SimpleTextarea" region="left" splitter="true" style="width: 200px;">
+				This is just some text in the left region.
+			</textarea>
+			<textarea id="center" name="center" dojoType="dijit.form.SimpleTextarea" region="center">
+				This is just some text in the center region.
+			</textarea>
+			<textarea id="right" name="right" dojoType="dijit.form.SimpleTextarea" region="right" splitter="true" style="width: 200px;">
+				This is just some text in the right region.
+			</textarea>
+			<textarea id="bottom" name="bottom" dojoType="dijit.form.SimpleTextarea" region="bottom" splitter="true" style="height: 100px;">
+				This is just some text in the bottom region.
+			</textarea>
+		</div>
+
+		<script>
+			function setAttr(attr, value){
+				dijit.registry.byClass('dijit.form.SimpleTextarea').forEach(function(widget){ widget.set(attr, value);});
+			}
+		</script>
+		<input type="button" onclick="setAttr('readOnly', false);" value="Remove readOnly">
+		<input type="button" onclick="setAttr('readOnly', false);" value="Set readOnly">
+		<input type="button" onclick="setAttr('disabled', true);" value="Disable">
+		<input type="button" onclick="setAttr('disabled', false);" value="Enable">
+</body>
+</html>
diff --git a/dijit/tests/form/test_Slider.html b/dijit/tests/form/test_Slider.html
new file mode 100644
index 0000000..2844ca1
--- /dev/null
+++ b/dijit/tests/form/test_Slider.html
@@ -0,0 +1,223 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+                "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Dojo Slider Widget Demo</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+			@import "../../../util/doh/robot/robot.css";
+			#slider2 .dijitButtonNode {
+				width:12px;
+				height:12px;
+				border: none;
+				font-size:11px;
+				padding:0px;
+			}
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript">
+				dojo.require("dijit.dijit"); // optimize: load dijit layer
+
+				dojo.require("dijit.form.HorizontalSlider");
+				dojo.require("dijit.form.VerticalSlider");
+				dojo.require("dijit.form.HorizontalRule");
+				dojo.require("dijit.form.VerticalRule");
+				dojo.require("dijit.form.HorizontalRuleLabels");
+				dojo.require("dijit.form.VerticalRuleLabels");
+
+				dojo.require("dijit.form.Button");
+				dojo.require("dojo.parser"); // scan page for widgets
+
+				// programatic vertical slider and labels
+				var programaticExample = function(){
+
+					var node = dojo.byId("programaticSlider");
+					// or var node = dojo.body().appendChild(document.createElement('div'));
+
+					// our rules are to be children of the slider
+					var rulesNode = document.createElement('div');
+					node.appendChild(rulesNode);
+
+					// setup the rules
+					var sliderRules = new dijit.form.VerticalRule({
+						count:11,
+						style:"width:5px"
+					},rulesNode);
+
+					// and setup the slider
+					var theSlider = new dijit.form.VerticalSlider({
+						value:1400,
+						onChange: function(){
+                                                    console.log(arguments);
+						},
+						name:"programaticSlider",
+						slideDuration:0,
+						onChange:function(val){ dojo.byId('sliderProgInput').value=val; },
+						style:"height:165px",
+						minimum:1000,
+						maximum:3000,
+						discreteValues:11,
+						intermediateChanges:"true",
+						showButtons:"true"
+					},node);
+
+					// and start them both
+					theSlider.startup();
+        				sliderRules.startup();
+
+				};
+				dojo.addOnLoad(programaticExample);
+		</script>
+	</head>
+
+	<body class="claro">
+		<h1 class="testTitle">Slider</h1>
+		Also try using the arrow keys, buttons, or clicking on the progress bar to move the slider.
+		<br>
+		<!--    to test form submission, you'll need to create an action handler similar to
+			http://www.utexas.edu/teamweb/cgi-bin/generic.cgi -->
+		<form id="form1" action="" name="example" method="post">
+		<br>initial value=10, min=0, max=100, pageIncrement=100, onChange event triggers input box value change immediately<br>
+		<label for="slider1"><strong>Horizontal Slider Example</strong></label>
+		<div dojoType="dijit.form.HorizontalSlider" name="horizontal1"
+			onChange="dojo.byId('slider1input').value=dojo.number.format(arguments[0]/100,{places:1,pattern:'#%'});"
+			value="10"
+			maximum="100"
+			minimum="0"
+			pageIncrement="100"
+			showButtons="true"
+			intermediateChanges="true"
+			slideDuration="500"
+			style="width:500px; height: 20px;"
+			id="slider1">
+				<ol dojoType="dijit.form.HorizontalRuleLabels" container="topDecoration" style="height:1.2em;font-size:75%;" count="6" numericMargin="1"></ol>
+				<div dojoType="dijit.form.HorizontalRule" container="topDecoration" count=6 style="height:5px;"></div>
+				<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count=5 style="height:5px;"></div>
+				<ol dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" style="height:1em;font-size:75%;">
+					<li>lowest</li>
+					<li>normal</li>
+					<li>highest</li>
+				</ol>
+		</div>
+
+		Slider1 Value:<input readonly id="slider1input" size="4" value="10.0%">
+		<br>
+		<button id="disableButton" dojoType="dijit.form.Button" onClick="dijit.byId('slider1').set('disabled', true);dijit.byId('disableButton').set('disabled',true);dijit.byId('enableButton').set('disabled',false);">Disable previous slider</button>
+		<button id="enableButton"  dojoType="dijit.form.Button" onClick="dijit.byId('slider1').set('disabled',false);dijit.byId('disableButton').set('disabled',false);dijit.byId('enableButton').set('disabled', true);" disabled>Enable previous slider</button>
+		<br>
+		<br>initial value=10, min=0, max=100, onChange event triggers input box value change when you mouse up or tab away<br>
+		<label for="slider2"><strong>Vertical Slider Example</strong></label>
+		<div dojoType="dijit.form.VerticalSlider" name="vertical1"
+			onChange="dojo.byId('slider2input').value=arguments[0];"
+			value="10"
+			maximum="100"
+			minimum="0"
+			discreteValues="11"
+			style="height:300px;"
+			id="slider2">
+				<ol dojoType="dijit.form.VerticalRuleLabels" container="leftDecoration" style="width:2em;" labelStyle="right:0px;">
+					<li>0</li>
+					<li>100</li>
+				</ol>
+				<div dojoType="dijit.form.VerticalRule" container="leftDecoration" count=11 style="width:5px;" ruleStyle="border-color: #888"></div>
+				<div dojoType="dijit.form.VerticalRule" container="rightDecoration" count=11 style="width:5px;" ruleStyle="border-color: #888"></div>
+				<ol dojoType="dijit.form.VerticalRuleLabels" container="rightDecoration" style="width:2em;" count="6" numericMargin="1" maximum="100" constraints="{pattern:'#'}"></ol>
+		</div>
+		Slider2 Value:<input readonly id="slider2input" size="3" value="10">
+		<h1>Fancy HTML labels (no slide animation):</h1>
+		<div dojoType="dijit.form.HorizontalSlider" name="horizontal2"
+			title="Fancy HTML Labels"
+			minimum="1"
+			value="2"
+			maximum="3"
+			discreteValues="3"
+			showButtons="false"
+			intermediateChanges="true"
+			slideDuration="0"
+			style="width:300px; height: 40px;"
+			id="slider3">
+				<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count=3 style="height:5px;"></div>
+				<ol dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" style="height:1em;font-size:75%;">
+					<li><img width=10 height=10 src="../images/note.gif"><br><span style="font-size: small">small</span></li>
+					<li><img width=15 height=15 src="../images/note.gif"><br><span style="font-size: medium">medium</span></li>
+					<li><img width=20 height=20 src="../images/note.gif"><br><span style="font-size: large">large</span></li>
+				</ol>
+		</div>
+
+		<p></p><h1>Standalone ruler example:</h1><p></p>
+
+		<div style="width:2in;border-top:1px solid black;">
+			<div dojoType="dijit.form.HorizontalRule" count=17 style="height:.4em;"></div>
+			<div dojoType="dijit.form.HorizontalRule" count=9 style="height:.4em;"></div>
+			<div dojoType="dijit.form.HorizontalRule" count=5 style="height:.4em;"></div>
+			<div dojoType="dijit.form.HorizontalRule" count=3 style="height:.4em;"></div>
+			<ol dojoType="dijit.form.HorizontalRuleLabels" labelStyle="font-style:monospace;font-size:.7em;margin:-1em 0px 0px -.35em;">
+				<li></li>
+				<li>1</li>
+				<li>2</li>
+			</ol>
+		</div>
+
+		<h1>horizontal, with buttons, disabled (to show styling):</h1>
+
+		<div dojoType="dijit.form.HorizontalSlider" name="horizontalH2"
+			onChange="dojo.byId('slider1input').value=arguments[0];"
+			value="10"
+			maximum="100"
+			minimum="0"
+			disabled="true"
+			showButtons="true"
+			intermediateChanges="true"
+			style="width:50%; height: 20px;"
+			id="sliderH2">
+				<ol dojoType="dijit.form.HorizontalRuleLabels" container="topDecoration" style="height:1.2em;font-size:75%;" count="7" constraints="{pattern:'#.00%'}"></ol>
+				<div dojoType="dijit.form.HorizontalRule" container="topDecoration" count=7 style="height:5px;"></div>
+				<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count=5 style="height:5px;"></div>
+				<ol dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" style="height:1em;font-size:75%;">
+					<li>lowest</li>
+					<li>normal</li>
+					<li>highest</li>
+				</ol>
+		</div>
+
+
+		<h2>Completely Programatic VerticalSlider and VerticalRule</h2>
+		<h3>min:1000, max:3000, 11 discrete values, no animation</h3>
+
+		<div id="programaticSlider"></div>
+		Programmatic Value:<input readonly id="sliderProgInput" size="5" value="1400">
+
+		        <script>
+				// so robot can get to it easily
+				document.displayData=function() {
+					var f = document.getElementById("form1");
+					var s = "";
+					for (var i = 0; i < f.elements.length; i++) {
+						var elem = f.elements[i];
+						if (elem.nodeName.toLowerCase() == "button" || elem.type=="submit" || elem.type=="button")  { continue; }
+						s += elem.name + ": " + elem.value + "\n";
+					}
+					return s;
+				}
+		        </script>
+
+		        <div>
+                		<button name="button" onclick="alert(displayData()); return false;">view data</button>
+        		        <input type="submit" name="submit" />
+		        </div>
+
+		</form>
+	</body>
+</html>
diff --git a/dijit/tests/form/test_Spinner.html b/dijit/tests/form/test_Spinner.html
new file mode 100644
index 0000000..1d0fc67
--- /dev/null
+++ b/dijit/tests/form/test_Spinner.html
@@ -0,0 +1,128 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Dojo Spinner Widget Test</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+			@import "../../../util/doh/robot/robot.css";
+
+			body .bigFont {
+			        font-size: larger; /* help test widget sizing */
+			}
+
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.NumberSpinner");
+			dojo.require("dojo.parser"); // scan page for widgets
+		</script>
+
+	</head>
+
+	<body class="claro">
+		<h1 class="testTitle">Dijit Spinner Test</h1>
+			Try typing values, and use the up/down arrow keys and/or the arrow push
+			buttons to spin
+			<br>
+		<form id="form1" action="" name="example" method="post">
+			<h1>number spinner</h1>
+			<br>
+			initial value=900, no delta specified, no min specified, max=1550, onChange captured, big font<br>
+			<label for="integerspinner1">Spinbox #1: </label><br>
+			<input dojoType="dijit.form.NumberSpinner"
+				onChange="dojo.byId('oc1').value=arguments[0]"
+				value="900"
+				class="bigFont"
+				constraints="{max:1550,places:0}"
+				name="integerspinner1"
+				id="integerspinner1">
+			onChange:<input id="oc1" disabled value="not fired yet!" autocomplete="off">
+			<input type="button" id="sv1_1" value="Set value to 400" onClick="dijit.byId('integerspinner1').set('value',400)" tabIndex="-1">
+			<input type="button" id="sv1_2" value="Set value to null" onClick="dijit.byId('integerspinner1').set('value',null)" tabIndex="-1">
+			<input type="button" id="sv1_3" value="Set required to false" onClick="dijit.byId('integerspinner1').set('required',false)" tabIndex="-1">
+			<input type="button" id="sv1_4" value="Set required to true" onClick="dijit.byId('integerspinner1').set('required',true)" tabIndex="-1">
+			<br>
+			<br>
+			initial value=1000, delta=10, min=9 max=1550<br>
+			<label for="integerspinner2">Spinbox with custom styling (width=50%, 200% Courier font): </label>
+			<input dojoType="dijit.form.NumberSpinner"
+				style="font-size:200%;font-family:Courier;border:1px solid blue;width:50%;"
+				value="1000"
+				smallDelta="10"
+				largeDelta="100"
+				constraints="{min:9,max:1550,places:0}"
+				name="integerspinner2"
+				id="integerspinner2">
+			<br>
+			<br>
+			<label for="integertextbox3">Spinner line break test: </label>initial value not specified, delta not specified, min not specified, max not specified, signed not specified, separator not specified<br>
+			[verify no line break just after this text]
+			<input dojoType="dijit.form.NumberSpinner" name="integertextbox3" id="integertextbox3">
+			[verify no line break just before this text]
+			<br>
+			<br>
+			Move the cursor left and right within the input field to see the effect on the spinner.
+			<br>
+			initial value=+1.0, smalldelta=0.1, largedelta=1.0, min=-10.9, max=155, places=1, maxLength=20, exponent=false<br>
+			<label for="realspinner1">Real Number Spinbox #1: </label><br>
+			<input dojoType="dijit.form.NumberSpinner"
+				value="1.0"
+				smallDelta="0.1"
+				largeDelta="1.0"
+				constraints="{min:-10.9,max:155,places:1,round:true,exponent:false}"
+				maxLength="20"
+				name="realspinner1"
+				id="realspinner1">
+			<br>
+
+			<p>
+			<label for="spinnerMinOnly">Spinner with no maximum, 1 decimal place: </label><br>
+			<input dojoType="dijit.form.NumberSpinner"
+				value="1.0"
+				smallDelta="0.1"
+				largeDelta="1.0"
+				constraints="{min:-10.9,places:1,round:false}"
+				maxLength="20"
+				name="spinnerMinOnly"
+				id="spinnerMinOnly">
+			<input type="button" onclick="dijit.byId('spinnerMinOnly').set('readOnly',false);" value="Remove readOnly">
+			<input type="button" onclick="dijit.byId('spinnerMinOnly').set('readOnly',true);" value="Set readOnly">
+			<input type="button" onclick="dijit.byId('spinnerMinOnly').set('disabled',false);" value="Remove disabled">
+			<input type="button" onclick="dijit.byId('spinnerMinOnly').set('disabled',true);" value="Set disabled">
+			</p>
+			<p>
+			<script type="text/javascript">
+				// so robot can get to it easily
+				document.displayData=function() {
+					var f = document.getElementById("form1");
+					var s = "";
+					for (var i = 0; i < f.elements.length; i++) {
+						var elem = f.elements[i];
+						if (elem.nodeName.toLowerCase() == "button" || elem.type=="submit" || elem.type=="button")  { continue; }
+						s += elem.name + ": " + elem.value + "\n";
+					}
+					return s;
+				}
+			</script>
+
+			<div>
+				<button name="button" onclick="alert(document.displayData()); return false;">view data</button>
+				<input type="submit" name="submit" />
+			</div>
+		</form>
+	</body>
+</html>
diff --git a/dijit/tests/form/test_Textarea.html b/dijit/tests/form/test_Textarea.html
new file mode 100644
index 0000000..7aa6c3e
--- /dev/null
+++ b/dijit/tests/form/test_Textarea.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!-- IE8 beta 2 incorrectly sets TEXTAREA scrollHeight when using strict DTD -->
+<html>
+	<head>
+		<title>Dojo dijit.form.Textarea Widget Test</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+
+			br { margin-bottom: 4em; }
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.Textarea");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dijit.layout.TabContainer");
+			dojo.require("dojo.parser");
+		</script>
+
+	</head>
+	<body class="claro">
+
+		<h1 class="testTitle">Auto-sizing Textarea Widget Test</h2>
+
+		<!--    to test form submission, you'll need to create an action handler similar to
+		        http://www.utexas.edu/teamweb/cgi-bin/generic.cgi -->
+		<form id="form1" action="" name="example" method="" style="width: 800px;">
+
+			<h2>Various dijit.form.Textarea widgets</h2>
+			<label for="blank">dijit.form.Textarea, initially blank:</label>
+			<textarea dojoType="dijit.form.Textarea" id="blank"></textarea>
+			<br>
+
+			<label for="simple">dijit.form.Textarea, inline with maxLength=50:</label><div name="simpleTextArea" maxLength="50" dojoType="dijit.form.Textarea" id="simple" style="width:33%;"
+	         		onChange="dojo.byId('ocSimple').value=arguments[0]"
+	         		onFocus="console.log('user focus handler')"
+	         		onBlur="console.log('user blur handler')"
+				>this is a very simple resizable text area</div>
+			onChange:<textarea id="ocSimple" readOnly>not fired yet!</textarea>
+			<br>
+
+			<label for="plain">Native HTML textarea, for comparison: </label><textarea name="plainTextArea" id="plain" rows="3">
+				this is a native text area
+				for comparison
+			</textarea>
+			<br>
+
+			<div dojoType="dijit.layout.TabContainer" persist="true" tabStrip="true" style="width: 100%; height: 20em;">
+				<div dojoType="dijit.layout.ContentPane" title="Tab 1">
+					<label for="programmatic">dijit.form.Textarea in TabContainer, programmatically created with custom styling:</label><br>
+					<textarea id="programmatic"></textarea>
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Tab 2">
+					<input type="button" onclick="programmaticTextarea.set('value', 'new value for programmatic textarea\nmore text for testing\nmore\neven more\nvery last line');" value="change value">
+				</div>
+			</div>
+			<script type="text/javascript">
+				// See if we can make a widget in script
+				dojo.addOnLoad(function(){
+					programmaticTextarea = new dijit.form.Textarea({
+						id: "programmatic",
+						name: "programmaticTextArea",
+						cols: "60",
+						value: "created programatically with custom border, padding, margin",
+						style: "border:5px solid gray;padding:11px;margin:7px;"
+					}, "programmatic");
+				});
+			</script>
+			<br>
+
+
+			<label for="largeTextArea">dijit.form.Textarea, initially full:</label>
+<!--	‪ and ‬ are inserted solely for testing purposes to mark the beginning and end of left-to-right text so that 
+	cogniscent browsers don't render garbled punctuation nor exhibit strange home/end key behavior while in right-to-left mode -->
+		<textarea dojoType="dijit.form.Textarea" name="largeTextArea" id="largeTextArea">
+‪This is a textarea with a LOT of content.‬
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril d [...]
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril d [...]
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril d [...]
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril d [...]
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril d [...]
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril d [...]
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril d [...]
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril d [...]
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril d [...]
+
+‪This is the end.‬</textarea>
+
+			<h2>Set properties for every dijit.form.Textarea</h2>			
+			<script>
+				function setAttr(attr, value){
+					dijit.registry.byClass('dijit.form.Textarea').forEach(function(widget){ widget.set(attr, value);});
+				}
+			</script>
+			<input type="button" onclick="setAttr('readOnly', false);" value="Remove readOnly">
+			<input type="button" onclick="setAttr('readOnly', true);" value="Set readOnly">
+			<input type="button" onclick="setAttr('disabled', true);" value="Disable">
+			<input type="button" onclick="setAttr('disabled', false);" value="Enable">
+
+			<h2>Submit page as form</h2>
+			<div>
+				<button type="button" name="button" onclick="displayData();">view data</button>
+				<input type="submit" name="submit" />
+			</div>
+			<script type="text/javascript">
+				function displayData() {
+					var f = dojo.byId("form1");
+					var s = "";
+					for(var i = 0; i < f.elements.length; i++){
+						var elem = f.elements[i];
+						if(elem.name == "button" || !dojo.isString(elem.value)){ continue; }
+						s += elem.name + ":[" + elem.value + "]\n";
+					}
+					console.log(s);
+				}
+			</script>
+
+		</form>
+	</body>
+</html>
diff --git a/dijit/tests/form/test_TimeTextBox.html b/dijit/tests/form/test_TimeTextBox.html
new file mode 100644
index 0000000..8ea9cd1
--- /dev/null
+++ b/dijit/tests/form/test_TimeTextBox.html
@@ -0,0 +1,174 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Test TimeTextBox Widget</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			.noticeMessage {
+				color:#093669;
+				font-size:0.95em;
+				margin-left:0.5em;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.TextBox");
+			dojo.require("dijit.form.ValidationTextBox");
+			dojo.require("dijit.form.NumberTextBox");
+			dojo.require("dijit.form.CurrencyTextBox");
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dijit.form.TimeTextBox");
+			dojo.require("dojo.currency");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+		</script>
+	</head>
+
+	<body class="claro">
+		<h1 class="testTitle">Test TimeTextBox Widget</h1>
+		<!--	to test form submission, you'll need to create an action handler similar to
+			http://www.utexas.edu/teamweb/cgi-bin/generic.cgi -->
+		<form id="form1" action="" name="example" method="">
+
+	<div class="dojoTitlePaneLabel">
+		<label for="q1">Time using local conventions with seconds</label>
+		<span class="noticeMessage">TimeTextBox class,
+			Attributes: {formatLength:'medium'}</span>
+	</div>
+	<div class="testExample">
+		<input id="q1" type="text" name="time1" value="T17:45:00"
+			dojoType="dijit.form.TimeTextBox"
+			constraints="{formatLength:'medium'}"
+			required="true"
+			onChange="dojo.byId('oc1').value=arguments[0]"
+			invalidMessage="Invalid time." />
+		onChange:<input id="oc1" size="34" disabled value="not fired yet!" autocomplete="off">
+	</div>
+
+	<div class="dojoTitlePaneLabel">
+		<label for="q2">Time using local conventions without seconds, required, no invalid message tooltip</label>
+		<span class="noticeMessage">TimeTextBox class,
+			Attributes: {formatLength:'short'}</span>
+	</div>
+	<div class="testExample">
+		<input id="q2" type="text" name="time1a" value="T17:45:00"
+			dojoType="dijit.form.TimeTextBox"
+			constraints="{formatLength:'short'}"
+			required="true"
+			invalidMessage="" />
+	</div>
+
+	<div class="dojoTitlePaneLabel">
+		<label for="q3"> 12 Hour Time </label>
+		<span class="noticeMessage">TimeTextBox class,
+			Attributes: {timePattern:'h:mm:ss a'}</span>
+	</div>
+	<div class="testExample">
+		<input id="q3" type="text" name="time1b" value="T17:45:00"
+			dojoType="dijit.form.TimeTextBox"
+			constraints="{timePattern:'h:mm:ss a'}"
+			required="true"
+			invalidMessage="Invalid time." />
+	</div>
+
+	<div class="dojoTitlePaneLabel">
+		<label for="q4"> 24 Hour Time</label>
+		<span class="noticeMessage">TimeTextBox class,
+			Attributes: {timePattern:'HH:mm:ss'}</span>
+	</div>
+	<div class="testExample">
+		<input id="q4" type="text" name="time2" value="T17:45:00"
+			dojoType="dijit.form.TimeTextBox"
+			constraints="{timePattern:'HH:mm:ss'}"
+			required="true"
+			invalidMessage="Invalid time. Use HH:mm:ss where HH is 00 - 23 hours.">
+	</div>
+
+	<div class="dojoTitlePaneLabel">
+		<label for="q5">24 Hour Time with 1 Hour TimePicker</label>
+		<span class="noticeMessage">TimeTextBox class,
+			Attributes: {timePattern:'HH:mm:ss', clickableIncrement:'T00:15:00', visibleIncrement:'T00:15:00', visibleRange:'T01:00:00'}</span>
+	</div>
+	<div class="testExample">
+		<input id="q5" type="text" name="time2" value="T17:45:00"
+			dojoType="dijit.form.TimeTextBox"
+			constraints="{timePattern:'HH:mm:ss', clickableIncrement:'T00:15:00', visibleIncrement:'T00:15:00', visibleRange:'T01:00:00'}"
+			required="true"
+			invalidMessage="Invalid time. Use HH:mm:ss where HH is 00 - 23 hours.">
+	</div>
+
+	<div class="dojoTitlePaneLabel">
+		<label for="q6">Initially empty time text box</label>
+		<span class="noticeMessage">TimeTextBox class,
+			Attributes: {formatLength:'medium',min:'T00:00:00',max:'T12:00:00'}</span>
+	</div>
+	<div class="testExample">
+		<input id="q6" type="text" name="time6"
+			dojoType="dijit.form.TimeTextBox"
+			constraints="{formatLength:'medium',min:'T00:00:00',max:'T12:00:00'}"
+			required="true"
+			onChange="dojo.byId('oc6').value=arguments[0]"
+			invalidMessage="Invalid time." />
+		onChange:<input id="oc6" size="34" disabled value="not fired yet!" autocomplete="off">
+	</div>
+	<div class="dojoTitlePaneLabel">
+		<strong>Using title attribute for label.</strong>
+		<span class="noticeMessage">TimeTextBox class,
+			Attributes: {formatLength:'short'} Time using local conventions without seconds, required, no invalid message tooltip</span>
+	</div>
+	<div class="testExample">
+		<input id="q20" type="text" name="q20" value="T17:45:00"
+			dojoType="dijit.form.TimeTextBox"
+			title="title: Time using local conventions"
+			constraints="{formatLength:'short'}"
+			required="true"
+			invalidMessage="" />
+	</div>
+
+	<script>
+	        function displayData() {
+	                var f = document.getElementById("form1");
+	                var s = "";
+	                for (var i = 0; i < f.elements.length; i++) {
+	                        var elem = f.elements[i];
+	                        if (elem.name == "button")  { continue; }
+	                        s += elem.name + ": " + elem.value + "\n";
+	                }
+	                alert(s);
+	        }
+	</script>
+
+		<div>
+			<button name="button" onclick="displayData(); return false;">view data</button>
+			<input type="submit" name="submit" />
+		</div>
+
+		</form>
+	</body>
+</html>
diff --git a/dijit/tests/form/test_validStatePerformance.html b/dijit/tests/form/test_validStatePerformance.html
new file mode 100644
index 0000000..8bf5cf1
--- /dev/null
+++ b/dijit/tests/form/test_validStatePerformance.html
@@ -0,0 +1,116 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+  "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+  <head>
+    <title>Performance Test of NumberTextBox</title>
+
+    <style type="text/css">
+      @import "../../../dojo/resources/dojo.css";
+      @import "../css/dijitTests.css";
+    </style>
+
+    <!-- required: the default dijit theme: -->
+    <link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+    <!-- required: dojo.js -->
+    <script type="text/javascript" src="../../../dojo/dojo.js"
+      djConfig="isDebug: true, parseOnLoad: true"></script>
+
+    <!-- only needed for alternate theme testing: -->
+    <script type="text/javascript" src="../_testCommon.js"></script>
+
+    <script type="text/javascript">
+      dojo.require("dijit.dijit"); // optimize: load dijit layer
+      dojo.require("dijit.form.TextBox");
+      dojo.require("dijit.form.ValidationTextBox");
+      dojo.require("dijit.form.NumberTextBox");
+      dojo.require("dijit.form.Form");
+      dojo.require("dojo.parser");  // scan page for widgets and instantiate them
+    </script>
+
+  </head>
+
+  <body class="claro">
+    <script>
+      function performancetest() {
+        console.log("Dojo version " + dojo.version);
+        var startTime1 = (new Date()).getTime();
+        dijit.byId("form1").reset();
+        console.log("Time 1: Reset form with NumberTextBox-fields: " + ((new Date()).getTime() - startTime1) + " millis");
+
+        var startTime2 = (new Date()).getTime();
+        dijit.byId("form2").reset();
+        console.log("Time 2: Reset form with ValidationTextBox-fields: " + ((new Date()).getTime() - startTime2) + " millis");
+
+        var startTime3 = (new Date()).getTime();
+        for (var i = 1; i <= 20; i++) {
+			    var w = dijit.byId("input1_" + i);
+			    if(dojo.version.major == 1 && dojo.version.minor == 2) {
+			      w.set("value", i);
+			    } else {
+			      w.set("value", i);
+			    }
+			  }
+        console.log("Time 3: Inserting value into NumberTextBox-fields: " + ((new Date()).getTime() - startTime3) + " millis");
+
+        var startTime4 = (new Date()).getTime();
+        for (var i = 1; i <= 20; i++) {
+			    var w = dijit.byId("input2_" + i);
+			    if(dojo.version.major == 1 && dojo.version.minor == 2) {
+			      w.set("value", i);
+			    } else {
+			      w.set("value", i);
+			    }
+			  }
+        console.log("Time 4: Inserting value into ValidationTextBox-fields: " + ((new Date()).getTime() - startTime4) + " millis");
+      }
+    </script>
+      <form id="form1" dojoType="dijit.form.Form" action="" method="">
+      <input id="input1_1" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_2" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_3" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_4" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_5" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_6" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_7" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_8" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_9" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_10" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_11" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_12" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_13" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_14" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_15" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_16" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_17" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_18" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_19" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      <input id="input1_20" name="input1" maxLength="6" type="text" dojoType="dijit.form.NumberTextBox"/>
+      </form>
+      <br/>
+      <form id="form2" dojoType="dijit.form.Form" action="" method="">
+      <input id="input2_1" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_2" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_3" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_4" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_5" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_6" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_7" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_8" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_9" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_10" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_11" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_12" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_13" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_14" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_15" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_16" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_17" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_18" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_19" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      <input id="input2_20" name="input1" maxLength="6" type="text" dojoType="dijit.form.ValidationTextBox"/>
+      </form>
+      <br/>
+      <button name="button" onclick="performancetest()">Run tests</button>
+  </body>
+</html>
diff --git a/dijit/tests/form/test_validate.html b/dijit/tests/form/test_validate.html
new file mode 100644
index 0000000..a7d3aa6
--- /dev/null
+++ b/dijit/tests/form/test_validate.html
@@ -0,0 +1,491 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Test TextBox Validation Widgets</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			body .small {
+				width: 3em;
+			}
+			body .medium {
+				width: 10em;
+			}
+			body .long {
+				width: 20em;
+			}
+			body .verylong {
+				width: 90%;
+			}
+
+			.noticeMessage {
+				color:#093669;
+				font-size:0.95em;
+				margin-left:0.5em;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+			#widget_q26 .dijitInputField {
+				padding:10px !important;
+			}
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true, extraLocale: ['de-de']"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.TextBox");
+			dojo.require("dijit.form.ValidationTextBox");
+			dojo.require("dijit.form.NumberTextBox");
+			dojo.require("dijit.form.CurrencyTextBox");
+			dojo.require("dojo.currency");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+		</script>
+	</head>
+
+	<body class="claro">
+		<h1 class="testTitle">Dijit Validation Widgets</h1>
+		<!--	to test form submission, you'll need to create an action handler similar to
+			http://www.utexas.edu/teamweb/cgi-bin/generic.cgi -->
+		<form id="form1" action="" name="example" method="">
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q01">First Name:  </label>
+				<span class="noticeMessage"> TextBox class, <b>tabIndex=2</b>, Attributes: {trim: true, propercase: true, intermediateChanges: true, style: 'width:700px', selectOnClick: true}, First letter of each word is upper case.</span>
+			</div>
+			<div class="testExample">
+				<input id="q01" type="text" name="firstname" value="testing testing" style="width: 700px;" tabIndex=2
+					dojoType="dijit.form.TextBox"
+					trim="true"
+					selectOnClick="true"
+					onfocus="console.log('user onfocus handler')"
+					onblur="console.log('user onblur handler')"
+				        onChange="dojo.byId('oc1').value=arguments[0]"
+					intermediateChanges="true"
+					propercase="true" />
+				<br>onChange:<input id="oc1" size="34" disabled value="not fired yet!" autocomplete="off">
+				<input tabIndex="-1" type="button" onclick="dijit.byId('q01').set('disabled', true);" value="Disable">
+				<input tabIndex="-1" type="button" onclick="dijit.byId('q01').set('disabled', false);" value="Enable">
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q02">Last Name:  </label>
+				<span class="noticeMessage"> TextBox class, Attributes: {trim: true, uppercase: true, class: 'verylong'}, all letters converted to upper case. </span>
+			</div>
+			<div class="testExample">
+				<input id="q02" type="text" name="lastname" value="testing testing" class="verylong"
+					dojoType="dijit.form.TextBox"
+					trim="true"
+					uppercase="true" />
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q03">Age:  </label>
+				<span class="noticeMessage"> NumberTextBox class, <b>tabIndex=1</b>, Attributes: {trim: true}, no initial value specified, tooltipPosition=[above, below].  Displays a prompt message if field is blank.</span>
+			</div>
+			<div class="testExample">
+				<input id="q03" type="text" name="age" tabIndex=1
+					dojoType="dijit.form.NumberTextBox"
+					promptMessage="(optional) Enter an age between 0 and 120"
+					maxLength="3"
+					class="small"
+					constraints="{places:0,min:0,max:120}"
+                                        onChange="dojo.byId('oc3').value=''+arguments[0]"
+					tooltipPosition="above, below"
+                                >
+				onChange:<input id="oc3" size="14" disabled value="not fired yet!" autocomplete="off">
+				<nobr>
+				<button id="q03_valid" type=button onclick="dijit.byId('q03').set('value', 120);">set value to 120</button>
+				<button id="q03_outofrange" type=button onclick="dijit.byId('q03').set('value', 121);">set value to 121</button>
+				<button id="q03_invalid" type=button onclick="dijit.byId('q03').set('value', 'two');">set value to two</button>
+				<button id="q03_null" type=button onclick="dijit.byId('q03').set('value', null);">set value to null</button>
+				<button type=button onclick="dojo.byId('gv3').value=''+dijit.byId('q03').get('value');">get value</button>
+				<input id="gv3" size="10" disabled value="" autocomplete="off">
+				</nobr>
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="fav">Favorite Number (1-100):  </label>
+				<span class="noticeMessage"> NumberTextBox class, Attributes: required=true, must be integer, no messages provided,  no initial value specified, maxlength=3</span>
+			</div>
+			<div class="testExample">
+				<input id="fav" type="text" name="fav" class="small"
+					dojoType="dijit.form.NumberTextBox"
+					maxLength="3"
+					constraints="{places:0,min:1,max:100}"
+					regExpGen="return '\\d+'"
+					required="true">
+					<button onclick="dijit.byId('fav').set('required', true); return false;">attr(required, true)</button>
+					<button onclick="dijit.byId('fav').set('required', false); return false;">attr(required, false)</button>
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q04">Occupation:  </label>
+				<span class="noticeMessage">ValidationTextBox class,
+					Attributes: {lowercase: true, required: true, class: verylong, style: font-size: 15pt;}. Displays a prompt message if field is blank.</span>
+			</div>
+			<div class="testExample">
+				<input id="q04" type="text" name="occupation" class="verylong" style="font-size:15pt;"
+					dojoType="dijit.form.ValidationTextBox"
+					lowercase="true"
+					required="true"
+					promptMessage="Enter an occupation" />
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q05">Elevation:  </label>
+				<span class="noticeMessage">IntegerTextBox class,
+					Attributes: {required: true, min:-20000, max:+20000 }, displays a prompt message if field is blank, thousands separator remains during editing.</span>
+				<span calss="noticeMessage">Enter feet above sea level with a sign.</span>
+			</div>
+			<div class="testExample">
+				<input id="q05" class="small"/>
+				onChange:<input id="oc5" size="10" disabled value="not fired yet!" autocomplete="off">
+			</div>
+<script>
+	// See if we can make a widget in script and attach it to the DOM ourselves.
+	dojo.addOnLoad(function(){
+		var props = {
+			name: "elevation",
+			value: 3000,
+			constraints: {min:-20000,max:20000,places:0},
+			promptMessage: "Enter a value between -20000 and +20000",
+			required: true,
+			editOptions:{pattern:'#,##0'},
+			invalidMessage: "Invalid elevation.",
+			onChange: function(){dojo.byId('oc5').value=arguments[0]},
+			"class": "medium"
+		};
+		var w = new dijit.form.NumberTextBox(props, "q05");
+	});
+</script>
+<!--
+			<div class="dojoTitlePaneLabel">
+				<label for="attach-here">Population:  </label>
+				<span class="noticeMessage">IntegerTextBox class,
+					Attributes: {trim: true, required: true, signed: false, separator: ","}. <br><b> This widget was added in script, not markup. </b> </span>
+			</div>
+			<div class="testExample" >
+				<input id="attach-here" type="text" name="population" class="medium" value="1500000"/>
+			</div>
+
+			<script>
+				// See if we can make a widget in script and attach it to the DOM ourselves.
+				dojo.addOnLoad(function(){
+					var props = {
+						name: "population",
+						value: "1,500,000",
+						trim: "true",
+						required: "true",
+						regExpGen: dojo.regexp.integer,
+						constraints: {signed:false, separator: ","},
+						invalidMessage: "Invalid population.  Enter a number."
+					};
+					var w = new dijit.form.ValidationTextBox(props, "attach-here");
+					});
+			</script>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q06">Real Number:  </label>
+				<span class="noticeMessage">RealNumberTextBox class,
+					Attributes: {trim: true, required: true}. Enter any sort of real number.</span>
+			</div>
+			<div class="testExample">
+				<input id="q06" type="text" name="real1" class="medium" value="+0.1234"
+					dojoType="dijit.form.ValidationTextBox"
+					regExpGen="dojo.regexp.realNumber"
+					trim="true"
+					required="true"
+					invalidMessage="This is not a valid real number." />
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<label for="q07">Exponential Notation:  </label>
+				<span class="noticeMessage">RealNumberTextBox class,
+					Attributes: {exponent: true}. Enter a real number in exponential notation.</span>
+			</div>
+			<div class="testExample">
+				<input id="q07" type="text" name="real2" class="medium" value="+0.12"
+					dojoType="dijit.form.ValidationTextBox"
+					regExpGen="dojo.regexp.realNumber"
+					trim="true"
+					required="true"
+					constraints="{exponent:true}"
+					invalidMessage="Number must be in exponential notation. Example +5E-28" />
+			</div>
+			-->
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q08">Annual Income:  </label>
+				<span class="noticeMessage">CurrencyTextBox class,
+					Attributes: {fractional: true}.  Enter whole and cents.  Currency symbol is optional. Cents are MANDATORY.</span>
+			</div>
+
+			<div class="testExample">
+				<input id="q08" type="text" name="income1" class="medium" value="54775.53"
+					dojoType="dijit.form.CurrencyTextBox"
+					required="true"
+					constraints="{fractional:true}"
+					currency="USD"
+				        onChange="dojo.byId('oc8').value=arguments[0]"
+					invalidMessage="Invalid amount.  Cents are MANDATORY." />USD
+				 onChange:<input id="oc8" size="15" disabled value="not fired yet!" autocomplete="off">
+			</div>
+
+			<div class="testExample">
+				euro currency (local format) fractional part is optional:
+				<input id="q08eur" type="text" name="income2"
+					class="medium" value="54775.53"
+					dojoType="dijit.form.CurrencyTextBox"
+					required="true"
+					currency="EUR"
+					invalidMessage="Invalid amount.  Include cents." />EUR
+				<button onclick="dijit.byId('q08eur').set('disabled',true); return false;">Disable</button>
+				<button onclick="dijit.byId('q08eur').set('disabled',false); return false;">Enable</button>
+				<button onclick="dijit.byId('q08eur').reset(); return false;">Reset</button>
+			</div>
+
+			<!--
+				It is unusual to override the lang properties on individual
+				widgets.  Usually it should be the user's default or set on
+				a page basis by the server.  This is for testing purposes
+			-->
+			<div class="testExample">
+				euro currency (fixed lang: de-de) programmatically created, fractional part is optional: <input id="q08eurde" class="medium"/>EUR
+			</div>
+
+			<script>
+				// See if we can make a widget in script and attach it
+				// to the DOM ourselves.
+				dojo.addOnLoad(function(){
+					var example = dojo.currency.format(54775.53, {locale: 'de-de', currency: "EUR"});
+					var props = {
+						name: "income3",
+						value: 54775.53,
+						lang: 'de-de',
+						required: true,
+						currency: "EUR",
+						invalidMessage: "Invalid amount.  Example: " + example
+					};
+					var w = new dijit.form.CurrencyTextBox(props, "q08eurde");
+				});
+			</script>
+
+			<!--
+			<div class="dojoTitlePaneLabel">
+				<label for="q08a">Annual Income:  </label>
+				<span class="noticeMessage">Old regexp currency textbox,
+							Attributes: {fractional: true}. Enter dollars and cents.</span>
+			</div>
+			<div class="testExample">
+				<input id="q08a" type="text" name="income3" class="medium" value="$54,775.53"
+					dojoType="dijit.form.ValidationTextBox"
+					regExpGen="dojo.regexp.currency"
+					trim="true"
+					required="true"
+					constraints="{fractional:true}"
+					invalidMessage="Invalid amount.  Include cents. Example: $12,000.00" />
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q09">IPv4 Address:  </label>
+				<span class="noticeMessage">IpAddressTextBox class,
+					Attributes: {allowIPv6: false, allowHybrid: false}. Also Dotted Hex works, 0x18.0x11.0x9b.0x28</span>
+			</div>
+			<div class="testExample">
+				<input id="q09" type="text" name="ipv4" class="medium" value="24.17.155.40"
+					dojoType="dijit.form.ValidationTextBox"
+					regExpGen="dojo.regexp.ipAddress"
+					trim="true"
+					required="true"
+					constraints="{allowIPv6:false,allowHybrid:false}"
+					invalidMessage="Invalid IPv4 address.">
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q10"> IPv6 Address:  </label>
+				<span class="noticeMessage">IpAddressTextBox class,
+					Attributes: {allowDottedDecimal: false, allowDottedHex: false}.
+							Also hybrid works, x:x:x:x:x:x:d.d.d.d</span>
+			</div>
+			<div class="testExample">
+				<input id="q10" type="text" name="ipv6" class="long" value="0000:0000:0000:0000:0000:0000:0000:0000"
+					dojoType="dijit.form.ValidationTextBox"
+					regExpGen="dojo.regexp.ipAddress"
+					trim="true"
+					uppercase = "true"
+					required="true"
+					constraints="{allowDottedDecimal:false, allowDottedHex:false, allowDottedOctal:false}"
+					invalidMessage="Invalid IPv6 address, please enter eight groups of four hexadecimal digits. x:x:x:x:x:x:x:x">
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q11"> URL:  </label>
+				<span class="noticeMessage">UrlTextBox class,
+					Attributes: {required: true, trim: true, scheme: true}. </span>
+			</div>
+
+			<div class="testExample">
+				<input id="q11" type="text" name="url" class="long" value="http://www.xyz.com/a/b/c?x=2#p3"
+					dojoType="dijit.form.ValidationTextBox"
+					regExpGen="dojo.regexp.url"
+					trim="true"
+					required="true"
+					constraints="{scheme:true}"
+					invalidMessage="Invalid URL.  Be sure to include the scheme, http://..." />
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q12"> Email Address  </label>
+				<span class="noticeMessage">EmailTextBox class,
+					Attributes: {required: true, trim: true}. </span>
+			</div>
+
+			<div class="testExample">
+				<input id="q12" type="text" name="email" class="long" value="fred&barney at stonehenge.com"
+					dojoType="dijit.form.ValidationTextBox"
+					regExpGen="dojo.regexp.emailAddress"
+					trim="true"
+					required="true"
+					invalidMessage="Invalid Email Address." />
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q13"> Email Address List </label>
+				<span class="noticeMessage">EmailListTextBox class,
+					Attributes: {required: true, trim: true}. </span>
+			</div>
+
+			<div class="testExample">
+				<input id="q13" type="text" name="email" class="long" value="a at xyz.com; b at xyz.com; c at xyz.com; "
+					dojoType="dijit.form.ValidationTextBox"
+					regExpGen="dojo.regexp.emailAddressList"
+					trim="true"
+					required="true"
+					invalidMessage="Invalid Email Address List." />
+			</div>
+			-->
+			<div class="dojoTitlePaneLabel">
+				<label for="q22">Regular Expression </label>
+				<span class="noticeMessage">RegexpTextBox class,
+					Attributes: {required: true} </span>
+			</div>
+			<div class="testExample">
+				<input id="q22" type="text" name="phone" class="medium" value="someTestString"
+					dojoType="dijit.form.ValidationTextBox"
+					regExp="[\w]+"
+					required="true"
+					invalidMessage="Invalid Non-Space Text.">
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q23"> Password </label>
+				<span class="noticeMessage">(just a test that type attribute is obeyed) </span>
+			</div>
+			<div class="testExample">
+				<input id="q23" type="password" name="password" class="medium"
+					dojoType="dijit.form.TextBox">
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="ticket1651">Trac ticket 1651:  </label>
+				<span class="noticeMessage">value: null should show up as empty</span>
+			</div>
+			<div class="testExample">
+				<input id="ticket1651" class="medium" value="not null"/>
+			</div>
+
+			<script>
+					// See if we can make a widget in script and attach it to the DOM ourselves.
+					dojo.addOnLoad(function(){
+							var props = {
+									name: "ticket1651",
+									id: "mname",
+									value: null
+							};
+							var w = new dijit.form.TextBox(props, "ticket1651");
+					});
+			</script>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q24">initially readOnly TextBox</label>
+				<span class="noticeMessage">a test that readOnly and disabled are understood for TextBox</span>
+			</div>
+			<div class="testExample">
+				<input id="q24" type="text" name="readOnly" class="medium" readOnly value="cannot type here"
+					dojoType="dijit.form.TextBox">
+				<input type="button" id="removereadonly" onclick="dijit.byId('q24').set('readOnly',false);" value="Remove readOnly" tabIndex="-1">
+				<input type="button" onclick="dijit.byId('q24').set('readOnly',true);" value="Set readOnly" tabIndex="-1">
+				<input type="button" id="removedisabled" onclick="dijit.byId('q24').set('disabled',false);" value="Remove disabled" tabIndex="-1">
+				<input type="button" onclick="dijit.byId('q24').set('disabled',true);" value="Set disabled" tabIndex="-1">
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<label for="q25">initially disabled ValidationTextBox</label>
+				<span class="noticeMessage">a test that disabled is understood for ValidationTextBox</span>
+			</div>
+			<div class="testExample">
+				<input id="q25" type="text" name="disabled" class="medium" disabled value="cannot type here"
+					dojoType="dijit.form.ValidationTextBox">
+				<input type="button" onclick="dijit.byId('q25').set('readOnly',false);" value="Remove readOnly" tabIndex="-1">
+				<input type="button" onclick="dijit.byId('q25').set('readOnly',true);" value="Set readOnly" tabIndex="-1">
+				<input type="button" onclick="dijit.byId('q25').set('disabled',false);" value="Remove disabled" tabIndex="-1">
+				<input type="button" onclick="dijit.byId('q25').set('disabled',true);" value="Set disabled" tabIndex="-1">
+			</div>
+
+		        <script>
+				// so robot can get to it easily
+				document.displayData=function() {
+					var f = document.getElementById("form1");
+					var s = "";
+					for (var i = 0; i < f.elements.length; i++) {
+						var elem = f.elements[i];
+						if (elem.nodeName.toLowerCase() == "button" || elem.type=="submit" || elem.type=="button")  { continue; }
+						s += elem.name + ": " + elem.value + "\n";
+					}
+					return s;
+				}
+		        </script>
+
+			<div>
+				<button name="button" onclick="alert(document.displayData()); return false;" tabIndex="-1">view data</button>
+				<input type="submit" name="submit"  tabIndex="-1"/>
+			</div>
+
+		</form>
+		<div class="dojoTitlePaneLabel">
+				<label for="q26">TextBox with placeholder</label>
+				<span class="noticeMessage">a test that placeholder works for TextBox.  10px padding added for testing.</span>
+		</div>
+		<div class="testExample">
+			<input id="q26" type="text" placeHolder="placeholder is here" name="placeHolder" value=""
+						dojoType="dijit.form.TextBox">
+		</div>
+		<h2>Tooltip positioning</h2>
+		<p>
+		These buttons switch the positions searched to try to place the validation error tooltips.
+		Note that setting tooltip positioning to "above" or "below" is dangerous if
+		you have a node with a dropdown, but the drop down might overlap the tooltip.
+		</p>
+		<button onclick="dijit.Tooltip.defaultPosition=['above', 'below'];">above, below</button>
+		<button onclick="dijit.Tooltip.defaultPosition=['after', 'before'];">after, before (default)</button>
+	</body>
+</html>
diff --git a/dijit/tests/form/test_validationState.html b/dijit/tests/form/test_validationState.html
new file mode 100644
index 0000000..405f979
--- /dev/null
+++ b/dijit/tests/form/test_validationState.html
@@ -0,0 +1,102 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Test Form Validation State</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true, extraLocale: ['de-de', 'en-us']"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.form.ValidationTextBox");
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.form.FilteringSelect");
+			dojo.require("dijit.form.Form");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+		</script>
+	</head>
+
+	<body class="claro">
+		<h1 class="testTitle">Dijit Validation State</h1>
+		<form dojoType="dijit.form.Form" id="form1" action="" name="example" method="">
+			<table>
+				<tr>
+					<td><label for="name">Name:</label></td>
+					<td><input id="name" dojoType="dijit.form.ValidationTextBox"
+						required="true" name="name" /></td>
+				</tr>
+				<tr id="newRow" style="display: none;">
+					<td><label for="lastName">Last Name:</label></td>
+					<td><input id="lastName" /></td>
+				</tr>
+				<tr>
+					<td><label for="birth">Birthdate (before 2006-12-31):</label></td>
+					<td><div><input id="birth" dojoType="dijit.form.DateTextBox" value="2000-01-01"
+						required="true" name="birth" constraints="{min:'1900-01-01', max:'2006-12-31'}" />
+					<button onclick="dijit.byId('birth').set('disabled',true);return false">Disable</button>
+					<button onclick="dijit.byId('birth').set('disabled',false);return false">Enable</button>
+					<button onclick="dijit.byId('birth').reset();return false">Reset</button>
+					</div></td>
+				</tr>
+				<tr>
+					<td><label for="notes">Notes (optional)</label></td>
+					<td><input id="notes" dojoType="dijit.form.TextBox"
+						name="notes" /></td>
+				</tr>
+				<tr id="newRow2" style="display: none;">
+					<td><label for="color">Favorite Color</label></td>
+					<td><select id="color">
+						<option value="red">Red</option>
+						<option value="yellow">Yellow</option>
+						<option value="blue">Blue</option>
+					</select></td>
+				</tr>
+			</table>
+			<button dojoType="dijit.form.Button">
+				<script type="dojo/method" event="onClick">
+					console.dir(dijit.byId("form1").get('value'));
+				</script>
+				<script type="dojo/method" event="startup">
+					var form = dijit.byId("form1");
+					//  set initial state
+					this.set("disabled", !form.isValid());
+					this.connect(form, "onValidStateChange", function(state){
+							this.set("disabled", !state);
+					});
+				</script>
+				Submit
+			</button>
+			<button dojoType="dijit.form.Button">
+				<script type="dojo/method" event="onClick">
+					new dijit.form.FilteringSelect({name: "color",
+													required: true},
+													dojo.byId("color"));
+					new dijit.form.ValidationTextBox({name: "lastName",
+													required: true},
+													dojo.byId("lastName"));
+					dojo.byId("newRow").style.display = "";
+					dojo.byId("newRow2").style.display = "";
+					this.set("disabled", true);
+					this.domNode.blur();
+					// Call this, since we added a new widget - so that our
+					// form knows that we have something else to watch.
+					dijit.byId("form1").connectChildren();
+				</script>
+				Add More Fields
+			</button>
+		</form>
+	</body>
+</html>
diff --git a/dijit/tests/formAction.html b/dijit/tests/formAction.html
new file mode 100644
index 0000000..319893d
--- /dev/null
+++ b/dijit/tests/formAction.html
@@ -0,0 +1,26 @@
+<html>
+<!-- form submit page that grabs the parameters from the URL and calls javascript with an array -->
+<head>
+<script type='text/javascript'>
+	var values = {};
+	var win = frameElement.ownerDocument.defaultView||frameElement.document.parentWindow;
+        var str = window.location.search.substr(1).replace(/[%]0D/g, "").replace(/[+]/g, " ").split(/&/);
+        for(var i=0; i<str.length; i++){
+                var split = str[i].split(/=/),
+                        key = unescape(split[0] || ''),
+                        value = unescape(split[1] || '');
+		if(values[key] === undefined){
+			values[key] = value;
+		}else if(values[key] instanceof Array || typeof values[key] == "array"){
+			values[key].push(value);
+		}else{
+			var old = values[key];
+			values[key] = [old, value];
+		}
+        }
+	frameElement.values = values;
+</script>
+</head>
+<body onload="setTimeout(function(){ frameElement.values = null; window.location.href='about:blank' }, 0)">
+</body>
+</html>
diff --git a/dijit/tests/general-module.js b/dijit/tests/general-module.js
new file mode 100644
index 0000000..7e57f72
--- /dev/null
+++ b/dijit/tests/general-module.js
@@ -0,0 +1,29 @@
+dojo.provide("dijit.tests.general-module");
+
+try{
+	var userArgs = window.location.search.replace(/[\?&](dojoUrl|testUrl|testModule)=[^&]*/g,"").replace(/^&/,"?");
+
+	// top level widget tests
+	doh.registerUrl("dijit.tests.robot.Menu_mouse", dojo.moduleUrl("dijit","tests/robot/Menu_mouse.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.robot.Menu_a11y", dojo.moduleUrl("dijit","tests/robot/Menu_a11y.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.robot.Dialog_mouse", dojo.moduleUrl("dijit","tests/robot/Dialog_mouse.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.robot.Dialog_a11y", dojo.moduleUrl("dijit","tests/robot/Dialog_a11y.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.robot.Tooltip_mouse", dojo.moduleUrl("dijit","tests/robot/Tooltip_mouse.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.robot.Tooltip_a11y", dojo.moduleUrl("dijit","tests/robot/Tooltip_a11y.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.robot.TooltipDialog_mouse", dojo.moduleUrl("dijit","tests/robot/TooltipDialog_mouse.html"+userArgs), 99999999);
+	doh.registerUrl("dijit.tests.robot.TooltipDialog_a11y", dojo.moduleUrl("dijit","tests/robot/TooltipDialog_a11y.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.robot.InlineEditBox", dojo.moduleUrl("dijit","tests/robot/InlineEditBox.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.robot.ColorPalette", dojo.moduleUrl("dijit","tests/robot/ColorPalette.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.robot.TitlePane", dojo.moduleUrl("dijit","tests/robot/TitlePane.html"+userArgs), 99999999);
+
+	doh.registerUrl("dijit.tests.robot.Toolbar", dojo.moduleUrl("dijit","tests/robot/Toolbar.html"+userArgs), 99999999);
+
+}catch(e){
+	doh.debug(e);
+}
\ No newline at end of file
diff --git a/dijit/tests/helpers.js b/dijit/tests/helpers.js
new file mode 100644
index 0000000..297aaad
--- /dev/null
+++ b/dijit/tests/helpers.js
@@ -0,0 +1,19 @@
+// Helper methods for automated testing
+
+function isVisible(node){
+		if(node.domNode){ node = node.domNode; }
+		return (dojo.style(node, "display") != "none") &&
+				(dojo.style(node, "visibility") != "hidden") &&
+				(dojo.position(node).y + (dojo._getBorderExtents(node).t || 0) >= 0); // border check is for claro prone to shifting the border offscreen
+}
+
+function isHidden(node){
+		if(node.domNode){ node = node.domNode; }
+		return (dojo.style(node, "display") == "none") ||
+				(dojo.style(node, "visibility") == "hidden") ||
+				(dojo.position(node).y < 0); // + dojo.position(node).h ??
+}
+
+function innerText(node){
+	return node.textContent || node.innerText || "";
+}
diff --git a/dijit/tests/i18n/README b/dijit/tests/i18n/README
new file mode 100644
index 0000000..a6516b6
--- /dev/null
+++ b/dijit/tests/i18n/README
@@ -0,0 +1,4 @@
+Global Verification Tests (GVT)
+
+In order to run these tests, you will need full locale support in Dojo.  Dojo only ships with a small subset by default.
+See util/buildscripts/cldr for an ant-based build script.
diff --git a/dijit/tests/i18n/calendar.html b/dijit/tests/i18n/calendar.html
new file mode 100644
index 0000000..cf2e855
--- /dev/null
+++ b/dijit/tests/i18n/calendar.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Calendar Widget Test</title>
+
+		<!-- for tests -->
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+		</style>
+
+		<!-- required: a default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js.
+			Explicitly include extra locales because this example has multiple locales
+			on the page besides the browser's default.  -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="parseOnLoad: true, isDebug: true, extraLocale: ['en-us', 'ar-sy', 'es-es', 'zh-cn']"></script>
+
+		<!-- not needed, for testing alternate themes -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.Calendar");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.parser"); // scan page for widgets
+
+			dojo.addOnLoad(function(){
+				//Need to declare BigCalendar here in an addOnLoad block so that it works
+				//with xdomain loading, where the dojo.require for dijit.Calendar
+				//may load asynchronously. This also means we cannot have HTML
+				//markup in the body tag for BigCalendar, but instead inject it in this
+				//onload handler after BigCalendar is defined.
+				dojo.declare("BigCalendar", dijit.Calendar, {
+					templateString: dojo.cache("dijit", "tests/_altCalendar.html"),
+					isDisabledDate: dojo.date.locale.isWeekend,
+					getClassForDate: function(date){
+						if(!(date.getDate() % 10)){ return "blue"; } // apply special style to all days divisible by 10
+					}
+				});
+
+				var bigCalendar = dojo.byId("calendar5");
+				bigCalendar.setAttribute("dojoType", "BigCalendar");
+				dojo.parser.parse(bigCalendar.parentNode);
+			});
+
+			function myHandler(id,newValue){
+				console.debug("onChange for id = " + id + ", value: " + newValue);
+			}
+		</script>
+	</head>
+	<body class="claro">
+
+		<h1 class="testTitle">Dijit Calendar Test</h1>
+
+		before
+		<input id="calendar1" dojoType="dijit.Calendar" onChange="myHandler(this.id,arguments[0])" lang="en-us">
+		<input id="calendar2" dojoType="dijit.Calendar" onChange="myHandler(this.id,arguments[0])" lang="es-es">
+		<input id="calendar3" dojoType="dijit.Calendar" onChange="myHandler(this.id,arguments[0])" lang="zh-cn">
+		<input id="calendar4" dojoType="dijit.Calendar" onChange="myHandler(this.id,arguments[0])" lang="ar-sy">
+		after
+		<p>
+			<a href="#"
+			   onClick="for(var i=1; i!=5; i++){
+						var c = dijit.byId('calendar'+i);
+						c.isDisabledDate=dojo.date.locale.isWeekend;
+						c._populateGrid();
+					}
+				">disable weekends</a>
+		</p>
+
+		<p>Customized template with "today" button</p>
+		<style>
+			#calendar5 .dijitCalendarDateTemplate { height: 50px; width: 50px; border: 1px solid #ccc; vertical-align: top }
+			#calendar5 .dijitCalendarDateLabel, #calendar5 .dijitCalendarDateTemplate { text-align: inherit }
+			#calendar5 .dijitCalendarDayLabel { font-weight: bold }
+			#calendar5 .dijitCalendarSelectedYear { font-size: 1.5em }
+			#calendar5 .dijitCalendarMonth { font-family: serif; letter-spacing: 0.2em; font-size: 2em }
+			.blue { color: blue }
+		</style>
+		<div>
+			<!-- Parent div used so we have a handle to use for dojo.parser.parse after BigCalendar gets defined. -->
+			<!-- The input below will be replaced by BigCalendar which is defined in a dojo.addOnLoad block. -->
+			<input id="calendar5" dayWidth="abbr" value="2008-03-15">
+		</div>
+<!--
+		<input id="calendar5" dojoType="dijit.Calendar" dayWidth="abbr" templatePath="../dijit/tests/_altCalendar.html" value="2008-03-15">
+ -->
+	</body>
+</html>
diff --git a/dijit/tests/i18n/currency.html b/dijit/tests/i18n/currency.html
new file mode 100644
index 0000000..ca73528
--- /dev/null
+++ b/dijit/tests/i18n/currency.html
@@ -0,0 +1,211 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>Test CurrencyTextBox</title>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, extraLocale: ['zh-cn','fr-fr','ja-jp']"></script>
+		<script type="text/javascript" src="../../../dojo/currency.js"></script>
+		<script type="text/javascript" src="../../../dojo/number.js"></script>
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.NumberTextBox");
+			dojo.require("dijit.form.CurrencyTextBox");
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dijit.form.ValidationTextBox");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.date.stamp");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+			dojo.require("doh.runner");
+		</script>
+		<script src="test_i18n.js"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				doh.register("t", getAllTestCases());
+				doh.run();
+			});
+		</script>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../themes/tundra/tundra.css";
+			@import "../css/dijitTests.css";
+
+			.title {
+				background-color:#ddd;
+			}
+
+			.hint {
+				background-color:#eee;
+			}
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+
+			td {white-space:nowrap}
+		</style>
+	</head>
+
+	<body class="claro">
+		<h1 class="testTitle">Dijit TextBox Globalization Test for Currency</h1>
+
+<!--		<h2 class="testTitle">Press the following button to start all test after this page is loaded.</h2>
+ 		<button id="startButton" onclick="startTest()">Start Test</button> -->
+		<p>
+			Before start this test, make sure the <b>dojo/cldr/nls</b> contains the data for "zh-cn", "fr-fr", and "ja-jp"
+			and currencies CNY, EGP, EUR, JPY. If not, convert these CLDR data and put them there.
+		</p>
+
+		<script>
+		(function() {
+			genFormatTestCases("Currency Format", "dijit.form.CurrencyTextBox", [
+
+				{ attrs: {Currency: "CNY", lang: "zh-cn"},
+				  desc: "Locale: <b>zh_CN</b> Currency: <b>CNY</b>",
+				  value: "123456789.46",
+				  expValue: "&#xFFE5;123,456,789.46",
+				  comment: ""
+				},
+				{ attrs: {Currency: "CNY", lang: "zh-cn"},
+				  desc: "Locale: <b>zh_CN</b> Currency: <b>CNY</b>",
+				  value: "-123456789.46",
+				  expValue: "-&#xFFE5;123,456,789.46",
+				  comment: ""
+				},
+
+				{ attrs: {Currency: "EUR", lang: "fr-fr"},
+				  desc: "Locale: <b>fr_FR</b> Currency: <b>EUR</b>",
+				  value: "123456789.46",
+				  expValue: "123 456 789,46 €",
+				  comment: ""
+				},
+				{ attrs: {Currency: "EUR", lang: "fr-fr"},
+				  desc: "Locale: <b>zh_CN</b> Currency: <b>EUR</b>",
+				  value: "-123456789.46",
+				  expValue: "-123 456 789,46 €",
+				  comment: ""
+				},
+
+				{ attrs: {Currency: "JPY", lang: "ja-jp"},
+				  desc: "Locale: <b>ja_JP</b> Currency: <b>JPY</b>",
+				  value: "123456789.46",
+				  expValue: "&#xFFE5;123,456,789",
+				  comment: ""
+				},
+				{ attrs: {Currency: "JPY", lang: "ja-jp"},
+				  desc: "Locale: <b>ja_JP</b> Currency: <b>JPY</b>",
+				  value: "-123456789.46",
+				  expValue: "-&#xFFE5;123,456,789",
+				  comment: ""
+				}
+			]);
+
+			genValidateTestCases("Currency Validate", "dijit.form.CurrencyTextBox", [
+
+				{ attrs: {Currency: "CNY", lang: "zh-cn"},
+				  desc: "Locale: <b>zh_CN</b> Currency: <b>CNY</b>",
+				  value: 123456789.46,
+				  expValue: "&#xFFE5;123,456,789.46",
+				  comment: ""
+				},
+				{ attrs: {Currency: "CNY", lang: "zh-cn"},
+				  desc: "Locale: <b>zh_CN</b> Currency: <b>CNY</b>",
+				  value: -123456789.46,
+				  expValue: "-&#xFFE5;123,456,789.46",
+				  comment: ""
+				},
+
+				{ attrs: {Currency: "EUR", lang: "fr-fr"},
+				  desc: "Locale: <b>fr_FR</b> Currency: <b>EUR</b>",
+				  value: 123456789.46,
+				  expValue: "123 456 789,46 €",
+				  comment: ""
+				},
+				{ attrs: {Currency: "EUR", lang: "fr-fr"},
+				  desc: "Locale: <b>zh_CN</b> Currency: <b>EUR</b>",
+				  value: -123456789.46,
+				  expValue: "-123 456 789,46 €",
+				  comment: ""
+				},
+
+				{ attrs: {Currency: "JPY", lang: "ja-jp"},
+				  desc: "Locale: <b>ja_JP</b> Currency: <b>JPY</b>",
+				  value: 123456789,
+				  expValue: "&#xFFE5;123,456,789",
+				  comment: ""
+				},
+				{ attrs: {Currency: "JPY", lang: "ja-jp"},
+				  desc: "Locale: <b>ja_JP</b> Currency: <b>JPY</b>",
+				  value: -123456789,
+				  expValue: "-&#xFFE5;123,456,789",
+				  comment: ""
+				}
+			]);
+
+			dojo.parser.parse();
+
+		})();
+
+		</script>
+
+		<h2 class="testTitle">Issues & Comments</h2>
+		<h3 class="testTitle"><a name="cmt_1">Issue #1<sup style="color:blue">Fixed</sup></a></h3>
+		<p>
+			Some browsers like FireFox have a bug on the non-breaking space character (U+00A0, <b>&nbsp;</b> or <b>&#160;</b> or
+			<b>&#xA0;</b> in HTML).
+			They always convert the NBSP character to a normal space (U+0020, <b>&#x20;</b> in HTML) automatically in the following circumstances:
+        </p>
+		<ul>
+			<li>Copy text from the page</li>
+			<li>Use <b>innerHTML</b> to get the content of a certain element</li>
+			<li>Use <b>value</b> to get an <b>INPUT</b> element's value</li>
+		</ul>
+
+		<p>
+			You cannot read a real NBSP character from an <b>INPUT</b> element on these browsers. It causes issues when some formatting data in CLDR
+			contains an NBSP character. For example,
+		</p>
+		<ul>
+			<li>Many locales like French use an NBSP character as a group separator in numbers</li>
+			<li>French and Finnish use NBSP characters in their percentage and currency format patterns respectively</li>
+		</ul>
+
+		<p>
+			So Dojo may generate formatted data with NBSP characters in it but cannot read NBSP charaters from user's input in some browser.
+		</p>
+
+		<h3 class="testTitle"><a name="cmt_2">Issue #2<sup style="color:blue">Fixed: the CLDR data generator should be fixed by adding code to convert U+200F to "\u200F" in nls JS files.</sup></a></h3>
+		<p>
+			Most Bidi currency symbols contain an LTR-MARK (U+200F) character at the very beginning.
+			But Firefox ignores it when it is not in any escaping form. This should be a bug of Firefox.
+			For example, click <a href="javascript:alert('‏'.indexOf('\u200F'))"><code>alert('‏'.indexOf('\u+200F'))</code></a> (there is a U+200F in the empty-looking string):
+		</p>
+		<ul>
+			<li>In Firefox, shows "-1" -- no U+200F found</li>
+			<li>In IE & Opera, shows "0" -- the U+200F is found</li>
+		</ul>
+		<p>
+			But if the U+200F is in some escaping form, Firefox will work as well as other browsers.
+			Click <a href="javascript:alert('\u200F'.indexOf('\u200F'))"><code>alert('\u200F'.indexOf('\u+200F'))</code></a> to see the same result both in Firefox and IE:
+		</p>
+
+
+		<h3 class="testTitle"><a name="cmt_3">Issue #3<sup style="color:blue">Fixed: added a "localeDigit" to the options</sup></a></h3>
+		<p>
+			Strictly speaking, the data conversion must support non-European number characters in some locales like Arabic and Hindi.
+			For example, ICU formats a number data into Indic number characters by default in the Arabic locale.
+			However, currently Dojo does not support this feature (Dojo uses the default number conversion of the browser).
+		</p>
+
+	</body>
+</html>
diff --git a/dijit/tests/i18n/date.html b/dijit/tests/i18n/date.html
new file mode 100644
index 0000000..6b3354f
--- /dev/null
+++ b/dijit/tests/i18n/date.html
@@ -0,0 +1,156 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>Test DateTextBox</title>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, extraLocale: ['zh-cn','fr-fr','ja-jp','ru-ru','en-us','de-de','es-es','it-it','pt-br','ko-kr','zh-tw']"></script>
+		<script type="text/javascript" src="../../../dojo/currency.js"></script>
+		<script type="text/javascript" src="../../../dojo/number.js"></script>
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.NumberTextBox");
+			dojo.require("dijit.form.CurrencyTextBox");
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dijit.form.ValidationTextBox");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.date.stamp");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+			dojo.require("doh.runner");
+		</script>
+		<script src="test_i18n.js"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				doh.register("t", getAllTestCases());
+				doh.run();
+			});
+		</script>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../themes/tundra/tundra.css";
+			@import "../css/dijitTests.css";
+
+			.title {
+				background-color:#ddd;
+			}
+
+			.hint {
+				background-color:#eee;
+			}
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+
+			td {white-space:nowrap}
+		</style>
+		<script>
+			function gen4DateFormat(testCases, language, locale, date, short, shortCmt, medium, mediumCmt, long, longCmt, full, fullCmt) {
+				testCases.push({
+				  attrs: {constraints: "{formatLength:'short'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Short</b>",
+				  value: date,
+				  expValue: short,
+				  comment: shortCmt
+				});
+				testCases.push({
+				  attrs: {constraints: "{formatLength:'medium'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Medium</b>",
+				  value: date,
+				  expValue: medium,
+				  comment: mediumCmt
+				});
+				testCases.push({
+				  attrs: {constraints: "{formatLength:'long'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Long</b>",
+				  value: date,
+				  expValue: long,
+				  comment: longCmt
+				});
+				testCases.push({
+				  attrs: {constraints: "{formatLength:'full'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Full</b>",
+				  value: date,
+				  expValue: full,
+				  comment: fullCmt
+				});
+			}
+		</script>
+	</head>
+
+	<body class="claro">
+		<h1 class="testTitle">Dijit TextBox Globalization Test for Date</h1>
+
+<!--		<h2 class="testTitle">Press the following button to start all test after this page is loaded.</h2>
+		<button id="startButton" onclick="startTest()">Start Test</button>-->
+		<p>
+			Before start this test, make sure the <b>dojo/cldr/nls</b> contains the data for "zh-cn", "fr-fr", "ja-jp", "ru-ru", "hi-in", "en-us" and "ar-eg". If not, convert these CLDR data and put them there.
+		</p>
+
+		<script>
+		(function() {
+			var testCases = [];
+			gen4DateFormat(testCases, "ru-ru", "ru_RU", "2005-07-31",
+				"31.07.05", "", "31.07.2005", "", "31 июля 2005 г.", "Failed in Firefox. <a href='currency.html#cmt_1'>See #1 (currency.html).</a>", "31 июля 2005 г.", "Failed in Firefox. <a href='currency.html#cmt_1'>See #1 (currency.html).</a>");
+			gen4DateFormat(testCases, "zh-cn", "zh_CN", "2005-07-31",
+				"05-7-31", "", "2005-7-31", "", "2005年7月31日", "", "2005年7月31日星期日", "");
+			gen4DateFormat(testCases, "en-us", "en_US", "2005-07-31",
+				"7/31/05", "", "Jul 31, 2005", "", "July 31, 2005", "", "Sunday, July 31, 2005", "");
+			gen4DateFormat(testCases, "fr-fr", "fr_FR", "2005-07-31",
+				"31/07/05", "", "31 juil. 2005", "", "31 juillet 2005", "", "dimanche 31 juillet 2005", "");
+			gen4DateFormat(testCases, "ja-jp", "ja_JP", "2005-07-31",
+				"05/07/31", "", "2005/07/31", "", "2005年7月31日", "", "2005年7月31日日曜日", "");
+			gen4DateFormat(testCases, "de-de", "de_DE", "2005-07-31",
+				"31.07.05", "", "31.07.2005", "", "31. Juli 2005", "", "Sonntag, 31. Juli 2005", "");
+			gen4DateFormat(testCases, "es-es", "es_ES", "2005-07-31",
+				"31/07/05", "", "31/07/2005", "", "31 de julio de 2005", "", "domingo 31 de julio de 2005", "");
+			gen4DateFormat(testCases, "pt-br", "pt-BR", "2005-07-31",
+				"31/07/05", "", "31/07/2005", "", "31 de julho de 2005", "", "domingo, 31 de julho de 2005", "");
+			gen4DateFormat(testCases, "it-it", "it-IT", "2005-07-31",
+				"31/07/05", "", "31/lug/2005", "", "31 luglio 2005", "", "domenica 31 luglio 2005", "");
+			gen4DateFormat(testCases, "ko-kr", "ko-KR", "2005-07-31",
+				"05. 7. 31.", "", "2005. 7. 31.", "", "2005년 7월 31일", "", "2005년 7월 31일 일요일", "");
+			gen4DateFormat(testCases, "zh-tw", "zh-TW", "2005-07-31",
+				"2005/7/31", "", "2005/7/31", "", "2005年7月31日", "", "2005年7月31日星期日", "");
+			genFormatTestCases("Date Format", "dijit.form.DateTextBox", testCases);
+
+			testCases = [];
+			gen4DateFormat(testCases, "ru-ru", "ru_RU", new Date(2005, 6, 31),
+				"31.07.05", "", "31.07.2005", "", "31 июля 2005 г.", "Failed in Firefox. <a href='currency.html#cmt_1'>See #1 (currency.html).</a>", "31 июля 2005 г.", "Failed in Firefox. <a href='currency.html#cmt_1'>See #1 (currency.html).</a>");
+			gen4DateFormat(testCases, "zh-cn", "zh_CN", new Date(2005, 6, 31),
+				"05-7-31", "", "2005-7-31", "", "2005年7月31日", "", "2005年7月31日星期日", "");
+			gen4DateFormat(testCases, "en-us", "en_US", new Date(2005, 6, 31),
+				"7/31/05", "", "Jul 31, 2005", "", "July 31, 2005", "", "Sunday, July 31, 2005", "");
+			gen4DateFormat(testCases, "fr-fr", "fr_FR", new Date(2005, 6, 31),
+				"31/07/05", "", "31 juil. 2005", "", "31 juillet 2005", "", "dimanche 31 juillet 2005", "");
+			gen4DateFormat(testCases, "ja-jp", "ja_JP", new Date(2005, 6, 31),
+				"05/07/31", "", "2005/07/31", "", "2005年7月31日", "", "2005年7月31日日曜日", "");
+			gen4DateFormat(testCases, "de-de", "de_DE", new Date(2005, 6, 31),
+				"31.07.05", "", "31.07.2005", "", "31. Juli 2005", "", "Sonntag, 31. Juli 2005", "");
+			gen4DateFormat(testCases, "es-es", "es_ES", new Date(2005, 6, 31),
+				"31/07/05", "", "31/07/2005", "", "31 de julio de 2005", "", "domingo 31 de julio de 2005", "");
+			gen4DateFormat(testCases, "pt-br", "pt-BR", new Date(2005, 6, 31),
+				"31/07/05", "", "31/07/2005", "", "31 de julho de 2005", "", "domingo, 31 de julho de 2005", "");
+			gen4DateFormat(testCases, "it-it", "it-IT", new Date(2005, 6, 31),
+				"31/07/05", "", "31/lug/2005", "", "31 luglio 2005", "", "domenica 31 luglio 2005", "");
+			gen4DateFormat(testCases, "ko-kr", "ko-KR", new Date(2005, 6, 31),
+				"05. 7. 31.", "", "2005. 7. 31.", "", "2005년 7월 31일", "", "2005년 7월 31일 일요일", "");
+			gen4DateFormat(testCases, "zh-tw", "zh-TW", new Date(2005, 6, 31),
+				"2005/7/31", "", "2005/7/31", "", "2005年7月31日", "", "2005年7月31日星期日", "");
+			genValidateTestCases("Date Validate", "dijit.form.DateTextBox", testCases);
+
+			dojo.parser.parse();
+		})();
+		</script>
+	</body>
+</html>
diff --git a/dijit/tests/i18n/digit.html b/dijit/tests/i18n/digit.html
new file mode 100644
index 0000000..3890100
--- /dev/null
+++ b/dijit/tests/i18n/digit.html
@@ -0,0 +1,295 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>Test Hindi/Arabic numerals</title>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, extraLocale: ['ar-eg','hi-in']"></script>
+		<script type="text/javascript" src="../../../dojo/currency.js"></script>
+		<script type="text/javascript" src="../../../dojo/number.js"></script>
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.NumberTextBox");
+			dojo.require("dijit.form.CurrencyTextBox");
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dijit.form.ValidationTextBox");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.date.stamp");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+			dojo.require("doh.runner");
+		</script>
+		<script src="test_i18n.js"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				doh.register("t", getAllTestCases());
+				doh.run();
+			});
+		</script>
+
+		<script>
+			function gen4DateFormat(testCases, language, locale, date, short, shortCmt, medium, mediumCmt, long, longCmt, full, fullCmt) {
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'short', localeDigit: true}" : "{formatLength:'short'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Short</b>",
+				  value: date,
+				  expValue: short,
+				  comment: shortCmt
+				});
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'medium', localeDigit: true}" : "{formatLength:'medium'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Medium</b>",
+				  value: date,
+				  expValue: medium,
+				  comment: mediumCmt
+				});
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'long', localeDigit: true}" : "{formatLength:'long'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Long</b>",
+				  value: date,
+				  expValue: long,
+				  comment: longCmt
+				});
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'full', localeDigit: true}" : "{formatLength:'full'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Full</b>",
+				  value: date,
+				  expValue: full,
+				  comment: fullCmt
+				});
+			}
+		</script>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../themes/tundra/tundra.css";
+			@import "../css/dijitTests.css";
+
+			.title {
+				background-color:#ddd;
+			}
+
+			.hint {
+				background-color:#eee;
+			}
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+
+			td {white-space:nowrap}
+		</style>
+	</head>
+
+	<body class="claro">
+		<h1 class="testTitle">Dijit TextBox Globalization Test for Number</h1>
+
+<!--		<h2 class="testTitle">Press the following button to start all test after this page is loaded.</h2>
+		<button id="startButton" onclick="startTest()">Start Test</button>-->
+		<p>
+			Before start this test, make sure the <b>dojo/cldr/nls</b> contains the data for "ar-eg" and "hi-in". If not, convert these CLDR data and put them there.
+		</p>
+
+		<script>
+		(function() {
+
+			genFormatTestCases("Number Format", "dijit.form.NumberTextBox", [
+				{ attrs: {lang: "ar-eg"},
+				  desc: "Locale: ar_EG",
+				  value: "12345.067",
+				  expValue: "12٬345٫067",
+				  comment: ""
+				},
+				{ attrs: {lang: "ar-eg"},
+				  desc: "Locale: ar_EG",
+				  value: "-12345.067",
+				  expValue: "12٬345٫067-",
+				  comment: ""
+				},
+
+				{ attrs: {lang: "ar-eg", constraints: "{localeDigit: true}"},
+				  desc: "Locale: ar_EG",
+				  value: "12345.067",
+				  expValue: "١٢\u066C٣٤٥\u066B٠٦٧",
+				  comment: "<a href='currency.html#cmt_2'>See #2 (currency.html).</a>"
+				},
+				{ attrs: {lang: "ar-eg", constraints: "{localeDigit: true}"},
+				  desc: "Locale: ar_EG",
+				  value: "-12345.067",
+				  expValue: "١٢\u066C٣٤٥\u066B٠٦٧-",
+				  comment: "<a href='currency.html#cmt_2'>See #2 (currency.html).</a>"
+				},
+
+				{ attrs: {lang: "hi-in", constraints: "{localeDigit: true}"},
+				  desc: "Locale: hi_IN",
+				  value: "123456789.068",
+				  expValue: "१२,३४,५६,७८९.०६८",
+				  comment: "<a href='currency.html#cmt_2'>See #2 (currency.html).</a>"
+				},
+				{ attrs: {lang: "hi-in", constraints: "{localeDigit: true}"},
+				  desc: "Locale: hi_IN",
+				  value: "-123456789.068",
+				  expValue: "-१२,३४,५६,७८९.०६८",
+				  comment: "<a href='currency.html#cmt_2'>See #2 (currency.html).</a>"
+				}
+			]);
+
+			genValidateTestCases("Number Validate", "dijit.form.NumberTextBox", [
+
+				{ attrs: {lang: "ar-eg"},
+				  desc: "Locale: ar_EG",
+				  value: 12345.067,
+				  expValue: "12٬345٫067",
+				  comment: ""
+				},
+				{ attrs: {lang: "ar-eg"},
+				  desc: "Locale: ar_EG",
+				  value: -12345.067,
+				  expValue: "12٬345٫067-",
+				  comment: ""
+				},
+
+				{ attrs: {lang: "ar-eg", constraints: "{localeDigit: true}"},
+				  desc: "Locale: ar_EG",
+				  value: 12345.067,
+				  expValue: "١٢\u066C٣٤٥\u066B٠٦٧",
+				  comment: "<a href='currency.html#cmt_2'>See #2 (currency.html).</a>"
+				},
+				{ attrs: {lang: "ar-eg", constraints: "{localeDigit: true}"},
+				  desc: "Locale: ar_EG",
+				  value: -12345.067,
+				  expValue: "١٢\u066C٣٤٥\u066B٠٦٧-",
+				  comment: "<a href='currency.html#cmt_2'>See #2 (currency.html).</a>"
+				},
+
+				{ attrs: {lang: "hi-in", constraints: "{localeDigit: true}"},
+				  desc: "Locale: hi_IN",
+				  value: 123456789.068,
+				  expValue: "१२,३४,५६,७८९.०६८",
+				  comment: "<a href='currency.html#cmt_2'>See #2 (currency.html).</a>"
+				},
+				{ attrs: {lang: "hi-in", constraints: "{localeDigit: true}"},
+				  desc: "Locale: hi_IN",
+				  value: -123456789.068,
+				  expValue: "-१२,३४,५६,७८९.०६८",
+				  comment: "<a href='currency.html#cmt_2'>See #2 (currency.html).</a>"
+				}
+			]);
+
+			genFormatTestCases("Currency Format", "dijit.form.CurrencyTextBox", [
+
+				{ attrs: {Currency: "EGP", lang: "ar-eg"},
+				  desc: "Locale: <b>ar_EG</b> Currency: <b>EGP</b>",
+				  value: "123456789.46",
+				  expValue: "&#x062C;.&#x0645;.\u200F 123&#x066C;456&#x066C;789&#x066B;46",
+				  comment: ""
+				},
+				{ attrs: {Currency: "EGP", lang: "ar-eg"},
+				  desc: "Locale: <b>ar_EG</b> Currency: <b>EGP</b>",
+				  value: "-123456789.46",
+				  expValue: "&#x062C;.&#x0645;.\u200F 123&#x066C;456&#x066C;789&#x066B;46-",
+				  comment: ""
+				},
+
+				{ attrs: {Currency: "EGP", lang: "ar-eg", constraints: "{localeDigit: true}"},
+				  desc: "Locale: <b>ar_EG</b> Currency: <b>EGP</b>",
+				  value: "123456789.46",
+				  expValue: "&#x062C;.&#x0645;.\u200F ١٢٣\u066C٤٥٦\u066C٧٨٩\u066B٤٦",
+				  comment: "<a href='#cmt_3'>See #3.</a> Failed in Firefox. <a href='#cmt_2'>See #2.</a>"
+				},
+				{ attrs: {Currency: "EGP", lang: "ar-eg", constraints: "{localeDigit: true}"},
+				  desc: "Locale: <b>ar_EG</b> Currency: <b>EGP</b>",
+				  value: "-123456789.46",
+				  expValue: "&#x062C;.&#x0645;.\u200F ١٢٣\u066C٤٥٦\u066C٧٨٩\u066B٤٦-",
+				  comment: "<a href='#cmt_3'>See #3.</a> Failed in Firefox. <a href='#cmt_2'>See #2.</a>"
+				}
+			]);
+
+			genValidateTestCases("Currency Validate", "dijit.form.CurrencyTextBox", [
+
+				{ attrs: {Currency: "EGP", lang: "ar-eg"},
+				  desc: "Locale: <b>ar_EG</b> Currency: <b>EGP</b>",
+				  value: 123456789.46,
+				  expValue: "&#x062C;.&#x0645;.\u200F 123&#x066C;456&#x066C;789&#x066B;46",
+				  comment: "Failed in Firefox. <a href='#cmt_2'>See #2.</a>"
+				},
+				{ attrs: {Currency: "EGP", lang: "ar-eg"},
+				  desc: "Locale: <b>ar_EG</b> Currency: <b>EGP</b>",
+				  value: -123456789.46,
+				  expValue: "&#x062C;.&#x0645;.\u200F 123&#x066C;456&#x066C;789&#x066B;46-",
+				  comment: "Failed in Firefox. <a href='#cmt_2'>See #2.</a>"
+				},
+
+				{ attrs: {Currency: "EGP", lang: "ar-eg", constraints: "{localeDigit: true}"},
+				  desc: "Locale: <b>ar_EG</b> Currency: <b>EGP</b>",
+				  value: 123456789.46,
+				  expValue: "&#x062C;.&#x0645;.\u200F ١٢٣\u066C٤٥٦\u066C٧٨٩\u066B٤٦",
+				  comment: "<a href='#cmt_3'>See #3.</a> Failed in Firefox. <a href='#cmt_2'>See #2.</a>"
+				},
+				{ attrs: {Currency: "EGP", lang: "ar-eg", constraints: "{localeDigit: true}"},
+				  desc: "Locale: <b>ar_EG</b> Currency: <b>EGP</b>",
+				  value: -123456789.46,
+				  expValue: "&#x062C;.&#x0645;.\u200F ١٢٣\u066C٤٥٦\u066C٧٨٩\u066B٤٦-",
+				  comment: "<a href='#cmt_3'>See #3.</a> Failed in Firefox. <a href='#cmt_2'>See #2.</a>"
+				}
+			]);
+
+			var testCases = [];
+			gen4DateFormat(testCases, "ar-eg", "ar_EG", "2005-07-31",
+				"31/7/2005", "", "31/07/2005", "", "31 &#x064A;&#x0648;&#x0644;&#x064A;&#x0648;&#x2C; 2005", "", "&#x0627;&#x0644;&#x0623;&#x062D;&#x062F;&#x2C; 31 &#x064A;&#x0648;&#x0644;&#x064A;&#x0648;&#x2C; 2005", "");
+			gen4DateFormat(testCases, "hi-in", "hi_IN", "2005-07-31",
+				"२००५-०७-३१", "<a href='currency.html#cmt_3'>See #3 (currency.html).</a>", "२००५ जुलाई ३१", "<a href='currency.html#cmt_3'>See #3 (currency.html).</a>", "२००५ जुलाई ३१", "<a href='currency.html#cmt_3'>See #3 (currency.html).</a>", "रविवार, २००५ जुलाई ३१", "<a href='currency.html#cmt_3'>See #3 (currency.html).</a>");
+			genFormatTestCases("Date Format", "dijit.form.DateTextBox", testCases);
+
+			testCases = [];
+			gen4DateFormat(testCases, "ar-eg", "ar_EG", new Date(2005, 6, 31),
+				"31/7/2005", "", "31/07/2005", "", "31 &#x064A;&#x0648;&#x0644;&#x064A;&#x0648;&#x2C; 2005", "", "&#x0627;&#x0644;&#x0623;&#x062D;&#x062F;&#x2C; 31 &#x064A;&#x0648;&#x0644;&#x064A;&#x0648;&#x2C; 2005", "");
+			gen4DateFormat(testCases, "hi-in", "hi_IN", new Date(2005, 6, 31),
+				"२००५-०७-३१", "<a href='currency.html#cmt_3'>See #3 (currency.html).</a>", "२००५ जुलाई ३१", "<a href='currency.html#cmt_3'>See #3 (currency.html).</a>", "२००५ जुलाई ३१", "<a href='currency.html#cmt_3'>See #3 (currency.html).</a>", "रविवार, २००५ जुलाई ३१", "<a href='currency.html#cmt_3'>See #3 (currency.html).</a>");
+			genValidateTestCases("Date Validate", "dijit.form.DateTextBox", testCases);
+
+			dojo.parser.parse();
+
+		})();
+
+		</script>
+	</body>
+</html>
+
+<!--
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'short', localeDigit: true}" : "{formatLength:'short'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Short</b>",
+				  value: date,
+				  expValue: short,
+				  comment: shortCmt
+				});
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'medium', localeDigit: true}" : "{formatLength:'medium'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Medium</b>",
+				  value: date,
+				  expValue: medium,
+				  comment: mediumCmt
+				});
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'long', localeDigit: true}" : "{formatLength:'long'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Long</b>",
+				  value: date,
+				  expValue: long,
+				  comment: longCmt
+				});
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'full', localeDigit: true}" : "{formatLength:'full'}", lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Full</b>",
+				  value: date,
+				  expValue: full,
+				  comment: fullCmt
+-->
+
diff --git a/dijit/tests/i18n/module.js b/dijit/tests/i18n/module.js
new file mode 100644
index 0000000..aa62367
--- /dev/null
+++ b/dijit/tests/i18n/module.js
@@ -0,0 +1,14 @@
+dojo.provide("dijit.tests.i18n.module");
+
+try{
+	if(dojo.isBrowser){
+		doh.registerUrl("dijit.tests.i18n.currency", dojo.moduleUrl("dijit", "tests/i18n/currency.html"), 99999999);
+		doh.registerUrl("dijit.tests.i18n.date", dojo.moduleUrl("dijit", "tests/i18n/date.html"), 99999999);
+		doh.registerUrl("dijit.tests.i18n.number", dojo.moduleUrl("dijit", "tests/i18n/number.html"), 99999999);
+		doh.registerUrl("dijit.tests.i18n.textbox", dojo.moduleUrl("dijit", "tests/i18n/textbox.html"), 99999999);
+		doh.registerUrl("dijit.tests.i18n.time", dojo.moduleUrl("dijit", "tests/i18n/time.html"), 99999999);
+		doh.registerUrl("dijit.tests.i18n.digit", dojo.moduleUrl("dijit", "tests/i18n/digit.html"), 99999999);
+	}
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dijit/tests/i18n/number.html b/dijit/tests/i18n/number.html
new file mode 100644
index 0000000..774eddf
--- /dev/null
+++ b/dijit/tests/i18n/number.html
@@ -0,0 +1,137 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>Test NumberTextBox</title>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, extraLocale: ['zh-cn','fr-fr']"></script>
+		<script type="text/javascript" src="../../../dojo/currency.js"></script>
+		<script type="text/javascript" src="../../../dojo/number.js"></script>
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.NumberTextBox");
+			dojo.require("dijit.form.CurrencyTextBox");
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dijit.form.ValidationTextBox");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.date.stamp");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+			dojo.require("doh.runner");
+		</script>
+		<script src="test_i18n.js"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				doh.register("t", getAllTestCases());
+				doh.run();
+			});
+		</script>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../themes/tundra/tundra.css";
+			@import "../css/dijitTests.css";
+
+			.title {
+				background-color:#ddd;
+			}
+
+			.hint {
+				background-color:#eee;
+			}
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+
+			td {white-space:nowrap}
+		</style>
+	</head>
+
+	<body class="claro">
+		<h1 class="testTitle">Dijit TextBox Globalization Test for Number</h1>
+
+<!--		<h2 class="testTitle">Press the following button to start all test after this page is loaded.</h2>
+		<button id="startButton" onclick="startTest()">Start Test</button>-->
+		<p>
+			Before start this test, make sure the <b>dojo/cldr/nls</b> contains the data for "zh-cn", "fr-fr". If not, convert these CLDR data and put them there.
+		</p>
+
+		<script>
+		(function() {
+
+			genFormatTestCases("Number Format", "dijit.form.NumberTextBox", [
+
+				{ attrs: {lang: "zh-cn"},
+				  desc: "Locale: zh_CN",
+				  value: "12345.067",
+				  expValue: "12,345.067",
+				  comment: ""
+				},
+				{ attrs: {lang: "zh-cn"},
+				  desc: "Locale: zh_CN",
+				  value: "-12345.067",
+				  expValue: "-12,345.067",
+				  comment: ""
+				},
+
+				{ attrs: {lang: "fr-fr"},
+				  desc: "Locale: fr_FR",
+				  value: "12345.067",
+				  expValue: "12 345,067",
+				  comment: ""
+				},
+				{ attrs: {lang: "fr-fr"},
+				  desc: "Locale: zh_CN",
+				  value: "-12345.067",
+				  expValue: "-12 345,067",
+				  comment: ""
+				}
+			]);
+
+			genValidateTestCases("Number Validate", "dijit.form.NumberTextBox", [
+
+				{ attrs: {lang: "zh-cn"},
+				  desc: "Locale: zh_CN",
+				  value: 12345.067,
+				  expValue: "12,345.067",
+				  comment: ""
+				},
+				{ attrs: {lang: "zh-cn"},
+				  desc: "Locale: zh_CN",
+				  value: -12345.067,
+				  expValue: "-12,345.067",
+				  comment: ""
+				},
+
+				{ attrs: {lang: "fr-fr"},
+				  desc: "Locale: fr_FR",
+				  value: 12345.067,
+				  expValue: "12 345,067",
+				  comment: ""
+				},
+				{ attrs: {lang: "fr-fr"},
+				  desc: "Locale: zh_CN",
+				  value: -12345.067,
+				  expValue: "-12 345,067",
+				  comment: ""
+				}
+			]);
+
+			dojo.parser.parse();
+
+		})();
+
+		</script>
+	</body>
+</html>
+
+
diff --git a/dijit/tests/i18n/test_i18n.js b/dijit/tests/i18n/test_i18n.js
new file mode 100644
index 0000000..caac878
--- /dev/null
+++ b/dijit/tests/i18n/test_i18n.js
@@ -0,0 +1,206 @@
+var validateValues = [];
+var formatWidgetCount = 0;
+var validateWidgetCount = 0;
+
+function getElementsById(id){
+	var result = [];
+
+	if(!id || typeof(id) != "string"){
+		return result;
+	}
+
+	var ae = document.getElementsByTagName(dojo.byId(id).tagName);
+	for(var i = 0; i < ae.length; i++){
+		if(ae[i].id == id){
+			result.push(ae[i]);
+		}
+	}
+	return result;
+}
+
+function getString(n){
+	return n && n.toString();
+}
+
+function startTest(t){
+	startTestFormat(t);
+	startTestValidate(t);
+}
+
+function escapeEx(s){
+	var result = "";
+	for(var i = 0; i < s.length; i++){
+		var c = s.charAt(i);
+		switch (c){
+			case '"':
+				result += '\\"';
+				break;
+			case "'":
+				result += "\\'";
+				break;
+			default:
+				result += escape(c);
+				break;
+		}
+	}
+	return result;
+}
+
+function getAllTestCases(){
+	var allTestCases = [];
+	for(var i = 0; i < formatWidgetCount; i++){
+		allTestCases.push({
+			name: "format-" + i,
+			runTest: new Function("t", "startTestFormat(" + i + ", t)")
+		});
+	}
+	for(var i = 0; i < validateWidgetCount; i++){
+		allTestCases.push({
+			name: "validate-" + i,
+			runTest: new Function("t", "startTestValidate(" + i + ", t)")
+		});
+	}
+	return allTestCases;
+}
+
+function startTestFormat(i, t){
+	var test_node = dojo.doc.getElementById("test_display_" + i);
+	var exp = dojo.doc.getElementById("test_display_expected_" + i).value;
+	var res_node = dojo.doc.getElementById("test_display_result_" + i);
+	res_node.innerHTML = test_node.value;
+	res_node.style.backgroundColor = (test_node.value == exp) ? "#AFA" : "#FAA";
+	res_node.innerHTML += " <a style='font-size:0.8em' href='javascript:alert(\"Expected: " + escapeEx(exp) + "\\n Result: " + escapeEx(test_node.value) + "\")'>Compare (Escaped)</a>";
+	t.is(exp, test_node.value);
+}
+
+function startTestValidate(i, t){
+	/*
+	 * The dijit.byNode has an issue: cannot handle same id.
+	 */
+	var test_node = dojo.doc.getElementById("test_validate_" + i);
+	var inp_node = dojo.doc.getElementById("test_validate_input_" + i);
+	var exp = dojo.doc.getElementById("test_validate_expected_" + i).innerHTML;
+	var res_node = dojo.doc.getElementById("test_validate_result_" + i);
+	var val_node = dojo.doc.getElementById("test_display_value_" + i);
+
+	test_node.value = inp_node.value;
+	/*
+	 * The dijit.byNode has an issue.
+	 */
+	var widget = null;
+	var node = test_node;
+	while ((widget = dijit.byNode(node)) == null){
+		node = node.parentNode;
+		if(!node){
+			break;
+		}
+	}
+
+	if(widget){
+		widget.focus();
+
+		var expected = validateValues[i];
+		var result = widget.getValue();
+		if(validateValues[i].processValue){
+			expected = validateValues[i].processValue(expected);
+			result = validateValues[i].processValue(result);
+		}
+		var parseCorrect = getString(expected) == getString(result);
+		val_node.style.backgroundColor = parseCorrect ?  "#AFA" : "#FAA";
+		val_node.innerHTML = getString(result) + (parseCorrect ? "" : "<br>Expected: " + getString(expected));
+
+		res_node.innerHTML = widget.isValid && !widget.isValid() ? "Wrong" : "Correct";
+		res_node.style.backgroundColor = res_node.innerHTML == exp ? "#AFA" : "#FAA";
+
+		t.is(getString(expected), getString(result));
+	}
+}
+
+function genFormatTestCase(desc, dojoType, dojoAttrs, value, expValue, comment){
+	dojo.doc.write("<tr>");
+	dojo.doc.write("<td>" + desc + "</td>");
+	dojo.doc.write("<td>");
+	dojo.doc.write("<input id='test_display_" + formatWidgetCount + "' type='text' value='" + value + "' ");
+	dojo.doc.write("dojoType='" + dojoType + "' ");
+	for(var attr in dojoAttrs){
+		dojo.doc.write(attr + "=\"" + dojoAttrs[attr] + "\" ");
+	}
+	dojo.doc.write("/>");
+	dojo.doc.write("</td>");
+	dojo.doc.write("<td><input id='test_display_expected_" + formatWidgetCount + "' value='" + expValue + "'></td>");
+	dojo.doc.write("<td id='test_display_result_" + formatWidgetCount + "'></td>");
+	dojo.doc.write("<td style='white-space:normal'>" + comment + "</td>");
+	dojo.doc.write("</tr>");
+	formatWidgetCount++;
+}
+/*
+[
+	{attrs: {currency: "CNY", lang: "zh-cn"}, desc: "", value:"-123456789.46", expValue: "", comment: ""},
+	...
+]
+*/
+function genFormatTestCases(title, dojoType, testCases){
+	dojo.doc.write("<h2 class=testTitle>" + title + "</h2>");
+	dojo.doc.write("<table border=1>");
+	dojo.doc.write("<tr>");
+	dojo.doc.write("<td class=title><b>Test Description</b></td>");
+	dojo.doc.write("<td class=title><b>Test</b></td>");
+	dojo.doc.write("<td class=title><b>Expected</b></td>");
+	dojo.doc.write("<td class=title><b>Result</b></td>");
+	dojo.doc.write("<td class=title><b>Comment</b></td>");
+	dojo.doc.write("</tr>");
+
+	for(var i = 0; i < testCases.length; i++){
+		var testCase = testCases[i];
+		genFormatTestCase(testCase.desc, dojoType, testCase.attrs, testCase.value, testCase.expValue, testCase.comment);
+	}
+
+	dojo.doc.write("</table>");
+}
+
+function genValidateTestCase(desc, dojoType, dojoAttrs, input, value, comment, isWrong){
+	dojo.doc.write("<tr>");
+	dojo.doc.write("<td>" + desc + "</td>");
+	dojo.doc.write("<td>");
+	dojo.doc.write("<input id='test_validate_" + validateWidgetCount + "' type='text' ");
+	dojo.doc.write("dojoType='" + dojoType + "' ");
+	for(var attr in dojoAttrs){
+		dojo.doc.write(attr + "=\"" + dojoAttrs[attr] + "\" ");
+	}
+	dojo.doc.write("/>");
+	dojo.doc.write("</td>");
+	dojo.doc.write("<td><input id='test_validate_input_" + validateWidgetCount + "' value='" + input + "'></td>");
+	dojo.doc.write("<td id='test_display_value_" + validateWidgetCount + "'></td>");
+	dojo.doc.write("<td id='test_validate_expected_" + validateWidgetCount + "'>" + (isWrong ? "Wrong" : "Correct") + "</td>");
+	dojo.doc.write("<td id='test_validate_result_" + validateWidgetCount + "'></td>");
+	dojo.doc.write("<td style='white-space:normal'>" + comment + "</td>");
+	dojo.doc.write("</tr>");
+	validateValues.push(value);
+	validateWidgetCount++;
+}
+/*
+[
+	{attrs: {currency: "CNY", lang: "zh-cn"}, desc: "", value:false, expValue: "-123456789.46", comment: ""},
+	...
+]
+*/
+function genValidateTestCases(title, dojoType, testCases){
+	dojo.doc.write("<h2 class=testTitle>" + title + "</h2>");
+	dojo.doc.write("<table border=1>");
+	dojo.doc.write("<tr>");
+	dojo.doc.write("<td class=title><b>Test Description</b></td>");
+	dojo.doc.write("<td class=title><b>Test</b></td>");
+	dojo.doc.write("<td class=title><b>Input</b></td>");
+	dojo.doc.write("<td class=title><b>Parsed Value</b></td>");
+	dojo.doc.write("<td class=title><b>Expected</b></td>");
+	dojo.doc.write("<td class=title><b>Result</b></td>");
+	dojo.doc.write("<td class=title><b>Comment</b></td>");
+	dojo.doc.write("</tr>");
+
+	for(var i = 0; i < testCases.length; i++){
+		var testCase = testCases[i];
+		genValidateTestCase(testCase.desc, dojoType, testCase.attrs, testCase.expValue, testCase.value, testCase.comment, testCase.isWrong);
+	}
+
+	dojo.doc.write("</table>");
+}
diff --git a/dijit/tests/i18n/textbox.html b/dijit/tests/i18n/textbox.html
new file mode 100644
index 0000000..f9b41c4
--- /dev/null
+++ b/dijit/tests/i18n/textbox.html
@@ -0,0 +1,174 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>Test TextBox</title>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript" src="../../../dojo/currency.js"></script>
+		<script type="text/javascript" src="../../../dojo/number.js"></script>
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.NumberTextBox");
+			dojo.require("dijit.form.CurrencyTextBox");
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dijit.form.ValidationTextBox");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.date.stamp");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+			dojo.require("doh.runner");
+		</script>
+		<script src="test_i18n.js"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				doh.register("t", getAllTestCases());
+				doh.run();
+			});
+		</script>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../themes/tundra/tundra.css";
+			@import "../css/dijitTests.css";
+
+			.title {
+				background-color:#ddd;
+			}
+
+			.hint {
+				background-color:#eee;
+			}
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+
+			td {white-space:nowrap}
+		</style>
+	</head>
+
+	<body class="claro">
+		<h1 class="testTitle">Dijit TextBox Globalization Test</h1>
+
+<!--		<h2 class="testTitle">Press the following button to start all test after this page is loaded.</h2>
+		<button id="startButton" onclick="startTest()">Start Test</button>-->
+
+		<script>
+		(function() {
+			genFormatTestCases("Natural Language Casing Mapping", "dijit.form.TextBox", [
+
+				{ attrs: {uppercase: "true"},
+				  desc: "Upper casing: Basic Latin",
+				  value: "abcdefghijklmnopqrstuvwxyz",
+				  expValue: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+				  comment: ""
+				},
+
+				{ attrs: {uppercase: "true"},
+				  desc: "Upper casing: Latin with accents",
+				  value: "àáâãäåæçèéêëìíîïðñòóôõö",
+				  expValue: "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ",
+				  comment: ""
+				},
+
+				{ attrs: {uppercase: "true"},
+				  desc: "Upper casing: Turkish",
+				  value: "ıi",
+				  expValue: "Iİ",
+				  comment: "<a href='#cmt_1'>See #1.</a>"
+				},
+
+				{ attrs: {uppercase: "true"},
+				  desc: "Upper casing: Russian",
+				  value: "абвгдежз",
+				  expValue: "АБВГДЕЖЗ",
+				  comment: ""
+				},
+
+				{ attrs: {uppercase: "true"},
+				  desc: "Upper casing: German",
+				  value: "ß",
+				  expValue: "SS",
+				  comment: "<a href='#cmt_1'>See #1.</a>"
+				},
+
+				{ attrs: {lowercase: "true"},
+				  desc: "Lower casing: Turkish",
+				  value: "Iİ",
+				  expValue: "ıi",
+				  comment: "<a href='#cmt_1'>See #1.</a>"
+				},
+
+				{ attrs: {propercase: "true"},
+				  desc: "Title/Proper casing: Latin",
+				  value: "\u01F1abc",
+				  expValue: "\u01F2abc",
+				  comment: "<a href='#cmt_1'>See #1.</a>"
+				}
+			]);
+
+			genFormatTestCases("White-space Detecting", "dijit.form.TextBox", [
+
+				{ attrs: {trim: "true"},
+				  desc: "Normal space & tab",
+				  value: "   abc\t\t\t",
+				  expValue: "abc",
+				  comment: ""
+				},
+
+				{ attrs: {trim: "true"},
+				  desc: "NO-BREAK SPACE",
+				  value: "\u00A0abc\u00A0",
+				  expValue: "abc",
+				  comment: "Failed in IE. <a href='#cmt_2'>See #2.</a>"
+				},
+
+				{ attrs: {trim: "true"},
+				  desc: "EN QUAD",
+				  value: "\u2000abc\u2000",
+				  expValue: "abc",
+				  comment: "Failed in IE. <a href='#cmt_2'>See #2.</a>"
+				},
+
+				{ attrs: {trim: "true"},
+				  desc: "IDEOGRAPHIC SPACE",
+				  value: "\u3000abc\u3000",
+				  expValue: "abc",
+				  comment: "Failed in IE. <a href='#cmt_2'>See #2.</a>"
+				}
+
+
+			]);
+
+			dojo.parser.parse();
+
+		})();
+		</script>
+
+		<h2 class="testTitle">Issues & Comments </h2>
+		<a name="cmt_1"><h3 class="testTitle">Issue #1 <sup style="color:red">Not fixed. Avoid using this function of TextBox.</sup></h3></a>
+		<p>
+			Strictly speaking, all casing manipulation must use ICU case mapping rules (routine). However, the default JavaScript routines used by Dojo
+			do not support ICU case mapping rules in all browsers.
+		</p>
+
+		<a name="cmt_2"><h3 class="testTitle">Issue #2 <sup style="color:red">Not fixed. Avoid using this function of TextBox.</sup></h3></a>
+		<p>
+			Trimming must get rid of all Unicode characters with the white space property. However, the default JavaScript routines used by Dojo
+			do not support get character properties in some browsers like IE. Other browsers like Firefox might support trimming more white space
+			characters.
+		</p>
+
+	</body>
+</html>
+
+
diff --git a/dijit/tests/i18n/time.html b/dijit/tests/i18n/time.html
new file mode 100644
index 0000000..c921183
--- /dev/null
+++ b/dijit/tests/i18n/time.html
@@ -0,0 +1,208 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>Test TextBox for Time</title>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, extraLocale: ['zh-cn','fr-fr','ja-jp','ar-eg','ru-ru','hi-in','en-us']"></script>
+		<script type="text/javascript" src="../../../dojo/currency.js"></script>
+		<script type="text/javascript" src="../../../dojo/number.js"></script>
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.ValidationTextBox");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.date.stamp");
+			dojo.require("dojo.date");
+			dojo.require("dojo.string");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+			dojo.require("doh.runner");
+		</script>
+		<script src="test_i18n.js"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				doh.register("t", getAllTestCases());
+				doh.run();
+			});
+		</script>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../themes/tundra/tundra.css";
+			@import "../css/dijitTests.css";
+
+			.title {
+				background-color:#ddd;
+			}
+
+			.hint {
+				background-color:#eee;
+			}
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+
+			td {white-space:nowrap}
+		</style>
+		<script>
+			dojo.declare(
+				"dijit.form.TimeTextBox",
+				dijit.form.ValidationTextBox,
+				{
+					regExpGen: dojo.date.locale.regexp,
+					format: dojo.date.locale.format,
+					parse: dojo.date.locale.parse,
+					value: new Date()
+				}
+			);
+
+			var tz_s = dojo.date.getTimezoneName(new Date());
+			if (!tz_s) {
+				var offset = new Date().getTimezoneOffset();
+				var tz = [
+					(offset <= 0 ? "+" : "-"),
+					dojo.string.pad(Math.floor(Math.abs(offset) / 60), 2),
+					dojo.string.pad(Math.abs(offset) % 60, 2)
+				];
+				tz.splice(0, 0, "GMT");
+				tz.splice(3, 0, ":");
+				tz_s = tz.join("");
+			}
+
+			function gen4DateFormat(testCases, language, locale, date, short, shortCmt, medium, mediumCmt, long, longCmt, full, fullCmt) {
+				var tz_l = language.indexOf("hi") == 0 && dojo.number.normalizeDigitChars ?
+					dojo.number.normalizeDigitChars(tz_s, language) : tz_s;
+
+				short = short.replace(/UTC/, tz_l);
+				medium = medium.replace(/UTC/, tz_l);
+				long = long.replace(/UTC/g, tz_l);
+				full = full.replace(/UTC/, tz_l);
+
+				var shortDate = null;
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'short', selector:'time', localeDigit:true}" : "{formatLength:'short', selector:'time'}",
+				  		lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Short</b>",
+				  value: typeof(date) == "string" ? date : shortDate = new Date(date.getYear(), date.getMonth(), date.getDay() - 5, date.getHours(), date.getMinutes()),
+				  expValue: short,
+				  comment: shortCmt
+				});
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'medium', selector:'time', localeDigit:true}" : "{formatLength:'medium', selector:'time'}",
+				  		lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Medium</b>",
+				  value: date,
+				  expValue: medium,
+				  comment: mediumCmt
+				});
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'long', selector:'time', localeDigit:true}" : "{formatLength:'long', selector:'time'}",
+				  		lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Long</b>",
+				  value: date,
+				  expValue: long,
+				  comment: longCmt
+				});
+				testCases.push({
+				  attrs: {constraints: language.indexOf("hi") == 0 ? "{formatLength:'full', selector:'time', localeDigit:true}" : "{formatLength:'full', selector:'time'}",
+				  		lang: language},
+				  desc: "Locale: <b>" + locale + "</b> Format: <b>Full</b>",
+				  //value: typeof(date) == "string" || language.indexOf("fr") ? date : shortDate,
+				  value: date,
+				  expValue: full,
+				  comment: fullCmt
+				});
+
+				date.processValue = function (value) {
+					return value ? new Date(1970, 0, 1, value.getHours(), value.getMinutes(), value.getSeconds()) : value;
+				};
+				if (shortDate) {
+					shortDate.processValue = date.processValue;
+				}
+			}
+		</script>
+	</head>
+
+	<body class="claro">
+		<h1 class="testTitle">Dijit TextBox Globalization Test for Time</h1>
+
+		<h2 class="testTitle">Press the following button to start all test after this page is loaded.</h2>
+		<button id="startButton" onclick="startTest()">Start Test</button>
+		<p>
+			Before start this test, make sure the <b>dojo/cldr/nls</b> contains the data for "zh-cn", "fr-fr", "ja-jp", "ru-ru", "hi-in", "en-us" and "ar-eg". If not, convert these CLDR data and put them there.
+		</p>
+
+		<script>
+		(function() {
+			var testCases = [];
+			gen4DateFormat(testCases, "ru-ru", "ru_RU", "1970-01-01T15:25:35",
+				"15:25", "", "15:25:35", "", "15:25:35 UTC", "<a href='#cmt_1'>See #1.</a>", "15:25:35 UTC", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "zh-cn", "zh_CN", "1970-01-01T15:25:35",
+				"下午3:25", "", "下午03:25:35", "", "下午03时25分35秒", "", "下午03时25分35秒 UTC", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "en-us", "en_US", "1970-01-01T15:25:35",
+				"3:25 PM", "", "3:25:35 PM", "", "3:25:35 PM UTC", "<a href='#cmt_1'>See #1.</a>", "3:25:35 PM UTC", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "fr-fr", "fr_FR", "1970-01-01T15:25:35",
+				"15:25", "", "15:25:35", "", "15:25:35 UTC", "<a href='#cmt_1'>See #1.</a>", "15:25:35 UTC", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "ja-jp", "ja_JP", "1970-01-01T15:25:35",
+				"15:25", "", "15:25:35", "", "15:25:35:UTC", "<a href='#cmt_1'>See #1.</a>", "15時25分35秒UTC", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "ar-eg", "ar_EG", "1970-01-01T15:25:35",
+				"3:25 \u0645", "", "3:25:35 \u0645", "", "UTC 3:25:35 \u0645", "", "UTC 3:25:35 \u0645", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "hi-in", "hi_IN", "1970-01-01T15:25:35",
+				"१५:२५", "<a href='#cmt_2'>See #2.</a>", "१५:२५:३५", "<a href='#cmt_2'>See #2.</a>", "१५:२५:३५ UTC", "<a href='#cmt_1'>See #1.</a> <a href='#cmt_2'>See #2.</a>", "१५:२५:३५ UTC", "<a href='#cmt_1'>See #1.</a> <a href='#cmt_2'>See #2.</a>");
+			genFormatTestCases("Time Format", "dijit.form.TimeTextBox", testCases);
+
+			testCases = [];
+			gen4DateFormat(testCases, "ru-ru", "ru_RU", new Date(1970, 0, 1, 15, 25, 35),
+				"15:25", "", "15:25:35", "", "15:25:35 UTC", "<a href='#cmt_1'>See #1.</a>", "15:25:35 UTC", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "zh-cn", "zh_CN", new Date(1970, 0, 1, 15, 25, 35),
+				"下午3:25", "<a href='#cmt_3'>See #3.</a>", "下午03:25:35", "<a href='#cmt_3'>See #3.</a>", "下午03时25分35秒", "<a href='#cmt_3'>See #3.</a>", "下午03时25分35秒 UTC", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "en-us", "en_US", new Date(1970, 0, 1, 15, 25, 35),
+				"3:25 PM", "", "3:25:35 PM", "", "3:25:35 PM UTC", "<a href='#cmt_1'>See #1.</a>", "3:25:35 PM UTC", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "fr-fr", "fr_FR", new Date(1970, 0, 1, 15, 25, 35),
+				"15:25", "", "15:25:35", "", "15:25:35 UTC", "<a href='#cmt_1'>See #1.</a>", "15:25:35 UTC", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "ja-jp", "ja_JP", new Date(1970, 0, 1, 15, 25, 35),
+				"15:25", "", "15:25:35", "", "15:25:35:UTC", "<a href='#cmt_1'>See #1.</a>", "15時25分35秒UTC", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "ar-eg", "ar_EG", new Date(1970, 0, 1, 15, 25, 35),
+				"3:25 \u0645", "", "3:25:35 \u0645", "", "UTC 3:25:35 \u0645", "", "UTC 3:25:35 \u0645", "<a href='#cmt_1'>See #1.</a>");
+			gen4DateFormat(testCases, "hi-in", "hi_IN", new Date(1970, 0, 1, 15, 25, 35),
+				"१५:२५", "<a href='#cmt_2'>See #2.</a>", "१५:२५:३५", "<a href='#cmt_2'>See #2.</a>", "१५:२५:३५ UTC", "<a href='#cmt_1'>See #1.</a> <a href='#cmt_2'>See #2.</a>", "१५:२५:३५ UTC", "<a href='#cmt_1'>See #1.</a> <a href='#cmt_2'>See #2.</a>");
+			genValidateTestCases("Time Validate", "dijit.form.TimeTextBox", testCases);
+
+			dojo.parser.parse();
+		})();
+		</script>
+
+		<h2 class="testTitle">Issues & Comments</h2>
+		<h3 class="testTitle"><a name="cmt_1">Issue #1 <sup style="color:blue">Fixed</sup></a></h3>
+		<p>
+			Currently Dojo do not support parsing for most "long" and "full" time format which have a timezone mark in it.
+		</p>
+
+		<h3 class="testTitle"><a name="cmt_2">Issue #2 <sup style="color:blue">Fixed: added a "localeDigit" to the options</sup></a></h3>
+		<p>
+			Strictly speaking, the data conversion must support non-European number characters in some locales like Arabic and Hindi.
+			For example, ICU formats a number data into Indic number characters by default in the Arabic locale.
+			However, currently Dojo does not support this feature (Dojo uses the default number conversion of the browser).
+		</p>
+
+		<h3 class="testTitle"><a name="cmt_3">Issue #3 <sup style="color:blue">Fixed</sup></a></h3>
+		<p>
+			This defect only occurs on the "zh-cn" locale. Dojo accepts "下午"(pm) in the textbox, but it automatically changes it to
+			"上午"(am) after the focus changed. The date value of the textbox is also changed.
+		</p>
+		<p>
+			The root cause of this issue is that the parser method's code assumes am/pm symbol always appears after the hour value.
+			But this is not true, for example, the pattern for "zh-cn" puts am/pm field before all the other fields.
+		</p>
+	</body>
+</html>
+
diff --git a/dijit/tests/images/arrowSmall.gif b/dijit/tests/images/arrowSmall.gif
new file mode 100644
index 0000000..8459ffa
Binary files /dev/null and b/dijit/tests/images/arrowSmall.gif differ
diff --git a/dijit/tests/images/copy.gif b/dijit/tests/images/copy.gif
new file mode 100644
index 0000000..3fa0366
Binary files /dev/null and b/dijit/tests/images/copy.gif differ
diff --git a/dijit/tests/images/cut.gif b/dijit/tests/images/cut.gif
new file mode 100644
index 0000000..27d2dd6
Binary files /dev/null and b/dijit/tests/images/cut.gif differ
diff --git a/dijit/tests/images/flatScreen.gif b/dijit/tests/images/flatScreen.gif
new file mode 100644
index 0000000..05edd72
Binary files /dev/null and b/dijit/tests/images/flatScreen.gif differ
diff --git a/dijit/tests/images/folderIcons.gif b/dijit/tests/images/folderIcons.gif
new file mode 100644
index 0000000..d0b1760
Binary files /dev/null and b/dijit/tests/images/folderIcons.gif differ
diff --git a/dijit/tests/images/folderIcons.png b/dijit/tests/images/folderIcons.png
new file mode 100755
index 0000000..f333fbe
Binary files /dev/null and b/dijit/tests/images/folderIcons.png differ
diff --git a/dijit/tests/images/note.gif b/dijit/tests/images/note.gif
new file mode 100644
index 0000000..ae5c621
Binary files /dev/null and b/dijit/tests/images/note.gif differ
diff --git a/dijit/tests/images/paste.gif b/dijit/tests/images/paste.gif
new file mode 100644
index 0000000..4862a28
Binary files /dev/null and b/dijit/tests/images/paste.gif differ
diff --git a/dijit/tests/images/plus.gif b/dijit/tests/images/plus.gif
new file mode 100644
index 0000000..0e92383
Binary files /dev/null and b/dijit/tests/images/plus.gif differ
diff --git a/dijit/tests/images/testsBodyBg.gif b/dijit/tests/images/testsBodyBg.gif
new file mode 100644
index 0000000..4e0b4a7
Binary files /dev/null and b/dijit/tests/images/testsBodyBg.gif differ
diff --git a/dijit/tests/images/tube.gif b/dijit/tests/images/tube.gif
new file mode 100644
index 0000000..b506513
Binary files /dev/null and b/dijit/tests/images/tube.gif differ
diff --git a/dijit/tests/images/tubeTall.gif b/dijit/tests/images/tubeTall.gif
new file mode 100644
index 0000000..e4fdb8b
Binary files /dev/null and b/dijit/tests/images/tubeTall.gif differ
diff --git a/dijit/tests/infrastructure-module.js b/dijit/tests/infrastructure-module.js
new file mode 100644
index 0000000..e6d6dd9
--- /dev/null
+++ b/dijit/tests/infrastructure-module.js
@@ -0,0 +1,20 @@
+dojo.provide("dijit.tests.infrastructure-module");
+
+try{
+	// _Widget
+	doh.registerUrl("dijit.tests._Widget-lifecycle", dojo.moduleUrl("dijit", "tests/_Widget-lifecycle.html"), 99999999);
+	doh.registerUrl("dijit.tests._Widget-attr", dojo.moduleUrl("dijit", "tests/_Widget-attr.html"), 99999999);
+	doh.registerUrl("dijit.tests._Widget-subscribe", dojo.moduleUrl("dijit", "tests/_Widget-subscribe.html"), 99999999);
+	doh.registerUrl("dijit.tests.Widget-placeAt", dojo.moduleUrl("dijit", "tests/Widget-placeAt.html"), 99999999);
+	doh.registerUrl("dijit.tests.robot._Widget-deferredConnect", dojo.moduleUrl("dijit","tests/robot/_Widget-deferredConnect.html"), 99999999);
+	doh.registerUrl("dijit.tests.robot._Widget-ondijitclick_mouse", dojo.moduleUrl("dijit","tests/robot/_Widget-ondijitclick_mouse.html"), 99999999);
+
+	doh.registerUrl("dijit.tests.robot._Widget-ondijitclick_a11y", dojo.moduleUrl("dijit","tests/robot/_Widget-ondijitclick_a11y.html"), 99999999);
+
+	// _Templated and other base classes
+	doh.registerUrl("dijit.tests._Templated", dojo.moduleUrl("dijit", "tests/_Templated.html"), 99999999);
+	doh.registerUrl("dijit.tests._Templated-widgetsInTemplate", dojo.moduleUrl("dijit", "tests/_Templated-widgetsInTemplate.html"), 99999999);
+	doh.registerUrl("dijit.tests._Container", dojo.moduleUrl("dijit", "tests/_Container.html"), 99999999);
+}catch(e){
+	doh.debug(e);
+}
\ No newline at end of file
diff --git a/dijit/tests/layout/AccordionContainer.html b/dijit/tests/layout/AccordionContainer.html
new file mode 100644
index 0000000..188abc3
--- /dev/null
+++ b/dijit/tests/layout/AccordionContainer.html
@@ -0,0 +1,229 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Accordion Widget Automated Test</title>
+
+	<!-- only needed for test files: -->
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.ContentPane");
+
+		var accordion;
+
+		dojo.addOnLoad(function(){
+			doh.register("basic",
+				[
+					{
+						name: "create",
+						runTest: function(t){
+							accordion = new dijit.layout.AccordionContainer({style: "width: 400px; height: 400px;"}).placeAt(dojo.body());
+
+							dojo.forEach([ "pane 1", "pane 2", "pane 3" ], function(title, i){
+								var content = new dijit.layout.ContentPane({id: title, title: title, selected: i==1});
+								content.containerNode.innerHTML = "this is " + title;
+								accordion.addChild(content);
+							});
+							accordion.startup();
+							var titles = dojo.query(".dijitAccordionText", accordion.domNode);
+							t.is(3, titles.length, "number of titles");
+							t.is("pane 3", titles[2].innerHTML);
+
+							var children = accordion.getChildren();
+							t.is(3, children.length, "number of children (ie, contentpanes)");
+						}
+					},
+					{
+						name: "initially open pane",
+						runTest: function(t){
+							// Pane 2 is initially open
+							var openPanes = dojo.query(".dijitAccordionInnerContainer > .dijitVisible", accordion.containerNode);
+							t.is(1, openPanes.length, "exactly one open pane");
+							t.is("pane 2", dijit.byNode(openPanes[0]).title, "pane 2 is initially open");
+
+							// And others are closed
+							var closedPanes = dojo.query(".dijitAccordionInnerContainer > .dijitHidden", accordion.containerNode);
+							t.is(2, closedPanes.length, "n-1 closed panes");
+						}
+					},
+					{
+						name: "addChild at end",
+						runTest: function(t){
+							var pane4 = new dijit.layout.ContentPane({title: "pane 4", content: "this is pane 4"});
+							accordion.addChild(pane4);
+
+							var titles = dojo.query(".dijitAccordionText", accordion.domNode);
+							t.is(4, titles.length, "number of titles");
+							t.is("pane 4", titles[3].innerHTML);
+
+							var children = accordion.getChildren();
+							t.is(4, children.length, "number of children (ie, contentpanes)");
+							t.is(pane4, children[3], "last child is the newly inserted one");
+						}
+					},
+					{
+						name: "addChild after pane 1",
+						runTest: function(t){
+							pane1half = new dijit.layout.ContentPane({id: "pane1half", title: "pane 1.5", content: "this is pane 1.5"});
+							accordion.addChild(pane1half, 1);
+
+							var titles = dojo.query(".dijitAccordionText", accordion.domNode);
+							t.is(5, titles.length, "number of titles");
+							t.is("pane 1.5", titles[1].innerHTML);
+
+							var children = accordion.getChildren();
+							t.is(5, children.length, "number of children (ie, contentpanes)");
+							t.is(pane1half, children[1], "second child is the newly inserted one");
+						}
+					},
+					{
+						name: "removeChild(pane 1.5)",
+						runTest: function(t){
+							accordion.removeChild(dijit.byId('pane1half'));
+
+							var titles = dojo.query(".dijitAccordionText", accordion.domNode);
+							t.is(4, titles.length, "number of titles");
+							t.is("pane 2", titles[1].innerHTML);
+
+							var children = accordion.getChildren();
+							t.is(4, children.length, "number of children (ie, contentpanes)");
+							t.is("pane 2", children[1].title, "second child is again 'pane 2'");
+							
+							// spec is that removing a child shouldn't delete it
+							t.t(dijit.byId("pane1half"), "child removed but still exists");
+						}
+					},
+					{
+						name: "initially open pane (checking again)",
+						runTest: function(t){
+							// Pane 2 is initially open
+							var openPanes = dojo.query(".dijitAccordionInnerContainer > .dijitVisible", accordion.containerNode);
+							t.is(1, openPanes.length, "exactly one open pane");
+							t.is("pane 2", dijit.byNode(openPanes[0]).title, "pane 2 is initially open");
+
+							// And others are closed
+							var closedPanes = dojo.query(".dijitAccordionInnerContainer > .dijitHidden", accordion.containerNode);
+							t.is(3, closedPanes.length, "n-1 closed panes");
+						}
+					},
+					{
+						name: "select new pane",
+						timeout: 3000,
+						setUp: function(t){
+							// Note that this kicks off an animation so it might be a while before the
+							// bottom setTimeout() fires, likely longer than the 300ms specified
+							accordion.selectChild(dijit.byId('pane 3'));
+						},
+						runTest: function(t){
+							// Selecting pane 3 should open it and close pane 1
+							var d = new doh.Deferred();
+							setTimeout(d.getTestCallback(
+								function(){
+									// Pane 3 is now open
+									var openPanes = dojo.query(".dijitAccordionInnerContainer > .dijitVisible", accordion.containerNode);
+									t.is(1, openPanes.length, "exactly one open pane");
+									t.is("pane 3", dijit.byNode(openPanes[0]).title, "pane 3 is now open");
+
+									// And others are closed
+									var closedPanes = dojo.query(".dijitAccordionInnerContainer > .dijitHidden", accordion.containerNode);
+									t.is(3, closedPanes.length, "n-1 closed panes");
+								})
+							, 300);
+							return d;
+						}
+					},
+					{
+						name: "destroy recursive",
+						runTest: function(t){
+							accordion.destroyRecursive();
+							t.is(1, dijit.registry.toArray().length, "accordion and subwidgets destroyed, pane1half remains");
+						}
+					}
+				]
+			);
+			doh.register("zero children",
+				[
+					{
+						name: "create w/no children",
+						runTest: function(t){
+							accordion = new dijit.layout.AccordionContainer({style: "width: 400px; height: 400px;"}).placeAt(dojo.body());
+							accordion.startup();
+							var children = accordion.getChildren();
+							t.is(0, children.length, "no children");
+							accordion.resize();
+							t.t(true, "resize ran w/out exception");
+						}
+					},
+					{
+						name: "add children",
+						runTest: function(t){
+							dojo.forEach([ "pane 10", "pane 11"], function(title, i){
+								var content = new dijit.layout.ContentPane({id: title, title: title});
+								content.containerNode.innerHTML = "this is " + title;
+								accordion.addChild(content);
+							});
+							var children = accordion.getChildren();
+							t.is(2, children.length, "2 children");
+						}
+					},
+					{
+						name: "remove all children",
+						runTest: function(t){
+							var pane10 = dijit.byId("pane 10"),
+								pane11 = dijit.byId("pane 11");
+
+							t.is(pane10, accordion.selectedChildWidget, "pane 10 initially selected");
+
+							accordion.removeChild(pane10);
+							t.is(pane11, accordion.selectedChildWidget, "after pane 10 removed, pane 11 selected");
+
+							accordion.removeChild(pane11);
+							t.f(accordion.selectedChildWidget, "after pane 11 removed, no pane selected");
+							var children = accordion.getChildren();
+							t.is(0, children.length, "all children removed");
+						}
+					},
+					{
+						name: "add back children",
+						runTest: function(t){
+							dojo.forEach([ "pane 12", "pane 13"], function(title, i){
+								var content = new dijit.layout.ContentPane({id: title, title: title});
+								content.containerNode.innerHTML = "this is " + title;
+								accordion.addChild(content);
+							});
+
+							var children = accordion.getChildren();
+							t.is(2, children.length, "two new children");
+							t.is(dijit.byId("pane 12"), accordion.selectedChildWidget, "pane 12 selected");
+						}
+					}
+				]
+			);
+
+			doh.run();
+		});
+	</script>
+</head>
+<body class="claro" style="padding: 50px;">
+
+	<h1 class="testTitle">AccordionContainer Automated Tests</h1>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/ContentPane.html b/dijit/tests/layout/ContentPane.html
new file mode 100644
index 0000000..a75d4c2
--- /dev/null
+++ b/dijit/tests/layout/ContentPane.html
@@ -0,0 +1,879 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>ContentPane DOH test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../themes/tundra/tundra.css";
+		@import "../css/dijitTests.css";
+
+		.box {
+			border: 1px solid black;
+			padding: 8px;
+		}
+
+		.dijitTestWidget {
+			border: 1px dashed red;
+			background-color: #C0E209 ;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dijit._Container");
+		dojo.require("dijit.layout._LayoutWidget");
+		dojo.require("dijit._Templated");
+		dojo.require("dijit.layout.StackContainer");
+
+		// create a do nothing, only for test widget
+		dojo.declare("dijit.TestWidget",
+			[dijit._Widget, dijit._Templated], {
+			templateString: "<span class='dijitTestWidget'></span>"
+		});
+
+
+		dojo.addOnLoad(function(){
+			doh.register("pane1",
+				[
+					{
+						name: "no_autoparse",
+						runTest: function(t){
+							if(dijit.byId("pane1")){
+								throw doh._AssertFailure("Page got autoparsed when it shouldn't");
+							}
+						}
+					}
+				]
+			);
+
+			var pane2;
+
+			doh.registerGroup("pane2",
+				[
+					{
+						name: "clear_content",
+						setUp: function(t){
+							pane2 = new dijit.layout.ContentPane({
+								preventCache: true
+							}, dojo.byId("pane2"));
+							pane2.set("content", "");// pass undefined on purpose
+						},
+						runTest: function(t){
+							t.assertEqual(0, dijit._Widget.prototype.getChildren.call(pane2).length);
+							t.assertEqual("", pane2.domNode.innerHTML)
+						}
+					},
+					{
+						name: "setContent_String",
+						setUp: function(){
+							pane2.set("content", "");
+						},
+						runTest: function(t){
+							var msg = "<h3>a simple html string</h3>";
+							pane2.set("content", msg);
+							t.assertEqual(msg, pane2.domNode.innerHTML.toLowerCase());
+						}
+					},
+					{
+						name: "setContent_DOMNode",
+						setUp: function(t){
+							var div = dojo.doc.createElement('div');
+							div.innerHTML = "set('content', [DOMNode] )";
+							div.setAttribute('dojoType', 'dijit.TestWidget');
+							pane2.set("content", div);
+						},
+						runTest: function(t){
+							t.assertEqual(1, dijit._Widget.prototype.getChildren.call(pane2).length);
+						},
+						tearDown: function(t){
+							pane2.set("content", ""); // clear content for next test
+						}
+					},
+					{
+						name: "setContent_NodeList",
+						setUp: function(t){
+							var div = dojo.doc.createElement('div');
+							div.innerHTML = "<div dojotype='dijit.TestWidget'>above</div>"
+											+"Testing!<div><p><span><b>Deep nested</b></span></p></div>"
+											+"<div dojotype='dijit.TestWidget'>below</div>";
+
+							var list = div.childNodes;
+							pane2.set("content", div.childNodes);
+						},
+						runTest: function(t){
+							t.assertEqual(2, dijit._Widget.prototype.getChildren.call(pane2).length);
+
+							//regular DOM check
+							var children = pane2.domNode.childNodes;
+							t.assertEqual(4, children.length);
+							t.assertEqual("Testing!", children[1].nodeValue);
+							t.assertEqual("div", children[2].nodeName.toLowerCase());
+							t.assertEqual("<p><span><b>deep nested</b></span></p>", children[2].innerHTML.toLowerCase());
+						}
+					},
+					{
+						name: "setContent_dojo_NodeList",
+						setUp: function(t){
+							pane2.set("content", "");
+						},
+						runTest: function(t){
+							var div = dojo.doc.createElement('div');
+							div.innerHTML = "<div dojotype='dijit.TestWidget'>above</div>"
+										+"Testing!<div><p><span><b>Deep nested</b></span></p></div>"
+										+"<div dojotype='dijit.TestWidget'>below</div>";
+
+							var list = new dojo.NodeList();
+							dojo.forEach(div.childNodes, function(n){
+								list.push(n.cloneNode(true));
+							});
+
+							pane2.set("content", list);
+							t.assertEqual(4, pane2.domNode.childNodes.length);
+						}
+					},
+					{
+						name: "extractContent",
+						runTest: function(t){
+							var def = pane2.extractContent;
+							t.assertFalse(def);
+
+							// test that it's actually working
+							pane2.extractContent = true;
+							pane2.set("content", '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" '
+								+'"http://www.w3.org/TR/html4/strict.dtd">'
+								+'<html><head><style>body{font-weight:bold;}</style></head>'
+								+'<body>extractContent test</body></html>');
+
+							t.assertEqual("extractContent test", pane2.domNode.innerHTML);
+
+							// reset back to default
+							pane2.extractContent = def;
+						}
+					},
+
+					/////////////////////////////////////////////////////////////////////////
+					// We assume that our network connection has a maximum of 1.5 sec latency
+					/////////////////////////////////////////////////////////////////////////
+					{
+						name: "setHref_loading",
+						timeout: 1800,
+						setUp: function(t){
+							pane2.set('href', 'getResponse.php?messId=1');
+						},
+						runTest: function(t){
+							var d = new tests.Deferred();
+							setTimeout(d.getTestCallback(
+								function(){
+									t.assertEqual(1, dijit._Widget.prototype.getChildren.call(pane2).length);
+								})
+							, 1500);
+							return d;
+						}
+					},
+					{
+						name: "setHref_then_cancel",
+						timeout: 2800,
+						setUp: function(t){
+							pane2.set("content", "");// clear previous
+						},
+						runTest: function(t){
+							var msg = "This should NEVER be seen!";
+							pane2.set('href', 'getResponse.php?delay=1000&message='+encodeURI(msg));
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(
+								function(){
+									t.assertFalse(pane2.domNode.innerHTML == msg);
+								}
+							), 2500);
+
+							pane2.cancel();
+
+							return d;
+						}
+					},
+					{
+						// test that setHref cancels a inflight setHref
+						name: "setHref_cancels_previous_setHref",
+						timeout: 2800,
+						setUp: function(t){
+							pane2.set("content", "");
+						},
+						runTest: function(t){
+							var msgCanceled = "This should be canceled";
+							pane2.set('href', "getResponse.php?delay=1000&message="+encodeURI(msgCanceled));
+
+							var msg = "This message should win over the previous";
+							setTimeout(function(){
+								pane2.set('href', "getResponse.php?message="+encodeURI(msg));
+							}, 900);
+
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(
+								function(){
+									t.assertEqual(msg, pane2.domNode.innerHTML);
+								}
+							), 2500);
+							return d;
+						}
+					},
+					{
+						name: "setContent_cancels_setHref",
+						timeout: 2800,
+						setUp: function(t){
+							pane2.set("content", "");
+						},
+						runTest: function(t){
+							dojo.connect(pane2, "onUnload", function(){
+								console.log("pane2 unload of: " + pane2.get('content'));
+							});
+							dojo.connect(pane2, "onLoad", function(){
+								console.log("pane2 load of: " + pane2.get('content'));
+							});
+							var msgCanceled = "This message be canceled";
+							pane2.set('href', "getResponse.php?delay=1000&message="+encodeURI(msgCanceled));
+
+							var msg = "This message should win over (ie, cancel) the inflight one";
+							setTimeout(function(){
+								pane2.set("content", msg);
+							}, 500);
+
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(
+								function(){
+									t.assertEqual(msg, pane2.domNode.innerHTML);
+								}
+							), 2500);
+							return d;
+						}
+					},
+					{
+						name: "refresh",
+						timeout: 1900,
+						setUp: function(t){
+							pane2.set('href', "getResponse.php?message="+encodeURI('initial load'));
+						},
+						runTest: function(t){
+							var msg = 'refreshed load'
+							setTimeout(function(){
+								pane2.href = "getResponse.php?message="+encodeURI(msg);
+								pane2.refresh();
+							}, 100);
+
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(
+								function(){
+									t.assertEqual(msg, pane2.domNode.innerHTML);
+								}
+							), 1600);
+							return d;
+
+						}
+					},
+					{
+						// Test isLoaded attribute lifecycle and that onLoad/onUnload callbacks
+						// are called at the right times
+						name: "isLoaded",
+
+						timeout: 1800,
+						setUp: function(t){
+							pane2.set("content", "");
+						},
+						runTest: function(t){
+							t.assertTrue(pane2.isLoaded);
+
+							// Setup handlers to track when onUnload and onLoad are called,
+							// including tracking if they get called repeatedly (they shouldn't)
+							var history = "";
+							var handles = [
+								dojo.connect(pane2, "onUnload", function(){ history += "unloaded"}),
+								dojo.connect(pane2, "onLoad", function(){ history += " and reloaded"})
+							];
+
+							pane2.set('href', "getResponse.php?delay=300&message=test");
+
+							t.assertFalse(pane2.isLoaded);
+							t.assertEqual("unloaded", history);
+
+							var ilObj = {}; // a object to get a reference instead of copy
+
+							// probe after 200ms
+							setTimeout(function(){
+								ilObj.probed = pane2.isLoaded;
+							}, 200);
+
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(
+								function(){
+									t.assertTrue(pane2.isLoaded);
+									t.assertFalse(ilObj.probed);
+									t.assertEqual("unloaded and reloaded", history);
+									console.log("history in callback is ", history);
+
+									dojo.forEach(handles, dojo.disconnect);
+								}
+							), 1500);
+							return d;
+						}
+					},
+					{
+						// test that we don't load a response if we are hidden
+						name: "wait_with_load_when_domNode_hidden",
+						timeout: 1800,
+						setUp: function(t){
+							pane2.domNode.style.display = 'none';
+							pane2.set("content", "");
+						},
+						runTest: function(t){
+							pane2._msg = "This text should not be loaded until after widget is shown";
+							pane2.set('href', "getResponse.php?message="+encodeURI(pane2._msg));
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(
+								function(){
+									t.assertFalse(pane2.domNode.innerHTML == pane2._msg);
+								}
+							), 1500);
+							return d;
+						},
+						tearDown: function(t){
+							pane2.domNode.style.display = "";
+						}
+					},
+					{
+						name: "onDownloadError",
+						timeout: 1800,
+						setUp: function(t){
+							pane2.set("content", "");
+						},
+						runTest: function(t){
+							var res = {};
+							var msg = "Error downloading modified message";
+							var orig = pane2.onDownloadError;
+
+
+							pane2.onDownloadError = function(){
+								return msg;
+							}
+
+							this.onError = function(e){
+								res.onError = true;
+								res.onError_Arg = !!e;
+								return "This message should be ignored as it gets invoked by dojo.connect";
+							}
+
+							var evtHandle = dojo.connect(pane2, 'onDownloadError', this, 'onError');
+
+							// test onDownloadError
+							pane2.set('href', 'nonexistant');
+
+							// do the test
+							var d = new t.Deferred();
+							setTimeout(function(){
+								try{
+									if(!res.onError){
+										d.errback(new doh._AssertFailure("onDownloadError was never invoked"));
+									}
+									if(!res.onError_Arg){
+										d.errback(new doh._AssertFailure("onDownloadError did'nt get any argument on invokation"));
+									}
+									if(pane2.domNode.innerHTML != msg){
+										d.errback(new doh._AssertFailure("custom errortext not set"));
+									}
+									d.callback(true);
+								}catch(e){
+									d.errback(e);
+								}finally{
+									// reset to default
+									dojo.disconnect(evtHandle);
+									pane2.onDownloadError = orig;
+								}
+							}, 1500);
+
+							return d;
+						}
+					},
+					{
+						name: "onLoad|Unload_onDownloadStart|End",
+						timeout: 2400,
+						setUp:function(t){
+							pane2.set("content", "");
+						},
+						runTest:function(t){
+							var obj = {
+								start:function(){
+									this.start_called = 1;
+									// check that custom message gets set
+									setTimeout(function(){
+										obj.start_msg = (pane2.domNode.innerHTML == msg);
+									}, 20);
+								},
+								end: function(){ this.end_called = 1; },
+								load: function(){ this.load_called = 1; },
+								unload: function(){ this.unload_called = 1; }
+							};
+
+							//set custom message
+							var origStart = pane2.onDownloadStart;
+							var msg = "custom downloadstart message";
+							pane2.onDownloadStart = function(){ return msg; };
+
+							var startHandler = dojo.connect(pane2, 'onDownloadStart', obj, 'start');
+							var endHandler = dojo.connect(pane2, 'onDownloadEnd', obj, 'end');
+							var loadHandler = dojo.connect(pane2, 'onLoad', obj, 'load');
+							var unloadHandler = dojo.connect(pane2, 'onUnload', obj, 'unload');
+
+							pane2.set('href', 'getResponse.php?delay=400');
+
+							var d = new t.Deferred();
+							setTimeout(function(){
+								try{
+									if(!obj.start_called){
+										d.errback(new doh._AssertFailure('onDownloadStart not called'));
+									}
+									if(!obj.start_msg){
+										d.errback(new doh._AssertFailure('custom download message not set'));
+									}
+									if(!obj.end_called){
+										d.errback(new doh._AssertFailure('onDownloadEnd not called'));
+									}
+									if(!obj.unload_called){
+										d.errback(new doh._AssertFailure('onUnload not called'));
+									}
+									if(!obj.load_called){
+										d.errback(new doh._AssertFailure('onLoad not called'));
+									}
+									d.callback(true);
+								}catch(e){
+									d.errback(e);
+								}finally{
+									dojo.disconnect(endHandler);
+									dojo.disconnect(startHandler);
+									dojo.disconnect(unloadHandler);
+									dojo.disconnect(loadHandler);
+
+									pane2.onDownloadStart = origStart;
+								}
+							}, 1900);
+
+							return d;
+						}
+					}
+
+				]
+			);
+
+			var st,		// stack container
+				pane3, pane3UnloadCnt=0, pane3LoadCnt=0,	// second child of stack container (initially hidden)
+				tmp;
+
+			doh.registerGroup("child_to_StackContainer",
+				[
+					{
+						// TODO: this test should be moved to registerGroup setUp now that #3504 is fixed
+						//		We actually don't need to test anything here, just setUp
+						name: "setUp_StackContainer",
+						setUp:function(t){
+							// create a StackContainer
+							st = dojo.byId('stackcontainer');
+							dojo.addClass(st, 'box');
+							st = new dijit.layout.StackContainer({}, st);
+
+							// the first child (by default) is the one that will
+							// be shown
+							st.addChild(new dijit.TestWidget());
+
+							// the second child *won't* be shown until selected
+							pane3 = new dijit.layout.ContentPane({
+								href:'getResponse.php?delay=300&message=Loaded!',
+								preventCache: true,
+								onLoad: function(){ pane3LoadCnt++; },
+								onUnload: function(){ pane3UnloadCnt++; }
+							}, dojo.doc.createElement('div'));
+							st.addChild(pane3);
+
+							// start the StackContainer; shouldn't cause ContentPane to load.
+							st.startup();
+						},
+						runTest:function(t){
+							t.assertTrue(st);
+							t.assertEqual(2, st.getChildren().length);
+						}
+					},
+					{
+						name: "preload_false_by_default",
+						runTest: function(t){
+							t.assertFalse(pane3.isLoaded);
+							t.assertEqual('', pane3.domNode.innerHTML);
+						}
+					},
+					{
+						name: "unload event not called initially",
+						runTest: function(t){
+							t.assertEqual(0, pane3UnloadCnt);
+						}
+					},
+					{
+						name: "load event fired when pane is shown",
+						timeout: 2100,
+						runTest: function(t){
+							t.assertEqual(0, pane3LoadCnt, "onload hasn't been called yet");
+							st.selectChild(pane3);
+							t.assertEqual(0, pane3UnloadCnt,
+								"unload shouldn't have been called b/c no initial contents (#1)");
+
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(
+								function(){
+									t.assertTrue(pane3.isLoaded);
+									t.assertEqual(1, pane3LoadCnt, "onload was called");
+									t.assertEqual('Loaded!', pane3.domNode.innerHTML);
+									t.assertEqual(0, pane3UnloadCnt,
+										"unload shouldn't have been called b/c no initial contents (#2)");
+								}
+							), 1800);
+
+							return d;
+						}
+					},
+					{
+						name: "refreshOnShow parameter works",
+						timeout: 2100,
+						setUp: function(t){
+							tmp = {
+								onUnload: function(){ this._unload_fired = 1; },
+								onLoad: function(){ this._load_fired = 1; }
+							};
+							tmp.unloadHandle = dojo.connect(pane3, 'onUnload', tmp, 'onUnload');
+							tmp.loadHandle = dojo.connect(pane3, 'onLoad', tmp, 'onLoad');
+
+							pane3.refreshOnShow = true;
+						},
+						runTest: function(t){
+							var d = new t.Deferred();
+							st.back();
+							st.forward();	// show pane #3
+
+							setTimeout(d.getTestCallback(function(){
+								t.assertTrue(tmp._unload_fired, "unload was fired");
+								t.assertTrue(tmp._load_fired, "load was fired");
+								t.assertEqual('Loaded!', pane3.domNode.innerHTML);
+							}), 1800);
+
+							return d;
+						},
+						tearDown: function(){
+							dojo.disconnect(tmp.unloadHandle);
+							dojo.disconnect(tmp.loadHandle);
+							pane3.refreshOnShow = pane3.constructor.prototype.refreshOnShow;
+						}
+					},
+					{
+						// Test if a plain ContentPane downloads it's contents when startup() is called.
+						// Nothing in particular to do with StackContainer.
+						name: "downloadTriggeredOnStartup",
+						timeout: 1800,
+						runTest: function(t){
+							var href = 'getResponse.php?message=Loaded!'
+							var pane4 = new dijit.layout.ContentPane({
+								href:href,
+								preventCache: true
+							});
+							pane4.placeAt(st.domNode, "after");
+
+							pane4.startup(); // parser should call startup when djConfig.parseOnLoad=true
+
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('Loaded!', pane4.domNode.innerHTML);
+								pane4.destroy();
+							}), 1500);
+							return d;
+						}
+					}
+				]
+			);
+
+			// Tests for doLayout parameter.
+			// When this parameter is true, the single ContentPane child is resized
+			// to match the size of the ContentPane.
+			var pane5;
+			doh.registerGroup("doLayout",
+				[
+					{
+						name: "simple",
+						setUp: function(t){
+							pane5 = new dijit.layout.ContentPane({
+								content:"<div dojoType='dijit.layout.StackContainer'></div>"
+							}, dojo.byId("pane5"));
+							console.log(pane5);
+						},
+						runTest: function(t){
+							// since there's just a single child it should be marked
+							// for layout/resize along w/the ContentPane
+							t.assertTrue(pane5._singleChild);
+						},
+						tearDown: function(t){
+							pane5.destroyRecursive();
+						}
+					},
+					{
+						name: "doLayout=false",
+						setUp: function(t){
+							pane5 = new dijit.layout.ContentPane({
+								content:
+									"<div dojoType='dijit.layout.StackContainer'></div>",
+								doLayout: false
+							}, dojo.byId("pane5"));
+						},
+						runTest: function(t){
+							// since doLayout=false shouldn't try to resize child
+							t.assertFalse(pane5._singleChild);
+						},
+						tearDown: function(t){
+							pane5.destroyRecursive();
+						}
+					},
+					{
+						name: "mixed content",
+						setUp: function(t){
+							pane5 = new dijit.layout.ContentPane({
+								content:
+									"<span>hello world</span>" +
+									"<div dojoType='dijit.layout.StackContainer'></div>"
+							}, dojo.byId("pane5"));
+						},
+						runTest: function(t){
+							// since there's plain HTML along with the widget, ContentPane shouldn't try to adjust
+							// this size of the widget (since that would cover up the other HTML)
+							t.assertFalse(pane5._singleChild);
+						},
+						tearDown: function(t){
+							pane5.destroyRecursive();
+						}
+					},
+					{
+						name: "two widgets",
+						setUp: function(t){
+							pane5 = new dijit.layout.ContentPane({
+								content:
+									"<div dojoType='dijit.layout.StackContainer'></div>" +
+									"<div dojoType='dijit.layout.StackContainer'></div>"
+							}, dojo.byId("pane5"));
+						},
+						runTest: function(t){
+							// since there are multiple children, neither should be marked
+							// for layout/resize along w/the ContentPane
+							t.assertFalse(pane5._singleChild);
+						},
+						tearDown: function(t){
+							pane5.destroyRecursive();
+						}
+					},
+					{
+						name: "dojo.data",
+						setUp: function(t){
+							pane5 = new dijit.layout.ContentPane({
+								content:
+									"<div dojoType='dojo.data.ItemFileReadStore' jsId='dd'></div>" +
+									"<div dojoType='dijit.layout.StackContainer' id='sc'></div>"
+							}, dojo.byId("pane5"));
+						},
+						runTest: function(t){
+							// there are two children but one is invisible, so the other should be marked
+							// for layout/resize along w/the ContentPane
+							t.assertTrue(dd);
+							t.assertTrue(dijit.byId("sc"));
+							t.assertEqual(pane5._singleChild, dijit.byId("sc"));
+						},
+						tearDown: function(t){
+							pane5.destroyRecursive();
+						}
+					},
+					{
+						name: "script tags ignored",
+						setUp: function(t){
+							pane5 = new dijit.layout.ContentPane({
+								content:
+									"<scri" + "pt></scri" + "pt>" +
+									"<div dojoType='dijit.layout.StackContainer' id='sc'></div>"
+							}, dojo.byId("pane5"));
+						},
+						runTest: function(t){
+							// script tag should be ignored, should be detected as single child
+							t.assertTrue(pane5._singleChild, "script tag ignored, marked as single child");
+						},
+						tearDown: function(t){
+							pane5.destroyRecursive();
+						}
+					}
+				]
+			);
+
+			dojo.declare("dijit.TestContained",
+				dijit.layout._LayoutWidget, {
+					startup: function(){
+						this.inherited(arguments);
+						this._started = true;
+					},
+					resize: function(){
+						this.inherited(arguments);
+						this._resized = true;
+					}
+				}
+			);
+
+			var container;
+			doh.register("ContentPane as _Container-like widget",
+				[
+					{
+						name: "creation",
+						runTest: function(t){
+							container = new dijit.layout.ContentPane();
+							container.placeAt(dojo.body(), "last");
+							container.startup();
+							t.is(0, container.getChildren().length, "number of children before set('content', ...)");
+							container.set('content',
+								'<span>plain non-widget content</span>' +
+								'<div><span>' +
+									'<div id="zero" dojoType="dijit.TestContained"></div>' +
+									'<div id="one" dojoType="dijit.TestContained"></div>' +
+								'</span></div>' +
+								'<div id="two" dojoType="dijit.TestContained"></div>' +
+								'<div id="three" dojoType="dijit._Widget"></div>'
+							);
+
+							// Since ContentPane is a container it should call startup
+							// on it's children
+							t.t(dijit.byId('two')._started, "started");
+
+							// Also, Layout widgets expect resize() to be
+							// called by their parent
+							t.t(dijit.byId('two')._resized, "resized");
+						}
+					},
+					{
+						name: "getChildren",
+						runTest: function(t){
+							var children = container.getChildren();
+							t.is(4, children.length, "number of children");
+							t.is("zero", children[0].id);
+							t.is("one", children[1].id);
+							t.is("two", children[2].id);
+							t.is("three", children[3].id);
+						}
+					},
+
+					{
+						name: "deferred resize",
+						runTest: function(t){
+							// This tests that startup isn't called on the child widgets
+							// until the contentpane is made visible
+
+							var hiddenCP = new dijit.layout.ContentPane({style: {display: "none"}});
+							hiddenCP.placeAt(dojo.body(), "last");
+							hiddenCP.startup();
+
+							t.is(0, hiddenCP.getChildren().length, "number of children before set('content', ...)");
+							hiddenCP.set('content',
+								'<span>plain non-widget content</span>' +
+								'<div><span>' +
+									'<div id="deferredZero" dojoType="dijit.TestContained"></div>' +
+									'<div id="deferredOne" dojoType="dijit.TestContained"></div>' +
+								'</span></div>' +
+								'<div id="deferredTwo" dojoType="dijit.TestContained"></div>' +
+								'<div id="deferredThree" dojoType="dijit._Widget"></div>'
+							);
+
+							t.f(dijit.byId('deferredTwo')._resized, "not resized yet");
+
+							hiddenCP.set("style", {display: "block"});
+							hiddenCP._onShow();
+
+							t.t(dijit.byId('deferredTwo')._resized, "resized");
+						}
+					}
+
+/***
+					,
+					{
+						name: "addChild",
+						runTest: function(t){
+							var afterTwo = new dijit.TestContained({id: "twoPointFive"});
+							container.addChild(afterTwo, 3);
+
+							// Make sure child was added and is in order
+							var children = container.getChildren();
+							t.is(5, children.length);
+							t.is("zero", children[0].id);
+							t.is("one", children[1].id);
+							t.is("two", children[2].id);
+							t.is("twoPointFive", children[3].id);
+							t.is("three", children[4].id);
+
+							// Since ContentPane is a container it should call startup
+							// on it's children
+							t.t(afterTwo._started, "started");
+
+							// Also, Layout widgets expect resize() to be
+							// called by their parent
+							t.t(afterTwo._resized, "resized");
+						}
+					},
+					{
+						name: "removeChild",
+						runTest: function(t){
+							var children = container.getChildren();
+							t.is(5, children.length);
+							container.removeChild(dijit.byId("zero"));
+							container.removeChild(1); // should remove "two" - because zero is already removed
+							children = container.getChildren();
+							t.is(3, children.length);
+							t.is("one", children[0].id);
+							t.is("three", children[2].id);
+						}
+					}
+****/
+				]
+			);
+
+			doh.run();
+		});
+	</script>
+</head>
+<body class="claro">
+	<h2>dijit.layout.ContentPane DOH test</h2>
+	<h3>Test designed to run on localhost (minimize impact from network latency)</h3>
+
+	<h4>This should NOT be parsed automatically</h4>
+	<div dojoType="dijit.layout.ContentPane" class="box" id="pane1">
+		<div dojoType='dijit.TestWidget'>If this has a different background and a red border, the page parsed when it shouldn't</div>
+	</div>
+	<br/><h3>Testing ContentPane</h3>
+	<div id='pane2' class='box'>
+		Even though the entire page isn't scanned for widgets,
+		any sub widgets of a ContentPane will be created when a ContentPane is created<br/>
+		<span id="zero" dojoType='dijit.TestWidget'>This should have a backgroundcolor and a border</span>
+		<div id="one" dojoType="dijit._Widget"></div>
+		<div id="two" dojoType="dijit._Widget"></div>
+		<div id="three" dojoType="dijit._Widget"></div>
+	</div>
+	<br/><br/>
+	<div id='stackcontainer'></div>
+	<div id="pane5"></div>
+
+	<!-- for container tests -->
+	<div id="container" dojoType="dijit.layout.ContentPane">
+		<div id="zero" dojoType="dijit.TestContained"></div>
+		<div id="one" dojoType="dijit.TestContained"></div>
+		<div id="two" dojoType="dijit.TestContained"></div>
+		<div id="three" dojoType="dijit._Widget"></div>
+	</div>
+	<div id="outside" dojoType="dijit._Widget"></div>
+	<div id="outsideCont" dojoType="dijit.TestContained"></div>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/ContentPaneLayout.html b/dijit/tests/layout/ContentPaneLayout.html
new file mode 100644
index 0000000..ac143ff
--- /dev/null
+++ b/dijit/tests/layout/ContentPaneLayout.html
@@ -0,0 +1,651 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>ContentPane layout-related DOH test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../themes/tundra/tundra.css";
+		@import "../css/dijitTests.css";
+
+		.resizableWidget {
+			border: 1px dashed red;
+			background-color: #C0E209 ;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit._Widget");
+		dojo.require("dijit._Templated");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.TitlePane");
+		dojo.require("dijit.Dialog");
+
+		// widgets used in doc loaded via href
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.Button");
+
+		// create a do nothing, only for test widget
+		dojo.declare("ResizableWidget",
+			[dijit._Widget, dijit._Templated], {
+			templateString: "<span class='resizableWidget'>resizable widget</span>",
+			_resized: 0,
+			_resizeArgs: null,
+			resize: function(){
+				this._resized++;
+				this._resizeArgs = arguments;
+			}
+		});
+
+		// Keep track of which panes have had a load event, and how
+		// many load events have occured for those panes
+		var loadEvents = {
+		};
+		function myOnLoad(){
+			console.log("onload for " + this);
+			loadEvents[this.id] = (loadEvents[this.id] || 0) + 1;
+		}
+
+		dojo.addOnLoad(function(){
+
+			// Keep track of the number of startup() calls to every widget.
+			// Since the href's widgets haven't been created yet we monitor startup() calls on the prototype
+			var startups = {};
+			dojo.connect(dijit._Widget.prototype, "startup", function(){
+				startups[this.id] = (startups[this.id] || 0) + 1;
+			});
+
+			// Test that ContentPanes calls startup() on child widgets appropriately
+			// TODO: overlap here (and other places) with ContentPane.html?
+			doh.register("startup events",
+				{
+					name: "startup on href pane's children",
+					timeout: 5000,
+					runTest: function(t){
+						var d = new doh.Deferred();
+						// Wait for load events to occur (after fetching URL's)
+						setTimeout(d.getTestCallback(function(){
+							var pane1 = dijit.byId("pane1"),
+								children = pane1.getChildren();
+							doh.is(2, children.length, "found combobox and button");
+							doh.is(1, startups[children[0].id], "combobox started once");
+							doh.is(1, startups[children[0].id], "button started once");
+							
+							// startup of layout widgets is tested below, indirectly, by
+							// monitoring how man times resize is called etc. 
+						}), 4000);
+						return d;
+					}
+				}
+			);
+
+			// Test that ContentPanes defer their load until they are shown
+			doh.register("load events",
+				[
+					{
+						name: "initial conditions",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							// Wait for load events to occur (after fetching URL's)
+							setTimeout(d.getTestCallback(function(){
+								doh.is(1, loadEvents.pane1, "pane1");
+								dojo.forEach(["pane2", "innerPane1", "innerPane2", "bcPane1", "bcPane2"], function(pane){
+									doh.f(loadEvents[pane], pane, pane + " shouldn't be loaded");
+								});
+							}), 4000);
+							return d;
+						}
+					},
+					{
+						name: "reset href in hidden pane, pane2",
+						timeout: 2000,
+						runTest: function(t){
+							// Resetting an href on a hidden pane should have no effect
+							var d = new doh.Deferred();
+
+							dijit.byId("pane2").set("href", "doc0.html");
+							setTimeout(d.getTestCallback(function(){
+								doh.f(loadEvents.pane2, "pane2 shouldn't be loaded");
+							}), 750);
+
+							return d;
+						}
+					},
+					{
+						name: "reset href in hidden pane, innerPane1",
+						timeout: 2000,
+						runTest: function(t){
+							// Resetting an href on a hidden pane should have no effect
+							var d = new doh.Deferred();
+
+							dijit.byId("innerPane1").set("href", "doc1.html");
+							setTimeout(d.getTestCallback(function(){
+								doh.f(loadEvents.innerPane1, "innerPane1 shouldn't be loaded");
+							}), 750);
+
+							return d;
+						}
+					},
+					{
+						name: "reset href in hidden pane, bcPane2",
+						timeout: 2000,
+						runTest: function(t){
+							// Resetting an href on a hidden pane should have no effect
+							var d = new doh.Deferred();
+
+							dijit.byId("bcPane2").set("href", "doc0.html");
+							setTimeout(d.getTestCallback(function(){
+								doh.f(loadEvents.bcPane2, "bcPane2 shouldn't be loaded");
+							}), 750);
+
+							return d;
+						}
+					},
+					{
+						name: "selecting ContentPane causes it to load",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							dijit.byId("outerTC").selectChild(dijit.byId("pane2"));
+							setTimeout(d.getTestCallback(function(){
+								doh.is(1, loadEvents.pane2, "pane2");
+							}), 4000);
+
+							return d;
+						}
+					},
+					{
+						name: "selecting a TabContainer causes it's selected child to load",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							doh.f(loadEvents.innerPane1, "innerPane1 not loaded yet");
+							dijit.byId("outerTC").selectChild(dijit.byId("innerTC"));
+							setTimeout(d.getTestCallback(function(){
+								doh.is(1, loadEvents.innerPane1, "innerPane1 now loaded");
+							}), 4000);
+
+							return d;
+						}
+					},
+					{
+						name: "selecting a BorderContainer causes it's children to load",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							//doh.f(loadEvents.bcPane1, "bcPane1 not loaded");
+							//doh.f(loadEvents.bcPane2, "bcPane2 not loaded");
+
+							dijit.byId("outerTC").selectChild(dijit.byId("bc"));
+
+							setTimeout(d.getTestCallback(function(){
+								doh.is(1, loadEvents.bcPane1, "bcPane1");
+								doh.is(1, loadEvents.bcPane2, "bcPane2");
+							}), 4000);
+
+							return d;
+						}
+					}
+				]
+			);
+
+			// Keep track of which layout widgets each resize call to each layout widget,
+			// specifically whether each call specified a size or not.
+			// Since the href's widgets haven't been created yet we can't connect to their resize()
+			// methods, but we can monitor resize() on the prototype
+			var layoutResizes = {};
+			dojo.connect(dijit.layout._LayoutWidget.prototype, "resize", function(){
+				// this is the pointer to the widget, and arguments are newsize/curSize args to resize()
+				var ary = layoutResizes[this.id];
+				if(!ary){
+					ary = layoutResizes[this.id] = [];
+				}
+				ary.push(arguments);
+			});
+
+			doh.register("resize events",
+				[
+					// Test that when ContentPane w/single resizable child is shown,
+					// the child is sized to match the ContentPane
+					{
+						name: "single child",
+						runTest: function(t){
+							var child = dijit.byId("singleChildResizable");
+							doh.is(0, child._resized, "hasn't been shown yet so no resize events");
+
+							dijit.byId("resizeTC").selectChild(dijit.byId("singleChildPane"))
+
+							doh.t(child._resized, "got resize event");	// note: should only be 1 but currently gets 2
+							doh.t(child._resizeArgs && child._resizeArgs.length, "got size specified")
+
+							var size = child._resizeArgs[0];
+							doh.t(size && size.h, "non-0 height specified");
+							doh.t(size && size.w, "non-0 width specified");
+						}
+					},
+					// Test that when ContentPane w/multiple resizable children is shown,
+					// the children aren't sized to match the ContentPane, but we do call
+					// resize on them so they can lay themselves out
+					{
+						name: "multiple children",
+						runTest: function(t){
+							var child1 = dijit.byId("multipleChildResizable1"),
+								child2 = dijit.byId("multipleChildResizable2");
+
+							doh.is(0, child1._resized, "child1 hasn't been shown yet so no resize events");
+							doh.is(0, child2._resized, "child2 hasn't been shown yet so no resize events");
+
+							dijit.byId("resizeTC").selectChild(dijit.byId("multipleChildPanes"))
+
+							doh.t(child1._resized, "got resize event for child1");
+							doh.is(0, child1._resizeArgs && child1._resizeArgs.length, "no size specified for child1")
+							doh.t(child2._resized, "got resize event for child2");
+							doh.is(0, child2._resizeArgs && child2._resizeArgs.length, "no size specified for child2")
+						}
+					},
+
+					// Test that resize event works correctly for href w/single layout widget
+					{
+						name: "single resizable href",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							dijit.byId("resizeTC").selectChild(dijit.byId("singleChildHref"))
+
+							// Wait for load events to occur (after fetching URL's)
+							setTimeout(d.getTestCallback(function(){
+								// Check top level border container got sized to fit ContentPane
+								var child = dijit.byId("singleChildHrefBorderContainer");
+								doh.t(child, "href was loaded and top level BorderContainer was created")
+								doh.t(layoutResizes["singleChildHrefBorderContainer"], "got resize event");
+								doh.t(layoutResizes["singleChildHrefBorderContainer"][0].length, "got size specified")
+
+								var size = layoutResizes["singleChildHrefBorderContainer"][0][0];
+								doh.t(size && size.h, "non-0 height specified");
+								doh.t(size && size.w, "non-0 width specified");
+
+								// Check that resize() events also trickled down to inner TabContainer
+								var child2 = dijit.byId("singleChildHrefInnerTabContainer");
+								doh.t(child2, "inner TabContainer was created")
+								doh.t(layoutResizes["singleChildHrefInnerTabContainer"], "got resize event");
+								doh.is(0, layoutResizes["singleChildHrefInnerTabContainer"][0].length, "no size specified")
+							}), 4000);
+							return d;
+						}
+					},
+
+					// Test that resize event works correctly for href w/multiple layout widgets
+					{
+						name: "multiple resizable href",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							dijit.byId("resizeTC").selectChild(dijit.byId("multipleChildHref"))
+
+							// Wait for load events to occur (after fetching URL's)
+							setTimeout(d.getTestCallback(function(){
+								// Check that resize() done on TabContainer
+								var child = dijit.byId("multipleChildHrefTabContainer");
+								doh.t(child, "TabContainer was created")
+								doh.t(layoutResizes["multipleChildHrefTabContainer"], "got resize event");
+								doh.is(0, layoutResizes["multipleChildHrefTabContainer"][0].length, "no size specified")
+							}), 4000);
+							return d;
+						}
+					}
+				]
+			);
+
+			// Make sure that TitlePane loads it's href at the appropriate time, and also that
+			// it calls resize on it's children at the appropriate time (since that's the contract
+			// for layout widgets, and ContentPane is acting as a layout widget).
+			doh.register("TitlePane",
+				[
+				/***
+				 * test for #8197, uncomment when it's fixed.
+					{
+						name: "initially open, single child",
+						timeout: 2000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							var tp = dijit.byId("otpHsc");
+
+							// Allow time for href to load
+							setTimeout(d.getTestCallback(function(){
+								// Check that href loaded
+								doh.is(1, loadEvents["otpHsc"], "otpHsc loaded on page load");
+
+								// Check that resize() done on child
+								doh.t(layoutResizes["otpHscBorderContainer"], "got resize event");
+								doh.is(0, layoutResizes["otpHscBorderContainer"][0].length, "no size specified")
+							}), 750);
+
+							return d;
+						}
+					},
+				  */
+					{
+						name: "initially open, href multiple children",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							var tp = dijit.byId("otpHmc");
+
+							// Allow time for href to load
+							setTimeout(d.getTestCallback(function(){
+								// Check that href loaded
+								doh.is(1, loadEvents["otpHmc"], "otpHmc loaded on page load");
+
+								// Check that resize() done on children
+								doh.t(layoutResizes["otpHmcBorderContainer"], "got resize event for BC");
+								doh.t(layoutResizes["otpHmcTabContainer"], "got resize event for TC");
+								doh.is(0, layoutResizes["otpHmcBorderContainer"][0].length, "no size specified for BC")
+							}), 4000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "initially open, multiple children",
+						runTest: function(t){
+							var tp = dijit.byId("otpMc");
+
+							// Check that resize() done on children
+							doh.t(dijit.byId("otpMc_child1")._resized, "got resize event for child1");
+							doh.t(dijit.byId("otpMc_child2")._resized, "got resize event for child2");
+						}
+					},
+
+					{
+						name: "initially closed, href multiple children",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							doh.f(loadEvents["ctpHmc"], "ctpHmc load deferred until open");
+
+							var tp = dijit.byId("ctpHmc");
+							tp.set("open", true);
+
+							// Allow time for href to load, pane to expand, and resize to be called on children
+							setTimeout(d.getTestCallback(function(){
+								// Check that href loaded
+								doh.is(1, loadEvents["ctpHmc"], "ctpHmc loaded when expanded");
+
+								// Check that resize() done on children
+								doh.t(layoutResizes["ctpHmcBorderContainer"], "got resize event for BC");
+								doh.t(layoutResizes["ctpHmcTabContainer"], "got resize event for TC");
+								doh.is(0, layoutResizes["ctpHmcBorderContainer"][0].length, "no size specified for BC")
+							}), 4000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "initially closed, multiple children",
+						timeout: 2000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							doh.f(dijit.byId("ctpMc_child1")._resized, "resize event for child1 deferred");
+							doh.f(dijit.byId("ctpMc_child2")._resized, "resize event for child2 deferred");
+
+							var tp = dijit.byId("ctpMc");
+							tp.set("open", true);
+
+							// Allow time for pane to expand, and resize to be called on children
+							setTimeout(d.getTestCallback(function(){
+								// Check that resize() done on children
+								doh.t(dijit.byId("ctpMc_child1")._resized, "got resize event for child1");
+								doh.t(dijit.byId("ctpMc_child2")._resized, "got resize event for child2");
+							}), 750);
+
+							return d;
+						}
+					}
+				]
+			);
+
+			// Make sure that Dialog loads it's href when shown, and also that
+			// it calls resize on it's children when shown (since that's the contract
+			// for layout widgets, and ContentPane is acting as a layout widget).
+			doh.register("Dialog",
+				[
+					{
+						name: "href multiple children",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							doh.f(loadEvents["dlgHmc"], "dlgHmc load deferred until open");
+
+							var dlg = dijit.byId("dlgHmc");
+							dlg.show();
+
+							// Allow time for href to load, pane to expand, and resize to be called on children
+							setTimeout(d.getTestCallback(function(){
+								// Check that href loaded
+								doh.is(1, loadEvents["dlgHmc"], "dlgHmc loaded when expanded");
+
+								// Check that resize() done on children
+								doh.t(layoutResizes["dlgHmcBorderContainer"], "got resize event for BC");
+								doh.t(layoutResizes["dlgHmcTabContainer"], "got resize event for TC");
+								doh.is(0, layoutResizes["dlgHmcBorderContainer"][0].length, "no size specified for BC")
+							}), 4000);
+
+							return d;
+						},
+						tearDown: function(){
+							var dlg = dijit.byId("dlgHmc");
+							dlg.hide();
+						}
+					},
+
+					{
+						name: "multiple inlined children",
+						timeout: 2000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							doh.f(dijit.byId("dlgMc_child1")._resized, "resize event for child1 deferred");
+							doh.f(dijit.byId("dlgMc_child2")._resized, "resize event for child2 deferred");
+
+							var dlg = dijit.byId("dlgMc");
+							dlg.show();
+
+							// Allow time for pane to expand, and resize to be called on children
+							setTimeout(d.getTestCallback(function(){
+								// Check that resize() done on children
+								doh.t(dijit.byId("dlgMc_child1")._resized, "got resize event for child1");
+								doh.t(dijit.byId("dlgMc_child2")._resized, "got resize event for child2");
+							}), 750);
+
+							return d;
+						},
+						tearDown: function(){
+							var dlg = dijit.byId("dlgMc");
+							dlg.hide();
+						}
+					}
+				]
+			);
+
+			// Test that resizing a TabContainer doesn't reload href (when refreshOnShow=true), bug #8197
+			doh.register("TabContainer resize/reload tests",
+				[
+					{
+						name: "initial conditions",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							// Wait for load events to occur (after fetching URL's)
+							setTimeout(d.getTestCallback(function(){
+								doh.is(1, loadEvents.reloadTC_pane1, "pane1 loaded");
+							}), 4000);
+							return d;
+						}
+					},
+					{
+						name: "reload on reshow",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							dijit.byId("reloadTC").selectChild(dijit.byId("reloadTC_pane2"));
+							dijit.byId("reloadTC").selectChild(dijit.byId("reloadTC_pane1"));
+							setTimeout(d.getTestCallback(function(){
+								doh.is(2, loadEvents.reloadTC_pane1, "pane1 loaded again");
+							}), 4000);
+							return d;
+						}
+					},
+					{
+						name: "no reload on TabContainer resize",
+						timeout: 5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							dijit.byId("reloadTC").resize({h: 300, w: 300});
+							setTimeout(d.getTestCallback(function(){
+								doh.is(2, loadEvents.reloadTC_pane1, "pane1 not loaded again");
+							}), 4000);
+							return d;
+						}
+					}
+				]
+			);
+
+			doh.run();
+		});
+
+	</script>
+</head>
+<body class="claro">
+	<h2>dijit.layout.ContentPane layout related DOH test</h2>
+
+	<p>
+		Tests ContentPane in it's role as a layout widget, including as child of another layout widgets (especially TabContainer).
+	</p>
+	<hr>
+
+	<p>Tests that href gets loaded when ContentPane is first made visible:</p>
+	<div dojoType="dijit.layout.TabContainer" id="outerTC" style="width: 880px; height: 200px;">
+		<div dojoType="dijit.layout.ContentPane" id="pane1" href="doc0.html" title="Initially Selected" onLoad="myOnLoad">
+			initially selected pane
+		</div>
+		<div dojoType="dijit.layout.ContentPane" id="pane2" href="doc1.html" title="Initially Hidden" onLoad="myOnLoad">
+			unselected pane
+		</div>
+		<div dojoType="dijit.layout.TabContainer" id="innerTC" nested="true" title="Nested TabContainer">
+			<div dojoType="dijit.layout.ContentPane" id="innerPane1" href="doc0.html" title="Initially Selected" onLoad="myOnLoad">
+				initially selected inner pane
+			</div>
+			<div dojoType="dijit.layout.ContentPane" id="innerPane2" href="doc1.html" title="Initially Hidden" onLoad="myOnLoad">
+				unselected pane
+			</div>
+		</div>
+		<div dojoType="dijit.layout.BorderContainer" id="bc" title="BorderContainer">
+			<div dojoType="dijit.layout.ContentPane" id="bcPane1" href="doc0.html" region="left" style="width: 200px;" onLoad="myOnLoad">
+				left pane
+			</div>
+			<div dojoType="dijit.layout.ContentPane" id="bcPane2" href="doc1.html" region="center" onLoad="myOnLoad">
+				center pane
+
+				<!-- when this ContentPane is shown each of these widgets should get a resize()
+				 	 call w/no size specification -->
+				<div dojoType="ResizableWidget" id="bcResizable1"></div>
+				<div dojoType="ResizableWidget" id="bcResizable2"></div>
+			</div>
+		</div>
+	</div>
+
+	<p>Tests for resizing in a layout container hierarchy:</p>
+	<div dojoType="dijit.layout.TabContainer" id="resizeTC" style="width: 880px; height: 200px;">
+		<div dojoType="dijit.layout.ContentPane" id="resizePane1" title="Initially Selected" onLoad="myOnLoad">
+			initially selected pane
+		</div>
+		<div dojoType="dijit.layout.ContentPane" id="singleChildPane" title="Single ResizableChild" onLoad="myOnLoad">
+			<div dojoType="ResizableWidget" id="singleChildResizable"></div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" id="multipleChildPanes" title="Multiple ResizableChild" onLoad="myOnLoad">
+			<div dojoType="ResizableWidget" id="multipleChildResizable1"></div>
+			<div style="border: groove blue medium;">
+				<span>hide the second widget to see if ContentPane can still find it</span>
+				<div dojoType="ResizableWidget" id="multipleChildResizable2"></div>
+				<span>ending text</span>
+			</div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" id="singleChildHref" title="Href Single Child"
+			href="borderContainer.php?id=singleChildHref" onLoad="myOnLoad"></div>
+		<div dojoType="dijit.layout.ContentPane" id="multipleChildHref" title="Href Multiple Children"
+			href="multipleLayoutWidgets.php?id=multipleChildHref" onLoad="myOnLoad"></div>
+	</div>
+
+	<p>Tests that ContentPane resize doesn't trigger reload:</p>
+	<div dojoType="dijit.layout.TabContainer" id="reloadTC" style="width: 880px; height: 200px;">
+		<div dojoType="dijit.layout.ContentPane" id="reloadTC_pane1" href="doc0.html" title="Initially Selected" onLoad="myOnLoad" refreshOnShow=true>
+			initially selected pane
+		</div>
+		<div dojoType="dijit.layout.ContentPane" id="reloadTC_pane2" href="doc1.html" title="Initially Hidden" onLoad="myOnLoad">
+			unselected pane
+		</div>
+	</div>
+
+	<p>Test the ContentPane loads href and resizes children (as per it's contract a layout widget)
+			when it's not a child of a layout container itself:</p>
+	<div dojoType="dijit.TitlePane" id="ctpHsc" title="Closed TitlePane Href Single Child" open=false
+		href="borderContainer.php?id=ctpHsc&sized=true" onLoad="myOnLoad"></div>
+	<br><br>
+
+	<div dojoType="dijit.TitlePane" id="ctpHmc" title="Closed TitlePane Href Multiple Children" open=false
+		href="multipleLayoutWidgets.php?id=ctpHmc" onLoad="myOnLoad"></div>
+	<br><br>
+
+	<div dojoType="dijit.TitlePane" id="otpHsc" title="Opened TitlePane Href Single Child"
+		href="borderContainer.php?id=otpHsc&sized=true" onLoad="myOnLoad"></div>
+	<br><br>
+
+	<div dojoType="dijit.TitlePane" id="otpHmc" title="Opened TitlePane Href Multiple Children"
+		href="multipleLayoutWidgets.php?id=otpHmc" onLoad="myOnLoad"></div>
+	<br><br>
+
+	<div dojoType="dijit.TitlePane" id="otpMc" title="Opened TitlePane Multiple Children">
+		<!-- these widgets should get a resize on page load -->
+		<div dojoType="ResizableWidget" id="otpMc_child1"></div>
+		<div dojoType="ResizableWidget" id="otpMc_child2"></div>
+	</div>
+	<br><br>
+
+	<div dojoType="dijit.TitlePane" id="ctpMc" title="Closed TitlePane Multiple Children" open=false>
+		<!-- these widgets should get a resize() when the TitlePane is opened -->
+		<div dojoType="ResizableWidget" id="ctpMc_child1"></div>
+		<div dojoType="ResizableWidget" id="ctpMc_child2"></div>
+	</div>
+	<br><br>
+
+	<div dojoType="dijit.Dialog" id="dlgHmc" title="Dialog Href Multiple Children"
+		href="multipleLayoutWidgets.php?id=dlgHmc" onLoad="myOnLoad"></div>
+
+	<div dojoType="dijit.Dialog" id="dlgMc" title="Dialog Multiple Children">
+		<!-- these widgets should get a resize() when the Dialog is opened -->
+		<div dojoType="ResizableWidget" id="dlgMc_child1"></div>
+		<div dojoType="ResizableWidget" id="dlgMc_child2"></div>
+	</div>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/TabContainer.html b/dijit/tests/layout/TabContainer.html
new file mode 100644
index 0000000..ab2222f
--- /dev/null
+++ b/dijit/tests/layout/TabContainer.html
@@ -0,0 +1,479 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>TabContainer Test</title>
+
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../helpers.js"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+
+	<script type="text/javascript">
+		dojo.require('doh.runner');
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		// create a do nothing, only for test widget
+		dojo.addOnLoad(function(){
+
+			doh.register("creationAndDestruction", [
+
+				// Test that destroyRecursive removes all supporting widgets, including the list-of-tabs menu
+				// and the close menu
+				{
+					name: 'destroyRecursive',
+					runTest: function(t){
+						var num = dijit.registry.length;
+	
+						var tc = new dijit.layout.TabContainer({ id:"creationAndDestruction", useMenu:true }).placeAt(dojo.body());
+						tc.addChild(new dijit.layout.ContentPane({title: "test pane 1", closable: true}));
+						tc.addChild(new dijit.layout.ContentPane({title: "test pane 2"}));
+						tc.startup();
+	
+						tc.destroyRecursive();
+	
+						t.assertEqual(dijit.registry.length, num);
+					}
+				},
+	
+				// Tests that creating a TabContainer creates the list-of-tabs Menu.
+				// (Note though that TabContainer doesn't need to create that Menu until the user presses the show-menu Button)
+				{
+					name: 'createWithMenu',
+					runTest: function(t){
+						var numMenus = dijit.registry.byClass("dijit.Menu").length;
+						var tc = new dijit.layout.TabContainer({ id:"createWithMenu", useMenu:true }).placeAt(dojo.body());
+						
+						var numCreatedMenus = dijit.registry.byClass("dijit.Menu").length;
+						t.assertEqual(numMenus + 1, numCreatedMenus);
+	
+						tc.destroyRecursive();
+					}
+				},
+	
+				// Tests that creating a TabContainer with useMenu=false doesn't create a list-of-tabs Menu.
+				{
+					name: 'createWithoutMenu',
+					runTest: function(t){
+						var numMenus = dijit.registry.byClass("dijit.Menu").length;
+						var tc = new dijit.layout.TabContainer({ id:"createWithoutMenu", useMenu:false }).placeAt(dojo.body());
+						
+						var numCreatedMenus = dijit.registry.byClass("dijit.Menu").length;
+						t.assertEqual(numMenus, numCreatedMenus);
+	
+						tc.destroyRecursive();
+					}
+				},
+				
+				// Check that tab labels for initial tabs are created
+				{
+					name: 'checkTabLabels',
+					runTest: function(t){
+						var tabLabels = dojo.query("#tc1 .tabLabel");
+						t.assertEqual(4, tabLabels.length);
+					}
+				}
+			]);
+			
+			doh.register("addingTabs", [
+
+				// Test that adding a pane creates new tab button and new menu item
+				{
+					name: 'add new tab',
+					runTest: function(t){
+						var tc = dijit.byId("tc1");
+						var cp1 = new dijit.layout.ContentPane({
+								id: "newTab1",
+						         title: "newTab1",
+						         content: "newTab1 content"
+						    });
+						tc.addChild(cp1);
+						
+						var tabLabels = dijit.byId("tc1").getChildren();
+						var menuLabels = dijit.byId("tc1_tablist_menu").getChildren();
+						
+						t.assertEqual(5, tabLabels.length, "there are 5 tabs");
+						t.assertEqual(5, menuLabels.length, "there are 5 menu items");
+					}
+				},
+				
+				// Test that scroll buttons show up when tab buttons overflow
+				{
+					name: 'addTabsOverflowMenu',
+					runTest: function(t){
+						var tc = dijit.byId("tc1");
+						
+						var cp2 = new dijit.layout.ContentPane({
+						         id: "newTab2",
+						         title: "newTab2",
+						         content: "newTab2 content"
+							});
+						tc.addChild(cp2);
+						
+						var left = dojo.byId("tc1_tablist_leftBtn");
+						var right = dojo.byId("tc1_tablist_rightBtn");						
+						var menu = dojo.byId("tc1_tablist_menuBtn");
+
+						t.assertTrue(left, "verify left scroll button exists");
+						t.assertTrue(right, "verify right scroll button exists");
+						t.assertTrue(menu, "verify dropdown menu button exists");
+							
+						t.assertTrue(isVisible(left), "left scroll is displayed");
+						t.assertTrue(isVisible(right), "right scroll is displayed");
+						t.assertTrue(isVisible(menu), "menu is displayed");	
+					}
+				}
+			]);
+
+			doh.register("selectingTabs", [
+
+				// Check that tab button is scrolled into view when tab is selected
+				{
+					name: 'isVisible',
+					timeout: 10000,
+					runTest: function(t){
+						var d = new doh.Deferred();
+						
+						var tc = dijit.byId("tc1");
+						var cp = dijit.byId("newTab1");
+
+						tc.selectChild(cp);
+						
+						setTimeout(d.getTestCallback(function(){
+								var cpLeft = dojo.byId("tc1_tablist_leftBtn");
+								var left = dojo.position(cpLeft).x + dojo.position(cpLeft).w;
+
+								var cpRight = dojo.byId("tc1_tablist_rightBtn");
+								var right = dojo.position(cpRight).x;
+
+								var tab = dijit.byId("tc1_tablist_newTab1");
+								var tabLeft = dojo.position(tab.domNode).x;
+								var tabRight = dojo.position(tab.domNode).x + dojo.position(tab.domNode).w;
+								
+								var isTabVisible = ((tabLeft > left) && (tabRight < right));
+								doh.t(isTabVisible, "verify chosen tab is in viewable area");
+						}), 1000);
+						
+						return d;
+					}
+				}
+			]);
+
+			doh.register("icons", [
+				{
+					name: "initialIcon",
+					runTest: function(t){
+						var cp =  dijit.byId("cp4");
+						var menuTitle = dijit.byId("cp7_stcMi").label;
+						
+						t.assertEqual('plusIcon', cp.controlButton.iconClass, "an icon image is displayed");
+						t.assertEqual('plus', menuTitle, "the menu's text label is 'plus'");
+					}
+				},
+				{
+					name: "changeIcon",
+					runTest: function(t){
+						var cp =  dijit.byId("cp4");
+						cp.set("iconClass", "noteIcon"); 
+						cp.set("title", "note");
+						
+						var menuTitle = dijit.byId("cp7_stcMi").label;
+						
+						t.assertEqual('noteIcon', cp.controlButton.iconClass, "new icon is displayed in tab");
+						t.assertEqual('plus', menuTitle, "the menu's text label has changed");
+					}
+				},
+				{
+					name: "noTitle",
+					runTest: function(t){
+						var cp =  dijit.byId("cp7");
+						t.assertFalse(cp.controlButton.showLabel, "an icon exists, but there is no text label");
+					}
+				}
+			]);
+
+			doh.register("changeTabName", [
+				{
+					name: 'changeName',
+					runTest: function(t){
+						var cp = dijit.byId('cpTitle');
+						cp.set('title', 'newTitle');
+						
+						var title = dojo.query("#tc1_tablist_cpTitle span.tabLabel")[0];
+						var menuTitle = dijit.byId("cpTitle_stcMi").label;
+						
+						t.assertEqual('newTitle', innerText(title), "the tab's text label has changed");
+						t.assertEqual('newTitle', menuTitle, "the menu's text label has changed");
+					}
+				}
+			]);
+
+			doh.register("deletingTabs", [
+
+				// Check that deleting a pane removes the tab button, menu item, etc.
+				{
+					name: 'deleteTab',
+					runTest: function(t){
+						var tc1 = dijit.byId("tc1");
+						var cp = dijit.byId("cpTitle");
+						
+						tc1.removeChild(cp);
+						
+						var childPanes = tc1.getChildren();
+						var menuLabels = dijit.byId("tc1_tablist_menu").getChildren();
+						
+						t.assertEqual(5, childPanes.length, "verify there are now only 4 tabs instead of 5");
+						t.assertEqual(5,  menuLabels.length, "verify there are now only 4 menu items instead of 5");
+						t.assertTrue(cp.domNode, "verify that the deleted tab's content pane still exists on the page");
+
+						var label = dojo.byId("#tc1_tablist_cpTitle");
+						t.assertFalse(label, "verify that deleted tab's label does not exist");
+					}
+				},
+				
+				// Check that scroll buttons disappear when no longer needed
+				{
+					name: 'removedOverflowMenu',
+					runTest: function(t){
+						var tc = dijit.byId("tc3");
+						
+						var cp = dijit.byId('cp10');
+						tc.removeChild(cp);	
+						cp = dijit.byId('cp9');
+						tc.removeChild(cp);
+						cp = dijit.byId('cp8');
+						tc.removeChild(cp);
+						cp = dijit.byId('cp7');
+						tc.removeChild(cp);			
+						
+						var left = dijit.byId("tc3_tablist_leftBtn").domNode;
+						var right = dijit.byId("tc3_tablist_rightBtn").domNode;
+						var menu = dijit.byId("tc3_tablist_menuBtn").domNode;
+						
+						t.assertTrue(isHidden(left), "left scroll is hidden");
+						t.assertTrue(isHidden(right), "right scroll is hidden");
+						t.assertTrue(isHidden(menu), "menu is hidden");
+					}
+				}
+			]);
+
+			doh.register("closableTabs", [
+				{
+					name: "closeTab",
+					runTest: function(t){
+						var cp = dijit.byId("cp6");
+						var cp2 = dijit.byId("cp5");
+						
+						t.assertTrue(cp.controlButton.closeButton, "close button is displayed");
+						t.assertFalse(cp2.controlButton.closeButton, "close button is displayed");
+					}
+				}
+			]);		
+
+			doh.register("layoutTests", [
+				{
+					name: "topLeftRightBottom",
+					runTest: function(t){
+						var tc = dijit.byId("tc1");
+
+						// TODO: should test actual positions of tabs vs. content, not just settings
+						t.assertEqual('top', tc.tabPosition, "tabs are on the top of the container");
+						
+						tc.set("tabPosition", "left");						
+						t.assertEqual('left', tc.tabPosition, "tabs are on the left of the container");
+						
+						tc.set("tabPosition", "right");						
+						t.assertEqual('right', tc.tabPosition, "tabs are on the right of the container");
+						
+						tc.set("tabPosition", "bottom");						
+						t.assertEqual('bottom', tc.tabPosition, "tabs are on the bottom of the container");
+					}
+				},
+				{
+					name: "nested",
+					runTest: function(t){
+						var tc = dijit.byId("tcNested");
+
+						// TODO: check that nested CSS class applied in the right place
+						t.assertFalse(tc.nested, "parent TabContainer is not nested");
+						
+						var children = tc.getChildren();
+						t.assertEqual(2, children.length, "parent TabContainer has multiple children");
+						
+						t.assertTrue(children[1].nested, "second child of parent TabContainer has nested tabs");
+					}
+				},
+				{
+					name: "doLayoutFalse",
+					runTest: function(t){
+						var tc = dijit.byId("tcDoLayout");
+						var cps = tc.getChildren();
+
+						// TODO: should check that height of TabContainer itself changes when different
+						// tabs are selected
+						tc.selectChild(cps[1]);
+						var height1 = cps[0]._contentBox.h;
+						var height2 = cps[1]._contentBox.h;
+						
+						t.assertTrue(height1 < height2, "height changes with the content length");
+					}
+				},
+				{
+					name: "doLayoutTrue",
+					runTest: function(t){
+						var tc = dijit.byId("tc3");
+						var cps = tc.getChildren();
+						
+						// TODO: should check that height of TabContainer itself stays constant when different
+						// tabs are selected
+						tc.selectChild(cps[1]);
+						var height1 = cps[0]._contentBox.h;
+						var height2 = cps[1]._contentBox.h;
+						
+						t.assertTrue(height1 === height2, "height does not change with the content length");
+					}
+				}
+				
+			]);
+			doh.register("destroy widget", [
+				// TODO: looks like this can be moved up to be part of top group, creationAndDestruction?
+				{
+					name: 'destroyRecursive',
+					runTest: function(t){
+						var tcAmount = dijit.registry.byClass("dijit.layout.TabContainer").length - 1;
+
+						var tc = dijit.byId("tc1");
+						tc.destroyRecursive();
+						
+						var tc1 = dojo.query("#tc1");
+						var tcNewAmount = dijit.registry.byClass("dijit.layout.TabContainer").length;
+
+						t.assertEqual(0, tc1.length, "the html for the TabContainer is removed from the page");
+						t.assertEqual(tcAmount, tcNewAmount, "the amount of TabContainers on the page");
+					}
+				}
+			]);
+			doh.run();
+
+		});
+	</script>
+
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit layout.TabContainer tests</h1>
+	
+	<div dojoType="dijit.layout.TabContainer" style="width: 300px; height: 100px;" id="tc1">
+	  <div dojoType="dijit.layout.ContentPane" title="tab1" id="cpTitle" selected="true">
+	    Lorem ipsum and all around...
+	  </div>
+	  <div dojoType="dijit.layout.ContentPane" title="tab2">
+	    Lorem ipsum and all around - second...
+	  </div>
+	  <div dojoType="dijit.layout.ContentPane" id="t3" title="tab3" closable="true">
+	    Lorem ipsum and all around - last...
+	  </div>
+		 <div dojoType="dijit.layout.ContentPane" title="tab4" closable="true">
+		    Lorem ipsum and all around - last...
+		  </div>
+	</div>
+	
+	<div dojoType="dijit.layout.TabContainer" style="width: 300px; height: 100px;" id="tc2">
+	  <div dojoType="dijit.layout.ContentPane" id="cp1" title="tab1" selected="true">
+	    Lorem ipsum and all around...
+	  </div>
+	  <div dojoType="dijit.layout.ContentPane" id="cp2" title="tab2">
+	    Lorem ipsum and all around - second...
+	  </div>
+	  <div dojoType="dijit.layout.ContentPane" id="cp3" title="tab3" closable="true">
+	    Lorem ipsum and all around - last...
+	  </div>
+	</div>
+	
+	<div dojoType="dijit.layout.TabContainer" style="width: 300px; height: 100px;" id="tc3">
+	  	<div dojoType="dijit.layout.ContentPane" id="cp4" title="tab1" selected="true" iconClass="plusIcon">
+	    	Lorem ipsum and all around...
+	  	</div>
+	  	<div dojoType="dijit.layout.ContentPane" id="cp5" title="tab2">
+	    	 Lorem ipsum and all around - last...
+	            <br />
+	            <br />
+	            <br />
+	            Hmmm even more expanding tabs......
+	  	</div>
+	  	<div dojoType="dijit.layout.ContentPane" id="cp6" title="tab3" closable="true">
+	    	Lorem ipsum and all around - last...
+	  	</div>
+		<div dojoType="dijit.layout.ContentPane" id="cp7" title="plus" closable="true" iconClass="plusIcon" showTitle="false">
+	    	Lorem ipsum and all around - last...
+	  	</div>
+		<div dojoType="dijit.layout.ContentPane" id="cp8" title="tab4" closable="true">
+	    	Lorem ipsum and all around - last...
+	  	</div>
+		<div dojoType="dijit.layout.ContentPane" id="cp9" title="tab5" closable="true">
+	    	Lorem ipsum and all around - last...
+	  	</div>
+		<div dojoType="dijit.layout.ContentPane" id="cp10" title="tab6" closable="true">
+	    	Lorem ipsum and all around - last...
+	  	</div>
+	</div>
+	
+	<div dojoType="dijit.layout.TabContainer" style="width: 400px; height: 100px;" id="tcNested">
+	    <div dojoType="dijit.layout.TabContainer" title="Tab 1" nested="true">
+	        <div dojoType="dijit.layout.ContentPane" title="My first inner tab" selected="true">
+	            Lorem ipsum and all around...
+	        </div>
+	        <div dojoType="dijit.layout.ContentPane" title="My second inner tab">
+	            Lorem ipsum and all around - second...
+	        </div>
+	        <div dojoType="dijit.layout.ContentPane" title="My last inner tab">
+	            Lorem ipsum and all around - last...
+	        </div>
+	    </div>
+	    <div dojoType="dijit.layout.TabContainer" title="Tab 2" nested="true">
+	        <div dojoType="dijit.layout.ContentPane" title="My first inner tab" selected="true">
+	            Lorem ipsum and all around...
+	        </div>
+	        <div dojoType="dijit.layout.ContentPane" title="My second inner tab">
+	            Lorem ipsum and all around - second...
+	        </div>
+	        <div dojoType="dijit.layout.ContentPane" title="My last inner tab">
+	            Lorem ipsum and all around - last...
+	        </div>
+	    </div>
+	</div>
+	
+	<div dojoType="dijit.layout.TabContainer" id="tcDoLayout" style="width: 100%;" doLayout="false">
+	        <div dojoType="dijit.layout.ContentPane" title="My first tab" selected="true">
+	            Lorem ipsum and all around...
+	        </div>
+	        <div dojoType="dijit.layout.ContentPane" title="My second tab" closable="true">
+	            Lorem ipsum and all around - second...
+	            <br />
+	            Hmmm expanding tabs......
+	        </div>
+	        <div dojoType="dijit.layout.ContentPane" title="My last tab">
+	            Lorem ipsum and all around - last...
+	            <br />
+	            <br />
+	            <br />
+	            Hmmm even more expanding tabs......
+	        </div>
+	    </div>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dijit/tests/layout/_lorem.html b/dijit/tests/layout/_lorem.html
new file mode 100644
index 0000000..9b9d4c0
--- /dev/null
+++ b/dijit/tests/layout/_lorem.html
@@ -0,0 +1,3 @@
+<p>
+	lorem ipsum dolor. Check net tab for a new XHR.
+</p>
\ No newline at end of file
diff --git a/dijit/tests/layout/borderContainer.php b/dijit/tests/layout/borderContainer.php
new file mode 100644
index 0000000..1585325
--- /dev/null
+++ b/dijit/tests/layout/borderContainer.php
@@ -0,0 +1,32 @@
+<?php
+	// This file is loaded by the test files via ContentPane's href attribute.
+
+	// If you call this file like borderContainer.php?id=foo then the id's of the created widgets
+	// will be based on the string "foo"
+	$id = $_GET['id'];
+
+	// sized=true means that it will add a width/height to the BorderContainer
+?>
+<div dojoType="dijit.layout.BorderContainer"
+	id="<?=$id?>BorderContainer"
+	<?php
+		if($_GET['sized']){
+			print "style='width: 300px; height: 300px;'";
+		}
+	?>
+>
+	<div dojoType="dijit.layout.ContentPane" region="left" style="width: 200px;">
+		This file contains a single top-level BorderContainer layout widget.
+	</div>
+	<div dojoType="dijit.layout.ContentPane" region="center" onLoad="myOnLoad">
+		But it also has some nested layout widgets, and when this file is loaded the TabContainer and
+		BorderContainer below should get resize() called on them
+		<div dojoType="dijit.layout.TabContainer" id="<?=$id?>InnerTabContainer" style="width: 300px; height: 300px;">
+			<div dojoType="dijit.layout.ContentPane" title="Tab 1"><?=$id?> tab1</div>
+			<div dojoType="dijit.layout.ContentPane" title="Tab 2"><?=$id?> tab2</div>
+		</div>
+		<div dojoType="dijit.layout.BorderContainer" id="<?=$id?>InnerBorderContainer" style="width: 300px; height: 300px;">
+			<div dojoType="dijit.layout.ContentPane" region="center">inner border container</div>
+		</div>
+	</div>
+</div>
\ No newline at end of file
diff --git a/dijit/tests/layout/combotab.html b/dijit/tests/layout/combotab.html
new file mode 100644
index 0000000..c881761
--- /dev/null
+++ b/dijit/tests/layout/combotab.html
@@ -0,0 +1,11 @@
+<div dojoType="dojo.data.ItemFileReadStore" jsId="stateStore"
+	url="../_data/states.json"></div>
+State:
+<span id="editable" dojoType="dijit.InlineEditBox" editor="dijit.form.ComboBox"
+	editorParams="{value: 'California', store: stateStore, searchAttr: 'name', promptMessage: 'Please enter a state'}">
+	<script type="dojo/connect" event="onChange">
+		// connect to editable onChange event, Note that we dont need to disconnect
+		console.log('User selected:'+this.getValue());
+	</script>
+</span>
+
diff --git a/dijit/tests/layout/doc0.html b/dijit/tests/layout/doc0.html
new file mode 100644
index 0000000..f2fb959
--- /dev/null
+++ b/dijit/tests/layout/doc0.html
@@ -0,0 +1,14 @@
+<h1>Document 0</h1>
+This document has <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+(to check we're copying children around properly).<br />
+Plus some widgets and native fields:<br />
+<input value="native input">
+<select dojoType="dijit.form.ComboBox">
+	<option value="1">dijit</option>
+	<option value="2">form</option>
+	<option value="3">ComboBox</option>
+</select>
+<button>native button</button>
+<button dojoType="dijit.form.Button">dijit.Button</button><br>
+
+Here's some text that comes AFTER the button.
diff --git a/dijit/tests/layout/doc1.html b/dijit/tests/layout/doc1.html
new file mode 100644
index 0000000..2bff8c5
--- /dev/null
+++ b/dijit/tests/layout/doc1.html
@@ -0,0 +1,13 @@
+<!-- Used from test_RemotePane.html -->
+
+<h1> Document 1</h1>
+
+<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus risus. Praesent eu lacus et enim laoreet sollicitudin. Quisque mollis mi a lectus. Cras ante. Aliquam tempus justo laoreet justo. Vestibulum egestas feugiat nisi. Nulla ultrices consequat felis. Curabitur dignissim augue vel enim. Fusce tempus tempor mauris. Praesent suscipit pede in nunc. Duis mi neque, malesuada non, volutpat et, nonummy et, ante. Aliquam neque. Nulla rhoncus, turpis eget mattis molestie, magna nulla  [...]
+
+<p>Nulla massa lectus, porttitor vitae, dignissim vel, iaculis eget, mi. Vestibulum sed lorem. Nullam convallis elit id leo. Aliquam est purus, rutrum at, sodales non, nonummy a, justo. Proin at diam vel nibh dictum rhoncus. Duis nisl. Etiam orci. Integer hendrerit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In ac erat. Sed velit orci, sodales quis, commodo ut, elementum sed, nibh. Cras mattis vulputate nisl. Mauris eu nulla sed orci dig [...]
+
+<p>Praesent rutrum nunc quis felis. Morbi tempor. Quisque porta magna imperdiet magna. Ut gravida, ipsum eu euismod consectetuer, nisl lectus posuere diam, vel dignissim elit nisi sit amet lorem. Curabitur non nunc. Morbi metus. Nulla facilisi. Sed et ante. Etiam ac lectus. Duis tristique molestie sem. Pellentesque nec quam. Nullam pellentesque ullamcorper sem.</p>
+
+<p>Duis ut massa eget arcu porttitor pharetra. Curabitur malesuada nisi id eros. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Vivamus massa. Donec quis justo ut tortor faucibus suscipit. Vivamus commodo neque eget nulla. Donec imperdiet lacus condimentum justo. In sollicitudin magna vitae libero. Curabitur scelerisque libero et eros imperdiet cursus. Maecenas adipiscing. Integer imperdiet, neque ut fringilla semper, leo nisi tincidunt enim,  [...]
+
+<p>Morbi ante sapien, consequat non, consectetuer vitae, pharetra non, dui. Cras tempus posuere quam. Vestibulum quis neque. Duis lobortis urna in elit. Aliquam non tellus. Etiam nisi eros, posuere vel, congue id, fringilla in, risus. Duis semper rutrum risus. Nullam felis massa, lobortis sit amet, posuere tempor, mattis id, tellus. Nulla id arcu interdum risus commodo tincidunt. Vivamus pretium pulvinar pede. Vivamus eget erat. Cum sociis natoque penatibus et magnis dis parturient monte [...]
diff --git a/dijit/tests/layout/doc2.html b/dijit/tests/layout/doc2.html
new file mode 100644
index 0000000..1173b29
--- /dev/null
+++ b/dijit/tests/layout/doc2.html
@@ -0,0 +1,13 @@
+<!-- Used from test_RemotePane.html -->
+
+<h1> Document 2</h1>
+
+<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus risus. Praesent eu lacus et enim laoreet sollicitudin. Quisque mollis mi a lectus. Cras ante. Aliquam tempus justo laoreet justo. Vestibulum egestas feugiat nisi. Nulla ultrices consequat felis. Curabitur dignissim augue vel enim. Fusce tempus tempor mauris. Praesent suscipit pede in nunc. Duis mi neque, malesuada non, volutpat et, nonummy et, ante. Aliquam neque. Nulla rhoncus, turpis eget mattis molestie, magna nulla  [...]
+
+<p>Nulla massa lectus, porttitor vitae, dignissim vel, iaculis eget, mi. Vestibulum sed lorem. Nullam convallis elit id leo. Aliquam est purus, rutrum at, sodales non, nonummy a, justo. Proin at diam vel nibh dictum rhoncus. Duis nisl. Etiam orci. Integer hendrerit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In ac erat. Sed velit orci, sodales quis, commodo ut, elementum sed, nibh. Cras mattis vulputate nisl. Mauris eu nulla sed orci dig [...]
+
+<p>Praesent rutrum nunc quis felis. Morbi tempor. Quisque porta magna imperdiet magna. Ut gravida, ipsum eu euismod consectetuer, nisl lectus posuere diam, vel dignissim elit nisi sit amet lorem. Curabitur non nunc. Morbi metus. Nulla facilisi. Sed et ante. Etiam ac lectus. Duis tristique molestie sem. Pellentesque nec quam. Nullam pellentesque ullamcorper sem.</p>
+
+<p>Duis ut massa eget arcu porttitor pharetra. Curabitur malesuada nisi id eros. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Vivamus massa. Donec quis justo ut tortor faucibus suscipit. Vivamus commodo neque eget nulla. Donec imperdiet lacus condimentum justo. In sollicitudin magna vitae libero. Curabitur scelerisque libero et eros imperdiet cursus. Maecenas adipiscing. Integer imperdiet, neque ut fringilla semper, leo nisi tincidunt enim,  [...]
+
+<p>Morbi ante sapien, consequat non, consectetuer vitae, pharetra non, dui. Cras tempus posuere quam. Vestibulum quis neque. Duis lobortis urna in elit. Aliquam non tellus. Etiam nisi eros, posuere vel, congue id, fringilla in, risus. Duis semper rutrum risus. Nullam felis massa, lobortis sit amet, posuere tempor, mattis id, tellus. Nulla id arcu interdum risus commodo tincidunt. Vivamus pretium pulvinar pede. Vivamus eget erat. Cum sociis natoque penatibus et magnis dis parturient monte [...]
diff --git a/dijit/tests/layout/getResponse.php b/dijit/tests/layout/getResponse.php
new file mode 100644
index 0000000..4510547
--- /dev/null
+++ b/dijit/tests/layout/getResponse.php
@@ -0,0 +1,57 @@
+<?php
+	// this just bounces a message as a response, and optionally emulates network latency.
+
+	// default delay is 0 sec, to change:
+	// getResponse.php?delay=[Int milliseconds]
+
+	// to change the message returned
+	// getResponse.php?mess=whatever%20string%20you%20want.
+
+	// to select a predefined message
+	// getResponse.php?messId=0
+
+	error_reporting(E_ALL ^ E_NOTICE);
+
+	$delay = 1; // 1 micro second to avoid zero division in messId 2
+	if(isset($_GET['delay']) && is_numeric($_GET['delay'])){
+		$delay = (intval($_GET['delay']) * 1000);
+	}
+
+	if(isset($_GET['messId']) && is_numeric($_GET['messId'])){
+		switch($_GET['messId']){
+			case 0:
+				echo "<h3>WARNING This should NEVER be seen, delayed by 2 sec!</h3>";
+				$delay = 2;
+				break;
+			case 1:
+				echo "<div dojotype='dijit.TestWidget'>Testing attr('href', ...)</div>";
+				break;
+			case 2:
+				echo "<div dojotype='dijit.TestWidget'>Delayed attr('href', ...) test</div>
+					  <div dojotype='dijit.TestWidget'>Delayed by " . ($delay/1000000) . " sec.</div>";
+				break;
+			case 3:
+				echo "IT WAS the best of times, it was the worst of <a id='timeref' href='http://www.timeanddate.com/worldclock/'>times</a>, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way [...]
+				break;
+			case 4:
+				echo "There were a king with a large jaw and a queen with a plain face, on the throne of England; there were a king with a large jaw and a queen with a fair face, on the throne of France. In both countries it was clearer than crystal to the lords of the State preserves of loaves and fishes, that things in general were settled for ever.";
+				break;
+			case 5:
+				echo "It was the year of Our Lord one thousand seven hundred and seventy- five. Spiritual revelations were conceded to England at that favoured period, as at this. Mrs. Southcott had recently attained her five-and- twentieth blessed birthday, of whom a prophetic private in the Life Guards had heralded the sublime appearance by announcing that arrangements were made for the swallowing up of London and Westminster. Even the Cock-lane ghost had been laid only a round dozen of years, aft [...]
+				break;
+			default:
+				echo "unknown messId:". htmlentities($_GET['messId']);
+		}
+	}
+
+	if(isset($_GET['bounceGetStr']) &&  $_GET['bounceGetStr']){
+		echo "<div id='bouncedGetStr'>".htmlentities($_SERVER["QUERY_STRING"])."</div>";
+	}
+
+	if(isset($_GET['message']) && $_GET['message']){
+		echo htmlentities($_GET['message']);
+	}
+
+	usleep($delay);
+
+?>
diff --git a/dijit/tests/layout/module.js b/dijit/tests/layout/module.js
new file mode 100644
index 0000000..7e61101
--- /dev/null
+++ b/dijit/tests/layout/module.js
@@ -0,0 +1,20 @@
+dojo.provide("dijit.tests.layout.module");
+
+try{
+	doh.registerUrl("dijit.tests.layout.ContentPane", dojo.moduleUrl("dijit", "tests/layout/ContentPane.html"), 99999999);
+	doh.registerUrl("dijit.tests.layout.ContentPaneLayout", dojo.moduleUrl("dijit", "tests/layout/ContentPaneLayout.html"), 99999999);
+
+	doh.registerUrl("dijit.tests.layout.StackContainer", dojo.moduleUrl("dijit", "tests/layout/nestedStack.html"), 99999999); 
+
+	doh.registerUrl("dijit.tests.layout.TabContainer", dojo.moduleUrl("dijit", "tests/layout/TabContainer.html"), 99999999);
+	doh.registerUrl("dijit.tests.layout.robot.TabContainer_a11y", dojo.moduleUrl("dijit","tests/layout/robot/TabContainer_a11y.html"), 99999999);
+	doh.registerUrl("dijit.tests.layout.robot.TabContainer_mouse", dojo.moduleUrl("dijit","tests/layout/robot/TabContainer_mouse.html"), 99999999);
+
+	doh.registerUrl("dijit.tests.layout.AccordionContainer", dojo.moduleUrl("dijit", "tests/layout/AccordionContainer.html"), 99999999);
+	doh.registerUrl("dijit.tests.layout.robot.AccordionContainer_a11y", dojo.moduleUrl("dijit","tests/layout/robot/AccordionContainer_a11y.html"), 99999999);
+	doh.registerUrl("dijit.tests.layout.robot.AccordionContainer_mouse", dojo.moduleUrl("dijit","tests/layout/robot/AccordionContainer_mouse.html"), 99999999);
+
+	doh.registerUrl("dijit.tests.layout.robot.BorderContainer", dojo.moduleUrl("dijit", "tests/layout/robot/BorderContainer.html"), 99999999); 
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dijit/tests/layout/multipleLayoutWidgets.php b/dijit/tests/layout/multipleLayoutWidgets.php
new file mode 100644
index 0000000..9437111
--- /dev/null
+++ b/dijit/tests/layout/multipleLayoutWidgets.php
@@ -0,0 +1,14 @@
+<?php
+	// If you call this file like multipleLayoutWidgets.php?id=foo then the id's of the created widgets
+	// will be based on the string "foo"
+	$id = $_GET['id'];
+?>
+This file has some nested layout widgets, and when this file is loaded the TabContainer and
+BorderContainer below should get resize() called on them
+<div dojoType="dijit.layout.TabContainer" id="<?=$id?>TabContainer" style="width: 300px; height: 300px;">
+	<div dojoType="dijit.layout.ContentPane" title="Tab 1">doc4 tab1</div>
+	<div dojoType="dijit.layout.ContentPane" title="Tab 2">doc4 tab2</div>
+</div>
+<div dojoType="dijit.layout.BorderContainer" id="<?=$id?>BorderContainer" style="width: 300px; height: 300px;">
+	<div dojoType="dijit.layout.ContentPane" region="center">inner border container</div>
+</div>
\ No newline at end of file
diff --git a/dijit/tests/layout/nestedStack.html b/dijit/tests/layout/nestedStack.html
new file mode 100644
index 0000000..9713acf
--- /dev/null
+++ b/dijit/tests/layout/nestedStack.html
@@ -0,0 +1,194 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+	<title>TabContainerLite in StackContainer</title>
+	<link href="../../themes/tundra/tundra.css" rel="stylesheet" type="text/css" />
+	<link href="../../../dojo/resources/dojo.css" rel="stylesheet" type="text/css" />
+	<script type="text/javascript"
+			language="javascript"
+			src="../../../dojo/dojo.js"
+			djConfig="parseOnLoad: true, isDebug: true">
+	</script>
+	<script type="text/javascript" language="javascript">
+		dojo.require("doh.runner");
+		dojo.require("dijit.layout._LayoutWidget");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.StackContainer");
+		dojo.require("dijit.layout.StackController");
+		dojo.require("dijit.form.Button");
+
+		// This keeps track of which panes were resized, and their hidden/visible state
+		// when they were resized.
+		var resizeLog = {};
+
+		// This keeps track of how many times each pane was resized
+		var resizeCnt = {};
+
+		function onResize(widget){
+			// called when a ContentPane or TabContainer is resized
+			console.log("resize on " + widget.id + ", display is " + dojo.style(widget.domNode, "display"));
+			resizeLog[widget.id] = dojo.style(widget.domNode, "style");
+			resizeCnt[widget.id] = (resizeCnt[widget.id] || 0) + 1;
+		}
+
+		dojo.declare("dijit.TestLayoutContained",
+			dijit.layout._LayoutWidget, {
+				startup: function(){
+					this.inherited(arguments);
+					this._started = true;
+				},
+				resize: function(){
+					this.inherited(arguments);
+					this._contentBox = dojo.contentBox(this.domNode);
+					this._resized = true;
+				}
+			}
+		);
+
+		dojo.addOnLoad(function(){
+			doh.registerGroup("after load",
+				[
+					{
+						name: "TabContainer 1 visible and resized",
+						runTest: function(t){
+							doh.is(1, resizeCnt["tab1"], "TabContainer 1 was resized once");
+							doh.is("block", dojo.style(dijit.byId("tab1").domNode, "display"), "TabContainer 1 is visible");
+							doh.t(resizeLog["tab1"] != "none", "TabContainer 1 was visible when it was resized");
+						}
+					},
+					{
+						name: "TabContainer 1 content pane 1 visible and resized",
+						runTest: function(t){
+							doh.is(1, resizeCnt["tab1cp1"], "Tab 1 was resized once");
+							doh.is("block", dojo.style(dijit.byId("tab1cp1").domNode, "display"), "TabContainer1 Tab 1 is visible");
+							doh.t(resizeLog["tab1cp1"] != "none", "Tab 1 was visible when it was resized");
+						}
+					},
+					{
+						name: "TabContainer 1 content pane 2 hidden",
+						runTest: function(t){
+							doh.f(!"tab1cp2" in resizeCnt, "tab 2 hasn't been resized");
+							doh.is("none", dojo.style(dijit.byId("tab1cp2").domNode, "display"), "TabContainer1 Tab 2 is hidden");
+						}
+					},
+					{
+						name: "TabContainer 2 hidden and unsized",
+						runTest: function(t){
+							doh.f(!"tab2" in resizeCnt, "TabContainer 2 hasn't been resized");
+							doh.is("none", dojo.style(dijit.byId("tab2").domNode, "display"), "TabContainer 2 is hidden");
+						}
+					},
+					{
+						name: "TabContainer 2 content pane 1 unsized",
+						runTest: function(t){
+							doh.f(!"tab2cp1" in resizeCnt, "TabContainer 2 tab 1 hasn't been resized");
+						}
+					}
+				]);
+			doh.registerGroup("selecting TabContainer 2",
+				[
+					function setUp(){
+						dijit.byId("myStackContainerPR").selectChild("tab2");
+					},
+					{
+						name: "TabContainer 1 hidden",
+						runTest: function(t){
+							doh.is("none", dojo.style(dijit.byId("tab1").domNode, "display"), "TabContainer1 is hidden");
+						}
+					},
+					{
+						name: "TabContainer 2 visible and resized",
+						runTest: function(t){
+							doh.is(1, resizeCnt["tab2"], "TabContainer 2 was resized once");
+							doh.is("block", dojo.style(dijit.byId("tab2").domNode, "display"), "TabContainer 2 is visible");
+							doh.t(resizeLog["tab2"] != "none", "TabContainer 2 was visible when it was resized");
+						}
+					},
+					{
+						name: "TabContainer 2 content pane 1 visible and resized",
+						runTest: function(t){
+							doh.is(1, resizeCnt["tab2cp1"], "Tab 2 was resized once");
+							doh.is("block", dojo.style(dijit.byId("tab2cp1").domNode, "display"), "TabContainer2 Tab 1 is visible");
+							doh.t(resizeLog["tab2cp1"] != "none", "Tab 2 was visible when it was resized");
+						}
+					}
+				]);
+			doh.registerGroup("resize of ContentPane contents",
+				[
+					{
+						name: "nested layout widgets haven't been resized yet",
+						runTest: function(t){
+							doh.f(deferredOne._resized, "nested layout widget not yet resized");
+						}
+					},
+					{
+						name: "select tab 2 of TabContainer 2",
+						runTest: function(t){
+							dijit.byId("tab2").selectChild("tab2cp2");
+						}
+					},
+					{
+						name: "resize was called on nested layout widgets after tab was made visible",
+						runTest: function(t){
+							doh.is(1, resizeCnt["tab2cp2"], "Tab 2 was resized once");
+							doh.t(deferredOne._resized, "deferredOne nested layout widget was resized");
+
+							var sizeAtResize = deferredOne._contentBox;
+							doh.t(sizeAtResize.w > 50, "content box has measurable width of " + sizeAtResize.w);
+							doh.t(sizeAtResize.h > 10, "content box has measurable height of " + sizeAtResize.h);
+						}
+					}
+				]);
+			doh.run();
+		});
+	</script>
+</head>
+<body class="claro">
+	<h1>Integration: TabContainer in StackContainer</h1>
+	<br>
+	<button dojoType="dijit.form.Button" id="previousPR"
+		onClick="dijit.byId('myStackContainerPR').back()"><</button>
+	<span dojoType="dijit.layout.StackController" containerId="myStackContainerPR"></span>
+	<button dojoType="dijit.form.Button" id="nextPR"
+		onClick="dijit.byId('myStackContainerPR').forward()">></button>
+	<div id="myStackContainerPR" dojoType="dijit.layout.StackContainer"
+		style="height:150px; width: 400px;">
+			<div dojoType="dijit.layout.TabContainer" id="tab1" title="tab container 1">
+				<script type="dojo/connect" event="resize">
+					onResize(this);
+				</script>
+				<div dojoType="dijit.layout.ContentPane" id="tab1cp1" title="TC1/tab1" href="tab1.html">
+					<script type="dojo/connect" event="resize">
+						onResize(this);
+					</script>
+				</div>
+				<div dojoType="dijit.layout.ContentPane" id="tab1cp2" title="TC1/tab2" href="tab2.html">
+					<script type="dojo/connect" event="resize">
+						onResize(this);
+					</script>
+				</div>
+			</div>
+			<div dojoType="dijit.layout.TabContainer" id="tab2" title="tab container 2">
+				<script type="dojo/connect" event="resize">
+					onResize(this);
+				</script>
+				<div dojoType="dijit.layout.ContentPane" id="tab2cp1" title="TC2/tab 1" href="tab1.html">
+					<script type="dojo/connect" event="resize">
+						onResize(this);
+					</script>
+				</div>
+				<div dojoType="dijit.layout.ContentPane" id="tab2cp2" title="TC2/tab 2">
+					<script type="dojo/connect" event="resize">
+						onResize(this);
+					</script>
+					<div><span>
+						<div jsId="deferredZero" dojoType="dijit.TestLayoutContained">test nested layout widget</div>
+						<div jsId="deferredOne" dojoType="dijit.TestLayoutContained">another test nested layout widget</div>
+					</span></div>
+				</div>
+			</div>
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/layout/robot/AccordionContainer_a11y.html b/dijit/tests/layout/robot/AccordionContainer_a11y.html
new file mode 100644
index 0000000..f4297ee
--- /dev/null
+++ b/dijit/tests/layout/robot/AccordionContainer_a11y.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot AccordionContainer A11Y Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_AccordionContainer.html');
+				doh.register("Accordion A11Y tests",[
+					{
+						name: "basic operation",
+						timeout: 10000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							doh.robot.sequence(function(){
+								dojo.byId("beforeMarkupAccordion").focus();
+							}, 500, 500);
+
+							// Tab into accordion, landing on title of first pane
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(/A Simple Pane/.test(innerText(dojo.global.dijit._curFocus)), "tabbed to first pane's title");
+							}), 500);
+
+							// Use down arrow to get to second pane's title
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.f(/A Simple Pane/.test(innerText(dojo.global.dijit._curFocus)), "moved away from first pane's title");
+								doh.t(/Lazy Load Pane/.test(innerText(dojo.global.dijit._curFocus)), "moved to second pane's title");
+								doh.is("lazyLoadPane", dojo.global.dijit.byId("markupAccordion").get("selectedChildWidget").id, "second pane is now selected");
+							}), 500);
+
+							// Tab into second pane's content area, landing on link inside pane
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("WebA11y", innerText(dojo.global.dijit._curFocus), "tabbed into second pane");
+							}), 500);
+
+							// tab out of AccordionContainer
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("afterMarkupAccordion", dojo.global.dijit._curFocus.id, "tabbed out of accordion");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+				
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
\ No newline at end of file
diff --git a/dijit/tests/layout/robot/AccordionContainer_mouse.html b/dijit/tests/layout/robot/AccordionContainer_mouse.html
new file mode 100644
index 0000000..9a165a3
--- /dev/null
+++ b/dijit/tests/layout/robot/AccordionContainer_mouse.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot AccordionContainer Mouse Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_AccordionContainer.html');
+				doh.register("Accordion Mouse tests",[
+					{
+						name: "basic operation",
+						timeout: 10000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							// Click open second pane
+							doh.robot.mouseMoveAt("lazyLoadPane_button_title", 500);
+							doh.robot.mouseClick({left: true}, 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("lazyLoadPane", dojo.global.dijit.byId("markupAccordion").get("selectedChildWidget").id, "second pane is now selected");
+							}), 500);
+
+							// Click open fourth pane
+							doh.robot.mouseMoveAt("embeddedLayoutPane_button_title", 500);
+							doh.robot.mouseClick({left: true}, 2000);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("embeddedLayoutPane", dojo.global.dijit.byId("markupAccordion").get("selectedChildWidget").id, "fourth pane is now selected");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+				
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
\ No newline at end of file
diff --git a/dijit/tests/layout/robot/BorderContainer.html b/dijit/tests/layout/robot/BorderContainer.html
new file mode 100644
index 0000000..3412500
--- /dev/null
+++ b/dijit/tests/layout/robot/BorderContainer.html
@@ -0,0 +1,358 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot BorderContainer Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			function checkInside(/*Widget*/ child, /*Widget*/ parent){
+				// summary:
+				//		Test that child is fully inside of parent
+				var cp = dojo.position(child.domNode, true),
+					pp = dojo.position(parent.domNode, true);
+
+				doh.t(
+					cp.y > pp.y && cp.y+cp.h < pp.y+pp.h &&
+					cp.x > pp.x && cp.x+cp.w < pp.x+pp.w,
+					child.region + " inside " + parent.id + dojo.toJson(cp) + dojo.toJson(pp)
+				);
+			}
+			function checkAbove(/*String*/ comment, /*Widget*/ above, /*Widget*/ below){
+				// summary:
+				//		Test that child is fully inside of parent
+
+				var ap = dojo.position(above.domNode, true),
+					bp = dojo.position(below.domNode, true);
+
+				doh.t(ap.y+ap.h < bp.y,
+					comment + " " + above.region + " above " + below.region + dojo.toJson(ap) + dojo.toJson(bp)
+				);
+			}
+			function checkLeft(/*String*/ comment, /*Widget*/ left, /*Widget*/ right){
+				// summary:
+				//		Test that child is fully inside of parent
+
+				var lp = dojo.position(left.domNode, true),
+					rp = dojo.position(right.domNode, true);
+
+				doh.t(lp.x+lp.w < rp.x,
+					comment + " " + left.region + " to left of " + right.region + dojo.toJson(lp) + dojo.toJson(rp)
+				);
+			}
+
+			function checkBCpanes(/*BorderContainer*/ bc){
+				// summary:
+				//		Check that all the panes in this BorderContainer are in sane
+				//		positions relative to each other
+				var children = bc.getChildren(),
+					regions = {};
+
+				// Check all panes inside BorderContainer
+				dojo.forEach(children, function(child){
+					checkInside(child, bc);
+					regions[child.region] = child;
+				});
+
+				// Check pane positions relative to each other
+				dojo.forEach(children, function(child){
+					switch(child.region){
+						case "top":
+							dojo.forEach(bc.design == "sidebar" ? ["center", "bottom"] : ["left", "center", "right", "bottom"], function(region){
+								if(regions[region]){
+									checkAbove(bc.id, child, regions[region]);
+								}
+							});
+							break;
+						case "bottom":
+							dojo.forEach(bc.design == "sidebar" ? ["center", "top"] : ["left", "center", "right", "top"], function(region){
+								if(regions[region]){
+									checkAbove(bc.id, regions[region], child);
+								}
+							});
+							break;
+						case "left":
+							dojo.forEach(bc.design == "sidebar" ? ["top", "center", "bottom", "right"] : ["right"], function(region){
+								if(regions[region]){
+									checkLeft(bc.id, child, regions[region]);
+								}
+							});
+							break;
+						case "right":
+							dojo.forEach(bc.design == "sidebar" ? ["top", "center", "bottom", "left"] : ["left"], function(region){
+								if(regions[region]){
+									checkLeft(bc.id, regions[region], child);
+								}
+							});
+							break;
+					}
+				});
+			}
+
+			function within(/*Number*/ a, /*Number*/ b, /*Number*/ range){
+				// summary:
+				//		Returns true if a and b are within range
+				return Math.abs(a-b) <= range;
+			}
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_BorderContainer.html');
+
+				doh.register("API", [
+					function initialConditions(){
+						checkBCpanes(dijit.byId("border1"));
+						checkBCpanes(dijit.byId("border2"));
+					},
+
+					function resize(){
+						// current size of panes
+						var oTop = dojo.position(dojo.byId("border1-top")),
+							oLeft = dojo.position(dojo.byId("border1-left")),
+							oCenter = dojo.position(dojo.byId("border1-center")),
+							oRight = dojo.position(dojo.byId("border1-right")),
+							oBottom = dojo.position(dojo.byId("border1-bottom"));
+
+						// make whole BorderContainer 100px bigger (width and height)
+						var mb = dojo.marginBox("border1");
+						dijit.byId("border1").resize({w: mb.w + 100, h: mb.h + 100});
+
+						// new size of panes
+						var nTop = dojo.position(dojo.byId("border1-top")),
+							nLeft = dojo.position(dojo.byId("border1-left")),
+							nCenter = dojo.position(dojo.byId("border1-center")),
+							nRight = dojo.position(dojo.byId("border1-right")),
+							nBottom = dojo.position(dojo.byId("border1-bottom"));
+
+						doh.is(oTop.w + 100, nTop.w, "top width + 100");
+						doh.is(oTop.h, nTop.h, "top height unchanged");
+						doh.is(oCenter.w + 100, nCenter.w, "center width + 100");
+						doh.is(oCenter.h + 100, nCenter.h, "center height + 100");
+						doh.is(oBottom.w + 100, nBottom.w, "bottom width + 100");
+						doh.is(oBottom.h, nBottom.h, "bottom height unchanged");
+						doh.is(oLeft.w, nLeft.w, "left width unchanged");
+						doh.is(oLeft.h + 100, nLeft.h, "left height + 100");
+						doh.is(oRight.w, nRight.w, "right width unchanged");
+						doh.is(oRight.h + 100, nRight.h, "right height + 100");
+
+						// size BorderContainer back to original size
+						dijit.byId("border1").resize({w: mb.w, h: mb.h});
+
+						var nnTop = dojo.position(dojo.byId("border1-top")),
+							nnLeft = dojo.position(dojo.byId("border1-left")),
+							nnCenter = dojo.position(dojo.byId("border1-center")),
+							nnRight = dojo.position(dojo.byId("border1-right")),
+							nnBottom = dojo.position(dojo.byId("border1-bottom"));
+
+						doh.is(dojo.toJson(oTop), dojo.toJson(nnTop), "top after second resize");
+						doh.is(dojo.toJson(oCenter), dojo.toJson(nnCenter), "center after second resize");
+						doh.is(dojo.toJson(oBottom), dojo.toJson(nnBottom), "bottom after second resize");
+						doh.is(dojo.toJson(oLeft), dojo.toJson(nnLeft), "left after second resize");
+						doh.is(dojo.toJson(oRight), dojo.toJson(nnRight), "right after second resize");
+					},
+
+					function addRemovePanes(){
+						// current size of panes
+						var oLeft = dojo.position(dojo.byId("border1-left")),
+							oCenter = dojo.position(dojo.byId("border1-center")),
+							oRight = dojo.position(dojo.byId("border1-right")),
+							oBottom = dojo.position(dojo.byId("border1-bottom"));
+
+						// remove top pane... should expand left/center/right
+						dijit.byId("border1").removeChild(dijit.byId("border1-top"));
+
+						// new size of panes
+						var nLeft = dojo.position(dojo.byId("border1-left")),
+							nCenter = dojo.position(dojo.byId("border1-center")),
+							nRight = dojo.position(dojo.byId("border1-right")),
+							nBottom = dojo.position(dojo.byId("border1-bottom"));
+
+						doh.t(nLeft.h > oLeft.h, "left height increased");
+						doh.t(nCenter.h > oCenter.h, "center height increased");
+						doh.t(nRight.h > oRight.h, "left height increased");
+						doh.is(oBottom.h, nBottom.h, "bottom height didn't change");
+
+						// remove left pane... should just expand center pane
+						dijit.byId("border1").removeChild(dijit.byId("border1-left"));
+
+						// new size of panes
+						var nnCenter = dojo.position(dojo.byId("border1-center")),
+							nnRight = dojo.position(dojo.byId("border1-right")),
+							nnBottom = dojo.position(dojo.byId("border1-bottom"));
+
+						doh.t(nnCenter.w > nCenter.w, "center width increased");
+						doh.is(dojo.toJson(nRight), dojo.toJson(nnRight), "right stayed same");
+						doh.is(dojo.toJson(nBottom), dojo.toJson(nnBottom), "bottom stayed same");
+
+						// check that all panes sane
+						checkBCpanes(dijit.byId("border1"));
+
+						// put back left pane as the top pane
+						// Due to #11430 need to clear style info on the pane first
+						dijit.byId("border1-left").set({
+							region: "top",
+							style: {top: "auto", bottom: "auto", left: "auto", right: "auto", width: "auto", height: "auto"}
+						});
+						dijit.byId("border1").addChild(dijit.byId("border1-left"));
+
+						// check that all panes sane
+						checkBCpanes(dijit.byId("border1"));
+					}
+				]);
+
+				doh.register("mouse", [
+					{
+						name: "expand right pane",
+						timeout: 10000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							var oTop = dojo.position(dojo.byId("border2-top")),
+								oCenter = dojo.position(dojo.byId("border2-center")),
+								oRight = dojo.position(dojo.byId("border2-trailing")),
+								oBottom = dojo.position(dojo.byId("border2-bottom"));
+
+							// Drag slider to expand pane 
+							var size = dojo.position("border2-trailing_splitter");
+							doh.robot.mouseMoveAt("border2-trailing_splitter", 500);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt("border2-trailing_splitter", 500, 100,
+								size.w/2 + (dojo._isBodyLtr() ? -100 : 100), size.h/2);
+							doh.robot.mouseRelease({left: true}, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								var nTop = dojo.position(dojo.byId("border2-top")),
+									nCenter = dojo.position(dojo.byId("border2-center")),
+									nRight = dojo.position(dojo.byId("border2-trailing")),
+									nBottom = dojo.position(dojo.byId("border2-bottom"));
+					
+								doh.t(within(oRight.w + 100, nRight.w, 10), "right width went from " + oRight.w + " to " + nRight.w);
+								doh.t(within(oTop.w - 100, nTop.w, 10), "top width went from " + oTop.w + " to " + nTop.w);
+								doh.t(within(oCenter.w - 100, nCenter.w, 10), "center width went from " + oCenter.w + " to " + nCenter.w);
+								doh.t(within(oBottom.w - 100, nBottom.w, 10), "bottom width went from " + nBottom.w + " to " + nBottom.w);
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "shrink bottom pane",
+						timeout: 10000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							var oTop = dojo.position(dojo.byId("border2-top")),
+								oCenter = dojo.position(dojo.byId("border2-center")),
+								oRight = dojo.position(dojo.byId("border2-trailing")),
+								oBottom = dojo.position(dojo.byId("border2-bottom"));
+
+							// Drag slider to shrink pane 
+							var size = dojo.position("border2-bottom_splitter");
+							doh.robot.mouseMoveAt("border2-bottom_splitter", 500);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt("border2-bottom_splitter", 500, 100, size.w/2, size.h/2 + 10);
+							doh.robot.mouseRelease({left: true}, 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								var nTop = dojo.position(dojo.byId("border2-top")),
+									nCenter = dojo.position(dojo.byId("border2-center")),
+									nRight = dojo.position(dojo.byId("border2-trailing")),
+									nBottom = dojo.position(dojo.byId("border2-bottom"));
+					
+								doh.t(within(oBottom.h - 10, nBottom.h, 10), "bottom height went from " + oBottom.h + " to " + nBottom.h);
+								doh.t(within(oCenter.h + 10, nCenter.h, 10), "center height went from " + oCenter.h + " to " + nCenter.h);
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("keyboard", [
+					{
+						name: "tabIndex",
+						timeout: 10000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							doh.robot.sequence(function(){
+								dojo.byId("toggleLeftButton").focus();
+							}, 500, 500);
+
+							// Tab into second BorderContainer, landing on link
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("a link", innerText(dojo.global.dijit._curFocus), "tabbed to link");
+							}), 500);
+
+							// Tab past ComboBox to get to splitter for bottom panel
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("border2-bottom_splitter", dojo.global.dijit._curFocus.id, "focus on bottom splitter");
+							}), 500);
+
+							// Tab to get to splitter for right panel
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("border2-trailing_splitter", dojo.global.dijit._curFocus.id, "focus on bottom splitter");
+							}), 500);
+
+							// tab out of BorderContainer, into the next one
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("a link", innerText(dojo.global.dijit._curFocus), "tabbed to link in next BC");
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "expand/contract",
+						timeout: 10000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							var oSize, nSize;
+
+							// contract bottom pane
+							doh.robot.sequence(function(){
+								dojo.byId("border2-bottom_splitter").focus();
+								oSize = dojo.position("border2-bottom");
+							}, 500, 500);
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								nSize = dojo.position("border2-bottom");
+								doh.t(nSize.h < oSize.h, "contracted bottom pane");
+							}), 500);
+
+							// expand trailing pane
+							doh.robot.sequence(function(){
+								dojo.byId("border2-trailing_splitter").focus();
+								oSize = dojo.position("border2-trailing");
+							}, 500, 500);
+							doh.robot.keyPress(dojo._isBodyLtr() ? dojo.keys.LEFT_ARROW : dojo.keys.RIGHT_ARROW, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								nSize = dojo.position("border2-trailing");
+								doh.t(nSize.w > oSize.w, "expanded trailing pane");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
\ No newline at end of file
diff --git a/dijit/tests/layout/robot/TabContainer_a11y.html b/dijit/tests/layout/robot/TabContainer_a11y.html
new file mode 100644
index 0000000..bd34434
--- /dev/null
+++ b/dijit/tests/layout/robot/TabContainer_a11y.html
@@ -0,0 +1,278 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot TabContainer A11Y Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_TabContainer.html');
+				doh.register("basic navigation",[
+					{
+						name: "focus on first tab",
+						timeout: 10000,
+						runTest: function(t){
+								var d = new doh.Deferred();
+								doh.robot.sequence(function(){
+									dojo.query("button")[0].focus();
+								}, 500, 500);
+								
+								doh.robot.keyPress(dojo.keys.TAB, 500, {});
+								
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is("mainTabContainer_tablist_tab2", dojo.global.dijit._curFocus.id, "tabbing to focuses on selected Tab");
+								}), 500);
+
+								return d;
+						}
+					},
+					{
+						name: "move to tab with RIGHT button",
+						timeout: 10000,
+						runTest: function(t){
+								var d = new doh.Deferred();
+								
+								doh.robot.sequence(function(){
+									dojo.byId("mainTabContainer_tablist_tab2").focus();
+								}, 500, 500);
+								
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+								
+								doh.robot.sequence(d.getTestCallback(function(){
+									var tc = dijit.byId("mainTabContainer");
+									doh.is('mainTabContainer_tablist_tab3', dojo.global.dijit._curFocus.id, "currently chosen tab");
+									doh.is("tab3", tc.selectedChildWidget.id, "currently displayed pane");
+								}), 750);
+								return d;
+						}
+					},
+					{
+						name: "move to with LEFT button",
+						timeout: 10000,
+						runTest: function(t){
+								var d = new doh.Deferred();
+								
+								doh.robot.keyPress(dojo.keys.LEFT_ARROW, 500, {});
+								var tc = dijit.byId("mainTabContainer");
+								
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is('mainTabContainer_tablist_tab2', dojo.global.dijit._curFocus.id, "currently chosen tab");
+									doh.is("tab2", tc.selectedChildWidget.id, "currently chosen pane");
+								}), 750);
+								
+								return d;
+						}
+					},
+
+					
+					{
+						name: "TAB focus to nested tab",
+						timeout: 10000,
+						runTest: function(t){
+								var d = new doh.Deferred();
+								
+								doh.robot.sequence(function(){
+									dojo.byId("mainTabContainer_tablist_tab2").focus();
+								}, 500, 500);
+								
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 750, {});
+								doh.robot.keyPress(dojo.keys.TAB, 750, {});
+								
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is('inlined_tablist_tab2href', dojo.global.dijit._curFocus.id);
+								}), 500);
+								
+								return d;
+						}
+					},
+					{
+						name: "move through parent tabs from nested tabs",
+						timeout: 10000,
+						runTest: function(t){
+								var d = new doh.Deferred();
+								
+								doh.robot.sequence(function(){
+									dojo.byId("inlined_tablist_tab2href").focus();
+								}, 500, 500);
+								
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+								doh.robot.keyPress(dojo.keys.TAB, 750, {shift:true});
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+								
+								//verify that we can navigate to the top menu from a nested tab container
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is('mainTabContainer_tablist_tab3href', dojo.global.dijit._curFocus.id);
+								}), 750);
+								return d;
+						}
+					},
+					{
+						name: "verify nested tabs keep their state",
+						timeout: 10000,
+						runTest: function(t){
+								var d = new doh.Deferred();
+								
+								doh.robot.sequence(function(){
+									dojo.byId("mainTabContainer_tablist_tab3href").focus();
+								}, 500, 500);
+								
+								doh.robot.keyPress(dojo.keys.LEFT_ARROW, 500, {});
+								doh.robot.keyPress(dojo.keys.TAB, 750, {});	// give IE8 time to complete slide animation
+								
+								//verify that the second tab in Tab 1 is still focused
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is('inlined_tablist_subtab3', dojo.global.dijit._curFocus.id);
+								}), 500);
+								
+								return d;
+						}
+					}
+				]);
+
+				doh.register("closing tabs", [
+					{
+						name: "close tab with DELETE button",
+						timeout: 10000,
+						runTest: function(t){
+								var d = new doh.Deferred();
+								
+								doh.robot.sequence(function(){
+									dojo.byId("mainTabContainer_tablist_inlined").focus();
+								}, 500, 500);
+								
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+								doh.robot.keyPress(dojo.keys.DELETE, 750, {});
+
+								var tc = dijit.byId("mainTabContainer");
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is(6, tc.getChildren().length);
+								}), 500);
+								
+								return d;
+						}
+					},
+					{
+						name: "close tab with CTRL-W button",
+						timeout: 10000,
+						runTest: function(t){
+								var d = new doh.Deferred();
+								
+								doh.robot.sequence(function(){
+									dojo.byId("mainTabContainer_tablist_tab1").focus();
+								}, 500, 500);
+								
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 750, {});
+								if(dojo.isChrome){
+									// on chrome ctrl+w isn't trapped, and closes the whole browser!
+									doh.robot.keyPress(dojo.keys.DELETE, 750, {});
+								}else{
+									doh.robot.keyPress("w", 750, {ctrl:true});
+								}
+								
+								var tc = dijit.byId("mainTabContainer");
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is(5, tc.getChildren().length);
+								}), 500);
+								return d;
+						}
+					}
+				]);
+
+				// Run test about opening context menu via keyboard, except on:
+				//	- safari/mac where it doesn't work unless VoiceOver is turned on (#9927)
+				//	- webkit/win, where in suite mode (runTests.html), F10 triggers context menu
+				//		in both the iframe and the outer window
+				if(!dojo.isWebKit){
+					doh.register("closing tabs via context menu", {
+						name: "close tab through context menu",
+						timeout: 10000,
+						runTest: function(t){
+								var d = new doh.Deferred();
+								
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 750, {});
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 750, {});
+								
+								// open via keyboard
+								if(dojo.isMac){
+									doh.robot.keyPress(dojo.keys.SPACE, 500, {
+										ctrl: true
+									});
+								}else{
+									doh.robot.keyPress(dojo.keys.F10, 500, {
+										shift: true
+									});
+								}
+								
+								doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+								
+								var tc = dijit.byId("mainTabContainer");
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is(4, tc.getChildren().length);
+								}), 500);
+								
+								return d;
+						}
+					});
+				}
+
+				doh.register("up/down arrows", [
+					{
+						name: "move to tab with DOWN button",
+						timeout: 10000,
+						runTest: function(t){
+								var d = new doh.Deferred();
+								
+								doh.robot.sequence(function(){
+									dojo.byId("ltabs_tablist_HanselGretel1").focus();
+								}, 500, 500);
+								
+								doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+								var tc = dijit.byId("ltabs");
+								
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is('ltabs_tablist_GreenTwigs1', dojo.global.dijit._curFocus.id, "currently chosen tab");
+									doh.is("GreenTwigs1", tc.selectedChildWidget.id, "currently displayed pane");
+								}), 500);
+								return d;
+						}
+					},
+					{
+						name: "move to tab with UP button",
+						timeout: 10000,
+						runTest: function(t){
+								var d = new doh.Deferred();
+								
+								doh.robot.keyPress(dojo.keys.UP_ARROW, 500, {});
+								var tc = dijit.byId("ltabs");
+								
+								doh.robot.sequence(d.getTestCallback(function(){
+									doh.is('ltabs_tablist_HanselGretel1', dojo.global.dijit._curFocus.id, "currently chosen tab");
+									doh.is("HanselGretel1", tc.selectedChildWidget.id, "currently chosen pane");
+								}), 500);
+								
+								return d;
+						}
+					}
+				]);
+				
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
\ No newline at end of file
diff --git a/dijit/tests/layout/robot/TabContainer_mouse.html b/dijit/tests/layout/robot/TabContainer_mouse.html
new file mode 100644
index 0000000..4f6d636
--- /dev/null
+++ b/dijit/tests/layout/robot/TabContainer_mouse.html
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot TabContainer Mouse Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_TabContainer.html');
+				doh.register("mouse tests",[
+					
+					{
+						name: "tab hover state",
+						timeout: 10000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							// workaround DOH robot bug where iframe overlay not removed
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.mouseMoveAt('mainTabContainer_tablist_tab3', 500);
+							
+							doh.robot.sequence(d.getTestCallback(function(){
+								var tabHover = dojo.query(".dijitTabHover #mainTabContainer_tablist_tab3");
+								doh.is(1, tabHover.length);
+							}), 500);
+							
+							return d;
+						}
+					},
+					{
+						name: "click on a tab",
+						timeout: 10000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							doh.robot.mouseMoveAt('mainTabContainer_tablist_tab3', 500);
+							doh.robot.mouseClick({left: true}, 500);
+							doh.robot.mouseClick({left: true}, 500);
+							
+							var tc = dijit.byId("mainTabContainer");
+							
+							doh.robot.sequence(d.getTestCallback(function(){
+								// verify tab button is selected
+								doh.is('mainTabContainer_tablist_tab3', dojo.global.dijit._curFocus.id, "verify chosen tab is in its chosen state and focused");
+
+								// verify pane is shown
+								doh.is("tab3", tc.selectedChildWidget.id, "verify that the appropiate contentpane is displayed");
+								doh.t(isVisible(dijit.byId("tab3")), "tab3 shown");
+								doh.t(isHidden(dijit.byId("tab2")), "tab2 hidden");
+							}), 500);
+							
+							return d;
+						}
+					},
+					{
+						name: "close button hover state",
+						timeout: 10000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							doh.robot.mouseClick({left: true}, 500);
+							doh.robot.mouseMoveAt(dojo.query('#mainTabContainer_tablist_tab3 span.dijitTabCloseButton')[0], 500);
+							
+							// verify the close button is in its hover state
+							doh.robot.sequence(d.getTestCallback(function(){
+								var closeHover = dojo.query("#mainTabContainer_tablist_tab3 .dijitTabCloseButtonHover");
+								doh.is(1, closeHover.length);
+							}), 500);
+							
+							return d;
+						}
+					},
+					{
+						name: "close a tab",
+						timeout: 10000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							doh.robot.mouseMoveAt(dojo.query('#mainTabContainer_tablist_tab3 span.dijitTabCloseButton')[0], 500);
+							doh.robot.mouseClick({left: true}, 500);
+							
+							var tc = dijit.byId("mainTabContainer");
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(6, tc.getChildren().length);
+							}), 500);
+							
+							return d;
+						}
+					},
+					{
+						name: "choose a tab from TabContainer's menu",
+						timeout: 10000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							doh.robot.mouseMoveAt("mainTabContainer_tablist_menuBtn", 500);
+							doh.robot.mouseClick({left: true}, 500);
+							doh.robot.mouseMoveAt("tab4href_stcMi", 500);
+							doh.robot.mouseClick({left: true}, 1000);
+							
+							// verify SplitContainer tab is displayed (but it doesn't get focus, see #10727)
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Check that tab button is scrolled correctly into view
+								// TODO: this check won't work in RTL mode
+								var tc = dijit.byId("mainTabContainer");
+
+								var leftButton = dojo.byId("mainTabContainer_tablist_leftBtn");
+								var tablistLeft = dojo.position(leftButton).x + dojo.position(leftButton).w;
+	
+								var rightButton = dojo.byId("mainTabContainer_tablist_rightBtn");
+								var tablistRight = dojo.position(rightButton).x;
+	
+								var tab = dijit.byId("mainTabContainer_tablist_tab4href");
+	
+								var tabLeft = dojo.position(tab.domNode).x;
+								var tabRight = dojo.position(tab.domNode).x + dojo.position(tab.domNode).w;
+	
+								var isTabVisible = (tablistLeft < tabLeft && tablistRight > tabRight);
+
+								doh.t(isTabVisible, "verify tab is in display area")
+								
+								// And verify that pane is shown
+								doh.is("tab4href", tc.selectedChildWidget.id, "verify that the appropiate contentpane is displayed");
+								doh.t(isVisible(dijit.byId("tab4href")), "tab4 shown");
+								doh.t(isHidden(dijit.byId("tab1")), "tab1 hidden");
+							}), 1000);
+							
+							return d;
+						}
+					}
+				]);
+				
+				
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
\ No newline at end of file
diff --git a/dijit/tests/layout/tab1.html b/dijit/tests/layout/tab1.html
new file mode 100644
index 0000000..a37b927
--- /dev/null
+++ b/dijit/tests/layout/tab1.html
@@ -0,0 +1,6 @@
+
+<h1>Tab 1</h1>
+
+<p>I am tab 1. I was loaded externally. <a href="http://www.weba11y.com">WebA11y</a>(something to get focus)</p>
+
+<div label="foo!">blah</div>
diff --git a/dijit/tests/layout/tab2.html b/dijit/tests/layout/tab2.html
new file mode 100644
index 0000000..ed1ad76
--- /dev/null
+++ b/dijit/tests/layout/tab2.html
@@ -0,0 +1,3 @@
+<h1>Tab 2</h1>
+
+<p>I am tab 2. I was loaded externally as well.</p>
diff --git a/dijit/tests/layout/tab3.html b/dijit/tests/layout/tab3.html
new file mode 100644
index 0000000..e7a1710
--- /dev/null
+++ b/dijit/tests/layout/tab3.html
@@ -0,0 +1,39 @@
+<div dojoType="dijit.layout.TabContainer" nested="true">
+	<div dojoType="dijit.layout.ContentPane" title="Subtab #1">
+		<p>This is a nested tab container BUT loaded via an href.</p>
+	</div>
+	<div dojoType="dijit.layout.ContentPane" title="Subtab #2">
+		<p>
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+		semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+		porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+		Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+		Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+		risus.
+		</p>
+		<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+		imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+		nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+		massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+		pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+		quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+		felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+		quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+		rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+		semper velit ante id metus. Praesent massa dolor, porttitor sed,
+		pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+		tortor pharetra congue. Suspendisse pulvinar.
+		</p>
+		<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+		ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+		nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+		lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+		est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+		dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+		nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+		pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+		sociosqu ad litora torquent per conubia nostra, per inceptos
+		hymenaeos.
+		</p>
+	</div>
+</div>
\ No newline at end of file
diff --git a/dijit/tests/layout/tab3_noLayout.html b/dijit/tests/layout/tab3_noLayout.html
new file mode 100644
index 0000000..9a3a6b9
--- /dev/null
+++ b/dijit/tests/layout/tab3_noLayout.html
@@ -0,0 +1,39 @@
+<div dojoType="dijit.layout.TabContainer" doLayout="false">
+	<div dojoType="dijit.layout.ContentPane" title="Subtab #1">
+		<p>This is a nested tab container BUT loaded via an href.</p>
+	</div>
+	<div dojoType="dijit.layout.ContentPane" title="Subtab #2">
+		<p>
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+		semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+		porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+		Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+		Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+		risus.
+		</p>
+		<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+		imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+		nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+		massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+		pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+		quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+		felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+		quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+		rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+		semper velit ante id metus. Praesent massa dolor, porttitor sed,
+		pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+		tortor pharetra congue. Suspendisse pulvinar.
+		</p>
+		<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+		ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+		nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+		lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+		est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+		dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+		nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+		pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+		sociosqu ad litora torquent per conubia nostra, per inceptos
+		hymenaeos.
+		</p>
+	</div>
+</div>
\ No newline at end of file
diff --git a/dijit/tests/layout/tab4.html b/dijit/tests/layout/tab4.html
new file mode 100644
index 0000000..de9cd3c
--- /dev/null
+++ b/dijit/tests/layout/tab4.html
@@ -0,0 +1,40 @@
+<div dojoType="dijit.layout.SplitContainer" orientation="vertical">
+	<div dojoType="dijit.layout.ContentPane" title="split #1">
+		<p>Top of split container loaded via an href.</p>
+	</div>
+	<div dojoType="dijit.layout.ContentPane" title="split #2">
+		<p>Bottom of split container loaded via an href.</p>
+		<p>
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+		semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+		porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+		Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+		Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+		risus.
+		</p>
+		<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+		imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+		nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+		massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+		pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+		quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+		felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+		quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+		rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+		semper velit ante id metus. Praesent massa dolor, porttitor sed,
+		pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+		tortor pharetra congue. Suspendisse pulvinar.
+		</p>
+		<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+		ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+		nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+		lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+		est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+		dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+		nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+		pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+		sociosqu ad litora torquent per conubia nostra, per inceptos
+		hymenaeos.
+		</p>
+	</div>
+</div>
\ No newline at end of file
diff --git a/dijit/tests/layout/test_AccordionContainer.html b/dijit/tests/layout/test_AccordionContainer.html
new file mode 100644
index 0000000..7a307d4
--- /dev/null
+++ b/dijit/tests/layout/test_AccordionContainer.html
@@ -0,0 +1,308 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Accordion Widget Demo</title>
+
+	<!-- only needed for test files: -->
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<!-- uncomment for profiling
+		<script type="text/javascript"
+			src="../../../dojo/_base/html.js"></script>
+		<script type="text/javascript"
+			src="../../base/Layout.js"></script>
+	-->
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.form.ComboBox");
+	 	dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+		dojo.addOnLoad(function(){
+			dojo.subscribe("focusNode", function(node){ console.log("focused on " + (node?(node.id||node.tagName):"nothing"));});
+		});
+	</script>
+
+	<style type="text/css">
+		.somePadding .dijitAccordionBody {
+			padding: 5px;
+		}
+		.extremePadding .dijitAccordionBody {
+			padding: 50px;
+		}
+	</style>
+</head>
+<body class="claro" style="padding: 50px;">
+
+	<h1 class="testTitle">AccordionContainer Tests</h1>
+
+	<h2>Accordion from markup:</h2>
+
+	<input id="beforeMarkupAccordion" value="for tabIndex testing">
+	<div dojoType="dijit.layout.AccordionContainer" id="markupAccordion"
+		style="width: 400px; height: 300px; overflow: hidden">
+		<div dojoType="dijit.layout.ContentPane" selected="true"
+			title="A Simple Pane" iconClass="dijitEditorIcon dijitEditorIconSave" tooltip="tooltip for simple pane" id="pane1">
+				<select>
+					<option>red</option>
+					<option>blue</option>
+					<option>green</option>
+				</select>
+				<p>
+				Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin
+				suscipit porta magna. Duis accumsan nunc in velit. Nam et nibh.
+				Nulla facilisi. Cras venenatis urna et magna. Aenean magna mauris,
+				bibendum sit amet, semper quis, aliquet nec, sapien.  Aliquam
+				aliquam odio quis erat. Etiam est nisi, condimentum non, lacinia
+				ac, vehicula laoreet, elit. Sed interdum augue sit amet quam
+				dapibus semper. Nulla facilisi. Pellentesque lobortis erat nec
+				quam.
+				</p>
+				<p>
+				Sed arcu magna, molestie at, <input value="fringilla in, sodales"/> fringilla in, sodales eu, elit.
+				Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+				vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+				augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+				metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+				ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+				euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+				risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+				porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+				faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+				consequat quis, varius interdum, nulla. Donec neque tortor,
+				sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+				ut eros sit amet ante pharetra interdum.
+				</p>
+		</div>
+
+		<!-- test lazy loading.   margin style for testing size calculations. -->
+		<div dojoType="dijit.layout.ContentPane" id="lazyLoadPane"
+			title="Lazy Load Pane" iconClass="dijitEditorIcon dijitEditorIconCopy" href="tab1.html"
+			style="margin: 5px;"></div>
+
+		<div dojoType="dijit.layout.BorderContainer" id="borderContainerPane" title="BorderContainer Pane" iconClass="dijitEditorIcon dijitEditorIconPaste">
+			<div dojoType="dijit.layout.ContentPane" region="left" style="width:50%" splitter="true">
+			1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+			Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+			vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+			augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+			metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+			ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+			euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+			risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+			porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+			faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+			consequat quis, varius interdum, nulla. Donec neque tortor,
+			sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+			ut eros sit amet ante pharetra interdum.
+			</div>
+			<div dojoType="dijit.layout.ContentPane" region="center">
+			2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+			Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+			vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+			augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+			metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+			ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+			euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+			risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+			porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+			faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+			consequat quis, varius interdum, nulla. Donec neque tortor,
+			sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+			ut eros sit amet ante pharetra interdum.
+			</div>
+		</div>
+
+		<div dojoType="dijit.layout.ContentPane" id="embeddedLayoutPane" title="Embedded layout widgets" iconClass="dijitEditorIcon dijitEditorIconCut">
+			<p>
+				The pane has some text, plus two embedded layout widgets, which should
+				appear correctly even though the pane is initially hidden.
+			</p>
+			<p>
+				Here's a BorderContainer:
+			</p>
+			<div dojoType="dijit.layout.BorderContainer" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" region="left" style="width:100px" splitter="true">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				And a TabContainer:
+			</p>
+			<div dojoType="dijit.layout.TabContainer" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" title="Tab 1">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Tab 2">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				Text after the widgets.
+			</p>
+		</div>
+	</div>
+	<input id="afterMarkupAccordion" value="for tabIndex testing">
+	<button onclick="dijit.byId('pane1').set('title', 'My First Pane');">Change title of first pane</button>
+	<button onclick="dijit.byId('pane1').set('iconClass', 'plusIcon');">Change icon of first pane</button>
+	<button onclick="dijit.byId('markupAccordion').removeChild(dijit.byId('lazyLoadPane'));">Remove lazy-load pane</button>
+
+	<p></p>
+	<h2>Accordion with padding</h2>
+	<div dojoType="dijit.layout.AccordionContainer"
+		style="width: 400px; height: 300px; overflow: hidden">
+		<div dojoType="dijit.layout.ContentPane" class="somePadding" title="Some Padding">
+			<p>
+				Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin
+				suscipit porta magna. Duis accumsan nunc in velit. Nam et nibh.
+				Nulla facilisi. Cras venenatis urna et magna. Aenean magna mauris,
+				bibendum sit amet, semper quis, aliquet nec, sapien.  Aliquam
+				aliquam odio quis erat. Etiam est nisi, condimentum non, lacinia
+				ac, vehicula laoreet, elit. Sed interdum augue sit amet quam
+				dapibus semper. Nulla facilisi. Pellentesque lobortis erat nec
+				quam.
+			</p>
+			<p>
+				Sed arcu magna, molestie at, <input value="fringilla in, sodales"/> eu, elit.
+				Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+				vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+				augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+				metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+				ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+				euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+				risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+				porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+				faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+				consequat quis, varius interdum, nulla. Donec neque tortor,
+				sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+				ut eros sit amet ante pharetra interdum.
+			</p>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="No Padding">
+			<p>
+				Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin
+				suscipit porta magna. Duis accumsan nunc in velit. Nam et nibh.
+				Nulla facilisi. Cras venenatis urna et magna. Aenean magna mauris,
+				bibendum sit amet, semper quis, aliquet nec, sapien.  Aliquam
+				aliquam odio quis erat. Etiam est nisi, condimentum non, lacinia
+				ac, vehicula laoreet, elit. Sed interdum augue sit amet quam
+				dapibus semper. Nulla facilisi. Pellentesque lobortis erat nec
+				quam.
+			</p>
+			<p>
+				Sed arcu magna, molestie at, <input value="fringilla in, sodales"/> eu, elit.
+				Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+				vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+				augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+				metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+				ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+				euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+				risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+				porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+				faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+				consequat quis, varius interdum, nulla. Donec neque tortor,
+				sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+				ut eros sit amet ante pharetra interdum.
+			</p>
+		</div>
+		<div dojoType="dijit.layout.AccordionPane" class="extremePadding" title="Extreme Padding">
+			<p>(Leaving one to test deprecation)</p>
+			<p>
+				Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin
+				suscipit porta magna. Duis accumsan nunc in velit. Nam et nibh.
+				Nulla facilisi. Cras venenatis urna et magna. Aenean magna mauris,
+				bibendum sit amet, semper quis, aliquet nec, sapien.  Aliquam
+				aliquam odio quis erat. Etiam est nisi, condimentum non, lacinia
+				ac, vehicula laoreet, elit. Sed interdum augue sit amet quam
+				dapibus semper. Nulla facilisi. Pellentesque lobortis erat nec
+				quam.
+			</p>
+			<p>
+				Sed arcu magna, molestie at, <input value="fringilla in, sodales"/> eu, elit.
+				Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+				vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+				augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+				metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+				ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+				euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+				risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+				porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+				faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+				consequat quis, varius interdum, nulla. Donec neque tortor,
+				sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+				ut eros sit amet ante pharetra interdum.
+			</p>
+		</div>
+	</div>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_AccordionContainerDestroy.html b/dijit/tests/layout/test_AccordionContainerDestroy.html
new file mode 100644
index 0000000..90172e6
--- /dev/null
+++ b/dijit/tests/layout/test_AccordionContainerDestroy.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Accordion Widget Demo</title>
+
+	<!-- only needed for test files: -->
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<!-- uncomment for profiling
+		<script type="text/javascript"
+			src="../../../dojo/_base/html.js"></script>
+		<script type="text/javascript"
+			src="../../base/Layout.js"></script>
+	-->
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+	<script type="text/javascript">
+		function createAccordion()
+		{
+			var html='<div dojoType="dijit.layout.AccordionContainer" id="Accordion">' +
+				 	'<div dojoType="dijit.layout.ContentPane" title="first" id="first">first</div>' +
+				 	'<div dojoType="dijit.layout.ContentPane" title="second" id="second">second</div>' +
+					'</div>';
+			accPane.set("content",html);
+		}
+	</script>
+</head>
+<body class="claro" style="padding: 50px;">
+
+	<h1 class="testTitle">AccordionContainer Tests</h1>
+	<div dojoType="dijit.layout.ContentPane" jsId="accPane">
+	</div>
+	Click the button twice - it will work correctly unless there was a problem destroying the accordion, in which case the second time
+	the Accordion will not be created and you will see an error like <b>Tried to register widget with id==first_button but that id is already registered</b><br/>
+	<button type="button" onclick="createAccordion()">create Accordion</button>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_BorderContainer.html b/dijit/tests/layout/test_BorderContainer.html
new file mode 100644
index 0000000..1b5e76b
--- /dev/null
+++ b/dijit/tests/layout/test_BorderContainer.html
@@ -0,0 +1,241 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.layout.BorderContainer Test</title>
+
+	<!-- only needed for test files: -->
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+
+		/* styles for this test */
+		.dijitContentPane:focus { color: cyan; font-weight: bold }
+		body { margin-left: 20px }
+		#mondrian .dijitSplitter { border: 0; background: black !important }
+		#mondrian .dijitSplitterH { height: 10px }
+		#mondrian .dijitSplitterV { width: 10px }
+		#mondrian .dijitSplitterThumb { display: none }
+		#mondrian .dijitSplitterActive { background-color: blue }
+		.dj_webkit #mondrian .dijitSplitter:focus {
+			/* override orange focus border w/something easier to see (response to a11y bug report) */
+			outline: auto 5px blue;
+		}
+		#mondrian SPAN { display: none }
+		#mondrian:hover SPAN { display: inline }
+
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.form.FilteringSelect");
+
+		function togglePanel(button, id){
+			var leftPanel = dijit.byId(id);
+			if(leftPanel){
+				dijit.byId('border1').removeChild(leftPanel);
+				leftPanel.destroy();
+				button.innerHTML='Add left panel';
+			}else{
+				var container = dijit.byId('border1');
+				var div = dojo.doc.createElement('div');
+				div.innerHTML='left';
+				container.domNode.appendChild(div);
+				leftPanel = new dijit.layout.ContentPane({id: id, region:'left', style:'background-color: #acb386; width:200px', splitter:true, minSize:150, maxSize:250}, div);
+				dijit.byId('border1').addChild(leftPanel);
+				button.innerHTML='Remove left panel';
+			}
+		}
+
+		function watchSplitters(bc) {
+
+			var out = dojo.byId("watchedOutput");
+			var moveConnects = {};
+			dojo.forEach(["top", "left"], function(region) {
+				var spl = bc.getSplitter(region);
+
+				dojo.connect(spl, "_startDrag", function() {
+
+					dojo.style(spl.child.domNode, "opacity", "0.4");
+					moveConnects[spl.widgetId] = dojo.connect(spl.domNode, "onmousemove", function(evt) {
+
+						out.innerHTML = spl.region + ": " + dojo.toJson({
+							x: !spl.horizontal ? spl.domNode.style[spl.region] : 0,
+							y: spl.horizontal ? spl.domNode.style[spl.region] : 0
+						});
+					})
+
+				});
+				dojo.connect(spl, "_stopDrag", function(evt) {
+					dojo.style(spl.child.domNode, "opacity", 1);
+					dojo.disconnect(moveConnects[spl.widgetId]);
+					delete moveConnects[spl.widgetId];
+				});
+			})
+		}
+		dojo.addOnLoad(function() {
+			watchSplitters( dijit.byId("watchedBC") );
+		})
+	</script>
+</head>
+<body class="claro">
+
+	<h2 class="testTitle">dijit.layout.BorderContainer tests</h2>
+	<p>Headline layout (default), left is constrained - min:150, max:250</p>
+	<div id="border1" dojoType="dijit.layout.BorderContainer"
+		style="width: 1000px; height: 300px; border: 2px solid blue;">
+		<div id="border1-top" dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; border: 15px black solid; height: 50px;" splitter="true" role="banner">
+			top bar (resizable)
+		</div>
+		<div id="border1-left" dojoType="dijit.layout.ContentPane" region="left" style="background-color: #acb386; border: 10px green solid; width: 100px;"
+		role="navigation" splitter="true" minSize="150" maxSize="250">
+			left (resizable b/w 150 → 250)
+		</div>
+		<div id="border1-center" dojoType="dijit.layout.ContentPane" region="center" style="background-color: #f5ffbf; padding: 30px;" role="main">
+			main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+			(to check we're copying children around properly).<br />
+			<select dojoType="dijit.form.FilteringSelect">
+				<option value="1">foo</option>
+				<option value="2">bar</option>
+				<option value="3">baz</option>
+			</select>
+			Here's some text that comes AFTER the combo box.
+		</div>
+		<div id="border1-right" dojoType="dijit.layout.ContentPane" region="right" style="background-color: #acb386; width: 100px;">
+			right (fixed size)
+		</div>
+		<div id="border1-bottom" dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 50px;" splitter="true" role="contentinfo">
+			bottom bar (resizable)
+		</div>
+	</div>
+
+	<button id="toggleLeftButton" onClick="togglePanel(this, 'border1-left')">Remove left panel</button>
+	<br />
+
+	<p>Sidebar layout, BiDi sensitive, liveSplitters: false</p>
+	<div id="border2" dojoType="dijit.layout.BorderContainer" design="sidebar" liveSplitters="false"
+		style="border: 20px solid black; width: 1000px; height: 300px;">
+		<div id="border2-leading" dojoType="dijit.layout.ContentPane" region="leading" style="background-color: #acb386; width: 100px;">
+			leading (fixed size)
+		</div>
+		<div id="border2-top" dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; height: 80px;">
+			top bar (fixed size)
+		</div>
+		<div id="border2-center" dojoType="dijit.layout.ContentPane" region="center" style="background-color: #f5ffbf; padding: 10px;">
+			main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+			(to check we're copying children around properly).<br />
+			<select dojoType="dijit.form.FilteringSelect">
+				<option value="1">foo</option>
+				<option value="2">bar</option>
+				<option value="3">baz</option>
+			</select>
+			Here's some text that comes AFTER the combo box.
+		</div>
+		<div id="border2-bottom" dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 80px;" splitter="true">
+			bottom bar (resizable)
+		</div>
+		<div id="border2-trailing" dojoType="dijit.layout.ContentPane" region="trailing" style="background-color: #acb386; width: 100px;" splitter="true">
+			trailing (resizable)
+		</div>
+	</div>
+
+	<p>gutters=false layout</p>
+
+	<div dojoType="dijit.layout.BorderContainer" design="sidebar" gutters="false"
+		style="border: 20px solid black; width: 1000px; height: 300px;">
+		<div dojoType="dijit.layout.ContentPane" region="leading" style="background-color: #acb386; width: 100px;">
+			leading
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; height: 80px;">
+			top bar
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="center" style="background-color: #f5ffbf; padding: 10px;">
+			main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+			(to check we're copying children around properly).<br />
+			<select dojoType="dijit.form.FilteringSelect">
+				<option value="1">foo</option>
+				<option value="2">bar</option>
+				<option value="3">baz</option>
+			</select>
+			Here's some text that comes AFTER the combo box.
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 80px;">
+			bottom bar
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="trailing" style="background-color: #acb386; width: 100px;">
+			trailing
+		</div>
+	</div>
+
+	<p>Vertical panels only with splitters</p>
+
+	<div dojoType="dijit.layout.BorderContainer" design="sidebar"
+		style="border: 2px solid black; width: 1000px; height: 300px; padding: 10px;">
+		<div dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; height: 80px;" splitter="true">
+			top bar
+		</div>
+
+		<div dojoType="dijit.layout.ContentPane" region="center" style="background-color: #f5ffbf; padding: 10px;">
+			main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+			(to check we're copying children around properly).<br />
+			<select dojoType="dijit.form.FilteringSelect">
+				<option value="1">foo</option>
+				<option value="2">bar</option>
+				<option value="3">baz</option>
+			</select>
+			Here's some text that comes AFTER the combo box.
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 80px;" splitter="true">
+			bottom bar
+		</div>
+	</div>
+
+	<br />
+	<p>More fun with layouts</p>
+
+	<div id="mondrian" dojoType="dijit.layout.BorderContainer" design="sidebar" gutters="false" persist="true" style="height: 300px; width: 400px;">
+		<div id="mondrian_top" dojoType="dijit.layout.ContentPane" region="top" style="height: 100px" splitter="true">
+			<div  id="mondrian_top_bc" dojoType="dijit.layout.BorderContainer" persist="true" gutters="false" style="height: 100px; width: 100%">
+				<div id="top_a" dojoType="dijit.layout.ContentPane" region="leading" style="width: 125px" splitter="true"><span>top a</span></div>
+				<div id="top_b" dojoType="dijit.layout.ContentPane" region="center" style="background-color: yellow" splitter="true"><span>top b</span></div>
+			</div>
+		</div>
+		<div id="mondrian_bottom" dojoType="dijit.layout.ContentPane" region="bottom" style="height: 100px" splitter="true">
+			<div id="mondrian_bottom_bc" dojoType="dijit.layout.BorderContainer" persist="true" gutters="false" style="height: 100px; width: 100%">
+				<div id="bottom_c" dojoType="dijit.layout.ContentPane" region="top" style="height: 40px" splitter="true"><span>bottom c</span></div>
+				<div id="bottom_d" dojoType="dijit.layout.ContentPane" region="center"><span>bottom d</span></div>
+			</div>
+		</div>
+		<div id="mondrian_leading" dojoType="dijit.layout.ContentPane" region="leading" style="width: 100px" splitter="true">
+			<div id="mondrian_leading_bc" dojoType="dijit.layout.BorderContainer" persist="true" gutters="false" style="height: 300px; width: 100%">
+				<div id="leading_e" dojoType="dijit.layout.ContentPane" region="center"><span>leading e</span></div>
+				<div id="leading_f" dojoType="dijit.layout.ContentPane" region="bottom" style="height: 100px; background-color: red" splitter="true"><span>leading f</span></div>
+			</div>
+		</div>
+		<div id="trailing_g" dojoType="dijit.layout.ContentPane" region="trailing" style="width: 100px" splitter="true"><span>trailing g</span></div>
+	</div>
+
+	<br />
+	<p>Watching the splitter events</p>
+	<div dojoType="dijit.layout.BorderContainer" id="watchedBC" persist="false" gutters="false" style="height: 200px; width: 100%">
+		<div dojoType="dijit.layout.ContentPane" region="top" splitter="true" style="background-color: #ccffcc; height: 50px;">Top:</div>
+		<div dojoType="dijit.layout.ContentPane" region="left" style="background-color: #ccccff; width: 40px" splitter="true"><span>Bottom</span></div>
+		<div dojoType="dijit.layout.ContentPane" region="center" style="background-color: #ffffcc"><span>Center</span></div>
+	</div>
+
+	<p>Splitter coords output:</p>
+	<div id="watchedOutput" style="border: 1px solid #999">nothing moving</div>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_BorderContainer_complex.html b/dijit/tests/layout/test_BorderContainer_complex.html
new file mode 100644
index 0000000..6685ebb
--- /dev/null
+++ b/dijit/tests/layout/test_BorderContainer_complex.html
@@ -0,0 +1,182 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.layout.BorderContainer Test - complex layout</title>
+
+	<!-- only needed for test files: -->
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.LinkPane");
+		dojo.require("dijit.Tooltip");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.SplitContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.form.FilteringSelect");
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">dijit.layout.BorderContainer complex layout test</h1>
+
+	<div dojoType="dijit.layout.BorderContainer"
+		style="border: 2px solid black; width: 90%; height: 500px; padding: 10px;">
+		<div dojoType="dijit.layout.AccordionContainer"
+			region="left" style="background-color: #acb386; width: 400px;" splitter="true">
+			<div dojoType="dijit.layout.ContentPane" title="a">
+				left bar
+			</div>
+			<div dojoType="dijit.layout.ContentPane" title="b">
+				<p>
+					Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin
+					suscipit porta magna. Duis accumsan nunc in velit. Nam et nibh.
+					Nulla facilisi. Cras venenatis urna et magna. Aenean magna mauris,
+					bibendum sit amet, semper quis, aliquet nec, sapien.  Aliquam
+					aliquam odio quis erat. Etiam est nisi, condimentum non, lacinia
+					ac, vehicula laoreet, elit. Sed interdum augue sit amet quam
+					dapibus semper. Nulla facilisi. Pellentesque lobortis erat nec
+					quam.
+				</p>
+				<p>
+					Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</p>
+			</div>
+			<div dojoType="dijit.layout.ContentPane" title="c">
+				<p>The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.</p>
+			</div>
+		</div>
+
+		<div dojoType="dijit.layout.AccordionContainer"
+			region="right" style="background-color: #acb386; width: 200px;">
+			<div dojoType="dijit.layout.ContentPane" title="a">
+				right bar
+			</div>
+			<div dojoType="dijit.layout.ContentPane" title="b">
+				<p>
+					Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin
+					suscipit porta magna. Duis accumsan nunc in velit. Nam et nibh.
+					Nulla facilisi. Cras venenatis urna et magna. Aenean magna mauris,
+					bibendum sit amet, semper quis, aliquet nec, sapien.  Aliquam
+					aliquam odio quis erat. Etiam est nisi, condimentum non, lacinia
+					ac, vehicula laoreet, elit. Sed interdum augue sit amet quam
+					dapibus semper. Nulla facilisi. Pellentesque lobortis erat nec
+					quam.
+				</p>
+				<p>
+					Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</p>
+			</div>
+			<div dojoType="dijit.layout.ContentPane" title="c">
+				<p>The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.  The quick brown fox jumps over the lazy dog.</p>
+			</div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; height: 150px;" splitter="true">
+
+			<div id="mainTabContainer" dojoType="dijit.layout.TabContainer" style="width: 100%; height: 20em;">
+
+				<div id="tab1" dojoType="dijit.layout.ContentPane" href="../../../dijit/tests/layout/tab1.html" title="Tab 1"></div>
+
+				<div id="tab2" dojoType="dijit.layout.ContentPane" href="../../../dijit/tests/layout/tab2.html" refreshOnShow="true" title="Tab 2" selected="true"></div>
+
+				<div dojoType="dijit.layout.ContentPane" title="Tab 3">
+					<h1>I am tab 3</h1>
+					<p>And I was already part of the page! That's cool, no?</p>
+					<p id="foo">tooltip on this paragraph</p>
+					<div dojoType="dijit.Tooltip" connectId="foo">I'm a tooltip!</div>
+					<button dojoType="dijit.form.Button">I'm a button </button>
+					<br>
+					<button dojoType="dijit.form.Button">So am I!</button>
+					<p>
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+					semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+					porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+					Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+					Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+					risus.
+					</p>
+					<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+					imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+					nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+					massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+					pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+					quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+					felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+					quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+					rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+					semper velit ante id metus. Praesent massa dolor, porttitor sed,
+					pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+					tortor pharetra congue. Suspendisse pulvinar.
+					</p>
+				</div>
+
+				<div dojoType="dijit.layout.TabContainer" title="Inlined Sub TabContainer">
+					<a dojoType="dijit.layout.LinkPane" href="../../../dijit/tests/layout/tab1.html">SubTab 1</a>
+					<a dojoType="dijit.layout.LinkPane" href="../../../dijit/tests/layout/tab2.html" selected="true">SubTab 2</a>
+				</div>
+
+				<a dojoType="dijit.layout.LinkPane" href="../../../dijit/tests/layout/tab3.html">Sub TabContainer from href</a>
+
+				<a dojoType="dijit.layout.LinkPane" href="../../../dijit/tests/layout/tab4.html">SplitContainer from href</a>
+
+			</div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 150px;">
+			<div style="border: 1px solid black;">
+				<div dojoType="dijit.Editor" id="editor1"><p>bottom bar (edit me)</p></div>
+			</div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="center" style="background-color: #f5ffbf; padding: 10px;">
+			main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+			(to check we're copying children around properly).<br />
+			<select dojoType="dijit.form.FilteringSelect">
+				<option value="1">foo</option>
+				<option value="2">bar</option>
+				<option value="3">baz</option>
+			</select>
+			Here's some text that comes AFTER the combo box.
+		</div>
+	</div>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_BorderContainer_experimental.html b/dijit/tests/layout/test_BorderContainer_experimental.html
new file mode 100644
index 0000000..77d5e9a
--- /dev/null
+++ b/dijit/tests/layout/test_BorderContainer_experimental.html
@@ -0,0 +1,258 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+		<title>BorderContainer Experiments | The Dojo Toolkit</title>
+
+		<!-- only needed for test files: -->
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../css/dijitTests.css";
+			#pane1 { background-color:red;
+			}
+			#pane2{
+				background-color:green;
+			}
+			#pane3 {
+				background-color:blue;
+			}
+			#pane0 {
+				background-color:#ededed;
+			}
+			.wrapper { padding:25px; }
+			.bc { margin:10px; border:2px solid #ededed; }
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dijit.layout.BorderContainer");
+			dojo.declare("my.BorderContainer",dijit.layout.BorderContainer,{
+
+				opts: {
+					// single pane view
+					"a":{
+						panes: [
+							{ id: "pane0", sizeable:false, region:"center", style: { width:"100%", height:"100%" } },
+							{ id: "pane1", hidden:true },
+							{ id: "pane2", hidden:true },
+							{ id: "pane3", hidden:true }
+						]
+					},
+					// top / bottom view
+					"ah":{
+						panes: [
+							{ id: "pane0", sizeable:false, region:"center", style: { width:"100%", height:"50%" } },
+							{ id: "pane1", sizeable:true, region:"bottom", style: { width:"100%", height:"50%" } },
+							{ id: "pane2", hidden:true },
+							{ id: "pane3", hidden:true }
+						]
+					},
+					// left / right view
+					"av":{
+						panes: [
+							{ id: "pane0", sizeable:true, region:"left", style: { width:"50%", height:"100%" } },
+							{ id: "pane1", sizeable:false, region:"center", style: { width:"50%", height:"100%" } },
+							{ id: "pane2", hidden:true },
+							{ id: "pane3", hidden:true }
+						]
+					}
+
+				},
+
+				_clearSplitters: function(){
+					// cleanup all splitters on the page
+					dojo.query(".dijitSplitter",this.domNode).forEach(function(n){
+						dijit.byNode(n).destroy();
+					});
+					dojo.query(".dijitSplitterCover").forEach(dojo.destroy);
+					delete this._splitters;
+					this._splitters = {};
+				},
+
+				setLayoutENUM: function(lay){
+					// set the layout to a predefined setup
+					if(this._layoutSetting != lay){
+
+						this._layoutSetting = lay;
+						var struct = this.opts[lay] || false;
+						this._clearSplitters();
+
+						dojo.forEach(struct.panes,function(pane,i){
+							// setup each pane
+							var d = dijit.byId(pane.id);
+							d.region = pane.region || "center";
+							d.splitter = pane.sizeable;
+							if(pane.minSize){ d.minSize = pane.minSize; }
+							if(pane.maxSize){ d.maxSize = pane.maxSize; }
+							if(pane.hidden){
+								// reset this widget to our hidden holder node
+								this.extractChild(d,dojo.byId("holder"));
+								d.splitter = null;
+								d.region = null;
+								d.maxSize = null;
+								d.minSize = null;
+							}else{
+								if(pane.style){
+									// object setter via style only in trunk:
+									dojo.style(d.domNode,pane.style);
+								}
+								this.addChild(d,i);
+							}
+						},this);
+					}
+					this.layout();
+				},
+
+				extractChild: function(/*dijit._Widget*/ child, /*DomNode*/ node){
+					// a non-destructive cleanup for the bordercontainer.
+					// cleanup a widget, and append it's domNode to some
+					// other node in the dom
+					var region = child.region;
+					var splitter = this._splitters[region];
+					if(splitter){
+						dijit.byNode(splitter).destroy();
+						delete this._splitters[region];
+					}
+					delete this["_"+region];
+					node.appendChild(child.domNode);
+					if(this._started){
+						this._layoutChildren();
+					}
+					return child.domNode;
+				}
+			});
+
+			var open = false;
+
+			dojo.addOnLoad(function(){
+				// make buttons
+				dojo.forEach(["a","av","ah"],function(n){
+
+					var but = new dijit.form.Button({
+						label: "Set "+n,
+						onClick: function(){
+							console.log(n);
+							layout.setLayoutENUM(n);
+						}
+					});
+					dojo.byId("buttons").appendChild(but.domNode);
+					but.startup();
+				})
+
+			});
+		</script>
+
+    </head>
+    <body class="claro">
+
+		<h1>This is a test</h1>
+		<p>This is only a test. An experiment in dynamically altering a BorderContainer's layout
+		(a seemingly unsupported feature just yet). It Demonstrates how to programatically alter/animate
+		the size of non-center regions though, and several simple layout configurations
+		</p>
+
+		<div>
+			<h3>Layouts:</h3>
+			<div id="buttons"></div>
+		</div>
+
+		<div jsId="layout" id="container" dojoType="my.BorderContainer" style="width:600px; height:300px; border:3px solid #333;">
+			<div dojoType="dijit.layout.ContentPane" region="center" id="pane0">
+				pane0
+			</div>
+		</div>
+
+		<div class="bc" dojoType="dijit.layout.BorderContainer" style="height:200px">
+			<div dojoType="dijit.layout.ContentPane" region="center">
+				Sinlge pane - l1
+			</div>
+		</div>
+
+		<div class="wrapper">
+			<h3>two panes, vertical split:</h3>
+
+
+			<div class="bc" id="animBC" dojoType="dijit.layout.BorderContainer" style="height:200px">
+				<div dojoType="dijit.layout.ContentPane" id="sizing1" style="background-color:red" region="left" splitter="true">
+					Sinlge pane - left
+				</div>
+				<div dojoType="dijit.layout.ContentPane"  region="center">
+					Sinlge pane - center
+					<button dojoType="dijit.form.Button">
+					Size Me
+					<script type="dojo/method" event="onClick">
+						var n = dijit.byId("sizing1").domNode;
+						dojo.animateProperty({
+							node:n,
+							duration:1000,
+							properties: { width: { end: (open ? "100" : "400"), units:"px" } },
+							onEnd: function(){
+								open = !open;
+								dijit.byId("animBC").layout();
+							}
+						}).play(1);
+					</script>
+				</button>
+				</div>
+			</div>
+
+			<div class="bc" dojoType="dijit.layout.BorderContainer" style="height:200px">
+				<div dojoType="dijit.layout.ContentPane" region="center" splitter="true">
+					Single pane - center (splitter) (this is unsupported, and does not work)
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="right">
+					Single pane - right (no splitter)
+				</div>
+			</div>
+
+			<div class="bc" dojoType="dijit.layout.BorderContainer" style="height:200px">
+				<div dojoType="dijit.layout.ContentPane" region="center">
+					Single pane - center (no splitter)
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="right" splitter="true">
+					Single pane - right (splitter)
+				</div>
+			</div>
+		</div>
+
+		<div class="bc" dojoType="dijit.layout.BorderContainer" style="width:200px; height:400px;">
+			<div dojoType="dijit.layout.ContentPane" region="top" splitter="true">
+				Single pane - top (splitter)
+
+			</div>
+			<div dojoType="dijit.layout.ContentPane" region="center">
+				Single pane - center
+			</div>
+		</div>
+
+		<div class="bc" dojoType="dijit.layout.BorderContainer" style="width:200px; height:400px;">
+			<div dojoType="dijit.layout.ContentPane" region="center">
+				Single pane - center
+			</div>
+			<div dojoType="dijit.layout.ContentPane" region="bottom" splitter="true">
+				Single Pane Bottom (splitter)
+			</div>
+			<div dojoType="dijit.layout.ContentPane" region="top" splitter="true">
+				Single Pane Top (splitter)
+			</div>
+		</div>
+
+		<div id="holder" style="visibility:hidden">
+			<div dojoType="dijit.layout.ContentPane" id="pane1">pane 1</div>
+			<div dojoType="dijit.layout.ContentPane" id="pane2">pane 2</div>
+			<div dojoType="dijit.layout.ContentPane" id="pane3">pane 3</div>
+		</div>
+
+    </body>
+</html>
diff --git a/dijit/tests/layout/test_BorderContainer_full.html b/dijit/tests/layout/test_BorderContainer_full.html
new file mode 100644
index 0000000..e823571
--- /dev/null
+++ b/dijit/tests/layout/test_BorderContainer_full.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.layout.BorderContainer Test - Full Screen</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+
+		html, body, #main{
+			width: 100%;	/* make the body expand to fill the visible window */
+			height: 100%;
+			overflow: hidden;	/* erase window level scrollbars */
+			padding: 0 0 0 0;
+			margin: 0 0 0 0;
+			font: 10pt Arial,Myriad,Tahoma,Verdana,sans-serif;
+		}
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.form.FilteringSelect");
+	</script>
+
+</head>
+<body class="claro">
+	<div dojoType="dijit.layout.BorderContainer" design="sidebar" id="main">
+		<div dojoType="dijit.layout.ContentPane" region="leading" style="background-color: #acb386; width: 100px;">
+			leading
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; height: 100px;">
+			top bar
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="center" style="background-color: #f5ffbf; padding: 10px;">
+			main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+			(to check we're copying children around properly).<br />
+			<select dojoType="dijit.form.FilteringSelect">
+				<option value="1">foo</option>
+				<option value="2">bar</option>
+				<option value="3">baz</option>
+			</select>
+			Here's some text that comes AFTER the combo box.
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 100px;" splitter="true">
+			bottom bar
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="trailing" style="background-color: #acb386; width: 100px;" splitter="true">
+			trailing
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/layout/test_BorderContainer_nested.html b/dijit/tests/layout/test_BorderContainer_nested.html
new file mode 100644
index 0000000..cd34acd
--- /dev/null
+++ b/dijit/tests/layout/test_BorderContainer_nested.html
@@ -0,0 +1,118 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.layout.BorderContainer Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.form.FilteringSelect");
+	</script>
+</head>
+<body class="claro">
+
+	<h2 class="testTitle">dijit.layout.BorderContainer tests</h2>
+	<p>Basic layout</p>
+
+	<div dojoType="dijit.layout.TabContainer" style="width:800px;height:600px;">
+		<div dojoType="dijit.layout.BorderContainer" title="Tab 1"
+			style="border: 2px solid black; width: 90%; height: 500px; padding: 10px;">
+			<div dojoType="dijit.layout.ContentPane" region="left" style="background-color: #acb386; width: 100px;">
+				left
+			</div>
+			<div dojoType="dijit.layout.ContentPane" region="right" style="background-color: #acb386; width: 100px;">
+				right
+			</div>
+			<div dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; height: 100px;">
+				top bar
+			</div>
+			<div dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 100px;">
+				bottom bar
+			</div>
+
+			<div dojoType="dijit.layout.BorderContainer" region="center" design="sidebar"
+				style="border: 2px solid black; padding: 0px;">
+				<div dojoType="dijit.layout.ContentPane" region="left" style="background-color: #acb386; width: 100px;">
+					left
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="right" style="background-color: #acb386; width: 100px;">
+					right
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; height: 100px;">
+					top bar
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 100px;">
+					bottom bar
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center" style="background-color: #f5ffbf; padding: 10px;">
+					main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+					(to check we're copying children around properly).<br />
+					<select dojoType="dijit.form.FilteringSelect">
+						<option value="1">foo</option>
+						<option value="2">bar</option>
+						<option value="3">baz</option>
+					</select>
+					Here's some text that comes AFTER the combo box.
+				</div>
+			</div>
+		</div>
+		<div dojoType="dijit.layout.BorderContainer" title="Tab 2">
+			<div dojoType="dijit.layout.ContentPane" region="left" splitter="true" style="background-color: #770; width: 100px;">
+				left
+			</div>
+			<div dojoType="dijit.layout.ContentPane" region="right" splitter="true" style="background-color: #077; width: 100px;">
+				right
+			</div>
+			<div dojoType="dijit.layout.ContentPane" region="top" splitter="true" style="background-color: #700; height: 100px;">
+				top bar
+			</div>
+			<div dojoType="dijit.layout.ContentPane" region="bottom" splitter="true" style="background-color: #007; height: 100px;">
+				bottom bar
+			</div>
+
+			<div dojoType="dijit.layout.BorderContainer" region="center" design="sidebar"
+				style="border: 2px solid black; padding: 0px;">
+				<div dojoType="dijit.layout.ContentPane" region="left" style="background-color: #acb386; width: 100px;">
+					left
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="right" style="background-color: #acb386; width: 100px;">
+					right
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; height: 100px;">
+					top bar
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 100px;">
+					bottom bar
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center" style="background-color: #f5ffbf; padding: 10px;">
+					main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+					(to check we're copying children around properly).<br />
+					<select dojoType="dijit.form.FilteringSelect">
+						<option value="1">foo</option>
+						<option value="2">bar</option>
+						<option value="3">baz</option>
+					</select>
+					Here's some text that comes AFTER the combo box.
+				</div>
+			</div>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/layout/test_BorderContainer_prog.html b/dijit/tests/layout/test_BorderContainer_prog.html
new file mode 100644
index 0000000..4821025
--- /dev/null
+++ b/dijit/tests/layout/test_BorderContainer_prog.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.layout.BorderContainer Test</title>
+
+	<!-- only needed for test files: -->
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.BorderContainer");
+        dojo.require("dijit.layout.ContentPane");
+
+		var bc, cp1, cp2, cp3;
+        dojo.addOnLoad(function(){
+                bc = new dijit.layout.BorderContainer({style:'height:400px;width:500px;border:1px solid black'}, dojo.byId('main'));
+
+				cp1 = new dijit.layout.ContentPane({region:'top',style:'height:100px;background-color:red',splitter:true});
+				cp1.domNode.innerHTML = "top pane";
+				bc.addChild(cp1);
+
+				cp2 = new dijit.layout.ContentPane({region:'center',style:'background-color:green'});
+				cp2.domNode.innerHTML = "center pane";
+				bc.addChild(cp2);
+
+                bc.startup();
+        });
+
+        function addLeftPane(){
+			cp3 = new dijit.layout.ContentPane({region:'left', splitter: true, style:'width: 100px;'});
+			cp3.domNode.innerHTML = "left pane";
+			bc.addChild(cp3);
+        }
+	</script>
+</head>
+<body class="claro">
+	<h2 class="testTitle">dijit.layout.BorderContainer programmatic test</h2>
+	<div id='main'></div>
+
+	<button onclick="addLeftPane();">add left pane</button>
+	<button onclick="bc.removeChild(cp1);">remove top pane</button>
+</body>
+</html>
diff --git a/dijit/tests/layout/test_ContentPane.html b/dijit/tests/layout/test_ContentPane.html
new file mode 100644
index 0000000..5e70511
--- /dev/null
+++ b/dijit/tests/layout/test_ContentPane.html
@@ -0,0 +1,208 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>ContentPane Test</title>
+
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+
+		.box {
+		  position: relative;
+			background-color: white;
+			border: 2px solid black;
+			padding: 8px;
+			margin: 4px;
+		}
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+
+	<script type="text/javascript">
+		dojo.require('doh.runner');
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.Dialog");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.InlineEditBox");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		// create a do nothing, only for test widget
+		dojo.declare("dijit.TestWidget",
+			[dijit._Widget, dijit._Templated], {
+			templateString: "<span class='dojoxTestWidget'></span>"
+		});
+
+		dojo.addOnLoad(function(){
+
+			var pane1 = dijit.byId('parsedPane');
+			var dialogCtrPane = dijit.byId("dialogContainer");
+
+			doh.register("basicChecks", [
+			{
+				name: 'setContent',
+				runTest: function(t){
+					console.log("basicChecks: " + this.name);
+					var msg = "Simple Test";
+					pane1.set('content', msg);
+					t.assertEqual(msg, pane1.domNode.innerHTML);
+				}
+			},
+			{
+				name: 'parseInitialContent',
+				runTest: function(t){
+					console.log("basicChecks: " + this.name);
+					var parserTest = dijit.byId("parserTest");
+					t.assertTrue(parserTest);
+				}
+			},
+			{
+				name: 'parseNewContent',
+				runTest: function(t){
+					console.log("basicChecks: " + this.name);
+					dialogCtrPane.set(
+						"content",
+						'<div dojoType="dijit.Dialog" id="sacrificialDlg" title="Life is short for this fellow">'
+						+'	<p>This dialog should be cleanly destroyed when the unit tests run</p>'
+						+'</div>'
+					);
+
+					t.assertTrue(dijit.byId("sacrificialDlg"));
+					t.assertFalse(dijit.byId("parserTest"));
+				}
+			},
+			{
+				name: 'empty',
+				runTest: function(t){
+					console.log("basicChecks: " + this.name);
+					t.assertTrue(dijit.byId("sacrificialDlg"));
+
+					var dialog = dijit.byId("sacrificialDlg");
+					// dialog is supposed to move its domNode to the body..
+					// we need to check it gets cleanly removed when we set content on the CP
+					t.assertTrue(dialog);
+					t.assertTrue(dialog.domNode.parentNode == dojo.body());
+
+					dialogCtrPane.set('content', "new content, no more dialog");
+					t.assertFalse(dijit.byId("sacrificialDlg"));
+					t.assertFalse(dojo.byId("sacrificialDlg"));
+				}
+			},
+			{
+				name: 'reuse',
+				runTest: function(t) {
+					console.log("basicChecks: " + this.name);
+					// do the same thing over again - we should be error free
+					dialogCtrPane.set(
+						"content",
+						'<div dojoType="dijit.Dialog" id="sacrificialDlg" title="Life is short for this fellow">'
+						+'	<p>This dialog should be cleanly destroyed when the unit tests run</p>'
+						+'</div>'
+					);
+					var dialog = dijit.byId("sacrificialDlg");
+					// dialog is supposed to move its domNode to the body..
+					// we need to check it gets cleanly removed when we set content on the CP
+					t.assertTrue(dialog);
+					t.assertTrue(dialog.domNode.parentNode == dojo.body());
+				}
+			},
+			{
+				name: 'destroy',
+				runTest: function(t) {
+					console.log("basicChecks: " + this.name);
+
+					// manually stick a widget into the ContentPane
+					var manualWidget = new dijit.TestWidget({id: "destroyTestWidget"});
+					dojo.place(manualWidget.domNode, dialogCtrPane.domNode, "last");
+
+					// make sure widget created via get('content') and also the above widget are there
+					t.assertTrue(dijit.byId("sacrificialDlg"), "dialog in dialogContainer still there");
+					t.assertTrue(dijit.byId("destroyTestWidget"), "test widget in dialogContainer still there");
+
+					// when we kill the CP, it should also destroy any widgets created when we set content,
+					// and for backwards-compatibility reasons, any widgets that user stuck in there
+					// manually too
+					dialogCtrPane.destroyRecursive();
+
+					// make sure everything got deleted
+					t.assertFalse(dijit.byId("dialogContainer"));
+					t.assertFalse(dijit.byId("sacrificialDlg"), "dialog in dialogContainer was destroyed");
+					t.assertFalse(dijit.byId("destroyTestWidget"), "test widget in dialogContainer was destroyed");
+					t.assertFalse(dojo.byId("sacrificialDlg"));
+				}
+			}
+			]);
+			doh.run();
+
+		});
+	</script>
+
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit layout.ContentPane tests</h1>
+		<p>pre-container paragraph</p>
+
+		<div dojoType="dijit.layout.ContentPane" class="box">
+			some text (top-level container)
+
+			<div dojoType="dijit.layout.ContentPane" class="box">
+
+				text in the inner container (1)
+
+				<div dojoType="dijit.layout.ContentPane" class="box" href="tab2.html">
+					hi
+				</div>
+
+				text in the inner container (2)
+
+				<div dojoType="dijit.layout.ContentPane" class="box">
+					inner-inner 2
+				</div>
+
+				text in the inner container (3)
+
+				<div dojoType="dijit.layout.ContentPane" class="box">
+					inner-inner 3
+				</div>
+
+				text in the inner container (4)
+
+			</div>
+
+			some more text (top-level container)
+		</div>
+
+		<p>mid-container paragraph</p>
+
+		<div dojoType="dijit.layout.ContentPane" class="box">
+			2nd top-level container
+		</div>
+
+		<p>post-container paragraph</p>
+
+		<div dojoType="dijit.layout.ContentPane" class="box" href="combotab.html" id="test">
+			<p style='background-color:yellow;border:1px solid red;text-align:center;'>This text should automatically be replaced by downloaded content from combotab.html</p>
+		</div>
+
+		<hr/>
+		<p>ContentPanes used by the unit tests to verify functionality
+		<div class='box' dojoType="dijit.layout.ContentPane" id='parsedPane'>
+			Some Content Here
+		</div>
+		<div class='box' dojoType="dijit.layout.ContentPane" id='dialogContainer'>
+			<div dojoType="dijit.TestWidget" id="parserTest"></div>
+		</div>
+	</body>
+</html>
diff --git a/dijit/tests/layout/test_ContentPane_prog.html b/dijit/tests/layout/test_ContentPane_prog.html
new file mode 100644
index 0000000..5a0ec9d
--- /dev/null
+++ b/dijit/tests/layout/test_ContentPane_prog.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>ContentPane Programmatic Test</title>
+
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		var cp;
+
+		dojo.addOnLoad(function(){
+			cp = new dijit.layout.ContentPane({
+				content: "hello world",
+				style: "border: solid black thin;"
+			});
+			dojo.body().appendChild(cp.domNode);
+		});
+	</script>
+
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit layout.ContentPane programmatic tests</h1>
+
+	<button onclick="cp.set('content', 'good night, sweet prince')">set content</button>
+	<button onclick="cp.set('href', 'doc0.html')">set href</button>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_Gui.html b/dijit/tests/layout/test_Gui.html
new file mode 100644
index 0000000..865be23
--- /dev/null
+++ b/dijit/tests/layout/test_Gui.html
@@ -0,0 +1,275 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit UI Tester</title>
+
+	<!-- required: a default theme -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+
+		html, body {
+			height: 100%;
+			width: 100%;
+			padding: 0px;
+			margin: 0px;
+			border: 0;
+			background: #fff;
+		}
+		#main {
+			font-size: 0.9em;
+			height: 100%;
+			width: 100%;
+			padding: 5px;
+			margin: 0px;
+		}
+
+		/* initial sizing */
+		#leftAccordion {
+			width: 25%;
+		}
+		#bottomTabs {
+			height: 40%;
+		}
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: false"></script>
+
+	<!-- do not use: only for debugging / testing themes -->
+	<script type="text/javascript" src="../../tests/_testCommon.js"></script>
+
+	<script type="text/javascript">
+		// dojo.requires()
+		dojo.require("dijit.dijit");
+		dojo.require("dijit.dijit-all");
+
+		// layouts used in page
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.TitlePane");
+
+	</script>
+</head>
+<body class="claro">
+
+	<!-- "main" BorderContainer just contains page title and another BorderContainer -->
+	<div id="main" dojoType="dijit.layout.BorderContainer" gutters=true>
+		<div dojoType="dijit.layout.ContentPane" region="top" splitter="false">This test is to make sure nested layout elements work fine in regards to double borders etc. You need a screen with a very high resolution to not get cramped tabs and other weird visual effects </div>
+
+		<!-- "mainSplit" BorderContainer has all the real content -->
+		<div dojoType="dijit.layout.BorderContainer" liveSplitters="false" design="sidebar"
+			region="center" id="mainSplit">
+
+			<div dojoType="dijit.layout.AccordionContainer"
+				minSize="20" style="width: 300px;" id="leftAccordion" region="leading" splitter="true">
+
+				<div dojoType="dijit.layout.ContentPane" title="Popups and Alerts">
+				</div>
+
+				<div dojoType="dijit.layout.ContentPane" title="Dojo Tree from Store">
+				</div>
+
+				<div dojoType="dijit.layout.ContentPane" title="Calendar" selected="true">
+				</div>
+
+				<div dojoType="dijit.layout.ContentPane" title="Color Picker">
+				</div>
+
+			</div><!-- end AccordionContainer -->
+
+			<div dojoType="dijit.layout.BorderContainer" liveSplitters="false" region="center">
+				<!-- top tabs (marked as "center" to take up the main part of the BorderContainer) -->
+				<div dojoType="dijit.layout.TabContainer" region="top" id="topTabs1" tabStrip="true" splitter="true" style="height:200px;">
+
+					<div dojoType="dijit.layout.ContentPane"
+						id="basdicFormTab"
+						title="Basic Form Widgets"
+						layoutType="fit"
+						style="padding:10px;display:none;">
+						Hi friends of dijit
+					</div> <!-- end of basic form widgets -->
+					<div dojoType="dijit.layout.AccordionContainer"
+						id="tabAccordion"
+						title="Accordion in Tab"
+						layoutType="tab"
+						minSize="20"
+						style="width: 100%;">
+
+						<div dojoType="dijit.layout.ContentPane" title="Popups and Alerts">
+						</div>
+
+						<div dojoType="dijit.layout.ContentPane" title="Dojo Tree from Store">
+						</div>
+
+						<div dojoType="dijit.layout.ContentPane" title="Calendar" selected="true">
+						</div>
+
+						<div dojoType="dijit.layout.ContentPane" title="Color Picker">
+						</div>
+
+					</div><!-- end AccordionContainer -->
+
+					<div dojoType="dijit.layout.ContentPane"
+						id="textareaTab"
+						layoutType="tab"
+						title="Accordion in Content Tab">
+
+						<div dojoType="dijit.layout.AccordionContainer"
+							minSize="20" layoutType="default" style="width: 100%;" id="tabAccordionContainer">
+
+							<div dojoType="dijit.layout.ContentPane" title="Popups and Alerts">
+							</div>
+
+							<div dojoType="dijit.layout.ContentPane" title="Tabs in Accordion">
+								<!-- bottom right tabs -->
+								<div dojoType="dijit.layout.BorderContainer" liveSplitters="false" design="sidebar"
+									id="mainSplit1" style="padding: 0px;width: 300px; height: 100px">
+
+									<div dojoType="dijit.layout.TabContainer" id="accTabs"
+										tabPosition="top" region="center" selectedChild="bbtab1">
+
+										<!-- btab 1 -->
+										<div dojoType="dijit.layout.ContentPane" id="bbtab1"
+											layoutType="tab" title="Info" style=" padding:10px;">
+										</div><!-- end:info btab1 -->
+
+										<div dojoType="dijit.layout.ContentPane" id="bbtab2"
+											layoutType="tab" title="Alternate Themes" style="padding:20px;">
+										</div><!-- btab2 -->
+
+										<div dojoType="dijit.layout.ContentPane" id="bbtab3"
+											layoutType="tab" title="Bottom 3" closable="true">
+										</div><!-- btab3 -->
+
+									</div><!-- end Bottom TabContainer -->
+								</div>
+							</div>
+
+							<div dojoType="dijit.layout.ContentPane" title="Calendar" selected="true">
+							</div>
+
+							<div dojoType="dijit.layout.ContentPane" title="Color Picker">
+							</div>
+
+						</div><!-- end AccordionContainer -->
+
+					</div><!-- end of Textarea/Editor tab -->
+
+
+					<div dojoType="dijit.layout.ContentPane"
+						title="Title Pane in Content Pane"
+						layoutType="tab"
+						doLayout="false"
+						style="display:none;">
+
+						Here's some text, then a TitlePane:
+						<div dojoType="dijit.TitlePane" title="Color Picker">
+							Hi friends of dijit
+						</div>
+						... and some more text.
+					</div>
+
+					<div dojoType="dijit.layout.TabContainer" title="TabContainer in Tab" nested="true" closable="true">
+						<div id="basicFormTab1" dojoType="dijit.layout.ContentPane"
+							layoutType="fit" title="Basic Form Widgets 1"
+							style="padding:10px; display:none;">
+						    Hi friends of dijit
+						</div>
+						<div id="basicFormTab2" dojoType="dijit.layout.ContentPane"
+							layoutType="fit" title="Basic Form Widgets 2"
+							style="padding:10px; display:none;">
+						    Hi friends of dijit
+						</div>
+					</div>
+
+					<div id="closableTab" dojoType="dijit.layout.ContentPane" layoutType="tab" title="Closable ContentPane w/TabContainer"
+						style="display:none; padding:0px;" closable="true">
+
+						<div dojoType="dijit.layout.TabContainer" title="Tab in Tab" nested="true">
+
+							<div id="basicFormTab3" dojoType="dijit.layout.ContentPane" layoutType="fit" title="Basic Form Widgets 3" style="padding:10px;display:none;">
+							    Hi friends of dijit
+							</div>
+							<div id="basicFormTab4" dojoType="dijit.layout.ContentPane" layoutType="fit" title="Basic Form Widgets 4" style="padding:10px;display:none;">
+							    Hi friends of dijit
+							</div>
+						</div>
+					</div>
+				</div><!-- end of region="center" TabContainer -->
+				<div dojoType="dijit.layout.BorderContainer" liveSplitters="false" region="center">
+					<div dojoType="dijit.layout.TabContainer" id="bottomTabs1" tabStrip="true"
+						tabPosition="left-h" selectedChild="btabA" region="top" style="height: 50%;" splitter="true">
+
+						<!-- btab 1 -->
+						<div id="btabA" dojoType="dijit.layout.ContentPane" layoutType="tab" title="Info" style="padding:10px;">
+
+						</div><!-- end:info btabA -->
+
+						<div id="btabB" dojoType="dijit.layout.ContentPane" layoutType="tab" title="Alternate Themes" style="padding:20px;">
+
+						</div><!-- btabB -->
+
+						<div id="btabC" dojoType="dijit.layout.ContentPane" layoutType="tab" title="Bottom 3" closable="true">
+
+						</div><!-- btabC -->
+
+					</div><!-- end Bottom TabContainer -->
+					<div dojoType="dijit.layout.TabContainer" id="bottomTabs2" tabStrip="true"
+						tabPosition="right-h" selectedChild="btabD" region="center">
+
+						<!-- btab 1 -->
+						<div id="btabD" dojoType="dijit.layout.ContentPane" layoutType="tab" title="Info" style="padding:10px;">
+
+						</div><!-- end:info btabD -->
+
+						<div id="btabE" dojoType="dijit.layout.ContentPane" layoutType="tab" title="Alternate Themes" style="padding:20px;">
+
+						</div><!-- btabE -->
+
+						<div id="btabF" dojoType="dijit.layout.ContentPane" layoutType="tab" title="Bottom 3" closable="true">
+
+						</div><!-- btabF -->
+
+					</div><!-- end Bottom TabContainer -->
+				</div>
+				<!-- bottom right tabs -->
+				<div dojoType="dijit.layout.TabContainer" id="bottomTabs" tabStrip="true"
+					tabPosition="bottom" selectedChild="btab1" region="bottom" splitter="true">
+
+					<!-- btab 1 -->
+					<div dojoType="dijit.layout.BorderContainer" liveSplitters="false" design="sidebar"
+						region="center" id="bottomSplit" title="BorderContainer in Tabs" style="padding: 5px; width: 100%">
+						<div dojoType="dijit.layout.ContentPane" region="top" splitter="true" liveSplitters="false">This test is to make sure nested layout elements work fine in regards to double borders etc. You need a screen with a very high resolution to not get cramped tabs and other weird visual effects </div>
+						<div dojoType="dijit.layout.TabContainer" id="bottomTabs22"
+							tabPosition="top" selectedChild="btabAA" region="center" splitter="true">
+
+							<!-- btab 1 -->
+							<div id="btabAA" dojoType="dijit.layout.ContentPane" layoutType="tab" title="Info" style="padding:10px;">Hi</div>
+						</div>
+
+						<div dojoType="dijit.layout.ContentPane" region="bottom" splitter="true" liveSplitters="false">This test is to make sure nested layout elements work fine in regards to double borders etc. You need a screen with a very high resolution to not get cramped tabs and other weird visual effects </div>
+
+					</div>
+
+					<div id="btab2" dojoType="dijit.layout.ContentPane" layoutType="tab" title="Alternate Themes" style="padding:20px;">
+
+					</div><!-- btab2 -->
+
+					<div id="btab3" dojoType="dijit.layout.ContentPane" layoutType="tab" title="Bottom 3" closable="true">
+
+					</div><!-- btab3 -->
+
+				</div><!-- end Bottom TabContainer -->
+			</div>
+		</div> <!-- end of "mainSplit" BorderContainer -->
+		<div dojoType="dijit.layout.ContentPane" region="trailing" splitter="true" style="width: 10%;" liveSplitters="false">Hi </div>
+
+	</div><!-- end of "main" BorderContainer -->
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_LayoutContainer.html b/dijit/tests/layout/test_LayoutContainer.html
new file mode 100644
index 0000000..9f642fc
--- /dev/null
+++ b/dijit/tests/layout/test_LayoutContainer.html
@@ -0,0 +1,183 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.layout.LayoutContainer Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../themes/tundra/tundra.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.LayoutContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+
+</head>
+<body class="claro">
+	<h2>Dijit layout.LayoutContainer tests</h2>
+
+	<p>Basic layout. Tabindex="0" added to each pane to test for tab order matching source code order.  Tab order
+	should be:  left, right, top, middle/main, bottom</p>
+
+	<div dojoType="dijit.layout.LayoutContainer"
+		style="border: 2px solid black; width: 90%; height: 300px; padding: 10px;"
+	>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="left" style="background-color: #acb386; width: 100px;" tabindex="0">
+			left
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="right" style="background-color: #acb386;"  tabindex="0">
+			right
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="top" style="background-color: #b39b86; "  tabindex="0">
+			top bar
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="client" style="background-color: #f5ffbf; padding: 10px;"  tabindex="0">
+			main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+			(to check we're copying children around properly).<br />
+			<select dojoType="dijit.form.FilteringSelect">
+				<option value="1">foo</option>
+				<option value="2">bar</option>
+				<option value="3">baz</option>
+			</select>
+			Here's some text that comes AFTER the combo box.
+		</div>
+
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="bottom" style="background-color: #b39b86;"  tabindex="0">
+			bottom bar
+		</div>
+
+	</div>
+
+	<p>Advanced layout. Tabindex="0" added to each pane to test for tab order matching source code order.  Tab order
+	should be:  left, top, bottom, inner left, inner middle, inner right. This is not an ideal tab order. See below to use nested
+	layout containers to achieve a tab order which matches presentation and source code order.</p>
+	<div dojoType="dijit.layout.LayoutContainer"
+		style="border: 2px solid black; width: 90%; height: 300px; padding: 10px;"
+	>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="left" style="background-color: #acb386; width: 100px; margin: 5px;" tabindex="0">
+			left
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="top" style="background-color: #b39b86;  margin: 5px;" tabindex="0">
+			top bar
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="bottom" style="background-color: #b39b86; margin: 5px;" tabindex="0">
+
+			bottom bar
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="left" style="background-color: #eeeeee; width: 100px; margin: 5px;" tabindex="0">
+			inner left
+		</div>
+
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="client" style="background-color: #f5ffbf; padding: 10px; margin: 5px;" tabindex="0">
+			main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+
+			(to check we're copying children around properly).<br />
+			<select dojoType="dijit.form.FilteringSelect">
+				<option value="1">foo</option>
+				<option value="2">bar</option>
+				<option value="3">baz</option>
+			</select>
+			Here's some text that comes AFTER the combo box.
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="right" style="background-color: #eeeeee; width: 100px; margin: 5px;" tabindex="0">
+			inner right
+		</div>
+	</div>
+
+	<p>Advanced layout with nested containers.  Tabindex="0" added to content panes to show tab order. Order should be:
+	left, top, inner left, inner middle, inner right, bottom. This is the preferred tab order for this type of layout.</p>
+	<div dojoType="dijit.layout.LayoutContainer"
+		style="border: 2px solid black; width: 90%; height: 300px; padding: 10px;"
+	>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="left" style="background-color: #acb386; width: 100px; margin: 5px;" tabindex="0">
+			left
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="client" style="margin: 5px;" >
+			<div dojoType="dijit.layout.LayoutContainer"	style="height:90%;border: 2px solid black;padding: 10px;">
+
+				<div dojoType="dijit.layout.ContentPane" layoutAlign="top" style="background-color: #b39b86;  margin: 5px;" tabindex="0">
+					top bar
+				</div>
+				<div dojoType="dijit.layout.ContentPane" layoutAlign="client" style="margin: 5px;">
+					<div dojoType="dijit.layout.LayoutContainer"	style="height:80%;border: 2px solid black;padding: 10px;">
+						<div dojoType="dijit.layout.ContentPane" layoutAlign="left" style="background-color: #eeeeee; width: 100px; margin: 5px;" tabindex="0">
+							inner left
+						</div>
+						<div dojoType="dijit.layout.ContentPane" layoutAlign="client" style="background-color: #f5ffbf; padding: 10px; margin: 5px;" tabindex="0">
+							main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+							(to check we're copying children around properly).<br />
+							<select dojoType="dijit.form.FilteringSelect">
+								<option value="1">foo</option>
+								<option value="2">bar</option>
+								<option value="3">baz</option>
+							</select>
+							Here's some text that comes AFTER the combo box.
+						</div>
+						<div dojoType="dijit.layout.ContentPane" layoutAlign="right" style="background-color: #eeeeee; width: 100px; margin: 5px;" tabindex="0">
+							inner right
+						</div>
+					</div>
+				</div>
+				<div dojoType="dijit.layout.ContentPane" layoutAlign="bottom" style="background-color: #b39b86; margin: 5px;" tabindex="0"	>
+					bottom bar
+				</div>
+			</div>
+		</div>
+	</div>
+
+	<p>Goofy spiral layout.  Match of source code order to tab order can not be achieved with this type of layout.</p>
+	<div dojoType="dijit.layout.LayoutContainer"
+		style="border: 2px solid black; width: 90%; height: 300px; padding: 10px;"
+	>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="left" style="background-color: #663333; color: white; width: 100px;">
+			outer left
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="top" style="background-color: #333366; color: white; height: 50px;">
+			outer top
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="right" style="background-color: #663333; color: white; width: 100px;">
+			outer right
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="bottom" style="background-color: #333366; color: white; height: 50px;">
+			outer bottom
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="left" style="background-color: #99CC99; width: 100px;">
+			inner left
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="top" style="background-color: #999966; height: 50px;">
+			inner top
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="right" style="background-color: #99CC99; width: 100px;">
+			inner right
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="bottom" style="background-color: #999966; height: 50px;">
+			inner bottom
+		</div>
+		<div dojoType="dijit.layout.ContentPane" layoutAlign="client" style="padding: 10px;">
+			main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+			(to check we're copying children around properly).<br />
+			<select dojoType="dijit.form.FilteringSelect">
+				<option value="1">foo</option>
+				<option value="2">bar</option>
+				<option value="3">baz</option>
+			</select>
+			Here's some text that comes AFTER the combo box.
+		</div>
+	</div>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_SplitContainer.html b/dijit/tests/layout/test_SplitContainer.html
new file mode 100644
index 0000000..1089290
--- /dev/null
+++ b/dijit/tests/layout/test_SplitContainer.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>SplitContainer Widget Demo</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+		.dojoContentPane {
+			padding:1em;
+		}
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.SplitContainer");
+		dojo.require("dijit.layout.ContentPane");
+
+		// these exist inside our href splitcontainer
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.ComboBox");
+		var programaticExample = function(){
+
+			var rootNode = dojo.byId("holderNode");
+			// add two children
+			var pane1 = rootNode.appendChild(document.createElement('div'));
+			var pane2 = rootNode.appendChild(document.createElement('div'));
+			var pane3 = rootNode.appendChild(document.createElement('div'));
+
+			// set the content. can use xhrGet, also
+			pane1.innerHTML = "Pane one test"; pane2.innerHTML = "Pane two test";
+
+			// should use css, but this works:
+			dojo.style(rootNode,"height","150px");
+			dojo.style(rootNode,"border","1px solid #333");
+
+			// make them contentpanes
+			var cp1 = new dijit.layout.ContentPane({ sizeShare:20 },pane1);
+			var cp2 = new dijit.layout.ContentPane({ sizeShare:30 },pane2);
+			var cp3 = new dijit.layout.ContentPane({
+				href: "doc0.html",
+				sizeShare:30
+			},pane3).startup();
+
+			// init the splitcontainer
+			var split = new dijit.layout.SplitContainer({
+				orientation:"horizontal",
+				sizerWidth:7
+			},rootNode).startup();
+
+		};
+		dojo.addOnLoad(programaticExample);
+
+	</script>
+</head>
+<body>
+	<h1 class="testTitle">Dijit Split Container Test - DEPRECATED!</h1>
+	<p><strong>dijit.layout.SplitContainer is deprecated use
+	BorderContainer with splitter instead -- will be removed in version: 2</strong></p>
+	<p>HTML before</p>
+
+	<div dojoType="dijit.layout.SplitContainer"
+		orientation="vertical"
+		sizerWidth="7"
+		activeSizing="false"
+		style="border: 1px solid #bfbfbf; float: left; margin-right: 30px;  width: 400px; height: 300px;"
+	>
+		<div dojoType="dijit.layout.ContentPane" sizeMin="10" sizeShare="50">
+			this box has three split panes
+		</div>
+		<div dojoType="dijit.layout.ContentPane" sizeMin="20" sizeShare="50"
+			style="background-color: yellow; border: 3px solid purple;">
+			in vertical mode
+		</div>
+		<div dojoType="dijit.layout.ContentPane" sizeMin="10" sizeShare="50">
+			without active resizing
+		</div>
+	</div>
+
+	<div dojoType="dijit.layout.SplitContainer"
+		orientation="horizontal"
+		sizerWidth="7"
+		activeSizing="true"
+		style="border: 1px solid #bfbfbf; float: left; width: 400px; height: 300px;">
+		<div dojoType="dijit.layout.ContentPane" sizeMin="20" sizeShare="20">
+			this box has two horizontal panes
+		</div>
+		<div dojoType="dijit.layout.ContentPane" sizeMin="50" sizeShare="50">
+			with active resizing, a smaller sizer, different starting sizes and minimum sizes
+		</div>
+	</div>
+
+	<p style="clear: both;">HTML after</p>
+
+the following splitter contains two iframes, see whether the resizer works ok in this situation
+<div dojoType="dijit.layout.SplitContainer"
+	orientation="horizontal"
+	sizerWidth="5"
+	activeSizing="false"
+	style="border: 2px solid black; float: left; width: 100%; height: 300px;"
+>
+	<div dojoType="dijit.layout.ContentPane" sizeMin="20" sizeShare="20">
+		<iframe style="width: 100%; height: 100%"></iframe>
+	</div>
+	<div dojoType="dijit.layout.ContentPane" sizeMin="50" sizeShare="50">
+		<iframe style="width: 100%; height: 100%"></iframe>
+	</div>
+</div>
+
+<h3>Programatic Example:</h3>
+<div id="holderNode"></div>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_StackContainer.html b/dijit/tests/layout/test_StackContainer.html
new file mode 100644
index 0000000..f41d579
--- /dev/null
+++ b/dijit/tests/layout/test_StackContainer.html
@@ -0,0 +1,171 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>StackContainer Demo</title>
+
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+		.dijitStackController .dijitToggleButtonChecked button {
+			background-color: white;
+			background-image: none;
+		}
+		.dijit_a11y .dijitStackController .dijitToggleButtonChecked button {
+			border-style: dashed !important;
+		}
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.StackContainer");
+		dojo.require("dijit.layout.StackController");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		function selected(page){
+			console.debug("page selected " + page.id);
+			var widget=dijit.byId("myStackContainer");
+			dijit.byId("previous").set("disabled", page.isFirstChild);
+			dijit.byId("next").set("disabled", page.isLastChild);
+			dijit.byId("previous2").set("disabled", page.isFirstChild);
+			dijit.byId("next2").set("disabled", page.isLastChild);
+		}
+		dojo.subscribe("myStackContainer-selectChild", selected);
+	</script>
+</head>
+
+<body class="claro">
+	<h1 class="testTitle">A Tale Of Two Cities</h1>
+
+	<button dojoType="dijit.form.Button" id="previous"
+		onClick="dijit.byId('myStackContainer').back()"><</button>
+	<span dojoType="dijit.layout.StackController" containerId="myStackContainer"></span>
+	<button dojoType="dijit.form.Button" id="next"
+		onClick="dijit.byId('myStackContainer').forward()">></button>
+
+	<div id="myStackContainer" dojoType="dijit.layout.StackContainer"
+		style="width: 90%; border: 1px solid #9b9b9b; height: 20em; margin: 0.5em 0 0.5em 0; padding: 0.5em;">
+		<p id="page1" dojoType="dijit.layout.ContentPane" title="page 1">IT WAS the best of times, it <input value="was the worst" /> of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the  [...]
+		<p id="page2" dojoType="dijit.layout.ContentPane" title="page 2">There were a king with a large jaw and a queen with a plain face, on the throne of England; there were a king with a large jaw and a queen with a fair face, on the throne of <a href="http://www.france.com">France</a>. In both countries it was clearer than crystal to the lords of the State preserves of loaves and fishes, that things in general were settled for ever.</p>
+		<p id="page3" dojoType="dijit.layout.ContentPane" title="page 3">It was the year of Our Lord one thousand seven hundred and seventy- five. Spiritual revelations were conceded to England at that favoured period, as at this. Mrs. Southcott had recently attained her five-and- twentieth blessed birthday, of whom a prophetic private in the Life Guards had heralded the sublime appearance by announcing that arrangements were made for the swallowing up of London and Westminster. Even the Cock- [...]
+	</div>
+
+	<button dojoType="dijit.form.Button" id="previous2" onClick="dijit.byId('myStackContainer').back()"><</button>
+	<span dojoType="dijit.layout.StackController" containerId="myStackContainer"></span>
+	<button dojoType="dijit.form.Button" id="next2" onClick="dijit.byId('myStackContainer').forward()">></button>
+
+
+	<h1 class="testTitle" style="margin-top: 3em;">Embedded layout widgets</h1>
+	<p>This tests having layout widgets embedded in the StackContainer, making sure they render on the hidden pane.</p>
+
+	<button dojoType="dijit.form.Button" id="previousPR"
+		onClick="dijit.byId('myStackContainerPR').back()"><</button>
+	<span dojoType="dijit.layout.StackController" containerId="myStackContainerPR"></span>
+	<button dojoType="dijit.form.Button" id="nextPR"
+		onClick="dijit.byId('myStackContainerPR').forward()">></button>
+
+	<div id="myStackContainerPR" dojoType="dijit.layout.StackContainer"
+		style="width: 90%; border: 1px solid #9b9b9b; height: 20em; margin: 0.5em 0 0.5em 0; padding: 0.5em;">
+		<div id="page1PR" dojoType="dijit.layout.ContentPane" title="page 1">
+			<p>
+				The next pane should have some text, plus two embedded layout widgets, which should
+				appear correctly even though the pane is initially hidden
+			</p>
+		</div>
+		<div id="page2PR" dojoType="dijit.layout.ContentPane" title="page 2" style="padding: 1em;">
+			<p>
+				Here's a BorderContainer:
+			</p>
+			<div dojoType="dijit.layout.BorderContainer" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" region="left" style="width:100px" splitter="true">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				And a TabContainer:
+			</p>
+			<div dojoType="dijit.layout.TabContainer" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" title="Tab 1">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Tab 2">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				That's it!
+			</p>
+		</div>
+	</div>
+
+	<button dojoType="dijit.form.Button" id="previous2PR" onClick="dijit.byId('myStackContainerPR').back()"><</button>
+	<span dojoType="dijit.layout.StackController" containerId="myStackContainerPR"></span>
+	<button dojoType="dijit.form.Button" id="next2PR" onClick="dijit.byId('myStackContainerPR').forward()">></button>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_StackContainer_code.html b/dijit/tests/layout/test_StackContainer_code.html
new file mode 100644
index 0000000..cdc1583
--- /dev/null
+++ b/dijit/tests/layout/test_StackContainer_code.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>StackContainer Demo</title>
+
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+		.dijitStackController .dijitToggleButtonChecked button {
+			background-color: white;
+			background-image: none;
+		}
+		.dijit_a11y .dijitStackController .dijitToggleButtonChecked button {
+			border-style: dashed !important;
+		}
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.StackContainer");
+		dojo.require("dijit.layout.StackController");
+		dojo.require("dijit.form.Button");
+
+		dojo.addOnLoad(function(){
+			// make the container
+			var container = new dijit.layout.StackContainer({ id: "sc" },"myStackContainer");
+			container.addChild(new dijit.layout.ContentPane({
+					title: "Page 1",
+					content: "IT WAS the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period,  [...]
+			}));
+			container.addChild(new dijit.layout.ContentPane({
+					title: "Page 2",
+					content: "There were a king with a large jaw and a queen with a plain face, on the throne of England; there were a king with a large jaw and a queen with a fair face, on the throne of France. In both countries it was clearer than crystal to the lords of the State preserves of loaves and fishes, that things in general were settled for ever."
+			}));
+			container.addChild(new dijit.layout.ContentPane({
+					title: "Page 3",
+					content: "It was the year of Our Lord one thousand seven hundred and seventy- five. Spiritual revelations were conceded to England at that favoured period, as at this. Mrs. Southcott had recently attained her five-and- twentieth blessed birthday, of whom a prophetic private in the Life Guards had heralded the sublime appearance by announcing that arrangements were made for the swallowing up of London and Westminster. Even the Cock-lane ghost had been laid only a round dozen of years [...]
+			}));
+
+			// make the controller
+			var controller = new dijit.layout.StackController({containerId: "sc"}, "holder");
+
+			// start 'em up
+ 			controller.startup();
+ 			container.startup();
+		});
+	</script>
+</head>
+
+<body class="claro">
+	<h1 class="testTitle">A Tale Of Two Cities</h1>
+
+	Links: <span id="holder"></span>
+
+	<div id="myStackContainer" style="width: 90%; border: 1px solid #9b9b9b; height: 20em; margin: 0.5em 0 0.5em 0; padding: 0.5em;">
+	</div>
+
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_TabContainer.html b/dijit/tests/layout/test_TabContainer.html
new file mode 100644
index 0000000..e2816ae
--- /dev/null
+++ b/dijit/tests/layout/test_TabContainer.html
@@ -0,0 +1,1059 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>TabContainer Demo</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+
+		body {
+			font-family : sans-serif;
+			margin:20px;
+		}
+
+		/* add padding to each contentpane inside the tab container, and scrollbar if necessary */
+		.dojoTabPane {
+			padding : 10px 10px 10px 10px;
+			overflow: auto;
+		}
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.SplitContainer");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.Tooltip");
+		dojo.require("dijit.layout.LinkPane");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		function testClose(pane,tab){
+		  return confirm("Please confirm that you want tab "+tab.title+" closed");
+		}
+
+		startTime = new Date();
+		dojo.addOnLoad(function(){
+			var elapsed = new Date().getTime() - startTime;
+			var p = document.createElement("p");
+			p.appendChild(document.createTextNode("Widgets loaded in " + elapsed + "ms"));
+			document.body.appendChild(p);
+		});
+
+		var progTabCounter = 1;
+		function makeTab(){
+			var tc = dijit.byId("mainTabContainer");
+			var cp = new dijit.layout.ContentPane({
+				title: 'Programmatically created tab ' + (progTabCounter++) ,
+				closable: true
+			});
+			cp.domNode.innerHTML = "I was created programmatically!";
+			tc.addChild(cp, 0);
+		}
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit layout.TabContainer tests</h1>
+
+	<p>These tabs are made up of local and external content. Tab 1 and Tab 2 are loading
+	files tab1.html and tab2.html. Tab 3 and Another Tab are using content that is already
+	part of this page.   Tab2 is initially selected. Attribute tabStrip is set to true
+	</p>
+
+	<p>
+		More tabs can be displayed in the first two TabContainers by clicking the
+		drop down control to the right of the widget.  If the tabs are not wider than
+		the widget, the scrolling controls should disappear - this can be tested by closing the
+		closable tabs.
+	</p>
+
+	<button id="firstButton" onclick="makeTab()">Click To Add Tab</button>
+
+	<br><br>
+
+	<div id="mainTabContainer" dojoType="dijit.layout.TabContainer"
+				persist="false" tabStrip="true" style="width: 400px;height: 20em;">
+
+		<div id="tab1" dojoType="dijit.layout.ContentPane" href="tab1.html" title="Tab 1" iconClass="plusIcon"
+			tooltip="Tooltip for tab #1"></div>
+
+		<div id="tab2" dojoType="dijit.layout.ContentPane" href="tab2.html" refreshOnShow="true" title="Tab 2" iconClass="noteIcon" selected="true"></div>
+
+		<div dojoType="dijit.layout.ContentPane" id="tab3" title="Tab 3"
+				iconClass="dijitEditorIcon dijitEditorIconSave" closable="true">
+			<h1>I am tab 3</h1>
+			<p>And I was already part of the page! That's cool, no?</p>
+			<p id="foo">tooltip on this paragraph</p>
+			<div dojoType="dijit.Tooltip" connectId="foo">I'm a tooltip!</div>
+			<button dojoType="dijit.form.Button">I'm a button </button>
+			<br>
+			<button dojoType="dijit.form.Button">So am I!</button>
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+			porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+			Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+			Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+			risus.
+			</p>
+			<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+			nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+			massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+			pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+			quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+			felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+			quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+			rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+			semper velit ante id metus. Praesent massa dolor, porttitor sed,
+			pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+			tortor pharetra congue. Suspendisse pulvinar.
+			</p>
+		</div>
+
+		<div dojoType="dijit.layout.TabContainer" id="inlined" title="Inlined Sub TabContainer" iconClass="plusIcon" nested="true">
+			<a dojoType="dijit.layout.LinkPane" id="tab1href" href="tab1.html" onLoad="console.log('load of SubTab 1');" iconClass="plusIcon" >SubTab 1</a>
+			<a dojoType="dijit.layout.LinkPane" id="tab2href" href="tab2.html"  onLoad="console.log('load of SubTab 2');" selected="true"  iconClass="dijitEditorIcon dijitEditorIconSave">SubTab 2</a>
+			<div dojoType="dijit.layout.ContentPane" id="subtab3" title="SubTab 3"  iconClass="dijitEditorIcon dijitEditorIconCut">
+				<h1>I am tab 3, inlined.</h1>
+			</div>
+			<div dojoType="dijit.layout.ContentPane" id="subtab4" title="SubTab 4" iconClass="dijitEditorIcon dijitEditorIconCopy">
+				<h1>I am tab 4, inlined.</h1>
+			</div>
+		</div>
+
+		<a dojoType="dijit.layout.LinkPane" id="tab3href" href="tab3.html" refreshOnShow="true" closable="true"
+				style="padding: 0" iconClass="dijitEditorIcon dijitEditorIconSave">Sub TabContainer from href</a>
+		<a dojoType="dijit.layout.LinkPane" id="tab4href" href="tab4.html"
+				closable="true" iconClass="dijitEditorIcon dijitEditorIconCut">SplitContainer from href</a>
+		<div dojoType="dijit.layout.ContentPane" id="embedded" title="Embedded layout widgets"
+				closable="true" iconClass="dijitEditorIcon dijitEditorIconCopy">
+			<p>
+				The tab has some text, plus two embedded layout widgets, which should
+				appear correctly even though the tab is initially hidden.
+			</p>
+			<p>
+				Here's a BorderContainer:
+			</p>
+			<div dojoType="dijit.layout.BorderContainer" id="bc" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" region="left" style="width:100px" splitter="true">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				And a TabContainer:
+			</p>
+			<div dojoType="dijit.layout.TabContainer" id="embeddedTC" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" id="embeddedTab1" title="Tab 1">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" id="embeddedTab2" title="Tab 2">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				Text after the widgets.
+			</p>
+		</div>
+	</div>
+
+	<button onclick="dijit.byId('tab1').set('title', 'Tab 1 Renamed');">Rename Tab #1</button>
+	<button onclick="dijit.byId('tab2').set('title', 'Tab 2 Renamed To Something Very Long');">Rename Tab #2</button>
+	<button onclick="dijit.byId('tab1').set('closable', !dijit.byId('tab1').get('closable'));">Toggle Tab #1 closable</button>
+	<br/>
+	<p>
+		This tab container has the Menu function for selecting tabs disabled, using <b>useMenu="false"</b>
+	</p>
+
+	<div dojoType="dijit.layout.TabContainer" useMenu="false"
+				persist="false" tabStrip="true" style="width: 400px;height: 20em;">
+		<div  dojoType="dijit.layout.ContentPane" href="tab1.html" title="Tab 1"></div>
+
+
+		<div  dojoType="dijit.layout.ContentPane" href="tab2.html" refreshOnShow="true" title="Tab 2" selected="true"></div>
+
+		<div dojoType="dijit.layout.ContentPane"  title="Tab 3" closable="true">
+			<h1>I am tab 3</h1>
+			<p>And I was already part of the page! That's cool, no?</p>
+			<p id="foo">tooltip on this paragraph</p>
+			<div dojoType="dijit.Tooltip" connectId="foo">I'm a tooltip!</div>
+			<button dojoType="dijit.form.Button">I'm a button </button>
+			<br>
+			<button dojoType="dijit.form.Button">So am I!</button>
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+			porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+			Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+			Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+			risus.
+			</p>
+			<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+			nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+			massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+			pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+			quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+			felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+			quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+			rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+			semper velit ante id metus. Praesent massa dolor, porttitor sed,
+			pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+			tortor pharetra congue. Suspendisse pulvinar.
+			</p>
+		</div>
+
+		<div dojoType="dijit.layout.TabContainer"  closable="true" title="Inlined Sub TabContainer" nested="true">
+			<a dojoType="dijit.layout.LinkPane"  href="tab1.html" onLoad="console.log('load of SubTab 1');">SubTab 1</a>
+			<a dojoType="dijit.layout.LinkPane"  href="tab2.html"  onLoad="console.log('load of SubTab 2');" selected="true">SubTab 2</a>
+			<div dojoType="dijit.layout.ContentPane"  title="SubTab 3">
+				<h1>I am tab 3, inlined.</h1>
+			</div>
+			<div dojoType="dijit.layout.ContentPane"  title="SubTab 4">
+				<h1>I am tab 4, inlined.</h1>
+			</div>
+		</div>
+
+		<a dojoType="dijit.layout.LinkPane"  href="tab3.html" closable="true" refreshOnShow="true" style="padding: 0">Sub TabContainer from href</a>
+
+		<a dojoType="dijit.layout.LinkPane"  closable="true" href="tab4.html">SplitContainer from href</a>
+
+		<div dojoType="dijit.layout.ContentPane"  closable="true" title="Embedded layout widgets">
+			<p>
+				The tab has some text, plus two embedded layout widgets, which should
+				appear correctly even though the tab is initially hidden.
+			</p>
+			<p>
+				Here's a BorderContainer:
+			</p>
+			<div dojoType="dijit.layout.BorderContainer" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" region="left" style="width:100px" splitter="true">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				And a TabContainer:
+			</p>
+			<div dojoType="dijit.layout.TabContainer"  style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" title="Tab 1">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Tab 2">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				Text after the widgets.
+			</p>
+		</div>
+	</div>
+
+
+	<br/>
+
+	<p>Tabs w/only icons (except in high-contrast mode where labels display):</p>
+	<div id="iconTabs" dojoType="dijit.layout.TabContainer" tabPosition="top" style="width: 100%; height: 10em;">
+		<div id="iconTab1" dojoType="dijit.layout.ContentPane" title="Cut" tooltip="tooltip for cut button" showTitle="false" iconClass="dijitEditorIcon dijitEditorIconCut">Cut icon tab</div>
+		<div id="iconTab2" dojoType="dijit.layout.ContentPane" title="Copy" showTitle="false" iconClass="dijitEditorIcon dijitEditorIconCopy">Copy icon tab</div>
+		<div id="iconTab3" dojoType="dijit.layout.ContentPane" title="Paste" showTitle="false" iconClass="dijitEditorIcon dijitEditorIconPaste">Paste icon tab</div>
+	</div>
+
+
+	<p>
+		This tab container has the Slider function for selecting tabs disabled, using <b>useSlider="false"</b>
+	</p>
+	<div dojoType="dijit.layout.TabContainer" useSlider="false"
+				persist="false" tabStrip="true" style="width: 400px;height: 20em;">
+
+		<div  dojoType="dijit.layout.ContentPane" href="tab1.html" title="Tab 1"></div>
+
+		<div  dojoType="dijit.layout.ContentPane" href="tab2.html" refreshOnShow="true" title="Tab 2" selected="true"></div>
+
+		<div dojoType="dijit.layout.ContentPane"  title="Tab 3" closable="true">
+			<h1>I am tab 3</h1>
+			<p>And I was already part of the page! That's cool, no?</p>
+			<p id="foo">tooltip on this paragraph</p>
+			<div dojoType="dijit.Tooltip" connectId="foo">I'm a tooltip!</div>
+			<button dojoType="dijit.form.Button">I'm a button </button>
+			<br>
+			<button dojoType="dijit.form.Button">So am I!</button>
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+			porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+			Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+			Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+			risus.
+			</p>
+			<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+			nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+			massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+			pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+			quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+			felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+			quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+			rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+			semper velit ante id metus. Praesent massa dolor, porttitor sed,
+			pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+			tortor pharetra congue. Suspendisse pulvinar.
+			</p>
+		</div>
+
+		<div dojoType="dijit.layout.TabContainer"  closable="true" title="Inlined Sub TabContainer" nested="true">
+			<a dojoType="dijit.layout.LinkPane"  href="tab1.html" onLoad="console.log('load of SubTab 1');">SubTab 1</a>
+			<a dojoType="dijit.layout.LinkPane"  href="tab2.html"  onLoad="console.log('load of SubTab 2');" selected="true">SubTab 2</a>
+			<div dojoType="dijit.layout.ContentPane"  title="SubTab 3">
+				<h1>I am tab 3, inlined.</h1>
+			</div>
+			<div dojoType="dijit.layout.ContentPane"  title="SubTab 4">
+				<h1>I am tab 4, inlined.</h1>
+			</div>
+		</div>
+
+		<a dojoType="dijit.layout.LinkPane"  href="tab3.html" closable="true" refreshOnShow="true" style="padding: 0">Sub TabContainer from href</a>
+
+		<a dojoType="dijit.layout.LinkPane"  closable="true" href="tab4.html">SplitContainer from href</a>
+
+		<div dojoType="dijit.layout.ContentPane"  closable="true" title="Embedded layout widgets">
+			<p>
+				The tab has some text, plus two embedded layout widgets, which should
+				appear correctly even though the tab is initially hidden.
+			</p>
+			<p>
+				Here's a BorderContainer:
+			</p>
+			<div dojoType="dijit.layout.BorderContainer" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" region="left" style="width:100px" splitter="true">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				And a TabContainer:
+			</p>
+			<div dojoType="dijit.layout.TabContainer"  style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" title="Tab 1">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Tab 2">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				Text after the widgets.
+			</p>
+		</div>
+	</div>
+	<br/>
+	<p>
+		This tab container has the tab strip disabled, using <b>tabStrip="false"</b>
+	</p>
+	<div dojoType="dijit.layout.TabContainer" tabStrip="false"
+				persist="false" tabStrip="true" style="width: 400px;height: 20em;">
+
+		<div  dojoType="dijit.layout.ContentPane" href="tab1.html" title="Tab 1"></div>
+
+		<div  dojoType="dijit.layout.ContentPane" href="tab2.html" refreshOnShow="true" title="Tab 2" selected="true"></div>
+
+		<div dojoType="dijit.layout.ContentPane"  title="Tab 3" closable="true">
+			<h1>I am tab 3</h1>
+			<p>And I was already part of the page! That's cool, no?</p>
+			<p id="foo">tooltip on this paragraph</p>
+			<div dojoType="dijit.Tooltip" connectId="foo">I'm a tooltip!</div>
+			<button dojoType="dijit.form.Button">I'm a button </button>
+			<br>
+			<button dojoType="dijit.form.Button">So am I!</button>
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+			porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+			Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+			Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+			risus.
+			</p>
+			<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+			nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+			massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+			pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+			quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+			felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+			quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+			rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+			semper velit ante id metus. Praesent massa dolor, porttitor sed,
+			pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+			tortor pharetra congue. Suspendisse pulvinar.
+			</p>
+		</div>
+
+		<div dojoType="dijit.layout.TabContainer"  closable="true" title="Inlined Sub TabContainer" nested="true">
+			<a dojoType="dijit.layout.LinkPane"  href="tab1.html" onLoad="console.log('load of SubTab 1');">SubTab 1</a>
+			<a dojoType="dijit.layout.LinkPane"  href="tab2.html"  onLoad="console.log('load of SubTab 2');" selected="true">SubTab 2</a>
+			<div dojoType="dijit.layout.ContentPane"  title="SubTab 3">
+				<h1>I am tab 3, inlined.</h1>
+			</div>
+			<div dojoType="dijit.layout.ContentPane"  title="SubTab 4">
+				<h1>I am tab 4, inlined.</h1>
+			</div>
+		</div>
+
+		<a dojoType="dijit.layout.LinkPane"  href="tab3.html" closable="true" refreshOnShow="true" style="padding: 0">Sub TabContainer from href</a>
+
+		<a dojoType="dijit.layout.LinkPane"  closable="true" href="tab4.html">SplitContainer from href</a>
+
+		<div dojoType="dijit.layout.ContentPane"  closable="true" title="Embedded layout widgets">
+			<p>
+				The tab has some text, plus two embedded layout widgets, which should
+				appear correctly even though the tab is initially hidden.
+			</p>
+			<p>
+				Here's a BorderContainer:
+			</p>
+			<div dojoType="dijit.layout.BorderContainer" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" region="left" style="width:100px" splitter="true">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				And a TabContainer:
+			</p>
+			<div dojoType="dijit.layout.TabContainer"  style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" title="Tab 1">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Tab 2">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				Text after the widgets.
+			</p>
+		</div>
+	</div>
+
+	<p>These tabs are made up of local and external content. Tab 1 and Tab 2 are loading
+	files tab1.html and tab2.html. Tab 3 and Another Tab are using content that is already
+	part of this page.   Tab2 is initially selected. Attribute tabStrip is set to true,
+	and the tabPosition is "bottom"
+	</p>
+
+	<div id="mainTabContainerBottom" dojoType="dijit.layout.TabContainer" tabPosition="bottom"
+				persist="true" tabStrip="true" style="width: 400px; height: 20em;">
+
+		<div dojoType="dijit.layout.ContentPane" href="tab1.html" title="Tab 1"></div>
+
+		<div dojoType="dijit.layout.ContentPane" href="tab2.html" refreshOnShow="true" title="Tab 2" selected="true"></div>
+
+		<div dojoType="dijit.layout.ContentPane" closable="true" title="Tab 3">
+			<h1>I am tab 3</h1>
+			<p>And I was already part of the page! That's cool, no?</p>
+			<p id="foo">tooltip on this paragraph</p>
+			<div dojoType="dijit.Tooltip" connectId="foo">I'm a tooltip!</div>
+			<button dojoType="dijit.form.Button">I'm a button </button>
+			<br>
+			<button dojoType="dijit.form.Button">So am I!</button>
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+			porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+			Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+			Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+			risus.
+			</p>
+			<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+			nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+			massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+			pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+			quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+			felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+			quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+			rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+			semper velit ante id metus. Praesent massa dolor, porttitor sed,
+			pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+			tortor pharetra congue. Suspendisse pulvinar.
+			</p>
+		</div>
+
+		<div dojoType="dijit.layout.TabContainer" closable="true" title="Inlined Sub TabContainer" nested="true">
+			<a dojoType="dijit.layout.LinkPane"  href="tab1.html" onLoad="console.log('load of SubTab 1');">SubTab 1</a>
+			<a dojoType="dijit.layout.LinkPane"  href="tab2.html"  onLoad="console.log('load of SubTab 2');" selected="true">SubTab 2</a>
+			<div dojoType="dijit.layout.ContentPane"  title="SubTab 3">
+				<h1>I am tab 3, inlined.</h1>
+			</div>
+			<div dojoType="dijit.layout.ContentPane"  title="SubTab 4">
+				<h1>I am tab 4, inlined.</h1>
+			</div>
+		</div>
+
+		<a dojoType="dijit.layout.LinkPane" closable="true" href="tab3.html" refreshOnShow="true" style="padding: 0">Sub TabContainer from href</a>
+
+		<a dojoType="dijit.layout.LinkPane" closable="true" href="tab4.html">SplitContainer from href</a>
+
+		<div dojoType="dijit.layout.ContentPane" closable="true" title="Embedded layout widgets">
+			<p>
+				The tab has some text, plus two embedded layout widgets, which should
+				appear correctly even though the tab is initially hidden.
+			</p>
+			<p>
+				Here's a BorderContainer:
+			</p>
+			<div dojoType="dijit.layout.BorderContainer" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" region="left" style="width:100px" splitter="true">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				And a TabContainer:
+			</p>
+			<div dojoType="dijit.layout.TabContainer" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" title="Tab 1">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Tab 2">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				Text after the widgets.
+			</p>
+		</div>
+	</div>
+	<br>
+	<p>
+		This tab container has its tabs at the bottom, and the tab strip disabled
+	</p>
+
+	<div dojoType="dijit.layout.TabContainer" tabPosition="bottom"
+				persist="true" tabStrip="false" style="width: 400px; height: 20em;">
+
+		<div dojoType="dijit.layout.ContentPane" href="tab1.html" title="Tab 1"></div>
+
+		<div dojoType="dijit.layout.ContentPane" href="tab2.html" refreshOnShow="true" title="Tab 2" selected="true"></div>
+
+		<div dojoType="dijit.layout.ContentPane" closable="true" title="Tab 3">
+			<h1>I am tab 3</h1>
+			<p>And I was already part of the page! That's cool, no?</p>
+			<p id="foo">tooltip on this paragraph</p>
+			<div dojoType="dijit.Tooltip" connectId="foo">I'm a tooltip!</div>
+			<button dojoType="dijit.form.Button">I'm a button </button>
+			<br>
+			<button dojoType="dijit.form.Button">So am I!</button>
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+			porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+			Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+			Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+			risus.
+			</p>
+			<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+			nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+			massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+			pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+			quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+			felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+			quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+			rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+			semper velit ante id metus. Praesent massa dolor, porttitor sed,
+			pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+			tortor pharetra congue. Suspendisse pulvinar.
+			</p>
+		</div>
+
+		<div dojoType="dijit.layout.TabContainer" closable="true" title="Inlined Sub TabContainer" nested="true">
+			<a dojoType="dijit.layout.LinkPane"  href="tab1.html" onLoad="console.log('load of SubTab 1');">SubTab 1</a>
+			<a dojoType="dijit.layout.LinkPane"  href="tab2.html"  onLoad="console.log('load of SubTab 2');" selected="true">SubTab 2</a>
+			<div dojoType="dijit.layout.ContentPane"  title="SubTab 3">
+				<h1>I am tab 3, inlined.</h1>
+			</div>
+			<div dojoType="dijit.layout.ContentPane"  title="SubTab 4">
+				<h1>I am tab 4, inlined.</h1>
+			</div>
+		</div>
+
+		<a dojoType="dijit.layout.LinkPane" closable="true" href="tab3.html" refreshOnShow="true" style="padding: 0">Sub TabContainer from href</a>
+
+		<a dojoType="dijit.layout.LinkPane" closable="true" href="tab4.html">SplitContainer from href</a>
+
+		<div dojoType="dijit.layout.ContentPane" closable="true" title="Embedded layout widgets">
+			<p>
+				The tab has some text, plus two embedded layout widgets, which should
+				appear correctly even though the tab is initially hidden.
+			</p>
+			<p>
+				Here's a BorderContainer:
+			</p>
+			<div dojoType="dijit.layout.BorderContainer" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" region="left" style="width:100px" splitter="true">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				And a TabContainer:
+			</p>
+			<div dojoType="dijit.layout.TabContainer" style="height:200px; width:300px">
+				<div dojoType="dijit.layout.ContentPane" title="Tab 1">
+					1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Tab 2">
+					2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+					Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+					vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+					augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+					metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+					ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+					euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+					risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+					porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+					faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+					consequat quis, varius interdum, nulla. Donec neque tortor,
+					sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+					ut eros sit amet ante pharetra interdum.
+				</div>
+			</div>
+			<p>
+				Text after the widgets.
+			</p>
+		</div>
+	</div>
+
+	<p>
+		The next example is with closable tabs.
+		Tab 1 and Tab 3 can be closed; Tab 3 has a confirm box.
+	</p>
+
+	<div id="ttabs" dojoType="dijit.layout.TabContainer" tabPosition="top" style="width: 100%; height: 10em;"
+		onfocus="console.log('user focus handler')"
+		onblur="console.log('user blur handler')"
+	>
+		<div id="ttab1" dojoType="dijit.layout.ContentPane" href="tab1.html" title="First" closable="true"></div>
+		<div id="ttab2" dojoType="dijit.layout.ContentPane" href="tab2.html" refreshOnShow="true" title="Second"></div>
+		<div dojoType="dijit.layout.ContentPane" title="Third" onClose="testClose" closable="true">
+			<h1>I am tab 3</h1>
+			<p>And I was already part of the page! That's cool, no?</p>
+			<p>If you try to close me there should be a confirm dialog.</p>
+		</div>
+	</div>
+
+	<p>Tabs with titles on the bottom:</p>
+
+	<div id="btabs" dojoType="dijit.layout.TabContainer" tabPosition="bottom" style="width: 100%; height: 10em;">
+		<div id="btab1" dojoType="dijit.layout.ContentPane" href="tab1.html" title="Tab 1" closable="true"></div>
+		<div id="btab2" dojoType="dijit.layout.ContentPane" href="tab2.html" refreshOnShow="true" onLoad="console.debug('Tab2 onLoad');" title="Tab 2"></div>
+	</div>
+
+	<p>Tabs with titles on the left and tabStrip="false":</p>
+
+	<div id="ltabs" dojoType="dijit.layout.TabContainer" style="width:500px;height:100px" tabStrip="false" tabPosition="left-h">
+		<div id="LittleRed1" dojoType="dijit.layout.ContentPane" title="Little Red Cap">
+			Once upon a time there was a dear little girl who was loved by
+			every one who looked at her, but most of all by her grandmother,
+			and there was nothing that she would not have given to the child.
+		</div>
+		<div id="HanselGretel1" dojoType="dijit.layout.ContentPane"
+		     title="Hansel and Gretel" closable="true" selected="true">
+			Hard by a great forest dwelt a poor wood-cutter with his wife
+			and his two children. The boy was called Hansel and the girl Gretel.
+			He had little to bite and to break, and once when great dearth fell
+			on the land, he could no longer procure even daily bread.
+		</div>
+		<div id="GreenTwigs1" dojoType="dijit.layout.ContentPane"
+		 title="The Three Green Twigs">
+			There was once upon a time a hermit who lived in a forest at the foot
+			of a mountain, and passed his time in prayer and good works,
+			and every evening he carried, to the glory of God, two pails of water
+			up the mountain.
+		</div>
+	</div>
+
+	<p>Tabs with titles on the left and tabStrip=true:</p>
+
+	<div id="ltabsStrip" dojoType="dijit.layout.TabContainer" style="width:500px;height:100px" tabStrip="true" tabPosition="left-h">
+		<div dojoType="dijit.layout.ContentPane" title="Little Red Cap">
+			Once upon a time there was a dear little girl who was loved by
+			every one who looked at her, but most of all by her grandmother,
+			and there was nothing that she would not have given to the child.
+		</div>
+		<div dojoType="dijit.layout.ContentPane"
+		     title="Hansel and Gretel" closable="true" selected="true">
+			Hard by a great forest dwelt a poor wood-cutter with his wife
+			and his two children. The boy was called Hansel and the girl Gretel.
+			He had little to bite and to break, and once when great dearth fell
+			on the land, he could no longer procure even daily bread.
+		</div>
+		<div dojoType="dijit.layout.ContentPane"
+		 title="The Three Green Twigs">
+			There was once upon a time a hermit who lived in a forest at the foot
+			of a mountain, and passed his time in prayer and good works,
+			and every evening he carried, to the glory of God, two pails of water
+			up the mountain.
+		</div>
+	</div>
+
+	<p>Tabs with titles on the right and tabStrip=true:</p>
+
+	<div id="rtabsStrip" dojoType="dijit.layout.TabContainer" tabStrip="true" style="width:500px;height:100px" tabPosition="right-h">
+		<div id="LittleRed2" dojoType="dijit.layout.ContentPane" title="Little Red Cap">
+			Once upon a time there was a dear little girl who was loved by
+			every one who looked at her, but most of all by her grandmother,
+			and there was nothing that she would not have given to the child.
+		</div>
+		<div id="HanselGretel2" dojoType="dijit.layout.ContentPane"
+		     title="Hansel and Gretel" closable="true" selected="true">
+			Hard by a great forest dwelt a poor wood-cutter with his wife
+			and his two children. The boy was called Hansel and the girl Gretel.
+			He had little to bite and to break, and once when great dearth fell
+			on the land, he could no longer procure even daily bread.
+		</div>
+		<div id="GreenTwigs2" dojoType="dijit.layout.ContentPane"
+		 title="The Three Green Twigs">
+			There was once upon a time a hermit who lived in a forest at the foot
+			of a mountain, and passed his time in prayer and good works,
+			and every evening he carried, to the glory of God, two pails of water
+			up the mountain.
+		</div>
+	</div>
+
+	<p>Tabs with titles on the right and tabStrip=false:</p>
+
+	<div id="rtabs" dojoType="dijit.layout.TabContainer" tabStrip="false" style="width:500px;height:100px" tabPosition="right-h">
+		<div dojoType="dijit.layout.ContentPane" title="Little Red Cap">
+			Once upon a time there was a dear little girl who was loved by
+			every one who looked at her, but most of all by her grandmother,
+			and there was nothing that she would not have given to the child.
+		</div>
+		<div dojoType="dijit.layout.ContentPane"
+		     title="Hansel and Gretel" closable="true" selected="true">
+			Hard by a great forest dwelt a poor wood-cutter with his wife
+			and his two children. The boy was called Hansel and the girl Gretel.
+			He had little to bite and to break, and once when great dearth fell
+			on the land, he could no longer procure even daily bread.
+		</div>
+		<div dojoType="dijit.layout.ContentPane"
+		 title="The Three Green Twigs">
+			There was once upon a time a hermit who lived in a forest at the foot
+			of a mountain, and passed his time in prayer and good works,
+			and every evening he carried, to the glory of God, two pails of water
+			up the mountain.
+		</div>
+	</div>
+
+	<h3>Typical rendering time</h3>
+	<table border=1>
+	  <tr><th>IE</th><th>Firefox (mac)</th></tr>
+	  <tr><td>1719</td><td>922</td></tr>
+	</table>
+	<h3>Rendering time</h3>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_TabContainerTitlePane.html b/dijit/tests/layout/test_TabContainerTitlePane.html
new file mode 100644
index 0000000..175cb7f
--- /dev/null
+++ b/dijit/tests/layout/test_TabContainerTitlePane.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>TabContainer Nested TitlePane Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+
+		body {
+			font-family : sans-serif;
+			margin:20px;
+		}
+
+		/* add padding to each contentpane inside the tab container, and scrollbar if necessary */
+		.dojoTabPane {
+			padding : 10px 10px 10px 10px;
+			overflow: auto;
+		}
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.TitlePane");
+
+		startTime = new Date();
+		dojo.addOnLoad(function(){
+			var elapsed = new Date().getTime() - startTime;
+			var p = document.createElement("p");
+			p.appendChild(document.createTextNode("Widgets loaded in " + elapsed + "ms"));
+			document.body.appendChild(p);
+			// dojo.parser.parse(dojo.body());
+		});
+
+	</script>
+
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit layout.TabContainer nested TitlePane tests</h1>
+
+	<div id="mainTabContainer" dojoType="dijit.layout.TabContainer" style="width: 100%; height: 20em;">
+
+		<div dojoType="dijit.layout.ContentPane" title="Tab 1">
+			<h1>I am tab 1</h1>
+			<div dojoType="dijit.TitlePane" title="Title pane" width="300">
+				<p>This is a title pane, containing another tab container ...</p>
+				<p>
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque iaculis, nulla id semper faucibus, pede tellus nonummy magna, vitae adipiscing orci arcu ut augue. Nunc condimentum, magna a vestibulum convallis, libero purus pulvinar orci, sed vestibulum urna sem ut pede. More Ipsum...
+				</p>
+				<div id="subTabContainer" dojoType="dijit.layout.TabContainer" style="width: 100%; height: 20em;">
+					<div id="tab3" dojoType="dijit.layout.ContentPane" href="tab1.html" title="Tab 3"></div>
+					<div id="tab4" dojoType="dijit.layout.ContentPane" href="tab2.html" refreshOnShow="true" title="Tab 4" selected="true"></div>
+				</div>
+			</div>
+		</div>
+		<div id="tab2" dojoType="dijit.layout.ContentPane" href="tab2.html" title="Tab 2"></div>
+
+	</div>
+
+
+	<h3>Typical rendering time</h3>
+	<table border=1>
+	  <tr><th>IE</th><th>Firefox (mac)</th></tr>
+	  <tr><td>1719</td><td>922</td></tr>
+	</table>
+	<h3>Rendering time</h3>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_TabContainer_noLayout.html b/dijit/tests/layout/test_TabContainer_noLayout.html
new file mode 100644
index 0000000..0488241
--- /dev/null
+++ b/dijit/tests/layout/test_TabContainer_noLayout.html
@@ -0,0 +1,172 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>TabContainer doLayout=false Demo</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+
+		body {
+			font-family : sans-serif;
+			margin:20px;
+		}
+
+		/* add padding to each contentpane inside the tab container, and scrollbar if necessary */
+		.dojoTabPane {
+			padding : 10px 10px 10px 10px;
+			overflow: auto;
+		}
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.Tooltip");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.layout.LinkPane");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		function testClose(pane,tab){
+		  return confirm("Please confirm that you want tab "+tab.title+" closed");
+		}
+
+		var tab = 6;
+
+        function addTab(){
+			cp = new dijit.layout.ContentPane({title: 'Tab' + tab, closable: true});
+			cp.domNode.innerHTML = "Contents of Tab " + tab++;
+			dijit.byId("mainTabContainer").addChild(cp);
+        }
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit layout.TabContainer doLayout=false tests</h1>
+
+	<p>
+		This tests tabs in doLayout=false mode, in which case the tab container's height ==
+		the height of the currently selected tab.
+	</p>
+	<p>
+		With doLayout=false mode tabs only (the default) tabPosition=top is supported.
+	</p>
+
+	<button onclick="addTab();">add tab</button>
+	<button onclick="dijit.byId('mainTabContainer').destroyRecursive();">destroy tab container</button>
+
+	<div id="mainTabContainer" dojoType="dijit.layout.TabContainer" doLayout="false" style="width: 700px;">
+
+		<div id="tab1" dojoType="dijit.layout.ContentPane" href="tab1.html" title="Tab 1"></div>
+
+		<div id="tab2" dojoType="dijit.layout.ContentPane" href="tab2.html" refreshOnShow="true" title="Tab 2" selected="true"></div>
+
+		<div dojoType="dijit.layout.ContentPane" title="Tab 3">
+			<h1>I am tab 3</h1>
+			<p>And I was already part of the page! That's cool, no?</p>
+			<span id="foo">tooltip on this span</span>
+			<div dojoType="dijit.Tooltip" connectId="foo">I'm a tooltip!</div>
+			<button dojoType="dijit.form.Button">I'm a button </button>
+			<br>
+			<button dojoType="dijit.form.Button">So am I!</button>
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+			porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+			Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+			Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+			risus.
+			</p>
+			<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+			nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+			massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+			pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+			quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+			felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+			quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+			rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+			semper velit ante id metus. Praesent massa dolor, porttitor sed,
+			pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+			tortor pharetra congue. Suspendisse pulvinar.
+			</p>
+		</div>
+
+		<div dojoType="dijit.layout.TabContainer" title="Inlined Sub TabContainer" doLayout="false" nested="true">
+			<a dojoType="dijit.layout.LinkPane" href="tab1.html">SubTab 1</a>
+			<a dojoType="dijit.layout.LinkPane" href="tab2.html" selected="true">SubTab 2</a>
+		</div>
+
+		<a dojoType="dijit.layout.LinkPane" href="tab3_noLayout.html" doLayout="false">Sub TabContainer from href</a>
+	</div>
+
+	<p>
+		Some text here.  This should appear directly below the TabContainer,
+		and the position will change based on the current height of the TabContainer.
+	</p>
+
+	<p>No width specified (defaults to 100%):</p>
+	<div id="anotherTabContainer" dojoType="dijit.layout.TabContainer" doLayout="false">
+
+		<div id="atab1" dojoType="dijit.layout.ContentPane" href="tab1.html" title="Tab 1"></div>
+
+		<div id="atab2" dojoType="dijit.layout.ContentPane" href="tab2.html" refreshOnShow="true" title="Tab 2" selected="true"></div>
+
+		<div dojoType="dijit.layout.ContentPane" title="Tab 3">
+			<h1>I am tab 3</h1>
+			<p>And I was already part of the page! That's cool, no?</p>
+			<span id="foo">tooltip on this span</span>
+			<div dojoType="dijit.Tooltip" connectId="foo">I'm a tooltip!</div>
+			<button dojoType="dijit.form.Button">I'm a button </button>
+			<br>
+			<button dojoType="dijit.form.Button">So am I!</button>
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+			porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+			Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+			Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+			risus.
+			</p>
+			<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+			nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+			massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+			pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+			quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+			felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+			quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+			rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+			semper velit ante id metus. Praesent massa dolor, porttitor sed,
+			pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+			tortor pharetra congue. Suspendisse pulvinar.
+			</p>
+		</div>
+
+		<div dojoType="dijit.layout.TabContainer" title="Inlined Sub TabContainer" nested="true" doLayout="false">
+			<a dojoType="dijit.layout.LinkPane" href="tab1.html">SubTab 1</a>
+			<a dojoType="dijit.layout.LinkPane" href="tab2.html" selected="true">SubTab 2</a>
+		</div>
+
+		<a dojoType="dijit.layout.LinkPane" href="tab3_noLayout.html" doLayout="false">Sub TabContainer from href</a>
+	</div>
+
+	<p>
+		Some text here.  This should appear directly below the TabContainer,
+		and the position will change based on the current height of the TabContainer.
+	</p>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_TabContainer_prog.html b/dijit/tests/layout/test_TabContainer_prog.html
new file mode 100644
index 0000000..da754ba
--- /dev/null
+++ b/dijit/tests/layout/test_TabContainer_prog.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dijit.layout.TabContainer Programmatic Test</title>
+
+	<!-- only needed for test files: -->
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.TabContainer");
+        dojo.require("dijit.layout.ContentPane");
+
+		var tab = 1;
+
+		var tc, cp;
+		function create(initialTabs){
+			tc = new dijit.layout.TabContainer({style:'height:200px;width:500px;'}, dojo.byId('main'));
+
+			for(var i=0; i<initialTabs; i++){
+				cp = new dijit.layout.ContentPane({title: 'Tab ' + tab});
+				cp.domNode.innerHTML = "Contents of Tab " + tab++;
+				tc.addChild(cp);
+			}
+
+			tc.startup();
+        }
+
+        function addTab(){
+			cp = new dijit.layout.ContentPane({title: 'Tab' + tab});
+			cp.domNode.innerHTML = "Contents of Tab " + tab++;
+			tc.addChild(cp);
+        }
+	</script>
+</head>
+<body class="claro">
+	<h2 class="testTitle">dijit.layout.TabContainer programmatic test</h2>
+	<div id='main'>
+	</div>
+
+	<button onclick="create(0)">create empty tab container</button>
+	<button onclick="create(2)">create tab container w/2 tabs</button>
+
+	<button onclick="tc.selectChild(tc.getChildren()[1]);">select second tab</button>
+	<button onclick="tc.removeChild(tc.getChildren()[1]);">remove second tab</button>
+	<button onclick="addTab();">add tab</button>
+</body>
+</html>
diff --git a/dijit/tests/layout/test_TabContainer_remote.html b/dijit/tests/layout/test_TabContainer_remote.html
new file mode 100644
index 0000000..c09f11f
--- /dev/null
+++ b/dijit/tests/layout/test_TabContainer_remote.html
@@ -0,0 +1,116 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>TabContainer Demo</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+
+		body {
+			font-family : sans-serif;
+			margin:20px;
+		}
+
+		/* add padding to each contentpane inside the tab container, and scrollbar if necessary */
+		.dojoTabPane {
+			padding : 10px 10px 10px 10px;
+			overflow: auto;
+		}
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.Tooltip");
+		dojo.require("dijit.layout.LinkPane");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		var tabCounter;
+		function testClose(pane, tab){
+			// remove html from title
+			var title = dojo.trim(tab.title.replace(/<\/?[a-z][a-z0-9]*[^>]*>/ig, ""));
+			return confirm("Please confirm that you want tab "+title+" closed");
+		}
+
+		function randomMessageId(){
+			return Math.floor(Math.random() * 3) + 3;
+		}
+
+		function createTab(){
+			if(!tabCounter){ tabCounter = 3; }
+
+			var title = '<img src="../images/plus.gif" style="background-color:#95B7D3;"/> Tab ' +(++tabCounter);
+			var refreshOnShow = !!(tabCounter % 2);
+
+			var newTab = new dijit.layout.ContentPane({
+				title: title + (refreshOnShow ? ' <i>refreshOnShow</i>': ''),
+				closable:true,
+				refreshOnShow: refreshOnShow,
+				href: 'getResponse.php?delay=1000&messId='+randomMessageId()
+					+"&message="+encodeURI("<h1>Programmatically created Tab "+tabCounter+"</h1>")
+			}, dojo.doc.createElement('div'));
+
+			dijit.byId('ttabs').addChild(newTab);
+
+			newTab.startup(); // find parent TabContainer and subscribe to selectChild event
+		}
+
+		startTime = new Date();
+		dojo.addOnLoad(function(){
+			var elapsed = new Date().getTime() - startTime;
+			var p = document.createElement("p");
+			p.appendChild(document.createTextNode("Widgets loaded in " + elapsed + "ms"));
+			document.body.appendChild(p);
+		});
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit layout.TabContainer (delayed) remote tests</h1>
+
+	<p>These tabs are made up of external content. Loading is delayed to make it easier to see if refreshOnShow and preload = 'false' is working.<br/>
+	The tabs also tests to insert html in the Tab title
+	</p>
+
+	<div dojoType='dijit.form.Button' onClick='createTab()'>Create a Tab</div>
+	<div id="ttabs" dojoType="dijit.layout.TabContainer" tabPosition="top" style="width: 100%; height: 20em;">
+		<a id="ttab1" dojoType="dijit.layout.LinkPane"
+			href="getResponse.php?messId=3&delay=1000"
+			closable="true"
+		><img src='../images/copy.gif'/> Tab1</a>
+		<a id="ttab2" dojoType="dijit.layout.LinkPane"
+			href="getResponse.php?messId=4&delay=1000"
+			refreshOnShow="true" title="Tab 2 "
+			selected='true'
+			closable='true'
+		><i>refreshOnShow</i>
+			<img src='../images/cut.gif'/>
+		</a>
+		<a dojoType="dijit.layout.LinkPane"
+			href="getResponse.php?messId=5&delay=1000"
+			onClose="testClose"
+			closable="true"
+		>
+			<b>Tab 3</b>
+			<img src='../images/paste.gif'/>
+		</a>
+	</div>
+
+	<h3>Rendering time</h3>
+
+</body>
+</html>
diff --git a/dijit/tests/layout/test_refreshOnShow.html b/dijit/tests/layout/test_refreshOnShow.html
new file mode 100644
index 0000000..844cedb
--- /dev/null
+++ b/dijit/tests/layout/test_refreshOnShow.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>ContentPane Test</title>
+
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+
+		body {
+			margin: 1em;
+			padding: 1em;
+		}
+
+		.box {
+		  position: relative;
+			background-color: white;
+			border: 2px solid black;
+			padding: 8px;
+			margin: 4px;
+		}
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.AccordionContainer");
+	</script>
+
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit layout.ContentPane tests</h1>
+
+	<!-- works: -->
+	<div dojoType="dijit.layout.TabContainer" style="height:200px;">
+		<div dojoType="dijit.layout.ContentPane" href="_lorem.html" title="one" refreshOnShow="false"></div>
+		<div dojoType="dijit.layout.ContentPane" href="_lorem.html" title="two" refreshOnShow="false"></div>
+		<div dojoType="dijit.layout.ContentPane" href="_lorem.html" title="three" refreshOnShow="false"></div>
+	</div>
+
+	<!-- does not work yet: -->
+    <div dojoType="dijit.layout.AccordionContainer" style="height:200px; width:400px;">
+		<div dojoType="dijit.layout.ContentPane" title="one" refreshOnShow="false" href="_lorem.html"></div>
+		<div dojoType="dijit.layout.ContentPane" title="two" refreshOnShow="true" href="_lorem.html"></div>
+		<div dojoType="dijit.layout.ContentPane" title="three" refreshOnShow="false" href="_lorem.html"></div>
+	</div>
+
+
+
+</body>
+</html>
diff --git a/dijit/tests/loose.html b/dijit/tests/loose.html
new file mode 100644
index 0000000..5bf5923
--- /dev/null
+++ b/dijit/tests/loose.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0 Transitional//EN'
+		'http://www.w3.org/TR/html4/loose.dtd'>
+<html>
+<head>
+<script src="_loadTest.js"></script>
+</head>
+</html>
diff --git a/dijit/tests/module.js b/dijit/tests/module.js
new file mode 100644
index 0000000..f370ce5
--- /dev/null
+++ b/dijit/tests/module.js
@@ -0,0 +1,16 @@
+dojo.provide("dijit.tests.module");
+
+try{
+	dojo.require("dijit.tests._base.module");
+	dojo.require("dijit.tests.infrastructure-module");
+
+	dojo.require("dijit.tests.general-module");
+	dojo.require("dijit.tests.tree.module");
+	dojo.require("dijit.tests.editor.module");
+	dojo.require("dijit.tests.form.module");
+	dojo.require("dijit.tests.layout.module");
+}catch(e){
+	doh.debug(e);
+}
+
+
diff --git a/dijit/tests/quirks.html b/dijit/tests/quirks.html
new file mode 100644
index 0000000..21ecd83
--- /dev/null
+++ b/dijit/tests/quirks.html
@@ -0,0 +1,5 @@
+<html>
+<head>
+<script src="_loadTest.js"></script>
+</head>
+</html>
diff --git a/dijit/tests/robot/Calendar_a11y.html b/dijit/tests/robot/Calendar_a11y.html
new file mode 100644
index 0000000..d26c6de
--- /dev/null
+++ b/dijit/tests/robot/Calendar_a11y.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Calendar A11Y Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+			dojo.require("dojo.date");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Calendar.html');
+
+				// refs to Calendar widget
+				var cal1;
+
+				// log of calls to onChange handler
+				var changes = [];
+
+				doh.register("dijit.Calendar keyboard tests",[
+					{
+						name: "arrow navigation",
+						timeout: 10000,
+						setUp: function(){
+							// refs to Calendar widget
+					    	cal1 = dijit.byId('calendar1');
+							cal1.set("value", new Date(2009, 8, 16));
+
+					    	// setup onChange handler to monitor onChange calls on cal1
+							dojo.connect(cal1, 'onChange', function(val){
+								console.log('onchange w/value: ', val);
+								changes.push(val);
+							});
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							doh.robot.sequence(function(){
+								// monitor onchange events
+								changes = [];
+								cal1.domNode.focus();
+							}, 500);
+
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.LEFT_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.UP_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.UP_ARROW, 500, {});
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								var value = cal1.get('value');
+								doh.is(0, dojo.date.compare(new Date(2009, 8, 10), value), 'actual value is ' + value);
+								doh.is(6, changes.length, 'six onchange events');
+								doh.is(0, dojo.date.compare(new Date(2009, 8, 17), changes[0]),
+										'value reported by onchange: ' + changes[0] +
+										', should be ' + new Date(2009, 8, 17));
+							})), 1000);
+							return d;
+						}
+					},
+					{
+						name: "month navigation",
+						timeout: 5000,
+						setUp: function(){
+							// refs to Calendar widget
+					    	cal1 = dijit.byId('calendar1');
+							cal1.set("value", new Date(2008, 0, 31));
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							doh.robot.sequence(function(){
+								// monitor onchange events
+								cal1.domNode.focus();
+							}, 500);
+
+							doh.robot.keyPress(dojo.keys.PAGE_DOWN, 500, {});
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								var value = cal1.get('value');
+								doh.is(0, dojo.date.compare(new Date(2008, 1, 29), value), 'actual value is ' + value);
+							})), 1000);
+							return d;
+						}
+					},
+					{
+						name: "month+year navigation",
+						timeout: 5000,
+						setUp: function(){
+							// refs to Calendar widget
+					    	cal1 = dijit.byId('calendar1');
+							cal1.set("value", new Date(2008, 1, 15));
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							doh.robot.sequence(function(){
+								// monitor onchange events
+								cal1.domNode.focus();
+							}, 500);
+
+							doh.robot.keyPress(dojo.keys.END, 500, {});
+							doh.robot.keyPress(dojo.keys.PAGE_DOWN, 500, {ctrl:true});
+							doh.robot.keyPress(dojo.keys.PAGE_UP, 500, {ctrl:true});
+							doh.robot.keyPress(dojo.keys.PAGE_UP, 500, {ctrl:true});
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								var value = cal1.get('value');
+								doh.is(0, dojo.date.compare(new Date(2007, 1, 28), value), 'actual value is ' + value);
+							})), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/ColorPalette.html b/dijit/tests/robot/ColorPalette.html
new file mode 100644
index 0000000..7371980
--- /dev/null
+++ b/dijit/tests/robot/ColorPalette.html
@@ -0,0 +1,228 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot ColorPalette Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_ColorPalette.html');
+
+				var big, small, prog;
+
+				// log of calls to onChange handler
+				var changes = [];
+
+				doh.register("dijit.ColorPalette tests", [
+					{
+						name: "initial conditions",
+						setUp: function(){
+
+							// refs to ColorPalette widgets
+					    	big = dijit.byId("big");
+					    	small = dijit.byId("small");
+					    	prog = dijit.byId("prog");
+
+					    	// setup onChange handler to monitor onChange calls
+							dojo.connect(big, 'onChange', function(val){
+								console.log('onchange w/value: ', val);
+								changes.push(val);
+							});
+						},
+						runTest: function(){
+							doh.f(big.get('value'), "no value for big");
+							doh.f(small.get('value'), "no value for small");
+							doh.f(prog.get('value'), "no value for prog");
+						}
+					},
+					
+					// TODO: when attr() is implemented as a setter, add tests like big.set("value", "#ffc0cb")
+
+					{
+						name: "focus",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							big.focus();
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(0, changes.length, "no onchange events yet");
+								
+								// test that focus is on top left cell
+								var focus = dojo.global.dijit._curFocus;
+								doh.t(focus, "something is focused");
+								var imgNode = focus.getElementsByTagName("img")[0]
+								doh.t(imgNode, "found image node");
+                                //
+                                var dye = big._getDye(focus);                                
+								doh.is("#ffffff", dye.getValue(), "focused on white");
+							}), 500);
+							
+							return d;
+						}
+					},
+
+					{
+						name: "arrow navigation",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Move around some
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.LEFT_ARROW, 500, {});
+							
+							// Focus should follow the current position for the benefit of screen readers.
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								var focus = dojo.global.dijit._curFocus;
+								doh.t(focus, "something is focused");
+								
+								var imgNode = focus.getElementsByTagName("img")[0]
+								doh.t(imgNode, "found image node");
+                                //
+                                var dye = big._getDye(focus);
+								doh.is("#ffc0cb", dye.getValue(), "focused on right color");
+							})), 1000);
+							
+							// Select the current value
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is("#ffc0cb", big.get("value"), "selected value");
+								
+								doh.is(1, changes.length, 'one onchange event');
+								doh.is("#ffc0cb", changes[0], "correct value");
+								
+								big.set('value', null);
+								doh.is(big.get('value'), null, "value has been cleared");
+							})), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "tab stops",
+						timeout: 10000,
+						runTest: function(){
+							// After the navigation above, make sure that there's (still) exactly one
+							// tab stop associated w/the color picker
+							var d = new doh.Deferred();
+
+							dojo.byId("beforeBig").focus();
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("pink", dojo.global.dijit._curFocus.title, "tab into colorpalette, focus goes to pink (last focused cell)")
+							}), 1000);
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("afterBig", dojo.global.dijit._curFocus.id, "another tab, went to input after ColorPalette")
+							}), 1000);
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("pink", dojo.global.dijit._curFocus.title, "shift-tab back into colorpalette")
+							}), 1000);
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("beforeBig", dojo.global.dijit._curFocus.id, "another shift-tab, to input before ColorPalette")
+							}), 1000);
+
+							return d;
+						}
+					},
+					{
+						name: "small palette (keyboard)",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// go to small colorpalette
+							dojo.byId("beforeSmall").focus();
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							// select a value
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var value = small.get('value');
+								doh.is("#ffff00", value);
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "small palette (mouse)",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Testing nls too...
+							var red = dojo.query("[title=rojo]", small.domNode);
+							doh.is(1, red.length, "found rojo (red)");
+
+							doh.robot.mouseMoveAt(red[0], 500);
+							doh.robot.mouseClick({left: true}, 500);
+							if(dojo.isMoz){
+								// workaround robot bug where first mouse click doesn't happen occasionally :-(
+								doh.robot.mouseClick({left: true}, 500);
+							}
+							
+								var green = dojo.query("[title=verde]", small.domNode);
+							doh.is(1, green.length, "found verde (green)");
+
+							doh.robot.mouseMoveAt(green[0], 500);
+							doh.robot.mouseClick({left: true}, 500);
+							if(dojo.isMoz){
+								// workaround robot bug where first mouse click doesn't happen occasionally :-(
+								doh.robot.mouseClick({left: true}, 500);
+							}
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// test that value set
+								var value = small.get('value');
+								doh.is("#008000", value, "value");
+								
+								// test that focus also got set
+								var focus = dojo.global.dijit._curFocus;
+								doh.t(focus, "something is focused");
+								var imgNode = focus.getElementsByTagName("img")[0]
+								doh.t(imgNode, "found image node");
+								var dye = small._getDye(focus);
+								doh.is("#008000", dye.getValue(), "focused");
+								
+								//test that selected style was removed from previously selected cell and added to new selection
+								doh.f(dojo.hasClass(red[0], "dijitPaletteCellSelected"),
+								"Red swatch should not have selected class, actual class is: " + red[0].className);
+								doh.t(dojo.hasClass(green[0], "dijitPaletteCellSelected"), "Green swatch should have selected class, actual class is: " + green[0].className);
+							}), 1000);
+							
+							
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/Dialog_a11y.html b/dijit/tests/robot/Dialog_a11y.html
new file mode 100644
index 0000000..d7066ff
--- /dev/null
+++ b/dijit/tests/robot/Dialog_a11y.html
@@ -0,0 +1,501 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Dialog A11Y Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			var dialogIds = [
+				{ dlg: "dialog1", firstFocus: "name" },
+				{ dlg: "tabDialog", firstFocus: "tc_tablist_cp1" },
+				{ dlg: "fifthDlg", firstFocus: "timeref" }, //timeref is in layout/getResponse.php
+				{ dlg: "dialog6", firstFocus: "dialog6", fileInput: "afile" },
+				{ dlg: "cantmove", firstFocus: "cantmove" },
+				{ dlg: "preventer", firstFocus: "preventerOK" }
+			];
+
+			// testing utilities
+			function dialogTests(){
+				var that = {};
+				var xtraPara = null;
+				var firstTabStop = null;
+				var gotFocus = false;
+				var lostFocus = false;
+				var focusConnect = null;
+				var blurConnect = null;
+
+				// Define a known location to place keyboard focus, and put it there.  Allows for a
+				// place for focus to return to when dialog is dismissed.
+				function addTabNavFocus(){
+					removeTabNavFocus();
+					xtraPara = dojo.doc.createElement("p");
+					dojo.attr(xtraPara, 'tabIndex', 0);
+					xtraPara.innerHTML = "Tab-focussable paragraph";
+					xtraPara.id="focusPara";
+					dojo.place(xtraPara, dojo.body(), "first");
+					xtraPara.focus();
+				};
+
+				function removeTabNavFocus(){
+					if(xtraPara && xtraPara.parentNode){
+						xtraPara.parentNode.removeChild(xtraPara);
+					}
+				};
+
+				that.ariaFocusSetup = function(/*dialog's and first focusable ids*/ ids){
+					addTabNavFocus();
+					gotFocus = lostFocus = false;
+					var dlog = dijit.byId(ids.dlg);
+					// need to show dialog in order to find the first tab stop.
+					if( !dojo.isMoz && ids.fileInput){
+						that.firstTabStop = ids.fileInput;
+					}else{
+						that.firstTabStop = ids.firstFocus;
+					}
+				};
+
+				that.ariaFocusTeardown = function(){
+					removeTabNavFocus();
+				};
+
+				that.ariaFocus = function(dlogId){
+					var d = new doh.Deferred();
+					var dlog = dijit.byId(dlogId.dlg);
+					var doShow = function(){
+						dlog.show();
+					};
+					var doHide = function(){
+						dlog.hide();
+					};
+					var doFocusTest = function(){
+						gotFocus = (dojo.global.dijit._curFocus.id == that.firstTabStop);
+					}
+					var doBlurTest = function(){
+						lostFocus = (dojo.global.dijit._curFocus.id != that.firstTabStop);
+					}
+					// <firstTabStop> set in that.ariaFocusSetup(), above.
+					doh.isNot(null, that.firstTabStop,  + "no first-focusable item for dialog: " + dlog.id);
+					doh.robot.sequence(doShow, 200);
+					doh.robot.sequence(doFocusTest, (dlogId.dlg == "fifthDlg" ? 4000 : 1000));  // wait for dialog to display
+					doh.robot.sequence(doHide, 1000);
+					doh.robot.sequence(doBlurTest, 1000);
+					var testShowHide = function(){
+						doh.t(gotFocus, "first focusable didn't get focus on open, for: " + dlog.id);
+						doh.t(lostFocus, "first focusable didn't lose focus on close, for: " + dlog.id);
+					};
+					doh.robot.sequence(d.getTestCallback(testShowHide), 1000);
+					return d;
+				};
+				return that;
+
+			}	// end dialogTests().
+
+			var dialogTest;
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Dialog.html');
+
+				doh.register("dijit.Dialog keyboard tests (cancel)",[
+					{
+						name: "open dialog",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Click the button.  We do this manually rather than calling Dialog.show()
+							// so we can later test that focus is restored (to the previous position)
+							// when the dialog is closed
+							doh.robot.sequence(function(){
+								dojo.byId("dialog1button").focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys.SPACE, 1500, {});
+							doh.robot.typeKeys("Bill", 1000, 2000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("dialog1"), "dialog 1 has been made visible");
+								doh.is("name", dojo.global.dijit._curFocus.id, "focus is on the first field");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "tab to the date field",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.typeKeys("Japan", 500, 2500);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("date", dojo.global.dijit._curFocus.id, "focus is on the date field");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "close date drop down",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("date", dojo.global.dijit._curFocus.id, "focus is still on the date field");
+								doh.t(isVisible("dialog1"), "dialog 1 wasn't closed");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "tabbing loops around",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("name", dojo.global.dijit._curFocus.id, "focus looped back to name field");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "reverse-tabbing loops around",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("ok", dojo.global.dijit._curFocus.id, "focus looped back to submit button");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "close via ESC",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("dialog1"), "dialog 1 was closed");
+								doh.is("dialog1button", dojo.global.dijit._curFocus.id, "focus returned to button");
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("dijit.Dialog keyboard tests (submit)",[
+					{
+						name: "submit some data",
+						timeout: 15000,
+						setUp: function(){
+							dijit.byId("dialog1").reset();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Setup handler to catch submitted data
+							var data;
+							dojo.connect(dijit.byId("dialog1"), "execute", function(vals){
+								data = vals;
+							});
+
+							// Open the dialog
+							doh.robot.sequence(function(){
+								dojo.byId("dialog1button").focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+
+							// Enter some info
+							doh.robot.typeKeys("Ted", 2000, 1500);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.typeKeys("America", 500, 3500);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							// Submit
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("dialog1"), "dialog 1 was closed on submit");
+								doh.t(data, "got submit data");
+								doh.is("Ted", data.name, "Name");
+								doh.is("America", data.loc, "Location");
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("dijit.Dialog keyboard tests (cancel via Cancel button)",[
+					{
+						name: "close Dialog via Cancel button",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Test which callbacks are called on cancel
+							var executed = false, canceled = false;
+							dojo.connect(dijit.byId("ABDlg1"), "execute", function(vals){
+								executed = true;
+							});
+							dojo.connect(dijit.byId("ABDlg1"), "onCancel", function(){
+								canceled = true;
+							});
+
+							// Open the dialog
+							doh.robot.sequence(function(){
+								dojo.byId("ABDlg1Btn").focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("ABDlg1"), "dialog opened");
+							}), 1000);
+
+							// Cancel
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("ABDlg1"), "dialog closed on cancel");
+								doh.t(canceled, "cancel callback was called");
+								doh.f(executed, "execute callback wasn't called");
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				var dialogTest = dialogTests();
+
+				// Loop to register tests for each dialog in the <dialogIds> array
+				// TODO:
+				//		The a11yAriaRole, a11yLabel, and a11yAriaExpanded tests probably only need
+				//		to be done for one dialog.
+				// TODO:
+				//		Even the focus tests, the only things we need to test that haven't been tested
+				//		already are:
+				//			1. focus for a dialog with no focusable elements
+				//			2. the file focus thing
+				for(i=0; i<dialogIds.length; i++){
+
+					// aria role and properties (aria-labelledby) tests.
+					doh.register("a11yAriaRole", {
+						name:dialogIds[i].dlg+"_role",
+						dialogId:dialogIds[i].dlg,
+						runTest:function(){
+							var dlog = dijit.byId(this.dialogId);
+							doh.is("dialog", dijit.getWaiRole(dlog.domNode), dlog.id + ": aria role (dialog)");
+						}
+					});
+					doh.register("a11yLabel", {
+						name:dialogIds[i].dlg+"_label",
+						dialogId:dialogIds[i].dlg,
+						runTest:function(){
+							var dlog = dijit.byId(this.dialogId);
+							var label = dijit.getWaiState(dlog.domNode, 'label');
+							if(!label){
+								var labelNodeId = dijit.getWaiState(dlog.domNode, 'labelledby');
+								if(labelNodeId){
+									var labelNode = dojo.byId(labelNodeId);
+								}
+								if(labelNode){
+									label = labelNode.innerHTML;
+								}
+							}
+							var hint = "aria-label or aria-labelledby (" + dlog.id + ")";
+							doh.isNot(null, label, "null " + hint);
+							doh.isNot("", label, "empty " + hint);
+						}
+					});
+
+	/*				// dijit.Dialog does not implment aria-expanded as of this writing -- should it?
+					doh.register("a11yAriaExpanded",{
+						name:dialogIds[i].dlg+"_aria-expanded",
+						dialogId:dialogIds[i].dlg,
+						runTest:function(){
+							var dlog = dijit.byId(this.dialogId);
+							var expanded = dijit.getWaiState(dlog.domNode, 'expanded');
+							if(expanded=="") expanded = "false";
+							doh.is("false", expanded, dlog.id + ": not shown");
+							dlog.show();
+							expanded = dijit.getWaiState(dlog.domNode, 'expanded');
+							dlog.hide();
+							doh.is("true", expanded, dlog.id + ": shown");
+						}
+					});
+	*/
+
+					// First focusable tests
+					doh.register("a11yFirstFocusable",{
+						name:"a11yFirstFocusable_"+dialogIds[i].dlg,
+						dialog:dialogIds[i],
+						timeout:20000,
+						setUp:function(){
+							dialogTest.ariaFocusSetup(this.dialog);
+						},
+						runTest:function(){
+							return dialogTest.ariaFocus(this.dialog);
+						},
+						tearDown:function(){
+							dialogTest.ariaFocusTeardown();
+						}
+					});
+				}	// end for() loop thru dialogIds array.
+
+				doh.register("dijit.Dialog keyboard tests (multiple dialogs)",[
+					{
+						name: "open first dialog",
+						timeout: 10000,
+						setUp: function(){
+							dijit.byId("dialog1").reset();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Click the button.  We do this manually rather than calling Dialog.show()
+							// so we can later test that focus is restored (to the previous position)
+							// when the dialog is closed
+							doh.robot.sequence(function(){
+								dojo.byId("dialog1button").focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+							doh.robot.typeKeys("lower", 1000,1000);
+
+							// Move focus to second field
+							doh.robot.keyPress(dojo.keys.TAB, 1000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("dialog1"), "dialog 1 is visible");
+
+								var dialog1Z = dojo.style(dijit.byId("dialog1").domNode, "zIndex"),
+									underlayZ = dojo.style(dojo.global.dijit._underlay.domNode, "zIndex");
+
+								doh.t(dialog1Z > underlayZ, "dialog1 (zIndex=" + dialog1Z +
+									") above underlay (zIndex=" + underlayZ + ")");
+
+								doh.is("loc", dojo.global.dijit._curFocus.id, "focus is on the second field");
+							}), 5000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "open second dialog",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.sequence(function(){
+								dijit.byId("tabDialog").show();
+							}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("tabDialog"), "tab dialog has been made visible");
+								doh.t(isVisible("dialog1"), "dialog 1 is still visible");
+
+								var tabDialogZ = dojo.style(dijit.byId("tabDialog").domNode, "zIndex"),
+									dialog1Z = dojo.style(dijit.byId("dialog1").domNode, "zIndex"),
+									underlayZ = dojo.style(dojo.global.dijit._underlay.domNode, "zIndex");
+
+								doh.t(tabDialogZ > underlayZ, "tabDialog (zIndex=" + tabDialogZ +
+									") above underlay (zIndex=" + underlayZ + ")");
+								doh.t(dialog1Z < underlayZ, "dialog1 (zIndex=" + dialog1Z +
+									") below underlay (zIndex=" + underlayZ + ")");
+							}), 5000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "cancel second dialog",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("tabDialog"), "tab dialog has been hidden");
+								doh.t(isVisible("dialog1"), "dialog 1 is still visible");
+
+								var dialog1Z = dojo.style(dijit.byId("dialog1").domNode, "zIndex"),
+									underlayZ = dojo.style(dojo.global.dijit._underlay.domNode, "zIndex");
+
+								doh.t(dialog1Z > underlayZ, "dialog1 (zIndex=" + dialog1Z +
+									") above underlay (zIndex=" + underlayZ + ")");
+
+								doh.is("loc", dojo.global.dijit._curFocus.id, "focus is on the second field");
+							}), 5000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "cancel first dialog",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("dialog1"), "dialog 1 was closed");
+								doh.is("dialog1button", dojo.global.dijit._curFocus.id, "focus returned to button");
+							}), 5000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/Dialog_mouse.html b/dijit/tests/robot/Dialog_mouse.html
new file mode 100644
index 0000000..889f7cd
--- /dev/null
+++ b/dijit/tests/robot/Dialog_mouse.html
@@ -0,0 +1,169 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Dialog A11Y Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Dialog.html');
+
+				doh.register("dijit.Dialog mouse tests (cancel)",[
+					{
+						name: "open dialog",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Open the dialog
+							doh.robot.mouseMoveAt("dialog1button", 1000);
+							doh.robot.mouseClick({left: true}, 1000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("dialog1"), "dialog 1 has been made visible");
+								doh.is("name", dojo.global.dijit._curFocus.id, "focus is on the first field");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "test that other controls on page can't be clicked",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMoveAt("plainInput", 500);
+							doh.robot.mouseClick({left: true}, 1000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible("dialog1"), "dialog 1 still visible");
+								doh.isNot("plainInput", dojo.global.dijit._curFocus && dojo.global.dijit._curFocus.id, "plain input wasn't focused");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "open date drop down",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMoveAt("date", 500);
+							doh.robot.mouseClick({left: true}, 1000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("date", dojo.global.dijit._curFocus.id, "focus is on the date field");
+								doh.is(1, dojo.query(".dijitCalendarContainer").length, "calendar is being shown");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "close date drop down",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMove(10, 10, 500);
+							doh.robot.mouseClick({left: true}, 1000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(0, dojo.query(".dijitCalendarContainer").length, "calendar has disappeared");
+								doh.t(isVisible("dialog1"), "dialog 1 wasn't closed");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "cancel dialog",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var button = dojo.query("#dialog1 .dijitDialogCloseIcon")[0];
+							doh.robot.mouseMoveAt(button, 500);
+							doh.robot.mouseClick({left: true}, 1000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("dialog1"), "dialog 1 was closed");
+								doh.is("dialog1button", dojo.global.dijit._curFocus.id, "focus returned to button");
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("dijit.Dialog mouse tests (submit)",[
+					{
+						name: "submit some data",
+						timeout: 15000,
+						setUp: function(){
+							dijit.byId("dialog1").reset();
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Setup handler to catch submitted data
+							var data;
+							dojo.connect(dijit.byId("dialog1"), "execute", function(vals){
+								data = vals;
+							});
+
+							// Open the dialog
+							doh.robot.mouseMoveAt("dialog1button", 500);
+							doh.robot.mouseClick({left: true}, 1000);
+
+							// Enter some info
+							doh.robot.mouseMoveAt("name", 2000);
+							doh.robot.mouseClick({left: true}, 1000);
+							doh.robot.typeKeys("Ted", 500);
+
+							doh.robot.mouseMoveAt("loc", 500);
+							doh.robot.mouseClick({left: true}, 1000);
+							doh.robot.typeKeys("America", 500);
+
+
+							// Submit
+							doh.robot.mouseMoveAt("ok", 500);
+							doh.robot.mouseClick({left: true}, 1000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("dialog1"), "dialog 1 was closed on submit");
+								doh.t(data, "got submit data");
+								doh.is("Ted", data.name, "Name");
+								doh.is("America", data.loc, "Location");
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/InlineEditBox.html b/dijit/tests/robot/InlineEditBox.html
new file mode 100644
index 0000000..22dd685
--- /dev/null
+++ b/dijit/tests/robot/InlineEditBox.html
@@ -0,0 +1,399 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot InlineEditBox Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.date.locale");
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_InlineEditBox.html');
+
+				function moveAndClick(node) {
+					doh.robot.mouseMoveAt(node, 500, 500);
+					doh.robot.mouseClick({left: true}, 500);
+				}
+				function cancel(deferred, widget){
+					moveAndClick(function(){
+						try{
+							var buttons = dojo.query(".cancelButton", widget.domNode.parentNode);
+							return buttons[buttons.length-1];
+						}catch(e){ deferred.errback(e); }
+					});
+					doh.robot.sequence(function(){}, 1000); // slow down to allow widget to exit edit mode
+				}
+				function save(deferred, widget){
+					moveAndClick(function(){
+						try{
+							var buttons = dojo.query(".saveButton", widget.domNode.parentNode);
+							return buttons[buttons.length-1];
+						}catch(e){ deferred.errback(e); }
+					});
+					doh.robot.sequence(function(){}, 1000); // slow down to allow widget to exit edit mode
+				}
+				function testOK(deferred, delay){
+					doh.robot.sequence(dojo.hitch(deferred, "callback", true), delay? delay : 1);
+				}
+
+				doh.register("dijit.InlineEditBox autosave tests", [
+					{
+						name: "CurrencyTextBox invalid value: blur",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("dollar_as");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.typeKeys("dollar", 1000, 1200); // invalid
+							moveAndClick("predefined");
+							doh.robot.sequence(d.getTestCallback(function(){
+								var currencyTextBox = inlineBox.wrapperWidget.editWidget;
+								doh.is('dollar', currencyTextBox.get("displayedValue"), "displayedValue");
+								doh.f(currencyTextBox.isValid(), "!isValid");
+								inlineBox.cancel(false);
+								doh.is('', inlineBox.get("value"), "value");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "CurrencyTextBox invalid value: ENTER",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("dollar_as");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.typeKeys("dollar", 1000, 1200); // invalid
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								var currencyTextBox = inlineBox.wrapperWidget.editWidget;
+								doh.is('dollar', currencyTextBox.get("displayedValue"), "displayedValue");
+								doh.f(currencyTextBox.isValid(), "!isValid");
+							}), 1000);
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is('', inlineBox.get("value"), "value");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "CurrencyTextBox valid value: blur",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("dollar_as");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.typeKeys("123", 1000, 600);
+							moveAndClick("predefined");
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("$123.00", inlineBox.get("value"), "value");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "CurrencyTextBox valid value: ENTER",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("dollar_as");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.typeKeys("234", 1000, 600);
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is('$234.00', inlineBox.get("value"), "value");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "CurrencyTextBox valid value: ESCAPE",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("dollar_as");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.typeKeys("345", 1000, 600);
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("$234.00", inlineBox.get("value"), "value");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "CurrencyTextBox valid value: TAB",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("dollar_as");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.typeKeys("456", 1000, 600);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is('$456.00', inlineBox.get("value"), "value");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "Focus test",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("editable");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.typeKeys("editable", 1000, 1600);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 1500, {}); // wait more than 1 second to TAB
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+							doh.robot.typeKeys("567", 500, 600);
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true}); // do this fast
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true}); // do this fast
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {}); // quickly back to editable
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+							doh.robot.typeKeys(" again", 1000, 1200);
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is('$567.00', dijit.byId("dollar_as").get("value"), "value");
+								doh.is('editable again', inlineBox.get("value"), "value");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "Textarea test",
+						timeout: 15000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("textarea");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.typeKeys("line 1", 1000, 1200);
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+							doh.robot.typeKeys("line 2", 500, 1200);
+							moveAndClick("predefined");
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is('line 1\\nline 2', inlineBox.get("value").replace(/\n/g, "\\n"), "textarea programmatic value was " + inlineBox.get("value").replace(/\n/g, "\\n"));
+								doh.is('line 1<br>line 2', inlineBox.domNode.innerHTML.toLowerCase(), "textarea rendered value was " + inlineBox.domNode.innerHTML);
+							}), 1000);
+							return d;
+						}
+					}
+				]);
+
+				// Testing that the initial display value of the InlineEditBox gets sent to the editor.
+				// For example, in this markup:
+				//		<span dojoType="dijit.InlineEditBox" ...>01/05/2007</span>
+				// When the editor is clicked the calendar should open to that date.
+				doh.register("dijit.InlineEditBox preDefinedValue tests", [
+					{
+						name: "CurrencyTextBox preDefinedValue",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("dollar");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is('$2,000', inlineBox.get("value"), "value");
+								var currencyTextBox = inlineBox.wrapperWidget.editWidget;
+								doh.is('2000.00', currencyTextBox.get("displayedValue"), "displayedValue");
+							}), 1000);
+							cancel(d, inlineBox);
+							testOK(d);
+							return d;
+						}
+					},
+					{
+						name: "NumberSpinner preDefinedValue",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("quantity");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is(3, inlineBox.get("value"));
+								var numberSpinner = inlineBox.wrapperWidget.editWidget;
+								doh.is(3, numberSpinner.get("value"));
+							}), 1000);
+							cancel(d, inlineBox);
+							testOK(d);
+							return d;
+						}
+					},
+					{
+						name: "ComboBox preDefinedValue",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("item");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("refrigerators", dojo.trim(inlineBox.get("value")));
+								var comboBox = inlineBox.wrapperWidget.editWidget;
+								doh.is("refrigerators", comboBox.get("value"));
+							}), 1000);
+							cancel(d, inlineBox);
+							testOK(d);
+							return d;
+						}
+					},
+					{
+						name: "DateTextBox preDefinedValue",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("purchase");
+							moveAndClick(inlineBox.domNode);
+							var preDate = dojo.date.locale.parse("01/05/2007", {datePattern: 'MM/dd/yyyy', selector:'date'});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("01/05/2007", inlineBox.get("value"));
+								var dateTextBox = inlineBox.wrapperWidget.editWidget;
+								doh.is(preDate.toString(), dateTextBox.get("value").toString());
+							}), 1000);
+							cancel(d, inlineBox);
+							testOK(d);
+							return d;
+						}
+					},
+					{
+						name: "FilteringSelect preDefinedValue",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("state");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("Pennsylvania", dojo.trim(inlineBox.get("value")));
+								var filteringSelect = inlineBox.wrapperWidget.editWidget;
+								doh.is("PA", filteringSelect.get("value"));
+							}), 1000);
+							cancel(d, inlineBox);
+							testOK(d);
+							return d;
+						}
+					}
+				]);
+
+				doh.register("renderAsHtml", [
+
+					// "plain text" mode, < > & have no special meaning
+					{
+						name: "false",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// confirm initial displayed value
+							var inlineBox = dijit.byId("renderAsHtml_false");
+							doh.is("<B>not bold</B>&lt;input&gt;", dojo.trim(inlineBox.domNode.innerHTML),
+								"confirm initial value (with special chars) wasn't modified");
+							doh.is("<B>not bold</B><input>", inlineBox.get("value"),
+								"confirm initial get('value')");
+
+							// launch editor, and make sure that special characters aren't mangled
+							moveAndClick(inlineBox.domNode);
+							doh.robot.sequence(d.getTestErrback(function(){
+								var editor = inlineBox.wrapperWidget.editWidget;
+								doh.is("<B>not bold</B><input>", editor.get("value"), "initial editor value");
+							}), 1000);
+
+							// edit value and save		
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 1000, {});
+							doh.robot.typeKeys("end", 2000, 1000);
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							// check that display value didn't mangle special characters
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("<B>not bold</B>&lt;input&gt;end", dojo.trim(inlineBox.domNode.innerHTML),
+									"displayed value after edit");
+								doh.is("<B>not bold</B><input>end", inlineBox.get("value"),
+									"get('value') after edit");
+							}), 1000);
+
+							return d;
+						}	
+					},
+
+					// HTML mode, display mode has rich text, which is passed to editor
+					{
+						name: "true",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// confirm initial displayed value
+							var inlineBox = dijit.byId("renderAsHtml_true");
+							doh.is("<b>not bold</b><b>bold</b>&lt;input&gt;",
+								dojo.trim(inlineBox.domNode.innerHTML).toLowerCase(),
+								"confirm initial value (with special chars) wasn't modified");
+							doh.is("<b>not bold</b><b>bold</b>&lt;input&gt;",
+								inlineBox.get("value").toLowerCase(),
+								"confirm initial get('value')");
+
+							// launch editor, and make sure that value was passed to editor as HTML
+							moveAndClick(inlineBox.domNode);
+							doh.robot.sequence(d.getTestErrback(function(){
+								var editor = inlineBox.wrapperWidget.editWidget;
+								doh.is("<b>not bold</b><b>bold</b>&lt;input&gt;",
+									editor.get("value").toLowerCase(),
+									"initial editor value");
+							}), 1000);
+
+							// edit value and save		
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 1000, {});
+							doh.robot.typeKeys("end", 2000, 1000);
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							// check that display value didn't mangle special characters
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("<b>not bold</b><b>bold</b>&lt;input&gt;end",
+									dojo.trim(inlineBox.domNode.innerHTML).toLowerCase(),
+									"displayed value after edit");
+								doh.is("<b>not bold</b><b>bold</b>&lt;input&gt;end",
+									inlineBox.get("value").toLowerCase(),
+									"get('value') after edit");
+							}), 1000);
+
+							return d;
+						}	
+					}
+				]);
+
+
+				doh.register("focus tests", [
+					{
+						name: "RTE",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var inlineBox = dijit.byId("inlineRTE");
+							moveAndClick(inlineBox.domNode);
+							doh.robot.typeKeys("!start!", 1000, 1400);
+							save(d, inlineBox);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(inlineBox.get("value").indexOf('!start!') >= 0, "value changed");
+							}), 1000);
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/Menu_a11y.html b/dijit/tests/robot/Menu_a11y.html
new file mode 100644
index 0000000..12d2b01
--- /dev/null
+++ b/dijit/tests/robot/Menu_a11y.html
@@ -0,0 +1,447 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Menu Keyboard Tests</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Menu.html');
+
+				if(!(dojo.isSafari < 4)){ // Tab-focus not well supported on old Safari
+				doh.register("dijit.MenuBar general keyboard tests",[
+					{
+						name: "start focus on the link, outside of menubar",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Start at the link
+							doh.robot.sequence(function(){
+								dijit.focus(dojo.byId("link"));
+							}, 500, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(dojo.global.dijit._curFocus, "something has focus");
+								doh.is("random link", dojo.global.dijit._curFocus.innerHTML, "check that focus is on the link");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "tab to the menubar",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// tab to the MenuBar... then focus should automatically shift to "File" menu,
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("File", dojo.trim(dojo.global.dijit._curFocus.innerText || dojo.global.dijit._curFocus.textContent),
+										"check that focus is on File menu");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "arrow to the edit menu",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});		// TODO: use left arrow in RTL mode
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("Edit", dojo.trim(dojo.global.dijit._curFocus.innerText || dojo.global.dijit._curFocus.textContent),
+										"check that focus is on Edit MenuItem");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "shift-tab back",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift:true});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("random link", dojo.trim(dojo.global.dijit._curFocus.innerText || dojo.global.dijit._curFocus.textContent),
+										"check that focus is back on the link");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "open file menu",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Start at the link
+							doh.robot.sequence(function(){
+								dijit.focus(dojo.byId("link"));
+							}, 500, 500);
+
+							// tab to the MenuBar... then focus should automatically shift to "File" menu
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							// and then down arrow to menu... focus should go to "New"
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t((dojo.global.dijit._curFocus.innerText || dojo.global.dijit._curFocus.textContent).indexOf("New") >= 0,
+										"check that focus is on New menu item of the File menu (indirectly checks that menu is visible)");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "click 'new' using enter key",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var clicked = false;
+							dijit.byId("new").onClick = function(){ clicked = true; };
+
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(clicked, "new was clicked");
+								doh.t(isHidden("fileMenu"), "File menu disappeared");
+								doh.f(dojo.hasClass("file", "dijitMenuItemSelected"),
+									"File MenuBarItem should no longer have selected effect, actual class is: " + dojo.byId("edit").className);
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "open submenu",
+						timeout: 8000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Start at the link
+							doh.robot.sequence(function(){
+								dijit.focus(dojo.byId("link"));
+							}, 500, 500);
+
+							// tab to the MenuBar... then focus should automatically shift to "File" menu item
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							// and then move to "View" menu item
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+
+							// open the menu
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							// go down to "Zoom" menu item
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 1000, {});
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+
+							// open the submenu (landing on first item)
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t( (dojo.global.dijit._curFocus.innerText || dojo.global.dijit._curFocus.textContent).indexOf("50%") >= 0,
+										"check that focus is on '50%'");
+								doh.robot.keyPress(dojo.keys.ENTER, 0, {}, true); // close popup menus
+							}), 1000, 500);
+
+							return d;
+						}
+					}
+				]);
+
+				// Using left-arrow to back up (#10437)
+				doh.register("dijit.MenuBar left arrow tests",[
+					{
+						name: "start focus on the link, outside of menubar",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Start at the link
+							doh.robot.sequence(function(){
+								dijit.focus(dojo.byId("link"));
+							}, 500, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(dojo.global.dijit._curFocus, "something has focus");
+								doh.is("random link", dojo.global.dijit._curFocus.innerHTML, "check that focus is on the link");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "tab to the menubar",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// tab to the MenuBar... then focus should automatically shift to "File" menu,
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("File", dijit.getEnclosingWidget(dojo.global.dijit._curFocus).label,
+										"check that focus is on File MenuItem");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "arrow to the view menu",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});		// TODO: use left arrow in RTL mode
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});		// TODO: use left arrow in RTL mode
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("View", dojo.trim(dojo.global.dijit._curFocus.innerText || dojo.global.dijit._curFocus.textContent),
+										"check that focus is on View MenuItem");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "down to the zoom menuitem",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});	// focuses "Normal", first menu item
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});	// focuses "Outline", second menu item
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});	// focuses "Zoom", third menu item
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("Zoom", dijit.getEnclosingWidget(dojo.global.dijit._curFocus).label,
+										"check that focus is on Zoom MenuItem");
+							}), 1000);
+
+							return d;
+						}
+					},
+					
+					{
+						name: "open the zoom menu",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("50%", dijit.getEnclosingWidget(dojo.global.dijit._curFocus).label,
+										"check that focus is on Zoom MenuItem");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "close Zoom menu, back to View menu",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.LEFT_ARROW, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("Zoom", dijit.getEnclosingWidget(dojo.global.dijit._curFocus).label,
+										"check that focus is on Zoom MenuItem");
+										
+								doh.is(0, dojo.query("#zoomMenu .dijitMenuItemSelected").length,
+									"dijitMenuItemSelected removed from Zoom Menu")
+							}), 1000);
+
+							return d;
+						}
+					},
+					
+					{
+						name: "close View menu, back to MenuBar",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// This should move focus to "Edit" in the MenuBar, which then opens
+							// the drop down and focuses on the first item (Cut)
+							doh.robot.keyPress(dojo.keys.LEFT_ARROW, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("Cut", dijit.getEnclosingWidget(dojo.global.dijit._curFocus).label,
+										"check that focus is on first MenuItem in Edit Menu");
+
+								doh.is(0, dojo.query("#viewMenu .dijitMenuItemSelected").length,
+									"dijitMenuItemSelected removed from View Menu")
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				// Run test about opening context menu via keyboard, except on safari/mac where that isn't
+				// possible (#9927)
+				if (!dojo.isMac || !dojo.isWebKit) {
+					doh.register("Context menu keyboard tests", [{
+						name: "open global context menu (keyboard)",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Put focus on the link; this is just a random place on the screen to have focus
+							doh.robot.sequence(function(){
+								dijit.focus(dojo.byId("link"));
+							}, 500, 500);
+
+							// open via keyboard
+							if(dojo.isMac){
+								doh.robot.keyPress(dojo.keys.SPACE, 500, {
+									ctrl: true
+								});
+							}else{
+								doh.robot.keyPress(dojo.keys.F10, 500, {
+									shift: true
+								});
+							}
+
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var menu = dijit.byId("windowContextMenu");
+								doh.t(isVisible(menu), "menu is now shown");
+
+								var menuCoords = dojo.position(menu.domNode),
+									linkCoords = dojo.position("link");
+
+								doh.t(menuCoords.x < 100, "x < 100", "actual x: " + menuCoords.x);
+								doh.t(menuCoords.y < 50, "y < 50", "actual y: " + menuCoords.y);
+								doh.t(menuCoords.x >= 0, "x >= 0", "actual x: " + menuCoords.x);
+								doh.t(menuCoords.y >= 0, "y >= 0", "actual y: " + menuCoords.y);
+								doh.robot.keyPress(dojo.keys.ESCAPE, 0, {}, true); // close context menu
+							}), 1000);
+
+							return d;
+						}
+					}]);
+				}
+
+				doh.register("Cancellation (ESCAPE) tests", [
+					{
+						name: "MenuBar selection and cancellation",
+						timeout: 20000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Start at the link
+							doh.robot.sequence(function(){
+								dijit.focus(dojo.byId("link"));
+							}, 500, 500);
+
+							// tab to the MenuBar... then focus should automatically shift to "File" menu,
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {}); // open File menu
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("fileMenu"), "File menu should be visible");
+							}), 1000);
+
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {}); // close File menu
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden("fileMenu"), "File menu is hidden after cancel");
+								doh.t(dojo.hasClass("file", "dijitMenuItemSelected"),
+									"File MenuBarItem should have selected class, actual class is: " + dojo.byId("file").className);
+							}), 1000);
+
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {}); // move to Edit menu
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.f(dojo.hasClass("file", "dijitMenuItemSelected"),
+									"File MenuBarItem should not have selected class, actual class is: " + dojo.byId("file").className);
+								doh.t(isHidden("editMenu"), "Edit menu is hidden after cancel and select");
+								doh.t(dojo.hasClass("edit", "dijitMenuItemSelected"),
+									"Edit MenuBarItem should have selected class, actual class is: " + dojo.byId("edit").className);
+							}), 1000);
+
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {}); // open Edit menu
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 1000, {}); // move to copy more slowly
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {}); // move to paste option
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {}); // click paste, closing edit menu
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden("editMenu"), "edit menu disappeared");
+								dijit.focus(dojo.byId("link"));
+							}), 1000, 500);
+
+							// tab to the MenuBar... then focus should automatically shift to "File" menu,
+							doh.robot.keyPress(dojo.keys.TAB, 500, {}); // move to File
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden("fileMenu"), "File menu should be hidden");
+							}), 1000);
+
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {}); // open File menu
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("fileMenu"), "File menu should be visible");
+							}), 1000);
+
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 75, {}); // #9846
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 75, {}); // move to View menu
+							doh.robot.keyPress(dojo.keys.LEFT_ARROW, 75, {}); // move to Edit menu
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("editMenu"), "Edit menu should be visible and File menu hidden");
+								doh.t(isHidden("fileMenu"), "File menu should be hidden and Edit menu visible");
+							}), 1000);
+
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {}); // close Edit menu
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("editMenu"), "edit menu disappeared");
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+				} // !dojo.isSafari
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/Menu_mouse.html b/dijit/tests/robot/Menu_mouse.html
new file mode 100644
index 0000000..663ff4e
--- /dev/null
+++ b/dijit/tests/robot/Menu_mouse.html
@@ -0,0 +1,489 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Menu Mouse Tests</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Menu.html');
+
+				doh.register("dijit.MenuBar mouse tests", [
+
+					{
+						name: "mouse over file MenuBarItem",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Check initial conditions
+							doh.f(dojo.hasClass("file", "dijitMenuItemHover"), "File MenuBarItem doesn't have hover effect");
+							doh.t(isHidden("fileMenu"), "File menu is hidden");
+
+							// Move over the File MenuBarItem
+							doh.robot.mouseMoveAt("file", 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// The "File" MenuBarItem should be highlighted
+								doh.t(dojo.hasClass("file", "dijitMenuItemHover"),
+									"File MenuBarItem should have hover effect, actual class is: " + dojo.byId("file").className);
+
+								// However, just moving over the MenuBarItem shouldn't have opened the menu
+								doh.t(isHidden("fileMenu"), "File menu is hidden");
+							}), 1000);	// 1000ms == give IE time to make that backgroune iframe
+
+							return d;
+						}
+					},
+
+					{
+						name: "click on file MenuBarItem",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// click the File MenuBarItem
+							doh.robot.mouseMoveAt("file", 500);
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// The "File" MenuBarItem should have the selected class in addition to the hover
+								// class
+								doh.t(dojo.hasClass("file", "dijitMenuItemHover"),
+									"File MenuBarItem should have hover effect, actual class is: " + dojo.byId("file").className);
+								doh.t(dojo.hasClass("file", "dijitMenuItemSelected"),
+									"File MenuBarItem should have selected class, actual class is: " + dojo.byId("file").className);
+
+								// And the file menu should be visible
+								doh.t(isVisible("fileMenu"), "File menu is visible");
+
+								// And the first item in the file menu should be selected
+								doh.t(dojo.hasClass("new", "dijitMenuItemSelected"),
+									"New MenuItem should have selected class, actual class is: " + dojo.byId("new").className);
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "hover edit menu item",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMoveAt("edit", 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Since we've already activated the MenuBar by clicking "File",
+								// hovering over "Edit" should automatically show the edit menu
+								doh.t(isVisible("editMenu"), "Edit menu is visible");
+
+								// And also, the file menu should have disappeared
+								doh.t(isHidden("fileMenu"), "File menu is hidden");
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "move to copy",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMoveAt("copy", 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(dojo.hasClass("edit", "dijitMenuItemHover"),
+									"Edit MenuBarItem shouldn't have hover effect anymore, actual class is: " + dojo.byId("edit").className);
+								doh.t(dojo.hasClass("edit", "dijitMenuItemSelected"),
+									"Edit MenuBarItem should still have selected class, actual class is: " + dojo.byId("edit").className);
+
+								doh.t(dojo.hasClass("copy", "dijitMenuItemHover"),
+									"Copy Menu item should have hover effect, actual class is: " + dojo.byId("copy").className);
+								doh.t(dojo.hasClass("copy", "dijitMenuItemSelected"),
+									"Copy Menu item should have selected effect, actual class is: " + dojo.byId("copy").className);
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "click copy",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var clicked = false;
+							dijit.byId("copy").onClick = function(){ clicked = true; };
+
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(clicked, "copy was clicked");
+								doh.t(isHidden("editMenu"), "edit menu disappeared");
+								doh.f(dojo.hasClass("edit", "dijitMenuItemSelected"),
+									"Edit MenuBarItem should no longer have selected effect, actual class is: " + dojo.byId("edit").className);
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "mouse over file MenuBarItem again",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Check initial conditions
+							doh.f(dojo.hasClass("file", "dijitMenuItemHover"), "File MenuBarItem doesn't have hover effect");
+							doh.t(isHidden("fileMenu"), "File menu is hidden");
+
+							// Move over the File MenuBarItem
+							doh.robot.mouseMoveAt("file", 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// The "File" MenuBarItem should be highlighted
+								doh.t(dojo.hasClass("file", "dijitMenuItemHover"),
+									"File MenuBarItem should have hover effect, actual class is: " + dojo.byId("file").className);
+
+								// However, it shouldn't be "selected", and
+								// just moving over the MenuBarItem shouldn't have opened the menu,
+								// given that after clicking above, the MenuBar should have reverted to it's
+								// "dormant" state so that it needs to be clicked again before menus show up automatically
+								doh.f(dojo.hasClass("file", "dijitMenuItemSelected"),
+									"File MenuBarItem shouldn't have selected effect, actual class is: " + dojo.byId("file").className);
+								doh.t(isHidden("fileMenu"), "File menu is hidden");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+
+				doh.register("Navigation menu mouse tests", [
+
+					{
+						name: "mouse over enabled submenu",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Check initial conditions
+							doh.f(dojo.hasClass("navMenuPopupItem1", "dijitMenuItemHover"), "navMenuPopupItem1 MenuItem doesn't have hover effect");
+							doh.t(isHidden("navMenuSub1"), "sub menu is hidden");
+
+							doh.robot.mouseMoveAt("navMenuPopupItem1", 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// The "enabled submenu" MenuItem should be highlighted
+								doh.t(dojo.hasClass("navMenuPopupItem1", "dijitMenuItemHover"),
+									"'Enabled Submenu' MenuItem should have hover effect, actual class is: " + dojo.byId("navMenuPopupItem1").className);
+
+								// However, just moving over the MenuItem shouldn't have opened the menu
+								doh.t(isHidden("navMenuSub1"), "sub menu is hidden");
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "open submenu",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(dojo.hasClass("navMenuPopupItem1", "dijitMenuItemHover"),
+									"'Enabled Submenu' MenuItem should have hover effect, actual class is: " + dojo.byId("navMenuPopupItem1").className);
+								doh.t(dojo.hasClass("navMenuPopupItem1", "dijitMenuItemSelected"),
+									"'Enabled Submenu' MenuItem should have selected effect, actual class is: " + dojo.byId("navMenuPopupItem1").className);
+
+								// And the sub menu should be visible
+								doh.t(isVisible("navMenuSub1"), "sub menu is visible");
+
+								// And the first item in the sub menu should be selected
+								doh.t(dojo.hasClass("navMenuSub1_item1", "dijitMenuItemSelected"),
+									"first item in sub menu should have selected class, actual class is: " + dojo.byId("new").className);
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "toggle CheckedMenuItem",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.f(dijit.byId("checked2").get('checked'), "not initially checked");
+
+							doh.robot.mouseMoveAt("checked2", 500);
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(dijit.byId("checked2").get('checked'), "now it's checked");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("Context menu mouse tests", [
+					{
+						name: "open global context menu (mouse)",
+						timeout: 3000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var menu = dijit.byId("windowContextMenu");
+
+							doh.t(isHidden(menu), "menu should be initially hidden");
+
+							// click random point on screen
+							doh.robot.mouseMoveAt("link", 500);
+							doh.robot.mouseClick({right: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isVisible(menu), "menu is now shown");
+
+								var linkCoords = dojo.position("link");
+									menuCoords = dojo.position(menu.domNode);
+
+								doh.t(menuCoords.x > linkCoords.x, "to right of link left edge");
+								doh.t(menuCoords.x < linkCoords.x + linkCoords.w, "to left of link right edge");
+								doh.t(menuCoords.y > linkCoords.y, "starts below top of link");
+								doh.t(menuCoords.y < linkCoords.x + linkCoords.h, "starts above bottom of link");
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "close global context menu (mouse)",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var menu = dijit.byId("windowContextMenu");
+
+							// close menu from above test
+							doh.robot.mouseMove(2, 2, 100);
+							doh.robot.mouseClick({left: true}, 100);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden(menu), "menu should be hidden again");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("More MenuBar mouse tests", [
+					{
+						name: "MenuBar selection and cancellation",
+						timeout: 20000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMoveAt("file", 500);
+							doh.robot.mouseClick({left: true}, 500); // click File
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("fileMenu"), "File menu should be visible #1");
+							}), 1000);
+
+							doh.robot.mouseClick({left: true}, 500); // close File menu
+							doh.robot.mouseMoveAt("edit", 500);
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden("fileMenu"), "File menu is hidden #1");
+								doh.t(isHidden("editMenu"), "Edit menu is hidden #1");
+
+								doh.f(dojo.hasClass("file", "dijitMenuItemSelected"),
+									"File MenuBarItem should not have selected class, actual class is: " + dojo.byId("file").className);
+								doh.f(dojo.hasClass("file", "dijitMenuItemHover"),
+									"File MenuBarItem shouldn't have hover effect anymore, actual class is: " + dojo.byId("edit").className);
+								doh.t(dojo.hasClass("edit", "dijitMenuItemHover"),
+									"Edit MenuBarItem should have hover effect, actual class is: " + dojo.byId("edit").className);
+							}), 1000);
+
+							doh.robot.mouseClick({left: true}, 500); // open edit menu
+							doh.robot.mouseMoveAt("paste", 1000);
+							doh.robot.mouseClick({left: true}, 500); // click paste, closing edit menu
+							doh.robot.mouseMoveAt("edit", 1000);
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(dojo.hasClass("edit", "dijitMenuItemHover"),
+									"Edit MenuBarItem should still have hover effect, actual class is: " + dojo.byId("edit").className);
+								doh.t(isHidden("editMenu"), "edit menu disappeared #1");
+							}), 1000);
+
+							doh.robot.mouseMoveAt("file", 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden("fileMenu"), "File menu should be hidden #2");
+							}), 500);
+
+							doh.robot.mouseClick({left: true}, 500); // click File
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("fileMenu"), "File menu should be visible #2");
+							}), 1000);
+
+							doh.robot.mouseMoveAt("view", 0, 150); // #9846
+							doh.robot.mouseMoveAt("edit", 0, 75);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden("fileMenu"), "File menu should be hidden #3");
+								doh.t(isVisible("editMenu"), "Edit menu should be visible");
+								var paste = dojo.position('paste');
+								doh.robot._mouseMove(paste.x + (paste.w >> 1), paste.y + paste.h + 20, false, 500);
+							}), 500, 1000);
+
+							// click point on screen under the Edit menu
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("editMenu"), "edit menu disappeared #2");
+							}), 1000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "MenuBar navigation with BOTH mouse and keyboard",
+						timeout: 20000,
+						runTest: function(){
+						    if(!(dojo.isSafari < 4)){ // doesn't support keyboard navigation
+							var d = new doh.Deferred();
+
+							// click random point on screen
+							doh.robot.mouseMoveAt("link", 500);
+							doh.robot.mouseClick({left: true}, 500); // click link to focus it
+
+							doh.robot.mouseMoveAt("view", 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(dojo.hasClass("view", "dijitMenuItemHover"),
+									"View MenuBarItem should have hover effect, actual class is: " + dojo.byId("view").className);
+								doh.t(isHidden("viewMenu"), "View menu is hidden");
+							}), 500);
+
+							// tab to the MenuBar... then focus should automatically shift to "File" menu,
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden("fileMenu"), "File menu is hidden");
+								doh.t(dojo.hasClass("file", "dijitMenuItemSelected"),
+									"File MenuBarItem should have selected class, actual class is: " + dojo.byId("file").className);
+								doh.f(dojo.hasClass("view", "dijitMenuItemHover"),
+									"View MenuBarItem shouldn't have hover effect anymore, actual class is: " + dojo.byId("view").className);
+							}), 1000);
+
+							doh.robot.mouseMoveAt("edit", 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(dojo.hasClass("edit", "dijitMenuItemHover"),
+									"Edit MenuBarItem should have hover effect, actual class is: " + dojo.byId("edit").className);
+								doh.t(isHidden("editMenu"), "View menu is hidden");
+							}), 500);
+
+							// move to View item with keyboard
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 1000, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("viewMenu"), "View menu is hidden");
+								doh.t(dojo.hasClass("view", "dijitMenuItemSelected"),
+									"View MenuBarItem should have selected class, actual class is: " + dojo.byId("file").className);
+								doh.f(dojo.hasClass("edit", "dijitMenuItemHover"),
+									"Edit MenuBarItem shouldn't have hover effect anymore, actual class is: " + dojo.byId("edit").className);
+							}), 1000);
+
+							return d;
+						    }
+						}
+					}
+				]);
+
+				doh.register("Menu diagonal movement tests", [
+					{
+						name: "Menu selection via sloppy movement",
+						timeout: 20000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseMoveAt("navMenuPopupItem1", 500); // move to Enabled submenu
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden("navMenuSub1"), "Enabled submenu should be hidden");
+							}), 500);
+
+							doh.robot.mouseClick({left: true}, 500); // click Enabled Submenu
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("navMenuSub1"), "Enabled submenu should be visible");
+							}), 1000);
+
+							doh.robot.mouseMoveAt("navMenuDisabledItem", 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden("navMenuSub1"), "Enabled submenu should be hidden");
+							}), 1000); // linger long enough for menu to close
+
+							doh.robot.mouseMoveAt("navMenuPopupItem1", 500, 500); // move back to Enabled submenu
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("navMenuSub1"), "Enabled submenu should be visible");
+							}), 1000); // linger long enough for menu to open
+
+							doh.robot.mouseMoveAt("navMenuDisabledItem", 500, 50); // QUICKLY move to the next menu item
+							doh.robot.sequence(d.getTestErrback(function(){
+							}), 200, 50);
+
+							doh.robot.mouseMoveAt("navMenuSub1_item2", 0, 50); // QUICKLY move to the popup menu
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("navMenuSub1"), "Enabled submenu 1 should be visible");
+								doh.t(dojo.hasClass("navMenuSub1_item2", "dijitMenuItemHover"),
+									"Submenu 1, item 2 navigation MenuItem should have hover effect, actual class is: " + dojo.byId("navMenuDisabledItem").className);
+								doh.t(dojo.hasClass("navMenuPopupItem1", "dijitMenuItemSelected"),
+									"'Enabled Submenu' MenuItem should have selected effect, actual class is: " + dojo.byId("navMenuPopupItem1").className);
+								var popup = dojo.position('navMenuSub1_popup');
+								doh.robot._mouseMove(popup.x + (popup.w >> 1), popup.y + popup.h + 20, false, 500);
+							}), 500, 1000);
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("navMenuSub1"), "Enabled submenu 1 menu still there");
+							}), 1000);
+
+							// click point on screen under the menu
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("navMenuSub1"), "Enabled submenu 1 menu disappeared");
+							}), 1000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
\ No newline at end of file
diff --git a/dijit/tests/robot/TitlePane.html b/dijit/tests/robot/TitlePane.html
new file mode 100644
index 0000000..159a4ab
--- /dev/null
+++ b/dijit/tests/robot/TitlePane.html
@@ -0,0 +1,254 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot TitlePane Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_TitlePane.html');
+
+				var pane1, pane2, pane3, href1, href2;
+
+				doh.register("api", [
+					{
+						name: "setup",
+						runTest: function(){
+					    	pane1 = dijit.byId("testPane1");
+					    	pane2 = dijit.byId("pane_2");
+					    	pane3 = dijit.byId("closed");		// initially closed
+							href1 = dijit.byId("href1");	// initially closed href, href load completes after expand
+							href2 = dijit.byId("href2");	// initially closed href, href load completes during expand
+						}
+					},
+					{
+						name: "title",
+						runTest: function(){
+							doh.is("Title Pane #1", pane1.get("title"), "title attr");
+							doh.is("Title Pane #1", innerText(pane1.titleNode), "inner text");
+							
+							pane1.set("title", "modified title");
+
+							doh.is("modified title", pane1.get("title"), "title attr modified");
+							doh.is("modified title", innerText(pane1.titleNode), "inner text modified");
+						}
+					},
+
+					{
+						name: "open",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.t(pane1.domNode.offsetHeight > 100, "pane 1 is open");
+							doh.t(pane1.get("open"), "pane1.open is true");
+
+							pane1.set("open", false);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(pane1.domNode.offsetHeight < 100, "pane 1 is closed");
+								doh.f(pane1.get("open"), "pane1.open is false");
+							}), 500);
+							
+							return d;
+						}
+					}
+				]);
+
+				doh.register("keyboard", [
+					{
+						name: "tabbing",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							dijit.focus(dojo.byId("input"));
+
+							// should go to title bar
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is(pane1.focusNode, dojo.global.dijit._curFocus,"focused on pane1 title")
+							}), 500);
+
+							// should skip hidden content and go to button
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is(dojo.byId("titleButton"), dojo.global.dijit._curFocus,"focused on title button after pane")
+							}), 500);
+
+							// go back to title bar
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(pane1.focusNode, dojo.global.dijit._curFocus,"focused on pane1 title")
+							}), 500);
+
+							return d;
+						}
+					},
+
+					{
+						name: "open",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.SPACE, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(pane1.domNode.offsetHeight > 100, "pane 1 is open");
+								doh.t(pane1.get("open"), "pane1.open is true");
+							}), 500);
+							
+							return d;
+						}
+					},
+					
+					{
+						name: "close",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.keyPress(dojo.keys.ENTER, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(pane1.domNode.offsetHeight < 100, "pane 1 is closed");
+							}), 500);
+							
+							return d;
+						}
+					}
+				]);
+
+				doh.register("height checks", [
+					{
+						name: "content change",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var height1, height2, height3;
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								pane1.set("open", true);
+							}), 500);
+
+							// Changing the content while open should change the height
+							doh.robot.sequence(d.getTestErrback(function(){
+								height1 = pane1.domNode.offsetHeight;
+								pane1.set("content", pane1.get("content") + "<br>new line");
+							}), 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								height2 = pane1.domNode.offsetHeight;
+								doh.t(height2 > height1,  "expected height increase, actually went from " + height1 + " to " + height2);
+							}), 500);
+
+							// Change the content while closed should also change the height (when it is next opened)
+							doh.robot.sequence(d.getTestErrback(function(){
+								pane1.set("open", false);
+							}), 500);
+							doh.robot.sequence(d.getTestErrback(function(){
+								pane1.set("content", pane1.get("content") + "<br>another new line");
+								pane1.set("open", true);
+							}), 500);
+							doh.robot.sequence(d.getTestCallback(function(){
+								height3 = pane1.domNode.offsetHeight;
+								doh.t(height3 > height2, "expected height increase, actually went from " + height2 + " to " + height3);
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "href loading",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Open the href pane, causing the href to load
+							dojo.window.scrollIntoView(dijit.byId("inner").domNode);
+							doh.robot.sequence(d.getTestErrback(function(){
+								href1.set("open", true);
+							}), 1000);
+
+							// Initially it should display "Loading..." with a small height (enough for that one message)
+							var height1, height2;
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("Loading...", dojo.trim(innerText(href1.containerNode)));
+								height1 = href1.domNode.offsetHeight;
+							}), 1500);
+
+							// Then the real content should be loaded and height should change to accommodate it
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.isNot("Loading...", dojo.trim(innerText(href1.containerNode)), "actual content");
+								height2 = href1.domNode.offsetHeight;
+								doh.t(height2 > height1, "expected height increase, actually went from " + height1 + " to " + height2);
+							}), 3000);
+
+							return d;
+						}
+					},
+					{
+						name: "href load complete during expand",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Opening the href pane will cause it to expand, and during the expansion the load
+							// will finish.   Make sure height shows full content
+							href2.set("open", true);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var height = href2.domNode.offsetHeight;
+								doh.t(height > 100, "height for full content not just loading message: " + height);
+							}), 2000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("layout", [
+					{
+						name: "resize event",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// The first time pane3 is opened the tab container should get a resize event
+							var resized = false;
+							dojo.connect(dijit.byId("tabContainer"), "resize", function(){ resized = true;});
+
+							doh.f(pane3.get("open"), "pane3 is closed");
+							pane3.set("open", true);
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(resized, "tabcontainer was resized");
+							}), 500);
+							
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/Toolbar.html b/dijit/tests/robot/Toolbar.html
new file mode 100644
index 0000000..5e4d80a
--- /dev/null
+++ b/dijit/tests/robot/Toolbar.html
@@ -0,0 +1,250 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Toolbar Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Toolbar.html');
+
+				var toolbar1Before, toolbar1After, toolbar1, toolbar2, toolbar3, toolbar4;
+
+				doh.register("initial conditions",[
+					{
+						name: "creation",
+						setUp: function(){
+							toolbar1Before = dojo.byId("toolbar1Before");
+					    	toolbar1 = dijit.byId("toolbar1");
+							toolbar1After = dojo.byId("toolbar1After");
+					    	toolbar2 = dijit.byId("toolbar2");
+					    	toolbar3 = dijit.byId("toolbar3");
+					    	toolbar4 = dijit.byId("toolbar4");							
+						},
+						runTest: function(){
+							// make sure that all the toolbars exist
+							doh.t(toolbar1, "toolbar 1");
+							doh.t(toolbar2, "toolbar 2");
+							doh.t(toolbar3, "toolbar 3");
+							doh.t(toolbar4, "toolbar 4");
+							
+							// and that labels are shown except when showLabel=true
+							var cutText = dojo.query(".dijitButtonText", dojo.byId("toolbar1.cut"))[0];
+							doh.is(0, cutText.offsetWidth, "cut button - text hidden");						
+
+							var copyText = dojo.query(".dijitButtonText", dojo.byId("toolbar1.copy"))[0];
+							doh.t(copyText.offsetWidth > 0, "copy button - text shown");						
+						}
+					}
+				]);
+					
+				doh.register("keyboard",[
+					{
+						name: "tab in and out",
+						timeout: 20000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								toolbar1Before.focus();
+							})), 500);
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("toolbar1.cut", dojo.global.dijit._curFocus.id, "cut, first visit");
+							})), 1000);
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("toolbar1After", dojo.global.dijit._curFocus.id);
+							})), 1000);
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("toolbar1.cut", dojo.global.dijit._curFocus.id, "cut, second visit");
+							})), 1000);
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is("toolbar1Before", dojo.global.dijit._curFocus.id, "back before toolbar1");
+							})), 1000);
+
+							return d;
+						}
+					},
+	
+					{
+						name: "left/right arrow keys",
+						timeout: 40000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Disable a bunch of buttons to make sure that left/right arrow
+							// keys skip over disabled buttons, and also that initial focus
+							// goes to the first enabled button
+							dojo.forEach(["toolbar1.cut", "toolbar1.copy", "toolbar1.bold", "toolbar1.backcolor",
+								"toolbar1.forecolor", "toolbar1.combo2"], function(widgetName){
+								dijit.byId(widgetName).set("disabled", true);
+							});
+
+							// Initial focus (upon tabbing into toolbar) should go to first enabled button
+							toolbar1Before.focus();
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("toolbar1.italic", dojo.global.dijit._curFocus.id, "cut, first visit");
+							})), 1000);
+
+							// Remaining enabled positons that left/right arrow should navigate to (not including the initial leftmost button),
+							var focusPoints = ["toolbar1.dialog", "toolbar1.combo_button", "toolbar1.combo_arrow", "toolbar1.insertorderedlist"];
+
+							// Use right arrow key to visit every enabled button (and for combobutton to hit left and right sides)
+							dojo.forEach(focusPoints, function(str){
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+								doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+									doh.is(str, dojo.global.dijit._curFocus.id, str + ", first visit");
+								})), 1000);
+							});
+
+							// Now go backwards
+							focusPoints.reverse();
+							focusPoints.shift();
+							dojo.forEach(focusPoints, function(str){
+								doh.robot.keyPress(dojo.keys.LEFT_ARROW, 500, {});
+								doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+									doh.is(str, dojo.global.dijit._curFocus.id, str + ", second visit");
+								})), 1000);
+							});
+
+							// Test the TAB key takes us to the <input> after the toolbar.
+							// This confirms that the currently focused toolbar button
+							// is in the correct position in the tab order (ie, the position specified
+							// for the toolbar itself), and that there are no stray tabstops on the toolbar itself
+							// or on the other buttons. 
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("toolbar1After", dojo.global.dijit._curFocus.id, "first time past toolbar1");
+							})), 1000);
+
+							// Make sure that we can still shift-tab back to before the toolbar too
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("toolbar1.italic", dojo.global.dijit._curFocus.id, "cut, after shift-tab back into toolbar");
+							})), 1000);
+
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								doh.is("toolbar1Before", dojo.global.dijit._curFocus.id, "back before toolbar1");
+							})), 1000);
+
+							return d;
+						}
+					},
+
+					// Test drop down ability.   These tests are probably redundant with the Button tests themselves,
+					// so they aren't strictly necessary.
+					{
+						name: "drop downs",
+						timeout: 60000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Re-enable the ToolipDialog and ColorPalette drop down so that we can test it
+							dijit.byId("toolbar1.dialog").set("disabled", false);
+							dijit.byId("toolbar1.backcolor").set("disabled", false);
+
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								toolbar1Before.focus();
+							})), 500);
+
+							// Tab into toolbar and move to tooltip dialog button
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("toolbar1.dialog", dojo.global.dijit._curFocus.id, "dialog button, first visit");
+							})), 1000);
+
+							// Open the dialog, focus should go to first input
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("user", dojo.global.dijit._curFocus.id);
+							})), 1000);
+
+							// ESC should restore focus to toolbar dialog button
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("toolbar1.dialog", dojo.global.dijit._curFocus.id, "dialog button, second visit");
+							})), 1000);
+
+							// Open the dialog again
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("user", dojo.global.dijit._curFocus.id, "user, again");
+							})), 1000);
+
+							// Submit should also restore focus to toolbar dialog button, assuming that it
+							// doesn't reset the focus somewhere else (like into the editor)
+							doh.robot.keyPress(dojo.keys.TAB, 500);
+							doh.robot.keyPress(dojo.keys.TAB, 500);
+							doh.robot.keyPress(dojo.keys.ENTER, 500);
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("toolbar1.dialog", dojo.global.dijit._curFocus.id, "dialog button, third visit");
+							})), 1000);
+
+							// Try the ColorPalette
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500);
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500);
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.t(dojo.isDescendant(dojo.global.dijit._curFocus, dijit.byId("toolbar1.colorPalette").domNode),
+									"focus inside colorpalette, actual focus is: " + (dojo.global.dijit._curFocus ? 
+										(dojo.global.dijit._curFocus.id||"no id") : "no focus"));
+							})), 1000);
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500);	// navigation in the ColorPalette
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500);	// navigation in the ColorPalette
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.t(dojo.isDescendant(dojo.global.dijit._curFocus, dijit.byId("toolbar1.colorPalette").domNode),
+									"focus still inside colorpalette, actual focus is: " + (dojo.global.dijit._curFocus ? 
+										(dojo.global.dijit._curFocus.id||"no id") : "no focus"));
+							})), 1000);
+							
+							// pressing tab in the colorpalette should move focus back to the toolbar
+							doh.robot.keyPress(dojo.keys.TAB, 500);
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								doh.is("toolbar1.backcolor", dojo.global.dijit._curFocus.id, "back on colorpalette button");
+							})), 1000);
+
+							// try the ComboButton
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500);
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 500);
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500);
+							doh.robot.sequence(d.getTestErrback(dojo.hitch(this, function(){
+								// TODO: test that focus is on menu
+							})), 1000);
+							doh.robot.keyPress(dojo.keys.SPACE, 500);	// select first menu option
+							doh.robot.sequence(d.getTestCallback(dojo.hitch(this, function(){
+								// TODO: test that focus is returned to button
+							})), 1000);
+
+							return d;
+						}
+					}
+
+				]);
+				// TODO: mouse
+				
+				
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/TooltipDialog_a11y.html b/dijit/tests/robot/TooltipDialog_a11y.html
new file mode 100644
index 0000000..c84261f
--- /dev/null
+++ b/dijit/tests/robot/TooltipDialog_a11y.html
@@ -0,0 +1,370 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot TooltipDialog A11y Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_TooltipDialog.html');
+
+				doh.register("TooltipDialog normal operation", [
+					{
+						name: "basic navigation",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var button = dijit.byId("tooltipDlgButton");
+							
+							// open TooltipDialog
+							doh.robot.sequence(function(){
+								button.focus();
+							}, 1000, 1000);
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should be showing");
+							}), 1000);
+
+							// shift-tab should loop around to last field
+							doh.robot.keyPress(dojo.keys.TAB, 500, {shift: true});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("submit", dojo.global.dijit._curFocus.id, "focused on button");
+							}), 1000);
+
+							// tab should loop around to first field
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.is("inline", dojo.global.dijit._curFocus.id, "focused on InlineEditBox");
+							}), 1000);
+
+							// close TooltipDialog
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(button._opened, "TooltipDialog should not be showing after Esc");
+							}), 1000);
+							return d;
+						}
+					},
+					{
+						name: "nested popup",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var button = dijit.byId("tooltipDlgButton"),
+								select = dijit.byId("combo");
+							
+							// open TooltipDialog, advance to FilteringSelect
+							doh.robot.sequence(function(){
+								button.focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should be showing");
+								doh.is("combo", dojo.global.dijit._curFocus.id, "focused on combo");
+							}), 1000);
+
+							// pick second option
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 0, {});
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 1000, {});
+							doh.robot.keyPress(dojo.keys.DOWN_ARROW, 500, {});
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should still be showing");
+								doh.is("pepperoni", select.get("value"), "selected pepperoni");
+							}), 1000);
+
+							// close TooltipDialog
+							doh.robot.keyPress(dojo.keys.ESCAPE, 0, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(button._opened, "TooltipDialog closed");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("interacton with autosave InlineEditBox", [
+					{
+						name: "InlineEditBox edit mode, change value, then Esc",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var button = dijit.byId("tooltipDlgButton"),
+								inlineEditBox = dijit.byId("inline"),
+								initialValue = inlineEditBox.get("value");
+							
+							// open TooltipDialog
+							doh.robot.sequence(function(){
+								button.focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should be showing");
+								doh.f(inlineEditBox.editing, "InlineEditBox not in edit mode yet");
+							}), 1000);
+
+							// edit InlineEditBox
+							doh.robot.keyPress(dojo.keys.SPACE, 0, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should still be showing");
+								doh.t(inlineEditBox.editing, "InlineEditBox in edit mode");
+							}), 1000);
+
+							// type something
+							doh.robot.typeKeys("esc", 0, 600);
+
+							// abort edit
+							doh.robot.keyPress(dojo.keys.ESCAPE, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should still still be showing");
+								doh.f(inlineEditBox.editing, "Esc should have exited InlineEditBox edit mode");
+								doh.is(initialValue, inlineEditBox.get("value"), "initial value was inline");
+							}), 1000);
+
+							// close TooltipDialog
+							doh.robot.keyPress(dojo.keys.ESCAPE, 0, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(button._opened, "TooltipDialog closed");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "InlineEditBox edit mode, change value, then Tab",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var button = dijit.byId("tooltipDlgButton"),
+								inlineEditBox = dijit.byId("inline");
+							
+							// open TooltipDialog
+							doh.robot.sequence(function(){
+								button.focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should be showing");
+								doh.f(inlineEditBox.editing, "InlineEditBox not in edit mode yet");
+							}), 1000);
+
+							// edit InlineEditBox
+							doh.robot.keyPress(dojo.keys.SPACE, 0, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should still be showing");
+								doh.t(inlineEditBox.editing, "InlineEditBox in edit mode");
+							}), 1000);
+
+							// type something
+							doh.robot.typeKeys("tab", 0, 600);
+
+							// save edit
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should still still be showing");
+								doh.f(inlineEditBox.editing, "Tab should have exited InlineEditBox edit mode");
+								doh.is("tab", inlineEditBox.get("value"), "value changed to tab");
+							}), 1000);
+
+							// close TooltipDialog
+							doh.robot.keyPress(dojo.keys.ESCAPE, 0, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(button._opened, "TooltipDialog closed");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "InlineEditBox edit mode, change value, then Enter",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var button = dijit.byId("tooltipDlgButton"),
+								inlineEditBox = dijit.byId("inline");
+							
+							// open TooltipDialog
+							doh.robot.sequence(function(){
+								button.focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should be showing");
+								doh.f(inlineEditBox.editing, "InlineEditBox not in edit mode yet");
+							}), 1000);
+
+							// edit InlineEditBox
+							doh.robot.keyPress(dojo.keys.SPACE, 0, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should still be showing");
+								doh.t(inlineEditBox.editing, "InlineEditBox in edit mode");
+							}), 1000);
+
+							// type something
+							doh.robot.typeKeys("enter", 0, 600);
+
+							// save edit
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should still still be showing");
+								doh.f(inlineEditBox.editing, "Tab should have exited InlineEditBox edit mode");
+								doh.is("enter", inlineEditBox.get("value"), "value changed to enter");
+							}), 1000);
+
+							// close TooltipDialog
+							doh.robot.keyPress(dojo.keys.ESCAPE, 0, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.f(button._opened, "TooltipDialog closed");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "InlineEditBox double edit (esc, enter)",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var button = dijit.byId("tooltipDlgButton")
+								inlineEditBox = dijit.byId("inline");
+
+							// open TooltipDialog
+							doh.robot.sequence(function(){
+								button.focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should be showing");
+							}), 1000);
+
+							// start editing
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+	
+							// abort editing, then re-enter edit mode
+							doh.robot.keyPress(dojo.keys.ESCAPE, 1000, {});
+							doh.robot.keyPress(dojo.keys.ENTER, 1000, {});
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(button._opened, "TooltipDialog should still be showing");
+								doh.t(inlineEditBox.editing, "Enter should have reentered edit mode");
+								inlineEditBox.cancel(true);
+								button.closeDropDown(true);
+							}), 2000);
+							return d;
+						}
+					},
+					{
+						name: "InlineEditBox double edit (enter, enter)",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+							var button = dijit.byId("tooltipDlgButton"),
+								inlineEditBox = dijit.byId("inline");
+
+							// open TooltipDialog
+							doh.robot.sequence(function(){
+								button.focus();
+							}, 1000, 1000);
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should be showing");
+							}), 1000);
+
+							// start editing
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+							doh.robot.typeKeys("enter #2", 1000, 1000);
+							
+							// save via ENTER key, the press ENTER again to re-edit
+							doh.robot.keyPress(dojo.keys.ENTER, 200, {});
+							doh.robot.keyPress(dojo.keys.ENTER, 1000, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(button._opened, "TooltipDialog should still be showing");
+								doh.t(inlineEditBox.editing, "2nd Enter should have reentered edit mode");
+								inlineEditBox.cancel(true);
+								button.closeDropDown(true);
+							}), 2000);
+							return d;
+						}
+					},
+					{
+						name: "InlineEditBox focused after Tab/Shift+Tab",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var button = dijit.byId("tooltipDlgButton"),
+								inlineEditBox = dijit.byId("inline");
+
+							// open TooltipDialog
+							doh.robot.sequence(function(){
+								button.focus();
+							}, 1000, 1000);
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(button._opened, "TooltipDialog should be showing");
+							}), 1000);
+
+							// start editing
+							doh.robot.keyPress(dojo.keys.SPACE, 500, {});
+							doh.robot.typeKeys("tab", 1000, 600);
+
+							// tab forward, then back (first tab will cancel edit)
+							doh.robot.keyPress(dojo.keys.TAB, 100, {});	
+							doh.robot.keyPress(dojo.keys.TAB, 1000, {shift:true});
+
+							// re-enter edit mode
+							doh.robot.keyPress(dojo.keys.ENTER, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(button._opened, "TooltipDialog should still be showing");
+								doh.t(inlineEditBox.editing, "Enter after shift+Tab should have reentered edit mode");
+								inlineEditBox.cancel(true);
+								button.closeDropDown(true);
+							}), 2000);
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/TooltipDialog_mouse.html b/dijit/tests/robot/TooltipDialog_mouse.html
new file mode 100644
index 0000000..bfff248
--- /dev/null
+++ b/dijit/tests/robot/TooltipDialog_mouse.html
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot TooltipDialog Mouse Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_TooltipDialog.html');
+
+				doh.register("TooltipDialog", [
+					{
+						name: "Select",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								select = dijit.byId("select");
+							
+							// open TooltipDialog
+							doh.robot.mouseMoveAt("tooltipDlgButton", 1000);
+							doh.robot.mouseClick({left: true}, 1000);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("tooltipDlg"), "TooltipDialog should be showing");
+							}), 1000);
+
+							// open Select
+							doh.robot.mouseMoveAt("select", 0);
+							doh.robot.mouseClick({left: true}, 1000);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("tooltipDlg"), "TooltipDialog should still be showing");
+								doh.t(isVisible("select_menu"), "Select Menu showing too");
+							}), 1000);
+							
+							// pick second option
+							doh.robot.mouseMoveAt(function(){
+								return dojo.query("tr", dojo.byId("select_menu"))[1];
+							}, 0);
+							doh.robot.mouseClick({left: true}, 1000);
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden("select_menu"), "Select Menu closed");
+								doh.t(isVisible("tooltipDlg"), "TooltipDialog should still still be showing");
+								doh.is("peppers", select.get("value"), "selected peppers");
+							}), 1000);
+
+							// close TooltipDialog
+							doh.robot.mouseMove(10, 10, 0);
+							doh.robot.mouseClick({left: true}, 1000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("tooltipDlg"), "Tooltip dialog closed");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "InlineEditBox",
+						timeout: 20000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								inlineEditBox = dijit.byId("inline");
+							
+							// open TooltipDialog
+							doh.robot.mouseMoveAt("tooltipDlgButton", 500);
+							doh.robot.mouseClick({left: true}, 1000);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("tooltipDlg"), "TooltipDialog should be showing");
+							}), 1000);
+
+							// start editing InlineEditBox
+							doh.robot.mouseMoveAt("inline", 0);
+							doh.robot.mouseClick({left: true}, 1000);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isVisible("tooltipDlg"), "TooltipDialog should still be showing");
+								doh.t(inlineEditBox.editing, "InlineEditBox in edit mode");
+							}), 1000);
+							
+							// type something
+							doh.robot.typeKeys("changed", 0, 600);
+
+							// close InlineEditBox by clicking on blank area of TooltipDialog
+							doh.robot.mouseMoveAt("tooltipDlg", 0, 500, 10, 20);
+							doh.robot.mouseClick({left: true}, 1000);
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.f(inlineEditBox.editing, "InlineEditBox no longer in edit mode");
+								doh.t(isVisible("tooltipDlg"), "TooltipDialog should still still be showing");
+								doh.is("changed", inlineEditBox.get("value"), "value changed to changed");
+							}), 1000);
+
+							// close TooltipDialog
+							doh.robot.mouseMove(10, 10, 0);
+							doh.robot.mouseClick({left: true}, 1000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden("tooltipDlg"), "Tooltip dialog closed");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/Tooltip_a11y.html b/dijit/tests/robot/Tooltip_a11y.html
new file mode 100644
index 0000000..ea363ed
--- /dev/null
+++ b/dijit/tests/robot/Tooltip_a11y.html
@@ -0,0 +1,352 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Tooltip A11Y Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Tooltip.html');
+
+				// Pointer to master tooltip.  This gets set in the first test when the
+				// first tooltip is shown
+				var masterTT;
+
+				doh.register("setup", function(){
+					// Avoid the page being scrolled when you run the test twice (via browser's refresh button)
+					dojo.body().parentNode.scrollTop = 0;	// works on FF
+					dojo.body().scrollTop = 0;	// works on safari
+				});
+
+				doh.register("dijit.Tooltip keyboard tests", [
+					{
+						name: "show on focus",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								around = dojo.byId("four");
+
+							doh.robot.sequence(function(){
+								around.focus();
+								masterTT = dojo.global.dijit._masterTT;
+								doh.t(!masterTT || isHidden(masterTT.domNode), "tooltip either hidden or doesn't exist yet");
+							}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// At this point the master tooltip should have been created, so save in
+								// global variable
+								masterTT = dojo.global.dijit._masterTT;
+
+								doh.t(masterTT && isVisible(masterTT.domNode), "tooltip shown");
+
+								// make sure tooltip is in right place (but note that it could be to the
+								// left of the right depending on page BIDI setting)
+								var aroundCoords = dojo.position(around),
+									tooltipCoords = dojo.position(masterTT.domNode);
+								doh.is(aroundCoords.y + aroundCoords.h, tooltipCoords.y + Math.round(tooltipCoords.h), "aligned");
+
+								// Make sure it has right content
+								doh.is("tooltip on a button", dojo.trim(innerText(masterTT.domNode)), "tooltip text");
+							}), 2000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "hide on blur",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Tab off of the "button w/tooltip" to the "remove button",
+							// which doesn't have a tooltip
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(masterTT && isHidden(masterTT.domNode), "tooltip hidden");
+							}), 2000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "show another tooltip",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								around = dojo.byId("seven");
+
+							// Tab off of the "remove button" to the <select>
+							doh.robot.keyPress(dojo.keys.TAB, 500, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(masterTT && isVisible(masterTT.domNode), "tooltip shown");
+
+								// make sure tooltip is on the screen (in LTR mode it needs to go to the
+								// left of the <select>, not to the right like it usually does)
+								var viewportCoords = dojo.window.getBox(),
+									tooltipCoords = dojo.position(masterTT.domNode);
+								console.log("viewport coords: ", viewportCoords, "tooltip coords: ", tooltipCoords);
+								doh.t(tooltipCoords.x > 0, "x > 0");
+								doh.t(tooltipCoords.x + tooltipCoords.w <= viewportCoords.w, "t.x + t.w");
+								doh.t(tooltipCoords.y > 0, "y > 0");
+								doh.t(tooltipCoords.y + tooltipCoords.h <= viewportCoords.h, "t.y + t.h");
+
+								// Make sure it has the new content.
+								// There's a newline in this tooltip text, so to make comparison easier do substr()
+								doh.is("tooltip on a select", dojo.trim(innerText(masterTT.domNode)).substr(0, 19), "tooltip text");
+							}), 2000);
+
+							return d;
+						}
+					}
+
+				]);
+
+				doh.register("dijit.Tooltip negative keyboard tests", [
+					// Test that quickly going over a node doesn't cause the tooltip
+					// to show up
+ 					{
+						name: "jump over",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								around = dojo.byId("one");
+
+							// Focus onto something w/out a tooltip to make currently displayed tooltip disappear
+							doh.robot.sequence(d.getTestErrback(function(){
+								dojo.byId("removeButton").focus();
+							}), 50);
+
+							// Focus on a node w/a tooltip
+							doh.robot.sequence(d.getTestErrback(function(){
+								around.focus();
+							}), 500);
+
+							doh.robot.sequence(d.getTestErrback(function(){
+								doh.t(isHidden(masterTT.domNode), "tooltip should be hidden on initial focus, but text shown is: " +
+										dojo.trim(innerText(masterTT.domNode)));
+							}), 50);
+
+							// But then tab away after 100ms, before tooltip is shown
+							doh.robot.keyPress(dojo.keys.TAB, 50, {shift: true});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(isHidden(masterTT.domNode), "tooltip still hidden after tabbing away");
+							}), 1000);
+
+							return d;
+						}
+					}
+            	]);
+
+				doh.register("dijit.Tooltip API tests", [
+
+					// These tests are for a tooltip attached to multiple nodes,
+					// and for dynamically changing the nodes that a tooltip is attached to.
+
+					// Initially, the tooltip is attached to "t1 text" and "t3 text".
+					// It should show for either of them.
+					// "t2 text" shouldn't show until we connect the tooltip to that node.
+
+					{
+						name: "setup",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								tooltip = dijit.byId("t_tooltip");
+
+							// While we are at it, test set('label', ...) too
+							tooltip.set('label', 'bill was here');
+
+							var connectIds = tooltip.get("connectId");
+							doh.is(2, connectIds.length, "2 connect ids initially");
+							doh.is("t1", connectIds[0]);
+							doh.is("t3", connectIds[1]);
+						}
+					},
+
+					{
+						name: "tooltip connected to 't1 text'",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								around = dojo.byId("t1");
+
+							doh.robot.sequence(function(){
+								dojo.window.scrollIntoView(around);
+								around.focus();
+							}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(masterTT && isVisible(masterTT.domNode), "tooltip shown");
+
+								// Make sure it has right content
+								doh.is("bill was here", dojo.trim(innerText(masterTT.domNode)), "tooltip text");
+							}), 2000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "tooltip *not* connected to 't2 text'",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								around = dojo.byId("t2");
+
+							doh.robot.sequence(function(){
+								dojo.window.scrollIntoView(around);
+								around.focus();
+							}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(masterTT && isHidden(masterTT.domNode), "tooltip hidden");
+							}), 2000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "'t3 text' is connected to the tooltip",
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								around = dojo.byId("t3");
+
+							doh.robot.sequence(function(){
+								dojo.window.scrollIntoView(around);
+								around.focus();
+							}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(masterTT && isVisible(masterTT.domNode), "tooltip visible");
+							}), 2000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "connect to 't2 text'",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								tooltip = dijit.byId("t_tooltip"),
+								around = dojo.byId("t2");
+
+							tooltip.addTarget("t2");
+
+							var connectIds = tooltip.get("connectId");
+							doh.is(3, connectIds.length, "3 connect ids");
+							doh.is("t1", connectIds[0]);
+							doh.is("t3", connectIds[1]);
+							doh.is("t2", connectIds[2]);
+
+							// Focus "t2 text" and make sure tooltip shows
+							dojo.window.scrollIntoView(around);
+							around.focus();
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(masterTT && isVisible(masterTT.domNode), "tooltip shown");
+							}), 2000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "disconnect from 't3 text'",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								tooltip = dijit.byId("t_tooltip"),
+								around = dojo.byId("t3");
+
+							tooltip.removeTarget("t3");
+							var connectIds = tooltip.get("connectId");
+							doh.is(2, connectIds.length, "2 connect ids");
+							doh.is("t1", connectIds[0]);
+							doh.is("t2", connectIds[1]);
+
+							// Focus "t3 text" and make sure tooltip doesn't show
+							dojo.window.scrollIntoView(around);
+							around.focus();
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(masterTT && isHidden(masterTT.domNode), "tooltip hidden");
+							}), 2000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "reset connectId array",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								tooltip = dijit.byId("t_tooltip"),
+								around = dojo.byId("t2");
+
+							// Move focus somewhere out of the way
+							dojo.byId("t5").focus();
+
+							// Disconnecting from "t2 text", and adding "t4 text"
+							tooltip.set("connectId", ["t3", "t4"]);
+
+							// Focus "t2 text" and make sure tooltip doesn't show anymore
+							dojo.window.scrollIntoView(around);
+							around.focus();
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(masterTT && isHidden(masterTT.domNode), "tooltip hidden");
+							}), 2000);
+
+							return d;
+						}
+					},
+					{
+						name: "further testing connectId array reset worked",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								tooltip = dijit.byId("t_tooltip"),
+								around = dojo.byId("t4");
+
+							// Focus "t4 text" and make sure tooltip shows
+							dojo.window.scrollIntoView(around);
+							around.focus();
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(masterTT && isVisible(masterTT.domNode), "tooltip visible");
+							}), 2000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/Tooltip_mouse.html b/dijit/tests/robot/Tooltip_mouse.html
new file mode 100644
index 0000000..f5c3b87
--- /dev/null
+++ b/dijit/tests/robot/Tooltip_mouse.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Tooltip Mouse Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../test_Tooltip.html');
+
+				// Pointer to master tooltip.  This gets set in the first test when the
+				// first tooltip is shown
+				var masterTT;
+
+				doh.register("dijit.Tooltip mouse tests", [
+					{
+						name: "show on mouse over",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								around = dojo.byId("four");
+
+							doh.robot.mouseMoveAt("four", 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// At this point the master tooltip should have been created, so save in
+								// global variable
+								masterTT = dojo.global.dijit._masterTT;
+
+								doh.t(masterTT && isVisible(masterTT.domNode), "tooltip shown");
+							}), 2000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "hide on defocus",
+						timeout: 4000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Tab off of the "button w/tooltip" to the "remove button",
+							// which doesn't have a tooltip
+							doh.robot.mouseMoveAt(dojo.query("h1")[0], 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.t(masterTT && isHidden(masterTT.domNode), "tooltip hidden");
+							}), 2000);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/Tree_a11y.html b/dijit/tests/robot/Tree_a11y.html
new file mode 100644
index 0000000..21b8659
--- /dev/null
+++ b/dijit/tests/robot/Tree_a11y.html
@@ -0,0 +1,772 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>doh.robot Tree Test</title>
+
+	<style>
+		@import "../../../util/doh/robot/robot.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");
+
+		var treeIds = ["mytree", "tree2"];
+
+		function treeTests(){
+			var that = {};
+
+			var forceLoadChildItems = function(/*dijit._TreeNode*/inNode, /*dijit.Tree*/inTree){
+				if(inTree.model.mayHaveChildren(inNode.item)){
+					if(inNode.getChildren().length > 0){
+						return;
+					}
+					var childItems = null;
+					inTree.model.getChildren(inNode.item, function(items){ childItems = items; });
+					inNode.setChildItems(childItems);
+					childItems = null;
+				}
+			};
+
+			that.testTreeItemRole = function(/*dijit._TreeNode*/inRoot, /*dijit.Tree*/inTree){
+				if(inRoot){
+					doh.is("treeitem", dijit.getWaiRole(inRoot.labelNode), inRoot.label + "[" + inTree.id + "]: aria role (treeItem)");
+					//recurse
+					forceLoadChildItems(inRoot, inTree);
+					var children = inRoot.getChildren();
+					for(var i = 0; i < children.length; i++){
+						that.testTreeItemRole(children[i], inTree);
+					}
+				}
+			};
+
+			that.test1TreeItemExpandedState = function(/*dijit._TreeNode*/inItem, /*dijit.Tree*/inTree){
+				if(inItem){
+					if(inItem.isExpandable){
+						var wasExpanded = inItem.isExpanded;
+						inTree._expandNode(inItem);
+						var nowExpanded = dijit.getWaiState(inItem.labelNode, "expanded");
+						inTree._collapseNode(inItem);
+						var nowCollapsed = dijit.getWaiState(inItem.labelNode, "expanded");
+						if(wasExpanded){
+							inTree._expandNode(inItem);
+						}
+						doh.is("true", nowExpanded, inItem.label + "[" + inTree.id + "]: aria state expanded=true");
+						doh.is("false", nowCollapsed, inItem.label + "[" + inTree.id + "]: aria state expanded=false");
+					}else{
+						doh.is("", dijit.getWaiState(inItem.labelNode, "expanded"), inItem.label + "[" + inTree.id + "]: aria state expanded=false");
+					}
+				}
+			};
+
+			that.testTreeItemExpandedState = function(/*dijit._TreeNode*/inRoot, /*dijit.Tree*/inTree){
+				if(inRoot){
+					that.test1TreeItemExpandedState(inRoot, inTree);
+					//recurse
+					forceLoadChildItems(inRoot, inTree);
+					var children = inRoot.getChildren();
+					for(var i = 0; i < children.length; i++){
+						that.testTreeItemExpandedState(children[i], inTree);
+					}
+				}
+			};
+
+			// Tab focus test data and functions
+			var xtraParas = [];
+			var expectedBlurCount = 0;
+			var focusCount = 0;
+			var blurCount = 0;
+			var gotFocus = function(){
+				focusCount++;
+			};
+			var lostFocus = function(){
+				blurCount++;
+			};
+			that.focusConnect = null;
+			that.blurConnect = null;
+
+			var addTabNavFoci = function(inTree){
+				var aPara = dojo.doc.createElement("p");
+				dojo.attr(aPara, 'tabIndex', 0);
+				aPara.innerHTML = "Tab-focussable paragraph just above " + inTree.id;
+				dojo.place(aPara, inTree.domNode, "before");
+				xtraParas.push(aPara);
+				aPara = dojo.doc.createElement("p");
+				dojo.attr(aPara, 'tabIndex', 0);
+				aPara.innerHTML = "Tab-focussable paragraph just below  " + inTree.id;
+				dojo.place(aPara, inTree.domNode, "after");
+				xtraParas.push(aPara);
+			};
+
+			var walkTreeToLeaf = function(inTree, inRootNode, /*array, optional*/ioPath){
+				var leaf = inRootNode;
+				if (ioPath){ ioPath.push(inRootNode); }
+				if(inRootNode.isExpandable){
+					forceLoadChildItems(inRootNode, inTree);
+					inTree._expandNode(inRootNode);
+					var down = inRootNode.getChildren()[0];
+					if(down){
+						leaf = walkTreeToLeaf(inTree, down, ioPath);
+					}
+				}
+				return(leaf);
+			};
+
+			that.tabFocusSetup = function(inTreeId, /*boolean*/ leaf){
+				var tree = dijit.byId(inTreeId);
+				that.collapseAllButRoot(tree);
+				addTabNavFoci(tree);
+				// set up focus listener machinery
+				focusCount = blurCount = 0;
+				var focusThing;
+				if(leaf){
+					focusThing = walkTreeToLeaf(tree, tree.rootNode);
+				}else if(tree.showRoot){
+					focusThing = tree.rootNode;
+				}else{
+					focusThing = tree.rootNode.getChildren()[0];
+				}
+				that.focusConnect = tree.connect(focusThing.labelNode, "onfocus", gotFocus);
+				that.blurConnect = tree.connect(focusThing.labelNode, "onblur", lostFocus);
+				tree.focusNode(focusThing);
+			};
+
+			that.tabFocusA11yTest = function(inTreeId){
+				var d = new doh.Deferred();
+				var tree = dijit.byId(inTreeId);
+				// shift+tab away, tab back, tab away, shift+tab back
+				doh.robot.keyPress(dojo.keys.TAB, 1000, {shift:true});
+				doh.robot.keyPress(dojo.keys.TAB, 300);
+				doh.robot.keyPress(dojo.keys.TAB, 300);
+				doh.robot.keyPress(dojo.keys.TAB, 300, {shift:true});
+				var checkTabNav = function(){
+					tree.disconnect(that.focusConnect);
+					tree.disconnect(that.blurConnect);
+					doh.is(3, focusCount,  tree.id + ": # of times focussed");
+					doh.is(2, blurCount, tree.id + ": # of times lost focus");
+				};
+				doh.robot.sequence(d.getTestCallback(checkTabNav), 500);
+				return d;
+			};
+
+			that.tabFocusTearDown = function(){
+				dojo.forEach(xtraParas, function(item){
+					item.parentNode.removeChild(item);
+				});
+				xtraParas.length = 0;
+				that.focusCount = 0;
+				that.blurCount = 0;
+			};
+
+			// arrow key navigation, expand, and collapse tests.
+			that.collapseAllButRoot = function(inTree){
+				function collapse(node){
+					if(node){
+						var children = node.getChildren();
+						dojo.forEach(children, function(child){
+							if(child.isExpandable){
+								collapse(child);
+								inTree._collapseNode(child);
+							}
+						});
+					}
+				}
+				if(inTree){
+					collapse(inTree.rootNode);
+				}
+			};
+
+			that.openConnect = null;
+			that.closeConnect = null;
+			var openedLabels = [];
+			var closedLabels = [];
+
+			that.a11yNavExpandCollapseSetup = function(inTreeId){
+				var tree = dijit.byId(inTreeId);
+				that.collapseAllButRoot(tree);
+				var startingNode = tree.showRoot ? tree.rootNode : tree.rootNode.getChildren()[0];
+				tree.focusNode(startingNode);
+				var rootChilds = tree.rootNode.getChildren();
+				// down, right (open), left (close), down, left (open)
+				if(tree.showRoot){
+					openedLabels[0] = { expected: rootChilds[0].label };
+					openedLabels[1] = { expected: rootChilds[1].label };
+				}else{
+					openedLabels[0] = { expected: rootChilds[1].label };
+					openedLabels[1] = { expected: rootChilds[2].label };
+				}
+				closedLabels[0] = openedLabels[0];
+				var openIdx = 0;
+				var collectOpen = function(item, node){
+					openedLabels[openIdx].actual = node.label;
+				};
+				var collectClose = function(item, node){
+					closedLabels[openIdx].actual = node.label;
+					openIdx++;
+				};
+				that.openConnect = dojo.connect(tree, "onOpen", collectOpen);
+				that.closeConnect = dojo.connect(tree, "onClose", collectClose);
+			};
+
+			that.a11yNavExpandCollapseTest = function(inTreeId){
+				var d = new doh.Deferred();
+				// assume (1) collapaseAllButRoot(), and (2) focus is on first visible child.
+				doh.robot.keyPress(dojo.keys.DOWN_ARROW, 1000);		// move down one
+				doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 300);		// expand
+				doh.robot.keyPress(dojo.keys.LEFT_ARROW, 300);		// collapse
+				doh.robot.keyPress(dojo.keys.DOWN_ARROW, 300);		// move down one
+				doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 300);		// expand
+				var checkKeystrokes = function(){
+					for(var idx = 0; idx < openedLabels.length; idx++){
+						doh.is(openedLabels[idx].expected, openedLabels[idx].actual, "onOpen");
+					}
+					for(idx = 0; idx < closedLabels.length; idx++){
+						doh.is(closedLabels[idx].expected, closedLabels[idx].actual, "onClose");
+					}
+				};
+				doh.robot.sequence(d.getTestCallback(checkKeystrokes), 500);
+				return d;
+			};
+
+			that.a11yNavExpandCollapseTearDown = function(){
+				dojo.disconnect(that.openConnect);
+				dojo.disconnect(that.closeConnect);
+			};
+
+			var expectedNode;
+			var actualNode;
+			var arrowDownCount;
+			var arrowRightCount;
+
+			that.a11yNavToLeafSetup = function(inTreeId){
+				var tree = dijit.byId(inTreeId);
+				// randomly choose a top-level node to traverse.
+				arrowDownCount = Math.floor(Math.random() * tree.rootNode.getChildren().length);
+				var path = [];
+				expectedNode = walkTreeToLeaf(tree, tree.rootNode.getChildren()[arrowDownCount], path);
+				that.collapseAllButRoot(tree);
+				if(tree.showRoot){
+					tree.focusNode(tree.rootNode);
+					arrowDownCount++;
+				}else{
+					tree.focusNode(tree.rootNode.getChildren()[0]);
+				}
+				// 1 to open root node, 2 for every non-leaf, 1 to get to the leaf
+				arrowRightCount = 1 + (path.length - 2)*2 + 1;
+				that.focusConnect = tree.connect(expectedNode.labelNode, "onfocus", function(evt){
+					actualNode = evt.target;
+				});
+			};
+
+			that.a11yNavToLeaf = function(inTreeId){
+				var d = new doh.Deferred();
+				var tree = dijit.byId(inTreeId);
+				// assume (1) collapseAllButRoot(), and (2) focus is on a top level tree node.
+				for(var i = 0; i < arrowDownCount; i++) {
+					doh.robot.keyPress(dojo.keys.DOWN_ARROW, 300);
+				}
+				for(i = 0; i < arrowRightCount; i++){
+					doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 300);
+				}
+				var checkLeaf = function(){
+					tree.disconnect(that.focusConnect);
+					doh.is(expectedNode.labelNode, actualNode, "expected: " + expectedNode.label + ", actual: " + actualNode.innerHTML);
+				};
+				doh.robot.sequence(d.getTestCallback(checkLeaf), 500);
+				return d;
+			};
+
+			that.lastVisibleNode = function(inTree){
+				var node = inTree.rootNode;
+				while(node.isExpanded){
+					var c = node.getChildren();
+					node = c[c.length-1];
+				}
+				return node;
+			};
+
+			that.a11yHomeEndKeySetup = function(inTreeId, inKey){
+				// put focus on an random leaf.
+				var tree = dijit.byId(inTreeId);
+				that.collapseAllButRoot(tree);
+				var topLvl = Math.floor(Math.random() * tree.rootNode.getChildren().length);
+				var leaf = walkTreeToLeaf(tree, tree.rootNode.getChildren()[topLvl]);
+				tree.focusNode(leaf);
+				// determine the expected/actual home.
+				if(inKey == dojo.keys.HOME){
+					expectedNode = ( tree.showRoot ? tree.rootNode : tree.rootNode.getChildren()[0] );
+				}else{
+					expectedNode = that.lastVisibleNode(tree);
+				}
+				focusConnect = tree.connect(expectedNode.labelNode, "onfocus", function(evt){
+					actualNode = evt.target;
+				});
+			};
+
+			that.a11yHomeEndKeyTest = function(inTreeId, inKey){
+				var d = new doh.Deferred();
+				var tree = dijit.byId(inTreeId);
+				doh.robot.keyPress(inKey, 300);
+				var checkAtHomeEnd = function(){
+					tree.disconnect(focusConnect);
+					doh.is(expectedNode.label, actualNode.innerHTML);
+				}
+				doh.robot.sequence(d.getTestCallback(checkAtHomeEnd), 500);
+				return d;
+			};
+
+			return that;
+		}
+
+		dojo.addOnLoad(function(){
+			doh.robot.initRobot('../test_Tree.html');
+			var treeTest = treeTests();
+
+			// aria role and properties tests.
+			doh.register("a11yAria",
+			[
+				function ariaTreeRole(){
+					for(i=0; i<treeIds.length; i++){
+						var tree = dijit.byId(treeIds[i]);
+						doh.is("tree", dijit.getWaiRole(tree.domNode), tree.id + ": aria role (tree)");
+					}
+				},
+
+				function ariaTreeStateExpanded(){
+					for(i=0; i<treeIds.length; i++){
+						var tree = dijit.byId(treeIds[i]);
+						var wasExpanded = tree.rootNode.isExpanded;
+						tree.rootNode.expand();
+						var nowExpanded = dijit.getWaiState(tree.domNode, "expanded");
+						tree.rootNode.collapse();
+						var nowCollapsed = dijit.getWaiState(tree.domNode, "expanded");
+						if(wasExpanded){
+							tree.rootNode.expand();
+						}
+						doh.is("true", nowExpanded, tree.id + ": aria state expanded=true");
+						doh.is("false", nowCollapsed, tree.id + ": aria state expanded=false ");
+					}
+				},
+
+				function ariaTreeItemRole(){
+					for(i=0; i<treeIds.length; i++){
+						var tree = dijit.byId(treeIds[i]);
+						treeTest.testTreeItemRole(tree.rootNode, tree);
+					}
+				},
+
+				function ariaTreeItemStateExpanded(){
+					for(i=0; i<treeIds.length; i++){
+						var tree = dijit.byId(treeIds[i]);
+						treeTest.testTreeItemExpandedState(tree.rootNode, tree);
+					}
+				}
+			]);
+
+			// Keyboard focus robot tests
+			doh.register("a11y tab navigation",
+			[
+				{
+					name:"mytreeTabFocusTest",
+					timeout:4000,
+					setUp:function(){
+						treeTest.tabFocusSetup('mytree', false);
+					},
+					runTest:function(){
+						return treeTest.tabFocusA11yTest('mytree');
+					},
+					tearDown:function(){
+						treeTest.tabFocusTearDown();
+					}
+				},
+				{
+					name:"tree2TabFocusTest",
+					timeout:4000,
+					setUp:function(){
+						treeTest.tabFocusSetup('tree2');
+					},
+					runTest:function(){
+						return treeTest.tabFocusA11yTest('tree2', false);
+					},
+					tearDown:function(){
+						treeTest.tabFocusTearDown();
+					}
+				},
+				{
+					name:"mytreeExpandedTabFocusTest",
+					timeout:4000,
+					setUp:function(){
+						treeTest.tabFocusSetup('mytree', true);
+					},
+					runTest:function(){
+						return treeTest.tabFocusA11yTest('mytree');
+					},
+					tearDown:function(){
+						treeTest.tabFocusTearDown();
+					}
+				},
+				{
+					name:"tree2ExpandedTabFocusTest",
+					timeout:4000,
+					setUp:function(){
+						treeTest.tabFocusSetup('tree2', true);
+					},
+					runTest:function(){
+						return treeTest.tabFocusA11yTest('tree2');
+					},
+					tearDown:function(){
+						treeTest.tabFocusTearDown();
+					}
+				}
+			]);
+
+			// Keyboard navigate/expand/collapse robot tests (arrow keys, and home/end)
+			doh.register("keyboard arrow navigation/expand/collapse",
+			[
+				{
+					name:"mytreeNavExpandCollpaseA11y",
+					timeout:4000,
+					setUp:function(){
+						treeTest.a11yNavExpandCollapseSetup('mytree');
+					},
+					runTest:function(){
+						return treeTest.a11yNavExpandCollapseTest('mytree');
+					},
+					tearDown: function(){
+						treeTest.a11yNavExpandCollapseTearDown();
+					}
+				},
+				{
+					name:"tree2NavExpandCollpaseA11y",
+					timeout:4000,
+					setUp:function(){
+						treeTest.a11yNavExpandCollapseSetup('tree2');
+					},
+					runTest:function(){
+						return treeTest.a11yNavExpandCollapseTest('tree2');
+					},
+					tearDown: function(){
+						treeTest.a11yNavExpandCollapseTearDown();
+					}
+				},
+				{
+					name:"mytreeNavToLeaf",
+					timeout:4000,
+					setUp:function(){
+						treeTest.a11yNavToLeafSetup('mytree');
+					},
+					runTest:function(){
+						return treeTest.a11yNavToLeaf('mytree');
+					}
+				},
+				{
+					name:"tree2NavToLeaf",
+					timeout:4000,
+					setUp:function(){
+						treeTest.a11yNavToLeafSetup('tree2');
+					},
+					runTest:function(){
+						return treeTest.a11yNavToLeaf('tree2');
+					}
+				},
+				{
+					name:"mytreeNavToHome",
+					timeout:4000,
+					setUp:function(){
+						treeTest.a11yHomeEndKeySetup('mytree', dojo.keys.HOME);
+					},
+					runTest:function(){
+						return treeTest.a11yHomeEndKeyTest('mytree', dojo.keys.HOME);
+					}
+				},
+				{
+					name:"mytreeNavToEnd",
+					timeout:4000,
+					setUp:function(){
+						treeTest.a11yHomeEndKeySetup('mytree', dojo.keys.END);
+					},
+					runTest:function(){
+						return treeTest.a11yHomeEndKeyTest('mytree', dojo.keys.END);
+					}
+				},
+				{
+					name:"tree2NavToHome",
+					timeout:4000,
+					setUp:function(){
+						treeTest.a11yHomeEndKeySetup('tree2', dojo.keys.HOME);
+					},
+					runTest:function(){
+						return treeTest.a11yHomeEndKeyTest('tree2', dojo.keys.HOME);
+					}
+				},
+				{
+					name:"tree2NavToEnd",
+					timeout:4000,
+					setUp:function(){
+						treeTest.a11yHomeEndKeySetup('tree2', dojo.keys.END);
+					},
+					runTest:function(){
+						return treeTest.a11yHomeEndKeyTest('tree2', dojo.keys.END);
+					}
+				}
+			]);
+
+			// Test for typing "a" to navigate to nodes that start with "a", etc.
+			doh.register("keyboard search tests",
+			[
+				{
+					name:"Setup tree",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var tree = dijit.byId("mytree");
+
+						// Close all tree nodes except for Asia and Oceania
+						dojo.forEach(tree.rootNode.getChildren(), function(child, idx){
+							if(child.label == "Asia" || child.label == "Oceania"){
+								console.log("expanding " + child.label);
+								if(!child.isExpanded){
+									tree._expandNode(child);
+								}
+							}else{
+								console.log("collapsing " + child.label);
+								if(child.isExpanded){
+									tree._collapseNode(child);
+								}
+							}
+						});
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							// Just waiting for animation to finish...
+						}), 500);
+
+						return d;
+					}
+				},
+				{
+					name:"Focus on Continents",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var tree = dijit.byId("mytree");
+						tree.focusNode(tree.rootNode);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							var focus = dojo.global.dijit._curFocus;
+							doh.t(tree.rootNode.labelNode, "focused on continents");
+						}), 500);
+
+						return d;
+					}
+				},
+				{
+					name:"First 'A' key goes to Africa",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						// From Continents node, press "A".   Should go to Africa.
+						doh.robot.keyPress("a", 100);
+						doh.robot.sequence(d.getTestCallback(function(){
+							var focus = dijit.getEnclosingWidget(dojo.global.dijit._curFocus);
+							doh.t(focus, "there is a focused widget");
+							doh.is("Africa", focus.label);
+						}), 500);
+
+						return d;
+					}
+				},
+				{
+					name:"Second 'A' key goes to Asia",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						// From Africa node, press "A" again.   Should go to Asia.
+						doh.robot.keyPress("a", 100);
+						doh.robot.sequence(d.getTestCallback(function(){
+							var focus = dijit.getEnclosingWidget(dojo.global.dijit._curFocus);
+							doh.t(focus, "there is a focused widget");
+							doh.is("Asia", focus.label);
+						}), 500);
+
+						return d;
+					}
+				},
+				{
+					name:"Third 'A' key goes to Australia (nested node)",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var oceania = dijit.byId("mytree").rootNode.getChildren()[2];
+						doh.t(oceania, "found Oceania node");
+						doh.t(oceania.isExpanded, "Oceania node is expanded");
+
+						doh.robot.keyPress("a", 100);
+						doh.robot.sequence(d.getTestCallback(function(){
+							var focus = dijit.getEnclosingWidget(dojo.global.dijit._curFocus);
+							doh.t(focus, "there is a focused widget");
+							doh.is("Australia", focus.label);
+						}), 500);
+
+						return d;
+					}
+				},
+				{
+					name:"Fourth 'A' key loops back to Africa",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						doh.robot.keyPress("a", 100);
+						doh.robot.sequence(d.getTestCallback(function(){
+							var focus = dijit.getEnclosingWidget(dojo.global.dijit._curFocus);
+							doh.t(focus, "there is a focused widget");
+							doh.is("Africa", focus.label);
+						}), 500);
+
+						return d;
+					}
+				},
+				{
+					name:"multi-key navigation",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						// Skip over China and go to Continents
+						doh.robot.typeKeys("co", 100);
+						doh.robot.sequence(d.getTestCallback(function(){
+							var focus = dijit.getEnclosingWidget(dojo.global.dijit._curFocus);
+							doh.t(focus, "there is a focused widget");
+							doh.is("Continents", focus.label);
+						}), 500);
+
+						return d;
+					}
+				},
+				{
+					name:"multi-key navigation",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						// By typing AS should skip over Africa and go to Asia
+						doh.robot.typeKeys("as", 100);
+						doh.robot.sequence(d.getTestCallback(function(){
+							var focus = dijit.getEnclosingWidget(dojo.global.dijit._curFocus);
+							doh.t(focus, "there is a focused widget");
+							doh.is("Asia", focus.label);
+						}), 500);
+
+						return d;
+					}
+				},
+				{
+					name:"multi-key navigation clears",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						// After the 500ms delay from above, typing a new character should
+						// start a new search
+						doh.robot.typeKeys("n", 100);
+						doh.robot.sequence(d.getTestCallback(function(){
+							var focus = dijit.getEnclosingWidget(dojo.global.dijit._curFocus);
+							doh.t(focus, "there is a focused widget");
+							doh.is("North America", focus.label);
+						}), 500);
+
+						return d;
+					}
+				}
+			]);
+
+			doh.register("selection and focus",
+			[
+				{
+					name:"select Africa",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var tree = dijit.byId("mytree");
+
+						doh.robot.keyPress(dojo.keys.HOME, 300);			// go to Continents
+						doh.robot.keyPress(dojo.keys.LEFT_ARROW, 300);		// collapse tree, if it's open
+						doh.robot.keyPress(dojo.keys.RIGHT_ARROW, 300);		// expand
+						doh.robot.keyPress(dojo.keys.DOWN_ARROW, 300);		// move down to Africa
+						doh.robot.keyPress(dojo.keys.ENTER, 300);			// select it
+						
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.is("Africa", tree.lastFocused.label, "Africa is focused");
+
+							var item = tree.get("selectedItem"),
+								label = tree.model.getLabel(item);
+							doh.is("Africa", label, "Africa is selected");
+						}), 500);
+
+						return d;
+					}
+				},
+
+				{
+					name:"focus Asia",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var tree = dijit.byId("mytree");
+
+						if(tree.lastFocused.isExpanded){
+							doh.robot.keyPress(dojo.keys.LEFT_ARROW, 300);		// collapse tree, if it's open
+						}
+						doh.robot.keyPress(dojo.keys.DOWN_ARROW, 300);		// move down to Asia
+						
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.is("Asia", tree.lastFocused.label, "Asia is focused");
+
+							var item = tree.get("selectedItem"),
+								label = tree.model.getLabel(item);
+							doh.is("Africa", label, "but Africa is still selected");
+						}), 500);
+
+						return d;
+					}
+				},
+
+				{
+					name:"select Asia",
+					timeout:4000,
+					runTest:function(){
+						var d = new doh.Deferred();
+
+						var tree = dijit.byId("mytree");
+
+						doh.robot.keyPress(dojo.keys.ENTER, 300);			// select it
+						
+						doh.robot.sequence(d.getTestCallback(function(){
+							var item = tree.get("selectedItem"),
+								label = tree.model.getLabel(item);
+							doh.is("Asia", label, "after ENTER focus shifted from Africa to Asia");
+						}), 500);
+
+						return d;
+					}
+				}
+			]);
+
+			doh.run();
+		});
+
+	</script>
+</head>
+</html>
+
diff --git a/dijit/tests/robot/Tree_dnd.html b/dijit/tests/robot/Tree_dnd.html
new file mode 100644
index 0000000..f2c8273
--- /dev/null
+++ b/dijit/tests/robot/Tree_dnd.html
@@ -0,0 +1,340 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Tree DnD Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+		<script type="text/javascript" src="Tree_dnd.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../tree/test_Tree_DnD.html');
+
+				doh.register("setup", {
+					name: "setup",
+					timeout: 20000,
+					setUp: function(){
+						setup();
+					}
+				});
+
+				// Dragging from an external source and dropping onto the Tree,
+				// creating a duplicate of the dragged item
+				doh.register("drop into", [
+					{
+						name: "drag 'Apple' over 'Fruits'",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							// Find the fruitsTreeNode category
+							var fruitsTreeNode = findTreeNode("itemTree", "Fruits");
+							doh.f(fruitsTreeNode.isExpanded, "fruitsTreeNode is initially closed");
+							doh.t(fruitsTreeNode.isExpandable, "but has (or may have) children");
+
+							// Check state of store too
+							var children = getNamesOfChildrenOfItem("Fruits");
+							doh.is(1, children.categories.length, "one category child");
+							doh.is("Citrus", children.categories[0]);
+							doh.is(0, children.items.length, "no item children yet");
+
+							// (Try to) make sure drag source and drop source are both in viewport
+							dojo.window.scrollIntoView(fruitsTreeNode.domNode);
+
+							// Drag "Apple" onto Fruits.
+							doh.robot.mouseMoveAt("1001", 0, 1000);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt(fruitsTreeNode.labelNode, 500, 2000);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// TODO: check drag avatar shows drop is valid (ie, avatar is green)
+								doh.t(dojo.hasClass(fruitsTreeNode.rowNode, "dijitTreeRowHover"), "tree node has hover class");
+								doh.t(dojo.hasClass(fruitsTreeNode.rowNode, "dojoDndItemOver"), "tree node has DND drop class");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "drop 'Apple' on to 'Fruits'",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							doh.robot.mouseRelease({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Check that new item was created and added to the store.
+								var children = getNamesOfChildrenOfItem("Fruits");
+								doh.is(1, children.categories.length, "one category child");
+								doh.is("Citrus", children.categories[0]);
+								doh.is(1, children.items.length, "one item child");
+								doh.is("Apple", children.items[0]);
+
+								// Check that data store update was reflected in the tree
+								var fruitsTreeNode = findTreeNode("itemTree", "Fruits");
+
+								doh.t(fruitsTreeNode.isExpanded, "drop caused the node to expand");
+								var treeNodeChildren = fruitsTreeNode.getChildren();
+								doh.is(2, treeNodeChildren.length, "2 TreeNode children")
+								doh.is("Apple", innerText(treeNodeChildren[0].labelNode));
+								doh.is("Citrus", innerText(treeNodeChildren[1].labelNode));
+							}), 1000);	// 1000ms to wait for 'Fruits' node to expand and show 'Apple' node
+
+							return d;
+						}
+					}
+				]);
+
+				// Moving an item w/in the tree
+				doh.register("re-parent an item", [
+					{
+						name: "drag 'Apple' from 'Fruits' to 'Citrus'",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var fruitsTreeNode = findTreeNode("itemTree", "Fruits");
+								appleTreeNode = findTreeNode("itemTree", "Apple"),
+								citrusTreeNode = findTreeNode("itemTree", "Citrus");
+
+							// Drag "Apple" into Citrus .
+							doh.robot.mouseMoveAt(appleTreeNode.labelNode, 0, 500);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt(citrusTreeNode.labelNode, 500, 1000);
+							doh.robot.mouseMoveAt(citrusTreeNode.labelNode, 500, 1000);// If prev. mouseMove caused scroll, readjust
+							doh.robot.mouseRelease({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var myStore = dojo.global.myStore;
+
+								// Check that data store item was orphaned from Fruits
+								var fruitsItemChildren = getNamesOfChildrenOfItem("Fruits");
+								doh.is(0, fruitsItemChildren.items.length, "no item children");
+
+								// Check that data store update was reflected in the tree
+								var fruitsTreeNode = findTreeNode("itemTree", "Fruits");
+
+								var fruitsTreeNodeChildren = fruitsTreeNode.getChildren();
+								doh.is(1, fruitsTreeNodeChildren.length, "1 TreeNode children")
+								doh.is("Citrus", innerText(fruitsTreeNodeChildren[0].labelNode));
+
+								// ... and parented to Citrus item
+								var citrusItemChildren = getNamesOfChildrenOfItem("Citrus");
+								doh.is(2, citrusItemChildren.items.length, "two item children");
+								doh.is("Orange", citrusItemChildren.items[0]);
+								doh.is("Apple", citrusItemChildren.items[1]);
+
+								// Check that data store update was reflected in the tree
+								var citrusTreeNode = findTreeNode("itemTree", "Citrus");
+
+								var citrusTreeNodeChildren = citrusTreeNode.getChildren();
+								doh.is(2, citrusTreeNodeChildren.length, "2 TreeNode children for Citrus")
+								doh.is("Orange", innerText(citrusTreeNodeChildren[0].labelNode), "child of Citrus TreeNode");
+								doh.is("Apple", innerText(citrusTreeNodeChildren[1].labelNode), "child of Citrus TreeNode");
+							}), 2000);
+
+							return d;
+						}
+					},
+
+					{
+						name: "drag 'Cereals' to be before 'Vegetables' (reordering)",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var vegetablesTreeNode = findTreeNode("collectionsTree", "Vegetables (0)"),
+								cerealsTreeNode = findTreeNode("collectionsTree", "Cereals (0)");
+
+							// (Try to) make sure drag source and drop source are both in viewport
+							dojo.window.scrollIntoView(cerealsTreeNode.domNode);
+
+							// Drag 'Cereals' and drop near top edge of 'Vegetables'.
+							// It should become Vegetables' prior-sibling
+							doh.robot.mouseMoveAt(cerealsTreeNode.domNode, 500, 1000);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt(vegetablesTreeNode.domNode, 500, 1000, 50, 2);
+							doh.robot.mouseRelease({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var myStore = dojo.global.myStore;
+
+								// Check that order of children was changed
+								var foodsItemChildren = getNamesOfChildrenOfItem("Foods").categories;
+								doh.is(3, foodsItemChildren.length, "3 categories");
+								doh.is("Fruits", foodsItemChildren[0]);
+								doh.is("Cereals", foodsItemChildren[1]);
+								doh.is("Vegetables", foodsItemChildren[2]);
+
+								// Check that data store update was reflected in the tree
+								var foodsTreeNode = findTreeNode("collectionsTree", "Foods (1)"),
+									foodsTreeNodeChildren = foodsTreeNode.getChildren();
+								doh.is(3, foodsTreeNodeChildren.length, "3 TreeNode children")
+								doh.is("Fruits (2)", innerText(foodsTreeNodeChildren[0].labelNode));
+								doh.is("Cereals (0)", innerText(foodsTreeNodeChildren[1].labelNode));
+								doh.is("Vegetables (0)", innerText(foodsTreeNodeChildren[2].labelNode));
+							}), 2000);
+
+							return d;
+						}
+					},
+
+					// We need to expand the Fruits TreeNode for the benefit of the next test,
+					// and we do it as a separate test so that citrusTreeNode will exist etc.
+					// by the time the next test starts.
+					{
+						name: "expand 'Fruits' TreeNode",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var fruitsTreeNode = findTreeNode("collectionsTree", "Fruits (2)");
+							doh.robot.mouseMoveAt(fruitsTreeNode.expandoNode, 500, 1000);
+							doh.robot.mouseClick({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// This is just here to wait for the expand operation to take place,
+								// and then notify DOH that we are finished
+							}), 1000);
+							return d;
+						}
+					},
+
+					{
+						name: "drag 'Vegetables' to be after 'Citrus' (reordering)",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var vegetablesTreeNode = findTreeNode("collectionsTree", "Vegetables (0)"),
+								citrusTreeNode = findTreeNode("collectionsTree", "Citrus (1)"),
+								citrusTreeNodeSize = dojo.contentBox(citrusTreeNode.domNode);
+
+							// (Try to) make sure drag source and drop source are both in viewport
+							dojo.window.scrollIntoView(vegetablesTreeNode.domNode);
+
+							// Drag 'Vegetables' and drop near bottom edge of 'Citrus'.
+							// It should become Citrus' prior-sibling
+							doh.robot.mouseMoveAt(vegetablesTreeNode.domNode, 500, 1000);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt(citrusTreeNode.domNode, 1000, 2000, 50, citrusTreeNodeSize.h - 2);
+							doh.robot.mouseRelease({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var myStore = dojo.global.myStore;
+
+								// Check that order of children in data store was changed
+								var foodsItemChildren = getNamesOfChildrenOfItem("Foods").categories;
+								doh.is(2, foodsItemChildren.length, "2 categories under foods");
+								doh.is("Fruits", foodsItemChildren[0]);
+								doh.is("Cereals", foodsItemChildren[1]);
+
+								var fruitsItemChildren = getNamesOfChildrenOfItem("Fruits").categories;
+								doh.is(2, fruitsItemChildren.length, "2 categories under fruits");
+								doh.is("Citrus", fruitsItemChildren[0]);
+								doh.is("Vegetables", fruitsItemChildren[1]);
+
+								// Check that data store update was reflected in the tree
+								var foodsTreeNode = findTreeNode("collectionsTree", "Foods (1)"),
+									foodsTreeNodeChildren = foodsTreeNode.getChildren();
+								doh.is(2, foodsTreeNodeChildren.length, "2 TreeNode children for foods")
+								doh.is("Fruits (2)", innerText(foodsTreeNodeChildren[0].labelNode));
+								doh.is("Cereals (0)", innerText(foodsTreeNodeChildren[1].labelNode));
+
+								var fruitsTreeNode = findTreeNode("collectionsTree", "Fruits (2)"),
+								fruitsTreeNodeChildren = fruitsTreeNode.getChildren();
+								doh.is(2, fruitsTreeNodeChildren.length, "2 TreeNode children for fruits")
+								doh.is("Citrus (1)", innerText(fruitsTreeNodeChildren[0].labelNode));
+								doh.is("Vegetables (0)", innerText(fruitsTreeNodeChildren[1].labelNode));
+							}), 500);
+
+							return d;
+						}
+					}
+
+				]);
+
+				doh.register("drag between trees", [
+					{
+						name: "move 'Vegetables' from left tree to right tree, from 'Fruits' to 'Foods'",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var vegetablesTreeNode = findTreeNode("collectionsTree", "Vegetables (0)");
+								foodsTreeNode = dijit.byId("itemTree").rootNode;
+
+							doh.robot.mouseMoveAt(vegetablesTreeNode.labelNode, 0, 500);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt(foodsTreeNode.labelNode, 500, 1000);
+							doh.robot.mouseRelease({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var myStore = dojo.global.myStore;
+
+								// Check that data store item was orphaned from Fruits
+								var fruitsItemChildren = getNamesOfChildrenOfItem("Fruits");
+								doh.is(1, fruitsItemChildren.categories.length, "one fruits child");
+								doh.is("Citrus", fruitsItemChildren.categories[0], "one fruits child");
+
+								// And added to Foods
+								var foodsItemChildren = getNamesOfChildrenOfItem("Foods");
+								doh.is(3, foodsItemChildren.categories.length, "three foods children");
+								doh.is("Fruits", foodsItemChildren.categories[0], "food child");
+								doh.is("Cereals", foodsItemChildren.categories[1], "food child");
+								doh.is("Vegetables", foodsItemChildren.categories[2], "food child");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("drop in Tree outside of a treeNode", [
+					{
+						name: "drop 'Orange' within Tree but not over a TreeNode",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var orangeTreeNode = findTreeNode("itemTree", "Orange");
+
+							doh.robot.mouseMoveAt(orangeTreeNode.labelNode, 0, 500);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseRelease({left: true}, 500);
+
+							doh.robot.mouseMoveAt("itemTree", 0, 500, 5, 50);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt("itemTree", 0, 500, 5, 100);
+							doh.robot.mouseRelease({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								var org = findTreeNode("itemTree", "Orange");
+								doh.t( org != null);
+							}), 500);
+							return d;
+						}
+					}
+				]);
+
+				// TODO: test icon and highlighting when valid drop target and invalid target (another item)
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/Tree_dnd.js b/dijit/tests/robot/Tree_dnd.js
new file mode 100644
index 0000000..da82a08
--- /dev/null
+++ b/dijit/tests/robot/Tree_dnd.js
@@ -0,0 +1,103 @@
+/*
+ * Helper functions for Tree_dnd.html and Tree_dnd_multiParent.html tests
+ */
+
+function setup(){
+	// Disable auto-scrolling because otherwise the viewport scrolls as doh.robot.mouseMoveAt()
+	// moves the mouse, literally making the the drop target a moving target
+	// (and mouseMoveAt() doesn't take this possibility into account).
+	dojo.global.dojo.dnd.autoScrollNodes = function(){};
+
+	// Scroll viewport to (try to) make sure that both tree and drag-source
+	// are simultaneously in view.
+	var scroll = dojo.position("1001").y;
+	dojo.body().parentNode.scrollTop = scroll;	// works on FF
+	dojo.body().scrollTop = scroll;	// works on safari
+}
+
+function findTreeNode(/*String*/ treeId, /*String*/ label){
+	// summary:
+	//		Find the TreeNode with the specified label in the given tree.
+	//		Assumes that there's only one TreeNode w/that label (i.e. it
+	//		breaks if certain items have multiple parents and appear in the
+	//		tree multiple times)
+	var nodes = dojo.query(".dijitTreeLabel", treeId);
+	for(var i=0; i<nodes.length; i++){
+		if(innerText(nodes[i]) == label){
+			return dijit.getEnclosingWidget(nodes[i]);	// TreeNode
+		}
+	}
+	return null;
+}
+
+function findTreeNodeByPath(/*String*/ treeId, /*String[] */ path){
+	// summary:
+	//		Find the TreeNode with the specified path (like ["Fruits", "Apple"] in a tree like:
+	//	|	* Foods
+	//	|		* Vegetbles
+	//	|		* Fruits
+	//	|			* Orange
+	//	|			* Apple
+	//		Path shouldn't include the root node.
+
+	var tree = dijit.byId(treeId);
+	for(var i=0, node=tree.rootNode; i<path.length; i++){
+		var pathElem = path[i], matchingChildNode;
+		for(var j=0, children=node.getChildren(); j < children.length; j++){
+			if(children[j].label == pathElem){
+				matchingChildNode = children[j];
+				break;
+			}
+		}
+		if(!matchingChildNode){
+			return null;
+		}
+		node = matchingChildNode;
+	}
+	return node;
+}
+
+function getChildrenOfItem(/*String*/ name){
+	// summary:
+	//		Return the children of the data store item w/the specified name
+	//		Note that test_Tree_Dnd.html splits the children up into the "children"
+	//		and "items" attributes.
+
+	// Get the parent item
+	// Note that the ItemFileWriteStore's callback will happen immediately.
+	var myStore = dojo.global.myStore,
+		parentItem;
+	myStore.fetch({
+		query: {name: name},
+		onItem: function(item){ parentItem = item; }
+	});
+
+	// Get the children, which are stored in two separate attributes,
+	// categories (like 'Fruits') and items (ie, leaf nodes)  (like 'Apple')
+	return {
+		categories: myStore.getValues(parentItem, 'children'),
+		items: myStore.getValues(parentItem, 'items')
+	};
+}
+
+function mapItemsToNames(ary){
+	// summary:
+	//		Convert an array of items into an array of names
+	var myStore = dojo.global.myStore;
+	return dojo.map(ary, function(item){
+		return myStore.getValue(item, "name");
+	});
+}
+
+function getNamesOfChildrenOfItem(/*String*/ name){
+	// summary:
+	//		Return the names of the (items that are) children of the item w/the specified name
+
+	// Get the parent item (according to
+	var obj = getChildrenOfItem(name);
+	return {
+		categories: mapItemsToNames(obj.categories),
+		items: mapItemsToNames(obj.items)
+	};
+}
+
diff --git a/dijit/tests/robot/Tree_dnd_multiParent.html b/dijit/tests/robot/Tree_dnd_multiParent.html
new file mode 100644
index 0000000..2c5ab14
--- /dev/null
+++ b/dijit/tests/robot/Tree_dnd_multiParent.html
@@ -0,0 +1,273 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Tree DnD Multi-parent Test</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../helpers.js"></script>
+		<script type="text/javascript" src="Tree_dnd.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.window");
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../tree/test_Tree_DnD.html');
+
+				doh.register("setup", {
+					name: "setup",
+					timeout: 20000,
+					setUp: function(){
+						setup();
+					}
+				});
+
+				doh.register("multi-parent tests", [
+					{
+						name: "add 'Fruits' as parent of vegetables",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var vegetablesTreeNode = findTreeNodeByPath("collectionsTree", ["Vegetables (0)"]),	// the left tree
+								foodsTreeNode = dijit.byId("itemTree").rootNode,								// right tree
+								fruitsTreeNode = findTreeNodeByPath("itemTree", ["Fruits"]);					// right tree
+
+							// (Try to) make sure drag source and drop source are both in viewport
+							dojo.window.scrollIntoView(fruitsTreeNode.domNode);
+
+							// Drag and Drop, *copying* in order to add a parent rather than change
+							doh.robot.mouseMoveAt(vegetablesTreeNode.domNode, 500, 1000);
+							doh.robot.keyDown(dojo.keys.copyKey, 500);
+							if(dojo.isMac){
+								// I can't get DOH robot to generate the mousePress event w/metaKey=true so
+								// hack it
+								doh.robot.sequence(function(){
+									realIsCopyKey = dojo.global.dojo.isCopyKey;
+									dojo.global.dojo.isCopyKey = function(){ return true; }
+								});
+							}
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt(fruitsTreeNode.labelNode, 500, 2000);
+							doh.robot.mouseRelease({left: true}, 500);
+							doh.robot.keyUp(dojo.keys.copyKey, 500);
+							if(dojo.isMac){
+								// See if(dojo.isMac) above
+								doh.robot.sequence(function(){
+									dojo.global.dojo.isCopyKey = realIsCopyKey;
+								});
+							}
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Check that Vegetables remains a child of Foods
+								var children = getNamesOfChildrenOfItem("Foods");
+								doh.is(3, children.categories.length, "foods category child");
+								doh.is("Fruits", children.categories[0]);
+								doh.is("Vegetables", children.categories[1]);
+								doh.is("Cereals", children.categories[2]);
+
+								// Check that Vegetables added as child of Fruits
+								var children = getNamesOfChildrenOfItem("Fruits");
+								doh.is(2, children.categories.length, "foods category child");
+								doh.is("Citrus", children.categories[0]);
+								doh.is("Vegetables", children.categories[1]);
+
+								// Check that new item *wasn't* created
+								var items;
+								dojo.global.myStore.fetch({
+									onComplete: function(i){ items = i; }
+								});
+								doh.is(6, items.length, "# of items in store");
+
+								// Check that data store update was reflected in the tree
+								doh.t(fruitsTreeNode.isExpanded, "drop caused the node to expand");
+								var treeNodeChildren = fruitsTreeNode.getChildren();
+								doh.is(2, treeNodeChildren.length, "2 TreeNode children")
+								doh.is("Citrus", innerText(treeNodeChildren[0].labelNode));
+								doh.is("Vegetables", innerText(treeNodeChildren[1].labelNode));
+							}), 1000);	// 1000ms to wait for 'Fruits' node to expand and show 'Apple' node
+
+							return d;
+						}
+					},
+					{
+						name: "move Foods/Vegetables to Foods/Cereal/Vegetables",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var vegetablesTreeNode = findTreeNodeByPath("itemTree", ["Vegetables"]),
+								cerealsTreeNode = findTreeNodeByPath("itemTree", ["Cereals"]);
+
+							// (Try to) make sure drag source and drop source are both in viewport
+							dojo.window.scrollIntoView(cerealsTreeNode.domNode);
+
+							// Drag and Drop
+							doh.robot.mouseMoveAt(vegetablesTreeNode.domNode, 0, 1000);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt(cerealsTreeNode.labelNode, 500, 1000);
+							doh.robot.mouseRelease({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Check that Vegetables remains a child of Fruits
+								var children = getNamesOfChildrenOfItem("Fruits");
+								doh.is(2, children.categories.length, "fruits category child");
+								doh.is("Citrus", children.categories[0]);
+								doh.is("Vegetables", children.categories[1]);
+
+								// Check that Vegetables added as child of Cereals
+								children = getNamesOfChildrenOfItem("Cereals");
+								doh.is(1, children.categories.length, "cereals category child");
+								doh.is("Vegetables", children.categories[0]);
+
+								// Check that Vegetables no longer a child of Foods
+								children = getNamesOfChildrenOfItem("Foods");
+								doh.is(2, children.categories.length, "foods category child");
+								doh.is("Fruits", children.categories[0]);
+								doh.is("Cereals", children.categories[1]);
+
+								// Check that new item *wasn't* created
+								var items;
+								dojo.global.myStore.fetch({
+									onComplete: function(i){ items = i; }
+								});
+								doh.is(6, items.length, "# of items in store");
+							}), 1000);	// 1000ms to wait for 'Fruits' node to expand and show 'Apple' node
+
+							return d;
+						}
+					},
+					{
+						name: "move Fruits/Vegetables to Fruits/Citrus",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var vegetablesTreeNode = findTreeNodeByPath("itemTree", ["Fruits", "Vegetables"]),
+								citrusTreeNode = findTreeNodeByPath("itemTree", ["Fruits", "Citrus"]);
+
+							// (Try to) make sure drag source and drop source are both in viewport
+							dojo.window.scrollIntoView(vegetablesTreeNode.domNode);
+
+							// Drag and Drop
+							doh.robot.mouseMoveAt(vegetablesTreeNode.domNode, 0, 1000);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt(citrusTreeNode.labelNode, 500, 1000);
+							doh.robot.mouseRelease({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								// Check that Vegetables remains a child of Cereals
+								var children = getNamesOfChildrenOfItem("Cereals");
+								doh.is(1, children.categories.length, "cereals category child");
+								doh.is("Vegetables", children.categories[0]);
+
+								// Check that Vegetables added as child of Citrus
+								children = getNamesOfChildrenOfItem("Citrus");
+								doh.is(1, children.categories.length, "citrus category child");
+								doh.is("Vegetables", children.categories[0]);
+								doh.is(1, children.items.length, "citrus item child");
+								doh.is("Orange", children.items[0]);
+
+								// Check that Vegetables removed as child of Fruits
+								children = getNamesOfChildrenOfItem("Fruits");
+								doh.is(1, children.categories.length, "fruits category child");
+								doh.is("Citrus", children.categories[0]);
+
+								// Check that new item *wasn't* created
+								var items;
+								dojo.global.myStore.fetch({
+									onComplete: function(i){ items = i; }
+								});
+								doh.is(6, items.length, "# of items in store");
+							}), 1000);	// 1000ms to wait for 'Fruits' node to expand and show 'Apple' node
+
+							return d;
+						}
+					}
+				]);
+
+				doh.register("external drop tests", [
+					{
+						name: "drop banana on fruits",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var fruitsTreeNode = findTreeNodeByPath("itemTree", ["Fruits"]);					// right tree
+
+							doh.robot.mouseMoveAt(dojo.byId("1003"), 500, 1000);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt(fruitsTreeNode.labelNode, 500, 2000);
+							doh.robot.mouseRelease({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+
+								var children = getChildrenOfItem("Fruits");
+								doh.is(1, children.items.length, "new item added");
+								doh.is(1003, children.items[0].id, "id of new item came from dropped node");
+								doh.is("Banana", children.items[0].name, "name of new item came from dropped node");
+
+								dojo.global.myStore.fetch({
+									query: { name: "Banana" },
+									queryOptions: { deep: true },
+									onComplete: function(i){ items = i; }
+								});
+								doh.is(1, items.length, "1 banana item in store");
+							}), 1000);
+
+							return d;
+						}
+					},
+					{
+						name: "drop banana on cereal",
+						timeout: 10000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							var cerealsTreeNode = findTreeNodeByPath("itemTree", ["Cereals"]);					// right tree
+
+							doh.robot.mouseMoveAt(dojo.byId("1003"), 500, 1000);
+							doh.robot.mousePress({left: true}, 500);
+							doh.robot.mouseMoveAt(cerealsTreeNode.labelNode, 500, 2000);
+							doh.robot.mouseRelease({left: true}, 500);
+
+							doh.robot.sequence(d.getTestCallback(function(){
+
+								var children = getChildrenOfItem("Cereals");
+								doh.is(1, children.items.length, "banana is child of cereals");
+								doh.is(1003, children.items[0].id, "id of item came from dropped node");
+								doh.is("Banana", children.items[0].name, "name of new item came from dropped node");
+
+								var children = getChildrenOfItem("Fruits");
+								doh.is(1, children.items.length, "banana still a child of fruits");
+								doh.is(1003, children.items[0].id, "id of new item came from dropped node");
+								doh.is("Banana", children.items[0].name, "name of new item came from dropped node");
+
+								dojo.global.myStore.fetch({
+									query: { name: "Banana" },
+									queryOptions: { deep: true },
+									onComplete: function(i){ items = i; }
+								});
+								doh.is(1, items.length, "1 banana item in store (with 2 parents)");
+							}), 1000);
+
+							return d;
+						}
+					}
+
+				]);
+
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dijit/tests/robot/_Widget-deferredConnect.html b/dijit/tests/robot/_Widget-deferredConnect.html
new file mode 100644
index 0000000..779b891
--- /dev/null
+++ b/dijit/tests/robot/_Widget-deferredConnect.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>doh.robot deferred connect tests</title>
+
+	<style>
+		@import "../../../../util/doh/robot/robot.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true"></script>
+
+	<!-- functions to help test -->
+	<script type="text/javascript" src="../helpers.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");
+
+		dojo.addOnLoad(function(){
+
+			doh.robot.initRobot('../_Widget-deferredConnect.html');
+
+			// Test that deferred connections get set up correctly when they need to be
+			// (_Widget only does the dojo.connect() for onmousemove if it needs to)
+			doh.register("deferredConnect",
+			[
+				{
+					name: "mouse move on widget where onmousemove overridden",
+					timeout: 5000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						doh.robot.mouseMoveAt("overrode", 500);
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.t(dojo.global.overrodeMouseMoved, "overrode button event handler fired");
+						}), 500);
+						return d;
+					}
+				},
+				{
+					name: "mouse move on widget where onmousemove connected",
+					timeout: 5000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						doh.robot.mouseMoveAt("connect", 500);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.t(dojo.global.connectedMouseMoved, "connected button event handler fired");
+						}), 500);
+						return d;
+					}
+				},
+				{
+					name: "mouse move on widget where onmousemove overridden and connected",
+					timeout: 5000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						doh.robot.mouseMoveAt("both", 500);
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.t(dojo.global.bothOverrodeMouseMoved, "dojo/method handler fired");
+							doh.t(dojo.global.bothConnectedMouseMoved, "dojo/connect handler fired");
+						}), 500);
+						return d;
+					}
+				}
+			]);
+
+			doh.run();
+		});
+	</script>
+</head>
+</html>
diff --git a/dijit/tests/robot/_Widget-ondijitclick_a11y.html b/dijit/tests/robot/_Widget-ondijitclick_a11y.html
new file mode 100644
index 0000000..8abc73e
--- /dev/null
+++ b/dijit/tests/robot/_Widget-ondijitclick_a11y.html
@@ -0,0 +1,166 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Test Dijit Internal Event: "ondijitclick"</title>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");
+
+		dojo.addOnLoad(function(){
+			doh.robot.initRobot('../_Widget-ondijitclick.html');
+
+			// Event monitoring
+			var widgetClicks = 0, buttonClicks = 0, button2Clicks = 0, thirdClicks = 0;
+			var w;
+
+			doh.register("setup", function(){
+				doh.robot.sequence(function(){
+					w = dijit.byId("first");
+					dojo.connect(w, "_onClick", function(){
+						widgetClicks++;
+					});
+					dojo.connect(dojo.byId("plainbutton"), "onclick", function(){
+						buttonClicks++;
+					});
+					dojo.connect(dojo.byId("button2"), "onclick", function(){
+						button2Clicks++;
+					});
+					dojo.connect(dojo.byId("third"), "onclick", function(){
+						thirdClicks++;
+					});
+				});
+			});
+
+			// Test ondijitclick on a <div> which refocuses onto a native <button> node.
+			// Make sure that the <button> doesn't get a spurious click event.
+			dojo.forEach(["SPACE", "ENTER"], function(key){
+
+				doh.register("ondijitclick by " + key, [
+					{
+						name: "ondijitclick by " + key,
+						timeout: 5000,
+						runTest: function(){
+							widgetClicks = buttonClicks = 0;
+							var d = new doh.Deferred();
+
+							// Keyboard-click the widget
+							doh.robot.sequence(function(){
+								w.domNode.focus();
+							}, 500);
+							doh.robot.keyDown(dojo.keys[key], 250, {});
+							doh.robot.keyUp(dojo.keys[key], 250, {});
+
+							// Check that ondijitclick fired but no spurious event
+							// on the widget that got focused in the ondijitclick handler
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(1, widgetClicks, "ondijitclick handler fired");
+								doh.is(0, buttonClicks, "spurious button click event");
+							}), 500);
+
+							return d;
+						}
+					},
+					{
+						name: "ondijitclick by " + key + " w/modifier",
+						timeout: 5000,
+						runTest: function(){
+							widgetClicks = buttonClicks = 0;
+							var d = new doh.Deferred();
+
+							// Keyboard-click with modifier shouldn't do anything
+							doh.robot.sequence(function(){
+								w.domNode.focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys[key], 100, {shift: true});
+							if(!dojo.isMac){
+								// Don't do this check on mac because ctrl-space causes the context menu to show up
+								doh.robot.keyPress(dojo.keys[key], 100, {ctrl: true});
+							}
+
+							// meta key can open browser menus etc.   let's just not
+							// even try it...
+							//doh.robot.keyPress(dojo.keys[key], 100, {meta: true});
+
+							// Check that ondijitclick fired but no spurious event
+							// on the widget that got focused in the ondijitclick handler
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(0, widgetClicks, "ondijitclick handler wasn't fired");
+								doh.is(0, buttonClicks, "button click handler wasn't fired");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+			});
+
+			// Test ondijitclick on a <div> which refocuses onto a native <textarea> node.
+			// Tests that the keyboard event gets supressed so it doesn't modify the focused node.
+			dojo.forEach(["SPACE","ENTER"], function(key){
+
+				doh.register("focus to textarea by " + key, [
+					{
+						name: "ondijitclick by " + key,
+						timeout: 5000,
+						runTest: function(){
+							var d = new doh.Deferred(),
+								w = dijit.byId("second");
+
+							// Keyboard-click the widget
+							doh.robot.sequence(function(){
+								w.domNode.focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys[key], 500, {});
+
+							// Check that ondijitclick fired but that focused textarea didn't get the key
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is("hello world", dojo.byId("textarea").value);
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+			});
+
+			// Test onclick on a <button> which refocuses onto a <div> w/an ondijitclick handler.
+			// Make sure that the <div> doesn't get a spurious click event.
+			dojo.forEach(["SPACE", "ENTER" ], function(key){
+
+				doh.register("focus to ondijitclick-div by " + key, [
+					{
+						name: "click by " + key,
+						timeout: 5000,
+						runTest: function(){
+							button2Clicks = thirdClicks = 0;
+
+							var d = new doh.Deferred(),
+								button = dojo.byId("button2");
+
+							// Keyboard-click the native button
+							doh.robot.sequence(function(){
+								button.focus();
+							}, 500);
+							doh.robot.keyPress(dojo.keys[key], 500, {});
+
+							// Check that ondijitclick didn't fire
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(1, button2Clicks, "button2 was clicked (and focus moved to ondijitclick-div)");
+								doh.is(0, thirdClicks, "ondijitclick-div didn't get a spurious click event");
+							}), 500);
+
+							return d;
+						}
+					}
+				]);
+			});
+
+			doh.run();
+		});
+
+	</script>
+</head>
+</html>
diff --git a/dijit/tests/robot/_Widget-ondijitclick_mouse.html b/dijit/tests/robot/_Widget-ondijitclick_mouse.html
new file mode 100644
index 0000000..80bd6aa
--- /dev/null
+++ b/dijit/tests/robot/_Widget-ondijitclick_mouse.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Test Dijit Internal Event: "ondijitclick"</title>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");
+
+		dojo.addOnLoad(function(){
+			doh.robot.initRobot('../_Widget-ondijitclick.html');
+
+			// Event monitoring
+			var widgetClicks = 0, buttonClicks = 0;
+			var w;
+
+			doh.register("ondijitclick w/mouse", {
+				timeout:5000,
+				runTest:function(){
+					var d = new doh.Deferred();
+
+					doh.robot.sequence(function(){
+						w = dijit.byId("first");
+						dojo.connect(w, "_onClick", function(){
+							widgetClicks++;
+						}),
+						dojo.connect(dojo.byId("plainbutton"), "onclick", function(){
+							buttonClicks++;
+						})
+						w.domNode.focus();
+					}, 100);
+
+					// click the widget
+					doh.robot.mouseMoveAt("first", 500);
+					doh.robot.mouseClick({left: true}, 500);
+
+					doh.robot.sequence(d.getTestCallback(function(){
+						doh.is(1, widgetClicks, "ondijitclick handler fired once");
+					}), 1000);
+
+					return d;
+				}
+			});
+
+			doh.run();
+		});
+
+	</script>
+</head>
+</html>
diff --git a/dijit/tests/runTests.html b/dijit/tests/runTests.html
new file mode 100644
index 0000000..163bde1
--- /dev/null
+++ b/dijit/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+	<head>
+	<title>Dijit Unit Test Runner</title>
+	<meta http-equiv="REFRESH" content="0;url=../../util/doh/runner.html?testModule=dijit.tests.module"></HEAD>
+	<BODY>
+		Redirecting to D.O.H runner.
+	</BODY>
+</HTML>
diff --git a/dijit/tests/strict.html b/dijit/tests/strict.html
new file mode 100644
index 0000000..37f8d75
--- /dev/null
+++ b/dijit/tests/strict.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<script src="_loadTest.js"></script>
+</head>
+</html>
diff --git a/dijit/tests/test.html b/dijit/tests/test.html
new file mode 100644
index 0000000..5db5044
--- /dev/null
+++ b/dijit/tests/test.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>widget infrastructure test</title>
+
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.form.Button");
+
+		dojo.addOnLoad(function(){
+			for(var i=1; i<=3; i++){
+				var node = dojo.byId("b"+i);
+				var myButton = new dijit.form.Button(null, node);
+			}
+		});
+
+	</script>
+
+	<style type="text/css">
+
+		@import "../../dojo/resources/dojo.css";
+		@import "../themes/tundra/tundra.css";
+		@import "css/dijitTests.css";
+
+		body { padding: 5em; }
+	</style>
+</head>
+
+<body class="claro">
+	<button id="b1" style="background: yellow;">button #1</button>
+	<button id="b2" style="background: orange;">button #2</button>
+	<button id="b3" style="background: violet;">button #3</button>
+</body>
+</html>
diff --git a/dijit/tests/test_Calendar.html b/dijit/tests/test_Calendar.html
new file mode 100644
index 0000000..8f4272d
--- /dev/null
+++ b/dijit/tests/test_Calendar.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Calendar Widget Test</title>
+
+		<!-- for tests -->
+		<style type="text/css">
+			@import "../../dojo/resources/dojo.css";
+			@import "css/dijitTests.css";
+		</style>
+
+		<style>
+			#calendar5 .dijitCalendarDateTemplate { height: 50px; width: 50px; border: 1px solid #ccc; vertical-align: top }
+			#calendar5 .dijitCalendarDateLabel, #calendar5 .dijitCalendarDateTemplate { text-align: inherit }
+			#calendar5 .dijitCalendarDayLabel { font-weight: bold }
+			#calendar5 .dijitCalendarSelectedYear { font-size: 1.5em }
+			#calendar5 .dijitCalendarMonthLabel { font-family: serif; letter-spacing: 0.2em; font-size: 2em }
+			.blue { color: blue }
+		</style>
+
+		<!-- required: a default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../dojo/dojo.js"
+			djConfig="parseOnLoad: true, isDebug: true"></script>
+
+		<!-- not needed, for testing alternate themes -->
+		<script type="text/javascript" src="_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.Calendar");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.parser"); // scan page for widgets
+
+			dojo.addOnLoad(function(){
+				//Need to declare BigCalendar here in an addOnLoad block so that it works
+				//with xdomain loading, where the dojo.require for dijit.Calendar
+				//may load asynchronously. This also means we cannot have HTML
+				//markup in the body tag for BigCalendar, but instead inject it in this
+				//onload handler after BigCalendar is defined.
+				dojo.declare("BigCalendar", dijit.Calendar, {
+					templateString: dojo.cache("dijit.tests", "_altCalendar.html"),
+					isDisabledDate: dojo.date.locale.isWeekend,
+					getClassForDate: function(date){
+						if(!(date.getDate() % 10)){ return "blue"; } // apply special style to all days divisible by 10
+					}
+				});
+
+				var bigCalendar = dojo.byId("calendar5");
+				bigCalendar.setAttribute("dojoType", "BigCalendar");
+				dojo.parser.parse(bigCalendar.parentNode);
+			});
+
+			function myHandler(id,newValue){
+				console.debug("onChange for id = " + id + ", value: " + newValue);
+			}
+		</script>
+	</head>
+	<body class="claro">
+
+		<h1 class="testTitle">Dijit Calendar Test</h1>
+
+		<input value="input before" id="before">
+		<input id="calendar1" dojoType="dijit.Calendar" onChange="myHandler(this.id,arguments[0])">
+		<input value="input after" id="after">
+		<p>
+			<a href="#"
+			   onClick="dijit.registry.forEach(function(c){
+					c.isDisabledDate = dojo.date.locale.isWeekend;
+					c._populateGrid();
+				});">disable weekends</a>
+		</p>
+
+		<p>Customized template with "today" button</p>
+		<div>
+			<!-- Parent div used so we have a handle to use for dojo.parser.parse after BigCalendar gets defined. -->
+			<!-- The input below will be replaced by BigCalendar which is defined in a dojo.addOnLoad block. -->
+			<input id="calendar5" dayWidth="abbr" value="2008-03-14">
+		</div>
+	</body>
+</html>
diff --git a/dijit/tests/test_ColorPalette.html b/dijit/tests/test_ColorPalette.html
new file mode 100644
index 0000000..f2abdfa
--- /dev/null
+++ b/dijit/tests/test_ColorPalette.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>ColorPalette Test</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true, extraLocale: ['en-us', 'es-mx']"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.ColorPalette");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		var palette;
+		dojo.addOnLoad(function(){
+            var date0 = new Date();
+            palette = new dijit.ColorPalette({palette: "7x10", id: "prog"}, dojo.byId("programPalette"));
+            console.log("creation time for 7x10 palette: " + (new Date() - date0) );
+        });
+
+		function setColor(color){
+			var theSpan = dojo.byId("outputSpan");
+			theSpan.style.color = color;
+			theSpan.innerHTML = color;
+		}
+	</script>
+</head>
+
+<body class="claro">
+
+	<h1 class="testTitle">dijit.ColorPalette test:</h1>
+
+	<p>Large color palette (7x10), English tooltips:</p>
+	<input id="beforeBig" value="for tabIndex testing">
+	<div dojoType="dijit.ColorPalette" id="big" onChange="setColor(this.value);" lang="en-us"></div>
+	Test color is: <span id="outputSpan"></span>.
+	<input id="afterBig" value="for tabIndex testing">
+
+	<p>Small color palette (3x4), Spanish tooltips:</p>
+	<input id="beforeSmall" value="for tabIndex testing">
+	<div dojoType="dijit.ColorPalette" id="small" palette="3x4" lang="es-mx"></div>
+	<input id="afterSmall" value="for tabIndex testing">
+
+	<p>Default color palette (7x10) created programatically:</p>
+	<div id="programPalette"></div>
+
+</body>
+</html>
diff --git a/dijit/tests/test_ColorPalette_quirks.html b/dijit/tests/test_ColorPalette_quirks.html
new file mode 100644
index 0000000..fc06de9
--- /dev/null
+++ b/dijit/tests/test_ColorPalette_quirks.html
@@ -0,0 +1,5 @@
+<html>
+<head>
+<script type="text/javascript" src="_loadTest.js" file="test_ColorPalette.html"></script>
+</head>
+</html>
diff --git a/dijit/tests/test_Declaration.html b/dijit/tests/test_Declaration.html
new file mode 100644
index 0000000..91df301
--- /dev/null
+++ b/dijit/tests/test_Declaration.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Dojo Toolkit - Declaration test</title>
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Declaration");
+		dojo.require("dijit.ProgressBar");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+
+</head>
+<body class="claro">
+	<h3>Simple macro:</h3>
+	<p>(Check to make sure that links contain employee number)
+	<div dojoType="dijit.Declaration" widgetClass="Employee" defaults="{ empid: 123, name: '' }">
+		<span>${name}</span>
+		<a href="update.php?id=${empid}">update</a>
+		<a href="delete.php?id=${empid}">delete</a>
+	</div>
+	<div dojoType="Employee" empid="100" name="Alan Allen"></div>
+	<div dojoType="Employee" empid="101" name="Bob Brown"></div>
+	<div dojoType="Employee" empid="102" name="Cathy Cameron"></div>
+
+	<h3>Using dojoAttachEvent, dojoAttachPoint</h3>
+	<div dojoType="dijit.Declaration" widgetClass="HideButton">
+		XXX<button dojoAttachEvent="onclick" dojoAttachPoint="containerNode"></button>XXX
+		<script type='dojo/method' event='onclick'>
+			this.domNode.style.display="none";
+		</script>
+	</div>
+	<button dojoType="HideButton">Click to hide</button>
+	<button dojoType="HideButton">Click to hide #2</button>
+
+	<h3>Extending another widget</h3>
+	<p>HideButton2 extends HideButton (above) and changes the template (but keeps the onclick handler).</p>
+	<span dojoType="dijit.Declaration" widgetClass="HideButton2" mixins="HideButton">
+		YYY<button dojoAttachEvent="onclick" dojoAttachPoint="containerNode"></button>YYY
+	</span>
+	<button dojoType="HideButton2">Hide me extended</button>
+	<button dojoType="HideButton2">Hide me extended #2</button>
+
+	<h3>Using dojo/method:</h3>
+	<div dojoType="dijit.Declaration" widgetClass="m" defaults="{ foo: 'thud', progress: 10 }">
+		<script type='dojo/method' event='postCreate'>
+			console.log("in postCreate ", this, arguments);
+			this.inherited(arguments);
+			this.baz.innerHTML += " (created via custom postCreate) ";
+		</script>
+
+		<p>thinger blah stuff ${foo}</p>
+
+		<div style="width:400px" maximum="200"
+			progress="${progress}" dojoType="dijit.ProgressBar"></div>
+		<p dojoAttachPoint='baz'>baz thud</p>
+	</div>
+
+	<div dojoType="m" foo="blah" progress="50"></div>
+	<div dojoType="m" foo="thinger" progress="73"></div>
+
+	<h3>Using dojo/connect:</h3>
+	<div dojoType="dijit.Declaration" widgetClass="foo" defaults="{ foo: 'thud', progress: 10 }">
+		<script type='dojo/connect' event='startup'>
+			this.baz.innerHTML += " (modified by dojo/connect event=startup) ";
+		</script>
+
+		<p>thinger blah stuff ${foo}</p>
+
+		<div style="width:400px" maximum="200"
+			progress="${progress}" dojoType="dijit.ProgressBar"></div>
+		<p dojoAttachPoint='baz'>baz thud</p>
+	</div>
+
+	<div dojoType="foo" foo="blah" progress="50"></div>
+	<div dojoType="foo" foo="thinger" progress="73"></div>
+
+</body>
+</html>
diff --git a/dijit/tests/test_Dialog.html b/dijit/tests/test_Dialog.html
new file mode 100644
index 0000000..c2afb48
--- /dev/null
+++ b/dijit/tests/test_Dialog.html
@@ -0,0 +1,599 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dialog Widget Dojo Tests</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+
+		form { margin-bottom : 0; }
+		table { border: none; }
+		#dialog3_underlay { background-color: #027 }
+		#fifthDlg_underlay { background-color: yellow; }
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Dialog");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.DateTextBox");
+		dojo.require("dijit.form.TimeTextBox");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.InlineEditBox");
+		dojo.require("dijit.Menu");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		// create a do nothing, only for test widget
+		dojo.declare("dijit.TestWidget",
+			[dijit._Widget, dijit._Templated], {
+			templateString: "<div style='margin: 10px; border: inset #700 4px; padding: 5px;' dojoAttachPoint='containerNode'></div>"
+		});
+
+		// make dojo.toJson() print dates correctly (this feels a bit dirty)
+		Date.prototype.json = function(){ return dojo.date.stamp.toISOString(this, {selector: 'date'});};
+
+		var thirdDlg;
+		function createDialog() {
+			if(!thirdDlg){
+				var pane = dojo.byId('thirdDialog');
+				// should specify a width on dialogs with <p> tags, otherwise they get too wide
+				thirdDlg = new dijit.Dialog({
+					id: "dialog3",
+					title: "Programatic Dialog Creation",
+					style: {width: '300px'}
+				},pane);
+			}
+			setTimeout(function(){ thirdDlg.show(); },"3000");
+		}
+		dojo.addOnLoad(function(){
+			dojo.subscribe("focusNode", function(node){ console.log("focused on " + (node?(node.id||node.tagName):"nothing"));});
+		});
+		function open2Dialogs(){
+			dijit.byId('dialog1').show();
+			setTimeout(dojo.hitch(dijit.byId('fifthDlg'), 'show'), 1000);
+		}
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit layout.Dialog tests</h1>
+	<button dojoType="dijit.form.Button"  id="dialog1button" onclick="dijit.byId('dialog1').show()">Show Dialog</button> |
+
+	<div dojoType="dijit.Dialog" id="dialog1" title="First Dialog"
+			aria-describedby="intro"
+			onfocus="console.log('user focus handler')"
+			onblur="console.log('user blur handler')"
+			execute="console.log('submitted w/args:\n' + dojo.toJson(arguments[0], true));">
+		<div id="intro" style="width:30em;">Introductory information spoken by screen reader if aria-describedby is
+		added to the declaration of dialog above with value equal to the id of the container element for this text. This technique
+		will work in Dojo 1.4. </div>
+		<table>
+			<tr>
+				<td><label for="name">Name: </label></td>
+				<td><input dojoType=dijit.form.TextBox type="text" name="name" id="name"></td>
+			</tr>
+			<tr>
+				<td><label for="loc">Location: </label></td>
+				<td><input dojoType=dijit.form.TextBox type="text" name="loc" id="loc"></td>
+			</tr>
+			<tr>
+				<td><label for="date">Date: </label></td>
+				<td><input dojoType=dijit.form.DateTextBox type="text" name="date" id="date"></td>
+			</tr>
+			<tr>
+				<td><label for="time">Time: </label></td>
+				<td><div dojoType="dijit.InlineEditBox" editor=dijit.form.TimeTextBox type="text" name="time" id="time" width="100px" style="width:100px;"></div></td>
+			</tr>
+			<tr>
+				<td><label for="desc">Description: </label></td>
+				<td><input dojoType=dijit.form.TextBox type="text" name="desc" id="desc"></td>
+			</tr>
+			<tr>
+				<td colspan="2" align="center">
+					<button dojoType=dijit.form.Button id="ok" type="submit">OK</button></td>
+			</tr>
+		</table>
+	</div>
+
+
+	<button dojoType="dijit.form.Button" onclick="createDialog()" title="shows after 3 second delay, with blue background">Programatic Dialog (3 second delay)</button> |
+
+
+	<div id="thirdDialog" style="display: none;">
+		<form>
+		<input>
+		<br>
+		<button>hello</button>
+		<br>
+		<select>
+			<option>Lorem</option>
+			<option>ipsum</option>
+			<option>dolor</option>
+			<option>sit</option>
+			<option>amet</option>
+		</select>
+		</form>
+		<p>
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+		semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+		porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+		Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+		Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+		risus.
+		</p>
+	</div>
+
+	<button dojoType="dijit.form.Button" onclick="dijit.byId('tabDialog').show()">Show TabContainer Dialog</button> |
+
+	<div dojoType="dijit.Dialog" id="tabDialog" title="TabContainer Dialog">
+		<div dojoType="dijit.layout.TabContainer" id="tc" style="width: 400px; height: 400px;">
+			<div dojoType="dijit.layout.ContentPane" id="cp1" title="First tab">
+				<p>
+					This is the first tab.
+				</p>
+				<p>
+				Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+				porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+				Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+				Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+				risus.
+				</p>
+			</div>
+			<div dojoType="dijit.layout.ContentPane" id="cp2" title="Second tab">
+				<p>
+					This is the second tab.
+				</p>
+				<p>
+				Make it overflow. <a href="http://www.lipsum.com/">ipsum dolor sit amet</a>, consectetuer adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+				porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+				Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+				Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+				risus.
+				</p>
+				<p>
+				Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+				porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+				Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+				Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+				risus.
+				</p>
+				<p>
+				Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+				porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+				Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+				Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+				risus.
+				</p>
+			</div>
+		</div>
+	</div>
+
+	<button dojoType="dijit.form.Button" onclick="dijit.byId('fifthDlg').show();">Test slow loading HREF Dialog</button> |
+
+	<div dojoType="dijit.Dialog" id="fifthDlg" href="layout/getResponse.php?delay=3000&messId=3"
+		style="width: 300px" title="From HREF (slow network simulated)"></div>
+
+	<button dojoType="dijit.form.Button" onclick="dijit.byId('dialog6').show()">Show File Dialog</button>
+
+	<div dojoType="dijit.Dialog" id="dialog6" title="File Dialog"
+			onfocus="console.log('user focus handler')"
+			onblur="console.log('user blur handler')"
+			execute="alert('submitted w/args:\n' + dojo.toJson(arguments[0], true));" style="min-width: 350px">
+		<!-- note: style="min-width: 350px" to workaround FF bug where width is too short, see http://bugs.dojotoolkit.org/ticket/5976 -->
+			<label for="afile">ID File: </label>
+			<input dojoType=dijit.form.TextBox type="file" name="afile" id="afile">
+	</div>
+
+	<button dojoType="dijit.form.Button" onclick="dijit.byId('cantmove').show()">Show Unmovable</button>
+
+	<div dojoType="dijit.Dialog" id="cantmove" title="unmovable" draggable="false">
+		<p>You should not be able to <br /> drag this dialog</p>
+	</div>
+
+	<button dojoType="dijit.form.Button" onclick="dijit.byId('preventer').show()">Show Close prevention</button>
+
+	<div dojoType="dijit.Dialog" id="preventer" title="Confirm Close">
+		I am done entering data:
+		<button dojoType="dijit.form.Button" id="preventerOK" type="submit" onClick="return confirm('Are you sure?')">OK</button>
+	</div>
+
+	<button dojoType="dijit.form.Button" onclick="dijit.byId('embedded').show()">Dialog w/embedded layout widgets</button> |
+
+	<div dojoType="dijit.Dialog" id="embedded" title="Embedded layout widgets"
+		onShow="dojo.attr(this.domNode, 'aria-describedby', 'describe');" >
+		<p id="describe">
+			The pane has some text, plus two embedded layout widgets, which should
+			appear correctly even though the pane is initially hidden.
+		</p>
+		<p>
+			Here's a BorderContainer:
+		</p>
+		<div dojoType="dijit.layout.BorderContainer" style="height:200px; width:300px">
+			<div dojoType="dijit.layout.ContentPane" region="left" style="width:100px" splitter="true">
+				1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+				Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+				vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+				augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+				metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+				ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+				euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+				risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+				porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+				faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+				consequat quis, varius interdum, nulla. Donec neque tortor,
+				sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+				ut eros sit amet ante pharetra interdum.
+			</div>
+			<div dojoType="dijit.layout.ContentPane" region="center">
+				2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+				Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+				vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+				augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+				metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+				ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+				euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+				risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+				porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+				faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+				consequat quis, varius interdum, nulla. Donec neque tortor,
+				sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+				ut eros sit amet ante pharetra interdum.
+			</div>
+		</div>
+		<p>
+			And a TabContainer:
+		</p>
+		<div dojoType="dijit.layout.TabContainer" style="height:200px; width:300px">
+			<div dojoType="dijit.layout.ContentPane" title="Tab 1">
+				1Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+				Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+				vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+				augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+				metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+				ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+				euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+				risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+				porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+				faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+				consequat quis, varius interdum, nulla. Donec neque tortor,
+				sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+				ut eros sit amet ante pharetra interdum.
+			</div>
+			<div dojoType="dijit.layout.ContentPane" title="Tab 2">
+				2Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+				Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+				vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+				augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+				metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+				ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+				euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+				risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+				porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+				faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+				consequat quis, varius interdum, nulla. Donec neque tortor,
+				sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+				ut eros sit amet ante pharetra interdum.
+			</div>
+		</div>
+		<p>
+			Text after the widgets.
+		</p>
+	</div>
+	
+	
+	<!-- Action Bar test case -->
+	<button dojoType="dijit.form.Button"  id="ABDlg1Btn" onclick="dijit.byId('ABDlg1').show()">Show Dialog With Action Buttons</button>
+	<div dojoType="dijit.Dialog" id="ABDlg1" title="ActionBar Dialog 1" 
+			onExecute="console.log('OK button pressed')"
+			onCancel="console.log('Cancel button pressed')"
+			aria-describedby="intro"
+			execute="console.log('submitted w/args:\n' + dojo.toJson(arguments[0], true));">
+		<div class="dijitDialogPaneContentArea">
+			<div id="ABintro1" style="width:30em;">Introductory information spoken by screen reader if aria-describedby is
+			added to the declaration of dialog above with value equal to the id of the container element for this text. This technique
+			will work in Dojo 1.4. </div>
+		</div>
+		
+		
+		<div class="dijitDialogPaneActionBar">
+			<button dojoType="dijit.form.Button" type="submit" id="ABdialog1button1">OK</button>
+			<button dojoType="dijit.form.Button" type="button" onClick="dijit.byId('ABDlg1').onCancel();" 
+					id="ABdialog1button2">Cancel</button>
+		</div>
+	</div>
+	
+	<button dojoType="dijit.form.Button"  id="NABDlgBtn" onclick="dijit.byId('NABDlg').show()">Show Dialog With No Action Buttons</button>
+	<div dojoType="dijit.Dialog" id="NABDlg" title="No Action Bar Dialog"
+			aria-describedby="intro"
+			onfocus="console.log('user focus handler')"
+			onblur="console.log('user blur handler')"
+			execute="console.log('submitted w/args:\n' + dojo.toJson(arguments[0], true));">
+				
+		<div class="dijitDialogPaneContentArea">
+			<div id="NABintro" style="width:30em;">Introductory information spoken by screen reader if aria-describedby is
+			added to the declaration of dialog above with value equal to the id of the container element for this text. This technique
+			will work in Dojo 1.4. </div>
+			<table>
+				<tr>
+					<td><label for="name">Name: </label></td>
+					<td><input dojoType=dijit.form.TextBox type="text" name="NABname" id="NABname"></td>
+				</tr>
+				<tr>
+					<td><label for="loc">Location: </label></td>
+					<td><input dojoType=dijit.form.TextBox type="text" name="NABloc" id="NABloc"></td>
+				</tr>
+				<tr>
+					<td><label for="date">Date: </label></td>
+					<td><input dojoType=dijit.form.DateTextBox type="text" name="NABdate" id="NABdate"></td>
+				</tr>
+				<tr>
+					<td><label for="desc">Description: </label></td>
+					<td><input dojoType=dijit.form.TextBox type="text" name="NABdesc" id="NABdesc"></td>
+				</tr>
+			</table>
+		</div>
+	</div>
+
+
+	<button dojoType="dijit.form.Button"  id="layeredDialogs" onclick="open2Dialogs">Show 2 Dialogs</button>
+
+	<button dojoType="dijit.form.Button"  id="iframeDlg" onclick='dijit.byId("dlgFrame").show();'>Show iframe in dialog</button>
+	<div dojoType="dijit.Dialog" id="dlgFrame" title="Search">
+		<iframe title="Test IFrame" src="layout/getResponse.php?delay=3000&messId=3" style="width:600px; height: 400px;">
+	</iframe>
+				
+	</div>
+	
+	<p><b><i>(scroll down to see more links to click, for testing positioning / scroll handling)</i></b></p>
+
+	<p>
+	Here's a form.  Try clicking the programatic dialog link, then focusing on the form.
+	After the dialog closes focus should be returned to the form
+	</p>
+
+	<form>
+	<input id="plainInput">
+	<br>
+	<button id="plainButton">hello</button>
+	<br>
+	<select>
+		<option>Lorem</option>
+		<option>ipsum</option>
+		<option>dolor</option>
+		<option>sit</option>
+		<option>amet</option>
+	</select>
+	</form>
+
+
+	<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+	imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+	nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+	massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+	pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+	quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+	felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+	quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+	rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+	semper velit ante id metus. Praesent massa dolor, porttitor sed,
+	pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+	tortor pharetra congue. Suspendisse pulvinar.
+	</p>
+	<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+	ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+	nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+	lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+	est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+	dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+	nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+	pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+	sociosqu ad litora torquent per conubia nostra, per inceptos
+	hymenaeos.
+	</p>
+	<form>
+		<center>
+			<select>
+				<option>1</option>
+				<option>2</option>
+			</select>
+		</center>
+	</form>
+	<p>Mauris pharetra lorem sit amet sapien. Nulla libero metus, tristique
+	et, dignissim a, tempus et, metus. Ut libero. Vivamus tempus purus vel
+	ipsum. Quisque mauris urna, vestibulum commodo, rutrum vitae, ultrices
+	vitae, nisl. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos hymenaeos. Nulla id erat sit amet odio
+	luctus eleifend. Proin massa libero, ultricies non, tincidunt a,
+	vestibulum non, tellus. Nunc nunc purus, lobortis a, pulvinar at,
+	egestas a, mi. Cras adipiscing velit a mauris. Morbi felis. Etiam at
+	felis. Cras eget eros et justo mattis pulvinar. Nullam at justo id
+	risus porttitor dignissim. Vestibulum sed velit vel metus tincidunt
+	tempus. Nunc euismod nisl id dolor tristique tincidunt. Nullam placerat
+	turpis sed odio. Curabitur in est id nibh tempus ultrices. Aliquam
+	consectetuer dapibus eros. Aliquam nisl.
+	</p>
+	<div id="reallyWide">[spacer]</div>
+	<p>
+	Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+	semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+	porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+	Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+	Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+	risus.
+	</p>
+	<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+	imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+	nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+	massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+	pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+	quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+	felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+	quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+	rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+	semper velit ante id metus. Praesent massa dolor, porttitor sed,
+	pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+	tortor pharetra congue. Suspendisse pulvinar.
+	</p>
+	<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+	ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+	nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+	lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+	est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+	dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+	nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+	pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+	sociosqu ad litora torquent per conubia nostra, per inceptos
+	hymenaeos.
+	</p>
+	<form>
+		<center>
+			<select>
+				<option>1</option>
+				<option>2</option>
+			</select>
+		</center>
+	</form>
+	<p>Mauris pharetra lorem sit amet sapien. Nulla libero metus, tristique
+	et, dignissim a, tempus et, metus. Ut libero. Vivamus tempus purus vel
+	ipsum. Quisque mauris urna, vestibulum commodo, rutrum vitae, ultrices
+	vitae, nisl. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos hymenaeos. Nulla id erat sit amet odio
+	luctus eleifend. Proin massa libero, ultricies non, tincidunt a,
+	vestibulum non, tellus. Nunc nunc purus, lobortis a, pulvinar at,
+	egestas a, mi. Cras adipiscing velit a mauris. Morbi felis. Etiam at
+	felis. Cras eget eros et justo mattis pulvinar. Nullam at justo id
+	risus porttitor dignissim. Vestibulum sed velit vel metus tincidunt
+	tempus. Nunc euismod nisl id dolor tristique tincidunt. Nullam placerat
+	turpis sed odio. Curabitur in est id nibh tempus ultrices. Aliquam
+	consectetuer dapibus eros. Aliquam nisl.
+	</p>
+
+	<p>
+	<button dojoType="dijit.form.Button" onClick="dijit.byId('dialog1').show()">Show Dialog</button> |
+	<!-- showing a dialog from an anchor with inline onclick="" is a solution to page onUnLoad firing
+		but you must return false; alternatively, you can dojo.connect() to the anchor links, and
+		e.preventDefault() on the event object passed. using href="javascript:" inline causes onUnLoad
+		to destroy all widgets in IE6
+	-->
+	<a href="http://dojotoolkit.org" onclick="dijit.byId('dialog1').show(); return false; ">Show Dialog</a>
+	</p>
+
+	<p>
+	Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+	semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+	porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+	Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+	Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+	risus.
+	</p>
+	<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+	imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+	nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+	massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+	pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+	quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+	felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+	quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+	rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+	semper velit ante id metus. Praesent massa dolor, porttitor sed,
+	pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+	tortor pharetra congue. Suspendisse pulvinar.
+	</p>
+	<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+	ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+	nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+	lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+	est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+	dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+	nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+	pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+	sociosqu ad litora torquent per conubia nostra, per inceptos
+	hymenaeos.
+	</p>
+	<p>Mauris pharetra lorem sit amet sapien. Nulla libero metus, tristique
+	et, dignissim a, tempus et, metus. Ut libero. Vivamus tempus purus vel
+	ipsum. Quisque mauris urna, vestibulum commodo, rutrum vitae, ultrices
+	vitae, nisl. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos hymenaeos. Nulla id erat sit amet odio
+	luctus eleifend. Proin massa libero, ultricies non, tincidunt a,
+	vestibulum non, tellus. Nunc nunc purus, lobortis a, pulvinar at,
+	egestas a, mi. Cras adipiscing velit a mauris. Morbi felis. Etiam at
+	felis. Cras eget eros et justo mattis pulvinar. Nullam at justo id
+	risus porttitor dignissim. Vestibulum sed velit vel metus tincidunt
+	tempus. Nunc euismod nisl id dolor tristique tincidunt. Nullam placerat
+	turpis sed odio. Curabitur in est id nibh tempus ultrices. Aliquam
+	consectetuer dapibus eros. Aliquam nisl.
+	</p>
+
+	<p>
+	Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+	semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+	porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+	Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+	Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+	risus.
+	</p>
+	<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+	imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+	nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+	massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+	pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+	quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+	felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+	quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+	rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+	semper velit ante id metus. Praesent massa dolor, porttitor sed,
+	pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+	tortor pharetra congue. Suspendisse pulvinar.
+	</p>
+	<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+	ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+	nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+	lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+	est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+	dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+	nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+	pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+	sociosqu ad litora torquent per conubia nostra, per inceptos
+	hymenaeos.
+	</p>
+	<p>Mauris pharetra lorem sit amet sapien. Nulla libero metus, tristique
+	et, dignissim a, tempus et, metus. Ut libero. Vivamus tempus purus vel
+	ipsum. Quisque mauris urna, vestibulum commodo, rutrum vitae, ultrices
+	vitae, nisl. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos hymenaeos. Nulla id erat sit amet odio
+	luctus eleifend. Proin massa libero, ultricies non, tincidunt a,
+	vestibulum non, tellus. Nunc nunc purus, lobortis a, pulvinar at,
+	egestas a, mi. Cras adipiscing velit a mauris. Morbi felis. Etiam at
+	felis. Cras eget eros et justo mattis pulvinar. Nullam at justo id
+	risus porttitor dignissim. Vestibulum sed velit vel metus tincidunt
+	tempus. Nunc euismod nisl id dolor tristique tincidunt. Nullam placerat
+	turpis sed odio. Curabitur in est id nibh tempus ultrices. Aliquam
+	consectetuer dapibus eros. Aliquam nisl.
+	</p>
+
+</body>
+</html>
+
+
diff --git a/dijit/tests/test_Dialog_focusDestroy.html b/dijit/tests/test_Dialog_focusDestroy.html
new file mode 100644
index 0000000..fe5de72
--- /dev/null
+++ b/dijit/tests/test_Dialog_focusDestroy.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dialog Widget Dojo Tests</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+
+		body { font-family : sans-serif; }
+		form { margin-bottom : 0; }
+		table { border: none; }
+		#dialog3_underlay { background-color: #027 }
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Dialog");
+		dojo.require("dijit.form.Button");
+
+		// make dojo.toJson() print dates correctly (this feels a bit dirty)
+		function createAndShow() {
+			var node = document.createElement("div");
+			dojo.body().appendChild(node);
+			var dlg = new dijit.Dialog({ title: "test input focus" }, node);
+
+			var input = document.createElement("input");
+			dojo.attr(input,"tabIndex","0");
+			dlg.containerNode.appendChild(input);
+
+			var btn = new dijit.form.Button({ label: "Close" });
+			dlg.containerNode.appendChild(btn.domNode);
+
+			dojo.connect(btn, "onClick", function(){
+				console.log("destroying, while visible");
+				dlg.destroy();
+
+			});
+			dlg.show();
+		}
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit layout.Dialog tests</h1>
+
+	<p>If you input this box, you can type. You should be able to type and use backspace/etc
+	when you destroy the visible dialog. refs <a href="http://trac.dojotoolkit.org/ticket/5351">#5351</a>
+	</p>
+
+	<input id="testInput" name="foo" value="bar" />
+
+	<button dojoType="dijit.form.Button" onclick="createAndShow()">Show Dialog</button>
+
+</body>
+</html>
+
diff --git a/dijit/tests/test_InlineEditBox.html b/dijit/tests/test_InlineEditBox.html
new file mode 100644
index 0000000..5484a38
--- /dev/null
+++ b/dijit/tests/test_InlineEditBox.html
@@ -0,0 +1,261 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Inline Edit Box Test</title>
+
+		<style type="text/css">
+			@import "../../dojo/resources/dojo.css";
+			@import "css/dijitTests.css";
+
+			.inlineEdit { background-color: #CCC76A; }
+
+			/* some style rules on nodes just to test that style gets copied to the edit widget */
+			p { font-family: cursive; }
+			.letter p { font-family: monospace; }
+			h3 { font-family: helvetica; font-style: italic; }
+		</style>
+
+		<!-- required: a default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../dojo/dojo.js"
+			djConfig="parseOnLoad: true, isDebug: true"></script>
+
+		<!-- not needed, for testing alternate themes -->
+		<script type="text/javascript" src="_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dojo.data.ItemFileReadStore");
+			dojo.require("dijit.InlineEditBox");
+			dojo.require("dijit.form.Textarea");
+			dojo.require("dijit.form.TextBox");
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dijit.form.CurrencyTextBox");
+			dojo.require("dojo.currency");
+			dojo.require("dijit.form.ComboBox");
+			dojo.require("dijit.form.FilteringSelect");
+			dojo.require("dijit.form.NumberSpinner");
+
+			dojo.require("dijit.Editor");
+			dojo.require("dijit._editor.plugins.AlwaysShowToolbar");
+
+			dojo.require("dojo.parser");	  // scan page for widgets and instantiate them
+
+			function myHandler(id,newValue){
+				console.debug("onChange for id = " + id + ", value: " + newValue);
+			};
+			/*
+			dojo.addOnLoad(function(){
+				dojo.subscribe("widgetFocus", function(widget){
+					console.log("focused on widget " + (widget?widget:"nothing"));
+				});
+				dojo.subscribe("widgetBlur", function(widget){
+					console.log("blurred widget " + (widget?widget:"nothing"));
+				});
+				dojo.subscribe("focusNode", function(node){ console.log("focused on node " + (node?(node.id||node.tagName):"nothing"));});
+			});
+			*/
+		</script>
+	</head>
+	<body class="claro">
+
+		<h1 class="testTitle">Dijit InlineEditBox Test</h1>
+
+		<span dojoType="dojo.data.ItemFileReadStore" jsId="stateStore"
+			url="_data/states.json"></span>
+		<span dojoType="dojo.data.ItemFileReadStore" jsId="productStore">
+			<script type="dojo/method">
+				this._jsonData =
+					{ identifier: 'name',
+					  label: 'name',
+					  items: [
+						{ name: "refrigerator" },
+						{ name: "freezer" },
+						{ name: "stove" },
+						{ name: "heater" }
+					]};
+			</script>
+		</span>
+
+		<h2>Form Letter with blanks</h2>
+		<div class="letter">
+			<h3 id="editable" dojoType="dijit.InlineEditBox" onChange="myHandler(this.id,arguments[0])" autoSave="true" title="company name"></h3>
+			<p>
+				Dear <span id="MrSmith" dojoType="dijit.InlineEditBox" width="200px" title="recipient name"></span>,
+			</p>
+			<p class="letter">
+				Thank you for your recent order.
+				Please remit
+				<span id="dollar_as" dojoType="dijit.InlineEditBox" editor="dijit.form.CurrencyTextBox" editorParams="{currency: 'USD'}" width="100px" title="dollar amount"></span> for
+				your purchase of
+				<span dojoType="dijit.InlineEditBox" editor="dijit.form.NumberSpinner" editorParams="{constraints: {places:0} }" width="70px" title="quantity"></span> deluxe
+				<span dojoType="dijit.InlineEditBox" editor="dijit.form.ComboBox" title="item name"
+					editorParams="{searchAttr: 'name', store: productStore, autocomplete: false, hasDownArrow: false}"
+					 width="200px"></span> on
+				<span dojoType="dijit.InlineEditBox" editor="dijit.form.DateTextBox" width="200px" title="purchase date as mm/dd/yy"></span> in
+				<span dojoType="dijit.InlineEditBox" editor="dijit.form.FilteringSelect"
+					editorParams="{searchAttr: 'name', keyAttr: 'abbreviation', store: stateStore, autocomplete: true, hasDownArrow: true}"
+					 width="200px" title="state of purchase"></span>.
+			</p>
+			<p id="textarea" dojoType="dijit.InlineEditBox" autoSave="true" editor="dijit.form.Textarea" title="additional details"></p>
+			<p>
+				Sincerely,
+			</p>
+			<span  style="margin-left: 2em; font-family: cursive;" dojoType="dijit.InlineEditBox" width="400px" title="sender name"                                                                           ></span>
+		</div>
+		<hr style="margin-bottom: 1em;">
+
+		<h2>Form Letter with <span id="predefined">predefined values</span>, and no auto-save</h2>
+		<div class="letter">
+			<h3 id="editable2" dojoType="dijit.InlineEditBox" onChange="myHandler(this.id,arguments[0])" autoSave="false" title="company name">
+				Bob Vance Refrigeration
+			</h3>
+			<p>
+				Dear <span dojoType="dijit.InlineEditBox" width="200px" autoSave="false" title="recipient name">John</span>,
+			</p>
+			<p class="letter">
+				Thank you for your recent order.
+				Please remit
+				<span id="dollar" dojoType="dijit.InlineEditBox" editor="dijit.form.CurrencyTextBox" editorParams="{currency: 'USD'}" width="100px" autoSave="false" title="dollar amount">$2,000</span>
+				for your purchase of
+				<span id="quantity" dojoType="dijit.InlineEditBox" editor="dijit.form.NumberSpinner" editorParams="{constraints: {places:0} }" width="70px" autoSave="false" title="quantity">3</span>
+				deluxe
+				<span id="item" dojoType="dijit.InlineEditBox" editor="dijit.form.ComboBox"
+					editorParams="{searchAttr: 'name', store: productStore, autocomplete: false, hasDownArrow: false}"
+					 width="200px" autoSave="false" title="item name">refrigerators</span>
+				on
+				<!--
+					normally the server is in charge of formatting the displayed date pattern (01/05/2007) below
+					in the client's locale (since the user is expecting to see it that way and so is DateTextBox),
+					but since this test is static HTML, we instead hardcode the displayed value and use editorParams
+					to tell DateTextBox to expect that pattern regardless of the machine's locale
+				-->
+				<span id="purchase" dojoType="dijit.InlineEditBox"
+					editor="dijit.form.DateTextBox" editorParams="{constraints: {datePattern: 'MM/dd/yyyy'}}"
+					width="200px" autoSave="false" title="purchase date as mm/dd/yy">01/05/2007</span>
+				in
+				<span id="state" dojoType="dijit.InlineEditBox" editor="dijit.form.FilteringSelect"
+					editorParams="{searchAttr: 'name', keyAttr: 'abbreviation', store: stateStore, autocomplete: true, hasDownArrow: false}"
+					 width="200px" autoSave="false" title="state of purchase">
+					 Pennsylvania
+				</span>.
+			</p>
+			<p dojoType="dijit.InlineEditBox" autoSave="false" editor="dijit.form.Textarea" title="additional details">
+				We sincerely appreciate your business and hope we can do business again.
+			</p>
+			<p>
+				Sincerely,
+			</p>
+			<span  style="margin-left: 2em; font-family: cursive;" dojoType="dijit.InlineEditBox" width="400px" autoSave="false" title="sender name">Bob Vance</span>
+		</div>
+		<hr style="margin-bottom: 1em;">
+
+
+		<h2>Inline-block Text (of 400px width)</h2>
+		<div>
+			The following section uses inline block text of 400px.
+			When clicking the editable text it should bring up an editor which is also 400px wide.
+		</div>
+		(before plain inline) <fieldset class="dijitInline"><div style="width: 400px;">hello world</div></fieldset> (after plain inline)
+		<br>
+		(before editable inline)
+		<fieldset class="dijitInline"><div dojoType="dijit.InlineEditBox" onChange="myHandler(this.id,arguments[0])" width="400px" style="width: 400px;">
+			hello world
+		</div></fieldset>
+		(after editable inline)
+		<hr style="width:100%;">
+
+		<h2>Pararagraph</h2>
+		(before plain paragraph)
+		<p>
+		Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+semper velit ante id metus. Praesent massa dolor, porttitor sed,
+pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+tortor pharetra congue. Suspendisse pulvinar.
+		</p>
+		(before editable paragraph.  the editable paragraph has Save/Cancel buttons when open.)
+		<p id="areaEditable" dojoType="dijit.InlineEditBox" autoSave="false" editor="dijit.form.Textarea">
+			Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+semper velit ante id metus. Praesent massa dolor, porttitor sed,
+pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+tortor pharetra congue. Suspendisse pulvinar.
+		</p>
+		These buttons will
+		<button onClick="dijit.byId('areaEditable').set('disabled', true)">disable</button> /
+		<button onClick="dijit.byId('areaEditable').set('disabled', false)">enable</button>
+		the InlineEditBox above.
+		<hr style="width:100%;">
+
+		<h2>Editor</h2>
+		<div id="inlineRTE" dojoType="dijit.InlineEditBox" editor="dijit.Editor"
+			autoSave="false" renderAsHtml="true"
+			editorParams="{height: '', extraPlugins: ['dijit._editor.plugins.AlwaysShowToolbar']}">
+			<b>Aliquam</b> vitae enim. <i>Duis</i> scelerisque metus auctor est venenatis
+imperdiet. <u>Fusce</u> dignissim porta augue. Nulla vestibulum. Integer lorem
+nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+semper velit ante id metus. Praesent massa dolor, porttitor sed,
+pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+tortor pharetra congue. Suspendisse pulvinar.
+		</div>
+		<p>
+			Note: since the Editor may return a result containing one or more <p> nodes,
+			don't make the InlineEditBox itself a <p> because that would cause nested
+			<p>s, which is illegal, and messes up IE
+		</p>
+
+		<h2>FilteringSelect (no down arrow, and save/cancel buttons):</h2>
+		before
+		<span id="filteringSelect2" dojoType="dijit.InlineEditBox" editor="dijit.form.FilteringSelect"
+			editorParams="{searchAttr: 'name', keyAttr: 'abbreviation', store: stateStore, autocomplete: true, hasDownArrow: false}"
+			 width="200px" autoSave="false">
+			Indiana
+		</span>
+		<button onclick="dijit.byId('filteringSelect2').edit();return false;">Edit previous value</button>
+		after
+		<hr style="width:100%;">
+
+		<h2>Programmatically created:</h2>
+		before block<div style="display:block;" id="programmatic">Click here to edit a block programmatically created inline edit region</div>after
+		<script type="text/javascript">
+			// See if we can make a widget in script
+			dojo.addOnLoad(function(){
+				var inlineWidget = new dijit.InlineEditBox({renderAsHtml: true}, 'programmatic');
+ 			});
+		</script>
+		<hr style="width:100%;">
+		<h2>Complex renderAsHtml="false"</h2>
+		<div id="renderAsHtml_false" dojoType="dijit.InlineEditBox" renderAsHtml="false" width="400px" style="width:400px;">
+			<B>not bold</B>&lt;input&gt;
+		</div>
+		<hr style="width:100%;">
+		<h2>Complex renderAsHtml="true"</h2>
+		<div id="renderAsHtml_true" dojoType="dijit.InlineEditBox" renderAsHtml="true" width="400px" style="width:400px;">
+			<B>not bold</B><B>bold</B>&lt;input&gt;
+		</div>
+	</body>
+</html>
diff --git a/dijit/tests/test_Menu.html b/dijit/tests/test_Menu.html
new file mode 100644
index 0000000..b647159
--- /dev/null
+++ b/dijit/tests/test_Menu.html
@@ -0,0 +1,466 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Menu System Test</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+
+		body { padding: 0; }
+
+		/* styling for left-hand-side navigation menu to become a column equal to length of page */
+		#formattingTable {
+			border: 0px;
+			border-spacing: 0px;
+		}
+		#contentContainer { padding: 2em; }
+
+		#navMenu {
+			/* make the sidebar menu blend in with the whole sidebar */
+			border: none;
+		}
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Menu");
+		dojo.require("dijit.MenuItem");
+		dojo.require("dijit.PopupMenuItem");
+		dojo.require("dijit.MenuBar");
+		dojo.require("dijit.MenuBarItem");
+		dojo.require("dijit.PopupMenuBarItem");
+		dojo.require("dijit.MenuSeparator");
+		dojo.require("dijit.ColorPalette");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+
+    <script language="Javascript" type="text/javascript">
+        function createMenu() {
+            // create a menu programmatically
+            function fClick() {console.log("clicked!")};
+
+            pMenu = new dijit.Menu({targetNodeIds:["prog_menu"], id:"progMenu"});
+            pMenu.addChild(new dijit.MenuItem({label:"Programmatic Context Menu", disabled:true}));
+            pMenu.addChild(new dijit.MenuSeparator());
+            pMenu.addChild(new dijit.MenuItem({label:"Simple menu item", onClick:fClick, accelKey:"Shift+S"}));
+            pMenu.addChild(new dijit.MenuItem({label:"Another menu item", onClick:fClick, accelKey:"Ctrl+A"}));
+            pMenu.addChild(new dijit.MenuItem({label:"With an icon", iconClass:"dijitEditorIcon dijitEditorIconCut", onClick:fClick}));
+            var mItem = new dijit.MenuItem({label:"dojo.event clicking", accelKey: "Alt+D"});
+            dojo.connect(mItem, "onClick", function(){console.log("click! handler created via dojo.connect()")});
+            pMenu.addChild(mItem);
+
+            mItem = new dijit.CheckedMenuItem({label:"checkable menu item"});
+            pMenu.addChild(mItem);
+
+            var pSubMenu = new dijit.Menu({parentMenu:pMenu, id:"progSubMenu"});
+            pSubMenu.addChild(new dijit.MenuItem({label:"Submenu item", onClick:fClick}));
+            pSubMenu.addChild(new dijit.MenuItem({label:"Submenu item", onClick:fClick}));
+			
+            var pSubSubMenu = new dijit.Menu({parentMenu:pSubMenu, id:"progSubSubMenu"});
+            pSubSubMenu.addChild(new dijit.MenuItem({label:"SubSubmenu item", onClick:fClick}));
+            pSubSubMenu.addChild(new dijit.MenuItem({label:"SubSubmenu item", onClick:fClick}));
+            pSubMenu.addChild(new dijit.PopupMenuItem({label:"SubSubmenu", popup:pSubSubMenu, id:"progPopupMenuItem2"}));
+
+            pMenu.addChild(new dijit.PopupMenuItem({label:"Submenu", popup:pSubMenu, id:"progPopupMenuItem"}));
+
+            pMenu.startup();
+
+	    updateButtons(true);
+            dojo.byId("prog_menu").innerHTML="This div has a programmatic context menu on it that's different to the page menu.";
+
+            dojo.byId("createButton").disabled = true;
+            dojo.byId("destroyButton").disabled = false;
+        }
+
+        function destroyMenu(){
+        	pMenu.destroyRecursive();
+            updateButtons(false);
+        }
+
+	function updateButtons(created){
+            dojo.byId("prog_menu").innerHTML=created?"This div has a programmatic context menu on it that's different to the page menu.":"No programmatic menu on this div, should get page level menu.";
+            dojo.byId("createButton").disabled = created;
+            dojo.byId("destroyButton").disabled = !created;
+	}
+	dojo.addOnLoad(function(){
+		// need to explicitly update our buttons states, otherwise the
+		// browser will remember the last states of them before reloading
+		// (so a programmatic menu is created, reload, and "the create
+		// programmatic menu" button is still in disabled state)
+		updateButtons(false);
+	});
+    </script>
+</head>
+<body class="claro">
+
+	<div dojoType="dijit.Menu" id="windowContextMenu" contextMenuForWindow="true" style="display: none;">
+		<div dojoType="dijit.MenuItem" onClick="console.log('Hello world');">Context Menu</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.MenuItem" disabled="true" onClick="alert('this shouldn\'t appear');">Disabled Item</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+			onClick="console.log('not actually cutting anything, just a test!')" accelKey="Ctrl+X">Cut</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+			onClick="console.log('not actually copying anything, just a test!')" accelKey="Ctrl+C">Copy</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+			onClick="console.log('not actually pasting anything, just a test!')" accelKey="Ctrl+V">Paste</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.PopupMenuItem" id="enabledSubmenu">
+			<span>Enabled Submenu</span>
+			<div dojoType="dijit.Menu" id="submenu2">
+				<div dojoType="dijit.MenuItem" id="submenu2_item1" onClick="console.log('Submenu 1!')">Submenu Item One</div>
+				<div dojoType="dijit.MenuItem" id="submenu2_item2" onClick="console.log('Submenu 2!')">Submenu Item Two</div>
+				<div dojoType="dijit.PopupMenuItem" id="deeperSubmenu">
+					<span>Deeper Submenu</span>
+					<div dojoType="dijit.Menu" id="submenu4">
+						<div dojoType="dijit.MenuItem" onClick="console.log('Sub-submenu 1!')">Sub-sub-menu Item One</div>
+						<div dojoType="dijit.MenuItem" onClick="console.log('Sub-submenu 2!')">Sub-sub-menu Item Two</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem" disabled="true">
+			<span>Disabled Submenu</span>
+			<div dojoType="dijit.Menu" id="submenu3" style="display: none;">
+				<div dojoType="dijit.MenuItem" onClick="console.log('Submenu 1!')">Submenu Item One</div>
+				<div dojoType="dijit.MenuItem" onClick="console.log('Submenu 2!')">Submenu Item Two</div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Different popup</span>
+			<div dojoType="dijit.ColorPalette"></div>
+		</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.CheckedMenuItem" checked="true" onChange="console.log('Now set to ' + arguments[0])">Checked</div>
+		<div dojoType="dijit.CheckedMenuItem">Not Checked</div>
+		<div dojoType="dijit.CheckedMenuItem" checked="true" disabled="true">Checked Disabled</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Bigger Submenu</span>
+			<div dojoType="dijit.Menu" id="bigsubmenu" style="display: none;">
+				<div dojoType="dijit.MenuItem">Item One</div>
+				<div dojoType="dijit.MenuItem">Item Two</div>
+				<div dojoType="dijit.MenuItem">Item Three</div>
+				<div dojoType="dijit.MenuItem">Item Four</div>
+				<div dojoType="dijit.MenuItem">Item Five</div>
+				<div dojoType="dijit.MenuItem">Item Six</div>
+				<div dojoType="dijit.MenuItem">Item Seven</div>
+				<div dojoType="dijit.MenuItem">Item Eight</div>
+				<div dojoType="dijit.MenuItem">Item Nine</div>
+				<div dojoType="dijit.MenuItem">Item Ten</div>
+			</div>
+		</div>
+	</div>
+
+	<div dojoType="dijit.Menu" id="leftClickContextMenu" leftClickToOpen="true" targetNodeIds="input2" style="display: none;">
+		<div dojoType="dijit.MenuItem" disabled="true">Left Click Menu</div>
+		<div dojoType="dijit.MenuItem" onClick="console.log('Hello world');">Enabled Item</div>
+		<div dojoType="dijit.MenuItem" disabled="true">Disabled Item</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+			onClick="console.log('not actually cutting anything, just a test!')">Cut</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+			onClick="console.log('not actually copying anything, just a test!')">Copy</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+			onClick="console.log('not actually pasting anything, just a test!')">Paste</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Enabled Submenu</span>
+			<div dojoType="dijit.Menu" id="leftsubmenu2">
+				<div dojoType="dijit.MenuItem" onClick="console.log('Submenu 1!')">Submenu Item One</div>
+				<div dojoType="dijit.MenuItem" onClick="console.log('Submenu 2!')">Submenu Item Two</div>
+				<div dojoType="dijit.PopupMenuItem">
+					<span>Deeper Submenu</span>
+					<div dojoType="dijit.Menu" id="leftsubmenu4">
+						<div dojoType="dijit.MenuItem" onClick="console.log('Sub-submenu 1!')">Sub-sub-menu Item One</div>
+						<div dojoType="dijit.MenuItem" onClick="console.log('Sub-submenu 2!')">Sub-sub-menu Item Two</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem" disabled="true">
+			<span>Disabled Submenu</span>
+			<div dojoType="dijit.Menu" id="leftsubmenu3" style="display: none;">
+				<div dojoType="dijit.MenuItem" onClick="console.log('Submenu 1!')">Submenu Item One</div>
+				<div dojoType="dijit.MenuItem" onClick="console.log('Submenu 2!')">Submenu Item Two</div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Different popup</span>
+			<div dojoType="dijit.ColorPalette"></div>
+		</div>
+	</div>
+
+	<table id="formattingTable">
+		<tr>
+			<td width="0%">
+				<!-- This is here for tabIndex testing.
+				     Use textarea since Chrome 1.0 likes it better for TABing and
+				     because it has innerText property and because it doesn't mess
+				     with the URL when clicked -->
+				<textarea id="link" tabIndex="0" readOnly class="dijitReset" style="font-family:monospace;font-size:12px;width:84px;text-decoration:underline;overflow:hidden;background-color:transparent;" rows=1>random link</textarea>
+			</td>
+			<td id="menuBarContainer" width="100%">
+				<div id="menubar" dojoType="dijit.MenuBar">
+					<div dojoType="dijit.PopupMenuBarItem" id="file">
+						<span>File</span>
+						<div dojoType="dijit.Menu" id="fileMenu">
+							<div dojoType="dijit.MenuItem" id="new">New</div>
+							<div dojoType="dijit.MenuItem" id="open">Open</div>
+							<div dojoType="dijit.MenuSeparator" id="separator"></div>
+							<div dojoType="dijit.MenuItem" id="save" iconClass="dijitEditorIconSave">Save</div>
+							<div dojoType="dijit.MenuItem" id="saveas">Save As...</div>
+						</div>
+					</div>
+					<div dojoType="dijit.PopupMenuBarItem" id="edit">
+						<span>Edit</span>
+						<div dojoType="dijit.Menu" id="editMenu">
+							<div dojoType="dijit.MenuItem" id="cut" iconClass="dijitEditorIcon dijitEditorIconCut"
+								onClick="console.log('not actually cutting anything, just a test!');" accelKey="Ctrl+X">Cut</div>
+							<div dojoType="dijit.MenuItem" id="copy" iconClass="dijitEditorIcon dijitEditorIconCopy"
+								onClick="console.log('not actually copying anything, just a test!')" accelKey="Ctrl+C">Copy</div>
+							<div dojoType="dijit.MenuItem" id="paste" iconClass="dijitEditorIcon dijitEditorIconPaste"
+								onClick="console.log('not actually pasting anything, just a test!')" accelKey="Ctrl+V">Paste</div>
+						</div>
+					</div>
+					<div dojoType="dijit.PopupMenuBarItem" id="view">
+						<span>View</span>
+						<div dojoType="dijit.Menu" id="viewMenu">
+							<div dojoType="dijit.MenuItem">Normal</div>
+							<div dojoType="dijit.MenuItem">Outline</div>
+							<div dojoType="dijit.PopupMenuItem">
+								<span>Zoom</span>
+								<div dojoType="dijit.Menu" id="zoomMenu">
+									<div dojoType="dijit.MenuItem">50%</div>
+									<div dojoType="dijit.MenuItem">75%</div>
+									<div dojoType="dijit.MenuItem">100%</div>
+									<div dojoType="dijit.MenuItem">150%</div>
+									<div dojoType="dijit.MenuItem">200%</div>
+								</div>
+							</div>
+						</div>
+					</div>
+					<div dojoType="dijit.PopupMenuBarItem" id="help">
+						<span>Help</span>
+						<div dojoType="dijit.Menu" id="helpMenu">
+							<div dojoType="dijit.MenuItem">Help Topics</div>
+							<div dojoType="dijit.MenuItem">About Dijit</div>
+						</div>
+					</div>
+					<div dojoType="dijit.PopupMenuBarItem" disabled="true">
+						<span>Disabled</span>
+						<div dojoType="dijit.Menu">
+							<div dojoType="dijit.MenuItem">You should not see this</div>
+						</div>
+					</div>
+					<div dojoType="dijit.PopupMenuBarItem">
+						<span>Empty</span>
+						<div dojoType="dijit.Menu">
+						</div>
+					</div>
+					<div dojoType="dijit.MenuBarItem" onclick="console.log('no submenu, just a clickable MenuItem');">
+						Click me!
+					</div>
+				</div>
+			</td>
+		</tr>
+		<tr>
+			<td id="navMenuContainer" class="dijitMenu" valign=top width="0%">
+
+				<h3 style="margin-bottom: 2em;">Navigation menu:</h3>
+				<div dojoType="dijit.Menu" id="navMenu">
+					<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+						onClick="console.log('drama!');">Drama</div>
+					<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+						onClick="console.log('comedy!')">Comedy</div>
+					<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+						onClick="console.log('romance!')">Romance</div>
+					<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+						onClick="console.log('documentary!')">Documentary</div>
+					<div dojoType="dijit.MenuSeparator"></div>
+					<div dojoType="dijit.PopupMenuItem" id="navMenuPopupItem1">
+						<span>Enabled Submenu</span>
+						<div dojoType="dijit.Menu" id="navMenuSub1">
+							<div dojoType="dijit.MenuItem" id="navMenuSub1_item1" onClick="console.log('Submenu 1!')">Submenu Item One</div>
+							<div dojoType="dijit.MenuItem" id="navMenuSub1_item2" onClick="console.log('Submenu 2!')">Submenu Item Two</div>
+							<div dojoType="dijit.PopupMenuItem" id="navMenuSub1_popup">
+								<span>Deeper Submenu</span>
+								<div dojoType="dijit.Menu" id="navMenuSub2">
+									<div dojoType="dijit.MenuItem" onClick="console.log('Sub-submenu 1!')">Sub-sub-menu Item One</div>
+									<div dojoType="dijit.MenuItem" onClick="console.log('Sub-submenu 2!')">Sub-sub-menu Item Two</div>
+								</div>
+							</div>
+						</div>
+					</div>
+					<div dojoType="dijit.PopupMenuItem" disabled="true" id="navMenuDisabledItem">
+						<span>Disabled Submenu</span>
+						<div dojoType="dijit.Menu" id="navMenuSub3" style="display: none;">
+							<div dojoType="dijit.MenuItem" onClick="console.log('Submenu 1!')">Submenu Item One</div>
+							<div dojoType="dijit.MenuItem" onClick="console.log('Submenu 2!')">Submenu Item Two</div>
+						</div>
+					</div>
+					<div dojoType="dijit.PopupMenuItem">
+						<span>Different popup</span>
+						<div dojoType="dijit.ColorPalette"></div>
+					</div>
+					<div dojoType="dijit.MenuSeparator"></div>
+					<div dojoType="dijit.CheckedMenuItem" checked="true" onChange="console.log('Now set to ' + arguments[0])">Checked</div>
+					<div dojoType="dijit.CheckedMenuItem" id="checked2" >Not Checked</div>
+					<div dojoType="dijit.CheckedMenuItem" checked="true" disabled="true">Checked Disabled</div>
+				</div>
+			</td>
+
+			<td style="padding: 1em" id="contentContainer">
+
+				<h1 class="testTitle">Dijit Menu System Test</h1>
+
+				<p>This page contains:</p>
+				<ul>
+					<li>"Navigation bar" Menu widget on left, a.k.a vertical MenuBar
+					<li>MenuBar on top
+					<li>page level context menu (right-click anywhere on page)
+					<li>left click context menu (left click on input on far right)
+					<li>Example of programatically created menu
+					<li>Note: while some accelerator (shortcut) keys are displayed in the context menu, they are not actually hooked up to the corresponding actions (if any), they need to be setup explicitly by the user
+				</ul>
+
+				<h3>Form</h3>
+
+				<form>
+					<p style="float:right; text-align: right;">
+						left click to open the menu for this input:<br/>
+						Note: because of the window contextMenu, make sure you get<br/>
+						the right menu by verifying the left<br/>
+						click one starts with "Left Click Menu"<br/>
+						at the very top.
+						<input id=input2 value="top-right">
+					</p>
+					<input id=input1 value="top-left">
+					<textarea id=textarea>hello there!</textarea><br>
+					<select>
+						<option>check if i</option>
+						<option>bleed through</option>
+						<option>on IE6</option>
+					</select>
+					<button id=button>push me</button>
+				</form>
+
+			    <div id="prog_menu" style="clear: both; border:1px solid blue; padding:10px; margin:20px 0;">
+			        Click button below to create special menu on this div.
+			    </div>
+			    <button id="createButton" onclick="createMenu();">create programmatic menu</button>
+			    <button id="destroyButton" onclick="destroyMenu();" disabled>destroy programmatic menu</button>
+
+				<div style="height:500px"></div>
+				<p>(this space intentionally left blank to aid testing with controls
+				at the bottom of the browser window)</p>
+				<div style="height:500px"></div>
+				<input id=input3 value="bottom-left">
+				<p style="text-align:right"><input id=input4 value="bottom-right"></p>
+
+				<p>See also: <a href="form/test_Button.html">form/test_Button</a>
+				(PopupMenu is used with DropDownButton and ComboButton)</p>
+
+				<h3>Mouse opening tests</h3>
+
+				<ul>
+					<li>Right click on the client area of the page (ctrl-click for Macintosh). Menu should open.</li>
+					<li>Right click on each of the form controls above. Menu should open.</li>
+					<li>Right click near the righthand window border. Menu should open to the left of the pointer.</li>
+					<li>Right click near the bottom window border. Menu should open above the pointer.</li>
+				</ul>
+
+
+				<h3>Mouse hover tests</h3>
+
+				<ul>
+					<li>Hover over the first item with the pointer. Item should highlight and get focus.</li>
+					<li>Hover over the second (disabled) item. Item should highlight and get focus.</li>
+					<li>Seperator items should not highlight on hover - no items should highlight in this case.</li>
+				</ul>
+
+
+				<h3>Mouse click tests</h3>
+
+				<ul>
+					<li>Click on the first menu item. console.log should log the message "Hello world". The menu should dissapear.</li>
+					<li>Click on the second menu item (disabled). Should not do anything - focus should remain on the disabled item.</li>
+					<li>Click anywhere outside the menu. Menu should close. Focus will be set by the browser based on where the user clicks.</li>
+				</ul>
+
+
+				<h3>Mouse submenu tests</h3>
+
+				<ul>
+					<li>Hover over the "Enabled Submenu" item. Item should highlight and then pop open a submenu after a short (500ms) delay.</li>
+					<li>Hover over any of the other menu items. Submenu should close immediately and deselect the submenu parent item. The newly hovered item should become selected.</li>
+					<li>Hover over the "Disabled Submenu" item. Item should highlight, but no submenu should appear.</li>
+					<li>Clicking on the "Enabled Submenu" item before the submenu has opened (you'll have to be quick!) should immediatley open the submenu.</li>
+					<li>Clicking on the "Enabled Submenu" item <i>after</i> the submenu has opened should have no effect - the item is still selected and the submenu still open.</li>
+					<li>Hover over submenu item 1. Should select it - the parent menu item should stay selected also.</li>
+					<li>Hover over submenu item 2. Should select it - the parent menu item should stay selected also.</li>
+				</ul>
+
+
+				<h3>Keyboard opening tests</h3>
+
+				<ul>
+					<li>On Windows: press shift-f10 with focus on any of the form controls. Should open the menu.</li>
+					<li>On Windows: press the context menu key (located on the right of the space bar on North American keyboards) with focus on any of the form controls. Should open the menu.</li>
+					<li>On Firefox on the Mac: press ctrl-space with focus on any of the form controls. Should open the menu.</li>
+				</ul>
+
+
+				<h3>Keyboard closing tests</h3>
+
+				<ul>
+					<li>Open the menu.</li>
+					<li>Press tab. Should close the menu and return focus to where it was before the menu was opened.</li>
+					<li>Open the menu.</li>
+					<li>Press escape. Should close the menu and return focus to where it was before the menu was opened.</li>
+				</ul>
+
+
+				<h3>Keyboard navigation tests</h3>
+
+				<ul>
+					<li>Open the menu.</li>
+					<li>Pressing up or down arrow should cycle focus through the items in that menu.</li>
+					<li>Pressing enter or space should invoke the menu item.</li>
+					<li>Disabled items receive focus but no action is taken upon pressing enter or space.</li>
+				</ul>
+
+
+				<h3>Keyboard submenu tests</h3>
+
+				<ul>
+					<li>Open the menu.</li>
+					<li>The first item should become selected.</li>
+					<li>Press the right arrow key. Nothing should happen.</li>
+					<li>Press the left arrow key. Nothing should happen.</li>
+					<li>Press the down arrow until "Enabled Submenu" is selected. The submenu should not appear.</li>
+					<li>Press enter. The submenu should appear with the first item selected.</li>
+					<li>Press escape. The submenu should vanish - "Enabled Submenu" should remain selected.</li>
+					<li>Press the right arrow key. The submenu should appear with the first item selected.</li>
+					<li>Press the right arrow key. Nothing should happen.</li>
+					<li>Press the left arrow key. The submenu should close - "Enabled Submenu" should remain selected.</li>
+					<li>Press the left arrow key. The menu should <i>not</i> close and "Enabled Submenu" should remain selected.</li>
+					<li>Press escape. The menu should close and focus should be returned to where it was before the menu was opened.</li>
+				</ul>
+			</td>
+		</tr>
+	</table>
+</body>
+</html>
diff --git a/dijit/tests/test_Menu_iframe.html b/dijit/tests/test_Menu_iframe.html
new file mode 100644
index 0000000..3fa36b6
--- /dev/null
+++ b/dijit/tests/test_Menu_iframe.html
@@ -0,0 +1,38 @@
+<html>
+<head>
+<style type="text/css">
+	@import "../themes/tundra/tundra.css";
+</style>
+<script type="text/javascript" src="../../dojo/dojo.js"
+	djConfig="parseOnLoad:true, isDebug:true"></script>
+<script type="text/javascript">
+	dojo.require("dijit.Menu");
+
+	function setContents(str){
+		dojo.byId('iframe').src = "javascript:'" + str.replace("'", "\\'") + "'";
+	}
+	function button2(){
+		setContents('<div style="height: 300px; border: solid blue 2px">bill was here</div>');
+	}
+</script>
+</head>
+<body class="claro">
+	<div dojoType="dijit.Menu" id="menu" targetNodeIds="iframe" style="display:none;">
+		<div dojoType="dijit.MenuItem">context menu</div>
+	</div>
+	<div style="border: 1px solid gray; height: 150px;">filler div to offset iframe position (for testing)</div>
+	<div style="position: relative; border: 3px solid blue; padding: 10px;">
+		This is a position:relative div containing an iframe.
+		<iframe id="iframe"
+			src="javascript:'<html><body style=\'margin: 3em;\'><div style=\'height:300px;border:1px solid red;\'>right click for menu</div><body></html>'"
+			style="height: 200px; margin: 30px; padding: 20px; border: solid dotted 10px;" onload="console.log('iframe onload');">
+		</iframe>
+		End of div.
+	</div>
+	<br>
+	<button onclick="dojo.byId('iframe').src='layout/doc0.html'">reset contents to doc0.html</button>
+	<button onclick="button2();">reset contents to 'bill was here'</button>
+	<button onclick="dijit.byId('menu').unBindDomNode('iframe')">detach menu</button>
+	<button onclick="dijit.byId('menu').bindDomNode('iframe')">re-attach menu</button>
+</body>
+</html>
diff --git a/dijit/tests/test_ProgressBar.html b/dijit/tests/test_ProgressBar.html
new file mode 100644
index 0000000..a832030
--- /dev/null
+++ b/dijit/tests/test_ProgressBar.html
@@ -0,0 +1,172 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo Toolkit - ProgressBar test</title>
+
+	<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+		body {
+			margin: 1em;
+		}
+		.smallred .dijitProgressBarTile {
+			background:red;
+		}
+		.smallred .dijitProgressBarLabel {
+			display:none;
+		}
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.ProgressBar");
+		dojo.require("dojo.parser");	// scan page for widgets
+		dojo.require("dojo.string");
+
+		dojo.addOnLoad(go);
+
+		function go(){
+			// note that programmatic instantiation doesn't pull any parameters from the srcNodeRef, not even id
+			var theBar = new dijit.ProgressBar({id: "testBar", width: 400, maximum: 256, duration: 2000,
+				report:function(percent){
+					return dojo.string.substitute("${0} out of ${1} max chars", [this.progress, this.maximum]);
+				}
+			}, dojo.byId("testBar"));
+
+			dojo.byId("test").value="";
+			dojo.byId("progressValue").focus();
+			dojo.byId("progressValue").value = dijit.byId("setTestBar").progress;
+			dojo.byId("maximum").value = dijit.byId("setTestBar").maximum;
+			dojo.connect(dojo.byId("test"), "onkeyup", null, keyUpHandler);
+			dojo.connect(dojo.byId("set"), "onclick", null, setParameters);
+			dojo.connect(dojo.byId("startTimer"), "onclick", null,
+				function(){ remoteProgress(dijit.byId("timerBar")); } );
+
+			function indeterminateSetter(id, value){
+				return function(){
+					dijit.byId(id).update({'indeterminate': value});
+				}
+			}
+			dojo.connect(dojo.byId("setIndeterminate1True"), "onclick", null,
+				indeterminateSetter("indeterminateBar1", true));
+			dojo.connect(dojo.byId("setIndeterminate1False"), "onclick", null,
+				indeterminateSetter("indeterminateBar1", false));
+			dojo.connect(dojo.byId("setIndeterminate2True"), "onclick", null,
+				indeterminateSetter("indeterminateBar2", true));
+			dojo.connect(dojo.byId("setIndeterminate2False"), "onclick", null,
+				indeterminateSetter("indeterminateBar2", false));
+		}
+
+		// An example of polling on a separate (heartbeat) server thread.  This is useful when the progress
+		// is entirely server bound and there is no existing interaction with the server to determine status.
+
+		// We don't have a server to run against, but a simple heartbeat implementation might look something
+		// like this:
+
+		// function getProgressReport(){
+		//	var dataSource = "http://dojotoolkit.org";
+		//	return dojo.xhrGet({url: dataSource, handleAs: "json", content: {key: "progress"}});
+		// }
+
+		// Instead, we'll just tick off intervals of 10
+
+		var fakeProgress = 0;
+		function getProgressReport(){
+			var deferred = new dojo.Deferred();
+			fakeProgress = Math.min(fakeProgress + 10, 100);
+			deferred.callback(fakeProgress+"%");
+			return deferred;
+		}
+
+		function remoteProgress(bar){
+			var _timer = setInterval(function(){
+				var report = getProgressReport();
+				report.addCallback(function(response){
+					bar.update({progress: response});
+					if(response == "100%"){
+						clearInterval(_timer);
+						_timer = null;
+						return;
+					}
+				});
+			}, 3000); // on 3 second intervals
+		}
+
+		function setParameters(){
+			dijit.byId("setTestBar").update({maximum: dojo.byId("maximum").value, progress: dojo.byId("progressValue").value});
+		}
+
+		function keyUpHandler(){
+			dijit.byId("testBar").update({progress:dojo.byId("test").value.length});
+			dijit.byId("testBarInt").update({progress:dojo.byId("test").value.length});
+			dijit.byId("smallTestBar").update({progress:dojo.byId("test").value.length});
+		}
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit ProgressBar Tests</h1>
+
+	<h3>Test 1</h3>
+	Progress Value <input type="text" name="progressValue" id="progressValue" />
+	<br>
+	Max Progress Value <input type="text" name="maximum" id="maximum" />
+	<br>
+	<input type="button" name="set" id="set" value="set!" />
+	<br>
+	<div style="width:400px"
+		maximum="200" id="setTestBar" progress="20" dojoType="dijit.ProgressBar"></div>
+
+	<h3>Test 2</h3>
+	Write here: <input type="text" value="" name="test" maxLength="256" id="test" style="width:300"/>
+	<br />
+	<br />
+	<div id="testBar" style='width:300px'></div>
+	<br />
+	Small, without text and background image:
+	<br />
+	<div style="width:400px; height:10px" class="smallred"
+		maximum="256" id="smallTestBar" dojoType="dijit.ProgressBar"></div>
+	<br />
+	Show decimal place:
+	<div places="1" style="width:400px"
+		maximum="256" id="testBarInt" dojoType="dijit.ProgressBar"></div>
+
+	<h3>Test 3</h3>
+	No explicit maximum (both 50%)
+	<div style="width:400px"
+		id="implied1" progress="50" dojoType="dijit.ProgressBar"></div>
+	<br />
+	<div style="width:400px"
+		id="implied2" progress="50%" dojoType="dijit.ProgressBar"></div>
+
+	<h3>Test 4</h3>
+	<input type="button" name="startTimer" id="startTimer" value="Start Timer" />
+	<div style="width:400px" id="timerBar"
+		maximum="100" progress="0" dojoType="dijit.ProgressBar"></div>
+
+	<h3>Test 5 - indeterminate progess</h3>
+	<input type="button" name="setIndeterminate1True" id="setIndeterminate1True" value="Make Indeterminate" />
+	<input type="button" name="setIndeterminate1False" id="setIndeterminate1False" value="Make Determinate" />
+	<div style="width:400px" indeterminate="true" id="indeterminateBar1"
+		dojoType="dijit.ProgressBar"></div>
+	<input type="button" name="setIndeterminate2True" id="setIndeterminate2True" value="Make Indeterminate" />
+	<input type="button" name="setIndeterminate2False" id="setIndeterminate2False" value="Make Determinate" />
+	<div style="width:400px" progress="50" id="indeterminateBar2"
+		dojoType="dijit.ProgressBar"></div>
+
+</body>
+</html>
diff --git a/dijit/tests/test_TitlePane.html b/dijit/tests/test_TitlePane.html
new file mode 100644
index 0000000..94ef483
--- /dev/null
+++ b/dijit/tests/test_TitlePane.html
@@ -0,0 +1,162 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>TitlePane Test</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.TitlePane");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		// widgets used inside subpage loaded via href=
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.LinkPane");
+
+		function randomMessageId(){
+			return Math.floor(Math.random() * 3) + 3;
+		}
+
+		dojo.declare("dijit.TestTitlePane", dijit.TitlePane, {
+			templateString: '<div class="dijitTitlePane">' +
+							'    <div class="dijitTitlePaneTitle" dojoAttachPoint="titleBarNode" style="cursor: default;">' +
+							        '<span dojoAttachEvent="onclick:toggle,onkeypress: _onTitleKey" tabindex="0"' +
+							                'waiRole="button" dojoAttachPoint="focusNode,arrowNode" style="cursor: pointer;">' +
+										'<img src="${_blankGif}" alt="" class="dijitArrowNode" waiRole="presentation">' +
+										'<span dojoAttachPoint="arrowNodeInner" class="dijitArrowNodeInner"></span>' +
+									 '</span>' +
+							        '<span dojoAttachPoint="titleNode" class="dijitTitlePaneTextNode"></span>' +
+							    '</div>' +
+							    '<div class="dijitTitlePaneContentOuter" dojoAttachPoint="hideNode">' +
+							        '<div class="dijitReset" dojoAttachPoint="wipeNode">' +
+							            '<div class="dijitTitlePaneContentInner" dojoAttachPoint="containerNode" waiRole="region" tabindex="-1">' +
+							            '</div>' +
+							        '</div>' +
+							    '</div>' +
+							'</div>'
+		});
+	</script>
+</head>
+<body class="claro">
+	<h1 class="testTitle">Dijit TitlePane Test</h1>
+
+	<input id="input" value="for tab testing">
+
+	<h1>Test #1: plain title pane, width=300px</h1>
+	<div dojoType="dijit.TitlePane" title="Title Pane #1"
+		tooltip="I'm the tooltip for Title Pane #1's title bar"
+		style="width: 300px;" jsId="pane1" id="testPane1">
+		Lorem Ipsum Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque
+		iaculis, nulla id semper faucibus, pede tellus nonummy magna, vitae adipiscing
+		orci arcu ut augue. Nunc condimentum, magna a vestibulum convallis, libero purus
+		pulvinar orci, sed vestibulum urna sem ut pede. More Ipsum...
+		Sed sollicitudin suscipit risus. Nam ullamcorper. Sed nisl lectus, pellentesque
+		nec, malesuada eget, ornare a, libero. Lorem ipsum dolor sit amet,
+		consectetuer adipiscing elit.
+	</div>
+	<button id="titleButton" onclick="pane1.set('title', 'New Title')">change title</button>
+	<button id="closeButton" onclick="pane1.set('open', false)">close pane</button>
+	<h1>Test #2: title pane with form, width=300px</h1>
+
+	<div dojoType="dijit.TitlePane" title="Title Pane #2" id="pane_2" style="width: 300px;">
+		<form>
+			<label for="age">Age: </label> <input id="age"><br>
+			<label for="disc">Discount card </label><input id="disc" type=checkbox><br>
+			<button>Submit</button><br>
+		</form>
+	</div>
+	<br>
+
+	<h1>Test #3: initially closed pane</h1>
+	<div id="closed" dojoType="dijit.TitlePane" title="Initially closed pane" open="false" width="200">
+		<form>
+			<label for="age">Age: </label><input id="age"><br>
+			<label for="discount">Discount card </label><input type="checkbox" id="discount"><br>
+			<button>Submit</button><br>
+		</form>
+
+		<p>And a TabContainer, to make sure it lays out correctly:</p>
+		<div id="tabContainer" dojoType="dijit.layout.TabContainer" style="width: 400px; height: 250px;">
+			<a dojoType="dijit.layout.LinkPane" href="layout/tab1.html" onLoad="console.log('load of SubTab 1');">SubTab 1</a>
+			<a dojoType="dijit.layout.LinkPane" href="layout/tab2.html"  onLoad="console.log('load of SubTab 2');" selected="true">SubTab 2</a>
+		</div>
+	</div>
+	<button onclick="dijit.byId('closed').set('content', 'hello world! (' + new Date() + ')');">reset content</button>
+
+	<h1>Test #4: title pane with href (initially closed)</h1>
+	<p>The pane should open to "Loading..." message and then 3 seconds later it should slide open more to show loaded data.</p>
+	<div dojoType="dijit.TitlePane" duration="1000" title="Pane from href" id="href1" open="false"
+		href="layout/getResponse.php?delay=3000&messId=3" preventCache="true"
+		style="width: 400px;">
+		Loading...
+	</div>
+
+	<h1>Test #5: title pane with href (initially closed)</h1>
+	<p>The pane should start to open to "Loading..." but halfway through href data will be loaded, and it should expand correctly.</p>
+	<div dojoType="dijit.TitlePane" duration="1000" title="Pane from href" id="href2" open="false"
+		href="layout/getResponse.php?delay=500&messId=3" preventCache="true"
+		style="width: 400px;">
+		Loading...
+	</div>
+
+	<h1>Test #6: nested title pane</h1>
+	<div id="outer" dojoType="dijit.TitlePane" title="Outer pane" width="300">
+		<p>This is a title pane, containing another title pane ...
+		<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque iaculis, nulla id semper faucibus, pede tellus nonummy magna, vitae adipiscing orci arcu ut augue. Nunc condimentum, magna a vestibulum convallis, libero purus pulvinar orci, sed vestibulum urna sem ut pede.
+More Ipsum...
+
+		<div id="inner" dojoType="dijit.TitlePane" title="Inner pane" width="250">
+			<p>And this is the inner title pane...
+			<p>Sed sollicitudin suscipit risus. Nam ullamcorper. Sed nisl lectus, pellentesque nec, malesuada eget, ornare a, libero. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+		</div>
+
+		<p>And this is the closing line for the outer title pane.
+	</div>
+
+	<h1>Test #7: subclassed title pane (only arrow is selectable and focusable)</h1>
+	<div dojoType="dijit.TestTitlePane" title="Title Pane #7" style="width: 300px;" id="ttp">
+		Lorem Ipsum Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque
+		iaculis, nulla id semper faucibus, pede tellus nonummy magna, vitae adipiscing
+		orci arcu ut augue. Nunc condimentum, magna a vestibulum convallis, libero purus
+		pulvinar orci, sed vestibulum urna sem ut pede. More Ipsum...
+		Sed sollicitudin suscipit risus. Nam ullamcorper. Sed nisl lectus, pellentesque
+		nec, malesuada eget, ornare a, libero. Lorem ipsum dolor sit amet,
+		consectetuer adipiscing elit.
+	</div>
+
+	<table style="border: solid blue 2px; margin-top: 1em;">
+		<tr>
+			<td>
+				Here's some text below the title panes (to make sure that closing a title pane releases the space that the content was taking up)
+			</td>
+		</tr>
+	</table>
+	<h1>Test #8: locked open title pane</h1>
+	<div dojoType="dijit.TitlePane" title="Title Pane #8" style="width: 300px;" toggleable="false" id="locked">
+		Lorem Ipsum Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque
+		iaculis, nulla id semper faucibus, pede tellus nonummy magna, vitae adipiscing
+		orci arcu ut augue. Nunc condimentum, magna a vestibulum convallis, libero purus
+		pulvinar orci, sed vestibulum urna sem ut pede. More Ipsum...
+		Sed sollicitudin suscipit risus. Nam ullamcorper. Sed nisl lectus, pellentesque
+		nec, malesuada eget, ornare a, libero. Lorem ipsum dolor sit amet,
+		consectetuer adipiscing elit.
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/test_Toolbar.html b/dijit/tests/test_Toolbar.html
new file mode 100644
index 0000000..3b76936
--- /dev/null
+++ b/dijit/tests/test_Toolbar.html
@@ -0,0 +1,159 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo Toolbar Widget Test</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+
+		dojo.require("dijit.Declaration");
+		dojo.require("dijit.Toolbar");
+		dojo.require("dijit.ToolbarSeparator");
+
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.DropDownButton");
+		dojo.require("dijit.form.ComboButton");
+		dojo.require("dijit.form.ToggleButton");
+
+		dojo.require("dijit.ColorPalette");
+		dojo.require("dijit.TooltipDialog");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.Menu");
+
+		dojo.require("dojo.parser");
+
+		dojo.addOnLoad(function(){
+			// programatic creation
+			dojo.forEach(["toolbar2", "toolbar3", "toolbar4"], function(toolbarId){
+				var toolbar = new dijit.Toolbar({}, dojo.byId(toolbarId));
+				dojo.forEach(["Cut", "Copy", "Paste"], function(label){
+					var button = new dijit.form.Button({
+                        id: toolbarId+"."+label,
+                        // note: should always specify a label, for accessibility reasons.
+                        // Just set showLabel=false if you don't want it to be displayed normally
+                        label: label,
+                        showLabel: (toolbarId == "toolbar2" ? false : true),
+                        iconClass: toolbarId == "toolbar4" ? "" : "dijitEditorIcon dijitEditorIcon"+label
+                    });
+                    toolbar.addChild(button);
+				});
+			});
+			
+		});
+	</script>
+</head>
+<body class="claro">
+	<h1 class="testTitle">Toolbar test</h1>
+
+	<span dojoType="dijit.Declaration" widgetClass="ToolbarSectionStart" defaults="{ label: 'Label'}">
+		<span dojoType="dijit.ToolbarSeparator"></span><i>${label}:</i>
+	</span>
+
+	<h2>Toolbar from markup</h2>
+
+	<input id="toolbar1Before" value="input before toolbar1">
+	<div id="toolbar1" dojoType="dijit.Toolbar"
+			><div dojoType="ToolbarSectionStart" label="Buttons"></div
+			><div dojoType="dijit.form.Button" id="toolbar1.cut" iconClass="dijitEditorIcon dijitEditorIconCut" showLabel="false">Cut</div
+			><div dojoType="dijit.form.Button" id="toolbar1.copy" iconClass="dijitEditorIcon dijitEditorIconCopy" showLabel="true">Copy</div
+
+			><div dojoType="ToolbarSectionStart" label="Toggles"></div
+			><div dojoType="dijit.form.ToggleButton" id="toolbar1.bold" iconClass="dijitEditorIcon dijitEditorIconBold" showLabel="false">Bold</div
+			><div dojoType="dijit.form.ToggleButton" id="toolbar1.italic" iconClass="dijitEditorIcon dijitEditorIconItalic" showLabel="true">Italic</div
+
+><!--
+			<span dojoType="dijit.ToolbarSeparator"> </span>
+
+			<span dojo:type="ToolbarButtonGroup" name="justify" defaultButton="justifyleft" preventDeselect="true" showLabel="false">
+				<div dojoType="dijit.form.ToggleButton" iconClass="dijitEditorIcon dijitEditorIconJustifyLeft" name="justify" showLabel="false">Left</div>
+				<div dojoType="dijit.form.ToggleButton" iconClass="dijitEditorIcon dijitEditorIconJustifyRight" name="justify" showLabel="false">Right</div>
+				<div dojoType="dijit.form.ToggleButton" iconClass="dijitEditorIcon dijitEditorIconJustifyCenter" name="justify" showLabel="false">Center</div>
+			 </span>
+-->
+
+			<div dojoType="ToolbarSectionStart" label="Dropdowns"></div
+			><div dojoType="dijit.form.DropDownButton" id="toolbar1.dialog" iconClass="plusIcon" showLabel="true">
+				<span>TooltipDialog</span>
+				<div dojoType="dijit.TooltipDialog" id="tooltipDlg" title="Enter Login information"
+					execute="console.log('submitted w/args:\n' + dojo.toJson(arguments[0], true));">
+					<table>
+						<tr>
+							<td><label for="user">User:</label></td>
+							<td><input id="user" dojoType=dijit.form.TextBox type="text" name="user" ></td>
+						</tr>
+						<tr>
+							<td><label for="pwd">Password:</label></td>
+							<td><input id="password" dojoType=dijit.form.TextBox type="password" name="pwd"></td>
+						</tr>
+						<tr>
+							<td colspan="2" align="center">
+								<button dojoType=dijit.form.Button type="submit" name="submit">Login</button></td>
+						</tr>
+					</table>
+				</div
+			></div
+			><div dojoType="dijit.form.DropDownButton" id="toolbar1.backcolor" iconClass="dijitEditorIcon dijitEditorIconBackColor" showLabel="true">
+				<span>ColorPalette</span>
+				<div dojoType="dijit.ColorPalette" id="toolbar1.colorPalette" style="display: none" palette="7x10" onChange="console.log(this.value);"></div>
+			</div
+			><div dojoType="dijit.form.DropDownButton" id="toolbar1.forecolor" iconClass="dijitEditorIcon dijitEditorIconForeColor" showLabel="false">
+				<span>Foreground</span>
+				<div dojoType="dijit.ColorPalette" id="toolbar1.colorPalette2" style="display: none" palette="3x4" onChange="console.log(this.value);"></div>
+			</div
+
+			><div dojoType="ToolbarSectionStart" label="Combos"></div
+			><div dojoType="dijit.form.ComboButton" id="toolbar1.combo" optionsTitle='save options' iconClass="plusIcon" showLabel="true"
+				onClick='console.log("clicked combo save")'>
+				<span>Menu</span>
+				<div dojoType="dijit.Menu" id="saveMenu" style="display: none;">
+					<div dojoType="dijit.MenuItem"  iconClass="dijitEditorIcon dijitEditorIconSave"
+						onClick="console.log('not actually saving anything, just a test!')">Save</div>
+					<div dojoType="dijit.MenuItem"
+						onClick="console.log('not actually saving anything, just a test!')">Save As</div>
+				</div>
+			</div
+			><div dojoType="dijit.form.ComboButton" id="toolbar1.combo2" optionsTitle='save options2' iconClass="plusIcon" showLabel="false"
+				onClick='console.log("clicked combo save")'>
+				<span>Menu2</span>
+				<div dojoType="dijit.Menu" id="saveMenu2" style="display: none;">
+					<div dojoType="dijit.MenuItem"  iconClass="dijitEditorIcon dijitEditorIconSave"
+						onClick="console.log('not actually saving anything, just a test!')">Save</div>
+					<div dojoType="dijit.MenuItem"
+						onClick="console.log('not actually saving anything, just a test!')">Save As</div>
+				</div>
+			</div
+
+			><span dojoType="dijit.ToolbarSeparator"></span
+			><div dojoType="dijit.form.Button" id="toolbar1.insertorderedlist" iconClass="dijitEditorIcon dijitEditorIconInsertOrderedList" showLabel="false">Ordered list</div
+	></div>
+	<input id="toolbar1After" value="input after toolbar1">
+
+	<h2>Toolbar from script with icons only</h2>
+	<div id="toolbar2"></div>
+
+	<h2>Toolbar from script with text and icons</h2>
+	<div id="toolbar3"></div>
+
+	<h2>Toolbar from script with text only</h2>
+	<div id="toolbar4"></div>
+
+    <!-- leave some space before the console window -->
+    <br><br>
+  </body>
+</html>
diff --git a/dijit/tests/test_Tooltip.html b/dijit/tests/test_Tooltip.html
new file mode 100644
index 0000000..359d9a7
--- /dev/null
+++ b/dijit/tests/test_Tooltip.html
@@ -0,0 +1,192 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo Tooltip Widget Test</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+
+		td { padding: 20px; }
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Tooltip");
+		dojo.require("dijit.ColorPalette");
+		dojo.addOnLoad(function(){
+			console.log("on load func");
+			var tt = new dijit.Tooltip({label:"programmatically created tooltip", connectId:["programmaticTest"]});
+			console.log("created", tt, tt.id);
+
+			dojo.connect(dijit.byId("t_tooltip"),"onShow",function(t, p){
+				console.log("Dynamic target tooltip onShow", t, p);//To check correct order in event call
+				if(!p || !p.length){ p = dijit.Tooltip.defaultPosition; }
+				dojo.byId("t_shown").innerHTML = "Tooltip shown for node " + t.id + " at position " + p;
+			});
+			dojo.connect(dijit.byId("t_tooltip"),"onHide",function(){
+				console.log("Dynamic target tooltip onHide");//To check correct order in event call
+				dojo.byId("t_shown").innerHTML = "Tooltip hidden";
+			});
+			updateDynamicIds();
+		});
+
+		function updateDynamicIds(){
+			dojo.byId("t_connected_id").innerHTML = "Tooltip connected with nodes: " + dijit.byId("t_tooltip").get("connectId");
+		}
+		function addDynamicTarget(id){
+			dijit.byId("t_tooltip").addTarget(id);
+			updateDynamicIds();
+		}
+		function removeDynamicTarget(id){
+			dijit.byId("t_tooltip").removeTarget(id);
+			updateDynamicIds();
+		}
+
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Tooltip test</h1>
+
+	<p>Mouse-over or focus the items below to test tooltips.</p>
+	<table>
+		<tr>
+			<td>
+				Change tooltip positioning search list:
+			</td>
+			<td>
+				Set background color:
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<button onclick="dijit.Tooltip.defaultPosition=['above', 'below']; dojo.byId('current').innerHTML='Current: ' + dijit.Tooltip.defaultPosition;">above, below</button>
+				<button onclick="dijit.Tooltip.defaultPosition=['after', 'before']; dojo.byId('current').innerHTML='Current: ' + dijit.Tooltip.defaultPosition;">after, before (default)</button>
+				<div id=current>
+					Current: default (unchanged)
+				</div>
+			</td>
+			<td>
+				<div dojoType="dijit.ColorPalette" onChange="dojo.query('body').style('background', arguments[0]);"></div>
+			</td>
+		</tr>
+	</table>
+	<div><span id="one" class="tt" tabindex="0"> focusable text </span>
+		<span dojoType="dijit.Tooltip" connectId="one" id="one_tooltip">
+			<b>
+				<span style="color: blue;">rich formatting</span>
+				<span style="color: red; font-size: x-large;"><i>!</i></span>
+			</b>
+		</span>
+	</div>
+	<span id="oneA" class="tt"> plain text (not focusable) </span>
+	<span dojoType="dijit.Tooltip" connectId="oneA" id="oneA_tooltip">
+		<span> keyboard users can not access this tooltip</span>
+	</span>
+    <a id="three" href="#bogus">anchor</a>
+	<span dojoType="dijit.Tooltip" connectId="three" id="three_tooltip">tooltip on a link </span>
+	<p></p>
+
+	<span id="programmaticTest">this text has a programmatically created tooltip</span>
+	<br>
+
+	<button id="four">button w/tooltip</button>
+	<span id="btnTt" dojoType="dijit.Tooltip" connectId="four" id="four_tooltip">tooltip on a button</span>
+	<button id="removeButton" onclick="dijit.byId('btnTt').destroy()">Remove</button> tooltip from "button w/tooltip".
+
+	<span style="float: right">
+		Test tooltip on right aligned element.  Tooltip should flow to the left -->
+		<select id="seven">
+			<option value="alpha">Alpha</option>
+			<option value="beta">Beta</option>
+			<option value="gamma">Gamma</option>
+			<option value="delta">Delta</option>
+		</select>
+
+		<span dojoType="dijit.Tooltip" connectId="seven" id="seven_tooltip">
+			tooltip on a select<br>
+			two line tooltip.
+		</span>
+	</span>
+
+	<p></p>
+
+	<form>
+		<input id="id1" value="#1"><br>
+		<input id="id2" value="#2"><br>
+		<input id="id3" value="#3"><br>
+		<input id="id4" value="#4"><br>
+   		<input id="id5" value="#5"><br>
+		<input id="id6" value="#6"><br>
+	</form>
+	<br>
+
+	<div style="overflow: auto; height: 100px; position: relative; border: solid blue 3px;">
+		<span id="s1">s1 text</span><br><br><br>
+		<span id="s2">s2 text</span><br><br><br>
+		<span id="s3">s3 text</span><br><br><br>
+		<span id="s4">s4 text</span><br><br><br>
+		<span id="s5">s5 text</span><br><br><br>
+	</div>
+
+	<span dojoType="dijit.Tooltip" connectId="id1" id="id1_tooltip">
+
+	tooltip for #1<br>
+	long long long long long long long long long long long text<br>
+	make sure that this works properly with a really narrow window
+	</span>
+
+	<span dojoType="dijit.Tooltip" connectId="id2" id="id2_tooltip">tooltip for #2</span>
+	<span dojoType="dijit.Tooltip" connectId="id3" id="id3_tooltip">tooltip for #3</span>
+	<span dojoType="dijit.Tooltip" connectId="id4" id="id4_tooltip">tooltip for #4</span>
+	<span dojoType="dijit.Tooltip" connectId="id5" id="id5_tooltip">tooltip for #5</span>
+	<span dojoType="dijit.Tooltip" connectId="id6" id="id6_tooltip">tooltip for #6</span>
+
+	<span dojoType="dijit.Tooltip" connectId="s1" id="s1_tooltip">s1 tooltip</span>
+	<span dojoType="dijit.Tooltip" connectId="s2" id="s2_tooltip">s2 tooltip</span>
+	<span dojoType="dijit.Tooltip" connectId="s3" id="s3_tooltip">s3 tooltip</span>
+	<span dojoType="dijit.Tooltip" connectId="s4" id="s4_tooltip">s4 tooltip</span>
+	<span dojoType="dijit.Tooltip" connectId="s5" id="s5_tooltip">s5 tooltip</span>
+
+	<h3>One Tooltip for multiple connect nodes</h3>
+	<span dojoType="dijit.Tooltip" connectId="multi1,multi2" id="multi1,multi2_tooltip" style="display:none;">multi tooltip</span>
+	<a id="multi1" href="#bogus">multi1</a><br><a id="multi2" href="#bogus">multi2</a>
+
+
+	<h3>Dynamic target tooltip</h3>
+	<div>
+		<button onclick="addDynamicTarget('t1');">Add</button>
+		<button onclick="removeDynamicTarget('t1');">Remove</button>
+		<span id="t1" tabIndex="0">t1 text</span><br>
+		<button onclick="addDynamicTarget('t2');">Add</button>
+		<button onclick="removeDynamicTarget('t2');">Remove</button>
+		<span id="t2" tabIndex="0">t2 text</span><br>
+		<button onclick="addDynamicTarget('t3');">Add</button>
+		<button onclick="removeDynamicTarget('t3');">Remove</button>
+		<span id="t3" tabIndex="0">t3 text</span><br>
+		<button onclick="addDynamicTarget('t4');">Add</button>
+		<button onclick="removeDynamicTarget('t4');">Remove</button>
+		<span id="t4" tabIndex="0">t4 text</span><br>
+		<button onclick="addDynamicTarget('t5');">Add</button>
+		<button onclick="removeDynamicTarget('t5');">Remove</button>
+		<span id="t5" tabIndex="0">t5 text</span><br>
+	</div>
+	<span id="t_connected_id"></span><br>
+	<span id="t_shown">Tooltip hidden (initial)</span>
+
+	<span dojoType="dijit.Tooltip" connectId="t1,t3" id="t_tooltip">Dynamic target tooltip</span>
+</body>
+</html>
+
diff --git a/dijit/tests/test_TooltipDialog.html b/dijit/tests/test_TooltipDialog.html
new file mode 100644
index 0000000..08155fb
--- /dev/null
+++ b/dijit/tests/test_TooltipDialog.html
@@ -0,0 +1,405 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>TooltipDialog Widget Tests</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+
+		body { font-family : sans-serif; }
+		form { margin-bottom : 0; }
+		table { border: none; }
+		.tundra .tooltipLink .dijitButtonNode,
+		.tundra .tooltipLink .dijitButtonNode .dijitDropDownButtonHover,
+		.tundra .buttonLink .dijitButtonNode,
+		.tundra .buttonLink .dijitButtonHover .dijitButtonNode {
+				background: none !important;
+				border:none;
+		}
+		.tundra .tooltipLink .dijitArrowButtonInner {
+			display:none;
+		}
+		.tundra .tooltipLink button,
+		.tundra .tooltipLink button .dijitButtonText,
+		.tundra .buttonLink button .dijitButtonText {
+				text-decoration:underline !important;
+				color:blue;
+				display:inline;
+		}
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.TooltipDialog");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.DateTextBox");
+		dojo.require("dijit.form.TimeTextBox");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dijit.form.Select");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.InlineEditBox");
+		dojo.require("dijit.Menu");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		// create a do nothing, only for test widget
+		dojo.declare("dijit.TestWidget",
+			[dijit._Widget, dijit._Templated], {
+			templateString: "<div style='margin: 10px; border: inset #700 4px; padding: 5px;' dojoAttachPoint='containerNode'></div>"
+		});
+
+		// make dojo.toJson() print dates correctly (this feels a bit dirty)
+		Date.prototype.json = function(){ return dojo.date.stamp.toISOString(this, {selector: 'date'});};
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">dijit.TooltipDialog tests</h1>
+
+	<div dojoType="dijit.form.DropDownButton" id="tooltipDlgButton">
+		<span>Show Tooltip Dialog</span>
+		<div dojoType="dijit.TooltipDialog" id="tooltipDlg" title="Enter Login information">
+			<table>
+				<tr>
+					<td><label for="inline">InlineEditBox:</label></td>
+					<td><div dojoType=dijit.InlineEditBox type="text" name="inline" id="inline">inline</div></td>
+				</tr>
+				<tr>
+					<td><label for="text">TextBox:</label></td>
+					<td><input dojoType=dijit.form.TextBox name="text" id="text"></td>
+				</tr>
+				<tr>
+					<td><label for="date2">Date:</label></td>
+					<td><input dojoType=dijit.form.DateTextBox name="date" id="date2"></td>
+				</tr>
+				<tr>
+					<td><label for="time2">Time:</label></td>
+					<td><input dojoType=dijit.form.TimeTextBox name="time" id="time2"></td>
+				</tr>
+				<tr>
+					<td><label for="combo">FilteringSelect:</label></td>
+					<td>
+						<select dojoType=dijit.form.FilteringSelect name="combo" id="combo" hasDownArrow="true">
+							<option value="cheese">cheese</option>
+							<option value="pepperoni">pepperoni</option>
+							<option value="sausage">sausage</option>
+						</select>
+					</td>
+				</tr>
+				<tr>
+					<td><label for="select">Select:</label></td>
+					<td>
+						<select dojoType=dijit.form.Select name="select" id="select">
+							<option value="olives">olives</option>
+							<option value="peppers">peppers</option>
+							<option value="tomatoes">tomatoes</option>
+						</select>
+					</td>
+				</tr>
+				<tr>
+					<td colspan="2" align="center">
+						<button dojoType=dijit.form.Button type="submit" name="submit" id="submit">Order</button>
+					</td>
+				</tr>
+			</table>
+			<div style="width: 300px;">Note: This tooltip dialog has a bunch of nested drop downs for testing keyboard and click handling</div>
+		</div>
+	</div> |
+
+	<div dojoType="dijit.form.DropDownButton">
+		<span>Show Tooltip Dialog with TabContainer</span>
+		<div dojoType="dijit.TooltipDialog" id="tabTooltip" title="Tab Container Tooltip">
+			<div dojoType="dijit.layout.TabContainer" style="width: 400px; height: 300px;">
+				<div dojoType="dijit.layout.ContentPane" title="First tab">
+					<p>
+						This is the first tab.
+					</p>
+					<p>
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+					semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+					porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+					Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+					Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+					risus.
+					</p>
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Second tab">
+					<p>
+						This is the second tab.
+					</p>
+					<p>
+					<a href="http://www.lipsum.com/">ipsum dolor sit amet</a>, consectetuer adipiscing elit. Aenean
+					semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+					porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+					Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+					Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+					risus.
+					</p>
+				</div>
+			</div>
+		</div>
+	</div> |
+
+	<div dojoType="dijit.form.DropDownButton">
+		<span>Test slowloading HREF Tooltip Dialog</span>
+		<div dojoType="dijit.TooltipDialog" id="slowLoad" href="layout/getResponse.php?delay=500&messId=2"
+			title="tooltip dialog with no focusable items"></div>
+	</div> |
+
+<div dojoType="dijit.form.DropDownButton" class="tooltipLink">
+	<span>What is this?</span>
+	<div dojoType="dijit.TooltipDialog" id="tooltipHelpDlg" title="Test Dialog tooltip" style="width:350px" >
+		<div class="buttonLink" style="float:right;font-size:x-small" title="close" tabindex="0" dojoType="dijit.form.Button">[close]
+			<script type="dojo/method" event="onClick">
+					dijit.byId('tooltipHelpDlg').onCancel();
+			</script>
+		</div>
+		<div role="alert" style="margin-top:1em">
+			<strong>Important!</strong> This is a tooltip dialog with just text! It could be used
+			to provide help. It will stay open until the user explicitly closes it via pressing escape, clicking [close] or by
+			clicking somewhere else on the page.  To make certain a screen reader will speak this text (at least in Firefox 3),
+			the div containing the text was given an
+			<a href="http://www.w3.org/WAI/PF/aria/">ARIA</a> role of alert. In the future the tooltip
+			dialog may be given a role of alertdialog.
+		</div>
+
+	</div>
+</div>
+
+
+	<p><b><i>(scroll down to see more links to click, for testing positioning / scroll handling)</i></b></p>
+
+	<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+	imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+	nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+	massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+	pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+	quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+	felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+	quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+	rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+	semper velit ante id metus. Praesent massa dolor, porttitor sed,
+	pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+	tortor pharetra congue. Suspendisse pulvinar.
+	</p>
+	<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+	ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+	nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+	lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+	est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+	dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+	nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+	pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+	sociosqu ad litora torquent per conubia nostra, per inceptos
+	hymenaeos.
+	</p>
+	<form>
+		<center>
+			<select>
+				<option>1</option>
+				<option>2</option>
+			</select>
+		</center>
+	</form>
+	<p>Mauris pharetra lorem sit amet sapien. Nulla libero metus, tristique
+	et, dignissim a, tempus et, metus. Ut libero. Vivamus tempus purus vel
+	ipsum. Quisque mauris urna, vestibulum commodo, rutrum vitae, ultrices
+	vitae, nisl. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos hymenaeos. Nulla id erat sit amet odio
+	luctus eleifend. Proin massa libero, ultricies non, tincidunt a,
+	vestibulum non, tellus. Nunc nunc purus, lobortis a, pulvinar at,
+	egestas a, mi. Cras adipiscing velit a mauris. Morbi felis. Etiam at
+	felis. Cras eget eros et justo mattis pulvinar. Nullam at justo id
+	risus porttitor dignissim. Vestibulum sed velit vel metus tincidunt
+	tempus. Nunc euismod nisl id dolor tristique tincidunt. Nullam placerat
+	turpis sed odio. Curabitur in est id nibh tempus ultrices. Aliquam
+	consectetuer dapibus eros. Aliquam nisl.
+	</p>
+	<div style="float:right;clear:right;" dojoType="dijit.form.DropDownButton">
+		<span>dropdown at right</span>
+	<div dojoType="dijit.TooltipDialog" id="dialogright">
+			<div style="white-space:nowrap;">Aliquam vitae enim. Duis scelerisque metus auctor est venenatis</div>
+	</div>
+	</div>
+	<p>
+	Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+	semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+	porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+	Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+	Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+	risus.
+	</p>
+	<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+	imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+	nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+	massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+	pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+	quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+	felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+	quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+	rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+	semper velit ante id metus. Praesent massa dolor, porttitor sed,
+	pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+	tortor pharetra congue. Suspendisse pulvinar.
+	</p>
+
+	<div dojoType="dijit.form.DropDownButton" title="Enter Login information2">
+		<span>Show Tooltip Dialog pointing upwards, with links</span>
+		<div dojoType="dijit.TooltipDialog" title="General Information Dialog">
+			<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. <a href="http://www.lipsum.com/">Vestibulum</a> vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in <a href="http://www.lipsum.com/">ipsum</a>. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. <a href="http://www.lipsum.com/">Suspendisse imperdiet</a>. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+			</p>
+		</div>
+	</div>
+	(will go up if there isn't enough space on the bottom of the screen)
+
+	<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+	ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+	nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+	lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+	est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+	dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+	nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+	pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+	sociosqu ad litora torquent per conubia nostra, per inceptos
+	hymenaeos.
+	</p>
+	<form>
+		<center>
+			<select>
+				<option>1</option>
+				<option>2</option>
+			</select>
+		</center>
+	</form>
+	<p>Mauris pharetra lorem sit amet sapien. Nulla libero metus, tristique
+	et, dignissim a, tempus et, metus. Ut libero. Vivamus tempus purus vel
+	ipsum. Quisque mauris urna, vestibulum commodo, rutrum vitae, ultrices
+	vitae, nisl. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos hymenaeos. Nulla id erat sit amet odio
+	luctus eleifend. Proin massa libero, ultricies non, tincidunt a,
+	vestibulum non, tellus. Nunc nunc purus, lobortis a, pulvinar at,
+	egestas a, mi. Cras adipiscing velit a mauris. Morbi felis. Etiam at
+	felis. Cras eget eros et justo mattis pulvinar. Nullam at justo id
+	risus porttitor dignissim. Vestibulum sed velit vel metus tincidunt
+	tempus. Nunc euismod nisl id dolor tristique tincidunt. Nullam placerat
+	turpis sed odio. Curabitur in est id nibh tempus ultrices. Aliquam
+	consectetuer dapibus eros. Aliquam nisl.
+	</p>
+	<p>
+	Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+	semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+	porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+	Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+	Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+	risus.
+	</p>
+	<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+	imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+	nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+	massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+	pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+	quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+	felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+	quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+	rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+	semper velit ante id metus. Praesent massa dolor, porttitor sed,
+	pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+	tortor pharetra congue. Suspendisse pulvinar.
+	</p>
+	<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+	ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+	nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+	lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+	est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+	dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+	nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+	pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+	sociosqu ad litora torquent per conubia nostra, per inceptos
+	hymenaeos.
+	</p>
+	<p>Mauris pharetra lorem sit amet sapien. Nulla libero metus, tristique
+	et, dignissim a, tempus et, metus. Ut libero. Vivamus tempus purus vel
+	ipsum. Quisque mauris urna, vestibulum commodo, rutrum vitae, ultrices
+	vitae, nisl. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos hymenaeos. Nulla id erat sit amet odio
+	luctus eleifend. Proin massa libero, ultricies non, tincidunt a,
+	vestibulum non, tellus. Nunc nunc purus, lobortis a, pulvinar at,
+	egestas a, mi. Cras adipiscing velit a mauris. Morbi felis. Etiam at
+	felis. Cras eget eros et justo mattis pulvinar. Nullam at justo id
+	risus porttitor dignissim. Vestibulum sed velit vel metus tincidunt
+	tempus. Nunc euismod nisl id dolor tristique tincidunt. Nullam placerat
+	turpis sed odio. Curabitur in est id nibh tempus ultrices. Aliquam
+	consectetuer dapibus eros. Aliquam nisl.
+	</p>
+
+	<p>
+	Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+	semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+	porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+	Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+	Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+	risus.
+	</p>
+	<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+	imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+	nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+	massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+	pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+	quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+	felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+	quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+	rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+	semper velit ante id metus. Praesent massa dolor, porttitor sed,
+	pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+	tortor pharetra congue. Suspendisse pulvinar.
+	</p>
+	<p>Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+	ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+	nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+	lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+	est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+	dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+	nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+	pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+	sociosqu ad litora torquent per conubia nostra, per inceptos
+	hymenaeos.
+	</p>
+	<p>Mauris pharetra lorem sit amet sapien. Nulla libero metus, tristique
+	et, dignissim a, tempus et, metus. Ut libero. Vivamus tempus purus vel
+	ipsum. Quisque mauris urna, vestibulum commodo, rutrum vitae, ultrices
+	vitae, nisl. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos hymenaeos. Nulla id erat sit amet odio
+	luctus eleifend. Proin massa libero, ultricies non, tincidunt a,
+	vestibulum non, tellus. Nunc nunc purus, lobortis a, pulvinar at,
+	egestas a, mi. Cras adipiscing velit a mauris. Morbi felis. Etiam at
+	felis. Cras eget eros et justo mattis pulvinar. Nullam at justo id
+	risus porttitor dignissim. Vestibulum sed velit vel metus tincidunt
+	tempus. Nunc euismod nisl id dolor tristique tincidunt. Nullam placerat
+	turpis sed odio. Curabitur in est id nibh tempus ultrices. Aliquam
+	consectetuer dapibus eros. Aliquam nisl.
+	</p>
+
+</body>
+</html>
+
diff --git a/dijit/tests/test_Tree.html b/dijit/tests/test_Tree.html
new file mode 100644
index 0000000..3919742
--- /dev/null
+++ b/dijit/tests/test_Tree.html
@@ -0,0 +1,174 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit Tree Test</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+		dojo.require("dijit.ColorPalette");
+		dojo.require("dijit.Menu");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit Tree Test</h1>
+
+	<div dojoType="dojo.data.ItemFileReadStore" jsId="continentStore"
+		url="_data/countries.json"></div>
+	<div dojoType="dijit.tree.ForestStoreModel" jsId="continentModel"
+		store="continentStore" query="{type:'continent'}"
+		rootId="continentRoot" rootLabel="Continents" childrenAttrs="children"></div>
+
+	<h2>Tree with hardcoded root node (not corresponding to any item in the store)</h2>
+	<p>
+		Clicking a folder node will open/close it (openOnclick==true),
+		and clicking a leaf node will log a message to the console.
+	</p>
+	<div dojoType="dijit.Tree" id="mytree"
+		model="continentModel" openOnClick="true" onLoad="console.log('loaded mytree (first tree)');">
+		<script type="dojo/method" event="onClick" args="item">
+			console.log("Execute of node " + continentStore.getLabel(item)
+				+", population=" + continentStore.getValue(item, "population"));
+		</script>
+		<script type="dojo/method" event="onOpen" args="item">
+			console.log("Open of node " + continentStore.getLabel(item)||"root");
+		</script>
+		<script type="dojo/method" event="onClose" args="item">
+			console.log("Close of node " + continentStore.getLabel(item)||"root");
+		</script>
+	</div>
+
+	<button onclick="dijit.byId('mytree').destroyRecursive();">destroy</button>
+
+	<h2>A rootless tree (no "continents" node) with context menus, and custom icons</h2>
+
+	<ul dojoType="dijit.Menu" id="tree_menu" style="display: none;">
+		<li dojoType="dijit.MenuItem" onClick="console.log('Hello world');">Enabled Item</li>
+		<li dojoType="dijit.MenuItem" disabled="true">Disabled Item</li>
+		<li dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+			onClick="console.log('not actually cutting anything, just a test!')">Cut</li>
+		<li dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+			onClick="console.log('not actually copying anything, just a test!')">Copy</li>
+		<li dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+			onClick="console.log('not actually pasting anything, just a test!')">Paste</li>
+		<li dojoType="dijit.PopupMenuItem">
+			<span>Enabled Submenu</span>
+			<ul dojoType="dijit.Menu" id="submenu2">
+				<li dojoType="dijit.MenuItem" onClick="console.log('Submenu 1!')">Submenu Item One</li>
+				<li dojoType="dijit.MenuItem" onClick="console.log('Submenu 2!')">Submenu Item Two</li>
+				<li dojoType="dijit.PopupMenuItem">
+					<span>Deeper Submenu</span>
+					<ul dojoType="dijit.Menu" id="submenu4">
+						<li dojoType="dijit.MenuItem" onClick="console.log('Sub-submenu 1!')">Sub-sub-menu Item One</li>
+						<li dojoType="dijit.MenuItem" onClick="console.log('Sub-submenu 2!')">Sub-sub-menu Item Two</li>
+					</ul>
+				</li>
+			</ul>
+		</li>
+		<li dojoType="dijit.PopupMenuItem" disabled="true">
+			<span>Disabled Submenu</span>
+			<ul dojoType="dijit.Menu" id="submenu3" style="display: none;">
+				<li dojoType="dijit.MenuItem" onClick="console.log('Submenu 1!')">Submenu Item One</li>
+				<li dojoType="dijit.MenuItem" onClick="console.log('Submenu 2!')">Submenu Item Two</li>
+			</ul>
+		</li>
+	</ul>
+
+	<div dojoType="dijit.Tree" id="tree2"
+		model="continentModel" showRoot="false" openOnClick="true"onLoad="console.log('loaded tree2 (second tree)');">
+
+		<script type="dojo/connect">
+			var menu = dijit.byId("tree_menu");
+			// when we right-click anywhere on the tree, make sure we open the menu
+			menu.bindDomNode(this.domNode);
+
+			dojo.connect(menu, "_openMyself", this, function(e){
+				// get a hold of, and log out, the tree node that was the source of this open event
+				var tn = dijit.getEnclosingWidget(e.target);
+				console.debug(tn);
+
+				// now inspect the data store item that backs the tree node:
+				console.debug(tn.item);
+
+				// contrived condition: if this tree node doesn't have any children, disable all of the menu items
+				dojo.forEach(menu.getChildren(), function(i){ i.set('disabled', !tn.item.children); });
+
+				// IMPLEMENT CUSTOM MENU BEHAVIOR HERE
+			});
+		</script>
+		<script type="dojo/method" event="getIconClass" args="item, opened">
+           return (item == this.model.root || continentStore.getValue(item, "type") == "continent") ?
+                   (opened ? "customFolderOpenedIcon" : "customFolderClosedIcon") :
+                    "noteIcon";
+		</script>
+		<script type="dojo/method" event="onClick" args="item">
+			console.log("Execute of node " + this.model.getLabel(item)
+				+", population=" + continentStore.getValue(item, "population"));
+		</script>
+</div>
+
+	<h2>Double click, expand on load, direct style setting, tooltip test</h2>
+	<p>
+		Double-Clicking a folder node will open/close it (openOnDblClick==true),
+		and clicking or Double Clicking a leaf node will log a message to the console.
+	</p>
+	<div dojoType="dijit.Tree" id="mytree3" store="continentStore" query="{type:'continent'}"
+		label="Continents" openOnClick="false" openOnDblClick="true"
+		autoExpand="true" onLoad="console.log('loaded mytree3 (third tree)');">
+		<script type="dojo/method" event="getLabelStyle" args="item,opened">
+			if(item && continentStore.getValue(item,"type") == "continent"){
+				return {color: "red"};
+			}else{
+				return {color: "green"};
+			}
+		</script>
+		<script type="dojo/method" event="getIconStyle" args="item,opened">
+			if(item && continentStore.getValue(item,"type") == "continent"){
+				return {
+					backgroundImage: "url('images/flatScreen.gif')",
+					height: "32px",
+					width: "32px"
+				};
+			}else{
+				return null;
+			}
+		</script>
+		<script type="dojo/method" event="getIconClass" args="item, opened">
+	       if (!item || continentStore.getValue(item, "type") != "continent")
+				return (!item || this.model.mayHaveChildren(item)) ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "dijitLeaf"
+	       	else
+	       		return "";
+		</script>
+		<script type="dojo/method" event="getTooltip" args="item,opened">
+			return item && ("Tooltip for " + this.model.getLabel(item));
+		</script>
+		<script type="dojo/method" event="onDblClick" args="item">
+			console.log("Execute of node " + this.model.getLabel(item)
+				+", population=" + continentStore.getValue(item, "population"));
+		</script>
+	</div>
+
+
+</body>
+</html>
diff --git a/dijit/tests/test_Tree_Notification_API_Support.html b/dijit/tests/test_Tree_Notification_API_Support.html
new file mode 100644
index 0000000..b27577f
--- /dev/null
+++ b/dijit/tests/test_Tree_Notification_API_Support.html
@@ -0,0 +1,293 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit Tree Test</title>
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "../../dojo/resources/dnd.css";
+		@import "../../dojo/tests/dnd/dndDefault.css";
+		@import "css/dijitTests.css";
+
+		.clear {
+			clear: both;
+		}
+
+		.box {
+			border: #ccc 3px solid;
+			padding: 1em;
+			-moz-border-radius: 8px 8px;
+			radius: 8px;
+		}
+
+		label {
+			display: inline-block;
+			min-width: 8em;
+		}
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dojo.dnd.Source");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Declaration");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.TreeStoreModel");
+		dojo.require("dijit.Menu");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		// Hash of id-->item for all the items (including children) in the data store.
+		var allItems = {};
+
+		function deleteItem(){
+			store.deleteItem(selectedItem);
+			store.save();
+
+			resetForms();
+			loadItemsTable();
+		}
+
+		function newItem(){
+			var pInfo = selectedItem ? {parent: selectedItem, attribute:"children"} : null,
+				item = {
+					id: dojo.byId('nId').value,
+					name: dojo.byId("nLabel").value,
+					someProperty: dojo.byId("nSomeProperty").value,
+					children: dojo.query("> *", "nChildren").map( function(child){
+								var id = child.id;
+								return allItems[id];
+							})
+				};
+
+			console.debug("New item: ", item, ", pInfo = ", pInfo);
+
+			store.newItem(item, pInfo);
+			store.save();
+
+			resetForms();
+			loadItemsTable();
+		}
+
+		function resetForms() {
+			selectedItem=null;
+
+			// Update item form
+			dojo.byId("uLabel").value = "";
+			dojo.byId("uSomeProperty").value = "";
+
+			dojo.byId("uChildren").innerHTML = "";
+			uChildrenDragSource.clearItems();
+
+			dojo.byId("uPotentialChildren").innerHTML = "";
+			uPotentialChildrenDragSource.clearItems();
+
+			// New item form
+			dojo.byId("nChildren").innerHTML = "";
+			nChildrenDragSource.clearItems();
+
+			dojo.byId("nPotentialChildren").innerHTML = "";
+			nPotentialChildrenDragSource.clearItems();
+		}
+
+		function updateItem(){
+			if (selectedItem!=null){
+				if (dojo.byId("uLabel").value != store.getValue(selectedItem, "name")){
+					store.setValue(selectedItem, "name", dojo.byId("uLabel").value);
+				}
+
+				if (dojo.byId("uSomeProperty").value != store.getValue(selectedItem, "someProperty")){
+					store.setValue(selectedItem, "someProperty", dojo.byId("uSomeProperty").value);
+				}
+
+				var children = dojo.query("> *", "uChildren").map( function(child){
+					var id = child.id;
+					return allItems[id];
+				});
+				store.setValues(selectedItem, "children", children);
+
+				store.save();
+
+				resetForms();
+				loadItemsTable();
+			}else{
+				console.error("Can't update the tree root");
+			}
+		}
+
+		dojo.addOnLoad(function(){
+			resetForms();
+			loadItemsTable();
+		});
+
+		function loadItemsTable(){
+			// summary: for each item in the datastore generate a row in the table
+			function processItem(item){
+				allItems[store.getIdentity(item)] = item;
+
+				var vals = {
+					itemId: store.getIdentity(item),
+					label: store.getLabel(item),
+					someProperty: store.getValue(item, "someProperty"),
+					children: store.getValues(item, "children")
+				};
+
+				// add this item to children list in "new item" form
+				dojo.byId("nPotentialChildren").innerHTML +=
+					"<div class='dojoDndItem' id='" + vals.itemId + "'>" +
+						vals.label +
+					"</div>";
+				nPotentialChildrenDragSource.setItem(vals.itemId, {
+					data: vals.label,
+					type: ["text"]
+				});
+
+				// update table listing items
+				var row = new ItemRow(vals);
+				dojo.byId("itemsTable").appendChild(row.domNode);
+
+				//dojo.forEach(vals.children, processItem);
+			}
+
+			allItems = {};
+			dijit.registry.byClass("ItemRow").forEach(function(widget){ widget.destroy(); });
+			store.fetch({onItem: processItem});
+		}
+
+		function onSelectItem(item){
+			resetForms();
+			loadItemsTable();
+
+			console.log("Selected item: ", item ? store.getLabel(item) : "none");
+			selectedItem = item;
+
+			if(item){
+				// Display basic attribute values
+				dojo.byId('uLabel').value = item ? store.getLabel(item) : "";
+				dojo.byId('uSomeProperty').value = item ? store.getValue(item,"someProperty") : "";
+
+				// Fill in info about children
+				var children = store.getValues(item, "children");
+				dojo.forEach(children, function(item){
+					var id = store.getIdentity(item),
+						label = store.getLabel(item);
+					dojo.byId("uChildren").innerHTML +=
+						"<div class='dojoDndItem' id='" + id + "'>" +
+							label +
+						"</div>";
+					uChildrenDragSource.setItem(id, {
+						data: label,
+						type: ["text"]
+					});
+				});
+
+				// and the items that could be children but aren't currently
+				// (including items that would cause cycles, because i'm lazy)
+				for(var id in allItems){
+					var child = allItems[id];
+					if(dojo.indexOf(children, child) == -1){
+						var label = store.getLabel(child);
+						dojo.byId("uPotentialChildren").innerHTML +=
+							"<div class='dojoDndItem' id='" + id + "'>" +
+								label +
+							"</div>";
+						uPotentialChildrenDragSource.setItem(id, {
+							data: label,
+							type: ["text"]
+						});
+					}
+				}
+			}
+
+			// New Item section
+			dojo.byId('nParent').value = item ? store.getLabel(item) : "";
+		}
+	</script>
+
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit Tree Test - dojo.data.Notification API support</h1>
+
+	<div dojoType="dojo.data.ItemFileWriteStore" jsId="store"
+		url="../tests/_data/treeTest.json"></div>
+	<div dojoType="dijit.tree.TreeStoreModel" jsId="model"
+		store="store" query="{id:'root'}"></div>
+	<div dojoType="dijit.Tree" id="myTree" model="model" onClick="onSelectItem"></div>
+
+	<br />
+	<h2>Selected Item:</h2>
+	<div class="box">
+		<label for="uLabel">Name:</label>				<input id="uLabel" width="50" value="Enter Node Label"  autocomplete="off"/><br />
+		<label for="uSomeProperty">Description:</label> <input id="uSomeProperty" width="50" value="Some Test Property"  autocomplete="off"/><br /><br />
+		<div style="float:left; margin-right: 2em;">
+			<label for="uChildren">Children (in order):</label>
+			<div dojoType="dojo.dnd.Source" class="container" id="uChildren" jsId="uChildrenDragSource"></div>
+		</div>
+		<div style="float:left">
+			<label for="uPotentialChildren">Potential Children:</label>
+			<div dojoType="dojo.dnd.Source" class="container" id="uPotentialChildren" jsId="uPotentialChildrenDragSource"></div>
+		</div>
+		<div class="clear">(drag and drop items to adjust list of children, and order of those children)</div>
+	</div>
+	<div dojoType="dijit.form.Button" iconClass="noteIcon" onClick="updateItem();">Update Item</div>
+	<div dojoType="dijit.form.Button" iconClass="noteIcon" onClick="deleteItem();">Delete Item</div>
+
+	<h2>New Item</h2>
+	<p>Enter an Id, Name, and optionally a description to be added as a new item to the store.  Upon successful addition, the tree will recieve notification of this event and respond accordingly.  If you select a node the item will be added to that node, otherwise the item will be added to the tree root. "Id" is the identifer here and as such must be unique for all items in the store.</p>
+	<div class="box">
+		<label for="nId">Id:</label>					<input id="nId" width="50" value="Enter Item Id"  autocomplete="off"/><br />
+		<label for="nLabel">Name:</label>				<input id="nLabel" width="50" value="Enter Item Name"  autocomplete="off"/><br />
+		<label for="nSomeProperty">Description:</label> <input id="nSomeProperty" width="50" value="Enter Some Property Value"  autocomplete="off"/><br /><br />
+		<label for="nParent">Parent:</label>			<input id="nParent" readonly autocomplete="off"/><br /><br />
+		<div style="float:left; margin-right: 2em;">
+			Children (in order):
+			<div dojoType="dojo.dnd.Source" class="container" id="nChildren" jsId="nChildrenDragSource"></div>
+		</div>
+		<div style="float:left">
+			<label for="nPotentialChildren">Potential Children:</label>
+			<div dojoType="dojo.dnd.Source" class="container" id="nPotentialChildren" jsId="nPotentialChildrenDragSource"></div>
+		</div>
+		<div class="clear">(drag and drop items to adjust list of children, and order of those children)</div>
+	</div>
+
+	<div dojoType="dijit.form.Button" iconClass="noteIcon" onClick="newItem();">Add Item to Store</div>
+	<br />
+
+	<h2>Data in flat form</h2>
+	<!--
+		flat view of the items in the data store.
+		TODO: use the table widget from the mail demo, or dojox.Grid
+	-->
+	<div dojoType="dijit.Declaration" widgetClass="ItemRow" defaults="{ item: {}, itemId: 'thud', label: 'foo', someProperty: 'foo', children: {} }">
+		Id: ${itemId}, Label: ${label}
+
+		Children:
+		<span class="dijitInline" dojoAttachPoint="childrenContainerNode"></span>
+
+		<script type='dojo/connect' event='postCreate'>
+			var children =
+				dojo.map(this.children, function(childItem){
+					return "<span class='itemReference'>" + store.getLabel(childItem) + "</span>";
+				});
+			this.childrenContainerNode.innerHTML = children.join(" ");
+		</script>
+	</div>
+	<div id="itemsTable"></div>
+	</body>
+</html>
+
+
+
+
diff --git a/dijit/tests/test_bgIframe.html b/dijit/tests/test_bgIframe.html
new file mode 100644
index 0000000..ebf8864
--- /dev/null
+++ b/dijit/tests/test_bgIframe.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Dojo Toolkit - Background Iframe test</title>
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script type="text/javascript">
+		// adding this for IE
+		doh = { robot: {}, run: function(){} };
+
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.Dialog");
+		dojo.require("dijit.form.DateTextBox");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.Tooltip");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+
+</head>
+<body class="claro">
+	<span dojoType="dijit.Tooltip" connectId="one" id="one_tooltip">
+		This is one tooltip.
+	</span>
+	<span dojoType="dijit.Tooltip" connectId="two" id="two_tooltip">
+		This is another tooltip.  A little longer...
+	</span>
+	<button dojoType="dijit.form.Button">
+		Show Dialog
+		<script type="dojo/connect" event="onClick">
+			dialog.show();
+		</script>
+	</button>
+	<table>
+		<tbody>
+			<tr>
+				<td></td>
+				<td>
+					<input dojoType="dijit.form.DateTextBox" type="text" />
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<div style="width: 200px;">
+						This tooltip will disappear on IE6
+						when the dialog is displayed.
+						But the tooltip's iframe shouldn't make it disappear because they shouldn't overlap.
+					</div>
+					<select>
+						<option>cat</option>
+						<option>dog</option>
+						<option>mouse</option>
+					</select>
+					<br /><br />
+
+					<div id="one">Mouse over this to see the tooltip</div>
+					<br />
+					<div id="two">Mouse over this to see a different tooltip</div>
+				</td>
+				<td>
+					<applet width="400" height="400" code="DOHRobot.class" archive="../../util/doh/robot/DOHRobot.jar">
+						<param name="mayscript" value="false">
+						<param name="scriptable" value="false">
+						<param name="initial_focus" value="false">
+					</applet>
+				</td>
+			</tr>
+		</tbody>
+	</table>
+	<div id="dialog" jsId="dialog" dojoType="dijit.Dialog">
+		Hello!
+	</div>
+</body>
+</html>
diff --git a/dijit/tests/test_instantiate.html b/dijit/tests/test_instantiate.html
new file mode 100644
index 0000000..b681aa1
--- /dev/null
+++ b/dijit/tests/test_instantiate.html
@@ -0,0 +1,118 @@
+<html>
+	<head>
+		<title>dojo.NodeList.instantiate() tests</title>
+
+		<style type="text/css">
+			@import "../../dojo/resources/dojo.css";
+			@import "css/dijitTests.css";
+			#container { height:200px; }
+		</style>
+
+		<!-- required: a default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../dojo/dojo.js"
+			djConfig="parseOnLoad: true, isDebug: true"></script>
+
+		<!-- not needed, for testing alternate themes -->
+		<script type="text/javascript" src="_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit._Widget");
+			dojo.require("dojo.parser");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.layout.TabContainer");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dijit.layout.LinkPane");
+
+			// declare a simple widget to use as a base test:
+			dojo.declare("test._Widget",dijit._Widget,{
+				message:"",
+				postCreate:function(){
+					this.inherited(arguments);
+					this.connect(this.domNode,"onclick","workit");
+					dojo.style(this.domNode,{
+						cursor:"pointer",
+						color:"#333"
+					});
+					this.domNode.innerHTML += this.message +" ("+this.id +")";
+					console.log('created',this.id);
+				},
+				workit:function(){
+					dojo.place(this.domNode,this.domNode.parentNode,"end");
+				}
+			});
+
+			var init = function(){
+				dojo.byId("status").innerHTML = "after.";
+
+				// test widgeting
+				dojo.query("#testList li").instantiate(test._Widget,{}).connect("onclick",console.log);
+
+				// make a tab container from some div, and all it's children div's
+				dojo.query("#container")
+					.forEach(function(n){
+						dojo.query("div",n)
+							// create contentpanes from the children and style them
+							.instantiate(dijit.layout.ContentPane,{})
+							.forEach(function(wn,idx){
+								dojo.mixin(dijit.byNode(wn),{ title:"tab" + (idx + 1) })
+							})
+						;
+					})
+					.instantiate(dijit.layout.TabContainer,{})
+				;
+				// should we add auto-startup calling?
+				dijit.byId("container").startup();
+				//dijit.byId("container").layout();
+
+				// another test widget example
+				dojo.query("#altList li").instantiate(test._Widget,{ message:"woot" });
+
+				// bunches of buttons, use you imagination on how to relate them to something
+				dojo.query("#buttonTest").forEach(function(n){
+					dojo.query("button",n).instantiate(dijit.form.Button,{
+						onClick:function(){
+							console.log('clicked:',this.domNode);
+						}
+					});
+				});
+			};
+			dojo.addOnLoad(init)
+			//dojo.addOnLoad(function(){
+			//	setTimeout(init,25);
+			//});
+		</script>
+	</head>
+	<body class="claro">
+
+		<h1>dojo.NodeList.instantiate() tests: <span id="status">before</span></h1>
+
+			<h2>Some simple widgets:</h2>
+			<ul id="testList">
+					<li>inner</li><li>inner</li><li>inner</li><li>inner</li><li>inner</li><li>inner</li><li>inner</li><li>inner</li><li>inner</li>
+			</ul>
+			<ul id="altList">
+					<li>inner</li><li>inner</li><li>inner</li><li>inner</li><li>inner</li><li>inner</li><li>inner</li><li>inner</li><li>inner</li>
+			</ul>
+
+			<h2>A TabContainer:</h2>
+			<div id="container">
+				<div>pane1</div>
+				<div>pane2</div>
+				<div>pane3</div>
+			</div>
+
+			<h2>Some Buttons</h2>
+			<div id="buttonTest">
+				<button>button 1</button>
+				<button>button 2</button>
+				<button>button 3</button>
+				<button>button 4</button>
+				<button>button 5</button>
+			</div>
+
+	</body>
+</html>
diff --git a/dijit/tests/tree/module.js b/dijit/tests/tree/module.js
new file mode 100644
index 0000000..e059eff
--- /dev/null
+++ b/dijit/tests/tree/module.js
@@ -0,0 +1,16 @@
+dojo.provide("dijit.tests.tree.module");
+
+try{
+	var userArgs = window.location.search.replace(/[\?&](dojoUrl|testUrl|testModule)=[^&]*/g,"").replace(/^&/,"?"),
+		test_robot = true;
+
+	doh.registerUrl("dijit.tests.Tree", dojo.moduleUrl("dijit", "tests/Tree.html"), 99999999);
+	doh.registerUrl("dijit.tests.Tree_with_JRS", dojo.moduleUrl("dijit", "tests/Tree_with_JRS.html"), 99999999);
+	if(test_robot){
+		doh.registerUrl("dijit.tests.robot.Tree_a11y", dojo.moduleUrl("dijit","tests/robot/Tree_a11y.html"+userArgs), 99999999);
+		doh.registerUrl("dijit.tests.robot.Tree_DnD", dojo.moduleUrl("dijit","tests/robot/Tree_dnd.html"+userArgs), 99999999);
+		doh.registerUrl("dijit.tests.robot.Tree_DnD_multiParent", dojo.moduleUrl("dijit","tests/robot/Tree_dnd_multiParent.html"+userArgs), 99999999);
+	}
+}catch(e){
+	doh.debug(e);
+}
\ No newline at end of file
diff --git a/dijit/tests/tree/node1.1 b/dijit/tests/tree/node1.1
new file mode 100644
index 0000000..21d1923
--- /dev/null
+++ b/dijit/tests/tree/node1.1
@@ -0,0 +1,4 @@
+{ id: 'node1.1',name:'node1.1', someProperty:'somePropertyA1', children: [
+			{ $ref: 'node1.1.1', name: 'node1.1.1'},
+			{ $ref: 'node1.1.2', name: 'node1.1.2'}
+]}
diff --git a/dijit/tests/tree/node1.2 b/dijit/tests/tree/node1.2
new file mode 100644
index 0000000..b221fab
--- /dev/null
+++ b/dijit/tests/tree/node1.2
@@ -0,0 +1 @@
+{ id: 'node1.2',name:'node1.2', someProperty:'somePropertyA2'}
diff --git a/dijit/tests/tree/places.json b/dijit/tests/tree/places.json
new file mode 100644
index 0000000..0ea6e7a
--- /dev/null
+++ b/dijit/tests/tree/places.json
@@ -0,0 +1,29 @@
+{
+	identifier: 'id',
+	label: 'name',
+	items: [
+		{ id: 'root', children: [
+			{_reference: 'h0'},
+			{_reference: 'h1'},
+			{_reference: 'h2'},
+			{_reference: 'h3'},
+			{_reference: 'h4'} ]},
+		{ id: 'h0', name:'South Africa', type: 'header', children:[ {_reference: 'p0'}] },
+		{ id: 'h1', name:'Ireland', type: 'header', children:[ {_reference: 'p1'},  {_reference: 'p2'}] },
+		{ id: 'h2', name:'France', type: 'header',  children:[ {_reference: 'p3'},  {_reference: 'p4'}] },
+		{ id: 'h3', name:'Canada', type: 'header',
+				children:[ {_reference: 'p5'},  {_reference: 'p6'},  {_reference: 'p7'},  {_reference: 'p8'} ] },
+		{ id: 'h4', name:'Korea', type: 'header', children:[ {_reference: 'p9'}] },
+
+		{ id: 'p0', name:'Joburg', type: 'place'},
+		{ id: 'p1', name:'Knocknahilan', type: 'place'  },
+		{ id: 'p2', name:'Kinsale',  type: 'place' },
+		{ id: 'p3', name:'Lyon',  type: 'place' },
+		{ id: 'p4', name:'Nice', type: 'place' },
+		{ id: 'p5', name:'Toronto',  type: 'place'},
+		{ id: 'p6', name:'Hudson Bay', type: 'place'},
+		{ id: 'p7', name:'Quebec',  type: 'place' },
+		{ id: 'p8', name:'Polar Bear County', type: 'place' },
+		{ id: 'p9', name:'Jeonju', type: 'place' }
+	]
+}
diff --git a/dijit/tests/tree/test_CustomLabel.html b/dijit/tests/tree/test_CustomLabel.html
new file mode 100644
index 0000000..73e693c
--- /dev/null
+++ b/dijit/tests/tree/test_CustomLabel.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit Tree Custom Label Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit Tree Custom Label Test</h1>
+
+	<div dojoType="dojo.data.ItemFileReadStore" jsId="store"
+		url="../_data/states.json"></div>
+
+	<h2>Standard label (state names)</h2>
+	<div dojoType="dijit.tree.ForestStoreModel" jsId="nameModel" store="store" rootLabel="States"></div>
+	<div dojoType="dijit.Tree" id="nameTree" model="nameModel" openOnClick="true"></div>
+
+	<h2>LabelAttr (state abbreviation)</h2>
+	<div dojoType="dijit.tree.ForestStoreModel" jsId="codeModel" store="store" rootLabel="States" labelAttr="abbreviation"></div>
+	<div dojoType="dijit.Tree" id="codeTree" model="codeModel" openOnClick="true"></div>
+
+	<h2>Custom label via callback</h2>
+	<div dojoType="dijit.tree.ForestStoreModel" jsId="customModel" store="store">
+		<script type="dojo/method" event="getLabel" args="item">
+			if(item.root){ return "States"; }
+			return (store.getLabel(item) + " (" + store.getIdentity(item) + ")");
+		</script>
+	</div>
+	<div dojoType="dijit.Tree" id="customTree" model="customModel" openOnClick="true"></div>
+
+
+</body>
+</html>
diff --git a/dijit/tests/tree/test_Tree_DnD.html b/dijit/tests/tree/test_Tree_DnD.html
new file mode 100644
index 0000000..3926f28
--- /dev/null
+++ b/dijit/tests/tree/test_Tree_DnD.html
@@ -0,0 +1,214 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit Tree Test</title>
+
+	<style someProperty="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+		@import "../../../dojo/resources/dnd.css";
+		@import "../../../dojo/tests/dnd/dndDefault.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script language="JavaScript" someProperty="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.TreeStoreModel");
+		dojo.require("dijit.tree.dndSource");
+		dojo.require("dijit.Menu");
+		dojo.require("dijit.form.Button");
+
+		dojo.require("dojo.dnd.common");
+		dojo.require("dojo.dnd.Source");
+
+		selected=[];
+
+		globalId=1000;
+		lastSelected=null;
+
+		dojo.addOnLoad(function(){
+
+			//record the selection from tree 1
+			dojo.subscribe("myTree", null, function(message){
+				if(message.event=="execute"){
+					console.log("Tree1 Select: ",dijit.byId("myTree").store.getLabel(message.item));
+					lastSelected=selected["myTree"]=message.item;
+				}
+			});
+
+			//record the selection from tree 2
+			dojo.subscribe("myTree2", null, function(message){
+				if(message.event=="execute"){
+					console.log("Tree2 Select: ",dijit.byId("myTree2").store.getLabel(message.item));
+					lastSelected=selected["myTree2"]=message.item;
+				}
+			});
+
+			//connect to the add button and have it add a new container to the store as necessary
+			dojo.connect(dijit.byId("addButton"), "onClick", function(){
+				var pInfo = {
+					parent: lastSelected,
+					attribute: "children"
+				};
+
+				//store.newItem({name: dojo.byId('newCat').value, id:globalId++, numberOfItems:dojo.byId('numItems').value}, pInfo);
+				myStore.newItem({name: dojo.byId('newCat').value, numberOfItems:0,id:globalId++}, pInfo);
+			});
+
+			//since we don't have a server, we're going to connect to the store and do a few things the server/store combination would normal be taking care of for us
+			dojo.connect(myStore, "onNew", function(item, pInfo){
+				var p = pInfo && pInfo.item;
+				if (p) {
+					var currentTotal = myStore.getValues(p, "numberOfItems")[0];
+					myStore.setValue(p, "numberOfItems", ++currentTotal);
+				}
+
+			});
+		});
+
+
+		//create a custom label for tree one consisting of the label property pluss the value of the numberOfItems Column
+		function catTreeCustomLabel(item){
+			var label = myStore.getLabel(item);
+			var num = myStore.hasAttribute(item, "numberOfItems") ? myStore.getValues(item,"numberOfItems") : "?";
+			return label + ' (' + num+ ')';
+		}
+
+		//on item tree , we only want to drop on containers, or the root node itself, not on items in the containers
+		function itemTreeCheckItemAcceptance(node,source) {
+			source.forInSelectedItems(function(item){
+				console.log("testing to drop item of type " + item.type[0] + " and data " + item.data);
+			});
+			var item = dijit.getEnclosingWidget(node).item;
+			if (item && (item.root || myStore.hasAttribute(item,"numberOfItems"))){
+				return true;
+			}
+			return false;
+		}
+
+		//on collection tree, only accept itself as the source tree
+		function collectionTreeCheckItemAcceptance(node,source,position) {
+			if(source.tree && source.tree.id == "collectionsTree"){
+				return true;
+			}
+			return false;
+		}
+
+		function dndAccept(source,nodes){
+			if (this.tree.id=="myTree"){
+				return false;
+			}
+			return true;
+		}
+
+		function getIcon(item) {
+			if (!item || myStore.hasAttribute(item, "numberOfItems")) {
+				return "myFolder";
+			}
+			return "myItem"
+		}
+	</script>
+
+	<style>
+		.myFolder{
+			display: "block";
+			width: 16px;
+			height: 16px;
+			background: blue;
+		}
+
+		.myItem{
+			display: "block";
+			width: 16px;
+			height: 16px;
+			background: green;
+
+		}
+	</style>
+
+</head>
+<body class="claro">
+	<h1 class="testTitle">Dijit Tree Test - Drag And Drop Support</h1>
+
+	<div dojoType="dojo.data.ItemFileWriteStore" jsId="myStore"
+		url="../_data/categories.json"></div>
+
+	<table width="100%" style="margin:5px solid gray" >
+
+	<tr style="width:100%">
+		<td style="width: 50%">
+			<h2>Custom</h2>
+			<p>Should add this category to the store.  The second parameter is the value for numberOfItems.</p>
+			<div class="container">
+				<input id="newCat" type="text" value="Pottedmeat" /><input id="numItems" type="text" value="0" size="3"/><div id="addButton" dojoType="dijit.form.Button">Add Category</div>
+			</div>
+		</td>
+		<td>
+			<h2>Items: </h2>
+			<p>List of Items to be categorized<p>
+				<div dojoType="dojo.dnd.Source" jsId="c2" class="container" style="height: 100px; overflow: auto">
+				<div class="dojoDndItem" id="1001">Apple</div>
+				<div class="dojoDndItem" id="1002">Orange</div>
+				<div class="dojoDndItem" id="1003">Banana</div>
+				<div class="dojoDndItem" id="1004">Tomato</div>
+				<div class="dojoDndItem" id="1005">Pepper</div>
+				<div class="dojoDndItem" id="1006">Wheat</div>
+				<div class="dojoDndItem" id="1007">Corn</div>
+				<div class="dojoDndItem" id="1008">Spinach</div>
+				<div class="dojoDndItem" id="1009">Cucumber</div>
+				<div class="dojoDndItem" id="1010">Carrot</div>
+				<div class="dojoDndItem" id="1011">Potato</div>
+				<div class="dojoDndItem" id="1012">Grape</div>
+				<div class="dojoDndItem" id="1013">Lemon</div>
+				<div class="dojoDndItem" id="1014">Lettuce</div>
+				<div class="dojoDndItem" id="1015">Peanut</div>
+			</div>
+		</td>
+	</tr>
+	<tr>
+		<td>
+			<h2>Collection Count Summary</h2>
+			<p>
+				You can't drop items onto this tree, but you can reorder categories. The between threshold
+				is set to 5, so if you are near the top or bottom of a node the drop will be above or below it.
+			</p>
+			<div dojoType="dijit.tree.TreeStoreModel" jsId="catModel"
+				store="myStore" query="{id: '0'}"></div>
+			<div class="container" dojoType="dijit.Tree" id="collectionsTree" model="catModel"
+				getLabel="catTreeCustomLabel"  dndController="dijit.tree.dndSource" betweenThreshold="5"
+				checkAcceptance="dndAccept" checkItemAcceptance="collectionTreeCheckItemAcceptance" getIconClass="getIcon"
+				persist="false"></div>
+		</td>
+		<td>
+			<h2>Collection</h2>
+			<p>
+				Drop items from above list onto this tree, but only on to categories; should fail to let you drop on other items.
+				Can also move items within this tree. The drag threshold is set to 8, so you have a few pixels
+				of buffer before drag operations start.
+			</p>
+			<div dojoType="dijit.tree.TreeStoreModel" jsId="itemModel"
+				store="myStore" query="{id: '0'}" childrenAttrs="items, children"></div>
+			<div class="container" dojoType="dijit.Tree" id="itemTree"
+				model="itemModel"
+				dndController="dijit.tree.dndSource" checkAcceptance="dndAccept" checkItemAcceptance="itemTreeCheckItemAcceptance"
+				dragThreshold="8"
+				getIconClass="getIcon"
+				persist="false"></div>
+		</td>
+	</tr>
+	</table>
+
+	</body>
+</html>
diff --git a/dijit/tests/tree/test_Tree_Programmatic.html b/dijit/tests/tree/test_Tree_Programmatic.html
new file mode 100644
index 0000000..3f86815
--- /dev/null
+++ b/dijit/tests/tree/test_Tree_Programmatic.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit Tree Programmatic Test</title>
+
+	<style someProperty="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+		@import "../../../dojo/resources/dnd.css";
+		@import "../../../dojo/tests/dnd/dndDefault.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script language="JavaScript" someProperty="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+		dojo.require("dijit.tree.dndSource");
+
+		dojo.addOnLoad(function(){
+ 			myStore = new dojo.data.ItemFileWriteStore({url:'../_data/countries.json'});
+			myModel = new dijit.tree.ForestStoreModel({
+				store: myStore,
+				query: {type:'continent'},
+				rootId: "earth",
+				rootLabel: "Earth",
+				childrenAttrs: ["children"]
+			});
+		});
+
+		function createTree(){
+			myTree = new dijit.Tree({
+				id: "myTree",
+				model: myModel,
+				dndController: "dijit.tree.dndSource"
+			});
+			dojo.byId("container").appendChild(myTree.domNode);
+			myTree.startup();
+			dojo.byId("create").disabled = true;
+			dojo.byId("destroy").disabled = false;
+		}
+
+		function destroyTree(){
+			myTree.destroy();
+			dojo.byId("create").disabled = false;
+			dojo.byId("destroy").disabled = true;
+		}
+	</script>
+</head>
+<body class="claro">
+        <h1 class="testTitle">Dijit Forest Store Programmatic Test</h1>
+        <button id="create" onclick="createTree();">Create Tree</button>
+        <button id="destroy" onclick="destroyTree();" disabled>Destroy Tree</button>
+        <div id="container"></div>
+</body>
+</html>
diff --git a/dijit/tests/tree/test_Tree_Styling.html b/dijit/tests/tree/test_Tree_Styling.html
new file mode 100644
index 0000000..2992b02
--- /dev/null
+++ b/dijit/tests/tree/test_Tree_Styling.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Styling The Tree to have Headers</title>
+
+	<style someProperty="text/css">
+		@import "../../../dojo/dojo/resources/dojo.css";
+		@import "../../../dojo/dijit/css/dijitTests.css";
+		@import "../../../dojo/dojo/resources/dnd.css";
+
+		.listTree {
+			width: 300px;
+		}
+
+		.dijitTreeExpandoOpened,
+		.dijitTreeExpandoClosed {
+			display: none;
+		}
+
+
+		.dijitTreeNode .dijitTreeRow {
+			padding-top: 4px;
+			padding-bottom: 2px;
+			border-bottom: 1px solid #bbb;
+		}
+
+		.dijitTreeExpandoLeaf {
+			display: none;
+		}
+
+		.dijitTreeIsLast,
+		.dijitTreeNode {
+			background: transparent;
+		}
+		.dojoDndItemAnchor,
+		.dojoDndItemSelected {
+			background:#CCCCFF none repeat scroll 0 0;
+			color:black;
+		}
+
+		.headerRow {
+			background-color: #eee;
+		}
+		.headerRow .dijitTreeLabel {
+			font-weight: bold;
+		}
+
+		.dijitExpandoText {
+			display: none;
+		}
+
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/soria/soria.css">
+
+	<!-- required: dojo.js -->
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dijit.tree.TreeStoreModel");
+		dojo.require("dijit.Tree");
+
+		function getRowClass(item, isExpanded) {
+			if (!item
+					|| !treeStore.isItem(item)
+					|| treeStore.getValue(item, "type") != "header") {
+				return null;
+			}
+			return "headerRow";
+		}
+
+	</script>
+
+</head>
+<body class="soria">
+
+	<div dojoType="dojo.data.ItemFileWriteStore" jsId="treeStore"
+		url="places.json"></div>
+
+	<div
+		dojoType="dijit.tree.TreeStoreModel"
+		jsId="treeModel"
+		store="treeStore"
+		query="{id:'root'}"
+		childrenAttrs="children"></div>
+
+	<h1 class="testTitle">Styling a Tree to appear like an expandable list</h1>
+	<p>
+		This example shows how to style the dijit.Tree widget to look like an expandable list.
+		To do this, you must specify the getRowClass function
+	</p>
+
+	<div
+		dojoType="dijit.Tree"
+		id="placeTree"
+		model="treeModel"
+		showRoot="false"
+
+		getRowClass="getRowClass"
+
+		class="listTree"
+		openOnClick="true"
+		persist="false"
+	></div>
+
+	</body>
+</html>
diff --git a/dijit/tests/tree/test_Tree_v1.html b/dijit/tests/tree/test_Tree_v1.html
new file mode 100644
index 0000000..1047ffc
--- /dev/null
+++ b/dijit/tests/tree/test_Tree_v1.html
@@ -0,0 +1,118 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit Tree Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.ColorPalette");
+		dojo.require("dijit.Menu");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+<body class="claro">
+
+	<h1 class="testTitle">Dijit Tree Test</h1>
+
+	<div dojoType="dojo.data.ItemFileReadStore" jsId="continentStore"
+		url="../../tests/_data/countries.json"></div>
+
+	<h3>Tree with hardcoded root node (not corresponding to any item in the store)</h3>
+	<p>Clicking a folder node will open/close it (openOnclick==true), and clicking a leaf node will popup an alert.</p>
+	<div dojoType="dijit.Tree" id="mytree" store="continentStore" query="{type:'continent'}"
+		onfocus="console.log('user focus handler')"
+		onblur="console.log('user blur handler')"
+		label="Continents" openOnClick="true">
+		<script type="dojo/method" event="onClick" args="item">
+			alert("Execute of node " + continentStore.getLabel(item)
+				+", population=" + continentStore.getValue(item, "population"));
+		</script>
+	</div>
+
+	<button onclick="dijit.byId('mytree').destroyRecursive();">destroy</button>
+
+	<h2>A rootless tree (no "continents" node) with context menus, and custom icons</h2>
+
+	<ul dojoType="dijit.Menu" id="tree_menu" style="display: none;">
+		<li dojoType="dijit.MenuItem" onClick="alert('Hello world');">Enabled Item</li>
+		<li dojoType="dijit.MenuItem" disabled="true">Disabled Item</li>
+		<li dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+			onClick="alert('not actually cutting anything, just a test!')">Cut</li>
+		<li dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+			onClick="alert('not actually copying anything, just a test!')">Copy</li>
+		<li dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+			onClick="alert('not actually pasting anything, just a test!')">Paste</li>
+		<li dojoType="dijit.PopupMenuItem">
+			<span>Enabled Submenu</span>
+			<ul dojoType="dijit.Menu" id="submenu2">
+				<li dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</li>
+				<li dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</li>
+				<li dojoType="dijit.PopupMenuItem">
+					<span>Deeper Submenu</span>
+					<ul dojoType="dijit.Menu" id="submenu4">
+						<li dojoType="dijit.MenuItem" onClick="alert('Sub-submenu 1!')">Sub-sub-menu Item One</li>
+						<li dojoType="dijit.MenuItem" onClick="alert('Sub-submenu 2!')">Sub-sub-menu Item Two</li>
+					</ul>
+				</li>
+			</ul>
+		</li>
+		<li dojoType="dijit.PopupMenuItem" disabled="true">
+			<span>Disabled Submenu</span>
+			<ul dojoType="dijit.Menu" id="submenu3" style="display: none;">
+				<li dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</li>
+				<li dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</li>
+			</ul>
+		</li>
+	</ul>
+
+	<div dojoType="dijit.Tree" id="tree2" store="continentStore" query="{type:'continent'}">
+		<script type="dojo/connect">
+			var menu = dijit.byId("tree_menu");
+			// when we right-click anywhere on the tree, make sure we open the menu
+			menu.bindDomNode(this.domNode);
+
+			dojo.connect(menu, "_openMyself", this, function(e){
+				// get a hold of, and log out, the tree node that was the source of this open event
+				var tn = dijit.getEnclosingWidget(e.target);
+				console.debug(tn);
+
+				// now inspect the data store item that backs the tree node:
+				console.debug(tn.item);
+
+				// contrived condition: if this tree node doesn't have any children, disable all of the menu items
+				dojo.forEach(menu.getChildren(), function(i){ i.set('disabled', !tn.item.children); });
+
+				// IMPLEMENT CUSTOM MENU BEHAVIOR HERE
+			});
+		</script>
+		<script type="dojo/method" event="getIconClass" args="item, opened">
+           return (!item || continentStore.getValue(item, "type") == "continent") ?
+                   (opened ? "customFolderOpenedIcon" : "customFolderClosedIcon") :
+                    "noteIcon";
+		</script>
+		<script type="dojo/method" event="onClick" args="item">
+			alert("Execute of node " + continentStore.getLabel(item)
+				+", population=" + continentStore.getValue(item, "population"));
+		</script>
+</div>
+
+</body>
+</html>
diff --git a/dijit/tests/tree/treeTestRoot b/dijit/tests/tree/treeTestRoot
new file mode 100644
index 0000000..4a9adf1
--- /dev/null
+++ b/dijit/tests/tree/treeTestRoot
@@ -0,0 +1,10 @@
+[ 
+	{ id: 'node1', name:'node1', someProperty:'somePropertyA', children:[
+			{ $ref: 'node1.1', name: 'node1.1', children: true},
+			{ $ref: 'node1.2', name: 'node1.2'}
+	]},
+	{ id: 'node2', name:'node2', someProperty:'somePropertyB'},
+	{ id: 'node3', name:'node3', someProperty:'somePropertyC'},
+	{ id: 'node4', name:'node4', someProperty:'somePropertyA'},
+	{ id: 'node5', name:'node5', someProperty:'somePropertyB'}
+]
diff --git a/dijit/themes/a11y/colors3x4-rtl.png b/dijit/themes/a11y/colors3x4-rtl.png
new file mode 100644
index 0000000..51a7d11
Binary files /dev/null and b/dijit/themes/a11y/colors3x4-rtl.png differ
diff --git a/dijit/themes/a11y/colors3x4.png b/dijit/themes/a11y/colors3x4.png
index e407881..5125cb6 100644
Binary files a/dijit/themes/a11y/colors3x4.png and b/dijit/themes/a11y/colors3x4.png differ
diff --git a/dijit/themes/a11y/colors7x10-rtl.png b/dijit/themes/a11y/colors7x10-rtl.png
new file mode 100644
index 0000000..c191e90
Binary files /dev/null and b/dijit/themes/a11y/colors7x10-rtl.png differ
diff --git a/dijit/themes/a11y/colors7x10.png b/dijit/themes/a11y/colors7x10.png
index 77d22ce..d1354af 100644
Binary files a/dijit/themes/a11y/colors7x10.png and b/dijit/themes/a11y/colors7x10.png differ
diff --git a/dijit/themes/claro/Calendar.css b/dijit/themes/claro/Calendar.css
new file mode 100644
index 0000000..0cd4b4c
--- /dev/null
+++ b/dijit/themes/claro/Calendar.css
@@ -0,0 +1,257 @@
+/* Calendar
+ * 
+ * Styling Calendar mainly includes:
+ * 
+ * 1. Calendar container
+ * 		.dijitCalendar - main container
+ * 		.dijitCalendarHover / .dijitCalendarActive - states e.g. hover,active
+ * 
+ * 2. Month
+ * 		.dijitCalendarMonthContainer
+ * 		.dijitCalendarMonthLabel
+ *      .dijitCalendarDecrease / .dijitCalendarDecrease - icons for switching to previous/next month
+ *      .dijitCalendarArrowActive .dijitCalendarDecrease - states e.g. hover,active
+ * 
+ * 3. Date
+ * 		.dijitCalendarDayLabelTemplate - week day column header e.g. S M T w T F S
+ * 		.dijitCalendarDateTemplate - date label wrapper
+ * 		.dijitCalendarPreviousMonth .dijitCalendarDateLabel - special labels for previous or next month
+ *      .dijitCalendarSelectedDate .dijitCalendarDateLabel - styles for selected date
+ * 		.dijitCalendarDisabledDate .dijitCalendarDateLabel - styles for disabled date
+ * 		.dijitCalendarActiveDate .dijitCalendarDateLabel - states e.g. hover,active
+ * 
+ * 4. Year
+ * 		.dijitCalendarYearContainer
+ * 		.dijitCalendarYearLabel
+ * 		.dijitCalendarPreviousYear /.dijitCalendarNextYear
+ *      .dijitCalendarNextYearHover / .dijitCalendarPreviousYearHover - states e.g. hover,active
+ *      
+ * 5. Dropdown Month Menu
+ * 		.dijitCalendarMonthContainer .dijitMenu - menu container     
+ * 		.dijitCalendarMonthContainer .dijitMenu .dijitCalendarMonthLabel - month label in menu item
+ * 		.dijitCalendarMonthContainer .dijitMenu .dijitMenuItemHover - menu item hover state
+ */
+
+.claro .dijitCalendar {
+	border:solid 1px #b5bcc7;
+	background-color:#d4ebff;
+	background-image:url("images/calendarContainerImages.png");
+	background-position:0px -448px;
+	background-repeat:repeat-x;
+	text-align:center;
+	padding:6px 5px 3px 5px;
+	-moz-border-radius:4px;
+	-webkit-border-radius:4px;	
+}
+.dj_ie6 .claro .dijitCalendar {
+	background-image:none;
+}
+.claro .dijitCalendar img {
+	border:none;
+}
+.claro .dijitCalendarHover,
+.claro .dijitCalendarActive {
+	background-color: #b7dcff;
+	border:solid 1px #769dc0;
+}
+.claro .dijitCalendarMonthContainer th {
+	text-align:center;
+	padding-bottom:4px;
+	vertical-align:middle;
+}
+.claro .dijitCalendarMonthLabelSpacer {
+	display:none;
+}
+.claro .dijitCalendarMonthLabel {
+	color:#000000;
+	font-size: 1.091em;
+	display: block;
+}
+
+/* next/previous month arrows */
+.claro .dijitCalendarIncrementControl {
+	width:18px;
+	height:16px;
+	background-image: url("images/calendarArrows.png");
+	background-repeat: no-repeat;
+}
+.dj_ie6 .claro .dijitCalendarIncrementControl {
+	background-image: url("images/calendarArrows8bit.png");
+}
+.claro .dijitCalendarIncrease {
+	background-position:-18px 0px;
+}
+.claro .dijitCalendarArrowHover .dijitCalendarDecrease {
+	background-position:-36px 0px;
+}
+.claro .dijitCalendarArrowHover .dijitCalendarIncrease {
+	background-position:-55px 0px;
+}
+.claro .dijitCalendarArrowActive .dijitCalendarDecrease {
+	background-position:-72px 0px;
+}
+.claro .dijitCalendarArrowActive .dijitCalendarIncrease {
+	background-position:-91px 0px;
+}
+.claro .dijitA11ySideArrow {
+	/* text +/- labels instead of arrow icons, for high contrast mode */
+	display: none;
+}
+
+
+.claro .dijitDayLabels th {
+	padding:0px 4px 0px 4px;
+	border-bottom:solid 1px #99b5cd;
+	font-weight:bold;
+	text-align:center;
+}
+.claro .dijitCalendarDayLabelTemplate {
+	padding-bottom:0em;
+	text-align:center;
+	border-bottom:1px solid #99B5CD;
+	font-size:0.909em;
+	padding:0 3px 2px;
+}
+.claro .dijitCalendarDateTemplate {
+	text-align:center;
+	background-color:#fff;
+	background-image:url("images/calendarContainerImages.png");
+	background-position:0px 0px;
+	background-repeat:repeat-x;
+	border-bottom: 1px solid #dadde1;
+	padding-top:0px;
+	font-size:0.909em;
+	font-family: Arial;
+	font-weight:bold;
+	letter-spacing:.05em;
+	text-align:center;
+}
+.dj_ie6 .claro .dijitCalendarDateTemplate {
+	background-image: none;
+}
+.claro .dijitCalendarPreviousMonth,
+.claro .dijitCalendarNextMonth {
+	background-color:#ebf3f9;
+	background-image:none;
+	border-bottom:solid 1px #d2dae8;
+	color:#547da1;
+}
+.claro .dijitCalendarDateTemplate .dijitCalendarDateLabel {
+	text-decoration:none;
+	display:block;
+	padding:3px 5px 3px 4px;
+	border:solid 1px #fff;
+	color:#1e1e1e;
+	background-color:rgba(171,212,251,0);	/* transparent causes black-flash animation problem on webkit */
+	-webkit-transition-property:background-color, border;
+ 	-webkit-transition-duration:.35s;
+}
+.claro .dijitCalendarPreviousMonth .dijitCalendarDateLabel,
+.claro .dijitCalendarNextMonth .dijitCalendarDateLabel{
+	color:#547da1;
+	border-color:#ebf3f9;
+}
+
+.claro .dijitCalendarYearContainer {
+	vertical-align:middle;
+}
+.claro .dijitCalendarYearControl {
+	padding: 1px 2px 2px 2px;
+}
+.claro .dijitCalendarYearLabel {
+	padding:2px 0px 0px 0px;
+	margin:0;
+}
+.claro .dijitCalendarYearLabel span {
+	/* trying to center next/current/previous year vertically, doesn't work on IE6/7 though */
+	vertical-align:middle;
+}
+.claro .dijitCalendarSelectedYear {
+	padding:0px 3px;
+}
+.claro .dijitCalendarNextYear,
+.claro .dijitCalendarPreviousYear {
+	padding: 1px 6px 1px 6px;
+	font-size:0.909em;
+}
+.claro .dijitCalendarSelectedYear {
+	font-size:1.091em;
+	color:#000;
+}
+/* End Normal Calendar Style */
+/* Hovered Calendar Style */
+.claro .dijitCalendarHoveredDate .dijitCalendarDateLabel{
+	background-color:#abd4fb;
+	border:solid 1px #729dc2;
+	color:#000;
+	-webkit-transition-duration:.2s;
+}
+.claro .dijitCalendarNextYearHover,
+.claro .dijitCalendarPreviousYearHover {
+	color:#000;
+	border:solid 1px #fefefe;
+	padding: 0px 5px 0px 5px;	/* reduced by 1 to make room for border */
+	background-color:#eaf4fe;
+}
+/* End Hovered Calendar Style */
+/* Active Calendar Style */
+.claro .dijitCalendarNextYearActive,
+.claro .dijitCalendarPreviousYearActive {
+	border: solid 1px #87b3d9;
+	padding: 0px 5px 0px 5px;	/* reduced by 1 to make room for border */
+	background-color:#90bde6;
+}
+.claro .dijitCalendarActiveDate .dijitCalendarDateLabel {
+	background-image:url("images/calendarContainerImages.png");
+	background-position:0px -300px;
+	background-color:#75b5f0;
+	border:solid 1px #fff;
+	-webkit-transition-duration:.1s;
+}
+.dj_ie6 .claro .dijitCalendarActiveDate .dijitCalendarDateLabel {
+	background-image:none;
+}
+/* End Active Calendar Style */
+/* Selected Calendar Style */
+.claro .dijitCalendarSelectedDate .dijitCalendarDateLabel {
+	color:#000;
+	background-color:#e7f4ff;
+	border-color:#accfed;
+}
+/* End Selected Calendar Style */
+/* Disabled Calendar Style*/
+.claro .dijitCalendarDisabledDate .dijitCalendarDateLabel {
+	text-decoration:line-through;
+	
+	/* override hover effects above, hover and click on disabled date should have no effect */
+	background-color: transparent;
+	border-width: 0px;
+	padding: 4px 6px 4px 5px;
+	color: #547DA1;
+}
+
+/* End Disabled Calendar Style */
+
+/* Styling for month drop down list */
+
+.claro .dijitCalendarMonthContainer .dijitMenu{
+	/* top: 20px !important modifying date drop down so it appears below, instead of over, the current date */
+	top: 20px !important;
+	left: 0px;
+	border-color: #769dc0;
+	background-color: #fff;
+	text-align:center;
+	background-image: none;
+}
+.claro .dijitCalendarMonthContainer .dijitMenu .dijitCalendarMonthLabel{
+	border-top: solid 1px #fff;
+	border-bottom: solid 1px #fff;
+	padding: 2px 20px;
+}
+.claro .dijitCalendarMonthContainer .dijitMenu .dijitMenuItemHover {
+	background-color: #abd6ff;
+	border-color: #769dc0;
+	border-width:1px 0px;
+	background-image: url("images/commonHighlight.png");
+	background-repeat:repeat-x;
+}
\ No newline at end of file
diff --git a/dijit/themes/claro/Calendar_rtl.css b/dijit/themes/claro/Calendar_rtl.css
new file mode 100644
index 0000000..424844b
--- /dev/null
+++ b/dijit/themes/claro/Calendar_rtl.css
@@ -0,0 +1,19 @@
+.claro .dijitCalendarRtl .dijitCalendarIncrease{
+	background-position: 0px 0px;
+}
+.claro .dijitCalendarRtl .dijitCalendarDecrease {
+	background-position: -18px 0px;
+}
+.claro .dijitCalendarRtl .dijitCalendarArrowHover .dijitCalendarIncrease {
+	background-position: -36px 0px;
+}
+.claro .dijitCalendarRtl .dijitCalendarArrowHover .dijitCalendarDecrease {
+	background-position: -55px 0px;
+}
+.claro .dijitCalendarRtl .dijitCalendarArrowActive .dijitCalendarIncrease {
+	background-position: -72px 0px;
+}
+.claro .dijitCalendarRtl .dijitCalendarArrowActive .dijitCalendarDecrease {
+	background-position: -91px 0px;
+}
+
diff --git a/dijit/themes/claro/ColorPalette.css b/dijit/themes/claro/ColorPalette.css
new file mode 100644
index 0000000..938ceb1
--- /dev/null
+++ b/dijit/themes/claro/ColorPalette.css
@@ -0,0 +1,44 @@
+/* ColorPalette
+ * 
+ * Styling of the ColorPalette consists of the following:
+ * 
+ * 1. the whole color palette
+ *		.dijitColorPalette - for outline, border, and background color of the whole color palette
+ *		Note: outline does not work for IE
+ *
+ * 2. the color swatch 
+ *		.dijitColorPalette .dijitPaletteImg
+ *		transparent (but clickable) <img> node inside of each <td>, overlaying the color swatch.
+ *		displays border around a color swatch
+ *
+ * 3. hovered swatch
+ * 		.dijitColorPalette .dijitPaletteCellHover .dijitPaletteImg
+ *		the hovered state of the color swatch - adds border
+ * 	
+ * 4. active and selected swatch
+ * 		.dijitColorPalette .dijitPaletteCellActive .dijitPaletteImg
+ *		.dijitColorPalette .dijitPaletteCellSelected .dijitPaletteImg
+ *		adds border for active or selected state
+ */
+
+.claro  .dijitColorPalette {
+	outline: 1px solid #769dc0; 
+	border: 1px solid #c0ccdf;
+	background:#fff;
+
+	-moz-border-radius: 0px;
+}
+
+.claro .dijitColorPalette .dijitPaletteImg {
+	/* transparent (but clickable) <img> node inside of each <td>, overlaying the color swatch.
+	 * displays border around a color swatch
+	 * overrides border color in dijit.css */
+	border: 1px solid #cecece;
+}
+.claro .dijitColorPalette .dijitPaletteCellHover .dijitPaletteImg {
+	border: 1px solid #000;
+}
+.claro .dijitColorPalette .dijitPaletteCellActive .dijitPaletteImg,
+.claro .dijitColorPalette .dijitPaletteCellSelected .dijitPaletteImg {
+	border: 2px solid #000;
+}
diff --git a/dijit/themes/claro/Common.css b/dijit/themes/claro/Common.css
new file mode 100644
index 0000000..e2f21be
--- /dev/null
+++ b/dijit/themes/claro/Common.css
@@ -0,0 +1,79 @@
+/* ========= Styling rules to affect widgets ========= */
+
+.claro .dijitPopup {
+	box-shadow: 0px 1px 5px rgba(0,0,0,0.25);
+	-webkit-box-shadow: 0px 1px 5px rgba(0,0,0,0.25);
+	-moz-box-shadow: 0px 1px 5px rgba(0,0,0,0.25);
+}
+.claro .dijitTooltipDialogPopup {
+	/* exception popups: do not use a shadow on these because they aren't rectangular */
+	box-shadow: none;
+	-webkit-box-shadow: none;
+	-moz-box-shadow: none;
+}
+
+/* The highlight is shown in the ComboBox menu. */
+.claro .dijitComboBoxHighlightMatch {
+	background-color:#a5beda;
+}
+
+.claro .dijitFocusedLabel {
+	/* for checkboxes or radio buttons, hatch border around the corresponding label, to indicate focus */
+	outline: 1px dotted #666666;
+}
+
+.claro .dijitContentPaneLoading {
+	background:url('images/loadingAnimation.gif') no-repeat left center;
+	padding-left:25px;
+}
+
+/* .dijitContentPaneError icon renders in a dialog box with the error messsage when  there is an error in a HREF url */
+.claro .dijitContentPaneError {
+    background:url('../../icons/images/commonIconsObjActEnabled.png') no-repeat left center;
+    background-position: -496px; 
+	no-repeat left center;
+	padding-left:25px;
+}
+
+/* Drag and Drop */
+.claro .dojoDndItemBefore,
+.claro .dojoDndItemAfter{
+	border-top: 1px solid #769DC0;
+}
+.claro .dojoDndItemOver {
+	cursor:pointer;
+	}
+.claro table.dojoDndAvatar {
+	border: 1px solid #b5bcc7;
+	border-collapse: collapse;
+	background-color: #fff;
+	-webkit-box-shadow:0px 1px 3px rgba(0, 0, 0, .25);
+}
+.claro .dojoDndAvatarHeader td	{ 
+	height: 20px;
+	padding-left:21px;
+}
+.claro.dojoDndMove .dojoDndAvatarHeader, .claro.dojoDndCopy .dojoDndAvatarHeader {
+	background-image: url(images/dnd.png);
+	background-repeat: no-repeat;
+	background-position:2px -122px;
+}
+.claro .dojoDndAvatarItem td {
+	padding: 5px;
+}
+.claro.dojoDndMove .dojoDndAvatarHeader	{
+	background-color: #f58383; 
+	background-position:2px -103px;
+}
+.claro.dojoDndCopy .dojoDndAvatarHeader	{
+	background-color: #f58383; 
+	background-position:2px -68px;
+}
+.claro.dojoDndMove .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{
+	background-color: #97e68d; 
+	background-position:2px -33px;
+}
+.claro.dojoDndCopy .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{
+	background-color: #97e68d;
+	background-position:2px 2px;
+}
diff --git a/dijit/themes/claro/Dialog.css b/dijit/themes/claro/Dialog.css
new file mode 100644
index 0000000..b3bdfcb
--- /dev/null
+++ b/dijit/themes/claro/Dialog.css
@@ -0,0 +1,212 @@
+/* Dialog 
+ * 
+ * Styling Dialog includes two sections: Dialog and Tooltip & TooltipDialog
+ * 
+ * Dialog:
+ * 1. Dialog (default styling): 
+ * 		.dijitDialog - styles for dialog's bounding box
+ *
+ * 2. Dialog title 
+ * 		.dijitDialogTitleBar - styles for the title container at the top of dialog
+ * 		.dijitDialogTitle - the text container in dialog title
+ * 
+ * 3. Dialog content 
+ * 		.dijitDialogPaneContent - main container for content area and action bar
+ * 		.dijitDialogPaneContentArea - styles for content container
+ * 
+ * 4. Dialog action bar 
+ * 		.dijitDialogPaneActionBar - styles for action buttons lie at the bottom of dialog pane content
+ * 
+ * 5. Dialog underlay 
+ * 		.dijitDialogUnderlay - div under the dialog which used for separate dialog and page content
+ * 
+ * 
+ * Tooltip & TooltipDialog:
+ * 1. tooltip content container: 
+ * 		.dijitTooltipContainer - tooltip content container
+ *
+ * 2. tooltip connector: 
+ * 		.dijitTooltipConnector - tooltip anchor includes 4 direction(up, down, left, right)
+ */
+
+.claro .dijitDialog {
+	border: 1px solid #769dc0;
+	box-shadow:0px 1px 5px rgba(0,0,0,0.25);
+	-webkit-box-shadow:0px 1px 5px rgba(0,0,0,0.25);
+	-moz-box-shadow: 0px 1px 5px rgba(0,0,0,0.25);
+} 
+
+.claro .dijitDialogPaneContent {
+	background: #fff repeat-x top left;
+	border-top: 1px solid #769dc0;
+	padding:10px 8px;
+	position: relative;
+}
+
+.claro .dijitDialogPaneContentArea {
+	/* trick to get action bar (gray bar at bottom with OK/cancel buttons) to span from
+	 * left to right but still indent dialog content
+	 */ 
+	margin: -10px -8px;
+	padding: 10px 8px;
+}
+
+.claro .dijitDialogPaneActionBar {
+	/* gray bar at bottom of dialog with OK/Cancel buttons */
+	background-color: #f2f2f2;
+	padding: 3px 5px 2px 7px;
+	text-align: right;
+	border-top: 1px solid #cdcdcd;
+	margin: 10px -8px -10px;
+}
+.claro .dijitDialogPaneActionBar .dijitButton {
+	float: none;
+}
+
+.claro .dijitDialogTitleBar {
+	/* outer container for the titlebar of the dialog */
+	border: 1px solid #fff;
+	border-top:none;
+	background-color: #abd6ff;
+	background-image: url("images/titlebar.png");
+	background-repeat:repeat-x;
+	padding: 5px 7px 4px 7px;
+}
+
+.claro .dijitDialogTitle {
+	/* typography and styling of the dialog title */
+	padding: 0px 1px;
+	font-size:1.091em;
+}
+
+.claro .dijitDialogCloseIcon {
+	/* the default close icon for the dialog */
+	background: url("images/dialogCloseIcon.png");
+	background-repeat:no-repeat;
+	position: absolute;
+	right: 5px;
+	height: 15px;
+	width: 21px;
+}
+.dj_ie6 .claro .dijitDialogCloseIcon {
+	background-image: url("images/dialogCloseIcon8bit.png");
+}
+.claro .dijitDialogCloseIconHover {
+	background-position:-21px;
+}
+.claro .dijitDialogCloseIconActive {
+	background-position:-42px;
+}
+
+/* Tooltip and TooltipDialog */
+
+.claro .dijitTooltip,
+.claro .dijitTooltipDialog {
+	/* the outermost dom node, holding the connector and container */
+	background: transparent;	/* make the area on the sides of the arrow transparent */
+}
+.dijitTooltipBelow {
+	/* leave room for arrow above content */
+	padding-top: 13px;
+	padding-left:3px;
+	padding-right:3px;
+}
+
+.dijitTooltipAbove {
+	/* leave room for arrow below content */
+	padding-bottom: 13px;
+	padding-left:3px;
+	padding-right:3px;
+}
+
+.claro .dijitTooltipContainer {
+	/* the part with the text */
+	background-color:#fff;
+	background-image:url("images/tooltip.png");
+	background-repeat:repeat-x;
+	background-position:-575px 100%;
+	border:1px solid #769DC0;
+	padding:6px 8px;
+	border-radius: 4px;
+	-webkit-border-radius: 4px;
+	-moz-border-radius: 4px;
+	box-shadow:0px 1px 3px rgba(0,0,0,0.25);
+	-webkit-box-shadow:0px 1px 3px rgba(0,0,0,0.25);
+	-moz-box-shadow: 0px 1px 3px rgba(0,0,0,0.25);
+	font-size: 1em;
+} 
+
+.dj_ie6 .claro .dijitTooltipContainer {
+	background-image: none;
+}
+.claro .dijitTooltipConnector {
+	/* the arrow piece */
+	border: 0px;
+	z-index: 2;
+	background-image:url("images/tooltip.png");
+	background-repeat:no-repeat;
+	width:16px;
+	height:14px;
+}
+.dj_ie6 .claro .dijitTooltipConnector {
+	background-image:url("images/tooltip8bit.png");
+}
+.claro .dijitTooltipABRight .dijitTooltipConnector {
+	/* above or below tooltip, but the arrow appears on the right,
+		and the right edges of target and tooltip are aligned rather than the left */
+	left: auto !important;
+	right: 3px;
+}
+
+.claro .dijitTooltipBelow .dijitTooltipConnector {
+	/* the arrow piece for tooltips below an element */
+	top: 0px;
+	left: 3px;
+	background-position:-31px 0%;
+	width:16px;
+	height:14px;
+}
+
+.claro .dijitTooltipAbove .dijitTooltipConnector {
+	/* the arrow piece for tooltips above an element */
+	bottom: 0px;
+	left: 3px;
+	background-position:-15px 0%;
+	width:16px;
+	height:14px;
+}
+.dj_ie7 .claro .dijitTooltipAbove .dijitTooltipConnector,
+.dj_ie6 .claro .dijitTooltipAbove .dijitTooltipConnector {
+	bottom: -1px;
+}
+
+.claro .dijitTooltipLeft {
+	padding-right: 14px;
+}
+.dj_ie6 .claro .dijitTooltipLeft {
+	padding-left: 15px;
+}
+.claro .dijitTooltipLeft .dijitTooltipConnector {
+	/* the arrow piece for tooltips to the left of an element, bottom borders aligned */
+	right: 0px;
+	bottom: 3px;
+	background-position:0px 0%;
+	width:16px;
+	height:14px;
+}
+
+.claro .dijitTooltipRight {
+	padding-left: 14px;
+}
+.claro .dijitTooltipRight .dijitTooltipConnector {
+	/* the arrow piece for tooltips to the right of an element, bottom borders aligned */
+	left: 0px;
+	bottom: 3px;
+	background-position:-48px 0%;
+	width:16px;
+	height:14px;
+}
+
+.claro .dijitDialogUnderlay {
+	background: #fff;
+}
diff --git a/dijit/themes/claro/Dialog_rtl.css b/dijit/themes/claro/Dialog_rtl.css
new file mode 100644
index 0000000..7c1e0f5
--- /dev/null
+++ b/dijit/themes/claro/Dialog_rtl.css
@@ -0,0 +1,10 @@
+/* Dialog */
+.claro .dijitDialogRtl .dijitDialogCloseIcon {
+	right: auto;
+	left: 5px;
+}
+
+.claro .dijitDialogRtl .dijitDialogPaneActionBar {
+	text-align: left;
+	padding: 3px 7px 2px 5px;
+}
diff --git a/dijit/themes/claro/Editor.css b/dijit/themes/claro/Editor.css
new file mode 100644
index 0000000..8c30469
--- /dev/null
+++ b/dijit/themes/claro/Editor.css
@@ -0,0 +1,56 @@
+/* Editor 
+ * 
+ * Styling Editor means styling the Editor inside iframe container (dijitEditorIFrameContainer)
+ * 
+ * 1. Editor iframe container (default styling): 
+ * 		.dijitEditorIFrameContainer - normal state styles: background-color, border, padding
+ *
+ * 2. hovered Editor iframe container (ie, mouse hover on editor)
+ * 		.dijitEditorHover .dijitEditorIFrameContainer/dijitEditorIFrame - styles when mouse hover on the container
+ * 
+ * 3. focused Editor iframe container (ie, mouse focus on the editor pane)
+ * 		.dijitEditorFocused .dijitEditorIFrameContainer/dijitEditorIFrame - styles when container focused
+ * 
+ * 3. disabled Editor iframe container 
+ * 		.dijitEditorDisabled - editor's inner iframe container disable status styles: background, border
+ */
+
+.claro .dijitEditorIFrameContainer{
+	padding:3px 3px 1px 10px;
+}
+.claro .dijitEditorIFrame {
+	background-color: #fff;
+}
+.claro .dijitEditor {
+	border: 1px solid #b5bcc7;
+}
+.claro .dijitEditor .dijitEditorIFrameContainer{
+	background-color: #fff;
+	background-image: url('form/images/textBox_back.png');
+	background-repeat:repeat-x;
+}
+.dj_ie6 .claro .dijitEditor .dijitEditorIFrameContainer{
+	background-image: none;
+}
+.claro .dijitEditorHover .dijitEditorIFrameContainer,
+.claro .dijitEditorHover .dijitEditorIFrameContainer .dijitEditorIFrame{
+	background-color: #eef7ff;
+}
+.claro .dijitEditorFocused .dijitEditorIFrameContainer,
+.claro .dijitEditorFocused .dijitEditorIFrameContainer .dijitEditorIFrame{
+	/* TODO: contradicts rule above, which background-color do you want? */
+	background-color: #fff;
+}
+
+
+/* Disabled */
+.claro .dijitEditorDisabled {
+	border: 1px solid #d3d3d3;
+	color: #818181;
+}
+
+.claro .dijitDisabled .dijitEditorIFrame,
+.claro .dijitDisabled .dijitEditorIFrameContainer {
+	background-color: #efefef;
+	background-image: none;
+}
\ No newline at end of file
diff --git a/dijit/themes/claro/Editor_rtl.css b/dijit/themes/claro/Editor_rtl.css
new file mode 100644
index 0000000..f9427db
--- /dev/null
+++ b/dijit/themes/claro/Editor_rtl.css
@@ -0,0 +1,7 @@
+/* Editor */
+
+.claro .dijitEditorRtl .dijitEditorIFrameContainer{
+	padding:3px 10px 1px 3px;
+}
+
+
diff --git a/dijit/themes/claro/InlineEditBox.css b/dijit/themes/claro/InlineEditBox.css
new file mode 100644
index 0000000..50bb5c0
--- /dev/null
+++ b/dijit/themes/claro/InlineEditBox.css
@@ -0,0 +1,23 @@
+/* InlineEditBox
+ * 
+ * Styling InlineEditBox mainly includes:
+ * 
+ * 1. Normal state
+ * 		.dijitInlineEditBoxDisplayMode  - for border
+ * 
+ * 2. Hover state
+ * 		.dijitInlineEditBoxDisplayModeHover - for border and background color
+ */
+
+.claro .dijitInlineEditBoxDisplayMode {
+	border: 1px solid transparent;
+}
+
+.claro .dijitInlineEditBoxDisplayModeHover {
+	background-color: #e2f1ff;
+	border: solid 1px #769dc0;
+}
+
+.dj_ie6 .claro .dijitInlineEditBoxDisplayMode {
+	border: none;
+}
diff --git a/dijit/themes/claro/Menu.css b/dijit/themes/claro/Menu.css
new file mode 100644
index 0000000..df310f6
--- /dev/null
+++ b/dijit/themes/claro/Menu.css
@@ -0,0 +1,182 @@
+/* Menu 
+
+There are three areas of styling for the Menu:  
+ 
+ 1. The menu 
+ 	There are three types of menus:
+ 	i)Context Menu
+ 	ii)Drop down Menu
+ 	iii) Navigation Menu
+ 	All three types of menus are affected by the .dijitMenu class in which you can set the background-color, padding and border
+ 	.dijitMenu affects the drop down menu in TimeTextBox, Calendar, ComboBox and FilteringSelect
+  .dijitMenuTable - for padding - also affects Select widget 	
+  	
+ 2. The menu bar
+ 	.dijitMenuBar - for border, margins, padding, background-color of the menu bar
+ 	.dijitMenuBar .dijitMenuItem - for padding, text color of menu items in the menu bar (overrides .dijitMenuItem) 
+ 	
+ 3. Menu items - items in the menu.  
+ 	.dijitMenuItem - for color
+ 	.dijitMenuItemHover, .dijitMenuItemSelected - for background-color, border, text color, padding of a menu item or menubar item that has been hovered over or selected	
+ 	.dijitMenuItemActive - for bacgkround-color of an active (mousedown) menu item
+	td.dijitMenuItemIconCell - for padding around a  menu item's icon
+	td.dijitMenuItemLabel - for padding around a menu item's label	
+	.dijitMenuSeparatorTop - for border, top border, of the separator
+	.dijitMenuSeparatorBottom - for bottom margin of the separator
+	
+	Styles specific to ComboBox and FilteringSelect widgets: 
+	.dijitComboBoxMenu .dijitMenuItem - for padding and border of a menu item in a ComboBox or FilteringSelect widget's menu
+	.dijitComboBoxMenu .dijitMenuItemSelected- for text color, background-color and border of a menu item in a ComboBox or FilteringSelect widget's menu
+
+*/
+.claro .dijitMenuBar {
+	border: 1px solid #b5bcc7;
+	margin: 0px;
+	padding: 0px;
+	background-color: #e6e6e7;
+	background-image: url("images/commonHighlight.png");
+	background-position:0px 0px;
+	background-repeat:repeat-x;
+}
+.dj_ie6 .claro .dijitMenuBar {
+	background-image:none;
+}
+.claro .dijitMenu {
+	background-repeat:repeat-y;
+	background-color:#fff;
+	border: 1px solid #769dc0;
+
+	/* so adjoining borders of MenuBar/ComboBox and Menu overlap, avoiding double border */
+	margin: -1px 0;
+}
+.claro .dijitMenuBar .dijitMenuItem {  
+	padding: 6px 10px 7px;
+	background-position:0px 100px;
+	color:#4a4a4a;
+	margin:-1px;
+}	
+.claro .dijitMenuItem {
+	background-image: url("images/menuHighlight.png");
+	background-position:0px -40px;
+	background-repeat:repeat-x;
+}
+
+/* this prevents jiggling upon hover of a menu item */
+.claro .dijitMenuTable {
+	border-collapse:separate;
+	border-spacing:0 0;
+	padding:0px;
+}
+.claro .dijitMenuItem td{
+	padding:1px;
+}
+/* hover over a MenuBarItem */
+.claro .dijitMenuPassive .dijitMenuItemHover,
+.claro .dijitMenuPassive .dijitMenuItemSelected {
+	background-color: #abd6ff;
+	border:solid 1px #769dc0;
+	background-position:0px 0px;
+	color:#000;
+	padding: 5px 9px 6px;
+}
+.claro .dijitMenuPassive .dijitMenuItemActive{
+	background-position:0px -177px;
+}
+.dj_ie6 .claro .dijitMenuItem,
+.dj_ie6 .claro .dijitMenuPassive .dijitMenuItem {
+	background-image: none;
+}
+
+/* MenuBarItem that has been selected and menu drops down from it */
+.claro .dijitMenuActive .dijitMenuItemHover,
+.claro .dijitMenuActive .dijitMenuItemSelected {
+	border:solid 1px #769dc0;
+	padding: 5px 9px 6px;
+	background-color: #9dcfff;
+	background-position:0px 0px;
+	color:#000;
+}
+.dj_ie .claro .dijitMenuActive .dijitMenuItemHover,
+.dj_ie .claro .dijitMenuActive .dijitMenuItemSelected,
+.dj_ie .claro .dijitMenuPassive .dijitMenuItemHover,
+.dj_ie .claro .dijitMenuPassive .dijitMenuItemSelected {
+	padding-top: 6px;
+	padding-bottom: 5px;
+	margin-top: -3px;
+}
+.claro .dijitMenuActive .dijitMenuItemActive{
+	background-color: #7dbefa;
+	background-position:0px -177px;
+}
+.claro .dijitMenuItemActive {
+	background-position:0px -177px;
+}
+.claro td.dijitMenuItemIconCell {
+ padding: 2px;
+ margin: 0px 0px 0px 4px;
+}
+.claro td.dijitMenuItemLabel {
+	padding-top: 5px;
+	padding-bottom: 5px;
+}
+.claro .dijitMenuExpand {
+	width: 7px;
+	height: 7px;
+	background-image: url('images/spriteArrows.png');
+	background-position: -14px 0px;
+	margin-right:3px;
+}
+.claro .dijitMenuItemDisabled .dijitMenuItemIconCell {
+	opacity:1;
+}
+.claro .dijitMenuSeparatorTop {
+	height: auto;
+	margin-top:1px; /* prevents spacing above/below separator */
+	border-bottom: 1px solid #b5bcc7
+}
+.claro .dijitMenuSeparatorBottom{
+	height: auto;
+	margin-bottom:1px;
+}
+/* the checked menu item */
+.claro .dijitCheckedMenuItemIconChar {
+	display: none;
+}
+.claro .dijitCheckedMenuItemIcon {
+	background-image: url('form/images/checkboxRadioButtonStates.png');
+	background-repeat:no-repeat;
+	background-position: -15px 50%;
+	width:15px;
+	height:16px;
+}
+.dj_ie6 .claro .dijitCheckedMenuItemIcon {
+	background-image: url('form/images/checkboxAndRadioButtons_IE6.png');
+}
+.claro .dijitCheckedMenuItemChecked .dijitCheckedMenuItemIcon {
+	background-position: 0 50%;
+}
+
+/*ComboBox Menu*/
+.claro .dijitComboBoxMenu {
+	margin-left:0px;
+	background-image: none;
+}
+.claro .dijitComboBoxMenu .dijitMenuItem{
+	padding:2px 0px;
+	text-indent:6px;
+	border-width:1px 0px 1px 0px;
+	border-style:solid;
+	border-color:#fff;
+}
+.claro .dijitComboBoxMenu .dijitMenuItemSelected {
+	color:#000;
+	border-color:#768dc0;
+	background-color:#abd6ff;
+}
+.claro .dijitComboBoxMenuActive .dijitMenuItemSelected {
+	background-position:0px -177px;
+	background-color:#7dbefa;
+}
+.claro .dijitMenuPreviousButton, .claro .dijitMenuNextButton {
+	font-style: italic;
+}
diff --git a/dijit/themes/claro/Menu_rtl.css b/dijit/themes/claro/Menu_rtl.css
new file mode 100644
index 0000000..00e820c
--- /dev/null
+++ b/dijit/themes/claro/Menu_rtl.css
@@ -0,0 +1,9 @@
+.claro .dijitMenuItemRtl .dijitMenuExpand {
+	background-position: -7px 0px;
+	margin-right: 0px;
+	margin-left: 3px;
+}
+
+.claro .dijitMenuItemRtl .dijitMenuItemIcon {
+	margin:0px 4px 0px 0px;
+}
diff --git a/dijit/themes/claro/ProgressBar.css b/dijit/themes/claro/ProgressBar.css
new file mode 100644
index 0000000..57c5a2a
--- /dev/null
+++ b/dijit/themes/claro/ProgressBar.css
@@ -0,0 +1,53 @@
+/* ProgressBar
+ * 
+ * Styling of the ProgressBar consists of the following:
+ * 
+ * 1. the base progress bar
+ *		.dijitProgressBar -	sets margins for the progress bar
+ *
+ * 2. the empty bar
+ *		.dijitProgressBarEmpty  - sets background img and color for bar or parts of bar that are not finished yet
+ *		Also sets border color for whole bar
+ *
+ * 3. tile mode
+ * 		.dijitProgressBarTile
+ *		inner container for finished portion when in 'tile' (image) mode 
+ * 	
+ * 4. full bar mode
+ * 		.dijitProgressBarFull
+ *		adds border to right side of the filled portion of bar
+ *
+ * 5. text for label of  bar
+ *		.dijitProgressBarLabel - sets text color, which must contrast with both the "Empty" and "Full" parts. 
+ * 	
+ * 6. indeterminate mode
+ *		.dijitProgressBarIndeterminate .dijitProgressBarTile 
+ * 		sets animated gif for the progress bar in 'indeterminate' mode
+ */
+ 
+.claro .dijitProgressBar {
+	margin:2px 0px 2px 0px;
+}
+.claro .dijitProgressBarEmpty {
+	/* outer container and background of the bar that's not finished yet*/
+	background:#fff url("images/progressBarEmpty.png") repeat-none left;
+	border-color: #769dc0;
+}
+.claro .dijitProgressBarTile {
+	/* inner container for finished portion when in 'tile' (image) mode */
+	background:#9dcfff url("images/progressBarFull.png") repeat-x top;	
+}
+.dj_ie6 .claro .dijitProgressBarTile {
+	background-image: none;
+} 
+.claro .dijitProgressBarFull {
+	border-right:1px solid #769dc0;
+}
+.claro .dijitProgressBarLabel {
+	/* Set to a color that contrasts with both the "Empty" and "Full" parts. */
+	color:#293a4b;
+}
+.claro .dijitProgressBarIndeterminate .dijitProgressBarTile {
+	/* use an animated gif for the progress bar in 'indeterminate' mode */
+	background:#cad2de url("images/progressBarAnim.gif") repeat-x top;
+} 
\ No newline at end of file
diff --git a/dijit/themes/claro/TimePicker.css b/dijit/themes/claro/TimePicker.css
new file mode 100644
index 0000000..3b6ca98
--- /dev/null
+++ b/dijit/themes/claro/TimePicker.css
@@ -0,0 +1,125 @@
+/* Time Picker 
+ *
+ * Styling the Time Picker consists of the following: 
+ *
+ * 1. minor time values
+ * 		.dijitTimePickerTick - set text color, size, background color of minor values
+ * 		.dijitTimePickerTickHover - set hover style of minor time values
+ * 		dijitTimePickerTickSelected - set selected style of minor time values
+ *
+ * 2. major time values - 1:00, 2:00, times on the hour 
+ * 		set text color, size, background color, left/right margins for "zoom" affect
+ * 		.dijitTimePickerMarkerHover - to set hover style of major time values
+ * 		.dijitTimePickerMarkerSelected - set selected style of major time values
+ * 
+ * 3. up and down arrow buttons
+ * 		.dijitTimePicker .dijitButtonNode - background-color, border
+ * 		.dijitTimePicker .dijitUpArrowHover, .dijitTimePicker .dijitDownArrowHover - set background-color for hover state
+ *
+ *	Other classes provide the fundamental structure of the TimePicker and should not be modified. 
+ */
+
+/* override Button.css */
+.claro .dijitTimePicker .dijitButtonNode {
+	padding: 0 0;
+	border-radius: 0;
+	-moz-border-radius: 0;
+	-webkit-border-radius: 0;
+}
+.claro .dijitTimePicker{
+	border:1px #b5bcc7 solid;
+	border-top:none;
+	border-bottom:none;
+	background-color:#fff;
+}
+.claro .dijitTimePickerItem{
+	/* dijitTimePickerItem refers to both Tick's (minor values like 2:15, 2:30, 2:45) and Marker's (major values like 2PM, 3PM) */
+	background-image: url("images/commonHighlight.png");
+	background-position:0px -1px;
+	background-repeat:repeat-x;
+	border-top:solid 1px #b5bcc7;
+	border-bottom:solid 1px #b5bcc7;
+	margin-right:-1px;
+	margin-left:-1px;
+	margin-top:-1px;
+}
+/* to make up for lack of alpha transparency in IE6 */
+.dj_ie6 .claro .dijitTimePickerItem {
+	background-image: none;
+}
+.claro .dijitTimePickerTick {
+	/* minor value */
+	color:#7a7a7a;
+	background-color:#f2f2f2;
+	font-size:0.818em;
+}
+.claro .dijitTimePickerMarker {
+	/* major value - 1:00, 2:00, times on the hour */
+	color:#000;
+	background-color:#e3f2ff;
+	font-size: 1em;
+	white-space: nowrap;
+}
+.claro .dijitTimePickerTickHover,
+.claro .dijitTimePickerMarkerHover,
+.claro .dijitTimePickerMarkerSelected,
+.claro .dijitTimePickerTickSelected {
+	background-color: #83c0fa;
+	color:#000;
+	border:solid 1px #b5bcc7;
+	margin-left:-7px;
+	margin-right:-7px;
+}
+.claro .dijitTimePickerMarkerSelected,
+.claro .dijitTimePickerTickSelected {
+	font-size: 1em;
+	}
+.dj_ie .claro .dijitTimePickerTickHover,
+.dj_ie .claro .dijitTimePickerMarkerHover,
+.dj_ie .claro .dijitTimePickerMarkerSelected,
+.dj_ie .claro .dijitTimePickerTickSelected  {
+	width: 114%;
+}
+.dj_ie6 .claro .dijitTimePickerTickHover,
+.dj_ie6 .claro .dijitTimePickerMarkerHover,
+.dj_ie6 .claro .dijitTimePickerMarkerSelected,
+.dj_ie6 .claro .dijitTimePickerTickSelected  {
+	position: relative; /* creates widening of element */	
+	zoom: 1; /* creates widening of element */
+}
+.claro .dijitTimePickerTick .dijitTimePickerItemInner {
+	padding:1px;
+	margin:0px;
+}
+.claro .dijitTimePicker .dijitButtonNode {
+	border-left:none;
+	border-right:none;
+	border-color:#b5bcc7;
+	background-color: #f6f7fa;
+	background-image: url("images/commonHighlight.png");
+	background-position:0px -1px;
+	background-repeat:repeat-x;
+}
+.dj_ie6 .claro .dijitTimePicker .dijitButtonNode {
+	background-image: none;
+}
+.claro .dijitTimePicker .dijitArrowButtonInner{
+	height: 100%; /* hack claro.button.css */
+	background-image: url("form/images/commonFormArrows.png");
+	background-repeat: no-repeat;
+	background-position:-140px 45%;
+}
+.claro .dijitTimePicker .dijitDownArrowButton .dijitArrowButtonInner{
+	background-position:-35px 45%;
+}
+/* hover */
+.claro .dijitTimePicker .dijitUpArrowHover, 
+.claro .dijitTimePicker .dijitDownArrowHover {
+	background-color: #abd6ff;
+}
+.claro .dijitTimePicker .dijitUpArrowHover .dijitArrowButtonInner {
+	background-position:-175px 45%;
+}
+.claro .dijitTimePicker .dijitDownArrowHover .dijitArrowButtonInner {
+	background-position:-70px 45%;
+}
\ No newline at end of file
diff --git a/dijit/themes/claro/TimePicker_rtl.css b/dijit/themes/claro/TimePicker_rtl.css
new file mode 100644
index 0000000..0a471a9
--- /dev/null
+++ b/dijit/themes/claro/TimePicker_rtl.css
@@ -0,0 +1,10 @@
+/* TimePicker */
+
+.dj_ie .claro .dijitTimePickerRtl .dijitTimePickerTickHover,
+.dj_ie .claro .dijitTimePickerRtl .dijitTimePickerMarkerHover,
+.dj_ie .claro .dijitTimePickerRtl .dijitTimePickerMarkerSelected,
+.dj_ie .claro .dijitTimePickerRtl .dijitTimePickerTickSelected {
+	margin-left:-6px;
+	margin-right:-8px;
+	width: 114%;	
+}
\ No newline at end of file
diff --git a/dijit/themes/claro/TitlePane.css b/dijit/themes/claro/TitlePane.css
new file mode 100644
index 0000000..b7bdecb
--- /dev/null
+++ b/dijit/themes/claro/TitlePane.css
@@ -0,0 +1,73 @@
+/* TitlePane 
+ * 
+ * Styling TitlePane means styling the TitlePane title and its content container  (dijitTitlePane)
+ * 
+ * TitlePane title:
+ * 1. TitlePane title (default styling): 
+ * 		.dijitTitlePaneTitle - TitlePane's title div style: background-color, border
+ *
+ * 2. hovered TitlePane title (ie, mouse hover on a title bar)
+ * 		.dijitTitlePaneTitleHover - styles when mouse hover on the title div
+ * 
+ * 3. active TitlePane title (ie, mouse down on a title bar)
+ * 		.dijitTitlePaneTitleActive - styles when mouse down on the title div
+ * 
+ * 
+ * TitlePane Content Container:
+ * 1. outer/inner container: 
+ * 		.dijitTitlePaneContentOuter / dijitTitlePaneContentInner - styles for the content outer div
+ */
+
+.claro .dijitTitlePaneTitle {
+	background-color: #e6e6e7;
+	background-image: url("images/titlebar.png");
+	background-repeat:repeat-x;
+	border:1px solid #b5bcc7;
+	padding: 0px 7px 3px 7px;
+	min-height:17px;
+	color:#131313;
+}
+.dj_ie6 .claro .dijitTitlePaneTitle {
+	background-image: none;
+}
+.claro .dijitTitlePaneTitleHover {
+	background-color: #abd6ff;
+	border-color: #769dc0;
+}
+.claro .dijitTitlePaneTitleActive {
+	background-color: #7dbefa;
+	border-color: #769dc0;
+	background-position:0px -136px;
+}
+.claro .dijitTitlePaneTitleFocus {
+	margin-top:3px;
+	padding-bottom:2px;
+}
+.claro .dijitTitlePane .dijitArrowNode {
+	background-image: url('images/spriteArrows.png');
+	background-repeat: no-repeat;
+	height: 8px;
+	width: 7px;
+}
+.claro .dijitTitlePane .dijitOpen .dijitArrowNode {
+	background-position: 0px 0px;
+}
+.claro .dijitTitlePane .dijitClosed .dijitArrowNode {
+	background-position: -14px 0px;
+}
+.claro .dijitTitlePaneFocused .dijitTitlePaneTextNode {
+	color:#000;
+}
+.claro .dijitTitlePaneContentOuter {
+	background: #ffffff;
+	border:1px solid #b5bcc7;
+	border-top:none;
+}
+.claro .dijitTitlePaneContentInner {
+	padding:10px;
+}
+.claro .dijitTitlePaneTextNode {
+	margin-left: 4px;
+	margin-right: 4px;
+	vertical-align:text-top;
+}
\ No newline at end of file
diff --git a/dijit/themes/claro/TitlePane_rtl.css b/dijit/themes/claro/TitlePane_rtl.css
new file mode 100644
index 0000000..a0e2856
--- /dev/null
+++ b/dijit/themes/claro/TitlePane_rtl.css
@@ -0,0 +1,4 @@
+/* TitlePane */
+.claro .dijitTitlePaneRtl .dijitClosed .dijitArrowNode {
+	background-position: -7px 0px;
+}
\ No newline at end of file
diff --git a/dijit/themes/claro/Toolbar.css b/dijit/themes/claro/Toolbar.css
new file mode 100644
index 0000000..a222aa5
--- /dev/null
+++ b/dijit/themes/claro/Toolbar.css
@@ -0,0 +1,170 @@
+/* Toolbar 
+ * 
+ * Styling Toolbar means styling the toolbar container and the widget inside toolbar  (dijitToolbar)
+ * 
+ * 1. toolbar (default styling): 
+ * 		.dijitToolbar - styles for outer container
+ *
+ * 2. widget inside toolbar
+ * 		.dijitToolbar .dijitButtonNode   - Button widget
+ * 					  .dijitComboButton  - ComboButton widget
+ * 					  .dijitDropDownButton  - DropDownButton widget
+ * 					  .dijitToggleButton  - ToggleButton widget
+ * 		
+ * 3. hovered widget inside toolbar (ie, mouse hover on the widget inside)
+ * 			.dijitToolbar .dijitButtonNodeHover  - styles for hovered Button widget
+ * 
+ * 4. actived widget inside toolbar (ie, mouse down on the widget inside)
+ * 			.dijitToolbar .dijitButtonNodeActive  - mouse down on Button widget
+ */
+
+.claro .dijitToolbar {
+	border-bottom: 1px solid #b5bcc7;
+	background-color: #f1f1f1;
+	background-image: url("images/commonHighlight.png");
+	background-position:0px 0px;
+	background-repeat:repeat-x;
+	padding: 2px 0px 2px 4px;
+	zoom: 1;
+}
+
+.claro .dijitToolbar label {
+	padding: 0px 3px 0 6px;
+}
+
+/** override claro/form/Button.css **/
+.claro .dijitToolbar .dijitButtonNode {
+	border:none;
+	padding: 2px;
+	background-image: url("images/commonHighlight.png");
+	background-position:0 -30px;
+	background-repeat:repeat-x;
+	background-color:rgba(171,214,255,0);
+	border-radius: 2px;	
+	-moz-border-radius: 2px;	
+	-webkit-border-radius: 2px;	
+	-moz-box-shadow: none;
+	-webkit-box-shadow: none;
+	-webkit-transition-property:background-color;
+	-webkit-transition-duration:.3s, .35s;
+}
+.claro .dijitToolbar .dijitComboButton .dijitButtonNode{
+	padding: 3px 2px 3px 2px;	/* make the ComboButton in toolbar more stable when mouse hovering */
+}
+.dj_ie .claro .dijitToolbar .dijitButtonNode {
+	background-color: transparent;   /* for IE, which doesn't understand rgba(...) */
+}
+.dj_ie6 .claro .dijitToolbar .dijitButtonNode {
+	background: none;	/* because background-color: transparent above doesn't work */
+}
+
+.claro .dijitToolbar .dijitComboBox .dijitButtonNode {
+	padding: 0px;
+}
+
+.claro .dijitToolbar .dijitComboButton {
+	padding: 1px;
+}
+/* hover status */
+.claro .dijitToolbar .dijitButtonHover .dijitButtonNode,
+.claro .dijitToolbar .dijitDropDownButtonHover .dijitButtonNode,
+.claro .dijitToolbar .dijitToggleButtonHover .dijitButtonNode {
+	background-position:0 0;
+	border:solid 1px #769dc0;
+	background-color: #abd6ff;
+	padding: 1px;
+}
+.claro .dijitToolbar .dijitComboButtonHover {
+	background-color: #abd6ff;
+	border: solid 1px #769dc0;
+	padding: 0px;
+}
+.claro .dijitToolbar .dijitComboButtonHover .dijitButtonNode,
+.claro .dijitToolbar .dijitComboButtonHover .dijitDownArrowButton {
+	background-position:0 0;
+	padding: 2px;
+}
+.claro .dijitToolbar .dijitComboButtonHover .dijitDownArrowButton {
+	background-color: #7dd6fa;
+}
+/* actve status */
+.claro .dijitToolbar .dijitButtonActive .dijitButtonNode,
+.claro .dijitToolbar .dijitDropDownButtonActive .dijitButtonNode,
+.claro .dijitToolbar .dijitToggleButtonActive .dijitButtonNode {
+	border:solid 1px #769dc0;
+	background-color:#7dbefa;
+	background-position:0px -177px;
+	padding: 1px;
+}
+.claro .dijitToolbar .dijitComboButtonActive {
+	-webkit-transition-duration:.2s;
+	border: solid 1px #769dc0;
+	padding: 0px;
+}
+.claro .dijitToolbar .dijitComboButtonActive .dijitButtonNode {
+	background-color: #7dbefa;
+	background-position:0px -177px;
+	padding: 2px;
+}
+.claro .dijitToolbar .dijitComboButton .dijitDownArrowButtonActive {
+	background-color: #7dbefa;
+}
+/* toggle button checked status */
+.claro .dijitToolbar .dijitToggleButtonChecked .dijitButtonNode {
+	border-color: #769dc0;
+	background-color:#fff;
+	padding: 1px;
+}
+
+
+/** hacks for browsers **/
+.dj_ie6 .claro .dijitToolbar .dijitButtonContents, 
+.dj_ie7 .claro .dijitToolbar .dijitButtonContents {
+	margin: -2px 0;
+	padding: 0;
+}
+
+.dj_ie6 .claro .dijitToolbar {
+	background-image: none;
+}
+
+.dj_ie6 .claro .dijitToolbar .dijitButtonNode {
+	margin: 1px; /* as transparent the border */
+	border: none;
+}
+
+.dj_ie6 .claro .dijitToolbar .dijitButtonHover .dijitButtonNode,
+.dj_ie6 .claro .dijitToolbar .dijitDropDownButtonHover .dijitButtonNode,
+.dj_ie6 .claro .dijitToolbar .dijitComboButton .dijitButtonNodeHover,
+.dj_ie6 .claro .dijitToolbar .dijitComboButton .dijitDownArrowButtonHover,
+.dj_ie6 .claro .dijitToolbar .dijitToggleButtonHover .dijitButtonNode,
+.dj_ie6 .claro .dijitToolbar .dijitButtonActive .dijitButtonNode,
+.dj_ie6 .claro .dijitToolbar .dijitDropDownButtonActive .dijitButtonNode,
+.dj_ie6 .claro .dijitToolbar .dijitComboButton .dijitButtonNodeActive,
+.dj_ie6 .claro .dijitToolbar .dijitComboButton .dijitDownArrowButtonActive,
+.dj_ie6 .claro .dijitToolbar .dijitToggleButtonActive .dijitButtonNode,
+.claro .dijitToolbar .dijitToggleButtonChecked .dijitButtonNode {
+	margin: 0;	/* remove margin and add a border */
+	border-width: 1px;
+	border-style: solid;
+	background-image: none;
+}
+
+.dj_ie6 .claro .dijitToolbar .dijitComboButton .dijitButtonNodeHover,
+.dj_ie6 .claro .dijitToolbar .dijitComboButton .dijitDownArrowButtonHover,
+.dj_ie6 .claro .dijitToolbar .dijitComboButton .dijitButtonNodeActive,
+.dj_ie6 .claro .dijitToolbar .dijitComboButton .dijitDownArrowButtonActive {
+	padding: 1px;	/* ComboButton use table td has no margin, so we minus padding 2px -> 1px for the 1px border. ie6... */
+}
+
+.claro .dijitToolbarSeparator {
+	/* separator icon in the editor sprite */
+	background: url('../../icons/images/editorIconsEnabled.png');
+}
+
+/* Toolbar inside of disabled Editor */
+.claro .dijitDisabled .dijitToolbar {
+	background:none;
+	background-color:#f5f5f5;
+	border-bottom: 1px solid #d3d3d3;
+}
diff --git a/dijit/themes/claro/Tree.css b/dijit/themes/claro/Tree.css
new file mode 100644
index 0000000..9158c40
--- /dev/null
+++ b/dijit/themes/claro/Tree.css
@@ -0,0 +1,122 @@
+/* Tree 
+ * 
+ * Styling Tree mostly means styling the TreeRow (dijitTreeRow)
+ * There are 4 basic states to style:
+ * 
+ * Tree Row:
+ * 1. tree row (default styling): 
+ * 		.dijitTreeRow - styles for each row of the tree
+ *
+ * 2. hovered tree row (mouse hover on a tree row)
+ * 		.dijitTreeRowHover - styles when mouse over on one row
+ * 
+ * 3. active tree row (mouse down on a tree row)
+ * 		.dijitTreeRowActive - styles when mouse down on one row
+ * 
+ * 4. selected tree row
+ * 		dijitTreeRowSelected - style when the row has been selected
+ * 
+ * Tree Expando:
+ * 	    dijitTreeExpando - the expando at the left of the text of each tree row
+ * 
+ * Drag and Drop on TreeNodes: (insert line on dijitTreeContent node so it'll aligned w/ target element)
+ * 		.dijitTreeNode .dojoDndItemBefore/.dojoDndItemAfter - use border style simulate a separate line
+ */
+
+.claro .dijitTreeNode {
+    zoom: 1;	/* force layout on IE (TODO: may not be needed anymore) */
+}
+.claro .dijitTreeIsRoot {
+    background-image: none;
+}
+.claro .dijitTreeRow {
+	/* so insert line shows up on IE when dropping after a target element */
+	padding: 4px 1px 2px 0px;
+	margin-left: 1px;
+	background-image: url("images/commonHighlight.png");
+	background-position:0px 0px;
+	background-repeat:repeat-x;
+	border-color: rgba(118,157,192,0);
+	background-color: rgba(171,214,255,0);
+	-webkit-transition-property:background-color, border-color;
+	-webkit-transition-duration:.25s ;
+	-webkit-transition-timing-function: ease-out;
+}
+.dj_ie6 .claro .dijitTreeRow {
+	background-image: none;
+}
+
+.claro .dijitTreeRowSelected {
+	background-repeat:repeat-x;
+	background-color:#d8edff;
+	padding: 3px 0px 1px;
+	margin-left: 0px;
+	border:solid 1px #c3e2fd;
+	color:#000;
+}
+.claro .dijitTreeRowHover {
+	background-color:#abd6ff;
+	padding: 3px 0px 1px;
+	margin-left: 0px;
+	border:solid 1px #769dc0;
+	color:#000;
+	-webkit-transition-duration:.25s ; 
+}
+.claro .dijitTreeRowActive {
+	background-color:#7dbefa;
+	background-position:0px -177px;
+	padding: 3px 0px 1px;
+	margin-left: 0px;
+	border:solid 1px #769dc0;
+	color:#000;
+}
+.dj_ie6 .claro .dijitTreeRowActive {
+	background-image: none;
+}
+.claro .dijitTreeRowFocused {
+	background-repeat: repeat;
+}
+
+/* expando (open/closed) icon */
+
+.claro .dijitTreeExpando {
+	background-image: url('images/treeExpandImages.png');
+    width: 16px;
+    height: 16px;
+	background-position: -35px 0px		/* for dijitTreeExpandoOpened */
+}
+.dj_ie6 .claro .dijitTreeExpando {
+	background-image: url('images/treeExpandImages8bit.png');
+}
+.claro .dijitTreeRowHover .dijitTreeExpandoOpened {
+	background-position: -53px 0px;
+}
+.claro .dijitTreeExpandoClosed {
+	background-position: 1px 0px;
+}
+.claro .dijitTreeRowHover .dijitTreeExpandoClosed {
+	background-position: -17px 0px;
+}
+.claro .dijitTreeExpandoLeaf{
+	background-image:none;
+}
+.claro .dijitTreeExpandoLoading {
+	background-image: url('images/loadingAnimation.gif');
+}
+
+/* Drag and Drop on TreeNodes
+ * Put insert line on dijitTreeContent node so it's aligned w/
+ * (ie, indented equally with) target element, even
+ * though dijitTreeRowNode is the actual "drag object"
+ */
+.claro .dijitTreeNode .dojoDndItemBefore,
+.claro .dijitTreeNode .dojoDndItemAfter {
+	border-bottom: none;
+	border-top: none;
+}
+.claro .dijitTreeNode .dojoDndItemBefore .dijitTreeContent {
+	border-top: 2px solid #369;
+}
+.claro .dijitTreeNode .dojoDndItemAfter .dijitTreeContent {
+	border-bottom: 2px solid #369;
+}
diff --git a/dijit/themes/claro/claro.css b/dijit/themes/claro/claro.css
new file mode 100644
index 0000000..f11f380
--- /dev/null
+++ b/dijit/themes/claro/claro.css
@@ -0,0 +1,29 @@
+ at import url("../dijit.css");
+ at import url("document.css");	/* rules on the document itself (rather than widgets), overriding dojo.css */
+ at import url("../../icons/commonIcons.css");/*sprite containing common icons to be used by all themes*/
+ at import url("Common.css");
+ at import url("form/Common.css");
+ at import url("form/Button.css");
+ at import url("form/Checkbox.css");
+ at import url("form/RadioButton.css");
+ at import url("form/Select.css");
+ at import url("layout/TabContainer.css");
+ at import url("Dialog.css");
+ at import url("layout/AccordionContainer.css");
+ at import url("layout/ContentPane.css");
+ at import url("Calendar.css");
+ at import url("Menu.css");
+ at import url("form/Slider.css");
+ at import url("ColorPalette.css");
+ at import url("InlineEditBox.css");
+ at import url("ProgressBar.css");
+ at import url("TimePicker.css");
+ at import url("layout/BorderContainer.css");
+ at import url("Tree.css"); 
+ at import url("Toolbar.css");
+ at import url("Editor.css");/*in order to test button or menu item with icon */
+ at import url("../../icons/editorIcons.css"); /*sprite for editor icons to be used by all themes*/
+ at import url("TitlePane.css");
+ at import url("form/NumberSpinner.css");
+
+ at import url("claro_rtl.css");
diff --git a/dijit/themes/claro/claro_rtl.css b/dijit/themes/claro/claro_rtl.css
new file mode 100644
index 0000000..874f20c
--- /dev/null
+++ b/dijit/themes/claro/claro_rtl.css
@@ -0,0 +1,15 @@
+/* RTL files */
+ at import url("../dijit_rtl.css");
+ at import url("form/Common_rtl.css");
+ at import url("form/Button_rtl.css");
+ at import url("layout/TabContainer_rtl.css");
+ at import url("form/Slider_rtl.css");
+ at import url("form/Select_rtl.css");
+ at import url("Dialog_rtl.css");
+ at import url("Editor_rtl.css");
+ at import url("../../icons/editorIcons_rtl.css");/* RTL sprite for editor icons to be used by all themes*/
+ at import url("../../icons/commonIcons_rtl.css");/* RTL sprite for common icons to be used by all themes*/
+ at import url("TitlePane_rtl.css");
+ at import url("Menu_rtl.css");
+ at import url("Calendar_rtl.css");
+ at import url("TimePicker_rtl.css");
diff --git a/dijit/themes/claro/document.css b/dijit/themes/claro/document.css
new file mode 100644
index 0000000..9a965bb
--- /dev/null
+++ b/dijit/themes/claro/document.css
@@ -0,0 +1,109 @@
+/* ======= Styling for the document itself (overriding dojo.css) ======== */
+
+.claro {
+	font-family:Verdana,Arial,Helvetica,sans-serif;
+	font-size: .688em;
+	color: #131313;
+}
+
+/* Headings */
+h1 {
+	font-size: 1.545em; 
+	font-weight: normal;
+	line-height: 1em; 
+	margin-top: 1em;
+	margin-bottom:0.727em;
+}
+.claro .dijitDialog h1 { 
+	margin-top:0em; 
+
+}
+h2 { 
+	font-size: 1.364em; 
+	line-height: 1.455em; 
+	margin-top:1em; 
+	margin-bottom:0.60em;
+	font-weight: normal;
+}
+
+h3, h4, h5, h6 {
+	font-size:1.091em; 
+	font-weight: normal; 
+	line-height: 1.5em; 
+	margin-top: 1.5em; 
+	margin-bottom: 0;
+}
+
+/* paragraphs, quotes and lists */
+p { 
+	font-size: 1em; 
+	line-height: 1.3em;
+}
+
+blockquote { 
+	font-size: 0.916em; 
+	margin-top: 3.272em; 
+	margin-bottom: 3.272em; 
+	line-height: 1.636em; 
+	padding: 1.636em; 
+	border-top: 1px solid #ccc; 
+	border-bottom: 1px solid #ccc;
+}
+
+ol li, ul li { 
+	font-size: 1em; 
+	line-height: 1.5em; 
+	margin: 0;
+}
+
+/* pre and code */
+pre, code { 
+	font-size:115%;
+	*font-size:100%;
+	font-family:inherit; 
+	background-color: #efefef; 
+	border: 1px solid #ccc;
+}
+
+pre { 
+	border-width: 1px 0; 
+	padding: 1.5em;
+}
+/*
+	Tables
+
+	Note that these table definitions make the assumption that you are using tables
+	to display tabular data, and NOT using tables as layout mechanisms.  If you are
+	using tables for layout, you will probably want to override these rules with
+	more specific ones.
+
+	These definitions make tabular data look presentable, particularly when presented
+	inline with paragraphs.
+*/
+table {  font-size:100%; }
+
+table.dojoTabular { 
+	border-collapse: collapse; 
+	border-spacing: 0; 
+	border: 1px solid #ccc; 
+	margin: 0 1.5em;
+}
+
+.dojoTabular th { 
+	text-align: center; 
+	font-weight: bold;
+}
+
+table.dojoTabular thead, table.dojoTabular tfoot { 
+	background-color: #efefef; 
+	border: 1px solid #ccc; 
+	border-width: 1px 0; 
+}
+
+table.dojoTabular thead tr th,
+table.dojoTabular thead tr td,
+table.dojoTabular tbody tr td,
+table.dojoTabular tfoot tr td { 
+	padding: 0.25em 0.5em;
+}
+
diff --git a/dijit/themes/claro/form/Button.css b/dijit/themes/claro/form/Button.css
new file mode 100644
index 0000000..7edec6b
--- /dev/null
+++ b/dijit/themes/claro/form/Button.css
@@ -0,0 +1,168 @@
+/* Button | DropDownButton | ComboButton | ToggleButton
+ * 
+ * Styling Buttons mainly includes:
+ * 
+ * 1. Containers
+ * 		.dijitButton
+ * 		.dijitDropDownButton
+ * 		.dijitComboButton
+ * 		.dijitButtonNode - common button/arrow wrapper shared across all three button types 
+ *
+ * 2. Button text
+ * 		.dijitButtonText
+ * 
+ * 3. Arrows - only for DropDownButton and ComboButton
+ * 	     There are total four diredtions arrows - down, left, right, up:
+ * 		.dijitArrowButtonInner - down arrow by default
+ *      .dijitLeftArrowButton .dijitArrowButtonInner - left arrow
+ *      .dijitRightArrowButton .dijitArrowButtonInner - right arrow
+ *      .dijitUpArrowButton .dijitArrowButtonInner - up arrow
+ * 
+ * 4. States - Hover, Active, Disabled, e.g.
+ * 		.dijitButtonHover .dijitButtonNode
+ * 		.dijitButtonActive .dijitButtonNode
+ * 		.dijitButtonDisabled .dijitButtonNode
+ *      
+ *      .dijitDisabled .dijitArrowButtonInner  - disabled arrow states 
+ */
+
+.claro .dijitButtonNode {
+	/* rules for dijit.form.*Button widgets and arrow nodes on ComboBox, Spinner etc. */
+	-webkit-transition-property:background-color;
+ 	-webkit-transition-duration:.3s;
+}
+
+.claro .dijitButton .dijitButtonNode,
+.claro .dijitDropDownButton .dijitButtonNode,
+.claro .dijitComboButton .dijitButtonNode,
+.claro .dijitToggleButton .dijitButtonNode {
+	/* rules for the dijit.form.*Button widgets (see also ComboButton section below) */
+	border: 1px solid #769dc0;
+	padding:2px 4px 4px 4px;
+	background-image: url("images/button.png");
+	background-position: center top;
+	background-repeat: repeat-x;
+	background-color: #e4f2ff;
+	border-radius: 4px;
+	-moz-border-radius: 4px;
+	-webkit-border-radius: 4px;
+	box-shadow:0px 1px 1px rgba(0,0,0,0.15);
+	-webkit-box-shadow:0px 1px 1px rgba(0,0,0,0.15);
+	-moz-box-shadow: 0px 1px 1px rgba(0,0,0,0.15);	
+}
+
+.claro .dijitComboButton .dijitArrowButton {
+	border-left-width: 0px;
+	padding: 4px 2px 4px 2px;	/* TODO: still needed? */
+}
+
+/*arrow styles for down/up/left/right directions*/
+.claro .dijitArrowButtonInner {
+	width: 15px;
+	height: 15px;
+	margin: 0 auto;
+	background-image:url("images/buttonArrows.png");
+	background-repeat:no-repeat;
+	background-position:-51px 53%;
+}
+.claro .dijitLeftArrowButton .dijitArrowButtonInner {
+	background-position: -77px 53%;
+}
+.claro .dijitRightArrowButton .dijitArrowButtonInner {
+	background-position: -26px 53%;
+}
+.claro .dijitUpArrowButton .dijitArrowButtonInner {
+	background-position: 0px 53%;
+}
+.claro .dijitDisabled .dijitArrowButtonInner {
+	background-position: -151px 53%;
+}
+.claro .dijitDisabled .dijitLeftArrowButton .dijitArrowButtonInner {
+	background-position: -177px 53%;
+}
+.claro .dijitDisabled .dijitRightArrowButton .dijitArrowButtonInner {
+	background-position: -126px 53%;
+}
+.claro .dijitDisabled .dijitUpArrowButton .dijitArrowButtonInner {
+	background-position: -100px 53%;
+}
+
+.claro .dijitButtonText {
+	padding: 0 0.3em;
+	text-align: center;
+}
+
+.claro .dijitDisabled .dijitButtonText {
+	color: #7F7F7F;
+}
+
+/* hover status */
+.claro .dijitButtonHover .dijitButtonNode,
+.claro .dijitDropDownButtonHover .dijitButtonNode,
+.claro .dijitComboButton .dijitButtonNodeHover, 
+.claro .dijitComboButton .dijitDownArrowButtonHover,
+.claro .dijitToggleButtonHover .dijitButtonNode {
+	background-color: #afd9ff;
+	color:#000;
+ 	-webkit-transition-duration:.2s;
+}
+
+/* checked status */
+.claro .dijitButtonActive .dijitButtonNode, 
+.claro .dijitDropDownButtonActive .dijitButtonNode,
+.claro .dijitComboButtonActive .dijitButtonNode,
+.claro .dijitToggleButtonActive .dijitButtonNode {
+	background-color: #99cfff;
+	box-shadow:0px 0px 0px rgba(0,0,0,0);
+	-webkit-box-shadow:0px 0px 0px rgba(0,0,0,0);
+	-moz-box-shadow: 0px 0px 0px rgba(0,0,0,0);
+ 	-webkit-transition-duration:.1s;
+}
+
+/* disabled status */
+.claro .dijitButtonDisabled,
+.claro .dijitDropDownButtonDisabled,
+.claro .dijitComboButtonDisabled,
+.claro .dijitToggleButtonDisabled {
+	background-image: none;
+	outline: none;
+}
+
+.claro .dijitButtonDisabled .dijitButtonNode,
+.claro .dijitDropDownButtonDisabled .dijitButtonNode,
+.claro .dijitComboButtonDisabled .dijitButtonNode,
+.claro .dijitToggleButtonDisabled .dijitButtonNode { 
+	background-position:0px -149px;
+	background-color: #e3e3e3;
+	border: solid 1px #c9c9c9;
+	color: #696969;
+	box-shadow:0px 0px 0px rgba(0,0,0,0);
+	-webkit-box-shadow:0px 0px 0px rgba(0,0,0,0);
+	-moz-box-shadow: 0px 0px 0px rgba(0,0,0,0);
+}
+.claro .dijitComboButtonDisabled .dijitArrowButton{ 
+	border-left-width: 0px;
+}
+/* for ComboButton */
+.claro table.dijitComboButton {
+	border-collapse: separate;	/* override dijit.css so that ComboBox rounded corners work */
+}
+
+.dj_ie6 .claro .dijitButtonNode {
+	background-image: none;
+}
+
+.claro .dijitComboButton .dijitStretch {
+	-moz-border-radius: 4px 0px 0px 4px;
+	-webkit-border-top-left-radius: 4px;
+	-webkit-border-top-right-radius: 0px;
+	-webkit-border-bottom-right-radius: 0px;
+	-webkit-border-bottom-left-radius: 4px;
+}
+.claro .dijitComboButton .dijitArrowButton {
+	-moz-border-radius: 0px 4px 4px 0px;
+	-webkit-border-top-left-radius: 0px;
+	-webkit-border-top-right-radius: 4px;
+	-webkit-border-bottom-right-radius: 4px;
+	-webkit-border-bottom-left-radius: 0px;
+}
\ No newline at end of file
diff --git a/dijit/themes/claro/form/Button_rtl.css b/dijit/themes/claro/form/Button_rtl.css
new file mode 100644
index 0000000..4cf6915
--- /dev/null
+++ b/dijit/themes/claro/form/Button_rtl.css
@@ -0,0 +1,22 @@
+/* Combo Button */
+
+.claro .dijitComboButtonRtl .dijitStretch {
+	-moz-border-radius: 0px 4px 4px 0px;
+	-webkit-border-top-left-radius: 0px;
+    -webkit-border-top-right-radius: 4px;
+    -webkit-border-bottom-right-radius: 4px;
+    -webkit-border-bottom-left-radius: 0px;	
+}
+
+.claro .dijitComboButtonRtl .dijitArrowButton {
+	-moz-border-radius:  4px 0px 0px  4px;
+	-webkit-border-top-left-radius:4px;
+    -webkit-border-top-right-radius:0px;
+    -webkit-border-bottom-right-radius:0px;
+    -webkit-border-bottom-left-radius:4px;
+	padding:3px 0px 4px;
+	border-left-width: 1px;
+	border-right-width: 0px;
+}
+
+/* End Combo Button */
\ No newline at end of file
diff --git a/dijit/themes/claro/form/Checkbox.css b/dijit/themes/claro/form/Checkbox.css
new file mode 100644
index 0000000..a98f7bc
--- /dev/null
+++ b/dijit/themes/claro/form/Checkbox.css
@@ -0,0 +1,77 @@
+/* CheckBox
+ * 
+ * Styling CheckBox mainly includes:
+ * 
+ * 1. Containers
+ * 		.dijitCheckBox|.dijitCheckBoxIcon - for border, padding, width|height and background image
+ * 
+ * 2. CheckBox within ToggleButton
+ * 		.dijitToggleButton|.dijitToggleButtonChecked .* - for background image
+ * 
+ * 3. Checked state
+ * 		.dijitCheckBoxChecked - for checked background-color|image
+ * 		.dijitToggleButtonChecked - for border, background-color|image, display and width|height
+ * 
+ * 4. Hover state
+ * 		.dijitCheckBoxHover|.dijitCheckBoxCheckedHover - for background image
+ * 
+ * 5. Disabled state
+ * 		.dijitCheckBoxDisabled|.dijitCheckBoxCheckedDisabled - for background image
+ */
+
+.claro .dijitToggleButton .dijitCheckBoxIcon {
+	background-image: url('../images/checkmarkNoBorder.png');
+}
+
+.dj_ie6 .claro .dijitToggleButton .dijitCheckBoxIcon {
+	background-image: url('../images/checkmarkNoBorder.gif');
+}
+
+.claro .dijitCheckBox,
+.claro .dijitCheckBoxIcon		/* inside a toggle button */	{
+	background-image: url('images/checkboxRadioButtonStates.png'); /* checkbox sprite image */
+	background-repeat: no-repeat;
+	width: 15px;
+	height: 16px;
+	margin: 0 2px 0 0;
+	padding: 0;
+}
+
+.dj_ie6 .claro .dijitCheckBox,
+.dj_ie6 .claro .dijitCheckBoxIcon		/* inside a toggle button */	{
+	background-image: url('images/checkboxAndRadioButtons_IE6.png'); /* checkbox sprite image */
+}
+
+.claro .dijitCheckBox,
+.claro .dijitToggleButton .dijitCheckBoxIcon {
+	/* unchecked */
+	background-position: -15px;
+}
+
+.claro .dijitCheckBoxChecked,
+.claro .dijitToggleButtonChecked .dijitCheckBoxIcon {
+	/* checked */
+	background-position: -0px;
+}
+
+.claro .dijitCheckBoxDisabled {
+	/* disabled */
+	background-position: -75px;
+}
+
+.claro .dijitCheckBoxCheckedDisabled {
+	/* disabled but checked */
+	background-position: -60px;
+}
+
+.claro .dijitCheckBoxHover {
+	/* hovering over an unchecked enabled checkbox */
+	background-position: -45px;
+}
+
+.claro .dijitCheckBoxCheckedHover {
+	/* hovering over an checked enabled checkbox */
+	background-position: -30px;
+}
+
+
diff --git a/dijit/themes/claro/form/Common.css b/dijit/themes/claro/form/Common.css
new file mode 100644
index 0000000..4ee207f
--- /dev/null
+++ b/dijit/themes/claro/form/Common.css
@@ -0,0 +1,176 @@
+/* claro/form/Common.css */
+
+/*========================= common css =========================*/
+
+/* 'dijitTextBox' refers to 'dijit(TextBox|DateTextBox|CurrencyTextBox|...)' */
+
+.claro .dijitTextBoxError .dijitValidationContainer {
+	background-color: #d46363;
+	background-image: url('images/error.png');
+	background-position: top center;
+	border: solid #d46464 0px;
+	border-left-width: 1px;
+	width: 9px;
+}
+.claro .dijitTextBoxError .dijitValidationIcon {
+	width: 0px;
+	background-color: transparent !important; /* so the INPUT doesn't obscure the border in rtl+a11y */
+}
+
+/* .dijitInputField .dijitPlaceHolder is explicitly listed below because
+   dijitPlaceHolder is absolutely positioned, so padding set on dijitInputField
+   won't affect it */
+.claro .dijitTextBox .dijitInputContainer,
+.claro .dijitTextArea,
+.claro .dijitInputField .dijitPlaceHolder {
+	padding: 2px;
+}
+
+.claro .dijitTextBox,
+.claro .dijitTextBox .dijitButtonNode {
+	/* color for (outer) border on *TextBox widgets, and border between input and buttons on ComboBox and Spinner */
+	border-color: #b5bcc7;
+	-webkit-transition-property:background-color, border;
+ 	-webkit-transition-duration:.35s;
+}
+.claro .dijitTextBox {
+	background-color: #f7fcff;
+}
+
+/* hover */
+.claro .dijitTextBoxHover,
+.claro .dijitTextBoxHover .dijitButtonNode {
+	border-color: #769dc0;
+ 	-webkit-transition-duration:.25s;
+}
+.claro .dijitTextBoxHover {
+	background-color: #e9f4fe;
+	background-image: url('images/textBox_back.png');
+	background-repeat: repeat-x;
+}
+
+/* error state */
+.claro .dijitTextBoxError,
+.claro .dijitTextBoxError .dijitButtonNode {
+	border-color: #d46464;
+}
+.claro .dijitTextBoxError,
+.claro .dijitTextBoxError .dijitInputContainer {
+	background-color: #fdf7f7;
+}
+
+/* focused state */
+.claro .dijitTextBoxFocused,
+.claro .dijitTextBoxFocused .dijitButtonNode {
+	border-color:#769dc0;
+ 	-webkit-transition-duration:.1s;
+}
+.claro .dijitTextBoxFocused {
+	background-color: #fff;
+	background-image: url('images/textBox_back.png');
+	background-repeat: repeat-x;
+}
+.claro .dijitTextBoxFocused .dijitInputContainer {
+	background: #fff;
+}
+
+.claro .dijitTextBoxErrorFocused,
+.claro .dijitTextBoxErrorFocused .dijitButtonNode {
+	border-color: #ce4f4f;
+}
+
+/* disabled state */
+.claro .dijitTextBoxDisabled,
+.claro .dijitTextBoxDisabled .dijitButtonNode {
+	border-color: #d3d3d3;
+}
+.claro .dijitTextBoxDisabled {
+	background-color: #efefef;
+	background-image: none;
+	color: #818181;
+}
+
+/*========================= for special widgets =========================*/
+
+/* ComboBox */
+
+.claro .dijitComboBox .dijitArrowButtonInner {
+	background-image: url("images/commonFormArrows.png");
+	background-position:-35px 53%;
+	background-repeat: no-repeat;
+	margin: 0px;
+	width:16px;
+	height:100%;
+	border: 1px solid #fff;
+}
+
+.claro .dijitTextBox .dijitInputField {
+	padding-top: 1px; /* 1px and not 2px due to 1px padding on the INPUT */
+	padding-bottom: 1px;
+}
+.claro .dijitTextBox .dijitInputInner {
+	/* left padding helps line up input text with menu text */
+	padding: 1px 2px 1px 0; /* match 1px vertical border on button */
+}
+.claro .dijitTextBox .dijitValidationContainer {
+	padding: 0 0 2px 0; /* match 1px border height in button */
+}
+
+.claro .dijitComboBox .dijitButtonNode {
+	background-color: #ebeef4;
+	background-image: url("images/formHighlight.png");
+	background-repeat:repeat-x;
+}
+
+/* hover state */
+.claro .dijitComboBoxHover .dijitButtonNode {
+	background-color:#abd6ff;
+}
+.claro .dijitComboBoxHover .dijitArrowButtonInner {
+	background-position:-70px 53%;
+}
+
+/* focused state */
+.claro .dijitComboBoxFocused .dijitButtonNode {
+	background-color:#7dbefa;
+	background-position:0px -177px;
+	padding: 1px;
+}	
+.claro .dijitComboBoxFocused .dijitArrowButtonInner {
+	background-position:-70px 53%;
+	border: 0px none;
+}
+
+/* disabled state */
+.claro div.dijitComboBoxDisabled .dijitArrowButtonInner {
+	/* specific selector set to override background-position setting from Button.js
+	 * (.claro .dijitComboBoxDisabled .dijitArrowButtonInner) */
+	background-position:0px 50%;
+	background-color:#f1f1f1;
+}
+
+/*========================= hacks for browsers =========================*/
+/* it seems the input[type="hidden"] has a height (16px) too... this may cause the widget's height calcuate error */
+.dj_ff3 .claro .dijitInputField input[type="hidden"] {
+	display: none;
+	height: 0;
+	width: 0;
+}
+
+/* ie6 doesn't support transparent background img */
+.dj_ie6 .claro .dijitTextBox,
+.dj_ie6 .claro .dijitComboBox .dijitButtonNode {
+	background-image: none;
+}
+
+
+/* In quirks mode strangely all browsers do border-box sizing for input nodes.
+ * Drop the 1px white border around ComboBox arrow to fix misalignment of icon, and to jump on focus.
+ * Note also that these rules are copying what is done on focus.
+ */
+.dj_quirks .claro .dijitComboBox .dijitArrowButtonInner {
+	border: 0px;
+}
+.dj_quirks .claro .dijitComboBox .dijitArrowButtonContainer {
+	padding: 1px;
+}
diff --git a/dijit/themes/claro/form/Common_rtl.css b/dijit/themes/claro/form/Common_rtl.css
new file mode 100644
index 0000000..1e21dec
--- /dev/null
+++ b/dijit/themes/claro/form/Common_rtl.css
@@ -0,0 +1,10 @@
+/* claro/form/Common_rtl.css */
+/*claro should not have the icon on the container
+.claro .dijitTextBoxRtlError .dijitValidationIcon {
+	border-left-width: 0px;
+	border-right-width: 1px;
+}*/
+.claro .dijitTextBoxRtlError .dijitValidationContainer {
+	border-left-width: 0px;
+	border-right-width: 1px;
+}
diff --git a/dijit/themes/claro/form/NumberSpinner.css b/dijit/themes/claro/form/NumberSpinner.css
new file mode 100644
index 0000000..1009ee0
--- /dev/null
+++ b/dijit/themes/claro/form/NumberSpinner.css
@@ -0,0 +1,143 @@
+/* NumberSpinner - namespace "dijitSpinner"
+ * 
+ * Styling NumberSpinner mainly includes:
+ * 
+ * 1. Arrows
+ * 		Outer containers: .dijitSpinnerButtonContainer|.dijitSpinnerButtonInner  - for border, padding and position
+ * 		Arrows: .dijitArrowButton|.dijitUpArrowButton.|dijitDownArrowButton
+ * 		Inner container: .dijitArrowButtonInner - for border, padding, width|height and background image
+ * 
+ * 2. Hover state
+ * 		.dijitUpArrowButtonHover|.dijitDownArrowButtonHover .*  - for background color|image
+ * 
+ * 3. Active state
+ * 		.dijitUpArrowButtonActive|.dijitDownArrowButtonActive .*  - for border, padding, margin and background color|image
+ * 
+ * 4. Focused state
+ * 		.dijitSpinnerFocused .* - for background color|image
+ * 
+ * 5. Disabled state
+ * 		.dijitSpinnerDisabled .* - for background color|image
+ */
+
+.claro .dijitSpinnerButtonContainer {
+	overflow: hidden;
+	position: relative;
+	width: auto;
+	padding: 0 2px;
+}
+.claro .dijitSpinnerButtonContainer .dijitSpinnerButtonInner {
+	border-width: 1px 0; /* reserve space to match the claro combobox button border with border and not padding to make IE happier */
+	border-style: solid none;
+}
+
+/* button */
+.claro .dijitSpinner .dijitArrowButton {
+	width:auto;
+	background-color: #ebeef4;
+	background-image: url("images/formHighlight.png");
+	background-position:0px 0px;
+	background-repeat:repeat-x;
+	overflow: hidden;
+}
+.dj_iequirks .claro .dijitSpinner .dijitArrowButton {
+	overflow: visible; /* 0 height w/o this */
+}
+
+.claro .dijitSpinner .dijitSpinnerButtonInner {
+	width: 15px;
+}
+/* up & down button icons */
+.claro .dijitSpinner .dijitArrowButtonInner {
+	border:solid 1px #fff;
+	border-bottom-width: 0; /* 2 top borders = 1 top+bottom border in ComboBox */
+	background-image: url("images/commonFormArrows.png");
+	background-repeat: no-repeat;
+	height: 100%;
+	width:15px;
+	padding-left: 1px;
+	padding-right: 1px;
+
+	/* for up arrow */
+	background-position:-139px center;
+
+	/* override button.css (TODO: move to Common.css since ComboBox needs this too) */
+	display: block;
+	margin: -1px 0px -1px 0px;	/* compensate for inner border */
+	#margin-top: 0; /* since its bottom aligned */
+}
+.dj_iequirks .claro .dijitSpinner .dijitArrowButtonInner {
+	width: 19px;
+}
+.claro .dijitSpinner .dijitDownArrowButton .dijitArrowButtonInner {
+	background-position:-34px;
+}
+.claro .dijitSpinner .dijitArrowButtonInner .dijitInputField {
+	padding: 0;
+}
+
+/** hover & focused status **/
+
+.claro .dijitUpArrowButtonActive,
+.claro .dijitDownArrowButtonActive {
+	background-color:#abd6ff;
+}
+
+.claro .dijitSpinner .dijitUpArrowButtonHover,
+.claro .dijitSpinner .dijitDownArrowButtonHover,
+.claro .dijitSpinnerFocused .dijitArrowButton {
+	background-color: #a0d1ff;
+}
+
+.claro .dijitSpinner .dijitUpArrowButtonHover .dijitArrowButtonInner {
+	background-position:-174px;
+}
+.claro .dijitSpinner .dijitDownArrowButtonHover .dijitArrowButtonInner {
+	background-position:-69px;
+}
+
+.claro .dijitSpinnerFocused {
+	background-color: #fff;
+	background-image: none;
+}
+
+/* mouse down status */
+.claro .dijitSpinner .dijitDownArrowButtonActive,
+.claro .dijitSpinner .dijitUpArrowButtonActive {
+	background-color: #3299f9;
+	background-position:0px -177px;
+}
+.claro .dijitSpinner .dijitUpArrowButtonActive .dijitArrowButtonInner,
+.claro .dijitSpinner .dijitDownArrowButtonActive .dijitArrowButtonInner {
+	/* hide inner border while button is depressed */
+	border: 0px;
+	padding: 1px;
+	margin-right:2px;
+	margin-bottom:1px;
+}
+.claro .dijitSpinner .dijitUpArrowButtonActive .dijitArrowButtonInner {
+	background-position:-173px;
+}
+.claro .dijitSpinner .dijitDownArrowButtonActive .dijitArrowButtonInner {
+	background-position:-68px;
+}
+
+/* disabled */
+
+.claro .dijitSpinnerDisabled .dijitArrowButtonInner {
+	background-color: #f1f1f1;
+}
+.claro .dijitSpinnerDisabled .dijitUpArrowButton .dijitArrowButtonInner {
+	background-position:-104px;
+}
+.claro .dijitSpinnerDisabled .dijitDownArrowButton .dijitArrowButtonInner {
+	background-position:1px;
+}
+
+/** hacks for browsers **/
+
+/* for IE 7, when div is enlarged, 
+ * should be no empty space between dijitInputLayoutContainer and dijitSpinner*/
+.dj_ie7 .claro .dijitSpinner {
+	overflow:visible;
+} 
\ No newline at end of file
diff --git a/dijit/themes/claro/form/RadioButton.css b/dijit/themes/claro/form/RadioButton.css
new file mode 100644
index 0000000..382386d
--- /dev/null
+++ b/dijit/themes/claro/form/RadioButton.css
@@ -0,0 +1,82 @@
+/* RadioButton
+ * 
+ * Styling RadioButton mainly includes:
+ * 
+ * 1. Containers
+ * 		.dijitRadio|.dijitRadioIcon - for border, padding, width|height and background image
+ * 
+ * 2. RadioButton within ToggleButton
+ * 		.dijitToggleButton|.dijitToggleButtonChecked .* - for background image
+ * 
+ * 3. Checked state
+ * 		.dijitRadioChecked - for checked background-color|image
+ * 		.dijitToggleButtonChecked - for border, background-color|image, display and width|height
+ * 
+ * 4. Hover state
+ * 		.dijitRadioHover|.dijitRadioCheckedHover - for background image
+ * 
+ * 5. Disabled state
+ * 		.dijitRadioDisabled|.dijitRadioCheckedDisabled - for background image
+ */
+
+.claro .dijitToggleButton .dijitRadio,
+.claro .dijitToggleButton .dijitRadioIcon {
+	background-image: url('images/checkboxRadioButtonStates.png');
+}
+
+.dj_ie6 .claro .dijitToggleButton .dijitRadio,
+.dj_ie6 .claro .dijitToggleButton .dijitRadioIcon {
+	background-image: url('images/checkboxAndRadioButtons_IE6.png');
+}
+
+.claro .dijitRadio,
+.claro .dijitRadioIcon	{		/* inside a toggle button */
+	background-image: url('images/checkboxRadioButtonStates.png'); /* checkbox sprite image */
+	background-repeat: no-repeat;
+	width: 15px;
+	height: 15px;
+	margin: 0px 2px 0px 0px;
+	padding: 0px;
+}
+
+.dj_ie6 .claro .dijitRadio,
+.dj_ie6 .claro .dijitRadioIcon	{		/* inside a toggle button */
+	background-image: url('images/checkboxAndRadioButtons_IE6.png'); /* checkbox sprite image */
+}
+
+.claro .dijitRadio{
+	/* unselected */
+	background-position: -105px;
+}
+
+.claro .dijitToggleButton .dijitRadioIcon {
+	/* unselected */
+	background-position: -107px;
+}
+
+.claro .dijitRadioDisabled {
+	/* unselected and disabled */
+	background-position: -165px;
+}
+
+.claro .dijitRadioHover {
+	/* hovering over an unselected enabled radio button */
+	background-position: -135px;
+}
+
+.claro .dijitRadioChecked{
+	background-position: -90px;
+}
+
+.claro .dijitToggleButtonChecked .dijitRadioIcon {
+	background-position: -92px;
+}
+
+.claro .dijitRadioCheckedHover{
+	background-position: -120px;
+}
+
+.claro .dijitRadioCheckedDisabled {
+	/* selected but disabled */
+	background-position: -150px;
+}
diff --git a/dijit/themes/claro/form/Select.css b/dijit/themes/claro/form/Select.css
new file mode 100644
index 0000000..5f4f019
--- /dev/null
+++ b/dijit/themes/claro/form/Select.css
@@ -0,0 +1,124 @@
+/* Select
+ * 
+ * Styling Select mainly includes:
+ * 
+ * 1. Containers
+ * 		.dijitSelect - for border, background-color
+ * 		.dijitButtonContents - for border
+ *
+ * 2. Arrow
+ * 		.dijitArrowButton - for border, padding and background-color|image
+ * 		.dijitArrowButtonInner - for border, background-color|image, display and width|height
+ * 
+ * 3. Menu
+ * 		.dijitSelectMenu .* - for border, padding
+ * 
+ * 4. Various states
+ * 		.dijitSelectHover|.dijitSelectFocused|.dijitSelectDisabled .* - for border, padding and background-color|image 
+ */
+
+.claro .dijitSelect .dijitButtonText {
+	padding: 0px 5px 2px 5px;
+}
+
+/* normal status */
+.claro .dijitSelect {
+	border: 1px solid #b5bcc7;
+	background-color: #f7fcff;
+	border-collapse: separate;
+}
+.dj_ie6 .claro .dijitSelect,
+.dj_ie6 .claro .dijitSelect .dijitButtonNode {
+	background-image:none;
+}
+
+.claro .dijitSelect .dijitButtonContents {
+	border: 0px solid #b5bcc7;
+	border-right-width: 1px;
+}
+
+.claro .dijitSelect .dijitArrowButton {
+	padding: 0;
+	border: 1px solid #fff;	/* inner white border on button node */
+	border-top:none;
+	background-color:#ebeef4;
+	background-image: url("images/formHighlight.png");
+	background-repeat:repeat-x;
+}
+
+.claro .dijitSelect .dijitArrowButton .dijitArrowButtonInner {
+	background-image: url("images/commonFormArrows.png");
+	background-position:-35px 70%;
+	background-repeat: no-repeat;
+	width:16px;
+	height:16px;
+	display:block;
+}
+
+/* hover status */
+.claro .dijitSelectHover {
+	border: 1px solid #769dc0;
+	background-color: #e9f4fe;
+	background-image: url('images/textBox_back.png');
+	background-repeat: repeat-x;
+}
+
+.claro .dijitSelectHover .dijitButtonContents {
+	border-color:#81a5c6;
+}
+
+.claro .dijitSelectHover .dijitArrowButton {
+	background-color:#abd6ff;
+}
+.claro .dijitSelectHover .dijitArrowButton .dijitArrowButtonInner {
+	background-position:-70px 70%;
+}
+
+/* focused status */
+.claro .dijitSelectFocused {
+	border: 1px solid #769dc0;
+}
+.claro .dijitSelectFocused .dijitButtonContents {
+	border-color:#81a5c6;
+}
+.claro .dijitSelectFocused .dijitArrowButton {
+	background-color:#7dbefa;
+	background-position:0px -177px;
+	border: none;
+	padding: 0px 1px;
+}
+.claro .dijitSelectFocused .dijitArrowButton .dijitArrowButtonInner {
+	background-position:-70px 70%;
+	margin-bottom: 1px;
+}
+
+/* disable status */
+.claro .dijitSelectDisabled {
+	border: 1px solid #d3d3d3;
+	background-color: #efefef;
+	background-image: none;
+	color: #818181;
+}
+.claro .dijitSelectDisabled .dijitArrowButton { 
+	background-color: #efefef;
+}
+.claro .dijitSelectDisabled .dijitArrowButton .dijitArrowButtonInner {
+	background-position:0px 70%
+}
+
+/* Dropdown menu style for select */
+
+.claro .dijitSelectMenu td.dijitMenuItemIconCell,
+.claro .dijitSelectMenu td.dijitMenuArrowCell { 
+	/* so that arrow and icon cells from MenuItem are not displayed */
+	display: none;  
+}
+.claro .dijitSelectMenu td.dijitMenuItemLabel {
+	/* line up menu text with text in select box (in LTR and RTL modes) */
+	padding-left: 5px;
+	padding-right: 5px;
+}
+
+.claro .dijitSelectMenu .dijitMenuSeparatorTop {
+	border-bottom:1px solid #769dc0;
+}
diff --git a/dijit/themes/claro/form/Select_rtl.css b/dijit/themes/claro/form/Select_rtl.css
new file mode 100644
index 0000000..4379750
--- /dev/null
+++ b/dijit/themes/claro/form/Select_rtl.css
@@ -0,0 +1,4 @@
+.claro .dijitSelectRtl .dijitButtonContents {
+	border-right-width: 0px;
+	border-left-width: 1px;
+}
diff --git a/dijit/themes/claro/form/Slider.css b/dijit/themes/claro/form/Slider.css
new file mode 100644
index 0000000..3c109f1
--- /dev/null
+++ b/dijit/themes/claro/form/Slider.css
@@ -0,0 +1,359 @@
+/* Slider 
+ * 
+ * Styling Slider mainly includes styling the Slider progress bar (dijitSliderProgressBar)
+ * 
+ * Slider progress bar:
+ * 1. Slider progress bar (default styling): 
+ * 		.dijitSliderProgressBarH - progress bar at the middle of horizontal slider
+ * 		.dijitSliderLeftBumper - bar at the left of horizontal slider
+ * 		.dijitSliderRightBumper - bar at the right of horizontal slider
+ * 		.dijitSliderProgressBarV - progress bar at the middle of vertical slider
+ * 		.dijitSliderTopBumper - bar at the top of vertical slider
+ * 		.dijitSliderBottomtBumper - bar at the bottom of vertical slider
+ * 
+ * 2. hovered Slider progress bar (ie, mouse hover on progress bar)
+ * 		.dijitSliderHover .dijitSliderProgressBarH(horizontal) - hovered bar style: background, border
+ * 
+ * 3. focused Slider progress bar (ie, mouse focused on progress bar)
+ * 		.dijitSliderFocused .dijitSliderProgressBarH(horizontal) - focus bar style: background, border
+ * 
+ * 4. disabled/read-only Slider progress bar 
+ * 		.dijitSliderDisabled .dijitSliderProgressBarH(horizontal) - bar styles when slider is disabled
+ * 
+ * 
+ * Slider Thumbs:
+ * 1. Slider Thumbs (default styling): 
+ * 		.dijitSliderImageHandleH / .dijitSliderImageHandleV - styles for the controller on the progress bar
+ * 
+ * 2. hovered Slider Thumbs (ie, mouse hover on slider thumbs)
+ * 		.dijitSliderHover .dijitSliderImageHandleH - hovered controller style
+ * 
+ * 3. focused Slider progress bar (ie, mouse focused on slider thumbs)
+ * 		.dijitSliderFocused .dijitSliderImageHandleV - focused controller style
+ * 
+ * 
+ * Slider Increment/Decrement Buttons:
+ * 1. Slider Increment/Decrement Buttons (default styling): 
+ * 		.dijitSliderDecrementIconH - decrement icon which lies at the left of horizontal slider
+ * 		.dijitSliderIncrementIconH - increment icon which lies at the right of horizontal slider
+ * 		.dijitSliderDecrementIconV - decrement icon which lies at the bottom of vertical slider
+ * 		.dijitSliderIncrementIconV - increment icon which lies at the top of vertical slider
+ * 
+ * 2. hovered Slider Increment/Decrement Buttons (mouse hover on the icons)
+ * 		.dijitSliderHover .dijitSliderDecrementIconH - for background, border
+ * 
+ * 3. active Slider Increment/Decrement Buttons (mouse down on the icons)
+ * 		.dijitSliderActive .dijitSliderIncrementIconV - for background, border
+ * 
+ * 4. disabled/read-only Slider Increment/Decrement Buttons
+ * 		.dijitSliderDisabled .dijitSliderDecrementIconH - styles for the icons in disabled slider
+ * 		.dijitSliderReadOnly .dijitSliderIncrementIconV - styles for the icons in read-only slider
+ */
+
+.claro .dijitSliderBar {
+	border-style: solid;
+	outline: 1px;
+}
+.claro .dijitSliderFocused .dijitSliderBar {
+	border-color: #769dc0;
+}
+.claro .dijitSliderHover .dijitSliderBar {
+	border-color: #769dc0;
+}
+.claro .dijitSliderDisabled .dijitSliderBar {
+	background-image: none;
+	border-color: #d3d3d3;
+}
+
+/* Horizontal Slider */
+
+.claro .dijitRuleLabelsContainerH {
+	padding: 2px 0px;
+}
+.claro .dijitSlider .dijitSliderProgressBarH,
+.claro .dijitSlider .dijitSliderLeftBumper{
+	background-image: url("images/sliderHorizontal.png");
+	background-repeat:repeat-x;
+	background-position:0 -20px;
+	border-color: #b5bcc7;
+	background-color: #cfe5fa;
+}
+.claro .dijitSlider .dijitSliderRemainingBarH,
+.claro .dijitSlider .dijitSliderRightBumper{
+	background-image: url("images/sliderHorizontal.png");
+	background-repeat:repeat-x;
+	background-position:0 -11px;
+	border-color: #b5bcc7;
+	background-color: #fff;
+}
+.claro .dijitSliderRightBumper {
+	border-right: solid 1px #b5bcc7;
+}
+.claro .dijitSliderLeftBumper {
+	border-left: solid 1px #b5bcc7;
+}
+.claro .dijitSliderHover .dijitSliderProgressBarH,
+.claro .dijitSliderHover .dijitSliderLeftBumper{
+	background-position:0 -20px;
+	background-color: #abd6ff;
+	border-color: #769dc0;
+}
+.claro .dijitSliderHover .dijitSliderRemainingBarH,
+.claro .dijitSliderHover .dijitSliderRightBumper{
+	background-position:0 0px;
+	background-color: #fff;
+	border-color: #769dc0;
+}
+.claro .dijitSliderFocused .dijitSliderProgressBarH,
+.claro .dijitSliderFocused .dijitSliderLeftBumper{
+	background-position:0 -30px;
+	background-color: #abd6ff;
+	border-color: #769dc0;
+}
+.claro .dijitSliderFocused .dijitSliderRemainingBarH,
+.claro .dijitSliderFocused .dijitSliderRightBumper{
+	background-position:0 -9px;
+	background-color: #fff;
+	border-color: #769dc0;
+}
+.claro .dijitSliderDisabled .dijitSliderProgressBarH,
+.claro .dijitSliderDisabled .dijitSliderLeftBumper{
+	background-color: #cdcdcd;
+	background-image:none;
+}
+.claro .dijitSliderDisabled .dijitSliderRemainingBarH,
+.claro .dijitSliderDisabled .dijitSliderRightBumper{
+	background-color: #efefef;
+}
+
+/* Vertical Slider */
+
+.claro .dijitRuleLabelsContainerV {
+	padding: 0px 2px;
+}
+.claro .dijitSlider .dijitSliderProgressBarV,
+.claro .dijitSlider .dijitSliderBottomBumper{
+	background-image: url("images/sliderVertical.png");
+	background-repeat:repeat-y;
+	background-position:-36px 0;
+	border-color: #b5bcc7;
+	background-color: #cfe5fa;
+}
+.claro .dijitSlider .dijitSliderRemainingBarV,
+.claro .dijitSlider .dijitSliderTopBumper{
+	background-image: url("images/sliderVertical.png");
+	background-repeat:repeat-y;
+	background-position:-3px 0;
+	border-color: #b5bcc7;
+	background-color: #fff;
+}
+.claro .dijitSliderBottomBumper {
+	border-bottom: solid 1px #b5bcc7;
+}
+.claro .dijitSliderTopBumper {
+	border-top: solid 1px #b5bcc7;
+}
+.claro .dijitSliderHover .dijitSliderProgressBarV,
+.claro .dijitSliderHover .dijitSliderBottomBumper{
+	background-position:-36px 0;
+	background-color: #abd6ff;
+}
+.claro .dijitSliderHover .dijitSliderRemainingBarV,
+.claro .dijitSliderHover .dijitSliderTopBumper{
+	background-position:0 0;
+	background-color: #fff;
+}
+.claro .dijitSliderFocused .dijitSliderProgressBarV,
+.claro .dijitSliderFocused .dijitSliderBottomBumper{
+	background-position:-56px 0;
+	background-color: #abd6ff;
+}
+.claro .dijitSliderFocused .dijitSliderRemainingBarV,
+.claro .dijitSliderFocused .dijitSliderTopBumper{
+	background-position:-18px 0;
+	background-color: #fff;
+}
+.claro .dijitSliderDisabled .dijitSliderProgressBarV,
+.claro .dijitSliderDisabled .dijitSliderBottomBumper{
+	background-color: #cdcdcd;
+}
+.claro .dijitSliderDisabled .dijitSliderRemainingBarV,
+.claro .dijitSliderDisabled .dijitSliderTopBumper{
+	background-color: #efefef;
+}
+
+
+/* ------- Thumbs ------- */
+
+.claro .dijitSliderImageHandleH {
+	border: 0px;
+	width: 18px;
+	height: 16px;
+	background-image: url("images/sliderThumbs.png");
+	background-repeat:no-repeat;
+	background-position:0 0;
+}
+.claro .dijitSliderHover .dijitSliderImageHandleH {
+	background-position:-18px 0;
+}
+.claro .dijitSliderFocused .dijitSliderImageHandleH {
+	background-position:-36px 0;
+}
+.claro .dijitSliderProgressBarH .dijitSliderThumbHover{
+	background-position:-36px 0;
+}
+.claro .dijitSliderProgressBarH .dijitSliderThumbActive{
+	background-position:-36px 0;
+}
+.claro .dijitSliderReadOnly .dijitSliderImageHandleH,
+.claro .dijitSliderDisabled .dijitSliderImageHandleH {
+	background-position:-54px 0;
+}
+.claro .dijitSliderImageHandleV {
+	border: 0px;
+	width: 18px;
+	height: 16px;
+	background-image: url("images/sliderThumbs.png");
+	background-repeat:no-repeat;
+	background-position:-289px 0;
+}
+.claro .dijitSliderHover .dijitSliderImageHandleV {
+	background-position:-307px 0;
+}
+.claro .dijitSliderFocused .dijitSliderImageHandleV {
+	background-position:-325px 0;
+}
+.claro .dijitSliderProgressBarV .dijitSliderThumbHover{
+	background-position:-325px 0;
+}
+.claro .dijitSliderProgressBarV .dijitSliderThumbActive{
+	background-position:-325px 0;
+}
+.claro .dijitSliderReadOnly .dijitSliderImageHandleV,
+.claro .dijitSliderDisabled .dijitSliderImageHandleV {
+	background-position:-343px 0;
+}
+
+/* ---- Increment/Decrement Buttons ---- */
+
+.claro .dijitSliderButtonContainerH{
+	padding: 1px 3px 1px 2px;
+}
+.claro .dijitSliderButtonContainerV{
+	padding: 3px 1px 2px 1px;
+}
+.claro .dijitSliderDecrementIconH,
+.claro .dijitSliderIncrementIconH,
+.claro .dijitSliderDecrementIconV,
+.claro .dijitSliderIncrementIconV {
+	background-image: url('images/commonFormArrows.png');
+	background-repeat:no-repeat;
+	background-color: #e9ecf2;
+	-moz-border-radius: 2px;
+	-webkit-border-radius: 2px;
+	border: solid 1px #b5bcc7;
+	font-size: 1px;
+}
+.claro .dijitSliderDecrementIconH,
+.claro .dijitSliderIncrementIconH {
+	height: 12px;
+	width: 9px;
+}
+.claro .dijitSliderDecrementIconV,
+.claro .dijitSliderIncrementIconV {
+	height: 9px;
+	width: 12px;
+}
+.claro .dijitSliderActive .dijitSliderDecrementIconH,
+.claro .dijitSliderActive .dijitSliderIncrementIconH,
+.claro .dijitSliderActive .dijitSliderDecrementIconV,
+.claro .dijitSliderActive .dijitSliderIncrementIconV,
+.claro .dijitSliderHover .dijitSliderDecrementIconH,
+.claro .dijitSliderHover .dijitSliderIncrementIconH,
+.claro .dijitSliderHover .dijitSliderDecrementIconV,
+.claro .dijitSliderHover .dijitSliderIncrementIconV {
+	border: solid 1px #769dc0;
+	background-color:#fff;
+}
+.claro .dijitSliderDecrementIconH {
+	background-position:-357px 50%;
+}
+.claro .dijitSliderActive .dijitSliderDecrementIconH
+.claro .dijitSliderHover .dijitSliderDecrementIconH {
+	background-position:-393px 50%;
+}
+.claro .dijitSliderIncrementIconH {
+	background-position:-251px 50%;
+}
+.claro .dijitSliderActive .dijitSliderIncrementIconH
+.claro .dijitSliderHover .dijitSliderIncrementIconH {
+	background-position:-283px 50%;
+}
+.claro .dijitSliderDecrementIconV {
+	background-position:-38px 50%;
+}
+.claro .dijitSliderActive .dijitSliderDecrementIconV
+.claro .dijitSliderHover .dijitSliderDecrementIconV {
+	background-position:-73px 50%;
+}
+.claro .dijitSliderIncrementIconV {
+	background-position:-143px 49%;
+}
+.claro .dijitSliderActive .dijitSliderIncrementIconV
+.claro .dijitSliderHover .dijitSliderIncrementIconV {
+	background-position:-178px 49%;
+}
+.claro .dijitSliderButtonContainerV .dijitSliderDecrementButtonHover,
+.claro .dijitSliderButtonContainerH .dijitSliderDecrementButtonHover,
+.claro .dijitSliderButtonContainerV .dijitSliderIncrementButtonHover,
+.claro .dijitSliderButtonContainerH .dijitSliderIncrementButtonHover {
+	background-color: #cce3fc;
+}
+.claro .dijitSliderButtonContainerV .dijitSliderDecrementButtonActive,
+.claro .dijitSliderButtonContainerH .dijitSliderDecrementButtonActive,
+.claro .dijitSliderButtonContainerV .dijitSliderIncrementButtonActive,
+.claro .dijitSliderButtonContainerH .dijitSliderIncrementButtonActive {
+	background-color: #a5d0fc;
+	border-color:#6591b9;
+}
+.claro .dijitSliderButtonInner {
+	visibility: hidden;
+}
+.claro .dijitSliderDisabled .dijitSliderBar{
+	border-color: #d3d3d3;
+}
+.claro .dijitSliderReadOnly *,.claro .dijitSliderDisabled * {
+	border-color: #d3d3d3;
+	color: #bdbdbd;
+}
+.claro .dijitSliderReadOnly .dijitSliderDecrementIconH,
+.claro .dijitSliderDisabled .dijitSliderDecrementIconH {
+	background-position:-321px 50%;
+	background-color:#e9e9e9;
+}
+.claro .dijitSliderReadOnly .dijitSliderIncrementIconH,
+.claro .dijitSliderDisabled .dijitSliderIncrementIconH {
+	background-position:-215px 50%;
+	background-color:#e9e9e9;
+}
+.claro .dijitSliderReadOnly .dijitSliderDecrementIconV,
+.claro .dijitSliderDisabled .dijitSliderDecrementIconV {
+	background-position:-3px 49%;
+	background-color:#e9e9e9;
+}
+.claro .dijitSliderReadOnly .dijitSliderIncrementIconV,
+.claro .dijitSliderDisabled .dijitSliderIncrementIconV {
+	background-position:-107px 49%;
+	background-color:#e9e9e9;
+}
+
+.dj_ie6 .claro .dijitSlider .dijitSliderProgressBarH,
+.dj_ie6 .claro .dijitSlider .dijitSliderLeftBumper,
+.dj_ie6 .claro .dijitSlider .dijitSliderRemainingBarH,
+.dj_ie6 .claro .dijitSlider .dijitSliderRightBumper,
+.dj_ie6 .claro .dijitSlider .dijitSliderProgressBarV,
+.dj_ie6 .claro .dijitSlider .dijitSliderTopBumper,
+.dj_ie6 .claro .dijitSlider .dijitSliderRemainingBarV,
+.dj_ie6 .claro .dijitSlider .dijitSliderBottomBumper {
+	background-image:none;
+}
diff --git a/dijit/themes/claro/form/Slider_rtl.css b/dijit/themes/claro/form/Slider_rtl.css
new file mode 100644
index 0000000..6df7d4f
--- /dev/null
+++ b/dijit/themes/claro/form/Slider_rtl.css
@@ -0,0 +1,31 @@
+.claro .dijitSliderRtl .dijitSliderProgressBarH,
+.claro .dijitSliderRtl .dijitSliderRemainingBarH,
+.claro .dijitSliderRtl .dijitSliderLeftBumper,
+.claro .dijitSliderRtl .dijitSliderRightBumper,
+.claro .dijitSliderRtl .dijitSliderTopBumper {
+	background-position: top right;
+}
+
+.claro .dijitSliderRtl .dijitSliderProgressBarV,
+.claro .dijitSliderRtl .dijitSliderRemainingBarV,
+.claro .dijitSliderRtl .dijitSliderBottomBumper {
+	background-position: bottom right;
+}
+
+.claro .dijitSliderRtl .dijitSliderLeftBumper {
+	border-left-width: 0px;
+	border-right-width: 1px;
+}
+
+.claro .dijitSliderRtl .dijitSliderRightBumper {
+	border-left-width: 1px;
+	border-right-width: 0px;
+}
+
+.claro .dijitSliderRtl .dijitSliderIncrementIconH {
+	background-position:-357px 50%;
+}
+
+.claro .dijitSliderRtl .dijitSliderDecrementIconH {
+	background-position:-251px 50%;
+}
diff --git a/dijit/themes/claro/form/images/button.png b/dijit/themes/claro/form/images/button.png
new file mode 100644
index 0000000..cb787cb
Binary files /dev/null and b/dijit/themes/claro/form/images/button.png differ
diff --git a/dijit/themes/claro/form/images/buttonArrows.png b/dijit/themes/claro/form/images/buttonArrows.png
new file mode 100644
index 0000000..642eff3
Binary files /dev/null and b/dijit/themes/claro/form/images/buttonArrows.png differ
diff --git a/dijit/themes/claro/form/images/button_grad_d.png b/dijit/themes/claro/form/images/button_grad_d.png
new file mode 100644
index 0000000..3a71a46
Binary files /dev/null and b/dijit/themes/claro/form/images/button_grad_d.png differ
diff --git a/dijit/themes/claro/form/images/checkboxAndRadioButtons_IE6.png b/dijit/themes/claro/form/images/checkboxAndRadioButtons_IE6.png
new file mode 100644
index 0000000..92d2221
Binary files /dev/null and b/dijit/themes/claro/form/images/checkboxAndRadioButtons_IE6.png differ
diff --git a/dijit/themes/claro/form/images/checkboxRadioButtonStates.png b/dijit/themes/claro/form/images/checkboxRadioButtonStates.png
new file mode 100644
index 0000000..2d06a82
Binary files /dev/null and b/dijit/themes/claro/form/images/checkboxRadioButtonStates.png differ
diff --git a/dijit/themes/claro/form/images/commonFormArrows.png b/dijit/themes/claro/form/images/commonFormArrows.png
new file mode 100644
index 0000000..6d04742
Binary files /dev/null and b/dijit/themes/claro/form/images/commonFormArrows.png differ
diff --git a/dijit/themes/claro/form/images/error.png b/dijit/themes/claro/form/images/error.png
new file mode 100644
index 0000000..46de1cd
Binary files /dev/null and b/dijit/themes/claro/form/images/error.png differ
diff --git a/dijit/themes/claro/form/images/formHighlight.png b/dijit/themes/claro/form/images/formHighlight.png
new file mode 100644
index 0000000..f90eb25
Binary files /dev/null and b/dijit/themes/claro/form/images/formHighlight.png differ
diff --git a/dijit/themes/claro/form/images/shadow.png b/dijit/themes/claro/form/images/shadow.png
new file mode 100644
index 0000000..72d60e6
Binary files /dev/null and b/dijit/themes/claro/form/images/shadow.png differ
diff --git a/dijit/themes/claro/form/images/sliderHorizontal.png b/dijit/themes/claro/form/images/sliderHorizontal.png
new file mode 100644
index 0000000..d769a64
Binary files /dev/null and b/dijit/themes/claro/form/images/sliderHorizontal.png differ
diff --git a/dijit/themes/claro/form/images/sliderThumbs.png b/dijit/themes/claro/form/images/sliderThumbs.png
new file mode 100644
index 0000000..70ab2fe
Binary files /dev/null and b/dijit/themes/claro/form/images/sliderThumbs.png differ
diff --git a/dijit/themes/claro/form/images/sliderVertical.png b/dijit/themes/claro/form/images/sliderVertical.png
new file mode 100644
index 0000000..9d69d04
Binary files /dev/null and b/dijit/themes/claro/form/images/sliderVertical.png differ
diff --git a/dijit/themes/claro/form/images/textBox_back.png b/dijit/themes/claro/form/images/textBox_back.png
new file mode 100644
index 0000000..dfc752a
Binary files /dev/null and b/dijit/themes/claro/form/images/textBox_back.png differ
diff --git a/dijit/themes/claro/images/calendarArrows.png b/dijit/themes/claro/images/calendarArrows.png
new file mode 100644
index 0000000..3f6faa5
Binary files /dev/null and b/dijit/themes/claro/images/calendarArrows.png differ
diff --git a/dijit/themes/claro/images/calendarArrows8bit.png b/dijit/themes/claro/images/calendarArrows8bit.png
new file mode 100644
index 0000000..ab9d66c
Binary files /dev/null and b/dijit/themes/claro/images/calendarArrows8bit.png differ
diff --git a/dijit/themes/claro/images/calendarContainerImages.png b/dijit/themes/claro/images/calendarContainerImages.png
new file mode 100644
index 0000000..44fa088
Binary files /dev/null and b/dijit/themes/claro/images/calendarContainerImages.png differ
diff --git a/dijit/themes/tundra/images/checkmarkNoBorder.gif b/dijit/themes/claro/images/checkmarkNoBorder.gif
similarity index 100%
copy from dijit/themes/tundra/images/checkmarkNoBorder.gif
copy to dijit/themes/claro/images/checkmarkNoBorder.gif
diff --git a/dijit/themes/tundra/images/checkmarkNoBorder.png b/dijit/themes/claro/images/checkmarkNoBorder.png
similarity index 100%
copy from dijit/themes/tundra/images/checkmarkNoBorder.png
copy to dijit/themes/claro/images/checkmarkNoBorder.png
diff --git a/dijit/themes/claro/images/commonHighlight.png b/dijit/themes/claro/images/commonHighlight.png
new file mode 100644
index 0000000..f90eb25
Binary files /dev/null and b/dijit/themes/claro/images/commonHighlight.png differ
diff --git a/dijit/themes/claro/images/dialogCloseIcon.png b/dijit/themes/claro/images/dialogCloseIcon.png
new file mode 100644
index 0000000..a605c71
Binary files /dev/null and b/dijit/themes/claro/images/dialogCloseIcon.png differ
diff --git a/dijit/themes/claro/images/dialogCloseIcon8bit.png b/dijit/themes/claro/images/dialogCloseIcon8bit.png
new file mode 100644
index 0000000..d2b063b
Binary files /dev/null and b/dijit/themes/claro/images/dialogCloseIcon8bit.png differ
diff --git a/dijit/themes/claro/images/dnd.png b/dijit/themes/claro/images/dnd.png
new file mode 100644
index 0000000..8cb04aa
Binary files /dev/null and b/dijit/themes/claro/images/dnd.png differ
diff --git a/dijit/themes/tundra/images/loading.gif b/dijit/themes/claro/images/loading.gif
similarity index 100%
copy from dijit/themes/tundra/images/loading.gif
copy to dijit/themes/claro/images/loading.gif
diff --git a/dijit/themes/claro/images/loadingAnimation.gif b/dijit/themes/claro/images/loadingAnimation.gif
new file mode 100644
index 0000000..d76e4cd
Binary files /dev/null and b/dijit/themes/claro/images/loadingAnimation.gif differ
diff --git a/dijit/themes/claro/images/menuHighlight.png b/dijit/themes/claro/images/menuHighlight.png
new file mode 100644
index 0000000..22328a7
Binary files /dev/null and b/dijit/themes/claro/images/menuHighlight.png differ
diff --git a/dijit/themes/claro/images/progressBarAnim.gif b/dijit/themes/claro/images/progressBarAnim.gif
new file mode 100644
index 0000000..30c0d9d
Binary files /dev/null and b/dijit/themes/claro/images/progressBarAnim.gif differ
diff --git a/dijit/themes/claro/images/progressBarEmpty.png b/dijit/themes/claro/images/progressBarEmpty.png
new file mode 100644
index 0000000..e0a6856
Binary files /dev/null and b/dijit/themes/claro/images/progressBarEmpty.png differ
diff --git a/dijit/themes/claro/images/progressBarFull.png b/dijit/themes/claro/images/progressBarFull.png
new file mode 100644
index 0000000..280f51d
Binary files /dev/null and b/dijit/themes/claro/images/progressBarFull.png differ
diff --git a/dijit/themes/claro/images/spriteArrows.png b/dijit/themes/claro/images/spriteArrows.png
new file mode 100644
index 0000000..608f4c7
Binary files /dev/null and b/dijit/themes/claro/images/spriteArrows.png differ
diff --git a/dijit/themes/claro/images/titlebar.png b/dijit/themes/claro/images/titlebar.png
new file mode 100644
index 0000000..4818103
Binary files /dev/null and b/dijit/themes/claro/images/titlebar.png differ
diff --git a/dijit/themes/claro/images/tooltip.png b/dijit/themes/claro/images/tooltip.png
new file mode 100644
index 0000000..aca1498
Binary files /dev/null and b/dijit/themes/claro/images/tooltip.png differ
diff --git a/dijit/themes/claro/images/tooltip8bit.png b/dijit/themes/claro/images/tooltip8bit.png
new file mode 100644
index 0000000..51f65f1
Binary files /dev/null and b/dijit/themes/claro/images/tooltip8bit.png differ
diff --git a/dijit/themes/claro/images/treeExpandImages.png b/dijit/themes/claro/images/treeExpandImages.png
new file mode 100644
index 0000000..75cf385
Binary files /dev/null and b/dijit/themes/claro/images/treeExpandImages.png differ
diff --git a/dijit/themes/claro/images/treeExpandImages8bit.png b/dijit/themes/claro/images/treeExpandImages8bit.png
new file mode 100644
index 0000000..290b2e1
Binary files /dev/null and b/dijit/themes/claro/images/treeExpandImages8bit.png differ
diff --git a/dijit/themes/claro/images/treeExpand_loading.gif b/dijit/themes/claro/images/treeExpand_loading.gif
new file mode 100644
index 0000000..424d376
Binary files /dev/null and b/dijit/themes/claro/images/treeExpand_loading.gif differ
diff --git a/dijit/themes/claro/layout/AccordionContainer.css b/dijit/themes/claro/layout/AccordionContainer.css
new file mode 100644
index 0000000..e55b862
--- /dev/null
+++ b/dijit/themes/claro/layout/AccordionContainer.css
@@ -0,0 +1,108 @@
+/* Accordion
+ * 
+ * Styling AccordionContainer basically means styling the accordion pane (dijitAccordionInnerContainer)
+ * and the title inside of it (dijitAccordionTitle).   There are 4 basic states to style:
+ * 
+ * 1. accordion bounding container
+ * 		.dijitAccordionContainer - container for the whole accordion 
+ * 
+ * 2. closed pane (and default styling): 
+ * 		.dijitAccordionInnerContainer - container for each accordion child
+ * 		.dijitAccordionTitle - title for each accordion child
+ *
+ * 3. active closed pane (ie, mouse down on a title bar)
+ * 		.dijitAccordionInnerContainerActive - for background-color, border
+ * 		.dijitAccordionInnerContainerActive dijitAccordionTitle - for text color
+ * 
+ * 4. open pane (expanded child)
+ * 		These rules need to override the closed pane active:
+ *
+ * 		.dijitAccordionInnerContainerSelected - for background-color, border
+ * 		.dijitAccordionInnerContainerSelected .dijitAccordionTitle - for text color
+ * 
+ * 5. hovered pane, open or closed
+ * 		The selectors below affect hovering over both a closed pane (ie, hovering a title bar),
+ * 		and hovering over an open pane.   Also, treat mouse down on an open pane as a hover:
+ *
+ * 		.dijitAccordionInnerContainerHover, .dijitAccordionInnerContainerSelectedActive - for background-color, border
+ * 		.dijitAccordionInnerContainerHover .dijitAccordionTitle - for text color
+ */
+
+.claro .dijitAccordionContainer {
+	border:none;
+}
+.claro .dijitAccordionInnerContainer {
+	background-color: #e6e6e7;	/* gray, for closed pane */
+	border:solid 1px #b5bcc7;
+	margin-bottom:1px;
+	-webkit-transition-property:background-color,border;
+ 	-webkit-transition-duration:.3s;
+	-webkit-transition-timing-function:linear;
+}
+.claro .dijitAccordionTitle {
+	background-color: transparent;	/* pick up color from dijitAccordionInnerContainer */
+	background-image: url("images/accordion.png");
+	background-position:0px 0px;
+	background-repeat:repeat-x;
+	padding: 5px 7px 2px 7px;
+	min-height:17px;
+	color:#4a4a4a;
+}
+.dj_ie6 .claro .dijitAccordionTitle {
+	background-image: none;
+}
+.claro .dijitAccordionContainer .dijitAccordionContainer-child {
+	background-color:#fff;
+	/*
+	 * border style need to be !important to override the style "border:medium none !important"
+	 * in class ".dijitTabPane, .dijitStackContainer-child, .dijitAccordionContainer-child"
+	 */
+	border:1px solid #92bce1 !important;
+	margin: 0px 2px 2px;
+	padding: 9px;
+}
+
+/* Active state for closed pane */
+
+.claro .dijitAccordionInnerContainerActive {
+	border:1px solid #769DC0;
+	background-color:#7dbefa;
+	-webkit-transition-duration:.1s;
+}
+.claro .dijitAccordionInnerContainerActive .dijitAccordionTitle {
+	background-position:0px -136px;
+	color:#000;
+}
+
+/* Open pane */
+
+.claro .dijitAccordionInnerContainerSelected {
+	border-color:#92bce1;
+	background-color: #cde8ff;
+}
+.claro .dijitAccordionInnerContainerSelected .dijitAccordionTitle {
+	color:#000;
+	background-position: 0 0;	/* avoid effect when clicking the title of the open pane */
+}
+
+/* Hovering open or closed pane */
+
+.claro .dijitAccordionInnerContainerHover dijitAccordionTitle {
+	/* both open and closed */
+	color:#000;
+}
+
+.claro .dijitAccordionInnerContainerHover,
+.claro .dijitAccordionInnerContainerSelectedActive {
+	border:1px solid #769DC0;
+	background-color:#9dcfff;
+	-webkit-transition-duration:.2s;
+}
+
+.claro .dijitAccordionInnerContainerSelectedHover .dijitAccordionContainer-child,
+.claro .dijitAccordionInnerContainerSelectedActive .dijitAccordionContainer-child {
+	background-color:#ffffff;
+	border:1px solid #769DC0 !important;
+	-webkit-box-shadow:inset 0px 0px 3px rgba(0, 0, 0, .25);
+	-moz-box-shadow:inset 0px 0px 3px rgba(0, 0, 0, .25);
+}
diff --git a/dijit/themes/claro/layout/BorderContainer.css b/dijit/themes/claro/layout/BorderContainer.css
new file mode 100644
index 0000000..894704e
--- /dev/null
+++ b/dijit/themes/claro/layout/BorderContainer.css
@@ -0,0 +1,134 @@
+/* BorderContainer 
+
+Splitters and gutters separate panes within a BorderContainer. Splitters can be moved up and down (horizonal splitters) or left and right (vertical splitters), while Gutters are static. A "thumb" is the slit on a Splitter that indicates it is movable. 
+
+Styling the BorderContainer widget consists of the following: 
+
+.dijitBorderContainer - for border and padding of the entire border container
+
+.dijitSplitContainer-child, .dijitBorderContainer-child - for border or child panes of the border container. By default borders are put on all children of BorderContainer.  
+
+.dijitBorderContainer-dijitTabContainerTop,
+.dijitBorderContainer-dijitTabContainerBottom,
+.dijitBorderContainer-dijitTabContainerLeft,
+.dijitBorderContainer-dijitTabContainerRight,
+.dijitBorderContainer-dijitAccordionContainer   -for border of the border containers within TabContainer or AccordionContainer widget
+
+.dijitBorderContainer-dijitBorderContainer - for border and padding of nested BorderContainers
+
+Splitters and gutters:  
+
+.dijitSplitterH, .dijitGutterH - for height, background, and border of a horizontal splitter and gutter 
+.dijitSplitterH .dijitSplitterThumb - for color, height/width of the thumb on a horizontal splitter
+.dijitSplitterV, .dijitGutterV - - for height, background, and border of a vertical splitter and gutter 
+.dijitSplitterV .dijitSplitterThumb - for color, height/width of the thumb on a vertical splitter
+.dijitSplitterHHover - for background-color of a hovered horizontal splitter
+.dijitSplitterHHover .dijitSplitterThumb - for background-color of a hovered thumb on a horizontal splitter
+.dijitSplitterVHover  - for background-color of a hovered vertical splitter
+.dijitSplitterVHover .dijitSplitterThumb - for background-color of a hovered thumb on a vertical splitter
+.dijitSplitterHActive - for background-color of an active horizontal splitter
+.dijitSplitterVActive - for background-color of an active horizontal splitter
+
+
+*/
+.claro .dijitBorderContainer {
+	border: 1px #b5bcc7 solid;
+	padding: 5px;
+}
+
+.claro .dijitSplitContainer-child,
+.claro .dijitBorderContainer-child {
+	/* By default put borders on all children of BorderContainer,
+	 *  to give illusion of borders on the splitters themselves.
+	 */
+	border: 1px #b5bcc7 solid;
+}
+
+.claro .dijitBorderContainer-dijitTabContainerTop,
+.claro .dijitBorderContainer-dijitTabContainerBottom,
+.claro .dijitBorderContainer-dijitTabContainerLeft,
+.claro .dijitBorderContainer-dijitTabContainerRight,
+.claro .dijitBorderContainer-dijitAccordionContainer {
+	/* except that TabContainer defines borders on it's sub-nodes (tablist and dijitTabPaneWrapper),
+	 * so override rule setting border on domNode
+	 */
+	 border: none;
+
+}
+.claro .dijitBorderContainer-dijitBorderContainer {
+	/* also, make nested BorderContainers look like a single big widget with lots of splitters */
+	border: 1px #c0ccdf solid;
+	padding: 5px;
+}
+
+/* Splitters and gutters */
+
+.claro .dijitSplitterH,
+.claro .dijitGutterH {
+	background:none;
+	border:0;
+	height:5px;
+}
+
+.claro .dijitSplitterH .dijitSplitterThumb {
+	background:#dde2e9 none;
+	height:1px;
+	top:2px;
+	width:19px;
+}
+
+.claro .dijitSplitterV,
+.claro .dijitGutterV {
+	background:none;
+	border:0;
+	width:5px;
+	margin: 0;
+}
+
+.claro .dijitSplitterV .dijitSplitterThumb {
+	background:#dde2e9 none;
+	height:19px;
+	left:2px;
+	width:1px;
+	margin: 0;
+}
+
+/* hovered splitter */
+.claro .dijitSplitterHHover {
+	font-size: 1px;
+	background: url("images/splitterHorizontalHover.png") no-repeat center top;
+}
+
+
+.claro .dijitSplitterHHover .dijitSplitterThumb {
+	background:#769dc0 none;
+}
+
+.claro .dijitSplitterVHover {
+	font-size: 1px;
+	background: url("images/splitterVerticalHover.png") no-repeat center left;
+}
+
+.claro .dijitSplitterVHover .dijitSplitterThumb {
+	background:#769dc0 none;
+}
+
+.dj_ie6 .dijitSplitterHHover,
+.dj_ie6 .claro .dijitSplitterVHover {
+	background-color:#cfe9ff;
+	background-image:none;
+}
+
+/* active splitter */
+.claro .dijitSplitterHActive {
+	font-size: 1px;
+	background-color:#abd4fb;
+	border-top:blue;
+
+}
+
+.claro .dijitSplitterVActive {
+	font-size: 1px;
+	background-color:#abd4fb;
+
+}
diff --git a/dijit/themes/claro/layout/ContentPane.css b/dijit/themes/claro/layout/ContentPane.css
new file mode 100644
index 0000000..b32c790
--- /dev/null
+++ b/dijit/themes/claro/layout/ContentPane.css
@@ -0,0 +1,40 @@
+/* ContentPane 
+ *	
+ * .dijitContentPane
+ * 	set padding for basic content pane
+ * 	
+ * Nested layouts:
+ * 
+ * .dijitTabContainerTop-dijitContentPane,
+ * .dijitTabContainerLeft-dijitContentPane,
+ * .dijitTabContainerBottom-dijitContentPane,
+ * .dijitTabContainerRight-dijitContentPane
+ * 	set background-color and padding of ContentPanes nested within TabContainer (can do top, left, bottom, or right) or Accordion Container
+ *
+ * .dijitAccordionContainer-dijitContentPane
+ * 	set background-color and padding of ContentPane nested within Accordion
+ *
+ * .dijitSplitContainer-dijitContentPane, 
+ *	set background-color and padding of ContentPane nested within a SplitContainer 
+ *
+ * .dijitBorderContainer-dijitContentPane
+ *	set background-color and padding of ContentPane nested within a BorderContainer 
+ */
+.claro .dijitContentPane {
+	padding: 8px;
+}		
+
+/* nested layouts */
+.claro .dijitTabContainerTop-dijitContentPane,
+.claro .dijitTabContainerLeft-dijitContentPane,
+.claro .dijitTabContainerBottom-dijitContentPane,
+.claro .dijitTabContainerRight-dijitContentPane,
+.claro .dijitAccordionContainer-dijitContentPane {
+	background-color: #fff;
+	padding: 8px;		
+}
+.claro .dijitSplitContainer-dijitContentPane,
+.claro .dijitBorderContainer-dijitContentPane {
+	background-color: #fff;		
+	padding: 8px;
+}
\ No newline at end of file
diff --git a/dijit/themes/claro/layout/TabContainer.css b/dijit/themes/claro/layout/TabContainer.css
new file mode 100644
index 0000000..12e4c8e
--- /dev/null
+++ b/dijit/themes/claro/layout/TabContainer.css
@@ -0,0 +1,439 @@
+/* TabContainer 
+ * 
+ * Styling TabContainer means styling the TabList and Its content container  (dijitTitlePane)
+ * 
+ * Tab List: (including 4 kinds of tab location)
+ * 		.dijitTabContainerTop-tabs     - tablist container at top
+ * 		.dijitTabContainerBottom-tabs  - tablist container at bottom
+ * 		.dijitTabContainerLeft-tabs    - tablist container at left
+ * 		.dijitTabContainerRight-tabs   - tablist container at right
+ * 
+ * Tab Strip Button:
+ * 		.dijitTabStripIcon - tab strip button icon
+ * 		.dijitTabStripMenuIcon - down arrow icon position
+ * 		.dijitTabStripSlideLeftIcon - left arrow icon position
+ * 		.dijitTabStripSlideRightIcon - right arrow icon position
+ * 
+ * 		.tabStripButtonDisabled - styles for disabled tab strip buttons
+ * 
+ * Tab Button:
+ * 		.dijitTabContainerTop-tabs .dijitTabInnerDiv/.dijitTabContent     - styles for top tab botton container
+ * 		.dijitTabContainerBottom-tabs .dijitTabInnerDiv/.dijitTabContent  - styles for bottom tab botton container
+ * 		.dijitTabContainerLeft-tabs .dijitTabInnerDiv/.dijitTabContent    - styles for left tab botton container
+ * 		.dijitTabContainerRight-tabs .dijitTabInnerDiv/.dijitTabContent   - styles for right tab botton container
+ * 
+ * 		.dijitTabContainerTop-tabs .dijitTabChecked .dijitTabInnerDiv/.dijitTabContent    
+ * 				- styles for selected status of top tab botton
+ * 		same to Bottom, Left, Right Tabs
+ * 
+ * 		.dijitTabHover .dijitTabInnerDiv   - styles when mouse hover on tab bottons
+ * 		.dijitTabActive .dijitTabInnerDiv  - styles when mouse down on tab bottons
+ * 		.dijitTabChecked .dijitTabInnerDiv  - styles when on buttons of selected tab		
+ * 
+ * 		.dijitTabCloseButton - the close action buttons lie at the right top of each tab button on closable tabs
+ * 		.dijitTabCloseButtonHover - styles when mouse hover on close action button
+ * 		.dijitTabCloseButtonActive - styles when mouse down on close action button
+ * 
+ * Tab Button: (checked status)
+ * 
+ * Tab Content Container:
+ * 		.dijitTabContainerTop-dijitContentPane
+ * 		.dijitTabContainerBottom-dijitContentPane
+ * 		.dijitTabContainerLeft-dijitContentPane
+ * 		.dijitTabContainerRight-dijitContentPane - for background and padding
+ * 
+ * Nested Tabs:
+ * 		.dijitTabContainerNested - Container for nested tabs
+ * 		.dijitTabContainerTabListNested - tab list container for nested tabs
+ */
+
+/*** some common features ***/
+.claro .dijitTabPaneWrapper {
+	background:#fff;
+}
+.claro .dijitTabPaneWrapper,
+.claro .dijitTabContainerTop-tabs,
+.claro .dijitTabContainerBottom-tabs,
+.claro .dijitTabContainerLeft-tabs,
+.claro .dijitTabContainerRight-tabs {
+	/* todo: add common class name for this div */
+	border-color: #b5bcc7;
+}
+.claro .dijitTabCloseButton {
+	background: url("images/tabClose.png") no-repeat;
+	width: 14px;
+	height: 14px;
+	margin-left: 5px;
+	margin-right:-3px;
+}
+.claro .dijitTabCloseButtonHover {
+	background-position:-14px;
+}
+.claro .dijitTabCloseButtonActive {
+	background-position:-28px;
+}
+.claro .dijitTabSpacer {
+	/* set the spacer invisible.  note that height:0 doesn't work on IE/quirks, it's still 10px. */
+	display: none;
+}
+.claro .dijitTabInnerDiv {
+	background-color:#e6e6e7;
+	-webkit-transition-property:background-color, border;
+ 	-webkit-transition-duration:.35s;
+	color:#4a4a4a;
+}
+.claro .dijitTabHover .dijitTabInnerDiv {
+	background-color:#a9d6ff;
+ 	-webkit-transition-duration:.25s;
+	color:#000;
+}
+.claro .dijitTabActive .dijitTabInnerDiv {
+	background-color:#8bc4f9;
+	color:#000;
+	-webkit-transition-duration:.1s;
+}
+.claro .dijitTabChecked .dijitTabInnerDiv {
+	background-color:#b2d4f3;
+	color:#000;
+}
+
+.claro .dijitTabContent {
+	border: 1px solid #b5bcc7;
+}
+.claro .dijitTabHover .dijitTabContent,
+.claro .dijitTabActive .dijitTabContent {
+	border-color: #769dc0;
+}
+.claro .dijitTabChecked .dijitTabContent {
+	color:#000;
+	border-color: #b5bcc7;	
+}
+
+.claro .tabStripButton .dijitTabInnerDiv {
+	background-color: transparent;
+}
+.claro .tabStripButton .dijitTabContent {
+	border: none;
+}
+/*** end common ***/
+
+
+/*************** top tab ***************/
+.claro .dijitTabContainerTop-tabs .dijitTab {
+	top: 1px;	/* used for overlap */
+	margin-right: 1px;
+	padding-top: 3px;
+}
+.dj_ie7 .claro .dijitTabContainerTop-tabs .dijitTab {
+	top: 3px;
+}
+/* for top tab padding. change height when status changes */
+.claro .dijitTabContainerTop-tabs .dijitTabContent {
+	padding:3px 8px 3px 4px;
+	border-bottom: 1px;
+	background-image:url("images/tabTop.png");
+	background-position:0px 0px;
+	background-repeat:repeat-x;
+	min-width: 60px;
+	text-align: center;
+}
+.claro .dijitTabContainerTop-tabs .dijitTabChecked .dijitTabContent {
+	padding-bottom: 4px;
+	padding-top: 6px;
+}
+.dj_ie .claro .dijitTabContainerTop-tabs .dijitTabChecked .dijitTabContent {
+	border-bottom: none;
+}
+
+/* normal status */
+.claro .dijitTabContainerTop-tabs .dijitTabInnerDiv {
+	background-image:url("images/tabTop.png");
+	background-position:0px -248px;
+	background-position:bottom;
+	background-repeat:repeat-x;
+	box-shadow: 0px -1px 1px rgba(0, 0, 0, 0.04);
+	-webkit-box-shadow: 0px -1px 1px rgba(0, 0, 0, 0.04);
+	-moz-box-shadow: 0px -1px 1px rgba(0, 0, 0, 0.04);
+}
+
+/* checked status */
+.claro .dijitTabContainerTop-tabs .dijitTabChecked .dijitTabInnerDiv {
+	background-image:none;
+	box-shadow: 0px -1px 2px rgba(0, 0, 0, 0.05);
+	-webkit-box-shadow: 0px -1px 2px rgba(0, 0, 0, 0.05);
+	-moz-box-shadow: 0px -1px 2px rgba(0, 0, 0, 0.05);
+}
+.claro .dijitTabContainerTop-tabs .dijitTabChecked .dijitTabContent {
+	background-position:0px -102px;
+	background-repeat:repeat-x;
+}
+/** end top tab **/
+
+
+/*************** bottom tab ***************/
+.claro .dijitTabContainerBottom-tabs .dijitTab {
+	top: -1px;	/* used for overlap */
+	margin-right: 1px;
+}
+/* calculate the position and size */
+.claro .dijitTabContainerBottom-tabs .dijitTabContent {
+	padding:3px 8px 4px 4px;
+	border-top: none;
+	background-image: url("images/tabBottom.png");
+	background-position:0px -249px;
+	background-repeat: repeat-x;
+	background-position:bottom;
+	min-width: 60px;
+	text-align: center;
+}
+.claro .dijitTabContainerBottom-tabs .dijitTab {
+	padding-bottom: 3px;
+}
+/* normal status */
+.claro .dijitTabContainerBottom-tabs .dijitTabInnerDiv {
+	background-image: url("images/tabBottom.png");
+	background-position: top;
+	background-repeat: repeat-x;
+	box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.04);
+	-webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.04);
+	-moz-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.04);
+	
+}
+
+/* checked status */
+.claro .dijitTabContainerBottom-tabs .dijitTabChecked .dijitTabContent {
+	padding-bottom: 7px;
+	padding-top: 4px;
+	background-position:0px -119px;
+}
+.claro .dijitTabContainerBottom-tabs .dijitTabChecked {
+	padding-bottom: 0;
+}
+.claro .dijitTabContainerBottom-tabs .dijitTabChecked .dijitTabInnerDiv {
+	background-image:none;
+	box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.05);
+	-webkit-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.05);
+	-moz-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.05);
+}
+/** end bottom tab **/
+
+/*************** left tab ***************/
+.claro .dijitTabContainerLeft-tabs .dijitTab {
+	left: 1px;	/* used for overlap */
+	margin-bottom: 1px;
+}
+/* normal status */
+.claro .dijitTabContainerLeft-tabs .dijitTabInnerDiv {
+	background-image: url("images/tabLeft.png");
+	background-position: -347px -340px;
+	background-repeat: repeat-y;
+}
+.claro .dijitTabContainerLeft-tabs .dijitTabContent {
+	padding:3px 8px 4px 4px;
+	background-image: url("images/tabLeft.png");
+	background-repeat: repeat-y;
+	background-position:0px 0px;
+}
+/* checked status */
+.claro .dijitTabContainerLeft-tabs .dijitTabChecked .dijitTabContent {
+	padding-right: 9px;
+	border-right: none;
+	background-image: none;
+}
+.claro .dijitTabContainerLeft-tabs .dijitTabChecked .dijitTabInnerDiv {
+	background-position:0px -179px;
+	background-repeat:repeat-y;
+	box-shadow: -1px 0px 2px rgba(0, 0, 0, .05);
+	-webkit-box-shadow: -1px 0px 2px rgba(0, 0, 0, .05);
+	-moz-box-shadow: -1px 0px 2px rgba(0, 0, 0, 0.05);
+}
+/** end left tab **/
+
+/*************** right tab ***************/
+.claro .dijitTabContainerRight-tabs .dijitTab {
+	left: -1px;	/* used for overlap */
+	margin-bottom: 1px;
+}
+/* normal status */
+.claro .dijitTabContainerRight-tabs .dijitTabInnerDiv {
+	background-image: url("images/tabRight.png");
+	background-repeat: repeat-y;
+	background-position: -1px -347px;
+}
+.claro .dijitTabContainerRight-tabs .dijitTabContent {
+	padding:3px 8px 4px 4px;
+	background-image: url("images/tabRight.png");
+	background-position:right top;
+	background-repeat: repeat-y;
+}
+/* checked status */
+.claro .dijitTabContainerRight-tabs .dijitTabChecked .dijitTabContent {
+	padding-left: 5px;
+	border-left: none;
+	background-image: none;
+}
+.claro .dijitTabContainerRight-tabs .dijitTabChecked .dijitTabInnerDiv {
+	background-position:-348px -179px;
+	box-shadow: 1px 0px 2px rgba(0, 0, 0, 0.07);
+	-webkit-box-shadow: 1px 0px 2px rgba(0, 0, 0, 0.07);
+	-moz-box-shadow: 1px 0px 2px rgba(0, 0, 0, 0.07);
+}
+/** end right tab **/
+
+/** round corner **/
+.claro .dijitTabContainerTop-tabs .dijitTabInnerDiv,
+.claro .dijitTabContainerTop-tabs .dijitTabContent {
+	border-radius: 2px 2px 0px 0px;
+	-moz-border-radius: 2px 2px 0px 0px;
+	-webkit-border-top-left-radius:2px;
+	-webkit-border-top-right-radius:2px;
+}
+.claro .dijitTabContainerBottom-tabs .dijitTabInnerDiv,
+.claro .dijitTabContainerBottom-tabs .dijitTabContent{
+	border-radius: 0px 0px 2px 2px;
+	-moz-border-radius: 0px 0px 2px 2px;
+	-webkit-border-bottom-right-radius:2px;
+	-webkit-border-bottom-left-radius:2px;
+}
+.claro .dijitTabContainerLeft-tabs .dijitTabInnerDiv,
+.claro .dijitTabContainerLeft-tabs .dijitTabContent{
+	border-radius: 2px 0px 0px 2px;
+	-moz-border-radius: 2px 0px 0px 2px;
+	-webkit-border-top-left-radius:2px;
+	-webkit-border-bottom-left-radius:2px;
+}
+
+.claro .dijitTabContainerRight-tabs .dijitTabInnerDiv,
+.claro .dijitTabContainerRight-tabs .dijitTabContent{
+	border-radius: 0px 2px 2px 0px;
+	-moz-border-radius: 0px 2px 2px 0px;
+	-webkit-border-top-right-radius:2px;
+	-webkit-border-bottom-right-radius:2px;
+}
+
+/************ left/right scroll buttons + menu button ************/
+.claro .tabStripButton {
+	background-color:#deecf9;
+	border: 1px solid #b5bcc7;
+}
+.claro .dijitTabListContainer-top .tabStripButton {
+	padding: 4px 3px;
+	margin-top:7px;
+	background-image: url("images/tabTop.png");
+	background-position:0px 0px;
+}
+.claro .dijitTabListContainer-bottom .tabStripButton {
+	padding:5px 3px;
+	margin-bottom:4px;
+	background-image: url("images/tabTop.png");
+	background-position:0px -248px;
+	background-position:bottom;
+}
+.claro .tabStripButtonHover {
+	background-color:#a6d2fb;
+}
+.claro .tabStripButtonActive {
+	background-color:#7dbefa;
+}
+.claro .dijitTabStripIcon {
+	height:15px;
+	width:15px;
+	margin: 0 auto;
+	background:url("../form/images/buttonArrows.png") no-repeat -75px 50%;
+	background-color: transparent;
+}
+.claro .dijitTabStripSlideRightIcon{
+	background-position: -24px 50%;
+}
+.claro .dijitTabStripMenuIcon {
+	background-position: -51px 50%;
+}
+
+/*disabled styles for tab strip buttons*/
+.claro .dijitTabListContainer-top .tabStripButtonDisabled,
+.claro .dijitTabListContainer-bottom .tabStripButtonDisabled {
+	background-color:#dddddd;
+	border:1px solid #c9c9c9;
+}
+.claro .tabStripButtonDisabled .dijitTabStripSlideLeftIcon {
+	background-position:-175px 50%;
+}
+.claro .tabStripButtonDisabled .dijitTabStripSlideRightIcon {
+	background-position: -124px 50%;
+}
+.claro .tabStripButtonDisabled .dijitTabStripMenuIcon {
+	background-position: -151px 50%;
+} 
+/* Nested Tabs */
+.claro .dijitTabContainerNested .dijitTabListWrapper {
+	height: auto;
+}
+.claro .dijitTabContainerNested .dijitTabContainerTop-tabs {
+	border-bottom:solid 1px #b5bcc7;
+	padding:1px 2px 4px;
+	margin-top:-2px;
+}
+.claro .dijitTabContainerTabListNested .dijitTabContent {
+	background:rgba(255, 255, 255, 0) none repeat scroll 0 0;
+	border: none;
+	padding: 4px;
+	border-color: rgba(118,157,192,0);
+	-webkit-transition-property:background-color, border-color;
+ 	-webkit-transition-duration:.3s;
+}
+.claro .dijitTabContainerTabListNested .dijitTab .dijitTabInnerDiv {
+	/* 4 element selector to override box-shadow setting from above rule:
+	 *		.claro .dijitTabContainerTop-tabs .dijitTabChecked .dijitTabInnerDiv { ... }
+	 */
+	background: none;
+	border: none;
+	top: 0px;/* to override top: 1px/-1px for normal tabs */
+	box-shadow: none;
+	-webkit-box-shadow: none;
+	-moz-box-shadow: none;
+}
+.claro .dijitTabContainerTabListNested .dijitTabHover .dijitTabContent {
+	background-color:#eaf4fc;
+	border-radius: 2px 2px 2px 2px;
+	-moz-border-radius: 2px 2px 2px 2px;
+	-webkit-border-radius:2px;
+	border:solid 1px #c8dff3;
+	padding: 3px;
+	webkit-transition-duration:.2s;
+}
+.claro .dijitTabContainerTabListNested .dijitTabHover .tabLabel {
+	text-decoration: none;
+}
+.claro .dijitTabContainerTabListNested .dijitTabActive .dijitTabContent {
+	border-radius: 2px 2px 2px 2px;
+	-moz-border-radius: 2px 2px 2px 2px;
+	-webkit-border-radius:2px;
+	border:solid 1px #a8c7e2;
+	padding: 3px;
+	background:#b9d9f5 url("images/tabNested.png") repeat-x;
+	-webkit-transition-duration:.1s;
+}
+.claro .dijitTabContainerTabListNested .dijitTabChecked .dijitTabContent {
+	border-radius: 2px 2px 2px 2px;
+	-moz-border-radius: 2px 2px 2px 2px;
+	-webkit-border-radius:2px;
+	padding: 3px;
+	border:solid 1px #a8c7e2;
+	background-position: 0px 105px;
+	background-color:#d4e8f9;
+}
+.claro .dijitTabContainerTabListNested .dijitTabChecked .tabLabel {
+	text-decoration: none;
+	background-image:none;
+}
+.claro .dijitTabPaneWrapperNested {
+	border: none;/* prevent double border */
+}
+
+
+.dj_ie6 .claro .dijitTabContent,
+.dj_ie6 .claro .dijitTabInnerDiv,
+.dj_ie6 .dijitTabListContainer-top .tabStripButton,
+.dj_ie6 .dijitTabListContainer-bottom .tabStripButton{
+	background-image: none;
+}
diff --git a/dijit/themes/claro/layout/TabContainer_rtl.css b/dijit/themes/claro/layout/TabContainer_rtl.css
new file mode 100644
index 0000000..280582a
--- /dev/null
+++ b/dijit/themes/claro/layout/TabContainer_rtl.css
@@ -0,0 +1,77 @@
+.claro .dijitTabContainerTop-tabs .dijitTabRtl,
+.claro .dijitTabContainerBottom-tabs .dijitTabRtl {
+	margin-right: 0;
+	margin-left: 1px;
+}
+.claro .dijitTabRtl {
+	-moz-box-orient:horizontal;
+	text-align: right;
+}
+.dj_ie7 .claro .dijitTabRtl .dijitTabContent {
+	display: block;
+	left: 0;
+}
+.dj_ie7 .claro .dijitTabContainerTop-tabs .dijitTabRtl,
+.dj_ie7 .claro .dijitTabContainerTop-tabs .dijitTabCheckedRtl {
+	top: 1px;
+}
+.dj_ie7 .claro .tabStripButtonRtl .dijitButtonContents,
+.dj_ie8 .claro .tabStripButtonRtl .dijitButtonContents,	/* needed for IE8 quirks, but breaks IE6 quirks */
+.dj_ie6 .claro .dijitTabContainerTop-tabs .dijitTabRtl .dijitTabInnerDiv,
+.dj_ie6 .claro .dijitTabContainerBottom-tabs .dijitTabRtl .dijitTabInnerDiv,
+.dj_ie7 .claro .dijitTabContainerTop-tabs .dijitTabRtl .dijitTabInnerDiv,
+.dj_ie7 .claro .dijitTabContainerBottom-tabs .dijitTabRtl .dijitTabInnerDiv,
+.dj_iequirks .claro .dijitTabContainerTop-tabs .dijitTabRtl .dijitTabInnerDiv,
+.dj_iequirks .claro .dijitTabContainerBottom-tabs .dijitTabRtl .dijitTabInnerDiv {
+	float:left;
+}
+.dj_ie6 .claro .dijitTabRtl .tabLabel,
+.dj_ie6 .claro .dijitTabContainerRight-tabs .dijitTabRtl,
+.dj_ie6 .claro .dijitTabContainerLeft-tabs .dijitTabRtl,
+.dj_ie7 .claro .dijitTabContainerRight-tabs .dijitTabRtl .dijitTabInnerDiv,
+.dj_ie7 .claro .dijitTabContainerLeft-tabs .dijitTabRtl .dijitTabInnerDiv {
+	/*Make the .tablabel have width in ie6 with haslayout property, fix Close icon position bug*/
+	zoom:1;
+}
+.dj_ie6 .claro .dijitTabRtl .dijitTabCloseButton,
+.dj_ie7 .claro .dijitTabRtl .dijitTabCloseButton,
+.dj_iequirks .claro .dijitTabRtl .dijitTabCloseButton {
+	margin-right:5px;
+}
+
+.dj_ie6 .claro .dijitTabContainerRightRtl .dijitTabContainerRight-tabs,
+.dj_ie6 .claro .dijitTabContainerLeftRtl .dijitTabContainerLeft-tabs {
+	width:1%;
+}
+
+.dj_ie6 .dijitTabContainerTopStrip,
+.dj_ie6 .dijitTabContainerBottomStrip {
+	position:absolute;
+}
+.dj_iequirks .claro .dijitTabContainerTopRtl .dijitTabContainerTopStrip {
+	padding-top: 10px;
+}
+.dj_ie7 .claro .dijitTabContainerRight-tabs .dijitTabRtlChecked .dijitTabInnerDiv {
+	background-position:-341px -179px;
+}
+
+.dj_ie6 .dijitTabContainerTopRtl .dijitTabStripIcon,
+.dj_ie6 .dijitTabContainerBottomRtl .dijitTabStripIcon {
+   position: relative;
+}
+
+
+.dj_ie6-rtl .claro .dijitTabContainerTop-tabs {	
+	/* this strange rule prevents IE6 bug in themeTester.html?dir=rtl upon closing
+	 * "Closable" tab, where the other tabs disappear
+	 */
+	padding-left: 3px;
+}
+
+.dj_iequirks-rtl .claro .dijitTabListWrapper {
+	/* this strange rule prevents IE6 bug in themeTesterQuirk.html?dir=rtl upon closing
+	 * "Closable" tab, where the other tabs disappear
+	 */
+	border-left: 1px solid #fff;
+	border-right: 1px solid #fff;
+}
diff --git a/dijit/themes/claro/layout/images/accordion.png b/dijit/themes/claro/layout/images/accordion.png
new file mode 100644
index 0000000..4818103
Binary files /dev/null and b/dijit/themes/claro/layout/images/accordion.png differ
diff --git a/dijit/themes/claro/layout/images/splitterHorizontalHover.png b/dijit/themes/claro/layout/images/splitterHorizontalHover.png
new file mode 100644
index 0000000..0f5b691
Binary files /dev/null and b/dijit/themes/claro/layout/images/splitterHorizontalHover.png differ
diff --git a/dijit/themes/claro/layout/images/splitterVerticalHover.png b/dijit/themes/claro/layout/images/splitterVerticalHover.png
new file mode 100644
index 0000000..2c3c696
Binary files /dev/null and b/dijit/themes/claro/layout/images/splitterVerticalHover.png differ
diff --git a/dijit/themes/claro/layout/images/tabBottom.png b/dijit/themes/claro/layout/images/tabBottom.png
new file mode 100644
index 0000000..bf23240
Binary files /dev/null and b/dijit/themes/claro/layout/images/tabBottom.png differ
diff --git a/dijit/themes/claro/layout/images/tabClose.png b/dijit/themes/claro/layout/images/tabClose.png
new file mode 100644
index 0000000..f3b2363
Binary files /dev/null and b/dijit/themes/claro/layout/images/tabClose.png differ
diff --git a/dijit/themes/claro/layout/images/tabLeft.png b/dijit/themes/claro/layout/images/tabLeft.png
new file mode 100644
index 0000000..8e9fcba
Binary files /dev/null and b/dijit/themes/claro/layout/images/tabLeft.png differ
diff --git a/dijit/themes/claro/layout/images/tabNested.png b/dijit/themes/claro/layout/images/tabNested.png
new file mode 100644
index 0000000..0140cf4
Binary files /dev/null and b/dijit/themes/claro/layout/images/tabNested.png differ
diff --git a/dijit/themes/claro/layout/images/tabRight.png b/dijit/themes/claro/layout/images/tabRight.png
new file mode 100644
index 0000000..0aaae53
Binary files /dev/null and b/dijit/themes/claro/layout/images/tabRight.png differ
diff --git a/dijit/themes/claro/layout/images/tabTop.png b/dijit/themes/claro/layout/images/tabTop.png
new file mode 100644
index 0000000..db7626e
Binary files /dev/null and b/dijit/themes/claro/layout/images/tabTop.png differ
diff --git a/dijit/themes/dijit.css b/dijit/themes/dijit.css
index df8b8cd..450380a 100644
--- a/dijit/themes/dijit.css
+++ b/dijit/themes/dijit.css
@@ -1,6 +1,19 @@
+/*
+	Essential styles that themes can inherit.
+	In other words, works but doesn't look great.
+*/
+
+
+
+/****
+		GENERIC PIECES
+ ****/
 
 .dijitReset {
-	
+	/* Use this style to null out padding, margin, border in your template elements
+		so that page specific styles don't break them.
+		- Use in all TABLE, TR and TD tags.
+	*/
 	margin:0;
 	border:0;
 	padding:0;
@@ -8,46 +21,88 @@
 	font: inherit;
 	color: inherit;
 }
+.dijit_a11y .dijitReset {
+	-moz-appearance: none; /* remove predefined high-contrast styling in Firefox */
+}
+
 .dijitInline {
-	
-	display:inline-block;			
-	#zoom: 1; 
-	#display:inline; 
+	/*  To inline block elements.
+		Similar to InlineBox below, but this has fewer side-effects in Moz.
+		Also, apparently works on a DIV as well as a FIELDSET.
+	*/
+	display:inline-block;			/* webkit and FF3 */
+	#zoom: 1; /* set hasLayout:true to mimic inline-block */
+	#display:inline; /* don't use .dj_ie since that increases the priority */
 	border:0;
 	padding:0;
 	vertical-align:middle;
-	#vertical-align: auto;	
+	#vertical-align: auto;	/* makes TextBox,Button line up w/native counterparts on IE6 */
 }
+
 .dijitHidden {
-	
+	/* To hide unselected panes in StackContainer etc. */
 	display: none !important;
 }
+
 .dijitVisible {
-	
-	display: block !important;	
-	position: relative;			
+	/* To show selected pane in StackContainer etc. */
+	display: block !important;	/* override user's display:none setting via style setting or indirectly via class */
+	position: relative;			/* to support setting width/height, see #2033 */
+}
+
+.dijitInputContainer {
+	/* for positioning of placeHolder */
+	#zoom: 1;
+	overflow: hidden;
+	float: none !important; /* needed by FF to squeeze the INPUT in */
+	position:relative;
 }
+
 .dj_ie INPUT.dijitTextBox,
-.dj_ie .dijitInputField INPUT {
+.dj_ie .dijitTextBox INPUT {
 	font-size: 100%;
 }
-.dj_ie .dijitInputField INPUT { 
-	margin: -1px 0 !important;
+.dijitTextBox .dijitSpinnerButtonContainer,
+.dijitTextBox .dijitArrowButtonContainer,
+.dijitTextBox .dijitValidationContainer {
+	float: right;
+	text-align: center;
+}
+.dijitTextBox INPUT.dijitInputField {
+	/* override unreasonable user styling of buttons and icons */
+	padding-left: 0 !important;
+	padding-right: 0 !important;
+}
+.dijitTextBox .dijitValidationContainer {
+	display: none;
 }
 .dijitInlineTable {
-	
+	/* To inline tables with a given width set (otherwise, use dijitInline above) */
 	display:inline-table;
-	display:inline-block;		
-	#zoom: 1; 
-	#display:inline; 
+	display:inline-block;		/* webkit and FF3 */
+	#zoom: 1; /* set hasLayout:true to mimic inline-block */
+	#display:inline; /* don't use .dj_ie since that increases the priority */
 	box-sizing: content-box; -moz-box-sizing: content-box;
 	border:0;
 	padding:0;
 }
+
 .dijitTeeny {
 	font-size:1px;
 	line-height:1px;
 }
+
+.dijitOffScreen {
+	position: absolute;
+	visibility: hidden;
+	left: 50%;
+	top: -10000px;
+}
+
+/*
+ * Popup items have a wrapper div (dijitPopup)
+ * with the real popup inside, and maybe an iframe too
+ */
 .dijitPopup {
 	position: absolute;
 	background-color: transparent;
@@ -56,17 +111,14 @@
 	padding: 0;
 }
 .dijit_a11y .dijitPopup,
-.dijit_ally .dijitPopup div,
-.dijit_a11y .dijitPopup table,
+.dijit_ally .dijitPopup DIV,
+.dijit_a11y .dijitPopup TABLE,
 .dijit_a11y .dijitTooltipContainer {
 	background-color: white !important;
 }
-.dijitInputField {
-	overflow:hidden;
-	#zoom:1;
-}
+
 .dijitPositionOnly {
-	
+	/* Null out all position-related properties */
 	padding: 0 !important;
 	border: 0 !important;
 	background-color: transparent !important;
@@ -74,15 +126,17 @@
 	height: auto !important;
 	width: auto !important;
 }
+
 .dijitNonPositionOnly {
-	
+	/* Null position-related properties */
 	float: none !important;
 	position: static !important;
 	margin: 0 0 0 0 !important;
 	vertical-align: middle !important;
 }
+
 .dijitBackgroundIframe {
-	
+	/* iframe used to prevent problems with PDF or other applets overlaying menus etc */
 	position: absolute;
 	left: 0;
 	top: 0;
@@ -93,39 +147,59 @@
 	padding: 0;
 	margin: 0;
 }
-.dijitClickableRegion {
-	
-	background-color: #e2ebf2;
-	cursor: text;
-}
+
 .dijitDisplayNone {
-	
+	/* hide something.  Use this as a class rather than element.style so another class can override */
 	display:none !important;
 }
+
 .dijitContainer {
-	
-	overflow: hidden;	
+	/* for all layout containers */
+	overflow: hidden;	/* need on IE so something can be reduced in size, and so scrollbars aren't temporarily displayed when resizing */
 }
+
+/****
+		A11Y
+ ****/
 .dijit_a11y * {
 	background-image:none !important;
 }
+.dijit_a11y .dijitIcon,
+.dijit_a11y DIV.dijitArrowButtonInner, /* is this only for Spinner?  if so, it should be deleted */
+.dijit_a11y SPAN.dijitArrowButtonInner,
+.dijit_a11y IMG.dijitArrowButtonInner,
 .dijit_a11y .dijitCalendarIncrementControl {
-	display: none;	
+	/* hide icon nodes in high contrast mode; when necesary they will be replaced by character equivalents
+	 * exception for INPUT.dijitArrowButtonInner, because the icon and character are controlled by the same node */
+	display: none;
+}
+.dijitSpinner DIV.dijitArrowButtonInner {
+	display: block; /* override previous rule */
 }
+
 .dijit_a11y .dijitA11ySideArrow {
-	display: inline !important; 
+	display: inline !important; /* display text instead */
 	cursor: pointer;
 }
+
+/*
+ * Since we can't use shading in a11y mode, and since the underline indicates today's date,
+ * use a border to show the selected date.
+ * Avoid screen jitter when switching selected date by compensating for the selected node's
+ * border w/padding on other nodes.
+ */
 .dijit_a11y .dijitCalendarDateLabel {
 	padding: 1px;
 }
 .dijit_a11y .dijitCalendarSelectedDate .dijitCalendarDateLabel {
-	border: solid 1px black;
+	border-style: dotted !important;
+	border-width: 1px;
 	padding: 0px;
 }
 .dijit_a11y .dijitCalendarDateTemplate {
-	padding-bottom: 0.1em !important;	
+	padding-bottom: 0.1em !important;	/* otherwise bottom border doesn't appear on IE */
 }
+
 .dijit_a11y .dijit * {
 	background:white !important;
 	color:black !important;
@@ -135,89 +209,112 @@
 	border-style: outset!important;
 	border-width: medium!important;
 }
-.dijit_a11y .dijitComboBoxReadOnly .dijitInputField,
-.dijit_a11y .dijitComboBoxReadOnly .dijitButtonNode,
-.dijit_a11y .dijitSpinnerReadOnly .dijitButtonNode,
-.dijit_a11y .dijitSpinnerReadOnly .dijitInputField,
-.dijit_a11y .dijitButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitDropDownButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitComboButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitComboBoxDisabled .dijitInputField,
-.dijit_a11y .dijitComboBoxDisabled .dijitButtonNode,
-.dijit_a11y .dijitSpinnerDisabled .dijitButtonNode,
-.dijit_a11y .dijitSpinnerDisabled .dijitInputField {
+
+.dijit_a11y .dijitTextBoxReadOnly .dijitInputField,
+.dijit_a11y .dijitTextBoxReadOnly .dijitButtonNode {
 	border-style: outset!important;
 	border-width: medium!important;
 	border-color: #999 !important;
 	color:#999 !important;
 }
+
+/* button inner contents - labels, icons etc. */
 .dijitButtonNode * {
 	vertical-align: middle;
 }
-.dijit_a11y .dijitArrowButtonInner {
-	width: 1em;
-	display: none !important;
-}
 .dijitButtonNode .dijitArrowButtonInner {
-	background:no-repeat center;
-	width: 16px;
-}
-.dijitComboBox .dijitArrowButtonInner {
-	display: block;
-}
-.dijit_a11y .dijitToggleButtonChecked .dijitToggleButtonIconChar {
-	display: inline !important;
+	/* the arrow icon node */
+	background: no-repeat center;
+	width: 12px;
+	height: 12px;
+	direction: ltr; /* needed by IE/RTL */
 }
+
+/****
+	3-element borders:  ( dijitLeft + dijitStretch + dijitRight )
+	These were added for rounded corners on dijit.form.*Button but never actually used.
+ ****/
+
 .dijitLeft {
-	
+	/* Left part of a 3-element border */
 	background-position:left top;
 	background-repeat:no-repeat;
 }
+
 .dijitStretch {
-	
-	white-space:nowrap;			
+	/* Middle (stretchy) part of a 3-element border */
+	white-space:nowrap;			/* MOW: move somewhere else */
 	background-repeat:repeat-x;
 }
+
 .dijitRight {
-	
-	#display:inline;				
+	/* Right part of a 3-element border */
+	#display:inline;				/* IE7 sizes to outer size w/o this */
 	background-position:right top;
 	background-repeat:no-repeat;
 }
+
+/* Buttons */
+
 .dijitToggleButton,
 .dijitButton,
 .dijitDropDownButton,
 .dijitComboButton {
-	
+	/* outside of button */
 	margin: 0.2em;
 }
+
+.dijitButtonContents {
+	display: block;		/* to make focus border rectangular */
+}
+td.dijitButtonContents {
+	display: table-cell;	/* but don't affect Select, ComboButton */
+}
+
+.dijitButtonNode IMG {
+	/* make text and images line up cleanly */
+	vertical-align:middle;
+	/*margin-bottom:.2em;*/
+}
+
+TABLE.dijitComboButton { /* TODO: why not add dijitReset class to ComboButton? */
+	/* In ComboButton, borders are on each cell rather than on <table> itself */
+	border-collapse: collapse;
+	border:0;
+	padding:0;
+	margin:0;
+}
+.dijitToolbar .dijitComboButton {
+	/* because Toolbar only draws a border around the hovered thing */
+	border-collapse: separate;
+}
+
 .dijitToolbar .dijitToggleButton,
 .dijitToolbar .dijitButton,
 .dijitToolbar .dijitDropDownButton,
 .dijitToolbar .dijitComboButton {
 	margin: 0;
 }
-.dj_ie8 .dijitToolbar button,
-.dj_webkit .dijitToolbar button {
-	
+
+.dijitToolbar .dijitButtonContents {
+	/* just because it used to be this way */
 	padding: 1px 2px;
 }
-.dj_ie .dijitToolbar .dijitComboBox{
-	
-	vertical-align: middle;
-}
+
 .dj_ie .dijitComboButton {
-	
+	/* hack to get inline-table to vertically align w/other buttons */
 	margin-bottom: -3px;
 }
+
 .dj_webkit .dijitToolbar .dijitDropDownButton {
 	padding-left: 0.3em;
 }
 .dj_gecko .dijitToolbar .dijitButtonNode::-moz-focus-inner {
 	padding:0;
 }
+
 .dijitButtonNode {
-	
+	/* Node that is acting as a button -- may or may not be a BUTTON element */
 	border:1px solid gray;
 	margin:0;
 	line-height:normal;
@@ -226,140 +323,309 @@
 	text-align:center;
 	white-space: nowrap;
 }
-.dijitButtonNode, .dijitButtonNode * {
-	cursor: pointer;
+.dj_webkit .dijitSpinner .dijitSpinnerButtonContainer {
+	/* apparent WebKit bug where messing with the font coupled with line-height:normal X 2 (dijitReset & dijitButtonNode)
+	can be different than just a single line-height:normal, visible in InlineEditBox/Spinner */
+	line-height:inherit;
 }
-.dijitReadOnly *,
-.dijitDisabled *,
-.dijitReadOnly,
-.dijitDisabled,
-.dijitDisabledClickableRegion {	
-	cursor: not-allowed !important;
+.dijitTextBox .dijitButtonNode {
+	border-width: 0;
+}
+
+.dijitButtonNode,
+.dijitButtonNode * {
+	cursor: pointer;
 }
+
 .dj_ie .dijitButtonNode {
-	
+	/* ensure hasLayout */
 	zoom: 1;
 }
+
 .dj_ie .dijitButtonNode button {
-	
+	/*
+		disgusting hack to get rid of spurious padding around button elements
+		on IE. MSIE is truly the web's boat anchor.
+	*/
 	overflow: visible;
 }
-.dijitArrowButton {
-	
-	
-	padding: 0 .4em;
-}
+
 DIV.dijitArrowButton {
 	float: right;
 }
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	border-style: solid;
+
+/******
+	TextBox related.
+	Everything that has an <input>
+*******/
+
+.dijitTextBox {
+	border: solid black 1px;
+	#overflow: hidden; /* #6027, #6067 */
+	width: 15em;	/* need to set default size on outer node since inner nodes say <input style="width:100%"> and <td width=100%>.  user can override */
+	vertical-align: middle;
+	#vertical-align: auto;
+}
+
+.dijitTextBoxReadOnly,
+.dijitTextBoxDisabled {
+	color: gray;
+}
+.dj_webkit .dijitTextBoxDisabled INPUT {
+	color: #eee; /* because WebKit lightens disabled input/textarea no matter what color you specify */
+}
+.dj_webkit TEXTAREA.dijitTextAreaDisabled {
+	color: #333; /* because WebKit lightens disabled input/textarea no matter what color you specify */
+}
+.dj_gecko .dijitTextBoxReadOnly INPUT,
+.dj_gecko .dijitTextBoxDisabled INPUT {
+	-moz-user-input: none; /* prevent focus of disabled textbox buttons */
+}
+
+.dijitPlaceHolder {
+	/* hint text that appears in a textbox until user starts typing */
+	color: #AAAAAA;
+	font-style: italic;
+	position: absolute;
+	top: 0;
+	left: 0;
+	#filter: ""; /* make this showup in IE6 after the rendering of the widget */
+}
+
+.dijitTimeTextBox {
+	width: 8em;
+}
+
+/* rules for webkit to deal with fuzzy blue focus border */
+.dijitTextBox INPUT:focus {
+	outline: none;	/* blue fuzzy line looks wrong on combobox or something w/validation icon showing */
+}
+.dijitTextBoxFocused {
+	outline: auto 5px -webkit-focus-ring-color;
+}
+
+.dijitTextBox INPUT {
+	float: left; /* needed by IE to remove secret margin */
+}
+.dijitInputInner {
+	/* for when an <input> is embedded inside an inline-block <div> with a size and border */
+	border:0 !important;
+	vertical-align:middle !important;
+	background-color:transparent !important;
+	width:100% !important;
+	/* IE dislikes horizontal tweaking combined with width:100% so punish everyone for consistency */
+	padding-left: 0 !important;
+	padding-right: 0 !important;
+	margin-left: 0 !important;
+	margin-right: 0 !important;
+}
+.dijit_a11y .dijitTextBox INPUT {
+	margin: 0 !important;
+}
+.dijitTextBoxError INPUT.dijitValidationInner,
+.dijitTextBox INPUT.dijitArrowButtonInner {
+	/* <input> used to display arrow icon/validation icon, or in arrow character in high contrast mode.
+	 * The css below is a trick to hide the character in non-high-contrast mode
+	 */
+	text-indent: -1em !important;
+	direction: ltr !important;
+	text-align: left !important;
+	height: auto !important;
+	#text-indent: 0 !important;
+	#letter-spacing: -5em !important;
+	#text-align: right !important;
+}
+.dj_ie .dijitTextBox INPUT,
+.dj_ie INPUT.dijitTextBox {
+	overflow-y: visible; /* INPUTs need help expanding when padding is added or line-height is adjusted */
+	line-height: normal; /* strict mode */
+}
+.dj_ie7 .dijitTextBox INPUT.dijitValidationInner,
+.dj_ie7 .dijitTextBox INPUT.dijitArrowButtonInner {
+	line-height: 86%; /* IE7 problem where the icon is vertically too low w/o this - real input stays at normal */
+}
+.dj_ie6 .dijitTextBox INPUT,
+.dj_ie6 INPUT.dijitTextBox,
+.dj_iequirks .dijitTextBox INPUT.dijitValidationInner,
+.dj_iequirks .dijitTextBox INPUT.dijitArrowButtonInner,
+.dj_iequirks .dijitTextBox INPUT.dijitSpinnerButtonInner,
+.dj_iequirks .dijitTextBox INPUT.dijitInputInner,
+.dj_iequirks INPUT.dijitTextBox {
+	line-height: 100%; /* IE7 problem where the icon is vertically way too low w/o this */
+}
+.dijit_a11y INPUT.dijitValidationInner,
+.dijit_a11y INPUT.dijitArrowButtonInner {
+	/* (in high contrast mode) revert rules from above so character displays */
+	text-indent: 0 !important;
+	width: 1em !important;
+	#text-align: left !important;
+}
+.dijitTextBoxError .dijitValidationContainer {
+	display: inline;
+	cursor: default;
+}
+
+/* ComboBox & Spinner */
+
+.dijitSpinner .dijitSpinnerButtonContainer,
+.dijitComboBox .dijitArrowButtonContainer {
+	/* dividing line between input area and up/down button(s) for ComboBox and Spinner */
+	border-width: 0 0 0 1px !important; /* !important needed due to wayward ".theme .dijitButtonNode" rules */
+}
+.dijitSpinner .dijitSpinnerButtonContainer .dijitButtonNode {
+	/* dividing line between input area and up/down button(s) for ComboBox and Spinner */
+	border-width: 0;
+}
+.dj_ie .dijit_a11y .dijitSpinner .dijitSpinnerButtonContainer .dijitButtonNode {
+	clear: both; /* IE workaround */
+}
+.dijit_a11y .dijitTextBox .dijitValidationContainer,
+.dijit_a11y .dijitTextBox .dijitSpinnerButtonContainer,
+.dijit_a11y .dijitComboBox .dijitArrowButtonContainer {
+	/* dividing line between input area and up/down button(s) for ComboBox and Spinner */
+	border: solid black !important;
 	border-width: 0 0 0 1px !important;
+}
+
+.dj_ie .dijitToolbar .dijitComboBox {
+	/* make combobox buttons align porperly with other buttons in a toolbar */
+	vertical-align: middle;
+}
+
+/* Spinner */
+
+.dijitTextBox .dijitSpinnerButtonContainer {
+	width: 1em;
+	position: relative !important;
+	overflow: hidden;
+}
+.dijitSpinner .dijitSpinnerButtonInner {
+	width:1em;
+	visibility:hidden !important; /* just a sizing element */
+	overflow-x:hidden;
+}
+.dijitComboBox .dijitButtonNode,
+.dijitSpinnerButtonContainer .dijitButtonNode {
+	border-width: 0;
+}
+.dijit_a11y .dijitSpinnerButtonContainer .dijitButtonNode {
+	border: 0 none !important;
+}
+.dijit_a11y .dijitTextBox .dijitSpinnerButtonContainer,
+.dijit_a11y .dijitSpinner .dijitArrowButtonInner,
+.dijit_a11y .dijitSpinnerButtonContainer INPUT {
+	width: 1em !important;
+}
+.dijit_a11y .dijitSpinner .dijitArrowButtonInner {
+	margin: 0 auto !important; /* should auto-center */
+}
+.dj_ie .dijit_a11y .dijitSpinner .dijitArrowButtonInner .dijitInputField {
+	padding-left: 0.3em !important;
+	padding-right: 0.3em !important;
+	margin-left: 0.3em !important;
+	margin-right: 0.3em !important;
+	width: 1.4em !important;
+}
+.dj_ie7 .dijit_a11y .dijitSpinner .dijitArrowButtonInner .dijitInputField {
+	padding-left: 0.0em !important; /* manually center INPUT: character is .5em and total width = 1em */
+	padding-right: 0.0em !important;
+	width: 1em !important;
+}
+.dj_ie6 .dijit_a11y .dijitSpinner .dijitArrowButtonInner .dijitInputField {
+	margin-left: 0.1em !important;
+	margin-right: 0.1em !important;
+	width: 1em !important;
+}
+.dj_iequirks .dijit_a11y .dijitSpinner .dijitArrowButtonInner .dijitInputField {
+	margin-left: 0 !important;
+	margin-right: 0 !important;
+	width: 2em !important;
+}
+.dijitSpinner .dijitSpinnerButtonContainer .dijitArrowButton {
+	/* note: .dijitInputLayoutContainer makes this rule override .dijitArrowButton settings
+	 * for dijit.form.Button
+	 */
 	padding: 0;
-	position: absolute;
+	position: absolute !important;
 	right: 0;
 	float: none;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	position: absolute;
 	height: 50%;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitDownArrowButton {
-	top: auto;
-	bottom: 0;
-	border-top-width: 1px !important;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitUpArrowButton {
-	top: 0;
+	width: 100%;
 	bottom: auto;
+	left: 0;
+	right: auto;
 }
-TABLE.dijitComboButton {
-	
-	border-collapse: collapse;
-	border:0;
-	padding:0;
-	margin:0;
+.dj_iequirks .dijitSpinner .dijitSpinnerButtonContainer .dijitArrowButton {
+	width: auto;
 }
-.dijitToolbar .dijitComboButton {
-	
-	border-collapse: separate;
+.dijit_a11y .dijitSpinnerButtonContainer .dijitArrowButton {
+	overflow: visible !important;
 }
-.dj_ie BUTTON.dijitButtonNode {
-	overflow: visible; 
+.dijitSpinner .dijitSpinnerButtonContainer .dijitDownArrowButton {
+	top: 50%;
+	border-top-width: 1px !important;
 }
-table .dijitButton .dijitButtonNode,
-table .dijitComboButton .dijitButtonNode {
-	#overflow:hidden; 
+.dijitSpinner .dijitSpinnerButtonContainer .dijitUpArrowButton {
+	#bottom: 50%;	/* otherwise (on some machines) top arrow icon too close to splitter border (IE6/7) */
+	top: 0;
 }
-.dijitButtonNode IMG {
-	
-	vertical-align:middle;
-	
+.dijitSpinner .dijitArrowButtonInner {
+	margin: auto;
+	overflow-x: hidden;
+	height: 100% !important;
 }
-.dijitTextBox,
-.dijitComboBox,
-.dijitSpinner {
-	border: solid black 1px;
-	#overflow: hidden; 
-	width: 15em;	
-	vertical-align: middle;
-	#vertical-align: auto;
+.dj_iequirks .dijitSpinner .dijitArrowButtonInner {
+	height: auto !important;
 }
-.dijitTimeTextBox {
-	width: 8em;
+.dijitSpinner .dijitArrowButtonInner .dijitInputField {
+	-moz-transform: scale(0.5);
+	-moz-transform-origin: center top;
+	-webkit-transform: scale(0.5);
+	-webkit-transform-origin: center top;
+	-o-transform: scale(0.5);
+	-o-transform-origin: center top;
+	transform: scale(0.5);
+	transform-origin: left top;
+	padding-top: 0;
+	padding-bottom: 0;
+	padding-left: 0 !important;
+	padding-right: 0 !important;
+	width: 100%;
 }
-.dijitTextBox input:focus,
-.dijitComboBox input:focus,
-.dijitSpinner input:focus {
-	outline: none;	
+.dj_ie .dijitSpinner .dijitArrowButtonInner .dijitInputField {
+	zoom: 50%; /* emulate transform: scale(0.5) */
 }
-.dijitTextBoxFocused,
-.dijitComboBoxFocused,
-.dijitSpinnerFocused, .dijitSpinnerUpArrowActive, .dijitSpinnerDownArrowActive,
-.dijitTextAreaFocused {
-	
-	outline: auto 5px -webkit-focus-ring-color;
+.dijitSpinner .dijitSpinnerButtonContainer .dijitArrowButtonInner {
+	overflow: hidden;
 }
-.dijitTextBox INPUT,
-.dijitComboBox INPUT,
-.dijitSpinner INPUT {
-	border-left: solid black 1px;	
-	display:inline;
-	position:static !important;
-	border:0 !important;
-	margin:0 !important;
-	vertical-align:top !important;
-	background-color:transparent !important;
-	background-image:none !important;
-	width:100% !important;
+
+.dijit_a11y .dijitSpinner .dijitSpinnerButtonContainer .dijitArrowButton {
+	width: 100%;
 }
-.dijitValidationIcon {
-	visibility: hidden;
-	display: block;
-	padding: 0 2px;
-	float: right;
-	height: auto;
+.dj_iequirks .dijit_a11y .dijitSpinner .dijitSpinnerButtonContainer .dijitArrowButton {
+	width: 1em; /* matches .dijit_a11y .dijitTextBox .dijitSpinnerButtonContainer rule - 100% is the whole screen width in quirks */
 }
-.dijitValidationIconText {
+.dijitSpinner .dijitArrowButtonInner .dijitInputField {
 	visibility: hidden;
-	display: none;
-	float:right;
-	font-family: sans-serif;
-	font-style:italic;
-	font-size: 0.75em;
-	padding-right: 0.15em;
-	line-height: 160%;
-}
-.dijit_a11y .dijitValidationIcon { display: none !important; }
-.dijit_a11y .dijitValidationIconText { display: block !important; }
-.dijitError .dijitValidationIcon,
-.dijitError .dijitValidationIconText {
+}
+.dijit_a11y .dijitSpinner .dijitArrowButtonInner .dijitInputField {
+	vertical-align:top;
 	visibility: visible;
 }
-.dijitTextBox .dijitArrowButton {
-	
-	display:none;
+.dijit_a11y .dijitSpinnerButtonContainer {
+	width: 1em;
+}
+.dijit_a11y .dijitSpinnerButtonContainer .dijitButtonNode {
+	border-width: 1px 0px 0px 0px;
+	border-style: solid !important;
 }
+
+/****
+		dijit.form.CheckBox
+ 	 &
+  		dijit.form.RadioButton
+ ****/
+
 .dijitCheckBox,
 .dijitRadio,
 .dijitCheckBoxInput {
@@ -371,23 +637,28 @@ table .dijitComboButton .dijitButtonNode {
 	background-repeat:no-repeat;
 	overflow: hidden;
 }
+
 .dijitCheckBox INPUT,
 .dijitRadio INPUT {
 	margin: 0;
 	padding: 0;
 	display: block;
 }
+
 .dijitCheckBoxInput {
-	
+	/* place the actual input on top, but all-but-invisible */
 	opacity: 0.01;
 }
+
 .dj_ie .dijitCheckBoxInput {
 	filter: alpha(opacity=0);
 }
+
 .dijit_a11y .dijitCheckBox,
 .dijit_a11y .dijitRadio {
-	width: auto;
-	height: auto;
+	/* in a11y mode we display the native checkbox (not the icon), so don't restrict the size */
+	width: auto !important;
+	height: auto !important;
 }
 .dijit_a11y .dijitCheckBoxInput {
 	opacity: 1;
@@ -395,14 +666,21 @@ table .dijitComboButton .dijitButtonNode {
 	width: auto;
 	height: auto;
 }
-.dijitProgressBarEmpty{
-	
+
+
+/****
+		dijit.ProgressBar
+ ****/
+
+.dijitProgressBarEmpty {
+	/* outer container and background of the bar that's not finished yet*/
 	position:relative;overflow:hidden;
-	border:1px solid black; 	
-	z-index:0;			
+	border:1px solid black; 	/* a11y: border necessary for high-contrast mode */
+	z-index:0;			/* establish a stacking context for this progress bar */
 }
+
 .dijitProgressBarFull {
-	
+	/* outer container for background of bar that is finished */
 	position:absolute;
 	overflow:hidden;
 	z-index:-1;
@@ -412,8 +690,9 @@ table .dijitComboButton .dijitButtonNode {
 .dj_ie6 .dijitProgressBarFull {
 	height:1.6em;
 }
+
 .dijitProgressBarTile {
-	
+	/* inner container for finished portion */
 	position:absolute;
 	overflow:hidden;
 	top:0;
@@ -427,27 +706,33 @@ table .dijitComboButton .dijitButtonNode {
 	background-color:#aaa;
 	background-attachment: fixed;
 }
-.dijit_a11y .dijitProgressBarTile{
-	
-	border-width:4px;
+
+.dijit_a11y .dijitProgressBarTile {
+	/* a11y:  The border provides visibility in high-contrast mode */
+	border-width:2px;
 	border-style:solid;
 	background-color:transparent !important;
 }
+
 .dj_ie6 .dijitProgressBarTile {
-	
+	/* width:auto works in IE6 with position:static but not position:absolute */
 	position:static;
-	
+	/* height:auto or 100% does not work in IE6 */
 	height:1.6em;
 }
+
 .dijitProgressBarIndeterminate .dijitProgressBarLabel {
 	visibility:hidden;
 }
+
 .dijitProgressBarIndeterminate .dijitProgressBarTile {
-	
+	/* animated gif for 'indeterminate' mode */
 }
+
 .dijitProgressBarIndeterminateHighContrastImage {
 	display:none;
 }
+
 .dijit_a11y .dijitProgressBarIndeterminate .dijitProgressBarIndeterminateHighContrastImage {
 	display:block;
 	position:absolute;
@@ -458,6 +743,7 @@ table .dijitComboButton .dijitButtonNode {
 	width:100%;
 	height:auto;
 }
+
 .dijitProgressBarLabel {
 	display:block;
 	position:static;
@@ -465,35 +751,52 @@ table .dijitComboButton .dijitButtonNode {
 	text-align:center;
 	background-color:transparent !important;
 }
+
+/****
+		dijit.Tooltip
+ ****/
+
 .dijitTooltip {
 	position: absolute;
 	z-index: 2000;
 	display: block;
-	
+	/* make visible but off screen */
 	left: 50%;
 	top: -10000px;
 	overflow: visible;
 }
+
 .dijitTooltipContainer {
 	border: solid black 2px;
 	background: #b8b5b5;
 	color: black;
 	font-size: small;
 }
+
 .dijitTooltipFocusNode {
 	padding: 2px 2px 2px 2px;
 }
+
 .dijitTooltipConnector {
 	position: absolute;
 }
+.dijit_a11y .dijitTooltipConnector {
+	display: none;	/* won't show b/c it's background-image; hide to avoid border gap */
+}
+
 .dijitTooltipData {
 	display:none;
 }
-.dijitLayoutContainer{
+
+/* Layout widgets. This is essential CSS to make layout work (it isn't "styling" CSS)
+   make sure that the position:absolute in dijitAlign* overrides other classes */
+
+.dijitLayoutContainer {
 	position: relative;
 	display: block;
 	overflow: hidden;
 }
+
 body .dijitAlignTop,
 body .dijitAlignBottom,
 body .dijitAlignLeft,
@@ -501,41 +804,62 @@ body .dijitAlignRight {
 	position: absolute;
 	overflow: hidden;
 }
+
 body .dijitAlignClient { position: absolute; }
+
+/*
+ * BorderContaienr
+ *
+ * .dijitBorderContainer is a stylized layout where panes have border and margin.
+ * .dijitBorderContainerNoGutter is a raw layout.
+ */
 .dijitBorderContainer, .dijitBorderContainerNoGutter {
 	position:relative;
 	overflow: hidden;
 }
+
 .dijitBorderContainerPane,
 .dijitBorderContainerNoGutterPane {
-	position: absolute !important;	
-	z-index: 2;		
+	position: absolute !important;	/* !important to override position:relative in dijitTabContainer etc. */
+	z-index: 2;		/* above the splitters so that off-by-one browser errors don't cover up border of pane */
 }
+
 .dijitBorderContainer > .dijitTextArea {
-	
+	/* On Safari, for SimpleTextArea inside a BorderContainer,
+		don't want to display the grip to resize */
 	resize: none;
 }
+
 .dijitGutter {
-	
+	/* gutter is just a place holder for empty space between panes in BorderContainer */
 	position: absolute;
-	font-size: 1px;		
+	font-size: 1px;		/* needed by IE6 even though div is empty, otherwise goes to 15px */
 }
+
+/* SplitContainer
+
+	'V' == container that splits vertically (up/down)
+	'H' = horizontal (left/right)
+*/
+
 .dijitSplitter {
 	position: absolute;
 	overflow: hidden;
-	z-index: 10;		
+	z-index: 10;		/* above the panes so that splitter focus is visible on FF, see #7583*/
 	background-color: #fff;
 	border-color: gray;
 	border-style: solid;
 	border-width: 0;
 }
 .dj_ie .dijitSplitter {
-	z-index: 1;	
+	z-index: 1;	/* behind the panes so that pane borders aren't obscured see test_Gui.html/[14392] */
 }
+
 .dijitSplitterActive {
 	z-index: 11 !important;
 }
-.dijitSplitterCover{
+
+.dijitSplitterCover {
 	position:absolute;
 	z-index:-1;
 	top:0;
@@ -543,13 +867,17 @@ body .dijitAlignClient { position: absolute; }
 	width:100%;
 	height:100%;
 }
-.dijitSplitterCoverActive{
+
+.dijitSplitterCoverActive {
 	z-index:3 !important;
 }
-.dj_ie .dijitSplitterCover{
+
+/* #6945: stop mouse events */
+.dj_ie .dijitSplitterCover {
 	background: white;
 	filter: alpha(opacity=0);
 }
+
 .dijitSplitterH {
 	height: 7px;
 	border-top:1px;
@@ -562,14 +890,20 @@ body .dijitAlignClient { position: absolute; }
 	border-right:1px;
 	cursor: ew-resize;
 }
-.dijitSplitContainer{
+.dijitSplitContainer {
 	position: relative;
 	overflow: hidden;
 	display: block;
 }
-.dijitSplitPane{
+.dj_ff3 .dijit_a11y div.dijitSplitter:focus {
+	outline-style:dotted;
+	outline-width: 2px;
+}
+
+.dijitSplitPane {
 	position: absolute;
 }
+
 .dijitSplitContainerSizerH,
 .dijitSplitContainerSizerV {
 	position:absolute;
@@ -581,15 +915,18 @@ body .dijitAlignClient { position: absolute; }
 	border-color: ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight;
 	margin: 0;
 }
+
 .dijitSplitContainerSizerH .thumb, .dijitSplitterV .dijitSplitterThumb {
 	overflow:hidden;
 	position:absolute;
 	top:49%;
 }
+
 .dijitSplitContainerSizerV .thumb, .dijitSplitterH .dijitSplitterThumb {
 	position:absolute;
 	left:49%;
 }
+
 .dijitSplitterShadow,
 .dijitSplitContainerVirtualSizerH,
 .dijitSplitContainerVirtualSizerV {
@@ -600,12 +937,14 @@ body .dijitAlignClient { position: absolute; }
 	filter: Alpha(Opacity=50);
 	margin: 0;
 }
+
 .dj_ie .dijitSplitterV, .dijitSplitContainerVirtualSizerH {
 	cursor: w-resize;
 }
 .dj_ie .dijitSplitterH, .dijitSplitContainerSizerV, .dijitSplitContainerVirtualSizerV {
 	cursor: n-resize;
 }
+
 .dijit_a11y .dijitSplitterH {
 	border-top:1px solid #d3d3d3 !important;
 	border-bottom:1px solid #d3d3d3 !important;
@@ -614,182 +953,292 @@ body .dijitAlignClient { position: absolute; }
 	border-left:1px solid #d3d3d3 !important;
 	border-right:1px solid #d3d3d3 !important;
 }
+
+/* ContentPane */
+
 .dijitContentPane {
 	display: block;
-	overflow: auto;	
+	overflow: auto;	/* if we don't have this (or overflow:hidden), then Widget.resizeTo() doesn't make sense for ContentPane */
 }
+
 .dijitContentPaneSingleChild {
-	
+	/*
+	 * if the ContentPane holds a single layout widget child which is being sized to match the content pane,
+	 * then the ContentPane should never get a scrollbar (but it does due to browser bugs, see #9449
+	 */
 	overflow: hidden;
 }
+
+/* TitlePane */
+
 .dijitTitlePane {
 	display: block;
 	overflow: hidden;
 }
+.dijitTitlePaneTitle {
+	cursor: pointer;
+}
+.dijitFixedOpen {
+	/* TitlePane that cannot be closed */
+	cursor: default;
+}
+.dijitTitlePaneTitle * {
+	vertical-align: middle;
+}
+.dijitTitlePane .dijitArrowNodeInner {
+	/* normally, hide arrow text in favor of icon */
+	display: none;
+}
+.dijit_a11y .dijitTitlePane .dijitArrowNodeInner {
+	/* ... except in a11y mode, then show text arrow */
+	display:inline !important;
+	font-family: monospace;		/* because - and + are different widths */
+}
+.dijit_a11y .dijitTitlePane .dijitArrowNode {
+	/* ... and hide icon */
+	display:none;
+}
+
+.dj_ie6 .dijitTitlePaneContentOuter,
+.dj_ie6 .dijitTitlePane .dijitTitlePaneTitle {
+	/* force hasLayout to ensure borders etc, show up */
+	zoom: 1;
+}
+
+/* Color Palette
+ * Sizes designed so that table cell positions match icons in underlying image,
+ * which appear at 20x20 intervals.
+ */
+
 .dijitColorPalette {
-	border:1px solid #999;
-	background:#fff;
-	-moz-border-radius:3pt;
+	border: 1px solid #999;
+	background: #fff;
+	position: relative;
 }
+
 img.dijitColorPaletteUnder {
-	border-style:none;
-	position:absolute;
-	left:0;
-	top:0;
+	/* This single image contains the "icons" for every color in the color palette, and sits behind the transparent <table> */
+	border-style: none;
+	position: absolute;
+	left: 0;
+	top: 0;
 }
-.dijitColorPaletteInner {
+.dijitColorPalette .dijitPaletteTable {
+	/* Table that holds the palette cells, and overlays image file with color swatches.
+	 * padding/margin to align table with image.
+	 */
+	padding: 2px 3px 3px 3px;
 	position: relative;
-	overflow:hidden;
-	outline:0;
+	overflow: hidden;
+	outline: 0;
+	border-collapse: separate;
 }
-.dijitPaletteCell {
-	width: 20px;
+.dj_ie6 .dijitColorPalette .dijitPaletteTable,
+.dj_ie7 .dijitColorPalette .dijitPaletteTable,
+.dj_iequirks .dijitColorPalette .dijitPaletteTable {
+	/* using padding above so that focus border isn't cutoff on moz/webkit,
+	 * but using margin on IE because padding doesn't seem to work
+	 */
+	padding: 0;
+	margin: 2px 3px 3px 3px;
+}
+
+.dijitColorPalette .dijitPaletteCell {
+	/* <td> in the <table>, matching size of color swatches embedded in the img.dijitColorPaletteUnder */
 	height: 20px;
-	position: absolute;
-	overflow: hidden;
-	z-index: 10;
-	outline-width: 0;
+	width: 20px;
+	font-size: 1px;
+	vertical-align: middle;
+	text-align: center;
 }
-.dijitPaletteImg {
-	width: 16px; 
-	height: 14px; 
-	position: absolute;
-	top: 1px;
-	left: 1px;
-	overflow: hidden;
+.dijitColorPalette .dijitPaletteImg {
+	/* transparent (but clickable) <img> node inside of each <td>, overlaying the color swatch.
+	 * displays border around a color swatch
+	 */
+	width: 16px;
+	height: 14px;
+	border: 1px solid #999;
 	cursor: default;
-	border:1px solid #999;
-	
+	vertical-align: middle;
 }
-.dijitPaletteCellHighlight img {
-	width: 14px; 
-	height: 12px; 
-	position: absolute;
-	top: 1px;
-	left: 1px;
-	overflow: hidden;
-	cursor: default;
-	border:2px solid #000;
-	outline:1px solid #dedede;
-	
+.dj_iequirks .dijitColorPalette .dijitPaletteImg {
+	margin: 1px;	/* needed to fix spacing for ColorPalette in TooltipDialog on IE/quirks */
 }
-.dijit_a11y .dijitPaletteCell {
-	background-color:transparent !important;
+.dijitPaletteTable td {
+		padding: 0px;
 }
-.dijit_a11y .dijitPaletteImg {
-	background-color:transparent !important;
+.dijitColorPalette .dijitPaletteCellHover .dijitPaletteImg {
+	/* hovered color swatch */
+	border: 1px solid #000;
+}
+
+.dijitColorPalette .dijitPaletteCellActive .dijitPaletteImg,
+.dijitColorPalette .dijitPaletteCellSelected .dijitPaletteImg {
+	border: 2px solid #000;
+}
+
+
+.dijit_a11y .dijitColorPalette .dijitPaletteTable,
+.dijit_a11y .dijitColorPalette .dijitPaletteTable * {
+	/* table cells are to catch events, but the swatches are in the PaletteImg behind the table */
+	background-color: transparent !important;
 }
+.dj_gecko .dijit_a11y .dijitColorPalette .dijitPaletteCellFocused .dijitPaletteImg {
+	border: 3px dotted #000;	/* focus border on table cells broken in FF high contrast :-( */
+	margin: -1px;
+}
+
+.dijit_a11y  .dijitColorPalette .dijitPaletteCellHover .dijitPaletteImg {
+	border: 2px solid #000 !important;
+}
+
+/* AccordionContainer */
+
 .dijitAccordionContainer {
 	border:1px solid #b7b7b7;
 	border-top:0 !important;
 }
-.dj_webkit .dijitAccordionContainer  div:focus {
-	outline:none;
-}
-.dj_ff3 .dijitAccordionContainer  div:focus {
-	outline:none;
-}
 .dijitAccordionTitle {
 	cursor: pointer;
 }
-.dijitAccordionFocused  {
-	text-decoration: underline;
+.dijitAccordionTitleSelected {
+	cursor: default;
 }
+
+/* images off, high-contrast mode styles */
 .dijitAccordionTitle .arrowTextUp,
 .dijitAccordionTitle .arrowTextDown {
 	display: none;
 	font-size: 0.65em;
 	font-weight: normal !important;
 }
+
 .dijit_a11y .dijitAccordionTitle .arrowTextUp,
-.dijit_a11y .dijitAccordionTitle-selected .arrowTextDown {
+.dijit_a11y .dijitAccordionTitleSelected .arrowTextDown {
 	display: inline;
 }
-.dijit_a11y .dijitAccordionTitle-selected .arrowTextUp {
+
+.dijit_a11y .dijitAccordionTitleSelected .arrowTextUp {
 	display: none;
 }
-.dijitCalendarContainer thead tr th, .dijitCalendarContainer thead tr td, .dijitCalendarContainer tbody tr td, .dijitCalendarContainer tfoot tr td {
+
+.dj_ie6 .dijitAccordionTitle,
+.dj_iequirks .dijitAccordionTitle {
+	/* avoid IE6/IE quirks size calc bug where accordion ends up too short (themeTesterQuirk.html)
+	 * and IE6 bug where the first title bar turns white upon hovering any title bar
+	 */
+	zoom: 1;
+}
+
+/* Calendar */
+
+.dijitCalendarContainer {
+	width: auto;	/* in case user has specified a width for the TABLE nodes, see #10553 */
+}
+.dijitCalendarContainer th, .dijitCalendarContainer td {
 	padding: 0;
 }
+
 .dijitCalendarNextYear {
 	margin:0 0 0 0.55em;
 }
+
 .dijitCalendarPreviousYear {
 	margin:0 0.55em 0 0;
 }
+
 .dijitCalendarIncrementControl {
 	vertical-align: middle;
 }
-.dijitCalendarDisabledDate {
-	color:gray !important;
-}
-.dijitCalendarPreviousMonthDisabled,
-.dijitCalendarCurrentMonthDisabled,
-.dijitCalendarNextMonthDisabled {
-	cursor:default !important
-}
+
 .dijitCalendarIncrementControl,
-.dijitCalendarBodyContainer tbody tr td,
 .dijitCalendarDateTemplate,
-.dijitCalendarContainer .dijitInline {
-	cursor:pointer;
+.dijitCalendarMonthLabel,
+.dijitCalendarPreviousYear,
+.dijitCalendarNextYear {
+	cursor: pointer;
+}
+
+.dijitCalendarDisabledDate {
+	color: gray;
+	text-decoration: line-through;
+	cursor: default;
 }
+
 .dijitSpacer {
-	
+	/* don't display it, but make it affect the width */
   	position: relative;
   	height: 1px;
   	overflow: hidden;
   	visibility: hidden;
 }
+
+
+/* Menu */
+
 .dijitMenu {
 	border:1px solid black;
 	background-color:white;
 }
 .dijitMenuTable {
-	margin:1px 0;
 	border-collapse:collapse;
 	border-width:0;
 	background-color:white;
 }
+
+/* workaround for webkit bug #8427, remove this when it is fixed upstream */
 .dj_webkit .dijitMenuTable td[colspan="2"]{
 	border-right:hidden;
 }
-.dijitMenuItem{
+
+.dijitMenuItem {
 	text-align: left;
 	white-space: nowrap;
 	padding:.1em .2em;
 	cursor:pointer;
 }
+
 .dijitMenuPassive .dijitMenuItemHover,
 .dijitMenuItemSelected {
-	
+	/*
+	 * dijitMenuItemHover refers to actual mouse over
+	 * dijitMenuItemSelected is used after a menu has been "activated" by
+	 * clicking it, tabbing into it, or being opened from a parent menu,
+	 * and denotes that the menu item has focus or that focus is on a child
+	 * menu
+	 */
 	background-color:black;
 	color:white;
 }
+
 .dijitMenuItemIcon, .dijitMenuExpand {
 	background-repeat: no-repeat;
 }
+
 .dijitMenuItemDisabled * {
-	
-	opacity:0.3;
+	/* for a disabled menu item, just set it to mostly transparent */
+	opacity:0.5;
 	cursor:default;
 }
+.dj_ie .dijit_a11y .dijitMenuItemDisabled,
 .dj_ie .dijit_a11y .dijitMenuItemDisabled td,
 .dj_ie .dijitMenuItemDisabled *,
 .dj_ie .dijitMenuItemDisabled td {
 	color:gray !important;
 	filter: alpha(opacity=35);
 }
+
 .dijitMenuItemLabel {
 	position: relative;
 	vertical-align: middle;
 }
+
 .dijit_a11y .dijitMenuItemSelected {
-	border: 1px #fff dotted !important;
+	border: 1px dotted black !important;
 }
 .dj_ff3 .dijit_a11y .dijitMenuItem td {
 	padding: none !important;
-	background:none ! important;
+	background:none !important;
 }
 .dijit_a11y .dijitMenuItemSelected .dijitMenuItemLabel {
 	border-width: 1px;
@@ -798,28 +1247,35 @@ img.dijitColorPaletteUnder {
 .dj_ie8 .dijit_a11y .dijitMenuItemLabel {
 	position:static;
 }
+
 .dijitMenuExpandA11y {
 	display: none;
 }
 .dijit_a11y .dijitMenuExpandA11y {
 	display: inline;
 }
+
 .dijitMenuSeparator td {
 	border: 0;
 	padding: 0;
 }
+
+/* separator can be two pixels -- set border of either one to 0 to have only one */
 .dijitMenuSeparatorTop {
 	height: 50%;
 	margin: 0;
 	margin-top:3px;
 	font-size: 1px;
 }
+
 .dijitMenuSeparatorBottom {
 	height: 50%;
 	margin: 0;
 	margin-bottom:3px;
 	font-size: 1px;
 }
+
+/* the checked menu item */
 .dijitCheckedMenuItemIconChar {
 	vertical-align: middle;
 	visibility:hidden;
@@ -833,18 +1289,30 @@ img.dijitColorPaletteUnder {
 .dijit_a11y .dijitCheckedMenuItemIcon {
 	display: none;
 }
+.dj_ie .dijit_a11y .dijitMenuBar .dijitMenuItem {
+	/* so bottom border of MenuBar appears on IE7 in high-contrast mode */
+	margin: 0px;
+}
+
+/* StackContainer */
+
 .dijitStackController .dijitToggleButtonChecked * {
-	cursor: default;	
+	cursor: default;	/* because pressing it has no effect */
 }
+
+/* TabContainer */
+
 .dijitTabContainerNoLayout {
-	width: 100%;	
+	width: 100%;	/* otherwise ScrollingTabController goes to 50K pixels wide */
 }
+
 .dijitTabContainerBottom-tabs,
 .dijitTabContainerTop-tabs,
 .dijitTabContainerLeft-tabs,
 .dijitTabContainerRight-tabs {
-	overflow: visible !important;  
+	overflow: visible !important;  /* so tabs can cover up border adjacent to container */
 }
+
 .dijitTabContainerBottom-container,
 .dijitTabContainerTop-container,
 .dijitTabContainerLeft-container,
@@ -853,24 +1321,27 @@ img.dijitColorPaletteUnder {
 	overflow: hidden;
 	border: 1px solid black;
 }
-.dijitTabContainer .nowrapTabStrip {
+.nowrapTabStrip {
 	width: 50000px;
 	display: block;
 	position: relative;
 }
-.dijitTabContainer .dijitTabListWrapper {
+.dijitTabListWrapper {
 	overflow: hidden;
 }
-.dijit_a11y .dijitTabContainer .tabStripButton img {
-	
+
+.dijit_a11y .tabStripButton img {
+	/* hide the icons (or rather the empty space where they normally appear) because text will appear instead */
 	display: none;
 }
+
 .dijitTabContainerTop-tabs {
 	border-bottom: 1px solid black;
 }
 .dijitTabContainerTop-container {
 	border-top: 0px;
 }
+
 .dijitTabContainerLeft-tabs {
 	border-right: 1px solid black;
 	float: left;
@@ -878,12 +1349,14 @@ img.dijitColorPaletteUnder {
 .dijitTabContainerLeft-container {
 	border-left: 0px;
 }
+
 .dijitTabContainerBottom-tabs {
 	border-top: 1px solid black;
 }
 .dijitTabContainerBottom-container {
 	border-bottom: 0px;
 }
+
 .dijitTabContainerRight-tabs {
 	border-left: 1px solid black;
 	float: left;
@@ -891,9 +1364,11 @@ img.dijitColorPaletteUnder {
 .dijitTabContainerRight-container {
 	border-right: 0px;
 }
-div.dijitTabBtnDisabled, .dj_ie div.dijitTabBtnDisabled {
+
+DIV.dijitTabDisabled, .dj_ie DIV.dijitTabDisabled {
 	cursor: auto;
 }
+
 .dijitTab {
 	position:relative;
 	cursor:pointer;
@@ -901,108 +1376,139 @@ div.dijitTabBtnDisabled, .dj_ie div.dijitTabBtnDisabled {
 	z-index:3;
 }
 .dijitTab * {
-	
+	/* make tab icons and close icon line up w/text */
 	vertical-align: middle;
 }
 .dijitTabChecked {
-	cursor: default;	
-}
-.dijitTabButtonIcon {
-	height: 18px;
+	cursor: default;	/* because clicking will have no effect */
 }
+
 .dijitTabContainerTop-tabs .dijitTab {
-	top: 1px;	
+	top: 1px;	/* to overlap border on .dijitTabContainerTop-tabs */
 }
 .dijitTabContainerBottom-tabs .dijitTab {
-	top: -1px;	
+	top: -1px;	/* to overlap border on .dijitTabContainerBottom-tabs */
 }
 .dijitTabContainerLeft-tabs .dijitTab {
-	left: 1px;	
+	left: 1px;	/* to overlap border on .dijitTabContainerLeft-tabs */
 }
 .dijitTabContainerRight-tabs .dijitTab {
-	left: -1px;	
+	left: -1px;	/* to overlap border on .dijitTabContainerRight-tabs */
 }
+
+
 .dijitTabContainerTop-tabs .dijitTab,
 .dijitTabContainerBottom-tabs .dijitTab {
-	
-	display:inline-block;			
-	#zoom: 1; 
-	#display:inline; 
+	/* Inline-block */
+	display:inline-block;			/* webkit and FF3 */
+	#zoom: 1; /* set hasLayout:true to mimic inline-block */
+	#display:inline; /* don't use .dj_ie since that increases the priority */
 }
+
 .dijitTabInnerDiv {
 	position:relative;
 }
+
+
 .tabStripButton {
 	z-index: 12;
 }
+
 .dijitTabButtonDisabled .tabStripButton {
 	display: none;
 }
-.dijitTab .closeButton {
+
+
+.dijitTabCloseButton {
 	margin-left: 1em;
 }
-.dijitTab .closeText {
+
+.dijitTabCloseText {
 	display:none;
 }
-.dijit_a11y .closeText {
-	display:inline;
-	margin: 0px 6px;
+
+/* images off, high-contrast mode styles */
+
+.dijit_a11y .dijitTabCloseButton {
+	background-image: none !important;
+	width: auto !important;
+	height: auto !important;
+	border: thin dotted;	/* non-hover state */
 }
-.dijit_a11y .dijitTab .closeImage {
-	display:none;
+.dijit_a11y .dijitTabCloseButtonHover {
+	border:thin solid;	/* hover state */
 }
-.dijit_a11y .closeButton-hover .closeText {
-	border:thin solid;
+
+.dijit_a11y .dijitTabCloseText {
+	display: inline;
 }
+
 .dijit_a11y .dijitTabChecked {
+	/* the selected tab */
 	border-style:dashed !important;
 }
+
 .dijit_a11y .dijitTabInnerDiv {
 	border-left:none !important;
  }
+
 .dijitTabPane,
 .dijitStackContainer-child,
 .dijitAccordionContainer-child {
-	
+	/* children of TabContainer, StackContainer, and AccordionContainer shouldn't have borders
+	 * b/c a border is already there from the TabContainer/StackContainer/AccordionContainer itself.
+	 */
     border: none !important;
 }
-.dijitInlineEditor {
-	
-	position:relative;
-	vertical-align:bottom;
-}
-.dj_ie .dijitInlineEditor {
-	vertical-align:middle;
+
+/* InlineEditBox */
+.dijitInlineEditBoxDisplayMode {
+	border: 1px solid transparent;	/* so keyline (border) on hover can appear without screen jump */
+	cursor: text;
 }
-.dijitInlineValue {
-	
+
+.dijit_a11y .dijitInlineEditBoxDisplayMode,
+.dj_ie6 .dijitInlineEditBoxDisplayMode {
+	/* except that IE6 doesn't support transparent borders, nor does high contrast mode */
+	border: none;
 }
-.dijitInlineEditor .dijitButtonContainer {
-	
-	position:absolute;
-	right:0;
-	overflow:visible;
+
+.dijitInlineEditBoxDisplayModeHover,
+.dijit_a11y .dijitInlineEditBoxDisplayModeHover,
+.dj_ie6 .dijitInlineEditBoxDisplayModeHover {
+	/* An InlineEditBox in view mode (click this to edit the text) */
+	background-color: #e2ebf2;
+	border: solid 1px black;
 }
-.dijitInlineEditor .saveButton,
-.dijitInlineEditor .cancelButton {
+
+.dijitInlineEditBoxDisplayModeDisabled {
+	cursor: default;
 }
+
+/* Tree */
+
 .dijitTreeIndent {
-	
+	/* amount to indent each tree node (relative to parent node) */
 	width: 19px;
 }
+
 .dijitTreeRow, .dijitTreeContent {
 	white-space: nowrap;
 }
+
 .dijitTreeRow img {
-	
+	/* make the expando and folder icons line up with the label */
 	vertical-align: middle;
 }
+
 .dijitTreeContent {
     cursor: default;
 }
+
 .dijitExpandoText {
 	display: none;
 }
+
 .dijit_a11y .dijitExpandoText {
 	display: inline;
 	padding-left: 10px;
@@ -1012,18 +1518,28 @@ div.dijitTabBtnDisabled, .dj_ie div.dijitTabBtnDisabled {
 	border-width: thin;
 	cursor: pointer;
 }
+
 .dijitTreeLabel {
 	margin: 0px 4px;
 }
+
+/* Dialog */
+
 .dijitDialog {
 	position: absolute;
 	z-index: 999;
-	padding: 1px;
-	overflow: hidden;       
+	overflow: hidden;       /* override overflow: auto; from ContentPane to make dragging smoother */
+}
+
+.dijitDialogTitleBar {
+	cursor: move;
 }
-.dijitDialogFixed div.dijitDialogTitleBar {
+.dijitDialogFixed .dijitDialogTitleBar {
 	cursor:default;
 }
+.dijitDialogCloseIcon {
+	cursor: pointer;
+}
 .dijitDialogUnderlayWrapper {
 	position: absolute;
 	left: 0;
@@ -1032,191 +1548,272 @@ div.dijitTabBtnDisabled, .dj_ie div.dijitTabBtnDisabled {
 	display: none;
 	background: transparent !important;
 }
+
 .dijitDialogUnderlay {
 	background: #eee;
 	opacity: 0.5;
 }
+
 .dj_ie .dijitDialogUnderlay {
 	filter: alpha(opacity=50);
 }
-.dijit_a11y .dijitInputLayoutContainer,
+
+/* images off, high-contrast mode styles */
+.dijit_a11y .dijitSpinnerButtonContainer,
 .dijit_a11y .dijitDialog {
 	opacity: 1 !important;
 	background-color: white !important;
 }
+
 .dijitDialog .closeText {
 	display:none;
-	
+	/* for the onhover border in high contrast on IE: */
 	position:absolute;
 }
+
 .dijit_a11y .dijitDialog .closeText {
 	display:inline;
 }
+
+/* Slider */
+
 .dijitSliderMoveable {
 	z-index:99;
 	position:absolute !important;
 	display:block;
 	vertical-align:middle;
 }
+
 .dijitSliderMoveableH {
 	right:0;
 }
-.dijit_a11y div.dijitSliderImageHandle,
+.dijitSliderMoveableV {
+	right:50%;
+}
+
+.dijit_a11y DIV.dijitSliderImageHandle,
 .dijitSliderImageHandle {
 	margin:0;
 	padding:0;
-	position:absolute !important;
+	position:relative !important;
 	border:8px solid gray;
 	width:0;
 	height:0;
+	cursor: pointer;
+}
+.dj_iequirks .dijit_a11y .dijitSliderImageHandle {
+	font-size: 0;
+}
+.dj_ie7 .dijitSliderImageHandle {
+	overflow: hidden; /* IE7 workaround to make slider handle VISIBLE in non-a11y mode */
+}
+.dj_ie7 .dijit_a11y .dijitSliderImageHandle {
+	overflow: visible; /* IE7 workaround to make slider handle VISIBLE in a11y mode */
 }
 .dijit_a11y .dijitSliderFocused .dijitSliderImageHandle {
 	border:4px solid #000;
 	height:8px;
 	width:8px;
 }
+
 .dijitSliderImageHandleV {
 	top:-8px;
-	left:-6px;
+	right: -50%;
 }
+
 .dijitSliderImageHandleH {
-	left:-8px;
+	left:50%;
 	top:-5px;
 	vertical-align:top;
 }
+
 .dijitSliderBar {
 	border-style:solid;
 	border-color:black;
+	cursor: pointer;
 }
+
 .dijitSliderBarContainerV {
 	position:relative;
 	height:100%;
 	z-index:1;
 }
+
 .dijitSliderBarContainerH {
 	position:relative;
 	z-index:1;
 }
+
 .dijitSliderBarH {
 	height:4px;
 	border-width:1px 0;
 }
+
 .dijitSliderBarV {
 	width:4px;
 	border-width:0 1px;
 }
+
 .dijitSliderProgressBar {
 	background-color:red;
 	z-index:1;
 }
+
 .dijitSliderProgressBarV {
 	position:static !important;
 	height:0%;
 	vertical-align:top;
 	text-align:left;
 }
+
 .dijitSliderProgressBarH {
 	position:absolute !important;
 	width:0%;
 	vertical-align:middle;
 	overflow:visible;
 }
+
 .dijitSliderRemainingBar {
 	overflow:hidden;
 	background-color:transparent;
 	z-index:1;
 }
+
 .dijitSliderRemainingBarV {
 	height:100%;
 	text-align:left;
 }
+
 .dijitSliderRemainingBarH {
 	width:100% !important;
 }
+
+/* the slider bumper is the space consumed by the slider handle when it hangs over an edge */
 .dijitSliderBumper {
 	overflow:hidden;
 	z-index:1;
 }
+
 .dijitSliderBumperV {
 	width:4px;
 	height:8px;
 	border-width:0 1px;
 }
+
 .dijitSliderBumperH {
 	width:8px;
 	height:4px;
 	border-width:1px 0;
 }
+
 .dijitSliderBottomBumper,
 .dijitSliderLeftBumper {
 	background-color:red;
 }
+
 .dijitSliderTopBumper,
 .dijitSliderRightBumper {
 	background-color:transparent;
 }
-.dijitSliderDecorationH {
+
+.dijitSliderDecoration {
 	text-align:center;
 }
-.dijitSlider .dijitSliderButton {
+.dijitSliderV TD {
+	position: relative; /* needed for IE+quirks+RTL+vertical (rendering bug) but add everywhere for custom styling consistency but this messes up IE horizontal sliders */
+}
+
+.dijitSliderDecorationH {
+	width: 100%;
+}
+
+.dijitSliderDecorationV {
+	height: 100%;
+}
+
+.dijitSliderButton {
 	font-family:monospace;
 	margin:0;
 	padding:0;
 	display:block;
 }
+
 .dijit_a11y .dijitSliderButtonInner {
 	visibility:visible !important;
 }
+
 .dijitSliderButtonContainer {
 	text-align:center;
-	height:0;
+	height:0;	/* ??? */
+}
+.dijitSliderButtonContainer * {
+	cursor: pointer;
 }
+
 .dijitSlider .dijitButtonNode {
 	padding:0;
 	display:block;
 }
+
 .dijitRuleContainer {
 	position:relative;
 	overflow:visible;
 }
+
 .dijitRuleContainerV {
 	height:100%;
 	line-height:0;
 	float:left;
 	text-align:left;
 }
+
 .dj_opera .dijitRuleContainerV {
 	line-height:2%;
 }
+
 .dj_ie .dijitRuleContainerV {
 	line-height:normal;
 }
+
 .dj_gecko .dijitRuleContainerV {
-	margin:0 0 1px 0; 
+	margin:0 0 1px 0; /* mozilla bug workaround for float:left,height:100% block elements */
 }
+
 .dijitRuleMark {
 	position:absolute;
 	border:1px solid black;
 	line-height:0;
 	height:100%;
 }
+
 .dijitRuleMarkH {
 	width:0;
 	border-top-width:0 !important;
 	border-bottom-width:0 !important;
 	border-left-width:0 !important;
 }
+
 .dijitRuleLabelContainer {
 	position:absolute;
 }
+
 .dijitRuleLabelContainerH {
 	text-align:center;
 	display:inline-block;
 }
+
 .dijitRuleLabelH {
 	position:relative;
 	left:-50%;
 }
+
+.dijitRuleLabelV {
+	/* so that long labels don't overflow to multiple rows, or overwrite slider itself */
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	overflow: hidden;
+}
+
 .dijitRuleMarkV {
 	height:0;
 	border-right-width:0 !important;
@@ -1225,152 +1822,161 @@ div.dijitTabBtnDisabled, .dj_ie div.dijitTabBtnDisabled {
 	width:100%;
 	left:0;
 }
+
 .dj_ie .dijitRuleLabelContainerV {
 	margin-top:-.55em;
 }
+
+.dijit_a11y .dijitSliderReadOnly,
+.dijit_a11y .dijitSliderDisabled {
+	opacity:0.6;
+}
+.dj_ie .dijit_a11y .dijitSliderReadOnly .dijitSliderBar,
+.dj_ie .dijit_a11y .dijitSliderDisabled .dijitSliderBar {
+	filter: alpha(opacity=40);
+}
+
+/* + and - Slider buttons: override theme settings to display icons */
+.dijit_a11y .dijitSlider .dijitSliderButtonContainer DIV {
+	font-family: monospace; /* otherwise hyphen is larger and more vertically centered */
+	font-size: 1em;
+	line-height: 1em;
+	height: auto;
+	width: auto;
+	margin: 0px 4px;
+}
+
+/* Icon-only buttons (often in toolbars) still display the text in high-contrast mode */
 .dijit_a11y .dijitButtonContents .dijitButtonText,
 .dijit_a11y .dijitTab .tabLabel {
 	display: inline !important;
 }
-.dj_ie7 .dijitButtonNode > BUTTON.dijitButtonContents > * {
-	position: relative; 
-}
+
+/* TextArea, SimpleTextArea */
 .dijitTextArea {
 	width:100%;
-	overflow-y: auto;	
+	overflow-y: auto;	/* w/out this IE's SimpleTextArea goes to overflow: scroll */
 }
 .dijitTextArea[cols] {
-	width:auto; 
+	width:auto; /* SimpleTextArea cols */
 }
 .dj_ie .dijitTextAreaCols {
 	width:auto;
 }
-.dijitTextArea > DIV {
-	text-decoration:none;
-	overflow:auto;
-	min-height: 1.40em;
-}
-.dj_ie .dijitTextArea p {
-	margin-top:0;
-	margin-bottom:0;
-	line-height: normal !important;
-}
+
+/* Toolbar
+ * Note that other toolbar rules (for objects in toolbars) are scattered throughout this file.
+ */
+
 .dijitToolbarSeparator {
 	height: 18px;
 	width: 5px;
 	padding: 0 1px;
 	margin: 0;
 }
+
+/* Editor */
 .dijitIEFixedToolbar {
 	position:absolute;
-	
+	/* top:0; */
 	top: expression(eval((document.documentElement||document.body).scrollTop));
 }
-.RichTextEditable {
-	display: block;	
+
+.dijitEditor {
+	display: block;	/* prevents glitch on FF with InlineEditBox, see #8404 */
+}
+
+.dijitEditorDisabled,
+.dijitEditorReadOnly {
+	color: gray;
 }
+
+/* TimePicker */
+
 .dijitTimePickerItemInner {
 	text-align:center;
 	border:0;
 	padding:2px 8px 2px 8px;
 }
+
 .dijitTimePickerTick,
 .dijitTimePickerMarker {
 	border-bottom:1px solid gray;
 }
+
 .dijitTimePicker .dijitDownArrowButton {
 	border-top: none !important;
 }
+
 .dijitTimePickerTick {
 	color:#CCC;
 }
+
 .dijitTimePickerMarker {
 	color:black;
 	background-color:#CCC;
 }
+
 .dijitTimePickerItemSelected {
 	font-weight:bold;
 	color:#333;
 	background-color:#b7cdee;
 }
+
 .dijitTimePickerItemHover {
 	background-color:gray;
 	color:white;
 	cursor:pointer;
 }
-.dijit_a11y .dijitTimePickerItem {
-	border-bottom:1px solid #333;
+.dijit_a11y .dijitTimePickerItemSelected .dijitTimePickerItemInner {
+	border: solid 4px black;
 }
+.dijit_a11y .dijitTimePickerItemHover .dijitTimePickerItemInner {
+	border: dashed 4px black;
+}
+
+
 .dijitToggleButtonIconChar {
+	/* character (instead of icon) to show that ToggleButton is checked */
 	display:none !important;
 }
-.dijit_a11y .dijitToggleButtonIconChar {
+.dijit_a11y .dijitToggleButton .dijitToggleButtonIconChar {
 	display:inline !important;
-}
-.dijit_a11y .dijitToggleButtonIconChar {
 	visibility:hidden;
 }
+.dj_ie6 .dijitToggleButtonIconChar, .dj_ie6 .tabStripButton .dijitButtonText {
+	font-family: "Arial Unicode MS";	/* otherwise the a11y character (checkmark, arrow, etc.) appears as a box */
+}
 .dijit_a11y .dijitToggleButtonChecked .dijitToggleButtonIconChar {
+	display: inline !important; /* In high contrast mode, display the check symbol */
 	visibility:visible !important;
 }
+
 .dijitArrowButtonChar {
-	display:none !important;
+        display:none !important;
 }
 .dijit_a11y .dijitArrowButtonChar {
-	display:inline !important;
-}
-.dijitInputLayoutContainer {
-	position: relative;
-	overflow: hidden;
-}
-.dijitSpinnerButtonContainer {
-	float: right;
-	width: 18px;
-	position: relative;
-	overflow: hidden;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	height: 50%;
-	width: 16px;
-	overflow: hidden;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButtonInner {
-	overflow: hidden;
-	line-height: 50%;
-}
-.dijit_a11y .dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	width: 100%;
-}
-.dijit_a11y .dijitSpinner .dijitArrowButton .dijitArrowButtonChar {
-	font-size: 0.4em;
-	vertical-align: top;
-}
-.dijit_a11y .dijitSpinnerButtonContainer {
-	width: 0.5em;
-	margin-left: 2px;
-	overflow: visible;
+        display:inline !important;
 }
-.dijit_a11y .dijitSpinnerButtonContainer .dijitButtonNode {
-	border-width: 1px 0px 0px 1px;
-	border-style: solid !important;
+
+.dijit_a11y .dijitDropDownButton .dijitArrowButtonInner,
+.dijit_a11y .dijitComboButton .dijitArrowButtonInner {
+	display:none !important;
 }
+
+/* Select */
 .dijitSelect {
 	margin: 0.2em;
+	border-collapse: collapse;
 }
 .dj_ie .dijitSelect,
 .dj_ie7 .dijitSelect,
 .dj_iequirks .dijitSelect {
-	vertical-align: middle; 
+	vertical-align: middle; /* Set this back for what we hack in dijit inline */
 }
 .dj_ie8 .dijitSelect .dijitButtonText {
 	vertical-align: top;
 }
-.dijitSelect .dijitButtonNode {
-	text-align: left;
-}
-.dijitRtl .dijitSelect .dijitButtonNode {
-	text-align: right;
-}
 .dijitToolbar .dijitSelect {
 	margin: 0;
 }
@@ -1386,70 +1992,56 @@ div.dijitTabBtnDisabled, .dj_ie div.dijitTabBtnDisabled {
 .dijitSelect .dijitButtonContents {
 	padding: 0px;
 	background: transparent none;
+	white-space: nowrap;
+	text-align: left;
 }
 .dijitSelectFixedWidth .dijitButtonContents {
 	width: 100%;
 }
-.dijitSelect .dijitArrowButton {
-	width: 16px;
+
+.dijitSelectMenu .dijitMenuItemIcon {
+	/* avoid blank area in left side of menu (since we have no icons) */
+	display:none;
 }
 .dj_ie6 .dijitSelectMenu .dijitMenuItemLabel,
 .dj_ie7 .dijitSelectMenu .dijitMenuItemLabel {
-	
+	/* Set back to static due to bug in ie6/ie7 - See Bug #9651 */
 	position: static;
 }
+
+/* Fix the baseline of our label (for multi-size font elements) */
 .dijitSelectLabel *
 {
 	vertical-align: baseline;
 }
+
+/* Styling for the currently-selected option (rich text can mess this up) */
 .dijitSelectSelectedOption * {
 	font-weight: bold;
 }
+
+/* Fix the styling of the dropdown menu to be more combobox-like */
 .dijitSelectMenu {
 	border-width: 1px;
 }
-.dijitSelect .dijitButtonContents {
-	white-space: nowrap;
-}
+
+/* Style the different areas of the button to look like a "real" dropdown */
+/* Remove margins on the sub-table */
 .dijitSelectMenu .dijitMenuTable {
 	margin: 0px;
 	background-color: transparent;
 }
-.dijitTextBoxReadOnly,
-.dijitComboBoxReadOnly,
-.dijitSpinnerReadOnly,
-.dijitTextAreaReadOnly,
-.dijitTextBoxDisabled,
-.dijitComboBoxDisabled,
-.dijitSpinnerDisabled,
-.dijitTextAreaDisabled {
-	color: gray;
-}
-.dj_webkit .dijitTextBoxDisabled INPUT,
-.dj_webkit .dijitComboBoxDisabled INPUT,
-.dj_webkit .dijitSpinnerDisabled INPUT {
-	color: #eee;
-}
-.dj_webkit INPUT.dijitTextBoxDisabled,
-.dj_webkit TEXTAREA.dijitTextAreaDisabled {
-	color: #333; 
-}
-.dijit_a11y .dijitSliderReadOnly,
-.dijit_a11y .dijitSliderDisabled {
-	opacity:0.6;
-}
-.dj_ie .dijit_a11y .dijitSliderReadOnly .dijitSliderBar,
-.dj_ie .dijit_a11y .dijitSliderDisabled .dijitSliderBar {
-	filter: alpha(opacity=40);
-}
-.dijit_a11y .dijitSlider .dijitSliderButtonContainer DIV {
-	font-family: monospace; 
-	font-size: 1em;
-	line-height: 1em;
-	height: auto;
-	width: auto;
-	margin: 0px 4px;
-}
+
+/* Used in cases, such as FullScreen plugin, when we need to force stuff to static positioning. */
 .dijitForceStatic {
-    position: static !important;
+	position: static !important;
+}
+
+/**** Disabled cursor *****/
+.dijitReadOnly *,
+.dijitDisabled *,
+.dijitReadOnly,
+.dijitDisabled {
+	/* a region the user would be able to click on, but it's disabled */
+	cursor: default;
 }
diff --git a/dijit/themes/dijit_rtl.css b/dijit/themes/dijit_rtl.css
index 8af6f2f..f777b4c 100644
--- a/dijit/themes/dijit_rtl.css
+++ b/dijit/themes/dijit_rtl.css
@@ -1,82 +1,126 @@
-.dj_gecko-rtl .dijitInputField {
-	direction: ltr; 
-}
-.dj_gecko-rtl .dijitInputField * {
-	direction: rtl; 
-}
-.dijitRtl .dijitMenuItem {
+.dijitRtl .dijitPlaceHolder {
+	left: auto;
+	right: 0;
+}
+
+/* Menu */
+
+.dijitMenuItemRtl {
 	text-align: right;
 }
-.dijitRtl .dijitComboBox .dijitInputField {
-	border-right-width:1px !important;
-	border-left-width:0 !important;
+
+/* Button */
+
+.dj_iequirks .dijitComboButtonRtl BUTTON {
+	/* workaround bug where label invisible (themeTesterQuirk.html?dir=rtl) */
+	float:left;
+}
+
+/* TextBox, ComboBox, Spinner */
+
+.dijit_a11y .dijitTextBoxRtl .dijitValidationContainer,
+.dijitTextBoxRtl .dijitSpinnerButtonContainer,
+.dijitComboBoxRtl .dijitArrowButtonContainer {
+	/* combobox and spinner: line between the input area and the drop down button */
+	border-right-width: 1px !important;
+	border-right-style: solid !important;
+	border-left-width: 0px !important;
+	border-left-style: none !important;
+}
+.dijit_a11y .dijitTextBoxRtl .dijitValidationContainer,
+.dijit_a11y .dijitTextBoxRtl .dijitSpinnerButtonContainer,
+.dijit_a11y .dijitComboBoxRtl .dijitArrowButtonContainer {
+	border-right: 1px solid black !important;
+	border-left: 0px none black !important;
+}
+
+.dijitSpinnerRtl .dijitSpinnerButtonContainer .dijitArrowButton {
+	right: 0;
+	left: auto;
+}
+
+.dijitTextBoxRtl .dijitSpinnerButtonContainer,
+.dijitTextBoxRtl .dijitValidationContainer,
+.dijitTextBoxRtl .dijitArrowButtonContainer {
+	float: left;
 }
-.dijitRtl .dijitCalendarNextYear {
+
+/* Calendar */
+
+.dijitCalendarRtl .dijitCalendarNextYear {
 	margin:0 0.55em 0 0;
 }
-.dijitRtl .dijitCalendarPreviousYear {
+
+.dijitCalendarRtl .dijitCalendarPreviousYear {
 	margin:0 0 0 0.55em;
 }
-.dijitRtl .dijitProgressBarFull .dijitProgressBarLabel {
-	right:0; 
-}
-.dijitRtl .dijitSliderImageHandleV {
+
+
+/* Slider */
+
+.dijitSliderRtl .dijitSliderImageHandleV {
 	left:auto;
-	right:-6px;
 }
-.dj_ie-rtl .dijitSliderImageHandleV {
-	right:-10px;
+
+.dijitSliderRtl .dijitSliderImageHandleH {
+	left:-50%;
 }
-.dijitRtl .dijitSliderMoveableH {
+
+.dijitSliderRtl .dijitSliderMoveableH {
 	right:auto;
 	left:0;
 }
-.dijitRtl .dijitRuleContainerV {
+
+.dijitSliderRtl .dijitRuleContainerV {
 	float:right;
 }
-.dj_gecko-rtl .dijitRuleContainerV {
-	float:left;
-}
-.dj_ie-rtl .dijitRuleContainerV {
+
+.dj_ie .dijitSliderRtl .dijitRuleContainerV {
 	text-align:right;
 }
-.dj_ie-rtl .dijitRuleLabelV {
+
+.dj_ie .dijitSliderRtl .dijitRuleLabelV {
 	text-align:left;
 }
-.dj_ie-rtl .dijitRuleLabelH {
+
+.dj_ie .dijitSliderRtl .dijitRuleLabelH {
 	zoom:1;
 }
-.dj_ie-rtl .dijitSliderProgressBarH {
-	right:0;
-	left:auto;
-}
-.dj_gecko-rtl .dijitSliderProgressBarH {
+
+.dijitSliderRtl .dijitSliderProgressBarH {
+	/* workarounds for IE and FF */
 	float:right;
 	right:0;
 	left:auto;
 }
-.dijitRtl .dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	right: auto;
-	left: 0;
-	border-width: 0 1px 0 0 !important;
-}
-.dijitRtl .dijitSpinnerButtonContainer {
-	float: left;
-}
-.dijitRtl .dijit_a11y .dijitSpinnerButtonContainer {
-	margin-left: none;
-	margin-right: 2px;
-}
-.dijitRtl DIV.dijitArrowButton, .dijitRtl .dijitValidationIcon, .dijitRtl .dijitValidationIconText {
-	float: left;
-}
+
+/* ContentPane*/
 .dijitRtl .dijitContentPaneLoading, .dijitRtl .dijitContentPaneError {
 	background-position:right;
 	padding-right:25px;
 }
-.dijitRtl .dijitTabContainer .tabStripMenuButton {
-	float: left;
-}
-.dj_iequirks-rtl .dijitComboButton BUTTON {
-        float:left;
-}
+
+/* TabContainer */
+
+.dijitTabRtl .dijitTabCloseButton {
+	margin-left: 0px;
+	margin-right: 1em;
+}
+
+/* TimePicker */
+.dj_ie .dijitTimePickerRtl .dijitTimePickerItem {
+	width:100%;
+}
+
+
+/* ColorPalette */
+.dijitColorPaletteRtl .dijitColorPaletteUnder {
+	/* needed in RTL mode when DropDownButton expands the ColorPalette beyond it's natural width */
+	left: auto;
+	right: 0;
+}
+
+/* Select */
+.dijitSelectRtl .dijitButtonContents {
+	text-align: right;
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/Calendar.css b/dijit/themes/nihilo/Calendar.css
index 6ead491..81f3f71 100644
--- a/dijit/themes/nihilo/Calendar.css
+++ b/dijit/themes/nihilo/Calendar.css
@@ -1,6 +1,7 @@
+/* Calendar*/
 
 .nihilo .dijitCalendarIncrementControl {
-	
+	/* next/prev month buttons */
 	width:15px;
 	height:15px;
 	background-image: url("images/spriteRoundedIconsSmall.png");
@@ -10,15 +11,18 @@
 	font-size:.1em;
 	background-image: url("images/spriteRoundedIconsSmall.gif");
 }
+
 .nihilo .dijitA11ySideArrow {
 	display: none;
 }
+
 .nihilo .dijitCalendarDecrease {
 	background-position: top left;
 }
 .nihilo .dijitCalendarIncrease {
 	background-position: -30px top;
 }
+
 .nihilo table.dijitCalendarContainer {
 	font-size: 100%;
 	border-spacing: 0;
@@ -26,8 +30,9 @@
 	border: 1px solid #ccc;
 	margin: 0;
 }
+
 .nihilo .dijitCalendarMonthContainer th {
-	
+	/* month header cell */
 	background:#d3d3d3 url("images/titleBar.png") repeat-x top;
 	padding-top:.3em;
 	padding-bottom:.2em;
@@ -36,9 +41,11 @@
 .dj_ie6 .nihilo .dijitCalendarMonthContainer th {
 	padding-top:.2em;
 	padding-bottom:.1em;
+
 }
+
 .nihilo .dijitCalendarDayLabelTemplate {
-	
+	/* day of week labels */
 	background:#fefefe;
 	font-weight:normal;
 	padding-top:.15em;
@@ -47,15 +54,18 @@
 	color:#293a4b;
 	text-align:center;
 }
+
 .nihilo .dijitCalendarBodyContainer {
 	border-bottom: 1px solid #eeeeee;
 }
+
 .nihilo .dijitCalendarMonthLabel {
 	color:#293a4b;
 	font-weight: bold;
 }
+
 .nihilo .dijitCalendarDateTemplate {
-	
+	/* style for each day cell */
 	font-size: 0.9em;
 	font-weight: bold;
 	text-align: center;
@@ -64,66 +74,65 @@
 	background-color: #fdfdfd;
 	border:#fdfdfd solid 1px !important;
 }
+
 .dj_ie .nihilo .dijitCalendarDateTemplate {
 	padding: 0.1em .33em 0.02em .33em;
 }
+
 .nihilo .dijitCalendarPreviousMonth,
 .nihilo .dijitCalendarNextMonth 		{
-	
+	/* days that are part of the previous or next month */
 	color:#999999;
 	background-color:#f5f5f5 !important;
 	border:#f5f5f5 solid 1px !important;
 }
-.nihilo .dijitCalendarPreviousMonthDisabled,
-.nihilo .dijitCalendarNextMonthDisabled	{
-	
-	background-color:#a4a5a6 !important;
-}
+
 .nihilo .dijitCalendarCurrentMonth {
-	
-}
-.nihilo .dijitCalendarCurrentMonthDisabled {
-	
-	background-color:#bbbbbc !important;
+	/* days that are part of this month */
 }
+
 .nihilo .dijitCalendarDisabledDate {
-	
-	
 	text-decoration:line-through !important;
-	cursor:default !important;
 }
+
 .nihilo .dijitCalendarCurrentDate {
-	
+	/* cell for today's date */
 	text-decoration:underline;
 	font-weight:bold;
 }
+
 .nihilo .dijitCalendarSelectedDate {
-	
+	/* cell for the selected date */
 	background-color:#ffe284 !important;
 	color:black !important;
 	border:#f7c95c solid 1px !important;
 }
+
+
 .nihilo .dijitCalendarYearContainer {
-	
+	/* footer of the table that contains the year display/selector */
 	background:white url("images/titleBar.png") repeat-x top;
 }
+
 .nihilo .dijitCalendarYearLabel {
-	
+	/* container for all of 3 year labels */
 	margin:0;
 	padding:0.4em 0 0.25em 0;
 	text-align:center;
 }
+
 .nihilo .dijitCalendarSelectedYear {
-	
+	/* label for selected year */
 	color:black;
 	padding:0.2em;
 	padding-bottom:0.1em;
 	background-color:#ffe284 !important;
 	border:#f7c95c solid 1px !important;
 }
+
 .nihilo .dijitCalendarNextYear,
 .nihilo .dijitCalendarPreviousYear {
-	
+	/* label for next/prev years */
 	color:black !important;
 	font-weight:normal;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/Calendar_rtl.css b/dijit/themes/nihilo/Calendar_rtl.css
index 245d93f..7b29bac 100644
--- a/dijit/themes/nihilo/Calendar_rtl.css
+++ b/dijit/themes/nihilo/Calendar_rtl.css
@@ -1,7 +1,9 @@
+/* Calendar */
 
 .dijitRtl .nihilo .dijitCalendarDecrease {
 	background-position: -30px top;
 }
+
 .dijitRtl .nihilo .dijitCalendarIncrease {
 	background-position: 0px top;
 }
diff --git a/dijit/themes/nihilo/ColorPalette.css b/dijit/themes/nihilo/ColorPalette.css
index 328bc84..59a4689 100644
--- a/dijit/themes/nihilo/ColorPalette.css
+++ b/dijit/themes/nihilo/ColorPalette.css
@@ -2,4 +2,4 @@
 	border:1px solid #d3d3d3;
 	background:#fff;
 	-moz-border-radius: 0px !important;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/Common.css b/dijit/themes/nihilo/Common.css
index c894dea..4986990 100644
--- a/dijit/themes/nihilo/Common.css
+++ b/dijit/themes/nihilo/Common.css
@@ -1,13 +1,17 @@
-
+/* DnD avatar-specific settings */
+/* For now it uses a default set of rules. Some other DnD classes can be modified as well. */
 .nihilo .dojoDndItemBefore {
 	border-top: 2px solid #369;
 }
+
 .nihilo .dojoDndItemAfter {
 	border-bottom: 2px solid #369;
 }
+
 .nihilo .dojoDndItemOver {
 	cursor:pointer;
 }
+
 .nihilo table.dojoDndAvatar { -moz-border-radius: 0; border: 1px solid #ccc; border-collapse: collapse; background-color: #fff; font-size: 75%; color: black;}
 .nihilo .dojoDndAvatar td	{ border: none; }
 .nihilo .dojoDndAvatar tr	{ border: none; }
diff --git a/dijit/themes/nihilo/Dialog.css b/dijit/themes/nihilo/Dialog.css
index b5ade7e..64fbaf0 100644
--- a/dijit/themes/nihilo/Dialog.css
+++ b/dijit/themes/nihilo/Dialog.css
@@ -1,3 +1,4 @@
+/* Dialog */
 
 .nihilo .dijitDialog {
 	background: #eee;
@@ -5,28 +6,31 @@
 	-webkit-box-shadow: 0px 5px 10px #adadad;
 	padding: 0px;
 }
+
 .nihilo .dijitDialog .dijitDialogTitle {
-	
+	/* typography and styling of the dialog title */
 	font-size: 0.9em;
 	color: #3243C5F;
 	font-weight: bold;
 	padding: 0px 4px;
 }
+
 .nihilo .dijitDialog .dijitDialogPaneContent {
 	background: #ffffff;
-	border:none;
-	border-top: 1px solid #d3d3d3; 
+	border-top: 1px solid #d3d3d3;
 	padding:10px;
+
 }
+
 .nihilo .dijitDialogTitleBar {
-	
+	/* outer container for the titlebar of the dialog */
 	background: #fafafa url("images/titleBar.png") repeat-x top left;
 	padding: 5px 6px 3px 6px;
-	cursor: move;
-	outline:0; 
+	outline:0; /* remove this line if keyboard focus on dialog startup is an issue. tab still takes you to first focusable element */
 }
+
 .nihilo .dijitDialogCloseIcon {
-	
+	/* the default close icon for the dialog */
 	background-image: url("images/spriteRoundedIconsSmall.png");
 	background-repeat: no-repeat;
 	background-position: -60px 0px;
@@ -36,56 +40,75 @@
 	top: 4px;
 	height: 15px;
 	width: 15px;
-	cursor: pointer;
 }
 .dj_ie6 .nihilo .dijitDialogCloseIcon {
 	background-image: url("images/spriteRoundedIconsSmall.gif");
 }
-.nihilo .dijitDialogCloseIcon-hover {
+.nihilo .dijitDialogCloseIconHover {
 	background-position: -60px -15px;
 }
+
+/* Tooltip and TooltipDialog */
+
 .nihilo .dijitTooltip,
 .nihilo .dijitTooltipDialog {
-	
-	background: transparent;	
+	/* the outermost dom node, holding the connector and container */
+	background: transparent;	/* make the area on the sides of the arrow transparent */
 }
+
 .dijitTooltipBelow {
-	
+	/* leave room for arrow above content */
 	padding-top: 10px;
 }
+
 .dijitTooltipAbove {
-	
+	/* leave room for arrow below content */
 	padding-bottom: 10px;
 }
+
 .nihilo .dijitTooltipContainer {
-	
+	/*
+		The part with the text.
+
+		NOTE:
+			FF doesn't clip images used as CSS bgs if you specify a border
+			radius. If you use a solid color, it does. Webkit gets it right.
+			Sigh.
+		background: #ffffff url("images/popupMenuBg.gif") repeat-x bottom left;
+	*/
 	background-color: #fff;
 	border:1px solid #d3d3d3;
 	padding:0.45em;
 }
+
 .nihilo .dijitTooltipConnector {
-	
+	/* the arrow piece */
 	border:0px;
 	z-index: 2;
 }
+
 .nihilo .dijitTooltipABRight .dijitTooltipConnector {
-	
+	/* above or below tooltip, but the arrow appears on the right,
+		and the right edges of target and tooltip are aligned rather than the left */
 	left: auto !important;
 	right: 6px;
 }
+
 .nihilo .dijitTooltipBelow .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips below an element */
 	top: 0px;
 	left: 6px;
 	background:url("images/tooltipConnectorUp.png") no-repeat top left;
 	width:17px;
 	height:11px;
 }
+
 .dj_ie .nihilo .dijitTooltipBelow .dijitTooltipConnector {
 	background-image: url("images/tooltipConnectorUp.gif");
 }
+
 .nihilo .dijitTooltipAbove .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips above an element */
 	bottom: 0px;
 	left: 6px;
 	background:url("images/tooltipConnectorDown.png") no-repeat top left;
@@ -98,6 +121,7 @@
 .dj_ie6 .nihilo .dijitTooltipAbove .dijitTooltipConnector {
 	bottom: -5px;
 }
+
 .nihilo .dijitTooltipLeft {
 	padding-right: 10px;
 }
@@ -105,7 +129,7 @@
 	padding-left: 11px;
 }
 .nihilo .dijitTooltipLeft .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips to the left of an element, bottom borders aligned */
 	right: 0px;
 	bottom: 3px;
 	background:url("images/tooltipConnectorRight.png") no-repeat top left;
@@ -115,11 +139,12 @@
 .dj_ie .nihilo .dijitTooltipLeft .dijitTooltipConnector {
 	background-image: url("images/tooltipConnectorRight.gif");
 }
+
 .nihilo .dijitTooltipRight {
 	padding-left: 10px;
 }
 .nihilo .dijitTooltipRight .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips to the right of an element, bottom borders aligned */
 	left: 0px;
 	bottom: 3px;
 	background:url("images/tooltipConnectorLeft.png") no-repeat top left;
@@ -129,3 +154,4 @@
 .dj_ie .nihilo .dijitTooltipRight .dijitTooltipConnector {
 	background-image: url("images/tooltipConnectorLeft.gif");
 }
+
diff --git a/dijit/themes/nihilo/Dialog_rtl.css b/dijit/themes/nihilo/Dialog_rtl.css
index 105d504..5e0cffc 100644
--- a/dijit/themes/nihilo/Dialog_rtl.css
+++ b/dijit/themes/nihilo/Dialog_rtl.css
@@ -1,3 +1,4 @@
+/* Dialog */
 
 .dijitRtl .nihilo .dijitDialogTitleBar .dijitDialogCloseIcon {
 	right: auto;
diff --git a/dijit/themes/nihilo/Editor.css b/dijit/themes/nihilo/Editor.css
index 54e69e3..108aae7 100644
--- a/dijit/themes/nihilo/Editor.css
+++ b/dijit/themes/nihilo/Editor.css
@@ -1,65 +1,16 @@
-.dijitIEFixedToolbar {
-	position:absolute;
-	
-	top: expression(eval((document.documentElement||document.body).scrollTop));
-}
 .nihilo .dijitToolbar .dijitToolbarSeparator {
-	background: url('images/editor.gif');
+	background: url('../../icons/images/editorIconsEnabled.png'); /* separator in editor icons sprite image - enabled state */
 }
+
+/**** ICONS *****/
+
 .nihilo .dijitEditorIcon {
-	background-image: url('images/editor.gif'); 
+	background-image: url('../../icons/images/editorIconsEnabled.png'); /* editor icons sprite image - enabled state */
 	background-repeat: no-repeat;
 	width: 18px;
 	height: 18px;
 	text-align: center;
 }
 .nihilo .dijitDisabled .dijitEditorIcon {
-	background-image: url('images/editorDisabled.gif'); 
+	background-image: url('../../icons/images/editorIconsDisabled.png'); /* editor icons sprite image - disabled state */
 }
-.nihilo .dijitEditorIconSep { background-position: 0px; }
-.nihilo .dijitEditorIconBackColor { background-position: -18px; }
-.nihilo .dijitEditorIconBold { background-position: -36px; }
-.nihilo .dijitEditorIconCancel { background-position: -54px; }
-.nihilo .dijitEditorIconCopy { background-position: -72px; }
-.nihilo .dijitEditorIconCreateLink { background-position: -90px; }
-.nihilo .dijitEditorIconCut { background-position: -108px; }
-.nihilo .dijitEditorIconDelete { background-position: -126px; }
-.nihilo .dijitEditorIconForeColor { background-position: -144px; }
-.nihilo .dijitEditorIconHiliteColor { background-position: -162px; }
-.nihilo .dijitEditorIconIndent { background-position: -180px; }
-.nihilo .dijitEditorIconInsertHorizontalRule { background-position: -198px; }
-.nihilo .dijitEditorIconInsertImage { background-position: -216px; }
-.nihilo .dijitEditorIconInsertOrderedList { background-position: -234px; }
-.nihilo .dijitEditorIconInsertTable { background-position: -252px; }
-.nihilo .dijitEditorIconInsertUnorderedList { background-position: -270px; }
-.nihilo .dijitEditorIconItalic { background-position: -288px; }
-.nihilo .dijitEditorIconJustifyCenter { background-position: -306px; }
-.nihilo .dijitEditorIconJustifyFull { background-position: -324px; }
-.nihilo .dijitEditorIconJustifyLeft { background-position: -342px; }
-.nihilo .dijitEditorIconJustifyRight { background-position: -360px; }
-.nihilo .dijitEditorIconLeftToRight { background-position: -378px; }
-.nihilo .dijitEditorIconListBulletIndent { background-position: -396px; }
-.nihilo .dijitEditorIconListBulletOutdent { background-position: -414px; }
-.nihilo .dijitEditorIconListNumIndent { background-position: -432px; }
-.nihilo .dijitEditorIconListNumOutdent { background-position: -450px; }
-.nihilo .dijitEditorIconOutdent { background-position: -468px; }
-.nihilo .dijitEditorIconPaste { background-position: -486px; }
-.nihilo .dijitEditorIconRedo { background-position: -504px; }
-.nihilo .dijitEditorIconRemoveFormat { background-position: -522px; }
-.nihilo .dijitEditorIconRightToLeft { background-position: -540px; }
-.nihilo .dijitEditorIconSave { background-position: -558px; }
-.nihilo .dijitEditorIconSpace { background-position: -576px; }
-.nihilo .dijitEditorIconStrikethrough { background-position: -594px; }
-.nihilo .dijitEditorIconSubscript { background-position: -612px; }
-.nihilo .dijitEditorIconSuperscript { background-position: -630px; }
-.nihilo .dijitEditorIconUnderline { background-position: -648px; }
-.nihilo .dijitEditorIconUndo { background-position: -666px; }
-.nihilo .dijitEditorIconWikiword { background-position: -684px; }
-.nihilo .dijitEditorIconToggleDir { background-position: -540px; }
-.nihilo .dijitEditorIconTabIndent { background-position: -702px; }
-.nihilo .dijitEditorIconSelectAll { background-position: -720px; }
-.nihilo .dijitEditorIconUnlink { background-position: -738px; }
-.nihilo .dijitEditorIconFullScreen { background-position: -756px; }
-.nihilo .dijitEditorIconViewSource { background-position: -774px; }
-.nihilo .dijitEditorIconPrint { background-position: -792px; }
-.nihilo .dijitEditorIconNewPage { background-position: -810px; }
diff --git a/dijit/themes/nihilo/Editor_rtl.css b/dijit/themes/nihilo/Editor_rtl.css
index 7d77754..ca1cc0c 100644
--- a/dijit/themes/nihilo/Editor_rtl.css
+++ b/dijit/themes/nihilo/Editor_rtl.css
@@ -1,10 +1,9 @@
-
+/* Editor */
 .dijitRtl .nihilo .dijitEditorIcon {
-	background-image: url('images/editor_rtl.gif'); 
+	background-image: url('../../icons/images/editorIconsEnabled_rtl.png'); /* editor icons sprite image - enabled state */
 }
 .dijitRtl .nihilo .dijitDisabled .dijitEditorIcon {
-	background-image: url('images/editorDisabled_rtl.gif'); 
-}
-.dijitRtl .nihilo .dijitToolbar .dijitToolbarSeparator {
-	background-image: url('images/editor_rtl.gif');
+	background-image: url('../../icons/images/editorIconsDisabled_rtl.png'); /* editor icons sprite image - disabled state */
 }
+
+
diff --git a/dijit/themes/nihilo/Menu.css b/dijit/themes/nihilo/Menu.css
index b530a90..6d128ab 100644
--- a/dijit/themes/nihilo/Menu.css
+++ b/dijit/themes/nihilo/Menu.css
@@ -1,4 +1,5 @@
 
+/* Menu */
 .nihilo .dijitMenu,
 .nihilo .dijitMenuBar {
 	border: 1px solid #d3d3d3;
@@ -6,9 +7,11 @@
 	padding: 0px;
 	background-color: #fff;
 }
+
 .nihilo .dijitBorderContainer .dijitMenuBar {
 	border: 1px #ccc solid;
 }
+
 .nihilo .dijitMenuItem {
 	font-family: sans-serif;
 	margin: 0px;
@@ -17,21 +20,25 @@
 .nihilo .dijitMenuBar .dijitMenuItem {
 	padding: 4px 5px;
 }
+
 .nihilo .dijitMenuPreviousButton, .nihilo .dijitMenuNextButton {
 	font-style: italic;
 }
 .nihilo .dijitMenuItem TD {
 	padding:1px;
 }
+
 .nihilo .dijitMenuPassive .dijitMenuItemHover,
 .nihilo .dijitMenuItemSelected {
-	background-color: #ffe284; 
+	background-color: #ffe284; /* #95a0b0; #555555; #aaaaaa; #646464;  #60a1ea; #848484; */
 	color: #243C5F;
 }
+
 .nihilo .dijitMenuItemIcon {
 	width: 15px;
 	height: 15px;
 }
+
 .nihilo .dijitMenuExpand {
 	width:15px;
 	height:15px;
@@ -41,22 +48,30 @@
 .dj_ie6 .nihilo .dijitMenuExpand {
 	background-image:url('images/spriteRoundedIconsSmall.gif');
 }
+
 .nihilo .dijitMenuSeparator {
 	height: 1px;
 }
+
+/* separator can be two pixels -- set border of either one to 0px to have only one */
 .nihilo .dijitMenuSeparatorTop {
-	border-bottom: 1px solid #fff; 
+	border-bottom: 1px solid #fff; /*97adcb; */
 }
+
 .nihilo .dijitMenuSeparatorBottom {
 	border-top: 1px solid #d3d3d3;
 }
+
+/* the checked menu item */
 .nihilo .dijitCheckedMenuItemIconChar {
 	display: none;
 }
+
 .nihilo .dijitCheckedMenuItemIcon {
 	background-image: url('images/spriteCheckbox.gif');
 	background-position: -80px;
 }
+
 .nihilo .dijitCheckedMenuItemChecked .dijitCheckedMenuItemIcon {
 	background-position: -64px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/Menu_rtl.css b/dijit/themes/nihilo/Menu_rtl.css
index 06fccbf..f07fbd6 100644
--- a/dijit/themes/nihilo/Menu_rtl.css
+++ b/dijit/themes/nihilo/Menu_rtl.css
@@ -1,8 +1,10 @@
+/* Menu */
 
 .dijitRtl .nihilo .dijitMenuItem .dijitMenuItemIcon {
 	padding-left: 3px;
 	padding-right: 0px;
 }
+
 .dijitRtl .nihilo .dijitMenuItem .dijitMenuExpand {
 	background-position: 0px top;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/ProgressBar.css b/dijit/themes/nihilo/ProgressBar.css
index 7713aeb..aaa49ea 100644
--- a/dijit/themes/nihilo/ProgressBar.css
+++ b/dijit/themes/nihilo/ProgressBar.css
@@ -1,24 +1,33 @@
 
+/****
+		dijit.ProgressBar
+ ****/
+
 .nihilo .dijitProgressBar {
 	margin:2px 0px 2px 0px;
 }
+
 .nihilo .dijitProgressBarEmpty{
-	
+	/* outer container and background of the bar that's not finished yet*/
 	background:#fff url("images/progressBarEmpty.png") repeat-x center center;
 	border-color: #f8d582 #f8d582 #f8d582 #f8d582;
 }
+
 .nihilo .dijitProgressBarTile{
-	
+	/* inner container for finished portion when in 'tile' (image) mode */
 	background:#f0f0f0 url("images/progressBarFull.png") repeat-x center center;
 }
+
 .nihilo .dijitProgressBarFull {
 	border-right:1px solid #f8d582;
 }
+
 .nihilo .dijitProgressBarLabel {
-	
+	/* Set to a color that contrasts with both the "Empty" and "Full" parts. */
 	color:#293a4b;
 }
+
 .nihilo .dijitProgressBarIndeterminate .dijitProgressBarTile {
-	
+	/* use an animated gif for the progress bar in 'indeterminate' mode */
 	background:#cad2de url("images/progressBarAnim.gif") repeat-x center center;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/TimePicker.css b/dijit/themes/nihilo/TimePicker.css
index 70ee3b5..cffdbf5 100644
--- a/dijit/themes/nihilo/TimePicker.css
+++ b/dijit/themes/nihilo/TimePicker.css
@@ -1,50 +1,51 @@
-
+/* Time Picker */
 .nihilo .dijitTimePickerTick,
 .nihilo .dijitTimePickerMarker {
 	border-color: #eeeeee;
 }
+
 .nihilo .dijitTimePickerTick {
 	color:white;
 }
+
 .nihilo .dijitTimePickerMarker {
 	background:#d3d3d3 url("images/titleBar.png") repeat-x top;
 	color:#293a4b;
 	font-weight: bold;
 }
+
 .nihilo .dijitTimePickerItemSelected {
 	color: black;
 	background: #ffe284 none;
 }
+
 .nihilo .dijitTimePickerItemHover {
 	background: #d6d6dd none;
 	color:black;
 }
+
 .nihilo .dijitTimePickerItemHover,
 .nihilo .dijitTimePickerItemSelected {
 	position: relative;
 	z-index: 10;
 }
+
 .nihilo .dijitTimePickerTick .dijitTimePickerItemInner {
 	font-size:0.4em;
 }
+
 .nihilo .dijitTimePickerItemHover .dijitTimePickerItemInner,
 .nihilo .dijitTimePickerItemSelected .dijitTimePickerItemInner {
 	font-size:1em;
 }
+
 .nihilo .dijitTimePickerMarkerHover {
 	border-top: 1px solid #eeeeee;
 }
+
 .nihilo .dijitTimePickerTickHover,
 .nihilo .dijitTimePickerTickSelected {
 	margin-top:-0.3em;
 	margin-bottom:-0.3em;
 	border-bottom: none;
-}
-.dijit_a11y .dijitTimePickerTickHover {
-	background-color: #CCC !important;
-	border-top: 1px solid #333 !important;
-	border-bottom: 1px solid #333 !important;
-}
-.dijit_a11y .dijitTimePickerMarkerHover {
-	border-bottom-width: 2px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/TimePicker_rtl.css b/dijit/themes/nihilo/TimePicker_rtl.css
new file mode 100644
index 0000000..377f738
--- /dev/null
+++ b/dijit/themes/nihilo/TimePicker_rtl.css
@@ -0,0 +1,4 @@
+.dj_ie6-rtl .nihilo .dijitTimePickerMarkerHover,
+.dj_ie7-rtl .nihilo .dijitTimePickerMarkerHover {
+        border-top: 0px; /* IE6/7 bug causes mouseover/out event storm */
+}
diff --git a/dijit/themes/nihilo/TitlePane.css b/dijit/themes/nihilo/TitlePane.css
index 83aa48e..ae5b452 100644
--- a/dijit/themes/nihilo/TitlePane.css
+++ b/dijit/themes/nihilo/TitlePane.css
@@ -1,3 +1,7 @@
+/**
+ * dijit.TitlePane
+ *
+ */
 
 .nihilo .dijitTitlePaneTitle {
 	background: #cccccc;
@@ -8,25 +12,20 @@
 	font-weight: bold;
 	color: #6d6d6d;
 }
-.nihilo .dijitTitlePaneTitle-hover  {
+.nihilo .dijitTitlePaneTitleHover  {
 	background: #f9f9f9 url("images/accordionItemActive.png") top repeat-x;
-	cursor: pointer;
-}
-.nihilo .dijitTitlePaneTitle * {
-	vertical-align: middle;
 }
+
 .nihilo .dijitTitlePane .dijitOpen .dijitArrowNode,
 .nihilo .dijitTitlePane .dijitClosed .dijitArrowNode {
 	width:15px;
 	height:15px;
 }
-.nihilo .dijitTitlePaneFocused .dijitTitlePaneTextNode {
-	color: #243C5F;
-}
-.nihilo .dijitOpen .dijitTitlePaneTextNode,
-.nihilo .dijitFixedOpen .dijitTitlePaneTextNode {
+
+.nihilo .dijitTitlePaneTextNode {
 	color: #243C5F;
 }
+
 .nihilo .dijitTitlePane .dijitClosed .dijitArrowNode {
 	background: url('images/spriteRoundedIconsSmall.png') no-repeat -30px top;
 }
@@ -39,31 +38,17 @@
 .dj_ie6 .nihilo .dijitTitlePane .dijitOpen .dijitArrowNode {
 	background:url('images/spriteRoundedIconsSmall.gif') no-repeat -15px top;
 }
-.nihilo .dijitTitlePane .dijitArrowNodeInner {
-	display:none;
-}
-.dijit_a11y .dijitTitlePane .dijitOpen .dijitArrowNodeInner,
-.dijit_a11y .dijitTitlePane .dijitClosed .dijitArrowNodeInner {
-	display:inline !important;
-	font-family:monospace;
-	padding-bottom:.2em;
-}
-.dijit_a11y .dijitTitlePane .dijitArrowNode {
-	display:none;
-}
+
 .nihilo .dijitTitlePaneContentOuter {
 	background: #ffffff;
 	border:1px solid #bfbfbf;
-	border-top: 0px solid #3d3d3d;	
+	border-top: 0px;
 }
 .nihilo .dijitTitlePaneContentInner {
 	padding:10px;
 }
-.dj_ie6 .nihilo .dijitTitlePaneContentOuter,
-.dj_ie6 .nihilo .dijitTitlePane .dijitTitlePaneTitle {
-	zoom: 1;
-}
+
 .nihilo .dijitTitlePaneTextNode {
 	margin-left: 4px;
 	margin-right: 4px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/TitlePane_rtl.css b/dijit/themes/nihilo/TitlePane_rtl.css
index a8aef83..50a5d43 100644
--- a/dijit/themes/nihilo/TitlePane_rtl.css
+++ b/dijit/themes/nihilo/TitlePane_rtl.css
@@ -3,4 +3,4 @@
 }
 .dj_ie6-rtl .nihilo .dijitTitlePane .dijitClosed .dijitArrowNode {
 	background-position: 0px top;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/Toolbar.css b/dijit/themes/nihilo/Toolbar.css
index 4106fad..5b4cd12 100644
--- a/dijit/themes/nihilo/Toolbar.css
+++ b/dijit/themes/nihilo/Toolbar.css
@@ -2,9 +2,12 @@
 	border-bottom: 1px solid #ccc;
 	background:#eaeaea url("images/titleBar.png") repeat-x top left;
 }
+
+/* setting a min-height on ditor toolbar */
 .dj_ie6 .nihilo .dijitToolbar {
 	height: 10px;
 }
+
 .nihilo .dijitToolbar .dijitButtonNode,
 .nihilo .dijitToolbar .dijitComboButton .dijitButtonContents,
 .nihilo .dijitToolbar .dijitComboButton .dijitDownArrowButton {
@@ -14,20 +17,23 @@
 	border: none;
 	font-size: 12px;
 }
+
 .nihilo .dijitToolbar .dijitButton,
 .nihilo .dijitToolbar .dijitToggleButton,
 .nihilo .dijitToolbar .dijitDropDownButton,
 .nihilo .dijitToolbar .dijitComboButton .dijitButtonContents,
 .nihilo .dijitToolbar .dijitComboButton .dijitDownArrowButton {
 	background: none;
-	padding: 1px;	
+	padding: 1px;	/* on hover etc., margin replaced w/border */
 }
+
 .nihilo .dijitToolbar .dijitButtonChecked,
 .nihilo .dijitToolbar .dijitToggleButtonChecked {
 	background-color:#ffeeb9;
 	border:1px solid #f7c95c;
 	padding: 0;
 }
+
 .nihilo .dijitToolbar .dijitButtonCheckedHover,
 .nihilo .dijitToolbar .dijitToggleButtonCheckedHover
  {
@@ -35,22 +41,25 @@
 	border:1px solid #f7c95c;
 	padding: 0;
 }
+
 .nihilo .dijitToolbar .dijitButtonHover,
 .nihilo .dijitToolbar .dijitToggleButtonHover,
 .nihilo .dijitToolbar .dijitDropDownButtonHover,
-.nihilo .dijitToolbar .dijitComboButtonHover .dijitButtonContents,
-.nihilo .dijitToolbar .dijitComboButtonDownArrowHover .dijitDownArrowButton {
-	
+.nihilo .dijitToolbar .dijitComboButton .dijitButtonContentsHover,
+.nihilo .dijitToolbar .dijitComboButton .dijitDownArrowButtonHover {
+	/* TODO: change this from Hover to Selected so that button is still highlighted while drop down is being used */
 	border: 1px solid #f7c95c;
 	padding: 0;
 	background-color:#ffe284;
 }
+
 .nihilo .dijitToolbar label {
 	padding: 3px 3px 0 6px;
 }
+
 .dj_ie .nihilo .dijitToolbar .dijitComboButton .dijitButtonContentsFocused,
 .dj_ie .nihilo .dijitToolbar .dijitComboButton .dijitDownArrowButtonFocused {
-	
+	/* focus border doesn't appear on <td> for IE, so need to add it manually */
 	border: 1px #555 dotted !important;
 	padding: 0px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/Tree.css b/dijit/themes/nihilo/Tree.css
index 18e97cb..f71b653 100644
--- a/dijit/themes/nihilo/Tree.css
+++ b/dijit/themes/nihilo/Tree.css
@@ -1,87 +1,100 @@
+/* Tree */
 
 .nihilo .dijitTreeNode {
     background : url('images/treeI.gif') no-repeat;
     background-position : top left;
     background-repeat : repeat-y;
-    zoom: 1;	
+    zoom: 1;	/* MOW: what the heck is this doing in here? */
 }
+
+/* left vertical line (grid) for all nodes */
 .nihilo .dijitTreeIsLast {
     background: url('images/treeI_half.gif') no-repeat;
 }
-.nihilo .dijitTreeNodeHover {
-	
+
+.nihilo .dijitTreeRowHover {
+	/* using a transparent png so that we can still see grid lines, which are (unfortunately) behind the dijitRowNode that we are hovering over */
 	background-image: url(images/treeHover.png);
 	background-repeat: repeat;
-	background-color: none !important;
+	background-color: transparent !important;
 }
+
 .nihilo .dijitTreeLabel {
 	font-weight: normal;
 	margin-left: 3px;
 }
+
 .nihilo .dijitTreeIsRoot {
     margin-left: 0;
     background-image: none;
 }
+
 .nihilo .dijitTreeExpando {
     width: 18px;
     height: 18px;
 }
+
 .nihilo .dijitTreeRow {
-	
+	/* so insert line shows up on IE when dropping after a target element */
 	padding-bottom: 2px;
 }
+
 .nihilo .dijitTreeContent {
     min-height: 18px;
     min-width: 18px;
     padding-left:1px;
 }
-.nihilo .dijitTreeExpand {
-    width: 18px;
-    height: 18px;
-    background-repeat : no-repeat;
-}
-.nihilo .dijitTreeNodeEmphasized {
-    background-color: Highlight;
-    color: HighlightText;
-}
-.nihilo .dijitTreeLabelFocused {
-	outline: 1px invert dotted;
-}
+
 .nihilo .dijitTreeExpandoOpened {
 	background: url('images/spriteTree.gif') no-repeat -18px top;
 }
+
 .nihilo .dijitTreeExpandoClosed {
 	background-image: url('images/spriteTree.gif');
 }
+
 .nihilo .dijitTreeExpandoLeaf {
 	background: url('images/spriteTree.gif') no-repeat -36px top;
 }
+
 .nihilo .dijitTreeExpandoLoading {
 	background-image: url('images/treeExpand_loading.gif');
 }
+
 .nihilo .dijitTreeIcon {
 	width: 16px;
 	height: 16px;
 }
+
 .nihilo .dijitFolderOpened {
 	background: url('images/spriteDivIcons.gif') no-repeat -16px top;
 }
+
 .nihilo .dijitFolderClosed {
 	background: url('images/spriteDivIcons.gif') no-repeat top left;
 }
+
 .nihilo .dijitLeaf {
 	background: url('images/spriteDivIcons.gif') no-repeat -32px top;
 }
+
+/* Drag and Drop on TreeNodes
+ * Put insert line on dijitTreeContent node so it's aligned w/
+ * (ie, indented equally with) target element, even
+ * though dijitTreeRowNode is the actual "drag object"
+ */
 .nihilo .dijitTreeNode .dojoDndItemBefore,
 .nihilo .dijitTreeNode .dojoDndItemAfter {
 	border-bottom: none;
 	border-top: none;
 }
+
 .nihilo .dijitTreeNode .dojoDndItemBefore .dijitTreeContent {
-	
+	/* copied from Common.css */
 	border-top: 2px solid #369;
 }
+
 .nihilo .dijitTreeNode .dojoDndItemAfter .dijitTreeContent {
-	
+	/* copied from Common.css */
 	border-bottom: 2px solid #369;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/Tree_rtl.css b/dijit/themes/nihilo/Tree_rtl.css
index e92d5d5..ecf3207 100644
--- a/dijit/themes/nihilo/Tree_rtl.css
+++ b/dijit/themes/nihilo/Tree_rtl.css
@@ -1,22 +1,22 @@
+/* Tree */
 
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeNode {
-    background-image : none;
+.dijitRtl .nihilo .dijitTreeNode,
+.dijitRtl .nihilo .dijitTreeExpandoLeaf {
+	/* disable grid lines for Tree in RTL mode, too hard to support */
+    background-image: none;
 }
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeIsRoot {
-}
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeIsLast {
-    background-image: url('images/treeI_half_rtl.gif');
-}
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeContent {
-    padding-left: auto;
+
+.dijitRtl .nihilo .dijitTreeContent {
+    padding-left: 0px;
     padding-right: 1px;
 }
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeExpandoOpened {
+
+.dijitRtl .nihilo .dijitTreeExpandoOpened {
+	/* todo: icon contains grid line but grid lines disabled above */
 	background: url('images/spriteTree_rtl.gif') no-repeat -18px top;
 }
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeExpandoClosed {
+
+.dijitRtl .nihilo .dijitTreeExpandoClosed {
+	/* todo: icon contains grid line but grid lines disabled above */
 	background-image: url('images/spriteTree_rtl.gif');
 }
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeExpandoLeaf {
-	background: none;
-}
diff --git a/dijit/themes/nihilo/form/Button.css b/dijit/themes/nihilo/form/Button.css
index 01dc674..934705e 100644
--- a/dijit/themes/nihilo/form/Button.css
+++ b/dijit/themes/nihilo/form/Button.css
@@ -1,32 +1,42 @@
 
+/*****
+		dijit.form.Button
+		dijit.form.DropDownButton
+		dijit.form.ComboButton
+		dijit.form.ComboBox (partial)
+		dijit.form.Spinner (partial) (TODO: create NumberSpinner.css file like claro has)
+ *****/
+
 .nihilo .dijitButtonNode {
-	
-	
+	/* enabled state - inner */
+	/* border:1px outset #a0a0a0; */
 	border:1px solid #dedede;
 	border-bottom:1px solid #dedede;
 	padding: 0.1em 0.2em 0.2em 0.2em;
 	background: #fff url("../images/buttonEnabled.png") repeat-x top left;
 }
+
 .nihilo .dijitSelect .dijitButtonContents {
 	border-right: none;
 }
-.nihilo .dijitButtonNode button {
-	border: 0px;
-	background-color: transparent;
-}
+
 .nihilo .dijitButtonText {
 	text-align: center;
 	padding: 0 0.3em;
 }
+
 .nihilo .dijitComboBox .dijitButtonNode {
 	border-width: 0px 0px 0px 1px;
 }
+
 .nihilo .dijitArrowButton {
 	color: #111;
 }
+
 .nihilo .dijitComboButton .dijitDownArrowButton {
 	padding-right:4px;
 }
+
 .nihilo .dijitComboBoxReadOnly,
 .nihilo .dijitSpinnerReadOnly,
 .nihilo .dijitSpinnerReadOnly .dijitButtonNode,
@@ -37,57 +47,83 @@
 .nihilo .dijitComboBoxDisabled,
 .nihilo .dijitSpinnerDisabled,
 .nihilo .dijitSpinnerDisabled .dijitButtonNode {
-	
+	/* disabled state - inner */
 	border-color: #dedede;
 	background:#fafafa url("../images/buttonDisabled.png") top repeat-x;
 	opacity: 0.60;
 }
-.dj_ie6 .nihilo .dijitComboButtonDisabled .dijitButtonText {
-	
+.dj_ie6 .nihilo .dijitReadOnly INPUT,
+.dj_ie7 .nihilo .dijitReadOnly INPUT,
+.dj_ie6 .nihilo .dijitComboButtonDisabled .dijitButtonText,
+.dj_ie7 .nihilo .dijitComboButtonDisabled .dijitButtonText {
+	/* opacity doesn't work on table node in IE, work around here */
 	color: #aaa;
 }
+
+
 .nihilo .dijitButtonHover .dijitButtonNode,
 .nihilo .dijitButtonNodeHover,
 .nihilo .dijitToggleButtonHover .dijitButtonNode,
 .nihilo .dijitDropDownButtonHover .dijitButtonNode,
-.nihilo .dijitComboButtonHover .dijitButtonContents,
-.nihilo .dijitComboButtonDownArrowHover .dijitDownArrowButton,
-.nihilo .dijitComboBoxHover .dijitDownArrowButton,
-.nihilo .dijitSpinnerUpArrowHover .dijitUpArrowButton,
-.nihilo .dijitSpinnerDownArrowHover .dijitDownArrowButton {
-	
-	
+.nihilo .dijitButtonContentsHover,
+.nihilo .dijitDownArrowButtonHover,
+.nihilo .dijitUpArrowButtonHover {
+	/* hover state - inner */
+	/* TODO: change from Hover to Selected so that button is still highlighted while drop down is being used */
 	color:#243C5F;
 	background:#fcfcfc url("../images/buttonHover.png") repeat-x top left;
 }
-.nihilo .dijitSpinnerUpArrowActive .dijitUpArrowButton,
-.nihilo .dijitSpinnerDownArrowActive .dijitDownArrowButton,
+
+.nihilo .dijitUpArrowButtonActive,
+.nihilo .dijitDownArrowButtonActive,
 .nihilo .dijitButtonActive .dijitButtonNode,
 .nihilo .dijitToggleButtonActive .dijitButtonNode,
 .nihilo .dijitDropDownButtonActive .dijitButtonNode,
-.nihilo .dijitComboButtonActive .dijitButtonContents,
-.nihilo .dijitDownArrowActive .dijitDownArrowButton,
-.nihilo .dijitComboBoxActive .dijitDownArrowButton,
+.nihilo .dijitComboButton .dijitButtonContentsActive,
 .nihilo .dijitStackController .dijitToggleButtonChecked .dijitButtonNode {
-	
+	/* active state - inner (for when you are pressing a normal button, or
+	 * when a radio-type button is in a depressed state
+	 */
 	border-color:#dedede;
 	background: #f5f5f5 url("../images/buttonActive.png") top left repeat-x;
 }
+
+
 .nihilo .dijitArrowButtonInner {
 	background-image: url("../images/spriteArrows.png");
 	background-repeat: no-repeat;
-	background-position: 0px top;
+	background-position: 0px center;
 	width: 11px;
+	height: 11px;
 }
 .nihilo .dijitLeftArrowButton .dijitArrowButtonInner {
-	background-position: -11px top;
+	background-position: -11px center;
 }
 .nihilo .dijitUpArrowButton .dijitArrowButtonInner {
-	background-position: -22px top;
+	background-position: -22px center;
 }
 .nihilo .dijitRightArrowButton .dijitArrowButtonInner {
-	background-position: -33px top;
+	background-position: -33px center;
 }
 .dj_ie6 .nihilo .dijitArrowButtonInner {
 	background-image: url("../images/spriteArrows.gif");
 }
+.dj_webkit .nihilo .dijitSpinner .dijitUpArrowButton .dijitArrowButtonInner {
+	margin-top: -1px; /* image has too many blank pixels on top */
+}
+.dj_ie .nihilo .dijitSpinner .dijitUpArrowButton .dijitArrowButtonInner {
+	margin-top: 1px; /* image has too many blank pixels on top */
+}
+.nihilo .dijitSpinnerButtonContainer {
+	width: auto;
+	padding: 0;
+}
+.nihilo .dijitSpinner .dijitArrowButton {
+	width: 15px;
+}
+.nihilo .dijitSpinner .dijitSpinnerButtonInner {
+	width: 15px;
+}
+.nihilo .dijitSpinner .dijitArrowButtonInner .dijitInputField {
+	padding: 0;
+}
diff --git a/dijit/themes/nihilo/form/Button_rtl.css b/dijit/themes/nihilo/form/Button_rtl.css
index 3a7acc0..f856feb 100644
--- a/dijit/themes/nihilo/form/Button_rtl.css
+++ b/dijit/themes/nihilo/form/Button_rtl.css
@@ -5,3 +5,4 @@
 	border-left: none;
 	border-right-width: 1px;
 }
+
diff --git a/dijit/themes/nihilo/form/Checkbox.css b/dijit/themes/nihilo/form/Checkbox.css
index ceee44f..b35ebf3 100644
--- a/dijit/themes/nihilo/form/Checkbox.css
+++ b/dijit/themes/nihilo/form/Checkbox.css
@@ -1,40 +1,67 @@
 
+/*
+ *  CheckBox and Radio Widgets,
+ *	and the CSS to embed a checkbox or radio icon inside a ToggleButton.
+ *
+ *	Order of images in the default sprite (from L to R, checkbox and radio in same image):
+ *		checkbox	normal 	 - checked
+ *							 - unchecked
+ *					disabled - checked
+ *							 - unchecked
+ *					hover 	 - checked
+ *							 - unchecked
+ *
+ *		radio		normal 	 - checked
+ *							 - unchecked
+ *					disabled - checked
+ *							 - unchecked
+ *					hover 	 - checked
+ *							 - unchecked
+*/
+
 .nihilo .dijitToggleButton .dijitCheckBox,
 .nihilo .dijitToggleButton .dijitCheckBoxIcon {
 	background-image: url('../images/spriteCheckbox.gif');
 }
+
 .nihilo .dijitCheckBox,
-.nihilo .dijitCheckBoxIcon {		
-	background-image: url('../images/spriteCheckbox.gif'); 
+.nihilo .dijitCheckBoxIcon {		/* inside a toggle button */
+	background-image: url('../images/spriteCheckbox.gif'); /* checkbox sprite image */
 	background-repeat: no-repeat;
 	width: 16px;
 	height: 16px;
 	margin: 0;
 	padding: 0;
 }
+
 .nihilo .dijitCheckBox,
 .nihilo .dijitToggleButton .dijitCheckBoxIcon {
-	
+	/* unchecked */
 	background-position: -16px;
 }
+
 .nihilo .dijitCheckBoxChecked,
 .nihilo .dijitToggleButtonChecked .dijitCheckBoxIcon {
-	
+	/* checked */
 	background-position: 0px;
 }
+
 .nihilo .dijitCheckBoxDisabled {
-	
+	/* disabled */
 	background-position: -48px;
 }
+
 .nihilo .dijitCheckBoxCheckedDisabled {
-	
+	/* disabled but checked */
 	background-position: -32px;
 }
+
 .nihilo .dijitCheckBoxHover {
-	
+	/* hovering over an unchecked enabled checkbox */
 	background-position: -80px;
 }
+
 .nihilo .dijitCheckBoxCheckedHover {
-	
+	/* hovering over a checked enabled checkbox */
 	background-position: -64px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/form/ComboBox.css b/dijit/themes/nihilo/form/ComboBox.css
deleted file mode 100644
index fa7262e..0000000
--- a/dijit/themes/nihilo/form/ComboBox.css
+++ /dev/null
@@ -1,10 +0,0 @@
-.nihilo .dijitComboBox .dijitArrowButton .dijitArrowButtonInner {
-	background:url("../images/spriteArrows.png") no-repeat left center;
-	width: 11px;
-}
-.dj_ie6 .nihilo .dijitComboBox .dijitArrowButton .dijitArrowButtonInner {
-	background:url("../images/spriteArrows.gif") no-repeat left center;
-}
-.nihilo .dijitComboBoxHover .dijitArrowButtonInner {
-	
-}
diff --git a/dijit/themes/nihilo/form/Common.css b/dijit/themes/nihilo/form/Common.css
index 4a9ddc0..da77b3b 100644
--- a/dijit/themes/nihilo/form/Common.css
+++ b/dijit/themes/nihilo/form/Common.css
@@ -1,76 +1,74 @@
 
-.nihilo .dijitInputField INPUT,
-.nihilo .dijitTextBox,
-.nihilo .dijitComboBox,
-.nihilo .dijitSpinner {
+/****
+		dijit.form.TextBox
+		dijit.form.ValidationTextBox
+		dijit.form.SerializableTextBox
+		dijit.form.RangeBoundTextBox
+		dijit.form.NumberTextBox
+		dijit.form.CurrencyTextBox
+		dijit.form.NumberSpinner
+		dijit.form.ComboBox (partial)
+ ****/
+
+.nihilo .dijitInputContainer INPUT,
+.nihilo .dijitTextBox {
 	margin: 0em 0.1em;
 }
+
 .nihilo .dijitTextBox,
-.nihilo .dijitComboBox,
-.nihilo .dijitSpinner,
-.nihilo .dijitInlineEditor input,
 .nihilo .dijitTextArea {
-	
+	/* 	For all except dijit.form.NumberSpinner:  the actual input element.
+		For TextBox, ComboBox, Spinner: the table that contains the input.
+		Otherwise the actual input element.
+	*/
 	background:#fff url("../images/validationInputBg.png") repeat-x top left;
+	#background:#fff url('../images/validationInputBg.gif') repeat-x top left;
 	border:1px solid #d3d3d3;
-	line-height: normal;
-}
-.dj_ie6 .nihilo .dijitTextBox,
-.dj_ie6 .nihilo .dijitComboBox,
-.dj_ie6 .nihilo .dijitSpinner,
-.dj_ie6 .nihilo .dijitInlineEditor input,
-.dj_ie6 .nihilo .dijitTextArea {
-	background:#fff url('../images/validationInputBg.gif') repeat-x top left;
 }
+
 .nihilo .dijitComboBox .dijitButtonNode {
-	padding: 0 0.2em;
+	padding: 0 0.2em !important;
 }
-.nihilo .dijitComboBox .dijitButtonNode,
-.nihilo .dijitSpinner .dijitButtonNode {
-	
+.nihilo .dijitTextBox .dijitButtonNode {
+	/* line between the input area and the drop down button */
 	border-color: #d3d3d3;
-	border-left: 1px solid #d3d3d3;
 }
+
 .nihilo .dijitTextBoxFocused,
-.nihilo .dijitComboBoxFocused,
-.nihilo .dijitSpinnerFocused, .nihilo .dijitSpinnerUpArrowActive, .nihilo .dijitSpinnerDownArrowActive,
 .nihilo .dijitTextAreaFocused {
-	
+	/* input field when focused (ie: typing affects it) */
 	border-color:#b3b3b3;
 }
-.nihilo .dijitComboBoxFocused .dijitButtonNode,
-.nihilo .dijitSpinnerFocused .dijitButtonNode,
-.nihilo .dijitSpinnerUpArrowActive .dijitButtonNode,
-.nihilo .dijitSpinnerDownArrowActive .dijitButtonNode {
+.nihilo .dijitTextBoxFocused .dijitButtonNode,
+.nihilo .dijitSpinner .dijitUpArrowButtonActive,
+.nihilo .dijitSpinner .dijitDownArrowButtonActive {
 	border-left-color:#d3d3d3;
 }
 .nihilo .dijitSpinnerFocused .dijitDownArrowButton,
-.nihilo .dijitSpinnerUpArrowActive .dijitDownArrowButton,
-.nihilo .dijitSpinnerDownArrowActive .dijitDownArrowButton {
+.nihilo .dijitSpinner .dijitUpArrowButtonActive,
+.nihilo .dijitSpinner .dijitDownArrowButtonActive {
 	border-top-color:#d3d3d3;
 }
+
 .nihilo .dijitError {
 	border-color:#b3b3b3;
 	background-color:#f9f7ba;
 	background-image:none;
 }
-.dj_ie6 .nihilo .dijitError INPUT {
-	
-	background-color:#f9f7ba !important;
-}
+
 .nihilo .dijitErrorFocused {
 	background-color:#ff6;
 	background-image:none;
 }
-.dj_ie6 .nihilo .dijitErrorFocused INPUT {
-	
-	background-color:#ff6 !important;
-}
+
+/* Validation errors  */
 .nihilo .dijitValidationIcon {
-	
+	/* prevent height change when widget goes from valid to invalid state */
 	width: 16px;
 	background: transparent url('../images/warning.png') no-repeat center center;
 }
+
+/* The highlight is shown in the ComboBox menu. */
 .nihilo .dijitComboBoxHighlightMatch {
 	background-color:#d3d3d3;
 }
diff --git a/dijit/themes/nihilo/form/Common_rtl.css b/dijit/themes/nihilo/form/Common_rtl.css
deleted file mode 100644
index d4e95c3..0000000
--- a/dijit/themes/nihilo/form/Common_rtl.css
+++ /dev/null
@@ -1,7 +0,0 @@
-.dijitRtl .nihilo .dijitComboBox .dijitButtonNode,
-.dijitRtl .nihilo .dijitSpinner .dijitButtonNode {
-	
-	border-color: #8ba0bd;
-	border-left: 0px solid #8ba0bd;
-	border-right: 1px solid #8ba0bd;
-}
diff --git a/dijit/themes/nihilo/form/RadioButton.css b/dijit/themes/nihilo/form/RadioButton.css
index c876f59..258f26d 100644
--- a/dijit/themes/nihilo/form/RadioButton.css
+++ b/dijit/themes/nihilo/form/RadioButton.css
@@ -1,40 +1,66 @@
+/*
+ *  CheckBox and Radio Widgets,
+ *	and the CSS to embed a checkbox or radio icon inside a ToggleButton.
+ *
+ *	Order of images in the default sprite (from L to R, checkbox and radio in same image):
+ *		checkbox	normal 	 - checked
+ *							 - unchecked
+ *					disabled - checked
+ *							 - unchecked
+ *					hover 	 - checked
+ *							 - unchecked
+ *
+ *		radio		normal 	 - checked
+ *							 - unchecked
+ *					disabled - checked
+ *							 - unchecked
+ *					hover 	 - checked
+ *							 - unchecked
+*/
 
 .nihilo .dijitToggleButton .dijitRadio,
 .nihilo .dijitToggleButton .dijitRadioIcon {
 	background-image: url('../images/spriteRadio.gif');
 }
+
 .nihilo .dijitRadio,
-.nihilo .dijitRadioIcon	{		
-	background-image: url('../images/spriteRadio.gif'); 
+.nihilo .dijitRadioIcon	{		/* inside a toggle button */
+	background-image: url('../images/spriteRadio.gif'); /* checkbox sprite image */
 	background-repeat: no-repeat;
 	width: 16px;
 	height: 16px;
 	margin: 0;
 	padding: 0;
 }
+
 .nihilo .dijitRadio,
 .nihilo .dijitToggleButton .dijitRadioIcon {
-	
+	/* unselected */
 	background-position: -16px;
 }
+
 .nihilo .dijitRadioChecked,
 .nihilo .dijitToggleButtonChecked .dijitRadioIcon {
-	
+	/* selected */
 	background-position: 0px;
 }
+
 .nihilo .dijitRadioDisabled {
-	
+	/* unselected and disabled */
 	background-position: -48px;
 }
+
 .nihilo .dijitRadioCheckedDisabled {
-	
+	/* selected but disabled */
 	background-position: -32px;
 }
+
 .nihilo .dijitRadioHover {
-	
+	/* hovering over an unselected enabled radio button */
 	background-position: -80px;
 }
+
 .nihilo .dijitRadioCheckedHover {
-	
+	/* hovering over a selected enabled radio button */
 	background-position: -64px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/form/Select.css b/dijit/themes/nihilo/form/Select.css
index 8872b18..2d32ec3 100644
--- a/dijit/themes/nihilo/form/Select.css
+++ b/dijit/themes/nihilo/form/Select.css
@@ -1,13 +1,8 @@
-
-.nihilo .dijitSelectDisabled * {
-    cursor: not-allowed !important;
-}
-.nihilo .dijitSelectReadOnly * {
-    cursor: default !important;
-}
 .nihilo .dijitSelect .dijitButtonNode {
 	padding: 0px;
 }
+
+/* Make unselected "look" more like a text box and less like a button */
 .nihilo .dijitSelect .dijitButtonContents {
 	padding-top: 1px;
     background:#fff url("../images/validationInputBg.png") repeat-x top left;
@@ -23,6 +18,12 @@
 .dj_ie .nihilo .dijitSelect .dijitButtonContents {
 	padding-top: 0px;
 }
+
+.nihilo .dijitSelect .dijitArrowButton {
+	padding: 0px 2px;
+}
+
+/* Mirror DropDownButton */
 .nihilo .dijitSelectDisabled .dijitButtonNode {
     border-color: #dedede;
     background:#fafafa url("../images/buttonDisabled.png") top repeat-x;
@@ -30,23 +31,24 @@
 .dj_ie .nihilo .dijitSelectDisabled  .dijitButtonNode * {
 	filter: gray() alpha(opacity=50);
 }
+
 .nihilo .dijitSelectHover .dijitButtonNode {
     color:#000;
     background:#fcfcfc url("../images/buttonHover.png") repeat-x top left;
 }
+
 .nihilo .dijitSelectActive .dijitButtonNode,
 .nihilo .dijitSelectOpened .dijitButtonNode {
     border-color:#dedede;
     background: #f5f5f5 url("../images/buttonActive.png") top left repeat-x;
 }
+
+/* Make the menu look more combobox-like */
 .nihilo .dijitSelectMenu td {
 	padding: 0em;
 }
-.nihilo .dijitSelectMenu .dijitMenuItemIcon {
-	margin: 0.1em 0.2em;
-	display: none;
-}
 .nihilo .dijitSelectMenu .dijitMenuItemLabel,
 .nihilo .dijitSelectMenu .dijitMenuArrowCell {
 	padding: 0.1em 0.2em;
 }
+
diff --git a/dijit/themes/nihilo/form/Slider.css b/dijit/themes/nihilo/form/Slider.css
index 47b0ca2..d2db2ef 100644
--- a/dijit/themes/nihilo/form/Slider.css
+++ b/dijit/themes/nihilo/form/Slider.css
@@ -1,99 +1,111 @@
 
+/****
+ 	SLIDER
+****/
+
 .nihilo .dijitSliderProgressBarH {
 	border-color: #aab0bb;
 	background: #c0c2c5 url("../images/sliderFull.png") repeat-x top left;
 }
+
 .nihilo .dijitSliderProgressBarV {
 	border-color: #aab0bb;
 	background: #c0c2c5 url("../images/sliderFullVertical.png") repeat-y bottom left;
 }
+
 .nihilo .dijitSliderFocused .dijitSliderProgressBarH,
 .nihilo .dijitSliderFocused .dijitSliderLeftBumper {
 	background-image:url("../images/sliderFullFocus.png");
 }
+
 .nihilo .dijitSliderFocused .dijitSliderProgressBarV,
 .nihilo .dijitSliderFocused .dijitSliderBottomBumper {
 	background-image:url("../images/sliderFullVerticalFocus.png");
 }
+
 .nihilo .dijitSliderRemainingBarV {
 	border-color: #b4b4b4;
 	background: #dcdcdc url("../images/sliderEmptyVertical.png") repeat-y bottom left;
 }
+
 .nihilo .dijitSliderRemainingBarH {
 	border-color: #b4b4b4;
 	background: #dcdcdc url("../images/sliderEmpty.png") repeat-x top left;
 }
+
 .nihilo .dijitSliderBar {
 	border-style: solid;
 	outline:1px;
-	
+	/* border-color: #b4b4b4; */
 }
 .nihilo .dijitSliderFocused .dijitSliderBar {
 	border-color:#727272;
 }
-.dijit_a11y .dijitSliderProgressBar {
-	background-color:#333 !important;
-}
+
 .nihilo .dijitSliderImageHandleH {
 	border:0px;
 	width:15px;
 	height:18px;
 	background:url("../images/preciseSliderThumb.png") no-repeat center top;
 	#background:url("../images/preciseSliderThumb.gif") no-repeat center top;
-	cursor:pointer;
 }
 .nihilo .dijitSliderFocused .dijitSliderImageHandleH {
 	background-image:url("../images/preciseSliderThumbFocus.png");
 	#background-image:url("../images/preciseSliderThumbFocus.gif");
 }
+
 .nihilo .dijitSliderLeftBumper {
 	border-left-width: 1px;
 	border-color: #aab0bb;
 	background: #c0c2c5 url("../images/sliderFull.png") repeat-x top left;
 }
+
 .nihilo .dijitSliderRightBumper {
 	background: #dcdcdc url("../images/sliderEmpty.png") repeat-x top left;
 	border-color: #b4b4b4;
 	border-right-width: 1px;
 }
+
 .nihilo .dijitSliderImageHandleV {
 	border:0px;
 	width:20px;
 	height:15px;
 	background:url("../images/sliderThumb.png") no-repeat center center;
 	#background:url("../images/sliderThumb.gif") no-repeat center center;
-	cursor:pointer;
 }
+
 .nihilo .dijitSliderFocused .dijitSliderImageHandleV {
 	background-image:url("../images/sliderThumbFocus.png");
 	#background-image:url("../images/sliderThumbFocus.gif");
 }
+
 .nihilo .dijitSliderBottomBumper {
 	border-bottom-width: 1px;
 	border-color: #aab0bb;
 	background: #c0c2c5 url("../images/sliderFullVertical.png") repeat-y bottom left;
 }
+
 .nihilo .dijitSliderTopBumper {
 	background: #dcdcdc url("../images/sliderEmptyVertical.png") repeat-y top left;
 	border-color: #b4b4b4;
 	border-top-width: 1px;
 }
+
 .nihilo .dijitSliderIncrementIconH,
 .nihilo .dijitSliderIncrementIconV {
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat -45px top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat -45px top;
 	width:15px; height:15px;
-	cursor:pointer;
 }
 .nihilo .dijitSliderIncrementIconH {
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat -30px top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat -30px top;
 }
+
 .nihilo .dijitSliderDecrementIconH,
 .nihilo .dijitSliderDecrementIconV {
 	width:15px;
 	height:15px;
-	cursor:pointer;
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat -15px top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat -15px top;
 }
@@ -101,9 +113,11 @@
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat 0px top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat 0px top;
 }
+
 .nihilo .dijitSliderButtonInner {
 	visibility:hidden;
 }
+
 .nihilo .dijitSliderReadOnly *,
 .nihilo .dijitSliderDisabled * {
 	border-color: #d5d5d5 #bdbdbd #bdbdbd #d5d5d5;
@@ -124,4 +138,4 @@
 .nihilo .dijitSliderReadOnly .dijitSliderIncrementIconV,
 .nihilo .dijitSliderDisabled .dijitSliderIncrementIconV {
 	background-position: -45px -15px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/form/Slider_rtl.css b/dijit/themes/nihilo/form/Slider_rtl.css
index fc40452..8410f36 100644
--- a/dijit/themes/nihilo/form/Slider_rtl.css
+++ b/dijit/themes/nihilo/form/Slider_rtl.css
@@ -1,4 +1,6 @@
 
+/* Slider */
+
 .dijitRtl .nihilo .dijitSliderProgressBarH,
 .dijitRtl .nihilo .dijitSliderRemainingBarH,
 .dijitRtl .nihilo .dijitSliderLeftBumper,
@@ -6,23 +8,28 @@
 .dijitRtl .nihilo .dijitSliderTopBumper {
 	background-position: top right;
 }
+
 .dijitRtl .nihilo .dijitSliderProgressBarV,
 .dijitRtl .nihilo .dijitSliderRemainingBarV,
 .dijitRtl .nihilo .dijitSliderBottomBumper {
 	background-position: bottom right;
 }
+
 .dijitRtl .nihilo .dijitSliderLeftBumper {
 	border-left-width: 0px;
 	border-right-width: 1px;
 }
+
 .dijitRtl .nihilo .dijitSliderRightBumper {
 	border-left-width: 1px;
 	border-right-width: 0px;
 }
+
 .dijitRtl .nihilo .dijitSliderIncrementIconH {
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat left top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat left top;
 }
+
 .dijitRtl .nihilo .dijitSliderDecrementIconH {
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat -30px top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat -30px top;
diff --git a/dijit/themes/nihilo/form/TimeTextBox.css b/dijit/themes/nihilo/form/TimeTextBox.css
index d450925..bf67b66 100644
--- a/dijit/themes/nihilo/form/TimeTextBox.css
+++ b/dijit/themes/nihilo/form/TimeTextBox.css
@@ -1 +1 @@
- at CHARSET "UTF-8";
+ at CHARSET "UTF-8";
\ No newline at end of file
diff --git a/dijit/themes/nihilo/images/editor.gif b/dijit/themes/nihilo/images/editor.gif
deleted file mode 100644
index 750c6b9..0000000
Binary files a/dijit/themes/nihilo/images/editor.gif and /dev/null differ
diff --git a/dijit/themes/nihilo/images/editorDisabled.gif b/dijit/themes/nihilo/images/editorDisabled.gif
deleted file mode 100644
index e40460d..0000000
Binary files a/dijit/themes/nihilo/images/editorDisabled.gif and /dev/null differ
diff --git a/dijit/themes/nihilo/images/editorDisabled_rtl.gif b/dijit/themes/nihilo/images/editorDisabled_rtl.gif
deleted file mode 100644
index a0f6c10..0000000
Binary files a/dijit/themes/nihilo/images/editorDisabled_rtl.gif and /dev/null differ
diff --git a/dijit/themes/nihilo/images/editor_rtl.gif b/dijit/themes/nihilo/images/editor_rtl.gif
deleted file mode 100644
index a9740c2..0000000
Binary files a/dijit/themes/nihilo/images/editor_rtl.gif and /dev/null differ
diff --git a/dijit/themes/nihilo/layout/AccordionContainer.css b/dijit/themes/nihilo/layout/AccordionContainer.css
index f87199f..f42db80 100644
--- a/dijit/themes/nihilo/layout/AccordionContainer.css
+++ b/dijit/themes/nihilo/layout/AccordionContainer.css
@@ -1,36 +1,45 @@
+/**
+ * dijit.layout.Accordioncontainer
+ *
+ */
 
 .nihilo .dijitAccordionContainer {
 	border-color: #ccc;
 	background-color: #fff;
 }
+
+/* common */
+
 .nihilo .dijitAccordionTitle {
 	background:#fafafa url("../images/titleBar.png") repeat-x top left;
 	border-top: 1px solid #dedede;
 	padding: 5px 4px 6px 8px;
-	cursor:pointer;
 	font-size: 0.9em;
 	font-weight: bold;
 	color: #6d6d6d;
 }
-.nihilo .dijitAccordionTitle-selected  {
+
+.nihilo .dijitAccordionTitleSelected  {
 	background: #f9f9f9 url("../images/accordionItemActive.png") top repeat-x;
 	font-weight: bold;
 	border-top: 1px solid #dedede;
 	border-bottom: 1px solid #dedede;
 	padding: 5px 4px 5px 8px;
-	cursor: default;
 	color: #243C5F;
 }
+
 .nihilo .dijitAccordionArrow {
 	background:url("../images/spriteRoundedIconsSmall.gif") no-repeat -30px top;
 	width:15px;
 	height:15px;
 	margin-top:-1px;
 }
-.nihilo .dijitAccordionTitle-selected .dijitAccordionArrow {
+
+.nihilo .dijitAccordionTitleSelected .dijitAccordionArrow {
 	background:url("../images/spriteRoundedIconsSmall.gif") no-repeat -15px top;
 	margin-top:-1px;
 }
+
 .nihilo .dijitAccordionText {
 	margin-left: 4px;
 	margin-right: 4px;
diff --git a/dijit/themes/nihilo/layout/AccordionContainer_rtl.css b/dijit/themes/nihilo/layout/AccordionContainer_rtl.css
index 00d3292..760f783 100644
--- a/dijit/themes/nihilo/layout/AccordionContainer_rtl.css
+++ b/dijit/themes/nihilo/layout/AccordionContainer_rtl.css
@@ -1,7 +1,8 @@
 .dijitRtl .nihilo .dijitAccordionArrow {
 	background-position: 0px top;
 }
-.dijitRtl .nihilo .dijitAccordionTitle-selected .dijitAccordionArrow {
-	
+
+.dijitRtl .nihilo .dijitAccordionTitleSelected .dijitAccordionArrow {
+	/* same rule as LTR mode, just listed to override previous rule in this file */
 	background-position: -15px top;
 }
diff --git a/dijit/themes/nihilo/layout/BorderContainer.css b/dijit/themes/nihilo/layout/BorderContainer.css
index 29fcc39..1e876f3 100644
--- a/dijit/themes/nihilo/layout/BorderContainer.css
+++ b/dijit/themes/nihilo/layout/BorderContainer.css
@@ -1,25 +1,37 @@
+/**
+ * dijit.layout.BorderContainer
+ *
+ */
 
 .nihilo .dijitBorderContainer {
 	background-color: #fcfcfc;
 	padding: 5px;
 }
+
 .nihilo .dijitSplitContainer-child,
 .nihilo .dijitBorderContainer-child {
-	
+	/* By default, put borders on all children of BorderContainer,
+	 *  to give illusion of borders on the splitters themselves.
+	 */
     border: 1px #ccc solid;
 }
+
 .nihilo .dijitBorderContainer-dijitTabContainerTop,
 .nihilo .dijitBorderContainer-dijitTabContainerBottom,
 .nihilo .dijitBorderContainer-dijitTabContainerLeft,
 .nihilo .dijitBorderContainer-dijitTabContainerRight {
-	
+	/* except that TabContainer defines borders on it's sub-nodes (tablist and dijitTabPaneWrapper),
+	 * so override rule setting border on domNode
+	 */
 	 border: none;
 }
+
 .nihilo .dijitBorderContainer-dijitBorderContainer {
-	
+	/* also, make nested BorderContainers look like a single big widget with lots of splitters */
 	border: none;
 	padding: 0px;
 }
+
 .nihilo .dijitSplitterH,
 .nihilo .dijitGutterH {
 	background:#FCFCFC;
@@ -28,12 +40,14 @@
 	border-right:0px solid #d3d3d3;
 	height:5px;
 }
+
 .nihilo .dijitSplitterH .dijitSplitterThumb {
 	background:#8BA0BD none;
 	height:1px;
 	top:2px;
 	width:19px;
 }
+
 .nihilo .dijitSplitterV,
 .nihilo .dijitGutterV {
 	background:#FCFCFC;
@@ -42,12 +56,15 @@
 	border-bottom:0px solid #d3d3d3;
 	width:5px;
 }
+
 .nihilo .dijitSplitterV .dijitSplitterThumb {
 	background:#8BA0BD none;
 	height:19px;
 	left:2px;
 	width:1px;
 }
+
+/* active splitter */
 .nihilo .dijitSplitterActive {
 	font-size: 1px;
 	background-image: none;
@@ -56,4 +73,4 @@
 	opacity: 0.6;
 	filter: Alpha(Opacity=60);
 	margin: 0;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/layout/ContentPane.css b/dijit/themes/nihilo/layout/ContentPane.css
index 2bd0a19..37ef084 100644
--- a/dijit/themes/nihilo/layout/ContentPane.css
+++ b/dijit/themes/nihilo/layout/ContentPane.css
@@ -1,7 +1,10 @@
+/* ContentPane */
 
 .nihilo .dijitContentPane {
     padding: 0px;
 }
+
+/* nested layouts */
 .nihilo .dijitTabContainerTop-dijitContentPane,
 .nihilo .dijitTabContainerLeft-dijitContentPane,
 .nihilo .dijitTabContainerRight-dijitContentPane,
@@ -10,8 +13,9 @@
     background-color: #fff;
     padding: 5px;
 }
+
 .nihilo .dijitSplitContainer-dijitContentPane,
 .nihilo .dijitBorderContainer-dijitContentPane {
-    background-color: #fff;		
+    background-color: #fff;		/* override background-color setting on parent .dijitBorderContainer */
     padding: 5px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/layout/SplitContainer.css b/dijit/themes/nihilo/layout/SplitContainer.css
index 79d8fbd..e73c0e7 100644
--- a/dijit/themes/nihilo/layout/SplitContainer.css
+++ b/dijit/themes/nihilo/layout/SplitContainer.css
@@ -1,3 +1,7 @@
+/**
+ * dijit.layout.SplitContainer
+ *
+ */
 
 .nihilo .dijitSplitContainerSizerH {
 	background:url("../images/splitContainerSizerV.png") repeat-y #fff;
@@ -6,12 +10,14 @@
 	border-right:0px solid #d3d3d3;
 	width:5px;
 }
+
 .nihilo .dijitSplitContainerSizerH .thumb {
 	background:url("../images/splitContainerSizerV-thumb.png") no-repeat;
 	left:1px;
 	width:2px;
 	height:19px;
 }
+
 .nihilo .dijitSplitContainerSizerV {
 	background:url("../images/splitContainerSizerH.png") repeat-x #fff;
 	border:0;
@@ -19,9 +25,10 @@
 	border-bottom:0px solid #d3d3d3;
 	height:2px;
 }
+
 .nihilo .dijitSplitContainerSizerV .thumb {
 	background:url("../images/splitContainerSizerH-thumb.png") no-repeat;
 	top:1px;
 	width:19px;
 	height:5px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/layout/TabContainer.css b/dijit/themes/nihilo/layout/TabContainer.css
index 585e440..cbb2506 100644
--- a/dijit/themes/nihilo/layout/TabContainer.css
+++ b/dijit/themes/nihilo/layout/TabContainer.css
@@ -1,137 +1,99 @@
+/**
+ * dijit.layout.TabContainer
+ *
+ * To style TabContainer with rounded corners
+ * you can use these classes: .dijitTab (left), .dijitTabContent (center), dijitTabInnerDiv (right)
+ * For tabs aligned to top you can style a stripe div right underneath the tabs using .dijitTabStripe
+ */
+ at import url("../Menu.css");
+
+/* Classes for all types of tabs (top/bottom/left/right) */
 
-.nihilo .dijitMenu,
-.nihilo .dijitMenuBar {
-	border: 1px solid #d3d3d3;
-	margin: 0px;
-	padding: 0px;
-	background-color: #fff;
-}
-.nihilo .dijitBorderContainer .dijitMenuBar {
-	border: 1px #ccc solid;
-}
-.nihilo .dijitMenuItem {
-	font-family: sans-serif;
-	margin: 0px;
-	color: #243C5F;
-}
-.nihilo .dijitMenuBar .dijitMenuItem {
-	padding: 4px 5px;
-}
-.nihilo .dijitMenuPreviousButton, .nihilo .dijitMenuNextButton {
-	font-style: italic;
-}
-.nihilo .dijitMenuItem TD {
-	padding:1px;
-}
-.nihilo .dijitMenuPassive .dijitMenuItemHover,
-.nihilo .dijitMenuItemSelected {
-	background-color: #ffe284; 
-	color: #243C5F;
-}
-.nihilo .dijitMenuItemIcon {
-	width: 15px;
-	height: 15px;
-}
-.nihilo .dijitMenuExpand {
-	width:15px;
-	height:15px;
-	background-image: url(../images/spriteRoundedIconsSmall.png);
-	background-position: -30px top;
-}
-.dj_ie6 .nihilo .dijitMenuExpand {
-	background-image:url(../images/spriteRoundedIconsSmall.gif);
-}
-.nihilo .dijitMenuSeparator {
-	height: 1px;
-}
-.nihilo .dijitMenuSeparatorTop {
-	border-bottom: 1px solid #fff; 
-}
-.nihilo .dijitMenuSeparatorBottom {
-	border-top: 1px solid #d3d3d3;
-}
-.nihilo .dijitCheckedMenuItemIconChar {
-	display: none;
-}
-.nihilo .dijitCheckedMenuItemIcon {
-	background-image: url(../images/spriteCheckbox.gif);
-	background-position: -80px;
-}
-.nihilo .dijitCheckedMenuItemChecked .dijitCheckedMenuItemIcon {
-	background-position: -64px;
-}
 .nihilo .dijitTabContainer .tabStripRBtn {
 	margin-right: 21px;
 }
 .nihilo .dijitTabContainer .tabStripLBtn {
 	margin-left: 21px;
 }
+
 .nihilo .dijitTabContainerBottom .nowrapTabStrip .dijitTab {
 	top: 0px;
 }
-.nihilo .dijitTabContainer .tabStripMenuButton-Hover {
-	cursor: pointer;
-}
+
+/* Tabs, shared classes */
 .nihilo .dijitTabPaneWrapper {
 	background:#fff;
 	border:1px solid #ccc;
 	margin: 0;
 	padding: 0;
 }
+
 .nihilo .dijitTabInnerDiv {
 	padding:0px 3px 0px 0px;
 	margin: 0 0 0 4px;
 	background: url("../images/tabContainerSprite.gif") no-repeat;
 	background-position: right -400px;
 }
+
 .nihilo .dijitTab {
 	line-height:normal;
-	margin:0 2px 0 0;	
+	margin:0 2px 0 0;	/* space between one tab and the next in top/bottom mode */
 	padding:0px;
 	background: url("../images/tabContainerSprite.gif") no-repeat 0 -300px;
 	color: #6d6d6d;
 	border-bottom: 1px #ccc solid;
 }
+
 .nihilo .dijitTabInnerDiv .dijitTabContent {
 	padding:3px 3px 3px 4px;
 	background: url("../images/tabContainerSprite.gif") repeat-x 0 -350px;
 	position: relative;
 }
+
+/* hovered tab */
 .nihilo .dijitTabHover {
 	color: #243C5F;
 	background: url("../images/tabContainerSprite.gif") no-repeat 0px -150px;
 }
+
 .nihilo .dijitTabHover .dijitTabInnerDiv {
 	background: url("../images/tabContainerSprite.gif") no-repeat right -250px;
 }
+
 .nihilo .dijitTabHover .dijitTabInnerDiv .dijitTabContent {
 	background: url("../images/tabContainerSprite.gif") repeat-x 0 -200px;
 }
-.nihilo .dijitTabChecked,
-.nihilo .dijitTabCloseButtonChecked
+
+/* checked tab*/
+.nihilo .dijitTabChecked
 {
-	
+	/* the selected tab (with or without hover) */
 	background: url("../images/tabContainerSprite.gif") no-repeat 0px -0px;
 }
+
 .nihilo .dijitTabChecked .dijitTabInnerDiv {
 	background: url("../images/tabContainerSprite.gif") no-repeat right -100px;
 }
+
 .nihilo .dijitTabChecked .dijitTabInnerDiv .dijitTabContent {
 	background: url("../images/tabContainerSprite.gif") repeat-x 0 -50px;
 	color: #243C5F !important;
 }
+
+/* Nested Tabs */
 .nihilo .dijitTabContainerNested .dijitTabListWrapper {
 	height: auto;
 }
+
 .nihilo .dijitTabContainerTabListNested {
 	background: #FDFDFD;
 	border: none;
-	margin-bottom: 0px;		
+	margin-bottom: 0px;		/* override margin: -1px; */
 }
 .nihilo .dijitTabContainerTabListNested .dijitTab {
 	background: none;
 	border: none;
-	top: 0px;	
+	top: 0px;	/* override top:1px setting of top-level tabs */
 }
 .nihilo .dijitTabContainerTabListNested .dijitTab .dijitTabInnerDiv,
 .nihilo .dijitTabContainerTabListNested .dijitTab .dijitTabContent {
@@ -145,62 +107,79 @@
 	font-weight: bold;
 }
 .nihilo .dijitTabContainerSpacerNested {
-	
+	/* thinner line between tab (labels) and content */
 	height: 0px;
 	border-bottom: 0px;
 }
 .nihilo .dijitTabPaneWrapperNested {
-	border: none;	
+	border: none;	/* prevent double border */
 }
-.nihilo .dijitTab .closeImage {
+
+
+/* Close button */
+.nihilo .dijitTabCloseButton {
 	background: url("../images/spriteRoundedIconsSmall.png") no-repeat -60px top;
 	width: 15px;
 	height: 15px;
 	margin-top: -1px;
 }
-.dj_ie6 .nihilo .dijitTab .closeImage {
+
+.dj_ie6 .nihilo .dijitTabCloseButton {
 	background: url("../images/spriteRoundedIconsSmall.gif") no-repeat -60px top;
 }
-.nihilo .dijitTab .closeButton-hover .closeImage {
+.nihilo .dijitTabCloseButtonHover {
 	background: url("../images/spriteRoundedIconsSmall.png") no-repeat -60px -15px;
 }
-.dj_ie6 .nihilo .dijitTab .closeButton-hover .closeImage {
+.dj_ie6 .nihilo .dijitTabCloseButtonHover {
 	background: url("../images/spriteRoundedIconsSmall.gif") no-repeat -60px -15px;
 }
+
 .nihilo .dijitTab .tabLabel {
-	
+	/* make sure tabs w/close button and w/out close button are same height, even w/small (<15px) font */
 	min-height: 15px;
 	display: inline-block;
 }
 .dj_ie6 .nihilo .dijitTabButtonIcon {
-	
+	/* because min-height doesn't work on IE6 */
 	height: 18px;
 	width: 1px;
 }
+
+/* ================================ */
+/* top tabs */
 .nihilo .dijitTabContainerTop-tabs {
 	border-bottom: none;
 	padding-bottom: 1px;
 	background-position: bottom;
 	padding-left: 3px;
 }
+
 .dj_ie6 .nihilo .dijitTabListContainer-top,
 .dj_ie7 .nihilo .dijitTabListContainer-top {
 	z-index: 3;
 }
+
 .dj_ie6 .nihilo .dijitTabContainerTop-tabs,
 .dj_ie7 .nihilo .dijitTabContainerTop-tabs {
 	border-bottom: 1px solid #ccc;
 	padding-bottom: 0px;
 }
+
 .nihilo .dijitTabContainerTopNoStrip {
 	padding-top: 3px;
 }
+
+/* top container */
 .nihilo .dijitTabContainerTop-container {
 	border-top: none;
 }
+
+/* checked tabs */
 .nihilo .dijitTabContainerTop-tabs .dijitTabChecked {
 	border-bottom-color: #f8f8f8;
 }
+
+/* strip */
 .nihilo .dijitTabContainer .dijitTabContainerTopStrip {
 	border-bottom: none;
 	padding-top: 1px;
@@ -210,79 +189,105 @@
 	border-right: 1px solid #CCC;
 	border-left: 1px solid #CCC;
 }
+
+
+/* ================================ */
+/* bottom tabs */
 .nihilo .dijitTabContainerBottom-tabs {
 	border-top: none;
 	background-position: top;
 	padding-left: 3px;
 }
+
 .dj_ie6 .nihilo .dijitTabListContainer-bottom,
 .dj_ie7 .nihilo .dijitTabListContainer-bottom {
 	z-index: 3;
 }
+
 .dj_ie6 .nihilo .dijitTabContainerBottom-tabs,
 .dj_ie7 .nihilo .dijitTabContainerBottom-tabs {
 	border-top: 1px solid #ccc;
 	margin-top: -1px;
 }
+
+/* bottom container */
 .nihilo .dijitTabContainerBottom-container {
 	border-bottom: none;
 }
+
 .nihilo .dijitTabContainerBottom-tabs .dijitTab {
 	border-bottom: none;
 	border-top: 1px solid #ccc;
 	background: url("../images/tabBottomEnabledSpriteLR.gif") no-repeat bottom left;
 }
+
+/* checked tabs */
 .nihilo .dijitTabContainerBottom-tabs .dijitTabChecked {
 	border-top-color: #f8f8f8;
 }
+
 .nihilo .dijitTabContainerBottom-tabs .dijitTabInnerDiv .dijitTabContent {
 	padding-top: 3px;
 	padding-bottom: 3px;
 	background: url("../images/tabBottomEnabledC.gif") repeat-x bottom left;
 }
+
 .nihilo .dijitTabContainerBottom-tabs .dijitTabInnerDiv {
 	background: url("../images/tabBottomEnabledSpriteLR.gif") no-repeat bottom right;
 }
+
 .nihilo .dijitTabContainerBottom-tabs .dijitTabHover {
 	color: #243C5F;
 	background: url("../images/tabBottomHoverSpriteLR.gif") no-repeat bottom left;
 }
+
 .nihilo .dijitTabContainerBottom-tabs .dijitTabHover .dijitTabInnerDiv {
 	background: url("../images/tabBottomHoverSpriteLR.gif") no-repeat bottom right;
 }
+
 .nihilo .dijitTabContainerBottom-tabs .dijitTabHover .dijitTabInnerDiv .dijitTabContent {
 	background: url("../images/tabBottomHoverC.gif") repeat-x bottom left;
 }
-.nihilo .dijitTabContainerBottom-tabs .dijitTabChecked,
-.nihilo .dijitTabContainerBottom-tabs .dijitTabCloseButtonChecked
-{
-	
+
+.nihilo .dijitTabContainerBottom-tabs .dijitTabChecked {
+	/* the selected tab (with or without hover) */
 	background: url("../images/tabBottomActiveSpriteLR.gif") no-repeat bottom left;
 }
+
 .nihilo .dijitTabContainerBottom-tabs .dijitTabChecked .dijitTabInnerDiv {
 	background: url("../images/tabBottomActiveSpriteLR.gif") no-repeat bottom right;
 }
+
 .nihilo .dijitTabContainerBottom-tabs .dijitTabChecked .dijitTabInnerDiv .dijitTabContent {
 	background: url("../images/tabBottomActiveC.gif") repeat-x bottom left;
 }
+
+/* strip */
 .nihilo .dijitTabContainer .dijitTabContainerBottomStrip {
 	border: 1px solid #ccc;
 	background: #f2f2f2;
 	border-top: none;
 	padding-bottom: 2px;
 }
+
+/* top/bottom strip */
 .nihilo .dijitTabContainerBottom-spacer,
 .nihilo .dijitTabContainerTop-spacer {
 	height: 2px;
 	border: 1px solid #ccc;
 	background: #f8f8f8;
 }
+
 .nihilo  .dijitTabContainerTop-spacer {
 	margin-top: -1px;
 }
 .nihilo .dijitTabContainerBottom-spacer {
 	margin-bottom: -1px;
 }
+
+
+/* ================================ */
+/* right tabs */
 .nihilo .dijitTabContainerRight-tabs {
 	border-color: #ccc;
 	padding-top: 3px;
@@ -290,53 +295,76 @@
 .nihilo .dijitTabContainerRight .dijitTabListWrapper {
 	padding-right: 3px;
 }
+
+/* right container */
 .nihilo .dijitTabContainerRight-container {
 	border-right: none;
 }
+
 .nihilo .dijitTabContainerRight-tabs .dijitTab {
 	border-bottom: none;
 	border-left: 1px solid #ccc;
 	border-bottom: 1px solid #dedede !important;
 }
+
+
+/* some odd ie bug when borders dissapear when setting a bottom margin, this sortof helps */
 .dj_ie .nihilo .dijitTabContainerRight-tabs .dijitTabInnerDiv {
 	border-bottom: solid #fff 1px;
 }
+
+/* checked tabs */
 .nihilo .dijitTabContainerRight-tabs .dijitTabChecked {
 	border-left-color: #f8f8f8;
 }
+
 .nihilo .dijitTabContainerRight-tabs .dijitTabChecked {
 	background: url("../images/tabRightChecked.gif") no-repeat left top !important;
 }
+
+/* some odd ie bug when borders dissapear when setting a bottom margin, this sortof helps */
 .dj_ie .nihilo .dijitTabContainerRight-tabs .dijitTabChecked .dijitTabInnerDiv,
 .dj_ie .nihilo .dijitTabContainerRight-tabs .dijitTabCheckedHover .dijitTabInnerDiv {
 	border-bottom: solid #efefef 1px;
 }
+
 .nihilo .dijitTabContainerRight-tabs .dijitTab {
 	background: url("../images/tabContainerSprite.gif") no-repeat left -350px;
 }
 .nihilo .dijitTabContainerRight-tabs .dijitTabHover .dijitTab {
 	background: url("../images/tabContainerSprite.gif") no-repeat left -200px;
 }
+
+/* strip */
 .nihilo .dijitTabContainerRightStrip {
 	padding-right: 2px;
 	border: 1px solid #ccc;
 	border-left: none;
 	background: #f2f2f2;
 }
+
+/* ================================ */
+/* left tabs */
 .nihilo .dijitTabContainerLeft-tabs {
 	border-color: #ccc;
 	padding-top: 3px;
 }
+
+/* left conatiner */
 .nihilo .dijitTabContainerLeft-container {
 	border-left: none;
 }
+
 .nihilo .dijitTabContainerLeft-tabs .dijitTab {
 	border-right: 1px solid #ccc;
 	border-bottom: 1px solid #dedede;
 }
+
+/* checked tabs */
 .nihilo .dijitTabContainerLeft-tabs .dijitTabChecked {
 	border-right: 1px solid #f8f8f8;
 }
+
 .nihilo .dijitTabContainerLeft-tabs .dijitTabInnerDiv {
 	background: url("../images/tabContainerSprite.gif") no-repeat right -350px;
 }
@@ -347,35 +375,47 @@
 .nihilo .dijitTabContainerLeft-tabs .dijitTabCheckedHover .dijitTabInnerDiv {
 	background: url("../images/tabLeftChecked.gif") no-repeat right top;
 }
+
 .dj_ie .nihilo .dijitTabContainerLeft-tabs .dijitTabChecked .dijitTabInnerDiv,
 .dj_ie .nihilo .dijitTabContainerLeft-tabs .dijitTabCheckedHover .dijitTabInnerDiv {
 	border-bottom: solid #efefef 1px;
 }
+
 .dj_ie .nihilo .dijitTabContainerLeft-tabs .dijitTabInnerDiv {
 	border-bottom: solid #fff 1px;
 }
+
+/* strip */
 .nihilo .dijitTabContainerLeftStrip {
 	padding-left: 2px;
 	border: 1px solid #ccc;
 	border-right: none;
 }
+
 .nihilo .dijitTabContainerLeftStrip {
 	background: #f2f2f2;
 }
+
+/* ================================ */
+/* left/right tabs */
 .nihilo .dijitTabContainerLeft-tabs .dijitTab,
 .nihilo .dijitTabContainerRight-tabs .dijitTab {
 	margin-right:auto;
-	margin-bottom:2px;	
+	margin-bottom:2px;	/* space between one tab and the next in left/right mode */
 }
+
+/* left/right tabstrip */
 .nihilo .dijitTabContainerLeft-spacer,
 .nihilo .dijitTabContainerRight-spacer {
 	width: 2px;
 	border: 1px solid #ccc;
 	background: #f8f8f8;
 }
+
 .nihilo .dijitTabContainerRight-spacer {
 	border-right: none;
 }
+
 .nihilo .dijitTabContainerRight-tabs {
 	padding-top: 3px;
 	height: 100%;
@@ -383,9 +423,14 @@
 .nihilo .dijitTabContainerLeft-tabs {
 	height: 100%;
 }
+
 .nihilo .dijitTabContainerLeft-spacer {
 	border-left: none;
 }
+
+/* ================================ */
+
+/* this resets the tabcontainer stripe when within a contentpane */
 .nihilo .dijitTabContainerTop-dijitContentPane .dijitTabContainerTop-tabs {
 	border-left: 0px solid #ccc;
 	border-top: 0px solid #ccc;
@@ -393,56 +438,70 @@
 	padding-top: 0px;
 	padding-left: 0px;
 }
+
+/* ================================ */
+
+/* Menu and slider control styles */
 .nihilo .dijitTabContainer .tabStripButton {
 	margin-right: 0px;
 }
+
 .nihilo .tabStripButton .dijitTabInnerDiv .dijitTabContent {
 	padding: 5px 0 6px;
 }
+
 .dj_ie6 .nihilo .tabStripButton .dijitTabInnerDiv .dijitTabContent,
 .dj_ie7 .nihilo .tabStripButton .dijitTabInnerDiv .dijitTabContent,
 .dj_opera .nihilo .tabStripButton .dijitTabInnerDiv .dijitTabContent {
 	padding-bottom: 7px;
 }
+
 .nihilo .tabStrip-disabled .tabStripButton .dijitTabInnerDiv .dijitTabContent {
 	padding: 3px 0 5px;
 }
+
 .dj_ie6 .nihilo .tabStrip-disabled .tabStripButton .dijitTabInnerDiv .dijitTabContent,
 .dj_ie7 .nihilo .tabStrip-disabled .tabStripButton .dijitTabInnerDiv .dijitTabContent,
 .dj_opera .nihilo .tabStrip-disabled .tabStripButton .dijitTabInnerDiv .dijitTabContent {
 	padding-top: 4px;
 }
-.nihilo .dijitTabContainer .tabStripButton {
-	
-	width: 21px;
-}
-.nihilo .dijitTabContainer .tabStripButton img {
+
+.nihilo .dijitTabStripIcon {
 	height: 14px;
-	background: url(../images/spriteRoundedIconsSmall.png) no-repeat left top ;
+	width: 14px;
+	background: url(../images/spriteRoundedIconsSmall.png) no-repeat left top;
 }
-.dj_ie6 .nihilo .dijitTabContainer .tabStripButton img {
+
+.dj_ie6 .nihilo .dijitTabStripIcon {
 	background-image: url(../images/spriteRoundedIconsSmall.gif);
 }
-.nihilo .dijitTabContainer .tabStripSlideButtonRight img {
+
+.nihilo .dijitTabStripSlideRightIcon {
 	background-position: -30px top;
 }
-.nihilo .dijitTabContainer .tabStripMenuButton img {
+
+.nihilo .dijitTabStripMenuIcon {
 	background-position: -15px top;
 }
+
 .nihilo .dijitTabContainerTopNone {
 	padding-top: 0px;
 }
+
 .nihilo .dijitTabContainer .tabStripButton-top {
 	margin-top: 1px;
 }
+
 .nihilo .dijitTabContainer .tabStripButton-bottom {
 	background: transparent url(../images/tabBottomEnabledSpriteLR.gif) no-repeat scroll left bottom;
 	border-bottom: medium none;
 	border-top: 1px solid #CCCCCC;
 }
+
 .nihilo .dijitTabContainer .tabStripButton-bottom .dijitTabInnerDiv {
 	background: transparent url(../images/tabBottomEnabledSpriteLR.gif) no-repeat scroll right bottom;
 }
+
 .nihilo .dijitTabContainer .tabStripButton-bottom .dijitTabContent {
 	background: transparent;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/layout/TabContainer_rtl.css b/dijit/themes/nihilo/layout/TabContainer_rtl.css
index 8a55f50..7421e2e 100644
--- a/dijit/themes/nihilo/layout/TabContainer_rtl.css
+++ b/dijit/themes/nihilo/layout/TabContainer_rtl.css
@@ -1,10 +1,13 @@
 .dijitRtl .nihilo .dijitTab {
 	margin-right:0;
-	margin-left:2px;		
+	margin-left:2px;		/* space between one tab and the next in top/bottom mode */
 }
+
+/* tab strips */
 .dijitRtl .nihilo .dijitTabContainer .tabStripButton {
 	margin-left: 0;
 }
+
 .dijitRtl .nihilo .dijitTabContainerTopStrip,
 .dijitRtl .nihilo .dijitTabContainerBottomStrip,
 .dijitRtl .nihilo .dijitTabContainerTop-tabs,
@@ -12,23 +15,29 @@
 	padding-left: 0;
 	padding-right: 3px;
 }
+
 .dijitRtl .nihilo .dijitTabInnerDiv {
 	padding-left: 3px;
 	padding-right: 4px;
 }
+
 .dijitRtl .nihilo .dijitTabPaneWrapper {
 	#zoom: 1;
 }
+
 .dj_ie-rtl .nihilo .dijitTabContainerLeft-tabs {
 	margin-left: 0px !important;
 }
+
 .dj_ie-rtl .nihilo .dijitTabContainerRight-tabs {
 	margin-right: 0px !important;
 }
+
 .dijitRtl .nihilo .dijitTabContainerLeft-tabs .dijitTab,
 .dijitRtl .nihilo .dijitTabContainerRight-tabs .dijitTab {
 	margin-left:0px;
 }
+
 .dj_ie-rtl .nihilo .dijitTab .dijitTabInnerDiv{
 	width : 1%;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/nihilo/nihilo.css b/dijit/themes/nihilo/nihilo.css
index 6a42a06..97ba8f6 100644
--- a/dijit/themes/nihilo/nihilo.css
+++ b/dijit/themes/nihilo/nihilo.css
@@ -1,3159 +1,42 @@
+/*
+	Adds cosmetic styling to Dijit.  Users may swap with a custom theme CSS file.
 
-.dijitReset {
-	
-	margin:0;
-	border:0;
-	padding:0;
-	line-height:normal;
-	font: inherit;
-	color: inherit;
-}
-.dijitInline {
-	
-	display:inline-block;			
-	#zoom: 1; 
-	#display:inline; 
-	border:0;
-	padding:0;
-	vertical-align:middle;
-	#vertical-align: auto;	
-}
-.dijitHidden {
-	
-	display: none !important;
-}
-.dijitVisible {
-	
-	display: block !important;	
-	position: relative;			
-}
-.dj_ie INPUT.dijitTextBox,
-.dj_ie .dijitInputField INPUT {
-	font-size: 100%;
-}
-.dj_ie .dijitInputField INPUT { 
-	margin: -1px 0 !important;
-}
-.dijitInlineTable {
-	
-	display:inline-table;
-	display:inline-block;		
-	#zoom: 1; 
-	#display:inline; 
-	box-sizing: content-box; -moz-box-sizing: content-box;
-	border:0;
-	padding:0;
-}
-.dijitTeeny {
-	font-size:1px;
-	line-height:1px;
-}
-.dijitPopup {
-	position: absolute;
-	background-color: transparent;
-	margin: 0;
-	border: 0;
-	padding: 0;
-}
-.dijit_a11y .dijitPopup,
-.dijit_ally .dijitPopup div,
-.dijit_a11y .dijitPopup table,
-.dijit_a11y .dijitTooltipContainer {
-	background-color: white !important;
-}
-.dijitInputField {
-	overflow:hidden;
-	#zoom:1;
-}
-.dijitPositionOnly {
-	
-	padding: 0 !important;
-	border: 0 !important;
-	background-color: transparent !important;
-	background-image: none !important;
-	height: auto !important;
-	width: auto !important;
-}
-.dijitNonPositionOnly {
-	
-	float: none !important;
-	position: static !important;
-	margin: 0 0 0 0 !important;
-	vertical-align: middle !important;
-}
-.dijitBackgroundIframe {
-	
-	position: absolute;
-	left: 0;
-	top: 0;
-	width: 100%;
-	height: 100%;
-	z-index: -1;
-	border: 0;
-	padding: 0;
-	margin: 0;
-}
-.dijitClickableRegion {
-	
-	background-color: #e2ebf2;
-	cursor: text;
-}
-.dijitDisplayNone {
-	
-	display:none !important;
-}
-.dijitContainer {
-	
-	overflow: hidden;	
-}
-.dijit_a11y * {
-	background-image:none !important;
-}
-.dijit_a11y .dijitCalendarIncrementControl {
-	display: none;	
-}
-.dijit_a11y .dijitA11ySideArrow {
-	display: inline !important; 
-	cursor: pointer;
-}
-.dijit_a11y .dijitCalendarDateLabel {
-	padding: 1px;
-}
-.dijit_a11y .dijitCalendarSelectedDate .dijitCalendarDateLabel {
-	border: solid 1px black;
-	padding: 0px;
-}
-.dijit_a11y .dijitCalendarDateTemplate {
-	padding-bottom: 0.1em !important;	
-}
-.dijit_a11y .dijit * {
-	background:white !important;
-	color:black !important;
-}
-.dijit_a11y .dijitButtonNode {
-	border-color: black!important;
-	border-style: outset!important;
-	border-width: medium!important;
-}
-.dijit_a11y .dijitComboBoxReadOnly .dijitInputField,
-.dijit_a11y .dijitComboBoxReadOnly .dijitButtonNode,
-.dijit_a11y .dijitSpinnerReadOnly .dijitButtonNode,
-.dijit_a11y .dijitSpinnerReadOnly .dijitInputField,
-.dijit_a11y .dijitButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitDropDownButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitComboButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitComboBoxDisabled .dijitInputField,
-.dijit_a11y .dijitComboBoxDisabled .dijitButtonNode,
-.dijit_a11y .dijitSpinnerDisabled .dijitButtonNode,
-.dijit_a11y .dijitSpinnerDisabled .dijitInputField {
-	border-style: outset!important;
-	border-width: medium!important;
-	border-color: #999 !important;
-	color:#999 !important;
-}
-.dijitButtonNode * {
-	vertical-align: middle;
-}
-.dijit_a11y .dijitArrowButtonInner {
-	width: 1em;
-	display: none !important;
-}
-.dijitButtonNode .dijitArrowButtonInner {
-	background:no-repeat center;
-	width: 16px;
-}
-.dijitComboBox .dijitArrowButtonInner {
-	display: block;
-}
-.dijit_a11y .dijitToggleButtonChecked .dijitToggleButtonIconChar {
-	display: inline !important;
-}
-.dijitLeft {
-	
-	background-position:left top;
-	background-repeat:no-repeat;
-}
-.dijitStretch {
-	
-	white-space:nowrap;			
-	background-repeat:repeat-x;
-}
-.dijitRight {
-	
-	#display:inline;				
-	background-position:right top;
-	background-repeat:no-repeat;
-}
-.dijitToggleButton,
-.dijitButton,
-.dijitDropDownButton,
-.dijitComboButton {
-	
-	margin: 0.2em;
-}
-.dijitToolbar .dijitToggleButton,
-.dijitToolbar .dijitButton,
-.dijitToolbar .dijitDropDownButton,
-.dijitToolbar .dijitComboButton {
-	margin: 0;
-}
-.dj_ie8 .dijitToolbar button,
-.dj_webkit .dijitToolbar button {
-	
-	padding: 1px 2px;
-}
-.dj_ie .dijitToolbar .dijitComboBox{
-	
-	vertical-align: middle;
-}
-.dj_ie .dijitComboButton {
-	
-	margin-bottom: -3px;
-}
-.dj_webkit .dijitToolbar .dijitDropDownButton {
-	padding-left: 0.3em;
-}
-.dj_gecko .dijitToolbar .dijitButtonNode::-moz-focus-inner {
-	padding:0;
-}
-.dijitButtonNode {
-	
-	border:1px solid gray;
-	margin:0;
-	line-height:normal;
-	vertical-align: middle;
-	#vertical-align: auto;
-	text-align:center;
-	white-space: nowrap;
-}
-.dijitButtonNode, .dijitButtonNode * {
-	cursor: pointer;
-}
-.dijitReadOnly *,
-.dijitDisabled *,
-.dijitReadOnly,
-.dijitDisabled,
-.dijitDisabledClickableRegion {	
-	cursor: not-allowed !important;
-}
-.dj_ie .dijitButtonNode {
-	
-	zoom: 1;
-}
-.dj_ie .dijitButtonNode button {
-	
-	overflow: visible;
-}
-.dijitArrowButton {
-	
-	
-	padding: 0 .4em;
-}
-DIV.dijitArrowButton {
-	float: right;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	border-style: solid;
-	border-width: 0 0 0 1px !important;
-	padding: 0;
-	position: absolute;
-	right: 0;
-	float: none;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	position: absolute;
-	height: 50%;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitDownArrowButton {
-	top: auto;
-	bottom: 0;
-	border-top-width: 1px !important;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitUpArrowButton {
-	top: 0;
-	bottom: auto;
-}
-TABLE.dijitComboButton {
-	
-	border-collapse: collapse;
-	border:0;
-	padding:0;
-	margin:0;
-}
-.dijitToolbar .dijitComboButton {
-	
-	border-collapse: separate;
-}
-.dj_ie BUTTON.dijitButtonNode {
-	overflow: visible; 
-}
-table .dijitButton .dijitButtonNode,
-table .dijitComboButton .dijitButtonNode {
-	#overflow:hidden; 
-}
-.dijitButtonNode IMG {
-	
-	vertical-align:middle;
-	
-}
-.dijitTextBox,
-.dijitComboBox,
-.dijitSpinner {
-	border: solid black 1px;
-	#overflow: hidden; 
-	width: 15em;	
-	vertical-align: middle;
-	#vertical-align: auto;
-}
-.dijitTimeTextBox {
-	width: 8em;
-}
-.dijitTextBox input:focus,
-.dijitComboBox input:focus,
-.dijitSpinner input:focus {
-	outline: none;	
-}
-.dijitTextBoxFocused,
-.dijitComboBoxFocused,
-.dijitSpinnerFocused, .dijitSpinnerUpArrowActive, .dijitSpinnerDownArrowActive,
-.dijitTextAreaFocused {
-	
-	outline: auto 5px -webkit-focus-ring-color;
-}
-.dijitTextBox INPUT,
-.dijitComboBox INPUT,
-.dijitSpinner INPUT {
-	border-left: solid black 1px;	
-	display:inline;
-	position:static !important;
-	border:0 !important;
-	margin:0 !important;
-	vertical-align:top !important;
-	background-color:transparent !important;
-	background-image:none !important;
-	width:100% !important;
-}
-.dijitValidationIcon {
-	visibility: hidden;
-	display: block;
-	padding: 0 2px;
-	float: right;
-	height: auto;
-}
-.dijitValidationIconText {
-	visibility: hidden;
-	display: none;
-	float:right;
-	font-family: sans-serif;
-	font-style:italic;
-	font-size: 0.75em;
-	padding-right: 0.15em;
-	line-height: 160%;
-}
-.dijit_a11y .dijitValidationIcon { display: none !important; }
-.dijit_a11y .dijitValidationIconText { display: block !important; }
-.dijitError .dijitValidationIcon,
-.dijitError .dijitValidationIconText {
-	visibility: visible;
-}
-.dijitTextBox .dijitArrowButton {
-	
-	display:none;
-}
-.dijitCheckBox,
-.dijitRadio,
-.dijitCheckBoxInput {
-	padding: 0;
-	border: 0;
-	width: 16px;
-	height: 16px;
-	background-position:center center;
-	background-repeat:no-repeat;
-	overflow: hidden;
-}
-.dijitCheckBox INPUT,
-.dijitRadio INPUT {
-	margin: 0;
-	padding: 0;
-	display: block;
-}
-.dijitCheckBoxInput {
-	
-	opacity: 0.01;
-}
-.dj_ie .dijitCheckBoxInput {
-	filter: alpha(opacity=0);
-}
-.dijit_a11y .dijitCheckBox,
-.dijit_a11y .dijitRadio {
-	width: auto;
-	height: auto;
-}
-.dijit_a11y .dijitCheckBoxInput {
-	opacity: 1;
-	filter: none;
-	width: auto;
-	height: auto;
-}
-.dijitProgressBarEmpty{
-	
-	position:relative;overflow:hidden;
-	border:1px solid black; 	
-	z-index:0;			
-}
-.dijitProgressBarFull {
-	
-	position:absolute;
-	overflow:hidden;
-	z-index:-1;
-	top:0;
-	width:100%;
-}
-.dj_ie6 .dijitProgressBarFull {
-	height:1.6em;
-}
-.dijitProgressBarTile {
-	
-	position:absolute;
-	overflow:hidden;
-	top:0;
-	left:0;
-	bottom:0;
-	right:0;
-	margin:0;
-	padding:0;
-	width:auto;
-	height:auto;
-	background-color:#aaa;
-	background-attachment: fixed;
-}
-.dijit_a11y .dijitProgressBarTile{
-	
-	border-width:4px;
-	border-style:solid;
-	background-color:transparent !important;
-}
-.dj_ie6 .dijitProgressBarTile {
-	
-	position:static;
-	
-	height:1.6em;
-}
-.dijitProgressBarIndeterminate .dijitProgressBarLabel {
-	visibility:hidden;
-}
-.dijitProgressBarIndeterminate .dijitProgressBarTile {
-	
-}
-.dijitProgressBarIndeterminateHighContrastImage {
-	display:none;
-}
-.dijit_a11y .dijitProgressBarIndeterminate .dijitProgressBarIndeterminateHighContrastImage {
-	display:block;
-	position:absolute;
-	top:0;
-	bottom:0;
-	margin:0;
-	padding:0;
-	width:100%;
-	height:auto;
-}
-.dijitProgressBarLabel {
-	display:block;
-	position:static;
-	width:100%;
-	text-align:center;
-	background-color:transparent !important;
-}
-.dijitTooltip {
-	position: absolute;
-	z-index: 2000;
-	display: block;
-	
-	left: 50%;
-	top: -10000px;
-	overflow: visible;
-}
-.dijitTooltipContainer {
-	border: solid black 2px;
-	background: #b8b5b5;
-	color: black;
-	font-size: small;
-}
-.dijitTooltipFocusNode {
-	padding: 2px 2px 2px 2px;
-}
-.dijitTooltipConnector {
-	position: absolute;
-}
-.dijitTooltipData {
-	display:none;
-}
-.dijitLayoutContainer{
-	position: relative;
-	display: block;
-	overflow: hidden;
-}
-body .dijitAlignTop,
-body .dijitAlignBottom,
-body .dijitAlignLeft,
-body .dijitAlignRight {
-	position: absolute;
-	overflow: hidden;
-}
-body .dijitAlignClient { position: absolute; }
-.dijitBorderContainer, .dijitBorderContainerNoGutter {
-	position:relative;
-	overflow: hidden;
-}
-.dijitBorderContainerPane,
-.dijitBorderContainerNoGutterPane {
-	position: absolute !important;	
-	z-index: 2;		
-}
-.dijitBorderContainer > .dijitTextArea {
-	
-	resize: none;
-}
-.dijitGutter {
-	
-	position: absolute;
-	font-size: 1px;		
-}
-.dijitSplitter {
-	position: absolute;
-	overflow: hidden;
-	z-index: 10;		
-	background-color: #fff;
-	border-color: gray;
-	border-style: solid;
-	border-width: 0;
-}
-.dj_ie .dijitSplitter {
-	z-index: 1;	
-}
-.dijitSplitterActive {
-	z-index: 11 !important;
-}
-.dijitSplitterCover{
-	position:absolute;
-	z-index:-1;
-	top:0;
-	left:0;
-	width:100%;
-	height:100%;
-}
-.dijitSplitterCoverActive{
-	z-index:3 !important;
-}
-.dj_ie .dijitSplitterCover{
-	background: white;
-	filter: alpha(opacity=0);
-}
-.dijitSplitterH {
-	height: 7px;
-	border-top:1px;
-	border-bottom:1px;
-	cursor: ns-resize;
-}
-.dijitSplitterV {
-	width: 7px;
-	border-left:1px;
-	border-right:1px;
-	cursor: ew-resize;
-}
-.dijitSplitContainer{
-	position: relative;
-	overflow: hidden;
-	display: block;
-}
-.dijitSplitPane{
-	position: absolute;
-}
-.dijitSplitContainerSizerH,
-.dijitSplitContainerSizerV {
-	position:absolute;
-	font-size: 1px;
-	cursor: move;
-	cursor: w-resize;
-	background-color: ThreeDFace;
-	border: 1px solid;
-	border-color: ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight;
-	margin: 0;
-}
-.dijitSplitContainerSizerH .thumb, .dijitSplitterV .dijitSplitterThumb {
-	overflow:hidden;
-	position:absolute;
-	top:49%;
-}
-.dijitSplitContainerSizerV .thumb, .dijitSplitterH .dijitSplitterThumb {
-	position:absolute;
-	left:49%;
-}
-.dijitSplitterShadow,
-.dijitSplitContainerVirtualSizerH,
-.dijitSplitContainerVirtualSizerV {
-	font-size: 1px;
-	background-color: ThreeDShadow;
-	-moz-opacity: 0.5;
-	opacity: 0.5;
-	filter: Alpha(Opacity=50);
-	margin: 0;
-}
-.dj_ie .dijitSplitterV, .dijitSplitContainerVirtualSizerH {
-	cursor: w-resize;
-}
-.dj_ie .dijitSplitterH, .dijitSplitContainerSizerV, .dijitSplitContainerVirtualSizerV {
-	cursor: n-resize;
-}
-.dijit_a11y .dijitSplitterH {
-	border-top:1px solid #d3d3d3 !important;
-	border-bottom:1px solid #d3d3d3 !important;
-}
-.dijit_a11y .dijitSplitterV {
-	border-left:1px solid #d3d3d3 !important;
-	border-right:1px solid #d3d3d3 !important;
-}
-.dijitContentPane {
-	display: block;
-	overflow: auto;	
-}
-.dijitContentPaneSingleChild {
-	
-	overflow: hidden;
-}
-.dijitTitlePane {
-	display: block;
-	overflow: hidden;
-}
-.dijitColorPalette {
-	border:1px solid #999;
-	background:#fff;
-	-moz-border-radius:3pt;
-}
-img.dijitColorPaletteUnder {
-	border-style:none;
-	position:absolute;
-	left:0;
-	top:0;
-}
-.dijitColorPaletteInner {
-	position: relative;
-	overflow:hidden;
-	outline:0;
-}
-.dijitPaletteCell {
-	width: 20px;
-	height: 20px;
-	position: absolute;
-	overflow: hidden;
-	z-index: 10;
-	outline-width: 0;
-}
-.dijitPaletteImg {
-	width: 16px; 
-	height: 14px; 
-	position: absolute;
-	top: 1px;
-	left: 1px;
-	overflow: hidden;
-	cursor: default;
-	border:1px solid #999;
-	
-}
-.dijitPaletteCellHighlight img {
-	width: 14px; 
-	height: 12px; 
-	position: absolute;
-	top: 1px;
-	left: 1px;
-	overflow: hidden;
-	cursor: default;
-	border:2px solid #000;
-	outline:1px solid #dedede;
-	
-}
-.dijit_a11y .dijitPaletteCell {
-	background-color:transparent !important;
-}
-.dijit_a11y .dijitPaletteImg {
-	background-color:transparent !important;
-}
-.dijitAccordionContainer {
-	border:1px solid #b7b7b7;
-	border-top:0 !important;
-}
-.dj_webkit .dijitAccordionContainer  div:focus {
-	outline:none;
-}
-.dj_ff3 .dijitAccordionContainer  div:focus {
-	outline:none;
-}
-.dijitAccordionTitle {
-	cursor: pointer;
-}
-.dijitAccordionFocused  {
-	text-decoration: underline;
-}
-.dijitAccordionTitle .arrowTextUp,
-.dijitAccordionTitle .arrowTextDown {
-	display: none;
-	font-size: 0.65em;
-	font-weight: normal !important;
-}
-.dijit_a11y .dijitAccordionTitle .arrowTextUp,
-.dijit_a11y .dijitAccordionTitle-selected .arrowTextDown {
-	display: inline;
-}
-.dijit_a11y .dijitAccordionTitle-selected .arrowTextUp {
-	display: none;
-}
-.dijitCalendarContainer thead tr th, .dijitCalendarContainer thead tr td, .dijitCalendarContainer tbody tr td, .dijitCalendarContainer tfoot tr td {
-	padding: 0;
-}
-.dijitCalendarNextYear {
-	margin:0 0 0 0.55em;
-}
-.dijitCalendarPreviousYear {
-	margin:0 0.55em 0 0;
-}
-.dijitCalendarIncrementControl {
-	vertical-align: middle;
-}
-.dijitCalendarDisabledDate {
-	color:gray !important;
-}
-.dijitCalendarPreviousMonthDisabled,
-.dijitCalendarCurrentMonthDisabled,
-.dijitCalendarNextMonthDisabled {
-	cursor:default !important
-}
-.dijitCalendarIncrementControl,
-.dijitCalendarBodyContainer tbody tr td,
-.dijitCalendarDateTemplate,
-.dijitCalendarContainer .dijitInline {
-	cursor:pointer;
-}
-.dijitSpacer {
-	
-  	position: relative;
-  	height: 1px;
-  	overflow: hidden;
-  	visibility: hidden;
-}
-.dijitMenu {
-	border:1px solid black;
-	background-color:white;
-}
-.dijitMenuTable {
-	margin:1px 0;
-	border-collapse:collapse;
-	border-width:0;
-	background-color:white;
-}
-.dj_webkit .dijitMenuTable td[colspan="2"]{
-	border-right:hidden;
-}
-.dijitMenuItem{
-	text-align: left;
-	white-space: nowrap;
-	padding:.1em .2em;
-	cursor:pointer;
-}
-.dijitMenuPassive .dijitMenuItemHover,
-.dijitMenuItemSelected {
-	
-	background-color:black;
-	color:white;
-}
-.dijitMenuItemIcon, .dijitMenuExpand {
-	background-repeat: no-repeat;
-}
-.dijitMenuItemDisabled * {
-	
-	opacity:0.3;
-	cursor:default;
-}
-.dj_ie .dijit_a11y .dijitMenuItemDisabled td,
-.dj_ie .dijitMenuItemDisabled *,
-.dj_ie .dijitMenuItemDisabled td {
-	color:gray !important;
-	filter: alpha(opacity=35);
-}
-.dijitMenuItemLabel {
-	position: relative;
-	vertical-align: middle;
-}
-.dijit_a11y .dijitMenuItemSelected {
-	border: 1px #fff dotted !important;
-}
-.dj_ff3 .dijit_a11y .dijitMenuItem td {
-	padding: none !important;
-	background:none ! important;
-}
-.dijit_a11y .dijitMenuItemSelected .dijitMenuItemLabel {
-	border-width: 1px;
-	border-style: solid;
-}
-.dj_ie8 .dijit_a11y .dijitMenuItemLabel {
-	position:static;
-}
-.dijitMenuExpandA11y {
-	display: none;
-}
-.dijit_a11y .dijitMenuExpandA11y {
-	display: inline;
-}
-.dijitMenuSeparator td {
-	border: 0;
-	padding: 0;
-}
-.dijitMenuSeparatorTop {
-	height: 50%;
-	margin: 0;
-	margin-top:3px;
-	font-size: 1px;
-}
-.dijitMenuSeparatorBottom {
-	height: 50%;
-	margin: 0;
-	margin-bottom:3px;
-	font-size: 1px;
-}
-.dijitCheckedMenuItemIconChar {
-	vertical-align: middle;
-	visibility:hidden;
-}
-.dijitCheckedMenuItemChecked .dijitCheckedMenuItemIconChar {
-	visibility: visible;
-}
-.dijit_a11y .dijitCheckedMenuItemIconChar {
-	display:inline !important;
-}
-.dijit_a11y .dijitCheckedMenuItemIcon {
-	display: none;
-}
-.dijitStackController .dijitToggleButtonChecked * {
-	cursor: default;	
-}
-.dijitTabContainerNoLayout {
-	width: 100%;	
-}
-.dijitTabContainerBottom-tabs,
-.dijitTabContainerTop-tabs,
-.dijitTabContainerLeft-tabs,
-.dijitTabContainerRight-tabs {
-	overflow: visible !important;  
-}
-.dijitTabContainerBottom-container,
-.dijitTabContainerTop-container,
-.dijitTabContainerLeft-container,
-.dijitTabContainerRight-container {
-	z-index:0;
-	overflow: hidden;
-	border: 1px solid black;
-}
-.dijitTabContainer .nowrapTabStrip {
-	width: 50000px;
-	display: block;
-	position: relative;
-}
-.dijitTabContainer .dijitTabListWrapper {
-	overflow: hidden;
-}
-.dijit_a11y .dijitTabContainer .tabStripButton img {
-	
-	display: none;
-}
-.dijitTabContainerTop-tabs {
-	border-bottom: 1px solid black;
-}
-.dijitTabContainerTop-container {
-	border-top: 0px;
-}
-.dijitTabContainerLeft-tabs {
-	border-right: 1px solid black;
-	float: left;
-}
-.dijitTabContainerLeft-container {
-	border-left: 0px;
-}
-.dijitTabContainerBottom-tabs {
-	border-top: 1px solid black;
-}
-.dijitTabContainerBottom-container {
-	border-bottom: 0px;
-}
-.dijitTabContainerRight-tabs {
-	border-left: 1px solid black;
-	float: left;
-}
-.dijitTabContainerRight-container {
-	border-right: 0px;
-}
-div.dijitTabBtnDisabled, .dj_ie div.dijitTabBtnDisabled {
-	cursor: auto;
-}
-.dijitTab {
-	position:relative;
-	cursor:pointer;
-	white-space:nowrap;
-	z-index:3;
-}
-.dijitTab * {
-	
-	vertical-align: middle;
-}
-.dijitTabChecked {
-	cursor: default;	
-}
-.dijitTabButtonIcon {
-	height: 18px;
-}
-.dijitTabContainerTop-tabs .dijitTab {
-	top: 1px;	
-}
-.dijitTabContainerBottom-tabs .dijitTab {
-	top: -1px;	
-}
-.dijitTabContainerLeft-tabs .dijitTab {
-	left: 1px;	
-}
-.dijitTabContainerRight-tabs .dijitTab {
-	left: -1px;	
-}
-.dijitTabContainerTop-tabs .dijitTab,
-.dijitTabContainerBottom-tabs .dijitTab {
-	
-	display:inline-block;			
-	#zoom: 1; 
-	#display:inline; 
-}
-.dijitTabInnerDiv {
-	position:relative;
-}
-.tabStripButton {
-	z-index: 12;
-}
-.dijitTabButtonDisabled .tabStripButton {
-	display: none;
-}
-.dijitTab .closeButton {
-	margin-left: 1em;
-}
-.dijitTab .closeText {
-	display:none;
-}
-.dijit_a11y .closeText {
-	display:inline;
-	margin: 0px 6px;
-}
-.dijit_a11y .dijitTab .closeImage {
-	display:none;
-}
-.dijit_a11y .closeButton-hover .closeText {
-	border:thin solid;
-}
-.dijit_a11y .dijitTabChecked {
-	border-style:dashed !important;
-}
-.dijit_a11y .dijitTabInnerDiv {
-	border-left:none !important;
- }
-.dijitTabPane,
-.dijitStackContainer-child,
-.dijitAccordionContainer-child {
-	
-    border: none !important;
-}
-.dijitInlineEditor {
-	
-	position:relative;
-	vertical-align:bottom;
-}
-.dj_ie .dijitInlineEditor {
-	vertical-align:middle;
-}
-.dijitInlineValue {
-	
-}
-.dijitInlineEditor .dijitButtonContainer {
-	
-	position:absolute;
-	right:0;
-	overflow:visible;
-}
-.dijitInlineEditor .saveButton,
-.dijitInlineEditor .cancelButton {
-}
-.dijitTreeIndent {
-	
-	width: 19px;
-}
-.dijitTreeRow, .dijitTreeContent {
-	white-space: nowrap;
-}
-.dijitTreeRow img {
-	
-	vertical-align: middle;
-}
-.dijitTreeContent {
-    cursor: default;
-}
-.dijitExpandoText {
-	display: none;
-}
-.dijit_a11y .dijitExpandoText {
-	display: inline;
-	padding-left: 10px;
-	padding-right: 10px;
-	font-family: monospace;
-	border-style: solid;
-	border-width: thin;
-	cursor: pointer;
-}
-.dijitTreeLabel {
-	margin: 0px 4px;
-}
-.dijitDialog {
-	position: absolute;
-	z-index: 999;
-	padding: 1px;
-	overflow: hidden;       
-}
-.dijitDialogFixed div.dijitDialogTitleBar {
-	cursor:default;
-}
-.dijitDialogUnderlayWrapper {
-	position: absolute;
-	left: 0;
-	top: 0;
-	z-index: 998;
-	display: none;
-	background: transparent !important;
-}
-.dijitDialogUnderlay {
-	background: #eee;
-	opacity: 0.5;
-}
-.dj_ie .dijitDialogUnderlay {
-	filter: alpha(opacity=50);
-}
-.dijit_a11y .dijitInputLayoutContainer,
-.dijit_a11y .dijitDialog {
-	opacity: 1 !important;
-	background-color: white !important;
-}
-.dijitDialog .closeText {
-	display:none;
-	
-	position:absolute;
-}
-.dijit_a11y .dijitDialog .closeText {
-	display:inline;
-}
-.dijitSliderMoveable {
-	z-index:99;
-	position:absolute !important;
-	display:block;
-	vertical-align:middle;
-}
-.dijitSliderMoveableH {
-	right:0;
-}
-.dijit_a11y div.dijitSliderImageHandle,
-.dijitSliderImageHandle {
-	margin:0;
-	padding:0;
-	position:absolute !important;
-	border:8px solid gray;
-	width:0;
-	height:0;
-}
-.dijit_a11y .dijitSliderFocused .dijitSliderImageHandle {
-	border:4px solid #000;
-	height:8px;
-	width:8px;
-}
-.dijitSliderImageHandleV {
-	top:-8px;
-	left:-6px;
-}
-.dijitSliderImageHandleH {
-	left:-8px;
-	top:-5px;
-	vertical-align:top;
-}
-.dijitSliderBar {
-	border-style:solid;
-	border-color:black;
-}
-.dijitSliderBarContainerV {
-	position:relative;
-	height:100%;
-	z-index:1;
-}
-.dijitSliderBarContainerH {
-	position:relative;
-	z-index:1;
-}
-.dijitSliderBarH {
-	height:4px;
-	border-width:1px 0;
-}
-.dijitSliderBarV {
-	width:4px;
-	border-width:0 1px;
-}
-.dijitSliderProgressBar {
-	background-color:red;
-	z-index:1;
-}
-.dijitSliderProgressBarV {
-	position:static !important;
-	height:0%;
-	vertical-align:top;
-	text-align:left;
-}
-.dijitSliderProgressBarH {
-	position:absolute !important;
-	width:0%;
-	vertical-align:middle;
-	overflow:visible;
-}
-.dijitSliderRemainingBar {
-	overflow:hidden;
-	background-color:transparent;
-	z-index:1;
-}
-.dijitSliderRemainingBarV {
-	height:100%;
-	text-align:left;
-}
-.dijitSliderRemainingBarH {
-	width:100% !important;
-}
-.dijitSliderBumper {
-	overflow:hidden;
-	z-index:1;
-}
-.dijitSliderBumperV {
-	width:4px;
-	height:8px;
-	border-width:0 1px;
-}
-.dijitSliderBumperH {
-	width:8px;
-	height:4px;
-	border-width:1px 0;
-}
-.dijitSliderBottomBumper,
-.dijitSliderLeftBumper {
-	background-color:red;
-}
-.dijitSliderTopBumper,
-.dijitSliderRightBumper {
-	background-color:transparent;
-}
-.dijitSliderDecorationH {
-	text-align:center;
-}
-.dijitSlider .dijitSliderButton {
-	font-family:monospace;
-	margin:0;
-	padding:0;
-	display:block;
-}
-.dijit_a11y .dijitSliderButtonInner {
-	visibility:visible !important;
-}
-.dijitSliderButtonContainer {
-	text-align:center;
-	height:0;
-}
-.dijitSlider .dijitButtonNode {
-	padding:0;
-	display:block;
-}
-.dijitRuleContainer {
-	position:relative;
-	overflow:visible;
-}
-.dijitRuleContainerV {
-	height:100%;
-	line-height:0;
-	float:left;
-	text-align:left;
-}
-.dj_opera .dijitRuleContainerV {
-	line-height:2%;
-}
-.dj_ie .dijitRuleContainerV {
-	line-height:normal;
-}
-.dj_gecko .dijitRuleContainerV {
-	margin:0 0 1px 0; 
-}
-.dijitRuleMark {
-	position:absolute;
-	border:1px solid black;
-	line-height:0;
-	height:100%;
-}
-.dijitRuleMarkH {
-	width:0;
-	border-top-width:0 !important;
-	border-bottom-width:0 !important;
-	border-left-width:0 !important;
-}
-.dijitRuleLabelContainer {
-	position:absolute;
-}
-.dijitRuleLabelContainerH {
-	text-align:center;
-	display:inline-block;
-}
-.dijitRuleLabelH {
-	position:relative;
-	left:-50%;
-}
-.dijitRuleMarkV {
-	height:0;
-	border-right-width:0 !important;
-	border-bottom-width:0 !important;
-	border-left-width:0 !important;
-	width:100%;
-	left:0;
-}
-.dj_ie .dijitRuleLabelContainerV {
-	margin-top:-.55em;
-}
-.dijit_a11y .dijitButtonContents .dijitButtonText,
-.dijit_a11y .dijitTab .tabLabel {
-	display: inline !important;
-}
-.dj_ie7 .dijitButtonNode > BUTTON.dijitButtonContents > * {
-	position: relative; 
-}
-.dijitTextArea {
-	width:100%;
-	overflow-y: auto;	
-}
-.dijitTextArea[cols] {
-	width:auto; 
-}
-.dj_ie .dijitTextAreaCols {
-	width:auto;
-}
-.dijitTextArea > DIV {
-	text-decoration:none;
-	overflow:auto;
-	min-height: 1.40em;
-}
-.dj_ie .dijitTextArea p {
-	margin-top:0;
-	margin-bottom:0;
-	line-height: normal !important;
-}
-.dijitToolbarSeparator {
-	height: 18px;
-	width: 5px;
-	padding: 0 1px;
-	margin: 0;
-}
-.dijitIEFixedToolbar {
-	position:absolute;
-	
-	top: expression(eval((document.documentElement||document.body).scrollTop));
-}
-.RichTextEditable {
-	display: block;	
-}
-.dijitTimePickerItemInner {
-	text-align:center;
-	border:0;
-	padding:2px 8px 2px 8px;
-}
-.dijitTimePickerTick,
-.dijitTimePickerMarker {
-	border-bottom:1px solid gray;
-}
-.dijitTimePicker .dijitDownArrowButton {
-	border-top: none !important;
-}
-.dijitTimePickerTick {
-	color:#CCC;
-}
-.dijitTimePickerMarker {
-	color:black;
-	background-color:#CCC;
-}
-.dijitTimePickerItemSelected {
-	font-weight:bold;
-	color:#333;
-	background-color:#b7cdee;
-}
-.dijitTimePickerItemHover {
-	background-color:gray;
-	color:white;
-	cursor:pointer;
-}
-.dijit_a11y .dijitTimePickerItem {
-	border-bottom:1px solid #333;
-}
-.dijitToggleButtonIconChar {
-	display:none !important;
-}
-.dijit_a11y .dijitToggleButtonIconChar {
-	display:inline !important;
-}
-.dijit_a11y .dijitToggleButtonIconChar {
-	visibility:hidden;
-}
-.dijit_a11y .dijitToggleButtonChecked .dijitToggleButtonIconChar {
-	visibility:visible !important;
-}
-.dijitArrowButtonChar {
-	display:none !important;
-}
-.dijit_a11y .dijitArrowButtonChar {
-	display:inline !important;
-}
-.dijitInputLayoutContainer {
-	position: relative;
-	overflow: hidden;
-}
-.dijitSpinnerButtonContainer {
-	float: right;
-	width: 18px;
-	position: relative;
-	overflow: hidden;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	height: 50%;
-	width: 16px;
-	overflow: hidden;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButtonInner {
-	overflow: hidden;
-	line-height: 50%;
-}
-.dijit_a11y .dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	width: 100%;
-}
-.dijit_a11y .dijitSpinner .dijitArrowButton .dijitArrowButtonChar {
-	font-size: 0.4em;
-	vertical-align: top;
-}
-.dijit_a11y .dijitSpinnerButtonContainer {
-	width: 0.5em;
-	margin-left: 2px;
-	overflow: visible;
-}
-.dijit_a11y .dijitSpinnerButtonContainer .dijitButtonNode {
-	border-width: 1px 0px 0px 1px;
-	border-style: solid !important;
-}
-.dijitSelect {
-	margin: 0.2em;
-}
-.dj_ie .dijitSelect,
-.dj_ie7 .dijitSelect,
-.dj_iequirks .dijitSelect {
-	vertical-align: middle; 
-}
-.dj_ie8 .dijitSelect .dijitButtonText {
-	vertical-align: top;
-}
-.dijitSelect .dijitButtonNode {
-	text-align: left;
-}
-.dijitRtl .dijitSelect .dijitButtonNode {
-	text-align: right;
-}
-.dijitToolbar .dijitSelect {
-	margin: 0;
-}
-.dj_webkit .dijitToolbar .dijitSelect {
-	padding-left: 0.3em;
-}
-.dijit_a11y .dijitSelectDisabled .dijitButtonNode {
-	border-style: outset!important;
-	border-width: medium!important;
-	border-color: #999 !important;
-	color:#999 !important;
-}
-.dijitSelect .dijitButtonContents {
-	padding: 0px;
-	background: transparent none;
-}
-.dijitSelectFixedWidth .dijitButtonContents {
-	width: 100%;
-}
-.dijitSelect .dijitArrowButton {
-	width: 16px;
-}
-.dj_ie6 .dijitSelectMenu .dijitMenuItemLabel,
-.dj_ie7 .dijitSelectMenu .dijitMenuItemLabel {
-	
-	position: static;
-}
-.dijitSelectLabel *
-{
-	vertical-align: baseline;
-}
-.dijitSelectSelectedOption * {
-	font-weight: bold;
-}
-.dijitSelectMenu {
-	border-width: 1px;
-}
-.dijitSelect .dijitButtonContents {
-	white-space: nowrap;
-}
-.dijitSelectMenu .dijitMenuTable {
-	margin: 0px;
-	background-color: transparent;
-}
-.dijitTextBoxReadOnly,
-.dijitComboBoxReadOnly,
-.dijitSpinnerReadOnly,
-.dijitTextAreaReadOnly,
-.dijitTextBoxDisabled,
-.dijitComboBoxDisabled,
-.dijitSpinnerDisabled,
-.dijitTextAreaDisabled {
-	color: gray;
-}
-.dj_webkit .dijitTextBoxDisabled INPUT,
-.dj_webkit .dijitComboBoxDisabled INPUT,
-.dj_webkit .dijitSpinnerDisabled INPUT {
-	color: #eee;
-}
-.dj_webkit INPUT.dijitTextBoxDisabled,
-.dj_webkit TEXTAREA.dijitTextAreaDisabled {
-	color: #333; 
-}
-.dijit_a11y .dijitSliderReadOnly,
-.dijit_a11y .dijitSliderDisabled {
-	opacity:0.6;
-}
-.dj_ie .dijit_a11y .dijitSliderReadOnly .dijitSliderBar,
-.dj_ie .dijit_a11y .dijitSliderDisabled .dijitSliderBar {
-	filter: alpha(opacity=40);
-}
-.dijit_a11y .dijitSlider .dijitSliderButtonContainer DIV {
-	font-family: monospace; 
-	font-size: 1em;
-	line-height: 1em;
-	height: auto;
-	width: auto;
-	margin: 0px 4px;
-}
-.dijitForceStatic {
-    position: static !important;
-}
-.nihilo .dojoDndItemBefore {
-	border-top: 2px solid #369;
-}
-.nihilo .dojoDndItemAfter {
-	border-bottom: 2px solid #369;
-}
-.nihilo .dojoDndItemOver {
-	cursor:pointer;
-}
-.nihilo table.dojoDndAvatar { -moz-border-radius: 0; border: 1px solid #ccc; border-collapse: collapse; background-color: #fff; font-size: 75%; color: black;}
-.nihilo .dojoDndAvatar td	{ border: none; }
-.nihilo .dojoDndAvatar tr	{ border: none; }
-.nihilo .dojoDndAvatarHeader td	{ height: 20px; padding: 0 0 0 21px; }
-.nihilo .dojoDndAvatarItem td { padding: 2px;}
-.nihilo.dojoDndMove .dojoDndAvatarHeader	{background-color: #f58383; background-image: url(images/dndNoMove.png); background-repeat: no-repeat; background-position: 2px center;}
-.nihilo.dojoDndCopy .dojoDndAvatarHeader	{background-color: #f58383; background-image: url(images/dndNoCopy.png); background-repeat: no-repeat; background-position: 2px center;}
-.nihilo.dojoDndMove .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{background-color: #97e68d; background-image: url(images/dndMove.png); background-repeat: no-repeat; background-position: 2px center;}
-.nihilo.dojoDndCopy .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{background-color: #97e68d; background-image: url(images/dndCopy.png); background-repeat: no-repeat; background-position: 2px center;}
-.nihilo .dijitContentPane {
-    padding: 0px;
-}
-.nihilo .dijitTabContainerTop-dijitContentPane,
-.nihilo .dijitTabContainerLeft-dijitContentPane,
-.nihilo .dijitTabContainerRight-dijitContentPane,
-.nihilo .dijitTabContainerBottom-dijitContentPane,
-.nihilo .dijitAccordionContainer-dijitContentPane {
-    background-color: #fff;
-    padding: 5px;
-}
-.nihilo .dijitSplitContainer-dijitContentPane,
-.nihilo .dijitBorderContainer-dijitContentPane {
-    background-color: #fff;		
-    padding: 5px;
-}
-.nihilo .dijitMenu,
-.nihilo .dijitMenuBar {
-	border: 1px solid #d3d3d3;
-	margin: 0px;
-	padding: 0px;
-	background-color: #fff;
-}
-.nihilo .dijitBorderContainer .dijitMenuBar {
-	border: 1px #ccc solid;
-}
-.nihilo .dijitMenuItem {
-	font-family: sans-serif;
-	margin: 0px;
-	color: #243C5F;
-}
-.nihilo .dijitMenuBar .dijitMenuItem {
-	padding: 4px 5px;
-}
-.nihilo .dijitMenuPreviousButton, .nihilo .dijitMenuNextButton {
-	font-style: italic;
-}
-.nihilo .dijitMenuItem TD {
-	padding:1px;
-}
-.nihilo .dijitMenuPassive .dijitMenuItemHover,
-.nihilo .dijitMenuItemSelected {
-	background-color: #ffe284; 
-	color: #243C5F;
-}
-.nihilo .dijitMenuItemIcon {
-	width: 15px;
-	height: 15px;
-}
-.nihilo .dijitMenuExpand {
-	width:15px;
-	height:15px;
-	background-image: url(images/spriteRoundedIconsSmall.png);
-	background-position: -30px top;
-}
-.dj_ie6 .nihilo .dijitMenuExpand {
-	background-image:url(images/spriteRoundedIconsSmall.gif);
-}
-.nihilo .dijitMenuSeparator {
-	height: 1px;
-}
-.nihilo .dijitMenuSeparatorTop {
-	border-bottom: 1px solid #fff; 
-}
-.nihilo .dijitMenuSeparatorBottom {
-	border-top: 1px solid #d3d3d3;
-}
-.nihilo .dijitCheckedMenuItemIconChar {
-	display: none;
-}
-.nihilo .dijitCheckedMenuItemIcon {
-	background-image: url(images/spriteCheckbox.gif);
-	background-position: -80px;
-}
-.nihilo .dijitCheckedMenuItemChecked .dijitCheckedMenuItemIcon {
-	background-position: -64px;
-}
-.nihilo .dijitTabContainer .tabStripRBtn {
-	margin-right: 21px;
-}
-.nihilo .dijitTabContainer .tabStripLBtn {
-	margin-left: 21px;
-}
-.nihilo .dijitTabContainerBottom .nowrapTabStrip .dijitTab {
-	top: 0px;
-}
-.nihilo .dijitTabContainer .tabStripMenuButton-Hover {
-	cursor: pointer;
-}
-.nihilo .dijitTabPaneWrapper {
-	background:#fff;
-	border:1px solid #ccc;
-	margin: 0;
-	padding: 0;
-}
-.nihilo .dijitTabInnerDiv {
-	padding:0px 3px 0px 0px;
-	margin: 0 0 0 4px;
-	background: url(images/tabContainerSprite.gif) no-repeat;
-	background-position: right -400px;
-}
-.nihilo .dijitTab {
-	line-height:normal;
-	margin:0 2px 0 0;	
-	padding:0px;
-	background: url(images/tabContainerSprite.gif) no-repeat 0 -300px;
-	color: #6d6d6d;
-	border-bottom: 1px #ccc solid;
-}
-.nihilo .dijitTabInnerDiv .dijitTabContent {
-	padding:3px 3px 3px 4px;
-	background: url(images/tabContainerSprite.gif) repeat-x 0 -350px;
-	position: relative;
-}
-.nihilo .dijitTabHover {
-	color: #243C5F;
-	background: url(images/tabContainerSprite.gif) no-repeat 0px -150px;
-}
-.nihilo .dijitTabHover .dijitTabInnerDiv {
-	background: url(images/tabContainerSprite.gif) no-repeat right -250px;
-}
-.nihilo .dijitTabHover .dijitTabInnerDiv .dijitTabContent {
-	background: url(images/tabContainerSprite.gif) repeat-x 0 -200px;
-}
-.nihilo .dijitTabChecked,
-.nihilo .dijitTabCloseButtonChecked
-{
-	
-	background: url(images/tabContainerSprite.gif) no-repeat 0px -0px;
-}
-.nihilo .dijitTabChecked .dijitTabInnerDiv {
-	background: url(images/tabContainerSprite.gif) no-repeat right -100px;
-}
-.nihilo .dijitTabChecked .dijitTabInnerDiv .dijitTabContent {
-	background: url(images/tabContainerSprite.gif) repeat-x 0 -50px;
-	color: #243C5F !important;
-}
-.nihilo .dijitTabContainerNested .dijitTabListWrapper {
-	height: auto;
-}
-.nihilo .dijitTabContainerTabListNested {
-	background: #FDFDFD;
-	border: none;
-	margin-bottom: 0px;		
-}
-.nihilo .dijitTabContainerTabListNested .dijitTab {
-	background: none;
-	border: none;
-	top: 0px;	
-}
-.nihilo .dijitTabContainerTabListNested .dijitTab .dijitTabInnerDiv,
-.nihilo .dijitTabContainerTabListNested .dijitTab .dijitTabContent {
-	background: none;
-}
-.nihilo .dijitTabContainerTabListNested .dijitTabHover .dijitTabContent .tabLabel {
-	text-decoration: underline;
-}
-.nihilo .dijitTabContainerTabListNested .dijitTabChecked .tabLabel {
-	text-decoration: underline;
-	font-weight: bold;
-}
-.nihilo .dijitTabContainerSpacerNested {
-	
-	height: 0px;
-	border-bottom: 0px;
-}
-.nihilo .dijitTabPaneWrapperNested {
-	border: none;	
-}
-.nihilo .dijitTab .closeImage {
-	background: url(images/spriteRoundedIconsSmall.png) no-repeat -60px top;
-	width: 15px;
-	height: 15px;
-	margin-top: -1px;
-}
-.dj_ie6 .nihilo .dijitTab .closeImage {
-	background: url(images/spriteRoundedIconsSmall.gif) no-repeat -60px top;
-}
-.nihilo .dijitTab .closeButton-hover .closeImage {
-	background: url(images/spriteRoundedIconsSmall.png) no-repeat -60px -15px;
-}
-.dj_ie6 .nihilo .dijitTab .closeButton-hover .closeImage {
-	background: url(images/spriteRoundedIconsSmall.gif) no-repeat -60px -15px;
-}
-.nihilo .dijitTab .tabLabel {
-	
-	min-height: 15px;
-	display: inline-block;
-}
-.dj_ie6 .nihilo .dijitTabButtonIcon {
-	
-	height: 18px;
-	width: 1px;
-}
-.nihilo .dijitTabContainerTop-tabs {
-	border-bottom: none;
-	padding-bottom: 1px;
-	background-position: bottom;
-	padding-left: 3px;
-}
-.dj_ie6 .nihilo .dijitTabListContainer-top,
-.dj_ie7 .nihilo .dijitTabListContainer-top {
-	z-index: 3;
-}
-.dj_ie6 .nihilo .dijitTabContainerTop-tabs,
-.dj_ie7 .nihilo .dijitTabContainerTop-tabs {
-	border-bottom: 1px solid #ccc;
-	padding-bottom: 0px;
-}
-.nihilo .dijitTabContainerTopNoStrip {
-	padding-top: 3px;
-}
-.nihilo .dijitTabContainerTop-container {
-	border-top: none;
-}
-.nihilo .dijitTabContainerTop-tabs .dijitTabChecked {
-	border-bottom-color: #f8f8f8;
-}
-.nihilo .dijitTabContainer .dijitTabContainerTopStrip {
-	border-bottom: none;
-	padding-top: 1px;
-	margin-top: 1px;
-	background: #f2f2f2;
-	border-top: 1px solid #CCC;
-	border-right: 1px solid #CCC;
-	border-left: 1px solid #CCC;
-}
-.nihilo .dijitTabContainerBottom-tabs {
-	border-top: none;
-	background-position: top;
-	padding-left: 3px;
-}
-.dj_ie6 .nihilo .dijitTabListContainer-bottom,
-.dj_ie7 .nihilo .dijitTabListContainer-bottom {
-	z-index: 3;
-}
-.dj_ie6 .nihilo .dijitTabContainerBottom-tabs,
-.dj_ie7 .nihilo .dijitTabContainerBottom-tabs {
-	border-top: 1px solid #ccc;
-	margin-top: -1px;
-}
-.nihilo .dijitTabContainerBottom-container {
-	border-bottom: none;
-}
-.nihilo .dijitTabContainerBottom-tabs .dijitTab {
-	border-bottom: none;
-	border-top: 1px solid #ccc;
-	background: url(images/tabBottomEnabledSpriteLR.gif) no-repeat bottom left;
-}
-.nihilo .dijitTabContainerBottom-tabs .dijitTabChecked {
-	border-top-color: #f8f8f8;
-}
-.nihilo .dijitTabContainerBottom-tabs .dijitTabInnerDiv .dijitTabContent {
-	padding-top: 3px;
-	padding-bottom: 3px;
-	background: url(images/tabBottomEnabledC.gif) repeat-x bottom left;
-}
-.nihilo .dijitTabContainerBottom-tabs .dijitTabInnerDiv {
-	background: url(images/tabBottomEnabledSpriteLR.gif) no-repeat bottom right;
-}
-.nihilo .dijitTabContainerBottom-tabs .dijitTabHover {
-	color: #243C5F;
-	background: url(images/tabBottomHoverSpriteLR.gif) no-repeat bottom left;
-}
-.nihilo .dijitTabContainerBottom-tabs .dijitTabHover .dijitTabInnerDiv {
-	background: url(images/tabBottomHoverSpriteLR.gif) no-repeat bottom right;
-}
-.nihilo .dijitTabContainerBottom-tabs .dijitTabHover .dijitTabInnerDiv .dijitTabContent {
-	background: url(images/tabBottomHoverC.gif) repeat-x bottom left;
-}
-.nihilo .dijitTabContainerBottom-tabs .dijitTabChecked,
-.nihilo .dijitTabContainerBottom-tabs .dijitTabCloseButtonChecked
-{
-	
-	background: url(images/tabBottomActiveSpriteLR.gif) no-repeat bottom left;
-}
-.nihilo .dijitTabContainerBottom-tabs .dijitTabChecked .dijitTabInnerDiv {
-	background: url(images/tabBottomActiveSpriteLR.gif) no-repeat bottom right;
-}
-.nihilo .dijitTabContainerBottom-tabs .dijitTabChecked .dijitTabInnerDiv .dijitTabContent {
-	background: url(images/tabBottomActiveC.gif) repeat-x bottom left;
-}
-.nihilo .dijitTabContainer .dijitTabContainerBottomStrip {
-	border: 1px solid #ccc;
-	background: #f2f2f2;
-	border-top: none;
-	padding-bottom: 2px;
-}
-.nihilo .dijitTabContainerBottom-spacer,
-.nihilo .dijitTabContainerTop-spacer {
-	height: 2px;
-	border: 1px solid #ccc;
-	background: #f8f8f8;
-}
-.nihilo  .dijitTabContainerTop-spacer {
-	margin-top: -1px;
-}
-.nihilo .dijitTabContainerBottom-spacer {
-	margin-bottom: -1px;
-}
-.nihilo .dijitTabContainerRight-tabs {
-	border-color: #ccc;
-	padding-top: 3px;
-}
-.nihilo .dijitTabContainerRight .dijitTabListWrapper {
-	padding-right: 3px;
-}
-.nihilo .dijitTabContainerRight-container {
-	border-right: none;
-}
-.nihilo .dijitTabContainerRight-tabs .dijitTab {
-	border-bottom: none;
-	border-left: 1px solid #ccc;
-	border-bottom: 1px solid #dedede !important;
-}
-.dj_ie .nihilo .dijitTabContainerRight-tabs .dijitTabInnerDiv {
-	border-bottom: solid #fff 1px;
-}
-.nihilo .dijitTabContainerRight-tabs .dijitTabChecked {
-	border-left-color: #f8f8f8;
-}
-.nihilo .dijitTabContainerRight-tabs .dijitTabChecked {
-	background: url(images/tabRightChecked.gif) no-repeat left top !important;
-}
-.dj_ie .nihilo .dijitTabContainerRight-tabs .dijitTabChecked .dijitTabInnerDiv,
-.dj_ie .nihilo .dijitTabContainerRight-tabs .dijitTabCheckedHover .dijitTabInnerDiv {
-	border-bottom: solid #efefef 1px;
-}
-.nihilo .dijitTabContainerRight-tabs .dijitTab {
-	background: url(images/tabContainerSprite.gif) no-repeat left -350px;
-}
-.nihilo .dijitTabContainerRight-tabs .dijitTabHover .dijitTab {
-	background: url(images/tabContainerSprite.gif) no-repeat left -200px;
-}
-.nihilo .dijitTabContainerRightStrip {
-	padding-right: 2px;
-	border: 1px solid #ccc;
-	border-left: none;
-	background: #f2f2f2;
-}
-.nihilo .dijitTabContainerLeft-tabs {
-	border-color: #ccc;
-	padding-top: 3px;
-}
-.nihilo .dijitTabContainerLeft-container {
-	border-left: none;
-}
-.nihilo .dijitTabContainerLeft-tabs .dijitTab {
-	border-right: 1px solid #ccc;
-	border-bottom: 1px solid #dedede;
-}
-.nihilo .dijitTabContainerLeft-tabs .dijitTabChecked {
-	border-right: 1px solid #f8f8f8;
-}
-.nihilo .dijitTabContainerLeft-tabs .dijitTabInnerDiv {
-	background: url(images/tabContainerSprite.gif) no-repeat right -350px;
-}
-.nihilo .dijitTabContainerLeft-tabs .dijitTabHover .dijitTabInnerDiv {
-	background: url(images/tabContainerSprite.gif) no-repeat right -200px;
-}
-.nihilo .dijitTabContainerLeft-tabs .dijitTabChecked .dijitTabInnerDiv,
-.nihilo .dijitTabContainerLeft-tabs .dijitTabCheckedHover .dijitTabInnerDiv {
-	background: url(images/tabLeftChecked.gif) no-repeat right top;
-}
-.dj_ie .nihilo .dijitTabContainerLeft-tabs .dijitTabChecked .dijitTabInnerDiv,
-.dj_ie .nihilo .dijitTabContainerLeft-tabs .dijitTabCheckedHover .dijitTabInnerDiv {
-	border-bottom: solid #efefef 1px;
-}
-.dj_ie .nihilo .dijitTabContainerLeft-tabs .dijitTabInnerDiv {
-	border-bottom: solid #fff 1px;
-}
-.nihilo .dijitTabContainerLeftStrip {
-	padding-left: 2px;
-	border: 1px solid #ccc;
-	border-right: none;
-}
-.nihilo .dijitTabContainerLeftStrip {
-	background: #f2f2f2;
-}
-.nihilo .dijitTabContainerLeft-tabs .dijitTab,
-.nihilo .dijitTabContainerRight-tabs .dijitTab {
-	margin-right:auto;
-	margin-bottom:2px;	
-}
-.nihilo .dijitTabContainerLeft-spacer,
-.nihilo .dijitTabContainerRight-spacer {
-	width: 2px;
-	border: 1px solid #ccc;
-	background: #f8f8f8;
-}
-.nihilo .dijitTabContainerRight-spacer {
-	border-right: none;
-}
-.nihilo .dijitTabContainerRight-tabs {
-	padding-top: 3px;
-	height: 100%;
-}
-.nihilo .dijitTabContainerLeft-tabs {
-	height: 100%;
-}
-.nihilo .dijitTabContainerLeft-spacer {
-	border-left: none;
-}
-.nihilo .dijitTabContainerTop-dijitContentPane .dijitTabContainerTop-tabs {
-	border-left: 0px solid #ccc;
-	border-top: 0px solid #ccc;
-	border-right: 0px solid #ccc;
-	padding-top: 0px;
-	padding-left: 0px;
-}
-.nihilo .dijitTabContainer .tabStripButton {
-	margin-right: 0px;
-}
-.nihilo .tabStripButton .dijitTabInnerDiv .dijitTabContent {
-	padding: 5px 0 6px;
-}
-.dj_ie6 .nihilo .tabStripButton .dijitTabInnerDiv .dijitTabContent,
-.dj_ie7 .nihilo .tabStripButton .dijitTabInnerDiv .dijitTabContent,
-.dj_opera .nihilo .tabStripButton .dijitTabInnerDiv .dijitTabContent {
-	padding-bottom: 7px;
-}
-.nihilo .tabStrip-disabled .tabStripButton .dijitTabInnerDiv .dijitTabContent {
-	padding: 3px 0 5px;
-}
-.dj_ie6 .nihilo .tabStrip-disabled .tabStripButton .dijitTabInnerDiv .dijitTabContent,
-.dj_ie7 .nihilo .tabStrip-disabled .tabStripButton .dijitTabInnerDiv .dijitTabContent,
-.dj_opera .nihilo .tabStrip-disabled .tabStripButton .dijitTabInnerDiv .dijitTabContent {
-	padding-top: 4px;
-}
-.nihilo .dijitTabContainer .tabStripButton {
-	
-	width: 21px;
-}
-.nihilo .dijitTabContainer .tabStripButton img {
-	height: 14px;
-	background: url(images/spriteRoundedIconsSmall.png) no-repeat left top ;
-}
-.dj_ie6 .nihilo .dijitTabContainer .tabStripButton img {
-	background-image: url(images/spriteRoundedIconsSmall.gif);
-}
-.nihilo .dijitTabContainer .tabStripSlideButtonRight img {
-	background-position: -30px top;
-}
-.nihilo .dijitTabContainer .tabStripMenuButton img {
-	background-position: -15px top;
-}
-.nihilo .dijitTabContainerTopNone {
-	padding-top: 0px;
-}
-.nihilo .dijitTabContainer .tabStripButton-top {
-	margin-top: 1px;
-}
-.nihilo .dijitTabContainer .tabStripButton-bottom {
-	background: transparent url(images/tabBottomEnabledSpriteLR.gif) no-repeat scroll left bottom;
-	border-bottom: medium none;
-	border-top: 1px solid #CCCCCC;
-}
-.nihilo .dijitTabContainer .tabStripButton-bottom .dijitTabInnerDiv {
-	background: transparent url(images/tabBottomEnabledSpriteLR.gif) no-repeat scroll right bottom;
-}
-.nihilo .dijitTabContainer .tabStripButton-bottom .dijitTabContent {
-	background: transparent;
-}
-.nihilo .dijitAccordionContainer {
-	border-color: #ccc;
-	background-color: #fff;
-}
-.nihilo .dijitAccordionTitle {
-	background:#fafafa url(images/titleBar.png) repeat-x top left;
-	border-top: 1px solid #dedede;
-	padding: 5px 4px 6px 8px;
-	cursor:pointer;
-	font-size: 0.9em;
-	font-weight: bold;
-	color: #6d6d6d;
-}
-.nihilo .dijitAccordionTitle-selected  {
-	background: #f9f9f9 url(images/accordionItemActive.png) top repeat-x;
-	font-weight: bold;
-	border-top: 1px solid #dedede;
-	border-bottom: 1px solid #dedede;
-	padding: 5px 4px 5px 8px;
-	cursor: default;
-	color: #243C5F;
-}
-.nihilo .dijitAccordionArrow {
-	background:url(images/spriteRoundedIconsSmall.gif) no-repeat -30px top;
-	width:15px;
-	height:15px;
-	margin-top:-1px;
-}
-.nihilo .dijitAccordionTitle-selected .dijitAccordionArrow {
-	background:url(images/spriteRoundedIconsSmall.gif) no-repeat -15px top;
-	margin-top:-1px;
-}
-.nihilo .dijitAccordionText {
-	margin-left: 4px;
-	margin-right: 4px;
-}
-.nihilo .dijitSplitContainerSizerH {
-	background:url(images/splitContainerSizerV.png) repeat-y #fff;
-	border:0;
-	border-left:0px solid #d3d3d3;
-	border-right:0px solid #d3d3d3;
-	width:5px;
-}
-.nihilo .dijitSplitContainerSizerH .thumb {
-	background:url(images/splitContainerSizerV-thumb.png) no-repeat;
-	left:1px;
-	width:2px;
-	height:19px;
-}
-.nihilo .dijitSplitContainerSizerV {
-	background:url(images/splitContainerSizerH.png) repeat-x #fff;
-	border:0;
-	border-top:0px solid #d3d3d3;
-	border-bottom:0px solid #d3d3d3;
-	height:2px;
-}
-.nihilo .dijitSplitContainerSizerV .thumb {
-	background:url(images/splitContainerSizerH-thumb.png) no-repeat;
-	top:1px;
-	width:19px;
-	height:5px;
-}
-.nihilo .dijitBorderContainer {
-	background-color: #fcfcfc;
-	padding: 5px;
-}
-.nihilo .dijitSplitContainer-child,
-.nihilo .dijitBorderContainer-child {
-	
-    border: 1px #ccc solid;
-}
-.nihilo .dijitBorderContainer-dijitTabContainerTop,
-.nihilo .dijitBorderContainer-dijitTabContainerBottom,
-.nihilo .dijitBorderContainer-dijitTabContainerLeft,
-.nihilo .dijitBorderContainer-dijitTabContainerRight {
-	
-	 border: none;
-}
-.nihilo .dijitBorderContainer-dijitBorderContainer {
-	
-	border: none;
-	padding: 0px;
-}
-.nihilo .dijitSplitterH,
-.nihilo .dijitGutterH {
-	background:#FCFCFC;
-	border:0;
-	border-left:0px solid #d3d3d3;
-	border-right:0px solid #d3d3d3;
-	height:5px;
-}
-.nihilo .dijitSplitterH .dijitSplitterThumb {
-	background:#8BA0BD none;
-	height:1px;
-	top:2px;
-	width:19px;
-}
-.nihilo .dijitSplitterV,
-.nihilo .dijitGutterV {
-	background:#FCFCFC;
-	border:0;
-	border-top:0px solid #d3d3d3;
-	border-bottom:0px solid #d3d3d3;
-	width:5px;
-}
-.nihilo .dijitSplitterV .dijitSplitterThumb {
-	background:#8BA0BD none;
-	height:19px;
-	left:2px;
-	width:1px;
-}
-.nihilo .dijitSplitterActive {
-	font-size: 1px;
-	background-image: none;
-	background-color: #aaa;
-	-moz-opacity: 0.6;
-	opacity: 0.6;
-	filter: Alpha(Opacity=60);
-	margin: 0;
-}
-.nihilo .dijitInputField INPUT,
-.nihilo .dijitTextBox,
-.nihilo .dijitComboBox,
-.nihilo .dijitSpinner {
-	margin: 0em 0.1em;
-}
-.nihilo .dijitTextBox,
-.nihilo .dijitComboBox,
-.nihilo .dijitSpinner,
-.nihilo .dijitInlineEditor input,
-.nihilo .dijitTextArea {
-	
-	background:#fff url(images/validationInputBg.png) repeat-x top left;
-	border:1px solid #d3d3d3;
-	line-height: normal;
-}
-.dj_ie6 .nihilo .dijitTextBox,
-.dj_ie6 .nihilo .dijitComboBox,
-.dj_ie6 .nihilo .dijitSpinner,
-.dj_ie6 .nihilo .dijitInlineEditor input,
-.dj_ie6 .nihilo .dijitTextArea {
-	background:#fff url(images/validationInputBg.gif) repeat-x top left;
-}
-.nihilo .dijitComboBox .dijitButtonNode {
-	padding: 0 0.2em;
-}
-.nihilo .dijitComboBox .dijitButtonNode,
-.nihilo .dijitSpinner .dijitButtonNode {
-	
-	border-color: #d3d3d3;
-	border-left: 1px solid #d3d3d3;
-}
-.nihilo .dijitTextBoxFocused,
-.nihilo .dijitComboBoxFocused,
-.nihilo .dijitSpinnerFocused, .nihilo .dijitSpinnerUpArrowActive, .nihilo .dijitSpinnerDownArrowActive,
-.nihilo .dijitTextAreaFocused {
-	
-	border-color:#b3b3b3;
-}
-.nihilo .dijitComboBoxFocused .dijitButtonNode,
-.nihilo .dijitSpinnerFocused .dijitButtonNode,
-.nihilo .dijitSpinnerUpArrowActive .dijitButtonNode,
-.nihilo .dijitSpinnerDownArrowActive .dijitButtonNode {
-	border-left-color:#d3d3d3;
-}
-.nihilo .dijitSpinnerFocused .dijitDownArrowButton,
-.nihilo .dijitSpinnerUpArrowActive .dijitDownArrowButton,
-.nihilo .dijitSpinnerDownArrowActive .dijitDownArrowButton {
-	border-top-color:#d3d3d3;
-}
-.nihilo .dijitError {
-	border-color:#b3b3b3;
-	background-color:#f9f7ba;
-	background-image:none;
-}
-.dj_ie6 .nihilo .dijitError INPUT {
-	
-	background-color:#f9f7ba !important;
-}
-.nihilo .dijitErrorFocused {
-	background-color:#ff6;
-	background-image:none;
-}
-.dj_ie6 .nihilo .dijitErrorFocused INPUT {
-	
-	background-color:#ff6 !important;
-}
-.nihilo .dijitValidationIcon {
-	
-	width: 16px;
-	background: transparent url(images/warning.png) no-repeat center center;
-}
-.nihilo .dijitComboBoxHighlightMatch {
-	background-color:#d3d3d3;
-}
-.nihilo .dijitButtonNode {
-	
-	
-	border:1px solid #dedede;
-	border-bottom:1px solid #dedede;
-	padding: 0.1em 0.2em 0.2em 0.2em;
-	background: #fff url(images/buttonEnabled.png) repeat-x top left;
-}
-.nihilo .dijitSelect .dijitButtonContents {
-	border-right: none;
-}
-.nihilo .dijitButtonNode button {
-	border: 0px;
-	background-color: transparent;
-}
-.nihilo .dijitButtonText {
-	text-align: center;
-	padding: 0 0.3em;
-}
-.nihilo .dijitComboBox .dijitButtonNode {
-	border-width: 0px 0px 0px 1px;
-}
-.nihilo .dijitArrowButton {
-	color: #111;
-}
-.nihilo .dijitComboButton .dijitDownArrowButton {
-	padding-right:4px;
-}
-.nihilo .dijitComboBoxReadOnly,
-.nihilo .dijitSpinnerReadOnly,
-.nihilo .dijitSpinnerReadOnly .dijitButtonNode,
-.nihilo .dijitButtonDisabled .dijitButtonNode,
-.nihilo .dijitToggleButtonDisabled .dijitButtonNode,
-.nihilo .dijitDropDownButtonDisabled .dijitButtonNode,
-.nihilo .dijitComboButtonDisabled .dijitButtonNode,
-.nihilo .dijitComboBoxDisabled,
-.nihilo .dijitSpinnerDisabled,
-.nihilo .dijitSpinnerDisabled .dijitButtonNode {
-	
-	border-color: #dedede;
-	background:#fafafa url(images/buttonDisabled.png) top repeat-x;
-	opacity: 0.60;
-}
-.dj_ie6 .nihilo .dijitComboButtonDisabled .dijitButtonText {
-	
-	color: #aaa;
-}
-.nihilo .dijitButtonHover .dijitButtonNode,
-.nihilo .dijitButtonNodeHover,
-.nihilo .dijitToggleButtonHover .dijitButtonNode,
-.nihilo .dijitDropDownButtonHover .dijitButtonNode,
-.nihilo .dijitComboButtonHover .dijitButtonContents,
-.nihilo .dijitComboButtonDownArrowHover .dijitDownArrowButton,
-.nihilo .dijitComboBoxHover .dijitDownArrowButton,
-.nihilo .dijitSpinnerUpArrowHover .dijitUpArrowButton,
-.nihilo .dijitSpinnerDownArrowHover .dijitDownArrowButton {
-	
-	
-	color:#243C5F;
-	background:#fcfcfc url(images/buttonHover.png) repeat-x top left;
-}
-.nihilo .dijitSpinnerUpArrowActive .dijitUpArrowButton,
-.nihilo .dijitSpinnerDownArrowActive .dijitDownArrowButton,
-.nihilo .dijitButtonActive .dijitButtonNode,
-.nihilo .dijitToggleButtonActive .dijitButtonNode,
-.nihilo .dijitDropDownButtonActive .dijitButtonNode,
-.nihilo .dijitComboButtonActive .dijitButtonContents,
-.nihilo .dijitDownArrowActive .dijitDownArrowButton,
-.nihilo .dijitComboBoxActive .dijitDownArrowButton,
-.nihilo .dijitStackController .dijitToggleButtonChecked .dijitButtonNode {
-	
-	border-color:#dedede;
-	background: #f5f5f5 url(images/buttonActive.png) top left repeat-x;
-}
-.nihilo .dijitArrowButtonInner {
-	background-image: url(images/spriteArrows.png);
-	background-repeat: no-repeat;
-	background-position: 0px top;
-	width: 11px;
-}
-.nihilo .dijitLeftArrowButton .dijitArrowButtonInner {
-	background-position: -11px top;
-}
-.nihilo .dijitUpArrowButton .dijitArrowButtonInner {
-	background-position: -22px top;
-}
-.nihilo .dijitRightArrowButton .dijitArrowButtonInner {
-	background-position: -33px top;
-}
-.dj_ie6 .nihilo .dijitArrowButtonInner {
-	background-image: url(images/spriteArrows.gif);
-}
-.nihilo .dijitComboBox .dijitArrowButton .dijitArrowButtonInner {
-	background:url(images/spriteArrows.png) no-repeat left center;
-	width: 11px;
-}
-.dj_ie6 .nihilo .dijitComboBox .dijitArrowButton .dijitArrowButtonInner {
-	background:url(images/spriteArrows.gif) no-repeat left center;
-}
-.nihilo .dijitComboBoxHover .dijitArrowButtonInner {
-	
-}
-.nihilo .dijitToggleButton .dijitCheckBox,
-.nihilo .dijitToggleButton .dijitCheckBoxIcon {
-	background-image: url(images/spriteCheckbox.gif);
-}
-.nihilo .dijitCheckBox,
-.nihilo .dijitCheckBoxIcon {		
-	background-image: url(images/spriteCheckbox.gif); 
-	background-repeat: no-repeat;
-	width: 16px;
-	height: 16px;
-	margin: 0;
-	padding: 0;
-}
-.nihilo .dijitCheckBox,
-.nihilo .dijitToggleButton .dijitCheckBoxIcon {
-	
-	background-position: -16px;
-}
-.nihilo .dijitCheckBoxChecked,
-.nihilo .dijitToggleButtonChecked .dijitCheckBoxIcon {
-	
-	background-position: 0px;
-}
-.nihilo .dijitCheckBoxDisabled {
-	
-	background-position: -48px;
-}
-.nihilo .dijitCheckBoxCheckedDisabled {
-	
-	background-position: -32px;
-}
-.nihilo .dijitCheckBoxHover {
-	
-	background-position: -80px;
-}
-.nihilo .dijitCheckBoxCheckedHover {
-	
-	background-position: -64px;
-}
-.nihilo .dijitToggleButton .dijitRadio,
-.nihilo .dijitToggleButton .dijitRadioIcon {
-	background-image: url(images/spriteRadio.gif);
-}
-.nihilo .dijitRadio,
-.nihilo .dijitRadioIcon	{		
-	background-image: url(images/spriteRadio.gif); 
-	background-repeat: no-repeat;
-	width: 16px;
-	height: 16px;
-	margin: 0;
-	padding: 0;
-}
-.nihilo .dijitRadio,
-.nihilo .dijitToggleButton .dijitRadioIcon {
-	
-	background-position: -16px;
-}
-.nihilo .dijitRadioChecked,
-.nihilo .dijitToggleButtonChecked .dijitRadioIcon {
-	
-	background-position: 0px;
-}
-.nihilo .dijitRadioDisabled {
-	
-	background-position: -48px;
-}
-.nihilo .dijitRadioCheckedDisabled {
-	
-	background-position: -32px;
-}
-.nihilo .dijitRadioHover {
-	
-	background-position: -80px;
-}
-.nihilo .dijitRadioCheckedHover {
-	
-	background-position: -64px;
-}
-.nihilo .dijitSliderProgressBarH {
-	border-color: #aab0bb;
-	background: #c0c2c5 url(images/sliderFull.png) repeat-x top left;
-}
-.nihilo .dijitSliderProgressBarV {
-	border-color: #aab0bb;
-	background: #c0c2c5 url(images/sliderFullVertical.png) repeat-y bottom left;
-}
-.nihilo .dijitSliderFocused .dijitSliderProgressBarH,
-.nihilo .dijitSliderFocused .dijitSliderLeftBumper {
-	background-image:url(images/sliderFullFocus.png);
-}
-.nihilo .dijitSliderFocused .dijitSliderProgressBarV,
-.nihilo .dijitSliderFocused .dijitSliderBottomBumper {
-	background-image:url(images/sliderFullVerticalFocus.png);
-}
-.nihilo .dijitSliderRemainingBarV {
-	border-color: #b4b4b4;
-	background: #dcdcdc url(images/sliderEmptyVertical.png) repeat-y bottom left;
-}
-.nihilo .dijitSliderRemainingBarH {
-	border-color: #b4b4b4;
-	background: #dcdcdc url(images/sliderEmpty.png) repeat-x top left;
-}
-.nihilo .dijitSliderBar {
-	border-style: solid;
-	outline:1px;
-	
-}
-.nihilo .dijitSliderFocused .dijitSliderBar {
-	border-color:#727272;
-}
-.dijit_a11y .dijitSliderProgressBar {
-	background-color:#333 !important;
-}
-.nihilo .dijitSliderImageHandleH {
-	border:0px;
-	width:15px;
-	height:18px;
-	background:url(images/preciseSliderThumb.png) no-repeat center top;
-	#background:url(images/preciseSliderThumb.gif) no-repeat center top;
-	cursor:pointer;
-}
-.nihilo .dijitSliderFocused .dijitSliderImageHandleH {
-	background-image:url(images/preciseSliderThumbFocus.png);
-	#background-image:url(images/preciseSliderThumbFocus.gif);
-}
-.nihilo .dijitSliderLeftBumper {
-	border-left-width: 1px;
-	border-color: #aab0bb;
-	background: #c0c2c5 url(images/sliderFull.png) repeat-x top left;
-}
-.nihilo .dijitSliderRightBumper {
-	background: #dcdcdc url(images/sliderEmpty.png) repeat-x top left;
-	border-color: #b4b4b4;
-	border-right-width: 1px;
-}
-.nihilo .dijitSliderImageHandleV {
-	border:0px;
-	width:20px;
-	height:15px;
-	background:url(images/sliderThumb.png) no-repeat center center;
-	#background:url(images/sliderThumb.gif) no-repeat center center;
-	cursor:pointer;
-}
-.nihilo .dijitSliderFocused .dijitSliderImageHandleV {
-	background-image:url(images/sliderThumbFocus.png);
-	#background-image:url(images/sliderThumbFocus.gif);
-}
-.nihilo .dijitSliderBottomBumper {
-	border-bottom-width: 1px;
-	border-color: #aab0bb;
-	background: #c0c2c5 url(images/sliderFullVertical.png) repeat-y bottom left;
-}
-.nihilo .dijitSliderTopBumper {
-	background: #dcdcdc url(images/sliderEmptyVertical.png) repeat-y top left;
-	border-color: #b4b4b4;
-	border-top-width: 1px;
-}
-.nihilo .dijitSliderIncrementIconH,
-.nihilo .dijitSliderIncrementIconV {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat -45px top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat -45px top;
-	width:15px; height:15px;
-	cursor:pointer;
-}
-.nihilo .dijitSliderIncrementIconH {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat -30px top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat -30px top;
-}
-.nihilo .dijitSliderDecrementIconH,
-.nihilo .dijitSliderDecrementIconV {
-	width:15px;
-	height:15px;
-	cursor:pointer;
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat -15px top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat -15px top;
-}
-.nihilo .dijitSliderDecrementIconH {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat 0px top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat 0px top;
-}
-.nihilo .dijitSliderButtonInner {
-	visibility:hidden;
-}
-.nihilo .dijitSliderReadOnly *,
-.nihilo .dijitSliderDisabled * {
-	border-color: #d5d5d5 #bdbdbd #bdbdbd #d5d5d5;
-	color: #bdbdbd;
-}
-.nihilo .dijitSliderReadOnly .dijitSliderDecrementIconH,
-.nihilo .dijitSliderDisabled .dijitSliderDecrementIconH {
-	background-position: 0px -15px;
-}
-.nihilo .dijitSliderReadOnly .dijitSliderIncrementIconH,
-.nihilo .dijitSliderDisabled .dijitSliderIncrementIconH {
-	background-position: -30px -15px;
-}
-.nihilo .dijitSliderReadOnly .dijitSliderDecrementIconV,
-.nihilo .dijitSliderDisabled .dijitSliderDecrementIconV {
-	background-position: -15px -15px;
-}
-.nihilo .dijitSliderReadOnly .dijitSliderIncrementIconV,
-.nihilo .dijitSliderDisabled .dijitSliderIncrementIconV {
-	background-position: -45px -15px;
-}
-.nihilo .dijitSelectDisabled * {
-    cursor: not-allowed !important;
-}
-.nihilo .dijitSelectReadOnly * {
-    cursor: default !important;
-}
-.nihilo .dijitSelect .dijitButtonNode {
-	padding: 0px;
-}
-.nihilo .dijitSelect .dijitButtonContents {
-	padding-top: 1px;
-    background:#fff url(images/validationInputBg.png) repeat-x top left;
-    #background:#fff url(images/validationInputBg.gif) repeat-x top left;
-}
-.nihilo .dijitSelectHover .dijitButtonContents,
-.nihilo .dijitSelectActive .dijitButtonContents,
-.nihilo .dijitSelectOpened .dijitButtonContents,
-.nihilo .dijitSelectDisabled .dijitButtonContents,
-.nihilo .dijitSelectReadOnly .dijitButtonContents{
-	background: transparent none;
-}
-.dj_ie .nihilo .dijitSelect .dijitButtonContents {
-	padding-top: 0px;
-}
-.nihilo .dijitSelectDisabled .dijitButtonNode {
-    border-color: #dedede;
-    background:#fafafa url(images/buttonDisabled.png) top repeat-x;
-}
-.dj_ie .nihilo .dijitSelectDisabled  .dijitButtonNode * {
-	filter: gray() alpha(opacity=50);
-}
-.nihilo .dijitSelectHover .dijitButtonNode {
-    color:#000;
-    background:#fcfcfc url(images/buttonHover.png) repeat-x top left;
-}
-.nihilo .dijitSelectActive .dijitButtonNode,
-.nihilo .dijitSelectOpened .dijitButtonNode {
-    border-color:#dedede;
-    background: #f5f5f5 url(images/buttonActive.png) top left repeat-x;
-}
-.nihilo .dijitSelectMenu td {
-	padding: 0em;
-}
-.nihilo .dijitSelectMenu .dijitMenuItemIcon {
-	margin: 0.1em 0.2em;
-	display: none;
-}
-.nihilo .dijitSelectMenu .dijitMenuItemLabel,
-.nihilo .dijitSelectMenu .dijitMenuArrowCell {
-	padding: 0.1em 0.2em;
-}
-.nihilo .dijitTreeNode {
-    background : url(images/treeI.gif) no-repeat;
-    background-position : top left;
-    background-repeat : repeat-y;
-    zoom: 1;	
-}
-.nihilo .dijitTreeIsLast {
-    background: url(images/treeI_half.gif) no-repeat;
-}
-.nihilo .dijitTreeNodeHover {
-	
-	background-image: url(images/treeHover.png);
-	background-repeat: repeat;
-	background-color: none !important;
-}
-.nihilo .dijitTreeLabel {
-	font-weight: normal;
-	margin-left: 3px;
-}
-.nihilo .dijitTreeIsRoot {
-    margin-left: 0;
-    background-image: none;
-}
-.nihilo .dijitTreeExpando {
-    width: 18px;
-    height: 18px;
-}
-.nihilo .dijitTreeRow {
-	
-	padding-bottom: 2px;
-}
-.nihilo .dijitTreeContent {
-    min-height: 18px;
-    min-width: 18px;
-    padding-left:1px;
-}
-.nihilo .dijitTreeExpand {
-    width: 18px;
-    height: 18px;
-    background-repeat : no-repeat;
-}
-.nihilo .dijitTreeNodeEmphasized {
-    background-color: Highlight;
-    color: HighlightText;
-}
-.nihilo .dijitTreeLabelFocused {
-	outline: 1px invert dotted;
-}
-.nihilo .dijitTreeExpandoOpened {
-	background: url(images/spriteTree.gif) no-repeat -18px top;
-}
-.nihilo .dijitTreeExpandoClosed {
-	background-image: url(images/spriteTree.gif);
-}
-.nihilo .dijitTreeExpandoLeaf {
-	background: url(images/spriteTree.gif) no-repeat -36px top;
-}
-.nihilo .dijitTreeExpandoLoading {
-	background-image: url(images/treeExpand_loading.gif);
-}
-.nihilo .dijitTreeIcon {
-	width: 16px;
-	height: 16px;
-}
-.nihilo .dijitFolderOpened {
-	background: url(images/spriteDivIcons.gif) no-repeat -16px top;
-}
-.nihilo .dijitFolderClosed {
-	background: url(images/spriteDivIcons.gif) no-repeat top left;
-}
-.nihilo .dijitLeaf {
-	background: url(images/spriteDivIcons.gif) no-repeat -32px top;
-}
-.nihilo .dijitTreeNode .dojoDndItemBefore,
-.nihilo .dijitTreeNode .dojoDndItemAfter {
-	border-bottom: none;
-	border-top: none;
-}
-.nihilo .dijitTreeNode .dojoDndItemBefore .dijitTreeContent {
-	
-	border-top: 2px solid #369;
-}
-.nihilo .dijitTreeNode .dojoDndItemAfter .dijitTreeContent {
-	
-	border-bottom: 2px solid #369;
-}
-.nihilo .dijitProgressBar {
-	margin:2px 0px 2px 0px;
-}
-.nihilo .dijitProgressBarEmpty{
-	
-	background:#fff url(images/progressBarEmpty.png) repeat-x center center;
-	border-color: #f8d582 #f8d582 #f8d582 #f8d582;
-}
-.nihilo .dijitProgressBarTile{
-	
-	background:#f0f0f0 url(images/progressBarFull.png) repeat-x center center;
-}
-.nihilo .dijitProgressBarFull {
-	border-right:1px solid #f8d582;
-}
-.nihilo .dijitProgressBarLabel {
-	
-	color:#293a4b;
-}
-.nihilo .dijitProgressBarIndeterminate .dijitProgressBarTile {
-	
-	background:#cad2de url(images/progressBarAnim.gif) repeat-x center center;
-}
-.nihilo .dijitTitlePaneTitle {
-	background: #cccccc;
-	background:#fff url(images/titleBar.png) repeat-x top left;
-	border:1px solid #bfbfbf;
-	padding:3px 4px;
-	font-size: 0.9em;
-	font-weight: bold;
-	color: #6d6d6d;
-}
-.nihilo .dijitTitlePaneTitle-hover  {
-	background: #f9f9f9 url(images/accordionItemActive.png) top repeat-x;
-	cursor: pointer;
-}
-.nihilo .dijitTitlePaneTitle * {
-	vertical-align: middle;
-}
-.nihilo .dijitTitlePane .dijitOpen .dijitArrowNode,
-.nihilo .dijitTitlePane .dijitClosed .dijitArrowNode {
-	width:15px;
-	height:15px;
-}
-.nihilo .dijitTitlePaneFocused .dijitTitlePaneTextNode {
-	color: #243C5F;
-}
-.nihilo .dijitOpen .dijitTitlePaneTextNode,
-.nihilo .dijitFixedOpen .dijitTitlePaneTextNode {
-	color: #243C5F;
-}
-.nihilo .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background: url(images/spriteRoundedIconsSmall.png) no-repeat -30px top;
-}
-.dj_ie6 .nihilo .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background:url(images/spriteRoundedIconsSmall.gif) no-repeat -30px top;
-}
-.nihilo .dijitTitlePane .dijitOpen .dijitArrowNode {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat -15px top;
-}
-.dj_ie6 .nihilo .dijitTitlePane .dijitOpen .dijitArrowNode {
-	background:url(images/spriteRoundedIconsSmall.gif) no-repeat -15px top;
-}
-.nihilo .dijitTitlePane .dijitArrowNodeInner {
-	display:none;
-}
-.dijit_a11y .dijitTitlePane .dijitOpen .dijitArrowNodeInner,
-.dijit_a11y .dijitTitlePane .dijitClosed .dijitArrowNodeInner {
-	display:inline !important;
-	font-family:monospace;
-	padding-bottom:.2em;
-}
-.dijit_a11y .dijitTitlePane .dijitArrowNode {
-	display:none;
-}
-.nihilo .dijitTitlePaneContentOuter {
-	background: #ffffff;
-	border:1px solid #bfbfbf;
-	border-top: 0px solid #3d3d3d;	
-}
-.nihilo .dijitTitlePaneContentInner {
-	padding:10px;
-}
-.dj_ie6 .nihilo .dijitTitlePaneContentOuter,
-.dj_ie6 .nihilo .dijitTitlePane .dijitTitlePaneTitle {
-	zoom: 1;
-}
-.nihilo .dijitTitlePaneTextNode {
-	margin-left: 4px;
-	margin-right: 4px;
-}
-.nihilo .dijitCalendarIncrementControl {
-	
-	width:15px;
-	height:15px;
-	background-image: url(images/spriteRoundedIconsSmall.png);
-	background-repeat: no-repeat
-}
-.dj_ie6 .nihilo .dijitCalendarIncrementControl {
-	font-size:.1em;
-	background-image: url(images/spriteRoundedIconsSmall.gif);
-}
-.nihilo .dijitA11ySideArrow {
-	display: none;
-}
-.nihilo .dijitCalendarDecrease {
-	background-position: top left;
-}
-.nihilo .dijitCalendarIncrease {
-	background-position: -30px top;
-}
-.nihilo table.dijitCalendarContainer {
-	font-size: 100%;
-	border-spacing: 0;
-	border-collapse: separate;
-	border: 1px solid #ccc;
-	margin: 0;
-}
-.nihilo .dijitCalendarMonthContainer th {
-	
-	background:#d3d3d3 url(images/titleBar.png) repeat-x top;
-	padding-top:.3em;
-	padding-bottom:.2em;
-	text-align:center;
-}
-.dj_ie6 .nihilo .dijitCalendarMonthContainer th {
-	padding-top:.2em;
-	padding-bottom:.1em;
-}
-.nihilo .dijitCalendarDayLabelTemplate {
-	
-	background:#fefefe;
-	font-weight:normal;
-	padding-top:.15em;
-	padding-bottom:.2em;
-	border-bottom: 1px solid #eeeeee;
-	color:#293a4b;
-	text-align:center;
-}
-.nihilo .dijitCalendarBodyContainer {
-	border-bottom: 1px solid #eeeeee;
-}
-.nihilo .dijitCalendarMonthLabel {
-	color:#293a4b;
-	font-weight: bold;
-}
-.nihilo .dijitCalendarDateTemplate {
-	
-	font-size: 0.9em;
-	font-weight: bold;
-	text-align: center;
-	padding: 0.3em 0.3em 0.05em 0.3em;
-	letter-spacing: 1px;
-	background-color: #fdfdfd;
-	border:#fdfdfd solid 1px !important;
-}
-.dj_ie .nihilo .dijitCalendarDateTemplate {
-	padding: 0.1em .33em 0.02em .33em;
-}
-.nihilo .dijitCalendarPreviousMonth,
-.nihilo .dijitCalendarNextMonth 		{
-	
-	color:#999999;
-	background-color:#f5f5f5 !important;
-	border:#f5f5f5 solid 1px !important;
-}
-.nihilo .dijitCalendarPreviousMonthDisabled,
-.nihilo .dijitCalendarNextMonthDisabled	{
-	
-	background-color:#a4a5a6 !important;
-}
-.nihilo .dijitCalendarCurrentMonth {
-	
-}
-.nihilo .dijitCalendarCurrentMonthDisabled {
-	
-	background-color:#bbbbbc !important;
-}
-.nihilo .dijitCalendarDisabledDate {
-	
-	
-	text-decoration:line-through !important;
-	cursor:default !important;
-}
-.nihilo .dijitCalendarCurrentDate {
-	
-	text-decoration:underline;
-	font-weight:bold;
-}
-.nihilo .dijitCalendarSelectedDate {
-	
-	background-color:#ffe284 !important;
-	color:black !important;
-	border:#f7c95c solid 1px !important;
-}
-.nihilo .dijitCalendarYearContainer {
-	
-	background:white url(images/titleBar.png) repeat-x top;
-}
-.nihilo .dijitCalendarYearLabel {
-	
-	margin:0;
-	padding:0.4em 0 0.25em 0;
-	text-align:center;
-}
-.nihilo .dijitCalendarSelectedYear {
-	
-	color:black;
-	padding:0.2em;
-	padding-bottom:0.1em;
-	background-color:#ffe284 !important;
-	border:#f7c95c solid 1px !important;
-}
-.nihilo .dijitCalendarNextYear,
-.nihilo .dijitCalendarPreviousYear {
-	
-	color:black !important;
-	font-weight:normal;
-}
-.nihilo .dijitTimePickerTick,
-.nihilo .dijitTimePickerMarker {
-	border-color: #eeeeee;
-}
-.nihilo .dijitTimePickerTick {
-	color:white;
-}
-.nihilo .dijitTimePickerMarker {
-	background:#d3d3d3 url(images/titleBar.png) repeat-x top;
-	color:#293a4b;
-	font-weight: bold;
-}
-.nihilo .dijitTimePickerItemSelected {
-	color: black;
-	background: #ffe284 none;
-}
-.nihilo .dijitTimePickerItemHover {
-	background: #d6d6dd none;
-	color:black;
-}
-.nihilo .dijitTimePickerItemHover,
-.nihilo .dijitTimePickerItemSelected {
-	position: relative;
-	z-index: 10;
-}
-.nihilo .dijitTimePickerTick .dijitTimePickerItemInner {
-	font-size:0.4em;
-}
-.nihilo .dijitTimePickerItemHover .dijitTimePickerItemInner,
-.nihilo .dijitTimePickerItemSelected .dijitTimePickerItemInner {
-	font-size:1em;
-}
-.nihilo .dijitTimePickerMarkerHover {
-	border-top: 1px solid #eeeeee;
-}
-.nihilo .dijitTimePickerTickHover,
-.nihilo .dijitTimePickerTickSelected {
-	margin-top:-0.3em;
-	margin-bottom:-0.3em;
-	border-bottom: none;
-}
-.dijit_a11y .dijitTimePickerTickHover {
-	background-color: #CCC !important;
-	border-top: 1px solid #333 !important;
-	border-bottom: 1px solid #333 !important;
-}
-.dijit_a11y .dijitTimePickerMarkerHover {
-	border-bottom-width: 2px;
-}
-.nihilo .dijitToolbar {
-	border-bottom: 1px solid #ccc;
-	background:#eaeaea url(images/titleBar.png) repeat-x top left;
-}
-.dj_ie6 .nihilo .dijitToolbar {
-	height: 10px;
-}
-.nihilo .dijitToolbar .dijitButtonNode,
-.nihilo .dijitToolbar .dijitComboButton .dijitButtonContents,
-.nihilo .dijitToolbar .dijitComboButton .dijitDownArrowButton {
-	background: none;
-	margin: 0px;
-	padding: 0px;
-	border: none;
-	font-size: 12px;
-}
-.nihilo .dijitToolbar .dijitButton,
-.nihilo .dijitToolbar .dijitToggleButton,
-.nihilo .dijitToolbar .dijitDropDownButton,
-.nihilo .dijitToolbar .dijitComboButton .dijitButtonContents,
-.nihilo .dijitToolbar .dijitComboButton .dijitDownArrowButton {
-	background: none;
-	padding: 1px;	
-}
-.nihilo .dijitToolbar .dijitButtonChecked,
-.nihilo .dijitToolbar .dijitToggleButtonChecked {
-	background-color:#ffeeb9;
-	border:1px solid #f7c95c;
-	padding: 0;
-}
-.nihilo .dijitToolbar .dijitButtonCheckedHover,
-.nihilo .dijitToolbar .dijitToggleButtonCheckedHover
- {
-	background-color:#ffe284;
-	border:1px solid #f7c95c;
-	padding: 0;
-}
-.nihilo .dijitToolbar .dijitButtonHover,
-.nihilo .dijitToolbar .dijitToggleButtonHover,
-.nihilo .dijitToolbar .dijitDropDownButtonHover,
-.nihilo .dijitToolbar .dijitComboButtonHover .dijitButtonContents,
-.nihilo .dijitToolbar .dijitComboButtonDownArrowHover .dijitDownArrowButton {
-	
-	border: 1px solid #f7c95c;
-	padding: 0;
-	background-color:#ffe284;
-}
-.nihilo .dijitToolbar label {
-	padding: 3px 3px 0 6px;
-}
-.dj_ie .nihilo .dijitToolbar .dijitComboButton .dijitButtonContentsFocused,
-.dj_ie .nihilo .dijitToolbar .dijitComboButton .dijitDownArrowButtonFocused {
-	
-	border: 1px #555 dotted !important;
-	padding: 0px;
-}
-.nihilo .dijitDialog {
-	background: #eee;
-	border: 1px solid #d3d3d3;
-	-webkit-box-shadow: 0px 5px 10px #adadad;
-	padding: 0px;
-}
-.nihilo .dijitDialog .dijitDialogTitle {
-	
-	font-size: 0.9em;
-	color: #3243C5F;
-	font-weight: bold;
-	padding: 0px 4px;
-}
-.nihilo .dijitDialog .dijitDialogPaneContent {
-	background: #ffffff;
-	border:none;
-	border-top: 1px solid #d3d3d3; 
-	padding:10px;
-}
-.nihilo .dijitDialogTitleBar {
-	
-	background: #fafafa url(images/titleBar.png) repeat-x top left;
-	padding: 5px 6px 3px 6px;
-	cursor: move;
-	outline:0; 
-}
-.nihilo .dijitDialogCloseIcon {
-	
-	background-image: url(images/spriteRoundedIconsSmall.png);
-	background-repeat: no-repeat;
-	background-position: -60px 0px;
-	position: absolute;
-	vertical-align: middle;
-	right: 6px;
-	top: 4px;
-	height: 15px;
-	width: 15px;
-	cursor: pointer;
-}
-.dj_ie6 .nihilo .dijitDialogCloseIcon {
-	background-image: url(images/spriteRoundedIconsSmall.gif);
-}
-.nihilo .dijitDialogCloseIcon-hover {
-	background-position: -60px -15px;
-}
-.nihilo .dijitTooltip,
-.nihilo .dijitTooltipDialog {
-	
-	background: transparent;	
-}
-.dijitTooltipBelow {
-	
-	padding-top: 10px;
-}
-.dijitTooltipAbove {
-	
-	padding-bottom: 10px;
-}
-.nihilo .dijitTooltipContainer {
-	
-	background-color: #fff;
-	border:1px solid #d3d3d3;
-	padding:0.45em;
-}
-.nihilo .dijitTooltipConnector {
-	
-	border:0px;
-	z-index: 2;
-}
-.nihilo .dijitTooltipABRight .dijitTooltipConnector {
-	
-	left: auto !important;
-	right: 6px;
-}
-.nihilo .dijitTooltipBelow .dijitTooltipConnector {
-	
-	top: 0px;
-	left: 6px;
-	background:url(images/tooltipConnectorUp.png) no-repeat top left;
-	width:17px;
-	height:11px;
-}
-.dj_ie .nihilo .dijitTooltipBelow .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorUp.gif);
-}
-.nihilo .dijitTooltipAbove .dijitTooltipConnector {
-	
-	bottom: 0px;
-	left: 6px;
-	background:url(images/tooltipConnectorDown.png) no-repeat top left;
-	width:17px;
-	height:11px;
-}
-.dj_ie .nihilo .dijitTooltipAbove .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorDown.gif);
-}
-.dj_ie6 .nihilo .dijitTooltipAbove .dijitTooltipConnector {
-	bottom: -5px;
-}
-.nihilo .dijitTooltipLeft {
-	padding-right: 10px;
-}
-.dj_ie6 .nihilo .dijitTooltipLeft {
-	padding-left: 11px;
-}
-.nihilo .dijitTooltipLeft .dijitTooltipConnector {
-	
-	right: 0px;
-	bottom: 3px;
-	background:url(images/tooltipConnectorRight.png) no-repeat top left;
-	width:11px;
-	height:17px;
-}
-.dj_ie .nihilo .dijitTooltipLeft .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorRight.gif);
-}
-.nihilo .dijitTooltipRight {
-	padding-left: 10px;
-}
-.nihilo .dijitTooltipRight .dijitTooltipConnector {
-	
-	left: 0px;
-	bottom: 3px;
-	background:url(images/tooltipConnectorLeft.png) no-repeat top left;
-	width:11px;
-	height:17px;
-}
-.dj_ie .nihilo .dijitTooltipRight .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorLeft.gif);
-}
-.nihilo .dijitMenu,
-.nihilo .dijitMenuBar {
-	border: 1px solid #d3d3d3;
-	margin: 0px;
-	padding: 0px;
-	background-color: #fff;
-}
-.nihilo .dijitBorderContainer .dijitMenuBar {
-	border: 1px #ccc solid;
-}
-.nihilo .dijitMenuItem {
-	font-family: sans-serif;
-	margin: 0px;
-	color: #243C5F;
-}
-.nihilo .dijitMenuBar .dijitMenuItem {
-	padding: 4px 5px;
-}
-.nihilo .dijitMenuPreviousButton, .nihilo .dijitMenuNextButton {
-	font-style: italic;
-}
-.nihilo .dijitMenuItem TD {
-	padding:1px;
-}
-.nihilo .dijitMenuPassive .dijitMenuItemHover,
-.nihilo .dijitMenuItemSelected {
-	background-color: #ffe284; 
-	color: #243C5F;
-}
-.nihilo .dijitMenuItemIcon {
-	width: 15px;
-	height: 15px;
-}
-.nihilo .dijitMenuExpand {
-	width:15px;
-	height:15px;
-	background-image: url(images/spriteRoundedIconsSmall.png);
-	background-position: -30px top;
-}
-.dj_ie6 .nihilo .dijitMenuExpand {
-	background-image:url(images/spriteRoundedIconsSmall.gif);
-}
-.nihilo .dijitMenuSeparator {
-	height: 1px;
-}
-.nihilo .dijitMenuSeparatorTop {
-	border-bottom: 1px solid #fff; 
-}
-.nihilo .dijitMenuSeparatorBottom {
-	border-top: 1px solid #d3d3d3;
-}
-.nihilo .dijitCheckedMenuItemIconChar {
-	display: none;
-}
-.nihilo .dijitCheckedMenuItemIcon {
-	background-image: url(images/spriteCheckbox.gif);
-	background-position: -80px;
-}
-.nihilo .dijitCheckedMenuItemChecked .dijitCheckedMenuItemIcon {
-	background-position: -64px;
-}
-.dijitIEFixedToolbar {
-	position:absolute;
-	
-	top: expression(eval((document.documentElement||document.body).scrollTop));
-}
-.nihilo .dijitToolbar .dijitToolbarSeparator {
-	background: url(images/editor.gif);
-}
-.nihilo .dijitEditorIcon {
-	background-image: url(images/editor.gif); 
-	background-repeat: no-repeat;
-	width: 18px;
-	height: 18px;
-	text-align: center;
-}
-.nihilo .dijitDisabled .dijitEditorIcon {
-	background-image: url(images/editorDisabled.gif); 
-}
-.nihilo .dijitEditorIconSep { background-position: 0px; }
-.nihilo .dijitEditorIconBackColor { background-position: -18px; }
-.nihilo .dijitEditorIconBold { background-position: -36px; }
-.nihilo .dijitEditorIconCancel { background-position: -54px; }
-.nihilo .dijitEditorIconCopy { background-position: -72px; }
-.nihilo .dijitEditorIconCreateLink { background-position: -90px; }
-.nihilo .dijitEditorIconCut { background-position: -108px; }
-.nihilo .dijitEditorIconDelete { background-position: -126px; }
-.nihilo .dijitEditorIconForeColor { background-position: -144px; }
-.nihilo .dijitEditorIconHiliteColor { background-position: -162px; }
-.nihilo .dijitEditorIconIndent { background-position: -180px; }
-.nihilo .dijitEditorIconInsertHorizontalRule { background-position: -198px; }
-.nihilo .dijitEditorIconInsertImage { background-position: -216px; }
-.nihilo .dijitEditorIconInsertOrderedList { background-position: -234px; }
-.nihilo .dijitEditorIconInsertTable { background-position: -252px; }
-.nihilo .dijitEditorIconInsertUnorderedList { background-position: -270px; }
-.nihilo .dijitEditorIconItalic { background-position: -288px; }
-.nihilo .dijitEditorIconJustifyCenter { background-position: -306px; }
-.nihilo .dijitEditorIconJustifyFull { background-position: -324px; }
-.nihilo .dijitEditorIconJustifyLeft { background-position: -342px; }
-.nihilo .dijitEditorIconJustifyRight { background-position: -360px; }
-.nihilo .dijitEditorIconLeftToRight { background-position: -378px; }
-.nihilo .dijitEditorIconListBulletIndent { background-position: -396px; }
-.nihilo .dijitEditorIconListBulletOutdent { background-position: -414px; }
-.nihilo .dijitEditorIconListNumIndent { background-position: -432px; }
-.nihilo .dijitEditorIconListNumOutdent { background-position: -450px; }
-.nihilo .dijitEditorIconOutdent { background-position: -468px; }
-.nihilo .dijitEditorIconPaste { background-position: -486px; }
-.nihilo .dijitEditorIconRedo { background-position: -504px; }
-.nihilo .dijitEditorIconRemoveFormat { background-position: -522px; }
-.nihilo .dijitEditorIconRightToLeft { background-position: -540px; }
-.nihilo .dijitEditorIconSave { background-position: -558px; }
-.nihilo .dijitEditorIconSpace { background-position: -576px; }
-.nihilo .dijitEditorIconStrikethrough { background-position: -594px; }
-.nihilo .dijitEditorIconSubscript { background-position: -612px; }
-.nihilo .dijitEditorIconSuperscript { background-position: -630px; }
-.nihilo .dijitEditorIconUnderline { background-position: -648px; }
-.nihilo .dijitEditorIconUndo { background-position: -666px; }
-.nihilo .dijitEditorIconWikiword { background-position: -684px; }
-.nihilo .dijitEditorIconToggleDir { background-position: -540px; }
-.nihilo .dijitEditorIconTabIndent { background-position: -702px; }
-.nihilo .dijitEditorIconSelectAll { background-position: -720px; }
-.nihilo .dijitEditorIconUnlink { background-position: -738px; }
-.nihilo .dijitEditorIconFullScreen { background-position: -756px; }
-.nihilo .dijitEditorIconViewSource { background-position: -774px; }
-.nihilo .dijitEditorIconPrint { background-position: -792px; }
-.nihilo .dijitEditorIconNewPage { background-position: -810px; }
-.dijitColorPalette {
-	border:1px solid #d3d3d3;
-	background:#fff;
-	-moz-border-radius: 0px !important;
-}
+	NOTES:
+	---
+	Dialog.css contains css classes for both Dialog and Tooltip!
+	This because currently a dijit.TooltipDialog exist. Until this is resolved
+	you need to include Dialog.css for both dijits
+	---
+	Toolbar.css contains classes also used in Editor. Until this is resolved
+	you need to include Toolbar.css for both Toolbar and Editor
+	---
+	Button.css contains classes for combobox,
+
+*/
+
+ at import url("../dijit.css");
+ at import url("../../icons/commonIcons.css");/*sprite containing common icons to be used by all themes*/
+ at import url("Common.css");
+
+ at import url("layout/ContentPane.css");
+ at import url("layout/TabContainer.css");
+ at import url("layout/AccordionContainer.css");
+ at import url("layout/SplitContainer.css");
+ at import url("layout/BorderContainer.css");
+ at import url("form/Common.css");
+ at import url("form/Button.css");
+ at import url("form/Checkbox.css");
+ at import url("form/RadioButton.css");
+ at import url("form/Slider.css");
+ at import url("form/Select.css");
+ at import url("Tree.css");
+ at import url("ProgressBar.css");
+ at import url("TitlePane.css");
+ at import url("Calendar.css");
+ at import url("TimePicker.css");
+ at import url("Toolbar.css");
+ at import url("Dialog.css");
+ at import url("Menu.css");
+ at import url("Editor.css");
+ at import url("../../icons/editorIcons.css"); /* sprite for editor icons to be used by all themes */
+ at import url("ColorPalette.css");
\ No newline at end of file
diff --git a/dijit/themes/nihilo/nihilo_rtl.css b/dijit/themes/nihilo/nihilo_rtl.css
index 1dc04aa..1e9a6af 100644
--- a/dijit/themes/nihilo/nihilo_rtl.css
+++ b/dijit/themes/nihilo/nihilo_rtl.css
@@ -1,219 +1,29 @@
+/*
+	Adds cosmetic styling to Dijit.  Users may swap with a custom theme CSS file.
 
-.dj_gecko-rtl .dijitInputField {
-	direction: ltr; 
-}
-.dj_gecko-rtl .dijitInputField * {
-	direction: rtl; 
-}
-.dijitRtl .dijitMenuItem {
-	text-align: right;
-}
-.dijitRtl .dijitComboBox .dijitInputField {
-	border-right-width:1px !important;
-	border-left-width:0 !important;
-}
-.dijitRtl .dijitCalendarNextYear {
-	margin:0 0.55em 0 0;
-}
-.dijitRtl .dijitCalendarPreviousYear {
-	margin:0 0 0 0.55em;
-}
-.dijitRtl .dijitProgressBarFull .dijitProgressBarLabel {
-	right:0; 
-}
-.dijitRtl .dijitSliderImageHandleV {
-	left:auto;
-	right:-6px;
-}
-.dj_ie-rtl .dijitSliderImageHandleV {
-	right:-10px;
-}
-.dijitRtl .dijitSliderMoveableH {
-	right:auto;
-	left:0;
-}
-.dijitRtl .dijitRuleContainerV {
-	float:right;
-}
-.dj_gecko-rtl .dijitRuleContainerV {
-	float:left;
-}
-.dj_ie-rtl .dijitRuleContainerV {
-	text-align:right;
-}
-.dj_ie-rtl .dijitRuleLabelV {
-	text-align:left;
-}
-.dj_ie-rtl .dijitRuleLabelH {
-	zoom:1;
-}
-.dj_ie-rtl .dijitSliderProgressBarH {
-	right:0;
-	left:auto;
-}
-.dj_gecko-rtl .dijitSliderProgressBarH {
-	float:right;
-	right:0;
-	left:auto;
-}
-.dijitRtl .dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	right: auto;
-	left: 0;
-	border-width: 0 1px 0 0 !important;
-}
-.dijitRtl .dijitSpinnerButtonContainer {
-	float: left;
-}
-.dijitRtl .dijit_a11y .dijitSpinnerButtonContainer {
-	margin-left: none;
-	margin-right: 2px;
-}
-.dijitRtl DIV.dijitArrowButton, .dijitRtl .dijitValidationIcon, .dijitRtl .dijitValidationIconText {
-	float: left;
-}
-.dijitRtl .dijitContentPaneLoading, .dijitRtl .dijitContentPaneError {
-	background-position:right;
-	padding-right:25px;
-}
-.dijitRtl .dijitTabContainer .tabStripMenuButton {
-	float: left;
-}
-.dj_iequirks-rtl .dijitComboButton BUTTON {
-        float:left;
-}
-.dijitRtl .nihilo .dijitTab {
-	margin-right:0;
-	margin-left:2px;		
-}
-.dijitRtl .nihilo .dijitTabContainer .tabStripButton {
-	margin-left: 0;
-}
-.dijitRtl .nihilo .dijitTabContainerTopStrip,
-.dijitRtl .nihilo .dijitTabContainerBottomStrip,
-.dijitRtl .nihilo .dijitTabContainerTop-tabs,
-.dijitRtl .nihilo .dijitTabContainerBottom-tabs {
-	padding-left: 0;
-	padding-right: 3px;
-}
-.dijitRtl .nihilo .dijitTabInnerDiv {
-	padding-left: 3px;
-	padding-right: 4px;
-}
-.dijitRtl .nihilo .dijitTabPaneWrapper {
-	#zoom: 1;
-}
-.dj_ie-rtl .nihilo .dijitTabContainerLeft-tabs {
-	margin-left: 0px !important;
-}
-.dj_ie-rtl .nihilo .dijitTabContainerRight-tabs {
-	margin-right: 0px !important;
-}
-.dijitRtl .nihilo .dijitTabContainerLeft-tabs .dijitTab,
-.dijitRtl .nihilo .dijitTabContainerRight-tabs .dijitTab {
-	margin-left:0px;
-}
-.dj_ie-rtl .nihilo .dijitTab .dijitTabInnerDiv{
-	width : 1%;
-}
-.dijitRtl .nihilo .dijitAccordionArrow {
-	background-position: 0px top;
-}
-.dijitRtl .nihilo .dijitAccordionTitle-selected .dijitAccordionArrow {
-	
-	background-position: -15px top;
-}
-.dijitRtl .nihilo .dijitSliderProgressBarH,
-.dijitRtl .nihilo .dijitSliderRemainingBarH,
-.dijitRtl .nihilo .dijitSliderLeftBumper,
-.dijitRtl .nihilo .dijitSliderRightBumper,
-.dijitRtl .nihilo .dijitSliderTopBumper {
-	background-position: top right;
-}
-.dijitRtl .nihilo .dijitSliderProgressBarV,
-.dijitRtl .nihilo .dijitSliderRemainingBarV,
-.dijitRtl .nihilo .dijitSliderBottomBumper {
-	background-position: bottom right;
-}
-.dijitRtl .nihilo .dijitSliderLeftBumper {
-	border-left-width: 0px;
-	border-right-width: 1px;
-}
-.dijitRtl .nihilo .dijitSliderRightBumper {
-	border-left-width: 1px;
-	border-right-width: 0px;
-}
-.dijitRtl .nihilo .dijitSliderIncrementIconH {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat left top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat left top;
-}
-.dijitRtl .nihilo .dijitSliderDecrementIconH {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat -30px top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat -30px top;
-}
-.dijitRtl .nihilo .dijitComboBox .dijitButtonNode {
-	border-width: 0px 0px 0px 1px;
-}
-.dijitRtl .nihilo .dijitSelect .dijitButtonContents {
-	border-left: none;
-	border-right-width: 1px;
-}
-.dijitRtl .nihilo .dijitComboBox .dijitButtonNode,
-.dijitRtl .nihilo .dijitSpinner .dijitButtonNode {
-	
-	border-color: #8ba0bd;
-	border-left: 0px solid #8ba0bd;
-	border-right: 1px solid #8ba0bd;
-}
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeNode {
-    background-image : none;
-}
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeIsRoot {
-}
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeIsLast {
-    background-image: url(images/treeI_half_rtl.gif);
-}
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeContent {
-    padding-left: auto;
-    padding-right: 1px;
-}
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeExpandoOpened {
-	background: url(images/spriteTree_rtl.gif) no-repeat -18px top;
-}
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeExpandoClosed {
-	background-image: url(images/spriteTree_rtl.gif);
-}
-.dijitRtl .nihilo .dijitTreeContainer .dijitTreeExpandoLeaf {
-	background: none;
-}
-.dijitRtl .nihilo .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background-position: 0px top;
-}
-.dj_ie6-rtl .nihilo .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background-position: 0px top;
-}
-.dijitRtl .nihilo .dijitCalendarDecrease {
-	background-position: -30px top;
-}
-.dijitRtl .nihilo .dijitCalendarIncrease {
-	background-position: 0px top;
-}
-.dijitRtl .nihilo .dijitDialogTitleBar .dijitDialogCloseIcon {
-	right: auto;
-	left: 5px;
-}
-.dijitRtl .nihilo .dijitMenuItem .dijitMenuItemIcon {
-	padding-left: 3px;
-	padding-right: 0px;
-}
-.dijitRtl .nihilo .dijitMenuItem .dijitMenuExpand {
-	background-position: 0px top;
-}
-.dijitRtl .nihilo .dijitEditorIcon {
-	background-image: url(images/editor_rtl.gif); 
-}
-.dijitRtl .nihilo .dijitDisabled .dijitEditorIcon {
-	background-image: url(images/editorDisabled_rtl.gif); 
-}
-.dijitRtl .nihilo .dijitToolbar .dijitToolbarSeparator {
-	background-image: url(images/editor_rtl.gif);
-}
+	NOTES:
+	---
+	Dialog.css contains css classes for both Dialog and Tooltip!
+	This because currently a dijit.TooltipDialog exist. Until this is resolved
+	you need to include Dialog.css for both dijits
+	---
+	Toolbar.css contains classes also used in Editor. Until this is resolved
+	you need to include Toolbar.css for both Toolbar and Editor
+	---
+	Button.css contains classes for combobox,
+
+*/
+
+ at import url("../dijit_rtl.css");
+ at import url("layout/TabContainer_rtl.css");
+ at import url("layout/AccordionContainer_rtl.css");
+ at import url("form/Slider_rtl.css");
+ at import url("form/Button_rtl.css");
+ at import url("Tree_rtl.css");
+ at import url("TitlePane_rtl.css");
+ at import url("Calendar_rtl.css");
+ at import url("TimePicker_rtl.css");
+ at import url("Dialog_rtl.css");
+ at import url("Menu_rtl.css");
+ at import url("Editor_rtl.css");
+ at import url("../../icons/editorIcons_rtl.css");/* RTL sprite for editor icons to be used by all themes*/
\ No newline at end of file
diff --git a/dijit/themes/soria/Calendar.css b/dijit/themes/soria/Calendar.css
index de0029d..7b38d4d 100644
--- a/dijit/themes/soria/Calendar.css
+++ b/dijit/themes/soria/Calendar.css
@@ -1,6 +1,7 @@
+/* Calendar*/
 
 .soria .dijitCalendarIncrementControl {
-	
+	/* next/prev month buttons */
 	width:15px;
 	height:15px;
 	background-image: url("images/spriteRoundedIconsSmall.png");
@@ -10,15 +11,18 @@
 	font-size:.1em;
 	background-image: url("images/spriteRoundedIconsSmall.gif");
 }
+
 .soria .dijitA11ySideArrow {
 	display: none;
 }
+
 .soria .dijitCalendarDecrease {
 	background-position: top left;
 }
 .soria .dijitCalendarIncrease {
 	background-position: -30px top;
 }
+
 .soria table.dijitCalendarContainer {
 	font-size: 100%;
 	border-spacing: 0;
@@ -26,8 +30,9 @@
 	border: 1px solid #b1badf;
 	margin: 0;
 }
+
 .soria .dijitCalendarMonthContainer th {
-	
+	/* month header cell */
 	background:#bed7f0 url("images/titleBar.png") repeat-x top;
 	padding-top:.3em;
 	padding-bottom:.2em;
@@ -37,8 +42,9 @@
 	padding-top:.2em;
 	padding-bottom:.1em;
 }
+
 .soria .dijitCalendarDayLabelTemplate {
-	
+	/* day of week labels */
 	background:#bed7f0;
 	font-weight:normal;
 	padding-top:.15em;
@@ -47,15 +53,18 @@
 	color:#293a4b;
 	text-align:center;
 }
+
 .soria .dijitCalendarBodyContainer {
 	border-bottom: 1px solid #eeeeee;
 }
+
 .soria .dijitCalendarMonthLabel {
 	color:#293a4b;
 	font-weight: bold;
 }
+
 .soria .dijitCalendarDateTemplate {
-	
+	/* style for each day cell */
 	font-size: 0.9em;
 	font-weight: bold;
 	text-align: center;
@@ -64,66 +73,65 @@
 	background-color: #fff;
 	border:#fff solid 1px !important;
 }
+
 .dj_ie .soria .dijitCalendarDateTemplate {
 	padding: 0.1em .33em 0.02em .33em;
 }
+
 .soria .dijitCalendarPreviousMonth,
 .soria .dijitCalendarNextMonth 		{
-	
+	/* days that are part of the previous or next month */
 	color:#999999;
 	background-color:#fdfdfd !important;
 	border:#fdfdfd solid 1px !important;
 }
-.soria .dijitCalendarPreviousMonthDisabled,
-.soria .dijitCalendarNextMonthDisabled	{
-	
-	background-color:#a4a5a6 !important;
-}
+
 .soria .dijitCalendarCurrentMonth {
-	
-}
-.soria .dijitCalendarCurrentMonthDisabled {
-	
-	background-color:#bbbbbc !important;
+	/* days that are part of this month */
 }
+
 .soria .dijitCalendarDisabledDate {
-	
-	
 	text-decoration:line-through !important;
-	cursor:default !important;
 }
+
 .soria .dijitCalendarCurrentDate {
-	
+	/* cell for today's date */
 	text-decoration:underline;
 	font-weight:bold;
 }
+
 .soria .dijitCalendarSelectedDate {
-	
+	/* cell for the selected date */
 	background-color:#b9cbf1 !important;
 	color:black !important;
 	border:#4b5aaa solid 1px !important;
 }
+
+
 .soria .dijitCalendarYearContainer {
-	
+	/* footer of the table that contains the year display/selector */
 	background:white url("images/titleBar.png") repeat-x top;
 }
+
 .soria .dijitCalendarYearLabel {
-	
+	/* container for all of 3 year labels */
 	margin:0;
 	padding:0.4em 0 0.25em 0;
 	text-align:center;
 }
+
 .soria .dijitCalendarSelectedYear {
-	
+	/* label for selected year */
 	color:black;
 	padding:0.2em;
 	padding-bottom:0.1em;
 	background-color:#b9cbf1 !important;
 	border:#4b5aaa solid 1px !important;
 }
+
 .soria .dijitCalendarNextYear,
 .soria .dijitCalendarPreviousYear {
-	
+	/* label for next/prev years */
 	color:black !important;
 	font-weight:normal;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/Calendar_rtl.css b/dijit/themes/soria/Calendar_rtl.css
index bcfa495..70efe52 100644
--- a/dijit/themes/soria/Calendar_rtl.css
+++ b/dijit/themes/soria/Calendar_rtl.css
@@ -1,7 +1,9 @@
+/* Calendar */
 
 .dijitRtl .soria .dijitCalendarDecrease {
 	background-position: -30px top;
 }
+
 .dijitRtl .soria .dijitCalendarIncrease {
 	background-position: 0px top;
 }
diff --git a/dijit/themes/soria/ColorPalette.css b/dijit/themes/soria/ColorPalette.css
index 5a51275..ed922ac 100644
--- a/dijit/themes/soria/ColorPalette.css
+++ b/dijit/themes/soria/ColorPalette.css
@@ -2,4 +2,4 @@
 	border:1px solid #cbcbcb;
 	background:#fff;
 	-moz-border-radius: 0px !important;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/Common.css b/dijit/themes/soria/Common.css
index 362a867..d5a7c9d 100644
--- a/dijit/themes/soria/Common.css
+++ b/dijit/themes/soria/Common.css
@@ -1,13 +1,17 @@
-
+/* DnD avatar-specific settings */
+/* For now it uses a default set of rules. Some other DnD classes can be modified as well. */
 .soria .dojoDndItemBefore {
 	border-top: 2px solid #369;
 }
+
 .soria .dojoDndItemAfter {
 	border-bottom: 2px solid #369;
 }
+
 .soria .dojoDndItemOver {
 	cursor:pointer;
 }
+
 .soria table.dojoDndAvatar { -moz-border-radius: 0; border: 1px solid #ccc; border-collapse: collapse; background-color: #fff; font-size: 75%; color: black;}
 .soria .dojoDndAvatar td	{ border: none; }
 .soria .dojoDndAvatar tr	{ border: none; }
diff --git a/dijit/themes/soria/Dialog.css b/dijit/themes/soria/Dialog.css
index c12f27d..c2a5107 100644
--- a/dijit/themes/soria/Dialog.css
+++ b/dijit/themes/soria/Dialog.css
@@ -1,3 +1,4 @@
+/* Dialog */
 
 .soria .dijitDialog {
 	background: #eee;
@@ -5,28 +6,31 @@
 	-webkit-box-shadow: 0px 5px 10px #adadad;
 	padding: 0px;
 }
+
 .soria .dijitDialog .dijitDialogTitle {
-	
+	/* typography and styling of the dialog title */
 	font-weight: bold;
 	padding: 0px 4px;
 	font-size: 0.9em;
 	color: #3243C5F;
 }
+
 .soria .dijitDialog .dijitDialogPaneContent {
 	background: #ffffff;
-	border:none;
-	border-top: 1px solid #b1badf; 
+	border-top: 1px solid #b1badf;
 	padding:10px;
+
 }
+
 .soria .dijitDialogTitleBar {
-	
+	/* outer container for the titlebar of the dialog */
 	background: #fafafa url("images/titleBar.png") repeat-x top left;
 	padding: 5px 6px 3px 6px;
-	cursor: move;
-	outline:0; 
+	outline:0; /* remove this line if keyboard focus on dialog startup is an issue. tab still takes you to first focusable element */
 }
+
 .soria .dijitDialogCloseIcon {
-	
+	/* the default close icon for the dialog */
 	background-image: url("images/spriteRoundedIconsSmallBl.png");
 	background-repeat: no-repeat;
 	background-position: -60px 0px;
@@ -36,56 +40,75 @@
 	top: 4px;
 	height: 15px;
 	width: 15px;
-	cursor: pointer;
 }
 .dj_ie6 .soria .dijitDialogCloseIcon {
 	background-image: url("images/spriteRoundedIconsSmallBl.gif");
 }
-.soria .dijitDialogCloseIcon-hover {
+.soria .dijitDialogCloseIconHover {
 	background-position: -60px -15px;
 }
+
+/* Tooltip and TooltipDialog */
+
 .soria .dijitTooltip,
 .soria .dijitTooltipDialog {
-	
-	background: transparent;	
+	/* the outermost dom node, holding the connector and container */
+	background: transparent;	/* make the area on the sides of the arrow transparent */
 }
+
 .dijitTooltipBelow {
-	
+	/* leave room for arrow above content */
 	padding-top: 10px;
 }
+
 .dijitTooltipAbove {
-	
+	/* leave room for arrow below content */
 	padding-bottom: 10px;
 }
+
 .soria .dijitTooltipContainer {
-	
+	/*
+		The part with the text.
+
+		NOTE:
+			FF doesn't clip images used as CSS bgs if you specify a border
+			radius. If you use a solid color, it does. Webkit gets it right.
+			Sigh.
+		background: #ffffff url("images/popupMenuBg.gif") repeat-x bottom left;
+	*/
 	background-color: #fff;
 	border:1px solid #cbcbcb;
 	padding:0.45em;
 }
+
 .soria .dijitTooltipConnector {
-	
+	/* the arrow piece */
 	border:0px;
 	z-index: 2;
 }
+
 .soria .dijitTooltipABRight .dijitTooltipConnector {
-	
+	/* above or below tooltip, but the arrow appears on the right,
+		and the right edges of target and tooltip are aligned rather than the left */
 	left: auto !important;
 	right: 6px;
 }
+
 .soria .dijitTooltipBelow .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips below an element */
 	top: 0px;
 	left: 6px;
 	background:url("images/tooltipConnectorUp.png") no-repeat top left;
 	width:17px;
 	height:11px;
 }
+
 .dj_ie .soria .dijitTooltipBelow .dijitTooltipConnector {
 	background-image: url("images/tooltipConnectorUp.gif");
 }
+
 .soria .dijitTooltipAbove .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips above an element */
 	bottom: 0px;
 	left: 6px;
 	background:url("images/tooltipConnectorDown.png") no-repeat top left;
@@ -101,6 +124,7 @@
 .dj_ie6 .soria .dijitTooltipAbove .dijitTooltipConnector {
 	bottom: -5px;
 }
+
 .soria .dijitTooltipLeft {
 	padding-right: 10px;
 }
@@ -108,7 +132,7 @@
 	padding-left: 11px;
 }
 .soria .dijitTooltipLeft .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips to the left of an element, bottom borders aligned */
 	right: 0px;
 	bottom: 3px;
 	background:url("images/tooltipConnectorRight.png") no-repeat top left;
@@ -118,11 +142,12 @@
 .dj_ie .soria .dijitTooltipLeft .dijitTooltipConnector {
 	background-image: url("images/tooltipConnectorRight.gif");
 }
+
 .soria .dijitTooltipRight {
 	padding-left: 10px;
 }
 .soria .dijitTooltipRight .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips to the right of an element, bottom borders aligned */
 	left: 0px;
 	bottom: 3px;
 	background:url("images/tooltipConnectorLeft.png") no-repeat top left;
@@ -132,3 +157,4 @@
 .dj_ie .soria .dijitTooltipRight .dijitTooltipConnector {
 	background-image: url("images/tooltipConnectorLeft.gif");
 }
+
diff --git a/dijit/themes/soria/Dialog_rtl.css b/dijit/themes/soria/Dialog_rtl.css
index 41db9ce..838700a 100644
--- a/dijit/themes/soria/Dialog_rtl.css
+++ b/dijit/themes/soria/Dialog_rtl.css
@@ -1,4 +1,4 @@
-
+/* Dialog */
 .dijitRtl .soria .dijitDialogTitleBar .dijitDialogCloseIcon {
 	right: auto;
 	left: 5px;
diff --git a/dijit/themes/soria/Editor.css b/dijit/themes/soria/Editor.css
index 6b481c7..d2dd293 100644
--- a/dijit/themes/soria/Editor.css
+++ b/dijit/themes/soria/Editor.css
@@ -1,65 +1,17 @@
-.dijitIEFixedToolbar {
-	position:absolute;
-	
-	top: expression(eval((document.documentElement||document.body).scrollTop));
-}
 .soria .dijitToolbar .dijitToolbarSeparator {
-	background: url('images/editor.gif');
+	background: url('../../icons/images/editorIconsEnabled.png'); /* separator in editor icons sprite image - enabled state */
 }
+
+/**** ICONS *****/
+
 .soria .dijitEditorIcon {
-	background-image: url('images/editor.gif'); 
+	background-image: url('../../icons/images/editorIconsEnabled.png'); /* editor icons sprite image - enabled state */
 	background-repeat: no-repeat;
 	width: 18px;
 	height: 18px;
 	text-align: center;
 }
 .soria .dijitDisabled .dijitEditorIcon {
-	background-image: url('images/editorDisabled.gif'); 
+	background-image: url('../../icons/images/editorIconsDisabled.png'); /* editor icons sprite image - disabled state */
 }
-.soria .dijitEditorIconSep { background-position: 0px; }
-.soria .dijitEditorIconBackColor { background-position: -18px; }
-.soria .dijitEditorIconBold { background-position: -36px; }
-.soria .dijitEditorIconCancel { background-position: -54px; }
-.soria .dijitEditorIconCopy { background-position: -72px; }
-.soria .dijitEditorIconCreateLink { background-position: -90px; }
-.soria .dijitEditorIconCut { background-position: -108px; }
-.soria .dijitEditorIconDelete { background-position: -126px; }
-.soria .dijitEditorIconForeColor { background-position: -144px; }
-.soria .dijitEditorIconHiliteColor { background-position: -162px; }
-.soria .dijitEditorIconIndent { background-position: -180px; }
-.soria .dijitEditorIconInsertHorizontalRule { background-position: -198px; }
-.soria .dijitEditorIconInsertImage { background-position: -216px; }
-.soria .dijitEditorIconInsertOrderedList { background-position: -234px; }
-.soria .dijitEditorIconInsertTable { background-position: -252px; }
-.soria .dijitEditorIconInsertUnorderedList { background-position: -270px; }
-.soria .dijitEditorIconItalic { background-position: -288px; }
-.soria .dijitEditorIconJustifyCenter { background-position: -306px; }
-.soria .dijitEditorIconJustifyFull { background-position: -324px; }
-.soria .dijitEditorIconJustifyLeft { background-position: -342px; }
-.soria .dijitEditorIconJustifyRight { background-position: -360px; }
-.soria .dijitEditorIconLeftToRight { background-position: -378px; }
-.soria .dijitEditorIconListBulletIndent { background-position: -396px; }
-.soria .dijitEditorIconListBulletOutdent { background-position: -414px; }
-.soria .dijitEditorIconListNumIndent { background-position: -432px; }
-.soria .dijitEditorIconListNumOutdent { background-position: -450px; }
-.soria .dijitEditorIconOutdent { background-position: -468px; }
-.soria .dijitEditorIconPaste { background-position: -486px; }
-.soria .dijitEditorIconRedo { background-position: -504px; }
-.soria .dijitEditorIconRemoveFormat { background-position: -522px; }
-.soria .dijitEditorIconRightToLeft { background-position: -540px; }
-.soria .dijitEditorIconSave { background-position: -558px; }
-.soria .dijitEditorIconSpace { background-position: -576px; }
-.soria .dijitEditorIconStrikethrough { background-position: -594px; }
-.soria .dijitEditorIconSubscript { background-position: -612px; }
-.soria .dijitEditorIconSuperscript { background-position: -630px; }
-.soria .dijitEditorIconUnderline { background-position: -648px; }
-.soria .dijitEditorIconUndo { background-position: -666px; }
-.soria .dijitEditorIconWikiword { background-position: -684px; }
-.soria .dijitEditorIconToggleDir { background-position: -540px; }
-.soria .dijitEditorIconTabIndent { background-position: -702px; }
-.soria .dijitEditorIconSelectAll { background-position: -720px; }
-.soria .dijitEditorIconUnlink { background-position: -738px; }
-.soria .dijitEditorIconFullScreen { background-position: -756px; }
-.soria .dijitEditorIconViewSource { background-position: -774px; }
-.soria .dijitEditorIconPrint { background-position: -792px; }
-.soria .dijitEditorIconNewPage { background-position: -810px; }
+
diff --git a/dijit/themes/soria/Editor_rtl.css b/dijit/themes/soria/Editor_rtl.css
index fd9658a..a1f76e8 100644
--- a/dijit/themes/soria/Editor_rtl.css
+++ b/dijit/themes/soria/Editor_rtl.css
@@ -1,10 +1,7 @@
-
+/* Editor */
 .dijitRtl .soria .dijitEditorIcon {
-	background-image: url('images/editor_rtl.gif'); 
+	background-image: url('../../icons/images/editorIconsEnabled_rtl.png'); /* editor icons sprite image - enabled state */
 }
 .dijitRtl .soria .dijitDisabled .dijitEditorIcon {
-	background-image: url('images/editorDisabled_rtl.gif'); 
-}
-.dijitRtl .soria .dijitToolbar .dijitToolbarSeparator {
-	background-image: url('images/editor_rtl.gif');
+	background-image: url('../../icons/images/editorIconsDisabled_rtl.png'); /* editor icons sprite image - disabled state */
 }
diff --git a/dijit/themes/soria/Menu.css b/dijit/themes/soria/Menu.css
index 9d6b97a..6a93f5f 100644
--- a/dijit/themes/soria/Menu.css
+++ b/dijit/themes/soria/Menu.css
@@ -1,4 +1,5 @@
 
+/* Menu */
 .soria .dijitMenu,
 .soria .dijitMenuBar {
 	border: 1px solid #cbcbcb;
@@ -6,9 +7,11 @@
 	padding: 0px;
 	background-color: #fff;
 }
+
 .soria .dijitBorderContainer .dijitMenuBar {
 	border:1px solid #B1BADF;
 }
+
 .soria .dijitMenuItem {
 	font-family: sans-serif;
 	margin: 0px;
@@ -17,21 +20,25 @@
 .soria .dijitMenuBar .dijitMenuItem {
 	padding: 4px 5px;
 }
+
 .soria .dijitMenuPreviousButton, .soria .dijitMenuNextButton {
 	font-style: italic;
 }
 .soria .dijitMenuItem TD {
 	padding:1px;
 }
+
 .soria .dijitMenuPassive .dijitMenuItemHover,
 .soria .dijitMenuItemSelected {
-	background-color: #d9e6f9; 
+	background-color: #d9e6f9; /* #95a0b0; #555555; #aaaaaa; #646464;  #60a1ea; #848484; */
 	color: #243C5F;
 }
+
 .soria .dijitMenuItemIcon {
 	width: 15px;
 	height: 15px;
 }
+
 .soria .dijitMenuExpand {
 	width:15px;
 	height:15px;
@@ -41,22 +48,30 @@
 .dj_ie6 .soria .dijitMenuExpand {
 	background-image: url('images/spriteRoundedIconsSmall.gif');
 }
+
 .soria .dijitMenuSeparator {
 	height: 1px;
 }
+
+/* separator can be two pixels -- set border of either one to 0px to have only one */
 .soria .dijitMenuSeparatorTop {
-	border-bottom: 1px solid #fff; 
+	border-bottom: 1px solid #fff; /*97adcb; */
 }
+
 .soria .dijitMenuSeparatorBottom {
 	border-top: 1px solid #8ba0bd;
 }
+
+/* the checked menu item */
 .soria .dijitCheckedMenuItemIconChar {
 	display: none;
 }
+
 .soria .dijitCheckedMenuItemIcon {
 	background-image: url('images/spriteCheckbox.gif');
 	background-position: -80px;
 }
+
 .soria .dijitCheckedMenuItemChecked .dijitCheckedMenuItemIcon {
 	background-position: -64px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/Menu_rtl.css b/dijit/themes/soria/Menu_rtl.css
index 6fa9a6a..fd521af 100644
--- a/dijit/themes/soria/Menu_rtl.css
+++ b/dijit/themes/soria/Menu_rtl.css
@@ -1,8 +1,10 @@
+/* Menu */
 
 .dijitRtl .soria .dijitMenuItem .dijitMenuItemIcon {
 	padding-left: 3px;
 	padding-right: 0px;
 }
+
 .dijitRtl .soria .dijitMenuItem .dijitMenuExpand {
 	background-position: left top;
 }
diff --git a/dijit/themes/soria/ProgressBar.css b/dijit/themes/soria/ProgressBar.css
index 566d048..7919cf3 100644
--- a/dijit/themes/soria/ProgressBar.css
+++ b/dijit/themes/soria/ProgressBar.css
@@ -1,24 +1,33 @@
 
+/****
+		dijit.ProgressBar
+ ****/
+
 .soria .dijitProgressBar {
 	margin:2px 0px 2px 0px;
 }
+
 .soria .dijitProgressBarEmpty{
-	
+	/* outer container and background of the bar that's not finished yet*/
 	background:#fff url("images/progressBarEmpty.png") repeat-x center center;
 	border-color: #8ba0bd;
 }
+
 .soria .dijitProgressBarTile{
-	
+	/* inner container for finished portion when in 'tile' (image) mode */
 	background:#f0f0f0 url("images/progressBarFull.png") repeat-x center center;
 }
+
 .soria .dijitProgressBarFull {
 	border-right:1px solid #8ba0bd;
 }
+
 .soria .dijitProgressBarLabel {
-	
+	/* Set to a color that contrasts with both the "Empty" and "Full" parts. */
 	color:#293a4b;
 }
+
 .soria .dijitProgressBarIndeterminate .dijitProgressBarTile {
-	
+	/* use an animated gif for the progress bar in 'indeterminate' mode */
 	background:#cad2de url("images/progressBarAnim.gif") repeat-x center center;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/TimePicker.css b/dijit/themes/soria/TimePicker.css
index a9db415..757d746 100644
--- a/dijit/themes/soria/TimePicker.css
+++ b/dijit/themes/soria/TimePicker.css
@@ -1,50 +1,51 @@
-
+/* Time Picker */
 .soria .dijitTimePickerTick,
 .soria .dijitTimePickerMarker {
 	border-color: #b1badf;
 }
+
 .soria .dijitTimePickerTick {
 	color:white;
 }
+
 .soria .dijitTimePickerMarker {
 	background:#bed7f0 url("images/titleBar.png") repeat-x top;
 	color:#293a4b;
 	font-weight: bold;
 }
+
 .soria .dijitTimePickerItemSelected {
 	color: black;
 	background: #b9cbf1 none;
 }
+
 .soria .dijitTimePickerItemHover {
 	background: #60a1ea none;
 	color:white;
 }
+
 .soria .dijitTimePickerItemHover,
 .soria .dijitTimePickerItemSelected {
 	position: relative;
 	z-index: 10;
 }
+
 .soria .dijitTimePickerTick .dijitTimePickerItemInner {
 	font-size:0.4em;
 }
+
 .soria .dijitTimePickerItemHover .dijitTimePickerItemInner,
 .soria .dijitTimePickerItemSelected .dijitTimePickerItemInner {
 	font-size:1em;
 }
+
 .soria .dijitTimePickerMarkerHover {
 	border-top: 1px solid #94b9ef;
 }
+
 .soria .dijitTimePickerTickHover,
 .soria .dijitTimePickerTickSelected {
 	margin-top:-0.3em;
 	margin-bottom:-0.3em;
 	border-bottom: none;
 }
-.dijit_a11y .dijitTimePickerTickHover {
-	background-color: #CCC !important;
-	border-top: 1px solid #333 !important;
-	border-bottom: 1px solid #333 !important;
-}
-.dijit_a11y .dijitTimePickerMarkerHover {
-	border-bottom-width: 2px;
-}
diff --git a/dijit/themes/soria/TimePicker_rtl.css b/dijit/themes/soria/TimePicker_rtl.css
new file mode 100644
index 0000000..bce88ad
--- /dev/null
+++ b/dijit/themes/soria/TimePicker_rtl.css
@@ -0,0 +1,4 @@
+.dj_ie6-rtl .soria .dijitTimePickerMarkerHover,
+.dj_ie7-rtl .soria .dijitTimePickerMarkerHover {
+        border-top: 0px; /* IE6/7 bug causes mouseover/out event storm */
+}
diff --git a/dijit/themes/soria/TitlePane.css b/dijit/themes/soria/TitlePane.css
index f9e49cd..04f6e0a 100644
--- a/dijit/themes/soria/TitlePane.css
+++ b/dijit/themes/soria/TitlePane.css
@@ -1,3 +1,7 @@
+/**
+ * dijit.TitlePane
+ *
+ */
 
 .soria .dijitTitlePaneTitle {
 	background: #cccccc;
@@ -8,25 +12,24 @@
 	font-weight: bold;
 	color: #6d6d6d;
 }
-.soria .dijitTitlePaneTitle-hover {
+.soria .dijitTitlePaneTitleHover {
 	background: #f9f9f9 url("images/accordionItemActive.png") top repeat-x;
-	cursor: pointer;
 }
+
 .soria .dijitTitlePaneTitle * {
 	vertical-align: middle;
 }
+
 .soria .dijitTitlePane .dijitOpen .dijitArrowNode,
 .soria .dijitTitlePane .dijitClosed .dijitArrowNode {
 	width:15px;
 	height:15px;
 }
-.soria .dijitTitlePaneFocused .dijitTitlePaneTextNode {
-	color: #243C5F;
-}
-.soria .dijitOpen .dijitTitlePaneTextNode,
-.soria .dijitFixedOpen .dijitTitlePaneTextNode {
+
+.soria .dijitTitlePaneTextNode {
 	color: #243C5F;
 }
+
 .soria .dijitTitlePane .dijitClosed .dijitArrowNode {
 	background: url('images/spriteRoundedIconsSmall.png') no-repeat -30px top;
 }
@@ -39,31 +42,17 @@
 .dj_ie6 .soria .dijitTitlePane .dijitOpen .dijitArrowNode {
 	background:url('images/spriteRoundedIconsSmall.gif') no-repeat -15px top;
 }
-.soria .dijitTitlePane .dijitArrowNodeInner {
-	display:none;
-}
-.dijit_a11y .dijitTitlePane .dijitOpen .dijitArrowNodeInner,
-.dijit_a11y .dijitTitlePane .dijitClosed .dijitArrowNodeInner {
-	display:inline !important;
-	font-family:monospace;
-	padding-bottom:.2em;
-}
-.dijit_a11y .dijitTitlePane .dijitArrowNode {
-	display:none;
-}
+
 .soria .dijitTitlePaneContentOuter {
 	background: #ffffff;
-	border:1px solid #bfbfbf;
-	border-top: 0px solid #3d3d3d;	
+	border: 1px solid #bfbfbf;
+	border-top: 0px;
 }
 .soria .dijitTitlePaneContentInner {
 	padding:10px;
 }
-.dj_ie6 .soria .dijitTitlePaneContentOuter,
-.dj_ie6 .soria .dijitTitlePane .dijitTitlePaneTitle {
-	zoom: 1;
-}
+
 .soria .dijitTitlePaneTextNode {
 	margin-left: 4px;
 	margin-right: 4px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/TitlePane_rtl.css b/dijit/themes/soria/TitlePane_rtl.css
index 1ac1245..82174fa 100644
--- a/dijit/themes/soria/TitlePane_rtl.css
+++ b/dijit/themes/soria/TitlePane_rtl.css
@@ -3,4 +3,4 @@
 }
 .dj_ie6-rtl .soria .dijitTitlePane .dijitClosed .dijitArrowNode {
 	background-position: 0px top;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/Toolbar.css b/dijit/themes/soria/Toolbar.css
index c3f2f6e..fc8913f 100644
--- a/dijit/themes/soria/Toolbar.css
+++ b/dijit/themes/soria/Toolbar.css
@@ -2,9 +2,12 @@
 	border-bottom: 1px solid #ccc;
 	background:#eaeaea url("images/titleBar.png") repeat-x top left;
 }
+
+/* setting a min-height on ditor toolbar */
 .dj_ie6 .soria .dijitToolbar {
 	height: 10px;
 }
+
 .soria .dijitToolbar .dijitButtonNode,
 .soria .dijitToolbar .dijitComboButton .dijitButtonContents,
 .soria .dijitToolbar .dijitComboButton .dijitDownArrowButton {
@@ -14,20 +17,23 @@
 	border: none;
 	font-size: 12px;
 }
+
 .soria .dijitToolbar .dijitButton,
 .soria .dijitToolbar .dijitToggleButton,
 .soria .dijitToolbar .dijitDropDownButton,
 .soria .dijitToolbar .dijitComboButton .dijitButtonContents,
 .soria .dijitToolbar .dijitComboButton .dijitDownArrowButton {
 	background: none;
-	padding: 1px;	
+	padding: 1px;	/* on hover etc., margin replaced w/border */
 }
+
 .soria .dijitToolbar .dijitButtonChecked,
 .soria .dijitToolbar .dijitToggleButtonChecked {
 	background-color:#d8e5f8;
 	border:1px solid #316ac5;
 	padding: 0px;
 }
+
 .soria .dijitToolbar .dijitButtonCheckedHover,
 .soria .dijitToolbar .dijitToggleButtonCheckedHover
  {
@@ -35,22 +41,25 @@
 	border:1px solid #316ac5;
 	padding: 0px;
 }
+
 .soria .dijitToolbar .dijitButtonHover,
 .soria .dijitToolbar .dijitToggleButtonHover,
 .soria .dijitToolbar .dijitDropDownButtonHover,
-.soria .dijitToolbar .dijitComboButtonHover .dijitButtonContents,
-.soria .dijitToolbar .dijitComboButtonDownArrowHover .dijitDownArrowButton {
-	
+.soria .dijitToolbar .dijitComboButton .dijitButtonContentsHover,
+.soria .dijitToolbar .dijitComboButton .dijitDownArrowButtonHover {
+	/* TODO: change this from Hover to Selected so that button is still highlighted while drop down is being used */
 	border: 1px solid #316ac5;
 	padding: 0px;
 	background-color:#9abbea;
 }
+
 .soria .dijitToolbar label {
 	padding: 3px 3px 0 6px;
 }
+
 .dj_ie .soria .dijitToolbar .dijitComboButton .dijitButtonContentsFocused,
 .dj_ie .soria .dijitToolbar .dijitComboButton .dijitDownArrowButtonFocused {
-	
+	/* focus border doesn't appear on <td> for IE, so need to add it manually */
 	border: 1px #777 dotted !important;
 	padding: 0px;
 }
diff --git a/dijit/themes/soria/Tree.css b/dijit/themes/soria/Tree.css
index 3930d25..dacf166 100644
--- a/dijit/themes/soria/Tree.css
+++ b/dijit/themes/soria/Tree.css
@@ -1,90 +1,105 @@
+/* Tree */
 
 .soria .dijitTreeNode {
     background : url('images/treeI.gif') no-repeat;
     background-position : top left;
     background-repeat : repeat-y;
-    zoom: 1;	
+    zoom: 1;	/* MOW: what the heck is this doing in here? */
 }
-.soria .dijitTreeNodeHover {
-	
+
+.soria .dijitTreeRowHover {
+	/* using a transparent png so that we can still see grid lines, which are (unfortunately) behind the dijitRowNode that we are hovering over */
 	background-image: url(images/treeHover.png);
 	background-repeat: repeat;
-	background-color: none !important;
+	background-color: transparent !important;
 }
+
+
+/* left vertical line (grid) for all nodes */
 .soria .dijitTreeIsLast {
     background: url('images/treeI_half.gif') no-repeat;
 }
+
 .soria .dijitTreeLabel {
 	font-weight: normal;
 	margin-left: 3px;
 }
+
 .soria .dijitTreeIsRoot {
     margin-left: 0;
     background-image: none;
 }
+
 .soria .dijitTreeExpando {
     width: 18px;
     height: 18px;
 }
+
 .soria .dijitTreeRow {
-	
+	/* so insert line shows up on IE when dropping after a target element */
 	padding-bottom: 2px;
 }
+
 .soria .dijitTreeContent {
     min-height: 18px;
     min-width: 18px;
     padding-left:1px;
 }
-.soria .dijitTreeExpand {
-    width: 18px;
-    height: 18px;
-    background-repeat : no-repeat;
-}
-.soria .dijitTreeNodeEmphasized {
-    background-color: Highlight;
-    color: HighlightText;
-}
-.soria .dijitTreeLabelFocused {
-	outline: 1px invert dotted;
-}
-.soria .dijitTreeNodeSelected .dijitTreeLabel{
+
+.soria .dijitTreeRowSelected .dijitTreeLabel{
 	background:#b8cbec;
 }
+
 .soria .dijitTreeExpandoOpened {
 	background: url('images/spriteTree.gif') no-repeat -18px top;
 }
+
 .soria .dijitTreeExpandoClosed {
 	background-image: url('images/spriteTree.gif');
 }
+
 .soria .dijitTreeExpandoLeaf {
 	background: url('images/spriteTree.gif') no-repeat -36px top;
 }
+
 .soria .dijitTreeExpandoLoading {
 	background-image: url('images/treeExpand_loading.gif');
 }
+
 .soria .dijitTreeIcon {
 	width: 16px;
 	height: 16px;
 }
+
 .soria .dijitFolderOpened {
 	background: url('images/spriteDivIcons.gif') no-repeat -16px top;
 }
+
 .soria .dijitFolderClosed {
 	background: url('images/spriteDivIcons.gif') no-repeat top left;
 }
+
 .soria .dijitLeaf {
 	background: url('images/spriteDivIcons.gif') no-repeat -32px top;
 }
+
+/* Drag and Drop on TreeNodes
+ * Put insert line on dijitTreeContent node so it's aligned w/
+ * (ie, indented equally with) target element, even
+ * though dijitTreeRowNode is the actual "drag object"
+ */
 .soria .dijitTreeNode .dojoDndItemBefore,
 .soria .dijitTreeNode .dojoDndItemAfter {
 	border-bottom: none;
 	border-top: none;
 }
+
 .soria .dijitTreeNode .dojoDndItemBefore .dijitTreeContent {
-	
+	/* copied from Common.css */
 	border-top: 2px solid #369;
 }
+
 .soria .dijitTreeNode .dojoDndItemAfter .dijitTreeContent {
-	
+	/* copied from Common.css */
 	border-bottom: 2px solid #369;
 }
diff --git a/dijit/themes/soria/Tree_rtl.css b/dijit/themes/soria/Tree_rtl.css
index ebe50b0..e68a1db 100644
--- a/dijit/themes/soria/Tree_rtl.css
+++ b/dijit/themes/soria/Tree_rtl.css
@@ -1,17 +1,22 @@
+/* Tree */
 
-.dijitRtl .soria .dijitTreeContainer .dijitTreeNode {
-    background-image : none;
+.dijitRtl .soria .dijitTreeNode,
+.dijitRtl .soria .dijitTreeExpandoLeaf {
+	/* disable grid lines for Tree in RTL mode, too hard to support */
+    background-image: none;
 }
-.dijitRtl .soria .dijitTreeContainer .dijitTreeContent {
-    padding-left: auto;
+
+.dijitRtl .soria .dijitTreeContent {
+    padding-left: 0px;
     padding-right: 1px;
 }
-.dijitRtl .soria .dijitTreeContainer .dijitTreeExpandoOpened {
+
+.dijitRtl .soria .dijitTreeExpandoOpened {
+	/* todo: icon contains grid line but grid lines disabled above */
 	background: url('images/spriteTree_rtl.gif') no-repeat -18px top;
 }
-.dijitRtl .soria .dijitTreeContainer .dijitTreeExpandoClosed {
+
+.dijitRtl .soria .dijitTreeExpandoClosed {
+	/* todo: icon contains grid line but grid lines disabled above */
 	background-image: url('images/spriteTree_rtl.gif');
 }
-.dijitRtl .soria .dijitTreeContainer .dijitTreeExpandoLeaf {
-	background: none;
-}
diff --git a/dijit/themes/soria/form/Button.css b/dijit/themes/soria/form/Button.css
index c85e954..c5b2646 100644
--- a/dijit/themes/soria/form/Button.css
+++ b/dijit/themes/soria/form/Button.css
@@ -1,7 +1,14 @@
 
+/*****
+		dijit.form.Button
+		dijit.form.DropDownButton
+		dijit.form.ComboButton
+		dijit.form.ComboBox (partial)
+		dijit.form.Spinner (partial) (TODO: create NumberSpinner.css file like claro has)
+ *****/
+
 .soria .dijitButtonNode {
-	
-	
+	/* enabled state - inner */
 	border: 1px solid #8ba0bd;
 	border-bottom:1px solid #657c9c;
 	padding: 0.1em 0.2em 0.2em 0.2em;
@@ -10,86 +17,106 @@
 .soria .dijitSelect .dijitButtonContents {
 	border-right: none;
 }
-.soria .dijitButtonNode button {
-	border: 0px;
-	background-color: transparent;
-}
+
 .soria .dijitButtonText {
 	text-align: center;
 	padding: 0 0.3em;
 }
-.soria .dijitComboBox .dijitButtonNode {
-	border-width: 0px 0px 0px 1px;
-}
+
 .soria .dijitArrowButton {
 	color: #111;
 }
+
 .soria .dijitComboButton .dijitDownArrowButton {
 	padding-right:4px;
 }
-.soria .dijitComboBoxReadOnly,
-.soria .dijitSpinnerReadOnly,
-.soria .dijitSpinnerReadOnly .dijitButtonNode,
+
+.soria .dijitTextBoxReadOnly,
+.soria .dijitTextBoxReadOnly .dijitButtonNode,
 .soria .dijitButtonDisabled .dijitButtonNode,
 .soria .dijitToggleButtonDisabled .dijitButtonNode,
 .soria .dijitDropDownButtonDisabled .dijitButtonNode,
 .soria .dijitComboButtonDisabled .dijitButtonNode,
-.soria .dijitComboBoxDisabled,
-.soria .dijitSpinnerDisabled,
-.soria .dijitSpinnerDisabled .dijitButtonNode {
-	
+.soria .dijitTextBoxDisabled,
+.soria .dijitTextBoxDisabled .dijitButtonNode {
+	/* disabled state - inner */
 	border-color: #b9bbdd #b9bbdd #b9bbdd #b9bbdd;
 	background:#c3d3e5 url("../images/buttonDisabled.png") top repeat-x;
 	opacity: 0.60;
 }
-.dj_ie6 .soria .dijitComboButtonDisabled .dijitButtonText {
-	
+.dj_ie6 .soria .dijitReadOnly INPUT,
+.dj_ie7 .soria .dijitReadOnly INPUT,
+.dj_ie6 .soria .dijitComboButtonDisabled .dijitButtonText,
+.dj_ie7 .soria .dijitComboButtonDisabled .dijitButtonText {
+	/* opacity doesn't work on table node in IE, work around here */
 	color: #aaa;
 }
 .soria .dijitButtonHover .dijitButtonNode,
 .soria .dijitButtonNodeHover,
 .soria .dijitToggleButtonHover .dijitButtonNode,
 .soria .dijitDropDownButtonHover .dijitButtonNode,
-.soria .dijitComboButtonHover .dijitButtonContents,
-.soria .dijitComboButtonDownArrowHover .dijitDownArrowButton,
-.soria .dijitComboBoxHover .dijitDownArrowButton,
-.soria .dijitSpinnerUpArrowHover .dijitUpArrowButton,
-.soria .dijitSpinnerDownArrowHover .dijitDownArrowButton {
-	
-	
+.soria .dijitButtonContentsHover,
+.soria .dijitUpArrowButtonHover,
+.soria .dijitDownArrowButtonHover {
+	/* hover state - inner */
+	/* TODO: change from Hover to Selected so that button is still highlighted while drop down is being used */
 	color:#243C5F;
 	background:#acc5e2 url("../images/buttonHover.png") repeat-x top left;
 }
+
 .soria .dijitButtonActive .dijitButtonNode,
 .soria .dijitToggleButtonActive .dijitButtonNode,
 .soria .dijitDropDownButtonActive .dijitButtonNode,
 .soria .dijitComboButtonActive .dijitButtonContents,
 .soria .dijitStackController .dijitToggleButtonChecked .dijitButtonNode {
-	
+	/* active state - inner (for when you are pressing a normal button, or
+	 * when a radio-type button is in a depressed state
+	 */
 	border-color:#657c9c;
 	background: #91b4e5 url("../images/buttonActive.png") top left repeat-x;
 }
-.soria .dijitSpinnerUpArrowActive .dijitUpArrowButton,
-.soria .dijitSpinnerDownArrowActive .dijitDownArrowButton,
-.soria .dijitComboBoxActive .dijitDownArrowButton {
-	
+.soria .dijitUpArrowButtonActive,
+.soria .dijitDownArrowButtonActive {
+	/* same as above except don't adjust border color (it's controlled by the containing Spinner/ComboBox) */
 	background: #91b4e5 url("../images/buttonActive.png") top left repeat-x;
 }
+
+
 .soria .dijitArrowButtonInner {
 	background-image: url("../images/spriteArrows.png");
 	background-repeat: no-repeat;
-	background-position: 0px top;
+	background-position: 0px center;
 	width: 11px;
+	height: 11px;
+}
+.soria .dijitComboBox .dijitArrowButtonInner {
+        background-position: 0 center;
 }
 .soria .dijitLeftArrowButton .dijitArrowButtonInner {
-	background-position: -11px top;
+	background-position: -11px center;
 }
 .soria .dijitUpArrowButton .dijitArrowButtonInner {
-	background-position: -22px top;
+	background-position: -22px center;
 }
 .soria .dijitRightArrowButton .dijitArrowButtonInner {
-	background-position: -33px top;
+	background-position: -33px center;
 }
 .dj_ie6 .soria .dijitArrowButtonInner {
 	background-image: url("../images/spriteArrows.gif");
 }
+.dj_ie .soria .dijitSpinner .dijitUpArrowButton .dijitArrowButtonInner {
+	margin-top: 1px; /* image has too many blank pixels on top */
+}
+.soria .dijitSpinnerButtonContainer {
+	width: auto;
+	padding: 0;
+}
+.soria .dijitSpinner .dijitArrowButton {
+	width: 15px;
+}
+.soria .dijitSpinner .dijitSpinnerButtonInner {
+	width: 15px;
+}
+.soria .dijitSpinner .dijitArrowButtonInner .dijitInputField {
+	padding: 0;
+}
diff --git a/dijit/themes/soria/form/Checkbox.css b/dijit/themes/soria/form/Checkbox.css
index 8227dcb..7ad1411 100644
--- a/dijit/themes/soria/form/Checkbox.css
+++ b/dijit/themes/soria/form/Checkbox.css
@@ -1,40 +1,67 @@
 
+/*
+ *  CheckBox and Radio Widgets,
+ *	and the CSS to embed a checkbox or radio icon inside a ToggleButton.
+ *
+ *	Order of images in the default sprite (from L to R, checkbox and radio in same image):
+ *		checkbox	normal 	 - checked
+ *							 - unchecked
+ *					disabled - checked
+ *							 - unchecked
+ *					hover 	 - checked
+ *							 - unchecked
+ *
+ *		radio		normal 	 - checked
+ *							 - unchecked
+ *					disabled - checked
+ *							 - unchecked
+ *					hover 	 - checked
+ *							 - unchecked
+*/
+
 .soria .dijitToggleButton .dijitCheckBox,
 .soria .dijitToggleButton .dijitCheckBoxIcon {
 	background-image: url('../images/spriteCheckbox.gif');
 }
+
 .soria .dijitCheckBox,
-.soria .dijitCheckBoxIcon {		
-	background-image: url('../images/spriteCheckbox.gif'); 
+.soria .dijitCheckBoxIcon {		/* inside a toggle button */
+	background-image: url('../images/spriteCheckbox.gif'); /* checkbox sprite image */
 	background-repeat: no-repeat;
 	width: 16px;
 	height: 16px;
 	margin: 0;
 	padding: 0;
 }
+
 .soria .dijitCheckBox,
 .soria .dijitToggleButton .dijitCheckBoxIcon {
-	
+	/* unchecked */
 	background-position: -16px;
 }
+
 .soria .dijitCheckBoxChecked,
 .soria .dijitToggleButtonChecked .dijitCheckBoxIcon {
-	
+	/* checked */
 	background-position: 0px;
 }
+
 .soria .dijitCheckBoxDisabled {
-	
+	/* disabled */
 	background-position: -48px;
 }
+
 .soria .dijitCheckBoxCheckedDisabled {
-	
+	/* disabled but checked */
 	background-position: -32px;
 }
+
 .soria .dijitCheckBoxHover {
-	
+	/* hovering over an unchecked enabled checkbox */
 	background-position: -80px;
 }
+
 .soria .dijitCheckBoxCheckedHover {
-	
+	/* hovering over a checked enabled checkbox */
 	background-position: -64px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/form/ComboBox.css b/dijit/themes/soria/form/ComboBox.css
deleted file mode 100644
index 9167139..0000000
--- a/dijit/themes/soria/form/ComboBox.css
+++ /dev/null
@@ -1,10 +0,0 @@
-.soria .dijitComboBox .dijitArrowButton .dijitArrowButtonInner {
-	background:url("../images/spriteArrows.png") no-repeat left center;
-	width: 11px;
-}
-.dj_ie6 .soria .dijitComboBox .dijitArrowButton .dijitArrowButtonInner {
-	background:url("../images/spriteArrows.gif") no-repeat left center;
-}
-.soria .dijitComboBoxHover .dijitArrowButtonInner {
-	
-}
diff --git a/dijit/themes/soria/form/Common.css b/dijit/themes/soria/form/Common.css
index 23bb181..faf18ae 100644
--- a/dijit/themes/soria/form/Common.css
+++ b/dijit/themes/soria/form/Common.css
@@ -1,76 +1,74 @@
 
-.soria .dijitInputField INPUT,
-.soria .dijitTextBox,
-.soria .dijitComboBox,
-.soria .dijitSpinner {
+/****
+		dijit.form.TextBox
+		dijit.form.ValidationTextBox
+		dijit.form.SerializableTextBox
+		dijit.form.RangeBoundTextBox
+		dijit.form.NumberTextBox
+		dijit.form.CurrencyTextBox
+		dijit.form.NumberSpinner
+		dijit.form.ComboBox (partial)
+ ****/
+
+.soria .dijitInputContainer INPUT,
+.soria .dijitTextBox {
 	margin: 0em 0.1em;
 }
+
 .soria .dijitTextBox,
-.soria .dijitComboBox,
-.soria .dijitSpinner,
-.soria .dijitInlineEditor input,
 .soria .dijitTextArea {
-	
+	/* 	For all except dijit.form.NumberSpinner:  the actual input element.
+		For TextBox, ComboBox, Spinner: the table that contains the input.
+		Otherwise the actual input element.
+	*/
 	background:#fff url("../images/validationInputBg.png") repeat-x top left;
+	#background:#fff url('../images/validationInputBg.gif') repeat-x top left;
 	border:1px solid #8ba0bd;
-	line-height: normal;
-}
-.dj_ie6 .soria .dijitTextBox,
-.dj_ie6 .soria .dijitComboBox,
-.dj_ie6 .soria .dijitSpinner,
-.dj_ie6 .soria .dijitInlineEditor input,
-.dj_ie6 .soria .dijitTextArea {
-	background:#fff url('../images/validationInputBg.gif') repeat-x top left;
 }
+
 .soria .dijitComboBox .dijitButtonNode {
 	padding: 0 0.2em;
 }
-.soria .dijitComboBox .dijitButtonNode,
-.soria .dijitSpinner .dijitButtonNode {
-	
+.soria .dijitTextBox .dijitButtonNode {
+	/* line between the input area and the drop down button */
 	border-color: #8ba0bd;
-	border-left: 1px solid #8ba0bd;
 }
+
 .soria .dijitTextBoxFocused,
-.soria .dijitComboBoxFocused,
-.soria .dijitSpinnerFocused, .soria .dijitSpinnerUpArrowActive, .soria .dijitSpinnerDownArrowActive,
 .soria .dijitTextAreaFocused {
-	
+	/* input field when focused (ie: typing affects it) */
 	border-color:#406b9b;
 }
-.soria .dijitComboBoxFocused .dijitButtonNode,
-.soria .dijitSpinnerFocused .dijitButtonNode,
-.soria .dijitSpinnerUpArrowActive .dijitButtonNode,
-.soria .dijitSpinnerDownArrowActive .dijitButtonNode {
+.soria .dijitTextBoxFocused .dijitButtonNode,
+.soria .dijitSpinner .dijitUpArrowButtonActive,
+.soria .dijitSpinner .dijitDownArrowButtonActive {
 	border-left-color:#8ba0bd;
 }
 .soria .dijitSpinnerFocused .dijitDownArrowButton,
-.soria .dijitSpinnerUpArrowActive .dijitDownArrowButton,
-.soria .dijitSpinnerDownArrowActive .dijitDownArrowButton {
+.soria .dijitSpinner .dijitUpArrowButtonActive,
+.soria .dijitSpinner .dijitDownArrowButtonActive {
 	border-top-color:#8ba0bd;
 }
+
 .soria .dijitError {
 	border-color:#f3d118;
 	background-color:#f9f7ba;
 	background-image:none;
 }
-.dj_ie6 .soria .dijitError INPUT {
-	
-	background-color:#f9f7ba !important;
-}
+
 .soria .dijitErrorFocused {
 	background-color:#ff6;
 	background-image:none;
 }
-.dj_ie6 .soria .dijitErrorFocused INPUT {
-	
-	background-color:#ff6 !important;
-}
+
+/* Validation errors  */
 .soria .dijitValidationIcon {
-	
+	/* prevent height change when widget goes from valid to invalid state */
 	width: 16px;
 	background: transparent url('../images/warning.png') no-repeat center center;
 }
+
+/* The highlight is shown in the ComboBox menu. */
 .soria .dijitComboBoxHighlightMatch {
 	background-color:#f9f7ba;
 }
diff --git a/dijit/themes/soria/form/Common_rtl.css b/dijit/themes/soria/form/Common_rtl.css
deleted file mode 100644
index 89f5ad7..0000000
--- a/dijit/themes/soria/form/Common_rtl.css
+++ /dev/null
@@ -1,7 +0,0 @@
-.dijitRtl .soria .dijitComboBox .dijitButtonNode,
-.dijitRtl .soria .dijitSpinner .dijitButtonNode {
-	
-	border-color: #8ba0bd;
-	border-left: 0px solid #8ba0bd;
-	border-right: 1px solid #8ba0bd;
-}
diff --git a/dijit/themes/soria/form/RadioButton.css b/dijit/themes/soria/form/RadioButton.css
index 543694e..7b875db 100644
--- a/dijit/themes/soria/form/RadioButton.css
+++ b/dijit/themes/soria/form/RadioButton.css
@@ -1,40 +1,66 @@
+/*
+ *  CheckBox and Radio Widgets,
+ *	and the CSS to embed a checkbox or radio icon inside a ToggleButton.
+ *
+ *	Order of images in the default sprite (from L to R, checkbox and radio in same image):
+ *		checkbox	normal 	 - checked
+ *							 - unchecked
+ *					disabled - checked
+ *							 - unchecked
+ *					hover 	 - checked
+ *							 - unchecked
+ *
+ *		radio		normal 	 - checked
+ *							 - unchecked
+ *					disabled - checked
+ *							 - unchecked
+ *					hover 	 - checked
+ *							 - unchecked
+*/
 
 .soria .dijitToggleButton .dijitRadio,
 .soria .dijitToggleButton .dijitRadioIcon {
 	background-image: url('../images/spriteRadio.gif');
 }
+
 .soria .dijitRadio,
-.soria .dijitRadioIcon	{		
-	background-image: url('../images/spriteRadio.gif'); 
+.soria .dijitRadioIcon	{		/* inside a toggle button */
+	background-image: url('../images/spriteRadio.gif'); /* checkbox sprite image */
 	background-repeat: no-repeat;
 	width: 16px;
 	height: 16px;
 	margin: 0;
 	padding: 0;
 }
+
 .soria .dijitRadio,
 .soria .dijitToggleButton .dijitRadioIcon {
-	
+	/* unselected */
 	background-position: -16px;
 }
+
 .soria .dijitRadioChecked,
 .soria .dijitToggleButtonChecked .dijitRadioIcon {
-	
+	/* selected */
 	background-position: 0px;
 }
+
 .soria .dijitRadioDisabled {
-	
+	/* unselected and disabled */
 	background-position: -48px;
 }
+
 .soria .dijitRadioCheckedDisabled {
-	
+	/* selected but disabled */
 	background-position: -32px;
 }
+
 .soria .dijitRadioHover {
-	
+	/* hovering over an unselected enabled radio button */
 	background-position: -80px;
 }
+
 .soria .dijitRadioCheckedHover {
-	
+	/* hovering over a selected enabled radio button */
 	background-position: -64px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/form/Select.css b/dijit/themes/soria/form/Select.css
index c0cd68e..758d25c 100644
--- a/dijit/themes/soria/form/Select.css
+++ b/dijit/themes/soria/form/Select.css
@@ -1,13 +1,8 @@
-
-.soria .dijitSelectDisabled * {
-    cursor: not-allowed !important;
-}
-.soria .dijitSelectReadOnly * {
-    cursor: default !important;
-}
 .soria .dijitSelect .dijitButtonNode {
 	padding: 0px;
 }
+
+/* Make unselected "look" more like a text box and less like a button */
 .soria .dijitSelect .dijitButtonContents {
 	padding-top: 1px;
     background:#fff url("../images/validationInputBg.png") repeat-x top left;
@@ -23,6 +18,12 @@
 .dj_ie .soria .dijitSelect .dijitButtonContents {
 	padding-top: 0px;
 }
+
+.soria .dijitSelect .dijitArrowButton {
+	padding: 0px 2px;
+}
+
+/* Mirror DropDownButton */
 .soria .dijitSelectDisabled .dijitButtonNode {
     border-color: #b9bbdd #b9bbdd #b9bbdd #b9bbdd;
     background:#c3d3e5 url("../images/buttonDisabled.png") top repeat-x;
@@ -30,23 +31,24 @@
 .dj_ie .soria .dijitSelectDisabled  .dijitButtonNode * {
 	filter: gray() alpha(opacity=50);
 }
+
 .soria .dijitSelectHover .dijitButtonNode {
     color:#000;
     background:#acc5e2 url("../images/buttonHover.png") repeat-x top left;
 }
+
 .soria .dijitSelectActive .dijitButtonNode,
 .soria .dijitSelectOpened .dijitButtonNode {
     border-color:#657c9c;
     background: #91b4e5 url("../images/buttonActive.png") top left repeat-x;
 }
+
+/* Make the menu look more combobox-like */
 .soria .dijitSelectMenu td {
 	padding: 0em;
 }
-.soria .dijitSelectMenu .dijitMenuItemIcon {
-	margin: 0.1em 0.2em;
-	display: none;
-}
 .soria .dijitSelectMenu .dijitMenuItemLabel,
 .soria .dijitSelectMenu .dijitMenuArrowCell {
 	padding: 0.1em 0.2em;
 }
+
diff --git a/dijit/themes/soria/form/Slider.css b/dijit/themes/soria/form/Slider.css
index f5a42ea..2884a13 100644
--- a/dijit/themes/soria/form/Slider.css
+++ b/dijit/themes/soria/form/Slider.css
@@ -1,101 +1,114 @@
 
+/****
+ 	SLIDER
+****/
+
 .soria .dijitSliderProgressBarH {
 	border-color: #b1badf;
 	background: #c0c2c5 url("../images/sliderFull.png") repeat-x top left;
 }
+
 .soria .dijitSliderProgressBarV {
 	border-color: #b1badf;
 	background: #c0c2c5 url("../images/sliderFullVertical.png") repeat-y bottom left;
 }
+
 .soria .dijitSliderFocused .dijitSliderProgressBarH,
 .soria .dijitSliderFocused .dijitSliderLeftBumper {
 	background-image:url("../images/sliderFullFocus.png");
 }
+
 .soria .dijitSliderFocused .dijitSliderProgressBarV,
 .soria .dijitSliderFocused .dijitSliderBottomBumper {
 	background-image:url("../images/sliderFullVerticalFocus.png");
 }
+
 .soria .dijitSliderRemainingBarV {
 	border-color: #b4b4b4;
 	background: #dcdcdc url("../images/sliderEmptyVertical.png") repeat-y bottom left;
 }
+
 .soria .dijitSliderRemainingBarH {
 	border-color: #b4b4b4;
 	background: #dcdcdc url("../images/sliderEmpty.png") repeat-x top left;
 }
+
 .soria .dijitSliderBar {
 	border-style: solid;
 	outline:1px;
-	
+	/* border-color: #b4b4b4; */
 }
 .soria .dijitSliderFocused .dijitSliderBar {
 	border-color:#8ba0bd;
 }
-.dijit_a11y .dijitSliderProgressBar {
-	background-color:#333 !important;
-}
+
 .soria .dijitSliderImageHandleH {
 	border:0px;
 	width:15px;
 	height:18px;
 	background:url("../images/preciseSliderThumb.png") no-repeat center top;
-	cursor:pointer;
 }
 .soria .dijitSliderFocused .dijitSliderImageHandleH {
 	background-image:url("../images/preciseSliderThumbFocus.png");
 	#background-image:url("../images/preciseSliderThumbFocus.gif");
 }
+
 .dj_ie6 .soria .dijitSliderImageHandleH {
 	background-image:url("../images/preciseSliderThumb.gif");
 }
+
 .soria .dijitSliderLeftBumper {
 	border-left-width: 1px;
 	border-color: #aab0bb;
 	background: #c0c2c5 url("../images/sliderFull.png") repeat-x top left;
 }
+
 .soria .dijitSliderRightBumper {
 	background: #dcdcdc url("../images/sliderEmpty.png") repeat-x top left;
 	border-color: #b4b4b4;
 	border-right-width: 1px;
 }
+
 .soria .dijitSliderImageHandleV {
 	border:0px;
 	width:20px;
 	height:15px;
 	background:url("../images/sliderThumb.png") no-repeat center center;
 	#background:url("../images/sliderThumb.gif") no-repeat center center;
-	cursor:pointer;
 }
+
 .soria .dijitSliderFocused .dijitSliderImageHandleV {
 	background-image:url("../images/sliderThumbFocus.png");
 	#background-image:url("../images/sliderThumbFocus.gif");
 }
+
 .soria .dijitSliderBottomBumper {
 	border-bottom-width: 1px;
 	border-color: #aab0bb;
 	background: #c0c2c5 url("../images/sliderFullVertical.png") repeat-y bottom left;
 }
+
 .soria .dijitSliderTopBumper {
 	background: #dcdcdc url("../images/sliderEmptyVertical.png") repeat-y top left;
 	border-color: #b4b4b4;
 	border-top-width: 1px;
 }
+
 .soria .dijitSliderIncrementIconH,
 .soria .dijitSliderIncrementIconV {
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat -45px top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat -45px top;
 	width:15px; height:15px;
-	cursor:pointer;
 }
 .soria .dijitSliderIncrementIconH {
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat -30px top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat -30px top;
 }
+
 .soria .dijitSliderDecrementIconH,
 .soria .dijitSliderDecrementIconV {
 	width:15px;
 	height:15px;
-	cursor:pointer;
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat -15px top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat -15px top;
 }
@@ -103,9 +116,11 @@
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat 0px top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat 0px top;
 }
+
 .soria .dijitSliderButtonInner {
 	visibility:hidden;
 }
+
 .soria .dijitSliderReadOnly *,
 .soria .dijitSliderDisabled * {
 	border-color: #d5d5d5 #bdbdbd #bdbdbd #d5d5d5;
@@ -126,4 +141,4 @@
 .soria .dijitSliderReadOnly .dijitSliderIncrementIconV,
 .soria .dijitSliderDisabled .dijitSliderIncrementIconV {
 	background-position: -45px -15px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/form/Slider_rtl.css b/dijit/themes/soria/form/Slider_rtl.css
index c1d8de3..2f7a08a 100644
--- a/dijit/themes/soria/form/Slider_rtl.css
+++ b/dijit/themes/soria/form/Slider_rtl.css
@@ -1,4 +1,6 @@
 
+/* Slider */
+
 .dijitRtl .soria .dijitSliderProgressBarH,
 .dijitRtl .soria .dijitSliderRemainingBarH,
 .dijitRtl .soria .dijitSliderLeftBumper,
@@ -6,23 +8,28 @@
 .dijitRtl .soria .dijitSliderTopBumper {
 	background-position: top right;
 }
+
 .dijitRtl .soria .dijitSliderProgressBarV,
 .dijitRtl .soria .dijitSliderRemainingBarV,
 .dijitRtl .soria .dijitSliderBottomBumper {
 	background-position: bottom right;
 }
+
 .dijitRtl .soria .dijitSliderLeftBumper {
 	border-left-width: 0px;
 	border-right-width: 1px;
 }
+
 .dijitRtl .soria .dijitSliderRightBumper {
 	border-left-width: 1px;
 	border-right-width: 0px;
 }
+
 .dijitRtl .soria .dijitSliderIncrementIconH {
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat left top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat left top;
 }
+
 .dijitRtl .soria .dijitSliderDecrementIconH {
 	background:url('../images/spriteRoundedIconsSmall.png') no-repeat -30px top;
 	#background:url('../images/spriteRoundedIconsSmall.gif') no-repeat -30px top;
diff --git a/dijit/themes/soria/form/TimeTextBox.css b/dijit/themes/soria/form/TimeTextBox.css
index d450925..bf67b66 100644
--- a/dijit/themes/soria/form/TimeTextBox.css
+++ b/dijit/themes/soria/form/TimeTextBox.css
@@ -1 +1 @@
- at CHARSET "UTF-8";
+ at CHARSET "UTF-8";
\ No newline at end of file
diff --git a/dijit/themes/soria/images/editor.gif b/dijit/themes/soria/images/editor.gif
deleted file mode 100644
index 750c6b9..0000000
Binary files a/dijit/themes/soria/images/editor.gif and /dev/null differ
diff --git a/dijit/themes/soria/images/editorDisabled.gif b/dijit/themes/soria/images/editorDisabled.gif
deleted file mode 100644
index e40460d..0000000
Binary files a/dijit/themes/soria/images/editorDisabled.gif and /dev/null differ
diff --git a/dijit/themes/soria/images/editorDisabled_rtl.gif b/dijit/themes/soria/images/editorDisabled_rtl.gif
deleted file mode 100644
index a0f6c10..0000000
Binary files a/dijit/themes/soria/images/editorDisabled_rtl.gif and /dev/null differ
diff --git a/dijit/themes/soria/images/editor_rtl.gif b/dijit/themes/soria/images/editor_rtl.gif
deleted file mode 100644
index a9740c2..0000000
Binary files a/dijit/themes/soria/images/editor_rtl.gif and /dev/null differ
diff --git a/dijit/themes/soria/layout/AccordionContainer.css b/dijit/themes/soria/layout/AccordionContainer.css
index eaaeebd..3e2d22d 100644
--- a/dijit/themes/soria/layout/AccordionContainer.css
+++ b/dijit/themes/soria/layout/AccordionContainer.css
@@ -1,37 +1,46 @@
+/**
+ * dijit.layout.Accordioncontainer
+ *
+ */
 
 .soria .dijitAccordionContainer {
 	border-color: #b1badf;
 	background-color: #fff;
 }
+
+/* common */
+
 .soria .dijitAccordionTitle {
 	background:#fafafa url("../images/titleBar.png") repeat-x top left;
 	border-top: 1px solid #b9bbdd;
 	padding: 5px 4px 6px 8px;
-	cursor:pointer;
 	font-size: 0.9em;
 	font-weight: bold;
 	color: #373941;
 }
-.soria .dijitAccordionTitle-selected  {
+
+.soria .dijitAccordionTitleSelected  {
 	background: #f9f9f9 url("../images/accordionItemActive.png") top repeat-x;
 	font-weight: bold;
 	border-top: 1px solid #b9bbdd;
 	border-bottom: 1px solid #b9bbdd;
 	padding: 5px 4px 5px 8px;
-	cursor: default;
 	color: #243C5F;
 }
+
 .soria .dijitAccordionArrow {
 	background:url("../images/spriteRoundedIconsSmallBl.gif") no-repeat -30px top;
 	width:15px;
 	height:15px;
 	margin-top:-1px;
 }
-.soria .dijitAccordionTitle-selected .dijitAccordionArrow {
+
+.soria .dijitAccordionTitleSelected .dijitAccordionArrow {
 	background:url("../images/spriteRoundedIconsSmallBl.gif") no-repeat -15px top;
 	margin-top:-1px;
 }
+
 .soria .dijitAccordionText {
 	margin-left: 4px;
 	margin-right: 4px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/layout/AccordionContainer_rtl.css b/dijit/themes/soria/layout/AccordionContainer_rtl.css
index bc67630..4c20d39 100644
--- a/dijit/themes/soria/layout/AccordionContainer_rtl.css
+++ b/dijit/themes/soria/layout/AccordionContainer_rtl.css
@@ -1,7 +1,8 @@
 .dijitRtl .soria .dijitAccordionArrow {
 	background-position: 0px top;
 }
-.dijitRtl .soria .dijitAccordionTitle-selected .dijitAccordionArrow {
-	
+
+.dijitRtl .soria .dijitAccordionTitleSelected .dijitAccordionArrow {
+	/* same rule as LTR mode, just listed to override previous rule in this file */
 	background-position: -15px top;
 }
diff --git a/dijit/themes/soria/layout/BorderContainer.css b/dijit/themes/soria/layout/BorderContainer.css
index aec147a..a170e83 100644
--- a/dijit/themes/soria/layout/BorderContainer.css
+++ b/dijit/themes/soria/layout/BorderContainer.css
@@ -1,25 +1,38 @@
+/**
+ * dijit.layout.BorderContainer
+ *
+ */
 
 .soria .dijitBorderContainer {
 	background-color: #e1ebfb;
 	padding: 5px;
 }
+
 .soria .dijitSplitContainer-child,
 .soria .dijitBorderContainer-child {
-	
+	/* By default put borders on all children of BorderContainer,
+	 *  to give illusion of borders on the splitters themselves.
+	 */
 	border: 1px #b1badf solid;
 }
+
 .soria .dijitBorderContainer-dijitTabContainerTop,
 .soria .dijitBorderContainer-dijitTabContainerBottom,
 .soria .dijitBorderContainer-dijitTabContainerLeft,
 .soria .dijitBorderContainer-dijitTabContainerRight {
-	
+	/* except that TabContainer defines borders on it's sub-nodes (tablist and dijitTabPaneWrapper),
+	 * so no border on domNode
+	 */
 	 border: none;
 }
+
 .soria .dijitBorderContainer-dijitBorderContainer {
-	
+	/* also, make nested BorderContainers look like a single big widget with lots of splitters */
 	border: none;
 	padding: 0px;
 }
+
+
 .soria .dijitSplitterH,
 .soria .dijitGutterH {
 	background: #E1EBFB;
@@ -28,12 +41,14 @@
 	border-right:0px solid #d3d3d3;
 	height:5px;
 }
+
 .soria .dijitSplitterH .dijitSplitterThumb {
 	background:#B0B0B0 none;
 	height:1px;
 	top:2px;
 	width:19px;
 }
+
 .soria .dijitSplitterV,
 .soria .dijitGutterV {
 	background: #E1EBFB;
@@ -42,12 +57,15 @@
 	border-bottom:0px solid #d3d3d3;
 	width:5px;
 }
+
 .soria .dijitSplitterV .dijitSplitterThumb {
 	background:#B0B0B0 none;
 	height:19px;
 	left:2px;
 	width:1px;
 }
+
+/* active splitter */
 .soria .dijitSplitterActive {
 	font-size: 1px;
 	background-image: none;
@@ -56,4 +74,4 @@
 	opacity: 0.6;
 	filter: Alpha(Opacity=60);
 	margin: 0;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/layout/ContentPane.css b/dijit/themes/soria/layout/ContentPane.css
index 9308d50..d1492d5 100644
--- a/dijit/themes/soria/layout/ContentPane.css
+++ b/dijit/themes/soria/layout/ContentPane.css
@@ -1,7 +1,10 @@
+/* ContentPane */
 
 .soria .dijitContentPane {
     padding: 0px;
 }
+
+/* nested layouts */
 .soria .dijitTabContainerTop-dijitContentPane,
 .soria .dijitTabContainerLeft-dijitContentPane,
 .soria .dijitTabContainerBottom-dijitContentPane,
@@ -10,8 +13,9 @@
     background-color: #fff;
     padding: 5px;
 }
+
 .soria .dijitSplitContainer-dijitContentPane,
 .soria .dijitBorderContainer-dijitContentPane {
-    background-color: #fff;		
+    background-color: #fff;		/* override background-color setting on parent .dijitBorderContainer */
     padding: 5px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/layout/SplitContainer.css b/dijit/themes/soria/layout/SplitContainer.css
index 87f0657..e066a3c 100644
--- a/dijit/themes/soria/layout/SplitContainer.css
+++ b/dijit/themes/soria/layout/SplitContainer.css
@@ -1,3 +1,7 @@
+/**
+ * dijit.layout.SplitContainer
+ *
+ */
 
 .soria .dijitSplitContainerSizerH {
 	background:url("../images/splitContainerSizerV.png") repeat-y #cddef4;
@@ -6,12 +10,14 @@
 	border-right:0px solid #436496;
 	width:5px;
 }
+
 .soria .dijitSplitContainerSizerH .thumb {
 	background:url("../images/splitContainerSizerV-thumb.png") no-repeat #ccc;
 	left:1px;
 	width:2px;
 	height:19px;
 }
+
 .soria .dijitSplitContainerSizerV {
 	background:url("../images/splitContainerSizerH.png") repeat-x #cddef4;
 	border:0;
@@ -19,9 +25,10 @@
 	border-bottom:0px solid #436496;
 	height:2px;
 }
+
 .soria .dijitSplitContainerSizerV .thumb {
 	background:url("../images/splitContainerSizerH-thumb.png") no-repeat #ccc;
 	top:1px;
 	width:19px;
 	height:5px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/layout/TabContainer.css b/dijit/themes/soria/layout/TabContainer.css
index 24f10f4..45472a4 100644
--- a/dijit/themes/soria/layout/TabContainer.css
+++ b/dijit/themes/soria/layout/TabContainer.css
@@ -1,3 +1,12 @@
+/**
+ * dijit.layout.TabContainer
+ *
+ * To style TabContainer with rounded corners
+ * you can use these classes: .dijitTab (left), .dijitTabContent (center), dijitTabInnerDiv (right)
+ * For tabs aligned to top you can style a stripe div right underneath the tabs using .dijitTabStripe
+ */
+
+/* Classes for all types of tabs (top/bottom/left/right) */
 
  .soria .dijitTabContainer .tabStripRBtn {
 	margin-right: 21px;
@@ -5,67 +14,84 @@
  .soria .dijitTabContainer .tabStripLBtn {
 	margin-left: 21px;
 }
+
  .soria .nowrapTabStrip .dijitTab {
 	top: 2px;
 }
+
  .soria .dijitTabContainerBottom-tabs .dijitTab {
 	top: -1px;
 	bottom: 2px;
 }
- .soria .dijitTabContainer .tabStripMenuButton-Hover {
-	cursor: pointer;
-}
+
+/* Tabs, shared classes */
 .soria .dijitTabPaneWrapper {
 	background:#fff;
 	border:1px solid #B1BADF;
 	margin: 0;
 	padding-left: 0px;
 }
+
 .soria .dijitTabInnerDiv {
 	padding:0px 3px 0px 0px;
 	margin: 0 0 0 4px;
 	background: url("../images/tabContainerSprite.gif") no-repeat;
 	background-position: right -400px;
 }
+
 .soria .dijitTab {
 	line-height:normal;
-	margin:0 2px 0 0;	
+	margin:0 2px 0 0;	/* space between one tab and the next in top/bottom mode */
 	padding:0px;
 	background: url("../images/tabContainerSprite.gif") no-repeat 0 -300px;
 	color: #243C5F;
 	border-bottom: 1px #B1BADF solid;
 }
+
 .soria .dijitTabInnerDiv .dijitTabContent {
 	padding:4px 3px 2px 4px;
 	background: url("../images/tabContainerSprite.gif") repeat-x 0 -350px;
 	position: relative;
 }
+
+
+
 .soria .dijitTabListWrapper {
 	z-index: 10;
 }
+
+/* hovered tab */
 .soria .dijitTabHover {
 	color: #243C5F;
 	background: url("../images/tabContainerSprite.gif") no-repeat 0px -150px;
 }
+
 .soria .dijitTabHover .dijitTabInnerDiv {
 	background: url("../images/tabContainerSprite.gif") no-repeat right -250px;
 }
+
 .soria .dijitTabHover .dijitTabInnerDiv .dijitTabContent {
 	background: url("../images/tabContainerSprite.gif") repeat-x 0 -200px;
 }
-.soria .dijitTabChecked,
-.soria .dijitTabCloseButtonChecked
+
+/* checked tab*/
+.soria .dijitTabChecked
 {
-	
+	/* the selected tab (with or without hover) */
 	background: url("../images/tabContainerSprite.gif") no-repeat 0px -0px;
 }
+
 .soria .dijitTabChecked .dijitTabInnerDiv {
 	background: url("../images/tabContainerSprite.gif") no-repeat right -100px;
 }
+
 .soria .dijitTabChecked .dijitTabInnerDiv .dijitTabContent {
 	background: url("../images/tabContainerSprite.gif") repeat-x 0 -50px;
 	color: #243C5F !important;
 }
+
+/* Nested Tabs */
+
 .soria .dijitTabContainerTabListNested {
 	background: #F0F4FC;
 	background: #D9E9F9;
@@ -74,7 +100,7 @@
 .soria .dijitTabContainerTabListNested .dijitTab {
 	background: none;
 	border: none;
-	top: 0px;	
+	top: 0px;	/* override top:1px setting of top-level tabs */
 }
 .soria .dijitTabContainerTabListNested .dijitTab .dijitTabInnerDiv,
 .soria .dijitTabContainerTabListNested .dijitTab .dijitTabContent {
@@ -88,163 +114,221 @@
 	font-weight: bold;
 }
 .soria .dijitTabContainerSpacerNested .dijitTabSpacer {
-	
+	/* thinner line between tab (labels) and content */
 	height: 0px;
 }
 .soria .dijitTabPaneWrapperNested {
-	border: none;	
+	border: none;	/* prevent double border */
 }
-.soria .dijitTab .closeImage {
+
+
+/* Close Button */
+.soria .dijitTabCloseButton {
 	width: 15px;
 	height: 15px;
 	background: url("../images/spriteRoundedIconsSmall.png") no-repeat -60px top;
 	margin-top: -1px;
 }
-.dj_ie6 .soria .dijitTab .dijitClosable .closeImage {
+.dj_ie6 .soria .dijitTabCloseButton {
 	background: url("../images/spriteRoundedIconsSmall.gif") no-repeat -60px top;
 }
-.soria .dijitTab .closeButton-hover .closeImage {
+
+.soria .dijitTabCloseButtonHover {
 	background: url("../images/spriteRoundedIconsSmall.png") no-repeat -60px -15px;
 }
-.dj_ie6 .soria .dijitTab .closeButton-hover .closeImage {
+.dj_ie6 .soria .dijitTabCloseButtonHover {
 	background: url("../images/spriteRoundedIconsSmall.gif") no-repeat -60px -15px;
 }
+
 .soria .dijitTab .tabLabel {
-	
+	/* make sure tabs w/close button and w/out close button are same height, even w/small (<15px) font */
 	min-height: 15px;
 	display: inline-block;
 }
 .dj_ie6 .soria .dijitTabButtonIcon {
-	
+	/* because min-height doesn't work on IE6 */
 	height: 18px;
 	width: 1px;
 }
+
+/* ================================ */
+/* top tabs */
 .soria .dijitTabContainerTop-tabs {
 	border-color: #B1BADF;
 	padding-left: 3px;
 }
+
 .soria .dijitTabContainerTopNoStrip {
 	padding-top: 3px;
 }
+
+/* top container */
 .soria .dijitTabContainerTop-container {
 	border-top: none;
 }
+
 .soria .dijitTabContainerTop .dijitTabListWrapper {
 	border-bottom: none;
 }
+
+/*non-checked tabs */
 .soria .dijitTabContainerTop-tabs .dijitTab {
 	top: 1px;
 }
+
+/* checked tabs */
 .soria .dijitTabContainerTop-tabs .dijitTabChecked {
 	border-bottom-color: #94b4e6;
 }
+
+/* strip */
 .soria .dijitTabContainerTopStrip {
 	border: 1px solid #B1BADF;
 	margin-top: 1px;
 	padding-top: 1px;
 	background: #F0F4FC;
 }
+
 .soria .dijitTabContainerTopStrip .dijitTabContainerTop-tabs {
 	padding-left: 3px;
 }
+
+
 .soria .dijitTabContainerNested .dijitTabListWrapper {
 	height: auto;
 }
+
+/* ================================ */
+/* bottom tabs */
 .soria .dijitTabContainerBottom-tabs {
 	margin-top: -1px;
 	padding-left: 3px;
 	border-top: 1px solid #B1BADF;
 }
+
 .soria .dijitTabContainerBottom .dijitTabListWrapper {
 	border-top: none;
 	padding-top: 1px;
 	padding-bottom: 1px;
 	float: left;
 }
+
+/* bottom container */
 .soria .dijitTabContainerBottom-container {
 	border-bottom: none;
 }
+
 .soria .dijitTabContainerBottom-tabs .dijitTab {
 	border-bottom: none;
 	border-top: 1px solid #B1BADF;
 	background: url("../images/tabBottomEnabledSpriteLR.gif") no-repeat bottom left;
 }
+
+/* checked tabs */
 .soria .dijitTabContainerBottom-tabs .dijitTabChecked {
 	border-top-color:#94b4e6;
 }
+
+
 .soria .dijitTabContainerBottom-tabs .dijitTabInnerDiv .dijitTabContent {
 	padding-top: 3px;
 	padding-bottom: 3px;
 	background: url("../images/tabBottomEnabledC.gif") repeat-x bottom left;
 }
+
 .soria .dijitTabContainerBottom-tabs .dijitTabInnerDiv {
 	background: url("../images/tabBottomEnabledSpriteLR.gif") no-repeat bottom right;
 }
+
 .soria .dijitTabContainerBottom-tabs .dijitTabHover {
 	color: #243C5F;
 	background: url("../images/tabBottomHoverSpriteLR.gif") no-repeat bottom left;
 }
+
 .soria .dijitTabContainerBottom-tabs .dijitTabHover .dijitTabInnerDiv {
 	background: url("../images/tabBottomHoverSpriteLR.gif") no-repeat bottom right;
 }
+
 .soria .dijitTabContainerBottom-tabs .dijitTabHover .dijitTabInnerDiv .dijitTabContent {
 	background: url("../images/tabBottomHoverC.gif") repeat-x bottom left;
 }
-.soria .dijitTabContainerBottom-tabs .dijitTabChecked,
-.soria .dijitTabContainerBottom-tabs .dijitTabCloseButtonChecked
-{
-	
+
+.soria .dijitTabContainerBottom-tabs .dijitTabChecked {
+	/* the selected tab (with or without hover) */
 	background: url("../images/tabBottomActiveSpriteLR.gif") no-repeat bottom left;
 }
+
 .soria .dijitTabContainerBottom-tabs .dijitTabChecked .dijitTabInnerDiv {
 	background: url("../images/tabBottomActiveSpriteLR.gif") no-repeat bottom right;
 }
+
 .soria .dijitTabContainerBottom-tabs .dijitTabChecked .dijitTabInnerDiv .dijitTabContent {
 	background: url("../images/tabBottomActiveC.gif") repeat-x bottom left;
 }
+
+/* strip */
 .soria .dijitTabContainerBottomStrip {
 	padding-bottom: 2px;
 	border: 1px solid #B1BADF;
 }
+
 .soria .dijitTabContainerBottomStrip {
 	background: #F0F4FC;
 }
+
+/* top/bottom strip */
 .soria .dijitTabContainerBottom-spacer,
 .soria .dijitTabContainerTop-spacer {
 	height: 2px;
 	border: 1px solid #8ba0bd;
 	background: #94b4e6;
 }
+
 .soria .dijitTabContainerTop-spacer {
 	border-top: none;
 }
+
 .soria .dijitTabContainerBottom-spacer {
 	border-bottom: none;
 }
+
+/* ================================ */
+/* right tabs */
 .soria .dijitTabContainerRight-tabs {
 	height: 100%;
 	border-color: #ccc;
 	padding-top: 3px;
 }
+
+/* right container */
 .soria .dijitTabContainerRight-container {
 	border-right: none;
 }
+
 .soria .dijitTabContainerRight-tabs .dijitTab {
 	border-bottom: none;
 	border-left: 1px solid #B1BADF;
 	border-bottom: 1px solid #B1BADF !important;
 }
+
+
+/* some odd ie bug when borders dissapear when setting a bottom margin, this sortof helps */
 .dj_ie6 .soria .dijitTabContainerRight-tabs .dijitTabInnerDiv,
 .dj_ie7 .soria .dijitTabContainerRight-tabs .dijitTabInnerDiv {
 	border-bottom: solid #B1BADF 1px;
 	margin-bottom: -1px;
 }
+
+/* checked tabs */
 .soria .dijitTabContainerRight-tabs .dijitTabChecked {
 	border-left-color: #94b4e6;
 }
+
 .soria .dijitTabContainerRight-tabs .dijitTabChecked {
 	background: url("../images/tabRightChecked.gif") no-repeat left top !important;
 }
+
+/* some odd ie bug when borders dissapear when setting a bottom margin, this sortof helps */
 .dj_ie6 .soria .dijitTabContainerRight-tabs .dijitTabChecked .dijitTabInnerDiv,
 .dj_ie7 .soria .dijitTabContainerRight-tabs .dijitTabChecked .dijitTabInnerDiv,
 .dj_ie6 .soria .dijitTabContainerRight-tabs .dijitTabCheckedHover .dijitTabInnerDiv,
@@ -252,33 +336,45 @@
 	border-bottom: solid #94b4e6 1px;
 	margin-bottom: -1px;
 }
+
 .soria .dijitTabContainerRight-tabs .dijitTab {
 	background: url("../images/tabContainerSprite.gif") no-repeat left -350px;
 }
 .soria .dijitTabContainerRight-tabs .dijitTabHover .dijitTab {
 	background: url("../images/tabContainerSprite.gif") no-repeat left -200px;
 }
+
+/* strip */
 .soria .dijitTabContainerRightStrip {
 	padding-right: 2px;
 	border: 1px solid #B1BADF;
 	background: #F0F4FC;
 	border-left: none;
 }
+
+/* ================================ */
+/* left tabs */
 .soria .dijitTabContainerLeft-tabs {
 	border-color: #ccc;
 	padding-top: 3px;
 	height: 100%;
 }
+
+/* left conatiner */
 .soria .dijitTabContainerLeft-container {
 	border-left: none;
 }
+
 .soria .dijitTabContainerLeft-tabs .dijitTab {
 	border-right: 1px solid #B1BADF;
 	border-bottom: 1px solid #B1BADF;
 }
+
+/* checked tabs */
 .soria .dijitTabContainerLeft-tabs .dijitTabChecked {
 	border-right: 1px solid #94b4e6;
 }
+
 .soria .dijitTabContainerLeft-tabs .dijitTabInnerDiv {
 	background: url("../images/tabContainerSprite.gif") no-repeat right -350px;
 }
@@ -289,11 +385,13 @@
 .soria .dijitTabContainerLeft-tabs .dijitTabCheckedHover .dijitTabInnerDiv {
 	background: url("../images/tabLeftChecked.gif") no-repeat right top;
 }
+
 .dj_ie6 .soria .dijitTabContainerLeft-tabs .dijitTabInnerDiv,
 .dj_ie7 .soria .dijitTabContainerLeft-tabs .dijitTabInnerDiv {
 	border-bottom: solid #B1BADF 1px;
 	margin-bottom: -1px;
 }
+
 .dj_ie6 .soria .dijitTabContainerLeft-tabs .dijitTabChecked .dijitTabInnerDiv,
 .dj_ie7 .soria .dijitTabContainerLeft-tabs .dijitTabChecked .dijitTabInnerDiv,
 .dj_ie6 .soria .dijitTabContainerLeft-tabs .dijitTabCheckedHover .dijitTabInnerDiv,
@@ -301,29 +399,40 @@
 	border-bottom: solid #94b4e6 1px;
 	margin-bottom: -1px;
 }
+
+/* strip */
 .soria .dijitTabContainerLeftStrip {
 	padding-left: 2px;
 	border: 1px solid #B1BADF;
 	background: #F0F4FC;
 	border-right: none;
 }
+
+/* ================================ */
+/* left/right tabs */
 .soria .dijitTabContainerLeft-tabs .dijitTab,
 .soria .dijitTabContainerRight-tabs .dijitTab {
 	margin-right:auto;
-	margin-bottom:2px;	
+	margin-bottom:2px;	/* space between one tab and the next in left/right mode */
 }
+
+/* left/right tabstrip */
 .soria .dijitTabContainerLeft-spacer,
 .soria .dijitTabContainerRight-spacer {
 	width: 2px;
 	border: 1px solid #8ba0bd;
 	background: #94b4e6;
 }
+
 .soria .dijitTabContainerLeft-spacer {
 	border-left: none;
 }
 .soria .dijitTabContainerRight-spacer {
 	border-right: none;
 }
+/* ================================ */
+
+/* this resets the tabcontainer stripe when within a contentpane */
 .soria .dijitTabContainerTop-dijitContentPane .dijitTabContainerTop-tabs {
 	border-left: 0px solid #ccc;
 	border-top: 0px solid #ccc;
@@ -331,54 +440,64 @@
 	padding-top: 0px;
 	padding-left: 0px;
 }
+
+
+/* ================================ */
+
+/* Menu and slider control styles */
 .soria .dijitTabContainer .tabStripButton {
 	margin-right: 0;
 }
 .soria .dijitTabContainer .tabStripButton-top {
 	margin-top: 1px;
 }
+
 .soria .tabStripButton .dijitTabContent{
 	padding: 6px 0 5px 0;
 }
+
 .dj_ie6 .soria .tabStripButton .dijitTabContent,
 .dj_ie7 .soria .tabStripButton .dijitTabContent {
 	padding-top: 7px;
 }
+
 .soria .tabStrip-disabled .tabStripButton .dijitTabContent {
 	padding: 5px 0 3px 0;
 }
+
 .dj_ie6 .soria .tabStrip-disabled .tabStripButton .dijitTabContent,
 .dj_ie7 .soria .tabStrip-disabled .tabStripButton .dijitTabContent {
 	padding-top: 6px;
 }
+
 .soria .dijitTabContainer .tabStripButton-bottom {
 	background: transparent url(../images/tabBottomEnabledSpriteLR.gif) no-repeat scroll left bottom;
 	border-bottom: medium none;
 	border-top: 1px solid #B1BADF;
 }
+
 .soria .dijitTabContainer .tabStripButton-bottom .dijitTabInnerDiv {
 	background: transparent url(../images/tabBottomEnabledSpriteLR.gif) no-repeat scroll right bottom;
 }
+
 .soria .dijitTabContainer .tabStripButton-bottom .dijitTabContent {
 	background: transparent;
 }
-.soria .dijitTabContainer .tabStripButton {
-	
-	width: 21px;
-}
-.soria .dijitTabContainer .tabStripButton img {
+
+.soria .dijitTabStripIcon {
 	height: 14px;
-	background: url(../images/spriteRoundedIconsSmall.png) no-repeat;
+	width: 14px;
+	background: url(../images/spriteRoundedIconsSmall.png) no-repeat left top ;
 }
-.dj_ie6 .soria .dijitTabContainer .tabStripButton img {
+
+.dj_ie6 .soria .dijitTabStripIcon {
 	background-image: url(../images/spriteRoundedIconsSmall.gif);
 }
-.soria .dijitTabContainer .tabStripMenuButton img {
-	background-position: -15px top;
-}
-.soria .dijitTabContainer .tabStripSlideButtonLeft img {
-	background-position: 0px top;
-}
-.soria .dijitTabContainer .tabStripSlideButtonRight img {
+
+.soria .dijitTabStripSlideRightIcon {
 	background-position: -30px top;
 }
+
+.soria .dijitTabStripMenuIcon {
+	background-position: -15px top;
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/layout/TabContainer_rtl.css b/dijit/themes/soria/layout/TabContainer_rtl.css
index 8638498..e9e1fbf 100644
--- a/dijit/themes/soria/layout/TabContainer_rtl.css
+++ b/dijit/themes/soria/layout/TabContainer_rtl.css
@@ -1,10 +1,13 @@
 .dijitRtl .soria .dijitTab {
 	margin-right:0;
-	margin-left:2px;		
+	margin-left:2px;		/* space between one tab and the next in top/bottom mode */
 }
+
+/* tab strips */
 .dijitRtl .soria .dijitTabContainer .tabStripButton {
 	margin-left: 0;
 }
+
 .dijitRtl .soria .dijitTabContainerTopStrip,
 .dijitRtl .soria .dijitTabContainerBottomStrip,
 .dijitRtl .soria .dijitTabContainerTop-tabs,
@@ -12,23 +15,29 @@
 	padding-left: 0;
 	padding-right: 3px;
 }
+
 .dijitRtl .soria .dijitTabInnerDiv {
 	padding-left: 3px;
 	padding-right: 4px;
 }
+
 .dijitRtl .soria .dijitTabPaneWrapper {
 	#zoom: 1;
 }
+
 .dj_ie-rtl .soria .dijitTabContainerLeft-tabs {
 	margin-left: 0px !important;
 }
+
 .dj_ie-rtl .soria .dijitTabContainerRight-tabs {
 	margin-right: 0px !important;
 }
+
 .dijitRtl .soria .dijitTabContainerLeft-tabs .dijitTab,
 .dijitRtl .soria .dijitTabContainerRight-tabs .dijitTab {
 	margin-left:0px;
 }
+
 .dj_ie-rtl .soria .dijitTab .dijitTabInnerDiv{
 	width : 1%;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/soria/soria.css b/dijit/themes/soria/soria.css
index 2493f7c..36471d0 100644
--- a/dijit/themes/soria/soria.css
+++ b/dijit/themes/soria/soria.css
@@ -1,3105 +1,41 @@
+/*
+	Adds cosmetic styling to Dijit.  Users may swap with a custom theme CSS file.
 
-.dijitReset {
-	
-	margin:0;
-	border:0;
-	padding:0;
-	line-height:normal;
-	font: inherit;
-	color: inherit;
-}
-.dijitInline {
-	
-	display:inline-block;			
-	#zoom: 1; 
-	#display:inline; 
-	border:0;
-	padding:0;
-	vertical-align:middle;
-	#vertical-align: auto;	
-}
-.dijitHidden {
-	
-	display: none !important;
-}
-.dijitVisible {
-	
-	display: block !important;	
-	position: relative;			
-}
-.dj_ie INPUT.dijitTextBox,
-.dj_ie .dijitInputField INPUT {
-	font-size: 100%;
-}
-.dj_ie .dijitInputField INPUT { 
-	margin: -1px 0 !important;
-}
-.dijitInlineTable {
-	
-	display:inline-table;
-	display:inline-block;		
-	#zoom: 1; 
-	#display:inline; 
-	box-sizing: content-box; -moz-box-sizing: content-box;
-	border:0;
-	padding:0;
-}
-.dijitTeeny {
-	font-size:1px;
-	line-height:1px;
-}
-.dijitPopup {
-	position: absolute;
-	background-color: transparent;
-	margin: 0;
-	border: 0;
-	padding: 0;
-}
-.dijit_a11y .dijitPopup,
-.dijit_ally .dijitPopup div,
-.dijit_a11y .dijitPopup table,
-.dijit_a11y .dijitTooltipContainer {
-	background-color: white !important;
-}
-.dijitInputField {
-	overflow:hidden;
-	#zoom:1;
-}
-.dijitPositionOnly {
-	
-	padding: 0 !important;
-	border: 0 !important;
-	background-color: transparent !important;
-	background-image: none !important;
-	height: auto !important;
-	width: auto !important;
-}
-.dijitNonPositionOnly {
-	
-	float: none !important;
-	position: static !important;
-	margin: 0 0 0 0 !important;
-	vertical-align: middle !important;
-}
-.dijitBackgroundIframe {
-	
-	position: absolute;
-	left: 0;
-	top: 0;
-	width: 100%;
-	height: 100%;
-	z-index: -1;
-	border: 0;
-	padding: 0;
-	margin: 0;
-}
-.dijitClickableRegion {
-	
-	background-color: #e2ebf2;
-	cursor: text;
-}
-.dijitDisplayNone {
-	
-	display:none !important;
-}
-.dijitContainer {
-	
-	overflow: hidden;	
-}
-.dijit_a11y * {
-	background-image:none !important;
-}
-.dijit_a11y .dijitCalendarIncrementControl {
-	display: none;	
-}
-.dijit_a11y .dijitA11ySideArrow {
-	display: inline !important; 
-	cursor: pointer;
-}
-.dijit_a11y .dijitCalendarDateLabel {
-	padding: 1px;
-}
-.dijit_a11y .dijitCalendarSelectedDate .dijitCalendarDateLabel {
-	border: solid 1px black;
-	padding: 0px;
-}
-.dijit_a11y .dijitCalendarDateTemplate {
-	padding-bottom: 0.1em !important;	
-}
-.dijit_a11y .dijit * {
-	background:white !important;
-	color:black !important;
-}
-.dijit_a11y .dijitButtonNode {
-	border-color: black!important;
-	border-style: outset!important;
-	border-width: medium!important;
-}
-.dijit_a11y .dijitComboBoxReadOnly .dijitInputField,
-.dijit_a11y .dijitComboBoxReadOnly .dijitButtonNode,
-.dijit_a11y .dijitSpinnerReadOnly .dijitButtonNode,
-.dijit_a11y .dijitSpinnerReadOnly .dijitInputField,
-.dijit_a11y .dijitButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitDropDownButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitComboButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitComboBoxDisabled .dijitInputField,
-.dijit_a11y .dijitComboBoxDisabled .dijitButtonNode,
-.dijit_a11y .dijitSpinnerDisabled .dijitButtonNode,
-.dijit_a11y .dijitSpinnerDisabled .dijitInputField {
-	border-style: outset!important;
-	border-width: medium!important;
-	border-color: #999 !important;
-	color:#999 !important;
-}
-.dijitButtonNode * {
-	vertical-align: middle;
-}
-.dijit_a11y .dijitArrowButtonInner {
-	width: 1em;
-	display: none !important;
-}
-.dijitButtonNode .dijitArrowButtonInner {
-	background:no-repeat center;
-	width: 16px;
-}
-.dijitComboBox .dijitArrowButtonInner {
-	display: block;
-}
-.dijit_a11y .dijitToggleButtonChecked .dijitToggleButtonIconChar {
-	display: inline !important;
-}
-.dijitLeft {
-	
-	background-position:left top;
-	background-repeat:no-repeat;
-}
-.dijitStretch {
-	
-	white-space:nowrap;			
-	background-repeat:repeat-x;
-}
-.dijitRight {
-	
-	#display:inline;				
-	background-position:right top;
-	background-repeat:no-repeat;
-}
-.dijitToggleButton,
-.dijitButton,
-.dijitDropDownButton,
-.dijitComboButton {
-	
-	margin: 0.2em;
-}
-.dijitToolbar .dijitToggleButton,
-.dijitToolbar .dijitButton,
-.dijitToolbar .dijitDropDownButton,
-.dijitToolbar .dijitComboButton {
-	margin: 0;
-}
-.dj_ie8 .dijitToolbar button,
-.dj_webkit .dijitToolbar button {
-	
-	padding: 1px 2px;
-}
-.dj_ie .dijitToolbar .dijitComboBox{
-	
-	vertical-align: middle;
-}
-.dj_ie .dijitComboButton {
-	
-	margin-bottom: -3px;
-}
-.dj_webkit .dijitToolbar .dijitDropDownButton {
-	padding-left: 0.3em;
-}
-.dj_gecko .dijitToolbar .dijitButtonNode::-moz-focus-inner {
-	padding:0;
-}
-.dijitButtonNode {
-	
-	border:1px solid gray;
-	margin:0;
-	line-height:normal;
-	vertical-align: middle;
-	#vertical-align: auto;
-	text-align:center;
-	white-space: nowrap;
-}
-.dijitButtonNode, .dijitButtonNode * {
-	cursor: pointer;
-}
-.dijitReadOnly *,
-.dijitDisabled *,
-.dijitReadOnly,
-.dijitDisabled,
-.dijitDisabledClickableRegion {	
-	cursor: not-allowed !important;
-}
-.dj_ie .dijitButtonNode {
-	
-	zoom: 1;
-}
-.dj_ie .dijitButtonNode button {
-	
-	overflow: visible;
-}
-.dijitArrowButton {
-	
-	
-	padding: 0 .4em;
-}
-DIV.dijitArrowButton {
-	float: right;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	border-style: solid;
-	border-width: 0 0 0 1px !important;
-	padding: 0;
-	position: absolute;
-	right: 0;
-	float: none;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	position: absolute;
-	height: 50%;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitDownArrowButton {
-	top: auto;
-	bottom: 0;
-	border-top-width: 1px !important;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitUpArrowButton {
-	top: 0;
-	bottom: auto;
-}
-TABLE.dijitComboButton {
-	
-	border-collapse: collapse;
-	border:0;
-	padding:0;
-	margin:0;
-}
-.dijitToolbar .dijitComboButton {
-	
-	border-collapse: separate;
-}
-.dj_ie BUTTON.dijitButtonNode {
-	overflow: visible; 
-}
-table .dijitButton .dijitButtonNode,
-table .dijitComboButton .dijitButtonNode {
-	#overflow:hidden; 
-}
-.dijitButtonNode IMG {
-	
-	vertical-align:middle;
-	
-}
-.dijitTextBox,
-.dijitComboBox,
-.dijitSpinner {
-	border: solid black 1px;
-	#overflow: hidden; 
-	width: 15em;	
-	vertical-align: middle;
-	#vertical-align: auto;
-}
-.dijitTimeTextBox {
-	width: 8em;
-}
-.dijitTextBox input:focus,
-.dijitComboBox input:focus,
-.dijitSpinner input:focus {
-	outline: none;	
-}
-.dijitTextBoxFocused,
-.dijitComboBoxFocused,
-.dijitSpinnerFocused, .dijitSpinnerUpArrowActive, .dijitSpinnerDownArrowActive,
-.dijitTextAreaFocused {
-	
-	outline: auto 5px -webkit-focus-ring-color;
-}
-.dijitTextBox INPUT,
-.dijitComboBox INPUT,
-.dijitSpinner INPUT {
-	border-left: solid black 1px;	
-	display:inline;
-	position:static !important;
-	border:0 !important;
-	margin:0 !important;
-	vertical-align:top !important;
-	background-color:transparent !important;
-	background-image:none !important;
-	width:100% !important;
-}
-.dijitValidationIcon {
-	visibility: hidden;
-	display: block;
-	padding: 0 2px;
-	float: right;
-	height: auto;
-}
-.dijitValidationIconText {
-	visibility: hidden;
-	display: none;
-	float:right;
-	font-family: sans-serif;
-	font-style:italic;
-	font-size: 0.75em;
-	padding-right: 0.15em;
-	line-height: 160%;
-}
-.dijit_a11y .dijitValidationIcon { display: none !important; }
-.dijit_a11y .dijitValidationIconText { display: block !important; }
-.dijitError .dijitValidationIcon,
-.dijitError .dijitValidationIconText {
-	visibility: visible;
-}
-.dijitTextBox .dijitArrowButton {
-	
-	display:none;
-}
-.dijitCheckBox,
-.dijitRadio,
-.dijitCheckBoxInput {
-	padding: 0;
-	border: 0;
-	width: 16px;
-	height: 16px;
-	background-position:center center;
-	background-repeat:no-repeat;
-	overflow: hidden;
-}
-.dijitCheckBox INPUT,
-.dijitRadio INPUT {
-	margin: 0;
-	padding: 0;
-	display: block;
-}
-.dijitCheckBoxInput {
-	
-	opacity: 0.01;
-}
-.dj_ie .dijitCheckBoxInput {
-	filter: alpha(opacity=0);
-}
-.dijit_a11y .dijitCheckBox,
-.dijit_a11y .dijitRadio {
-	width: auto;
-	height: auto;
-}
-.dijit_a11y .dijitCheckBoxInput {
-	opacity: 1;
-	filter: none;
-	width: auto;
-	height: auto;
-}
-.dijitProgressBarEmpty{
-	
-	position:relative;overflow:hidden;
-	border:1px solid black; 	
-	z-index:0;			
-}
-.dijitProgressBarFull {
-	
-	position:absolute;
-	overflow:hidden;
-	z-index:-1;
-	top:0;
-	width:100%;
-}
-.dj_ie6 .dijitProgressBarFull {
-	height:1.6em;
-}
-.dijitProgressBarTile {
-	
-	position:absolute;
-	overflow:hidden;
-	top:0;
-	left:0;
-	bottom:0;
-	right:0;
-	margin:0;
-	padding:0;
-	width:auto;
-	height:auto;
-	background-color:#aaa;
-	background-attachment: fixed;
-}
-.dijit_a11y .dijitProgressBarTile{
-	
-	border-width:4px;
-	border-style:solid;
-	background-color:transparent !important;
-}
-.dj_ie6 .dijitProgressBarTile {
-	
-	position:static;
-	
-	height:1.6em;
-}
-.dijitProgressBarIndeterminate .dijitProgressBarLabel {
-	visibility:hidden;
-}
-.dijitProgressBarIndeterminate .dijitProgressBarTile {
-	
-}
-.dijitProgressBarIndeterminateHighContrastImage {
-	display:none;
-}
-.dijit_a11y .dijitProgressBarIndeterminate .dijitProgressBarIndeterminateHighContrastImage {
-	display:block;
-	position:absolute;
-	top:0;
-	bottom:0;
-	margin:0;
-	padding:0;
-	width:100%;
-	height:auto;
-}
-.dijitProgressBarLabel {
-	display:block;
-	position:static;
-	width:100%;
-	text-align:center;
-	background-color:transparent !important;
-}
-.dijitTooltip {
-	position: absolute;
-	z-index: 2000;
-	display: block;
-	
-	left: 50%;
-	top: -10000px;
-	overflow: visible;
-}
-.dijitTooltipContainer {
-	border: solid black 2px;
-	background: #b8b5b5;
-	color: black;
-	font-size: small;
-}
-.dijitTooltipFocusNode {
-	padding: 2px 2px 2px 2px;
-}
-.dijitTooltipConnector {
-	position: absolute;
-}
-.dijitTooltipData {
-	display:none;
-}
-.dijitLayoutContainer{
-	position: relative;
-	display: block;
-	overflow: hidden;
-}
-body .dijitAlignTop,
-body .dijitAlignBottom,
-body .dijitAlignLeft,
-body .dijitAlignRight {
-	position: absolute;
-	overflow: hidden;
-}
-body .dijitAlignClient { position: absolute; }
-.dijitBorderContainer, .dijitBorderContainerNoGutter {
-	position:relative;
-	overflow: hidden;
-}
-.dijitBorderContainerPane,
-.dijitBorderContainerNoGutterPane {
-	position: absolute !important;	
-	z-index: 2;		
-}
-.dijitBorderContainer > .dijitTextArea {
-	
-	resize: none;
-}
-.dijitGutter {
-	
-	position: absolute;
-	font-size: 1px;		
-}
-.dijitSplitter {
-	position: absolute;
-	overflow: hidden;
-	z-index: 10;		
-	background-color: #fff;
-	border-color: gray;
-	border-style: solid;
-	border-width: 0;
-}
-.dj_ie .dijitSplitter {
-	z-index: 1;	
-}
-.dijitSplitterActive {
-	z-index: 11 !important;
-}
-.dijitSplitterCover{
-	position:absolute;
-	z-index:-1;
-	top:0;
-	left:0;
-	width:100%;
-	height:100%;
-}
-.dijitSplitterCoverActive{
-	z-index:3 !important;
-}
-.dj_ie .dijitSplitterCover{
-	background: white;
-	filter: alpha(opacity=0);
-}
-.dijitSplitterH {
-	height: 7px;
-	border-top:1px;
-	border-bottom:1px;
-	cursor: ns-resize;
-}
-.dijitSplitterV {
-	width: 7px;
-	border-left:1px;
-	border-right:1px;
-	cursor: ew-resize;
-}
-.dijitSplitContainer{
-	position: relative;
-	overflow: hidden;
-	display: block;
-}
-.dijitSplitPane{
-	position: absolute;
-}
-.dijitSplitContainerSizerH,
-.dijitSplitContainerSizerV {
-	position:absolute;
-	font-size: 1px;
-	cursor: move;
-	cursor: w-resize;
-	background-color: ThreeDFace;
-	border: 1px solid;
-	border-color: ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight;
-	margin: 0;
-}
-.dijitSplitContainerSizerH .thumb, .dijitSplitterV .dijitSplitterThumb {
-	overflow:hidden;
-	position:absolute;
-	top:49%;
-}
-.dijitSplitContainerSizerV .thumb, .dijitSplitterH .dijitSplitterThumb {
-	position:absolute;
-	left:49%;
-}
-.dijitSplitterShadow,
-.dijitSplitContainerVirtualSizerH,
-.dijitSplitContainerVirtualSizerV {
-	font-size: 1px;
-	background-color: ThreeDShadow;
-	-moz-opacity: 0.5;
-	opacity: 0.5;
-	filter: Alpha(Opacity=50);
-	margin: 0;
-}
-.dj_ie .dijitSplitterV, .dijitSplitContainerVirtualSizerH {
-	cursor: w-resize;
-}
-.dj_ie .dijitSplitterH, .dijitSplitContainerSizerV, .dijitSplitContainerVirtualSizerV {
-	cursor: n-resize;
-}
-.dijit_a11y .dijitSplitterH {
-	border-top:1px solid #d3d3d3 !important;
-	border-bottom:1px solid #d3d3d3 !important;
-}
-.dijit_a11y .dijitSplitterV {
-	border-left:1px solid #d3d3d3 !important;
-	border-right:1px solid #d3d3d3 !important;
-}
-.dijitContentPane {
-	display: block;
-	overflow: auto;	
-}
-.dijitContentPaneSingleChild {
-	
-	overflow: hidden;
-}
-.dijitTitlePane {
-	display: block;
-	overflow: hidden;
-}
-.dijitColorPalette {
-	border:1px solid #999;
-	background:#fff;
-	-moz-border-radius:3pt;
-}
-img.dijitColorPaletteUnder {
-	border-style:none;
-	position:absolute;
-	left:0;
-	top:0;
-}
-.dijitColorPaletteInner {
-	position: relative;
-	overflow:hidden;
-	outline:0;
-}
-.dijitPaletteCell {
-	width: 20px;
-	height: 20px;
-	position: absolute;
-	overflow: hidden;
-	z-index: 10;
-	outline-width: 0;
-}
-.dijitPaletteImg {
-	width: 16px; 
-	height: 14px; 
-	position: absolute;
-	top: 1px;
-	left: 1px;
-	overflow: hidden;
-	cursor: default;
-	border:1px solid #999;
-	
-}
-.dijitPaletteCellHighlight img {
-	width: 14px; 
-	height: 12px; 
-	position: absolute;
-	top: 1px;
-	left: 1px;
-	overflow: hidden;
-	cursor: default;
-	border:2px solid #000;
-	outline:1px solid #dedede;
-	
-}
-.dijit_a11y .dijitPaletteCell {
-	background-color:transparent !important;
-}
-.dijit_a11y .dijitPaletteImg {
-	background-color:transparent !important;
-}
-.dijitAccordionContainer {
-	border:1px solid #b7b7b7;
-	border-top:0 !important;
-}
-.dj_webkit .dijitAccordionContainer  div:focus {
-	outline:none;
-}
-.dj_ff3 .dijitAccordionContainer  div:focus {
-	outline:none;
-}
-.dijitAccordionTitle {
-	cursor: pointer;
-}
-.dijitAccordionFocused  {
-	text-decoration: underline;
-}
-.dijitAccordionTitle .arrowTextUp,
-.dijitAccordionTitle .arrowTextDown {
-	display: none;
-	font-size: 0.65em;
-	font-weight: normal !important;
-}
-.dijit_a11y .dijitAccordionTitle .arrowTextUp,
-.dijit_a11y .dijitAccordionTitle-selected .arrowTextDown {
-	display: inline;
-}
-.dijit_a11y .dijitAccordionTitle-selected .arrowTextUp {
-	display: none;
-}
-.dijitCalendarContainer thead tr th, .dijitCalendarContainer thead tr td, .dijitCalendarContainer tbody tr td, .dijitCalendarContainer tfoot tr td {
-	padding: 0;
-}
-.dijitCalendarNextYear {
-	margin:0 0 0 0.55em;
-}
-.dijitCalendarPreviousYear {
-	margin:0 0.55em 0 0;
-}
-.dijitCalendarIncrementControl {
-	vertical-align: middle;
-}
-.dijitCalendarDisabledDate {
-	color:gray !important;
-}
-.dijitCalendarPreviousMonthDisabled,
-.dijitCalendarCurrentMonthDisabled,
-.dijitCalendarNextMonthDisabled {
-	cursor:default !important
-}
-.dijitCalendarIncrementControl,
-.dijitCalendarBodyContainer tbody tr td,
-.dijitCalendarDateTemplate,
-.dijitCalendarContainer .dijitInline {
-	cursor:pointer;
-}
-.dijitSpacer {
-	
-  	position: relative;
-  	height: 1px;
-  	overflow: hidden;
-  	visibility: hidden;
-}
-.dijitMenu {
-	border:1px solid black;
-	background-color:white;
-}
-.dijitMenuTable {
-	margin:1px 0;
-	border-collapse:collapse;
-	border-width:0;
-	background-color:white;
-}
-.dj_webkit .dijitMenuTable td[colspan="2"]{
-	border-right:hidden;
-}
-.dijitMenuItem{
-	text-align: left;
-	white-space: nowrap;
-	padding:.1em .2em;
-	cursor:pointer;
-}
-.dijitMenuPassive .dijitMenuItemHover,
-.dijitMenuItemSelected {
-	
-	background-color:black;
-	color:white;
-}
-.dijitMenuItemIcon, .dijitMenuExpand {
-	background-repeat: no-repeat;
-}
-.dijitMenuItemDisabled * {
-	
-	opacity:0.3;
-	cursor:default;
-}
-.dj_ie .dijit_a11y .dijitMenuItemDisabled td,
-.dj_ie .dijitMenuItemDisabled *,
-.dj_ie .dijitMenuItemDisabled td {
-	color:gray !important;
-	filter: alpha(opacity=35);
-}
-.dijitMenuItemLabel {
-	position: relative;
-	vertical-align: middle;
-}
-.dijit_a11y .dijitMenuItemSelected {
-	border: 1px #fff dotted !important;
-}
-.dj_ff3 .dijit_a11y .dijitMenuItem td {
-	padding: none !important;
-	background:none ! important;
-}
-.dijit_a11y .dijitMenuItemSelected .dijitMenuItemLabel {
-	border-width: 1px;
-	border-style: solid;
-}
-.dj_ie8 .dijit_a11y .dijitMenuItemLabel {
-	position:static;
-}
-.dijitMenuExpandA11y {
-	display: none;
-}
-.dijit_a11y .dijitMenuExpandA11y {
-	display: inline;
-}
-.dijitMenuSeparator td {
-	border: 0;
-	padding: 0;
-}
-.dijitMenuSeparatorTop {
-	height: 50%;
-	margin: 0;
-	margin-top:3px;
-	font-size: 1px;
-}
-.dijitMenuSeparatorBottom {
-	height: 50%;
-	margin: 0;
-	margin-bottom:3px;
-	font-size: 1px;
-}
-.dijitCheckedMenuItemIconChar {
-	vertical-align: middle;
-	visibility:hidden;
-}
-.dijitCheckedMenuItemChecked .dijitCheckedMenuItemIconChar {
-	visibility: visible;
-}
-.dijit_a11y .dijitCheckedMenuItemIconChar {
-	display:inline !important;
-}
-.dijit_a11y .dijitCheckedMenuItemIcon {
-	display: none;
-}
-.dijitStackController .dijitToggleButtonChecked * {
-	cursor: default;	
-}
-.dijitTabContainerNoLayout {
-	width: 100%;	
-}
-.dijitTabContainerBottom-tabs,
-.dijitTabContainerTop-tabs,
-.dijitTabContainerLeft-tabs,
-.dijitTabContainerRight-tabs {
-	overflow: visible !important;  
-}
-.dijitTabContainerBottom-container,
-.dijitTabContainerTop-container,
-.dijitTabContainerLeft-container,
-.dijitTabContainerRight-container {
-	z-index:0;
-	overflow: hidden;
-	border: 1px solid black;
-}
-.dijitTabContainer .nowrapTabStrip {
-	width: 50000px;
-	display: block;
-	position: relative;
-}
-.dijitTabContainer .dijitTabListWrapper {
-	overflow: hidden;
-}
-.dijit_a11y .dijitTabContainer .tabStripButton img {
-	
-	display: none;
-}
-.dijitTabContainerTop-tabs {
-	border-bottom: 1px solid black;
-}
-.dijitTabContainerTop-container {
-	border-top: 0px;
-}
-.dijitTabContainerLeft-tabs {
-	border-right: 1px solid black;
-	float: left;
-}
-.dijitTabContainerLeft-container {
-	border-left: 0px;
-}
-.dijitTabContainerBottom-tabs {
-	border-top: 1px solid black;
-}
-.dijitTabContainerBottom-container {
-	border-bottom: 0px;
-}
-.dijitTabContainerRight-tabs {
-	border-left: 1px solid black;
-	float: left;
-}
-.dijitTabContainerRight-container {
-	border-right: 0px;
-}
-div.dijitTabBtnDisabled, .dj_ie div.dijitTabBtnDisabled {
-	cursor: auto;
-}
-.dijitTab {
-	position:relative;
-	cursor:pointer;
-	white-space:nowrap;
-	z-index:3;
-}
-.dijitTab * {
-	
-	vertical-align: middle;
-}
-.dijitTabChecked {
-	cursor: default;	
-}
-.dijitTabButtonIcon {
-	height: 18px;
-}
-.dijitTabContainerTop-tabs .dijitTab {
-	top: 1px;	
-}
-.dijitTabContainerBottom-tabs .dijitTab {
-	top: -1px;	
-}
-.dijitTabContainerLeft-tabs .dijitTab {
-	left: 1px;	
-}
-.dijitTabContainerRight-tabs .dijitTab {
-	left: -1px;	
-}
-.dijitTabContainerTop-tabs .dijitTab,
-.dijitTabContainerBottom-tabs .dijitTab {
-	
-	display:inline-block;			
-	#zoom: 1; 
-	#display:inline; 
-}
-.dijitTabInnerDiv {
-	position:relative;
-}
-.tabStripButton {
-	z-index: 12;
-}
-.dijitTabButtonDisabled .tabStripButton {
-	display: none;
-}
-.dijitTab .closeButton {
-	margin-left: 1em;
-}
-.dijitTab .closeText {
-	display:none;
-}
-.dijit_a11y .closeText {
-	display:inline;
-	margin: 0px 6px;
-}
-.dijit_a11y .dijitTab .closeImage {
-	display:none;
-}
-.dijit_a11y .closeButton-hover .closeText {
-	border:thin solid;
-}
-.dijit_a11y .dijitTabChecked {
-	border-style:dashed !important;
-}
-.dijit_a11y .dijitTabInnerDiv {
-	border-left:none !important;
- }
-.dijitTabPane,
-.dijitStackContainer-child,
-.dijitAccordionContainer-child {
-	
-    border: none !important;
-}
-.dijitInlineEditor {
-	
-	position:relative;
-	vertical-align:bottom;
-}
-.dj_ie .dijitInlineEditor {
-	vertical-align:middle;
-}
-.dijitInlineValue {
-	
-}
-.dijitInlineEditor .dijitButtonContainer {
-	
-	position:absolute;
-	right:0;
-	overflow:visible;
-}
-.dijitInlineEditor .saveButton,
-.dijitInlineEditor .cancelButton {
-}
-.dijitTreeIndent {
-	
-	width: 19px;
-}
-.dijitTreeRow, .dijitTreeContent {
-	white-space: nowrap;
-}
-.dijitTreeRow img {
-	
-	vertical-align: middle;
-}
-.dijitTreeContent {
-    cursor: default;
-}
-.dijitExpandoText {
-	display: none;
-}
-.dijit_a11y .dijitExpandoText {
-	display: inline;
-	padding-left: 10px;
-	padding-right: 10px;
-	font-family: monospace;
-	border-style: solid;
-	border-width: thin;
-	cursor: pointer;
-}
-.dijitTreeLabel {
-	margin: 0px 4px;
-}
-.dijitDialog {
-	position: absolute;
-	z-index: 999;
-	padding: 1px;
-	overflow: hidden;       
-}
-.dijitDialogFixed div.dijitDialogTitleBar {
-	cursor:default;
-}
-.dijitDialogUnderlayWrapper {
-	position: absolute;
-	left: 0;
-	top: 0;
-	z-index: 998;
-	display: none;
-	background: transparent !important;
-}
-.dijitDialogUnderlay {
-	background: #eee;
-	opacity: 0.5;
-}
-.dj_ie .dijitDialogUnderlay {
-	filter: alpha(opacity=50);
-}
-.dijit_a11y .dijitInputLayoutContainer,
-.dijit_a11y .dijitDialog {
-	opacity: 1 !important;
-	background-color: white !important;
-}
-.dijitDialog .closeText {
-	display:none;
-	
-	position:absolute;
-}
-.dijit_a11y .dijitDialog .closeText {
-	display:inline;
-}
-.dijitSliderMoveable {
-	z-index:99;
-	position:absolute !important;
-	display:block;
-	vertical-align:middle;
-}
-.dijitSliderMoveableH {
-	right:0;
-}
-.dijit_a11y div.dijitSliderImageHandle,
-.dijitSliderImageHandle {
-	margin:0;
-	padding:0;
-	position:absolute !important;
-	border:8px solid gray;
-	width:0;
-	height:0;
-}
-.dijit_a11y .dijitSliderFocused .dijitSliderImageHandle {
-	border:4px solid #000;
-	height:8px;
-	width:8px;
-}
-.dijitSliderImageHandleV {
-	top:-8px;
-	left:-6px;
-}
-.dijitSliderImageHandleH {
-	left:-8px;
-	top:-5px;
-	vertical-align:top;
-}
-.dijitSliderBar {
-	border-style:solid;
-	border-color:black;
-}
-.dijitSliderBarContainerV {
-	position:relative;
-	height:100%;
-	z-index:1;
-}
-.dijitSliderBarContainerH {
-	position:relative;
-	z-index:1;
-}
-.dijitSliderBarH {
-	height:4px;
-	border-width:1px 0;
-}
-.dijitSliderBarV {
-	width:4px;
-	border-width:0 1px;
-}
-.dijitSliderProgressBar {
-	background-color:red;
-	z-index:1;
-}
-.dijitSliderProgressBarV {
-	position:static !important;
-	height:0%;
-	vertical-align:top;
-	text-align:left;
-}
-.dijitSliderProgressBarH {
-	position:absolute !important;
-	width:0%;
-	vertical-align:middle;
-	overflow:visible;
-}
-.dijitSliderRemainingBar {
-	overflow:hidden;
-	background-color:transparent;
-	z-index:1;
-}
-.dijitSliderRemainingBarV {
-	height:100%;
-	text-align:left;
-}
-.dijitSliderRemainingBarH {
-	width:100% !important;
-}
-.dijitSliderBumper {
-	overflow:hidden;
-	z-index:1;
-}
-.dijitSliderBumperV {
-	width:4px;
-	height:8px;
-	border-width:0 1px;
-}
-.dijitSliderBumperH {
-	width:8px;
-	height:4px;
-	border-width:1px 0;
-}
-.dijitSliderBottomBumper,
-.dijitSliderLeftBumper {
-	background-color:red;
-}
-.dijitSliderTopBumper,
-.dijitSliderRightBumper {
-	background-color:transparent;
-}
-.dijitSliderDecorationH {
-	text-align:center;
-}
-.dijitSlider .dijitSliderButton {
-	font-family:monospace;
-	margin:0;
-	padding:0;
-	display:block;
-}
-.dijit_a11y .dijitSliderButtonInner {
-	visibility:visible !important;
-}
-.dijitSliderButtonContainer {
-	text-align:center;
-	height:0;
-}
-.dijitSlider .dijitButtonNode {
-	padding:0;
-	display:block;
-}
-.dijitRuleContainer {
-	position:relative;
-	overflow:visible;
-}
-.dijitRuleContainerV {
-	height:100%;
-	line-height:0;
-	float:left;
-	text-align:left;
-}
-.dj_opera .dijitRuleContainerV {
-	line-height:2%;
-}
-.dj_ie .dijitRuleContainerV {
-	line-height:normal;
-}
-.dj_gecko .dijitRuleContainerV {
-	margin:0 0 1px 0; 
-}
-.dijitRuleMark {
-	position:absolute;
-	border:1px solid black;
-	line-height:0;
-	height:100%;
-}
-.dijitRuleMarkH {
-	width:0;
-	border-top-width:0 !important;
-	border-bottom-width:0 !important;
-	border-left-width:0 !important;
-}
-.dijitRuleLabelContainer {
-	position:absolute;
-}
-.dijitRuleLabelContainerH {
-	text-align:center;
-	display:inline-block;
-}
-.dijitRuleLabelH {
-	position:relative;
-	left:-50%;
-}
-.dijitRuleMarkV {
-	height:0;
-	border-right-width:0 !important;
-	border-bottom-width:0 !important;
-	border-left-width:0 !important;
-	width:100%;
-	left:0;
-}
-.dj_ie .dijitRuleLabelContainerV {
-	margin-top:-.55em;
-}
-.dijit_a11y .dijitButtonContents .dijitButtonText,
-.dijit_a11y .dijitTab .tabLabel {
-	display: inline !important;
-}
-.dj_ie7 .dijitButtonNode > BUTTON.dijitButtonContents > * {
-	position: relative; 
-}
-.dijitTextArea {
-	width:100%;
-	overflow-y: auto;	
-}
-.dijitTextArea[cols] {
-	width:auto; 
-}
-.dj_ie .dijitTextAreaCols {
-	width:auto;
-}
-.dijitTextArea > DIV {
-	text-decoration:none;
-	overflow:auto;
-	min-height: 1.40em;
-}
-.dj_ie .dijitTextArea p {
-	margin-top:0;
-	margin-bottom:0;
-	line-height: normal !important;
-}
-.dijitToolbarSeparator {
-	height: 18px;
-	width: 5px;
-	padding: 0 1px;
-	margin: 0;
-}
-.dijitIEFixedToolbar {
-	position:absolute;
-	
-	top: expression(eval((document.documentElement||document.body).scrollTop));
-}
-.RichTextEditable {
-	display: block;	
-}
-.dijitTimePickerItemInner {
-	text-align:center;
-	border:0;
-	padding:2px 8px 2px 8px;
-}
-.dijitTimePickerTick,
-.dijitTimePickerMarker {
-	border-bottom:1px solid gray;
-}
-.dijitTimePicker .dijitDownArrowButton {
-	border-top: none !important;
-}
-.dijitTimePickerTick {
-	color:#CCC;
-}
-.dijitTimePickerMarker {
-	color:black;
-	background-color:#CCC;
-}
-.dijitTimePickerItemSelected {
-	font-weight:bold;
-	color:#333;
-	background-color:#b7cdee;
-}
-.dijitTimePickerItemHover {
-	background-color:gray;
-	color:white;
-	cursor:pointer;
-}
-.dijit_a11y .dijitTimePickerItem {
-	border-bottom:1px solid #333;
-}
-.dijitToggleButtonIconChar {
-	display:none !important;
-}
-.dijit_a11y .dijitToggleButtonIconChar {
-	display:inline !important;
-}
-.dijit_a11y .dijitToggleButtonIconChar {
-	visibility:hidden;
-}
-.dijit_a11y .dijitToggleButtonChecked .dijitToggleButtonIconChar {
-	visibility:visible !important;
-}
-.dijitArrowButtonChar {
-	display:none !important;
-}
-.dijit_a11y .dijitArrowButtonChar {
-	display:inline !important;
-}
-.dijitInputLayoutContainer {
-	position: relative;
-	overflow: hidden;
-}
-.dijitSpinnerButtonContainer {
-	float: right;
-	width: 18px;
-	position: relative;
-	overflow: hidden;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	height: 50%;
-	width: 16px;
-	overflow: hidden;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButtonInner {
-	overflow: hidden;
-	line-height: 50%;
-}
-.dijit_a11y .dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	width: 100%;
-}
-.dijit_a11y .dijitSpinner .dijitArrowButton .dijitArrowButtonChar {
-	font-size: 0.4em;
-	vertical-align: top;
-}
-.dijit_a11y .dijitSpinnerButtonContainer {
-	width: 0.5em;
-	margin-left: 2px;
-	overflow: visible;
-}
-.dijit_a11y .dijitSpinnerButtonContainer .dijitButtonNode {
-	border-width: 1px 0px 0px 1px;
-	border-style: solid !important;
-}
-.dijitSelect {
-	margin: 0.2em;
-}
-.dj_ie .dijitSelect,
-.dj_ie7 .dijitSelect,
-.dj_iequirks .dijitSelect {
-	vertical-align: middle; 
-}
-.dj_ie8 .dijitSelect .dijitButtonText {
-	vertical-align: top;
-}
-.dijitSelect .dijitButtonNode {
-	text-align: left;
-}
-.dijitRtl .dijitSelect .dijitButtonNode {
-	text-align: right;
-}
-.dijitToolbar .dijitSelect {
-	margin: 0;
-}
-.dj_webkit .dijitToolbar .dijitSelect {
-	padding-left: 0.3em;
-}
-.dijit_a11y .dijitSelectDisabled .dijitButtonNode {
-	border-style: outset!important;
-	border-width: medium!important;
-	border-color: #999 !important;
-	color:#999 !important;
-}
-.dijitSelect .dijitButtonContents {
-	padding: 0px;
-	background: transparent none;
-}
-.dijitSelectFixedWidth .dijitButtonContents {
-	width: 100%;
-}
-.dijitSelect .dijitArrowButton {
-	width: 16px;
-}
-.dj_ie6 .dijitSelectMenu .dijitMenuItemLabel,
-.dj_ie7 .dijitSelectMenu .dijitMenuItemLabel {
-	
-	position: static;
-}
-.dijitSelectLabel *
-{
-	vertical-align: baseline;
-}
-.dijitSelectSelectedOption * {
-	font-weight: bold;
-}
-.dijitSelectMenu {
-	border-width: 1px;
-}
-.dijitSelect .dijitButtonContents {
-	white-space: nowrap;
-}
-.dijitSelectMenu .dijitMenuTable {
-	margin: 0px;
-	background-color: transparent;
-}
-.dijitTextBoxReadOnly,
-.dijitComboBoxReadOnly,
-.dijitSpinnerReadOnly,
-.dijitTextAreaReadOnly,
-.dijitTextBoxDisabled,
-.dijitComboBoxDisabled,
-.dijitSpinnerDisabled,
-.dijitTextAreaDisabled {
-	color: gray;
-}
-.dj_webkit .dijitTextBoxDisabled INPUT,
-.dj_webkit .dijitComboBoxDisabled INPUT,
-.dj_webkit .dijitSpinnerDisabled INPUT {
-	color: #eee;
-}
-.dj_webkit INPUT.dijitTextBoxDisabled,
-.dj_webkit TEXTAREA.dijitTextAreaDisabled {
-	color: #333; 
-}
-.dijit_a11y .dijitSliderReadOnly,
-.dijit_a11y .dijitSliderDisabled {
-	opacity:0.6;
-}
-.dj_ie .dijit_a11y .dijitSliderReadOnly .dijitSliderBar,
-.dj_ie .dijit_a11y .dijitSliderDisabled .dijitSliderBar {
-	filter: alpha(opacity=40);
-}
-.dijit_a11y .dijitSlider .dijitSliderButtonContainer DIV {
-	font-family: monospace; 
-	font-size: 1em;
-	line-height: 1em;
-	height: auto;
-	width: auto;
-	margin: 0px 4px;
-}
-.dijitForceStatic {
-    position: static !important;
-}
-.soria .dojoDndItemBefore {
-	border-top: 2px solid #369;
-}
-.soria .dojoDndItemAfter {
-	border-bottom: 2px solid #369;
-}
-.soria .dojoDndItemOver {
-	cursor:pointer;
-}
-.soria table.dojoDndAvatar { -moz-border-radius: 0; border: 1px solid #ccc; border-collapse: collapse; background-color: #fff; font-size: 75%; color: black;}
-.soria .dojoDndAvatar td	{ border: none; }
-.soria .dojoDndAvatar tr	{ border: none; }
-.soria .dojoDndAvatarHeader td	{ height: 20px; padding: 0 0 0 21px; }
-.soria .dojoDndAvatarItem td { padding: 2px;}
-.soria.dojoDndMove .dojoDndAvatarHeader	{background-color: #f58383; background-image: url(images/dndNoMove.png); background-repeat: no-repeat; background-position: 2px center;}
-.soria.dojoDndCopy .dojoDndAvatarHeader	{background-color: #f58383; background-image: url(images/dndNoCopy.png); background-repeat: no-repeat; background-position: 2px center;}
-.soria.dojoDndMove .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{background-color: #97e68d; background-image: url(images/dndMove.png); background-repeat: no-repeat; background-position: 2px center;}
-.soria.dojoDndCopy .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{background-color: #97e68d; background-image: url(images/dndCopy.png); background-repeat: no-repeat; background-position: 2px center;}
-.soria .dijitContentPane {
-    padding: 0px;
-}
-.soria .dijitTabContainerTop-dijitContentPane,
-.soria .dijitTabContainerLeft-dijitContentPane,
-.soria .dijitTabContainerBottom-dijitContentPane,
-.soria .dijitTabContainerRight-dijitContentPane,
-.soria .dijitAccordionContainer-dijitContentPane {
-    background-color: #fff;
-    padding: 5px;
-}
-.soria .dijitSplitContainer-dijitContentPane,
-.soria .dijitBorderContainer-dijitContentPane {
-    background-color: #fff;		
-    padding: 5px;
-}
- .soria .dijitTabContainer .tabStripRBtn {
-	margin-right: 21px;
-}
- .soria .dijitTabContainer .tabStripLBtn {
-	margin-left: 21px;
-}
- .soria .nowrapTabStrip .dijitTab {
-	top: 2px;
-}
- .soria .dijitTabContainerBottom-tabs .dijitTab {
-	top: -1px;
-	bottom: 2px;
-}
- .soria .dijitTabContainer .tabStripMenuButton-Hover {
-	cursor: pointer;
-}
-.soria .dijitTabPaneWrapper {
-	background:#fff;
-	border:1px solid #B1BADF;
-	margin: 0;
-	padding-left: 0px;
-}
-.soria .dijitTabInnerDiv {
-	padding:0px 3px 0px 0px;
-	margin: 0 0 0 4px;
-	background: url(images/tabContainerSprite.gif) no-repeat;
-	background-position: right -400px;
-}
-.soria .dijitTab {
-	line-height:normal;
-	margin:0 2px 0 0;	
-	padding:0px;
-	background: url(images/tabContainerSprite.gif) no-repeat 0 -300px;
-	color: #243C5F;
-	border-bottom: 1px #B1BADF solid;
-}
-.soria .dijitTabInnerDiv .dijitTabContent {
-	padding:4px 3px 2px 4px;
-	background: url(images/tabContainerSprite.gif) repeat-x 0 -350px;
-	position: relative;
-}
-.soria .dijitTabListWrapper {
-	z-index: 10;
-}
-.soria .dijitTabHover {
-	color: #243C5F;
-	background: url(images/tabContainerSprite.gif) no-repeat 0px -150px;
-}
-.soria .dijitTabHover .dijitTabInnerDiv {
-	background: url(images/tabContainerSprite.gif) no-repeat right -250px;
-}
-.soria .dijitTabHover .dijitTabInnerDiv .dijitTabContent {
-	background: url(images/tabContainerSprite.gif) repeat-x 0 -200px;
-}
-.soria .dijitTabChecked,
-.soria .dijitTabCloseButtonChecked
-{
-	
-	background: url(images/tabContainerSprite.gif) no-repeat 0px -0px;
-}
-.soria .dijitTabChecked .dijitTabInnerDiv {
-	background: url(images/tabContainerSprite.gif) no-repeat right -100px;
-}
-.soria .dijitTabChecked .dijitTabInnerDiv .dijitTabContent {
-	background: url(images/tabContainerSprite.gif) repeat-x 0 -50px;
-	color: #243C5F !important;
-}
-.soria .dijitTabContainerTabListNested {
-	background: #F0F4FC;
-	background: #D9E9F9;
-	border: none;
-}
-.soria .dijitTabContainerTabListNested .dijitTab {
-	background: none;
-	border: none;
-	top: 0px;	
-}
-.soria .dijitTabContainerTabListNested .dijitTab .dijitTabInnerDiv,
-.soria .dijitTabContainerTabListNested .dijitTab .dijitTabContent {
-	background: none;
-}
-.soria .dijitTabContainerTabListNested .dijitTabHover .dijitTabContent .tabLabel {
-	text-decoration: underline;
-}
-.soria .dijitTabContainerTabListNested .dijitTabChecked .tabLabel {
-	text-decoration: underline;
-	font-weight: bold;
-}
-.soria .dijitTabContainerSpacerNested .dijitTabSpacer {
-	
-	height: 0px;
-}
-.soria .dijitTabPaneWrapperNested {
-	border: none;	
-}
-.soria .dijitTab .closeImage {
-	width: 15px;
-	height: 15px;
-	background: url(images/spriteRoundedIconsSmall.png) no-repeat -60px top;
-	margin-top: -1px;
-}
-.dj_ie6 .soria .dijitTab .dijitClosable .closeImage {
-	background: url(images/spriteRoundedIconsSmall.gif) no-repeat -60px top;
-}
-.soria .dijitTab .closeButton-hover .closeImage {
-	background: url(images/spriteRoundedIconsSmall.png) no-repeat -60px -15px;
-}
-.dj_ie6 .soria .dijitTab .closeButton-hover .closeImage {
-	background: url(images/spriteRoundedIconsSmall.gif) no-repeat -60px -15px;
-}
-.soria .dijitTab .tabLabel {
-	
-	min-height: 15px;
-	display: inline-block;
-}
-.dj_ie6 .soria .dijitTabButtonIcon {
-	
-	height: 18px;
-	width: 1px;
-}
-.soria .dijitTabContainerTop-tabs {
-	border-color: #B1BADF;
-	padding-left: 3px;
-}
-.soria .dijitTabContainerTopNoStrip {
-	padding-top: 3px;
-}
-.soria .dijitTabContainerTop-container {
-	border-top: none;
-}
-.soria .dijitTabContainerTop .dijitTabListWrapper {
-	border-bottom: none;
-}
-.soria .dijitTabContainerTop-tabs .dijitTab {
-	top: 1px;
-}
-.soria .dijitTabContainerTop-tabs .dijitTabChecked {
-	border-bottom-color: #94b4e6;
-}
-.soria .dijitTabContainerTopStrip {
-	border: 1px solid #B1BADF;
-	margin-top: 1px;
-	padding-top: 1px;
-	background: #F0F4FC;
-}
-.soria .dijitTabContainerTopStrip .dijitTabContainerTop-tabs {
-	padding-left: 3px;
-}
-.soria .dijitTabContainerNested .dijitTabListWrapper {
-	height: auto;
-}
-.soria .dijitTabContainerBottom-tabs {
-	margin-top: -1px;
-	padding-left: 3px;
-	border-top: 1px solid #B1BADF;
-}
-.soria .dijitTabContainerBottom .dijitTabListWrapper {
-	border-top: none;
-	padding-top: 1px;
-	padding-bottom: 1px;
-	float: left;
-}
-.soria .dijitTabContainerBottom-container {
-	border-bottom: none;
-}
-.soria .dijitTabContainerBottom-tabs .dijitTab {
-	border-bottom: none;
-	border-top: 1px solid #B1BADF;
-	background: url(images/tabBottomEnabledSpriteLR.gif) no-repeat bottom left;
-}
-.soria .dijitTabContainerBottom-tabs .dijitTabChecked {
-	border-top-color:#94b4e6;
-}
-.soria .dijitTabContainerBottom-tabs .dijitTabInnerDiv .dijitTabContent {
-	padding-top: 3px;
-	padding-bottom: 3px;
-	background: url(images/tabBottomEnabledC.gif) repeat-x bottom left;
-}
-.soria .dijitTabContainerBottom-tabs .dijitTabInnerDiv {
-	background: url(images/tabBottomEnabledSpriteLR.gif) no-repeat bottom right;
-}
-.soria .dijitTabContainerBottom-tabs .dijitTabHover {
-	color: #243C5F;
-	background: url(images/tabBottomHoverSpriteLR.gif) no-repeat bottom left;
-}
-.soria .dijitTabContainerBottom-tabs .dijitTabHover .dijitTabInnerDiv {
-	background: url(images/tabBottomHoverSpriteLR.gif) no-repeat bottom right;
-}
-.soria .dijitTabContainerBottom-tabs .dijitTabHover .dijitTabInnerDiv .dijitTabContent {
-	background: url(images/tabBottomHoverC.gif) repeat-x bottom left;
-}
-.soria .dijitTabContainerBottom-tabs .dijitTabChecked,
-.soria .dijitTabContainerBottom-tabs .dijitTabCloseButtonChecked
-{
-	
-	background: url(images/tabBottomActiveSpriteLR.gif) no-repeat bottom left;
-}
-.soria .dijitTabContainerBottom-tabs .dijitTabChecked .dijitTabInnerDiv {
-	background: url(images/tabBottomActiveSpriteLR.gif) no-repeat bottom right;
-}
-.soria .dijitTabContainerBottom-tabs .dijitTabChecked .dijitTabInnerDiv .dijitTabContent {
-	background: url(images/tabBottomActiveC.gif) repeat-x bottom left;
-}
-.soria .dijitTabContainerBottomStrip {
-	padding-bottom: 2px;
-	border: 1px solid #B1BADF;
-}
-.soria .dijitTabContainerBottomStrip {
-	background: #F0F4FC;
-}
-.soria .dijitTabContainerBottom-spacer,
-.soria .dijitTabContainerTop-spacer {
-	height: 2px;
-	border: 1px solid #8ba0bd;
-	background: #94b4e6;
-}
-.soria .dijitTabContainerTop-spacer {
-	border-top: none;
-}
-.soria .dijitTabContainerBottom-spacer {
-	border-bottom: none;
-}
-.soria .dijitTabContainerRight-tabs {
-	height: 100%;
-	border-color: #ccc;
-	padding-top: 3px;
-}
-.soria .dijitTabContainerRight-container {
-	border-right: none;
-}
-.soria .dijitTabContainerRight-tabs .dijitTab {
-	border-bottom: none;
-	border-left: 1px solid #B1BADF;
-	border-bottom: 1px solid #B1BADF !important;
-}
-.dj_ie6 .soria .dijitTabContainerRight-tabs .dijitTabInnerDiv,
-.dj_ie7 .soria .dijitTabContainerRight-tabs .dijitTabInnerDiv {
-	border-bottom: solid #B1BADF 1px;
-	margin-bottom: -1px;
-}
-.soria .dijitTabContainerRight-tabs .dijitTabChecked {
-	border-left-color: #94b4e6;
-}
-.soria .dijitTabContainerRight-tabs .dijitTabChecked {
-	background: url(images/tabRightChecked.gif) no-repeat left top !important;
-}
-.dj_ie6 .soria .dijitTabContainerRight-tabs .dijitTabChecked .dijitTabInnerDiv,
-.dj_ie7 .soria .dijitTabContainerRight-tabs .dijitTabChecked .dijitTabInnerDiv,
-.dj_ie6 .soria .dijitTabContainerRight-tabs .dijitTabCheckedHover .dijitTabInnerDiv,
-.dj_ie7 .soria .dijitTabContainerRight-tabs .dijitTabCheckedHover .dijitTabInnerDiv {
-	border-bottom: solid #94b4e6 1px;
-	margin-bottom: -1px;
-}
-.soria .dijitTabContainerRight-tabs .dijitTab {
-	background: url(images/tabContainerSprite.gif) no-repeat left -350px;
-}
-.soria .dijitTabContainerRight-tabs .dijitTabHover .dijitTab {
-	background: url(images/tabContainerSprite.gif) no-repeat left -200px;
-}
-.soria .dijitTabContainerRightStrip {
-	padding-right: 2px;
-	border: 1px solid #B1BADF;
-	background: #F0F4FC;
-	border-left: none;
-}
-.soria .dijitTabContainerLeft-tabs {
-	border-color: #ccc;
-	padding-top: 3px;
-	height: 100%;
-}
-.soria .dijitTabContainerLeft-container {
-	border-left: none;
-}
-.soria .dijitTabContainerLeft-tabs .dijitTab {
-	border-right: 1px solid #B1BADF;
-	border-bottom: 1px solid #B1BADF;
-}
-.soria .dijitTabContainerLeft-tabs .dijitTabChecked {
-	border-right: 1px solid #94b4e6;
-}
-.soria .dijitTabContainerLeft-tabs .dijitTabInnerDiv {
-	background: url(images/tabContainerSprite.gif) no-repeat right -350px;
-}
-.soria .dijitTabContainerLeft-tabs .dijitTabHover .dijitTabInnerDiv {
-	background: url(images/tabContainerSprite.gif) no-repeat right -200px;
-}
-.soria .dijitTabContainerLeft-tabs .dijitTabChecked .dijitTabInnerDiv,
-.soria .dijitTabContainerLeft-tabs .dijitTabCheckedHover .dijitTabInnerDiv {
-	background: url(images/tabLeftChecked.gif) no-repeat right top;
-}
-.dj_ie6 .soria .dijitTabContainerLeft-tabs .dijitTabInnerDiv,
-.dj_ie7 .soria .dijitTabContainerLeft-tabs .dijitTabInnerDiv {
-	border-bottom: solid #B1BADF 1px;
-	margin-bottom: -1px;
-}
-.dj_ie6 .soria .dijitTabContainerLeft-tabs .dijitTabChecked .dijitTabInnerDiv,
-.dj_ie7 .soria .dijitTabContainerLeft-tabs .dijitTabChecked .dijitTabInnerDiv,
-.dj_ie6 .soria .dijitTabContainerLeft-tabs .dijitTabCheckedHover .dijitTabInnerDiv,
-.dj_ie7 .soria .dijitTabContainerLeft-tabs .dijitTabCheckedHover .dijitTabInnerDiv {
-	border-bottom: solid #94b4e6 1px;
-	margin-bottom: -1px;
-}
-.soria .dijitTabContainerLeftStrip {
-	padding-left: 2px;
-	border: 1px solid #B1BADF;
-	background: #F0F4FC;
-	border-right: none;
-}
-.soria .dijitTabContainerLeft-tabs .dijitTab,
-.soria .dijitTabContainerRight-tabs .dijitTab {
-	margin-right:auto;
-	margin-bottom:2px;	
-}
-.soria .dijitTabContainerLeft-spacer,
-.soria .dijitTabContainerRight-spacer {
-	width: 2px;
-	border: 1px solid #8ba0bd;
-	background: #94b4e6;
-}
-.soria .dijitTabContainerLeft-spacer {
-	border-left: none;
-}
-.soria .dijitTabContainerRight-spacer {
-	border-right: none;
-}
-.soria .dijitTabContainerTop-dijitContentPane .dijitTabContainerTop-tabs {
-	border-left: 0px solid #ccc;
-	border-top: 0px solid #ccc;
-	border-right: 0px solid #ccc;
-	padding-top: 0px;
-	padding-left: 0px;
-}
-.soria .dijitTabContainer .tabStripButton {
-	margin-right: 0;
-}
-.soria .dijitTabContainer .tabStripButton-top {
-	margin-top: 1px;
-}
-.soria .tabStripButton .dijitTabContent{
-	padding: 6px 0 5px 0;
-}
-.dj_ie6 .soria .tabStripButton .dijitTabContent,
-.dj_ie7 .soria .tabStripButton .dijitTabContent {
-	padding-top: 7px;
-}
-.soria .tabStrip-disabled .tabStripButton .dijitTabContent {
-	padding: 5px 0 3px 0;
-}
-.dj_ie6 .soria .tabStrip-disabled .tabStripButton .dijitTabContent,
-.dj_ie7 .soria .tabStrip-disabled .tabStripButton .dijitTabContent {
-	padding-top: 6px;
-}
-.soria .dijitTabContainer .tabStripButton-bottom {
-	background: transparent url(images/tabBottomEnabledSpriteLR.gif) no-repeat scroll left bottom;
-	border-bottom: medium none;
-	border-top: 1px solid #B1BADF;
-}
-.soria .dijitTabContainer .tabStripButton-bottom .dijitTabInnerDiv {
-	background: transparent url(images/tabBottomEnabledSpriteLR.gif) no-repeat scroll right bottom;
-}
-.soria .dijitTabContainer .tabStripButton-bottom .dijitTabContent {
-	background: transparent;
-}
-.soria .dijitTabContainer .tabStripButton {
-	
-	width: 21px;
-}
-.soria .dijitTabContainer .tabStripButton img {
-	height: 14px;
-	background: url(images/spriteRoundedIconsSmall.png) no-repeat;
-}
-.dj_ie6 .soria .dijitTabContainer .tabStripButton img {
-	background-image: url(images/spriteRoundedIconsSmall.gif);
-}
-.soria .dijitTabContainer .tabStripMenuButton img {
-	background-position: -15px top;
-}
-.soria .dijitTabContainer .tabStripSlideButtonLeft img {
-	background-position: 0px top;
-}
-.soria .dijitTabContainer .tabStripSlideButtonRight img {
-	background-position: -30px top;
-}
-.soria .dijitAccordionContainer {
-	border-color: #b1badf;
-	background-color: #fff;
-}
-.soria .dijitAccordionTitle {
-	background:#fafafa url(images/titleBar.png) repeat-x top left;
-	border-top: 1px solid #b9bbdd;
-	padding: 5px 4px 6px 8px;
-	cursor:pointer;
-	font-size: 0.9em;
-	font-weight: bold;
-	color: #373941;
-}
-.soria .dijitAccordionTitle-selected  {
-	background: #f9f9f9 url(images/accordionItemActive.png) top repeat-x;
-	font-weight: bold;
-	border-top: 1px solid #b9bbdd;
-	border-bottom: 1px solid #b9bbdd;
-	padding: 5px 4px 5px 8px;
-	cursor: default;
-	color: #243C5F;
-}
-.soria .dijitAccordionArrow {
-	background:url(images/spriteRoundedIconsSmallBl.gif) no-repeat -30px top;
-	width:15px;
-	height:15px;
-	margin-top:-1px;
-}
-.soria .dijitAccordionTitle-selected .dijitAccordionArrow {
-	background:url(images/spriteRoundedIconsSmallBl.gif) no-repeat -15px top;
-	margin-top:-1px;
-}
-.soria .dijitAccordionText {
-	margin-left: 4px;
-	margin-right: 4px;
-}
-.soria .dijitSplitContainerSizerH {
-	background:url(images/splitContainerSizerV.png) repeat-y #cddef4;
-	border:0;
-	border-left:0px solid #436496;
-	border-right:0px solid #436496;
-	width:5px;
-}
-.soria .dijitSplitContainerSizerH .thumb {
-	background:url(images/splitContainerSizerV-thumb.png) no-repeat #ccc;
-	left:1px;
-	width:2px;
-	height:19px;
-}
-.soria .dijitSplitContainerSizerV {
-	background:url(images/splitContainerSizerH.png) repeat-x #cddef4;
-	border:0;
-	border-top:0px solid #436496;
-	border-bottom:0px solid #436496;
-	height:2px;
-}
-.soria .dijitSplitContainerSizerV .thumb {
-	background:url(images/splitContainerSizerH-thumb.png) no-repeat #ccc;
-	top:1px;
-	width:19px;
-	height:5px;
-}
-.soria .dijitBorderContainer {
-	background-color: #e1ebfb;
-	padding: 5px;
-}
-.soria .dijitSplitContainer-child,
-.soria .dijitBorderContainer-child {
-	
-	border: 1px #b1badf solid;
-}
-.soria .dijitBorderContainer-dijitTabContainerTop,
-.soria .dijitBorderContainer-dijitTabContainerBottom,
-.soria .dijitBorderContainer-dijitTabContainerLeft,
-.soria .dijitBorderContainer-dijitTabContainerRight {
-	
-	 border: none;
-}
-.soria .dijitBorderContainer-dijitBorderContainer {
-	
-	border: none;
-	padding: 0px;
-}
-.soria .dijitSplitterH,
-.soria .dijitGutterH {
-	background: #E1EBFB;
-	border:0;
-	border-left:0px solid #d3d3d3;
-	border-right:0px solid #d3d3d3;
-	height:5px;
-}
-.soria .dijitSplitterH .dijitSplitterThumb {
-	background:#B0B0B0 none;
-	height:1px;
-	top:2px;
-	width:19px;
-}
-.soria .dijitSplitterV,
-.soria .dijitGutterV {
-	background: #E1EBFB;
-	border:0;
-	border-top:0px solid #d3d3d3;
-	border-bottom:0px solid #d3d3d3;
-	width:5px;
-}
-.soria .dijitSplitterV .dijitSplitterThumb {
-	background:#B0B0B0 none;
-	height:19px;
-	left:2px;
-	width:1px;
-}
-.soria .dijitSplitterActive {
-	font-size: 1px;
-	background-image: none;
-	background-color: #aaa;
-	-moz-opacity: 0.6;
-	opacity: 0.6;
-	filter: Alpha(Opacity=60);
-	margin: 0;
-}
-.soria .dijitInputField INPUT,
-.soria .dijitTextBox,
-.soria .dijitComboBox,
-.soria .dijitSpinner {
-	margin: 0em 0.1em;
-}
-.soria .dijitTextBox,
-.soria .dijitComboBox,
-.soria .dijitSpinner,
-.soria .dijitInlineEditor input,
-.soria .dijitTextArea {
-	
-	background:#fff url(images/validationInputBg.png) repeat-x top left;
-	border:1px solid #8ba0bd;
-	line-height: normal;
-}
-.dj_ie6 .soria .dijitTextBox,
-.dj_ie6 .soria .dijitComboBox,
-.dj_ie6 .soria .dijitSpinner,
-.dj_ie6 .soria .dijitInlineEditor input,
-.dj_ie6 .soria .dijitTextArea {
-	background:#fff url(images/validationInputBg.gif) repeat-x top left;
-}
-.soria .dijitComboBox .dijitButtonNode {
-	padding: 0 0.2em;
-}
-.soria .dijitComboBox .dijitButtonNode,
-.soria .dijitSpinner .dijitButtonNode {
-	
-	border-color: #8ba0bd;
-	border-left: 1px solid #8ba0bd;
-}
-.soria .dijitTextBoxFocused,
-.soria .dijitComboBoxFocused,
-.soria .dijitSpinnerFocused, .soria .dijitSpinnerUpArrowActive, .soria .dijitSpinnerDownArrowActive,
-.soria .dijitTextAreaFocused {
-	
-	border-color:#406b9b;
-}
-.soria .dijitComboBoxFocused .dijitButtonNode,
-.soria .dijitSpinnerFocused .dijitButtonNode,
-.soria .dijitSpinnerUpArrowActive .dijitButtonNode,
-.soria .dijitSpinnerDownArrowActive .dijitButtonNode {
-	border-left-color:#8ba0bd;
-}
-.soria .dijitSpinnerFocused .dijitDownArrowButton,
-.soria .dijitSpinnerUpArrowActive .dijitDownArrowButton,
-.soria .dijitSpinnerDownArrowActive .dijitDownArrowButton {
-	border-top-color:#8ba0bd;
-}
-.soria .dijitError {
-	border-color:#f3d118;
-	background-color:#f9f7ba;
-	background-image:none;
-}
-.dj_ie6 .soria .dijitError INPUT {
-	
-	background-color:#f9f7ba !important;
-}
-.soria .dijitErrorFocused {
-	background-color:#ff6;
-	background-image:none;
-}
-.dj_ie6 .soria .dijitErrorFocused INPUT {
-	
-	background-color:#ff6 !important;
-}
-.soria .dijitValidationIcon {
-	
-	width: 16px;
-	background: transparent url(images/warning.png) no-repeat center center;
-}
-.soria .dijitComboBoxHighlightMatch {
-	background-color:#f9f7ba;
-}
-.soria .dijitButtonNode {
-	
-	
-	border: 1px solid #8ba0bd;
-	border-bottom:1px solid #657c9c;
-	padding: 0.1em 0.2em 0.2em 0.2em;
-	background: #bcd5f0 url(images/buttonEnabled.png) repeat-x top left;
-}
-.soria .dijitSelect .dijitButtonContents {
-	border-right: none;
-}
-.soria .dijitButtonNode button {
-	border: 0px;
-	background-color: transparent;
-}
-.soria .dijitButtonText {
-	text-align: center;
-	padding: 0 0.3em;
-}
-.soria .dijitComboBox .dijitButtonNode {
-	border-width: 0px 0px 0px 1px;
-}
-.soria .dijitArrowButton {
-	color: #111;
-}
-.soria .dijitComboButton .dijitDownArrowButton {
-	padding-right:4px;
-}
-.soria .dijitComboBoxReadOnly,
-.soria .dijitSpinnerReadOnly,
-.soria .dijitSpinnerReadOnly .dijitButtonNode,
-.soria .dijitButtonDisabled .dijitButtonNode,
-.soria .dijitToggleButtonDisabled .dijitButtonNode,
-.soria .dijitDropDownButtonDisabled .dijitButtonNode,
-.soria .dijitComboButtonDisabled .dijitButtonNode,
-.soria .dijitComboBoxDisabled,
-.soria .dijitSpinnerDisabled,
-.soria .dijitSpinnerDisabled .dijitButtonNode {
-	
-	border-color: #b9bbdd #b9bbdd #b9bbdd #b9bbdd;
-	background:#c3d3e5 url(images/buttonDisabled.png) top repeat-x;
-	opacity: 0.60;
-}
-.dj_ie6 .soria .dijitComboButtonDisabled .dijitButtonText {
-	
-	color: #aaa;
-}
-.soria .dijitButtonHover .dijitButtonNode,
-.soria .dijitButtonNodeHover,
-.soria .dijitToggleButtonHover .dijitButtonNode,
-.soria .dijitDropDownButtonHover .dijitButtonNode,
-.soria .dijitComboButtonHover .dijitButtonContents,
-.soria .dijitComboButtonDownArrowHover .dijitDownArrowButton,
-.soria .dijitComboBoxHover .dijitDownArrowButton,
-.soria .dijitSpinnerUpArrowHover .dijitUpArrowButton,
-.soria .dijitSpinnerDownArrowHover .dijitDownArrowButton {
-	
-	
-	color:#243C5F;
-	background:#acc5e2 url(images/buttonHover.png) repeat-x top left;
-}
-.soria .dijitButtonActive .dijitButtonNode,
-.soria .dijitToggleButtonActive .dijitButtonNode,
-.soria .dijitDropDownButtonActive .dijitButtonNode,
-.soria .dijitComboButtonActive .dijitButtonContents,
-.soria .dijitStackController .dijitToggleButtonChecked .dijitButtonNode {
-	
-	border-color:#657c9c;
-	background: #91b4e5 url(images/buttonActive.png) top left repeat-x;
-}
-.soria .dijitSpinnerUpArrowActive .dijitUpArrowButton,
-.soria .dijitSpinnerDownArrowActive .dijitDownArrowButton,
-.soria .dijitComboBoxActive .dijitDownArrowButton {
-	
-	background: #91b4e5 url(images/buttonActive.png) top left repeat-x;
-}
-.soria .dijitArrowButtonInner {
-	background-image: url(images/spriteArrows.png);
-	background-repeat: no-repeat;
-	background-position: 0px top;
-	width: 11px;
-}
-.soria .dijitLeftArrowButton .dijitArrowButtonInner {
-	background-position: -11px top;
-}
-.soria .dijitUpArrowButton .dijitArrowButtonInner {
-	background-position: -22px top;
-}
-.soria .dijitRightArrowButton .dijitArrowButtonInner {
-	background-position: -33px top;
-}
-.dj_ie6 .soria .dijitArrowButtonInner {
-	background-image: url(images/spriteArrows.gif);
-}
-.soria .dijitComboBox .dijitArrowButton .dijitArrowButtonInner {
-	background:url(images/spriteArrows.png) no-repeat left center;
-	width: 11px;
-}
-.dj_ie6 .soria .dijitComboBox .dijitArrowButton .dijitArrowButtonInner {
-	background:url(images/spriteArrows.gif) no-repeat left center;
-}
-.soria .dijitComboBoxHover .dijitArrowButtonInner {
-	
-}
-.soria .dijitToggleButton .dijitCheckBox,
-.soria .dijitToggleButton .dijitCheckBoxIcon {
-	background-image: url(images/spriteCheckbox.gif);
-}
-.soria .dijitCheckBox,
-.soria .dijitCheckBoxIcon {		
-	background-image: url(images/spriteCheckbox.gif); 
-	background-repeat: no-repeat;
-	width: 16px;
-	height: 16px;
-	margin: 0;
-	padding: 0;
-}
-.soria .dijitCheckBox,
-.soria .dijitToggleButton .dijitCheckBoxIcon {
-	
-	background-position: -16px;
-}
-.soria .dijitCheckBoxChecked,
-.soria .dijitToggleButtonChecked .dijitCheckBoxIcon {
-	
-	background-position: 0px;
-}
-.soria .dijitCheckBoxDisabled {
-	
-	background-position: -48px;
-}
-.soria .dijitCheckBoxCheckedDisabled {
-	
-	background-position: -32px;
-}
-.soria .dijitCheckBoxHover {
-	
-	background-position: -80px;
-}
-.soria .dijitCheckBoxCheckedHover {
-	
-	background-position: -64px;
-}
-.soria .dijitToggleButton .dijitRadio,
-.soria .dijitToggleButton .dijitRadioIcon {
-	background-image: url(images/spriteRadio.gif);
-}
-.soria .dijitRadio,
-.soria .dijitRadioIcon	{		
-	background-image: url(images/spriteRadio.gif); 
-	background-repeat: no-repeat;
-	width: 16px;
-	height: 16px;
-	margin: 0;
-	padding: 0;
-}
-.soria .dijitRadio,
-.soria .dijitToggleButton .dijitRadioIcon {
-	
-	background-position: -16px;
-}
-.soria .dijitRadioChecked,
-.soria .dijitToggleButtonChecked .dijitRadioIcon {
-	
-	background-position: 0px;
-}
-.soria .dijitRadioDisabled {
-	
-	background-position: -48px;
-}
-.soria .dijitRadioCheckedDisabled {
-	
-	background-position: -32px;
-}
-.soria .dijitRadioHover {
-	
-	background-position: -80px;
-}
-.soria .dijitRadioCheckedHover {
-	
-	background-position: -64px;
-}
-.soria .dijitSliderProgressBarH {
-	border-color: #b1badf;
-	background: #c0c2c5 url(images/sliderFull.png) repeat-x top left;
-}
-.soria .dijitSliderProgressBarV {
-	border-color: #b1badf;
-	background: #c0c2c5 url(images/sliderFullVertical.png) repeat-y bottom left;
-}
-.soria .dijitSliderFocused .dijitSliderProgressBarH,
-.soria .dijitSliderFocused .dijitSliderLeftBumper {
-	background-image:url(images/sliderFullFocus.png);
-}
-.soria .dijitSliderFocused .dijitSliderProgressBarV,
-.soria .dijitSliderFocused .dijitSliderBottomBumper {
-	background-image:url(images/sliderFullVerticalFocus.png);
-}
-.soria .dijitSliderRemainingBarV {
-	border-color: #b4b4b4;
-	background: #dcdcdc url(images/sliderEmptyVertical.png) repeat-y bottom left;
-}
-.soria .dijitSliderRemainingBarH {
-	border-color: #b4b4b4;
-	background: #dcdcdc url(images/sliderEmpty.png) repeat-x top left;
-}
-.soria .dijitSliderBar {
-	border-style: solid;
-	outline:1px;
-	
-}
-.soria .dijitSliderFocused .dijitSliderBar {
-	border-color:#8ba0bd;
-}
-.dijit_a11y .dijitSliderProgressBar {
-	background-color:#333 !important;
-}
-.soria .dijitSliderImageHandleH {
-	border:0px;
-	width:15px;
-	height:18px;
-	background:url(images/preciseSliderThumb.png) no-repeat center top;
-	cursor:pointer;
-}
-.soria .dijitSliderFocused .dijitSliderImageHandleH {
-	background-image:url(images/preciseSliderThumbFocus.png);
-	#background-image:url(images/preciseSliderThumbFocus.gif);
-}
-.dj_ie6 .soria .dijitSliderImageHandleH {
-	background-image:url(images/preciseSliderThumb.gif);
-}
-.soria .dijitSliderLeftBumper {
-	border-left-width: 1px;
-	border-color: #aab0bb;
-	background: #c0c2c5 url(images/sliderFull.png) repeat-x top left;
-}
-.soria .dijitSliderRightBumper {
-	background: #dcdcdc url(images/sliderEmpty.png) repeat-x top left;
-	border-color: #b4b4b4;
-	border-right-width: 1px;
-}
-.soria .dijitSliderImageHandleV {
-	border:0px;
-	width:20px;
-	height:15px;
-	background:url(images/sliderThumb.png) no-repeat center center;
-	#background:url(images/sliderThumb.gif) no-repeat center center;
-	cursor:pointer;
-}
-.soria .dijitSliderFocused .dijitSliderImageHandleV {
-	background-image:url(images/sliderThumbFocus.png);
-	#background-image:url(images/sliderThumbFocus.gif);
-}
-.soria .dijitSliderBottomBumper {
-	border-bottom-width: 1px;
-	border-color: #aab0bb;
-	background: #c0c2c5 url(images/sliderFullVertical.png) repeat-y bottom left;
-}
-.soria .dijitSliderTopBumper {
-	background: #dcdcdc url(images/sliderEmptyVertical.png) repeat-y top left;
-	border-color: #b4b4b4;
-	border-top-width: 1px;
-}
-.soria .dijitSliderIncrementIconH,
-.soria .dijitSliderIncrementIconV {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat -45px top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat -45px top;
-	width:15px; height:15px;
-	cursor:pointer;
-}
-.soria .dijitSliderIncrementIconH {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat -30px top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat -30px top;
-}
-.soria .dijitSliderDecrementIconH,
-.soria .dijitSliderDecrementIconV {
-	width:15px;
-	height:15px;
-	cursor:pointer;
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat -15px top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat -15px top;
-}
-.soria .dijitSliderDecrementIconH {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat 0px top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat 0px top;
-}
-.soria .dijitSliderButtonInner {
-	visibility:hidden;
-}
-.soria .dijitSliderReadOnly *,
-.soria .dijitSliderDisabled * {
-	border-color: #d5d5d5 #bdbdbd #bdbdbd #d5d5d5;
-	color: #bdbdbd;
-}
-.soria .dijitSliderReadOnly .dijitSliderDecrementIconH,
-.soria .dijitSliderDisabled .dijitSliderDecrementIconH {
-	background-position: 0px -15px;
-}
-.soria .dijitSliderReadOnly .dijitSliderIncrementIconH,
-.soria .dijitSliderDisabled .dijitSliderIncrementIconH {
-	background-position: -30px -15px;
-}
-.soria .dijitSliderReadOnly .dijitSliderDecrementIconV,
-.soria .dijitSliderDisabled .dijitSliderDecrementIconV {
-	background-position: -15px -15px;
-}
-.soria .dijitSliderReadOnly .dijitSliderIncrementIconV,
-.soria .dijitSliderDisabled .dijitSliderIncrementIconV {
-	background-position: -45px -15px;
-}
-.soria .dijitSelectDisabled * {
-    cursor: not-allowed !important;
-}
-.soria .dijitSelectReadOnly * {
-    cursor: default !important;
-}
-.soria .dijitSelect .dijitButtonNode {
-	padding: 0px;
-}
-.soria .dijitSelect .dijitButtonContents {
-	padding-top: 1px;
-    background:#fff url(images/validationInputBg.png) repeat-x top left;
-    #background:#fff url(images/validationInputBg.gif) repeat-x top left;
-}
-.soria .dijitSelectHover .dijitButtonContents,
-.soria .dijitSelectActive .dijitButtonContents,
-.soria .dijitSelectOpened .dijitButtonContents,
-.soria .dijitSelectDisabled .dijitButtonContents,
-.soria .dijitSelectReadOnly .dijitButtonContents{
-	background: transparent none;
-}
-.dj_ie .soria .dijitSelect .dijitButtonContents {
-	padding-top: 0px;
-}
-.soria .dijitSelectDisabled .dijitButtonNode {
-    border-color: #b9bbdd #b9bbdd #b9bbdd #b9bbdd;
-    background:#c3d3e5 url(images/buttonDisabled.png) top repeat-x;
-}
-.dj_ie .soria .dijitSelectDisabled  .dijitButtonNode * {
-	filter: gray() alpha(opacity=50);
-}
-.soria .dijitSelectHover .dijitButtonNode {
-    color:#000;
-    background:#acc5e2 url(images/buttonHover.png) repeat-x top left;
-}
-.soria .dijitSelectActive .dijitButtonNode,
-.soria .dijitSelectOpened .dijitButtonNode {
-    border-color:#657c9c;
-    background: #91b4e5 url(images/buttonActive.png) top left repeat-x;
-}
-.soria .dijitSelectMenu td {
-	padding: 0em;
-}
-.soria .dijitSelectMenu .dijitMenuItemIcon {
-	margin: 0.1em 0.2em;
-	display: none;
-}
-.soria .dijitSelectMenu .dijitMenuItemLabel,
-.soria .dijitSelectMenu .dijitMenuArrowCell {
-	padding: 0.1em 0.2em;
-}
-.soria .dijitTreeNode {
-    background : url(images/treeI.gif) no-repeat;
-    background-position : top left;
-    background-repeat : repeat-y;
-    zoom: 1;	
-}
-.soria .dijitTreeNodeHover {
-	
-	background-image: url(images/treeHover.png);
-	background-repeat: repeat;
-	background-color: none !important;
-}
-.soria .dijitTreeIsLast {
-    background: url(images/treeI_half.gif) no-repeat;
-}
-.soria .dijitTreeLabel {
-	font-weight: normal;
-	margin-left: 3px;
-}
-.soria .dijitTreeIsRoot {
-    margin-left: 0;
-    background-image: none;
-}
-.soria .dijitTreeExpando {
-    width: 18px;
-    height: 18px;
-}
-.soria .dijitTreeRow {
-	
-	padding-bottom: 2px;
-}
-.soria .dijitTreeContent {
-    min-height: 18px;
-    min-width: 18px;
-    padding-left:1px;
-}
-.soria .dijitTreeExpand {
-    width: 18px;
-    height: 18px;
-    background-repeat : no-repeat;
-}
-.soria .dijitTreeNodeEmphasized {
-    background-color: Highlight;
-    color: HighlightText;
-}
-.soria .dijitTreeLabelFocused {
-	outline: 1px invert dotted;
-}
-.soria .dijitTreeNodeSelected .dijitTreeLabel{
-	background:#b8cbec;
-}
-.soria .dijitTreeExpandoOpened {
-	background: url(images/spriteTree.gif) no-repeat -18px top;
-}
-.soria .dijitTreeExpandoClosed {
-	background-image: url(images/spriteTree.gif);
-}
-.soria .dijitTreeExpandoLeaf {
-	background: url(images/spriteTree.gif) no-repeat -36px top;
-}
-.soria .dijitTreeExpandoLoading {
-	background-image: url(images/treeExpand_loading.gif);
-}
-.soria .dijitTreeIcon {
-	width: 16px;
-	height: 16px;
-}
-.soria .dijitFolderOpened {
-	background: url(images/spriteDivIcons.gif) no-repeat -16px top;
-}
-.soria .dijitFolderClosed {
-	background: url(images/spriteDivIcons.gif) no-repeat top left;
-}
-.soria .dijitLeaf {
-	background: url(images/spriteDivIcons.gif) no-repeat -32px top;
-}
-.soria .dijitTreeNode .dojoDndItemBefore,
-.soria .dijitTreeNode .dojoDndItemAfter {
-	border-bottom: none;
-	border-top: none;
-}
-.soria .dijitTreeNode .dojoDndItemBefore .dijitTreeContent {
-	
-	border-top: 2px solid #369;
-}
-.soria .dijitTreeNode .dojoDndItemAfter .dijitTreeContent {
-	
-	border-bottom: 2px solid #369;
-}
-.soria .dijitProgressBar {
-	margin:2px 0px 2px 0px;
-}
-.soria .dijitProgressBarEmpty{
-	
-	background:#fff url(images/progressBarEmpty.png) repeat-x center center;
-	border-color: #8ba0bd;
-}
-.soria .dijitProgressBarTile{
-	
-	background:#f0f0f0 url(images/progressBarFull.png) repeat-x center center;
-}
-.soria .dijitProgressBarFull {
-	border-right:1px solid #8ba0bd;
-}
-.soria .dijitProgressBarLabel {
-	
-	color:#293a4b;
-}
-.soria .dijitProgressBarIndeterminate .dijitProgressBarTile {
-	
-	background:#cad2de url(images/progressBarAnim.gif) repeat-x center center;
-}
-.soria .dijitTitlePaneTitle {
-	background: #cccccc;
-	background:#fff url(images/titleBar.png) repeat-x top left;
-	border:1px solid #bfbfbf;
-	padding:3px 4px;
-	font-size: 0.9em;
-	font-weight: bold;
-	color: #6d6d6d;
-}
-.soria .dijitTitlePaneTitle-hover {
-	background: #f9f9f9 url(images/accordionItemActive.png) top repeat-x;
-	cursor: pointer;
-}
-.soria .dijitTitlePaneTitle * {
-	vertical-align: middle;
-}
-.soria .dijitTitlePane .dijitOpen .dijitArrowNode,
-.soria .dijitTitlePane .dijitClosed .dijitArrowNode {
-	width:15px;
-	height:15px;
-}
-.soria .dijitTitlePaneFocused .dijitTitlePaneTextNode {
-	color: #243C5F;
-}
-.soria .dijitOpen .dijitTitlePaneTextNode,
-.soria .dijitFixedOpen .dijitTitlePaneTextNode {
-	color: #243C5F;
-}
-.soria .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background: url(images/spriteRoundedIconsSmall.png) no-repeat -30px top;
-}
-.dj_ie6 .soria .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background:url(images/spriteRoundedIconsSmall.gif) no-repeat -30px top;
-}
-.soria .dijitTitlePane .dijitOpen .dijitArrowNode {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat -15px top;
-}
-.dj_ie6 .soria .dijitTitlePane .dijitOpen .dijitArrowNode {
-	background:url(images/spriteRoundedIconsSmall.gif) no-repeat -15px top;
-}
-.soria .dijitTitlePane .dijitArrowNodeInner {
-	display:none;
-}
-.dijit_a11y .dijitTitlePane .dijitOpen .dijitArrowNodeInner,
-.dijit_a11y .dijitTitlePane .dijitClosed .dijitArrowNodeInner {
-	display:inline !important;
-	font-family:monospace;
-	padding-bottom:.2em;
-}
-.dijit_a11y .dijitTitlePane .dijitArrowNode {
-	display:none;
-}
-.soria .dijitTitlePaneContentOuter {
-	background: #ffffff;
-	border:1px solid #bfbfbf;
-	border-top: 0px solid #3d3d3d;	
-}
-.soria .dijitTitlePaneContentInner {
-	padding:10px;
-}
-.dj_ie6 .soria .dijitTitlePaneContentOuter,
-.dj_ie6 .soria .dijitTitlePane .dijitTitlePaneTitle {
-	zoom: 1;
-}
-.soria .dijitTitlePaneTextNode {
-	margin-left: 4px;
-	margin-right: 4px;
-}
-.soria .dijitCalendarIncrementControl {
-	
-	width:15px;
-	height:15px;
-	background-image: url(images/spriteRoundedIconsSmall.png);
-	background-repeat: no-repeat;
-}
-.dj_ie6 .soria .dijitCalendarIncrementControl {
-	font-size:.1em;
-	background-image: url(images/spriteRoundedIconsSmall.gif);
-}
-.soria .dijitA11ySideArrow {
-	display: none;
-}
-.soria .dijitCalendarDecrease {
-	background-position: top left;
-}
-.soria .dijitCalendarIncrease {
-	background-position: -30px top;
-}
-.soria table.dijitCalendarContainer {
-	font-size: 100%;
-	border-spacing: 0;
-	border-collapse: separate;
-	border: 1px solid #b1badf;
-	margin: 0;
-}
-.soria .dijitCalendarMonthContainer th {
-	
-	background:#bed7f0 url(images/titleBar.png) repeat-x top;
-	padding-top:.3em;
-	padding-bottom:.2em;
-	text-align:center;
-}
-.dj_ie6 .soria .dijitCalendarMonthContainer th {
-	padding-top:.2em;
-	padding-bottom:.1em;
-}
-.soria .dijitCalendarDayLabelTemplate {
-	
-	background:#bed7f0;
-	font-weight:normal;
-	padding-top:.15em;
-	padding-bottom:.2em;
-	border-bottom: 1px solid #b1badf;
-	color:#293a4b;
-	text-align:center;
-}
-.soria .dijitCalendarBodyContainer {
-	border-bottom: 1px solid #eeeeee;
-}
-.soria .dijitCalendarMonthLabel {
-	color:#293a4b;
-	font-weight: bold;
-}
-.soria .dijitCalendarDateTemplate {
-	
-	font-size: 0.9em;
-	font-weight: bold;
-	text-align: center;
-	padding: 0.3em 0.3em 0.05em 0.3em;
-	letter-spacing: 1px;
-	background-color: #fff;
-	border:#fff solid 1px !important;
-}
-.dj_ie .soria .dijitCalendarDateTemplate {
-	padding: 0.1em .33em 0.02em .33em;
-}
-.soria .dijitCalendarPreviousMonth,
-.soria .dijitCalendarNextMonth 		{
-	
-	color:#999999;
-	background-color:#fdfdfd !important;
-	border:#fdfdfd solid 1px !important;
-}
-.soria .dijitCalendarPreviousMonthDisabled,
-.soria .dijitCalendarNextMonthDisabled	{
-	
-	background-color:#a4a5a6 !important;
-}
-.soria .dijitCalendarCurrentMonth {
-	
-}
-.soria .dijitCalendarCurrentMonthDisabled {
-	
-	background-color:#bbbbbc !important;
-}
-.soria .dijitCalendarDisabledDate {
-	
-	
-	text-decoration:line-through !important;
-	cursor:default !important;
-}
-.soria .dijitCalendarCurrentDate {
-	
-	text-decoration:underline;
-	font-weight:bold;
-}
-.soria .dijitCalendarSelectedDate {
-	
-	background-color:#b9cbf1 !important;
-	color:black !important;
-	border:#4b5aaa solid 1px !important;
-}
-.soria .dijitCalendarYearContainer {
-	
-	background:white url(images/titleBar.png) repeat-x top;
-}
-.soria .dijitCalendarYearLabel {
-	
-	margin:0;
-	padding:0.4em 0 0.25em 0;
-	text-align:center;
-}
-.soria .dijitCalendarSelectedYear {
-	
-	color:black;
-	padding:0.2em;
-	padding-bottom:0.1em;
-	background-color:#b9cbf1 !important;
-	border:#4b5aaa solid 1px !important;
-}
-.soria .dijitCalendarNextYear,
-.soria .dijitCalendarPreviousYear {
-	
-	color:black !important;
-	font-weight:normal;
-}
-.soria .dijitTimePickerTick,
-.soria .dijitTimePickerMarker {
-	border-color: #b1badf;
-}
-.soria .dijitTimePickerTick {
-	color:white;
-}
-.soria .dijitTimePickerMarker {
-	background:#bed7f0 url(images/titleBar.png) repeat-x top;
-	color:#293a4b;
-	font-weight: bold;
-}
-.soria .dijitTimePickerItemSelected {
-	color: black;
-	background: #b9cbf1 none;
-}
-.soria .dijitTimePickerItemHover {
-	background: #60a1ea none;
-	color:white;
-}
-.soria .dijitTimePickerItemHover,
-.soria .dijitTimePickerItemSelected {
-	position: relative;
-	z-index: 10;
-}
-.soria .dijitTimePickerTick .dijitTimePickerItemInner {
-	font-size:0.4em;
-}
-.soria .dijitTimePickerItemHover .dijitTimePickerItemInner,
-.soria .dijitTimePickerItemSelected .dijitTimePickerItemInner {
-	font-size:1em;
-}
-.soria .dijitTimePickerMarkerHover {
-	border-top: 1px solid #94b9ef;
-}
-.soria .dijitTimePickerTickHover,
-.soria .dijitTimePickerTickSelected {
-	margin-top:-0.3em;
-	margin-bottom:-0.3em;
-	border-bottom: none;
-}
-.dijit_a11y .dijitTimePickerTickHover {
-	background-color: #CCC !important;
-	border-top: 1px solid #333 !important;
-	border-bottom: 1px solid #333 !important;
-}
-.dijit_a11y .dijitTimePickerMarkerHover {
-	border-bottom-width: 2px;
-}
-.soria .dijitToolbar {
-	border-bottom: 1px solid #ccc;
-	background:#eaeaea url(images/titleBar.png) repeat-x top left;
-}
-.dj_ie6 .soria .dijitToolbar {
-	height: 10px;
-}
-.soria .dijitToolbar .dijitButtonNode,
-.soria .dijitToolbar .dijitComboButton .dijitButtonContents,
-.soria .dijitToolbar .dijitComboButton .dijitDownArrowButton {
-	background: none;
-	margin: 0px;
-	padding: 0px;
-	border: none;
-	font-size: 12px;
-}
-.soria .dijitToolbar .dijitButton,
-.soria .dijitToolbar .dijitToggleButton,
-.soria .dijitToolbar .dijitDropDownButton,
-.soria .dijitToolbar .dijitComboButton .dijitButtonContents,
-.soria .dijitToolbar .dijitComboButton .dijitDownArrowButton {
-	background: none;
-	padding: 1px;	
-}
-.soria .dijitToolbar .dijitButtonChecked,
-.soria .dijitToolbar .dijitToggleButtonChecked {
-	background-color:#d8e5f8;
-	border:1px solid #316ac5;
-	padding: 0px;
-}
-.soria .dijitToolbar .dijitButtonCheckedHover,
-.soria .dijitToolbar .dijitToggleButtonCheckedHover
- {
-	background-color:#9abbea;
-	border:1px solid #316ac5;
-	padding: 0px;
-}
-.soria .dijitToolbar .dijitButtonHover,
-.soria .dijitToolbar .dijitToggleButtonHover,
-.soria .dijitToolbar .dijitDropDownButtonHover,
-.soria .dijitToolbar .dijitComboButtonHover .dijitButtonContents,
-.soria .dijitToolbar .dijitComboButtonDownArrowHover .dijitDownArrowButton {
-	
-	border: 1px solid #316ac5;
-	padding: 0px;
-	background-color:#9abbea;
-}
-.soria .dijitToolbar label {
-	padding: 3px 3px 0 6px;
-}
-.dj_ie .soria .dijitToolbar .dijitComboButton .dijitButtonContentsFocused,
-.dj_ie .soria .dijitToolbar .dijitComboButton .dijitDownArrowButtonFocused {
-	
-	border: 1px #777 dotted !important;
-	padding: 0px;
-}
-.soria .dijitDialog {
-	background: #eee;
-	border: 1px solid #cbcbcb;
-	-webkit-box-shadow: 0px 5px 10px #adadad;
-	padding: 0px;
-}
-.soria .dijitDialog .dijitDialogTitle {
-	
-	font-weight: bold;
-	padding: 0px 4px;
-	font-size: 0.9em;
-	color: #3243C5F;
-}
-.soria .dijitDialog .dijitDialogPaneContent {
-	background: #ffffff;
-	border:none;
-	border-top: 1px solid #b1badf; 
-	padding:10px;
-}
-.soria .dijitDialogTitleBar {
-	
-	background: #fafafa url(images/titleBar.png) repeat-x top left;
-	padding: 5px 6px 3px 6px;
-	cursor: move;
-	outline:0; 
-}
-.soria .dijitDialogCloseIcon {
-	
-	background-image: url(images/spriteRoundedIconsSmallBl.png);
-	background-repeat: no-repeat;
-	background-position: -60px 0px;
-	position: absolute;
-	vertical-align: middle;
-	right: 6px;
-	top: 4px;
-	height: 15px;
-	width: 15px;
-	cursor: pointer;
-}
-.dj_ie6 .soria .dijitDialogCloseIcon {
-	background-image: url(images/spriteRoundedIconsSmallBl.gif);
-}
-.soria .dijitDialogCloseIcon-hover {
-	background-position: -60px -15px;
-}
-.soria .dijitTooltip,
-.soria .dijitTooltipDialog {
-	
-	background: transparent;	
-}
-.dijitTooltipBelow {
-	
-	padding-top: 10px;
-}
-.dijitTooltipAbove {
-	
-	padding-bottom: 10px;
-}
-.soria .dijitTooltipContainer {
-	
-	background-color: #fff;
-	border:1px solid #cbcbcb;
-	padding:0.45em;
-}
-.soria .dijitTooltipConnector {
-	
-	border:0px;
-	z-index: 2;
-}
-.soria .dijitTooltipABRight .dijitTooltipConnector {
-	
-	left: auto !important;
-	right: 6px;
-}
-.soria .dijitTooltipBelow .dijitTooltipConnector {
-	
-	top: 0px;
-	left: 6px;
-	background:url(images/tooltipConnectorUp.png) no-repeat top left;
-	width:17px;
-	height:11px;
-}
-.dj_ie .soria .dijitTooltipBelow .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorUp.gif);
-}
-.soria .dijitTooltipAbove .dijitTooltipConnector {
-	
-	bottom: 0px;
-	left: 6px;
-	background:url(images/tooltipConnectorDown.png) no-repeat top left;
-	width:17px;
-	height:11px;
-}
-.dj_ie .soria .dijitTooltipAbove .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorDown.gif);
-}
-.dj_ie .soria .dijitTooltipAbove .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorDown.gif);
-}
-.dj_ie6 .soria .dijitTooltipAbove .dijitTooltipConnector {
-	bottom: -5px;
-}
-.soria .dijitTooltipLeft {
-	padding-right: 10px;
-}
-.dj_ie6 .soria .dijitTooltipLeft {
-	padding-left: 11px;
-}
-.soria .dijitTooltipLeft .dijitTooltipConnector {
-	
-	right: 0px;
-	bottom: 3px;
-	background:url(images/tooltipConnectorRight.png) no-repeat top left;
-	width:11px;
-	height:17px;
-}
-.dj_ie .soria .dijitTooltipLeft .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorRight.gif);
-}
-.soria .dijitTooltipRight {
-	padding-left: 10px;
-}
-.soria .dijitTooltipRight .dijitTooltipConnector {
-	
-	left: 0px;
-	bottom: 3px;
-	background:url(images/tooltipConnectorLeft.png) no-repeat top left;
-	width:11px;
-	height:17px;
-}
-.dj_ie .soria .dijitTooltipRight .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorLeft.gif);
-}
-.soria .dijitMenu,
-.soria .dijitMenuBar {
-	border: 1px solid #cbcbcb;
-	margin: 0px;
-	padding: 0px;
-	background-color: #fff;
-}
-.soria .dijitBorderContainer .dijitMenuBar {
-	border:1px solid #B1BADF;
-}
-.soria .dijitMenuItem {
-	font-family: sans-serif;
-	margin: 0px;
-	color: #243C5F;
-}
-.soria .dijitMenuBar .dijitMenuItem {
-	padding: 4px 5px;
-}
-.soria .dijitMenuPreviousButton, .soria .dijitMenuNextButton {
-	font-style: italic;
-}
-.soria .dijitMenuItem TD {
-	padding:1px;
-}
-.soria .dijitMenuPassive .dijitMenuItemHover,
-.soria .dijitMenuItemSelected {
-	background-color: #d9e6f9; 
-	color: #243C5F;
-}
-.soria .dijitMenuItemIcon {
-	width: 15px;
-	height: 15px;
-}
-.soria .dijitMenuExpand {
-	width:15px;
-	height:15px;
-	background-image: url(images/spriteRoundedIconsSmall.png);
-	background-position: -30px top;
-}
-.dj_ie6 .soria .dijitMenuExpand {
-	background-image: url(images/spriteRoundedIconsSmall.gif);
-}
-.soria .dijitMenuSeparator {
-	height: 1px;
-}
-.soria .dijitMenuSeparatorTop {
-	border-bottom: 1px solid #fff; 
-}
-.soria .dijitMenuSeparatorBottom {
-	border-top: 1px solid #8ba0bd;
-}
-.soria .dijitCheckedMenuItemIconChar {
-	display: none;
-}
-.soria .dijitCheckedMenuItemIcon {
-	background-image: url(images/spriteCheckbox.gif);
-	background-position: -80px;
-}
-.soria .dijitCheckedMenuItemChecked .dijitCheckedMenuItemIcon {
-	background-position: -64px;
-}
-.dijitIEFixedToolbar {
-	position:absolute;
-	
-	top: expression(eval((document.documentElement||document.body).scrollTop));
-}
-.soria .dijitToolbar .dijitToolbarSeparator {
-	background: url(images/editor.gif);
-}
-.soria .dijitEditorIcon {
-	background-image: url(images/editor.gif); 
-	background-repeat: no-repeat;
-	width: 18px;
-	height: 18px;
-	text-align: center;
-}
-.soria .dijitDisabled .dijitEditorIcon {
-	background-image: url(images/editorDisabled.gif); 
-}
-.soria .dijitEditorIconSep { background-position: 0px; }
-.soria .dijitEditorIconBackColor { background-position: -18px; }
-.soria .dijitEditorIconBold { background-position: -36px; }
-.soria .dijitEditorIconCancel { background-position: -54px; }
-.soria .dijitEditorIconCopy { background-position: -72px; }
-.soria .dijitEditorIconCreateLink { background-position: -90px; }
-.soria .dijitEditorIconCut { background-position: -108px; }
-.soria .dijitEditorIconDelete { background-position: -126px; }
-.soria .dijitEditorIconForeColor { background-position: -144px; }
-.soria .dijitEditorIconHiliteColor { background-position: -162px; }
-.soria .dijitEditorIconIndent { background-position: -180px; }
-.soria .dijitEditorIconInsertHorizontalRule { background-position: -198px; }
-.soria .dijitEditorIconInsertImage { background-position: -216px; }
-.soria .dijitEditorIconInsertOrderedList { background-position: -234px; }
-.soria .dijitEditorIconInsertTable { background-position: -252px; }
-.soria .dijitEditorIconInsertUnorderedList { background-position: -270px; }
-.soria .dijitEditorIconItalic { background-position: -288px; }
-.soria .dijitEditorIconJustifyCenter { background-position: -306px; }
-.soria .dijitEditorIconJustifyFull { background-position: -324px; }
-.soria .dijitEditorIconJustifyLeft { background-position: -342px; }
-.soria .dijitEditorIconJustifyRight { background-position: -360px; }
-.soria .dijitEditorIconLeftToRight { background-position: -378px; }
-.soria .dijitEditorIconListBulletIndent { background-position: -396px; }
-.soria .dijitEditorIconListBulletOutdent { background-position: -414px; }
-.soria .dijitEditorIconListNumIndent { background-position: -432px; }
-.soria .dijitEditorIconListNumOutdent { background-position: -450px; }
-.soria .dijitEditorIconOutdent { background-position: -468px; }
-.soria .dijitEditorIconPaste { background-position: -486px; }
-.soria .dijitEditorIconRedo { background-position: -504px; }
-.soria .dijitEditorIconRemoveFormat { background-position: -522px; }
-.soria .dijitEditorIconRightToLeft { background-position: -540px; }
-.soria .dijitEditorIconSave { background-position: -558px; }
-.soria .dijitEditorIconSpace { background-position: -576px; }
-.soria .dijitEditorIconStrikethrough { background-position: -594px; }
-.soria .dijitEditorIconSubscript { background-position: -612px; }
-.soria .dijitEditorIconSuperscript { background-position: -630px; }
-.soria .dijitEditorIconUnderline { background-position: -648px; }
-.soria .dijitEditorIconUndo { background-position: -666px; }
-.soria .dijitEditorIconWikiword { background-position: -684px; }
-.soria .dijitEditorIconToggleDir { background-position: -540px; }
-.soria .dijitEditorIconTabIndent { background-position: -702px; }
-.soria .dijitEditorIconSelectAll { background-position: -720px; }
-.soria .dijitEditorIconUnlink { background-position: -738px; }
-.soria .dijitEditorIconFullScreen { background-position: -756px; }
-.soria .dijitEditorIconViewSource { background-position: -774px; }
-.soria .dijitEditorIconPrint { background-position: -792px; }
-.soria .dijitEditorIconNewPage { background-position: -810px; }
-.dijitColorPalette {
-	border:1px solid #cbcbcb;
-	background:#fff;
-	-moz-border-radius: 0px !important;
-}
+	NOTES:
+	---
+	Dialog.css contains css classes for both Dialog and Tooltip!
+	This because currently a dijit.TooltipDialog exist. Until this is resolved
+	you need to include Dialog.css for both dijits
+	---
+	Toolbar.css contains classes also used in Editor. Until this is resolved
+	you need to include Toolbar.css for both Toolbar and Editor
+	---
+	Button.css contains classes for combobox,
+
+*/
+
+ at import url("../dijit.css");
+ at import url("../../icons/commonIcons.css");/*sprite containing common icons to be used by all themes*/
+ at import url("Common.css");
+ at import url("layout/ContentPane.css");
+ at import url("layout/TabContainer.css");
+ at import url("layout/AccordionContainer.css");
+ at import url("layout/SplitContainer.css");
+ at import url("layout/BorderContainer.css");
+ at import url("form/Common.css");
+ at import url("form/Button.css");
+ at import url("form/Checkbox.css");
+ at import url("form/RadioButton.css");
+ at import url("form/Slider.css");
+ at import url("form/Select.css");
+ at import url("Tree.css");
+ at import url("ProgressBar.css");
+ at import url("TitlePane.css");
+ at import url("Calendar.css");
+ at import url("TimePicker.css");
+ at import url("Toolbar.css");
+ at import url("Dialog.css");
+ at import url("Menu.css");
+ at import url("Editor.css");
+ at import url("../../icons/editorIcons.css"); /* sprite for editor icons to be used by all themes */
+ at import url("ColorPalette.css");
\ No newline at end of file
diff --git a/dijit/themes/soria/soria_rtl.css b/dijit/themes/soria/soria_rtl.css
index c70b13b..b804011 100644
--- a/dijit/themes/soria/soria_rtl.css
+++ b/dijit/themes/soria/soria_rtl.css
@@ -1,214 +1,29 @@
+/*
+	Adds cosmetic styling to Dijit.  Users may swap with a custom theme CSS file.
 
-.dj_gecko-rtl .dijitInputField {
-	direction: ltr; 
-}
-.dj_gecko-rtl .dijitInputField * {
-	direction: rtl; 
-}
-.dijitRtl .dijitMenuItem {
-	text-align: right;
-}
-.dijitRtl .dijitComboBox .dijitInputField {
-	border-right-width:1px !important;
-	border-left-width:0 !important;
-}
-.dijitRtl .dijitCalendarNextYear {
-	margin:0 0.55em 0 0;
-}
-.dijitRtl .dijitCalendarPreviousYear {
-	margin:0 0 0 0.55em;
-}
-.dijitRtl .dijitProgressBarFull .dijitProgressBarLabel {
-	right:0; 
-}
-.dijitRtl .dijitSliderImageHandleV {
-	left:auto;
-	right:-6px;
-}
-.dj_ie-rtl .dijitSliderImageHandleV {
-	right:-10px;
-}
-.dijitRtl .dijitSliderMoveableH {
-	right:auto;
-	left:0;
-}
-.dijitRtl .dijitRuleContainerV {
-	float:right;
-}
-.dj_gecko-rtl .dijitRuleContainerV {
-	float:left;
-}
-.dj_ie-rtl .dijitRuleContainerV {
-	text-align:right;
-}
-.dj_ie-rtl .dijitRuleLabelV {
-	text-align:left;
-}
-.dj_ie-rtl .dijitRuleLabelH {
-	zoom:1;
-}
-.dj_ie-rtl .dijitSliderProgressBarH {
-	right:0;
-	left:auto;
-}
-.dj_gecko-rtl .dijitSliderProgressBarH {
-	float:right;
-	right:0;
-	left:auto;
-}
-.dijitRtl .dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	right: auto;
-	left: 0;
-	border-width: 0 1px 0 0 !important;
-}
-.dijitRtl .dijitSpinnerButtonContainer {
-	float: left;
-}
-.dijitRtl .dijit_a11y .dijitSpinnerButtonContainer {
-	margin-left: none;
-	margin-right: 2px;
-}
-.dijitRtl DIV.dijitArrowButton, .dijitRtl .dijitValidationIcon, .dijitRtl .dijitValidationIconText {
-	float: left;
-}
-.dijitRtl .dijitContentPaneLoading, .dijitRtl .dijitContentPaneError {
-	background-position:right;
-	padding-right:25px;
-}
-.dijitRtl .dijitTabContainer .tabStripMenuButton {
-	float: left;
-}
-.dj_iequirks-rtl .dijitComboButton BUTTON {
-        float:left;
-}
-.dijitRtl .soria .dijitTab {
-	margin-right:0;
-	margin-left:2px;		
-}
-.dijitRtl .soria .dijitTabContainer .tabStripButton {
-	margin-left: 0;
-}
-.dijitRtl .soria .dijitTabContainerTopStrip,
-.dijitRtl .soria .dijitTabContainerBottomStrip,
-.dijitRtl .soria .dijitTabContainerTop-tabs,
-.dijitRtl .soria .dijitTabContainerBottom-tabs {
-	padding-left: 0;
-	padding-right: 3px;
-}
-.dijitRtl .soria .dijitTabInnerDiv {
-	padding-left: 3px;
-	padding-right: 4px;
-}
-.dijitRtl .soria .dijitTabPaneWrapper {
-	#zoom: 1;
-}
-.dj_ie-rtl .soria .dijitTabContainerLeft-tabs {
-	margin-left: 0px !important;
-}
-.dj_ie-rtl .soria .dijitTabContainerRight-tabs {
-	margin-right: 0px !important;
-}
-.dijitRtl .soria .dijitTabContainerLeft-tabs .dijitTab,
-.dijitRtl .soria .dijitTabContainerRight-tabs .dijitTab {
-	margin-left:0px;
-}
-.dj_ie-rtl .soria .dijitTab .dijitTabInnerDiv{
-	width : 1%;
-}
-.dijitRtl .soria .dijitAccordionArrow {
-	background-position: 0px top;
-}
-.dijitRtl .soria .dijitAccordionTitle-selected .dijitAccordionArrow {
-	
-	background-position: -15px top;
-}
-.dijitRtl .soria .dijitSliderProgressBarH,
-.dijitRtl .soria .dijitSliderRemainingBarH,
-.dijitRtl .soria .dijitSliderLeftBumper,
-.dijitRtl .soria .dijitSliderRightBumper,
-.dijitRtl .soria .dijitSliderTopBumper {
-	background-position: top right;
-}
-.dijitRtl .soria .dijitSliderProgressBarV,
-.dijitRtl .soria .dijitSliderRemainingBarV,
-.dijitRtl .soria .dijitSliderBottomBumper {
-	background-position: bottom right;
-}
-.dijitRtl .soria .dijitSliderLeftBumper {
-	border-left-width: 0px;
-	border-right-width: 1px;
-}
-.dijitRtl .soria .dijitSliderRightBumper {
-	border-left-width: 1px;
-	border-right-width: 0px;
-}
-.dijitRtl .soria .dijitSliderIncrementIconH {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat left top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat left top;
-}
-.dijitRtl .soria .dijitSliderDecrementIconH {
-	background:url(images/spriteRoundedIconsSmall.png) no-repeat -30px top;
-	#background:url(images/spriteRoundedIconsSmall.gif) no-repeat -30px top;
-}
-.dijitRtl .soria .dijitComboBox .dijitButtonNode {
-	border-width: 0px 0px 0px 1px;
-}
-.dijitRtl .soria .dijitSelect .dijitButtonContents {
-	border-left: none;
-	border-right-width: 1px;
-}
-.dijitRtl .soria .dijitComboBox .dijitButtonNode,
-.dijitRtl .soria .dijitSpinner .dijitButtonNode {
-	
-	border-color: #8ba0bd;
-	border-left: 0px solid #8ba0bd;
-	border-right: 1px solid #8ba0bd;
-}
-.dijitRtl .soria .dijitTreeContainer .dijitTreeNode {
-    background-image : none;
-}
-.dijitRtl .soria .dijitTreeContainer .dijitTreeContent {
-    padding-left: auto;
-    padding-right: 1px;
-}
-.dijitRtl .soria .dijitTreeContainer .dijitTreeExpandoOpened {
-	background: url(images/spriteTree_rtl.gif) no-repeat -18px top;
-}
-.dijitRtl .soria .dijitTreeContainer .dijitTreeExpandoClosed {
-	background-image: url(images/spriteTree_rtl.gif);
-}
-.dijitRtl .soria .dijitTreeContainer .dijitTreeExpandoLeaf {
-	background: none;
-}
-.dijitRtl .soria .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background-position: 0px top;
-}
-.dj_ie6-rtl .soria .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background-position: 0px top;
-}
-.dijitRtl .soria .dijitCalendarDecrease {
-	background-position: -30px top;
-}
-.dijitRtl .soria .dijitCalendarIncrease {
-	background-position: 0px top;
-}
-.dijitRtl .soria .dijitDialogTitleBar .dijitDialogCloseIcon {
-	right: auto;
-	left: 5px;
-}
-.dijitRtl .soria .dijitMenuItem .dijitMenuItemIcon {
-	padding-left: 3px;
-	padding-right: 0px;
-}
-.dijitRtl .soria .dijitMenuItem .dijitMenuExpand {
-	background-position: left top;
-}
-.dijitRtl .soria .dijitEditorIcon {
-	background-image: url(images/editor_rtl.gif); 
-}
-.dijitRtl .soria .dijitDisabled .dijitEditorIcon {
-	background-image: url(images/editorDisabled_rtl.gif); 
-}
-.dijitRtl .soria .dijitToolbar .dijitToolbarSeparator {
-	background-image: url(images/editor_rtl.gif);
-}
+	NOTES:
+	---
+	Dialog.css contains css classes for both Dialog and Tooltip!
+	This because currently a dijit.TooltipDialog exist. Until this is resolved
+	you need to include Dialog.css for both dijits
+	---
+	Toolbar.css contains classes also used in Editor. Until this is resolved
+	you need to include Toolbar.css for both Toolbar and Editor
+	---
+	Button.css contains classes for combobox,
+
+*/
+
+ at import url("../dijit_rtl.css");
+ at import url("layout/TabContainer_rtl.css");
+ at import url("layout/AccordionContainer_rtl.css");
+ at import url("form/Slider_rtl.css");
+ at import url("form/Button_rtl.css");
+ at import url("Tree_rtl.css");
+ at import url("TitlePane_rtl.css");
+ at import url("Calendar_rtl.css");
+ at import url("TimePicker_rtl.css");
+ at import url("Dialog_rtl.css");
+ at import url("Menu_rtl.css");
+ at import url("Editor_rtl.css");
+ at import url("../../icons/editorIcons_rtl.css"); /*sprite for editor icons to be used by all themes*/
\ No newline at end of file
diff --git a/dijit/themes/themeTester.html b/dijit/themes/themeTester.html
new file mode 100644
index 0000000..b941691
--- /dev/null
+++ b/dijit/themes/themeTester.html
@@ -0,0 +1,1235 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit Theme Tester</title>
+
+	<!-- required: a default theme -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/claro/claro.css">
+
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "../tests/css/dijitTests.css";
+
+		html, body { height: 100%; width: 100%; padding: 0; border: 0; }
+		#main { height: 100%; width: 100%; border: 0; }
+		#header { margin: 0px; }
+		#leftAccordion { width: 25%; }
+		#bottomTabs { height: 40%; }
+
+		/* pre-loader specific stuff to prevent unsightly flash of unstyled content */
+		#loader {
+			padding:0;
+			margin:0;
+			position:absolute;
+			top:0; left:0;
+			width:100%; height:100%;
+			background:#ededed;
+			z-index:999;
+			vertical-align:middle;
+		}
+		#loaderInner {
+			padding:5px;
+			position:relative;
+			left:0;
+			top:0;
+			width:175px;
+			background:#3c3;
+			color:#fff;
+		}
+
+		hr.spacer { border:0; background-color:#ededed; width:80%; height:1px; }
+
+		/* rules used to test custom setting of TextBox padding */
+		.inputPadding0 .dijitInputField { padding: 0px !important; }
+		.inputPadding1 .dijitInputField { padding: 1px !important; }
+		.inputPadding2 .dijitInputField { padding: 2px !important; }
+		.inputPadding3 .dijitInputField { padding: 3px !important; }
+		.inputPadding4 .dijitInputField { padding: 4px !important; }
+		.inputPadding5 .dijitInputField { padding: 5px !important; }
+	</style>
+
+	<!-- a check for stray globals: not needed! -->
+	<script type="text/javascript">
+		window.__globalList = {dojo: true, dijit: true, dojox: true, djConfig: true};
+		for(var i in window){
+			window.__globalList[i] = true;
+		}
+	</script>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="parseOnLoad: false, isDebug: true"></script>
+
+	<!-- do not use: only for debugging / testing themes -->
+	<script type="text/javascript" src="../tests/_testCommon.js"></script>
+	<!--
+	<script type="text/javascript" src="http://prototypejs.org/assets/2007/10/16/prototype.js"></script>
+	-->
+	<script type="text/javascript" src="../dijit.js"></script>
+	<script type="text/javascript" src="../dijit-all.js" charset="utf-8"></script>
+
+
+	<script type="text/javascript"> // dojo.requires()
+
+		dojo.require("dijit.Menu");
+		dojo.require("dijit.MenuItem");
+		dojo.require("dijit.PopupMenuItem");
+
+		dojo.require("dijit.Calendar");
+		dojo.require("dijit.ColorPalette");
+		dojo.require("dijit.ProgressBar");
+		dojo.require("dijit.TitlePane");
+		dojo.require("dijit.Tooltip");
+		dojo.require("dijit.Tree");
+
+		dojo.require("dijit.MenuBar");
+		dojo.require("dijit.MenuBarItem");
+		dojo.require("dijit.PopupMenuBarItem");
+
+		// editor:
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.FontChoice");
+		dojo.require("dijit._editor.plugins.LinkDialog");
+
+		// dnd:
+		dojo.require("dojo.dnd.Source");
+
+		// various Form elements
+		dojo.require("dijit.form.CheckBox");
+		dojo.require("dijit.form.Textarea");
+		dojo.require("dijit.form.SimpleTextarea");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.DateTextBox");
+		dojo.require("dijit.form.TimeTextBox");
+		dojo.require("dijit.form.CurrencyTextBox");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.InlineEditBox");
+		dojo.require("dijit.form.NumberSpinner");
+
+		dojo.require("dijit.form.VerticalSlider");
+		dojo.require("dijit.form.VerticalRuleLabels");
+		dojo.require("dijit.form.VerticalRule");
+		dojo.require("dijit.form.HorizontalSlider");
+		dojo.require("dijit.form.HorizontalRuleLabels");
+		dojo.require("dijit.form.HorizontalRule");
+
+		// layouts used in page
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.LinkPane");
+		dojo.require("dijit.Dialog");
+
+		// scan page for widgets and instantiate them
+		dojo.require("dojo.parser");
+
+		// humm?
+		dojo.require("dojo.date.locale");
+
+		// for the Tree
+		dojo.require("dojo.data.ItemFileReadStore");
+
+		// for the colorpalette
+		function setColor(color){
+			var theSpan = dojo.byId("outputSpan");
+			dojo.style(theSpan,"color",color);
+			theSpan.innerHTML = color;
+		}
+
+		// for the calendar
+		function myHandler(id,newValue){
+			console.debug("onChange for id = " + id + ", value: " + newValue);
+		}
+
+		// current setting (if there is one) to override theme default padding on TextBox based widgets
+		currentInputPadding = "";
+
+		function setTextBoxPadding(){
+			// summary:
+			//		Handler for when a MenuItem is clicked to set non-default padding for
+			//		TextBox widgets
+
+			// Effectively ignore clicks on the  currently checked MenuItem
+			if(!this.get("checked")){
+				this.set("checked", true);
+			}
+
+			// val will be "theme default", "0px", "1px", ..., "5px"
+			var val = this.get("label");
+			
+			// Set class on body to get requested padding, and remove any previously set class
+			if(currentInputPadding){
+				dojo.removeClass(dojo.body(), currentInputPadding);
+				currentInputPadding = "";
+			}
+			if(val != "theme default"){
+				currentInputPadding = "inputPadding" + val.replace("px", "");
+				dojo.addClass(dojo.body(), currentInputPadding);
+			}
+
+			// Clear previously checked MenuItem (radio-button effect).
+			dojo.forEach(this.getParent().getChildren(), function(mi){
+				if(mi != this){
+					mi.set("checked", false);
+				}
+			}, this);
+		}
+
+		dojo.addOnLoad(function() {
+
+			var start = new Date().getTime();
+			dojo.parser.parse(dojo.byId('container'));
+			console.info("Total parse time: " + (new Date().getTime() - start) + "ms");
+
+			dojo.byId('loaderInner').innerHTML += " done.";
+			setTimeout(function hideLoader(){
+				var loader = dojo.byId('loader');
+				dojo.fadeOut({ node: loader, duration:500,
+					onEnd: function(){
+						loader.style.display = "none";
+					}
+				}).play();
+			}, 250);
+
+			logStrayGlobals();
+
+			// Fill in menu/links to get to other themes.		
+			// availableThemes[] is just a list of 'official' dijit themes, you can use ?theme=String
+			// for 'un-supported' themes, too. (eg: yours)
+			var availableThemes = [
+				{ theme:"claro", author:"Dojo", baseUri:"../themes/" },
+				{ theme:"tundra", author:"Dojo", baseUri:"../themes/" },
+				{ theme:"soria", author:"nikolai", baseUri:"../themes/" },
+				{ theme:"nihilo", author:"nikolai", baseUri:"../themes/" }
+			];
+
+			var tmpString='';
+			dojo.forEach(availableThemes,function(theme){
+				tmpString += 
+					'<a href="?theme='+theme.theme+'">'+theme.theme+'</'+'a> (' +
+					'<a href="?theme='+theme.theme+'&dir=rtl">RTL</'+'a> ' +
+					'<a href="?theme='+theme.theme+'&a11y=true">high-contrast</'+'a> ' +
+					'<a href="?theme='+theme.theme+'&dir=rtl&a11y=true">RTL+high-contrast</'+'a> )' +
+					' - by: '+theme.author+' <br>';
+				dijit.byId('themeMenu').addChild(new dijit.MenuItem({
+					label: theme.theme,
+					onClick: function(){ location.search = "?theme=" + theme.theme; }
+				}))
+			});
+			dojo.byId('themeData').innerHTML = tmpString;
+		});
+
+		function logStrayGlobals(){
+			// summary:
+			//		Print all the global variables that we've created [by mistake] inside of dojo
+			var strayGlobals = [];
+			for(var i in window){
+				if(!window.__globalList[i]){ strayGlobals.push(i); }
+			}
+			if(strayGlobals.length){
+				console.warn("Stray globals: "+strayGlobals.join(", "));
+			}
+		}
+
+		function logWidgets(){
+			// summary:
+			//		Print all the widgets to console
+			console.log("Widgets in registry:");
+			dijit.registry.forEach(function(w){
+				console.log(w);
+			});
+		}
+
+		function tearDown(){
+			// summary:
+			//		Destroy all widgets, top down, and then check for any orphaned widgets
+			dijit._destroyAll();
+			logWidgets();
+		}
+
+		dojo.addOnLoad(function(){
+			// It's the server's responsibility to localize the date displayed in the (non-edit) version of an InlineEditBox,
+			// but since we don't have a server we'll hack it in the client
+			dijit.byId("backgroundArea").set('value', dojo.date.locale.format(new Date(2005, 11, 30), { selector: 'date' }));
+
+			var nineAm = new Date(0);
+			nineAm.setHours(9);
+			dijit.byId("timePicker").set('value', dojo.date.locale.format(nineAm, { selector: 'time' }));
+		});
+
+		/***
+		dojo.addOnLoad(function(){
+			// use "before advice" to print log message each time resize is called on a layout widget
+			var origResize = dijit.layout._LayoutWidget.prototype.resize;
+			dijit.layout._LayoutWidget.prototype.resize = function(mb){
+				console.log(this + ": resize({w:"+ mb.w + ", h:" + mb.h + "})");
+				origResize.apply(this, arguments);
+			};
+
+			// content pane has no children so just use dojo's builtin after advice
+			dojo.connect(dijit.layout.ContentPane.prototype, "resize", function(mb){
+				console.log(this + ": resize({w:"+ mb.w + ", h:" + mb.h + "})");
+			});
+		});
+		***/
+	</script>
+</head>
+<body class="claro">
+	<!-- basic preloader: -->
+	<div id="loader"><div id="loaderInner" style="direction:ltr;">Loading themeTester ... </div></div>
+
+	<!-- data for tree and combobox -->
+	<div dojoType="dojo.data.ItemFileReadStore" jsId="continentStore"
+		url="../tests/_data/countries.json"></div>
+	<div dojoType="dojo.data.ItemFileReadStore" jsId="stateStore"
+		url="../tests/_data/states.json"></div>
+	<!-- contentMenu popup -->
+	<div dojoType="dijit.Menu" id="submenu1" contextMenuForWindow="true" style="display: none;">
+		<div dojoType="dijit.MenuItem" onClick="alert('Hello world');">Enabled Item</div>
+		<div dojoType="dijit.MenuItem" disabled="true">Disabled Item</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitIconCut"
+			onClick="alert('not actually cutting anything, just a test!')">Cut</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitIconCopy"
+			onClick="alert('not actually copying anything, just a test!')">Copy</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitIconPaste"
+			onClick="alert('not actually pasting anything, just a test!')">Paste</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Enabled Submenu</span>
+			<div dojoType="dijit.Menu" id="submenu2">
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</div>
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</div>
+				<div dojoType="dijit.PopupMenuItem">
+					<span>Deeper Submenu</span>
+					<div dojoType="dijit.Menu" id="submenu4">
+						<div dojoType="dijit.MenuItem" onClick="alert('Sub-submenu 1!')">Sub-sub-menu Item One</div>
+						<div dojoType="dijit.MenuItem" onClick="alert('Sub-submenu 2!')">Sub-sub-menu Item Two</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem" disabled="true">
+			<span>Disabled Submenu</span>
+			<div dojoType="dijit.Menu" id="submenu3" style="display: none;">
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</div>
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Different popup</span>
+			<div dojoType="dijit.ColorPalette"></div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Different popup</span>
+			<div dojoType="dijit.Calendar"></div>
+		</div>
+	</div>
+	<!-- end contextMenu -->
+
+	<div id="main" dojoType="dijit.layout.BorderContainer" liveSplitters="false" design="sidebar">
+
+		<div id="header" dojoType="dijit.MenuBar" region="top">
+			<div dojoType="dijit.PopupMenuBarItem" id="file">
+				<span>File</span>
+				<div dojoType="dijit.Menu" id="fileMenu">
+					<div dojoType="dijit.MenuItem" id="globals" onClick="logStrayGlobals();">Log globals</div>
+					<div dojoType="dijit.MenuItem" id="widgets" onClick="logWidgets();">Log widgets</div>
+					<div dojoType="dijit.MenuItem" id="destroy" iconClass="dijitIconDelete" onClick="tearDown();">Destroy All</div>
+				</div>
+			</div>
+			<div dojoType="dijit.PopupMenuBarItem" id="edit">
+				<span>Edit</span>
+				<div dojoType="dijit.Menu" id="editMenu">
+					<div dojoType="dijit.MenuItem" id="cut" iconClass="dijitIconCut"
+						onClick="console.log('not actually cutting anything, just a test!')">Cut</div>
+					<div dojoType="dijit.MenuItem" id="copy" iconClass="dijitIconCopy"
+						onClick="console.log('not actually copying anything, just a test!')">Copy</div>
+					<div dojoType="dijit.MenuItem" id="paste" iconClass="dijitIconPaste"
+						onClick="console.log('not actually pasting anything, just a test!')">Paste</div>
+					<div dojoType="dijit.MenuSeparator" id="separator"></div>
+					<div dojoType="dijit.MenuItem" id="undo" iconClass="dijitIconUndo">Undo</div>
+				</div>
+			</div>
+			<div dojoType="dijit.PopupMenuBarItem" id="view">
+				<span>View</span>
+				<div dojoType="dijit.Menu" id="viewMenu">
+					<div dojoType="dijit.MenuItem">Normal</div>
+					<div dojoType="dijit.MenuItem">Outline</div>
+					<div dojoType="dijit.PopupMenuItem">
+						<span>Zoom</span>
+						<div dojoType="dijit.Menu" id="zoomMenu">
+							<div dojoType="dijit.MenuItem">50%</div>
+							<div dojoType="dijit.MenuItem">75%</div>
+							<div dojoType="dijit.MenuItem">100%</div>
+							<div dojoType="dijit.MenuItem">150%</div>
+							<div dojoType="dijit.MenuItem">200%</div>
+						</div>
+					</div>
+				</div>
+			</div>
+			<div dojoType="dijit.PopupMenuBarItem" id="themes">
+				<span>Themes</span>
+				<div dojoType="dijit.Menu" id="themeMenu">
+				</div>
+			</div>
+			<div dojoType="dijit.PopupMenuBarItem" id="dialogs">
+				<span>Dialogs</span>
+				<div dojoType="dijit.Menu" id="dialogMenu">
+					<div dojoType="dijit.MenuItem">
+						<script type="dojo/method" event="onClick">
+							var dlg = dijit.byId('dialog1');
+							dlg.show();
+							// avoid (trying to) restore focus to a closed menu, go to MenuBar instead
+							dlg._savedFocus = dojo.byId("header");
+						</script>
+						slow loading
+					</div>
+					<div dojoType="dijit.MenuItem">
+						<script type="dojo/method" event="onClick">
+							var dlg = dijit.byId('dialogAB');
+							dlg.show();
+							// avoid (trying to) restore focus to a closed menu, go to MenuBar instead
+							dlg._savedFocus = dojo.byId("header");
+						</script>
+						action bar
+					</div>
+				</div>
+			</div>
+			<div dojoType="dijit.PopupMenuBarItem" id="inputPadding">
+				<span>TextBox Padding</span>
+				<div dojoType="dijit.Menu" id="inputPaddingMenu">
+					<div dojoType="dijit.CheckedMenuItem" onClick="setTextBoxPadding" checked>theme default</div>
+					<div dojoType="dijit.CheckedMenuItem" onClick="setTextBoxPadding">0px</div>
+					<div dojoType="dijit.CheckedMenuItem" onClick="setTextBoxPadding">1px</div>
+					<div dojoType="dijit.CheckedMenuItem" onClick="setTextBoxPadding">2px</div>
+					<div dojoType="dijit.CheckedMenuItem" onClick="setTextBoxPadding">3px</div>
+					<div dojoType="dijit.CheckedMenuItem" onClick="setTextBoxPadding">4px</div>
+					<div dojoType="dijit.CheckedMenuItem" onClick="setTextBoxPadding">5px</div>
+				</div>
+			</div>
+			<div dojoType="dijit.PopupMenuBarItem" id="help">
+				<span>Help</span>
+				<div dojoType="dijit.Menu" id="helpMenu">
+					<div dojoType="dijit.MenuItem">Help Topics</div>
+					<div dojoType="dijit.MenuItem">About Dijit</div>
+				</div>
+			</div>
+			<div dojoType="dijit.PopupMenuBarItem" disabled="true">
+				<span>Disabled</span>
+				<div dojoType="dijit.Menu">
+					<div dojoType="dijit.MenuItem">You should not see this</div>
+				</div>
+			</div>
+			<div dojoType="dijit.MenuBarItem" onclick="alert('no submenu, just a clickable MenuItem');">
+				Click me!
+			</div>
+		</div>
+
+		<div dojoType="dijit.layout.AccordionContainer"
+			minSize="20" style="width: 300px;" id="leftAccordion" region="leading" splitter="true">
+
+			<div dojoType="dijit.layout.ContentPane" title="Popups and Alerts"><div style="padding:8px">
+				<h2>Tooltips</h2>
+				<ul>
+					<li>
+					<span id="ttRich"><b>rich</b> <i>text</i> tooltip</span>
+					<span dojoType="dijit.Tooltip" connectId="ttRich" style="display:none;">
+						Embedded <b>bold</b> <i>RICH</i> text <span style="color:#309; font-size:x-large;">weirdness!</span>
+					</span>
+					</li>
+
+					<li><a id="ttOne" href="#bogus">anchor tooltip</a>
+					<span dojoType="dijit.Tooltip" connectId="ttOne" style="display:none;">tooltip on anchor</span>
+					</li>
+				</ul>
+
+				<table style="width: 100%;">
+					<tr>
+						<td></td>
+						<td>
+							<div id="ttBelow" href="#bogus">tooltip below</div>
+							<div dojoType="dijit.Tooltip" connectId="ttBelow" style="display:none; width: 100px;" position="below" >I'm <i>below</i>!</div>
+						</td>
+						<td></td>
+					</tr>
+					<tr>
+						<td>
+							<div id="ttRight" href="#bogus">tooltip after</div>
+							<div dojoType="dijit.Tooltip" connectId="ttRight" style="display:none;" position="after" >I'm on the <i>right</i>!<br>(or left on RTL systems)</div>
+						</td>
+						<td></td>
+						<td>
+							<div id="ttLeft" href="#bogus">tooltip before</div>
+							<div dojoType="dijit.Tooltip" connectId="ttLeft" style="display:none;" position="before,after" >I'm on the <i>left</i>!<br>(or right on RTL systems)</div>
+						</td>
+					</tr>
+					<tr>
+						<td></td>
+						<td>
+							<div id="ttAbove" href="#bogus">tooltip above</div>
+							<div dojoType="dijit.Tooltip" connectId="ttAbove" style="display:none;" position="above" >I'm <i>above</i>!</div>
+						</td>
+						<td></td>
+					</tr>
+				</table>
+
+				<hr class="spacer">
+
+				<h2>Dialogs</h2>
+				<ul>
+					<li><a href="#" onclick="dijit.byId('dialog1').show()">slow loading modal dialog</a></li>
+					<li><a href="#" onclick="dijit.byId('dialogAB').show()">modal dialog w/action bar</a></li>
+				</ul>
+
+				<div dojoType="dijit.form.DropDownButton">
+					<span>Show Tooltip Dialog</span>
+					<div dojoType="dijit.TooltipDialog" id="tooltipDlg" title="Enter Login information"
+						execute="alert('submitted w/args:\n' + dojo.toJson(arguments[0], true));">
+						<table>
+							<tr>
+								<td><label for="user">User:</label></td>
+								<td><input dojoType=dijit.form.TextBox type="text" id="user" name="user" ></td>
+							</tr>
+							<tr>
+								<td><label for="pwd">Password:</label></td>
+								<td><input dojoType=dijit.form.TextBox type="password" id="pwd" name="pwd"></td>
+							</tr>
+							<tr>
+								<td colspan="2" align="center">
+									<button dojoType=dijit.form.Button type="submit" name="submit">Login</button>
+							</tr>
+						</table>
+					</div>
+				</div>
+			</div>
+			</div>
+
+			<div dojoType="dijit.layout.ContentPane" title="Dojo Tree from Store">
+				<!-- tree widget -->
+				<div dojoType="dijit.Tree" store="continentStore" query="{type:'continent'}"
+					label="Continents" openOnClick="true">
+				</div>
+			</div>
+
+			<div dojoType="dijit.layout.ContentPane" title="Calendar" selected="true">
+				<!-- calendar widget pane -->
+				<input id="calendar1" dojoType="dijit.Calendar" onChange="myHandler(this.id,arguments[0])">
+			</div>
+
+			<div dojoType="dijit.layout.ContentPane" title="Color Picker">
+				<p>
+					Selecting a color will change the background color of the page.
+					Use this to test how tooltips and drop downs appear with different backgrounds.
+				</p>
+				<h2 class="testHeader">3x4</h2>
+				<script>
+					function setBackground(color){
+						dojo.query('.dijitAccordionBody').style('background', color);
+						dojo.query('.dijitTabPaneWrapper').style('background', color);
+					}
+				</script>
+				<div dojoType="dijit.ColorPalette"  palette="3x4" onChange="setBackground(arguments[0]);"></div>
+				<h2 class="testHeader">7x10</h2>
+				<div dojoType="dijit.ColorPalette" onChange="setBackground(arguments[0]);"></div>
+			</div>
+			<div dojoType="dijit.layout.TabContainer" useMenu="false" title="Sliding TabContainer"
+						id="slidingTab">
+				<div dojoType="dijit.layout.ContentPane" title="Information">
+					This tab container uses slide controls when the tabs are too wide to fit beside each other.
+					If you make the left column narrow enough, the slide controls should appear.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Rootless Tree" closable="true">
+					<div
+						dojoType="dijit.Tree"
+						id="rootlessTree"
+						store="continentStore"
+						query="{type:'continent'}"
+						openOnClick="true">
+					</div>
+
+				</div>
+				<div dojoType="dijit.layout.TabContainer"
+						id="inlined" closable="true"
+						title="Nested TabContainer" nested="true">
+					<a dojoType="dijit.layout.LinkPane" id="tab1href" href="../tests/layout/tab1.html" onLoad="console.log('load of SubTab 1');">SubTab 1</a>
+					<a dojoType="dijit.layout.LinkPane" id="tab2href" href="../tests/layout/tab2.html"  onLoad="console.log('load of SubTab 2');" selected="true">SubTab 2</a>
+					<div dojoType="dijit.layout.ContentPane" id="subtab3" title="SubTab 3">
+						<h1>I am tab 3, inlined.</h1>
+					</div>
+					<div dojoType="dijit.layout.ContentPane" id="subtab4" title="SubTab 4">
+						<h1>I am tab 4, inlined.</h1>
+					</div>
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Menu Bar" closable="true">
+					<div id="menubar" dojoType="dijit.MenuBar">
+					<div dojoType="dijit.PopupMenuBarItem" >
+						<span>File</span>
+						<div dojoType="dijit.Menu">
+							<div dojoType="dijit.MenuItem" iconClass="dijitIconNewTask">New</div>
+							<div dojoType="dijit.MenuItem">Open</div>
+							<div dojoType="dijit.MenuSeparator"></div>
+							<div dojoType="dijit.MenuItem" iconClass="dijitIconSave">Save</div>
+							<div dojoType="dijit.MenuItem">Save As...</div>
+						</div>
+					</div>
+					<div dojoType="dijit.PopupMenuBarItem">
+						<span>Edit</span>
+						<div dojoType="dijit.Menu" >
+							<div dojoType="dijit.MenuItem"  iconClass="dijitIconCut"
+								onClick="console.log('not actually cutting anything, just a test!')">Cut</div>
+							<div dojoType="dijit.MenuItem"  iconClass="dijitIconCopy"
+								onClick="console.log('not actually copying anything, just a test!')">Copy</div>
+							<div dojoType="dijit.MenuItem"  iconClass="dijitIconPaste"
+								onClick="console.log('not actually pasting anything, just a test!')">Paste</div>
+						</div>
+					</div>
+					<div dojoType="dijit.PopupMenuBarItem">
+						<span>View</span>
+						<div dojoType="dijit.Menu">
+							<div dojoType="dijit.MenuItem">Normal</div>
+							<div dojoType="dijit.MenuItem">Outline</div>
+							<div dojoType="dijit.PopupMenuItem">
+								<span>Zoom</span>
+								<div dojoType="dijit.Menu">
+									<div dojoType="dijit.MenuItem">50%</div>
+									<div dojoType="dijit.MenuItem">75%</div>
+									<div dojoType="dijit.MenuItem">100%</div>
+									<div dojoType="dijit.MenuItem">150%</div>
+									<div dojoType="dijit.MenuItem">200%</div>
+								</div>
+							</div>
+						</div>
+					</div>
+					<div dojoType="dijit.PopupMenuBarItem">
+						<span>Help</span>
+						<div dojoType="dijit.Menu">
+							<div dojoType="dijit.MenuItem">Help Topics</div>
+							<div dojoType="dijit.MenuItem">About Dijit</div>
+						</div>
+					</div>
+					<div dojoType="dijit.PopupMenuBarItem" disabled="true">
+						<span>Disabled</span>
+						<div dojoType="dijit.Menu">
+							<div dojoType="dijit.MenuItem">You should not see this</div>
+						</div>
+					</div>
+					<div dojoType="dijit.MenuBarItem" onclick="alert('no submenu, just a clickable MenuItem');">
+						Click me!
+					</div>
+				</div>
+				</div>
+			</div>
+
+
+		</div><!-- end AccordionContainer -->
+
+		<!-- top tabs (marked as "center" to take up the main part of the BorderContainer) -->
+		<div dojoType="dijit.layout.TabContainer" region="center" id="topTabs" tabStrip="true">
+
+			<div id="basicFormTab" dojoType="dijit.layout.ContentPane" title="Basic Form Widgets" style="padding:10px;display:none;">
+
+				<h2>Buttons</h2>
+				<p>Buttons can do an action, display a menu, or both:</p>
+
+				Enabled:
+
+				<button dojoType="dijit.form.Button" iconClass="dijitIconTask" onClick='console.debug("clicked simple")'>
+					Simple
+				</button>
+
+				<button dojoType="dijit.form.DropDownButton" iconClass="dijitIconEdit">
+					<span>Drop Down</span>
+					<div dojoType="dijit.Menu" id="editMenu1" style="display: none;">
+						<div dojoType="dijit.MenuItem"
+							iconClass="dijitIconCut"
+							onClick="console.debug('not actually cutting anything, just a test!')">
+							Cut
+						</div>
+
+						<div dojoType="dijit.MenuItem"
+							 iconClass="dijitIconCopy"
+							onClick="console.debug('not actually copying anything, just a test!')">
+							Copy
+						</div>
+
+						<div dojoType="dijit.MenuItem"
+							 iconClass="dijitIconPaste"
+							onClick="console.debug('not actually pasting anything, just a test!')">
+							Paste
+						</div>
+					</div>
+				</button>
+
+				<button dojoType="dijit.form.ComboButton" iconClass="dijitIconSave"
+					optionsTitle='save options'
+					onClick='console.debug("clicked combo save")'>
+					<span>Combo</span>
+					<div dojoType="dijit.Menu" id="saveMenu1" style="display: none;">
+						<div dojoType="dijit.MenuItem"
+							 iconClass="dijitIconSave"
+							onClick="console.debug('not actually saving anything, just a test!')">
+							Save
+						</div>
+						<div dojoType="dijit.MenuItem"
+							onClick="console.debug('not actually saving anything, just a test!')">
+							Save As
+						</div>
+					</div>
+				</button>
+
+				<button dojoType="dijit.form.ToggleButton" checked onChange="console.log('toggled button checked='+arguments[0]);" iconClass="dijitCheckBoxIcon">
+					Toggle
+				</button>
+
+				<hr class="spacer">
+
+				Disabled:
+
+				<button dojoType="dijit.form.Button" iconClass="dijitIconTask" disabled>
+					Simple
+				</button>
+
+				<button dojoType="dijit.form.DropDownButton" iconClass="dijitIconEdit" disabled>
+					<span>Drop Down</span>
+					<div dojoType="dijit.Menu" id="editMenu2" style="display: none;">
+						<div dojoType="dijit.MenuItem"
+							iconClass="dijitIconCut"
+							onClick="console.debug('not actually cutting anything, just a test!')">
+							Cut
+						</div>
+
+						<div dojoType="dijit.MenuItem"
+							 iconClass="dijitIconCopy"
+							onClick="console.debug('not actually copying anything, just a test!')">
+							Copy
+						</div>
+
+						<div dojoType="dijit.MenuItem"
+							 iconClass="dijitIconPaste"
+							onClick="console.debug('not actually pasting anything, just a test!')">
+							Paste
+						</div>
+					</div>
+				</button>
+
+				<button dojoType="dijit.form.ComboButton" iconClass="dijitIconSave"
+					optionsTitle='save options'
+					disabled>
+					<span>Combo</span>
+					<div dojoType="dijit.Menu" id="saveMenu2" style="display: none;">
+						<div dojoType="dijit.MenuItem"
+							 iconClass="dijitIconSave"
+							onClick="console.debug('not actually saving anything, just a test!')">
+							Save
+						</div>
+						<div dojoType="dijit.MenuItem"
+							onClick="console.debug('not actually saving anything, just a test!')">
+							Save As
+						</div>
+					</div>
+				</button>
+
+				<button dojoType="dijit.form.ToggleButton" checked disabled iconClass="dijitCheckBoxIcon">
+					Toggle
+				</button>
+
+				<hr class="spacer">
+
+				<h2>CheckBox</h2>
+				<fieldset>
+					<input id="check1" type="checkBox" dojoType="dijit.form.CheckBox">
+					<label for="check1">unchecked</label>
+
+					<input id="check2" type="checkBox" dojoType="dijit.form.CheckBox" checked="checked">
+					<label for="check2">checked</label>
+
+					<input id="check3" type="checkBox" dojoType="dijit.form.CheckBox" disabled>
+					<label for="check3">disabled</label>
+
+					<input id="check4" type="checkBox" dojoType="dijit.form.CheckBox" checked="checked" disabled>
+					<label for="check4">disabled and checked</label>
+				</fieldset>
+
+				<h2>Radio Buttons</h2>
+				<fieldset>
+					<input type="radio" name="g1" id="g1rb1" value="news" dojoType="dijit.form.RadioButton">
+					<label for="g1rb1">news</label>
+					<input type="radio" name="g1" id="g1rb2" value="talk" dojoType="dijit.form.RadioButton" checked>
+					<label for="g1rb2">talk</label>
+					<input type="radio" name="g1" id="g1rb3" value="weather" dojoType="dijit.form.RadioButton" disabled>
+					<label for="g1rb3">weather (disabled)</label>
+				</fieldset>
+			</div> <!-- end of basic form widgets -->
+
+			<div id="textboxTab" dojoType="dijit.layout.ContentPane" title="Text Input Widgets" style="padding:10px;display:none;">
+
+				<h2>dijit.form.DateTextBox</h2>
+				<label for="date1">Enabled w/placeHolder:</label>
+				<input id="date1" name="date1" type="text" dojoType="dijit.form.DateTextBox" placeHolder="Birthday">
+				<label for="date2">Disabled w/placeHolder:</label>
+				<input id="date2" name="date2" type="text" dojoType="dijit.form.DateTextBox" placeHolder="Birthday" disabled="disabled">
+				<label for="date2">Disabled w/value:</label>
+				<input id="date3" name="date3" type="text" dojoType="dijit.form.DateTextBox" value="2008-12-25" disabled="disabled">
+
+				<h2>dijit.form.TimeTextBox</h2>
+				<label for="time1">Enabled:</label>
+				<input id="time1" name="time1" type="text" dojoType="dijit.form.TimeTextBox" value="T17:45:00">
+				<label for="time2">Disabled:</label>
+				<input id="time2" name="time2" type="text" dojoType="dijit.form.TimeTextBox" value="T17:45:00" disabled>
+
+				<h2>dijit.form.CurrencyTextBox</h2>
+				<label for="currency1">Enabled:</label>
+				<input id="currency1" type="text" name="income1" value="54775.53"
+					dojoType="dijit.form.CurrencyTextBox"
+					required="true"
+					constraints="{fractional:true}"
+					currency="USD"
+					invalidMessage="Invalid amount.  Include dollar sign, commas, and cents.  Cents are mandatory.">
+				<label for="currency2">Disabled:</label>
+				<input id="currency2" type="text" name="income1" value="54775.53"
+					dojoType="dijit.form.CurrencyTextBox"
+					required="true"
+					constraints="{fractional:true}"
+					currency="USD"
+					invalidMessage="Invalid amount.  Include dollar sign, commas, and cents.  Cents are mandatory." disabled>
+
+				<hr class="spacer">
+
+				<h2>dijit.form.NumberSpinner max=100</h2>
+				<label for="spinner1">Enabled: </label>
+				<input dojoType="dijit.form.NumberSpinner" constraints="{max:100,places:0}" id="spinner1" value="10">
+				<label for="spinner2">Disabled: </label>
+				<input dojoType="dijit.form.NumberSpinner" constraints="{max:100,places:0}" id="spinner2" value="10" disabled>
+
+			</div>
+
+			<div id="selectTab" dojoType="dijit.layout.ContentPane" title="Select Widgets" style="padding:10px;display:none;">
+
+				<h2>dijit.form.Select</h2>
+				<label for="selectEnabled">Enabled: </label>
+				<div id="selectEnabled" value="AK" dojoType="dijit.form.Select">
+					<span value="AL"><b>Alabama</b></span>
+					<span value="AK"><font color="red">A</font><font color="orange">l</font><font color="yellow">a</font><font color="green">s</font><font color="blue">k</font><font color="purple">a</font></span>
+					<span value="AZ"><i>Arizona</i></span>
+					<span value="AR"><span class="ark">Arkansas</span></span>
+					<span value="CA"><span style="font-size:25%">C</span><span style="font-size:50%">a</span><span style="font-size:75%">l</span><span style="font-size:90%">i</span><span style="font-size:100%">f</span><span style="font-size:125%">o</span><span style="font-size:133%">r</span><span style="font-size:150%">n</span><span style="font-size:175%">i</span><span style="font-size:200%">a</span></span>
+					<span value="NM" disabled="disabled">New<br>  Mexico</span>
+				</div>
+	
+				<label for="selectDisabled">Disabled: </label>
+				<div id="selectDisabled" value="AK" dojoType="dijit.form.Select" disabled>
+					<span value="AL"><b>Alabama</b></span>
+					<span value="AK"><font color="red">A</font><font color="orange">l</font><font color="yellow">a</font><font color="green">s</font><font color="blue">k</font><font color="purple">a</font></span>
+					<span value="AZ"><i>Arizona</i></span>
+					<span value="AR"><span class="ark">Arkansas</span></span>
+					<span value="CA"><span style="font-size:25%">C</span><span style="font-size:50%">a</span><span style="font-size:75%">l</span><span style="font-size:90%">i</span><span style="font-size:100%">f</span><span style="font-size:125%">o</span><span style="font-size:133%">r</span><span style="font-size:150%">n</span><span style="font-size:175%">i</span><span style="font-size:200%">a</span></span>
+					<span value="NM" disabled="disabled">New<br>  Mexico</span>
+				</div>
+
+				<hr class="spacer">
+
+				<h2>dijit.form.FilteringSelect</h2>
+				<label for="filteringSelect">Enabled w/placeHolder: </label>
+				<input dojoType="dijit.form.FilteringSelect"
+					placeHolder="State"
+					store="stateStore"
+					searchAttr="name"
+					name="state2"
+					id="filteringSelect"
+				>
+				<label for="filteringSelect2">Disabled w/placeHolder: </label>
+				<input dojoType="dijit.form.FilteringSelect"
+					placeHolder="State"
+					store="stateStore"
+					searchAttr="name"
+					name="state2"
+					id="filteringSelect2"
+					disabled
+				>
+				<label for="filteringSelect3">Disabled w/value: </label>
+				<input dojoType="dijit.form.FilteringSelect"
+					value="California"
+					store="stateStore"
+					searchAttr="name"
+					name="state3"
+					id="filteringSelect3"
+					disabled
+				>
+
+
+			</div>
+
+			<div id="textareaTab" dojoType="dijit.layout.ContentPane" title="Textarea" style="padding:10px;">
+
+				<!--	‪ and ‬ are inserted solely for testing purposes to mark the beginning and end of left-to-right text so that
+					cogniscent browsers don't render garbled punctuation nor exhibit strange home/end key behavior while in right-to-left mode -->
+				<h2>dijit.form.Textarea</h2>
+				<p>Enabled:</p>
+				<textarea dojoType="dijit.form.Textarea" name="areText">This text area will expand and contract as you type ‪text.‬
+
+Lorem ipsum dolor sit ‪amet,‬
+consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
+dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci
+tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo ‪consequat.‬
+				</textarea>
+
+				<br>
+				<p>Disabled:</p>
+				<textarea dojoType="dijit.form.Textarea" name="areText2" disabled>This text
+				area is disabled and you shouldn't be able to type in ‪it.‬
+				</textarea>
+
+
+				<h2>dijit.form.SimpleTextarea</h2>
+				<p></p>
+				<p>Enabled:</p>
+				<textarea dojoType="dijit.form.SimpleTextarea" name="areText">This text area has a constant height and displays a scrollbar when ‪necessary.‬
+
+Lorem ipsum dolor sit ‪amet,‬
+consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
+dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci
+tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis
+autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie ‪consequat,‬
+vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
+dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait
+nulla ‪facilisi.‬
+				</textarea>
+
+				<p>Disabled:</p>
+				<textarea dojoType="dijit.form.SimpleTextarea" name="areText2" disabled>Lorem ipsum dolor sit ‪amet,‬
+				consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
+				dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci
+				tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis
+				autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie ‪consequat,‬
+				vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
+				dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait
+				nulla ‪facilisi.‬
+				</textarea>
+			</div><!-- end of Textarea tab -->
+
+			<div id="editorTab" dojoType="dijit.layout.ContentPane" title="Editor" style="padding:10px;">
+				<p>Enabled:</p>
+				<!-- FIXME:
+					set height on this node to size the whole editor, but causes the tab to not scroll
+					until you select another tab and come back. alternative is no height: here, but that
+					causes editor to become VERY tall, and size to a normal height when selected (like the
+					dijit.form.TextArea in "Form Feel" Tab), but in reverse. refs #3980 and is maybe new bug?
+				-->
+				<div height="175" dojoType="dijit.Editor" extraPlugins="['|', 'createLink', 'fontName']" styleSheets="../../dojo/resources/dojo.css">
+					<ul>
+						<li>Lorem <a href="http://dojotoolkit.org">and a link</a>, what do you think?</li>
+						<li>This is the Editor with a Toolbar attached.</li>
+					</ul>
+				</div>
+				<p>Disabled:</p>
+				<div height="175" dojoType="dijit.Editor" extraPlugins="['|', 'createLink', 'fontName']" styleSheets="../../dojo/resources/dojo.css" disabled="true">
+					<ul>
+						<li>Lorem <a href="http://dojotoolkit.org">and a link</a>, what do you think?</li>
+						<li>This is the Editor with a Toolbar attached.</li>
+					</ul>
+				</div>
+			</div><!-- end of Editor tab -->
+
+
+			<div dojoType="dijit.layout.ContentPane" title="Sliders" style="padding:10px;display:none;">
+
+
+				<!-- Sliders: -->
+
+				<h2>Enabled</h2>
+				<div style="float:right;">
+				<div dojoType="dijit.form.VerticalSlider"
+					onChange="dojo.byId('slider2input').value=arguments[0];"
+					value="10"
+					maximum="100"
+					minimum="0"
+					discreteValues="11"
+					style="height:176px; clear:both;"
+					id="slider2">
+						<ol dojoType="dijit.form.VerticalRuleLabels" container="leftDecoration"style="width:2em;" labelStyle="right:0px;">
+							<li>0
+							<li>100
+						</ol>
+
+						<div dojoType="dijit.form.VerticalRule" container="leftDecoration" count=11 style="width:5px;"></div>
+						<div dojoType="dijit.form.VerticalRule" container="rightDecoration" count=11 style="width:5px;"></div>
+						<ol dojoType="dijit.form.VerticalRuleLabels" container="rightDecoration"style="width:2em;" maximum="100" count="6" numericMargin="1" constraints="{pattern:'#'}"></ol>
+				</div>
+				<br> Slider2 Value:<input disabled id="slider2input" size="3" value="10" autocomplete="off">
+				</div>
+
+				<div dojoType="dijit.form.HorizontalSlider"
+					onChange="dojo.byId('slider1input').value=dojo.number.format(arguments[0]/100,{places:1,pattern:'#%'});"
+					value="10"
+					maximum="100"
+					minimum="0"
+					showButtons="false"
+					intermediateChanges="true"
+					style="width:50%; height: 20px;"
+					id="horizontal1">
+						<ol dojoType="dijit.form.HorizontalRuleLabels" container="topDecoration" style="height:1.2em;font-size:75%;" numericMargin="1" count="6"></ol>
+						<div dojoType="dijit.form.HorizontalRule" container="topDecoration" count=11 style="height:5px;"></div>
+						<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count=5 style="height:5px;"></div>
+						<ol dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" style="height:1em;font-size:75%;">
+							<li>lowest
+							<li>normal
+							<li>highest
+						</ol>
+
+				</div>
+				<br>Value: <input disabled id="slider1input" size="5" value="10.0%" autocomplete="off">
+
+				<div dojoType="dijit.form.HorizontalSlider"
+					minimum="1"
+					value="2"
+					maximum="3"
+					discreteValues="3"
+					showButtons="false"
+					intermediateChanges="true"
+					style="width:300px; height: 40px;"
+					id="horizontal2">
+						<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count=3 style="height:5px;"></div>
+						<ol dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration"style="height:1em;font-size:75%;">
+							<li><img width=10 height=10 src="../tests/images/note.gif"><br><span style="font-size: small">small</span>
+							<li><img width=15 height=15 src="../tests/images/note.gif"><br><span style="font-size: medium">medium</span>
+
+							<li><img width=20 height=20 src="../tests/images/note.gif"><br><span style="font-size: large">large</span>
+						</ol>
+				</div>
+
+				<h2 style="clear:both">Disabled</h2>
+				<div style="float:right;">
+				<div dojoType="dijit.form.VerticalSlider"
+					value="10"
+					maximum="100"
+					minimum="0"
+					discreteValues="11"
+					style="height:175px; clear:both"
+					disabled>
+						<ol dojoType="dijit.form.VerticalRuleLabels" container="leftDecoration"style="width:2em;" labelStyle="right:0px;">
+							<li>0
+							<li>100
+						</ol>
+
+						<div dojoType="dijit.form.VerticalRule" container="leftDecoration" count=11 style="width:5px;"></div>
+						<div dojoType="dijit.form.VerticalRule" container="rightDecoration" count=11 style="width:5px;"></div>
+						<ol dojoType="dijit.form.VerticalRuleLabels" container="rightDecoration"style="width:2em;" maximum="100" count="6" numericMargin="1" constraints="{pattern:'#'}"></ol>
+				</div>
+				</div>
+				<div dojoType="dijit.form.HorizontalSlider"
+					value="10"
+					maximum="100"
+					minimum="0"
+					showButtons="false"
+					intermediateChanges="true"
+					style="width:50%; height: 20px;"
+					disabled>
+						<ol dojoType="dijit.form.HorizontalRuleLabels" container="topDecoration" style="height:1.2em;font-size:75%;" numericMargin="1" count="6"></ol>
+						<div dojoType="dijit.form.HorizontalRule" container="topDecoration" count=11 style="height:5px;"></div>
+						<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count=5 style="height:5px;"></div>
+						<ol dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" style="height:1em;font-size:75%;">
+							<li>lowest
+							<li>normal
+							<li>highest
+						</ol>
+
+				</div>
+
+				<div dojoType="dijit.form.HorizontalSlider"
+					minimum="1"
+					value="2"
+					maximum="3"
+					discreteValues="3"
+					showButtons="false"
+					intermediateChanges="true"
+					style="width:300px; height: 40px;"
+					disabled>
+						<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count=3 style="height:5px;"></div>
+						<ol dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration"style="height:1em;font-size:75%;">
+							<li><img width=10 height=10 src="../tests/images/note.gif"><br><span style="font-size: small">small</span>
+							<li><img width=15 height=15 src="../tests/images/note.gif"><br><span style="font-size: medium">medium</span>
+							<li><img width=20 height=20 src="../tests/images/note.gif"><br><span style="font-size: large">large</span>
+						</ol>
+				</div>
+			</div>
+
+			<div id="variousTab" dojoType="dijit.layout.ContentPane" title="Various Dijits"
+				style="padding:10px; display:none;">
+
+
+				<h2>TitlePane</h2>
+				<div dojoType="dijit.TitlePane" title="my pane" width="275">
+					<p>This is a title pane.  It can be expanded and collapsed.</p>
+
+					<p>Sed sollicitudin suscipit risus. Nam
+					ullamcorper. Sed nisl lectus, pellentesque nec,
+					malesuada eget, ornare a, libero. Lorem ipsum dolor
+					sit amet, consectetuer adipiscing elit.</p>
+
+				</div><!-- end title pane -->
+
+				<hr class="spacer">
+
+				<h2>ProgressBar</h2>
+				<div style="width:400px;" maximum="200" id="setTestBar"
+					progress="20" dojoType="dijit.ProgressBar"></div>
+
+				Indeterminate:
+				<div style="width:400px;" indeterminate="true" dojoType="dijit.ProgressBar"></div>
+
+			</div><!-- end:various dijits upper tab -->
+
+			<div id="InlineEditBoxTab" dojoType="dijit.layout.ContentPane" title="InlineEditBox"
+				style="padding:10px; display:none;">
+
+				<h2 class="testTitle">dijit.InlineEditBox + dijit.form.TextBox on <h3></h2>
+
+				(HTML before)
+				<h3 id="editable" style="font-size:larger;" dojoType="dijit.InlineEditBox" onChange="myHandler(this.id,arguments[0])">
+					Edit me - I trigger the onChange callback
+				</h3>
+				(HTML after)
+
+				<hr class="spacer">
+
+				<h2>dijit.InlineEditBox + dijit.form.Textarea</h2>
+
+				(HTML before)
+				<p id="areaEditable" dojoType="dijit.InlineEditBox" editor="dijit.form.Textarea" autoSave="false">
+					I'm one big ‪paragraph.‬  Go ahead and edit ‪me.‬  I dare ‪you.‬
+					The quick brown fox jumped over the lazy ‪dog.‬  Blah blah blah blah blah blah ‪blah ...‬
+				</p>
+				(HTML after)
+
+				<p>
+					These links will
+					<a href="#" onClick="dijit.byId('areaEditable').set('disabled', true)">disable</a> /
+					<a href="#" onClick="dijit.byId('areaEditable').set('disabled', false)">enable</a>
+					the text area above.
+				</p>
+
+				<hr class="spacer">
+
+				<h2>dijit.form.DateTextBox</h2>
+
+				(HTML inline before)
+				<!-- set programmatically to match locale; a server might generate this content also. -->
+				<span id="backgroundArea" dojoType="dijit.InlineEditBox" editor="dijit.form.DateTextBox" width="170px"></span>
+				(HTML after)
+				<hr class="spacer">
+
+				<h2>dijit.form.TimeTextBox</h2>
+
+				(HTML inline before)
+				<!-- set programmatically to match locale; a server might generate this content also. -->
+				<span id="timePicker" dojoType="dijit.InlineEditBox" editor="dijit.form.TimeTextBox" width="150px"></span>
+				(HTML after)
+
+				<hr class="spacer">
+
+
+				<h2>dijit.form.FilteringSelect + Inline + remote data store</h2>
+				(HTML inline before)
+				<span id="backgroundArea2" dojoType="dijit.InlineEditBox" editor="dijit.form.FilteringSelect"
+					editorParams="{store: stateStore, autoComplete: true, promptMessage: 'Please enter a state'}"
+					width="300px">
+					Indiana
+				</span>
+				(HTML after)
+
+			</div><!-- end InlineEditBox tab -->
+
+			<div id="dndTab" dojoType="dijit.layout.ContentPane" title="DnD"
+				style="padding:10px; display:none;">
+				<div style="float:left; margin:5px;">
+					<h3>Source 1</h3>
+					<div dojoType="dojo.dnd.Source" style="border:3px solid #ccc; padding: 1em 3em; ">
+						<div class="dojoDndItem">Item <strong>X</strong></div>
+						<div class="dojoDndItem">Item <strong>Y</strong></div>
+						<div class="dojoDndItem">Item <strong>Z</strong></div>
+					</div>
+				</div>
+				<div style="float:left; margin:5px; ">
+					<h3>Source 2</h3>
+					<div dojoType="dojo.dnd.Source" style="border:3px solid #ccc; padding: 1em 3em; ">
+						<div class="dojoDndItem">Item <strong>1</strong></div>
+						<div class="dojoDndItem">Item <strong>2</strong></div>
+						<div class="dojoDndItem">Item <strong>3</strong></div>
+					</div>
+				</div>
+			</div><!-- end DnD tab -->
+
+			<div id="closableTab" dojoType="dijit.layout.ContentPane" title="Closable"
+				style="display:none; padding:10px; " closable="true">
+				This pane is closable, just for the icon ...
+			</div>
+		</div><!-- end of region="center" TabContainer -->
+
+		<!-- bottom right tabs -->
+		<div dojoType="dijit.layout.TabContainer" id="bottomTabs"
+			tabPosition="bottom" selectedChild="btab1" region="bottom" splitter="true" tabStrip="true">
+
+			<!-- btab 1 -->
+			<div id="btab1" dojoType="dijit.layout.ContentPane" title="Info" style=" padding:10px; ">
+				<p>You can explore this single page after applying a Theme
+				for use in creation of your own theme.</p>
+
+				<p>I am whole slew of Widgets on a page. Jump to <a href="../tests/">dijit tests</a> to
+				test individual components.</p>
+
+				<p>There is a right-click [context] pop-up menu here, as well.</p>
+			</div><!-- end:info btab1 -->
+
+			<div id="btab2" dojoType="dijit.layout.ContentPane" title="Alternate Themes" style="padding:20px;">
+				<span id="themeData"></span>
+			</div><!-- btab2 -->
+
+			<div id="btab3" dojoType="dijit.layout.ContentPane" title="Bottom 3" closable="true">
+				<p>I am the last Tab</p>
+				<div id="dialog2" dojoType="dijit.Dialog" title="Encased Dialog" style="display:none;">
+				I am the second dialog. I am
+				parented by the Low Tab Pane #3
+				</div>
+			</div><!-- btab3 -->
+
+		</div><!-- end Bottom TabContainer -->
+
+	</div><!-- end of BorderContainer -->
+
+	<!-- dialog in body -->
+	<div id="dialog1" dojoType="dijit.Dialog"
+		title="Floating Modal Dialog from href" style="display:none; width: 400px;"
+		href="../tests/layout/getResponse.php?delay=3000&messId=3" refreshOnShow="true"></div>
+	<div id="dialogAB" dojoType="dijit.Dialog"
+		title="Floating Modal Dialog" style="display:none;">
+		<div class="dijitDialogPaneContentArea">
+			<table>
+				<tr>
+					<td><label for="name">Name: </label></td>
+					<td><input dojoType=dijit.form.TextBox type="text" name="name" id="name"></td>
+				</tr>
+				<tr>
+					<td><label for="loc">Location: </label></td>
+					<td><input dojoType=dijit.form.TextBox type="text" name="loc" id="loc"></td>
+				</tr>
+				<tr>
+					<td><label for="date">Date: </label></td>
+					<td><input dojoType=dijit.form.DateTextBox type="text" name="date" id="date"></td>
+				</tr>
+			</table>
+		</div>
+		
+		
+		<div class="dijitDialogPaneActionBar">
+			<button dojoType="dijit.form.Button" type="submit" id="ABdialog1button1">OK</button>
+			<button dojoType="dijit.form.Button" type="button" onClick="dijit.byId('dialogAB').onCancel();" 
+					id="ABdialog1button2">Cancel</button>
+		</div>
+	</div>
+
+</body>
+</html>
diff --git a/dijit/themes/themeTesterImages/blackButtonEnabled.gif b/dijit/themes/themeTesterImages/blackButtonEnabled.gif
new file mode 100644
index 0000000..9174efd
Binary files /dev/null and b/dijit/themes/themeTesterImages/blackButtonEnabled.gif differ
diff --git a/dijit/themes/themeTesterImages/blackButtonHover.gif b/dijit/themes/themeTesterImages/blackButtonHover.gif
new file mode 100644
index 0000000..16f087c
Binary files /dev/null and b/dijit/themes/themeTesterImages/blackButtonHover.gif differ
diff --git a/dijit/themes/themeTesterQuirk.html b/dijit/themes/themeTesterQuirk.html
new file mode 100644
index 0000000..8414143
--- /dev/null
+++ b/dijit/themes/themeTesterQuirk.html
@@ -0,0 +1,5 @@
+<html>
+<head>
+<script type="text/javascript" src="../tests/_loadTest.js" file="themeTester.html"></script>
+</head>
+</html>
diff --git a/dijit/themes/tundra/Calendar.css b/dijit/themes/tundra/Calendar.css
index 25b605f..be235b3 100644
--- a/dijit/themes/tundra/Calendar.css
+++ b/dijit/themes/tundra/Calendar.css
@@ -1,6 +1,7 @@
+/* Calendar*/
 
 .tundra .dijitCalendarIncrementControl {
-	
+	/* next/prev month buttons */
 	width:15px;
 	height:15px;
 	background-image: url("images/spriteRoundedIconsSmall.png");
@@ -10,24 +11,28 @@
 	font-size:.1em;
 	background-image: url("images/spriteRoundedIconsSmall.gif");
 }
+
 .tundra .dijitA11ySideArrow {
 	display: none;
 }
+
 .tundra .dijitCalendarDecrease {
 	background-position: top left;
 }
 .tundra .dijitCalendarIncrease {
 	background-position: -30px top;
 }
-.tundra table.dijitCalendarContainer {
+
+.tundra .dijitCalendarContainer {
 	font-size: 100%;
 	border-spacing: 0;
 	border-collapse: separate;
 	border: 1px solid #ccc;
 	margin: 0;
 }
+
 .tundra .dijitCalendarMonthContainer th {
-	
+	/* month header cell */
 	background:#d3d3d3 url("images/titleBar.png") repeat-x top;
 	padding-top:.3em;
 	padding-bottom:.2em;
@@ -37,8 +42,9 @@
 	padding-top:.2em;
 	padding-bottom:.1em;
 }
+
 .tundra .dijitCalendarDayLabelTemplate {
-	
+	/* day of week labels */
 	background:white url("images/calendarDayLabel.png") repeat-x bottom;
 	font-weight:normal;
 	padding-top:.15em;
@@ -47,81 +53,85 @@
 	color:#293a4b;
 	text-align:center;
 }
+
 .tundra .dijitCalendarBodyContainer {
 	border-bottom: 1px solid #eeeeee;
 }
+
 .tundra .dijitCalendarMonthLabel {
 	color:#293a4b;
 	font-weight: bold;
 }
+
 .tundra .dijitCalendarDateTemplate {
-	
+	/* style for each day cell */
 	font-size: 0.9em;
 	font-weight: bold;
 	text-align: center;
 	padding: 0.3em 0.3em 0.05em 0.3em;
 	letter-spacing: 1px;
 }
+
 .dj_ie .tundra .dijitCalendarDateTemplate {
 	padding: 0.1em .33em 0.02em .33em;
 }
+
 .tundra .dijitCalendarPreviousMonth,
 .tundra .dijitCalendarNextMonth 		{
-	
+	/* days that are part of the previous or next month */
 	color:#999999;
-	background-color:#f8f8f8 !important;
-}
-.tundra .dijitCalendarPreviousMonthDisabled,
-.tundra .dijitCalendarNextMonthDisabled	{
-	
-	background-color:#a4a5a6 !important;
+	background-color:#f8f8f8;
 }
+
 .tundra .dijitCalendarCurrentMonth {
-	
-	background-color:white !important;
-}
-.tundra .dijitCalendarCurrentMonthDisabled {
-	
-	background-color:#bbbbbc !important;
-}
-.tundra .dijitCalendarDisabledDate {
-	cursor:default !important;
-	text-decoration:line-through !important;
+	/* days that are part of this month */
+	background-color: white;
 }
+
 .tundra .dijitCalendarCurrentDate {
-	
+	/* cell for today's date */
 	text-decoration:underline;
 	font-weight:bold;
 }
+
 .tundra .dijitCalendarHoveredDate {
-	background-color: #e2ebf2 !important;
+	background-color: #e2ebf2;
+}
+
+.tundra .dijitCalendarDisabledDate {
+	text-decoration: line-through;
+	background-color: white;	/* override hover effects above, hover and click on disabled date should have no effect */
 }
+
 .tundra .dijitCalendarSelectedDate {
-	
+	/* cell for the selected date */
 	background-color:#bbc4d0 !important;
 	color:black !important;
 }
 .tundra .dijitCalendarYearContainer {
-	
+	/* footer of the table that contains the year display/selector */
 	background:white url("images/calendarYearLabel.png") repeat-x bottom;
 	border-top:1px solid #ccc;
 }
+
 .tundra .dijitCalendarYearLabel {
-	
+	/* container for all of 3 year labels */
 	margin:0;
 	padding:0.4em 0 0.25em 0;
 	text-align:center;
 }
+
 .tundra .dijitCalendarSelectedYear {
-	
+	/* label for selected year */
 	color:black;
 	padding:0.2em;
 	padding-bottom:0.1em;
 	background-color:#bbc4d0 !important;
 }
+
 .tundra .dijitCalendarNextYear,
 .tundra .dijitCalendarPreviousYear {
-	
+	/* label for next/prev years */
 	color:black !important;
 	font-weight:normal;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/tundra/Calendar_rtl.css b/dijit/themes/tundra/Calendar_rtl.css
index 4baf371..58e7653 100644
--- a/dijit/themes/tundra/Calendar_rtl.css
+++ b/dijit/themes/tundra/Calendar_rtl.css
@@ -1,7 +1,9 @@
+/* Calendar */
 
-.dijitRtl .tundra .dijitCalendarDecrease {
+.tundra .dijitCalendarRtl .dijitCalendarDecrease {
 	background-position: -30px top;
 }
-.dijitRtl .tundra .dijitCalendarIncrease {
+
+.tundra .dijitCalendarRtl .dijitCalendarIncrease {
 	background-position: 0px top;
 }
diff --git a/dijit/themes/tundra/ColorPalette.css b/dijit/themes/tundra/ColorPalette.css
index 56fa558..9d3c4cc 100644
--- a/dijit/themes/tundra/ColorPalette.css
+++ b/dijit/themes/tundra/ColorPalette.css
@@ -2,4 +2,4 @@
 	border:1px solid #7eabcd;
 	background:#fff;
 	-moz-border-radius: 0px !important;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/tundra/Common.css b/dijit/themes/tundra/Common.css
index b7f8ace..c339263 100644
--- a/dijit/themes/tundra/Common.css
+++ b/dijit/themes/tundra/Common.css
@@ -1,13 +1,17 @@
-
+/* DnD avatar-specific settings */
+/* For now it uses a default set of rules. Some other DnD classes can be modified as well. */
 .tundra .dojoDndItemBefore {
 	border-top: 2px solid #369;
 }
+
 .tundra .dojoDndItemAfter {
 	border-bottom: 2px solid #369;
 }
+
 .tundra .dojoDndItemOver {
 	cursor:pointer;
 }
+
 .tundra table.dojoDndAvatar { -moz-border-radius: 0; border: 1px solid #ccc; border-collapse: collapse; background-color: #fff; font-size: 75%; color: black;}
 .tundra .dojoDndAvatar td	{ border: none; }
 .tundra .dojoDndAvatar tr	{ border: none; }
@@ -17,10 +21,12 @@
 .tundra.dojoDndCopy .dojoDndAvatarHeader	{background-color: #f58383; background-image: url(images/dndNoCopy.png); background-repeat: no-repeat; background-position: 2px center;}
 .tundra.dojoDndMove .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{background-color: #97e68d; background-image: url(images/dndMove.png); background-repeat: no-repeat; background-position: 2px center;}
 .tundra.dojoDndCopy .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{background-color: #97e68d; background-image: url(images/dndCopy.png); background-repeat: no-repeat; background-position: 2px center;}
+
 .tundra .dijitContentPaneLoading {
 	background:url('images/loading.gif') no-repeat left center;
 	padding-left:25px;
 }
+
 .tundra .dijitContentPaneError {
 	background:url('images/warning.png') no-repeat left center;
 	padding-left:25px;
diff --git a/dijit/themes/tundra/Dialog.css b/dijit/themes/tundra/Dialog.css
index ac5774c..535603a 100644
--- a/dijit/themes/tundra/Dialog.css
+++ b/dijit/themes/tundra/Dialog.css
@@ -1,32 +1,35 @@
+/* Dialog and Tooltip/TooltipDialog */
 
 .tundra .dijitDialog {
 	background: #fff;
 	border: 1px solid #7eabcd;
-	
 	padding: 0px;
 	-webkit-box-shadow: 0px 5px 10px #adadad;
 }
-.tundra .dijitDialog .dijitDialogPaneContent {
+
+.tundra .dijitDialogPaneContent {
 	background: #fff;
-	border:none;
-	border-top: 1px solid #d3d3d3; 
+	border-top: 1px solid #d3d3d3;
 	padding:10px;
+
 }
+
 .tundra .dijitDialogTitleBar {
-	
+	/* outer container for the titlebar of the dialog */
 	background: #fafafa url("images/titleBar.png") repeat-x top left;
 	padding: 5px 6px 3px 6px;
-	cursor: move;
-	outline:0; 
+	outline:0; /* remove this line if keyboard focus on dialog startup is an issue. tab still takes you to first focusable element */
 }
+
 .tundra .dijitDialogTitle {
-	
+	/* typography and styling of the dialog title */
 	font-weight: bold;
 	padding: 0px 4px;
 }
+
 .tundra .dijitDialogCloseIcon {
-	
-	
+	/* the default close icon for the dialog */
+	/* background : url("images/spriteRoundedIconsSmall.png") no-repeat right top; */
 	background: url("images/tabClose.png") no-repeat right top;
 	position: absolute;
 	vertical-align: middle;
@@ -34,62 +37,75 @@
 	top: 4px;
 	height: 15px;
 	width: 15px;
-	cursor: pointer;
 }
 .dj_ie6 .tundra .dijitDialogCloseIcon {
 	background : url("images/tabClose.gif") no-repeat right top;
 }
-.tundra .dijitDialogCloseIcon-hover {
+
+.tundra .dijitDialogCloseIconHover {
 	background: url("images/tabCloseHover.png") no-repeat right top;
 }
-.dj_ie6 .tundra .dijitDialogCloseIcon-hover {
+.dj_ie6 .tundra .dijitDialogCloseIconHover {
 	background : url("images/tabCloseHover.gif") no-repeat right top;
 }
+
+/* Tooltip and TooltipDialog */
+
 .tundra .dijitTooltip,
 .tundra .dijitTooltipDialog {
-	
-	background: transparent;	
+	/* the outermost dom node, holding the connector and container */
+	background: transparent;	/* make the area on the sides of the arrow transparent */
 }
+
 .dijitTooltipBelow {
-	
+	/* leave room for arrow above content */
 	padding-top: 13px;
 }
+
 .dijitTooltipAbove {
-	
+	/* leave room for arrow below content */
 	padding-bottom: 13px;
 }
+
 .tundra .dijitTooltipContainer {
-	
+	/*
+		The part with the text.
+	*/
 	background: #ffffff url("images/popupMenuBg.gif") repeat-x bottom left;
 	border: 1px solid #7eabcd;
 	padding: 0.45em;
 	-webkit-border-radius: 3px;
 	-moz-border-radius: 3px;
 }
+
 .tundra .dijitTooltipConnector {
-	
+	/* the arrow piece */
 	border:0px;
 	z-index: 2;
 }
 .tundra .dijitTooltipABRight .dijitTooltipConnector {
-	
+	/* above or below tooltip, but the arrow appears on the right,
+		and the right edges of target and tooltip are aligned rather than the left */
 	left: auto !important;
 	right: 3px;
 }
+
 .tundra .dijitTooltipBelow .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips below an element */
 	top: 0px;
 	left: 3px;
 	background:url("images/tooltipConnectorUp.png") no-repeat top left;
 	width:16px;
 	height:14px;
 }
+
 .dj_ie .tundra .dijitTooltipBelow .dijitTooltipConnector {
-	
+	/* use gif for IE7 too, due to png rendering problems on fade-in (see http://trac.dojotoolkit.org/ticket/6555) */
 	background-image: url("images/tooltipConnectorUp.gif");
 }
+
 .tundra .dijitTooltipAbove .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips above an element */
 	bottom: 0px;
 	left: 3px;
 	background:url("images/tooltipConnectorDown.png") no-repeat top left;
@@ -102,6 +118,7 @@
 .dj_ie6 .tundra .dijitTooltipAbove .dijitTooltipConnector {
 	bottom: -3px;
 }
+
 .tundra .dijitTooltipLeft {
 	padding-right: 14px;
 }
@@ -109,7 +126,7 @@
 	padding-left: 15px;
 }
 .tundra .dijitTooltipLeft .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips to the left of an element, bottom borders aligned */
 	right: 0px;
 	bottom: 3px;
 	background:url("images/tooltipConnectorRight.png") no-repeat top left;
@@ -119,11 +136,12 @@
 .dj_ie .tundra .dijitTooltipLeft .dijitTooltipConnector {
 	background-image: url("images/tooltipConnectorRight.gif");
 }
+
 .tundra .dijitTooltipRight {
 	padding-left: 14px;
 }
 .tundra .dijitTooltipRight .dijitTooltipConnector {
-	
+	/* the arrow piece for tooltips to the right of an element, bottom borders aligned */
 	left: 0px;
 	bottom: 3px;
 	background:url("images/tooltipConnectorLeft.png") no-repeat top left;
@@ -133,8 +151,7 @@
 .dj_ie .tundra .dijitTooltipRight .dijitTooltipConnector {
 	background-image: url("images/tooltipConnectorLeft.gif");
 }
-.dj_webkit .tundra .dijitPopup .dijitTooltipContainer,
-.dj_webkit .tundra .dijitPopup .dijitMenu {
-	
+
+.dj_webkit .tundra .dijitTooltipContainer {
 	-webkit-box-shadow: 0px 5px 10px #adadad;
 }
diff --git a/dijit/themes/tundra/Dialog_rtl.css b/dijit/themes/tundra/Dialog_rtl.css
index a7fd88b..9337680 100644
--- a/dijit/themes/tundra/Dialog_rtl.css
+++ b/dijit/themes/tundra/Dialog_rtl.css
@@ -1,5 +1,5 @@
-
-.dijitRtl .tundra .dijitDialogTitleBar .dijitDialogCloseIcon {
+/* Dialog */
+.tundra .dijitDialogRtl .dijitDialogCloseIcon {
 	right: auto;
 	left: 5px;
 }
diff --git a/dijit/themes/tundra/Editor.css b/dijit/themes/tundra/Editor.css
index a6f4ecb..b6f07a1 100644
--- a/dijit/themes/tundra/Editor.css
+++ b/dijit/themes/tundra/Editor.css
@@ -1,65 +1,16 @@
-.dijitIEFixedToolbar {
-	position:absolute;
-	
-	top: expression(eval((document.documentElement||document.body).scrollTop));
-}
-.tundra .dijitToolbar .dijitToolbarSeparator {
-	background: url('images/editor.gif');
+.dijitEditor {
+	border:1px solid #bfbfbf;
+	border-top:0;
 }
+
 .tundra .dijitEditorIcon {
-	background-image: url('images/editor.gif'); 
+	background-image: url('../../icons/images/editorIconsEnabled.png'); /* editor icons sprite image - enabled state */
 	background-repeat: no-repeat;
 	width: 18px;
 	height: 18px;
 	text-align: center;
 }
 .tundra .dijitDisabled .dijitEditorIcon {
-	background-image: url('images/editorDisabled.gif'); 
+	background-image: url('../../icons/images/editorIconsDisabled.png'); /* editor icons sprite image - disabled state */
 }
-.tundra .dijitEditorIconSep { background-position: 0px; }
-.tundra .dijitEditorIconBackColor { background-position: -18px; }
-.tundra .dijitEditorIconBold { background-position: -36px; }
-.tundra .dijitEditorIconCancel { background-position: -54px; }
-.tundra .dijitEditorIconCopy { background-position: -72px; }
-.tundra .dijitEditorIconCreateLink { background-position: -90px; }
-.tundra .dijitEditorIconCut { background-position: -108px; }
-.tundra .dijitEditorIconDelete { background-position: -126px; }
-.tundra .dijitEditorIconForeColor { background-position: -144px; }
-.tundra .dijitEditorIconHiliteColor { background-position: -162px; }
-.tundra .dijitEditorIconIndent { background-position: -180px; }
-.tundra .dijitEditorIconInsertHorizontalRule { background-position: -198px; }
-.tundra .dijitEditorIconInsertImage { background-position: -216px; }
-.tundra .dijitEditorIconInsertOrderedList { background-position: -234px; }
-.tundra .dijitEditorIconInsertTable { background-position: -252px; }
-.tundra .dijitEditorIconInsertUnorderedList { background-position: -270px; }
-.tundra .dijitEditorIconItalic { background-position: -288px; }
-.tundra .dijitEditorIconJustifyCenter { background-position: -306px; }
-.tundra .dijitEditorIconJustifyFull { background-position: -324px; }
-.tundra .dijitEditorIconJustifyLeft { background-position: -342px; }
-.tundra .dijitEditorIconJustifyRight { background-position: -360px; }
-.tundra .dijitEditorIconLeftToRight { background-position: -378px; }
-.tundra .dijitEditorIconListBulletIndent { background-position: -396px; }
-.tundra .dijitEditorIconListBulletOutdent { background-position: -414px; }
-.tundra .dijitEditorIconListNumIndent { background-position: -432px; }
-.tundra .dijitEditorIconListNumOutdent { background-position: -450px; }
-.tundra .dijitEditorIconOutdent { background-position: -468px; }
-.tundra .dijitEditorIconPaste { background-position: -486px; }
-.tundra .dijitEditorIconRedo { background-position: -504px; }
-.tundra .dijitEditorIconRemoveFormat { background-position: -522px; }
-.tundra .dijitEditorIconRightToLeft { background-position: -540px; }
-.tundra .dijitEditorIconSave { background-position: -558px; }
-.tundra .dijitEditorIconSpace { background-position: -576px; }
-.tundra .dijitEditorIconStrikethrough { background-position: -594px; }
-.tundra .dijitEditorIconSubscript { background-position: -612px; }
-.tundra .dijitEditorIconSuperscript { background-position: -630px; }
-.tundra .dijitEditorIconUnderline { background-position: -648px; }
-.tundra .dijitEditorIconUndo { background-position: -666px; }
-.tundra .dijitEditorIconWikiword { background-position: -684px; }
-.tundra .dijitEditorIconToggleDir { background-position: -540px; }
-.tundra .dijitEditorIconTabIndent { background-position: -702px; }
-.tundra .dijitEditorIconSelectAll { background-position: -720px; }
-.tundra .dijitEditorIconUnlink { background-position: -738px; }
-.tundra .dijitEditorIconFullScreen { background-position: -756px; }
-.tundra .dijitEditorIconViewSource { background-position: -774px; }
-.tundra .dijitEditorIconPrint { background-position: -792px; }
-.tundra .dijitEditorIconNewPage { background-position: -810px; }
+
diff --git a/dijit/themes/tundra/Editor_rtl.css b/dijit/themes/tundra/Editor_rtl.css
index 0ac4885..cd4849e 100644
--- a/dijit/themes/tundra/Editor_rtl.css
+++ b/dijit/themes/tundra/Editor_rtl.css
@@ -1,10 +1,7 @@
-
-.dijitRtl .tundra .dijitEditorIcon {
-	background-image: url('images/editor_rtl.gif'); 
+/* Editor */
+.tundra .dijitEditorRtl .dijitEditorIcon {
+	background-image: url('../../icons/images/editorIconsEnabled_rtl.png'); /* editor icons sprite image - enabled state */
 }
-.dijitRtl .tundra .dijitDisabled .dijitEditorIcon {
-	background-image: url('images/editorDisabled_rtl.gif'); 
-}
-.dijitRtl .tundra .dijitToolbar .dijitToolbarSeparator {
-	background-image: url('images/editor_rtl.gif');
+.tundra .dijitEditorRtlDisabled .dijitEditorIcon {
+	background-image: url('../../icons/images/editorIconsDisabled_rtl.png'); /* editor icons sprite image - disabled state  */
 }
diff --git a/dijit/themes/tundra/Menu.css b/dijit/themes/tundra/Menu.css
index 172b547..ff1e640 100644
--- a/dijit/themes/tundra/Menu.css
+++ b/dijit/themes/tundra/Menu.css
@@ -4,34 +4,41 @@
 	margin: 0px;
 	padding: 0px;
 	background-color: #f7f7f7;
-	
 }
+
 .tundra .dijitBorderContainer .dijitMenuBar {
 	border:1px solid #ccc;
 }
+
 .tundra .dijitMenuItem {
 	font-family: sans-serif;
 	margin: 0;
 }
-.tundra .dijitMenuBar .dijitMenuItem {
+
+.tundra .dijitMenuItem {
 	padding: 4px 5px;
 }
+
 .tundra .dijitMenuPreviousButton, .tundra .dijitMenuNextButton {
 	font-style: italic;
 }
 .tundra .dijitMenuItem td {
 	padding: 2px;
 }
+
 .tundra .dijitMenuPassive .dijitMenuItemHover,
 .tundra .dijitMenuItemSelected {
 	background-color: #3559ac;
 	color:#fff;
 }
+
 .tundra .dijitMenuItemIcon {
 	width: 16px;
 	height: 16px;
 }
+
 .tundra .dijitMenuExpand {
+	/* arrow to indicate this MenuItem opens a sub-menu */
 	width: 7px;
 	height: 7px;
 	background-image: url('images/spriteArrows.png');
@@ -40,22 +47,30 @@
 .dj_ie6 .tundra .dijitMenuExpand {
 	background-image: url('images/spriteArrows.gif');
 }
+
+/* separator can be two pixels -- set border of either one to 0px to have only one */
 .tundra .dijitMenuSeparatorTop {
 	border-bottom: 1px solid #9b9b9b;
 }
+
 .tundra .dijitMenuSeparatorBottom {
 	border-top: 1px solid #e8e8e8;
 }
+
+/* the checked menu item */
 .tundra .dijitCheckedMenuItemIconChar {
 	display: none;
 }
+
 .tundra .dijitCheckedMenuItemIcon {
 	background-image: url('images/checkmark.png');
 	background-position: -80px;
 }
+
 .dj_ie6 .tundra .dijitCheckedMenuItemIcon {
 	background-image: url('images/checkmark.gif');
 }
+
 .tundra .dijitCheckedMenuItemChecked .dijitCheckedMenuItemIcon {
 	background-position: -64px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/tundra/Menu_rtl.css b/dijit/themes/tundra/Menu_rtl.css
index 6d64c87..0e7fbbe 100644
--- a/dijit/themes/tundra/Menu_rtl.css
+++ b/dijit/themes/tundra/Menu_rtl.css
@@ -1,7 +1,3 @@
-.dijitRtl .tundra .dijitMenuItem .dijitMenuItemIcon {
-	padding-left: 3px;
-	padding-right: 0px;
-}
-.dijitRtl .tundra .dijitMenuItem .dijitMenuExpand {
+.tundra .dijitMenuItemRtl .dijitMenuExpand {
 	background-position: -7px 0px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/tundra/ProgressBar.css b/dijit/themes/tundra/ProgressBar.css
index 3f555c42..5b8a118 100644
--- a/dijit/themes/tundra/ProgressBar.css
+++ b/dijit/themes/tundra/ProgressBar.css
@@ -1,23 +1,28 @@
 .tundra .dijitProgressBar {
 	margin:2px 0px 2px 0px;
 }
+
 .tundra .dijitProgressBarEmpty {
-	
+	/* outer container and background of the bar that's not finished yet*/
 	background:#fff url("images/progressBarEmpty.png") repeat-x center center;
 	border-color: #a2a2a2 #b8b8b8 #b8b8b8 #a2a2a2;
 }
+
 .tundra .dijitProgressBarTile {
-	
+	/* inner container for finished portion when in 'tile' (image) mode */
 	background:#f0f0f0 url("images/progressBarFull.png") repeat-x center center;
 }
+
 .tundra .dijitProgressBarFull {
 	border-right:1px solid #b8b8b8;
 }
+
 .tundra .dijitProgressBarLabel {
-	
+	/* Set to a color that contrasts with both the "Empty" and "Full" parts. */
 	color:#293a4b;
 }
+
 .tundra .dijitProgressBarIndeterminate .dijitProgressBarTile {
-	
+	/* use an animated gif for the progress bar in 'indeterminate' mode */
 	background:#cad2de url("images/progressBarAnim.gif") repeat-x center center;
 }
diff --git a/dijit/themes/tundra/TimePicker.css b/dijit/themes/tundra/TimePicker.css
index 0129fa1..13dc7f8 100644
--- a/dijit/themes/tundra/TimePicker.css
+++ b/dijit/themes/tundra/TimePicker.css
@@ -1,50 +1,52 @@
-
+/* Time Picker */
 .tundra .dijitTimePickerTick,
 .tundra .dijitTimePickerMarker {
 	border-color: #ccc;
 }
+
 .tundra .dijitTimePickerTick {
 	color:white;
 }
+
 .tundra .dijitTimePickerMarker {
 	background:#d3d3d3 url("images/titleBar.png") repeat-x top;
 	color:#293a4b;
 	font-weight: bold;
 }
+
 .tundra .dijitTimePickerItemSelected {
 	color: black;
 	background: #bbc4d0 none;
 }
+
 .tundra .dijitTimePickerItemHover {
 	background: #60a1ea none;
 	color:white;
 }
+
 .tundra .dijitTimePickerItemHover,
 .tundra .dijitTimePickerItemSelected {
 	position: relative;
 	z-index: 10;
 }
+
 .tundra .dijitTimePickerTick .dijitTimePickerItemInner {
 	font-size:0.4em;
 }
+
 .tundra .dijitTimePickerItemHover .dijitTimePickerItemInner,
 .tundra .dijitTimePickerItemSelected .dijitTimePickerItemInner {
 	font-size:1em;
 }
+
 .tundra .dijitTimePickerMarkerHover {
 	border-top: 1px solid #ccc;
 }
+
 .tundra .dijitTimePickerTickHover,
 .tundra .dijitTimePickerTickSelected {
 	margin-top:-0.3em;
 	margin-bottom:-0.3em;
 	border-bottom: none;
 }
-.dijit_a11y .dijitTimePickerTickHover {
-	background-color: #CCC !important;
-	border-top: 1px solid #333 !important;
-	border-bottom: 1px solid #333 !important;
-}
-.dijit_a11y .dijitTimePickerMarkerHover {
-	border-bottom-width: 2px;
-}
+
diff --git a/dijit/themes/tundra/TimePicker_rtl.css b/dijit/themes/tundra/TimePicker_rtl.css
new file mode 100644
index 0000000..da923d9
--- /dev/null
+++ b/dijit/themes/tundra/TimePicker_rtl.css
@@ -0,0 +1,4 @@
+ .dj_ie6 .tundra .dijitTimePickerRtl .dijitTimePickerMarkerHover,
+.dj_ie7 .tundra .dijitTimePickerRtl .dijitTimePickerMarkerHover {
+        border-top: 0px; /* IE6/7 bug causes mouseover/out event storm */
+}
diff --git a/dijit/themes/tundra/TitlePane.css b/dijit/themes/tundra/TitlePane.css
index 3fc2433..141cc4b 100644
--- a/dijit/themes/tundra/TitlePane.css
+++ b/dijit/themes/tundra/TitlePane.css
@@ -4,59 +4,35 @@
 	border:1px solid #bfbfbf;
 	padding:3px 4px;
 }
-.tundra .dijitTitlePaneTitle-hover  {
+.tundra .dijitTitlePaneTitleHover  {
 	background: #f8fafd url("images/accordionItemHover.gif") bottom repeat-x;
-	cursor: pointer;
 }
-.tundra .dijitTitlePaneTitle * {
-	vertical-align: middle;
-}
-.tundra .dijitTitlePane .dijitOpen .dijitArrowNode,
-.tundra .dijitTitlePane .dijitClosed .dijitArrowNode {
+
+.tundra .dijitTitlePane .dijitArrowNode {
 	background-image: url('images/spriteArrows.png');
 	background-repeat: no-repeat;
+	background-position: 0px 0px;
 	height: 7px;
 	width: 7px;
 }
 .dj_ie6 .tundra .dijitTitlePane .dijitArrowNode {
 	background-image: url('images/spriteArrows.gif');
 }
-.tundra .dijitTitlePane .dijitOpen .dijitArrowNode {
-	background-position: 0px 0px;
-}
+
 .tundra .dijitTitlePane .dijitClosed .dijitArrowNode {
 	background-position: -14px 0px;
 }
-.tundra .dijitTitlePaneFocused .dijitTitlePaneTextNode {
-	text-decoration:underline;
-}
-.tundra .dijitTitlePane .dijitArrowNodeInner {
-	
-	display:none;
-}
-.dijit_a11y .dijitTitlePane .dijitOpen .dijitArrowNodeInner,
-.dijit_a11y .dijitTitlePane .dijitClosed .dijitArrowNodeInner {
-	display:inline !important;
-	font-family:monospace;
-	padding-bottom:.2em;
-}
-.dijit_a11y .dijitTitlePane .dijitArrowNode {
-	
-	display:none;
-}
+
 .tundra .dijitTitlePaneContentOuter {
 	background: #ffffff;
 	border:1px solid #bfbfbf;
-	border-top: 1px solid #ccc;	
+	border-top: 0px;
 }
 .tundra .dijitTitlePaneContentInner {
 	padding:10px;
 }
-.dj_ie6 .tundra .dijitTitlePaneContentOuter,
-.dj_ie6 .tundra .dijitTitlePane .dijitTitlePaneTitle {
-	zoom: 1;
-}
+
 .tundra .dijitTitlePaneTextNode {
 	margin-left: 4px;
 	margin-right: 4px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/tundra/TitlePane_rtl.css b/dijit/themes/tundra/TitlePane_rtl.css
index a99135d..e4b082d 100644
--- a/dijit/themes/tundra/TitlePane_rtl.css
+++ b/dijit/themes/tundra/TitlePane_rtl.css
@@ -1,3 +1,3 @@
-.dijitRtl .tundra .dijitTitlePane .dijitClosed .dijitArrowNode {
+.tundra .dijitTitlePaneRtl .dijitClosed .dijitArrowNode {
 	background-position: -7px 0px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/tundra/Toolbar.css b/dijit/themes/tundra/Toolbar.css
index bbb7cdb..2e6420f 100644
--- a/dijit/themes/tundra/Toolbar.css
+++ b/dijit/themes/tundra/Toolbar.css
@@ -2,9 +2,12 @@
 	border-bottom: 1px solid #ccc;
 	background:#eaeaea url("images/titleBar.png") repeat-x top left;
 }
+
+/* setting a min-height on ditor toolbar */
 .dj_ie6 .tundra .dijitToolbar {
 	height: 10px;
 }
+
 .tundra .dijitToolbar .dijitButtonNode,
 .tundra .dijitToolbar .dijitComboButton .dijitButtonContents,
 .tundra .dijitToolbar .dijitComboButton .dijitDownArrowButton {
@@ -14,6 +17,7 @@
 	border: none;
 	font-size: 12px;
 }
+
 .tundra .dijitToolbar .dijitButton,
 .tundra .dijitToolbar .dijitToggleButton,
 .tundra .dijitToolbar .dijitDropDownButton,
@@ -22,35 +26,50 @@
 	background: none;
 	padding: 1px;
 }
+
 .tundra .dijitToolbar .dijitButtonChecked,
 .tundra .dijitToolbar .dijitToggleButtonChecked {
 	background-color:#d4dff2;
 	border:1px solid #316ac5;
-	padding: 0px;	
+	padding: 0px;	/* reduce padding to compensate for space taken by border */
 }
+
 .tundra .dijitToolbar .dijitButtonCheckedHover,
 .tundra .dijitToolbar .dijitToggleButtonCheckedHover
  {
 	background-color:#abc1e5;
 	border:1px solid #316ac5;
-	padding: 0px;	
+	padding: 0px;	/* reduce padding to compensate for space taken by border */
 }
+
 .tundra .dijitToolbar .dijitButtonHover,
 .tundra .dijitToolbar .dijitToggleButtonHover,
 .tundra .dijitToolbar .dijitDropDownButtonHover,
-.tundra .dijitToolbar .dijitComboButtonHover .dijitButtonContents,
-.tundra .dijitToolbar .dijitComboButtonDownArrowHover .dijitDownArrowButton {
-	
+.tundra .dijitToolbar .dijitComboButton .dijitButtonContentsHover,
+.tundra .dijitToolbar .dijitComboButton .dijitDownArrowButtonHover {
+	/* TODO: change this from Hover to Selected so that button is still highlighted while drop down is being used */
 	border: 1px solid #869cbf;
-	padding: 0px;	
+	padding: 0px;	/* reduce padding to compensate for space taken by border */
 	background-color:#e1e5f0;
 }
+
 .tundra .dijitToolbar label {
 	padding: 3px 3px 0 6px;
 }
+
 .dj_ie .tundra .dijitToolbar .dijitComboButton .dijitButtonContentsFocused,
 .dj_ie .tundra .dijitToolbar .dijitComboButton .dijitDownArrowButtonFocused {
-	
+	/* focus border doesn't appear on <td> for IE, so need to add it manually */
 	border: 1px #555 dotted !important;
 	padding: 0px;
 }
+
+.tundra .dijitToolbarSeparator {
+	/* separator icon in the editor sprite */
+	background: url('../../icons/images/editorIconsEnabled.png');
+}
+
+.tundra .dijitToolbarRtl .dijitToolbarSeparator {
+	/* separator icon in the editor sprite */
+	background-image: url('../../icons/images/editorIconsDisabled.png');
+}
diff --git a/dijit/themes/tundra/Tree.css b/dijit/themes/tundra/Tree.css
index d6dc5a5..76c81e0 100644
--- a/dijit/themes/tundra/Tree.css
+++ b/dijit/themes/tundra/Tree.css
@@ -1,85 +1,96 @@
+/* Tree */
 
 .tundra .dijitTreeNode {
     background-image : url('images/i.gif');
     background-repeat : repeat-y;
-    zoom: 1;	
+    zoom: 1;	/* force layout on IE (TODO: may not be needed anymore) */
 }
+
+/* left vertical line (grid) for all nodes */
 .tundra .dijitTreeIsLast {
     background: url('images/i_half.gif') no-repeat;
 }
+
 .tundra .dijitTreeIsRoot {
     margin-left: 0;
     background-image: none;
 }
+
 .tundra .dijitTreeExpando {
     width: 18px;
     height: 18px;
 }
+
 .tundra .dijitTreeRow {
-	
+	/* so insert line shows up on IE when dropping after a target element */
 	padding-bottom: 2px;
 }
+
 .tundra .dijitTreeContent {
     min-height: 18px;
     min-width: 18px;
- }
-.tundra .dijitTreeExpand {
-    width: 18px;
-    height: 18px;
-    background-repeat : no-repeat;
-}
-.tundra .dijitTreeNodeEmphasized {
-    background-color: Highlight;
-    color: HighlightText;
-}
-.tundra .dijitTreeLabelFocused {
-	outline: 1px invert dotted;
 }
-.tundra .dijitTreeNodeSelected .dijitTreeLabel {
+
+.tundra .dijitTreeRowSelected .dijitTreeLabel {
 	background:#e2ebfe;
 }
-.tundra .dijitTreeNodeHover {
-	
-	
+.tundra .dijitTreeRowHover {
+	/* using a transparent png so that we can still see grid lines, which are (unfortunately) behind the dijitRowNode that we are hovering over */
 	background-image: url(images/treeHover.png);
 	background-repeat: repeat;
-	background-color: none !important;
+	background-color: transparent !important;
 }
+
 .tundra .dijitTreeExpandoOpened {
 	background-image: url('images/treeExpand_minus.gif');
 }
+
 .tundra .dijitTreeExpandoClosed {
 	background-image: url('images/treeExpand_plus.gif');
 }
+
 .tundra .dijitTreeExpandoLeaf {
 	background-image: url('images/treeExpand_leaf.gif');
 }
+
 .tundra .dijitTreeExpandoLoading {
 	background-image: url('images/treeExpand_loading.gif');
 }
+
 .tundra .dijitTreeIcon {
 	width: 16px;
 	height: 16px;
 }
+
 .tundra .dijitFolderOpened {
 	background: url('images/folderOpened.gif') no-repeat;
 }
+
 .tundra .dijitFolderClosed {
 	background: url('images/folderClosed.gif') no-repeat;
 }
+
 .tundra .dijitLeaf {
 	background: url('images/leaf.gif') no-repeat;
 }
+
+/* Drag and Drop on TreeNodes
+ * Put insert line on dijitTreeContent node so it's aligned w/
+ * (ie, indented equally with) target element, even
+ * though dijitTreeRowNode is the actual "drag object"
+ */
 .tundra .dijitTreeNode .dojoDndItemBefore,
 .tundra .dijitTreeNode .dojoDndItemAfter {
 	border-bottom: none;
 	border-top: none;
 }
+
 .tundra .dijitTreeNode .dojoDndItemBefore .dijitTreeContent {
-	
+	/* copied from Common.css */
 	border-top: 2px solid #369;
 }
+
 .tundra .dijitTreeNode .dojoDndItemAfter .dijitTreeContent {
-	
+	/* copied from Common.css */
 	border-bottom: 2px solid #369;
 }
diff --git a/dijit/themes/tundra/Tree_rtl.css b/dijit/themes/tundra/Tree_rtl.css
index 1a7c938..607b71c 100644
--- a/dijit/themes/tundra/Tree_rtl.css
+++ b/dijit/themes/tundra/Tree_rtl.css
@@ -1,13 +1,17 @@
+/* Tree */
 
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeNode {
-    background-image : none;
+.tundra .dijitTreeNodeRtl,
+.tundra .dijitTreeNodeRtl .dijitTreeExpandoLeaf {
+	/* disable grid lines in RTL mode; too hard to support */
+    background-image: none;
 }
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeExpandoOpened {
+
+.tundra .dijitTreeNodeRtl .dijitTreeExpandoOpened {
+	/* todo: get rid of transparent space in icon files,
+		and just use background-placement (or margin maybe) to get desired alignment */
 	background-image: url('images/treeExpand_minus_rtl.gif');
 }
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeExpandoClosed {
+
+.tundra .dijitTreeNodeRtl .dijitTreeExpandoClosed {
 	background-image: url('images/treeExpand_plus_rtl.gif');
 }
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeExpandoLeaf {
-	background-image: none;
-}
diff --git a/dijit/themes/tundra/form/Button.css b/dijit/themes/tundra/form/Button.css
index 8617f37..fe307fe 100644
--- a/dijit/themes/tundra/form/Button.css
+++ b/dijit/themes/tundra/form/Button.css
@@ -1,89 +1,91 @@
 
+/*****
+		dijit.form.Button
+		dijit.form.DropDownButton
+		dijit.form.ComboButton
+		dijit.form.ComboBox (partial)
+		dijit.form.Spinner (partial) (TODO: create NumberSpinner.css file like claro has)
+ *****/
+
 .tundra .dijitButtonNode {
-	
+	/* enabled state - inner */
 	border: 1px solid #c0c0c0;
 	border-bottom: 1px solid #9b9b9b;
 	padding: 0.1em 0.2em 0.2em 0.2em;
 	background: #fff url("../images/buttonEnabled.png") repeat-x bottom left;
 }
-.tundra .dijitSelect .dijitButtonContents {
-	border-right: none;
-}
-.dijitRtl .tundra .dijitSelect .dijitButtonContents {
-	border-left: none;
-	border-right-width: 1px;
-}
-.tundra .dijitButtonNode button {
-	border: 0px;
-	background-color: transparent;
-}
 .tundra .dijitButtonText {
 	text-align: center;
 	padding: 0 0.3em;
 }
+
 .tundra .dijitDisabled .dijitButtonText {
 	color: #7F7F7F;
 }
+
 .tundra .dijitArrowButton {
 	color: #111;
 }
+
 .tundra .dijitComboButton .dijitDownArrowButton {
 	padding-right:4px;
 }
-.tundra .dijitComboBoxReadOnly,
-.tundra .dijitSpinnerReadOnly,
-.tundra .dijitSpinnerReadOnly .dijitButtonNode,
+
+.tundra .dijitTextBoxReadOnly,
+.tundra .dijitTextBoxReadOnly .dijitButtonNode,
 .tundra .dijitButtonDisabled .dijitButtonNode,
 .tundra .dijitToggleButtonDisabled .dijitButtonNode,
 .tundra .dijitDropDownButtonDisabled .dijitButtonNode,
 .tundra .dijitComboButtonDisabled .dijitButtonNode,
-.tundra .dijitComboBoxDisabled,
-.tundra .dijitSpinnerDisabled,
-.tundra .dijitSpinnerDisabled .dijitButtonNode {
-	
-	
+.tundra .dijitTextBoxDisabled,
+.tundra .dijitTextBoxDisabled .dijitButtonNode {
+	/* disabled state - inner */
 	border-color: #d5d5d5 #d5d5d5 #bdbdbd #d5d5d5;
 	background:#e4e4e4 url("../images/buttonDisabled.png") top repeat-x;
 }
+
 .tundra .dijitButtonHover .dijitButtonNode,
 .tundra .dijitButtonNodeHover,
 .tundra .dijitToggleButtonHover .dijitButtonNode,
 .tundra .dijitDropDownButtonHover .dijitButtonNode,
-.tundra .dijitComboButtonHover .dijitButtonContents,
-.tundra .dijitComboButtonDownArrowHover .dijitArrowButton {
-	
-	
+.tundra .dijitComboButton .dijitButtonContentsHover,
+.tundra .dijitComboButton .dijitDownArrowButtonHover {
+	/* hover state - inner */
+	/* TODO: change from Hover to Selected so that button is still highlighted while drop down is being used */
 	border-color: #a5beda;
 	border-bottom-color:#5c7590;
 	color:#243C5F;
 	background:#fcfdff url("../images/buttonHover.png") repeat-x bottom;
 }
-.tundra .dijitComboBoxHover .dijitDownArrowButton,
-.tundra .dijitSpinnerUpArrowHover .dijitUpArrowButton,
-.tundra .dijitSpinnerDownArrowHover .dijitDownArrowButton {
-	
+.tundra .dijitDownArrowButtonHover,
+.tundra .dijitUpArrowButtonHover {
+	/* same as above except don't adjust border color (it's controlled by the containing Spinner/ComboBox) */
 	color:#243C5F;
 	background:#fcfdff url("../images/buttonHover.png") repeat-x bottom;
 }
-.tundra .dijitSpinnerUpArrowActive .dijitUpArrowButton,
-.tundra .dijitSpinnerDownArrowActive .dijitDownArrowButton,
+
+.tundra .dijitUpArrowButtonActive,
+.tundra .dijitDownArrowButtonActive,
 .tundra .dijitButtonActive .dijitButtonNode,
 .tundra .dijitToggleButtonActive .dijitButtonNode,
 .tundra .dijitDropDownButtonActive .dijitButtonNode,
-.tundra .dijitComboButtonActive .dijitButtonContents,
-.tundra .dijitDownArrowActive .dijitDownArrowButton,
-.tundra .dijitComboBoxActive .dijitDownArrowButton,
+.tundra .dijitButtonContentsActive,
 .tundra .dijitStackController .dijitToggleButtonChecked .dijitButtonNode {
-	
+	/* active state - inner (for when you are pressing a normal button, or
+	 * when a radio-type button is in a depressed state
+	 */
 	border-color:#366dba;
 	background: #ededed url("../images/buttonActive.png") bottom repeat-x;
 }
+
 .tundra .dijitArrowButtonInner {
 	background:url("../images/spriteArrows.png") no-repeat scroll 0px center;
 	width: 7px;
 	height: 7px;
-	font-size: 1px;
-	margin: 0px 4px 0px 5px;
+	margin: 0px 4px 0px 4px;
+}
+.tundra .dijitTextBox .dijitArrowButtonInner {
+	background-position: 0 center;
 }
 .dj_ie6 .tundra .dijitArrowButtonInner {
 	background-image:url("../images/spriteArrows.gif");
@@ -97,6 +99,7 @@
 .tundra .dijitUpArrowButton .dijitArrowButtonInner {
 	background-position: -21px center;
 }
+
 .tundra .dijitDisabled .dijitArrowButtonInner {
 	background-position: -28px center;
 }
@@ -109,20 +112,25 @@
 .tundra .dijitDisabled .dijitUpArrowButton .dijitArrowButtonInner {
 	background-position: -49px center;
 }
-.tundra .dijitComboBox .dijitArrowButton .dijitArrowButtonInner {
-	height: auto;
-	font-size: 100%;
-	font-size: inherit;
-}
-.tundra .dijitComboBoxHover .dijitArrowButtonInner {
-	
-}
-.tundra .dijitSpinner .dijitArrowButtonInner {
-	display: block;  
-	position:absolute;
-	top: 50%;
-	margin-top: -4px; 
-	left: 50%;
-	margin-left: -4px; 
-	line-height: 2px;
+.dj_webkit .tundra .dijitSpinner .dijitUpArrowButton .dijitArrowButtonInner {
+	margin-top: -1px; /* image has too many blank pixels on top */
+}
+.dj_ie .tundra .dijitSpinner .dijitDownArrowButton .dijitArrowButtonInner {
+	margin-top: -2px; /* image has too many blank pixels on top */
+}
+.dj_ie8 .tundra .dijitSpinner .dijitDownArrowButton .dijitArrowButtonInner {
+	margin-top: -1px; /* image has too many blank pixels on top */
+}
+.tundra .dijitSpinnerButtonContainer {
+	width: auto;
+	padding: 0;
+}
+.tundra .dijitSpinner .dijitArrowButton {
+	width: 15px;
+}
+.tundra .dijitSpinner .dijitSpinnerButtonInner {
+	width: 15px;
+}
+.tundra .dijitSpinner .dijitArrowButtonInner .dijitInputField {
+	padding: 0;
 }
diff --git a/dijit/themes/tundra/form/Checkbox.css b/dijit/themes/tundra/form/Checkbox.css
index e7ff2f9..5a93037 100644
--- a/dijit/themes/tundra/form/Checkbox.css
+++ b/dijit/themes/tundra/form/Checkbox.css
@@ -1,45 +1,54 @@
 .tundra .dijitToggleButton .dijitCheckBoxIcon {
 	background-image: url('../images/checkmarkNoBorder.png');
 }
+
 .dj_ie6 .tundra .dijitToggleButton .dijitCheckBoxIcon {
 	background-image: url('../images/checkmarkNoBorder.gif');
 }
+
 .tundra .dijitCheckBox,
-.tundra .dijitCheckBoxIcon			{
-	background-image: url('../images/checkmark.png'); 
+.tundra .dijitCheckBoxIcon		/* inside a toggle button */	{
+	background-image: url('../images/checkmark.png'); /* checkbox sprite image */
 	background-repeat: no-repeat;
 	width: 16px;
 	height: 16px;
 	margin: 0 2px 0 0;
 	padding: 0;
 }
+
 .dj_ie6 .tundra .dijitCheckBox,
-.dj_ie6 .tundra .dijitCheckBoxIcon			{
-	background-image: url('../images/checkmark.gif'); 
+.dj_ie6 .tundra .dijitCheckBoxIcon		/* inside a toggle button */	{
+	background-image: url('../images/checkmark.gif'); /* checkbox sprite image */
 }
+
 .tundra .dijitCheckBox,
 .tundra .dijitToggleButton .dijitCheckBoxIcon {
-	
+	/* unchecked */
 	background-position: -16px;
 }
+
 .tundra .dijitCheckBoxChecked,
 .tundra .dijitToggleButtonChecked .dijitCheckBoxIcon {
-	
+	/* checked */
 	background-position: 0px;
 }
+
 .tundra .dijitCheckBoxDisabled {
-	
+	/* disabled */
 	background-position: -48px;
 }
+
 .tundra .dijitCheckBoxCheckedDisabled {
-	
+	/* disabled but checked */
 	background-position: -32px;
 }
+
 .tundra .dijitCheckBoxHover {
-	
+	/* hovering over an unchecked enabled checkbox */
 	background-position: -80px;
 }
+
 .tundra .dijitCheckBoxCheckedHover {
-	
+	/* hovering over a checked enabled checkbox */
 	background-position: -64px;
 }
diff --git a/dijit/themes/tundra/form/Common.css b/dijit/themes/tundra/form/Common.css
index c949d1e..1abf817 100644
--- a/dijit/themes/tundra/form/Common.css
+++ b/dijit/themes/tundra/form/Common.css
@@ -1,105 +1,76 @@
 
-.tundra .dijitInputField INPUT,
-.tundra .dijitTextBox,
-.tundra .dijitComboBox,
-.tundra .dijitSpinner {
+/****
+		dijit.form.TextBox
+		dijit.form.ValidationTextBox
+		dijit.form.SerializableTextBox
+		dijit.form.RangeBoundTextBox
+		dijit.form.NumberTextBox
+		dijit.form.CurrencyTextBox
+		dijit.form.NumberSpinner
+		dijit.form.ComboBox (partial)
+ ****/
+
+.tundra .dijitInputContainer INPUT,
+.tundra .dijitTextBox {
 	margin: 0em 0.1em;
 }
-.tundra .dijitTextBox,
-.tundra .dijitComboBox,
-.tundra .dijitSpinner,
-.tundra .dijitTextArea {
-	font-family: sans-serif;
-	font-size: 100%;
-}
+
 .tundra .dijitTextArea {
 	padding: 3px;
 }
-.tundra .dijitTextBox,
-.tundra .dijitComboBox,
-.tundra .dijitSpinner,
-.tundra .dijitTextArea,
-.tundra .dijitInlineEditor input {
-	
+
+.tundra .dijitTextBox {
+	/* 	For all except dijit.form.NumberSpinner:  the actual input element.
+		For TextBox, ComboBox, Spinner: the div that contains the input.
+		Otherwise the actual input element.
+	*/
 	background:#fff url("../images/validationInputBg.png") repeat-x top left;
 	#background:#fff url('../images/validationInputBg.gif') repeat-x top left;
 	border:1px solid #b3b3b3;
-	line-height: normal;
-}
-.tundra .dijitComboBox .dijitInputField {
-	padding: 1px 0;
 }
+
+/* ComboBox specific rules*/
 .tundra .dijitComboBox .dijitButtonNode {
-	padding: 1px 0.2em;
+	padding: 0 0.2em;
 }
-.tundra .dijitComboBox .dijitButtonNode,
-.tundra .dijitSpinner .dijitButtonNode {
-	
+.tundra .dijitTextBox .dijitButtonNode {
+	/* line between the input area and the drop down button, and also between
+	 * the up and down buttons of a spinner
+	 */
 	border-color: #9b9b9b;
-	border-width: 0px 0px 0px 1px;
-	border-style: solid;
 }
-.tundra .dijitTextBoxFocused,
-.tundra .dijitComboBoxFocused,
-.tundra .dijitSpinnerFocused, .tundra .dijitSpinnerUpArrowActive, .tundra .dijitSpinnerDownArrowActive,
-.tundra .dijitTextAreaFocused {
-	
+
+.tundra .dijitTextBoxFocused {
+	/* input field when focused (ie: typing affects it) */
 	border-color:#406b9b;
 }
-.tundra .dijitComboBoxFocused .dijitButtonNode,
-.tundra .dijitSpinnerFocused .dijitButtonNode,
-.tundra .dijitSpinnerUpArrowActive .dijitButtonNode,
-.tundra .dijitSpinnerDownArrowActive .dijitButtonNode {
-	border-left-color:#366dba;
-}
-.tundra .dijitSpinnerFocused .dijitDownArrowButton,
-.tundra .dijitSpinnerUpArrowActive .dijitDownArrowButton,
-.tundra .dijitSpinnerDownArrowActive .dijitDownArrowButton {
-	border-top-color:#366dba;
+.tundra .dijitTextBoxFocused .dijitButtonNode {
+	border-color:#366dba;
 }
+
 .tundra .dijitError {
 	background-color:#f9f7ba;
 	background-image:none;
 }
-.dj_ie6 .tundra .dijitError INPUT {
-	
-	background-color:#f9f7ba !important;
-}
+
 .tundra .dijitErrorFocused {
 	background-color:#f9f999;
 	background-image:none;
 }
-.dj_ie6 .tundra .dijitErrorFocused INPUT {
-	
-	background-color:#f9f999 !important;
-}
+
+/* Validation errors  */
 .tundra .dijitValidationIcon {
-	
+	/* prevent height change when widget goes from valid to invalid state */
 	width: 16px;
 	background: transparent url('../images/warning.png') no-repeat center center;
 }
-.tundra .dijitInlineValue {
-	
-	padding:3px;
-	margin:4px;
-}
-.tundra .dijitInlineEditor {
-	
-	display: inline-block;
-	#display:inline;
-}
-.dijitInlineEditor .saveButton,
-.dijitInlineEditor .cancelButton {
-	margin:3px 3px 3px 0px;
-}
-.RichTextEditable {
-	border:1px solid #bfbfbf;
-	border-top:0;
-}
+
+/* The highlight is shown in the ComboBox menu. */
 .tundra .dijitComboBoxHighlightMatch {
 	background-color:#a5beda;
 }
+
 .tundra .dijitFocusedLabel {
-	
+	/* for checkboxes or radio buttons, hatch border around the corresponding label, to indicate focus */
 	outline: 1px dotted #666666;
 }
diff --git a/dijit/themes/tundra/form/Common_rtl.css b/dijit/themes/tundra/form/Common_rtl.css
deleted file mode 100644
index d1a7f8c..0000000
--- a/dijit/themes/tundra/form/Common_rtl.css
+++ /dev/null
@@ -1,6 +0,0 @@
-.dijitRtl .tundra .dijitComboBox .dijitButtonNode,
-.dijitRtl .tundra .dijitSpinner .dijitButtonNode {
-	
-	border-left-width: 0px;
-	border-right-width: 1px;
-}
diff --git a/dijit/themes/tundra/form/RadioButton.css b/dijit/themes/tundra/form/RadioButton.css
index 0d3b534..4dfc0fa 100644
--- a/dijit/themes/tundra/form/RadioButton.css
+++ b/dijit/themes/tundra/form/RadioButton.css
@@ -1,14 +1,7 @@
-.tundra .dijitToggleButton .dijitRadio,
-.tundra .dijitToggleButton .dijitRadioIcon {
-	background-image: url('../images/checkmarkNoBorder.png');
-}
-.dj_ie6 .tundra .dijitToggleButton .dijitRadio,
-.dj_ie6 .tundra .dijitToggleButton .dijitRadioIcon {
-	background-image: url('../images/checkmarkNoBorder.gif');
-}
-.tundra .dijitRadio,
-.tundra .dijitRadioIcon	{		
-	background-image: url('../images/checkmark.png'); 
+
+.tundra .dijitRadio,			/* stand alone */
+.tundra .dijitRadioIcon	{		/* inside a toggle button */
+	background-image: url('../images/checkmark.png'); /* checkbox sprite image */
 	background-repeat: no-repeat;
 	width: 16px;
 	height: 16px;
@@ -16,29 +9,44 @@
 	padding: 0;
 }
 .dj_ie6 .tundra .dijitRadio,
-.dj_ie6 .tundra .dijitRadioIcon	{		
-	background-image: url('../images/checkmark.gif'); 
+.dj_ie6 .tundra .dijitRadioIcon	{
+	background-image: url('../images/checkmark.gif'); /* checkbox sprite image */
 }
-.tundra .dijitRadio,
+
 .tundra .dijitToggleButton .dijitRadioIcon {
-	
+	/* for checkbox in a toggle button, override above setting to have no border */
+	background-image: url('../images/checkmarkNoBorder.png');
+}
+.dj_ie6 .tundra .dijitToggleButton .dijitRadioIcon {
+	background-image: url('../images/checkmarkNoBorder.gif');
+}
+
+.tundra .dijitRadio,
+.tundra .dijitRadioIcon {
+	/* unselected */
 	background-position: -112px;
 }
+
 .tundra .dijitRadioDisabled {
-	
+	/* unselected and disabled */
 	background-position: -144px;
 }
+
 .tundra .dijitRadioHover {
-	
+	/* hovering over an unselected enabled radio button */
 	background-position: -176px;
 }
+
 .tundra .dijitRadioChecked,
 .tundra .dijitRadioCheckedHover,
 .tundra .dijitToggleButtonChecked .dijitRadioIcon {
-	
+	/* selected.  Since clicking a selected radio button doesn't change anything, there's
+	 * no hover effect on selected radio buttons.
+	 */
 	background-position: -96px;
 }
+
 .tundra .dijitRadioCheckedDisabled {
-	
+	/* selected but disabled */
 	background-position: -128px;
 }
diff --git a/dijit/themes/tundra/form/Select.css b/dijit/themes/tundra/form/Select.css
index fc5092b..a52eb71 100644
--- a/dijit/themes/tundra/form/Select.css
+++ b/dijit/themes/tundra/form/Select.css
@@ -1,17 +1,15 @@
-
-.tundra .dijitSelectDisabled * {
-    cursor: not-allowed !important;
-}
-.tundra .dijitSelectReadOnly * {
-    cursor: default !important;
-}
 .tundra .dijitSelect .dijitButtonNode {
 	padding: 0px;
 }
+.tundra .dijitSelect .dijitButtonNode .dijitArrowButtonInner {
+	margin: 0px 4px 0px 5px;
+}
+
+/* Make unselected content portion "look" more like a text box and less like a button */
 .tundra .dijitSelect .dijitButtonContents {
 	padding-top: 1px;
-    background:#fff url("../images/validationInputBg.png") repeat-x top left;
-    #background:#fff url('../images/validationInputBg.gif') repeat-x top left;
+	background:#fff url("../images/validationInputBg.png") repeat-x top left;
+	#background:#fff url('../images/validationInputBg.gif') repeat-x top left;
 }
 .tundra .dijitSelectHover .dijitButtonContents,
 .tundra .dijitSelectActive .dijitButtonContents,
@@ -23,33 +21,37 @@
 .dj_ie .tundra .dijitSelect .dijitButtonContents {
 	padding-top: 0px;
 }
+
+/* Mirror DropDownButton */
 .tundra .dijitSelectDisabled .dijitButtonNode {
-    border-color: #d5d5d5 #bdbdbd #bdbdbd #d5d5d5;
-    background:#e4e4e4 url("../images/buttonDisabled.png") top repeat-x;
+	border-color: #d5d5d5 #bdbdbd #bdbdbd #d5d5d5;
+	background:#e4e4e4 url("../images/buttonDisabled.png") top repeat-x;
 }
 .dj_ie .tundra .dijitSelectDisabled  .dijitButtonNode * {
 	filter: gray() alpha(opacity=50);
 }
+
 .tundra .dijitSelectHover .dijitButtonNode {
-    border-color:#a5beda;
-    border-bottom-color:#5c7590;
-    border-right-color:#5c7590;
-    color:#243C5F;
-    background:#fcfdff url("../images/buttonHover.png") repeat-x bottom;
+	border-color:#a5beda;
+	border-bottom-color:#5c7590;
+	border-right-color:#5c7590;
+	color:#243C5F;
+	background:#fcfdff url("../images/buttonHover.png") repeat-x bottom;
 }
+
 .tundra .dijitSelectActive .dijitButtonNode,
 .tundra .dijitSelectOpened .dijitButtonNode {
-    border-color:#366dba;
-    background: #ededed url("../images/buttonActive.png") bottom repeat-x;
+	border-color:#366dba;
+	background: #ededed url("../images/buttonActive.png") bottom repeat-x;
 }
+
+/* Make the menu look more combobox-like */
 .tundra .dijitSelectMenu td {
 	padding: 0em;
 }
-.tundra .dijitSelectMenu .dijitMenuItemIcon {
-	margin: 0.1em 0.2em;
-	display: none;
-}
 .tundra .dijitSelectMenu .dijitMenuItemLabel,
 .tundra .dijitSelectMenu .dijitMenuArrowCell {
 	padding: 0.1em 0.2em;
 }
+
+
diff --git a/dijit/themes/tundra/form/Slider.css b/dijit/themes/tundra/form/Slider.css
index dbb95d7..17c3d6e 100644
--- a/dijit/themes/tundra/form/Slider.css
+++ b/dijit/themes/tundra/form/Slider.css
@@ -2,26 +2,32 @@
 	border-color: #aab0bb;
 	background: #c0c2c5 url("../images/sliderFull.png") repeat-x top left;
 }
+
 .tundra .dijitSliderProgressBarV {
 	border-color: #aab0bb;
 	background: #c0c2c5 url("../images/sliderFullVertical.png") repeat-y bottom left;
 }
+
 .tundra .dijitSliderFocused .dijitSliderProgressBarH,
 .tundra .dijitSliderFocused .dijitSliderLeftBumper {
 	background-image:url("../images/sliderFullFocus.png");
 }
+
 .tundra .dijitSliderFocused .dijitSliderProgressBarV,
 .tundra .dijitSliderFocused .dijitSliderBottomBumper {
 	background-image:url("../images/sliderFullVerticalFocus.png");
 }
+
 .tundra .dijitSliderRemainingBarV {
 	border-color: #b4b4b4;
 	background: #dcdcdc url("../images/sliderEmptyVertical.png") repeat-y bottom left;
 }
+
 .tundra .dijitSliderRemainingBarH {
 	border-color: #b4b4b4;
 	background: #dcdcdc url("../images/sliderEmpty.png") repeat-x top left;
 }
+
 .tundra .dijitSliderBar {
 	border-style: solid;
 	outline:1px;
@@ -29,61 +35,64 @@
 .tundra .dijitSliderFocused .dijitSliderBar {
 	border-color:#888;
 }
-.dijit_a11y .dijitSliderProgressBar {
-	background-color:#888 !important;
-}
+
 .tundra .dijitSliderImageHandleH {
 	border:0px;
 	width:16px;
 	height:16px;
 	background:url("../images/preciseSliderThumb.png") no-repeat center top;
-	cursor:pointer;
 }
 .tundra .dijitSliderFocused .dijitSliderImageHandleH {
 	background-image:url("../images/preciseSliderThumbFocus.png");
 	#background-image:url("../images/preciseSliderThumbFocus.gif");
 }
+
 .dj_ie6 .tundra .dijitSliderImageHandleH {
 	background-image:url("../images/preciseSliderThumb.gif");
 }
+
 .tundra .dijitSliderLeftBumper {
 	border-left-width: 1px;
 	border-color: #aab0bb;
 	background: #c0c2c5 url("../images/sliderFull.png") repeat-x top left;
 }
+
 .tundra .dijitSliderRightBumper {
 	background: #dcdcdc url("../images/sliderEmpty.png") repeat-x top left;
 	border-color: #b4b4b4;
 	border-right-width: 1px;
 }
+
 .tundra .dijitSliderImageHandleV {
 	border:0px;
 	width:16px;
 	height:16px;
 	background:url("../images/sliderThumb.png") no-repeat center center;
-	cursor:pointer;
 }
+
 .tundra .dijitSliderFocused .dijitSliderImageHandleV {
 	background-image:url("../images/sliderThumbFocus.png");
 }
 .dj_ie6 .tundra .dijitSliderFocused .dijitSliderImageHandleV {
 	background-image:url("../images/sliderThumbFocus.gif");
 }
+
 .tundra .dijitSliderBottomBumper {
 	border-bottom-width: 1px;
 	border-color: #aab0bb;
 	background: #c0c2c5 url("../images/sliderFullVertical.png") repeat-y bottom left;
 }
+
 .tundra .dijitSliderTopBumper {
 	background: #dcdcdc url("../images/sliderEmptyVertical.png") repeat-y top left;
 	border-color: #b4b4b4;
 	border-top-width: 1px;
 }
+
 .tundra .dijitSliderDecrementIconH,
 .tundra .dijitSliderDecrementIconV,
 .tundra .dijitSliderIncrementIconH,
 .tundra .dijitSliderIncrementIconV {
-	cursor: pointer;
 	background-image: url('../images/spriteArrows.png');
 	background-repeat: no-repeat;
 	margin: 5px;
@@ -97,6 +106,7 @@
 .dj_ie6 .tundra .dijitSliderIncrementIconV {
 	background-image: url('../images/spriteArrows.gif');
 }
+
 .tundra .dijitSliderDecrementIconH {
 	background-position: -7px 0px;
 }
@@ -109,9 +119,11 @@
 .tundra .dijitSliderIncrementIconV {
 	background-position: -21px 0px;
 }
+
 .tundra .dijitSliderButtonInner {
 	visibility:hidden;
 }
+
 .tundra .dijitSliderReadOnly *,
 .tundra .dijitSliderDisabled * {
 	border-color: #d5d5d5 #bdbdbd #bdbdbd #d5d5d5;
@@ -132,4 +144,4 @@
 .tundra .dijitSliderReadOnly .dijitSliderIncrementIconV,
 .tundra .dijitSliderDisabled .dijitSliderIncrementIconV {
 	background-position: -49px 0px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/tundra/form/Slider_rtl.css b/dijit/themes/tundra/form/Slider_rtl.css
index 90d2b73..e816d7a 100644
--- a/dijit/themes/tundra/form/Slider_rtl.css
+++ b/dijit/themes/tundra/form/Slider_rtl.css
@@ -1,26 +1,31 @@
-.dijitRtl .tundra .dijitSliderProgressBarH,
-.dijitRtl .tundra .dijitSliderRemainingBarH,
-.dijitRtl .tundra .dijitSliderLeftBumper,
-.dijitRtl .tundra .dijitSliderRightBumper,
-.dijitRtl .tundra .dijitSliderTopBumper {
+.tundra .dijitSliderRtl .dijitSliderProgressBarH,
+.tundra .dijitSliderRtl .dijitSliderRemainingBarH,
+.tundra .dijitSliderRtl .dijitSliderLeftBumper,
+.tundra .dijitSliderRtl .dijitSliderRightBumper,
+.tundra .dijitSliderRtl .dijitSliderTopBumper {
 	background-position: top right;
 }
-.dijitRtl .tundra .dijitSliderProgressBarV,
-.dijitRtl .tundra .dijitSliderRemainingBarV,
-.dijitRtl .tundra .dijitSliderBottomBumper {
+
+.tundra .dijitSliderRtl .dijitSliderProgressBarV,
+.tundra .dijitSliderRtl .dijitSliderRemainingBarV,
+.tundra .dijitSliderRtl .dijitSliderBottomBumper {
 	background-position: bottom right;
 }
-.dijitRtl .tundra .dijitSliderLeftBumper {
+
+.tundra .dijitSliderRtl .dijitSliderLeftBumper {
 	border-left-width: 0px;
 	border-right-width: 1px;
 }
-.dijitRtl .tundra .dijitSliderRightBumper {
+
+.tundra .dijitSliderRtl .dijitSliderRightBumper {
 	border-left-width: 1px;
 	border-right-width: 0px;
 }
-.dijitRtl .tundra .dijitSliderIncrementIconH {
+
+.tundra .dijitSliderRtl .dijitSliderIncrementIconH {
 	background-position: -7px 0px;
 }
-.dijitRtl .tundra .dijitSliderDecrementIconH {
+
+.tundra .dijitSliderRtl .dijitSliderDecrementIconH {
 	background-position: -14px 0px;
 }
diff --git a/dijit/themes/tundra/images/checkmark.gif b/dijit/themes/tundra/images/checkmark.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/checkmarkNoBorder.gif b/dijit/themes/tundra/images/checkmarkNoBorder.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/checkmarkNoBorder.png b/dijit/themes/tundra/images/checkmarkNoBorder.png
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/circleIcon.gif b/dijit/themes/tundra/images/circleIcon.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/circleIcon.png b/dijit/themes/tundra/images/circleIcon.png
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/dojoTundraGradientBg.gif b/dijit/themes/tundra/images/dojoTundraGradientBg.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/editor.gif b/dijit/themes/tundra/images/editor.gif
deleted file mode 100644
index 750c6b9..0000000
Binary files a/dijit/themes/tundra/images/editor.gif and /dev/null differ
diff --git a/dijit/themes/tundra/images/editorDisabled.gif b/dijit/themes/tundra/images/editorDisabled.gif
deleted file mode 100644
index e40460d..0000000
Binary files a/dijit/themes/tundra/images/editorDisabled.gif and /dev/null differ
diff --git a/dijit/themes/tundra/images/editorDisabled_rtl.gif b/dijit/themes/tundra/images/editorDisabled_rtl.gif
deleted file mode 100644
index a0f6c10..0000000
Binary files a/dijit/themes/tundra/images/editorDisabled_rtl.gif and /dev/null differ
diff --git a/dijit/themes/tundra/images/editorMaster.png b/dijit/themes/tundra/images/editorMaster.png
deleted file mode 100644
index 2e6772f..0000000
Binary files a/dijit/themes/tundra/images/editorMaster.png and /dev/null differ
diff --git a/dijit/themes/tundra/images/editor_rtl.gif b/dijit/themes/tundra/images/editor_rtl.gif
deleted file mode 100644
index a9740c2..0000000
Binary files a/dijit/themes/tundra/images/editor_rtl.gif and /dev/null differ
diff --git a/dijit/themes/tundra/images/i.gif b/dijit/themes/tundra/images/i.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/i_half.gif b/dijit/themes/tundra/images/i_half.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/loading.gif b/dijit/themes/tundra/images/loading.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/noX.gif b/dijit/themes/tundra/images/noX.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/preciseSliderThumb.gif b/dijit/themes/tundra/images/preciseSliderThumb.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/sliderFullFocus.png b/dijit/themes/tundra/images/sliderFullFocus.png
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/sliderFullVerticalFocus.png b/dijit/themes/tundra/images/sliderFullVerticalFocus.png
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/tabClose.gif b/dijit/themes/tundra/images/tabClose.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/tabCloseHover.gif b/dijit/themes/tundra/images/tabCloseHover.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/tabHover.gif b/dijit/themes/tundra/images/tabHover.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/treeExpand_minus.gif b/dijit/themes/tundra/images/treeExpand_minus.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/treeExpand_plus.gif b/dijit/themes/tundra/images/treeExpand_plus.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/images/validationInputBg.gif b/dijit/themes/tundra/images/validationInputBg.gif
old mode 100644
new mode 100755
diff --git a/dijit/themes/tundra/layout/AccordionContainer.css b/dijit/themes/tundra/layout/AccordionContainer.css
index a96f49f..c5621ef 100644
--- a/dijit/themes/tundra/layout/AccordionContainer.css
+++ b/dijit/themes/tundra/layout/AccordionContainer.css
@@ -1,22 +1,26 @@
+/* Accordion */
 
 .tundra .dijitAccordionContainer {
 	border-color: #ccc;
 	background-color: #fff;
 }
+
+/* common */
+
 .tundra .dijitAccordionTitle {
 	background:#fafafa url("../images/titleBar.png") repeat-x bottom left;
 	border-top: 1px solid #bfbfbf;
 	padding: 4px 4px 4px 8px;
-	cursor:pointer;
 }
-.tundra .dijitAccordionTitle-hover  {
+
+.tundra .dijitAccordionTitleHover  {
 	background: #f8fafd url("../images/accordionItemHover.gif") bottom repeat-x;
 }
-.tundra .dijitAccordionTitle-selected  {
+
+.tundra .dijitAccordionTitleSelected  {
 	background: #f9f9f9 url("../images/accordionItemActive.gif") bottom repeat-x;
 	font-weight: bold;
 	border-top: 1px solid #aaaaaa;
 	border-bottom: 1px solid #bfbfbf;
 	padding: 4px 4px 4px 8px;
-	cursor: default;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/tundra/layout/BorderContainer.css b/dijit/themes/tundra/layout/BorderContainer.css
index 076460f..0057fcb 100644
--- a/dijit/themes/tundra/layout/BorderContainer.css
+++ b/dijit/themes/tundra/layout/BorderContainer.css
@@ -1,49 +1,63 @@
+/* BorderContainer */
 
 .tundra .dijitBorderContainer {
 	background-color: #fcfcfc;
 	padding: 5px;
 }
+
 .tundra .dijitSplitContainer-child,
 .tundra .dijitBorderContainer-child {
-	
+	/* By default put borders on all children of BorderContainer,
+	 *  to give illusion of borders on the splitters themselves.
+	 */
 	border: 1px #ccc solid;
 }
+
 .tundra .dijitBorderContainer-dijitTabContainerTop,
 .tundra .dijitBorderContainer-dijitTabContainerBottom,
 .tundra .dijitBorderContainer-dijitTabContainerLeft,
 .tundra .dijitBorderContainer-dijitTabContainerRight {
-	
+	/* except that TabContainer defines borders on it's sub-nodes (tablist and dijitTabPaneWrapper),
+	 * so override rule setting border on domNode
+	 */
 	 border: none;
 }
+
 .tundra .dijitBorderContainer-dijitBorderContainer {
-	
+	/* also, make nested BorderContainers look like a single big widget with lots of splitters */
 	border: none;
 	padding: 0px;
 }
+
 .tundra .dijitSplitterH,
 .tundra .dijitGutterH {
 	background:#fcfcfc;
 	border:0;
 	height:5px;
 }
+
 .tundra .dijitSplitterH .dijitSplitterThumb {
 	background:#B0B0B0 none;
 	height:1px;
 	top:2px;
 	width:19px;
 }
+
 .tundra .dijitSplitterV,
 .tundra .dijitGutterV {
 	background:#fcfcfc;
 	border:0;
 	width:5px;
 }
+
 .tundra .dijitSplitterV .dijitSplitterThumb {
 	background:#B0B0B0 none;
 	height:19px;
 	left:2px;
 	width:1px;
 }
+
+/* active splitter */
 .tundra .dijitSplitterActive {
 	font-size: 1px;
 	background-image: none;
diff --git a/dijit/themes/tundra/layout/ContentPane.css b/dijit/themes/tundra/layout/ContentPane.css
index 8b470b9..27d8fb9 100644
--- a/dijit/themes/tundra/layout/ContentPane.css
+++ b/dijit/themes/tundra/layout/ContentPane.css
@@ -1,7 +1,10 @@
+/* ContentPane */
 
 .tundra .dijitContentPane {
 	padding: 0px;
 }
+
+/* nested layouts */
 .tundra .dijitTabContainerTop-dijitContentPane,
 .tundra .dijitTabContainerLeft-dijitContentPane,
 .tundra .dijitTabContainerBottom-dijitContentPane,
@@ -10,8 +13,9 @@
 	background-color: #fff;
 	padding: 5px;
 }
+
 .tundra .dijitSplitContainer-dijitContentPane,
 .tundra .dijitBorderContainer-dijitContentPane {
-	background-color: #fff;		
+	background-color: #fff;		/* override background-color setting on parent .dijitBorderContainer */
 	padding: 5px;
-}
+}
\ No newline at end of file
diff --git a/dijit/themes/tundra/layout/SplitContainer.css b/dijit/themes/tundra/layout/SplitContainer.css
index b9945d6..5a3eed6 100644
--- a/dijit/themes/tundra/layout/SplitContainer.css
+++ b/dijit/themes/tundra/layout/SplitContainer.css
@@ -5,6 +5,7 @@
 	border-right:1px solid #bfbfbf;
 	width:7px;
 }
+
 .tundra .dijitSplitContainerSizerH .thumb {
 	background:url("../images/splitContainerSizerV-thumb.png") no-repeat #ccc;
 	left:1px;
@@ -12,6 +13,7 @@
 	height:19px;
 	overflow: hidden;
 }
+
 .tundra .dijitSplitContainerSizerV {
 	background:url("../images/splitContainerSizerH.png") repeat-x #fff;
 	border:0;
@@ -19,6 +21,7 @@
 	border-bottom:1px solid #bfbfbf;
 	height:7px;
 }
+
 .tundra .dijitSplitContainerSizerV .thumb {
 	background:url("../images/splitContainerSizerH-thumb.png") no-repeat #ccc;
 	top:1px;
@@ -26,6 +29,3 @@
 	height:3px;
 	overflow: hidden;
 }
-.tundra .dijitSplitter {
-	border-color: #bfbfbf;
-}
diff --git a/dijit/themes/tundra/layout/TabContainer.css b/dijit/themes/tundra/layout/TabContainer.css
index f644935..d28eab5 100644
--- a/dijit/themes/tundra/layout/TabContainer.css
+++ b/dijit/themes/tundra/layout/TabContainer.css
@@ -1,29 +1,34 @@
-
+/* Tabs, shared classes */
 .tundra .dijitTabPaneWrapper {
 	background:#fff;
 	border:1px solid #ccc;
 	margin: 0;
 	padding: 0;
 }
+
 .tundra .dijitTab {
 	line-height:normal;
-	margin-right:4px;	
+	margin-right:4px;	/* space between one tab and the next in top/bottom mode */
 	padding:0px;
 	border:1px solid #ccc;
 	background:#e2e2e2 url("../images/tabEnabled.png") repeat-x;
 }
+
 .tundra .dijitTabInnerDiv {
 	padding:2px 8px 2px 9px;
 }
+
 .tundra .dijitTabSpacer {
 	display: none;
 }
+
 .tundra .dijitTabContainer .tabStripRBtn {
 	margin-right: 20px;
 }
 .tundra .dijitTabContainer .tabStripLBtn {
 	margin-left: 20px;
 }
+
 .tundra .nowrapTabStrip .dijitTab {
 	top: 2px;
 }
@@ -31,15 +36,16 @@
 	top: 0px;
 	bottom: 2px;
 }
-.tundra .dijitTabContainer .tabStripMenuButton-Hover {
-	cursor: pointer;
-}
+
+/* checked tab*/
 .tundra .dijitTabChecked {
-	
+	/* the selected tab (with or without hover) */
 	background-color:#fff;
 	border-color: #ccc;
 	background-image:none;
 }
+
+/* hovered tab */
 .tundra .dijitTabHover {
 	color: #243C5F;
 	border-top-color:#92a0b3;
@@ -48,43 +54,49 @@
 	border-bottom-color:#92a0b3;
 	background:#e2e2e2 url("../images/tabHover.gif") repeat-x;
 }
+
 .tundra .dijitTabContainerTop .dijitTabHover {
 	border-bottom-color:#ccc;
 }
+
 .tundra .dijitTabContainerBottom .dijitTabHover {
 	border-top-color:#ccc;
 }
+
 .tundra .dijitTabContainerLeft .dijitTabHover {
 	border-right-color:#ccc;
 }
+
 .tundra .dijitTabContainerRight .dijitTabHover {
 	border-left-color:#ccc;
 }
+
 .tundra .dijitTabContainer .dijitTabCheckedHover {
 	color: inherit;
 	border:1px solid #ccc;
 	background:#fff;
 }
-.tundra .dijitTab .dijitClosable .closeImage {
-	background: url("../images/tabClose.png") no-repeat right top;
-	width: 12px;
-	height: 12px;
-}
+
 .tundra .dijitTab .tabLabel {
-	
+	/* make sure tabs w/close button and w/out close button are same height, even w/small (<12px) font */
 	min-height: 12px;
 	display: inline-block;
 }
+
+/* Nested Tabs */
+
 .tundra .dijitTabContainerNested .dijitTabListWrapper {
 	height: auto;
 }
+
 .tundra .dijitTabContainerNested .dijitTabContainerTop-tabs {
 	border-bottom: 1px solid #CCC;
 }
+
 .tundra .dijitTabContainerTabListNested .dijitTab {
 	background: none;
 	border: none;
-	top: 0px;		
+	top: 0px;		/* to override top: 1px/-1px for normal tabs */
 }
 .tundra .dijitTabContainerTabListNested .dijitTab .dijitTabContent {
 }
@@ -94,23 +106,33 @@
 .tundra .dijitTabContainerTabListNested .dijitTabChecked .dijitTabContent .tabLabel {
 	text-decoration: underline;
 	font-weight: bold;
-	
+	/*background:#f3f3f3;*/
 }
 .tundra .dijitTabContainer .dijitTabPaneWrapperNested {
-	border: none;	
+	border: none;	/* prevent double border */
 }
-.tundra .dijitTab .closeImage {
-	background-image : url("../images/tabClose.png");
+
+/* Close button */
+
+.tundra .dijitTabCloseButton {
+	background: url("../images/tabClose.png") no-repeat right top;
+	width: 12px;
+	height: 12px;
 }
-.dj_ie6 .tundra .dijitTab .closeImage {
+.dj_ie6 .tundra .dijitTabCloseButton {
 	background-image : url("../images/tabClose.gif");
 }
-.tundra .dijitTab .closeButton-hover .closeImage {
+
+.tundra .dijitTabCloseButtonHover {
 	background-image : url("../images/tabCloseHover.png");
 }
-.dj_ie6 .tundra .dijitTab .closeButton-hover .closeImage {
+.dj_ie6 .tundra .dijitTabCloseButtonHover {
 	background-image : url("../images/tabCloseHover.gif");
 }
+
+/* ================================ */
+/* top tabs */
+
 .tundra .dijitTabContainerTop-tabs {
 	margin-bottom: 0px;
 	border-color: #cccccc;
@@ -121,17 +143,24 @@
 	top: 0px;
 	margin-bottom: -1px;
 }
+
+/* top container */
 .tundra .dijitTabContainerTop-container {
 	border-top: none;
 }
+
+/* checked tabs */
 .tundra .dijitTabContainerTop-tabs .dijitTabChecked {
 	border-bottom-color:white;
 }
+
 .tundra .dijitTabContainerTop-tabs,
 .tundra .dijitTabContainerBottom-tabs {
 	padding-left: 3px;
 	padding-right: 3px;
 }
+
+/* strip */
 .tundra .dijitTabContainerTopStrip {
 	border-top: 1px solid #CCC;
 	border-right: 1px solid #CCC;
@@ -139,9 +168,14 @@
 	padding-top: 2px;
 	background: #f2f2f2;
 }
+
 .tundra .dijitTabContainerTopNone {
 	padding-top: 0px;
 }
+
+
+/* ================================ */
+/* bottom tabs */
 .tundra .dijitTabContainerBottom-tabs {
 	margin-top: 0px;
 	border-color: #cccccc;
@@ -152,63 +186,94 @@
 	bottom: 0px;
 	margin-top: -1px;
 }
+
+/* bottom container */
 .tundra .dijitTabContainerBottom-container {
 	border-bottom: none;
 }
+
+/* checked tabs */
 .tundra .dijitTabContainerBottom-tabs .dijitTabChecked {
 	border-top-color:white;
 }
+
+/* strip */
 .tundra .dijitTabContainerBottomStrip {
 	padding-bottom: 2px;
 	border: 1px solid #ccc;
 	background: #f2f2f2;
 	border-top: none;
 }
+
+/* ================================ */
+/* right tabs */
 .tundra .dijitTabContainerRight-tabs {
 	border-color: #ccc;
 	height: 100%;
 	padding-top: 3px;
 }
+
 .tundra .dijitTabContainerRightStrip {
 	margin-left: -1px;
 }
+
+/* right container */
 .tundra .dijitTabContainerRight-container {
 	border-right: none;
 }
+
+/* checked tabs */
 .tundra .dijitTabContainerRight-tabs .dijitTabChecked {
 	border-left-color:white;
 }
+
+/* strip */
 .tundra .dijitTabContainerRightStrip {
 	padding-right: 2px;
 	border: 1px solid #ccc;
 }
+
 .tundra .dijitTabContainerRightStrip {
 	background: #f2f2f2;
 }
+
+/* ================================ */
+/* left tabs */
 .tundra .dijitTabContainerLeft-tabs {
 	border-color: #ccc;
 	padding-top: 3px;
 	height: 100%;
 }
-.tundra .dijitTabContainerLeft .dijitTabListWrapper {
-}
+
+/* left conatiner */
 .tundra .dijitTabContainerLeft-container {
 	border-left: none;
 }
+
+/* checked tabs */
 .tundra .dijitTabContainerLeft-tabs .dijitTabChecked {
 	border-right-color:white;
 }
+
+/* strip */
 .tundra .dijitTabContainerLeftStrip {
 	padding-left: 2px;
 	border: 1px solid #ccc;
 	background: #f2f2f2;
 	border-right: none;
 }
+
+/* ================================ */
+/* left/right tabs */
 .tundra .dijitTabContainerLeft-tabs .dijitTab,
 .tundra .dijitTabContainerRight-tabs .dijitTab {
 	margin-right:0px;
-	margin-bottom:4px;	
+	margin-bottom:4px;	/* space between one tab and the next in left/right mode */
 }
+
+/* ================================ */
+
+/* this resets the tabcontainer stripe when within a contentpane */
 .tundra .dijitTabContainerTop-dijitContentPane .dijitTabContainerTop-tabs {
 	border-left: 0px solid #ccc;
 	border-top: 0px solid #ccc;
@@ -216,21 +281,29 @@
 	padding-top: 0px;
 	padding-left: 0px;
 }
+
+/* ================================ */
+
+/* Menu and slider control styles */
 .tundra .dijitTabContainer .tabStripButton {
 	margin-right: 0;
 	padding-top: 2px;
 	z-index: 12;
 }
+
 .tundra .dijitTabContainerBottom .tabStripButton {
 	padding-top: 2px;
 }
+
 .tundra .tabStrip-disabled .tabStripButton .dijitTabInnerDiv {
 	padding-bottom: 3px;
 	padding-top: 1px;
 }
+
 .tundra .tabStripButton .dijitTabInnerDiv {
 	padding: 3px 2px 4px 2px;
 }
+
 .dj_ie6 .tundra .tabStripButton .dijitTabInnerDiv,
 .dj_ie7 .tundra .tabStripButton .dijitTabInnerDiv,
 .dj_opera .tundra .tabStripButton .dijitTabInnerDiv {
@@ -241,23 +314,22 @@
 .dj_opera .tundra .tabStrip-disabled .tabStripButton .dijitTabInnerDiv {
 	padding-bottom: 4px;
 }
-.tundra .dijitTabContainer .tabStripButton {
-	
-	width: 21px;
-}
-.tundra .dijitTabContainer .tabStripButton img {
+
+.tundra .dijitTabStripIcon {
 	height: 14px;
-	background: url(../images/spriteRoundedIconsSmall.png) no-repeat;
+	width: 14px;
+	background: url(../images/spriteRoundedIconsSmall.png) no-repeat left top ;
 }
-.dj_ie6 .tundra .dijitTabContainer .tabStripButton img {
+
+.dj_ie6 .tundra .dijitTabStripIcon {
 	background-image: url(../images/spriteRoundedIconsSmall.gif);
 }
-.tundra .dijitTabContainer .tabStripMenuButton img {
-	background-position: -15px top;
-}
-.tundra .dijitTabContainer .tabStripSlideButtonLeft img {
-	background-position: 0px top;
-}
-.tundra .dijitTabContainer .tabStripSlideButtonRight img {
+
+.tundra .dijitTabStripSlideRightIcon {
 	background-position: -30px top;
 }
+
+.tundra .dijitTabStripMenuIcon {
+	background-position: -15px top;
+}
+
diff --git a/dijit/themes/tundra/layout/TabContainer_rtl.css b/dijit/themes/tundra/layout/TabContainer_rtl.css
index b55835e..95c8a66 100644
--- a/dijit/themes/tundra/layout/TabContainer_rtl.css
+++ b/dijit/themes/tundra/layout/TabContainer_rtl.css
@@ -1,31 +1,51 @@
-.dijitRtl .tundra .dijitTab {
+.tundra .dijitTabRtl {
 	-moz-box-orient:horizontal;
 	text-align: right;
 }
-.dijitRtl .tundra .dijitTabInnerDiv {
+
+.tundra .dijitTabRtl .dijitTabInnerDiv {
 	padding:2px 9px 2px 8px;
 }
-.dijitRtl .tundra .tabStrip-disabled .tabStripButton .dijitTabInnerDiv {
+
+.tundra .tabStrip-disabled .tabStripButtonRtl .dijitTabInnerDiv {
+	/* this is not special for RTL mode, but just here to override rule above (for enabled tabstrip) */
 	padding-bottom: 3px;
 	padding-top: 1px;
 }
-.dijitRtl .tundra .tabStripButton .dijitTabInnerDiv {
+
+.tundra .tabStripButtonRtl .dijitTabInnerDiv {
 	padding: 3px 2px 4px 2px;
 }
-.dijitRtl .tundra .dijitTabPaneWrapper {
+
+.tundra .dijitTabPaneWrapper {
 	#zoom: 1;
 }
+
 .dj_ie-rtl .tundra .dijitTabContainerLeft-tabs {
 	margin-left: 1px !important;
 }
+
 .dj_ie-rtl .tundra .dijitTabContainerRight-tabs {
 	margin-right: 1px !important;
 }
-.dijitRtl .tundra .dijitTabContainerLeft-tabs .dijitTab,
-.dijitRtl .tundra .dijitTabContainerRight-tabs .dijitTab {
+
+.tundra .dijitTabContainerLeft-tabs .dijitTabRtl,
+.tundra .dijitTabContainerRight-tabs .dijitTabRtl {
 	margin-left:0px;
 }
-.dj_ie-rtl .tundra .dijitTab .dijitTabInnerDiv {
-	
+
+.dj_ie .tundra .dijitTabRtl .dijitTabInnerDiv {
+	/* without this the tab label and icon become invisible, as though they were set to visibility:hidden */
 	width : 0.1% !important;
 }
+
+
+
+.dj_iequirks-rtl .tundra .dijitTabContainerTopNone,
+.dj_iequirks-rtl .tundra .dijitTabContainerBottomNone {
+	/* this strange rule prevents IE6 bug in themeTesterQuirk.html?dir=rtl upon closing
+	 * "Closable" tab, where the other tabs disappear
+	 */
+	border-left: 1px solid #fff;
+	border-right: 1px solid #fff;
+}
diff --git a/dijit/themes/tundra/tundra.css b/dijit/themes/tundra/tundra.css
index 15fa9e4..f1d239c 100644
--- a/dijit/themes/tundra/tundra.css
+++ b/dijit/themes/tundra/tundra.css
@@ -1,3230 +1,41 @@
+/*
+	Adds cosmetic styling to Dijit.  Users may swap with a custom theme CSS file.
 
-.dijitReset {
-	
-	margin:0;
-	border:0;
-	padding:0;
-	line-height:normal;
-	font: inherit;
-	color: inherit;
-}
-.dijitInline {
-	
-	display:inline-block;			
-	#zoom: 1; 
-	#display:inline; 
-	border:0;
-	padding:0;
-	vertical-align:middle;
-	#vertical-align: auto;	
-}
-.dijitHidden {
-	
-	display: none !important;
-}
-.dijitVisible {
-	
-	display: block !important;	
-	position: relative;			
-}
-.dj_ie INPUT.dijitTextBox,
-.dj_ie .dijitInputField INPUT {
-	font-size: 100%;
-}
-.dj_ie .dijitInputField INPUT { 
-	margin: -1px 0 !important;
-}
-.dijitInlineTable {
-	
-	display:inline-table;
-	display:inline-block;		
-	#zoom: 1; 
-	#display:inline; 
-	box-sizing: content-box; -moz-box-sizing: content-box;
-	border:0;
-	padding:0;
-}
-.dijitTeeny {
-	font-size:1px;
-	line-height:1px;
-}
-.dijitPopup {
-	position: absolute;
-	background-color: transparent;
-	margin: 0;
-	border: 0;
-	padding: 0;
-}
-.dijit_a11y .dijitPopup,
-.dijit_ally .dijitPopup div,
-.dijit_a11y .dijitPopup table,
-.dijit_a11y .dijitTooltipContainer {
-	background-color: white !important;
-}
-.dijitInputField {
-	overflow:hidden;
-	#zoom:1;
-}
-.dijitPositionOnly {
-	
-	padding: 0 !important;
-	border: 0 !important;
-	background-color: transparent !important;
-	background-image: none !important;
-	height: auto !important;
-	width: auto !important;
-}
-.dijitNonPositionOnly {
-	
-	float: none !important;
-	position: static !important;
-	margin: 0 0 0 0 !important;
-	vertical-align: middle !important;
-}
-.dijitBackgroundIframe {
-	
-	position: absolute;
-	left: 0;
-	top: 0;
-	width: 100%;
-	height: 100%;
-	z-index: -1;
-	border: 0;
-	padding: 0;
-	margin: 0;
-}
-.dijitClickableRegion {
-	
-	background-color: #e2ebf2;
-	cursor: text;
-}
-.dijitDisplayNone {
-	
-	display:none !important;
-}
-.dijitContainer {
-	
-	overflow: hidden;	
-}
-.dijit_a11y * {
-	background-image:none !important;
-}
-.dijit_a11y .dijitCalendarIncrementControl {
-	display: none;	
-}
-.dijit_a11y .dijitA11ySideArrow {
-	display: inline !important; 
-	cursor: pointer;
-}
-.dijit_a11y .dijitCalendarDateLabel {
-	padding: 1px;
-}
-.dijit_a11y .dijitCalendarSelectedDate .dijitCalendarDateLabel {
-	border: solid 1px black;
-	padding: 0px;
-}
-.dijit_a11y .dijitCalendarDateTemplate {
-	padding-bottom: 0.1em !important;	
-}
-.dijit_a11y .dijit * {
-	background:white !important;
-	color:black !important;
-}
-.dijit_a11y .dijitButtonNode {
-	border-color: black!important;
-	border-style: outset!important;
-	border-width: medium!important;
-}
-.dijit_a11y .dijitComboBoxReadOnly .dijitInputField,
-.dijit_a11y .dijitComboBoxReadOnly .dijitButtonNode,
-.dijit_a11y .dijitSpinnerReadOnly .dijitButtonNode,
-.dijit_a11y .dijitSpinnerReadOnly .dijitInputField,
-.dijit_a11y .dijitButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitDropDownButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitComboButtonDisabled .dijitButtonNode,
-.dijit_a11y .dijitComboBoxDisabled .dijitInputField,
-.dijit_a11y .dijitComboBoxDisabled .dijitButtonNode,
-.dijit_a11y .dijitSpinnerDisabled .dijitButtonNode,
-.dijit_a11y .dijitSpinnerDisabled .dijitInputField {
-	border-style: outset!important;
-	border-width: medium!important;
-	border-color: #999 !important;
-	color:#999 !important;
-}
-.dijitButtonNode * {
-	vertical-align: middle;
-}
-.dijit_a11y .dijitArrowButtonInner {
-	width: 1em;
-	display: none !important;
-}
-.dijitButtonNode .dijitArrowButtonInner {
-	background:no-repeat center;
-	width: 16px;
-}
-.dijitComboBox .dijitArrowButtonInner {
-	display: block;
-}
-.dijit_a11y .dijitToggleButtonChecked .dijitToggleButtonIconChar {
-	display: inline !important;
-}
-.dijitLeft {
-	
-	background-position:left top;
-	background-repeat:no-repeat;
-}
-.dijitStretch {
-	
-	white-space:nowrap;			
-	background-repeat:repeat-x;
-}
-.dijitRight {
-	
-	#display:inline;				
-	background-position:right top;
-	background-repeat:no-repeat;
-}
-.dijitToggleButton,
-.dijitButton,
-.dijitDropDownButton,
-.dijitComboButton {
-	
-	margin: 0.2em;
-}
-.dijitToolbar .dijitToggleButton,
-.dijitToolbar .dijitButton,
-.dijitToolbar .dijitDropDownButton,
-.dijitToolbar .dijitComboButton {
-	margin: 0;
-}
-.dj_ie8 .dijitToolbar button,
-.dj_webkit .dijitToolbar button {
-	
-	padding: 1px 2px;
-}
-.dj_ie .dijitToolbar .dijitComboBox{
-	
-	vertical-align: middle;
-}
-.dj_ie .dijitComboButton {
-	
-	margin-bottom: -3px;
-}
-.dj_webkit .dijitToolbar .dijitDropDownButton {
-	padding-left: 0.3em;
-}
-.dj_gecko .dijitToolbar .dijitButtonNode::-moz-focus-inner {
-	padding:0;
-}
-.dijitButtonNode {
-	
-	border:1px solid gray;
-	margin:0;
-	line-height:normal;
-	vertical-align: middle;
-	#vertical-align: auto;
-	text-align:center;
-	white-space: nowrap;
-}
-.dijitButtonNode, .dijitButtonNode * {
-	cursor: pointer;
-}
-.dijitReadOnly *,
-.dijitDisabled *,
-.dijitReadOnly,
-.dijitDisabled,
-.dijitDisabledClickableRegion {	
-	cursor: not-allowed !important;
-}
-.dj_ie .dijitButtonNode {
-	
-	zoom: 1;
-}
-.dj_ie .dijitButtonNode button {
-	
-	overflow: visible;
-}
-.dijitArrowButton {
-	
-	
-	padding: 0 .4em;
-}
-DIV.dijitArrowButton {
-	float: right;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	border-style: solid;
-	border-width: 0 0 0 1px !important;
-	padding: 0;
-	position: absolute;
-	right: 0;
-	float: none;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	position: absolute;
-	height: 50%;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitDownArrowButton {
-	top: auto;
-	bottom: 0;
-	border-top-width: 1px !important;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitUpArrowButton {
-	top: 0;
-	bottom: auto;
-}
-TABLE.dijitComboButton {
-	
-	border-collapse: collapse;
-	border:0;
-	padding:0;
-	margin:0;
-}
-.dijitToolbar .dijitComboButton {
-	
-	border-collapse: separate;
-}
-.dj_ie BUTTON.dijitButtonNode {
-	overflow: visible; 
-}
-table .dijitButton .dijitButtonNode,
-table .dijitComboButton .dijitButtonNode {
-	#overflow:hidden; 
-}
-.dijitButtonNode IMG {
-	
-	vertical-align:middle;
-	
-}
-.dijitTextBox,
-.dijitComboBox,
-.dijitSpinner {
-	border: solid black 1px;
-	#overflow: hidden; 
-	width: 15em;	
-	vertical-align: middle;
-	#vertical-align: auto;
-}
-.dijitTimeTextBox {
-	width: 8em;
-}
-.dijitTextBox input:focus,
-.dijitComboBox input:focus,
-.dijitSpinner input:focus {
-	outline: none;	
-}
-.dijitTextBoxFocused,
-.dijitComboBoxFocused,
-.dijitSpinnerFocused, .dijitSpinnerUpArrowActive, .dijitSpinnerDownArrowActive,
-.dijitTextAreaFocused {
-	
-	outline: auto 5px -webkit-focus-ring-color;
-}
-.dijitTextBox INPUT,
-.dijitComboBox INPUT,
-.dijitSpinner INPUT {
-	border-left: solid black 1px;	
-	display:inline;
-	position:static !important;
-	border:0 !important;
-	margin:0 !important;
-	vertical-align:top !important;
-	background-color:transparent !important;
-	background-image:none !important;
-	width:100% !important;
-}
-.dijitValidationIcon {
-	visibility: hidden;
-	display: block;
-	padding: 0 2px;
-	float: right;
-	height: auto;
-}
-.dijitValidationIconText {
-	visibility: hidden;
-	display: none;
-	float:right;
-	font-family: sans-serif;
-	font-style:italic;
-	font-size: 0.75em;
-	padding-right: 0.15em;
-	line-height: 160%;
-}
-.dijit_a11y .dijitValidationIcon { display: none !important; }
-.dijit_a11y .dijitValidationIconText { display: block !important; }
-.dijitError .dijitValidationIcon,
-.dijitError .dijitValidationIconText {
-	visibility: visible;
-}
-.dijitTextBox .dijitArrowButton {
-	
-	display:none;
-}
-.dijitCheckBox,
-.dijitRadio,
-.dijitCheckBoxInput {
-	padding: 0;
-	border: 0;
-	width: 16px;
-	height: 16px;
-	background-position:center center;
-	background-repeat:no-repeat;
-	overflow: hidden;
-}
-.dijitCheckBox INPUT,
-.dijitRadio INPUT {
-	margin: 0;
-	padding: 0;
-	display: block;
-}
-.dijitCheckBoxInput {
-	
-	opacity: 0.01;
-}
-.dj_ie .dijitCheckBoxInput {
-	filter: alpha(opacity=0);
-}
-.dijit_a11y .dijitCheckBox,
-.dijit_a11y .dijitRadio {
-	width: auto;
-	height: auto;
-}
-.dijit_a11y .dijitCheckBoxInput {
-	opacity: 1;
-	filter: none;
-	width: auto;
-	height: auto;
-}
-.dijitProgressBarEmpty{
-	
-	position:relative;overflow:hidden;
-	border:1px solid black; 	
-	z-index:0;			
-}
-.dijitProgressBarFull {
-	
-	position:absolute;
-	overflow:hidden;
-	z-index:-1;
-	top:0;
-	width:100%;
-}
-.dj_ie6 .dijitProgressBarFull {
-	height:1.6em;
-}
-.dijitProgressBarTile {
-	
-	position:absolute;
-	overflow:hidden;
-	top:0;
-	left:0;
-	bottom:0;
-	right:0;
-	margin:0;
-	padding:0;
-	width:auto;
-	height:auto;
-	background-color:#aaa;
-	background-attachment: fixed;
-}
-.dijit_a11y .dijitProgressBarTile{
-	
-	border-width:4px;
-	border-style:solid;
-	background-color:transparent !important;
-}
-.dj_ie6 .dijitProgressBarTile {
-	
-	position:static;
-	
-	height:1.6em;
-}
-.dijitProgressBarIndeterminate .dijitProgressBarLabel {
-	visibility:hidden;
-}
-.dijitProgressBarIndeterminate .dijitProgressBarTile {
-	
-}
-.dijitProgressBarIndeterminateHighContrastImage {
-	display:none;
-}
-.dijit_a11y .dijitProgressBarIndeterminate .dijitProgressBarIndeterminateHighContrastImage {
-	display:block;
-	position:absolute;
-	top:0;
-	bottom:0;
-	margin:0;
-	padding:0;
-	width:100%;
-	height:auto;
-}
-.dijitProgressBarLabel {
-	display:block;
-	position:static;
-	width:100%;
-	text-align:center;
-	background-color:transparent !important;
-}
-.dijitTooltip {
-	position: absolute;
-	z-index: 2000;
-	display: block;
-	
-	left: 50%;
-	top: -10000px;
-	overflow: visible;
-}
-.dijitTooltipContainer {
-	border: solid black 2px;
-	background: #b8b5b5;
-	color: black;
-	font-size: small;
-}
-.dijitTooltipFocusNode {
-	padding: 2px 2px 2px 2px;
-}
-.dijitTooltipConnector {
-	position: absolute;
-}
-.dijitTooltipData {
-	display:none;
-}
-.dijitLayoutContainer{
-	position: relative;
-	display: block;
-	overflow: hidden;
-}
-body .dijitAlignTop,
-body .dijitAlignBottom,
-body .dijitAlignLeft,
-body .dijitAlignRight {
-	position: absolute;
-	overflow: hidden;
-}
-body .dijitAlignClient { position: absolute; }
-.dijitBorderContainer, .dijitBorderContainerNoGutter {
-	position:relative;
-	overflow: hidden;
-}
-.dijitBorderContainerPane,
-.dijitBorderContainerNoGutterPane {
-	position: absolute !important;	
-	z-index: 2;		
-}
-.dijitBorderContainer > .dijitTextArea {
-	
-	resize: none;
-}
-.dijitGutter {
-	
-	position: absolute;
-	font-size: 1px;		
-}
-.dijitSplitter {
-	position: absolute;
-	overflow: hidden;
-	z-index: 10;		
-	background-color: #fff;
-	border-color: gray;
-	border-style: solid;
-	border-width: 0;
-}
-.dj_ie .dijitSplitter {
-	z-index: 1;	
-}
-.dijitSplitterActive {
-	z-index: 11 !important;
-}
-.dijitSplitterCover{
-	position:absolute;
-	z-index:-1;
-	top:0;
-	left:0;
-	width:100%;
-	height:100%;
-}
-.dijitSplitterCoverActive{
-	z-index:3 !important;
-}
-.dj_ie .dijitSplitterCover{
-	background: white;
-	filter: alpha(opacity=0);
-}
-.dijitSplitterH {
-	height: 7px;
-	border-top:1px;
-	border-bottom:1px;
-	cursor: ns-resize;
-}
-.dijitSplitterV {
-	width: 7px;
-	border-left:1px;
-	border-right:1px;
-	cursor: ew-resize;
-}
-.dijitSplitContainer{
-	position: relative;
-	overflow: hidden;
-	display: block;
-}
-.dijitSplitPane{
-	position: absolute;
-}
-.dijitSplitContainerSizerH,
-.dijitSplitContainerSizerV {
-	position:absolute;
-	font-size: 1px;
-	cursor: move;
-	cursor: w-resize;
-	background-color: ThreeDFace;
-	border: 1px solid;
-	border-color: ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight;
-	margin: 0;
-}
-.dijitSplitContainerSizerH .thumb, .dijitSplitterV .dijitSplitterThumb {
-	overflow:hidden;
-	position:absolute;
-	top:49%;
-}
-.dijitSplitContainerSizerV .thumb, .dijitSplitterH .dijitSplitterThumb {
-	position:absolute;
-	left:49%;
-}
-.dijitSplitterShadow,
-.dijitSplitContainerVirtualSizerH,
-.dijitSplitContainerVirtualSizerV {
-	font-size: 1px;
-	background-color: ThreeDShadow;
-	-moz-opacity: 0.5;
-	opacity: 0.5;
-	filter: Alpha(Opacity=50);
-	margin: 0;
-}
-.dj_ie .dijitSplitterV, .dijitSplitContainerVirtualSizerH {
-	cursor: w-resize;
-}
-.dj_ie .dijitSplitterH, .dijitSplitContainerSizerV, .dijitSplitContainerVirtualSizerV {
-	cursor: n-resize;
-}
-.dijit_a11y .dijitSplitterH {
-	border-top:1px solid #d3d3d3 !important;
-	border-bottom:1px solid #d3d3d3 !important;
-}
-.dijit_a11y .dijitSplitterV {
-	border-left:1px solid #d3d3d3 !important;
-	border-right:1px solid #d3d3d3 !important;
-}
-.dijitContentPane {
-	display: block;
-	overflow: auto;	
-}
-.dijitContentPaneSingleChild {
-	
-	overflow: hidden;
-}
-.dijitTitlePane {
-	display: block;
-	overflow: hidden;
-}
-.dijitColorPalette {
-	border:1px solid #999;
-	background:#fff;
-	-moz-border-radius:3pt;
-}
-img.dijitColorPaletteUnder {
-	border-style:none;
-	position:absolute;
-	left:0;
-	top:0;
-}
-.dijitColorPaletteInner {
-	position: relative;
-	overflow:hidden;
-	outline:0;
-}
-.dijitPaletteCell {
-	width: 20px;
-	height: 20px;
-	position: absolute;
-	overflow: hidden;
-	z-index: 10;
-	outline-width: 0;
-}
-.dijitPaletteImg {
-	width: 16px; 
-	height: 14px; 
-	position: absolute;
-	top: 1px;
-	left: 1px;
-	overflow: hidden;
-	cursor: default;
-	border:1px solid #999;
-	
-}
-.dijitPaletteCellHighlight img {
-	width: 14px; 
-	height: 12px; 
-	position: absolute;
-	top: 1px;
-	left: 1px;
-	overflow: hidden;
-	cursor: default;
-	border:2px solid #000;
-	outline:1px solid #dedede;
-	
-}
-.dijit_a11y .dijitPaletteCell {
-	background-color:transparent !important;
-}
-.dijit_a11y .dijitPaletteImg {
-	background-color:transparent !important;
-}
-.dijitAccordionContainer {
-	border:1px solid #b7b7b7;
-	border-top:0 !important;
-}
-.dj_webkit .dijitAccordionContainer  div:focus {
-	outline:none;
-}
-.dj_ff3 .dijitAccordionContainer  div:focus {
-	outline:none;
-}
-.dijitAccordionTitle {
-	cursor: pointer;
-}
-.dijitAccordionFocused  {
-	text-decoration: underline;
-}
-.dijitAccordionTitle .arrowTextUp,
-.dijitAccordionTitle .arrowTextDown {
-	display: none;
-	font-size: 0.65em;
-	font-weight: normal !important;
-}
-.dijit_a11y .dijitAccordionTitle .arrowTextUp,
-.dijit_a11y .dijitAccordionTitle-selected .arrowTextDown {
-	display: inline;
-}
-.dijit_a11y .dijitAccordionTitle-selected .arrowTextUp {
-	display: none;
-}
-.dijitCalendarContainer thead tr th, .dijitCalendarContainer thead tr td, .dijitCalendarContainer tbody tr td, .dijitCalendarContainer tfoot tr td {
-	padding: 0;
-}
-.dijitCalendarNextYear {
-	margin:0 0 0 0.55em;
-}
-.dijitCalendarPreviousYear {
-	margin:0 0.55em 0 0;
-}
-.dijitCalendarIncrementControl {
-	vertical-align: middle;
-}
-.dijitCalendarDisabledDate {
-	color:gray !important;
-}
-.dijitCalendarPreviousMonthDisabled,
-.dijitCalendarCurrentMonthDisabled,
-.dijitCalendarNextMonthDisabled {
-	cursor:default !important
-}
-.dijitCalendarIncrementControl,
-.dijitCalendarBodyContainer tbody tr td,
-.dijitCalendarDateTemplate,
-.dijitCalendarContainer .dijitInline {
-	cursor:pointer;
-}
-.dijitSpacer {
-	
-  	position: relative;
-  	height: 1px;
-  	overflow: hidden;
-  	visibility: hidden;
-}
-.dijitMenu {
-	border:1px solid black;
-	background-color:white;
-}
-.dijitMenuTable {
-	margin:1px 0;
-	border-collapse:collapse;
-	border-width:0;
-	background-color:white;
-}
-.dj_webkit .dijitMenuTable td[colspan="2"]{
-	border-right:hidden;
-}
-.dijitMenuItem{
-	text-align: left;
-	white-space: nowrap;
-	padding:.1em .2em;
-	cursor:pointer;
-}
-.dijitMenuPassive .dijitMenuItemHover,
-.dijitMenuItemSelected {
-	
-	background-color:black;
-	color:white;
-}
-.dijitMenuItemIcon, .dijitMenuExpand {
-	background-repeat: no-repeat;
-}
-.dijitMenuItemDisabled * {
-	
-	opacity:0.3;
-	cursor:default;
-}
-.dj_ie .dijit_a11y .dijitMenuItemDisabled td,
-.dj_ie .dijitMenuItemDisabled *,
-.dj_ie .dijitMenuItemDisabled td {
-	color:gray !important;
-	filter: alpha(opacity=35);
-}
-.dijitMenuItemLabel {
-	position: relative;
-	vertical-align: middle;
-}
-.dijit_a11y .dijitMenuItemSelected {
-	border: 1px #fff dotted !important;
-}
-.dj_ff3 .dijit_a11y .dijitMenuItem td {
-	padding: none !important;
-	background:none ! important;
-}
-.dijit_a11y .dijitMenuItemSelected .dijitMenuItemLabel {
-	border-width: 1px;
-	border-style: solid;
-}
-.dj_ie8 .dijit_a11y .dijitMenuItemLabel {
-	position:static;
-}
-.dijitMenuExpandA11y {
-	display: none;
-}
-.dijit_a11y .dijitMenuExpandA11y {
-	display: inline;
-}
-.dijitMenuSeparator td {
-	border: 0;
-	padding: 0;
-}
-.dijitMenuSeparatorTop {
-	height: 50%;
-	margin: 0;
-	margin-top:3px;
-	font-size: 1px;
-}
-.dijitMenuSeparatorBottom {
-	height: 50%;
-	margin: 0;
-	margin-bottom:3px;
-	font-size: 1px;
-}
-.dijitCheckedMenuItemIconChar {
-	vertical-align: middle;
-	visibility:hidden;
-}
-.dijitCheckedMenuItemChecked .dijitCheckedMenuItemIconChar {
-	visibility: visible;
-}
-.dijit_a11y .dijitCheckedMenuItemIconChar {
-	display:inline !important;
-}
-.dijit_a11y .dijitCheckedMenuItemIcon {
-	display: none;
-}
-.dijitStackController .dijitToggleButtonChecked * {
-	cursor: default;	
-}
-.dijitTabContainerNoLayout {
-	width: 100%;	
-}
-.dijitTabContainerBottom-tabs,
-.dijitTabContainerTop-tabs,
-.dijitTabContainerLeft-tabs,
-.dijitTabContainerRight-tabs {
-	overflow: visible !important;  
-}
-.dijitTabContainerBottom-container,
-.dijitTabContainerTop-container,
-.dijitTabContainerLeft-container,
-.dijitTabContainerRight-container {
-	z-index:0;
-	overflow: hidden;
-	border: 1px solid black;
-}
-.dijitTabContainer .nowrapTabStrip {
-	width: 50000px;
-	display: block;
-	position: relative;
-}
-.dijitTabContainer .dijitTabListWrapper {
-	overflow: hidden;
-}
-.dijit_a11y .dijitTabContainer .tabStripButton img {
-	
-	display: none;
-}
-.dijitTabContainerTop-tabs {
-	border-bottom: 1px solid black;
-}
-.dijitTabContainerTop-container {
-	border-top: 0px;
-}
-.dijitTabContainerLeft-tabs {
-	border-right: 1px solid black;
-	float: left;
-}
-.dijitTabContainerLeft-container {
-	border-left: 0px;
-}
-.dijitTabContainerBottom-tabs {
-	border-top: 1px solid black;
-}
-.dijitTabContainerBottom-container {
-	border-bottom: 0px;
-}
-.dijitTabContainerRight-tabs {
-	border-left: 1px solid black;
-	float: left;
-}
-.dijitTabContainerRight-container {
-	border-right: 0px;
-}
-div.dijitTabBtnDisabled, .dj_ie div.dijitTabBtnDisabled {
-	cursor: auto;
-}
-.dijitTab {
-	position:relative;
-	cursor:pointer;
-	white-space:nowrap;
-	z-index:3;
-}
-.dijitTab * {
-	
-	vertical-align: middle;
-}
-.dijitTabChecked {
-	cursor: default;	
-}
-.dijitTabButtonIcon {
-	height: 18px;
-}
-.dijitTabContainerTop-tabs .dijitTab {
-	top: 1px;	
-}
-.dijitTabContainerBottom-tabs .dijitTab {
-	top: -1px;	
-}
-.dijitTabContainerLeft-tabs .dijitTab {
-	left: 1px;	
-}
-.dijitTabContainerRight-tabs .dijitTab {
-	left: -1px;	
-}
-.dijitTabContainerTop-tabs .dijitTab,
-.dijitTabContainerBottom-tabs .dijitTab {
-	
-	display:inline-block;			
-	#zoom: 1; 
-	#display:inline; 
-}
-.dijitTabInnerDiv {
-	position:relative;
-}
-.tabStripButton {
-	z-index: 12;
-}
-.dijitTabButtonDisabled .tabStripButton {
-	display: none;
-}
-.dijitTab .closeButton {
-	margin-left: 1em;
-}
-.dijitTab .closeText {
-	display:none;
-}
-.dijit_a11y .closeText {
-	display:inline;
-	margin: 0px 6px;
-}
-.dijit_a11y .dijitTab .closeImage {
-	display:none;
-}
-.dijit_a11y .closeButton-hover .closeText {
-	border:thin solid;
-}
-.dijit_a11y .dijitTabChecked {
-	border-style:dashed !important;
-}
-.dijit_a11y .dijitTabInnerDiv {
-	border-left:none !important;
- }
-.dijitTabPane,
-.dijitStackContainer-child,
-.dijitAccordionContainer-child {
-	
-    border: none !important;
-}
-.dijitInlineEditor {
-	
-	position:relative;
-	vertical-align:bottom;
-}
-.dj_ie .dijitInlineEditor {
-	vertical-align:middle;
-}
-.dijitInlineValue {
-	
-}
-.dijitInlineEditor .dijitButtonContainer {
-	
-	position:absolute;
-	right:0;
-	overflow:visible;
-}
-.dijitInlineEditor .saveButton,
-.dijitInlineEditor .cancelButton {
-}
-.dijitTreeIndent {
-	
-	width: 19px;
-}
-.dijitTreeRow, .dijitTreeContent {
-	white-space: nowrap;
-}
-.dijitTreeRow img {
-	
-	vertical-align: middle;
-}
-.dijitTreeContent {
-    cursor: default;
-}
-.dijitExpandoText {
-	display: none;
-}
-.dijit_a11y .dijitExpandoText {
-	display: inline;
-	padding-left: 10px;
-	padding-right: 10px;
-	font-family: monospace;
-	border-style: solid;
-	border-width: thin;
-	cursor: pointer;
-}
-.dijitTreeLabel {
-	margin: 0px 4px;
-}
-.dijitDialog {
-	position: absolute;
-	z-index: 999;
-	padding: 1px;
-	overflow: hidden;       
-}
-.dijitDialogFixed div.dijitDialogTitleBar {
-	cursor:default;
-}
-.dijitDialogUnderlayWrapper {
-	position: absolute;
-	left: 0;
-	top: 0;
-	z-index: 998;
-	display: none;
-	background: transparent !important;
-}
-.dijitDialogUnderlay {
-	background: #eee;
-	opacity: 0.5;
-}
-.dj_ie .dijitDialogUnderlay {
-	filter: alpha(opacity=50);
-}
-.dijit_a11y .dijitInputLayoutContainer,
-.dijit_a11y .dijitDialog {
-	opacity: 1 !important;
-	background-color: white !important;
-}
-.dijitDialog .closeText {
-	display:none;
-	
-	position:absolute;
-}
-.dijit_a11y .dijitDialog .closeText {
-	display:inline;
-}
-.dijitSliderMoveable {
-	z-index:99;
-	position:absolute !important;
-	display:block;
-	vertical-align:middle;
-}
-.dijitSliderMoveableH {
-	right:0;
-}
-.dijit_a11y div.dijitSliderImageHandle,
-.dijitSliderImageHandle {
-	margin:0;
-	padding:0;
-	position:absolute !important;
-	border:8px solid gray;
-	width:0;
-	height:0;
-}
-.dijit_a11y .dijitSliderFocused .dijitSliderImageHandle {
-	border:4px solid #000;
-	height:8px;
-	width:8px;
-}
-.dijitSliderImageHandleV {
-	top:-8px;
-	left:-6px;
-}
-.dijitSliderImageHandleH {
-	left:-8px;
-	top:-5px;
-	vertical-align:top;
-}
-.dijitSliderBar {
-	border-style:solid;
-	border-color:black;
-}
-.dijitSliderBarContainerV {
-	position:relative;
-	height:100%;
-	z-index:1;
-}
-.dijitSliderBarContainerH {
-	position:relative;
-	z-index:1;
-}
-.dijitSliderBarH {
-	height:4px;
-	border-width:1px 0;
-}
-.dijitSliderBarV {
-	width:4px;
-	border-width:0 1px;
-}
-.dijitSliderProgressBar {
-	background-color:red;
-	z-index:1;
-}
-.dijitSliderProgressBarV {
-	position:static !important;
-	height:0%;
-	vertical-align:top;
-	text-align:left;
-}
-.dijitSliderProgressBarH {
-	position:absolute !important;
-	width:0%;
-	vertical-align:middle;
-	overflow:visible;
-}
-.dijitSliderRemainingBar {
-	overflow:hidden;
-	background-color:transparent;
-	z-index:1;
-}
-.dijitSliderRemainingBarV {
-	height:100%;
-	text-align:left;
-}
-.dijitSliderRemainingBarH {
-	width:100% !important;
-}
-.dijitSliderBumper {
-	overflow:hidden;
-	z-index:1;
-}
-.dijitSliderBumperV {
-	width:4px;
-	height:8px;
-	border-width:0 1px;
-}
-.dijitSliderBumperH {
-	width:8px;
-	height:4px;
-	border-width:1px 0;
-}
-.dijitSliderBottomBumper,
-.dijitSliderLeftBumper {
-	background-color:red;
-}
-.dijitSliderTopBumper,
-.dijitSliderRightBumper {
-	background-color:transparent;
-}
-.dijitSliderDecorationH {
-	text-align:center;
-}
-.dijitSlider .dijitSliderButton {
-	font-family:monospace;
-	margin:0;
-	padding:0;
-	display:block;
-}
-.dijit_a11y .dijitSliderButtonInner {
-	visibility:visible !important;
-}
-.dijitSliderButtonContainer {
-	text-align:center;
-	height:0;
-}
-.dijitSlider .dijitButtonNode {
-	padding:0;
-	display:block;
-}
-.dijitRuleContainer {
-	position:relative;
-	overflow:visible;
-}
-.dijitRuleContainerV {
-	height:100%;
-	line-height:0;
-	float:left;
-	text-align:left;
-}
-.dj_opera .dijitRuleContainerV {
-	line-height:2%;
-}
-.dj_ie .dijitRuleContainerV {
-	line-height:normal;
-}
-.dj_gecko .dijitRuleContainerV {
-	margin:0 0 1px 0; 
-}
-.dijitRuleMark {
-	position:absolute;
-	border:1px solid black;
-	line-height:0;
-	height:100%;
-}
-.dijitRuleMarkH {
-	width:0;
-	border-top-width:0 !important;
-	border-bottom-width:0 !important;
-	border-left-width:0 !important;
-}
-.dijitRuleLabelContainer {
-	position:absolute;
-}
-.dijitRuleLabelContainerH {
-	text-align:center;
-	display:inline-block;
-}
-.dijitRuleLabelH {
-	position:relative;
-	left:-50%;
-}
-.dijitRuleMarkV {
-	height:0;
-	border-right-width:0 !important;
-	border-bottom-width:0 !important;
-	border-left-width:0 !important;
-	width:100%;
-	left:0;
-}
-.dj_ie .dijitRuleLabelContainerV {
-	margin-top:-.55em;
-}
-.dijit_a11y .dijitButtonContents .dijitButtonText,
-.dijit_a11y .dijitTab .tabLabel {
-	display: inline !important;
-}
-.dj_ie7 .dijitButtonNode > BUTTON.dijitButtonContents > * {
-	position: relative; 
-}
-.dijitTextArea {
-	width:100%;
-	overflow-y: auto;	
-}
-.dijitTextArea[cols] {
-	width:auto; 
-}
-.dj_ie .dijitTextAreaCols {
-	width:auto;
-}
-.dijitTextArea > DIV {
-	text-decoration:none;
-	overflow:auto;
-	min-height: 1.40em;
-}
-.dj_ie .dijitTextArea p {
-	margin-top:0;
-	margin-bottom:0;
-	line-height: normal !important;
-}
-.dijitToolbarSeparator {
-	height: 18px;
-	width: 5px;
-	padding: 0 1px;
-	margin: 0;
-}
-.dijitIEFixedToolbar {
-	position:absolute;
-	
-	top: expression(eval((document.documentElement||document.body).scrollTop));
-}
-.RichTextEditable {
-	display: block;	
-}
-.dijitTimePickerItemInner {
-	text-align:center;
-	border:0;
-	padding:2px 8px 2px 8px;
-}
-.dijitTimePickerTick,
-.dijitTimePickerMarker {
-	border-bottom:1px solid gray;
-}
-.dijitTimePicker .dijitDownArrowButton {
-	border-top: none !important;
-}
-.dijitTimePickerTick {
-	color:#CCC;
-}
-.dijitTimePickerMarker {
-	color:black;
-	background-color:#CCC;
-}
-.dijitTimePickerItemSelected {
-	font-weight:bold;
-	color:#333;
-	background-color:#b7cdee;
-}
-.dijitTimePickerItemHover {
-	background-color:gray;
-	color:white;
-	cursor:pointer;
-}
-.dijit_a11y .dijitTimePickerItem {
-	border-bottom:1px solid #333;
-}
-.dijitToggleButtonIconChar {
-	display:none !important;
-}
-.dijit_a11y .dijitToggleButtonIconChar {
-	display:inline !important;
-}
-.dijit_a11y .dijitToggleButtonIconChar {
-	visibility:hidden;
-}
-.dijit_a11y .dijitToggleButtonChecked .dijitToggleButtonIconChar {
-	visibility:visible !important;
-}
-.dijitArrowButtonChar {
-	display:none !important;
-}
-.dijit_a11y .dijitArrowButtonChar {
-	display:inline !important;
-}
-.dijitInputLayoutContainer {
-	position: relative;
-	overflow: hidden;
-}
-.dijitSpinnerButtonContainer {
-	float: right;
-	width: 18px;
-	position: relative;
-	overflow: hidden;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	height: 50%;
-	width: 16px;
-	overflow: hidden;
-}
-.dijitSpinner .dijitInputLayoutContainer .dijitArrowButtonInner {
-	overflow: hidden;
-	line-height: 50%;
-}
-.dijit_a11y .dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	width: 100%;
-}
-.dijit_a11y .dijitSpinner .dijitArrowButton .dijitArrowButtonChar {
-	font-size: 0.4em;
-	vertical-align: top;
-}
-.dijit_a11y .dijitSpinnerButtonContainer {
-	width: 0.5em;
-	margin-left: 2px;
-	overflow: visible;
-}
-.dijit_a11y .dijitSpinnerButtonContainer .dijitButtonNode {
-	border-width: 1px 0px 0px 1px;
-	border-style: solid !important;
-}
-.dijitSelect {
-	margin: 0.2em;
-}
-.dj_ie .dijitSelect,
-.dj_ie7 .dijitSelect,
-.dj_iequirks .dijitSelect {
-	vertical-align: middle; 
-}
-.dj_ie8 .dijitSelect .dijitButtonText {
-	vertical-align: top;
-}
-.dijitSelect .dijitButtonNode {
-	text-align: left;
-}
-.dijitRtl .dijitSelect .dijitButtonNode {
-	text-align: right;
-}
-.dijitToolbar .dijitSelect {
-	margin: 0;
-}
-.dj_webkit .dijitToolbar .dijitSelect {
-	padding-left: 0.3em;
-}
-.dijit_a11y .dijitSelectDisabled .dijitButtonNode {
-	border-style: outset!important;
-	border-width: medium!important;
-	border-color: #999 !important;
-	color:#999 !important;
-}
-.dijitSelect .dijitButtonContents {
-	padding: 0px;
-	background: transparent none;
-}
-.dijitSelectFixedWidth .dijitButtonContents {
-	width: 100%;
-}
-.dijitSelect .dijitArrowButton {
-	width: 16px;
-}
-.dj_ie6 .dijitSelectMenu .dijitMenuItemLabel,
-.dj_ie7 .dijitSelectMenu .dijitMenuItemLabel {
-	
-	position: static;
-}
-.dijitSelectLabel *
-{
-	vertical-align: baseline;
-}
-.dijitSelectSelectedOption * {
-	font-weight: bold;
-}
-.dijitSelectMenu {
-	border-width: 1px;
-}
-.dijitSelect .dijitButtonContents {
-	white-space: nowrap;
-}
-.dijitSelectMenu .dijitMenuTable {
-	margin: 0px;
-	background-color: transparent;
-}
-.dijitTextBoxReadOnly,
-.dijitComboBoxReadOnly,
-.dijitSpinnerReadOnly,
-.dijitTextAreaReadOnly,
-.dijitTextBoxDisabled,
-.dijitComboBoxDisabled,
-.dijitSpinnerDisabled,
-.dijitTextAreaDisabled {
-	color: gray;
-}
-.dj_webkit .dijitTextBoxDisabled INPUT,
-.dj_webkit .dijitComboBoxDisabled INPUT,
-.dj_webkit .dijitSpinnerDisabled INPUT {
-	color: #eee;
-}
-.dj_webkit INPUT.dijitTextBoxDisabled,
-.dj_webkit TEXTAREA.dijitTextAreaDisabled {
-	color: #333; 
-}
-.dijit_a11y .dijitSliderReadOnly,
-.dijit_a11y .dijitSliderDisabled {
-	opacity:0.6;
-}
-.dj_ie .dijit_a11y .dijitSliderReadOnly .dijitSliderBar,
-.dj_ie .dijit_a11y .dijitSliderDisabled .dijitSliderBar {
-	filter: alpha(opacity=40);
-}
-.dijit_a11y .dijitSlider .dijitSliderButtonContainer DIV {
-	font-family: monospace; 
-	font-size: 1em;
-	line-height: 1em;
-	height: auto;
-	width: auto;
-	margin: 0px 4px;
-}
-.dijitForceStatic {
-    position: static !important;
-}
-.tundra .dojoDndItemBefore {
-	border-top: 2px solid #369;
-}
-.tundra .dojoDndItemAfter {
-	border-bottom: 2px solid #369;
-}
-.tundra .dojoDndItemOver {
-	cursor:pointer;
-}
-.tundra table.dojoDndAvatar { -moz-border-radius: 0; border: 1px solid #ccc; border-collapse: collapse; background-color: #fff; font-size: 75%; color: black;}
-.tundra .dojoDndAvatar td	{ border: none; }
-.tundra .dojoDndAvatar tr	{ border: none; }
-.tundra .dojoDndAvatarHeader td	{ height: 20px; padding: 0 0 0 21px; }
-.tundra .dojoDndAvatarItem td { padding: 2px;}
-.tundra.dojoDndMove .dojoDndAvatarHeader	{background-color: #f58383; background-image: url(images/dndNoMove.png); background-repeat: no-repeat; background-position: 2px center;}
-.tundra.dojoDndCopy .dojoDndAvatarHeader	{background-color: #f58383; background-image: url(images/dndNoCopy.png); background-repeat: no-repeat; background-position: 2px center;}
-.tundra.dojoDndMove .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{background-color: #97e68d; background-image: url(images/dndMove.png); background-repeat: no-repeat; background-position: 2px center;}
-.tundra.dojoDndCopy .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{background-color: #97e68d; background-image: url(images/dndCopy.png); background-repeat: no-repeat; background-position: 2px center;}
-.tundra .dijitContentPaneLoading {
-	background:url(images/loading.gif) no-repeat left center;
-	padding-left:25px;
-}
-.tundra .dijitContentPaneError {
-	background:url(images/warning.png) no-repeat left center;
-	padding-left:25px;
-}
-.tundra .dijitContentPane {
-	padding: 0px;
-}
-.tundra .dijitTabContainerTop-dijitContentPane,
-.tundra .dijitTabContainerLeft-dijitContentPane,
-.tundra .dijitTabContainerBottom-dijitContentPane,
-.tundra .dijitTabContainerRight-dijitContentPane,
-.tundra .dijitAccordionContainer-dijitContentPane {
-	background-color: #fff;
-	padding: 5px;
-}
-.tundra .dijitSplitContainer-dijitContentPane,
-.tundra .dijitBorderContainer-dijitContentPane {
-	background-color: #fff;		
-	padding: 5px;
-}
-.tundra .dijitTabPaneWrapper {
-	background:#fff;
-	border:1px solid #ccc;
-	margin: 0;
-	padding: 0;
-}
-.tundra .dijitTab {
-	line-height:normal;
-	margin-right:4px;	
-	padding:0px;
-	border:1px solid #ccc;
-	background:#e2e2e2 url(images/tabEnabled.png) repeat-x;
-}
-.tundra .dijitTabInnerDiv {
-	padding:2px 8px 2px 9px;
-}
-.tundra .dijitTabSpacer {
-	display: none;
-}
-.tundra .dijitTabContainer .tabStripRBtn {
-	margin-right: 20px;
-}
-.tundra .dijitTabContainer .tabStripLBtn {
-	margin-left: 20px;
-}
-.tundra .nowrapTabStrip .dijitTab {
-	top: 2px;
-}
-.tundra .dijitTabContainerBottom .nowrapTabStrip .dijitTab {
-	top: 0px;
-	bottom: 2px;
-}
-.tundra .dijitTabContainer .tabStripMenuButton-Hover {
-	cursor: pointer;
-}
-.tundra .dijitTabChecked {
-	
-	background-color:#fff;
-	border-color: #ccc;
-	background-image:none;
-}
-.tundra .dijitTabHover {
-	color: #243C5F;
-	border-top-color:#92a0b3;
-	border-left-color:#92a0b3;
-	border-right-color:#92a0b3;
-	border-bottom-color:#92a0b3;
-	background:#e2e2e2 url(images/tabHover.gif) repeat-x;
-}
-.tundra .dijitTabContainerTop .dijitTabHover {
-	border-bottom-color:#ccc;
-}
-.tundra .dijitTabContainerBottom .dijitTabHover {
-	border-top-color:#ccc;
-}
-.tundra .dijitTabContainerLeft .dijitTabHover {
-	border-right-color:#ccc;
-}
-.tundra .dijitTabContainerRight .dijitTabHover {
-	border-left-color:#ccc;
-}
-.tundra .dijitTabContainer .dijitTabCheckedHover {
-	color: inherit;
-	border:1px solid #ccc;
-	background:#fff;
-}
-.tundra .dijitTab .dijitClosable .closeImage {
-	background: url(images/tabClose.png) no-repeat right top;
-	width: 12px;
-	height: 12px;
-}
-.tundra .dijitTab .tabLabel {
-	
-	min-height: 12px;
-	display: inline-block;
-}
-.tundra .dijitTabContainerNested .dijitTabListWrapper {
-	height: auto;
-}
-.tundra .dijitTabContainerNested .dijitTabContainerTop-tabs {
-	border-bottom: 1px solid #CCC;
-}
-.tundra .dijitTabContainerTabListNested .dijitTab {
-	background: none;
-	border: none;
-	top: 0px;		
-}
-.tundra .dijitTabContainerTabListNested .dijitTab .dijitTabContent {
-}
-.tundra .dijitTabContainerTabListNested .dijitTabHover .dijitTabContent .tabLabel {
-	text-decoration: underline;
-}
-.tundra .dijitTabContainerTabListNested .dijitTabChecked .dijitTabContent .tabLabel {
-	text-decoration: underline;
-	font-weight: bold;
-	
-}
-.tundra .dijitTabContainer .dijitTabPaneWrapperNested {
-	border: none;	
-}
-.tundra .dijitTab .closeImage {
-	background-image : url(images/tabClose.png);
-}
-.dj_ie6 .tundra .dijitTab .closeImage {
-	background-image : url(images/tabClose.gif);
-}
-.tundra .dijitTab .closeButton-hover .closeImage {
-	background-image : url(images/tabCloseHover.png);
-}
-.dj_ie6 .tundra .dijitTab .closeButton-hover .closeImage {
-	background-image : url(images/tabCloseHover.gif);
-}
-.tundra .dijitTabContainerTop-tabs {
-	margin-bottom: 0px;
-	border-color: #cccccc;
-	padding-left: 3px;
-	background-position: bottom;
-}
-.tundra .dijitTabContainerTop-tabs .dijitTab {
-	top: 0px;
-	margin-bottom: -1px;
-}
-.tundra .dijitTabContainerTop-container {
-	border-top: none;
-}
-.tundra .dijitTabContainerTop-tabs .dijitTabChecked {
-	border-bottom-color:white;
-}
-.tundra .dijitTabContainerTop-tabs,
-.tundra .dijitTabContainerBottom-tabs {
-	padding-left: 3px;
-	padding-right: 3px;
-}
-.tundra .dijitTabContainerTopStrip {
-	border-top: 1px solid #CCC;
-	border-right: 1px solid #CCC;
-	border-left: 1px solid #CCC;
-	padding-top: 2px;
-	background: #f2f2f2;
-}
-.tundra .dijitTabContainerTopNone {
-	padding-top: 0px;
-}
-.tundra .dijitTabContainerBottom-tabs {
-	margin-top: 0px;
-	border-color: #cccccc;
-	background-position: top;
-	padding-left: 3px;
-}
-.tundra .dijitTabContainerBottom-tabs .dijitTab {
-	bottom: 0px;
-	margin-top: -1px;
-}
-.tundra .dijitTabContainerBottom-container {
-	border-bottom: none;
-}
-.tundra .dijitTabContainerBottom-tabs .dijitTabChecked {
-	border-top-color:white;
-}
-.tundra .dijitTabContainerBottomStrip {
-	padding-bottom: 2px;
-	border: 1px solid #ccc;
-	background: #f2f2f2;
-	border-top: none;
-}
-.tundra .dijitTabContainerRight-tabs {
-	border-color: #ccc;
-	height: 100%;
-	padding-top: 3px;
-}
-.tundra .dijitTabContainerRightStrip {
-	margin-left: -1px;
-}
-.tundra .dijitTabContainerRight-container {
-	border-right: none;
-}
-.tundra .dijitTabContainerRight-tabs .dijitTabChecked {
-	border-left-color:white;
-}
-.tundra .dijitTabContainerRightStrip {
-	padding-right: 2px;
-	border: 1px solid #ccc;
-}
-.tundra .dijitTabContainerRightStrip {
-	background: #f2f2f2;
-}
-.tundra .dijitTabContainerLeft-tabs {
-	border-color: #ccc;
-	padding-top: 3px;
-	height: 100%;
-}
-.tundra .dijitTabContainerLeft .dijitTabListWrapper {
-}
-.tundra .dijitTabContainerLeft-container {
-	border-left: none;
-}
-.tundra .dijitTabContainerLeft-tabs .dijitTabChecked {
-	border-right-color:white;
-}
-.tundra .dijitTabContainerLeftStrip {
-	padding-left: 2px;
-	border: 1px solid #ccc;
-	background: #f2f2f2;
-	border-right: none;
-}
-.tundra .dijitTabContainerLeft-tabs .dijitTab,
-.tundra .dijitTabContainerRight-tabs .dijitTab {
-	margin-right:0px;
-	margin-bottom:4px;	
-}
-.tundra .dijitTabContainerTop-dijitContentPane .dijitTabContainerTop-tabs {
-	border-left: 0px solid #ccc;
-	border-top: 0px solid #ccc;
-	border-right: 0px solid #ccc;
-	padding-top: 0px;
-	padding-left: 0px;
-}
-.tundra .dijitTabContainer .tabStripButton {
-	margin-right: 0;
-	padding-top: 2px;
-	z-index: 12;
-}
-.tundra .dijitTabContainerBottom .tabStripButton {
-	padding-top: 2px;
-}
-.tundra .tabStrip-disabled .tabStripButton .dijitTabInnerDiv {
-	padding-bottom: 3px;
-	padding-top: 1px;
-}
-.tundra .tabStripButton .dijitTabInnerDiv {
-	padding: 3px 2px 4px 2px;
-}
-.dj_ie6 .tundra .tabStripButton .dijitTabInnerDiv,
-.dj_ie7 .tundra .tabStripButton .dijitTabInnerDiv,
-.dj_opera .tundra .tabStripButton .dijitTabInnerDiv {
-	padding-bottom: 5px;
-}
-.dj_ie6 .tundra .tabStrip-disabled .tabStripButton .dijitTabInnerDiv,
-.dj_ie7 .tundra .tabStrip-disabled .tabStripButton .dijitTabInnerDiv,
-.dj_opera .tundra .tabStrip-disabled .tabStripButton .dijitTabInnerDiv {
-	padding-bottom: 4px;
-}
-.tundra .dijitTabContainer .tabStripButton {
-	
-	width: 21px;
-}
-.tundra .dijitTabContainer .tabStripButton img {
-	height: 14px;
-	background: url(images/spriteRoundedIconsSmall.png) no-repeat;
-}
-.dj_ie6 .tundra .dijitTabContainer .tabStripButton img {
-	background-image: url(images/spriteRoundedIconsSmall.gif);
-}
-.tundra .dijitTabContainer .tabStripMenuButton img {
-	background-position: -15px top;
-}
-.tundra .dijitTabContainer .tabStripSlideButtonLeft img {
-	background-position: 0px top;
-}
-.tundra .dijitTabContainer .tabStripSlideButtonRight img {
-	background-position: -30px top;
-}
-.tundra .dijitAccordionContainer {
-	border-color: #ccc;
-	background-color: #fff;
-}
-.tundra .dijitAccordionTitle {
-	background:#fafafa url(images/titleBar.png) repeat-x bottom left;
-	border-top: 1px solid #bfbfbf;
-	padding: 4px 4px 4px 8px;
-	cursor:pointer;
-}
-.tundra .dijitAccordionTitle-hover  {
-	background: #f8fafd url(images/accordionItemHover.gif) bottom repeat-x;
-}
-.tundra .dijitAccordionTitle-selected  {
-	background: #f9f9f9 url(images/accordionItemActive.gif) bottom repeat-x;
-	font-weight: bold;
-	border-top: 1px solid #aaaaaa;
-	border-bottom: 1px solid #bfbfbf;
-	padding: 4px 4px 4px 8px;
-	cursor: default;
-}
-.tundra .dijitSplitContainerSizerH {
-	background:url(images/splitContainerSizerV.png) repeat-y #fff;
-	border:0;
-	border-left:1px solid #bfbfbf;
-	border-right:1px solid #bfbfbf;
-	width:7px;
-}
-.tundra .dijitSplitContainerSizerH .thumb {
-	background:url(images/splitContainerSizerV-thumb.png) no-repeat #ccc;
-	left:1px;
-	width:3px;
-	height:19px;
-	overflow: hidden;
-}
-.tundra .dijitSplitContainerSizerV {
-	background:url(images/splitContainerSizerH.png) repeat-x #fff;
-	border:0;
-	border-top:1px solid #bfbfbf;
-	border-bottom:1px solid #bfbfbf;
-	height:7px;
-}
-.tundra .dijitSplitContainerSizerV .thumb {
-	background:url(images/splitContainerSizerH-thumb.png) no-repeat #ccc;
-	top:1px;
-	width:19px;
-	height:3px;
-	overflow: hidden;
-}
-.tundra .dijitSplitter {
-	border-color: #bfbfbf;
-}
-.tundra .dijitBorderContainer {
-	background-color: #fcfcfc;
-	padding: 5px;
-}
-.tundra .dijitSplitContainer-child,
-.tundra .dijitBorderContainer-child {
-	
-	border: 1px #ccc solid;
-}
-.tundra .dijitBorderContainer-dijitTabContainerTop,
-.tundra .dijitBorderContainer-dijitTabContainerBottom,
-.tundra .dijitBorderContainer-dijitTabContainerLeft,
-.tundra .dijitBorderContainer-dijitTabContainerRight {
-	
-	 border: none;
-}
-.tundra .dijitBorderContainer-dijitBorderContainer {
-	
-	border: none;
-	padding: 0px;
-}
-.tundra .dijitSplitterH,
-.tundra .dijitGutterH {
-	background:#fcfcfc;
-	border:0;
-	height:5px;
-}
-.tundra .dijitSplitterH .dijitSplitterThumb {
-	background:#B0B0B0 none;
-	height:1px;
-	top:2px;
-	width:19px;
-}
-.tundra .dijitSplitterV,
-.tundra .dijitGutterV {
-	background:#fcfcfc;
-	border:0;
-	width:5px;
-}
-.tundra .dijitSplitterV .dijitSplitterThumb {
-	background:#B0B0B0 none;
-	height:19px;
-	left:2px;
-	width:1px;
-}
-.tundra .dijitSplitterActive {
-	font-size: 1px;
-	background-image: none;
-	background-color: #aaa;
-	-moz-opacity: 0.6;
-	opacity: 0.6;
-	filter: Alpha(Opacity=60);
-	margin: 0;
-}
-.tundra .dijitInputField INPUT,
-.tundra .dijitTextBox,
-.tundra .dijitComboBox,
-.tundra .dijitSpinner {
-	margin: 0em 0.1em;
-}
-.tundra .dijitTextBox,
-.tundra .dijitComboBox,
-.tundra .dijitSpinner,
-.tundra .dijitTextArea {
-	font-family: sans-serif;
-	font-size: 100%;
-}
-.tundra .dijitTextArea {
-	padding: 3px;
-}
-.tundra .dijitTextBox,
-.tundra .dijitComboBox,
-.tundra .dijitSpinner,
-.tundra .dijitTextArea,
-.tundra .dijitInlineEditor input {
-	
-	background:#fff url(images/validationInputBg.png) repeat-x top left;
-	#background:#fff url(images/validationInputBg.gif) repeat-x top left;
-	border:1px solid #b3b3b3;
-	line-height: normal;
-}
-.tundra .dijitComboBox .dijitInputField {
-	padding: 1px 0;
-}
-.tundra .dijitComboBox .dijitButtonNode {
-	padding: 1px 0.2em;
-}
-.tundra .dijitComboBox .dijitButtonNode,
-.tundra .dijitSpinner .dijitButtonNode {
-	
-	border-color: #9b9b9b;
-	border-width: 0px 0px 0px 1px;
-	border-style: solid;
-}
-.tundra .dijitTextBoxFocused,
-.tundra .dijitComboBoxFocused,
-.tundra .dijitSpinnerFocused, .tundra .dijitSpinnerUpArrowActive, .tundra .dijitSpinnerDownArrowActive,
-.tundra .dijitTextAreaFocused {
-	
-	border-color:#406b9b;
-}
-.tundra .dijitComboBoxFocused .dijitButtonNode,
-.tundra .dijitSpinnerFocused .dijitButtonNode,
-.tundra .dijitSpinnerUpArrowActive .dijitButtonNode,
-.tundra .dijitSpinnerDownArrowActive .dijitButtonNode {
-	border-left-color:#366dba;
-}
-.tundra .dijitSpinnerFocused .dijitDownArrowButton,
-.tundra .dijitSpinnerUpArrowActive .dijitDownArrowButton,
-.tundra .dijitSpinnerDownArrowActive .dijitDownArrowButton {
-	border-top-color:#366dba;
-}
-.tundra .dijitError {
-	background-color:#f9f7ba;
-	background-image:none;
-}
-.dj_ie6 .tundra .dijitError INPUT {
-	
-	background-color:#f9f7ba !important;
-}
-.tundra .dijitErrorFocused {
-	background-color:#f9f999;
-	background-image:none;
-}
-.dj_ie6 .tundra .dijitErrorFocused INPUT {
-	
-	background-color:#f9f999 !important;
-}
-.tundra .dijitValidationIcon {
-	
-	width: 16px;
-	background: transparent url(images/warning.png) no-repeat center center;
-}
-.tundra .dijitInlineValue {
-	
-	padding:3px;
-	margin:4px;
-}
-.tundra .dijitInlineEditor {
-	
-	display: inline-block;
-	#display:inline;
-}
-.dijitInlineEditor .saveButton,
-.dijitInlineEditor .cancelButton {
-	margin:3px 3px 3px 0px;
-}
-.RichTextEditable {
-	border:1px solid #bfbfbf;
-	border-top:0;
-}
-.tundra .dijitComboBoxHighlightMatch {
-	background-color:#a5beda;
-}
-.tundra .dijitFocusedLabel {
-	
-	outline: 1px dotted #666666;
-}
-.tundra .dijitButtonNode {
-	
-	border: 1px solid #c0c0c0;
-	border-bottom: 1px solid #9b9b9b;
-	padding: 0.1em 0.2em 0.2em 0.2em;
-	background: #fff url(images/buttonEnabled.png) repeat-x bottom left;
-}
-.tundra .dijitSelect .dijitButtonContents {
-	border-right: none;
-}
-.dijitRtl .tundra .dijitSelect .dijitButtonContents {
-	border-left: none;
-	border-right-width: 1px;
-}
-.tundra .dijitButtonNode button {
-	border: 0px;
-	background-color: transparent;
-}
-.tundra .dijitButtonText {
-	text-align: center;
-	padding: 0 0.3em;
-}
-.tundra .dijitDisabled .dijitButtonText {
-	color: #7F7F7F;
-}
-.tundra .dijitArrowButton {
-	color: #111;
-}
-.tundra .dijitComboButton .dijitDownArrowButton {
-	padding-right:4px;
-}
-.tundra .dijitComboBoxReadOnly,
-.tundra .dijitSpinnerReadOnly,
-.tundra .dijitSpinnerReadOnly .dijitButtonNode,
-.tundra .dijitButtonDisabled .dijitButtonNode,
-.tundra .dijitToggleButtonDisabled .dijitButtonNode,
-.tundra .dijitDropDownButtonDisabled .dijitButtonNode,
-.tundra .dijitComboButtonDisabled .dijitButtonNode,
-.tundra .dijitComboBoxDisabled,
-.tundra .dijitSpinnerDisabled,
-.tundra .dijitSpinnerDisabled .dijitButtonNode {
-	
-	
-	border-color: #d5d5d5 #d5d5d5 #bdbdbd #d5d5d5;
-	background:#e4e4e4 url(images/buttonDisabled.png) top repeat-x;
-}
-.tundra .dijitButtonHover .dijitButtonNode,
-.tundra .dijitButtonNodeHover,
-.tundra .dijitToggleButtonHover .dijitButtonNode,
-.tundra .dijitDropDownButtonHover .dijitButtonNode,
-.tundra .dijitComboButtonHover .dijitButtonContents,
-.tundra .dijitComboButtonDownArrowHover .dijitArrowButton {
-	
-	
-	border-color: #a5beda;
-	border-bottom-color:#5c7590;
-	color:#243C5F;
-	background:#fcfdff url(images/buttonHover.png) repeat-x bottom;
-}
-.tundra .dijitComboBoxHover .dijitDownArrowButton,
-.tundra .dijitSpinnerUpArrowHover .dijitUpArrowButton,
-.tundra .dijitSpinnerDownArrowHover .dijitDownArrowButton {
-	
-	color:#243C5F;
-	background:#fcfdff url(images/buttonHover.png) repeat-x bottom;
-}
-.tundra .dijitSpinnerUpArrowActive .dijitUpArrowButton,
-.tundra .dijitSpinnerDownArrowActive .dijitDownArrowButton,
-.tundra .dijitButtonActive .dijitButtonNode,
-.tundra .dijitToggleButtonActive .dijitButtonNode,
-.tundra .dijitDropDownButtonActive .dijitButtonNode,
-.tundra .dijitComboButtonActive .dijitButtonContents,
-.tundra .dijitDownArrowActive .dijitDownArrowButton,
-.tundra .dijitComboBoxActive .dijitDownArrowButton,
-.tundra .dijitStackController .dijitToggleButtonChecked .dijitButtonNode {
-	
-	border-color:#366dba;
-	background: #ededed url(images/buttonActive.png) bottom repeat-x;
-}
-.tundra .dijitArrowButtonInner {
-	background:url(images/spriteArrows.png) no-repeat scroll 0px center;
-	width: 7px;
-	height: 7px;
-	font-size: 1px;
-	margin: 0px 4px 0px 5px;
-}
-.dj_ie6 .tundra .dijitArrowButtonInner {
-	background-image:url(images/spriteArrows.gif);
-}
-.tundra .dijitLeftArrowButton .dijitArrowButtonInner {
-	background-position: -7px center;
-}
-.tundra .dijitRightArrowButton .dijitArrowButtonInner {
-	background-position: -14px center;
-}
-.tundra .dijitUpArrowButton .dijitArrowButtonInner {
-	background-position: -21px center;
-}
-.tundra .dijitDisabled .dijitArrowButtonInner {
-	background-position: -28px center;
-}
-.tundra .dijitDisabled .dijitLeftArrowButton .dijitArrowButtonInner {
-	background-position: -35px center;
-}
-.tundra .dijitDisabled .dijitRightArrowButton .dijitArrowButtonInner {
-	background-position: -42px center;
-}
-.tundra .dijitDisabled .dijitUpArrowButton .dijitArrowButtonInner {
-	background-position: -49px center;
-}
-.tundra .dijitComboBox .dijitArrowButton .dijitArrowButtonInner {
-	height: auto;
-	font-size: 100%;
-	font-size: inherit;
-}
-.tundra .dijitComboBoxHover .dijitArrowButtonInner {
-	
-}
-.tundra .dijitSpinner .dijitArrowButtonInner {
-	display: block;  
-	position:absolute;
-	top: 50%;
-	margin-top: -4px; 
-	left: 50%;
-	margin-left: -4px; 
-	line-height: 2px;
-}
-.tundra .dijitToggleButton .dijitCheckBoxIcon {
-	background-image: url(images/checkmarkNoBorder.png);
-}
-.dj_ie6 .tundra .dijitToggleButton .dijitCheckBoxIcon {
-	background-image: url(images/checkmarkNoBorder.gif);
-}
-.tundra .dijitCheckBox,
-.tundra .dijitCheckBoxIcon			{
-	background-image: url(images/checkmark.png); 
-	background-repeat: no-repeat;
-	width: 16px;
-	height: 16px;
-	margin: 0 2px 0 0;
-	padding: 0;
-}
-.dj_ie6 .tundra .dijitCheckBox,
-.dj_ie6 .tundra .dijitCheckBoxIcon			{
-	background-image: url(images/checkmark.gif); 
-}
-.tundra .dijitCheckBox,
-.tundra .dijitToggleButton .dijitCheckBoxIcon {
-	
-	background-position: -16px;
-}
-.tundra .dijitCheckBoxChecked,
-.tundra .dijitToggleButtonChecked .dijitCheckBoxIcon {
-	
-	background-position: 0px;
-}
-.tundra .dijitCheckBoxDisabled {
-	
-	background-position: -48px;
-}
-.tundra .dijitCheckBoxCheckedDisabled {
-	
-	background-position: -32px;
-}
-.tundra .dijitCheckBoxHover {
-	
-	background-position: -80px;
-}
-.tundra .dijitCheckBoxCheckedHover {
-	
-	background-position: -64px;
-}
-.tundra .dijitToggleButton .dijitRadio,
-.tundra .dijitToggleButton .dijitRadioIcon {
-	background-image: url(images/checkmarkNoBorder.png);
-}
-.dj_ie6 .tundra .dijitToggleButton .dijitRadio,
-.dj_ie6 .tundra .dijitToggleButton .dijitRadioIcon {
-	background-image: url(images/checkmarkNoBorder.gif);
-}
-.tundra .dijitRadio,
-.tundra .dijitRadioIcon	{		
-	background-image: url(images/checkmark.png); 
-	background-repeat: no-repeat;
-	width: 16px;
-	height: 16px;
-	margin: 0;
-	padding: 0;
-}
-.dj_ie6 .tundra .dijitRadio,
-.dj_ie6 .tundra .dijitRadioIcon	{		
-	background-image: url(images/checkmark.gif); 
-}
-.tundra .dijitRadio,
-.tundra .dijitToggleButton .dijitRadioIcon {
-	
-	background-position: -112px;
-}
-.tundra .dijitRadioDisabled {
-	
-	background-position: -144px;
-}
-.tundra .dijitRadioHover {
-	
-	background-position: -176px;
-}
-.tundra .dijitRadioChecked,
-.tundra .dijitRadioCheckedHover,
-.tundra .dijitToggleButtonChecked .dijitRadioIcon {
-	
-	background-position: -96px;
-}
-.tundra .dijitRadioCheckedDisabled {
-	
-	background-position: -128px;
-}
-.tundra .dijitSliderProgressBarH {
-	border-color: #aab0bb;
-	background: #c0c2c5 url(images/sliderFull.png) repeat-x top left;
-}
-.tundra .dijitSliderProgressBarV {
-	border-color: #aab0bb;
-	background: #c0c2c5 url(images/sliderFullVertical.png) repeat-y bottom left;
-}
-.tundra .dijitSliderFocused .dijitSliderProgressBarH,
-.tundra .dijitSliderFocused .dijitSliderLeftBumper {
-	background-image:url(images/sliderFullFocus.png);
-}
-.tundra .dijitSliderFocused .dijitSliderProgressBarV,
-.tundra .dijitSliderFocused .dijitSliderBottomBumper {
-	background-image:url(images/sliderFullVerticalFocus.png);
-}
-.tundra .dijitSliderRemainingBarV {
-	border-color: #b4b4b4;
-	background: #dcdcdc url(images/sliderEmptyVertical.png) repeat-y bottom left;
-}
-.tundra .dijitSliderRemainingBarH {
-	border-color: #b4b4b4;
-	background: #dcdcdc url(images/sliderEmpty.png) repeat-x top left;
-}
-.tundra .dijitSliderBar {
-	border-style: solid;
-	outline:1px;
-}
-.tundra .dijitSliderFocused .dijitSliderBar {
-	border-color:#888;
-}
-.dijit_a11y .dijitSliderProgressBar {
-	background-color:#888 !important;
-}
-.tundra .dijitSliderImageHandleH {
-	border:0px;
-	width:16px;
-	height:16px;
-	background:url(images/preciseSliderThumb.png) no-repeat center top;
-	cursor:pointer;
-}
-.tundra .dijitSliderFocused .dijitSliderImageHandleH {
-	background-image:url(images/preciseSliderThumbFocus.png);
-	#background-image:url(images/preciseSliderThumbFocus.gif);
-}
-.dj_ie6 .tundra .dijitSliderImageHandleH {
-	background-image:url(images/preciseSliderThumb.gif);
-}
-.tundra .dijitSliderLeftBumper {
-	border-left-width: 1px;
-	border-color: #aab0bb;
-	background: #c0c2c5 url(images/sliderFull.png) repeat-x top left;
-}
-.tundra .dijitSliderRightBumper {
-	background: #dcdcdc url(images/sliderEmpty.png) repeat-x top left;
-	border-color: #b4b4b4;
-	border-right-width: 1px;
-}
-.tundra .dijitSliderImageHandleV {
-	border:0px;
-	width:16px;
-	height:16px;
-	background:url(images/sliderThumb.png) no-repeat center center;
-	cursor:pointer;
-}
-.tundra .dijitSliderFocused .dijitSliderImageHandleV {
-	background-image:url(images/sliderThumbFocus.png);
-}
-.dj_ie6 .tundra .dijitSliderFocused .dijitSliderImageHandleV {
-	background-image:url(images/sliderThumbFocus.gif);
-}
-.tundra .dijitSliderBottomBumper {
-	border-bottom-width: 1px;
-	border-color: #aab0bb;
-	background: #c0c2c5 url(images/sliderFullVertical.png) repeat-y bottom left;
-}
-.tundra .dijitSliderTopBumper {
-	background: #dcdcdc url(images/sliderEmptyVertical.png) repeat-y top left;
-	border-color: #b4b4b4;
-	border-top-width: 1px;
-}
-.tundra .dijitSliderDecrementIconH,
-.tundra .dijitSliderDecrementIconV,
-.tundra .dijitSliderIncrementIconH,
-.tundra .dijitSliderIncrementIconV {
-	cursor: pointer;
-	background-image: url(images/spriteArrows.png);
-	background-repeat: no-repeat;
-	margin: 5px;
-	height: 7px;
-	width: 7px;
-	font-size: 1px;
-}
-.dj_ie6 .tundra .dijitSliderDecrementIconH,
-.dj_ie6 .tundra .dijitSliderDecrementIconV,
-.dj_ie6 .tundra .dijitSliderIncrementIconH,
-.dj_ie6 .tundra .dijitSliderIncrementIconV {
-	background-image: url(images/spriteArrows.gif);
-}
-.tundra .dijitSliderDecrementIconH {
-	background-position: -7px 0px;
-}
-.tundra .dijitSliderIncrementIconH {
-	background-position: -14px 0px;
-}
-.tundra .dijitSliderDecrementIconV {
-	background-position: 0px 0px;
-}
-.tundra .dijitSliderIncrementIconV {
-	background-position: -21px 0px;
-}
-.tundra .dijitSliderButtonInner {
-	visibility:hidden;
-}
-.tundra .dijitSliderReadOnly *,
-.tundra .dijitSliderDisabled * {
-	border-color: #d5d5d5 #bdbdbd #bdbdbd #d5d5d5;
-	color: #bdbdbd;
-}
-.tundra .dijitSliderReadOnly .dijitSliderDecrementIconH,
-.tundra .dijitSliderDisabled .dijitSliderDecrementIconH {
-	background-position: -35px 0px;
-}
-.tundra .dijitSliderReadOnly .dijitSliderIncrementIconH,
-.tundra .dijitSliderDisabled .dijitSliderIncrementIconH {
-	background-position: -42px 0px;
-}
-.tundra .dijitSliderReadOnly .dijitSliderDecrementIconV,
-.tundra .dijitSliderDisabled .dijitSliderDecrementIconV {
-	background-position: -28px 0px;
-}
-.tundra .dijitSliderReadOnly .dijitSliderIncrementIconV,
-.tundra .dijitSliderDisabled .dijitSliderIncrementIconV {
-	background-position: -49px 0px;
-}
-.tundra .dijitSelectDisabled * {
-    cursor: not-allowed !important;
-}
-.tundra .dijitSelectReadOnly * {
-    cursor: default !important;
-}
-.tundra .dijitSelect .dijitButtonNode {
-	padding: 0px;
-}
-.tundra .dijitSelect .dijitButtonContents {
-	padding-top: 1px;
-    background:#fff url(images/validationInputBg.png) repeat-x top left;
-    #background:#fff url(images/validationInputBg.gif) repeat-x top left;
-}
-.tundra .dijitSelectHover .dijitButtonContents,
-.tundra .dijitSelectActive .dijitButtonContents,
-.tundra .dijitSelectOpened .dijitButtonContents,
-.tundra .dijitSelectDisabled .dijitButtonContents,
-.tundra .dijitSelectReadOnly .dijitButtonContents{
-	background: transparent none;
-}
-.dj_ie .tundra .dijitSelect .dijitButtonContents {
-	padding-top: 0px;
-}
-.tundra .dijitSelectDisabled .dijitButtonNode {
-    border-color: #d5d5d5 #bdbdbd #bdbdbd #d5d5d5;
-    background:#e4e4e4 url(images/buttonDisabled.png) top repeat-x;
-}
-.dj_ie .tundra .dijitSelectDisabled  .dijitButtonNode * {
-	filter: gray() alpha(opacity=50);
-}
-.tundra .dijitSelectHover .dijitButtonNode {
-    border-color:#a5beda;
-    border-bottom-color:#5c7590;
-    border-right-color:#5c7590;
-    color:#243C5F;
-    background:#fcfdff url(images/buttonHover.png) repeat-x bottom;
-}
-.tundra .dijitSelectActive .dijitButtonNode,
-.tundra .dijitSelectOpened .dijitButtonNode {
-    border-color:#366dba;
-    background: #ededed url(images/buttonActive.png) bottom repeat-x;
-}
-.tundra .dijitSelectMenu td {
-	padding: 0em;
-}
-.tundra .dijitSelectMenu .dijitMenuItemIcon {
-	margin: 0.1em 0.2em;
-	display: none;
-}
-.tundra .dijitSelectMenu .dijitMenuItemLabel,
-.tundra .dijitSelectMenu .dijitMenuArrowCell {
-	padding: 0.1em 0.2em;
-}
-.tundra .dijitTreeNode {
-    background-image : url(images/i.gif);
-    background-repeat : repeat-y;
-    zoom: 1;	
-}
-.tundra .dijitTreeIsLast {
-    background: url(images/i_half.gif) no-repeat;
-}
-.tundra .dijitTreeIsRoot {
-    margin-left: 0;
-    background-image: none;
-}
-.tundra .dijitTreeExpando {
-    width: 18px;
-    height: 18px;
-}
-.tundra .dijitTreeRow {
-	
-	padding-bottom: 2px;
-}
-.tundra .dijitTreeContent {
-    min-height: 18px;
-    min-width: 18px;
- }
-.tundra .dijitTreeExpand {
-    width: 18px;
-    height: 18px;
-    background-repeat : no-repeat;
-}
-.tundra .dijitTreeNodeEmphasized {
-    background-color: Highlight;
-    color: HighlightText;
-}
-.tundra .dijitTreeLabelFocused {
-	outline: 1px invert dotted;
-}
-.tundra .dijitTreeNodeSelected .dijitTreeLabel {
-	background:#e2ebfe;
-}
-.tundra .dijitTreeNodeHover {
-	
-	
-	background-image: url(images/treeHover.png);
-	background-repeat: repeat;
-	background-color: none !important;
-}
-.tundra .dijitTreeExpandoOpened {
-	background-image: url(images/treeExpand_minus.gif);
-}
-.tundra .dijitTreeExpandoClosed {
-	background-image: url(images/treeExpand_plus.gif);
-}
-.tundra .dijitTreeExpandoLeaf {
-	background-image: url(images/treeExpand_leaf.gif);
-}
-.tundra .dijitTreeExpandoLoading {
-	background-image: url(images/treeExpand_loading.gif);
-}
-.tundra .dijitTreeIcon {
-	width: 16px;
-	height: 16px;
-}
-.tundra .dijitFolderOpened {
-	background: url(images/folderOpened.gif) no-repeat;
-}
-.tundra .dijitFolderClosed {
-	background: url(images/folderClosed.gif) no-repeat;
-}
-.tundra .dijitLeaf {
-	background: url(images/leaf.gif) no-repeat;
-}
-.tundra .dijitTreeNode .dojoDndItemBefore,
-.tundra .dijitTreeNode .dojoDndItemAfter {
-	border-bottom: none;
-	border-top: none;
-}
-.tundra .dijitTreeNode .dojoDndItemBefore .dijitTreeContent {
-	
-	border-top: 2px solid #369;
-}
-.tundra .dijitTreeNode .dojoDndItemAfter .dijitTreeContent {
-	
-	border-bottom: 2px solid #369;
-}
-.tundra .dijitProgressBar {
-	margin:2px 0px 2px 0px;
-}
-.tundra .dijitProgressBarEmpty {
-	
-	background:#fff url(images/progressBarEmpty.png) repeat-x center center;
-	border-color: #a2a2a2 #b8b8b8 #b8b8b8 #a2a2a2;
-}
-.tundra .dijitProgressBarTile {
-	
-	background:#f0f0f0 url(images/progressBarFull.png) repeat-x center center;
-}
-.tundra .dijitProgressBarFull {
-	border-right:1px solid #b8b8b8;
-}
-.tundra .dijitProgressBarLabel {
-	
-	color:#293a4b;
-}
-.tundra .dijitProgressBarIndeterminate .dijitProgressBarTile {
-	
-	background:#cad2de url(images/progressBarAnim.gif) repeat-x center center;
-}
-.tundra .dijitTitlePaneTitle {
-	background: #cccccc;
-	background:#fff url(images/titleBar.png) repeat-x bottom left;
-	border:1px solid #bfbfbf;
-	padding:3px 4px;
-}
-.tundra .dijitTitlePaneTitle-hover  {
-	background: #f8fafd url(images/accordionItemHover.gif) bottom repeat-x;
-	cursor: pointer;
-}
-.tundra .dijitTitlePaneTitle * {
-	vertical-align: middle;
-}
-.tundra .dijitTitlePane .dijitOpen .dijitArrowNode,
-.tundra .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background-image: url(images/spriteArrows.png);
-	background-repeat: no-repeat;
-	height: 7px;
-	width: 7px;
-}
-.dj_ie6 .tundra .dijitTitlePane .dijitArrowNode {
-	background-image: url(images/spriteArrows.gif);
-}
-.tundra .dijitTitlePane .dijitOpen .dijitArrowNode {
-	background-position: 0px 0px;
-}
-.tundra .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background-position: -14px 0px;
-}
-.tundra .dijitTitlePaneFocused .dijitTitlePaneTextNode {
-	text-decoration:underline;
-}
-.tundra .dijitTitlePane .dijitArrowNodeInner {
-	
-	display:none;
-}
-.dijit_a11y .dijitTitlePane .dijitOpen .dijitArrowNodeInner,
-.dijit_a11y .dijitTitlePane .dijitClosed .dijitArrowNodeInner {
-	display:inline !important;
-	font-family:monospace;
-	padding-bottom:.2em;
-}
-.dijit_a11y .dijitTitlePane .dijitArrowNode {
-	
-	display:none;
-}
-.tundra .dijitTitlePaneContentOuter {
-	background: #ffffff;
-	border:1px solid #bfbfbf;
-	border-top: 1px solid #ccc;	
-}
-.tundra .dijitTitlePaneContentInner {
-	padding:10px;
-}
-.dj_ie6 .tundra .dijitTitlePaneContentOuter,
-.dj_ie6 .tundra .dijitTitlePane .dijitTitlePaneTitle {
-	zoom: 1;
-}
-.tundra .dijitTitlePaneTextNode {
-	margin-left: 4px;
-	margin-right: 4px;
-}
-.tundra .dijitCalendarIncrementControl {
-	
-	width:15px;
-	height:15px;
-	background-image: url(images/spriteRoundedIconsSmall.png);
-	background-repeat: no-repeat
-}
-.dj_ie6 .tundra .dijitCalendarIncrementControl {
-	font-size:.1em;
-	background-image: url(images/spriteRoundedIconsSmall.gif);
-}
-.tundra .dijitA11ySideArrow {
-	display: none;
-}
-.tundra .dijitCalendarDecrease {
-	background-position: top left;
-}
-.tundra .dijitCalendarIncrease {
-	background-position: -30px top;
-}
-.tundra table.dijitCalendarContainer {
-	font-size: 100%;
-	border-spacing: 0;
-	border-collapse: separate;
-	border: 1px solid #ccc;
-	margin: 0;
-}
-.tundra .dijitCalendarMonthContainer th {
-	
-	background:#d3d3d3 url(images/titleBar.png) repeat-x top;
-	padding-top:.3em;
-	padding-bottom:.2em;
-	text-align:center;
-}
-.dj_ie6 .tundra .dijitCalendarMonthContainer th {
-	padding-top:.2em;
-	padding-bottom:.1em;
-}
-.tundra .dijitCalendarDayLabelTemplate {
-	
-	background:white url(images/calendarDayLabel.png) repeat-x bottom;
-	font-weight:normal;
-	padding-top:.15em;
-	padding-bottom:0em;
-	border-top: 1px solid #eeeeee;
-	color:#293a4b;
-	text-align:center;
-}
-.tundra .dijitCalendarBodyContainer {
-	border-bottom: 1px solid #eeeeee;
-}
-.tundra .dijitCalendarMonthLabel {
-	color:#293a4b;
-	font-weight: bold;
-}
-.tundra .dijitCalendarDateTemplate {
-	
-	font-size: 0.9em;
-	font-weight: bold;
-	text-align: center;
-	padding: 0.3em 0.3em 0.05em 0.3em;
-	letter-spacing: 1px;
-}
-.dj_ie .tundra .dijitCalendarDateTemplate {
-	padding: 0.1em .33em 0.02em .33em;
-}
-.tundra .dijitCalendarPreviousMonth,
-.tundra .dijitCalendarNextMonth 		{
-	
-	color:#999999;
-	background-color:#f8f8f8 !important;
-}
-.tundra .dijitCalendarPreviousMonthDisabled,
-.tundra .dijitCalendarNextMonthDisabled	{
-	
-	background-color:#a4a5a6 !important;
-}
-.tundra .dijitCalendarCurrentMonth {
-	
-	background-color:white !important;
-}
-.tundra .dijitCalendarCurrentMonthDisabled {
-	
-	background-color:#bbbbbc !important;
-}
-.tundra .dijitCalendarDisabledDate {
-	cursor:default !important;
-	text-decoration:line-through !important;
-}
-.tundra .dijitCalendarCurrentDate {
-	
-	text-decoration:underline;
-	font-weight:bold;
-}
-.tundra .dijitCalendarHoveredDate {
-	background-color: #e2ebf2 !important;
-}
-.tundra .dijitCalendarSelectedDate {
-	
-	background-color:#bbc4d0 !important;
-	color:black !important;
-}
-.tundra .dijitCalendarYearContainer {
-	
-	background:white url(images/calendarYearLabel.png) repeat-x bottom;
-	border-top:1px solid #ccc;
-}
-.tundra .dijitCalendarYearLabel {
-	
-	margin:0;
-	padding:0.4em 0 0.25em 0;
-	text-align:center;
-}
-.tundra .dijitCalendarSelectedYear {
-	
-	color:black;
-	padding:0.2em;
-	padding-bottom:0.1em;
-	background-color:#bbc4d0 !important;
-}
-.tundra .dijitCalendarNextYear,
-.tundra .dijitCalendarPreviousYear {
-	
-	color:black !important;
-	font-weight:normal;
-}
-.tundra .dijitTimePickerTick,
-.tundra .dijitTimePickerMarker {
-	border-color: #ccc;
-}
-.tundra .dijitTimePickerTick {
-	color:white;
-}
-.tundra .dijitTimePickerMarker {
-	background:#d3d3d3 url(images/titleBar.png) repeat-x top;
-	color:#293a4b;
-	font-weight: bold;
-}
-.tundra .dijitTimePickerItemSelected {
-	color: black;
-	background: #bbc4d0 none;
-}
-.tundra .dijitTimePickerItemHover {
-	background: #60a1ea none;
-	color:white;
-}
-.tundra .dijitTimePickerItemHover,
-.tundra .dijitTimePickerItemSelected {
-	position: relative;
-	z-index: 10;
-}
-.tundra .dijitTimePickerTick .dijitTimePickerItemInner {
-	font-size:0.4em;
-}
-.tundra .dijitTimePickerItemHover .dijitTimePickerItemInner,
-.tundra .dijitTimePickerItemSelected .dijitTimePickerItemInner {
-	font-size:1em;
-}
-.tundra .dijitTimePickerMarkerHover {
-	border-top: 1px solid #ccc;
-}
-.tundra .dijitTimePickerTickHover,
-.tundra .dijitTimePickerTickSelected {
-	margin-top:-0.3em;
-	margin-bottom:-0.3em;
-	border-bottom: none;
-}
-.dijit_a11y .dijitTimePickerTickHover {
-	background-color: #CCC !important;
-	border-top: 1px solid #333 !important;
-	border-bottom: 1px solid #333 !important;
-}
-.dijit_a11y .dijitTimePickerMarkerHover {
-	border-bottom-width: 2px;
-}
-.tundra .dijitToolbar {
-	border-bottom: 1px solid #ccc;
-	background:#eaeaea url(images/titleBar.png) repeat-x top left;
-}
-.dj_ie6 .tundra .dijitToolbar {
-	height: 10px;
-}
-.tundra .dijitToolbar .dijitButtonNode,
-.tundra .dijitToolbar .dijitComboButton .dijitButtonContents,
-.tundra .dijitToolbar .dijitComboButton .dijitDownArrowButton {
-	background: none;
-	margin: 0px;
-	padding: 0px;
-	border: none;
-	font-size: 12px;
-}
-.tundra .dijitToolbar .dijitButton,
-.tundra .dijitToolbar .dijitToggleButton,
-.tundra .dijitToolbar .dijitDropDownButton,
-.tundra .dijitToolbar .dijitComboButton .dijitButtonContents,
-.tundra .dijitToolbar .dijitComboButton .dijitDownArrowButton  {
-	background: none;
-	padding: 1px;
-}
-.tundra .dijitToolbar .dijitButtonChecked,
-.tundra .dijitToolbar .dijitToggleButtonChecked {
-	background-color:#d4dff2;
-	border:1px solid #316ac5;
-	padding: 0px;	
-}
-.tundra .dijitToolbar .dijitButtonCheckedHover,
-.tundra .dijitToolbar .dijitToggleButtonCheckedHover
- {
-	background-color:#abc1e5;
-	border:1px solid #316ac5;
-	padding: 0px;	
-}
-.tundra .dijitToolbar .dijitButtonHover,
-.tundra .dijitToolbar .dijitToggleButtonHover,
-.tundra .dijitToolbar .dijitDropDownButtonHover,
-.tundra .dijitToolbar .dijitComboButtonHover .dijitButtonContents,
-.tundra .dijitToolbar .dijitComboButtonDownArrowHover .dijitDownArrowButton {
-	
-	border: 1px solid #869cbf;
-	padding: 0px;	
-	background-color:#e1e5f0;
-}
-.tundra .dijitToolbar label {
-	padding: 3px 3px 0 6px;
-}
-.dj_ie .tundra .dijitToolbar .dijitComboButton .dijitButtonContentsFocused,
-.dj_ie .tundra .dijitToolbar .dijitComboButton .dijitDownArrowButtonFocused {
-	
-	border: 1px #555 dotted !important;
-	padding: 0px;
-}
-.tundra .dijitDialog {
-	background: #fff;
-	border: 1px solid #7eabcd;
-	
-	padding: 0px;
-	-webkit-box-shadow: 0px 5px 10px #adadad;
-}
-.tundra .dijitDialog .dijitDialogPaneContent {
-	background: #fff;
-	border:none;
-	border-top: 1px solid #d3d3d3; 
-	padding:10px;
-}
-.tundra .dijitDialogTitleBar {
-	
-	background: #fafafa url(images/titleBar.png) repeat-x top left;
-	padding: 5px 6px 3px 6px;
-	cursor: move;
-	outline:0; 
-}
-.tundra .dijitDialogTitle {
-	
-	font-weight: bold;
-	padding: 0px 4px;
-}
-.tundra .dijitDialogCloseIcon {
-	
-	
-	background: url(images/tabClose.png) no-repeat right top;
-	position: absolute;
-	vertical-align: middle;
-	right: 6px;
-	top: 4px;
-	height: 15px;
-	width: 15px;
-	cursor: pointer;
-}
-.dj_ie6 .tundra .dijitDialogCloseIcon {
-	background : url(images/tabClose.gif) no-repeat right top;
-}
-.tundra .dijitDialogCloseIcon-hover {
-	background: url(images/tabCloseHover.png) no-repeat right top;
-}
-.dj_ie6 .tundra .dijitDialogCloseIcon-hover {
-	background : url(images/tabCloseHover.gif) no-repeat right top;
-}
-.tundra .dijitTooltip,
-.tundra .dijitTooltipDialog {
-	
-	background: transparent;	
-}
-.dijitTooltipBelow {
-	
-	padding-top: 13px;
-}
-.dijitTooltipAbove {
-	
-	padding-bottom: 13px;
-}
-.tundra .dijitTooltipContainer {
-	
-	background: #ffffff url(images/popupMenuBg.gif) repeat-x bottom left;
-	border: 1px solid #7eabcd;
-	padding: 0.45em;
-	-webkit-border-radius: 3px;
-	-moz-border-radius: 3px;
-}
-.tundra .dijitTooltipConnector {
-	
-	border:0px;
-	z-index: 2;
-}
-.tundra .dijitTooltipABRight .dijitTooltipConnector {
-	
-	left: auto !important;
-	right: 3px;
-}
-.tundra .dijitTooltipBelow .dijitTooltipConnector {
-	
-	top: 0px;
-	left: 3px;
-	background:url(images/tooltipConnectorUp.png) no-repeat top left;
-	width:16px;
-	height:14px;
-}
-.dj_ie .tundra .dijitTooltipBelow .dijitTooltipConnector {
-	
-	background-image: url(images/tooltipConnectorUp.gif);
-}
-.tundra .dijitTooltipAbove .dijitTooltipConnector {
-	
-	bottom: 0px;
-	left: 3px;
-	background:url(images/tooltipConnectorDown.png) no-repeat top left;
-	width:16px;
-	height:14px;
-}
-.dj_ie .tundra .dijitTooltipAbove .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorDown.gif);
-}
-.dj_ie6 .tundra .dijitTooltipAbove .dijitTooltipConnector {
-	bottom: -3px;
-}
-.tundra .dijitTooltipLeft {
-	padding-right: 14px;
-}
-.dj_ie6 .tundra .dijitTooltipLeft {
-	padding-left: 15px;
-}
-.tundra .dijitTooltipLeft .dijitTooltipConnector {
-	
-	right: 0px;
-	bottom: 3px;
-	background:url(images/tooltipConnectorRight.png) no-repeat top left;
-	width:16px;
-	height:14px;
-}
-.dj_ie .tundra .dijitTooltipLeft .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorRight.gif);
-}
-.tundra .dijitTooltipRight {
-	padding-left: 14px;
-}
-.tundra .dijitTooltipRight .dijitTooltipConnector {
-	
-	left: 0px;
-	bottom: 3px;
-	background:url(images/tooltipConnectorLeft.png) no-repeat top left;
-	width:16px;
-	height:14px;
-}
-.dj_ie .tundra .dijitTooltipRight .dijitTooltipConnector {
-	background-image: url(images/tooltipConnectorLeft.gif);
-}
-.dj_webkit .tundra .dijitPopup .dijitTooltipContainer,
-.dj_webkit .tundra .dijitPopup .dijitMenu {
-	
-	-webkit-box-shadow: 0px 5px 10px #adadad;
-}
-.tundra .dijitMenu,
-.tundra .dijitMenuBar {
-	border: 1px solid #7eabcd;
-	margin: 0px;
-	padding: 0px;
-	background-color: #f7f7f7;
-	
-}
-.tundra .dijitBorderContainer .dijitMenuBar {
-	border:1px solid #ccc;
-}
-.tundra .dijitMenuItem {
-	font-family: sans-serif;
-	margin: 0;
-}
-.tundra .dijitMenuBar .dijitMenuItem {
-	padding: 4px 5px;
-}
-.tundra .dijitMenuPreviousButton, .tundra .dijitMenuNextButton {
-	font-style: italic;
-}
-.tundra .dijitMenuItem td {
-	padding: 2px;
-}
-.tundra .dijitMenuPassive .dijitMenuItemHover,
-.tundra .dijitMenuItemSelected {
-	background-color: #3559ac;
-	color:#fff;
-}
-.tundra .dijitMenuItemIcon {
-	width: 16px;
-	height: 16px;
-}
-.tundra .dijitMenuExpand {
-	width: 7px;
-	height: 7px;
-	background-image: url(images/spriteArrows.png);
-	background-position: -14px 0px;
-}
-.dj_ie6 .tundra .dijitMenuExpand {
-	background-image: url(images/spriteArrows.gif);
-}
-.tundra .dijitMenuSeparatorTop {
-	border-bottom: 1px solid #9b9b9b;
-}
-.tundra .dijitMenuSeparatorBottom {
-	border-top: 1px solid #e8e8e8;
-}
-.tundra .dijitCheckedMenuItemIconChar {
-	display: none;
-}
-.tundra .dijitCheckedMenuItemIcon {
-	background-image: url(images/checkmark.png);
-	background-position: -80px;
-}
-.dj_ie6 .tundra .dijitCheckedMenuItemIcon {
-	background-image: url(images/checkmark.gif);
-}
-.tundra .dijitCheckedMenuItemChecked .dijitCheckedMenuItemIcon {
-	background-position: -64px;
-}
-.dijitIEFixedToolbar {
-	position:absolute;
-	
-	top: expression(eval((document.documentElement||document.body).scrollTop));
-}
-.tundra .dijitToolbar .dijitToolbarSeparator {
-	background: url(images/editor.gif);
-}
-.tundra .dijitEditorIcon {
-	background-image: url(images/editor.gif); 
-	background-repeat: no-repeat;
-	width: 18px;
-	height: 18px;
-	text-align: center;
-}
-.tundra .dijitDisabled .dijitEditorIcon {
-	background-image: url(images/editorDisabled.gif); 
-}
-.tundra .dijitEditorIconSep { background-position: 0px; }
-.tundra .dijitEditorIconBackColor { background-position: -18px; }
-.tundra .dijitEditorIconBold { background-position: -36px; }
-.tundra .dijitEditorIconCancel { background-position: -54px; }
-.tundra .dijitEditorIconCopy { background-position: -72px; }
-.tundra .dijitEditorIconCreateLink { background-position: -90px; }
-.tundra .dijitEditorIconCut { background-position: -108px; }
-.tundra .dijitEditorIconDelete { background-position: -126px; }
-.tundra .dijitEditorIconForeColor { background-position: -144px; }
-.tundra .dijitEditorIconHiliteColor { background-position: -162px; }
-.tundra .dijitEditorIconIndent { background-position: -180px; }
-.tundra .dijitEditorIconInsertHorizontalRule { background-position: -198px; }
-.tundra .dijitEditorIconInsertImage { background-position: -216px; }
-.tundra .dijitEditorIconInsertOrderedList { background-position: -234px; }
-.tundra .dijitEditorIconInsertTable { background-position: -252px; }
-.tundra .dijitEditorIconInsertUnorderedList { background-position: -270px; }
-.tundra .dijitEditorIconItalic { background-position: -288px; }
-.tundra .dijitEditorIconJustifyCenter { background-position: -306px; }
-.tundra .dijitEditorIconJustifyFull { background-position: -324px; }
-.tundra .dijitEditorIconJustifyLeft { background-position: -342px; }
-.tundra .dijitEditorIconJustifyRight { background-position: -360px; }
-.tundra .dijitEditorIconLeftToRight { background-position: -378px; }
-.tundra .dijitEditorIconListBulletIndent { background-position: -396px; }
-.tundra .dijitEditorIconListBulletOutdent { background-position: -414px; }
-.tundra .dijitEditorIconListNumIndent { background-position: -432px; }
-.tundra .dijitEditorIconListNumOutdent { background-position: -450px; }
-.tundra .dijitEditorIconOutdent { background-position: -468px; }
-.tundra .dijitEditorIconPaste { background-position: -486px; }
-.tundra .dijitEditorIconRedo { background-position: -504px; }
-.tundra .dijitEditorIconRemoveFormat { background-position: -522px; }
-.tundra .dijitEditorIconRightToLeft { background-position: -540px; }
-.tundra .dijitEditorIconSave { background-position: -558px; }
-.tundra .dijitEditorIconSpace { background-position: -576px; }
-.tundra .dijitEditorIconStrikethrough { background-position: -594px; }
-.tundra .dijitEditorIconSubscript { background-position: -612px; }
-.tundra .dijitEditorIconSuperscript { background-position: -630px; }
-.tundra .dijitEditorIconUnderline { background-position: -648px; }
-.tundra .dijitEditorIconUndo { background-position: -666px; }
-.tundra .dijitEditorIconWikiword { background-position: -684px; }
-.tundra .dijitEditorIconToggleDir { background-position: -540px; }
-.tundra .dijitEditorIconTabIndent { background-position: -702px; }
-.tundra .dijitEditorIconSelectAll { background-position: -720px; }
-.tundra .dijitEditorIconUnlink { background-position: -738px; }
-.tundra .dijitEditorIconFullScreen { background-position: -756px; }
-.tundra .dijitEditorIconViewSource { background-position: -774px; }
-.tundra .dijitEditorIconPrint { background-position: -792px; }
-.tundra .dijitEditorIconNewPage { background-position: -810px; }
-.dijitColorPalette {
-	border:1px solid #7eabcd;
-	background:#fff;
-	-moz-border-radius: 0px !important;
-}
-.dj_gecko-rtl .dijitInputField {
-	direction: ltr; 
-}
-.dj_gecko-rtl .dijitInputField * {
-	direction: rtl; 
-}
-.dijitRtl .dijitMenuItem {
-	text-align: right;
-}
-.dijitRtl .dijitComboBox .dijitInputField {
-	border-right-width:1px !important;
-	border-left-width:0 !important;
-}
-.dijitRtl .dijitCalendarNextYear {
-	margin:0 0.55em 0 0;
-}
-.dijitRtl .dijitCalendarPreviousYear {
-	margin:0 0 0 0.55em;
-}
-.dijitRtl .dijitProgressBarFull .dijitProgressBarLabel {
-	right:0; 
-}
-.dijitRtl .dijitSliderImageHandleV {
-	left:auto;
-	right:-6px;
-}
-.dj_ie-rtl .dijitSliderImageHandleV {
-	right:-10px;
-}
-.dijitRtl .dijitSliderMoveableH {
-	right:auto;
-	left:0;
-}
-.dijitRtl .dijitRuleContainerV {
-	float:right;
-}
-.dj_gecko-rtl .dijitRuleContainerV {
-	float:left;
-}
-.dj_ie-rtl .dijitRuleContainerV {
-	text-align:right;
-}
-.dj_ie-rtl .dijitRuleLabelV {
-	text-align:left;
-}
-.dj_ie-rtl .dijitRuleLabelH {
-	zoom:1;
-}
-.dj_ie-rtl .dijitSliderProgressBarH {
-	right:0;
-	left:auto;
-}
-.dj_gecko-rtl .dijitSliderProgressBarH {
-	float:right;
-	right:0;
-	left:auto;
-}
-.dijitRtl .dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	right: auto;
-	left: 0;
-	border-width: 0 1px 0 0 !important;
-}
-.dijitRtl .dijitSpinnerButtonContainer {
-	float: left;
-}
-.dijitRtl .dijit_a11y .dijitSpinnerButtonContainer {
-	margin-left: none;
-	margin-right: 2px;
-}
-.dijitRtl DIV.dijitArrowButton, .dijitRtl .dijitValidationIcon, .dijitRtl .dijitValidationIconText {
-	float: left;
-}
-.dijitRtl .dijitContentPaneLoading, .dijitRtl .dijitContentPaneError {
-	background-position:right;
-	padding-right:25px;
-}
-.dijitRtl .dijitTabContainer .tabStripMenuButton {
-	float: left;
-}
-.dj_iequirks-rtl .dijitComboButton BUTTON {
-        float:left;
-}
-.dijitRtl .tundra .dijitCalendarDecrease {
-	background-position: -30px top;
-}
-.dijitRtl .tundra .dijitCalendarIncrease {
-	background-position: 0px top;
-}
-.dijitRtl .tundra .dijitDialogTitleBar .dijitDialogCloseIcon {
-	right: auto;
-	left: 5px;
-}
-.dijitRtl .tundra .dijitEditorIcon {
-	background-image: url(images/editor_rtl.gif); 
-}
-.dijitRtl .tundra .dijitDisabled .dijitEditorIcon {
-	background-image: url(images/editorDisabled_rtl.gif); 
-}
-.dijitRtl .tundra .dijitToolbar .dijitToolbarSeparator {
-	background-image: url(images/editor_rtl.gif);
-}
-.dijitRtl .tundra .dijitMenuItem .dijitMenuItemIcon {
-	padding-left: 3px;
-	padding-right: 0px;
-}
-.dijitRtl .tundra .dijitMenuItem .dijitMenuExpand {
-	background-position: -7px 0px;
-}
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeNode {
-    background-image : none;
-}
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeExpandoOpened {
-	background-image: url(images/treeExpand_minus_rtl.gif);
-}
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeExpandoClosed {
-	background-image: url(images/treeExpand_plus_rtl.gif);
-}
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeExpandoLeaf {
-	background-image: none;
-}
-.dijitRtl .tundra .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background-position: -7px 0px;
-}
-.dijitRtl .tundra .dijitTab {
-	-moz-box-orient:horizontal;
-	text-align: right;
-}
-.dijitRtl .tundra .dijitTabInnerDiv {
-	padding:2px 9px 2px 8px;
-}
-.dijitRtl .tundra .tabStrip-disabled .tabStripButton .dijitTabInnerDiv {
-	padding-bottom: 3px;
-	padding-top: 1px;
-}
-.dijitRtl .tundra .tabStripButton .dijitTabInnerDiv {
-	padding: 3px 2px 4px 2px;
-}
-.dijitRtl .tundra .dijitTabPaneWrapper {
-	#zoom: 1;
-}
-.dj_ie-rtl .tundra .dijitTabContainerLeft-tabs {
-	margin-left: 1px !important;
-}
-.dj_ie-rtl .tundra .dijitTabContainerRight-tabs {
-	margin-right: 1px !important;
-}
-.dijitRtl .tundra .dijitTabContainerLeft-tabs .dijitTab,
-.dijitRtl .tundra .dijitTabContainerRight-tabs .dijitTab {
-	margin-left:0px;
-}
-.dj_ie-rtl .tundra .dijitTab .dijitTabInnerDiv {
-	
-	width : 0.1% !important;
-}
-.dijitRtl .tundra .dijitSliderProgressBarH,
-.dijitRtl .tundra .dijitSliderRemainingBarH,
-.dijitRtl .tundra .dijitSliderLeftBumper,
-.dijitRtl .tundra .dijitSliderRightBumper,
-.dijitRtl .tundra .dijitSliderTopBumper {
-	background-position: top right;
-}
-.dijitRtl .tundra .dijitSliderProgressBarV,
-.dijitRtl .tundra .dijitSliderRemainingBarV,
-.dijitRtl .tundra .dijitSliderBottomBumper {
-	background-position: bottom right;
-}
-.dijitRtl .tundra .dijitSliderLeftBumper {
-	border-left-width: 0px;
-	border-right-width: 1px;
-}
-.dijitRtl .tundra .dijitSliderRightBumper {
-	border-left-width: 1px;
-	border-right-width: 0px;
-}
-.dijitRtl .tundra .dijitSliderIncrementIconH {
-	background-position: -7px 0px;
-}
-.dijitRtl .tundra .dijitSliderDecrementIconH {
-	background-position: -14px 0px;
-}
-.dijitRtl .tundra .dijitComboBox .dijitButtonNode,
-.dijitRtl .tundra .dijitSpinner .dijitButtonNode {
-	
-	border-left-width: 0px;
-	border-right-width: 1px;
-}
+	NOTES:
+	---
+	Dialog.css contains css classes for both Dialog and Tooltip!
+	This because currently a dijit.TooltipDialog exist. Until this is resolved
+	you need to include Dialog.css for both dijits
+	---
+	Toolbar.css contains classes also used in Editor. Until this is resolved
+	you need to include Toolbar.css for both Toolbar and Editor
+	---
+	Button.css contains classes for combobox,
+
+*/
+ at import url("../dijit.css");
+ at import url("../../icons/commonIcons.css");/*sprite containing common icons to be used by all themes*/
+ at import url("Common.css");
+ at import url("layout/ContentPane.css");
+ at import url("layout/TabContainer.css");
+ at import url("layout/AccordionContainer.css");
+ at import url("layout/SplitContainer.css");
+ at import url("layout/BorderContainer.css");
+ at import url("form/Common.css");
+ at import url("form/Button.css");
+ at import url("form/Checkbox.css");
+ at import url("form/RadioButton.css");
+ at import url("form/Slider.css");
+ at import url("form/Select.css");
+ at import url("Tree.css");
+ at import url("ProgressBar.css");
+ at import url("TitlePane.css");
+ at import url("Calendar.css");
+ at import url("TimePicker.css");
+ at import url("Toolbar.css");
+ at import url("Dialog.css");
+ at import url("Menu.css");
+ at import url("Editor.css");
+ at import url("../../icons/editorIcons.css"); /* sprite for editor icons to be used by all themes */
+ at import url("ColorPalette.css");
+ at import url("tundra_rtl.css");
diff --git a/dijit/themes/tundra/tundra_rtl.css b/dijit/themes/tundra/tundra_rtl.css
index f399328..58b7541 100644
--- a/dijit/themes/tundra/tundra_rtl.css
+++ b/dijit/themes/tundra/tundra_rtl.css
@@ -1,187 +1,27 @@
+/*
+	Adds cosmetic styling to Dijit.  Users may swap with a custom theme CSS file.
 
-.dj_gecko-rtl .dijitInputField {
-	direction: ltr; 
-}
-.dj_gecko-rtl .dijitInputField * {
-	direction: rtl; 
-}
-.dijitRtl .dijitMenuItem {
-	text-align: right;
-}
-.dijitRtl .dijitComboBox .dijitInputField {
-	border-right-width:1px !important;
-	border-left-width:0 !important;
-}
-.dijitRtl .dijitCalendarNextYear {
-	margin:0 0.55em 0 0;
-}
-.dijitRtl .dijitCalendarPreviousYear {
-	margin:0 0 0 0.55em;
-}
-.dijitRtl .dijitProgressBarFull .dijitProgressBarLabel {
-	right:0; 
-}
-.dijitRtl .dijitSliderImageHandleV {
-	left:auto;
-	right:-6px;
-}
-.dj_ie-rtl .dijitSliderImageHandleV {
-	right:-10px;
-}
-.dijitRtl .dijitSliderMoveableH {
-	right:auto;
-	left:0;
-}
-.dijitRtl .dijitRuleContainerV {
-	float:right;
-}
-.dj_gecko-rtl .dijitRuleContainerV {
-	float:left;
-}
-.dj_ie-rtl .dijitRuleContainerV {
-	text-align:right;
-}
-.dj_ie-rtl .dijitRuleLabelV {
-	text-align:left;
-}
-.dj_ie-rtl .dijitRuleLabelH {
-	zoom:1;
-}
-.dj_ie-rtl .dijitSliderProgressBarH {
-	right:0;
-	left:auto;
-}
-.dj_gecko-rtl .dijitSliderProgressBarH {
-	float:right;
-	right:0;
-	left:auto;
-}
-.dijitRtl .dijitSpinner .dijitInputLayoutContainer .dijitArrowButton {
-	right: auto;
-	left: 0;
-	border-width: 0 1px 0 0 !important;
-}
-.dijitRtl .dijitSpinnerButtonContainer {
-	float: left;
-}
-.dijitRtl .dijit_a11y .dijitSpinnerButtonContainer {
-	margin-left: none;
-	margin-right: 2px;
-}
-.dijitRtl DIV.dijitArrowButton, .dijitRtl .dijitValidationIcon, .dijitRtl .dijitValidationIconText {
-	float: left;
-}
-.dijitRtl .dijitContentPaneLoading, .dijitRtl .dijitContentPaneError {
-	background-position:right;
-	padding-right:25px;
-}
-.dijitRtl .dijitTabContainer .tabStripMenuButton {
-	float: left;
-}
-.dj_iequirks-rtl .dijitComboButton BUTTON {
-        float:left;
-}
-.dijitRtl .tundra .dijitCalendarDecrease {
-	background-position: -30px top;
-}
-.dijitRtl .tundra .dijitCalendarIncrease {
-	background-position: 0px top;
-}
-.dijitRtl .tundra .dijitDialogTitleBar .dijitDialogCloseIcon {
-	right: auto;
-	left: 5px;
-}
-.dijitRtl .tundra .dijitEditorIcon {
-	background-image: url(images/editor_rtl.gif); 
-}
-.dijitRtl .tundra .dijitDisabled .dijitEditorIcon {
-	background-image: url(images/editorDisabled_rtl.gif); 
-}
-.dijitRtl .tundra .dijitToolbar .dijitToolbarSeparator {
-	background-image: url(images/editor_rtl.gif);
-}
-.dijitRtl .tundra .dijitMenuItem .dijitMenuItemIcon {
-	padding-left: 3px;
-	padding-right: 0px;
-}
-.dijitRtl .tundra .dijitMenuItem .dijitMenuExpand {
-	background-position: -7px 0px;
-}
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeNode {
-    background-image : none;
-}
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeExpandoOpened {
-	background-image: url(images/treeExpand_minus_rtl.gif);
-}
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeExpandoClosed {
-	background-image: url(images/treeExpand_plus_rtl.gif);
-}
-.dijitRtl .tundra .dijitTreeContainer .dijitTreeExpandoLeaf {
-	background-image: none;
-}
-.dijitRtl .tundra .dijitTitlePane .dijitClosed .dijitArrowNode {
-	background-position: -7px 0px;
-}
-.dijitRtl .tundra .dijitTab {
-	-moz-box-orient:horizontal;
-	text-align: right;
-}
-.dijitRtl .tundra .dijitTabInnerDiv {
-	padding:2px 9px 2px 8px;
-}
-.dijitRtl .tundra .tabStrip-disabled .tabStripButton .dijitTabInnerDiv {
-	padding-bottom: 3px;
-	padding-top: 1px;
-}
-.dijitRtl .tundra .tabStripButton .dijitTabInnerDiv {
-	padding: 3px 2px 4px 2px;
-}
-.dijitRtl .tundra .dijitTabPaneWrapper {
-	#zoom: 1;
-}
-.dj_ie-rtl .tundra .dijitTabContainerLeft-tabs {
-	margin-left: 1px !important;
-}
-.dj_ie-rtl .tundra .dijitTabContainerRight-tabs {
-	margin-right: 1px !important;
-}
-.dijitRtl .tundra .dijitTabContainerLeft-tabs .dijitTab,
-.dijitRtl .tundra .dijitTabContainerRight-tabs .dijitTab {
-	margin-left:0px;
-}
-.dj_ie-rtl .tundra .dijitTab .dijitTabInnerDiv {
-	
-	width : 0.1% !important;
-}
-.dijitRtl .tundra .dijitSliderProgressBarH,
-.dijitRtl .tundra .dijitSliderRemainingBarH,
-.dijitRtl .tundra .dijitSliderLeftBumper,
-.dijitRtl .tundra .dijitSliderRightBumper,
-.dijitRtl .tundra .dijitSliderTopBumper {
-	background-position: top right;
-}
-.dijitRtl .tundra .dijitSliderProgressBarV,
-.dijitRtl .tundra .dijitSliderRemainingBarV,
-.dijitRtl .tundra .dijitSliderBottomBumper {
-	background-position: bottom right;
-}
-.dijitRtl .tundra .dijitSliderLeftBumper {
-	border-left-width: 0px;
-	border-right-width: 1px;
-}
-.dijitRtl .tundra .dijitSliderRightBumper {
-	border-left-width: 1px;
-	border-right-width: 0px;
-}
-.dijitRtl .tundra .dijitSliderIncrementIconH {
-	background-position: -7px 0px;
-}
-.dijitRtl .tundra .dijitSliderDecrementIconH {
-	background-position: -14px 0px;
-}
-.dijitRtl .tundra .dijitComboBox .dijitButtonNode,
-.dijitRtl .tundra .dijitSpinner .dijitButtonNode {
-	
-	border-left-width: 0px;
-	border-right-width: 1px;
-}
+	NOTES:
+	---
+	Dialog.css contains css classes for both Dialog and Tooltip!
+	This because currently a dijit.TooltipDialog exist. Until this is resolved
+	you need to include Dialog.css for both dijits
+	---
+	Toolbar.css contains classes also used in Editor. Until this is resolved
+	you need to include Toolbar.css for both Toolbar and Editor
+	---
+	Button.css contains classes for combobox,
+
+*/
+/* RTL files */
+ at import url("../dijit_rtl.css");
+ at import url("Calendar_rtl.css");
+ at import url("TimePicker_rtl.css");
+ at import url("Dialog_rtl.css");
+ at import url("Editor_rtl.css");
+ at import url("../../icons/editorIcons_rtl.css");/* RTL sprite for editor icons to be used by all themes*/
+ at import url("Menu_rtl.css");
+ at import url("Tree_rtl.css");
+ at import url("TitlePane_rtl.css");
+ at import url("layout/TabContainer_rtl.css");
+ at import url("form/Slider_rtl.css");
diff --git a/dijit/tree/ForestStoreModel.js b/dijit/tree/ForestStoreModel.js
index 9edf788..f39a978 100644
--- a/dijit/tree/ForestStoreModel.js
+++ b/dijit/tree/ForestStoreModel.js
@@ -1,83 +1,239 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.tree.ForestStoreModel"]){
-dojo._hasResource["dijit.tree.ForestStoreModel"]=true;
 dojo.provide("dijit.tree.ForestStoreModel");
+
 dojo.require("dijit.tree.TreeStoreModel");
-dojo.declare("dijit.tree.ForestStoreModel",dijit.tree.TreeStoreModel,{rootId:"$root$",rootLabel:"ROOT",query:null,constructor:function(_1){
-this.root={store:this,root:true,id:_1.rootId,label:_1.rootLabel,children:_1.rootChildren};
-},mayHaveChildren:function(_2){
-return _2===this.root||this.inherited(arguments);
-},getChildren:function(_3,_4,_5){
-if(_3===this.root){
-if(this.root.children){
-_4(this.root.children);
-}else{
-this.store.fetch({query:this.query,onComplete:dojo.hitch(this,function(_6){
-this.root.children=_6;
-_4(_6);
-}),onError:_5});
-}
-}else{
-this.inherited(arguments);
-}
-},isItem:function(_7){
-return (_7===this.root)?true:this.inherited(arguments);
-},fetchItemByIdentity:function(_8){
-if(_8.identity==this.root.id){
-var _9=_8.scope?_8.scope:dojo.global;
-if(_8.onItem){
-_8.onItem.call(_9,this.root);
-}
-}else{
-this.inherited(arguments);
-}
-},getIdentity:function(_a){
-return (_a===this.root)?this.root.id:this.inherited(arguments);
-},getLabel:function(_b){
-return (_b===this.root)?this.root.label:this.inherited(arguments);
-},newItem:function(_c,_d,_e){
-if(_d===this.root){
-this.onNewRootItem(_c);
-return this.store.newItem(_c);
-}else{
-return this.inherited(arguments);
-}
-},onNewRootItem:function(_f){
-},pasteItem:function(_10,_11,_12,_13,_14){
-if(_11===this.root){
-if(!_13){
-this.onLeaveRoot(_10);
-}
-}
-dijit.tree.TreeStoreModel.prototype.pasteItem.call(this,_10,_11===this.root?null:_11,_12===this.root?null:_12,_13,_14);
-if(_12===this.root){
-this.onAddToRoot(_10);
-}
-},onAddToRoot:function(_15){
-},onLeaveRoot:function(_16){
-},_requeryTop:function(){
-var _17=this.root.children||[];
-this.store.fetch({query:this.query,onComplete:dojo.hitch(this,function(_18){
-this.root.children=_18;
-if(_17.length!=_18.length||dojo.some(_17,function(_19,idx){
-return _18[idx]!=_19;
-})){
-this.onChildrenChange(this.root,_18);
-}
-})});
-},onNewItem:function(_1a,_1b){
-this._requeryTop();
-this.inherited(arguments);
-},onDeleteItem:function(_1c){
-if(dojo.indexOf(this.root.children,_1c)!=-1){
-this._requeryTop();
-}
-this.inherited(arguments);
-}});
-}
+
+dojo.declare("dijit.tree.ForestStoreModel", dijit.tree.TreeStoreModel, {
+	// summary:
+	//		Interface between Tree and a dojo.store that doesn't have a root item,
+	//		i.e. has multiple "top level" items.
+	//
+	// description
+	//		Use this class to wrap a dojo.store, making all the items matching the specified query
+	//		appear as children of a fabricated "root item".  If no query is specified then all the
+	//		items returned by fetch() on the underlying store become children of the root item.
+	//		It allows dijit.Tree to assume a single root item, even if the store doesn't have one.
+
+	// Parameters to constructor
+
+	// rootId: String
+	//		ID of fabricated root item
+	rootId: "$root$",
+
+	// rootLabel: String
+	//		Label of fabricated root item
+	rootLabel: "ROOT",
+
+	// query: String
+	//		Specifies the set of children of the root item.
+	// example:
+	//	|	{type:'continent'}
+	query: null,
+
+	// End of parameters to constructor
+
+	constructor: function(params){
+		// summary:
+		//		Sets up variables, etc.
+		// tags:
+		//		private
+
+		// Make dummy root item
+		this.root = {
+			store: this,
+			root: true,
+			id: params.rootId,
+			label: params.rootLabel,
+			children: params.rootChildren	// optional param
+		};
+	},
+
+	// =======================================================================
+	// Methods for traversing hierarchy
+
+	mayHaveChildren: function(/*dojo.data.Item*/ item){
+		// summary:
+		//		Tells if an item has or may have children.  Implementing logic here
+		//		avoids showing +/- expando icon for nodes that we know don't have children.
+		//		(For efficiency reasons we may not want to check if an element actually
+		//		has children until user clicks the expando node)
+		// tags:
+		//		extension
+		return item === this.root || this.inherited(arguments);
+	},
+
+	getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ callback, /*function*/ onError){
+		// summary:
+		// 		Calls onComplete() with array of child items of given parent item, all loaded.
+		if(parentItem === this.root){
+			if(this.root.children){
+				// already loaded, just return
+				callback(this.root.children);
+			}else{
+				this.store.fetch({
+					query: this.query,
+					onComplete: dojo.hitch(this, function(items){
+						this.root.children = items;
+						callback(items);
+					}),
+					onError: onError
+				});
+			}
+		}else{
+			this.inherited(arguments);
+		}
+	},
+
+	// =======================================================================
+	// Inspecting items
+
+	isItem: function(/* anything */ something){
+		return (something === this.root) ? true : this.inherited(arguments);
+	},
+
+	fetchItemByIdentity: function(/* object */ keywordArgs){
+		if(keywordArgs.identity == this.root.id){
+			var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+			if(keywordArgs.onItem){
+				keywordArgs.onItem.call(scope, this.root);
+			}
+		}else{
+			this.inherited(arguments);
+		}
+	},
+
+	getIdentity: function(/* item */ item){
+		return (item === this.root) ? this.root.id : this.inherited(arguments);
+	},
+
+	getLabel: function(/* item */ item){
+		return	(item === this.root) ? this.root.label : this.inherited(arguments);
+	},
+
+	// =======================================================================
+	// Write interface
+
+	newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
+		// summary:
+		//		Creates a new item.   See dojo.data.api.Write for details on args.
+		//		Used in drag & drop when item from external source dropped onto tree.
+		if(parent === this.root){
+			this.onNewRootItem(args);
+			return this.store.newItem(args);
+		}else{
+			return this.inherited(arguments);
+		}
+	},
+
+	onNewRootItem: function(args){
+		// summary:
+		//		User can override this method to modify a new element that's being
+		//		added to the root of the tree, for example to add a flag like root=true
+	},
+
+	pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
+		// summary:
+		//		Move or copy an item from one parent item to another.
+		//		Used in drag & drop
+		if(oldParentItem === this.root){
+			if(!bCopy){
+				// It's onLeaveRoot()'s responsibility to modify the item so it no longer matches
+				// this.query... thus triggering an onChildrenChange() event to notify the Tree
+				// that this element is no longer a child of the root node
+				this.onLeaveRoot(childItem);
+			}
+		}
+		dijit.tree.TreeStoreModel.prototype.pasteItem.call(this, childItem,
+			oldParentItem === this.root ? null : oldParentItem,
+			newParentItem === this.root ? null : newParentItem,
+			bCopy,
+			insertIndex
+		);
+		if(newParentItem === this.root){
+			// It's onAddToRoot()'s responsibility to modify the item so it matches
+			// this.query... thus triggering an onChildrenChange() event to notify the Tree
+			// that this element is now a child of the root node
+			this.onAddToRoot(childItem);
+		}
+	},
+
+	// =======================================================================
+	// Handling for top level children
+
+	onAddToRoot: function(/* item */ item){
+		// summary:
+		//		Called when item added to root of tree; user must override this method
+		//		to modify the item so that it matches the query for top level items
+		// example:
+		//	|	store.setValue(item, "root", true);
+		// tags:
+		//		extension
+		console.log(this, ": item ", item, " added to root");
+	},
+
+	onLeaveRoot: function(/* item */ item){
+		// summary:
+		//		Called when item removed from root of tree; user must override this method
+		//		to modify the item so it doesn't match the query for top level items
+		// example:
+		// 	|	store.unsetAttribute(item, "root");
+		// tags:
+		//		extension
+		console.log(this, ": item ", item, " removed from root");
+	},
+
+	// =======================================================================
+	// Events from data store
+
+	_requeryTop: function(){
+		// reruns the query for the children of the root node,
+		// sending out an onSet notification if those children have changed
+		var oldChildren = this.root.children || [];
+		this.store.fetch({
+			query: this.query,
+			onComplete: dojo.hitch(this, function(newChildren){
+				this.root.children = newChildren;
+
+				// If the list of children or the order of children has changed...
+				if(oldChildren.length != newChildren.length ||
+					dojo.some(oldChildren, function(item, idx){ return newChildren[idx] != item;})){
+					this.onChildrenChange(this.root, newChildren);
+				}
+			})
+		});
+	},
+
+	onNewItem: function(/* dojo.data.Item */ item, /* Object */ parentInfo){
+		// summary:
+		//		Handler for when new items appear in the store.  Developers should override this
+		//		method to be more efficient based on their app/data.
+		// description:
+		//		Note that the default implementation requeries the top level items every time
+		//		a new item is created, since any new item could be a top level item (even in
+		//		addition to being a child of another item, since items can have multiple parents).
+		//
+		//		Developers can override this function to do something more efficient if they can
+		//		detect which items are possible top level items (based on the item and the
+		//		parentInfo parameters).  Often all top level items have parentInfo==null, but
+		//		that will depend on which store you use and what your data is like.
+		// tags:
+		//		extension
+		this._requeryTop();
+
+		this.inherited(arguments);
+	},
+
+	onDeleteItem: function(/*Object*/ item){
+		// summary:
+		//		Handler for delete notifications from underlying store
+
+		// check if this was a child of root, and if so send notification that root's children
+		// have changed
+		if(dojo.indexOf(this.root.children, item) != -1){
+			this._requeryTop();
+		}
+
+		this.inherited(arguments);
+	}
+});
+
+
diff --git a/dijit/tree/TreeStoreModel.js b/dijit/tree/TreeStoreModel.js
index 9b18d98..660b2fd 100644
--- a/dijit/tree/TreeStoreModel.js
+++ b/dijit/tree/TreeStoreModel.js
@@ -1,145 +1,363 @@
-/*
-	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
-*/
+dojo.provide("dijit.tree.TreeStoreModel");
+
+dojo.declare(
+		"dijit.tree.TreeStoreModel",
+		null,
+	{
+		// summary:
+		//		Implements dijit.Tree.model connecting to a store with a single
+		//		root item.  Any methods passed into the constructor will override
+		//		the ones defined here.
+
+		// store: dojo.data.Store
+		//		Underlying store
+		store: null,
+
+		// childrenAttrs: String[]
+		//		One or more attribute names (attributes in the dojo.data item) that specify that item's children
+		childrenAttrs: ["children"],
+
+		// newItemIdAttr: String
+		//		Name of attribute in the Object passed to newItem() that specifies the id.
+		//
+		//		If newItemIdAttr is set then it's used when newItem() is called to see if an
+		//		item with the same id already exists, and if so just links to the old item
+		//		(so that the old item ends up with two parents).
+		//
+		//		Setting this to null or "" will make every drop create a new item.
+		newItemIdAttr: "id",
+
+		// labelAttr: String
+		//		If specified, get label for tree node from this attribute, rather
+		//		than by calling store.getLabel()
+		labelAttr: "",
+
+	 	// root: [readonly] dojo.data.Item
+		//		Pointer to the root item (read only, not a parameter)
+		root: null,
+
+		// query: anything
+		//		Specifies datastore query to return the root item for the tree.
+		//		Must only return a single item.   Alternately can just pass in pointer
+		//		to root item.
+		// example:
+		//	|	{id:'ROOT'}
+		query: null,
+
+		// deferItemLoadingUntilExpand: Boolean
+		//		Setting this to true will cause the TreeStoreModel to defer calling loadItem on nodes
+		// 		until they are expanded. This allows for lazying loading where only one
+		//		loadItem (and generally one network call, consequently) per expansion
+		// 		(rather than one for each child).
+		// 		This relies on partial loading of the children items; each children item of a
+		// 		fully loaded item should contain the label and info about having children.
+		deferItemLoadingUntilExpand: false,
+
+		constructor: function(/* Object */ args){
+			// summary:
+			//		Passed the arguments listed above (store, etc)
+			// tags:
+			//		private
+
+			dojo.mixin(this, args);
+
+			this.connects = [];
+
+			var store = this.store;
+			if(!store.getFeatures()['dojo.data.api.Identity']){
+				throw new Error("dijit.Tree: store must support dojo.data.Identity");
+			}
+
+			// if the store supports Notification, subscribe to the notification events
+			if(store.getFeatures()['dojo.data.api.Notification']){
+				this.connects = this.connects.concat([
+					dojo.connect(store, "onNew", this, "onNewItem"),
+					dojo.connect(store, "onDelete", this, "onDeleteItem"),
+					dojo.connect(store, "onSet", this, "onSetItem")
+				]);
+			}
+		},
+
+		destroy: function(){
+			dojo.forEach(this.connects, dojo.disconnect);
+			// TODO: should cancel any in-progress processing of getRoot(), getChildren()
+		},
+
+		// =======================================================================
+		// Methods for traversing hierarchy
+
+		getRoot: function(onItem, onError){
+			// summary:
+			//		Calls onItem with the root item for the tree, possibly a fabricated item.
+			//		Calls onError on error.
+			if(this.root){
+				onItem(this.root);
+			}else{
+				this.store.fetch({
+					query: this.query,
+					onComplete: dojo.hitch(this, function(items){
+						if(items.length != 1){
+							throw new Error(this.declaredClass + ": query " + dojo.toJson(this.query) + " returned " + items.length +
+							 	" items, but must return exactly one item");
+						}
+						this.root = items[0];
+						onItem(this.root);
+					}),
+					onError: onError
+				});
+			}
+		},
+
+		mayHaveChildren: function(/*dojo.data.Item*/ item){
+			// summary:
+			//		Tells if an item has or may have children.  Implementing logic here
+			//		avoids showing +/- expando icon for nodes that we know don't have children.
+			//		(For efficiency reasons we may not want to check if an element actually
+			//		has children until user clicks the expando node)
+			return dojo.some(this.childrenAttrs, function(attr){
+				return this.store.hasAttribute(item, attr);
+			}, this);
+		},
+
+		getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete, /*function*/ onError){
+			// summary:
+			// 		Calls onComplete() with array of child items of given parent item, all loaded.
+
+			var store = this.store;
+			if(!store.isItemLoaded(parentItem)){
+				// The parent is not loaded yet, we must be in deferItemLoadingUntilExpand
+				// mode, so we will load it and just return the children (without loading each
+				// child item)
+				var getChildren = dojo.hitch(this, arguments.callee);
+				store.loadItem({
+					item: parentItem,
+					onItem: function(parentItem){
+						getChildren(parentItem, onComplete, onError);
+					},
+					onError: onError
+				});
+				return;
+			}
+			// get children of specified item
+			var childItems = [];
+			for(var i=0; i<this.childrenAttrs.length; i++){
+				var vals = store.getValues(parentItem, this.childrenAttrs[i]);
+				childItems = childItems.concat(vals);
+			}
+
+			// count how many items need to be loaded
+			var _waitCount = 0;
+			if(!this.deferItemLoadingUntilExpand){
+				dojo.forEach(childItems, function(item){ if(!store.isItemLoaded(item)){ _waitCount++; } });
+			}
+
+			if(_waitCount == 0){
+				// all items are already loaded (or we aren't loading them).  proceed...
+				onComplete(childItems);
+			}else{
+				// still waiting for some or all of the items to load
+				dojo.forEach(childItems, function(item, idx){
+					if(!store.isItemLoaded(item)){
+						store.loadItem({
+							item: item,
+							onItem: function(item){
+								childItems[idx] = item;
+								if(--_waitCount == 0){
+									// all nodes have been loaded, send them to the tree
+									onComplete(childItems);
+								}
+							},
+							onError: onError
+						});
+					}
+				});
+			}
+		},
+
+		// =======================================================================
+		// Inspecting items
+
+		isItem: function(/* anything */ something){
+			return this.store.isItem(something);	// Boolean
+		},
+
+		fetchItemByIdentity: function(/* object */ keywordArgs){
+			this.store.fetchItemByIdentity(keywordArgs);
+		},
+
+		getIdentity: function(/* item */ item){
+			return this.store.getIdentity(item);	// Object
+		},
+
+		getLabel: function(/*dojo.data.Item*/ item){
+			// summary:
+			//		Get the label for an item
+			if(this.labelAttr){
+				return this.store.getValue(item,this.labelAttr);	// String
+			}else{
+				return this.store.getLabel(item);	// String
+			}
+		},
+
+		// =======================================================================
+		// Write interface
+
+		newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
+			// summary:
+			//		Creates a new item.   See `dojo.data.api.Write` for details on args.
+			//		Used in drag & drop when item from external source dropped onto tree.
+			// description:
+			//		Developers will need to override this method if new items get added
+			//		to parents with multiple children attributes, in order to define which
+			//		children attribute points to the new item.
+
+			var pInfo = {parent: parent, attribute: this.childrenAttrs[0], insertIndex: insertIndex};
+
+			if(this.newItemIdAttr && args[this.newItemIdAttr]){
+				// Maybe there's already a corresponding item in the store; if so, reuse it.
+				this.fetchItemByIdentity({identity: args[this.newItemIdAttr], scope: this, onItem: function(item){
+					if(item){
+						// There's already a matching item in store, use it
+						this.pasteItem(item, null, parent, true, insertIndex);
+					}else{
+						// Create new item in the tree, based on the drag source.
+						this.store.newItem(args, pInfo);
+					}
+				}});
+			}else{
+				// [as far as we know] there is no id so we must assume this is a new item
+				this.store.newItem(args, pInfo);
+			}
+		},
+
+		pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
+			// summary:
+			//		Move or copy an item from one parent item to another.
+			//		Used in drag & drop
+			var store = this.store,
+				parentAttr = this.childrenAttrs[0];	// name of "children" attr in parent item
+
+			// remove child from source item, and record the attribute that child occurred in
+			if(oldParentItem){
+				dojo.forEach(this.childrenAttrs, function(attr){
+					if(store.containsValue(oldParentItem, attr, childItem)){
+						if(!bCopy){
+							var values = dojo.filter(store.getValues(oldParentItem, attr), function(x){
+								return x != childItem;
+							});
+							store.setValues(oldParentItem, attr, values);
+						}
+						parentAttr = attr;
+					}
+				});
+			}
+
+			// modify target item's children attribute to include this item
+			if(newParentItem){
+				if(typeof insertIndex == "number"){
+					// call slice() to avoid modifying the original array, confusing the data store
+					var childItems = store.getValues(newParentItem, parentAttr).slice();
+					childItems.splice(insertIndex, 0, childItem);
+					store.setValues(newParentItem, parentAttr, childItems);
+				}else{
+					store.setValues(newParentItem, parentAttr,
+						store.getValues(newParentItem, parentAttr).concat(childItem));
+				}
+			}
+		},
+
+		// =======================================================================
+		// Callbacks
+
+		onChange: function(/*dojo.data.Item*/ item){
+			// summary:
+			//		Callback whenever an item has changed, so that Tree
+			//		can update the label, icon, etc.   Note that changes
+			//		to an item's children or parent(s) will trigger an
+			//		onChildrenChange() so you can ignore those changes here.
+			// tags:
+			//		callback
+		},
+
+		onChildrenChange: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
+			// summary:
+			//		Callback to do notifications about new, updated, or deleted items.
+			// tags:
+			//		callback
+		},
+
+		onDelete: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
+			// summary:
+			//		Callback when an item has been deleted.
+			// description:
+			//		Note that there will also be an onChildrenChange() callback for the parent
+			//		of this item.
+			// tags:
+			//		callback
+		},
+
+		// =======================================================================
+		// Events from data store
+
+		onNewItem: function(/* dojo.data.Item */ item, /* Object */ parentInfo){
+			// summary:
+			//		Handler for when new items appear in the store, either from a drop operation
+			//		or some other way.   Updates the tree view (if necessary).
+			// description:
+			//		If the new item is a child of an existing item,
+			//		calls onChildrenChange() with the new list of children
+			//		for that existing item.
+			//
+			// tags:
+			//		extension
+
+			// We only care about the new item if it has a parent that corresponds to a TreeNode
+			// we are currently displaying
+			if(!parentInfo){
+				return;
+			}
+
+			// Call onChildrenChange() on parent (ie, existing) item with new list of children
+			// In the common case, the new list of children is simply parentInfo.newValue or
+			// [ parentInfo.newValue ], although if items in the store has multiple
+			// child attributes (see `childrenAttr`), then it's a superset of parentInfo.newValue,
+			// so call getChildren() to be sure to get right answer.
+			this.getChildren(parentInfo.item, dojo.hitch(this, function(children){
+				this.onChildrenChange(parentInfo.item, children);
+			}));
+		},
+
+		onDeleteItem: function(/*Object*/ item){
+			// summary:
+			//		Handler for delete notifications from underlying store
+			this.onDelete(item);
+		},
+
+		onSetItem: function(/* item */ item,
+						/* attribute-name-string */ attribute,
+						/* object | array */ oldValue,
+						/* object | array */ newValue){
+			// summary:
+			//		Updates the tree view according to changes in the data store.
+			// description:
+			//		Handles updates to an item's children by calling onChildrenChange(), and
+			//		other updates to an item by calling onChange().
+			//
+			//		See `onNewItem` for more details on handling updates to an item's children.
+			// tags:
+			//		extension
+
+			if(dojo.indexOf(this.childrenAttrs, attribute) != -1){
+				// item's children list changed
+				this.getChildren(item, dojo.hitch(this, function(children){
+					// See comments in onNewItem() about calling getChildren()
+					this.onChildrenChange(item, children);
+				}));
+			}else{
+				// item's label/icon/etc. changed.
+				this.onChange(item);
+			}
+		}
+	});
 
 
-if(!dojo._hasResource["dijit.tree.TreeStoreModel"]){
-dojo._hasResource["dijit.tree.TreeStoreModel"]=true;
-dojo.provide("dijit.tree.TreeStoreModel");
-dojo.declare("dijit.tree.TreeStoreModel",null,{store:null,childrenAttrs:["children"],newItemIdAttr:"id",labelAttr:"",root:null,query:null,deferItemLoadingUntilExpand:false,constructor:function(_1){
-dojo.mixin(this,_1);
-this.connects=[];
-var _2=this.store;
-if(!_2.getFeatures()["dojo.data.api.Identity"]){
-throw new Error("dijit.Tree: store must support dojo.data.Identity");
-}
-if(_2.getFeatures()["dojo.data.api.Notification"]){
-this.connects=this.connects.concat([dojo.connect(_2,"onNew",this,"onNewItem"),dojo.connect(_2,"onDelete",this,"onDeleteItem"),dojo.connect(_2,"onSet",this,"onSetItem")]);
-}
-},destroy:function(){
-dojo.forEach(this.connects,dojo.disconnect);
-},getRoot:function(_3,_4){
-if(this.root){
-_3(this.root);
-}else{
-this.store.fetch({query:this.query,onComplete:dojo.hitch(this,function(_5){
-if(_5.length!=1){
-throw new Error(this.declaredClass+": query "+dojo.toJson(this.query)+" returned "+_5.length+" items, but must return exactly one item");
-}
-this.root=_5[0];
-_3(this.root);
-}),onError:_4});
-}
-},mayHaveChildren:function(_6){
-return dojo.some(this.childrenAttrs,function(_7){
-return this.store.hasAttribute(_6,_7);
-},this);
-},getChildren:function(_8,_9,_a){
-var _b=this.store;
-if(!_b.isItemLoaded(_8)){
-var _c=dojo.hitch(this,arguments.callee);
-_b.loadItem({item:_8,onItem:function(_d){
-_c(_d,_9,_a);
-},onError:_a});
-return;
-}
-var _e=[];
-for(var i=0;i<this.childrenAttrs.length;i++){
-var _f=_b.getValues(_8,this.childrenAttrs[i]);
-_e=_e.concat(_f);
-}
-var _10=0;
-if(!this.deferItemLoadingUntilExpand){
-dojo.forEach(_e,function(_11){
-if(!_b.isItemLoaded(_11)){
-_10++;
-}
-});
-}
-if(_10==0){
-_9(_e);
-}else{
-var _12=function _12(_13){
-if(--_10==0){
-_9(_e);
-}
-};
-dojo.forEach(_e,function(_14){
-if(!_b.isItemLoaded(_14)){
-_b.loadItem({item:_14,onItem:_12,onError:_a});
-}
-});
-}
-},isItem:function(_15){
-return this.store.isItem(_15);
-},fetchItemByIdentity:function(_16){
-this.store.fetchItemByIdentity(_16);
-},getIdentity:function(_17){
-return this.store.getIdentity(_17);
-},getLabel:function(_18){
-if(this.labelAttr){
-return this.store.getValue(_18,this.labelAttr);
-}else{
-return this.store.getLabel(_18);
-}
-},newItem:function(_19,_1a,_1b){
-var _1c={parent:_1a,attribute:this.childrenAttrs[0],insertIndex:_1b};
-if(this.newItemIdAttr&&_19[this.newItemIdAttr]){
-this.fetchItemByIdentity({identity:_19[this.newItemIdAttr],scope:this,onItem:function(_1d){
-if(_1d){
-this.pasteItem(_1d,null,_1a,true,_1b);
-}else{
-this.store.newItem(_19,_1c);
-}
-}});
-}else{
-this.store.newItem(_19,_1c);
-}
-},pasteItem:function(_1e,_1f,_20,_21,_22){
-var _23=this.store,_24=this.childrenAttrs[0];
-if(_1f){
-dojo.forEach(this.childrenAttrs,function(_25){
-if(_23.containsValue(_1f,_25,_1e)){
-if(!_21){
-var _26=dojo.filter(_23.getValues(_1f,_25),function(x){
-return x!=_1e;
-});
-_23.setValues(_1f,_25,_26);
-}
-_24=_25;
-}
-});
-}
-if(_20){
-if(typeof _22=="number"){
-var _27=_23.getValues(_20,_24);
-_27.splice(_22,0,_1e);
-_23.setValues(_20,_24,_27);
-}else{
-_23.setValues(_20,_24,_23.getValues(_20,_24).concat(_1e));
-}
-}
-},onChange:function(_28){
-},onChildrenChange:function(_29,_2a){
-},onDelete:function(_2b,_2c){
-},onNewItem:function(_2d,_2e){
-if(!_2e){
-return;
-}
-this.getChildren(_2e.item,dojo.hitch(this,function(_2f){
-this.onChildrenChange(_2e.item,_2f);
-}));
-},onDeleteItem:function(_30){
-this.onDelete(_30);
-},onSetItem:function(_31,_32,_33,_34){
-if(dojo.indexOf(this.childrenAttrs,_32)!=-1){
-this.getChildren(_31,dojo.hitch(this,function(_35){
-this.onChildrenChange(_31,_35);
-}));
-}else{
-this.onChange(_31);
-}
-}});
-}
diff --git a/dijit/tree/_dndContainer.js b/dijit/tree/_dndContainer.js
index 39804d2..3fa3c5d 100644
--- a/dijit/tree/_dndContainer.js
+++ b/dijit/tree/_dndContainer.js
@@ -1,49 +1,153 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.tree._dndContainer"]){
-dojo._hasResource["dijit.tree._dndContainer"]=true;
 dojo.provide("dijit.tree._dndContainer");
 dojo.require("dojo.dnd.common");
 dojo.require("dojo.dnd.Container");
-dojo.declare("dijit.tree._dndContainer",null,{constructor:function(_1,_2){
-this.tree=_1;
-this.node=_1.domNode;
-dojo.mixin(this,_2);
-this.map={};
-this.current=null;
-this.containerState="";
-dojo.addClass(this.node,"dojoDndContainer");
-this.events=[dojo.connect(this.node,"onmouseenter",this,"onOverEvent"),dojo.connect(this.node,"onmouseleave",this,"onOutEvent"),dojo.connect(this.tree,"_onNodeMouseEnter",this,"onMouseOver"),dojo.connect(this.tree,"_onNodeMouseLeave",this,"onMouseOut"),dojo.connect(this.node,"ondragstart",dojo,"stopEvent"),dojo.connect(this.node,"onselectstart",dojo,"stopEvent")];
-},getItem:function(_3){
-var _4=this.selection[_3],_5={data:dijit.getEnclosingWidget(_4),type:["treeNode"]};
-return _5;
-},destroy:function(){
-dojo.forEach(this.events,dojo.disconnect);
-this.node=this.parent=null;
-},onMouseOver:function(_6,_7){
-this.current=_6.rowNode;
-this.currentWidget=_6;
-},onMouseOut:function(_8,_9){
-this.current=null;
-this.currentWidget=null;
-},_changeState:function(_a,_b){
-var _c="dojoDnd"+_a;
-var _d=_a.toLowerCase()+"State";
-dojo.removeClass(this.node,_c+this[_d]);
-dojo.addClass(this.node,_c+_b);
-this[_d]=_b;
-},_addItemClass:function(_e,_f){
-dojo.addClass(_e,"dojoDndItem"+_f);
-},_removeItemClass:function(_10,_11){
-dojo.removeClass(_10,"dojoDndItem"+_11);
-},onOverEvent:function(){
-this._changeState("Container","Over");
-},onOutEvent:function(){
-this._changeState("Container","");
-}});
-}
+
+dojo.declare("dijit.tree._dndContainer",
+	null,
+	{
+
+		// summary:
+		//		This is a base class for `dijit.tree._dndSelector`, and isn't meant to be used directly.
+		//		It's modeled after `dojo.dnd.Container`.
+		// tags:
+		//		protected
+
+		/*=====
+		// current: DomNode
+		//		The currently hovered TreeNode.rowNode (which is the DOM node
+		//		associated w/a given node in the tree, excluding it's descendants)
+		current: null,
+		=====*/
+
+		constructor: function(tree, params){
+			// summary:
+			//		A constructor of the Container
+			// tree: Node
+			//		Node or node's id to build the container on
+			// params: dijit.tree.__SourceArgs
+			//		A dict of parameters, which gets mixed into the object
+			// tags:
+			//		private
+			this.tree = tree;
+			this.node = tree.domNode;	// TODO: rename; it's not a TreeNode but the whole Tree
+			dojo.mixin(this, params);
+
+			// class-specific variables
+			this.map = {};
+			this.current = null;	// current TreeNode's DOM node
+
+			// states
+			this.containerState = "";
+			dojo.addClass(this.node, "dojoDndContainer");
+
+			// set up events
+			this.events = [
+				// container level events
+				dojo.connect(this.node, "onmouseenter", this, "onOverEvent"),
+				dojo.connect(this.node, "onmouseleave",	this, "onOutEvent"),
+
+				// switching between TreeNodes
+				dojo.connect(this.tree, "_onNodeMouseEnter", this, "onMouseOver"),
+				dojo.connect(this.tree, "_onNodeMouseLeave", this, "onMouseOut"),
+
+				// cancel text selection and text dragging
+				dojo.connect(this.node, "ondragstart", dojo, "stopEvent"),
+				dojo.connect(this.node, "onselectstart", dojo, "stopEvent")
+			];
+		},
+
+		getItem: function(/*String*/ key){
+			// summary:
+			//		Returns the dojo.dnd.Item (representing a dragged node) by it's key (id).
+			//		Called by dojo.dnd.Source.checkAcceptance().
+			// tags:
+			//		protected
+
+			var node = this.selection[key],
+				ret = {
+					data: dijit.getEnclosingWidget(node),
+					type: ["treeNode"]
+				};
+
+			return ret;	// dojo.dnd.Item
+		},
+
+		destroy: function(){
+			// summary:
+			//		Prepares this object to be garbage-collected
+
+			dojo.forEach(this.events, dojo.disconnect);
+			// this.clearItems();
+			this.node = this.parent = null;
+		},
+
+		// mouse events
+		onMouseOver: function(/*TreeNode*/ widget, /*Event*/ evt){
+			// summary:
+			//		Called when mouse is moved over a TreeNode
+			// tags:
+			//		protected
+			this.current = widget.rowNode;
+			this.currentWidget = widget;
+		},
+
+		onMouseOut: function(/*TreeNode*/ widget, /*Event*/ evt){
+			// summary:
+			//		Called when mouse is moved away from a TreeNode
+			// tags:
+			//		protected
+			this.current = null;
+			this.currentWidget = null;
+		},
+
+		_changeState: function(type, newState){
+			// summary:
+			//		Changes a named state to new state value
+			// type: String
+			//		A name of the state to change
+			// newState: String
+			//		new state
+			var prefix = "dojoDnd" + type;
+			var state = type.toLowerCase() + "State";
+			//dojo.replaceClass(this.node, prefix + newState, prefix + this[state]);
+			dojo.removeClass(this.node, prefix + this[state]);
+			dojo.addClass(this.node, prefix + newState);
+			this[state] = newState;
+		},
+
+		_addItemClass: function(node, type){
+			// summary:
+			//		Adds a class with prefix "dojoDndItem"
+			// node: Node
+			//		A node
+			// type: String
+			//		A variable suffix for a class name
+			dojo.addClass(node, "dojoDndItem" + type);
+		},
+
+		_removeItemClass: function(node, type){
+			// summary:
+			//		Removes a class with prefix "dojoDndItem"
+			// node: Node
+			//		A node
+			// type: String
+			//		A variable suffix for a class name
+			dojo.removeClass(node, "dojoDndItem" + type);
+		},
+
+		onOverEvent: function(){
+			// summary:
+			//		This function is called once, when mouse is over our container
+			// tags:
+			//		protected
+			this._changeState("Container", "Over");
+		},
+
+		onOutEvent: function(){
+			// summary:
+			//		This function is called once, when mouse is out of our container
+			// tags:
+			//		protected
+			this._changeState("Container", "");
+		}
+});
diff --git a/dijit/tree/_dndSelector.js b/dijit/tree/_dndSelector.js
index 30b1ade..bfecfed 100644
--- a/dijit/tree/_dndSelector.js
+++ b/dijit/tree/_dndSelector.js
@@ -1,125 +1,218 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.tree._dndSelector"]){
-dojo._hasResource["dijit.tree._dndSelector"]=true;
 dojo.provide("dijit.tree._dndSelector");
 dojo.require("dojo.dnd.common");
 dojo.require("dijit.tree._dndContainer");
-dojo.declare("dijit.tree._dndSelector",dijit.tree._dndContainer,{constructor:function(_1,_2){
-this.selection={};
-this.anchor=null;
-this.simpleSelection=false;
-this.events.push(dojo.connect(this.tree.domNode,"onmousedown",this,"onMouseDown"),dojo.connect(this.tree.domNode,"onmouseup",this,"onMouseUp"),dojo.connect(this.tree.domNode,"onmousemove",this,"onMouseMove"));
-},singular:false,getSelectedNodes:function(){
-return this.selection;
-},selectNone:function(){
-return this._removeSelection()._removeAnchor();
-},destroy:function(){
-this.inherited(arguments);
-this.selection=this.anchor=null;
-},onMouseDown:function(e){
-if(!this.current){
-return;
-}
-if(e.button==dojo.mouseButtons.RIGHT){
-return;
-}
-var _3=dijit.getEnclosingWidget(this.current),id=_3.id+"-dnd";
-if(!dojo.hasAttr(this.current,"id")){
-dojo.attr(this.current,"id",id);
-}
-if(!this.singular&&!dojo.isCopyKey(e)&&!e.shiftKey&&(this.current.id in this.selection)){
-this.simpleSelection=true;
-dojo.stopEvent(e);
-return;
-}
-if(this.singular){
-if(this.anchor==this.current){
-if(dojo.isCopyKey(e)){
-this.selectNone();
-}
-}else{
-this.selectNone();
-this.anchor=this.current;
-this._addItemClass(this.anchor,"Anchor");
-this.selection[this.current.id]=this.current;
-}
-}else{
-if(!this.singular&&e.shiftKey){
-if(dojo.isCopyKey(e)){
-}else{
-}
-}else{
-if(dojo.isCopyKey(e)){
-if(this.anchor==this.current){
-delete this.selection[this.anchor.id];
-this._removeAnchor();
-}else{
-if(this.current.id in this.selection){
-this._removeItemClass(this.current,"Selected");
-delete this.selection[this.current.id];
-}else{
-if(this.anchor){
-this._removeItemClass(this.anchor,"Anchor");
-this._addItemClass(this.anchor,"Selected");
-}
-this.anchor=this.current;
-this._addItemClass(this.current,"Anchor");
-this.selection[this.current.id]=this.current;
-}
-}
-}else{
-if(!(id in this.selection)){
-this.selectNone();
-this.anchor=this.current;
-this._addItemClass(this.current,"Anchor");
-this.selection[id]=this.current;
-}
-}
-}
-}
-dojo.stopEvent(e);
-},onMouseUp:function(e){
-if(!this.simpleSelection){
-return;
-}
-this.simpleSelection=false;
-this.selectNone();
-if(this.current){
-this.anchor=this.current;
-this._addItemClass(this.anchor,"Anchor");
-this.selection[this.current.id]=this.current;
-}
-},onMouseMove:function(e){
-this.simpleSelection=false;
-},_removeSelection:function(){
-var e=dojo.dnd._empty;
-for(var i in this.selection){
-if(i in e){
-continue;
-}
-var _4=dojo.byId(i);
-if(_4){
-this._removeItemClass(_4,"Selected");
-}
-}
-this.selection={};
-return this;
-},_removeAnchor:function(){
-if(this.anchor){
-this._removeItemClass(this.anchor,"Anchor");
-this.anchor=null;
-}
-return this;
-},forInSelectedItems:function(f,o){
-o=o||dojo.global;
-for(var id in this.selection){
-f.call(o,this.getItem(id),id,this);
-}
-}});
-}
+
+dojo.declare("dijit.tree._dndSelector",
+	dijit.tree._dndContainer,
+	{
+		// summary:
+		//		This is a base class for `dijit.tree.dndSource` , and isn't meant to be used directly.
+		//		It's based on `dojo.dnd.Selector`.
+		// tags:
+		//		protected
+
+		/*=====
+		// selection: Hash<String, DomNode>
+		//		(id, DomNode) map for every TreeNode that's currently selected.
+		//		The DOMNode is the TreeNode.rowNode.
+		selection: {},
+		=====*/
+
+		constructor: function(tree, params){
+			// summary:
+			//		Initialization
+			// tags:
+			//		private
+
+			this.selection={};
+			this.anchor = null;
+			this.simpleSelection=false;
+
+			this.events.push(
+				dojo.connect(this.tree.domNode, "onmousedown", this,"onMouseDown"),
+				dojo.connect(this.tree.domNode, "onmouseup", this,"onMouseUp"),
+				dojo.connect(this.tree.domNode, "onmousemove", this,"onMouseMove")
+			);
+		},
+
+		//	singular: Boolean
+		//		Allows selection of only one element, if true.
+		//		Tree hasn't been tested in singular=true mode, unclear if it works.
+		singular: false,
+
+		// methods
+
+		getSelectedNodes: function(){
+			// summary:
+			//		Returns the set of selected nodes.
+			//		Used by dndSource on the start of a drag.
+			// tags:
+			//		protected
+			return this.selection;
+		},
+
+		selectNone: function(){
+			// summary:
+			//		Unselects all items
+			// tags:
+			//		private
+
+			return this._removeSelection()._removeAnchor();	// self
+		},
+
+		destroy: function(){
+			// summary:
+			//		Prepares the object to be garbage-collected
+			this.inherited(arguments);
+			this.selection = this.anchor = null;
+		},
+
+		// mouse events
+		onMouseDown: function(e){
+			// summary:
+			//		Event processor for onmousedown
+			// e: Event
+			//		mouse event
+			// tags:
+			//		protected
+
+			if(!this.current){ return; }
+
+			if(e.button == dojo.mouseButtons.RIGHT){ return; }	// ignore right-click
+
+			var treeNode = dijit.getEnclosingWidget(this.current),
+				id = treeNode.id + "-dnd"	// so id doesn't conflict w/widget
+
+			if(!dojo.hasAttr(this.current, "id")){
+				dojo.attr(this.current, "id", id);
+			}
+
+			if(!this.singular && !dojo.isCopyKey(e) && !e.shiftKey && (this.current.id in this.selection)){
+				this.simpleSelection = true;
+				dojo.stopEvent(e);
+				return;
+			}
+			if(this.singular){
+				if(this.anchor == this.current){
+					if(dojo.isCopyKey(e)){
+						this.selectNone();
+					}
+				}else{
+					this.selectNone();
+					this.anchor = this.current;
+					this._addItemClass(this.anchor, "Anchor");
+
+					this.selection[this.current.id] = this.current;
+				}
+			}else{
+				if(!this.singular && e.shiftKey){
+					if(dojo.isCopyKey(e)){
+						//TODO add range to selection
+					}else{
+						//TODO select new range from anchor
+					}
+				}else{
+					if(dojo.isCopyKey(e)){
+						if(this.anchor == this.current){
+							delete this.selection[this.anchor.id];
+							this._removeAnchor();
+						}else{
+							if(this.current.id in this.selection){
+								this._removeItemClass(this.current, "Selected");
+								delete this.selection[this.current.id];
+							}else{
+								if(this.anchor){
+									this._removeItemClass(this.anchor, "Anchor");
+									this._addItemClass(this.anchor, "Selected");
+								}
+								this.anchor = this.current;
+								this._addItemClass(this.current, "Anchor");
+								this.selection[this.current.id] = this.current;
+							}
+						}
+					}else{
+						if(!(id in this.selection)){
+							this.selectNone();
+							this.anchor = this.current;
+							this._addItemClass(this.current, "Anchor");
+							this.selection[id] = this.current;
+						}
+					}
+				}
+			}
+
+			dojo.stopEvent(e);
+		},
+
+		onMouseUp: function(e){
+			// summary:
+			//		Event processor for onmouseup
+			// e: Event
+			//		mouse event
+			// tags:
+			//		protected
+
+			// TODO: this code is apparently for handling an edge case when the user is selecting
+			// multiple nodes and then mousedowns on a node by accident... it lets the user keep the
+			// current selection by moving the mouse away (or something like that).   It doesn't seem
+			// to work though and requires a lot of plumbing (including this code, the onmousemove
+			// handler, and the this.simpleSelection attribute.   Consider getting rid of all of it.
+
+			if(!this.simpleSelection){ return; }
+			this.simpleSelection = false;
+			this.selectNone();
+			if(this.current){
+				this.anchor = this.current;
+				this._addItemClass(this.anchor, "Anchor");
+				this.selection[this.current.id] = this.current;
+			}
+		},
+		onMouseMove: function(e){
+			// summary
+			//		event processor for onmousemove
+			// e: Event
+			//		mouse event
+			this.simpleSelection = false;
+		},
+
+		_removeSelection: function(){
+			// summary:
+			//		Unselects all items
+			// tags:
+			//		private
+			var e = dojo.dnd._empty;
+			for(var i in this.selection){
+				if(i in e){ continue; }
+				var node = dojo.byId(i);
+				if(node){ this._removeItemClass(node, "Selected"); }
+			}
+			this.selection = {};
+			return this;	// self
+		},
+
+		_removeAnchor: function(){
+			// summary:
+			//		Removes the Anchor CSS class from a node.
+			//		According to `dojo.dnd.Selector`, anchor means that
+			//		"an item is selected, and is an anchor for a 'shift' selection".
+			//		It's not relevant for Tree at this point, since we don't support multiple selection.
+			// tags:
+			//		private
+			if(this.anchor){
+				this._removeItemClass(this.anchor, "Anchor");
+				this.anchor = null;
+			}
+			return this;	// self
+		},
+
+		forInSelectedItems: function(/*Function*/ f, /*Object?*/ o){
+			// summary:
+			//		Iterates over selected items;
+			//		see `dojo.dnd.Container.forInItems()` for details
+			o = o || dojo.global;
+			for(var id in this.selection){
+				console.log("selected item id: " + id);
+				f.call(o, this.getItem(id), id, this);
+			}
+		}
+});
diff --git a/dijit/tree/dndSource.js b/dijit/tree/dndSource.js
index d8f3627..54b867b 100644
--- a/dijit/tree/dndSource.js
+++ b/dijit/tree/dndSource.js
@@ -1,240 +1,526 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dijit.tree.dndSource"]){
-dojo._hasResource["dijit.tree.dndSource"]=true;
 dojo.provide("dijit.tree.dndSource");
+
 dojo.require("dijit.tree._dndSelector");
 dojo.require("dojo.dnd.Manager");
-dojo.declare("dijit.tree.dndSource",dijit.tree._dndSelector,{isSource:true,accept:["text","treeNode"],copyOnly:false,dragThreshold:5,betweenThreshold:0,constructor:function(_1,_2){
-if(!_2){
-_2={};
-}
-dojo.mixin(this,_2);
-this.isSource=typeof _2.isSource=="undefined"?true:_2.isSource;
-var _3=_2.accept instanceof Array?_2.accept:["text","treeNode"];
-this.accept=null;
-if(_3.length){
-this.accept={};
-for(var i=0;i<_3.length;++i){
-this.accept[_3[i]]=1;
-}
-}
-this.isDragging=false;
-this.mouseDown=false;
-this.targetAnchor=null;
-this.targetBox=null;
-this.dropPosition="";
-this._lastX=0;
-this._lastY=0;
-this.sourceState="";
-if(this.isSource){
-dojo.addClass(this.node,"dojoDndSource");
-}
-this.targetState="";
-if(this.accept){
-dojo.addClass(this.node,"dojoDndTarget");
-}
-this.topics=[dojo.subscribe("/dnd/source/over",this,"onDndSourceOver"),dojo.subscribe("/dnd/start",this,"onDndStart"),dojo.subscribe("/dnd/drop",this,"onDndDrop"),dojo.subscribe("/dnd/cancel",this,"onDndCancel")];
-},checkAcceptance:function(_4,_5){
-return true;
-},copyState:function(_6){
-return this.copyOnly||_6;
-},destroy:function(){
-this.inherited("destroy",arguments);
-dojo.forEach(this.topics,dojo.unsubscribe);
-this.targetAnchor=null;
-},_onDragMouse:function(e){
-var m=dojo.dnd.manager(),_7=this.targetAnchor,_8=this.current,_9=this.currentWidget,_a=this.dropPosition;
-var _b="Over";
-if(_8&&this.betweenThreshold>0){
-if(!this.targetBox||_7!=_8){
-this.targetBox=dojo.position(_8,true);
-}
-if((e.pageY-this.targetBox.y)<=this.betweenThreshold){
-_b="Before";
-}else{
-if((e.pageY-this.targetBox.y)>=(this.targetBox.h-this.betweenThreshold)){
-_b="After";
-}
-}
-}
-if(_8!=_7||_b!=_a){
-if(_7){
-this._removeItemClass(_7,_a);
-}
-if(_8){
-this._addItemClass(_8,_b);
-}
-if(!_8){
-m.canDrop(false);
-}else{
-if(_9==this.tree.rootNode&&_b!="Over"){
-m.canDrop(false);
-}else{
-if(m.source==this&&(_8.id in this.selection)){
-m.canDrop(false);
-}else{
-if(this.checkItemAcceptance(_8,m.source,_b.toLowerCase())&&!this._isParentChildDrop(m.source,_8)){
-m.canDrop(true);
-}else{
-m.canDrop(false);
-}
-}
-}
-}
-this.targetAnchor=_8;
-this.dropPosition=_b;
-}
-},onMouseMove:function(e){
-if(this.isDragging&&this.targetState=="Disabled"){
-return;
-}
-this.inherited(arguments);
-var m=dojo.dnd.manager();
-if(this.isDragging){
-this._onDragMouse(e);
-}else{
-if(this.mouseDown&&this.isSource&&(Math.abs(e.pageX-this._lastX)>=this.dragThreshold||Math.abs(e.pageY-this._lastY)>=this.dragThreshold)){
-var n=this.getSelectedNodes();
-var _c=[];
-for(var i in n){
-_c.push(n[i]);
-}
-if(_c.length){
-m.startDrag(this,_c,this.copyState(dojo.isCopyKey(e)));
-}
-}
-}
-},onMouseDown:function(e){
-this.mouseDown=true;
-this.mouseButton=e.button;
-this._lastX=e.pageX;
-this._lastY=e.pageY;
-this.inherited("onMouseDown",arguments);
-},onMouseUp:function(e){
-if(this.mouseDown){
-this.mouseDown=false;
-this.inherited("onMouseUp",arguments);
-}
-},onMouseOut:function(){
-this.inherited(arguments);
-this._unmarkTargetAnchor();
-},checkItemAcceptance:function(_d,_e,_f){
-return true;
-},onDndSourceOver:function(_10){
-if(this!=_10){
-this.mouseDown=false;
-this._unmarkTargetAnchor();
-}else{
-if(this.isDragging){
-var m=dojo.dnd.manager();
-m.canDrop(false);
-}
-}
-},onDndStart:function(_11,_12,_13){
-if(this.isSource){
-this._changeState("Source",this==_11?(_13?"Copied":"Moved"):"");
-}
-var _14=this.checkAcceptance(_11,_12);
-this._changeState("Target",_14?"":"Disabled");
-if(this==_11){
-dojo.dnd.manager().overSource(this);
-}
-this.isDragging=true;
-},itemCreator:function(_15,_16,_17){
-return dojo.map(_15,function(_18){
-return {"id":_18.id,"name":_18.textContent||_18.innerText||""};
+
+/*=====
+dijit.tree.__SourceArgs = function(){
+	// summary:
+	//		A dict of parameters for Tree source configuration.
+	// isSource: Boolean?
+	//		Can be used as a DnD source. Defaults to true.
+	// accept: String[]
+	//		List of accepted types (text strings) for a target; defaults to
+	//		["text", "treeNode"]
+	// copyOnly: Boolean?
+	//		Copy items, if true, use a state of Ctrl key otherwise,
+	// dragThreshold: Number
+	//		The move delay in pixels before detecting a drag; 0 by default
+	// betweenThreshold: Integer
+	//		Distance from upper/lower edge of node to allow drop to reorder nodes
+	this.isSource = isSource;
+	this.accept = accept;
+	this.autoSync = autoSync;
+	this.copyOnly = copyOnly;
+	this.dragThreshold = dragThreshold;
+	this.betweenThreshold = betweenThreshold;
+}
+=====*/
+
+dojo.declare("dijit.tree.dndSource", dijit.tree._dndSelector, {
+	// summary:
+	//		Handles drag and drop operations (as a source or a target) for `dijit.Tree`
+
+	// isSource: [private] Boolean
+	//		Can be used as a DnD source.
+	isSource: true,
+
+	// accept: String[]
+	//		List of accepted types (text strings) for the Tree; defaults to
+	//		["text"]
+	accept: ["text", "treeNode"],
+
+	// copyOnly: [private] Boolean
+	//		Copy items, if true, use a state of Ctrl key otherwise
+	copyOnly: false,
+
+	// dragThreshold: Number
+	//		The move delay in pixels before detecting a drag; 5 by default
+	dragThreshold: 5,
+
+	// betweenThreshold: Integer
+	//		Distance from upper/lower edge of node to allow drop to reorder nodes
+	betweenThreshold: 0,
+
+	constructor: function(/*dijit.Tree*/ tree, /*dijit.tree.__SourceArgs*/ params){
+		// summary:
+		//		a constructor of the Tree DnD Source
+		// tags:
+		//		private
+		if(!params){ params = {}; }
+		dojo.mixin(this, params);
+		this.isSource = typeof params.isSource == "undefined" ? true : params.isSource;
+		var type = params.accept instanceof Array ? params.accept : ["text", "treeNode"];
+		this.accept = null;
+		if(type.length){
+			this.accept = {};
+			for(var i = 0; i < type.length; ++i){
+				this.accept[type[i]] = 1;
+			}
+		}
+
+		// class-specific variables
+		this.isDragging = false;
+		this.mouseDown = false;
+		this.targetAnchor = null;	// DOMNode corresponding to the currently moused over TreeNode
+		this.targetBox = null;	// coordinates of this.targetAnchor
+		this.dropPosition = "";	// whether mouse is over/after/before this.targetAnchor
+		this._lastX = 0;
+		this._lastY = 0;
+
+		// states
+		this.sourceState = "";
+		if(this.isSource){
+			dojo.addClass(this.node, "dojoDndSource");
+		}
+		this.targetState = "";
+		if(this.accept){
+			dojo.addClass(this.node, "dojoDndTarget");
+		}
+
+		// set up events
+		this.topics = [
+			dojo.subscribe("/dnd/source/over", this, "onDndSourceOver"),
+			dojo.subscribe("/dnd/start", this, "onDndStart"),
+			dojo.subscribe("/dnd/drop", this, "onDndDrop"),
+			dojo.subscribe("/dnd/cancel", this, "onDndCancel")
+		];
+	},
+
+	// methods
+	checkAcceptance: function(source, nodes){
+		// summary:
+		//		Checks if the target can accept nodes from this source
+		// source: dijit.tree.dndSource
+		//		The source which provides items
+		// nodes: DOMNode[]
+		//		Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if
+		//		source is a dijit.Tree.
+		// tags:
+		//		extension
+		return true;	// Boolean
+	},
+
+	copyState: function(keyPressed){
+		// summary:
+		//		Returns true, if we need to copy items, false to move.
+		//		It is separated to be overwritten dynamically, if needed.
+		// keyPressed: Boolean
+		//		The "copy" control key was pressed
+		// tags:
+		//		protected
+		return this.copyOnly || keyPressed;	// Boolean
+	},
+	destroy: function(){
+		// summary:
+		//		Prepares the object to be garbage-collected.
+		this.inherited("destroy",arguments);
+		dojo.forEach(this.topics, dojo.unsubscribe);
+		this.targetAnchor = null;
+	},
+
+	_onDragMouse: function(e){
+		// summary:
+		//		Helper method for processing onmousemove/onmouseover events while drag is in progress.
+		//		Keeps track of current drop target.
+
+		var m = dojo.dnd.manager(),
+			oldTarget = this.targetAnchor,			// the DOMNode corresponding to TreeNode mouse was previously over
+			newTarget = this.current,				// DOMNode corresponding to TreeNode mouse is currently over
+			newTargetWidget = this.currentWidget,	// the TreeNode itself
+			oldDropPosition = this.dropPosition;	// the previous drop position (over/before/after)
+
+		// calculate if user is indicating to drop the dragged node before, after, or over
+		// (i.e., to become a child of) the target node
+		var newDropPosition = "Over";
+		if(newTarget && this.betweenThreshold > 0){
+			// If mouse is over a new TreeNode, then get new TreeNode's position and size
+			if(!this.targetBox || oldTarget != newTarget){
+				this.targetBox = dojo.position(newTarget, true);
+			}
+			if((e.pageY - this.targetBox.y) <= this.betweenThreshold){
+				newDropPosition = "Before";
+			}else if((e.pageY - this.targetBox.y) >= (this.targetBox.h - this.betweenThreshold)){
+				newDropPosition = "After";
+			}
+		}
+
+		if(newTarget != oldTarget || newDropPosition != oldDropPosition){
+			if(oldTarget){
+				this._removeItemClass(oldTarget, oldDropPosition);
+			}
+			if(newTarget){
+				this._addItemClass(newTarget, newDropPosition);
+			}
+
+			// Check if it's ok to drop the dragged node on/before/after the target node.
+			if(!newTarget){
+				m.canDrop(false);
+			}else if(newTargetWidget == this.tree.rootNode && newDropPosition != "Over"){
+				// Can't drop before or after tree's root node; the dropped node would just disappear (at least visually)
+				m.canDrop(false);
+			}else if(m.source == this && (newTarget.id in this.selection)){
+				// Guard against dropping onto yourself (TODO: guard against dropping onto your descendant, #7140)
+				m.canDrop(false);
+			}else if(this.checkItemAcceptance(newTarget, m.source, newDropPosition.toLowerCase())
+					&& !this._isParentChildDrop(m.source, newTarget)){
+				m.canDrop(true);
+			}else{
+				m.canDrop(false);
+			}
+
+			this.targetAnchor = newTarget;
+			this.dropPosition = newDropPosition;
+		}
+	},
+
+	onMouseMove: function(e){
+		// summary:
+		//		Called for any onmousemove events over the Tree
+		// e: Event
+		//		onmousemouse event
+		// tags:
+		//		private
+		if(this.isDragging && this.targetState == "Disabled"){ return; }
+		this.inherited(arguments);
+		var m = dojo.dnd.manager();
+		if(this.isDragging){
+			this._onDragMouse(e);
+		}else{
+			if(this.mouseDown && this.isSource &&
+				 (Math.abs(e.pageX-this._lastX)>=this.dragThreshold || Math.abs(e.pageY-this._lastY)>=this.dragThreshold)){
+				var n = this.getSelectedNodes();
+				var nodes=[];
+				for(var i in n){
+					nodes.push(n[i]);
+				}
+				if(nodes.length){
+					m.startDrag(this, nodes, this.copyState(dojo.isCopyKey(e)));
+				}
+			}
+		}
+	},
+
+	onMouseDown: function(e){
+		// summary:
+		//		Event processor for onmousedown
+		// e: Event
+		//		onmousedown event
+		// tags:
+		//		private
+		this.mouseDown = true;
+		this.mouseButton = e.button;
+		this._lastX = e.pageX;
+		this._lastY = e.pageY;
+		this.inherited("onMouseDown",arguments);
+	},
+
+	onMouseUp: function(e){
+		// summary:
+		//		Event processor for onmouseup
+		// e: Event
+		//		onmouseup event
+		// tags:
+		//		private
+		if(this.mouseDown){
+			this.mouseDown = false;
+			this.inherited("onMouseUp",arguments);
+		}
+	},
+
+	onMouseOut: function(){
+		// summary:
+		//		Event processor for when mouse is moved away from a TreeNode
+		// tags:
+		//		private
+		this.inherited(arguments);
+		this._unmarkTargetAnchor();
+	},
+
+	checkItemAcceptance: function(target, source, position){
+		// summary:
+		//		Stub function to be overridden if one wants to check for the ability to drop at the node/item level
+		// description:
+		//		In the base case, this is called to check if target can become a child of source.
+		//		When betweenThreshold is set, position="before" or "after" means that we
+		//		are asking if the source node can be dropped before/after the target node.
+		// target: DOMNode
+		//		The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to
+		//		Use dijit.getEnclosingWidget(target) to get the TreeNode.
+		// source: dijit.tree.dndSource
+		//		The (set of) nodes we are dropping
+		// position: String
+		//		"over", "before", or "after"
+		// tags:
+		//		extension
+		return true;
+	},
+
+	// topic event processors
+	onDndSourceOver: function(source){
+		// summary:
+		//		Topic event processor for /dnd/source/over, called when detected a current source.
+		// source: Object
+		//		The dijit.tree.dndSource / dojo.dnd.Source which has the mouse over it
+		// tags:
+		//		private
+		if(this != source){
+			this.mouseDown = false;
+			this._unmarkTargetAnchor();
+		}else if(this.isDragging){
+			var m = dojo.dnd.manager();
+			m.canDrop(false);
+		}
+	},
+	onDndStart: function(source, nodes, copy){
+		// summary:
+		//		Topic event processor for /dnd/start, called to initiate the DnD operation
+		// source: Object
+		//		The dijit.tree.dndSource / dojo.dnd.Source which is providing the items
+		// nodes: DomNode[]
+		//		The list of transferred items, dndTreeNode nodes if dragging from a Tree
+		// copy: Boolean
+		//		Copy items, if true, move items otherwise
+		// tags:
+		//		private
+
+		if(this.isSource){
+			this._changeState("Source", this == source ? (copy ? "Copied" : "Moved") : "");
+		}
+		var accepted = this.checkAcceptance(source, nodes);
+
+		this._changeState("Target", accepted ? "" : "Disabled");
+
+		if(this == source){
+			dojo.dnd.manager().overSource(this);
+		}
+
+		this.isDragging = true;
+	},
+
+	itemCreator: function(/*DomNode[]*/ nodes, target, /*dojo.dnd.Source*/ source){
+		// summary:
+		//		Returns objects passed to `Tree.model.newItem()` based on DnD nodes
+		//		dropped onto the tree.   Developer must override this method to enable
+		// 		dropping from external sources onto this Tree, unless the Tree.model's items
+		//		happen to look like {id: 123, name: "Apple" } with no other attributes.
+		// description:
+		//		For each node in nodes[], which came from source, create a hash of name/value
+		//		pairs to be passed to Tree.model.newItem().  Returns array of those hashes.
+		// returns: Object[]
+		//		Array of name/value hashes for each new item to be added to the Tree, like:
+		// |	[
+		// |		{ id: 123, label: "apple", foo: "bar" },
+		// |		{ id: 456, label: "pear", zaz: "bam" }
+		// |	]
+		// tags:
+		//		extension
+
+		// TODO: for 2.0 refactor so itemCreator() is called once per drag node, and
+		// make signature itemCreator(sourceItem, node, target) (or similar).
+
+		return dojo.map(nodes, function(node){
+			return {
+				"id": node.id,
+				"name": node.textContent || node.innerText || ""
+			};
+		}); // Object[]
+	},
+
+	onDndDrop: function(source, nodes, copy){
+		// summary:
+		//		Topic event processor for /dnd/drop, called to finish the DnD operation.
+		// description:
+		//		Updates data store items according to where node was dragged from and dropped
+		//		to.   The tree will then respond to those data store updates and redraw itself.
+		// source: Object
+		//		The dijit.tree.dndSource / dojo.dnd.Source which is providing the items
+		// nodes: DomNode[]
+		//		The list of transferred items, dndTreeNode nodes if dragging from a Tree
+		// copy: Boolean
+		//		Copy items, if true, move items otherwise
+		// tags:
+		//		protected
+		if(this.containerState == "Over"){
+			var tree = this.tree,
+				model = tree.model,
+				target = this.targetAnchor,
+				requeryRoot = false;	// set to true iff top level items change
+
+			this.isDragging = false;
+
+			// Compute the new parent item
+			var targetWidget = dijit.getEnclosingWidget(target);
+			var newParentItem;
+			var insertIndex;
+			newParentItem = (targetWidget && targetWidget.item) || tree.item;
+			if(this.dropPosition == "Before" || this.dropPosition == "After"){
+				// TODO: if there is no parent item then disallow the drop.
+				// Actually this should be checked during onMouseMove too, to make the drag icon red.
+				newParentItem = (targetWidget.getParent() && targetWidget.getParent().item) || tree.item;
+				// Compute the insert index for reordering
+				insertIndex = targetWidget.getIndexInParent();
+				if(this.dropPosition == "After"){
+					insertIndex = targetWidget.getIndexInParent() + 1;
+				}
+			}else{
+				newParentItem = (targetWidget && targetWidget.item) || tree.item;
+			}
+
+			// If necessary, use this variable to hold array of hashes to pass to model.newItem()
+			// (one entry in the array for each dragged node).
+			var newItemsParams;
+
+			dojo.forEach(nodes, function(node, idx){
+				// dojo.dnd.Item representing the thing being dropped.
+				// Don't confuse the use of item here (meaning a DnD item) with the
+				// uses below where item means dojo.data item.
+				var sourceItem = source.getItem(node.id);
+
+				// Information that's available if the source is another Tree
+				// (possibly but not necessarily this tree, possibly but not
+				// necessarily the same model as this Tree)
+				if(dojo.indexOf(sourceItem.type, "treeNode") != -1){
+					var childTreeNode = sourceItem.data,
+						childItem = childTreeNode.item,
+						oldParentItem = childTreeNode.getParent().item;
+				}
+
+				if(source == this){
+					// This is a node from my own tree, and we are moving it, not copying.
+					// Remove item from old parent's children attribute.
+					// TODO: dijit.tree.dndSelector should implement deleteSelectedNodes()
+					// and this code should go there.
+
+					if(typeof insertIndex == "number"){
+						if(newParentItem == oldParentItem && childTreeNode.getIndexInParent() < insertIndex){
+							insertIndex -= 1;
+						}
+					}
+					model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex);
+				}else if(model.isItem(childItem)){
+					// Item from same model
+					// (maybe we should only do this branch if the source is a tree?)
+					model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex);
+				}else{
+					// Get the hash to pass to model.newItem().  A single call to
+					// itemCreator() returns an array of hashes, one for each drag source node.
+					if(!newItemsParams){
+						newItemsParams = this.itemCreator(nodes, target, source);
+					}
+
+					// Create new item in the tree, based on the drag source.
+					model.newItem(newItemsParams[idx], newParentItem, insertIndex);
+				}
+			}, this);
+
+			// Expand the target node (if it's currently collapsed) so the user can see
+			// where their node was dropped.   In particular since that node is still selected.
+			this.tree._expandNode(targetWidget);
+		}
+		this.onDndCancel();
+	},
+
+	onDndCancel: function(){
+		// summary:
+		//		Topic event processor for /dnd/cancel, called to cancel the DnD operation
+		// tags:
+		//		private
+		this._unmarkTargetAnchor();
+		this.isDragging = false;
+		this.mouseDown = false;
+		delete this.mouseButton;
+		this._changeState("Source", "");
+		this._changeState("Target", "");
+	},
+
+	// When focus moves in/out of the entire Tree
+	onOverEvent: function(){
+		// summary:
+		//		This method is called when mouse is moved over our container (like onmouseenter)
+		// tags:
+		//		private
+		this.inherited(arguments);
+		dojo.dnd.manager().overSource(this);
+	},
+	onOutEvent: function(){
+		// summary:
+		//		This method is called when mouse is moved out of our container (like onmouseleave)
+		// tags:
+		//		private
+		this._unmarkTargetAnchor();
+		var m = dojo.dnd.manager();
+		if(this.isDragging){
+			m.canDrop(false);
+		}
+		m.outSource(this);
+
+		this.inherited(arguments);
+	},
+
+	_isParentChildDrop: function(source, targetRow){
+		// summary:
+		//		Checks whether the dragged items are parent rows in the tree which are being
+		//		dragged into their own children.
+		//
+		// source:
+		//		The DragSource object.
+		//
+		// targetRow:
+		//		The tree row onto which the dragged nodes are being dropped.
+		//
+		// tags:
+		//		private
+
+		// If the dragged object is not coming from the tree this widget belongs to,
+		// it cannot be invalid.
+		if(!source.tree || source.tree != this.tree){
+			return false;
+		}
+
+
+		var root = source.tree.domNode;
+		var ids = {};
+		for(var x in source.selection){
+			ids[source.selection[x].parentNode.id] = true;
+		}
+
+		var node = targetRow.parentNode;
+
+		// Iterate up the DOM hierarchy from the target drop row,
+		// checking of any of the dragged nodes have the same ID.
+		while(node != root && (!node.id || !ids[node.id])){
+			node = node.parentNode;
+		}
+
+		return node.id && ids[node.id];
+	},
+
+	_unmarkTargetAnchor: function(){
+		// summary:
+		//		Removes hover class of the current target anchor
+		// tags:
+		//		private
+		if(!this.targetAnchor){ return; }
+		this._removeItemClass(this.targetAnchor, this.dropPosition);
+		this.targetAnchor = null;
+		this.targetBox = null;
+		this.dropPosition = null;
+	},
+
+	_markDndStatus: function(copy){
+		// summary:
+		//		Changes source's state based on "copy" status
+		this._changeState("Source", copy ? "Copied" : "Moved");
+	}
 });
-},onDndDrop:function(_19,_1a,_1b){
-if(this.containerState=="Over"){
-var _1c=this.tree,_1d=_1c.model,_1e=this.targetAnchor,_1f=false;
-this.isDragging=false;
-var _20=dijit.getEnclosingWidget(_1e);
-var _21;
-var _22;
-_21=(_20&&_20.item)||_1c.item;
-if(this.dropPosition=="Before"||this.dropPosition=="After"){
-_21=(_20.getParent()&&_20.getParent().item)||_1c.item;
-_22=_20.getIndexInParent();
-if(this.dropPosition=="After"){
-_22=_20.getIndexInParent()+1;
-}
-}else{
-_21=(_20&&_20.item)||_1c.item;
-}
-var _23;
-dojo.forEach(_1a,function(_24,idx){
-var _25=_19.getItem(_24.id);
-if(dojo.indexOf(_25.type,"treeNode")!=-1){
-var _26=_25.data,_27=_26.item,_28=_26.getParent().item;
-}
-if(_19==this){
-if(typeof _22=="number"){
-if(_21==_28&&_26.getIndexInParent()<_22){
-_22-=1;
-}
-}
-_1d.pasteItem(_27,_28,_21,_1b,_22);
-}else{
-if(_1d.isItem(_27)){
-_1d.pasteItem(_27,_28,_21,_1b,_22);
-}else{
-if(!_23){
-_23=this.itemCreator(_1a,_1e,_19);
-}
-_1d.newItem(_23[idx],_21,_22);
-}
-}
-},this);
-this.tree._expandNode(_20);
-}
-this.onDndCancel();
-},onDndCancel:function(){
-this._unmarkTargetAnchor();
-this.isDragging=false;
-this.mouseDown=false;
-delete this.mouseButton;
-this._changeState("Source","");
-this._changeState("Target","");
-},onOverEvent:function(){
-this.inherited(arguments);
-dojo.dnd.manager().overSource(this);
-},onOutEvent:function(){
-this._unmarkTargetAnchor();
-var m=dojo.dnd.manager();
-if(this.isDragging){
-m.canDrop(false);
-}
-m.outSource(this);
-this.inherited(arguments);
-},_isParentChildDrop:function(_29,_2a){
-if(!_29.tree||_29.tree!=this.tree){
-return false;
-}
-var _2b=_29.tree.domNode;
-var ids={};
-for(var x in _29.selection){
-ids[_29.selection[x].parentNode.id]=true;
-}
-var _2c=_2a.parentNode;
-while(_2c!=_2b&&(!_2c.id||!ids[_2c.id])){
-_2c=_2c.parentNode;
-}
-return _2c.id&&ids[_2c.id];
-},_unmarkTargetAnchor:function(){
-if(!this.targetAnchor){
-return;
-}
-this._removeItemClass(this.targetAnchor,this.dropPosition);
-this.targetAnchor=null;
-this.targetBox=null;
-this.dropPosition=null;
-},_markDndStatus:function(_2d){
-this._changeState("Source",_2d?"Copied":"Moved");
-}});
-}
diff --git a/dijit/tree/model.js b/dijit/tree/model.js
index b21a9b6..5791a2e 100644
--- a/dijit/tree/model.js
+++ b/dijit/tree/model.js
@@ -1,20 +1,128 @@
-/*
-	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
-*/
-
-
-dojo.declare("dijit.tree.model",null,{destroy:function(){
-},getRoot:function(_1){
-},mayHaveChildren:function(_2){
-},getChildren:function(_3,_4){
-},isItem:function(_5){
-},fetchItemByIdentity:function(_6){
-},getIdentity:function(_7){
-},getLabel:function(_8){
-},newItem:function(_9,_a,_b){
-},pasteItem:function(_c,_d,_e,_f){
-},onChange:function(_10){
-},onChildrenChange:function(_11,_12){
-}});
+
+dojo.declare(
+	"dijit.tree.model",
+	null,
+{
+	// summary:
+	//		Contract for any data provider object for the tree.
+	// description:
+	//		Tree passes in values to the constructor to specify the callbacks.
+	//		"item" is typically a dojo.data.Item but it's just a black box so
+	//		it could be anything.
+	//
+	//		This (like `dojo.data.api.Read`) is just documentation, and not meant to be used.
+
+	destroy: function(){
+		// summary:
+		//		Destroys this object, releasing connections to the store
+		// tags:
+		//		extension
+	},
+
+	// =======================================================================
+	// Methods for traversing hierarchy
+
+	getRoot: function(onItem){
+		// summary:
+		//		Calls onItem with the root item for the tree, possibly a fabricated item.
+		//		Throws exception on error.
+		// tags:
+		//		extension
+	},
+
+	mayHaveChildren: function(/*dojo.data.Item*/ item){
+		// summary:
+		//		Tells if an item has or may have children.  Implementing logic here
+		//		avoids showing +/- expando icon for nodes that we know don't have children.
+		//		(For efficiency reasons we may not want to check if an element actually
+		//		has children until user clicks the expando node)
+		// tags:
+		//		extension
+	},
+
+	getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete){
+		// summary:
+		// 		Calls onComplete() with array of child items of given parent item, all loaded.
+		//		Throws exception on error.
+		// tags:
+		//		extension
+	},
+
+	// =======================================================================
+	// Inspecting items
+
+	isItem: function(/* anything */ something){
+		// summary:
+		//		Returns true if *something* is an item and came from this model instance.
+		//		Returns false if *something* is a literal, an item from another model instance,
+		//		or is any object other than an item.
+		// tags:
+		//		extension
+	},
+
+	fetchItemByIdentity: function(/* object */ keywordArgs){
+		// summary:
+		//		Given the identity of an item, this method returns the item that has
+		//		that identity through the onItem callback.  Conforming implementations
+		//		should return null if there is no item with the given identity.
+		//		Implementations of fetchItemByIdentity() may sometimes return an item
+		//		from a local cache and may sometimes fetch an item from a remote server.
+		// tags:
+		//		extension
+	},
+
+	getIdentity: function(/* item */ item){
+		// summary:
+		//		Returns identity for an item
+		// tags:
+		//		extension
+	},
+
+	getLabel: function(/*dojo.data.Item*/ item){
+		// summary:
+		//		Get the label for an item
+		// tags:
+		//		extension
+	},
+
+	// =======================================================================
+	// Write interface
+
+	newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
+		// summary:
+		//		Creates a new item.   See `dojo.data.api.Write` for details on args.
+		// tags:
+		//		extension
+	},
+
+	pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy){
+		// summary:
+		//		Move or copy an item from one parent item to another.
+		//		Used in drag & drop.
+		//		If oldParentItem is specified and bCopy is false, childItem is removed from oldParentItem.
+		//		If newParentItem is specified, childItem is attached to newParentItem.
+		// tags:
+		//		extension
+	},
+
+	// =======================================================================
+	// Callbacks
+
+	onChange: function(/*dojo.data.Item*/ item){
+		// summary:
+		//		Callback whenever an item has changed, so that Tree
+		//		can update the label, icon, etc.   Note that changes
+		//		to an item's children or parent(s) will trigger an
+		//		onChildrenChange() so you can ignore those changes here.
+		// tags:
+		//		callback
+	},
+
+	onChildrenChange: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
+		// summary:
+		//		Callback to do notifications about new, updated, or deleted items.
+		// tags:
+		//		callback
+	}
+});
+
diff --git a/dojo/AdapterRegistry.js b/dojo/AdapterRegistry.js
index 60039b3..d186330 100644
--- a/dojo/AdapterRegistry.js
+++ b/dojo/AdapterRegistry.js
@@ -1,39 +1,95 @@
-/*
-	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
-*/
+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
 
-if(!dojo._hasResource["dojo.AdapterRegistry"]){
-dojo._hasResource["dojo.AdapterRegistry"]=true;
-dojo.provide("dojo.AdapterRegistry");
-dojo.AdapterRegistry=function(_1){
-this.pairs=[];
-this.returnWrappers=_1||false;
-};
-dojo.extend(dojo.AdapterRegistry,{register:function(_2,_3,_4,_5,_6){
-this.pairs[((_6)?"unshift":"push")]([_2,_3,_4,_5]);
-},match:function(){
-for(var i=0;i<this.pairs.length;i++){
-var _7=this.pairs[i];
-if(_7[1].apply(this,arguments)){
-if((_7[3])||(this.returnWrappers)){
-return _7[2];
-}else{
-return _7[2].apply(this,arguments);
-}
-}
-}
-throw new Error("No match found");
-},unregister:function(_8){
-for(var i=0;i<this.pairs.length;i++){
-var _9=this.pairs[i];
-if(_9[0]==_8){
-this.pairs.splice(i,1);
-return true;
-}
-}
-return false;
-}});
+	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;
+	}
+});
diff --git a/dojo/DeferredList.js b/dojo/DeferredList.js
index abc81d3..797c612 100644
--- a/dojo/DeferredList.js
+++ b/dojo/DeferredList.js
@@ -1,69 +1,72 @@
-/*
-	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
-*/
+dojo.provide("dojo.DeferredList");
+dojo.DeferredList = function(/*Array*/ list, /*Boolean?*/ fireOnOneCallback, /*Boolean?*/ fireOnOneErrback, /*Boolean?*/ consumeErrors, /*Function?*/ canceller){
+	// summary:
+	//		Provides event handling for a group of Deferred objects.
+	// description:
+	//		DeferredList takes an array of existing deferreds and returns a new deferred of its own
+	//		this new deferred will typically have its callback fired when all of the deferreds in
+	//		the given list have fired their own deferreds.  The parameters `fireOnOneCallback` and
+	//		fireOnOneErrback, will fire before all the deferreds as appropriate
+	//
+	//	list:
+	//		The list of deferreds to be synchronizied with this DeferredList
+	//	fireOnOneCallback:
+	//		Will cause the DeferredLists callback to be fired as soon as any
+	//		of the deferreds in its list have been fired instead of waiting until
+	//		the entire list has finished
+	//	fireonOneErrback:
+	//		Will cause the errback to fire upon any of the deferreds errback
+	//	canceller:
+	//		A deferred canceller function, see dojo.Deferred
+	var resultList = [];
+	dojo.Deferred.call(this);
+	var self = this;
+	if(list.length === 0 && !fireOnOneCallback){
+		this.resolve([0, []]);
+	}
+	var finished = 0;
+	dojo.forEach(list, function(item, i){
+		item.then(function(result){
+			if(fireOnOneCallback){
+				self.resolve([i, result]);
+			}else{
+				addResult(true, result);
+			}
+		},function(error){
+			if(fireOnOneErrback){
+				self.reject(error);
+			}else{
+				addResult(false, error);
+			}
+			if(consumeErrors){
+				return null;
+			}
+			throw error;
+		});
+		function addResult(succeeded, result){
+			resultList[i] = [succeeded, result];
+			finished++;
+			if(finished === list.length){
+				self.resolve(resultList);
+			}
+			
+		}
+	});
+};
+dojo.DeferredList.prototype = new dojo.Deferred();
 
+dojo.DeferredList.prototype.gatherResults= function(deferredList){
+	// summary:	
+	//	Gathers the results of the deferreds for packaging
+	//	as the parameters to the Deferred Lists' callback
 
-if(!dojo._hasResource["dojo.DeferredList"]){
-dojo._hasResource["dojo.DeferredList"]=true;
-dojo.provide("dojo.DeferredList");
-dojo.declare("dojo.DeferredList",dojo.Deferred,{constructor:function(_1,_2,_3,_4,_5){
-this.list=_1;
-this.resultList=new Array(this.list.length);
-this.chain=[];
-this.id=this._nextId();
-this.fired=-1;
-this.paused=0;
-this.results=[null,null];
-this.canceller=_5;
-this.silentlyCancelled=false;
-if(this.list.length===0&&!_2){
-this.callback(this.resultList);
-}
-this.finishedCount=0;
-this.fireOnOneCallback=_2;
-this.fireOnOneErrback=_3;
-this.consumeErrors=_4;
-dojo.forEach(this.list,function(d,_6){
-d.addCallback(this,function(r){
-this._cbDeferred(_6,true,r);
-return r;
-});
-d.addErrback(this,function(r){
-this._cbDeferred(_6,false,r);
-return r;
-});
-},this);
-},_cbDeferred:function(_7,_8,_9){
-this.resultList[_7]=[_8,_9];
-this.finishedCount+=1;
-if(this.fired!==0){
-if(_8&&this.fireOnOneCallback){
-this.callback([_7,_9]);
-}else{
-if(!_8&&this.fireOnOneErrback){
-this.errback(_9);
-}else{
-if(this.finishedCount==this.list.length){
-this.callback(this.resultList);
-}
-}
-}
-}
-if(!_8&&this.consumeErrors){
-_9=null;
-}
-return _9;
-},gatherResults:function(_a){
-var d=new dojo.DeferredList(_a,false,true,false);
-d.addCallback(function(_b){
-var _c=[];
-dojo.forEach(_b,function(_d){
-_c.push(_d[1]);
-});
-return _c;
-});
-return d;
-}});
-}
+	var d = new dojo.DeferredList(deferredList, false, true, false);
+	d.addCallback(function(results){
+		var ret = [];
+		dojo.forEach(results, function(result){
+			ret.push(result[1]);
+		});
+		return ret;
+	});
+	return d;
+};
diff --git a/dojo/LICENSE b/dojo/LICENSE
index ad1676a..4c93ded 100644
--- a/dojo/LICENSE
+++ b/dojo/LICENSE
@@ -13,7 +13,7 @@ The text of the AFL and BSD licenses is reproduced below.
 The "New" BSD License:
 **********************
 
-Copyright (c) 2005-2009, The Dojo Foundation
+Copyright (c) 2005-2010, The Dojo Foundation
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/dojo/NodeList-fx.js b/dojo/NodeList-fx.js
index 76a26fd..40d3b39 100644
--- a/dojo/NodeList-fx.js
+++ b/dojo/NodeList-fx.js
@@ -1,40 +1,207 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.NodeList-fx"]){
-dojo._hasResource["dojo.NodeList-fx"]=true;
 dojo.provide("dojo.NodeList-fx");
 dojo.require("dojo.fx");
-dojo.extend(dojo.NodeList,{_anim:function(_1,_2,_3){
-_3=_3||{};
-return dojo.fx.combine(this.map(function(_4){
-var _5={node:_4};
-dojo.mixin(_5,_3);
-return _1[_2](_5);
-}));
-},wipeIn:function(_6){
-return this._anim(dojo.fx,"wipeIn",_6);
-},wipeOut:function(_7){
-return this._anim(dojo.fx,"wipeOut",_7);
-},slideTo:function(_8){
-return this._anim(dojo.fx,"slideTo",_8);
-},fadeIn:function(_9){
-return this._anim(dojo,"fadeIn",_9);
-},fadeOut:function(_a){
-return this._anim(dojo,"fadeOut",_a);
-},animateProperty:function(_b){
-return this._anim(dojo,"animateProperty",_b);
-},anim:function(_c,_d,_e,_f,_10){
-var _11=dojo.fx.combine(this.map(function(_12){
-return dojo.animateProperty({node:_12,properties:_c,duration:_d||350,easing:_e});
-}));
-if(_f){
-dojo.connect(_11,"onEnd",_f);
-}
-return _11.play(_10||0);
-}});
-}
+
+/*=====
+dojo["NodeList-fx"] = {
+	// summary: Adds dojo.fx animation support to dojo.query()
+};
+=====*/
+
+dojo.extend(dojo.NodeList, {
+	_anim: function(obj, method, args){
+		args = args||{};
+		var a = dojo.fx.combine(
+			this.map(function(item){
+				var tmpArgs = { node: item };
+				dojo.mixin(tmpArgs, args);
+				return obj[method](tmpArgs);
+			})
+		); 
+		return args.auto ? a.play() && this : a; // dojo.Animation|dojo.NodeList
+	},
+
+	wipeIn: function(args){
+		//	summary:
+		//		wipe in all elements of this NodeList via `dojo.fx.wipeIn`
+		//
+		//	args: Object?
+		//		Additional dojo.Animation arguments to mix into this set with the addition of 
+		//		an `auto` parameter.
+		//
+		//	returns: dojo.Animation|dojo.NodeList
+		//		A special args member `auto` can be passed to automatically play the animation.
+		//		If args.auto is present, the original dojo.NodeList will be returned for further
+		//		chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+		//
+		//	example:
+		//		Fade in all tables with class "blah":
+		//		|	dojo.query("table.blah").wipeIn().play();
+		//
+		//	example:
+		//		Utilizing `auto` to get the NodeList back:
+		//		|	dojo.query(".titles").wipeIn({ auto:true }).onclick(someFunction);
+		//
+		return this._anim(dojo.fx, "wipeIn", args); // dojo.Animation|dojo.NodeList
+	},
+
+	wipeOut: function(args){
+		//	summary:
+		//		wipe out all elements of this NodeList via `dojo.fx.wipeOut`
+		//
+		//	args: Object?
+		//		Additional dojo.Animation arguments to mix into this set with the addition of 
+		//		an `auto` parameter.
+		//
+		//	returns: dojo.Animation|dojo.NodeList
+		//		A special args member `auto` can be passed to automatically play the animation.
+		//		If args.auto is present, the original dojo.NodeList will be returned for further
+		//		chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+		//
+		//	example:
+		//		Wipe out all tables with class "blah":
+		//		|	dojo.query("table.blah").wipeOut().play();
+		return this._anim(dojo.fx, "wipeOut", args); // dojo.Animation|dojo.NodeList
+	},
+
+	slideTo: function(args){
+		//	summary:
+		//		slide all elements of the node list to the specified place via `dojo.fx.slideTo`
+		//
+		//	args: Object?
+		//		Additional dojo.Animation arguments to mix into this set with the addition of 
+		//		an `auto` parameter.
+		//
+		//	returns: dojo.Animation|dojo.NodeList
+		//		A special args member `auto` can be passed to automatically play the animation.
+		//		If args.auto is present, the original dojo.NodeList will be returned for further
+		//		chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+		//
+		//	example:
+		//		|	Move all tables with class "blah" to 300/300:
+		//		|	dojo.query("table.blah").slideTo({
+		//		|		left: 40,
+		//		|		top: 50
+		//		|	}).play();
+		return this._anim(dojo.fx, "slideTo", args); // dojo.Animation|dojo.NodeList
+	},
+
+
+	fadeIn: function(args){
+		//	summary:
+		//		fade in all elements of this NodeList via `dojo.fadeIn`
+		//
+		//	args: Object?
+		//		Additional dojo.Animation arguments to mix into this set with the addition of 
+		//		an `auto` parameter.
+		//
+		//	returns: dojo.Animation|dojo.NodeList
+		//		A special args member `auto` can be passed to automatically play the animation.
+		//		If args.auto is present, the original dojo.NodeList will be returned for further
+		//		chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+		//
+		//	example:
+		//		Fade in all tables with class "blah":
+		//		|	dojo.query("table.blah").fadeIn().play();
+		return this._anim(dojo, "fadeIn", args); // dojo.Animation|dojo.NodeList
+	},
+
+	fadeOut: function(args){
+		//	summary:
+		//		fade out all elements of this NodeList via `dojo.fadeOut`
+		//
+		//	args: Object?
+		//		Additional dojo.Animation arguments to mix into this set with the addition of 
+		//		an `auto` parameter.
+		//
+		//	returns: dojo.Animation|dojo.NodeList
+		//		A special args member `auto` can be passed to automatically play the animation.
+		//		If args.auto is present, the original dojo.NodeList will be returned for further
+		//		chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+		//
+		//	example:
+		//		Fade out all elements with class "zork":
+		//		|	dojo.query(".zork").fadeOut().play();
+		//	example:
+		//		Fade them on a delay and do something at the end:
+		//		|	var fo = dojo.query(".zork").fadeOut();
+		//		|	dojo.connect(fo, "onEnd", function(){ /*...*/ });
+		//		|	fo.play();
+		//	example:
+		//		Using `auto`:
+		//		|	dojo.query("li").fadeOut({ auto:true }).filter(filterFn).forEach(doit);
+		//
+		return this._anim(dojo, "fadeOut", args); // dojo.Animation|dojo.NodeList
+	},
+
+	animateProperty: function(args){
+		//	summary:
+		//		Animate all elements of this NodeList across the properties specified.
+		//		syntax identical to `dojo.animateProperty`
+		//
+		// returns: dojo.Animation|dojo.NodeList
+		//		A special args member `auto` can be passed to automatically play the animation.
+		//		If args.auto is present, the original dojo.NodeList will be returned for further
+		//		chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+		//
+		//	example:
+		//	|	dojo.query(".zork").animateProperty({
+		//	|		duration: 500,
+		//	|		properties: { 
+		//	|			color:		{ start: "black", end: "white" },
+		//	|			left:		{ end: 300 } 
+		//	|		} 
+		//	|	}).play();
+		//
+		//	example:
+		//	|	dojo.query(".grue").animateProperty({ 
+		//	|		auto:true,
+		//	|		properties: {
+		//	|			height:240
+		//	|		}
+		//	|	}).onclick(handler);
+		return this._anim(dojo, "animateProperty", args); // dojo.Animation|dojo.NodeList
+	},
+
+	anim: function( /*Object*/			properties, 
+					/*Integer?*/		duration, 
+					/*Function?*/		easing, 
+					/*Function?*/		onEnd,
+					/*Integer?*/		delay){
+		//	summary:
+		//		Animate one or more CSS properties for all nodes in this list.
+		//		The returned animation object will already be playing when it
+		//		is returned. See the docs for `dojo.anim` for full details.
+		//	properties: Object
+		//		the properties to animate. does NOT support the `auto` parameter like other 
+		//		NodeList-fx methods. 
+		//	duration: Integer?
+		//		Optional. The time to run the animations for
+		//	easing: Function?
+		//		Optional. The easing function to use.
+		//	onEnd: Function?
+		//		A function to be called when the animation ends
+		//	delay:
+		//		how long to delay playing the returned animation
+		//	example:
+		//		Another way to fade out:
+		//	|	dojo.query(".thinger").anim({ opacity: 0 });
+		//	example:
+		//		animate all elements with the "thigner" class to a width of 500
+		//		pixels over half a second
+		//	|	dojo.query(".thinger").anim({ width: 500 }, 700);
+		var canim = dojo.fx.combine(
+			this.map(function(item){
+				return dojo.animateProperty({
+					node: item,
+					properties: properties,
+					duration: duration||350,
+					easing: easing
+				});
+			})
+		); 
+		if(onEnd){
+			dojo.connect(canim, "onEnd", onEnd);
+		}
+		return canim.play(delay||0); // dojo.Animation
+	}
+});
diff --git a/dojo/NodeList-html.js b/dojo/NodeList-html.js
index 76281ee..e485a1d 100644
--- a/dojo/NodeList-html.js
+++ b/dojo/NodeList-html.js
@@ -1,21 +1,38 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.NodeList-html"]){
-dojo._hasResource["dojo.NodeList-html"]=true;
 dojo.provide("dojo.NodeList-html");
 dojo.require("dojo.html");
-dojo.extend(dojo.NodeList,{html:function(_1,_2){
-var _3=new dojo.html._ContentSetter(_2||{});
-this.forEach(function(_4){
-_3.node=_4;
-_3.set(_1);
-_3.tearDown();
+
+/*=====
+dojo["NodeList-html"] = {
+	// summary: Adds a chainable html method to dojo.query() / Nodelist instances for setting/replacing node content
+};
+=====*/
+
+dojo.extend(dojo.NodeList, {
+	html: function(content, /* Object? */params){
+		//	summary:
+		//		see `dojo.html.set()`. Set the content of all elements of this NodeList
+		//
+		// description: 
+		//		Based around `dojo.html.set()`, set the content of the Elements in a 
+		//		NodeList to the given content (string/node/nodelist), with optional arguments
+		//		to further tune the set content behavior.
+		//
+		//	example:
+		//	| dojo.query(".thingList").html("<li dojoType='dojo.dnd.Moveable'>1</li><li dojoType='dojo.dnd.Moveable'>2</li><li dojoType='dojo.dnd.Moveable'>3</li>",
+		//	| { 
+		//	| 	parseContent: true, 
+		//	| 	onBegin: function(){
+		//	| 		this.content = this.content.replace(/([0-9])/g, this.id + ": $1");
+		//	| 		this.inherited("onBegin", arguments);
+		//	| 	}
+		//	| }).removeClass("notdone").addClass("done");
+
+		var dhs = new dojo.html._ContentSetter(params || {});
+		this.forEach(function(elm){
+			dhs.node = elm; 
+			dhs.set(content);
+			dhs.tearDown();
+		});
+		return this; // dojo.NodeList
+	}
 });
-return this;
-}});
-}
diff --git a/dojo/NodeList-manipulate.js b/dojo/NodeList-manipulate.js
index ba22fa8..f0e4db1 100644
--- a/dojo/NodeList-manipulate.js
+++ b/dojo/NodeList-manipulate.js
@@ -1,212 +1,720 @@
-/*
-	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
-*/
+dojo.provide("dojo.NodeList-manipulate");
 
+/*=====
+dojo["NodeList-manipulate"] = {
+	// summary: Adds a chainable methods to dojo.query() / Nodelist instances for manipulating HTML
+	// and DOM nodes and their properties.
+};
+=====*/
+
+//TODO: add a way to parse for widgets in the injected markup?
 
-if(!dojo._hasResource["dojo.NodeList-manipulate"]){
-dojo._hasResource["dojo.NodeList-manipulate"]=true;
-dojo.provide("dojo.NodeList-manipulate");
 (function(){
-function _1(_2){
-var _3="",ch=_2.childNodes;
-for(var i=0,n;n=ch[i];i++){
-if(n.nodeType!=8){
-if(n.nodeType==1){
-_3+=_1(n);
-}else{
-_3+=n.nodeValue;
-}
-}
-}
-return _3;
-};
-function _4(_5){
-while(_5.childNodes[0]&&_5.childNodes[0].nodeType==1){
-_5=_5.childNodes[0];
-}
-return _5;
-};
-function _6(_7,_8){
-if(typeof _7=="string"){
-_7=dojo._toDom(_7,(_8&&_8.ownerDocument));
-if(_7.nodeType==11){
-_7=_7.childNodes[0];
-}
-}else{
-if(_7.nodeType==1&&_7.parentNode){
-_7=_7.cloneNode(false);
-}
-}
-return _7;
-};
-dojo.extend(dojo.NodeList,{_placeMultiple:function(_9,_a){
-var _b=typeof _9=="string"||_9.nodeType?dojo.query(_9):_9;
-var _c=[];
-for(var i=0;i<_b.length;i++){
-var _d=_b[i];
-var _e=this.length;
-for(var j=_e-1,_f;_f=this[j];j--){
-if(i>0){
-_f=this._cloneNode(_f);
-_c.unshift(_f);
-}
-if(j==_e-1){
-dojo.place(_f,_d,_a);
-}else{
-_d.parentNode.insertBefore(_f,_d);
-}
-_d=_f;
-}
-}
-if(_c.length){
-_c.unshift(0);
-_c.unshift(this.length-1);
-Array.prototype.splice.apply(this,_c);
-}
-return this;
-},innerHTML:function(_10){
-if(arguments.length){
-return this.addContent(_10,"only");
-}else{
-return this[0].innerHTML;
-}
-},text:function(_11){
-if(arguments.length){
-for(var i=0,_12;_12=this[i];i++){
-if(_12.nodeType==1){
-dojo.empty(_12);
-_12.appendChild(_12.ownerDocument.createTextNode(_11));
-}
-}
-return this;
-}else{
-var _13="";
-for(i=0;_12=this[i];i++){
-_13+=_1(_12);
-}
-return _13;
-}
-},val:function(_14){
-if(arguments.length){
-var _15=dojo.isArray(_14);
-for(var _16=0,_17;_17=this[_16];_16++){
-var _18=_17.nodeName.toUpperCase();
-var _19=_17.type;
-var _1a=_15?_14[_16]:_14;
-if(_18=="SELECT"){
-var _1b=_17.options;
-for(var i=0;i<_1b.length;i++){
-var opt=_1b[i];
-if(_17.multiple){
-opt.selected=(dojo.indexOf(_14,opt.value)!=-1);
-}else{
-opt.selected=(opt.value==_1a);
-}
-}
-}else{
-if(_19=="checkbox"||_19=="radio"){
-_17.checked=(_17.value==_1a);
-}else{
-_17.value=_1a;
-}
-}
-}
-return this;
-}else{
-_17=this[0];
-if(!_17||_17.nodeType!=1){
-return undefined;
-}
-_14=_17.value||"";
-if(_17.nodeName.toUpperCase()=="SELECT"&&_17.multiple){
-_14=[];
-_1b=_17.options;
-for(i=0;i<_1b.length;i++){
-opt=_1b[i];
-if(opt.selected){
-_14.push(opt.value);
-}
-}
-if(!_14.length){
-_14=null;
-}
-}
-return _14;
-}
-},append:function(_1c){
-return this.addContent(_1c,"last");
-},appendTo:function(_1d){
-return this._placeMultiple(_1d,"last");
-},prepend:function(_1e){
-return this.addContent(_1e,"first");
-},prependTo:function(_1f){
-return this._placeMultiple(_1f,"first");
-},after:function(_20){
-return this.addContent(_20,"after");
-},insertAfter:function(_21){
-return this._placeMultiple(_21,"after");
-},before:function(_22){
-return this.addContent(_22,"before");
-},insertBefore:function(_23){
-return this._placeMultiple(_23,"before");
-},remove:dojo.NodeList.prototype.orphan,wrap:function(_24){
-if(this[0]){
-_24=_6(_24,this[0]);
-for(var i=0,_25;_25=this[i];i++){
-var _26=this._cloneNode(_24);
-if(_25.parentNode){
-_25.parentNode.replaceChild(_26,_25);
-}
-var _27=_4(_26);
-_27.appendChild(_25);
-}
-}
-return this;
-},wrapAll:function(_28){
-if(this[0]){
-_28=_6(_28,this[0]);
-this[0].parentNode.replaceChild(_28,this[0]);
-var _29=_4(_28);
-for(var i=0,_2a;_2a=this[i];i++){
-_29.appendChild(_2a);
-}
-}
-return this;
-},wrapInner:function(_2b){
-if(this[0]){
-_2b=_6(_2b,this[0]);
-for(var i=0;i<this.length;i++){
-var _2c=this._cloneNode(_2b);
-this._wrap(dojo._toArray(this[i].childNodes),null,this._NodeListCtor).wrapAll(_2c);
-}
-}
-return this;
-},replaceWith:function(_2d){
-_2d=this._normalize(_2d,this[0]);
-for(var i=0,_2e;_2e=this[i];i++){
-this._place(_2d,_2e,"before",i>0);
-_2e.parentNode.removeChild(_2e);
-}
-return this;
-},replaceAll:function(_2f){
-var nl=dojo.query(_2f);
-var _30=this._normalize(this,this[0]);
-for(var i=0,_31;_31=nl[i];i++){
-this._place(_30,_31,"before",i>0);
-_31.parentNode.removeChild(_31);
-}
-return this;
-},clone:function(){
-var ary=[];
-for(var i=0;i<this.length;i++){
-ary.push(this._cloneNode(this[i]));
-}
-return this._wrap(ary,this,this._NodeListCtor);
-}});
-if(!dojo.NodeList.prototype.html){
-dojo.NodeList.prototype.html=dojo.NodeList.prototype.innerHTML;
-}
+	function getText(/*DOMNode*/node){
+		// summary:
+		// 		recursion method for text() to use. Gets text value for a node.
+		// description:
+		// 		Juse uses nodedValue so things like <br/> tags do not end up in
+		// 		the text as any sort of line return.
+		var text = "", ch = node.childNodes;
+		for(var i = 0, n; n = ch[i]; i++){
+			//Skip comments.
+			if(n.nodeType != 8){
+				if(n.nodeType == 1){
+					text += getText(n);
+				}else{
+					text += n.nodeValue;
+				}
+			}
+		}
+		return text;
+	}
+
+	function getWrapInsertion(/*DOMNode*/node){
+		// summary:
+		// 		finds the innermost element to use for wrap insertion.
+
+		//Make it easy, assume single nesting, no siblings.
+		while(node.childNodes[0] && node.childNodes[0].nodeType == 1){
+			node = node.childNodes[0];
+		}
+		return node; //DOMNode
+	}
+
+	function makeWrapNode(/*DOMNode||String*/html, /*DOMNode*/refNode){
+		// summary: 
+		// 		convert HTML into nodes if it is not already a node.
+		if(typeof html == "string"){
+			html = dojo._toDom(html, (refNode && refNode.ownerDocument));
+			if(html.nodeType == 11){
+				//DocumentFragment cannot handle cloneNode, so choose first child.
+				html = html.childNodes[0];
+			}
+		}else if(html.nodeType == 1 && html.parentNode){
+			//This element is already in the DOM clone it, but not its children.
+			html = html.cloneNode(false);
+		}
+		return html; /*DOMNode*/
+	}
+
+	dojo.extend(dojo.NodeList, {
+		_placeMultiple: function(/*String||Node||NodeList*/query, /*String*/position){
+			// summary:
+			// 		private method for inserting queried nodes into all nodes in this NodeList
+			// 		at different positions. Differs from NodeList.place because it will clone
+			// 		the nodes in this NodeList if the query matches more than one element.
+			var nl2 = typeof query == "string" || query.nodeType ? dojo.query(query) : query;
+			var toAdd = [];
+			for(var i = 0; i < nl2.length; i++){
+				//Go backwards in DOM to make dom insertions easier via insertBefore
+				var refNode = nl2[i];
+				var length = this.length;
+				for(var j = length - 1, item; item = this[j]; j--){
+					if(i > 0){
+						//Need to clone the item. This also means
+						//it needs to be added to the current NodeList
+						//so it can also be the target of other chaining operations.
+						item = this._cloneNode(item);
+						toAdd.unshift(item);
+					}
+					if(j == length - 1){
+						dojo.place(item, refNode, position);
+					}else{
+						refNode.parentNode.insertBefore(item, refNode);
+					}
+					refNode = item;
+				}
+			}
+
+			if(toAdd.length){
+				//Add the toAdd items to the current NodeList. Build up list of args
+				//to pass to splice.
+				toAdd.unshift(0);
+				toAdd.unshift(this.length - 1);
+				Array.prototype.splice.apply(this, toAdd);
+			}
+
+			return this; //dojo.NodeList
+		},
+
+		innerHTML: function(/*String?||DOMNode?|NodeList?*/value){
+			// summary:
+			// 		allows setting the innerHTML of each node in the NodeList,
+			// 		if there is a value passed in, otherwise, reads the innerHTML value of the first node.
+			// description:
+			// 		This method is simpler than the dojo.NodeList.html() method provided by
+			// 		`dojo.NodeList-html`. This method just does proper innerHTML insertion of HTML fragments,
+			// 		and it allows for the innerHTML to be read for the first node in the node list.
+			// 		Since dojo.NodeList-html already took the "html" name, this method is called
+			// 		"innerHTML". However, if dojo.NodeList-html has not been loaded yet, this
+			// 		module will define an "html" method that can be used instead. Be careful if you
+			// 		are working in an environment where it is possible that dojo.NodeList-html could
+			// 		have been loaded, since its definition of "html" will take precedence.
+			// 		The nodes represented by the value argument will be cloned if more than one
+			// 		node is in this NodeList. The nodes in this NodeList are returned in the "set"
+			// 		usage of this method, not the HTML that was inserted.
+			//	returns:
+			//		if no value is passed, the result is String, the innerHTML of the first node.
+			//		If a value is passed, the return is this dojo.NodeList
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div id="foo"></div>
+			//	|	<div id="bar"></div>
+			//		This code inserts <p>Hello World</p> into both divs:
+			//	|	dojo.query("div").innerHTML("<p>Hello World</p>");
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div id="foo"><p>Hello Mars</p></div>
+			//	|	<div id="bar"><p>Hello World</p></div>
+			//		This code returns "<p>Hello Mars</p>":
+			//	|	var message = dojo.query("div").innerHTML();
+			if(arguments.length){
+				return this.addContent(value, "only"); //dojo.NodeList
+			}else{
+				return this[0].innerHTML; //String
+			}
+		},
+
+		/*=====
+		html: function(value){
+			// summary:
+			//		see the information for "innerHTML". "html" is an alias for "innerHTML", but is
+			// 		only defined if dojo.NodeList-html has not been loaded.
+			// description:
+			// 		An alias for the "innerHTML" method, but only defined if there is not an existing
+			// 		"html" method on dojo.NodeList. Be careful if you are working in an environment
+			// 		where it is possible that dojo.NodeList-html could have been loaded, since its
+			// 		definition of "html" will take precedence. If you are not sure if dojo.NodeList-html
+			// 		could be loaded, use the "innerHTML" method.
+			//	value: String?||DOMNode?||NodeList?
+			//		optional. The HTML fragment to use as innerHTML. If value is not passed, then the innerHTML
+			// 		of the first element in this NodeList is returned.
+			//	returns:
+			//		if no value is passed, the result is String, the innerHTML of the first node.
+			//		If a value is passed, the return is this dojo.NodeList
+			return; // dojo.NodeList
+			return; // String
+		},
+		=====*/
+
+		text: function(/*String*/value){
+			// summary:
+			// 		allows setting the text value of each node in the NodeList,
+			// 		if there is a value passed in, otherwise, returns the text value for all the
+			// 		nodes in the NodeList in one string.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div id="foo"></div>
+			//	|	<div id="bar"></div>
+			//		This code inserts "Hello World" into both divs:
+			//	|	dojo.query("div").text("Hello World");
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div id="foo"><p>Hello Mars <span>today</span></p></div>
+			//	|	<div id="bar"><p>Hello World</p></div>
+			//		This code returns "Hello Mars today":
+			//	|	var message = dojo.query("div").text();
+			//	returns:
+			//		if no value is passed, the result is String, the text value of the first node.
+			//		If a value is passed, the return is this dojo.NodeList
+			if(arguments.length){
+				for(var i = 0, node; node = this[i]; i++){
+					if(node.nodeType == 1){
+						dojo.empty(node);
+						node.appendChild(node.ownerDocument.createTextNode(value));
+					}
+				}
+				return this; //dojo.NodeList
+			}else{
+				var result = "";
+				for(i = 0; node = this[i]; i++){
+					result += getText(node);
+				}
+				return result; //String
+			}
+		},
+
+		val: function(/*String||Array*/value){
+			// summary:
+			// 		If a value is passed, allows seting the value property of form elements in this
+			// 		NodeList, or properly selecting/checking the right value for radio/checkbox/select
+			// 		elements. If no value is passed, the value of the first node in this NodeList
+			// 		is returned.
+			//	returns:
+			//		if no value is passed, the result is String or an Array, for the value of the
+			//		first node.
+			//		If a value is passed, the return is this dojo.NodeList
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<input type="text" value="foo">
+			//	|	<select multiple>
+			//	|		<option value="red" selected>Red</option>
+			//	|		<option value="blue">Blue</option>
+			//	|		<option value="yellow" selected>Yellow</option>
+			//	|	</select>
+			//		This code gets and sets the values for the form fields above:
+			//	|	dojo.query('[type="text"]').val(); //gets value foo
+			//	|	dojo.query('[type="text"]').val("bar"); //sets the input's value to "bar"
+			// 	|	dojo.query("select").val() //gets array value ["red", "yellow"]
+			// 	|	dojo.query("select").val(["blue", "yellow"]) //Sets the blue and yellow options to selected.
+
+			//Special work for input elements.
+			if(arguments.length){
+				var isArray = dojo.isArray(value);
+				for(var index = 0, node; node = this[index]; index++){
+					var name = node.nodeName.toUpperCase();
+					var type = node.type;
+					var newValue = isArray ? value[index] : value;
+	
+					if(name == "SELECT"){
+						var opts = node.options;
+						for(var i = 0; i < opts.length; i++){
+							var opt = opts[i];
+							if(node.multiple){
+								opt.selected = (dojo.indexOf(value, opt.value) != -1);
+							}else{
+								opt.selected = (opt.value == newValue);
+							}
+						}
+					}else if(type == "checkbox" || type == "radio"){
+						node.checked = (node.value == newValue);
+					}else{
+						node.value = newValue;
+					}
+				}
+				return this; //dojo.NodeList
+			}else{
+				//node already declared above.
+				node = this[0];
+				if(!node || node.nodeType != 1){
+					return undefined;
+				}
+				value = node.value || "";
+				if(node.nodeName.toUpperCase() == "SELECT" && node.multiple){
+					//A multivalued selectbox. Do the pain.
+					value = [];
+					//opts declared above in if block.
+					opts = node.options;
+					//i declared above in if block;
+					for(i = 0; i < opts.length; i++){
+						//opt declared above in if block
+						opt = opts[i];
+						if(opt.selected){
+							value.push(opt.value);
+						}
+					}
+					if(!value.length){
+						value = null;
+					}
+				}
+				return value; //String||Array
+			}
+		},
+
+		append: function(/*String||DOMNode||NodeList*/content){
+			// summary:
+			// 		appends the content to every node in the NodeList.
+			// description:
+			// 		The content will be cloned if the length of NodeList
+			// 		is greater than 1. Only the DOM nodes are cloned, not
+			// 		any attached event handlers.
+			// returns:
+			//		dojo.NodeList, the nodes currently in this NodeList will be returned,
+			//		not the appended content.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div id="foo"><p>Hello Mars</p></div>
+			//	|	<div id="bar"><p>Hello World</p></div>
+			//		Running this code:
+			//	|	dojo.query("div").append("<span>append</span>");
+			//		Results in this DOM structure:
+			//	|	<div id="foo"><p>Hello Mars</p><span>append</span></div>
+			//	|	<div id="bar"><p>Hello World</p><span>append</span></div>
+			return this.addContent(content, "last"); //dojo.NodeList
+		},
+
+		appendTo: function(/*String*/query){
+			// summary:
+			// 		appends nodes in this NodeList to the nodes matched by
+			// 		the query passed to appendTo.
+			// description:
+			// 		The nodes in this NodeList will be cloned if the query
+			// 		matches more than one element. Only the DOM nodes are cloned, not
+			// 		any attached event handlers.
+			// returns:
+			//		dojo.NodeList, the nodes currently in this NodeList will be returned,
+			//		not the matched nodes from the query.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<span>append</span>
+			//	|	<p>Hello Mars</p>
+			//	|	<p>Hello World</p>
+			//		Running this code:
+			//	|	dojo.query("span").appendTo("p");
+			//		Results in this DOM structure:
+			//	|	<p>Hello Mars<span>append</span></p>
+			//	|	<p>Hello World<span>append</span></p>
+			return this._placeMultiple(query, "last"); //dojo.NodeList
+		},
+
+		prepend: function(/*String||DOMNode||NodeList*/content){
+			// summary:
+			// 		prepends the content to every node in the NodeList.
+			// description:
+			// 		The content will be cloned if the length of NodeList
+			// 		is greater than 1. Only the DOM nodes are cloned, not
+			// 		any attached event handlers.
+			// returns:
+			//		dojo.NodeList, the nodes currently in this NodeList will be returned,
+			//		not the appended content.
+			//		assume a DOM created by this markup:
+			//	|	<div id="foo"><p>Hello Mars</p></div>
+			//	|	<div id="bar"><p>Hello World</p></div>
+			//		Running this code:
+			//	|	dojo.query("div").prepend("<span>prepend</span>");
+			//		Results in this DOM structure:
+			//	|	<div id="foo"><span>prepend</span><p>Hello Mars</p></div>
+			//	|	<div id="bar"><span>prepend</span><p>Hello World</p></div>
+			return this.addContent(content, "first"); //dojo.NodeList
+		},
+
+		prependTo: function(/*String*/query){
+			// summary:
+			// 		prepends nodes in this NodeList to the nodes matched by
+			// 		the query passed to prependTo.
+			// description:
+			// 		The nodes in this NodeList will be cloned if the query
+			// 		matches more than one element. Only the DOM nodes are cloned, not
+			// 		any attached event handlers.
+			// returns:
+			//		dojo.NodeList, the nodes currently in this NodeList will be returned,
+			//		not the matched nodes from the query.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<span>prepend</span>
+			//	|	<p>Hello Mars</p>
+			//	|	<p>Hello World</p>
+			//		Running this code:
+			//	|	dojo.query("span").prependTo("p");
+			//		Results in this DOM structure:
+			//	|	<p><span>prepend</span>Hello Mars</p>
+			//	|	<p><span>prepend</span>Hello World</p>
+			return this._placeMultiple(query, "first"); //dojo.NodeList
+		},
+
+		after: function(/*String||Element||NodeList*/content){
+			// summary:
+			// 		Places the content after every node in the NodeList.
+			// description:
+			// 		The content will be cloned if the length of NodeList
+			// 		is greater than 1. Only the DOM nodes are cloned, not
+			// 		any attached event handlers.
+			// returns:
+			//		dojo.NodeList, the nodes currently in this NodeList will be returned,
+			//		not the appended content.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div id="foo"><p>Hello Mars</p></div>
+			//	|	<div id="bar"><p>Hello World</p></div>
+			//		Running this code:
+			//	|	dojo.query("div").after("<span>after</span>");
+			//		Results in this DOM structure:
+			//	|	<div id="foo"><p>Hello Mars</p></div><span>after</span>
+			//	|	<div id="bar"><p>Hello World</p></div><span>after</span>
+			return this.addContent(content, "after"); //dojo.NodeList
+		},
+
+		insertAfter: function(/*String*/query){
+			// summary:
+			// 		The nodes in this NodeList will be placed after the nodes
+			// 		matched by the query passed to insertAfter.
+			// description:
+			// 		The nodes in this NodeList will be cloned if the query
+			// 		matches more than one element. Only the DOM nodes are cloned, not
+			// 		any attached event handlers.
+			// returns:
+			//		dojo.NodeList, the nodes currently in this NodeList will be returned,
+			//		not the matched nodes from the query.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<span>after</span>
+			//	|	<p>Hello Mars</p>
+			//	|	<p>Hello World</p>
+			//		Running this code:
+			//	|	dojo.query("span").insertAfter("p");
+			//		Results in this DOM structure:
+			//	|	<p>Hello Mars</p><span>after</span>
+			//	|	<p>Hello World</p><span>after</span>
+			return this._placeMultiple(query, "after"); //dojo.NodeList
+		},
+
+		before: function(/*String||DOMNode||NodeList*/content){
+			// summary:
+			// 		Places the content before every node in the NodeList.
+			// description:
+			// 		The content will be cloned if the length of NodeList
+			// 		is greater than 1. Only the DOM nodes are cloned, not
+			// 		any attached event handlers.
+			// returns:
+			//		dojo.NodeList, the nodes currently in this NodeList will be returned,
+			//		not the appended content.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div id="foo"><p>Hello Mars</p></div>
+			//	|	<div id="bar"><p>Hello World</p></div>
+			//		Running this code:
+			//	|	dojo.query("div").before("<span>before</span>");
+			//		Results in this DOM structure:
+			//	|	<span>before</span><div id="foo"><p>Hello Mars</p></div>
+			//	|	<span>before</span><div id="bar"><p>Hello World</p></div>
+			return this.addContent(content, "before"); //dojo.NodeList
+		},
+
+		insertBefore: function(/*String*/query){
+			// summary:
+			// 		The nodes in this NodeList will be placed after the nodes
+			// 		matched by the query passed to insertAfter.
+			// description:
+			// 		The nodes in this NodeList will be cloned if the query
+			// 		matches more than one element. Only the DOM nodes are cloned, not
+			// 		any attached event handlers.
+			// returns:
+			//		dojo.NodeList, the nodes currently in this NodeList will be returned,
+			//		not the matched nodes from the query.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<span>before</span>
+			//	|	<p>Hello Mars</p>
+			//	|	<p>Hello World</p>
+			//		Running this code:
+			//	|	dojo.query("span").insertBefore("p");
+			//		Results in this DOM structure:
+			//	|	<span>before</span><p>Hello Mars</p>
+			//	|	<span>before</span><p>Hello World</p>
+			return this._placeMultiple(query, "before"); //dojo.NodeList
+		},
+
+		/*=====
+		remove: function(simpleFilter){
+			//	summary:
+			//		alias for dojo.NodeList's orphan method. Removes elements
+			// 		in this list that match the simple filter from their parents
+			// 		and returns them as a new NodeList.
+			//	simpleFilter: String
+			//		single-expression CSS rule. For example, ".thinger" or
+			//		"#someId[attrName='value']" but not "div > span". In short,
+			//		anything which does not invoke a descent to evaluate but
+			//		can instead be used to test a single node is acceptable.
+			//	returns:
+			//		dojo.NodeList
+			return; // dojo.NodeList
+		},
+		=====*/
+		remove: dojo.NodeList.prototype.orphan,
+
+		wrap: function(/*String||DOMNode*/html){
+			// summary:
+			// 		Wrap each node in the NodeList with html passed to wrap.
+			// description:
+			// 		html will be cloned if the NodeList has more than one
+			// 		element. Only DOM nodes are cloned, not any attached
+			// 		event handlers.
+			// returns:
+			//		dojo.NodeList, the nodes in the current NodeList will be returned,
+			//		not the nodes from html argument.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<b>one</b>
+			//	|	<b>two</b>
+			//		Running this code:
+			//	|	dojo.query("b").wrap("<div><span></span></div>");
+			//		Results in this DOM structure:
+			//	|	<div><span><b>one</b></span></div>
+			//	|	<div><span><b>two</b></span></div>
+			if(this[0]){
+				html = makeWrapNode(html, this[0]);
+
+				//Now cycle through the elements and do the insertion.
+				for(var i = 0, node; node = this[i]; i++){
+					//Always clone because if html is used to hold one of
+					//the "this" nodes, then on the clone of html it will contain
+					//that "this" node, and that would be bad.
+					var clone = this._cloneNode(html);
+					if(node.parentNode){
+						node.parentNode.replaceChild(clone, node);
+					}
+					//Find deepest element and insert old node in it.
+					var insertion = getWrapInsertion(clone);
+					insertion.appendChild(node);
+				}
+			}
+			return this; //dojo.NodeList
+		},
+
+		wrapAll: function(/*String||DOMNode*/html){
+			// summary:
+			// 		Insert html where the first node in this NodeList lives, then place all
+			// 		nodes in this NodeList as the child of the html.
+			// returns:
+			//		dojo.NodeList, the nodes in the current NodeList will be returned,
+			//		not the nodes from html argument.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div class="container">
+			// 	|		<div class="red">Red One</div>
+			// 	|		<div class="blue">Blue One</div>
+			// 	|		<div class="red">Red Two</div>
+			// 	|		<div class="blue">Blue Two</div>
+			//	|	</div>
+			//		Running this code:
+			//	|	dojo.query(".red").wrapAll('<div class="allRed"></div>');
+			//		Results in this DOM structure:
+			//	|	<div class="container">
+			// 	|		<div class="allRed">
+			// 	|			<div class="red">Red One</div>
+			// 	|			<div class="red">Red Two</div>
+			// 	|		</div>
+			// 	|		<div class="blue">Blue One</div>
+			// 	|		<div class="blue">Blue Two</div>
+			//	|	</div>
+			if(this[0]){
+				html = makeWrapNode(html, this[0]);
+
+				//Place the wrap HTML in place of the first node.
+				this[0].parentNode.replaceChild(html, this[0]);
+
+				//Now cycle through the elements and move them inside
+				//the wrap.
+				var insertion = getWrapInsertion(html);
+				for(var i = 0, node; node = this[i]; i++){
+					insertion.appendChild(node);
+				}
+			}
+			return this; //dojo.NodeList
+		},
+
+		wrapInner: function(/*String||DOMNode*/html){
+			// summary:
+			// 		For each node in the NodeList, wrap all its children with the passed in html.
+			// description:
+			// 		html will be cloned if the NodeList has more than one
+			// 		element. Only DOM nodes are cloned, not any attached
+			// 		event handlers.
+			// returns:
+			//		dojo.NodeList, the nodes in the current NodeList will be returned,
+			//		not the nodes from html argument.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div class="container">
+			// 	|		<div class="red">Red One</div>
+			// 	|		<div class="blue">Blue One</div>
+			// 	|		<div class="red">Red Two</div>
+			// 	|		<div class="blue">Blue Two</div>
+			//	|	</div>
+			//		Running this code:
+			//	|	dojo.query(".red").wrapInner('<span class="special"></span>');
+			//		Results in this DOM structure:
+			//	|	<div class="container">
+			// 	|		<div class="red"><span class="special">Red One</span></div>
+			// 	|		<div class="blue">Blue One</div>
+			// 	|		<div class="red"><span class="special">Red Two</span></div>
+			// 	|		<div class="blue">Blue Two</div>
+			//	|	</div>
+			if(this[0]){
+				html = makeWrapNode(html, this[0]);
+				for(var i = 0; i < this.length; i++){
+					//Always clone because if html is used to hold one of
+					//the "this" nodes, then on the clone of html it will contain
+					//that "this" node, and that would be bad.
+					var clone = this._cloneNode(html);
+					
+					//Need to convert the childNodes to an array since wrapAll modifies the
+					//DOM and can change the live childNodes NodeList.
+					this._wrap(dojo._toArray(this[i].childNodes), null, this._NodeListCtor).wrapAll(clone);
+				}
+			}
+			return this; //dojo.NodeList
+		},
+
+		replaceWith: function(/*String||DOMNode||NodeList*/content){
+			// summary:
+			// 		Replaces each node in ths NodeList with the content passed to replaceWith.
+			// description:
+			// 		The content will be cloned if the length of NodeList
+			// 		is greater than 1. Only the DOM nodes are cloned, not
+			// 		any attached event handlers.
+			// returns:
+			//		The nodes currently in this NodeList will be returned, not the replacing content.
+			//		Note that the returned nodes have been removed from the DOM.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div class="container">
+			// 	|		<div class="red">Red One</div>
+			// 	|		<div class="blue">Blue One</div>
+			// 	|		<div class="red">Red Two</div>
+			// 	|		<div class="blue">Blue Two</div>
+			//	|	</div>
+			//		Running this code:
+			//	|	dojo.query(".red").replaceWith('<div class="green">Green</div>');
+			//		Results in this DOM structure:
+			//	|	<div class="container">
+			// 	|		<div class="green">Green</div>
+			// 	|		<div class="blue">Blue One</div>
+			// 	|		<div class="green">Green</div>
+			// 	|		<div class="blue">Blue Two</div>
+			//	|	</div>
+			content = this._normalize(content, this[0]);
+			for(var i = 0, node; node = this[i]; i++){
+				this._place(content, node, "before", i > 0);
+				node.parentNode.removeChild(node);
+			}
+			return this; //dojo.NodeList
+		},
+
+		replaceAll: function(/*String*/query){
+			// summary:
+			// 		replaces nodes matched by the query passed to replaceAll with the nodes
+			// 		in this NodeList.
+			// description:
+			// 		The nodes in this NodeList will be cloned if the query
+			// 		matches more than one element. Only the DOM nodes are cloned, not
+			// 		any attached event handlers.
+			// returns:
+			//		The nodes currently in this NodeList will be returned, not the matched nodes
+			//		from the query. The nodes currently in this NodeLIst could have
+			//		been cloned, so the returned NodeList will include the cloned nodes.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div class="container">
+			// 	|		<div class="spacer">___</div>			
+			// 	|		<div class="red">Red One</div>
+			// 	|		<div class="spacer">___</div>			
+			// 	|		<div class="blue">Blue One</div>
+			// 	|		<div class="spacer">___</div>			
+			// 	|		<div class="red">Red Two</div>
+			// 	|		<div class="spacer">___</div>			
+			// 	|		<div class="blue">Blue Two</div>
+			//	|	</div>
+			//		Running this code:
+			//	|	dojo.query(".red").replaceAll(".blue");
+			//		Results in this DOM structure:
+			//	|	<div class="container">
+			// 	|		<div class="spacer">___</div>			
+			// 	|		<div class="spacer">___</div>			
+			// 	|		<div class="red">Red One</div>
+			// 	|		<div class="red">Red Two</div>
+			// 	|		<div class="spacer">___</div>			
+			// 	|		<div class="spacer">___</div>			
+			// 	|		<div class="red">Red One</div>
+			// 	|		<div class="red">Red Two</div>
+			//	|	</div>
+			var nl = dojo.query(query);
+			var content = this._normalize(this, this[0]);
+			for(var i = 0, node; node = nl[i]; i++){
+				this._place(content, node, "before", i > 0);
+				node.parentNode.removeChild(node);
+			}
+			return this; //dojo.NodeList
+		},
+
+		clone: function(){
+			// summary:
+			// 		Clones all the nodes in this NodeList and returns them as a new NodeList.
+			// description:
+			// 		Only the DOM nodes are cloned, not any attached event handlers.
+			// returns:
+			//		dojo.NodeList, a cloned set of the original nodes.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div class="container">
+			// 	|		<div class="red">Red One</div>
+			// 	|		<div class="blue">Blue One</div>
+			// 	|		<div class="red">Red Two</div>
+			// 	|		<div class="blue">Blue Two</div>
+			//	|	</div>
+			//		Running this code:
+			//	|	dojo.query(".red").clone().appendTo(".container");
+			//		Results in this DOM structure:
+			//	|	<div class="container">
+			// 	|		<div class="red">Red One</div>
+			// 	|		<div class="blue">Blue One</div>
+			// 	|		<div class="red">Red Two</div>
+			// 	|		<div class="blue">Blue Two</div>
+			// 	|		<div class="red">Red One</div>
+			// 	|		<div class="red">Red Two</div>
+			//	|	</div>
+
+			//TODO: need option to clone events?
+			var ary = [];
+			for(var i = 0; i < this.length; i++){
+				ary.push(this._cloneNode(this[i]));
+			}
+			return this._wrap(ary, this, this._NodeListCtor); //dojo.NodeList
+		}
+	});
+
+	//set up html method if one does not exist
+	if(!dojo.NodeList.prototype.html){
+		dojo.NodeList.prototype.html = dojo.NodeList.prototype.innerHTML;
+	}
 })();
-}
diff --git a/dojo/NodeList-traverse.js b/dojo/NodeList-traverse.js
index d2b367a..b14095f 100644
--- a/dojo/NodeList-traverse.js
+++ b/dojo/NodeList-traverse.js
@@ -1,131 +1,506 @@
-/*
-	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
-*/
+dojo.provide("dojo.NodeList-traverse");
 
+/*=====
+dojo["NodeList-traverse"] = {
+	// summary: Adds a chainable methods to dojo.query() / Nodelist instances for traversing the DOM
+};
+=====*/
 
-if(!dojo._hasResource["dojo.NodeList-traverse"]){
-dojo._hasResource["dojo.NodeList-traverse"]=true;
-dojo.provide("dojo.NodeList-traverse");
-dojo.extend(dojo.NodeList,{_buildArrayFromCallback:function(_1){
-var _2=[];
-for(var i=0;i<this.length;i++){
-var _3=_1.call(this[i],this[i],_2);
-if(_3){
-_2=_2.concat(_3);
-}
-}
-return _2;
-},_filterQueryResult:function(_4,_5){
-var _6=dojo.filter(_4,function(_7){
-return dojo.query(_5,_7.parentNode).indexOf(_7)!=-1;
-});
-var _8=this._wrap(_6);
-return _8;
-},_getUniqueAsNodeList:function(_9){
-var _a=[];
-for(var i=0,_b;_b=_9[i];i++){
-if(_b.nodeType==1&&dojo.indexOf(_a,_b)==-1){
-_a.push(_b);
-}
-}
-return this._wrap(_a,null,this._NodeListCtor);
-},_getUniqueNodeListWithParent:function(_c,_d){
-var _e=this._getUniqueAsNodeList(_c);
-_e=(_d?this._filterQueryResult(_e,_d):_e);
-return _e._stash(this);
-},_getRelatedUniqueNodes:function(_f,_10){
-return this._getUniqueNodeListWithParent(this._buildArrayFromCallback(_10),_f);
-},children:function(_11){
-return this._getRelatedUniqueNodes(_11,function(_12,ary){
-return dojo._toArray(_12.childNodes);
-});
-},closest:function(_13){
-var _14=this;
-return this._getRelatedUniqueNodes(_13,function(_15,ary){
-do{
-if(_14._filterQueryResult([_15],_13).length){
-return _15;
-}
-}while((_15=_15.parentNode)&&_15.nodeType==1);
-return null;
-});
-},parent:function(_16){
-return this._getRelatedUniqueNodes(_16,function(_17,ary){
-return _17.parentNode;
-});
-},parents:function(_18){
-return this._getRelatedUniqueNodes(_18,function(_19,ary){
-var _1a=[];
-while(_19.parentNode){
-_19=_19.parentNode;
-_1a.push(_19);
-}
-return _1a;
-});
-},siblings:function(_1b){
-return this._getRelatedUniqueNodes(_1b,function(_1c,ary){
-var _1d=[];
-var _1e=(_1c.parentNode&&_1c.parentNode.childNodes);
-for(var i=0;i<_1e.length;i++){
-if(_1e[i]!=_1c){
-_1d.push(_1e[i]);
-}
-}
-return _1d;
-});
-},next:function(_1f){
-return this._getRelatedUniqueNodes(_1f,function(_20,ary){
-var _21=_20.nextSibling;
-while(_21&&_21.nodeType!=1){
-_21=_21.nextSibling;
-}
-return _21;
-});
-},nextAll:function(_22){
-return this._getRelatedUniqueNodes(_22,function(_23,ary){
-var _24=[];
-var _25=_23;
-while((_25=_25.nextSibling)){
-if(_25.nodeType==1){
-_24.push(_25);
-}
-}
-return _24;
-});
-},prev:function(_26){
-return this._getRelatedUniqueNodes(_26,function(_27,ary){
-var _28=_27.previousSibling;
-while(_28&&_28.nodeType!=1){
-_28=_28.previousSibling;
-}
-return _28;
-});
-},prevAll:function(_29){
-return this._getRelatedUniqueNodes(_29,function(_2a,ary){
-var _2b=[];
-var _2c=_2a;
-while((_2c=_2c.previousSibling)){
-if(_2c.nodeType==1){
-_2b.push(_2c);
-}
-}
-return _2b;
-});
-},andSelf:function(){
-return this.concat(this._parent);
-},first:function(){
-return this._wrap(((this[0]&&[this[0]])||[]),this);
-},last:function(){
-return this._wrap((this.length?[this[this.length-1]]:[]),this);
-},even:function(){
-return this.filter(function(_2d,i){
-return i%2!=0;
-});
-},odd:function(){
-return this.filter(function(_2e,i){
-return i%2==0;
+dojo.extend(dojo.NodeList, {
+	_buildArrayFromCallback: function(/*Function*/callback){
+		// summary:
+		// 		builds a new array of possibly differing size based on the input list.
+		// 		Since the returned array is likely of different size than the input array,
+		// 		the array's map function cannot be used.
+		var ary = [];
+		for(var i = 0; i < this.length; i++){
+			var items = callback.call(this[i], this[i], ary);
+			if(items){
+				ary = ary.concat(items);
+			}
+		}
+		return ary;	
+	},
+
+	_filterQueryResult: function(nodeList, query){
+		// summmary: 
+		// 		Replacement for dojo._filterQueryResult that does a full
+		// 		query. Slower, but allows for more types of queries.
+		var filter = dojo.filter(nodeList, function(node){
+			return dojo.query(query, node.parentNode).indexOf(node) != -1;
+		});
+		var result = this._wrap(filter);
+		return result;
+	},
+
+	_getUniqueAsNodeList: function(nodes){
+		// summary:
+		// 		given a list of nodes, make sure only unique
+		// 		elements are returned as our NodeList object.
+		// 		Does not call _stash().
+		var ary = [];
+		//Using for loop for better speed.
+		for(var i = 0, node; node = nodes[i]; i++){
+			//Should be a faster way to do this. dojo.query has a private
+			//_zip function that may be inspirational, but there are pathways
+			//in query that force nozip?
+			if(node.nodeType == 1 && dojo.indexOf(ary, node) == -1){
+				ary.push(node);
+			}
+		}
+		return this._wrap(ary, null, this._NodeListCtor);	 //dojo.NodeList
+	},
+
+	_getUniqueNodeListWithParent: function(nodes, query){
+		// summary:
+		// 		gets unique element nodes, filters them further
+		// 		with an optional query and then calls _stash to track parent NodeList.
+		var ary = this._getUniqueAsNodeList(nodes);
+		ary = (query ? this._filterQueryResult(ary, query) : ary);
+		return ary._stash(this);  //dojo.NodeList
+	},
+
+	_getRelatedUniqueNodes: function(/*String?*/query, /*Function*/callback){
+		// summary:
+		// 		cycles over all the nodes and calls a callback
+		// 		to collect nodes for a possible inclusion in a result.
+		// 		The callback will get two args: callback(node, ary), 
+		// 		where ary is the array being used to collect the nodes.
+		return this._getUniqueNodeListWithParent(this._buildArrayFromCallback(callback), query);  //dojo.NodeList
+	},
+
+	children: function(/*String?*/query){
+		// summary:
+		// 		Returns all immediate child elements for nodes in this dojo.NodeList.
+		// 		Optionally takes a query to filter the child elements.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		// query:
+		//		a CSS selector.
+		// returns:
+		//		dojo.NodeList, all immediate child elements for the nodes in this dojo.NodeList.
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red">Red One</div>
+		// 	|		Some Text
+		// 	|		<div class="blue">Blue One</div>
+		// 	|		<div class="red">Red Two</div>
+		// 	|		<div class="blue">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".container").children();
+		//		returns the four divs that are children of the container div.
+		//		Running this code:
+		//	|	dojo.query(".container").children(".red");
+		//		returns the two divs that have the class "red".
+		return this._getRelatedUniqueNodes(query, function(node, ary){
+			return dojo._toArray(node.childNodes);
+		}); //dojo.NodeList
+	},
+
+	closest: function(/*String*/query){
+		// summary:
+		// 		Returns closest parent that matches query, including current node in this
+		// 		dojo.NodeList if it matches the query.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		//	query:
+		//		a CSS selector.
+		// returns:
+		//		dojo.NodeList, the closest parent that matches the query, including the current
+		//		node in this dojo.NodeList if it matches the query.
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red">Red One</div>
+		// 	|		Some Text
+		// 	|		<div class="blue">Blue One</div>
+		// 	|		<div class="red">Red Two</div>
+		// 	|		<div class="blue">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".red").closest(".container");
+		//		returns the div with class "container".
+		var self = this;
+		return this._getRelatedUniqueNodes(query, function(node, ary){
+			do{
+				if(self._filterQueryResult([node], query).length){
+					return node;
+				}
+			}while((node = node.parentNode) && node.nodeType == 1);
+			return null; //To make rhino strict checking happy.
+		}); //dojo.NodeList
+	},
+
+	parent: function(/*String?*/query){
+		// summary:
+		// 		Returns immediate parent elements for nodes in this dojo.NodeList.
+		// 		Optionally takes a query to filter the parent elements.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		//	query:
+		//		a CSS selector.
+		// returns:
+		//		dojo.NodeList, immediate parent elements for nodes in this dojo.NodeList.
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red">Red One</div>
+		// 	|		<div class="blue first"><span class="text">Blue One</span></div>
+		// 	|		<div class="red">Red Two</div>
+		// 	|		<div class="blue"><span class="text">Blue Two</span></div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".text").parent();
+		//		returns the two divs with class "blue".
+		//		Running this code:
+		//	|	dojo.query(".text").parent(".first");
+		//		returns the one div with class "blue" and "first".
+		return this._getRelatedUniqueNodes(query, function(node, ary){
+			return node.parentNode;
+		}); //dojo.NodeList
+	},
+
+	parents: function(/*String?*/query){
+		// summary:
+		// 		Returns all parent elements for nodes in this dojo.NodeList.
+		// 		Optionally takes a query to filter the child elements.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		//	query:
+		//		a CSS selector.
+		// returns:
+		//		dojo.NodeList, all parent elements for nodes in this dojo.NodeList.
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red">Red One</div>
+		// 	|		<div class="blue first"><span class="text">Blue One</span></div>
+		// 	|		<div class="red">Red Two</div>
+		// 	|		<div class="blue"><span class="text">Blue Two</span></div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".text").parents();
+		//		returns the two divs with class "blue", the div with class "container",
+		// 	|	the body element and the html element.
+		//		Running this code:
+		//	|	dojo.query(".text").parents(".container");
+		//		returns the one div with class "container".
+		return this._getRelatedUniqueNodes(query, function(node, ary){
+			var pary = []
+			while(node.parentNode){
+				node = node.parentNode;
+				pary.push(node);
+			}
+			return pary;
+		}); //dojo.NodeList
+	},
+
+	siblings: function(/*String?*/query){
+		// summary:
+		// 		Returns all sibling elements for nodes in this dojo.NodeList.
+		// 		Optionally takes a query to filter the sibling elements.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		//	query:
+		//		a CSS selector.
+		// returns:
+		//		dojo.NodeList, all sibling elements for nodes in this dojo.NodeList.
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red">Red One</div>
+		// 	|		Some Text
+		// 	|		<div class="blue first">Blue One</div>
+		// 	|		<div class="red">Red Two</div>
+		// 	|		<div class="blue">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".first").siblings();
+		//		returns the two divs with class "red" and the other div
+		// 	|	with class "blue" that does not have "first".
+		//		Running this code:
+		//	|	dojo.query(".first").siblings(".red");
+		//		returns the two div with class "red".
+		return this._getRelatedUniqueNodes(query, function(node, ary){
+			var pary = []
+			var nodes = (node.parentNode && node.parentNode.childNodes);
+			for(var i = 0; i < nodes.length; i++){
+				if(nodes[i] != node){
+					pary.push(nodes[i]);
+				}
+			}
+			return pary;
+		}); //dojo.NodeList
+	},
+
+	next: function(/*String?*/query){
+		// summary:
+		// 		Returns the next element for nodes in this dojo.NodeList.
+		// 		Optionally takes a query to filter the next elements.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		//	query:
+		//		a CSS selector.
+		// returns:
+		//		dojo.NodeList, the next element for nodes in this dojo.NodeList.
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red">Red One</div>
+		// 	|		Some Text
+		// 	|		<div class="blue first">Blue One</div>
+		// 	|		<div class="red">Red Two</div>
+		// 	|		<div class="blue last">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".first").next();
+		//		returns the div with class "red" and has innerHTML of "Red Two".
+		//		Running this code:
+		//	|	dojo.query(".last").next(".red");
+		//		does not return any elements.
+		return this._getRelatedUniqueNodes(query, function(node, ary){
+			var next = node.nextSibling;
+			while(next && next.nodeType != 1){
+				next = next.nextSibling;
+			}
+			return next;
+		}); //dojo.NodeList
+	},
+
+	nextAll: function(/*String?*/query){
+		// summary:
+		// 		Returns all sibling elements that come after the nodes in this dojo.NodeList.
+		// 		Optionally takes a query to filter the sibling elements.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		//	query:
+		//		a CSS selector.
+		// returns:
+		//		dojo.NodeList, all sibling elements that come after the nodes in this dojo.NodeList.
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red">Red One</div>
+		// 	|		Some Text
+		// 	|		<div class="blue first">Blue One</div>
+		// 	|		<div class="red next">Red Two</div>
+		// 	|		<div class="blue next">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".first").nextAll();
+		//		returns the two divs with class of "next".
+		//		Running this code:
+		//	|	dojo.query(".first").nextAll(".red");
+		//		returns the one div with class "red" and innerHTML "Red Two".
+		return this._getRelatedUniqueNodes(query, function(node, ary){
+			var pary = []
+			var next = node;
+			while((next = next.nextSibling)){
+				if(next.nodeType == 1){
+					pary.push(next);
+				}
+			}
+			return pary;
+		}); //dojo.NodeList
+	},
+
+	prev: function(/*String?*/query){
+		// summary:
+		// 		Returns the previous element for nodes in this dojo.NodeList.
+		// 		Optionally takes a query to filter the previous elements.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		//	query:
+		//		a CSS selector.
+		// returns:
+		//		dojo.NodeList, the previous element for nodes in this dojo.NodeList.
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red">Red One</div>
+		// 	|		Some Text
+		// 	|		<div class="blue first">Blue One</div>
+		// 	|		<div class="red">Red Two</div>
+		// 	|		<div class="blue">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".first").prev();
+		//		returns the div with class "red" and has innerHTML of "Red One".
+		//		Running this code:
+		//	|	dojo.query(".first").prev(".blue");
+		//		does not return any elements.
+		return this._getRelatedUniqueNodes(query, function(node, ary){
+			var prev = node.previousSibling;
+			while(prev && prev.nodeType != 1){
+				prev = prev.previousSibling;
+			}
+			return prev;
+		}); //dojo.NodeList
+	},
+
+	prevAll: function(/*String?*/query){
+		// summary:
+		// 		Returns all sibling elements that come before the nodes in this dojo.NodeList.
+		// 		Optionally takes a query to filter the sibling elements.
+		// description:
+		// 		The returned nodes will be in reverse DOM order -- the first node in the list will
+		// 		be the node closest to the original node/NodeList.
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		//	query:
+		//		a CSS selector.
+		// returns:
+		//		dojo.NodeList, all sibling elements that come before the nodes in this dojo.NodeList.
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red prev">Red One</div>
+		// 	|		Some Text
+		// 	|		<div class="blue prev">Blue One</div>
+		// 	|		<div class="red second">Red Two</div>
+		// 	|		<div class="blue">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".second").prevAll();
+		//		returns the two divs with class of "prev".
+		//		Running this code:
+		//	|	dojo.query(".first").prevAll(".red");
+		//		returns the one div with class "red prev" and innerHTML "Red One".
+		return this._getRelatedUniqueNodes(query, function(node, ary){
+			var pary = []
+			var prev = node;
+			while((prev = prev.previousSibling)){
+				if(prev.nodeType == 1){
+					pary.push(prev);
+				}
+			}
+			return pary;
+		}); //dojo.NodeList
+	},
+
+	andSelf: function(){
+		// summary:
+		// 		Adds the nodes from the previous dojo.NodeList to the current dojo.NodeList.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		// returns:
+		//		dojo.NodeList
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red prev">Red One</div>
+		// 	|		Some Text
+		// 	|		<div class="blue prev">Blue One</div>
+		// 	|		<div class="red second">Red Two</div>
+		// 	|		<div class="blue">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".second").prevAll().andSelf();
+		//		returns the two divs with class of "prev", as well as the div with class "second".
+		return this.concat(this._parent);
+	},
+
+	//Alternate methods for the :first/:last/:even/:odd pseudos.
+	first: function(){
+		// summary:
+		// 		Returns the first node in this dojo.NodeList as a dojo.NodeList.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		// returns:
+		//		dojo.NodeList, with the first node in this dojo.NodeList
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red">Red One</div>
+		// 	|		<div class="blue first">Blue One</div>
+		// 	|		<div class="red">Red Two</div>
+		// 	|		<div class="blue last">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".blue").first();
+		//		returns the div with class "blue" and "first".
+		return this._wrap(((this[0] && [this[0]]) || []), this); //dojo.NodeList
+	},
+
+	last: function(){
+		// summary:
+		// 		Returns the last node in this dojo.NodeList as a dojo.NodeList.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		// returns:
+		//		dojo.NodeList, with the last node in this dojo.NodeList
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="red">Red One</div>
+		// 	|		<div class="blue first">Blue One</div>
+		// 	|		<div class="red">Red Two</div>
+		// 	|		<div class="blue last">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".blue").last();
+		//		returns the last div with class "blue", 
+		return this._wrap((this.length ? [this[this.length - 1]] : []), this); //dojo.NodeList
+	},
+
+	even: function(){
+		// summary:
+		// 		Returns the even nodes in this dojo.NodeList as a dojo.NodeList.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		// returns:
+		//		dojo.NodeList, with the even nodes in this dojo.NodeList
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="interior red">Red One</div>
+		// 	|		<div class="interior blue">Blue One</div>
+		// 	|		<div class="interior red">Red Two</div>
+		// 	|		<div class="interior blue">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".interior").even();
+		//		returns the two divs with class "blue"
+		return this.filter(function(item, i){
+			return i % 2 != 0;
+		}); //dojo.NodeList
+	},
+
+	odd: function(){
+		// summary:
+		// 		Returns the odd nodes in this dojo.NodeList as a dojo.NodeList.
+		// description:
+		// 		.end() can be used on the returned dojo.NodeList to get back to the
+		// 		original dojo.NodeList.
+		// returns:
+		//		dojo.NodeList, with the odd nodes in this dojo.NodeList
+		//	example:
+		//		assume a DOM created by this markup:
+		//	|	<div class="container">
+		// 	|		<div class="interior red">Red One</div>
+		// 	|		<div class="interior blue">Blue One</div>
+		// 	|		<div class="interior red">Red Two</div>
+		// 	|		<div class="interior blue">Blue Two</div>
+		//	|	</div>
+		//		Running this code:
+		//	|	dojo.query(".interior").odd();
+		//		returns the two divs with class "red"
+		return this.filter(function(item, i){
+			return i % 2 == 0;
+		}); //dojo.NodeList
+	}
 });
-}});
-}
diff --git a/dojo/OpenAjax.js b/dojo/OpenAjax.js
index 60d18aa..32cf358 100644
--- a/dojo/OpenAjax.js
+++ b/dojo/OpenAjax.js
@@ -1,155 +1,194 @@
-/*
-	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
-*/
-
+/*******************************************************************************
+ * OpenAjax.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-2007 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(){
-var t=true;
-var f=false;
-var g=window;
-var _1;
-var _2="org.openajax.hub.";
-var h={};
-this.hub=h;
-h.implementer="http://openajax.org";
-h.implVersion="0.6";
-h.specVersion="0.6";
-h.implExtraData={};
-var _1={};
-h.libraries=_1;
-h.registerLibrary=function(_3,_4,_5,_6){
-_1[_3]={prefix:_3,namespaceURI:_4,version:_5,extraData:_6};
-this.publish(_2+"registerLibrary",_1[_3]);
-};
-h.unregisterLibrary=function(_7){
-this.publish(_2+"unregisterLibrary",_1[_7]);
-delete _1[_7];
-};
-h._subscriptions={c:{},s:[]};
-h._cleanup=[];
-h._subIndex=0;
-h._pubDepth=0;
-h.subscribe=function(_8,_9,_a,_b,_c){
-if(!_a){
-_a=window;
-}
-var _d=_8+"."+this._subIndex;
-var _e={scope:_a,cb:_9,fcb:_c,data:_b,sid:this._subIndex++,hdl:_d};
-var _f=_8.split(".");
-this._subscribe(this._subscriptions,_f,0,_e);
-return _d;
-};
-h.publish=function(_10,_11){
-var _12=_10.split(".");
-this._pubDepth++;
-this._publish(this._subscriptions,_12,0,_10,_11);
-this._pubDepth--;
-if((this._cleanup.length>0)&&(this._pubDepth==0)){
-for(var i=0;i<this._cleanup.length;i++){
-this.unsubscribe(this._cleanup[i].hdl);
-}
-delete (this._cleanup);
-this._cleanup=[];
-}
-};
-h.unsubscribe=function(sub){
-var _13=sub.split(".");
-var sid=_13.pop();
-this._unsubscribe(this._subscriptions,_13,0,sid);
-};
-h._subscribe=function(_14,_15,_16,sub){
-var _17=_15[_16];
-if(_16==_15.length){
-_14.s.push(sub);
-}else{
-if(typeof _14.c=="undefined"){
-_14.c={};
-}
-if(typeof _14.c[_17]=="undefined"){
-_14.c[_17]={c:{},s:[]};
-this._subscribe(_14.c[_17],_15,_16+1,sub);
-}else{
-this._subscribe(_14.c[_17],_15,_16+1,sub);
-}
-}
-};
-h._publish=function(_18,_19,_1a,_1b,msg){
-if(typeof _18!="undefined"){
-var _1c;
-if(_1a==_19.length){
-_1c=_18;
-}else{
-this._publish(_18.c[_19[_1a]],_19,_1a+1,_1b,msg);
-this._publish(_18.c["*"],_19,_1a+1,_1b,msg);
-_1c=_18.c["**"];
-}
-if(typeof _1c!="undefined"){
-var _1d=_1c.s;
-var max=_1d.length;
-for(var i=0;i<max;i++){
-if(_1d[i].cb){
-var sc=_1d[i].scope;
-var cb=_1d[i].cb;
-var fcb=_1d[i].fcb;
-var d=_1d[i].data;
-if(typeof cb=="string"){
-cb=sc[cb];
-}
-if(typeof fcb=="string"){
-fcb=sc[fcb];
-}
-if((!fcb)||(fcb.call(sc,_1b,msg,d))){
-cb.call(sc,_1b,msg,d);
-}
-}
-}
-}
-}
-};
-h._unsubscribe=function(_1e,_1f,_20,sid){
-if(typeof _1e!="undefined"){
-if(_20<_1f.length){
-var _21=_1e.c[_1f[_20]];
-this._unsubscribe(_21,_1f,_20+1,sid);
-if(_21.s.length==0){
-for(var x in _21.c){
-return;
-}
-delete _1e.c[_1f[_20]];
-}
-return;
-}else{
-var _22=_1e.s;
-var max=_22.length;
-for(var i=0;i<max;i++){
-if(sid==_22[i].sid){
-if(this._pubDepth>0){
-_22[i].cb=null;
-this._cleanup.push(_22[i]);
-}else{
-_22.splice(i,1);
-}
-return;
-}
-}
-}
-}
-};
-h.reinit=function(){
-for(var lib in OpenAjax.hub.libraries){
-delete OpenAjax.hub.libraries[lib];
-}
-OpenAjax.hub.registerLibrary("OpenAjax","http://openajax.org/hub","0.6",{});
-delete OpenAjax._subscriptions;
-OpenAjax._subscriptions={c:{},s:[]};
-delete OpenAjax._cleanup;
-OpenAjax._cleanup=[];
-OpenAjax._subIndex=0;
-OpenAjax._pubDepth=0;
-};
-};
-OpenAjax.hub.registerLibrary("OpenAjax","http://openajax.org/hub","0.6",{});
+	OpenAjax = new function(){
+		// summary: the OpenAjax hub
+		// description: see http://www.openajax.org/member/wiki/OpenAjax_Hub_Specification
+
+		var t = true;
+		var f = false;
+		var g = window;
+		var libs;
+		var ooh = "org.openajax.hub.";
+
+		var h = {};
+		this.hub = h;
+		h.implementer = "http://openajax.org";
+		h.implVersion = "0.6";
+		h.specVersion = "0.6";
+		h.implExtraData = {};
+		var libs = {};
+		h.libraries = libs;
+
+		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];
+		}
+
+		h._subscriptions = { c:{}, s:[] };
+		h._cleanup = [];
+		h._subIndex = 0;
+		h._pubDepth = 0;
+
+		h.subscribe = function(name, callback, scope, subscriberData, filter){
+			if(!scope){
+				scope = window;
+			}
+			var handle = name + "." + this._subIndex;
+			var sub = { scope: scope, cb: callback, fcb: filter, data: subscriberData, sid: this._subIndex++, hdl: handle };
+			var path = name.split(".");
+	 		this._subscribe(this._subscriptions, path, 0, sub);
+			return handle;
+		}
+
+		h.publish = function(name, message){
+			var path = name.split(".");
+			this._pubDepth++;
+			this._publish(this._subscriptions, path, 0, name, message);
+			this._pubDepth--;
+			if((this._cleanup.length > 0) && (this._pubDepth == 0)){
+				for(var i = 0; i < this._cleanup.length; i++){ 
+					this.unsubscribe(this._cleanup[i].hdl);
+				}
+				delete(this._cleanup);
+				this._cleanup = [];
+			}
+		}
+
+		h.unsubscribe = function(sub){
+			var path = sub.split(".");
+			var sid = path.pop();
+			this._unsubscribe(this._subscriptions, path, 0, sid);
+		}
+		
+		h._subscribe = function(tree, path, index, sub){
+			var token = path[index];
+			if(index == path.length){
+				tree.s.push(sub);
+			}else{ 
+				if(typeof tree.c == "undefined"){
+					 tree.c = {};
+				}
+				if(typeof tree.c[token] == "undefined"){
+					tree.c[token] = { c: {}, s: [] }; 
+					this._subscribe(tree.c[token], path, index + 1, sub);
+				}else{
+					this._subscribe( tree.c[token], path, index + 1, sub);
+				}
+			}
+		}
+
+		h._publish = function(tree, path, index, name, msg){
+			if(typeof tree != "undefined"){
+				var node;
+				if(index == path.length) {
+					node = tree;
+				}else{
+					this._publish(tree.c[path[index]], path, index + 1, name, msg);
+					this._publish(tree.c["*"], path, index + 1, name, msg);			
+					node = tree.c["**"];
+				}
+				if(typeof node != "undefined"){
+					var callbacks = node.s;
+					var max = callbacks.length;
+					for(var i = 0; i < max; i++){
+						if(callbacks[i].cb){
+							var sc = callbacks[i].scope;
+							var cb = callbacks[i].cb;
+							var fcb = callbacks[i].fcb;
+							var d = callbacks[i].data;
+							if(typeof cb == "string"){
+								// get a function object
+								cb = sc[cb];
+							}
+							if(typeof fcb == "string"){
+								// get a function object
+								fcb = sc[fcb];
+							}
+							if((!fcb) || 
+							   (fcb.call(sc, name, msg, d))) {
+								cb.call(sc, name, msg, d);
+							}
+						}
+					}
+				}
+			}
+		}
+			
+		h._unsubscribe = function(tree, path, index, sid) {
+			if(typeof tree != "undefined") {
+				if(index < path.length) {
+					var childNode = tree.c[path[index]];
+					this._unsubscribe(childNode, path, index + 1, sid);
+					if(childNode.s.length == 0) {
+						for(var x in childNode.c) 
+					 		return;		
+						delete tree.c[path[index]];	
+					}
+					return;
+				}
+				else {
+					var callbacks = tree.s;
+					var max = callbacks.length;
+					for(var i = 0; i < max; i++) 
+						if(sid == callbacks[i].sid) {
+							if(this._pubDepth > 0) {
+								callbacks[i].cb = null;	
+								this._cleanup.push(callbacks[i]);						
+							}
+							else
+								callbacks.splice(i, 1);
+							return; 	
+						}
+				}
+			}
+		}
+		// The following function is provided for automatic testing purposes.
+		// It is not expected to be deployed in run-time OpenAjax Hub implementations.
+		h.reinit = function()
+		{
+			for (var lib in OpenAjax.hub.libraries) {
+				delete OpenAjax.hub.libraries[lib];
+			}
+			OpenAjax.hub.registerLibrary("OpenAjax", "http://openajax.org/hub", "0.6", {});
+
+			delete OpenAjax._subscriptions;
+			OpenAjax._subscriptions = {c:{},s:[]};
+			delete OpenAjax._cleanup;
+			OpenAjax._cleanup = [];
+			OpenAjax._subIndex = 0;
+			OpenAjax._pubDepth = 0;
+		}
+	};
+	// Register the OpenAjax Hub itself as a library.
+	OpenAjax.hub.registerLibrary("OpenAjax", "http://openajax.org/hub", "0.6", {});
+
 }
diff --git a/dojo/Stateful.js b/dojo/Stateful.js
new file mode 100644
index 0000000..e213490
--- /dev/null
+++ b/dojo/Stateful.js
@@ -0,0 +1,123 @@
+dojo.provide("dojo.Stateful");
+
+dojo.declare("dojo.Stateful", null, {
+	// summary:
+	//		Base class for objects that provide named properties with optional getter/setter
+	//		control and the ability to watch for property changes
+	// example:
+	//	|	var obj = new dojo.Stateful();
+	//	|	obj.watch("foo", function(){
+	//	|		console.log("foo changed to " + this.get("foo"));
+	//	|	});
+	//	|	obj.set("foo","bar");
+	postscript: function(mixin){
+		if(mixin){
+			dojo.mixin(this, mixin);
+		}
+	},
+	
+	get: function(/*String*/name){
+		// summary:
+		//		Get a property on a Stateful instance.
+		//	name:
+		//		The property to get.
+		// description:
+		//		Get a named property on a Stateful object. The property may
+		//		potentially be retrieved via a getter method in subclasses. In the base class
+		// 		this just retrieves the object's property. 
+		// 		For example:
+		//	|	stateful = new dojo.Stateful({foo: 3});
+		//	|	stateful.get("foo") // returns 3
+		//	|	stateful.foo // returns 3
+		
+		return this[name];
+	},
+	set: function(/*String*/name, /*Object*/value){
+		// summary:
+		//		Set a property on a Stateful instance
+		//	name:
+		//		The property to set. 
+		//	value:
+		//		The value to set in the property.
+		// description:
+		//		Sets named properties on a stateful object and notifies any watchers of 
+		// 		the property. A programmatic setter may be defined in subclasses.
+		// 		For example:
+		//	|	stateful = new dojo.Stateful();
+		//	|	stateful.watch(function(name, oldValue, value){
+		//	|		// this will be called on the set below
+		//	|	}
+		//	|	stateful.set(foo, 5);
+		//
+		//	set() may also be called with a hash of name/value pairs, ex:
+		//	|	myObj.set({
+		//	|		foo: "Howdy",
+		//	|		bar: 3
+		//	|	})
+		//	This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
+		if(typeof name === "object"){
+			for(var x in name){
+				this.set(x, name[x]); 
+			}
+			return this;
+		}
+		var oldValue = this[name];
+		this[name] = value;
+		if(this._watchCallbacks){
+			this._watchCallbacks(name, oldValue, value);
+		}
+		return this;
+	},
+	watch: function(/*String?*/name, /*Function*/callback){
+		// summary:
+		//		Watches a property for changes
+		//	name:
+		//		Indicates the property to watch. This is optional (the callback may be the 
+		// 		only parameter), and if omitted, all the properties will be watched
+		// returns:
+		//		An object handle for the watch. The unwatch method of this object 
+		// 		can be used to discontinue watching this property:
+		//		|	var watchHandle = obj.watch("foo", callback);
+		//		|	watchHandle.unwatch(); // callback won't be called now
+		//	callback:
+		//		The function to execute when the property changes. This will be called after
+		//		the property has been changed. The callback will be called with the |this|
+		//		set to the instance, the first argument as the name of the property, the 
+		// 		second argument as the old value and the third argument as the new value.
+		
+		var callbacks = this._watchCallbacks;
+		if(!callbacks){
+			var self = this;
+			callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
+				var notify = function(propertyCallbacks){
+					for(var i = 0, l = propertyCallbacks && propertyCallbacks.length; i < l; i++){
+						try{
+							propertyCallbacks[i].call(self, name, oldValue, value);
+						}catch(e){
+							console.error(e);
+						}
+					}
+				};
+				notify(callbacks[name]);
+				if(!ignoreCatchall){
+					notify(callbacks["*"]); // the catch-all
+				}
+			}; // we use a function instead of an object so it will be ignored by JSON conversion
+		}
+		if(!callback && typeof name === "function"){
+			callback = name;
+			name = "*";
+		}
+		var propertyCallbacks = callbacks[name];
+		if(typeof propertyCallbacks !== "object"){
+			propertyCallbacks = callbacks[name] = [];
+		}
+		propertyCallbacks.push(callback);
+		return {
+			unwatch: function(){
+				propertyCallbacks.splice(dojo.indexOf(propertyCallbacks, callback), 1);
+			}
+		};
+	}
+	
+});
\ No newline at end of file
diff --git a/dojo/_base.js b/dojo/_base.js
index 9fff822..8219259 100644
--- a/dojo/_base.js
+++ b/dojo/_base.js
@@ -1,19 +1,9 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base"]){
-dojo._hasResource["dojo._base"]=true;
 dojo.provide("dojo._base");
 dojo.require("dojo._base.lang");
+dojo.require("dojo._base.array");
 dojo.require("dojo._base.declare");
 dojo.require("dojo._base.connect");
 dojo.require("dojo._base.Deferred");
 dojo.require("dojo._base.json");
-dojo.require("dojo._base.array");
 dojo.require("dojo._base.Color");
-dojo.requireIf(dojo.isBrowser,"dojo._base.browser");
-}
+dojo.requireIf(dojo.isBrowser, "dojo._base.browser");
diff --git a/dojo/_base/Color.js b/dojo/_base/Color.js
index 8882137..7509f16 100644
--- a/dojo/_base/Color.js
+++ b/dojo/_base/Color.js
@@ -1,102 +1,216 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.Color"]){
-dojo._hasResource["dojo._base.Color"]=true;
 dojo.provide("dojo._base.Color");
 dojo.require("dojo._base.array");
 dojo.require("dojo._base.lang");
+
 (function(){
-var d=dojo;
-dojo.Color=function(_1){
-if(_1){
-this.setColor(_1);
-}
-};
-dojo.Color.named={black:[0,0,0],silver:[192,192,192],gray:[128,128,128],white:[255,255,255],maroon:[128,0,0],red:[255,0,0],purple:[128,0,128],fuchsia:[255,0,255],green:[0,128,0],lime:[0,255,0],olive:[128,128,0],yellow:[255,255,0],navy:[0,0,128],blue:[0,0,255],teal:[0,128,128],aqua:[0,255,255],transparent:d.config.transparentColor||[255,255,255]};
-dojo.extend(dojo.Color,{r:255,g:255,b:255,a:1,_set:function(r,g,b,a){
-var t=this;
-t.r=r;
-t.g=g;
-t.b=b;
-t.a=a;
-},setColor:function(_2){
-if(d.isString(_2)){
-d.colorFromString(_2,this);
-}else{
-if(d.isArray(_2)){
-d.colorFromArray(_2,this);
-}else{
-this._set(_2.r,_2.g,_2.b,_2.a);
-if(!(_2 instanceof d.Color)){
-this.sanitize();
-}
-}
-}
-return this;
-},sanitize:function(){
-return this;
-},toRgb:function(){
-var t=this;
-return [t.r,t.g,t.b];
-},toRgba:function(){
-var t=this;
-return [t.r,t.g,t.b,t.a];
-},toHex:function(){
-var _3=d.map(["r","g","b"],function(x){
-var s=this[x].toString(16);
-return s.length<2?"0"+s:s;
-},this);
-return "#"+_3.join("");
-},toCss:function(_4){
-var t=this,_5=t.r+", "+t.g+", "+t.b;
-return (_4?"rgba("+_5+", "+t.a:"rgb("+_5)+")";
-},toString:function(){
-return this.toCss(true);
-}});
-dojo.blendColors=function(_6,_7,_8,_9){
-var t=_9||new d.Color();
-d.forEach(["r","g","b","a"],function(x){
-t[x]=_6[x]+(_7[x]-_6[x])*_8;
-if(x!="a"){
-t[x]=Math.round(t[x]);
-}
-});
-return t.sanitize();
-};
-dojo.colorFromRgb=function(_a,_b){
-var m=_a.toLowerCase().match(/^rgba?\(([\s\.,0-9]+)\)/);
-return m&&dojo.colorFromArray(m[1].split(/\s*,\s*/),_b);
-};
-dojo.colorFromHex=function(_c,_d){
-var t=_d||new d.Color(),_e=(_c.length==4)?4:8,_f=(1<<_e)-1;
-_c=Number("0x"+_c.substr(1));
-if(isNaN(_c)){
-return null;
-}
-d.forEach(["b","g","r"],function(x){
-var c=_c&_f;
-_c>>=_e;
-t[x]=_e==4?17*c:c;
-});
-t.a=1;
-return t;
-};
-dojo.colorFromArray=function(a,obj){
-var t=obj||new d.Color();
-t._set(Number(a[0]),Number(a[1]),Number(a[2]),Number(a[3]));
-if(isNaN(t.a)){
-t.a=1;
-}
-return t.sanitize();
-};
-dojo.colorFromString=function(str,obj){
-var a=d.Color.named[str];
-return a&&d.colorFromArray(a,obj)||d.colorFromRgb(str,obj)||d.colorFromHex(str,obj);
-};
+
+	var d = dojo;
+
+	dojo.Color = function(/*Array|String|Object*/ color){
+		// summary:
+		//	 	Takes a named string, hex string, array of rgb or rgba values,
+		//	 	an object with r, g, b, and a properties, or another `dojo.Color` object
+		//	 	and creates a new Color instance to work from.
+		//
+		// example:
+		//		Work with a Color instance:
+		//	 | var c = new dojo.Color();
+		//	 | c.setColor([0,0,0]); // black
+		//	 | var hex = c.toHex(); // #000000
+		//
+		// example:
+		//		Work with a node's color:
+		//	 | var color = dojo.style("someNode", "backgroundColor");
+		//	 | var n = new dojo.Color(color);
+		//	 | // adjust the color some
+		//	 | n.r *= .5;
+		//	 | console.log(n.toString()); // rgb(128, 255, 255);
+		if(color){ this.setColor(color); }
+	};
+
+	// FIXME:
+	// 	there's got to be a more space-efficient way to encode or discover
+	// 	these!!  Use hex?
+	dojo.Color.named = {
+		black:      [0,0,0],
+		silver:     [192,192,192],
+		gray:       [128,128,128],
+		white:      [255,255,255],
+		maroon:		[128,0,0],
+		red:        [255,0,0],
+		purple:		[128,0,128],
+		fuchsia:	[255,0,255],
+		green:	    [0,128,0],
+		lime:	    [0,255,0],
+		olive:		[128,128,0],
+		yellow:		[255,255,0],
+		navy:       [0,0,128],
+		blue:       [0,0,255],
+		teal:		[0,128,128],
+		aqua:		[0,255,255],
+		transparent: d.config.transparentColor || [255,255,255]
+	};
+
+	dojo.extend(dojo.Color, {
+		r: 255, g: 255, b: 255, a: 1,
+		_set: function(r, g, b, a){
+			var t = this; t.r = r; t.g = g; t.b = b; t.a = a;
+		},
+		setColor: function(/*Array|String|Object*/ color){
+			// summary:
+			//		Takes a named string, hex string, array of rgb or rgba values,
+			//		an object with r, g, b, and a properties, or another `dojo.Color` object
+			//		and sets this color instance to that value.
+			//
+			// example:
+			//	|	var c = new dojo.Color(); // no color
+			//	|	c.setColor("#ededed"); // greyish
+			if(d.isString(color)){
+				d.colorFromString(color, this);
+			}else if(d.isArray(color)){
+				d.colorFromArray(color, this);
+			}else{
+				this._set(color.r, color.g, color.b, color.a);
+				if(!(color instanceof d.Color)){ this.sanitize(); }
+			}
+			return this;	// dojo.Color
+		},
+		sanitize: function(){
+			// summary:
+			//		Ensures the object has correct attributes
+			// description:
+			//		the default implementation does nothing, include dojo.colors to
+			//		augment it with real checks
+			return this;	// dojo.Color
+		},
+		toRgb: function(){
+			// summary:
+			//		Returns 3 component array of rgb values
+			// example:
+			//	|	var c = new dojo.Color("#000000");
+			//	| 	console.log(c.toRgb()); // [0,0,0]
+			var t = this;
+			return [t.r, t.g, t.b];	// Array
+		},
+		toRgba: function(){
+			// summary:
+			//		Returns a 4 component array of rgba values from the color
+			//		represented by this object.
+			var t = this;
+			return [t.r, t.g, t.b, t.a];	// Array
+		},
+		toHex: function(){
+			// summary:
+			//		Returns a CSS color string in hexadecimal representation
+			// example:
+			//	| 	console.log(new dojo.Color([0,0,0]).toHex()); // #000000
+			var arr = d.map(["r", "g", "b"], function(x){
+				var s = this[x].toString(16);
+				return s.length < 2 ? "0" + s : s;
+			}, this);
+			return "#" + arr.join("");	// String
+		},
+		toCss: function(/*Boolean?*/ includeAlpha){
+			// summary:
+			//		Returns a css color string in rgb(a) representation
+			// example:
+			//	|	var c = new dojo.Color("#FFF").toCss();
+			//	|	console.log(c); // rgb('255','255','255')
+			var t = this, rgb = t.r + ", " + t.g + ", " + t.b;
+			return (includeAlpha ? "rgba(" + rgb + ", " + t.a : "rgb(" + rgb) + ")";	// String
+		},
+		toString: function(){
+			// summary:
+			//		Returns a visual representation of the color
+			return this.toCss(true); // String
+		}
+	});
+
+	dojo.blendColors = function(
+		/*dojo.Color*/ start,
+		/*dojo.Color*/ end,
+		/*Number*/ weight,
+		/*dojo.Color?*/ obj
+	){
+		// summary:
+		//		Blend colors end and start with weight from 0 to 1, 0.5 being a 50/50 blend,
+		//		can reuse a previously allocated dojo.Color object for the result
+		var t = obj || new d.Color();
+		d.forEach(["r", "g", "b", "a"], function(x){
+			t[x] = start[x] + (end[x] - start[x]) * weight;
+			if(x != "a"){ t[x] = Math.round(t[x]); }
+		});
+		return t.sanitize();	// dojo.Color
+	};
+
+	dojo.colorFromRgb = function(/*String*/ color, /*dojo.Color?*/ obj){
+		// summary:
+		//		Returns a `dojo.Color` instance from a string of the form
+		//		"rgb(...)" or "rgba(...)". Optionally accepts a `dojo.Color`
+		//		object to update with the parsed value and return instead of
+		//		creating a new object.
+		// returns:
+		//		A dojo.Color object. If obj is passed, it will be the return value.
+		var m = color.toLowerCase().match(/^rgba?\(([\s\.,0-9]+)\)/);
+		return m && dojo.colorFromArray(m[1].split(/\s*,\s*/), obj);	// dojo.Color
+	};
+
+	dojo.colorFromHex = function(/*String*/ color, /*dojo.Color?*/ obj){
+		// summary:
+		//		Converts a hex string with a '#' prefix to a color object.
+		//		Supports 12-bit #rgb shorthand. Optionally accepts a
+		//		`dojo.Color` object to update with the parsed value.
+		//
+		// returns:
+		//		A dojo.Color object. If obj is passed, it will be the return value.
+		//
+		// example:
+		//	 | var thing = dojo.colorFromHex("#ededed"); // grey, longhand
+		//
+		// example:
+		//	| var thing = dojo.colorFromHex("#000"); // black, shorthand
+		var t = obj || new d.Color(),
+			bits = (color.length == 4) ? 4 : 8,
+			mask = (1 << bits) - 1;
+		color = Number("0x" + color.substr(1));
+		if(isNaN(color)){
+			return null; // dojo.Color
+		}
+		d.forEach(["b", "g", "r"], function(x){
+			var c = color & mask;
+			color >>= bits;
+			t[x] = bits == 4 ? 17 * c : c;
+		});
+		t.a = 1;
+		return t;	// dojo.Color
+	};
+
+	dojo.colorFromArray = function(/*Array*/ a, /*dojo.Color?*/ obj){
+		// summary:
+		//		Builds a `dojo.Color` from a 3 or 4 element array, mapping each
+		//		element in sequence to the rgb(a) values of the color.
+		// example:
+		//		| var myColor = dojo.colorFromArray([237,237,237,0.5]); // grey, 50% alpha 
+		// returns:
+		//		A dojo.Color object. If obj is passed, it will be the return value.
+		var t = obj || new d.Color();
+		t._set(Number(a[0]), Number(a[1]), Number(a[2]), Number(a[3]));
+		if(isNaN(t.a)){ t.a = 1; }
+		return t.sanitize();	// dojo.Color
+	};
+
+	dojo.colorFromString = function(/*String*/ str, /*dojo.Color?*/ obj){
+		// summary:
+		//		Parses `str` for a color value. Accepts hex, rgb, and rgba
+		//		style color values.
+		// description:
+		//		Acceptable input values for str may include arrays of any form
+		//		accepted by dojo.colorFromArray, hex strings such as "#aaaaaa", or
+		//		rgb or rgba strings such as "rgb(133, 200, 16)" or "rgba(10, 10,
+		//		10, 50)"
+		// returns:
+		//		A dojo.Color object. If obj is passed, it will be the return value.
+		var a = d.Color.named[str];
+		return a && d.colorFromArray(a, obj) || d.colorFromRgb(str, obj) || d.colorFromHex(str, obj);
+	};
 })();
-}
diff --git a/dojo/_base/Deferred.js b/dojo/_base/Deferred.js
index 8db920b..bb22bf7 100644
--- a/dojo/_base/Deferred.js
+++ b/dojo/_base/Deferred.js
@@ -1,135 +1,331 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.Deferred"]){
-dojo._hasResource["dojo._base.Deferred"]=true;
 dojo.provide("dojo._base.Deferred");
 dojo.require("dojo._base.lang");
-dojo.Deferred=function(_1){
-this.chain=[];
-this.id=this._nextId();
-this.fired=-1;
-this.paused=0;
-this.results=[null,null];
-this.canceller=_1;
-this.silentlyCancelled=false;
-this.isFiring=false;
-};
-dojo.extend(dojo.Deferred,{_nextId:(function(){
-var n=1;
-return function(){
-return n++;
-};
-})(),cancel:function(){
-var _2;
-if(this.fired==-1){
-if(this.canceller){
-_2=this.canceller(this);
-}else{
-this.silentlyCancelled=true;
-}
-if(this.fired==-1){
-if(!(_2 instanceof Error)){
-var _3=_2;
-var _4="Deferred Cancelled";
-if(_2&&_2.toString){
-_4+=": "+_2.toString();
-}
-_2=new Error(_4);
-_2.dojoType="cancel";
-_2.cancelResult=_3;
-}
-this.errback(_2);
-}
-}else{
-if((this.fired==0)&&(this.results[0] instanceof dojo.Deferred)){
-this.results[0].cancel();
-}
-}
-},_resback:function(_5){
-this.fired=((_5 instanceof Error)?1:0);
-this.results[this.fired]=_5;
-this._fire();
-},_check:function(){
-if(this.fired!=-1){
-if(!this.silentlyCancelled){
-throw new Error("already called!");
-}
-this.silentlyCancelled=false;
-return;
-}
-},callback:function(_6){
-this._check();
-this._resback(_6);
-},errback:function(_7){
-this._check();
-if(!(_7 instanceof Error)){
-_7=new Error(_7);
-}
-this._resback(_7);
-},addBoth:function(cb,_8){
-var _9=dojo.hitch.apply(dojo,arguments);
-return this.addCallbacks(_9,_9);
-},addCallback:function(cb,_a){
-return this.addCallbacks(dojo.hitch.apply(dojo,arguments));
-},addErrback:function(cb,_b){
-return this.addCallbacks(null,dojo.hitch.apply(dojo,arguments));
-},addCallbacks:function(cb,eb){
-this.chain.push([cb,eb]);
-if(this.fired>=0&&!this.isFiring){
-this._fire();
-}
-return this;
-},_fire:function(){
-this.isFiring=true;
-var _c=this.chain;
-var _d=this.fired;
-var _e=this.results[_d];
-var _f=this;
-var cb=null;
-while((_c.length>0)&&(this.paused==0)){
-var f=_c.shift()[_d];
-if(!f){
-continue;
-}
-var _10=function(){
-var ret=f(_e);
-if(typeof ret!="undefined"){
-_e=ret;
-}
-_d=((_e instanceof Error)?1:0);
-if(_e instanceof dojo.Deferred){
-cb=function(res){
-_f._resback(res);
-_f.paused--;
-if((_f.paused==0)&&(_f.fired>=0)){
-_f._fire();
-}
-};
-this.paused++;
-}
+
+(function(){
+	var mutator = function(){};		
+	var freeze = Object.freeze || function(){};
+	// A deferred provides an API for creating and resolving a promise.
+	dojo.Deferred = function(/*Function?*/canceller){
+	// summary:
+	//		Deferreds provide a generic means for encapsulating an asynchronous
+	// 		operation and notifying users of the completion and result of the operation. 
+	// description:
+	//		The dojo.Deferred API is based on the concept of promises that provide a
+	//		generic interface into the eventual completion of an asynchronous action.
+	//		The motivation for promises fundamentally is about creating a 
+	//		separation of concerns that allows one to achieve the same type of 
+	//		call patterns and logical data flow in asynchronous code as can be 
+	//		achieved in synchronous code. Promises allows one 
+	//		to be able to call a function purely with arguments needed for 
+	//		execution, without conflating the call with concerns of whether it is 
+	//		sync or async. One shouldn't need to alter a call's arguments if the 
+	//		implementation switches from sync to async (or vice versa). By having 
+	//		async functions return promises, the concerns of making the call are 
+	//		separated from the concerns of asynchronous interaction (which are 
+	//		handled by the promise).
+	// 
+	//  	The dojo.Deferred is a type of promise that provides methods for fulfilling the 
+	// 		promise with a successful result or an error. The most important method for 
+	// 		working with Dojo's promises is the then() method, which follows the 
+	// 		CommonJS proposed promise API. An example of using a Dojo promise:
+	//		
+	//		| 	var resultingPromise = someAsyncOperation.then(function(result){
+	//		|		... handle result ...
+	//		|	},
+	//		|	function(error){
+	//		|		... handle error ...
+	//		|	});
+	//	
+	//		The .then() call returns a new promise that represents the result of the 
+	// 		execution of the callback. The callbacks will never affect the original promises value.
+	//
+	//		The dojo.Deferred instances also provide the following functions for backwards compatibility:
+	//
+	//			* addCallback(handler)
+	//			* addErrback(handler)
+	//			* callback(result)
+	//			* errback(result)
+	//
+	//		Callbacks are allowed to return promisesthemselves, so
+	//		you can build complicated sequences of events with ease.
+	//
+	//		The creator of the Deferred may specify a canceller.  The canceller
+	//		is a function that will be called if Deferred.cancel is called
+	//		before the Deferred fires. You can use this to implement clean
+	//		aborting of an XMLHttpRequest, etc. Note that cancel will fire the
+	//		deferred with a CancelledError (unless your canceller returns
+	//		another kind of error), so the errbacks should be prepared to
+	//		handle that error for cancellable Deferreds.
+	// example:
+	//	|	var deferred = new dojo.Deferred();
+	//	|	setTimeout(function(){ deferred.callback({success: true}); }, 1000);
+	//	|	return deferred;
+	// example:
+	//		Deferred objects are often used when making code asynchronous. It
+	//		may be easiest to write functions in a synchronous manner and then
+	//		split code using a deferred to trigger a response to a long-lived
+	//		operation. For example, instead of register a callback function to
+	//		denote when a rendering operation completes, the function can
+	//		simply return a deferred:
+	//
+	//		|	// callback style:
+	//		|	function renderLotsOfData(data, callback){
+	//		|		var success = false
+	//		|		try{
+	//		|			for(var x in data){
+	//		|				renderDataitem(data[x]);
+	//		|			}
+	//		|			success = true;
+	//		|		}catch(e){ }
+	//		|		if(callback){
+	//		|			callback(success);
+	//		|		}
+	//		|	}
+	//
+	//		|	// using callback style
+	//		|	renderLotsOfData(someDataObj, function(success){
+	//		|		// handles success or failure
+	//		|		if(!success){
+	//		|			promptUserToRecover();
+	//		|		}
+	//		|	});
+	//		|	// NOTE: no way to add another callback here!!
+	// example:
+	//		Using a Deferred doesn't simplify the sending code any, but it
+	//		provides a standard interface for callers and senders alike,
+	//		providing both with a simple way to service multiple callbacks for
+	//		an operation and freeing both sides from worrying about details
+	//		such as "did this get called already?". With Deferreds, new
+	//		callbacks can be added at any time.
+	//
+	//		|	// Deferred style:
+	//		|	function renderLotsOfData(data){
+	//		|		var d = new dojo.Deferred();
+	//		|		try{
+	//		|			for(var x in data){
+	//		|				renderDataitem(data[x]);
+	//		|			}
+	//		|			d.callback(true);
+	//		|		}catch(e){ 
+	//		|			d.errback(new Error("rendering failed"));
+	//		|		}
+	//		|		return d;
+	//		|	}
+	//
+	//		|	// using Deferred style
+	//		|	renderLotsOfData(someDataObj).then(null, function(){
+	//		|		promptUserToRecover();
+	//		|	});
+	//		|	// NOTE: addErrback and addCallback both return the Deferred
+	//		|	// again, so we could chain adding callbacks or save the
+	//		|	// deferred for later should we need to be notified again.
+	// example:
+	//		In this example, renderLotsOfData is syncrhonous and so both
+	//		versions are pretty artificial. Putting the data display on a
+	//		timeout helps show why Deferreds rock:
+	//
+	//		|	// Deferred style and async func
+	//		|	function renderLotsOfData(data){
+	//		|		var d = new dojo.Deferred();
+	//		|		setTimeout(function(){
+	//		|			try{
+	//		|				for(var x in data){
+	//		|					renderDataitem(data[x]);
+	//		|				}
+	//		|				d.callback(true);
+	//		|			}catch(e){ 
+	//		|				d.errback(new Error("rendering failed"));
+	//		|			}
+	//		|		}, 100);
+	//		|		return d;
+	//		|	}
+	//
+	//		|	// using Deferred style
+	//		|	renderLotsOfData(someDataObj).then(null, function(){
+	//		|		promptUserToRecover();
+	//		|	});
+	//
+	//		Note that the caller doesn't have to change his code at all to
+	//		handle the asynchronous case.
+		var result, finished, isError, head, nextListener;
+		var promise = this.promise = {};
+		
+		function complete(value){
+			if(finished){
+				throw new Error("This deferred has already been resolved");				
+			}
+			result = value;
+			finished = true;
+			notify();
+		}
+		function notify(){
+			var mutated;
+			while(!mutated && nextListener){
+				var listener = nextListener;
+				nextListener = nextListener.next;
+				if(mutated = (listener.progress == mutator)){ // assignment and check
+					finished = false;
+				}
+				var func = (isError ? listener.error : listener.resolved);
+				if (func) {
+					try {
+						var newResult = func(result);
+						if (newResult && typeof newResult.then === "function") {
+							newResult.then(dojo.hitch(listener.deferred, "resolve"), dojo.hitch(listener.deferred, "reject"));
+							continue;
+						}
+						var unchanged = mutated && newResult === undefined;
+						listener.deferred[unchanged && isError ? "reject" : "resolve"](unchanged ? result : newResult);
+					}
+					catch (e) {
+						listener.deferred.reject(e);
+					}
+				}else {
+					if(isError){
+						listener.deferred.reject(result);
+					}else{
+						listener.deferred.resolve(result);
+					}
+				}
+			}	
+		}
+		// calling resolve will resolve the promise
+		this.resolve = this.callback = function(value){
+			// summary:
+			//		Fulfills the Deferred instance successfully with the provide value
+			this.fired = 0;
+			this.results = [value, null];
+			complete(value);
+		};
+		
+		
+		// calling error will indicate that the promise failed
+		this.reject = this.errback = function(error){
+			// summary:
+			//		Fulfills the Deferred instance as an error with the provided error 
+			isError = true;
+			this.fired = 1;
+			complete(error);
+			this.results = [null, error];
+			if(!error || error.log !== false){
+				(dojo.config.deferredOnError || function(x){ console.error(x); })(error);
+			}
+		};
+		// call progress to provide updates on the progress on the completion of the promise
+		this.progress = function(update){
+			// summary
+			//		Send progress events to all listeners
+			var listener = nextListener;
+			while(listener){
+				var progress = listener.progress;
+				progress && progress(update);
+				listener = listener.next;	
+			}
+		};
+		this.addCallbacks = function(/*Function?*/callback, /*Function?*/errback){
+			this.then(callback, errback, mutator);
+			return this;
+		};
+		// provide the implementation of the promise
+		this.then = promise.then = function(/*Function?*/resolvedCallback, /*Function?*/errorCallback, /*Function?*/progressCallback){
+			// summary
+			// 		Adds a fulfilledHandler, errorHandler, and progressHandler to be called for 
+			// 		completion of a promise. The fulfilledHandler is called when the promise 
+			// 		is fulfilled. The errorHandler is called when a promise fails. The 
+			// 		progressHandler is called for progress events. All arguments are optional 
+			// 		and non-function values are ignored. The progressHandler is not only an 
+			// 		optional argument, but progress events are purely optional. Promise 
+			// 		providers are not required to ever create progress events.
+			// 
+			// 		This function will return a new promise that is fulfilled when the given 
+			// 		fulfilledHandler or errorHandler callback is finished. This allows promise 
+			// 		operations to be chained together. The value returned from the callback 
+			// 		handler is the fulfillment value for the returned promise. If the callback 
+			// 		throws an error, the returned promise will be moved to failed state.
+			//	
+			// example:
+			// 		An example of using a CommonJS compliant promise:
+  			//		|	asyncComputeTheAnswerToEverything().
+			//		|		then(addTwo).
+			//		|		then(printResult, onError);
+  			//		|	>44 
+			// 		
+			var returnDeferred = progressCallback == mutator ? this : new dojo.Deferred(promise.cancel);
+			var listener = {
+				resolved: resolvedCallback, 
+				error: errorCallback, 
+				progress: progressCallback, 
+				deferred: returnDeferred
+			}; 
+			if(nextListener){
+				head = head.next = listener;
+			}
+			else{
+				nextListener = head = listener;
+			}
+			if(finished){
+				notify();
+			}
+			return returnDeferred.promise;
+		};
+		var deferred = this;
+		this.cancel = promise.cancel = function () {
+			// summary:
+			//		Cancels the asynchronous operation
+			if(!finished){
+				var error = canceller && canceller(deferred);
+				if(!finished){
+					if (!(error instanceof Error)) {
+						error = new Error(error);
+					}
+					error.log = false;
+					deferred.reject(error);
+				}
+			}
+		}
+		freeze(promise);
+	};
+	dojo.extend(dojo.Deferred, {
+		addCallback: function (/*Function*/callback) {
+			return this.addCallbacks(dojo.hitch.apply(dojo, arguments));
+		},
+	
+		addErrback: function (/*Function*/errback) {
+			return this.addCallbacks(null, dojo.hitch.apply(dojo, arguments));
+		},
+	
+		addBoth: function (/*Function*/callback) {
+			var enclosed = dojo.hitch.apply(dojo, arguments);
+			return this.addCallbacks(enclosed, enclosed);
+		},
+		fired: -1
+	});
+})();
+dojo.when = function(promiseOrValue, /*Function?*/callback, /*Function?*/errback, /*Function?*/progressHandler){
+	// summary:
+	//		This provides normalization between normal synchronous values and 
+	//		asynchronous promises, so you can interact with them in a common way
+	//	example:
+	//		|	function printFirstAndList(items){
+	//		|		dojo.when(findFirst(items), console.log);
+	//		|		dojo.when(findLast(items), console.log);
+	//		|	}
+	//		|	function findFirst(items){
+	//		|		return dojo.when(items, function(items){
+	//		|			return items[0];
+	//		|		});
+	//		|	}
+	//		|	function findLast(items){
+	//		|		return dojo.when(items, function(items){
+	//		|			return items[items.length];
+	//		|		});
+	//		|	}
+	//		And now all three of his functions can be used sync or async.
+	//		|	printFirstAndLast([1,2,3,4]) will work just as well as
+	//		|	printFirstAndLast(dojo.xhrGet(...));
+	
+	if(promiseOrValue && typeof promiseOrValue.then === "function"){
+		return promiseOrValue.then(callback, errback, progressHandler);
+	}
+	return callback(promiseOrValue);
 };
-if(dojo.config.debugAtAllCosts){
-_10.call(this);
-}else{
-try{
-_10.call(this);
-}
-catch(err){
-_d=1;
-_e=err;
-}
-}
-}
-this.fired=_d;
-this.results[_d]=_e;
-this.isFiring=false;
-if((cb)&&(this.paused)){
-_e.addBoth(cb);
-}
-}});
-}
diff --git a/dojo/_base/NodeList.js b/dojo/_base/NodeList.js
index 919c97a..279ace4 100644
--- a/dojo/_base/NodeList.js
+++ b/dojo/_base/NodeList.js
@@ -1,229 +1,1009 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.NodeList"]){
-dojo._hasResource["dojo._base.NodeList"]=true;
 dojo.provide("dojo._base.NodeList");
 dojo.require("dojo._base.lang");
 dojo.require("dojo._base.array");
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 (function(){
-var d=dojo;
-var ap=Array.prototype,_1=ap.slice,_2=ap.concat;
-var _3=function(a,_4,_5){
-if(!a.sort){
-a=_1.call(a,0);
-}
-var _6=_5||this._NodeListCtor||d._NodeListCtor;
-a.constructor=_6;
-dojo._mixin(a,_6.prototype);
-a._NodeListCtor=_6;
-return _4?a._stash(_4):a;
-};
-var _7=function(f,a,o){
-a=[0].concat(_1.call(a,0));
-o=o||d.global;
-return function(_8){
-a[0]=_8;
-return f.apply(o,a);
-};
-};
-var _9=function(f,o){
-return function(){
-this.forEach(_7(f,arguments,o));
-return this;
-};
-};
-var _a=function(f,o){
-return function(){
-return this.map(_7(f,arguments,o));
-};
-};
-var _b=function(f,o){
-return function(){
-return this.filter(_7(f,arguments,o));
-};
-};
-var _c=function(f,g,o){
-return function(){
-var a=arguments,_d=_7(f,a,o);
-if(g.call(o||d.global,a)){
-return this.map(_d);
-}
-this.forEach(_d);
-return this;
-};
-};
-var _e=function(a){
-return a.length==1&&(typeof a[0]=="string");
-};
-var _f=function(_10){
-var p=_10.parentNode;
-if(p){
-p.removeChild(_10);
-}
-};
-dojo.NodeList=function(){
-return _3(Array.apply(null,arguments));
-};
-d._NodeListCtor=d.NodeList;
-var nl=d.NodeList,nlp=nl.prototype;
-nl._wrap=nlp._wrap=_3;
-nl._adaptAsMap=_a;
-nl._adaptAsForEach=_9;
-nl._adaptAsFilter=_b;
-nl._adaptWithCondition=_c;
-d.forEach(["slice","splice"],function(_11){
-var f=ap[_11];
-nlp[_11]=function(){
-return this._wrap(f.apply(this,arguments),_11=="slice"?this:null);
-};
-});
-d.forEach(["indexOf","lastIndexOf","every","some"],function(_12){
-var f=d[_12];
-nlp[_12]=function(){
-return f.apply(d,[this].concat(_1.call(arguments,0)));
-};
-});
-d.forEach(["attr","style"],function(_13){
-nlp[_13]=_c(d[_13],_e);
-});
-d.forEach(["connect","addClass","removeClass","toggleClass","empty","removeAttr"],function(_14){
-nlp[_14]=_9(d[_14]);
-});
-dojo.extend(dojo.NodeList,{_normalize:function(_15,_16){
-var _17=_15.parse===true?true:false;
-if(typeof _15.template=="string"){
-var _18=_15.templateFunc||(dojo.string&&dojo.string.substitute);
-_15=_18?_18(_15.template,_15):_15;
-}
-var _19=(typeof _15);
-if(_19=="string"||_19=="number"){
-_15=dojo._toDom(_15,(_16&&_16.ownerDocument));
-if(_15.nodeType==11){
-_15=dojo._toArray(_15.childNodes);
-}else{
-_15=[_15];
-}
-}else{
-if(!dojo.isArrayLike(_15)){
-_15=[_15];
-}else{
-if(!dojo.isArray(_15)){
-_15=dojo._toArray(_15);
-}
-}
-}
-if(_17){
-_15._runParse=true;
-}
-return _15;
-},_cloneNode:function(_1a){
-return _1a.cloneNode(true);
-},_place:function(ary,_1b,_1c,_1d){
-if(_1b.nodeType!=1&&_1c=="only"){
-return;
-}
-var _1e=_1b,_1f;
-var _20=ary.length;
-for(var i=_20-1;i>=0;i--){
-var _21=(_1d?this._cloneNode(ary[i]):ary[i]);
-if(ary._runParse&&dojo.parser&&dojo.parser.parse){
-if(!_1f){
-_1f=_1e.ownerDocument.createElement("div");
-}
-_1f.appendChild(_21);
-dojo.parser.parse(_1f);
-_21=_1f.firstChild;
-while(_1f.firstChild){
-_1f.removeChild(_1f.firstChild);
-}
-}
-if(i==_20-1){
-dojo.place(_21,_1e,_1c);
-}else{
-_1e.parentNode.insertBefore(_21,_1e);
-}
-_1e=_21;
-}
-},_stash:function(_22){
-this._parent=_22;
-return this;
-},end:function(){
-if(this._parent){
-return this._parent;
-}else{
-return new this._NodeListCtor();
-}
-},concat:function(_23){
-var t=d.isArray(this)?this:_1.call(this,0),m=d.map(arguments,function(a){
-return a&&!d.isArray(a)&&(typeof NodeList!="undefined"&&a.constructor===NodeList||a.constructor===this._NodeListCtor)?_1.call(a,0):a;
-});
-return this._wrap(_2.apply(t,m),this);
-},map:function(_24,obj){
-return this._wrap(d.map(this,_24,obj),this);
-},forEach:function(_25,_26){
-d.forEach(this,_25,_26);
-return this;
-},coords:_a(d.coords),position:_a(d.position),place:function(_27,_28){
-var _29=d.query(_27)[0];
-return this.forEach(function(_2a){
-d.place(_2a,_29,_28);
-});
-},orphan:function(_2b){
-return (_2b?d._filterQueryResult(this,_2b):this).forEach(_f);
-},adopt:function(_2c,_2d){
-return d.query(_2c).place(this[0],_2d)._stash(this);
-},query:function(_2e){
-if(!_2e){
-return this;
-}
-var ret=this.map(function(_2f){
-return d.query(_2e,_2f).filter(function(_30){
-return _30!==undefined;
-});
-});
-return this._wrap(_2.apply([],ret),this);
-},filter:function(_31){
-var a=arguments,_32=this,_33=0;
-if(typeof _31=="string"){
-_32=d._filterQueryResult(this,a[0]);
-if(a.length==1){
-return _32._stash(this);
-}
-_33=1;
-}
-return this._wrap(d.filter(_32,a[_33],a[_33+1]),this);
-},addContent:function(_34,_35){
-_34=this._normalize(_34,this[0]);
-for(var i=0,_36;_36=this[i];i++){
-this._place(_34,_36,_35,i>0);
-}
-return this;
-},instantiate:function(_37,_38){
-var c=d.isFunction(_37)?_37:d.getObject(_37);
-_38=_38||{};
-return this.forEach(function(_39){
-new c(_38,_39);
-});
-},at:function(){
-var t=new this._NodeListCtor();
-d.forEach(arguments,function(i){
-if(this[i]){
-t.push(this[i]);
-}
-},this);
-return t._stash(this);
-}});
-nl.events=["blur","focus","change","click","error","keydown","keypress","keyup","load","mousedown","mouseenter","mouseleave","mousemove","mouseout","mouseover","mouseup","submit"];
-d.forEach(nl.events,function(evt){
-var _3a="on"+evt;
-nlp[_3a]=function(a,b){
-return this.connect(_3a,a,b);
-};
-});
+
+	var d = dojo;
+//>>excludeEnd("webkitMobile");
+
+	var ap = Array.prototype, aps = ap.slice, apc = ap.concat;
+
+	var tnl = function(/*Array*/ a, /*dojo.NodeList?*/ parent, /*Function?*/ NodeListCtor){
+		// summary:
+		// 		decorate an array to make it look like a `dojo.NodeList`.
+		// a:
+		// 		Array of nodes to decorate.
+		// parent:
+		// 		An optional parent NodeList that generated the current
+		// 		list of nodes. Used to call _stash() so the parent NodeList
+		// 		can be accessed via end() later.
+		// NodeListCtor:
+		// 		An optional constructor function to use for any
+		// 		new NodeList calls. This allows a certain chain of
+		// 		NodeList calls to use a different object than dojo.NodeList.
+		if(!a.sort){
+			// make sure it's a real array before we pass it on to be wrapped
+			a = aps.call(a, 0);
+		}
+		var ctor = NodeListCtor || this._NodeListCtor || d._NodeListCtor;
+		a.constructor = ctor;
+		dojo._mixin(a, ctor.prototype);
+		a._NodeListCtor = ctor;
+		return parent ? a._stash(parent) : a;
+	};
+
+	var loopBody = function(f, a, o){
+		a = [0].concat(aps.call(a, 0));
+		o = o || d.global;
+		return function(node){
+			a[0] = node;
+			return f.apply(o, a);
+		};
+	};
+
+	// adapters
+
+	var adaptAsForEach = function(f, o){
+		//	summary:
+		//		adapts a single node function to be used in the forEach-type
+		//		actions. The initial object is returned from the specialized
+		//		function.
+		//	f: Function
+		//		a function to adapt
+		//	o: Object?
+		//		an optional context for f
+		return function(){
+			this.forEach(loopBody(f, arguments, o));
+			return this;	// Object
+		};
+	};
+
+	var adaptAsMap = function(f, o){
+		//	summary:
+		//		adapts a single node function to be used in the map-type
+		//		actions. The return is a new array of values, as via `dojo.map`
+		//	f: Function
+		//		a function to adapt
+		//	o: Object?
+		//		an optional context for f
+		return function(){
+			return this.map(loopBody(f, arguments, o));
+		};
+	};
+
+	var adaptAsFilter = function(f, o){
+		//	summary:
+		//		adapts a single node function to be used in the filter-type actions
+		//	f: Function
+		//		a function to adapt
+		//	o: Object?
+		//		an optional context for f
+		return function(){
+			return this.filter(loopBody(f, arguments, o));
+		};
+	};
+
+	var adaptWithCondition = function(f, g, o){
+		//	summary:
+		//		adapts a single node function to be used in the map-type
+		//		actions, behaves like forEach() or map() depending on arguments
+		//	f: Function
+		//		a function to adapt
+		//	g: Function
+		//		a condition function, if true runs as map(), otherwise runs as forEach()
+		//	o: Object?
+		//		an optional context for f and g
+		return function(){
+			var a = arguments, body = loopBody(f, a, o);
+			if(g.call(o || d.global, a)){
+				return this.map(body);	// self
+			}
+			this.forEach(body);
+			return this;	// self
+		};
+	};
+
+	var magicGuard = function(a){
+		//	summary:
+		//		the guard function for dojo.attr() and dojo.style()
+		return a.length == 1 && (typeof a[0] == "string"); // inline'd type check
+	};
+
+	var orphan = function(node){
+		//	summary:
+		//		function to orphan nodes
+		var p = node.parentNode;
+		if(p){
+			p.removeChild(node);
+		}
+	};
+	// FIXME: should we move orphan() to dojo.html?
+
+	dojo.NodeList = function(){
+		//	summary:
+		//		dojo.NodeList is an of Array subclass which adds syntactic
+		//		sugar for chaining, common iteration operations, animation, and
+		//		node manipulation. NodeLists are most often returned as the
+		//		result of dojo.query() calls.
+		//	description:
+		//		dojo.NodeList instances provide many utilities that reflect
+		//		core Dojo APIs for Array iteration and manipulation, DOM
+		//		manipulation, and event handling. Instead of needing to dig up
+		//		functions in the dojo.* namespace, NodeLists generally make the
+		//		full power of Dojo available for DOM manipulation tasks in a
+		//		simple, chainable way.
+		//	example:
+		//		create a node list from a node
+		//		|	new dojo.NodeList(dojo.byId("foo"));
+		//	example:
+		//		get a NodeList from a CSS query and iterate on it
+		//		|	var l = dojo.query(".thinger");
+		//		|	l.forEach(function(node, index, nodeList){
+		//		|		console.log(index, node.innerHTML);
+		//		|	});
+		//	example:
+		//		use native and Dojo-provided array methods to manipulate a
+		//		NodeList without needing to use dojo.* functions explicitly:
+		//		|	var l = dojo.query(".thinger");
+		//		|	// since NodeLists are real arrays, they have a length
+		//		|	// property that is both readable and writable and
+		//		|	// push/pop/shift/unshift methods
+		//		|	console.log(l.length);
+		//		|	l.push(dojo.create("span"));
+		//		|
+		//		|	// dojo's normalized array methods work too:
+		//		|	console.log( l.indexOf(dojo.byId("foo")) );
+		//		|	// ...including the special "function as string" shorthand
+		//		|	console.log( l.every("item.nodeType == 1") );
+		//		|
+		//		|	// NodeLists can be [..] indexed, or you can use the at()
+		//		|	// function to get specific items wrapped in a new NodeList:
+		//		|	var node = l[3]; // the 4th element
+		//		|	var newList = l.at(1, 3); // the 2nd and 4th elements
+		//	example:
+		//		the style functions you expect are all there too:
+		//		|	// style() as a getter...
+		//		|	var borders = dojo.query(".thinger").style("border");
+		//		|	// ...and as a setter:
+		//		|	dojo.query(".thinger").style("border", "1px solid black");
+		//		|	// class manipulation
+		//		|	dojo.query("li:nth-child(even)").addClass("even");
+		//		|	// even getting the coordinates of all the items
+		//		|	var coords = dojo.query(".thinger").coords();
+		//	example:
+		//		DOM manipulation functions from the dojo.* namespace area also
+		//		available:
+		//		|	// remove all of the elements in the list from their
+		//		|	// parents (akin to "deleting" them from the document)
+		//		|	dojo.query(".thinger").orphan();
+		//		|	// place all elements in the list at the front of #foo
+		//		|	dojo.query(".thinger").place("foo", "first");
+		//	example:
+		//		Event handling couldn't be easier. `dojo.connect` is mapped in,
+		//		and shortcut handlers are provided for most DOM events:
+		//		|	// like dojo.connect(), but with implicit scope
+		//		|	dojo.query("li").connect("onclick", console, "log");
+		//		|
+		//		|	// many common event handlers are already available directly:
+		//		|	dojo.query("li").onclick(console, "log");
+		//		|	var toggleHovered = dojo.hitch(dojo, "toggleClass", "hovered");
+		//		|	dojo.query("p")
+		//		|		.onmouseenter(toggleHovered)
+		//		|		.onmouseleave(toggleHovered);
+		//	example:
+		//		chainability is a key advantage of NodeLists:
+		//		|	dojo.query(".thinger")
+		//		|		.onclick(function(e){ /* ... */ })
+		//		|		.at(1, 3, 8) // get a subset
+		//		|			.style("padding", "5px")
+		//		|			.forEach(console.log);
+
+		return tnl(Array.apply(null, arguments));
+	};
+
+	//Allow things that new up a NodeList to use a delegated or alternate NodeList implementation.
+	d._NodeListCtor = d.NodeList;
+
+	var nl = d.NodeList, nlp = nl.prototype;
+
+	// expose adapters and the wrapper as private functions
+
+	nl._wrap = nlp._wrap = tnl;
+	nl._adaptAsMap = adaptAsMap;
+	nl._adaptAsForEach = adaptAsForEach;
+	nl._adaptAsFilter  = adaptAsFilter;
+	nl._adaptWithCondition = adaptWithCondition;
+
+	// mass assignment
+
+	// add array redirectors
+	d.forEach(["slice", "splice"], function(name){
+		var f = ap[name];
+		//Use a copy of the this array via this.slice() to allow .end() to work right in the splice case.
+		// CANNOT apply ._stash()/end() to splice since it currently modifies
+		// the existing this array -- it would break backward compatibility if we copy the array before
+		// the splice so that we can use .end(). So only doing the stash option to this._wrap for slice.
+		nlp[name] = function(){ return this._wrap(f.apply(this, arguments), name == "slice" ? this : null); };
+	});
+	// concat should be here but some browsers with native NodeList have problems with it
+
+	// add array.js redirectors
+	d.forEach(["indexOf", "lastIndexOf", "every", "some"], function(name){
+		var f = d[name];
+		nlp[name] = function(){ return f.apply(d, [this].concat(aps.call(arguments, 0))); };
+	});
+
+	// add conditional methods
+	d.forEach(["attr", "style"], function(name){
+		nlp[name] = adaptWithCondition(d[name], magicGuard);
+	});
+
+	// add forEach actions
+	d.forEach(["connect", "addClass", "removeClass", "toggleClass", "empty", "removeAttr"], function(name){
+		nlp[name] = adaptAsForEach(d[name]);
+	});
+
+	dojo.extend(dojo.NodeList, {
+		_normalize: function(/*String||Element||Object||NodeList*/content, /*DOMNode?*/refNode){
+			// summary:
+			// 		normalizes data to an array of items to insert.
+			// description:
+			// 		If content is an object, it can have special properties "template" and
+			// 		"parse". If "template" is defined, then the template value is run through
+			// 		dojo.string.substitute (if dojo.string.substitute has been dojo.required elsewhere),
+			// 		or if templateFunc is a function on the content, that function will be used to
+			// 		transform the template into a final string to be used for for passing to dojo._toDom.
+			// 		If content.parse is true, then it is remembered for later, for when the content
+			// 		nodes are inserted into the DOM. At that point, the nodes will be parsed for widgets
+			// 		(if dojo.parser has been dojo.required elsewhere).
+
+			//Wanted to just use a DocumentFragment, but for the array/NodeList
+			//case that meant  using cloneNode, but we may not want that.
+			//Cloning should only happen if the node operations span
+			//multiple refNodes. Also, need a real array, not a NodeList from the
+			//DOM since the node movements could change those NodeLists.
+
+			var parse = content.parse === true ? true : false;
+
+			//Do we have an object that needs to be run through a template?
+			if(typeof content.template == "string"){
+				var templateFunc = content.templateFunc || (dojo.string && dojo.string.substitute);
+				content = templateFunc ? templateFunc(content.template, content) : content;
+			}
+
+			var type = (typeof content);
+			if(type == "string" || type == "number"){
+				content = dojo._toDom(content, (refNode && refNode.ownerDocument));
+				if(content.nodeType == 11){
+					//DocumentFragment. It cannot handle cloneNode calls, so pull out the children.
+					content = dojo._toArray(content.childNodes);
+				}else{
+					content = [content];
+				}
+			}else if(!dojo.isArrayLike(content)){
+				content = [content];
+			}else if(!dojo.isArray(content)){
+				//To get to this point, content is array-like, but
+				//not an array, which likely means a DOM NodeList. Convert it now.
+				content = dojo._toArray(content);
+			}
+
+			//Pass around the parse info
+			if(parse){
+				content._runParse = true;
+			}
+			return content; //Array
+		},
+
+		_cloneNode: function(/*DOMNode*/ node){
+			// summary:
+			// 		private utiltity to clone a node. Not very interesting in the vanilla
+			// 		dojo.NodeList case, but delegates could do interesting things like
+			// 		clone event handlers if that is derivable from the node.
+			return node.cloneNode(true);
+		},
+
+		_place: function(/*Array*/ary, /*DOMNode*/refNode, /*String*/position, /*Boolean*/useClone){
+			// summary:
+			// 		private utility to handle placing an array of nodes relative to another node.
+			// description:
+			// 		Allows for cloning the nodes in the array, and for
+			// 		optionally parsing widgets, if ary._runParse is true.
+
+			//Avoid a disallowed operation if trying to do an innerHTML on a non-element node.
+			if(refNode.nodeType != 1 && position == "only"){
+				return;
+			}
+			var rNode = refNode, tempNode;
+
+			//Always cycle backwards in case the array is really a
+			//DOM NodeList and the DOM operations take it out of the live collection.
+			var length = ary.length;
+			for(var i = length - 1; i >= 0; i--){
+				var node = (useClone ? this._cloneNode(ary[i]) : ary[i]);
+
+				//If need widget parsing, use a temp node, instead of waiting after inserting into
+				//real DOM because we need to start widget parsing at one node up from current node,
+				//which could cause some already parsed widgets to be parsed again.
+				if(ary._runParse && dojo.parser && dojo.parser.parse){
+					if(!tempNode){
+						tempNode = rNode.ownerDocument.createElement("div");
+					}
+					tempNode.appendChild(node);
+					dojo.parser.parse(tempNode);
+					node = tempNode.firstChild;
+					while(tempNode.firstChild){
+						tempNode.removeChild(tempNode.firstChild);
+					}
+				}
+
+				if(i == length - 1){
+					dojo.place(node, rNode, position);
+				}else{
+					rNode.parentNode.insertBefore(node, rNode);
+				}
+				rNode = node;
+			}
+		},
+
+		_stash: function(parent){
+			// summary:
+			// 		private function to hold to a parent NodeList. end() to return the parent NodeList.
+			//
+			// example:
+			// How to make a `dojo.NodeList` method that only returns the third node in
+			// the dojo.NodeList but allows access to the original NodeList by using this._stash:
+			//	|	dojo.extend(dojo.NodeList, {
+			//	|		third: function(){
+			//  |			var newNodeList = dojo.NodeList(this[2]);
+			//	|			return newNodeList._stash(this);
+			//	|		}
+			//	|	});
+			//	|	// then see how _stash applies a sub-list, to be .end()'ed out of
+			//	|	dojo.query(".foo")
+			//	|		.third()
+			//	|			.addClass("thirdFoo")
+			//	|		.end()
+			//	|		// access to the orig .foo list
+			//	|		.removeClass("foo")
+			//	|
+			//
+			this._parent = parent;
+			return this; //dojo.NodeList
+		},
+
+		end: function(){
+			// summary:
+			// 		Ends use of the current `dojo.NodeList` by returning the previous dojo.NodeList
+			// 		that generated the current dojo.NodeList.
+			// description:
+			// 		Returns the `dojo.NodeList` that generated the current `dojo.NodeList`. If there
+			// 		is no parent dojo.NodeList, an empty dojo.NodeList is returned.
+			// example:
+			//	|	dojo.query("a")
+			//	|		.filter(".disabled")
+			//	|			// operate on the anchors that only have a disabled class
+			//	|			.style("color", "grey")
+			//	|		.end()
+			//	|		// jump back to the list of anchors
+			//	|		.style(...)
+			//
+			if(this._parent){
+				return this._parent;
+			}else{
+				//Just return empy list.
+				return new this._NodeListCtor();
+			}
+		},
+
+		// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array#Methods
+
+		// FIXME: handle return values for #3244
+		//		http://trac.dojotoolkit.org/ticket/3244
+
+		// FIXME:
+		//		need to wrap or implement:
+		//			join (perhaps w/ innerHTML/outerHTML overload for toString() of items?)
+		//			reduce
+		//			reduceRight
+
+		/*=====
+		slice: function(begin, end){
+			// summary:
+			//		Returns a new NodeList, maintaining this one in place
+			// description:
+			//		This method behaves exactly like the Array.slice method
+			//		with the caveat that it returns a dojo.NodeList and not a
+			//		raw Array. For more details, see Mozilla's (slice
+			//		documentation)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:slice]
+			// begin: Integer
+			//		Can be a positive or negative integer, with positive
+			//		integers noting the offset to begin at, and negative
+			//		integers denoting an offset from the end (i.e., to the left
+			//		of the end)
+			// end: Integer?
+			//		Optional parameter to describe what position relative to
+			//		the NodeList's zero index to end the slice at. Like begin,
+			//		can be positive or negative.
+			return this._wrap(a.slice.apply(this, arguments));
+		},
+
+		splice: function(index, howmany, item){
+			// summary:
+			//		Returns a new NodeList, manipulating this NodeList based on
+			//		the arguments passed, potentially splicing in new elements
+			//		at an offset, optionally deleting elements
+			// description:
+			//		This method behaves exactly like the Array.splice method
+			//		with the caveat that it returns a dojo.NodeList and not a
+			//		raw Array. For more details, see Mozilla's (splice
+			//		documentation)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:splice]
+			// 		For backwards compatibility, calling .end() on the spliced NodeList
+			// 		does not return the original NodeList -- splice alters the NodeList in place.
+			// index: Integer
+			//		begin can be a positive or negative integer, with positive
+			//		integers noting the offset to begin at, and negative
+			//		integers denoting an offset from the end (i.e., to the left
+			//		of the end)
+			// howmany: Integer?
+			//		Optional parameter to describe what position relative to
+			//		the NodeList's zero index to end the slice at. Like begin,
+			//		can be positive or negative.
+			// item: Object...?
+			//		Any number of optional parameters may be passed in to be
+			//		spliced into the NodeList
+			// returns:
+			//		dojo.NodeList
+			return this._wrap(a.splice.apply(this, arguments));
+		},
+
+		indexOf: function(value, fromIndex){
+			//	summary:
+			//		see dojo.indexOf(). The primary difference is that the acted-on 
+			//		array is implicitly this NodeList
+			// value: Object:
+			//		The value to search for.
+			// fromIndex: Integer?:
+			//		The loction to start searching from. Optional. Defaults to 0.
+			//	description:
+			//		For more details on the behavior of indexOf, see Mozilla's
+			//		(indexOf
+			//		docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf]
+			//	returns:
+			//		Positive Integer or 0 for a match, -1 of not found.
+			return d.indexOf(this, value, fromIndex); // Integer
+		},
+
+		lastIndexOf: function(value, fromIndex){
+			// summary:
+			//		see dojo.lastIndexOf(). The primary difference is that the
+			//		acted-on array is implicitly this NodeList
+			//	description:
+			//		For more details on the behavior of lastIndexOf, see
+			//		Mozilla's (lastIndexOf
+			//		docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf]
+			// value: Object
+			//		The value to search for.
+			// fromIndex: Integer?
+			//		The loction to start searching from. Optional. Defaults to 0.
+			// returns:
+			//		Positive Integer or 0 for a match, -1 of not found.
+			return d.lastIndexOf(this, value, fromIndex); // Integer
+		},
+
+		every: function(callback, thisObject){
+			//	summary:
+			//		see `dojo.every()` and the (Array.every
+			//		docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every].
+			//		Takes the same structure of arguments and returns as
+			//		dojo.every() with the caveat that the passed array is
+			//		implicitly this NodeList
+			// callback: Function: the callback
+			// thisObject: Object?: the context
+			return d.every(this, callback, thisObject); // Boolean
+		},
+
+		some: function(callback, thisObject){
+			//	summary:
+			//		Takes the same structure of arguments and returns as
+			//		`dojo.some()` with the caveat that the passed array is
+			//		implicitly this NodeList.  See `dojo.some()` and Mozilla's
+			//		(Array.some
+			//		documentation)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some].
+			// callback: Function: the callback
+			// thisObject: Object?: the context
+			return d.some(this, callback, thisObject); // Boolean
+		},
+		=====*/
+
+		concat: function(item){
+			// summary:
+			//		Returns a new NodeList comprised of items in this NodeList
+			//		as well as items passed in as parameters
+			// description:
+			//		This method behaves exactly like the Array.concat method
+			//		with the caveat that it returns a `dojo.NodeList` and not a
+			//		raw Array. For more details, see the (Array.concat
+			//		docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:concat]
+			// item: Object?
+			//		Any number of optional parameters may be passed in to be
+			//		spliced into the NodeList
+			// returns:
+			//		dojo.NodeList
+
+			//return this._wrap(apc.apply(this, arguments));
+			// the line above won't work for the native NodeList :-(
+
+			// implementation notes:
+			// 1) Native NodeList is not an array, and cannot be used directly
+			// in concat() --- the latter doesn't recognize it as an array, and
+			// does not inline it, but append as a single entity.
+			// 2) On some browsers (e.g., Safari) the "constructor" property is
+			// read-only and cannot be changed. So we have to test for both
+			// native NodeList and dojo.NodeList in this property to recognize
+			// the node list.
+
+			var t = d.isArray(this) ? this : aps.call(this, 0),
+				m = d.map(arguments, function(a){
+					return a && !d.isArray(a) &&
+						(typeof NodeList != "undefined" && a.constructor === NodeList || a.constructor === this._NodeListCtor) ?
+							aps.call(a, 0) : a;
+				});
+			return this._wrap(apc.apply(t, m), this);	// dojo.NodeList
+		},
+
+		map: function(/*Function*/ func, /*Function?*/ obj){
+			//	summary:
+			//		see dojo.map(). The primary difference is that the acted-on
+			//		array is implicitly this NodeList and the return is a
+			//		dojo.NodeList (a subclass of Array)
+			///return d.map(this, func, obj, d.NodeList); // dojo.NodeList
+			return this._wrap(d.map(this, func, obj), this); // dojo.NodeList
+		},
+
+		forEach: function(callback, thisObj){
+			//	summary:
+			//		see `dojo.forEach()`. The primary difference is that the acted-on 
+			//		array is implicitly this NodeList. If you want the option to break out
+			//		of the forEach loop, use every() or some() instead.
+			d.forEach(this, callback, thisObj);
+			// non-standard return to allow easier chaining
+			return this; // dojo.NodeList 
+		},
+
+		/*=====
+		coords: function(){
+			//	summary:
+			//		Returns the box objects of all elements in a node list as
+			//		an Array (*not* a NodeList). Acts like `dojo.coords`, though assumes
+			//		the node passed is each node in this list.
+
+			return d.map(this, d.coords); // Array
+		},
+
+		position: function(){
+			//	summary:
+			//		Returns border-box objects (x/y/w/h) of all elements in a node list
+			//		as an Array (*not* a NodeList). Acts like `dojo.position`, though
+			//		assumes the node passed is each node in this list. 
+
+			return d.map(this, d.position); // Array
+		},
+
+		attr: function(property, value){
+			//	summary:
+			//		gets or sets the DOM attribute for every element in the
+			//		NodeList. See also `dojo.attr`
+			//	property: String
+			//		the attribute to get/set
+			//	value: String?
+			//		optional. The value to set the property to
+			//	returns:
+			//		if no value is passed, the result is an array of attribute values
+			//		If a value is passed, the return is this NodeList
+			//	example:
+			//		Make all nodes with a particular class focusable:
+			//	|	dojo.query(".focusable").attr("tabIndex", -1);
+			//	example:
+			//		Disable a group of buttons:
+			//	|	dojo.query("button.group").attr("disabled", true);
+			//	example:
+			//		innerHTML can be assigned or retreived as well:
+			//	|	// get the innerHTML (as an array) for each list item
+			//	|	var ih = dojo.query("li.replaceable").attr("innerHTML");
+			return; // dojo.NodeList
+			return; // Array
+		},
+
+		style: function(property, value){
+			//	summary:
+			//		gets or sets the CSS property for every element in the NodeList
+			//	property: String
+			//		the CSS property to get/set, in JavaScript notation
+			//		("lineHieght" instead of "line-height")
+			//	value: String?
+			//		optional. The value to set the property to
+			//	returns:
+			//		if no value is passed, the result is an array of strings.
+			//		If a value is passed, the return is this NodeList
+			return; // dojo.NodeList
+			return; // Array
+		},
+
+		addClass: function(className){
+			//	summary:
+			//		adds the specified class to every node in the list
+			//	className: String|Array
+			//		A String class name to add, or several space-separated class names,
+			//		or an array of class names.
+			return; // dojo.NodeList
+		},
+
+		removeClass: function(className){
+			//	summary:
+			//		removes the specified class from every node in the list
+			//	className: String|Array?
+			//		An optional String class name to remove, or several space-separated
+			//		class names, or an array of class names. If omitted, all class names
+			//		will be deleted.
+			//	returns:
+			//		dojo.NodeList, this list
+			return; // dojo.NodeList
+		},
+
+		toggleClass: function(className, condition){
+			//	summary:
+			//		Adds a class to node if not present, or removes if present.
+			//		Pass a boolean condition if you want to explicitly add or remove.
+			//	condition: Boolean?
+			//		If passed, true means to add the class, false means to remove.
+			//	className: String
+			//		the CSS class to add
+			return; // dojo.NodeList
+		},
+
+		connect: function(methodName, objOrFunc, funcName){
+			//	summary:
+			//		attach event handlers to every item of the NodeList. Uses dojo.connect()
+			//		so event properties are normalized
+			//	methodName: String
+			//		the name of the method to attach to. For DOM events, this should be
+			//		the lower-case name of the event
+			//	objOrFunc: Object|Function|String
+			//		if 2 arguments are passed (methodName, objOrFunc), objOrFunc should
+			//		reference a function or be the name of the function in the global
+			//		namespace to attach. If 3 arguments are provided
+			//		(methodName, objOrFunc, funcName), objOrFunc must be the scope to 
+			//		locate the bound function in
+			//	funcName: String?
+			//		optional. A string naming the function in objOrFunc to bind to the
+			//		event. May also be a function reference.
+			//	example:
+			//		add an onclick handler to every button on the page
+			//		|	dojo.query("div:nth-child(odd)").connect("onclick", function(e){
+			//		|		console.log("clicked!");
+			//		|	});
+			// example:
+			//		attach foo.bar() to every odd div's onmouseover
+			//		|	dojo.query("div:nth-child(odd)").connect("onmouseover", foo, "bar");
+		},
+
+		empty: function(){
+			//	summary:
+			//		clears all content from each node in the list. Effectively
+			//		equivalent to removing all child nodes from every item in
+			//		the list.
+			return this.forEach("item.innerHTML='';"); // dojo.NodeList
+			// FIXME: should we be checking for and/or disposing of widgets below these nodes?
+		},
+		=====*/
+
+		// useful html methods
+		coords:	adaptAsMap(d.coords),
+		position: adaptAsMap(d.position),
+
+		// FIXME: connectPublisher()? connectRunOnce()?
+
+		/*
+		destroy: function(){
+			//	summary:
+			//		destroys every item in 	the list.
+			this.forEach(d.destroy);
+			// FIXME: should we be checking for and/or disposing of widgets below these nodes?
+		},
+		*/
+
+		place: function(/*String||Node*/ queryOrNode, /*String*/ position){
+			//	summary:
+			//		places elements of this node list relative to the first element matched
+			//		by queryOrNode. Returns the original NodeList. See: `dojo.place`
+			//	queryOrNode:
+			//		may be a string representing any valid CSS3 selector or a DOM node.
+			//		In the selector case, only the first matching element will be used 
+			//		for relative positioning.
+			//	position:
+			//		can be one of:
+			//		|	"last" (default)
+			//		|	"first"
+			//		|	"before"
+			//		|	"after"
+			//		|	"only"
+			//		|	"replace"
+			// 		or an offset in the childNodes property
+			var item = d.query(queryOrNode)[0];
+			return this.forEach(function(node){ d.place(node, item, position); }); // dojo.NodeList
+		},
+
+		orphan: function(/*String?*/ simpleFilter){
+			//	summary:
+			//		removes elements in this list that match the simple filter
+			//		from their parents and returns them as a new NodeList.
+			//	simpleFilter:
+			//		single-expression CSS rule. For example, ".thinger" or
+			//		"#someId[attrName='value']" but not "div > span". In short,
+			//		anything which does not invoke a descent to evaluate but
+			//		can instead be used to test a single node is acceptable.
+			//	returns:
+			//		`dojo.NodeList` containing the orpahned elements 
+			return (simpleFilter ? d._filterQueryResult(this, simpleFilter) : this).forEach(orphan); // dojo.NodeList
+		},
+
+		adopt: function(/*String||Array||DomNode*/ queryOrListOrNode, /*String?*/ position){
+			//	summary:
+			//		places any/all elements in queryOrListOrNode at a
+			//		position relative to the first element in this list.
+			//		Returns a dojo.NodeList of the adopted elements.
+			//	queryOrListOrNode:
+			//		a DOM node or a query string or a query result.
+			//		Represents the nodes to be adopted relative to the
+			//		first element of this NodeList.
+			//	position:
+			//		can be one of:
+			//		|	"last" (default)
+			//		|	"first"
+			//		|	"before"
+			//		|	"after"
+			//		|	"only"
+			//		|	"replace"
+			// 		or an offset in the childNodes property
+			return d.query(queryOrListOrNode).place(this[0], position)._stash(this);	// dojo.NodeList
+		},
+
+		// FIXME: do we need this?
+		query: function(/*String*/ queryStr){
+			//	summary:
+			//		Returns a new list whose memebers match the passed query,
+			//		assuming elements of the current NodeList as the root for
+			//		each search.
+			//	example:
+			//		assume a DOM created by this markup:
+			//	|	<div id="foo">
+			//	|		<p>
+			//	|			bacon is tasty, <span>dontcha think?</span>
+			//	|		</p>
+			//	|	</div>
+			//	|	<div id="bar">
+			//	|		<p>great commedians may not be funny <span>in person</span></p>
+			//	|	</div>
+			//		If we are presented with the following defintion for a NodeList:
+			//	|	var l = new dojo.NodeList(dojo.byId("foo"), dojo.byId("bar"));
+			//		it's possible to find all span elements under paragraphs
+			//		contained by these elements with this sub-query:
+			//	| 	var spans = l.query("p span");
+
+			// FIXME: probably slow
+			if(!queryStr){ return this; }
+			var ret = this.map(function(node){
+				// FIXME: why would we ever get undefined here?
+				return d.query(queryStr, node).filter(function(subNode){ return subNode !== undefined; });
+			});
+			return this._wrap(apc.apply([], ret), this);	// dojo.NodeList
+		},
+
+		filter: function(/*String|Function*/ simpleFilter){
+			//	summary:
+			// 		"masks" the built-in javascript filter() method (supported
+			// 		in Dojo via `dojo.filter`) to support passing a simple
+			// 		string filter in addition to supporting filtering function
+			// 		objects.
+			//	simpleFilter:
+			//		If a string, a single-expression CSS rule. For example,
+			//		".thinger" or "#someId[attrName='value']" but not "div >
+			//		span". In short, anything which does not invoke a descent
+			//		to evaluate but can instead be used to test a single node
+			//		is acceptable.
+			//	example:
+			//		"regular" JS filter syntax as exposed in dojo.filter:
+			//		|	dojo.query("*").filter(function(item){
+			//		|		// highlight every paragraph
+			//		|		return (item.nodeName == "p");
+			//		|	}).style("backgroundColor", "yellow");
+			// example:
+			//		the same filtering using a CSS selector
+			//		|	dojo.query("*").filter("p").styles("backgroundColor", "yellow");
+
+			var a = arguments, items = this, start = 0;
+			if(typeof simpleFilter == "string"){ // inline'd type check
+				items = d._filterQueryResult(this, a[0]);
+				if(a.length == 1){
+					// if we only got a string query, pass back the filtered results
+					return items._stash(this); // dojo.NodeList
+				}
+				// if we got a callback, run it over the filtered items
+				start = 1;
+			}
+			return this._wrap(d.filter(items, a[start], a[start + 1]), this);	// dojo.NodeList
+		},
+
+		/*
+		// FIXME: should this be "copyTo" and include parenting info?
+		clone: function(){
+			// summary:
+			//		creates node clones of each element of this list
+			//		and returns a new list containing the clones
+		},
+		*/
+
+		addContent: function(/*String||DomNode||Object||dojo.NodeList*/ content, /*String||Integer?*/ position){
+			//	summary:
+			//		add a node, NodeList or some HTML as a string to every item in the
+			//		list.  Returns the original list.
+			//	description:
+			//		a copy of the HTML content is added to each item in the
+			//		list, with an optional position argument. If no position
+			//		argument is provided, the content is appended to the end of
+			//		each item.
+			//	content:
+			//		DOM node, HTML in string format, a NodeList or an Object. If a DOM node or
+			// 		NodeList, the content will be cloned if the current NodeList has more than one
+			// 		element. Only the DOM nodes are cloned, no event handlers. If it is an Object,
+			// 		it should be an object with at "template" String property that has the HTML string
+			// 		to insert. If dojo.string has already been dojo.required, then dojo.string.substitute
+			// 		will be used on the "template" to generate the final HTML string. Other allowed
+			// 		properties on the object are: "parse" if the HTML
+			// 		string should be parsed for widgets (dojo.require("dojo.parser") to get that
+			// 		option to work), and "templateFunc" if a template function besides dojo.string.substitute
+			// 		should be used to transform the "template".
+			//	position:
+			//		can be one of:
+			//		|	"last"||"end" (default)
+			//		|	"first||"start"
+			//		|	"before"
+			//		|	"after"
+			//		|	"replace" (replaces nodes in this NodeList with new content)
+			//		|	"only" (removes other children of the nodes so new content is hte only child)
+			// 		or an offset in the childNodes property
+			//	example:
+			//		appends content to the end if the position is ommitted
+			//	|	dojo.query("h3 > p").addContent("hey there!");
+			//	example:
+			//		add something to the front of each element that has a
+			//		"thinger" property:
+			//	|	dojo.query("[thinger]").addContent("...", "first");
+			//	example:
+			//		adds a header before each element of the list
+			//	|	dojo.query(".note").addContent("<h4>NOTE:</h4>", "before");
+			//	example:
+			//		add a clone of a DOM node to the end of every element in
+			//		the list, removing it from its existing parent.
+			//	|	dojo.query(".note").addContent(dojo.byId("foo"));
+			//  example:
+			//  	Append nodes from a templatized string.
+			// 		dojo.require("dojo.string");
+			// 		dojo.query(".note").addContent({
+			//  		template: '<b>${id}: </b><span>${name}</span>',
+			// 			id: "user332",
+			//  		name: "Mr. Anderson"
+			//  	});
+			//  example:
+			//  	Append nodes from a templatized string that also has widgets parsed.
+			//  	dojo.require("dojo.string");
+			//  	dojo.require("dojo.parser");
+			//  	var notes = dojo.query(".note").addContent({
+			//  		template: '<button dojoType="dijit.form.Button">${text}</button>',
+			//  		parse: true,
+			//  		text: "Send"
+			//  	});
+			content = this._normalize(content, this[0]);
+			for(var i = 0, node; node = this[i]; i++){
+				this._place(content, node, position, i > 0);
+			}
+			return this; //dojo.NodeList
+		},
+
+		instantiate: function(/*String|Object*/ declaredClass, /*Object?*/ properties){
+			//	summary:
+			//		Create a new instance of a specified class, using the
+			//		specified properties and each node in the nodeList as a
+			//		srcNodeRef.
+			//	example:
+			//		Grabs all buttons in the page and converts them to diji.form.Buttons.
+			//	|	var buttons = dojo.query("button").instantiate("dijit.form.Button", {showLabel: true});
+			var c = d.isFunction(declaredClass) ? declaredClass : d.getObject(declaredClass);
+			properties = properties || {};
+			return this.forEach(function(node){
+				new c(properties, node);
+			});	// dojo.NodeList
+		},
+
+		at: function(/*===== index =====*/){
+			//	summary:
+			//		Returns a new NodeList comprised of items in this NodeList
+			//		at the given index or indices.
+			//
+			//	index: Integer...
+			//		One or more 0-based indices of items in the current
+			//		NodeList. A negative index will start at the end of the
+			//		list and go backwards. 
+			//
+			//	example:
+			//	Shorten the list to the first, second, and third elements
+			//	|	dojo.query("a").at(0, 1, 2).forEach(fn); 
+			//
+			//	example:
+			//	Retrieve the first and last elements of a unordered list:
+			//	|	dojo.query("ul > li").at(0, -1).forEach(cb);
+			//
+			//	example:
+			//	Do something for the first element only, but end() out back to
+			//	the original list and continue chaining:
+			//	|	dojo.query("a").at(0).onclick(fn).end().forEach(function(n){
+			//	|		console.log(n); // all anchors on the page. 
+			//	|	})	
+			//
+			//	returns:
+			//		dojo.NodeList
+			var t = new this._NodeListCtor();
+			d.forEach(arguments, function(i){ 
+				if(i < 0){ i = this.length + i }
+				if(this[i]){ t.push(this[i]); }
+			}, this);
+			return t._stash(this); // dojo.NodeList
+		}
+
+	});
+
+	nl.events = [
+		// summary: list of all DOM events used in NodeList
+		"blur", "focus", "change", "click", "error", "keydown", "keypress",
+		"keyup", "load", "mousedown", "mouseenter", "mouseleave", "mousemove",
+		"mouseout", "mouseover", "mouseup", "submit"
+	];
+	
+	// FIXME: pseudo-doc the above automatically generated on-event functions
+
+	// syntactic sugar for DOM events
+	d.forEach(nl.events, function(evt){
+			var _oe = "on" + evt;
+			nlp[_oe] = function(a, b){
+				return this.connect(_oe, a, b);
+			}
+				// FIXME: should these events trigger publishes?
+				/*
+				return (a ? this.connect(_oe, a, b) :
+							this.forEach(function(n){
+								// FIXME:
+								//		listeners get buried by
+								//		addEventListener and can't be dug back
+								//		out to be triggered externally.
+								// see:
+								//		http://developer.mozilla.org/en/docs/DOM:element
+
+								console.log(n, evt, _oe);
+
+								// FIXME: need synthetic event support!
+								var _e = { target: n, faux: true, type: evt };
+								// dojo._event_listener._synthesizeEvent({}, { target: n, faux: true, type: evt });
+								try{ n[evt](_e); }catch(e){ console.log(e); }
+								try{ n[_oe](_e); }catch(e){ console.log(e); }
+							})
+				);
+				*/
+		}
+	);
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 })();
-}
+//>>excludeEnd("webkitMobile");
diff --git a/dojo/_base/_loader/bootstrap.js b/dojo/_base/_loader/bootstrap.js
index 80930c7..419d55d 100644
--- a/dojo/_base/_loader/bootstrap.js
+++ b/dojo/_base/_loader/bootstrap.js
@@ -1,120 +1,505 @@
-/*
-	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
-*/
+/*=====
+// note:
+//		'djConfig' does not exist under 'dojo.*' so that it can be set before the
+//		'dojo' variable exists.
+// note:
+//		Setting any of these variables *after* the library has loaded does
+//		nothing at all.
 
+djConfig = {
+	// summary:
+	//		Application code can set the global 'djConfig' prior to loading
+	//		the library to override certain global settings for how dojo works.
+	//
+	// isDebug: Boolean
+	//		Defaults to `false`. If set to `true`, ensures that Dojo provides
+	//		extended debugging feedback via Firebug. If Firebug is not available
+	//		on your platform, setting `isDebug` to `true` will force Dojo to
+	//		pull in (and display) the version of Firebug Lite which is
+	//		integrated into the Dojo distribution, thereby always providing a
+	//		debugging/logging console when `isDebug` is enabled. Note that
+	//		Firebug's `console.*` methods are ALWAYS defined by Dojo. If
+	//		`isDebug` is false and you are on a platform without Firebug, these
+	//		methods will be defined as no-ops.
+	isDebug: false,
+	// debugAtAllCosts: Boolean
+	//		Defaults to `false`. If set to `true`, this triggers an alternate
+	//		mode of the package system in which dependencies are detected and
+	//		only then are resources evaluated in dependency order via
+	//		`<script>` tag inclusion. This may double-request resources and
+	//		cause problems with scripts which expect `dojo.require()` to
+	//		preform synchronously. `debugAtAllCosts` can be an invaluable
+	//		debugging aid, but when using it, ensure that all code which
+	//		depends on Dojo modules is wrapped in `dojo.addOnLoad()` handlers.
+	//		Due to the somewhat unpredictable side-effects of using
+	//		`debugAtAllCosts`, it is strongly recommended that you enable this
+	//		flag as a last resort. `debugAtAllCosts` has no effect when loading
+	//		resources across domains. For usage information, see the
+	//		[Dojo Book](http://dojotoolkit.org/book/book-dojo/part-4-meta-dojo-making-your-dojo-code-run-faster-and-better/debugging-facilities/deb)
+	debugAtAllCosts: false,
+	// locale: String
+	//		The locale to assume for loading localized resources in this page,
+	//		specified according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt).
+	//		Must be specified entirely in lowercase, e.g. `en-us` and `zh-cn`.
+	//		See the documentation for `dojo.i18n` and `dojo.requireLocalization`
+	//		for details on loading localized resources. If no locale is specified,
+	//		Dojo assumes the locale of the user agent, according to `navigator.userLanguage`
+	//		or `navigator.language` properties.
+	locale: undefined,
+	// extraLocale: Array
+	//		No default value. Specifies additional locales whose
+	//		resources should also be loaded alongside the default locale when
+	//		calls to `dojo.requireLocalization()` are processed.
+	extraLocale: undefined,
+	// baseUrl: String
+	//		The directory in which `dojo.js` is located. Under normal
+	//		conditions, Dojo auto-detects the correct location from which it
+	//		was loaded. You may need to manually configure `baseUrl` in cases
+	//		where you have renamed `dojo.js` or in which `<base>` tags confuse
+	//		some browsers (e.g. IE 6). The variable `dojo.baseUrl` is assigned
+	//		either the value of `djConfig.baseUrl` if one is provided or the
+	//		auto-detected root if not. Other modules are located relative to
+	//		this path. The path should end in a slash.
+	baseUrl: undefined,
+	// modulePaths: Object
+	//		A map of module names to paths relative to `dojo.baseUrl`. The
+	//		key/value pairs correspond directly to the arguments which
+	//		`dojo.registerModulePath` accepts. Specifiying
+	//		`djConfig.modulePaths = { "foo": "../../bar" }` is the equivalent
+	//		of calling `dojo.registerModulePath("foo", "../../bar");`. Multiple
+	//		modules may be configured via `djConfig.modulePaths`.
+	modulePaths: {},
+	// afterOnLoad: Boolean 
+	//		Indicates Dojo was added to the page after the page load. In this case
+	//		Dojo will not wait for the page DOMContentLoad/load events and fire
+	//		its dojo.addOnLoad callbacks after making sure all outstanding
+	//		dojo.required modules have loaded. Only works with a built dojo.js,
+	//		it does not work the dojo.js directly from source control.
+	afterOnLoad: false,
+	// addOnLoad: Function or Array
+	//		Adds a callback via dojo.addOnLoad. Useful when Dojo is added after
+	//		the page loads and djConfig.afterOnLoad is true. Supports the same
+	//		arguments as dojo.addOnLoad. When using a function reference, use
+	//		`djConfig.addOnLoad = function(){};`. For object with function name use
+	//		`djConfig.addOnLoad = [myObject, "functionName"];` and for object with
+	//		function reference use
+	//		`djConfig.addOnLoad = [myObject, function(){}];`
+	addOnLoad: null,
+	// require: Array
+	//		An array of module names to be loaded immediately after dojo.js has been included
+	//		in a page.
+	require: [],
+	// defaultDuration: Array
+	//		Default duration, in milliseconds, for wipe and fade animations within dijits.
+	//		Assigned to dijit.defaultDuration.
+	defaultDuration: 200,
+	// dojoBlankHtmlUrl: String
+	//		Used by some modules to configure an empty iframe. Used by dojo.io.iframe and
+	//		dojo.back, and dijit popup support in IE where an iframe is needed to make sure native
+	//		controls do not bleed through the popups. Normally this configuration variable 
+	//		does not need to be set, except when using cross-domain/CDN Dojo builds.
+	//		Save dojo/resources/blank.html to your domain and set `djConfig.dojoBlankHtmlUrl`
+	//		to the path on your domain your copy of blank.html.
+	dojoBlankHtmlUrl: undefined,
+	//	ioPublish: Boolean?
+	//		Set this to true to enable publishing of topics for the different phases of
+	// 		IO operations. Publishing is done via dojo.publish. See dojo.__IoPublish for a list
+	// 		of topics that are published.
+	ioPublish: false,
+	//  useCustomLogger: Anything?
+	//		If set to a value that evaluates to true such as a string or array and
+	//		isDebug is true and Firebug is not available or running, then it bypasses
+	//		the creation of Firebug Lite allowing you to define your own console object.
+	useCustomLogger: undefined,
+	// transparentColor: Array
+	//		Array containing the r, g, b components used as transparent color in dojo.Color;
+	//		if undefined, [255,255,255] (white) will be used.
+	transparentColor: undefined,
+	// skipIeDomLoaded: Boolean
+	//		For IE only, skip the DOMContentLoaded hack used. Sometimes it can cause an Operation
+	//		Aborted error if the rest of the page triggers script defers before the DOM is ready.
+	//		If this is config value is set to true, then dojo.addOnLoad callbacks will not be
+	//		triggered until the page load event, which is after images and iframes load. If you
+	//		want to trigger the callbacks sooner, you can put a script block in the bottom of
+	//		your HTML that calls dojo._loadInit();. If you are using multiversion support, change
+	//		"dojo." to the appropriate scope name for dojo.
+	skipIeDomLoaded: false
+}
+=====*/
 
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 (function(){
-if(typeof this["loadFirebugConsole"]=="function"){
-this["loadFirebugConsole"]();
-}else{
-this.console=this.console||{};
-var cn=["assert","count","debug","dir","dirxml","error","group","groupEnd","info","profile","profileEnd","time","timeEnd","trace","warn","log"];
-var i=0,tn;
-while((tn=cn[i++])){
-if(!console[tn]){
-(function(){
-var _1=tn+"";
-console[_1]=("log" in console)?function(){
-var a=Array.apply({},arguments);
-a.unshift(_1+":");
-console["log"](a.join(" "));
-}:function(){
-};
-console[_1]._fake=true;
-})();
-}
-}
-}
-if(typeof dojo=="undefined"){
-dojo={_scopeName:"dojo",_scopePrefix:"",_scopePrefixArgs:"",_scopeSuffix:"",_scopeMap:{},_scopeMapRev:{}};
-}
-var d=dojo;
-if(typeof dijit=="undefined"){
-dijit={_scopeName:"dijit"};
-}
-if(typeof dojox=="undefined"){
-dojox={_scopeName:"dojox"};
-}
-if(!d._scopeArgs){
-d._scopeArgs=[dojo,dijit,dojox];
-}
-d.global=this;
-d.config={isDebug:false,debugAtAllCosts:false};
-if(typeof djConfig!="undefined"){
-for(var _2 in djConfig){
-d.config[_2]=djConfig[_2];
-}
-}
-dojo.locale=d.config.locale;
-var _3="$Rev: 21629 $".match(/\d+/);
-dojo.version={major:1,minor:4,patch:3,flag:"",revision:_3?+_3[0]:NaN,toString:function(){
-with(d.version){
-return major+"."+minor+"."+patch+flag+" ("+revision+")";
-}
-}};
-if(typeof OpenAjax!="undefined"){
-OpenAjax.hub.registerLibrary(dojo._scopeName,"http://dojotoolkit.org",d.version.toString());
-}
-var _4,_5,_6={};
-for(var i in {toString:1}){
-_4=[];
-break;
-}
-dojo._extraNames=_4=_4||["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"];
-_5=_4.length;
-dojo._mixin=function(_7,_8){
-var _9,s,i;
-for(_9 in _8){
-s=_8[_9];
-if(!(_9 in _7)||(_7[_9]!==s&&(!(_9 in _6)||_6[_9]!==s))){
-_7[_9]=s;
-}
-}
-if(_5&&_8){
-for(i=0;i<_5;++i){
-_9=_4[i];
-s=_8[_9];
-if(!(_9 in _7)||(_7[_9]!==s&&(!(_9 in _6)||_6[_9]!==s))){
-_7[_9]=s;
-}
-}
-}
-return _7;
-};
-dojo.mixin=function(_a,_b){
-if(!_a){
-_a={};
-}
-for(var i=1,l=arguments.length;i<l;i++){
-d._mixin(_a,arguments[i]);
-}
-return _a;
-};
-dojo._getProp=function(_c,_d,_e){
-var _f=_e||d.global;
-for(var i=0,p;_f&&(p=_c[i]);i++){
-if(i==0&&d._scopeMap[p]){
-p=d._scopeMap[p];
-}
-_f=(p in _f?_f[p]:(_d?_f[p]={}:undefined));
+//>>excludeEnd("webkitMobile");
+	// firebug stubs
+
+	if(typeof this["loadFirebugConsole"] == "function"){
+		// for Firebug 1.2
+		this["loadFirebugConsole"]();
+	}else{
+		this.console = this.console || {};
+
+		//	Be careful to leave 'log' always at the end
+		var cn = [
+			"assert", "count", "debug", "dir", "dirxml", "error", "group",
+			"groupEnd", "info", "profile", "profileEnd", "time", "timeEnd",
+			"trace", "warn", "log"
+		];
+		var i=0, tn;
+		while((tn=cn[i++])){
+			if(!console[tn]){
+				(function(){
+					var tcn = tn+"";
+					console[tcn] = ('log' in console) ? function(){
+						var a = Array.apply({}, arguments);
+						a.unshift(tcn+":");
+						console["log"](a.join(" "));
+					} : function(){}
+					console[tcn]._fake = true;
+				})();
+			}
+		}
+	}
+
+	//TODOC:  HOW TO DOC THIS?
+	// dojo is the root variable of (almost all) our public symbols -- make sure it is defined.
+	if(typeof dojo == "undefined"){
+		dojo = {
+			_scopeName: "dojo",
+			_scopePrefix: "",
+			_scopePrefixArgs: "",
+			_scopeSuffix: "",
+			_scopeMap: {},
+			_scopeMapRev: {}
+		};
+	}
+
+	var d = dojo;
+
+	//Need placeholders for dijit and dojox for scoping code.
+	if(typeof dijit == "undefined"){
+		dijit = {_scopeName: "dijit"};
+	}
+	if(typeof dojox == "undefined"){
+		dojox = {_scopeName: "dojox"};
+	}
+
+	if(!d._scopeArgs){
+		d._scopeArgs = [dojo, dijit, dojox];
+	}
+
+/*=====
+dojo.global = {
+	//	summary:
+	//		Alias for the global scope
+	//		(e.g. the window object in a browser).
+	//	description:
+	//		Refer to 'dojo.global' rather than referring to window to ensure your
+	//		code runs correctly in contexts other than web browsers (e.g. Rhino on a server).
 }
-return _f;
-};
-dojo.setObject=function(_10,_11,_12){
-var _13=_10.split("."),p=_13.pop(),obj=d._getProp(_13,true,_12);
-return obj&&p?(obj[p]=_11):undefined;
-};
-dojo.getObject=function(_14,_15,_16){
-return d._getProp(_14.split("."),_15,_16);
-};
-dojo.exists=function(_17,obj){
-return !!d.getObject(_17,false,obj);
-};
-dojo["eval"]=function(_18){
-return d.global.eval?d.global.eval(_18):eval(_18);
-};
-d.deprecated=d.experimental=function(){
-};
+=====*/
+	d.global = this;
+
+	d.config =/*===== djConfig = =====*/{
+		isDebug: false,
+		debugAtAllCosts: false
+	};
+
+	if(typeof djConfig != "undefined"){
+		for(var opt in djConfig){
+			d.config[opt] = djConfig[opt];
+		}
+	}
+
+/*=====
+	// Override locale setting, if specified
+	dojo.locale = {
+		// summary: the locale as defined by Dojo (read-only)
+	};
+=====*/
+	dojo.locale = d.config.locale;
+
+	var rev = "$Rev: 22487 $".match(/\d+/);
+
+/*=====
+	dojo.version = function(){
+		// summary:
+		//		Version number of the Dojo Toolkit
+		// major: Integer
+		//		Major version. If total version is "1.2.0beta1", will be 1
+		// minor: Integer
+		//		Minor version. If total version is "1.2.0beta1", will be 2
+		// patch: Integer
+		//		Patch version. If total version is "1.2.0beta1", will be 0
+		// flag: String
+		//		Descriptor flag. If total version is "1.2.0beta1", will be "beta1"
+		// revision: Number
+		//		The SVN rev from which dojo was pulled
+		this.major = 0;
+		this.minor = 0;
+		this.patch = 0;
+		this.flag = "";
+		this.revision = 0;
+	}
+=====*/
+	dojo.version = {
+		major: 1, minor: 5, patch: 0, flag: "",
+		revision: rev ? +rev[0] : NaN,
+		toString: function(){
+			with(d.version){
+				return major + "." + minor + "." + patch + flag + " (" + revision + ")";	// String
+			}
+		}
+	}
+
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	// Register with the OpenAjax hub
+	if(typeof OpenAjax != "undefined"){
+		OpenAjax.hub.registerLibrary(dojo._scopeName, "http://dojotoolkit.org", d.version.toString());
+	}
+	//>>excludeEnd("webkitMobile");
+
+	var extraNames, extraLen, empty = {};
+	for(var i in {toString: 1}){ extraNames = []; break; }
+	dojo._extraNames = extraNames = extraNames || ["hasOwnProperty", "valueOf", "isPrototypeOf",
+		"propertyIsEnumerable", "toLocaleString", "toString", "constructor"];
+	extraLen = extraNames.length;
+
+	dojo._mixin = function(/*Object*/ target, /*Object*/ source){
+		// summary:
+		//		Adds all properties and methods of source to target. This addition
+		//		is "prototype extension safe", so that instances of objects
+		//		will not pass along prototype defaults.
+		var name, s, i;
+		for(name in source){
+			// the "tobj" condition avoid copying properties in "source"
+			// inherited from Object.prototype.  For example, if target has a custom
+			// toString() method, don't overwrite it with the toString() method
+			// that source inherited from Object.prototype
+			s = source[name];
+			if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
+				target[name] = s;
+			}
+		}
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		// IE doesn't recognize some custom functions in for..in
+		if(extraLen && source){
+			for(i = 0; i < extraLen; ++i){
+				name = extraNames[i];
+				s = source[name];
+				if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
+					target[name] = s;
+				}
+			}
+		}
+		//>>excludeEnd("webkitMobile");
+		return target; // Object
+	}
+
+	dojo.mixin = function(/*Object*/obj, /*Object...*/props){
+		// summary:
+		//		Adds all properties and methods of props to obj and returns the
+		//		(now modified) obj.
+		//	description:
+		//		`dojo.mixin` can mix multiple source objects into a
+		//		destination object which is then returned. Unlike regular
+		//		`for...in` iteration, `dojo.mixin` is also smart about avoiding
+		//		extensions which other toolkits may unwisely add to the root
+		//		object prototype
+		//	obj:
+		//		The object to mix properties into. Also the return value.
+		//	props:
+		//		One or more objects whose values are successively copied into
+		//		obj. If more than one of these objects contain the same value,
+		//		the one specified last in the function call will "win".
+		//	example:
+		//		make a shallow copy of an object
+		//	|	var copy = dojo.mixin({}, source);
+		//	example:
+		//		many class constructors often take an object which specifies
+		//		values to be configured on the object. In this case, it is
+		//		often simplest to call `dojo.mixin` on the `this` object:
+		//	|	dojo.declare("acme.Base", null, {
+		//	|		constructor: function(properties){
+		//	|			// property configuration:
+		//	|			dojo.mixin(this, properties);
+		//	|	
+		//	|			console.log(this.quip);
+		//	|			//  ...
+		//	|		},
+		//	|		quip: "I wasn't born yesterday, you know - I've seen movies.",
+		//	|		// ...
+		//	|	});
+		//	|
+		//	|	// create an instance of the class and configure it
+		//	|	var b = new acme.Base({quip: "That's what it does!" });
+		//	example:
+		//		copy in properties from multiple objects
+		//	|	var flattened = dojo.mixin(
+		//	|		{
+		//	|			name: "Frylock",
+		//	|			braces: true
+		//	|		},
+		//	|		{
+		//	|			name: "Carl Brutanananadilewski"
+		//	|		}
+		//	|	);
+		//	|	
+		//	|	// will print "Carl Brutanananadilewski"
+		//	|	console.log(flattened.name);
+		//	|	// will print "true"
+		//	|	console.log(flattened.braces);
+		if(!obj){ obj = {}; }
+		for(var i=1, l=arguments.length; i<l; i++){
+			d._mixin(obj, arguments[i]);
+		}
+		return obj; // Object
+	}
+
+	dojo._getProp = function(/*Array*/parts, /*Boolean*/create, /*Object*/context){
+		var obj=context || d.global;
+		for(var i=0, p; obj && (p=parts[i]); i++){
+			if(i == 0 && d._scopeMap[p]){
+				p = d._scopeMap[p];
+			}
+			obj = (p in obj ? obj[p] : (create ? obj[p]={} : undefined));
+		}
+		return obj; // mixed
+	}
+
+	dojo.setObject = function(/*String*/name, /*Object*/value, /*Object?*/context){
+		// summary:
+		//		Set a property from a dot-separated string, such as "A.B.C"
+		//	description:
+		//		Useful for longer api chains where you have to test each object in
+		//		the chain, or when you have an object reference in string format.
+		//		Objects are created as needed along `path`. Returns the passed
+		//		value if setting is successful or `undefined` if not.
+		//	name:
+		//		Path to a property, in the form "A.B.C".
+		//	context:
+		//		Optional. Object to use as root of path. Defaults to
+		//		`dojo.global`.
+		//	example:
+		//		set the value of `foo.bar.baz`, regardless of whether
+		//		intermediate objects already exist:
+		//	|	dojo.setObject("foo.bar.baz", value);
+		//	example:
+		//		without `dojo.setObject`, we often see code like this:
+		//	|	// ensure that intermediate objects are available
+		//	|	if(!obj["parent"]){ obj.parent = {}; }
+		//	|	if(!obj.parent["child"]){ obj.parent.child= {}; }
+		//	|	// now we can safely set the property
+		//	|	obj.parent.child.prop = "some value";
+		//		wheras with `dojo.setObject`, we can shorten that to:
+		//	|	dojo.setObject("parent.child.prop", "some value", obj);
+		var parts=name.split("."), p=parts.pop(), obj=d._getProp(parts, true, context);
+		return obj && p ? (obj[p]=value) : undefined; // Object
+	}
+
+	dojo.getObject = function(/*String*/name, /*Boolean?*/create, /*Object?*/context){
+		// summary:
+		//		Get a property from a dot-separated string, such as "A.B.C"
+		//	description:
+		//		Useful for longer api chains where you have to test each object in
+		//		the chain, or when you have an object reference in string format.
+		//	name:
+		//		Path to an property, in the form "A.B.C".
+		//	create:
+		//		Optional. Defaults to `false`. If `true`, Objects will be
+		//		created at any point along the 'path' that is undefined.
+		//	context:
+		//		Optional. Object to use as root of path. Defaults to
+		//		'dojo.global'. Null may be passed.
+		return d._getProp(name.split("."), create, context); // Object
+	}
+
+	dojo.exists = function(/*String*/name, /*Object?*/obj){
+		//	summary:
+		//		determine if an object supports a given method
+		//	description:
+		//		useful for longer api chains where you have to test each object in
+		//		the chain. Useful only for object and method detection.
+		//		Not useful for testing generic properties on an object.
+		//		In particular, dojo.exists("foo.bar") when foo.bar = ""
+		//		will return false. Use ("bar" in foo) to test for those cases.
+		//	name:
+		//		Path to an object, in the form "A.B.C".
+		//	obj:
+		//		Object to use as root of path. Defaults to
+		//		'dojo.global'. Null may be passed.
+		//	example:
+		//	|	// define an object
+		//	|	var foo = {
+		//	|		bar: { }
+		//	|	};
+		//	|
+		//	|	// search the global scope
+		//	|	dojo.exists("foo.bar"); // true
+		//	|	dojo.exists("foo.bar.baz"); // false
+		//	|
+		//	|	// search from a particular scope
+		//	|	dojo.exists("bar", foo); // true
+		//	|	dojo.exists("bar.baz", foo); // false
+		return !!d.getObject(name, false, obj); // Boolean
+	}
+
+	dojo["eval"] = function(/*String*/ scriptFragment){
+		//	summary:
+		//		A legacy method created for use exclusively by internal Dojo methods. Do not use
+		//		this method directly, the behavior of this eval will differ from the normal
+		//		browser eval.
+		//	description:
+		//		Placed in a separate function to minimize size of trapped
+		//		exceptions. Calling eval() directly from some other scope may
+		//		complicate tracebacks on some platforms.
+		//	returns:
+		//		The result of the evaluation. Often `undefined`
+		return d.global.eval ? d.global.eval(scriptFragment) : eval(scriptFragment); 	// Object
+	}
+
+	/*=====
+		dojo.deprecated = function(behaviour, extra, removal){
+			//	summary:
+			//		Log a debug message to indicate that a behavior has been
+			//		deprecated.
+			//	behaviour: String
+			//		The API or behavior being deprecated. Usually in the form
+			//		of "myApp.someFunction()".
+			//	extra: String?
+			//		Text to append to the message. Often provides advice on a
+			//		new function or facility to achieve the same goal during
+			//		the deprecation period.
+			//	removal: String?
+			//		Text to indicate when in the future the behavior will be
+			//		removed. Usually a version number.
+			//	example:
+			//	|	dojo.deprecated("myApp.getTemp()", "use myApp.getLocaleTemp() instead", "1.0");
+		}
+
+		dojo.experimental = function(moduleName, extra){
+			//	summary: Marks code as experimental.
+			//	description:
+			//	 	This can be used to mark a function, file, or module as
+			//	 	experimental.  Experimental code is not ready to be used, and the
+			//	 	APIs are subject to change without notice.  Experimental code may be
+			//	 	completed deleted without going through the normal deprecation
+			//	 	process.
+			//	moduleName: String
+			//	 	The name of a module, or the name of a module file or a specific
+			//	 	function
+			//	extra: String?
+			//	 	some additional message for the user
+			//	example:
+			//	|	dojo.experimental("dojo.data.Result");
+			//	example:
+			//	|	dojo.experimental("dojo.weather.toKelvin()", "PENDING approval from NOAA");
+		}
+	=====*/
+
+	//Real functions declared in dojo._firebug.firebug.
+	d.deprecated = d.experimental = function(){};
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 })();
+//>>excludeEnd("webkitMobile");
+// vim:ai:ts=4:noet
diff --git a/dojo/_base/_loader/hostenv_browser.js b/dojo/_base/_loader/hostenv_browser.js
index 32feb26..0b6808e 100644
--- a/dojo/_base/_loader/hostenv_browser.js
+++ b/dojo/_base/_loader/hostenv_browser.js
@@ -1,228 +1,487 @@
-/*
-	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
-*/
-
-
-if(typeof window!="undefined"){
-dojo.isBrowser=true;
-dojo._name="browser";
-(function(){
-var d=dojo;
-if(document&&document.getElementsByTagName){
-var _1=document.getElementsByTagName("script");
-var _2=/dojo(\.xd)?\.js(\W|$)/i;
-for(var i=0;i<_1.length;i++){
-var _3=_1[i].getAttribute("src");
-if(!_3){
-continue;
-}
-var m=_3.match(_2);
-if(m){
-if(!d.config.baseUrl){
-d.config.baseUrl=_3.substring(0,m.index);
-}
-var _4=_1[i].getAttribute("djConfig");
-if(_4){
-var _5=eval("({ "+_4+" })");
-for(var x in _5){
-dojo.config[x]=_5[x];
-}
-}
-break;
-}
-}
-}
-d.baseUrl=d.config.baseUrl;
-var n=navigator;
-var _6=n.userAgent,_7=n.appVersion,tv=parseFloat(_7);
-if(_6.indexOf("Opera")>=0){
-d.isOpera=tv;
-}
-if(_6.indexOf("AdobeAIR")>=0){
-d.isAIR=1;
-}
-d.isKhtml=(_7.indexOf("Konqueror")>=0)?tv:0;
-d.isWebKit=parseFloat(_6.split("WebKit/")[1])||undefined;
-d.isChrome=parseFloat(_6.split("Chrome/")[1])||undefined;
-d.isMac=_7.indexOf("Macintosh")>=0;
-var _8=Math.max(_7.indexOf("WebKit"),_7.indexOf("Safari"),0);
-if(_8&&!dojo.isChrome){
-d.isSafari=parseFloat(_7.split("Version/")[1]);
-if(!d.isSafari||parseFloat(_7.substr(_8+7))<=419.3){
-d.isSafari=2;
-}
-}
-if(_6.indexOf("Gecko")>=0&&!d.isKhtml&&!d.isWebKit){
-d.isMozilla=d.isMoz=tv;
-}
-if(d.isMoz){
-d.isFF=parseFloat(_6.split("Firefox/")[1]||_6.split("Minefield/")[1])||undefined;
-}
-if(document.all&&!d.isOpera){
-d.isIE=parseFloat(_7.split("MSIE ")[1])||undefined;
-var _9=document.documentMode;
-if(_9&&_9!=5&&Math.floor(d.isIE)!=_9){
-d.isIE=_9;
-}
-}
-if(dojo.isIE&&window.location.protocol==="file:"){
-dojo.config.ieForceActiveXXhr=true;
-}
-d.isQuirks=document.compatMode=="BackCompat";
-d.locale=dojo.config.locale||(d.isIE?n.userLanguage:n.language).toLowerCase();
-d._XMLHTTP_PROGIDS=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"];
-d._xhrObj=function(){
-var _a,_b;
-if(!dojo.isIE||!dojo.config.ieForceActiveXXhr){
-try{
-_a=new XMLHttpRequest();
-}
-catch(e){
-}
-}
-if(!_a){
-for(var i=0;i<3;++i){
-var _c=d._XMLHTTP_PROGIDS[i];
-try{
-_a=new ActiveXObject(_c);
-}
-catch(e){
-_b=e;
-}
-if(_a){
-d._XMLHTTP_PROGIDS=[_c];
-break;
-}
-}
-}
-if(!_a){
-throw new Error("XMLHTTP not available: "+_b);
-}
-return _a;
-};
-d._isDocumentOk=function(_d){
-var _e=_d.status||0,lp=location.protocol;
-return (_e>=200&&_e<300)||_e==304||_e==1223||(!_e&&(lp=="file:"||lp=="chrome:"||lp=="app:"));
+/*=====
+dojo.isBrowser = {
+	//	example:
+	//	|	if(dojo.isBrowser){ ... }
 };
-var _f=window.location+"";
-var _10=document.getElementsByTagName("base");
-var _11=(_10&&_10.length>0);
-d._getText=function(uri,_12){
-var _13=d._xhrObj();
-if(!_11&&dojo._Url){
-uri=(new dojo._Url(_f,uri)).toString();
-}
-if(d.config.cacheBust){
-uri+="";
-uri+=(uri.indexOf("?")==-1?"?":"&")+String(d.config.cacheBust).replace(/\W+/g,"");
-}
-_13.open("GET",uri,false);
-try{
-_13.send(null);
-if(!d._isDocumentOk(_13)){
-var err=Error("Unable to load "+uri+" status:"+_13.status);
-err.status=_13.status;
-err.responseText=_13.responseText;
-throw err;
-}
-}
-catch(e){
-if(_12){
-return null;
-}
-throw e;
-}
-return _13.responseText;
-};
-var _14=window;
-var _15=function(_16,fp){
-var _17=_14.attachEvent||_14.addEventListener;
-_16=_14.attachEvent?_16:_16.substring(2);
-_17(_16,function(){
-fp.apply(_14,arguments);
-},false);
-};
-d._windowUnloaders=[];
-d.windowUnloaded=function(){
-var mll=d._windowUnloaders;
-while(mll.length){
-(mll.pop())();
-}
-};
-var _18=0;
-d.addOnWindowUnload=function(obj,_19){
-d._onto(d._windowUnloaders,obj,_19);
-if(!_18){
-_18=1;
-_15("onunload",d.windowUnloaded);
-}
+
+dojo.isFF = {
+	//	example:
+	//	|	if(dojo.isFF > 1){ ... }
 };
-var _1a=0;
-d.addOnUnload=function(obj,_1b){
-d._onto(d._unloaders,obj,_1b);
-if(!_1a){
-_1a=1;
-_15("onbeforeunload",dojo.unloaded);
-}
+
+dojo.isIE = {
+	// example:
+	//	|	if(dojo.isIE > 6){
+	//	|		// we are IE7
+	// 	|	}
 };
-})();
-dojo._initFired=false;
-dojo._loadInit=function(e){
-if(!dojo._initFired){
-dojo._initFired=true;
-if(!dojo.config.afterOnLoad&&window.detachEvent){
-window.detachEvent("onload",dojo._loadInit);
-}
-if(dojo._inFlightCount==0){
-dojo._modulesLoaded();
-}
-}
+
+dojo.isSafari = {
+	//	example:
+	//	|	if(dojo.isSafari){ ... }
+	//	example: 
+	//		Detect iPhone:
+	//	|	if(dojo.isSafari && navigator.userAgent.indexOf("iPhone") != -1){ 
+	//	|		// we are iPhone. Note, iPod touch reports "iPod" above and fails this test.
+	//	|	}
 };
-if(!dojo.config.afterOnLoad){
-if(document.addEventListener){
-document.addEventListener("DOMContentLoaded",dojo._loadInit,false);
-window.addEventListener("load",dojo._loadInit,false);
-}else{
-if(window.attachEvent){
-window.attachEvent("onload",dojo._loadInit);
-}
-}
-}
-if(dojo.isIE){
-if(!dojo.config.afterOnLoad&&!dojo.config.skipIeDomLoaded){
-document.write("<scr"+"ipt defer src=\"//:\" "+"onreadystatechange=\"if(this.readyState=='complete'){"+dojo._scopeName+"._loadInit();}\">"+"</scr"+"ipt>");
-}
-try{
-document.namespaces.add("v","urn:schemas-microsoft-com:vml");
-var vmlElems=["*","group","roundrect","oval","shape","rect","imagedata"],i=0,l=1,s=document.createStyleSheet();
-if(dojo.isIE>=8){
-i=1;
-l=vmlElems.length;
-}
-for(;i<l;++i){
-s.addRule("v\\:"+vmlElems[i],"behavior:url(#default#VML); display:inline-block");
-}
-}
-catch(e){
-}
-}
-}
+
+dojo = {
+	// isBrowser: Boolean
+	//		True if the client is a web-browser
+	isBrowser: true,
+	//	isFF: Number | undefined
+	//		Version as a Number if client is FireFox. undefined otherwise. Corresponds to
+	//		major detected FireFox version (1.5, 2, 3, etc.)
+	isFF: 2,
+	//	isIE: Number | undefined
+	//		Version as a Number if client is MSIE(PC). undefined otherwise. Corresponds to
+	//		major detected IE version (6, 7, 8, etc.)
+	isIE: 6,
+	//	isKhtml: Number | undefined
+	//		Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major
+	//		detected version.
+	isKhtml: 0,
+	//	isWebKit: Number | undefined
+	//		Version as a Number if client is a WebKit-derived browser (Konqueror,
+	//		Safari, Chrome, etc.). undefined otherwise.
+	isWebKit: 0,
+	//	isMozilla: Number | undefined
+	//		Version as a Number if client is a Mozilla-based browser (Firefox,
+	//		SeaMonkey). undefined otherwise. Corresponds to major detected version.
+	isMozilla: 0,
+	//	isOpera: Number | undefined
+	//		Version as a Number if client is Opera. undefined otherwise. Corresponds to
+	//		major detected version.
+	isOpera: 0,
+	//	isSafari: Number | undefined
+	//		Version as a Number if client is Safari or iPhone. undefined otherwise.
+	isSafari: 0,
+	//	isChrome: Number | undefined
+	//		Version as a Number if client is Chrome browser. undefined otherwise.
+	isChrome: 0
+	//	isMac: Boolean
+	//		True if the client runs on Mac
+}
+=====*/
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+if(typeof window != 'undefined'){
+//>>excludeEnd("webkitMobile");
+	dojo.isBrowser = true;
+	dojo._name = "browser";
+
+
+	// attempt to figure out the path to dojo if it isn't set in the config
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	(function(){
+		var d = dojo;
+//>>excludeEnd("webkitMobile");
+
+		// this is a scope protection closure. We set browser versions and grab
+		// the URL we were loaded from here.
+
+		// grab the node we were loaded from
+		if(document && document.getElementsByTagName){
+			var scripts = document.getElementsByTagName("script");
+			var rePkg = /dojo(\.xd)?\.js(\W|$)/i;
+			for(var i = 0; i < scripts.length; i++){
+				var src = scripts[i].getAttribute("src");
+				if(!src){ continue; }
+				var m = src.match(rePkg);
+				if(m){
+					// find out where we came from
+					if(!d.config.baseUrl){
+						d.config.baseUrl = src.substring(0, m.index);
+					}
+					// and find out if we need to modify our behavior
+					var cfg = scripts[i].getAttribute("djConfig");
+					if(cfg){
+						var cfgo = eval("({ "+cfg+" })");
+						for(var x in cfgo){
+							dojo.config[x] = cfgo[x];
+						}
+					}
+					break; // "first Dojo wins"
+				}
+			}
+		}
+		d.baseUrl = d.config.baseUrl;
+
+		// fill in the rendering support information in dojo.render.*
+		var n = navigator;
+		var dua = n.userAgent,
+			dav = n.appVersion,
+			tv = parseFloat(dav);
+
+		if(dua.indexOf("Opera") >= 0){ d.isOpera = tv; }
+		if(dua.indexOf("AdobeAIR") >= 0){ d.isAIR = 1; }
+		d.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : 0;
+		d.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined;
+		d.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined;
+		d.isMac = dav.indexOf("Macintosh") >= 0;
+
+		// safari detection derived from:
+		//		http://developer.apple.com/internet/safari/faq.html#anchor2
+		//		http://developer.apple.com/internet/safari/uamatrix.html
+		var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);
+		if(index && !dojo.isChrome){
+			// try to grab the explicit Safari version first. If we don't get
+			// one, look for less than 419.3 as the indication that we're on something
+			// "Safari 2-ish".
+			d.isSafari = parseFloat(dav.split("Version/")[1]);
+			if(!d.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){
+				d.isSafari = 2;
+			}
+		}
+
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		if(dua.indexOf("Gecko") >= 0 && !d.isKhtml && !d.isWebKit){ d.isMozilla = d.isMoz = tv; }
+		if(d.isMoz){
+			//We really need to get away from this. Consider a sane isGecko approach for the future.
+			d.isFF = parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined;
+		}
+		if(document.all && !d.isOpera){
+			d.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined;
+			//In cases where the page has an HTTP header or META tag with
+			//X-UA-Compatible, then it is in emulation mode.
+			//Make sure isIE reflects the desired version.
+			//document.documentMode of 5 means quirks mode.
+			//Only switch the value if documentMode's major version
+			//is different from isIE's major version.
+			var mode = document.documentMode;
+			if(mode && mode != 5 && Math.floor(d.isIE) != mode){
+				d.isIE = mode;
+			}
+		}
+
+		//Workaround to get local file loads of dojo to work on IE 7
+		//by forcing to not use native xhr.
+		if(dojo.isIE && window.location.protocol === "file:"){
+			dojo.config.ieForceActiveXXhr=true;
+		}
+		//>>excludeEnd("webkitMobile");
+
+		d.isQuirks = document.compatMode == "BackCompat";
+
+		// TODO: is the HTML LANG attribute relevant?
+		d.locale = dojo.config.locale || (d.isIE ? n.userLanguage : n.language).toLowerCase();
+
+		// These are in order of decreasing likelihood; this will change in time.
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		d._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
+		//>>excludeEnd("webkitMobile");
+
+		d._xhrObj = function(){
+			// summary: 
+			//		does the work of portably generating a new XMLHTTPRequest object.
+			var http, last_e;
+			//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+			if(!dojo.isIE || !dojo.config.ieForceActiveXXhr){
+			//>>excludeEnd("webkitMobile");
+				try{ http = new XMLHttpRequest(); }catch(e){}
+			//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+			}
+			if(!http){
+				for(var i=0; i<3; ++i){
+					var progid = d._XMLHTTP_PROGIDS[i];
+					try{
+						http = new ActiveXObject(progid);
+					}catch(e){
+						last_e = e;
+					}
+
+					if(http){
+						d._XMLHTTP_PROGIDS = [progid];  // so faster next time
+						break;
+					}
+				}
+			}
+			//>>excludeEnd("webkitMobile");
+
+			if(!http){
+				throw new Error("XMLHTTP not available: "+last_e);
+			}
+
+			return http; // XMLHTTPRequest instance
+		}
+
+		d._isDocumentOk = function(http){
+			var stat = http.status || 0,
+				lp = location.protocol;
+			return (stat >= 200 && stat < 300) || 	// Boolean
+				stat == 304 || 						// allow any 2XX response code
+				stat == 1223 || 						// get it out of the cache
+				// Internet Explorer mangled the status code OR we're Titanium/browser chrome/chrome extension requesting a local file
+				(!stat && (lp == "file:" || lp == "chrome:" || lp == "chrome-extension:" || lp == "app:") );
+		}
+
+		//See if base tag is in use.
+		//This is to fix http://trac.dojotoolkit.org/ticket/3973,
+		//but really, we need to find out how to get rid of the dojo._Url reference
+		//below and still have DOH work with the dojo.i18n test following some other
+		//test that uses the test frame to load a document (trac #2757).
+		//Opera still has problems, but perhaps a larger issue of base tag support
+		//with XHR requests (hasBase is true, but the request is still made to document
+		//path, not base path).
+		var owloc = window.location+"";
+		var base = document.getElementsByTagName("base");
+		var hasBase = (base && base.length > 0);
+
+		d._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){
+			// summary: Read the contents of the specified uri and return those contents.
+			// uri:
+			//		A relative or absolute uri. If absolute, it still must be in
+			//		the same "domain" as we are.
+			// fail_ok:
+			//		Default false. If fail_ok and loading fails, return null
+			//		instead of throwing.
+			// returns: The response text. null is returned when there is a
+			//		failure and failure is okay (an exception otherwise)
+
+			// NOTE: must be declared before scope switches ie. this._xhrObj()
+			var http = d._xhrObj();
+
+			if(!hasBase && dojo._Url){
+				uri = (new dojo._Url(owloc, uri)).toString();
+			}
+
+			if(d.config.cacheBust){
+				//Make sure we have a string before string methods are used on uri
+				uri += "";
+				uri += (uri.indexOf("?") == -1 ? "?" : "&") + String(d.config.cacheBust).replace(/\W+/g,"");
+			}
+
+			http.open('GET', uri, false);
+			try{
+				http.send(null);
+				if(!d._isDocumentOk(http)){
+					var err = Error("Unable to load "+uri+" status:"+ http.status);
+					err.status = http.status;
+					err.responseText = http.responseText;
+					throw err;
+				}
+			}catch(e){
+				if(fail_ok){ return null; } // null
+				// rethrow the exception
+				throw e;
+			}
+			return http.responseText; // String
+		}
+		
+
+		var _w = window;
+		var _handleNodeEvent = function(/*String*/evtName, /*Function*/fp){
+			// summary:
+			//		non-destructively adds the specified function to the node's
+			//		evtName handler.
+			// evtName: should be in the form "onclick" for "onclick" handlers.
+			// Make sure you pass in the "on" part.
+			var _a = _w.attachEvent || _w.addEventListener;
+			evtName = _w.attachEvent ? evtName : evtName.substring(2);
+			_a(evtName, function(){
+				fp.apply(_w, arguments);
+			}, false);
+		};
+
+
+		d._windowUnloaders = [];
+		
+		d.windowUnloaded = function(){
+			// summary:
+			//		signal fired by impending window destruction. You may use
+			//		dojo.addOnWindowUnload() to register a listener for this
+			//		event. NOTE: if you wish to dojo.connect() to this method
+			//		to perform page/application cleanup, be aware that this
+			//		event WILL NOT fire if no handler has been registered with
+			//		dojo.addOnWindowUnload. This behavior started in Dojo 1.3.
+			//		Previous versions always triggered dojo.windowUnloaded. See
+			//		dojo.addOnWindowUnload for more info.
+			var mll = d._windowUnloaders;
+			while(mll.length){
+				(mll.pop())();
+			}
+			d = null;
+		};
+
+		var _onWindowUnloadAttached = 0;
+		d.addOnWindowUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){
+			// summary:
+			//		registers a function to be triggered when window.onunload
+			//		fires. 
+			//	description:
+			//		The first time that addOnWindowUnload is called Dojo
+			//		will register a page listener to trigger your unload
+			//		handler with. Note that registering these handlers may
+			//		destory "fastback" page caching in browsers that support
+			//		it. Be careful trying to modify the DOM or access
+			//		JavaScript properties during this phase of page unloading:
+			//		they may not always be available. Consider
+			//		dojo.addOnUnload() if you need to modify the DOM or do
+			//		heavy JavaScript work since it fires at the eqivalent of
+			//		the page's "onbeforeunload" event.
+			// example:
+			//	|	dojo.addOnWindowUnload(functionPointer)
+			//	|	dojo.addOnWindowUnload(object, "functionName");
+			//	|	dojo.addOnWindowUnload(object, function(){ /* ... */});
+
+			d._onto(d._windowUnloaders, obj, functionName);
+			if(!_onWindowUnloadAttached){
+				_onWindowUnloadAttached = 1;
+				_handleNodeEvent("onunload", d.windowUnloaded);
+			}
+		};
+
+		var _onUnloadAttached = 0;
+		d.addOnUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){
+			// summary:
+			//		registers a function to be triggered when the page unloads.
+			//	description:
+			//		The first time that addOnUnload is called Dojo will
+			//		register a page listener to trigger your unload handler
+			//		with. 
+			//
+			//		In a browser enviroment, the functions will be triggered
+			//		during the window.onbeforeunload event. Be careful of doing
+			//		too much work in an unload handler. onbeforeunload can be
+			//		triggered if a link to download a file is clicked, or if
+			//		the link is a javascript: link. In these cases, the
+			//		onbeforeunload event fires, but the document is not
+			//		actually destroyed. So be careful about doing destructive
+			//		operations in a dojo.addOnUnload callback.
+			//
+			//		Further note that calling dojo.addOnUnload will prevent
+			//		browsers from using a "fast back" cache to make page
+			//		loading via back button instantaneous. 
+			// example:
+			//	|	dojo.addOnUnload(functionPointer)
+			//	|	dojo.addOnUnload(object, "functionName")
+			//	|	dojo.addOnUnload(object, function(){ /* ... */});
+
+			d._onto(d._unloaders, obj, functionName);
+			if(!_onUnloadAttached){
+				_onUnloadAttached = 1;
+				_handleNodeEvent("onbeforeunload", dojo.unloaded);
+			}
+		};
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	})();
+//>>excludeEnd("webkitMobile");
+
+	//START DOMContentLoaded
+	dojo._initFired = false;
+	dojo._loadInit = function(e){
+		if(dojo._scrollIntervalId){
+			clearInterval(dojo._scrollIntervalId);
+			dojo._scrollIntervalId = 0;
+		}
+
+		if(!dojo._initFired){
+			dojo._initFired = true;
+
+			//Help out IE to avoid memory leak.
+			if(!dojo.config.afterOnLoad && window.detachEvent){
+				window.detachEvent("onload", dojo._loadInit);
+			}
+
+			if(dojo._inFlightCount == 0){
+				dojo._modulesLoaded();
+			}
+		}
+	}
+
+	if(!dojo.config.afterOnLoad){		
+		if(document.addEventListener){
+			//Standards. Hooray! Assumption here that if standards based,
+			//it knows about DOMContentLoaded. It is OK if it does not, the fall through
+			//to window onload should be good enough.
+			document.addEventListener("DOMContentLoaded", dojo._loadInit, false);
+			window.addEventListener("load", dojo._loadInit, false);
+		}else if(window.attachEvent){
+			window.attachEvent("onload", dojo._loadInit);
+
+			//DOMContentLoaded approximation. Diego Perini found this MSDN article
+			//that indicates doScroll is available after DOM ready, so do a setTimeout
+			//to check when it is available.
+			//http://msdn.microsoft.com/en-us/library/ms531426.aspx
+			if(!dojo.config.skipIeDomLoaded && self === self.top){
+				dojo._scrollIntervalId = setInterval(function (){
+					try{
+						//When dojo is loaded into an iframe in an IE HTML Application 
+						//(HTA), such as in a selenium test, javascript in the iframe
+						//can't see anything outside of it, so self===self.top is true,
+						//but the iframe is not the top window and doScroll will be 
+						//available before document.body is set. Test document.body
+						//before trying the doScroll trick
+						if(document.body){
+							document.documentElement.doScroll("left");
+							dojo._loadInit();
+						}
+					}catch (e){}
+				}, 30);
+			}
+		}
+	}
+
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	if(dojo.isIE){
+		try{
+			(function(){
+				document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
+				var vmlElems = ["*", "group", "roundrect", "oval", "shape", "rect", "imagedata", "path", "textpath", "text"],
+					i = 0, l = 1, s = document.createStyleSheet();
+				if(dojo.isIE >= 8){
+					i = 1;
+					l = vmlElems.length;
+				}
+				for(; i < l; ++i){
+					s.addRule("v\\:" + vmlElems[i], "behavior:url(#default#VML); display:inline-block");
+				}
+			})();
+		}catch(e){}
+	}
+	//>>excludeEnd("webkitMobile");
+	//END DOMContentLoaded
+
+
+	/*
+	OpenAjax.subscribe("OpenAjax", "onload", function(){
+		if(dojo._inFlightCount == 0){
+			dojo._modulesLoaded();
+		}
+	});
+
+	OpenAjax.subscribe("OpenAjax", "onunload", function(){
+		dojo.unloaded();
+	});
+	*/
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+} //if (typeof window != 'undefined')
+
+//Register any module paths set up in djConfig. Need to do this
+//in the hostenvs since hostenv_browser can read djConfig from a
+//script tag's attribute.
 (function(){
-var mp=dojo.config["modulePaths"];
-if(mp){
-for(var _1c in mp){
-dojo.registerModulePath(_1c,mp[_1c]);
-}
-}
+//>>excludeEnd("webkitMobile");
+	var mp = dojo.config["modulePaths"];
+	if(mp){
+		for(var param in mp){
+			dojo.registerModulePath(param, mp[param]);
+		}
+	}
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 })();
+//>>excludeEnd("webkitMobile");
+
+//Load debug code if necessary.
 if(dojo.config.isDebug){
-dojo.require("dojo._firebug.firebug");
+	dojo.require("dojo._firebug.firebug");
 }
+
 if(dojo.config.debugAtAllCosts){
-dojo.config.useXDomain=true;
-dojo.require("dojo._base._loader.loader_xd");
-dojo.require("dojo._base._loader.loader_debug");
-dojo.require("dojo.i18n");
+	dojo.config.useXDomain = true;
+	dojo.require("dojo._base._loader.loader_xd");
+	dojo.require("dojo._base._loader.loader_debug");
+	dojo.require("dojo.i18n");
 }
diff --git a/dojo/_base/_loader/hostenv_ff_ext.js b/dojo/_base/_loader/hostenv_ff_ext.js
index e7ccc52..d99cf1a 100644
--- a/dojo/_base/_loader/hostenv_ff_ext.js
+++ b/dojo/_base/_loader/hostenv_ff_ext.js
@@ -1,175 +1,331 @@
-/*
-	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
-*/
+// a host environment specifically built for Mozilla extensions, but derived
+// from the browser host environment
+if(typeof window != 'undefined'){
+	dojo.isBrowser = true;
+	dojo._name = "browser";
 
 
-if(typeof window!="undefined"){
-dojo.isBrowser=true;
-dojo._name="browser";
-(function(){
-var d=dojo;
-d.baseUrl=d.config.baseUrl;
-var n=navigator;
-var _1=n.userAgent;
-var _2=n.appVersion;
-var tv=parseFloat(_2);
-d.isMozilla=d.isMoz=tv;
-if(d.isMoz){
-d.isFF=parseFloat(_1.split("Firefox/")[1])||undefined;
-}
-d.isQuirks=document.compatMode=="BackCompat";
-d.locale=dojo.config.locale||n.language.toLowerCase();
-d._xhrObj=function(){
-return new XMLHttpRequest();
-};
-var _3=d._loadUri;
-d._loadUri=function(_4,cb){
-var _5=["file:","chrome:","resource:"].some(function(_6){
-return String(_4).indexOf(_6)==0;
-});
-if(_5){
-var l=Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
-var _7=l.loadSubScript(_4,d.global);
-if(cb){
-cb(_7);
-}
-return true;
-}else{
-return _3.apply(d,arguments);
-}
-};
-d._isDocumentOk=function(_8){
-var _9=_8.status||0;
-return (_9>=200&&_9<300)||_9==304||_9==1223||(!_9&&(location.protocol=="file:"||location.protocol=="chrome:"));
-};
-var _a=false;
-d._getText=function(_b,_c){
-var _d=d._xhrObj();
-if(!_a&&dojo._Url){
-_b=(new dojo._Url(_b)).toString();
-}
-if(d.config.cacheBust){
-_b+="";
-_b+=(_b.indexOf("?")==-1?"?":"&")+String(d.config.cacheBust).replace(/\W+/g,"");
-}
-var _e=["file:","chrome:","resource:"].some(function(_f){
-return String(_b).indexOf(_f)==0;
-});
-if(_e){
-var _10=Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
-var _11=Components.classes["@mozilla.org/scriptableinputstream;1"].getService(Components.interfaces.nsIScriptableInputStream);
-var _12=_10.newChannel(_b,null,null);
-var _13=_12.open();
-_11.init(_13);
-var str=_11.read(_13.available());
-_11.close();
-_13.close();
-return str;
-}else{
-_d.open("GET",_b,false);
-try{
-_d.send(null);
-if(!d._isDocumentOk(_d)){
-var err=Error("Unable to load "+_b+" status:"+_d.status);
-err.status=_d.status;
-err.responseText=_d.responseText;
-throw err;
-}
-}
-catch(e){
-if(_c){
-return null;
-}
-throw e;
-}
-return _d.responseText;
-}
-};
-d._windowUnloaders=[];
-d.windowUnloaded=function(){
-var mll=d._windowUnloaders;
-while(mll.length){
-(mll.pop())();
-}
-};
-d.addOnWindowUnload=function(obj,_14){
-d._onto(d._windowUnloaders,obj,_14);
-};
-var _15=[];
-var _16=null;
-dojo._defaultContext=[window,document];
-dojo.pushContext=function(g,d){
-var old=[dojo.global,dojo.doc];
-_15.push(old);
-var n;
-if(!g&&!d){
-n=dojo._defaultContext;
-}else{
-n=[g,d];
-if(!d&&dojo.isString(g)){
-var t=document.getElementById(g);
-if(t.contentDocument){
-n=[t.contentWindow,t.contentDocument];
-}
-}
-}
-_16=n;
-dojo.setContext.apply(dojo,n);
-return old;
-};
-dojo.popContext=function(){
-var oc=_16;
-if(!_15.length){
-return oc;
-}
-dojo.setContext.apply(dojo,_15.pop());
-return oc;
-};
-dojo._inContext=function(g,d,f){
-var a=dojo._toArray(arguments);
-f=a.pop();
-if(a.length==1){
-d=null;
-}
-dojo.pushContext(g,d);
-var r=f();
-dojo.popContext();
-return r;
-};
-})();
-dojo._initFired=false;
-dojo._loadInit=function(e){
-dojo._initFired=true;
-var _17=(e&&e.type)?e.type.toLowerCase():"load";
-if(arguments.callee.initialized||(_17!="domcontentloaded"&&_17!="load")){
-return;
-}
-arguments.callee.initialized=true;
-if(dojo._inFlightCount==0){
-dojo._modulesLoaded();
-}
-};
-if(!dojo.config.afterOnLoad){
-window.addEventListener("DOMContentLoaded",function(e){
-dojo._loadInit(e);
-},false);
-}
-}
+	// FIXME: PORTME
+	//	http://developer.mozilla.org/en/mozIJSSubScriptLoader
+
+
+	// attempt to figure out the path to dojo if it isn't set in the config
+	(function(){
+		var d = dojo;
+		// this is a scope protection closure. We set browser versions and grab
+		// the URL we were loaded from here.
+
+		// FIXME: need to probably use a different reference to "document" to get the hosting XUL environment
+
+		d.baseUrl = d.config.baseUrl;
+
+		// fill in the rendering support information in dojo.render.*
+		var n = navigator;
+		var dua = n.userAgent;
+		var dav = n.appVersion;
+		var tv = parseFloat(dav);
+
+		d.isMozilla = d.isMoz = tv;
+		if(d.isMoz){
+			d.isFF = parseFloat(dua.split("Firefox/")[1]) || undefined;
+		}
+
+		// FIXME
+		d.isQuirks = document.compatMode == "BackCompat";
+
+		// FIXME
+		// TODO: is the HTML LANG attribute relevant?
+		d.locale = dojo.config.locale || n.language.toLowerCase();
+
+		d._xhrObj = function(){
+			return new XMLHttpRequest();
+		}
+
+		// monkey-patch _loadUri to handle file://, chrome://, and resource:// url's
+		var oldLoadUri = d._loadUri;
+		d._loadUri = function(uri, cb){
+			var handleLocal = ["file:", "chrome:", "resource:"].some(function(prefix){
+				return String(uri).indexOf(prefix) == 0;
+			});
+			if(handleLocal){
+				// see:
+				//		http://developer.mozilla.org/en/mozIJSSubScriptLoader
+				var l = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
+					.getService(Components.interfaces.mozIJSSubScriptLoader);
+				var value = l.loadSubScript(uri, d.global)
+				if(cb){ cb(value); }
+				return true;
+			}else{
+				// otherwise, call the pre-existing version
+				return oldLoadUri.apply(d, arguments);
+			}
+		}
+
+		// FIXME: PORTME
+		d._isDocumentOk = function(http){
+			var stat = http.status || 0;
+			return (stat >= 200 && stat < 300) || 	// Boolean
+				stat == 304 || 						// allow any 2XX response code
+				stat == 1223 || 						// get it out of the cache
+				(!stat && (location.protocol=="file:" || location.protocol=="chrome:") );
+		}
+
+		// FIXME: PORTME
+		// var owloc = window.location+"";
+		// var base = document.getElementsByTagName("base");
+		// var hasBase = (base && base.length > 0);
+		var hasBase = false;
+
+		d._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){
+			// summary: Read the contents of the specified uri and return those contents.
+			// uri:
+			//		A relative or absolute uri. If absolute, it still must be in
+			//		the same "domain" as we are.
+			// fail_ok:
+			//		Default false. If fail_ok and loading fails, return null
+			//		instead of throwing.
+			// returns: The response text. null is returned when there is a
+			//		failure and failure is okay (an exception otherwise)
+
+			// alert("_getText: " + uri);
+
+			// NOTE: must be declared before scope switches ie. this._xhrObj()
+			var http = d._xhrObj();
+
+			if(!hasBase && dojo._Url){
+				uri = (new dojo._Url(uri)).toString();
+			}
+			if(d.config.cacheBust){
+				//Make sure we have a string before string methods are used on uri
+				uri += "";
+				uri += (uri.indexOf("?") == -1 ? "?" : "&") + String(d.config.cacheBust).replace(/\W+/g,"");
+			}
+			var handleLocal = ["file:", "chrome:", "resource:"].some(function(prefix){
+				return String(uri).indexOf(prefix) == 0;
+			});
+			if(handleLocal){
+				// see:
+				//		http://forums.mozillazine.org/viewtopic.php?p=921150#921150
+				var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+					.getService(Components.interfaces.nsIIOService);
+				var scriptableStream=Components
+					.classes["@mozilla.org/scriptableinputstream;1"]
+					.getService(Components.interfaces.nsIScriptableInputStream);
+
+				var channel = ioService.newChannel(uri, null, null);
+				var input = channel.open();
+				scriptableStream.init(input);
+				var str = scriptableStream.read(input.available());
+				scriptableStream.close();
+				input.close();
+				return str;
+			}else{
+				http.open('GET', uri, false);
+				try{
+					http.send(null);
+					// alert(http);
+					if(!d._isDocumentOk(http)){
+						var err = Error("Unable to load "+uri+" status:"+ http.status);
+						err.status = http.status;
+						err.responseText = http.responseText;
+						throw err;
+					}
+				}catch(e){
+					if(fail_ok){ return null; } // null
+					// rethrow the exception
+					throw e;
+				}
+				return http.responseText; // String
+			}
+		}
+		
+		d._windowUnloaders = [];
+		
+		// FIXME: PORTME
+		d.windowUnloaded = function(){
+			// summary:
+			//		signal fired by impending window destruction. You may use
+			//		dojo.addOnWIndowUnload() or dojo.connect() to this method to perform
+			//		page/application cleanup methods. See dojo.addOnWindowUnload for more info.
+			var mll = d._windowUnloaders;
+			while(mll.length){
+				(mll.pop())();
+			}
+		}
+
+		// FIXME: PORTME
+		d.addOnWindowUnload = function(/*Object?*/obj, /*String|Function?*/functionName){
+			// summary:
+			//		registers a function to be triggered when window.onunload fires.
+			//		Be careful trying to modify the DOM or access JavaScript properties
+			//		during this phase of page unloading: they may not always be available.
+			//		Consider dojo.addOnUnload() if you need to modify the DOM or do heavy
+			//		JavaScript work.
+			// example:
+			//	|	dojo.addOnWindowUnload(functionPointer)
+			//	|	dojo.addOnWindowUnload(object, "functionName")
+			//	|	dojo.addOnWindowUnload(object, function(){ /* ... */});
+	
+			d._onto(d._windowUnloaders, obj, functionName);
+		}
+
+		// XUL specific APIs
+		var contexts = [];
+		var current = null;
+		dojo._defaultContext = [ window, document ];
+
+		dojo.pushContext = function(/*Object|String?*/g, /*MDocumentElement?*/d){
+			//	summary:
+			//		causes subsequent calls to Dojo methods to assume the
+			//		passed object and, optionally, document as the default
+			//		scopes to use. A 2-element array of the previous global and
+			//		document are returned.
+			//	description:
+			//		dojo.pushContext treats contexts as a stack. The
+			//		auto-detected contexts which are initially provided using
+			//		dojo.setContext() require authors to keep state in order to
+			//		"return" to a previous context, whereas the
+			//		dojo.pushContext and dojo.popContext methods provide a more
+			//		natural way to augment blocks of code to ensure that they
+			//		execute in a different window or frame without issue. If
+			//		called without any arguments, the default context (the
+			//		context when Dojo is first loaded) is instead pushed into
+			//		the stack. If only a single string is passed, a node in the
+			//		intitial context's document is looked up and its
+			//		contextWindow and contextDocument properties are used as
+			//		the context to push. This means that iframes can be given
+			//		an ID and code can be executed in the scope of the iframe's
+			//		document in subsequent calls easily.
+			//	g:
+			//		The global context. If a string, the id of the frame to
+			//		search for a context and document.
+			//	d:
+			//		The document element to execute subsequent code with.
+			var old = [dojo.global, dojo.doc];
+			contexts.push(old);
+			var n;
+			if(!g && !d){
+				n = dojo._defaultContext;
+			}else{
+				n = [ g, d ];
+				if(!d && dojo.isString(g)){
+					var t = document.getElementById(g);
+					if(t.contentDocument){
+						n = [t.contentWindow, t.contentDocument];
+					}
+				}
+			}
+			current = n;
+			dojo.setContext.apply(dojo, n);
+			return old; // Array
+		};
+
+		dojo.popContext = function(){
+			//	summary:
+			//		If the context stack contains elements, ensure that
+			//		subsequent code executes in the *previous* context to the
+			//		current context. The current context set ([global,
+			//		document]) is returned.
+			var oc = current;
+			if(!contexts.length){
+				return oc;
+			}
+			dojo.setContext.apply(dojo, contexts.pop());
+			return oc;
+		};
+
+		// FIXME: 
+		//		don't really like the current arguments and order to
+		//		_inContext, so don't make it public until it's right!
+		dojo._inContext = function(g, d, f){
+			var a = dojo._toArray(arguments);
+			f = a.pop();
+			if(a.length == 1){
+				d = null;
+			}
+			dojo.pushContext(g, d);
+			var r = f();
+			dojo.popContext();
+			return r;
+		};
+
+	})();
+
+	dojo._initFired = false;
+	//	BEGIN DOMContentLoaded, from Dean Edwards (http://dean.edwards.name/weblog/2006/06/again/)
+	dojo._loadInit = function(e){
+		dojo._initFired = true;
+		// allow multiple calls, only first one will take effect
+		// A bug in khtml calls events callbacks for document for event which isnt supported
+		// for example a created contextmenu event calls DOMContentLoaded, workaround
+		var type = (e && e.type) ? e.type.toLowerCase() : "load";
+		if(arguments.callee.initialized || (type != "domcontentloaded" && type != "load")){ return; }
+		arguments.callee.initialized = true;
+		if(dojo._inFlightCount == 0){
+			dojo._modulesLoaded();
+		}
+	}
+
+	/*
+	(function(){
+		var _w = window;
+		var _handleNodeEvent = function(evtName, fp){
+			// summary:
+			//		non-destructively adds the specified function to the node's
+			//		evtName handler.
+			// evtName: should be in the form "onclick" for "onclick" handlers.
+			// Make sure you pass in the "on" part.
+			var oldHandler = _w[evtName] || function(){};
+			_w[evtName] = function(){
+				fp.apply(_w, arguments);
+				oldHandler.apply(_w, arguments);
+			};
+		};
+		// FIXME: PORT
+		// FIXME: dojo.unloaded requires dojo scope, so using anon function wrapper.
+		_handleNodeEvent("onbeforeunload", function() { dojo.unloaded(); });
+		_handleNodeEvent("onunload", function() { dojo.windowUnloaded(); });
+	})();
+	*/
+	
+
+	//	FIXME: PORTME
+	// 		this event fires a lot, namely for all plugin XUL overlays and for
+	// 		all iframes (in addition to window navigations). We only want
+	// 		Dojo's to fire once..but we might care if pages navigate. We'll
+	// 		probably need an extension-specific API
+	if(!dojo.config.afterOnLoad){
+		window.addEventListener("DOMContentLoaded",function(e){ 
+			dojo._loadInit(e);
+			// console.log("DOM content loaded", e);
+		}, false);
+	}
+
+} //if (typeof window != 'undefined')
+
+//Register any module paths set up in djConfig. Need to do this
+//in the hostenvs since hostenv_browser can read djConfig from a
+//script tag's attribute.
 (function(){
-var mp=dojo.config["modulePaths"];
-if(mp){
-for(var _18 in mp){
-dojo.registerModulePath(_18,mp[_18]);
-}
-}
+	var mp = dojo.config["modulePaths"];
+	if(mp){
+		for(var param in mp){
+			dojo.registerModulePath(param, mp[param]);
+		}
+	}
 })();
+
+//Load debug code if necessary.
 if(dojo.config.isDebug){
-console.log=function(m){
-var s=Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
-s.logStringMessage(m);
-};
-console.debug=function(){
-};
+	// logging stub for extension logging
+	console.log = function(m){
+		var s = Components.classes["@mozilla.org/consoleservice;1"].getService(
+			Components.interfaces.nsIConsoleService
+		);
+		s.logStringMessage(m);
+	}
+	console.debug = function(){
+		console.log(dojo._toArray(arguments).join(" "));
+	}
+	// FIXME: what about the rest of the console.* methods? And is there any way to reach into firebug and log into it directly?
 }
diff --git a/dojo/_base/_loader/hostenv_rhino.js b/dojo/_base/_loader/hostenv_rhino.js
index aa20149..df66ad3 100644
--- a/dojo/_base/_loader/hostenv_rhino.js
+++ b/dojo/_base/_loader/hostenv_rhino.js
@@ -1,153 +1,201 @@
 /*
-	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
+* Rhino host environment
 */
 
-
 if(dojo.config["baseUrl"]){
-dojo.baseUrl=dojo.config["baseUrl"];
+	dojo.baseUrl = dojo.config["baseUrl"];
 }else{
-dojo.baseUrl="./";
+	dojo.baseUrl = "./";
 }
-dojo.locale=dojo.locale||String(java.util.Locale.getDefault().toString().replace("_","-").toLowerCase());
-dojo._name="rhino";
-dojo.isRhino=true;
-if(typeof print=="function"){
-console.debug=print;
+
+dojo.locale = dojo.locale || String(java.util.Locale.getDefault().toString().replace('_','-').toLowerCase());
+dojo._name = 'rhino';
+dojo.isRhino = true;
+
+if(typeof print == "function"){
+	console.debug = print;
 }
+
 if(!("byId" in dojo)){
-dojo.byId=function(id,_1){
-if(id&&(typeof id=="string"||id instanceof String)){
-if(!_1){
-_1=document;
-}
-return _1.getElementById(id);
-}
-return id;
-};
-}
-dojo._isLocalUrl=function(_2){
-var _3=(new java.io.File(_2)).exists();
-if(!_3){
-var _4;
-try{
-_4=(new java.net.URL(_2)).openStream();
-_4.close();
-}
-finally{
-if(_4&&_4.close){
-_4.close();
-}
-}
-}
-return _3;
-};
-dojo._loadUri=function(_5,cb){
-try{
-var _6;
-try{
-_6=dojo._isLocalUrl(_5);
-}
-catch(e){
-return false;
-}
-if(cb){
-var _7=(_6?readText:readUri)(_5,"UTF-8");
-if(!eval("'‏'").length){
-_7=String(_7).replace(/[\u200E\u200F\u202A-\u202E]/g,function(_8){
-return "\\u"+_8.charCodeAt(0).toString(16);
-});
-}
-cb(eval("("+_7+")"));
-}else{
-load(_5);
-}
-return true;
-}
-catch(e){
-return false;
-}
-};
-dojo.exit=function(_9){
-quit(_9);
-};
-function readText(_a,_b){
-_b=_b||"utf-8";
-var jf=new java.io.File(_a);
-var is=new java.io.FileInputStream(jf);
-return dj_readInputStream(is,_b);
-};
-function readUri(_c,_d){
-var _e=(new java.net.URL(_c)).openConnection();
-_d=_d||_e.getContentEncoding()||"utf-8";
-var is=_e.getInputStream();
-return dj_readInputStream(is,_d);
-};
-function dj_readInputStream(is,_f){
-var _10=new java.io.BufferedReader(new java.io.InputStreamReader(is,_f));
-try{
-var sb=new java.lang.StringBuffer();
-var _11="";
-while((_11=_10.readLine())!==null){
-sb.append(_11);
-sb.append(java.lang.System.getProperty("line.separator"));
-}
-return sb.toString();
-}
-finally{
-_10.close();
+	dojo.byId = function(id, doc){
+		if(id && (typeof id == "string" || id instanceof String)){
+			if(!doc){ doc = document; }
+			return doc.getElementById(id);
+		}
+		return id; // assume it's a node
+	}
 }
-};
-dojo._getText=function(uri,_12){
-try{
-var _13=dojo._isLocalUrl(uri);
-var _14=(_13?readText:readUri)(uri,"UTF-8");
-if(_14!==null){
-_14+="";
+
+dojo._isLocalUrl = function(/*String*/ uri) {
+	// summary:
+	// 		determines if URI is local or not.
+
+	var local = (new java.io.File(uri)).exists();
+	if(!local){
+		var stream;
+		//Try remote URL. Allow this method to throw,
+		//but still do cleanup.
+		try{
+			// try it as a file first, URL second
+			stream = (new java.net.URL(uri)).openStream();
+			// close the stream so we don't leak resources
+			stream.close();
+		}finally{
+			if(stream && stream.close){
+				stream.close();
+			}
+		}
+	}
+	return local;
 }
-return _14;
+
+// see comments in spidermonkey loadUri
+dojo._loadUri = function(uri, cb){
+	try{
+		var local;
+		try{
+			local = dojo._isLocalUrl(uri);
+		}catch(e){
+			// no debug output; this failure just means the uri was not found.
+			return false;
+		}
+
+		//FIXME: Use Rhino 1.6 native readFile/readUrl if available?
+		if(cb){
+			var contents = (local ? readText : readUri)(uri, "UTF-8");
+
+			// patch up the input to eval until https://bugzilla.mozilla.org/show_bug.cgi?id=471005 is fixed.
+			if(!eval("'\u200f'").length){
+				contents = String(contents).replace(/[\u200E\u200F\u202A-\u202E]/g, function(match){ 
+					return "\\u" + match.charCodeAt(0).toString(16); 
+				})
+			}
+
+			cb(eval('('+contents+')'));
+		}else{
+			load(uri);
+		}
+		return true;
+	}catch(e){
+		console.debug("rhino load('" + uri + "') failed. Exception: " + e);
+		return false;
+	}
 }
-catch(e){
-if(_12){
-return null;
-}else{
-throw e;
+
+dojo.exit = function(exitcode){ 
+	quit(exitcode);
 }
+
+// reading a file from disk in Java is a humiliating experience by any measure.
+// Lets avoid that and just get the freaking text
+function readText(path, encoding){
+	encoding = encoding || "utf-8";
+	// NOTE: we intentionally avoid handling exceptions, since the caller will
+	// want to know
+	var jf = new java.io.File(path);
+	var is = new java.io.FileInputStream(jf);
+	return dj_readInputStream(is, encoding);
 }
-};
-dojo.doc=typeof document!="undefined"?document:null;
-dojo.body=function(){
-return document.body;
-};
-if(typeof setTimeout=="undefined"||typeof clearTimeout=="undefined"){
-dojo._timeouts=[];
-clearTimeout=function(idx){
-if(!dojo._timeouts[idx]){
-return;
+
+function readUri(uri, encoding){
+	var conn = (new java.net.URL(uri)).openConnection();
+	encoding = encoding || conn.getContentEncoding() || "utf-8";
+	var is = conn.getInputStream();
+	return dj_readInputStream(is, encoding);
 }
-dojo._timeouts[idx].stop();
-};
-setTimeout=function(_15,_16){
-var def={sleepTime:_16,hasSlept:false,run:function(){
-if(!this.hasSlept){
-this.hasSlept=true;
-java.lang.Thread.currentThread().sleep(this.sleepTime);
+
+function dj_readInputStream(is, encoding){
+	var input = new java.io.BufferedReader(new java.io.InputStreamReader(is, encoding));
+	try {
+		var sb = new java.lang.StringBuffer();
+		var line = "";
+		while((line = input.readLine()) !== null){
+			sb.append(line);
+			sb.append(java.lang.System.getProperty("line.separator"));
+		}
+		return sb.toString();
+	} finally {
+		input.close();
+	}
 }
-try{
-_15();
+
+dojo._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){
+	// summary: Read the contents of the specified uri and return those contents.
+	// uri:
+	//		A relative or absolute uri.
+	// fail_ok:
+	//		Default false. If fail_ok and loading fails, return null
+	//		instead of throwing.
+	// returns: The response text. null is returned when there is a
+	//		failure and failure is okay (an exception otherwise)
+	try{
+		var local = dojo._isLocalUrl(uri);
+		var text = (local ? readText : readUri)(uri, "UTF-8");
+		if(text !== null){
+			//Force JavaScript string.
+			text += "";
+		}
+		return text;
+	}catch(e){
+		if(fail_ok){
+			return null;
+		}else{
+			throw e;
+		}
+	}
 }
-catch(e){
+
+// summary:
+//		return the document object associated with the dojo.global
+dojo.doc = typeof document != "undefined" ? document : null;
+
+dojo.body = function(){
+	return document.body;	
 }
-}};
-var _17=new java.lang.Runnable(def);
-var _18=new java.lang.Thread(_17);
-_18.start();
-return dojo._timeouts.push(_18)-1;
-};
+
+// Supply setTimeout/clearTimeout implementations if they aren't already there
+// Note: this assumes that we define both if one is not provided... there might
+// be a better way to do this if there is a use case where one is defined but
+// not the other
+if(typeof setTimeout == "undefined" || typeof clearTimeout == "undefined"){
+	dojo._timeouts = [];
+	clearTimeout = function(idx){
+		if(!dojo._timeouts[idx]){ return; }
+		dojo._timeouts[idx].stop();
+	}
+
+	setTimeout = function(func, delay){
+		// summary: provides timed callbacks using Java threads
+
+		var def={
+			sleepTime:delay,
+			hasSlept:false,
+		
+			run:function(){
+				if(!this.hasSlept){
+					this.hasSlept=true;
+					java.lang.Thread.currentThread().sleep(this.sleepTime);
+				}
+				try{
+					func();
+				}catch(e){
+					console.debug("Error running setTimeout thread:" + e);
+				}
+			}
+		};
+	
+		var runnable = new java.lang.Runnable(def);
+		var thread = new java.lang.Thread(runnable);
+		thread.start();
+		return dojo._timeouts.push(thread)-1;
+	}
 }
+
+//Register any module paths set up in djConfig. Need to do this
+//in the hostenvs since hostenv_browser can read djConfig from a
+//script tag's attribute.
 if(dojo.config["modulePaths"]){
-for(var param in dojo.config["modulePaths"]){
-dojo.registerModulePath(param,dojo.config["modulePaths"][param]);
-}
+	for(var param in dojo.config["modulePaths"]){
+		dojo.registerModulePath(param, dojo.config["modulePaths"][param]);
+	}
 }
diff --git a/dojo/_base/_loader/hostenv_spidermonkey.js b/dojo/_base/_loader/hostenv_spidermonkey.js
index 7d5cdc7..9203bbf 100644
--- a/dojo/_base/_loader/hostenv_spidermonkey.js
+++ b/dojo/_base/_loader/hostenv_spidermonkey.js
@@ -1,50 +1,80 @@
 /*
-	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
-*/
-
+ * SpiderMonkey host environment
+ */
 
 if(dojo.config["baseUrl"]){
-dojo.baseUrl=dojo.config["baseUrl"];
+	dojo.baseUrl = dojo.config["baseUrl"];
 }else{
-dojo.baseUrl="./";
+	dojo.baseUrl = "./";
 }
-dojo._name="spidermonkey";
-dojo.isSpidermonkey=true;
-dojo.exit=function(_1){
-quit(_1);
+
+dojo._name = 'spidermonkey';
+
+/*=====
+dojo.isSpidermonkey = {
+	// summary: Detect spidermonkey 
 };
-if(typeof print=="function"){
-console.debug=print;
-}
-if(typeof line2pc=="undefined"){
-throw new Error("attempt to use SpiderMonkey host environment when no 'line2pc' global");
+=====*/
+
+dojo.isSpidermonkey = true;
+dojo.exit = function(exitcode){ 
+	quit(exitcode); 
 }
-dojo._spidermonkeyCurrentFile=function(_2){
-var s="";
-try{
-throw Error("whatever");
+
+if(typeof print == "function"){
+	console.debug = print;
 }
-catch(e){
-s=e.stack;
+
+if(typeof line2pc == 'undefined'){
+	throw new Error("attempt to use SpiderMonkey host environment when no 'line2pc' global");
 }
-var _3=s.match(/[^@]*\.js/gi);
-if(!_3){
-throw Error("could not parse stack string: '"+s+"'");
+
+dojo._spidermonkeyCurrentFile = function(depth){
+	//	
+	//	This is a hack that determines the current script file by parsing a
+	//	generated stack trace (relying on the non-standard "stack" member variable
+	//	of the SpiderMonkey Error object).
+	//	
+	//	If param depth is passed in, it'll return the script file which is that far down
+	//	the stack, but that does require that you know how deep your stack is when you are
+	//	calling.
+	//	
+    var s = '';
+    try{
+		throw Error("whatever");
+	}catch(e){
+		s = e.stack;
+	}
+    // lines are like: bu_getCurrentScriptURI_spidermonkey("ScriptLoader.js")@burst/Runtime.js:101
+    var matches = s.match(/[^@]*\.js/gi);
+    if(!matches){ 
+		throw Error("could not parse stack string: '" + s + "'");
+	}
+    var fname = (typeof depth != 'undefined' && depth) ? matches[depth + 1] : matches[matches.length - 1];
+    if(!fname){ 
+		throw Error("could not find file name in stack string '" + s + "'");
+	}
+    //print("SpiderMonkeyRuntime got fname '" + fname + "' from stack string '" + s + "'");
+    return fname;
 }
-var _4=(typeof _2!="undefined"&&_2)?_3[_2+1]:_3[_3.length-1];
-if(!_4){
-throw Error("could not find file name in stack string '"+s+"'");
+
+// print(dojo._spidermonkeyCurrentFile(0)); 
+
+dojo._loadUri = function(uri){
+	// spidermonkey load() evaluates the contents into the global scope (which
+	// is what we want).
+	// TODO: sigh, load() does not return a useful value. 
+	// Perhaps it is returning the value of the last thing evaluated?
+	var ok = load(uri);
+	// console.log("spidermonkey load(", uri, ") returned ", ok);
+	return 1;
 }
-return _4;
-};
-dojo._loadUri=function(_5){
-var ok=load(_5);
-return 1;
-};
+
+//Register any module paths set up in djConfig. Need to do this
+//in the hostenvs since hostenv_browser can read djConfig from a
+//script tag's attribute.
 if(dojo.config["modulePaths"]){
-for(var param in dojo.config["modulePaths"]){
-dojo.registerModulePath(param,dojo.config["modulePaths"][param]);
-}
+	for(var param in dojo.config["modulePaths"]){
+		dojo.registerModulePath(param, dojo.config["modulePaths"][param]);
+	}
 }
diff --git a/dojo/_base/_loader/loader.js b/dojo/_base/_loader/loader.js
index 0bf4a0e..48a6b10 100644
--- a/dojo/_base/_loader/loader.js
+++ b/dojo/_base/_loader/loader.js
@@ -1,300 +1,799 @@
 /*
-	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
-*/
+ * loader.js - A bootstrap module.  Runs before the hostenv_*.js file. Contains
+ * all of the package loading methods.
+ */
 
-
-if(!dojo._hasResource["dojo.foo"]){
-dojo._hasResource["dojo.foo"]=true;
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 (function(){
-var d=dojo;
-d.mixin(d,{_loadedModules:{},_inFlightCount:0,_hasResource:{},_modulePrefixes:{dojo:{name:"dojo",value:"."},doh:{name:"doh",value:"../util/doh"},tests:{name:"tests",value:"tests"}},_moduleHasPrefix:function(_1){
-var mp=d._modulePrefixes;
-return !!(mp[_1]&&mp[_1].value);
-},_getModulePrefix:function(_2){
-var mp=d._modulePrefixes;
-if(d._moduleHasPrefix(_2)){
-return mp[_2].value;
-}
-return _2;
-},_loadedUrls:[],_postLoad:false,_loaders:[],_unloaders:[],_loadNotifying:false});
-dojo._loadPath=function(_3,_4,cb){
-var _5=((_3.charAt(0)=="/"||_3.match(/^\w+:/))?"":d.baseUrl)+_3;
-try{
-return !_4?d._loadUri(_5,cb):d._loadUriAndCheck(_5,_4,cb);
-}
-catch(e){
-console.error(e);
-return false;
-}
-};
-dojo._loadUri=function(_6,cb){
-if(d._loadedUrls[_6]){
-return true;
-}
-d._inFlightCount++;
-var _7=d._getText(_6,true);
-if(_7){
-d._loadedUrls[_6]=true;
-d._loadedUrls.push(_6);
-if(cb){
-_7="("+_7+")";
-}else{
-_7=d._scopePrefix+_7+d._scopeSuffix;
-}
-if(!d.isIE){
-_7+="\r\n//@ sourceURL="+_6;
-}
-var _8=d["eval"](_7);
-if(cb){
-cb(_8);
-}
-}
-if(--d._inFlightCount==0&&d._postLoad&&d._loaders.length){
-setTimeout(function(){
-if(d._inFlightCount==0){
-d._callLoaded();
-}
-},0);
-}
-return !!_7;
-};
-dojo._loadUriAndCheck=function(_9,_a,cb){
-var ok=false;
-try{
-ok=d._loadUri(_9,cb);
-}
-catch(e){
-console.error("failed loading "+_9+" with error: "+e);
-}
-return !!(ok&&d._loadedModules[_a]);
-};
-dojo.loaded=function(){
-d._loadNotifying=true;
-d._postLoad=true;
-var _b=d._loaders;
-d._loaders=[];
-for(var x=0;x<_b.length;x++){
-_b[x]();
-}
-d._loadNotifying=false;
-if(d._postLoad&&d._inFlightCount==0&&_b.length){
-d._callLoaded();
-}
-};
-dojo.unloaded=function(){
-var _c=d._unloaders;
-while(_c.length){
-(_c.pop())();
-}
-};
-d._onto=function(_d,_e,fn){
-if(!fn){
-_d.push(_e);
-}else{
-if(fn){
-var _f=(typeof fn=="string")?_e[fn]:fn;
-_d.push(function(){
-_f.call(_e);
-});
-}
-}
-};
-dojo.ready=dojo.addOnLoad=function(obj,_10){
-d._onto(d._loaders,obj,_10);
-if(d._postLoad&&d._inFlightCount==0&&!d._loadNotifying){
-d._callLoaded();
-}
-};
-var dca=d.config.addOnLoad;
-if(dca){
-d.addOnLoad[(dca instanceof Array?"apply":"call")](d,dca);
-}
-dojo._modulesLoaded=function(){
-if(d._postLoad){
-return;
-}
-if(d._inFlightCount>0){
-console.warn("files still in flight!");
-return;
-}
-d._callLoaded();
-};
-dojo._callLoaded=function(){
-if(typeof setTimeout=="object"||(d.config.useXDomain&&d.isOpera)){
-setTimeout(d.isAIR?function(){
-d.loaded();
-}:d._scopeName+".loaded();",0);
-}else{
-d.loaded();
-}
-};
-dojo._getModuleSymbols=function(_11){
-var _12=_11.split(".");
-for(var i=_12.length;i>0;i--){
-var _13=_12.slice(0,i).join(".");
-if(i==1&&!d._moduleHasPrefix(_13)){
-_12[0]="../"+_12[0];
-}else{
-var _14=d._getModulePrefix(_13);
-if(_14!=_13){
-_12.splice(0,i,_14);
-break;
-}
-}
-}
-return _12;
-};
-dojo._global_omit_module_check=false;
-dojo.loadInit=function(_15){
-_15();
-};
-dojo._loadModule=dojo.require=function(_16,_17){
-_17=d._global_omit_module_check||_17;
-var _18=d._loadedModules[_16];
-if(_18){
-return _18;
-}
-var _19=d._getModuleSymbols(_16).join("/")+".js";
-var _1a=!_17?_16:null;
-var ok=d._loadPath(_19,_1a);
-if(!ok&&!_17){
-throw new Error("Could not load '"+_16+"'; last tried '"+_19+"'");
-}
-if(!_17&&!d._isXDomain){
-_18=d._loadedModules[_16];
-if(!_18){
-throw new Error("symbol '"+_16+"' is not defined after loading '"+_19+"'");
-}
-}
-return _18;
-};
-dojo.provide=function(_1b){
-_1b=_1b+"";
-return (d._loadedModules[_1b]=d.getObject(_1b,true));
-};
-dojo.platformRequire=function(_1c){
-var _1d=_1c.common||[];
-var _1e=_1d.concat(_1c[d._name]||_1c["default"]||[]);
-for(var x=0;x<_1e.length;x++){
-var _1f=_1e[x];
-if(_1f.constructor==Array){
-d._loadModule.apply(d,_1f);
-}else{
-d._loadModule(_1f);
-}
-}
-};
-dojo.requireIf=function(_20,_21){
-if(_20===true){
-var _22=[];
-for(var i=1;i<arguments.length;i++){
-_22.push(arguments[i]);
-}
-d.require.apply(d,_22);
-}
-};
-dojo.requireAfterIf=d.requireIf;
-dojo.registerModulePath=function(_23,_24){
-d._modulePrefixes[_23]={name:_23,value:_24};
-};
-dojo.requireLocalization=function(_25,_26,_27,_28){
-d.require("dojo.i18n");
-d.i18n._requireLocalization.apply(d.hostenv,arguments);
-};
-var ore=new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"),ire=new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$");
-dojo._Url=function(){
-var n=null,_29=arguments,uri=[_29[0]];
-for(var i=1;i<_29.length;i++){
-if(!_29[i]){
-continue;
-}
-var _2a=new d._Url(_29[i]+""),_2b=new d._Url(uri[0]+"");
-if(_2a.path==""&&!_2a.scheme&&!_2a.authority&&!_2a.query){
-if(_2a.fragment!=n){
-_2b.fragment=_2a.fragment;
-}
-_2a=_2b;
-}else{
-if(!_2a.scheme){
-_2a.scheme=_2b.scheme;
-if(!_2a.authority){
-_2a.authority=_2b.authority;
-if(_2a.path.charAt(0)!="/"){
-var _2c=_2b.path.substring(0,_2b.path.lastIndexOf("/")+1)+_2a.path;
-var _2d=_2c.split("/");
-for(var j=0;j<_2d.length;j++){
-if(_2d[j]=="."){
-if(j==_2d.length-1){
-_2d[j]="";
-}else{
-_2d.splice(j,1);
-j--;
-}
-}else{
-if(j>0&&!(j==1&&_2d[0]=="")&&_2d[j]==".."&&_2d[j-1]!=".."){
-if(j==(_2d.length-1)){
-_2d.splice(j,1);
-_2d[j-1]="";
-}else{
-_2d.splice(j-1,2);
-j-=2;
-}
-}
-}
-}
-_2a.path=_2d.join("/");
-}
-}
-}
-}
-uri=[];
-if(_2a.scheme){
-uri.push(_2a.scheme,":");
-}
-if(_2a.authority){
-uri.push("//",_2a.authority);
-}
-uri.push(_2a.path);
-if(_2a.query){
-uri.push("?",_2a.query);
-}
-if(_2a.fragment){
-uri.push("#",_2a.fragment);
-}
-}
-this.uri=uri.join("");
-var r=this.uri.match(ore);
-this.scheme=r[2]||(r[1]?"":n);
-this.authority=r[4]||(r[3]?"":n);
-this.path=r[5];
-this.query=r[7]||(r[6]?"":n);
-this.fragment=r[9]||(r[8]?"":n);
-if(this.authority!=n){
-r=this.authority.match(ire);
-this.user=r[3]||n;
-this.password=r[4]||n;
-this.host=r[6]||r[7];
-this.port=r[9]||n;
-}
-};
-dojo._Url.prototype.toString=function(){
-return this.uri;
-};
-dojo.moduleUrl=function(_2e,url){
-var loc=d._getModuleSymbols(_2e).join("/");
-if(!loc){
-return null;
-}
-if(loc.lastIndexOf("/")!=loc.length-1){
-loc+="/";
-}
-var _2f=loc.indexOf(":");
-if(loc.charAt(0)!="/"&&(_2f==-1||_2f>loc.indexOf("/"))){
-loc=d.baseUrl+loc;
-}
-return new d._Url(loc,url);
-};
+	var d = dojo;
+//>>excludeEnd("webkitMobile");
+
+	d.mixin(d, {
+		_loadedModules: {},
+		_inFlightCount: 0,
+		_hasResource: {},
+
+		_modulePrefixes: {
+			dojo: 	{	name: "dojo", value: "." },
+			// dojox: 	{	name: "dojox", value: "../dojox" },
+			// dijit: 	{	name: "dijit", value: "../dijit" },
+			doh: 	{	name: "doh", value: "../util/doh" },
+			tests: 	{	name: "tests", value: "tests" }
+		},
+
+		_moduleHasPrefix: function(/*String*/module){
+			// summary: checks to see if module has been established
+			var mp = d._modulePrefixes;
+			return !!(mp[module] && mp[module].value); // Boolean
+		},
+
+		_getModulePrefix: function(/*String*/module){
+			// summary: gets the prefix associated with module
+			var mp = d._modulePrefixes;
+			if(d._moduleHasPrefix(module)){
+				return mp[module].value; // String
+			}
+			return module; // String
+		},
+
+		_loadedUrls: [],
+
+		//WARNING: 
+		//		This variable is referenced by packages outside of bootstrap:
+		//		FloatingPane.js and undo/browser.js
+		_postLoad: false,
+		
+		//Egad! Lots of test files push on this directly instead of using dojo.addOnLoad.
+		_loaders: [],
+		_unloaders: [],
+		_loadNotifying: false
+	});
+
+
+	//>>excludeStart("xdomainExclude", fileName.indexOf("dojo.xd.js") != -1 && kwArgs.loader == "xdomain");
+	dojo._loadPath = function(/*String*/relpath, /*String?*/module, /*Function?*/cb){
+		// 	summary:
+		//		Load a Javascript module given a relative path
+		//
+		//	description:
+		//		Loads and interprets the script located at relpath, which is
+		//		relative to the script root directory.  If the script is found but
+		//		its interpretation causes a runtime exception, that exception is
+		//		not caught by us, so the caller will see it.  We return a true
+		//		value if and only if the script is found.
+		//
+		// relpath: 
+		//		A relative path to a script (no leading '/', and typically ending
+		//		in '.js').
+		// module: 
+		//		A module whose existance to check for after loading a path.  Can be
+		//		used to determine success or failure of the load.
+		// cb: 
+		//		a callback function to pass the result of evaluating the script
+
+		var uri = ((relpath.charAt(0) == '/' || relpath.match(/^\w+:/)) ? "" : d.baseUrl) + relpath;
+		try{
+			return !module ? d._loadUri(uri, cb) : d._loadUriAndCheck(uri, module, cb); // Boolean
+		}catch(e){
+			console.error(e);
+			return false; // Boolean
+		}
+	}
+
+	dojo._loadUri = function(/*String*/uri, /*Function?*/cb){
+		//	summary:
+		//		Loads JavaScript from a URI
+		//	description:
+		//		Reads the contents of the URI, and evaluates the contents.  This is
+		//		used to load modules as well as resource bundles. Returns true if
+		//		it succeeded. Returns false if the URI reading failed.  Throws if
+		//		the evaluation throws.
+		//	uri: a uri which points at the script to be loaded
+		//	cb: 
+		//		a callback function to process the result of evaluating the script
+		//		as an expression, typically used by the resource bundle loader to
+		//		load JSON-style resources
+
+		if(d._loadedUrls[uri]){
+			return true; // Boolean
+		}
+		d._inFlightCount++; // block addOnLoad calls that arrive while we're busy downloading
+		var contents = d._getText(uri, true);
+		if(contents){ // not 404, et al
+			d._loadedUrls[uri] = true;
+			d._loadedUrls.push(uri);
+			if(cb){
+				contents = '('+contents+')';
+			}else{
+				//Only do the scoping if no callback. If a callback is specified,
+				//it is most likely the i18n bundle stuff.
+				contents = d._scopePrefix + contents + d._scopeSuffix;
+			}
+			if(!d.isIE){ contents += "\r\n//@ sourceURL=" + uri; } // debugging assist for Firebug
+			var value = d["eval"](contents);
+			if(cb){ cb(value); }
+		}
+		// Check to see if we need to call _callLoaded() due to an addOnLoad() that arrived while we were busy downloading
+		if(--d._inFlightCount == 0 && d._postLoad && d._loaders.length){
+			// We shouldn't be allowed to get here but Firefox allows an event 
+			// (mouse, keybd, async xhrGet) to interrupt a synchronous xhrGet. 
+			// If the current script block contains multiple require() statements, then after each
+			// require() returns, inFlightCount == 0, but we want to hold the _callLoaded() until
+			// all require()s are done since the out-of-sequence addOnLoad() presumably needs them all.
+			// setTimeout allows the next require() to start (if needed), and then we check this again.
+			setTimeout(function(){ 
+				// If inFlightCount > 0, then multiple require()s are running sequentially and 
+				// the next require() started after setTimeout() was executed but before we got here.
+				if(d._inFlightCount == 0){ 
+					d._callLoaded();
+				}
+			}, 0);
+		}
+		return !!contents; // Boolean: contents? true : false
+	}
+	//>>excludeEnd("xdomainExclude");
+
+	// FIXME: probably need to add logging to this method
+	dojo._loadUriAndCheck = function(/*String*/uri, /*String*/moduleName, /*Function?*/cb){
+		// summary: calls loadUri then findModule and returns true if both succeed
+		var ok = false;
+		try{
+			ok = d._loadUri(uri, cb);
+		}catch(e){
+			console.error("failed loading " + uri + " with error: " + e);
+		}
+		return !!(ok && d._loadedModules[moduleName]); // Boolean
+	}
+
+	dojo.loaded = function(){
+		// summary:
+		//		signal fired when initial environment and package loading is
+		//		complete. You should use dojo.addOnLoad() instead of doing a 
+		//		direct dojo.connect() to this method in order to handle
+		//		initialization tasks that require the environment to be
+		//		initialized. In a browser host,	declarative widgets will 
+		//		be constructed when this function finishes runing.
+		d._loadNotifying = true;
+		d._postLoad = true;
+		var mll = d._loaders;
+
+		//Clear listeners so new ones can be added
+		//For other xdomain package loads after the initial load.
+		d._loaders = [];
+
+		for(var x = 0; x < mll.length; x++){
+			mll[x]();
+		}
+
+		d._loadNotifying = false;
+		
+		//Make sure nothing else got added to the onload queue
+		//after this first run. If something did, and we are not waiting for any
+		//more inflight resources, run again.
+		if(d._postLoad && d._inFlightCount == 0 && mll.length){
+			d._callLoaded();
+		}
+	}
+
+	dojo.unloaded = function(){
+		// summary:
+		//		signal fired by impending environment destruction. You should use
+		//		dojo.addOnUnload() instead of doing a direct dojo.connect() to this 
+		//		method to perform page/application cleanup methods. See 
+		//		dojo.addOnUnload for more info.
+		var mll = d._unloaders;
+		while(mll.length){
+			(mll.pop())();
+		}
+	}
+
+	d._onto = function(arr, obj, fn){
+		if(!fn){
+			arr.push(obj);
+		}else if(fn){
+			var func = (typeof fn == "string") ? obj[fn] : fn;
+			arr.push(function(){ func.call(obj); });
+		}
+	}
+
+	dojo.ready = dojo.addOnLoad = function(/*Object*/obj, /*String|Function?*/functionName){
+		// summary:
+		//		Registers a function to be triggered after the DOM and dojo.require() calls 
+		//		have finished loading.
+		//
+		// description:
+		//		Registers a function to be triggered after the DOM has finished
+		//		loading and `dojo.require` modules have loaded. Widgets declared in markup 
+		//		have been instantiated if `djConfig.parseOnLoad` is true when this fires. 
+		//
+		//		Images and CSS files may or may not have finished downloading when
+		//		the specified function is called.  (Note that widgets' CSS and HTML
+		//		code is guaranteed to be downloaded before said widgets are
+		//		instantiated, though including css resouces BEFORE any script elements
+		//		is highly recommended).
+		//
+		// example:
+		//	Register an anonymous function to run when everything is ready
+		//	|	dojo.addOnLoad(function(){ doStuff(); });
+		//
+		// example:
+		//	Register a function to run when everything is ready by pointer:
+		//	|	var init = function(){ doStuff(); }
+		//	|	dojo.addOnLoad(init);
+		//
+		// example:
+		//	Register a function to run scoped to `object`, either by name or anonymously:
+		//	|	dojo.addOnLoad(object, "functionName");
+		//	|	dojo.addOnLoad(object, function(){ doStuff(); });
+
+		d._onto(d._loaders, obj, functionName);
+
+		//Added for xdomain loading. dojo.addOnLoad is used to
+		//indicate callbacks after doing some dojo.require() statements.
+		//In the xdomain case, if all the requires are loaded (after initial
+		//page load), then immediately call any listeners.
+		if(d._postLoad && d._inFlightCount == 0 && !d._loadNotifying){
+			d._callLoaded();
+		}
+	}
+
+	//Support calling dojo.addOnLoad via djConfig.addOnLoad. Support all the
+	//call permutations of dojo.addOnLoad. Mainly useful when dojo is added
+	//to the page after the page has loaded.
+	var dca = d.config.addOnLoad;
+	if(dca){
+		d.addOnLoad[(dca instanceof Array ? "apply" : "call")](d, dca);
+	}
+
+	dojo._modulesLoaded = function(){
+		if(d._postLoad){ return; }
+		if(d._inFlightCount > 0){ 
+			console.warn("files still in flight!");
+			return;
+		}
+		d._callLoaded();
+	}
+
+	dojo._callLoaded = function(){
+
+		// The "object" check is for IE, and the other opera check fixes an
+		// issue in Opera where it could not find the body element in some
+		// widget test cases.  For 0.9, maybe route all browsers through the
+		// setTimeout (need protection still for non-browser environments
+		// though). This might also help the issue with FF 2.0 and freezing
+		// issues where we try to do sync xhr while background css images are
+		// being loaded (trac #2572)? Consider for 0.9.
+		if(typeof setTimeout == "object" || (d.config.useXDomain && d.isOpera)){
+			setTimeout(
+				d.isAIR ? function(){ d.loaded(); } : d._scopeName + ".loaded();",
+				0);
+		}else{
+			d.loaded();
+		}
+	}
+
+	dojo._getModuleSymbols = function(/*String*/modulename){
+		// summary:
+		//		Converts a module name in dotted JS notation to an array
+		//		representing the path in the source tree
+		var syms = modulename.split(".");
+		for(var i = syms.length; i>0; i--){
+			var parentModule = syms.slice(0, i).join(".");
+			if(i == 1 && !d._moduleHasPrefix(parentModule)){		
+				// Support default module directory (sibling of dojo) for top-level modules 
+				syms[0] = "../" + syms[0];
+			}else{
+				var parentModulePath = d._getModulePrefix(parentModule);
+				if(parentModulePath != parentModule){
+					syms.splice(0, i, parentModulePath);
+					break;
+				}
+			}
+		}
+		return syms; // Array
+	}
+
+	dojo._global_omit_module_check = false;
+
+	dojo.loadInit = function(/*Function*/init){
+		//	summary:
+		//		Executes a function that needs to be executed for the loader's dojo.requireIf
+		//		resolutions to work. This is needed mostly for the xdomain loader case where
+		//		a function needs to be executed to set up the possible values for a dojo.requireIf
+		//		call.
+		//	init:
+		//		a function reference. Executed immediately.
+		//	description: This function is mainly a marker for the xdomain loader to know parts of
+		//		code that needs be executed outside the function wrappper that is placed around modules.
+		//		The init function could be executed more than once, and it should make no assumptions
+		//		on what is loaded, or what modules are available. Only the functionality in Dojo Base
+		//		is allowed to be used. Avoid using this method. For a valid use case,
+		//		see the source for dojox.gfx.
+		init();
+	}
+
+	dojo._loadModule = dojo.require = function(/*String*/moduleName, /*Boolean?*/omitModuleCheck){
+		//	summary:
+		//		loads a Javascript module from the appropriate URI
+		//	moduleName:
+		//		module name to load, using periods for separators,
+		//		 e.g. "dojo.date.locale".  Module paths are de-referenced by dojo's
+		//		internal mapping of locations to names and are disambiguated by
+		//		longest prefix. See `dojo.registerModulePath()` for details on
+		//		registering new modules.
+		//	omitModuleCheck:
+		//		if `true`, omitModuleCheck skips the step of ensuring that the
+		//		loaded file actually defines the symbol it is referenced by.
+		//		For example if it called as `dojo.require("a.b.c")` and the
+		//		file located at `a/b/c.js` does not define an object `a.b.c`,
+		//		and exception will be throws whereas no exception is raised
+		//		when called as `dojo.require("a.b.c", true)`
+		//	description:
+		// 		Modules are loaded via dojo.require by using one of two loaders: the normal loader
+		// 		and the xdomain loader. The xdomain loader is used when dojo was built with a
+		// 		custom build that specified loader=xdomain and the module lives on a modulePath
+		// 		that is a whole URL, with protocol and a domain. The versions of Dojo that are on
+		// 		the Google and AOL CDNs use the xdomain loader.
+		// 
+		// 		If the module is loaded via the xdomain loader, it is an asynchronous load, since
+		// 		the module is added via a dynamically created script tag. This
+		// 		means that dojo.require() can return before the module has loaded. However, this 
+		// 		should only happen in the case where you do dojo.require calls in the top-level
+		// 		HTML page, or if you purposely avoid the loader checking for dojo.require
+		// 		dependencies in your module by using a syntax like dojo["require"] to load the module.
+		// 
+		// 		Sometimes it is useful to not have the loader detect the dojo.require calls in the
+		// 		module so that you can dynamically load the modules as a result of an action on the
+		// 		page, instead of right at module load time.
+		// 
+		// 		Also, for script blocks in an HTML page, the loader does not pre-process them, so
+		// 		it does not know to download the modules before the dojo.require calls occur.
+		// 
+		// 		So, in those two cases, when you want on-the-fly module loading or for script blocks
+		// 		in the HTML page, special care must be taken if the dojo.required code is loaded
+		// 		asynchronously. To make sure you can execute code that depends on the dojo.required
+		// 		modules, be sure to add the code that depends on the modules in a dojo.addOnLoad()
+		// 		callback. dojo.addOnLoad waits for all outstanding modules to finish loading before
+		// 		executing. Example:
+		// 
+		//	   	|	<script type="text/javascript">
+		//		|	dojo.require("foo");
+		//		|	dojo.require("bar");
+		//	   	|	dojo.addOnLoad(function(){
+		//	   	|		//you can now safely do something with foo and bar
+		//	   	|	});
+		//	   	|	</script>
+		// 
+		// 		This type of syntax works with both xdomain and normal loaders, so it is good
+		// 		practice to always use this idiom for on-the-fly code loading and in HTML script
+		// 		blocks. If at some point you change loaders and where the code is loaded from,
+		// 		it will all still work.
+		// 
+		// 		More on how dojo.require
+		//		`dojo.require("A.B")` first checks to see if symbol A.B is
+		//		defined. If it is, it is simply returned (nothing to do).
+		//	
+		//		If it is not defined, it will look for `A/B.js` in the script root
+		//		directory.
+		//	
+		//		`dojo.require` throws an excpetion if it cannot find a file
+		//		to load, or if the symbol `A.B` is not defined after loading.
+		//	
+		//		It returns the object `A.B`, but note the caveats above about on-the-fly loading and
+		// 		HTML script blocks when the xdomain loader is loading a module.
+		//	
+		//		`dojo.require()` does nothing about importing symbols into
+		//		the current namespace.  It is presumed that the caller will
+		//		take care of that. For example, to import all symbols into a
+		//		local block, you might write:
+		//	
+		//		|	with (dojo.require("A.B")) {
+		//		|		...
+		//		|	}
+		//	
+		//		And to import just the leaf symbol to a local variable:
+		//	
+		//		|	var B = dojo.require("A.B");
+		//	   	|	...
+		//	returns: the required namespace object
+		omitModuleCheck = d._global_omit_module_check || omitModuleCheck;
+
+		//Check if it is already loaded.
+		var module = d._loadedModules[moduleName];
+		if(module){
+			return module;
+		}
+
+		// convert periods to slashes
+		var relpath = d._getModuleSymbols(moduleName).join("/") + '.js';
+
+		var modArg = !omitModuleCheck ? moduleName : null;
+		var ok = d._loadPath(relpath, modArg);
+
+		if(!ok && !omitModuleCheck){
+			throw new Error("Could not load '" + moduleName + "'; last tried '" + relpath + "'");
+		}
+
+		// check that the symbol was defined
+		// Don't bother if we're doing xdomain (asynchronous) loading.
+		if(!omitModuleCheck && !d._isXDomain){
+			// pass in false so we can give better error
+			module = d._loadedModules[moduleName];
+			if(!module){
+				throw new Error("symbol '" + moduleName + "' is not defined after loading '" + relpath + "'"); 
+			}
+		}
+
+		return module;
+	}
+
+	dojo.provide = function(/*String*/ resourceName){
+		//	summary:
+		//		Register a resource with the package system. Works in conjunction with `dojo.require`
+		//
+		//	description:
+		//		Each javascript source file is called a resource.  When a
+		//		resource is loaded by the browser, `dojo.provide()` registers
+		//		that it has been loaded.
+		//
+		//		Each javascript source file must have at least one
+		//		`dojo.provide()` call at the top of the file, corresponding to
+		//		the file name.  For example, `js/dojo/foo.js` must have
+		//		`dojo.provide("dojo.foo");` before any calls to
+		//		`dojo.require()` are made.
+		//	
+		//		For backwards compatibility reasons, in addition to registering
+		//		the resource, `dojo.provide()` also ensures that the javascript
+		//		object for the module exists.  For example,
+		//		`dojo.provide("dojox.data.FlickrStore")`, in addition to
+		//		registering that `FlickrStore.js` is a resource for the
+		//		`dojox.data` module, will ensure that the `dojox.data`
+		//		javascript object exists, so that calls like 
+		//		`dojo.data.foo = function(){ ... }` don't fail.
+		//
+		//		In the case of a build where multiple javascript source files
+		//		are combined into one bigger file (similar to a .lib or .jar
+		//		file), that file may contain multiple dojo.provide() calls, to
+		//		note that it includes multiple resources.
+		//
+		// resourceName: String
+		//		A dot-sperated string identifying a resource. 
+		//
+		// example:
+		//	Safely create a `my` object, and make dojo.require("my.CustomModule") work
+		//	|	dojo.provide("my.CustomModule"); 
+
+		//Make sure we have a string.
+		resourceName = resourceName + "";
+		return (d._loadedModules[resourceName] = d.getObject(resourceName, true)); // Object
+	}
+
+	//Start of old bootstrap2:
+
+	dojo.platformRequire = function(/*Object*/modMap){
+		//	summary:
+		//		require one or more modules based on which host environment
+		//		Dojo is currently operating in
+		//	description:
+		//		This method takes a "map" of arrays which one can use to
+		//		optionally load dojo modules. The map is indexed by the
+		//		possible dojo.name_ values, with two additional values:
+		//		"default" and "common". The items in the "default" array will
+		//		be loaded if none of the other items have been choosen based on
+		//		dojo.name_, set by your host environment. The items in the
+		//		"common" array will *always* be loaded, regardless of which
+		//		list is chosen.
+		//	example:
+		//		|	dojo.platformRequire({
+		//		|		browser: [
+		//		|			"foo.sample", // simple module
+		//		|			"foo.test",
+		//		|			["foo.bar.baz", true] // skip object check in _loadModule (dojo.require)
+		//		|		],
+		//		|		default: [ "foo.sample._base" ],
+		//		|		common: [ "important.module.common" ]
+		//		|	});
+
+		var common = modMap.common || [];
+		var result = common.concat(modMap[d._name] || modMap["default"] || []);
+
+		for(var x=0; x<result.length; x++){
+			var curr = result[x];
+			if(curr.constructor == Array){
+				d._loadModule.apply(d, curr);
+			}else{
+				d._loadModule(curr);
+			}
+		}
+	}
+
+	dojo.requireIf = function(/*Boolean*/ condition, /*String*/ resourceName){
+		// summary:
+		//		If the condition is true then call `dojo.require()` for the specified
+		//		resource
+		//
+		// example:
+		//	|	dojo.requireIf(dojo.isBrowser, "my.special.Module");
+		
+		if(condition === true){
+			// FIXME: why do we support chained require()'s here? does the build system?
+			var args = [];
+			for(var i = 1; i < arguments.length; i++){ 
+				args.push(arguments[i]);
+			}
+			d.require.apply(d, args);
+		}
+	}
+
+	dojo.requireAfterIf = d.requireIf;
+
+	dojo.registerModulePath = function(/*String*/module, /*String*/prefix){
+		//	summary: 
+		//		Maps a module name to a path
+		//	description: 
+		//		An unregistered module is given the default path of ../[module],
+		//		relative to Dojo root. For example, module acme is mapped to
+		//		../acme.  If you want to use a different module name, use
+		//		dojo.registerModulePath. 
+		//	example:
+		//		If your dojo.js is located at this location in the web root:
+		//	|	/myapp/js/dojo/dojo/dojo.js
+		//		and your modules are located at:
+		//	|	/myapp/js/foo/bar.js
+		//	|	/myapp/js/foo/baz.js
+		//	|	/myapp/js/foo/thud/xyzzy.js
+		//		Your application can tell Dojo to locate the "foo" namespace by calling:
+		//	|	dojo.registerModulePath("foo", "../../foo");
+		//		At which point you can then use dojo.require() to load the
+		//		modules (assuming they provide() the same things which are
+		//		required). The full code might be:
+		//	|	<script type="text/javascript" 
+		//	|		src="/myapp/js/dojo/dojo/dojo.js"></script>
+		//	|	<script type="text/javascript">
+		//	|		dojo.registerModulePath("foo", "../../foo");
+		//	|		dojo.require("foo.bar");
+		//	|		dojo.require("foo.baz");
+		//	|		dojo.require("foo.thud.xyzzy");
+		//	|	</script>
+		d._modulePrefixes[module] = { name: module, value: prefix };
+	}
+
+	dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){
+		// summary:
+		//		Declares translated resources and loads them if necessary, in the
+		//		same style as dojo.require.  Contents of the resource bundle are
+		//		typically strings, but may be any name/value pair, represented in
+		//		JSON format.  See also `dojo.i18n.getLocalization`.
+		//
+		// description:
+		//		Load translated resource bundles provided underneath the "nls"
+		//		directory within a package.  Translated resources may be located in
+		//		different packages throughout the source tree.  
+		//
+		//		Each directory is named for a locale as specified by RFC 3066,
+		//		(http://www.ietf.org/rfc/rfc3066.txt), normalized in lowercase.
+		//		Note that the two bundles in the example do not define all the
+		//		same variants.  For a given locale, bundles will be loaded for
+		//		that locale and all more general locales above it, including a
+		//		fallback at the root directory.  For example, a declaration for
+		//		the "de-at" locale will first load `nls/de-at/bundleone.js`,
+		//		then `nls/de/bundleone.js` and finally `nls/bundleone.js`.  The
+		//		data will be flattened into a single Object so that lookups
+		//		will follow this cascading pattern.  An optional build step can
+		//		preload the bundles to avoid data redundancy and the multiple
+		//		network hits normally required to load these resources.
+		//
+		// moduleName: 
+		//		name of the package containing the "nls" directory in which the
+		//		bundle is found
+		//
+		// bundleName: 
+		//		bundle name, i.e. the filename without the '.js' suffix. Using "nls" as a
+		//		a bundle name is not supported, since "nls" is the name of the folder
+		//		that holds bundles. Using "nls" as the bundle name will cause problems
+		//		with the custom build.
+		//
+		// locale: 
+		//		the locale to load (optional)  By default, the browser's user
+		//		locale as defined by dojo.locale
+		//
+		// availableFlatLocales: 
+		//		A comma-separated list of the available, flattened locales for this
+		//		bundle. This argument should only be set by the build process.
+		//
+		//	example:
+		//		A particular widget may define one or more resource bundles,
+		//		structured in a program as follows, where moduleName is
+		//		mycode.mywidget and bundleNames available include bundleone and
+		//		bundletwo:
+		//	|		...
+		//	|	mycode/
+		//	|		mywidget/
+		//	|			nls/
+		//	|				bundleone.js (the fallback translation, English in this example)
+		//	|				bundletwo.js (also a fallback translation)
+		//	|				de/
+		//	|					bundleone.js
+		//	|					bundletwo.js
+		//	|				de-at/
+		//	|					bundleone.js
+		//	|				en/
+		//	|					(empty; use the fallback translation)
+		//	|				en-us/
+		//	|					bundleone.js
+		//	|				en-gb/
+		//	|					bundleone.js
+		//	|				es/
+		//	|					bundleone.js
+		//	|					bundletwo.js
+		//	|				  ...etc
+		//	|				...
+		//
+
+		d.require("dojo.i18n");
+		d.i18n._requireLocalization.apply(d.hostenv, arguments);
+	};
+
+
+	var ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"),
+		ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$");
+
+	dojo._Url = function(/*dojo._Url|String...*/){
+		// summary: 
+		//		Constructor to create an object representing a URL.
+		//		It is marked as private, since we might consider removing
+		//		or simplifying it.
+		// description: 
+		//		Each argument is evaluated in order relative to the next until
+		//		a canonical uri is produced. To get an absolute Uri relative to
+		//		the current document use:
+		//      	new dojo._Url(document.baseURI, url)
+
+		var n = null,
+			_a = arguments,
+			uri = [_a[0]];
+		// resolve uri components relative to each other
+		for(var i = 1; i<_a.length; i++){
+			if(!_a[i]){ continue; }
+
+			// Safari doesn't support this.constructor so we have to be explicit
+			// FIXME: Tracked (and fixed) in Webkit bug 3537.
+			//		http://bugs.webkit.org/show_bug.cgi?id=3537
+			var relobj = new d._Url(_a[i]+""),
+				uriobj = new d._Url(uri[0]+"");
+
+			if(
+				relobj.path == "" &&
+				!relobj.scheme &&
+				!relobj.authority &&
+				!relobj.query
+			){
+				if(relobj.fragment != n){
+					uriobj.fragment = relobj.fragment;
+				}
+				relobj = uriobj;
+			}else if(!relobj.scheme){
+				relobj.scheme = uriobj.scheme;
+
+				if(!relobj.authority){
+					relobj.authority = uriobj.authority;
+
+					if(relobj.path.charAt(0) != "/"){
+						var path = uriobj.path.substring(0,
+							uriobj.path.lastIndexOf("/") + 1) + relobj.path;
+
+						var segs = path.split("/");
+						for(var j = 0; j < segs.length; j++){
+							if(segs[j] == "."){
+								// flatten "./" references
+								if(j == segs.length - 1){
+									segs[j] = "";
+								}else{
+									segs.splice(j, 1);
+									j--;
+								}
+							}else if(j > 0 && !(j == 1 && segs[0] == "") &&
+								segs[j] == ".." && segs[j-1] != ".."){
+								// flatten "../" references
+								if(j == (segs.length - 1)){
+									segs.splice(j, 1);
+									segs[j - 1] = "";
+								}else{
+									segs.splice(j - 1, 2);
+									j -= 2;
+								}
+							}
+						}
+						relobj.path = segs.join("/");
+					}
+				}
+			}
+
+			uri = [];
+			if(relobj.scheme){ 
+				uri.push(relobj.scheme, ":");
+			}
+			if(relobj.authority){
+				uri.push("//", relobj.authority);
+			}
+			uri.push(relobj.path);
+			if(relobj.query){
+				uri.push("?", relobj.query);
+			}
+			if(relobj.fragment){
+				uri.push("#", relobj.fragment);
+			}
+		}
+
+		this.uri = uri.join("");
+
+		// break the uri into its main components
+		var r = this.uri.match(ore);
+
+		this.scheme = r[2] || (r[1] ? "" : n);
+		this.authority = r[4] || (r[3] ? "" : n);
+		this.path = r[5]; // can never be undefined
+		this.query = r[7] || (r[6] ? "" : n);
+		this.fragment  = r[9] || (r[8] ? "" : n);
+
+		if(this.authority != n){
+			// server based naming authority
+			r = this.authority.match(ire);
+
+			this.user = r[3] || n;
+			this.password = r[4] || n;
+			this.host = r[6] || r[7]; // ipv6 || ipv4
+			this.port = r[9] || n;
+		}
+	}
+
+	dojo._Url.prototype.toString = function(){ return this.uri; };
+
+	dojo.moduleUrl = function(/*String*/module, /*dojo._Url||String*/url){
+		//	summary: 
+		//		Returns a `dojo._Url` object relative to a module.
+		//	example:
+		//	|	var pngPath = dojo.moduleUrl("acme","images/small.png");
+		//	|	console.dir(pngPath); // list the object properties
+		//	|	// create an image and set it's source to pngPath's value:
+		//	|	var img = document.createElement("img");
+		// 	|	// NOTE: we assign the string representation of the url object
+		//	|	img.src = pngPath.toString(); 
+		//	|	// add our image to the document
+		//	|	dojo.body().appendChild(img);
+		//	example: 
+		//		you may de-reference as far as you like down the package
+		//		hierarchy.  This is sometimes handy to avoid lenghty relative
+		//		urls or for building portable sub-packages. In this example,
+		//		the `acme.widget` and `acme.util` directories may be located
+		//		under different roots (see `dojo.registerModulePath`) but the
+		//		the modules which reference them can be unaware of their
+		//		relative locations on the filesystem:
+		//	|	// somewhere in a configuration block
+		//	|	dojo.registerModulePath("acme.widget", "../../acme/widget");
+		//	|	dojo.registerModulePath("acme.util", "../../util");
+		//	|	
+		//	|	// ...
+		//	|	
+		//	|	// code in a module using acme resources
+		//	|	var tmpltPath = dojo.moduleUrl("acme.widget","templates/template.html");
+		//	|	var dataPath = dojo.moduleUrl("acme.util","resources/data.json");
+
+		var loc = d._getModuleSymbols(module).join('/');
+		if(!loc){ return null; }
+		if(loc.lastIndexOf("/") != loc.length-1){
+			loc += "/";
+		}
+		
+		//If the path is an absolute path (starts with a / or is on another
+		//domain/xdomain) then don't add the baseUrl.
+		var colonIndex = loc.indexOf(":");
+		if(loc.charAt(0) != "/" && (colonIndex == -1 || colonIndex > loc.indexOf("/"))){
+			loc = d.baseUrl + loc;
+		}
+
+		return new d._Url(loc, url); // dojo._Url
+	}
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 })();
-}
+//>>excludeEnd("webkitMobile");
diff --git a/dojo/_base/_loader/loader_debug.js b/dojo/_base/_loader/loader_debug.js
index 878e748..b85ee0b 100644
--- a/dojo/_base/_loader/loader_debug.js
+++ b/dojo/_base/_loader/loader_debug.js
@@ -1,59 +1,75 @@
-/*
-	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
-*/
+dojo.provide("dojo._base._loader.loader_debug");
 
+//Override dojo.provide, so we can trigger the next
+//script tag for the next local module. We can only add one
+//at a time because there are browsers that execute script tags
+//in the order that the code is received, and not in the DOM order.
+dojo.nonDebugProvide = dojo.provide;
 
-if(!dojo._hasResource["dojo._base._loader.loader_debug"]){
-dojo._hasResource["dojo._base._loader.loader_debug"]=true;
-dojo.provide("dojo._base._loader.loader_debug");
-dojo.nonDebugProvide=dojo.provide;
-dojo.provide=function(_1){
-var _2=dojo["_xdDebugQueue"];
-if(_2&&_2.length>0&&_1==_2["currentResourceName"]){
-if(dojo.isAIR){
-window.setTimeout(function(){
-dojo._xdDebugFileLoaded(_1);
-},1);
-}else{
-window.setTimeout(dojo._scopeName+"._xdDebugFileLoaded('"+_1+"')",1);
-}
-}
-return dojo.nonDebugProvide.apply(dojo,arguments);
-};
-dojo._xdDebugFileLoaded=function(_3){
-if(!dojo._xdDebugScopeChecked){
-if(dojo._scopeName!="dojo"){
-window.dojo=window[dojo.config.scopeMap[0][1]];
-window.dijit=window[dojo.config.scopeMap[1][1]];
-window.dojox=window[dojo.config.scopeMap[2][1]];
-}
-dojo._xdDebugScopeChecked=true;
-}
-var _4=dojo._xdDebugQueue;
-if(_3&&_3==_4.currentResourceName){
-_4.shift();
-}
-if(_4.length==0){
-dojo._xdWatchInFlight();
-}
-if(_4.length==0){
-_4.currentResourceName=null;
-for(var _5 in dojo._xdInFlight){
-if(dojo._xdInFlight[_5]===true){
-return;
-}
-}
-dojo._xdNotifyLoaded();
-}else{
-if(_3==_4.currentResourceName){
-_4.currentResourceName=_4[0].resourceName;
-var _6=document.createElement("script");
-_6.type="text/javascript";
-_6.src=_4[0].resourcePath;
-document.getElementsByTagName("head")[0].appendChild(_6);
-}
+dojo.provide = function(resourceName){
+	var dbgQueue = dojo["_xdDebugQueue"];
+	if(dbgQueue && dbgQueue.length > 0 && resourceName == dbgQueue["currentResourceName"]){
+		//Set a timeout so the module can be executed into existence. Normally the
+		//dojo.provide call in a module is the first line. Don't want to risk attaching
+		//another script tag until the current one finishes executing.
+		if(dojo.isAIR){
+			window.setTimeout(function(){dojo._xdDebugFileLoaded(resourceName);}, 1);
+		}else{
+			window.setTimeout(dojo._scopeName + "._xdDebugFileLoaded('" + resourceName + "')", 1);
+		}
+	}
+
+	return dojo.nonDebugProvide.apply(dojo, arguments);
 }
-};
+
+dojo._xdDebugFileLoaded = function(resourceName){
+
+	if(!dojo._xdDebugScopeChecked){
+		//If using a scoped dojo, we need to expose dojo as a real global
+		//for the debugAtAllCosts stuff to work.
+		if(dojo._scopeName != "dojo"){
+			window.dojo = window[dojo.config.scopeMap[0][1]];
+			window.dijit = window[dojo.config.scopeMap[1][1]];
+			window.dojox = window[dojo.config.scopeMap[2][1]];
+		}
+
+		dojo._xdDebugScopeChecked = true;
+	}
+	
+	var dbgQueue = dojo._xdDebugQueue;
+	
+	if(resourceName && resourceName == dbgQueue.currentResourceName){
+		dbgQueue.shift();
+	}
+
+	if(dbgQueue.length == 0){
+		//Check for more modules that need debug loading.
+		//dojo._xdWatchInFlight will add more things to the debug
+		//queue if they just recently loaded but it was not detected
+		//between the dojo._xdWatchInFlight intervals.
+		dojo._xdWatchInFlight();
+	}
+
+	if(dbgQueue.length == 0){
+		dbgQueue.currentResourceName = null;
+
+		//Make sure nothing else is in flight.
+		//If something is still in flight, then it still
+		//needs to be added to debug queue after it loads.
+		for(var param in dojo._xdInFlight){
+			if(dojo._xdInFlight[param] === true){
+				return;
+			}
+		}
+
+		dojo._xdNotifyLoaded();
+	}else{
+		if(resourceName == dbgQueue.currentResourceName){
+			dbgQueue.currentResourceName = dbgQueue[0].resourceName;
+			var element = document.createElement("script");
+			element.type = "text/javascript";
+			element.src = dbgQueue[0].resourcePath;
+			document.getElementsByTagName("head")[0].appendChild(element);
+		}
+	}
 }
diff --git a/dojo/_base/_loader/loader_xd.js b/dojo/_base/_loader/loader_xd.js
index 084071e..f8dca7d 100644
--- a/dojo/_base/_loader/loader_xd.js
+++ b/dojo/_base/_loader/loader_xd.js
@@ -1,465 +1,712 @@
-/*
-	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
-*/
+//Cross-domain resource loader.
+dojo.provide("dojo._base._loader.loader_xd");
 
+dojo._xdReset = function(){
+	//summary: Internal xd loader function. Resets the xd state.
 
-if(!dojo._hasResource["dojo._base._loader.loader_xd"]){
-dojo._hasResource["dojo._base._loader.loader_xd"]=true;
-dojo.provide("dojo._base._loader.loader_xd");
-dojo._xdReset=function(){
-dojo._isXDomain=dojo.config.useXDomain||false;
-dojo._xdClearInterval();
-dojo._xdInFlight={};
-dojo._xdOrderedReqs=[];
-dojo._xdDepMap={};
-dojo._xdContents=[];
-dojo._xdDefList=[];
-};
-dojo._xdClearInterval=function(){
-if(dojo._xdTimer){
-clearInterval(dojo._xdTimer);
-dojo._xdTimer=0;
-}
-};
-dojo._xdReset();
-dojo._xdCreateResource=function(_1,_2,_3){
-var _4=_1.replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,"");
-var _5=[];
-var _6=/dojo.(require|requireIf|provide|requireAfterIf|platformRequire|requireLocalization)\s*\(([\w\W]*?)\)/mg;
-var _7;
-while((_7=_6.exec(_4))!=null){
-if(_7[1]=="requireLocalization"){
-eval(_7[0]);
-}else{
-_5.push("\""+_7[1]+"\", "+_7[2]);
-}
-}
-var _8=[];
-_8.push(dojo._scopeName+"._xdResourceLoaded(function("+dojo._scopePrefixArgs+"){\n");
-var _9=dojo._xdExtractLoadInits(_1);
-if(_9){
-_1=_9[0];
-for(var i=1;i<_9.length;i++){
-_8.push(_9[i]+";\n");
-}
-}
-_8.push("return {");
-if(_5.length>0){
-_8.push("depends: [");
-for(i=0;i<_5.length;i++){
-if(i>0){
-_8.push(",\n");
-}
-_8.push("["+_5[i]+"]");
-}
-_8.push("],");
-}
-_8.push("\ndefineResource: function("+dojo._scopePrefixArgs+"){");
-if(!dojo.config["debugAtAllCosts"]||_2=="dojo._base._loader.loader_debug"){
-_8.push(_1);
-}
-_8.push("\n}, resourceName: '"+_2+"', resourcePath: '"+_3+"'};});");
-return _8.join("");
-};
-dojo._xdExtractLoadInits=function(_a){
-var _b=/dojo.loadInit\s*\(/g;
-_b.lastIndex=0;
-var _c=/[\(\)]/g;
-_c.lastIndex=0;
-var _d=[];
-var _e;
-while((_e=_b.exec(_a))){
-_c.lastIndex=_b.lastIndex;
-var _f=1;
-var _10;
-while((_10=_c.exec(_a))){
-if(_10[0]==")"){
-_f-=1;
-}else{
-_f+=1;
-}
-if(_f==0){
-break;
-}
-}
-if(_f!=0){
-throw "unmatched paren around character "+_c.lastIndex+" in: "+_a;
-}
-var _11=_b.lastIndex-_e[0].length;
-_d.push(_a.substring(_11,_c.lastIndex));
-var _12=_c.lastIndex-_11;
-_a=_a.substring(0,_11)+_a.substring(_c.lastIndex,_a.length);
-_b.lastIndex=_c.lastIndex-_12;
-_b.lastIndex=_c.lastIndex;
-}
-if(_d.length>0){
-_d.unshift(_a);
-}
-return (_d.length?_d:null);
-};
-dojo._xdIsXDomainPath=function(_13){
-var _14=_13.indexOf(":");
-var _15=_13.indexOf("/");
-if(_14>0&&_14<_15){
-return true;
-}else{
-var url=dojo.baseUrl;
-_14=url.indexOf(":");
-_15=url.indexOf("/");
-if(_14>0&&_14<_15&&(!location.host||url.indexOf("http://"+location.host)!=0)){
-return true;
-}
-}
-return false;
-};
-dojo._loadPath=function(_16,_17,cb){
-var _18=dojo._xdIsXDomainPath(_16);
-dojo._isXDomain|=_18;
-var uri=((_16.charAt(0)=="/"||_16.match(/^\w+:/))?"":dojo.baseUrl)+_16;
-try{
-return ((!_17||dojo._isXDomain)?dojo._loadUri(uri,cb,_18,_17):dojo._loadUriAndCheck(uri,_17,cb));
-}
-catch(e){
-console.error(e);
-return false;
-}
-};
-dojo._xdCharSet="utf-8";
-dojo._loadUri=function(uri,cb,_19,_1a){
-if(dojo._loadedUrls[uri]){
-return 1;
-}
-if(dojo._isXDomain&&_1a&&_1a!="dojo.i18n"){
-dojo._xdOrderedReqs.push(_1a);
-if(_19||uri.indexOf("/nls/")==-1){
-dojo._xdInFlight[_1a]=true;
-dojo._inFlightCount++;
-}
-if(!dojo._xdTimer){
-if(dojo.isAIR){
-dojo._xdTimer=setInterval(function(){
-dojo._xdWatchInFlight();
-},100);
-}else{
-dojo._xdTimer=setInterval(dojo._scopeName+"._xdWatchInFlight();",100);
-}
-}
-dojo._xdStartTime=(new Date()).getTime();
-}
-if(_19){
-var _1b=uri.lastIndexOf(".");
-if(_1b<=0){
-_1b=uri.length-1;
-}
-var _1c=uri.substring(0,_1b)+".xd";
-if(_1b!=uri.length-1){
-_1c+=uri.substring(_1b,uri.length);
-}
-if(dojo.isAIR){
-_1c=_1c.replace("app:/","/");
-}
-var _1d=document.createElement("script");
-_1d.type="text/javascript";
-if(dojo._xdCharSet){
-_1d.charset=dojo._xdCharSet;
-}
-_1d.src=_1c;
-if(!dojo.headElement){
-dojo._headElement=document.getElementsByTagName("head")[0];
-if(!dojo._headElement){
-dojo._headElement=document.getElementsByTagName("html")[0];
-}
-}
-dojo._headElement.appendChild(_1d);
-}else{
-var _1e=dojo._getText(uri,null,true);
-if(_1e==null){
-return 0;
-}
-if(dojo._isXDomain&&uri.indexOf("/nls/")==-1&&_1a!="dojo.i18n"){
-var res=dojo._xdCreateResource(_1e,_1a,uri);
-dojo.eval(res);
-}else{
-if(cb){
-_1e="("+_1e+")";
-}else{
-_1e=dojo._scopePrefix+_1e+dojo._scopeSuffix;
-}
-var _1f=dojo["eval"](_1e+"\r\n//@ sourceURL="+uri);
-if(cb){
-cb(_1f);
-}
-}
-}
-dojo._loadedUrls[uri]=true;
-dojo._loadedUrls.push(uri);
-return true;
-};
-dojo._xdResourceLoaded=function(res){
-res=res.apply(dojo.global,dojo._scopeArgs);
-var _20=res.depends;
-var _21=null;
-var _22=null;
-var _23=[];
-if(_20&&_20.length>0){
-var dep=null;
-var _24=0;
-var _25=false;
-for(var i=0;i<_20.length;i++){
-dep=_20[i];
-if(dep[0]=="provide"){
-_23.push(dep[1]);
-}else{
-if(!_21){
-_21=[];
-}
-if(!_22){
-_22=[];
-}
-var _26=dojo._xdUnpackDependency(dep);
-if(_26.requires){
-_21=_21.concat(_26.requires);
-}
-if(_26.requiresAfter){
-_22=_22.concat(_26.requiresAfter);
-}
-}
-var _27=dep[0];
-var _28=_27.split(".");
-if(_28.length==2){
-dojo[_28[0]][_28[1]].apply(dojo[_28[0]],dep.slice(1));
-}else{
-dojo[_27].apply(dojo,dep.slice(1));
-}
-}
-if(_23.length==1&&_23[0]=="dojo._base._loader.loader_debug"){
-res.defineResource(dojo);
-}else{
-var _29=dojo._xdContents.push({content:res.defineResource,resourceName:res["resourceName"],resourcePath:res["resourcePath"],isDefined:false})-1;
-for(i=0;i<_23.length;i++){
-dojo._xdDepMap[_23[i]]={requires:_21,requiresAfter:_22,contentIndex:_29};
-}
-}
-for(i=0;i<_23.length;i++){
-dojo._xdInFlight[_23[i]]=false;
-}
-}
-};
-dojo._xdLoadFlattenedBundle=function(_2a,_2b,_2c,_2d){
-_2c=_2c||"root";
-var _2e=dojo.i18n.normalizeLocale(_2c).replace("-","_");
-var _2f=[_2a,"nls",_2b].join(".");
-var _30=dojo["provide"](_2f);
-_30[_2e]=_2d;
-var _31=[_2a,_2e,_2b].join(".");
-var _32=dojo._xdBundleMap[_31];
-if(_32){
-for(var _33 in _32){
-_30[_33]=_2d;
-}
-}
-};
-dojo._xdInitExtraLocales=function(){
-var _34=dojo.config.extraLocale;
-if(_34){
-if(!_34 instanceof Array){
-_34=[_34];
-}
-dojo._xdReqLoc=dojo.xdRequireLocalization;
-dojo.xdRequireLocalization=function(m,b,_35,_36){
-dojo._xdReqLoc(m,b,_35,_36);
-if(_35){
-return;
-}
-for(var i=0;i<_34.length;i++){
-dojo._xdReqLoc(m,b,_34[i],_36);
-}
-};
-}
-};
-dojo._xdBundleMap={};
-dojo.xdRequireLocalization=function(_37,_38,_39,_3a){
-if(dojo._xdInitExtraLocales){
-dojo._xdInitExtraLocales();
-dojo._xdInitExtraLocales=null;
-dojo.xdRequireLocalization.apply(dojo,arguments);
-return;
-}
-var _3b=_3a.split(",");
-var _3c=dojo.i18n.normalizeLocale(_39);
-var _3d="";
-for(var i=0;i<_3b.length;i++){
-if(_3c.indexOf(_3b[i])==0){
-if(_3b[i].length>_3d.length){
-_3d=_3b[i];
-}
-}
-}
-var _3e=_3d.replace("-","_");
-var _3f=dojo.getObject([_37,"nls",_38].join("."));
-if(!_3f||!_3f[_3e]){
-var _40=[_37,(_3e||"root"),_38].join(".");
-var _41=dojo._xdBundleMap[_40];
-if(!_41){
-_41=dojo._xdBundleMap[_40]={};
-}
-_41[_3c.replace("-","_")]=true;
-dojo.require(_37+".nls"+(_3d?"."+_3d:"")+"."+_38);
-}
-};
-dojo._xdRealRequireLocalization=dojo.requireLocalization;
-dojo.requireLocalization=function(_42,_43,_44,_45){
-var _46=dojo.moduleUrl(_42).toString();
-if(dojo._xdIsXDomainPath(_46)){
-return dojo.xdRequireLocalization.apply(dojo,arguments);
-}else{
-return dojo._xdRealRequireLocalization.apply(dojo,arguments);
-}
-};
-dojo._xdUnpackDependency=function(dep){
-var _47=null;
-var _48=null;
-switch(dep[0]){
-case "requireIf":
-case "requireAfterIf":
-if(dep[1]===true){
-_47=[{name:dep[2],content:null}];
-}
-break;
-case "platformRequire":
-var _49=dep[1];
-var _4a=_49["common"]||[];
-_47=(_49[dojo.hostenv.name_])?_4a.concat(_49[dojo.hostenv.name_]||[]):_4a.concat(_49["default"]||[]);
-if(_47){
-for(var i=0;i<_47.length;i++){
-if(_47[i] instanceof Array){
-_47[i]={name:_47[i][0],content:null};
-}else{
-_47[i]={name:_47[i],content:null};
-}
-}
-}
-break;
-case "require":
-_47=[{name:dep[1],content:null}];
-break;
-case "i18n._preloadLocalizations":
-dojo.i18n._preloadLocalizations.apply(dojo.i18n._preloadLocalizations,dep.slice(1));
-break;
-}
-if(dep[0]=="requireAfterIf"||dep[0]=="requireIf"){
-_48=_47;
-_47=null;
-}
-return {requires:_47,requiresAfter:_48};
-};
-dojo._xdWalkReqs=function(){
-var _4b=null;
-var req;
-for(var i=0;i<dojo._xdOrderedReqs.length;i++){
-req=dojo._xdOrderedReqs[i];
-if(dojo._xdDepMap[req]){
-_4b=[req];
-_4b[req]=true;
-dojo._xdEvalReqs(_4b);
-}
-}
-};
-dojo._xdEvalReqs=function(_4c){
-while(_4c.length>0){
-var req=_4c[_4c.length-1];
-var res=dojo._xdDepMap[req];
-var i,_4d,_4e;
-if(res){
-_4d=res.requires;
-if(_4d&&_4d.length>0){
-for(i=0;i<_4d.length;i++){
-_4e=_4d[i].name;
-if(_4e&&!_4c[_4e]){
-_4c.push(_4e);
-_4c[_4e]=true;
-dojo._xdEvalReqs(_4c);
-}
+	//This flag indicates where or not we have crossed into xdomain territory. Once any resource says
+	//it is cross domain, then the rest of the resources have to be treated as xdomain because we need
+	//to evaluate resources in order. If there is a xdomain resource followed by a xhr resource, we can't load
+	//the xhr resource until the one before it finishes loading. The text of the xhr resource will be converted
+	//to match the format for a xd resource and put in the xd load queue.
+	dojo._isXDomain = dojo.config.useXDomain || false;
+
+	dojo._xdClearInterval();
+	dojo._xdInFlight = {};
+	dojo._xdOrderedReqs = [];
+	dojo._xdDepMap = {};
+	dojo._xdContents = [];
+	dojo._xdDefList = [];
 }
+
+dojo._xdClearInterval = function(){
+	//summary: Internal xd loader function.
+	//Clears the interval timer used to check on the
+	//status of in-flight xd module resource requests.
+	if(dojo._xdTimer){
+		clearInterval(dojo._xdTimer);
+		dojo._xdTimer = 0;
+	}
 }
-var _4f=dojo._xdContents[res.contentIndex];
-if(!_4f.isDefined){
-var _50=_4f.content;
-_50["resourceName"]=_4f["resourceName"];
-_50["resourcePath"]=_4f["resourcePath"];
-dojo._xdDefList.push(_50);
-_4f.isDefined=true;
+
+
+//Call reset immediately to set the state.
+dojo._xdReset();
+
+dojo._xdCreateResource = function(/*String*/contents, /*String*/resourceName, /*String*/resourcePath){
+	//summary: Internal xd loader function. Creates an xd module source given an
+	//non-xd module contents.
+
+	//Remove comments. Not perfect, but good enough for dependency resolution.
+	var depContents = contents.replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg , "");
+
+	//Find dependencies.
+	var deps = [];
+    var depRegExp = /dojo.(require|requireIf|provide|requireAfterIf|platformRequire|requireLocalization)\s*\(([\w\W]*?)\)/mg;
+    var match;
+	while((match = depRegExp.exec(depContents)) != null){
+		if(match[1] == "requireLocalization"){
+			//Need to load the local bundles asap, since they are not
+			//part of the list of modules watched for loading.
+			eval(match[0]);
+		}else{
+			deps.push('"' + match[1] + '", ' + match[2]);
+		}
+	}
+
+	//Create resource object and the call to _xdResourceLoaded.
+	var output = [];
+	output.push(dojo._scopeName + "._xdResourceLoaded(function(" + dojo._scopePrefixArgs + "){\n");
+
+	//See if there are any dojo.loadInit calls
+	var loadInitCalls = dojo._xdExtractLoadInits(contents);
+	if(loadInitCalls){
+		//Adjust fileContents since extractLoadInits removed something.
+		contents = loadInitCalls[0];
+		
+		//Add any loadInit calls to the top of the xd file.
+		for(var i = 1; i < loadInitCalls.length; i++){
+			output.push(loadInitCalls[i] + ";\n");
+		}
+	}
+
+	output.push("return {");
+
+	//Add dependencies
+	if(deps.length > 0){
+		output.push("depends: [");
+		for(i = 0; i < deps.length; i++){
+			if(i > 0){
+				output.push(",\n");
+			}
+			output.push("[" + deps[i] + "]");
+		}
+		output.push("],");
+	}
+
+	//Add the contents of the file inside a function.
+	//Pass in scope arguments so we can support multiple versions of the
+	//same module on a page.
+	output.push("\ndefineResource: function(" + dojo._scopePrefixArgs + "){");
+
+	//Don't put in the contents in the debugAtAllCosts case
+	//since the contents may have syntax errors. Let those
+	//get pushed up when the script tags are added to the page
+	//in the debugAtAllCosts case.
+	if(!dojo.config["debugAtAllCosts"] || resourceName == "dojo._base._loader.loader_debug"){
+		output.push(contents);
+	}
+	//Add isLocal property so we know if we have to do something different
+	//in debugAtAllCosts situations.
+	output.push("\n}, resourceName: '" + resourceName + "', resourcePath: '" + resourcePath + "'};});");
+	
+	return output.join(""); //String
 }
-dojo._xdDepMap[req]=null;
-_4d=res.requiresAfter;
-if(_4d&&_4d.length>0){
-for(i=0;i<_4d.length;i++){
-_4e=_4d[i].name;
-if(_4e&&!_4c[_4e]){
-_4c.push(_4e);
-_4c[_4e]=true;
-dojo._xdEvalReqs(_4c);
+
+dojo._xdExtractLoadInits = function(/*String*/fileContents){
+	//Extracts
+	var regexp = /dojo.loadInit\s*\(/g;
+	regexp.lastIndex = 0;
+
+	var parenRe = /[\(\)]/g;
+	parenRe.lastIndex = 0;
+
+	var results = [];
+	var matches;
+	while((matches = regexp.exec(fileContents))){
+		//Find end of the call by finding the matching end paren
+		parenRe.lastIndex = regexp.lastIndex;
+		var matchCount = 1;
+		var parenMatch;
+		while((parenMatch = parenRe.exec(fileContents))){
+			if(parenMatch[0] == ")"){
+				matchCount -= 1;
+			}else{
+				matchCount += 1;
+			}
+			if(matchCount == 0){
+				break;
+			}
+		}
+		
+		if(matchCount != 0){
+			throw "unmatched paren around character " + parenRe.lastIndex + " in: " + fileContents;
+		}
+
+		//Put the master matching string in the results.
+		var startIndex = regexp.lastIndex - matches[0].length;
+		results.push(fileContents.substring(startIndex, parenRe.lastIndex));
+
+		//Remove the matching section.
+		var remLength = parenRe.lastIndex - startIndex;
+		fileContents = fileContents.substring(0, startIndex) + fileContents.substring(parenRe.lastIndex, fileContents.length);
+
+		//Move the master regexp past the last matching paren point.
+		regexp.lastIndex = parenRe.lastIndex - remLength;
+
+		regexp.lastIndex = parenRe.lastIndex;
+	}
+
+	if(results.length > 0){
+		results.unshift(fileContents);
+	}
+
+	return (results.length ? results : null);
 }
+
+dojo._xdIsXDomainPath = function(/*string*/relpath) {
+    //summary: Figure out whether the path is local or x-domain
+	//If there is a colon before the first / then, we have a URL with a protocol.
+    
+	var colonIndex = relpath.indexOf(":");
+	var slashIndex = relpath.indexOf("/");
+
+	if(colonIndex > 0 && colonIndex < slashIndex){
+		return true;
+	}else{
+		//Is the base script URI-based URL a cross domain URL?
+		//If so, then the relpath will be evaluated relative to
+		//baseUrl, and therefore qualify as xdomain.
+		//Only treat it as xdomain if the page does not have a
+		//host (file:// url) or if the baseUrl does not match the
+		//current window's domain.
+		var url = dojo.baseUrl;
+		colonIndex = url.indexOf(":");
+		slashIndex = url.indexOf("/");
+		if(colonIndex > 0 && colonIndex < slashIndex && (!location.host || url.indexOf("http://" + location.host) != 0)){
+			return true;
+		}
+	}
+    return false;     
 }
+
+dojo._loadPath = function(/*String*/relpath, /*String?*/module, /*Function?*/cb){
+	//summary: Internal xd loader function. Overrides loadPath() from loader.js.
+	//xd loading requires slightly different behavior from loadPath().
+
+	var currentIsXDomain = dojo._xdIsXDomainPath(relpath);
+    dojo._isXDomain |= currentIsXDomain;
+
+	var uri = ((relpath.charAt(0) == '/' || relpath.match(/^\w+:/)) ? "" : dojo.baseUrl) + relpath;
+
+	try{
+		return ((!module || dojo._isXDomain) ? dojo._loadUri(uri, cb, currentIsXDomain, module) : dojo._loadUriAndCheck(uri, module, cb)); //Boolean
+	}catch(e){
+		console.error(e);
+		return false; //Boolean
+	}
 }
+
+dojo._xdCharSet = "utf-8";
+
+dojo._loadUri = function(/*String*/uri, /*Function?*/cb, /*boolean*/currentIsXDomain, /*String?*/module){
+	//summary: Internal xd loader function. Overrides loadUri() from loader.js.
+	//		xd loading requires slightly different behavior from loadPath().
+	//description: Wanted to override getText(), but it is used by
+	//		the widget code in too many, synchronous ways right now.
+	if(dojo._loadedUrls[uri]){
+		return 1; //Boolean
+	}
+
+	//Add the module (resource) to the list of modules.
+	//Only do this work if we have a modlue name. Otherwise, 
+	//it is a non-xd i18n bundle, which can load immediately and does not 
+	//need to be tracked. Also, don't track dojo.i18n, since it is a prerequisite
+	//and will be loaded correctly if we load it right away: it has no dependencies.
+	if(dojo._isXDomain && module && module != "dojo.i18n"){
+		dojo._xdOrderedReqs.push(module);
+
+		//Add to waiting resources if it is an xdomain resource.
+		//Don't add non-xdomain i18n bundles, those get evaled immediately.
+		if(currentIsXDomain || uri.indexOf("/nls/") == -1){
+			dojo._xdInFlight[module] = true;
+
+			//Increment inFlightCount
+			//This will stop the modulesLoaded from firing all the way.
+			dojo._inFlightCount++;
+		}
+
+		//Start timer
+		if(!dojo._xdTimer){
+			if(dojo.isAIR){
+				dojo._xdTimer = setInterval(function(){dojo._xdWatchInFlight();}, 100);
+			}else{
+				dojo._xdTimer = setInterval(dojo._scopeName + "._xdWatchInFlight();", 100);
+			}
+		}
+		dojo._xdStartTime = (new Date()).getTime();
+	}
+
+	if (currentIsXDomain){
+		//Fix name to be a .xd.fileextension name.
+		var lastIndex = uri.lastIndexOf('.');
+		if(lastIndex <= 0){
+			lastIndex = uri.length - 1;
+		}
+
+		var xdUri = uri.substring(0, lastIndex) + ".xd";
+		if(lastIndex != uri.length - 1){
+			xdUri += uri.substring(lastIndex, uri.length);
+		}
+
+		if (dojo.isAIR){
+			xdUri = xdUri.replace("app:/", "/");
+		}
+
+		//Add to script src
+		var element = document.createElement("script");
+		element.type = "text/javascript";
+		if(dojo._xdCharSet){
+			element.charset = dojo._xdCharSet;
+		}
+		element.src = xdUri;
+		if(!dojo.headElement){
+			dojo._headElement = document.getElementsByTagName("head")[0];
+
+			//Head element may not exist, particularly in html
+			//html 4 or tag soup cases where the page does not
+			//have a head tag in it. Use html element, since that will exist.
+			//Seems to be an issue mostly with Opera 9 and to lesser extent Safari 2
+			if(!dojo._headElement){
+				dojo._headElement = document.getElementsByTagName("html")[0];
+			}
+		}
+		dojo._headElement.appendChild(element);
+	}else{
+		var contents = dojo._getText(uri, null, true);
+		if(contents == null){ return 0; /*boolean*/}
+		
+		//If this is not xdomain, or if loading a i18n resource bundle, then send it down
+		//the normal eval/callback path.
+		if(dojo._isXDomain
+			&& uri.indexOf("/nls/") == -1
+			&& module != "dojo.i18n"){
+			var res = dojo._xdCreateResource(contents, module, uri);
+			dojo.eval(res);
+		}else{
+			if(cb){
+				contents = '('+contents+')';
+			}else{
+				//Only do the scoping if no callback. If a callback is specified,
+				//it is most likely the i18n bundle stuff.
+				contents = dojo._scopePrefix + contents + dojo._scopeSuffix;
+			}
+			var value = dojo["eval"](contents+"\r\n//@ sourceURL="+uri);
+			if(cb){
+				cb(value);
+			}
+		}
+	}
+
+	//These steps are done in the non-xd loader version of this function.
+	//Maintain these steps to fit in with the existing system.
+	dojo._loadedUrls[uri] = true;
+	dojo._loadedUrls.push(uri);
+	return true; //Boolean
 }
-_4c.pop();
+
+dojo._xdResourceLoaded = function(/*Object*/res){
+	//summary: Internal xd loader function. Called by an xd module resource when
+	//it has been loaded via a script tag.
+	
+	//Evaluate the function with scopeArgs for multiversion support.
+	res = res.apply(dojo.global, dojo._scopeArgs);
+
+	//Work through dependencies.
+	var deps = res.depends;
+	var requireList = null;
+	var requireAfterList = null;
+	var provideList = [];
+	if(deps && deps.length > 0){
+		var dep = null;
+		var insertHint = 0;
+		var attachedResource = false;
+		for(var i = 0; i < deps.length; i++){
+			dep = deps[i];
+
+			//Look for specific dependency indicators.
+			if (dep[0] == "provide"){
+				provideList.push(dep[1]);
+			}else{
+				if(!requireList){
+					requireList = [];
+				}
+				if(!requireAfterList){
+					requireAfterList = [];
+				}
+
+				var unpackedDeps = dojo._xdUnpackDependency(dep);
+				if(unpackedDeps.requires){
+					requireList = requireList.concat(unpackedDeps.requires);
+				}
+				if(unpackedDeps.requiresAfter){
+					requireAfterList = requireAfterList.concat(unpackedDeps.requiresAfter);
+				}
+			}
+
+			//Call the dependency indicator to allow for the normal dojo setup.
+			//Only allow for one dot reference, for the i18n._preloadLocalizations calls
+			//(and maybe future, one-dot things).
+			var depType = dep[0];
+			var objPath = depType.split(".");
+			if(objPath.length == 2){
+				dojo[objPath[0]][objPath[1]].apply(dojo[objPath[0]], dep.slice(1));
+			}else{
+				dojo[depType].apply(dojo, dep.slice(1));
+			}
+		}
+
+
+		//If loading the debugAtAllCosts module, eval it right away since we need
+		//its functions to properly load the other modules.
+		if(provideList.length == 1 && provideList[0] == "dojo._base._loader.loader_debug"){
+			res.defineResource(dojo);
+		}else{
+			//Save off the resource contents for definition later.
+			var contentIndex = dojo._xdContents.push({
+					content: res.defineResource,
+					resourceName: res["resourceName"],
+					resourcePath: res["resourcePath"],
+					isDefined: false
+				}) - 1;
+	
+			//Add provide/requires to dependency map.
+			for(i = 0; i < provideList.length; i++){
+				dojo._xdDepMap[provideList[i]] = { requires: requireList, requiresAfter: requireAfterList, contentIndex: contentIndex };
+			}
+		}
+
+		//Now update the inflight status for any provided resources in this loaded resource.
+		//Do this at the very end (in a *separate* for loop) to avoid shutting down the 
+		//inflight timer check too soon.
+		for(i = 0; i < provideList.length; i++){
+			dojo._xdInFlight[provideList[i]] = false;
+		}
+	}
 }
+
+dojo._xdLoadFlattenedBundle = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*Object*/bundleData){
+	//summary: Internal xd loader function. Used when loading
+	//a flattened localized bundle via a script tag.
+	locale = locale || "root";
+	var jsLoc = dojo.i18n.normalizeLocale(locale).replace('-', '_');
+ 	var bundleResource = [moduleName, "nls", bundleName].join(".");
+	var bundle = dojo["provide"](bundleResource);
+	bundle[jsLoc] = bundleData;
+	
+	//Assign the bundle for the original locale(s) we wanted.
+	var mapName = [moduleName, jsLoc, bundleName].join(".");
+	var bundleMap = dojo._xdBundleMap[mapName];
+	if(bundleMap){
+		for(var param in bundleMap){
+			bundle[param] = bundleData;
+		}
+	}
 };
-dojo._xdWatchInFlight=function(){
-var _51="";
-var _52=(dojo.config.xdWaitSeconds||15)*1000;
-var _53=(dojo._xdStartTime+_52)<(new Date()).getTime();
-for(var _54 in dojo._xdInFlight){
-if(dojo._xdInFlight[_54]===true){
-if(_53){
-_51+=_54+" ";
-}else{
-return;
-}
-}
-}
-dojo._xdClearInterval();
-if(_53){
-throw "Could not load cross-domain resources: "+_51;
-}
-dojo._xdWalkReqs();
-var _55=dojo._xdDefList.length;
-for(var i=0;i<_55;i++){
-var _56=dojo._xdDefList[i];
-if(dojo.config["debugAtAllCosts"]&&_56["resourceName"]){
-if(!dojo["_xdDebugQueue"]){
-dojo._xdDebugQueue=[];
-}
-dojo._xdDebugQueue.push({resourceName:_56.resourceName,resourcePath:_56.resourcePath});
-}else{
-_56.apply(dojo.global,dojo._scopeArgs);
-}
+
+
+dojo._xdInitExtraLocales = function(){
+	// Simulate the extra locale work that dojo.requireLocalization does.
+
+	var extra = dojo.config.extraLocale;
+	if(extra){
+		if(!extra instanceof Array){
+			extra = [extra];
+		}
+
+		dojo._xdReqLoc = dojo.xdRequireLocalization;
+		dojo.xdRequireLocalization = function(m, b, locale, fLocales){
+			dojo._xdReqLoc(m,b,locale, fLocales);
+			if(locale){return;}
+			for(var i=0; i<extra.length; i++){
+				dojo._xdReqLoc(m,b,extra[i], fLocales);
+			}
+		};
+	}
 }
-for(i=0;i<dojo._xdContents.length;i++){
-var _57=dojo._xdContents[i];
-if(_57.content&&!_57.isDefined){
-_57.content.apply(dojo.global,dojo._scopeArgs);
+
+dojo._xdBundleMap = {};
+
+dojo.xdRequireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String*/availableFlatLocales){
+	//summary: Internal xd loader function. The xd version of dojo.requireLocalization.
+	
+
+	//Account for allowing multiple extra locales. Do this here inside the function
+	//since dojo._xdInitExtraLocales() depends on djConfig being set up, but that only
+	//happens after hostenv_browser runs. loader_xd has to come before hostenv_browser
+	//though since hostenv_browser can do a dojo.require for the debug module.
+	if(dojo._xdInitExtraLocales){
+		dojo._xdInitExtraLocales();
+		dojo._xdInitExtraLocales = null;
+		dojo.xdRequireLocalization.apply(dojo, arguments);
+		return;
+	}
+
+	var locales = availableFlatLocales.split(",");
+	
+	//Find the best-match locale to load.
+	//Assumes dojo.i18n has already been loaded. This is true for xdomain builds,
+	//since it is included in dojo.xd.js.
+	var jsLoc = dojo.i18n.normalizeLocale(locale);
+
+	var bestLocale = "";
+	for(var i = 0; i < locales.length; i++){
+		//Locale must match from start of string.
+		if(jsLoc.indexOf(locales[i]) == 0){
+			if(locales[i].length > bestLocale.length){
+				bestLocale = locales[i];
+			}
+		}
+	}
+
+	var fixedBestLocale = bestLocale.replace('-', '_');
+	//See if the bundle we are going to use is already loaded.
+ 	var bundleResource = dojo.getObject([moduleName, "nls", bundleName].join("."));
+	if(!bundleResource || !bundleResource[fixedBestLocale]){
+		//Need to remember what locale we wanted and which one we actually use.
+		//Then when we load the one we are actually using, use that bundle for the one
+		//we originally wanted.
+		var mapName = [moduleName, (fixedBestLocale||"root"), bundleName].join(".");
+		var bundleMap = dojo._xdBundleMap[mapName];
+		if(!bundleMap){
+			bundleMap = dojo._xdBundleMap[mapName] = {};
+		}
+		bundleMap[jsLoc.replace('-', '_')] = true;
+		
+		//Do just a normal dojo.require so the resource tracking stuff works as usual.
+		dojo.require(moduleName + ".nls" + (bestLocale ? "." + bestLocale : "") + "." + bundleName);
+	}
 }
+
+// Replace dojo.requireLocalization with a wrapper
+dojo._xdRealRequireLocalization = dojo.requireLocalization;
+dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String*/availableFlatLocales){
+    // summary: loads a bundle intelligently based on whether the module is 
+    // local or xd. Overrides the local-case implementation.
+    
+    var modulePath = dojo.moduleUrl(moduleName).toString();
+    if (dojo._xdIsXDomainPath(modulePath)) {
+        // call cross-domain loader
+        return dojo.xdRequireLocalization.apply(dojo, arguments);
+    } else {
+        // call local-loader
+        return dojo._xdRealRequireLocalization.apply(dojo, arguments);
+    }
 }
-dojo._xdReset();
-if(dojo["_xdDebugQueue"]&&dojo._xdDebugQueue.length>0){
-dojo._xdDebugFileLoaded();
-}else{
-dojo._xdNotifyLoaded();
+
+//This is a bit brittle: it has to know about the dojo methods that deal with dependencies
+//It would be ideal to intercept the actual methods and do something fancy at that point,
+//but I have concern about knowing which provide to match to the dependency in that case,
+//since scripts can load whenever they want, and trigger new calls to dojo._xdResourceLoaded().
+dojo._xdUnpackDependency = function(/*Array*/dep){
+	//summary: Internal xd loader function. Determines what to do with a dependency
+	//that was listed in an xd version of a module contents.
+
+	//Extract the dependency(ies).
+	var newDeps = null;
+	var newAfterDeps = null;
+	switch(dep[0]){
+		case "requireIf":
+		case "requireAfterIf":
+			//First arg (dep[1]) is the test. Depedency is dep[2].
+			if(dep[1] === true){
+				newDeps = [{name: dep[2], content: null}];
+			}
+			break;
+		case "platformRequire":
+			var modMap = dep[1];
+			var common = modMap["common"]||[];
+			newDeps = (modMap[dojo.hostenv.name_]) ? common.concat(modMap[dojo.hostenv.name_]||[]) : common.concat(modMap["default"]||[]);	
+			//Flatten the array of arrays into a one-level deep array.
+			//Each result could be an array of 3 elements  (the 3 arguments to dojo.require).
+			//We only need the first one.
+			if(newDeps){
+				for(var i = 0; i < newDeps.length; i++){
+					if(newDeps[i] instanceof Array){
+						newDeps[i] = {name: newDeps[i][0], content: null};
+					}else{
+						newDeps[i] = {name: newDeps[i], content: null};
+					}
+				}
+			}
+			break;
+		case "require":
+			//Just worry about dep[1]
+			newDeps = [{name: dep[1], content: null}];
+			break;
+		case "i18n._preloadLocalizations":
+			//We can eval these immediately, since they load i18n bundles.
+			//Since i18n bundles have no dependencies, whenever they are loaded
+			//in a script tag, they are evaluated immediately, so we do not have to
+			//treat them has an explicit dependency for the dependency mapping.
+			//We can call it immediately since dojo.i18n is part of dojo.xd.js.
+			dojo.i18n._preloadLocalizations.apply(dojo.i18n._preloadLocalizations, dep.slice(1));
+			break;
+	}
+
+	//The requireIf and requireAfterIf needs to be evaluated after the current resource is evaluated.
+	if(dep[0] == "requireAfterIf" || dep[0] == "requireIf"){
+		newAfterDeps = newDeps;
+		newDeps = null;
+	}
+	return {requires: newDeps, requiresAfter: newAfterDeps}; //Object
 }
-};
-dojo._xdNotifyLoaded=function(){
-for(var _58 in dojo._xdInFlight){
-if(typeof dojo._xdInFlight[_58]=="boolean"){
-return;
+
+dojo._xdWalkReqs = function(){
+	//summary: Internal xd loader function. 
+	//Walks the requires and evaluates module resource contents in
+	//the right order.
+	var reqChain = null;
+	var req;
+	for(var i = 0; i < dojo._xdOrderedReqs.length; i++){
+		req = dojo._xdOrderedReqs[i];
+		if(dojo._xdDepMap[req]){
+			reqChain = [req];
+			reqChain[req] = true; //Allow for fast lookup of the req in the array
+			dojo._xdEvalReqs(reqChain);
+		}
+	}
 }
+
+dojo._xdEvalReqs = function(/*Array*/reqChain){
+	//summary: Internal xd loader function. 
+	//Does a depth first, breadth second search and eval of required modules.
+	while(reqChain.length > 0){
+		var req = reqChain[reqChain.length - 1];
+		var res = dojo._xdDepMap[req];
+		var i, reqs, nextReq;
+		if(res){
+			//Trace down any requires for this resource.
+			//START dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
+			reqs = res.requires;
+			if(reqs && reqs.length > 0){
+				for(i = 0; i < reqs.length; i++){
+					nextReq = reqs[i].name;
+					if(nextReq && !reqChain[nextReq]){
+						//New req depedency. Follow it down.
+						reqChain.push(nextReq);
+						reqChain[nextReq] = true;
+						dojo._xdEvalReqs(reqChain);
+					}
+				}
+			}
+			//END dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
+
+			//Evaluate the resource.
+			var contents = dojo._xdContents[res.contentIndex];
+			if(!contents.isDefined){
+				var content = contents.content;
+				content["resourceName"] = contents["resourceName"];
+				content["resourcePath"] = contents["resourcePath"];
+				dojo._xdDefList.push(content);
+				contents.isDefined = true;
+			}
+			dojo._xdDepMap[req] = null;
+
+			//Trace down any requireAfters for this resource.
+			//START dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
+			reqs = res.requiresAfter;
+			if(reqs && reqs.length > 0){
+				for(i = 0; i < reqs.length; i++){
+					nextReq = reqs[i].name;
+					if(nextReq && !reqChain[nextReq]){
+						//New req depedency. Follow it down.
+						reqChain.push(nextReq);
+						reqChain[nextReq] = true;
+						dojo._xdEvalReqs(reqChain);
+					}
+				}
+			}
+			//END dojo._xdTraceReqs() inlining for small Safari 2.0 call stack
+		}
+
+		//Done with that require. Remove it and go to the next one.
+		reqChain.pop();
+	}
 }
-dojo._inFlightCount=0;
-if(dojo._initFired&&!dojo._loadNotifying){
-dojo._callLoaded();
+
+dojo._xdWatchInFlight = function(){
+	//summary: Internal xd loader function.
+	//Monitors in-flight requests for xd module resources.
+
+	var noLoads = "";
+	var waitInterval = (dojo.config.xdWaitSeconds || 15) * 1000;
+	var expired = (dojo._xdStartTime + waitInterval) < (new Date()).getTime();
+
+	//If any xdInFlight are true, then still waiting for something to load.
+	//Come back later. If we timed out, report the things that did not load.
+	for(var param in dojo._xdInFlight){
+		if(dojo._xdInFlight[param] === true){
+			if(expired){
+				noLoads += param + " ";
+			}else{
+				return;
+			}
+		}
+	}
+
+	//All done. Clean up and notify.
+	dojo._xdClearInterval();
+
+	if(expired){
+		throw "Could not load cross-domain resources: " + noLoads;
+	}
+
+	dojo._xdWalkReqs();
+	
+	var defLength = dojo._xdDefList.length;
+	for(var i= 0; i < defLength; i++){
+		var content = dojo._xdDefList[i];
+		if(dojo.config["debugAtAllCosts"] && content["resourceName"]){
+			if(!dojo["_xdDebugQueue"]){
+				dojo._xdDebugQueue = [];
+			}
+			dojo._xdDebugQueue.push({resourceName: content.resourceName, resourcePath: content.resourcePath});
+		}else{
+			//Evaluate the resource to bring it into being.
+			//Pass in scope args to allow multiple versions of modules in a page.	
+			content.apply(dojo.global, dojo._scopeArgs);
+		}
+	}
+
+	//Evaluate any resources that were not evaled before.
+	//This normally shouldn't happen with proper dojo.provide and dojo.require
+	//usage, but providing it just in case. Note that these may not be executed
+	//in the original order that the developer intended.
+	for(i = 0; i < dojo._xdContents.length; i++){
+		var current = dojo._xdContents[i];
+		if(current.content && !current.isDefined){
+			//Pass in scope args to allow multiple versions of modules in a page.	
+			current.content.apply(dojo.global, dojo._scopeArgs);
+		}
+	}
+
+	//Clean up for the next round of xd loading.
+	dojo._xdReset();
+
+	if(dojo["_xdDebugQueue"] && dojo._xdDebugQueue.length > 0){
+		dojo._xdDebugFileLoaded();
+	}else{
+		dojo._xdNotifyLoaded();
+	}
 }
-};
+
+dojo._xdNotifyLoaded = function(){
+	//Clear inflight count so we will finally do finish work.
+
+	//Just having a legitimate status (true or false) for an inflight item
+	//means that it is still being processed. Do the typeof test
+	//to avoid bad JavaScript that might tinker with Object.prototype.
+	for(var prop in dojo._xdInFlight){
+		if(typeof dojo._xdInFlight[prop] == "boolean"){
+			return;
+		}
+	}
+
+	dojo._inFlightCount = 0; 
+
+	//Only trigger call loaded if dj_load_init has run. 
+	if(dojo._initFired && !dojo._loadNotifying){ 
+		dojo._callLoaded();
+	}
 }
diff --git a/dojo/_base/array.js b/dojo/_base/array.js
index 6d4d797..4aca04f 100644
--- a/dojo/_base/array.js
+++ b/dojo/_base/array.js
@@ -1,79 +1,269 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.array"]){
-dojo._hasResource["dojo._base.array"]=true;
 dojo.require("dojo._base.lang");
 dojo.provide("dojo._base.array");
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 (function(){
-var _1=function(_2,_3,cb){
-return [(typeof _2=="string")?_2.split(""):_2,_3||dojo.global,(typeof cb=="string")?new Function("item","index","array",cb):cb];
-};
-var _4=function(_5,_6,_7,_8){
-var _9=_1(_6,_8,_7);
-_6=_9[0];
-for(var i=0,l=_6.length;i<l;++i){
-var _a=!!_9[2].call(_9[1],_6[i],i,_6);
-if(_5^_a){
-return _a;
-}
-}
-return _5;
-};
-dojo.mixin(dojo,{indexOf:function(_b,_c,_d,_e){
-var _f=1,end=_b.length||0,i=0;
-if(_e){
-i=end-1;
-_f=end=-1;
-}
-if(_d!=undefined){
-i=_d;
-}
-if((_e&&i>end)||i<end){
-for(;i!=end;i+=_f){
-if(_b[i]==_c){
-return i;
-}
-}
-}
-return -1;
-},lastIndexOf:function(_10,_11,_12){
-return dojo.indexOf(_10,_11,_12,true);
-},forEach:function(arr,_13,_14){
-if(!arr||!arr.length){
-return;
-}
-var _15=_1(arr,_14,_13);
-arr=_15[0];
-for(var i=0,l=arr.length;i<l;++i){
-_15[2].call(_15[1],arr[i],i,arr);
-}
-},every:function(arr,_16,_17){
-return _4(true,arr,_16,_17);
-},some:function(arr,_18,_19){
-return _4(false,arr,_18,_19);
-},map:function(arr,_1a,_1b){
-var _1c=_1(arr,_1b,_1a);
-arr=_1c[0];
-var _1d=(arguments[3]?(new arguments[3]()):[]);
-for(var i=0,l=arr.length;i<l;++i){
-_1d.push(_1c[2].call(_1c[1],arr[i],i,arr));
-}
-return _1d;
-},filter:function(arr,_1e,_1f){
-var _20=_1(arr,_1f,_1e);
-arr=_20[0];
-var _21=[];
-for(var i=0,l=arr.length;i<l;++i){
-if(_20[2].call(_20[1],arr[i],i,arr)){
-_21.push(arr[i]);
-}
-}
-return _21;
-}});
+	var _getParts = function(arr, obj, cb){
+		return [ 
+			(typeof arr == "string") ? arr.split("") : arr, 
+			obj || dojo.global,
+			// FIXME: cache the anonymous functions we create here?
+			(typeof cb == "string") ? new Function("item", "index", "array", cb) : cb
+		];
+	};
+
+	var everyOrSome = function(/*Boolean*/every, /*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
+		var _p = _getParts(arr, thisObject, callback); arr = _p[0];
+		for(var i=0,l=arr.length; i<l; ++i){
+			var result = !!_p[2].call(_p[1], arr[i], i, arr);
+			if(every ^ result){
+				return result; // Boolean
+			}
+		}
+		return every; // Boolean
+	};
+
+	dojo.mixin(dojo, {
+		indexOf: function(	/*Array*/		array, 
+							/*Object*/		value,
+							/*Integer?*/	fromIndex,
+							/*Boolean?*/	findLast){
+			// summary:
+			//		locates the first index of the provided value in the
+			//		passed array. If the value is not found, -1 is returned.
+			// description:
+			//		This method corresponds to the JavaScript 1.6 Array.indexOf method, with one difference: when
+			//		run over sparse arrays, the Dojo function invokes the callback for every index whereas JavaScript 
+			//		1.6's indexOf skips the holes in the sparse array.
+			//		For details on this method, see:
+			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/indexOf
+
+			var step = 1, end = array.length || 0, i = 0;
+			if(findLast){
+				i = end - 1;
+				step = end = -1;
+			}
+			if(fromIndex != undefined){ i = fromIndex; }
+			if((findLast && i > end) || i < end){
+				for(; i != end; i += step){
+					if(array[i] == value){ return i; }
+				}
+			}
+			return -1;	// Number
+		},
+
+		lastIndexOf: function(/*Array*/array, /*Object*/value, /*Integer?*/fromIndex){
+			// summary:
+			//		locates the last index of the provided value in the passed
+			//		array. If the value is not found, -1 is returned.
+			// description:
+			//		This method corresponds to the JavaScript 1.6 Array.lastIndexOf method, with one difference: when
+			//		run over sparse arrays, the Dojo function invokes the callback for every index whereas JavaScript 
+			//		1.6's lastIndexOf skips the holes in the sparse array.
+			//		For details on this method, see:
+			// 			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/lastIndexOf
+			return dojo.indexOf(array, value, fromIndex, true); // Number
+		},
+
+		forEach: function(/*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
+			//	summary:
+			//		for every item in arr, callback is invoked. Return values are ignored.
+			//		If you want to break out of the loop, consider using dojo.every() or dojo.some().
+			//		forEach does not allow breaking out of the loop over the items in arr.
+			//	arr:
+			//		the array to iterate over. If a string, operates on individual characters.
+			//	callback:
+			//		a function is invoked with three arguments: item, index, and array
+			//	thisObject:
+			//		may be used to scope the call to callback
+			//	description:
+			//		This function corresponds to the JavaScript 1.6 Array.forEach() method, with one difference: when 
+			//		run over sparse arrays, this implemenation passes the "holes" in the sparse array to
+			//		the callback function with a value of undefined. JavaScript 1.6's forEach skips the holes in the sparse array.
+			//		For more details, see:
+			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/forEach
+			//	example:
+			//	|	// log out all members of the array:
+			//	|	dojo.forEach(
+			//	|		[ "thinger", "blah", "howdy", 10 ],
+			//	|		function(item){
+			//	|			console.log(item);
+			//	|		}
+			//	|	);
+			//	example:
+			//	|	// log out the members and their indexes
+			//	|	dojo.forEach(
+			//	|		[ "thinger", "blah", "howdy", 10 ],
+			//	|		function(item, idx, arr){
+			//	|			console.log(item, "at index:", idx);
+			//	|		}
+			//	|	);
+			//	example:
+			//	|	// use a scoped object member as the callback
+			//	|	
+			//	|	var obj = {
+			//	|		prefix: "logged via obj.callback:", 
+			//	|		callback: function(item){
+			//	|			console.log(this.prefix, item);
+			//	|		}
+			//	|	};
+			//	|	
+			//	|	// specifying the scope function executes the callback in that scope
+			//	|	dojo.forEach(
+			//	|		[ "thinger", "blah", "howdy", 10 ],
+			//	|		obj.callback,
+			//	|		obj
+			//	|	);
+			//	|	
+			//	|	// alternately, we can accomplish the same thing with dojo.hitch()
+			//	|	dojo.forEach(
+			//	|		[ "thinger", "blah", "howdy", 10 ],
+			//	|		dojo.hitch(obj, "callback")
+			//	|	);
+
+			// match the behavior of the built-in forEach WRT empty arrs
+			if(!arr || !arr.length){ return; }
+
+			// FIXME: there are several ways of handilng thisObject. Is
+			// dojo.global always the default context?
+			var _p = _getParts(arr, thisObject, callback); arr = _p[0];
+			for(var i=0,l=arr.length; i<l; ++i){ 
+				_p[2].call(_p[1], arr[i], i, arr);
+			}
+		},
+
+		every: function(/*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
+			// summary:
+			//		Determines whether or not every item in arr satisfies the
+			//		condition implemented by callback.
+			// arr:
+			//		the array to iterate on. If a string, operates on individual characters.
+			// callback:
+			//		a function is invoked with three arguments: item, index,
+			//		and array and returns true if the condition is met.
+			// thisObject:
+			//		may be used to scope the call to callback
+			// description:
+			//		This function corresponds to the JavaScript 1.6 Array.every() method, with one difference: when 
+			//		run over sparse arrays, this implemenation passes the "holes" in the sparse array to
+			//		the callback function with a value of undefined. JavaScript 1.6's every skips the holes in the sparse array.
+			//		For more details, see:
+			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/every
+			// example:
+			//	|	// returns false
+			//	|	dojo.every([1, 2, 3, 4], function(item){ return item>1; });
+			// example:
+			//	|	// returns true 
+			//	|	dojo.every([1, 2, 3, 4], function(item){ return item>0; });
+			return everyOrSome(true, arr, callback, thisObject); // Boolean
+		},
+
+		some: function(/*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
+			// summary:
+			//		Determines whether or not any item in arr satisfies the
+			//		condition implemented by callback.
+			// arr:
+			//		the array to iterate over. If a string, operates on individual characters.
+			// callback:
+			//		a function is invoked with three arguments: item, index,
+			//		and array and returns true if the condition is met.
+			// thisObject:
+			//		may be used to scope the call to callback
+			// description:
+			//		This function corresponds to the JavaScript 1.6 Array.some() method, with one difference: when 
+			//		run over sparse arrays, this implemenation passes the "holes" in the sparse array to
+			//		the callback function with a value of undefined. JavaScript 1.6's some skips the holes in the sparse array.
+			//		For more details, see:
+			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/some
+			// example:
+			//	|	// is true
+			//	|	dojo.some([1, 2, 3, 4], function(item){ return item>1; });
+			// example:
+			//	|	// is false
+			//	|	dojo.some([1, 2, 3, 4], function(item){ return item<1; });
+			return everyOrSome(false, arr, callback, thisObject); // Boolean
+		},
+
+		map: function(/*Array|String*/arr, /*Function|String*/callback, /*Function?*/thisObject){
+			// summary:
+			//		applies callback to each element of arr and returns
+			//		an Array with the results
+			// arr:
+			//		the array to iterate on. If a string, operates on
+			//		individual characters.
+			// callback:
+			//		a function is invoked with three arguments, (item, index,
+			//		array),  and returns a value
+			// thisObject:
+			//		may be used to scope the call to callback
+			// description:
+			//		This function corresponds to the JavaScript 1.6 Array.map() method, with one difference: when 
+			//		run over sparse arrays, this implemenation passes the "holes" in the sparse array to
+			//		the callback function with a value of undefined. JavaScript 1.6's map skips the holes in the sparse array.
+			//		For more details, see:
+			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
+			// example:
+			//	|	// returns [2, 3, 4, 5]
+			//	|	dojo.map([1, 2, 3, 4], function(item){ return item+1 });
+
+			var _p = _getParts(arr, thisObject, callback); arr = _p[0];
+			var outArr = (arguments[3] ? (new arguments[3]()) : []);
+			for(var i=0,l=arr.length; i<l; ++i){
+				outArr.push(_p[2].call(_p[1], arr[i], i, arr));
+			}
+			return outArr; // Array
+		},
+
+		filter: function(/*Array*/arr, /*Function|String*/callback, /*Object?*/thisObject){
+			// summary:
+			//		Returns a new Array with those items from arr that match the
+			//		condition implemented by callback.
+			// arr:
+			//		the array to iterate over.
+			// callback:
+			//		a function that is invoked with three arguments (item,
+			//		index, array). The return of this function is expected to
+			//		be a boolean which determines whether the passed-in item
+			//		will be included in the returned array.
+			// thisObject:
+			//		may be used to scope the call to callback
+			// description:
+			//		This function corresponds to the JavaScript 1.6 Array.filter() method, with one difference: when 
+			//		run over sparse arrays, this implemenation passes the "holes" in the sparse array to
+			//		the callback function with a value of undefined. JavaScript 1.6's filter skips the holes in the sparse array. 
+			//		For more details, see:
+			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
+			// example:
+			//	|	// returns [2, 3, 4]
+			//	|	dojo.filter([1, 2, 3, 4], function(item){ return item>1; });
+
+			var _p = _getParts(arr, thisObject, callback); arr = _p[0];
+			var outArr = [];
+			for(var i=0,l=arr.length; i<l; ++i){
+				if(_p[2].call(_p[1], arr[i], i, arr)){
+					outArr.push(arr[i]);
+				}
+			}
+			return outArr; // Array
+		}
+	});
 })();
-}
+//>>excludeEnd("webkitMobile");
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+/*
+//>>excludeEnd("webkitMobile");
+//>>includeStart("webkitMobile", kwArgs.webkitMobile);
+["indexOf", "lastIndexOf", "forEach", "map", "some", "every", "filter"].forEach(
+	function(name, idx){
+		dojo[name] = function(arr, callback, thisObj){
+			if((idx > 1) && (typeof callback == "string")){
+				callback = new Function("item", "index", "array", callback);
+			}
+			return Array.prototype[name].call(arr, callback, thisObj);
+		}
+	}
+);
+//>>includeEnd("webkitMobile");
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+*/
+//>>excludeEnd("webkitMobile");
diff --git a/dojo/_base/browser.js b/dojo/_base/browser.js
index e6222bf..68500ab 100644
--- a/dojo/_base/browser.js
+++ b/dojo/_base/browser.js
@@ -1,13 +1,5 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.browser"]){
-dojo._hasResource["dojo._base.browser"]=true;
 dojo.provide("dojo._base.browser");
+
 dojo.require("dojo._base.window");
 dojo.require("dojo._base.connect");
 dojo.require("dojo._base.event");
@@ -16,7 +8,11 @@ dojo.require("dojo._base.NodeList");
 dojo.require("dojo._base.query");
 dojo.require("dojo._base.xhr");
 dojo.require("dojo._base.fx");
-dojo.forEach(dojo.config.require,function(i){
-dojo["require"](i);
+
+//Need this to be the last code segment in base, so do not place any
+//dojo.requireIf calls in this file. Otherwise, due to how the build system
+//puts all requireIf dependencies after the current file, the require calls
+//could be called before all of base is defined.
+dojo.forEach(dojo.config.require, function(i){
+	dojo["require"](i);
 });
-}
diff --git a/dojo/_base/connect.js b/dojo/_base/connect.js
index 55ac57d..3e29885 100644
--- a/dojo/_base/connect.js
+++ b/dojo/_base/connect.js
@@ -1,85 +1,316 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.connect"]){
-dojo._hasResource["dojo._base.connect"]=true;
 dojo.provide("dojo._base.connect");
 dojo.require("dojo._base.lang");
-dojo._listener={getDispatcher:function(){
-return function(){
-var ap=Array.prototype,c=arguments.callee,ls=c._listeners,t=c.target;
-var r=t&&t.apply(this,arguments);
-var _1;
-_1=[].concat(ls);
-for(var i in _1){
-if(!(i in ap)){
-_1[i].apply(this,arguments);
-}
-}
-return r;
+
+// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
+
+// low-level delegation machinery
+dojo._listener = {
+	// create a dispatcher function
+	getDispatcher: function(){
+		// following comments pulled out-of-line to prevent cloning them 
+		// in the returned function.
+		// - indices (i) that are really in the array of listeners (ls) will 
+		//   not be in Array.prototype. This is the 'sparse array' trick
+		//   that keeps us safe from libs that take liberties with built-in 
+		//   objects
+		// - listener is invoked with current scope (this)
+		return function(){
+			var ap=Array.prototype, c=arguments.callee, ls=c._listeners, t=c.target;
+			// return value comes from original target function
+			var r = t && t.apply(this, arguments);
+			// make local copy of listener array so it is immutable during processing
+			var i, lls;
+			//>>includeStart("connectRhino", kwArgs.profileProperties.hostenvType == "rhino");
+			if(!dojo.isRhino){
+			//>>includeEnd("connectRhino");
+				//>>includeStart("connectBrowser", kwArgs.profileProperties.hostenvType != "rhino");
+				lls = [].concat(ls);
+				//>>includeEnd("connectBrowser");
+			//>>includeStart("connectRhino", kwArgs.profileProperties.hostenvType == "rhino");
+			}else{
+				// FIXME: in Rhino, using concat on a sparse Array results in a dense Array.
+				// IOW, if an array A has elements [0, 2, 4], then under Rhino, "concat [].A"
+				// results in [0, 1, 2, 3, 4], where element 1 and 3 have value 'undefined'
+				// "A.slice(0)" has the same behavior.
+				lls = [];
+				for(i in ls){
+					lls[i] = ls[i];
+				}
+			}
+			//>>includeEnd("connectRhino");
+
+			// invoke listeners after target function
+			for(i in lls){
+				if(!(i in ap)){
+					lls[i].apply(this, arguments);
+				}
+			}
+			// return value comes from original target function
+			return r;
+		};
+	},
+	// add a listener to an object
+	add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
+		// Whenever 'method' is invoked, 'listener' will have the same scope.
+		// Trying to supporting a context object for the listener led to 
+		// complexity. 
+		// Non trivial to provide 'once' functionality here
+		// because listener could be the result of a dojo.hitch call,
+		// in which case two references to the same hitch target would not
+		// be equivalent. 
+		source = source || dojo.global;
+		// The source method is either null, a dispatcher, or some other function
+		var f = source[method];
+		// Ensure a dispatcher
+		if(!f || !f._listeners){
+			var d = dojo._listener.getDispatcher();
+			// original target function is special
+			d.target = f;
+			// dispatcher holds a list of listeners
+			d._listeners = []; 
+			// redirect source to dispatcher
+			f = source[method] = d;
+		}
+		// The contract is that a handle is returned that can 
+		// identify this listener for disconnect. 
+		//
+		// The type of the handle is private. Here is it implemented as Integer. 
+		// DOM event code has this same contract but handle is Function 
+		// in non-IE browsers.
+		//
+		// We could have separate lists of before and after listeners.
+		return f._listeners.push(listener); /*Handle*/
+	},
+	// remove a listener from an object
+	remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
+		var f = (source || dojo.global)[method];
+		// remember that handle is the index+1 (0 is not a valid handle)
+		if(f && f._listeners && handle--){
+			delete f._listeners[handle];
+		}
+	}
 };
-},add:function(_2,_3,_4){
-_2=_2||dojo.global;
-var f=_2[_3];
-if(!f||!f._listeners){
-var d=dojo._listener.getDispatcher();
-d.target=f;
-d._listeners=[];
-f=_2[_3]=d;
+
+// Multiple delegation for arbitrary methods.
+
+// This unit knows nothing about DOM, but we include DOM aware documentation
+// and dontFix argument here to help the autodocs. Actual DOM aware code is in
+// event.js.
+
+dojo.connect = function(/*Object|null*/ obj, 
+						/*String*/ event, 
+						/*Object|null*/ context, 
+						/*String|Function*/ method,
+						/*Boolean?*/ dontFix){
+	// summary:
+	//		`dojo.connect` is the core event handling and delegation method in
+	//		Dojo. It allows one function to "listen in" on the execution of
+	//		any other, triggering the second whenever the first is called. Many
+	//		listeners may be attached to a function, and source functions may
+	//		be either regular function calls or DOM events.
+	//
+	// description:
+	//		Connects listeners to actions, so that after event fires, a
+	//		listener is called with the same arguments passed to the original
+	//		function.
+	//
+	//		Since `dojo.connect` allows the source of events to be either a
+	//		"regular" JavaScript function or a DOM event, it provides a uniform
+	//		interface for listening to all the types of events that an
+	//		application is likely to deal with though a single, unified
+	//		interface. DOM programmers may want to think of it as
+	//		"addEventListener for everything and anything".
+	//
+	//		When setting up a connection, the `event` parameter must be a
+	//		string that is the name of the method/event to be listened for. If
+	//		`obj` is null, `dojo.global` is assumed, meaning that connections
+	//		to global methods are supported but also that you may inadvertently
+	//		connect to a global by passing an incorrect object name or invalid
+	//		reference.
+	//
+	//		`dojo.connect` generally is forgiving. If you pass the name of a
+	//		function or method that does not yet exist on `obj`, connect will
+	//		not fail, but will instead set up a stub method. Similarly, null
+	//		arguments may simply be omitted such that fewer than 4 arguments
+	//		may be required to set up a connection See the examples for details.
+	//
+	//		The return value is a handle that is needed to 
+	//		remove this connection with `dojo.disconnect`.
+	//
+	// obj: 
+	//		The source object for the event function. 
+	//		Defaults to `dojo.global` if null.
+	//		If obj is a DOM node, the connection is delegated 
+	//		to the DOM event manager (unless dontFix is true).
+	//
+	// event:
+	//		String name of the event function in obj. 
+	//		I.e. identifies a property `obj[event]`.
+	//
+	// context: 
+	//		The object that method will receive as "this".
+	//
+	//		If context is null and method is a function, then method
+	//		inherits the context of event.
+	//	
+	//		If method is a string then context must be the source 
+	//		object object for method (context[method]). If context is null,
+	//		dojo.global is used.
+	//
+	// method:
+	//		A function reference, or name of a function in context. 
+	//		The function identified by method fires after event does. 
+	//		method receives the same arguments as the event.
+	//		See context argument comments for information on method's scope.
+	//
+	// dontFix:
+	//		If obj is a DOM node, set dontFix to true to prevent delegation 
+	//		of this connection to the DOM event manager.
+	//
+	// example:
+	//		When obj.onchange(), do ui.update():
+	//	|	dojo.connect(obj, "onchange", ui, "update");
+	//	|	dojo.connect(obj, "onchange", ui, ui.update); // same
+	//
+	// example:
+	//		Using return value for disconnect:
+	//	|	var link = dojo.connect(obj, "onchange", ui, "update");
+	//	|	...
+	//	|	dojo.disconnect(link);
+	//
+	// example:
+	//		When onglobalevent executes, watcher.handler is invoked:
+	//	|	dojo.connect(null, "onglobalevent", watcher, "handler");
+	//
+	// example:
+	//		When ob.onCustomEvent executes, customEventHandler is invoked:
+	//	|	dojo.connect(ob, "onCustomEvent", null, "customEventHandler");
+	//	|	dojo.connect(ob, "onCustomEvent", "customEventHandler"); // same
+	//
+	// example:
+	//		When ob.onCustomEvent executes, customEventHandler is invoked
+	//		with the same scope (this):
+	//	|	dojo.connect(ob, "onCustomEvent", null, customEventHandler);
+	//	|	dojo.connect(ob, "onCustomEvent", customEventHandler); // same
+	//
+	// example:
+	//		When globalEvent executes, globalHandler is invoked
+	//		with the same scope (this):
+	//	|	dojo.connect(null, "globalEvent", null, globalHandler);
+	//	|	dojo.connect("globalEvent", globalHandler); // same
+
+	// normalize arguments
+	var a=arguments, args=[], i=0;
+	// if a[0] is a String, obj was omitted
+	args.push(dojo.isString(a[0]) ? null : a[i++], a[i++]);
+	// if the arg-after-next is a String or Function, context was NOT omitted
+	var a1 = a[i+1];
+	args.push(dojo.isString(a1)||dojo.isFunction(a1) ? a[i++] : null, a[i++]);
+	// absorb any additional arguments
+	for(var l=a.length; i<l; i++){	args.push(a[i]); }
+	// do the actual work
+	return dojo._connect.apply(this, args); /*Handle*/
 }
-return f._listeners.push(_4);
-},remove:function(_5,_6,_7){
-var f=(_5||dojo.global)[_6];
-if(f&&f._listeners&&_7--){
-delete f._listeners[_7];
+
+// used by non-browser hostenvs. always overriden by event.js
+dojo._connect = function(obj, event, context, method){
+	var l=dojo._listener, h=l.add(obj, event, dojo.hitch(context, method)); 
+	return [obj, event, h, l]; // Handle
 }
-}};
-dojo.connect=function(_8,_9,_a,_b,_c){
-var a=arguments,_d=[],i=0;
-_d.push(dojo.isString(a[0])?null:a[i++],a[i++]);
-var a1=a[i+1];
-_d.push(dojo.isString(a1)||dojo.isFunction(a1)?a[i++]:null,a[i++]);
-for(var l=a.length;i<l;i++){
-_d.push(a[i]);
+
+dojo.disconnect = function(/*Handle*/ handle){
+	// summary:
+	//		Remove a link created by dojo.connect.
+	// description:
+	//		Removes the connection between event and the method referenced by handle.
+	// handle:
+	//		the return value of the dojo.connect call that created the connection.
+	if(handle && handle[0] !== undefined){
+		dojo._disconnect.apply(this, handle);
+		// let's not keep this reference
+		delete handle[0];
+	}
 }
-return dojo._connect.apply(this,_d);
-};
-dojo._connect=function(_e,_f,_10,_11){
-var l=dojo._listener,h=l.add(_e,_f,dojo.hitch(_10,_11));
-return [_e,_f,h,l];
-};
-dojo.disconnect=function(_12){
-if(_12&&_12[0]!==undefined){
-dojo._disconnect.apply(this,_12);
-delete _12[0];
+
+dojo._disconnect = function(obj, event, handle, listener){
+	listener.remove(obj, event, handle);
 }
-};
-dojo._disconnect=function(obj,_13,_14,_15){
-_15.remove(obj,_13,_14);
-};
-dojo._topics={};
-dojo.subscribe=function(_16,_17,_18){
-return [_16,dojo._listener.add(dojo._topics,_16,dojo.hitch(_17,_18))];
-};
-dojo.unsubscribe=function(_19){
-if(_19){
-dojo._listener.remove(dojo._topics,_19[0],_19[1]);
+
+// topic publish/subscribe
+
+dojo._topics = {};
+
+dojo.subscribe = function(/*String*/ topic, /*Object|null*/ context, /*String|Function*/ method){
+	//	summary:
+	//		Attach a listener to a named topic. The listener function is invoked whenever the
+	//		named topic is published (see: dojo.publish).
+	//		Returns a handle which is needed to unsubscribe this listener.
+	//	context:
+	//		Scope in which method will be invoked, or null for default scope.
+	//	method:
+	//		The name of a function in context, or a function reference. This is the function that
+	//		is invoked when topic is published.
+	//	example:
+	//	|	dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); });
+	//	|	dojo.publish("alerts", [ "read this", "hello world" ]);																	
+
+	// support for 2 argument invocation (omitting context) depends on hitch
+	return [topic, dojo._listener.add(dojo._topics, topic, dojo.hitch(context, method))]; /*Handle*/
 }
-};
-dojo.publish=function(_1a,_1b){
-var f=dojo._topics[_1a];
-if(f){
-f.apply(this,_1b||[]);
+
+dojo.unsubscribe = function(/*Handle*/ handle){
+	//	summary:
+	//	 	Remove a topic listener. 
+	//	handle:
+	//	 	The handle returned from a call to subscribe.
+	//	example:
+	//	|	var alerter = dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
+	//	|	...
+	//	|	dojo.unsubscribe(alerter);
+	if(handle){
+		dojo._listener.remove(dojo._topics, handle[0], handle[1]);
+	}
 }
-};
-dojo.connectPublisher=function(_1c,obj,_1d){
-var pf=function(){
-dojo.publish(_1c,arguments);
-};
-return (_1d)?dojo.connect(obj,_1d,pf):dojo.connect(obj,pf);
-};
+
+dojo.publish = function(/*String*/ topic, /*Array*/ args){
+	//	summary:
+	//	 	Invoke all listener method subscribed to topic.
+	//	topic:
+	//	 	The name of the topic to publish.
+	//	args:
+	//	 	An array of arguments. The arguments will be applied 
+	//	 	to each topic subscriber (as first class parameters, via apply).
+	//	example:
+	//	|	dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
+	//	|	dojo.publish("alerts", [ "read this", "hello world" ]);	
+
+	// Note that args is an array, which is more efficient vs variable length
+	// argument list.  Ideally, var args would be implemented via Array
+	// throughout the APIs.
+	var f = dojo._topics[topic];
+	if(f){
+		f.apply(this, args||[]);
+	}
 }
+
+dojo.connectPublisher = function(	/*String*/ topic, 
+									/*Object|null*/ obj, 
+									/*String*/ event){
+	//	summary:
+	//	 	Ensure that every time obj.event() is called, a message is published
+	//	 	on the topic. Returns a handle which can be passed to
+	//	 	dojo.disconnect() to disable subsequent automatic publication on
+	//	 	the topic.
+	//	topic:
+	//	 	The name of the topic to publish.
+	//	obj: 
+	//	 	The source object for the event function. Defaults to dojo.global
+	//	 	if null.
+	//	event:
+	//	 	The name of the event function in obj. 
+	//	 	I.e. identifies a property obj[event].
+	//	example:
+	//	|	dojo.connectPublisher("/ajax/start", dojo, "xhrGet");
+	var pf = function(){ dojo.publish(topic, arguments); }
+	return event ? dojo.connect(obj, event, pf) : dojo.connect(obj, pf); //Handle
+};
diff --git a/dojo/_base/declare.js b/dojo/_base/declare.js
index f8bc84c..3e7c1f6 100644
--- a/dojo/_base/declare.js
+++ b/dojo/_base/declare.js
@@ -1,379 +1,1037 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.declare"]){
-dojo._hasResource["dojo._base.declare"]=true;
 dojo.provide("dojo._base.declare");
+
 dojo.require("dojo._base.lang");
 dojo.require("dojo._base.array");
+
 (function(){
-var d=dojo,_1=d._mixin,op=Object.prototype,_2=op.toString,_3=new Function,_4=0,_5="constructor";
-function _6(_7){
-throw new Error("declare: "+_7);
-};
-function _8(_9){
-var _a=[],_b=[{cls:0,refs:[]}],_c={},_d=1,l=_9.length,i=0,j,_e,_f,top,_10,rec,_11,_12;
-for(;i<l;++i){
-_f=_9[i];
-if(!_f){
-_6("mixin #"+i+" is null");
-}
-_e=_f._meta?_f._meta.bases:[_f];
-top=0;
-for(j=_e.length-1;j>=0;--j){
-_10=_e[j].prototype;
-if(!_10.hasOwnProperty("declaredClass")){
-_10.declaredClass="uniqName_"+(_4++);
-}
-_11=_10.declaredClass;
-if(!_c.hasOwnProperty(_11)){
-_c[_11]={count:0,refs:[],cls:_e[j]};
-++_d;
-}
-rec=_c[_11];
-if(top&&top!==rec){
-rec.refs.push(top);
-++top.count;
-}
-top=rec;
-}
-++top.count;
-_b[0].refs.push(top);
-}
-while(_b.length){
-top=_b.pop();
-_a.push(top.cls);
---_d;
-while(_12=top.refs,_12.length==1){
-top=_12[0];
-if(!top||--top.count){
-top=0;
-break;
-}
-_a.push(top.cls);
---_d;
-}
-if(top){
-for(i=0,l=_12.length;i<l;++i){
-top=_12[i];
-if(!--top.count){
-_b.push(top);
-}
-}
-}
-}
-if(_d){
-_6("can't build consistent linearization");
-}
-_f=_9[0];
-_a[0]=_f?_f._meta&&_f===_a[_a.length-_f._meta.bases.length]?_f._meta.bases.length:1:0;
-return _a;
-};
-function _13(_14,a,f){
-var _15,_16,_17,_18,_19,_1a,_1b,opf,pos,_1c=this._inherited=this._inherited||{};
-if(typeof _14=="string"){
-_15=_14;
-_14=a;
-a=f;
-}
-f=0;
-_18=_14.callee;
-_15=_15||_18.nom;
-if(!_15){
-_6("can't deduce a name to call inherited()");
-}
-_19=this.constructor._meta;
-_17=_19.bases;
-pos=_1c.p;
-if(_15!=_5){
-if(_1c.c!==_18){
-pos=0;
-_1a=_17[0];
-_19=_1a._meta;
-if(_19.hidden[_15]!==_18){
-_16=_19.chains;
-if(_16&&typeof _16[_15]=="string"){
-_6("calling chained method with inherited: "+_15);
-}
-do{
-_19=_1a._meta;
-_1b=_1a.prototype;
-if(_19&&(_1b[_15]===_18&&_1b.hasOwnProperty(_15)||_19.hidden[_15]===_18)){
-break;
-}
-}while(_1a=_17[++pos]);
-pos=_1a?pos:-1;
-}
-}
-_1a=_17[++pos];
-if(_1a){
-_1b=_1a.prototype;
-if(_1a._meta&&_1b.hasOwnProperty(_15)){
-f=_1b[_15];
-}else{
-opf=op[_15];
-do{
-_1b=_1a.prototype;
-f=_1b[_15];
-if(f&&(_1a._meta?_1b.hasOwnProperty(_15):f!==opf)){
-break;
-}
-}while(_1a=_17[++pos]);
-}
-}
-f=_1a&&f||op[_15];
-}else{
-if(_1c.c!==_18){
-pos=0;
-_19=_17[0]._meta;
-if(_19&&_19.ctor!==_18){
-_16=_19.chains;
-if(!_16||_16.constructor!=="manual"){
-_6("calling chained constructor with inherited");
-}
-while(_1a=_17[++pos]){
-_19=_1a._meta;
-if(_19&&_19.ctor===_18){
-break;
-}
-}
-pos=_1a?pos:-1;
-}
-}
-while(_1a=_17[++pos]){
-_19=_1a._meta;
-f=_19?_19.ctor:_1a;
-if(f){
-break;
-}
-}
-f=_1a&&f;
-}
-_1c.c=f;
-_1c.p=pos;
-if(f){
-return a===true?f:f.apply(this,a||_14);
-}
-};
-function _1d(_1e,_1f){
-if(typeof _1e=="string"){
-return this.inherited(_1e,_1f,true);
-}
-return this.inherited(_1e,true);
-};
-function _20(cls){
-var _21=this.constructor._meta.bases;
-for(var i=0,l=_21.length;i<l;++i){
-if(_21[i]===cls){
-return true;
-}
-}
-return this instanceof cls;
-};
-function _22(_23,_24){
-var _25,t,i=0,l=d._extraNames.length;
-for(_25 in _24){
-t=_24[_25];
-if((t!==op[_25]||!(_25 in op))&&_25!=_5){
-if(_2.call(t)=="[object Function]"){
-t.nom=_25;
-}
-_23[_25]=t;
-}
-}
-for(;i<l;++i){
-_25=d._extraNames[i];
-t=_24[_25];
-if((t!==op[_25]||!(_25 in op))&&_25!=_5){
-if(_2.call(t)=="[object Function]"){
-t.nom=_25;
-}
-_23[_25]=t;
-}
-}
-return _23;
-};
-function _26(_27){
-_22(this.prototype,_27);
-return this;
-};
-function _28(_29,_2a){
-return function(){
-var a=arguments,_2b=a,a0=a[0],f,i,m,l=_29.length,_2c;
-if(_2a&&(a0&&a0.preamble||this.preamble)){
-_2c=new Array(_29.length);
-_2c[0]=a;
-for(i=0;;){
-a0=a[0];
-if(a0){
-f=a0.preamble;
-if(f){
-a=f.apply(this,a)||a;
-}
-}
-f=_29[i].prototype;
-f=f.hasOwnProperty("preamble")&&f.preamble;
-if(f){
-a=f.apply(this,a)||a;
-}
-if(++i==l){
-break;
-}
-_2c[i]=a;
-}
-}
-for(i=l-1;i>=0;--i){
-f=_29[i];
-m=f._meta;
-f=m?m.ctor:f;
-if(f){
-f.apply(this,_2c?_2c[i]:a);
-}
-}
-f=this.postscript;
-if(f){
-f.apply(this,_2b);
-}
-};
-};
-function _2d(_2e,_2f){
-return function(){
-var a=arguments,t=a,a0=a[0],f;
-if(_2f){
-if(a0){
-f=a0.preamble;
-if(f){
-t=f.apply(this,t)||t;
-}
-}
-f=this.preamble;
-if(f){
-f.apply(this,t);
-}
-}
-if(_2e){
-_2e.apply(this,a);
-}
-f=this.postscript;
-if(f){
-f.apply(this,a);
-}
-};
-};
-function _30(_31){
-return function(){
-var a=arguments,i=0,f;
-for(;f=_31[i];++i){
-m=f._meta;
-f=m?m.ctor:f;
-if(f){
-f.apply(this,a);
-break;
-}
-}
-f=this.postscript;
-if(f){
-f.apply(this,a);
-}
-};
-};
-function _32(_33,_34,_35){
-return function(){
-var b,m,f,i=0,_36=1;
-if(_35){
-i=_34.length-1;
-_36=-1;
-}
-for(;b=_34[i];i+=_36){
-m=b._meta;
-f=(m?m.hidden:b.prototype)[_33];
-if(f){
-f.apply(this,arguments);
-}
-}
-};
-};
-d.declare=function(_37,_38,_39){
-var _3a,i,t,_3b,_3c,_3d,_3e,_3f=1,_40=_38;
-if(typeof _37!="string"){
-_39=_38;
-_38=_37;
-_37="";
-}
-_39=_39||{};
-if(_2.call(_38)=="[object Array]"){
-_3d=_8(_38);
-t=_3d[0];
-_3f=_3d.length-t;
-_38=_3d[_3f];
-}else{
-_3d=[0];
-if(_38){
-t=_38._meta;
-_3d=_3d.concat(t?t.bases:_38);
-}
-}
-if(_38){
-for(i=_3f-1;;--i){
-_3.prototype=_38.prototype;
-_3a=new _3;
-if(!i){
-break;
-}
-t=_3d[i];
-_1(_3a,t._meta?t._meta.hidden:t.prototype);
-_3b=new Function;
-_3b.superclass=_38;
-_3b.prototype=_3a;
-_38=_3a.constructor=_3b;
-}
-}else{
-_3a={};
-}
-_22(_3a,_39);
-t=_39.constructor;
-if(t!==op.constructor){
-t.nom=_5;
-_3a.constructor=t;
-}
-_3.prototype=0;
-for(i=_3f-1;i;--i){
-t=_3d[i]._meta;
-if(t&&t.chains){
-_3e=_1(_3e||{},t.chains);
-}
-}
-if(_3a["-chains-"]){
-_3e=_1(_3e||{},_3a["-chains-"]);
-}
-t=!_3e||!_3e.hasOwnProperty(_5);
-_3d[0]=_3b=(_3e&&_3e.constructor==="manual")?_30(_3d):(_3d.length==1?_2d(_39.constructor,t):_28(_3d,t));
-_3b._meta={bases:_3d,hidden:_39,chains:_3e,parents:_40,ctor:_39.constructor};
-_3b.superclass=_38&&_38.prototype;
-_3b.extend=_26;
-_3b.prototype=_3a;
-_3a.constructor=_3b;
-_3a.getInherited=_1d;
-_3a.inherited=_13;
-_3a.isInstanceOf=_20;
-if(_37){
-_3a.declaredClass=_37;
-d.setObject(_37,_3b);
-}
-if(_3e){
-for(_3c in _3e){
-if(_3a[_3c]&&typeof _3e[_3c]=="string"&&_3c!=_5){
-t=_3a[_3c]=_32(_3c,_3d,_3e[_3c]==="after");
-t.nom=_3c;
-}
-}
-}
-return _3b;
-};
-d.safeMixin=_22;
+	var d = dojo, mix = d._mixin, op = Object.prototype, opts = op.toString,
+		xtor = new Function, counter = 0, cname = "constructor";
+
+	function err(msg){ throw new Error("declare: " + msg); }
+
+	// C3 Method Resolution Order (see http://www.python.org/download/releases/2.3/mro/)
+	function c3mro(bases){
+		var result = [], roots = [{cls: 0, refs: []}], nameMap = {}, clsCount = 1,
+			l = bases.length, i = 0, j, lin, base, top, proto, rec, name, refs;
+
+		// build a list of bases naming them if needed
+		for(; i < l; ++i){
+			base = bases[i];
+			if(!base){
+				err("mixin #" + i + " is unknown. Did you use dojo.require to pull it in?");
+			}else if(opts.call(base) != "[object Function]"){
+				err("mixin #" + i + " is not a callable constructor.");
+			}
+			lin = base._meta ? base._meta.bases : [base];
+			top = 0;
+			// add bases to the name map
+			for(j = lin.length - 1; j >= 0; --j){
+				proto = lin[j].prototype;
+				if(!proto.hasOwnProperty("declaredClass")){
+					proto.declaredClass = "uniqName_" + (counter++);
+				}
+				name = proto.declaredClass;
+				if(!nameMap.hasOwnProperty(name)){
+					nameMap[name] = {count: 0, refs: [], cls: lin[j]};
+					++clsCount;
+				}
+				rec = nameMap[name];
+				if(top && top !== rec){
+					rec.refs.push(top);
+					++top.count;
+				}
+				top = rec;
+			}
+			++top.count;
+			roots[0].refs.push(top);
+		}
+
+		// remove classes without external references recursively
+		while(roots.length){
+			top = roots.pop();
+			result.push(top.cls);
+			--clsCount;
+			// optimization: follow a single-linked chain
+			while(refs = top.refs, refs.length == 1){
+				top = refs[0];
+				if(!top || --top.count){
+					// branch or end of chain => do not end to roots
+					top = 0;
+					break;
+				}
+				result.push(top.cls);
+				--clsCount;
+			}
+			if(top){
+				// branch
+				for(i = 0, l = refs.length; i < l; ++i){
+					top = refs[i];
+					if(!--top.count){
+						roots.push(top);
+					}
+				}
+			}
+		}
+		if(clsCount){
+			err("can't build consistent linearization");
+		}
+
+		// calculate the superclass offset
+		base = bases[0];
+		result[0] = base ?
+			base._meta && base === result[result.length - base._meta.bases.length] ?
+				base._meta.bases.length : 1 : 0;
+
+		return result;
+	}
+
+	function inherited(args, a, f){
+		var name, chains, bases, caller, meta, base, proto, opf, pos,
+			cache = this._inherited = this._inherited || {};
+
+		// crack arguments
+		if(typeof args == "string"){
+			name = args;
+			args = a;
+			a = f;
+		}
+		f = 0;
+
+		caller = args.callee;
+		name = name || caller.nom;
+		if(!name){
+			err("can't deduce a name to call inherited()");
+		}
+
+		meta = this.constructor._meta;
+		bases = meta.bases;
+
+		pos = cache.p;
+		if(name != cname){
+			// method
+			if(cache.c !== caller){
+				// cache bust
+				pos = 0;
+				base = bases[0];
+				meta = base._meta;
+				if(meta.hidden[name] !== caller){
+					// error detection
+					chains = meta.chains;
+					if(chains && typeof chains[name] == "string"){
+						err("calling chained method with inherited: " + name);
+					}
+					// find caller
+					do{
+						meta = base._meta;
+						proto = base.prototype;
+						if(meta && (proto[name] === caller && proto.hasOwnProperty(name) || meta.hidden[name] === caller)){
+							break;
+						}
+					}while(base = bases[++pos]); // intentional assignment
+					pos = base ? pos : -1;
+				}
+			}
+			// find next
+			base = bases[++pos];
+			if(base){
+				proto = base.prototype;
+				if(base._meta && proto.hasOwnProperty(name)){
+					f = proto[name];
+				}else{
+					opf = op[name];
+					do{
+						proto = base.prototype;
+						f = proto[name];
+						if(f && (base._meta ? proto.hasOwnProperty(name) : f !== opf)){
+							break;
+						}
+					}while(base = bases[++pos]); // intentional assignment
+				}
+			}
+			f = base && f || op[name];
+		}else{
+			// constructor
+			if(cache.c !== caller){
+				// cache bust
+				pos = 0;
+				meta = bases[0]._meta;
+				if(meta && meta.ctor !== caller){
+					// error detection
+					chains = meta.chains;
+					if(!chains || chains.constructor !== "manual"){
+						err("calling chained constructor with inherited");
+					}
+					// find caller
+					while(base = bases[++pos]){ // intentional assignment
+						meta = base._meta;
+						if(meta && meta.ctor === caller){
+							break;
+						}
+					}
+					pos = base ? pos : -1;
+				}
+			}
+			// find next
+			while(base = bases[++pos]){	// intentional assignment
+				meta = base._meta;
+				f = meta ? meta.ctor : base;
+				if(f){
+					break;
+				}
+			}
+			f = base && f;
+		}
+
+		// cache the found super method
+		cache.c = f;
+		cache.p = pos;
+
+		// now we have the result
+		if(f){
+			return a === true ? f : f.apply(this, a || args);
+		}
+		// intentionally if a super method was not found
+	}
+
+	function getInherited(name, args){
+		if(typeof name == "string"){
+			return this.inherited(name, args, true);
+		}
+		return this.inherited(name, true);
+	}
+
+	// emulation of "instanceof"
+	function isInstanceOf(cls){
+		var bases = this.constructor._meta.bases;
+		for(var i = 0, l = bases.length; i < l; ++i){
+			if(bases[i] === cls){
+				return true;
+			}
+		}
+		return this instanceof cls;
+	}
+
+	function mixOwn(target, source){
+		var name, i = 0, l = d._extraNames.length;
+		// add props adding metadata for incoming functions skipping a constructor
+		for(name in source){
+			if(name != cname && source.hasOwnProperty(name)){
+				target[name] = source[name];
+			}
+		}
+		// process unenumerable methods on IE
+		for(; i < l; ++i){
+			name = d._extraNames[i];
+			if(name != cname && source.hasOwnProperty(name)){
+				target[name] = source[name];
+			}
+		}
+	}
+
+	// implementation of safe mixin function
+	function safeMixin(target, source){
+		var name, t, i = 0, l = d._extraNames.length;
+		// add props adding metadata for incoming functions skipping a constructor
+		for(name in source){
+			t = source[name];
+			if((t !== op[name] || !(name in op)) && name != cname){
+				if(opts.call(t) == "[object Function]"){
+					// non-trivial function method => attach its name
+					t.nom = name;
+				}
+				target[name] = t;
+			}
+		}
+		// process unenumerable methods on IE
+		for(; i < l; ++i){
+			name = d._extraNames[i];
+			t = source[name];
+			if((t !== op[name] || !(name in op)) && name != cname){
+				if(opts.call(t) == "[object Function]"){
+					// non-trivial function method => attach its name
+					t.nom = name;
+				}
+				target[name] = t;
+			}
+		}
+		return target;
+	}
+
+	function extend(source){
+		safeMixin(this.prototype, source);
+		return this;
+	}
+
+	// chained constructor compatible with the legacy dojo.declare()
+	function chainedConstructor(bases, ctorSpecial){
+		return function(){
+			var a = arguments, args = a, a0 = a[0], f, i, m,
+				l = bases.length, preArgs;
+
+			if(!(this instanceof a.callee)){
+				// not called via new, so force it
+				return applyNew(a);
+			}
+
+			//this._inherited = {};
+			// perform the shaman's rituals of the original dojo.declare()
+			// 1) call two types of the preamble
+			if(ctorSpecial && (a0 && a0.preamble || this.preamble)){
+				// full blown ritual
+				preArgs = new Array(bases.length);
+				// prepare parameters
+				preArgs[0] = a;
+				for(i = 0;;){
+					// process the preamble of the 1st argument
+					a0 = a[0];
+					if(a0){
+						f = a0.preamble;
+						if(f){
+							a = f.apply(this, a) || a;
+						}
+					}
+					// process the preamble of this class
+					f = bases[i].prototype;
+					f = f.hasOwnProperty("preamble") && f.preamble;
+					if(f){
+						a = f.apply(this, a) || a;
+					}
+					// one peculiarity of the preamble:
+					// it is called if it is not needed,
+					// e.g., there is no constructor to call
+					// let's watch for the last constructor
+					// (see ticket #9795)
+					if(++i == l){
+						break;
+					}
+					preArgs[i] = a;
+				}
+			}
+			// 2) call all non-trivial constructors using prepared arguments
+			for(i = l - 1; i >= 0; --i){
+				f = bases[i];
+				m = f._meta;
+				f = m ? m.ctor : f;
+				if(f){
+					f.apply(this, preArgs ? preArgs[i] : a);
+				}
+			}
+			// 3) continue the original ritual: call the postscript
+			f = this.postscript;
+			if(f){
+				f.apply(this, args);
+			}
+		};
+	}
+
+
+	// chained constructor compatible with the legacy dojo.declare()
+	function singleConstructor(ctor, ctorSpecial){
+		return function(){
+			var a = arguments, t = a, a0 = a[0], f;
+
+			if(!(this instanceof a.callee)){
+				// not called via new, so force it
+				return applyNew(a);
+			}
+
+			//this._inherited = {};
+			// perform the shaman's rituals of the original dojo.declare()
+			// 1) call two types of the preamble
+			if(ctorSpecial){
+				// full blown ritual
+				if(a0){
+					// process the preamble of the 1st argument
+					f = a0.preamble;
+					if(f){
+						t = f.apply(this, t) || t;
+					}
+				}
+				f = this.preamble;
+				if(f){
+					// process the preamble of this class
+					f.apply(this, t);
+					// one peculiarity of the preamble:
+					// it is called even if it is not needed,
+					// e.g., there is no constructor to call
+					// let's watch for the last constructor
+					// (see ticket #9795)
+				}
+			}
+			// 2) call a constructor
+			if(ctor){
+				ctor.apply(this, a);
+			}
+			// 3) continue the original ritual: call the postscript
+			f = this.postscript;
+			if(f){
+				f.apply(this, a);
+			}
+		};
+	}
+
+	// plain vanilla constructor (can use inherited() to call its base constructor)
+	function simpleConstructor(bases){
+		return function(){
+			var a = arguments, i = 0, f, m;
+
+			if(!(this instanceof a.callee)){
+				// not called via new, so force it
+				return applyNew(a);
+			}
+
+			//this._inherited = {};
+			// perform the shaman's rituals of the original dojo.declare()
+			// 1) do not call the preamble
+			// 2) call the top constructor (it can use this.inherited())
+			for(; f = bases[i]; ++i){ // intentional assignment
+				m = f._meta;
+				f = m ? m.ctor : f;
+				if(f){
+					f.apply(this, a);
+					break;
+				}
+			}
+			// 3) call the postscript
+			f = this.postscript;
+			if(f){
+				f.apply(this, a);
+			}
+		};
+	}
+
+	function chain(name, bases, reversed){
+		return function(){
+			var b, m, f, i = 0, step = 1;
+			if(reversed){
+				i = bases.length - 1;
+				step = -1;
+			}
+			for(; b = bases[i]; i += step){ // intentional assignment
+				m = b._meta;
+				f = (m ? m.hidden : b.prototype)[name];
+				if(f){
+					f.apply(this, arguments);
+				}
+			}
+		};
+	}
+
+	// forceNew(ctor)
+	// return a new object that inherits from ctor.prototype but
+	// without actually running ctor on the object.
+	function forceNew(ctor){
+		// create object with correct prototype using a do-nothing
+		// constructor
+		xtor.prototype = ctor.prototype;
+		var t = new xtor;
+		xtor.prototype = null;	// clean up
+		return t;
+	}
+
+	// applyNew(args)
+	// just like 'new ctor()' except that the constructor and its arguments come
+	// from args, which must be an array or an arguments object
+	function applyNew(args){
+		// create an object with ctor's prototype but without
+		// calling ctor on it.
+		var ctor = args.callee, t = forceNew(ctor);
+		// execute the real constructor on the new object
+		ctor.apply(t, args);
+		return t;
+	}
+
+	d.declare = function(className, superclass, props){
+		// crack parameters
+		if(typeof className != "string"){
+			props = superclass;
+			superclass = className;
+			className = "";
+		}
+		props = props || {};
+
+		var proto, i, t, ctor, name, bases, chains, mixins = 1, parents = superclass;
+
+		// build a prototype
+		if(opts.call(superclass) == "[object Array]"){
+			// C3 MRO
+			bases = c3mro(superclass);
+			t = bases[0];
+			mixins = bases.length - t;
+			superclass = bases[mixins];
+		}else{
+			bases = [0];
+			if(superclass){
+				if(opts.call(superclass) == "[object Function]"){
+					t = superclass._meta;
+					bases = bases.concat(t ? t.bases : superclass);
+				}else{
+					err("base class is not a callable constructor.");
+				}
+			}else if(superclass !== null){
+				err("unknown base class. Did you use dojo.require to pull it in?")
+			}
+		}
+		if(superclass){
+			for(i = mixins - 1;; --i){
+				proto = forceNew(superclass);
+				if(!i){
+					// stop if nothing to add (the last base)
+					break;
+				}
+				// mix in properties
+				t = bases[i];
+				(t._meta ? mixOwn : mix)(proto, t.prototype);
+				// chain in new constructor
+				ctor = new Function;
+				ctor.superclass = superclass;
+				ctor.prototype = proto;
+				superclass = proto.constructor = ctor;
+			}
+		}else{
+			proto = {};
+		}
+		// add all properties
+		safeMixin(proto, props);
+		// add constructor
+		t = props.constructor;
+		if(t !== op.constructor){
+			t.nom = cname;
+			proto.constructor = t;
+		}
+
+		// collect chains and flags
+		for(i = mixins - 1; i; --i){ // intentional assignment
+			t = bases[i]._meta;
+			if(t && t.chains){
+				chains = mix(chains || {}, t.chains);
+			}
+		}
+		if(proto["-chains-"]){
+			chains = mix(chains || {}, proto["-chains-"]);
+		}
+
+		// build ctor
+		t = !chains || !chains.hasOwnProperty(cname);
+		bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) :
+			(bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t));
+
+		// add meta information to the constructor
+		ctor._meta  = {bases: bases, hidden: props, chains: chains,
+			parents: parents, ctor: props.constructor};
+		ctor.superclass = superclass && superclass.prototype;
+		ctor.extend = extend;
+		ctor.prototype = proto;
+		proto.constructor = ctor;
+
+		// add "standard" methods to the prototype
+		proto.getInherited = getInherited;
+		proto.inherited = inherited;
+		proto.isInstanceOf = isInstanceOf;
+
+		// add name if specified
+		if(className){
+			proto.declaredClass = className;
+			d.setObject(className, ctor);
+		}
+
+		// build chains and add them to the prototype
+		if(chains){
+			for(name in chains){
+				if(proto[name] && typeof chains[name] == "string" && name != cname){
+					t = proto[name] = chain(name, bases, chains[name] === "after");
+					t.nom = name;
+				}
+			}
+		}
+		// chained methods do not return values
+		// no need to chain "invisible" functions
+
+		return ctor;	// Function
+	};
+
+	d.safeMixin = safeMixin;
+
+	/*=====
+	dojo.declare = function(className, superclass, props){
+		//	summary:
+		//		Create a feature-rich constructor from compact notation.
+		//	className: String?:
+		//		The optional name of the constructor (loosely, a "class")
+		//		stored in the "declaredClass" property in the created prototype.
+		//		It will be used as a global name for a created constructor.
+		//	superclass: Function|Function[]:
+		//		May be null, a Function, or an Array of Functions. This argument
+		//		specifies a list of bases (the left-most one is the most deepest
+		//		base).
+		//	props: Object:
+		//		An object whose properties are copied to the created prototype.
+		//		Add an instance-initialization function by making it a property
+		//		named "constructor".
+		//	returns:
+		//		New constructor function.
+		//	description:
+		//		Create a constructor using a compact notation for inheritance and
+		//		prototype extension.
+		//
+		//		Mixin ancestors provide a type of multiple inheritance.
+		//		Prototypes of mixin ancestors are copied to the new class:
+		//		changes to mixin prototypes will not affect classes to which
+		//		they have been mixed in.
+		//
+		//		Ancestors can be compound classes created by this version of
+		//		dojo.declare. In complex cases all base classes are going to be
+		//		linearized according to C3 MRO algorithm
+		//		(see http://www.python.org/download/releases/2.3/mro/ for more
+		//		details).
+		//
+		//		"className" is cached in "declaredClass" property of the new class,
+		//		if it was supplied. The immediate super class will be cached in
+		//		"superclass" property of the new class.
+		//
+		//		Methods in "props" will be copied and modified: "nom" property
+		//		(the declared name of the method) will be added to all copied
+		//		functions to help identify them for the internal machinery. Be
+		//		very careful, while reusing methods: if you use the same
+		//		function under different names, it can produce errors in some
+		//		cases.
+		//
+		//		It is possible to use constructors created "manually" (without
+		//		dojo.declare) as bases. They will be called as usual during the
+		//		creation of an instance, their methods will be chained, and even
+		//		called by "this.inherited()".
+		//
+		//		Special property "-chains-" governs how to chain methods. It is
+		//		a dictionary, which uses method names as keys, and hint strings
+		//		as values. If a hint string is "after", this method will be
+		//		called after methods of its base classes. If a hint string is
+		//		"before", this method will be called before methods of its base
+		//		classes.
+		//
+		//		If "constructor" is not mentioned in "-chains-" property, it will
+		//		be chained using the legacy mode: using "after" chaining,
+		//		calling preamble() method before each constructor, if available,
+		//		and calling postscript() after all constructors were executed.
+		//		If the hint is "after", it is chained as a regular method, but
+		//		postscript() will be called after the chain of constructors.
+		//		"constructor" cannot be chained "before", but it allows
+		//		a special hint string: "manual", which means that constructors
+		//		are not going to be chained in any way, and programmer will call
+		//		them manually using this.inherited(). In the latter case
+		//		postscript() will be called after the construction.
+		//
+		//		All chaining hints are "inherited" from base classes and
+		//		potentially can be overridden. Be very careful when overriding
+		//		hints! Make sure that all chained methods can work in a proposed
+		//		manner of chaining.
+		//
+		//		Once a method was chained, it is impossible to unchain it. The
+		//		only exception is "constructor". You don't need to define a
+		//		method in order to supply a chaining hint.
+		//
+		//		If a method is chained, it cannot use this.inherited() because
+		//		all other methods in the hierarchy will be called automatically.
+		//
+		//		Usually constructors and initializers of any kind are chained
+		//		using "after" and destructors of any kind are chained as
+		//		"before". Note that chaining assumes that chained methods do not
+		//		return any value: any returned value will be discarded.
+		//
+		//	example:
+		//	|	dojo.declare("my.classes.bar", my.classes.foo, {
+		//	|		// properties to be added to the class prototype
+		//	|		someValue: 2,
+		//	|		// initialization function
+		//	|		constructor: function(){
+		//	|			this.myComplicatedObject = new ReallyComplicatedObject();
+		//	|		},
+		//	|		// other functions
+		//	|		someMethod: function(){
+		//	|			doStuff();
+		//	|		}
+		//	|	});
+		//
+		//	example:
+		//	|	var MyBase = dojo.declare(null, {
+		//	|		// constructor, properties, and methods go here
+		//	|		// ...
+		//	|	});
+		//	|	var MyClass1 = dojo.declare(MyBase, {
+		//	|		// constructor, properties, and methods go here
+		//	|		// ...
+		//	|	});
+		//	|	var MyClass2 = dojo.declare(MyBase, {
+		//	|		// constructor, properties, and methods go here
+		//	|		// ...
+		//	|	});
+		//	|	var MyDiamond = dojo.declare([MyClass1, MyClass2], {
+		//	|		// constructor, properties, and methods go here
+		//	|		// ...
+		//	|	});
+		//
+		//	example:
+		//	|	var F = function(){ console.log("raw constructor"); };
+		//	|	F.prototype.method = function(){
+		//	|		console.log("raw method");
+		//	|	};
+		//	|	var A = dojo.declare(F, {
+		//	|		constructor: function(){
+		//	|			console.log("A.constructor");
+		//	|		},
+		//	|		method: function(){
+		//	|			console.log("before calling F.method...");
+		//	|			this.inherited(arguments);
+		//	|			console.log("...back in A");
+		//	|		}
+		//	|	});
+		//	|	new A().method();
+		//	|	// will print:
+		//	|	// raw constructor
+		//	|	// A.constructor
+		//	|	// before calling F.method...
+		//	|	// raw method
+		//	|	// ...back in A
+		//
+		//	example:
+		//	|	var A = dojo.declare(null, {
+		//	|		"-chains-": {
+		//	|			destroy: "before"
+		//	|		}
+		//	|	});
+		//	|	var B = dojo.declare(A, {
+		//	|		constructor: function(){
+		//	|			console.log("B.constructor");
+		//	|		},
+		//	|		destroy: function(){
+		//	|			console.log("B.destroy");
+		//	|		}
+		//	|	});
+		//	|	var C = dojo.declare(B, {
+		//	|		constructor: function(){
+		//	|			console.log("C.constructor");
+		//	|		},
+		//	|		destroy: function(){
+		//	|			console.log("C.destroy");
+		//	|		}
+		//	|	});
+		//	|	new C().destroy();
+		//	|	// prints:
+		//	|	// B.constructor
+		//	|	// C.constructor
+		//	|	// C.destroy
+		//	|	// B.destroy
+		//
+		//	example:
+		//	|	var A = dojo.declare(null, {
+		//	|		"-chains-": {
+		//	|			constructor: "manual"
+		//	|		}
+		//	|	});
+		//	|	var B = dojo.declare(A, {
+		//	|		constructor: function(){
+		//	|			// ...
+		//	|			// call the base constructor with new parameters
+		//	|			this.inherited(arguments, [1, 2, 3]);
+		//	|			// ...
+		//	|		}
+		//	|	});
+		//
+		//	example:
+		//	|	var A = dojo.declare(null, {
+		//	|		"-chains-": {
+		//	|			m1: "before"
+		//	|		},
+		//	|		m1: function(){
+		//	|			console.log("A.m1");
+		//	|		},
+		//	|		m2: function(){
+		//	|			console.log("A.m2");
+		//	|		}
+		//	|	});
+		//	|	var B = dojo.declare(A, {
+		//	|		"-chains-": {
+		//	|			m2: "after"
+		//	|		},
+		//	|		m1: function(){
+		//	|			console.log("B.m1");
+		//	|		},
+		//	|		m2: function(){
+		//	|			console.log("B.m2");
+		//	|		}
+		//	|	});
+		//	|	var x = new B();
+		//	|	x.m1();
+		//	|	// prints:
+		//	|	// B.m1
+		//	|	// A.m1
+		//	|	x.m2();
+		//	|	// prints:
+		//	|	// A.m2
+		//	|	// B.m2
+		return new Function(); // Function
+	};
+	=====*/
+
+	/*=====
+	dojo.safeMixin = function(target, source){
+		//	summary:
+		//		Mix in properties skipping a constructor and decorating functions
+		//		like it is done by dojo.declare.
+		//	target: Object
+		//		Target object to accept new properties.
+		//	source: Object
+		//		Source object for new properties.
+		//	description:
+		//		This function is used to mix in properties like dojo._mixin does,
+		//		but it skips a constructor property and decorates functions like
+		//		dojo.declare does.
+		//
+		//		It is meant to be used with classes and objects produced with
+		//		dojo.declare. Functions mixed in with dojo.safeMixin can use
+		//		this.inherited() like normal methods.
+		//
+		//		This function is used to implement extend() method of a constructor
+		//		produced with dojo.declare().
+		//
+		//	example:
+		//	|	var A = dojo.declare(null, {
+		//	|		m1: function(){
+		//	|			console.log("A.m1");
+		//	|		},
+		//	|		m2: function(){
+		//	|			console.log("A.m2");
+		//	|		}
+		//	|	});
+		//	|	var B = dojo.declare(A, {
+		//	|		m1: function(){
+		//	|			this.inherited(arguments);
+		//	|			console.log("B.m1");
+		//	|		}
+		//	|	});
+		//	|	B.extend({
+		//	|		m2: function(){
+		//	|			this.inherited(arguments);
+		//	|			console.log("B.m2");
+		//	|		}
+		//	|	});
+		//	|	var x = new B();
+		//	|	dojo.safeMixin(x, {
+		//	|		m1: function(){
+		//	|			this.inherited(arguments);
+		//	|			console.log("X.m1");
+		//	|		},
+		//	|		m2: function(){
+		//	|			this.inherited(arguments);
+		//	|			console.log("X.m2");
+		//	|		}
+		//	|	});
+		//	|	x.m2();
+		//	|	// prints:
+		//	|	// A.m1
+		//	|	// B.m1
+		//	|	// X.m1
+	};
+	=====*/
+
+	/*=====
+	Object.inherited = function(name, args, newArgs){
+		//	summary:
+		//		Calls a super method.
+		//	name: String?
+		//		The optional method name. Should be the same as the caller's
+		//		name. Usually "name" is specified in complex dynamic cases, when
+		//		the calling method was dynamically added, undecorated by
+		//		dojo.declare, and it cannot be determined.
+		//	args: Arguments
+		//		The caller supply this argument, which should be the original
+		//		"arguments".
+		//	newArgs: Object?
+		//		If "true", the found function will be returned without
+		//		executing it.
+		//		If Array, it will be used to call a super method. Otherwise
+		//		"args" will be used.
+		//	returns:
+		//		Whatever is returned by a super method, or a super method itself,
+		//		if "true" was specified as newArgs.
+		//	description:
+		//		This method is used inside method of classes produced with
+		//		dojo.declare to call a super method (next in the chain). It is
+		//		used for manually controlled chaining. Consider using the regular
+		//		chaining, because it is faster. Use "this.inherited()" only in
+		//		complex cases.
+		//
+		//		This method cannot me called from automatically chained
+		//		constructors including the case of a special (legacy)
+		//		constructor chaining. It cannot be called from chained methods.
+		//
+		//		If "this.inherited()" cannot find the next-in-chain method, it
+		//		does nothing and returns "undefined". The last method in chain
+		//		can be a default method implemented in Object, which will be
+		//		called last.
+		//
+		//		If "name" is specified, it is assumed that the method that
+		//		received "args" is the parent method for this call. It is looked
+		//		up in the chain list and if it is found the next-in-chain method
+		//		is called. If it is not found, the first-in-chain method is
+		//		called.
+		//
+		//		If "name" is not specified, it will be derived from the calling
+		//		method (using a methoid property "nom").
+		//
+		//	example:
+		//	|	var B = dojo.declare(A, {
+		//	|		method1: function(a, b, c){
+		//	|			this.inherited(arguments);
+		//	|		},
+		//	|		method2: function(a, b){
+		//	|			return this.inherited(arguments, [a + b]);
+		//	|		}
+		//	|	});
+		//	|	// next method is not in the chain list because it is added
+		//	|	// manually after the class was created.
+		//	|	B.prototype.method3 = function(){
+		//	|		console.log("This is a dynamically-added method.");
+		//	|		this.inherited("method3", arguments);
+		//	|	};
+		//	example:
+		//	|	var B = dojo.declare(A, {
+		//	|		method: function(a, b){
+		//	|			var super = this.inherited(arguments, true);
+		//	|			// ...
+		//	|			if(!super){
+		//	|				console.log("there is no super method");
+		//	|				return 0;
+		//	|			}
+		//	|			return super.apply(this, arguments);
+		//	|		}
+		//	|	});
+		return	{};	// Object
+	}
+	=====*/
+
+	/*=====
+	Object.getInherited = function(name, args){
+		//	summary:
+		//		Returns a super method.
+		//	name: String?
+		//		The optional method name. Should be the same as the caller's
+		//		name. Usually "name" is specified in complex dynamic cases, when
+		//		the calling method was dynamically added, undecorated by
+		//		dojo.declare, and it cannot be determined.
+		//	args: Arguments
+		//		The caller supply this argument, which should be the original
+		//		"arguments".
+		//	returns:
+		//		Returns a super method (Function) or "undefined".
+		//	description:
+		//		This method is a convenience method for "this.inherited()".
+		//		It uses the same algorithm but instead of executing a super
+		//		method, it returns it, or "undefined" if not found.
+		//
+		//	example:
+		//	|	var B = dojo.declare(A, {
+		//	|		method: function(a, b){
+		//	|			var super = this.getInherited(arguments);
+		//	|			// ...
+		//	|			if(!super){
+		//	|				console.log("there is no super method");
+		//	|				return 0;
+		//	|			}
+		//	|			return super.apply(this, arguments);
+		//	|		}
+		//	|	});
+		return	{};	// Object
+	}
+	=====*/
+
+	/*=====
+	Object.isInstanceOf = function(cls){
+		//	summary:
+		//		Checks the inheritance chain to see if it is inherited from this
+		//		class.
+		//	cls: Function
+		//		Class constructor.
+		//	returns:
+		//		"true", if this object is inherited from this class, "false"
+		//		otherwise.
+		//	description:
+		//		This method is used with instances of classes produced with
+		//		dojo.declare to determine of they support a certain interface or
+		//		not. It models "instanceof" operator.
+		//
+		//	example:
+		//	|	var A = dojo.declare(null, {
+		//	|		// constructor, properties, and methods go here
+		//	|		// ...
+		//	|	});
+		//	|	var B = dojo.declare(null, {
+		//	|		// constructor, properties, and methods go here
+		//	|		// ...
+		//	|	});
+		//	|	var C = dojo.declare([A, B], {
+		//	|		// constructor, properties, and methods go here
+		//	|		// ...
+		//	|	});
+		//	|	var D = dojo.declare(A, {
+		//	|		// constructor, properties, and methods go here
+		//	|		// ...
+		//	|	});
+		//	|
+		//	|	var a = new A(), b = new B(), c = new C(), d = new D();
+		//	|
+		//	|	console.log(a.isInstanceOf(A)); // true
+		//	|	console.log(b.isInstanceOf(A)); // false
+		//	|	console.log(c.isInstanceOf(A)); // true
+		//	|	console.log(d.isInstanceOf(A)); // true
+		//	|
+		//	|	console.log(a.isInstanceOf(B)); // false
+		//	|	console.log(b.isInstanceOf(B)); // true
+		//	|	console.log(c.isInstanceOf(B)); // true
+		//	|	console.log(d.isInstanceOf(B)); // false
+		//	|
+		//	|	console.log(a.isInstanceOf(C)); // false
+		//	|	console.log(b.isInstanceOf(C)); // false
+		//	|	console.log(c.isInstanceOf(C)); // true
+		//	|	console.log(d.isInstanceOf(C)); // false
+		//	|
+		//	|	console.log(a.isInstanceOf(D)); // false
+		//	|	console.log(b.isInstanceOf(D)); // false
+		//	|	console.log(c.isInstanceOf(D)); // false
+		//	|	console.log(d.isInstanceOf(D)); // true
+		return	{};	// Object
+	}
+	=====*/
+
+	/*=====
+	Object.extend = function(source){
+		//	summary:
+		//		Adds all properties and methods of source to constructor's
+		//		prototype, making them available to all instances created with
+		//		constructor. This method is specific to constructors created with
+		//		dojo.declare.
+		//	source: Object
+		//		Source object which properties are going to be copied to the
+		//		constructor's prototype.
+		//	description:
+		//		Adds source properties to the constructor's prototype. It can
+		//		override existing properties.
+		//
+		//		This method is similar to dojo.extend function, but it is specific
+		//		to constructors produced by dojo.declare. It is implemented
+		//		using dojo.safeMixin, and it skips a constructor property,
+		//		and properly decorates copied functions.
+		//
+		//	example:
+		//	|	var A = dojo.declare(null, {
+		//	|		m1: function(){},
+		//	|		s1: "Popokatepetl"
+		//	|	});
+		//	|	A.extend({
+		//	|		m1: function(){},
+		//	|		m2: function(){},
+		//	|		f1: true,
+		//	|		d1: 42
+		//	|	});
+	};
+	=====*/
 })();
-}
diff --git a/dojo/_base/event.js b/dojo/_base/event.js
index ae9fcfc..408da37 100644
--- a/dojo/_base/event.js
+++ b/dojo/_base/event.js
@@ -1,359 +1,654 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.event"]){
-dojo._hasResource["dojo._base.event"]=true;
 dojo.provide("dojo._base.event");
 dojo.require("dojo._base.connect");
+
+// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 (function(){
-var _1=(dojo._event_listener={add:function(_2,_3,fp){
-if(!_2){
-return;
-}
-_3=_1._normalizeEventName(_3);
-fp=_1._fixCallback(_3,fp);
-var _4=_3;
-if(!dojo.isIE&&(_3=="mouseenter"||_3=="mouseleave")){
-var _5=fp;
-_3=(_3=="mouseenter")?"mouseover":"mouseout";
-fp=function(e){
-if(!dojo.isDescendant(e.relatedTarget,_2)){
-return _5.call(this,e);
-}
-};
-}
-_2.addEventListener(_3,fp,false);
-return fp;
-},remove:function(_6,_7,_8){
-if(_6){
-_7=_1._normalizeEventName(_7);
-if(!dojo.isIE&&(_7=="mouseenter"||_7=="mouseleave")){
-_7=(_7=="mouseenter")?"mouseover":"mouseout";
-}
-_6.removeEventListener(_7,_8,false);
-}
-},_normalizeEventName:function(_9){
-return _9.slice(0,2)=="on"?_9.slice(2):_9;
-},_fixCallback:function(_a,fp){
-return _a!="keypress"?fp:function(e){
-return fp.call(this,_1._fixEvent(e,this));
-};
-},_fixEvent:function(_b,_c){
-switch(_b.type){
-case "keypress":
-_1._setKeyChar(_b);
-break;
-}
-return _b;
-},_setKeyChar:function(_d){
-_d.keyChar=_d.charCode?String.fromCharCode(_d.charCode):"";
-_d.charOrCode=_d.keyChar||_d.keyCode;
-},_punctMap:{106:42,111:47,186:59,187:43,188:44,189:45,190:46,191:47,192:96,219:91,220:92,221:93,222:39}});
-dojo.fixEvent=function(_e,_f){
-return _1._fixEvent(_e,_f);
-};
-dojo.stopEvent=function(evt){
-evt.preventDefault();
-evt.stopPropagation();
-};
-var _10=dojo._listener;
-dojo._connect=function(obj,_11,_12,_13,_14){
-var _15=obj&&(obj.nodeType||obj.attachEvent||obj.addEventListener);
-var lid=_15?(_14?2:1):0,l=[dojo._listener,_1,_10][lid];
-var h=l.add(obj,_11,dojo.hitch(_12,_13));
-return [obj,_11,h,lid];
-};
-dojo._disconnect=function(obj,_16,_17,_18){
-([dojo._listener,_1,_10][_18]).remove(obj,_16,_17);
-};
-dojo.keys={BACKSPACE:8,TAB:9,CLEAR:12,ENTER:13,SHIFT:16,CTRL:17,ALT:18,META:dojo.isSafari?91:224,PAUSE:19,CAPS_LOCK:20,ESCAPE:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT_ARROW:37,UP_ARROW:38,RIGHT_ARROW:39,DOWN_ARROW:40,INSERT:45,DELETE:46,HELP:47,LEFT_WINDOW:91,RIGHT_WINDOW:92,SELECT:93,NUMPAD_0:96,NUMPAD_1:97,NUMPAD_2:98,NUMPAD_3:99,NUMPAD_4:100,NUMPAD_5:101,NUMPAD_6:102,NUMPAD_7:103,NUMPAD_8:104,NUMPAD_9:105,NUMPAD_MULTIPLY:106,NUMPAD_PLUS:107,NUMPAD_ENTER:108,NUMPAD_MINUS [...]
-var _19=dojo.isMac?"metaKey":"ctrlKey";
-dojo.isCopyKey=function(e){
-return e[_19];
-};
-if(dojo.isIE){
-dojo.mouseButtons={LEFT:1,MIDDLE:4,RIGHT:2,isButton:function(e,_1a){
-return e.button&_1a;
-},isLeft:function(e){
-return e.button&1;
-},isMiddle:function(e){
-return e.button&4;
-},isRight:function(e){
-return e.button&2;
-}};
-}else{
-dojo.mouseButtons={LEFT:0,MIDDLE:1,RIGHT:2,isButton:function(e,_1b){
-return e.button==_1b;
-},isLeft:function(e){
-return e.button==0;
-},isMiddle:function(e){
-return e.button==1;
-},isRight:function(e){
-return e.button==2;
-}};
-}
-if(dojo.isIE){
-var _1c=function(e,_1d){
-try{
-return (e.keyCode=_1d);
-}
-catch(e){
-return 0;
-}
-};
-var iel=dojo._listener;
-var _1e=(dojo._ieListenersName="_"+dojo._scopeName+"_listeners");
-if(!dojo.config._allow_leaks){
-_10=iel=dojo._ie_listener={handlers:[],add:function(_1f,_20,_21){
-_1f=_1f||dojo.global;
-var f=_1f[_20];
-if(!f||!f[_1e]){
-var d=dojo._getIeDispatcher();
-d.target=f&&(ieh.push(f)-1);
-d[_1e]=[];
-f=_1f[_20]=d;
-}
-return f[_1e].push(ieh.push(_21)-1);
-},remove:function(_22,_23,_24){
-var f=(_22||dojo.global)[_23],l=f&&f[_1e];
-if(f&&l&&_24--){
-delete ieh[l[_24]];
-delete l[_24];
-}
-}};
-var ieh=iel.handlers;
-}
-dojo.mixin(_1,{add:function(_25,_26,fp){
-if(!_25){
-return;
-}
-_26=_1._normalizeEventName(_26);
-if(_26=="onkeypress"){
-var kd=_25.onkeydown;
-if(!kd||!kd[_1e]||!kd._stealthKeydownHandle){
-var h=_1.add(_25,"onkeydown",_1._stealthKeyDown);
-kd=_25.onkeydown;
-kd._stealthKeydownHandle=h;
-kd._stealthKeydownRefs=1;
-}else{
-kd._stealthKeydownRefs++;
-}
-}
-return iel.add(_25,_26,_1._fixCallback(fp));
-},remove:function(_27,_28,_29){
-_28=_1._normalizeEventName(_28);
-iel.remove(_27,_28,_29);
-if(_28=="onkeypress"){
-var kd=_27.onkeydown;
-if(--kd._stealthKeydownRefs<=0){
-iel.remove(_27,"onkeydown",kd._stealthKeydownHandle);
-delete kd._stealthKeydownHandle;
-}
-}
-},_normalizeEventName:function(_2a){
-return _2a.slice(0,2)!="on"?"on"+_2a:_2a;
-},_nop:function(){
-},_fixEvent:function(evt,_2b){
-if(!evt){
-var w=_2b&&(_2b.ownerDocument||_2b.document||_2b).parentWindow||window;
-evt=w.event;
-}
-if(!evt){
-return (evt);
-}
-evt.target=evt.srcElement;
-evt.currentTarget=(_2b||evt.srcElement);
-evt.layerX=evt.offsetX;
-evt.layerY=evt.offsetY;
-var se=evt.srcElement,doc=(se&&se.ownerDocument)||document;
-var _2c=((dojo.isIE<6)||(doc["compatMode"]=="BackCompat"))?doc.body:doc.documentElement;
-var _2d=dojo._getIeDocumentElementOffset();
-evt.pageX=evt.clientX+dojo._fixIeBiDiScrollLeft(_2c.scrollLeft||0)-_2d.x;
-evt.pageY=evt.clientY+(_2c.scrollTop||0)-_2d.y;
-if(evt.type=="mouseover"){
-evt.relatedTarget=evt.fromElement;
-}
-if(evt.type=="mouseout"){
-evt.relatedTarget=evt.toElement;
-}
-evt.stopPropagation=_1._stopPropagation;
-evt.preventDefault=_1._preventDefault;
-return _1._fixKeys(evt);
-},_fixKeys:function(evt){
-switch(evt.type){
-case "keypress":
-var c=("charCode" in evt?evt.charCode:evt.keyCode);
-if(c==10){
-c=0;
-evt.keyCode=13;
-}else{
-if(c==13||c==27){
-c=0;
-}else{
-if(c==3){
-c=99;
-}
-}
-}
-evt.charCode=c;
-_1._setKeyChar(evt);
-break;
-}
-return evt;
-},_stealthKeyDown:function(evt){
-var kp=evt.currentTarget.onkeypress;
-if(!kp||!kp[_1e]){
-return;
-}
-var k=evt.keyCode;
-var _2e=k!=13&&k!=32&&k!=27&&(k<48||k>90)&&(k<96||k>111)&&(k<186||k>192)&&(k<219||k>222);
-if(_2e||evt.ctrlKey){
-var c=_2e?0:k;
-if(evt.ctrlKey){
-if(k==3||k==13){
-return;
-}else{
-if(c>95&&c<106){
-c-=48;
-}else{
-if((!evt.shiftKey)&&(c>=65&&c<=90)){
-c+=32;
-}else{
-c=_1._punctMap[c]||c;
-}
-}
-}
-}
-var _2f=_1._synthesizeEvent(evt,{type:"keypress",faux:true,charCode:c});
-kp.call(evt.currentTarget,_2f);
-evt.cancelBubble=_2f.cancelBubble;
-evt.returnValue=_2f.returnValue;
-_1c(evt,_2f.keyCode);
-}
-},_stopPropagation:function(){
-this.cancelBubble=true;
-},_preventDefault:function(){
-this.bubbledKeyCode=this.keyCode;
-if(this.ctrlKey){
-_1c(this,0);
-}
-this.returnValue=false;
-}});
-dojo.stopEvent=function(evt){
-evt=evt||window.event;
-_1._stopPropagation.call(evt);
-_1._preventDefault.call(evt);
-};
-}
-_1._synthesizeEvent=function(evt,_30){
-var _31=dojo.mixin({},evt,_30);
-_1._setKeyChar(_31);
-_31.preventDefault=function(){
-evt.preventDefault();
-};
-_31.stopPropagation=function(){
-evt.stopPropagation();
-};
-return _31;
-};
-if(dojo.isOpera){
-dojo.mixin(_1,{_fixEvent:function(evt,_32){
-switch(evt.type){
-case "keypress":
-var c=evt.which;
-if(c==3){
-c=99;
-}
-c=c<41&&!evt.shiftKey?0:c;
-if(evt.ctrlKey&&!evt.shiftKey&&c>=65&&c<=90){
-c+=32;
-}
-return _1._synthesizeEvent(evt,{charCode:c});
-}
-return evt;
-}});
-}
-if(dojo.isWebKit){
-_1._add=_1.add;
-_1._remove=_1.remove;
-dojo.mixin(_1,{add:function(_33,_34,fp){
-if(!_33){
-return;
-}
-var _35=_1._add(_33,_34,fp);
-if(_1._normalizeEventName(_34)=="keypress"){
-_35._stealthKeyDownHandle=_1._add(_33,"keydown",function(evt){
-var k=evt.keyCode;
-var _36=k!=13&&k!=32&&(k<48||k>90)&&(k<96||k>111)&&(k<186||k>192)&&(k<219||k>222);
-if(_36||evt.ctrlKey){
-var c=_36?0:k;
-if(evt.ctrlKey){
-if(k==3||k==13){
-return;
-}else{
-if(c>95&&c<106){
-c-=48;
-}else{
-if(!evt.shiftKey&&c>=65&&c<=90){
-c+=32;
-}else{
-c=_1._punctMap[c]||c;
-}
-}
-}
-}
-var _37=_1._synthesizeEvent(evt,{type:"keypress",faux:true,charCode:c});
-fp.call(evt.currentTarget,_37);
-}
-});
-}
-return _35;
-},remove:function(_38,_39,_3a){
-if(_38){
-if(_3a._stealthKeyDownHandle){
-_1._remove(_38,"keydown",_3a._stealthKeyDownHandle);
-}
-_1._remove(_38,_39,_3a);
-}
-},_fixEvent:function(evt,_3b){
-switch(evt.type){
-case "keypress":
-if(evt.faux){
-return evt;
-}
-var c=evt.charCode;
-c=c>=32?c:0;
-return _1._synthesizeEvent(evt,{charCode:c,faux:true});
-}
-return evt;
-}});
-}
+//>>excludeEnd("webkitMobile");
+	// DOM event listener machinery
+	var del = (dojo._event_listener = {
+		add: function(/*DOMNode*/ node, /*String*/ name, /*Function*/ fp){
+			if(!node){return;} 
+			name = del._normalizeEventName(name);
+			fp = del._fixCallback(name, fp);
+			var oname = name;
+			if(
+				//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+				!dojo.isIE && 
+				//>>excludeEnd("webkitMobile");
+				(name == "mouseenter" || name == "mouseleave")
+			){
+				var ofp = fp;
+				//oname = name;
+				name = (name == "mouseenter") ? "mouseover" : "mouseout";
+				fp = function(e){
+					if(!dojo.isDescendant(e.relatedTarget, node)){
+						// e.type = oname; // FIXME: doesn't take? SJM: event.type is generally immutable.
+						return ofp.call(this, e); 
+					}
+				}
+			}
+			node.addEventListener(name, fp, false);
+			return fp; /*Handle*/
+		},
+		remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
+			// summary:
+			//		clobbers the listener from the node
+			// node:
+			//		DOM node to attach the event to
+			// event:
+			//		the name of the handler to remove the function from
+			// handle:
+			//		the handle returned from add
+			if(node){
+				event = del._normalizeEventName(event);
+				if(!dojo.isIE && (event == "mouseenter" || event == "mouseleave")){
+					event = (event == "mouseenter") ? "mouseover" : "mouseout";
+				}
+
+				node.removeEventListener(event, handle, false);
+			}
+		},
+		_normalizeEventName: function(/*String*/ name){
+			// Generally, name should be lower case, unless it is special
+			// somehow (e.g. a Mozilla DOM event).
+			// Remove 'on'.
+			return name.slice(0,2) =="on" ? name.slice(2) : name;
+		},
+		_fixCallback: function(/*String*/ name, fp){
+			// By default, we only invoke _fixEvent for 'keypress'
+			// If code is added to _fixEvent for other events, we have
+			// to revisit this optimization.
+			// This also applies to _fixEvent overrides for Safari and Opera
+			// below.
+			return name != "keypress" ? fp : function(e){ return fp.call(this, del._fixEvent(e, this)); };
+		},
+		_fixEvent: function(evt, sender){
+			// _fixCallback only attaches us to keypress.
+			// Switch on evt.type anyway because we might 
+			// be called directly from dojo.fixEvent.
+			switch(evt.type){
+				case "keypress":
+					del._setKeyChar(evt);
+					break;
+			}
+			return evt;
+		},
+		_setKeyChar: function(evt){
+			evt.keyChar = evt.charCode ? String.fromCharCode(evt.charCode) : '';
+			evt.charOrCode = evt.keyChar || evt.keyCode;
+		},
+		// For IE and Safari: some ctrl-key combinations (mostly w/punctuation) do not emit a char code in IE
+		// we map those virtual key codes to ascii here
+		// not valid for all (non-US) keyboards, so maybe we shouldn't bother
+		_punctMap: { 
+			106:42, 
+			111:47, 
+			186:59, 
+			187:43, 
+			188:44, 
+			189:45, 
+			190:46, 
+			191:47, 
+			192:96, 
+			219:91, 
+			220:92, 
+			221:93, 
+			222:39 
+		}
+	});
+
+	// DOM events
+	
+	dojo.fixEvent = function(/*Event*/ evt, /*DOMNode*/ sender){
+		// summary:
+		//		normalizes properties on the event object including event
+		//		bubbling methods, keystroke normalization, and x/y positions
+		// evt: Event
+		//		native event object
+		// sender: DOMNode
+		//		node to treat as "currentTarget"
+		return del._fixEvent(evt, sender);
+	}
+
+	dojo.stopEvent = function(/*Event*/ evt){
+		// summary:
+		//		prevents propagation and clobbers the default action of the
+		//		passed event
+		// evt: Event
+		//		The event object. If omitted, window.event is used on IE.
+		evt.preventDefault();
+		evt.stopPropagation();
+		// NOTE: below, this method is overridden for IE
+	}
+
+	// the default listener to use on dontFix nodes, overriden for IE
+	var node_listener = dojo._listener;
+	
+	// Unify connect and event listeners
+	dojo._connect = function(obj, event, context, method, dontFix){
+		// FIXME: need a more strict test
+		var isNode = obj && (obj.nodeType||obj.attachEvent||obj.addEventListener);
+		// choose one of three listener options: raw (connect.js), DOM event on a Node, custom event on a Node
+		// we need the third option to provide leak prevention on broken browsers (IE)
+		var lid = isNode ? (dontFix ? 2 : 1) : 0, l = [dojo._listener, del, node_listener][lid];
+		// create a listener
+		var h = l.add(obj, event, dojo.hitch(context, method));
+		// formerly, the disconnect package contained "l" directly, but if client code
+		// leaks the disconnect package (by connecting it to a node), referencing "l" 
+		// compounds the problem.
+		// instead we return a listener id, which requires custom _disconnect below.
+		// return disconnect package
+		return [ obj, event, h, lid ];
+	}
+
+	dojo._disconnect = function(obj, event, handle, listener){
+		([dojo._listener, del, node_listener][listener]).remove(obj, event, handle);
+	}
+
+	// Constants
+
+	// Public: client code should test
+	// keyCode against these named constants, as the
+	// actual codes can vary by browser.
+	dojo.keys = {
+		// summary:
+		//		Definitions for common key values
+		BACKSPACE: 8,
+		TAB: 9,
+		CLEAR: 12,
+		ENTER: 13,
+		SHIFT: 16,
+		CTRL: 17,
+		ALT: 18,
+		META: dojo.isSafari ? 91 : 224,		// the apple key on macs
+		PAUSE: 19,
+		CAPS_LOCK: 20,
+		ESCAPE: 27,
+		SPACE: 32,
+		PAGE_UP: 33,
+		PAGE_DOWN: 34,
+		END: 35,
+		HOME: 36,
+		LEFT_ARROW: 37,
+		UP_ARROW: 38,
+		RIGHT_ARROW: 39,
+		DOWN_ARROW: 40,
+		INSERT: 45,
+		DELETE: 46,
+		HELP: 47,
+		LEFT_WINDOW: 91,
+		RIGHT_WINDOW: 92,
+		SELECT: 93,
+		NUMPAD_0: 96,
+		NUMPAD_1: 97,
+		NUMPAD_2: 98,
+		NUMPAD_3: 99,
+		NUMPAD_4: 100,
+		NUMPAD_5: 101,
+		NUMPAD_6: 102,
+		NUMPAD_7: 103,
+		NUMPAD_8: 104,
+		NUMPAD_9: 105,
+		NUMPAD_MULTIPLY: 106,
+		NUMPAD_PLUS: 107,
+		NUMPAD_ENTER: 108,
+		NUMPAD_MINUS: 109,
+		NUMPAD_PERIOD: 110,
+		NUMPAD_DIVIDE: 111,
+		F1: 112,
+		F2: 113,
+		F3: 114,
+		F4: 115,
+		F5: 116,
+		F6: 117,
+		F7: 118,
+		F8: 119,
+		F9: 120,
+		F10: 121,
+		F11: 122,
+		F12: 123,
+		F13: 124,
+		F14: 125,
+		F15: 126,
+		NUM_LOCK: 144,
+		SCROLL_LOCK: 145,
+		// virtual key mapping
+		copyKey: dojo.isMac && !dojo.isAIR ? (dojo.isSafari ? 91 : 224 ) : 17
+	};
+	
+	var evtCopyKey = dojo.isMac ? "metaKey" : "ctrlKey";
+	
+	dojo.isCopyKey = function(e){
+		// summary:
+		//		Checks an event for the copy key (meta on Mac, and ctrl anywhere else)
+		// e: Event
+		//		Event object to examine
+		return e[evtCopyKey];	// Boolean
+	};
+
+	// Public: decoding mouse buttons from events
+
+/*=====
+	dojo.mouseButtons = {
+		// LEFT: Number
+		//		Numeric value of the left mouse button for the platform.
+		LEFT:   0,
+		// MIDDLE: Number
+		//		Numeric value of the middle mouse button for the platform.
+		MIDDLE: 1,
+		// RIGHT: Number
+		//		Numeric value of the right mouse button for the platform.
+		RIGHT:  2,
+	
+		isButton: function(e, button){
+			// summary:
+			//		Checks an event object for a pressed button
+			// e: Event
+			//		Event object to examine
+			// button: Number
+			//		The button value (example: dojo.mouseButton.LEFT)
+			return e.button == button; // Boolean
+		},
+		isLeft: function(e){
+			// summary:
+			//		Checks an event object for the pressed left button
+			// e: Event
+			//		Event object to examine
+			return e.button == 0; // Boolean
+		},
+		isMiddle: function(e){
+			// summary:
+			//		Checks an event object for the pressed middle button
+			// e: Event
+			//		Event object to examine
+			return e.button == 1; // Boolean
+		},
+		isRight: function(e){
+			// summary:
+			//		Checks an event object for the pressed right button
+			// e: Event
+			//		Event object to examine
+			return e.button == 2; // Boolean
+		}
+	};
+=====*/
+
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	if(dojo.isIE){
+		dojo.mouseButtons = {
+			LEFT:   1,
+			MIDDLE: 4,
+			RIGHT:  2,
+			// helper functions
+			isButton: function(e, button){ return e.button & button; },
+			isLeft:   function(e){ return e.button & 1; },
+			isMiddle: function(e){ return e.button & 4; },
+			isRight:  function(e){ return e.button & 2; }
+		};
+	}else{
+	//>>excludeEnd("webkitMobile");
+		dojo.mouseButtons = {
+			LEFT:   0,
+			MIDDLE: 1,
+			RIGHT:  2,
+			// helper functions
+			isButton: function(e, button){ return e.button == button; },
+			isLeft:   function(e){ return e.button == 0; },
+			isMiddle: function(e){ return e.button == 1; },
+			isRight:  function(e){ return e.button == 2; }
+		};
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	}
+	//>>excludeEnd("webkitMobile");
+
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	// IE event normalization
+	if(dojo.isIE){ 
+		var _trySetKeyCode = function(e, code){
+			try{
+				// squelch errors when keyCode is read-only
+				// (e.g. if keyCode is ctrl or shift)
+				return (e.keyCode = code);
+			}catch(e){
+				return 0;
+			}
+		}
+
+		// by default, use the standard listener
+		var iel = dojo._listener;
+		var listenersName = (dojo._ieListenersName = "_" + dojo._scopeName + "_listeners");
+		// dispatcher tracking property
+		if(!dojo.config._allow_leaks){
+			// custom listener that handles leak protection for DOM events
+			node_listener = iel = dojo._ie_listener = {
+				// support handler indirection: event handler functions are 
+				// referenced here. Event dispatchers hold only indices.
+				handlers: [],
+				// add a listener to an object
+				add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
+					source = source || dojo.global;
+					var f = source[method];
+					if(!f||!f[listenersName]){
+						var d = dojo._getIeDispatcher();
+						// original target function is special
+						d.target = f && (ieh.push(f) - 1);
+						// dispatcher holds a list of indices into handlers table
+						d[listenersName] = [];
+						// redirect source to dispatcher
+						f = source[method] = d;
+					}
+					return f[listenersName].push(ieh.push(listener) - 1) ; /*Handle*/
+				},
+				// remove a listener from an object
+				remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
+					var f = (source||dojo.global)[method], l = f && f[listenersName];
+					if(f && l && handle--){
+						delete ieh[l[handle]];
+						delete l[handle];
+					}
+				}
+			};
+			// alias used above
+			var ieh = iel.handlers;
+		}
+
+		dojo.mixin(del, {
+			add: function(/*DOMNode*/ node, /*String*/ event, /*Function*/ fp){
+				if(!node){return;} // undefined
+				event = del._normalizeEventName(event);
+				if(event=="onkeypress"){
+					// we need to listen to onkeydown to synthesize
+					// keypress events that otherwise won't fire
+					// on IE
+					var kd = node.onkeydown;
+					if(!kd || !kd[listenersName] || !kd._stealthKeydownHandle){
+						var h = del.add(node, "onkeydown", del._stealthKeyDown);
+						kd = node.onkeydown;
+						kd._stealthKeydownHandle = h;
+						kd._stealthKeydownRefs = 1;
+					}else{
+						kd._stealthKeydownRefs++;
+					}
+				}
+				return iel.add(node, event, del._fixCallback(fp));
+			},
+			remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
+				event = del._normalizeEventName(event);
+				iel.remove(node, event, handle); 
+				if(event=="onkeypress"){
+					var kd = node.onkeydown;
+					if(--kd._stealthKeydownRefs <= 0){
+						iel.remove(node, "onkeydown", kd._stealthKeydownHandle);
+						delete kd._stealthKeydownHandle;
+					}
+				}
+			},
+			_normalizeEventName: function(/*String*/ eventName){
+				// Generally, eventName should be lower case, unless it is
+				// special somehow (e.g. a Mozilla event)
+				// ensure 'on'
+				return eventName.slice(0,2) != "on" ? "on" + eventName : eventName;
+			},
+			_nop: function(){},
+			_fixEvent: function(/*Event*/ evt, /*DOMNode*/ sender){
+				// summary:
+				//		normalizes properties on the event object including event
+				//		bubbling methods, keystroke normalization, and x/y positions
+				// evt:
+				//		native event object
+				// sender:
+				//		node to treat as "currentTarget"
+				if(!evt){
+					var w = sender && (sender.ownerDocument || sender.document || sender).parentWindow || window;
+					evt = w.event; 
+				}
+				if(!evt){return(evt);}
+				evt.target = evt.srcElement; 
+				evt.currentTarget = (sender || evt.srcElement); 
+				evt.layerX = evt.offsetX;
+				evt.layerY = evt.offsetY;
+				// FIXME: scroll position query is duped from dojo.html to
+				// avoid dependency on that entire module. Now that HTML is in
+				// Base, we should convert back to something similar there.
+				var se = evt.srcElement, doc = (se && se.ownerDocument) || document;
+				// DO NOT replace the following to use dojo.body(), in IE, document.documentElement should be used
+				// here rather than document.body
+				var docBody = ((dojo.isIE < 6) || (doc["compatMode"] == "BackCompat")) ? doc.body : doc.documentElement;
+				var offset = dojo._getIeDocumentElementOffset();
+				evt.pageX = evt.clientX + dojo._fixIeBiDiScrollLeft(docBody.scrollLeft || 0) - offset.x;
+				evt.pageY = evt.clientY + (docBody.scrollTop || 0) - offset.y;
+				if(evt.type == "mouseover"){ 
+					evt.relatedTarget = evt.fromElement;
+				}
+				if(evt.type == "mouseout"){ 
+					evt.relatedTarget = evt.toElement;
+				}
+				evt.stopPropagation = del._stopPropagation;
+				evt.preventDefault = del._preventDefault;
+				return del._fixKeys(evt);
+			},
+			_fixKeys: function(evt){
+				switch(evt.type){
+					case "keypress":
+						var c = ("charCode" in evt ? evt.charCode : evt.keyCode);
+						if (c==10){
+							// CTRL-ENTER is CTRL-ASCII(10) on IE, but CTRL-ENTER on Mozilla
+							c=0;
+							evt.keyCode = 13;
+						}else if(c==13||c==27){
+							c=0; // Mozilla considers ENTER and ESC non-printable
+						}else if(c==3){
+							c=99; // Mozilla maps CTRL-BREAK to CTRL-c
+						}
+						// Mozilla sets keyCode to 0 when there is a charCode
+						// but that stops the event on IE.
+						evt.charCode = c;
+						del._setKeyChar(evt);
+						break;
+				}
+				return evt;
+			},
+			_stealthKeyDown: function(evt){
+				// IE doesn't fire keypress for most non-printable characters.
+				// other browsers do, we simulate it here.
+				var kp = evt.currentTarget.onkeypress;
+				// only works if kp exists and is a dispatcher
+				if(!kp || !kp[listenersName]){ return; }
+				// munge key/charCode
+				var k=evt.keyCode;
+				// These are Windows Virtual Key Codes
+				// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
+				var unprintable = k!=13 && k!=32 && k!=27 && (k<48||k>90) && (k<96||k>111) && (k<186||k>192) && (k<219||k>222);
+				// synthesize keypress for most unprintables and CTRL-keys
+				if(unprintable||evt.ctrlKey){
+					var c = unprintable ? 0 : k;
+					if(evt.ctrlKey){
+						if(k==3 || k==13){
+							return; // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively 
+						}else if(c>95 && c<106){ 
+							c -= 48; // map CTRL-[numpad 0-9] to ASCII
+						}else if((!evt.shiftKey)&&(c>=65&&c<=90)){ 
+							c += 32; // map CTRL-[A-Z] to lowercase
+						}else{ 
+							c = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
+						}
+					}
+					// simulate a keypress event
+					var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
+					kp.call(evt.currentTarget, faux);
+					evt.cancelBubble = faux.cancelBubble;
+					evt.returnValue = faux.returnValue;
+					_trySetKeyCode(evt, faux.keyCode);
+				}
+			},
+			// Called in Event scope
+			_stopPropagation: function(){
+				this.cancelBubble = true; 
+			},
+			_preventDefault: function(){
+				// Setting keyCode to 0 is the only way to prevent certain keypresses (namely
+				// ctrl-combinations that correspond to menu accelerator keys).
+				// Otoh, it prevents upstream listeners from getting this information
+				// Try to split the difference here by clobbering keyCode only for ctrl 
+				// combinations. If you still need to access the key upstream, bubbledKeyCode is
+				// provided as a workaround.
+				this.bubbledKeyCode = this.keyCode;
+				if(this.ctrlKey){_trySetKeyCode(this, 0);}
+				this.returnValue = false;
+			}
+		});
+				
+		// override stopEvent for IE
+		dojo.stopEvent = function(evt){
+			evt = evt || window.event;
+			del._stopPropagation.call(evt);
+			del._preventDefault.call(evt);
+		}
+	}
+	//>>excludeEnd("webkitMobile");
+
+	del._synthesizeEvent = function(evt, props){
+			var faux = dojo.mixin({}, evt, props);
+			del._setKeyChar(faux);
+			// FIXME: would prefer to use dojo.hitch: dojo.hitch(evt, evt.preventDefault); 
+			// but it throws an error when preventDefault is invoked on Safari
+			// does Event.preventDefault not support "apply" on Safari?
+			faux.preventDefault = function(){ evt.preventDefault(); }; 
+			faux.stopPropagation = function(){ evt.stopPropagation(); }; 
+			return faux;
+	}
+	
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	// Opera event normalization
+	if(dojo.isOpera){
+		dojo.mixin(del, {
+			_fixEvent: function(evt, sender){
+				switch(evt.type){
+					case "keypress":
+						var c = evt.which;
+						if(c==3){
+							c=99; // Mozilla maps CTRL-BREAK to CTRL-c
+						}
+						// can't trap some keys at all, like INSERT and DELETE
+						// there is no differentiating info between DELETE and ".", or INSERT and "-"
+						c = c<41 && !evt.shiftKey ? 0 : c;
+						if(evt.ctrlKey && !evt.shiftKey && c>=65 && c<=90){
+							// lowercase CTRL-[A-Z] keys
+							c += 32;
+						}
+						return del._synthesizeEvent(evt, { charCode: c });
+				}
+				return evt;
+			}
+		});
+	}
+	//>>excludeEnd("webkitMobile");
+
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	// Webkit event normalization
+	if(dojo.isWebKit){
+		//>>excludeEnd("webkitMobile");
+		del._add = del.add;
+		del._remove = del.remove;
+
+		dojo.mixin(del, {
+			add: function(/*DOMNode*/ node, /*String*/ event, /*Function*/ fp){
+				if(!node){return;} // undefined
+				var handle = del._add(node, event, fp);
+				if(del._normalizeEventName(event) == "keypress"){
+					// we need to listen to onkeydown to synthesize
+					// keypress events that otherwise won't fire
+					// in Safari 3.1+: https://lists.webkit.org/pipermail/webkit-dev/2007-December/002992.html
+					handle._stealthKeyDownHandle = del._add(node, "keydown", function(evt){
+						//A variation on the IE _stealthKeydown function
+						//Synthesize an onkeypress event, but only for unprintable characters.
+						var k=evt.keyCode;
+						// These are Windows Virtual Key Codes
+						// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
+						var unprintable = k!=13 && k!=32 && (k<48 || k>90) && (k<96 || k>111) && (k<186 || k>192) && (k<219 || k>222);
+						// synthesize keypress for most unprintables and CTRL-keys
+						if(unprintable || evt.ctrlKey){
+							var c = unprintable ? 0 : k;
+							if(evt.ctrlKey){
+								if(k==3 || k==13){
+									return; // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively 
+								}else if(c>95 && c<106){ 
+									c -= 48; // map CTRL-[numpad 0-9] to ASCII
+								}else if(!evt.shiftKey && c>=65 && c<=90){ 
+									c += 32; // map CTRL-[A-Z] to lowercase
+								}else{ 
+									c = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
+								}
+							}
+							// simulate a keypress event
+							var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
+							fp.call(evt.currentTarget, faux);
+						}
+					});
+				}
+				return handle; /*Handle*/
+			},
+
+			remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
+				if(node){
+					if(handle._stealthKeyDownHandle){
+						del._remove(node, "keydown", handle._stealthKeyDownHandle);
+					}
+					del._remove(node, event, handle);
+				}
+			},
+			_fixEvent: function(evt, sender){
+				switch(evt.type){
+					case "keypress":
+						if(evt.faux){ return evt; }
+						var c = evt.charCode;
+						c = c>=32 ? c : 0;
+						return del._synthesizeEvent(evt, {charCode: c, faux: true});
+				}
+				return evt;
+			}
+		});
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	}
+	//>>excludeEnd("webkitMobile");
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 })();
+//>>excludeEnd("webkitMobile");
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 if(dojo.isIE){
-dojo._ieDispatcher=function(_3c,_3d){
-var ap=Array.prototype,h=dojo._ie_listener.handlers,c=_3c.callee,ls=c[dojo._ieListenersName],t=h[c.target];
-var r=t&&t.apply(_3d,_3c);
-var lls=[].concat(ls);
-for(var i in lls){
-var f=h[lls[i]];
-if(!(i in ap)&&f){
-f.apply(_3d,_3c);
-}
-}
-return r;
-};
-dojo._getIeDispatcher=function(){
-return new Function(dojo._scopeName+"._ieDispatcher(arguments, this)");
-};
-dojo._event_listener._fixCallback=function(fp){
-var f=dojo._event_listener._fixEvent;
-return function(e){
-return fp.call(this,f(e,this));
-};
-};
-}
-}
+	// keep this out of the closure
+	// closing over 'iel' or 'ieh' b0rks leak prevention
+	// ls[i] is an index into the master handler array
+	dojo._ieDispatcher = function(args, sender){
+		var ap = Array.prototype,
+			h = dojo._ie_listener.handlers,
+			c = args.callee,
+			ls = c[dojo._ieListenersName],
+			t = h[c.target];
+		// return value comes from original target function
+		var r = t && t.apply(sender, args);
+		// make local copy of listener array so it's immutable during processing
+		var lls = [].concat(ls);
+		// invoke listeners after target function
+		for(var i in lls){
+			var f = h[lls[i]];
+			if(!(i in ap) && f){
+				f.apply(sender, args);
+			}
+		}
+		return r;
+	}
+	dojo._getIeDispatcher = function(){
+		// ensure the returned function closes over nothing ("new Function" apparently doesn't close)
+		return new Function(dojo._scopeName + "._ieDispatcher(arguments, this)"); // function
+	}
+	// keep this out of the closure to reduce RAM allocation
+	dojo._event_listener._fixCallback = function(fp){
+		var f = dojo._event_listener._fixEvent;
+		return function(e){ return fp.call(this, f(e, this)); };
+	}
+}
+//>>excludeEnd("webkitMobile");
diff --git a/dojo/_base/fx.js b/dojo/_base/fx.js
index 2d2bf98..2a7ccb1 100644
--- a/dojo/_base/fx.js
+++ b/dojo/_base/fx.js
@@ -1,303 +1,664 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.fx"]){
-dojo._hasResource["dojo._base.fx"]=true;
 dojo.provide("dojo._base.fx");
 dojo.require("dojo._base.Color");
 dojo.require("dojo._base.connect");
 dojo.require("dojo._base.lang");
 dojo.require("dojo._base.html");
+
+/*
+	Animation loosely package based on Dan Pupius' work, contributed under CLA:
+		http://pupius.co.uk/js/Toolkit.Drawing.js
+*/
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 (function(){
-var d=dojo;
-var _1=d._mixin;
-dojo._Line=function(_2,_3){
-this.start=_2;
-this.end=_3;
-};
-dojo._Line.prototype.getValue=function(n){
-return ((this.end-this.start)*n)+this.start;
-};
-dojo.Animation=function(_4){
-_1(this,_4);
-if(d.isArray(this.curve)){
-this.curve=new d._Line(this.curve[0],this.curve[1]);
-}
-};
-d._Animation=d.Animation;
-d.extend(dojo.Animation,{duration:350,repeat:0,rate:20,_percent:0,_startRepeatCount:0,_getStep:function(){
-var _5=this._percent,_6=this.easing;
-return _6?_6(_5):_5;
-},_fire:function(_7,_8){
-var a=_8||[];
-if(this[_7]){
-if(d.config.debugAtAllCosts){
-this[_7].apply(this,a);
-}else{
-try{
-this[_7].apply(this,a);
-}
-catch(e){
-console.error("exception in animation handler for:",_7);
-console.error(e);
-}
-}
-}
-return this;
-},play:function(_9,_a){
-var _b=this;
-if(_b._delayTimer){
-_b._clearTimer();
-}
-if(_a){
-_b._stopTimer();
-_b._active=_b._paused=false;
-_b._percent=0;
-}else{
-if(_b._active&&!_b._paused){
-return _b;
-}
-}
-_b._fire("beforeBegin",[_b.node]);
-var de=_9||_b.delay,_c=dojo.hitch(_b,"_play",_a);
-if(de>0){
-_b._delayTimer=setTimeout(_c,de);
-return _b;
-}
-_c();
-return _b;
-},_play:function(_d){
-var _e=this;
-if(_e._delayTimer){
-_e._clearTimer();
-}
-_e._startTime=new Date().valueOf();
-if(_e._paused){
-_e._startTime-=_e.duration*_e._percent;
-}
-_e._endTime=_e._startTime+_e.duration;
-_e._active=true;
-_e._paused=false;
-var _f=_e.curve.getValue(_e._getStep());
-if(!_e._percent){
-if(!_e._startRepeatCount){
-_e._startRepeatCount=_e.repeat;
-}
-_e._fire("onBegin",[_f]);
-}
-_e._fire("onPlay",[_f]);
-_e._cycle();
-return _e;
-},pause:function(){
-var _10=this;
-if(_10._delayTimer){
-_10._clearTimer();
-}
-_10._stopTimer();
-if(!_10._active){
-return _10;
-}
-_10._paused=true;
-_10._fire("onPause",[_10.curve.getValue(_10._getStep())]);
-return _10;
-},gotoPercent:function(_11,_12){
-var _13=this;
-_13._stopTimer();
-_13._active=_13._paused=true;
-_13._percent=_11;
-if(_12){
-_13.play();
-}
-return _13;
-},stop:function(_14){
-var _15=this;
-if(_15._delayTimer){
-_15._clearTimer();
-}
-if(!_15._timer){
-return _15;
-}
-_15._stopTimer();
-if(_14){
-_15._percent=1;
-}
-_15._fire("onStop",[_15.curve.getValue(_15._getStep())]);
-_15._active=_15._paused=false;
-return _15;
-},status:function(){
-if(this._active){
-return this._paused?"paused":"playing";
-}
-return "stopped";
-},_cycle:function(){
-var _16=this;
-if(_16._active){
-var _17=new Date().valueOf();
-var _18=(_17-_16._startTime)/(_16._endTime-_16._startTime);
-if(_18>=1){
-_18=1;
-}
-_16._percent=_18;
-if(_16.easing){
-_18=_16.easing(_18);
-}
-_16._fire("onAnimate",[_16.curve.getValue(_18)]);
-if(_16._percent<1){
-_16._startTimer();
-}else{
-_16._active=false;
-if(_16.repeat>0){
-_16.repeat--;
-_16.play(null,true);
-}else{
-if(_16.repeat==-1){
-_16.play(null,true);
-}else{
-if(_16._startRepeatCount){
-_16.repeat=_16._startRepeatCount;
-_16._startRepeatCount=0;
-}
-}
-}
-_16._percent=0;
-_16._fire("onEnd",[_16.node]);
-!_16.repeat&&_16._stopTimer();
-}
-}
-return _16;
-},_clearTimer:function(){
-clearTimeout(this._delayTimer);
-delete this._delayTimer;
-}});
-var ctr=0,_19=[],_1a=null,_1b={run:function(){
-}};
-d.extend(d.Animation,{_startTimer:function(){
-if(!this._timer){
-this._timer=d.connect(_1b,"run",this,"_cycle");
-ctr++;
-}
-if(!_1a){
-_1a=setInterval(d.hitch(_1b,"run"),this.rate);
-}
-},_stopTimer:function(){
-if(this._timer){
-d.disconnect(this._timer);
-this._timer=null;
-ctr--;
-}
-if(ctr<=0){
-clearInterval(_1a);
-_1a=null;
-ctr=0;
-}
-}});
-var _1c=d.isIE?function(_1d){
-var ns=_1d.style;
-if(!ns.width.length&&d.style(_1d,"width")=="auto"){
-ns.width="auto";
-}
-}:function(){
-};
-dojo._fade=function(_1e){
-_1e.node=d.byId(_1e.node);
-var _1f=_1({properties:{}},_1e),_20=(_1f.properties.opacity={});
-_20.start=!("start" in _1f)?function(){
-return +d.style(_1f.node,"opacity")||0;
-}:_1f.start;
-_20.end=_1f.end;
-var _21=d.animateProperty(_1f);
-d.connect(_21,"beforeBegin",d.partial(_1c,_1f.node));
-return _21;
-};
-dojo.fadeIn=function(_22){
-return d._fade(_1({end:1},_22));
-};
-dojo.fadeOut=function(_23){
-return d._fade(_1({end:0},_23));
-};
-dojo._defaultEasing=function(n){
-return 0.5+((Math.sin((n+1.5)*Math.PI))/2);
-};
-var _24=function(_25){
-this._properties=_25;
-for(var p in _25){
-var _26=_25[p];
-if(_26.start instanceof d.Color){
-_26.tempColor=new d.Color();
-}
-}
-};
-_24.prototype.getValue=function(r){
-var ret={};
-for(var p in this._properties){
-var _27=this._properties[p],_28=_27.start;
-if(_28 instanceof d.Color){
-ret[p]=d.blendColors(_28,_27.end,r,_27.tempColor).toCss();
-}else{
-if(!d.isArray(_28)){
-ret[p]=((_27.end-_28)*r)+_28+(p!="opacity"?_27.units||"px":0);
-}
-}
-}
-return ret;
-};
-dojo.animateProperty=function(_29){
-var n=_29.node=d.byId(_29.node);
-if(!_29.easing){
-_29.easing=d._defaultEasing;
-}
-var _2a=new d.Animation(_29);
-d.connect(_2a,"beforeBegin",_2a,function(){
-var pm={};
-for(var p in this.properties){
-if(p=="width"||p=="height"){
-this.node.display="block";
-}
-var _2b=this.properties[p];
-if(d.isFunction(_2b)){
-_2b=_2b(n);
-}
-_2b=pm[p]=_1({},(d.isObject(_2b)?_2b:{end:_2b}));
-if(d.isFunction(_2b.start)){
-_2b.start=_2b.start(n);
-}
-if(d.isFunction(_2b.end)){
-_2b.end=_2b.end(n);
-}
-var _2c=(p.toLowerCase().indexOf("color")>=0);
-function _2d(_2e,p){
-var v={height:_2e.offsetHeight,width:_2e.offsetWidth}[p];
-if(v!==undefined){
-return v;
-}
-v=d.style(_2e,p);
-return (p=="opacity")?+v:(_2c?v:parseFloat(v));
-};
-if(!("end" in _2b)){
-_2b.end=_2d(n,p);
-}else{
-if(!("start" in _2b)){
-_2b.start=_2d(n,p);
-}
-}
-if(_2c){
-_2b.start=new d.Color(_2b.start);
-_2b.end=new d.Color(_2b.end);
-}else{
-_2b.start=(p=="opacity")?+_2b.start:parseFloat(_2b.start);
-}
-}
-this.curve=new _24(pm);
-});
-d.connect(_2a,"onAnimate",d.hitch(d,"style",_2a.node));
-return _2a;
-};
-dojo.anim=function(_2f,_30,_31,_32,_33,_34){
-return d.animateProperty({node:_2f,duration:_31||d.Animation.prototype.duration,properties:_30,easing:_32,onEnd:_33}).play(_34||0);
-};
+	var d = dojo;
+//>>excludeEnd("webkitMobile");
+	var _mixin = d._mixin;
+
+	dojo._Line = function(/*int*/ start, /*int*/ end){
+		//	summary:
+		//		dojo._Line is the object used to generate values from a start value
+		//		to an end value
+		//	start: int
+		//		Beginning value for range
+		//	end: int
+		//		Ending value for range
+		this.start = start;
+		this.end = end;
+	};
+
+	dojo._Line.prototype.getValue = function(/*float*/ n){
+		//	summary: Returns the point on the line
+		//	n: a floating point number greater than 0 and less than 1
+		return ((this.end - this.start) * n) + this.start; // Decimal
+	};
+
+	dojo.Animation = function(args){
+		//	summary:
+		//		A generic animation class that fires callbacks into its handlers
+		//		object at various states.
+		//	description:
+		//		A generic animation class that fires callbacks into its handlers
+		//		object at various states. Nearly all dojo animation functions
+		//		return an instance of this method, usually without calling the
+		//		.play() method beforehand. Therefore, you will likely need to
+		//		call .play() on instances of `dojo.Animation` when one is
+		//		returned.
+		// args: Object
+		//		The 'magic argument', mixing all the properties into this
+		//		animation instance.
+
+		_mixin(this, args);
+		if(d.isArray(this.curve)){
+			this.curve = new d._Line(this.curve[0], this.curve[1]);
+		}
+
+	};
+
+	// Alias to drop come 2.0:
+	d._Animation = d.Animation;
+
+	d.extend(dojo.Animation, {
+		// duration: Integer
+		//		The time in milliseonds the animation will take to run
+		duration: 350,
+
+	/*=====
+		// curve: dojo._Line|Array
+		//		A two element array of start and end values, or a `dojo._Line` instance to be
+		//		used in the Animation.
+		curve: null,
+
+		// easing: Function?
+		//		A Function to adjust the acceleration (or deceleration) of the progress
+		//		across a dojo._Line
+		easing: null,
+	=====*/
+
+		// repeat: Integer?
+		//		The number of times to loop the animation
+		repeat: 0,
+
+		// rate: Integer?
+		//		the time in milliseconds to wait before advancing to next frame
+		//		(used as a fps timer: 1000/rate = fps)
+		rate: 20 /* 50 fps */,
+
+	/*=====
+		// delay: Integer?
+		//		The time in milliseconds to wait before starting animation after it
+		//		has been .play()'ed
+		delay: null,
+
+		// beforeBegin: Event?
+		//		Synthetic event fired before a dojo.Animation begins playing (synchronous)
+		beforeBegin: null,
+
+		// onBegin: Event?
+		//		Synthetic event fired as a dojo.Animation begins playing (useful?)
+		onBegin: null,
+
+		// onAnimate: Event?
+		//		Synthetic event fired at each interval of a `dojo.Animation`
+		onAnimate: null,
+
+		// onEnd: Event?
+		//		Synthetic event fired after the final frame of a `dojo.Animation`
+		onEnd: null,
+
+		// onPlay: Event?
+		//		Synthetic event fired any time a `dojo.Animation` is play()'ed
+		onPlay: null,
+
+		// onPause: Event?
+		//		Synthetic event fired when a `dojo.Animation` is paused
+		onPause: null,
+
+		// onStop: Event
+		//		Synthetic event fires when a `dojo.Animation` is stopped
+		onStop: null,
+
+	=====*/
+
+		_percent: 0,
+		_startRepeatCount: 0,
+
+		_getStep: function(){
+			var _p = this._percent,
+				_e = this.easing
+			;
+			return _e ? _e(_p) : _p;
+		},
+		_fire: function(/*Event*/ evt, /*Array?*/ args){
+			//	summary:
+			//		Convenience function.  Fire event "evt" and pass it the
+			//		arguments specified in "args".
+			//	description:
+			//		Convenience function.  Fire event "evt" and pass it the
+			//		arguments specified in "args".
+			//		Fires the callback in the scope of the `dojo.Animation`
+			//		instance.
+			//	evt:
+			//		The event to fire.
+			//	args:
+			//		The arguments to pass to the event.
+			var a = args||[];
+			if(this[evt]){
+				if(d.config.debugAtAllCosts){
+					this[evt].apply(this, a);
+				}else{
+					try{
+						this[evt].apply(this, a);
+					}catch(e){
+						// squelch and log because we shouldn't allow exceptions in
+						// synthetic event handlers to cause the internal timer to run
+						// amuck, potentially pegging the CPU. I'm not a fan of this
+						// squelch, but hopefully logging will make it clear what's
+						// going on
+						console.error("exception in animation handler for:", evt);
+						console.error(e);
+					}
+				}
+			}
+			return this; // dojo.Animation
+		},
+
+		play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
+			// summary:
+			//		Start the animation.
+			// delay:
+			//		How many milliseconds to delay before starting.
+			// gotoStart:
+			//		If true, starts the animation from the beginning; otherwise,
+			//		starts it from its current position.
+			// returns: dojo.Animation
+			//		The instance to allow chaining.
+
+			var _t = this;
+			if(_t._delayTimer){ _t._clearTimer(); }
+			if(gotoStart){
+				_t._stopTimer();
+				_t._active = _t._paused = false;
+				_t._percent = 0;
+			}else if(_t._active && !_t._paused){
+				return _t;
+			}
+
+			_t._fire("beforeBegin", [_t.node]);
+
+			var de = delay || _t.delay,
+				_p = dojo.hitch(_t, "_play", gotoStart);
+
+			if(de > 0){
+				_t._delayTimer = setTimeout(_p, de);
+				return _t;
+			}
+			_p();
+			return _t;
+		},
+
+		_play: function(gotoStart){
+			var _t = this;
+			if(_t._delayTimer){ _t._clearTimer(); }
+			_t._startTime = new Date().valueOf();
+			if(_t._paused){
+				_t._startTime -= _t.duration * _t._percent;
+			}
+
+			_t._active = true;
+			_t._paused = false;
+			var value = _t.curve.getValue(_t._getStep());
+			if(!_t._percent){
+				if(!_t._startRepeatCount){
+					_t._startRepeatCount = _t.repeat;
+				}
+				_t._fire("onBegin", [value]);
+			}
+
+			_t._fire("onPlay", [value]);
+
+			_t._cycle();
+			return _t; // dojo.Animation
+		},
+
+		pause: function(){
+			// summary: Pauses a running animation.
+			var _t = this;
+			if(_t._delayTimer){ _t._clearTimer(); }
+			_t._stopTimer();
+			if(!_t._active){ return _t; /*dojo.Animation*/ }
+			_t._paused = true;
+			_t._fire("onPause", [_t.curve.getValue(_t._getStep())]);
+			return _t; // dojo.Animation
+		},
+
+		gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay){
+			//	summary:
+			//		Sets the progress of the animation.
+			//	percent:
+			//		A percentage in decimal notation (between and including 0.0 and 1.0).
+			//	andPlay:
+			//		If true, play the animation after setting the progress.
+			var _t = this;
+			_t._stopTimer();
+			_t._active = _t._paused = true;
+			_t._percent = percent;
+			if(andPlay){ _t.play(); }
+			return _t; // dojo.Animation
+		},
+
+		stop: function(/*boolean?*/ gotoEnd){
+			// summary: Stops a running animation.
+			// gotoEnd: If true, the animation will end.
+			var _t = this;
+			if(_t._delayTimer){ _t._clearTimer(); }
+			if(!_t._timer){ return _t; /* dojo.Animation */ }
+			_t._stopTimer();
+			if(gotoEnd){
+				_t._percent = 1;
+			}
+			_t._fire("onStop", [_t.curve.getValue(_t._getStep())]);
+			_t._active = _t._paused = false;
+			return _t; // dojo.Animation
+		},
+
+		status: function(){
+			// summary:
+			//		Returns a string token representation of the status of
+			//		the animation, one of: "paused", "playing", "stopped"
+			if(this._active){
+				return this._paused ? "paused" : "playing"; // String
+			}
+			return "stopped"; // String
+		},
+
+		_cycle: function(){
+			var _t = this;
+			if(_t._active){
+				var curr = new Date().valueOf();
+				var step = (curr - _t._startTime) / (_t.duration);
+
+				if(step >= 1){
+					step = 1;
+				}
+				_t._percent = step;
+
+				// Perform easing
+				if(_t.easing){
+					step = _t.easing(step);
+				}
+
+				_t._fire("onAnimate", [_t.curve.getValue(step)]);
+
+				if(_t._percent < 1){
+					_t._startTimer();
+				}else{
+					_t._active = false;
+
+					if(_t.repeat > 0){
+						_t.repeat--;
+						_t.play(null, true);
+					}else if(_t.repeat == -1){
+						_t.play(null, true);
+					}else{
+						if(_t._startRepeatCount){
+							_t.repeat = _t._startRepeatCount;
+							_t._startRepeatCount = 0;
+						}
+					}
+					_t._percent = 0;
+					_t._fire("onEnd", [_t.node]);
+					!_t.repeat && _t._stopTimer();
+				}
+			}
+			return _t; // dojo.Animation
+		},
+
+		_clearTimer: function(){
+			// summary: Clear the play delay timer
+			clearTimeout(this._delayTimer);
+			delete this._delayTimer;
+		}
+
+	});
+
+	// the local timer, stubbed into all Animation instances
+	var ctr = 0,
+		timer = null,
+		runner = {
+			run: function(){}
+		};
+
+	d.extend(d.Animation, {
+
+		_startTimer: function(){
+			if(!this._timer){
+				this._timer = d.connect(runner, "run", this, "_cycle");
+				ctr++;
+			}
+			if(!timer){
+				timer = setInterval(d.hitch(runner, "run"), this.rate);
+			}
+		},
+
+		_stopTimer: function(){
+			if(this._timer){
+				d.disconnect(this._timer);
+				this._timer = null;
+				ctr--;
+			}
+			if(ctr <= 0){
+				clearInterval(timer);
+				timer = null;
+				ctr = 0;
+			}
+		}
+
+	});
+
+	var _makeFadeable =
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		d.isIE ? function(node){
+			// only set the zoom if the "tickle" value would be the same as the
+			// default
+			var ns = node.style;
+			// don't set the width to auto if it didn't already cascade that way.
+			// We don't want to f anyones designs
+			if(!ns.width.length && d.style(node, "width") == "auto"){
+				ns.width = "auto";
+			}
+		} :
+		//>>excludeEnd("webkitMobile");
+		function(){};
+
+	dojo._fade = function(/*Object*/ args){
+		//	summary:
+		//		Returns an animation that will fade the node defined by
+		//		args.node from the start to end values passed (args.start
+		//		args.end) (end is mandatory, start is optional)
+
+		args.node = d.byId(args.node);
+		var fArgs = _mixin({ properties: {} }, args),
+			props = (fArgs.properties.opacity = {});
+
+		props.start = !("start" in fArgs) ?
+			function(){
+				return +d.style(fArgs.node, "opacity")||0;
+			} : fArgs.start;
+		props.end = fArgs.end;
+
+		var anim = d.animateProperty(fArgs);
+		d.connect(anim, "beforeBegin", d.partial(_makeFadeable, fArgs.node));
+
+		return anim; // dojo.Animation
+	};
+
+	/*=====
+	dojo.__FadeArgs = function(node, duration, easing){
+		//	node: DOMNode|String
+		//		The node referenced in the animation
+		//	duration: Integer?
+		//		Duration of the animation in milliseconds.
+		//	easing: Function?
+		//		An easing function.
+		this.node = node;
+		this.duration = duration;
+		this.easing = easing;
+	}
+	=====*/
+
+	dojo.fadeIn = function(/*dojo.__FadeArgs*/ args){
+		// summary:
+		//		Returns an animation that will fade node defined in 'args' from
+		//		its current opacity to fully opaque.
+		return d._fade(_mixin({ end: 1 }, args)); // dojo.Animation
+	};
+
+	dojo.fadeOut = function(/*dojo.__FadeArgs*/  args){
+		// summary:
+		//		Returns an animation that will fade node defined in 'args'
+		//		from its current opacity to fully transparent.
+		return d._fade(_mixin({ end: 0 }, args)); // dojo.Animation
+	};
+
+	dojo._defaultEasing = function(/*Decimal?*/ n){
+		// summary: The default easing function for dojo.Animation(s)
+		return 0.5 + ((Math.sin((n + 1.5) * Math.PI)) / 2);
+	};
+
+	var PropLine = function(properties){
+		// PropLine is an internal class which is used to model the values of
+		// an a group of CSS properties across an animation lifecycle. In
+		// particular, the "getValue" function handles getting interpolated
+		// values between start and end for a particular CSS value.
+		this._properties = properties;
+		for(var p in properties){
+			var prop = properties[p];
+			if(prop.start instanceof d.Color){
+				// create a reusable temp color object to keep intermediate results
+				prop.tempColor = new d.Color();
+			}
+		}
+	};
+
+	PropLine.prototype.getValue = function(r){
+		var ret = {};
+		for(var p in this._properties){
+			var prop = this._properties[p],
+				start = prop.start;
+			if(start instanceof d.Color){
+				ret[p] = d.blendColors(start, prop.end, r, prop.tempColor).toCss();
+			}else if(!d.isArray(start)){
+				ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units || "px" : 0);
+			}
+		}
+		return ret;
+	};
+
+	/*=====
+	dojo.declare("dojo.__AnimArgs", [dojo.__FadeArgs], {
+		// Properties: Object?
+		//	A hash map of style properties to Objects describing the transition,
+		//	such as the properties of dojo._Line with an additional 'units' property
+		properties: {}
+
+		//TODOC: add event callbacks
+	});
+	=====*/
+
+	dojo.animateProperty = function(/*dojo.__AnimArgs*/ args){
+		// summary:
+		//		Returns an animation that will transition the properties of
+		//		node defined in `args` depending how they are defined in
+		//		`args.properties`
+		//
+		// description:
+		//		`dojo.animateProperty` is the foundation of most `dojo.fx`
+		//		animations. It takes an object of "properties" corresponding to
+		//		style properties, and animates them in parallel over a set
+		//		duration.
+		//
+		// example:
+		//		A simple animation that changes the width of the specified node.
+		//	|	dojo.animateProperty({
+		//	|		node: "nodeId",
+		//	|		properties: { width: 400 },
+		//	|	}).play();
+		//		Dojo figures out the start value for the width and converts the
+		//		integer specified for the width to the more expressive but
+		//		verbose form `{ width: { end: '400', units: 'px' } }` which you
+		//		can also specify directly. Defaults to 'px' if ommitted.
+		//
+		// example:
+		//		Animate width, height, and padding over 2 seconds... the
+		//		pedantic way:
+		//	|	dojo.animateProperty({ node: node, duration:2000,
+		//	|		properties: {
+		//	|			width: { start: '200', end: '400', units:"px" },
+		//	|			height: { start:'200', end: '400', units:"px" },
+		//	|			paddingTop: { start:'5', end:'50', units:"px" }
+		//	|		}
+		//	|	}).play();
+		//		Note 'paddingTop' is used over 'padding-top'. Multi-name CSS properties
+		//		are written using "mixed case", as the hyphen is illegal as an object key.
+		//
+		// example:
+		//		Plug in a different easing function and register a callback for
+		//		when the animation ends. Easing functions accept values between
+		//		zero and one and return a value on that basis. In this case, an
+		//		exponential-in curve.
+		//	|	dojo.animateProperty({
+		//	|		node: "nodeId",
+		//	|		// dojo figures out the start value
+		//	|		properties: { width: { end: 400 } },
+		//	|		easing: function(n){
+		//	|			return (n==0) ? 0 : Math.pow(2, 10 * (n - 1));
+		//	|		},
+		//	|		onEnd: function(node){
+		//	|			// called when the animation finishes. The animation
+		//	|			// target is passed to this function
+		//	|		}
+		//	|	}).play(500); // delay playing half a second
+		//
+		// example:
+		//		Like all `dojo.Animation`s, animateProperty returns a handle to the
+		//		Animation instance, which fires the events common to Dojo FX. Use `dojo.connect`
+		//		to access these events outside of the Animation definiton:
+		//	|	var anim = dojo.animateProperty({
+		//	|		node:"someId",
+		//	|		properties:{
+		//	|			width:400, height:500
+		//	|		}
+		//	|	});
+		//	|	dojo.connect(anim,"onEnd", function(){
+		//	|		console.log("animation ended");
+		//	|	});
+		//	|	// play the animation now:
+		//	|	anim.play();
+		//
+		// example:
+		//		Each property can be a function whose return value is substituted along.
+		//		Additionally, each measurement (eg: start, end) can be a function. The node
+		//		reference is passed direcly to callbacks.
+		//	|	dojo.animateProperty({
+		//	|		node:"mine",
+		//	|		properties:{
+		//	|			height:function(node){
+		//	|				// shrink this node by 50%
+		//	|				return dojo.position(node).h / 2
+		//	|			},
+		//	|			width:{
+		//	|				start:function(node){ return 100; },
+		//	|				end:function(node){ return 200; }
+		//	|			}
+		//	|		}
+		//	|	}).play();
+		//
+
+		var n = args.node = d.byId(args.node);
+		if(!args.easing){ args.easing = d._defaultEasing; }
+
+		var anim = new d.Animation(args);
+		d.connect(anim, "beforeBegin", anim, function(){
+			var pm = {};
+			for(var p in this.properties){
+				// Make shallow copy of properties into pm because we overwrite
+				// some values below. In particular if start/end are functions
+				// we don't want to overwrite them or the functions won't be
+				// called if the animation is reused.
+				if(p == "width" || p == "height"){
+					this.node.display = "block";
+				}
+				var prop = this.properties[p];
+				if(d.isFunction(prop)){
+					prop = prop(n);
+				}
+				prop = pm[p] = _mixin({}, (d.isObject(prop) ? prop: { end: prop }));
+
+				if(d.isFunction(prop.start)){
+					prop.start = prop.start(n);
+				}
+				if(d.isFunction(prop.end)){
+					prop.end = prop.end(n);
+				}
+				var isColor = (p.toLowerCase().indexOf("color") >= 0);
+				function getStyle(node, p){
+					// dojo.style(node, "height") can return "auto" or "" on IE; this is more reliable:
+					var v = { height: node.offsetHeight, width: node.offsetWidth }[p];
+					if(v !== undefined){ return v; }
+					v = d.style(node, p);
+					return (p == "opacity") ? +v : (isColor ? v : parseFloat(v));
+				}
+				if(!("end" in prop)){
+					prop.end = getStyle(n, p);
+				}else if(!("start" in prop)){
+					prop.start = getStyle(n, p);
+				}
+
+				if(isColor){
+					prop.start = new d.Color(prop.start);
+					prop.end = new d.Color(prop.end);
+				}else{
+					prop.start = (p == "opacity") ? +prop.start : parseFloat(prop.start);
+				}
+			}
+			this.curve = new PropLine(pm);
+		});
+		d.connect(anim, "onAnimate", d.hitch(d, "style", anim.node));
+		return anim; // dojo.Animation
+	};
+
+	dojo.anim = function(	/*DOMNode|String*/	node,
+							/*Object*/			properties,
+							/*Integer?*/		duration,
+							/*Function?*/		easing,
+							/*Function?*/		onEnd,
+							/*Integer?*/		delay){
+		//	summary:
+		//		A simpler interface to `dojo.animateProperty()`, also returns
+		//		an instance of `dojo.Animation` but begins the animation
+		//		immediately, unlike nearly every other Dojo animation API.
+		//	description:
+		//		`dojo.anim` is a simpler (but somewhat less powerful) version
+		//		of `dojo.animateProperty`.  It uses defaults for many basic properties
+		//		and allows for positional parameters to be used in place of the
+		//		packed "property bag" which is used for other Dojo animation
+		//		methods.
+		//
+		//		The `dojo.Animation` object returned from `dojo.anim` will be
+		//		already playing when it is returned from this function, so
+		//		calling play() on it again is (usually) a no-op.
+		//	node:
+		//		a DOM node or the id of a node to animate CSS properties on
+		//	duration:
+		//		The number of milliseconds over which the animation
+		//		should run. Defaults to the global animation default duration
+		//		(350ms).
+		//	easing:
+		//		An easing function over which to calculate acceleration
+		//		and deceleration of the animation through its duration.
+		//		A default easing algorithm is provided, but you may
+		//		plug in any you wish. A large selection of easing algorithms
+		//		are available in `dojo.fx.easing`.
+		//	onEnd:
+		//		A function to be called when the animation finishes
+		//		running.
+		//	delay:
+		//		The number of milliseconds to delay beginning the
+		//		animation by. The default is 0.
+		//	example:
+		//		Fade out a node
+		//	|	dojo.anim("id", { opacity: 0 });
+		//	example:
+		//		Fade out a node over a full second
+		//	|	dojo.anim("id", { opacity: 0 }, 1000);
+		return d.animateProperty({ // dojo.Animation
+			node: node,
+			duration: duration || d.Animation.prototype.duration,
+			properties: properties,
+			easing: easing,
+			onEnd: onEnd
+		}).play(delay || 0);
+	};
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 })();
-}
+//>>excludeEnd("webkitMobile");
diff --git a/dojo/_base/html.js b/dojo/_base/html.js
index 2b1aca0..1542fe2 100644
--- a/dojo/_base/html.js
+++ b/dojo/_base/html.js
@@ -1,742 +1,1879 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.html"]){
-dojo._hasResource["dojo._base.html"]=true;
 dojo.require("dojo._base.lang");
 dojo.provide("dojo._base.html");
+
+// FIXME: need to add unit tests for all the semi-public methods
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 try{
-document.execCommand("BackgroundImageCache",false,true);
-}
-catch(e){
-}
-if(dojo.isIE||dojo.isOpera){
-dojo.byId=function(id,_1){
-if(typeof id!="string"){
-return id;
-}
-var _2=_1||dojo.doc,te=_2.getElementById(id);
-if(te&&(te.attributes.id.value==id||te.id==id)){
-return te;
-}else{
-var _3=_2.all[id];
-if(!_3||_3.nodeName){
-_3=[_3];
-}
-var i=0;
-while((te=_3[i++])){
-if((te.attributes&&te.attributes.id&&te.attributes.id.value==id)||te.id==id){
-return te;
-}
-}
+	document.execCommand("BackgroundImageCache", false, true);
+}catch(e){
+	// sane browsers don't have cache "issues"
 }
-};
+//>>excludeEnd("webkitMobile");
+
+// =============================
+// DOM Functions
+// =============================
+
+/*=====
+dojo.byId = function(id, doc){
+	//	summary:
+	//		Returns DOM node with matching `id` attribute or `null`
+	//		if not found. If `id` is a DomNode, this function is a no-op.
+	//
+	//	id: String|DOMNode
+	//	 	A string to match an HTML id attribute or a reference to a DOM Node
+	//
+	//	doc: Document?
+	//		Document to work in. Defaults to the current value of
+	//		dojo.doc.  Can be used to retrieve
+	//		node references from other documents.
+	//
+	//	example:
+	//	Look up a node by ID:
+	//	|	var n = dojo.byId("foo");
+	//
+	//	example:
+	//	Check if a node exists, and use it.
+	//	|	var n = dojo.byId("bar");
+	//	|	if(n){ doStuff() ... }
+	//
+	//	example:
+	//	Allow string or DomNode references to be passed to a custom function:
+	//	|	var foo = function(nodeOrId){
+	//	|		nodeOrId = dojo.byId(nodeOrId);
+	//	|		// ... more stuff
+	//	|	}
+=====*/
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+if(dojo.isIE || dojo.isOpera){
+	dojo.byId = function(id, doc){
+		if(typeof id != "string"){
+			return id;
+		}
+		var _d = doc || dojo.doc, te = _d.getElementById(id);
+		// attributes.id.value is better than just id in case the 
+		// user has a name=id inside a form
+		if(te && (te.attributes.id.value == id || te.id == id)){
+			return te;
+		}else{
+			var eles = _d.all[id];
+			if(!eles || eles.nodeName){
+				eles = [eles];
+			}
+			// if more than 1, choose first with the correct id
+			var i=0;
+			while((te=eles[i++])){
+				if((te.attributes && te.attributes.id && te.attributes.id.value == id)
+					|| te.id == id){
+					return te;
+				}
+			}
+		}
+	};
 }else{
-dojo.byId=function(id,_4){
-return (typeof id=="string")?(_4||dojo.doc).getElementById(id):id;
+//>>excludeEnd("webkitMobile");
+	dojo.byId = function(id, doc){
+		// inline'd type check
+		return (typeof id == "string") ? (doc || dojo.doc).getElementById(id) : id; // DomNode
+	};
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+}
+//>>excludeEnd("webkitMobile");
+/*=====
 };
-}
+=====*/
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 (function(){
-var d=dojo;
-var _5=d.byId;
-var _6=null,_7;
-d.addOnWindowUnload(function(){
-_6=null;
-});
-dojo._destroyElement=dojo.destroy=function(_8){
-_8=_5(_8);
-try{
-var _9=_8.ownerDocument;
-if(!_6||_7!=_9){
-_6=_9.createElement("div");
-_7=_9;
-}
-_6.appendChild(_8.parentNode?_8.parentNode.removeChild(_8):_8);
-_6.innerHTML="";
-}
-catch(e){
-}
-};
-dojo.isDescendant=function(_a,_b){
-try{
-_a=_5(_a);
-_b=_5(_b);
-while(_a){
-if(_a==_b){
-return true;
-}
-_a=_a.parentNode;
-}
-}
-catch(e){
-}
-return false;
-};
-dojo.setSelectable=function(_c,_d){
-_c=_5(_c);
-if(d.isMozilla){
-_c.style.MozUserSelect=_d?"":"none";
-}else{
-if(d.isKhtml||d.isWebKit){
-_c.style.KhtmlUserSelect=_d?"auto":"none";
-}else{
-if(d.isIE){
-var v=(_c.unselectable=_d?"":"on");
-d.query("*",_c).forEach("item.unselectable = '"+v+"'");
-}
-}
-}
-};
-var _e=function(_f,ref){
-var _10=ref.parentNode;
-if(_10){
-_10.insertBefore(_f,ref);
-}
-};
-var _11=function(_12,ref){
-var _13=ref.parentNode;
-if(_13){
-if(_13.lastChild==ref){
-_13.appendChild(_12);
-}else{
-_13.insertBefore(_12,ref.nextSibling);
-}
-}
-};
-dojo.place=function(_14,_15,_16){
-_15=_5(_15);
-if(typeof _14=="string"){
-_14=_14.charAt(0)=="<"?d._toDom(_14,_15.ownerDocument):_5(_14);
-}
-if(typeof _16=="number"){
-var cn=_15.childNodes;
-if(!cn.length||cn.length<=_16){
-_15.appendChild(_14);
-}else{
-_e(_14,cn[_16<0?0:_16]);
-}
-}else{
-switch(_16){
-case "before":
-_e(_14,_15);
-break;
-case "after":
-_11(_14,_15);
-break;
-case "replace":
-_15.parentNode.replaceChild(_14,_15);
-break;
-case "only":
-d.empty(_15);
-_15.appendChild(_14);
-break;
-case "first":
-if(_15.firstChild){
-_e(_14,_15.firstChild);
-break;
-}
-default:
-_15.appendChild(_14);
-}
-}
-return _14;
-};
-dojo.boxModel="content-box";
-if(d.isIE){
-d.boxModel=document.compatMode=="BackCompat"?"border-box":"content-box";
-}
-var gcs;
-if(d.isWebKit){
-gcs=function(_17){
-var s;
-if(_17.nodeType==1){
-var dv=_17.ownerDocument.defaultView;
-s=dv.getComputedStyle(_17,null);
-if(!s&&_17.style){
-_17.style.display="";
-s=dv.getComputedStyle(_17,null);
-}
-}
-return s||{};
-};
-}else{
-if(d.isIE){
-gcs=function(_18){
-return _18.nodeType==1?_18.currentStyle:{};
-};
-}else{
-gcs=function(_19){
-return _19.nodeType==1?_19.ownerDocument.defaultView.getComputedStyle(_19,null):{};
-};
-}
-}
-dojo.getComputedStyle=gcs;
-if(!d.isIE){
-d._toPixelValue=function(_1a,_1b){
-return parseFloat(_1b)||0;
-};
-}else{
-d._toPixelValue=function(_1c,_1d){
-if(!_1d){
-return 0;
-}
-if(_1d=="medium"){
-return 4;
-}
-if(_1d.slice&&_1d.slice(-2)=="px"){
-return parseFloat(_1d);
-}
-with(_1c){
-var _1e=style.left;
-var _1f=runtimeStyle.left;
-runtimeStyle.left=currentStyle.left;
-try{
-style.left=_1d;
-_1d=style.pixelLeft;
-}
-catch(e){
-_1d=0;
-}
-style.left=_1e;
-runtimeStyle.left=_1f;
-}
-return _1d;
-};
-}
-var px=d._toPixelValue;
-var _20="DXImageTransform.Microsoft.Alpha";
-var af=function(n,f){
-try{
-return n.filters.item(_20);
-}
-catch(e){
-return f?{}:null;
-}
-};
-dojo._getOpacity=d.isIE?function(_21){
-try{
-return af(_21).Opacity/100;
-}
-catch(e){
-return 1;
-}
-}:function(_22){
-return gcs(_22).opacity;
-};
-dojo._setOpacity=d.isIE?function(_23,_24){
-var ov=_24*100;
-_23.style.zoom=1;
-af(_23,1).Enabled=!(_24==1);
-if(!af(_23)){
-_23.style.filter+=" progid:"+_20+"(Opacity="+ov+")";
-}else{
-af(_23,1).Opacity=ov;
-}
-if(_23.nodeName.toLowerCase()=="tr"){
-d.query("> td",_23).forEach(function(i){
-d._setOpacity(i,_24);
-});
-}
-return _24;
-}:function(_25,_26){
-return _25.style.opacity=_26;
-};
-var _27={left:true,top:true};
-var _28=/margin|padding|width|height|max|min|offset/;
-var _29=function(_2a,_2b,_2c){
-_2b=_2b.toLowerCase();
-if(d.isIE){
-if(_2c=="auto"){
-if(_2b=="height"){
-return _2a.offsetHeight;
-}
-if(_2b=="width"){
-return _2a.offsetWidth;
-}
-}
-if(_2b=="fontweight"){
-switch(_2c){
-case 700:
-return "bold";
-case 400:
-default:
-return "normal";
-}
-}
-}
-if(!(_2b in _27)){
-_27[_2b]=_28.test(_2b);
-}
-return _27[_2b]?px(_2a,_2c):_2c;
-};
-var _2d=d.isIE?"styleFloat":"cssFloat",_2e={"cssFloat":_2d,"styleFloat":_2d,"float":_2d};
-dojo.style=function(_2f,_30,_31){
-var n=_5(_2f),_32=arguments.length,op=(_30=="opacity");
-_30=_2e[_30]||_30;
-if(_32==3){
-return op?d._setOpacity(n,_31):n.style[_30]=_31;
-}
-if(_32==2&&op){
-return d._getOpacity(n);
-}
-var s=gcs(n);
-if(_32==2&&typeof _30!="string"){
-for(var x in _30){
-d.style(_2f,x,_30[x]);
-}
-return s;
-}
-return (_32==1)?s:_29(n,_30,s[_30]||n.style[_30]);
-};
-dojo._getPadExtents=function(n,_33){
-var s=_33||gcs(n),l=px(n,s.paddingLeft),t=px(n,s.paddingTop);
-return {l:l,t:t,w:l+px(n,s.paddingRight),h:t+px(n,s.paddingBottom)};
-};
-dojo._getBorderExtents=function(n,_34){
-var ne="none",s=_34||gcs(n),bl=(s.borderLeftStyle!=ne?px(n,s.borderLeftWidth):0),bt=(s.borderTopStyle!=ne?px(n,s.borderTopWidth):0);
-return {l:bl,t:bt,w:bl+(s.borderRightStyle!=ne?px(n,s.borderRightWidth):0),h:bt+(s.borderBottomStyle!=ne?px(n,s.borderBottomWidth):0)};
-};
-dojo._getPadBorderExtents=function(n,_35){
-var s=_35||gcs(n),p=d._getPadExtents(n,s),b=d._getBorderExtents(n,s);
-return {l:p.l+b.l,t:p.t+b.t,w:p.w+b.w,h:p.h+b.h};
-};
-dojo._getMarginExtents=function(n,_36){
-var s=_36||gcs(n),l=px(n,s.marginLeft),t=px(n,s.marginTop),r=px(n,s.marginRight),b=px(n,s.marginBottom);
-if(d.isWebKit&&(s.position!="absolute")){
-r=l;
-}
-return {l:l,t:t,w:l+r,h:t+b};
-};
-dojo._getMarginBox=function(_37,_38){
-var s=_38||gcs(_37),me=d._getMarginExtents(_37,s);
-var l=_37.offsetLeft-me.l,t=_37.offsetTop-me.t,p=_37.parentNode;
-if(d.isMoz){
-var sl=parseFloat(s.left),st=parseFloat(s.top);
-if(!isNaN(sl)&&!isNaN(st)){
-l=sl,t=st;
-}else{
-if(p&&p.style){
-var pcs=gcs(p);
-if(pcs.overflow!="visible"){
-var be=d._getBorderExtents(p,pcs);
-l+=be.l,t+=be.t;
-}
-}
-}
-}else{
-if(d.isOpera||(d.isIE>7&&!d.isQuirks)){
-if(p){
-be=d._getBorderExtents(p);
-l-=be.l;
-t-=be.t;
-}
-}
-}
-return {l:l,t:t,w:_37.offsetWidth+me.w,h:_37.offsetHeight+me.h};
-};
-dojo._getContentBox=function(_39,_3a){
-var s=_3a||gcs(_39),pe=d._getPadExtents(_39,s),be=d._getBorderExtents(_39,s),w=_39.clientWidth,h;
-if(!w){
-w=_39.offsetWidth,h=_39.offsetHeight;
-}else{
-h=_39.clientHeight,be.w=be.h=0;
-}
-if(d.isOpera){
-pe.l+=be.l;
-pe.t+=be.t;
-}
-return {l:pe.l,t:pe.t,w:w-pe.w-be.w,h:h-pe.h-be.h};
-};
-dojo._getBorderBox=function(_3b,_3c){
-var s=_3c||gcs(_3b),pe=d._getPadExtents(_3b,s),cb=d._getContentBox(_3b,s);
-return {l:cb.l-pe.l,t:cb.t-pe.t,w:cb.w+pe.w,h:cb.h+pe.h};
-};
-dojo._setBox=function(_3d,l,t,w,h,u){
-u=u||"px";
-var s=_3d.style;
-if(!isNaN(l)){
-s.left=l+u;
-}
-if(!isNaN(t)){
-s.top=t+u;
-}
-if(w>=0){
-s.width=w+u;
-}
-if(h>=0){
-s.height=h+u;
-}
-};
-dojo._isButtonTag=function(_3e){
-return _3e.tagName=="BUTTON"||_3e.tagName=="INPUT"&&(_3e.getAttribute("type")||"").toUpperCase()=="BUTTON";
-};
-dojo._usesBorderBox=function(_3f){
-var n=_3f.tagName;
-return d.boxModel=="border-box"||n=="TABLE"||d._isButtonTag(_3f);
-};
-dojo._setContentSize=function(_40,_41,_42,_43){
-if(d._usesBorderBox(_40)){
-var pb=d._getPadBorderExtents(_40,_43);
-if(_41>=0){
-_41+=pb.w;
-}
-if(_42>=0){
-_42+=pb.h;
-}
-}
-d._setBox(_40,NaN,NaN,_41,_42);
-};
-dojo._setMarginBox=function(_44,_45,_46,_47,_48,_49){
-var s=_49||gcs(_44),bb=d._usesBorderBox(_44),pb=bb?_4a:d._getPadBorderExtents(_44,s);
-if(d.isWebKit){
-if(d._isButtonTag(_44)){
-var ns=_44.style;
-if(_47>=0&&!ns.width){
-ns.width="4px";
-}
-if(_48>=0&&!ns.height){
-ns.height="4px";
-}
-}
-}
-var mb=d._getMarginExtents(_44,s);
-if(_47>=0){
-_47=Math.max(_47-pb.w-mb.w,0);
-}
-if(_48>=0){
-_48=Math.max(_48-pb.h-mb.h,0);
-}
-d._setBox(_44,_45,_46,_47,_48);
-};
-var _4a={l:0,t:0,w:0,h:0};
-dojo.marginBox=function(_4b,box){
-var n=_5(_4b),s=gcs(n),b=box;
-return !b?d._getMarginBox(n,s):d._setMarginBox(n,b.l,b.t,b.w,b.h,s);
-};
-dojo.contentBox=function(_4c,box){
-var n=_5(_4c),s=gcs(n),b=box;
-return !b?d._getContentBox(n,s):d._setContentSize(n,b.w,b.h,s);
-};
-var _4d=function(_4e,_4f){
-if(!(_4e=(_4e||0).parentNode)){
-return 0;
-}
-var val,_50=0,_51=d.body();
-while(_4e&&_4e.style){
-if(gcs(_4e).position=="fixed"){
-return 0;
-}
-val=_4e[_4f];
-if(val){
-_50+=val-0;
-if(_4e==_51){
-break;
-}
-}
-_4e=_4e.parentNode;
-}
-return _50;
-};
-dojo._docScroll=function(){
-var n=d.global;
-return "pageXOffset" in n?{x:n.pageXOffset,y:n.pageYOffset}:(n=d.doc.documentElement,n.clientHeight?{x:d._fixIeBiDiScrollLeft(n.scrollLeft),y:n.scrollTop}:(n=d.body(),{x:n.scrollLeft||0,y:n.scrollTop||0}));
-};
-dojo._isBodyLtr=function(){
-return "_bodyLtr" in d?d._bodyLtr:d._bodyLtr=(d.body().dir||d.doc.documentElement.dir||"ltr").toLowerCase()=="ltr";
-};
-dojo._getIeDocumentElementOffset=function(){
-var de=d.doc.documentElement;
-if(d.isIE<8){
-var r=de.getBoundingClientRect();
-var l=r.left,t=r.top;
-if(d.isIE<7){
-l+=de.clientLeft;
-t+=de.clientTop;
-}
-return {x:l<0?0:l,y:t<0?0:t};
-}else{
-return {x:0,y:0};
-}
-};
-dojo._fixIeBiDiScrollLeft=function(_52){
-var dd=d.doc;
-if(d.isIE<8&&!d._isBodyLtr()){
-var de=d.isQuirks?dd.body:dd.documentElement;
-return _52+de.clientWidth-de.scrollWidth;
-}
-return _52;
-};
-dojo._abs=dojo.position=function(_53,_54){
-var db=d.body(),dh=db.parentNode,ret;
-_53=_5(_53);
-if(_53["getBoundingClientRect"]){
-ret=_53.getBoundingClientRect();
-ret={x:ret.left,y:ret.top,w:ret.right-ret.left,h:ret.bottom-ret.top};
-if(d.isIE){
-var _55=d._getIeDocumentElementOffset();
-ret.x-=_55.x+(d.isQuirks?db.clientLeft+db.offsetLeft:0);
-ret.y-=_55.y+(d.isQuirks?db.clientTop+db.offsetTop:0);
-}else{
-if(d.isFF==3){
-var cs=gcs(dh);
-ret.x-=px(dh,cs.marginLeft)+px(dh,cs.borderLeftWidth);
-ret.y-=px(dh,cs.marginTop)+px(dh,cs.borderTopWidth);
-}
-}
-}else{
-ret={x:0,y:0,w:_53.offsetWidth,h:_53.offsetHeight};
-if(_53["offsetParent"]){
-ret.x-=_4d(_53,"scrollLeft");
-ret.y-=_4d(_53,"scrollTop");
-var _56=_53;
-do{
-var n=_56.offsetLeft,t=_56.offsetTop;
-ret.x+=isNaN(n)?0:n;
-ret.y+=isNaN(t)?0:t;
-cs=gcs(_56);
-if(_56!=_53){
-if(d.isMoz){
-ret.x+=2*px(_56,cs.borderLeftWidth);
-ret.y+=2*px(_56,cs.borderTopWidth);
-}else{
-ret.x+=px(_56,cs.borderLeftWidth);
-ret.y+=px(_56,cs.borderTopWidth);
-}
-}
-if(d.isMoz&&cs.position=="static"){
-var _57=_56.parentNode;
-while(_57!=_56.offsetParent){
-var pcs=gcs(_57);
-if(pcs.position=="static"){
-ret.x+=px(_56,pcs.borderLeftWidth);
-ret.y+=px(_56,pcs.borderTopWidth);
-}
-_57=_57.parentNode;
-}
-}
-_56=_56.offsetParent;
-}while((_56!=dh)&&_56);
-}else{
-if(_53.x&&_53.y){
-ret.x+=isNaN(_53.x)?0:_53.x;
-ret.y+=isNaN(_53.y)?0:_53.y;
-}
-}
-}
-if(_54){
-var _58=d._docScroll();
-ret.x+=_58.x;
-ret.y+=_58.y;
-}
-return ret;
-};
-dojo.coords=function(_59,_5a){
-var n=_5(_59),s=gcs(n),mb=d._getMarginBox(n,s);
-var abs=d.position(n,_5a);
-mb.x=abs.x;
-mb.y=abs.y;
-return mb;
-};
-var _5b={"class":"className","for":"htmlFor",tabindex:"tabIndex",readonly:"readOnly",colspan:"colSpan",frameborder:"frameBorder",rowspan:"rowSpan",valuetype:"valueType"},_5c={classname:"class",htmlfor:"for",tabindex:"tabIndex",readonly:"readOnly"},_5d={innerHTML:1,className:1,htmlFor:d.isIE,value:1};
-var _5e=function(_5f){
-return _5c[_5f.toLowerCase()]||_5f;
-};
-var _60=function(_61,_62){
-var _63=_61.getAttributeNode&&_61.getAttributeNode(_62);
-return _63&&_63.specified;
-};
-dojo.hasAttr=function(_64,_65){
-var lc=_65.toLowerCase();
-return _5d[_5b[lc]||_65]||_60(_5(_64),_5c[lc]||_65);
-};
-var _66={},_67=0,_68=dojo._scopeName+"attrid",_69={col:1,colgroup:1,table:1,tbody:1,tfoot:1,thead:1,tr:1,title:1};
-dojo.attr=function(_6a,_6b,_6c){
-_6a=_5(_6a);
-var _6d=arguments.length,_6e;
-if(_6d==2&&typeof _6b!="string"){
-for(var x in _6b){
-d.attr(_6a,x,_6b[x]);
-}
-return _6a;
-}
-var lc=_6b.toLowerCase(),_6f=_5b[lc]||_6b,_70=_5d[_6f],_71=_5c[lc]||_6b;
-if(_6d==3){
-do{
-if(_6f=="style"&&typeof _6c!="string"){
-d.style(_6a,_6c);
-break;
-}
-if(_6f=="innerHTML"){
-if(d.isIE&&_6a.tagName.toLowerCase() in _69){
-d.empty(_6a);
-_6a.appendChild(d._toDom(_6c,_6a.ownerDocument));
-}else{
-_6a[_6f]=_6c;
-}
-break;
-}
-if(d.isFunction(_6c)){
-var _72=d.attr(_6a,_68);
-if(!_72){
-_72=_67++;
-d.attr(_6a,_68,_72);
-}
-if(!_66[_72]){
-_66[_72]={};
-}
-var h=_66[_72][_6f];
-if(h){
-d.disconnect(h);
-}else{
-try{
-delete _6a[_6f];
-}
-catch(e){
-}
-}
-_66[_72][_6f]=d.connect(_6a,_6f,_6c);
-break;
-}
-if(_70||typeof _6c=="boolean"){
-_6a[_6f]=_6c;
-break;
-}
-_6a.setAttribute(_71,_6c);
-}while(false);
-return _6a;
-}
-_6c=_6a[_6f];
-if(_70&&typeof _6c!="undefined"){
-return _6c;
-}
-if(_6f!="href"&&(typeof _6c=="boolean"||d.isFunction(_6c))){
-return _6c;
-}
-return _60(_6a,_71)?_6a.getAttribute(_71):null;
-};
-dojo.removeAttr=function(_73,_74){
-_5(_73).removeAttribute(_5e(_74));
-};
-dojo.getNodeProp=function(_75,_76){
-_75=_5(_75);
-var lc=_76.toLowerCase(),_77=_5b[lc]||_76;
-if((_77 in _75)&&_77!="href"){
-return _75[_77];
-}
-var _78=_5c[lc]||_76;
-return _60(_75,_78)?_75.getAttribute(_78):null;
-};
-dojo.create=function(tag,_79,_7a,pos){
-var doc=d.doc;
-if(_7a){
-_7a=_5(_7a);
-doc=_7a.ownerDocument;
-}
-if(typeof tag=="string"){
-tag=doc.createElement(tag);
-}
-if(_79){
-d.attr(tag,_79);
-}
-if(_7a){
-d.place(tag,_7a,pos);
-}
-return tag;
-};
-d.empty=d.isIE?function(_7b){
-_7b=_5(_7b);
-for(var c;c=_7b.lastChild;){
-d.destroy(c);
-}
-}:function(_7c){
-_5(_7c).innerHTML="";
-};
-var _7d={option:["select"],tbody:["table"],thead:["table"],tfoot:["table"],tr:["table","tbody"],td:["table","tbody","tr"],th:["table","thead","tr"],legend:["fieldset"],caption:["table"],colgroup:["table"],col:["table","colgroup"],li:["ul"]},_7e=/<\s*([\w\:]+)/,_7f={},_80=0,_81="__"+d._scopeName+"ToDomId";
-for(var _82 in _7d){
-var tw=_7d[_82];
-tw.pre=_82=="option"?"<select multiple=\"multiple\">":"<"+tw.join("><")+">";
-tw.post="</"+tw.reverse().join("></")+">";
-}
-d._toDom=function(_83,doc){
-doc=doc||d.doc;
-var _84=doc[_81];
-if(!_84){
-doc[_81]=_84=++_80+"";
-_7f[_84]=doc.createElement("div");
-}
-_83+="";
-var _85=_83.match(_7e),tag=_85?_85[1].toLowerCase():"",_86=_7f[_84],_87,i,fc,df;
-if(_85&&_7d[tag]){
-_87=_7d[tag];
-_86.innerHTML=_87.pre+_83+_87.post;
-for(i=_87.length;i;--i){
-_86=_86.firstChild;
-}
-}else{
-_86.innerHTML=_83;
-}
-if(_86.childNodes.length==1){
-return _86.removeChild(_86.firstChild);
-}
-df=doc.createDocumentFragment();
-while(fc=_86.firstChild){
-df.appendChild(fc);
-}
-return df;
-};
-var _88="className";
-dojo.hasClass=function(_89,_8a){
-return ((" "+_5(_89)[_88]+" ").indexOf(" "+_8a+" ")>=0);
-};
-var _8b=/\s+/,a1=[""],_8c=function(s){
-if(typeof s=="string"||s instanceof String){
-if(s.indexOf(" ")<0){
-a1[0]=s;
-return a1;
-}else{
-return s.split(_8b);
-}
-}
-return s;
-};
-dojo.addClass=function(_8d,_8e){
-_8d=_5(_8d);
-_8e=_8c(_8e);
-var cls=" "+_8d[_88]+" ";
-for(var i=0,len=_8e.length,c;i<len;++i){
-c=_8e[i];
-if(c&&cls.indexOf(" "+c+" ")<0){
-cls+=c+" ";
-}
-}
-_8d[_88]=d.trim(cls);
-};
-dojo.removeClass=function(_8f,_90){
-_8f=_5(_8f);
-var cls;
-if(_90!==undefined){
-_90=_8c(_90);
-cls=" "+_8f[_88]+" ";
-for(var i=0,len=_90.length;i<len;++i){
-cls=cls.replace(" "+_90[i]+" "," ");
-}
-cls=d.trim(cls);
-}else{
-cls="";
-}
-if(_8f[_88]!=cls){
-_8f[_88]=cls;
-}
-};
-dojo.toggleClass=function(_91,_92,_93){
-if(_93===undefined){
-_93=!d.hasClass(_91,_92);
-}
-d[_93?"addClass":"removeClass"](_91,_92);
-};
+	var d = dojo;
+//>>excludeEnd("webkitMobile");
+	var byId = d.byId;
+
+	var _destroyContainer = null,
+		_destroyDoc;
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	d.addOnWindowUnload(function(){
+		_destroyContainer = null; //prevent IE leak
+	});
+	//>>excludeEnd("webkitMobile");
+
+/*=====
+	dojo._destroyElement = function(node){
+		// summary:
+		// 		Existing alias for `dojo.destroy`. Deprecated, will be removed
+		// 		in 2.0
+	}
+=====*/
+	dojo._destroyElement = dojo.destroy = function(/*String|DomNode*/node){
+		//	summary:
+		//		Removes a node from its parent, clobbering it and all of its
+		//		children.
+		//
+		//	description:
+		//		Removes a node from its parent, clobbering it and all of its
+		//		children. Function only works with DomNodes, and returns nothing.
+		//
+		//	node:
+		//		A String ID or DomNode reference of the element to be destroyed
+		//
+		//	example:
+		//	Destroy a node byId:
+		//	|	dojo.destroy("someId");
+		//
+		//	example:
+		//	Destroy all nodes in a list by reference:
+		//	|	dojo.query(".someNode").forEach(dojo.destroy);
+
+		node = byId(node);
+		try{
+			var doc = node.ownerDocument;
+			// cannot use _destroyContainer.ownerDocument since this can throw an exception on IE
+			if(!_destroyContainer || _destroyDoc != doc){
+				_destroyContainer = doc.createElement("div");
+				_destroyDoc = doc;
+			}
+			_destroyContainer.appendChild(node.parentNode ? node.parentNode.removeChild(node) : node);
+			// NOTE: see http://trac.dojotoolkit.org/ticket/2931. This may be a bug and not a feature
+			_destroyContainer.innerHTML = "";
+		}catch(e){
+			/* squelch */
+		}
+	};
+
+	dojo.isDescendant = function(/*DomNode|String*/node, /*DomNode|String*/ancestor){
+		//	summary:
+		//		Returns true if node is a descendant of ancestor
+		//	node: string id or node reference to test
+		//	ancestor: string id or node reference of potential parent to test against
+		//
+		// example:
+		//	Test is node id="bar" is a descendant of node id="foo"
+		//	|	if(dojo.isDescendant("bar", "foo")){ ... }
+		try{
+			node = byId(node);
+			ancestor = byId(ancestor);
+			while(node){
+				if(node == ancestor){
+					return true; // Boolean
+				}
+				node = node.parentNode;
+			}
+		}catch(e){ /* squelch, return false */ }
+		return false; // Boolean
+	};
+
+	dojo.setSelectable = function(/*DomNode|String*/node, /*Boolean*/selectable){
+		//	summary: 
+		//		Enable or disable selection on a node
+		//	node:
+		//		id or reference to node
+		//	selectable:
+		//		state to put the node in. false indicates unselectable, true 
+		//		allows selection.
+		//	example:
+		//	Make the node id="bar" unselectable
+		//	|	dojo.setSelectable("bar"); 
+		//	example:
+		//	Make the node id="bar" selectable
+		//	|	dojo.setSelectable("bar", true);
+		node = byId(node);
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		if(d.isMozilla){
+			node.style.MozUserSelect = selectable ? "" : "none";
+		}else if(d.isKhtml || d.isWebKit){
+		//>>excludeEnd("webkitMobile");
+			node.style.KhtmlUserSelect = selectable ? "auto" : "none";
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		}else if(d.isIE){
+			var v = (node.unselectable = selectable ? "" : "on");
+			d.query("*", node).forEach("item.unselectable = '"+v+"'");
+		}
+		//>>excludeEnd("webkitMobile");
+		//FIXME: else?  Opera?
+	};
+
+	var _insertBefore = function(/*DomNode*/node, /*DomNode*/ref){
+		var parent = ref.parentNode;
+		if(parent){
+			parent.insertBefore(node, ref);
+		}
+	};
+
+	var _insertAfter = function(/*DomNode*/node, /*DomNode*/ref){
+		//	summary:
+		//		Try to insert node after ref
+		var parent = ref.parentNode;
+		if(parent){
+			if(parent.lastChild == ref){
+				parent.appendChild(node);
+			}else{
+				parent.insertBefore(node, ref.nextSibling);
+			}
+		}
+	};
+
+	dojo.place = function(node, refNode, position){
+		//	summary:
+		//		Attempt to insert node into the DOM, choosing from various positioning options.
+		//		Returns the first argument resolved to a DOM node.
+		//
+		//	node: String|DomNode
+		//		id or node reference, or HTML fragment starting with "<" to place relative to refNode
+		//
+		//	refNode: String|DomNode
+		//		id or node reference to use as basis for placement
+		//
+		//	position: String|Number?
+		//		string noting the position of node relative to refNode or a
+		//		number indicating the location in the childNodes collection of refNode.
+		//		Accepted string values are:
+		//	|	* before
+		//	|	* after
+		//	|	* replace
+		//	|	* only
+		//	|	* first
+		//	|	* last
+		//		"first" and "last" indicate positions as children of refNode, "replace" replaces refNode,
+		//		"only" replaces all children.  position defaults to "last" if not specified
+		//
+		//	returns: DomNode
+		//		Returned values is the first argument resolved to a DOM node.
+		//
+		//		.place() is also a method of `dojo.NodeList`, allowing `dojo.query` node lookups.
+		//
+		// example:
+		//		Place a node by string id as the last child of another node by string id:
+		//	|	dojo.place("someNode", "anotherNode");
+		//
+		// example:
+		//		Place a node by string id before another node by string id
+		//	|	dojo.place("someNode", "anotherNode", "before");
+		//
+		// example:
+		//		Create a Node, and place it in the body element (last child):
+		//	|	dojo.place("<div></div>", dojo.body());
+		//
+		// example:
+		//		Put a new LI as the first child of a list by id:
+		//	|	dojo.place("<li></li>", "someUl", "first");
+
+		refNode = byId(refNode);
+		if(typeof node == "string"){ // inline'd type check
+			node = node.charAt(0) == "<" ? d._toDom(node, refNode.ownerDocument) : byId(node);
+		}
+		if(typeof position == "number"){ // inline'd type check
+			var cn = refNode.childNodes;
+			if(!cn.length || cn.length <= position){
+				refNode.appendChild(node);
+			}else{
+				_insertBefore(node, cn[position < 0 ? 0 : position]);
+			}
+		}else{
+			switch(position){
+				case "before":
+					_insertBefore(node, refNode);
+					break;
+				case "after":
+					_insertAfter(node, refNode);
+					break;
+				case "replace":
+					refNode.parentNode.replaceChild(node, refNode);
+					break;
+				case "only":
+					d.empty(refNode);
+					refNode.appendChild(node);
+					break;
+				case "first":
+					if(refNode.firstChild){
+						_insertBefore(node, refNode.firstChild);
+						break;
+					}
+					// else fallthrough...
+				default: // aka: last
+					refNode.appendChild(node);
+			}
+		}
+		return node; // DomNode
+	}
+
+	// Box functions will assume this model.
+	// On IE/Opera, BORDER_BOX will be set if the primary document is in quirks mode.
+	// Can be set to change behavior of box setters.
+
+	// can be either:
+	//	"border-box"
+	//	"content-box" (default)
+	dojo.boxModel = "content-box";
+
+	// We punt per-node box mode testing completely.
+	// If anybody cares, we can provide an additional (optional) unit 
+	// that overrides existing code to include per-node box sensitivity.
+
+	// Opera documentation claims that Opera 9 uses border-box in BackCompat mode.
+	// but experiments (Opera 9.10.8679 on Windows Vista) indicate that it actually continues to use content-box.
+	// IIRC, earlier versions of Opera did in fact use border-box.
+	// Opera guys, this is really confusing. Opera being broken in quirks mode is not our fault.
+
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	if(d.isIE /*|| dojo.isOpera*/){
+		// client code may have to adjust if compatMode varies across iframes
+		d.boxModel = document.compatMode == "BackCompat" ? "border-box" : "content-box";
+	}
+	//>>excludeEnd("webkitMobile");
+
+	// =============================
+	// Style Functions
+	// =============================
+
+	// getComputedStyle drives most of the style code.
+	// Wherever possible, reuse the returned object.
+	//
+	// API functions below that need to access computed styles accept an 
+	// optional computedStyle parameter.
+	// If this parameter is omitted, the functions will call getComputedStyle themselves.
+	// This way, calling code can access computedStyle once, and then pass the reference to 
+	// multiple API functions.
+
+/*=====
+	dojo.getComputedStyle = function(node){
+		//	summary:
+		//		Returns a "computed style" object.
+		//
+		//	description:
+		//		Gets a "computed style" object which can be used to gather
+		//		information about the current state of the rendered node.
+		//
+		//		Note that this may behave differently on different browsers.
+		//		Values may have different formats and value encodings across
+		//		browsers.
+		//
+		//		Note also that this method is expensive.  Wherever possible,
+		//		reuse the returned object.
+		//
+		//		Use the dojo.style() method for more consistent (pixelized)
+		//		return values.
+		//
+		//	node: DOMNode
+		//		A reference to a DOM node. Does NOT support taking an
+		//		ID string for speed reasons.
+		//	example:
+		//	|	dojo.getComputedStyle(dojo.byId('foo')).borderWidth;
+		//
+		//	example:
+		//	Reusing the returned object, avoiding multiple lookups:
+		//	|	var cs = dojo.getComputedStyle(dojo.byId("someNode"));
+		//	|	var w = cs.width, h = cs.height;
+		return; // CSS2Properties
+	}
+=====*/
+
+	// Although we normally eschew argument validation at this
+	// level, here we test argument 'node' for (duck)type,
+	// by testing nodeType, ecause 'document' is the 'parentNode' of 'body'
+	// it is frequently sent to this function even 
+	// though it is not Element.
+	var gcs;
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	if(d.isWebKit){
+	//>>excludeEnd("webkitMobile");
+		gcs = function(/*DomNode*/node){
+			var s;
+			if(node.nodeType == 1){
+				var dv = node.ownerDocument.defaultView;
+				s = dv.getComputedStyle(node, null);
+				if(!s && node.style){
+					node.style.display = "";
+					s = dv.getComputedStyle(node, null);
+				}
+			}
+			return s || {};
+		};
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	}else if(d.isIE){
+		gcs = function(node){
+			// IE (as of 7) doesn't expose Element like sane browsers
+			return node.nodeType == 1 /* ELEMENT_NODE*/ ? node.currentStyle : {};
+		};
+	}else{
+		gcs = function(node){
+			return node.nodeType == 1 ?
+				node.ownerDocument.defaultView.getComputedStyle(node, null) : {};
+		};
+	}
+	//>>excludeEnd("webkitMobile");
+	dojo.getComputedStyle = gcs;
+
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	if(!d.isIE){
+	//>>excludeEnd("webkitMobile");
+		d._toPixelValue = function(element, value){
+			// style values can be floats, client code may want
+			// to round for integer pixels.
+			return parseFloat(value) || 0;
+		};
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	}else{
+		d._toPixelValue = function(element, avalue){
+			if(!avalue){ return 0; }
+			// on IE7, medium is usually 4 pixels
+			if(avalue == "medium"){ return 4; }
+			// style values can be floats, client code may
+			// want to round this value for integer pixels.
+			if(avalue.slice && avalue.slice(-2) == 'px'){ return parseFloat(avalue); }
+			with(element){
+				var sLeft = style.left;
+				var rsLeft = runtimeStyle.left;
+				runtimeStyle.left = currentStyle.left;
+				try{
+					// 'avalue' may be incompatible with style.left, which can cause IE to throw
+					// this has been observed for border widths using "thin", "medium", "thick" constants
+					// those particular constants could be trapped by a lookup
+					// but perhaps there are more
+					style.left = avalue;
+					avalue = style.pixelLeft;
+				}catch(e){
+					avalue = 0;
+				}
+				style.left = sLeft;
+				runtimeStyle.left = rsLeft;
+			}
+			return avalue;
+		}
+	}
+	//>>excludeEnd("webkitMobile");
+	var px = d._toPixelValue;
+
+	// FIXME: there opacity quirks on FF that we haven't ported over. Hrm.
+	/*=====
+	dojo._getOpacity = function(node){
+			//	summary:
+			//		Returns the current opacity of the passed node as a
+			//		floating-point value between 0 and 1.
+			//	node: DomNode
+			//		a reference to a DOM node. Does NOT support taking an
+			//		ID string for speed reasons.
+			//	returns: Number between 0 and 1
+			return; // Number
+	}
+	=====*/
+
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	var astr = "DXImageTransform.Microsoft.Alpha";
+	var af = function(n, f){
+		try{
+			return n.filters.item(astr);
+		}catch(e){
+			return f ? {} : null;
+		}
+	};
+
+	//>>excludeEnd("webkitMobile");
+	dojo._getOpacity =
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		d.isIE ? function(node){
+			try{
+				return af(node).Opacity / 100; // Number
+			}catch(e){
+				return 1; // Number
+			}
+		} :
+	//>>excludeEnd("webkitMobile");
+		function(node){
+			return gcs(node).opacity;
+		};
+
+	/*=====
+	dojo._setOpacity = function(node, opacity){
+			//	summary:
+			//		set the opacity of the passed node portably. Returns the
+			//		new opacity of the node.
+			//	node: DOMNode
+			//		a reference to a DOM node. Does NOT support taking an
+			//		ID string for performance reasons.
+			//	opacity: Number
+			//		A Number between 0 and 1. 0 specifies transparent.
+			//	returns: Number between 0 and 1
+			return; // Number
+	}
+	=====*/
+
+	dojo._setOpacity =
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		d.isIE ? function(/*DomNode*/node, /*Number*/opacity){
+			var ov = opacity * 100, opaque = opacity == 1;
+			node.style.zoom = opaque ? "" : 1;
+
+			if(!af(node)){
+				if(opaque){
+					return opacity;
+				}
+				node.style.filter += " progid:" + astr + "(Opacity=" + ov + ")";
+			}else{
+				af(node, 1).Opacity = ov;
+			}
+
+			// on IE7 Alpha(Filter opacity=100) makes text look fuzzy so disable it altogether (bug #2661),
+			//but still update the opacity value so we can get a correct reading if it is read later.
+			af(node, 1).Enabled = !opaque;
+
+			if(node.nodeName.toLowerCase() == "tr"){
+				d.query("> td", node).forEach(function(i){
+					d._setOpacity(i, opacity);
+				});
+			}
+			return opacity;
+		} :
+		//>>excludeEnd("webkitMobile");
+		function(node, opacity){
+			return node.style.opacity = opacity;
+		};
+
+	var _pixelNamesCache = {
+		left: true, top: true
+	};
+	var _pixelRegExp = /margin|padding|width|height|max|min|offset/;  // |border
+	var _toStyleValue = function(node, type, value){
+		type = type.toLowerCase(); // FIXME: should we really be doing string case conversion here? Should we cache it? Need to profile!
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		if(d.isIE){
+			if(value == "auto"){
+				if(type == "height"){ return node.offsetHeight; }
+				if(type == "width"){ return node.offsetWidth; }
+			}
+			if(type == "fontweight"){
+				switch(value){
+					case 700: return "bold";
+					case 400:
+					default: return "normal";
+				}
+			}
+		}
+		//>>excludeEnd("webkitMobile");
+		if(!(type in _pixelNamesCache)){
+			_pixelNamesCache[type] = _pixelRegExp.test(type);
+		}
+		return _pixelNamesCache[type] ? px(node, value) : value;
+	};
+
+	var _floatStyle = d.isIE ? "styleFloat" : "cssFloat",
+		_floatAliases = { "cssFloat": _floatStyle, "styleFloat": _floatStyle, "float": _floatStyle }
+	;
+
+	// public API
+
+	dojo.style = function(	/*DomNode|String*/ node,
+							/*String?|Object?*/ style,
+							/*String?*/ value){
+		//	summary:
+		//		Accesses styles on a node. If 2 arguments are
+		//		passed, acts as a getter. If 3 arguments are passed, acts
+		//		as a setter.
+		//	description:
+		//		Getting the style value uses the computed style for the node, so the value
+		//		will be a calculated value, not just the immediate node.style value.
+		//		Also when getting values, use specific style names,
+		//		like "borderBottomWidth" instead of "border" since compound values like
+		//		"border" are not necessarily reflected as expected.
+		//		If you want to get node dimensions, use `dojo.marginBox()`, 
+		//		`dojo.contentBox()` or `dojo.position()`.
+		//	node:
+		//		id or reference to node to get/set style for
+		//	style:
+		//		the style property to set in DOM-accessor format
+		//		("borderWidth", not "border-width") or an object with key/value
+		//		pairs suitable for setting each property.
+		//	value:
+		//		If passed, sets value on the node for style, handling
+		//		cross-browser concerns.  When setting a pixel value,
+		//		be sure to include "px" in the value. For instance, top: "200px".
+		//		Otherwise, in some cases, some browsers will not apply the style.
+		//	example:
+		//		Passing only an ID or node returns the computed style object of
+		//		the node:
+		//	|	dojo.style("thinger");
+		//	example:
+		//		Passing a node and a style property returns the current
+		//		normalized, computed value for that property:
+		//	|	dojo.style("thinger", "opacity"); // 1 by default
+		//
+		//	example:
+		//		Passing a node, a style property, and a value changes the
+		//		current display of the node and returns the new computed value
+		//	|	dojo.style("thinger", "opacity", 0.5); // == 0.5
+		//
+		//	example:
+		//		Passing a node, an object-style style property sets each of the values in turn and returns the computed style object of the node:
+		//	|	dojo.style("thinger", {
+		//	|		"opacity": 0.5,
+		//	|		"border": "3px solid black",
+		//	|		"height": "300px"
+		//	|	});
+		//
+		// 	example:
+		//		When the CSS style property is hyphenated, the JavaScript property is camelCased.
+		//		font-size becomes fontSize, and so on.
+		//	|	dojo.style("thinger",{
+		//	|		fontSize:"14pt",
+		//	|		letterSpacing:"1.2em"
+		//	|	});
+		//
+		//	example:
+		//		dojo.NodeList implements .style() using the same syntax, omitting the "node" parameter, calling
+		//		dojo.style() on every element of the list. See: `dojo.query()` and `dojo.NodeList()`
+		//	|	dojo.query(".someClassName").style("visibility","hidden");
+		//	|	// or
+		//	|	dojo.query("#baz > div").style({
+		//	|		opacity:0.75,
+		//	|		fontSize:"13pt"
+		//	|	});
+
+		var n = byId(node), args = arguments.length, op = (style == "opacity");
+		style = _floatAliases[style] || style;
+		if(args == 3){
+			return op ? d._setOpacity(n, value) : n.style[style] = value; /*Number*/
+		}
+		if(args == 2 && op){
+			return d._getOpacity(n);
+		}
+		var s = gcs(n);
+		if(args == 2 && typeof style != "string"){ // inline'd type check
+			for(var x in style){
+				d.style(node, x, style[x]);
+			}
+			return s;
+		}
+		return (args == 1) ? s : _toStyleValue(n, style, s[style] || n.style[style]); /* CSS2Properties||String||Number */
+	}
+
+	// =============================
+	// Box Functions
+	// =============================
+
+	dojo._getPadExtents = function(/*DomNode*/n, /*Object*/computedStyle){
+		//	summary:
+		// 		Returns object with special values specifically useful for node
+		// 		fitting.
+		//	description:
+		//		Returns an object with `w`, `h`, `l`, `t` properties:
+		//	|		l/t = left/top padding (respectively)
+		//	|		w = the total of the left and right padding 
+		//	|		h = the total of the top and bottom padding
+		//		If 'node' has position, l/t forms the origin for child nodes.
+		//		The w/h are used for calculating boxes.
+		//		Normally application code will not need to invoke this
+		//		directly, and will use the ...box... functions instead.
+		var 
+			s = computedStyle||gcs(n),
+			l = px(n, s.paddingLeft),
+			t = px(n, s.paddingTop);
+		return {
+			l: l,
+			t: t,
+			w: l+px(n, s.paddingRight),
+			h: t+px(n, s.paddingBottom)
+		};
+	}
+
+	dojo._getBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){
+		//	summary:
+		//		returns an object with properties useful for noting the border
+		//		dimensions.
+		//	description:
+		// 		* l/t = the sum of left/top border (respectively)
+		//		* w = the sum of the left and right border
+		//		* h = the sum of the top and bottom border
+		//
+		//		The w/h are used for calculating boxes.
+		//		Normally application code will not need to invoke this
+		//		directly, and will use the ...box... functions instead.
+		var 
+			ne = "none",
+			s = computedStyle||gcs(n),
+			bl = (s.borderLeftStyle != ne ? px(n, s.borderLeftWidth) : 0),
+			bt = (s.borderTopStyle != ne ? px(n, s.borderTopWidth) : 0);
+		return {
+			l: bl,
+			t: bt,
+			w: bl + (s.borderRightStyle!=ne ? px(n, s.borderRightWidth) : 0),
+			h: bt + (s.borderBottomStyle!=ne ? px(n, s.borderBottomWidth) : 0)
+		};
+	}
+
+	dojo._getPadBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){
+		//	summary:
+		//		Returns object with properties useful for box fitting with
+		//		regards to padding.
+		// description:
+		//		* l/t = the sum of left/top padding and left/top border (respectively)
+		//		* w = the sum of the left and right padding and border
+		//		* h = the sum of the top and bottom padding and border
+		//
+		//		The w/h are used for calculating boxes.
+		//		Normally application code will not need to invoke this
+		//		directly, and will use the ...box... functions instead.
+		var 
+			s = computedStyle||gcs(n),
+			p = d._getPadExtents(n, s),
+			b = d._getBorderExtents(n, s);
+		return {
+			l: p.l + b.l,
+			t: p.t + b.t,
+			w: p.w + b.w,
+			h: p.h + b.h
+		};
+	}
+
+	dojo._getMarginExtents = function(n, computedStyle){
+		//	summary:
+		//		returns object with properties useful for box fitting with
+		//		regards to box margins (i.e., the outer-box).
+		//
+		//		* l/t = marginLeft, marginTop, respectively
+		//		* w = total width, margin inclusive
+		//		* h = total height, margin inclusive
+		//
+		//		The w/h are used for calculating boxes.
+		//		Normally application code will not need to invoke this
+		//		directly, and will use the ...box... functions instead.
+		var 
+			s = computedStyle||gcs(n),
+			l = px(n, s.marginLeft),
+			t = px(n, s.marginTop),
+			r = px(n, s.marginRight),
+			b = px(n, s.marginBottom);
+		if(d.isWebKit && (s.position != "absolute")){
+			// FIXME: Safari's version of the computed right margin
+			// is the space between our right edge and the right edge 
+			// of our offsetParent.
+			// What we are looking for is the actual margin value as 
+			// determined by CSS.
+			// Hack solution is to assume left/right margins are the same.
+			r = l;
+		}
+		return {
+			l: l,
+			t: t,
+			w: l+r,
+			h: t+b
+		};
+	}
+
+	// Box getters work in any box context because offsetWidth/clientWidth
+	// are invariant wrt box context
+	//
+	// They do *not* work for display: inline objects that have padding styles
+	// because the user agent ignores padding (it's bogus styling in any case)
+	//
+	// Be careful with IMGs because they are inline or block depending on 
+	// browser and browser mode.
+
+	// Although it would be easier to read, there are not separate versions of 
+	// _getMarginBox for each browser because:
+	// 1. the branching is not expensive
+	// 2. factoring the shared code wastes cycles (function call overhead)
+	// 3. duplicating the shared code wastes bytes
+
+	dojo._getMarginBox = function(/*DomNode*/node, /*Object*/computedStyle){
+		// summary:
+		//		returns an object that encodes the width, height, left and top
+		//		positions of the node's margin box.
+		var s = computedStyle || gcs(node), me = d._getMarginExtents(node, s);
+		var l = node.offsetLeft - me.l, t = node.offsetTop - me.t, p = node.parentNode;
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		if(d.isMoz){
+			// Mozilla:
+			// If offsetParent has a computed overflow != visible, the offsetLeft is decreased
+			// by the parent's border.
+			// We don't want to compute the parent's style, so instead we examine node's
+			// computed left/top which is more stable.
+			var sl = parseFloat(s.left), st = parseFloat(s.top);
+			if(!isNaN(sl) && !isNaN(st)){
+				l = sl, t = st;
+			}else{
+				// If child's computed left/top are not parseable as a number (e.g. "auto"), we
+				// have no choice but to examine the parent's computed style.
+				if(p && p.style){
+					var pcs = gcs(p);
+					if(pcs.overflow != "visible"){
+						var be = d._getBorderExtents(p, pcs);
+						l += be.l, t += be.t;
+					}
+				}
+			}
+		}else if(d.isOpera || (d.isIE > 7 && !d.isQuirks)){
+			// On Opera and IE 8, offsetLeft/Top includes the parent's border
+			if(p){
+				be = d._getBorderExtents(p);
+				l -= be.l;
+				t -= be.t;
+			}
+		}
+		//>>excludeEnd("webkitMobile");
+		return {
+			l: l,
+			t: t,
+			w: node.offsetWidth + me.w,
+			h: node.offsetHeight + me.h 
+		};
+	}
+
+	dojo._getContentBox = function(node, computedStyle){
+		// summary:
+		//		Returns an object that encodes the width, height, left and top
+		//		positions of the node's content box, irrespective of the
+		//		current box model.
+
+		// clientWidth/Height are important since the automatically account for scrollbars
+		// fallback to offsetWidth/Height for special cases (see #3378)
+		var s = computedStyle || gcs(node),
+			pe = d._getPadExtents(node, s),
+			be = d._getBorderExtents(node, s),
+			w = node.clientWidth,
+			h
+		;
+		if(!w){
+			w = node.offsetWidth, h = node.offsetHeight;
+		}else{
+			h = node.clientHeight, be.w = be.h = 0;
+		}
+		// On Opera, offsetLeft includes the parent's border
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		if(d.isOpera){ pe.l += be.l; pe.t += be.t; };
+		//>>excludeEnd("webkitMobile");
+		return {
+			l: pe.l,
+			t: pe.t,
+			w: w - pe.w - be.w,
+			h: h - pe.h - be.h
+		};
+	}
+
+	dojo._getBorderBox = function(node, computedStyle){
+		var s = computedStyle || gcs(node),
+			pe = d._getPadExtents(node, s),
+			cb = d._getContentBox(node, s)
+		;
+		return {
+			l: cb.l - pe.l,
+			t: cb.t - pe.t,
+			w: cb.w + pe.w,
+			h: cb.h + pe.h
+		};
+	}
+
+	// Box setters depend on box context because interpretation of width/height styles
+	// vary wrt box context.
+	//
+	// The value of dojo.boxModel is used to determine box context.
+	// dojo.boxModel can be set directly to change behavior.
+	//
+	// Beware of display: inline objects that have padding styles
+	// because the user agent ignores padding (it's a bogus setup anyway)
+	//
+	// Be careful with IMGs because they are inline or block depending on 
+	// browser and browser mode.
+	//
+	// Elements other than DIV may have special quirks, like built-in
+	// margins or padding, or values not detectable via computedStyle.
+	// In particular, margins on TABLE do not seems to appear 
+	// at all in computedStyle on Mozilla.
+
+	dojo._setBox = function(/*DomNode*/node, /*Number?*/l, /*Number?*/t, /*Number?*/w, /*Number?*/h, /*String?*/u){
+		//	summary:
+		//		sets width/height/left/top in the current (native) box-model
+		//		dimentions. Uses the unit passed in u.
+		//	node:
+		//		DOM Node reference. Id string not supported for performance
+		//		reasons.
+		//	l:
+		//		left offset from parent.
+		//	t:
+		//		top offset from parent.
+		//	w:
+		//		width in current box model.
+		//	h:
+		//		width in current box model.
+		//	u:
+		//		unit measure to use for other measures. Defaults to "px".
+		u = u || "px";
+		var s = node.style;
+		if(!isNaN(l)){ s.left = l + u; }
+		if(!isNaN(t)){ s.top = t + u; }
+		if(w >= 0){ s.width = w + u; }
+		if(h >= 0){ s.height = h + u; }
+	}
+
+	dojo._isButtonTag = function(/*DomNode*/node) {
+		// summary:
+		//		True if the node is BUTTON or INPUT.type="button".
+		return node.tagName == "BUTTON"
+			|| node.tagName=="INPUT" && (node.getAttribute("type")||'').toUpperCase() == "BUTTON"; // boolean
+	}
+
+	dojo._usesBorderBox = function(/*DomNode*/node){
+		//	summary:
+		//		True if the node uses border-box layout.
+
+		// We could test the computed style of node to see if a particular box
+		// has been specified, but there are details and we choose not to bother.
+
+		// TABLE and BUTTON (and INPUT type=button) are always border-box by default.
+		// If you have assigned a different box to either one via CSS then
+		// box functions will break.
+
+		var n = node.tagName;
+		return d.boxModel=="border-box" || n=="TABLE" || d._isButtonTag(node); // boolean
+	}
+
+	dojo._setContentSize = function(/*DomNode*/node, /*Number*/widthPx, /*Number*/heightPx, /*Object*/computedStyle){
+		//	summary:
+		//		Sets the size of the node's contents, irrespective of margins,
+		//		padding, or borders.
+		if(d._usesBorderBox(node)){
+			var pb = d._getPadBorderExtents(node, computedStyle);
+			if(widthPx >= 0){ widthPx += pb.w; }
+			if(heightPx >= 0){ heightPx += pb.h; }
+		}
+		d._setBox(node, NaN, NaN, widthPx, heightPx);
+	}
+
+	dojo._setMarginBox = function(/*DomNode*/node, 	/*Number?*/leftPx, /*Number?*/topPx,
+													/*Number?*/widthPx, /*Number?*/heightPx,
+													/*Object*/computedStyle){
+		//	summary:
+		//		sets the size of the node's margin box and placement
+		//		(left/top), irrespective of box model. Think of it as a
+		//		passthrough to dojo._setBox that handles box-model vagaries for
+		//		you.
+
+		var s = computedStyle || gcs(node),
+		// Some elements have special padding, margin, and box-model settings.
+		// To use box functions you may need to set padding, margin explicitly.
+		// Controlling box-model is harder, in a pinch you might set dojo.boxModel.
+			bb = d._usesBorderBox(node),
+			pb = bb ? _nilExtents : d._getPadBorderExtents(node, s)
+		;
+		if(d.isWebKit){
+			// on Safari (3.1.2), button nodes with no explicit size have a default margin
+			// setting an explicit size eliminates the margin.
+			// We have to swizzle the width to get correct margin reading.
+			if(d._isButtonTag(node)){
+				var ns = node.style;
+				if(widthPx >= 0 && !ns.width) { ns.width = "4px"; }
+				if(heightPx >= 0 && !ns.height) { ns.height = "4px"; }
+			}
+		}
+		var mb = d._getMarginExtents(node, s);
+		if(widthPx >= 0){ widthPx = Math.max(widthPx - pb.w - mb.w, 0); }
+		if(heightPx >= 0){ heightPx = Math.max(heightPx - pb.h - mb.h, 0); }
+		d._setBox(node, leftPx, topPx, widthPx, heightPx);
+	}
+
+	var _nilExtents = { l:0, t:0, w:0, h:0 };
+
+	// public API
+
+	dojo.marginBox = function(/*DomNode|String*/node, /*Object?*/box){
+		//	summary:
+		//		Getter/setter for the margin-box of node.
+		//	description:
+		//		Getter/setter for the margin-box of node.
+		//		Returns an object in the expected format of box (regardless
+		//		if box is passed). The object might look like:
+		//			`{ l: 50, t: 200, w: 300: h: 150 }`
+		//		for a node offset from its parent 50px to the left, 200px from
+		//		the top with a margin width of 300px and a margin-height of
+		//		150px.
+		//	node:
+		//		id or reference to DOM Node to get/set box for
+		//	box:
+		//		If passed, denotes that dojo.marginBox() should
+		//		update/set the margin box for node. Box is an object in the
+		//		above format. All properties are optional if passed.
+		//	example:
+		//	Retrieve the marginbox of a passed node
+		//	|	var box = dojo.marginBox("someNodeId");
+		//	|	console.dir(box);
+		//
+		//	example:
+		//	Set a node's marginbox to the size of another node
+		//	|	var box = dojo.marginBox("someNodeId");
+		//	|	dojo.marginBox("someOtherNode", box);
+		
+		var n = byId(node), s = gcs(n), b = box;
+		return !b ? d._getMarginBox(n, s) : d._setMarginBox(n, b.l, b.t, b.w, b.h, s); // Object
+	}
+
+	dojo.contentBox = function(/*DomNode|String*/node, /*Object?*/box){
+		//	summary:
+		//		Getter/setter for the content-box of node.
+		//	description:
+		//		Returns an object in the expected format of box (regardless if box is passed).
+		//		The object might look like:
+		//			`{ l: 50, t: 200, w: 300: h: 150 }`
+		//		for a node offset from its parent 50px to the left, 200px from
+		//		the top with a content width of 300px and a content-height of
+		//		150px. Note that the content box may have a much larger border
+		//		or margin box, depending on the box model currently in use and
+		//		CSS values set/inherited for node.
+		//		While the getter will return top and left values, the
+		//		setter only accepts setting the width and height.
+		//	node:
+		//		id or reference to DOM Node to get/set box for
+		//	box:
+		//		If passed, denotes that dojo.contentBox() should
+		//		update/set the content box for node. Box is an object in the
+		//		above format, but only w (width) and h (height) are supported.
+		//		All properties are optional if passed.
+		var n = byId(node), s = gcs(n), b = box;
+		return !b ? d._getContentBox(n, s) : d._setContentSize(n, b.w, b.h, s); // Object
+	}
+
+	// =============================
+	// Positioning 
+	// =============================
+
+	var _sumAncestorProperties = function(node, prop){
+		if(!(node = (node||0).parentNode)){return 0}
+		var val, retVal = 0, _b = d.body();
+		while(node && node.style){
+			if(gcs(node).position == "fixed"){
+				return 0;
+			}
+			val = node[prop];
+			if(val){
+				retVal += val - 0;
+				// opera and khtml #body & #html has the same values, we only
+				// need one value
+				if(node == _b){ break; }
+			}
+			node = node.parentNode;
+		}
+		return retVal;	//	integer
+	}
+
+	dojo._docScroll = function(){
+		var n = d.global;
+		return "pageXOffset" in n? { x:n.pageXOffset, y:n.pageYOffset } :
+			(n=d.doc.documentElement, n.clientHeight? { x:d._fixIeBiDiScrollLeft(n.scrollLeft), y:n.scrollTop } :
+			(n=d.body(), { x:n.scrollLeft||0, y:n.scrollTop||0 }));
+	};
+
+	dojo._isBodyLtr = function(){
+		return "_bodyLtr" in d? d._bodyLtr :
+			d._bodyLtr = (d.body().dir || d.doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean 
+	}
+
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	dojo._getIeDocumentElementOffset = function(){
+		//	summary:
+		//		returns the offset in x and y from the document body to the
+		//		visual edge of the page
+		//	description:
+		// The following values in IE contain an offset:
+		//	|		event.clientX
+		//	|		event.clientY
+		//	|		node.getBoundingClientRect().left
+		//	|		node.getBoundingClientRect().top
+		//	 	But other position related values do not contain this offset,
+		//	 	such as node.offsetLeft, node.offsetTop, node.style.left and
+		//	 	node.style.top. The offset is always (2, 2) in LTR direction.
+		//	 	When the body is in RTL direction, the offset counts the width
+		//	 	of left scroll bar's width.  This function computes the actual
+		//	 	offset.
+
+		//NOTE: assumes we're being called in an IE browser
+
+		var de = d.doc.documentElement; // only deal with HTML element here, _abs handles body/quirks 
+
+		if(d.isIE < 8){
+			var r = de.getBoundingClientRect(); // works well for IE6+
+			//console.debug('rect left,top = ' + r.left+','+r.top + ', html client left/top = ' + de.clientLeft+','+de.clientTop + ', rtl = ' + (!d._isBodyLtr()) + ', quirks = ' + d.isQuirks);
+			var l = r.left,
+			    t = r.top;
+			if(d.isIE < 7){
+				l += de.clientLeft;	// scrollbar size in strict/RTL, or,
+				t += de.clientTop;	// HTML border size in strict
+			}
+			return {
+				x: l < 0? 0 : l, // FRAME element border size can lead to inaccurate negative values
+				y: t < 0? 0 : t
+			};
+		}else{
+			return {
+				x: 0,
+				y: 0
+			};
+		}
+
+	};
+	//>>excludeEnd("webkitMobile");
+
+	dojo._fixIeBiDiScrollLeft = function(/*Integer*/ scrollLeft){
+		// In RTL direction, scrollLeft should be a negative value, but IE < 8
+		// returns a positive one. All codes using documentElement.scrollLeft
+		// must call this function to fix this error, otherwise the position
+		// will offset to right when there is a horizontal scrollbar.
+
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		var dd = d.doc;
+		if(d.isIE < 8 && !d._isBodyLtr()){
+			var de = d.isQuirks ? dd.body : dd.documentElement;
+			return scrollLeft + de.clientWidth - de.scrollWidth; // Integer
+		}
+		//>>excludeEnd("webkitMobile");
+		return scrollLeft; // Integer
+	}
+
+	// FIXME: need a setter for coords or a moveTo!!
+	dojo._abs = dojo.position = function(/*DomNode*/node, /*Boolean?*/includeScroll){
+		//	summary:
+		//		Gets the position and size of the passed element relative to
+		//		the viewport (if includeScroll==false), or relative to the
+		//		document root (if includeScroll==true).
+		//
+		//	description:
+		//		Returns an object of the form:
+		//			{ x: 100, y: 300, w: 20, h: 15 }
+		//		If includeScroll==true, the x and y values will include any
+		//		document offsets that may affect the position relative to the
+		//		viewport.
+		//		Uses the border-box model (inclusive of border and padding but
+		//		not margin).  Does not act as a setter.
+
+		var db = d.body(), dh = db.parentNode, ret;
+		node = byId(node);
+		if(node["getBoundingClientRect"]){
+			// IE6+, FF3+, super-modern WebKit, and Opera 9.6+ all take this branch
+			ret = node.getBoundingClientRect();
+			ret = { x: ret.left, y: ret.top, w: ret.right - ret.left, h: ret.bottom - ret.top };
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+			if(d.isIE){
+				// On IE there's a 2px offset that we need to adjust for, see _getIeDocumentElementOffset()
+				var offset = d._getIeDocumentElementOffset();
+
+				// fixes the position in IE, quirks mode
+				ret.x -= offset.x + (d.isQuirks ? db.clientLeft+db.offsetLeft : 0);
+				ret.y -= offset.y + (d.isQuirks ? db.clientTop+db.offsetTop : 0);
+			}else if(d.isFF == 3){
+				// In FF3 you have to subtract the document element margins.
+				// Fixed in FF3.5 though.
+				var cs = gcs(dh);
+				ret.x -= px(dh, cs.marginLeft) + px(dh, cs.borderLeftWidth);
+				ret.y -= px(dh, cs.marginTop) + px(dh, cs.borderTopWidth);
+			}
+		//>>excludeEnd("webkitMobile");
+		}else{
+			// FF2 and older WebKit
+			ret = {
+				x: 0,
+				y: 0,
+				w: node.offsetWidth,
+				h: node.offsetHeight
+			};
+			if(node["offsetParent"]){
+				ret.x -= _sumAncestorProperties(node, "scrollLeft");
+				ret.y -= _sumAncestorProperties(node, "scrollTop");
+
+				var curnode = node;
+				do{
+					var n = curnode.offsetLeft,
+						t = curnode.offsetTop;
+					ret.x += isNaN(n) ? 0 : n;
+					ret.y += isNaN(t) ? 0 : t;
+
+					cs = gcs(curnode);
+					if(curnode != node){
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+						if(d.isMoz){
+							// tried left+right with differently sized left/right borders
+							// it really is 2xleft border in FF, not left+right, even in RTL!
+							ret.x += 2 * px(curnode,cs.borderLeftWidth);
+							ret.y += 2 * px(curnode,cs.borderTopWidth);
+						}else{
+		//>>excludeEnd("webkitMobile");
+							ret.x += px(curnode, cs.borderLeftWidth);
+							ret.y += px(curnode, cs.borderTopWidth);
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+						}
+		//>>excludeEnd("webkitMobile");
+					}
+					// static children in a static div in FF2 are affected by the div's border as well
+					// but offsetParent will skip this div!
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+					if(d.isMoz && cs.position=="static"){
+						var parent=curnode.parentNode;
+						while(parent!=curnode.offsetParent){
+							var pcs=gcs(parent);
+							if(pcs.position=="static"){
+								ret.x += px(curnode,pcs.borderLeftWidth);
+								ret.y += px(curnode,pcs.borderTopWidth);
+							}
+							parent=parent.parentNode;
+						}
+					}
+		//>>excludeEnd("webkitMobile");
+					curnode = curnode.offsetParent;
+				}while((curnode != dh) && curnode);
+			}else if(node.x && node.y){
+				ret.x += isNaN(node.x) ? 0 : node.x;
+				ret.y += isNaN(node.y) ? 0 : node.y;
+			}
+		}
+		// account for document scrolling
+		// if offsetParent is used, ret value already includes scroll position
+		// so we may have to actually remove that value if !includeScroll
+		if(includeScroll){
+			var scroll = d._docScroll();
+			ret.x += scroll.x;
+			ret.y += scroll.y;
+		}
+
+		return ret; // Object
+	}
+
+	dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){
+		//	summary:
+		//		Deprecated: Use position() for border-box x/y/w/h
+		//		or marginBox() for margin-box w/h/l/t.
+		//		Returns an object representing a node's size and position.
+		//
+		//	description:
+		//		Returns an object that measures margin-box (w)idth/(h)eight
+		//		and absolute position x/y of the border-box. Also returned
+		//		is computed (l)eft and (t)op values in pixels from the
+		//		node's offsetParent as returned from marginBox().
+		//		Return value will be in the form:
+		//|			{ l: 50, t: 200, w: 300: h: 150, x: 100, y: 300 }
+		//		Does not act as a setter. If includeScroll is passed, the x and
+		//		y params are affected as one would expect in dojo.position().
+		var n = byId(node), s = gcs(n), mb = d._getMarginBox(n, s);
+		var abs = d.position(n, includeScroll);
+		mb.x = abs.x;
+		mb.y = abs.y;
+		return mb;
+	}
+
+	// =============================
+	// Element attribute Functions
+	// =============================
+
+	// dojo.attr() should conform to http://www.w3.org/TR/DOM-Level-2-Core/
+
+	var _propNames = {
+			// properties renamed to avoid clashes with reserved words
+			"class":   "className",
+			"for":     "htmlFor",
+			// properties written as camelCase
+			tabindex:  "tabIndex",
+			readonly:  "readOnly",
+			colspan:   "colSpan",
+			frameborder: "frameBorder",
+			rowspan:   "rowSpan",
+			valuetype: "valueType"
+		},
+		_attrNames = {
+			// original attribute names
+			classname: "class",
+			htmlfor:   "for",
+			// for IE
+			tabindex:  "tabIndex",
+			readonly:  "readOnly"
+		},
+		_forcePropNames = {
+			innerHTML: 1,
+			className: 1,
+			htmlFor:   d.isIE,
+			value:     1
+		};
+
+	var _fixAttrName = function(/*String*/ name){
+		return _attrNames[name.toLowerCase()] || name;
+	};
+
+	var _hasAttr = function(node, name){
+		var attr = node.getAttributeNode && node.getAttributeNode(name);
+		return attr && attr.specified; // Boolean
+	};
+
+	// There is a difference in the presence of certain properties and their default values
+	// between browsers. For example, on IE "disabled" is present on all elements,
+	// but it is value is "false"; "tabIndex" of <div> returns 0 by default on IE, yet other browsers
+	// can return -1.
+
+	dojo.hasAttr = function(/*DomNode|String*/node, /*String*/name){
+		//	summary:
+		//		Returns true if the requested attribute is specified on the
+		//		given element, and false otherwise.
+		//	node:
+		//		id or reference to the element to check
+		//	name:
+		//		the name of the attribute
+		//	returns:
+		//		true if the requested attribute is specified on the
+		//		given element, and false otherwise
+		var lc = name.toLowerCase();
+		return _forcePropNames[_propNames[lc] || name] || _hasAttr(byId(node), _attrNames[lc] || name);	// Boolean
+	}
+
+	var _evtHdlrMap = {}, _ctr = 0,
+		_attrId = dojo._scopeName + "attrid",
+		// the next dictionary lists elements with read-only innerHTML on IE
+		_roInnerHtml = {col: 1, colgroup: 1,
+			// frameset: 1, head: 1, html: 1, style: 1,
+			table: 1, tbody: 1, tfoot: 1, thead: 1, tr: 1, title: 1};
+
+	dojo.attr = function(/*DomNode|String*/node, /*String|Object*/name, /*String?*/value){
+		//	summary:
+		//		Gets or sets an attribute on an HTML element.
+		//	description:
+		//		Handles normalized getting and setting of attributes on DOM
+		//		Nodes. If 2 arguments are passed, and a the second argumnt is a
+		//		string, acts as a getter.
+		//
+		//		If a third argument is passed, or if the second argument is a
+		//		map of attributes, acts as a setter.
+		//
+		//		When passing functions as values, note that they will not be
+		//		directly assigned to slots on the node, but rather the default
+		//		behavior will be removed and the new behavior will be added
+		//		using `dojo.connect()`, meaning that event handler properties
+		//		will be normalized and that some caveats with regards to
+		//		non-standard behaviors for onsubmit apply. Namely that you
+		//		should cancel form submission using `dojo.stopEvent()` on the
+		//		passed event object instead of returning a boolean value from
+		//		the handler itself.
+		//	node:
+		//		id or reference to the element to get or set the attribute on
+		//	name:
+		//		the name of the attribute to get or set.
+		//	value:
+		//		The value to set for the attribute
+		//	returns:
+		//		when used as a getter, the value of the requested attribute
+		//		or null if that attribute does not have a specified or
+		//		default value;
+		//
+		//		when used as a setter, the DOM node
+		//
+		//	example:
+		//	|	// get the current value of the "foo" attribute on a node
+		//	|	dojo.attr(dojo.byId("nodeId"), "foo");
+		//	|	// or we can just pass the id:
+		//	|	dojo.attr("nodeId", "foo");
+		//
+		//	example:
+		//	|	// use attr() to set the tab index
+		//	|	dojo.attr("nodeId", "tabIndex", 3);
+		//	|
+		//
+		//	example:
+		//	Set multiple values at once, including event handlers:
+		//	|	dojo.attr("formId", {
+		//	|		"foo": "bar",
+		//	|		"tabIndex": -1,
+		//	|		"method": "POST",
+		//	|		"onsubmit": function(e){
+		//	|			// stop submitting the form. Note that the IE behavior
+		//	|			// of returning true or false will have no effect here
+		//	|			// since our handler is connect()ed to the built-in
+		//	|			// onsubmit behavior and so we need to use
+		//	|			// dojo.stopEvent() to ensure that the submission
+		//	|			// doesn't proceed.
+		//	|			dojo.stopEvent(e);
+		//	|
+		//	|			// submit the form with Ajax
+		//	|			dojo.xhrPost({ form: "formId" });
+		//	|		}
+		//	|	});
+		//
+		//	example:
+		//	Style is s special case: Only set with an object hash of styles
+		//	|	dojo.attr("someNode",{
+		//	|		id:"bar",
+		//	|		style:{
+		//	|			width:"200px", height:"100px", color:"#000"
+		//	|		}
+		//	|	});
+		//
+		//	example:
+		//	Again, only set style as an object hash of styles:
+		//	|	var obj = { color:"#fff", backgroundColor:"#000" };
+		//	|	dojo.attr("someNode", "style", obj);
+		//	|
+		//	|	// though shorter to use `dojo.style()` in this case:
+		//	|	dojo.style("someNode", obj);
+
+		node = byId(node);
+		var args = arguments.length, prop;
+		if(args == 2 && typeof name != "string"){ // inline'd type check
+			// the object form of setter: the 2nd argument is a dictionary
+			for(var x in name){
+				d.attr(node, x, name[x]);
+			}
+			return node; // DomNode
+		}
+		var lc = name.toLowerCase(),
+			propName = _propNames[lc] || name,
+			forceProp = _forcePropNames[propName],
+			attrName = _attrNames[lc] || name;
+		if(args == 3){
+			// setter
+			do{
+				if(propName == "style" && typeof value != "string"){ // inline'd type check
+					// special case: setting a style
+					d.style(node, value);
+					break;
+				}
+				if(propName == "innerHTML"){
+					// special case: assigning HTML
+					//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+					if(d.isIE && node.tagName.toLowerCase() in _roInnerHtml){
+						d.empty(node);
+						node.appendChild(d._toDom(value, node.ownerDocument));
+					}else{
+					//>>excludeEnd("webkitMobile");
+						node[propName] = value;
+					//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+					}
+					//>>excludeEnd("webkitMobile");
+					break;
+				}
+				if(d.isFunction(value)){
+					// special case: assigning an event handler
+					// clobber if we can
+					var attrId = d.attr(node, _attrId);
+					if(!attrId){
+						attrId = _ctr++;
+						d.attr(node, _attrId, attrId);
+					}
+					if(!_evtHdlrMap[attrId]){
+						_evtHdlrMap[attrId] = {};
+					}
+					var h = _evtHdlrMap[attrId][propName];
+					if(h){
+						d.disconnect(h);
+					}else{
+						try{
+							delete node[propName];
+						}catch(e){}
+					}
+					// ensure that event objects are normalized, etc.
+					_evtHdlrMap[attrId][propName] = d.connect(node, propName, value);
+					break;
+				}
+				if(forceProp || typeof value == "boolean"){
+					// special case: forcing assignment to the property
+					// special case: setting boolean to a property instead of attribute
+					node[propName] = value;
+					break;
+				}
+				// node's attribute
+				node.setAttribute(attrName, value);
+			}while(false);
+			return node; // DomNode
+		}
+		// getter
+		// should we access this attribute via a property or
+		// via getAttribute()?
+		value = node[propName];
+		if(forceProp && typeof value != "undefined"){
+			// node's property
+			return value;	// Anything
+		}
+		if(propName != "href" && (typeof value == "boolean" || d.isFunction(value))){
+			// node's property
+			return value;	// Anything
+		}
+		// node's attribute
+		// we need _hasAttr() here to guard against IE returning a default value
+		return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything
+	}
+
+	dojo.removeAttr = function(/*DomNode|String*/ node, /*String*/ name){
+		//	summary:
+		//		Removes an attribute from an HTML element.
+		//	node:
+		//		id or reference to the element to remove the attribute from
+		//	name:
+		//		the name of the attribute to remove
+		byId(node).removeAttribute(_fixAttrName(name));
+	}
+
+	dojo.getNodeProp = function(/*DomNode|String*/ node, /*String*/ name){
+		//	summary:
+		//		Returns an effective value of a property or an attribute.
+		//	node:
+		//		id or reference to the element to remove the attribute from
+		//	name:
+		//		the name of the attribute
+		node = byId(node);
+		var lc = name.toLowerCase(),
+			propName = _propNames[lc] || name;
+		if((propName in node) && propName != "href"){
+			// node's property
+			return node[propName];	// Anything
+		}
+		// node's attribute
+		var attrName = _attrNames[lc] || name;
+		return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything
+	}
+
+	dojo.create = function(tag, attrs, refNode, pos){
+		//	summary:
+		//		Create an element, allowing for optional attribute decoration
+		//		and placement.
+		//
+		// description:
+		//		A DOM Element creation function. A shorthand method for creating a node or
+		//		a fragment, and allowing for a convenient optional attribute setting step,
+		//		as well as an optional DOM placement reference.
+		//|
+		//		Attributes are set by passing the optional object through `dojo.attr`.
+		//		See `dojo.attr` for noted caveats and nuances, and API if applicable.
+		//|
+		//		Placement is done via `dojo.place`, assuming the new node to be the action 
+		//		node, passing along the optional reference node and position.
+		//
+		// tag: String|DomNode
+		//		A string of the element to create (eg: "div", "a", "p", "li", "script", "br"),
+		//		or an existing DOM node to process.
+		//
+		// attrs: Object
+		//		An object-hash of attributes to set on the newly created node.
+		//		Can be null, if you don't want to set any attributes/styles.
+		//		See: `dojo.attr` for a description of available attributes.
+		//
+		// refNode: String?|DomNode?
+		//		Optional reference node. Used by `dojo.place` to place the newly created
+		//		node somewhere in the dom relative to refNode. Can be a DomNode reference
+		//		or String ID of a node.
+		//
+		// pos: String?
+		//		Optional positional reference. Defaults to "last" by way of `dojo.place`,
+		//		though can be set to "first","after","before","last", "replace" or "only"
+		//		to further control the placement of the new node relative to the refNode.
+		//		'refNode' is required if a 'pos' is specified.
+		//
+		// returns: DomNode
+		//
+		// example:
+		//	Create a DIV:
+		//	|	var n = dojo.create("div");
+		//
+		// example:
+		//	Create a DIV with content:
+		//	|	var n = dojo.create("div", { innerHTML:"<p>hi</p>" });
+		//
+		// example:
+		//	Place a new DIV in the BODY, with no attributes set
+		//	|	var n = dojo.create("div", null, dojo.body());
+		//
+		// example:
+		//	Create an UL, and populate it with LI's. Place the list as the first-child of a 
+		//	node with id="someId":
+		//	|	var ul = dojo.create("ul", null, "someId", "first");
+		//	|	var items = ["one", "two", "three", "four"];
+		//	|	dojo.forEach(items, function(data){
+		//	|		dojo.create("li", { innerHTML: data }, ul);
+		//	|	});
+		//
+		// example:
+		//	Create an anchor, with an href. Place in BODY:
+		//	|	dojo.create("a", { href:"foo.html", title:"Goto FOO!" }, dojo.body());
+		//
+		// example:
+		//	Create a `dojo.NodeList()` from a new element (for syntatic sugar):
+		//	|	dojo.query(dojo.create('div'))
+		//	|		.addClass("newDiv")
+		//	|		.onclick(function(e){ console.log('clicked', e.target) })
+		//	|		.place("#someNode"); // redundant, but cleaner.
+
+		var doc = d.doc;
+		if(refNode){
+			refNode = byId(refNode);
+			doc = refNode.ownerDocument;
+		}
+		if(typeof tag == "string"){ // inline'd type check
+			tag = doc.createElement(tag);
+		}
+		if(attrs){ d.attr(tag, attrs); }
+		if(refNode){ d.place(tag, refNode, pos); }
+		return tag; // DomNode
+	}
+
+	/*=====
+	dojo.empty = function(node){
+			//	summary:
+			//		safely removes all children of the node.
+			//	node: DOMNode|String
+			//		a reference to a DOM node or an id.
+			//	example:
+			//	Destroy node's children byId:
+			//	|	dojo.empty("someId");
+			//
+			//	example:
+			//	Destroy all nodes' children in a list by reference:
+			//	|	dojo.query(".someNode").forEach(dojo.empty);
+	}
+	=====*/
+
+	d.empty =
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		d.isIE ?  function(node){
+			node = byId(node);
+			for(var c; c = node.lastChild;){ // intentional assignment
+				d.destroy(c);
+			}
+		} :
+		//>>excludeEnd("webkitMobile");
+		function(node){
+			byId(node).innerHTML = "";
+		};
+
+	/*=====
+	dojo._toDom = function(frag, doc){
+			//	summary:
+			//		instantiates an HTML fragment returning the corresponding DOM.
+			//	frag: String
+			//		the HTML fragment
+			//	doc: DocumentNode?
+			//		optional document to use when creating DOM nodes, defaults to
+			//		dojo.doc if not specified.
+			//	returns: DocumentFragment
+			//
+			//	example:
+			//	Create a table row:
+			//	|	var tr = dojo._toDom("<tr><td>First!</td></tr>");
+	}
+	=====*/
+
+	// support stuff for dojo._toDom
+	var tagWrap = {
+			option: ["select"],
+			tbody: ["table"],
+			thead: ["table"],
+			tfoot: ["table"],
+			tr: ["table", "tbody"],
+			td: ["table", "tbody", "tr"],
+			th: ["table", "thead", "tr"],
+			legend: ["fieldset"],
+			caption: ["table"],
+			colgroup: ["table"],
+			col: ["table", "colgroup"],
+			li: ["ul"]
+		},
+		reTag = /<\s*([\w\:]+)/,
+		masterNode = {}, masterNum = 0,
+		masterName = "__" + d._scopeName + "ToDomId";
+
+	// generate start/end tag strings to use
+	// for the injection for each special tag wrap case.
+	for(var param in tagWrap){
+		var tw = tagWrap[param];
+		tw.pre  = param == "option" ? '<select multiple="multiple">' : "<" + tw.join("><") + ">";
+		tw.post = "</" + tw.reverse().join("></") + ">";
+		// the last line is destructive: it reverses the array,
+		// but we don't care at this point
+	}
+
+	d._toDom = function(frag, doc){
+		//	summary:
+		// 		converts HTML string into DOM nodes.
+
+		doc = doc || d.doc;
+		var masterId = doc[masterName];
+		if(!masterId){
+			doc[masterName] = masterId = ++masterNum + "";
+			masterNode[masterId] = doc.createElement("div");
+		}
+
+		// make sure the frag is a string.
+		frag += "";
+
+		// find the starting tag, and get node wrapper
+		var match = frag.match(reTag),
+			tag = match ? match[1].toLowerCase() : "",
+			master = masterNode[masterId],
+			wrap, i, fc, df;
+		if(match && tagWrap[tag]){
+			wrap = tagWrap[tag];
+			master.innerHTML = wrap.pre + frag + wrap.post;
+			for(i = wrap.length; i; --i){
+				master = master.firstChild;
+			}
+		}else{
+			master.innerHTML = frag;
+		}
+
+		// one node shortcut => return the node itself
+		if(master.childNodes.length == 1){
+			return master.removeChild(master.firstChild); // DOMNode
+		}
+
+		// return multiple nodes as a document fragment
+		df = doc.createDocumentFragment();
+		while(fc = master.firstChild){ // intentional assignment
+			df.appendChild(fc);
+		}
+		return df; // DOMNode
+	}
+
+	// =============================
+	// (CSS) Class Functions
+	// =============================
+	var _className = "className";
+
+	dojo.hasClass = function(/*DomNode|String*/node, /*String*/classStr){
+		//	summary:
+		//		Returns whether or not the specified classes are a portion of the
+		//		class list currently applied to the node.
+		//
+		//	node:
+		//		String ID or DomNode reference to check the class for.
+		//
+		//	classStr:
+		//		A string class name to look for.
+		//
+		//	example:
+		//	Do something if a node with id="someNode" has class="aSillyClassName" present
+		//	|	if(dojo.hasClass("someNode","aSillyClassName")){ ... }
+
+		return ((" "+ byId(node)[_className] +" ").indexOf(" " + classStr + " ") >= 0);  // Boolean
+	};
+
+	var spaces = /\s+/, a1 = [""],
+		str2array = function(s){
+			if(typeof s == "string" || s instanceof String){
+				if(s.indexOf(" ") < 0){
+					a1[0] = s;
+					return a1;
+				}else{
+					return s.split(spaces);
+				}
+			}
+			// assumed to be an array
+			return s || "";
+		};
+
+	dojo.addClass = function(/*DomNode|String*/node, /*String|Array*/classStr){
+		//	summary:
+		//		Adds the specified classes to the end of the class list on the
+		//		passed node. Will not re-apply duplicate classes.
+		//
+		//	node:
+		//		String ID or DomNode reference to add a class string too
+		//
+		//	classStr:
+		//		A String class name to add, or several space-separated class names,
+		//		or an array of class names.
+		//
+		// example:
+		//	Add a class to some node:
+		//	|	dojo.addClass("someNode", "anewClass");
+		//
+		// example:
+		//	Add two classes at once:
+		//	|	dojo.addClass("someNode", "firstClass secondClass");
+		//
+		// example:
+		//	Add two classes at once (using array):
+		//	|	dojo.addClass("someNode", ["firstClass", "secondClass"]);
+		//
+		// example:
+		//	Available in `dojo.NodeList` for multiple additions
+		//	|	dojo.query("ul > li").addClass("firstLevel");
+
+		node = byId(node);
+		classStr = str2array(classStr);
+		var cls = node[_className], oldLen;
+		cls = cls ? " " + cls + " " : " ";
+		oldLen = cls.length;
+		for(var i = 0, len = classStr.length, c; i < len; ++i){
+			c = classStr[i];
+			if(c && cls.indexOf(" " + c + " ") < 0){
+				cls += c + " ";
+			}
+		}
+		if(oldLen < cls.length){
+			node[_className] = cls.substr(1, cls.length - 2);
+		}
+	};
+
+	dojo.removeClass = function(/*DomNode|String*/node, /*String|Array?*/classStr){
+		// summary:
+		//		Removes the specified classes from node. No `dojo.hasClass`
+		//		check is required.
+		//
+		// node:
+		// 		String ID or DomNode reference to remove the class from.
+		//
+		// classStr:
+		//		An optional String class name to remove, or several space-separated
+		//		class names, or an array of class names. If omitted, all class names
+		//		will be deleted.
+		//
+		// example:
+		//	Remove a class from some node:
+		//	|	dojo.removeClass("someNode", "firstClass");
+		//
+		// example:
+		//	Remove two classes from some node:
+		//	|	dojo.removeClass("someNode", "firstClass secondClass");
+		//
+		// example:
+		//	Remove two classes from some node (using array):
+		//	|	dojo.removeClass("someNode", ["firstClass", "secondClass"]);
+		//
+		// example:
+		//	Remove all classes from some node:
+		//	|	dojo.removeClass("someNode");
+		//
+		// example:
+		//	Available in `dojo.NodeList()` for multiple removal
+		//	|	dojo.query(".foo").removeClass("foo");
+
+		node = byId(node);
+		var cls;
+		if(classStr !== undefined){
+			classStr = str2array(classStr);
+			cls = " " + node[_className] + " ";
+			for(var i = 0, len = classStr.length; i < len; ++i){
+				cls = cls.replace(" " + classStr[i] + " ", " ");
+			}
+			cls = d.trim(cls);
+		}else{
+			cls = "";
+		}
+		if(node[_className] != cls){ node[_className] = cls; }
+	};
+
+	dojo.toggleClass = function(/*DomNode|String*/node, /*String|Array*/classStr, /*Boolean?*/condition){
+		//	summary:
+		//		Adds a class to node if not present, or removes if present.
+		//		Pass a boolean condition if you want to explicitly add or remove.
+		//	condition:
+		//		If passed, true means to add the class, false means to remove.
+		//
+		// example:
+		//	|	dojo.toggleClass("someNode", "hovered");
+		//
+		// example:
+		//	Forcefully add a class
+		//	|	dojo.toggleClass("someNode", "hovered", true);
+		//
+		// example:
+		//	Available in `dojo.NodeList()` for multiple toggles
+		//	|	dojo.query(".toggleMe").toggleClass("toggleMe");
+
+		if(condition === undefined){
+			condition = !d.hasClass(node, classStr);
+		}
+		d[condition ? "addClass" : "removeClass"](node, classStr);
+	};
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 })();
-}
+//>>excludeEnd("webkitMobile");
diff --git a/dojo/_base/json.js b/dojo/_base/json.js
index 30bbf1c..5430636 100644
--- a/dojo/_base/json.js
+++ b/dojo/_base/json.js
@@ -1,81 +1,143 @@
-/*
-	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
-*/
+dojo.provide("dojo._base.json");
 
+dojo.fromJson = function(/*String*/ json){
+	// summary:
+	// 		Parses a [JSON](http://json.org) string to return a JavaScript object.
+	// description:
+	// 		Throws for invalid JSON strings, but it does not use a strict JSON parser. It
+	// 		delegates to eval().  The content passed to this method must therefore come
+	//		from a trusted source.
+	// json: 
+	//		a string literal of a JSON item, for instance:
+	//			`'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'`
 
-if(!dojo._hasResource["dojo._base.json"]){
-dojo._hasResource["dojo._base.json"]=true;
-dojo.provide("dojo._base.json");
-dojo.fromJson=function(_1){
-return eval("("+_1+")");
-};
-dojo._escapeString=function(_2){
-return ("\""+_2.replace(/(["\\])/g,"\\$1")+"\"").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r");
-};
-dojo.toJsonIndentStr="\t";
-dojo.toJson=function(it,_3,_4){
-if(it===undefined){
-return "undefined";
-}
-var _5=typeof it;
-if(_5=="number"||_5=="boolean"){
-return it+"";
-}
-if(it===null){
-return "null";
-}
-if(dojo.isString(it)){
-return dojo._escapeString(it);
-}
-var _6=arguments.callee;
-var _7;
-_4=_4||"";
-var _8=_3?_4+dojo.toJsonIndentStr:"";
-var tf=it.__json__||it.json;
-if(dojo.isFunction(tf)){
-_7=tf.call(it);
-if(it!==_7){
-return _6(_7,_3,_8);
-}
-}
-if(it.nodeType&&it.cloneNode){
-throw new Error("Can't serialize DOM nodes");
-}
-var _9=_3?" ":"";
-var _a=_3?"\n":"";
-if(dojo.isArray(it)){
-var _b=dojo.map(it,function(_c){
-var _d=_6(_c,_3,_8);
-if(typeof _d!="string"){
-_d="undefined";
-}
-return _a+_8+_d;
-});
-return "["+_b.join(","+_9)+_a+_4+"]";
+	return eval("(" + json + ")"); // Object
 }
-if(_5=="function"){
-return null;
-}
-var _e=[],_f;
-for(_f in it){
-var _10,val;
-if(typeof _f=="number"){
-_10="\""+_f+"\"";
-}else{
-if(typeof _f=="string"){
-_10=dojo._escapeString(_f);
-}else{
-continue;
-}
-}
-val=_6(it[_f],_3,_8);
-if(typeof val!="string"){
-continue;
-}
-_e.push(_a+_8+_10+":"+_9+val);
+
+dojo._escapeString = function(/*String*/str){
+	//summary:
+	//		Adds escape sequences for non-visual characters, double quote and
+	//		backslash and surrounds with double quotes to form a valid string
+	//		literal.
+	return ('"' + str.replace(/(["\\])/g, '\\$1') + '"').
+		replace(/[\f]/g, "\\f").replace(/[\b]/g, "\\b").replace(/[\n]/g, "\\n").
+		replace(/[\t]/g, "\\t").replace(/[\r]/g, "\\r"); // string
 }
-return "{"+_e.join(","+_9)+_a+_4+"}";
-};
+
+dojo.toJsonIndentStr = "\t";
+dojo.toJson = function(/*Object*/ it, /*Boolean?*/ prettyPrint, /*String?*/ _indentStr){
+	//	summary:
+	//		Returns a [JSON](http://json.org) serialization of an object.
+	//	description:
+	//		Returns a [JSON](http://json.org) serialization of an object.
+	//		Note that this doesn't check for infinite recursion, so don't do that!
+	//	it:
+	//		an object to be serialized. Objects may define their own
+	//		serialization via a special "__json__" or "json" function
+	//		property. If a specialized serializer has been defined, it will
+	//		be used as a fallback.
+	//	prettyPrint:
+	//		if true, we indent objects and arrays to make the output prettier.
+	//		The variable `dojo.toJsonIndentStr` is used as the indent string --
+	//		to use something other than the default (tab), change that variable
+	//		before calling dojo.toJson().
+	//	_indentStr:
+	//		private variable for recursive calls when pretty printing, do not use.
+	//	example:
+	//		simple serialization of a trivial object
+	//		|	var jsonStr = dojo.toJson({ howdy: "stranger!", isStrange: true });
+	//		|	doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr);
+	//	example:
+	//		a custom serializer for an objects of a particular class:
+	//		|	dojo.declare("Furby", null, {
+	//		|		furbies: "are strange",
+	//		|		furbyCount: 10,
+	//		|		__json__: function(){
+	//		|		},
+	//		|	});
+
+	if(it === undefined){
+		return "undefined";
+	}
+	var objtype = typeof it;
+	if(objtype == "number" || objtype == "boolean"){
+		return it + "";
+	}
+	if(it === null){
+		return "null";
+	}
+	if(dojo.isString(it)){ 
+		return dojo._escapeString(it); 
+	}
+	// recurse
+	var recurse = arguments.callee;
+	// short-circuit for objects that support "json" serialization
+	// if they return "self" then just pass-through...
+	var newObj;
+	_indentStr = _indentStr || "";
+	var nextIndent = prettyPrint ? _indentStr + dojo.toJsonIndentStr : "";
+	var tf = it.__json__||it.json;
+	if(dojo.isFunction(tf)){
+		newObj = tf.call(it);
+		if(it !== newObj){
+			return recurse(newObj, prettyPrint, nextIndent);
+		}
+	}
+	if(it.nodeType && it.cloneNode){ // isNode
+		// we can't seriailize DOM nodes as regular objects because they have cycles
+		// DOM nodes could be serialized with something like outerHTML, but
+		// that can be provided by users in the form of .json or .__json__ function.
+		throw new Error("Can't serialize DOM nodes");
+	}
+
+	var sep = prettyPrint ? " " : "";
+	var newLine = prettyPrint ? "\n" : "";
+
+	// array
+	if(dojo.isArray(it)){
+		var res = dojo.map(it, function(obj){
+			var val = recurse(obj, prettyPrint, nextIndent);
+			if(typeof val != "string"){
+				val = "undefined";
+			}
+			return newLine + nextIndent + val;
+		});
+		return "[" + res.join("," + sep) + newLine + _indentStr + "]";
+	}
+	/*
+	// look in the registry
+	try {
+		window.o = it;
+		newObj = dojo.json.jsonRegistry.match(it);
+		return recurse(newObj, prettyPrint, nextIndent);
+	}catch(e){
+		// console.log(e);
+	}
+	// it's a function with no adapter, skip it
+	*/
+	if(objtype == "function"){
+		return null; // null
+	}
+	// generic object code path
+	var output = [], key;
+	for(key in it){
+		var keyStr, val;
+		if(typeof key == "number"){
+			keyStr = '"' + key + '"';
+		}else if(typeof key == "string"){
+			keyStr = dojo._escapeString(key);
+		}else{
+			// skip non-string or number keys
+			continue;
+		}
+		val = recurse(it[key], prettyPrint, nextIndent);
+		if(typeof val != "string"){
+			// skip non-serializable values
+			continue;
+		}
+		// FIXME: use += on Moz!!
+		//	 MOW NOTE: using += is a pain because you have to account for the dangling comma...
+		output.push(newLine + nextIndent + keyStr + ":" + sep + val);
+	}
+	return "{" + output.join("," + sep) + newLine + _indentStr + "}"; // String
 }
diff --git a/dojo/_base/lang.js b/dojo/_base/lang.js
index 692c7fa..839ee4d 100644
--- a/dojo/_base/lang.js
+++ b/dojo/_base/lang.js
@@ -1,148 +1,387 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.lang"]){
-dojo._hasResource["dojo._base.lang"]=true;
 dojo.provide("dojo._base.lang");
+
 (function(){
-var d=dojo,_1=Object.prototype.toString;
-dojo.isString=function(it){
-return (typeof it=="string"||it instanceof String);
-};
-dojo.isArray=function(it){
-return it&&(it instanceof Array||typeof it=="array");
-};
-dojo.isFunction=function(it){
-return _1.call(it)==="[object Function]";
-};
-dojo.isObject=function(it){
-return it!==undefined&&(it===null||typeof it=="object"||d.isArray(it)||d.isFunction(it));
-};
-dojo.isArrayLike=function(it){
-return it&&it!==undefined&&!d.isString(it)&&!d.isFunction(it)&&!(it.tagName&&it.tagName.toLowerCase()=="form")&&(d.isArray(it)||isFinite(it.length));
-};
-dojo.isAlien=function(it){
-return it&&!d.isFunction(it)&&/\{\s*\[native code\]\s*\}/.test(String(it));
-};
-dojo.extend=function(_2,_3){
-for(var i=1,l=arguments.length;i<l;i++){
-d._mixin(_2.prototype,arguments[i]);
-}
-return _2;
-};
-dojo._hitchArgs=function(_4,_5){
-var _6=d._toArray(arguments,2);
-var _7=d.isString(_5);
-return function(){
-var _8=d._toArray(arguments);
-var f=_7?(_4||d.global)[_5]:_5;
-return f&&f.apply(_4||this,_6.concat(_8));
-};
-};
-dojo.hitch=function(_9,_a){
-if(arguments.length>2){
-return d._hitchArgs.apply(d,arguments);
-}
-if(!_a){
-_a=_9;
-_9=null;
-}
-if(d.isString(_a)){
-_9=_9||d.global;
-if(!_9[_a]){
-throw (["dojo.hitch: scope[\"",_a,"\"] is null (scope=\"",_9,"\")"].join(""));
-}
-return function(){
-return _9[_a].apply(_9,arguments||[]);
-};
-}
-return !_9?_a:function(){
-return _a.apply(_9,arguments||[]);
-};
-};
-dojo.delegate=dojo._delegate=(function(){
-function _b(){
-};
-return function(_c,_d){
-_b.prototype=_c;
-var _e=new _b();
-_b.prototype=null;
-if(_d){
-d._mixin(_e,_d);
-}
-return _e;
-};
-})();
-var _f=function(obj,_10,_11){
-return (_11||[]).concat(Array.prototype.slice.call(obj,_10||0));
-};
-var _12=function(obj,_13,_14){
-var arr=_14||[];
-for(var x=_13||0;x<obj.length;x++){
-arr.push(obj[x]);
-}
-return arr;
-};
-dojo._toArray=d.isIE?function(obj){
-return ((obj.item)?_12:_f).apply(this,arguments);
-}:_f;
-dojo.partial=function(_15){
-var arr=[null];
-return d.hitch.apply(d,arr.concat(d._toArray(arguments)));
-};
-var _16=d._extraNames,_17=_16.length,_18={};
-dojo.clone=function(o){
-if(!o||typeof o!="object"||d.isFunction(o)){
-return o;
-}
-if(o.nodeType&&"cloneNode" in o){
-return o.cloneNode(true);
-}
-if(o instanceof Date){
-return new Date(o.getTime());
-}
-var r,i,l,s,_19;
-if(d.isArray(o)){
-r=[];
-for(i=0,l=o.length;i<l;++i){
-if(i in o){
-r.push(d.clone(o[i]));
-}
-}
-}else{
-r=o.constructor?new o.constructor():{};
-}
-for(_19 in o){
-s=o[_19];
-if(!(_19 in r)||(r[_19]!==s&&(!(_19 in _18)||_18[_19]!==s))){
-r[_19]=d.clone(s);
-}
-}
-if(_17){
-for(i=0;i<_17;++i){
-_19=_16[i];
-s=o[_19];
-if(!(_19 in r)||(r[_19]!==s&&(!(_19 in _18)||_18[_19]!==s))){
-r[_19]=s;
-}
-}
-}
-return r;
-};
-dojo.trim=String.prototype.trim?function(str){
-return str.trim();
-}:function(str){
-return str.replace(/^\s\s*/,"").replace(/\s\s*$/,"");
-};
-var _1a=/\{([^\}]+)\}/g;
-dojo.replace=function(_1b,map,_1c){
-return _1b.replace(_1c||_1a,d.isFunction(map)?map:function(_1d,k){
-return d.getObject(k,false,map);
-});
-};
+	var d = dojo, opts = Object.prototype.toString;
+
+	// Crockford (ish) functions
+
+	dojo.isString = function(/*anything*/ it){
+		//	summary:
+		//		Return true if it is a String
+		return (typeof it == "string" || it instanceof String); // Boolean
+	}
+
+	dojo.isArray = function(/*anything*/ it){
+		//	summary:
+		//		Return true if it is an Array.
+		//		Does not work on Arrays created in other windows.
+		return it && (it instanceof Array || typeof it == "array"); // Boolean
+	}
+
+	dojo.isFunction = function(/*anything*/ it){
+		// summary:
+		//		Return true if it is a Function
+		return opts.call(it) === "[object Function]";
+	};
+
+	dojo.isObject = function(/*anything*/ it){
+		// summary:
+		//		Returns true if it is a JavaScript object (or an Array, a Function
+		//		or null)
+		return it !== undefined &&
+			(it === null || typeof it == "object" || d.isArray(it) || d.isFunction(it)); // Boolean
+	}
+
+	dojo.isArrayLike = function(/*anything*/ it){
+		//	summary:
+		//		similar to dojo.isArray() but more permissive
+		//	description:
+		//		Doesn't strongly test for "arrayness".  Instead, settles for "isn't
+		//		a string or number and has a length property". Arguments objects
+		//		and DOM collections will return true when passed to
+		//		dojo.isArrayLike(), but will return false when passed to
+		//		dojo.isArray().
+		//	returns:
+		//		If it walks like a duck and quacks like a duck, return `true`
+		return it && it !== undefined && // Boolean
+			// keep out built-in constructors (Number, String, ...) which have length
+			// properties
+			!d.isString(it) && !d.isFunction(it) &&
+			!(it.tagName && it.tagName.toLowerCase() == 'form') &&
+			(d.isArray(it) || isFinite(it.length));
+	}
+
+	dojo.isAlien = function(/*anything*/ it){
+		// summary:
+		//		Returns true if it is a built-in function or some other kind of
+		//		oddball that *should* report as a function but doesn't
+		return it && !d.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean
+	}
+
+	dojo.extend = function(/*Object*/ constructor, /*Object...*/ props){
+		// summary:
+		//		Adds all properties and methods of props to constructor's
+		//		prototype, making them available to all instances created with
+		//		constructor.
+		for(var i=1, l=arguments.length; i<l; i++){
+			d._mixin(constructor.prototype, arguments[i]);
+		}
+		return constructor; // Object
+	}
+
+	dojo._hitchArgs = function(scope, method /*,...*/){
+		var pre = d._toArray(arguments, 2);
+		var named = d.isString(method);
+		return function(){
+			// arrayify arguments
+			var args = d._toArray(arguments);
+			// locate our method
+			var f = named ? (scope||d.global)[method] : method;
+			// invoke with collected args
+			return f && f.apply(scope || this, pre.concat(args)); // mixed
+		} // Function
+	}
+
+	dojo.hitch = function(/*Object*/scope, /*Function|String*/method /*,...*/){
+		//	summary:
+		//		Returns a function that will only ever execute in the a given scope.
+		//		This allows for easy use of object member functions
+		//		in callbacks and other places in which the "this" keyword may
+		//		otherwise not reference the expected scope.
+		//		Any number of default positional arguments may be passed as parameters 
+		//		beyond "method".
+		//		Each of these values will be used to "placehold" (similar to curry)
+		//		for the hitched function.
+		//	scope:
+		//		The scope to use when method executes. If method is a string,
+		//		scope is also the object containing method.
+		//	method:
+		//		A function to be hitched to scope, or the name of the method in
+		//		scope to be hitched.
+		//	example:
+		//	|	dojo.hitch(foo, "bar")();
+		//		runs foo.bar() in the scope of foo
+		//	example:
+		//	|	dojo.hitch(foo, myFunction);
+		//		returns a function that runs myFunction in the scope of foo
+		//	example:
+		//		Expansion on the default positional arguments passed along from
+		//		hitch. Passed args are mixed first, additional args after.
+		//	|	var foo = { bar: function(a, b, c){ console.log(a, b, c); } };
+		//	|	var fn = dojo.hitch(foo, "bar", 1, 2);
+		//	|	fn(3); // logs "1, 2, 3"
+		//	example:
+		//	|	var foo = { bar: 2 };
+		//	|	dojo.hitch(foo, function(){ this.bar = 10; })();
+		//		execute an anonymous function in scope of foo
+		
+		if(arguments.length > 2){
+			return d._hitchArgs.apply(d, arguments); // Function
+		}
+		if(!method){
+			method = scope;
+			scope = null;
+		}
+		if(d.isString(method)){
+			scope = scope || d.global;
+			if(!scope[method]){ throw(['dojo.hitch: scope["', method, '"] is null (scope="', scope, '")'].join('')); }
+			return function(){ return scope[method].apply(scope, arguments || []); }; // Function
+		}
+		return !scope ? method : function(){ return method.apply(scope, arguments || []); }; // Function
+	}
+
+	/*=====
+	dojo.delegate = function(obj, props){
+		//	summary:
+		//		Returns a new object which "looks" to obj for properties which it
+		//		does not have a value for. Optionally takes a bag of properties to
+		//		seed the returned object with initially.
+		//	description:
+		//		This is a small implementaton of the Boodman/Crockford delegation
+		//		pattern in JavaScript. An intermediate object constructor mediates
+		//		the prototype chain for the returned object, using it to delegate
+		//		down to obj for property lookup when object-local lookup fails.
+		//		This can be thought of similarly to ES4's "wrap", save that it does
+		//		not act on types but rather on pure objects.
+		//	obj:
+		//		The object to delegate to for properties not found directly on the
+		//		return object or in props.
+		//	props:
+		//		an object containing properties to assign to the returned object
+		//	returns:
+		//		an Object of anonymous type
+		//	example:
+		//	|	var foo = { bar: "baz" };
+		//	|	var thinger = dojo.delegate(foo, { thud: "xyzzy"});
+		//	|	thinger.bar == "baz"; // delegated to foo
+		//	|	foo.thud == undefined; // by definition
+		//	|	thinger.thud == "xyzzy"; // mixed in from props
+		//	|	foo.bar = "thonk";
+		//	|	thinger.bar == "thonk"; // still delegated to foo's bar
+	}
+	=====*/
+
+	dojo.delegate = dojo._delegate = (function(){
+		// boodman/crockford delegation w/ cornford optimization
+		function TMP(){}
+		return function(obj, props){
+			TMP.prototype = obj;
+			var tmp = new TMP();
+			TMP.prototype = null;
+			if(props){
+				d._mixin(tmp, props);
+			}
+			return tmp; // Object
+		}
+	})();
+
+	/*=====
+	dojo._toArray = function(obj, offset, startWith){
+		//	summary:
+		//		Converts an array-like object (i.e. arguments, DOMCollection) to an
+		//		array. Returns a new Array with the elements of obj.
+		//	obj: Object
+		//		the object to "arrayify". We expect the object to have, at a
+		//		minimum, a length property which corresponds to integer-indexed
+		//		properties.
+		//	offset: Number?
+		//		the location in obj to start iterating from. Defaults to 0.
+		//		Optional.
+		//	startWith: Array?
+		//		An array to pack with the properties of obj. If provided,
+		//		properties in obj are appended at the end of startWith and
+		//		startWith is the returned array.
+	}
+	=====*/
+
+	var efficient = function(obj, offset, startWith){
+		return (startWith||[]).concat(Array.prototype.slice.call(obj, offset||0));
+	};
+
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	var slow = function(obj, offset, startWith){
+		var arr = startWith||[];
+		for(var x = offset || 0; x < obj.length; x++){
+			arr.push(obj[x]);
+		}
+		return arr;
+	};
+	//>>excludeEnd("webkitMobile");
+
+	dojo._toArray =
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		d.isIE ?  function(obj){
+			return ((obj.item) ? slow : efficient).apply(this, arguments);
+		} :
+		//>>excludeEnd("webkitMobile");
+		efficient;
+
+	dojo.partial = function(/*Function|String*/method /*, ...*/){
+		//	summary:
+		//		similar to hitch() except that the scope object is left to be
+		//		whatever the execution context eventually becomes.
+		//	description:
+		//		Calling dojo.partial is the functional equivalent of calling:
+		//		|	dojo.hitch(null, funcName, ...);
+		var arr = [ null ];
+		return d.hitch.apply(d, arr.concat(d._toArray(arguments))); // Function
+	}
+
+	var extraNames = d._extraNames, extraLen = extraNames.length, empty = {};
+
+	dojo.clone = function(/*anything*/ o){
+		// summary:
+		//		Clones objects (including DOM nodes) and all children.
+		//		Warning: do not clone cyclic structures.
+		if(!o || typeof o != "object" || d.isFunction(o)){
+			// null, undefined, any non-object, or function
+			return o;	// anything
+		}
+		if(o.nodeType && "cloneNode" in o){
+			// DOM Node
+			return o.cloneNode(true); // Node
+		}
+		if(o instanceof Date){
+			// Date
+			return new Date(o.getTime());	// Date
+		}
+		var r, i, l, s, name;
+		if(d.isArray(o)){
+			// array
+			r = [];
+			for(i = 0, l = o.length; i < l; ++i){
+				if(i in o){
+					r.push(d.clone(o[i]));
+				}
+			}
+// we don't clone functions for performance reasons
+//		}else if(d.isFunction(o)){
+//			// function
+//			r = function(){ return o.apply(this, arguments); };
+		}else{
+			// generic objects
+			r = o.constructor ? new o.constructor() : {};
+		}
+		for(name in o){
+			// the "tobj" condition avoid copying properties in "source"
+			// inherited from Object.prototype.  For example, if target has a custom
+			// toString() method, don't overwrite it with the toString() method
+			// that source inherited from Object.prototype
+			s = o[name];
+			if(!(name in r) || (r[name] !== s && (!(name in empty) || empty[name] !== s))){
+				r[name] = d.clone(s);
+			}
+		}
+		//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+		// IE doesn't recognize some custom functions in for..in
+		if(extraLen){
+			for(i = 0; i < extraLen; ++i){
+				name = extraNames[i];
+				s = o[name];
+				if(!(name in r) || (r[name] !== s && (!(name in empty) || empty[name] !== s))){
+					r[name] = s; // functions only, we don't clone them
+				}
+			}
+		}
+		//>>excludeEnd("webkitMobile");
+		return r; // Object
+	}
+
+	/*=====
+	dojo.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 selected for inclusion into the base due
+		//		to its compact size and relatively good performance
+		//		(see [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript)
+		//		Uses String.prototype.trim instead, if available.
+		//		The fastest but longest version of this function is located at
+		//		dojo.string.trim()
+		return "";	// String
+	}
+	=====*/
+
+	dojo.trim = String.prototype.trim ?
+		function(str){ return str.trim(); } :
+		function(str){ return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); };
+
+	/*=====
+	dojo.replace = function(tmpl, map, pattern){
+		//	summary:
+		//		Performs parameterized substitutions on a string. Throws an
+		//		exception if any parameter is unmatched. 
+		//	tmpl: String
+		//		String to be used as a template.
+		//	map: Object|Function
+		//		If an object, it is used as a dictionary to look up substitutions.
+		//		If a function, it is called for every substitution with following
+		//		parameters: a whole match, a name, an offset, and the whole template
+		//		string (see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/replace
+		//		for more details).
+		//	pattern: RegEx?
+		//		Optional regular expression objects that overrides the default pattern.
+		//		Must be global and match one item. The default is: /\{([^\}]+)\}/g,
+		//		which matches patterns like that: "{xxx}", where "xxx" is any sequence
+		//		of characters, which doesn't include "}".
+		//	returns: String
+		//		Returns the substituted string.
+		//	example:
+		//	|	// uses a dictionary for substitutions:
+		//	|	dojo.replace("Hello, {name.first} {name.last} AKA {nick}!",
+		//	|	  {
+		//	|	    nick: "Bob",
+		//	|	    name: {
+		//	|	      first:  "Robert",
+		//	|	      middle: "X",
+		//	|	      last:   "Cringely"
+		//	|	    }
+		//	|	  });
+		//	|	// returns: Hello, Robert Cringely AKA Bob!
+		//	example:
+		//	|	// uses an array for substitutions:
+		//	|	dojo.replace("Hello, {0} {2}!",
+		//	|	  ["Robert", "X", "Cringely"]);
+		//	|	// returns: Hello, Robert Cringely!
+		//	example:
+		//	|	// uses a function for substitutions:
+		//	|	function sum(a){
+		//	|	  var t = 0;
+		//	|	  dojo.forEach(a, function(x){ t += x; });
+		//	|	  return t;
+		//	|	}
+		//	|	dojo.replace(
+		//	|	  "{count} payments averaging {avg} USD per payment.",
+		//	|	  dojo.hitch(
+		//	|	    { payments: [11, 16, 12] },
+		//	|	    function(_, key){
+		//	|	      switch(key){
+		//	|	        case "count": return this.payments.length;
+		//	|	        case "min":   return Math.min.apply(Math, this.payments);
+		//	|	        case "max":   return Math.max.apply(Math, this.payments);
+		//	|	        case "sum":   return sum(this.payments);
+		//	|	        case "avg":   return sum(this.payments) / this.payments.length;
+		//	|	      }
+		//	|	    }
+		//	|	  )
+		//	|	);
+		//	|	// prints: 3 payments averaging 13 USD per payment.
+		//	example:
+		//	|	// uses an alternative PHP-like pattern for substitutions:
+		//	|	dojo.replace("Hello, ${0} ${2}!",
+		//	|	  ["Robert", "X", "Cringely"], /\$\{([^\}]+)\}/g);
+		//	|	// returns: Hello, Robert Cringely!
+		return "";	// String
+	}
+	=====*/
+
+	var _pattern = /\{([^\}]+)\}/g;
+	dojo.replace = function(tmpl, map, pattern){
+		return tmpl.replace(pattern || _pattern, d.isFunction(map) ?
+			map : function(_, k){ return d.getObject(k, false, map); });
+	};
 })();
-}
diff --git a/dojo/_base/query-sizzle.js b/dojo/_base/query-sizzle.js
index 67d8f61..ba7fe3e 100644
--- a/dojo/_base/query-sizzle.js
+++ b/dojo/_base/query-sizzle.js
@@ -1,628 +1,858 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.query"]){
-dojo._hasResource["dojo._base.query"]=true;
-if(typeof dojo!="undefined"){
-dojo.provide("dojo._base.query");
-dojo.require("dojo._base.NodeList");
-dojo.query=function(_1,_2,_3){
-_3=_3||dojo.NodeList;
-if(!_1){
-return new _3();
-}
-if(_1.constructor==_3){
-return _1;
-}
-if(!dojo.isString(_1)){
-return new _3(_1);
-}
-if(dojo.isString(_2)){
-_2=dojo.byId(_2);
-if(!_2){
-return new _3();
-}
-}
-return dojo.Sizzle(_1,_2,new _3());
-};
-dojo._filterQueryResult=function(_4,_5){
-return dojo.Sizzle.filter(_5,_4);
-};
-}
-(function(ns){
-var _6=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|[^[\]]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,_7=0,_8=Object.prototype.toString;
-var _9=function(_a,_b,_c,_d){
-_c=_c||[];
-_b=_b||document;
-if(_b.nodeType!==1&&_b.nodeType!==9){
-return [];
-}
-if(!_a||typeof _a!=="string"){
-return _c;
-}
-var _e=[],m,_f,_10,_11,_12,_13,_14=true;
-_6.lastIndex=0;
-while((m=_6.exec(_a))!==null){
-_e.push(m[1]);
-if(m[2]){
-_13=RegExp.rightContext;
-break;
-}
-}
-if(_e.length>1&&_15.match.POS.exec(_a)){
-if(_e.length===2&&_15.relative[_e[0]]){
-var _16="",_17;
-while((_17=_15.match.POS.exec(_a))){
-_16+=_17[0];
-_a=_a.replace(_15.match.POS,"");
-}
-_f=_9.filter(_16,_9(_a,_b));
-}else{
-_f=_15.relative[_e[0]]?[_b]:_9(_e.shift(),_b);
-while(_e.length){
-var _18=[];
-_a=_e.shift();
-if(_15.relative[_a]){
-_a+=_e.shift();
-}
-for(var i=0,l=_f.length;i<l;i++){
-_9(_a,_f[i],_18);
-}
-_f=_18;
-}
-}
-}else{
-var ret=_d?{expr:_e.pop(),set:_19(_d)}:_9.find(_e.pop(),_e.length===1&&_b.parentNode?_b.parentNode:_b);
-_f=_9.filter(ret.expr,ret.set);
-if(_e.length>0){
-_10=_19(_f);
-}else{
-_14=false;
-}
-while(_e.length){
-var cur=_e.pop(),pop=cur;
-if(!_15.relative[cur]){
-cur="";
-}else{
-pop=_e.pop();
-}
-if(pop==null){
-pop=_b;
-}
-_15.relative[cur](_10,pop);
-}
-}
-if(!_10){
-_10=_f;
-}
-if(!_10){
-throw "Syntax error, unrecognized expression: "+(cur||_a);
-}
-if(_8.call(_10)==="[object Array]"){
-if(!_14){
-_c.push.apply(_c,_10);
-}else{
-if(_b.nodeType===1){
-for(var i=0;_10[i]!=null;i++){
-if(_10[i]&&(_10[i]===true||_10[i].nodeType===1&&_1a(_b,_10[i]))){
-_c.push(_f[i]);
-}
-}
-}else{
-for(var i=0;_10[i]!=null;i++){
-if(_10[i]&&_10[i].nodeType===1){
-_c.push(_f[i]);
-}
-}
-}
-}
-}else{
-_19(_10,_c);
-}
-if(_13){
-_9(_13,_b,_c,_d);
+/*!
+ * Sizzle CSS Selector Engine - v0.9
+ *  Copyright 2009, John Resig
+ *  Redistributed with the Dojo Toolkit under the terms of the New BSD license.
+ *  More information: http://sizzlejs.com/
+ *
+ *  This version from github, dated 1/23/2009, commit: e374a73bbffc12ec3b5f252e7f76e593c508dfa5
+ *  Modified for dojo loader, and to fit into dojo namespace. This was done by passing
+ *  dojo object to anonymous function, then assigning Sizzle to dojo.Sizzle instead of window.Sizzle.
+ *  Then an alias for dojo.query and dojo._filterQueryResult(). dojo.psuedos is not mapped.
+ *  Finally, dojo.provide/require added.
+ */
+
+//This file gets copied to dojo/_base/query.js, so set the provide accordingly.
+if(typeof dojo != "undefined"){
+	dojo.provide("dojo._base.query");
+	dojo.require("dojo._base.NodeList");
+
+	//Start Dojo mappings.
+	dojo.query = function(/*String*/ query, /*String|DOMNode?*/ root, /*Function?*/listCtor){
+		listCtor = listCtor || dojo.NodeList;
+
+		if(!query){
+			return new listCtor();
+		}
+
+		if(query.constructor == listCtor){
+			return query;
+		}
+		if(!dojo.isString(query)){
+			return new listCtor(query); // dojo.NodeList
+		}
+		if(dojo.isString(root)){
+			root = dojo.byId(root);
+			if(!root){ return new listCtor(); }
+		}
+
+		return dojo.Sizzle(query, root, new listCtor());
+	}
+
+	dojo._filterQueryResult = function(nodeList, simpleFilter){
+		return dojo.Sizzle.filter(simpleFilter, nodeList);
+	}
 }
-return _c;
+
+//Main Sizzle code follows...
+//ns argument, added for dojo, used at the end of the file.
+;(function(ns){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|[^[\]]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,
+	done = 0,
+	toString = Object.prototype.toString;
+
+var Sizzle = function(selector, context, results, seed) {
+	results = results || [];
+	context = context || document;
+
+	if ( context.nodeType !== 1 && context.nodeType !== 9 )
+		return [];
+	
+	if ( !selector || typeof selector !== "string" ) {
+		return results;
+	}
+
+	var parts = [], m, set, checkSet, check, mode, extra, prune = true;
+	
+	// Reset the position of the chunker regexp (start from head)
+	chunker.lastIndex = 0;
+	
+	while ( (m = chunker.exec(selector)) !== null ) {
+		parts.push( m[1] );
+		
+		if ( m[2] ) {
+			extra = RegExp.rightContext;
+			break;
+		}
+	}
+
+	if ( parts.length > 1 && Expr.match.POS.exec( selector ) ) {
+		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+			var later = "", match;
+
+			// Position selectors must be done after the filter
+			while ( (match = Expr.match.POS.exec( selector )) ) {
+				later += match[0];
+				selector = selector.replace( Expr.match.POS, "" );
+			}
+
+			set = Sizzle.filter( later, Sizzle( selector, context ) );
+		} else {
+			set = Expr.relative[ parts[0] ] ?
+				[ context ] :
+				Sizzle( parts.shift(), context );
+
+			while ( parts.length ) {
+				var tmpSet = [];
+
+				selector = parts.shift();
+				if ( Expr.relative[ selector ] )
+					selector += parts.shift();
+
+				for ( var i = 0, l = set.length; i < l; i++ ) {
+					Sizzle( selector, set[i], tmpSet );
+				}
+
+				set = tmpSet;
+			}
+		}
+	} else {
+		var ret = seed ?
+			{ expr: parts.pop(), set: makeArray(seed) } :
+			Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context );
+		set = Sizzle.filter( ret.expr, ret.set );
+
+		if ( parts.length > 0 ) {
+			checkSet = makeArray(set);
+		} else {
+			prune = false;
+		}
+
+		while ( parts.length ) {
+			var cur = parts.pop(), pop = cur;
+
+			if ( !Expr.relative[ cur ] ) {
+				cur = "";
+			} else {
+				pop = parts.pop();
+			}
+
+			if ( pop == null ) {
+				pop = context;
+			}
+
+			Expr.relative[ cur ]( checkSet, pop );
+		}
+	}
+
+	if ( !checkSet ) {
+		checkSet = set;
+	}
+
+	if ( !checkSet ) {
+		throw "Syntax error, unrecognized expression: " + (cur || selector);
+	}
+
+	if ( toString.call(checkSet) === "[object Array]" ) {
+		if ( !prune ) {
+			results.push.apply( results, checkSet );
+		} else if ( context.nodeType === 1 ) {
+			for ( var i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
+					results.push( set[i] );
+				}
+			}
+		} else {
+			for ( var i = 0; checkSet[i] != null; i++ ) {
+				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+					results.push( set[i] );
+				}
+			}
+		}
+	} else {
+		makeArray( checkSet, results );
+	}
+
+	if ( extra ) {
+		Sizzle( extra, context, results, seed );
+	}
+
+	return results;
 };
-_9.matches=function(_1b,set){
-return _9(_1b,null,null,set);
+
+Sizzle.matches = function(expr, set){
+	return Sizzle(expr, null, null, set);
 };
-_9.find=function(_1c,_1d){
-var set,_1e;
-if(!_1c){
-return [];
-}
-for(var i=0,l=_15.order.length;i<l;i++){
-var _1f=_15.order[i],_1e;
-if((_1e=_15.match[_1f].exec(_1c))){
-var _20=RegExp.leftContext;
-if(_20.substr(_20.length-1)!=="\\"){
-_1e[1]=(_1e[1]||"").replace(/\\/g,"");
-set=_15.find[_1f](_1e,_1d);
-if(set!=null){
-_1c=_1c.replace(_15.match[_1f],"");
-break;
-}
-}
-}
-}
-if(!set){
-set=_1d.getElementsByTagName("*");
-}
-return {set:set,expr:_1c};
+
+Sizzle.find = function(expr, context){
+	var set, match;
+
+	if ( !expr ) {
+		return [];
+	}
+
+	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+		var type = Expr.order[i], match;
+		
+		if ( (match = Expr.match[ type ].exec( expr )) ) {
+			var left = RegExp.leftContext;
+
+			if ( left.substr( left.length - 1 ) !== "\\" ) {
+				match[1] = (match[1] || "").replace(/\\/g, "");
+				set = Expr.find[ type ]( match, context );
+				if ( set != null ) {
+					expr = expr.replace( Expr.match[ type ], "" );
+					break;
+				}
+			}
+		}
+	}
+
+	if ( !set ) {
+		set = context.getElementsByTagName("*");
+	}
+
+	return {set: set, expr: expr};
 };
-_9.filter=function(_21,set,_22,not){
-var old=_21,_23=[],_24=set,_25,_26;
-while(_21&&set.length){
-for(var _27 in _15.filter){
-if((_25=_15.match[_27].exec(_21))!=null){
-var _28=_15.filter[_27],_29=null,_2a=0,_2b,_2c;
-_26=false;
-if(_24==_23){
-_23=[];
-}
-if(_15.preFilter[_27]){
-_25=_15.preFilter[_27](_25,_24,_22,_23,not);
-if(!_25){
-_26=_2b=true;
-}else{
-if(_25[0]===true){
-_29=[];
-var _2d=null,_2e;
-for(var i=0;(_2e=_24[i])!==undefined;i++){
-if(_2e&&_2d!==_2e){
-_29.push(_2e);
-_2d=_2e;
-}
-}
-}
-}
-}
-if(_25){
-for(var i=0;(_2c=_24[i])!==undefined;i++){
-if(_2c){
-if(_29&&_2c!=_29[_2a]){
-_2a++;
-}
-_2b=_28(_2c,_25,_2a,_29);
-var _2f=not^!!_2b;
-if(_22&&_2b!=null){
-if(_2f){
-_26=true;
-}else{
-_24[i]=false;
-}
-}else{
-if(_2f){
-_23.push(_2c);
-_26=true;
-}
-}
-}
-}
-}
-if(_2b!==undefined){
-if(!_22){
-_24=_23;
-}
-_21=_21.replace(_15.match[_27],"");
-if(!_26){
-return [];
-}
-break;
-}
-}
-}
-_21=_21.replace(/\s*,\s*/,"");
-if(_21==old){
-if(_26==null){
-throw "Syntax error, unrecognized expression: "+_21;
-}else{
-break;
-}
-}
-old=_21;
-}
-return _24;
+
+Sizzle.filter = function(expr, set, inplace, not){
+	var old = expr, result = [], curLoop = set, match, anyFound;
+
+	while ( expr && set.length ) {
+		for ( var type in Expr.filter ) {
+			if ( (match = Expr.match[ type ].exec( expr )) != null ) {
+				var filter = Expr.filter[ type ], goodArray = null, goodPos = 0, found, item;
+				anyFound = false;
+
+				if ( curLoop == result ) {
+					result = [];
+				}
+
+				if ( Expr.preFilter[ type ] ) {
+					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not );
+
+					if ( !match ) {
+						anyFound = found = true;
+					} else if ( match[0] === true ) {
+						goodArray = [];
+						var last = null, elem;
+						for ( var i = 0; (elem = curLoop[i]) !== undefined; i++ ) {
+							if ( elem && last !== elem ) {
+								goodArray.push( elem );
+								last = elem;
+							}
+						}
+					}
+				}
+
+				if ( match ) {
+					for ( var i = 0; (item = curLoop[i]) !== undefined; i++ ) {
+						if ( item ) {
+							if ( goodArray && item != goodArray[goodPos] ) {
+								goodPos++;
+							}
+	
+							found = filter( item, match, goodPos, goodArray );
+							var pass = not ^ !!found;
+
+							if ( inplace && found != null ) {
+								if ( pass ) {
+									anyFound = true;
+								} else {
+									curLoop[i] = false;
+								}
+							} else if ( pass ) {
+								result.push( item );
+								anyFound = true;
+							}
+						}
+					}
+				}
+
+				if ( found !== undefined ) {
+					if ( !inplace ) {
+						curLoop = result;
+					}
+
+					expr = expr.replace( Expr.match[ type ], "" );
+
+					if ( !anyFound ) {
+						return [];
+					}
+
+					break;
+				}
+			}
+		}
+
+		expr = expr.replace(/\s*,\s*/, "");
+
+		// Improper expression
+		if ( expr == old ) {
+			if ( anyFound == null ) {
+				throw "Syntax error, unrecognized expression: " + expr;
+			} else {
+				break;
+			}
+		}
+
+		old = expr;
+	}
+
+	return curLoop;
 };
-var _15=_9.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u0128-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u0128-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u0128-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[((?:[\w\u0128-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\]/,TAG:/^((?:[\w\u0128-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child\(?(even|odd|[\dn+-]*)\)?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)\(?(\d*)\)?(?:[^-]|$)/,PSEUDO:/:((?:[\w\u0128-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\ [...]
-for(var i=0,l=_30.length;i<l;i++){
-var _32=_30[i];
-if(_32){
-var cur=_32.previousSibling;
-while(cur&&cur.nodeType!==1){
-cur=cur.previousSibling;
-}
-_30[i]=typeof _31==="string"?cur||false:cur===_31;
-}
-}
-if(typeof _31==="string"){
-_9.filter(_31,_30,true);
-}
-},">":function(_33,_34){
-if(typeof _34==="string"&&!/\W/.test(_34)){
-_34=_34.toUpperCase();
-for(var i=0,l=_33.length;i<l;i++){
-var _35=_33[i];
-if(_35){
-var _36=_35.parentNode;
-_33[i]=_36.nodeName===_34?_36:false;
-}
-}
-}else{
-for(var i=0,l=_33.length;i<l;i++){
-var _35=_33[i];
-if(_35){
-_33[i]=typeof _34==="string"?_35.parentNode:_35.parentNode===_34;
-}
-}
-if(typeof _34==="string"){
-_9.filter(_34,_33,true);
-}
-}
-},"":function(_37,_38){
-var _39="done"+(_7++),_3a=_3b;
-if(!_38.match(/\W/)){
-var _3c=_38=_38.toUpperCase();
-_3a=_3d;
-}
-_3a("parentNode",_38,_39,_37,_3c);
-},"~":function(_3e,_3f){
-var _40="done"+(_7++),_41=_3b;
-if(typeof _3f==="string"&&!_3f.match(/\W/)){
-var _42=_3f=_3f.toUpperCase();
-_41=_3d;
-}
-_41("previousSibling",_3f,_40,_3e,_42);
-}},find:{ID:function(_43,_44){
-if(_44.getElementById){
-var m=_44.getElementById(_43[1]);
-return m?[m]:[];
-}
-},NAME:function(_45,_46){
-return _46.getElementsByName?_46.getElementsByName(_45[1]):null;
-},TAG:function(_47,_48){
-return _48.getElementsByTagName(_47[1]);
-}},preFilter:{CLASS:function(_49,_4a,_4b,_4c,not){
-_49=" "+_49[1].replace(/\\/g,"")+" ";
-for(var i=0;_4a[i];i++){
-if(not^(" "+_4a[i].className+" ").indexOf(_49)>=0){
-if(!_4b){
-_4c.push(_4a[i]);
-}
-}else{
-if(_4b){
-_4a[i]=false;
-}
-}
-}
-return false;
-},ID:function(_4d){
-return _4d[1];
-},TAG:function(_4e){
-return _4e[1].toUpperCase();
-},CHILD:function(_4f){
-if(_4f[1]=="nth"){
-var _50=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(_4f[2]=="even"&&"2n"||_4f[2]=="odd"&&"2n+1"||!/\D/.test(_4f[2])&&"0n+"+_4f[2]||_4f[2]);
-_4f[2]=(_50[1]+(_50[2]||1))-0;
-_4f[3]=_50[3]-0;
-}
-_4f[0]="done"+(_7++);
-return _4f;
-},ATTR:function(_51){
-var _52=_51[1];
-if(_15.attrMap[_52]){
-_51[1]=_15.attrMap[_52];
-}
-if(_51[2]==="~="){
-_51[4]=" "+_51[4]+" ";
-}
-return _51;
-},PSEUDO:function(_53,_54,_55,_56,not){
-if(_53[1]==="not"){
-if(_53[3].match(_6).length>1){
-_53[3]=_9(_53[3],null,null,_54);
-}else{
-var ret=_9.filter(_53[3],_54,_55,true^not);
-if(!_55){
-_56.push.apply(_56,ret);
-}
-return false;
-}
-}
-return _53;
-},POS:function(_57){
-_57.unshift(true);
-return _57;
-}},filters:{enabled:function(_58){
-return _58.disabled===false&&_58.type!=="hidden";
-},disabled:function(_59){
-return _59.disabled===true;
-},checked:function(_5a){
-return _5a.checked===true;
-},selected:function(_5b){
-_5b.parentNode.selectedIndex;
-return _5b.selected===true;
-},parent:function(_5c){
-return !!_5c.firstChild;
-},empty:function(_5d){
-return !_5d.firstChild;
-},has:function(_5e,i,_5f){
-return !!_9(_5f[3],_5e).length;
-},header:function(_60){
-return /h\d/i.test(_60.nodeName);
-},text:function(_61){
-return "text"===_61.type;
-},radio:function(_62){
-return "radio"===_62.type;
-},checkbox:function(_63){
-return "checkbox"===_63.type;
-},file:function(_64){
-return "file"===_64.type;
-},password:function(_65){
-return "password"===_65.type;
-},submit:function(_66){
-return "submit"===_66.type;
-},image:function(_67){
-return "image"===_67.type;
-},reset:function(_68){
-return "reset"===_68.type;
-},button:function(_69){
-return "button"===_69.type||_69.nodeName.toUpperCase()==="BUTTON";
-},input:function(_6a){
-return /input|select|textarea|button/i.test(_6a.nodeName);
-}},setFilters:{first:function(_6b,i){
-return i===0;
-},last:function(_6c,i,_6d,_6e){
-return i===_6e.length-1;
-},even:function(_6f,i){
-return i%2===0;
-},odd:function(_70,i){
-return i%2===1;
-},lt:function(_71,i,_72){
-return i<_72[3]-0;
-},gt:function(_73,i,_74){
-return i>_74[3]-0;
-},nth:function(_75,i,_76){
-return _76[3]-0==i;
-},eq:function(_77,i,_78){
-return _78[3]-0==i;
-}},filter:{CHILD:function(_79,_7a){
-var _7b=_7a[1],_7c=_79.parentNode;
-var _7d=_7a[0];
-if(_7c&&!_7c[_7d]){
-var _7e=1;
-for(var _7f=_7c.firstChild;_7f;_7f=_7f.nextSibling){
-if(_7f.nodeType==1){
-_7f.nodeIndex=_7e++;
-}
-}
-_7c[_7d]=_7e-1;
-}
-if(_7b=="first"){
-return _79.nodeIndex==1;
-}else{
-if(_7b=="last"){
-return _79.nodeIndex==_7c[_7d];
-}else{
-if(_7b=="only"){
-return _7c[_7d]==1;
-}else{
-if(_7b=="nth"){
-var add=false,_80=_7a[2],_81=_7a[3];
-if(_80==1&&_81==0){
-return true;
-}
-if(_80==0){
-if(_79.nodeIndex==_81){
-add=true;
-}
-}else{
-if((_79.nodeIndex-_81)%_80==0&&(_79.nodeIndex-_81)/_80>=0){
-add=true;
-}
-}
-return add;
-}
-}
-}
-}
-},PSEUDO:function(_82,_83,i,_84){
-var _85=_83[1],_86=_15.filters[_85];
-if(_86){
-return _86(_82,i,_83,_84);
-}else{
-if(_85==="contains"){
-return (_82.textContent||_82.innerText||"").indexOf(_83[3])>=0;
-}else{
-if(_85==="not"){
-var not=_83[3];
-for(var i=0,l=not.length;i<l;i++){
-if(not[i]===_82){
-return false;
-}
-}
-return true;
-}
-}
-}
-},ID:function(_87,_88){
-return _87.nodeType===1&&_87.getAttribute("id")===_88;
-},TAG:function(_89,_8a){
-return (_8a==="*"&&_89.nodeType===1)||_89.nodeName===_8a;
-},CLASS:function(_8b,_8c){
-return _8c.test(_8b.className);
-},ATTR:function(_8d,_8e){
-var _8f=_8d[_8e[1]]||_8d.getAttribute(_8e[1]),_90=_8f+"",_91=_8e[2],_92=_8e[4];
-return _8f==null?false:_91==="="?_90===_92:_91==="*="?_90.indexOf(_92)>=0:_91==="~="?(" "+_90+" ").indexOf(_92)>=0:!_8e[4]?_8f:_91==="!="?_90!=_92:_91==="^="?_90.indexOf(_92)===0:_91==="$="?_90.substr(_90.length-_92.length)===_92:_91==="|="?_90===_92||_90.substr(0,_92.length+1)===_92+"-":false;
-},POS:function(_93,_94,i,_95){
-var _96=_94[2],_97=_15.setFilters[_96];
-if(_97){
-return _97(_93,i,_94,_95);
-}
-}}};
-for(var _98 in _15.match){
-_15.match[_98]=RegExp(_15.match[_98].source+/(?![^\[]*\])(?![^\(]*\))/.source);
-}
-var _19=function(_99,_9a){
-_99=Array.prototype.slice.call(_99);
-if(_9a){
-_9a.push.apply(_9a,_99);
-return _9a;
-}
-return _99;
+
+var Expr = Sizzle.selectors = {
+	order: [ "ID", "NAME", "TAG" ],
+	match: {
+		ID: /#((?:[\w\u0128-\uFFFF_-]|\\.)+)/,
+		CLASS: /\.((?:[\w\u0128-\uFFFF_-]|\\.)+)/,
+		NAME: /\[name=['"]*((?:[\w\u0128-\uFFFF_-]|\\.)+)['"]*\]/,
+		ATTR: /\[((?:[\w\u0128-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\]/,
+		TAG: /^((?:[\w\u0128-\uFFFF\*_-]|\\.)+)/,
+		CHILD: /:(only|nth|last|first)-child\(?(even|odd|[\dn+-]*)\)?/,
+		POS: /:(nth|eq|gt|lt|first|last|even|odd)\(?(\d*)\)?(?:[^-]|$)/,
+		PSEUDO: /:((?:[\w\u0128-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
+	},
+	attrMap: {
+		"class": "className",
+		"for": "htmlFor"
+	},
+	relative: {
+		"+": function(checkSet, part){
+			for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+				var elem = checkSet[i];
+				if ( elem ) {
+					var cur = elem.previousSibling;
+					while ( cur && cur.nodeType !== 1 ) {
+						cur = cur.previousSibling;
+					}
+					checkSet[i] = typeof part === "string" ?
+						cur || false :
+						cur === part;
+				}
+			}
+
+			if ( typeof part === "string" ) {
+				Sizzle.filter( part, checkSet, true );
+			}
+		},
+		">": function(checkSet, part){
+			if ( typeof part === "string" && !/\W/.test(part) ) {
+				part = part.toUpperCase();
+
+				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+					var elem = checkSet[i];
+					if ( elem ) {
+						var parent = elem.parentNode;
+						checkSet[i] = parent.nodeName === part ? parent : false;
+					}
+				}
+			} else {
+				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+					var elem = checkSet[i];
+					if ( elem ) {
+						checkSet[i] = typeof part === "string" ?
+							elem.parentNode :
+							elem.parentNode === part;
+					}
+				}
+
+				if ( typeof part === "string" ) {
+					Sizzle.filter( part, checkSet, true );
+				}
+			}
+		},
+		"": function(checkSet, part){
+			var doneName = "done" + (done++), checkFn = dirCheck;
+
+			if ( !part.match(/\W/) ) {
+				var nodeCheck = part = part.toUpperCase();
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn("parentNode", part, doneName, checkSet, nodeCheck);
+		},
+		"~": function(checkSet, part){
+			var doneName = "done" + (done++), checkFn = dirCheck;
+
+			if ( typeof part === "string" && !part.match(/\W/) ) {
+				var nodeCheck = part = part.toUpperCase();
+				checkFn = dirNodeCheck;
+			}
+
+			checkFn("previousSibling", part, doneName, checkSet, nodeCheck);
+		}
+	},
+	find: {
+		ID: function(match, context){
+			if ( context.getElementById ) {
+				var m = context.getElementById(match[1]);
+				return m ? [m] : [];
+			}
+		},
+		NAME: function(match, context){
+			return context.getElementsByName ? context.getElementsByName(match[1]) : null;
+		},
+		TAG: function(match, context){
+			return context.getElementsByTagName(match[1]);
+		}
+	},
+	preFilter: {
+		CLASS: function(match, curLoop, inplace, result, not){
+			match = " " + match[1].replace(/\\/g, "") + " ";
+
+			for ( var i = 0; curLoop[i]; i++ ) {
+				if ( not ^ (" " + curLoop[i].className + " ").indexOf(match) >= 0 ) {
+					if ( !inplace )
+						result.push( curLoop[i] );
+				} else if ( inplace ) {
+					curLoop[i] = false;
+				}
+			}
+
+			return false;
+		},
+		ID: function(match){
+			return match[1];
+		},
+		TAG: function(match){
+			return match[1].toUpperCase();
+		},
+		CHILD: function(match){
+			if ( match[1] == "nth" ) {
+				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
+					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+				// calculate the numbers (first)n+(last) including if they are negative
+				match[2] = (test[1] + (test[2] || 1)) - 0;
+				match[3] = test[3] - 0;
+			}
+
+			// TODO: Move to normal caching system
+			match[0] = "done" + (done++);
+
+			return match;
+		},
+		ATTR: function(match){
+			var name = match[1];
+			
+			if ( Expr.attrMap[name] ) {
+				match[1] = Expr.attrMap[name];
+			}
+
+			if ( match[2] === "~=" ) {
+				match[4] = " " + match[4] + " ";
+			}
+
+			return match;
+		},
+		PSEUDO: function(match, curLoop, inplace, result, not){
+			if ( match[1] === "not" ) {
+				// If we're dealing with a complex expression, or a simple one
+				if ( match[3].match(chunker).length > 1 ) {
+					match[3] = Sizzle(match[3], null, null, curLoop);
+				} else {
+					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+					if ( !inplace ) {
+						result.push.apply( result, ret );
+					}
+					return false;
+				}
+			}
+			
+			return match;
+		},
+		POS: function(match){
+			match.unshift( true );
+			return match;
+		}
+	},
+	filters: {
+		enabled: function(elem){
+			return elem.disabled === false && elem.type !== "hidden";
+		},
+		disabled: function(elem){
+			return elem.disabled === true;
+		},
+		checked: function(elem){
+			return elem.checked === true;
+		},
+		selected: function(elem){
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			elem.parentNode.selectedIndex;
+			return elem.selected === true;
+		},
+		parent: function(elem){
+			return !!elem.firstChild;
+		},
+		empty: function(elem){
+			return !elem.firstChild;
+		},
+		has: function(elem, i, match){
+			return !!Sizzle( match[3], elem ).length;
+		},
+		header: function(elem){
+			return /h\d/i.test( elem.nodeName );
+		},
+		text: function(elem){
+			return "text" === elem.type;
+		},
+		radio: function(elem){
+			return "radio" === elem.type;
+		},
+		checkbox: function(elem){
+			return "checkbox" === elem.type;
+		},
+		file: function(elem){
+			return "file" === elem.type;
+		},
+		password: function(elem){
+			return "password" === elem.type;
+		},
+		submit: function(elem){
+			return "submit" === elem.type;
+		},
+		image: function(elem){
+			return "image" === elem.type;
+		},
+		reset: function(elem){
+			return "reset" === elem.type;
+		},
+		button: function(elem){
+			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
+		},
+		input: function(elem){
+			return /input|select|textarea|button/i.test(elem.nodeName);
+		}
+	},
+	setFilters: {
+		first: function(elem, i){
+			return i === 0;
+		},
+		last: function(elem, i, match, array){
+			return i === array.length - 1;
+		},
+		even: function(elem, i){
+			return i % 2 === 0;
+		},
+		odd: function(elem, i){
+			return i % 2 === 1;
+		},
+		lt: function(elem, i, match){
+			return i < match[3] - 0;
+		},
+		gt: function(elem, i, match){
+			return i > match[3] - 0;
+		},
+		nth: function(elem, i, match){
+			return match[3] - 0 == i;
+		},
+		eq: function(elem, i, match){
+			return match[3] - 0 == i;
+		}
+	},
+	filter: {
+		CHILD: function(elem, match){
+			var type = match[1], parent = elem.parentNode;
+
+			var doneName = match[0];
+			
+			if ( parent && !parent[ doneName ] ) {
+				var count = 1;
+
+				for ( var node = parent.firstChild; node; node = node.nextSibling ) {
+					if ( node.nodeType == 1 ) {
+						node.nodeIndex = count++;
+					}
+				}
+
+				parent[ doneName ] = count - 1;
+			}
+
+			if ( type == "first" ) {
+				return elem.nodeIndex == 1;
+			} else if ( type == "last" ) {
+				return elem.nodeIndex == parent[ doneName ];
+			} else if ( type == "only" ) {
+				return parent[ doneName ] == 1;
+			} else if ( type == "nth" ) {
+				var add = false, first = match[2], last = match[3];
+
+				if ( first == 1 && last == 0 ) {
+					return true;
+				}
+
+				if ( first == 0 ) {
+					if ( elem.nodeIndex == last ) {
+						add = true;
+					}
+				} else if ( (elem.nodeIndex - last) % first == 0 && (elem.nodeIndex - last) / first >= 0 ) {
+					add = true;
+				}
+
+				return add;
+			}
+		},
+		PSEUDO: function(elem, match, i, array){
+			var name = match[1], filter = Expr.filters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+			} else if ( name === "contains" ) {
+				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
+			} else if ( name === "not" ) {
+				var not = match[3];
+
+				for ( var i = 0, l = not.length; i < l; i++ ) {
+					if ( not[i] === elem ) {
+						return false;
+					}
+				}
+
+				return true;
+			}
+		},
+		ID: function(elem, match){
+			return elem.nodeType === 1 && elem.getAttribute("id") === match;
+		},
+		TAG: function(elem, match){
+			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
+		},
+		CLASS: function(elem, match){
+			return match.test( elem.className );
+		},
+		ATTR: function(elem, match){
+			var result = elem[ match[1] ] || elem.getAttribute( match[1] ), value = result + "", type = match[2], check = match[4];
+			return result == null ?
+				false :
+				type === "=" ?
+				value === check :
+				type === "*=" ?
+				value.indexOf(check) >= 0 :
+				type === "~=" ?
+				(" " + value + " ").indexOf(check) >= 0 :
+				!match[4] ?
+				result :
+				type === "!=" ?
+				value != check :
+				type === "^=" ?
+				value.indexOf(check) === 0 :
+				type === "$=" ?
+				value.substr(value.length - check.length) === check :
+				type === "|=" ?
+				value === check || value.substr(0, check.length + 1) === check + "-" :
+				false;
+		},
+		POS: function(elem, match, i, array){
+			var name = match[2], filter = Expr.setFilters[ name ];
+
+			if ( filter ) {
+				return filter( elem, i, match, array );
+			}
+		}
+	}
 };
-try{
-Array.prototype.slice.call(document.documentElement.childNodes);
-}
-catch(e){
-_19=function(_9b,_9c){
-var ret=_9c||[];
-if(_8.call(_9b)==="[object Array]"){
-Array.prototype.push.apply(ret,_9b);
-}else{
-if(typeof _9b.length==="number"){
-for(var i=0,l=_9b.length;i<l;i++){
-ret.push(_9b[i]);
-}
-}else{
-for(var i=0;_9b[i];i++){
-ret.push(_9b[i]);
-}
-}
+
+for ( var type in Expr.match ) {
+	Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
 }
-return ret;
+
+var makeArray = function(array, results) {
+	array = Array.prototype.slice.call( array );
+
+	if ( results ) {
+		results.push.apply( results, array );
+		return results;
+	}
+	
+	return array;
 };
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+try {
+	Array.prototype.slice.call( document.documentElement.childNodes );
+
+// Provide a fallback method if it does not work
+} catch(e){
+	makeArray = function(array, results) {
+		var ret = results || [];
+
+		if ( toString.call(array) === "[object Array]" ) {
+			Array.prototype.push.apply( ret, array );
+		} else {
+			if ( typeof array.length === "number" ) {
+				for ( var i = 0, l = array.length; i < l; i++ ) {
+					ret.push( array[i] );
+				}
+			} else {
+				for ( var i = 0; array[i]; i++ ) {
+					ret.push( array[i] );
+				}
+			}
+		}
+
+		return ret;
+	};
 }
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
 (function(){
-var _9d=document.createElement("form"),id="script"+(new Date).getTime();
-_9d.innerHTML="<input name='"+id+"'/>";
-var _9e=document.documentElement;
-_9e.insertBefore(_9d,_9e.firstChild);
-if(!!document.getElementById(id)){
-_15.find.ID=function(_9f,_a0){
-if(_a0.getElementById){
-var m=_a0.getElementById(_9f[1]);
-return m?m.id===_9f[1]||m.getAttributeNode&&m.getAttributeNode("id").nodeValue===_9f[1]?[m]:undefined:[];
-}
-};
-_15.filter.ID=function(_a1,_a2){
-var _a3=_a1.getAttributeNode&&_a1.getAttributeNode("id");
-return _a1.nodeType===1&&_a3&&_a3.nodeValue===_a2;
-};
-}
-_9e.removeChild(_9d);
+	// We're going to inject a fake input element with a specified name
+	var form = document.createElement("form"),
+		id = "script" + (new Date).getTime();
+	form.innerHTML = "<input name='" + id + "'/>";
+
+	// Inject it into the root element, check its status, and remove it quickly
+	var root = document.documentElement;
+	root.insertBefore( form, root.firstChild );
+
+	// The workaround has to do additional checks after a getElementById
+	// Which slows things down for other browsers (hence the branching)
+	if ( !!document.getElementById( id ) ) {
+		Expr.find.ID = function(match, context){
+			if ( context.getElementById ) {
+				var m = context.getElementById(match[1]);
+				return m ? m.id === match[1] || m.getAttributeNode && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
+			}
+		};
+
+		Expr.filter.ID = function(elem, match){
+			var node = elem.getAttributeNode && elem.getAttributeNode("id");
+			return elem.nodeType === 1 && node && node.nodeValue === match;
+		};
+	}
+
+	root.removeChild( form );
 })();
+
+// Check to see if the browser returns only elements
+// when doing getElementsByTagName("*")
 (function(){
-var div=document.createElement("div");
-div.appendChild(document.createComment(""));
-if(div.getElementsByTagName("*").length>0){
-_15.find.TAG=function(_a4,_a5){
-var _a6=_a5.getElementsByTagName(_a4[1]);
-if(_a4[1]==="*"){
-var tmp=[];
-for(var i=0;_a6[i];i++){
-if(_a6[i].nodeType===1){
-tmp.push(_a6[i]);
-}
-}
-_a6=tmp;
-}
-return _a6;
-};
-}
+	// Create a fake element
+	var div = document.createElement("div");
+	div.appendChild( document.createComment("") );
+
+	// Make sure no comments are found
+	if ( div.getElementsByTagName("*").length > 0 ) {
+		Expr.find.TAG = function(match, context){
+			var results = context.getElementsByTagName(match[1]);
+
+			// Filter out possible comments
+			if ( match[1] === "*" ) {
+				var tmp = [];
+
+				for ( var i = 0; results[i]; i++ ) {
+					if ( results[i].nodeType === 1 ) {
+						tmp.push( results[i] );
+					}
+				}
+
+				results = tmp;
+			}
+
+			return results;
+		};
+	}
 })();
-if(document.querySelectorAll){
-(function(){
-var _a7=_9;
-_9=function(_a8,_a9,_aa,_ab){
-_a9=_a9||document;
-if(!_ab&&_a9.nodeType===9){
-try{
-return _19(_a9.querySelectorAll(_a8),_aa);
-}
-catch(e){
-}
-}
-return _a7(_a8,_a9,_aa,_ab);
-};
-_9.find=_a7.find;
-_9.filter=_a7.filter;
-_9.selectors=_a7.selectors;
-_9.matches=_a7.matches;
+
+if ( document.querySelectorAll ) (function(){
+	var oldSizzle = Sizzle;
+	
+	Sizzle = function(query, context, extra, seed){
+		context = context || document;
+
+		if ( !seed && context.nodeType === 9 ) {
+			try {
+				return makeArray( context.querySelectorAll(query), extra );
+			} catch(e){}
+		}
+		
+		return oldSizzle(query, context, extra, seed);
+	};
+
+	Sizzle.find = oldSizzle.find;
+	Sizzle.filter = oldSizzle.filter;
+	Sizzle.selectors = oldSizzle.selectors;
+	Sizzle.matches = oldSizzle.matches;
 })();
+
+if ( document.documentElement.getElementsByClassName ) {
+	Expr.order.splice(1, 0, "CLASS");
+	Expr.find.CLASS = function(match, context) {
+		return context.getElementsByClassName(match[1]);
+	};
 }
-if(document.documentElement.getElementsByClassName){
-_15.order.splice(1,0,"CLASS");
-_15.find.CLASS=function(_ac,_ad){
-return _ad.getElementsByClassName(_ac[1]);
-};
-}
-function _3d(dir,cur,_ae,_af,_b0){
-for(var i=0,l=_af.length;i<l;i++){
-var _b1=_af[i];
-if(_b1){
-_b1=_b1[dir];
-var _b2=false;
-while(_b1&&_b1.nodeType){
-var _b3=_b1[_ae];
-if(_b3){
-_b2=_af[_b3];
-break;
-}
-if(_b1.nodeType===1){
-_b1[_ae]=i;
-}
-if(_b1.nodeName===cur){
-_b2=_b1;
-break;
-}
-_b1=_b1[dir];
-}
-_af[i]=_b2;
-}
-}
-};
-function _3b(dir,cur,_b4,_b5,_b6){
-for(var i=0,l=_b5.length;i<l;i++){
-var _b7=_b5[i];
-if(_b7){
-_b7=_b7[dir];
-var _b8=false;
-while(_b7&&_b7.nodeType){
-if(_b7[_b4]){
-_b8=_b5[_b7[_b4]];
-break;
-}
-if(_b7.nodeType===1){
-_b7[_b4]=i;
-if(typeof cur!=="string"){
-if(_b7===cur){
-_b8=true;
-break;
-}
-}else{
-if(_9.filter(cur,[_b7]).length>0){
-_b8=_b7;
-break;
-}
-}
-}
-_b7=_b7[dir];
-}
-_b5[i]=_b8;
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck ) {
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+		if ( elem ) {
+			elem = elem[dir];
+			var match = false;
+
+			while ( elem && elem.nodeType ) {
+				var done = elem[doneName];
+				if ( done ) {
+					match = checkSet[ done ];
+					break;
+				}
+
+				if ( elem.nodeType === 1 )
+					elem[doneName] = i;
+
+				if ( elem.nodeName === cur ) {
+					match = elem;
+					break;
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
 }
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck ) {
+	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+		var elem = checkSet[i];
+		if ( elem ) {
+			elem = elem[dir];
+			var match = false;
+
+			while ( elem && elem.nodeType ) {
+				if ( elem[doneName] ) {
+					match = checkSet[ elem[doneName] ];
+					break;
+				}
+
+				if ( elem.nodeType === 1 ) {
+					elem[doneName] = i;
+
+					if ( typeof cur !== "string" ) {
+						if ( elem === cur ) {
+							match = true;
+							break;
+						}
+
+					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+						match = elem;
+						break;
+					}
+				}
+
+				elem = elem[dir];
+			}
+
+			checkSet[i] = match;
+		}
+	}
 }
+
+var contains = document.compareDocumentPosition ?  function(a, b){
+	return a.compareDocumentPosition(b) & 16;
+} : function(a, b){
+	return a !== b && (a.contains ? a.contains(b) : true);
 };
-var _1a=document.compareDocumentPosition?function(a,b){
-return a.compareDocumentPosition(b)&16;
-}:function(a,b){
-return a!==b&&(a.contains?a.contains(b):true);
-};
-(ns||window).Sizzle=_9;
-})(typeof dojo=="undefined"?null:dojo);
-}
+
+// EXPOSE
+
+(ns || window).Sizzle = Sizzle;
+
+})(typeof dojo == "undefined" ? null : dojo);
diff --git a/dojo/_base/query.js b/dojo/_base/query.js
index 1e8fcad..5b045d8 100644
--- a/dojo/_base/query.js
+++ b/dojo/_base/query.js
@@ -1,797 +1,1640 @@
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+if(typeof dojo != "undefined"){
+//>>excludeEnd("webkitMobile");
+	dojo.provide("dojo._base.query");
+	dojo.require("dojo._base.NodeList");
+	dojo.require("dojo._base.lang");
+
+//>>excludeStart("acmeExclude", fileName.indexOf("dojo") != -1);
+
+}else if(!this["acme"] && !this["queryPortability"]){
+	// NOTE: 
+	//		the functions and properties are duplicates of things found
+	//		elsewhere in Dojo. They've been copied here to make query.js a
+	//		stand-alone system.  The "acmeExclude" ensures that it *never*
+	//		shows up in builds of Dojo.
+	(function(){
+		// a self-sufficient query impl
+		acme = {
+			trim: function(/*String*/ str){
+				// summary:
+				//		trims whitespaces from both sides of the string
+				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;	// String
+			},
+			forEach: function(/*String*/ arr, /*Function*/ callback, /*Object?*/ thisObject){
+				//	summary:
+				// 		an iterator function that passes items, indexes,
+				// 		and the array to a callback
+				if(!arr || !arr.length){ return; }
+				for(var i=0,l=arr.length; i<l; ++i){ 
+					callback.call(thisObject||window, arr[i], i, arr);
+				}
+			},
+			byId: function(id, doc){
+				// 	summary:
+				//		a function that return an element by ID, but also
+				//		accepts nodes safely
+				if(typeof id == "string"){
+					return (doc||document).getElementById(id); // DomNode
+				}else{
+					return id; // DomNode
+				}
+			},
+			// the default document to search
+			doc: document,
+			// the constructor for node list objects returned from query()
+			NodeList: Array
+		};
+
+		// define acme.isIE, acme.isSafari, acme.isOpera, etc.
+		var n = navigator;
+		var dua = n.userAgent;
+		var dav = n.appVersion;
+		var tv = parseFloat(dav);
+		acme.isOpera = (dua.indexOf("Opera") >= 0) ? tv: undefined;
+		acme.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : undefined;
+		acme.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined;
+		acme.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined;
+		var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);
+		if(index && !acme.isChrome){
+			acme.isSafari = parseFloat(dav.split("Version/")[1]);
+			if(!acme.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){
+				acme.isSafari = 2;
+			}
+		}
+		if(document.all && !acme.isOpera){
+			acme.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined;
+		}
+
+		Array._wrap = function(arr){ return arr; };
+	})();
+
+//>>excludeEnd("acmeExclude");
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+}
+
 /*
-	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
+	dojo.query() architectural overview:
+
+		dojo.query is a relatively full-featured CSS3 query library. It is
+		designed to take any valid CSS3 selector and return the nodes matching
+		the selector. To do this quickly, it processes queries in several
+		steps, applying caching where profitable.
+		
+		The steps (roughly in reverse order of the way they appear in the code):
+			1.) check to see if we already have a "query dispatcher"
+				- if so, use that with the given parameterization. Skip to step 4.
+			2.) attempt to determine which branch to dispatch the query to:
+				- JS (optimized DOM iteration)
+				- native (FF3.1+, Safari 3.1+, IE 8+)
+			3.) tokenize and convert to executable "query dispatcher"
+				- this is where the lion's share of the complexity in the
+				  system lies. In the DOM version, the query dispatcher is
+				  assembled as a chain of "yes/no" test functions pertaining to
+				  a section of a simple query statement (".blah:nth-child(odd)"
+				  but not "div div", which is 2 simple statements). Individual
+				  statement dispatchers are cached (to prevent re-definition)
+				  as are entire dispatch chains (to make re-execution of the
+				  same query fast)
+			4.) the resulting query dispatcher is called in the passed scope
+			    (by default the top-level document)
+				- for DOM queries, this results in a recursive, top-down
+				  evaluation of nodes based on each simple query section
+				- for native implementations, this may mean working around spec
+				  bugs. So be it.
+			5.) matched nodes are pruned to ensure they are unique (if necessary)
 */
 
+;(function(d){
+	// define everything in a closure for compressability reasons. "d" is an
+	// alias to "dojo" (or the toolkit alias object, e.g., "acme").
 
-if(!dojo._hasResource["dojo._base.query"]){
-dojo._hasResource["dojo._base.query"]=true;
-if(typeof dojo!="undefined"){
-dojo.provide("dojo._base.query");
-dojo.require("dojo._base.NodeList");
-dojo.require("dojo._base.lang");
-}
-(function(d){
-var _1=d.trim;
-var _2=d.forEach;
-var _3=d._NodeListCtor=d.NodeList;
-var _4=function(){
-return d.doc;
-};
-var _5=((d.isWebKit||d.isMozilla)&&((_4().compatMode)=="BackCompat"));
-var _6=!!_4().firstChild["children"]?"children":"childNodes";
-var _7=">~+";
-var _8=false;
-var _9=function(){
-return true;
-};
-var _a=function(_b){
-if(_7.indexOf(_b.slice(-1))>=0){
-_b+=" * ";
-}else{
-_b+=" ";
-}
-var ts=function(s,e){
-return _1(_b.slice(s,e));
-};
-var _c=[];
-var _d=-1,_e=-1,_f=-1,_10=-1,_11=-1,_12=-1,_13=-1,lc="",cc="",_14;
-var x=0,ql=_b.length,_15=null,_16=null;
-var _17=function(){
-if(_13>=0){
-var tv=(_13==x)?null:ts(_13,x);
-_15[(_7.indexOf(tv)<0)?"tag":"oper"]=tv;
-_13=-1;
-}
-};
-var _18=function(){
-if(_12>=0){
-_15.id=ts(_12,x).replace(/\\/g,"");
-_12=-1;
-}
-};
-var _19=function(){
-if(_11>=0){
-_15.classes.push(ts(_11+1,x).replace(/\\/g,""));
-_11=-1;
-}
-};
-var _1a=function(){
-_18();
-_17();
-_19();
-};
-var _1b=function(){
-_1a();
-if(_10>=0){
-_15.pseudos.push({name:ts(_10+1,x)});
-}
-_15.loops=(_15.pseudos.length||_15.attrs.length||_15.classes.length);
-_15.oquery=_15.query=ts(_14,x);
-_15.otag=_15.tag=(_15["oper"])?null:(_15.tag||"*");
-if(_15.tag){
-_15.tag=_15.tag.toUpperCase();
-}
-if(_c.length&&(_c[_c.length-1].oper)){
-_15.infixOper=_c.pop();
-_15.query=_15.infixOper.query+" "+_15.query;
-}
-_c.push(_15);
-_15=null;
-};
-for(;lc=cc,cc=_b.charAt(x),x<ql;x++){
-if(lc=="\\"){
-continue;
-}
-if(!_15){
-_14=x;
-_15={query:null,pseudos:[],attrs:[],classes:[],tag:null,oper:null,id:null,getTag:function(){
-return (_8)?this.otag:this.tag;
-}};
-_13=x;
-}
-if(_d>=0){
-if(cc=="]"){
-if(!_16.attr){
-_16.attr=ts(_d+1,x);
-}else{
-_16.matchFor=ts((_f||_d+1),x);
-}
-var cmf=_16.matchFor;
-if(cmf){
-if((cmf.charAt(0)=="\"")||(cmf.charAt(0)=="'")){
-_16.matchFor=cmf.slice(1,-1);
-}
-}
-_15.attrs.push(_16);
-_16=null;
-_d=_f=-1;
-}else{
-if(cc=="="){
-var _1c=("|~^$*".indexOf(lc)>=0)?lc:"";
-_16.type=_1c+cc;
-_16.attr=ts(_d+1,x-_1c.length);
-_f=x+1;
-}
-}
-}else{
-if(_e>=0){
-if(cc==")"){
-if(_10>=0){
-_16.value=ts(_e+1,x);
-}
-_10=_e=-1;
-}
-}else{
-if(cc=="#"){
-_1a();
-_12=x+1;
-}else{
-if(cc=="."){
-_1a();
-_11=x;
-}else{
-if(cc==":"){
-_1a();
-_10=x;
-}else{
-if(cc=="["){
-_1a();
-_d=x;
-_16={};
-}else{
-if(cc=="("){
-if(_10>=0){
-_16={name:ts(_10+1,x),value:null};
-_15.pseudos.push(_16);
-}
-_e=x;
-}else{
-if((cc==" ")&&(lc!=cc)){
-_1b();
-}
-}
-}
-}
-}
-}
-}
-}
-}
-return _c;
-};
-var _1d=function(_1e,_1f){
-if(!_1e){
-return _1f;
-}
-if(!_1f){
-return _1e;
-}
-return function(){
-return _1e.apply(window,arguments)&&_1f.apply(window,arguments);
-};
-};
-var _20=function(i,arr){
-var r=arr||[];
-if(i){
-r.push(i);
-}
-return r;
-};
-var _21=function(n){
-return (1==n.nodeType);
-};
-var _22="";
-var _23=function(_24,_25){
-if(!_24){
-return _22;
-}
-if(_25=="class"){
-return _24.className||_22;
-}
-if(_25=="for"){
-return _24.htmlFor||_22;
-}
-if(_25=="style"){
-return _24.style.cssText||_22;
-}
-return (_8?_24.getAttribute(_25):_24.getAttribute(_25,2))||_22;
-};
-var _26={"*=":function(_27,_28){
-return function(_29){
-return (_23(_29,_27).indexOf(_28)>=0);
-};
-},"^=":function(_2a,_2b){
-return function(_2c){
-return (_23(_2c,_2a).indexOf(_2b)==0);
-};
-},"$=":function(_2d,_2e){
-var _2f=" "+_2e;
-return function(_30){
-var ea=" "+_23(_30,_2d);
-return (ea.lastIndexOf(_2e)==(ea.length-_2e.length));
-};
-},"~=":function(_31,_32){
-var _33=" "+_32+" ";
-return function(_34){
-var ea=" "+_23(_34,_31)+" ";
-return (ea.indexOf(_33)>=0);
-};
-},"|=":function(_35,_36){
-var _37=" "+_36+"-";
-return function(_38){
-var ea=" "+_23(_38,_35);
-return ((ea==_36)||(ea.indexOf(_37)==0));
-};
-},"=":function(_39,_3a){
-return function(_3b){
-return (_23(_3b,_39)==_3a);
-};
-}};
-var _3c=(typeof _4().firstChild.nextElementSibling=="undefined");
-var _3d=!_3c?"nextElementSibling":"nextSibling";
-var _3e=!_3c?"previousElementSibling":"previousSibling";
-var _3f=(_3c?_21:_9);
-var _40=function(_41){
-while(_41=_41[_3e]){
-if(_3f(_41)){
-return false;
-}
-}
-return true;
-};
-var _42=function(_43){
-while(_43=_43[_3d]){
-if(_3f(_43)){
-return false;
-}
-}
-return true;
-};
-var _44=function(_45){
-var _46=_45.parentNode;
-var i=0,_47=_46[_6],ci=(_45["_i"]||-1),cl=(_46["_l"]||-1);
-if(!_47){
-return -1;
-}
-var l=_47.length;
-if(cl==l&&ci>=0&&cl>=0){
-return ci;
-}
-_46["_l"]=l;
-ci=-1;
-for(var te=_46["firstElementChild"]||_46["firstChild"];te;te=te[_3d]){
-if(_3f(te)){
-te["_i"]=++i;
-if(_45===te){
-ci=i;
-}
-}
-}
-return ci;
-};
-var _48=function(_49){
-return !((_44(_49))%2);
-};
-var _4a=function(_4b){
-return ((_44(_4b))%2);
-};
-var _4c={"checked":function(_4d,_4e){
-return function(_4f){
-return !!("checked" in _4f?_4f.checked:_4f.selected);
-};
-},"first-child":function(){
-return _40;
-},"last-child":function(){
-return _42;
-},"only-child":function(_50,_51){
-return function(_52){
-if(!_40(_52)){
-return false;
-}
-if(!_42(_52)){
-return false;
-}
-return true;
-};
-},"empty":function(_53,_54){
-return function(_55){
-var cn=_55.childNodes;
-var cnl=_55.childNodes.length;
-for(var x=cnl-1;x>=0;x--){
-var nt=cn[x].nodeType;
-if((nt===1)||(nt==3)){
-return false;
-}
-}
-return true;
-};
-},"contains":function(_56,_57){
-var cz=_57.charAt(0);
-if(cz=="\""||cz=="'"){
-_57=_57.slice(1,-1);
-}
-return function(_58){
-return (_58.innerHTML.indexOf(_57)>=0);
-};
-},"not":function(_59,_5a){
-var p=_a(_5a)[0];
-var _5b={el:1};
-if(p.tag!="*"){
-_5b.tag=1;
-}
-if(!p.classes.length){
-_5b.classes=1;
-}
-var ntf=_5c(p,_5b);
-return function(_5d){
-return (!ntf(_5d));
-};
-},"nth-child":function(_5e,_5f){
-var pi=parseInt;
-if(_5f=="odd"){
-return _4a;
-}else{
-if(_5f=="even"){
-return _48;
-}
-}
-if(_5f.indexOf("n")!=-1){
-var _60=_5f.split("n",2);
-var _61=_60[0]?((_60[0]=="-")?-1:pi(_60[0])):1;
-var idx=_60[1]?pi(_60[1]):0;
-var lb=0,ub=-1;
-if(_61>0){
-if(idx<0){
-idx=(idx%_61)&&(_61+(idx%_61));
-}else{
-if(idx>0){
-if(idx>=_61){
-lb=idx-idx%_61;
-}
-idx=idx%_61;
-}
-}
-}else{
-if(_61<0){
-_61*=-1;
-if(idx>0){
-ub=idx;
-idx=idx%_61;
-}
-}
-}
-if(_61>0){
-return function(_62){
-var i=_44(_62);
-return (i>=lb)&&(ub<0||i<=ub)&&((i%_61)==idx);
-};
-}else{
-_5f=idx;
-}
-}
-var _63=pi(_5f);
-return function(_64){
-return (_44(_64)==_63);
-};
-}};
-var _65=(d.isIE)?function(_66){
-var clc=_66.toLowerCase();
-if(clc=="class"){
-_66="className";
-}
-return function(_67){
-return (_8?_67.getAttribute(_66):_67[_66]||_67[clc]);
-};
-}:function(_68){
-return function(_69){
-return (_69&&_69.getAttribute&&_69.hasAttribute(_68));
-};
-};
-var _5c=function(_6a,_6b){
-if(!_6a){
-return _9;
-}
-_6b=_6b||{};
-var ff=null;
-if(!("el" in _6b)){
-ff=_1d(ff,_21);
-}
-if(!("tag" in _6b)){
-if(_6a.tag!="*"){
-ff=_1d(ff,function(_6c){
-return (_6c&&(_6c.tagName==_6a.getTag()));
-});
-}
-}
-if(!("classes" in _6b)){
-_2(_6a.classes,function(_6d,idx,arr){
-var re=new RegExp("(?:^|\\s)"+_6d+"(?:\\s|$)");
-ff=_1d(ff,function(_6e){
-return re.test(_6e.className);
-});
-ff.count=idx;
-});
-}
-if(!("pseudos" in _6b)){
-_2(_6a.pseudos,function(_6f){
-var pn=_6f.name;
-if(_4c[pn]){
-ff=_1d(ff,_4c[pn](pn,_6f.value));
-}
-});
-}
-if(!("attrs" in _6b)){
-_2(_6a.attrs,function(_70){
-var _71;
-var a=_70.attr;
-if(_70.type&&_26[_70.type]){
-_71=_26[_70.type](a,_70.matchFor);
-}else{
-if(a.length){
-_71=_65(a);
-}
-}
-if(_71){
-ff=_1d(ff,_71);
-}
-});
-}
-if(!("id" in _6b)){
-if(_6a.id){
-ff=_1d(ff,function(_72){
-return (!!_72&&(_72.id==_6a.id));
-});
-}
-}
-if(!ff){
-if(!("default" in _6b)){
-ff=_9;
-}
-}
-return ff;
-};
-var _73=function(_74){
-return function(_75,ret,bag){
-while(_75=_75[_3d]){
-if(_3c&&(!_21(_75))){
-continue;
-}
-if((!bag||_76(_75,bag))&&_74(_75)){
-ret.push(_75);
-}
-break;
-}
-return ret;
-};
-};
-var _77=function(_78){
-return function(_79,ret,bag){
-var te=_79[_3d];
-while(te){
-if(_3f(te)){
-if(bag&&!_76(te,bag)){
-break;
-}
-if(_78(te)){
-ret.push(te);
-}
-}
-te=te[_3d];
-}
-return ret;
-};
-};
-var _7a=function(_7b){
-_7b=_7b||_9;
-return function(_7c,ret,bag){
-var te,x=0,_7d=_7c[_6];
-while(te=_7d[x++]){
-if(_3f(te)&&(!bag||_76(te,bag))&&(_7b(te,x))){
-ret.push(te);
-}
-}
-return ret;
-};
-};
-var _7e=function(_7f,_80){
-var pn=_7f.parentNode;
-while(pn){
-if(pn==_80){
-break;
-}
-pn=pn.parentNode;
-}
-return !!pn;
-};
-var _81={};
-var _82=function(_83){
-var _84=_81[_83.query];
-if(_84){
-return _84;
-}
-var io=_83.infixOper;
-var _85=(io?io.oper:"");
-var _86=_5c(_83,{el:1});
-var qt=_83.tag;
-var _87=("*"==qt);
-var ecs=_4()["getElementsByClassName"];
-if(!_85){
-if(_83.id){
-_86=(!_83.loops&&_87)?_9:_5c(_83,{el:1,id:1});
-_84=function(_88,arr){
-var te=d.byId(_83.id,(_88.ownerDocument||_88));
-if(!te||!_86(te)){
-return;
-}
-if(9==_88.nodeType){
-return _20(te,arr);
-}else{
-if(_7e(te,_88)){
-return _20(te,arr);
-}
-}
-};
-}else{
-if(ecs&&/\{\s*\[native code\]\s*\}/.test(String(ecs))&&_83.classes.length&&!_5){
-_86=_5c(_83,{el:1,classes:1,id:1});
-var _89=_83.classes.join(" ");
-_84=function(_8a,arr,bag){
-var ret=_20(0,arr),te,x=0;
-var _8b=_8a.getElementsByClassName(_89);
-while((te=_8b[x++])){
-if(_86(te,_8a)&&_76(te,bag)){
-ret.push(te);
-}
-}
-return ret;
-};
-}else{
-if(!_87&&!_83.loops){
-_84=function(_8c,arr,bag){
-var ret=_20(0,arr),te,x=0;
-var _8d=_8c.getElementsByTagName(_83.getTag());
-while((te=_8d[x++])){
-if(_76(te,bag)){
-ret.push(te);
-}
-}
-return ret;
-};
-}else{
-_86=_5c(_83,{el:1,tag:1,id:1});
-_84=function(_8e,arr,bag){
-var ret=_20(0,arr),te,x=0;
-var _8f=_8e.getElementsByTagName(_83.getTag());
-while((te=_8f[x++])){
-if(_86(te,_8e)&&_76(te,bag)){
-ret.push(te);
-}
-}
-return ret;
-};
-}
-}
-}
-}else{
-var _90={el:1};
-if(_87){
-_90.tag=1;
-}
-_86=_5c(_83,_90);
-if("+"==_85){
-_84=_73(_86);
-}else{
-if("~"==_85){
-_84=_77(_86);
-}else{
-if(">"==_85){
-_84=_7a(_86);
-}
-}
-}
-}
-return _81[_83.query]=_84;
-};
-var _91=function(_92,_93){
-var _94=_20(_92),qp,x,te,qpl=_93.length,bag,ret;
-for(var i=0;i<qpl;i++){
-ret=[];
-qp=_93[i];
-x=_94.length-1;
-if(x>0){
-bag={};
-ret.nozip=true;
-}
-var gef=_82(qp);
-for(var j=0;(te=_94[j]);j++){
-gef(te,ret,bag);
-}
-if(!ret.length){
-break;
-}
-_94=ret;
-}
-return ret;
-};
-var _95={},_96={};
-var _97=function(_98){
-var _99=_a(_1(_98));
-if(_99.length==1){
-var tef=_82(_99[0]);
-return function(_9a){
-var r=tef(_9a,new _3());
-if(r){
-r.nozip=true;
-}
-return r;
-};
-}
-return function(_9b){
-return _91(_9b,_99);
-};
-};
-var nua=navigator.userAgent;
-var wk="WebKit/";
-var _9c=(d.isWebKit&&(nua.indexOf(wk)>0)&&(parseFloat(nua.split(wk)[1])>528));
-var _9d=d.isIE?"commentStrip":"nozip";
-var qsa="querySelectorAll";
-var _9e=(!!_4()[qsa]&&(!d.isSafari||(d.isSafari>3.1)||_9c));
-var _9f=/n\+\d|([^ ])?([>~+])([^ =])?/g;
-var _a0=function(_a1,pre,ch,_a2){
-return ch?(pre?pre+" ":"")+ch+(_a2?" "+_a2:""):_a1;
-};
-var _a3=function(_a4,_a5){
-_a4=_a4.replace(_9f,_a0);
-if(_9e){
-var _a6=_96[_a4];
-if(_a6&&!_a5){
-return _a6;
-}
-}
-var _a7=_95[_a4];
-if(_a7){
-return _a7;
-}
-var qcz=_a4.charAt(0);
-var _a8=(-1==_a4.indexOf(" "));
-if((_a4.indexOf("#")>=0)&&(_a8)){
-_a5=true;
-}
-var _a9=(_9e&&(!_a5)&&(_7.indexOf(qcz)==-1)&&(!d.isIE||(_a4.indexOf(":")==-1))&&(!(_5&&(_a4.indexOf(".")>=0)))&&(_a4.indexOf(":contains")==-1)&&(_a4.indexOf(":checked")==-1)&&(_a4.indexOf("|=")==-1));
-if(_a9){
-var tq=(_7.indexOf(_a4.charAt(_a4.length-1))>=0)?(_a4+" *"):_a4;
-return _96[_a4]=function(_aa){
-try{
-if(!((9==_aa.nodeType)||_a8)){
-throw "";
-}
-var r=_aa[qsa](tq);
-r[_9d]=true;
-return r;
-}
-catch(e){
-return _a3(_a4,true)(_aa);
-}
-};
-}else{
-var _ab=_a4.split(/\s*,\s*/);
-return _95[_a4]=((_ab.length<2)?_97(_a4):function(_ac){
-var _ad=0,ret=[],tp;
-while((tp=_ab[_ad++])){
-ret=ret.concat(_97(tp)(_ac));
-}
-return ret;
-});
-}
-};
-var _ae=0;
-var _af=d.isIE?function(_b0){
-if(_8){
-return (_b0.getAttribute("_uid")||_b0.setAttribute("_uid",++_ae)||_ae);
-}else{
-return _b0.uniqueID;
-}
-}:function(_b1){
-return (_b1._uid||(_b1._uid=++_ae));
-};
-var _76=function(_b2,bag){
-if(!bag){
-return 1;
-}
-var id=_af(_b2);
-if(!bag[id]){
-return bag[id]=1;
-}
-return 0;
-};
-var _b3="_zipIdx";
-var _b4=function(arr){
-if(arr&&arr.nozip){
-return (_3._wrap)?_3._wrap(arr):arr;
-}
-var ret=new _3();
-if(!arr||!arr.length){
-return ret;
-}
-if(arr[0]){
-ret.push(arr[0]);
-}
-if(arr.length<2){
-return ret;
-}
-_ae++;
-if(d.isIE&&_8){
-var _b5=_ae+"";
-arr[0].setAttribute(_b3,_b5);
-for(var x=1,te;te=arr[x];x++){
-if(arr[x].getAttribute(_b3)!=_b5){
-ret.push(te);
-}
-te.setAttribute(_b3,_b5);
-}
-}else{
-if(d.isIE&&arr.commentStrip){
-try{
-for(var x=1,te;te=arr[x];x++){
-if(_21(te)){
-ret.push(te);
-}
-}
-}
-catch(e){
-}
-}else{
-if(arr[0]){
-arr[0][_b3]=_ae;
-}
-for(var x=1,te;te=arr[x];x++){
-if(arr[x][_b3]!=_ae){
-ret.push(te);
-}
-te[_b3]=_ae;
-}
-}
-}
-return ret;
-};
-d.query=function(_b6,_b7){
-_3=d._NodeListCtor;
-if(!_b6){
-return new _3();
-}
-if(_b6.constructor==_3){
-return _b6;
-}
-if(typeof _b6!="string"){
-return new _3(_b6);
-}
-if(typeof _b7=="string"){
-_b7=d.byId(_b7);
-if(!_b7){
-return new _3();
-}
-}
-_b7=_b7||_4();
-var od=_b7.ownerDocument||_b7.documentElement;
-_8=(_b7.contentType&&_b7.contentType=="application/xml")||(d.isOpera&&(_b7.doctype||od.toString()=="[object XMLDocument]"))||(!!od)&&(d.isIE?od.xml:(_b7.xmlVersion||od.xmlVersion));
-var r=_a3(_b6)(_b7);
-if(r&&r.nozip&&!_3._wrap){
-return r;
-}
-return _b4(r);
-};
-d.query.pseudos=_4c;
-d._filterQueryResult=function(_b8,_b9){
-var _ba=new d._NodeListCtor();
-var _bb=_5c(_a(_b9)[0]);
-for(var x=0,te;te=_b8[x];x++){
-if(_bb(te)){
-_ba.push(te);
-}
-}
-return _ba;
-};
+	////////////////////////////////////////////////////////////////////////
+	// Toolkit aliases
+	////////////////////////////////////////////////////////////////////////
+
+	// if you are extracing dojo.query for use in your own system, you will
+	// need to provide these methods and properties. No other porting should be
+	// necessary, save for configuring the system to use a class other than
+	// dojo.NodeList as the return instance instantiator
+	var trim = 			d.trim;
+	var each = 			d.forEach;
+	// 					d.isIE; // float
+	// 					d.isSafari; // float
+	// 					d.isOpera; // float
+	// 					d.isWebKit; // float
+	// 					d.doc ; // document element
+	var qlc = d._NodeListCtor = 		d.NodeList;
+
+	var getDoc = function(){ return d.doc; };
+	// NOTE(alex): the spec is idiotic. CSS queries should ALWAYS be case-sensitive, but nooooooo
+	var cssCaseBug = ((d.isWebKit||d.isMozilla) && ((getDoc().compatMode) == "BackCompat"));
+
+	////////////////////////////////////////////////////////////////////////
+	// Global utilities
+	////////////////////////////////////////////////////////////////////////
+
+
+	// on browsers that support the "children" collection we can avoid a lot of
+	// iteration on chaff (non-element) nodes.
+	// why.
+	var childNodesName = !!getDoc().firstChild["children"] ? "children" : "childNodes";
+
+	var specials = ">~+";
+
+	// global thunk to determine whether we should treat the current query as
+	// case sensitive or not. This switch is flipped by the query evaluator
+	// based on the document passed as the context to search.
+	var caseSensitive = false;
+
+	// how high?
+	var yesman = function(){ return true; };
+
+	////////////////////////////////////////////////////////////////////////
+	// Tokenizer
+	////////////////////////////////////////////////////////////////////////
+
+	var getQueryParts = function(query){
+		//	summary: 
+		//		state machine for query tokenization
+		//	description:
+		//		instead of using a brittle and slow regex-based CSS parser,
+		//		dojo.query implements an AST-style query representation. This
+		//		representation is only generated once per query. For example,
+		//		the same query run multiple times or under different root nodes
+		//		does not re-parse the selector expression but instead uses the
+		//		cached data structure. The state machine implemented here
+		//		terminates on the last " " (space) charachter and returns an
+		//		ordered array of query component structures (or "parts"). Each
+		//		part represents an operator or a simple CSS filtering
+		//		expression. The structure for parts is documented in the code
+		//		below.
+
+
+		// NOTE: 
+		//		this code is designed to run fast and compress well. Sacrifices
+		//		to readibility and maintainability have been made.  Your best
+		//		bet when hacking the tokenizer is to put The Donnas on *really*
+		//		loud (may we recommend their "Spend The Night" release?) and
+		//		just assume you're gonna make mistakes. Keep the unit tests
+		//		open and run them frequently. Knowing is half the battle ;-)
+		if(specials.indexOf(query.slice(-1)) >= 0){
+			// if we end with a ">", "+", or "~", that means we're implicitly
+			// searching all children, so make it explicit
+			query += " * "
+		}else{
+			// if you have not provided a terminator, one will be provided for
+			// you...
+			query += " ";
+		}
+
+		var ts = function(/*Integer*/ s, /*Integer*/ e){
+			// trim and slice. 
+
+			// take an index to start a string slice from and an end position
+			// and return a trimmed copy of that sub-string
+			return trim(query.slice(s, e));
+		}
+
+		// the overall data graph of the full query, as represented by queryPart objects
+		var queryParts = []; 
+
+
+		// state keeping vars
+		var inBrackets = -1, inParens = -1, inMatchFor = -1, 
+			inPseudo = -1, inClass = -1, inId = -1, inTag = -1, 
+			lc = "", cc = "", pStart;
+
+		// iteration vars
+		var x = 0, // index in the query
+			ql = query.length,
+			currentPart = null, // data structure representing the entire clause
+			_cp = null; // the current pseudo or attr matcher
+
+		// several temporary variables are assigned to this structure durring a
+		// potential sub-expression match:
+		//		attr:
+		//			a string representing the current full attribute match in a
+		//			bracket expression
+		//		type:
+		//			if there's an operator in a bracket expression, this is
+		//			used to keep track of it
+		//		value:
+		//			the internals of parenthetical expression for a pseudo. for
+		//			:nth-child(2n+1), value might be "2n+1"
+
+		var endTag = function(){
+			// called when the tokenizer hits the end of a particular tag name.
+			// Re-sets state variables for tag matching and sets up the matcher
+			// to handle the next type of token (tag or operator).
+			if(inTag >= 0){
+				var tv = (inTag == x) ? null : ts(inTag, x); // .toLowerCase();
+				currentPart[ (specials.indexOf(tv) < 0) ? "tag" : "oper" ] = tv;
+				inTag = -1;
+			}
+		}
+
+		var endId = function(){
+			// called when the tokenizer might be at the end of an ID portion of a match
+			if(inId >= 0){
+				currentPart.id = ts(inId, x).replace(/\\/g, "");
+				inId = -1;
+			}
+		}
+
+		var endClass = function(){
+			// called when the tokenizer might be at the end of a class name
+			// match. CSS allows for multiple classes, so we augment the
+			// current item with another class in its list
+			if(inClass >= 0){
+				currentPart.classes.push(ts(inClass+1, x).replace(/\\/g, ""));
+				inClass = -1;
+			}
+		}
+
+		var endAll = function(){
+			// at the end of a simple fragment, so wall off the matches
+			endId(); endTag(); endClass();
+		}
+
+		var endPart = function(){
+			endAll();
+			if(inPseudo >= 0){
+				currentPart.pseudos.push({ name: ts(inPseudo+1, x) });
+			}
+			// hint to the selector engine to tell it whether or not it
+			// needs to do any iteration. Many simple selectors don't, and
+			// we can avoid significant construction-time work by advising
+			// the system to skip them
+			currentPart.loops = (	
+					currentPart.pseudos.length || 
+					currentPart.attrs.length || 
+					currentPart.classes.length	);
+
+			currentPart.oquery = currentPart.query = ts(pStart, x); // save the full expression as a string
+
+
+			// otag/tag are hints to suggest to the system whether or not
+			// it's an operator or a tag. We save a copy of otag since the
+			// tag name is cast to upper-case in regular HTML matches. The
+			// system has a global switch to figure out if the current
+			// expression needs to be case sensitive or not and it will use
+			// otag or tag accordingly
+			currentPart.otag = currentPart.tag = (currentPart["oper"]) ? null : (currentPart.tag || "*");
+
+			if(currentPart.tag){
+				// if we're in a case-insensitive HTML doc, we likely want
+				// the toUpperCase when matching on element.tagName. If we
+				// do it here, we can skip the string op per node
+				// comparison
+				currentPart.tag = currentPart.tag.toUpperCase();
+			}
+
+			// add the part to the list
+			if(queryParts.length && (queryParts[queryParts.length-1].oper)){
+				// operators are always infix, so we remove them from the
+				// list and attach them to the next match. The evaluator is
+				// responsible for sorting out how to handle them.
+				currentPart.infixOper = queryParts.pop();
+				currentPart.query = currentPart.infixOper.query + " " + currentPart.query;
+				/*
+				console.debug(	"swapping out the infix", 
+								currentPart.infixOper, 
+								"and attaching it to", 
+								currentPart);
+				*/
+			}
+			queryParts.push(currentPart);
+
+			currentPart = null;
+		}
+
+		// iterate over the query, charachter by charachter, building up a 
+		// list of query part objects
+		for(; lc=cc, cc=query.charAt(x), x < ql; x++){
+			//		cc: the current character in the match
+			//		lc: the last charachter (if any)
+
+			// someone is trying to escape something, so don't try to match any
+			// fragments. We assume we're inside a literal.
+			if(lc == "\\"){ continue; } 
+			if(!currentPart){ // a part was just ended or none has yet been created
+				// NOTE: I hate all this alloc, but it's shorter than writing tons of if's
+				pStart = x;
+				//	rules describe full CSS sub-expressions, like:
+				//		#someId
+				//		.className:first-child
+				//	but not:
+				//		thinger > div.howdy[type=thinger]
+				//	the indidual components of the previous query would be
+				//	split into 3 parts that would be represented a structure
+				//	like:
+				//		[
+				//			{
+				//				query: "thinger",
+				//				tag: "thinger",
+				//			},
+				//			{
+				//				query: "div.howdy[type=thinger]",
+				//				classes: ["howdy"],
+				//				infixOper: {
+				//					query: ">",
+				//					oper: ">",
+				//				}
+				//			},
+				//		]
+				currentPart = {
+					query: null, // the full text of the part's rule
+					pseudos: [], // CSS supports multiple pseud-class matches in a single rule
+					attrs: [], 	// CSS supports multi-attribute match, so we need an array
+					classes: [], // class matches may be additive, e.g.: .thinger.blah.howdy
+					tag: null, 	// only one tag...
+					oper: null, // ...or operator per component. Note that these wind up being exclusive.
+					id: null, 	// the id component of a rule
+					getTag: function(){
+						return (caseSensitive) ? this.otag : this.tag;
+					}
+				};
+
+				// if we don't have a part, we assume we're going to start at
+				// the beginning of a match, which should be a tag name. This
+				// might fault a little later on, but we detect that and this
+				// iteration will still be fine.
+				inTag = x; 
+			}
+
+			if(inBrackets >= 0){
+				// look for a the close first
+				if(cc == "]"){ // if we're in a [...] clause and we end, do assignment
+					if(!_cp.attr){
+						// no attribute match was previously begun, so we
+						// assume this is an attribute existance match in the
+						// form of [someAttributeName]
+						_cp.attr = ts(inBrackets+1, x);
+					}else{
+						// we had an attribute already, so we know that we're
+						// matching some sort of value, as in [attrName=howdy]
+						_cp.matchFor = ts((inMatchFor||inBrackets+1), x);
+					}
+					var cmf = _cp.matchFor;
+					if(cmf){
+						// try to strip quotes from the matchFor value. We want
+						// [attrName=howdy] to match the same 
+						//	as [attrName = 'howdy' ]
+						if(	(cmf.charAt(0) == '"') || (cmf.charAt(0)  == "'") ){
+							_cp.matchFor = cmf.slice(1, -1);
+						}
+					}
+					// end the attribute by adding it to the list of attributes. 
+					currentPart.attrs.push(_cp);
+					_cp = null; // necessary?
+					inBrackets = inMatchFor = -1;
+				}else if(cc == "="){
+					// if the last char was an operator prefix, make sure we
+					// record it along with the "=" operator. 
+					var addToCc = ("|~^$*".indexOf(lc) >=0 ) ? lc : "";
+					_cp.type = addToCc+cc;
+					_cp.attr = ts(inBrackets+1, x-addToCc.length);
+					inMatchFor = x+1;
+				}
+				// now look for other clause parts
+			}else if(inParens >= 0){
+				// if we're in a parenthetical expression, we need to figure
+				// out if it's attached to a pseduo-selector rule like
+				// :nth-child(1)
+				if(cc == ")"){
+					if(inPseudo >= 0){
+						_cp.value = ts(inParens+1, x);
+					}
+					inPseudo = inParens = -1;
+				}
+			}else if(cc == "#"){
+				// start of an ID match
+				endAll();
+				inId = x+1;
+			}else if(cc == "."){
+				// start of a class match
+				endAll();
+				inClass = x;
+			}else if(cc == ":"){
+				// start of a pseudo-selector match
+				endAll();
+				inPseudo = x;
+			}else if(cc == "["){
+				// start of an attribute match. 
+				endAll();
+				inBrackets = x;
+				// provide a new structure for the attribute match to fill-in
+				_cp = {
+					/*=====
+					attr: null, type: null, matchFor: null
+					=====*/
+				};
+			}else if(cc == "("){
+				// we really only care if we've entered a parenthetical
+				// expression if we're already inside a pseudo-selector match
+				if(inPseudo >= 0){
+					// provide a new structure for the pseudo match to fill-in
+					_cp = { 
+						name: ts(inPseudo+1, x), 
+						value: null
+					}
+					currentPart.pseudos.push(_cp);
+				}
+				inParens = x;
+			}else if(
+				(cc == " ") && 
+				// if it's a space char and the last char is too, consume the
+				// current one without doing more work
+				(lc != cc)
+			){
+				endPart();
+			}
+		}
+		return queryParts;
+	};
+	
+
+	////////////////////////////////////////////////////////////////////////
+	// DOM query infrastructure
+	////////////////////////////////////////////////////////////////////////
+
+	var agree = function(first, second){
+		// the basic building block of the yes/no chaining system. agree(f1,
+		// f2) generates a new function which returns the boolean results of
+		// both of the passed functions to a single logical-anded result. If
+		// either are not possed, the other is used exclusively.
+		if(!first){ return second; }
+		if(!second){ return first; }
+
+		return function(){
+			return first.apply(window, arguments) && second.apply(window, arguments);
+		}
+	};
+
+	var getArr = function(i, arr){
+		// helps us avoid array alloc when we don't need it
+		var r = arr||[]; // FIXME: should this be 'new d._NodeListCtor()' ?
+		if(i){ r.push(i); }
+		return r;
+	};
+
+	var _isElement = function(n){ return (1 == n.nodeType); };
+
+	// FIXME: need to coalesce _getAttr with defaultGetter
+	var blank = "";
+	var _getAttr = function(elem, attr){
+		if(!elem){ return blank; }
+		if(attr == "class"){
+			return elem.className || blank;
+		}
+		if(attr == "for"){
+			return elem.htmlFor || blank;
+		}
+		if(attr == "style"){
+			return elem.style.cssText || blank;
+		}
+		return (caseSensitive ? elem.getAttribute(attr) : elem.getAttribute(attr, 2)) || blank;
+	};
+
+	var attrs = {
+		"*=": function(attr, value){
+			return function(elem){
+				// E[foo*="bar"]
+				//		an E element whose "foo" attribute value contains
+				//		the substring "bar"
+				return (_getAttr(elem, attr).indexOf(value)>=0);
+			}
+		},
+		"^=": function(attr, value){
+			// E[foo^="bar"]
+			//		an E element whose "foo" attribute value begins exactly
+			//		with the string "bar"
+			return function(elem){
+				return (_getAttr(elem, attr).indexOf(value)==0);
+			}
+		},
+		"$=": function(attr, value){
+			// E[foo$="bar"]	
+			//		an E element whose "foo" attribute value ends exactly
+			//		with the string "bar"
+			var tval = " "+value;
+			return function(elem){
+				var ea = " "+_getAttr(elem, attr);
+				return (ea.lastIndexOf(value)==(ea.length-value.length));
+			}
+		},
+		"~=": function(attr, value){
+			// E[foo~="bar"]	
+			//		an E element whose "foo" attribute value is a list of
+			//		space-separated values, one of which is exactly equal
+			//		to "bar"
+
+			// return "[contains(concat(' ',@"+attr+",' '), ' "+ value +" ')]";
+			var tval = " "+value+" ";
+			return function(elem){
+				var ea = " "+_getAttr(elem, attr)+" ";
+				return (ea.indexOf(tval)>=0);
+			}
+		},
+		"|=": function(attr, value){
+			// E[hreflang|="en"]
+			//		an E element whose "hreflang" attribute has a
+			//		hyphen-separated list of values beginning (from the
+			//		left) with "en"
+			var valueDash = " "+value+"-";
+			return function(elem){
+				var ea = " "+_getAttr(elem, attr);
+				return (
+					(ea == value) ||
+					(ea.indexOf(valueDash)==0)
+				);
+			}
+		},
+		"=": function(attr, value){
+			return function(elem){
+				return (_getAttr(elem, attr) == value);
+			}
+		}
+	};
+
+	// avoid testing for node type if we can. Defining this in the negative
+	// here to avoid negation in the fast path.
+	var _noNES = (typeof getDoc().firstChild.nextElementSibling == "undefined");
+	var _ns = !_noNES ? "nextElementSibling" : "nextSibling";
+	var _ps = !_noNES ? "previousElementSibling" : "previousSibling";
+	var _simpleNodeTest = (_noNES ? _isElement : yesman);
+
+	var _lookLeft = function(node){
+		// look left
+		while(node = node[_ps]){
+			if(_simpleNodeTest(node)){ return false; }
+		}
+		return true;
+	};
+
+	var _lookRight = function(node){
+		// look right
+		while(node = node[_ns]){
+			if(_simpleNodeTest(node)){ return false; }
+		}
+		return true;
+	};
+
+	var getNodeIndex = function(node){
+		var root = node.parentNode;
+		var i = 0,
+			tret = root[childNodesName],
+			ci = (node["_i"]||-1),
+			cl = (root["_l"]||-1);
+
+		if(!tret){ return -1; }
+		var l = tret.length;
+
+		// we calcuate the parent length as a cheap way to invalidate the
+		// cache. It's not 100% accurate, but it's much more honest than what
+		// other libraries do
+		if( cl == l && ci >= 0 && cl >= 0 ){
+			// if it's legit, tag and release
+			return ci;
+		}
+
+		// else re-key things
+		root["_l"] = l;
+		ci = -1;
+		for(var te = root["firstElementChild"]||root["firstChild"]; te; te = te[_ns]){
+			if(_simpleNodeTest(te)){ 
+				te["_i"] = ++i;
+				if(node === te){ 
+					// NOTE:
+					// 	shortcuting the return at this step in indexing works
+					// 	very well for benchmarking but we avoid it here since
+					// 	it leads to potential O(n^2) behavior in sequential
+					// 	getNodexIndex operations on a previously un-indexed
+					// 	parent. We may revisit this at a later time, but for
+					// 	now we just want to get the right answer more often
+					// 	than not.
+					ci = i;
+				}
+			}
+		}
+		return ci;
+	};
+
+	var isEven = function(elem){
+		return !((getNodeIndex(elem)) % 2);
+	};
+
+	var isOdd = function(elem){
+		return ((getNodeIndex(elem)) % 2);
+	};
+
+	var pseudos = {
+		"checked": function(name, condition){
+			return function(elem){
+				return !!("checked" in elem ? elem.checked : elem.selected);
+			}
+		},
+		"first-child": function(){ return _lookLeft; },
+		"last-child": function(){ return _lookRight; },
+		"only-child": function(name, condition){
+			return function(node){ 
+				if(!_lookLeft(node)){ return false; }
+				if(!_lookRight(node)){ return false; }
+				return true;
+			};
+		},
+		"empty": function(name, condition){
+			return function(elem){
+				// DomQuery and jQuery get this wrong, oddly enough.
+				// The CSS 3 selectors spec is pretty explicit about it, too.
+				var cn = elem.childNodes;
+				var cnl = elem.childNodes.length;
+				// if(!cnl){ return true; }
+				for(var x=cnl-1; x >= 0; x--){
+					var nt = cn[x].nodeType;
+					if((nt === 1)||(nt == 3)){ return false; }
+				}
+				return true;
+			}
+		},
+		"contains": function(name, condition){
+			var cz = condition.charAt(0);
+			if( cz == '"' || cz == "'" ){ //remove quote
+				condition = condition.slice(1, -1);
+			}
+			return function(elem){
+				return (elem.innerHTML.indexOf(condition) >= 0);
+			}
+		},
+		"not": function(name, condition){
+			var p = getQueryParts(condition)[0];
+			var ignores = { el: 1 }; 
+			if(p.tag != "*"){
+				ignores.tag = 1;
+			}
+			if(!p.classes.length){
+				ignores.classes = 1;
+			}
+			var ntf = getSimpleFilterFunc(p, ignores);
+			return function(elem){
+				return (!ntf(elem));
+			}
+		},
+		"nth-child": function(name, condition){
+			var pi = parseInt;
+			// avoid re-defining function objects if we can
+			if(condition == "odd"){
+				return isOdd;
+			}else if(condition == "even"){
+				return isEven;
+			}
+			// FIXME: can we shorten this?
+			if(condition.indexOf("n") != -1){
+				var tparts = condition.split("n", 2);
+				var pred = tparts[0] ? ((tparts[0] == '-') ? -1 : pi(tparts[0])) : 1;
+				var idx = tparts[1] ? pi(tparts[1]) : 0;
+				var lb = 0, ub = -1;
+				if(pred > 0){
+					if(idx < 0){
+						idx = (idx % pred) && (pred + (idx % pred));
+					}else if(idx>0){
+						if(idx >= pred){
+							lb = idx - idx % pred;
+						}
+						idx = idx % pred;
+					}
+				}else if(pred<0){
+					pred *= -1;
+					// idx has to be greater than 0 when pred is negative;
+					// shall we throw an error here?
+					if(idx > 0){
+						ub = idx;
+						idx = idx % pred;
+					}
+				}
+				if(pred > 0){
+					return function(elem){
+						var i = getNodeIndex(elem);
+						return (i>=lb) && (ub<0 || i<=ub) && ((i % pred) == idx);
+					}
+				}else{
+					condition = idx;
+				}
+			}
+			var ncount = pi(condition);
+			return function(elem){
+				return (getNodeIndex(elem) == ncount);
+			}
+		}
+	};
+
+	var defaultGetter = (d.isIE) ? function(cond){
+		var clc = cond.toLowerCase();
+		if(clc == "class"){ cond = "className"; }
+		return function(elem){
+			return (caseSensitive ? elem.getAttribute(cond) : elem[cond]||elem[clc]);
+		}
+	} : function(cond){
+		return function(elem){
+			return (elem && elem.getAttribute && elem.hasAttribute(cond));
+		}
+	};
+
+	var getSimpleFilterFunc = function(query, ignores){
+		// generates a node tester function based on the passed query part. The
+		// query part is one of the structures generatd by the query parser
+		// when it creates the query AST. The "ignores" object specifies which
+		// (if any) tests to skip, allowing the system to avoid duplicating
+		// work where it may have already been taken into account by other
+		// factors such as how the nodes to test were fetched in the first
+		// place
+		if(!query){ return yesman; }
+		ignores = ignores||{};
+
+		var ff = null;
+
+		if(!("el" in ignores)){
+			ff = agree(ff, _isElement);
+		}
+
+		if(!("tag" in ignores)){
+			if(query.tag != "*"){
+				ff = agree(ff, function(elem){
+					return (elem && (elem.tagName == query.getTag()));
+				});
+			}
+		}
+
+		if(!("classes" in ignores)){
+			each(query.classes, function(cname, idx, arr){
+				// get the class name
+				/*
+				var isWildcard = cname.charAt(cname.length-1) == "*";
+				if(isWildcard){
+					cname = cname.substr(0, cname.length-1);
+				}
+				// I dislike the regex thing, even if memozied in a cache, but it's VERY short
+				var re = new RegExp("(?:^|\\s)" + cname + (isWildcard ? ".*" : "") + "(?:\\s|$)");
+				*/
+				var re = new RegExp("(?:^|\\s)" + cname + "(?:\\s|$)");
+				ff = agree(ff, function(elem){
+					return re.test(elem.className);
+				});
+				ff.count = idx;
+			});
+		}
+
+		if(!("pseudos" in ignores)){
+			each(query.pseudos, function(pseudo){
+				var pn = pseudo.name;
+				if(pseudos[pn]){
+					ff = agree(ff, pseudos[pn](pn, pseudo.value));
+				}
+			});
+		}
+
+		if(!("attrs" in ignores)){
+			each(query.attrs, function(attr){
+				var matcher;
+				var a = attr.attr;
+				// type, attr, matchFor
+				if(attr.type && attrs[attr.type]){
+					matcher = attrs[attr.type](a, attr.matchFor);
+				}else if(a.length){
+					matcher = defaultGetter(a);
+				}
+				if(matcher){
+					ff = agree(ff, matcher);
+				}
+			});
+		}
+
+		if(!("id" in ignores)){
+			if(query.id){
+				ff = agree(ff, function(elem){ 
+					return (!!elem && (elem.id == query.id));
+				});
+			}
+		}
+
+		if(!ff){
+			if(!("default" in ignores)){
+				ff = yesman; 
+			}
+		}
+		return ff;
+	};
+
+	var _nextSibling = function(filterFunc){
+		return function(node, ret, bag){
+			while(node = node[_ns]){
+				if(_noNES && (!_isElement(node))){ continue; }
+				if(
+					(!bag || _isUnique(node, bag)) &&
+					filterFunc(node)
+				){
+					ret.push(node);
+				}
+				break;
+			}
+			return ret;
+		}
+	};
+
+	var _nextSiblings = function(filterFunc){
+		return function(root, ret, bag){
+			var te = root[_ns];
+			while(te){
+				if(_simpleNodeTest(te)){
+					if(bag && !_isUnique(te, bag)){
+						break;
+					}
+					if(filterFunc(te)){
+						ret.push(te);
+					}
+				}
+				te = te[_ns];
+			}
+			return ret;
+		}
+	};
+
+	// get an array of child *elements*, skipping text and comment nodes
+	var _childElements = function(filterFunc){
+		filterFunc = filterFunc||yesman;
+		return function(root, ret, bag){
+			// get an array of child elements, skipping text and comment nodes
+			var te, x = 0, tret = root[childNodesName];
+			while(te = tret[x++]){
+				if(
+					_simpleNodeTest(te) &&
+					(!bag || _isUnique(te, bag)) &&
+					(filterFunc(te, x))
+				){ 
+					ret.push(te);
+				}
+			}
+			return ret;
+		};
+	};
+	
+	/*
+	// thanks, Dean!
+	var itemIsAfterRoot = d.isIE ? function(item, root){
+		return (item.sourceIndex > root.sourceIndex);
+	} : function(item, root){
+		return (item.compareDocumentPosition(root) == 2);
+	};
+	*/
+
+	// test to see if node is below root
+	var _isDescendant = function(node, root){
+		var pn = node.parentNode;
+		while(pn){
+			if(pn == root){
+				break;
+			}
+			pn = pn.parentNode;
+		}
+		return !!pn;
+	};
+
+	var _getElementsFuncCache = {};
+
+	var getElementsFunc = function(query){
+		var retFunc = _getElementsFuncCache[query.query];
+		// if we've got a cached dispatcher, just use that
+		if(retFunc){ return retFunc; }
+		// else, generate a new on
+
+		// NOTE:
+		//		this function returns a function that searches for nodes and
+		//		filters them.  The search may be specialized by infix operators
+		//		(">", "~", or "+") else it will default to searching all
+		//		descendants (the " " selector). Once a group of children is
+		//		founde, a test function is applied to weed out the ones we
+		//		don't want. Many common cases can be fast-pathed. We spend a
+		//		lot of cycles to create a dispatcher that doesn't do more work
+		//		than necessary at any point since, unlike this function, the
+		//		dispatchers will be called every time. The logic of generating
+		//		efficient dispatchers looks like this in pseudo code:
+		//
+		//		# if it's a purely descendant query (no ">", "+", or "~" modifiers)
+		//		if infixOperator == " ":
+		//			if only(id):
+		//				return def(root):
+		//					return d.byId(id, root);
+		//
+		//			elif id:
+		//				return def(root):
+		//					return filter(d.byId(id, root));
+		//
+		//			elif cssClass && getElementsByClassName:
+		//				return def(root):
+		//					return filter(root.getElementsByClassName(cssClass));
+		//
+		//			elif only(tag):
+		//				return def(root):
+		//					return root.getElementsByTagName(tagName);
+		//
+		//			else:
+		//				# search by tag name, then filter
+		//				return def(root):
+		//					return filter(root.getElementsByTagName(tagName||"*"));
+		//
+		//		elif infixOperator == ">":
+		//			# search direct children
+		//			return def(root):
+		//				return filter(root.children);
+		//
+		//		elif infixOperator == "+":
+		//			# search next sibling
+		//			return def(root):
+		//				return filter(root.nextElementSibling);
+		//
+		//		elif infixOperator == "~":
+		//			# search rightward siblings
+		//			return def(root):
+		//				return filter(nextSiblings(root));
+
+		var io = query.infixOper;
+		var oper = (io ? io.oper : "");
+		// the default filter func which tests for all conditions in the query
+		// part. This is potentially inefficient, so some optimized paths may
+		// re-define it to test fewer things.
+		var filterFunc = getSimpleFilterFunc(query, { el: 1 });
+		var qt = query.tag;
+		var wildcardTag = ("*" == qt);
+		var ecs = getDoc()["getElementsByClassName"]; 
+
+		if(!oper){
+			// if there's no infix operator, then it's a descendant query. ID
+			// and "elements by class name" variants can be accelerated so we
+			// call them out explicitly:
+			if(query.id){
+				// testing shows that the overhead of yesman() is acceptable
+				// and can save us some bytes vs. re-defining the function
+				// everywhere.
+				filterFunc = (!query.loops && wildcardTag) ? 
+					yesman : 
+					getSimpleFilterFunc(query, { el: 1, id: 1 });
+
+				retFunc = function(root, arr){
+					var te = d.byId(query.id, (root.ownerDocument||root));
+					if(!te || !filterFunc(te)){ return; }
+					if(9 == root.nodeType){ // if root's a doc, we just return directly
+						return getArr(te, arr);
+					}else{ // otherwise check ancestry
+						if(_isDescendant(te, root)){
+							return getArr(te, arr);
+						}
+					}
+				}
+			}else if(
+				ecs && 
+				// isAlien check. Workaround for Prototype.js being totally evil/dumb.
+				/\{\s*\[native code\]\s*\}/.test(String(ecs)) && 
+				query.classes.length &&
+				!cssCaseBug
+			){
+				// it's a class-based query and we've got a fast way to run it.
+
+				// ignore class and ID filters since we will have handled both
+				filterFunc = getSimpleFilterFunc(query, { el: 1, classes: 1, id: 1 });
+				var classesString = query.classes.join(" ");
+				retFunc = function(root, arr, bag){
+					var ret = getArr(0, arr), te, x=0;
+					var tret = root.getElementsByClassName(classesString);
+					while((te = tret[x++])){
+						if(filterFunc(te, root) && _isUnique(te, bag)){
+							ret.push(te);
+						}
+					}
+					return ret;
+				};
+
+			}else if(!wildcardTag && !query.loops){
+				// it's tag only. Fast-path it.
+				retFunc = function(root, arr, bag){
+					var ret = getArr(0, arr), te, x=0;
+					var tret = root.getElementsByTagName(query.getTag());
+					while((te = tret[x++])){
+						if(_isUnique(te, bag)){
+							ret.push(te);
+						}
+					}
+					return ret;
+				};
+			}else{
+				// the common case:
+				//		a descendant selector without a fast path. By now it's got
+				//		to have a tag selector, even if it's just "*" so we query
+				//		by that and filter
+				filterFunc = getSimpleFilterFunc(query, { el: 1, tag: 1, id: 1 });
+				retFunc = function(root, arr, bag){
+					var ret = getArr(0, arr), te, x=0;
+					// we use getTag() to avoid case sensitivity issues
+					var tret = root.getElementsByTagName(query.getTag());
+					while((te = tret[x++])){
+						if(filterFunc(te, root) && _isUnique(te, bag)){
+							ret.push(te);
+						}
+					}
+					return ret;
+				};
+			}
+		}else{
+			// the query is scoped in some way. Instead of querying by tag we
+			// use some other collection to find candidate nodes
+			var skipFilters = { el: 1 };
+			if(wildcardTag){
+				skipFilters.tag = 1;
+			}
+			filterFunc = getSimpleFilterFunc(query, skipFilters);
+			if("+" == oper){
+				retFunc = _nextSibling(filterFunc);
+			}else if("~" == oper){
+				retFunc = _nextSiblings(filterFunc);
+			}else if(">" == oper){
+				retFunc = _childElements(filterFunc);
+			}
+		}
+		// cache it and return
+		return _getElementsFuncCache[query.query] = retFunc;
+	};
+
+	var filterDown = function(root, queryParts){
+		// NOTE:
+		//		this is the guts of the DOM query system. It takes a list of
+		//		parsed query parts and a root and finds children which match
+		//		the selector represented by the parts
+		var candidates = getArr(root), qp, x, te, qpl = queryParts.length, bag, ret;
+
+		for(var i = 0; i < qpl; i++){
+			ret = [];
+			qp = queryParts[i];
+			x = candidates.length - 1;
+			if(x > 0){
+				// if we have more than one root at this level, provide a new
+				// hash to use for checking group membership but tell the
+				// system not to post-filter us since we will already have been
+				// gauranteed to be unique
+				bag = {};
+				ret.nozip = true;
+			}
+			var gef = getElementsFunc(qp);
+			for(var j = 0; (te = candidates[j]); j++){
+				// for every root, get the elements that match the descendant
+				// selector, adding them to the "ret" array and filtering them
+				// via membership in this level's bag. If there are more query
+				// parts, then this level's return will be used as the next
+				// level's candidates
+				gef(te, ret, bag);
+			}
+			if(!ret.length){ break; }
+			candidates = ret;
+		}
+		return ret;
+	};
+
+	////////////////////////////////////////////////////////////////////////
+	// the query runner
+	////////////////////////////////////////////////////////////////////////
+
+	// these are the primary caches for full-query results. The query
+	// dispatcher functions are generated then stored here for hash lookup in
+	// the future
+	var _queryFuncCacheDOM = {},
+		_queryFuncCacheQSA = {};
+
+	// this is the second level of spliting, from full-length queries (e.g.,
+	// "div.foo .bar") into simple query expressions (e.g., ["div.foo",
+	// ".bar"])
+	var getStepQueryFunc = function(query){
+		var qparts = getQueryParts(trim(query));
+
+		// if it's trivial, avoid iteration and zipping costs
+		if(qparts.length == 1){
+			// we optimize this case here to prevent dispatch further down the
+			// chain, potentially slowing things down. We could more elegantly
+			// handle this in filterDown(), but it's slower for simple things
+			// that need to be fast (e.g., "#someId").
+			var tef = getElementsFunc(qparts[0]);
+			return function(root){
+				var r = tef(root, new qlc());
+				if(r){ r.nozip = true; }
+				return r;
+			}
+		}
+
+		// otherwise, break it up and return a runner that iterates over the parts recursively
+		return function(root){
+			return filterDown(root, qparts);
+		}
+	};
+
+	// NOTES:
+	//	* we can't trust QSA for anything but document-rooted queries, so
+	//	  caching is split into DOM query evaluators and QSA query evaluators
+	//	* caching query results is dirty and leak-prone (or, at a minimum,
+	//	  prone to unbounded growth). Other toolkits may go this route, but
+	//	  they totally destroy their own ability to manage their memory
+	//	  footprint. If we implement it, it should only ever be with a fixed
+	//	  total element reference # limit and an LRU-style algorithm since JS
+	//	  has no weakref support. Caching compiled query evaluators is also
+	//	  potentially problematic, but even on large documents the size of the
+	//	  query evaluators is often < 100 function objects per evaluator (and
+	//	  LRU can be applied if it's ever shown to be an issue).
+	//	* since IE's QSA support is currently only for HTML documents and even
+	//	  then only in IE 8's "standards mode", we have to detect our dispatch
+	//	  route at query time and keep 2 separate caches. Ugg.
+
+	// we need to determine if we think we can run a given query via
+	// querySelectorAll or if we'll need to fall back on DOM queries to get
+	// there. We need a lot of information about the environment and the query
+	// to make the determiniation (e.g. does it support QSA, does the query in
+	// question work in the native QSA impl, etc.).
+	var nua = navigator.userAgent;
+	// some versions of Safari provided QSA, but it was buggy and crash-prone.
+	// We need te detect the right "internal" webkit version to make this work.
+	var wk = "WebKit/";
+	var is525 = (
+		d.isWebKit && 
+		(nua.indexOf(wk) > 0) && 
+		(parseFloat(nua.split(wk)[1]) > 528)
+	);
+
+	// IE QSA queries may incorrectly include comment nodes, so we throw the
+	// zipping function into "remove" comments mode instead of the normal "skip
+	// it" which every other QSA-clued browser enjoys
+	var noZip = d.isIE ? "commentStrip" : "nozip";
+
+	var qsa = "querySelectorAll";
+	var qsaAvail = (
+		!!getDoc()[qsa] && 
+		// see #5832
+		(!d.isSafari || (d.isSafari > 3.1) || is525 )
+	);
+
+	//Don't bother with n+3 type of matches, IE complains if we modify those.
+	var infixSpaceRe = /n\+\d|([^ ])?([>~+])([^ =])?/g;
+	var infixSpaceFunc = function(match, pre, ch, post) {
+		return ch ? (pre ? pre + " " : "") + ch + (post ? " " + post : "") : /*n+3*/ match;
+	};
+
+	var getQueryFunc = function(query, forceDOM){
+		//Normalize query. The CSS3 selectors spec allows for omitting spaces around
+		//infix operators, >, ~ and +
+		//Do the work here since detection for spaces is used as a simple "not use QSA"
+		//test below.
+		query = query.replace(infixSpaceRe, infixSpaceFunc);
+
+		if(qsaAvail){
+			// if we've got a cached variant and we think we can do it, run it!
+			var qsaCached = _queryFuncCacheQSA[query];
+			if(qsaCached && !forceDOM){ return qsaCached; }
+		}
+
+		// else if we've got a DOM cached variant, assume that we already know
+		// all we need to and use it
+		var domCached = _queryFuncCacheDOM[query];
+		if(domCached){ return domCached; }
+
+		// TODO: 
+		//		today we're caching DOM and QSA branches separately so we
+		//		recalc useQSA every time. If we had a way to tag root+query
+		//		efficiently, we'd be in good shape to do a global cache.
+
+		var qcz = query.charAt(0);
+		var nospace = (-1 == query.indexOf(" "));
+
+		// byId searches are wicked fast compared to QSA, even when filtering
+		// is required
+		if( (query.indexOf("#") >= 0) && (nospace) ){
+			forceDOM = true;
+		}
+
+		var useQSA = ( 
+			qsaAvail && (!forceDOM) &&
+			// as per CSS 3, we can't currently start w/ combinator:
+			//		http://www.w3.org/TR/css3-selectors/#w3cselgrammar
+			(specials.indexOf(qcz) == -1) && 
+			// IE's QSA impl sucks on pseudos
+			(!d.isIE || (query.indexOf(":") == -1)) &&
+
+			(!(cssCaseBug && (query.indexOf(".") >= 0))) &&
+
+			// FIXME:
+			//		need to tighten up browser rules on ":contains" and "|=" to
+			//		figure out which aren't good
+			//		Latest webkit (around 531.21.8) does not seem to do well with :checked on option
+			//		elements, even though according to spec, selected options should
+			//		match :checked. So go nonQSA for it:
+			//		http://bugs.dojotoolkit.org/ticket/5179
+			(query.indexOf(":contains") == -1) && (query.indexOf(":checked") == -1) && 
+			(query.indexOf("|=") == -1) // some browsers don't grok it
+		);
+
+		// TODO: 
+		//		if we've got a descendant query (e.g., "> .thinger" instead of
+		//		just ".thinger") in a QSA-able doc, but are passed a child as a
+		//		root, it should be possible to give the item a synthetic ID and
+		//		trivially rewrite the query to the form "#synid > .thinger" to
+		//		use the QSA branch
+
+
+		if(useQSA){
+			var tq = (specials.indexOf(query.charAt(query.length-1)) >= 0) ? 
+						(query + " *") : query;
+			return _queryFuncCacheQSA[query] = function(root){
+				try{
+					// the QSA system contains an egregious spec bug which
+					// limits us, effectively, to only running QSA queries over
+					// entire documents.  See:
+					//		http://ejohn.org/blog/thoughts-on-queryselectorall/
+					//	despite this, we can also handle QSA runs on simple
+					//	selectors, but we don't want detection to be expensive
+					//	so we're just checking for the presence of a space char
+					//	right now. Not elegant, but it's cheaper than running
+					//	the query parser when we might not need to
+					if(!((9 == root.nodeType) || nospace)){ throw ""; }
+					var r = root[qsa](tq);
+					// skip expensive duplication checks and just wrap in a NodeList
+					r[noZip] = true;
+					return r;
+				}catch(e){
+					// else run the DOM branch on this query, ensuring that we
+					// default that way in the future
+					return getQueryFunc(query, true)(root);
+				}
+			}
+		}else{
+			// DOM branch
+			var parts = query.split(/\s*,\s*/);
+			return _queryFuncCacheDOM[query] = ((parts.length < 2) ? 
+				// if not a compound query (e.g., ".foo, .bar"), cache and return a dispatcher
+				getStepQueryFunc(query) : 
+				// if it *is* a complex query, break it up into its
+				// constituent parts and return a dispatcher that will
+				// merge the parts when run
+				function(root){
+					var pindex = 0, // avoid array alloc for every invocation
+						ret = [],
+						tp;
+					while((tp = parts[pindex++])){
+						ret = ret.concat(getStepQueryFunc(tp)(root));
+					}
+					return ret;
+				}
+			);
+		}
+	};
+
+	var _zipIdx = 0;
+
+	// NOTE:
+	//		this function is Moo inspired, but our own impl to deal correctly
+	//		with XML in IE
+	var _nodeUID = d.isIE ? function(node){
+		if(caseSensitive){
+			// XML docs don't have uniqueID on their nodes
+			return (node.getAttribute("_uid") || node.setAttribute("_uid", ++_zipIdx) || _zipIdx);
+
+		}else{
+			return node.uniqueID;
+		}
+	} : 
+	function(node){
+		return (node._uid || (node._uid = ++_zipIdx));
+	};
+
+	// determine if a node in is unique in a "bag". In this case we don't want
+	// to flatten a list of unique items, but rather just tell if the item in
+	// question is already in the bag. Normally we'd just use hash lookup to do
+	// this for us but IE's DOM is busted so we can't really count on that. On
+	// the upside, it gives us a built in unique ID function. 
+	var _isUnique = function(node, bag){
+		if(!bag){ return 1; }
+		var id = _nodeUID(node);
+		if(!bag[id]){ return bag[id] = 1; }
+		return 0;
+	};
+
+	// attempt to efficiently determine if an item in a list is a dupe,
+	// returning a list of "uniques", hopefully in doucment order
+	var _zipIdxName = "_zipIdx";
+	var _zip = function(arr){
+		if(arr && arr.nozip){ 
+			return (qlc._wrap) ? qlc._wrap(arr) : arr;
+		}
+		// var ret = new d._NodeListCtor();
+		var ret = new qlc();
+		if(!arr || !arr.length){ return ret; }
+		if(arr[0]){
+			ret.push(arr[0]);
+		}
+		if(arr.length < 2){ return ret; }
+
+		_zipIdx++;
+		
+		// we have to fork here for IE and XML docs because we can't set
+		// expandos on their nodes (apparently). *sigh*
+		if(d.isIE && caseSensitive){
+			var szidx = _zipIdx+"";
+			arr[0].setAttribute(_zipIdxName, szidx);
+			for(var x = 1, te; te = arr[x]; x++){
+				if(arr[x].getAttribute(_zipIdxName) != szidx){ 
+					ret.push(te);
+				}
+				te.setAttribute(_zipIdxName, szidx);
+			}
+		}else if(d.isIE && arr.commentStrip){
+			try{
+				for(var x = 1, te; te = arr[x]; x++){
+					if(_isElement(te)){ 
+						ret.push(te);
+					}
+				}
+			}catch(e){ /* squelch */ }
+		}else{
+			if(arr[0]){ arr[0][_zipIdxName] = _zipIdx; }
+			for(var x = 1, te; te = arr[x]; x++){
+				if(arr[x][_zipIdxName] != _zipIdx){ 
+					ret.push(te);
+				}
+				te[_zipIdxName] = _zipIdx;
+			}
+		}
+		return ret;
+	};
+
+	// the main executor
+	d.query = function(/*String*/ query, /*String|DOMNode?*/ root){
+		//	summary:
+		//		Returns nodes which match the given CSS3 selector, searching the
+		//		entire document by default but optionally taking a node to scope
+		//		the search by. Returns an instance of dojo.NodeList.
+		//	description:
+		//		dojo.query() is the swiss army knife of DOM node manipulation in
+		//		Dojo. Much like Prototype's "$$" (bling-bling) function or JQuery's
+		//		"$" function, dojo.query provides robust, high-performance
+		//		CSS-based node selector support with the option of scoping searches
+		//		to a particular sub-tree of a document.
+		//
+		//		Supported Selectors:
+		//		--------------------
+		//
+		//		dojo.query() supports a rich set of CSS3 selectors, including:
+		//
+		//			* class selectors (e.g., `.foo`)
+		//			* node type selectors like `span`
+		//			* ` ` descendant selectors
+		//			* `>` child element selectors 
+		//			* `#foo` style ID selectors
+		//			* `*` universal selector
+		//			* `~`, the immediately preceeded-by sibling selector
+		//			* `+`, the preceeded-by sibling selector
+		//			* attribute queries:
+		//			|	* `[foo]` attribute presence selector
+		//			|	* `[foo='bar']` attribute value exact match
+		//			|	* `[foo~='bar']` attribute value list item match
+		//			|	* `[foo^='bar']` attribute start match
+		//			|	* `[foo$='bar']` attribute end match
+		//			|	* `[foo*='bar']` attribute substring match
+		//			* `:first-child`, `:last-child`, and `:only-child` positional selectors
+		//			* `:empty` content emtpy selector
+		//			* `:checked` pseudo selector
+		//			* `:nth-child(n)`, `:nth-child(2n+1)` style positional calculations
+		//			* `:nth-child(even)`, `:nth-child(odd)` positional selectors
+		//			* `:not(...)` negation pseudo selectors
+		//
+		//		Any legal combination of these selectors will work with
+		//		`dojo.query()`, including compound selectors ("," delimited).
+		//		Very complex and useful searches can be constructed with this
+		//		palette of selectors and when combined with functions for
+		//		manipulation presented by dojo.NodeList, many types of DOM
+		//		manipulation operations become very straightforward.
+		//		
+		//		Unsupported Selectors:
+		//		----------------------
+		//
+		//		While dojo.query handles many CSS3 selectors, some fall outside of
+		//		what's resaonable for a programmatic node querying engine to
+		//		handle. Currently unsupported selectors include:
+		//		
+		//			* namespace-differentiated selectors of any form
+		//			* all `::` pseduo-element selectors
+		//			* certain pseduo-selectors which don't get a lot of day-to-day use:
+		//			|	* `:root`, `:lang()`, `:target`, `:focus`
+		//			* all visual and state selectors:
+		//			|	* `:root`, `:active`, `:hover`, `:visisted`, `:link`,
+		//				  `:enabled`, `:disabled`
+		//			* `:*-of-type` pseudo selectors
+		//		
+		//		dojo.query and XML Documents:
+		//		-----------------------------
+		//		
+		//		`dojo.query` (as of dojo 1.2) supports searching XML documents
+		//		in a case-sensitive manner. If an HTML document is served with
+		//		a doctype that forces case-sensitivity (e.g., XHTML 1.1
+		//		Strict), dojo.query() will detect this and "do the right
+		//		thing". Case sensitivity is dependent upon the document being
+		//		searched and not the query used. It is therefore possible to
+		//		use case-sensitive queries on strict sub-documents (iframes,
+		//		etc.) or XML documents while still assuming case-insensitivity
+		//		for a host/root document.
+		//
+		//		Non-selector Queries:
+		//		---------------------
+		//
+		//		If something other than a String is passed for the query,
+		//		`dojo.query` will return a new `dojo.NodeList` instance
+		//		constructed from that parameter alone and all further
+		//		processing will stop. This means that if you have a reference
+		//		to a node or NodeList, you can quickly construct a new NodeList
+		//		from the original by calling `dojo.query(node)` or
+		//		`dojo.query(list)`.
+		//
+		//	query:
+		//		The CSS3 expression to match against. For details on the syntax of
+		//		CSS3 selectors, see <http://www.w3.org/TR/css3-selectors/#selectors>
+		//	root:
+		//		A DOMNode (or node id) to scope the search from. Optional.
+		//	returns: dojo.NodeList
+		//		An instance of `dojo.NodeList`. Many methods are available on
+		//		NodeLists for searching, iterating, manipulating, and handling
+		//		events on the matched nodes in the returned list.
+		//	example:
+		//		search the entire document for elements with the class "foo":
+		//	|	dojo.query(".foo");
+		//		these elements will match:
+		//	|	<span class="foo"></span>
+		//	|	<span class="foo bar"></span>
+		//	|	<p class="thud foo"></p>
+		//	example:
+		//		search the entire document for elements with the classes "foo" *and* "bar":
+		//	|	dojo.query(".foo.bar");
+		//		these elements will match:
+		//	|	<span class="foo bar"></span>
+		//		while these will not:
+		//	|	<span class="foo"></span>
+		//	|	<p class="thud foo"></p>
+		//	example:
+		//		find `<span>` elements which are descendants of paragraphs and
+		//		which have a "highlighted" class:
+		//	|	dojo.query("p span.highlighted");
+		//		the innermost span in this fragment matches:
+		//	|	<p class="foo">
+		//	|		<span>...
+		//	|			<span class="highlighted foo bar">...</span>
+		//	|		</span>
+		//	|	</p>
+		//	example:
+		//		set an "odd" class on all odd table rows inside of the table
+		//		`#tabular_data`, using the `>` (direct child) selector to avoid
+		//		affecting any nested tables:
+		//	|	dojo.query("#tabular_data > tbody > tr:nth-child(odd)").addClass("odd");
+		//	example:
+		//		remove all elements with the class "error" from the document
+		//		and store them in a list:
+		//	|	var errors = dojo.query(".error").orphan();
+		//	example:
+		//		add an onclick handler to every submit button in the document
+		//		which causes the form to be sent via Ajax instead:
+		//	|	dojo.query("input[type='submit']").onclick(function(e){
+		//	|		dojo.stopEvent(e); // prevent sending the form
+		//	|		var btn = e.target;
+		//	|		dojo.xhrPost({
+		//	|			form: btn.form,
+		//	|			load: function(data){
+		//	|				// replace the form with the response
+		//	|				var div = dojo.doc.createElement("div");
+		//	|				dojo.place(div, btn.form, "after");
+		//	|				div.innerHTML = data;
+		//	|				dojo.style(btn.form, "display", "none");
+		//	|			}
+		//	|		});
+		//	|	});
+
+		//Set list constructor to desired value. This can change
+		//between calls, so always re-assign here.
+		qlc = d._NodeListCtor;
+
+		if(!query){
+			return new qlc();
+		}
+
+		if(query.constructor == qlc){
+			return query;
+		}
+		if(typeof query != "string"){ // inline'd type check
+			return new qlc(query); // dojo.NodeList
+		}
+		if(typeof root == "string"){ // inline'd type check
+			root = d.byId(root);
+			if(!root){ return new qlc(); }
+		}
+
+		root = root||getDoc();
+		var od = root.ownerDocument||root.documentElement;
+
+		// throw the big case sensitivity switch
+
+		// NOTE:
+		// 		Opera in XHTML mode doesn't detect case-sensitivity correctly
+		// 		and it's not clear that there's any way to test for it
+		caseSensitive = (root.contentType && root.contentType=="application/xml") || 
+						(d.isOpera && (root.doctype || od.toString() == "[object XMLDocument]")) ||
+						(!!od) && 
+						(d.isIE ? od.xml : (root.xmlVersion||od.xmlVersion));
+
+		// NOTE: 
+		//		adding "true" as the 2nd argument to getQueryFunc is useful for
+		//		testing the DOM branch without worrying about the
+		//		behavior/performance of the QSA branch.
+		var r = getQueryFunc(query)(root);
+
+		// FIXME:
+		//		need to investigate this branch WRT #8074 and #8075
+		if(r && r.nozip && !qlc._wrap){
+			return r;
+		}
+		return _zip(r); // dojo.NodeList
+	}
+
+	// FIXME: need to add infrastructure for post-filtering pseudos, ala :last
+	d.query.pseudos = pseudos;
+
+	// one-off function for filtering a NodeList based on a simple selector
+	d._filterQueryResult = function(nodeList, simpleFilter){
+		var tmpNodeList = new d._NodeListCtor();
+		var filterFunc = getSimpleFilterFunc(getQueryParts(simpleFilter)[0]);
+		for(var x = 0, te; te = nodeList[x]; x++){
+			if(filterFunc(te)){ tmpNodeList.push(te); }
+		}
+		return tmpNodeList;
+	}
 })(this["queryPortability"]||this["acme"]||dojo);
-}
+//>>excludeEnd("webkitMobile");
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+/*
+//>>excludeEnd("webkitMobile");
+//>>includeStart("webkitMobile", kwArgs.webkitMobile);
+if(!dojo["query"]){
+	(function(){
+		var ctr = 0;
+		// QSA-only for webkit mobile. Welcome to the future.
+		dojo.query = function(query, root){
+			d._NodeListCtor = dojo.NodeList;
+			if(!query){
+				return new d._NodeListCtor();
+			}
+
+			if(query.constructor == d._NodeListCtor){
+				return query;
+			}
+
+			if(typeof query != "string"){ // inline'd type check
+				return new d._NodeListCtor(query); // dojo.NodeList
+			}
+
+			if(typeof root == "string"){ // inline'd type check
+				root = dojo.byId(root);
+				if(!root){ return new d._NodeListCtor(); }
+			}
+
+			root = root||dojo.doc;
+			var rootIsDoc = (root.nodeType == 9);
+			var doc = rootIsDoc ? root : (root.ownerDocument||dojo.doc);
+			// rewrite the query to be ID rooted
+			if(!rootIsDoc || (">~+".indexOf(query.charAt(0)) >= 0)){
+				root.id = root.id||("qUnique"+(ctr++));
+				query = "#"+root.id+" "+query;
+			}
+			// rewrite the query to not choke on something like ".yada.yada >"
+			// by adding a final descendant component
+
+			if(">~+".indexOf(query.slice(-1)) >= 0){
+				query += " *";
+			}
+			return d._NodeListCtor._wrap(
+				Array.prototype.slice.call(
+					doc.querySelectorAll(query)
+				)
+			);
+		};
+	})();
+}
+//>>includeEnd("webkitMobile");
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+*/
+//>>excludeEnd("webkitMobile");
diff --git a/dojo/_base/window.js b/dojo/_base/window.js
index 4e5f36d..5705614 100644
--- a/dojo/_base/window.js
+++ b/dojo/_base/window.js
@@ -1,49 +1,97 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.window"]){
-dojo._hasResource["dojo._base.window"]=true;
 dojo.provide("dojo._base.window");
-dojo.doc=window["document"]||null;
-dojo.body=function(){
-return dojo.doc.body||dojo.doc.getElementsByTagName("body")[0];
-};
-dojo.setContext=function(_1,_2){
-dojo.global=_1;
-dojo.doc=_2;
-};
-dojo.withGlobal=function(_3,_4,_5,_6){
-var _7=dojo.global;
-try{
-dojo.global=_3;
-return dojo.withDoc.call(null,_3.document,_4,_5,_6);
+
+/*=====
+dojo.doc = {
+	// summary:
+	//		Alias for the current document. 'dojo.doc' can be modified
+	//		for temporary context shifting. Also see dojo.withDoc().
+	// description:
+	//    Refer to dojo.doc rather
+	//    than referring to 'window.document' to ensure your code runs
+	//    correctly in managed contexts.
+	// example:
+	// 	|	n.appendChild(dojo.doc.createElement('div'));
 }
-finally{
-dojo.global=_7;
+=====*/
+dojo.doc = window["document"] || null;
+
+dojo.body = function(){
+	// summary:
+	//		Return the body element of the document
+	//		return the body object associated with dojo.doc
+	// example:
+	// 	|	dojo.body().appendChild(dojo.doc.createElement('div'));
+
+	// Note: document.body is not defined for a strict xhtml document
+	// Would like to memoize this, but dojo.doc can change vi dojo.withDoc().
+	return dojo.doc.body || dojo.doc.getElementsByTagName("body")[0]; // Node
 }
+
+dojo.setContext = function(/*Object*/globalObject, /*DocumentElement*/globalDocument){
+	// summary:
+	//		changes the behavior of many core Dojo functions that deal with
+	//		namespace and DOM lookup, changing them to work in a new global
+	//		context (e.g., an iframe). The varibles dojo.global and dojo.doc
+	//		are modified as a result of calling this function and the result of
+	//		`dojo.body()` likewise differs.
+	dojo.global = globalObject;
+	dojo.doc = globalDocument;
 };
-dojo.withDoc=function(_8,_9,_a,_b){
-var _c=dojo.doc,_d=dojo._bodyLtr,_e=dojo.isQuirks;
-try{
-dojo.doc=_8;
-delete dojo._bodyLtr;
-dojo.isQuirks=dojo.doc.compatMode=="BackCompat";
-if(_a&&typeof _9=="string"){
-_9=_a[_9];
-}
-return _9.apply(_a,_b||[]);
-}
-finally{
-dojo.doc=_c;
-delete dojo._bodyLtr;
-if(_d!==undefined){
-dojo._bodyLtr=_d;
-}
-dojo.isQuirks=_e;
+
+dojo.withGlobal = function(	/*Object*/globalObject, 
+							/*Function*/callback, 
+							/*Object?*/thisObject, 
+							/*Array?*/cbArguments){
+	// summary:
+	//		Invoke callback with globalObject as dojo.global and
+	//		globalObject.document as dojo.doc.
+	// description:
+	//		Invoke callback with globalObject as dojo.global and
+	//		globalObject.document as dojo.doc. If provided, globalObject
+	//		will be executed in the context of object thisObject
+	//		When callback() returns or throws an error, the dojo.global
+	//		and dojo.doc will be restored to its previous state.
+
+	var oldGlob = dojo.global;
+	try{
+		dojo.global = globalObject;
+		return dojo.withDoc.call(null, globalObject.document, callback, thisObject, cbArguments);
+	}finally{
+		dojo.global = oldGlob;
+	}
 }
+
+dojo.withDoc = function(	/*DocumentElement*/documentObject, 
+							/*Function*/callback, 
+							/*Object?*/thisObject, 
+							/*Array?*/cbArguments){
+	// summary:
+	//		Invoke callback with documentObject as dojo.doc.
+	// description:
+	//		Invoke callback with documentObject as dojo.doc. If provided,
+	//		callback will be executed in the context of object thisObject
+	//		When callback() returns or throws an error, the dojo.doc will
+	//		be restored to its previous state.
+
+	var oldDoc = dojo.doc,
+		oldLtr = dojo._bodyLtr,
+		oldQ = dojo.isQuirks;
+
+	try{
+		dojo.doc = documentObject;
+		delete dojo._bodyLtr; // uncache
+		dojo.isQuirks = dojo.doc.compatMode == "BackCompat"; // no need to check for QuirksMode which was Opera 7 only
+
+		if(thisObject && typeof callback == "string"){
+			callback = thisObject[callback];
+		}
+
+		return callback.apply(thisObject, cbArguments || []);
+	}finally{
+		dojo.doc = oldDoc;
+		delete dojo._bodyLtr; // in case it was undefined originally, and set to true/false by the alternate document
+		if(oldLtr !== undefined){ dojo._bodyLtr = oldLtr; }
+		dojo.isQuirks = oldQ;
+	}
 };
-}
+	
diff --git a/dojo/_base/xhr.js b/dojo/_base/xhr.js
index 0c7084e..b797cf0 100644
--- a/dojo/_base/xhr.js
+++ b/dojo/_base/xhr.js
@@ -1,437 +1,938 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._base.xhr"]){
-dojo._hasResource["dojo._base.xhr"]=true;
 dojo.provide("dojo._base.xhr");
 dojo.require("dojo._base.Deferred");
 dojo.require("dojo._base.json");
 dojo.require("dojo._base.lang");
 dojo.require("dojo._base.query");
+
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 (function(){
-var _1=dojo,_2=_1.config;
-function _3(_4,_5,_6){
-if(_6===null){
-return;
-}
-var _7=_4[_5];
-if(typeof _7=="string"){
-_4[_5]=[_7,_6];
-}else{
-if(_1.isArray(_7)){
-_7.push(_6);
-}else{
-_4[_5]=_6;
-}
-}
-};
-dojo.fieldToObject=function(_8){
-var _9=null;
-var _a=_1.byId(_8);
-if(_a){
-var _b=_a.name;
-var _c=(_a.type||"").toLowerCase();
-if(_b&&_c&&!_a.disabled){
-if(_c=="radio"||_c=="checkbox"){
-if(_a.checked){
-_9=_a.value;
-}
-}else{
-if(_a.multiple){
-_9=[];
-_1.query("option",_a).forEach(function(_d){
-if(_d.selected){
-_9.push(_d.value);
-}
-});
-}else{
-_9=_a.value;
-}
-}
-}
-}
-return _9;
-};
-dojo.formToObject=function(_e){
-var _f={};
-var _10="file|submit|image|reset|button|";
-_1.forEach(dojo.byId(_e).elements,function(_11){
-var _12=_11.name;
-var _13=(_11.type||"").toLowerCase();
-if(_12&&_13&&_10.indexOf(_13)==-1&&!_11.disabled){
-_3(_f,_12,_1.fieldToObject(_11));
-if(_13=="image"){
-_f[_12+".x"]=_f[_12+".y"]=_f[_12].x=_f[_12].y=0;
-}
-}
-});
-return _f;
-};
-dojo.objectToQuery=function(map){
-var enc=encodeURIComponent;
-var _14=[];
-var _15={};
-for(var _16 in map){
-var _17=map[_16];
-if(_17!=_15[_16]){
-var _18=enc(_16)+"=";
-if(_1.isArray(_17)){
-for(var i=0;i<_17.length;i++){
-_14.push(_18+enc(_17[i]));
-}
-}else{
-_14.push(_18+enc(_17));
-}
-}
-}
-return _14.join("&");
-};
-dojo.formToQuery=function(_19){
-return _1.objectToQuery(_1.formToObject(_19));
-};
-dojo.formToJson=function(_1a,_1b){
-return _1.toJson(_1.formToObject(_1a),_1b);
-};
-dojo.queryToObject=function(str){
-var ret={};
-var qp=str.split("&");
-var dec=decodeURIComponent;
-_1.forEach(qp,function(_1c){
-if(_1c.length){
-var _1d=_1c.split("=");
-var _1e=dec(_1d.shift());
-var val=dec(_1d.join("="));
-if(typeof ret[_1e]=="string"){
-ret[_1e]=[ret[_1e]];
-}
-if(_1.isArray(ret[_1e])){
-ret[_1e].push(val);
-}else{
-ret[_1e]=val;
-}
-}
-});
-return ret;
-};
-dojo._blockAsync=false;
-var _1f=_1._contentHandlers=dojo.contentHandlers={text:function(xhr){
-return xhr.responseText;
-},json:function(xhr){
-return _1.fromJson(xhr.responseText||null);
-},"json-comment-filtered":function(xhr){
-if(!dojo.config.useCommentedJson){
-console.warn("Consider using the standard mimetype:application/json."+" json-commenting can introduce security issues. To"+" decrease the chances of hijacking, use the standard the 'json' handler and"+" prefix your json with: {}&&\n"+"Use djConfig.useCommentedJson=true to turn off this message.");
-}
-var _20=xhr.responseText;
-var _21=_20.indexOf("/*");
-var _22=_20.lastIndexOf("*/");
-if(_21==-1||_22==-1){
-throw new Error("JSON was not comment filtered");
-}
-return _1.fromJson(_20.substring(_21+2,_22));
-},javascript:function(xhr){
-return _1.eval(xhr.responseText);
-},xml:function(xhr){
-var _23=xhr.responseXML;
-if(_1.isIE&&(!_23||!_23.documentElement)){
-var ms=function(n){
-return "MSXML"+n+".DOMDocument";
-};
-var dp=["Microsoft.XMLDOM",ms(6),ms(4),ms(3),ms(2)];
-_1.some(dp,function(p){
-try{
-var dom=new ActiveXObject(p);
-dom.async=false;
-dom.loadXML(xhr.responseText);
-_23=dom;
-}
-catch(e){
-return false;
-}
-return true;
-});
-}
-return _23;
-},"json-comment-optional":function(xhr){
-if(xhr.responseText&&/^[^{\[]*\/\*/.test(xhr.responseText)){
-return _1f["json-comment-filtered"](xhr);
-}else{
-return _1f["json"](xhr);
-}
-}};
-dojo._ioSetArgs=function(_24,_25,_26,_27){
-var _28={args:_24,url:_24.url};
-var _29=null;
-if(_24.form){
-var _2a=_1.byId(_24.form);
-var _2b=_2a.getAttributeNode("action");
-_28.url=_28.url||(_2b?_2b.value:null);
-_29=_1.formToObject(_2a);
-}
-var _2c=[{}];
-if(_29){
-_2c.push(_29);
-}
-if(_24.content){
-_2c.push(_24.content);
-}
-if(_24.preventCache){
-_2c.push({"dojo.preventCache":new Date().valueOf()});
-}
-_28.query=_1.objectToQuery(_1.mixin.apply(null,_2c));
-_28.handleAs=_24.handleAs||"text";
-var d=new _1.Deferred(_25);
-d.addCallbacks(_26,function(_2d){
-return _27(_2d,d);
-});
-var ld=_24.load;
-if(ld&&_1.isFunction(ld)){
-d.addCallback(function(_2e){
-return ld.call(_24,_2e,_28);
-});
-}
-var err=_24.error;
-if(err&&_1.isFunction(err)){
-d.addErrback(function(_2f){
-return err.call(_24,_2f,_28);
-});
-}
-var _30=_24.handle;
-if(_30&&_1.isFunction(_30)){
-d.addBoth(function(_31){
-return _30.call(_24,_31,_28);
-});
-}
-if(_2.ioPublish&&_1.publish&&_28.args.ioPublish!==false){
-d.addCallbacks(function(res){
-_1.publish("/dojo/io/load",[d,res]);
-return res;
-},function(res){
-_1.publish("/dojo/io/error",[d,res]);
-return res;
-});
-d.addBoth(function(res){
-_1.publish("/dojo/io/done",[d,res]);
-return res;
-});
-}
-d.ioArgs=_28;
-return d;
-};
-var _32=function(dfd){
-dfd.canceled=true;
-var xhr=dfd.ioArgs.xhr;
-var _33=typeof xhr.abort;
-if(_33=="function"||_33=="object"||_33=="unknown"){
-xhr.abort();
-}
-var err=dfd.ioArgs.error;
-if(!err){
-err=new Error("xhr cancelled");
-err.dojoType="cancel";
-}
-return err;
-};
-var _34=function(dfd){
-var ret=_1f[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);
-return ret===undefined?null:ret;
-};
-var _35=function(_36,dfd){
-if(!dfd.ioArgs.args.failOk){
-console.error(_36);
-}
-return _36;
-};
-var _37=null;
-var _38=[];
-var _39=0;
-var _3a=function(dfd){
-if(_39<=0){
-_39=0;
-if(_2.ioPublish&&_1.publish&&(!dfd||dfd&&dfd.ioArgs.args.ioPublish!==false)){
-_1.publish("/dojo/io/stop");
-}
-}
-};
-var _3b=function(){
-var now=(new Date()).getTime();
-if(!_1._blockAsync){
-for(var i=0,tif;i<_38.length&&(tif=_38[i]);i++){
-var dfd=tif.dfd;
-var _3c=function(){
-if(!dfd||dfd.canceled||!tif.validCheck(dfd)){
-_38.splice(i--,1);
-_39-=1;
-}else{
-if(tif.ioCheck(dfd)){
-_38.splice(i--,1);
-tif.resHandle(dfd);
-_39-=1;
-}else{
-if(dfd.startTime){
-if(dfd.startTime+(dfd.ioArgs.args.timeout||0)<now){
-_38.splice(i--,1);
-var err=new Error("timeout exceeded");
-err.dojoType="timeout";
-dfd.errback(err);
-dfd.cancel();
-_39-=1;
-}
-}
-}
-}
-};
-if(dojo.config.debugAtAllCosts){
-_3c.call(this);
-}else{
-try{
-_3c.call(this);
-}
-catch(e){
-dfd.errback(e);
-}
-}
-}
-}
-_3a(dfd);
-if(!_38.length){
-clearInterval(_37);
-_37=null;
-return;
-}
-};
-dojo._ioCancelAll=function(){
-try{
-_1.forEach(_38,function(i){
-try{
-i.dfd.cancel();
-}
-catch(e){
-}
-});
-}
-catch(e){
-}
-};
-if(_1.isIE){
-_1.addOnWindowUnload(_1._ioCancelAll);
-}
-_1._ioNotifyStart=function(dfd){
-if(_2.ioPublish&&_1.publish&&dfd.ioArgs.args.ioPublish!==false){
-if(!_39){
-_1.publish("/dojo/io/start");
-}
-_39+=1;
-_1.publish("/dojo/io/send",[dfd]);
-}
-};
-_1._ioWatch=function(dfd,_3d,_3e,_3f){
-var _40=dfd.ioArgs.args;
-if(_40.timeout){
-dfd.startTime=(new Date()).getTime();
-}
-_38.push({dfd:dfd,validCheck:_3d,ioCheck:_3e,resHandle:_3f});
-if(!_37){
-_37=setInterval(_3b,50);
-}
-if(_40.sync){
-_3b();
-}
-};
-var _41="application/x-www-form-urlencoded";
-var _42=function(dfd){
-return dfd.ioArgs.xhr.readyState;
-};
-var _43=function(dfd){
-return 4==dfd.ioArgs.xhr.readyState;
-};
-var _44=function(dfd){
-var xhr=dfd.ioArgs.xhr;
-if(_1._isDocumentOk(xhr)){
-dfd.callback(dfd);
-}else{
-var err=new Error("Unable to load "+dfd.ioArgs.url+" status:"+xhr.status);
-err.status=xhr.status;
-err.responseText=xhr.responseText;
-dfd.errback(err);
-}
-};
-dojo._ioAddQueryToUrl=function(_45){
-if(_45.query.length){
-_45.url+=(_45.url.indexOf("?")==-1?"?":"&")+_45.query;
-_45.query=null;
-}
-};
-dojo.xhr=function(_46,_47,_48){
-var dfd=_1._ioSetArgs(_47,_32,_34,_35);
-var _49=dfd.ioArgs;
-var xhr=_49.xhr=_1._xhrObj(_49.args);
-if(!xhr){
-dfd.cancel();
-return dfd;
-}
-if("postData" in _47){
-_49.query=_47.postData;
-}else{
-if("putData" in _47){
-_49.query=_47.putData;
-}else{
-if("rawBody" in _47){
-_49.query=_47.rawBody;
-}else{
-if((arguments.length>2&&!_48)||"POST|PUT".indexOf(_46.toUpperCase())==-1){
-_1._ioAddQueryToUrl(_49);
-}
-}
-}
-}
-xhr.open(_46,_49.url,_47.sync!==true,_47.user||undefined,_47.password||undefined);
-if(_47.headers){
-for(var hdr in _47.headers){
-if(hdr.toLowerCase()==="content-type"&&!_47.contentType){
-_47.contentType=_47.headers[hdr];
-}else{
-if(_47.headers[hdr]){
-xhr.setRequestHeader(hdr,_47.headers[hdr]);
-}
-}
-}
-}
-xhr.setRequestHeader("Content-Type",_47.contentType||_41);
-if(!_47.headers||!("X-Requested-With" in _47.headers)){
-xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");
-}
-_1._ioNotifyStart(dfd);
-if(dojo.config.debugAtAllCosts){
-xhr.send(_49.query);
-}else{
-try{
-xhr.send(_49.query);
-}
-catch(e){
-_49.error=e;
-dfd.cancel();
-}
-}
-_1._ioWatch(dfd,_42,_43,_44);
-xhr=null;
-return dfd;
-};
-dojo.xhrGet=function(_4a){
-return _1.xhr("GET",_4a);
-};
-dojo.rawXhrPost=dojo.xhrPost=function(_4b){
-return _1.xhr("POST",_4b,true);
-};
-dojo.rawXhrPut=dojo.xhrPut=function(_4c){
-return _1.xhr("PUT",_4c,true);
-};
-dojo.xhrDelete=function(_4d){
-return _1.xhr("DELETE",_4d);
-};
+//>>excludeEnd("webkitMobile");
+	var _d = dojo, cfg = _d.config;
+
+	function setValue(/*Object*/obj, /*String*/name, /*String*/value){
+		//summary:
+		//		For the named property in object, set the value. If a value
+		//		already exists and it is a string, convert the value to be an
+		//		array of values.
+
+		//Skip it if there is no value
+		if(value === null){
+			return;
+		}
+
+		var val = obj[name];
+		if(typeof val == "string"){ // inline'd type check
+			obj[name] = [val, value];
+		}else if(_d.isArray(val)){
+			val.push(value);
+		}else{
+			obj[name] = value;
+		}
+	}
+	
+	dojo.fieldToObject = function(/*DOMNode||String*/ inputNode){
+		// summary:
+		//		Serialize a form field to a JavaScript object.
+		//
+		// description:
+		//		Returns the value encoded in a form field as
+		//		as a string or an array of strings. Disabled form elements
+		//		and unchecked radio and checkboxes are skipped.	Multi-select
+		//		elements are returned as an array of string values.
+		var ret = null;
+		var item = _d.byId(inputNode);
+		if(item){
+			var _in = item.name;
+			var type = (item.type||"").toLowerCase();
+			if(_in && type && !item.disabled){
+				if(type == "radio" || type == "checkbox"){
+					if(item.checked){ ret = item.value }
+				}else if(item.multiple){
+					ret = [];
+					_d.query("option", item).forEach(function(opt){
+						if(opt.selected){
+							ret.push(opt.value);
+						}
+					});
+				}else{
+					ret = item.value;
+				}
+			}
+		}
+		return ret; // Object
+	}
+
+	dojo.formToObject = function(/*DOMNode||String*/ formNode){
+		// summary:
+		//		Serialize a form node to a JavaScript object.
+		// description:
+		//		Returns the values encoded in an HTML form as
+		//		string properties in an object which it then returns. Disabled form
+		//		elements, buttons, and other non-value form elements are skipped.
+		//		Multi-select elements are returned as an array of string values.
+		//
+		// example:
+		//		This form:
+		//		|	<form id="test_form">
+		//		|		<input type="text" name="blah" value="blah">
+		//		|		<input type="text" name="no_value" value="blah" disabled>
+		//		|		<input type="button" name="no_value2" value="blah">
+		//		|		<select type="select" multiple name="multi" size="5">
+		//		|			<option value="blah">blah</option>
+		//		|			<option value="thud" selected>thud</option>
+		//		|			<option value="thonk" selected>thonk</option>
+		//		|		</select>
+		//		|	</form>
+		//
+		//		yields this object structure as the result of a call to
+		//		formToObject():
+		//
+		//		|	{ 
+		//		|		blah: "blah",
+		//		|		multi: [
+		//		|			"thud",
+		//		|			"thonk"
+		//		|		]
+		//		|	};
+
+		var ret = {};
+		var exclude = "file|submit|image|reset|button|";
+		_d.forEach(dojo.byId(formNode).elements, function(item){
+			var _in = item.name;
+			var type = (item.type||"").toLowerCase();
+			if(_in && type && exclude.indexOf(type) == -1 && !item.disabled){
+				setValue(ret, _in, _d.fieldToObject(item));
+				if(type == "image"){
+					ret[_in+".x"] = ret[_in+".y"] = ret[_in].x = ret[_in].y = 0;
+				}
+			}
+		});
+		return ret; // Object
+	}
+
+	dojo.objectToQuery = function(/*Object*/ map){
+		//	summary:
+		//		takes a name/value mapping object and returns a string representing
+		//		a URL-encoded version of that object.
+		//	example:
+		//		this object:
+		//
+		//		|	{ 
+		//		|		blah: "blah",
+		//		|		multi: [
+		//		|			"thud",
+		//		|			"thonk"
+		//		|		]
+		//		|	};
+		//
+		//	yields the following query string:
+		//	
+		//	|	"blah=blah&multi=thud&multi=thonk"
+
+		// FIXME: need to implement encodeAscii!!
+		var enc = encodeURIComponent;
+		var pairs = [];
+		var backstop = {};
+		for(var name in map){
+			var value = map[name];
+			if(value != backstop[name]){
+				var assign = enc(name) + "=";
+				if(_d.isArray(value)){
+					for(var i=0; i < value.length; i++){
+						pairs.push(assign + enc(value[i]));
+					}
+				}else{
+					pairs.push(assign + enc(value));
+				}
+			}
+		}
+		return pairs.join("&"); // String
+	}
+
+	dojo.formToQuery = function(/*DOMNode||String*/ formNode){
+		// summary:
+		//		Returns a URL-encoded string representing the form passed as either a
+		//		node or string ID identifying the form to serialize
+		return _d.objectToQuery(_d.formToObject(formNode)); // String
+	}
+
+	dojo.formToJson = function(/*DOMNode||String*/ formNode, /*Boolean?*/prettyPrint){
+		// summary:
+		//		Create a serialized JSON string from a form node or string
+		//		ID identifying the form to serialize
+		return _d.toJson(_d.formToObject(formNode), prettyPrint); // String
+	}
+
+	dojo.queryToObject = function(/*String*/ str){
+		// summary:
+		//		Create an object representing a de-serialized query section of a
+		//		URL. Query keys with multiple values are returned in an array.
+		//
+		// example:
+		//		This string:
+		//
+		//	|		"foo=bar&foo=baz&thinger=%20spaces%20=blah&zonk=blarg&"
+		//		
+		//		results in this object structure:
+		//
+		//	|		{
+		//	|			foo: [ "bar", "baz" ],
+		//	|			thinger: " spaces =blah",
+		//	|			zonk: "blarg"
+		//	|		}
+		//	
+		//		Note that spaces and other urlencoded entities are correctly
+		//		handled.
+
+		// FIXME: should we grab the URL string if we're not passed one?
+		var ret = {};
+		var qp = str.split("&");
+		var dec = decodeURIComponent;
+		_d.forEach(qp, function(item){
+			if(item.length){
+				var parts = item.split("=");
+				var name = dec(parts.shift());
+				var val = dec(parts.join("="));
+				if(typeof ret[name] == "string"){ // inline'd type check
+					ret[name] = [ret[name]];
+				}
+
+				if(_d.isArray(ret[name])){
+					ret[name].push(val);
+				}else{
+					ret[name] = val;
+				}
+			}
+		});
+		return ret; // Object
+	}
+
+	// need to block async callbacks from snatching this thread as the result
+	// of an async callback might call another sync XHR, this hangs khtml forever
+	// must checked by watchInFlight()
+
+	dojo._blockAsync = false;
+
+	// MOW: remove dojo._contentHandlers alias in 2.0
+	var handlers = _d._contentHandlers = dojo.contentHandlers = {
+		// summary: 
+		//		A map of availble XHR transport handle types. Name matches the
+		//		`handleAs` attribute passed to XHR calls.
+		//
+		// description:
+		//		A map of availble XHR transport handle types. Name matches the
+		//		`handleAs` attribute passed to XHR calls. Each contentHandler is
+		//		called, passing the xhr object for manipulation. The return value
+		//		from the contentHandler will be passed to the `load` or `handle` 
+		//		functions defined in the original xhr call. 
+		//		
+		// example:
+		//		Creating a custom content-handler:
+		//	|	dojo.contentHandlers.makeCaps = function(xhr){
+		//	|		return xhr.responseText.toUpperCase();
+		//	|	}
+		//	|	// and later:
+		//	|	dojo.xhrGet({ 
+		//	|		url:"foo.txt",
+		//	|		handleAs:"makeCaps",
+		//	|		load: function(data){ /* data is a toUpper version of foo.txt */ }
+		//	|	});
+
+		text: function(xhr){ 
+			// summary: A contentHandler which simply returns the plaintext response data
+			return xhr.responseText; 
+		},
+		json: function(xhr){
+			// summary: A contentHandler which returns a JavaScript object created from the response data
+			return _d.fromJson(xhr.responseText || null);
+		},
+		"json-comment-filtered": function(xhr){ 
+			// summary: A contentHandler which expects comment-filtered JSON. 
+			// description: 
+			//		A contentHandler which expects comment-filtered JSON. 
+			//		the json-comment-filtered option was implemented to prevent
+			//		"JavaScript Hijacking", but it is less secure than standard JSON. Use
+			//		standard JSON instead. JSON prefixing can be used to subvert hijacking.
+			//		
+			//		Will throw a notice suggesting to use application/json mimetype, as
+			//		json-commenting can introduce security issues. To decrease the chances of hijacking,
+			//		use the standard `json` contentHandler, and prefix your "JSON" with: {}&& 
+			//		
+			//		use djConfig.useCommentedJson = true to turn off the notice
+			if(!dojo.config.useCommentedJson){
+				console.warn("Consider using the standard mimetype:application/json."
+					+ " json-commenting can introduce security issues. To"
+					+ " decrease the chances of hijacking, use the standard the 'json' handler and"
+					+ " prefix your json with: {}&&\n"
+					+ "Use djConfig.useCommentedJson=true to turn off this message.");
+			}
+
+			var value = xhr.responseText;
+			var cStartIdx = value.indexOf("\/*");
+			var cEndIdx = value.lastIndexOf("*\/");
+			if(cStartIdx == -1 || cEndIdx == -1){
+				throw new Error("JSON was not comment filtered");
+			}
+			return _d.fromJson(value.substring(cStartIdx+2, cEndIdx));
+		},
+		javascript: function(xhr){ 
+			// summary: A contentHandler which evaluates the response data, expecting it to be valid JavaScript
+
+			// FIXME: try Moz and IE specific eval variants?
+			return _d.eval(xhr.responseText);
+		},
+		xml: function(xhr){
+			// summary: A contentHandler returning an XML Document parsed from the response data
+			var result = xhr.responseXML;
+			//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+			if(_d.isIE && (!result || !result.documentElement)){
+				//WARNING: this branch used by the xml handling in dojo.io.iframe,
+				//so be sure to test dojo.io.iframe if making changes below.
+				var ms = function(n){ return "MSXML" + n + ".DOMDocument"; }
+				var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)];
+				_d.some(dp, function(p){
+					try{
+						var dom = new ActiveXObject(p);
+						dom.async = false;
+						dom.loadXML(xhr.responseText);
+						result = dom;
+					}catch(e){ return false; }
+					return true;
+				});
+			}
+			//>>excludeEnd("webkitMobile");
+			return result; // DOMDocument
+		},
+		"json-comment-optional": function(xhr){
+			// summary: A contentHandler which checks the presence of comment-filtered JSON and 
+			//		alternates between the `json` and `json-comment-filtered` contentHandlers.
+			if(xhr.responseText && /^[^{\[]*\/\*/.test(xhr.responseText)){
+				return handlers["json-comment-filtered"](xhr);
+			}else{
+				return handlers["json"](xhr);
+			}
+		}
+	};
+
+	/*=====
+	dojo.__IoArgs = function(){
+		//	url: String
+		//		URL to server endpoint.
+		//	content: Object?
+		//		Contains properties with string values. These
+		//		properties will be serialized as name1=value2 and
+		//		passed in the request.
+		//	timeout: Integer?
+		//		Milliseconds to wait for the response. If this time
+		//		passes, the then error callbacks are called.
+		//	form: DOMNode?
+		//		DOM node for a form. Used to extract the form values
+		//		and send to the server.
+		//	preventCache: Boolean?
+		//		Default is false. If true, then a
+		//		"dojo.preventCache" parameter is sent in the request
+		//		with a value that changes with each request
+		//		(timestamp). Useful only with GET-type requests.
+		//	handleAs: String?
+		//		Acceptable values depend on the type of IO
+		//		transport (see specific IO calls for more information).
+		// 	rawBody: String?
+		// 		Sets the raw body for an HTTP request. If this is used, then the content
+		// 		property is ignored. This is mostly useful for HTTP methods that have
+		// 		a body to their requests, like PUT or POST. This property can be used instead
+		// 		of postData and putData for dojo.rawXhrPost and dojo.rawXhrPut respectively.
+		//	ioPublish: Boolean?
+		//		Set this explicitly to false to prevent publishing of topics related to
+		// 		IO operations. Otherwise, if djConfig.ioPublish is set to true, topics
+		// 		will be published via dojo.publish for different phases of an IO operation.
+		// 		See dojo.__IoPublish for a list of topics that are published.
+		//	load: Function?
+		//		This function will be
+		//		called on a successful HTTP response code.
+		//	error: Function?
+		//		This function will
+		//		be called when the request fails due to a network or server error, the url
+		//		is invalid, etc. It will also be called if the load or handle callback throws an
+		//		exception, unless djConfig.debugAtAllCosts is true.  This allows deployed applications
+		//		to continue to run even when a logic error happens in the callback, while making
+		//		it easier to troubleshoot while in debug mode.
+		//	handle: Function?
+		//		This function will
+		//		be called at the end of every request, whether or not an error occurs.
+		this.url = url;
+		this.content = content;
+		this.timeout = timeout;
+		this.form = form;
+		this.preventCache = preventCache;
+		this.handleAs = handleAs;
+		this.ioPublish = ioPublish;
+		this.load = function(response, ioArgs){
+			// ioArgs: dojo.__IoCallbackArgs
+			//		Provides additional information about the request.
+			// response: Object
+			//		The response in the format as defined with handleAs.
+		}
+		this.error = function(response, ioArgs){
+			// ioArgs: dojo.__IoCallbackArgs
+			//		Provides additional information about the request.
+			// response: Object
+			//		The response in the format as defined with handleAs.
+		}
+		this.handle = function(loadOrError, response, ioArgs){
+			// loadOrError: String
+			//		Provides a string that tells you whether this function
+			//		was called because of success (load) or failure (error).
+			// response: Object
+			//		The response in the format as defined with handleAs.
+			// ioArgs: dojo.__IoCallbackArgs
+			//		Provides additional information about the request.
+		}
+	}
+	=====*/
+
+	/*=====
+	dojo.__IoCallbackArgs = function(args, xhr, url, query, handleAs, id, canDelete, json){
+		//	args: Object
+		//		the original object argument to the IO call.
+		//	xhr: XMLHttpRequest
+		//		For XMLHttpRequest calls only, the
+		//		XMLHttpRequest object that was used for the
+		//		request.
+		//	url: String
+		//		The final URL used for the call. Many times it
+		//		will be different than the original args.url
+		//		value.
+		//	query: String
+		//		For non-GET requests, the
+		//		name1=value1&name2=value2 parameters sent up in
+		//		the request.
+		//	handleAs: String
+		//		The final indicator on how the response will be
+		//		handled.
+		//	id: String
+		//		For dojo.io.script calls only, the internal
+		//		script ID used for the request.
+		//	canDelete: Boolean
+		//		For dojo.io.script calls only, indicates
+		//		whether the script tag that represents the
+		//		request can be deleted after callbacks have
+		//		been called. Used internally to know when
+		//		cleanup can happen on JSONP-type requests.
+		//	json: Object
+		//		For dojo.io.script calls only: holds the JSON
+		//		response for JSONP-type requests. Used
+		//		internally to hold on to the JSON responses.
+		//		You should not need to access it directly --
+		//		the same object should be passed to the success
+		//		callbacks directly.
+		this.args = args;
+		this.xhr = xhr;
+		this.url = url;
+		this.query = query;
+		this.handleAs = handleAs;
+		this.id = id;
+		this.canDelete = canDelete;
+		this.json = json;
+	}
+	=====*/
+
+
+	/*=====
+	dojo.__IoPublish = function(){
+		// 	summary:
+		// 		This is a list of IO topics that can be published
+		// 		if djConfig.ioPublish is set to true. IO topics can be
+		// 		published for any Input/Output, network operation. So,
+		// 		dojo.xhr, dojo.io.script and dojo.io.iframe can all
+		// 		trigger these topics to be published.
+		//	start: String
+		//		"/dojo/io/start" is sent when there are no outstanding IO
+		// 		requests, and a new IO request is started. No arguments
+		// 		are passed with this topic.
+		//	send: String
+		//		"/dojo/io/send" is sent whenever a new IO request is started.
+		// 		It passes the dojo.Deferred for the request with the topic.
+		//	load: String
+		//		"/dojo/io/load" is sent whenever an IO request has loaded
+		// 		successfully. It passes the response and the dojo.Deferred
+		// 		for the request with the topic.
+		//	error: String
+		//		"/dojo/io/error" is sent whenever an IO request has errored.
+		// 		It passes the error and the dojo.Deferred
+		// 		for the request with the topic.
+		//	done: String
+		//		"/dojo/io/done" is sent whenever an IO request has completed,
+		// 		either by loading or by erroring. It passes the error and
+		// 		the dojo.Deferred for the request with the topic.
+		//	stop: String
+		//		"/dojo/io/stop" is sent when all outstanding IO requests have
+		// 		finished. No arguments are passed with this topic.
+		this.start = "/dojo/io/start";
+		this.send = "/dojo/io/send";
+		this.load = "/dojo/io/load";
+		this.error = "/dojo/io/error";
+		this.done = "/dojo/io/done";
+		this.stop = "/dojo/io/stop";
+	}
+	=====*/
+
+
+	dojo._ioSetArgs = function(/*dojo.__IoArgs*/args,
+			/*Function*/canceller,
+			/*Function*/okHandler,
+			/*Function*/errHandler){
+		//	summary: 
+		//		sets up the Deferred and ioArgs property on the Deferred so it
+		//		can be used in an io call.
+		//	args:
+		//		The args object passed into the public io call. Recognized properties on
+		//		the args object are:
+		//	canceller:
+		//		The canceller function used for the Deferred object. The function
+		//		will receive one argument, the Deferred object that is related to the
+		//		canceller.
+		//	okHandler:
+		//		The first OK callback to be registered with Deferred. It has the opportunity
+		//		to transform the OK response. It will receive one argument -- the Deferred
+		//		object returned from this function.
+		//	errHandler:
+		//		The first error callback to be registered with Deferred. It has the opportunity
+		//		to do cleanup on an error. It will receive two arguments: error (the 
+		//		Error object) and dfd, the Deferred object returned from this function.
+
+		var ioArgs = {args: args, url: args.url};
+
+		//Get values from form if requestd.
+		var formObject = null;
+		if(args.form){ 
+			var form = _d.byId(args.form);
+			//IE requires going through getAttributeNode instead of just getAttribute in some form cases, 
+			//so use it for all.  See #2844
+			var actnNode = form.getAttributeNode("action");
+			ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null); 
+			formObject = _d.formToObject(form);
+		}
+
+		// set up the query params
+		var miArgs = [{}];
+	
+		if(formObject){
+			// potentially over-ride url-provided params w/ form values
+			miArgs.push(formObject);
+		}
+		if(args.content){
+			// stuff in content over-rides what's set by form
+			miArgs.push(args.content);
+		}
+		if(args.preventCache){
+			miArgs.push({"dojo.preventCache": new Date().valueOf()});
+		}
+		ioArgs.query = _d.objectToQuery(_d.mixin.apply(null, miArgs));
+	
+		// .. and the real work of getting the deferred in order, etc.
+		ioArgs.handleAs = args.handleAs || "text";
+		var d = new _d.Deferred(canceller);
+		d.addCallbacks(okHandler, function(error){
+			return errHandler(error, d);
+		});
+
+		//Support specifying load, error and handle callback functions from the args.
+		//For those callbacks, the "this" object will be the args object.
+		//The callbacks will get the deferred result value as the
+		//first argument and the ioArgs object as the second argument.
+		var ld = args.load;
+		if(ld && _d.isFunction(ld)){
+			d.addCallback(function(value){
+				return ld.call(args, value, ioArgs);
+			});
+		}
+		var err = args.error;
+		if(err && _d.isFunction(err)){
+			d.addErrback(function(value){
+				return err.call(args, value, ioArgs);
+			});
+		}
+		var handle = args.handle;
+		if(handle && _d.isFunction(handle)){
+			d.addBoth(function(value){
+				return handle.call(args, value, ioArgs);
+			});
+		}
+
+		//Plug in topic publishing, if dojo.publish is loaded.
+		if(cfg.ioPublish && _d.publish && ioArgs.args.ioPublish !== false){
+			d.addCallbacks(
+				function(res){
+					_d.publish("/dojo/io/load", [d, res]);
+					return res;
+				},
+				function(res){
+					_d.publish("/dojo/io/error", [d, res]);
+					return res;
+				}
+			);
+			d.addBoth(function(res){
+				_d.publish("/dojo/io/done", [d, res]);
+				return res;
+			});
+		}
+
+		d.ioArgs = ioArgs;
+	
+		// FIXME: need to wire up the xhr object's abort method to something
+		// analagous in the Deferred
+		return d;
+	}
+
+	var _deferredCancel = function(/*Deferred*/dfd){
+		// summary: canceller function for dojo._ioSetArgs call.
+		
+		dfd.canceled = true;
+		var xhr = dfd.ioArgs.xhr;
+		var _at = typeof xhr.abort;
+		if(_at == "function" || _at == "object" || _at == "unknown"){
+			xhr.abort();
+		}
+		var err = dfd.ioArgs.error;
+		if(!err){
+			err = new Error("xhr cancelled");
+			err.dojoType="cancel";
+		}
+		return err;
+	}
+	var _deferredOk = function(/*Deferred*/dfd){
+		// summary: okHandler function for dojo._ioSetArgs call.
+
+		var ret = handlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);
+		return ret === undefined ? null : ret;
+	}
+	var _deferError = function(/*Error*/error, /*Deferred*/dfd){
+		// summary: errHandler function for dojo._ioSetArgs call.
+
+		if(!dfd.ioArgs.args.failOk){
+			console.error(error);
+		}
+		return error;
+	}
+
+	// avoid setting a timer per request. It degrades performance on IE
+	// something fierece if we don't use unified loops.
+	var _inFlightIntvl = null;
+	var _inFlight = [];
+	
+	
+	//Use a separate count for knowing if we are starting/stopping io calls.
+	//Cannot use _inFlight.length since it can change at a different time than
+	//when we want to do this kind of test. We only want to decrement the count
+	//after a callback/errback has finished, since the callback/errback should be
+	//considered as part of finishing a request.
+	var _pubCount = 0;
+	var _checkPubCount = function(dfd){
+		if(_pubCount <= 0){
+			_pubCount = 0;
+			if(cfg.ioPublish && _d.publish && (!dfd || dfd && dfd.ioArgs.args.ioPublish !== false)){
+				_d.publish("/dojo/io/stop");
+			}
+		}
+	};
+
+	var _watchInFlight = function(){
+		//summary: 
+		//		internal method that checks each inflight XMLHttpRequest to see
+		//		if it has completed or if the timeout situation applies.
+		
+		var now = (new Date()).getTime();
+		// make sure sync calls stay thread safe, if this callback is called
+		// during a sync call and this results in another sync call before the
+		// first sync call ends the browser hangs
+		if(!_d._blockAsync){
+			// we need manual loop because we often modify _inFlight (and therefore 'i') while iterating
+			// note: the second clause is an assigment on purpose, lint may complain
+			for(var i = 0, tif; i < _inFlight.length && (tif = _inFlight[i]); i++){
+				var dfd = tif.dfd;
+				var func = function(){
+					if(!dfd || dfd.canceled || !tif.validCheck(dfd)){
+						_inFlight.splice(i--, 1); 
+						_pubCount -= 1;
+					}else if(tif.ioCheck(dfd)){
+						_inFlight.splice(i--, 1);
+						tif.resHandle(dfd);
+						_pubCount -= 1;
+					}else if(dfd.startTime){
+						//did we timeout?
+						if(dfd.startTime + (dfd.ioArgs.args.timeout || 0) < now){
+							_inFlight.splice(i--, 1);
+							var err = new Error("timeout exceeded");
+							err.dojoType = "timeout";
+							dfd.errback(err);
+							//Cancel the request so the io module can do appropriate cleanup.
+							dfd.cancel();
+							_pubCount -= 1;
+						}
+					}
+				};
+				if(dojo.config.debugAtAllCosts){
+					func.call(this);
+				}else{
+					try{
+						func.call(this);
+					}catch(e){
+						dfd.errback(e);
+					}
+				}
+			}
+		}
+
+		_checkPubCount(dfd);
+
+		if(!_inFlight.length){
+			clearInterval(_inFlightIntvl);
+			_inFlightIntvl = null;
+			return;
+		}
+	}
+
+	dojo._ioCancelAll = function(){
+		//summary: Cancels all pending IO requests, regardless of IO type
+		//(xhr, script, iframe).
+		try{
+			_d.forEach(_inFlight, function(i){
+				try{
+					i.dfd.cancel();
+				}catch(e){/*squelch*/}
+			});
+		}catch(e){/*squelch*/}
+	}
+
+	//Automatically call cancel all io calls on unload
+	//in IE for trac issue #2357.
+	//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+	if(_d.isIE){
+		_d.addOnWindowUnload(_d._ioCancelAll);
+	}
+	//>>excludeEnd("webkitMobile");
+
+	_d._ioNotifyStart = function(/*Deferred*/dfd){
+		// summary:
+		// 		If dojo.publish is available, publish topics
+		// 		about the start of a request queue and/or the
+		// 		the beginning of request.
+		// description:
+		// 		Used by IO transports. An IO transport should
+		// 		call this method before making the network connection.
+		if(cfg.ioPublish && _d.publish && dfd.ioArgs.args.ioPublish !== false){
+			if(!_pubCount){
+				_d.publish("/dojo/io/start");
+			}
+			_pubCount += 1;
+			_d.publish("/dojo/io/send", [dfd]);
+		}
+	}
+
+	_d._ioWatch = function(dfd, validCheck, ioCheck, resHandle){
+		// summary: 
+		//		Watches the io request represented by dfd to see if it completes.
+		// dfd: Deferred
+		//		The Deferred object to watch.
+		// validCheck: Function
+		//		Function used to check if the IO request is still valid. Gets the dfd
+		//		object as its only argument.
+		// ioCheck: Function
+		//		Function used to check if basic IO call worked. Gets the dfd
+		//		object as its only argument.
+		// resHandle: Function
+		//		Function used to process response. Gets the dfd
+		//		object as its only argument.
+		var args = dfd.ioArgs.args;
+		if(args.timeout){
+			dfd.startTime = (new Date()).getTime();
+		}
+		
+		_inFlight.push({dfd: dfd, validCheck: validCheck, ioCheck: ioCheck, resHandle: resHandle});
+		if(!_inFlightIntvl){
+			_inFlightIntvl = setInterval(_watchInFlight, 50);
+		}
+		// handle sync requests
+		//A weakness: async calls in flight
+		//could have their handlers called as part of the
+		//_watchInFlight call, before the sync's callbacks
+		// are called.
+		if(args.sync){
+			_watchInFlight();
+		}
+	}
+
+	var _defaultContentType = "application/x-www-form-urlencoded";
+
+	var _validCheck = function(/*Deferred*/dfd){
+		return dfd.ioArgs.xhr.readyState; //boolean
+	}
+	var _ioCheck = function(/*Deferred*/dfd){
+		return 4 == dfd.ioArgs.xhr.readyState; //boolean
+	}
+	var _resHandle = function(/*Deferred*/dfd){
+		var xhr = dfd.ioArgs.xhr;
+		if(_d._isDocumentOk(xhr)){
+			dfd.callback(dfd);
+		}else{
+			var err = new Error("Unable to load " + dfd.ioArgs.url + " status:" + xhr.status);
+			err.status = xhr.status;
+			err.responseText = xhr.responseText;
+			dfd.errback(err);
+		}
+	}
+
+	dojo._ioAddQueryToUrl = function(/*dojo.__IoCallbackArgs*/ioArgs){
+		//summary: Adds query params discovered by the io deferred construction to the URL.
+		//Only use this for operations which are fundamentally GET-type operations.
+		if(ioArgs.query.length){
+			ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query;
+			ioArgs.query = null;
+		}		
+	}
+
+	/*=====
+	dojo.declare("dojo.__XhrArgs", dojo.__IoArgs, {
+		constructor: function(){
+			//	summary:
+			//		In addition to the properties listed for the dojo._IoArgs type,
+			//		the following properties are allowed for dojo.xhr* methods.
+			//	handleAs: String?
+			//		Acceptable values are: text (default), json, json-comment-optional,
+			//		json-comment-filtered, javascript, xml. See `dojo.contentHandlers`
+			//	sync: Boolean?
+			//		false is default. Indicates whether the request should
+			//		be a synchronous (blocking) request.
+			//	headers: Object?
+			//		Additional HTTP headers to send in the request.
+			//	failOk: Boolean?
+			//		false is default. Indicates whether a request should be
+			//		allowed to fail (and therefore no console error message in
+			//		the event of a failure)
+			this.handleAs = handleAs;
+			this.sync = sync;
+			this.headers = headers;
+			this.failOk = failOk;
+		}
+	});
+	=====*/
+
+	dojo.xhr = function(/*String*/ method, /*dojo.__XhrArgs*/ args, /*Boolean?*/ hasBody){
+		//	summary:
+		//		Sends an HTTP request with the given method.
+		//	description:
+		//		Sends an HTTP request with the given method.
+		//		See also dojo.xhrGet(), xhrPost(), xhrPut() and dojo.xhrDelete() for shortcuts
+		//		for those HTTP methods. There are also methods for "raw" PUT and POST methods
+		//		via dojo.rawXhrPut() and dojo.rawXhrPost() respectively.
+		//	method:
+		//		HTTP method to be used, such as GET, POST, PUT, DELETE.  Should be uppercase.
+		//	hasBody:
+		//		If the request has an HTTP body, then pass true for hasBody.
+
+		//Make the Deferred object for this xhr request.
+		var dfd = _d._ioSetArgs(args, _deferredCancel, _deferredOk, _deferError);
+		var ioArgs = dfd.ioArgs;
+
+		//Pass the args to _xhrObj, to allow alternate XHR calls based specific calls, like
+		//the one used for iframe proxies.
+		var xhr = ioArgs.xhr = _d._xhrObj(ioArgs.args);
+		//If XHR factory fails, cancel the deferred.
+		if(!xhr){
+			dfd.cancel();
+			return dfd;
+		}
+
+		//Allow for specifying the HTTP body completely.
+		if("postData" in args){
+			ioArgs.query = args.postData;
+		}else if("putData" in args){
+			ioArgs.query = args.putData;
+		}else if("rawBody" in args){
+			ioArgs.query = args.rawBody;
+		}else if((arguments.length > 2 && !hasBody) || "POST|PUT".indexOf(method.toUpperCase()) == -1){
+			//Check for hasBody being passed. If no hasBody,
+			//then only append query string if not a POST or PUT request.
+			_d._ioAddQueryToUrl(ioArgs);
+		}
+
+		// IE 6 is a steaming pile. It won't let you call apply() on the native function (xhr.open).
+		// workaround for IE6's apply() "issues"
+		xhr.open(method, ioArgs.url, args.sync !== true, args.user || undefined, args.password || undefined);
+		if(args.headers){
+			for(var hdr in args.headers){
+				if(hdr.toLowerCase() === "content-type" && !args.contentType){
+					args.contentType = args.headers[hdr];
+				}else if(args.headers[hdr]){
+					//Only add header if it has a value. This allows for instnace, skipping
+					//insertion of X-Requested-With by specifying empty value.
+					xhr.setRequestHeader(hdr, args.headers[hdr]);
+				}
+			}
+		}
+		// FIXME: is this appropriate for all content types?
+		xhr.setRequestHeader("Content-Type", args.contentType || _defaultContentType);
+		if(!args.headers || !("X-Requested-With" in args.headers)){
+			xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+		}
+		// FIXME: set other headers here!
+		_d._ioNotifyStart(dfd);
+		if(dojo.config.debugAtAllCosts){
+			xhr.send(ioArgs.query);
+		}else{
+			try{
+				xhr.send(ioArgs.query);
+			}catch(e){
+				ioArgs.error = e;
+				dfd.cancel();
+			}
+		}
+		_d._ioWatch(dfd, _validCheck, _ioCheck, _resHandle);
+		xhr = null;
+		return dfd; // dojo.Deferred
+	}
+
+	dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){
+		//	summary: 
+		//		Sends an HTTP GET request to the server.
+		return _d.xhr("GET", args); // dojo.Deferred
+	}
+
+	dojo.rawXhrPost = dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){
+		//	summary:
+		//		Sends an HTTP POST request to the server. In addtion to the properties
+		//		listed for the dojo.__XhrArgs type, the following property is allowed:
+		//	postData:
+		//		String. Send raw data in the body of the POST request.
+		return _d.xhr("POST", args, true); // dojo.Deferred
+	}
+
+	dojo.rawXhrPut = dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){
+		//	summary:
+		//		Sends an HTTP PUT request to the server. In addtion to the properties
+		//		listed for the dojo.__XhrArgs type, the following property is allowed:
+		//	putData:
+		//		String. Send raw data in the body of the PUT request.
+		return _d.xhr("PUT", args, true); // dojo.Deferred
+	}
+
+	dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){
+		//	summary:
+		//		Sends an HTTP DELETE request to the server.
+		return _d.xhr("DELETE", args); //dojo.Deferred
+	}
+
+	/*
+	dojo.wrapForm = function(formNode){
+		//summary:
+		//		A replacement for FormBind, but not implemented yet.
+
+		// FIXME: need to think harder about what extensions to this we might
+		// want. What should we allow folks to do w/ this? What events to
+		// set/send?
+		throw new Error("dojo.wrapForm not yet implemented");
+	}
+	*/
+//>>excludeStart("webkitMobile", kwArgs.webkitMobile);
 })();
-}
+//>>excludeEnd("webkitMobile");
diff --git a/dojo/_firebug/firebug.css b/dojo/_firebug/firebug.css
index 3b6f4f9..27657ef 100644
--- a/dojo/_firebug/firebug.css
+++ b/dojo/_firebug/firebug.css
@@ -25,6 +25,7 @@
 	
 	background:#f0f0f0;
 }
+
 .firebug #firebugLog, .firebug #objectLog {
 	overflow: auto;
 	position: absolute;
@@ -171,6 +172,8 @@
 .firebug .propertyName {
 	font-weight: bold;
 }
+
+/*   tabs   */
 #firebugToolbar ul.tabs{
 	margin:0 !important;
 	padding:0;
@@ -205,4 +208,4 @@
 	text-decoration:none;
 	background:transparent url(tab_rgt_over.png) no-repeat right;
 	color:#FFFFFF;
-}
+}
\ No newline at end of file
diff --git a/dojo/_firebug/firebug.js b/dojo/_firebug/firebug.js
index 1f83c31..77efaf4 100644
--- a/dojo/_firebug/firebug.js
+++ b/dojo/_firebug/firebug.js
@@ -1,914 +1,1215 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo._firebug.firebug"]){
-dojo._hasResource["dojo._firebug.firebug"]=true;
 dojo.provide("dojo._firebug.firebug");
-dojo.deprecated=function(_1,_2,_3){
-var _4="DEPRECATED: "+_1;
-if(_2){
-_4+=" "+_2;
-}
-if(_3){
-_4+=" -- will be removed in version: "+_3;
-}
-console.warn(_4);
+	
+dojo.deprecated = function(/*String*/ behaviour, /*String?*/ extra, /*String?*/ removal){
+	// summary: 
+	//		Log a debug message to indicate that a behavior has been
+	//		deprecated.
+	// extra: Text to append to the message.
+	// removal: 
+	//		Text to indicate when in the future the behavior will be removed.
+	var message = "DEPRECATED: " + behaviour;
+	if(extra){ message += " " + extra; }
+	if(removal){ message += " -- will be removed in version: " + removal; }
+	console.warn(message);
 };
-dojo.experimental=function(_5,_6){
-var _7="EXPERIMENTAL: "+_5+" -- APIs subject to change without notice.";
-if(_6){
-_7+=" "+_6;
-}
-console.warn(_7);
+
+dojo.experimental = function(/* String */ moduleName, /* String? */ extra){
+	// summary: Marks code as experimental.
+	// description: 
+	//		This can be used to mark a function, file, or module as
+	//		experimental.  Experimental code is not ready to be used, and the
+	//		APIs are subject to change without notice.  Experimental code may be
+	//		completed deleted without going through the normal deprecation
+	//		process.
+	// moduleName: 
+	//		The name of a module, or the name of a module file or a specific
+	//		function
+	// extra: 
+	//		some additional message for the user
+	// example:
+	//	|	dojo.experimental("dojo.data.Result");
+	// example:
+	//	|	dojo.experimental("dojo.weather.toKelvin()", "PENDING approval from NOAA");
+	var message = "EXPERIMENTAL: " + moduleName + " -- APIs subject to change without notice.";
+	if(extra){ message += " " + extra; }
+	console.warn(message);
 };
+
+// FIREBUG LITE
+	// summary: Firebug Lite, the baby brother to Joe Hewitt's Firebug for Mozilla Firefox
+	// description:
+	//		Opens a console for logging, debugging, and error messages.
+	//		Contains partial functionality to Firebug. See function list below.
+	//	NOTE: 
+	//			Firebug is a Firefox extension created by Joe Hewitt (see license). You do not need Dojo to run Firebug.
+	//			Firebug Lite is included in Dojo by permission from Joe Hewitt
+	//			If you are new to Firebug, or used to the Dojo 0.4 dojo.debug, you can learn Firebug 
+	//				functionality by reading the function comments below or visiting http://www.getfirebug.com/docs.html
+	//	NOTE:
+	//		To test Firebug Lite in Firefox:
+	//			FF2: set "console = null" before loading dojo and set djConfig.isDebug=true
+	//			FF3: disable Firebug and set djConfig.isDebug=true
+	//
+	// example:
+	//		Supports inline objects in object inspector window (only simple trace of dom nodes, however)
+	//		|	console.log("my object", {foo:"bar"})
+	// example:
+	//		Option for console to open in popup window
+	//		|	var djConfig = {isDebug: true, popup:true };
+	// example:
+	//		Option for console height (ignored for popup)
+	//		|	var djConfig = {isDebug: true, debugHeight:100 }
+
+
+
 (function(){
-var _8=(/Trident/.test(window.navigator.userAgent));
-if(_8){
-var _9=["log","info","debug","warn","error"];
-for(var i=0;i<_9.length;i++){
-var m=_9[i];
-var n="_"+_9[i];
-console[n]=console[m];
-console[m]=(function(){
-var _a=n;
-return function(){
-console[_a](Array.prototype.slice.call(arguments).join(" "));
-};
-})();
-}
-try{
-console.clear();
-}
-catch(e){
-}
-}
-if(!dojo.isFF&&(!dojo.isChrome||dojo.isChrome<3)&&(!dojo.isSafari||dojo.isSafari<4)&&!_8&&!window.firebug&&(typeof console!="undefined"&&!console.firebug)&&!dojo.config.useCustomLogger&&!dojo.isAIR){
-try{
-if(window!=window.parent){
-if(window.parent["console"]){
-window.console=window.parent.console;
-}
-return;
-}
-}
-catch(e){
-}
-var _b=document;
-var _c=window;
-var _d=0;
-var _e=null;
-var _f=null;
-var _10=null;
-var _11=null;
-var _12=null;
-var _13=null;
-var _14=false;
-var _15=[];
-var _16=[];
-var _17={};
-var _18={};
-var _19=null;
-var _1a;
-var _1b;
-var _1c=false;
-var _1d=null;
-var _1e=document.createElement("div");
-var _1f;
-var _20;
-window.console={_connects:[],log:function(){
-_21(arguments,"");
-},debug:function(){
-_21(arguments,"debug");
-},info:function(){
-_21(arguments,"info");
-},warn:function(){
-_21(arguments,"warning");
-},error:function(){
-_21(arguments,"error");
-},assert:function(_22,_23){
-if(!_22){
-var _24=[];
-for(var i=1;i<arguments.length;++i){
-_24.push(arguments[i]);
-}
-_21(_24.length?_24:["Assertion Failure"],"error");
-throw _23?_23:"Assertion Failure";
-}
-},dir:function(obj){
-var str=_25(obj);
-str=str.replace(/\n/g,"<br />");
-str=str.replace(/\t/g,"    ");
-_26([str],"dir");
-},dirxml:function(_27){
-var _28=[];
-_29(_27,_28);
-_26(_28,"dirxml");
-},group:function(){
-_26(arguments,"group",_2a);
-},groupEnd:function(){
-_26(arguments,"",_2b);
-},time:function(_2c){
-_17[_2c]=new Date().getTime();
-},timeEnd:function(_2d){
-if(_2d in _17){
-var _2e=(new Date()).getTime()-_17[_2d];
-_21([_2d+":",_2e+"ms"]);
-delete _17[_2d];
-}
-},count:function(_2f){
-if(!_18[_2f]){
-_18[_2f]=0;
-}
-_18[_2f]++;
-_21([_2f+": "+_18[_2f]]);
-},trace:function(_30){
-var _31=_30||3;
-var f=console.trace.caller;
-for(var i=0;i<_31;i++){
-var _32=f.toString();
-var _33=[];
-for(var a=0;a<f.arguments.length;a++){
-_33.push(f.arguments[a]);
-}
-if(f.arguments.length){
-}else{
-}
-f=f.caller;
-}
-},profile:function(){
-this.warn(["profile() not supported."]);
-},profileEnd:function(){
-},clear:function(){
-if(_f){
-while(_f.childNodes.length){
-dojo.destroy(_f.firstChild);
-}
-}
-dojo.forEach(this._connects,dojo.disconnect);
-},open:function(){
-_34(true);
-},close:function(){
-if(_14){
-_34();
-}
-},_restoreBorder:function(){
-if(_1f){
-_1f.style.border=_20;
-}
-},openDomInspector:function(){
-_1c=true;
-_f.style.display="none";
-_19.style.display="block";
-_10.style.display="none";
-document.body.style.cursor="pointer";
-_1a=dojo.connect(document,"mousemove",function(evt){
-if(!_1c){
-return;
-}
-if(!_1d){
-_1d=setTimeout(function(){
-_1d=null;
-},50);
-}else{
-return;
-}
-var _35=evt.target;
-if(_35&&(_1f!==_35)){
-var _36=true;
-console._restoreBorder();
-var _37=[];
-_29(_35,_37);
-_19.innerHTML=_37.join("");
-_1f=_35;
-_20=_1f.style.border;
-_1f.style.border="#0000FF 1px solid";
-}
-});
-setTimeout(function(){
-_1b=dojo.connect(document,"click",function(evt){
-document.body.style.cursor="";
-_1c=!_1c;
-dojo.disconnect(_1b);
-});
-},30);
-},_closeDomInspector:function(){
-document.body.style.cursor="";
-dojo.disconnect(_1a);
-dojo.disconnect(_1b);
-_1c=false;
-console._restoreBorder();
-},openConsole:function(){
-_f.style.display="block";
-_19.style.display="none";
-_10.style.display="none";
-console._closeDomInspector();
-},openObjectInspector:function(){
-_f.style.display="none";
-_19.style.display="none";
-_10.style.display="block";
-console._closeDomInspector();
-},recss:function(){
-var i,a,s;
-a=document.getElementsByTagName("link");
-for(i=0;i<a.length;i++){
-s=a[i];
-if(s.rel.toLowerCase().indexOf("stylesheet")>=0&&s.href){
-var h=s.href.replace(/(&|%5C?)forceReload=\d+/,"");
-s.href=h+(h.indexOf("?")>=0?"&":"?")+"forceReload="+new Date().valueOf();
-}
-}
-}};
-function _34(_38){
-_14=_38||!_14;
-if(_e){
-_e.style.display=_14?"block":"none";
-}
-};
-function _39(){
-_34(true);
-if(_12){
-_12.focus();
-}
-};
-function _3a(x,y,w,h){
-var win=window.open("","_firebug","status=0,menubar=0,resizable=1,top="+y+",left="+x+",width="+w+",height="+h+",scrollbars=1,addressbar=0");
-if(!win){
-var msg="Firebug Lite could not open a pop-up window, most likely because of a blocker.\n"+"Either enable pop-ups for this domain, or change the djConfig to popup=false.";
-alert(msg);
-}
-_3b(win);
-var _3c=win.document;
-var _3d="<html style=\"height:100%;\"><head><title>Firebug Lite</title></head>\n"+"<body bgColor=\"#ccc\" style=\"height:97%;\" onresize=\"opener.onFirebugResize()\">\n"+"<div id=\"fb\"></div>"+"</body></html>";
-_3c.write(_3d);
-_3c.close();
-return win;
-};
-function _3b(wn){
-var d=new Date();
-d.setTime(d.getTime()+(60*24*60*60*1000));
-d=d.toUTCString();
-var dc=wn.document,_3e;
-if(wn.innerWidth){
-_3e=function(){
-return {w:wn.innerWidth,h:wn.innerHeight};
-};
-}else{
-if(dc.documentElement&&dc.documentElement.clientWidth){
-_3e=function(){
-return {w:dc.documentElement.clientWidth,h:dc.documentElement.clientHeight};
-};
-}else{
-if(dc.body){
-_3e=function(){
-return {w:dc.body.clientWidth,h:dc.body.clientHeight};
-};
-}
-}
-}
-window.onFirebugResize=function(){
-_4c(_3e().h);
-clearInterval(wn._firebugWin_resize);
-wn._firebugWin_resize=setTimeout(function(){
-var x=wn.screenLeft,y=wn.screenTop,w=wn.outerWidth||wn.document.body.offsetWidth,h=wn.outerHeight||wn.document.body.offsetHeight;
-document.cookie="_firebugPosition="+[x,y,w,h].join(",")+"; expires="+d+"; path=/";
-},5000);
-};
-};
-function _3f(){
-if(_e){
-return;
-}
-if(dojo.config.popup){
-var _40="100%";
-var _41=document.cookie.match(/(?:^|; )_firebugPosition=([^;]*)/);
-var p=_41?_41[1].split(","):[2,2,320,480];
-_c=_3a(p[0],p[1],p[2],p[3]);
-_b=_c.document;
-dojo.config.debugContainerId="fb";
-_c.console=window.console;
-_c.dojo=window.dojo;
-}else{
-_b=document;
-_40=(dojo.config.debugHeight||300)+"px";
-}
-var _42=_b.createElement("link");
-_42.href=dojo.moduleUrl("dojo._firebug","firebug.css");
-_42.rel="stylesheet";
-_42.type="text/css";
-var _43=_b.getElementsByTagName("head");
-if(_43){
-_43=_43[0];
-}
-if(!_43){
-_43=_b.getElementsByTagName("html")[0];
-}
-if(dojo.isIE){
-window.setTimeout(function(){
-_43.appendChild(_42);
-},0);
-}else{
-_43.appendChild(_42);
-}
-if(dojo.config.debugContainerId){
-_e=_b.getElementById(dojo.config.debugContainerId);
-}
-if(!_e){
-_e=_b.createElement("div");
-_b.body.appendChild(_e);
-}
-_e.className+=" firebug";
-_e.style.height=_40;
-_e.style.display=(_14?"block":"none");
-var _44=function(_45,_46,_47,_48){
-return "<li class=\""+_48+"\"><a href=\"javascript:void(0);\" onclick=\"console."+_47+"(); return false;\" title=\""+_46+"\">"+_45+"</a></li>";
-};
-_e.innerHTML="<div id=\"firebugToolbar\">"+"  <ul id=\"fireBugTabs\" class=\"tabs\">"+_44("Clear","Remove All Console Logs","clear","")+_44("ReCSS","Refresh CSS without reloading page","recss","")+_44("Console","Show Console Logs","openConsole","gap")+_44("DOM","Show DOM Inspector","openDomInspector","")+_44("Object","Show Object Inspector","openObjectInspector","")+((dojo.config.popup)?"":_44("Close","Close the console","close","gap"))+"\t</ul>"+"</div>"+"<input type=\"text\" id=\"fireb [...]
-_13=_b.getElementById("firebugToolbar");
-_12=_b.getElementById("firebugCommandLine");
-_49(_12,"keydown",_4a);
-_49(_b,dojo.isIE||dojo.isSafari?"keydown":"keypress",_4b);
-_f=_b.getElementById("firebugLog");
-_10=_b.getElementById("objectLog");
-_19=_b.getElementById("domInspect");
-_11=_b.getElementById("fireBugTabs");
-_4c();
-_4d();
-};
-dojo.addOnLoad(_3f);
-function _4e(){
-_b=null;
-if(_c.console){
-_c.console.clear();
-}
-_c=null;
-_e=null;
-_f=null;
-_10=null;
-_19=null;
-_12=null;
-_15=[];
-_16=[];
-_17={};
-};
-function _4f(){
-var _50=_12.value;
-_12.value="";
-_26([">  ",_50],"command");
-var _51;
-try{
-_51=eval(_50);
-}
-catch(e){
-}
-};
-function _4c(h){
-var _52=25;
-var _53=h?h-(_52+_12.offsetHeight+25+(h*0.01))+"px":(_e.offsetHeight-_52-_12.offsetHeight)+"px";
-_f.style.top=_52+"px";
-_f.style.height=_53;
-_10.style.height=_53;
-_10.style.top=_52+"px";
-_19.style.height=_53;
-_19.style.top=_52+"px";
-_12.style.bottom=0;
-dojo.addOnWindowUnload(_4e);
-};
-function _26(_54,_55,_56){
-if(_f){
-_57(_54,_55,_56);
-}else{
-_15.push([_54,_55,_56]);
-}
-};
-function _4d(){
-var _58=_15;
-_15=[];
-for(var i=0;i<_58.length;++i){
-_57(_58[i][0],_58[i][1],_58[i][2]);
-}
-};
-function _57(_59,_5a,_5b){
-var _5c=_f.scrollTop+_f.offsetHeight>=_f.scrollHeight;
-_5b=_5b||_5d;
-_5b(_59,_5a);
-if(_5c){
-_f.scrollTop=_f.scrollHeight-_f.offsetHeight;
-}
-};
-function _5e(row){
-var _5f=_16.length?_16[_16.length-1]:_f;
-_5f.appendChild(row);
-};
-function _5d(_60,_61){
-var row=_f.ownerDocument.createElement("div");
-row.className="logRow"+(_61?" logRow-"+_61:"");
-row.innerHTML=_60.join("");
-_5e(row);
-};
-function _2a(_62,_63){
-_21(_62,_63);
-var _64=_f.ownerDocument.createElement("div");
-_64.className="logGroupBox";
-_5e(_64);
-_16.push(_64);
-};
-function _2b(){
-_16.pop();
-};
-function _21(_65,_66){
-var _67=[];
-var _68=_65[0];
-var _69=0;
-if(typeof (_68)!="string"){
-_68="";
-_69=-1;
-}
-var _6a=_6b(_68);
-for(var i=0;i<_6a.length;++i){
-var _6c=_6a[i];
-if(_6c&&typeof _6c=="object"){
-_6c.appender(_65[++_69],_67);
-}else{
-_6d(_6c,_67);
-}
-}
-var ids=[];
-var obs=[];
-for(i=_69+1;i<_65.length;++i){
-_6d(" ",_67);
-var _6e=_65[i];
-if(_6e===undefined||_6e===null){
-_6f(_6e,_67);
-}else{
-if(typeof (_6e)=="string"){
-_6d(_6e,_67);
-}else{
-if(_6e instanceof Date){
-_6d(_6e.toString(),_67);
-}else{
-if(_6e.nodeType==9){
-_6d("[ XmlDoc ]",_67);
-}else{
-var id="_a"+_d++;
-ids.push(id);
-obs.push(_6e);
-var str="<a id=\""+id+"\" href=\"javascript:void(0);\">"+_70(_6e)+"</a>";
-_71(str,_67);
-}
-}
-}
-}
-}
-_26(_67,_66);
-for(i=0;i<ids.length;i++){
-var btn=_b.getElementById(ids[i]);
-if(!btn){
-continue;
-}
-btn.obj=obs[i];
-_c.console._connects.push(dojo.connect(btn,"onclick",function(){
-console.openObjectInspector();
-try{
-_25(this.obj);
-}
-catch(e){
-this.obj=e;
-}
-_10.innerHTML="<pre>"+_25(this.obj)+"</pre>";
-}));
-}
-};
-function _6b(_72){
-var _73=[];
-var reg=/((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;
-var _74={s:_6d,d:_75,i:_75,f:_76};
-for(var m=reg.exec(_72);m;m=reg.exec(_72)){
-var _77=m[8]?m[8]:m[5];
-var _78=_77 in _74?_74[_77]:_79;
-var _7a=m[3]?parseInt(m[3]):(m[4]=="."?-1:0);
-_73.push(_72.substr(0,m[0][0]=="%"?m.index:m.index+1));
-_73.push({appender:_78,precision:_7a});
-_72=_72.substr(m.index+m[0].length);
-}
-_73.push(_72);
-return _73;
-};
-function _7b(_7c){
-function _7d(ch){
-switch(ch){
-case "<":
-return "<";
-case ">":
-return ">";
-case "&":
-return "&";
-case "'":
-return "'";
-case "\"":
-return """;
-}
-return "?";
-};
-return String(_7c).replace(/[<>&"']/g,_7d);
-};
-function _7e(_7f){
-try{
-return _7f+"";
-}
-catch(e){
-return null;
-}
-};
-function _71(_80,_81){
-_81.push(_7e(_80));
-};
-function _6d(_82,_83){
-_83.push(_7b(_7e(_82)));
-};
-function _6f(_84,_85){
-_85.push("<span class=\"objectBox-null\">",_7b(_7e(_84)),"</span>");
-};
-function _86(_87,_88){
-_88.push("<span class=\"objectBox-string\">"",_7b(_7e(_87)),""</span>");
-};
-function _75(_89,_8a){
-_8a.push("<span class=\"objectBox-number\">",_7b(_7e(_89)),"</span>");
-};
-function _76(_8b,_8c){
-_8c.push("<span class=\"objectBox-number\">",_7b(_7e(_8b)),"</span>");
-};
-function _8d(_8e,_8f){
-_8f.push("<span class=\"objectBox-function\">",_70(_8e),"</span>");
-};
-function _79(_90,_91){
-try{
-if(_90===undefined){
-_6f("undefined",_91);
-}else{
-if(_90===null){
-_6f("null",_91);
-}else{
-if(typeof _90=="string"){
-_86(_90,_91);
-}else{
-if(typeof _90=="number"){
-_75(_90,_91);
-}else{
-if(typeof _90=="function"){
-_8d(_90,_91);
-}else{
-if(_90.nodeType==1){
-_92(_90,_91);
-}else{
-if(typeof _90=="object"){
-_93(_90,_91);
-}else{
-_6d(_90,_91);
-}
-}
-}
-}
-}
-}
-}
-}
-catch(e){
-}
-};
-function _93(_94,_95){
-var _96=_7e(_94);
-var _97=/\[object (.*?)\]/;
-var m=_97.exec(_96);
-_95.push("<span class=\"objectBox-object\">",m?m[1]:_96,"</span>");
-};
-function _92(_98,_99){
-_99.push("<span class=\"objectBox-selector\">");
-_99.push("<span class=\"selectorTag\">",_7b(_98.nodeName.toLowerCase()),"</span>");
-if(_98.id){
-_99.push("<span class=\"selectorId\">#",_7b(_98.id),"</span>");
-}
-if(_98.className){
-_99.push("<span class=\"selectorClass\">.",_7b(_98.className),"</span>");
-}
-_99.push("</span>");
-};
-function _29(_9a,_9b){
-if(_9a.nodeType==1){
-_9b.push("<div class=\"objectBox-element\">","<<span class=\"nodeTag\">",_9a.nodeName.toLowerCase(),"</span>");
-for(var i=0;i<_9a.attributes.length;++i){
-var _9c=_9a.attributes[i];
-if(!_9c.specified){
-continue;
-}
-_9b.push(" <span class=\"nodeName\">",_9c.nodeName.toLowerCase(),"</span>="<span class=\"nodeValue\">",_7b(_9c.nodeValue),"</span>"");
-}
-if(_9a.firstChild){
-_9b.push("></div><div class=\"nodeChildren\">");
-for(var _9d=_9a.firstChild;_9d;_9d=_9d.nextSibling){
-_29(_9d,_9b);
-}
-_9b.push("</div><div class=\"objectBox-element\"></<span class=\"nodeTag\">",_9a.nodeName.toLowerCase(),"></span></div>");
-}else{
-_9b.push("/></div>");
-}
-}else{
-if(_9a.nodeType==3){
-_9b.push("<div class=\"nodeText\">",_7b(_9a.nodeValue),"</div>");
-}
-}
-};
-function _49(_9e,_9f,_a0){
-if(document.all){
-_9e.attachEvent("on"+_9f,_a0);
-}else{
-_9e.addEventListener(_9f,_a0,false);
-}
-};
-function _a1(_a2,_a3,_a4){
-if(document.all){
-_a2.detachEvent("on"+_a3,_a4);
-}else{
-_a2.removeEventListener(_a3,_a4,false);
-}
-};
-function _a5(_a6){
-if(document.all){
-_a6.cancelBubble=true;
-}else{
-_a6.stopPropagation();
-}
-};
-function _a7(msg,_a8,_a9){
-var _aa=_a8.lastIndexOf("/");
-var _ab=_aa==-1?_a8:_a8.substr(_aa+1);
-var _ac=["<span class=\"errorMessage\">",msg,"</span>","<div class=\"objectBox-sourceLink\">",_ab," (line ",_a9,")</div>"];
-_26(_ac,"error");
-};
-var _ad=new Date().getTime();
-function _4b(_ae){
-var _af=(new Date()).getTime();
-if(_af>_ad+200){
-_ae=dojo.fixEvent(_ae);
-var _b0=dojo.keys;
-var ekc=_ae.keyCode;
-_ad=_af;
-if(ekc==_b0.F12){
-_34();
-}else{
-if((ekc==_b0.NUMPAD_ENTER||ekc==76)&&_ae.shiftKey&&(_ae.metaKey||_ae.ctrlKey)){
-_39();
-}else{
-return;
-}
-}
-_a5(_ae);
-}
-};
-function _4a(e){
-var dk=dojo.keys;
-if(e.keyCode==13&&_12.value){
-_b1(_12.value);
-_4f();
-}else{
-if(e.keyCode==27){
-_12.value="";
-}else{
-if(e.keyCode==dk.UP_ARROW||e.charCode==dk.UP_ARROW){
-_b2("older");
-}else{
-if(e.keyCode==dk.DOWN_ARROW||e.charCode==dk.DOWN_ARROW){
-_b2("newer");
-}else{
-if(e.keyCode==dk.HOME||e.charCode==dk.HOME){
-_b3=1;
-_b2("older");
-}else{
-if(e.keyCode==dk.END||e.charCode==dk.END){
-_b3=999999;
-_b2("newer");
-}
-}
-}
-}
-}
-}
-};
-var _b3=-1;
-var _b4=null;
-function _b1(_b5){
-var _b6=_b7("firebug_history");
-_b6=(_b6)?dojo.fromJson(_b6):[];
-var pos=dojo.indexOf(_b6,_b5);
-if(pos!=-1){
-_b6.splice(pos,1);
-}
-_b6.push(_b5);
-_b7("firebug_history",dojo.toJson(_b6),30);
-while(_b6.length&&!_b7("firebug_history")){
-_b6.shift();
-_b7("firebug_history",dojo.toJson(_b6),30);
-}
-_b4=null;
-_b3=-1;
-};
-function _b2(_b8){
-var _b9=_b7("firebug_history");
-_b9=(_b9)?dojo.fromJson(_b9):[];
-if(!_b9.length){
-return;
-}
-if(_b4===null){
-_b4=_12.value;
-}
-if(_b3==-1){
-_b3=_b9.length;
-}
-if(_b8=="older"){
---_b3;
-if(_b3<0){
-_b3=0;
-}
-}else{
-if(_b8=="newer"){
-++_b3;
-if(_b3>_b9.length){
-_b3=_b9.length;
-}
-}
-}
-if(_b3==_b9.length){
-_12.value=_b4;
-_b4=null;
-}else{
-_12.value=_b9[_b3];
-}
-};
-function _b7(_ba,_bb){
-var c=document.cookie;
-if(arguments.length==1){
-var _bc=c.match(new RegExp("(?:^|; )"+_ba+"=([^;]*)"));
-return _bc?decodeURIComponent(_bc[1]):undefined;
-}else{
-var d=new Date();
-d.setMonth(d.getMonth()+1);
-document.cookie=_ba+"="+encodeURIComponent(_bb)+((d.toUtcString)?"; expires="+d.toUTCString():"");
-}
-};
-function _bd(it){
-return it&&it instanceof Array||typeof it=="array";
-};
-function _be(o){
-var cnt=0;
-for(var nm in o){
-cnt++;
-}
-return cnt;
-};
-function _25(o,i,txt,_bf){
-var ind=" \t";
-txt=txt||"";
-i=i||ind;
-_bf=_bf||[];
-var _c0;
-if(o&&o.nodeType==1){
-var _c1=[];
-_29(o,_c1);
-return _c1.join("");
-}
-var br=",\n",cnt=0,_c2=_be(o);
-if(o instanceof Date){
-return i+o.toString()+br;
-}
-looking:
-for(var nm in o){
-cnt++;
-if(cnt==_c2){
-br="\n";
-}
-if(o[nm]===window||o[nm]===document){
-continue;
-}else{
-if(o[nm]===null){
-txt+=i+nm+" : NULL"+br;
-}else{
-if(o[nm]&&o[nm].nodeType){
-if(o[nm].nodeType==1){
-}else{
-if(o[nm].nodeType==3){
-txt+=i+nm+" : [ TextNode "+o[nm].data+" ]"+br;
-}
-}
-}else{
-if(typeof o[nm]=="object"&&(o[nm] instanceof String||o[nm] instanceof Number||o[nm] instanceof Boolean)){
-txt+=i+nm+" : "+o[nm]+","+br;
-}else{
-if(o[nm] instanceof Date){
-txt+=i+nm+" : "+o[nm].toString()+br;
-}else{
-if(typeof (o[nm])=="object"&&o[nm]){
-for(var j=0,_c3;_c3=_bf[j];j++){
-if(o[nm]===_c3){
-txt+=i+nm+" : RECURSION"+br;
-continue looking;
-}
-}
-_bf.push(o[nm]);
-_c0=(_bd(o[nm]))?["[","]"]:["{","}"];
-txt+=i+nm+" : "+_c0[0]+"\n";
-txt+=_25(o[nm],i+ind,"",_bf);
-txt+=i+_c0[1]+br;
-}else{
-if(typeof o[nm]=="undefined"){
-txt+=i+nm+" : undefined"+br;
-}else{
-if(nm=="toString"&&typeof o[nm]=="function"){
-var _c4=o[nm]();
-if(typeof _c4=="string"&&_c4.match(/function ?(.*?)\(/)){
-_c4=_7b(_70(o[nm]));
-}
-txt+=i+nm+" : "+_c4+br;
-}else{
-txt+=i+nm+" : "+_7b(_70(o[nm]))+br;
-}
-}
-}
-}
-}
-}
-}
-}
-}
-return txt;
-};
-function _70(obj){
-var _c5=(obj instanceof Error);
-if(obj.nodeType==1){
-return _7b("< "+obj.tagName.toLowerCase()+" id=\""+obj.id+"\" />");
-}
-if(obj.nodeType==3){
-return _7b("[TextNode: \""+obj.nodeValue+"\"]");
-}
-var nm=(obj&&(obj.id||obj.name||obj.ObjectID||obj.widgetId));
-if(!_c5&&nm){
-return "{"+nm+"}";
-}
-var _c6=2;
-var _c7=4;
-var cnt=0;
-if(_c5){
-nm="[ Error: "+(obj.message||obj.description||obj)+" ]";
-}else{
-if(_bd(obj)){
-nm="["+obj.slice(0,_c7).join(",");
-if(obj.length>_c7){
-nm+=" ... ("+obj.length+" items)";
-}
-nm+="]";
-}else{
-if(typeof obj=="function"){
-nm=obj+"";
-var reg=/function\s*([^\(]*)(\([^\)]*\))[^\{]*\{/;
-var m=reg.exec(nm);
-if(m){
-if(!m[1]){
-m[1]="function";
-}
-nm=m[1]+m[2];
-}else{
-nm="function()";
-}
-}else{
-if(typeof obj!="object"||typeof obj=="string"){
-nm=obj+"";
-}else{
-nm="{";
-for(var i in obj){
-cnt++;
-if(cnt>_c6){
-break;
-}
-nm+=i+":"+_7b(obj[i])+"  ";
-}
-nm+="}";
-}
-}
-}
-}
-return nm;
-};
-_49(document,dojo.isIE||dojo.isSafari?"keydown":"keypress",_4b);
-if((document.documentElement.getAttribute("debug")=="true")||(dojo.config.isDebug)){
-_34(true);
-}
-dojo.addOnWindowUnload(function(){
-_a1(document,dojo.isIE||dojo.isSafari?"keydown":"keypress",_4b);
-window.onFirebugResize=null;
-window.console=null;
-});
+
+	var isNewIE = (/Trident/.test(window.navigator.userAgent));
+	if(isNewIE){
+		// Fixing IE's console
+		// IE doesn't insert space between arguments. How annoying.
+		var calls = ["log", "info", "debug", "warn", "error"];
+		for(var i=0;i<calls.length;i++){
+			var m = calls[i];
+			var n = "_"+calls[i]
+			console[n] = console[m];
+			console[m] = (function(){
+				var type = n;
+				return function(){
+					console[type](Array.prototype.slice.call(arguments).join(" "));
+				}
+			})();
+		}
+		// clear the console on load. This is more than a convenience - too many logs crashes it.
+		// If closed it throws an error
+		try{ console.clear(); }catch(e){}
+	}
+	
+	if(
+		!dojo.isFF &&								// Firefox has Firebug
+		(!dojo.isChrome || dojo.isChrome < 3) &&
+		(!dojo.isSafari || dojo.isSafari < 4) &&	// Safari 4 has a console
+		!isNewIE &&									// Has the new IE console
+		!window.firebug &&							// Testing for mozilla firebug lite
+		(typeof console != "undefined" && !console.firebug) && //A console that is not firebug's
+		!dojo.config.useCustomLogger &&				// Allow custom loggers
+		!dojo.isAIR									// isDebug triggers AIRInsector, not Firebug
+	){
+	
+	
+	// don't build firebug in iframes
+	try{
+		if(window != window.parent){ 
+			// but if we've got a parent logger, connect to it
+			if(window.parent["console"]){
+				window.console = window.parent.console;
+			}
+			return; 
+		}
+	}catch(e){/*squelch*/}
+
+	// ***************************************************************************
+	// Placing these variables before the functions that use them to avoid a 
+	// shrinksafe bug where variable renaming does not happen correctly otherwise.
+	
+	// most of the objects in this script are run anonomously
+	var _firebugDoc = document;
+	var _firebugWin = window;
+	var __consoleAnchorId__ = 0;
+	
+	var consoleFrame = null;
+	var consoleBody = null;
+	var consoleObjectInspector = null;
+	var fireBugTabs = null;
+	var commandLine = null;
+	var consoleToolbar = null;
+	
+	var frameVisible = false;
+	var messageQueue = [];
+	var groupStack = [];
+	var timeMap = {};
+	var countMap = {};
+	
+	var consoleDomInspector = null;
+	var _inspectionMoveConnection;
+	var _inspectionClickConnection;
+	var _inspectionEnabled = false;
+	var _inspectionTimer = null;
+	var _inspectTempNode = document.createElement("div");
+			
+			
+	var _inspectCurrentNode;
+	var _restoreBorderStyle;
+
+	// ***************************************************************************
+
+	window.console = {
+		_connects: [],
+		log: function(){
+			// summary: 
+			//		Sends arguments to console.
+			logFormatted(arguments, "");
+		},
+		
+		debug: function(){
+			// summary: 
+			//		Sends arguments to console. Missing finctionality to show script line of trace.
+			logFormatted(arguments, "debug");
+		},
+		
+		info: function(){
+			// summary: 
+			//		Sends arguments to console, highlighted with (I) icon.
+			logFormatted(arguments, "info");
+		},
+		
+		warn: function(){
+			// summary: 
+			//		Sends warning arguments to console, highlighted with (!) icon and blue style.
+			logFormatted(arguments, "warning");
+		},
+		
+		error: function(){
+			// summary: 
+			//		Sends error arguments (object) to console, highlighted with (X) icon and yellow style
+			//			NEW: error object now displays in object inspector
+			logFormatted(arguments, "error");
+		},
+		
+		assert: function(truth, message){
+			// summary: 
+			//		Tests for true. Throws exception if false.
+			if(!truth){
+				var args = [];
+				for(var i = 1; i < arguments.length; ++i){
+					args.push(arguments[i]);
+				}
+				
+				logFormatted(args.length ? args : ["Assertion Failure"], "error");
+				throw message ? message : "Assertion Failure";
+			}
+		},
+		
+		dir: function(obj){
+			var str = printObject( obj );
+			str = str.replace(/\n/g, "<br />");
+			str = str.replace(/\t/g, "    ");
+			logRow([str], "dir");
+		},
+		
+		dirxml: function(node){
+			// summary: 
+			//
+			var html = [];
+			appendNode(node, html);
+			logRow(html, "dirxml");
+		},
+		
+		group: function(){
+			// summary: 
+			//		collects log messages into a group, starting with this call and ending with 
+			//			groupEnd(). Missing collapse functionality
+			logRow(arguments, "group", pushGroup);
+		},
+		
+		groupEnd: function(){
+			// summary: 
+			//		Closes group. See above
+			logRow(arguments, "", popGroup);
+		},
+		
+		time: function(name){
+			// summary: 
+			//		Starts timers assigned to name given in argument. Timer stops and displays on timeEnd(title);
+			//	example:
+			//	|	console.time("load");
+			//	|	console.time("myFunction");
+			//	|	console.timeEnd("load");
+			//	|	console.timeEnd("myFunction");
+			timeMap[name] = new Date().getTime();
+		},
+		
+		timeEnd: function(name){
+			// summary: 
+			//		See above.
+			if(name in timeMap){
+				var delta = (new Date()).getTime() - timeMap[name];
+				logFormatted([name+ ":", delta+"ms"]);
+				delete timeMap[name];
+			}
+		},
+		
+		count: function(name){
+			// summary: 
+			//		Not supported
+			if(!countMap[name]) countMap[name] = 0;
+			countMap[name]++;
+			logFormatted([name+": "+countMap[name]]);
+		},
+		
+		trace: function(_value){
+			var stackAmt = _value || 3;
+			var f = console.trace.caller; //function that called trace
+			console.log(">>> console.trace(stack)");
+			for(var i=0;i<stackAmt;i++){
+				var func = f.toString();
+				var args=[];
+				for (var a = 0; a < f.arguments.length; a++) {
+					args.push(f.arguments[a])
+				}
+				if(f.arguments.length){
+					console.dir({"function":func, "arguments":args});	
+				}else{
+					console.dir({"function":func});
+				}
+				
+				f = f.caller;
+			}	
+		},
+		
+		profile: function(){
+			// summary: 
+			//		Not supported
+			this.warn(["profile() not supported."]);
+		},
+		
+		profileEnd: function(){ },
+
+		clear: function(){
+			// summary: 
+			//		Clears message console. Do not call this directly
+			if(consoleBody){
+				while(consoleBody.childNodes.length){
+					dojo.destroy(consoleBody.firstChild);	
+				}
+			}
+			dojo.forEach(this._connects,dojo.disconnect);
+		},
+
+		open: function(){ 
+			// summary: 
+			//		Opens message console. Do not call this directly
+			toggleConsole(true); 
+		},
+		
+		close: function(){
+			// summary: 
+			//		Closes message console. Do not call this directly
+			if(frameVisible){
+				toggleConsole();
+			}
+		},
+		_restoreBorder: function(){
+			if(_inspectCurrentNode){
+				_inspectCurrentNode.style.border = _restoreBorderStyle;
+			}
+		},
+		openDomInspector: function(){
+			_inspectionEnabled = true;
+			consoleBody.style.display = "none";
+			consoleDomInspector.style.display = "block";
+			consoleObjectInspector.style.display = "none";
+			document.body.style.cursor = "pointer";
+			_inspectionMoveConnection = dojo.connect(document, "mousemove", function(evt){
+				if(!_inspectionEnabled){ return; }
+				if(!_inspectionTimer){
+					_inspectionTimer = setTimeout(function(){ _inspectionTimer = null; }, 50);
+				}else{
+					return;
+				}
+				var node = evt.target;
+				if(node && (_inspectCurrentNode !== node)){
+					var parent = true;
+					
+					console._restoreBorder();
+					var html = [];
+					appendNode(node, html);
+					consoleDomInspector.innerHTML = html.join("");
+						
+					_inspectCurrentNode = node;
+					_restoreBorderStyle = _inspectCurrentNode.style.border;
+					_inspectCurrentNode.style.border = "#0000FF 1px solid";
+				}
+			});
+			setTimeout(function(){
+				_inspectionClickConnection = dojo.connect(document, "click", function(evt){
+					document.body.style.cursor = "";
+					_inspectionEnabled = !_inspectionEnabled;																  
+					dojo.disconnect(_inspectionClickConnection);
+					// console._restoreBorder();
+				});
+			}, 30);
+		},
+		_closeDomInspector: function(){
+			document.body.style.cursor = "";
+			dojo.disconnect(_inspectionMoveConnection);
+			dojo.disconnect(_inspectionClickConnection);
+			_inspectionEnabled = false;
+			console._restoreBorder();
+		},
+		openConsole:function(){
+			// summary: 
+			//		Closes object inspector and opens message console. Do not call this directly
+			consoleBody.style.display = "block";
+			consoleDomInspector.style.display = "none";
+			consoleObjectInspector.style.display = "none";
+			console._closeDomInspector();
+		},
+		openObjectInspector:function(){
+			consoleBody.style.display = "none";
+			consoleDomInspector.style.display = "none";
+			consoleObjectInspector.style.display = "block";
+			console._closeDomInspector();
+		},
+		recss: function(){
+			// http://turtle.dojotoolkit.org/~david/recss.html
+			// this is placed in dojo since the console is most likely
+			// in another window and dojo is easilly accessible
+			var i,a,s;a=document.getElementsByTagName('link');
+			for(i=0;i<a.length;i++){
+				s=a[i];
+				if(s.rel.toLowerCase().indexOf('stylesheet')>=0&&s.href) {
+					var h=s.href.replace(/(&|%5C?)forceReload=\d+/,'');
+					s.href=h+(h.indexOf('?')>=0?'&':'?')+'forceReload='+new Date().valueOf();
+				}
+			}
+		}
+	}
+
+	// ***************************************************************************
+
+	function toggleConsole(forceOpen){
+		frameVisible = forceOpen || !frameVisible;
+		if(consoleFrame){
+			consoleFrame.style.display = frameVisible ? "block" : "none";
+		}
+	}
+
+	function focusCommandLine(){
+		toggleConsole(true);
+		if(commandLine){
+			commandLine.focus();
+		}
+	}
+	
+	function openWin(x,y,w,h){
+		var win = window.open("","_firebug","status=0,menubar=0,resizable=1,top="+y+",left="+x+",width="+w+",height="+h+",scrollbars=1,addressbar=0");
+		if(!win){
+			var msg = "Firebug Lite could not open a pop-up window, most likely because of a blocker.\n" +
+				"Either enable pop-ups for this domain, or change the djConfig to popup=false.";
+			alert(msg);
+		}
+		createResizeHandler(win);
+		var newDoc=win.document;
+		//Safari needs an HTML height
+		var HTMLstring=	'<html style="height:100%;"><head><title>Firebug Lite</title></head>\n' +
+					'<body bgColor="#ccc" style="height:97%;" onresize="opener.onFirebugResize()">\n' +
+					'<div id="fb"></div>' +
+					'</body></html>';
+	
+		newDoc.write(HTMLstring);
+		newDoc.close();
+		return win;
+	}
+
+	function createResizeHandler(wn){
+		// summary
+		//		Creates handle for onresize window. Called from script in popup's body tag (so that it will work with IE).
+		//
+		
+		var d = new Date();
+			d.setTime(d.getTime()+(60*24*60*60*1000)); // 60 days
+			d = d.toUTCString();
+			
+			var dc = wn.document,
+				getViewport;
+				
+			if (wn.innerWidth){
+				getViewport = function(){
+					return{w:wn.innerWidth, h:wn.innerHeight};
+				};
+			}else if (dc.documentElement && dc.documentElement.clientWidth){
+				getViewport = function(){
+					return{w:dc.documentElement.clientWidth, h:dc.documentElement.clientHeight};
+				};
+			}else if (dc.body){
+				getViewport = function(){
+					return{w:dc.body.clientWidth, h:dc.body.clientHeight};
+				};
+			}
+			
+
+		window.onFirebugResize = function(){ 
+			
+			//resize the height of the console log body
+			layout(getViewport().h);
+			
+			clearInterval(wn._firebugWin_resize);
+			wn._firebugWin_resize = setTimeout(function(){
+				var x = wn.screenLeft,
+					y = wn.screenTop,
+					w = wn.outerWidth  || wn.document.body.offsetWidth,
+					h = wn.outerHeight || wn.document.body.offsetHeight;
+				
+				document.cookie = "_firebugPosition=" + [x,y,w,h].join(",") + "; expires="+d+"; path=/";
+					 
+			 }, 5000); //can't capture window.onMove - long timeout gives better chance of capturing a resize, then the move
+		
+		};
+	}
+	
+	
+	/*****************************************************************************/
+	
+	
+	function createFrame(){
+		if(consoleFrame){
+			return;
+		}
+		
+		if(dojo.config.popup){
+			var containerHeight = "100%";
+			var cookieMatch = document.cookie.match(/(?:^|; )_firebugPosition=([^;]*)/);
+			var p = cookieMatch ? cookieMatch[1].split(",") : [2,2,320,480];
+
+			_firebugWin = openWin(p[0],p[1],p[2],p[3]);	// global
+			_firebugDoc = _firebugWin.document;			// global
+
+			dojo.config.debugContainerId = 'fb';
+		
+			// connecting popup
+			_firebugWin.console = window.console;
+			_firebugWin.dojo = window.dojo;
+		}else{
+			_firebugDoc = document;
+			containerHeight = (dojo.config.debugHeight || 300) + "px";
+		}
+		
+		var styleElement = _firebugDoc.createElement("link");
+		styleElement.href = dojo.moduleUrl("dojo._firebug", "firebug.css");
+		styleElement.rel = "stylesheet";
+		styleElement.type = "text/css";
+		var styleParent = _firebugDoc.getElementsByTagName("head");
+		if(styleParent){
+			styleParent = styleParent[0];
+		}
+		if(!styleParent){
+			styleParent = _firebugDoc.getElementsByTagName("html")[0];
+		}
+		if(dojo.isIE){
+			window.setTimeout(function(){ styleParent.appendChild(styleElement); }, 0);
+		}else{
+			styleParent.appendChild(styleElement);
+		}
+		
+		if(dojo.config.debugContainerId){
+			consoleFrame = _firebugDoc.getElementById(dojo.config.debugContainerId);
+		}
+		if(!consoleFrame){
+			consoleFrame = _firebugDoc.createElement("div");
+			_firebugDoc.body.appendChild(consoleFrame);
+		}
+		consoleFrame.className += " firebug";
+		consoleFrame.style.height = containerHeight;
+		consoleFrame.style.display = (frameVisible ? "block" : "none");	  
+		
+		var buildLink = function(label, title, method, _class){
+			return '<li class="'+_class+'"><a href="javascript:void(0);" onclick="console.'+ method +'(); return false;" title="'+title+'">'+label+'</a></li>';
+		};
+		consoleFrame.innerHTML = 
+			  '<div id="firebugToolbar">'
+			+ '  <ul id="fireBugTabs" class="tabs">'
+			
+			+ buildLink("Clear", "Remove All Console Logs", "clear", "")
+			+ buildLink("ReCSS", "Refresh CSS without reloading page", "recss", "")
+			
+			+ buildLink("Console", "Show Console Logs", "openConsole", "gap")
+			+ buildLink("DOM", "Show DOM Inspector", "openDomInspector", "")
+			+ buildLink("Object", "Show Object Inspector", "openObjectInspector", "")
+			+ ((dojo.config.popup) ? "" : buildLink("Close", "Close the console", "close", "gap"))
+			
+			+ '	</ul>'
+			+ '</div>'
+			+ '<input type="text" id="firebugCommandLine" />'
+			+ '<div id="firebugLog"></div>'
+			+ '<div id="objectLog" style="display:none;">Click on an object in the Log display</div>'
+			+ '<div id="domInspect" style="display:none;">Hover over HTML elements in the main page. Click to hold selection.</div>';
+
+
+		consoleToolbar = _firebugDoc.getElementById("firebugToolbar");
+
+		commandLine = _firebugDoc.getElementById("firebugCommandLine");
+		addEvent(commandLine, "keydown", onCommandLineKeyDown);
+
+		addEvent(_firebugDoc, dojo.isIE || dojo.isSafari ? "keydown" : "keypress", onKeyDown);
+		
+		consoleBody = _firebugDoc.getElementById("firebugLog");
+		consoleObjectInspector = _firebugDoc.getElementById("objectLog");
+		consoleDomInspector = _firebugDoc.getElementById("domInspect");
+		fireBugTabs = _firebugDoc.getElementById("fireBugTabs");
+		layout();
+		flush();
+	}
+
+	dojo.addOnLoad(createFrame);
+
+	function clearFrame(){
+		_firebugDoc = null;
+		
+		if(_firebugWin.console){
+			_firebugWin.console.clear();
+		}
+		_firebugWin = null;
+		consoleFrame = null;
+		consoleBody = null;
+		consoleObjectInspector = null;
+		consoleDomInspector = null;
+		commandLine = null;
+		messageQueue = [];
+		groupStack = [];
+		timeMap = {};
+	}
+	
+
+	function evalCommandLine(){
+		var text = commandLine.value;
+		commandLine.value = "";
+
+		logRow([">  ", text], "command");
+		
+		var value;
+		try{
+			value = eval(text);
+		}catch(e){
+			console.debug(e); // put exception on the console
+		}
+
+		console.log(value);
+	}
+	
+	function layout(h){
+		var tHeight = 25; //consoleToolbar.offsetHeight; // tab style not ready on load - throws off layout
+		var height = h ? 
+			h  - (tHeight + commandLine.offsetHeight +25 + (h*.01)) + "px" : 
+			(consoleFrame.offsetHeight - tHeight - commandLine.offsetHeight) + "px";
+		
+		consoleBody.style.top = tHeight + "px";
+		consoleBody.style.height = height;
+		consoleObjectInspector.style.height = height;
+		consoleObjectInspector.style.top = tHeight + "px";
+		consoleDomInspector.style.height = height;
+		consoleDomInspector.style.top = tHeight + "px";
+		commandLine.style.bottom = 0;
+		
+		dojo.addOnWindowUnload(clearFrame)
+	}
+	
+	function logRow(message, className, handler){
+		if(consoleBody){
+			writeMessage(message, className, handler);
+		}else{
+			messageQueue.push([message, className, handler]);
+		}
+	}
+	
+	function flush(){
+		var queue = messageQueue;
+		messageQueue = [];
+		
+		for(var i = 0; i < queue.length; ++i){
+			writeMessage(queue[i][0], queue[i][1], queue[i][2]);
+		}
+	}
+
+	function writeMessage(message, className, handler){
+		var isScrolledToBottom =
+			consoleBody.scrollTop + consoleBody.offsetHeight >= consoleBody.scrollHeight;
+
+		handler = handler||writeRow;
+		
+		handler(message, className);
+		
+		if(isScrolledToBottom){
+			consoleBody.scrollTop = consoleBody.scrollHeight - consoleBody.offsetHeight;
+		}
+	}
+	
+	function appendRow(row){
+		var container = groupStack.length ? groupStack[groupStack.length-1] : consoleBody;
+		container.appendChild(row);
+	}
+
+	function writeRow(message, className){
+		var row = consoleBody.ownerDocument.createElement("div");
+		row.className = "logRow" + (className ? " logRow-"+className : "");
+		row.innerHTML = message.join("");
+		appendRow(row);
+	}
+
+	function pushGroup(message, className){
+		logFormatted(message, className);
+
+		//var groupRow = consoleBody.ownerDocument.createElement("div");
+		//groupRow.className = "logGroup";
+		var groupRowBox = consoleBody.ownerDocument.createElement("div");
+		groupRowBox.className = "logGroupBox";
+		//groupRow.appendChild(groupRowBox);
+		appendRow(groupRowBox);
+		groupStack.push(groupRowBox);
+	}
+
+	function popGroup(){
+		groupStack.pop();
+	}
+	
+	// ***************************************************************************
+
+	function logFormatted(objects, className){
+		var html = [];
+		
+		var format = objects[0];
+		var objIndex = 0;
+
+		if(typeof(format) != "string"){
+			format = "";
+			objIndex = -1;
+		}
+
+		var parts = parseFormat(format);
+		
+		for(var i = 0; i < parts.length; ++i){
+			var part = parts[i];
+			if(part && typeof part == "object"){
+				part.appender(objects[++objIndex], html);
+			}else{
+				appendText(part, html);
+			}
+		}
+		
+		
+		var ids = [];
+		var obs = [];
+		for(i = objIndex+1; i < objects.length; ++i){
+			appendText(" ", html);
+			
+			var object = objects[i];
+			if(object === undefined || object === null ){
+				appendNull(object, html);
+
+			}else if(typeof(object) == "string"){
+				appendText(object, html);
+			
+			}else if(object instanceof Date){
+				appendText(object.toString(), html);
+				
+			}else if(object.nodeType == 9){
+				appendText("[ XmlDoc ]", html);
+
+			}else{
+				// Create link for object inspector
+				// need to create an ID for this link, since it is currently text
+				var id = "_a" + __consoleAnchorId__++;
+				ids.push(id);
+				// need to save the object, so the arrays line up
+				obs.push(object);
+				var str = '<a id="'+id+'" href="javascript:void(0);">'+getObjectAbbr(object)+'</a>';
+				
+				appendLink( str , html);
+			}
+		}
+		
+		logRow(html, className);
+		
+		// Now that the row is inserted in the DOM, loop through all of the links that were just created
+		for(i=0; i<ids.length; i++){
+			var btn = _firebugDoc.getElementById(ids[i]);
+			if(!btn){ continue; }
+	
+			// store the object in the dom btn for reference later
+			// avoid parsing these objects unless necessary
+			btn.obj = obs[i];
+	
+			_firebugWin.console._connects.push(dojo.connect(btn, "onclick", function(){
+				
+				console.openObjectInspector();
+				
+				try{
+					printObject(this.obj);
+				}catch(e){
+					this.obj = e;
+				}
+				consoleObjectInspector.innerHTML = "<pre>" + printObject( this.obj ) + "</pre>";
+			}));
+		}
+	}
+
+	function parseFormat(format){
+		var parts = [];
+
+		var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;	  
+		var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat};
+
+		for(var m = reg.exec(format); m; m = reg.exec(format)){
+			var type = m[8] ? m[8] : m[5];
+			var appender = type in appenderMap ? appenderMap[type] : appendObject;
+			var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
+
+			parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
+			parts.push({appender: appender, precision: precision});
+
+			format = format.substr(m.index+m[0].length);
+		}
+
+		parts.push(format);
+
+		return parts;
+	}
+
+	function escapeHTML(value){
+		function replaceChars(ch){
+			switch(ch){
+				case "<":
+					return "<";
+				case ">":
+					return ">";
+				case "&":
+					return "&";
+				case "'":
+					return "'";
+				case '"':
+					return """;
+			}
+			return "?";
+		}
+		return String(value).replace(/[<>&"']/g, replaceChars);
+	}
+
+	function objectToString(object){
+		try{
+			return object+"";
+		}catch(e){
+			return null;
+		}
+	}
+
+	// ***************************************************************************
+	function appendLink(object, html){
+		// needed for object links - no HTML escaping
+		html.push( objectToString(object) );
+	}
+	
+	function appendText(object, html){
+		html.push(escapeHTML(objectToString(object)));
+	}
+
+	function appendNull(object, html){
+		html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>');
+	}
+
+	function appendString(object, html){
+		html.push('<span class="objectBox-string">"', escapeHTML(objectToString(object)),
+			'"</span>');
+	}
+
+	function appendInteger(object, html){
+		html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
+	}
+
+	function appendFloat(object, html){
+		html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
+	}
+
+	function appendFunction(object, html){
+		html.push('<span class="objectBox-function">', getObjectAbbr(object), '</span>');
+	}
+	
+	function appendObject(object, html){
+		try{
+			if(object === undefined){
+				appendNull("undefined", html);
+			}else if(object === null){
+				appendNull("null", html);
+			}else if(typeof object == "string"){
+				appendString(object, html);
+			}else if(typeof object == "number"){
+				appendInteger(object, html);
+			}else if(typeof object == "function"){
+				appendFunction(object, html);
+			}else if(object.nodeType == 1){
+				appendSelector(object, html);
+			}else if(typeof object == "object"){
+				appendObjectFormatted(object, html);
+			}else{
+				appendText(object, html);
+			}
+		}catch(e){
+			/* squelch */
+		}
+	}
+		
+	function appendObjectFormatted(object, html){
+		var text = objectToString(object);
+		var reObject = /\[object (.*?)\]/;
+
+		var m = reObject.exec(text);
+		html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>');
+	}
+	
+	function appendSelector(object, html){
+		html.push('<span class="objectBox-selector">');
+
+		html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>');
+		if(object.id){
+			html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>');
+		}
+		if(object.className){
+			html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>');
+		}
+
+		html.push('</span>');
+	}
+
+	function appendNode(node, html){
+		if(node.nodeType == 1){
+			html.push(
+				'<div class="objectBox-element">',
+					'<<span class="nodeTag">', node.nodeName.toLowerCase(), '</span>');
+
+			for(var i = 0; i < node.attributes.length; ++i){
+				var attr = node.attributes[i];
+				if(!attr.specified){ continue; }
+				
+				html.push(' <span class="nodeName">', attr.nodeName.toLowerCase(),
+					'</span>="<span class="nodeValue">', escapeHTML(attr.nodeValue),
+					'</span>"');
+			}
+
+			if(node.firstChild){
+				html.push('></div><div class="nodeChildren">');
+
+				for(var child = node.firstChild; child; child = child.nextSibling){
+					appendNode(child, html);
+				}
+					
+				html.push('</div><div class="objectBox-element"></<span class="nodeTag">', 
+					node.nodeName.toLowerCase(), '></span></div>');
+			}else{
+				html.push('/></div>');
+			}
+		}else if (node.nodeType == 3){
+			html.push('<div class="nodeText">', escapeHTML(node.nodeValue),
+				'</div>');
+		}
+	}
+
+	// ***************************************************************************
+	
+	function addEvent(object, name, handler){
+		if(document.all){
+			object.attachEvent("on"+name, handler);
+		}else{
+			object.addEventListener(name, handler, false);
+		}
+	}
+	
+	function removeEvent(object, name, handler){
+		if(document.all){
+			object.detachEvent("on"+name, handler);
+		}else{
+			object.removeEventListener(name, handler, false);
+		}
+	}
+	
+	function cancelEvent(event){
+		if(document.all){
+			event.cancelBubble = true;
+		}else{
+			event.stopPropagation();		
+		}
+	}
+
+	function onError(msg, href, lineNo){
+		var lastSlash = href.lastIndexOf("/");
+		var fileName = lastSlash == -1 ? href : href.substr(lastSlash+1);
+
+		var html = [
+			'<span class="errorMessage">', msg, '</span>', 
+			'<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>'
+		];
+
+		logRow(html, "error");
+	}
+
+
+	//After converting to div instead of iframe, now getting two keydowns right away in IE 6.
+	//Make sure there is a little bit of delay.
+	var onKeyDownTime = new Date().getTime();
+
+	function onKeyDown(event){
+		var timestamp = (new Date()).getTime();
+		if(timestamp > onKeyDownTime + 200){
+			event = dojo.fixEvent(event);
+			var keys = dojo.keys;
+			var ekc = event.keyCode;
+			onKeyDownTime = timestamp;
+			if(ekc == keys.F12){
+				toggleConsole();
+			}else if(
+				(ekc == keys.NUMPAD_ENTER || ekc == 76) &&
+				event.shiftKey && 
+				(event.metaKey || event.ctrlKey)
+			){
+				focusCommandLine();
+			}else{
+				return;
+			}
+			cancelEvent(event);
+		}
+	}
+
+	function onCommandLineKeyDown(e){
+		var dk = dojo.keys;
+		if(e.keyCode == 13 && commandLine.value){
+			addToHistory(commandLine.value);
+			evalCommandLine();
+		}else if(e.keyCode == 27){
+			commandLine.value = "";
+		}else if(e.keyCode == dk.UP_ARROW || e.charCode == dk.UP_ARROW){
+			navigateHistory("older");
+		}else if(e.keyCode == dk.DOWN_ARROW || e.charCode == dk.DOWN_ARROW){
+			navigateHistory("newer");
+		}else if(e.keyCode == dk.HOME || e.charCode == dk.HOME){
+			historyPosition = 1;
+			navigateHistory("older");
+		}else if(e.keyCode == dk.END || e.charCode == dk.END){
+			historyPosition = 999999;
+			navigateHistory("newer");
+		}
+	}
+
+	var historyPosition = -1;
+	var historyCommandLine = null;
+
+	function addToHistory(value){
+		var history = cookie("firebug_history");
+		history = (history) ? dojo.fromJson(history) : [];
+		var pos = dojo.indexOf(history, value);
+		if (pos != -1){
+			history.splice(pos, 1);
+		}
+		history.push(value);
+		cookie("firebug_history", dojo.toJson(history), 30);
+		while(history.length && !cookie("firebug_history")){
+			history.shift();
+			cookie("firebug_history", dojo.toJson(history), 30);
+		}
+		historyCommandLine = null;
+		historyPosition = -1;
+	}
+
+	function navigateHistory(direction){
+		var history = cookie("firebug_history");
+		history = (history) ? dojo.fromJson(history) : [];
+		if(!history.length){
+			return;
+		}
+
+		if(historyCommandLine === null){
+			historyCommandLine = commandLine.value;
+		}
+
+		if(historyPosition == -1){
+			historyPosition = history.length;
+		}
+
+		if(direction == "older"){
+			--historyPosition;
+			if(historyPosition < 0){
+				historyPosition = 0;
+			}
+		}else if(direction == "newer"){
+			++historyPosition;
+			if(historyPosition > history.length){
+				historyPosition = history.length;
+			}
+		}
+
+		if(historyPosition == history.length){
+			commandLine.value = historyCommandLine;
+			historyCommandLine = null;
+		}else{
+			commandLine.value = history[historyPosition];
+		}
+	}
+
+	function cookie(name, value){
+		var c = document.cookie;
+		if(arguments.length == 1){
+			var matches = c.match(new RegExp("(?:^|; )" + name + "=([^;]*)"));
+			return matches ? decodeURIComponent(matches[1]) : undefined; // String or undefined
+		}else{
+			var d = new Date();
+			d.setMonth(d.getMonth()+1);
+			document.cookie = name + "=" + encodeURIComponent(value) + ((d.toUtcString) ? "; expires=" + d.toUTCString() : "");
+		}
+	};
+
+	function isArray(it){
+		return it && it instanceof Array || typeof it == "array";
+	}
+
+	//***************************************************************************************************
+	// Print Object Helpers
+	function objectLength(o){
+		var cnt = 0;
+		for(var nm in o){
+			cnt++	
+		}
+		return cnt;
+	}
+	
+	function printObject(o, i, txt, used){
+		// Recursively trace object, indenting to represent depth for display in object inspector
+		var ind = " \t";
+		txt = txt || "";
+		i = i || ind;
+		used = used || [];
+		var opnCls;
+		
+		if(o && o.nodeType == 1){
+			var html = [];
+			appendNode(o, html);
+			return html.join("");
+		}
+		
+		var br=",\n", cnt = 0, length = objectLength(o);
+		
+		if(o instanceof Date){
+			return i + o.toString() + br;
+		}
+		looking:
+		for(var nm in o){
+			cnt++;
+			if(cnt==length){br = "\n";}
+			if(o[nm] === window || o[nm] === document){
+				continue;
+			}else if(o[nm] === null){
+				txt += i+nm + " : NULL" + br;
+			}else if(o[nm] && o[nm].nodeType){
+				if(o[nm].nodeType == 1){
+					//txt += i+nm + " : < "+o[nm].tagName+" id=\""+ o[nm].id+"\" />" + br;
+				}else if(o[nm].nodeType == 3){
+					txt += i+nm + " : [ TextNode "+o[nm].data + " ]" + br;
+				}
+			
+			}else if(typeof o[nm] == "object" && (o[nm] instanceof String || o[nm] instanceof Number || o[nm] instanceof Boolean)){
+				txt += i+nm + " : " + o[nm] + "," + br;
+			
+			}else if(o[nm] instanceof Date){
+				txt += i+nm + " : " + o[nm].toString() + br;
+				
+			}else if(typeof(o[nm]) == "object" && o[nm]){
+				for(var j = 0, seen; seen = used[j]; j++){
+					if(o[nm] === seen){
+						txt += i+nm + " : RECURSION" + br;
+						continue looking;
+					}
+				}
+				used.push(o[nm]);
+				
+				opnCls = (isArray(o[nm]))?["[","]"]:["{","}"];
+				txt += i+nm +" : " + opnCls[0] + "\n";//non-standard break, (no comma)
+				txt += printObject(o[nm], i+ind, "", used);
+				txt += i + opnCls[1] + br;
+			
+			}else if(typeof o[nm] == "undefined"){
+				txt += i+nm + " : undefined" + br;
+			}else if(nm == "toString" && typeof o[nm] == "function"){
+				var toString = o[nm]();
+				if(typeof toString == "string" && toString.match(/function ?(.*?)\(/)){
+					toString = escapeHTML(getObjectAbbr(o[nm]));
+				}
+				txt += i+nm +" : " + toString + br;
+			}else{
+				txt += i+nm +" : "+ escapeHTML(getObjectAbbr(o[nm])) + br;
+			}
+		}
+		return txt;
+	}
+
+	function getObjectAbbr(obj){
+		// Gets an abbreviation of an object for display in log
+		// X items in object, including id
+		// X items in an array
+		// TODO: Firebug Sr. actually goes by char count
+		var isError = (obj instanceof Error);
+		if(obj.nodeType == 1){
+			return escapeHTML('< '+obj.tagName.toLowerCase()+' id=\"'+ obj.id+ '\" />');
+		}
+		if(obj.nodeType == 3){
+			return escapeHTML('[TextNode: "'+obj.nodeValue+'"]');
+		}
+		var nm = (obj && (obj.id || obj.name || obj.ObjectID || obj.widgetId));
+		if(!isError && nm){ return "{"+nm+"}";	}
+
+		var obCnt = 2;
+		var arCnt = 4;
+		var cnt = 0;
+
+		if(isError){
+			nm = "[ Error: "+(obj.message || obj.description || obj)+" ]";
+		}else if(isArray(obj)){
+			nm = "[" + obj.slice(0,arCnt).join(",");
+			if(obj.length > arCnt){
+				nm += " ... ("+obj.length+" items)";
+			}
+			nm += "]";
+		}else if(typeof obj == "function"){
+			nm = obj + "";
+			var reg = /function\s*([^\(]*)(\([^\)]*\))[^\{]*\{/;
+			var m = reg.exec(nm);
+			if(m){
+				if(!m[1]){
+					m[1] = "function";
+				}
+				nm = m[1] + m[2];
+			}else{
+				nm = "function()";
+			}
+		}else if(typeof obj != "object" || typeof obj == "string"){
+			nm = obj + "";
+		}else{
+			nm = "{";
+			for(var i in obj){
+				cnt++;
+				if(cnt > obCnt){ break; }
+				nm += i+":"+escapeHTML(obj[i])+"  ";
+			}
+			nm+="}";
+		}
+		
+		return nm;
+	}
+		
+	//*************************************************************************************
+	
+	//window.onerror = onError;
+	
+	addEvent(document, dojo.isIE || dojo.isSafari ? "keydown" : "keypress", onKeyDown);
+	
+	if(	(document.documentElement.getAttribute("debug") == "true")||
+		(dojo.config.isDebug)
+	){
+		toggleConsole(true);
+	}
+
+	dojo.addOnWindowUnload(function(){
+		// Erase the globals and event handlers I created, to prevent spurious leak warnings
+		removeEvent(document, dojo.isIE || dojo.isSafari ? "keydown" : "keypress", onKeyDown);
+		window.onFirebugResize = null;
+		window.console = null;
+	});
 }
+
 })();
-}
+
diff --git a/dojo/back.js b/dojo/back.js
index 47dd3a8..c8d0a29 100644
--- a/dojo/back.js
+++ b/dojo/back.js
@@ -1,258 +1,399 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.back"]){
-dojo._hasResource["dojo.back"]=true;
 dojo.provide("dojo.back");
-(function(){
-var _1=dojo.back;
-function _2(){
-var h=window.location.hash;
-if(h.charAt(0)=="#"){
-h=h.substring(1);
-}
-return dojo.isMozilla?h:decodeURIComponent(h);
-};
-function _3(h){
-if(!h){
-h="";
-}
-window.location.hash=encodeURIComponent(h);
-_4=history.length;
-};
-if(dojo.exists("tests.back-hash")){
-_1.getHash=_2;
-_1.setHash=_3;
-}
-var _5=(typeof (window)!=="undefined")?window.location.href:"";
-var _6=(typeof (window)!=="undefined")?_2():"";
-var _7=null;
-var _8=null;
-var _9=null;
-var _a=null;
-var _b=[];
-var _c=[];
-var _d=false;
-var _e=false;
-var _4;
-function _f(){
-var _10=_c.pop();
-if(!_10){
-return;
-}
-var _11=_c[_c.length-1];
-if(!_11&&_c.length==0){
-_11=_7;
-}
-if(_11){
-if(_11.kwArgs["back"]){
-_11.kwArgs["back"]();
-}else{
-if(_11.kwArgs["backButton"]){
-_11.kwArgs["backButton"]();
-}else{
-if(_11.kwArgs["handle"]){
-_11.kwArgs.handle("back");
-}
-}
-}
-}
-_b.push(_10);
-};
-_1.goBack=_f;
-function _12(){
-var _13=_b.pop();
-if(!_13){
-return;
-}
-if(_13.kwArgs["forward"]){
-_13.kwArgs.forward();
-}else{
-if(_13.kwArgs["forwardButton"]){
-_13.kwArgs.forwardButton();
-}else{
-if(_13.kwArgs["handle"]){
-_13.kwArgs.handle("forward");
-}
-}
-}
-_c.push(_13);
-};
-_1.goForward=_12;
-function _14(url,_15,_16){
-return {"url":url,"kwArgs":_15,"urlHash":_16};
-};
-function _17(url){
-var _18=url.split("?");
-if(_18.length<2){
-return null;
-}else{
-return _18[1];
-}
-};
-function _19(){
-var url=(dojo.config["dojoIframeHistoryUrl"]||dojo.moduleUrl("dojo","resources/iframe_history.html"))+"?"+(new Date()).getTime();
-_d=true;
-if(_a){
-dojo.isWebKit?_a.location=url:window.frames[_a.name].location=url;
-}else{
-}
-return url;
-};
-function _1a(){
-if(!_e){
-var hsl=_c.length;
-var _1b=_2();
-if((_1b===_6||window.location.href==_5)&&(hsl==1)){
-_f();
-return;
-}
-if(_b.length>0){
-if(_b[_b.length-1].urlHash===_1b){
-_12();
-return;
-}
-}
-if((hsl>=2)&&(_c[hsl-2])){
-if(_c[hsl-2].urlHash===_1b){
-_f();
-return;
-}
-}
-if(dojo.isSafari&&dojo.isSafari<3){
-var _1c=history.length;
-if(_1c>_4){
-_12();
-}else{
-if(_1c<_4){
-_f();
-}
-}
-_4=_1c;
-}
-}
-};
-_1.init=function(){
-if(dojo.byId("dj_history")){
-return;
-}
-var src=dojo.config["dojoIframeHistoryUrl"]||dojo.moduleUrl("dojo","resources/iframe_history.html");
-if(dojo._postLoad){
-console.error("dojo.back.init() must be called before the DOM has loaded. "+"If using xdomain loading or djConfig.debugAtAllCosts, include dojo.back "+"in a build layer.");
-}else{
-document.write("<iframe style=\"border:0;width:1px;height:1px;position:absolute;visibility:hidden;bottom:0;right:0;\" name=\"dj_history\" id=\"dj_history\" src=\""+src+"\"></iframe>");
-}
-};
-_1.setInitialState=function(_1d){
-_7=_14(_5,_1d,_6);
-};
-_1.addToHistory=function(_1e){
-_b=[];
-var _1f=null;
-var url=null;
-if(!_a){
-if(dojo.config["useXDomain"]&&!dojo.config["dojoIframeHistoryUrl"]){
-console.warn("dojo.back: When using cross-domain Dojo builds,"+" please save iframe_history.html to your domain and set djConfig.dojoIframeHistoryUrl"+" to the path on your domain to iframe_history.html");
-}
-_a=window.frames["dj_history"];
-}
-if(!_9){
-_9=dojo.create("a",{style:{display:"none"}},dojo.body());
-}
-if(_1e["changeUrl"]){
-_1f=""+((_1e["changeUrl"]!==true)?_1e["changeUrl"]:(new Date()).getTime());
-if(_c.length==0&&_7.urlHash==_1f){
-_7=_14(url,_1e,_1f);
-return;
-}else{
-if(_c.length>0&&_c[_c.length-1].urlHash==_1f){
-_c[_c.length-1]=_14(url,_1e,_1f);
-return;
-}
-}
-_e=true;
-setTimeout(function(){
-_3(_1f);
-_e=false;
-},1);
-_9.href=_1f;
-if(dojo.isIE){
-url=_19();
-var _20=_1e["back"]||_1e["backButton"]||_1e["handle"];
-var tcb=function(_21){
-if(_2()!=""){
-setTimeout(function(){
-_3(_1f);
-},1);
-}
-_20.apply(this,[_21]);
-};
-if(_1e["back"]){
-_1e.back=tcb;
-}else{
-if(_1e["backButton"]){
-_1e.backButton=tcb;
-}else{
-if(_1e["handle"]){
-_1e.handle=tcb;
-}
-}
-}
-var _22=_1e["forward"]||_1e["forwardButton"]||_1e["handle"];
-var tfw=function(_23){
-if(_2()!=""){
-_3(_1f);
-}
-if(_22){
-_22.apply(this,[_23]);
-}
-};
-if(_1e["forward"]){
-_1e.forward=tfw;
-}else{
-if(_1e["forwardButton"]){
-_1e.forwardButton=tfw;
-}else{
-if(_1e["handle"]){
-_1e.handle=tfw;
-}
-}
-}
-}else{
-if(!dojo.isIE){
-if(!_8){
-_8=setInterval(_1a,200);
-}
-}
-}
-}else{
-url=_19();
-}
-_c.push(_14(url,_1e,_1f));
-};
-_1._iframeLoaded=function(evt,_24){
-var _25=_17(_24.href);
-if(_25==null){
-if(_c.length==1){
-_f();
-}
-return;
-}
-if(_d){
-_d=false;
-return;
-}
-if(_c.length>=2&&_25==_17(_c[_c.length-2].url)){
-_f();
-}else{
-if(_b.length>0&&_25==_17(_b[_b.length-1].url)){
-_12();
-}
-}
-};
-})();
+
+/*=====
+dojo.back = {
+	// summary: Browser history management resources
 }
+=====*/
+
+
+(function(){ 
+	var back = dojo.back;
+
+	// everyone deals with encoding the hash slightly differently
+
+	function getHash(){ 
+		var h = window.location.hash;
+		if(h.charAt(0) == "#"){ h = h.substring(1); }
+		return dojo.isMozilla ? h : decodeURIComponent(h); 
+	}
+	
+	function setHash(h){
+		if(!h){ h = ""; }
+		window.location.hash = encodeURIComponent(h);
+		historyCounter = history.length;
+	}
+	
+	// if we're in the test for these methods, expose them on dojo.back. ok'd with alex.
+	if(dojo.exists("tests.back-hash")){
+		back.getHash = getHash;
+		back.setHash = setHash;		
+	}
+	
+	var initialHref = (typeof(window) !== "undefined") ? window.location.href : "";
+	var initialHash = (typeof(window) !== "undefined") ? getHash() : "";
+	var initialState = null;
+
+	var locationTimer = null;
+	var bookmarkAnchor = null;
+	var historyIframe = null;
+	var forwardStack = [];
+	var historyStack = [];
+	var moveForward = false;
+	var changingUrl = false;
+	var historyCounter;
+
+	function handleBackButton(){
+		//summary: private method. Do not call this directly.
+
+		//The "current" page is always at the top of the history stack.
+		var current = historyStack.pop();
+		if(!current){ return; }
+		var last = historyStack[historyStack.length-1];
+		if(!last && historyStack.length == 0){
+			last = initialState;
+		}
+		if(last){
+			if(last.kwArgs["back"]){
+				last.kwArgs["back"]();
+			}else if(last.kwArgs["backButton"]){
+				last.kwArgs["backButton"]();
+			}else if(last.kwArgs["handle"]){
+				last.kwArgs.handle("back");
+			}
+		}
+		forwardStack.push(current);
+	}
+
+	back.goBack = handleBackButton;
+
+	function handleForwardButton(){
+		//summary: private method. Do not call this directly.
+		var last = forwardStack.pop();
+		if(!last){ return; }
+		if(last.kwArgs["forward"]){
+			last.kwArgs.forward();
+		}else if(last.kwArgs["forwardButton"]){
+			last.kwArgs.forwardButton();
+		}else if(last.kwArgs["handle"]){
+			last.kwArgs.handle("forward");
+		}
+		historyStack.push(last);
+	}
+
+	back.goForward = handleForwardButton;
+
+	function createState(url, args, hash){
+		//summary: private method. Do not call this directly.
+		return {"url": url, "kwArgs": args, "urlHash": hash};	//Object
+	}
+
+	function getUrlQuery(url){
+		//summary: private method. Do not call this directly.
+		var segments = url.split("?");
+		if(segments.length < 2){
+			return null; //null
+		}
+		else{
+			return segments[1]; //String
+		}
+	}
+	
+	function loadIframeHistory(){
+		//summary: private method. Do not call this directly.
+		var url = (dojo.config["dojoIframeHistoryUrl"] || dojo.moduleUrl("dojo", "resources/iframe_history.html")) + "?" + (new Date()).getTime();
+		moveForward = true;
+        if(historyIframe){
+		    dojo.isWebKit ? historyIframe.location = url : window.frames[historyIframe.name].location = url;
+        }else{
+            //console.warn("dojo.back: Not initialised. You need to call dojo.back.init() from a <script> block that lives inside the <body> tag.");
+        }
+		return url; //String
+	}
+
+	function checkLocation(){
+		if(!changingUrl){
+			var hsl = historyStack.length;
+			
+			var hash = getHash();
+
+			if((hash === initialHash||window.location.href == initialHref)&&(hsl == 1)){
+				// FIXME: could this ever be a forward button?
+				// we can't clear it because we still need to check for forwards. Ugg.
+				// clearInterval(this.locationTimer);
+				handleBackButton();
+				return;
+			}
+			
+			// first check to see if we could have gone forward. We always halt on
+			// a no-hash item.
+			if(forwardStack.length > 0){
+				if(forwardStack[forwardStack.length-1].urlHash === hash){
+					handleForwardButton();
+					return;
+				}
+			}
+	
+			// ok, that didn't work, try someplace back in the history stack
+			if((hsl >= 2)&&(historyStack[hsl-2])){
+				if(historyStack[hsl-2].urlHash === hash){
+					handleBackButton();
+					return;
+				}
+			}
+			
+			if(dojo.isSafari && dojo.isSafari < 3){
+				var hisLen = history.length;
+				if(hisLen > historyCounter) handleForwardButton();
+				else if(hisLen < historyCounter) handleBackButton();
+			  historyCounter = hisLen;
+			}
+		}
+	};
+	
+	back.init = function(){
+		//summary: Initializes the undo stack. This must be called from a <script> 
+		//         block that lives inside the <body> tag to prevent bugs on IE.
+		// description:
+		// 		Only call this method before the page's DOM is finished loading. Otherwise
+		// 		it will not work. Be careful with xdomain loading or djConfig.debugAtAllCosts scenarios,
+		// 		in order for this method to work, dojo.back will need to be part of a build layer.
+		if(dojo.byId("dj_history")){ return; } // prevent reinit
+		var src = dojo.config["dojoIframeHistoryUrl"] || dojo.moduleUrl("dojo", "resources/iframe_history.html");
+		if (dojo._postLoad) {
+			console.error("dojo.back.init() must be called before the DOM has loaded. "
+			            + "If using xdomain loading or djConfig.debugAtAllCosts, include dojo.back "
+			            + "in a build layer.");
+		} else {
+			document.write('<iframe style="border:0;width:1px;height:1px;position:absolute;visibility:hidden;bottom:0;right:0;" name="dj_history" id="dj_history" src="' + src + '"></iframe>');
+		}
+	};
+
+	back.setInitialState = function(/*Object*/args){
+		//summary: 
+		//		Sets the state object and back callback for the very first page
+		//		that is loaded.
+		//description:
+		//		It is recommended that you call this method as part of an event
+		//		listener that is registered via dojo.addOnLoad().
+		//args: Object
+		//		See the addToHistory() function for the list of valid args properties.
+		initialState = createState(initialHref, args, initialHash);
+	};
+
+	//FIXME: Make these doc comments not be awful. At least they're not wrong.
+	//FIXME: Would like to support arbitrary back/forward jumps. Have to rework iframeLoaded among other things.
+	//FIXME: is there a slight race condition in moz using change URL with the timer check and when
+	//       the hash gets set? I think I have seen a back/forward call in quick succession, but not consistent.
+
+	
+	/*=====
+	dojo.__backArgs = function(kwArgs){
+		// back: Function?
+		//		A function to be called when this state is reached via the user
+		//		clicking the back button.
+		//	forward: Function?
+		//		Upon return to this state from the "back, forward" combination
+		//		of navigation steps, this function will be called. Somewhat
+		//		analgous to the semantic of an "onRedo" event handler.
+		//	changeUrl: Boolean?|String?
+		//		Boolean indicating whether or not to create a unique hash for
+		//		this state. If a string is passed instead, it is used as the
+		//		hash.
+	}
+	=====*/
+
+	back.addToHistory = function(/*dojo.__backArgs*/ args){
+		//	summary: 
+		//		adds a state object (args) to the history list. 
+		//	description:
+		//		To support getting back button notifications, the object
+		//		argument should implement a function called either "back",
+		//		"backButton", or "handle". The string "back" will be passed as
+		//		the first and only argument to this callback.
+		//	
+		//		To support getting forward button notifications, the object
+		//		argument should implement a function called either "forward",
+		//		"forwardButton", or "handle". The string "forward" will be
+		//		passed as the first and only argument to this callback.
+		//
+		//		If you want the browser location string to change, define "changeUrl" on the object. If the
+		//		value of "changeUrl" is true, then a unique number will be appended to the URL as a fragment
+		//		identifier (http://some.domain.com/path#uniquenumber). If it is any other value that does
+		//		not evaluate to false, that value will be used as the fragment identifier. For example,
+		//		if changeUrl: 'page1', then the URL will look like: http://some.domain.com/path#page1
+		//
+		//		There are problems with using dojo.back with semantically-named fragment identifiers
+		//		("hash values" on an URL). In most browsers it will be hard for dojo.back to know
+		//		distinguish a back from a forward event in those cases. For back/forward support to
+		//		work best, the fragment ID should always be a unique value (something using new Date().getTime()
+		//		for example). If you want to detect hash changes using semantic fragment IDs, then
+		//		consider using dojo.hash instead (in Dojo 1.4+).
+		//
+	 	//	example:
+		//		|	dojo.back.addToHistory({
+		//		|		back: function(){ console.log('back pressed'); },
+		//		|		forward: function(){ console.log('forward pressed'); },
+		//		|		changeUrl: true
+		//		|	});
+
+		//	BROWSER NOTES:
+		//  Safari 1.2: 
+		//	back button "works" fine, however it's not possible to actually
+		//	DETECT that you've moved backwards by inspecting window.location.
+		//	Unless there is some other means of locating.
+		//	FIXME: perhaps we can poll on history.length?
+		//	Safari 2.0.3+ (and probably 1.3.2+):
+		//	works fine, except when changeUrl is used. When changeUrl is used,
+		//	Safari jumps all the way back to whatever page was shown before
+		//	the page that uses dojo.undo.browser support.
+		//	IE 5.5 SP2:
+		//	back button behavior is macro. It does not move back to the
+		//	previous hash value, but to the last full page load. This suggests
+		//	that the iframe is the correct way to capture the back button in
+		//	these cases.
+		//	Don't test this page using local disk for MSIE. MSIE will not create 
+		//	a history list for iframe_history.html if served from a file: URL. 
+		//	The XML served back from the XHR tests will also not be properly 
+		//	created if served from local disk. Serve the test pages from a web 
+		//	server to test in that browser.
+		//	IE 6.0:
+		//	same behavior as IE 5.5 SP2
+		//	Firefox 1.0+:
+		//	the back button will return us to the previous hash on the same
+		//	page, thereby not requiring an iframe hack, although we do then
+		//	need to run a timer to detect inter-page movement.
+
+		//If addToHistory is called, then that means we prune the
+		//forward stack -- the user went back, then wanted to
+		//start a new forward path.
+		forwardStack = []; 
+
+		var hash = null;
+		var url = null;
+		if(!historyIframe){
+			if(dojo.config["useXDomain"] && !dojo.config["dojoIframeHistoryUrl"]){
+				console.warn("dojo.back: When using cross-domain Dojo builds,"
+					+ " please save iframe_history.html to your domain and set djConfig.dojoIframeHistoryUrl"
+					+ " to the path on your domain to iframe_history.html");
+			}
+			historyIframe = window.frames["dj_history"];
+		}
+		if(!bookmarkAnchor){
+			bookmarkAnchor = dojo.create("a", {style: {display: "none"}}, dojo.body());
+		}
+		if(args["changeUrl"]){
+			hash = ""+ ((args["changeUrl"]!==true) ? args["changeUrl"] : (new Date()).getTime());
+			
+			//If the current hash matches the new one, just replace the history object with
+			//this new one. It doesn't make sense to track different state objects for the same
+			//logical URL. This matches the browser behavior of only putting in one history
+			//item no matter how many times you click on the same #hash link, at least in Firefox
+			//and Safari, and there is no reliable way in those browsers to know if a #hash link
+			//has been clicked on multiple times. So making this the standard behavior in all browsers
+			//so that dojo.back's behavior is the same in all browsers.
+			if(historyStack.length == 0 && initialState.urlHash == hash){
+				initialState = createState(url, args, hash);
+				return;
+			}else if(historyStack.length > 0 && historyStack[historyStack.length - 1].urlHash == hash){
+				historyStack[historyStack.length - 1] = createState(url, args, hash);
+				return;
+			}
+
+			changingUrl = true;
+			setTimeout(function() { 
+					setHash(hash); 
+					changingUrl = false; 					
+				}, 1);
+			bookmarkAnchor.href = hash;
+			
+			if(dojo.isIE){
+				url = loadIframeHistory();
+
+				var oldCB = args["back"]||args["backButton"]||args["handle"];
+
+				//The function takes handleName as a parameter, in case the
+				//callback we are overriding was "handle". In that case,
+				//we will need to pass the handle name to handle.
+				var tcb = function(handleName){
+					if(getHash() != ""){
+						setTimeout(function() { setHash(hash); }, 1);
+					}
+					//Use apply to set "this" to args, and to try to avoid memory leaks.
+					oldCB.apply(this, [handleName]);
+				};
+		
+				//Set interceptor function in the right place.
+				if(args["back"]){
+					args.back = tcb;
+				}else if(args["backButton"]){
+					args.backButton = tcb;
+				}else if(args["handle"]){
+					args.handle = tcb;
+				}
+		
+				var oldFW = args["forward"]||args["forwardButton"]||args["handle"];
+		
+				//The function takes handleName as a parameter, in case the
+				//callback we are overriding was "handle". In that case,
+				//we will need to pass the handle name to handle.
+				var tfw = function(handleName){
+					if(getHash() != ""){
+						setHash(hash);
+					}
+					if(oldFW){ // we might not actually have one
+						//Use apply to set "this" to args, and to try to avoid memory leaks.
+						oldFW.apply(this, [handleName]);
+					}
+				};
+
+				//Set interceptor function in the right place.
+				if(args["forward"]){
+					args.forward = tfw;
+				}else if(args["forwardButton"]){
+					args.forwardButton = tfw;
+				}else if(args["handle"]){
+					args.handle = tfw;
+				}
+
+			}else if(!dojo.isIE){
+				// start the timer
+				if(!locationTimer){
+					locationTimer = setInterval(checkLocation, 200);
+				}
+				
+			}
+		}else{
+			url = loadIframeHistory();
+		}
+
+		historyStack.push(createState(url, args, hash));
+	};
+
+	back._iframeLoaded = function(evt, ifrLoc){
+		//summary: 
+		//		private method. Do not call this directly.
+		var query = getUrlQuery(ifrLoc.href);
+		if(query == null){ 
+			// alert("iframeLoaded");
+			// we hit the end of the history, so we should go back
+			if(historyStack.length == 1){
+				handleBackButton();
+			}
+			return;
+		}
+		if(moveForward){
+			// we were expecting it, so it's not either a forward or backward movement
+			moveForward = false;
+			return;
+		}
+	
+		//Check the back stack first, since it is more likely.
+		//Note that only one step back or forward is supported.
+		if(historyStack.length >= 2 && query == getUrlQuery(historyStack[historyStack.length-2].url)){
+			handleBackButton();
+		}else if(forwardStack.length > 0 && query == getUrlQuery(forwardStack[forwardStack.length-1].url)){
+			handleForwardButton();
+		}
+	};
+ })();
diff --git a/dojo/behavior.js b/dojo/behavior.js
index 875b223..34c5e54 100644
--- a/dojo/behavior.js
+++ b/dojo/behavior.js
@@ -1,94 +1,239 @@
-/*
-	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
-*/
+dojo.provide("dojo.behavior");
 
+dojo.behavior = new function(){
+	// summary: 
+	//		Utility for unobtrusive/progressive event binding, DOM traversal,
+	//		and manipulation.
+	//
+	// description:
+	//		
+	//		A very simple, lightweight mechanism for applying code to 
+	//		existing documents, based around `dojo.query` (CSS3 selectors) for node selection, 
+	//		and a simple two-command API: `dojo.behavior.add()` and `dojo.behavior.apply()`;
+	//	
+	//		Behaviors apply to a given page, and are registered following the syntax 
+	//		options described by `dojo.behavior.add` to match nodes to actions, or "behaviors".
+	//		
+	//		Added behaviors are applied to the current DOM when .apply() is called,
+	//		matching only new nodes found since .apply() was last called. 
+	//		
+	function arrIn(obj, name){
+		if(!obj[name]){ obj[name] = []; }
+		return obj[name];
+	}
 
-if(!dojo._hasResource["dojo.behavior"]){
-dojo._hasResource["dojo.behavior"]=true;
-dojo.provide("dojo.behavior");
-dojo.behavior=new function(){
-function _1(_2,_3){
-if(!_2[_3]){
-_2[_3]=[];
-}
-return _2[_3];
-};
-var _4=0;
-function _5(_6,_7,_8){
-var _9={};
-for(var x in _6){
-if(typeof _9[x]=="undefined"){
-if(!_8){
-_7(_6[x],x);
-}else{
-_8.call(_7,_6[x],x);
-}
-}
-}
-};
-this._behaviors={};
-this.add=function(_a){
-var _b={};
-_5(_a,this,function(_c,_d){
-var _e=_1(this._behaviors,_d);
-if(typeof _e["id"]!="number"){
-_e.id=_4++;
-}
-var _f=[];
-_e.push(_f);
-if((dojo.isString(_c))||(dojo.isFunction(_c))){
-_c={found:_c};
-}
-_5(_c,function(_10,_11){
-_1(_f,_11).push(_10);
-});
-});
-};
-var _12=function(_13,_14,_15){
-if(dojo.isString(_14)){
-if(_15=="found"){
-dojo.publish(_14,[_13]);
-}else{
-dojo.connect(_13,_15,function(){
-dojo.publish(_14,arguments);
-});
-}
-}else{
-if(dojo.isFunction(_14)){
-if(_15=="found"){
-_14(_13);
-}else{
-dojo.connect(_13,_15,_14);
-}
-}
-}
-};
-this.apply=function(){
-_5(this._behaviors,function(_16,id){
-dojo.query(id).forEach(function(_17){
-var _18=0;
-var bid="_dj_behavior_"+_16.id;
-if(typeof _17[bid]=="number"){
-_18=_17[bid];
-if(_18==(_16.length)){
-return;
-}
-}
-for(var x=_18,_19;_19=_16[x];x++){
-_5(_19,function(_1a,_1b){
-if(dojo.isArray(_1a)){
-dojo.forEach(_1a,function(_1c){
-_12(_17,_1c,_1b);
-});
-}
-});
-}
-_17[bid]=_16.length;
-});
-});
-};
-};
-dojo.addOnLoad(dojo.behavior,"apply");
+	var _inc = 0;
+
+	function forIn(obj, scope, func){
+		var tmpObj = {};
+		for(var x in obj){
+			if(typeof tmpObj[x] == "undefined"){
+				if(!func){
+					scope(obj[x], x);
+				}else{
+					func.call(scope, obj[x], x);
+				}
+			}
+		}
+	}
+
+	// FIXME: need a better test so we don't exclude nightly Safari's!
+	this._behaviors = {};
+	this.add = function(/* Object */behaviorObj){
+		//	summary:
+		//		Add the specified behavior to the list of behaviors, ignoring existing
+		//		matches. 
+		//
+		//	description:
+		//		Add the specified behavior to the list of behaviors which will
+		//		be applied the next time apply() is called. Calls to add() for
+		//		an already existing behavior do not replace the previous rules,
+		//		but are instead additive. New nodes which match the rule will
+		//		have all add()-ed behaviors applied to them when matched.
+		//		
+		//		The "found" method is a generalized handler that's called as soon
+		//		as the node matches the selector. Rules for values that follow also
+		//		apply to the "found" key.
+		//		
+		//		The "on*" handlers are attached with `dojo.connect()`, using the 
+		//		matching node
+		//		
+		//		If the value corresponding to the ID key is a function and not a
+		//		list, it's treated as though it was the value of "found".
+		//
+		// 		dojo.behavior.add() can be called any number of times before 
+		//		the DOM is ready. `dojo.behavior.apply()` is called automatically
+		//		by `dojo.addOnLoad`, though can be called to re-apply previously added
+		//		behaviors anytime the DOM changes.
+		//
+		//		There are a variety of formats permitted in the behaviorObject
+		//	
+		//	example:
+		//		Simple list of properties. "found" is special. "Found" is assumed if 
+		//		no property object for a given selector, and property is a function.
+		//
+		//	|	dojo.behavior.add({
+		//	|		"#id": {
+		//	|			"found": function(element){
+		//	|				// node match found
+		//	|			},
+		//	|			"onclick": function(evt){
+		//	|				// register onclick handler for found node
+		//	|			}
+		//	|		},
+		// 	|		"#otherid": function(element){
+		//	|			// assumes "found" with this syntax
+		//	|		}
+		//	|	});
+		//
+		//	example: 
+		//		 If property is a string, a dojo.publish will be issued on the channel:
+		//
+		//	|	dojo.behavior.add({
+		//	|		// dojo.publish() whenever class="noclick" found on anchors
+		//	|		"a.noclick": "/got/newAnchor",
+		//	|		"div.wrapper": {
+		//	|			"onclick": "/node/wasClicked"
+		//	|		}
+		//	|	});
+		//	|	dojo.subscribe("/got/newAnchor", function(node){
+		//	|		// handle node finding when dojo.behavior.apply() is called, 
+		//	|		// provided a newly matched node is found.
+		//	|	});
+		//
+		//	example:
+		//		Scoping can be accomplished by passing an object as a property to 
+		//		a connection handle (on*):
+		//	
+		//	|	dojo.behavior.add({ 
+		//	|		 	"#id": {
+		//	|				// like calling dojo.hitch(foo,"bar"). execute foo.bar() in scope of foo
+		//	|				"onmouseenter": { targetObj: foo, targetFunc: "bar" },
+		//	|				"onmouseleave": { targetObj: foo, targetFunc: "baz" }
+		//	|			}
+		//	|	});
+		//
+		//	example: 
+		//		Bahaviors match on CSS3 Selectors, powered by dojo.query. Example selectors:
+		//
+		//	|	dojo.behavior.add({
+		//	|		// match all direct descendants
+		//	|		"#id4 > *": function(element){
+		//	|			// ...
+		//	|		},
+		//	|		
+		//	|		// match the first child node that's an element
+		//	|		"#id4 > :first-child": { ... },
+		//	|		
+		//	|		// match the last child node that's an element
+		//	|		"#id4 > :last-child":  { ... },
+		//	|		
+		//	|		// all elements of type tagname
+		//	|		"tagname": {
+		//	|			// ...
+		//	|		},
+		//	|		
+		//	|		"tagname1 tagname2 tagname3": {
+		//	|			// ...
+		//	|		},
+		//	|		
+		//	|		".classname": {
+		//	|			// ...
+		//	|		},
+		//	|		
+		//	|		"tagname.classname": {
+		//	|			// ...
+		//	|		}
+		//	|	});
+		//   
+
+		var tmpObj = {};
+		forIn(behaviorObj, this, function(behavior, name){
+			var tBehavior = arrIn(this._behaviors, name);
+			if(typeof tBehavior["id"] != "number"){
+				tBehavior.id = _inc++;
+			}
+			var cversion = [];
+			tBehavior.push(cversion);
+			if((dojo.isString(behavior))||(dojo.isFunction(behavior))){
+				behavior = { found: behavior };
+			}
+			forIn(behavior, function(rule, ruleName){
+				arrIn(cversion, ruleName).push(rule);
+			});
+		});
+	}
+
+	var _applyToNode = function(node, action, ruleSetName){
+		if(dojo.isString(action)){
+			if(ruleSetName == "found"){
+				dojo.publish(action, [ node ]);
+			}else{
+				dojo.connect(node, ruleSetName, function(){
+					dojo.publish(action, arguments);
+				});
+			}
+		}else if(dojo.isFunction(action)){
+			if(ruleSetName == "found"){
+				action(node);
+			}else{
+				dojo.connect(node, ruleSetName, action);
+			}
+		}
+	}
+
+	this.apply = function(){
+		// summary:
+		//		Applies all currently registered behaviors to the document.
+		// 
+		// description:
+		//		Applies all currently registered behaviors to the document,
+		//		taking care to ensure that only incremental updates are made
+		//		since the last time add() or apply() were called. 
+		//	
+		//		If new matching nodes have been added, all rules in a behavior will be
+		//		applied to that node. For previously matched nodes, only
+		//		behaviors which have been added since the last call to apply()
+		//		will be added to the nodes.
+		//
+		//		apply() is called once automatically by `dojo.addOnLoad`, so 
+		//		registering behaviors with `dojo.behavior.add` before the DOM is
+		//		ready is acceptable, provided the dojo.behavior module is ready.
+		//		
+		//		Calling appy() manually after manipulating the DOM is required 
+		//		to rescan the DOM and apply newly .add()ed behaviors, or to match
+		//		nodes that match existing behaviors when those nodes are added to 
+		//		the DOM.
+		//		
+		forIn(this._behaviors, function(tBehavior, id){
+			dojo.query(id).forEach( 
+				function(elem){
+					var runFrom = 0;
+					var bid = "_dj_behavior_"+tBehavior.id;
+					if(typeof elem[bid] == "number"){
+						runFrom = elem[bid];
+						if(runFrom == (tBehavior.length)){
+							return;
+						}
+					}
+					// run through the versions, applying newer rules at each step
+
+					for(var x=runFrom, tver; tver = tBehavior[x]; x++){
+						forIn(tver, function(ruleSet, ruleSetName){
+							if(dojo.isArray(ruleSet)){
+								dojo.forEach(ruleSet, function(action){
+									_applyToNode(elem, action, ruleSetName);
+								});
+							}
+						});
+					}
+
+					// ensure that re-application only adds new rules to the node
+					elem[bid] = tBehavior.length;
+				}
+			);
+		});
+	}
 }
+
+dojo.addOnLoad(dojo.behavior, "apply");
diff --git a/dojo/build.txt b/dojo/build.txt
deleted file mode 100644
index 58f6bb9..0000000
--- a/dojo/build.txt
+++ /dev/null
@@ -1,308 +0,0 @@
-Files baked into this build:
-
-dojo.js:
-./jslib/dojoGuardStart.jsfrag
-./../../dojo/_base/_loader/bootstrap.js
-./../../dojo/_base/_loader/loader.js
-./../../dojo/_base/_loader/hostenv_browser.js
-./../../release/dojo-release-1.4.3/dojo/_base/lang.js
-./../../release/dojo-release-1.4.3/dojo/_base/array.js
-./../../release/dojo-release-1.4.3/dojo/_base/declare.js
-./../../release/dojo-release-1.4.3/dojo/_base/connect.js
-./../../release/dojo-release-1.4.3/dojo/_base/Deferred.js
-./../../release/dojo-release-1.4.3/dojo/_base/json.js
-./../../release/dojo-release-1.4.3/dojo/_base/Color.js
-./../../release/dojo-release-1.4.3/dojo/_base.js
-./../../release/dojo-release-1.4.3/dojo/_base/window.js
-./../../release/dojo-release-1.4.3/dojo/_base/event.js
-./../../release/dojo-release-1.4.3/dojo/_base/html.js
-./../../release/dojo-release-1.4.3/dojo/_base/NodeList.js
-./../../release/dojo-release-1.4.3/dojo/_base/query.js
-./../../release/dojo-release-1.4.3/dojo/_base/xhr.js
-./../../release/dojo-release-1.4.3/dojo/_base/fx.js
-./../../release/dojo-release-1.4.3/dojo/_base/browser.js
-./jslib/dojoGuardEnd.jsfrag
-
-../dijit/dijit.js:
-./../../release/dojo-release-1.4.3/dijit/_base/manager.js
-./../../release/dojo-release-1.4.3/dijit/_base/focus.js
-./../../release/dojo-release-1.4.3/dojo/AdapterRegistry.js
-./../../release/dojo-release-1.4.3/dijit/_base/place.js
-./../../release/dojo-release-1.4.3/dijit/_base/window.js
-./../../release/dojo-release-1.4.3/dijit/_base/popup.js
-./../../release/dojo-release-1.4.3/dijit/_base/scroll.js
-./../../release/dojo-release-1.4.3/dijit/_base/sniff.js
-./../../release/dojo-release-1.4.3/dijit/_base/typematic.js
-./../../release/dojo-release-1.4.3/dijit/_base/wai.js
-./../../release/dojo-release-1.4.3/dijit/_base.js
-./../../release/dojo-release-1.4.3/dojo/date/stamp.js
-./../../release/dojo-release-1.4.3/dojo/parser.js
-./../../release/dojo-release-1.4.3/dijit/_Widget.js
-./../../release/dojo-release-1.4.3/dojo/string.js
-./../../release/dojo-release-1.4.3/dojo/cache.js
-./../../release/dojo-release-1.4.3/dijit/_Templated.js
-./../../release/dojo-release-1.4.3/dijit/_Container.js
-./../../release/dojo-release-1.4.3/dijit/_Contained.js
-./../../release/dojo-release-1.4.3/dijit/layout/_LayoutWidget.js
-./../../release/dojo-release-1.4.3/dijit/form/_FormWidget.js
-./../../release/dojo-release-1.4.3/dijit/dijit.js
-
-../dijit/dijit-all.js:
-./../../release/dojo-release-1.4.3/dojo/colors.js
-./../../release/dojo-release-1.4.3/dojo/i18n.js
-./../../release/dojo-release-1.4.3/dijit/ColorPalette.js
-./../../release/dojo-release-1.4.3/dijit/Declaration.js
-./../../release/dojo-release-1.4.3/dojo/dnd/common.js
-./../../release/dojo-release-1.4.3/dojo/dnd/autoscroll.js
-./../../release/dojo-release-1.4.3/dojo/dnd/Mover.js
-./../../release/dojo-release-1.4.3/dojo/dnd/Moveable.js
-./../../release/dojo-release-1.4.3/dojo/dnd/move.js
-./../../release/dojo-release-1.4.3/dojo/dnd/TimedMoveable.js
-./../../release/dojo-release-1.4.3/dojo/fx/Toggler.js
-./../../release/dojo-release-1.4.3/dojo/fx.js
-./../../release/dojo-release-1.4.3/dijit/form/_FormMixin.js
-./../../release/dojo-release-1.4.3/dijit/_DialogMixin.js
-./../../release/dojo-release-1.4.3/dijit/DialogUnderlay.js
-./../../release/dojo-release-1.4.3/dojo/html.js
-./../../release/dojo-release-1.4.3/dijit/layout/ContentPane.js
-./../../release/dojo-release-1.4.3/dijit/TooltipDialog.js
-./../../release/dojo-release-1.4.3/dijit/Dialog.js
-./../../release/dojo-release-1.4.3/dijit/_editor/selection.js
-./../../release/dojo-release-1.4.3/dijit/_editor/range.js
-./../../release/dojo-release-1.4.3/dijit/_editor/html.js
-./../../release/dojo-release-1.4.3/dijit/_editor/RichText.js
-./../../release/dojo-release-1.4.3/dijit/_KeyNavContainer.js
-./../../release/dojo-release-1.4.3/dijit/ToolbarSeparator.js
-./../../release/dojo-release-1.4.3/dijit/Toolbar.js
-./../../release/dojo-release-1.4.3/dijit/_HasDropDown.js
-./../../release/dojo-release-1.4.3/dijit/form/Button.js
-./../../release/dojo-release-1.4.3/dijit/_editor/_Plugin.js
-./../../release/dojo-release-1.4.3/dijit/_editor/plugins/EnterKeyHandling.js
-./../../release/dojo-release-1.4.3/dijit/Editor.js
-./../../release/dojo-release-1.4.3/dijit/MenuItem.js
-./../../release/dojo-release-1.4.3/dijit/PopupMenuItem.js
-./../../release/dojo-release-1.4.3/dijit/CheckedMenuItem.js
-./../../release/dojo-release-1.4.3/dijit/MenuSeparator.js
-./../../release/dojo-release-1.4.3/dijit/Menu.js
-./../../release/dojo-release-1.4.3/dijit/MenuBar.js
-./../../release/dojo-release-1.4.3/dijit/MenuBarItem.js
-./../../release/dojo-release-1.4.3/dijit/PopupMenuBarItem.js
-./../../release/dojo-release-1.4.3/dojo/regexp.js
-./../../release/dojo-release-1.4.3/dojo/number.js
-./../../release/dojo-release-1.4.3/dijit/ProgressBar.js
-./../../release/dojo-release-1.4.3/dijit/TitlePane.js
-./../../release/dojo-release-1.4.3/dijit/Tooltip.js
-./../../release/dojo-release-1.4.3/dojo/DeferredList.js
-./../../release/dojo-release-1.4.3/dojo/cookie.js
-./../../release/dojo-release-1.4.3/dijit/tree/TreeStoreModel.js
-./../../release/dojo-release-1.4.3/dijit/tree/ForestStoreModel.js
-./../../release/dojo-release-1.4.3/dijit/Tree.js
-./../../release/dojo-release-1.4.3/dijit/form/TextBox.js
-./../../release/dojo-release-1.4.3/dijit/InlineEditBox.js
-./../../release/dojo-release-1.4.3/dijit/form/Form.js
-./../../release/dojo-release-1.4.3/dijit/form/DropDownButton.js
-./../../release/dojo-release-1.4.3/dijit/form/ComboButton.js
-./../../release/dojo-release-1.4.3/dijit/form/ToggleButton.js
-./../../release/dojo-release-1.4.3/dijit/form/CheckBox.js
-./../../release/dojo-release-1.4.3/dijit/form/RadioButton.js
-./../../release/dojo-release-1.4.3/dijit/form/ValidationTextBox.js
-./../../release/dojo-release-1.4.3/dojo/cldr/monetary.js
-./../../release/dojo-release-1.4.3/dojo/currency.js
-./../../release/dojo-release-1.4.3/dijit/form/NumberTextBox.js
-./../../release/dojo-release-1.4.3/dijit/form/CurrencyTextBox.js
-./../../release/dojo-release-1.4.3/dojo/cldr/supplemental.js
-./../../release/dojo-release-1.4.3/dojo/date.js
-./../../release/dojo-release-1.4.3/dojo/date/locale.js
-./../../release/dojo-release-1.4.3/dijit/Calendar.js
-./../../release/dojo-release-1.4.3/dijit/form/_DateTimeTextBox.js
-./../../release/dojo-release-1.4.3/dijit/form/DateTextBox.js
-./../../release/dojo-release-1.4.3/dijit/form/_Spinner.js
-./../../release/dojo-release-1.4.3/dijit/form/NumberSpinner.js
-./../../release/dojo-release-1.4.3/dojo/data/util/sorter.js
-./../../release/dojo-release-1.4.3/dojo/data/util/simpleFetch.js
-./../../release/dojo-release-1.4.3/dojo/data/util/filter.js
-./../../release/dojo-release-1.4.3/dijit/form/ComboBox.js
-./../../release/dojo-release-1.4.3/dijit/form/FilteringSelect.js
-./../../release/dojo-release-1.4.3/dijit/form/MultiSelect.js
-./../../release/dojo-release-1.4.3/dijit/form/HorizontalSlider.js
-./../../release/dojo-release-1.4.3/dijit/form/VerticalSlider.js
-./../../release/dojo-release-1.4.3/dijit/form/HorizontalRule.js
-./../../release/dojo-release-1.4.3/dijit/form/VerticalRule.js
-./../../release/dojo-release-1.4.3/dijit/form/HorizontalRuleLabels.js
-./../../release/dojo-release-1.4.3/dijit/form/VerticalRuleLabels.js
-./../../release/dojo-release-1.4.3/dijit/form/SimpleTextarea.js
-./../../release/dojo-release-1.4.3/dijit/form/Textarea.js
-./../../release/dojo-release-1.4.3/dijit/layout/StackController.js
-./../../release/dojo-release-1.4.3/dijit/layout/StackContainer.js
-./../../release/dojo-release-1.4.3/dijit/layout/AccordionPane.js
-./../../release/dojo-release-1.4.3/dijit/layout/AccordionContainer.js
-./../../release/dojo-release-1.4.3/dijit/layout/BorderContainer.js
-./../../release/dojo-release-1.4.3/dijit/layout/LayoutContainer.js
-./../../release/dojo-release-1.4.3/dijit/layout/LinkPane.js
-./../../release/dojo-release-1.4.3/dijit/layout/SplitContainer.js
-./../../release/dojo-release-1.4.3/dijit/layout/_TabContainerBase.js
-./../../release/dojo-release-1.4.3/dijit/layout/TabController.js
-./../../release/dojo-release-1.4.3/dijit/layout/ScrollingTabController.js
-./../../release/dojo-release-1.4.3/dijit/layout/TabContainer.js
-./../../release/dojo-release-1.4.3/dijit/dijit-all.js
-
-../dojox/grid/DataGrid.js:
-./../../release/dojo-release-1.4.3/dijit/_base/manager.js
-./../../release/dojo-release-1.4.3/dijit/_base/focus.js
-./../../release/dojo-release-1.4.3/dojo/AdapterRegistry.js
-./../../release/dojo-release-1.4.3/dijit/_base/place.js
-./../../release/dojo-release-1.4.3/dijit/_base/window.js
-./../../release/dojo-release-1.4.3/dijit/_base/popup.js
-./../../release/dojo-release-1.4.3/dijit/_base/scroll.js
-./../../release/dojo-release-1.4.3/dijit/_base/sniff.js
-./../../release/dojo-release-1.4.3/dijit/_base/typematic.js
-./../../release/dojo-release-1.4.3/dijit/_base/wai.js
-./../../release/dojo-release-1.4.3/dijit/_base.js
-./../../release/dojo-release-1.4.3/dojo/date/stamp.js
-./../../release/dojo-release-1.4.3/dojo/parser.js
-./../../release/dojo-release-1.4.3/dijit/_Widget.js
-./../../release/dojo-release-1.4.3/dojo/string.js
-./../../release/dojo-release-1.4.3/dojo/cache.js
-./../../release/dojo-release-1.4.3/dijit/_Templated.js
-./../../release/dojo-release-1.4.3/dijit/_Container.js
-./../../release/dojo-release-1.4.3/dijit/_Contained.js
-./../../release/dojo-release-1.4.3/dijit/layout/_LayoutWidget.js
-./../../release/dojo-release-1.4.3/dijit/form/_FormWidget.js
-./../../release/dojo-release-1.4.3/dijit/dijit.js
-./../../release/dojo-release-1.4.3/dijit/_KeyNavContainer.js
-./../../release/dojo-release-1.4.3/dijit/MenuItem.js
-./../../release/dojo-release-1.4.3/dijit/PopupMenuItem.js
-./../../release/dojo-release-1.4.3/dijit/CheckedMenuItem.js
-./../../release/dojo-release-1.4.3/dijit/MenuSeparator.js
-./../../release/dojo-release-1.4.3/dijit/Menu.js
-./../../release/dojo-release-1.4.3/dojox/html/metrics.js
-./../../release/dojo-release-1.4.3/dojox/grid/util.js
-./../../release/dojo-release-1.4.3/dojox/grid/_Scroller.js
-./../../release/dojo-release-1.4.3/dojox/grid/cells/_base.js
-./../../release/dojo-release-1.4.3/dojox/grid/cells.js
-./../../release/dojo-release-1.4.3/dojo/dnd/common.js
-./../../release/dojo-release-1.4.3/dojo/dnd/autoscroll.js
-./../../release/dojo-release-1.4.3/dojo/dnd/Mover.js
-./../../release/dojo-release-1.4.3/dojo/dnd/Moveable.js
-./../../release/dojo-release-1.4.3/dojox/grid/_Builder.js
-./../../release/dojo-release-1.4.3/dojo/dnd/Container.js
-./../../release/dojo-release-1.4.3/dojo/dnd/Selector.js
-./../../release/dojo-release-1.4.3/dojo/dnd/Avatar.js
-./../../release/dojo-release-1.4.3/dojo/dnd/Manager.js
-./../../release/dojo-release-1.4.3/dojo/dnd/Source.js
-./../../release/dojo-release-1.4.3/dojox/grid/_View.js
-./../../release/dojo-release-1.4.3/dojox/grid/_RowSelector.js
-./../../release/dojo-release-1.4.3/dojox/grid/_Layout.js
-./../../release/dojo-release-1.4.3/dojox/grid/_ViewManager.js
-./../../release/dojo-release-1.4.3/dojox/grid/_RowManager.js
-./../../release/dojo-release-1.4.3/dojox/grid/_FocusManager.js
-./../../release/dojo-release-1.4.3/dojox/grid/_EditManager.js
-./../../release/dojo-release-1.4.3/dojox/grid/Selection.js
-./../../release/dojo-release-1.4.3/dojox/grid/_Events.js
-./../../release/dojo-release-1.4.3/dojo/i18n.js
-./../../release/dojo-release-1.4.3/dojox/grid/_Grid.js
-./../../release/dojo-release-1.4.3/dojox/grid/DataSelection.js
-./../../release/dojo-release-1.4.3/dojox/grid/DataGrid.js
-
-../dojox/gfx.js:
-./../../release/dojo-release-1.4.3/dojox/gfx/matrix.js
-./../../release/dojo-release-1.4.3/dojox/gfx/_base.js
-./../../release/dojo-release-1.4.3/dojox/gfx.js
-
-../dojox/charting/widget/Chart2D.js:
-./../../release/dojo-release-1.4.3/dijit/_base/manager.js
-./../../release/dojo-release-1.4.3/dijit/_base/focus.js
-./../../release/dojo-release-1.4.3/dojo/AdapterRegistry.js
-./../../release/dojo-release-1.4.3/dijit/_base/place.js
-./../../release/dojo-release-1.4.3/dijit/_base/window.js
-./../../release/dojo-release-1.4.3/dijit/_base/popup.js
-./../../release/dojo-release-1.4.3/dijit/_base/scroll.js
-./../../release/dojo-release-1.4.3/dijit/_base/sniff.js
-./../../release/dojo-release-1.4.3/dijit/_base/typematic.js
-./../../release/dojo-release-1.4.3/dijit/_base/wai.js
-./../../release/dojo-release-1.4.3/dijit/_base.js
-./../../release/dojo-release-1.4.3/dijit/_Widget.js
-./../../release/dojo-release-1.4.3/dojox/gfx/matrix.js
-./../../release/dojo-release-1.4.3/dojox/gfx/_base.js
-./../../release/dojo-release-1.4.3/dojox/gfx.js
-./../../release/dojo-release-1.4.3/dojox/lang/functional/lambda.js
-./../../release/dojo-release-1.4.3/dojox/lang/functional/array.js
-./../../release/dojo-release-1.4.3/dojox/lang/functional/object.js
-./../../release/dojo-release-1.4.3/dojox/lang/functional.js
-./../../release/dojo-release-1.4.3/dojox/lang/functional/fold.js
-./../../release/dojo-release-1.4.3/dojox/lang/functional/reversed.js
-./../../release/dojo-release-1.4.3/dojo/colors.js
-./../../release/dojo-release-1.4.3/dojox/color/_base.js
-./../../release/dojo-release-1.4.3/dojox/color.js
-./../../release/dojo-release-1.4.3/dojox/color/Palette.js
-./../../release/dojo-release-1.4.3/dojox/charting/Theme.js
-./../../release/dojo-release-1.4.3/dojox/charting/Element.js
-./../../release/dojo-release-1.4.3/dojox/charting/Series.js
-./../../release/dojo-release-1.4.3/dojox/charting/scaler/common.js
-./../../release/dojo-release-1.4.3/dojox/charting/scaler/linear.js
-./../../release/dojo-release-1.4.3/dojox/charting/axis2d/common.js
-./../../release/dojo-release-1.4.3/dojox/charting/axis2d/Base.js
-./../../release/dojo-release-1.4.3/dojo/string.js
-./../../release/dojo-release-1.4.3/dojox/lang/utils.js
-./../../release/dojo-release-1.4.3/dojox/charting/axis2d/Default.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/common.js
-./../../release/dojo-release-1.4.3/dojox/charting/scaler/primitive.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Base.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Default.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Lines.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Areas.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Markers.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/MarkersOnly.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Scatter.js
-./../../release/dojo-release-1.4.3/dojox/lang/functional/sequence.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Stacked.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/StackedLines.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/StackedAreas.js
-./../../release/dojo-release-1.4.3/dojox/gfx/fx.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Columns.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/StackedColumns.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/ClusteredColumns.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Bars.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/StackedBars.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/ClusteredBars.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Grid.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Pie.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Bubble.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/Candlesticks.js
-./../../release/dojo-release-1.4.3/dojox/charting/plot2d/OHLC.js
-./../../release/dojo-release-1.4.3/dojox/charting/Chart2D.js
-./../../release/dojo-release-1.4.3/dojo/fx/easing.js
-./../../release/dojo-release-1.4.3/dojox/charting/action2d/Base.js
-./../../release/dojo-release-1.4.3/dojox/charting/action2d/Highlight.js
-./../../release/dojo-release-1.4.3/dojo/fx/Toggler.js
-./../../release/dojo-release-1.4.3/dojo/fx.js
-./../../release/dojo-release-1.4.3/dojox/charting/action2d/Magnify.js
-./../../release/dojo-release-1.4.3/dojox/lang/functional/scan.js
-./../../release/dojo-release-1.4.3/dojox/charting/action2d/MoveSlice.js
-./../../release/dojo-release-1.4.3/dojox/charting/action2d/Shake.js
-./../../release/dojo-release-1.4.3/dojo/date/stamp.js
-./../../release/dojo-release-1.4.3/dojo/parser.js
-./../../release/dojo-release-1.4.3/dojo/cache.js
-./../../release/dojo-release-1.4.3/dijit/_Templated.js
-./../../release/dojo-release-1.4.3/dijit/Tooltip.js
-./../../release/dojo-release-1.4.3/dojox/charting/action2d/Tooltip.js
-./../../release/dojo-release-1.4.3/dojox/charting/widget/Chart2D.js
-./../../release/dojo-release-1.4.3/dojox/charting/themes/ET/greys.js
-./../../release/dojo-release-1.4.3/dojox/charting/widget/Sparkline.js
-./../../release/dojo-release-1.4.3/dojox/charting/widget/Legend.js
-
-../dojox/dtl.js:
-./../../release/dojo-release-1.4.3/dojox/string/Builder.js
-./../../release/dojo-release-1.4.3/dojox/string/tokenize.js
-./../../release/dojo-release-1.4.3/dojox/dtl/_base.js
-./../../release/dojo-release-1.4.3/dojox/dtl.js
-./../../release/dojo-release-1.4.3/dojox/dtl/Context.js
-./../../release/dojo-release-1.4.3/dojox/dtl/tag/logic.js
-./../../release/dojo-release-1.4.3/dojox/dtl/tag/loop.js
-./../../release/dojo-release-1.4.3/dojo/date.js
-./../../release/dojo-release-1.4.3/dojox/date/php.js
-./../../release/dojo-release-1.4.3/dojox/dtl/utils/date.js
-./../../release/dojo-release-1.4.3/dojox/dtl/tag/date.js
-./../../release/dojo-release-1.4.3/dojox/dtl/tag/loader.js
-./../../release/dojo-release-1.4.3/dojox/dtl/tag/misc.js
-./../../release/dojo-release-1.4.3/dojox/dtl/ext-dojo/NodeList.js
diff --git a/dojo/cache.js b/dojo/cache.js
index 87c8f96..94dd2b5 100644
--- a/dojo/cache.js
+++ b/dojo/cache.js
@@ -1,54 +1,116 @@
-/*
-	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
-*/
+dojo.provide("dojo.cache");
 
+/*=====
+dojo.cache = { 
+	// summary:
+	// 		A way to cache string content that is fetchable via `dojo.moduleUrl`.
+};
+=====*/
 
-if(!dojo._hasResource["dojo.cache"]){
-dojo._hasResource["dojo.cache"]=true;
-dojo.provide("dojo.cache");
 (function(){
-var _1={};
-dojo.cache=function(_2,_3,_4){
-if(typeof _2=="string"){
-var _5=dojo.moduleUrl(_2,_3);
-}else{
-_5=_2;
-_4=_3;
-}
-var _6=_5.toString();
-var _7=_4;
-if(_4!==undefined&&!dojo.isString(_4)){
-_7=("value" in _4?_4.value:undefined);
-}
-var _8=_4&&_4.sanitize?true:false;
-if(_7||_7===null){
-if(_7==null){
-delete _1[_6];
-}else{
-_7=_1[_6]=_8?dojo.cache._sanitize(_7):_7;
-}
-}else{
-if(!(_6 in _1)){
-_7=dojo._getText(_6);
-_1[_6]=_8?dojo.cache._sanitize(_7):_7;
-}
-_7=_1[_6];
-}
-return _7;
-};
-dojo.cache._sanitize=function(_9){
-if(_9){
-_9=_9.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,"");
-var _a=_9.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
-if(_a){
-_9=_a[1];
-}
-}else{
-_9="";
-}
-return _9;
-};
+	var cache = {};
+	dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
+		// summary:
+		// 		A getter and setter for storing the string content associated with the
+		// 		module and url arguments.
+		// description:
+		// 		module and url are used to call `dojo.moduleUrl()` to generate a module URL.
+		// 		If value is specified, the cache value for the moduleUrl will be set to
+		// 		that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
+		// 		in its internal cache and return that cached value for the URL. To clear
+		// 		a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
+		// 		the URL contents, only modules on the same domain of the page can use this capability.
+		// 		The build system can inline the cache values though, to allow for xdomain hosting.
+		// module: String||Object
+		// 		If a String, the module name to use for the base part of the URL, similar to module argument
+		// 		to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
+		// 		generates a valid path for the cache item. For example, a dojo._Url object.
+		// url: String
+		// 		The rest of the path to append to the path derived from the module argument. If
+		// 		module is an object, then this second argument should be the "value" argument instead.
+		// value: String||Object?
+		// 		If a String, the value to use in the cache for the module/url combination.
+		// 		If an Object, it can have two properties: value and sanitize. The value property
+		// 		should be the value to use in the cache, and sanitize can be set to true or false,
+		// 		to indicate if XML declarations should be removed from the value and if the HTML
+		// 		inside a body tag in the value should be extracted as the real value. The value argument
+		// 		or the value property on the value argument are usually only used by the build system
+		// 		as it inlines cache content.
+		//	example:
+		//		To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
+		// 		of call is used to avoid an issue with the build system erroneously trying to intern
+		// 		this example. To get the build system to intern your dojo.cache calls, use the
+		// 		"dojo.cache" style of call):
+		// 		|	//If template.html contains "<h1>Hello</h1>" that will be
+		// 		|	//the value for the text variable.
+		//		|	var text = dojo["cache"]("my.module", "template.html");
+		//	example:
+		//		To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
+		// 		 (the dojo["cache"] style of call is used to avoid an issue with the build system 
+		// 		erroneously trying to intern this example. To get the build system to intern your
+		// 		dojo.cache calls, use the "dojo.cache" style of call):
+		// 		|	//If template.html contains "<html><body><h1>Hello</h1></body></html>", the
+		// 		|	//text variable will contain just "<h1>Hello</h1>".
+		//		|	var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
+		//	example:
+		//		Same example as previous, but demostrates how an object can be passed in as
+		//		the first argument, then the value argument can then be the second argument.
+		// 		|	//If template.html contains "<html><body><h1>Hello</h1></body></html>", the
+		// 		|	//text variable will contain just "<h1>Hello</h1>".
+		//		|	var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
+
+		//Module could be a string, or an object that has a toString() method
+		//that will return a useful path. If it is an object, then the "url" argument
+		//will actually be the value argument.
+		if(typeof module == "string"){
+			var pathObj = dojo.moduleUrl(module, url);
+		}else{
+			pathObj = module;
+			value = url;
+		}
+		var key = pathObj.toString();
+
+		var val = value;
+		if(value != undefined && !dojo.isString(value)){
+			val = ("value" in value ? value.value : undefined);
+		}
+
+		var sanitize = value && value.sanitize ? true : false;
+
+		if(typeof val == "string"){
+			//We have a string, set cache value
+			val = cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
+		}else if(val === null){
+			//Remove cached value
+			delete cache[key];
+		}else{
+			//Allow cache values to be empty strings. If key property does
+			//not exist, fetch it.
+			if(!(key in cache)){
+				val = dojo._getText(key);
+				cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
+			}
+			val = cache[key];
+		}
+		return val; //String
+	};
+
+	dojo.cache._sanitize = function(/*String*/val){
+		// 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.
+		// description:
+		// 		Copied from dijit._Templated._sanitizeTemplateString.
+		if(val){
+			val = val.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
+			var matches = val.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
+			if(matches){
+				val = matches[1];
+			}
+		}else{
+			val = "";
+		}
+		return val; //String
+	};
 })();
-}
diff --git a/dojo/cldr/monetary.js b/dojo/cldr/monetary.js
index be83bb0..adc68de 100644
--- a/dojo/cldr/monetary.js
+++ b/dojo/cldr/monetary.js
@@ -1,23 +1,26 @@
-/*
-	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
-*/
+dojo.provide("dojo.cldr.monetary");
 
+dojo.cldr.monetary.getData = function(/*String*/code){
+// summary: A mapping of currency code to currency-specific formatting information. Returns a unique object with properties: places, round.
+// code: an [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code
 
-if(!dojo._hasResource["dojo.cldr.monetary"]){
-dojo._hasResource["dojo.cldr.monetary"]=true;
-dojo.provide("dojo.cldr.monetary");
-dojo.cldr.monetary.getData=function(_1){
-var _2={ADP:0,BHD:3,BIF:0,BYR:0,CLF:0,CLP:0,DJF:0,ESP:0,GNF:0,IQD:3,ITL:0,JOD:3,JPY:0,KMF:0,KRW:0,KWD:3,LUF:0,LYD:3,MGA:0,MGF:0,OMR:3,PYG:0,RWF:0,TND:3,TRL:0,VUV:0,XAF:0,XOF:0,XPF:0};
-var _3={CHF:5};
-var _4=_2[_1],_5=_3[_1];
-if(typeof _4=="undefined"){
-_4=2;
-}
-if(typeof _5=="undefined"){
-_5=0;
-}
-return {places:_4,round:_5};
+// from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/currencyData/fractions
+
+	var placesData = {
+		ADP:0,AFN:0,ALL:0,AMD:0,BHD:3,BIF:0,BYR:0,CLF:0,CLP:0,
+		COP:0,CRC:0,DJF:0,ESP:0,GNF:0,GYD:0,HUF:0,IDR:0,IQD:0,
+		IRR:3,ISK:0,ITL:0,JOD:3,JPY:0,KMF:0,KPW:0,KRW:0,KWD:3,
+		LAK:0,LBP:0,LUF:0,LYD:3,MGA:0,MGF:0,MMK:0,MNT:0,MRO:0,
+		MUR:0,OMR:3,PKR:0,PYG:0,RSD:0,RWF:0,SLL:0,SOS:0,STD:0,
+		SYP:0,TMM:0,TND:3,TRL:0,TZS:0,UGX:0,UZS:0,VND:0,VUV:0,
+		XAF:0,XOF:0,XPF:0,YER:0,ZMK:0,ZWD:0
+	};
+
+	var roundingData = {CHF:5};
+
+	var places = placesData[code], round = roundingData[code];
+	if(typeof places == "undefined"){ places = 2; }
+	if(typeof round == "undefined"){ round = 0; }
+
+	return {places: places, round: round}; // Object
 };
-}
diff --git a/dojo/cldr/nls/ar/currency.js b/dojo/cldr/nls/ar/currency.js
index 7f45459..7351b83 100644
--- a/dojo/cldr/nls/ar/currency.js
+++ b/dojo/cldr/nls/ar/currency.js
@@ -1 +1,14 @@
-({"HKD_displayName":"دولار هونج كونج","CHF_displayName":"فرنك سويسري","CAD_displayName":"دولار كندي","CNY_displayName":"يوان صيني","AUD_displayName":"دولار أسترالي","JPY_displayName":"ين ياباني","USD_displayName":"دولار أمريكي","CNY_symbol":"ي.ص","GBP_displayName":"جنيه إسترليني","EUR_displayName":"يورو","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"دولار أسترالي",
+	CAD_displayName:"دولار كندي",
+	CHF_displayName:"فرنك سويسري",
+	CNY_displayName:"يوان صيني",
+	CNY_symbol:"ي.ص",
+	EUR_displayName:"يورو",
+	GBP_displayName:"جنيه إسترليني",
+	HKD_displayName:"دولار هونج كونج",
+	JPY_displayName:"ين ياباني",
+	USD_displayName:"دولار أمريكي"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/ar/gregorian.js b/dojo/cldr/nls/ar/gregorian.js
index bf36a39..4ab460d 100644
--- a/dojo/cldr/nls/ar/gregorian.js
+++ b/dojo/cldr/nls/ar/gregorian.js
@@ -1 +1,235 @@
-({"dateFormatItem-yM":"M‏/yyyy","field-dayperiod":"ص/م","dateFormatItem-yQ":"yyyy Q","field-minute":"الدقائق","eraNames":["قبل الميلاد","ميلادي"],"dateFormatItem-MMMEd":"E d MMM","field-weekday":"اليوم","dateFormatItem-yQQQ":"y QQQ","dateFormatItem-MMdd":"dd‏/MM","days-standAlone-wide":["الأحد","الإثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["ي","ف","م","أ","و","ن","ل","غ","س","ك","ب","د"],"field-era":"العصر","field-hour": [...]
\ No newline at end of file
+({
+	"dateFormatItem-yM": "M‏/yyyy", 
+	"field-dayperiod": "ص/م", 
+	"dayPeriods-format-wide-pm": "م", 
+	"dateFormatItem-yQ": "yyyy Q", 
+	"field-minute": "الدقائق", 
+	"eraNames": [
+		"قبل الميلاد", 
+		"ميلادي"
+	], 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"field-day-relative+-1": "أمس", 
+	"dateFormatItem-MMdd": "dd‏/MM", 
+	"dateFormatItem-yQQQ": "y QQQ", 
+	"field-weekday": "اليوم", 
+	"days-standAlone-wide": [
+		"الأحد", 
+		"الإثنين", 
+		"الثلاثاء", 
+		"الأربعاء", 
+		"الخميس", 
+		"الجمعة", 
+		"السبت"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"months-standAlone-narrow": [
+		"ي", 
+		"ف", 
+		"م", 
+		"أ", 
+		"و", 
+		"ن", 
+		"ل", 
+		"غ", 
+		"س", 
+		"ك", 
+		"ب", 
+		"د"
+	], 
+	"dayPeriods-format-wide-am": "ص", 
+	"field-era": "العصر", 
+	"field-hour": "الساعات", 
+	"quarters-standAlone-abbr": [
+		"الربع الأول", 
+		"الربع الثاني", 
+		"الربع الثالث", 
+		"الربع الرابع"
+	], 
+	"dateFormatItem-y": "y", 
+	"timeFormat-full": "zzzz h:mm:ss a", 
+	"months-standAlone-abbr": [
+		"يناير", 
+		"فبراير", 
+		"مارس", 
+		"أبريل", 
+		"مايو", 
+		"يونيو", 
+		"يوليو", 
+		"أغسطس", 
+		"سبتمبر", 
+		"أكتوبر", 
+		"نوفمبر", 
+		"ديسمبر"
+	], 
+	"dateFormatItem-yMMM": "MMM y", 
+	"field-day-relative+0": "اليوم", 
+	"days-standAlone-narrow": [
+		"ح", 
+		"ن", 
+		"ث", 
+		"ر", 
+		"خ", 
+		"ج", 
+		"س"
+	], 
+	"field-day-relative+1": "غدًا", 
+	"eraAbbr": [
+		"ق.م", 
+		"م"
+	], 
+	"field-day-relative+2": "بعد الغد", 
+	"dateFormatItem-yyyyMM": "MM‏/yyyy", 
+	"dateFormatItem-yyyyMMMM": "MMMM، y", 
+	"dateFormat-long": "d MMMM، y", 
+	"timeFormat-medium": "h:mm:ss a", 
+	"field-zone": "التوقيت", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"dateFormat-medium": "dd‏/MM‏/yyyy", 
+	"quarters-standAlone-wide": [
+		"الربع الأول", 
+		"الربع الثاني", 
+		"الربع الثالث", 
+		"الربع الرابع"
+	], 
+	"dateFormatItem-yMMMM": "MMMM y", 
+	"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": [
+		"أحد", 
+		"إثنين", 
+		"ثلاثاء", 
+		"أربعاء", 
+		"خميس", 
+		"جمعة", 
+		"سبت"
+	], 
+	"dateFormatItem-M": "L", 
+	"days-format-narrow": [
+		"ح", 
+		"ن", 
+		"ث", 
+		"ر", 
+		"خ", 
+		"ج", 
+		"س"
+	], 
+	"field-second": "الثواني", 
+	"field-day": "يوم", 
+	"months-format-narrow": [
+		"ي", 
+		"ف", 
+		"م", 
+		"أ", 
+		"و", 
+		"ن", 
+		"ل", 
+		"غ", 
+		"س", 
+		"ك", 
+		"ب", 
+		"د"
+	], 
+	"days-standAlone-abbr": [
+		"أحد", 
+		"إثنين", 
+		"ثلاثاء", 
+		"أربعاء", 
+		"خميس", 
+		"جمعة", 
+		"سبت"
+	], 
+	"dateFormat-short": "d‏/M‏/yyyy", 
+	"dateFormatItem-yMMMEd": "EEE، d MMMM y", 
+	"dateFormat-full": "EEEE، d MMMM، y", 
+	"dateFormatItem-Md": "d/‏M", 
+	"dateFormatItem-yMEd": "EEE، d/‏M/‏yyyy", 
+	"months-format-wide": [
+		"يناير", 
+		"فبراير", 
+		"مارس", 
+		"أبريل", 
+		"مايو", 
+		"يونيو", 
+		"يوليو", 
+		"أغسطس", 
+		"سبتمبر", 
+		"أكتوبر", 
+		"نوفمبر", 
+		"ديسمبر"
+	], 
+	"dateFormatItem-d": "d", 
+	"quarters-format-wide": [
+		"الربع الأول", 
+		"الربع الثاني", 
+		"الربع الثالث", 
+		"الربع الرابع"
+	], 
+	"days-format-wide": [
+		"الأحد", 
+		"الإثنين", 
+		"الثلاثاء", 
+		"الأربعاء", 
+		"الخميس", 
+		"الجمعة", 
+		"السبت"
+	], 
+	"eraNarrow": [
+		"ق.م", 
+		"م"
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/ar/hebrew.js b/dojo/cldr/nls/ar/hebrew.js
index c43bd65..5cf62de 100644
--- a/dojo/cldr/nls/ar/hebrew.js
+++ b/dojo/cldr/nls/ar/hebrew.js
@@ -1 +1,120 @@
-({"quarters-format-abbr":["الربع الأول","الربع الثاني","الربع الثالث","الربع الرابع"],"dateFormat-medium":"dd‏/MM‏/yyyy","dateFormatItem-MMMEd":"E d MMM","dateFormatItem-yMEd":"EEE، d/‏M/‏yyyy","timeFormat-full":"zzzz h:mm:ss a","dateFormatItem-Md":"d/‏M","months-standAlone-wide":["تشري","مرحشوان","كيسلو","طيفت","شباط","آذار الأول","آذار الثاني","نيسان","أيار","سيفان","تموز","آب"],"days-standAlone-narrow":["ح","ن","ث","ر","خ","ج","س"],"dateFormatItem-MMMMEd":"E d MMMM","dateFormatItem-MM [...]
\ No newline at end of file
+({
+	"dateFormat-medium": "dd‏/MM‏/yyyy", 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"dateFormatItem-yMEd": "EEE، d/‏M/‏yyyy", 
+	"timeFormat-full": "zzzz h:mm:ss a", 
+	"dateFormatItem-Md": "d/‏M", 
+	"months-standAlone-wide": [
+		"تشري", 
+		"مرحشوان", 
+		"كيسلو", 
+		"طيفت", 
+		"شباط", 
+		"آذار الأول", 
+		"آذار", 
+		"نيسان", 
+		"أيار", 
+		"سيفان", 
+		"تموز", 
+		"آب", 
+		"أيلول"
+	], 
+	"months-format-wide-leap": "آذار الثاني", 
+	"days-standAlone-narrow": [
+		"ح", 
+		"ن", 
+		"ث", 
+		"ر", 
+		"خ", 
+		"ج", 
+		"س"
+	], 
+	"dayPeriods-format-wide-pm": "م", 
+	"months-standAlone-abbr": [
+		"تشري", 
+		"مرحشوان", 
+		"كيسلو", 
+		"طيفت", 
+		"شباط", 
+		"آذار الأول", 
+		"آذار", 
+		"نيسان", 
+		"أيار", 
+		"سيفان", 
+		"تموز", 
+		"آب", 
+		"أيلول"
+	], 
+	"dayPeriods-format-wide-am": "ص", 
+	"quarters-standAlone-narrow": [
+		"١", 
+		"٢", 
+		"٣", 
+		"٤"
+	], 
+	"timeFormat-medium": "h:mm:ss a", 
+	"dateFormat-long": "d MMMM، y", 
+	"dateFormat-short": "d‏/M‏/yyyy", 
+	"dateFormatItem-yMMMEd": "EEE، d MMMM y", 
+	"months-format-wide": [
+		"تشري", 
+		"مرحشوان", 
+		"كيسلو", 
+		"طيفت", 
+		"شباط", 
+		"آذار الأول", 
+		"آذار", 
+		"نيسان", 
+		"أيار", 
+		"سيفان", 
+		"تموز", 
+		"آب", 
+		"أيلول"
+	], 
+	"dateFormatItem-yM": "M‏/yyyy", 
+	"timeFormat-short": "h:mm a", 
+	"months-format-abbr": [
+		"تشري", 
+		"مرحشوان", 
+		"كيسلو", 
+		"طيفت", 
+		"شباط", 
+		"آذار الأول", 
+		"آذار", 
+		"نيسان", 
+		"أيار", 
+		"سيفان", 
+		"تموز", 
+		"آب", 
+		"أيلول"
+	], 
+	"timeFormat-long": "z h:mm:ss a", 
+	"days-format-wide": [
+		"الأحد", 
+		"الإثنين", 
+		"الثلاثاء", 
+		"الأربعاء", 
+		"الخميس", 
+		"الجمعة", 
+		"السبت"
+	], 
+	"dateFormatItem-yQ": "yyyy Q", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"quarters-format-wide": [
+		"الربع الأول", 
+		"الربع الثاني", 
+		"الربع الثالث", 
+		"الربع الرابع"
+	], 
+	"dateFormat-full": "EEEE، d MMMM، y", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"days-format-abbr": [
+		"أحد", 
+		"إثنين", 
+		"ثلاثاء", 
+		"أربعاء", 
+		"خميس", 
+		"جمعة", 
+		"سبت"
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/ar/islamic-civil.js b/dojo/cldr/nls/ar/islamic-civil.js
index 2ca9a0e..61c2692 100644
--- a/dojo/cldr/nls/ar/islamic-civil.js
+++ b/dojo/cldr/nls/ar/islamic-civil.js
@@ -1 +1,221 @@
-({"quarters-format-abbr":["الربع الأول","الربع الثاني","الربع الثالث","الربع الرابع"],"dateFormat-medium":"dd‏/MM‏/yyyy","dateFormatItem-MMMEd":"E d MMM","dateFormatItem-yMEd":"EEE، d/‏M/‏yyyy","eraNarrow":["ه"],"timeFormat-full":"zzzz h:mm:ss a","dateFormatItem-Md":"d/‏M","months-standAlone-narrow":["م","ص","ر","ر","ج","ج","ر","ش","ر","ش","ذ","ذ"],"months-standAlone-wide":["محرم","صفر","ربيع الأول","ربيع الآخر","جمادى الأولى","جمادى الآخرة","رجب","شعبان","رمضان","شوال","ذو القعدة","ذو ا [...]
\ No newline at end of file
+({
+	"dateFormatItem-yM": "M‏/yyyy", 
+	"dateFormatItem-yQ": "yyyy Q", 
+	"dayPeriods-format-wide-pm": "م", 
+	"eraNames": [
+		"ه"
+	], 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"days-standAlone-wide": [
+		"الأحد", 
+		"الإثنين", 
+		"الثلاثاء", 
+		"الأربعاء", 
+		"الخميس", 
+		"الجمعة", 
+		"السبت"
+	], 
+	"patternChars": "GanjkHmsSEDFwWxhKzAeugXZvcL", 
+	"months-standAlone-narrow": [
+		"م", 
+		"ص", 
+		"ر", 
+		"ر", 
+		"ج", 
+		"ج", 
+		"ر", 
+		"ش", 
+		"ر", 
+		"ش", 
+		"ذ", 
+		"ذ"
+	], 
+	"dayPeriods-format-wide-am": "ص", 
+	"dayPeriods-am-format-wide": "ص", 
+	"quarters-standAlone-abbr": [
+		"الربع الأول", 
+		"الربع الثاني", 
+		"الربع الثالث", 
+		"الربع الرابع"
+	], 
+	"timeFormat-full": "zzzz h:mm:ss a", 
+	"dayPeriods-pm-format-wide": "م", 
+	"dayPeriods-format-wide": [
+		"ص", 
+		"م"
+	], 
+	"months-standAlone-abbr": [
+		"محرم", 
+		"صفر", 
+		"ربيع الأول", 
+		"ربيع الآخر", 
+		"جمادى الأولى", 
+		"جمادى الآخرة", 
+		"رجب", 
+		"شعبان", 
+		"رمضان", 
+		"شوال", 
+		"ذو القعدة", 
+		"ذو الحجة"
+	], 
+	"dateFormatItem-yMMM": "MMM y", 
+	"days-standAlone-narrow": [
+		"ح", 
+		"ن", 
+		"ث", 
+		"ر", 
+		"خ", 
+		"ج", 
+		"س"
+	], 
+	"eraAbbr": [
+		"ه"
+	], 
+	"dateFormat-long": "d MMMM، y", 
+	"timeFormat-medium": "h:mm:ss a", 
+	"dateFormat-medium": "dd‏/MM‏/yyyy", 
+	"dayPeriods-format-narrow": [
+		"ص", 
+		"م"
+	], 
+	"quarters-standAlone-wide": [
+		"الربع الأول", 
+		"الربع الثاني", 
+		"الربع الثالث", 
+		"الربع الرابع"
+	], 
+	"dateFormatItem-yMMMM": "MMMM y", 
+	"quarters-standAlone-narrow": [
+		"١", 
+		"٢", 
+		"٣", 
+		"٤"
+	], 
+	"months-standAlone-wide": [
+		"محرم", 
+		"صفر", 
+		"ربيع الأول", 
+		"ربيع الآخر", 
+		"جمادى الأولى", 
+		"جمادى الآخرة", 
+		"رجب", 
+		"شعبان", 
+		"رمضان", 
+		"شوال", 
+		"ذو القعدة", 
+		"ذو الحجة"
+	], 
+	"dateFormatItem-MMMMEd": "E d MMMM", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"quarters-format-narrow": [
+		"١", 
+		"٢", 
+		"٣", 
+		"٤"
+	], 
+	"timeFormat-long": "z h:mm:ss a", 
+	"months-format-abbr": [
+		"محرم", 
+		"صفر", 
+		"ربيع الأول", 
+		"ربيع الآخر", 
+		"جمادى الأولى", 
+		"جمادى الآخرة", 
+		"رجب", 
+		"شعبان", 
+		"رمضان", 
+		"شوال", 
+		"ذو القعدة", 
+		"ذو الحجة"
+	], 
+	"timeFormat-short": "h:mm a", 
+	"dateFormatItem-MMMMd": "d MMMM", 
+	"quarters-format-abbr": [
+		"الربع الأول", 
+		"الربع الثاني", 
+		"الربع الثالث", 
+		"الربع الرابع"
+	], 
+	"days-format-abbr": [
+		"أحد", 
+		"إثنين", 
+		"ثلاثاء", 
+		"أربعاء", 
+		"خميس", 
+		"جمعة", 
+		"سبت"
+	], 
+	"days-format-narrow": [
+		"ح", 
+		"ن", 
+		"ث", 
+		"ر", 
+		"خ", 
+		"ج", 
+		"س"
+	], 
+	"months-format-narrow": [
+		"م", 
+		"ص", 
+		"ر", 
+		"ر", 
+		"ج", 
+		"ج", 
+		"ر", 
+		"ش", 
+		"ر", 
+		"ش", 
+		"ذ", 
+		"ذ"
+	], 
+	"days-standAlone-abbr": [
+		"أحد", 
+		"إثنين", 
+		"ثلاثاء", 
+		"أربعاء", 
+		"خميس", 
+		"جمعة", 
+		"سبت"
+	], 
+	"dateFormat-short": "d‏/M‏/yyyy", 
+	"dateFormatItem-yMMMEd": "EEE، d MMMM y", 
+	"dateFormat-full": "EEEE، d MMMM، y", 
+	"dateFormatItem-Md": "d/‏M", 
+	"dateFormatItem-yMEd": "EEE، d/‏M/‏yyyy", 
+	"months-format-wide": [
+		"محرم", 
+		"صفر", 
+		"ربيع الأول", 
+		"ربيع الآخر", 
+		"جمادى الأولى", 
+		"جمادى الآخرة", 
+		"رجب", 
+		"شعبان", 
+		"رمضان", 
+		"شوال", 
+		"ذو القعدة", 
+		"ذو الحجة"
+	], 
+	"dayPeriods-format-abbr": [
+		"ص", 
+		"م"
+	], 
+	"quarters-format-wide": [
+		"الربع الأول", 
+		"الربع الثاني", 
+		"الربع الثالث", 
+		"الربع الرابع"
+	], 
+	"days-format-wide": [
+		"الأحد", 
+		"الإثنين", 
+		"الثلاثاء", 
+		"الأربعاء", 
+		"الخميس", 
+		"الجمعة", 
+		"السبت"
+	], 
+	"eraNarrow": [
+		"ه"
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/ar/islamic.js b/dojo/cldr/nls/ar/islamic.js
index 59823f0..3fc24d9 100644
--- a/dojo/cldr/nls/ar/islamic.js
+++ b/dojo/cldr/nls/ar/islamic.js
@@ -1 +1,152 @@
-({"dateFormatItem-yM":"M‏/yyyy","dateFormatItem-yQ":"yyyy Q","eraNames":["هـ"],"dateFormatItem-MMMEd":"E d MMM","months-standAlone-narrow":["م","ص","ر","ر","ج","ج","ر","ش","ر","ش","ذ","ذ"],"timeFormat-full":"zzzz h:mm:ss a","months-standAlone-abbr":["محرم","صفر","ربيع الأول","ربيع الآخر","جمادى الأولى","جمادى الآخرة","رجب","شعبان","رمضان","شوال","ذو القعدة","ذو الحجة"],"dateFormatItem-yMMM":"MMM y","days-standAlone-narrow":["ح","ن","ث","ر","خ","ج","س"],"eraAbbr":["هـ"],"dateFormat-long": [...]
\ No newline at end of file
+({
+	"dateFormat-medium": "dd‏/MM‏/yyyy", 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"dateFormatItem-yMEd": "EEE، d/‏M/‏yyyy", 
+	"eraNarrow": [
+		"هـ"
+	], 
+	"months-format-narrow": [
+		"م", 
+		"ص", 
+		"ر", 
+		"ر", 
+		"ج", 
+		"ج", 
+		"ر", 
+		"ش", 
+		"ر", 
+		"ش", 
+		"ذ", 
+		"ذ"
+	], 
+	"timeFormat-full": "zzzz h:mm:ss a", 
+	"dateFormatItem-Md": "d/‏M", 
+	"months-standAlone-narrow": [
+		"م", 
+		"ص", 
+		"ر", 
+		"ر", 
+		"ج", 
+		"ج", 
+		"ر", 
+		"ش", 
+		"ر", 
+		"ش", 
+		"ذ", 
+		"ذ"
+	], 
+	"months-standAlone-wide": [
+		"محرم", 
+		"صفر", 
+		"ربيع الأول", 
+		"ربيع الآخر", 
+		"جمادى الأولى", 
+		"جمادى الآخرة", 
+		"رجب", 
+		"شعبان", 
+		"رمضان", 
+		"شوال", 
+		"ذو القعدة", 
+		"ذو الحجة"
+	], 
+	"eraNames": [
+		"هـ"
+	], 
+	"days-standAlone-narrow": [
+		"ح", 
+		"ن", 
+		"ث", 
+		"ر", 
+		"خ", 
+		"ج", 
+		"س"
+	], 
+	"dayPeriods-format-wide-pm": "م", 
+	"months-standAlone-abbr": [
+		"محرم", 
+		"صفر", 
+		"ربيع الأول", 
+		"ربيع الآخر", 
+		"جمادى الأولى", 
+		"جمادى الآخرة", 
+		"رجب", 
+		"شعبان", 
+		"رمضان", 
+		"شوال", 
+		"ذو القعدة", 
+		"ذو الحجة"
+	], 
+	"dayPeriods-format-wide-am": "ص", 
+	"quarters-standAlone-narrow": [
+		"١", 
+		"٢", 
+		"٣", 
+		"٤"
+	], 
+	"timeFormat-medium": "h:mm:ss a", 
+	"dateFormat-long": "d MMMM، y", 
+	"dateFormat-short": "d‏/M‏/yyyy", 
+	"dateFormatItem-yMMMEd": "EEE، d MMMM y", 
+	"months-format-wide": [
+		"محرم", 
+		"صفر", 
+		"ربيع الأول", 
+		"ربيع الآخر", 
+		"جمادى الأولى", 
+		"جمادى الآخرة", 
+		"رجب", 
+		"شعبان", 
+		"رمضان", 
+		"شوال", 
+		"ذو القعدة", 
+		"ذو الحجة"
+	], 
+	"dateFormatItem-yM": "M‏/yyyy", 
+	"timeFormat-short": "h:mm a", 
+	"months-format-abbr": [
+		"محرم", 
+		"صفر", 
+		"ربيع الأول", 
+		"ربيع الآخر", 
+		"جمادى الأولى", 
+		"جمادى الآخرة", 
+		"رجب", 
+		"شعبان", 
+		"رمضان", 
+		"شوال", 
+		"ذو القعدة", 
+		"ذو الحجة"
+	], 
+	"eraAbbr": [
+		"هـ"
+	], 
+	"timeFormat-long": "z h:mm:ss a", 
+	"days-format-wide": [
+		"الأحد", 
+		"الإثنين", 
+		"الثلاثاء", 
+		"الأربعاء", 
+		"الخميس", 
+		"الجمعة", 
+		"السبت"
+	], 
+	"dateFormatItem-yQ": "yyyy Q", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"quarters-format-wide": [
+		"الربع الأول", 
+		"الربع الثاني", 
+		"الربع الثالث", 
+		"الربع الرابع"
+	], 
+	"dateFormat-full": "EEEE، d MMMM، y", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"days-format-abbr": [
+		"أحد", 
+		"إثنين", 
+		"ثلاثاء", 
+		"أربعاء", 
+		"خميس", 
+		"جمعة", 
+		"سبت"
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/ar/number.js b/dojo/cldr/nls/ar/number.js
index 543ccb3..abfaca3 100644
--- a/dojo/cldr/nls/ar/number.js
+++ b/dojo/cldr/nls/ar/number.js
@@ -1 +1,25 @@
-({"group":"٬","percentSign":"٪","exponential":"اس","list":"؛","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":"٫","nan":"ليس رقم","nativeZeroDigit":"٠","perMille":"؉","decimalFormat":"#,##0.###;#,##0.###-","currencyFormat":"¤ #,##0.00;¤ #,##0.00-","plusSign":"+","scientificFormat":"#E0","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afte [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'decimal':"٫",
+	'group':".",
+	'group':"٬",
+	'list':";",
+	'list':"؛",
+	'percentSign':"%",
+	'percentSign':"٪",
+	'nativeZeroDigit':"0",
+	'nativeZeroDigit':"٠",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'exponential':"اس",
+	'perMille':"‰",
+	'perMille':"؉",
+	'infinity':"∞",
+	'nan':"NaN",
+	'nan':"ليس رقم",
+	'decimalFormat':"#,##0.###;#,##0.###-",
+	'currencyFormat':"¤ #,##0.00;¤ #,##0.00-"
+})
diff --git a/dojo/cldr/nls/buddhist.js b/dojo/cldr/nls/buddhist.js
new file mode 100644
index 0000000..3369f45
--- /dev/null
+++ b/dojo/cldr/nls/buddhist.js
@@ -0,0 +1,236 @@
+({
+	"months-format-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"quarters-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4"
+	], 
+	"dateFormatItem-yQQQ": "y QQQ", 
+	"dateFormatItem-yMEd": "EEE, y-M-d", 
+	"dateFormatItem-MMMEd": "E MMM d", 
+	"eraNarrow": [
+		"BE"
+	], 
+	"dateTimeFormats-appendItem-Day-Of-Week": "{0} {1}", 
+	"dateFormat-long": "MMMM d, y G", 
+	"months-format-wide": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"dateTimeFormat-medium": "{1} {0}", 
+	"dateFormatItem-EEEd": "d EEE", 
+	"dayPeriods-format-wide-pm": "PM", 
+	"dateFormat-full": "EEEE, MMMM d, y G", 
+	"dateFormatItem-Md": "M-d", 
+	"dayPeriods-format-abbr-am": "AM", 
+	"dateTimeFormats-appendItem-Second": "{0} ({2}: {1})", 
+	"dateFormatItem-yM": "y-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"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"dateFormatItem-yMMM": "y MMM", 
+	"dateFormatItem-yQ": "y Q", 
+	"dateTimeFormats-appendItem-Era": "{0} {1}", 
+	"months-format-abbr": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"dateTimeFormats-appendItem-Week": "{0} ({2}: {1})", 
+	"dateFormatItem-H": "HH", 
+	"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"
+	], 
+	"timeFormat-medium": "HH:mm:ss", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"quarters-standAlone-abbr": [
+		"Q1", 
+		"Q2", 
+		"Q3", 
+		"Q4"
+	], 
+	"eraAbbr": [
+		"BE"
+	], 
+	"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-h": "h a", 
+	"dateTimeFormat-long": "{1} {0}", 
+	"dayPeriods-format-narrow-am": "AM", 
+	"dateFormatItem-MMMd": "MMM d", 
+	"dateFormatItem-MEd": "E, M-d", 
+	"dateTimeFormat-full": "{1} {0}", 
+	"days-format-wide": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"dateTimeFormats-appendItem-Day": "{0} ({2}: {1})", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"dateFormatItem-hm": "h:mm a", 
+	"dateTimeFormats-appendItem-Year": "{0} {1}", 
+	"dateTimeFormats-appendItem-Hour": "{0} ({2}: {1})", 
+	"dayPeriods-format-abbr-pm": "PM", 
+	"days-format-abbr": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"eraNames": [
+		"BE"
+	], 
+	"days-format-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"days-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dateTimeFormats-appendItem-Quarter": "{0} ({2}: {1})", 
+	"dayPeriods-format-wide-am": "AM", 
+	"dateTimeFormats-appendItem-Month": "{0} ({2}: {1})", 
+	"dateTimeFormats-appendItem-Minute": "{0} ({2}: {1})", 
+	"dateFormat-short": "M/d/yyyy", 
+	"dateFormatItem-yMMMEd": "EEE, y MMM d", 
+	"dateTimeFormats-appendItem-Timezone": "{0} {1}", 
+	"dateFormat-medium": "MMM d, y G", 
+	"dayPeriods-format-narrow-pm": "PM", 
+	"dateTimeFormat-short": "{1} {0}", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-hms": "h:mm:ss a"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/ca/currency.js b/dojo/cldr/nls/ca/currency.js
index 9a3c0b3..cc8ec4d 100644
--- a/dojo/cldr/nls/ca/currency.js
+++ b/dojo/cldr/nls/ca/currency.js
@@ -1 +1,13 @@
-({"HKD_displayName":"dòlar de Hong Kong","CHF_displayName":"franc suís","CAD_displayName":"dòlar canadenc","CNY_displayName":"iuan renmimbi xinès","AUD_displayName":"dòlar australià","JPY_displayName":"ien japonès","USD_displayName":"dòlar dels Estats Units","GBP_displayName":"lliura esterlina britànica","EUR_displayName":"euro","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"dòlar australià",
+	CAD_displayName:"dòlar canadenc",
+	CHF_displayName:"franc suís",
+	CNY_displayName:"iuan renmimbi xinès",
+	EUR_displayName:"euro",
+	GBP_displayName:"lliura esterlina britànica",
+	HKD_displayName:"dòlar de Hong Kong",
+	JPY_displayName:"ien japonès",
+	USD_displayName:"dòlar dels Estats Units"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/ca/gregorian.js b/dojo/cldr/nls/ca/gregorian.js
index f931281..b0bcfc6 100644
--- a/dojo/cldr/nls/ca/gregorian.js
+++ b/dojo/cldr/nls/ca/gregorian.js
@@ -1 +1,231 @@
-({"dateFormatItem-yM":"M/yyyy","field-dayperiod":"a.m./p.m.","dateFormatItem-yQ":"Q yyyy","field-minute":"minut","eraNames":["aC","dC"],"dateFormatItem-MMMEd":"E d MMM","field-weekday":"dia de la setmana","dateFormatItem-yQQQ":"QQQ y","days-standAlone-wide":["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["g","f","m","a","m","j","j","a","s","o","n","d"],"field-era":"era","field-hour":"hora","quarters-standA [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"g", 
+		"f", 
+		"m", 
+		"a", 
+		"m", 
+		"j", 
+		"j", 
+		"a", 
+		"s", 
+		"o", 
+		"n", 
+		"d"
+	], 
+	"field-weekday": "dia de la setmana", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"dateFormatItem-yMEd": "E d/M/yyyy", 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"eraNarrow": [
+		"aC", 
+		"dC"
+	], 
+	"dateFormat-long": "d MMMM 'de' y", 
+	"months-format-wide": [
+		"de gener", 
+		"de febrer", 
+		"de març", 
+		"d’abril", 
+		"de maig", 
+		"de juny", 
+		"de juliol", 
+		"d’agost", 
+		"de setembre", 
+		"d’octubre", 
+		"de novembre", 
+		"de desembre"
+	], 
+	"dateFormatItem-EEEd": "EEE d", 
+	"dayPeriods-format-wide-pm": "p.m.", 
+	"dateFormat-full": "EEEE d MMMM 'de' y", 
+	"dateFormatItem-Md": "d/M", 
+	"field-era": "era", 
+	"dateFormatItem-yM": "M/yyyy", 
+	"months-standAlone-wide": [
+		"gener", 
+		"febrer", 
+		"març", 
+		"abril", 
+		"maig", 
+		"juny", 
+		"juliol", 
+		"agost", 
+		"setembre", 
+		"octubre", 
+		"novembre", 
+		"desembre"
+	], 
+	"timeFormat-short": "H:mm", 
+	"quarters-format-wide": [
+		"1r trimestre", 
+		"2n trimestre", 
+		"3r trimestre", 
+		"4t trimestre"
+	], 
+	"timeFormat-long": "H:mm:ss z", 
+	"field-year": "any", 
+	"dateFormatItem-yMMM": "LLL y", 
+	"dateFormatItem-yQ": "Q yyyy", 
+	"field-hour": "hora", 
+	"months-format-abbr": [
+		"de gen.", 
+		"de febr.", 
+		"de març", 
+		"d’abr.", 
+		"de maig", 
+		"de juny", 
+		"de jul.", 
+		"d’ag.", 
+		"de set.", 
+		"d’oct.", 
+		"de nov.", 
+		"de des."
+	], 
+	"dateFormatItem-yyQ": "Q yy", 
+	"timeFormat-full": "H:mm:ss zzzz", 
+	"field-day-relative+0": "avui", 
+	"field-day-relative+1": "demà", 
+	"field-day-relative+2": "demà passat", 
+	"dateFormatItem-H": "H", 
+	"field-day-relative+3": "d'aquí a tres dies", 
+	"months-standAlone-abbr": [
+		"gen.", 
+		"febr.", 
+		"març", 
+		"abr.", 
+		"maig", 
+		"juny", 
+		"jul.", 
+		"ag.", 
+		"set.", 
+		"oct.", 
+		"nov.", 
+		"des."
+	], 
+	"quarters-format-abbr": [
+		"1T", 
+		"2T", 
+		"3T", 
+		"4T"
+	], 
+	"quarters-standAlone-wide": [
+		"1r trimestre", 
+		"2n trimestre", 
+		"3r trimestre", 
+		"4t trimestre"
+	], 
+	"dateFormatItem-M": "L", 
+	"days-standAlone-wide": [
+		"diumenge", 
+		"dilluns", 
+		"dimarts", 
+		"dimecres", 
+		"dijous", 
+		"divendres", 
+		"dissabte"
+	], 
+	"dateFormatItem-MMMMd": "d MMMM", 
+	"timeFormat-medium": "H:mm:ss", 
+	"dateFormatItem-Hm": "H:mm", 
+	"quarters-standAlone-abbr": [
+		"1T", 
+		"2T", 
+		"3T", 
+		"4T"
+	], 
+	"eraAbbr": [
+		"aC", 
+		"dC"
+	], 
+	"field-minute": "minut", 
+	"field-dayperiod": "a.m./p.m.", 
+	"days-standAlone-abbr": [
+		"dg", 
+		"dl", 
+		"dt", 
+		"dc", 
+		"dj", 
+		"dv", 
+		"ds"
+	], 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "ahir", 
+	"field-day-relative+-2": "abans d'ahir", 
+	"field-day-relative+-3": "fa tres dies", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"dateFormatItem-MEd": "E d/M", 
+	"dateFormatItem-yMMMM": "LLLL 'del' y", 
+	"field-day": "dia", 
+	"days-format-wide": [
+		"diumenge", 
+		"dilluns", 
+		"dimarts", 
+		"dimecres", 
+		"dijous", 
+		"divendres", 
+		"dissabte"
+	], 
+	"field-zone": "zona", 
+	"dateFormatItem-yyyyMM": "MM/yyyy", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"g", 
+		"f", 
+		"m", 
+		"a", 
+		"m", 
+		"j", 
+		"j", 
+		"a", 
+		"s", 
+		"o", 
+		"n", 
+		"d"
+	], 
+	"dateFormatItem-hm": "h:mm a", 
+	"days-format-abbr": [
+		"dg.", 
+		"dl.", 
+		"dt.", 
+		"dc.", 
+		"dj.", 
+		"dv.", 
+		"ds."
+	], 
+	"eraNames": [
+		"aC", 
+		"dC"
+	], 
+	"days-format-narrow": [
+		"g", 
+		"l", 
+		"t", 
+		"c", 
+		"j", 
+		"v", 
+		"s"
+	], 
+	"field-month": "mes", 
+	"days-standAlone-narrow": [
+		"g", 
+		"l", 
+		"t", 
+		"c", 
+		"j", 
+		"v", 
+		"s"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dayPeriods-format-wide-am": "a.m.", 
+	"dateFormatItem-MMMMEd": "E d MMMM", 
+	"dateFormat-short": "dd/MM/yy", 
+	"field-second": "segon", 
+	"dateFormatItem-yMMMEd": "EEE d MMM y", 
+	"field-week": "setmana", 
+	"dateFormat-medium": "dd/MM/yyyy", 
+	"dateFormatItem-mmss": "mm:ss", 
+	"dateFormatItem-Hms": "H:mm:ss", 
+	"dateFormatItem-hms": "h:mm:ss a"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/ca/number.js b/dojo/cldr/nls/ca/number.js
index da4300c..d0f0a5f 100644
--- a/dojo/cldr/nls/ca/number.js
+++ b/dojo/cldr/nls/ca/number.js
@@ -1 +1,19 @@
-({"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-afterCu [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':".",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/cs/currency.js b/dojo/cldr/nls/cs/currency.js
index 64c8a42..63bd725 100644
--- a/dojo/cldr/nls/cs/currency.js
+++ b/dojo/cldr/nls/cs/currency.js
@@ -1 +1,13 @@
-({"HKD_displayName":"Dolar hongkongský","CHF_displayName":"Frank švýcarský","CAD_displayName":"Dolar kanadský","CNY_displayName":"Juan renminbi","AUD_displayName":"Dolar australský","JPY_displayName":"Jen","USD_displayName":"Dolar americký","GBP_displayName":"Libra šterlinků","EUR_displayName":"Euro","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Dolar australský",
+	CAD_displayName:"Dolar kanadský",
+	CHF_displayName:"Frank švýcarský",
+	CNY_displayName:"Juan renminbi",
+	EUR_displayName:"Euro",
+	GBP_displayName:"Libra šterlinků",
+	HKD_displayName:"Dolar hongkongský",
+	JPY_displayName:"Jen",
+	USD_displayName:"Dolar americký"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/cs/gregorian.js b/dojo/cldr/nls/cs/gregorian.js
index 3d35825..ec58625 100644
--- a/dojo/cldr/nls/cs/gregorian.js
+++ b/dojo/cldr/nls/cs/gregorian.js
@@ -1 +1,194 @@
-({"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"],"m [...]
\ No newline at end of file
+({
+	"dayPeriods-format-wide-pm": "odp.", 
+	"eraNames": [
+		"př.Kr.", 
+		"po Kr."
+	], 
+	"field-day-relative+-1": "Včera", 
+	"field-day-relative+-2": "Předevčírem", 
+	"days-standAlone-wide": [
+		"neděle", 
+		"pondělí", 
+		"úterý", 
+		"středa", 
+		"čtvrtek", 
+		"pátek", 
+		"sobota"
+	], 
+	"months-standAlone-narrow": [
+		"l", 
+		"ú", 
+		"b", 
+		"d", 
+		"k", 
+		"č", 
+		"č", 
+		"s", 
+		"z", 
+		"ř", 
+		"l", 
+		"p"
+	], 
+	"dayPeriods-format-wide-am": "dop.", 
+	"quarters-standAlone-abbr": [
+		"1. čtvrtletí", 
+		"2. čtvrtletí", 
+		"3. čtvrtletí", 
+		"4. čtvrtletí"
+	], 
+	"timeFormat-full": "H:mm:ss zzzz", 
+	"months-standAlone-abbr": [
+		"1.", 
+		"2.", 
+		"3.", 
+		"4.", 
+		"5.", 
+		"6.", 
+		"7.", 
+		"8.", 
+		"9.", 
+		"10.", 
+		"11.", 
+		"12."
+	], 
+	"field-day-relative+0": "Dnes", 
+	"field-day-relative+1": "Zítra", 
+	"days-standAlone-narrow": [
+		"N", 
+		"P", 
+		"Ú", 
+		"S", 
+		"Č", 
+		"P", 
+		"S"
+	], 
+	"eraAbbr": [
+		"př.Kr.", 
+		"po Kr."
+	], 
+	"field-day-relative+2": "Pozítří", 
+	"dateFormat-long": "d. MMMM y", 
+	"timeFormat-medium": "H:mm:ss", 
+	"dateFormatItem-Hm": "H:mm", 
+	"dateFormat-medium": "d.M.yyyy", 
+	"dateFormatItem-Hms": "H:mm:ss", 
+	"quarters-standAlone-wide": [
+		"1. čtvrtletí", 
+		"2. čtvrtletí", 
+		"3. čtvrtletí", 
+		"4. čtvrtletí"
+	], 
+	"months-standAlone-wide": [
+		"leden", 
+		"únor", 
+		"březen", 
+		"duben", 
+		"květen", 
+		"červen", 
+		"červenec", 
+		"srpen", 
+		"září", 
+		"říjen", 
+		"listopad", 
+		"prosinec"
+	], 
+	"timeFormat-long": "H:mm:ss z", 
+	"months-format-abbr": [
+		"ledna", 
+		"února", 
+		"března", 
+		"dubna", 
+		"května", 
+		"června", 
+		"července", 
+		"srpna", 
+		"září", 
+		"října", 
+		"listopadu", 
+		"prosince"
+	], 
+	"timeFormat-short": "H:mm", 
+	"dateFormatItem-H": "H", 
+	"quarters-format-abbr": [
+		"1. čtvrtletí", 
+		"2. čtvrtletí", 
+		"3. čtvrtletí", 
+		"4. čtvrtletí"
+	], 
+	"days-format-abbr": [
+		"ne", 
+		"po", 
+		"út", 
+		"st", 
+		"čt", 
+		"pá", 
+		"so"
+	], 
+	"days-format-narrow": [
+		"N", 
+		"P", 
+		"Ú", 
+		"S", 
+		"Č", 
+		"P", 
+		"S"
+	], 
+	"months-format-narrow": [
+		"l", 
+		"ú", 
+		"b", 
+		"d", 
+		"k", 
+		"č", 
+		"č", 
+		"s", 
+		"z", 
+		"ř", 
+		"l", 
+		"p"
+	], 
+	"days-standAlone-abbr": [
+		"ne", 
+		"po", 
+		"út", 
+		"st", 
+		"čt", 
+		"pá", 
+		"so"
+	], 
+	"dateFormat-short": "d.M.yy", 
+	"dateFormat-full": "EEEE, d. MMMM y", 
+	"months-format-wide": [
+		"ledna", 
+		"února", 
+		"března", 
+		"dubna", 
+		"května", 
+		"června", 
+		"července", 
+		"srpna", 
+		"září", 
+		"října", 
+		"listopadu", 
+		"prosince"
+	], 
+	"quarters-format-wide": [
+		"1. čtvrtletí", 
+		"2. čtvrtletí", 
+		"3. čtvrtletí", 
+		"4. čtvrtletí"
+	], 
+	"days-format-wide": [
+		"neděle", 
+		"pondělí", 
+		"úterý", 
+		"středa", 
+		"čtvrtek", 
+		"pátek", 
+		"sobota"
+	], 
+	"eraNarrow": [
+		"př.Kr.", 
+		"po Kr."
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/cs/number.js b/dojo/cldr/nls/cs/number.js
index ad7c869..33c9d64 100644
--- a/dojo/cldr/nls/cs/number.js
+++ b/dojo/cldr/nls/cs/number.js
@@ -1 +1,19 @@
-({"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-afterCu [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':" ",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0 %",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/currency.js b/dojo/cldr/nls/currency.js
index 5007016..0c3ad16 100644
--- a/dojo/cldr/nls/currency.js
+++ b/dojo/cldr/nls/currency.js
@@ -1 +1,12 @@
-({"CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_symbol:"AU$",
+	CAD_symbol:"CA$",
+	CNY_symbol:"CN¥",
+	EUR_symbol:"€",
+	GBP_symbol:"£",
+	HKD_symbol:"HK$",
+	JPY_symbol:"JP¥",
+	USD_symbol:"US$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/da/currency.js b/dojo/cldr/nls/da/currency.js
index 431592c..dabbb43 100644
--- a/dojo/cldr/nls/da/currency.js
+++ b/dojo/cldr/nls/da/currency.js
@@ -1 +1,14 @@
-({"HKD_displayName":"Hongkong dollar","CHF_displayName":"Schweizisk franc","CAD_displayName":"Canadisk dollar","CNY_displayName":"Kinesisk yuan renminbi","USD_symbol":"$","AUD_displayName":"Australsk dollar","JPY_displayName":"Japansk yen","USD_displayName":"Amerikansk dollar","GBP_displayName":"Britisk pund","EUR_displayName":"Euro","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Australsk dollar",
+	CAD_displayName:"Canadisk dollar",
+	CHF_displayName:"Schweizisk franc",
+	CNY_displayName:"Kinesisk yuan renminbi",
+	EUR_displayName:"Euro",
+	GBP_displayName:"Britisk pund",
+	HKD_displayName:"Hongkong dollar",
+	JPY_displayName:"Japansk yen",
+	USD_displayName:"Amerikansk dollar",
+	USD_symbol:"$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/da/gregorian.js b/dojo/cldr/nls/da/gregorian.js
index bfcca51..5410b0a 100644
--- a/dojo/cldr/nls/da/gregorian.js
+++ b/dojo/cldr/nls/da/gregorian.js
@@ -1 +1,232 @@
-({"dateFormatItem-yM":"M-yyyy","field-dayperiod":"dagtid","dateFormatItem-yQ":"Q yyyy","field-minute":"minut","eraNames":["f.Kr.","e.Kr."],"dateFormatItem-MMMEd":"E d MMM","field-weekday":"ugedag","dateFormatItem-hms":"h.mm.ss a","dateFormatItem-yQQQ":"QQQ y","dateFormatItem-MMdd":"dd/MM","days-standAlone-wide":["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],"dateFormatItem-MMM":"MMM","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"field-e [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"J", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"field-weekday": "ugedag", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"dateFormatItem-yMEd": "EEE. d/M/y", 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"eraNarrow": [
+		"f.Kr.", 
+		"e.Kr."
+	], 
+	"dateFormat-long": "d. MMM y", 
+	"months-format-wide": [
+		"januar", 
+		"februar", 
+		"marts", 
+		"april", 
+		"maj", 
+		"juni", 
+		"juli", 
+		"august", 
+		"september", 
+		"oktober", 
+		"november", 
+		"december"
+	], 
+	"dayPeriods-format-wide-pm": "e.m.", 
+	"dateFormat-full": "EEEE 'den' d. MMMM y", 
+	"dateFormatItem-Md": "d/M", 
+	"field-era": "æra", 
+	"dateFormatItem-yM": "M/y", 
+	"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"
+	], 
+	"timeFormat-long": "HH.mm.ss z", 
+	"field-year": "år", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"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", 
+	"timeFormat-full": "HH.mm.ss zzzz", 
+	"field-day-relative+0": "i dag", 
+	"field-day-relative+1": "i morgen", 
+	"field-day-relative+2": "i overmorgen", 
+	"dateFormatItem-H": "HH", 
+	"field-day-relative+3": "i overovermorgen", 
+	"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-M": "M", 
+	"days-standAlone-wide": [
+		"søndag", 
+		"mandag", 
+		"tirsdag", 
+		"onsdag", 
+		"torsdag", 
+		"fredag", 
+		"lørdag"
+	], 
+	"dateFormatItem-yyyyMMM": "MMM y", 
+	"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", 
+	"field-day-relative+-1": "i går", 
+	"field-day-relative+-2": "i forgårs", 
+	"field-day-relative+-3": "i forforgårs", 
+	"dateFormatItem-MMMd": "d. MMM", 
+	"dateFormatItem-MEd": "E. d/M", 
+	"field-day": "dag", 
+	"days-format-wide": [
+		"søndag", 
+		"mandag", 
+		"tirsdag", 
+		"onsdag", 
+		"torsdag", 
+		"fredag", 
+		"lørdag"
+	], 
+	"field-zone": "zone", 
+	"dateFormatItem-yyyyMM": "MM/yyyy", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"J", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"dateFormatItem-yyMM": "MM/yy", 
+	"dateFormatItem-hm": "h.mm a", 
+	"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", 
+	"dayPeriods-format-wide-am": "f.m.", 
+	"dateFormatItem-MMMMEd": "E, d. MMMM", 
+	"dateFormat-short": "dd/MM/yy", 
+	"field-second": "sekund", 
+	"dateFormatItem-yMMMEd": "EEE. d. MMM y", 
+	"field-week": "uge", 
+	"dateFormat-medium": "dd/MM/yyyy", 
+	"dateFormatItem-Hms": "HH.mm.ss", 
+	"dateFormatItem-hms": "h.mm.ss a", 
+	"dateFormatItem-yyyy": "y"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/da/number.js b/dojo/cldr/nls/da/number.js
index 2f5fc8e..6ff39a5 100644
--- a/dojo/cldr/nls/da/number.js
+++ b/dojo/cldr/nls/da/number.js
@@ -1 +1,19 @@
-({"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-afterC [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':".",
+	'list':",",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0 %",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/de-de/number.js b/dojo/cldr/nls/de-de/number.js
deleted file mode 100644
index e600506..0000000
--- a/dojo/cldr/nls/de-de/number.js
+++ /dev/null
@@ -1 +0,0 @@
-({"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-afterC [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/de/currency.js b/dojo/cldr/nls/de/currency.js
index a80d3fc..f5f13c0 100644
--- a/dojo/cldr/nls/de/currency.js
+++ b/dojo/cldr/nls/de/currency.js
@@ -1 +1,15 @@
-({"HKD_displayName":"Hongkong-Dollar","CHF_displayName":"Schweizer Franken","JPY_symbol":"¥","CAD_displayName":"Kanadischer Dollar","CNY_displayName":"Renminbi Yuan","USD_symbol":"$","AUD_displayName":"Australischer Dollar","JPY_displayName":"Yen","USD_displayName":"US-Dollar","GBP_displayName":"Pfund Sterling","EUR_displayName":"Euro","CHF_symbol":"Fr.","HKD_symbol":"HK$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Australischer Dollar",
+	CAD_displayName:"Kanadischer Dollar",
+	CHF_displayName:"Schweizer Franken",
+	CNY_displayName:"Renminbi Yuan",
+	EUR_displayName:"Euro",
+	GBP_displayName:"Pfund Sterling",
+	HKD_displayName:"Hongkong-Dollar",
+	JPY_displayName:"Yen",
+	JPY_symbol:"¥",
+	USD_displayName:"US-Dollar",
+	USD_symbol:"$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/de/gregorian.js b/dojo/cldr/nls/de/gregorian.js
index 31d54b6..7a95c3a 100644
--- a/dojo/cldr/nls/de/gregorian.js
+++ b/dojo/cldr/nls/de/gregorian.js
@@ -1 +1,234 @@
-({"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 y","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-MMMEd":"E d. MMM","eraNarrow":["v. Chr.","n. Chr."],"dateFormat-long":"d. MMMM y","months-format-wide":["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"dateTimeFor [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"J", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"field-weekday": "Wochentag", 
+	"dateFormatItem-yyQQQQ": "QQQQ yy", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"dateFormatItem-yMEd": "EEE, d.M.y", 
+	"dateFormatItem-MMMEd": "E d. MMM", 
+	"eraNarrow": [
+		"v. Chr.", 
+		"n. Chr."
+	], 
+	"dayPeriods-format-wide-earlyMorning": "morgens", 
+	"dayPeriods-format-wide-morning": "vormittags", 
+	"dateFormat-long": "d. MMMM y", 
+	"months-format-wide": [
+		"Januar", 
+		"Februar", 
+		"März", 
+		"April", 
+		"Mai", 
+		"Juni", 
+		"Juli", 
+		"August", 
+		"September", 
+		"Oktober", 
+		"November", 
+		"Dezember"
+	], 
+	"dayPeriods-format-wide-evening": "abends", 
+	"dateFormatItem-EEEd": "d. EEE", 
+	"dayPeriods-format-wide-pm": "nachm.", 
+	"dateFormat-full": "EEEE, d. MMMM y", 
+	"dateFormatItem-Md": "d.M.", 
+	"dateFormatItem-yyMMdd": "dd.MM.yy", 
+	"dayPeriods-format-wide-noon": "Mittag", 
+	"field-era": "Epoche", 
+	"dateFormatItem-yM": "M.y", 
+	"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"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"field-year": "Jahr", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"dateFormatItem-yQ": "Q y", 
+	"dateFormatItem-yyyyMMMM": "MMMM y", 
+	"dateFormatItem-MMdd": "dd.MM.", 
+	"field-hour": "Stunde", 
+	"months-format-abbr": [
+		"Jan", 
+		"Feb", 
+		"Mär", 
+		"Apr", 
+		"Mai", 
+		"Jun", 
+		"Jul", 
+		"Aug", 
+		"Sep", 
+		"Okt", 
+		"Nov", 
+		"Dez"
+	], 
+	"dateFormatItem-yyQ": "Q yy", 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"field-day-relative+0": "heute", 
+	"field-day-relative+1": "morgen", 
+	"field-day-relative+2": "übermorgen", 
+	"dateFormatItem-H": "HH", 
+	"field-day-relative+3": "überübermorgen", 
+	"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-M": "L", 
+	"days-standAlone-wide": [
+		"Sonntag", 
+		"Montag", 
+		"Dienstag", 
+		"Mittwoch", 
+		"Donnerstag", 
+		"Freitag", 
+		"Samstag"
+	], 
+	"dateFormatItem-yyMMM": "MMM yy", 
+	"timeFormat-medium": "HH:mm:ss", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"eraAbbr": [
+		"v. Chr.", 
+		"n. Chr."
+	], 
+	"field-minute": "Minute", 
+	"field-dayperiod": "Tageshälfte", 
+	"dayPeriods-format-wide-night": "nachts", 
+	"days-standAlone-abbr": [
+		"So.", 
+		"Mo.", 
+		"Di.", 
+		"Mi.", 
+		"Do.", 
+		"Fr.", 
+		"Sa."
+	], 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "gestern", 
+	"field-day-relative+-2": "vorgestern", 
+	"field-day-relative+-3": "vorvorgestern", 
+	"dateFormatItem-MMMd": "d. MMM", 
+	"dateFormatItem-MEd": "E, d.M.", 
+	"field-day": "Tag", 
+	"days-format-wide": [
+		"Sonntag", 
+		"Montag", 
+		"Dienstag", 
+		"Mittwoch", 
+		"Donnerstag", 
+		"Freitag", 
+		"Samstag"
+	], 
+	"field-zone": "Zone", 
+	"dateFormatItem-y": "y", 
+	"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", 
+	"dayPeriods-format-wide-am": "vorm.", 
+	"dateFormatItem-MMMMdd": "dd. MMMM", 
+	"dateFormat-short": "dd.MM.yy", 
+	"dateFormatItem-MMd": "d.MM.", 
+	"dayPeriods-format-wide-afternoon": "nachmittags", 
+	"field-second": "Sekunde", 
+	"dateFormatItem-yMMMEd": "EEE, d. MMM y", 
+	"dateFormatItem-Ed": "E d.", 
+	"field-week": "Woche", 
+	"dateFormat-medium": "dd.MM.yyyy", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-yyyy": "y"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/de/number.js b/dojo/cldr/nls/de/number.js
index 90861a0..b59dd68 100644
--- a/dojo/cldr/nls/de/number.js
+++ b/dojo/cldr/nls/de/number.js
@@ -1 +1,19 @@
-({"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-afterC [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':".",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0 %",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/el/currency.js b/dojo/cldr/nls/el/currency.js
index bc0d162..84f91ff 100644
--- a/dojo/cldr/nls/el/currency.js
+++ b/dojo/cldr/nls/el/currency.js
@@ -1 +1,13 @@
-({"HKD_displayName":"Δολάριο Χονγκ Κονγκ","CHF_displayName":"Φράγκο Ελβετίας","CAD_displayName":"Δολάριο Καναδά","CNY_displayName":"Γιουάν Ρενμίμπι Κίνας","AUD_displayName":"Δολάριο Αυστραλίας","JPY_displayName":"Γιεν Ιαπωνίας","USD_displayName":"Δολάριο ΗΠΑ","GBP_displayName":"Λίρα Στερλίνα Βρετανίας","EUR_displayName":"Ευρώ","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Δολάριο Αυστραλίας",
+	CAD_displayName:"Δολάριο Καναδά",
+	CHF_displayName:"Φράγκο Ελβετίας",
+	CNY_displayName:"Γιουάν Ρενμίμπι Κίνας",
+	EUR_displayName:"Ευρώ",
+	GBP_displayName:"Λίρα Στερλίνα Βρετανίας",
+	HKD_displayName:"Δολάριο Χονγκ Κονγκ",
+	JPY_displayName:"Γιεν Ιαπωνίας",
+	USD_displayName:"Δολάριο ΗΠΑ"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/el/gregorian.js b/dojo/cldr/nls/el/gregorian.js
index affc062..5b5b2ad 100644
--- a/dojo/cldr/nls/el/gregorian.js
+++ b/dojo/cldr/nls/el/gregorian.js
@@ -1 +1,238 @@
-({"months-format-narrow":["Ι","Φ","Μ","Α","Μ","Ι","Ι","Α","Σ","Ο","Ν","Δ"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"Ημέρα εβδομάδας","dateFormatItem-yyQQQQ":"QQQQ yy","dateFormatItem-yQQQ":"y QQQ","dateFormatItem-yMEd":"EEE, d/M/yyyy","dateFormatItem-MMMEd":"E, d MMM","eraNarrow":["π.Χ.","μ.Χ."],"dateFormat-long":"dd MMMM y","months-format-wide":["Ιανουαρίου","Φεβρουαρίου","Μαρτίου","Απριλίου","Μαΐου","Ιουνίου","Ιουλίου","Αυγούστου","Σεπτεμβρίου","Οκτωβρίου","Νοεμβ [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"Ι", 
+		"Φ", 
+		"Μ", 
+		"Α", 
+		"Μ", 
+		"Ι", 
+		"Ι", 
+		"Α", 
+		"Σ", 
+		"Ο", 
+		"Ν", 
+		"Δ"
+	], 
+	"field-weekday": "Ημέρα εβδομάδας", 
+	"dateFormatItem-yyQQQQ": "QQQQ yy", 
+	"dateFormatItem-yQQQ": "y QQQ", 
+	"dateFormatItem-yMEd": "EEE, d/M/yyyy", 
+	"dateFormatItem-MMMEd": "E, d MMM", 
+	"eraNarrow": [
+		"π.Χ.", 
+		"μ.Χ."
+	], 
+	"dateFormat-long": "d MMMM y", 
+	"months-format-wide": [
+		"Ιανουαρίου", 
+		"Φεβρουαρίου", 
+		"Μαρτίου", 
+		"Απριλίου", 
+		"Μαΐου", 
+		"Ιουνίου", 
+		"Ιουλίου", 
+		"Αυγούστου", 
+		"Σεπτεμβρίου", 
+		"Οκτωβρίου", 
+		"Νοεμβρίου", 
+		"Δεκεμβρίου"
+	], 
+	"dateFormatItem-EEEd": "EEE d", 
+	"dayPeriods-format-wide-pm": "μ.μ.", 
+	"dateFormat-full": "EEEE, d MMMM y", 
+	"dateFormatItem-Md": "d/M", 
+	"field-era": "Περίοδος", 
+	"dateFormatItem-yM": "M/yyyy", 
+	"months-standAlone-wide": [
+		"Ιανουάριος", 
+		"Φεβρουάριος", 
+		"Μάρτιος", 
+		"Απρίλιος", 
+		"Μάιος", 
+		"Ιούνιος", 
+		"Ιούλιος", 
+		"Αύγουστος", 
+		"Σεπτέμβριος", 
+		"Οκτώβριος", 
+		"Νοέμβριος", 
+		"Δεκέμβριος"
+	], 
+	"timeFormat-short": "h:mm a", 
+	"quarters-format-wide": [
+		"1ο τρίμηνο", 
+		"2ο τρίμηνο", 
+		"3ο τρίμηνο", 
+		"4ο τρίμηνο"
+	], 
+	"timeFormat-long": "h:mm:ss a z", 
+	"field-year": "Έτος", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"dateFormatItem-yQ": "y Q", 
+	"dateFormatItem-yyyyMMMM": "MMMM y", 
+	"field-hour": "Ώρα", 
+	"dateFormatItem-MMdd": "dd/MM", 
+	"months-format-abbr": [
+		"Ιαν", 
+		"Φεβ", 
+		"Μαρ", 
+		"Απρ", 
+		"Μαϊ", 
+		"Ιουν", 
+		"Ιουλ", 
+		"Αυγ", 
+		"Σεπ", 
+		"Οκτ", 
+		"Νοε", 
+		"Δεκ"
+	], 
+	"dateFormatItem-yyQ": "Q yy", 
+	"timeFormat-full": "h:mm:ss a zzzz", 
+	"field-day-relative+0": "Σήμερα", 
+	"field-day-relative+1": "Αύριο", 
+	"field-day-relative+2": "Μεθαύριο", 
+	"dateFormatItem-H": "HH", 
+	"field-day-relative+3": "Σε τρεις ημέρες από τώρα", 
+	"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": "h:mm:ss a", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"quarters-standAlone-abbr": [
+		"Τ1", 
+		"Τ2", 
+		"Τ3", 
+		"Τ4"
+	], 
+	"eraAbbr": [
+		"π.Χ.", 
+		"μ.Χ."
+	], 
+	"field-minute": "Λεπτό", 
+	"field-dayperiod": "π.μ./μ.μ.", 
+	"days-standAlone-abbr": [
+		"Κυρ", 
+		"Δευ", 
+		"Τρι", 
+		"Τετ", 
+		"Πεμ", 
+		"Παρ", 
+		"Σαβ"
+	], 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "Χθες", 
+	"field-day-relative+-2": "Προχθές", 
+	"field-day-relative+-3": "Πριν από τρεις ημέρες", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"dateFormatItem-MEd": "E, d/M", 
+	"dateFormatItem-yMMMM": "LLLL y", 
+	"field-day": "Ημέρα", 
+	"days-format-wide": [
+		"Κυριακή", 
+		"Δευτέρα", 
+		"Τρίτη", 
+		"Τετάρτη", 
+		"Πέμπτη", 
+		"Παρασκευή", 
+		"Σάββατο"
+	], 
+	"field-zone": "Ζώνη", 
+	"dateFormatItem-yyyyMM": "MM/yyyy", 
+	"dateFormatItem-y": "y", 
+	"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", 
+	"dayPeriods-format-wide-am": "π.μ.", 
+	"dateFormatItem-MMMMEd": "E, d MMMM", 
+	"dateFormatItem-MMMMdd": "dd MMMM", 
+	"dateFormat-short": "d/M/yy", 
+	"field-second": "Δευτερόλεπτο", 
+	"dateFormatItem-yMMMEd": "EEE, d MMM y", 
+	"dateFormatItem-Ed": "E d", 
+	"field-week": "Εβδομάδα", 
+	"dateFormat-medium": "d MMM y", 
+	"dateFormatItem-mmss": "mm:ss", 
+	"dateFormatItem-yyyy": "y"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/el/number.js b/dojo/cldr/nls/el/number.js
index ff419fb..dc8f31b 100644
--- a/dojo/cldr/nls/el/number.js
+++ b/dojo/cldr/nls/el/number.js
@@ -1 +1,17 @@
-({"group":".","percentSign":"%","exponential":"e","percentFormat":"#,##0%","list":",","infinity":"∞","patternDigit":"#","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","currencyFormat":"#,##0.00 ¤","plusSign":"+","scientificFormat":"#E0","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingMatch":"[: [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':".",
+	'list':",",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"e",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/en-au/currency.js b/dojo/cldr/nls/en-au/currency.js
index b1caa0e..9e256e1 100644
--- a/dojo/cldr/nls/en-au/currency.js
+++ b/dojo/cldr/nls/en-au/currency.js
@@ -1 +1,6 @@
-({"AUD_symbol":"$","USD_symbol":"US$","HKD_displayName":"Hong Kong Dollar","CHF_displayName":"Swiss Franc","JPY_symbol":"¥","CAD_displayName":"Canadian Dollar","CNY_displayName":"Chinese Yuan Renminbi","AUD_displayName":"Australian Dollar","JPY_displayName":"Japanese Yen","USD_displayName":"US Dollar","GBP_displayName":"British Pound Sterling","EUR_displayName":"Euro","CHF_symbol":"Fr.","HKD_symbol":"HK$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_symbol:"$",
+	USD_symbol:"US$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/en-au/gregorian.js b/dojo/cldr/nls/en-au/gregorian.js
index 13145b6..2090a99 100644
--- a/dojo/cldr/nls/en-au/gregorian.js
+++ b/dojo/cldr/nls/en-au/gregorian.js
@@ -1 +1,15 @@
-({"dateFormat-short":"d/MM/yy","dateFormatItem-MMdd":"dd/MM","dateFormat-medium":"dd/MM/yyyy","dateFormat-long":"d MMMM y","dateFormatItem-MMMMd":"d MMMM","dateFormat-full":"EEEE, d MMMM y","dateFormatItem-yyyyMM":"MM/yyyy","dateFormatItem-yyyyMMMM":"MMMM y","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","dateTimeFormat-full":"{1} {0}","field-weekday": [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/calendars/calendar-gregorian
+({
+	'dateFormat-full': "EEEE, d MMMM y",
+	'dateFormat-long': "d MMMM y",
+	'dateFormat-medium': "dd/MM/yyyy",
+	'dateFormat-short': "d/MM/yy",
+	'dateFormatItem-MEd':"E, d/M",
+	'dateFormatItem-MMdd':"dd/MM",
+	'dateFormatItem-MMMEd':"E, d MMM",
+	'dateFormatItem-MMMMd':"d MMMM",
+	'dateFormatItem-yMEd':"EEE, d/M/y",
+	'dateFormatItem-yyyyMM':"MM/yyyy",
+	'dateFormatItem-yyyyMMMM':"MMMM y"
+})
+                        
\ No newline at end of file
diff --git a/dojo/cldr/nls/en-au/number.js b/dojo/cldr/nls/en-au/number.js
index 748ea80..eef8f4d 100644
--- a/dojo/cldr/nls/en-au/number.js
+++ b/dojo/cldr/nls/en-au/number.js
@@ -1 +1,4 @@
-({"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-afterCur [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'currencyFormat':"¤#,##0.00"
+})
diff --git a/dojo/cldr/nls/en-ca/currency.js b/dojo/cldr/nls/en-ca/currency.js
index 0fede32..a80668d 100644
--- a/dojo/cldr/nls/en-ca/currency.js
+++ b/dojo/cldr/nls/en-ca/currency.js
@@ -1 +1,6 @@
-({"CAD_symbol":"$","USD_symbol":"US$","HKD_displayName":"Hong Kong Dollar","CHF_displayName":"Swiss Franc","JPY_symbol":"¥","CAD_displayName":"Canadian Dollar","CNY_displayName":"Chinese Yuan Renminbi","AUD_displayName":"Australian Dollar","JPY_displayName":"Japanese Yen","USD_displayName":"US Dollar","GBP_displayName":"British Pound Sterling","EUR_displayName":"Euro","CHF_symbol":"Fr.","HKD_symbol":"HK$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	CAD_symbol:"$",
+	USD_symbol:"US$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/en-ca/gregorian.js b/dojo/cldr/nls/en-ca/gregorian.js
index 1eb4b3e..987ecb5 100644
--- a/dojo/cldr/nls/en-ca/gregorian.js
+++ b/dojo/cldr/nls/en-ca/gregorian.js
@@ -1 +1,18 @@
-({"dateFormat-short":"yy-MM-dd","dateFormatItem-MMdd":"MM-dd","dateFormat-medium":"yyyy-MM-dd","dateFormatItem-yyMMM":"MMM-yy","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","dateTimeFormat-full":"{1} {0}","field-weekday":"Day of the Week","dateFormatItem-yQQQ":"QQQ y","days-standAlone-wide":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday", [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/calendars/calendar-gregorian
+({
+	'dateFormat-full': "EEEE, d MMMM, y",
+	'dateFormat-long': "d MMMM, y",
+	'dateFormat-medium': "yyyy-MM-dd",
+	'dateFormat-short': "yy-MM-dd",
+	'dateFormatItem-Md':"M-d",
+	'dateFormatItem-MEd':"E, M-d",
+	'dateFormatItem-MMdd':"MM-dd",
+	'dateFormatItem-MMMd':"d MMM",
+	'dateFormatItem-MMMEd':"E, d MMM",
+	'dateFormatItem-MMMMd':"d MMMM",
+	'dateFormatItem-MMMMEd':"E, d MMMM",
+	'dateFormatItem-yMEd':"EEE, y-M-d",
+	'dateFormatItem-yMMMEd':"EEE, d MMM, y",
+	'dateFormatItem-yyMMM':"MMM-yy"
+})
+                        
\ No newline at end of file
diff --git a/dojo/cldr/nls/en-gb/gregorian.js b/dojo/cldr/nls/en-gb/gregorian.js
index 600dc9f..3eb850e 100644
--- a/dojo/cldr/nls/en-gb/gregorian.js
+++ b/dojo/cldr/nls/en-gb/gregorian.js
@@ -1 +1,21 @@
-({"dateFormatItem-yyMMM":"MMM yy","dateFormatItem-Md":"d/M","dateFormatItem-yMEd":"EEE, d/M/yyyy","dateFormatItem-yyyyMMMM":"MMMM y","timeFormat-full":"HH:mm:ss zzzz","timeFormat-medium":"HH:mm:ss","dateFormatItem-MEd":"E, d/M","dateFormat-medium":"d MMM y","dateFormatItem-MMdd":"dd/MM","dateFormatItem-yyyyMM":"MM/yyyy","dateFormat-full":"EEEE, d MMMM y","timeFormat-long":"HH:mm:ss z","timeFormat-short":"HH:mm","dateFormat-short":"dd/MM/yyyy","dateFormatItem-MMMMd":"d MMMM","dateFormat-l [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/calendars/calendar-gregorian
+({
+	'dateFormat-full': "EEEE, d MMMM y",
+	'dateFormat-long': "d MMMM y",
+	'dateFormat-medium': "d MMM y",
+	'dateFormat-short': "dd/MM/yyyy",
+	'timeFormat-full': "HH:mm:ss zzzz",
+	'timeFormat-long': "HH:mm:ss z",
+	'timeFormat-medium': "HH:mm:ss",
+	'timeFormat-short': "HH:mm",
+	'dateFormatItem-Md':"d/M",
+	'dateFormatItem-MEd':"E, d/M",
+	'dateFormatItem-MMdd':"dd/MM",
+	'dateFormatItem-MMMEd':"E d MMM",
+	'dateFormatItem-MMMMd':"d MMMM",
+	'dateFormatItem-yMEd':"EEE, d/M/yyyy",
+	'dateFormatItem-yyMMM':"MMM yy",
+	'dateFormatItem-yyyyMM':"MM/yyyy",
+	'dateFormatItem-yyyyMMMM':"MMMM y"
+})
+                        
\ No newline at end of file
diff --git a/dojo/cldr/nls/en-gb/number.js b/dojo/cldr/nls/en-gb/number.js
index 748ea80..eef8f4d 100644
--- a/dojo/cldr/nls/en-gb/number.js
+++ b/dojo/cldr/nls/en-gb/number.js
@@ -1 +1,4 @@
-({"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-afterCur [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'currencyFormat':"¤#,##0.00"
+})
diff --git a/dojo/cldr/nls/en-us/currency.js b/dojo/cldr/nls/en-us/currency.js
deleted file mode 100644
index fdfe855..0000000
--- a/dojo/cldr/nls/en-us/currency.js
+++ /dev/null
@@ -1 +0,0 @@
-({"USD_symbol":"$","HKD_displayName":"Hong Kong Dollar","CHF_displayName":"Swiss Franc","JPY_symbol":"¥","CAD_displayName":"Canadian Dollar","CNY_displayName":"Chinese Yuan Renminbi","AUD_displayName":"Australian Dollar","JPY_displayName":"Japanese Yen","USD_displayName":"US Dollar","GBP_displayName":"British Pound Sterling","EUR_displayName":"Euro","CHF_symbol":"Fr.","HKD_symbol":"HK$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
diff --git a/dojo/cldr/nls/en-us/number.js b/dojo/cldr/nls/en-us/number.js
deleted file mode 100644
index 6052262..0000000
--- a/dojo/cldr/nls/en-us/number.js
+++ /dev/null
@@ -1 +0,0 @@
-({"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":" ","currencySpac [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/en/currency.js b/dojo/cldr/nls/en/currency.js
index 20d9524..8ee34ae 100644
--- a/dojo/cldr/nls/en/currency.js
+++ b/dojo/cldr/nls/en/currency.js
@@ -1 +1,15 @@
-({"HKD_displayName":"Hong Kong Dollar","CHF_displayName":"Swiss Franc","JPY_symbol":"¥","CAD_displayName":"Canadian Dollar","CNY_displayName":"Chinese Yuan Renminbi","USD_symbol":"$","AUD_displayName":"Australian Dollar","JPY_displayName":"Japanese Yen","USD_displayName":"US Dollar","GBP_displayName":"British Pound Sterling","EUR_displayName":"Euro","CHF_symbol":"Fr.","HKD_symbol":"HK$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Australian Dollar",
+	CAD_displayName:"Canadian Dollar",
+	CHF_displayName:"Swiss Franc",
+	CNY_displayName:"Chinese Yuan Renminbi",
+	EUR_displayName:"Euro",
+	GBP_displayName:"British Pound Sterling",
+	HKD_displayName:"Hong Kong Dollar",
+	JPY_displayName:"Japanese Yen",
+	JPY_symbol:"¥",
+	USD_displayName:"US Dollar",
+	USD_symbol:"$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/en/gregorian.js b/dojo/cldr/nls/en/gregorian.js
index 4ed86f9..8262b0f 100644
--- a/dojo/cldr/nls/en/gregorian.js
+++ b/dojo/cldr/nls/en/gregorian.js
@@ -1 +1,225 @@
-({"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","dateTimeFormat-full":"{1} {0}","field-weekday":"Day of the Week","dateFormatItem-yQQQ":"QQQ y","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"],"dateTime [...]
\ No newline at end of file
+({
+	"dateFormatItem-yM": "M/y", 
+	"field-dayperiod": "AM/PM", 
+	"dayPeriods-format-wide-pm": "PM", 
+	"dateFormatItem-yQ": "Q y", 
+	"field-minute": "Minute", 
+	"eraNames": [
+		"Before Christ", 
+		"Anno Domini"
+	], 
+	"dateFormatItem-MMMEd": "E, MMM d", 
+	"dateTimeFormat-full": "{1} {0}", 
+	"field-day-relative+-1": "Yesterday", 
+	"dateFormatItem-hms": "h:mm:ss a", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"field-weekday": "Day of the Week", 
+	"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"
+	], 
+	"dateTimeFormat-short": "{1} {0}", 
+	"dayPeriods-format-wide-am": "AM", 
+	"dateTimeFormat-medium": "{1} {0}", 
+	"field-era": "Era", 
+	"field-hour": "Hour", 
+	"dateFormatItem-y": "y", 
+	"timeFormat-full": "h:mm:ss a zzzz", 
+	"months-standAlone-abbr": [
+		"Jan", 
+		"Feb", 
+		"Mar", 
+		"Apr", 
+		"May", 
+		"Jun", 
+		"Jul", 
+		"Aug", 
+		"Sep", 
+		"Oct", 
+		"Nov", 
+		"Dec"
+	], 
+	"dateFormatItem-yMMM": "MMM y", 
+	"field-day-relative+0": "Today", 
+	"days-standAlone-narrow": [
+		"S", 
+		"M", 
+		"T", 
+		"W", 
+		"T", 
+		"F", 
+		"S"
+	], 
+	"field-day-relative+1": "Tomorrow", 
+	"eraAbbr": [
+		"BC", 
+		"AD"
+	], 
+	"dateFormat-long": "MMMM d, y", 
+	"timeFormat-medium": "h:mm:ss a", 
+	"dateFormatItem-EEEd": "d EEE", 
+	"field-zone": "Zone", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"dateFormat-medium": "MMM d, y", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"quarters-standAlone-wide": [
+		"1st quarter", 
+		"2nd quarter", 
+		"3rd quarter", 
+		"4th quarter"
+	], 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-year": "Year", 
+	"quarters-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4"
+	], 
+	"dateTimeFormat-long": "{1} {0}", 
+	"field-week": "Week", 
+	"months-standAlone-wide": [
+		"January", 
+		"February", 
+		"March", 
+		"April", 
+		"May", 
+		"June", 
+		"July", 
+		"August", 
+		"September", 
+		"October", 
+		"November", 
+		"December"
+	], 
+	"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"
+	], 
+	"dayPeriods-format-wide-noon": "noon", 
+	"timeFormat-short": "h:mm a", 
+	"field-month": "Month", 
+	"quarters-format-abbr": [
+		"Q1", 
+		"Q2", 
+		"Q3", 
+		"Q4"
+	], 
+	"days-format-abbr": [
+		"Sun", 
+		"Mon", 
+		"Tue", 
+		"Wed", 
+		"Thu", 
+		"Fri", 
+		"Sat"
+	], 
+	"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", 
+	"days-standAlone-abbr": [
+		"Sun", 
+		"Mon", 
+		"Tue", 
+		"Wed", 
+		"Thu", 
+		"Fri", 
+		"Sat"
+	], 
+	"dateFormat-short": "M/d/yy", 
+	"dateFormatItem-yMMMEd": "EEE, MMM d, y", 
+	"dateFormat-full": "EEEE, MMMM d, y", 
+	"dateFormatItem-Md": "M/d", 
+	"dateFormatItem-yMEd": "EEE, M/d/y", 
+	"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"
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/en/number.js b/dojo/cldr/nls/en/number.js
index 92b2e32..2b73f19 100644
--- a/dojo/cldr/nls/en/number.js
+++ b/dojo/cldr/nls/en/number.js
@@ -1 +1,19 @@
-({"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":" ","currencySpac [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':".",
+	'group':",",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"¤#,##0.00;(¤#,##0.00)"
+})
diff --git a/dojo/cldr/nls/es-es/gregorian.js b/dojo/cldr/nls/es-es/gregorian.js
deleted file mode 100644
index f492831..0000000
--- a/dojo/cldr/nls/es-es/gregorian.js
+++ /dev/null
@@ -1 +0,0 @@
-({"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' y","m [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/es-es/number.js b/dojo/cldr/nls/es-es/number.js
deleted file mode 100644
index 89cefe8..0000000
--- a/dojo/cldr/nls/es-es/number.js
+++ /dev/null
@@ -1 +0,0 @@
-({"currencyFormat":"#,##0.00 ¤","group":".","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","minusSign":"-","decimal":",","nan":"NaN","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-afterCurrency-surroundingM [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/es/currency.js b/dojo/cldr/nls/es/currency.js
index 9b1ef69..d150af7 100644
--- a/dojo/cldr/nls/es/currency.js
+++ b/dojo/cldr/nls/es/currency.js
@@ -1 +1,13 @@
-({"HKD_displayName":"dólar de Hong Kong","CHF_displayName":"franco suizo","CAD_displayName":"dólar canadiense","CNY_displayName":"yuan renminbi chino","AUD_displayName":"dólar australiano","JPY_displayName":"yen japonés","USD_displayName":"dólar estadounidense","GBP_displayName":"libra esterlina británica","EUR_displayName":"euro","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"dólar australiano",
+	CAD_displayName:"dólar canadiense",
+	CHF_displayName:"franco suizo",
+	CNY_displayName:"yuan renminbi chino",
+	EUR_displayName:"euro",
+	GBP_displayName:"libra esterlina británica",
+	HKD_displayName:"dólar de Hong Kong",
+	JPY_displayName:"yen japonés",
+	USD_displayName:"dólar estadounidense"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/es/gregorian.js b/dojo/cldr/nls/es/gregorian.js
index 2a2a51f..7126948 100644
--- a/dojo/cldr/nls/es/gregorian.js
+++ b/dojo/cldr/nls/es/gregorian.js
@@ -1 +1,234 @@
-({"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' y","months-format-wide":["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septi [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"E", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"field-weekday": "día de la semana", 
+	"dateFormatItem-yyQQQQ": "QQQQ 'de' yy", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"dateFormatItem-yMEd": "EEE d/M/y", 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"eraNarrow": [
+		"a.C.", 
+		"d.C."
+	], 
+	"dateFormatItem-MMMdd": "dd-MMM", 
+	"dateFormat-long": "d 'de' MMMM 'de' y", 
+	"months-format-wide": [
+		"enero", 
+		"febrero", 
+		"marzo", 
+		"abril", 
+		"mayo", 
+		"junio", 
+		"julio", 
+		"agosto", 
+		"septiembre", 
+		"octubre", 
+		"noviembre", 
+		"diciembre"
+	], 
+	"dateFormatItem-EEEd": "EEE d", 
+	"dayPeriods-format-wide-pm": "p.m.", 
+	"dateFormat-full": "EEEE d 'de' MMMM 'de' y", 
+	"dateFormatItem-Md": "d/M", 
+	"field-era": "era", 
+	"dateFormatItem-yM": "M/y", 
+	"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"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"field-year": "año", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"dateFormatItem-yQ": "Q y", 
+	"field-hour": "hora", 
+	"months-format-abbr": [
+		"ene", 
+		"feb", 
+		"mar", 
+		"abr", 
+		"may", 
+		"jun", 
+		"jul", 
+		"ago", 
+		"sep", 
+		"oct", 
+		"nov", 
+		"dic"
+	], 
+	"dateFormatItem-yyQ": "Q yy", 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"field-day-relative+0": "hoy", 
+	"field-day-relative+1": "mañana", 
+	"field-day-relative+2": "pasado mañana", 
+	"field-day-relative+3": "Dentro de tres días", 
+	"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-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": "HH: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", 
+	"field-day-relative+-1": "ayer", 
+	"dateFormatItem-h": "hh a", 
+	"field-day-relative+-2": "antes de ayer", 
+	"field-day-relative+-3": "Hace tres días", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"dateFormatItem-MEd": "E, d/M", 
+	"dateFormatItem-yMMMM": "MMMM 'de' y", 
+	"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": "y", 
+	"months-standAlone-narrow": [
+		"E", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"dateFormatItem-yyMM": "MM/yy", 
+	"dateFormatItem-hm": "hh:mm a", 
+	"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", 
+	"dayPeriods-format-wide-am": "a.m.", 
+	"dateFormat-short": "dd/MM/yy", 
+	"dateFormatItem-MMd": "d/MM", 
+	"field-second": "segundo", 
+	"dateFormatItem-yMMMEd": "EEE, d MMM y", 
+	"field-week": "semana", 
+	"dateFormat-medium": "dd/MM/yyyy", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-hms": "hh:mm:ss a"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/es/number.js b/dojo/cldr/nls/es/number.js
index be433d8..4ca5f3c 100644
--- a/dojo/cldr/nls/es/number.js
+++ b/dojo/cldr/nls/es/number.js
@@ -1 +1,18 @@
-({"group":".","percentSign":"%","exponential":"E","percentFormat":"#,##0%","scientificFormat":"#E0","list":";","infinity":"∞","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-surroundingM [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':".",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"¤ #,##0.00"
+})
diff --git a/dojo/cldr/nls/fi/currency.js b/dojo/cldr/nls/fi/currency.js
index 42cc7dc..66a1277 100644
--- a/dojo/cldr/nls/fi/currency.js
+++ b/dojo/cldr/nls/fi/currency.js
@@ -1 +1,20 @@
-({"HKD_displayName":"Hongkongin dollari","CHF_displayName":"Sveitsin frangi","CHF_symbol":"CHF","JPY_symbol":"¥","HKD_symbol":"HKD","CAD_displayName":"Kanadan dollari","CNY_displayName":"Kiinan yuan","USD_symbol":"$","AUD_displayName":"Australian dollari","JPY_displayName":"Japanin jeni","CAD_symbol":"CAD","USD_displayName":"Yhdysvaltain dollari","CNY_symbol":"CNY","GBP_displayName":"Englannin punta","AUD_symbol":"AUD","EUR_displayName":"euro","EUR_symbol":"€","GBP_symbol":"£"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Australian dollari",
+	AUD_symbol:"AUD",
+	CAD_displayName:"Kanadan dollari",
+	CAD_symbol:"CAD",
+	CHF_displayName:"Sveitsin frangi",
+	CHF_symbol:"CHF",
+	CNY_displayName:"Kiinan yuan",
+	CNY_symbol:"CNY",
+	EUR_displayName:"euro",
+	GBP_displayName:"Englannin punta",
+	HKD_displayName:"Hongkongin dollari",
+	HKD_symbol:"HKD",
+	JPY_displayName:"Japanin jeni",
+	JPY_symbol:"¥",
+	USD_displayName:"Yhdysvaltain dollari",
+	USD_symbol:"$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/fi/gregorian.js b/dojo/cldr/nls/fi/gregorian.js
index b907a4f..b930b39 100644
--- a/dojo/cldr/nls/fi/gregorian.js
+++ b/dojo/cldr/nls/fi/gregorian.js
@@ -1 +1,235 @@
-({"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 y","dateFormatItem-yMEd":"EEE d.M.yyyy","dateFormatItem-MMMEd":"E d. MMM","eraNarrow":["eKr.","jKr."],"dateFormat-long":"d. MMMM y","months-format-wide":["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],"date [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"T", 
+		"H", 
+		"M", 
+		"H", 
+		"T", 
+		"K", 
+		"H", 
+		"E", 
+		"S", 
+		"L", 
+		"M", 
+		"J"
+	], 
+	"field-weekday": "viikonpäivä", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"dateFormatItem-yMEd": "EEE d.M.yyyy", 
+	"dateFormatItem-MMMEd": "E d. MMM", 
+	"eraNarrow": [
+		"eKr.", 
+		"jKr."
+	], 
+	"dateFormat-long": "d. MMMM y", 
+	"months-format-wide": [
+		"tammikuuta", 
+		"helmikuuta", 
+		"maaliskuuta", 
+		"huhtikuuta", 
+		"toukokuuta", 
+		"kesäkuuta", 
+		"heinäkuuta", 
+		"elokuuta", 
+		"syyskuuta", 
+		"lokakuuta", 
+		"marraskuuta", 
+		"joulukuuta"
+	], 
+	"dateFormatItem-EEEd": "EEE d.", 
+	"dayPeriods-format-wide-pm": "ip.", 
+	"dateFormat-full": "EEEE d. MMMM y", 
+	"dateFormatItem-Md": "d.M.", 
+	"dayPeriods-standAlone-wide-pm": "ip.", 
+	"dayPeriods-format-abbr-am": "ap.", 
+	"field-era": "aikakausi", 
+	"dateFormatItem-yM": "L.yyyy", 
+	"months-standAlone-wide": [
+		"tammikuu", 
+		"helmikuu", 
+		"maaliskuu", 
+		"huhtikuu", 
+		"toukokuu", 
+		"kesäkuu", 
+		"heinäkuu", 
+		"elokuu", 
+		"syyskuu", 
+		"lokakuu", 
+		"marraskuu", 
+		"joulukuu"
+	], 
+	"timeFormat-short": "H.mm", 
+	"quarters-format-wide": [
+		"1. neljännes", 
+		"2. neljännes", 
+		"3. neljännes", 
+		"4. neljännes"
+	], 
+	"timeFormat-long": "H.mm.ss z", 
+	"field-year": "vuosi", 
+	"dateFormatItem-yMMM": "LLL y", 
+	"dateFormatItem-yQ": "Q/yyyy", 
+	"dateFormatItem-yyyyMMMM": "LLLL y", 
+	"field-hour": "tunti", 
+	"months-format-abbr": [
+		"tammikuuta", 
+		"helmikuuta", 
+		"maaliskuuta", 
+		"huhtikuuta", 
+		"toukokuuta", 
+		"kesäkuuta", 
+		"heinäkuuta", 
+		"elokuuta", 
+		"syyskuuta", 
+		"lokakuuta", 
+		"marraskuuta", 
+		"joulukuuta"
+	], 
+	"dateFormatItem-yyQ": "Q/yy", 
+	"timeFormat-full": "H.mm.ss zzzz", 
+	"dateFormatItem-yyyyMEEEd": "EEE d.M.yyyy", 
+	"field-day-relative+0": "tänään", 
+	"field-day-relative+1": "huomenna", 
+	"field-day-relative+2": "ylihuomenna", 
+	"dateFormatItem-H": "H", 
+	"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-M": "L", 
+	"days-standAlone-wide": [
+		"sunnuntai", 
+		"maanantai", 
+		"tiistai", 
+		"keskiviikko", 
+		"torstai", 
+		"perjantai", 
+		"lauantai"
+	], 
+	"dateFormatItem-yyMMM": "LLLL 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", 
+	"field-day-relative+-1": "eilen", 
+	"field-day-relative+-2": "toissapäivänä", 
+	"dateFormatItem-MMMd": "d. MMM", 
+	"dateFormatItem-MEd": "E d.M.", 
+	"field-day": "päivä", 
+	"dateFormatItem-yMMMMccccd": "cccc, d. MMMM y", 
+	"days-format-wide": [
+		"sunnuntaina", 
+		"maanantaina", 
+		"tiistaina", 
+		"keskiviikkona", 
+		"torstaina", 
+		"perjantaina", 
+		"lauantaina"
+	], 
+	"field-zone": "aikavyöhyke", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"T", 
+		"H", 
+		"M", 
+		"H", 
+		"T", 
+		"K", 
+		"H", 
+		"E", 
+		"S", 
+		"L", 
+		"M", 
+		"J"
+	], 
+	"dateFormatItem-yyMM": "M/yy", 
+	"dateFormatItem-hm": "h.mm a", 
+	"dayPeriods-format-abbr-pm": "ip.", 
+	"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", 
+	"dayPeriods-format-wide-am": "ap.", 
+	"dayPeriods-standAlone-wide-am": "ap.", 
+	"dateFormat-short": "d.M.yyyy", 
+	"field-second": "sekunti", 
+	"dateFormatItem-yMMMEd": "EEE d. MMM y", 
+	"field-week": "viikko", 
+	"dateFormat-medium": "d.M.yyyy", 
+	"dateFormatItem-yyyyM": "M/yyyy", 
+	"dateFormatItem-yyyyQQQQ": "QQQQ y", 
+	"dateFormatItem-Hms": "H.mm.ss", 
+	"dateFormatItem-hms": "h.mm.ss a"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/fi/number.js b/dojo/cldr/nls/fi/number.js
index aa0fee6..4c1f6d4 100644
--- a/dojo/cldr/nls/fi/number.js
+++ b/dojo/cldr/nls/fi/number.js
@@ -1 +1,19 @@
-({"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-af [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':" ",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"epäluku",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0 %",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/fr/currency.js b/dojo/cldr/nls/fr/currency.js
index 3d3eabe..d539624 100644
--- a/dojo/cldr/nls/fr/currency.js
+++ b/dojo/cldr/nls/fr/currency.js
@@ -1 +1,21 @@
-({"HKD_displayName":"dollar de Hong Kong","CHF_displayName":"franc suisse","CHF_symbol":"CHF","JPY_symbol":"¥JP","HKD_symbol":"$HK","CAD_displayName":"dollar canadien","CNY_displayName":"yuan renminbi chinois","USD_symbol":"$US","AUD_displayName":"dollar australien","JPY_displayName":"yen japonais","CAD_symbol":"$CA","USD_displayName":"dollar des États-Unis","CNY_symbol":"Ұ","GBP_displayName":"livre sterling","GBP_symbol":"£UK","AUD_symbol":"$AU","EUR_displayName":"euro","EUR_symbol":"€"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"dollar australien",
+	AUD_symbol:"$AU",
+	CAD_displayName:"dollar canadien",
+	CAD_symbol:"$CA",
+	CHF_displayName:"franc suisse",
+	CHF_symbol:"CHF",
+	CNY_displayName:"yuan renminbi chinois",
+	CNY_symbol:"Ұ",
+	EUR_displayName:"euro",
+	GBP_displayName:"livre sterling",
+	GBP_symbol:"£UK",
+	HKD_displayName:"dollar de Hong Kong",
+	HKD_symbol:"$HK",
+	JPY_displayName:"yen japonais",
+	JPY_symbol:"¥JP",
+	USD_displayName:"dollar des États-Unis",
+	USD_symbol:"$US"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/fr/gregorian.js b/dojo/cldr/nls/fr/gregorian.js
index ea97b97..f835423 100644
--- a/dojo/cldr/nls/fr/gregorian.js
+++ b/dojo/cldr/nls/fr/gregorian.js
@@ -1 +1,243 @@
-({"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 y","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 y","months-format-wide":["janvier","février","mars","avril","mai","juin","juillet","août","septembre"," [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"J", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"field-weekday": "jour de la semaine", 
+	"dateFormatItem-yyQQQQ": "QQQQ yy", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"dateFormatItem-yMEd": "EEE d/M/yyyy", 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"eraNarrow": [
+		"av. J.-C.", 
+		"ap. J.-C."
+	], 
+	"dayPeriods-format-wide-morning": "matin", 
+	"dateFormatItem-MMMdd": "dd MMM", 
+	"dateFormat-long": "d MMMM y", 
+	"months-format-wide": [
+		"janvier", 
+		"février", 
+		"mars", 
+		"avril", 
+		"mai", 
+		"juin", 
+		"juillet", 
+		"août", 
+		"septembre", 
+		"octobre", 
+		"novembre", 
+		"décembre"
+	], 
+	"dateFormatItem-EEEd": "d EEE", 
+	"dayPeriods-format-wide-pm": "PM", 
+	"dateFormat-full": "EEEE d MMMM y", 
+	"dateFormatItem-Md": "d/M", 
+	"dayPeriods-format-wide-noon": "midi", 
+	"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"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"field-year": "année", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"dateFormatItem-yQ": "'T'Q y", 
+	"dateFormatItem-yyyyMMMM": "MMMM y", 
+	"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", 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"field-day-relative+0": "aujourd’hui", 
+	"field-day-relative+1": "demain", 
+	"field-day-relative+2": "après-demain", 
+	"field-day-relative+3": "après-après-demain", 
+	"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-M": "L", 
+	"days-standAlone-wide": [
+		"dimanche", 
+		"lundi", 
+		"mardi", 
+		"mercredi", 
+		"jeudi", 
+		"vendredi", 
+		"samedi"
+	], 
+	"dateFormatItem-yyMMMEEEd": "EEE d MMM yy", 
+	"dateFormatItem-yyMMM": "MMM yy", 
+	"timeFormat-medium": "HH:mm:ss", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"quarters-standAlone-abbr": [
+		"T1", 
+		"T2", 
+		"T3", 
+		"T4"
+	], 
+	"eraAbbr": [
+		"av. J.-C.", 
+		"ap. J.-C."
+	], 
+	"field-minute": "minute", 
+	"field-dayperiod": "cadran", 
+	"dayPeriods-format-wide-night": "soir", 
+	"days-standAlone-abbr": [
+		"dim.", 
+		"lun.", 
+		"mar.", 
+		"mer.", 
+		"jeu.", 
+		"ven.", 
+		"sam."
+	], 
+	"dateFormatItem-yyMMMd": "d MMM yy", 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm:ss", 
+	"quarters-format-narrow": [
+		"T1", 
+		"T2", 
+		"T3", 
+		"T4"
+	], 
+	"field-day-relative+-1": "hier", 
+	"field-day-relative+-2": "avant-hier", 
+	"field-day-relative+-3": "avant-avant-hier", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"dateFormatItem-MEd": "EEE d/M", 
+	"field-day": "jour", 
+	"days-format-wide": [
+		"dimanche", 
+		"lundi", 
+		"mardi", 
+		"mercredi", 
+		"jeudi", 
+		"vendredi", 
+		"samedi"
+	], 
+	"field-zone": "fuseau horaire", 
+	"dateFormatItem-y": "y", 
+	"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", 
+	"dayPeriods-format-wide-am": "AM", 
+	"dateFormatItem-MMMMEd": "EEE d MMMM", 
+	"dateFormat-short": "dd/MM/yy", 
+	"dateFormatItem-MMd": "d/MM", 
+	"dayPeriods-format-wide-afternoon": "après-midi", 
+	"field-second": "seconde", 
+	"dateFormatItem-yMMMEd": "EEE d MMM y", 
+	"field-week": "semaine", 
+	"dateFormat-medium": "d MMM y", 
+	"dateFormatItem-Hms": "HH:mm:ss"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/fr/number.js b/dojo/cldr/nls/fr/number.js
index f9a71ab..33c9d64 100644
--- a/dojo/cldr/nls/fr/number.js
+++ b/dojo/cldr/nls/fr/number.js
@@ -1 +1,19 @@
-({"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-afterC [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':" ",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0 %",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/gregorian.js b/dojo/cldr/nls/gregorian.js
index d8beca5..c7a7186 100644
--- a/dojo/cldr/nls/gregorian.js
+++ b/dojo/cldr/nls/gregorian.js
@@ -1 +1,253 @@
-({"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":"y QQQ","dateFormatItem-yMEd":"EEE, y-M-d","dateFormatItem-MMMEd":"E MMM d","eraNarrow":["BCE","CE"],"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateFormat-long":"y MMMM d","months-format-wide":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateTimeFormat-medium":"{1} {0}","dateFormatItem-EEEd": [...]
\ No newline at end of file
+({
+	"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": "y QQQ", 
+	"dateFormatItem-yMEd": "EEE, y-M-d", 
+	"dateFormatItem-MMMEd": "E MMM d", 
+	"eraNarrow": [
+		"BCE", 
+		"CE"
+	], 
+	"dateTimeFormats-appendItem-Day-Of-Week": "{0} {1}", 
+	"dateFormat-long": "y MMMM d", 
+	"months-format-wide": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"dateTimeFormat-medium": "{1} {0}", 
+	"dateFormatItem-EEEd": "d EEE", 
+	"dayPeriods-format-wide-pm": "PM", 
+	"dateFormat-full": "EEEE, y MMMM dd", 
+	"dateFormatItem-Md": "M-d", 
+	"dayPeriods-format-abbr-am": "AM", 
+	"dateTimeFormats-appendItem-Second": "{0} ({2}: {1})", 
+	"field-era": "Era", 
+	"dateFormatItem-yM": "y-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"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"field-year": "Year", 
+	"dateFormatItem-yMMM": "y MMM", 
+	"dateFormatItem-yQ": "y Q", 
+	"dateTimeFormats-appendItem-Era": "{0} {1}", 
+	"field-hour": "Hour", 
+	"months-format-abbr": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"dateTimeFormats-appendItem-Week": "{0} ({2}: {1})", 
+	"field-day-relative+0": "Today", 
+	"field-day-relative+1": "Tomorrow", 
+	"dateFormatItem-H": "HH", 
+	"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"
+	], 
+	"timeFormat-medium": "HH:mm:ss", 
+	"dateFormatItem-Hm": "HH: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"
+	], 
+	"field-day-relative+-1": "Yesterday", 
+	"dateFormatItem-h": "h a", 
+	"dateTimeFormat-long": "{1} {0}", 
+	"dayPeriods-format-narrow-am": "AM", 
+	"dateFormatItem-MMMd": "MMM d", 
+	"dateFormatItem-MEd": "E, M-d", 
+	"dateTimeFormat-full": "{1} {0}", 
+	"field-day": "Day", 
+	"days-format-wide": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"field-zone": "Zone", 
+	"dateTimeFormats-appendItem-Day": "{0} ({2}: {1})", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"dateFormatItem-hm": "h:mm a", 
+	"dateTimeFormats-appendItem-Year": "{0} {1}", 
+	"dateTimeFormats-appendItem-Hour": "{0} ({2}: {1})", 
+	"dayPeriods-format-abbr-pm": "PM", 
+	"days-format-abbr": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"eraNames": [
+		"BCE", 
+		"CE"
+	], 
+	"days-format-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"days-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"field-month": "Month", 
+	"dateTimeFormats-appendItem-Quarter": "{0} ({2}: {1})", 
+	"dayPeriods-format-wide-am": "AM", 
+	"dateTimeFormats-appendItem-Month": "{0} ({2}: {1})", 
+	"dateTimeFormats-appendItem-Minute": "{0} ({2}: {1})", 
+	"dateFormat-short": "yyyy-MM-dd", 
+	"field-second": "Second", 
+	"dateFormatItem-yMMMEd": "EEE, y MMM d", 
+	"dateTimeFormats-appendItem-Timezone": "{0} {1}", 
+	"field-week": "Week", 
+	"dateFormat-medium": "y MMM d", 
+	"dayPeriods-format-narrow-pm": "PM", 
+	"dateTimeFormat-short": "{1} {0}", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-hms": "h:mm:ss a"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/he/currency.js b/dojo/cldr/nls/he/currency.js
index 85d7c6c..d0a7e38 100644
--- a/dojo/cldr/nls/he/currency.js
+++ b/dojo/cldr/nls/he/currency.js
@@ -1 +1,13 @@
-({"HKD_displayName":"דולר הונג קונגי","CHF_displayName":"פרנק שוויצרי","CAD_displayName":"דולר קנדי","CNY_displayName":"יואן רנמינבי סיני","AUD_displayName":"דולר אוסטרלי","JPY_displayName":"ין יפני","USD_displayName":"דולר אמריקאי","GBP_displayName":"לירה שטרלינג","EUR_displayName":"אירו","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"דולר אוסטרלי",
+	CAD_displayName:"דולר קנדי",
+	CHF_displayName:"פרנק שוויצרי",
+	CNY_displayName:"יואן רנמינבי סיני",
+	EUR_displayName:"אירו",
+	GBP_displayName:"לירה שטרלינג",
+	HKD_displayName:"דולר הונג קונגי",
+	JPY_displayName:"ין יפני",
+	USD_displayName:"דולר אמריקאי"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/he/gregorian.js b/dojo/cldr/nls/he/gregorian.js
index af48452..3e74dfe 100644
--- a/dojo/cldr/nls/he/gregorian.js
+++ b/dojo/cldr/nls/he/gregorian.js
@@ -1 +1,209 @@
-({"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"יום בשבוע","dateFormatItem-yQQQ":"y QQQ","dateFormatItem-yMEd":"EEE, d.M.yyyy","dateFormatItem-MMMEd":"E d MMM","eraNarrow":["לפנה״ס","לסה״נ"],"dateFormat-long":"d בMMMM y","months-format-wide":["ינואר","פברואר","מרס","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],"dateTimeFormat-medium":"{1} {0}","dateFormat-full":"EEEE, d בMMMM y","dateFormatItem-Md":"d/M","field-era":"תקופה","dateFormatItem-yM [...]
\ No newline at end of file
+({
+	"field-weekday": "יום בשבוע", 
+	"dateFormatItem-yQQQ": "y QQQ", 
+	"dateFormatItem-yMEd": "EEE, d.M.yyyy", 
+	"dateFormatItem-MMMEd": "E, d בMMM", 
+	"eraNarrow": [
+		"לפנה״ס", 
+		"לסה״נ"
+	], 
+	"dateFormat-long": "d בMMMM y", 
+	"months-format-wide": [
+		"ינואר", 
+		"פברואר", 
+		"מרס", 
+		"אפריל", 
+		"מאי", 
+		"יוני", 
+		"יולי", 
+		"אוגוסט", 
+		"ספטמבר", 
+		"אוקטובר", 
+		"נובמבר", 
+		"דצמבר"
+	], 
+	"dateFormatItem-EEEd": "EEE ה-d", 
+	"dayPeriods-format-wide-pm": "אחה״צ", 
+	"dateFormat-full": "EEEE, d בMMMM y", 
+	"dateFormatItem-Md": "d/M", 
+	"field-era": "תקופה", 
+	"dateFormatItem-yM": "M.yyyy", 
+	"months-standAlone-wide": [
+		"ינואר", 
+		"פברואר", 
+		"מרס", 
+		"אפריל", 
+		"מאי", 
+		"יוני", 
+		"יולי", 
+		"אוגוסט", 
+		"ספטמבר", 
+		"אוקטובר", 
+		"נובמבר", 
+		"דצמבר"
+	], 
+	"timeFormat-short": "HH:mm", 
+	"quarters-format-wide": [
+		"רבעון 1", 
+		"רבעון 2", 
+		"רבעון 3", 
+		"רבעון 4"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"field-year": "שנה", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"dateFormatItem-yQ": "yyyy Q", 
+	"dateFormatItem-yyyyMMMM": "MMMM y", 
+	"field-hour": "שעה", 
+	"dateFormatItem-MMdd": "dd/MM", 
+	"months-format-abbr": [
+		"ינו", 
+		"פבר", 
+		"מרס", 
+		"אפר", 
+		"מאי", 
+		"יונ", 
+		"יול", 
+		"אוג", 
+		"ספט", 
+		"אוק", 
+		"נוב", 
+		"דצמ"
+	], 
+	"dateFormatItem-yyQ": "Q yy", 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"field-day-relative+0": "היום", 
+	"field-day-relative+1": "מחר", 
+	"field-day-relative+2": "מחרתיים", 
+	"dateFormatItem-H": "HH", 
+	"field-day-relative+3": "בעוד שלושה ימים", 
+	"months-standAlone-abbr": [
+		"ינו׳", 
+		"פבר׳", 
+		"מרס", 
+		"אפר׳", 
+		"מאי", 
+		"יונ׳", 
+		"יול׳", 
+		"אוג׳", 
+		"ספט׳", 
+		"אוק׳", 
+		"נוב׳", 
+		"דצמ׳"
+	], 
+	"quarters-standAlone-wide": [
+		"רבעון 1", 
+		"רבעון 2", 
+		"רבעון 3", 
+		"רבעון 4"
+	], 
+	"quarters-format-abbr": [
+		"רבעון 1", 
+		"רבעון 2", 
+		"רבעון 3", 
+		"רבעון 4"
+	], 
+	"dateFormatItem-M": "L", 
+	"days-standAlone-wide": [
+		"יום ראשון", 
+		"יום שני", 
+		"יום שלישי", 
+		"יום רביעי", 
+		"יום חמישי", 
+		"יום שישי", 
+		"יום שבת"
+	], 
+	"dateFormatItem-MMMMd": "d בMMMM", 
+	"dateFormatItem-yyMMM": "MMM yyyy", 
+	"timeFormat-medium": "HH:mm:ss", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"quarters-standAlone-abbr": [
+		"רבעון 1", 
+		"רבעון 2", 
+		"רבעון 3", 
+		"רבעון 4"
+	], 
+	"eraAbbr": [
+		"לפנה״ס", 
+		"לסה״נ"
+	], 
+	"field-minute": "דקה", 
+	"field-dayperiod": "לפה״צ/אחה״צ", 
+	"days-standAlone-abbr": [
+		"יום א׳", 
+		"יום ב׳", 
+		"יום ג׳", 
+		"יום ד׳", 
+		"יום ה׳", 
+		"יום ו׳", 
+		"שבת"
+	], 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "אתמול", 
+	"field-day-relative+-2": "שלשום", 
+	"field-day-relative+-3": "לפני שלושה ימים", 
+	"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": "y", 
+	"dateFormatItem-yyMM": "MM/yy", 
+	"dateFormatItem-hm": "h:mm a", 
+	"days-format-abbr": [
+		"יום א׳", 
+		"יום ב׳", 
+		"יום ג׳", 
+		"יום ד׳", 
+		"יום ה׳", 
+		"יום ו׳", 
+		"שבת"
+	], 
+	"eraNames": [
+		"לפני הספירה", 
+		"לספירה"
+	], 
+	"days-format-narrow": [
+		"א", 
+		"ב", 
+		"ג", 
+		"ד", 
+		"ה", 
+		"ו", 
+		"ש"
+	], 
+	"field-month": "חודש", 
+	"days-standAlone-narrow": [
+		"א", 
+		"ב", 
+		"ג", 
+		"ד", 
+		"ה", 
+		"ו", 
+		"ש"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dayPeriods-format-wide-am": "לפנה״צ", 
+	"dateFormatItem-MMMMEd": "E, d בMMMM", 
+	"dateFormat-short": "dd/MM/yy", 
+	"field-second": "שנייה", 
+	"dateFormatItem-yMMMEd": "EEE, d בMMM y", 
+	"dateFormatItem-Ed": "E ה-d", 
+	"field-week": "שבוע", 
+	"dateFormat-medium": "d בMMM yyyy", 
+	"dateFormatItem-mmss": "mm:ss", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-hms": "h:mm:ss a", 
+	"dateFormatItem-yyyy": "y"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/he/hebrew.js b/dojo/cldr/nls/he/hebrew.js
index 570b58e..7a9e0ba 100644
--- a/dojo/cldr/nls/he/hebrew.js
+++ b/dojo/cldr/nls/he/hebrew.js
@@ -1 +1,121 @@
-({"quarters-format-abbr":["רבעון 1","רבעון 2","רבעון 3","רבעון 4"],"dateFormat-medium":"dd/MM/yyyy","dateFormatItem-MMMEd":"E d MMM","dateFormatItem-yMEd":"EEE, d.M.yyyy","eraNarrow":["לבה\"ע"],"months-format-narrow":["תשרי","חשון","כסלו","טבת","שבט","אדר א'","אדר","ניסן","אייר","סיון","תמוז","אב","אלול"],"pm":"אחה\"צ","dateFormatItem-Md":"d/M","months-standAlone-narrow":["תשרי","חשון","כסלו","טבת","שבט","אדר א'","אדר","ניסן","אייר","סיון","תמוז","אב","אלול"],"months-standAlone-wide":["ת [...]
\ No newline at end of file
+({
+	"dateFormat-medium": "dd/MM/yyyy", 
+	"dateFormatItem-MMMEd": "E, d בMMM", 
+	"dateFormatItem-yMEd": "EEE, d.M.yyyy", 
+	"eraNarrow": [
+		"לבה״ע"
+	], 
+	"dateFormatItem-Md": "d/M", 
+	"months-standAlone-wide": [
+		"תשרי", 
+		"חשון", 
+		"כסלו", 
+		"טבת", 
+		"שבט", 
+		"אדר א׳", 
+		"אדר", 
+		"ניסן", 
+		"אייר", 
+		"סיון", 
+		"תמוז", 
+		"אב", 
+		"אלול"
+	], 
+	"months-format-wide-leap": "אדר ב׳", 
+	"dateFormatItem-EEEd": "EEE ה-d", 
+	"eraNames": [
+		"לבה״ע"
+	], 
+	"dateFormatItem-MMMMEd": "E, d בMMMM", 
+	"days-standAlone-narrow": [
+		"א", 
+		"ב", 
+		"ג", 
+		"ד", 
+		"ה", 
+		"ו", 
+		"ש"
+	], 
+	"dayPeriods-format-wide-pm": "אחה״צ", 
+	"months-standAlone-abbr": [
+		"תשרי", 
+		"חשון", 
+		"כסלו", 
+		"טבת", 
+		"שבט", 
+		"אדר א׳", 
+		"אדר", 
+		"ניסן", 
+		"אייר", 
+		"סיון", 
+		"תמוז", 
+		"אב", 
+		"אלול"
+	], 
+	"dayPeriods-format-wide-am": "לפנה״צ", 
+	"dateFormat-long": "d בMMMM y", 
+	"dateFormat-short": "dd/MM/yy", 
+	"dateFormatItem-yMMMEd": "EEE, d בMMM y", 
+	"months-format-wide": [
+		"תשרי", 
+		"חשון", 
+		"כסלו", 
+		"טבת", 
+		"שבט", 
+		"אדר א׳", 
+		"אדר", 
+		"ניסן", 
+		"אייר", 
+		"סיון", 
+		"תמוז", 
+		"אב", 
+		"אלול"
+	], 
+	"dateFormatItem-yM": "M.yyyy", 
+	"months-format-abbr": [
+		"תשרי", 
+		"חשון", 
+		"כסלו", 
+		"טבת", 
+		"שבט", 
+		"אדר א׳", 
+		"אדר", 
+		"ניסן", 
+		"אייר", 
+		"סיון", 
+		"תמוז", 
+		"אב", 
+		"אלול"
+	], 
+	"eraAbbr": [
+		"לבה״ע"
+	], 
+	"days-format-wide": [
+		"יום ראשון", 
+		"יום שני", 
+		"יום שלישי", 
+		"יום רביעי", 
+		"יום חמישי", 
+		"יום שישי", 
+		"יום שבת"
+	], 
+	"dateFormatItem-yQ": "yyyy Q", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"quarters-format-wide": [
+		"רבעון 1", 
+		"רבעון 2", 
+		"רבעון 3", 
+		"רבעון 4"
+	], 
+	"dateFormat-full": "EEEE, d בMMMM y", 
+	"dateFormatItem-MMMd": "d בMMM", 
+	"days-format-abbr": [
+		"יום א׳", 
+		"יום ב׳", 
+		"יום ג׳", 
+		"יום ד׳", 
+		"יום ה׳", 
+		"יום ו׳", 
+		"שבת"
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/he/islamic.js b/dojo/cldr/nls/he/islamic.js
index 0e5de97..59119d0 100644
--- a/dojo/cldr/nls/he/islamic.js
+++ b/dojo/cldr/nls/he/islamic.js
@@ -1 +1,115 @@
-({"quarters-format-abbr":["רבעון 1","רבעון 2","רבעון 3","רבעון 4"],"dateFormat-medium":"dd/MM/yyyy","dateFormatItem-MMMEd":"E d MMM","dateFormatItem-yMEd":"EEE, d.M.yyyy","eraNarrow":["שנת היג׳רה"],"dateFormatItem-Md":"d/M","months-standAlone-wide":["מוחרם","ספר","רביע אל-אוואל","רביע אל-תני","ג׳ומדה אל-אוואל","ג׳ומדה אל-תני","רג׳אב","שעבאן","ראמדן","שוואל","זו אל-QI'DAH","זו אל-חיג׳ה"],"eraNames":["שנת היג׳רה"],"days-standAlone-narrow":["א","ב","ג","ד","ה","ו","ש"],"dateFormatItem-MMMMd [...]
\ No newline at end of file
+({
+	"dateFormat-medium": "d בMMM yyyy", 
+	"dateFormatItem-MMMEd": "E, d בMMM", 
+	"dateFormatItem-yMEd": "EEE, d.M.yyyy", 
+	"eraNarrow": [
+		"שנת היג׳רה"
+	], 
+	"dateFormatItem-Md": "d/M", 
+	"months-standAlone-wide": [
+		"מוחרם", 
+		"ספר", 
+		"רביע אל-אוואל", 
+		"רביע אל-תני", 
+		"ג׳ומדה אל-אוואל", 
+		"ג׳ומדה אל-תני", 
+		"רג׳אב", 
+		"שעבאן", 
+		"ראמדן", 
+		"שוואל", 
+		"זו אל-QI'DAH", 
+		"זו אל-חיג׳ה"
+	], 
+	"dateFormatItem-EEEd": "EEE ה-d", 
+	"eraNames": [
+		"שנת היג׳רה"
+	], 
+	"days-standAlone-narrow": [
+		"א", 
+		"ב", 
+		"ג", 
+		"ד", 
+		"ה", 
+		"ו", 
+		"ש"
+	], 
+	"dayPeriods-format-wide-pm": "אחה״צ", 
+	"months-standAlone-abbr": [
+		"מוחרם", 
+		"ספר", 
+		"רביע אל-אוואל", 
+		"רביע אל-תני", 
+		"ג׳ומדה אל-אוואל", 
+		"ג׳ומדה אל-תני", 
+		"רג׳אב", 
+		"שעבאן", 
+		"ראמדן", 
+		"שוואל", 
+		"זו אל-QI'DAH", 
+		"זו אל-חיג׳ה"
+	], 
+	"dayPeriods-format-wide-am": "לפנה״צ", 
+	"dateFormat-long": "d בMMMM y", 
+	"dateFormat-short": "dd/MM/yy", 
+	"dateFormatItem-yMMMEd": "EEE, d בMMM y", 
+	"months-format-wide": [
+		"מוחרם", 
+		"ספר", 
+		"רביע אל-אוואל", 
+		"רביע אל-תני", 
+		"ג׳ומדה אל-אוואל", 
+		"ג׳ומדה אל-תני", 
+		"רג׳אב", 
+		"שעבאן", 
+		"ראמדן", 
+		"שוואל", 
+		"זו אל-QI'DAH", 
+		"זו אל-חיג׳ה"
+	], 
+	"dateFormatItem-yM": "M.yyyy", 
+	"months-format-abbr": [
+		"מוחרם", 
+		"ספר", 
+		"רביע אל-אוואל", 
+		"רביע אל-תני", 
+		"ג׳ומדה אל-אוואל", 
+		"ג׳ומדה אל-תני", 
+		"רג׳אב", 
+		"שעבאן", 
+		"ראמדן", 
+		"שוואל", 
+		"זו אל-QI'DAH", 
+		"זו אל-חיג׳ה"
+	], 
+	"eraAbbr": [
+		"שנת היג׳רה"
+	], 
+	"days-format-wide": [
+		"יום ראשון", 
+		"יום שני", 
+		"יום שלישי", 
+		"יום רביעי", 
+		"יום חמישי", 
+		"יום שישי", 
+		"יום שבת"
+	], 
+	"dateFormatItem-yQ": "yyyy Q", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"quarters-format-wide": [
+		"רבעון 1", 
+		"רבעון 2", 
+		"רבעון 3", 
+		"רבעון 4"
+	], 
+	"dateFormat-full": "EEEE, d בMMMM y", 
+	"dateFormatItem-MMMd": "d בMMM", 
+	"days-format-abbr": [
+		"יום א׳", 
+		"יום ב׳", 
+		"יום ג׳", 
+		"יום ד׳", 
+		"יום ה׳", 
+		"יום ו׳", 
+		"שבת"
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/he/number.js b/dojo/cldr/nls/he/number.js
index 23e6fa4..aac6735 100644
--- a/dojo/cldr/nls/he/number.js
+++ b/dojo/cldr/nls/he/number.js
@@ -1 +1,19 @@
-({"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-afterCu [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':".",
+	'group':",",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/hebrew.js b/dojo/cldr/nls/hebrew.js
index dbcf40a..4ed106d 100644
--- a/dojo/cldr/nls/hebrew.js
+++ b/dojo/cldr/nls/hebrew.js
@@ -1 +1,248 @@
-({"dateFormatItem-yM":"y-M","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateFormatItem-yQ":"y Q","eraNames":["AM"],"dateFormatItem-MMMEd":"E MMM d","dateTimeFormat-full":"{1} {0}","dateFormatItem-hms":"h:mm:ss a","dateFormatItem-yQQQ":"y QQQ","days-standAlone-wide":["1","2","3","4","5","6","7"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["1","2","3","4","5","6","7","8","9","10","11","12","13"],"dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormat-short":"{1} {0 [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"Tishri", 
+		"Heshvan", 
+		"Kislev", 
+		"Tevet", 
+		"Shevat", 
+		"Adar I", 
+		"Adar", 
+		"Nisan", 
+		"Iyar", 
+		"Sivan", 
+		"Tamuz", 
+		"Av", 
+		"Elul"
+	], 
+	"quarters-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4"
+	], 
+	"dateFormatItem-yQQQ": "y QQQ", 
+	"months-standAlone-narrow-leap": "Adar II", 
+	"dateFormatItem-yMEd": "EEE, y-M-d", 
+	"dateFormatItem-MMMEd": "E MMM d", 
+	"eraNarrow": [
+		"AM"
+	], 
+	"dateTimeFormats-appendItem-Day-Of-Week": "{0} {1}", 
+	"dateFormat-long": "y MMMM d", 
+	"months-format-wide": [
+		"Tishri", 
+		"Heshvan", 
+		"Kislev", 
+		"Tevet", 
+		"Shevat", 
+		"Adar I", 
+		"Adar", 
+		"Nisan", 
+		"Iyar", 
+		"Sivan", 
+		"Tamuz", 
+		"Av", 
+		"Elul"
+	], 
+	"dateTimeFormat-medium": "{1} {0}", 
+	"dateFormatItem-EEEd": "d EEE", 
+	"dayPeriods-format-wide-pm": "PM", 
+	"dateFormat-full": "EEEE, y MMMM dd", 
+	"dateFormatItem-Md": "M-d", 
+	"dayPeriods-format-abbr-am": "AM", 
+	"dateTimeFormats-appendItem-Second": "{0} ({2}: {1})", 
+	"dateFormatItem-yM": "y-M", 
+	"months-standAlone-wide": [
+		"Tishri", 
+		"Heshvan", 
+		"Kislev", 
+		"Tevet", 
+		"Shevat", 
+		"Adar I", 
+		"Adar", 
+		"Nisan", 
+		"Iyar", 
+		"Sivan", 
+		"Tamuz", 
+		"Av", 
+		"Elul"
+	], 
+	"timeFormat-short": "HH:mm", 
+	"quarters-format-wide": [
+		"Q1", 
+		"Q2", 
+		"Q3", 
+		"Q4"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"dateFormatItem-yMMM": "y MMM", 
+	"dateFormatItem-yQ": "y Q", 
+	"dateTimeFormats-appendItem-Era": "{0} {1}", 
+	"months-format-abbr-leap": "Adar II", 
+	"months-format-abbr": [
+		"Tishri", 
+		"Heshvan", 
+		"Kislev", 
+		"Tevet", 
+		"Shevat", 
+		"Adar I", 
+		"Adar", 
+		"Nisan", 
+		"Iyar", 
+		"Sivan", 
+		"Tamuz", 
+		"Av", 
+		"Elul"
+	], 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"dateTimeFormats-appendItem-Week": "{0} ({2}: {1})", 
+	"dateFormatItem-H": "HH", 
+	"months-standAlone-abbr": [
+		"Tishri", 
+		"Heshvan", 
+		"Kislev", 
+		"Tevet", 
+		"Shevat", 
+		"Adar I", 
+		"Adar", 
+		"Nisan", 
+		"Iyar", 
+		"Sivan", 
+		"Tamuz", 
+		"Av", 
+		"Elul"
+	], 
+	"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"
+	], 
+	"months-standAlone-wide-leap": "Adar II", 
+	"timeFormat-medium": "HH:mm:ss", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"quarters-standAlone-abbr": [
+		"Q1", 
+		"Q2", 
+		"Q3", 
+		"Q4"
+	], 
+	"months-format-narrow-leap": "Adar II", 
+	"eraAbbr": [
+		"AM"
+	], 
+	"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-h": "h a", 
+	"dateTimeFormat-long": "{1} {0}", 
+	"dayPeriods-format-narrow-am": "AM", 
+	"dateFormatItem-MMMd": "MMM d", 
+	"dateFormatItem-MEd": "E, M-d", 
+	"dateTimeFormat-full": "{1} {0}", 
+	"days-format-wide": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"months-standAlone-abbr-leap": "Adar II", 
+	"dateTimeFormats-appendItem-Day": "{0} ({2}: {1})", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"Tishri", 
+		"Heshvan", 
+		"Kislev", 
+		"Tevet", 
+		"Shevat", 
+		"Adar I", 
+		"Adar", 
+		"Nisan", 
+		"Iyar", 
+		"Sivan", 
+		"Tamuz", 
+		"Av", 
+		"Elul"
+	], 
+	"dateFormatItem-hm": "h:mm a", 
+	"dateTimeFormats-appendItem-Year": "{0} {1}", 
+	"dateTimeFormats-appendItem-Hour": "{0} ({2}: {1})", 
+	"dayPeriods-format-abbr-pm": "PM", 
+	"days-format-abbr": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"eraNames": [
+		"AM"
+	], 
+	"days-format-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"days-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dateTimeFormats-appendItem-Quarter": "{0} ({2}: {1})", 
+	"dayPeriods-format-wide-am": "AM", 
+	"dateTimeFormats-appendItem-Month": "{0} ({2}: {1})", 
+	"dateTimeFormats-appendItem-Minute": "{0} ({2}: {1})", 
+	"dateFormat-short": "yyyy-MM-dd", 
+	"dateFormatItem-yMMMEd": "EEE, y MMM d", 
+	"dateTimeFormats-appendItem-Timezone": "{0} {1}", 
+	"dateFormat-medium": "y MMM d", 
+	"dayPeriods-format-narrow-pm": "PM", 
+	"dateTimeFormat-short": "{1} {0}", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-hms": "h:mm:ss a", 
+	"months-format-wide-leap": "Adar II"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/hu/currency.js b/dojo/cldr/nls/hu/currency.js
index 0d768b2..fc8ac15 100644
--- a/dojo/cldr/nls/hu/currency.js
+++ b/dojo/cldr/nls/hu/currency.js
@@ -1 +1,15 @@
-({"HKD_displayName":"Hongkongi dollár","CHF_displayName":"Svájci frank","JPY_symbol":"¥","CAD_displayName":"Kanadai dollár","CNY_displayName":"Kínai jüan renminbi","USD_symbol":"$","AUD_displayName":"Ausztrál dollár","JPY_displayName":"Japán jen","USD_displayName":"USA dollár","GBP_displayName":"Brit font sterling","EUR_displayName":"Euro","CHF_symbol":"Fr.","HKD_symbol":"HK$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Ausztrál dollár",
+	CAD_displayName:"Kanadai dollár",
+	CHF_displayName:"Svájci frank",
+	CNY_displayName:"Kínai jüan renminbi",
+	EUR_displayName:"Euro",
+	GBP_displayName:"Brit font sterling",
+	HKD_displayName:"Hongkongi dollár",
+	JPY_displayName:"Japán jen",
+	JPY_symbol:"¥",
+	USD_displayName:"USA dollár",
+	USD_symbol:"$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/hu/gregorian.js b/dojo/cldr/nls/hu/gregorian.js
index 90e8cb4..d091582 100644
--- a/dojo/cldr/nls/hu/gregorian.js
+++ b/dojo/cldr/nls/hu/gregorian.js
@@ -1 +1,219 @@
-({"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","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 zzzz","month [...]
\ No newline at end of file
+({
+	"field-dayperiod": "napszak", 
+	"dayPeriods-format-wide-pm": "du.", 
+	"field-minute": "perc", 
+	"eraNames": [
+		"időszámításunk előtt", 
+		"időszámításunk szerint"
+	], 
+	"field-day-relative+-1": "tegnap", 
+	"dateFormatItem-MMdd": "MM.dd.", 
+	"field-day-relative+-2": "tegnapelőtt", 
+	"field-weekday": "hét napja", 
+	"field-day-relative+-3": "három nappal ezelőtt", 
+	"days-standAlone-wide": [
+		"vasárnap", 
+		"hétfő", 
+		"kedd", 
+		"szerda", 
+		"csütörtök", 
+		"péntek", 
+		"szombat"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"months-standAlone-narrow": [
+		"J", 
+		"F", 
+		"M", 
+		"Á", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"Sz", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"dayPeriods-format-wide-am": "de.", 
+	"field-era": "éra", 
+	"field-hour": "óra", 
+	"quarters-standAlone-abbr": [
+		"N1", 
+		"N2", 
+		"N3", 
+		"N4"
+	], 
+	"timeFormat-full": "H:mm:ss zzzz", 
+	"months-standAlone-abbr": [
+		"jan.", 
+		"febr.", 
+		"márc.", 
+		"ápr.", 
+		"máj.", 
+		"jún.", 
+		"júl.", 
+		"aug.", 
+		"szept.", 
+		"okt.", 
+		"nov.", 
+		"dec."
+	], 
+	"field-day-relative+0": "ma", 
+	"days-standAlone-narrow": [
+		"V", 
+		"H", 
+		"K", 
+		"Sz", 
+		"Cs", 
+		"P", 
+		"Sz"
+	], 
+	"field-day-relative+1": "holnap", 
+	"eraAbbr": [
+		"i. e.", 
+		"i. sz."
+	], 
+	"field-day-relative+2": "holnapután", 
+	"field-day-relative+3": "három nap múlva", 
+	"dateFormatItem-yyyyMM": "yyyy.MM", 
+	"dateFormatItem-yyyyMMMM": "y. MMMM", 
+	"dateFormat-long": "y. MMMM d.", 
+	"timeFormat-medium": "H:mm:ss", 
+	"field-zone": "zóna", 
+	"dateFormatItem-Hm": "H:mm", 
+	"dateFormat-medium": "yyyy.MM.dd.", 
+	"dateFormatItem-Hms": "H:mm:ss", 
+	"quarters-standAlone-wide": [
+		"I. negyedév", 
+		"II. negyedév", 
+		"III. negyedév", 
+		"IV. negyedév"
+	], 
+	"field-year": "év", 
+	"field-week": "hét", 
+	"months-standAlone-wide": [
+		"január", 
+		"február", 
+		"március", 
+		"április", 
+		"május", 
+		"június", 
+		"július", 
+		"augusztus", 
+		"szeptember", 
+		"október", 
+		"november", 
+		"december"
+	], 
+	"dateFormatItem-MMMd": "MMM d.", 
+	"dateFormatItem-yyQ": "yy/Q", 
+	"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", 
+	"dateFormatItem-H": "H", 
+	"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"
+	], 
+	"dateFormatItem-mmss": "mm:ss", 
+	"dateFormatItem-M": "L", 
+	"days-format-narrow": [
+		"V", 
+		"H", 
+		"K", 
+		"Sz", 
+		"Cs", 
+		"P", 
+		"Sz"
+	], 
+	"field-second": "másodperc", 
+	"field-day": "nap", 
+	"dateFormatItem-MEd": "M. d., E", 
+	"months-format-narrow": [
+		"J", 
+		"F", 
+		"M", 
+		"Á", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"Sz", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"days-standAlone-abbr": [
+		"V", 
+		"H", 
+		"K", 
+		"Sze", 
+		"Cs", 
+		"P", 
+		"Szo"
+	], 
+	"dateFormat-short": "yyyy.MM.dd.", 
+	"dateFormat-full": "y. MMMM d., EEEE", 
+	"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."
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/hu/number.js b/dojo/cldr/nls/hu/number.js
index 472a2c8..0dff8f1 100644
--- a/dojo/cldr/nls/hu/number.js
+++ b/dojo/cldr/nls/hu/number.js
@@ -1 +1,18 @@
-({"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": [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':" ",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/islamic-civil.js b/dojo/cldr/nls/islamic-civil.js
deleted file mode 100644
index 6f9d07d..0000000
--- a/dojo/cldr/nls/islamic-civil.js
+++ /dev/null
@@ -1 +0,0 @@
-({"months-format-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"quarters-standAlone-narrow":["1","2","3","4"],"*@localeAlias195":{"bundle":"islamic","target":"*"},"dateFormatItem-yQQQ":"y QQQ","dateFormatItem-yMEd":"EEE, y-M-d","dateFormatItem-MMMEd":"E MMM d","eraNarrow":["AH"],"eraNames at localeAlias213":{"bundle":"islamic","target":"eraAbbr"},"dateFormat at localeAlias215":{"bundle":"gregorian","target":"dateFormat"},"dateTimeFormats-appendItem-Day-Of-Week":"{0} {1}","dateFo [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/islamic.js b/dojo/cldr/nls/islamic.js
index 5fc0dd7..7f131c4 100644
--- a/dojo/cldr/nls/islamic.js
+++ b/dojo/cldr/nls/islamic.js
@@ -1 +1,236 @@
-({"dateFormatItem-yM":"y-M","dateTimeFormats-appendItem-Second":"{0} ({2}: {1})","dateFormatItem-yQ":"y Q","eraNames":["AH"],"dateFormatItem-MMMEd":"E MMM d","dateTimeFormat-full":"{1} {0}","dateFormatItem-hms":"h:mm:ss a","dateFormatItem-yQQQ":"y QQQ","days-standAlone-wide":["1","2","3","4","5","6","7"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"dateTimeFormats-appendItem-Year":"{0} {1}","dateTimeFormat-short":"{1} {0}","d [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"quarters-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4"
+	], 
+	"dateFormatItem-yQQQ": "y QQQ", 
+	"dateFormatItem-yMEd": "EEE, y-M-d", 
+	"dateFormatItem-MMMEd": "E MMM d", 
+	"eraNarrow": [
+		"AH"
+	], 
+	"dateTimeFormats-appendItem-Day-Of-Week": "{0} {1}", 
+	"dateFormat-long": "y MMMM d", 
+	"months-format-wide": [
+		"Muharram", 
+		"Safar", 
+		"Rabiʻ I", 
+		"Rabiʻ II", 
+		"Jumada I", 
+		"Jumada II", 
+		"Rajab", 
+		"Shaʻban", 
+		"Ramadan", 
+		"Shawwal", 
+		"Dhuʻl-Qiʻdah", 
+		"Dhuʻl-Hijjah"
+	], 
+	"dateTimeFormat-medium": "{1} {0}", 
+	"dateFormatItem-EEEd": "d EEE", 
+	"dayPeriods-format-wide-pm": "PM", 
+	"dateFormat-full": "EEEE, y MMMM dd", 
+	"dateFormatItem-Md": "M-d", 
+	"dayPeriods-format-abbr-am": "AM", 
+	"dateTimeFormats-appendItem-Second": "{0} ({2}: {1})", 
+	"dateFormatItem-yM": "y-M", 
+	"months-standAlone-wide": [
+		"Muharram", 
+		"Safar", 
+		"Rabiʻ I", 
+		"Rabiʻ II", 
+		"Jumada I", 
+		"Jumada II", 
+		"Rajab", 
+		"Shaʻban", 
+		"Ramadan", 
+		"Shawwal", 
+		"Dhuʻl-Qiʻdah", 
+		"Dhuʻl-Hijjah"
+	], 
+	"timeFormat-short": "HH:mm", 
+	"quarters-format-wide": [
+		"Q1", 
+		"Q2", 
+		"Q3", 
+		"Q4"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"dateFormatItem-yMMM": "y MMM", 
+	"dateFormatItem-yQ": "y Q", 
+	"dateTimeFormats-appendItem-Era": "{0} {1}", 
+	"months-format-abbr": [
+		"Muh.", 
+		"Saf.", 
+		"Rab. I", 
+		"Rab. II", 
+		"Jum. I", 
+		"Jum. II", 
+		"Raj.", 
+		"Sha.", 
+		"Ram.", 
+		"Shaw.", 
+		"Dhuʻl-Q.", 
+		"Dhuʻl-H."
+	], 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"dateTimeFormats-appendItem-Week": "{0} ({2}: {1})", 
+	"dateFormatItem-H": "HH", 
+	"months-standAlone-abbr": [
+		"Muh.", 
+		"Saf.", 
+		"Rab. I", 
+		"Rab. II", 
+		"Jum. I", 
+		"Jum. II", 
+		"Raj.", 
+		"Sha.", 
+		"Ram.", 
+		"Shaw.", 
+		"Dhuʻl-Q.", 
+		"Dhuʻl-H."
+	], 
+	"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"
+	], 
+	"timeFormat-medium": "HH:mm:ss", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"quarters-standAlone-abbr": [
+		"Q1", 
+		"Q2", 
+		"Q3", 
+		"Q4"
+	], 
+	"eraAbbr": [
+		"AH"
+	], 
+	"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-h": "h a", 
+	"dateTimeFormat-long": "{1} {0}", 
+	"dayPeriods-format-narrow-am": "AM", 
+	"dateFormatItem-MMMd": "MMM d", 
+	"dateFormatItem-MEd": "E, M-d", 
+	"dateTimeFormat-full": "{1} {0}", 
+	"days-format-wide": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"dateTimeFormats-appendItem-Day": "{0} ({2}: {1})", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"dateFormatItem-hm": "h:mm a", 
+	"dateTimeFormats-appendItem-Year": "{0} {1}", 
+	"dateTimeFormats-appendItem-Hour": "{0} ({2}: {1})", 
+	"dayPeriods-format-abbr-pm": "PM", 
+	"days-format-abbr": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"eraNames": [
+		"AH"
+	], 
+	"days-format-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"days-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dateTimeFormats-appendItem-Quarter": "{0} ({2}: {1})", 
+	"dayPeriods-format-wide-am": "AM", 
+	"dateTimeFormats-appendItem-Month": "{0} ({2}: {1})", 
+	"dateTimeFormats-appendItem-Minute": "{0} ({2}: {1})", 
+	"dateFormat-short": "yyyy-MM-dd", 
+	"dateFormatItem-yMMMEd": "EEE, y MMM d", 
+	"dateTimeFormats-appendItem-Timezone": "{0} {1}", 
+	"dateFormat-medium": "y MMM d", 
+	"dayPeriods-format-narrow-pm": "PM", 
+	"dateTimeFormat-short": "{1} {0}", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-hms": "h:mm:ss a"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/it-it/gregorian.js b/dojo/cldr/nls/it-it/gregorian.js
deleted file mode 100644
index c59394e..0000000
--- a/dojo/cldr/nls/it-it/gregorian.js
+++ /dev/null
@@ -1 +0,0 @@
-({"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 y","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 [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/it/currency.js b/dojo/cldr/nls/it/currency.js
index 3bde233..2ea10ba 100644
--- a/dojo/cldr/nls/it/currency.js
+++ b/dojo/cldr/nls/it/currency.js
@@ -1 +1,13 @@
-({"HKD_displayName":"Dollaro di Hong Kong","CHF_displayName":"Franco Svizzero","CAD_displayName":"Dollaro Canadese","CNY_displayName":"Renmimbi Cinese","AUD_displayName":"Dollaro Australiano","JPY_displayName":"Yen Giapponese","USD_displayName":"Dollaro Statunitense","GBP_displayName":"Sterlina Inglese","EUR_displayName":"Euro","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Dollaro Australiano",
+	CAD_displayName:"Dollaro Canadese",
+	CHF_displayName:"Franco Svizzero",
+	CNY_displayName:"Renmimbi Cinese",
+	EUR_displayName:"Euro",
+	GBP_displayName:"Sterlina Inglese",
+	HKD_displayName:"Dollaro di Hong Kong",
+	JPY_displayName:"Yen Giapponese",
+	USD_displayName:"Dollaro Statunitense"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/it/gregorian.js b/dojo/cldr/nls/it/gregorian.js
index 73f655e..237bdb4 100644
--- a/dojo/cldr/nls/it/gregorian.js
+++ b/dojo/cldr/nls/it/gregorian.js
@@ -1 +1,230 @@
-({"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 y","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- [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"G", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"G", 
+		"L", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"field-weekday": "giorno della settimana", 
+	"dateFormatItem-yyQQQQ": "QQQQ yy", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"dateFormatItem-yMEd": "EEE, d/M/y", 
+	"dateFormatItem-MMMEd": "EEE d MMM", 
+	"eraNarrow": [
+		"aC", 
+		"dC"
+	], 
+	"dateFormat-long": "dd MMMM y", 
+	"months-format-wide": [
+		"gennaio", 
+		"febbraio", 
+		"marzo", 
+		"aprile", 
+		"maggio", 
+		"giugno", 
+		"luglio", 
+		"agosto", 
+		"settembre", 
+		"ottobre", 
+		"novembre", 
+		"dicembre"
+	], 
+	"dayPeriods-format-wide-pm": "p.", 
+	"dateFormat-full": "EEEE d MMMM y", 
+	"dateFormatItem-Md": "d/M", 
+	"field-era": "era", 
+	"dateFormatItem-yM": "M/y", 
+	"months-standAlone-wide": [
+		"Gennaio", 
+		"Febbraio", 
+		"Marzo", 
+		"Aprile", 
+		"Maggio", 
+		"Giugno", 
+		"Luglio", 
+		"Agosto", 
+		"Settembre", 
+		"Ottobre", 
+		"Novembre", 
+		"Dicembre"
+	], 
+	"timeFormat-short": "HH:mm", 
+	"quarters-format-wide": [
+		"1o trimestre", 
+		"2o trimestre", 
+		"3o trimestre", 
+		"4o trimestre"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"field-year": "anno", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"dateFormatItem-yQ": "Q-yyyy", 
+	"dateFormatItem-yyyyMMMM": "MMMM y", 
+	"field-hour": "ora", 
+	"dateFormatItem-MMdd": "dd/MM", 
+	"months-format-abbr": [
+		"gen", 
+		"feb", 
+		"mar", 
+		"apr", 
+		"mag", 
+		"giu", 
+		"lug", 
+		"ago", 
+		"set", 
+		"ott", 
+		"nov", 
+		"dic"
+	], 
+	"dateFormatItem-yyQ": "Q yy", 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"field-day-relative+0": "oggi", 
+	"field-day-relative+1": "domani", 
+	"field-day-relative+2": "dopodomani", 
+	"field-day-relative+3": "tra tre giorni", 
+	"months-standAlone-abbr": [
+		"gen", 
+		"feb", 
+		"mar", 
+		"apr", 
+		"mag", 
+		"giu", 
+		"lug", 
+		"ago", 
+		"set", 
+		"ott", 
+		"nov", 
+		"dic"
+	], 
+	"quarters-format-abbr": [
+		"T1", 
+		"T2", 
+		"T3", 
+		"T4"
+	], 
+	"quarters-standAlone-wide": [
+		"1o trimestre", 
+		"2o trimestre", 
+		"3o trimestre", 
+		"4o trimestre"
+	], 
+	"dateFormatItem-M": "L", 
+	"days-standAlone-wide": [
+		"Domenica", 
+		"Lunedì", 
+		"Martedì", 
+		"Mercoledì", 
+		"Giovedì", 
+		"Venerdì", 
+		"Sabato"
+	], 
+	"timeFormat-medium": "HH:mm:ss", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"quarters-standAlone-abbr": [
+		"T1", 
+		"T2", 
+		"T3", 
+		"T4"
+	], 
+	"eraAbbr": [
+		"aC", 
+		"dC"
+	], 
+	"field-minute": "minuto", 
+	"field-dayperiod": "periodo del giorno", 
+	"days-standAlone-abbr": [
+		"dom", 
+		"lun", 
+		"mar", 
+		"mer", 
+		"gio", 
+		"ven", 
+		"sab"
+	], 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "ieri", 
+	"dateFormatItem-h": "hh a", 
+	"field-day-relative+-2": "l'altro ieri", 
+	"field-day-relative+-3": "tre giorni fa", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"dateFormatItem-MEd": "EEE d/M", 
+	"field-day": "giorno", 
+	"days-format-wide": [
+		"domenica", 
+		"lunedì", 
+		"martedì", 
+		"mercoledì", 
+		"giovedì", 
+		"venerdì", 
+		"sabato"
+	], 
+	"field-zone": "zona", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"G", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"G", 
+		"L", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"dateFormatItem-yyMM": "MM/yy", 
+	"dateFormatItem-hm": "hh:mm a", 
+	"days-format-abbr": [
+		"dom", 
+		"lun", 
+		"mar", 
+		"mer", 
+		"gio", 
+		"ven", 
+		"sab"
+	], 
+	"eraNames": [
+		"a.C.", 
+		"d.C"
+	], 
+	"days-format-narrow": [
+		"D", 
+		"L", 
+		"M", 
+		"M", 
+		"G", 
+		"V", 
+		"S"
+	], 
+	"field-month": "mese", 
+	"days-standAlone-narrow": [
+		"D", 
+		"L", 
+		"M", 
+		"M", 
+		"G", 
+		"V", 
+		"S"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dayPeriods-format-wide-am": "m.", 
+	"dateFormatItem-MMMMdd": "dd MMMM", 
+	"dateFormat-short": "dd/MM/yy", 
+	"field-second": "secondo", 
+	"dateFormatItem-yMMMEd": "EEE d MMM y", 
+	"field-week": "settimana", 
+	"dateFormat-medium": "dd/MMM/y", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-hms": "hh:mm:ss a"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/it/number.js b/dojo/cldr/nls/it/number.js
index d878fb3..3b94127 100644
--- a/dojo/cldr/nls/it/number.js
+++ b/dojo/cldr/nls/it/number.js
@@ -1 +1,9 @@
-({"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:]","currencySpacin [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':".",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"¤ #,##0.00"
+})
diff --git a/dojo/cldr/nls/ja-jp/number.js b/dojo/cldr/nls/ja-jp/number.js
deleted file mode 100644
index 4329dc1..0000000
--- a/dojo/cldr/nls/ja-jp/number.js
+++ /dev/null
@@ -1 +0,0 @@
-({"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 [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/ja/currency.js b/dojo/cldr/nls/ja/currency.js
index e408a6c..43d9ec5 100644
--- a/dojo/cldr/nls/ja/currency.js
+++ b/dojo/cldr/nls/ja/currency.js
@@ -1 +1,16 @@
-({"HKD_displayName":"香港ドル","CHF_displayName":"スイス フラン","JPY_symbol":"¥","CAD_displayName":"カナダ ドル","CNY_displayName":"中国人民元","USD_symbol":"$","AUD_displayName":"オーストラリア ドル","JPY_displayName":"日本円","USD_displayName":"米ドル","CNY_symbol":"元","GBP_displayName":"英国ポンド","EUR_displayName":"ユーロ","CHF_symbol":"Fr.","HKD_symbol":"HK$","CAD_symbol":"CA$","EUR_symbol":"€","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"オーストラリア ドル",
+	CAD_displayName:"カナダ ドル",
+	CHF_displayName:"スイス フラン",
+	CNY_displayName:"中国人民元",
+	CNY_symbol:"元",
+	EUR_displayName:"ユーロ",
+	GBP_displayName:"英国ポンド",
+	HKD_displayName:"香港ドル",
+	JPY_displayName:"日本円",
+	JPY_symbol:"¥",
+	USD_displayName:"米ドル",
+	USD_symbol:"$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/ja/gregorian.js b/dojo/cldr/nls/ja/gregorian.js
index 47d9ab7..372f6c9 100644
--- a/dojo/cldr/nls/ja/gregorian.js
+++ b/dojo/cldr/nls/ja/gregorian.js
@@ -1 +1,218 @@
-({"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"曜日","dateFormatItem-yQQQ":"yQQQ","dateFormatItem-yMEd":"y/M/d(EEE)","dateFormatItem-MMMEd":"M月d日(E)","eraNarrow":["紀元前","西暦"],"dateFormat-long":"y年M月d日","months-format-wide":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateTimeFormat-medium":"{1} {0}","dateFormat-full":"y年M月d日EEEE","dateFormatItem-Md":"M/d","dateFormatItem-yMd":"y/M/d","field-era":"時代","dateFormatItem-yM":"y/M","months-standAlone-wide" [...]
\ No newline at end of file
+({
+	"field-weekday": "曜日", 
+	"dateFormatItem-yQQQ": "yQQQ", 
+	"dateFormatItem-yMEd": "y/M/d(EEE)", 
+	"dateFormatItem-MMMEd": "M月d日(E)", 
+	"eraNarrow": [
+		"BC", 
+		"AD"
+	], 
+	"dateFormat-long": "y年M月d日", 
+	"months-format-wide": [
+		"1月", 
+		"2月", 
+		"3月", 
+		"4月", 
+		"5月", 
+		"6月", 
+		"7月", 
+		"8月", 
+		"9月", 
+		"10月", 
+		"11月", 
+		"12月"
+	], 
+	"dateTimeFormat-medium": "{1} {0}", 
+	"dayPeriods-format-wide-pm": "午後", 
+	"dateFormat-full": "y年M月d日EEEE", 
+	"dateFormatItem-Md": "M/d", 
+	"dateFormatItem-yMd": "y/M/d", 
+	"field-era": "時代", 
+	"dateFormatItem-yM": "y/M", 
+	"months-standAlone-wide": [
+		"1月", 
+		"2月", 
+		"3月", 
+		"4月", 
+		"5月", 
+		"6月", 
+		"7月", 
+		"8月", 
+		"9月", 
+		"10月", 
+		"11月", 
+		"12月"
+	], 
+	"timeFormat-short": "H:mm", 
+	"quarters-format-wide": [
+		"第1四半期", 
+		"第2四半期", 
+		"第3四半期", 
+		"第4四半期"
+	], 
+	"timeFormat-long": "H:mm:ss z", 
+	"field-year": "年", 
+	"dateFormatItem-yMMM": "y年M月", 
+	"dateFormatItem-yQ": "y/Q", 
+	"field-hour": "時", 
+	"dateFormatItem-MMdd": "MM/dd", 
+	"dateFormatItem-yyQ": "yy/Q", 
+	"months-format-abbr": [
+		"1月", 
+		"2月", 
+		"3月", 
+		"4月", 
+		"5月", 
+		"6月", 
+		"7月", 
+		"8月", 
+		"9月", 
+		"10月", 
+		"11月", 
+		"12月"
+	], 
+	"timeFormat-full": "H時mm分ss秒 zzzz", 
+	"field-day-relative+0": "今日", 
+	"field-day-relative+1": "明日", 
+	"field-day-relative+2": "明後日", 
+	"dateFormatItem-H": "H時", 
+	"field-day-relative+3": "3日後", 
+	"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": [
+		"第1四半期", 
+		"第2四半期", 
+		"第3四半期", 
+		"第4四半期"
+	], 
+	"dateFormatItem-M": "L", 
+	"days-standAlone-wide": [
+		"日曜日", 
+		"月曜日", 
+		"火曜日", 
+		"水曜日", 
+		"木曜日", 
+		"金曜日", 
+		"土曜日"
+	], 
+	"dateFormatItem-yyMMM": "y年M月", 
+	"timeFormat-medium": "H:mm:ss", 
+	"dateFormatItem-Hm": "H:mm", 
+	"eraAbbr": [
+		"BC", 
+		"AD"
+	], 
+	"field-minute": "分", 
+	"field-dayperiod": "午前/午後", 
+	"days-standAlone-abbr": [
+		"日", 
+		"月", 
+		"火", 
+		"水", 
+		"木", 
+		"金", 
+		"土"
+	], 
+	"dateFormatItem-d": "d日", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "昨日", 
+	"dateFormatItem-h": "ah", 
+	"dateTimeFormat-long": "{1}{0}", 
+	"field-day-relative+-2": "一昨日", 
+	"field-day-relative+-3": "3日前", 
+	"dateFormatItem-MMMd": "M月d日", 
+	"dateFormatItem-MEd": "M/d(E)", 
+	"dateTimeFormat-full": "{1}{0}", 
+	"field-day": "日", 
+	"days-format-wide": [
+		"日曜日", 
+		"月曜日", 
+		"火曜日", 
+		"水曜日", 
+		"木曜日", 
+		"金曜日", 
+		"土曜日"
+	], 
+	"field-zone": "タイムゾーン", 
+	"dateFormatItem-yyyyMM": "yyyy/MM", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"dateFormatItem-hm": "ah:mm", 
+	"dateFormatItem-GGGGyMd": "GGGGy年M月d日", 
+	"days-format-abbr": [
+		"日", 
+		"月", 
+		"火", 
+		"水", 
+		"木", 
+		"金", 
+		"土"
+	], 
+	"dateFormatItem-yMMMd": "y年M月d日", 
+	"eraNames": [
+		"紀元前", 
+		"西暦"
+	], 
+	"days-format-narrow": [
+		"日", 
+		"月", 
+		"火", 
+		"水", 
+		"木", 
+		"金", 
+		"土"
+	], 
+	"field-month": "月", 
+	"days-standAlone-narrow": [
+		"日", 
+		"月", 
+		"火", 
+		"水", 
+		"木", 
+		"金", 
+		"土"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dayPeriods-format-wide-am": "午前", 
+	"dateFormat-short": "yy/MM/dd", 
+	"field-second": "秒", 
+	"dateFormatItem-yMMMEd": "y年M月d日(EEE)", 
+	"dateFormatItem-Ed": "d日(EEE)", 
+	"field-week": "週", 
+	"dateFormat-medium": "yyyy/MM/dd", 
+	"dateTimeFormat-short": "{1} {0}", 
+	"dateFormatItem-Hms": "H:mm:ss", 
+	"dateFormatItem-hms": "ah:mm:ss", 
+	"dateFormatItem-yyyy": "y年"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/ja/number.js b/dojo/cldr/nls/ja/number.js
index 90d87b9..018f6e8 100644
--- a/dojo/cldr/nls/ja/number.js
+++ b/dojo/cldr/nls/ja/number.js
@@ -1 +1,9 @@
-({"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 [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':".",
+	'group':",",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"¤#,##0.00"
+})
diff --git a/dojo/cldr/nls/ko-kr/gregorian.js b/dojo/cldr/nls/ko-kr/gregorian.js
deleted file mode 100644
index efd1ca9..0000000
--- a/dojo/cldr/nls/ko-kr/gregorian.js
+++ /dev/null
@@ -1 +0,0 @@
-({"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":"y년 QQQ","dateFormatItem-yMEd":"yyyy. M. d. EEE","dateFormatItem-MMMEd":"MMM d일 (E)","eraNarrow":["기원전","서기"],"dateFormat-long":"y년 M월 d일","months-format-wide":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"dateTimeFormat-medium":"{1 [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/ko-kr/number.js b/dojo/cldr/nls/ko-kr/number.js
deleted file mode 100644
index 748ea80..0000000
--- a/dojo/cldr/nls/ko-kr/number.js
+++ /dev/null
@@ -1 +0,0 @@
-({"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-afterCur [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/ko/currency.js b/dojo/cldr/nls/ko/currency.js
index 60a7d03..e30ea1b 100644
--- a/dojo/cldr/nls/ko/currency.js
+++ b/dojo/cldr/nls/ko/currency.js
@@ -1 +1,13 @@
-({"HKD_displayName":"홍콩 달러","CHF_displayName":"스위스 프랑","CAD_displayName":"캐나다 달러","CNY_displayName":"중국 위안 인민폐","AUD_displayName":"호주 달러","JPY_displayName":"일본 엔화","USD_displayName":"미국 달러","GBP_displayName":"영국령 파운드 스털링","EUR_displayName":"유로화","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"호주 달러",
+	CAD_displayName:"캐나다 달러",
+	CHF_displayName:"스위스 프랑",
+	CNY_displayName:"중국 위안 인민폐",
+	EUR_displayName:"유로화",
+	GBP_displayName:"영국령 파운드 스털링",
+	HKD_displayName:"홍콩 달러",
+	JPY_displayName:"일본 엔화",
+	USD_displayName:"미국 달러"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/ko/gregorian.js b/dojo/cldr/nls/ko/gregorian.js
index e5581ef..06b27f8 100644
--- a/dojo/cldr/nls/ko/gregorian.js
+++ b/dojo/cldr/nls/ko/gregorian.js
@@ -1 +1,238 @@
-({"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. EEE","dateFormatItem-MMMEd":"MMM d일 (E)","eraNarrow":["기원전","서기"],"dateFormat-long":"y년 M월 d일","months-format-wide":["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"dateTimeFormat-medium":"{1} {0}","dateFormatItem-EEEd":"d일 EEE","dateFormat-full":"y년  [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"1월", 
+		"2월", 
+		"3월", 
+		"4월", 
+		"5월", 
+		"6월", 
+		"7월", 
+		"8월", 
+		"9월", 
+		"10월", 
+		"11월", 
+		"12월"
+	], 
+	"field-weekday": "요일", 
+	"dateFormatItem-yQQQ": "y년 QQQ", 
+	"dateFormatItem-yMEd": "yyyy. M. d. EEE", 
+	"dateFormatItem-MMMEd": "MMM d일 (E)", 
+	"eraNarrow": [
+		"기원전", 
+		"서기"
+	], 
+	"dateFormat-long": "y년 M월 d일", 
+	"months-format-wide": [
+		"1월", 
+		"2월", 
+		"3월", 
+		"4월", 
+		"5월", 
+		"6월", 
+		"7월", 
+		"8월", 
+		"9월", 
+		"10월", 
+		"11월", 
+		"12월"
+	], 
+	"dateTimeFormat-medium": "{1} {0}", 
+	"dateFormatItem-EEEd": "d일 EEE", 
+	"dayPeriods-format-wide-pm": "오후", 
+	"dateFormat-full": "y년 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분기"
+	], 
+	"timeFormat-long": "a h시 m분 s초 z", 
+	"field-year": "년", 
+	"dateFormatItem-yMMM": "y년 MMM", 
+	"dateFormatItem-yQ": "y년 Q분기", 
+	"field-hour": "시", 
+	"dateFormatItem-MMdd": "MM. dd", 
+	"dateFormatItem-yyQ": "yy년 Q분기", 
+	"months-format-abbr": [
+		"1월", 
+		"2월", 
+		"3월", 
+		"4월", 
+		"5월", 
+		"6월", 
+		"7월", 
+		"8월", 
+		"9월", 
+		"10월", 
+		"11월", 
+		"12월"
+	], 
+	"timeFormat-full": "a h시 m분 s초 zzzz", 
+	"field-day-relative+0": "오늘", 
+	"field-day-relative+1": "내일", 
+	"field-day-relative+2": "모레", 
+	"field-day-relative+3": "3일후", 
+	"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-yyMMM": "yy년 MMM", 
+	"timeFormat-medium": "a h:mm:ss", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"quarters-standAlone-abbr": [
+		"1분기", 
+		"2분기", 
+		"3분기", 
+		"4분기"
+	], 
+	"eraAbbr": [
+		"기원전", 
+		"서기"
+	], 
+	"field-minute": "분", 
+	"field-dayperiod": "오전/오후", 
+	"days-standAlone-abbr": [
+		"일", 
+		"월", 
+		"화", 
+		"수", 
+		"목", 
+		"금", 
+		"토"
+	], 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "어제", 
+	"dateFormatItem-h": "a h", 
+	"dateTimeFormat-long": "{1} {0}", 
+	"field-day-relative+-2": "그저께", 
+	"field-day-relative+-3": "그끄제", 
+	"dateFormatItem-MMMd": "MMM d일", 
+	"dateFormatItem-MEd": "M. d. (E)", 
+	"dateTimeFormat-full": "{1} {0}", 
+	"field-day": "일", 
+	"days-format-wide": [
+		"일요일", 
+		"월요일", 
+		"화요일", 
+		"수요일", 
+		"목요일", 
+		"금요일", 
+		"토요일"
+	], 
+	"field-zone": "시간대", 
+	"dateFormatItem-yyyyMM": "yyyy. MM", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"1월", 
+		"2월", 
+		"3월", 
+		"4월", 
+		"5월", 
+		"6월", 
+		"7월", 
+		"8월", 
+		"9월", 
+		"10월", 
+		"11월", 
+		"12월"
+	], 
+	"dateFormatItem-yyMM": "YY. M.", 
+	"dateFormatItem-hm": "a h:mm", 
+	"days-format-abbr": [
+		"일", 
+		"월", 
+		"화", 
+		"수", 
+		"목", 
+		"금", 
+		"토"
+	], 
+	"dateFormatItem-yMMMd": "y년 MMM d일", 
+	"eraNames": [
+		"서력기원전", 
+		"서력기원"
+	], 
+	"days-format-narrow": [
+		"일", 
+		"월", 
+		"화", 
+		"수", 
+		"목", 
+		"금", 
+		"토"
+	], 
+	"field-month": "월", 
+	"days-standAlone-narrow": [
+		"일", 
+		"월", 
+		"화", 
+		"수", 
+		"목", 
+		"금", 
+		"토"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dayPeriods-format-wide-am": "오전", 
+	"dateFormat-short": "yy. M. d.", 
+	"field-second": "초", 
+	"dateFormatItem-yMMMEd": "y년 MMM d일 EEE", 
+	"dateFormatItem-Ed": "d일 (E)", 
+	"field-week": "주", 
+	"dateFormat-medium": "yyyy. M. d.", 
+	"dateFormatItem-mmss": "mm:ss", 
+	"dateTimeFormat-short": "{1} {0}", 
+	"dateFormatItem-Hms": "H시 m분 s초", 
+	"dateFormatItem-hms": "a h:mm:ss"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/ko/number.js b/dojo/cldr/nls/ko/number.js
index b155b91..e06848f 100644
--- a/dojo/cldr/nls/ko/number.js
+++ b/dojo/cldr/nls/ko/number.js
@@ -1 +1,19 @@
-({"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-afterCur [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':".",
+	'group':",",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"¤#,##0.00"
+})
diff --git a/dojo/cldr/nls/nb/currency.js b/dojo/cldr/nls/nb/currency.js
index 88fcff8..569148f 100644
--- a/dojo/cldr/nls/nb/currency.js
+++ b/dojo/cldr/nls/nb/currency.js
@@ -1 +1,21 @@
-({"HKD_displayName":"Hongkong-dollar","CHF_displayName":"sveitsiske franc","CHF_symbol":"CHF","JPY_symbol":"JPY","CAD_displayName":"kanadiske dollar","CNY_displayName":"kinesiske yuan renminbi","USD_symbol":"USD","AUD_displayName":"australske dollar","JPY_displayName":"japanske yen","CAD_symbol":"CAD","USD_displayName":"amerikanske dollar","EUR_symbol":"EUR","CNY_symbol":"CNY","GBP_displayName":"britiske pund sterling","GBP_symbol":"GBP","AUD_symbol":"AUD","EUR_displayName":"euro","HKD_s [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"australske dollar",
+	AUD_symbol:"AUD",
+	CAD_displayName:"kanadiske dollar",
+	CAD_symbol:"CAD",
+	CHF_displayName:"sveitsiske franc",
+	CHF_symbol:"CHF",
+	CNY_displayName:"kinesiske yuan renminbi",
+	CNY_symbol:"CNY",
+	EUR_displayName:"euro",
+	EUR_symbol:"EUR",
+	GBP_displayName:"britiske pund sterling",
+	GBP_symbol:"GBP",
+	HKD_displayName:"Hongkong-dollar",
+	JPY_displayName:"japanske yen",
+	JPY_symbol:"JPY",
+	USD_displayName:"amerikanske dollar",
+	USD_symbol:"USD"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/nb/gregorian.js b/dojo/cldr/nls/nb/gregorian.js
index db0857b..7ca1300 100644
--- a/dojo/cldr/nls/nb/gregorian.js
+++ b/dojo/cldr/nls/nb/gregorian.js
@@ -1 +1,230 @@
-({"dateFormatItem-yM":"M yyyy","field-dayperiod":"AM/PM","dateFormatItem-yQ":"Q yyyy","field-minute":"minutt","eraNames":["f.Kr.","e.Kr."],"dateFormatItem-MMMEd":"E d. MMM","field-weekday":"ukedag","dateFormatItem-hms":"h.mm.ss a","dateFormatItem-yQQQ":"QQQ y","dateFormatItem-MMdd":"dd.MM","days-standAlone-wide":["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["J","F","M","A","M","J","J","A","S","O","N","D"],"field- [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"J", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"field-weekday": "ukedag", 
+	"dateFormatItem-yyQQQQ": "QQQQ yy", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"dateFormatItem-yMEd": "EEE d.M.yyyy", 
+	"dateFormatItem-MMMEd": "E d. MMM", 
+	"eraNarrow": [
+		"f.Kr.", 
+		"e.Kr."
+	], 
+	"dateFormat-long": "d. MMMM y", 
+	"months-format-wide": [
+		"januar", 
+		"februar", 
+		"mars", 
+		"april", 
+		"mai", 
+		"juni", 
+		"juli", 
+		"august", 
+		"september", 
+		"oktober", 
+		"november", 
+		"desember"
+	], 
+	"dateFormatItem-EEEd": "EEE d", 
+	"dayPeriods-format-wide-pm": "PM", 
+	"dateFormat-full": "EEEE d. MMMM y", 
+	"dateFormatItem-Md": "d.M.", 
+	"field-era": "tidsalder", 
+	"dateFormatItem-yM": "M y", 
+	"months-standAlone-wide": [
+		"januar", 
+		"februar", 
+		"mars", 
+		"april", 
+		"mai", 
+		"juni", 
+		"juli", 
+		"august", 
+		"september", 
+		"oktober", 
+		"november", 
+		"desember"
+	], 
+	"timeFormat-short": "HH:mm", 
+	"quarters-format-wide": [
+		"1. kvartal", 
+		"2. kvartal", 
+		"3. kvartal", 
+		"4. kvartal"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"field-year": "år", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"dateFormatItem-yQ": "Q yyyy", 
+	"dateFormatItem-yyyyMMMM": "MMMM y", 
+	"field-hour": "time", 
+	"dateFormatItem-MMdd": "dd.MM", 
+	"months-format-abbr": [
+		"jan.", 
+		"feb.", 
+		"mars", 
+		"apr.", 
+		"mai", 
+		"juni", 
+		"juli", 
+		"aug.", 
+		"sep.", 
+		"okt.", 
+		"nov.", 
+		"des."
+	], 
+	"dateFormatItem-yyQ": "Q yy", 
+	"timeFormat-full": "'kl'. HH:mm:ss zzzz", 
+	"field-day-relative+0": "i dag", 
+	"field-day-relative+1": "i morgen", 
+	"field-day-relative+2": "i overmorgen", 
+	"field-day-relative+3": "i overovermorgen", 
+	"months-standAlone-abbr": [
+		"jan.", 
+		"feb.", 
+		"mars", 
+		"apr.", 
+		"mai", 
+		"juni", 
+		"juli", 
+		"aug.", 
+		"sep.", 
+		"okt.", 
+		"nov.", 
+		"des."
+	], 
+	"quarters-format-abbr": [
+		"K1", 
+		"K2", 
+		"K3", 
+		"K4"
+	], 
+	"quarters-standAlone-wide": [
+		"1. kvartal", 
+		"2. kvartal", 
+		"3. kvartal", 
+		"4. kvartal"
+	], 
+	"dateFormatItem-M": "L", 
+	"days-standAlone-wide": [
+		"søndag", 
+		"mandag", 
+		"tirsdag", 
+		"onsdag", 
+		"torsdag", 
+		"fredag", 
+		"lørdag"
+	], 
+	"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": "minutt", 
+	"field-dayperiod": "AM/PM", 
+	"days-standAlone-abbr": [
+		"søn.", 
+		"man.", 
+		"tir.", 
+		"ons.", 
+		"tor.", 
+		"fre.", 
+		"lør."
+	], 
+	"dateFormatItem-d": "d.", 
+	"dateFormatItem-ms": "mm.ss", 
+	"field-day-relative+-1": "i går", 
+	"field-day-relative+-2": "i forgårs", 
+	"field-day-relative+-3": "i forforgårs", 
+	"dateFormatItem-MMMd": "d. MMM", 
+	"dateFormatItem-MEd": "E d.M", 
+	"field-day": "dag", 
+	"days-format-wide": [
+		"søndag", 
+		"mandag", 
+		"tirsdag", 
+		"onsdag", 
+		"torsdag", 
+		"fredag", 
+		"lørdag"
+	], 
+	"field-zone": "sone", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"J", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"dateFormatItem-yyMM": "MM.yy", 
+	"dateFormatItem-hm": "h:mm a", 
+	"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": "LLL", 
+	"dayPeriods-format-wide-am": "AM", 
+	"dateFormat-short": "dd.MM.yy", 
+	"field-second": "sekund", 
+	"dateFormatItem-yMMMEd": "EEE d. MMM y", 
+	"field-week": "uke", 
+	"dateFormat-medium": "d. MMM y", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-hms": "h:mm:ss a"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/nb/number.js b/dojo/cldr/nls/nb/number.js
index 2904b4b..6477bf6 100644
--- a/dojo/cldr/nls/nb/number.js
+++ b/dojo/cldr/nls/nb/number.js
@@ -1 +1,19 @@
-({"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-afterC [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':" ",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0 %",
+	'currencyFormat':"¤ #,##0.00"
+})
diff --git a/dojo/cldr/nls/nl/currency.js b/dojo/cldr/nls/nl/currency.js
index 67d39ea..5ca5f1c 100644
--- a/dojo/cldr/nls/nl/currency.js
+++ b/dojo/cldr/nls/nl/currency.js
@@ -1 +1,13 @@
-({"HKD_displayName":"Hongkongse dollar","CHF_displayName":"Zwitserse franc","CAD_displayName":"Canadese dollar","CNY_displayName":"Chinese yuan renminbi","AUD_displayName":"Australische dollar","JPY_displayName":"Japanse yen","USD_displayName":"Amerikaanse dollar","GBP_displayName":"Brits pond sterling","EUR_displayName":"Euro","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Australische dollar",
+	CAD_displayName:"Canadese dollar",
+	CHF_displayName:"Zwitserse franc",
+	CNY_displayName:"Chinese yuan renminbi",
+	EUR_displayName:"Euro",
+	GBP_displayName:"Brits pond sterling",
+	HKD_displayName:"Hongkongse dollar",
+	JPY_displayName:"Japanse yen",
+	USD_displayName:"Amerikaanse dollar"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/nl/gregorian.js b/dojo/cldr/nls/nl/gregorian.js
index 0e2d1dc..765d408 100644
--- a/dojo/cldr/nls/nl/gregorian.js
+++ b/dojo/cldr/nls/nl/gregorian.js
@@ -1 +1,228 @@
-({"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 y","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 [...]
\ No newline at end of file
+({
+	"dateFormatItem-yM": "M-y", 
+	"field-dayperiod": "AM/PM", 
+	"dayPeriods-format-wide-pm": "PM", 
+	"dateFormatItem-yQ": "Q yyyy", 
+	"field-minute": "Minuut", 
+	"eraNames": [
+		"Voor Christus", 
+		"na Christus"
+	], 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"field-day-relative+-1": "gisteren", 
+	"dateFormatItem-MMdd": "dd-MM", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"field-day-relative+-2": "eergisteren", 
+	"field-weekday": "Dag van de week", 
+	"field-day-relative+-3": "eereergisteren", 
+	"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"
+	], 
+	"dayPeriods-format-wide-am": "AM", 
+	"field-era": "Tijdperk", 
+	"field-hour": "Uur", 
+	"quarters-standAlone-abbr": [
+		"K1", 
+		"K2", 
+		"K3", 
+		"K4"
+	], 
+	"dateFormatItem-y": "y", 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"months-standAlone-abbr": [
+		"jan.", 
+		"feb.", 
+		"mrt.", 
+		"apr.", 
+		"mei", 
+		"jun.", 
+		"jul.", 
+		"aug.", 
+		"sep.", 
+		"okt.", 
+		"nov.", 
+		"dec."
+	], 
+	"dateFormatItem-yMMM": "MMM y", 
+	"field-day-relative+0": "vandaag", 
+	"days-standAlone-narrow": [
+		"Z", 
+		"M", 
+		"D", 
+		"W", 
+		"D", 
+		"V", 
+		"Z"
+	], 
+	"field-day-relative+1": "morgen", 
+	"eraAbbr": [
+		"v. Chr.", 
+		"n. Chr."
+	], 
+	"field-day-relative+2": "overmorgen", 
+	"field-day-relative+3": "overovermorgen", 
+	"dateFormatItem-yyyyMMMM": "MMMM y", 
+	"dateFormat-long": "d MMMM y", 
+	"timeFormat-medium": "HH:mm:ss", 
+	"field-zone": "Zone", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"dateFormatItem-MMd": "d-MM", 
+	"dateFormat-medium": "d MMM y", 
+	"dateFormatItem-yyMM": "MM-yy", 
+	"dateFormatItem-yyMMM": "MMM yy", 
+	"dateFormatItem-yyQQQQ": "QQQQ yy", 
+	"quarters-standAlone-wide": [
+		"1e kwartaal", 
+		"2e kwartaal", 
+		"3e kwartaal", 
+		"4e kwartaal"
+	], 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-year": "Jaar", 
+	"field-week": "Week", 
+	"months-standAlone-wide": [
+		"januari", 
+		"februari", 
+		"maart", 
+		"april", 
+		"mei", 
+		"juni", 
+		"juli", 
+		"augustus", 
+		"september", 
+		"oktober", 
+		"november", 
+		"december"
+	], 
+	"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"
+	], 
+	"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"
+	], 
+	"days-standAlone-abbr": [
+		"zo", 
+		"ma", 
+		"di", 
+		"wo", 
+		"do", 
+		"vr", 
+		"za"
+	], 
+	"dateFormat-short": "dd-MM-yy", 
+	"dateFormatItem-yMMMEd": "EEE d MMM y", 
+	"dateFormat-full": "EEEE d MMMM y", 
+	"dateFormatItem-Md": "d-M", 
+	"dateFormatItem-yMEd": "EEE d-M-y", 
+	"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."
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/nl/number.js b/dojo/cldr/nls/nl/number.js
index 6e47a0a..020b67b 100644
--- a/dojo/cldr/nls/nl/number.js
+++ b/dojo/cldr/nls/nl/number.js
@@ -1 +1,19 @@
-({"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":" ","currencySpa [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':".",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"¤ #,##0.00;¤ #,##0.00-"
+})
diff --git a/dojo/cldr/nls/number.js b/dojo/cldr/nls/number.js
index 8f76216..8c0abb6 100644
--- a/dojo/cldr/nls/number.js
+++ b/dojo/cldr/nls/number.js
@@ -1 +1,25 @@
-({"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":",","percen [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':".",
+	'group':",",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencySpacing-beforeCurrency-currencyMatch':"[:letter:]",
+	'currencySpacing-beforeCurrency-surroundingMatch':"[:digit:]",
+	'currencySpacing-beforeCurrency-insertBetween':" ",
+	'currencySpacing-afterCurrency-currencyMatch':"[:letter:]",
+	'currencySpacing-afterCurrency-surroundingMatch':"[:digit:]",
+	'currencySpacing-afterCurrency-insertBetween':" ",
+	'currencyFormat':"¤ #,##0.00"
+})
diff --git a/dojo/cldr/nls/pl/currency.js b/dojo/cldr/nls/pl/currency.js
index 6f0493c..2497f2b 100644
--- a/dojo/cldr/nls/pl/currency.js
+++ b/dojo/cldr/nls/pl/currency.js
@@ -1 +1,13 @@
-({"HKD_displayName":"dolar hongkoński","CHF_displayName":"frank szwajcarski","CAD_displayName":"dolar kanadyjski","CNY_displayName":"juan renminbi","AUD_displayName":"dolar australijski","JPY_displayName":"jen japoński","USD_displayName":"dolar amerykański ","GBP_displayName":"funt szterling","EUR_displayName":"euro","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"dolar australijski",
+	CAD_displayName:"dolar kanadyjski",
+	CHF_displayName:"frank szwajcarski",
+	CNY_displayName:"juan renminbi",
+	EUR_displayName:"euro",
+	GBP_displayName:"funt szterling",
+	HKD_displayName:"dolar hongkoński",
+	JPY_displayName:"jen japoński",
+	USD_displayName:"dolar amerykański "
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/pl/gregorian.js b/dojo/cldr/nls/pl/gregorian.js
index b4e3dd3..aba5519 100644
--- a/dojo/cldr/nls/pl/gregorian.js
+++ b/dojo/cldr/nls/pl/gregorian.js
@@ -1 +1,238 @@
-({"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":"y 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","fi [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"s", 
+		"l", 
+		"m", 
+		"k", 
+		"m", 
+		"c", 
+		"l", 
+		"s", 
+		"w", 
+		"p", 
+		"l", 
+		"g"
+	], 
+	"field-weekday": "Dzień tygodnia", 
+	"dateFormatItem-yQQQ": "y QQQ", 
+	"dateFormatItem-yMEd": "EEE, d-M-y", 
+	"dateFormatItem-MMMEd": "d MMM E", 
+	"eraNarrow": [
+		"p.n.e.", 
+		"n.e."
+	], 
+	"dayPeriods-format-wide-earlyMorning": "nad ranem", 
+	"dayPeriods-format-wide-morning": "rano", 
+	"dateFormat-long": "d MMMM y", 
+	"months-format-wide": [
+		"stycznia", 
+		"lutego", 
+		"marca", 
+		"kwietnia", 
+		"maja", 
+		"czerwca", 
+		"lipca", 
+		"sierpnia", 
+		"września", 
+		"października", 
+		"listopada", 
+		"grudnia"
+	], 
+	"dayPeriods-format-wide-evening": "wieczorem", 
+	"dayPeriods-format-wide-pm": "PM", 
+	"dateFormat-full": "EEEE, d MMMM y", 
+	"dateFormatItem-Md": "d-M", 
+	"dayPeriods-format-wide-noon": "w południe", 
+	"field-era": "Era", 
+	"dateFormatItem-yM": "M-y", 
+	"months-standAlone-wide": [
+		"styczeń", 
+		"luty", 
+		"marzec", 
+		"kwiecień", 
+		"maj", 
+		"czerwiec", 
+		"lipiec", 
+		"sierpień", 
+		"wrzesień", 
+		"październik", 
+		"listopad", 
+		"grudzień"
+	], 
+	"timeFormat-short": "HH:mm", 
+	"quarters-format-wide": [
+		"I kwartał", 
+		"II kwartał", 
+		"III kwartał", 
+		"IV kwartał"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"field-year": "Rok", 
+	"dateFormatItem-yQ": "yyyy Q", 
+	"dateFormatItem-yyyyMMMM": "LLLL y", 
+	"field-hour": "Godzina", 
+	"dateFormatItem-MMdd": "dd-MM", 
+	"months-format-abbr": [
+		"sty", 
+		"lut", 
+		"mar", 
+		"kwi", 
+		"maj", 
+		"cze", 
+		"lip", 
+		"sie", 
+		"wrz", 
+		"paź", 
+		"lis", 
+		"gru"
+	], 
+	"dateFormatItem-yyQ": "Q yy", 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"field-day-relative+0": "Dzisiaj", 
+	"field-day-relative+1": "Jutro", 
+	"field-day-relative+2": "Pojutrze", 
+	"field-day-relative+3": "Za trzy dni", 
+	"months-standAlone-abbr": [
+		"sty", 
+		"lut", 
+		"mar", 
+		"kwi", 
+		"maj", 
+		"cze", 
+		"lip", 
+		"sie", 
+		"wrz", 
+		"paź", 
+		"lis", 
+		"gru"
+	], 
+	"quarters-format-abbr": [
+		"K1", 
+		"K2", 
+		"K3", 
+		"K4"
+	], 
+	"quarters-standAlone-wide": [
+		"I kwartał", 
+		"II kwartał", 
+		"III kwartał", 
+		"IV kwartał"
+	], 
+	"dateFormatItem-M": "L", 
+	"days-standAlone-wide": [
+		"niedziela", 
+		"poniedziałek", 
+		"wtorek", 
+		"środa", 
+		"czwartek", 
+		"piątek", 
+		"sobota"
+	], 
+	"dateFormatItem-MMMMd": "d MMMM", 
+	"dateFormatItem-yyMMM": "MMM yy", 
+	"timeFormat-medium": "HH:mm:ss", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"quarters-standAlone-abbr": [
+		"1 kw.", 
+		"2 kw.", 
+		"3 kw.", 
+		"4 kw."
+	], 
+	"eraAbbr": [
+		"p.n.e.", 
+		"n.e."
+	], 
+	"field-minute": "Minuta", 
+	"field-dayperiod": "Dayperiod", 
+	"dayPeriods-format-wide-night": "w nocy", 
+	"days-standAlone-abbr": [
+		"niedz.", 
+		"pon.", 
+		"wt.", 
+		"śr.", 
+		"czw.", 
+		"pt.", 
+		"sob."
+	], 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "Wczoraj", 
+	"dateFormatItem-h": "hh a", 
+	"field-day-relative+-2": "Przedwczoraj", 
+	"field-day-relative+-3": "Trzy dni temu", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"dateFormatItem-MEd": "E, d-M", 
+	"dayPeriods-format-wide-lateMorning": "przed południem", 
+	"dateFormatItem-yMMMM": "LLLL y", 
+	"field-day": "Dzień", 
+	"days-format-wide": [
+		"niedziela", 
+		"poniedziałek", 
+		"wtorek", 
+		"środa", 
+		"czwartek", 
+		"piątek", 
+		"sobota"
+	], 
+	"field-zone": "Strefa", 
+	"dateFormatItem-yyyyMM": "yyyy-MM", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"s", 
+		"l", 
+		"m", 
+		"k", 
+		"m", 
+		"c", 
+		"l", 
+		"s", 
+		"w", 
+		"p", 
+		"l", 
+		"g"
+	], 
+	"dateFormatItem-yyMM": "MM/yy", 
+	"dateFormatItem-hm": "hh:mm a", 
+	"days-format-abbr": [
+		"niedz.", 
+		"pon.", 
+		"wt.", 
+		"śr.", 
+		"czw.", 
+		"pt.", 
+		"sob."
+	], 
+	"eraNames": [
+		"p.n.e.", 
+		"n.e."
+	], 
+	"days-format-narrow": [
+		"N", 
+		"P", 
+		"W", 
+		"Ś", 
+		"C", 
+		"P", 
+		"S"
+	], 
+	"field-month": "Miesiąc", 
+	"days-standAlone-narrow": [
+		"N", 
+		"P", 
+		"W", 
+		"Ś", 
+		"C", 
+		"P", 
+		"S"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dayPeriods-format-wide-am": "AM", 
+	"dateFormat-short": "dd-MM-yyyy", 
+	"dayPeriods-format-wide-afternoon": "po południu", 
+	"field-second": "Sekunda", 
+	"dateFormatItem-yMMMEd": "EEE, d MMM y", 
+	"field-week": "Tydzień", 
+	"dateFormat-medium": "dd-MM-yyyy", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-hms": "hh:mm:ss a"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/pl/number.js b/dojo/cldr/nls/pl/number.js
index ad7c869..5d516a6 100644
--- a/dojo/cldr/nls/pl/number.js
+++ b/dojo/cldr/nls/pl/number.js
@@ -1 +1,19 @@
-({"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-afterCu [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':" ",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/pt-br/gregorian.js b/dojo/cldr/nls/pt-br/gregorian.js
deleted file mode 100644
index 4144e28..0000000
--- a/dojo/cldr/nls/pt-br/gregorian.js
+++ /dev/null
@@ -1 +0,0 @@
-({"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", [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/pt-pt/gregorian.js b/dojo/cldr/nls/pt-pt/gregorian.js
index c4e4556..db26b56 100644
--- a/dojo/cldr/nls/pt-pt/gregorian.js
+++ b/dojo/cldr/nls/pt-pt/gregorian.js
@@ -1 +1,132 @@
-({"dateFormatItem-yyQ":"QQQ 'de' yy","quarters-standAlone-wide":["1.º trimestre","2.º trimestre","3.º trimestre","4.º trimestre"],"quarters-format-abbr":["1.º trimestre","2.º trimestre","3.º trimestre","4.º trimestre"],"months-standAlone-abbr":["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],"dateFormat-medium":"d 'de' MMM 'de' yyyy","am":"Antes do meio-dia","months-format-abbr":["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],"dateFormat [...]
\ No newline at end of file
+({
+	"quarters-standAlone-wide": [
+		"1.º trimestre", 
+		"2.º trimestre", 
+		"3.º trimestre", 
+		"4.º trimestre"
+	], 
+	"dayPeriods-standAlone-wide-am": "a.m.", 
+	"quarters-format-abbr": [
+		"1.º trimestre", 
+		"2.º trimestre", 
+		"3.º trimestre", 
+		"4.º trimestre"
+	], 
+	"dateFormat-medium": "d 'de' MMM 'de' yyyy", 
+	"quarters-standAlone-abbr": [
+		"1.º trimestre", 
+		"2.º trimestre", 
+		"3.º trimestre", 
+		"4.º trimestre"
+	], 
+	"dayPeriods-standAlone-abbr-pm": "p.m.", 
+	"dateFormatItem-hm": "h:mm", 
+	"months-standAlone-wide": [
+		"Janeiro", 
+		"Fevereiro", 
+		"Março", 
+		"Abril", 
+		"Maio", 
+		"Junho", 
+		"Julho", 
+		"Agosto", 
+		"Setembro", 
+		"Outubro", 
+		"Novembro", 
+		"Dezembro"
+	], 
+	"dayPeriods-standAlone-abbr-am": "a.m.", 
+	"dayPeriods-format-wide-pm": "Depois do meio-dia", 
+	"months-standAlone-abbr": [
+		"Jan", 
+		"Fev", 
+		"Mar", 
+		"Abr", 
+		"Mai", 
+		"Jun", 
+		"Jul", 
+		"Ago", 
+		"Set", 
+		"Out", 
+		"Nov", 
+		"Dez"
+	], 
+	"dateFormatItem-yQQQ": "QQQ 'de' y", 
+	"dayPeriods-format-wide-am": "Antes do meio-dia", 
+	"dayPeriods-format-abbr-pm": "p.m.", 
+	"dateFormatItem-yyQ": "QQQ 'de' yy", 
+	"dayPeriods-format-abbr-am": "a.m.", 
+	"months-format-wide": [
+		"Janeiro", 
+		"Fevereiro", 
+		"Março", 
+		"Abril", 
+		"Maio", 
+		"Junho", 
+		"Julho", 
+		"Agosto", 
+		"Setembro", 
+		"Outubro", 
+		"Novembro", 
+		"Dezembro"
+	], 
+	"days-standAlone-wide": [
+		"Domingo", 
+		"Segunda-feira", 
+		"Terça-feira", 
+		"Quarta-feira", 
+		"Quinta-feira", 
+		"Sexta-feira", 
+		"Sábado"
+	], 
+	"months-format-abbr": [
+		"Jan", 
+		"Fev", 
+		"Mar", 
+		"Abr", 
+		"Mai", 
+		"Jun", 
+		"Jul", 
+		"Ago", 
+		"Set", 
+		"Out", 
+		"Nov", 
+		"Dez"
+	], 
+	"days-standAlone-abbr": [
+		"Domingo", 
+		"Segunda-feira", 
+		"Terça-feira", 
+		"Quarta-feira", 
+		"Quinta-feira", 
+		"Sexta-feira", 
+		"Sábado"
+	], 
+	"days-format-wide": [
+		"Domingo", 
+		"Segunda-feira", 
+		"Terça-feira", 
+		"Quarta-feira", 
+		"Quinta-feira", 
+		"Sexta-feira", 
+		"Sábado"
+	], 
+	"dateFormatItem-yQ": "QQQ 'de' yyyy", 
+	"dateFormatItem-hms": "h:mm:ss", 
+	"quarters-format-wide": [
+		"1.º trimestre", 
+		"2.º trimestre", 
+		"3.º trimestre", 
+		"4.º trimestre"
+	], 
+	"dayPeriods-standAlone-wide-pm": "p.m.", 
+	"days-format-abbr": [
+		"Domingo", 
+		"Segunda-feira", 
+		"Terça-feira", 
+		"Quarta-feira", 
+		"Quinta-feira", 
+		"Sexta-feira", 
+		"Sábado"
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/pt-pt/number.js b/dojo/cldr/nls/pt-pt/number.js
index e06fd94..75b3981 100644
--- a/dojo/cldr/nls/pt-pt/number.js
+++ b/dojo/cldr/nls/pt-pt/number.js
@@ -1 +1,5 @@
-({"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-afterCu [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'group':" ",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/pt/currency.js b/dojo/cldr/nls/pt/currency.js
index 41baedf..688ebe6 100644
--- a/dojo/cldr/nls/pt/currency.js
+++ b/dojo/cldr/nls/pt/currency.js
@@ -1 +1,13 @@
-({"HKD_displayName":"Dólar de Hong Kong","CHF_displayName":"Franco suíço","CAD_displayName":"Dólar canadense","CNY_displayName":"Yuan Renminbi chinês","AUD_displayName":"Dólar australiano","JPY_displayName":"Iene japonês","USD_displayName":"Dólar norte-americano","GBP_displayName":"Libra esterlina britânica","EUR_displayName":"Euro","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symb [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Dólar australiano",
+	CAD_displayName:"Dólar canadense",
+	CHF_displayName:"Franco suíço",
+	CNY_displayName:"Yuan Renminbi chinês",
+	EUR_displayName:"Euro",
+	GBP_displayName:"Libra esterlina britânica",
+	HKD_displayName:"Dólar de Hong Kong",
+	JPY_displayName:"Iene japonês",
+	USD_displayName:"Dólar norte-americano"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/pt/gregorian.js b/dojo/cldr/nls/pt/gregorian.js
index 2d90f8b..d7916e0 100644
--- a/dojo/cldr/nls/pt/gregorian.js
+++ b/dojo/cldr/nls/pt/gregorian.js
@@ -1 +1,233 @@
-({"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":"y QQQ","dateFormatItem-yMEd":"EEE, dd/MM/yyyy","dateFormatItem-MMMEd":"EEE, d 'de' MMM","eraNarrow":["a.C.","d.C."],"dateFormat-long":"d 'de' MMMM 'de' y","months-format-wide":["janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"],"dateTimeFormat-medium": [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"J", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"field-weekday": "Dia da semana", 
+	"dateFormatItem-yQQQ": "y QQQ", 
+	"dateFormatItem-yMEd": "EEE, dd/MM/yyyy", 
+	"dateFormatItem-MMMEd": "EEE, d 'de' MMM", 
+	"eraNarrow": [
+		"a.C.", 
+		"d.C."
+	], 
+	"dayPeriods-format-wide-morning": "manhã", 
+	"dateFormat-long": "d 'de' MMMM 'de' y", 
+	"months-format-wide": [
+		"janeiro", 
+		"fevereiro", 
+		"março", 
+		"abril", 
+		"maio", 
+		"junho", 
+		"julho", 
+		"agosto", 
+		"setembro", 
+		"outubro", 
+		"novembro", 
+		"dezembro"
+	], 
+	"dateFormatItem-EEEd": "EEE, d", 
+	"dateFormat-full": "EEEE, d 'de' MMMM 'de' y", 
+	"dateFormatItem-Md": "d/M", 
+	"dayPeriods-format-wide-noon": "meio-dia", 
+	"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"
+	], 
+	"timeFormat-long": "HH'h'mm'min'ss's' z", 
+	"field-year": "Ano", 
+	"dateFormatItem-yMMM": "MMM 'de' y", 
+	"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' zzzz", 
+	"field-day-relative+0": "Hoje", 
+	"field-day-relative+1": "Amanhã", 
+	"field-day-relative+2": "Depois de amanhã", 
+	"field-day-relative+3": "Daqui a três dias", 
+	"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'h'mm'min'ss's'", 
+	"dateFormatItem-M": "L", 
+	"days-standAlone-wide": [
+		"domingo", 
+		"segunda-feira", 
+		"terça-feira", 
+		"quarta-feira", 
+		"quinta-feira", 
+		"sexta-feira", 
+		"sábado"
+	], 
+	"dateFormatItem-yyyyMMM": "MMM 'de' y", 
+	"dateFormatItem-yyMMMEEEd": "EEE, d 'de' MMM 'de' yy", 
+	"dateFormatItem-yyMMM": "MMM 'de' yy", 
+	"timeFormat-medium": "HH:mm:ss", 
+	"dateFormatItem-Hm": "HH'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"
+	], 
+	"dayPeriods-format-wide-night": "noite", 
+	"dateFormatItem-yyMMMd": "d 'de' MMM 'de' yy", 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm'min'ss's'", 
+	"field-day-relative+-1": "Ontem", 
+	"field-day-relative+-2": "Anteontem", 
+	"field-day-relative+-3": "Há três dias", 
+	"dateFormatItem-MMMd": "d 'de' MMM", 
+	"dateFormatItem-MEd": "EEE, dd/MM", 
+	"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": "y", 
+	"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'h'mm", 
+	"dateFormat-short": "dd/MM/yy", 
+	"dayPeriods-format-wide-afternoon": "tarde", 
+	"field-second": "Segundo", 
+	"dateFormatItem-yMMMEd": "EEE, d 'de' MMM 'de' y", 
+	"field-week": "Semana", 
+	"dateFormat-medium": "dd/MM/yyyy"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/pt/number.js b/dojo/cldr/nls/pt/number.js
index f10fcfa..8f15b61 100644
--- a/dojo/cldr/nls/pt/number.js
+++ b/dojo/cldr/nls/pt/number.js
@@ -1 +1,19 @@
-({"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":" ","currencySpac [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':".",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"¤#,##0.00;(¤#,##0.00)"
+})
diff --git a/dojo/cldr/nls/ru/currency.js b/dojo/cldr/nls/ru/currency.js
index 72cf7f0..d9f61cb 100644
--- a/dojo/cldr/nls/ru/currency.js
+++ b/dojo/cldr/nls/ru/currency.js
@@ -1 +1,14 @@
-({"HKD_displayName":"Гонконгский доллар","CHF_displayName":"Швейцарский франк","CAD_displayName":"Канадский доллар","CNY_displayName":"Юань Ренминби","USD_symbol":"$","AUD_displayName":"Австралийский доллар","JPY_displayName":"Японская иена","USD_displayName":"Доллар США","GBP_displayName":"Английский фунт стерлингов","EUR_displayName":"Евро","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Австралийский доллар",
+	CAD_displayName:"Канадский доллар",
+	CHF_displayName:"Швейцарский франк",
+	CNY_displayName:"Юань Ренминби",
+	EUR_displayName:"Евро",
+	GBP_displayName:"Английский фунт стерлингов",
+	HKD_displayName:"Гонконгский доллар",
+	JPY_displayName:"Японская иена",
+	USD_displayName:"Доллар США",
+	USD_symbol:"$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/ru/gregorian.js b/dojo/cldr/nls/ru/gregorian.js
index 7643715..edd6bf4 100644
--- a/dojo/cldr/nls/ru/gregorian.js
+++ b/dojo/cldr/nls/ru/gregorian.js
@@ -1 +1,228 @@
-({"months-format-narrow":["Я","Ф","М","А","М","И","И","А","С","О","Н","Д"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"День недели","dateFormatItem-yQQQ":"y QQQ","dateFormatItem-yMEd":"EEE, yyyy-M-d","dateFormatItem-yyyyLLLL":"LLLL y","dateFormatItem-MMMEd":"E MMM d","eraNarrow":["до н.э.","н.э."],"dateFormat-long":"d MMMM y 'г'.","months-format-wide":["января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"],"dateForma [...]
\ No newline at end of file
+({
+	"dateFormatItem-yM": "M.y", 
+	"field-dayperiod": "AM/PM", 
+	"field-minute": "Минута", 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"eraNames": [
+		"до н.э.", 
+		"н.э."
+	], 
+	"field-day-relative+-1": "Вчера", 
+	"dateFormatItem-MMdd": "dd.MM", 
+	"dateFormatItem-yQQQ": "y QQQ", 
+	"field-day-relative+-2": "Позавчера", 
+	"field-weekday": "День недели", 
+	"days-standAlone-wide": [
+		"Воскресенье", 
+		"Понедельник", 
+		"Вторник", 
+		"Среда", 
+		"Четверг", 
+		"Пятница", 
+		"Суббота"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"months-standAlone-narrow": [
+		"Я", 
+		"Ф", 
+		"М", 
+		"А", 
+		"М", 
+		"И", 
+		"И", 
+		"А", 
+		"С", 
+		"О", 
+		"Н", 
+		"Д"
+	], 
+	"field-era": "Эра", 
+	"field-hour": "Час", 
+	"quarters-standAlone-abbr": [
+		"1-й кв.", 
+		"2-й кв.", 
+		"3-й кв.", 
+		"4-й кв."
+	], 
+	"dateFormatItem-y": "y", 
+	"dateFormatItem-yyMMMEEEd": "EEE, d MMM yy", 
+	"timeFormat-full": "H:mm:ss zzzz", 
+	"dateFormatItem-yyyy": "y", 
+	"months-standAlone-abbr": [
+		"янв.", 
+		"февр.", 
+		"март", 
+		"апр.", 
+		"май", 
+		"июнь", 
+		"июль", 
+		"авг.", 
+		"сент.", 
+		"окт.", 
+		"нояб.", 
+		"дек."
+	], 
+	"dateFormatItem-Ed": "E d", 
+	"dateFormatItem-yMMM": "LLL y", 
+	"dateFormatItem-yyyyLLLL": "LLLL y", 
+	"field-day-relative+0": "Сегодня", 
+	"days-standAlone-narrow": [
+		"В", 
+		"П", 
+		"В", 
+		"С", 
+		"Ч", 
+		"П", 
+		"С"
+	], 
+	"field-day-relative+1": "Завтра", 
+	"eraAbbr": [
+		"до н.э.", 
+		"н.э."
+	], 
+	"field-day-relative+2": "Послезавтра", 
+	"dateFormatItem-yyyyMM": "MM.yyyy", 
+	"dateFormatItem-yyyyMMMM": "LLLL y", 
+	"dateFormat-long": "d MMMM y 'г'.", 
+	"timeFormat-medium": "H:mm:ss", 
+	"field-zone": "Часовой пояс", 
+	"dateFormatItem-Hm": "H:mm", 
+	"dateFormat-medium": "dd.MM.yyyy", 
+	"dateFormatItem-yyMM": "MM.yy", 
+	"dateFormatItem-Hms": "H:mm:ss", 
+	"dateFormatItem-yyMMM": "LLL yy", 
+	"quarters-standAlone-wide": [
+		"1-й квартал", 
+		"2-й квартал", 
+		"3-й квартал", 
+		"4-й квартал"
+	], 
+	"dateFormatItem-ms": "mm:ss", 
+	"dateFormatItem-yyyyQQQQ": "QQQQ y 'г'.", 
+	"field-year": "Год", 
+	"months-standAlone-wide": [
+		"Январь", 
+		"Февраль", 
+		"Март", 
+		"Апрель", 
+		"Май", 
+		"Июнь", 
+		"Июль", 
+		"Август", 
+		"Сентябрь", 
+		"Октябрь", 
+		"Ноябрь", 
+		"Декабрь"
+	], 
+	"field-week": "Неделя", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"dateFormatItem-yyQ": "Q yy", 
+	"timeFormat-long": "H:mm:ss z", 
+	"months-format-abbr": [
+		"янв.", 
+		"февр.", 
+		"марта", 
+		"апр.", 
+		"мая", 
+		"июня", 
+		"июля", 
+		"авг.", 
+		"сент.", 
+		"окт.", 
+		"нояб.", 
+		"дек."
+	], 
+	"timeFormat-short": "H:mm", 
+	"dateFormatItem-H": "H", 
+	"field-month": "Месяц", 
+	"quarters-format-abbr": [
+		"1-й кв.", 
+		"2-й кв.", 
+		"3-й кв.", 
+		"4-й кв."
+	], 
+	"days-format-abbr": [
+		"Вс", 
+		"Пн", 
+		"Вт", 
+		"Ср", 
+		"Чт", 
+		"Пт", 
+		"Сб"
+	], 
+	"dateFormatItem-M": "L", 
+	"days-format-narrow": [
+		"В", 
+		"П", 
+		"В", 
+		"С", 
+		"Ч", 
+		"П", 
+		"С"
+	], 
+	"field-second": "Секунда", 
+	"field-day": "День", 
+	"dateFormatItem-MEd": "E, d.M", 
+	"months-format-narrow": [
+		"Я", 
+		"Ф", 
+		"М", 
+		"А", 
+		"М", 
+		"И", 
+		"И", 
+		"А", 
+		"С", 
+		"О", 
+		"Н", 
+		"Д"
+	], 
+	"days-standAlone-abbr": [
+		"Вс", 
+		"Пн", 
+		"Вт", 
+		"Ср", 
+		"Чт", 
+		"Пт", 
+		"Сб"
+	], 
+	"dateFormat-short": "dd.MM.yy", 
+	"dateFormatItem-yMMMEd": "E, d MMM y", 
+	"dateFormat-full": "EEEE, d MMMM y 'г'.", 
+	"dateFormatItem-Md": "d.M", 
+	"dateFormatItem-yMEd": "EEE, d.M.y", 
+	"months-format-wide": [
+		"января", 
+		"февраля", 
+		"марта", 
+		"апреля", 
+		"мая", 
+		"июня", 
+		"июля", 
+		"августа", 
+		"сентября", 
+		"октября", 
+		"ноября", 
+		"декабря"
+	], 
+	"dateFormatItem-d": "d", 
+	"quarters-format-wide": [
+		"1-й квартал", 
+		"2-й квартал", 
+		"3-й квартал", 
+		"4-й квартал"
+	], 
+	"days-format-wide": [
+		"воскресенье", 
+		"понедельник", 
+		"вторник", 
+		"среда", 
+		"четверг", 
+		"пятница", 
+		"суббота"
+	], 
+	"eraNarrow": [
+		"до н.э.", 
+		"н.э."
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/ru/number.js b/dojo/cldr/nls/ru/number.js
index 55fbdf8..8a311c7 100644
--- a/dojo/cldr/nls/ru/number.js
+++ b/dojo/cldr/nls/ru/number.js
@@ -1 +1,18 @@
-({"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-afterC [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':" ",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0 %",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/sk/currency.js b/dojo/cldr/nls/sk/currency.js
index 3dec918..301673d 100644
--- a/dojo/cldr/nls/sk/currency.js
+++ b/dojo/cldr/nls/sk/currency.js
@@ -1 +1,13 @@
-({"HKD_displayName":"Hong Kongský dolár","CHF_displayName":"Švajčiarský frank","CAD_displayName":"Kanadský dolár","CNY_displayName":"Čínsky Yuan Renminbi","AUD_displayName":"Austrálsky dolár","JPY_displayName":"Japonský yen","USD_displayName":"US dolár","GBP_displayName":"Britská libra","EUR_displayName":"Euro","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Austrálsky dolár",
+	CAD_displayName:"Kanadský dolár",
+	CHF_displayName:"Švajčiarský frank",
+	CNY_displayName:"Čínsky Yuan Renminbi",
+	EUR_displayName:"Euro",
+	GBP_displayName:"Britská libra",
+	HKD_displayName:"Hong Kongský dolár",
+	JPY_displayName:"Japonský yen",
+	USD_displayName:"US dolár"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/sk/gregorian.js b/dojo/cldr/nls/sk/gregorian.js
index 4a8a5da..9ffb4c6 100644
--- a/dojo/cldr/nls/sk/gregorian.js
+++ b/dojo/cldr/nls/sk/gregorian.js
@@ -1 +1,221 @@
-({"field-dayperiod":"Časť dňa","dateFormatItem-yQ":"Q yyyy","field-minute":"Minúta","eraNames":["pred n.l.","n.l."],"dateFormatItem-MMMEd":"E, d. MMM","field-weekday":"Deň v týždni","dateFormatItem-yQQQ":"QQQ y","days-standAlone-wide":["nedeľa","pondelok","utorok","streda","štvrtok","piatok","sobota"],"months-standAlone-narrow":["j","f","m","a","m","j","j","a","s","o","n","d"],"field-era":"Éra","field-hour":"Hodina","timeFormat-full":"H:mm:ss zzzz","months-standAlone-abbr":["jan","feb"," [...]
\ No newline at end of file
+({
+	"field-dayperiod": "Časť dňa", 
+	"dayPeriods-format-wide-pm": "popoludní", 
+	"dateFormatItem-yQ": "Q yyyy", 
+	"field-minute": "Minúta", 
+	"dateFormatItem-MMMEd": "E, d. MMM", 
+	"eraNames": [
+		"pred n.l.", 
+		"n.l."
+	], 
+	"field-day-relative+-1": "Včera", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"field-day-relative+-2": "Predvčerom", 
+	"field-weekday": "Deň v týždni", 
+	"field-day-relative+-3": "Pred tromi dňami", 
+	"days-standAlone-wide": [
+		"nedeľa", 
+		"pondelok", 
+		"utorok", 
+		"streda", 
+		"štvrtok", 
+		"piatok", 
+		"sobota"
+	], 
+	"months-standAlone-narrow": [
+		"j", 
+		"f", 
+		"m", 
+		"a", 
+		"m", 
+		"j", 
+		"j", 
+		"a", 
+		"s", 
+		"o", 
+		"n", 
+		"d"
+	], 
+	"dayPeriods-format-wide-am": "dopoludnia", 
+	"field-era": "Éra", 
+	"field-hour": "Hodina", 
+	"timeFormat-full": "H:mm:ss zzzz", 
+	"months-standAlone-abbr": [
+		"jan", 
+		"feb", 
+		"mar", 
+		"apr", 
+		"máj", 
+		"jún", 
+		"júl", 
+		"aug", 
+		"sep", 
+		"okt", 
+		"nov", 
+		"dec"
+	], 
+	"dateFormatItem-yMMM": "LLL y", 
+	"field-day-relative+0": "Dnes", 
+	"days-standAlone-narrow": [
+		"N", 
+		"P", 
+		"U", 
+		"S", 
+		"Š", 
+		"P", 
+		"S"
+	], 
+	"field-day-relative+1": "Zajtra", 
+	"eraAbbr": [
+		"pred n.l.", 
+		"n.l."
+	], 
+	"field-day-relative+2": "Pozajtra", 
+	"field-day-relative+3": "O tri dni", 
+	"dateFormatItem-yyyyMMMM": "LLLL y", 
+	"dateFormat-long": "d. MMMM y", 
+	"timeFormat-medium": "H:mm:ss", 
+	"dateFormatItem-EEEd": "EEE, d.", 
+	"field-zone": "Pásmo", 
+	"dateFormatItem-Hm": "H:mm", 
+	"dateFormat-medium": "d.M.yyyy", 
+	"dateFormatItem-Hms": "H:mm:ss", 
+	"dateFormatItem-yyQQQQ": "QQQQ yy", 
+	"quarters-standAlone-wide": [
+		"1. štvrťrok", 
+		"2. štvrťrok", 
+		"3. štvrťrok", 
+		"4. štvrťrok"
+	], 
+	"dateFormatItem-yMMMM": "LLLL y", 
+	"dateFormatItem-ms": "mm:ss", 
+	"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ň", 
+	"dateFormatItem-MMMMEd": "E, d. MMMM", 
+	"dateFormatItem-MMMd": "d. MMM", 
+	"dateFormatItem-yyQ": "Q yy", 
+	"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", 
+	"dateFormatItem-H": "H", 
+	"field-month": "Mesiac", 
+	"dateFormatItem-MMMMd": "d. MMMM", 
+	"quarters-format-abbr": [
+		"Q1", 
+		"Q2", 
+		"Q3", 
+		"Q4"
+	], 
+	"days-format-abbr": [
+		"ne", 
+		"po", 
+		"ut", 
+		"st", 
+		"št", 
+		"pi", 
+		"so"
+	], 
+	"dateFormatItem-mmss": "mm:ss", 
+	"days-format-narrow": [
+		"N", 
+		"P", 
+		"U", 
+		"S", 
+		"Š", 
+		"P", 
+		"S"
+	], 
+	"field-second": "Sekunda", 
+	"field-day": "Deň", 
+	"dateFormatItem-MEd": "E, d.M.", 
+	"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", 
+	"dateFormatItem-yyyyM": "M.yyyy", 
+	"dateFormatItem-yMMMEd": "EEE, d. MMM y", 
+	"dateFormat-full": "EEEE, d. MMMM y", 
+	"dateFormatItem-Md": "d.M.", 
+	"dateFormatItem-yMEd": "EEE, d.M.yyyy", 
+	"months-format-wide": [
+		"januára", 
+		"februára", 
+		"marca", 
+		"apríla", 
+		"mája", 
+		"júna", 
+		"júla", 
+		"augusta", 
+		"septembra", 
+		"októbra", 
+		"novembra", 
+		"decembra"
+	], 
+	"dateFormatItem-d": "d.", 
+	"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."
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/sk/number.js b/dojo/cldr/nls/sk/number.js
index f4095fd..a9e09c1 100644
--- a/dojo/cldr/nls/sk/number.js
+++ b/dojo/cldr/nls/sk/number.js
@@ -1 +1,6 @@
-({"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:]","perMill [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':" ",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/sl/currency.js b/dojo/cldr/nls/sl/currency.js
index c00d92b..490d9f3 100644
--- a/dojo/cldr/nls/sl/currency.js
+++ b/dojo/cldr/nls/sl/currency.js
@@ -1 +1,15 @@
-({"HKD_displayName":"hongkonški dolar","CHF_displayName":"švicarski frank","JPY_symbol":"¥","CAD_displayName":"kanadski dolar","CNY_displayName":"kitajski juan renminbi","USD_symbol":"$","AUD_displayName":"avstralski dolar","JPY_displayName":"japonski jen","USD_displayName":"ameriški dolar","GBP_displayName":"britanski funt","EUR_displayName":"evro","CHF_symbol":"Fr.","HKD_symbol":"HK$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"avstralski dolar",
+	CAD_displayName:"kanadski dolar",
+	CHF_displayName:"švicarski frank",
+	CNY_displayName:"kitajski juan renminbi",
+	EUR_displayName:"evro",
+	GBP_displayName:"britanski funt",
+	HKD_displayName:"hongkonški dolar",
+	JPY_displayName:"japonski jen",
+	JPY_symbol:"¥",
+	USD_displayName:"ameriški dolar",
+	USD_symbol:"$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/sl/gregorian.js b/dojo/cldr/nls/sl/gregorian.js
index 8479597..00d831b 100644
--- a/dojo/cldr/nls/sl/gregorian.js
+++ b/dojo/cldr/nls/sl/gregorian.js
@@ -1 +1,209 @@
-({"field-dayperiod":"Čas dneva","field-minute":"Minuta","eraNames":["pred našim štetjem","naše štetje"],"field-weekday":"Dan v tednu","days-standAlone-wide":["nedelja","ponedeljek","torek","sreda","četrtek","petek","sobota"],"months-standAlone-narrow":["j","f","m","a","m","j","j","a","s","o","n","d"],"field-era":"Doba","field-hour":"Ura","dateFormatItem-y":"y","timeFormat-full":"H:mm:ss zzzz","months-standAlone-abbr":["jan","feb","mar","apr","maj","jun","jul","avg","sep","okt","nov","dec [...]
\ No newline at end of file
+({
+	"field-dayperiod": "Čas dneva", 
+	"dayPeriods-format-wide-pm": "pop.", 
+	"field-minute": "Minuta", 
+	"eraNames": [
+		"pred našim štetjem", 
+		"naše štetje"
+	], 
+	"field-day-relative+-1": "Včeraj", 
+	"field-day-relative+-2": "Predvčerajšnjim", 
+	"field-weekday": "Dan v tednu", 
+	"field-day-relative+-3": "Pred tremi dnevi", 
+	"days-standAlone-wide": [
+		"nedelja", 
+		"ponedeljek", 
+		"torek", 
+		"sreda", 
+		"četrtek", 
+		"petek", 
+		"sobota"
+	], 
+	"months-standAlone-narrow": [
+		"j", 
+		"f", 
+		"m", 
+		"a", 
+		"m", 
+		"j", 
+		"j", 
+		"a", 
+		"s", 
+		"o", 
+		"n", 
+		"d"
+	], 
+	"field-era": "Doba", 
+	"dayPeriods-format-wide-am": "dop.", 
+	"field-hour": "Ura", 
+	"dateFormatItem-y": "y", 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"months-standAlone-abbr": [
+		"jan", 
+		"feb", 
+		"mar", 
+		"apr", 
+		"maj", 
+		"jun", 
+		"jul", 
+		"avg", 
+		"sep", 
+		"okt", 
+		"nov", 
+		"dec"
+	], 
+	"field-day-relative+0": "Danes", 
+	"days-standAlone-narrow": [
+		"n", 
+		"p", 
+		"t", 
+		"s", 
+		"č", 
+		"p", 
+		"s"
+	], 
+	"field-day-relative+1": "Jutri", 
+	"eraAbbr": [
+		"pr. n. št.", 
+		"po Kr."
+	], 
+	"field-day-relative+2": "Pojutrišnjem", 
+	"field-day-relative+3": "Čez tri dni", 
+	"dateFormatItem-yyyyMMMM": "MMMM y", 
+	"dateFormat-long": "dd. MMMM y", 
+	"timeFormat-medium": "HH:mm:ss", 
+	"field-zone": "Območje", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"dateFormat-medium": "d. MMM. yyyy", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"quarters-standAlone-wide": [
+		"1. četrtletje", 
+		"2. četrtletje", 
+		"3. četrtletje", 
+		"4. četrtletje"
+	], 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-year": "Leto", 
+	"field-week": "Teden", 
+	"months-standAlone-wide": [
+		"januar", 
+		"februar", 
+		"marec", 
+		"april", 
+		"maj", 
+		"junij", 
+		"julij", 
+		"avgust", 
+		"september", 
+		"oktober", 
+		"november", 
+		"december"
+	], 
+	"dateFormatItem-yyQ": "Q/yy", 
+	"timeFormat-long": "HH:mm:ss z", 
+	"months-format-abbr": [
+		"jan", 
+		"feb", 
+		"mar", 
+		"apr", 
+		"maj", 
+		"jun", 
+		"jul", 
+		"avg", 
+		"sep", 
+		"okt", 
+		"nov", 
+		"dec"
+	], 
+	"timeFormat-short": "HH:mm", 
+	"field-month": "Mesec", 
+	"dateFormatItem-MMMMd": "d. MMMM", 
+	"quarters-format-abbr": [
+		"Q1", 
+		"Q2", 
+		"Q3", 
+		"Q4"
+	], 
+	"days-format-abbr": [
+		"ned", 
+		"pon", 
+		"tor", 
+		"sre", 
+		"čet", 
+		"pet", 
+		"sob"
+	], 
+	"dateFormatItem-MMMMdd": "dd. MMMM", 
+	"dateFormatItem-mmss": "mm:ss", 
+	"days-format-narrow": [
+		"n", 
+		"p", 
+		"t", 
+		"s", 
+		"č", 
+		"p", 
+		"s"
+	], 
+	"field-second": "Sekunda", 
+	"field-day": "Dan", 
+	"months-format-narrow": [
+		"j", 
+		"f", 
+		"m", 
+		"a", 
+		"m", 
+		"j", 
+		"j", 
+		"a", 
+		"s", 
+		"o", 
+		"n", 
+		"d"
+	], 
+	"days-standAlone-abbr": [
+		"ned", 
+		"pon", 
+		"tor", 
+		"sre", 
+		"čet", 
+		"pet", 
+		"sob"
+	], 
+	"dateFormat-short": "d. MM. yy", 
+	"dateFormatItem-yyyyM": "M/yyyy", 
+	"dateFormat-full": "EEEE, dd. MMMM y", 
+	"dateFormatItem-Md": "d. M.", 
+	"months-format-wide": [
+		"januar", 
+		"februar", 
+		"marec", 
+		"april", 
+		"maj", 
+		"junij", 
+		"julij", 
+		"avgust", 
+		"september", 
+		"oktober", 
+		"november", 
+		"december"
+	], 
+	"quarters-format-wide": [
+		"1. četrtletje", 
+		"2. četrtletje", 
+		"3. četrtletje", 
+		"4. četrtletje"
+	], 
+	"days-format-wide": [
+		"nedelja", 
+		"ponedeljek", 
+		"torek", 
+		"sreda", 
+		"četrtek", 
+		"petek", 
+		"sobota"
+	], 
+	"eraNarrow": [
+		"pr. n. št.", 
+		"po Kr."
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/sl/number.js b/dojo/cldr/nls/sl/number.js
index cc62788..a5d47fe 100644
--- a/dojo/cldr/nls/sl/number.js
+++ b/dojo/cldr/nls/sl/number.js
@@ -1 +1,19 @@
-({"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-afterCu [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':".",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"e",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/sv/currency.js b/dojo/cldr/nls/sv/currency.js
index 4eaa2c6..cbe0710 100644
--- a/dojo/cldr/nls/sv/currency.js
+++ b/dojo/cldr/nls/sv/currency.js
@@ -1 +1,16 @@
-({"HKD_displayName":"Hongkong-dollar","CHF_displayName":"schweizisk franc","CHF_symbol":"CHF","CAD_displayName":"kanadensisk dollar","CNY_displayName":"kinesisk yuan renminbi","AUD_displayName":"australisk dollar","JPY_displayName":"japansk yen","CAD_symbol":"CAD","USD_displayName":"US-dollar","CNY_symbol":"CNY","GBP_displayName":"brittiskt pund sterling","EUR_displayName":"euro","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","EUR_symbol":"€","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"australisk dollar",
+	CAD_displayName:"kanadensisk dollar",
+	CAD_symbol:"CAD",
+	CHF_displayName:"schweizisk franc",
+	CHF_symbol:"CHF",
+	CNY_displayName:"kinesisk yuan renminbi",
+	CNY_symbol:"CNY",
+	EUR_displayName:"euro",
+	GBP_displayName:"brittiskt pund sterling",
+	HKD_displayName:"Hongkong-dollar",
+	JPY_displayName:"japansk yen",
+	USD_displayName:"US-dollar"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/sv/gregorian.js b/dojo/cldr/nls/sv/gregorian.js
index eb5f1e3..a77799d 100644
--- a/dojo/cldr/nls/sv/gregorian.js
+++ b/dojo/cldr/nls/sv/gregorian.js
@@ -1 +1,241 @@
-({"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":"y QQQ","dateFormatItem-yMEd":"EEE, yyyy-MM-dd","dateFormatItem-MMMEd":"E d MMM","eraNarrow":["f.Kr.","e.Kr."],"dateFormat-long":"d MMMM y","months-format-wide":["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],"dateFormat-full":"EEEE d MMMM y","dateFormatIte [...]
\ No newline at end of file
+({
+	"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": "y QQQ", 
+	"dateFormatItem-yMEd": "EEE, yyyy-MM-dd", 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"eraNarrow": [
+		"f.Kr.", 
+		"e.Kr."
+	], 
+	"dateFormat-long": "d MMMM y", 
+	"months-format-wide": [
+		"januari", 
+		"februari", 
+		"mars", 
+		"april", 
+		"maj", 
+		"juni", 
+		"juli", 
+		"augusti", 
+		"september", 
+		"oktober", 
+		"november", 
+		"december"
+	], 
+	"dateFormatItem-EEEd": "EEE d", 
+	"dayPeriods-format-wide-pm": "em", 
+	"dateFormat-full": "EEEE'en' 'den' d:'e' MMMM y", 
+	"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"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"field-year": "år", 
+	"dateFormatItem-yMMM": "y 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 zzzz", 
+	"field-day-relative+0": "i dag", 
+	"field-day-relative+1": "i morgon", 
+	"field-day-relative+2": "i övermorgon", 
+	"field-day-relative+3": "i överövermorgon", 
+	"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-M": "L", 
+	"days-standAlone-wide": [
+		"söndag", 
+		"måndag", 
+		"tisdag", 
+		"onsdag", 
+		"torsdag", 
+		"fredag", 
+		"lördag"
+	], 
+	"dateFormatItem-yyyyMMM": "MMM y", 
+	"dateFormatItem-MMMMd": "d:'e' 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": "fm/em", 
+	"days-standAlone-abbr": [
+		"sön", 
+		"mån", 
+		"tis", 
+		"ons", 
+		"tors", 
+		"fre", 
+		"lör"
+	], 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "i går", 
+	"field-day-relative+-2": "i förrgår", 
+	"field-day-relative+-3": "i förrförrgår", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"dateFormatItem-MEd": "E d/M", 
+	"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": "y", 
+	"months-standAlone-narrow": [
+		"J", 
+		"F", 
+		"M", 
+		"A", 
+		"M", 
+		"J", 
+		"J", 
+		"A", 
+		"S", 
+		"O", 
+		"N", 
+		"D"
+	], 
+	"dateFormatItem-yyMM": "yy-MM", 
+	"dateFormatItem-hm": "h:mm a", 
+	"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", 
+	"dayPeriods-format-wide-am": "fm", 
+	"dateFormatItem-MMMMEd": "E d:'e' MMMM", 
+	"dateFormat-short": "yyyy-MM-dd", 
+	"dateFormatItem-MMd": "d/M", 
+	"field-second": "sekund", 
+	"dateFormatItem-yMMMEd": "EEE d MMM y", 
+	"field-week": "vecka", 
+	"dateFormat-medium": "d MMM y", 
+	"dateFormatItem-yyyyQQQQ": "QQQQ y", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-hms": "h:mm:ss a"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/sv/number.js b/dojo/cldr/nls/sv/number.js
index de83eac..49d869f 100644
--- a/dojo/cldr/nls/sv/number.js
+++ b/dojo/cldr/nls/sv/number.js
@@ -1 +1,19 @@
-({"group":" ","percentSign":"%","exponential":"×10^","percentFormat":"#,##0 %","scientificFormat":"#E0","list":";","infinity":"∞","patternDigit":"#","minusSign":"−","decimal":",","nan":"¤¤¤","nativeZeroDigit":"0","perMille":"‰","decimalFormat":"#,##0.###","currencyFormat":"#,##0.00 ¤","plusSign":"+","currencySpacing-afterCurrency-currencyMatch":"[:letter:]","currencySpacing-beforeCurrency-surroundingMatch":"[:digit:]","currencySpacing-afterCurrency-insertBetween":" ","currencySpacing-aft [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':" ",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"−",
+	'exponential':"×10^",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"¤¤¤",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0 %",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/th/buddhist.js b/dojo/cldr/nls/th/buddhist.js
index 716c2d3..5d0a41e 100644
--- a/dojo/cldr/nls/th/buddhist.js
+++ b/dojo/cldr/nls/th/buddhist.js
@@ -1 +1,114 @@
-({"dateFormatItem-yM":"M/yyyy","dateFormatItem-yQ":"Q yyyy","eraNames":["พุทธศักราช"],"dateFormatItem-MMMEd":"Eท d MMM","dateTimeFormat-full":"{1}, {0}","dateFormatItem-yQQQ":"QQQ y","months-standAlone-narrow":["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],"dateTimeFormat-short":"{1}, {0}","dateTimeFormat-medium":"{1}, {0}","timeFormat-full":"H นาฬิกา m นาที ss วินาที zzzz","dateFormatItem-yMMM":"MMM yyyy","days-standAlone-narrow":["อ","จ","อ","พ [...]
\ No newline at end of file
+({
+	"dateFormatItem-yM": "M/yyyy", 
+	"dateFormatItem-yQ": "Q yyyy", 
+	"dayPeriods-format-wide-pm": "หลังเที่ยง", 
+	"eraNames": [
+		"พุทธศักราช"
+	], 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"dateTimeFormat-full": "{1}, {0}", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"months-standAlone-narrow": [
+		"ม.ค.", 
+		"ก.พ.", 
+		"มี.ค.", 
+		"เม.ย.", 
+		"พ.ค.", 
+		"มิ.ย.", 
+		"ก.ค.", 
+		"ส.ค.", 
+		"ก.ย.", 
+		"ต.ค.", 
+		"พ.ย.", 
+		"ธ.ค."
+	], 
+	"dateTimeFormat-short": "{1}, {0}", 
+	"dayPeriods-format-wide-am": "ก่อนเที่ยง", 
+	"dateTimeFormat-medium": "{1}, {0}", 
+	"timeFormat-full": "H นาฬิกา m นาที ss วินาที zzzz", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"days-standAlone-narrow": [
+		"อ", 
+		"จ", 
+		"อ", 
+		"พ", 
+		"พ", 
+		"ศ", 
+		"ส"
+	], 
+	"eraAbbr": [
+		"พ.ศ."
+	], 
+	"dateFormat-long": "d MMMM y", 
+	"timeFormat-medium": "H:mm:ss", 
+	"dateFormatItem-EEEd": "EEE d", 
+	"dateFormatItem-Hm": "H:mm", 
+	"dateFormat-medium": "d MMM y", 
+	"dateFormatItem-Hms": "H:mm:ss", 
+	"dateTimeFormat-long": "{1}, {0}", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"timeFormat-long": "H นาฬิกา m นาที ss วินาที z", 
+	"months-format-abbr": [
+		"ม.ค.", 
+		"ก.พ.", 
+		"มี.ค.", 
+		"เม.ย.", 
+		"พ.ค.", 
+		"มิ.ย.", 
+		"ก.ค.", 
+		"ส.ค.", 
+		"ก.ย.", 
+		"ต.ค.", 
+		"พ.ย.", 
+		"ธ.ค."
+	], 
+	"timeFormat-short": "H:mm", 
+	"dateFormatItem-H": "H", 
+	"days-format-abbr": [
+		"อา.", 
+		"จ.", 
+		"อ.", 
+		"พ.", 
+		"พฤ.", 
+		"ศ.", 
+		"ส."
+	], 
+	"dateFormatItem-MEd": "E, d/M", 
+	"dateFormat-short": "d/M/yyyy", 
+	"dateFormatItem-yMMMEd": "EEE d MMM y", 
+	"dateFormat-full": "EEEEที่ d MMMM G y", 
+	"dateFormatItem-Md": "d/M", 
+	"dateFormatItem-yMEd": "EEE d/M/yyyy", 
+	"months-format-wide": [
+		"มกราคม", 
+		"กุมภาพันธ์", 
+		"มีนาคม", 
+		"เมษายน", 
+		"พฤษภาคม", 
+		"มิถุนายน", 
+		"กรกฎาคม", 
+		"สิงหาคม", 
+		"กันยายน", 
+		"ตุลาคม", 
+		"พฤศจิกายน", 
+		"ธันวาคม"
+	], 
+	"quarters-format-wide": [
+		"ไตรมาส 1", 
+		"ไตรมาส 2", 
+		"ไตรมาส 3", 
+		"ไตรมาส 4"
+	], 
+	"days-format-wide": [
+		"วันอาทิตย์", 
+		"วันจันทร์", 
+		"วันอังคาร", 
+		"วันพุธ", 
+		"วันพฤหัสบดี", 
+		"วันศุกร์", 
+		"วันเสาร์"
+	], 
+	"eraNarrow": [
+		"พ.ศ."
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/th/currency.js b/dojo/cldr/nls/th/currency.js
index 2b39ee1..f731df1 100644
--- a/dojo/cldr/nls/th/currency.js
+++ b/dojo/cldr/nls/th/currency.js
@@ -1 +1,14 @@
-({"HKD_displayName":"ดอลลาร์ฮ่องกง","CHF_displayName":"ฟรังก์สวิส","JPY_symbol":"¥","CAD_displayName":"ดอลลาร์แคนาดา","CNY_displayName":"หยวนเหรินหมินปี้ (สาธารณรัฐประชาชนจีน)","AUD_displayName":"ดอลลาร์ออสเตรเลีย","JPY_displayName":"เยนญี่ปุ่น","USD_displayName":"ดอลลาร์สหรัฐ","GBP_displayName":"ปอนด์สเตอร์ลิง (สหราชอาณาจักร)","EUR_displayName":"ยูโร","CHF_symbol":"Fr.","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_sym [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"ดอลลาร์ออสเตรเลีย",
+	CAD_displayName:"ดอลลาร์แคนาดา",
+	CHF_displayName:"ฟรังก์สวิส",
+	CNY_displayName:"หยวนเหรินหมินปี้ (สาธารณรัฐประชาชนจีน)",
+	EUR_displayName:"ยูโร",
+	GBP_displayName:"ปอนด์สเตอร์ลิง (สหราชอาณาจักร)",
+	HKD_displayName:"ดอลลาร์ฮ่องกง",
+	JPY_displayName:"เยนญี่ปุ่น",
+	JPY_symbol:"¥",
+	USD_displayName:"ดอลลาร์สหรัฐ"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/th/gregorian.js b/dojo/cldr/nls/th/gregorian.js
index 7088b42..7bea3c1 100644
--- a/dojo/cldr/nls/th/gregorian.js
+++ b/dojo/cldr/nls/th/gregorian.js
@@ -1 +1,228 @@
-({"dateFormatItem-yM":"M/yyyy","field-dayperiod":"ช่วงวัน","dateFormatItem-yQ":"Q yyyy","field-minute":"นาที","eraNames":["ปีก่อนคริสต์ศักราช","คริสต์ศักราช"],"dateFormatItem-MMMEd":"E d MMM","dateTimeFormat-full":"{1}, {0}","field-weekday":"วันในสัปดาห์","dateFormatItem-yQQQ":"QQQ y","days-standAlone-wide":["วันอาทิตย์","วันจันทร์","วันอังคาร","วันพุธ","วันพฤหัสบดี","วันศุกร์","วันเสาร์"],"dateFormatItem-MMM":"LLL","months-standAlone-narrow":["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย." [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"ม.ค.", 
+		"ก.พ.", 
+		"มี.ค.", 
+		"เม.ย.", 
+		"พ.ค.", 
+		"มิ.ย.", 
+		"ก.ค.", 
+		"ส.ค.", 
+		"ก.ย.", 
+		"ต.ค.", 
+		"พ.ย.", 
+		"ธ.ค."
+	], 
+	"field-weekday": "วันในสัปดาห์", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"dateFormatItem-yMEd": "EEE d/M/yyyy", 
+	"dateFormatItem-MMMEd": "E d MMM", 
+	"eraNarrow": [
+		"ก่อน ค.ศ.", 
+		"ค.ศ."
+	], 
+	"dateFormat-long": "d MMMM y", 
+	"months-format-wide": [
+		"มกราคม", 
+		"กุมภาพันธ์", 
+		"มีนาคม", 
+		"เมษายน", 
+		"พฤษภาคม", 
+		"มิถุนายน", 
+		"กรกฎาคม", 
+		"สิงหาคม", 
+		"กันยายน", 
+		"ตุลาคม", 
+		"พฤศจิกายน", 
+		"ธันวาคม"
+	], 
+	"dateTimeFormat-medium": "{1}, {0}", 
+	"dateFormatItem-EEEd": "EEE d", 
+	"dayPeriods-format-wide-pm": "หลังเที่ยง", 
+	"dateFormat-full": "EEEEที่ d MMMM G y", 
+	"dateFormatItem-Md": "d/M", 
+	"field-era": "สมัย", 
+	"dateFormatItem-yM": "M/yyyy", 
+	"months-standAlone-wide": [
+		"มกราคม", 
+		"กุมภาพันธ์", 
+		"มีนาคม", 
+		"เมษายน", 
+		"พฤษภาคม", 
+		"มิถุนายน", 
+		"กรกฎาคม", 
+		"สิงหาคม", 
+		"กันยายน", 
+		"ตุลาคม", 
+		"พฤศจิกายน", 
+		"ธันวาคม"
+	], 
+	"timeFormat-short": "H:mm", 
+	"quarters-format-wide": [
+		"ไตรมาส 1", 
+		"ไตรมาส 2", 
+		"ไตรมาส 3", 
+		"ไตรมาส 4"
+	], 
+	"timeFormat-long": "H นาฬิกา m นาที ss วินาที z", 
+	"field-year": "ปี", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"dateFormatItem-yQ": "Q yyyy", 
+	"dateFormatItem-yyyyMMMM": "MMMM y", 
+	"field-hour": "ชั่วโมง", 
+	"months-format-abbr": [
+		"ม.ค.", 
+		"ก.พ.", 
+		"มี.ค.", 
+		"เม.ย.", 
+		"พ.ค.", 
+		"มิ.ย.", 
+		"ก.ค.", 
+		"ส.ค.", 
+		"ก.ย.", 
+		"ต.ค.", 
+		"พ.ย.", 
+		"ธ.ค."
+	], 
+	"dateFormatItem-yyQ": "Q yy", 
+	"timeFormat-full": "H นาฬิกา m นาที ss วินาที zzzz", 
+	"field-day-relative+0": "วันนี้", 
+	"field-day-relative+1": "พรุ่งนี้", 
+	"field-day-relative+2": "มะรืนนี้", 
+	"dateFormatItem-H": "H", 
+	"field-day-relative+3": "สามวันต่อจากนี้", 
+	"months-standAlone-abbr": [
+		"ม.ค.", 
+		"ก.พ.", 
+		"มี.ค.", 
+		"เม.ย.", 
+		"พ.ค.", 
+		"มิ.ย.", 
+		"ก.ค.", 
+		"ส.ค.", 
+		"ก.ย.", 
+		"ต.ค.", 
+		"พ.ย.", 
+		"ธ.ค."
+	], 
+	"quarters-format-abbr": [
+		"Q1", 
+		"Q2", 
+		"Q3", 
+		"Q4"
+	], 
+	"quarters-standAlone-wide": [
+		"ไตรมาส 1", 
+		"ไตรมาส 2", 
+		"ไตรมาส 3", 
+		"ไตรมาส 4"
+	], 
+	"dateFormatItem-M": "L", 
+	"days-standAlone-wide": [
+		"วันอาทิตย์", 
+		"วันจันทร์", 
+		"วันอังคาร", 
+		"วันพุธ", 
+		"วันพฤหัสบดี", 
+		"วันศุกร์", 
+		"วันเสาร์"
+	], 
+	"dateFormatItem-MMMMd": "d MMMM", 
+	"timeFormat-medium": "H:mm:ss", 
+	"dateFormatItem-Hm": "H:mm", 
+	"eraAbbr": [
+		"ปีก่อน ค.ศ.", 
+		"ค.ศ."
+	], 
+	"field-minute": "นาที", 
+	"field-dayperiod": "ช่วงวัน", 
+	"days-standAlone-abbr": [
+		"อา.", 
+		"จ.", 
+		"อ.", 
+		"พ.", 
+		"พฤ.", 
+		"ศ.", 
+		"ส."
+	], 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "เมื่อวาน", 
+	"dateTimeFormat-long": "{1}, {0}", 
+	"field-day-relative+-2": "เมื่อวานซืน", 
+	"field-day-relative+-3": "สามวันก่อน", 
+	"dateFormatItem-MMMd": "d MMM", 
+	"dateFormatItem-MEd": "E, d/M", 
+	"dateTimeFormat-full": "{1}, {0}", 
+	"dateFormatItem-yMMMM": "MMMM y", 
+	"field-day": "วัน", 
+	"days-format-wide": [
+		"วันอาทิตย์", 
+		"วันจันทร์", 
+		"วันอังคาร", 
+		"วันพุธ", 
+		"วันพฤหัสบดี", 
+		"วันศุกร์", 
+		"วันเสาร์"
+	], 
+	"field-zone": "เขต", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"ม.ค.", 
+		"ก.พ.", 
+		"มี.ค.", 
+		"เม.ย.", 
+		"พ.ค.", 
+		"มิ.ย.", 
+		"ก.ค.", 
+		"ส.ค.", 
+		"ก.ย.", 
+		"ต.ค.", 
+		"พ.ย.", 
+		"ธ.ค."
+	], 
+	"days-format-abbr": [
+		"อา.", 
+		"จ.", 
+		"อ.", 
+		"พ.", 
+		"พฤ.", 
+		"ศ.", 
+		"ส."
+	], 
+	"eraNames": [
+		"ปีก่อนคริสต์ศักราช", 
+		"คริสต์ศักราช"
+	], 
+	"days-format-narrow": [
+		"อ", 
+		"จ", 
+		"อ", 
+		"พ", 
+		"พ", 
+		"ศ", 
+		"ส"
+	], 
+	"field-month": "เดือน", 
+	"days-standAlone-narrow": [
+		"อ", 
+		"จ", 
+		"อ", 
+		"พ", 
+		"พ", 
+		"ศ", 
+		"ส"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dayPeriods-format-wide-am": "ก่อนเที่ยง", 
+	"dateFormatItem-MMMMEd": "E d MMMM", 
+	"dateFormat-short": "d/M/yyyy", 
+	"field-second": "วินาที", 
+	"dateFormatItem-yMMMEd": "EEE d MMM y", 
+	"field-week": "สัปดาห์", 
+	"dateFormat-medium": "d MMM y", 
+	"dateFormatItem-yyyyM": "M/yyyy", 
+	"dateFormatItem-mmss": "mm:ss", 
+	"dateTimeFormat-short": "{1}, {0}", 
+	"dateFormatItem-Hms": "H:mm:ss"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/th/number.js b/dojo/cldr/nls/th/number.js
index 9d4a250..3e391eb 100644
--- a/dojo/cldr/nls/th/number.js
+++ b/dojo/cldr/nls/th/number.js
@@ -1 +1,19 @@
-({"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":" ","currencySpaci [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':".",
+	'group':",",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"¤#,##0.00;¤-#,##0.00"
+})
diff --git a/dojo/cldr/nls/tr/currency.js b/dojo/cldr/nls/tr/currency.js
index c2ca1a4..475a49b 100644
--- a/dojo/cldr/nls/tr/currency.js
+++ b/dojo/cldr/nls/tr/currency.js
@@ -1 +1,15 @@
-({"HKD_displayName":"Hong Kong Doları","CHF_displayName":"İsviçre Frangı","JPY_symbol":"¥","CAD_displayName":"Kanada Doları","CNY_displayName":"Çin Yuanı Renminbi","USD_symbol":"$","AUD_displayName":"Avustralya Doları","JPY_displayName":"Japon Yeni","USD_displayName":"ABD Doları","GBP_displayName":"İngiliz Sterlini","EUR_displayName":"Euro","CHF_symbol":"Fr.","HKD_symbol":"HK$","CAD_symbol":"CA$","EUR_symbol":"€","CNY_symbol":"CN¥","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"Avustralya Doları",
+	CAD_displayName:"Kanada Doları",
+	CHF_displayName:"İsviçre Frangı",
+	CNY_displayName:"Çin Yuanı Renminbi",
+	EUR_displayName:"Euro",
+	GBP_displayName:"İngiliz Sterlini",
+	HKD_displayName:"Hong Kong Doları",
+	JPY_displayName:"Japon Yeni",
+	JPY_symbol:"¥",
+	USD_displayName:"ABD Doları",
+	USD_symbol:"$"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/tr/gregorian.js b/dojo/cldr/nls/tr/gregorian.js
index 595c5bc..a951340 100644
--- a/dojo/cldr/nls/tr/gregorian.js
+++ b/dojo/cldr/nls/tr/gregorian.js
@@ -1 +1,235 @@
-({"months-format-narrow":["O","Ş","M","N","M","H","T","A","E","E","K","A"],"quarters-standAlone-narrow":["1","2","3","4"],"field-weekday":"Haftanın Günü","dateFormatItem-yyQQQQ":"QQQQ yy","dateFormatItem-yQQQ":"QQQ y","dateFormatItem-yMEd":"dd.MM.yyyy EEE","dateFormatItem-MMMEd":"dd MMM E","eraNarrow":["MÖ","MS"],"dateFormat-long":"dd MMMM y","months-format-wide":["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],"dateFormatItem-EEEd":"d  [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"O", 
+		"Ş", 
+		"M", 
+		"N", 
+		"M", 
+		"H", 
+		"T", 
+		"A", 
+		"E", 
+		"E", 
+		"K", 
+		"A"
+	], 
+	"field-weekday": "Haftanın Günü", 
+	"dateFormatItem-yyQQQQ": "QQQQ yy", 
+	"dateFormatItem-yQQQ": "QQQ y", 
+	"dateFormatItem-yMEd": "dd.MM.yyyy EEE", 
+	"dateFormatItem-MMMEd": "dd MMM E", 
+	"eraNarrow": [
+		"MÖ", 
+		"MS"
+	], 
+	"dateFormat-long": "dd MMMM y", 
+	"months-format-wide": [
+		"Ocak", 
+		"Şubat", 
+		"Mart", 
+		"Nisan", 
+		"Mayıs", 
+		"Haziran", 
+		"Temmuz", 
+		"Ağustos", 
+		"Eylül", 
+		"Ekim", 
+		"Kasım", 
+		"Aralık"
+	], 
+	"dateFormatItem-EEEd": "d EEE", 
+	"dayPeriods-format-wide-pm": "PM", 
+	"dateFormat-full": "dd MMMM y EEEE", 
+	"dateFormatItem-Md": "dd/MM", 
+	"field-era": "Miladi Dönem", 
+	"dateFormatItem-yM": "M/yyyy", 
+	"months-standAlone-wide": [
+		"Ocak", 
+		"Şubat", 
+		"Mart", 
+		"Nisan", 
+		"Mayıs", 
+		"Haziran", 
+		"Temmuz", 
+		"Ağustos", 
+		"Eylül", 
+		"Ekim", 
+		"Kasım", 
+		"Aralık"
+	], 
+	"timeFormat-short": "HH:mm", 
+	"quarters-format-wide": [
+		"1. çeyrek", 
+		"2. çeyrek", 
+		"3. çeyrek", 
+		"4. çeyrek"
+	], 
+	"timeFormat-long": "HH:mm:ss z", 
+	"field-year": "Yıl", 
+	"dateFormatItem-yMMM": "MMM y", 
+	"dateFormatItem-yQ": "Q yyyy", 
+	"field-hour": "Saat", 
+	"months-format-abbr": [
+		"Oca", 
+		"Şub", 
+		"Mar", 
+		"Nis", 
+		"May", 
+		"Haz", 
+		"Tem", 
+		"Ağu", 
+		"Eyl", 
+		"Eki", 
+		"Kas", 
+		"Ara"
+	], 
+	"dateFormatItem-yyQ": "Q yy", 
+	"timeFormat-full": "HH:mm:ss zzzz", 
+	"field-day-relative+0": "Bugün", 
+	"field-day-relative+1": "Yarın", 
+	"field-day-relative+2": "Yarından sonraki gün", 
+	"dateFormatItem-H": "HH", 
+	"field-day-relative+3": "Üç gün sonra", 
+	"months-standAlone-abbr": [
+		"Oca", 
+		"Şub", 
+		"Mar", 
+		"Nis", 
+		"May", 
+		"Haz", 
+		"Tem", 
+		"Ağu", 
+		"Eyl", 
+		"Eki", 
+		"Kas", 
+		"Ara"
+	], 
+	"quarters-format-abbr": [
+		"Ç1", 
+		"Ç2", 
+		"Ç3", 
+		"Ç4"
+	], 
+	"quarters-standAlone-wide": [
+		"1. çeyrek", 
+		"2. çeyrek", 
+		"3. çeyrek", 
+		"4. çeyrek"
+	], 
+	"dateFormatItem-M": "L", 
+	"days-standAlone-wide": [
+		"Pazar", 
+		"Pazartesi", 
+		"Salı", 
+		"Çarşamba", 
+		"Perşembe", 
+		"Cuma", 
+		"Cumartesi"
+	], 
+	"dateFormatItem-MMMMd": "dd MMMM", 
+	"dateFormatItem-yyMMM": "MMM yy", 
+	"timeFormat-medium": "HH:mm:ss", 
+	"dateFormatItem-Hm": "HH:mm", 
+	"quarters-standAlone-abbr": [
+		"Ç1", 
+		"Ç2", 
+		"Ç3", 
+		"Ç4"
+	], 
+	"eraAbbr": [
+		"MÖ", 
+		"MS"
+	], 
+	"field-minute": "Dakika", 
+	"field-dayperiod": "AM/PM", 
+	"days-standAlone-abbr": [
+		"Paz", 
+		"Pzt", 
+		"Sal", 
+		"Çar", 
+		"Per", 
+		"Cum", 
+		"Cmt"
+	], 
+	"dateFormatItem-d": "d", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "Dün", 
+	"field-day-relative+-2": "Evvelsi gün", 
+	"field-day-relative+-3": "Üç gün önce", 
+	"dateFormatItem-MMMd": "dd MMM", 
+	"dateFormatItem-MEd": "dd/MM E", 
+	"dateFormatItem-yMMMM": "MMMM y", 
+	"field-day": "Gün", 
+	"days-format-wide": [
+		"Pazar", 
+		"Pazartesi", 
+		"Salı", 
+		"Çarşamba", 
+		"Perşembe", 
+		"Cuma", 
+		"Cumartesi"
+	], 
+	"field-zone": "Saat Dilimi", 
+	"dateFormatItem-y": "y", 
+	"months-standAlone-narrow": [
+		"O", 
+		"Ş", 
+		"M", 
+		"N", 
+		"M", 
+		"H", 
+		"T", 
+		"A", 
+		"E", 
+		"E", 
+		"K", 
+		"A"
+	], 
+	"dateFormatItem-yyMM": "MM/yy", 
+	"dateFormatItem-hm": "h:mm a", 
+	"days-format-abbr": [
+		"Paz", 
+		"Pzt", 
+		"Sal", 
+		"Çar", 
+		"Per", 
+		"Cum", 
+		"Cmt"
+	], 
+	"eraNames": [
+		"Milattan Önce", 
+		"Milattan Sonra"
+	], 
+	"days-format-narrow": [
+		"P", 
+		"P", 
+		"S", 
+		"Ç", 
+		"P", 
+		"C", 
+		"C"
+	], 
+	"field-month": "Ay", 
+	"days-standAlone-narrow": [
+		"P", 
+		"P", 
+		"S", 
+		"Ç", 
+		"P", 
+		"C", 
+		"C"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dayPeriods-format-wide-am": "AM", 
+	"dateFormatItem-MMMMEd": "dd MMMM E", 
+	"dateFormat-short": "dd.MM.yyyy", 
+	"field-second": "Saniye", 
+	"dateFormatItem-yMMMEd": "dd MMM y EEE", 
+	"dateFormatItem-Ed": "d E", 
+	"field-week": "Hafta", 
+	"dateFormat-medium": "dd MMM y", 
+	"dateFormatItem-mmss": "mm:ss", 
+	"dateFormatItem-Hms": "HH:mm:ss", 
+	"dateFormatItem-hms": "h:mm:ss a", 
+	"dateFormatItem-yyyy": "y"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/tr/number.js b/dojo/cldr/nls/tr/number.js
index 0be4606..bdd4385 100644
--- a/dojo/cldr/nls/tr/number.js
+++ b/dojo/cldr/nls/tr/number.js
@@ -1 +1,19 @@
-({"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-afterC [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':",",
+	'group':".",
+	'list':";",
+	'percentSign':"%",
+	'nativeZeroDigit':"0",
+	'patternDigit':"#",
+	'plusSign':"+",
+	'minusSign':"-",
+	'exponential':"E",
+	'perMille':"‰",
+	'infinity':"∞",
+	'nan':"NaN",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"% #,##0",
+	'currencyFormat':"#,##0.00 ¤"
+})
diff --git a/dojo/cldr/nls/zh-cn/gregorian.js b/dojo/cldr/nls/zh-cn/gregorian.js
deleted file mode 100644
index 5b4dbe5..0000000
--- a/dojo/cldr/nls/zh-cn/gregorian.js
+++ /dev/null
@@ -1 +0,0 @@
-({"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":"y年M月d日,E"," [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/zh-cn/number.js b/dojo/cldr/nls/zh-cn/number.js
deleted file mode 100644
index 4329dc1..0000000
--- a/dojo/cldr/nls/zh-cn/number.js
+++ /dev/null
@@ -1 +0,0 @@
-({"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 [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/zh-tw/currency.js b/dojo/cldr/nls/zh-tw/currency.js
index ca5c927..fa48735 100644
--- a/dojo/cldr/nls/zh-tw/currency.js
+++ b/dojo/cldr/nls/zh-tw/currency.js
@@ -1 +1,345 @@
-({"BRE_displayName":"巴西克魯賽羅 (1990-1993)","DEM_displayName":"德國馬克","KGS_symbol":"som","CUP_displayName":"古巴披索","HUF_symbol":"Ft","BDT_symbol":"Tk","LSL_symbol":"M","VEF_symbol":"BsF","MDL_displayName":"摩杜雲列伊","DOP_displayName":"多明尼加披索","MTL_symbol":"Lm","NGN_displayName":"奈及利亞奈拉","KZT_displayName":"卡扎克斯坦坦吉","BGL_symbol":"lev","LTT_displayName":"立陶宛特羅","LAK_displayName":"寮國基普","LKR_displayName":"斯里蘭卡盧布","AOR_displayName":"安哥拉新寬扎 Reajustado (1995-1999)","XEU_displayName":"歐洲貨幣單位 XEU","SYP_s [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	"BRE_displayName": "巴西克魯賽羅 (1990-1993)", 
+	"DEM_displayName": "德國馬克", 
+	"KGS_symbol": "som", 
+	"CUP_displayName": "古巴披索", 
+	"HUF_symbol": "Ft", 
+	"BDT_symbol": "Tk", 
+	"LSL_symbol": "M", 
+	"VEF_symbol": "BsF", 
+	"MDL_displayName": "摩杜雲列伊", 
+	"DOP_displayName": "多明尼加披索", 
+	"MTL_symbol": "Lm", 
+	"NGN_displayName": "奈及利亞奈拉", 
+	"KZT_displayName": "卡扎克斯坦坦吉", 
+	"BGL_symbol": "lev", 
+	"LTT_displayName": "立陶宛特羅", 
+	"LAK_displayName": "寮國基普", 
+	"LKR_displayName": "斯里蘭卡盧布", 
+	"AOR_displayName": "安哥拉新寬扎 Reajustado (1995-1999)", 
+	"XEU_displayName": "歐洲貨幣單位 XEU", 
+	"SYP_symbol": "LS", 
+	"USS_displayName": "美元 (同一天)", 
+	"MNT_displayName": "蒙古圖格里克", 
+	"AMD_symbol": "dram", 
+	"MOP_displayName": "澳門元", 
+	"TJR_displayName": "塔吉克斯坦盧布", 
+	"LUC_displayName": "盧森堡可兌換法郎", 
+	"LUL_displayName": "盧森堡金融法郎", 
+	"MRO_symbol": "UM", 
+	"AON_displayName": "安哥拉新寬扎 (1990-2000)", 
+	"BEF_displayName": "比利時法郎", 
+	"IEP_displayName": "愛爾蘭鎊", 
+	"SBD_displayName": "索羅門群島元", 
+	"GRD_displayName": "希臘德拉克馬", 
+	"AZM_displayName": "阿塞拜彊馬特納", 
+	"MTP_displayName": "馬爾他鎊", 
+	"UGX_symbol": "U Sh", 
+	"ARS_symbol": "Arg$", 
+	"LVR_displayName": "拉脫維亞盧布", 
+	"GNF_displayName": "幾內亞法郎", 
+	"GIP_displayName": "直布羅陀鎊", 
+	"SRG_displayName": "蘇里南盾", 
+	"BAD_displayName": "波士尼亞-黑塞哥維那第納爾", 
+	"FJD_displayName": "斐濟元", 
+	"BAM_displayName": "波士尼亞-黑塞哥維那可轉換馬克", 
+	"XBB_displayName": "歐洲貨幣單位 XBB", 
+	"CDF_displayName": "剛果法郎", 
+	"HRD_displayName": "克羅地亞第納爾", 
+	"EQE_displayName": "埃奎維勒", 
+	"BZD_displayName": "伯利茲元", 
+	"MLF_displayName": "馬里法郎", 
+	"VEB_symbol": "Be", 
+	"EGP_displayName": "埃及鎊", 
+	"MVR_displayName": "馬爾地夫海島盧非亞", 
+	"KWD_symbol": "KD", 
+	"TRL_symbol": "TL", 
+	"ALL_symbol": "lek", 
+	"SDP_displayName": "蘇丹鎊", 
+	"NPR_displayName": "尼泊爾盧布", 
+	"PHP_displayName": "菲律賓披索", 
+	"DJF_symbol": "DF", 
+	"WST_displayName": "西薩摩亞塔拉", 
+	"JPY_displayName": "日圓", 
+	"TMM_displayName": "土庫曼馬納特", 
+	"STD_symbol": "Db", 
+	"BGN_displayName": "保加利亞新列弗", 
+	"KYD_displayName": "開曼群島美元", 
+	"VUV_displayName": "萬那杜萬杜", 
+	"IRR_displayName": "伊朗里亞爾", 
+	"DJF_displayName": "吉布地法郎", 
+	"BTN_symbol": "Nu", 
+	"XDR_displayName": "特殊提款權", 
+	"ECS_displayName": "厄瓜多蘇克雷", 
+	"LSM_displayName": "馬洛蒂", 
+	"MNT_symbol": "Tug", 
+	"NLG_displayName": "荷蘭盾", 
+	"MWK_displayName": "馬拉維克瓦查", 
+	"IRR_symbol": "RI", 
+	"OMR_symbol": "RO", 
+	"JMD_symbol": "J$", 
+	"PES_displayName": "秘魯太陽幣", 
+	"SRG_symbol": "Sf", 
+	"LYD_displayName": "利比亞第納爾", 
+	"BRR_displayName": "巴西克魯賽羅", 
+	"ETB_symbol": "Br", 
+	"KMF_symbol": "CF", 
+	"DKK_symbol": "DKr", 
+	"XXX_displayName": "XXX", 
+	"IDR_displayName": "印尼 - 盧布", 
+	"DZD_symbol": "DA", 
+	"TZS_symbol": "T Sh", 
+	"SGD_symbol": "SGD", 
+	"KGS_displayName": "吉爾吉斯索馬", 
+	"BRN_displayName": "巴西克如爾達農瓦", 
+	"AFN_symbol": "Af", 
+	"ISK_displayName": "冰島克朗", 
+	"LUF_displayName": "盧森堡法郎", 
+	"MXN_symbol": "MEX$", 
+	"GYD_symbol": "G$", 
+	"TOP_symbol": "T$", 
+	"SVC_displayName": "薩爾瓦多科郎", 
+	"ZMK_displayName": "尚比亞克瓦查", 
+	"TOP_displayName": "東加潘加", 
+	"ITL_displayName": "義大利里拉", 
+	"USN_displayName": "美元 (第二天)", 
+	"KWD_displayName": "科威特第納爾", 
+	"GEL_symbol": "lari", 
+	"KMF_displayName": "科摩羅法郎", 
+	"COP_symbol": "Col$", 
+	"MYR_displayName": "馬來西亞 - 林吉特", 
+	"XFU_displayName": "法國 UIC 法郎", 
+	"GMD_displayName": "甘比亞達拉西", 
+	"LVL_displayName": "拉脫維亞拉特銀幣", 
+	"AUD_displayName": "澳幣", 
+	"XPF_displayName": "CFP 法郎", 
+	"LBP_displayName": "黎巴嫩鎊", 
+	"SKK_symbol": "Sk", 
+	"BYB_displayName": "白俄羅斯新盧布 (1994-1999)", 
+	"MKD_displayName": "馬其頓第納爾", 
+	"GWP_displayName": "幾內亞披索披索", 
+	"CNY_displayName": "人民幣", 
+	"HNL_symbol": "L", 
+	"BOB_symbol": "Bs", 
+	"JOD_displayName": "約旦第納爾", 
+	"OMR_displayName": "阿曼里奧", 
+	"BOV_displayName": "玻利維亞幕多", 
+	"XPT_displayName": "白金", 
+	"AUD_symbol": "AU$", 
+	"NOK_displayName": "挪威克羅納", 
+	"SCR_displayName": "塞舌爾群島盧布", 
+	"XBA_displayName": "歐洲綜合單位", 
+	"CSK_displayName": "捷克斯洛伐克硬克朗", 
+	"PLZ_displayName": "波蘭茲羅提 (1950-1995)", 
+	"UAK_displayName": "烏克蘭卡本瓦那茲", 
+	"MGF_displayName": "馬達加斯加法郎", 
+	"GNS_displayName": "幾內亞西里", 
+	"YUN_displayName": "南斯拉夫 可轉換第納爾", 
+	"UYU_symbol": "Ur$", 
+	"GYD_displayName": "圭亞那元", 
+	"QAR_displayName": "卡達爾里亞爾", 
+	"BZD_symbol": "BZ$", 
+	"JOD_symbol": "JD", 
+	"ALL_displayName": "阿爾巴尼亞列克", 
+	"BBD_displayName": "巴貝多元", 
+	"RON_displayName": "羅馬尼亞列伊", 
+	"XCD_symbol": "EC$", 
+	"AMD_displayName": "亞美尼亞德拉姆", 
+	"CYP_displayName": "賽浦路斯鎊", 
+	"GBP_symbol": "£", 
+	"SEK_displayName": "瑞典克羅納", 
+	"MZN_symbol": "MTn", 
+	"MMK_displayName": "緬甸元", 
+	"ZAR_displayName": "南非蘭特", 
+	"ECV_displayName": "厄瓜多爾由里達瓦康斯坦 (UVC)", 
+	"LYD_symbol": "LD", 
+	"VUV_symbol": "VT", 
+	"AWG_displayName": "阿魯巴盾", 
+	"CVE_symbol": "CVEsc", 
+	"STD_displayName": "聖多美島和普林西比島多布拉", 
+	"CAD_displayName": "加幣", 
+	"ADP_displayName": "安道爾陪士特", 
+	"MRO_displayName": "茅利塔尼亞烏吉亞", 
+	"LSL_displayName": "賴索托羅蒂", 
+	"TND_displayName": "突尼西亞第納爾", 
+	"USD_symbol": "$", 
+	"BMD_symbol": "Ber$", 
+	"BAM_symbol": "KM", 
+	"BRC_displayName": "巴西克魯賽羅 (1986-1989)", 
+	"BMD_displayName": "百慕達幣", 
+	"BRL_displayName": "巴西里拉", 
+	"JMD_displayName": "牙買加元", 
+	"SOS_displayName": "索馬利亞先令", 
+	"SAR_displayName": "沙烏地里雅", 
+	"PEI_displayName": "祕魯因蒂", 
+	"ESP_displayName": "西班牙陪士特", 
+	"HKD_displayName": "港幣", 
+	"ESP_symbol": "₧", 
+	"BWP_displayName": "波札那 - 普拉", 
+	"TTD_displayName": "千里達及托巴哥元", 
+	"BSD_displayName": "巴哈馬元", 
+	"BIF_displayName": "蒲隆地法郎", 
+	"FRF_displayName": "法國法郎", 
+	"DKK_displayName": "丹麥克羅納", 
+	"AED_displayName": "阿拉伯聯合大公國迪爾汗", 
+	"GHS_symbol": "GH¢", 
+	"AOK_displayName": "安哥拉寬扎(1977-1990)", 
+	"ATS_displayName": "奧地利先令", 
+	"PEN_displayName": "秘魯新太陽幣", 
+	"CRC_displayName": "哥斯大黎加科郎", 
+	"PAB_displayName": "巴拿馬巴波亞", 
+	"CHE_displayName": "WIR 歐元", 
+	"GQE_displayName": "赤道幾內亞埃奎勒", 
+	"DZD_displayName": "阿爾及利亞第納爾", 
+	"EEK_displayName": "愛沙尼亞克朗", 
+	"YDD_displayName": "葉門第納爾", 
+	"GHC_displayName": "迦納仙蔕", 
+	"YER_symbol": "YRl", 
+	"PLN_symbol": "Zl", 
+	"NPR_symbol": "Nrs", 
+	"MXP_displayName": "墨西哥銀披索 (1861-1992)", 
+	"XAG_displayName": "XAG", 
+	"XFO_displayName": "法國金法郎", 
+	"GWE_displayName": "葡屬幾內亞埃斯庫多", 
+	"BOB_displayName": "玻利維亞貨幣單位", 
+	"CAD_symbol": "CA$", 
+	"ZWD_displayName": "辛巴威元", 
+	"SRD_displayName": "蘇利南元", 
+	"ZRN_displayName": "薩伊新扎伊爾", 
+	"XAU_displayName": "黃金", 
+	"GTQ_symbol": "Q", 
+	"KRW_symbol": "KRW", 
+	"BOP_displayName": "玻利維亞披索", 
+	"LBP_symbol": "LL", 
+	"XBD_displayName": "歐洲會計單位(XBD)", 
+	"TZS_displayName": "坦尚尼亞先令", 
+	"XPF_symbol": "CFPF", 
+	"TTD_symbol": "TT$", 
+	"LRD_displayName": "賴比瑞亞元", 
+	"KRW_displayName": "韓國圜", 
+	"SHP_displayName": "聖赫勒拿鎊", 
+	"NAD_symbol": "N$", 
+	"MZE_displayName": "莫桑比克埃斯庫多", 
+	"SDD_displayName": "蘇丹第納爾", 
+	"HRK_displayName": "克羅地亞庫納", 
+	"FKP_displayName": "福克蘭群島鎊", 
+	"COP_displayName": "哥倫比亞披索", 
+	"YUD_displayName": "南斯拉夫第納爾硬幣", 
+	"YUM_displayName": "南斯拉夫挪威亞第納爾", 
+	"BYR_symbol": "Rbl", 
+	"THB_displayName": "泰銖", 
+	"MGA_displayName": "馬達加斯加艾瑞爾", 
+	"TWD_displayName": "新臺幣", 
+	"UGS_displayName": "烏干達先令 (1966-1987)", 
+	"SBD_symbol": "SI$", 
+	"ZAL_displayName": "南非 - 蘭特 (金融)", 
+	"GEL_displayName": "喬治拉里", 
+	"ILP_displayName": "以色列鎊", 
+	"MKD_symbol": "MDen", 
+	"KES_displayName": "肯尼亞先令", 
+	"CZK_displayName": "捷克克朗", 
+	"UGX_displayName": "烏干達先令", 
+	"KZT_symbol": "T", 
+	"BGL_displayName": "保加利亞硬列弗", 
+	"ARP_displayName": "阿根廷披索(1983-1985)", 
+	"BBD_symbol": "BDS$", 
+	"MYR_symbol": "RM", 
+	"RUR_displayName": "俄羅斯盧布 (1991-1998)", 
+	"ERN_displayName": "厄立特里亞納克法", 
+	"BEF_symbol": "BF", 
+	"CLF_displayName": "卡林油達佛曼跎", 
+	"BRB_displayName": "巴西克魯薩多農瓦(1967-1986)", 
+	"IDR_symbol": "Rp", 
+	"IEP_symbol": "IR£", 
+	"BHD_displayName": "巴林第納爾", 
+	"SYP_displayName": "敘利亞鎊", 
+	"BIF_symbol": "Fbu", 
+	"SZL_displayName": "史瓦濟蘭里朗吉尼", 
+	"INR_displayName": "印度盧布", 
+	"PTE_displayName": "葡萄牙埃斯庫多", 
+	"KPW_displayName": "北朝鮮幣", 
+	"XOF_displayName": "西非法郎 BCEAO", 
+	"DOP_symbol": "RD$", 
+	"MXN_displayName": "墨西哥 - 披索", 
+	"RWF_displayName": "盧安達法郎", 
+	"ETB_displayName": "衣索比亞比爾", 
+	"LTL_displayName": "立陶宛里塔", 
+	"SZL_symbol": "E", 
+	"QAR_symbol": "QR", 
+	"SOS_symbol": "Sh.", 
+	"BND_displayName": "汶萊元", 
+	"SUR_displayName": "蘇聯盧布", 
+	"AOA_displayName": "安哥拉寬扎", 
+	"FJD_symbol": "F$", 
+	"CVE_displayName": "維德角埃斯庫多", 
+	"XTS_displayName": "XTS", 
+	"CLP_displayName": "智利披索", 
+	"HUF_displayName": "匈牙利 - 福林", 
+	"LKR_symbol": "SL Re", 
+	"SCR_symbol": "SR", 
+	"TJS_displayName": "塔吉克索莫尼", 
+	"MWK_symbol": "MK", 
+	"GBP_displayName": "英鎊", 
+	"TPE_displayName": "帝汶埃斯庫多", 
+	"GNF_symbol": "GF", 
+	"SGD_displayName": "新加坡幣", 
+	"SLL_displayName": "獅子山利昂", 
+	"MZM_symbol": "Mt", 
+	"PHP_symbol": "Php", 
+	"CYP_symbol": "£C", 
+	"XAF_displayName": "西非法郎 BEAC", 
+	"MTL_displayName": "馬爾他里拉", 
+	"KHR_displayName": "柬埔寨瑞爾", 
+	"ZRZ_displayName": "扎伊爾扎伊爾", 
+	"KES_symbol": "K Sh", 
+	"PKR_symbol": "Pra", 
+	"IQD_symbol": "ID", 
+	"BEC_displayName": "比利時法郎 (可轉換)", 
+	"BEL_displayName": "比利時法郎 (金融)", 
+	"AZN_displayName": "亞塞拜然蒙納特", 
+	"FIM_displayName": "芬蘭馬克", 
+	"PKR_displayName": "巴基斯坦盧布", 
+	"UYP_displayName": "烏拉圭披索 (1975-1993)", 
+	"ANG_symbol": "NA f.", 
+	"CHW_displayName": "WIR 法郎", 
+	"PLN_displayName": "波蘭茲羅提", 
+	"RON_symbol": "0≤lei|1≤leu|1", 
+	"BTN_displayName": "不丹那特倫", 
+	"UAH_displayName": "烏克蘭格里夫那", 
+	"YER_displayName": "也門里亞爾", 
+	"UYU_displayName": "烏拉圭披索", 
+	"CRC_symbol": "C", 
+	"PGK_displayName": "巴布亞紐幾內亞基那", 
+	"XBC_displayName": "歐洲會計單位(XBC)", 
+	"EUR_displayName": "歐元", 
+	"MUR_displayName": "模里西斯盧布", 
+	"BYR_displayName": "白俄羅斯盧布", 
+	"SEK_symbol": "SKr", 
+	"BHD_symbol": "BD", 
+	"IQD_displayName": "伊拉克第納爾", 
+	"VEB_displayName": "委內瑞拉博利瓦", 
+	"CLP_symbol": "Ch$", 
+	"MZM_displayName": "莫三比克梅蒂卡爾", 
+	"NZD_symbol": "$NZ", 
+	"CHF_symbol": "Fr.", 
+	"SIT_displayName": "斯洛維尼亞托勒", 
+	"NOK_symbol": "NKr", 
+	"XCD_displayName": "格瑞那達元", 
+	"RUB_displayName": "俄羅斯盧布", 
+	"BUK_displayName": "緬甸元 BUK", 
+	"ILS_displayName": "以色列新謝克爾", 
+	"KHR_symbol": "CR", 
+	"NAD_displayName": "納米比亞元", 
+	"HNL_displayName": "洪都拉斯倫皮拉", 
+	"GTQ_displayName": "瓜地馬拉格查爾", 
+	"EUR_symbol": "€", 
+	"NZD_displayName": "紐西蘭幣", 
+	"ARA_displayName": "阿根廷奧斯特納爾", 
+	"ARS_displayName": "阿根廷披索", 
+	"ANG_displayName": "荷屬安地列斯盾", 
+	"MOP_symbol": "MOP", 
+	"ZWD_symbol": "Z$", 
+	"ITL_symbol": "₤", 
+	"ZAR_symbol": "R"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/zh-tw/gregorian.js b/dojo/cldr/nls/zh-tw/gregorian.js
index 5cd1b16..d770486 100644
--- a/dojo/cldr/nls/zh-tw/gregorian.js
+++ b/dojo/cldr/nls/zh-tw/gregorian.js
@@ -1 +1,176 @@
-({"dateFormatItem-yM":"yyyy/M","field-minute":"分鐘","eraNames":["西元前","西元"],"field-weekday":"週天","dateFormatItem-MMdd":"MM/dd","months-standAlone-narrow":["1","2","3","4","5","6","7","8","9","10","11","12"],"field-era":"年代","field-hour":"小時","quarters-standAlone-abbr":["第1季","第2季","第3季","第4季"],"timeFormat-full":"zzzzah時mm分ss秒","months-standAlone-abbr":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateFormatItem-Ed":"d日(E)","dateFormatItem-yMMM":"y年M月","timeFormat-mediu [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/calendars/calendar-gregorian
+({
+	"dateFormatItem-yM": "yyyy/M", 
+	"field-minute": "分鐘", 
+	"eraNames": [
+		"西元前", 
+		"西元"
+	], 
+	"field-weekday": "週天", 
+	"dateFormatItem-MMdd": "MM/dd", 
+	"field-day-relative+-3": "大前天", 
+	"field-relative-day": "大後天", 
+	"months-standAlone-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"field-era": "年代", 
+	"field-hour": "小時", 
+	"quarters-standAlone-abbr": [
+		"第1季", 
+		"第2季", 
+		"第3季", 
+		"第4季"
+	], 
+	"timeFormat-full": "zzzzah時mm分ss秒", 
+	"months-standAlone-abbr": [
+		"1月", 
+		"2月", 
+		"3月", 
+		"4月", 
+		"5月", 
+		"6月", 
+		"7月", 
+		"8月", 
+		"9月", 
+		"10月", 
+		"11月", 
+		"12月"
+	], 
+	"dateFormatItem-Ed": "d日(E)", 
+	"dateFormatItem-yMMM": "y年M月", 
+	"eraAbbr": [
+		"西元前", 
+		"西元"
+	], 
+	"field-day-relative+2": "後天", 
+	"field-day-relative+3": "大後天", 
+	"timeFormat-medium": "ah:mm:ss", 
+	"field-zone": "區域", 
+	"dateFormatItem-yyMM": "yy-MM", 
+	"dateFormat-medium": "yyyy/M/d", 
+	"quarters-standAlone-wide": [
+		"第1季", 
+		"第2季", 
+		"第3季", 
+		"第4季"
+	], 
+	"dateFormatItem-yMMMM": "y年M月", 
+	"dateFormatItem-HHmmss": "H:mm:ss", 
+	"months-standAlone-wide": [
+		"1月", 
+		"2月", 
+		"3月", 
+		"4月", 
+		"5月", 
+		"6月", 
+		"7月", 
+		"8月", 
+		"9月", 
+		"10月", 
+		"11月", 
+		"12月"
+	], 
+	"field-week": "週", 
+	"dateFormatItem-HHmm": "H:mm", 
+	"timeFormat-long": "zah時mm分ss秒", 
+	"dateFormatItem-H": "H時", 
+	"quarters-format-abbr": [
+		"第1季", 
+		"第2季", 
+		"第3季", 
+		"第4季"
+	], 
+	"days-format-abbr": [
+		"週日", 
+		"週一", 
+		"週二", 
+		"週三", 
+		"週四", 
+		"週五", 
+		"週六"
+	], 
+	"field-second": "秒", 
+	"dateFormatItem-MEd": "M/d(E)", 
+	"months-format-narrow": [
+		"1", 
+		"2", 
+		"3", 
+		"4", 
+		"5", 
+		"6", 
+		"7", 
+		"8", 
+		"9", 
+		"10", 
+		"11", 
+		"12"
+	], 
+	"days-standAlone-abbr": [
+		"週日", 
+		"週一", 
+		"週二", 
+		"週三", 
+		"週四", 
+		"週五", 
+		"週六"
+	], 
+	"dateFormat-short": "yy/M/d", 
+	"dateFormatItem-yMMMEd": "y年M月d日EEE", 
+	"dateFormatItem-Md": "M/d", 
+	"dateFormatItem-yMEd": "yyyy/M/d(EEE)", 
+	"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"
+	], 
+	"quarters-format-wide": [
+		"第1季", 
+		"第2季", 
+		"第3季", 
+		"第4季"
+	], 
+	"eraNarrow": [
+		"西元前", 
+		"西元"
+	]
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/zh-tw/number.js b/dojo/cldr/nls/zh-tw/number.js
deleted file mode 100644
index dc51043..0000000
--- a/dojo/cldr/nls/zh-tw/number.js
+++ /dev/null
@@ -1 +0,0 @@
-({"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 [...]
\ No newline at end of file
diff --git a/dojo/cldr/nls/zh/currency.js b/dojo/cldr/nls/zh/currency.js
index 0c28db0..0a8f781 100644
--- a/dojo/cldr/nls/zh/currency.js
+++ b/dojo/cldr/nls/zh/currency.js
@@ -1 +1,14 @@
-({"HKD_displayName":"港元","CHF_displayName":"瑞士法郎","CAD_displayName":"加拿大元","CNY_displayName":"人民币","AUD_displayName":"澳大利亚元","JPY_displayName":"日元","USD_displayName":"美元","CNY_symbol":"¥","GBP_displayName":"英镑","EUR_displayName":"欧元","CHF_symbol":"Fr.","JPY_symbol":"JP¥","HKD_symbol":"HK$","USD_symbol":"US$","CAD_symbol":"CA$","EUR_symbol":"€","GBP_symbol":"£","AUD_symbol":"AU$"})
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({
+	AUD_displayName:"澳大利亚元",
+	CAD_displayName:"加拿大元",
+	CHF_displayName:"瑞士法郎",
+	CNY_displayName:"人民币",
+	CNY_symbol:"¥",
+	EUR_displayName:"欧元",
+	GBP_displayName:"英镑",
+	HKD_displayName:"港元",
+	JPY_displayName:"日元",
+	USD_displayName:"美元"
+})
+                 
\ No newline at end of file
diff --git a/dojo/cldr/nls/zh/gregorian.js b/dojo/cldr/nls/zh/gregorian.js
index f9f2ae8..24a60ab 100644
--- a/dojo/cldr/nls/zh/gregorian.js
+++ b/dojo/cldr/nls/zh/gregorian.js
@@ -1 +1,243 @@
-({"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":"y年M月d日,E","dateFormatItem-MMMEd":"MMMd日E","eraNarrow":["公元前","公元"],"dateFormat-long":"y年M月d日","months-format-wide":["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],"dateTimeFormat-medium":"{1} {0}","dateFormat-full":"y年M月d日EEEE","dateFormatItem-Md":"M-d","field-era [...]
\ No newline at end of file
+({
+	"months-format-narrow": [
+		"1月", 
+		"2月", 
+		"3月", 
+		"4月", 
+		"5月", 
+		"6月", 
+		"7月", 
+		"8月", 
+		"9月", 
+		"10月", 
+		"11月", 
+		"12月"
+	], 
+	"field-weekday": "周天", 
+	"dateFormatItem-yQQQ": "y年QQQ", 
+	"dateFormatItem-yMEd": "y年M月d日,E", 
+	"dateFormatItem-MMMEd": "MMMd日E", 
+	"eraNarrow": [
+		"公元前", 
+		"公元"
+	], 
+	"dayPeriods-format-wide-earlyMorning": "清晨", 
+	"dayPeriods-format-wide-morning": "上午", 
+	"dateFormat-long": "y年M月d日", 
+	"months-format-wide": [
+		"1月", 
+		"2月", 
+		"3月", 
+		"4月", 
+		"5月", 
+		"6月", 
+		"7月", 
+		"8月", 
+		"9月", 
+		"10月", 
+		"11月", 
+		"12月"
+	], 
+	"dateTimeFormat-medium": "{1} {0}", 
+	"dayPeriods-format-wide-pm": "下午", 
+	"dateFormat-full": "y年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季度"
+	], 
+	"timeFormat-long": "zah时mm分ss秒", 
+	"field-year": "年", 
+	"dateFormatItem-yMMM": "y年MMM", 
+	"dateFormatItem-yQ": "y年QQQ", 
+	"dateFormatItem-yyyyMMMM": "y年MMMM", 
+	"dateFormatItem-MMdd": "MM-dd", 
+	"field-hour": "小时", 
+	"months-format-abbr": [
+		"1月", 
+		"2月", 
+		"3月", 
+		"4月", 
+		"5月", 
+		"6月", 
+		"7月", 
+		"8月", 
+		"9月", 
+		"10月", 
+		"11月", 
+		"12月"
+	], 
+	"dateFormatItem-yyQ": "yy年第Q季度", 
+	"timeFormat-full": "zzzzah时mm分ss秒", 
+	"field-day-relative+0": "今天", 
+	"field-day-relative+1": "明天", 
+	"field-day-relative+2": "后天", 
+	"dateFormatItem-H": "H时", 
+	"months-standAlone-abbr": [
+		"一月", 
+		"二月", 
+		"三月", 
+		"四月", 
+		"五月", 
+		"六月", 
+		"七月", 
+		"八月", 
+		"九月", 
+		"十月", 
+		"十一月", 
+		"十二月"
+	], 
+	"quarters-format-abbr": [
+		"1季", 
+		"2季", 
+		"3季", 
+		"4季"
+	], 
+	"quarters-standAlone-wide": [
+		"第1季度", 
+		"第2季度", 
+		"第3季度", 
+		"第4季度"
+	], 
+	"dateFormatItem-M": "L", 
+	"days-standAlone-wide": [
+		"星期日", 
+		"星期一", 
+		"星期二", 
+		"星期三", 
+		"星期四", 
+		"星期五", 
+		"星期六"
+	], 
+	"dateFormatItem-yyMMM": "yy年MMM", 
+	"timeFormat-medium": "ah:mm:ss", 
+	"dateFormatItem-Hm": "H:mm", 
+	"quarters-standAlone-abbr": [
+		"1季", 
+		"2季", 
+		"3季", 
+		"4季"
+	], 
+	"eraAbbr": [
+		"公元前", 
+		"公元"
+	], 
+	"field-minute": "分钟", 
+	"field-dayperiod": "上午/下午", 
+	"dayPeriods-format-wide-night": "晚上", 
+	"days-standAlone-abbr": [
+		"周日", 
+		"周一", 
+		"周二", 
+		"周三", 
+		"周四", 
+		"周五", 
+		"周六"
+	], 
+	"dateFormatItem-d": "d日", 
+	"dateFormatItem-ms": "mm:ss", 
+	"field-day-relative+-1": "昨天", 
+	"dateFormatItem-h": "ah", 
+	"dateTimeFormat-long": "{1}{0}", 
+	"field-day-relative+-2": "前天", 
+	"dateFormatItem-MMMd": "MMMd日", 
+	"dayPeriods-format-wide-midDay": "中午", 
+	"dateFormatItem-MEd": "M-dE", 
+	"dateTimeFormat-full": "{1}{0}", 
+	"field-day": "日", 
+	"days-format-wide": [
+		"星期日", 
+		"星期一", 
+		"星期二", 
+		"星期三", 
+		"星期四", 
+		"星期五", 
+		"星期六"
+	], 
+	"field-zone": "区域", 
+	"dateFormatItem-y": "y年", 
+	"months-standAlone-narrow": [
+		"1月", 
+		"2月", 
+		"3月", 
+		"4月", 
+		"5月", 
+		"6月", 
+		"7月", 
+		"8月", 
+		"9月", 
+		"10月", 
+		"11月", 
+		"12月"
+	], 
+	"dateFormatItem-yyMM": "yy-MM", 
+	"dateFormatItem-hm": "ah:mm", 
+	"days-format-abbr": [
+		"周日", 
+		"周一", 
+		"周二", 
+		"周三", 
+		"周四", 
+		"周五", 
+		"周六"
+	], 
+	"dateFormatItem-yMMMd": "y年MMMd日", 
+	"eraNames": [
+		"公元前", 
+		"公元"
+	], 
+	"days-format-narrow": [
+		"日", 
+		"一", 
+		"二", 
+		"三", 
+		"四", 
+		"五", 
+		"六"
+	], 
+	"field-month": "月", 
+	"days-standAlone-narrow": [
+		"日", 
+		"一", 
+		"二", 
+		"三", 
+		"四", 
+		"五", 
+		"六"
+	], 
+	"dateFormatItem-MMM": "LLL", 
+	"dayPeriods-format-wide-am": "上午", 
+	"dateFormatItem-MMMMdd": "MMMMdd日", 
+	"dayPeriods-format-wide-weeHours": "凌晨", 
+	"dateFormat-short": "yy-M-d", 
+	"dayPeriods-format-wide-afternoon": "下午", 
+	"field-second": "秒钟", 
+	"dateFormatItem-yMMMEd": "y年MMMd日EEE", 
+	"dateFormatItem-Ed": "d日E", 
+	"field-week": "周", 
+	"dateFormat-medium": "yyyy-M-d", 
+	"dateFormatItem-yyyyM": "y年M月", 
+	"dateTimeFormat-short": "{1} {0}", 
+	"dateFormatItem-Hms": "H:mm:ss", 
+	"dateFormatItem-hms": "ah:mm:ss", 
+	"dateFormatItem-yyyy": "y年"
+})
\ No newline at end of file
diff --git a/dojo/cldr/nls/zh/number.js b/dojo/cldr/nls/zh/number.js
index 90d87b9..018f6e8 100644
--- a/dojo/cldr/nls/zh/number.js
+++ b/dojo/cldr/nls/zh/number.js
@@ -1 +1,9 @@
-({"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 [...]
\ No newline at end of file
+// generated from ldml/main/*.xml, xpath: ldml/numbers
+({
+	'decimal':".",
+	'group':",",
+	'decimalFormat':"#,##0.###",
+	'scientificFormat':"#E0",
+	'percentFormat':"#,##0%",
+	'currencyFormat':"¤#,##0.00"
+})
diff --git a/dojo/cldr/supplemental.js b/dojo/cldr/supplemental.js
index 28ca582..739acd5 100644
--- a/dojo/cldr/supplemental.js
+++ b/dojo/cldr/supplemental.js
@@ -1,45 +1,70 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.cldr.supplemental"]){
-dojo._hasResource["dojo.cldr.supplemental"]=true;
 dojo.provide("dojo.cldr.supplemental");
+
 dojo.require("dojo.i18n");
-dojo.cldr.supplemental.getFirstDayOfWeek=function(_1){
-var _2={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,sy:4};
-var _3=dojo.cldr.supplemental._region(_1);
-var _4=_2[_3];
-return (_4===undefined)?1:_4;
-};
-dojo.cldr.supplemental._region=function(_5){
-_5=dojo.i18n.normalizeLocale(_5);
-var _6=_5.split("-");
-var _7=_6[1];
-if(!_7){
-_7={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"}[_6[0]];
-}else{
-if(_7.length==4){
-_7=_6[2];
-}
-}
-return _7;
+
+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,
+		af:6,bh:6,dj:6,dz:6,eg:6,er:6,et:6,iq:6,ir:6,jo:6,ke:6,kw:6,
+		ly:6,ma:6,om:6,qa:6,sa:6,sd:6,so:6,tn:6,ye:6,
+		ar:0,as:0,az:0,bw:0,ca:0,cn:0,fo:0,ge:0,gl:0,gu:0,hk:0,ie:0,
+		il:0,'in':0,is:0,jm:0,jp:0,kg:0,kr:0,la:0,mh:0,mn:0,mo:0,mp:0,
+		mt:0,nz:0,ph:0,pk:0,sg:0,sy:0,th:0,tt:0,tw:0,um:0,us:0,uz:0,
+		vi:0,zw:0
+// variant. do not use?		gb:0,
+	};
+
+	var country = dojo.cldr.supplemental._region(locale);
+	var dow = firstDay[country];
+	return (dow === undefined) ? 1 : dow; /*Number*/
 };
-dojo.cldr.supplemental.getWeekend=function(_8){
-var _9={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 _a={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 _b=dojo.cldr.supplemental._region(_8);
-var _c=_9[_b];
-var _d=_a[_b];
-if(_c===undefined){
-_c=6;
-}
-if(_d===undefined){
-_d=0;
+
+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;
 }
-return {start:_c,end:_d};
+
+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*/
+		'in':0,
+		af:4,dz:4,ir:4,om:4,sa:4,ye:4,
+		ae:5,bh:5,eg:5,il:5,iq:5,jo:5,kw:5,ly:5,ma:5,qa:5,sd:5,sy:5,tn:5
+	};
+
+	var weekendEnd = {/*default is 0=Sunday*/
+		af:5,dz:5,ir:5,om:5,sa:5,ye:5,
+		ae:6,bh:5,eg:6,il:6,iq:6,jo:6,kw:6,ly:6,ma:6,qa:6,sd:6,sy:6,tn: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}*/
 };
-}
diff --git a/dojo/colors.js b/dojo/colors.js
index 0aea35d..602d65c 100644
--- a/dojo/colors.js
+++ b/dojo/colors.js
@@ -1,76 +1,225 @@
-/*
-	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
-*/
+dojo.provide("dojo.colors");
 
+//TODO: this module appears to break naming conventions
 
-if(!dojo._hasResource["dojo.colors"]){
-dojo._hasResource["dojo.colors"]=true;
-dojo.provide("dojo.colors");
-(function(){
-var _1=function(m1,m2,h){
-if(h<0){
-++h;
-}
-if(h>1){
---h;
-}
-var h6=6*h;
-if(h6<1){
-return m1+(m2-m1)*h6;
-}
-if(2*h<1){
-return m2;
-}
-if(3*h<2){
-return m1+(m2-m1)*(2/3-h)*6;
-}
-return m1;
-};
-dojo.colorFromRgb=function(_2,_3){
-var m=_2.toLowerCase().match(/^(rgba?|hsla?)\(([\s\.\-,%0-9]+)\)/);
-if(m){
-var c=m[2].split(/\s*,\s*/),l=c.length,t=m[1],a;
-if((t=="rgb"&&l==3)||(t=="rgba"&&l==4)){
-var r=c[0];
-if(r.charAt(r.length-1)=="%"){
-a=dojo.map(c,function(x){
-return parseFloat(x)*2.56;
-});
-if(l==4){
-a[3]=c[3];
-}
-return dojo.colorFromArray(a,_3);
-}
-return dojo.colorFromArray(c,_3);
-}
-if((t=="hsl"&&l==3)||(t=="hsla"&&l==4)){
-var H=((parseFloat(c[0])%360)+360)%360/360,S=parseFloat(c[1])/100,L=parseFloat(c[2])/100,m2=L<=0.5?L*(S+1):L+S-L*S,m1=2*L-m2;
-a=[_1(m1,m2,H+1/3)*256,_1(m1,m2,H)*256,_1(m1,m2,H-1/3)*256,1];
-if(l==4){
-a[3]=c[3];
+/*=====
+dojo.colors = {
+	// summary: Color utilities
 }
-return dojo.colorFromArray(a,_3);
-}
-}
-return null;
-};
-var _4=function(c,_5,_6){
-c=Number(c);
-return isNaN(c)?_6:c<_5?_5:c>_6?_6:c;
-};
-dojo.Color.prototype.sanitize=function(){
-var t=this;
-t.r=Math.round(_4(t.r,0,255));
-t.g=Math.round(_4(t.g,0,255));
-t.b=Math.round(_4(t.b,0,255));
-t.a=_4(t.a,0,1);
-return this;
-};
+=====*/
+
+(function(){
+	// this is a standard conversion prescribed by the CSS3 Color Module
+	var hue2rgb = function(m1, m2, h){
+		if(h < 0){ ++h; }
+		if(h > 1){ --h; }
+		var h6 = 6 * h;
+		if(h6 < 1){ return m1 + (m2 - m1) * h6; }
+		if(2 * h < 1){ return m2; }
+		if(3 * h < 2){ return m1 + (m2 - m1) * (2 / 3 - h) * 6; }
+		return m1;
+	};
+	
+	dojo.colorFromRgb = function(/*String*/ color, /*dojo.Color?*/ obj){
+		// summary:
+		//		get rgb(a) array from css-style color declarations
+		// description:
+		//		this function can handle all 4 CSS3 Color Module formats: rgb,
+		//		rgba, hsl, hsla, including rgb(a) with percentage values.
+		var m = color.toLowerCase().match(/^(rgba?|hsla?)\(([\s\.\-,%0-9]+)\)/);
+		if(m){
+			var c = m[2].split(/\s*,\s*/), l = c.length, t = m[1], a;
+			if((t == "rgb" && l == 3) || (t == "rgba" && l == 4)){
+				var r = c[0];
+				if(r.charAt(r.length - 1) == "%"){
+					// 3 rgb percentage values
+					a = dojo.map(c, function(x){
+						return parseFloat(x) * 2.56;
+					});
+					if(l == 4){ a[3] = c[3]; }
+					return dojo.colorFromArray(a, obj);	// dojo.Color
+				}
+				return dojo.colorFromArray(c, obj);	// dojo.Color
+			}
+			if((t == "hsl" && l == 3) || (t == "hsla" && l == 4)){
+				// normalize hsl values
+				var H = ((parseFloat(c[0]) % 360) + 360) % 360 / 360,
+					S = parseFloat(c[1]) / 100,
+					L = parseFloat(c[2]) / 100,
+					// calculate rgb according to the algorithm 
+					// recommended by the CSS3 Color Module 
+					m2 = L <= 0.5 ? L * (S + 1) : L + S - L * S, 
+					m1 = 2 * L - m2;
+				a = [
+					hue2rgb(m1, m2, H + 1 / 3) * 256,
+					hue2rgb(m1, m2, H) * 256,
+					hue2rgb(m1, m2, H - 1 / 3) * 256,
+					1
+				];
+				if(l == 4){ a[3] = c[3]; }
+				return dojo.colorFromArray(a, obj);	// dojo.Color
+			}
+		}
+		return null;	// dojo.Color
+	};
+	
+	var confine = function(c, low, high){
+		// summary:
+		//		sanitize a color component by making sure it is a number,
+		//		and clamping it to valid values
+		c = Number(c);
+		return isNaN(c) ? high : c < low ? low : c > high ? high : c;	// Number
+	};
+	
+	dojo.Color.prototype.sanitize = function(){
+		// summary: makes sure that the object has correct attributes
+		var t = this;
+		t.r = Math.round(confine(t.r, 0, 255));
+		t.g = Math.round(confine(t.g, 0, 255));
+		t.b = Math.round(confine(t.b, 0, 255));
+		t.a = confine(t.a, 0, 1);
+		return this;	// dojo.Color
+	};
 })();
-dojo.colors.makeGrey=function(g,a){
-return dojo.colorFromArray([g,g,g,a]);
+
+
+dojo.colors.makeGrey = function(/*Number*/ g, /*Number?*/ a){
+	// summary: creates a greyscale color with an optional alpha
+	return dojo.colorFromArray([g, g, g, a]);
 };
-dojo.mixin(dojo.Color.named,{aliceblue:[240,248,255],antiquewhite:[250,235,215],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],blanchedalmond:[255,235,205],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod: [...]
-}
+
+// mixin all CSS3 named colors not already in _base, along with SVG 1.0 variant spellings
+dojo.mixin(dojo.Color.named, {
+	aliceblue:	[240,248,255],
+	antiquewhite:	[250,235,215],
+	aquamarine:	[127,255,212],
+	azure:	[240,255,255],
+	beige:	[245,245,220],
+	bisque:	[255,228,196],
+	blanchedalmond:	[255,235,205],
+	blueviolet:	[138,43,226],
+	brown:	[165,42,42],
+	burlywood:	[222,184,135],
+	cadetblue:	[95,158,160],
+	chartreuse:	[127,255,0],
+	chocolate:	[210,105,30],
+	coral:	[255,127,80],
+	cornflowerblue:	[100,149,237],
+	cornsilk:	[255,248,220],
+	crimson:	[220,20,60],
+	cyan:	[0,255,255],
+	darkblue:	[0,0,139],
+	darkcyan:	[0,139,139],
+	darkgoldenrod:	[184,134,11],
+	darkgray:	[169,169,169],
+	darkgreen:	[0,100,0],
+	darkgrey:	[169,169,169],
+	darkkhaki:	[189,183,107],
+	darkmagenta:	[139,0,139],
+	darkolivegreen:	[85,107,47],
+	darkorange:	[255,140,0],
+	darkorchid:	[153,50,204],
+	darkred:	[139,0,0],
+	darksalmon:	[233,150,122],
+	darkseagreen:	[143,188,143],
+	darkslateblue:	[72,61,139],
+	darkslategray:	[47,79,79],
+	darkslategrey:	[47,79,79],
+	darkturquoise:	[0,206,209],
+	darkviolet:	[148,0,211],
+	deeppink:	[255,20,147],
+	deepskyblue:	[0,191,255],
+	dimgray:	[105,105,105],
+	dimgrey:	[105,105,105],
+	dodgerblue:	[30,144,255],
+	firebrick:	[178,34,34],
+	floralwhite:	[255,250,240],
+	forestgreen:	[34,139,34],
+	gainsboro:	[220,220,220],
+	ghostwhite:	[248,248,255],
+	gold:	[255,215,0],
+	goldenrod:	[218,165,32],
+	greenyellow:	[173,255,47],
+	grey:	[128,128,128],
+	honeydew:	[240,255,240],
+	hotpink:	[255,105,180],
+	indianred:	[205,92,92],
+	indigo:	[75,0,130],
+	ivory:	[255,255,240],
+	khaki:	[240,230,140],
+	lavender:	[230,230,250],
+	lavenderblush:	[255,240,245],
+	lawngreen:	[124,252,0],
+	lemonchiffon:	[255,250,205],
+	lightblue:	[173,216,230],
+	lightcoral:	[240,128,128],
+	lightcyan:	[224,255,255],
+	lightgoldenrodyellow:	[250,250,210],
+	lightgray:	[211,211,211],
+	lightgreen:	[144,238,144],
+	lightgrey:	[211,211,211],
+	lightpink:	[255,182,193],
+	lightsalmon:	[255,160,122],
+	lightseagreen:	[32,178,170],
+	lightskyblue:	[135,206,250],
+	lightslategray:	[119,136,153],
+	lightslategrey:	[119,136,153],
+	lightsteelblue:	[176,196,222],
+	lightyellow:	[255,255,224],
+	limegreen:	[50,205,50],
+	linen:	[250,240,230],
+	magenta:	[255,0,255],
+	mediumaquamarine:	[102,205,170],
+	mediumblue:	[0,0,205],
+	mediumorchid:	[186,85,211],
+	mediumpurple:	[147,112,219],
+	mediumseagreen:	[60,179,113],
+	mediumslateblue:	[123,104,238],
+	mediumspringgreen:	[0,250,154],
+	mediumturquoise:	[72,209,204],
+	mediumvioletred:	[199,21,133],
+	midnightblue:	[25,25,112],
+	mintcream:	[245,255,250],
+	mistyrose:	[255,228,225],
+	moccasin:	[255,228,181],
+	navajowhite:	[255,222,173],
+	oldlace:	[253,245,230],
+	olivedrab:	[107,142,35],
+	orange:	[255,165,0],
+	orangered:	[255,69,0],
+	orchid:	[218,112,214],
+	palegoldenrod:	[238,232,170],
+	palegreen:	[152,251,152],
+	paleturquoise:	[175,238,238],
+	palevioletred:	[219,112,147],
+	papayawhip:	[255,239,213],
+	peachpuff:	[255,218,185],
+	peru:	[205,133,63],
+	pink:	[255,192,203],
+	plum:	[221,160,221],
+	powderblue:	[176,224,230],
+	rosybrown:	[188,143,143],
+	royalblue:	[65,105,225],
+	saddlebrown:	[139,69,19],
+	salmon:	[250,128,114],
+	sandybrown:	[244,164,96],
+	seagreen:	[46,139,87],
+	seashell:	[255,245,238],
+	sienna:	[160,82,45],
+	skyblue:	[135,206,235],
+	slateblue:	[106,90,205],
+	slategray:	[112,128,144],
+	slategrey:	[112,128,144],
+	snow:	[255,250,250],
+	springgreen:	[0,255,127],
+	steelblue:	[70,130,180],
+	tan:	[210,180,140],
+	thistle:	[216,191,216],
+	tomato:	[255,99,71],
+	transparent: [0, 0, 0, 0],
+	turquoise:	[64,224,208],
+	violet:	[238,130,238],
+	wheat:	[245,222,179],
+	whitesmoke:	[245,245,245],
+	yellowgreen:	[154,205,50]
+});
diff --git a/dojo/cookie.js b/dojo/cookie.js
index aa708a0..983918a 100644
--- a/dojo/cookie.js
+++ b/dojo/cookie.js
@@ -1,50 +1,91 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.cookie"]){
-dojo._hasResource["dojo.cookie"]=true;
 dojo.provide("dojo.cookie");
+
 dojo.require("dojo.regexp");
-dojo.cookie=function(_1,_2,_3){
-var c=document.cookie;
-if(arguments.length==1){
-var _4=c.match(new RegExp("(?:^|; )"+dojo.regexp.escapeString(_1)+"=([^;]*)"));
-return _4?decodeURIComponent(_4[1]):undefined;
-}else{
-_3=_3||{};
-var _5=_3.expires;
-if(typeof _5=="number"){
-var d=new Date();
-d.setTime(d.getTime()+_5*24*60*60*1000);
-_5=_3.expires=d;
-}
-if(_5&&_5.toUTCString){
-_3.expires=_5.toUTCString();
-}
-_2=encodeURIComponent(_2);
-var _6=_1+"="+_2,_7;
-for(_7 in _3){
-_6+="; "+_7;
-var _8=_3[_7];
-if(_8!==true){
-_6+="="+_8;
-}
-}
-document.cookie=_6;
+
+/*=====
+dojo.__cookieProps = function(){
+	//	expires: Date|String|Number?
+	//		If a number, the number of days from today at which the cookie
+	//		will expire. If a date, the date past which the cookie will expire.
+	//		If expires is in the past, the cookie will be deleted.
+	//		If expires is omitted or is 0, the cookie will expire when the browser closes. << FIXME: 0 seems to disappear right away? FF3.
+	//	path: String?
+	//		The path to use for the cookie.
+	//	domain: String?
+	//		The domain to use for the cookie.
+	//	secure: Boolean?
+	//		Whether to only send the cookie on secure connections
+	this.expires = expires;
+	this.path = path;
+	this.domain = domain;
+	this.secure = secure;
 }
+=====*/
+
+
+dojo.cookie = function(/*String*/name, /*String?*/value, /*dojo.__cookieProps?*/props){
+	//	summary: 
+	//		Get or set a cookie.
+	//	description:
+	// 		If one argument is passed, returns the value of the cookie
+	// 		For two or more arguments, acts as a setter.
+	//	name:
+	//		Name of the cookie
+	//	value:
+	//		Value for the cookie
+	//	props: 
+	//		Properties for the cookie
+	//	example:
+	//		set a cookie with the JSON-serialized contents of an object which
+	//		will expire 5 days from now:
+	//	|	dojo.cookie("configObj", dojo.toJson(config), { expires: 5 });
+	//	
+	//	example:
+	//		de-serialize a cookie back into a JavaScript object:
+	//	|	var config = dojo.fromJson(dojo.cookie("configObj"));
+	//	
+	//	example:
+	//		delete a cookie:
+	//	|	dojo.cookie("configObj", null, {expires: -1});
+	var c = document.cookie;
+	if(arguments.length == 1){
+		var matches = c.match(new RegExp("(?:^|; )" + dojo.regexp.escapeString(name) + "=([^;]*)"));
+		return matches ? decodeURIComponent(matches[1]) : undefined; // String or undefined
+	}else{
+		props = props || {};
+// FIXME: expires=0 seems to disappear right away, not on close? (FF3)  Change docs?
+		var exp = props.expires;
+		if(typeof exp == "number"){ 
+			var d = new Date();
+			d.setTime(d.getTime() + exp*24*60*60*1000);
+			exp = props.expires = d;
+		}
+		if(exp && exp.toUTCString){ props.expires = exp.toUTCString(); }
+
+		value = encodeURIComponent(value);
+		var updatedCookie = name + "=" + value, propName;
+		for(propName in props){
+			updatedCookie += "; " + propName;
+			var propValue = props[propName];
+			if(propValue !== true){ updatedCookie += "=" + propValue; }
+		}
+		document.cookie = updatedCookie;
+	}
 };
-dojo.cookie.isSupported=function(){
-if(!("cookieEnabled" in navigator)){
-this("__djCookieTest__","CookiesAllowed");
-navigator.cookieEnabled=this("__djCookieTest__")=="CookiesAllowed";
-if(navigator.cookieEnabled){
-this("__djCookieTest__","",{expires:-1});
-}
-}
-return navigator.cookieEnabled;
+
+dojo.cookie.isSupported = function(){
+	//	summary:
+	//		Use to determine if the current browser supports cookies or not.
+	//		
+	//		Returns true if user allows cookies.
+	//		Returns false if user doesn't allow cookies.
+
+	if(!("cookieEnabled" in navigator)){
+		this("__djCookieTest__", "CookiesAllowed");
+		navigator.cookieEnabled = this("__djCookieTest__") == "CookiesAllowed";
+		if(navigator.cookieEnabled){
+			this("__djCookieTest__", "", {expires: -1});
+		}
+	}
+	return navigator.cookieEnabled;
 };
-}
diff --git a/dojo/currency.js b/dojo/currency.js
index eb8e87f..79a0ecf 100644
--- a/dojo/currency.js
+++ b/dojo/currency.js
@@ -1,36 +1,128 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.currency"]){
-dojo._hasResource["dojo.currency"]=true;
 dojo.provide("dojo.currency");
+
 dojo.require("dojo.number");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojo.cldr","currency",null,"ROOT,ar,ca,cs,da,de,el,en,en-au,en-ca,en-us,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
+dojo.requireLocalization("dojo.cldr", "currency");
 dojo.require("dojo.cldr.monetary");
-dojo.currency._mixInDefaults=function(_1){
-_1=_1||{};
-_1.type="currency";
-var _2=dojo.i18n.getLocalization("dojo.cldr","currency",_1.locale)||{};
-var _3=_1.currency;
-var _4=dojo.cldr.monetary.getData(_3);
-dojo.forEach(["displayName","symbol","group","decimal"],function(_5){
-_4[_5]=_2[_3+"_"+_5];
+
+/*=====
+dojo.currency = {
+	// summary: localized formatting and parsing routines for currencies
+	//
+	// description: extends dojo.number to provide culturally-appropriate formatting of values
+	//	in various world currencies, including use of a currency symbol.  The currencies are specified
+	//	by a three-letter international symbol in all uppercase, and support for the currencies is
+	//	provided by the data in `dojo.cldr`.  The scripts generating dojo.cldr specify which
+	//	currency support is included.  A fixed number of decimal places is determined based
+	//	on the currency type and is not determined by the 'pattern' argument.  The fractional
+	//	portion is optional, by default, and variable length decimals are not supported.
+}
+=====*/
+
+dojo.currency._mixInDefaults = function(options){
+	options = options || {};
+	options.type = "currency";
+
+	// Get locale-dependent currency data, like the symbol
+	var bundle = dojo.i18n.getLocalization("dojo.cldr", "currency", options.locale) || {};
+
+	// Mixin locale-independent currency data, like # of places
+	var iso = options.currency;
+	var data = dojo.cldr.monetary.getData(iso);
+
+	dojo.forEach(["displayName","symbol","group","decimal"], function(prop){
+		data[prop] = bundle[iso+"_"+prop];
+	});
+
+	data.fractional = [true, false];
+
+	// Mixin with provided options
+	return dojo.mixin(data, options);
+}
+
+/*=====
+dojo.declare("dojo.currency.__FormatOptions", [dojo.number.__FormatOptions], {
+	//	type: String?
+	//		Should not be set.  Value is assumed to be "currency".
+	//	symbol: String?
+	//		localized currency symbol. The default will be looked up in table of supported currencies in `dojo.cldr`
+	//		A [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code will be used if not found.
+	//	currency: String?
+	//		an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD".
+	//		For use with dojo.currency only.
+	//	places: Number?
+	//		number of decimal places to show.  Default is defined based on which currency is used.
+	type: "",
+	symbol: "",
+	currency: "",
+	places: ""
 });
-_4.fractional=[true,false];
-return dojo.mixin(_4,_1);
-};
-dojo.currency.format=function(_6,_7){
-return dojo.number.format(_6,dojo.currency._mixInDefaults(_7));
-};
-dojo.currency.regexp=function(_8){
-return dojo.number.regexp(dojo.currency._mixInDefaults(_8));
-};
-dojo.currency.parse=function(_9,_a){
-return dojo.number.parse(_9,dojo.currency._mixInDefaults(_a));
-};
+=====*/
+
+dojo.currency.format = function(/*Number*/value, /*dojo.currency.__FormatOptions?*/options){
+// summary:
+//		Format a Number as a currency, using locale-specific settings
+//
+// description:
+//		Create a string from a Number using a known, localized pattern.
+//		[Formatting patterns](http://www.unicode.org/reports/tr35/#Number_Elements)
+//		appropriate to the locale are chosen from the [CLDR](http://unicode.org/cldr)
+//		as well as the appropriate symbols and delimiters and number of decimal places.
+//
+// value:
+//		the number to be formatted.
+
+	return dojo.number.format(value, dojo.currency._mixInDefaults(options));
+}
+
+dojo.currency.regexp = function(/*dojo.number.__RegexpOptions?*/options){
+//
+// summary:
+//		Builds the regular needed to parse a currency value
+//
+// description:
+//		Returns regular expression with positive and negative match, group and decimal separators
+//		Note: the options.places default, the number of decimal places to accept, is defined by the currency type.
+	return dojo.number.regexp(dojo.currency._mixInDefaults(options)); // String
+}
+
+/*=====
+dojo.declare("dojo.currency.__ParseOptions", [dojo.number.__ParseOptions], {
+	//	type: String?
+	//		Should not be set.  Value is assumed to be currency.
+	//	currency: String?
+	//		an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD".
+	//		For use with dojo.currency only.
+	//	symbol: String?
+	//		localized currency symbol. The default will be looked up in table of supported currencies in `dojo.cldr`
+	//		A [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code will be used if not found.
+	//	places: Number?
+	//		fixed number of decimal places to accept.  The default is determined based on which currency is used.
+	//	fractional: Boolean?|Array?
+	//		Whether to include the fractional portion, where the number of decimal places are implied by the currency
+	//		or explicit 'places' parameter.  The value [true,false] makes the fractional portion optional.
+	//		By default for currencies, it the fractional portion is optional.
+	type: "",
+	currency: "",
+	symbol: "",
+	places: "",
+	fractional: ""
+});
+=====*/
+
+dojo.currency.parse = function(/*String*/expression, /*dojo.currency.__ParseOptions?*/options){
+	//
+	// summary:
+	//		Convert a properly formatted currency string to a primitive Number,
+	//		using locale-specific settings.
+	//
+	// description:
+	//		Create a Number from a string using a known, localized pattern.
+	//		[Formatting patterns](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+	//		are chosen appropriate to the locale, as well as the appropriate symbols and delimiters
+	//		and number of decimal places.
+	//
+	// expression: A string representation of a currency value
+
+	return dojo.number.parse(expression, dojo.currency._mixInDefaults(options));
 }
diff --git a/dojo/data/ItemFileReadStore.js b/dojo/data/ItemFileReadStore.js
index 5414641..4dc1dde 100644
--- a/dojo/data/ItemFileReadStore.js
+++ b/dojo/data/ItemFileReadStore.js
@@ -1,572 +1,938 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.data.ItemFileReadStore"]){
-dojo._hasResource["dojo.data.ItemFileReadStore"]=true;
 dojo.provide("dojo.data.ItemFileReadStore");
+
 dojo.require("dojo.data.util.filter");
 dojo.require("dojo.data.util.simpleFetch");
 dojo.require("dojo.date.stamp");
-dojo.declare("dojo.data.ItemFileReadStore",null,{constructor:function(_1){
-this._arrayOfAllItems=[];
-this._arrayOfTopLevelItems=[];
-this._loadFinished=false;
-this._jsonFileUrl=_1.url;
-this._ccUrl=_1.url;
-this.url=_1.url;
-this._jsonData=_1.data;
-this.data=null;
-this._datatypeMap=_1.typeMap||{};
-if(!this._datatypeMap["Date"]){
-this._datatypeMap["Date"]={type:Date,deserialize:function(_2){
-return dojo.date.stamp.fromISOString(_2);
-}};
-}
-this._features={"dojo.data.api.Read":true,"dojo.data.api.Identity":true};
-this._itemsByIdentity=null;
-this._storeRefPropName="_S";
-this._itemNumPropName="_0";
-this._rootItemPropName="_RI";
-this._reverseRefMap="_RRM";
-this._loadInProgress=false;
-this._queuedFetches=[];
-if(_1.urlPreventCache!==undefined){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-if(_1.hierarchical!==undefined){
-this.hierarchical=_1.hierarchical?true:false;
-}
-if(_1.clearOnClose){
-this.clearOnClose=true;
-}
-if("failOk" in _1){
-this.failOk=_1.failOk?true:false;
-}
-},url:"",_ccUrl:"",data:null,typeMap:null,clearOnClose:false,urlPreventCache:false,failOk:false,hierarchical:true,_assertIsItem:function(_3){
-if(!this.isItem(_3)){
-throw new Error("dojo.data.ItemFileReadStore: Invalid item argument.");
-}
-},_assertIsAttribute:function(_4){
-if(typeof _4!=="string"){
-throw new Error("dojo.data.ItemFileReadStore: Invalid attribute argument.");
-}
-},getValue:function(_5,_6,_7){
-var _8=this.getValues(_5,_6);
-return (_8.length>0)?_8[0]:_7;
-},getValues:function(_9,_a){
-this._assertIsItem(_9);
-this._assertIsAttribute(_a);
-return _9[_a]||[];
-},getAttributes:function(_b){
-this._assertIsItem(_b);
-var _c=[];
-for(var _d in _b){
-if((_d!==this._storeRefPropName)&&(_d!==this._itemNumPropName)&&(_d!==this._rootItemPropName)&&(_d!==this._reverseRefMap)){
-_c.push(_d);
-}
-}
-return _c;
-},hasAttribute:function(_e,_f){
-this._assertIsItem(_e);
-this._assertIsAttribute(_f);
-return (_f in _e);
-},containsValue:function(_10,_11,_12){
-var _13=undefined;
-if(typeof _12==="string"){
-_13=dojo.data.util.filter.patternToRegExp(_12,false);
-}
-return this._containsValue(_10,_11,_12,_13);
-},_containsValue:function(_14,_15,_16,_17){
-return dojo.some(this.getValues(_14,_15),function(_18){
-if(_18!==null&&!dojo.isObject(_18)&&_17){
-if(_18.toString().match(_17)){
-return true;
-}
-}else{
-if(_16===_18){
-return true;
-}
-}
-});
-},isItem:function(_19){
-if(_19&&_19[this._storeRefPropName]===this){
-if(this._arrayOfAllItems[_19[this._itemNumPropName]]===_19){
-return true;
-}
-}
-return false;
-},isItemLoaded:function(_1a){
-return this.isItem(_1a);
-},loadItem:function(_1b){
-this._assertIsItem(_1b.item);
-},getFeatures:function(){
-return this._features;
-},getLabel:function(_1c){
-if(this._labelAttr&&this.isItem(_1c)){
-return this.getValue(_1c,this._labelAttr);
-}
-return undefined;
-},getLabelAttributes:function(_1d){
-if(this._labelAttr){
-return [this._labelAttr];
-}
-return null;
-},_fetchItems:function(_1e,_1f,_20){
-var _21=this;
-var _22=function(_23,_24){
-var _25=[];
-var i,key;
-if(_23.query){
-var _26;
-var _27=_23.queryOptions?_23.queryOptions.ignoreCase:false;
-var _28={};
-for(key in _23.query){
-_26=_23.query[key];
-if(typeof _26==="string"){
-_28[key]=dojo.data.util.filter.patternToRegExp(_26,_27);
-}else{
-if(_26 instanceof RegExp){
-_28[key]=_26;
-}
-}
-}
-for(i=0;i<_24.length;++i){
-var _29=true;
-var _2a=_24[i];
-if(_2a===null){
-_29=false;
-}else{
-for(key in _23.query){
-_26=_23.query[key];
-if(!_21._containsValue(_2a,key,_26,_28[key])){
-_29=false;
-}
-}
-}
-if(_29){
-_25.push(_2a);
-}
-}
-_1f(_25,_23);
-}else{
-for(i=0;i<_24.length;++i){
-var _2b=_24[i];
-if(_2b!==null){
-_25.push(_2b);
-}
-}
-_1f(_25,_23);
-}
-};
-if(this._loadFinished){
-_22(_1e,this._getItemsArray(_1e.queryOptions));
-}else{
-if(this._jsonFileUrl!==this._ccUrl){
-dojo.deprecated("dojo.data.ItemFileReadStore: ","To change the url, set the url property of the store,"+" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
-this._ccUrl=this._jsonFileUrl;
-this.url=this._jsonFileUrl;
-}else{
-if(this.url!==this._ccUrl){
-this._jsonFileUrl=this.url;
-this._ccUrl=this.url;
-}
-}
-if(this.data!=null&&this._jsonData==null){
-this._jsonData=this.data;
-this.data=null;
-}
-if(this._jsonFileUrl){
-if(this._loadInProgress){
-this._queuedFetches.push({args:_1e,filter:_22});
-}else{
-this._loadInProgress=true;
-var _2c={url:_21._jsonFileUrl,handleAs:"json-comment-optional",preventCache:this.urlPreventCache,failOk:this.failOk};
-var _2d=dojo.xhrGet(_2c);
-_2d.addCallback(function(_2e){
-try{
-_21._getItemsFromLoadedData(_2e);
-_21._loadFinished=true;
-_21._loadInProgress=false;
-_22(_1e,_21._getItemsArray(_1e.queryOptions));
-_21._handleQueuedFetches();
-}
-catch(e){
-_21._loadFinished=true;
-_21._loadInProgress=false;
-_20(e,_1e);
-}
-});
-_2d.addErrback(function(_2f){
-_21._loadInProgress=false;
-_20(_2f,_1e);
-});
-var _30=null;
-if(_1e.abort){
-_30=_1e.abort;
-}
-_1e.abort=function(){
-var df=_2d;
-if(df&&df.fired===-1){
-df.cancel();
-df=null;
-}
-if(_30){
-_30.call(_1e);
-}
-};
-}
-}else{
-if(this._jsonData){
-try{
-this._loadFinished=true;
-this._getItemsFromLoadedData(this._jsonData);
-this._jsonData=null;
-_22(_1e,this._getItemsArray(_1e.queryOptions));
-}
-catch(e){
-_20(e,_1e);
-}
-}else{
-_20(new Error("dojo.data.ItemFileReadStore: No JSON source data was provided as either URL or a nested Javascript object."),_1e);
-}
-}
-}
-},_handleQueuedFetches:function(){
-if(this._queuedFetches.length>0){
-for(var i=0;i<this._queuedFetches.length;i++){
-var _31=this._queuedFetches[i];
-var _32=_31.args;
-var _33=_31.filter;
-if(_33){
-_33(_32,this._getItemsArray(_32.queryOptions));
-}else{
-this.fetchItemByIdentity(_32);
-}
-}
-this._queuedFetches=[];
-}
-},_getItemsArray:function(_34){
-if(_34&&_34.deep){
-return this._arrayOfAllItems;
-}
-return this._arrayOfTopLevelItems;
-},close:function(_35){
-if(this.clearOnClose&&this._loadFinished&&!this._loadInProgress){
-if(((this._jsonFileUrl==""||this._jsonFileUrl==null)&&(this.url==""||this.url==null))&&this.data==null){
-}
-this._arrayOfAllItems=[];
-this._arrayOfTopLevelItems=[];
-this._loadFinished=false;
-this._itemsByIdentity=null;
-this._loadInProgress=false;
-this._queuedFetches=[];
-}
-},_getItemsFromLoadedData:function(_36){
-var _37=false;
-var _38=this;
-function _39(_3a){
-var _3b=((_3a!==null)&&(typeof _3a==="object")&&(!dojo.isArray(_3a)||_37)&&(!dojo.isFunction(_3a))&&(_3a.constructor==Object||dojo.isArray(_3a))&&(typeof _3a._reference==="undefined")&&(typeof _3a._type==="undefined")&&(typeof _3a._value==="undefined")&&_38.hierarchical);
-return _3b;
-};
-function _3c(_3d){
-_38._arrayOfAllItems.push(_3d);
-for(var _3e in _3d){
-var _3f=_3d[_3e];
-if(_3f){
-if(dojo.isArray(_3f)){
-var _40=_3f;
-for(var k=0;k<_40.length;++k){
-var _41=_40[k];
-if(_39(_41)){
-_3c(_41);
-}
-}
-}else{
-if(_39(_3f)){
-_3c(_3f);
-}
-}
-}
-}
-};
-this._labelAttr=_36.label;
-var i;
-var _42;
-this._arrayOfAllItems=[];
-this._arrayOfTopLevelItems=_36.items;
-for(i=0;i<this._arrayOfTopLevelItems.length;++i){
-_42=this._arrayOfTopLevelItems[i];
-if(dojo.isArray(_42)){
-_37=true;
-}
-_3c(_42);
-_42[this._rootItemPropName]=true;
-}
-var _43={};
-var key;
-for(i=0;i<this._arrayOfAllItems.length;++i){
-_42=this._arrayOfAllItems[i];
-for(key in _42){
-if(key!==this._rootItemPropName){
-var _44=_42[key];
-if(_44!==null){
-if(!dojo.isArray(_44)){
-_42[key]=[_44];
-}
-}else{
-_42[key]=[null];
-}
-}
-_43[key]=key;
-}
-}
-while(_43[this._storeRefPropName]){
-this._storeRefPropName+="_";
-}
-while(_43[this._itemNumPropName]){
-this._itemNumPropName+="_";
-}
-while(_43[this._reverseRefMap]){
-this._reverseRefMap+="_";
-}
-var _45;
-var _46=_36.identifier;
-if(_46){
-this._itemsByIdentity={};
-this._features["dojo.data.api.Identity"]=_46;
-for(i=0;i<this._arrayOfAllItems.length;++i){
-_42=this._arrayOfAllItems[i];
-_45=_42[_46];
-var _47=_45[0];
-if(!this._itemsByIdentity[_47]){
-this._itemsByIdentity[_47]=_42;
-}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: ["+_46+"].  Value collided: ["+_47+"]");
-}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: ["+_46+"].  Value collided: ["+_47+"]");
-}
-}
-}
-}
-}else{
-this._features["dojo.data.api.Identity"]=Number;
-}
-for(i=0;i<this._arrayOfAllItems.length;++i){
-_42=this._arrayOfAllItems[i];
-_42[this._storeRefPropName]=this;
-_42[this._itemNumPropName]=i;
-}
-for(i=0;i<this._arrayOfAllItems.length;++i){
-_42=this._arrayOfAllItems[i];
-for(key in _42){
-_45=_42[key];
-for(var j=0;j<_45.length;++j){
-_44=_45[j];
-if(_44!==null&&typeof _44=="object"){
-if(("_type" in _44)&&("_value" in _44)){
-var _48=_44._type;
-var _49=this._datatypeMap[_48];
-if(!_49){
-throw new Error("dojo.data.ItemFileReadStore: in the typeMap constructor arg, no object class was specified for the datatype '"+_48+"'");
-}else{
-if(dojo.isFunction(_49)){
-_45[j]=new _49(_44._value);
-}else{
-if(dojo.isFunction(_49.deserialize)){
-_45[j]=_49.deserialize(_44._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(_44._reference){
-var _4a=_44._reference;
-if(!dojo.isObject(_4a)){
-_45[j]=this._itemsByIdentity[_4a];
-}else{
-for(var k=0;k<this._arrayOfAllItems.length;++k){
-var _4b=this._arrayOfAllItems[k];
-var _4c=true;
-for(var _4d in _4a){
-if(_4b[_4d]!=_4a[_4d]){
-_4c=false;
-}
-}
-if(_4c){
-_45[j]=_4b;
-}
-}
-}
-if(this.referenceIntegrity){
-var _4e=_45[j];
-if(this.isItem(_4e)){
-this._addReferenceToMap(_4e,_42,key);
-}
-}
-}else{
-if(this.isItem(_44)){
-if(this.referenceIntegrity){
-this._addReferenceToMap(_44,_42,key);
-}
-}
-}
-}
-}
-}
-}
-},_addReferenceToMap:function(_4f,_50,_51){
-},getIdentity:function(_52){
-var _53=this._features["dojo.data.api.Identity"];
-if(_53===Number){
-return _52[this._itemNumPropName];
-}else{
-var _54=_52[_53];
-if(_54){
-return _54[0];
-}
-}
-return null;
-},fetchItemByIdentity:function(_55){
-var _56;
-var _57;
-if(!this._loadFinished){
-var _58=this;
-if(this._jsonFileUrl!==this._ccUrl){
-dojo.deprecated("dojo.data.ItemFileReadStore: ","To change the url, set the url property of the store,"+" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
-this._ccUrl=this._jsonFileUrl;
-this.url=this._jsonFileUrl;
-}else{
-if(this.url!==this._ccUrl){
-this._jsonFileUrl=this.url;
-this._ccUrl=this.url;
-}
-}
-if(this.data!=null&&this._jsonData==null){
-this._jsonData=this.data;
-this.data=null;
-}
-if(this._jsonFileUrl){
-if(this._loadInProgress){
-this._queuedFetches.push({args:_55});
-}else{
-this._loadInProgress=true;
-var _59={url:_58._jsonFileUrl,handleAs:"json-comment-optional",preventCache:this.urlPreventCache,failOk:this.failOk};
-var _5a=dojo.xhrGet(_59);
-_5a.addCallback(function(_5b){
-var _5c=_55.scope?_55.scope:dojo.global;
-try{
-_58._getItemsFromLoadedData(_5b);
-_58._loadFinished=true;
-_58._loadInProgress=false;
-_56=_58._getItemByIdentity(_55.identity);
-if(_55.onItem){
-_55.onItem.call(_5c,_56);
-}
-_58._handleQueuedFetches();
-}
-catch(error){
-_58._loadInProgress=false;
-if(_55.onError){
-_55.onError.call(_5c,error);
-}
-}
-});
-_5a.addErrback(function(_5d){
-_58._loadInProgress=false;
-if(_55.onError){
-var _5e=_55.scope?_55.scope:dojo.global;
-_55.onError.call(_5e,_5d);
-}
-});
-}
-}else{
-if(this._jsonData){
-_58._getItemsFromLoadedData(_58._jsonData);
-_58._jsonData=null;
-_58._loadFinished=true;
-_56=_58._getItemByIdentity(_55.identity);
-if(_55.onItem){
-_57=_55.scope?_55.scope:dojo.global;
-_55.onItem.call(_57,_56);
-}
-}
-}
-}else{
-_56=this._getItemByIdentity(_55.identity);
-if(_55.onItem){
-_57=_55.scope?_55.scope:dojo.global;
-_55.onItem.call(_57,_56);
-}
-}
-},_getItemByIdentity:function(_5f){
-var _60=null;
-if(this._itemsByIdentity){
-_60=this._itemsByIdentity[_5f];
-}else{
-_60=this._arrayOfAllItems[_5f];
-}
-if(_60===undefined){
-_60=null;
-}
-return _60;
-},getIdentityAttributes:function(_61){
-var _62=this._features["dojo.data.api.Identity"];
-if(_62===Number){
-return null;
-}else{
-return [_62];
-}
-},_forceLoad:function(){
-var _63=this;
-if(this._jsonFileUrl!==this._ccUrl){
-dojo.deprecated("dojo.data.ItemFileReadStore: ","To change the url, set the url property of the store,"+" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
-this._ccUrl=this._jsonFileUrl;
-this.url=this._jsonFileUrl;
-}else{
-if(this.url!==this._ccUrl){
-this._jsonFileUrl=this.url;
-this._ccUrl=this.url;
-}
-}
-if(this.data!=null&&this._jsonData==null){
-this._jsonData=this.data;
-this.data=null;
-}
-if(this._jsonFileUrl){
-var _64={url:this._jsonFileUrl,handleAs:"json-comment-optional",preventCache:this.urlPreventCache,failOk:this.failOk,sync:true};
-var _65=dojo.xhrGet(_64);
-_65.addCallback(function(_66){
-try{
-if(_63._loadInProgress!==true&&!_63._loadFinished){
-_63._getItemsFromLoadedData(_66);
-_63._loadFinished=true;
-}else{
-if(_63._loadInProgress){
-throw new Error("dojo.data.ItemFileReadStore:  Unable to perform a synchronous load, an async load is in progress.");
-}
-}
-}
-catch(e){
-throw e;
-}
-});
-_65.addErrback(function(_67){
-throw _67;
+
+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._ccUrl = keywordParameters.url;
+		this.url = keywordParameters.url;
+		this._jsonData = keywordParameters.data;
+		this.data = null;
+		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.hierarchical !== undefined){
+			this.hierarchical = keywordParameters.hierarchical?true:false;
+		}
+		if(keywordParameters.clearOnClose){
+			this.clearOnClose = true;
+		}
+		if("failOk" in keywordParameters){
+			this.failOk = keywordParameters.failOk?true:false;
+		}
+	},
+	
+	url: "",	// use "" rather than undefined for the benefit of the parser (#3539)
+
+	//Internal var, crossCheckUrl.  Used so that setting either url or _jsonFileUrl, can still trigger a reload
+	//when clearOnClose and close is used.
+	_ccUrl: "",
+
+	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,
+	
+	//Parameter for specifying that it is OK for the xhrGet call to fail silently.
+	failOk: false,
+
+	//Parameter to indicate to process data from the url as hierarchical 
+	//(data items can contain other data items in js form).  Default is true 
+	//for backwards compatibility.  False means only root items are processed 
+	//as items, all child objects outside of type-mapped objects and those in 
+	//specific reference format, are left straight JS data objects.
+	hierarchical: true,
+
+	_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);
+		// Clone it before returning.  refs: #10474
+		return (item[attribute] || []).slice(0); // 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()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		return (attribute in item);
+	},
+
+	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,
+		    filter = function(requestArgs, arrayOfItems){
+			var items = [],
+			    i, key;
+			if(requestArgs.query){
+				var value,
+				    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);
+					}else if(value instanceof RegExp){
+						regexpList[key] = value;
+					}
+				}
+				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{
+			//Do a check on the JsonFileUrl and crosscheck it.
+			//If it doesn't match the cross-check, it needs to be updated
+			//This allows for either url or _jsonFileUrl to he changed to
+			//reset the store load location.  Done this way for backwards 
+			//compatibility.  People use _jsonFileUrl (even though officially
+			//private.
+			if(this._jsonFileUrl !== this._ccUrl){
+				dojo.deprecated("dojo.data.ItemFileReadStore: ", 
+					"To change the url, set the url property of the store," +
+					" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
+				this._ccUrl = this._jsonFileUrl;
+				this.url = this._jsonFileUrl;
+			}else if(this.url !== this._ccUrl){
+				this._jsonFileUrl = this.url;
+				this._ccUrl = this.url;
+			}
+
+			//See if there was any forced reset of data.
+			if(this.data != null && this._jsonData == null){
+				this._jsonData = this.data;
+				this.data = null;
+			}
+
+			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,
+							failOk: this.failOk
+						};
+					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],
+				    delayedQuery = fData.args,
+				    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._loadFinished && 
+			!this._loadInProgress){
+			 //Reset all internalsback to default state.  This will force a reload
+			 //on next fetch.  This also checks that the data or url param was set 
+			 //so that the store knows it can get data.  Without one of those being set,
+			 //the next fetch will trigger an error.
+
+			 if(((this._jsonFileUrl == "" || this._jsonFileUrl == null) && 
+				 (this.url == "" || this.url == null)
+				) && this.data == null){
+				 console.debug("dojo.data.ItemFileReadStore: WARNING!  Data reload " +
+					" information has not been provided." + 
+					"  Please set 'url' or 'data' to the appropriate value before" +
+					" the next fetch");
+			 }
+			 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,
+		    self = this;
+		
+		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") &&
+				self.hierarchical
+			);
+			return isItem;
+		}
+		
+		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,
+		    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 = {},
+		    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(("_type" in value) && ("_value" in 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._getItemByIdentity(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],
+									    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,
+		    scope;
+		if(!this._loadFinished){
+			var self = this;
+			//Do a check on the JsonFileUrl and crosscheck it.
+			//If it doesn't match the cross-check, it needs to be updated
+			//This allows for either url or _jsonFileUrl to he changed to
+			//reset the store load location.  Done this way for backwards 
+			//compatibility.  People use _jsonFileUrl (even though officially
+			//private.
+			if(this._jsonFileUrl !== this._ccUrl){
+				dojo.deprecated("dojo.data.ItemFileReadStore: ", 
+					"To change the url, set the url property of the store," +
+					" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
+				this._ccUrl = this._jsonFileUrl;
+				this.url = this._jsonFileUrl;
+			}else if(this.url !== this._ccUrl){
+				this._jsonFileUrl = this.url;
+				this._ccUrl = this.url;
+			}
+			
+			//See if there was any forced reset of data.
+			if(this.data != null && this._jsonData == null){
+				this._jsonData = this.data;
+				this.data = null;
+			}
+
+			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,
+							failOk: this.failOk
+					};
+					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;
+		//Do a check on the JsonFileUrl and crosscheck it.
+		//If it doesn't match the cross-check, it needs to be updated
+		//This allows for either url or _jsonFileUrl to he changed to
+		//reset the store load location.  Done this way for backwards 
+		//compatibility.  People use _jsonFileUrl (even though officially
+		//private.
+		if(this._jsonFileUrl !== this._ccUrl){
+			dojo.deprecated("dojo.data.ItemFileReadStore: ", 
+				"To change the url, set the url property of the store," +
+				" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
+			this._ccUrl = this._jsonFileUrl;
+			this.url = this._jsonFileUrl;
+		}else if(this.url !== this._ccUrl){
+			this._jsonFileUrl = this.url;
+			this._ccUrl = this.url;
+		}
+
+		//See if there was any forced reset of data.
+		if(this.data != null && this._jsonData == null){
+			this._jsonData = this.data;
+			this.data = null;
+		}
+
+		if(this._jsonFileUrl){
+				var getArgs = {
+					url: this._jsonFileUrl, 
+					handleAs: "json-comment-optional",
+					preventCache: this.urlPreventCache,
+					failOk: this.failOk,
+					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){
+					console.log(e);
+					throw e;
+				}
+			});
+			getHandler.addErrback(function(error){
+				throw error;
+			});
+		}else if(this._jsonData){
+			self._getItemsFromLoadedData(self._jsonData);
+			self._jsonData = null;
+			self._loadFinished = true;
+		} 
+	}
 });
-}else{
-if(this._jsonData){
-_63._getItemsFromLoadedData(_63._jsonData);
-_63._jsonData=null;
-_63._loadFinished=true;
-}
-}
-}});
+//Mix in the simple fetch implementation to this class.
 dojo.extend(dojo.data.ItemFileReadStore,dojo.data.util.simpleFetch);
-}
diff --git a/dojo/data/ItemFileWriteStore.js b/dojo/data/ItemFileWriteStore.js
index 3f4c01b..c8a1ed0 100644
--- a/dojo/data/ItemFileWriteStore.js
+++ b/dojo/data/ItemFileWriteStore.js
@@ -1,511 +1,806 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.data.ItemFileWriteStore"]){
-dojo._hasResource["dojo.data.ItemFileWriteStore"]=true;
 dojo.provide("dojo.data.ItemFileWriteStore");
 dojo.require("dojo.data.ItemFileReadStore");
-dojo.declare("dojo.data.ItemFileWriteStore",dojo.data.ItemFileReadStore,{constructor:function(_1){
-this._features["dojo.data.api.Write"]=true;
-this._features["dojo.data.api.Notification"]=true;
-this._pending={_newItems:{},_modifiedItems:{},_deletedItems:{}};
-if(!this._datatypeMap["Date"].serialize){
-this._datatypeMap["Date"].serialize=function(_2){
-return dojo.date.stamp.toISOString(_2,{zulu:true});
-};
-}
-if(_1&&(_1.referenceIntegrity===false)){
-this.referenceIntegrity=false;
-}
-this._saveInProgress=false;
-},referenceIntegrity:true,_assert:function(_3){
-if(!_3){
-throw new Error("assertion failed in ItemFileWriteStore");
-}
-},_getIdentifierAttribute:function(){
-var _4=this.getFeatures()["dojo.data.api.Identity"];
-return _4;
-},newItem:function(_5,_6){
-this._assert(!this._saveInProgress);
-if(!this._loadFinished){
-this._forceLoad();
-}
-if(typeof _5!="object"&&typeof _5!="undefined"){
-throw new Error("newItem() was passed something other than an object");
-}
-var _7=null;
-var _8=this._getIdentifierAttribute();
-if(_8===Number){
-_7=this._arrayOfAllItems.length;
-}else{
-_7=_5[_8];
-if(typeof _7==="undefined"){
-throw new Error("newItem() was not passed an identity for the new item");
-}
-if(dojo.isArray(_7)){
-throw new Error("newItem() was not passed an single-valued identity");
-}
-}
-if(this._itemsByIdentity){
-this._assert(typeof this._itemsByIdentity[_7]==="undefined");
-}
-this._assert(typeof this._pending._newItems[_7]==="undefined");
-this._assert(typeof this._pending._deletedItems[_7]==="undefined");
-var _9={};
-_9[this._storeRefPropName]=this;
-_9[this._itemNumPropName]=this._arrayOfAllItems.length;
-if(this._itemsByIdentity){
-this._itemsByIdentity[_7]=_9;
-_9[_8]=[_7];
-}
-this._arrayOfAllItems.push(_9);
-var _a=null;
-if(_6&&_6.parent&&_6.attribute){
-_a={item:_6.parent,attribute:_6.attribute,oldValue:undefined};
-var _b=this.getValues(_6.parent,_6.attribute);
-if(_b&&_b.length>0){
-var _c=_b.slice(0,_b.length);
-if(_b.length===1){
-_a.oldValue=_b[0];
-}else{
-_a.oldValue=_b.slice(0,_b.length);
-}
-_c.push(_9);
-this._setValueOrValues(_6.parent,_6.attribute,_c,false);
-_a.newValue=this.getValues(_6.parent,_6.attribute);
-}else{
-this._setValueOrValues(_6.parent,_6.attribute,_9,false);
-_a.newValue=_9;
-}
-}else{
-_9[this._rootItemPropName]=true;
-this._arrayOfTopLevelItems.push(_9);
-}
-this._pending._newItems[_7]=_9;
-for(var _d in _5){
-if(_d===this._storeRefPropName||_d===this._itemNumPropName){
-throw new Error("encountered bug in ItemFileWriteStore.newItem");
-}
-var _e=_5[_d];
-if(!dojo.isArray(_e)){
-_e=[_e];
-}
-_9[_d]=_e;
-if(this.referenceIntegrity){
-for(var i=0;i<_e.length;i++){
-var _f=_e[i];
-if(this.isItem(_f)){
-this._addReferenceToMap(_f,_9,_d);
-}
-}
-}
-}
-this.onNew(_9,_a);
-return _9;
-},_removeArrayElement:function(_10,_11){
-var _12=dojo.indexOf(_10,_11);
-if(_12!=-1){
-_10.splice(_12,1);
-return true;
-}
-return false;
-},deleteItem:function(_13){
-this._assert(!this._saveInProgress);
-this._assertIsItem(_13);
-var _14=_13[this._itemNumPropName];
-var _15=this.getIdentity(_13);
-if(this.referenceIntegrity){
-var _16=this.getAttributes(_13);
-if(_13[this._reverseRefMap]){
-_13["backup_"+this._reverseRefMap]=dojo.clone(_13[this._reverseRefMap]);
-}
-dojo.forEach(_16,function(_17){
-dojo.forEach(this.getValues(_13,_17),function(_18){
-if(this.isItem(_18)){
-if(!_13["backupRefs_"+this._reverseRefMap]){
-_13["backupRefs_"+this._reverseRefMap]=[];
-}
-_13["backupRefs_"+this._reverseRefMap].push({id:this.getIdentity(_18),attr:_17});
-this._removeReferenceFromMap(_18,_13,_17);
-}
-},this);
-},this);
-var _19=_13[this._reverseRefMap];
-if(_19){
-for(var _1a in _19){
-var _1b=null;
-if(this._itemsByIdentity){
-_1b=this._itemsByIdentity[_1a];
-}else{
-_1b=this._arrayOfAllItems[_1a];
-}
-if(_1b){
-for(var _1c in _19[_1a]){
-var _1d=this.getValues(_1b,_1c)||[];
-var _1e=dojo.filter(_1d,function(_1f){
-return !(this.isItem(_1f)&&this.getIdentity(_1f)==_15);
-},this);
-this._removeReferenceFromMap(_13,_1b,_1c);
-if(_1e.length<_1d.length){
-this._setValueOrValues(_1b,_1c,_1e,true);
-}
-}
-}
-}
-}
-}
-this._arrayOfAllItems[_14]=null;
-_13[this._storeRefPropName]=null;
-if(this._itemsByIdentity){
-delete this._itemsByIdentity[_15];
-}
-this._pending._deletedItems[_15]=_13;
-if(_13[this._rootItemPropName]){
-this._removeArrayElement(this._arrayOfTopLevelItems,_13);
-}
-this.onDelete(_13);
-return true;
-},setValue:function(_20,_21,_22){
-return this._setValueOrValues(_20,_21,_22,true);
-},setValues:function(_23,_24,_25){
-return this._setValueOrValues(_23,_24,_25,true);
-},unsetAttribute:function(_26,_27){
-return this._setValueOrValues(_26,_27,[],true);
-},_setValueOrValues:function(_28,_29,_2a,_2b){
-this._assert(!this._saveInProgress);
-this._assertIsItem(_28);
-this._assert(dojo.isString(_29));
-this._assert(typeof _2a!=="undefined");
-var _2c=this._getIdentifierAttribute();
-if(_29==_2c){
-throw new Error("ItemFileWriteStore does not have support for changing the value of an item's identifier.");
-}
-var _2d=this._getValueOrValues(_28,_29);
-var _2e=this.getIdentity(_28);
-if(!this._pending._modifiedItems[_2e]){
-var _2f={};
-for(var key in _28){
-if((key===this._storeRefPropName)||(key===this._itemNumPropName)||(key===this._rootItemPropName)){
-_2f[key]=_28[key];
-}else{
-if(key===this._reverseRefMap){
-_2f[key]=dojo.clone(_28[key]);
-}else{
-_2f[key]=_28[key].slice(0,_28[key].length);
-}
-}
-}
-this._pending._modifiedItems[_2e]=_2f;
-}
-var _30=false;
-if(dojo.isArray(_2a)&&_2a.length===0){
-_30=delete _28[_29];
-_2a=undefined;
-if(this.referenceIntegrity&&_2d){
-var _31=_2d;
-if(!dojo.isArray(_31)){
-_31=[_31];
-}
-for(var i=0;i<_31.length;i++){
-var _32=_31[i];
-if(this.isItem(_32)){
-this._removeReferenceFromMap(_32,_28,_29);
-}
-}
-}
-}else{
-var _33;
-if(dojo.isArray(_2a)){
-var _34=_2a;
-_33=_2a.slice(0,_2a.length);
-}else{
-_33=[_2a];
-}
-if(this.referenceIntegrity){
-if(_2d){
-var _31=_2d;
-if(!dojo.isArray(_31)){
-_31=[_31];
-}
-var map={};
-dojo.forEach(_31,function(_35){
-if(this.isItem(_35)){
-var id=this.getIdentity(_35);
-map[id.toString()]=true;
-}
-},this);
-dojo.forEach(_33,function(_36){
-if(this.isItem(_36)){
-var id=this.getIdentity(_36);
-if(map[id.toString()]){
-delete map[id.toString()];
-}else{
-this._addReferenceToMap(_36,_28,_29);
-}
-}
-},this);
-for(var rId in map){
-var _37;
-if(this._itemsByIdentity){
-_37=this._itemsByIdentity[rId];
-}else{
-_37=this._arrayOfAllItems[rId];
-}
-this._removeReferenceFromMap(_37,_28,_29);
-}
-}else{
-for(var i=0;i<_33.length;i++){
-var _32=_33[i];
-if(this.isItem(_32)){
-this._addReferenceToMap(_32,_28,_29);
-}
-}
-}
-}
-_28[_29]=_33;
-_30=true;
-}
-if(_2b){
-this.onSet(_28,_29,_2d,_2a);
-}
-return _30;
-},_addReferenceToMap:function(_38,_39,_3a){
-var _3b=this.getIdentity(_39);
-var _3c=_38[this._reverseRefMap];
-if(!_3c){
-_3c=_38[this._reverseRefMap]={};
-}
-var _3d=_3c[_3b];
-if(!_3d){
-_3d=_3c[_3b]={};
-}
-_3d[_3a]=true;
-},_removeReferenceFromMap:function(_3e,_3f,_40){
-var _41=this.getIdentity(_3f);
-var _42=_3e[this._reverseRefMap];
-var _43;
-if(_42){
-for(_43 in _42){
-if(_43==_41){
-delete _42[_43][_40];
-if(this._isEmpty(_42[_43])){
-delete _42[_43];
-}
-}
-}
-if(this._isEmpty(_42)){
-delete _3e[this._reverseRefMap];
-}
-}
-},_dumpReferenceMap:function(){
-var i;
-for(i=0;i<this._arrayOfAllItems.length;i++){
-var _44=this._arrayOfAllItems[i];
-if(_44&&_44[this._reverseRefMap]){
-}
-}
-},_getValueOrValues:function(_45,_46){
-var _47=undefined;
-if(this.hasAttribute(_45,_46)){
-var _48=this.getValues(_45,_46);
-if(_48.length==1){
-_47=_48[0];
-}else{
-_47=_48;
-}
-}
-return _47;
-},_flatten:function(_49){
-if(this.isItem(_49)){
-var _4a=_49;
-var _4b=this.getIdentity(_4a);
-var _4c={_reference:_4b};
-return _4c;
-}else{
-if(typeof _49==="object"){
-for(var _4d in this._datatypeMap){
-var _4e=this._datatypeMap[_4d];
-if(dojo.isObject(_4e)&&!dojo.isFunction(_4e)){
-if(_49 instanceof _4e.type){
-if(!_4e.serialize){
-throw new Error("ItemFileWriteStore:  No serializer defined for type mapping: ["+_4d+"]");
-}
-return {_type:_4d,_value:_4e.serialize(_49)};
-}
-}else{
-if(_49 instanceof _4e){
-return {_type:_4d,_value:_49.toString()};
-}
-}
-}
-}
-return _49;
-}
-},_getNewFileContentString:function(){
-var _4f={};
-var _50=this._getIdentifierAttribute();
-if(_50!==Number){
-_4f.identifier=_50;
-}
-if(this._labelAttr){
-_4f.label=this._labelAttr;
-}
-_4f.items=[];
-for(var i=0;i<this._arrayOfAllItems.length;++i){
-var _51=this._arrayOfAllItems[i];
-if(_51!==null){
-var _52={};
-for(var key in _51){
-if(key!==this._storeRefPropName&&key!==this._itemNumPropName&&key!==this._reverseRefMap&&key!==this._rootItemPropName){
-var _53=key;
-var _54=this.getValues(_51,_53);
-if(_54.length==1){
-_52[_53]=this._flatten(_54[0]);
-}else{
-var _55=[];
-for(var j=0;j<_54.length;++j){
-_55.push(this._flatten(_54[j]));
-_52[_53]=_55;
-}
-}
-}
-}
-_4f.items.push(_52);
-}
-}
-var _56=true;
-return dojo.toJson(_4f,_56);
-},_isEmpty:function(_57){
-var _58=true;
-if(dojo.isObject(_57)){
-var i;
-for(i in _57){
-_58=false;
-break;
-}
-}else{
-if(dojo.isArray(_57)){
-if(_57.length>0){
-_58=false;
-}
-}
-}
-return _58;
-},save:function(_59){
-this._assert(!this._saveInProgress);
-this._saveInProgress=true;
-var _5a=this;
-var _5b=function(){
-_5a._pending={_newItems:{},_modifiedItems:{},_deletedItems:{}};
-_5a._saveInProgress=false;
-if(_59&&_59.onComplete){
-var _5c=_59.scope||dojo.global;
-_59.onComplete.call(_5c);
-}
-};
-var _5d=function(err){
-_5a._saveInProgress=false;
-if(_59&&_59.onError){
-var _5e=_59.scope||dojo.global;
-_59.onError.call(_5e,err);
-}
-};
-if(this._saveEverything){
-var _5f=this._getNewFileContentString();
-this._saveEverything(_5b,_5d,_5f);
-}
-if(this._saveCustom){
-this._saveCustom(_5b,_5d);
-}
-if(!this._saveEverything&&!this._saveCustom){
-_5b();
-}
-},revert:function(){
-this._assert(!this._saveInProgress);
-var _60;
-for(_60 in this._pending._modifiedItems){
-var _61=this._pending._modifiedItems[_60];
-var _62=null;
-if(this._itemsByIdentity){
-_62=this._itemsByIdentity[_60];
-}else{
-_62=this._arrayOfAllItems[_60];
-}
-_61[this._storeRefPropName]=this;
-for(key in _62){
-delete _62[key];
-}
-dojo.mixin(_62,_61);
-}
-var _63;
-for(_60 in this._pending._deletedItems){
-_63=this._pending._deletedItems[_60];
-_63[this._storeRefPropName]=this;
-var _64=_63[this._itemNumPropName];
-if(_63["backup_"+this._reverseRefMap]){
-_63[this._reverseRefMap]=_63["backup_"+this._reverseRefMap];
-delete _63["backup_"+this._reverseRefMap];
-}
-this._arrayOfAllItems[_64]=_63;
-if(this._itemsByIdentity){
-this._itemsByIdentity[_60]=_63;
-}
-if(_63[this._rootItemPropName]){
-this._arrayOfTopLevelItems.push(_63);
-}
-}
-for(_60 in this._pending._deletedItems){
-_63=this._pending._deletedItems[_60];
-if(_63["backupRefs_"+this._reverseRefMap]){
-dojo.forEach(_63["backupRefs_"+this._reverseRefMap],function(_65){
-var _66;
-if(this._itemsByIdentity){
-_66=this._itemsByIdentity[_65.id];
-}else{
-_66=this._arrayOfAllItems[_65.id];
-}
-this._addReferenceToMap(_66,_63,_65.attr);
-},this);
-delete _63["backupRefs_"+this._reverseRefMap];
-}
-}
-for(_60 in this._pending._newItems){
-var _67=this._pending._newItems[_60];
-_67[this._storeRefPropName]=null;
-this._arrayOfAllItems[_67[this._itemNumPropName]]=null;
-if(_67[this._rootItemPropName]){
-this._removeArrayElement(this._arrayOfTopLevelItems,_67);
-}
-if(this._itemsByIdentity){
-delete this._itemsByIdentity[_60];
-}
-}
-this._pending={_newItems:{},_modifiedItems:{},_deletedItems:{}};
-return true;
-},isDirty:function(_68){
-if(_68){
-var _69=this.getIdentity(_68);
-return new Boolean(this._pending._newItems[_69]||this._pending._modifiedItems[_69]||this._pending._deletedItems[_69]).valueOf();
-}else{
-if(!this._isEmpty(this._pending._newItems)||!this._isEmpty(this._pending._modifiedItems)||!this._isEmpty(this._pending._deletedItems)){
-return true;
-}
-return false;
-}
-},onSet:function(_6a,_6b,_6c,_6d){
-},onNew:function(_6e,_6f){
-},onDelete:function(_70){
-},close:function(_71){
-if(this.clearOnClose){
-if(!this.isDirty()){
-this.inherited(arguments);
-}else{
-throw new Error("dojo.data.ItemFileWriteStore: There are unsaved changes present in the store.  Please save or revert the changes before invoking close.");
-}
-}
-}});
-}
+
+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]){
+				console.log("Item: [" + this.getIdentity(item) + "] is referenced by: " + dojo.toJson(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 copyOfItemState = this._pending._modifiedItems[identity];
+			var modifiedItem = null;
+			if(this._itemsByIdentity){
+				modifiedItem = this._itemsByIdentity[identity];
+			}else{
+				modifiedItem = this._arrayOfAllItems[identity];
+			}
+	
+			// Restore the original item into a full-fledged item again, we want to try to 
+			// keep the same object instance as if we don't it, causes bugs like #9022.
+			copyOfItemState[this._storeRefPropName] = this;
+			for(key in modifiedItem){
+				delete modifiedItem[key];
+			}
+			dojo.mixin(modifiedItem, copyOfItemState);
+		}
+		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{
+				 //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.");
+			 }
+		 }
+	}
+});
diff --git a/dojo/data/api/Identity.js b/dojo/data/api/Identity.js
index 2a1baf6..2db1dd8 100644
--- a/dojo/data/api/Identity.js
+++ b/dojo/data/api/Identity.js
@@ -1,26 +1,103 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.data.api.Identity"]){
-dojo._hasResource["dojo.data.api.Identity"]=true;
 dojo.provide("dojo.data.api.Identity");
 dojo.require("dojo.data.api.Read");
-dojo.declare("dojo.data.api.Identity",dojo.data.api.Read,{getFeatures:function(){
-return {"dojo.data.api.Read":true,"dojo.data.api.Identity":true};
-},getIdentity:function(_1){
-throw new Error("Unimplemented API: dojo.data.api.Identity.getIdentity");
-var _2=null;
-return _2;
-},getIdentityAttributes:function(_3){
-throw new Error("Unimplemented API: dojo.data.api.Identity.getIdentityAttributes");
-return null;
-},fetchItemByIdentity:function(_4){
-if(!this.isItemLoaded(_4.item)){
-throw new Error("Unimplemented API: dojo.data.api.Identity.fetchItemByIdentity");
-}
-}});
-}
+
+dojo.declare("dojo.data.api.Identity", dojo.data.api.Read, {
+	//	summary:
+	//		This is an abstract API that data provider implementations conform to.
+	//		This file defines methods signatures and intentionally leaves all the
+	//		methods unimplemented.
+
+	getFeatures: function(){
+		//	summary: 
+		//		See dojo.data.api.Read.getFeatures()
+		return {
+			 'dojo.data.api.Read': true,
+			 'dojo.data.api.Identity': true
+		};
+	},
+
+	getIdentity: function(/* item */ item){
+		//	summary:
+		//		Returns a unique identifier for an item.  The return value will be
+		//		either a string or something that has a toString() method (such as,
+		//		for example, a dojox.uuid.Uuid object).
+		//	item:
+		//		The item from the store from which to obtain its identifier.
+		//	exceptions:
+		//		Conforming implementations may throw an exception or return null if
+		//		item is not an item.
+		//	example:
+		//	|	var itemId = store.getIdentity(kermit);
+		//	|	assert(kermit === store.findByIdentity(store.getIdentity(kermit)));
+		throw new Error('Unimplemented API: dojo.data.api.Identity.getIdentity');
+		var itemIdentityString = null;
+		return itemIdentityString; // string
+	},
+
+	getIdentityAttributes: function(/* item */ item){
+		//	summary:
+		//		Returns an array of attribute names that are used to generate the identity. 
+		//		For most stores, this is a single attribute, but for some complex stores
+		//		such as RDB backed stores that use compound (multi-attribute) identifiers
+		//		it can be more than one.  If the identity is not composed of attributes
+		//		on the item, it will return null.  This function is intended to identify
+		//		the attributes that comprise the identity so that so that during a render
+		//		of all attributes, the UI can hide the the identity information if it 
+		//		chooses.
+		//	item:
+		//		The item from the store from which to obtain the array of public attributes that 
+		//		compose the identifier, if any.
+		//	example:
+		//	|	var itemId = store.getIdentity(kermit);
+		//	|	var identifiers = store.getIdentityAttributes(itemId);
+		//	|	assert(typeof identifiers === "array" || identifiers === null);
+		throw new Error('Unimplemented API: dojo.data.api.Identity.getIdentityAttributes');
+		return null; // string
+	},
+
+
+	fetchItemByIdentity: function(/* object */ keywordArgs){
+		//	summary:
+		//		Given the identity of an item, this method returns the item that has 
+		//		that identity through the onItem callback.  Conforming implementations 
+		//		should return null if there is no item with the given identity.  
+		//		Implementations of fetchItemByIdentity() may sometimes return an item 
+		//		from a local cache and may sometimes fetch an item from a remote server, 
+		//
+		// 	keywordArgs:
+		//		An anonymous object that defines the item to locate and callbacks to invoke when the 
+		//		item has been located and load has completed.  The format of the object is as follows:
+		//		{
+		//			identity: string|object,
+		//			onItem: Function,
+		//			onError: Function,
+		//			scope: object
+		//		}
+		//	The *identity* parameter.
+		//		The identity parameter is the identity of the item you wish to locate and load
+		//		This attribute is required.  It should be a string or an object that toString() 
+		//		can be called on.
+		//		
+		//	The *onItem* parameter.
+		//		Function(item)
+		//		The onItem parameter is the callback to invoke when the item has been loaded.  It takes only one
+		//		parameter, the item located, or null if none found.
+		//
+		//	The *onError* parameter.
+		//		Function(error)
+		//		The onError parameter is the callback to invoke when the item load encountered an error.  It takes only one
+		//		parameter, the error object
+		//
+		//	The *scope* parameter.
+		//		If a scope object is provided, all of the callback functions (onItem, 
+		//		onError, etc) will be invoked in the context of the scope object.
+		//		In the body of the callback function, the value of the "this"
+		//		keyword will be the scope object.   If no scope object is provided,
+		//		the callback functions will be called in the context of dojo.global.
+		//		For example, onItem.call(scope, item, request) vs. 
+		//		onItem.call(dojo.global, item, request)
+		if(!this.isItemLoaded(keywordArgs.item)){
+			throw new Error('Unimplemented API: dojo.data.api.Identity.fetchItemByIdentity');
+		}
+	}
+});
diff --git a/dojo/data/api/Notification.js b/dojo/data/api/Notification.js
index e063d48..6ad77dc 100644
--- a/dojo/data/api/Notification.js
+++ b/dojo/data/api/Notification.js
@@ -1,21 +1,115 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.data.api.Notification"]){
-dojo._hasResource["dojo.data.api.Notification"]=true;
 dojo.provide("dojo.data.api.Notification");
 dojo.require("dojo.data.api.Read");
-dojo.declare("dojo.data.api.Notification",dojo.data.api.Read,{getFeatures:function(){
-return {"dojo.data.api.Read":true,"dojo.data.api.Notification":true};
-},onSet:function(_1,_2,_3,_4){
-throw new Error("Unimplemented API: dojo.data.api.Notification.onSet");
-},onNew:function(_5,_6){
-throw new Error("Unimplemented API: dojo.data.api.Notification.onNew");
-},onDelete:function(_7){
-throw new Error("Unimplemented API: dojo.data.api.Notification.onDelete");
-}});
-}
+
+dojo.declare("dojo.data.api.Notification", dojo.data.api.Read, {
+	//	summary:
+	//		This is an abstract API that data provider implementations conform to.
+	//		This file defines functions signatures and intentionally leaves all the
+	//		functions unimplemented.
+	//
+	//	description:
+	//		This API defines a set of APIs that all datastores that conform to the
+	//		Notifications API must implement.  In general, most stores will implement 
+	//		these APIs as no-op functions for users who wish to monitor them to be able
+	//		to connect to then via dojo.connect().  For non-users of dojo.connect, 
+	//		they should be able to just replace the function on the store to obtain
+	//		 notifications.  Both read-only and read-write stores may implement
+	//		this feature.  In the case of a read-only store, this feature makes sense if 
+	//		the store itself does internal polling to a back-end server and periodically updates
+	//		its cache of items (deletes, adds, and updates).
+	//
+	//	example:
+	//
+	//	|	function onSet(item, attribute, oldValue, newValue) {
+	//	|		//Do something with the information...
+	//	|	};
+	//	|	var store = new some.newStore();
+	//	|	dojo.connect(store, "onSet", onSet);
+
+	getFeatures: function(){
+		//	summary: 
+		//		See dojo.data.api.Read.getFeatures()
+		return {
+			'dojo.data.api.Read': true,
+			'dojo.data.api.Notification': true
+		};
+	},
+
+	onSet: function(/* item */ item, 
+					/* attribute-name-string */ attribute, 
+					/* object | array */ oldValue,
+					/* object | array */ newValue){
+		//	summary:
+		//		This function is called any time an item is modified via setValue, setValues, unsetAttribute, etc.  
+		//	description:
+		//		This function is called any time an item is modified via setValue, setValues, unsetAttribute, etc.  
+		//		Its purpose is to provide a hook point for those who wish to monitor actions on items in the store 
+		//		in a simple manner.  The general expected usage is to dojo.connect() to the store's 
+		//		implementation and be called after the store function is called.
+		//
+		//	item:
+		//		The item being modified.
+		//	attribute:
+		//		The attribute being changed represented as a string name.
+		//	oldValue:
+		//		The old value of the attribute.  In the case of single value calls, such as setValue, unsetAttribute, etc,
+		//		this value will be generally be an atomic value of some sort (string, int, etc, object).  In the case of 
+		//		multi-valued attributes, it will be an array.
+		//	newValue:
+		//		The new value of the attribute.  In the case of single value calls, such as setValue, this value will be 
+		//		generally be an atomic value of some sort (string, int, etc, object).  In the case of multi-valued attributes, 
+		//		it will be an array.  In the case of unsetAttribute, the new value will be 'undefined'.
+		//
+		//	returns:
+		//		Nothing.
+		throw new Error('Unimplemented API: dojo.data.api.Notification.onSet');
+	},
+
+	onNew: function(/* item */ newItem, /*object?*/ parentInfo){
+		//	summary:
+		//		This function is called any time a new item is created in the store.
+		//		It is called immediately after the store newItem processing has completed.
+		//	description:
+		//		This function is called any time a new item is created in the store.
+		//		It is called immediately after the store newItem processing has completed.
+		//
+		//	newItem:
+		//		The item created.
+		//	parentInfo:
+		//		An optional javascript object that is passed when the item created was placed in the store
+		//		hierarchy as a value f another item's attribute, instead of a root level item.  Note that if this
+		//		function is invoked with a value for parentInfo, then onSet is not invoked stating the attribute of
+		//		the parent item was modified.  This is to avoid getting two notification  events occurring when a new item
+		//		with a parent is created.  The structure passed in is as follows:
+		//		{
+		//			item: someItem,							//The parent item
+		//			attribute:	"attribute-name-string",	//The attribute the new item was assigned to.
+		//			oldValue: something	//Whatever was the previous value for the attribute.  
+		//						//If it is a single-value attribute only, then this value will be a single value.
+		//						//If it was a multi-valued attribute, then this will be an array of all the values minues the new one.
+		//			newValue: something	//The new value of the attribute.  In the case of single value calls, such as setValue, this value will be
+		//						//generally be an atomic value of some sort (string, int, etc, object).  In the case of multi-valued attributes,
+		//						//it will be an array.  
+		//		}
+		//
+		//	returns:
+		//		Nothing.
+		throw new Error('Unimplemented API: dojo.data.api.Notification.onNew');
+	},
+
+	onDelete: function(/* item */ deletedItem){
+		//	summary:
+		//		This function is called any time an item is deleted from the store.
+		//		It is called immediately after the store deleteItem processing has completed.
+		//	description:
+		//		This function is called any time an item is deleted from the store.
+		//		It is called immediately after the store deleteItem processing has completed.
+		//
+		//	deletedItem:
+		//		The item deleted.
+		//
+		//	returns:
+		//		Nothing.
+		throw new Error('Unimplemented API: dojo.data.api.Notification.onDelete');
+	}
+});
diff --git a/dojo/data/api/Read.js b/dojo/data/api/Read.js
index 38594d2..1f943a2 100644
--- a/dojo/data/api/Read.js
+++ b/dojo/data/api/Read.js
@@ -1,55 +1,502 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.data.api.Read"]){
-dojo._hasResource["dojo.data.api.Read"]=true;
 dojo.provide("dojo.data.api.Read");
 dojo.require("dojo.data.api.Request");
-dojo.declare("dojo.data.api.Read",null,{getValue:function(_1,_2,_3){
-var _4=null;
-throw new Error("Unimplemented API: dojo.data.api.Read.getValue");
-return _4;
-},getValues:function(_5,_6){
-var _7=[];
-throw new Error("Unimplemented API: dojo.data.api.Read.getValues");
-return _7;
-},getAttributes:function(_8){
-var _9=[];
-throw new Error("Unimplemented API: dojo.data.api.Read.getAttributes");
-return _9;
-},hasAttribute:function(_a,_b){
-throw new Error("Unimplemented API: dojo.data.api.Read.hasAttribute");
-return false;
-},containsValue:function(_c,_d,_e){
-throw new Error("Unimplemented API: dojo.data.api.Read.containsValue");
-return false;
-},isItem:function(_f){
-throw new Error("Unimplemented API: dojo.data.api.Read.isItem");
-return false;
-},isItemLoaded:function(_10){
-throw new Error("Unimplemented API: dojo.data.api.Read.isItemLoaded");
-return false;
-},loadItem:function(_11){
-if(!this.isItemLoaded(_11.item)){
-throw new Error("Unimplemented API: dojo.data.api.Read.loadItem");
-}
-},fetch:function(_12){
-var _13=null;
-throw new Error("Unimplemented API: dojo.data.api.Read.fetch");
-return _13;
-},getFeatures:function(){
-return {"dojo.data.api.Read":true};
-},close:function(_14){
-throw new Error("Unimplemented API: dojo.data.api.Read.close");
-},getLabel:function(_15){
-throw new Error("Unimplemented API: dojo.data.api.Read.getLabel");
-return undefined;
-},getLabelAttributes:function(_16){
-throw new Error("Unimplemented API: dojo.data.api.Read.getLabelAttributes");
-return null;
-}});
-}
+
+dojo.declare("dojo.data.api.Read", null, {
+	//	summary:
+	//		This is an abstract API that data provider implementations conform to.  
+	//		This file defines methods signatures and intentionally leaves all the
+	//		methods unimplemented.  For more information on the dojo.data APIs, 
+	//		please visit: http://www.dojotoolkit.org/node/98
+
+	getValue: function(	/* item */ item, 
+						/* attribute-name-string */ attribute, 
+						/* value? */ defaultValue){
+		//	summary:
+		//		Returns a single attribute value.
+		//		Returns defaultValue if and only if *item* does not have a value for *attribute*.
+		//		Returns null if and only if null was explicitly set as the attribute value.
+		//		Returns undefined if and only if the item does not have a value for the
+		//		given attribute (which is the same as saying the item does not have the attribute). 
+		// description:
+		//		Saying that an "item x does not have a value for an attribute y"
+		//		is identical to saying that an "item x does not have attribute y". 
+		//		It is an oxymoron to say "that attribute is present but has no values" 
+		//		or "the item has that attribute but does not have any attribute values".
+		//		If store.hasAttribute(item, attribute) returns false, then
+		//		store.getValue(item, attribute) will return undefined.
+		//
+		//	item:
+		//		The item to access values on.
+		//	attribute:
+		//		The attribute to access represented as a string.
+		//	defaultValue:
+		//		Optional.  A default value to use for the getValue return in the attribute does not exist or has no value.
+		//
+		//	exceptions:
+		//		Throws an exception if *item* is not an item, or *attribute* is not a string
+		//	example:
+		//	|	var darthVader = store.getValue(lukeSkywalker, "father");
+		var attributeValue = null;
+		throw new Error('Unimplemented API: dojo.data.api.Read.getValue');
+		return attributeValue; // a literal, an item, null, or undefined (never an array)
+	},
+
+	getValues: function(/* item */ item,
+						/* attribute-name-string */ attribute){
+		//	summary:
+		// 		This getValues() method works just like the getValue() method, but getValues()
+		//		always returns an array rather than a single attribute value.  The array
+		//		may be empty, may contain a single attribute value, or may contain
+		//		many attribute values.
+		//		If the item does not have a value for the given attribute, then getValues()
+		//		will return an empty array: [].  (So, if store.hasAttribute(item, attribute)
+		//		has a return of false, then store.getValues(item, attribute) will return [].)
+		//
+		//	item:
+		//		The item to access values on.
+		//	attribute:
+		//		The attribute to access represented as a string.
+		//
+		//	exceptions:
+		//		Throws an exception if *item* is not an item, or *attribute* is not a string
+		//	example:
+		//	|	var friendsOfLuke = store.getValues(lukeSkywalker, "friends");
+		var array = [];
+		throw new Error('Unimplemented API: dojo.data.api.Read.getValues');
+		return array; // an array that may contain literals and items
+	},
+
+	getAttributes: function(/* item */ item){
+		//	summary:
+		//		Returns an array with all the attributes that this item has.  This
+		//		method will always return an array; if the item has no attributes
+		//		at all, getAttributes() will return an empty array: [].
+		//
+		//	item:
+		//		The item to access attributes on.
+		//
+		//	exceptions:
+		//		Throws an exception if *item* is not an item, or *attribute* is not a string
+		//	example:
+		//	|	var array = store.getAttributes(kermit);
+		var array = [];
+		throw new Error('Unimplemented API: dojo.data.api.Read.getAttributes');
+		return array; // array
+	},
+
+	hasAttribute: function(	/* item */ item,
+							/* attribute-name-string */ attribute){
+		//	summary:
+		//		Returns true if the given *item* has a value for the given *attribute*.
+		//
+		//	item:
+		//		The item to access attributes on.
+		//	attribute:
+		//		The attribute to access represented as a string.
+		//
+		//	exceptions:
+		//		Throws an exception if *item* is not an item, or *attribute* is not a string
+		//	example:
+		//	|	var trueOrFalse = store.hasAttribute(kermit, "color");
+		throw new Error('Unimplemented API: dojo.data.api.Read.hasAttribute');
+		return false; // boolean
+	},
+
+	containsValue: function(/* item */ item,
+							/* attribute-name-string */ attribute, 
+							/* anything */ value){
+		//	summary:
+		//		Returns true if the given *value* is one of the values that getValues()
+		//		would return.
+		//
+		//	item:
+		//		The item to access values on.
+		//	attribute:
+		//		The attribute to access represented as a string.
+		//	value:
+		//		The value to match as a value for the attribute.
+		//
+		//	exceptions:
+		//		Throws an exception if *item* is not an item, or *attribute* is not a string
+		//	example:
+		//	|	var trueOrFalse = store.containsValue(kermit, "color", "green");
+		throw new Error('Unimplemented API: dojo.data.api.Read.containsValue');
+		return false; // boolean
+	},
+
+	isItem: function(/* anything */ something){
+		//	summary:
+		//		Returns true if *something* is an item and came from the store instance.  
+		//		Returns false if *something* is a literal, an item from another store instance, 
+		//		or is any object other than an item.
+		//
+		//	something:
+		//		Can be anything.
+		//
+		//	example:
+		//	|	var yes = store.isItem(store.newItem());
+		//	|	var no  = store.isItem("green");
+		throw new Error('Unimplemented API: dojo.data.api.Read.isItem');
+		return false; // boolean
+	},
+
+	isItemLoaded: function(/* anything */ something){
+		//	summary:
+		//		Returns false if isItem(something) is false.  Returns false if
+		//		if isItem(something) is true but the the item is not yet loaded
+		//		in local memory (for example, if the item has not yet been read
+		//		from the server).
+		//
+		//	something:
+		//		Can be anything.
+		//
+		//	example:
+		//	|	var yes = store.isItemLoaded(store.newItem());
+		//	|	var no  = store.isItemLoaded("green");
+		throw new Error('Unimplemented API: dojo.data.api.Read.isItemLoaded');
+		return false; // boolean
+	},
+
+	loadItem: function(/* object */ keywordArgs){
+		//	summary:
+		//		Given an item, this method loads the item so that a subsequent call
+		//		to store.isItemLoaded(item) will return true.  If a call to
+		//		isItemLoaded() returns true before loadItem() is even called,
+		//		then loadItem() need not do any work at all and will not even invoke
+		//		the callback handlers.  So, before invoking this method, check that
+		//		the item has not already been loaded.  
+		// 	keywordArgs:
+		//		An anonymous object that defines the item to load and callbacks to invoke when the 
+		//		load has completed.  The format of the object is as follows:
+		//		{
+		//			item: object,
+		//			onItem: Function,
+		//			onError: Function,
+		//			scope: object
+		//		}
+		//	The *item* parameter.
+		//		The item parameter is an object that represents the item in question that should be
+		//		contained by the store.  This attribute is required.
+		
+		//	The *onItem* parameter.
+		//		Function(item)
+		//		The onItem parameter is the callback to invoke when the item has been loaded.  It takes only one
+		//		parameter, the fully loaded item.
+		//
+		//	The *onError* parameter.
+		//		Function(error)
+		//		The onError parameter is the callback to invoke when the item load encountered an error.  It takes only one
+		//		parameter, the error object
+		//
+		//	The *scope* parameter.
+		//		If a scope object is provided, all of the callback functions (onItem, 
+		//		onError, etc) will be invoked in the context of the scope object.
+		//		In the body of the callback function, the value of the "this"
+		//		keyword will be the scope object.   If no scope object is provided,
+		//		the callback functions will be called in the context of dojo.global().
+		//		For example, onItem.call(scope, item, request) vs. 
+		//		onItem.call(dojo.global(), item, request)
+		if(!this.isItemLoaded(keywordArgs.item)){
+			throw new Error('Unimplemented API: dojo.data.api.Read.loadItem');
+		}
+	},
+
+	fetch: function(/* Object */ keywordArgs){
+		//	summary:
+		//		Given a query and set of defined options, such as a start and count of items to return,
+		//		this method executes the query and makes the results available as data items.
+		//		The format and expectations of stores is that they operate in a generally asynchronous 
+		//		manner, therefore callbacks are always used to return items located by the fetch parameters.
+		//
+		//	description:
+		//		A Request object will always be returned and is returned immediately.
+		//		The basic request is nothing more than the keyword args passed to fetch and 
+		//		an additional function attached, abort().  The returned request object may then be used 
+		//		to cancel a fetch.  All data items returns are passed through the callbacks defined in the 
+		//		fetch parameters and are not present on the 'request' object.
+		//
+		//		This does not mean that custom stores can not add methods and properties to the request object
+		//		returned, only that the API does not require it.  For more info about the Request API, 
+		//		see dojo.data.api.Request
+		//
+		//	keywordArgs:
+		//		The keywordArgs parameter may either be an instance of 
+		//		conforming to dojo.data.api.Request or may be a simple anonymous object
+		//		that may contain any of the following:
+		//		{ 
+		//			query: query-object or query-string,
+		//			queryOptions: object,
+		//			onBegin: Function,
+		//			onItem: Function,
+		//			onComplete: Function,
+		//			onError: Function,
+		//			scope: object,
+		//			start: int
+		//			count: int
+		//			sort: array
+		//		}
+		//		All implementations should accept keywordArgs objects with any of
+		//		the 9 standard properties: query, onBegin, onItem, onComplete, onError 
+		//		scope, sort, start, and count.  Some implementations may accept additional 
+		//		properties in the keywordArgs object as valid parameters, such as 
+		//		{includeOutliers:true}.         
+		//
+		//	The *query* parameter.
+		//		The query may be optional in some data store implementations.
+		//		The dojo.data.api.Read API does not specify the syntax or semantics
+		//		of the query itself -- each different data store implementation
+		//		may have its own notion of what a query should look like.
+		//		However, as of dojo 0.9, 1.0, and 1.1, all the provided datastores in dojo.data
+		//		and dojox.data support an object structure query, where the object is a set of 
+		//		name/value parameters such as { attrFoo: valueBar, attrFoo1: valueBar1}.  Most of the
+		//		dijit widgets, such as ComboBox assume this to be the case when working with a datastore 
+		//		when they dynamically update the query.  Therefore, for maximum compatibility with dijit 
+		//		widgets the recommended query parameter is a key/value object.  That does not mean that the
+		//		the datastore may not take alternative query forms, such as a simple string, a Date, a number, 
+		//		or a mix of such.  Ultimately, The dojo.data.api.Read API is agnostic about what the query 
+		//		format.  
+		//		Further note:  In general for query objects that accept strings as attribute 
+		//		value matches, the store should also support basic filtering capability, such as * 
+		//		(match any character) and ? (match single character).  An example query that is a query object
+		//		would be like: { attrFoo: "value*"}.  Which generally means match all items where they have 
+		//		an attribute named attrFoo, with a value that starts with 'value'.
+		//
+		//	The *queryOptions* parameter
+		//		The queryOptions parameter is an optional parameter used to specify optiosn that may modify
+		//		the query in some fashion, such as doing a case insensitive search, or doing a deep search
+		//		where all items in a hierarchical representation of data are scanned instead of just the root 
+		//		items.  It currently defines two options that all datastores should attempt to honor if possible:
+		//		{
+		//			ignoreCase: boolean, //Whether or not the query should match case sensitively or not.  Default behaviour is false.
+		//			deep: boolean 	//Whether or not a fetch should do a deep search of items and all child 
+		//							//items instead of just root-level items in a datastore.  Default is false.
+		//		}
+		//
+		//	The *onBegin* parameter.
+		//		function(size, request);
+		//		If an onBegin callback function is provided, the callback function
+		//		will be called just once, before the first onItem callback is called.
+		//		The onBegin callback function will be passed two arguments, the
+		//		the total number of items identified and the Request object.  If the total number is
+		//		unknown, then size will be -1.  Note that size is not necessarily the size of the 
+		//		collection of items returned from the query, as the request may have specified to return only a 
+		//		subset of the total set of items through the use of the start and count parameters.
+		//
+		//	The *onItem* parameter.
+		//		function(item, request);
+		//		If an onItem callback function is provided, the callback function
+		//		will be called as each item in the result is received. The callback 
+		//		function will be passed two arguments: the item itself, and the
+		//		Request object.
+		//
+		//	The *onComplete* parameter.
+		//		function(items, request);
+		//
+		//		If an onComplete callback function is provided, the callback function
+		//		will be called just once, after the last onItem callback is called.
+		//		Note that if the onItem callback is not present, then onComplete will be passed
+		//		an array containing all items which matched the query and the request object.  
+		//		If the onItem callback is present, then onComplete is called as: 
+		//		onComplete(null, request).
+		//
+		//	The *onError* parameter.
+		//		function(errorData, request); 
+		//		If an onError callback function is provided, the callback function
+		//		will be called if there is any sort of error while attempting to
+		//		execute the query.
+		//		The onError callback function will be passed two arguments:
+		//		an Error object and the Request object.
+		//
+		//	The *scope* parameter.
+		//		If a scope object is provided, all of the callback functions (onItem, 
+		//		onComplete, onError, etc) will be invoked in the context of the scope
+		//		object.  In the body of the callback function, the value of the "this"
+		//		keyword will be the scope object.   If no scope object is provided,
+		//		the callback functions will be called in the context of dojo.global().  
+		//		For example, onItem.call(scope, item, request) vs. 
+		//		onItem.call(dojo.global(), item, request)
+		//
+		//	The *start* parameter.
+		//		If a start parameter is specified, this is a indication to the datastore to 
+		//		only start returning items once the start number of items have been located and
+		//		skipped.  When this parameter is paired withh 'count', the store should be able
+		//		to page across queries with millions of hits by only returning subsets of the 
+		//		hits for each query
+		//
+		//	The *count* parameter.
+		//		If a count parameter is specified, this is a indication to the datastore to 
+		//		only return up to that many items.  This allows a fetch call that may have 
+		//		millions of item matches to be paired down to something reasonable.  
+		//
+		//	The *sort* parameter.
+		//		If a sort parameter is specified, this is a indication to the datastore to 
+		//		sort the items in some manner before returning the items.  The array is an array of 
+		//		javascript objects that must conform to the following format to be applied to the
+		//		fetching of items:
+		//		{
+		//			attribute: attribute || attribute-name-string,
+		//			descending: true|false;   // Optional.  Default is false.
+		//		}
+		//		Note that when comparing attributes, if an item contains no value for the attribute
+		//		(undefined), then it the default ascending sort logic should push it to the bottom 
+		//		of the list.  In the descending order case, it such items should appear at the top of the list.
+		// 
+		//	returns:
+		//		The fetch() method will return a javascript object conforming to the API
+		//		defined in dojo.data.api.Request.  In general, it will be the keywordArgs
+		//		object returned with the required functions in Request.js attached.
+		//		Its general purpose is to provide a convenient way for a caller to abort an
+		//		ongoing fetch.  
+		// 
+		//		The Request object may also have additional properties when it is returned
+		//		such as request.store property, which is a pointer to the datastore object that 
+		//		fetch() is a method of.
+		//
+		//	exceptions:
+		//		Throws an exception if the query is not valid, or if the query
+		//		is required but was not supplied.
+		//
+		//	example:
+		//		Fetch all books identified by the query and call 'showBooks' when complete
+		//		|	var request = store.fetch({query:"all books", onComplete: showBooks});
+		//	example:
+		//		Fetch all items in the story and call 'showEverything' when complete.
+		//		|	var request = store.fetch(onComplete: showEverything);
+		//	example:
+		//		Fetch only 10 books that match the query 'all books', starting at the fifth book found during the search.
+		//		This demonstrates how paging can be done for specific queries.  
+		//		|	var request = store.fetch({query:"all books", start: 4, count: 10, onComplete: showBooks});
+		//	example:
+		//		Fetch all items that match the query, calling 'callback' each time an item is located.
+		//		|	var request = store.fetch({query:"foo/bar", onItem:callback});
+		//	example:
+		//		Fetch the first 100 books by author King, call showKing when up to 100 items have been located.
+		//		|	var request = store.fetch({query:{author:"King"}, start: 0, count:100, onComplete: showKing});
+		//	example:
+		//		Locate the books written by Author King, sort it on title and publisher, then return the first 100 items from the sorted items.
+		//		|	var request = store.fetch({query:{author:"King"}, sort: [{ attribute: "title", descending: true}, {attribute: "publisher"}], ,start: 0, count:100, onComplete: 'showKing'});
+		//	example:
+		//		Fetch the first 100 books by authors starting with the name King, then call showKing when up to 100 items have been located.
+		//		|	var request = store.fetch({query:{author:"King*"}, start: 0, count:100, onComplete: showKing});
+		//	example:
+		//		Fetch the first 100 books by authors ending with 'ing', but only have one character before it (King, Bing, Ling, Sing, etc.), then call showBooks when up to 100 items have been located.
+		//		|	var request = store.fetch({query:{author:"?ing"}, start: 0, count:100, onComplete: showBooks});
+		//	example:
+		//		Fetch the first 100 books by author King, where the name may appear as King, king, KING, kInG, and so on, then call showKing when up to 100 items have been located.
+		//		|	var request = store.fetch({query:{author:"King"}, queryOptions:(ignoreCase: true}, start: 0, count:100, onComplete: showKing});
+		//	example:
+		//		Paging
+		//		|	var store = new dojo.data.LargeRdbmsStore({url:"jdbc:odbc:foobar"});
+		//		|	var fetchArgs = {
+		//		|		query: {type:"employees", name:"Hillary *"}, // string matching
+		//		|		sort: [{attribute:"department", descending:true}],
+		//		|		start: 0,
+		//		|		count: 20,
+		//		|		scope: displayer,
+		//		|		onBegin: showThrobber,
+		//		|		onItem: displayItem,
+		//		|		onComplete: stopThrobber,
+		//		|		onError: handleFetchError,
+		//		|	};
+		//		|	store.fetch(fetchArgs);
+		//		|	...
+		//		and then when the user presses the "Next Page" button...
+		//		|	fetchArgs.start += 20;
+		//		|	store.fetch(fetchArgs);  // get the next 20 items
+		var request = null; 
+		throw new Error('Unimplemented API: dojo.data.api.Read.fetch');
+		return request; // an object conforming to the dojo.data.api.Request API
+	},
+
+	getFeatures: function(){
+		//	summary:
+		//		The getFeatures() method returns an simple keyword values object 
+		//		that specifies what interface features the datastore implements.  
+		//		A simple CsvStore may be read-only, and the only feature it 
+		//		implements will be the 'dojo.data.api.Read' interface, so the
+		//		getFeatures() method will return an object like this one:
+		//		{'dojo.data.api.Read': true}.
+		//		A more sophisticated datastore might implement a variety of
+		//		interface features, like 'dojo.data.api.Read', 'dojo.data.api.Write', 
+		//		'dojo.data.api.Identity', and 'dojo.data.api.Attribution'.
+		return {
+			'dojo.data.api.Read': true
+		};
+	},
+
+	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+		//	summary:
+		//		The close() method is intended for instructing the store to 'close' out 
+		//		any information associated with a particular request.
+		//
+		//	description:
+		//		The close() method is intended for instructing the store to 'close' out 
+		//		any information associated with a particular request.  In general, this API
+		//		expects to recieve as a parameter a request object returned from a fetch.  
+		//		It will then close out anything associated with that request, such as 
+		//		clearing any internal datastore caches and closing any 'open' connections.
+		//		For some store implementations, this call may be a no-op.
+		//
+		//	request:
+		//		An instance of a request for the store to use to identify what to close out.
+		//		If no request is passed, then the store should clear all internal caches (if any)
+		//		and close out all 'open' connections.  It does not render the store unusable from
+		//		there on, it merely cleans out any current data and resets the store to initial 
+		//		state.
+		//
+		//	example:
+		//	|	var request = store.fetch({onComplete: doSomething});
+		//	|	...
+		//	|	store.close(request);
+		throw new Error('Unimplemented API: dojo.data.api.Read.close');
+	},
+
+	getLabel: function(/* item */ item){
+		//	summary:
+		//		Method to inspect the item and return a user-readable 'label' for the item
+		//		that provides a general/adequate description of what the item is. 
+		//
+		//	description:
+		//		Method to inspect the item and return a user-readable 'label' for the item
+		//		that provides a general/adequate description of what the item is.  In general
+		//		most labels will be a specific attribute value or collection of the attribute
+		//		values that combine to label the item in some manner.  For example for an item
+		//		that represents a person it may return the label as:  "firstname lastlame" where
+		//		the firstname and lastname are attributes on the item.  If the store is unable 
+		//		to determine an adequate human readable label, it should return undefined.  Users that wish
+		//		to customize how a store instance labels items should replace the getLabel() function on 
+		//		their instance of the store, or extend the store and replace the function in 
+		//		the extension class.
+		//
+		//	item:
+		//		The item to return the label for.
+		//
+		//	returns: 
+		//		A user-readable string representing the item or undefined if no user-readable label can 
+		//		be generated.
+		throw new Error('Unimplemented API: dojo.data.api.Read.getLabel');
+		return undefined;
+	},
+
+	getLabelAttributes: function(/* item */ item){
+		//	summary:
+		//		Method to inspect the item and return an array of what attributes of the item were used 
+		//		to generate its label, if any.
+		//
+		//	description:
+		//		Method to inspect the item and return an array of what attributes of the item were used 
+		//		to generate its label, if any.  This function is to assist UI developers in knowing what
+		//		attributes can be ignored out of the attributes an item has when displaying it, in cases
+		//		where the UI is using the label as an overall identifer should they wish to hide 
+		//		redundant information.
+		//
+		//	item:
+		//		The item to return the list of label attributes for.
+		//
+		//	returns: 
+		//		An array of attribute names that were used to generate the label, or null if public attributes 
+		//		were not used to generate the label.
+		throw new Error('Unimplemented API: dojo.data.api.Read.getLabelAttributes');
+		return null;
+	}
+});
diff --git a/dojo/data/api/Request.js b/dojo/data/api/Request.js
index 72e1989..5490e25 100644
--- a/dojo/data/api/Request.js
+++ b/dojo/data/api/Request.js
@@ -1,14 +1,28 @@
-/*
-	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
-*/
+dojo.provide("dojo.data.api.Request");
 
+dojo.declare("dojo.data.api.Request", null, {
+	//	summary:
+	//		This class defines out the semantics of what a 'Request' object looks like
+	//		when returned from a fetch() method.  In general, a request object is
+	//		nothing more than the original keywordArgs from fetch with an abort function 
+	//		attached to it to allow users to abort a particular request if they so choose. 
+	//		No other functions are required on a general Request object return.  That does not
+	//		inhibit other store implementations from adding extentions to it, of course.
+	//
+	//		This is an abstract API that data provider implementations conform to.  
+	//		This file defines methods signatures and intentionally leaves all the
+	//		methods unimplemented.
+	//
+	//		For more details on fetch, see dojo.data.api.Read.fetch().
 
-if(!dojo._hasResource["dojo.data.api.Request"]){
-dojo._hasResource["dojo.data.api.Request"]=true;
-dojo.provide("dojo.data.api.Request");
-dojo.declare("dojo.data.api.Request",null,{abort:function(){
-throw new Error("Unimplemented API: dojo.data.api.Request.abort");
-}});
-}
+	abort: function(){
+		//	summary:
+		//		This function is a hook point for stores to provide as a way for 
+		//		a fetch to be halted mid-processing.
+		//	description:
+		//		This function is a hook point for stores to provide as a way for 
+		//		a fetch to be halted mid-processing.  For more details on the fetch() api,
+		//		please see dojo.data.api.Read.fetch().
+		throw new Error('Unimplemented API: dojo.data.api.Request.abort');
+	}
+});
diff --git a/dojo/data/api/Write.js b/dojo/data/api/Write.js
index d04d7d7..b197404 100644
--- a/dojo/data/api/Write.js
+++ b/dojo/data/api/Write.js
@@ -1,39 +1,222 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.data.api.Write"]){
-dojo._hasResource["dojo.data.api.Write"]=true;
 dojo.provide("dojo.data.api.Write");
 dojo.require("dojo.data.api.Read");
-dojo.declare("dojo.data.api.Write",dojo.data.api.Read,{getFeatures:function(){
-return {"dojo.data.api.Read":true,"dojo.data.api.Write":true};
-},newItem:function(_1,_2){
-var _3;
-throw new Error("Unimplemented API: dojo.data.api.Write.newItem");
-return _3;
-},deleteItem:function(_4){
-throw new Error("Unimplemented API: dojo.data.api.Write.deleteItem");
-return false;
-},setValue:function(_5,_6,_7){
-throw new Error("Unimplemented API: dojo.data.api.Write.setValue");
-return false;
-},setValues:function(_8,_9,_a){
-throw new Error("Unimplemented API: dojo.data.api.Write.setValues");
-return false;
-},unsetAttribute:function(_b,_c){
-throw new Error("Unimplemented API: dojo.data.api.Write.clear");
-return false;
-},save:function(_d){
-throw new Error("Unimplemented API: dojo.data.api.Write.save");
-},revert:function(){
-throw new Error("Unimplemented API: dojo.data.api.Write.revert");
-return false;
-},isDirty:function(_e){
-throw new Error("Unimplemented API: dojo.data.api.Write.isDirty");
-return false;
-}});
-}
+
+dojo.declare("dojo.data.api.Write", dojo.data.api.Read, {
+	//	summary:
+	//		This is an abstract API that data provider implementations conform to.  
+	//		This file defines function signatures and intentionally leaves all the
+	//		functionss unimplemented.
+
+	getFeatures: function(){
+		//	summary: 
+		//		See dojo.data.api.Read.getFeatures()
+		return {
+			'dojo.data.api.Read': true,
+			'dojo.data.api.Write': true
+		};
+	},
+
+	newItem: function(/* Object? */ keywordArgs, /*Object?*/ parentInfo){
+		//	summary:
+		//		Returns a newly created item.  Sets the attributes of the new
+		//		item based on the *keywordArgs* provided.  In general, the attribute
+		//		names in the keywords become the attributes in the new item and as for
+		//		the attribute values in keywordArgs, they become the values of the attributes
+		//		in the new item.  In addition, for stores that support hierarchical item 
+		//		creation, an optional second parameter is accepted that defines what item is the parent
+		//		of the new item and what attribute of that item should the new item be assigned to.
+		//		In general, this will assume that the attribute targetted is multi-valued and a new item
+		//		is appended onto the list of values for that attribute.  
+		//
+		//	keywordArgs:
+		//		A javascript object defining the initial content of the item as a set of JavaScript 'property name: value' pairs.
+		//	parentInfo:
+		//		An optional javascript object defining what item is the parent of this item (in a hierarchical store.  Not all stores do hierarchical items), 
+		//		and what attribute of that parent to assign the new item to.  If this is present, and the attribute specified
+		//		is a multi-valued attribute, it will append this item into the array of values for that attribute.  The structure
+		//		of the object is as follows:
+		//		{
+		//			parent: someItem,
+		//			attribute: "attribute-name-string"
+		//		}
+		//
+		//	exceptions:
+		//		Throws an exception if *keywordArgs* is a string or a number or
+		//		anything other than a simple anonymous object.  
+		//		Throws an exception if the item in parentInfo is not an item from the store
+		//		or if the attribute isn't an attribute name string.
+		//	example:
+		//	|	var kermit = store.newItem({name: "Kermit", color:[blue, green]});
+
+		var newItem;
+		throw new Error('Unimplemented API: dojo.data.api.Write.newItem');
+		return newItem; // item
+	},
+
+	deleteItem: function(/* item */ item){
+		//	summary:
+		//		Deletes an item from the store.
+		//
+		//	item: 
+		//		The item to delete.
+		//
+		//	exceptions:
+		//		Throws an exception if the argument *item* is not an item 
+		//		(if store.isItem(item) returns false).
+		//	example:
+		//	|	var success = store.deleteItem(kermit);
+		throw new Error('Unimplemented API: dojo.data.api.Write.deleteItem');
+		return false; // boolean
+	},
+
+	setValue: function(	/* item */ item, 
+						/* string */ attribute,
+						/* almost anything */ value){
+		//	summary:
+		//		Sets the value of an attribute on an item.
+		//		Replaces any previous value or values.
+		//
+		//	item:
+		//		The item to modify.
+		//	attribute:
+		//		The attribute of the item to change represented as a string name.
+		//	value:
+		//		The value to assign to the item.
+		//
+		//	exceptions:
+		//		Throws an exception if *item* is not an item, or if *attribute*
+		//		is neither an attribute object or a string.
+		//		Throws an exception if *value* is undefined.
+		//	example:
+		//	|	var success = store.set(kermit, "color", "green");
+		throw new Error('Unimplemented API: dojo.data.api.Write.setValue');
+		return false; // boolean
+	},
+
+	setValues: function(/* item */ item,
+						/* string */ attribute, 
+						/* array */ values){
+		//	summary:
+		//		Adds each value in the *values* array as a value of the given
+		//		attribute on the given item.
+		//		Replaces any previous value or values.
+		//		Calling store.setValues(x, y, []) (with *values* as an empty array) has
+		//		the same effect as calling store.unsetAttribute(x, y).
+		//
+		//	item:
+		//		The item to modify.
+		//	attribute:
+		//		The attribute of the item to change represented as a string name.
+		//	values:
+		//		An array of values to assign to the attribute..
+		//
+		//	exceptions:
+		//		Throws an exception if *values* is not an array, if *item* is not an
+		//		item, or if *attribute* is neither an attribute object or a string.
+		//	example:
+		//	|	var success = store.setValues(kermit, "color", ["green", "aqua"]);
+		//	|	success = store.setValues(kermit, "color", []);
+		//	|	if (success) {assert(!store.hasAttribute(kermit, "color"));}
+		throw new Error('Unimplemented API: dojo.data.api.Write.setValues');
+		return false; // boolean
+	},
+
+	unsetAttribute: function(	/* item */ item, 
+								/* string */ attribute){
+		//	summary:
+		//		Deletes all the values of an attribute on an item.
+		//
+		//	item:
+		//		The item to modify.
+		//	attribute:
+		//		The attribute of the item to unset represented as a string.
+		//
+		//	exceptions:
+		//		Throws an exception if *item* is not an item, or if *attribute*
+		//		is neither an attribute object or a string.
+		//	example:
+		//	|	var success = store.unsetAttribute(kermit, "color");
+		//	|	if (success) {assert(!store.hasAttribute(kermit, "color"));}
+		throw new Error('Unimplemented API: dojo.data.api.Write.clear');
+		return false; // boolean
+	},
+
+	save: function(/* object */ keywordArgs){
+		//	summary:
+		//		Saves to the server all the changes that have been made locally.
+		//		The save operation may take some time and is generally performed
+		//		in an asynchronous fashion.  The outcome of the save action is 
+		//		is passed into the set of supported callbacks for the save.
+		//   
+		//	keywordArgs:
+		//		{
+		//			onComplete: function
+		//			onError: function
+		//			scope: object
+		//		}
+		//
+		//	The *onComplete* parameter.
+		//		function();
+		//
+		//		If an onComplete callback function is provided, the callback function
+		//		will be called just once, after the save has completed.  No parameters
+		//		are generally passed to the onComplete.
+		//
+		//	The *onError* parameter.
+		//		function(errorData); 
+		//
+		//		If an onError callback function is provided, the callback function
+		//		will be called if there is any sort of error while attempting to
+		//		execute the save.  The onError function will be based one parameter, the
+		//		error.
+		//
+		//	The *scope* parameter.
+		//		If a scope object is provided, all of the callback function (
+		//		onComplete, onError, etc) will be invoked in the context of the scope
+		//		object.  In the body of the callback function, the value of the "this"
+		//		keyword will be the scope object.   If no scope object is provided,
+		//		the callback functions will be called in the context of dojo.global.  
+		//		For example, onComplete.call(scope) vs. 
+		//		onComplete.call(dojo.global)
+		//
+		//	returns:
+		//		Nothing.  Since the saves are generally asynchronous, there is 
+		//		no need to return anything.  All results are passed via callbacks.
+		//	example:
+		//	|	store.save({onComplete: onSave});
+		//	|	store.save({scope: fooObj, onComplete: onSave, onError: saveFailed});
+		throw new Error('Unimplemented API: dojo.data.api.Write.save');
+	},
+
+	revert: function(){
+		//	summary:
+		//		Discards any unsaved changes.
+		//	description:
+		//		Discards any unsaved changes.
+		//
+		//	example:
+		//	|	var success = store.revert();
+		throw new Error('Unimplemented API: dojo.data.api.Write.revert');
+		return false; // boolean
+	},
+
+	isDirty: function(/* item? */ item){
+		//	summary:
+		//		Given an item, isDirty() returns true if the item has been modified 
+		//		since the last save().  If isDirty() is called with no *item* argument,  
+		//		then this function returns true if any item has been modified since
+		//		the last save().
+		//
+		//	item:
+		//		The item to check.
+		//
+		//	exceptions:
+		//		Throws an exception if isDirty() is passed an argument and the
+		//		argument is not an item.
+		//	example:
+		//	|	var trueOrFalse = store.isDirty(kermit); // true if kermit is dirty
+		//	|	var trueOrFalse = store.isDirty();       // true if any item is dirty
+		throw new Error('Unimplemented API: dojo.data.api.Write.isDirty');
+		return false; // boolean
+	}
+});
diff --git a/dojo/data/util/filter.js b/dojo/data/util/filter.js
index 0f6fa8a..0ecf1ca 100644
--- a/dojo/data/util/filter.js
+++ b/dojo/data/util/filter.js
@@ -1,52 +1,65 @@
-/*
-	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
-*/
+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.
 
-if(!dojo._hasResource["dojo.data.util.filter"]){
-dojo._hasResource["dojo.data.util.filter"]=true;
-dojo.provide("dojo.data.util.filter");
-dojo.data.util.filter.patternToRegExp=function(_1,_2){
-var _3="^";
-var c=null;
-for(var i=0;i<_1.length;i++){
-c=_1.charAt(i);
-switch(c){
-case "\\":
-_3+=c;
-i++;
-_3+=_1.charAt(i);
-break;
-case "*":
-_3+=".*";
-break;
-case "?":
-_3+=".";
-break;
-case "$":
-case "^":
-case "/":
-case "+":
-case ".":
-case "|":
-case "(":
-case ")":
-case "{":
-case "}":
-case "[":
-case "]":
-_3+="\\";
-default:
-_3+=c;
-}
-}
-_3+="$";
-if(_2){
-return new RegExp(_3,"mi");
-}else{
-return new RegExp(_3,"m");
-}
+	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
+	}
+	
 };
-}
diff --git a/dojo/data/util/simpleFetch.js b/dojo/data/util/simpleFetch.js
index 4e96d3e..4b2dbf8 100644
--- a/dojo/data/util/simpleFetch.js
+++ b/dojo/data/util/simpleFetch.js
@@ -1,64 +1,86 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.data.util.simpleFetch"]){
-dojo._hasResource["dojo.data.util.simpleFetch"]=true;
 dojo.provide("dojo.data.util.simpleFetch");
 dojo.require("dojo.data.util.sorter");
-dojo.data.util.simpleFetch.fetch=function(_1){
-_1=_1||{};
-if(!_1.store){
-_1.store=this;
-}
-var _2=this;
-var _3=function(_4,_5){
-if(_5.onError){
-var _6=_5.scope||dojo.global;
-_5.onError.call(_6,_4,_5);
-}
-};
-var _7=function(_8,_9){
-var _a=_9.abort||null;
-var _b=false;
-var _c=_9.start?_9.start:0;
-var _d=(_9.count&&(_9.count!==Infinity))?(_c+_9.count):_8.length;
-_9.abort=function(){
-_b=true;
-if(_a){
-_a.call(_9);
-}
-};
-var _e=_9.scope||dojo.global;
-if(!_9.store){
-_9.store=_2;
-}
-if(_9.onBegin){
-_9.onBegin.call(_e,_8.length,_9);
-}
-if(_9.sort){
-_8.sort(dojo.data.util.sorter.createSortFunction(_9.sort,_2));
-}
-if(_9.onItem){
-for(var i=_c;(i<_8.length)&&(i<_d);++i){
-var _f=_8[i];
-if(!_b){
-_9.onItem.call(_e,_f,_9);
-}
-}
-}
-if(_9.onComplete&&!_b){
-var _10=null;
-if(!_9.onItem){
-_10=_8.slice(_c,_d);
-}
-_9.onComplete.call(_e,_10,_9);
-}
-};
-this._fetchItems(_1,_7,_3);
-return _1;
+
+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
 };
-}
diff --git a/dojo/data/util/sorter.js b/dojo/data/util/sorter.js
index 5c8dcb4..a96d64b 100644
--- a/dojo/data/util/sorter.js
+++ b/dojo/data/util/sorter.js
@@ -1,66 +1,91 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.data.util.sorter"]){
-dojo._hasResource["dojo.data.util.sorter"]=true;
 dojo.provide("dojo.data.util.sorter");
-dojo.data.util.sorter.basicComparator=function(a,b){
-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;
-};
-dojo.data.util.sorter.createSortFunction=function(_1,_2){
-var _3=[];
-function _4(_5,_6,_7,s){
-return function(_8,_9){
-var a=s.getValue(_8,_5);
-var b=s.getValue(_9,_5);
-return _6*_7(a,b);
-};
-};
-var _a;
-var _b=_2.comparatorMap;
-var bc=dojo.data.util.sorter.basicComparator;
-for(var i=0;i<_1.length;i++){
-_a=_1[i];
-var _c=_a.attribute;
-if(_c){
-var _d=(_a.descending)?-1:1;
-var _e=bc;
-if(_b){
-if(typeof _c!=="string"&&("toString" in _c)){
-_c=_c.toString();
-}
-_e=_b[_c]||bc;
-}
-_3.push(_4(_c,_d,_e,_2));
-}
-}
-return function(_f,_10){
-var i=0;
-while(i<_3.length){
-var ret=_3[i++](_f,_10);
-if(ret!==0){
-return ret;
-}
-}
-return 0;
+
+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, comp, s){
+		//Passing in comp and s (comparator and store), makes this
+		//function much faster.
+		return function(itemA, itemB){
+			var a = s.getValue(itemA, attr);
+			var b = s.getValue(itemB, attr);
+			return dir * comp(a,b); //int
+		};
+	}
+	var sortAttribute;
+	var map = store.comparatorMap;
+	var bc = dojo.data.util.sorter.basicComparator;
+	for(var i = 0; i < sortSpec.length; i++){
+		sortAttribute = sortSpec[i];
+		var attr = sortAttribute.attribute;
+		if(attr){
+			var dir = (sortAttribute.descending) ? -1 : 1;
+			var comp = bc;
+			if(map){
+				if(typeof attr !== "string" && ("toString" in attr)){
+					 attr = attr.toString();
+				}
+				comp = map[attr] || bc;
+			}
+			sortFunctions.push(createSortFunction(attr, 
+				dir, comp, store));
+		}
+	}
+	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
 };
-}
diff --git a/dojo/date.js b/dojo/date.js
index 67a8afd..8b54d32 100644
--- a/dojo/date.js
+++ b/dojo/date.js
@@ -1,213 +1,338 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.date"]){
-dojo._hasResource["dojo.date"]=true;
 dojo.provide("dojo.date");
-dojo.date.getDaysInMonth=function(_1){
-var _2=_1.getMonth();
-var _3=[31,28,31,30,31,30,31,31,30,31,30,31];
-if(_2==1&&dojo.date.isLeapYear(_1)){
-return 29;
-}
-return _3[_2];
-};
-dojo.date.isLeapYear=function(_4){
-var _5=_4.getFullYear();
-return !(_5%400)||(!(_5%4)&&!!(_5%100));
-};
-dojo.date.getTimezoneName=function(_6){
-var _7=_6.toString();
-var tz="";
-var _8;
-var _9=_7.indexOf("(");
-if(_9>-1){
-tz=_7.substring(++_9,_7.indexOf(")"));
-}else{
-var _a=/([A-Z\/]+) \d{4}$/;
-if((_8=_7.match(_a))){
-tz=_8[1];
-}else{
-_7=_6.toLocaleString();
-_a=/ ([A-Z\/]+)$/;
-if((_8=_7.match(_a))){
-tz=_8[1];
-}
-}
-}
-return (tz=="AM"||tz=="PM")?"":tz;
-};
-dojo.date.compare=function(_b,_c,_d){
-_b=new Date(+_b);
-_c=new Date(+(_c||new Date()));
-if(_d=="date"){
-_b.setHours(0,0,0,0);
-_c.setHours(0,0,0,0);
-}else{
-if(_d=="time"){
-_b.setFullYear(0,0,0);
-_c.setFullYear(0,0,0);
+
+/*=====
+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
 }
-if(_b>_c){
-return 1;
+
+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
 }
-if(_b<_c){
-return -1;
+
+// 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
 }
-return 0;
+
+// 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(+date1);
+	date2 = new Date(+(date2 || new Date()));
+
+	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(_e,_f,_10){
-var sum=new Date(+_e);
-var _11=false;
-var _12="Date";
-switch(_f){
-case "day":
-break;
-case "weekday":
-var _13,_14;
-var mod=_10%5;
-if(!mod){
-_13=(_10>0)?5:-5;
-_14=(_10>0)?((_10-5)/5):((_10+5)/5);
-}else{
-_13=mod;
-_14=parseInt(_10/5);
-}
-var _15=_e.getDay();
-var adj=0;
-if(_15==6&&_10>0){
-adj=1;
-}else{
-if(_15==0&&_10<0){
-adj=-1;
-}
-}
-var _16=_15+_13;
-if(_16==0||_16==6){
-adj=(_10>0)?2:-2;
-}
-_10=(7*_14)+_13+adj;
-break;
-case "year":
-_12="FullYear";
-_11=true;
-break;
-case "week":
-_10*=7;
-break;
-case "quarter":
-_10*=3;
-case "month":
-_11=true;
-_12="Month";
-break;
-default:
-_12="UTC"+_f.charAt(0).toUpperCase()+_f.substring(1)+"s";
-}
-if(_12){
-sum["set"+_12](sum["get"+_12]()+_10);
-}
-if(_11&&(sum.getDate()<_e.getDate())){
-sum.setDate(0);
-}
-return sum;
+
+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(+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":
+		default:
+			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(_17,_18,_19){
-_18=_18||new Date();
-_19=_19||"day";
-var _1a=_18.getFullYear()-_17.getFullYear();
-var _1b=1;
-switch(_19){
-case "quarter":
-var m1=_17.getMonth();
-var m2=_18.getMonth();
-var q1=Math.floor(m1/3)+1;
-var q2=Math.floor(m2/3)+1;
-q2+=(_1a*4);
-_1b=q2-q1;
-break;
-case "weekday":
-var _1c=Math.round(dojo.date.difference(_17,_18,"day"));
-var _1d=parseInt(dojo.date.difference(_17,_18,"week"));
-var mod=_1c%7;
-if(mod==0){
-_1c=_1d*5;
-}else{
-var adj=0;
-var _1e=_17.getDay();
-var _1f=_18.getDay();
-_1d=parseInt(_1c/7);
-mod=_1c%7;
-var _20=new Date(_17);
-_20.setDate(_20.getDate()+(_1d*7));
-var _21=_20.getDay();
-if(_1c>0){
-switch(true){
-case _1e==6:
-adj=-1;
-break;
-case _1e==0:
-adj=0;
-break;
-case _1f==6:
-adj=-1;
-break;
-case _1f==0:
-adj=-2;
-break;
-case (_21+mod)>5:
-adj=-2;
-}
-}else{
-if(_1c<0){
-switch(true){
-case _1e==6:
-adj=0;
-break;
-case _1e==0:
-adj=1;
-break;
-case _1f==6:
-adj=2;
-break;
-case _1f==0:
-adj=1;
-break;
-case (_21+mod)<0:
-adj=2;
-}
-}
-}
-_1c+=adj;
-_1c-=(_1d*2);
-}
-_1b=_1c;
-break;
-case "year":
-_1b=_1a;
-break;
-case "month":
-_1b=(_18.getMonth()-_17.getMonth())+(_1a*12);
-break;
-case "week":
-_1b=parseInt(dojo.date.difference(_17,_18,"day")/7);
-break;
-case "day":
-_1b/=24;
-case "hour":
-_1b/=60;
-case "minute":
-_1b/=60;
-case "second":
-_1b/=1000;
-case "millisecond":
-_1b*=_18.getTime()-_17.getTime();
-}
-return Math.round(_1b);
+
+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)
 };
-}
diff --git a/dojo/date/locale.js b/dojo/date/locale.js
index 13121b6..8b296fc 100644
--- a/dojo/date/locale.js
+++ b/dojo/date/locale.js
@@ -1,466 +1,663 @@
-/*
-	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
-*/
+dojo.provide("dojo.date.locale");
 
+// Localization methods for Date.   Honor local customs using locale-dependent dojo.cldr data.
 
-if(!dojo._hasResource["dojo.date.locale"]){
-dojo._hasResource["dojo.date.locale"]=true;
-dojo.provide("dojo.date.locale");
 dojo.require("dojo.date");
 dojo.require("dojo.cldr.supplemental");
 dojo.require("dojo.regexp");
 dojo.require("dojo.string");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojo.cldr","gregorian",null,"ROOT,ar,ca,cs,da,de,el,en,en-au,en-ca,en-gb,es,es-es,fi,fr,he,hu,it,it-it,ja,ko,ko-kr,nb,nl,pl,pt,pt-br,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-cn,zh-tw");
+
+// Load the bundles containing localization information for
+// names and formats
+dojo.requireLocalization("dojo.cldr", "gregorian");
+
+//NOTE: Everything in this module assumes Gregorian calendars.
+// Other calendars will be implemented in separate modules.
+
 (function(){
-function _1(_2,_3,_4,_5){
-return _5.replace(/([a-z])\1*/ig,function(_6){
-var s,_7,c=_6.charAt(0),l=_6.length,_8=["abbr","wide","narrow"];
-switch(c){
-case "G":
-s=_3[(l<4)?"eraAbbr":"eraNames"][_2.getFullYear()<0?0:1];
-break;
-case "y":
-s=_2.getFullYear();
-switch(l){
-case 1:
-break;
-case 2:
-if(!_4.fullYear){
-s=String(s);
-s=s.substr(s.length-2);
-break;
-}
-default:
-_7=true;
-}
-break;
-case "Q":
-case "q":
-s=Math.ceil((_2.getMonth()+1)/3);
-_7=true;
-break;
-case "M":
-var m=_2.getMonth();
-if(l<3){
-s=m+1;
-_7=true;
-}else{
-var _9=["months","format",_8[l-3]].join("-");
-s=_3[_9][m];
-}
-break;
-case "w":
-var _a=0;
-s=dojo.date.locale._getWeekOfYear(_2,_a);
-_7=true;
-break;
-case "d":
-s=_2.getDate();
-_7=true;
-break;
-case "D":
-s=dojo.date.locale._getDayOfYear(_2);
-_7=true;
-break;
-case "E":
-var d=_2.getDay();
-if(l<3){
-s=d+1;
-_7=true;
-}else{
-var _b=["days","format",_8[l-3]].join("-");
-s=_3[_b][d];
-}
-break;
-case "a":
-var _c=(_2.getHours()<12)?"am":"pm";
-s=_3[_c];
-break;
-case "h":
-case "H":
-case "K":
-case "k":
-var h=_2.getHours();
-switch(c){
-case "h":
-s=(h%12)||12;
-break;
-case "H":
-s=h;
-break;
-case "K":
-s=(h%12);
-break;
-case "k":
-s=h||24;
-break;
-}
-_7=true;
-break;
-case "m":
-s=_2.getMinutes();
-_7=true;
-break;
-case "s":
-s=_2.getSeconds();
-_7=true;
-break;
-case "S":
-s=Math.round(_2.getMilliseconds()*Math.pow(10,l-3));
-_7=true;
-break;
-case "v":
-case "z":
-s=dojo.date.locale._getZone(_2,true,_4);
-if(s){
-break;
-}
-l=4;
-case "Z":
-var _d=dojo.date.locale._getZone(_2,false,_4);
-var tz=[(_d<=0?"+":"-"),dojo.string.pad(Math.floor(Math.abs(_d)/60),2),dojo.string.pad(Math.abs(_d)%60,2)];
-if(l==4){
-tz.splice(0,0,"GMT");
-tz.splice(3,0,":");
-}
-s=tz.join("");
-break;
-default:
-throw new Error("dojo.date.locale.format: invalid pattern char: "+_5);
-}
-if(_7){
-s=dojo.string.pad(s,l);
-}
-return s;
-});
-};
-dojo.date.locale._getZone=function(_e,_f,_10){
-if(_f){
-return dojo.date.getTimezoneName(_e);
-}else{
-return _e.getTimezoneOffset();
-}
-};
-dojo.date.locale.format=function(_11,_12){
-_12=_12||{};
-var _13=dojo.i18n.normalizeLocale(_12.locale),_14=_12.formatLength||"short",_15=dojo.date.locale._getGregorianBundle(_13),str=[],_16=dojo.hitch(this,_1,_11,_15,_12);
-if(_12.selector=="year"){
-return _17(_15["dateFormatItem-yyyy"]||"yyyy",_16);
-}
-var _18;
-if(_12.selector!="date"){
-_18=_12.timePattern||_15["timeFormat-"+_14];
-if(_18){
-str.push(_17(_18,_16));
-}
-}
-if(_12.selector!="time"){
-_18=_12.datePattern||_15["dateFormat-"+_14];
-if(_18){
-str.push(_17(_18,_16));
-}
-}
-return str.length==1?str[0]:_15["dateTimeFormat-"+_14].replace(/\{(\d+)\}/g,function(_19,key){
-return str[key];
-});
-};
-dojo.date.locale.regexp=function(_1a){
-return dojo.date.locale._parseInfo(_1a).regexp;
+	// Format a pattern without literals
+	function formatPattern(dateObject, bundle, options, pattern){
+		return pattern.replace(/([a-z])\1*/ig, function(match){
+			var s, pad,
+				c = match.charAt(0),
+				l = match.length,
+				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(!options.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['dayPeriods-format-wide-' + 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.locale._getZone(dateObject, true, options);
+					if(s){break;}
+					l=4;
+					// fallthrough... use GMT if tz not available
+				case 'Z':
+					var offset = dojo.date.locale._getZone(dateObject, false, options);
+					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':
+//					console.log(match+" modifier unimplemented");
+				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._getZone = function(/*Date*/dateObject, /*boolean*/getName, /*dojo.date.locale.__FormatOptions?*/options){
+	// summary:
+	//		Returns the zone (or offset) for the given date and options.  This
+	//		is broken out into a separate function so that it can be overridden
+	//		by timezone-aware code.
+	//
+	// dateObject:
+	//		the date and/or time being formatted.
+	//
+	// getName:
+	//		Whether to return the timezone string (if true), or the offset (if false)
+	//
+	// options:
+	//		The options being used for formatting
+	if(getName){
+		return dojo.date.getTimezoneName(dateObject);
+	}else{
+		return dateObject.getTimezoneOffset();
+	}
 };
-dojo.date.locale._parseInfo=function(_1b){
-_1b=_1b||{};
-var _1c=dojo.i18n.normalizeLocale(_1b.locale),_1d=dojo.date.locale._getGregorianBundle(_1c),_1e=_1b.formatLength||"short",_1f=_1b.datePattern||_1d["dateFormat-"+_1e],_20=_1b.timePattern||_1d["timeFormat-"+_1e],_21;
-if(_1b.selector=="date"){
-_21=_1f;
-}else{
-if(_1b.selector=="time"){
-_21=_20;
-}else{
-_21=_1d["dateTimeFormat-"+_1e].replace(/\{(\d+)\}/g,function(_22,key){
-return [_20,_1f][key];
-});
-}
-}
-var _23=[],re=_17(_21,dojo.hitch(this,_24,_23,_1d,_1b));
-return {regexp:re,tokens:_23,bundle:_1d};
+
+
+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),
+		formatLength = options.formatLength || 'short',
+		bundle = dojo.date.locale._getGregorianBundle(locale),
+		str = [],
+		sauce = dojo.hitch(this, formatPattern, dateObject, bundle, options);
+	if(options.selector == "year"){
+		return _processPattern(bundle["dateFormatItem-yyyy"] || "yyyy", sauce);
+	}
+	var pattern;
+	if(options.selector != "date"){
+		pattern = options.timePattern || bundle["timeFormat-"+formatLength];
+		if(pattern){str.push(_processPattern(pattern, sauce));}
+	}
+	if(options.selector != "time"){
+		pattern = options.datePattern || bundle["dateFormat-"+formatLength];
+		if(pattern){str.push(_processPattern(pattern, sauce));}
+	}
+
+	return str.length == 1 ? str[0] : bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g,
+		function(match, key){ return str[key]; }); // String
 };
-dojo.date.locale.parse=function(_25,_26){
-var _27=dojo.date.locale._parseInfo(_26),_28=_27.tokens,_29=_27.bundle,re=new RegExp("^"+_27.regexp+"$",_27.strict?"":"i"),_2a=re.exec(_25);
-if(!_2a){
-return null;
-}
-var _2b=["abbr","wide","narrow"],_2c=[1970,0,1,0,0,0,0],_2d="",_2e=dojo.every(_2a,function(v,i){
-if(!i){
-return true;
-}
-var _2f=_28[i-1];
-var l=_2f.length;
-switch(_2f.charAt(0)){
-case "y":
-if(l!=2&&_26.strict){
-_2c[0]=v;
-}else{
-if(v<100){
-v=Number(v);
-var _30=""+new Date().getFullYear(),_31=_30.substring(0,2)*100,_32=Math.min(Number(_30.substring(2,4))+20,99),num=(v<_32)?_31+v:_31-100+v;
-_2c[0]=num;
-}else{
-if(_26.strict){
-return false;
-}
-_2c[0]=v;
-}
-}
-break;
-case "M":
-if(l>2){
-var _33=_29["months-format-"+_2b[l-3]].concat();
-if(!_26.strict){
-v=v.replace(".","").toLowerCase();
-_33=dojo.map(_33,function(s){
-return s.replace(".","").toLowerCase();
-});
-}
-v=dojo.indexOf(_33,v);
-if(v==-1){
-return false;
-}
-}else{
-v--;
-}
-_2c[1]=v;
-break;
-case "E":
-case "e":
-var _34=_29["days-format-"+_2b[l-3]].concat();
-if(!_26.strict){
-v=v.toLowerCase();
-_34=dojo.map(_34,function(d){
-return d.toLowerCase();
-});
-}
-v=dojo.indexOf(_34,v);
-if(v==-1){
-return false;
-}
-break;
-case "D":
-_2c[1]=0;
-case "d":
-_2c[2]=v;
-break;
-case "a":
-var am=_26.am||_29.am;
-var pm=_26.pm||_29.pm;
-if(!_26.strict){
-var _35=/\./g;
-v=v.replace(_35,"").toLowerCase();
-am=am.replace(_35,"").toLowerCase();
-pm=pm.replace(_35,"").toLowerCase();
-}
-if(_26.strict&&v!=am&&v!=pm){
-return false;
-}
-_2d=(v==pm)?"p":(v==am)?"a":"";
-break;
-case "K":
-if(v==24){
-v=0;
-}
-case "h":
-case "H":
-case "k":
-if(v>23){
-return false;
-}
-_2c[3]=v;
-break;
-case "m":
-_2c[4]=v;
-break;
-case "s":
-_2c[5]=v;
-break;
-case "S":
-_2c[6]=v;
-}
-return true;
-});
-var _36=+_2c[3];
-if(_2d==="p"&&_36<12){
-_2c[3]=_36+12;
-}else{
-if(_2d==="a"&&_36==12){
-_2c[3]=0;
-}
-}
-var _37=new Date(_2c[0],_2c[1],_2c[2],_2c[3],_2c[4],_2c[5],_2c[6]);
-if(_26.strict){
-_37.setFullYear(_2c[0]);
-}
-var _38=_28.join(""),_39=_38.indexOf("d")!=-1,_3a=_38.indexOf("M")!=-1;
-if(!_2e||(_3a&&_37.getMonth()>_2c[1])||(_39&&_37.getDate()>_2c[2])){
-return null;
-}
-if((_3a&&_37.getMonth()<_2c[1])||(_39&&_37.getDate()<_2c[2])){
-_37=dojo.date.add(_37,"hour",1);
-}
-return _37;
+
+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
 };
-function _17(_3b,_3c,_3d,_3e){
-var _3f=function(x){
-return x;
+
+dojo.date.locale._parseInfo = function(/*dojo.date.locale.__FormatOptions?*/options){
+	options = options || {};
+	var locale = dojo.i18n.normalizeLocale(options.locale),
+		bundle = dojo.date.locale._getGregorianBundle(locale),
+		formatLength = options.formatLength || 'short',
+		datePattern = options.datePattern || bundle["dateFormat-" + formatLength],
+		timePattern = options.timePattern || bundle["timeFormat-" + formatLength],
+		pattern;
+	if(options.selector == 'date'){
+		pattern = datePattern;
+	}else if(options.selector == 'time'){
+		pattern = timePattern;
+	}else{
+		pattern = bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g,
+			function(match, key){ return [timePattern, datePattern][key]; });
+	}
+
+	var tokens = [],
+		re = _processPattern(pattern, dojo.hitch(this, _buildDateTimeRE, tokens, bundle, options));
+	return {regexp: re, tokens: tokens, bundle: bundle};
 };
-_3c=_3c||_3f;
-_3d=_3d||_3f;
-_3e=_3e||_3f;
-var _40=_3b.match(/(''|[^'])+/g),_41=_3b.charAt(0)=="'";
-dojo.forEach(_40,function(_42,i){
-if(!_42){
-_40[i]="";
-}else{
-_40[i]=(_41?_3d:_3c)(_42);
-_41=!_41;
-}
-});
-return _3e(_40.join(""));
+
+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),
+		tokens = info.tokens, bundle = info.bundle,
+		re = new RegExp("^" + info.regexp + "$", info.strict ? "" : "i"),
+		match = re.exec(value);
+
+	if(!match){ return null; } // null
+
+	var widthList = ['abbr', 'wide', 'narrow'],
+		result = [1970,0,1,0,0,0,0], // will get converted to a Date at the end
+		amPm = "",
+		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(),
+							century = year.substring(0, 2) * 100,
+							cutoff = Math.min(Number(year.substring(2, 4)) + 20, 99),
+							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){
+//						console.log("dojo.date.locale.parse: Could not parse month name: '" + v + "'.");
+						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){
+//					console.log("dojo.date.locale.parse: Could not parse weekday name: '" + v + "'.");
+					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['dayPeriods-format-wide-am'],
+					pm = options.pm || bundle['dayPeriods-format-wide-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){
+//					console.log("dojo.date.locale.parse: Could not parse am/pm part.");
+					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){
+//					console.log("dojo.date.locale.parse: Illegal hours value");
+					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?
+//				console.log("dojo.date.locale.parse: unsupported pattern char=" + token.charAt(0));
+		}
+		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 _24(_43,_44,_45,_46){
-_46=dojo.regexp.escapeString(_46);
-if(!_45.strict){
-_46=_46.replace(" a"," ?a");
-}
-return _46.replace(/([a-z])\1*/ig,function(_47){
-var s,c=_47.charAt(0),l=_47.length,p2="",p3="";
-if(_45.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":
-s=p2+"[1-9]|1[0-2]";
-break;
-case "k":
-s=p2+"\\d|1[01]";
-break;
-case "H":
-s=p2+"\\d|1\\d|2[0-3]";
-break;
-case "K":
-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=_45.am||_44.am||"AM";
-var pm=_45.pm||_44.pm||"PM";
-if(_45.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:
-s=".*";
+
+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),
+		literal = pattern.charAt(0) == "'";
+
+	dojo.forEach(chunks, function(chunk, i){
+		if(!chunk){
+			chunks[i]='';
+		}else{
+			chunks[i]=(literal ? applyLiteral : applyPattern)(chunk.replace(/''/g, "'"));
+			literal = !literal;
+		}
+	});
+	return applyAll(chunks.join(''));
 }
-if(_43){
-_43.push(_47);
+
+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,
+			c = match.charAt(0),
+			l = match.length,
+			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 = '3[01]|[12]\\d|'+p2+'[1-9]';
+				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['dayPeriods-format-wide-am'],
+					pm = options.pm || bundle['dayPeriods-format-wide-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 = ".*";
+//				console.log("parse of date format, pattern=" + pattern);
+		}
+
+		if(tokens){ tokens.push(match); }
+
+		return "(" + s + ")"; // add capture
+	}).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace.  Need explicit handling of \xa0 for IE.
 }
-return "("+s+")";
-}).replace(/[\xa0 ]/g,"[\\s\\xa0]");
-};
 })();
+
 (function(){
-var _48=[];
-dojo.date.locale.addCustomFormats=function(_49,_4a){
-_48.push({pkg:_49,name:_4a});
+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(_4b){
-var _4c={};
-dojo.forEach(_48,function(_4d){
-var _4e=dojo.i18n.getLocalization(_4d.pkg,_4d.name,_4b);
-_4c=dojo.mixin(_4c,_4e);
-},this);
-return _4c;
+
+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(_4f,_50,_51,_52){
-var _53,_54=dojo.date.locale._getGregorianBundle(_52),_55=[_4f,_51,_50];
-if(_51=="standAlone"){
-var key=_55.join("-");
-_53=_54[key];
-if(_53[0]==1){
-_53=undefined;
-}
-}
-_55[1]="format";
-return (_53||_54[_55.join("-")]).concat();
+
+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,
+		lookup = dojo.date.locale._getGregorianBundle(locale),
+		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 absence 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(_56,_57){
-var _58=dojo.cldr.supplemental.getWeekend(_57),day=(_56||new Date()).getDay();
-if(_58.end<_58.start){
-_58.end+=7;
-if(day<_58.start){
-day+=7;
-}
-}
-return day>=_58.start&&day<=_58.end;
+
+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),
+		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
 };
-dojo.date.locale._getDayOfYear=function(_59){
-return dojo.date.difference(new Date(_59.getFullYear(),0,1,_59.getHours()),_59)+1;
+
+// 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(_5a,_5b){
-if(arguments.length==1){
-_5b=0;
-}
-var _5c=new Date(_5a.getFullYear(),0,1).getDay(),adj=(_5c-_5b+7)%7,_5d=Math.floor((dojo.date.locale._getDayOfYear(_5a)+adj-1)/7);
-if(_5c==_5b){
-_5d++;
-}
-return _5d;
+
+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(),
+		adj = (firstDayOfYear - firstDayOfWeek + 7) % 7,
+		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
 };
-}
diff --git a/dojo/date/stamp.js b/dojo/date/stamp.js
index 0bb4127..7b6b55a 100644
--- a/dojo/date/stamp.js
+++ b/dojo/date/stamp.js
@@ -1,84 +1,137 @@
-/*
-	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
-*/
+dojo.provide("dojo.date.stamp");
 
+// Methods to convert dates to or from a wire (string) format using well-known conventions
 
-if(!dojo._hasResource["dojo.date.stamp"]){
-dojo._hasResource["dojo.date.stamp"]=true;
-dojo.provide("dojo.date.stamp");
-dojo.date.stamp.fromISOString=function(_1,_2){
-if(!dojo.date.stamp._isoRegExp){
-dojo.date.stamp._isoRegExp=/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/;
-}
-var _3=dojo.date.stamp._isoRegExp.exec(_1),_4=null;
-if(_3){
-_3.shift();
-if(_3[1]){
-_3[1]--;
-}
-if(_3[6]){
-_3[6]*=1000;
-}
-if(_2){
-_2=new Date(_2);
-dojo.map(["FullYear","Month","Date","Hours","Minutes","Seconds","Milliseconds"],function(_5){
-return _2["get"+_5]();
-}).forEach(function(_6,_7){
-if(_3[_7]===undefined){
-_3[_7]=_6;
-}
-});
-}
-_4=new Date(_3[0]||1970,_3[1]||0,_3[2]||1,_3[3]||0,_3[4]||0,_3[5]||0,_3[6]||0);
-if(_3[0]<100){
-_4.setFullYear(_3[0]||1970);
-}
-var _8=0,_9=_3[7]&&_3[7].charAt(0);
-if(_9!="Z"){
-_8=((_3[8]||0)*60)+(Number(_3[9])||0);
-if(_9!="-"){
-_8*=-1;
-}
-}
-if(_9){
-_8-=_4.getTimezoneOffset();
-}
-if(_8){
-_4.setTime(_4.getTime()+_8*60000);
-}
-}
-return _4;
-};
-dojo.date.stamp.toISOString=function(_a,_b){
-var _c=function(n){
-return (n<10)?"0"+n:n;
-};
-_b=_b||{};
-var _d=[],_e=_b.zulu?"getUTC":"get",_f="";
-if(_b.selector!="time"){
-var _10=_a[_e+"FullYear"]();
-_f=["0000".substr((_10+"").length)+_10,_c(_a[_e+"Month"]()+1),_c(_a[_e+"Date"]())].join("-");
-}
-_d.push(_f);
-if(_b.selector!="date"){
-var _11=[_c(_a[_e+"Hours"]()),_c(_a[_e+"Minutes"]()),_c(_a[_e+"Seconds"]())].join(":");
-var _12=_a[_e+"Milliseconds"]();
-if(_b.milliseconds){
-_11+="."+(_12<100?"0":"")+_c(_12);
-}
-if(_b.zulu){
-_11+="Z";
-}else{
-if(_b.selector!="time"){
-var _13=_a.getTimezoneOffset();
-var _14=Math.abs(_13);
-_11+=(_13>0?"-":"+")+_c(Math.floor(_14/60))+":"+_c(_14%60);
-}
-}
-_d.push(_11);
+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),
+		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.forEach(dojo.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){
+				return defaultTime["get" + prop]();
+			}), function(value, index){
+				match[index] = 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); //TODO: UTC defaults
+		if(match[0] < 100){
+			result.setFullYear(match[0] || 1970);
+		}
+
+		var offset = 0,
+			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
 }
-return _d.join("T");
-};
+
+/*=====
+	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 = [],
+		getter = options.zulu ? "getUTC" : "get",
+		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
 }
diff --git a/dojo/dnd/Avatar.js b/dojo/dnd/Avatar.js
index 57342db..a6415d6 100644
--- a/dojo/dnd/Avatar.js
+++ b/dojo/dnd/Avatar.js
@@ -1,64 +1,105 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.dnd.Avatar"]){
-dojo._hasResource["dojo.dnd.Avatar"]=true;
 dojo.provide("dojo.dnd.Avatar");
+
 dojo.require("dojo.dnd.common");
-dojo.declare("dojo.dnd.Avatar",null,{constructor:function(_1){
-this.manager=_1;
-this.construct();
-},construct:function(){
-this.isA11y=dojo.hasClass(dojo.body(),"dijit_a11y");
-var a=dojo.create("table",{"class":"dojoDndAvatar",style:{position:"absolute",zIndex:"1999",margin:"0px"}}),_2=this.manager.source,_3,b=dojo.create("tbody",null,a),tr=dojo.create("tr",null,b),td=dojo.create("td",null,tr),_4=this.isA11y?dojo.create("span",{id:"a11yIcon",innerHTML:this.manager.copy?"+":"<"},td):null,_5=dojo.create("span",{innerHTML:_2.generateText?this._generateText():""},td),k=Math.min(5,this.manager.nodes.length),i=0;
-dojo.attr(tr,{"class":"dojoDndAvatarHeader",style:{opacity:0.9}});
-for(;i<k;++i){
-if(_2.creator){
-_3=_2._normalizedCreator(_2.getItem(this.manager.nodes[i].id).data,"avatar").node;
-}else{
-_3=this.manager.nodes[i].cloneNode(true);
-if(_3.tagName.toLowerCase()=="tr"){
-var _6=dojo.create("table"),_7=dojo.create("tbody",null,_6);
-_7.appendChild(_3);
-_3=_6;
-}
-}
-_3.id="";
-tr=dojo.create("tr",null,b);
-td=dojo.create("td",null,tr);
-td.appendChild(_3);
-dojo.attr(tr,{"class":"dojoDndAvatarItem",style:{opacity:(9-i)/10}});
-}
-this.node=a;
-},destroy:function(){
-dojo.destroy(this.node);
-this.node=false;
-},update:function(){
-dojo[(this.manager.canDropFlag?"add":"remove")+"Class"](this.node,"dojoDndAvatarCanDrop");
-if(this.isA11y){
-var _8=dojo.byId("a11yIcon");
-var _9="+";
-if(this.manager.canDropFlag&&!this.manager.copy){
-_9="< ";
-}else{
-if(!this.manager.canDropFlag&&!this.manager.copy){
-_9="o";
-}else{
-if(!this.manager.canDropFlag){
-_9="x";
-}
-}
-}
-_8.innerHTML=_9;
-}
-dojo.query(("tr.dojoDndAvatarHeader td span"+(this.isA11y?" span":"")),this.node).forEach(function(_a){
-_a.innerHTML=this._generateText();
-},this);
-},_generateText:function(){
-return this.manager.nodes.length.toString();
-}});
-}
+
+dojo.declare("dojo.dnd.Avatar", null, {
+	// summary:
+	//		Object that represents transferred DnD items visually
+	// manager: Object
+	//		a DnD manager object
+
+	constructor: function(manager){
+		this.manager = manager;
+		this.construct();
+	},
+
+	// methods
+	construct: function(){
+		// summary:
+		//		constructor function;
+		//		it is separate so it can be (dynamically) overwritten in case of need
+		this.isA11y = dojo.hasClass(dojo.body(),"dijit_a11y");
+		var a = dojo.create("table", {
+				"class": "dojoDndAvatar",
+				style: {
+					position: "absolute",
+					zIndex:   "1999",
+					margin:   "0px"
+				}
+			}),
+			source = this.manager.source, node,
+			b = dojo.create("tbody", null, a),
+			tr = dojo.create("tr", null, b),
+			td = dojo.create("td", null, tr),
+			icon = this.isA11y ? dojo.create("span", {
+						id : "a11yIcon",
+						innerHTML : this.manager.copy ? '+' : "<"
+					}, td) : null,
+			span = dojo.create("span", {
+				innerHTML: source.generateText ? this._generateText() : ""
+			}, td),
+			k = Math.min(5, this.manager.nodes.length), i = 0;
+		// we have to set the opacity on IE only after the node is live
+		dojo.attr(tr, {
+			"class": "dojoDndAvatarHeader",
+			style: {opacity: 0.9}
+		});
+		for(; i < k; ++i){
+			if(source.creator){
+				// create an avatar representation of the node
+				node = source._normalizedCreator(source.getItem(this.manager.nodes[i].id).data, "avatar").node;
+			}else{
+				// or just clone the node and hope it works
+				node = this.manager.nodes[i].cloneNode(true);
+				if(node.tagName.toLowerCase() == "tr"){
+					// insert extra table nodes
+					var table = dojo.create("table"),
+						tbody = dojo.create("tbody", null, table);
+					tbody.appendChild(node);
+					node = table;
+				}
+			}
+			node.id = "";
+			tr = dojo.create("tr", null, b);
+			td = dojo.create("td", null, tr);
+			td.appendChild(node);
+			dojo.attr(tr, {
+				"class": "dojoDndAvatarItem",
+				style: {opacity: (9 - i) / 10}
+			});
+		}
+		this.node = a;
+	},
+	destroy: function(){
+		// summary:
+		//		destructor for the avatar; called to remove all references so it can be garbage-collected
+		dojo.destroy(this.node);
+		this.node = false;
+	},
+	update: function(){
+		// summary:
+		//		updates the avatar to reflect the current DnD state
+		dojo[(this.manager.canDropFlag ? "add" : "remove") + "Class"](this.node, "dojoDndAvatarCanDrop");
+		if (this.isA11y){
+			var icon = dojo.byId("a11yIcon");
+			var text = '+';   // assume canDrop && copy
+			if (this.manager.canDropFlag && !this.manager.copy) {
+				text = '< '; // canDrop && move 
+			}else if (!this.manager.canDropFlag && !this.manager.copy) {
+				text = "o"; //!canDrop && move
+			}else if(!this.manager.canDropFlag){
+				text = 'x';  // !canDrop && copy
+			}
+			icon.innerHTML=text;
+		}
+		// replace text
+		dojo.query(("tr.dojoDndAvatarHeader td span" +(this.isA11y ? " span" : "")), this.node).forEach(
+			function(node){
+				node.innerHTML = this._generateText();
+			}, this);
+	},
+	_generateText: function(){
+		// summary: generates a proper text to reflect copying or moving of items
+		return this.manager.nodes.length.toString();
+	}
+});
diff --git a/dojo/dnd/Container.js b/dojo/dnd/Container.js
index 432013b..2b4bfab 100644
--- a/dojo/dnd/Container.js
+++ b/dojo/dnd/Container.js
@@ -1,233 +1,428 @@
+dojo.provide("dojo.dnd.Container");
+
+dojo.require("dojo.dnd.common");
+dojo.require("dojo.parser");
+
 /*
-	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
+	Container states:
+		""		- normal state
+		"Over"	- mouse over a container
+	Container item states:
+		""		- normal state
+		"Over"	- mouse over a container item
 */
 
+/*=====
+dojo.declare("dojo.dnd.__ContainerArgs", [], {
+	creator: function(){
+		// summary:
+		//		a creator function, which takes a data item, and returns an object like that:
+		//		{node: newNode, data: usedData, type: arrayOfStrings}
+	},
 
-if(!dojo._hasResource["dojo.dnd.Container"]){
-dojo._hasResource["dojo.dnd.Container"]=true;
-dojo.provide("dojo.dnd.Container");
-dojo.require("dojo.dnd.common");
-dojo.require("dojo.parser");
-dojo.declare("dojo.dnd.Container",null,{skipForm:false,constructor:function(_1,_2){
-this.node=dojo.byId(_1);
-if(!_2){
-_2={};
-}
-this.creator=_2.creator||null;
-this.skipForm=_2.skipForm;
-this.parent=_2.dropParent&&dojo.byId(_2.dropParent);
-this.map={};
-this.current=null;
-this.containerState="";
-dojo.addClass(this.node,"dojoDndContainer");
-if(!(_2&&_2._skipStartup)){
-this.startup();
-}
-this.events=[dojo.connect(this.node,"onmouseover",this,"onMouseOver"),dojo.connect(this.node,"onmouseout",this,"onMouseOut"),dojo.connect(this.node,"ondragstart",this,"onSelectStart"),dojo.connect(this.node,"onselectstart",this,"onSelectStart")];
-},creator:function(){
-},getItem:function(_3){
-return this.map[_3];
-},setItem:function(_4,_5){
-this.map[_4]=_5;
-},delItem:function(_6){
-delete this.map[_6];
-},forInItems:function(f,o){
-o=o||dojo.global;
-var m=this.map,e=dojo.dnd._empty;
-for(var i in m){
-if(i in e){
-continue;
-}
-f.call(o,m[i],i,this);
-}
-return o;
-},clearItems:function(){
-this.map={};
-},getAllNodes:function(){
-return dojo.query("> .dojoDndItem",this.parent);
-},sync:function(){
-var _7={};
-this.getAllNodes().forEach(function(_8){
-if(_8.id){
-var _9=this.getItem(_8.id);
-if(_9){
-_7[_8.id]=_9;
-return;
-}
-}else{
-_8.id=dojo.dnd.getUniqueId();
-}
-var _a=_8.getAttribute("dndType"),_b=_8.getAttribute("dndData");
-_7[_8.id]={data:_b||_8.innerHTML,type:_a?_a.split(/\s*,\s*/):["text"]};
-},this);
-this.map=_7;
-return this;
-},insertNodes:function(_c,_d,_e){
-if(!this.parent.firstChild){
-_e=null;
-}else{
-if(_d){
-if(!_e){
-_e=this.parent.firstChild;
-}
-}else{
-if(_e){
-_e=_e.nextSibling;
-}
-}
-}
-if(_e){
-for(var i=0;i<_c.length;++i){
-var t=this._normalizedCreator(_c[i]);
-this.setItem(t.node.id,{data:t.data,type:t.type});
-this.parent.insertBefore(t.node,_e);
-}
-}else{
-for(var i=0;i<_c.length;++i){
-var t=this._normalizedCreator(_c[i]);
-this.setItem(t.node.id,{data:t.data,type:t.type});
-this.parent.appendChild(t.node);
-}
-}
-return this;
-},destroy:function(){
-dojo.forEach(this.events,dojo.disconnect);
-this.clearItems();
-this.node=this.parent=this.current=null;
-},markupFactory:function(_f,_10){
-_f._skipStartup=true;
-return new dojo.dnd.Container(_10,_f);
-},startup:function(){
-if(!this.parent){
-this.parent=this.node;
-if(this.parent.tagName.toLowerCase()=="table"){
-var c=this.parent.getElementsByTagName("tbody");
-if(c&&c.length){
-this.parent=c[0];
-}
-}
-}
-this.defaultCreator=dojo.dnd._defaultCreator(this.parent);
-this.sync();
-},onMouseOver:function(e){
-var n=e.relatedTarget;
-while(n){
-if(n==this.node){
-break;
-}
-try{
-n=n.parentNode;
-}
-catch(x){
-n=null;
-}
-}
-if(!n){
-this._changeState("Container","Over");
-this.onOverEvent();
-}
-n=this._getChildByEvent(e);
-if(this.current==n){
-return;
-}
-if(this.current){
-this._removeItemClass(this.current,"Over");
-}
-if(n){
-this._addItemClass(n,"Over");
-}
-this.current=n;
-},onMouseOut:function(e){
-for(var n=e.relatedTarget;n;){
-if(n==this.node){
-return;
-}
-try{
-n=n.parentNode;
-}
-catch(x){
-n=null;
-}
-}
-if(this.current){
-this._removeItemClass(this.current,"Over");
-this.current=null;
-}
-this._changeState("Container","");
-this.onOutEvent();
-},onSelectStart:function(e){
-if(!this.skipForm||!dojo.dnd.isFormElement(e)){
-dojo.stopEvent(e);
-}
-},onOverEvent:function(){
-},onOutEvent:function(){
-},_changeState:function(_11,_12){
-var _13="dojoDnd"+_11;
-var _14=_11.toLowerCase()+"State";
-dojo.removeClass(this.node,_13+this[_14]);
-dojo.addClass(this.node,_13+_12);
-this[_14]=_12;
-},_addItemClass:function(_15,_16){
-dojo.addClass(_15,"dojoDndItem"+_16);
-},_removeItemClass:function(_17,_18){
-dojo.removeClass(_17,"dojoDndItem"+_18);
-},_getChildByEvent:function(e){
-var _19=e.target;
-if(_19){
-for(var _1a=_19.parentNode;_1a;_19=_1a,_1a=_19.parentNode){
-if(_1a==this.parent&&dojo.hasClass(_19,"dojoDndItem")){
-return _19;
-}
-}
-}
-return null;
-},_normalizedCreator:function(_1b,_1c){
-var t=(this.creator||this.defaultCreator).call(this,_1b,_1c);
-if(!dojo.isArray(t.type)){
-t.type=["text"];
-}
-if(!t.node.id){
-t.node.id=dojo.dnd.getUniqueId();
-}
-dojo.addClass(t.node,"dojoDndItem");
-return t;
-}});
-dojo.dnd._createNode=function(tag){
-if(!tag){
-return dojo.dnd._createSpan;
-}
-return function(_1d){
-return dojo.create(tag,{innerHTML:_1d});
-};
-};
-dojo.dnd._createTrTd=function(_1e){
-var tr=dojo.create("tr");
-dojo.create("td",{innerHTML:_1e},tr);
-return tr;
+	// skipForm: Boolean
+	//		don't start the drag operation, if clicked on form elements
+	skipForm: false,
+
+	// dropParent: Node||String
+	//		node or node's id to use as the parent node for dropped items
+	//		(must be underneath the 'node' parameter in the DOM)
+	dropParent: null,
+
+	// _skipStartup: Boolean
+	//		skip startup(), which collects children, for deferred initialization
+	//		(this is used in the markup mode)
+	_skipStartup: false
+});
+
+dojo.dnd.Item = function(){
+	// summary:
+	//		Represents (one of) the source node(s) being dragged.
+	//		Contains (at least) the "type" and "data" attributes.
+	// type: String[]
+	//		Type(s) of this item, by default this is ["text"]
+	// data: Object
+	//		Logical representation of the object being dragged.
+	//		If the drag object's type is "text" then data is a String,
+	//		if it's another type then data could be a different Object,
+	//		perhaps a name/value hash.
+	
+	this.type = type;
+	this.data = data;
+}
+=====*/
+
+dojo.declare("dojo.dnd.Container", null, {
+	// summary:
+	//		a Container object, which knows when mouse hovers over it, 
+	//		and over which element it hovers
+	
+	// object attributes (for markup)
+	skipForm: false,
+	
+	/*=====
+	// current: DomNode
+	//		The DOM node the mouse is currently hovered over
+	current: null,
+	
+	// map: Hash<String, dojo.dnd.Item>
+	//		Map from an item's id (which is also the DOMNode's id) to
+	//		the dojo.dnd.Item itself.
+	map: {},
+	=====*/
+	
+	constructor: function(node, params){
+		// summary:
+		//		a constructor of the Container
+		// node: Node
+		//		node or node's id to build the container on
+		// params: dojo.dnd.__ContainerArgs
+		//		a dictionary of parameters
+		this.node = dojo.byId(node);
+		if(!params){ params = {}; }
+		this.creator = params.creator || null;
+		this.skipForm = params.skipForm;
+		this.parent = params.dropParent && dojo.byId(params.dropParent);
+		
+		// class-specific variables
+		this.map = {};
+		this.current = null;
+
+		// states
+		this.containerState = "";
+		dojo.addClass(this.node, "dojoDndContainer");
+		
+		// mark up children
+		if(!(params && params._skipStartup)){
+			this.startup();
+		}
+
+		// set up events
+		this.events = [
+			dojo.connect(this.node, "onmouseover", this, "onMouseOver"),
+			dojo.connect(this.node, "onmouseout",  this, "onMouseOut"),
+			// cancel text selection and text dragging
+			dojo.connect(this.node, "ondragstart",   this, "onSelectStart"),
+			dojo.connect(this.node, "onselectstart", this, "onSelectStart")
+		];
+	},
+	
+	// object attributes (for markup)
+	creator: function(){
+		// summary:
+		//		creator function, dummy at the moment
+	},
+	
+	// abstract access to the map
+	getItem: function(/*String*/ key){
+		// summary:
+		//		returns a data item by its key (id)
+		return this.map[key];	// dojo.dnd.Item
+	},
+	setItem: function(/*String*/ key, /*dojo.dnd.Item*/ data){
+		// summary:
+		//		associates a data item with its key (id)
+		this.map[key] = data;
+	},
+	delItem: function(/*String*/ key){
+		// summary:
+		//		removes a data item from the map by its key (id)
+		delete this.map[key];
+	},
+	forInItems: function(/*Function*/ f, /*Object?*/ o){
+		// summary:
+		//		iterates over a data map skipping members that 
+		//		are present in the empty object (IE and/or 3rd-party libraries).
+		o = o || dojo.global;
+		var m = this.map, e = dojo.dnd._empty;
+		for(var i in m){
+			if(i in e){ continue; }
+			f.call(o, m[i], i, this);
+		}
+		return o;	// Object
+	},
+	clearItems: function(){
+		// summary:
+		//		removes all data items from the map
+		this.map = {};
+	},
+	
+	// methods
+	getAllNodes: function(){
+		// summary:
+		//		returns a list (an array) of all valid child nodes
+		return dojo.query("> .dojoDndItem", this.parent);	// NodeList
+	},
+	sync: function(){
+		// summary:
+		//		sync up the node list with the data map
+		var map = {};
+		this.getAllNodes().forEach(function(node){
+			if(node.id){
+				var item = this.getItem(node.id);
+				if(item){
+					map[node.id] = item;
+					return;
+				}
+			}else{
+				node.id = dojo.dnd.getUniqueId();
+			}
+			var type = node.getAttribute("dndType"),
+				data = node.getAttribute("dndData");
+			map[node.id] = {
+				data: data || node.innerHTML,
+				type: type ? type.split(/\s*,\s*/) : ["text"]
+			};
+		}, this);
+		this.map = map;
+		return this;	// self
+	},
+	insertNodes: function(data, before, anchor){
+		// summary:
+		//		inserts an array of new nodes before/after an anchor node
+		// data: Array
+		//		a list of data items, which should be processed by the creator function
+		// before: Boolean
+		//		insert before the anchor, if true, and after the anchor otherwise
+		// anchor: Node
+		//		the anchor node to be used as a point of insertion
+		if(!this.parent.firstChild){
+			anchor = null;
+		}else if(before){
+			if(!anchor){
+				anchor = this.parent.firstChild;
+			}
+		}else{
+			if(anchor){
+				anchor = anchor.nextSibling;
+			}
+		}
+		if(anchor){
+			for(var i = 0; i < data.length; ++i){
+				var t = this._normalizedCreator(data[i]);
+				this.setItem(t.node.id, {data: t.data, type: t.type});
+				this.parent.insertBefore(t.node, anchor);
+			}
+		}else{
+			for(var i = 0; i < data.length; ++i){
+				var t = this._normalizedCreator(data[i]);
+				this.setItem(t.node.id, {data: t.data, type: t.type});
+				this.parent.appendChild(t.node);
+			}
+		}
+		return this;	// self
+	},
+	destroy: function(){
+		// summary:
+		//		prepares this object to be garbage-collected
+		dojo.forEach(this.events, dojo.disconnect);
+		this.clearItems();
+		this.node = this.parent = this.current = null;
+	},
+
+	// markup methods
+	markupFactory: function(params, node){
+		params._skipStartup = true;
+		return new dojo.dnd.Container(node, params);
+	},
+	startup: function(){
+		// summary:
+		//		collects valid child items and populate the map
+		
+		// set up the real parent node
+		if(!this.parent){
+			// use the standard algorithm, if not assigned
+			this.parent = this.node;
+			if(this.parent.tagName.toLowerCase() == "table"){
+				var c = this.parent.getElementsByTagName("tbody");
+				if(c && c.length){ this.parent = c[0]; }
+			}
+		}
+		this.defaultCreator = dojo.dnd._defaultCreator(this.parent);
+
+		// process specially marked children
+		this.sync();
+	},
+
+	// mouse events
+	onMouseOver: function(e){
+		// summary:
+		//		event processor for onmouseover
+		// e: Event
+		//		mouse event
+		var n = e.relatedTarget;
+		while(n){
+			if(n == this.node){ break; }
+			try{
+				n = n.parentNode;
+			}catch(x){
+				n = null;
+			}
+		}
+		if(!n){
+			this._changeState("Container", "Over");
+			this.onOverEvent();
+		}
+		n = this._getChildByEvent(e);
+		if(this.current == n){ return; }
+		if(this.current){ this._removeItemClass(this.current, "Over"); }
+		if(n){ this._addItemClass(n, "Over"); }
+		this.current = n;
+	},
+	onMouseOut: function(e){
+		// summary:
+		//		event processor for onmouseout
+		// e: Event
+		//		mouse event
+		for(var n = e.relatedTarget; n;){
+			if(n == this.node){ return; }
+			try{
+				n = n.parentNode;
+			}catch(x){
+				n = null;
+			}
+		}
+		if(this.current){
+			this._removeItemClass(this.current, "Over");
+			this.current = null;
+		}
+		this._changeState("Container", "");
+		this.onOutEvent();
+	},
+	onSelectStart: function(e){
+		// summary:
+		//		event processor for onselectevent and ondragevent
+		// e: Event
+		//		mouse event
+		if(!this.skipForm || !dojo.dnd.isFormElement(e)){
+			dojo.stopEvent(e);
+		}
+	},
+	
+	// utilities
+	onOverEvent: function(){
+		// summary:
+		//		this function is called once, when mouse is over our container
+	},
+	onOutEvent: function(){
+		// summary:
+		//		this function is called once, when mouse is out of our container
+	},
+	_changeState: function(type, newState){
+		// summary:
+		//		changes a named state to new state value
+		// type: String
+		//		a name of the state to change
+		// newState: String
+		//		new state
+		var prefix = "dojoDnd" + type;
+		var state  = type.toLowerCase() + "State";
+		//dojo.replaceClass(this.node, prefix + newState, prefix + this[state]);
+		dojo.removeClass(this.node, prefix + this[state]);
+		dojo.addClass(this.node, prefix + newState);
+		this[state] = newState;
+	},
+	_addItemClass: function(node, type){
+		// summary:
+		//		adds a class with prefix "dojoDndItem"
+		// node: Node
+		//		a node
+		// type: String
+		//		a variable suffix for a class name
+		dojo.addClass(node, "dojoDndItem" + type);
+	},
+	_removeItemClass: function(node, type){
+		// summary:
+		//		removes a class with prefix "dojoDndItem"
+		// node: Node
+		//		a node
+		// type: String
+		//		a variable suffix for a class name
+		dojo.removeClass(node, "dojoDndItem" + type);
+	},
+	_getChildByEvent: function(e){
+		// summary:
+		//		gets a child, which is under the mouse at the moment, or null
+		// e: Event
+		//		a mouse event
+		var node = e.target;
+		if(node){
+			for(var parent = node.parentNode; parent; node = parent, parent = node.parentNode){
+				if(parent == this.parent && dojo.hasClass(node, "dojoDndItem")){ return node; }
+			}
+		}
+		return null;
+	},
+	_normalizedCreator: function(/*dojo.dnd.Item*/ item, /*String*/ hint){
+		// summary:
+		//		adds all necessary data to the output of the user-supplied creator function
+		var t = (this.creator || this.defaultCreator).call(this, item, hint);
+		if(!dojo.isArray(t.type)){ t.type = ["text"]; }
+		if(!t.node.id){ t.node.id = dojo.dnd.getUniqueId(); }
+		dojo.addClass(t.node, "dojoDndItem");
+		return t;
+	}
+});
+
+dojo.dnd._createNode = function(tag){
+	// summary:
+	//		returns a function, which creates an element of given tag 
+	//		(SPAN by default) and sets its innerHTML to given text
+	// tag: String
+	//		a tag name or empty for SPAN
+	if(!tag){ return dojo.dnd._createSpan; }
+	return function(text){	// Function
+		return dojo.create(tag, {innerHTML: text});	// Node
+	};
 };
-dojo.dnd._createSpan=function(_1f){
-return dojo.create("span",{innerHTML:_1f});
+
+dojo.dnd._createTrTd = function(text){
+	// summary:
+	//		creates a TR/TD structure with given text as an innerHTML of TD
+	// text: String
+	//		a text for TD
+	var tr = dojo.create("tr");
+	dojo.create("td", {innerHTML: text}, tr);
+	return tr;	// Node
 };
-dojo.dnd._defaultCreatorNodes={ul:"li",ol:"li",div:"div",p:"div"};
-dojo.dnd._defaultCreator=function(_20){
-var tag=_20.tagName.toLowerCase();
-var c=tag=="tbody"||tag=="thead"?dojo.dnd._createTrTd:dojo.dnd._createNode(dojo.dnd._defaultCreatorNodes[tag]);
-return function(_21,_22){
-var _23=_21&&dojo.isObject(_21),_24,_25,n;
-if(_23&&_21.tagName&&_21.nodeType&&_21.getAttribute){
-_24=_21.getAttribute("dndData")||_21.innerHTML;
-_25=_21.getAttribute("dndType");
-_25=_25?_25.split(/\s*,\s*/):["text"];
-n=_21;
-}else{
-_24=(_23&&_21.data)?_21.data:_21;
-_25=(_23&&_21.type)?_21.type:["text"];
-n=(_22=="avatar"?dojo.dnd._createSpan:c)(String(_24));
-}
-n.id=dojo.dnd.getUniqueId();
-return {node:n,data:_24,type:_25};
+
+dojo.dnd._createSpan = function(text){
+	// summary:
+	//		creates a SPAN element with given text as its innerHTML
+	// text: String
+	//		a text for SPAN
+	return dojo.create("span", {innerHTML: text});	// Node
 };
+
+// dojo.dnd._defaultCreatorNodes: Object
+//		a dictionary that maps container tag names to child tag names
+dojo.dnd._defaultCreatorNodes = {ul: "li", ol: "li", div: "div", p: "div"};
+
+dojo.dnd._defaultCreator = function(node){
+	// summary:
+	//		takes a parent node, and returns an appropriate creator function
+	// node: Node
+	//		a container node
+	var tag = node.tagName.toLowerCase();
+	var c = tag == "tbody" || tag == "thead" ? dojo.dnd._createTrTd :
+			dojo.dnd._createNode(dojo.dnd._defaultCreatorNodes[tag]);
+	return function(item, hint){	// Function
+		var isObj = item && dojo.isObject(item), data, type, n;
+		if(isObj && item.tagName && item.nodeType && item.getAttribute){
+			// process a DOM node
+			data = item.getAttribute("dndData") || item.innerHTML;
+			type = item.getAttribute("dndType");
+			type = type ? type.split(/\s*,\s*/) : ["text"];
+			n = item;	// this node is going to be moved rather than copied
+		}else{
+			// process a DnD item object or a string
+			data = (isObj && item.data) ? item.data : item;
+			type = (isObj && item.type) ? item.type : ["text"];
+			n = (hint == "avatar" ? dojo.dnd._createSpan : c)(String(data));
+		}
+		if(!n.id){
+			n.id = dojo.dnd.getUniqueId();
+		}
+		return {node: n, data: data, type: type};
+	};
 };
-}
diff --git a/dojo/dnd/Manager.js b/dojo/dnd/Manager.js
index f23d2f4..8df4fe9 100644
--- a/dojo/dnd/Manager.js
+++ b/dojo/dnd/Manager.js
@@ -1,128 +1,209 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.dnd.Manager"]){
-dojo._hasResource["dojo.dnd.Manager"]=true;
 dojo.provide("dojo.dnd.Manager");
+
 dojo.require("dojo.dnd.common");
 dojo.require("dojo.dnd.autoscroll");
 dojo.require("dojo.dnd.Avatar");
-dojo.declare("dojo.dnd.Manager",null,{constructor:function(){
-this.avatar=null;
-this.source=null;
-this.nodes=[];
-this.copy=true;
-this.target=null;
-this.canDropFlag=false;
-this.events=[];
-},OFFSET_X:16,OFFSET_Y:16,overSource:function(_1){
-if(this.avatar){
-this.target=(_1&&_1.targetState!="Disabled")?_1:null;
-this.canDropFlag=Boolean(this.target);
-this.avatar.update();
-}
-dojo.publish("/dnd/source/over",[_1]);
-},outSource:function(_2){
-if(this.avatar){
-if(this.target==_2){
-this.target=null;
-this.canDropFlag=false;
-this.avatar.update();
-dojo.publish("/dnd/source/over",[null]);
-}
-}else{
-dojo.publish("/dnd/source/over",[null]);
-}
-},startDrag:function(_3,_4,_5){
-this.source=_3;
-this.nodes=_4;
-this.copy=Boolean(_5);
-this.avatar=this.makeAvatar();
-dojo.body().appendChild(this.avatar.node);
-dojo.publish("/dnd/start",[_3,_4,this.copy]);
-this.events=[dojo.connect(dojo.doc,"onmousemove",this,"onMouseMove"),dojo.connect(dojo.doc,"onmouseup",this,"onMouseUp"),dojo.connect(dojo.doc,"onkeydown",this,"onKeyDown"),dojo.connect(dojo.doc,"onkeyup",this,"onKeyUp"),dojo.connect(dojo.doc,"ondragstart",dojo.stopEvent),dojo.connect(dojo.body(),"onselectstart",dojo.stopEvent)];
-var c="dojoDnd"+(_5?"Copy":"Move");
-dojo.addClass(dojo.body(),c);
-},canDrop:function(_6){
-var _7=Boolean(this.target&&_6);
-if(this.canDropFlag!=_7){
-this.canDropFlag=_7;
-this.avatar.update();
-}
-},stopDrag:function(){
-dojo.removeClass(dojo.body(),"dojoDndCopy");
-dojo.removeClass(dojo.body(),"dojoDndMove");
-dojo.forEach(this.events,dojo.disconnect);
-this.events=[];
-this.avatar.destroy();
-this.avatar=null;
-this.source=this.target=null;
-this.nodes=[];
-},makeAvatar:function(){
-return new dojo.dnd.Avatar(this);
-},updateAvatar:function(){
-this.avatar.update();
-},onMouseMove:function(e){
-var a=this.avatar;
-if(a){
-dojo.dnd.autoScrollNodes(e);
-var s=a.node.style;
-s.left=(e.pageX+this.OFFSET_X)+"px";
-s.top=(e.pageY+this.OFFSET_Y)+"px";
-var _8=Boolean(this.source.copyState(dojo.isCopyKey(e)));
-if(this.copy!=_8){
-this._setCopyStatus(_8);
-}
-}
-},onMouseUp:function(e){
-if(this.avatar){
-if(this.target&&this.canDropFlag){
-var _9=Boolean(this.source.copyState(dojo.isCopyKey(e))),_a=[this.source,this.nodes,_9,this.target];
-dojo.publish("/dnd/drop/before",_a);
-dojo.publish("/dnd/drop",_a);
-}else{
-dojo.publish("/dnd/cancel");
-}
-this.stopDrag();
-}
-},onKeyDown:function(e){
-if(this.avatar){
-switch(e.keyCode){
-case dojo.keys.CTRL:
-var _b=Boolean(this.source.copyState(true));
-if(this.copy!=_b){
-this._setCopyStatus(_b);
-}
-break;
-case dojo.keys.ESCAPE:
-dojo.publish("/dnd/cancel");
-this.stopDrag();
-break;
-}
-}
-},onKeyUp:function(e){
-if(this.avatar&&e.keyCode==dojo.keys.CTRL){
-var _c=Boolean(this.source.copyState(false));
-if(this.copy!=_c){
-this._setCopyStatus(_c);
-}
-}
-},_setCopyStatus:function(_d){
-this.copy=_d;
-this.source._markDndStatus(this.copy);
-this.updateAvatar();
-dojo.removeClass(dojo.body(),"dojoDnd"+(this.copy?"Move":"Copy"));
-dojo.addClass(dojo.body(),"dojoDnd"+(this.copy?"Copy":"Move"));
-}});
-dojo.dnd._manager=null;
-dojo.dnd.manager=function(){
-if(!dojo.dnd._manager){
-dojo.dnd._manager=new dojo.dnd.Manager();
-}
-return dojo.dnd._manager;
+
+dojo.declare("dojo.dnd.Manager", null, {
+	// summary:
+	//		the manager of DnD operations (usually a singleton)
+	constructor: function(){
+		this.avatar  = null;
+		this.source = null;
+		this.nodes = [];
+		this.copy  = true;
+		this.target = null;
+		this.canDropFlag = false;
+		this.events = [];
+	},
+
+	// avatar's offset from the mouse
+	OFFSET_X: 16,
+	OFFSET_Y: 16,
+	
+	// methods
+	overSource: function(source){
+		// summary:
+		//		called when a source detected a mouse-over condition
+		// source: Object
+		//		the reporter
+		if(this.avatar){
+			this.target = (source && source.targetState != "Disabled") ? source : null;
+			this.canDropFlag = Boolean(this.target);
+			this.avatar.update();
+		}
+		dojo.publish("/dnd/source/over", [source]);
+	},
+	outSource: function(source){
+		// summary:
+		//		called when a source detected a mouse-out condition
+		// source: Object
+		//		the reporter
+		if(this.avatar){
+			if(this.target == source){
+				this.target = null;
+				this.canDropFlag = false;
+				this.avatar.update();
+				dojo.publish("/dnd/source/over", [null]);
+			}
+		}else{
+			dojo.publish("/dnd/source/over", [null]);
+		}
+	},
+	startDrag: function(source, nodes, copy){
+		// summary:
+		//		called to initiate the DnD operation
+		// source: Object
+		//		the source which provides items
+		// nodes: Array
+		//		the list of transferred items
+		// copy: Boolean
+		//		copy items, if true, move items otherwise
+		this.source = source;
+		this.nodes  = nodes;
+		this.copy   = Boolean(copy); // normalizing to true boolean
+		this.avatar = this.makeAvatar();
+		dojo.body().appendChild(this.avatar.node);
+		dojo.publish("/dnd/start", [source, nodes, this.copy]);
+		this.events = [
+			dojo.connect(dojo.doc, "onmousemove", this, "onMouseMove"),
+			dojo.connect(dojo.doc, "onmouseup",   this, "onMouseUp"),
+			dojo.connect(dojo.doc, "onkeydown",   this, "onKeyDown"),
+			dojo.connect(dojo.doc, "onkeyup",     this, "onKeyUp"),
+			// cancel text selection and text dragging
+			dojo.connect(dojo.doc, "ondragstart",   dojo.stopEvent),
+			dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent)
+		];
+		var c = "dojoDnd" + (copy ? "Copy" : "Move");
+		dojo.addClass(dojo.body(), c); 
+	},
+	canDrop: function(flag){
+		// summary:
+		//		called to notify if the current target can accept items
+		var canDropFlag = Boolean(this.target && flag);
+		if(this.canDropFlag != canDropFlag){
+			this.canDropFlag = canDropFlag;
+			this.avatar.update();
+		}
+	},
+	stopDrag: function(){
+		// summary:
+		//		stop the DnD in progress
+		dojo.removeClass(dojo.body(), "dojoDndCopy");
+		dojo.removeClass(dojo.body(), "dojoDndMove");
+		dojo.forEach(this.events, dojo.disconnect);
+		this.events = [];
+		this.avatar.destroy();
+		this.avatar = null;
+		this.source = this.target = null;
+		this.nodes = [];
+	},
+	makeAvatar: function(){
+		// summary:
+		//		makes the avatar; it is separate to be overwritten dynamically, if needed
+		return new dojo.dnd.Avatar(this);
+	},
+	updateAvatar: function(){
+		// summary:
+		//		updates the avatar; it is separate to be overwritten dynamically, if needed
+		this.avatar.update();
+	},
+	
+	// mouse event processors
+	onMouseMove: function(e){
+		// summary:
+		//		event processor for onmousemove
+		// e: Event
+		//		mouse event
+		var a = this.avatar;
+		if(a){
+			dojo.dnd.autoScrollNodes(e);
+			//dojo.dnd.autoScroll(e);
+			var s = a.node.style;
+			s.left = (e.pageX + this.OFFSET_X) + "px";
+			s.top  = (e.pageY + this.OFFSET_Y) + "px";
+			var copy = Boolean(this.source.copyState(dojo.isCopyKey(e)));
+			if(this.copy != copy){ 
+				this._setCopyStatus(copy);
+			}
+		}
+	},
+	onMouseUp: function(e){
+		// summary:
+		//		event processor for onmouseup
+		// e: Event
+		//		mouse event
+		if(this.avatar){
+			if(this.target && this.canDropFlag){
+				var copy = Boolean(this.source.copyState(dojo.isCopyKey(e))),
+				params = [this.source, this.nodes, copy, this.target, e];
+				dojo.publish("/dnd/drop/before", params);
+				dojo.publish("/dnd/drop", params);
+			}else{
+				dojo.publish("/dnd/cancel");
+			}
+			this.stopDrag();
+		}
+	},
+	
+	// keyboard event processors
+	onKeyDown: function(e){
+		// summary:
+		//		event processor for onkeydown:
+		//		watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag
+		// e: Event
+		//		keyboard event
+		if(this.avatar){
+			switch(e.keyCode){
+				case dojo.keys.CTRL:
+					var copy = Boolean(this.source.copyState(true));
+					if(this.copy != copy){ 
+						this._setCopyStatus(copy);
+					}
+					break;
+				case dojo.keys.ESCAPE:
+					dojo.publish("/dnd/cancel");
+					this.stopDrag();
+					break;
+			}
+		}
+	},
+	onKeyUp: function(e){
+		// summary:
+		//		event processor for onkeyup, watching for CTRL for copy/move status
+		// e: Event
+		//		keyboard event
+		if(this.avatar && e.keyCode == dojo.keys.CTRL){
+			var copy = Boolean(this.source.copyState(false));
+			if(this.copy != copy){ 
+				this._setCopyStatus(copy);
+			}
+		}
+	},
+	
+	// utilities
+	_setCopyStatus: function(copy){
+		// summary:
+		//		changes the copy status
+		// copy: Boolean
+		//		the copy status
+		this.copy = copy;
+		this.source._markDndStatus(this.copy);
+		this.updateAvatar();
+		dojo.removeClass(dojo.body(), "dojoDnd" + (this.copy ? "Move" : "Copy"));
+		dojo.addClass(dojo.body(), "dojoDnd" + (this.copy ? "Copy" : "Move"));
+	}
+});
+
+// dojo.dnd._manager:
+//		The manager singleton variable. Can be overwritten if needed.
+dojo.dnd._manager = null;
+
+dojo.dnd.manager = function(){
+	// summary:
+	//		Returns the current DnD manager.  Creates one if it is not created yet.
+	if(!dojo.dnd._manager){
+		dojo.dnd._manager = new dojo.dnd.Manager();
+	}
+	return dojo.dnd._manager;	// Object
 };
-}
diff --git a/dojo/dnd/Moveable.js b/dojo/dnd/Moveable.js
index 2f506a2..84ded8c 100644
--- a/dojo/dnd/Moveable.js
+++ b/dojo/dnd/Moveable.js
@@ -1,77 +1,167 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.dnd.Moveable"]){
-dojo._hasResource["dojo.dnd.Moveable"]=true;
 dojo.provide("dojo.dnd.Moveable");
+
 dojo.require("dojo.dnd.Mover");
-dojo.declare("dojo.dnd.Moveable",null,{handle:"",delay:0,skip:false,constructor:function(_1,_2){
-this.node=dojo.byId(_1);
-if(!_2){
-_2={};
-}
-this.handle=_2.handle?dojo.byId(_2.handle):null;
-if(!this.handle){
-this.handle=this.node;
-}
-this.delay=_2.delay>0?_2.delay:0;
-this.skip=_2.skip;
-this.mover=_2.mover?_2.mover:dojo.dnd.Mover;
-this.events=[dojo.connect(this.handle,"onmousedown",this,"onMouseDown"),dojo.connect(this.handle,"ondragstart",this,"onSelectStart"),dojo.connect(this.handle,"onselectstart",this,"onSelectStart")];
-},markupFactory:function(_3,_4){
-return new dojo.dnd.Moveable(_4,_3);
-},destroy:function(){
-dojo.forEach(this.events,dojo.disconnect);
-this.events=this.node=this.handle=null;
-},onMouseDown:function(e){
-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){
-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){
-for(var i=0;i<2;++i){
-dojo.disconnect(this.events.pop());
-}
-dojo.stopEvent(e);
-},onSelectStart:function(e){
-if(!this.skip||!dojo.dnd.isFormElement(e)){
-dojo.stopEvent(e);
-}
-},onDragDetected:function(e){
-new this.mover(this.node,e,this);
-},onMoveStart:function(_5){
-dojo.publish("/dnd/move/start",[_5]);
-dojo.addClass(dojo.body(),"dojoMove");
-dojo.addClass(this.node,"dojoMoveItem");
-},onMoveStop:function(_6){
-dojo.publish("/dnd/move/stop",[_6]);
-dojo.removeClass(dojo.body(),"dojoMove");
-dojo.removeClass(this.node,"dojoMoveItem");
-},onFirstMove:function(_7){
-},onMove:function(_8,_9){
-this.onMoving(_8,_9);
-var s=_8.node.style;
-s.left=_9.l+"px";
-s.top=_9.t+"px";
-this.onMoved(_8,_9);
-},onMoving:function(_a,_b){
-},onMoved:function(_c,_d){
-}});
-}
+
+/*=====
+dojo.declare("dojo.dnd.__MoveableArgs", [], {
+	// handle: Node||String
+	//		A node (or node's id), which is used as a mouse handle.
+	//		If omitted, the node itself is used as a handle.
+	handle: null,
+
+	// delay: Number
+	//		delay move by this number of pixels
+	delay: 0,
+
+	// skip: Boolean
+	//		skip move of form elements
+	skip: false,
+
+	// mover: Object
+	//		a constructor of custom Mover
+	mover: dojo.dnd.Mover
+});
+=====*/
+
+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: dojo.dnd.__MoveableArgs?
+		//		optional parameters
+		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, /* Event */ e){
+		// 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, /* Event */ e){
+		// 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
+	}
+});
diff --git a/dojo/dnd/Mover.js b/dojo/dnd/Mover.js
index 8e2a010..1a904b9 100644
--- a/dojo/dnd/Mover.js
+++ b/dojo/dnd/Mover.js
@@ -1,65 +1,106 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.dnd.Mover"]){
-dojo._hasResource["dojo.dnd.Mover"]=true;
 dojo.provide("dojo.dnd.Mover");
+
 dojo.require("dojo.dnd.common");
 dojo.require("dojo.dnd.autoscroll");
-dojo.declare("dojo.dnd.Mover",null,{constructor:function(_1,e,_2){
-this.node=dojo.byId(_1);
-this.marginBox={l:e.pageX,t:e.pageY};
-this.mouseButton=e.button;
-var h=this.host=_2,d=_1.ownerDocument,_3=dojo.connect(d,"onmousemove",this,"onFirstMove");
-this.events=[dojo.connect(d,"onmousemove",this,"onMouseMove"),dojo.connect(d,"onmouseup",this,"onMouseUp"),dojo.connect(d,"ondragstart",dojo.stopEvent),dojo.connect(d.body,"onselectstart",dojo.stopEvent),_3];
-if(h&&h.onMoveStart){
-h.onMoveStart(this);
-}
-},onMouseMove:function(e){
-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.isMac&&this.mouseButton==2?e.button==0:this.mouseButton==e.button){
-this.destroy();
-}
-dojo.stopEvent(e);
-},onFirstMove:function(){
-var s=this.node.style,l,t,h=this.host;
-switch(s.position){
-case "relative":
-case "absolute":
-l=Math.round(parseFloat(s.left));
-t=Math.round(parseFloat(s.top));
-break;
-default:
-s.position="absolute";
-var m=dojo.marginBox(this.node);
-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(){
-dojo.forEach(this.events,dojo.disconnect);
-var h=this.host;
-if(h&&h.onMoveStop){
-h.onMoveStop(this);
-}
-this.events=this.node=this.host=null;
-}});
-}
+
+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}, e);
+		dojo.stopEvent(e);
+	},
+	onMouseUp: function(e){
+		if(dojo.isWebKit && dojo.isMac && this.mouseButton == 2 ? 
+				e.button == 0 : this.mouseButton == e.button){
+			this.destroy();
+		}
+		dojo.stopEvent(e);
+	},
+	// utilities
+	onFirstMove: function(e){
+		// 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)) || 0;
+				t = Math.round(parseFloat(s.top)) || 0;
+				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, e);
+		}
+		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;
+	}
+});
diff --git a/dojo/dnd/Selector.js b/dojo/dnd/Selector.js
index 7e4ef69..49a7a69 100644
--- a/dojo/dnd/Selector.js
+++ b/dojo/dnd/Selector.js
@@ -1,239 +1,325 @@
+dojo.provide("dojo.dnd.Selector");
+
+dojo.require("dojo.dnd.common");
+dojo.require("dojo.dnd.Container");
+
 /*
-	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
+	Container item states:
+		""			- an item is not selected
+		"Selected"	- an item is selected
+		"Anchor"	- an item is selected, and is an anchor for a "shift" selection
 */
 
+/*=====
+dojo.declare("dojo.dnd.__SelectorArgs", [dojo.dnd.__ContainerArgs], {
+	//	singular: Boolean
+	//		allows selection of only one element, if true
+	singular: false,
 
-if(!dojo._hasResource["dojo.dnd.Selector"]){
-dojo._hasResource["dojo.dnd.Selector"]=true;
-dojo.provide("dojo.dnd.Selector");
-dojo.require("dojo.dnd.common");
-dojo.require("dojo.dnd.Container");
-dojo.declare("dojo.dnd.Selector",dojo.dnd.Container,{constructor:function(_1,_2){
-if(!_2){
-_2={};
-}
-this.singular=_2.singular;
-this.autoSync=_2.autoSync;
-this.selection={};
-this.anchor=null;
-this.simpleSelection=false;
-this.events.push(dojo.connect(this.node,"onmousedown",this,"onMouseDown"),dojo.connect(this.node,"onmouseup",this,"onMouseUp"));
-},singular:false,getSelectedNodes:function(){
-var t=new dojo.NodeList();
-var e=dojo.dnd._empty;
-for(var i in this.selection){
-if(i in e){
-continue;
-}
-t.push(dojo.byId(i));
-}
-return t;
-},selectNone:function(){
-return this._removeSelection()._removeAnchor();
-},selectAll:function(){
-this.forInItems(function(_3,id){
-this._addItemClass(dojo.byId(id),"Selected");
-this.selection[id]=1;
-},this);
-return this._removeAnchor();
-},deleteSelectedNodes:function(){
-var e=dojo.dnd._empty;
-for(var i in this.selection){
-if(i in e){
-continue;
-}
-var n=dojo.byId(i);
-this.delItem(i);
-dojo.destroy(n);
-}
-this.anchor=null;
-this.selection={};
-return this;
-},forInSelectedItems:function(f,o){
-o=o||dojo.global;
-var s=this.selection,e=dojo.dnd._empty;
-for(var i in s){
-if(i in e){
-continue;
-}
-f.call(o,this.getItem(i),i,this);
-}
-},sync:function(){
-dojo.dnd.Selector.superclass.sync.call(this);
-if(this.anchor){
-if(!this.getItem(this.anchor.id)){
-this.anchor=null;
-}
-}
-var t=[],e=dojo.dnd._empty;
-for(var i in this.selection){
-if(i in e){
-continue;
-}
-if(!this.getItem(i)){
-t.push(i);
-}
-}
-dojo.forEach(t,function(i){
-delete this.selection[i];
-},this);
-return this;
-},insertNodes:function(_4,_5,_6,_7){
-var _8=this._normalizedCreator;
-this._normalizedCreator=function(_9,_a){
-var t=_8.call(this,_9,_a);
-if(_4){
-if(!this.anchor){
-this.anchor=t.node;
-this._removeItemClass(t.node,"Selected");
-this._addItemClass(this.anchor,"Anchor");
-}else{
-if(this.anchor!=t.node){
-this._removeItemClass(t.node,"Anchor");
-this._addItemClass(t.node,"Selected");
-}
-}
-this.selection[t.node.id]=1;
-}else{
-this._removeItemClass(t.node,"Selected");
-this._removeItemClass(t.node,"Anchor");
-}
-return t;
-};
-dojo.dnd.Selector.superclass.insertNodes.call(this,_5,_6,_7);
-this._normalizedCreator=_8;
-return this;
-},destroy:function(){
-dojo.dnd.Selector.superclass.destroy.call(this);
-this.selection=this.anchor=null;
-},markupFactory:function(_b,_c){
-_b._skipStartup=true;
-return new dojo.dnd.Selector(_c,_b);
-},onMouseDown:function(e){
-if(this.autoSync){
-this.sync();
-}
-if(!this.current){
-return;
-}
-if(!this.singular&&!dojo.isCopyKey(e)&&!e.shiftKey&&(this.current.id in this.selection)){
-this.simpleSelection=true;
-if(e.button===dojo.mouseButtons.LEFT){
-dojo.stopEvent(e);
-}
-return;
-}
-if(!this.singular&&e.shiftKey){
-if(!dojo.isCopyKey(e)){
-this._removeSelection();
-}
-var c=this.getAllNodes();
-if(c.length){
-if(!this.anchor){
-this.anchor=c[0];
-this._addItemClass(this.anchor,"Anchor");
-}
-this.selection[this.anchor.id]=1;
-if(this.anchor!=this.current){
-var i=0;
-for(;i<c.length;++i){
-var _d=c[i];
-if(_d==this.anchor||_d==this.current){
-break;
-}
-}
-for(++i;i<c.length;++i){
-var _d=c[i];
-if(_d==this.anchor||_d==this.current){
-break;
-}
-this._addItemClass(_d,"Selected");
-this.selection[_d.id]=1;
-}
-this._addItemClass(this.current,"Selected");
-this.selection[this.current.id]=1;
-}
-}
-}else{
-if(this.singular){
-if(this.anchor==this.current){
-if(dojo.isCopyKey(e)){
-this.selectNone();
-}
-}else{
-this.selectNone();
-this.anchor=this.current;
-this._addItemClass(this.anchor,"Anchor");
-this.selection[this.current.id]=1;
-}
-}else{
-if(dojo.isCopyKey(e)){
-if(this.anchor==this.current){
-delete this.selection[this.anchor.id];
-this._removeAnchor();
-}else{
-if(this.current.id in this.selection){
-this._removeItemClass(this.current,"Selected");
-delete this.selection[this.current.id];
-}else{
-if(this.anchor){
-this._removeItemClass(this.anchor,"Anchor");
-this._addItemClass(this.anchor,"Selected");
-}
-this.anchor=this.current;
-this._addItemClass(this.current,"Anchor");
-this.selection[this.current.id]=1;
-}
-}
-}else{
-if(!(this.current.id in this.selection)){
-this.selectNone();
-this.anchor=this.current;
-this._addItemClass(this.current,"Anchor");
-this.selection[this.current.id]=1;
-}
-}
-}
-}
-dojo.stopEvent(e);
-},onMouseUp:function(e){
-if(!this.simpleSelection){
-return;
-}
-this.simpleSelection=false;
-this.selectNone();
-if(this.current){
-this.anchor=this.current;
-this._addItemClass(this.anchor,"Anchor");
-this.selection[this.current.id]=1;
-}
-},onMouseMove:function(e){
-this.simpleSelection=false;
-},onOverEvent:function(){
-this.onmousemoveEvent=dojo.connect(this.node,"onmousemove",this,"onMouseMove");
-},onOutEvent:function(){
-dojo.disconnect(this.onmousemoveEvent);
-delete this.onmousemoveEvent;
-},_removeSelection:function(){
-var e=dojo.dnd._empty;
-for(var i in this.selection){
-if(i in e){
-continue;
-}
-var _e=dojo.byId(i);
-if(_e){
-this._removeItemClass(_e,"Selected");
-}
-}
-this.selection={};
-return this;
-},_removeAnchor:function(){
-if(this.anchor){
-this._removeItemClass(this.anchor,"Anchor");
-this.anchor=null;
-}
-return this;
-}});
-}
+	//	autoSync: Boolean
+	//		autosynchronizes the source with its list of DnD nodes,
+	autoSync: false
+});
+=====*/
+
+dojo.declare("dojo.dnd.Selector", dojo.dnd.Container, {
+	// summary:
+	//		a Selector object, which knows how to select its children
+	
+	/*=====
+	// selection: Set<String>
+	//		The set of id's that are currently selected, such that this.selection[id] == 1
+	//		if the node w/that id is selected.  Can iterate over selected node's id's like:
+	//	|		for(var id in this.selection)
+	selection: {},
+	=====*/
+
+	constructor: function(node, params){
+		// summary:
+		//		constructor of the Selector
+		// node: Node||String
+		//		node or node's id to build the selector on
+		// params: dojo.dnd.__SelectorArgs?
+		//		a dictionary of parameters
+		if(!params){ params = {}; }
+		this.singular = params.singular;
+		this.autoSync = params.autoSync;
+		// class-specific variables
+		this.selection = {};
+		this.anchor = null;
+		this.simpleSelection = false;
+		// set up events
+		this.events.push(
+			dojo.connect(this.node, "onmousedown", this, "onMouseDown"),
+			dojo.connect(this.node, "onmouseup",   this, "onMouseUp"));
+	},
+	
+	// object attributes (for markup)
+	singular: false,	// is singular property
+	
+	// methods
+	getSelectedNodes: function(){
+		// summary:
+		//		returns a list (an array) of selected nodes
+		var t = new dojo.NodeList();
+		var e = dojo.dnd._empty;
+		for(var i in this.selection){
+			if(i in e){ continue; }
+			t.push(dojo.byId(i));
+		}
+		return t;	// NodeList
+	},
+	selectNone: function(){
+		// summary:
+		//		unselects all items
+		return this._removeSelection()._removeAnchor();	// self
+	},
+	selectAll: function(){
+		// summary:
+		//		selects all items
+		this.forInItems(function(data, id){
+			this._addItemClass(dojo.byId(id), "Selected");
+			this.selection[id] = 1;
+		}, this);
+		return this._removeAnchor();	// self
+	},
+	deleteSelectedNodes: function(){
+		// summary:
+		//		deletes all selected items
+		var e = dojo.dnd._empty;
+		for(var i in this.selection){
+			if(i in e){ continue; }
+			var n = dojo.byId(i);
+			this.delItem(i);
+			dojo.destroy(n);
+		}
+		this.anchor = null;
+		this.selection = {};
+		return this;	// self
+	},
+	forInSelectedItems: function(/*Function*/ f, /*Object?*/ o){
+		// summary:
+		//		iterates over selected items;
+		//		see `dojo.dnd.Container.forInItems()` for details
+		o = o || dojo.global;
+		var s = this.selection, e = dojo.dnd._empty;
+		for(var i in s){
+			if(i in e){ continue; }
+			f.call(o, this.getItem(i), i, this);
+		}
+	},
+	sync: function(){
+		// summary:
+		//		sync up the node list with the data map
+		
+		dojo.dnd.Selector.superclass.sync.call(this);
+		
+		// fix the anchor
+		if(this.anchor){
+			if(!this.getItem(this.anchor.id)){
+				this.anchor = null;
+			}
+		}
+		
+		// fix the selection
+		var t = [], e = dojo.dnd._empty;
+		for(var i in this.selection){
+			if(i in e){ continue; }
+			if(!this.getItem(i)){
+				t.push(i);
+			}
+		}
+		dojo.forEach(t, function(i){
+			delete this.selection[i];
+		}, this);
+		
+		return this;	// self
+	},
+	insertNodes: function(addSelected, data, before, anchor){
+		// summary:
+		//		inserts new data items (see `dojo.dnd.Container.insertNodes()` method for details)
+		// addSelected: Boolean
+		//		all new nodes will be added to selected items, if true, no selection change otherwise
+		// data: Array
+		//		a list of data items, which should be processed by the creator function
+		// before: Boolean
+		//		insert before the anchor, if true, and after the anchor otherwise
+		// anchor: Node
+		//		the anchor node to be used as a point of insertion
+		var oldCreator = this._normalizedCreator;
+		this._normalizedCreator = function(item, hint){
+			var t = oldCreator.call(this, item, hint);
+			if(addSelected){
+				if(!this.anchor){
+					this.anchor = t.node;
+					this._removeItemClass(t.node, "Selected");
+					this._addItemClass(this.anchor, "Anchor");
+				}else if(this.anchor != t.node){
+					this._removeItemClass(t.node, "Anchor");
+					this._addItemClass(t.node, "Selected");
+				}
+				this.selection[t.node.id] = 1;
+			}else{
+				this._removeItemClass(t.node, "Selected");
+				this._removeItemClass(t.node, "Anchor");
+			}
+			return t;
+		};
+		dojo.dnd.Selector.superclass.insertNodes.call(this, data, before, anchor);
+		this._normalizedCreator = oldCreator;
+		return this;	// self
+	},
+	destroy: function(){
+		// summary:
+		//		prepares the object to be garbage-collected
+		dojo.dnd.Selector.superclass.destroy.call(this);
+		this.selection = this.anchor = null;
+	},
+
+	// markup methods
+	markupFactory: function(params, node){
+		params._skipStartup = true;
+		return new dojo.dnd.Selector(node, params);
+	},
+
+	// mouse events
+	onMouseDown: function(e){
+		// summary:
+		//		event processor for onmousedown
+		// e: Event
+		//		mouse event
+		if(this.autoSync){ this.sync(); }
+		if(!this.current){ return; }
+		if(!this.singular && !dojo.isCopyKey(e) && !e.shiftKey && (this.current.id in this.selection)){
+			this.simpleSelection = true;
+			if(e.button === dojo.mouseButtons.LEFT){
+				// accept the left button and stop the event
+				// for IE we don't stop event when multiple buttons are pressed
+				dojo.stopEvent(e);
+			}
+			return;
+		}
+		if(!this.singular && e.shiftKey){
+			if(!dojo.isCopyKey(e)){
+				this._removeSelection();
+			}
+			var c = this.getAllNodes();
+			if(c.length){
+				if(!this.anchor){
+					this.anchor = c[0];
+					this._addItemClass(this.anchor, "Anchor");
+				}
+				this.selection[this.anchor.id] = 1;
+				if(this.anchor != this.current){
+					var i = 0;
+					for(; i < c.length; ++i){
+						var node = c[i];
+						if(node == this.anchor || node == this.current){ break; }
+					}
+					for(++i; i < c.length; ++i){
+						var node = c[i];
+						if(node == this.anchor || node == this.current){ break; }
+						this._addItemClass(node, "Selected");
+						this.selection[node.id] = 1;
+					}
+					this._addItemClass(this.current, "Selected");
+					this.selection[this.current.id] = 1;
+				}
+			}
+		}else{
+			if(this.singular){
+				if(this.anchor == this.current){
+					if(dojo.isCopyKey(e)){
+						this.selectNone();
+					}
+				}else{
+					this.selectNone();
+					this.anchor = this.current;
+					this._addItemClass(this.anchor, "Anchor");
+					this.selection[this.current.id] = 1;
+				}
+			}else{
+				if(dojo.isCopyKey(e)){
+					if(this.anchor == this.current){
+						delete this.selection[this.anchor.id];
+						this._removeAnchor();
+					}else{
+						if(this.current.id in this.selection){
+							this._removeItemClass(this.current, "Selected");
+							delete this.selection[this.current.id];
+						}else{
+							if(this.anchor){
+								this._removeItemClass(this.anchor, "Anchor");
+								this._addItemClass(this.anchor, "Selected");
+							}
+							this.anchor = this.current;
+							this._addItemClass(this.current, "Anchor");
+							this.selection[this.current.id] = 1;
+						}
+					}
+				}else{
+					if(!(this.current.id in this.selection)){
+						this.selectNone();
+						this.anchor = this.current;
+						this._addItemClass(this.current, "Anchor");
+						this.selection[this.current.id] = 1;
+					}
+				}
+			}
+		}
+		dojo.stopEvent(e);
+	},
+	onMouseUp: function(e){
+		// summary:
+		//		event processor for onmouseup
+		// e: Event
+		//		mouse event
+		if(!this.simpleSelection){ return; }
+		this.simpleSelection = false;
+		this.selectNone();
+		if(this.current){
+			this.anchor = this.current;
+			this._addItemClass(this.anchor, "Anchor");
+			this.selection[this.current.id] = 1;
+		}
+	},
+	onMouseMove: function(e){
+		// summary
+		//		event processor for onmousemove
+		// e: Event
+		//		mouse event
+		this.simpleSelection = false;
+	},
+	
+	// utilities
+	onOverEvent: function(){
+		// summary:
+		//		this function is called once, when mouse is over our container
+		this.onmousemoveEvent = dojo.connect(this.node, "onmousemove", this, "onMouseMove");
+	},
+	onOutEvent: function(){
+		// summary:
+		//		this function is called once, when mouse is out of our container
+		dojo.disconnect(this.onmousemoveEvent);
+		delete this.onmousemoveEvent;
+	},
+	_removeSelection: function(){
+		// summary:
+		//		unselects all items
+		var e = dojo.dnd._empty;
+		for(var i in this.selection){
+			if(i in e){ continue; }
+			var node = dojo.byId(i);
+			if(node){ this._removeItemClass(node, "Selected"); }
+		}
+		this.selection = {};
+		return this;	// self
+	},
+	_removeAnchor: function(){
+		if(this.anchor){
+			this._removeItemClass(this.anchor, "Anchor");
+			this.anchor = null;
+		}
+		return this;	// self
+	}
+});
diff --git a/dojo/dnd/Source.js b/dojo/dnd/Source.js
index e1131dd..beb06fa 100644
--- a/dojo/dnd/Source.js
+++ b/dojo/dnd/Source.js
@@ -1,297 +1,538 @@
+dojo.provide("dojo.dnd.Source");
+
+dojo.require("dojo.dnd.Selector");
+dojo.require("dojo.dnd.Manager");
+
 /*
-	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
+	Container property:
+		"Horizontal"- if this is the horizontal container
+	Source states:
+		""			- normal state
+		"Moved"		- this source is being moved
+		"Copied"	- this source is being copied
+	Target states:
+		""			- normal state
+		"Disabled"	- the target cannot accept an avatar
+	Target anchor state:
+		""			- item is not selected
+		"Before"	- insert point is before the anchor
+		"After"		- insert point is after the anchor
 */
 
+/*=====
+dojo.dnd.__SourceArgs = function(){
+	//	summary:
+	//		a dict of parameters for DnD Source configuration. Note that any
+	//		property on Source elements may be configured, but this is the
+	//		short-list
+	//	isSource: Boolean?
+	//		can be used as a DnD source. Defaults to true.
+	//	accept: Array?
+	//		list of accepted types (text strings) for a target; defaults to
+	//		["text"]
+	//	autoSync: Boolean
+	//		if true refreshes the node list on every operation; false by default
+	//	copyOnly: Boolean?
+	//		copy items, if true, use a state of Ctrl key otherwise,
+	//		see selfCopy and selfAccept for more details
+	//	delay: Number
+	//		the move delay in pixels before detecting a drag; 0 by default
+	//	horizontal: Boolean?
+	//		a horizontal container, if true, vertical otherwise or when omitted
+	//	selfCopy: Boolean?
+	//		copy items by default when dropping on itself,
+	//		false by default, works only if copyOnly is true
+	//	selfAccept: Boolean?
+	//		accept its own items when copyOnly is true,
+	//		true by default, works only if copyOnly is true
+	//	withHandles: Boolean?
+	//		allows dragging only by handles, false by default
+	//  generateText: Boolean?
+	//		generate text node for drag and drop, true by default
+	this.isSource = isSource;
+	this.accept = accept;
+	this.autoSync = autoSync;
+	this.copyOnly = copyOnly;
+	this.delay = delay;
+	this.horizontal = horizontal;
+	this.selfCopy = selfCopy;
+	this.selfAccept = selfAccept;
+	this.withHandles = withHandles;
+	this.generateText = true;
+}
+=====*/
 
-if(!dojo._hasResource["dojo.dnd.Source"]){
-dojo._hasResource["dojo.dnd.Source"]=true;
-dojo.provide("dojo.dnd.Source");
-dojo.require("dojo.dnd.Selector");
-dojo.require("dojo.dnd.Manager");
-dojo.declare("dojo.dnd.Source",dojo.dnd.Selector,{isSource:true,horizontal:false,copyOnly:false,selfCopy:false,selfAccept:true,skipForm:false,withHandles:false,autoSync:false,delay:0,accept:["text"],generateText:true,constructor:function(_1,_2){
-dojo.mixin(this,dojo.mixin({},_2));
-var _3=this.accept;
-if(_3.length){
-this.accept={};
-for(var i=0;i<_3.length;++i){
-this.accept[_3[i]]=1;
-}
-}
-this.isDragging=false;
-this.mouseDown=false;
-this.targetAnchor=null;
-this.targetBox=null;
-this.before=true;
-this._lastX=0;
-this._lastY=0;
-this.sourceState="";
-if(this.isSource){
-dojo.addClass(this.node,"dojoDndSource");
-}
-this.targetState="";
-if(this.accept){
-dojo.addClass(this.node,"dojoDndTarget");
-}
-if(this.horizontal){
-dojo.addClass(this.node,"dojoDndHorizontal");
-}
-this.topics=[dojo.subscribe("/dnd/source/over",this,"onDndSourceOver"),dojo.subscribe("/dnd/start",this,"onDndStart"),dojo.subscribe("/dnd/drop",this,"onDndDrop"),dojo.subscribe("/dnd/cancel",this,"onDndCancel")];
-},checkAcceptance:function(_4,_5){
-if(this==_4){
-return !this.copyOnly||this.selfAccept;
-}
-for(var i=0;i<_5.length;++i){
-var _6=_4.getItem(_5[i].id).type;
-var _7=false;
-for(var j=0;j<_6.length;++j){
-if(_6[j] in this.accept){
-_7=true;
-break;
-}
-}
-if(!_7){
-return false;
-}
-}
-return true;
-},copyState:function(_8,_9){
-if(_8){
-return true;
-}
-if(arguments.length<2){
-_9=this==dojo.dnd.manager().target;
-}
-if(_9){
-if(this.copyOnly){
-return this.selfCopy;
-}
-}else{
-return this.copyOnly;
-}
-return false;
-},destroy:function(){
-dojo.dnd.Source.superclass.destroy.call(this);
-dojo.forEach(this.topics,dojo.unsubscribe);
-this.targetAnchor=null;
-},markupFactory:function(_a,_b){
-_a._skipStartup=true;
-return new dojo.dnd.Source(_b,_a);
-},onMouseMove:function(e){
-if(this.isDragging&&this.targetState=="Disabled"){
-return;
-}
-dojo.dnd.Source.superclass.onMouseMove.call(this,e);
-var m=dojo.dnd.manager();
-if(this.isDragging){
-var _c=false;
-if(this.current){
-if(!this.targetBox||this.targetAnchor!=this.current){
-this.targetBox=dojo.position(this.current,true);
-}
-if(this.horizontal){
-_c=(e.pageX-this.targetBox.x)<(this.targetBox.w/2);
-}else{
-_c=(e.pageY-this.targetBox.y)<(this.targetBox.h/2);
-}
-}
-if(this.current!=this.targetAnchor||_c!=this.before){
-this._markTargetAnchor(_c);
-m.canDrop(!this.current||m.source!=this||!(this.current.id in this.selection));
-}
-}else{
-if(this.mouseDown&&this.isSource&&(Math.abs(e.pageX-this._lastX)>this.delay||Math.abs(e.pageY-this._lastY)>this.delay)){
-var _d=this.getSelectedNodes();
-if(_d.length){
-m.startDrag(this,_d,this.copyState(dojo.isCopyKey(e),true));
-}
-}
-}
-},onMouseDown:function(e){
-if(!this.mouseDown&&this._legalMouseDown(e)&&(!this.skipForm||!dojo.dnd.isFormElement(e))){
-this.mouseDown=true;
-this._lastX=e.pageX;
-this._lastY=e.pageY;
-dojo.dnd.Source.superclass.onMouseDown.call(this,e);
-}
-},onMouseUp:function(e){
-if(this.mouseDown){
-this.mouseDown=false;
-dojo.dnd.Source.superclass.onMouseUp.call(this,e);
-}
-},onDndSourceOver:function(_e){
-if(this!=_e){
-this.mouseDown=false;
-if(this.targetAnchor){
-this._unmarkTargetAnchor();
-}
-}else{
-if(this.isDragging){
-var m=dojo.dnd.manager();
-m.canDrop(this.targetState!="Disabled"&&(!this.current||m.source!=this||!(this.current.id in this.selection)));
-}
-}
-},onDndStart:function(_f,_10,_11){
-if(this.autoSync){
-this.sync();
-}
-if(this.isSource){
-this._changeState("Source",this==_f?(_11?"Copied":"Moved"):"");
-}
-var _12=this.accept&&this.checkAcceptance(_f,_10);
-this._changeState("Target",_12?"":"Disabled");
-if(this==_f){
-dojo.dnd.manager().overSource(this);
-}
-this.isDragging=true;
-},onDndDrop:function(_13,_14,_15,_16){
-if(this==_16){
-this.onDrop(_13,_14,_15);
-}
-this.onDndCancel();
-},onDndCancel:function(){
-if(this.targetAnchor){
-this._unmarkTargetAnchor();
-this.targetAnchor=null;
-}
-this.before=true;
-this.isDragging=false;
-this.mouseDown=false;
-this._changeState("Source","");
-this._changeState("Target","");
-},onDrop:function(_17,_18,_19){
-if(this!=_17){
-this.onDropExternal(_17,_18,_19);
-}else{
-this.onDropInternal(_18,_19);
-}
-},onDropExternal:function(_1a,_1b,_1c){
-var _1d=this._normalizedCreator;
-if(this.creator){
-this._normalizedCreator=function(_1e,_1f){
-return _1d.call(this,_1a.getItem(_1e.id).data,_1f);
-};
-}else{
-if(_1c){
-this._normalizedCreator=function(_20,_21){
-var t=_1a.getItem(_20.id);
-var n=_20.cloneNode(true);
-n.id=dojo.dnd.getUniqueId();
-return {node:n,data:t.data,type:t.type};
-};
-}else{
-this._normalizedCreator=function(_22,_23){
-var t=_1a.getItem(_22.id);
-_1a.delItem(_22.id);
-return {node:_22,data:t.data,type:t.type};
-};
-}
-}
-this.selectNone();
-if(!_1c&&!this.creator){
-_1a.selectNone();
-}
-this.insertNodes(true,_1b,this.before,this.current);
-if(!_1c&&this.creator){
-_1a.deleteSelectedNodes();
-}
-this._normalizedCreator=_1d;
-},onDropInternal:function(_24,_25){
-var _26=this._normalizedCreator;
-if(this.current&&this.current.id in this.selection){
-return;
-}
-if(_25){
-if(this.creator){
-this._normalizedCreator=function(_27,_28){
-return _26.call(this,this.getItem(_27.id).data,_28);
-};
-}else{
-this._normalizedCreator=function(_29,_2a){
-var t=this.getItem(_29.id);
-var n=_29.cloneNode(true);
-n.id=dojo.dnd.getUniqueId();
-return {node:n,data:t.data,type:t.type};
-};
-}
-}else{
-if(!this.current){
-return;
-}
-this._normalizedCreator=function(_2b,_2c){
-var t=this.getItem(_2b.id);
-return {node:_2b,data:t.data,type:t.type};
-};
-}
-this._removeSelection();
-this.insertNodes(true,_24,this.before,this.current);
-this._normalizedCreator=_26;
-},onDraggingOver:function(){
-},onDraggingOut:function(){
-},onOverEvent:function(){
-dojo.dnd.Source.superclass.onOverEvent.call(this);
-dojo.dnd.manager().overSource(this);
-if(this.isDragging&&this.targetState!="Disabled"){
-this.onDraggingOver();
-}
-},onOutEvent:function(){
-dojo.dnd.Source.superclass.onOutEvent.call(this);
-dojo.dnd.manager().outSource(this);
-if(this.isDragging&&this.targetState!="Disabled"){
-this.onDraggingOut();
-}
-},_markTargetAnchor:function(_2d){
-if(this.current==this.targetAnchor&&this.before==_2d){
-return;
-}
-if(this.targetAnchor){
-this._removeItemClass(this.targetAnchor,this.before?"Before":"After");
-}
-this.targetAnchor=this.current;
-this.targetBox=null;
-this.before=_2d;
-if(this.targetAnchor){
-this._addItemClass(this.targetAnchor,this.before?"Before":"After");
-}
-},_unmarkTargetAnchor:function(){
-if(!this.targetAnchor){
-return;
-}
-this._removeItemClass(this.targetAnchor,this.before?"Before":"After");
-this.targetAnchor=null;
-this.targetBox=null;
-this.before=true;
-},_markDndStatus:function(_2e){
-this._changeState("Source",_2e?"Copied":"Moved");
-},_legalMouseDown:function(e){
-if(!dojo.mouseButtons.isLeft(e)){
-return false;
-}
-if(!this.withHandles){
-return true;
-}
-for(var _2f=e.target;_2f&&_2f!==this.node;_2f=_2f.parentNode){
-if(dojo.hasClass(_2f,"dojoDndHandle")){
-return true;
-}
-if(dojo.hasClass(_2f,"dojoDndItem")||dojo.hasClass(_2f,"dojoDndIgnore")){
-break;
-}
-}
-return false;
-}});
-dojo.declare("dojo.dnd.Target",dojo.dnd.Source,{constructor:function(_30,_31){
-this.isSource=false;
-dojo.removeClass(this.node,"dojoDndSource");
-},markupFactory:function(_32,_33){
-_32._skipStartup=true;
-return new dojo.dnd.Target(_33,_32);
-}});
-dojo.declare("dojo.dnd.AutoSource",dojo.dnd.Source,{constructor:function(_34,_35){
-this.autoSync=true;
-},markupFactory:function(_36,_37){
-_36._skipStartup=true;
-return new dojo.dnd.AutoSource(_37,_36);
-}});
-}
+dojo.declare("dojo.dnd.Source", dojo.dnd.Selector, {
+	// summary:
+	//		a Source object, which can be used as a DnD source, or a DnD target
+	
+	// object attributes (for markup)
+	isSource: true,
+	horizontal: false,
+	copyOnly: false,
+	selfCopy: false,
+	selfAccept: true,
+	skipForm: false,
+	withHandles: false,
+	autoSync: false,
+	delay: 0, // pixels
+	accept: ["text"],
+	generateText: true,
+	
+	constructor: function(/*DOMNode|String*/node, /*dojo.dnd.__SourceArgs?*/params){
+		// summary: 
+		//		a constructor of the Source
+		// node:
+		//		node or node's id to build the source on
+		// params: 
+		//		any property of this class may be configured via the params
+		//		object which is mixed-in to the `dojo.dnd.Source` instance
+		dojo.mixin(this, dojo.mixin({}, params));
+		var type = this.accept;
+		if(type.length){
+			this.accept = {};
+			for(var i = 0; i < type.length; ++i){
+				this.accept[type[i]] = 1;
+			}
+		}
+		// class-specific variables
+		this.isDragging = false;
+		this.mouseDown = false;
+		this.targetAnchor = null;
+		this.targetBox = null;
+		this.before = true;
+		this._lastX = 0;
+		this._lastY = 0;
+		// states
+		this.sourceState  = "";
+		if(this.isSource){
+			dojo.addClass(this.node, "dojoDndSource");
+		}
+		this.targetState  = "";
+		if(this.accept){
+			dojo.addClass(this.node, "dojoDndTarget");
+		}
+		if(this.horizontal){
+			dojo.addClass(this.node, "dojoDndHorizontal");
+		}
+		// set up events
+		this.topics = [
+			dojo.subscribe("/dnd/source/over", this, "onDndSourceOver"),
+			dojo.subscribe("/dnd/start",  this, "onDndStart"),
+			dojo.subscribe("/dnd/drop",   this, "onDndDrop"),
+			dojo.subscribe("/dnd/cancel", this, "onDndCancel")
+		];
+	},
+	
+	// methods
+	checkAcceptance: function(source, nodes){
+		// summary:
+		//		checks if the target can accept nodes from this source
+		// source: Object
+		//		the source which provides items
+		// nodes: Array
+		//		the list of transferred items
+		if(this == source){
+			return !this.copyOnly || this.selfAccept;
+		}
+		for(var i = 0; i < nodes.length; ++i){
+			var type = source.getItem(nodes[i].id).type;
+			// type instanceof Array
+			var flag = false;
+			for(var j = 0; j < type.length; ++j){
+				if(type[j] in this.accept){
+					flag = true;
+					break;
+				}
+			}
+			if(!flag){
+				return false;	// Boolean
+			}
+		}
+		return true;	// Boolean
+	},
+	copyState: function(keyPressed, self){
+		// summary:
+		//		Returns true if we need to copy items, false to move.
+		//		It is separated to be overwritten dynamically, if needed.
+		// keyPressed: Boolean
+		//		the "copy" key was pressed
+		// self: Boolean?
+		//		optional flag that means that we are about to drop on itself
+		
+		if(keyPressed){ return true; }
+		if(arguments.length < 2){
+			self = this == dojo.dnd.manager().target;
+		}
+		if(self){
+			if(this.copyOnly){
+				return this.selfCopy;
+			}
+		}else{
+			return this.copyOnly;
+		}
+		return false;	// Boolean
+	},
+	destroy: function(){
+		// summary:
+		//		prepares the object to be garbage-collected
+		dojo.dnd.Source.superclass.destroy.call(this);
+		dojo.forEach(this.topics, dojo.unsubscribe);
+		this.targetAnchor = null;
+	},
+
+	// markup methods
+	markupFactory: function(params, node){
+		params._skipStartup = true;
+		return new dojo.dnd.Source(node, params);
+	},
+
+	// mouse event processors
+	onMouseMove: function(e){
+		// summary:
+		//		event processor for onmousemove
+		// e: Event
+		//		mouse event
+		if(this.isDragging && this.targetState == "Disabled"){ return; }
+		dojo.dnd.Source.superclass.onMouseMove.call(this, e);
+		var m = dojo.dnd.manager();
+		if(!this.isDragging){
+			if(this.mouseDown && this.isSource &&
+					(Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay)){
+				var nodes = this.getSelectedNodes();
+				if(nodes.length){
+					m.startDrag(this, nodes, this.copyState(dojo.isCopyKey(e), true));
+				}
+			}
+		}
+		if(this.isDragging){
+			// calculate before/after
+			var before = false;
+			if(this.current){
+				if(!this.targetBox || this.targetAnchor != this.current){
+					this.targetBox = dojo.position(this.current, true);
+				}
+				if(this.horizontal){
+					before = (e.pageX - this.targetBox.x) < (this.targetBox.w / 2);
+				}else{
+					before = (e.pageY - this.targetBox.y) < (this.targetBox.h / 2);
+				}
+			}
+			if(this.current != this.targetAnchor || before != this.before){
+				this._markTargetAnchor(before);
+				m.canDrop(!this.current || m.source != this || !(this.current.id in this.selection));
+			}
+		}
+	},
+	onMouseDown: function(e){
+		// summary:
+		//		event processor for onmousedown
+		// e: Event
+		//		mouse event
+		if(!this.mouseDown && this._legalMouseDown(e) && (!this.skipForm || !dojo.dnd.isFormElement(e))){
+			this.mouseDown = true;
+			this._lastX = e.pageX;
+			this._lastY = e.pageY;
+			dojo.dnd.Source.superclass.onMouseDown.call(this, e);
+		}
+	},
+	onMouseUp: function(e){
+		// summary:
+		//		event processor for onmouseup
+		// e: Event
+		//		mouse event
+		if(this.mouseDown){
+			this.mouseDown = false;
+			dojo.dnd.Source.superclass.onMouseUp.call(this, e);
+		}
+	},
+	
+	// topic event processors
+	onDndSourceOver: function(source){
+		// summary:
+		//		topic event processor for /dnd/source/over, called when detected a current source
+		// source: Object
+		//		the source which has the mouse over it
+		if(this != source){
+			this.mouseDown = false;
+			if(this.targetAnchor){
+				this._unmarkTargetAnchor();
+			}
+		}else if(this.isDragging){
+			var m = dojo.dnd.manager();
+			m.canDrop(this.targetState != "Disabled" && (!this.current || m.source != this || !(this.current.id in this.selection)));
+		}
+	},
+	onDndStart: function(source, nodes, copy){
+		// summary:
+		//		topic event processor for /dnd/start, called to initiate the DnD operation
+		// source: Object
+		//		the source which provides items
+		// nodes: Array
+		//		the list of transferred items
+		// copy: Boolean
+		//		copy items, if true, move items otherwise
+		if(this.autoSync){ this.sync(); }
+		if(this.isSource){
+			this._changeState("Source", this == source ? (copy ? "Copied" : "Moved") : "");
+		}
+		var accepted = this.accept && this.checkAcceptance(source, nodes);
+		this._changeState("Target", accepted ? "" : "Disabled");
+		if(this == source){
+			dojo.dnd.manager().overSource(this);
+		}
+		this.isDragging = true;
+	},
+	onDndDrop: function(source, nodes, copy, target){
+		// summary:
+		//		topic event processor for /dnd/drop, called to finish the DnD operation
+		// source: Object
+		//		the source which provides items
+		// nodes: Array
+		//		the list of transferred items
+		// copy: Boolean
+		//		copy items, if true, move items otherwise
+		// target: Object
+		//		the target which accepts items
+		if(this == target){
+			// this one is for us => move nodes!
+			this.onDrop(source, nodes, copy);
+		}
+		this.onDndCancel();
+	},
+	onDndCancel: function(){
+		// summary:
+		//		topic event processor for /dnd/cancel, called to cancel the DnD operation
+		if(this.targetAnchor){
+			this._unmarkTargetAnchor();
+			this.targetAnchor = null;
+		}
+		this.before = true;
+		this.isDragging = false;
+		this.mouseDown = false;
+		this._changeState("Source", "");
+		this._changeState("Target", "");
+	},
+	
+	// local events
+	onDrop: function(source, nodes, copy){
+		// summary:
+		//		called only on the current target, when drop is performed
+		// source: Object
+		//		the source which provides items
+		// nodes: Array
+		//		the list of transferred items
+		// copy: Boolean
+		//		copy items, if true, move items otherwise
+		
+		if(this != source){
+			this.onDropExternal(source, nodes, copy);
+		}else{
+			this.onDropInternal(nodes, copy);
+		}
+	},
+	onDropExternal: function(source, nodes, copy){
+		// summary:
+		//		called only on the current target, when drop is performed
+		//		from an external source
+		// source: Object
+		//		the source which provides items
+		// nodes: Array
+		//		the list of transferred items
+		// copy: Boolean
+		//		copy items, if true, move items otherwise
+		
+		var oldCreator = this._normalizedCreator;
+		// transferring nodes from the source to the target
+		if(this.creator){
+			// use defined creator
+			this._normalizedCreator = function(node, hint){
+				return oldCreator.call(this, source.getItem(node.id).data, hint);
+			};
+		}else{
+			// we have no creator defined => move/clone nodes
+			if(copy){
+				// clone nodes
+				this._normalizedCreator = function(node, hint){
+					var t = source.getItem(node.id);
+					var n = node.cloneNode(true);
+					n.id = dojo.dnd.getUniqueId();
+					return {node: n, data: t.data, type: t.type};
+				};
+			}else{
+				// move nodes
+				this._normalizedCreator = function(node, hint){
+					var t = source.getItem(node.id);
+					source.delItem(node.id);
+					return {node: node, data: t.data, type: t.type};
+				};
+			}
+		}
+		this.selectNone();
+		if(!copy && !this.creator){
+			source.selectNone();
+		}
+		this.insertNodes(true, nodes, this.before, this.current);
+		if(!copy && this.creator){
+			source.deleteSelectedNodes();
+		}
+		this._normalizedCreator = oldCreator;
+	},
+	onDropInternal: function(nodes, copy){
+		// summary:
+		//		called only on the current target, when drop is performed
+		//		from the same target/source
+		// nodes: Array
+		//		the list of transferred items
+		// copy: Boolean
+		//		copy items, if true, move items otherwise
+		
+		var oldCreator = this._normalizedCreator;
+		// transferring nodes within the single source
+		if(this.current && this.current.id in this.selection){
+			// do nothing
+			return;
+		}
+		if(copy){
+			if(this.creator){
+				// create new copies of data items
+				this._normalizedCreator = function(node, hint){
+					return oldCreator.call(this, this.getItem(node.id).data, hint);
+				};
+			}else{
+				// clone nodes
+				this._normalizedCreator = function(node, hint){
+					var t = this.getItem(node.id);
+					var n = node.cloneNode(true);
+					n.id = dojo.dnd.getUniqueId();
+					return {node: n, data: t.data, type: t.type};
+				};
+			}
+		}else{
+			// move nodes
+			if(!this.current){
+				// do nothing
+				return;
+			}
+			this._normalizedCreator = function(node, hint){
+				var t = this.getItem(node.id);
+				return {node: node, data: t.data, type: t.type};
+			};
+		}
+		this._removeSelection();
+		this.insertNodes(true, nodes, this.before, this.current);
+		this._normalizedCreator = oldCreator;
+	},
+	onDraggingOver: function(){
+		// summary:
+		//		called during the active DnD operation, when items
+		//		are dragged over this target, and it is not disabled
+	},
+	onDraggingOut: function(){
+		// summary:
+		//		called during the active DnD operation, when items
+		//		are dragged away from this target, and it is not disabled
+	},
+	
+	// utilities
+	onOverEvent: function(){
+		// summary:
+		//		this function is called once, when mouse is over our container
+		dojo.dnd.Source.superclass.onOverEvent.call(this);
+		dojo.dnd.manager().overSource(this);
+		if(this.isDragging && this.targetState != "Disabled"){
+			this.onDraggingOver();
+		}
+	},
+	onOutEvent: function(){
+		// summary:
+		//		this function is called once, when mouse is out of our container
+		dojo.dnd.Source.superclass.onOutEvent.call(this);
+		dojo.dnd.manager().outSource(this);
+		if(this.isDragging && this.targetState != "Disabled"){
+			this.onDraggingOut();
+		}
+	},
+	_markTargetAnchor: function(before){
+		// summary:
+		//		assigns a class to the current target anchor based on "before" status
+		// before: Boolean
+		//		insert before, if true, after otherwise
+		if(this.current == this.targetAnchor && this.before == before){ return; }
+		if(this.targetAnchor){
+			this._removeItemClass(this.targetAnchor, this.before ? "Before" : "After");
+		}
+		this.targetAnchor = this.current;
+		this.targetBox = null;
+		this.before = before;
+		if(this.targetAnchor){
+			this._addItemClass(this.targetAnchor, this.before ? "Before" : "After");
+		}
+	},
+	_unmarkTargetAnchor: function(){
+		// summary:
+		//		removes a class of the current target anchor based on "before" status
+		if(!this.targetAnchor){ return; }
+		this._removeItemClass(this.targetAnchor, this.before ? "Before" : "After");
+		this.targetAnchor = null;
+		this.targetBox = null;
+		this.before = true;
+	},
+	_markDndStatus: function(copy){
+		// summary:
+		//		changes source's state based on "copy" status
+		this._changeState("Source", copy ? "Copied" : "Moved");
+	},
+	_legalMouseDown: function(e){
+		// summary:
+		//		checks if user clicked on "approved" items
+		// e: Event
+		//		mouse event
+		
+		// accept only the left mouse button
+		if(!dojo.mouseButtons.isLeft(e)){ return false; }
+		
+		if(!this.withHandles){ return true; }
+		
+		// check for handles
+		for(var node = e.target; node && node !== this.node; node = node.parentNode){
+			if(dojo.hasClass(node, "dojoDndHandle")){ return true; }
+			if(dojo.hasClass(node, "dojoDndItem") || dojo.hasClass(node, "dojoDndIgnore")){ break; }
+		}
+		return false;	// Boolean
+	}
+});
+
+dojo.declare("dojo.dnd.Target", dojo.dnd.Source, {
+	// summary: a Target object, which can be used as a DnD target
+	
+	constructor: function(node, params){
+		// summary:
+		//		a constructor of the Target --- see the `dojo.dnd.Source.constructor` for details
+		this.isSource = false;
+		dojo.removeClass(this.node, "dojoDndSource");
+	},
+
+	// markup methods
+	markupFactory: function(params, node){
+		params._skipStartup = true;
+		return new dojo.dnd.Target(node, params);
+	}
+});
+
+dojo.declare("dojo.dnd.AutoSource", dojo.dnd.Source, {
+	// summary:
+	//		a source that syncs its DnD nodes by default
+	
+	constructor: function(node, params){
+		// summary:
+		//		constructor of the AutoSource --- see the Source constructor for details
+		this.autoSync = true;
+	},
+
+	// markup methods
+	markupFactory: function(params, node){
+		params._skipStartup = true;
+		return new dojo.dnd.AutoSource(node, params);
+	}
+});
diff --git a/dojo/dnd/TimedMoveable.js b/dojo/dnd/TimedMoveable.js
index b512e58..aa40370 100644
--- a/dojo/dnd/TimedMoveable.js
+++ b/dojo/dnd/TimedMoveable.js
@@ -1,40 +1,70 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.dnd.TimedMoveable"]){
-dojo._hasResource["dojo.dnd.TimedMoveable"]=true;
 dojo.provide("dojo.dnd.TimedMoveable");
+
 dojo.require("dojo.dnd.Moveable");
+
+/*=====
+dojo.declare("dojo.dnd.__TimedMoveableArgs", [dojo.dnd.__MoveableArgs], {
+	// timeout: Number
+	//		delay move by this number of ms,
+	//		accumulating position changes during the timeout
+	timeout: 0
+});
+=====*/
+
 (function(){
-var _1=dojo.dnd.Moveable.prototype.onMove;
-dojo.declare("dojo.dnd.TimedMoveable",dojo.dnd.Moveable,{timeout:40,constructor:function(_2,_3){
-if(!_3){
-_3={};
-}
-if(_3.timeout&&typeof _3.timeout=="number"&&_3.timeout>=0){
-this.timeout=_3.timeout;
-}
-},markupFactory:function(_4,_5){
-return new dojo.dnd.TimedMoveable(_5,_4);
-},onMoveStop:function(_6){
-if(_6._timer){
-clearTimeout(_6._timer);
-_1.call(this,_6,_6._leftTop);
-}
-dojo.dnd.Moveable.prototype.onMoveStop.apply(this,arguments);
-},onMove:function(_7,_8){
-_7._leftTop=_8;
-if(!_7._timer){
-var _9=this;
-_7._timer=setTimeout(function(){
-_7._timer=null;
-_1.call(_9,_7,_7._leftTop);
-},this.timeout);
-}
-}});
+	// 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 that makes a node moveable with a timer
+			// node: Node||String
+			//		a node (or node's id) to be moved
+			// params: dojo.dnd.__TimedMoveableArgs
+			//		object with additional parameters.
+			
+			// 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);
+			}
+		}
+	});
 })();
-}
diff --git a/dojo/dnd/autoscroll.js b/dojo/dnd/autoscroll.js
index a5d091f..7ddeff9 100644
--- a/dojo/dnd/autoscroll.js
+++ b/dojo/dnd/autoscroll.js
@@ -1,99 +1,105 @@
-/*
-	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
-*/
+dojo.provide("dojo.dnd.autoscroll");
 
+dojo.dnd.getViewport = function(){
+	// summary:
+	//		Returns a viewport size (visible part of the window)
 
-if(!dojo._hasResource["dojo.dnd.autoscroll"]){
-dojo._hasResource["dojo.dnd.autoscroll"]=true;
-dojo.provide("dojo.dnd.autoscroll");
-dojo.dnd.getViewport=function(){
-var d=dojo.doc,dd=d.documentElement,w=window,b=dojo.body();
-if(dojo.isMozilla){
-return {w:dd.clientWidth,h:w.innerHeight};
-}else{
-if(!dojo.isOpera&&w.innerWidth){
-return {w:w.innerWidth,h:w.innerHeight};
-}else{
-if(!dojo.isOpera&&dd&&dd.clientWidth){
-return {w:dd.clientWidth,h:dd.clientHeight};
-}else{
-if(b.clientWidth){
-return {w:b.clientWidth,h:b.clientHeight};
-}
-}
-}
-}
-return null;
+	// TODO: remove this when getViewport() moved to dojo core, see #7028
+
+	// 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){
-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.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){
-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.position(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){
-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 _1=n.scrollLeft,_2=n.scrollTop;
-n.scrollLeft=n.scrollLeft+dx;
-n.scrollTop=n.scrollTop+dy;
-if(_1!=n.scrollLeft||_2!=n.scrollTop){
-return;
-}
-}
-}
-try{
-n=n.parentNode;
-}
-catch(x){
-n=null;
-}
-}
-dojo.dnd.autoScroll(e);
+
+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.position(n, true);
+				//console.log(b.l, b.t, t.x, t.y, n.scrollLeft, n.scrollTop);
+				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.position()
+					// 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;
+					}
+				}
+				//console.log("ry =", ry, "b.h =", b.h, "h =", h);
+				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);
 };
-}
diff --git a/dojo/dnd/common.js b/dojo/dnd/common.js
index 6b73bd1..88878ce 100644
--- a/dojo/dnd/common.js
+++ b/dojo/dnd/common.js
@@ -1,28 +1,26 @@
-/*
-	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
-*/
+dojo.provide("dojo.dnd.common");
 
+dojo.dnd.getCopyKeyState = dojo.isCopyKey;
 
-if(!dojo._hasResource["dojo.dnd.common"]){
-dojo._hasResource["dojo.dnd.common"]=true;
-dojo.provide("dojo.dnd.common");
-dojo.dnd.getCopyKeyState=dojo.isCopyKeyPressed;
-dojo.dnd._uniqueId=0;
-dojo.dnd.getUniqueId=function(){
-var id;
-do{
-id=dojo._scopeName+"Unique"+(++dojo.dnd._uniqueId);
-}while(dojo.byId(id));
-return id;
+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(e){
-var t=e.target;
-if(t.nodeType==3){
-t=t.parentNode;
-}
-return " button textarea input select option ".indexOf(" "+t.tagName.toLowerCase()+" ")>=0;
+
+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
 };
-}
diff --git a/dojo/dnd/move.js b/dojo/dnd/move.js
index 4556c14..fdf4dc0 100644
--- a/dojo/dnd/move.js
+++ b/dojo/dnd/move.js
@@ -1,125 +1,243 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.dnd.move"]){
-dojo._hasResource["dojo.dnd.move"]=true;
 dojo.provide("dojo.dnd.move");
+
 dojo.require("dojo.dnd.Mover");
 dojo.require("dojo.dnd.Moveable");
-dojo.declare("dojo.dnd.move.constrainedMoveable",dojo.dnd.Moveable,{constraints:function(){
-},within:false,markupFactory:function(_1,_2){
-return new dojo.dnd.move.constrainedMoveable(_2,_1);
-},constructor:function(_3,_4){
-if(!_4){
-_4={};
-}
-this.constraints=_4.constraints;
-this.within=_4.within;
-},onFirstMove:function(_5){
-var c=this.constraintBox=this.constraints.call(this,_5);
-c.r=c.l+c.w;
-c.b=c.t+c.h;
-if(this.within){
-var mb=dojo.marginBox(_5.node);
-c.r-=mb.w;
-c.b-=mb.h;
-}
-},onMove:function(_6,_7){
-var c=this.constraintBox,s=_6.node.style;
-s.left=(_7.l<c.l?c.l:c.r<_7.l?c.r:_7.l)+"px";
-s.top=(_7.t<c.t?c.t:c.b<_7.t?c.b:_7.t)+"px";
-}});
-dojo.declare("dojo.dnd.move.boxConstrainedMoveable",dojo.dnd.move.constrainedMoveable,{box:{},markupFactory:function(_8,_9){
-return new dojo.dnd.move.boxConstrainedMoveable(_9,_8);
-},constructor:function(_a,_b){
-var _c=_b&&_b.box;
-this.constraints=function(){
-return _c;
-};
-}});
-dojo.declare("dojo.dnd.move.parentConstrainedMoveable",dojo.dnd.move.constrainedMoveable,{area:"content",markupFactory:function(_d,_e){
-return new dojo.dnd.move.parentConstrainedMoveable(_e,_d);
-},constructor:function(_f,_10){
-var _11=_10&&_10.area;
-this.constraints=function(){
-var n=this.node.parentNode,s=dojo.getComputedStyle(n),mb=dojo._getMarginBox(n,s);
-if(_11=="margin"){
-return mb;
-}
-var t=dojo._getMarginExtents(n,s);
-mb.l+=t.l,mb.t+=t.t,mb.w-=t.w,mb.h-=t.h;
-if(_11=="border"){
-return mb;
-}
-t=dojo._getBorderExtents(n,s);
-mb.l+=t.l,mb.t+=t.t,mb.w-=t.w,mb.h-=t.h;
-if(_11=="padding"){
-return mb;
-}
-t=dojo._getPadExtents(n,s);
-mb.l+=t.l,mb.t+=t.t,mb.w-=t.w,mb.h-=t.h;
-return mb;
-};
-}});
-dojo.dnd.move.constrainedMover=function(fun,_12){
-dojo.deprecated("dojo.dnd.move.constrainedMover, use dojo.dnd.move.constrainedMoveable instead");
-var _13=function(_14,e,_15){
-dojo.dnd.Mover.call(this,_14,e,_15);
-};
-dojo.extend(_13,dojo.dnd.Mover.prototype);
-dojo.extend(_13,{onMouseMove:function(e){
-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(){
-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(_12){
-var mb=dojo.marginBox(this.node);
-c.r-=mb.w;
-c.b-=mb.h;
-}
-}});
-return _13;
-};
-dojo.dnd.move.boxConstrainedMover=function(box,_16){
-dojo.deprecated("dojo.dnd.move.boxConstrainedMover, use dojo.dnd.move.boxConstrainedMoveable instead");
-return dojo.dnd.move.constrainedMover(function(){
-return box;
-},_16);
+
+/*=====
+dojo.declare("dojo.dnd.move.__constrainedMoveableArgs", [dojo.dnd.__MoveableArgs], {
+	// constraints: Function
+	//		Calculates a constraint box.
+	//		It is called in a context of the moveable object.
+	constraints: function(){},
+
+	// within: Boolean
+	//		restrict move within boundaries.
+	within: false
+});
+=====*/
+
+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 that makes a node moveable
+		// node: Node
+		//		a node (or node's id) to be moved
+		// params: dojo.dnd.move.__constrainedMoveableArgs?
+		//		an optional object with additional parameters;
+		//		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.__boxConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
+	// box: Object
+	//		a constraint box
+	box: {}
+});
+=====*/
+
+dojo.declare("dojo.dnd.move.boxConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
+	// box:
+	//		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: dojo.dnd.move.__boxConstrainedMoveableArgs?
+		//		an optional object with parameters
+		var box = params && params.box;
+		this.constraints = function(){ return box; };
+	}
+});
+
+/*=====
+dojo.declare("dojo.dnd.move.__parentConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
+	// area: String
+	//		A parent's area to restrict the move.
+	//		Can be "margin", "border", "padding", or "content".
+	area: ""
+});
+=====*/
+
+dojo.declare("dojo.dnd.move.parentConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
+	// area:
+	//		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: dojo.dnd.move.__parentConstrainedMoveableArgs?
+		//		an optional object with parameters
+		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.parentConstrainedMover=function(_17,_18){
-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(_17=="margin"){
-return mb;
-}
-var t=dojo._getMarginExtents(n,s);
-mb.l+=t.l,mb.t+=t.t,mb.w-=t.w,mb.h-=t.h;
-if(_17=="border"){
-return mb;
-}
-t=dojo._getBorderExtents(n,s);
-mb.l+=t.l,mb.t+=t.t,mb.w-=t.w,mb.h-=t.h;
-if(_17=="padding"){
-return mb;
-}
-t=dojo._getPadExtents(n,s);
-mb.l+=t.l,mb.t+=t.t,mb.w-=t.w,mb.h-=t.h;
-return mb;
+
+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
 };
-return dojo.dnd.move.constrainedMover(fun,_18);
+
+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 within 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
 };
-dojo.dnd.constrainedMover=dojo.dnd.move.constrainedMover;
-dojo.dnd.boxConstrainedMover=dojo.dnd.move.boxConstrainedMover;
-dojo.dnd.parentConstrainedMover=dojo.dnd.move.parentConstrainedMover;
-}
+
+// 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;
diff --git a/dojo/dojo.js b/dojo/dojo.js
index 1c39acd..cbef3ab 100644
--- a/dojo/dojo.js
+++ b/dojo/dojo.js
@@ -1,16 +1,206 @@
-/*
-	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
-*/
+// summary:
+//		This is the "source loader" for Dojo. This dojo.js ensures that all
+//		Base APIs are available once its execution is complete and attempts to
+//		automatically determine the correct host environment to use.
+// description:
+//		"dojo.js" is the basic entry point into the toolkit for all uses and
+//		users. The "source loader" is replaced by environment-specific builds
+//		and so you should not assume that built versions of the toolkit will
+//		function in all supported platforms (Browsers, Rhino, Spidermonkey,
+//		etc.). In most cases, users will receive pre-built dojo.js files which
+//		contain all of the Base APIs in a single file and which specialize for
+//		the Browser platform. After loading dojo.js, you will be able to do the
+//		following with the toolkit:
+//			All platforms:
+//				- load other packages (dojo core, dijit, dojox, and custom
+//				  modules) to better structure your code and take advantage of
+//				  the inventive capabilities developed by the broad Dojo
+//				  community
+//				- perform basic network I/O
+//				- use Dojo's powerful language supplementing APIs
+//				- take advantage of the Dojo event system to better structure
+//				  your application
+//			Browser only:
+//				- use Dojo's powerful and blisteringly-fast CSS query engine to
+//				  upgrade and active your web pages without embedding
+//				  JavaScript in your markup
+//				- get and set accurate information about element style 
+//				- shorten the time it takes to build and manipulate DOM
+//				  structures with Dojo's HTML handling APIs
+//				- create more fluid UI transitions with Dojo's robust and
+//				  battle-tested animation facilities
 
-/*
-	This is a compiled version of Dojo, built for deployment and not for
-	development. To get an editable version, please visit:
+// NOTE:
+//		If you are reading this file, you have received a "source" build of
+//		Dojo. Unless you are a Dojo developer, it is very unlikely that this is
+//		what you want. While functionally identical to builds, source versions
+//		of Dojo load more slowly than pre-processed builds.
+//
+//		We strongly recommend that your applications always use a build of
+//		Dojo. To download such a build or find out how you can create
+//		customized, high-performance packages of Dojo suitable for use with
+//		your application, please visit:
+//
+//			http://dojotoolkit.org
+//
+//		Regards,
+//		The Dojo Team
 
-		http://dojotoolkit.org
+if(typeof dojo == "undefined"){
+	// only try to load Dojo if we don't already have one. Dojo always follows
+	// a "first Dojo wins" policy.
+	(function(){
+		var getRootNode = function(){
+			// attempt to figure out the path to dojo if it isn't set in the config
+			if(this["document"] && this["document"]["getElementsByTagName"]){
+				var scripts = document.getElementsByTagName("script");
+				var rePkg = /dojo\.js(\W|$)/i;
+				for(var i = 0; i < scripts.length; i++){
+					var src = scripts[i].getAttribute("src");
+					if(!src){ continue; }
+					var m = src.match(rePkg);
+					if(m){
+						return { 
+							node: scripts[i], 
+							root: src.substring(0, m.index)
+						};
+						/*
+						root = src.substring(0, m.index);
+						if(!this["djConfig"]){ djConfig = {}; }
+						djConfig["baseUrl"] = root;
+						break;
+						*/
+					}
+				}
+			}
+		}
 
-	for documentation and information on getting the source.
-*/
+		// we default to a browser environment if we can't figure it out
+		var hostEnv = "browser";
+		if(typeof djConfig !== "undefined" && djConfig.hostEnv){
+			hostEnv = djConfig.hostEnv;
+		}else if(
+			typeof this["load"] == "function" &&
+			(
+				typeof this["Packages"] == "function" ||
+				typeof this["Packages"] == "object"
+			)
+		){
+			// Rhino environments make Java code available via the Packages
+			// object. Obviously, this check could be "juiced" if someone
+			// creates a "Packages" object and a "load" function, but we've
+			// never seen this happen in the wild yet.
+			hostEnv = "rhino";
+		}else if(typeof this["load"] == "function"){
+			// Spidermonkey has a very spartan environment. The only thing we
+			// can count on from it is a "load" function.
+			hostEnv = "spidermonkey";
+		}
+		var tmps = ["bootstrap.js", "loader.js", "hostenv_"+hostEnv+".js"];
+		if (this.Jaxer && this.Jaxer.isOnServer) {
+			this.load = Jaxer.load;
+		}
+	
+		if(
+			this["djConfig"]&&
+			(
+				djConfig["forceXDomain"] ||
+				djConfig["useXDomain"]
+			)
+		){
+			tmps.push("loader_xd.js");
+		}
+	
+		if(this["djConfig"] && djConfig["baseUrl"]){
+			// if the user explicitly tells us where Dojo has been loaded from
+			// (or should be loaded from) via djConfig, skip the auto-detection
+			// routines.
+			var root = djConfig["baseUrl"];
+		}else{
+			var root = "./";
+			if(hostEnv === "spidermonkey"){
+				// auto-detect the base path via an exception. Hack!
+				try{
+					throw new Error(""); 
+				}catch(e){ 
+					root = String(e.fileName || e.sourceURL).split("dojo.js")[0];
+				}
+			}
+			if(!this["djConfig"]){
+				djConfig = { baseUrl: root };
+			}
+	
+			// attempt to figure out the path to dojo if it isn't set in the config
+			if(this["document"] && this["document"]["getElementsByTagName"]){
+				var root = getRootNode().root;	
+				if(!this["djConfig"]){ djConfig = {}; }
+				djConfig["baseUrl"] = root;
+			}
+		}
+		// FIXME: should we be adding the lang stuff here so we can count on it
+		// before the bootstrap stuff?
+		for(var x=0; x < tmps.length; x++){
+			tmps[x] = root+"_base/_loader/"+tmps[x];
+		}
+		// the "_base.js" file ensures that the rest of Dojo Base is available.
+		// It counts on the package system functioning in order to work, so add
+		// it last
+		tmps.push(root+"_base.js");
 
-(function(){var _1=null;if((_1||(typeof djConfig!="undefined"&&djConfig.scopeMap))&&(typeof window!="undefined")){var _2="",_3="",_4="",_5={},_6={};_1=_1||djConfig.scopeMap;for(var i=0;i<_1.length;i++){var _7=_1[i];_2+="var "+_7[0]+" = {}; "+_7[1]+" = "+_7[0]+";"+_7[1]+"._scopeName = '"+_7[1]+"';";_3+=(i==0?"":",")+_7[0];_4+=(i==0?"":",")+_7[1];_5[_7[0]]=_7[1];_6[_7[1]]=_7[0];}eval(_2+"dojo._scopeArgs = ["+_4+"];");dojo._scopePrefixArgs=_3;dojo._scopePrefix="(function("+_3+"){";dojo._sco [...]
+		var lastRoot;
+		var isOpera = 0;
+		var isWebKit = 0;
+
+		if(hostEnv == "browser"){
+			try{
+				lastRoot = getRootNode().node;
+				var ua = navigator.userAgent;
+				isOpera = (ua.indexOf("Opera") >= 0);
+				isWebKit = (ua.indexOf("WebKit") >= 0);
+			}catch(e){ /* squelch */ }
+		}
+
+		// Opera and Safari don't handle injected script tags in the right
+		// order, so we resort to XHR to make things work there when we find
+		// ourselves in a strict XHTML environment (e.g., document.write bombs
+		// out)
+		var injectXHRCode = function(src){
+			var xhr = new XMLHttpRequest();
+			xhr.open("GET", src, false);
+			xhr.send();
+			eval(xhr.responseText);
+		}
+	
+		var injectScriptNode = function(src){
+			if(isWebKit){ return injectXHRCode(src); }
+			var head = document.getElementsByTagName("head")[0];
+			var script = document.createElement("script");
+			script.setAttribute("type", "text/javascript");
+			if(head.lastChild === lastRoot){
+				head.appendChild(script);
+			}else{
+				lastRoot.parentNode.insertBefore(script, lastRoot.nextSibling);
+			}
+			script.src = src;
+			lastRoot = script;
+		}
+		for(var x=0; x < tmps.length; x++){
+			if(hostEnv === "rhino" || hostEnv === "spidermonkey" || (this.Jaxer && this.Jaxer.isOnServer)){
+				load(tmps[x]);
+			}else if(hostEnv === "ff_ext"){
+				var l = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
+					.getService(Components.interfaces.mozIJSSubScriptLoader);
+				l.loadSubScript(tmps[x], this)
+			}else if(isOpera){ // opera fails silently!!
+				injectXHRCode(tmps[x]);
+			}else{
+				try{
+					document.write("<scr"+"ipt type='text/javascript' src='"+tmps[x]+"'></scr"+"ipt>");
+				}catch(e){
+					// strict XHTML mode, no document.write
+					injectScriptNode(tmps[x]);
+				}
+			}
+		}
+	})();
+};
diff --git a/dojo/dojo.js.uncompressed.js b/dojo/dojo.js.uncompressed.js
deleted file mode 100644
index 13a7667..0000000
--- a/dojo/dojo.js.uncompressed.js
+++ /dev/null
@@ -1,11239 +0,0 @@
-/*
-	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.
-*/
-
-;(function(){
-
-	/*
-	dojo, dijit, and dojox must always be the first three, and in that order.
-	djConfig.scopeMap = [
-		["dojo", "fojo"],
-		["dijit", "fijit"],
-		["dojox", "fojox"]
-	
-	]
-	*/
-
-	/**Build will replace this comment with a scoped djConfig **/
-
-	//The null below can be relaced by a build-time value used instead of djConfig.scopeMap.
-	var sMap = null;
-
-	//See if new scopes need to be defined.
-	if((sMap || (typeof djConfig != "undefined" && djConfig.scopeMap)) && (typeof window != "undefined")){
-		var scopeDef = "", scopePrefix = "", scopeSuffix = "", scopeMap = {}, scopeMapRev = {};
-		sMap = sMap || djConfig.scopeMap;
-		for(var i = 0; i < sMap.length; i++){
-			//Make local variables, then global variables that use the locals.
-			var newScope = sMap[i];
-			scopeDef += "var " + newScope[0] + " = {}; " + newScope[1] + " = " + newScope[0] + ";" + newScope[1] + "._scopeName = '" + newScope[1] + "';";
-			scopePrefix += (i == 0 ? "" : ",") + newScope[0];
-			scopeSuffix += (i == 0 ? "" : ",") + newScope[1];
-			scopeMap[newScope[0]] = newScope[1];
-			scopeMapRev[newScope[1]] = newScope[0];
-		}
-
-		eval(scopeDef + "dojo._scopeArgs = [" + scopeSuffix + "];");
-
-		dojo._scopePrefixArgs = scopePrefix;
-		dojo._scopePrefix = "(function(" + scopePrefix + "){";
-		dojo._scopeSuffix = "})(" + scopeSuffix + ")";
-		dojo._scopeMap = scopeMap;
-		dojo._scopeMapRev = scopeMapRev;
-	}
-
-/*=====
-// note:
-//		'djConfig' does not exist under 'dojo.*' so that it can be set before the
-//		'dojo' variable exists.
-// note:
-//		Setting any of these variables *after* the library has loaded does
-//		nothing at all.
-
-djConfig = {
-	// summary:
-	//		Application code can set the global 'djConfig' prior to loading
-	//		the library to override certain global settings for how dojo works.
-	//
-	// isDebug: Boolean
-	//		Defaults to `false`. If set to `true`, ensures that Dojo provides
-	//		extended debugging feedback via Firebug. If Firebug is not available
-	//		on your platform, setting `isDebug` to `true` will force Dojo to
-	//		pull in (and display) the version of Firebug Lite which is
-	//		integrated into the Dojo distribution, thereby always providing a
-	//		debugging/logging console when `isDebug` is enabled. Note that
-	//		Firebug's `console.*` methods are ALWAYS defined by Dojo. If
-	//		`isDebug` is false and you are on a platform without Firebug, these
-	//		methods will be defined as no-ops.
-	isDebug: false,
-	// debugAtAllCosts: Boolean
-	//		Defaults to `false`. If set to `true`, this triggers an alternate
-	//		mode of the package system in which dependencies are detected and
-	//		only then are resources evaluated in dependency order via
-	//		`<script>` tag inclusion. This may double-request resources and
-	//		cause problems with scripts which expect `dojo.require()` to
-	//		preform synchronously. `debugAtAllCosts` can be an invaluable
-	//		debugging aid, but when using it, ensure that all code which
-	//		depends on Dojo modules is wrapped in `dojo.addOnLoad()` handlers.
-	//		Due to the somewhat unpredictable side-effects of using
-	//		`debugAtAllCosts`, it is strongly recommended that you enable this
-	//		flag as a last resort. `debugAtAllCosts` has no effect when loading
-	//		resources across domains. For usage information, see the
-	//		[Dojo Book](http://dojotoolkit.org/book/book-dojo/part-4-meta-dojo-making-your-dojo-code-run-faster-and-better/debugging-facilities/deb)
-	debugAtAllCosts: false,
-	// locale: String
-	//		The locale to assume for loading localized resources in this page,
-	//		specified according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt).
-	//		Must be specified entirely in lowercase, e.g. `en-us` and `zh-cn`.
-	//		See the documentation for `dojo.i18n` and `dojo.requireLocalization`
-	//		for details on loading localized resources. If no locale is specified,
-	//		Dojo assumes the locale of the user agent, according to `navigator.userLanguage`
-	//		or `navigator.language` properties.
-	locale: undefined,
-	// extraLocale: Array
-	//		No default value. Specifies additional locales whose
-	//		resources should also be loaded alongside the default locale when
-	//		calls to `dojo.requireLocalization()` are processed.
-	extraLocale: undefined,
-	// baseUrl: String
-	//		The directory in which `dojo.js` is located. Under normal
-	//		conditions, Dojo auto-detects the correct location from which it
-	//		was loaded. You may need to manually configure `baseUrl` in cases
-	//		where you have renamed `dojo.js` or in which `<base>` tags confuse
-	//		some browsers (e.g. IE 6). The variable `dojo.baseUrl` is assigned
-	//		either the value of `djConfig.baseUrl` if one is provided or the
-	//		auto-detected root if not. Other modules are located relative to
-	//		this path. The path should end in a slash.
-	baseUrl: undefined,
-	// modulePaths: Object
-	//		A map of module names to paths relative to `dojo.baseUrl`. The
-	//		key/value pairs correspond directly to the arguments which
-	//		`dojo.registerModulePath` accepts. Specifiying
-	//		`djConfig.modulePaths = { "foo": "../../bar" }` is the equivalent
-	//		of calling `dojo.registerModulePath("foo", "../../bar");`. Multiple
-	//		modules may be configured via `djConfig.modulePaths`.
-	modulePaths: {},
-	// afterOnLoad: Boolean 
-	//		Indicates Dojo was added to the page after the page load. In this case
-	//		Dojo will not wait for the page DOMContentLoad/load events and fire
-	//		its dojo.addOnLoad callbacks after making sure all outstanding
-	//		dojo.required modules have loaded. Only works with a built dojo.js,
-	//		it does not work the dojo.js directly from source control.
-	afterOnLoad: false,
-	// addOnLoad: Function or Array
-	//		Adds a callback via dojo.addOnLoad. Useful when Dojo is added after
-	//		the page loads and djConfig.afterOnLoad is true. Supports the same
-	//		arguments as dojo.addOnLoad. When using a function reference, use
-	//		`djConfig.addOnLoad = function(){};`. For object with function name use
-	//		`djConfig.addOnLoad = [myObject, "functionName"];` and for object with
-	//		function reference use
-	//		`djConfig.addOnLoad = [myObject, function(){}];`
-	addOnLoad: null,
-	// require: Array
-	//		An array of module names to be loaded immediately after dojo.js has been included
-	//		in a page.
-	require: [],
-	// defaultDuration: Array
-	//		Default duration, in milliseconds, for wipe and fade animations within dijits.
-	//		Assigned to dijit.defaultDuration.
-	defaultDuration: 200,
-	// dojoBlankHtmlUrl: String
-	//		Used by some modules to configure an empty iframe. Used by dojo.io.iframe and
-	//		dojo.back, and dijit popup support in IE where an iframe is needed to make sure native
-	//		controls do not bleed through the popups. Normally this configuration variable 
-	//		does not need to be set, except when using cross-domain/CDN Dojo builds.
-	//		Save dojo/resources/blank.html to your domain and set `djConfig.dojoBlankHtmlUrl`
-	//		to the path on your domain your copy of blank.html.
-	dojoBlankHtmlUrl: undefined,
-	//	ioPublish: Boolean?
-	//		Set this to true to enable publishing of topics for the different phases of
-	// 		IO operations. Publishing is done via dojo.publish. See dojo.__IoPublish for a list
-	// 		of topics that are published.
-	ioPublish: false,
-	//  useCustomLogger: Anything?
-	//		If set to a value that evaluates to true such as a string or array and
-	//		isDebug is true and Firebug is not available or running, then it bypasses
-	//		the creation of Firebug Lite allowing you to define your own console object.
-	useCustomLogger: undefined,
-	// transparentColor: Array
-	//		Array containing the r, g, b components used as transparent color in dojo.Color;
-	//		if undefined, [255,255,255] (white) will be used.
-	transparentColor: undefined,
-	// skipIeDomLoaded: Boolean
-	//		For IE only, skip the DOMContentLoaded hack used. Sometimes it can cause an Operation
-	//		Aborted error if the rest of the page triggers script defers before the DOM is ready.
-	//		If this is config value is set to true, then dojo.addOnLoad callbacks will not be
-	//		triggered until the page load event, which is after images and iframes load. If you
-	//		want to trigger the callbacks sooner, you can put a script block in the bottom of
-	//		your HTML that calls dojo._loadInit();. If you are using multiversion support, change
-	//		"dojo." to the appropriate scope name for dojo.
-	skipIeDomLoaded: false
-}
-=====*/
-
-(function(){
-	// firebug stubs
-
-	if(typeof this["loadFirebugConsole"] == "function"){
-		// for Firebug 1.2
-		this["loadFirebugConsole"]();
-	}else{
-		this.console = this.console || {};
-
-		//	Be careful to leave 'log' always at the end
-		var cn = [
-			"assert", "count", "debug", "dir", "dirxml", "error", "group",
-			"groupEnd", "info", "profile", "profileEnd", "time", "timeEnd",
-			"trace", "warn", "log"
-		];
-		var i=0, tn;
-		while((tn=cn[i++])){
-			if(!console[tn]){
-				(function(){
-					var tcn = tn+"";
-					console[tcn] = ('log' in console) ? function(){
-						var a = Array.apply({}, arguments);
-						a.unshift(tcn+":");
-						console["log"](a.join(" "));
-					} : function(){}
-					console[tcn]._fake = true;
-				})();
-			}
-		}
-	}
-
-	//TODOC:  HOW TO DOC THIS?
-	// dojo is the root variable of (almost all) our public symbols -- make sure it is defined.
-	if(typeof dojo == "undefined"){
-		dojo = {
-			_scopeName: "dojo",
-			_scopePrefix: "",
-			_scopePrefixArgs: "",
-			_scopeSuffix: "",
-			_scopeMap: {},
-			_scopeMapRev: {}
-		};
-	}
-
-	var d = dojo;
-
-	//Need placeholders for dijit and dojox for scoping code.
-	if(typeof dijit == "undefined"){
-		dijit = {_scopeName: "dijit"};
-	}
-	if(typeof dojox == "undefined"){
-		dojox = {_scopeName: "dojox"};
-	}
-
-	if(!d._scopeArgs){
-		d._scopeArgs = [dojo, dijit, dojox];
-	}
-
-/*=====
-dojo.global = {
-	//	summary:
-	//		Alias for the global scope
-	//		(e.g. the window object in a browser).
-	//	description:
-	//		Refer to 'dojo.global' rather than referring to window to ensure your
-	//		code runs correctly in contexts other than web browsers (e.g. Rhino on a server).
-}
-=====*/
-	d.global = this;
-
-	d.config =/*===== djConfig = =====*/{
-		isDebug: false,
-		debugAtAllCosts: false
-	};
-
-	if(typeof djConfig != "undefined"){
-		for(var opt in djConfig){
-			d.config[opt] = djConfig[opt];
-		}
-	}
-
-/*=====
-	// Override locale setting, if specified
-	dojo.locale = {
-		// summary: the locale as defined by Dojo (read-only)
-	};
-=====*/
-	dojo.locale = d.config.locale;
-
-	var rev = "$Rev: 21629 $".match(/\d+/);
-
-/*=====
-	dojo.version = function(){
-		// summary:
-		//		Version number of the Dojo Toolkit
-		// major: Integer
-		//		Major version. If total version is "1.2.0beta1", will be 1
-		// minor: Integer
-		//		Minor version. If total version is "1.2.0beta1", will be 2
-		// patch: Integer
-		//		Patch version. If total version is "1.2.0beta1", will be 0
-		// flag: String
-		//		Descriptor flag. If total version is "1.2.0beta1", will be "beta1"
-		// revision: Number
-		//		The SVN rev from which dojo was pulled
-		this.major = 0;
-		this.minor = 0;
-		this.patch = 0;
-		this.flag = "";
-		this.revision = 0;
-	}
-=====*/
-	dojo.version = {
-		major: 1, minor: 4, patch: 3, flag: "",
-		revision: rev ? +rev[0] : NaN,
-		toString: function(){
-			with(d.version){
-				return major + "." + minor + "." + patch + flag + " (" + revision + ")";	// String
-			}
-		}
-	}
-
-		// Register with the OpenAjax hub
-	if(typeof OpenAjax != "undefined"){
-		OpenAjax.hub.registerLibrary(dojo._scopeName, "http://dojotoolkit.org", d.version.toString());
-	}
-	
-	var extraNames, extraLen, empty = {};
-	for(var i in {toString: 1}){ extraNames = []; break; }
-	dojo._extraNames = extraNames = extraNames || ["hasOwnProperty", "valueOf", "isPrototypeOf",
-		"propertyIsEnumerable", "toLocaleString", "toString", "constructor"];
-	extraLen = extraNames.length;
-
-	dojo._mixin = function(/*Object*/ target, /*Object*/ source){
-		// summary:
-		//		Adds all properties and methods of source to target. This addition
-		//		is "prototype extension safe", so that instances of objects
-		//		will not pass along prototype defaults.
-		var name, s, i;
-		for(name in source){
-			// the "tobj" condition avoid copying properties in "source"
-			// inherited from Object.prototype.  For example, if target has a custom
-			// toString() method, don't overwrite it with the toString() method
-			// that source inherited from Object.prototype
-			s = source[name];
-			if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
-				target[name] = s;
-			}
-		}
-				// IE doesn't recognize some custom functions in for..in
-		if(extraLen && source){
-			for(i = 0; i < extraLen; ++i){
-				name = extraNames[i];
-				s = source[name];
-				if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
-					target[name] = s;
-				}
-			}
-		}
-				return target; // Object
-	}
-
-	dojo.mixin = function(/*Object*/obj, /*Object...*/props){
-		// summary:
-		//		Adds all properties and methods of props to obj and returns the
-		//		(now modified) obj.
-		//	description:
-		//		`dojo.mixin` can mix multiple source objects into a
-		//		destination object which is then returned. Unlike regular
-		//		`for...in` iteration, `dojo.mixin` is also smart about avoiding
-		//		extensions which other toolkits may unwisely add to the root
-		//		object prototype
-		//	obj:
-		//		The object to mix properties into. Also the return value.
-		//	props:
-		//		One or more objects whose values are successively copied into
-		//		obj. If more than one of these objects contain the same value,
-		//		the one specified last in the function call will "win".
-		//	example:
-		//		make a shallow copy of an object
-		//	|	var copy = dojo.mixin({}, source);
-		//	example:
-		//		many class constructors often take an object which specifies
-		//		values to be configured on the object. In this case, it is
-		//		often simplest to call `dojo.mixin` on the `this` object:
-		//	|	dojo.declare("acme.Base", null, {
-		//	|		constructor: function(properties){
-		//	|			// property configuration:
-		//	|			dojo.mixin(this, properties);
-		//	|	
-		//	|			console.log(this.quip);
-		//	|			//  ...
-		//	|		},
-		//	|		quip: "I wasn't born yesterday, you know - I've seen movies.",
-		//	|		// ...
-		//	|	});
-		//	|
-		//	|	// create an instance of the class and configure it
-		//	|	var b = new acme.Base({quip: "That's what it does!" });
-		//	example:
-		//		copy in properties from multiple objects
-		//	|	var flattened = dojo.mixin(
-		//	|		{
-		//	|			name: "Frylock",
-		//	|			braces: true
-		//	|		},
-		//	|		{
-		//	|			name: "Carl Brutanananadilewski"
-		//	|		}
-		//	|	);
-		//	|	
-		//	|	// will print "Carl Brutanananadilewski"
-		//	|	console.log(flattened.name);
-		//	|	// will print "true"
-		//	|	console.log(flattened.braces);
-		if(!obj){ obj = {}; }
-		for(var i=1, l=arguments.length; i<l; i++){
-			d._mixin(obj, arguments[i]);
-		}
-		return obj; // Object
-	}
-
-	dojo._getProp = function(/*Array*/parts, /*Boolean*/create, /*Object*/context){
-		var obj=context || d.global;
-		for(var i=0, p; obj && (p=parts[i]); i++){
-			if(i == 0 && d._scopeMap[p]){
-				p = d._scopeMap[p];
-			}
-			obj = (p in obj ? obj[p] : (create ? obj[p]={} : undefined));
-		}
-		return obj; // mixed
-	}
-
-	dojo.setObject = function(/*String*/name, /*Object*/value, /*Object?*/context){
-		// summary:
-		//		Set a property from a dot-separated string, such as "A.B.C"
-		//	description:
-		//		Useful for longer api chains where you have to test each object in
-		//		the chain, or when you have an object reference in string format.
-		//		Objects are created as needed along `path`. Returns the passed
-		//		value if setting is successful or `undefined` if not.
-		//	name:
-		//		Path to a property, in the form "A.B.C".
-		//	context:
-		//		Optional. Object to use as root of path. Defaults to
-		//		`dojo.global`.
-		//	example:
-		//		set the value of `foo.bar.baz`, regardless of whether
-		//		intermediate objects already exist:
-		//	|	dojo.setObject("foo.bar.baz", value);
-		//	example:
-		//		without `dojo.setObject`, we often see code like this:
-		//	|	// ensure that intermediate objects are available
-		//	|	if(!obj["parent"]){ obj.parent = {}; }
-		//	|	if(!obj.parent["child"]){ obj.parent.child= {}; }
-		//	|	// now we can safely set the property
-		//	|	obj.parent.child.prop = "some value";
-		//		wheras with `dojo.setObject`, we can shorten that to:
-		//	|	dojo.setObject("parent.child.prop", "some value", obj);
-		var parts=name.split("."), p=parts.pop(), obj=d._getProp(parts, true, context);
-		return obj && p ? (obj[p]=value) : undefined; // Object
-	}
-
-	dojo.getObject = function(/*String*/name, /*Boolean?*/create, /*Object?*/context){
-		// summary:
-		//		Get a property from a dot-separated string, such as "A.B.C"
-		//	description:
-		//		Useful for longer api chains where you have to test each object in
-		//		the chain, or when you have an object reference in string format.
-		//	name:
-		//		Path to an property, in the form "A.B.C".
-		//	create:
-		//		Optional. Defaults to `false`. If `true`, Objects will be
-		//		created at any point along the 'path' that is undefined.
-		//	context:
-		//		Optional. Object to use as root of path. Defaults to
-		//		'dojo.global'. Null may be passed.
-		return d._getProp(name.split("."), create, context); // Object
-	}
-
-	dojo.exists = function(/*String*/name, /*Object?*/obj){
-		//	summary:
-		//		determine if an object supports a given method
-		//	description:
-		//		useful for longer api chains where you have to test each object in
-		//		the chain. Useful only for object and method detection.
-		//		Not useful for testing generic properties on an object.
-		//		In particular, dojo.exists("foo.bar") when foo.bar = ""
-		//		will return false. Use ("bar" in foo) to test for those cases.
-		//	name:
-		//		Path to an object, in the form "A.B.C".
-		//	obj:
-		//		Object to use as root of path. Defaults to
-		//		'dojo.global'. Null may be passed.
-		//	example:
-		//	|	// define an object
-		//	|	var foo = {
-		//	|		bar: { }
-		//	|	};
-		//	|
-		//	|	// search the global scope
-		//	|	dojo.exists("foo.bar"); // true
-		//	|	dojo.exists("foo.bar.baz"); // false
-		//	|
-		//	|	// search from a particular scope
-		//	|	dojo.exists("bar", foo); // true
-		//	|	dojo.exists("bar.baz", foo); // false
-		return !!d.getObject(name, false, obj); // Boolean
-	}
-
-
-	dojo["eval"] = function(/*String*/ scriptFragment){
-		//	summary:
-		//		Perform an evaluation in the global scope. Use this rather than
-		//		calling 'eval()' directly.
-		//	description:
-		//		Placed in a separate function to minimize size of trapped
-		//		exceptions. Calling eval() directly from some other scope may
-		//		complicate tracebacks on some platforms.
-		//	returns:
-		//		The result of the evaluation. Often `undefined`
-
-
-		// note:
-		//	 - JSC eval() takes an optional second argument which can be 'unsafe'.
-		//	 - Mozilla/SpiderMonkey eval() takes an optional second argument which is the
-		//  	 scope object for new symbols.
-
-		// FIXME: investigate Joseph Smarr's technique for IE:
-		//		http://josephsmarr.com/2007/01/31/fixing-eval-to-use-global-scope-in-ie/
-		//	see also:
-		// 		http://trac.dojotoolkit.org/ticket/744
-		return d.global.eval ? d.global.eval(scriptFragment) : eval(scriptFragment); 	// Object
-	}
-
-	/*=====
-		dojo.deprecated = function(behaviour, extra, removal){
-			//	summary:
-			//		Log a debug message to indicate that a behavior has been
-			//		deprecated.
-			//	behaviour: String
-			//		The API or behavior being deprecated. Usually in the form
-			//		of "myApp.someFunction()".
-			//	extra: String?
-			//		Text to append to the message. Often provides advice on a
-			//		new function or facility to achieve the same goal during
-			//		the deprecation period.
-			//	removal: String?
-			//		Text to indicate when in the future the behavior will be
-			//		removed. Usually a version number.
-			//	example:
-			//	|	dojo.deprecated("myApp.getTemp()", "use myApp.getLocaleTemp() instead", "1.0");
-		}
-
-		dojo.experimental = function(moduleName, extra){
-			//	summary: Marks code as experimental.
-			//	description:
-			//	 	This can be used to mark a function, file, or module as
-			//	 	experimental.  Experimental code is not ready to be used, and the
-			//	 	APIs are subject to change without notice.  Experimental code may be
-			//	 	completed deleted without going through the normal deprecation
-			//	 	process.
-			//	moduleName: String
-			//	 	The name of a module, or the name of a module file or a specific
-			//	 	function
-			//	extra: String?
-			//	 	some additional message for the user
-			//	example:
-			//	|	dojo.experimental("dojo.data.Result");
-			//	example:
-			//	|	dojo.experimental("dojo.weather.toKelvin()", "PENDING approval from NOAA");
-		}
-	=====*/
-
-	//Real functions declared in dojo._firebug.firebug.
-	d.deprecated = d.experimental = function(){};
-
-})();
-// vim:ai:ts=4:noet
-
-/*
- * loader.js - A bootstrap module.  Runs before the hostenv_*.js file. Contains
- * all of the package loading methods.
- */
-
-(function(){
-	var d = dojo;
-
-	d.mixin(d, {
-		_loadedModules: {},
-		_inFlightCount: 0,
-		_hasResource: {},
-
-		_modulePrefixes: {
-			dojo: 	{	name: "dojo", value: "." },
-			// dojox: 	{	name: "dojox", value: "../dojox" },
-			// dijit: 	{	name: "dijit", value: "../dijit" },
-			doh: 	{	name: "doh", value: "../util/doh" },
-			tests: 	{	name: "tests", value: "tests" }
-		},
-
-		_moduleHasPrefix: function(/*String*/module){
-			// summary: checks to see if module has been established
-			var mp = d._modulePrefixes;
-			return !!(mp[module] && mp[module].value); // Boolean
-		},
-
-		_getModulePrefix: function(/*String*/module){
-			// summary: gets the prefix associated with module
-			var mp = d._modulePrefixes;
-			if(d._moduleHasPrefix(module)){
-				return mp[module].value; // String
-			}
-			return module; // String
-		},
-
-		_loadedUrls: [],
-
-		//WARNING: 
-		//		This variable is referenced by packages outside of bootstrap:
-		//		FloatingPane.js and undo/browser.js
-		_postLoad: false,
-		
-		//Egad! Lots of test files push on this directly instead of using dojo.addOnLoad.
-		_loaders: [],
-		_unloaders: [],
-		_loadNotifying: false
-	});
-
-
-		dojo._loadPath = function(/*String*/relpath, /*String?*/module, /*Function?*/cb){
-		// 	summary:
-		//		Load a Javascript module given a relative path
-		//
-		//	description:
-		//		Loads and interprets the script located at relpath, which is
-		//		relative to the script root directory.  If the script is found but
-		//		its interpretation causes a runtime exception, that exception is
-		//		not caught by us, so the caller will see it.  We return a true
-		//		value if and only if the script is found.
-		//
-		// relpath: 
-		//		A relative path to a script (no leading '/', and typically ending
-		//		in '.js').
-		// module: 
-		//		A module whose existance to check for after loading a path.  Can be
-		//		used to determine success or failure of the load.
-		// cb: 
-		//		a callback function to pass the result of evaluating the script
-
-		var uri = ((relpath.charAt(0) == '/' || relpath.match(/^\w+:/)) ? "" : d.baseUrl) + relpath;
-		try{
-			return !module ? d._loadUri(uri, cb) : d._loadUriAndCheck(uri, module, cb); // Boolean
-		}catch(e){
-			console.error(e);
-			return false; // Boolean
-		}
-	}
-
-	dojo._loadUri = function(/*String*/uri, /*Function?*/cb){
-		//	summary:
-		//		Loads JavaScript from a URI
-		//	description:
-		//		Reads the contents of the URI, and evaluates the contents.  This is
-		//		used to load modules as well as resource bundles. Returns true if
-		//		it succeeded. Returns false if the URI reading failed.  Throws if
-		//		the evaluation throws.
-		//	uri: a uri which points at the script to be loaded
-		//	cb: 
-		//		a callback function to process the result of evaluating the script
-		//		as an expression, typically used by the resource bundle loader to
-		//		load JSON-style resources
-
-		if(d._loadedUrls[uri]){
-			return true; // Boolean
-		}
-		d._inFlightCount++; // block addOnLoad calls that arrive while we're busy downloading
-		var contents = d._getText(uri, true);
-		if(contents){ // not 404, et al
-			d._loadedUrls[uri] = true;
-			d._loadedUrls.push(uri);
-			if(cb){
-				contents = '('+contents+')';
-			}else{
-				//Only do the scoping if no callback. If a callback is specified,
-				//it is most likely the i18n bundle stuff.
-				contents = d._scopePrefix + contents + d._scopeSuffix;
-			}
-			if(!d.isIE){ contents += "\r\n//@ sourceURL=" + uri; } // debugging assist for Firebug
-			var value = d["eval"](contents);
-			if(cb){ cb(value); }
-		}
-		// Check to see if we need to call _callLoaded() due to an addOnLoad() that arrived while we were busy downloading
-		if(--d._inFlightCount == 0 && d._postLoad && d._loaders.length){
-			// We shouldn't be allowed to get here but Firefox allows an event 
-			// (mouse, keybd, async xhrGet) to interrupt a synchronous xhrGet. 
-			// If the current script block contains multiple require() statements, then after each
-			// require() returns, inFlightCount == 0, but we want to hold the _callLoaded() until
-			// all require()s are done since the out-of-sequence addOnLoad() presumably needs them all.
-			// setTimeout allows the next require() to start (if needed), and then we check this again.
-			setTimeout(function(){ 
-				// If inFlightCount > 0, then multiple require()s are running sequentially and 
-				// the next require() started after setTimeout() was executed but before we got here.
-				if(d._inFlightCount == 0){ 
-					d._callLoaded();
-				}
-			}, 0);
-		}
-		return !!contents; // Boolean: contents? true : false
-	}
-	
-	// FIXME: probably need to add logging to this method
-	dojo._loadUriAndCheck = function(/*String*/uri, /*String*/moduleName, /*Function?*/cb){
-		// summary: calls loadUri then findModule and returns true if both succeed
-		var ok = false;
-		try{
-			ok = d._loadUri(uri, cb);
-		}catch(e){
-			console.error("failed loading " + uri + " with error: " + e);
-		}
-		return !!(ok && d._loadedModules[moduleName]); // Boolean
-	}
-
-	dojo.loaded = function(){
-		// summary:
-		//		signal fired when initial environment and package loading is
-		//		complete. You should use dojo.addOnLoad() instead of doing a 
-		//		direct dojo.connect() to this method in order to handle
-		//		initialization tasks that require the environment to be
-		//		initialized. In a browser host,	declarative widgets will 
-		//		be constructed when this function finishes runing.
-		d._loadNotifying = true;
-		d._postLoad = true;
-		var mll = d._loaders;
-
-		//Clear listeners so new ones can be added
-		//For other xdomain package loads after the initial load.
-		d._loaders = [];
-
-		for(var x = 0; x < mll.length; x++){
-			mll[x]();
-		}
-
-		d._loadNotifying = false;
-		
-		//Make sure nothing else got added to the onload queue
-		//after this first run. If something did, and we are not waiting for any
-		//more inflight resources, run again.
-		if(d._postLoad && d._inFlightCount == 0 && mll.length){
-			d._callLoaded();
-		}
-	}
-
-	dojo.unloaded = function(){
-		// summary:
-		//		signal fired by impending environment destruction. You should use
-		//		dojo.addOnUnload() instead of doing a direct dojo.connect() to this 
-		//		method to perform page/application cleanup methods. See 
-		//		dojo.addOnUnload for more info.
-		var mll = d._unloaders;
-		while(mll.length){
-			(mll.pop())();
-		}
-	}
-
-	d._onto = function(arr, obj, fn){
-		if(!fn){
-			arr.push(obj);
-		}else if(fn){
-			var func = (typeof fn == "string") ? obj[fn] : fn;
-			arr.push(function(){ func.call(obj); });
-		}
-	}
-
-	dojo.ready = dojo.addOnLoad = function(/*Object*/obj, /*String|Function?*/functionName){
-		// summary:
-		//		Registers a function to be triggered after the DOM and dojo.require() calls 
-		//		have finished loading.
-		//
-		// description:
-		//		Registers a function to be triggered after the DOM has finished
-		//		loading and `dojo.require` modules have loaded. Widgets declared in markup 
-		//		have been instantiated if `djConfig.parseOnLoad` is true when this fires. 
-		//
-		//		Images and CSS files may or may not have finished downloading when
-		//		the specified function is called.  (Note that widgets' CSS and HTML
-		//		code is guaranteed to be downloaded before said widgets are
-		//		instantiated, though including css resouces BEFORE any script elements
-		//		is highly recommended).
-		//
-		// example:
-		//	Register an anonymous function to run when everything is ready
-		//	|	dojo.addOnLoad(function(){ doStuff(); });
-		//
-		// example:
-		//	Register a function to run when everything is ready by pointer:
-		//	|	var init = function(){ doStuff(); }
-		//	|	dojo.addOnLoad(init);
-		//
-		// example:
-		//	Register a function to run scoped to `object`, either by name or anonymously:
-		//	|	dojo.addOnLoad(object, "functionName");
-		//	|	dojo.addOnLoad(object, function(){ doStuff(); });
-
-		d._onto(d._loaders, obj, functionName);
-
-		//Added for xdomain loading. dojo.addOnLoad is used to
-		//indicate callbacks after doing some dojo.require() statements.
-		//In the xdomain case, if all the requires are loaded (after initial
-		//page load), then immediately call any listeners.
-		if(d._postLoad && d._inFlightCount == 0 && !d._loadNotifying){
-			d._callLoaded();
-		}
-	}
-
-	//Support calling dojo.addOnLoad via djConfig.addOnLoad. Support all the
-	//call permutations of dojo.addOnLoad. Mainly useful when dojo is added
-	//to the page after the page has loaded.
-	var dca = d.config.addOnLoad;
-	if(dca){
-		d.addOnLoad[(dca instanceof Array ? "apply" : "call")](d, dca);
-	}
-
-	dojo._modulesLoaded = function(){
-		if(d._postLoad){ return; }
-		if(d._inFlightCount > 0){ 
-			console.warn("files still in flight!");
-			return;
-		}
-		d._callLoaded();
-	}
-
-	dojo._callLoaded = function(){
-
-		// The "object" check is for IE, and the other opera check fixes an
-		// issue in Opera where it could not find the body element in some
-		// widget test cases.  For 0.9, maybe route all browsers through the
-		// setTimeout (need protection still for non-browser environments
-		// though). This might also help the issue with FF 2.0 and freezing
-		// issues where we try to do sync xhr while background css images are
-		// being loaded (trac #2572)? Consider for 0.9.
-		if(typeof setTimeout == "object" || (d.config.useXDomain && d.isOpera)){
-			setTimeout(
-				d.isAIR ? function(){ d.loaded(); } : d._scopeName + ".loaded();",
-				0);
-		}else{
-			d.loaded();
-		}
-	}
-
-	dojo._getModuleSymbols = function(/*String*/modulename){
-		// summary:
-		//		Converts a module name in dotted JS notation to an array
-		//		representing the path in the source tree
-		var syms = modulename.split(".");
-		for(var i = syms.length; i>0; i--){
-			var parentModule = syms.slice(0, i).join(".");
-			if(i == 1 && !d._moduleHasPrefix(parentModule)){		
-				// Support default module directory (sibling of dojo) for top-level modules 
-				syms[0] = "../" + syms[0];
-			}else{
-				var parentModulePath = d._getModulePrefix(parentModule);
-				if(parentModulePath != parentModule){
-					syms.splice(0, i, parentModulePath);
-					break;
-				}
-			}
-		}
-		return syms; // Array
-	}
-
-	dojo._global_omit_module_check = false;
-
-	dojo.loadInit = function(/*Function*/init){
-		//	summary:
-		//		Executes a function that needs to be executed for the loader's dojo.requireIf
-		//		resolutions to work. This is needed mostly for the xdomain loader case where
-		//		a function needs to be executed to set up the possible values for a dojo.requireIf
-		//		call.
-		//	init:
-		//		a function reference. Executed immediately.
-		//	description: This function is mainly a marker for the xdomain loader to know parts of
-		//		code that needs be executed outside the function wrappper that is placed around modules.
-		//		The init function could be executed more than once, and it should make no assumptions
-		//		on what is loaded, or what modules are available. Only the functionality in Dojo Base
-		//		is allowed to be used. Avoid using this method. For a valid use case,
-		//		see the source for dojox.gfx.
-		init();
-	}
-
-	dojo._loadModule = dojo.require = function(/*String*/moduleName, /*Boolean?*/omitModuleCheck){
-		//	summary:
-		//		loads a Javascript module from the appropriate URI
-		//	moduleName:
-		//		module name to load, using periods for separators,
-		//		 e.g. "dojo.date.locale".  Module paths are de-referenced by dojo's
-		//		internal mapping of locations to names and are disambiguated by
-		//		longest prefix. See `dojo.registerModulePath()` for details on
-		//		registering new modules.
-		//	omitModuleCheck:
-		//		if `true`, omitModuleCheck skips the step of ensuring that the
-		//		loaded file actually defines the symbol it is referenced by.
-		//		For example if it called as `dojo.require("a.b.c")` and the
-		//		file located at `a/b/c.js` does not define an object `a.b.c`,
-		//		and exception will be throws whereas no exception is raised
-		//		when called as `dojo.require("a.b.c", true)`
-		//	description:
-		// 		Modules are loaded via dojo.require by using one of two loaders: the normal loader
-		// 		and the xdomain loader. The xdomain loader is used when dojo was built with a
-		// 		custom build that specified loader=xdomain and the module lives on a modulePath
-		// 		that is a whole URL, with protocol and a domain. The versions of Dojo that are on
-		// 		the Google and AOL CDNs use the xdomain loader.
-		// 
-		// 		If the module is loaded via the xdomain loader, it is an asynchronous load, since
-		// 		the module is added via a dynamically created script tag. This
-		// 		means that dojo.require() can return before the module has loaded. However, this 
-		// 		should only happen in the case where you do dojo.require calls in the top-level
-		// 		HTML page, or if you purposely avoid the loader checking for dojo.require
-		// 		dependencies in your module by using a syntax like dojo["require"] to load the module.
-		// 
-		// 		Sometimes it is useful to not have the loader detect the dojo.require calls in the
-		// 		module so that you can dynamically load the modules as a result of an action on the
-		// 		page, instead of right at module load time.
-		// 
-		// 		Also, for script blocks in an HTML page, the loader does not pre-process them, so
-		// 		it does not know to download the modules before the dojo.require calls occur.
-		// 
-		// 		So, in those two cases, when you want on-the-fly module loading or for script blocks
-		// 		in the HTML page, special care must be taken if the dojo.required code is loaded
-		// 		asynchronously. To make sure you can execute code that depends on the dojo.required
-		// 		modules, be sure to add the code that depends on the modules in a dojo.addOnLoad()
-		// 		callback. dojo.addOnLoad waits for all outstanding modules to finish loading before
-		// 		executing. Example:
-		// 
-		//	   	|	<script type="text/javascript">
-		//		|	dojo.require("foo");
-		//		|	dojo.require("bar");
-		//	   	|	dojo.addOnLoad(function(){
-		//	   	|		//you can now safely do something with foo and bar
-		//	   	|	});
-		//	   	|	</script>
-		// 
-		// 		This type of syntax works with both xdomain and normal loaders, so it is good
-		// 		practice to always use this idiom for on-the-fly code loading and in HTML script
-		// 		blocks. If at some point you change loaders and where the code is loaded from,
-		// 		it will all still work.
-		// 
-		// 		More on how dojo.require
-		//		`dojo.require("A.B")` first checks to see if symbol A.B is
-		//		defined. If it is, it is simply returned (nothing to do).
-		//	
-		//		If it is not defined, it will look for `A/B.js` in the script root
-		//		directory.
-		//	
-		//		`dojo.require` throws an excpetion if it cannot find a file
-		//		to load, or if the symbol `A.B` is not defined after loading.
-		//	
-		//		It returns the object `A.B`, but note the caveats above about on-the-fly loading and
-		// 		HTML script blocks when the xdomain loader is loading a module.
-		//	
-		//		`dojo.require()` does nothing about importing symbols into
-		//		the current namespace.  It is presumed that the caller will
-		//		take care of that. For example, to import all symbols into a
-		//		local block, you might write:
-		//	
-		//		|	with (dojo.require("A.B")) {
-		//		|		...
-		//		|	}
-		//	
-		//		And to import just the leaf symbol to a local variable:
-		//	
-		//		|	var B = dojo.require("A.B");
-		//	   	|	...
-		//	returns: the required namespace object
-		omitModuleCheck = d._global_omit_module_check || omitModuleCheck;
-
-		//Check if it is already loaded.
-		var module = d._loadedModules[moduleName];
-		if(module){
-			return module;
-		}
-
-		// convert periods to slashes
-		var relpath = d._getModuleSymbols(moduleName).join("/") + '.js';
-
-		var modArg = !omitModuleCheck ? moduleName : null;
-		var ok = d._loadPath(relpath, modArg);
-
-		if(!ok && !omitModuleCheck){
-			throw new Error("Could not load '" + moduleName + "'; last tried '" + relpath + "'");
-		}
-
-		// check that the symbol was defined
-		// Don't bother if we're doing xdomain (asynchronous) loading.
-		if(!omitModuleCheck && !d._isXDomain){
-			// pass in false so we can give better error
-			module = d._loadedModules[moduleName];
-			if(!module){
-				throw new Error("symbol '" + moduleName + "' is not defined after loading '" + relpath + "'"); 
-			}
-		}
-
-		return module;
-	}
-
-	dojo.provide = function(/*String*/ resourceName){
-		//	summary:
-		//		Register a resource with the package system. Works in conjunction with `dojo.require`
-		//
-		//	description:
-		//		Each javascript source file is called a resource.  When a
-		//		resource is loaded by the browser, `dojo.provide()` registers
-		//		that it has been loaded.
-		//
-		//		Each javascript source file must have at least one
-		//		`dojo.provide()` call at the top of the file, corresponding to
-		//		the file name.  For example, `js/dojo/foo.js` must have
-		//		`dojo.provide("dojo.foo");` before any calls to
-		//		`dojo.require()` are made.
-		//	
-		//		For backwards compatibility reasons, in addition to registering
-		//		the resource, `dojo.provide()` also ensures that the javascript
-		//		object for the module exists.  For example,
-		//		`dojo.provide("dojox.data.FlickrStore")`, in addition to
-		//		registering that `FlickrStore.js` is a resource for the
-		//		`dojox.data` module, will ensure that the `dojox.data`
-		//		javascript object exists, so that calls like 
-		//		`dojo.data.foo = function(){ ... }` don't fail.
-		//
-		//		In the case of a build where multiple javascript source files
-		//		are combined into one bigger file (similar to a .lib or .jar
-		//		file), that file may contain multiple dojo.provide() calls, to
-		//		note that it includes multiple resources.
-		//
-		// resourceName: String
-		//		A dot-sperated string identifying a resource. 
-		//
-		// example:
-		//	Safely create a `my` object, and make dojo.require("my.CustomModule") work
-		//	|	dojo.provide("my.CustomModule"); 
-
-		//Make sure we have a string.
-		resourceName = resourceName + "";
-		return (d._loadedModules[resourceName] = d.getObject(resourceName, true)); // Object
-	}
-
-	//Start of old bootstrap2:
-
-	dojo.platformRequire = function(/*Object*/modMap){
-		//	summary:
-		//		require one or more modules based on which host environment
-		//		Dojo is currently operating in
-		//	description:
-		//		This method takes a "map" of arrays which one can use to
-		//		optionally load dojo modules. The map is indexed by the
-		//		possible dojo.name_ values, with two additional values:
-		//		"default" and "common". The items in the "default" array will
-		//		be loaded if none of the other items have been choosen based on
-		//		dojo.name_, set by your host environment. The items in the
-		//		"common" array will *always* be loaded, regardless of which
-		//		list is chosen.
-		//	example:
-		//		|	dojo.platformRequire({
-		//		|		browser: [
-		//		|			"foo.sample", // simple module
-		//		|			"foo.test",
-		//		|			["foo.bar.baz", true] // skip object check in _loadModule (dojo.require)
-		//		|		],
-		//		|		default: [ "foo.sample._base" ],
-		//		|		common: [ "important.module.common" ]
-		//		|	});
-
-		var common = modMap.common || [];
-		var result = common.concat(modMap[d._name] || modMap["default"] || []);
-
-		for(var x=0; x<result.length; x++){
-			var curr = result[x];
-			if(curr.constructor == Array){
-				d._loadModule.apply(d, curr);
-			}else{
-				d._loadModule(curr);
-			}
-		}
-	}
-
-	dojo.requireIf = function(/*Boolean*/ condition, /*String*/ resourceName){
-		// summary:
-		//		If the condition is true then call `dojo.require()` for the specified
-		//		resource
-		//
-		// example:
-		//	|	dojo.requireIf(dojo.isBrowser, "my.special.Module");
-		
-		if(condition === true){
-			// FIXME: why do we support chained require()'s here? does the build system?
-			var args = [];
-			for(var i = 1; i < arguments.length; i++){ 
-				args.push(arguments[i]);
-			}
-			d.require.apply(d, args);
-		}
-	}
-
-	dojo.requireAfterIf = d.requireIf;
-
-	dojo.registerModulePath = function(/*String*/module, /*String*/prefix){
-		//	summary: 
-		//		Maps a module name to a path
-		//	description: 
-		//		An unregistered module is given the default path of ../[module],
-		//		relative to Dojo root. For example, module acme is mapped to
-		//		../acme.  If you want to use a different module name, use
-		//		dojo.registerModulePath. 
-		//	example:
-		//		If your dojo.js is located at this location in the web root:
-		//	|	/myapp/js/dojo/dojo/dojo.js
-		//		and your modules are located at:
-		//	|	/myapp/js/foo/bar.js
-		//	|	/myapp/js/foo/baz.js
-		//	|	/myapp/js/foo/thud/xyzzy.js
-		//		Your application can tell Dojo to locate the "foo" namespace by calling:
-		//	|	dojo.registerModulePath("foo", "../../foo");
-		//		At which point you can then use dojo.require() to load the
-		//		modules (assuming they provide() the same things which are
-		//		required). The full code might be:
-		//	|	<script type="text/javascript" 
-		//	|		src="/myapp/js/dojo/dojo/dojo.js"></script>
-		//	|	<script type="text/javascript">
-		//	|		dojo.registerModulePath("foo", "../../foo");
-		//	|		dojo.require("foo.bar");
-		//	|		dojo.require("foo.baz");
-		//	|		dojo.require("foo.thud.xyzzy");
-		//	|	</script>
-		d._modulePrefixes[module] = { name: module, value: prefix };
-	}
-
-	dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){
-		// summary:
-		//		Declares translated resources and loads them if necessary, in the
-		//		same style as dojo.require.  Contents of the resource bundle are
-		//		typically strings, but may be any name/value pair, represented in
-		//		JSON format.  See also `dojo.i18n.getLocalization`.
-		//
-		// description:
-		//		Load translated resource bundles provided underneath the "nls"
-		//		directory within a package.  Translated resources may be located in
-		//		different packages throughout the source tree.  
-		//
-		//		Each directory is named for a locale as specified by RFC 3066,
-		//		(http://www.ietf.org/rfc/rfc3066.txt), normalized in lowercase.
-		//		Note that the two bundles in the example do not define all the
-		//		same variants.  For a given locale, bundles will be loaded for
-		//		that locale and all more general locales above it, including a
-		//		fallback at the root directory.  For example, a declaration for
-		//		the "de-at" locale will first load `nls/de-at/bundleone.js`,
-		//		then `nls/de/bundleone.js` and finally `nls/bundleone.js`.  The
-		//		data will be flattened into a single Object so that lookups
-		//		will follow this cascading pattern.  An optional build step can
-		//		preload the bundles to avoid data redundancy and the multiple
-		//		network hits normally required to load these resources.
-		//
-		// moduleName: 
-		//		name of the package containing the "nls" directory in which the
-		//		bundle is found
-		//
-		// bundleName: 
-		//		bundle name, i.e. the filename without the '.js' suffix. Using "nls" as a
-		//		a bundle name is not supported, since "nls" is the name of the folder
-		//		that holds bundles. Using "nls" as the bundle name will cause problems
-		//		with the custom build.
-		//
-		// locale: 
-		//		the locale to load (optional)  By default, the browser's user
-		//		locale as defined by dojo.locale
-		//
-		// availableFlatLocales: 
-		//		A comma-separated list of the available, flattened locales for this
-		//		bundle. This argument should only be set by the build process.
-		//
-		//	example:
-		//		A particular widget may define one or more resource bundles,
-		//		structured in a program as follows, where moduleName is
-		//		mycode.mywidget and bundleNames available include bundleone and
-		//		bundletwo:
-		//	|		...
-		//	|	mycode/
-		//	|		mywidget/
-		//	|			nls/
-		//	|				bundleone.js (the fallback translation, English in this example)
-		//	|				bundletwo.js (also a fallback translation)
-		//	|				de/
-		//	|					bundleone.js
-		//	|					bundletwo.js
-		//	|				de-at/
-		//	|					bundleone.js
-		//	|				en/
-		//	|					(empty; use the fallback translation)
-		//	|				en-us/
-		//	|					bundleone.js
-		//	|				en-gb/
-		//	|					bundleone.js
-		//	|				es/
-		//	|					bundleone.js
-		//	|					bundletwo.js
-		//	|				  ...etc
-		//	|				...
-		//
-
-		d.require("dojo.i18n");
-		d.i18n._requireLocalization.apply(d.hostenv, arguments);
-	};
-
-
-	var ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"),
-		ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$");
-
-	dojo._Url = function(/*dojo._Url|String...*/){
-		// summary: 
-		//		Constructor to create an object representing a URL.
-		//		It is marked as private, since we might consider removing
-		//		or simplifying it.
-		// description: 
-		//		Each argument is evaluated in order relative to the next until
-		//		a canonical uri is produced. To get an absolute Uri relative to
-		//		the current document use:
-		//      	new dojo._Url(document.baseURI, url)
-
-		var n = null,
-			_a = arguments,
-			uri = [_a[0]];
-		// resolve uri components relative to each other
-		for(var i = 1; i<_a.length; i++){
-			if(!_a[i]){ continue; }
-
-			// Safari doesn't support this.constructor so we have to be explicit
-			// FIXME: Tracked (and fixed) in Webkit bug 3537.
-			//		http://bugs.webkit.org/show_bug.cgi?id=3537
-			var relobj = new d._Url(_a[i]+""),
-				uriobj = new d._Url(uri[0]+"");
-
-			if(
-				relobj.path == "" &&
-				!relobj.scheme &&
-				!relobj.authority &&
-				!relobj.query
-			){
-				if(relobj.fragment != n){
-					uriobj.fragment = relobj.fragment;
-				}
-				relobj = uriobj;
-			}else if(!relobj.scheme){
-				relobj.scheme = uriobj.scheme;
-
-				if(!relobj.authority){
-					relobj.authority = uriobj.authority;
-
-					if(relobj.path.charAt(0) != "/"){
-						var path = uriobj.path.substring(0,
-							uriobj.path.lastIndexOf("/") + 1) + relobj.path;
-
-						var segs = path.split("/");
-						for(var j = 0; j < segs.length; j++){
-							if(segs[j] == "."){
-								// flatten "./" references
-								if(j == segs.length - 1){
-									segs[j] = "";
-								}else{
-									segs.splice(j, 1);
-									j--;
-								}
-							}else if(j > 0 && !(j == 1 && segs[0] == "") &&
-								segs[j] == ".." && segs[j-1] != ".."){
-								// flatten "../" references
-								if(j == (segs.length - 1)){
-									segs.splice(j, 1);
-									segs[j - 1] = "";
-								}else{
-									segs.splice(j - 1, 2);
-									j -= 2;
-								}
-							}
-						}
-						relobj.path = segs.join("/");
-					}
-				}
-			}
-
-			uri = [];
-			if(relobj.scheme){ 
-				uri.push(relobj.scheme, ":");
-			}
-			if(relobj.authority){
-				uri.push("//", relobj.authority);
-			}
-			uri.push(relobj.path);
-			if(relobj.query){
-				uri.push("?", relobj.query);
-			}
-			if(relobj.fragment){
-				uri.push("#", relobj.fragment);
-			}
-		}
-
-		this.uri = uri.join("");
-
-		// break the uri into its main components
-		var r = this.uri.match(ore);
-
-		this.scheme = r[2] || (r[1] ? "" : n);
-		this.authority = r[4] || (r[3] ? "" : n);
-		this.path = r[5]; // can never be undefined
-		this.query = r[7] || (r[6] ? "" : n);
-		this.fragment  = r[9] || (r[8] ? "" : n);
-
-		if(this.authority != n){
-			// server based naming authority
-			r = this.authority.match(ire);
-
-			this.user = r[3] || n;
-			this.password = r[4] || n;
-			this.host = r[6] || r[7]; // ipv6 || ipv4
-			this.port = r[9] || n;
-		}
-	}
-
-	dojo._Url.prototype.toString = function(){ return this.uri; };
-
-	dojo.moduleUrl = function(/*String*/module, /*dojo._Url||String*/url){
-		//	summary: 
-		//		Returns a `dojo._Url` object relative to a module.
-		//	example:
-		//	|	var pngPath = dojo.moduleUrl("acme","images/small.png");
-		//	|	console.dir(pngPath); // list the object properties
-		//	|	// create an image and set it's source to pngPath's value:
-		//	|	var img = document.createElement("img");
-		// 	|	// NOTE: we assign the string representation of the url object
-		//	|	img.src = pngPath.toString(); 
-		//	|	// add our image to the document
-		//	|	dojo.body().appendChild(img);
-		//	example: 
-		//		you may de-reference as far as you like down the package
-		//		hierarchy.  This is sometimes handy to avoid lenghty relative
-		//		urls or for building portable sub-packages. In this example,
-		//		the `acme.widget` and `acme.util` directories may be located
-		//		under different roots (see `dojo.registerModulePath`) but the
-		//		the modules which reference them can be unaware of their
-		//		relative locations on the filesystem:
-		//	|	// somewhere in a configuration block
-		//	|	dojo.registerModulePath("acme.widget", "../../acme/widget");
-		//	|	dojo.registerModulePath("acme.util", "../../util");
-		//	|	
-		//	|	// ...
-		//	|	
-		//	|	// code in a module using acme resources
-		//	|	var tmpltPath = dojo.moduleUrl("acme.widget","templates/template.html");
-		//	|	var dataPath = dojo.moduleUrl("acme.util","resources/data.json");
-
-		var loc = d._getModuleSymbols(module).join('/');
-		if(!loc){ return null; }
-		if(loc.lastIndexOf("/") != loc.length-1){
-			loc += "/";
-		}
-		
-		//If the path is an absolute path (starts with a / or is on another
-		//domain/xdomain) then don't add the baseUrl.
-		var colonIndex = loc.indexOf(":");
-		if(loc.charAt(0) != "/" && (colonIndex == -1 || colonIndex > loc.indexOf("/"))){
-			loc = d.baseUrl + loc;
-		}
-
-		return new d._Url(loc, url); // dojo._Url
-	}
-})();
-
-/*=====
-dojo.isBrowser = {
-	//	example:
-	//	|	if(dojo.isBrowser){ ... }
-};
-
-dojo.isFF = {
-	//	example:
-	//	|	if(dojo.isFF > 1){ ... }
-};
-
-dojo.isIE = {
-	// example:
-	//	|	if(dojo.isIE > 6){
-	//	|		// we are IE7
-	// 	|	}
-};
-
-dojo.isSafari = {
-	//	example:
-	//	|	if(dojo.isSafari){ ... }
-	//	example: 
-	//		Detect iPhone:
-	//	|	if(dojo.isSafari && navigator.userAgent.indexOf("iPhone") != -1){ 
-	//	|		// we are iPhone. Note, iPod touch reports "iPod" above and fails this test.
-	//	|	}
-};
-
-dojo = {
-	// isBrowser: Boolean
-	//		True if the client is a web-browser
-	isBrowser: true,
-	//	isFF: Number | undefined
-	//		Version as a Number if client is FireFox. undefined otherwise. Corresponds to
-	//		major detected FireFox version (1.5, 2, 3, etc.)
-	isFF: 2,
-	//	isIE: Number | undefined
-	//		Version as a Number if client is MSIE(PC). undefined otherwise. Corresponds to
-	//		major detected IE version (6, 7, 8, etc.)
-	isIE: 6,
-	//	isKhtml: Number | undefined
-	//		Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major
-	//		detected version.
-	isKhtml: 0,
-	//	isWebKit: Number | undefined
-	//		Version as a Number if client is a WebKit-derived browser (Konqueror,
-	//		Safari, Chrome, etc.). undefined otherwise.
-	isWebKit: 0,
-	//	isMozilla: Number | undefined
-	//		Version as a Number if client is a Mozilla-based browser (Firefox,
-	//		SeaMonkey). undefined otherwise. Corresponds to major detected version.
-	isMozilla: 0,
-	//	isOpera: Number | undefined
-	//		Version as a Number if client is Opera. undefined otherwise. Corresponds to
-	//		major detected version.
-	isOpera: 0,
-	//	isSafari: Number | undefined
-	//		Version as a Number if client is Safari or iPhone. undefined otherwise.
-	isSafari: 0,
-	//	isChrome: Number | undefined
-	//		Version as a Number if client is Chrome browser. undefined otherwise.
-	isChrome: 0
-	//	isMac: Boolean
-	//		True if the client runs on Mac
-}
-=====*/
-
-if(typeof window != 'undefined'){
-	dojo.isBrowser = true;
-	dojo._name = "browser";
-
-
-	// attempt to figure out the path to dojo if it isn't set in the config
-	(function(){
-		var d = dojo;
-
-		// this is a scope protection closure. We set browser versions and grab
-		// the URL we were loaded from here.
-
-		// grab the node we were loaded from
-		if(document && document.getElementsByTagName){
-			var scripts = document.getElementsByTagName("script");
-			var rePkg = /dojo(\.xd)?\.js(\W|$)/i;
-			for(var i = 0; i < scripts.length; i++){
-				var src = scripts[i].getAttribute("src");
-				if(!src){ continue; }
-				var m = src.match(rePkg);
-				if(m){
-					// find out where we came from
-					if(!d.config.baseUrl){
-						d.config.baseUrl = src.substring(0, m.index);
-					}
-					// and find out if we need to modify our behavior
-					var cfg = scripts[i].getAttribute("djConfig");
-					if(cfg){
-						var cfgo = eval("({ "+cfg+" })");
-						for(var x in cfgo){
-							dojo.config[x] = cfgo[x];
-						}
-					}
-					break; // "first Dojo wins"
-				}
-			}
-		}
-		d.baseUrl = d.config.baseUrl;
-
-		// fill in the rendering support information in dojo.render.*
-		var n = navigator;
-		var dua = n.userAgent,
-			dav = n.appVersion,
-			tv = parseFloat(dav);
-
-		if(dua.indexOf("Opera") >= 0){ d.isOpera = tv; }
-		if(dua.indexOf("AdobeAIR") >= 0){ d.isAIR = 1; }
-		d.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : 0;
-		d.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined;
-		d.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined;
-		d.isMac = dav.indexOf("Macintosh") >= 0;
-
-		// safari detection derived from:
-		//		http://developer.apple.com/internet/safari/faq.html#anchor2
-		//		http://developer.apple.com/internet/safari/uamatrix.html
-		var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);
-		if(index && !dojo.isChrome){
-			// try to grab the explicit Safari version first. If we don't get
-			// one, look for less than 419.3 as the indication that we're on something
-			// "Safari 2-ish".
-			d.isSafari = parseFloat(dav.split("Version/")[1]);
-			if(!d.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){
-				d.isSafari = 2;
-			}
-		}
-
-				if(dua.indexOf("Gecko") >= 0 && !d.isKhtml && !d.isWebKit){ d.isMozilla = d.isMoz = tv; }
-		if(d.isMoz){
-			//We really need to get away from this. Consider a sane isGecko approach for the future.
-			d.isFF = parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined;
-		}
-		if(document.all && !d.isOpera){
-			d.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined;
-			//In cases where the page has an HTTP header or META tag with
-			//X-UA-Compatible, then it is in emulation mode.
-			//Make sure isIE reflects the desired version.
-			//document.documentMode of 5 means quirks mode.
-			//Only switch the value if documentMode's major version
-			//is different from isIE's major version.
-			var mode = document.documentMode;
-			if(mode && mode != 5 && Math.floor(d.isIE) != mode){
-				d.isIE = mode;
-			}
-		}
-
-		//Workaround to get local file loads of dojo to work on IE 7
-		//by forcing to not use native xhr.
-		if(dojo.isIE && window.location.protocol === "file:"){
-			dojo.config.ieForceActiveXXhr=true;
-		}
-		
-		d.isQuirks = document.compatMode == "BackCompat";
-
-		// TODO: is the HTML LANG attribute relevant?
-		d.locale = dojo.config.locale || (d.isIE ? n.userLanguage : n.language).toLowerCase();
-
-		// These are in order of decreasing likelihood; this will change in time.
-				d._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
-		
-		d._xhrObj = function(){
-			// summary: 
-			//		does the work of portably generating a new XMLHTTPRequest object.
-			var http, last_e;
-						if(!dojo.isIE || !dojo.config.ieForceActiveXXhr){
-							try{ http = new XMLHttpRequest(); }catch(e){}
-						}
-			if(!http){
-				for(var i=0; i<3; ++i){
-					var progid = d._XMLHTTP_PROGIDS[i];
-					try{
-						http = new ActiveXObject(progid);
-					}catch(e){
-						last_e = e;
-					}
-
-					if(http){
-						d._XMLHTTP_PROGIDS = [progid];  // so faster next time
-						break;
-					}
-				}
-			}
-			
-			if(!http){
-				throw new Error("XMLHTTP not available: "+last_e);
-			}
-
-			return http; // XMLHTTPRequest instance
-		}
-
-		d._isDocumentOk = function(http){
-			var stat = http.status || 0,
-				lp = location.protocol;
-			return (stat >= 200 && stat < 300) || 	// Boolean
-				stat == 304 || 						// allow any 2XX response code
-				stat == 1223 || 						// get it out of the cache
-				(!stat && (lp == "file:" || lp == "chrome:" || lp == "app:") ); // Internet Explorer mangled the status code OR we're Titanium requesting a local file
-		}
-
-		//See if base tag is in use.
-		//This is to fix http://trac.dojotoolkit.org/ticket/3973,
-		//but really, we need to find out how to get rid of the dojo._Url reference
-		//below and still have DOH work with the dojo.i18n test following some other
-		//test that uses the test frame to load a document (trac #2757).
-		//Opera still has problems, but perhaps a larger issue of base tag support
-		//with XHR requests (hasBase is true, but the request is still made to document
-		//path, not base path).
-		var owloc = window.location+"";
-		var base = document.getElementsByTagName("base");
-		var hasBase = (base && base.length > 0);
-
-		d._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){
-			// summary: Read the contents of the specified uri and return those contents.
-			// uri:
-			//		A relative or absolute uri. If absolute, it still must be in
-			//		the same "domain" as we are.
-			// fail_ok:
-			//		Default false. If fail_ok and loading fails, return null
-			//		instead of throwing.
-			// returns: The response text. null is returned when there is a
-			//		failure and failure is okay (an exception otherwise)
-
-			// NOTE: must be declared before scope switches ie. this._xhrObj()
-			var http = d._xhrObj();
-
-			if(!hasBase && dojo._Url){
-				uri = (new dojo._Url(owloc, uri)).toString();
-			}
-
-			if(d.config.cacheBust){
-				//Make sure we have a string before string methods are used on uri
-				uri += "";
-				uri += (uri.indexOf("?") == -1 ? "?" : "&") + String(d.config.cacheBust).replace(/\W+/g,"");
-			}
-
-			http.open('GET', uri, false);
-			try{
-				http.send(null);
-				if(!d._isDocumentOk(http)){
-					var err = Error("Unable to load "+uri+" status:"+ http.status);
-					err.status = http.status;
-					err.responseText = http.responseText;
-					throw err;
-				}
-			}catch(e){
-				if(fail_ok){ return null; } // null
-				// rethrow the exception
-				throw e;
-			}
-			return http.responseText; // String
-		}
-		
-
-		var _w = window;
-		var _handleNodeEvent = function(/*String*/evtName, /*Function*/fp){
-			// summary:
-			//		non-destructively adds the specified function to the node's
-			//		evtName handler.
-			// evtName: should be in the form "onclick" for "onclick" handlers.
-			// Make sure you pass in the "on" part.
-			var _a = _w.attachEvent || _w.addEventListener;
-			evtName = _w.attachEvent ? evtName : evtName.substring(2);
-			_a(evtName, function(){
-				fp.apply(_w, arguments);
-			}, false);
-		};
-
-
-		d._windowUnloaders = [];
-		
-		d.windowUnloaded = function(){
-			// summary:
-			//		signal fired by impending window destruction. You may use
-			//		dojo.addOnWindowUnload() to register a listener for this
-			//		event. NOTE: if you wish to dojo.connect() to this method
-			//		to perform page/application cleanup, be aware that this
-			//		event WILL NOT fire if no handler has been registered with
-			//		dojo.addOnWindowUnload. This behavior started in Dojo 1.3.
-			//		Previous versions always triggered dojo.windowUnloaded. See
-			//		dojo.addOnWindowUnload for more info.
-			var mll = d._windowUnloaders;
-			while(mll.length){
-				(mll.pop())();
-			}
-		};
-
-		var _onWindowUnloadAttached = 0;
-		d.addOnWindowUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){
-			// summary:
-			//		registers a function to be triggered when window.onunload
-			//		fires. 
-			//	description:
-			//		The first time that addOnWindowUnload is called Dojo
-			//		will register a page listener to trigger your unload
-			//		handler with. Note that registering these handlers may
-			//		destory "fastback" page caching in browsers that support
-			//		it. Be careful trying to modify the DOM or access
-			//		JavaScript properties during this phase of page unloading:
-			//		they may not always be available. Consider
-			//		dojo.addOnUnload() if you need to modify the DOM or do
-			//		heavy JavaScript work since it fires at the eqivalent of
-			//		the page's "onbeforeunload" event.
-			// example:
-			//	|	dojo.addOnWindowUnload(functionPointer)
-			//	|	dojo.addOnWindowUnload(object, "functionName");
-			//	|	dojo.addOnWindowUnload(object, function(){ /* ... */});
-
-			d._onto(d._windowUnloaders, obj, functionName);
-			if(!_onWindowUnloadAttached){
-				_onWindowUnloadAttached = 1;
-				_handleNodeEvent("onunload", d.windowUnloaded);
-			}
-		};
-
-		var _onUnloadAttached = 0;
-		d.addOnUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){
-			// summary:
-			//		registers a function to be triggered when the page unloads.
-			//	description:
-			//		The first time that addOnUnload is called Dojo will
-			//		register a page listener to trigger your unload handler
-			//		with. 
-			//
-			//		In a browser enviroment, the functions will be triggered
-			//		during the window.onbeforeunload event. Be careful of doing
-			//		too much work in an unload handler. onbeforeunload can be
-			//		triggered if a link to download a file is clicked, or if
-			//		the link is a javascript: link. In these cases, the
-			//		onbeforeunload event fires, but the document is not
-			//		actually destroyed. So be careful about doing destructive
-			//		operations in a dojo.addOnUnload callback.
-			//
-			//		Further note that calling dojo.addOnUnload will prevent
-			//		browsers from using a "fast back" cache to make page
-			//		loading via back button instantaneous. 
-			// example:
-			//	|	dojo.addOnUnload(functionPointer)
-			//	|	dojo.addOnUnload(object, "functionName")
-			//	|	dojo.addOnUnload(object, function(){ /* ... */});
-
-			d._onto(d._unloaders, obj, functionName);
-			if(!_onUnloadAttached){
-				_onUnloadAttached = 1;
-				_handleNodeEvent("onbeforeunload", dojo.unloaded);
-			}
-		};
-
-	})();
-
-	//START DOMContentLoaded
-	dojo._initFired = false;
-	dojo._loadInit = function(e){
-		if(!dojo._initFired){
-			dojo._initFired = true;
-
-			//Help out IE to avoid memory leak.
-			if(!dojo.config.afterOnLoad && window.detachEvent){
-				window.detachEvent("onload", dojo._loadInit);
-			}
-
-			if(dojo._inFlightCount == 0){
-				dojo._modulesLoaded();
-			}
-		}
-	}
-
-	if(!dojo.config.afterOnLoad){
-		if(document.addEventListener){
-			//Standards. Hooray! Assumption here that if standards based,
-			//it knows about DOMContentLoaded. It is OK if it does not, the fall through
-			//to window onload should be good enough.
-			document.addEventListener("DOMContentLoaded", dojo._loadInit, false);
-			window.addEventListener("load", dojo._loadInit, false);
-		}else if(window.attachEvent){
-			window.attachEvent("onload", dojo._loadInit);
-		}
-	}
-
-		if(dojo.isIE){
-		// 	for Internet Explorer. readyState will not be achieved on init
-		// 	call, but dojo doesn't need it however, we'll include it
-		// 	because we don't know if there are other functions added that
-		// 	might.  Note that this has changed because the build process
-		// 	strips all comments -- including conditional ones.
-		if(!dojo.config.afterOnLoad && !dojo.config.skipIeDomLoaded){
-			document.write('<scr'+'ipt defer src="//:" '
-				+ 'onreadystatechange="if(this.readyState==\'complete\'){' + dojo._scopeName + '._loadInit();}">'
-				+ '</scr'+'ipt>'
-			);
-		}
-
-		try{
-			document.namespaces.add("v","urn:schemas-microsoft-com:vml");
-			var vmlElems = ["*", "group", "roundrect", "oval", "shape", "rect", "imagedata"],
-				i = 0, l = 1, s = document.createStyleSheet();
-			if(dojo.isIE >= 8){
-				i = 1;
-				l = vmlElems.length;
-			}
-			for(; i < l; ++i){
-				s.addRule("v\\:" + vmlElems[i], "behavior:url(#default#VML); display:inline-block");
-			}
-		}catch(e){}
-	}
-		//END DOMContentLoaded
-
-
-	/*
-	OpenAjax.subscribe("OpenAjax", "onload", function(){
-		if(dojo._inFlightCount == 0){
-			dojo._modulesLoaded();
-		}
-	});
-
-	OpenAjax.subscribe("OpenAjax", "onunload", function(){
-		dojo.unloaded();
-	});
-	*/
-} //if (typeof window != 'undefined')
-
-//Register any module paths set up in djConfig. Need to do this
-//in the hostenvs since hostenv_browser can read djConfig from a
-//script tag's attribute.
-(function(){
-	var mp = dojo.config["modulePaths"];
-	if(mp){
-		for(var param in mp){
-			dojo.registerModulePath(param, mp[param]);
-		}
-	}
-})();
-
-//Load debug code if necessary.
-if(dojo.config.isDebug){
-	dojo.require("dojo._firebug.firebug");
-}
-
-if(dojo.config.debugAtAllCosts){
-	dojo.config.useXDomain = true;
-	dojo.require("dojo._base._loader.loader_xd");
-	dojo.require("dojo._base._loader.loader_debug");
-	dojo.require("dojo.i18n");
-}
-
-if(!dojo._hasResource["dojo._base.lang"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.lang"] = true;
-dojo.provide("dojo._base.lang");
-
-(function(){
-	var d = dojo, opts = Object.prototype.toString;
-
-	// Crockford (ish) functions
-
-	dojo.isString = function(/*anything*/ it){
-		//	summary:
-		//		Return true if it is a String
-		return (typeof it == "string" || it instanceof String); // Boolean
-	}
-
-	dojo.isArray = function(/*anything*/ it){
-		//	summary:
-		//		Return true if it is an Array.
-		//		Does not work on Arrays created in other windows.
-		return it && (it instanceof Array || typeof it == "array"); // Boolean
-	}
-
-	dojo.isFunction = function(/*anything*/ it){
-		// summary:
-		//		Return true if it is a Function
-		return opts.call(it) === "[object Function]";
-	};
-
-	dojo.isObject = function(/*anything*/ it){
-		// summary:
-		//		Returns true if it is a JavaScript object (or an Array, a Function
-		//		or null)
-		return it !== undefined &&
-			(it === null || typeof it == "object" || d.isArray(it) || d.isFunction(it)); // Boolean
-	}
-
-	dojo.isArrayLike = function(/*anything*/ it){
-		//	summary:
-		//		similar to dojo.isArray() but more permissive
-		//	description:
-		//		Doesn't strongly test for "arrayness".  Instead, settles for "isn't
-		//		a string or number and has a length property". Arguments objects
-		//		and DOM collections will return true when passed to
-		//		dojo.isArrayLike(), but will return false when passed to
-		//		dojo.isArray().
-		//	returns:
-		//		If it walks like a duck and quacks like a duck, return `true`
-		return it && it !== undefined && // Boolean
-			// keep out built-in constructors (Number, String, ...) which have length
-			// properties
-			!d.isString(it) && !d.isFunction(it) &&
-			!(it.tagName && it.tagName.toLowerCase() == 'form') &&
-			(d.isArray(it) || isFinite(it.length));
-	}
-
-	dojo.isAlien = function(/*anything*/ it){
-		// summary:
-		//		Returns true if it is a built-in function or some other kind of
-		//		oddball that *should* report as a function but doesn't
-		return it && !d.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean
-	}
-
-	dojo.extend = function(/*Object*/ constructor, /*Object...*/ props){
-		// summary:
-		//		Adds all properties and methods of props to constructor's
-		//		prototype, making them available to all instances created with
-		//		constructor.
-		for(var i=1, l=arguments.length; i<l; i++){
-			d._mixin(constructor.prototype, arguments[i]);
-		}
-		return constructor; // Object
-	}
-
-	dojo._hitchArgs = function(scope, method /*,...*/){
-		var pre = d._toArray(arguments, 2);
-		var named = d.isString(method);
-		return function(){
-			// arrayify arguments
-			var args = d._toArray(arguments);
-			// locate our method
-			var f = named ? (scope||d.global)[method] : method;
-			// invoke with collected args
-			return f && f.apply(scope || this, pre.concat(args)); // mixed
-		} // Function
-	}
-
-	dojo.hitch = function(/*Object*/scope, /*Function|String*/method /*,...*/){
-		//	summary:
-		//		Returns a function that will only ever execute in the a given scope.
-		//		This allows for easy use of object member functions
-		//		in callbacks and other places in which the "this" keyword may
-		//		otherwise not reference the expected scope.
-		//		Any number of default positional arguments may be passed as parameters 
-		//		beyond "method".
-		//		Each of these values will be used to "placehold" (similar to curry)
-		//		for the hitched function.
-		//	scope:
-		//		The scope to use when method executes. If method is a string,
-		//		scope is also the object containing method.
-		//	method:
-		//		A function to be hitched to scope, or the name of the method in
-		//		scope to be hitched.
-		//	example:
-		//	|	dojo.hitch(foo, "bar")();
-		//		runs foo.bar() in the scope of foo
-		//	example:
-		//	|	dojo.hitch(foo, myFunction);
-		//		returns a function that runs myFunction in the scope of foo
-		//	example:
-		//		Expansion on the default positional arguments passed along from
-		//		hitch. Passed args are mixed first, additional args after.
-		//	|	var foo = { bar: function(a, b, c){ console.log(a, b, c); } };
-		//	|	var fn = dojo.hitch(foo, "bar", 1, 2);
-		//	|	fn(3); // logs "1, 2, 3"
-		//	example:
-		//	|	var foo = { bar: 2 };
-		//	|	dojo.hitch(foo, function(){ this.bar = 10; })();
-		//		execute an anonymous function in scope of foo
-		
-		if(arguments.length > 2){
-			return d._hitchArgs.apply(d, arguments); // Function
-		}
-		if(!method){
-			method = scope;
-			scope = null;
-		}
-		if(d.isString(method)){
-			scope = scope || d.global;
-			if(!scope[method]){ throw(['dojo.hitch: scope["', method, '"] is null (scope="', scope, '")'].join('')); }
-			return function(){ return scope[method].apply(scope, arguments || []); }; // Function
-		}
-		return !scope ? method : function(){ return method.apply(scope, arguments || []); }; // Function
-	}
-
-	/*=====
-	dojo.delegate = function(obj, props){
-		//	summary:
-		//		Returns a new object which "looks" to obj for properties which it
-		//		does not have a value for. Optionally takes a bag of properties to
-		//		seed the returned object with initially.
-		//	description:
-		//		This is a small implementaton of the Boodman/Crockford delegation
-		//		pattern in JavaScript. An intermediate object constructor mediates
-		//		the prototype chain for the returned object, using it to delegate
-		//		down to obj for property lookup when object-local lookup fails.
-		//		This can be thought of similarly to ES4's "wrap", save that it does
-		//		not act on types but rather on pure objects.
-		//	obj:
-		//		The object to delegate to for properties not found directly on the
-		//		return object or in props.
-		//	props:
-		//		an object containing properties to assign to the returned object
-		//	returns:
-		//		an Object of anonymous type
-		//	example:
-		//	|	var foo = { bar: "baz" };
-		//	|	var thinger = dojo.delegate(foo, { thud: "xyzzy"});
-		//	|	thinger.bar == "baz"; // delegated to foo
-		//	|	foo.thud == undefined; // by definition
-		//	|	thinger.thud == "xyzzy"; // mixed in from props
-		//	|	foo.bar = "thonk";
-		//	|	thinger.bar == "thonk"; // still delegated to foo's bar
-	}
-	=====*/
-
-	dojo.delegate = dojo._delegate = (function(){
-		// boodman/crockford delegation w/ cornford optimization
-		function TMP(){}
-		return function(obj, props){
-			TMP.prototype = obj;
-			var tmp = new TMP();
-			TMP.prototype = null;
-			if(props){
-				d._mixin(tmp, props);
-			}
-			return tmp; // Object
-		}
-	})();
-
-	/*=====
-	dojo._toArray = function(obj, offset, startWith){
-		//	summary:
-		//		Converts an array-like object (i.e. arguments, DOMCollection) to an
-		//		array. Returns a new Array with the elements of obj.
-		//	obj: Object
-		//		the object to "arrayify". We expect the object to have, at a
-		//		minimum, a length property which corresponds to integer-indexed
-		//		properties.
-		//	offset: Number?
-		//		the location in obj to start iterating from. Defaults to 0.
-		//		Optional.
-		//	startWith: Array?
-		//		An array to pack with the properties of obj. If provided,
-		//		properties in obj are appended at the end of startWith and
-		//		startWith is the returned array.
-	}
-	=====*/
-
-	var efficient = function(obj, offset, startWith){
-		return (startWith||[]).concat(Array.prototype.slice.call(obj, offset||0));
-	};
-
-		var slow = function(obj, offset, startWith){
-		var arr = startWith||[];
-		for(var x = offset || 0; x < obj.length; x++){
-			arr.push(obj[x]);
-		}
-		return arr;
-	};
-	
-	dojo._toArray =
-				d.isIE ?  function(obj){
-			return ((obj.item) ? slow : efficient).apply(this, arguments);
-		} :
-				efficient;
-
-	dojo.partial = function(/*Function|String*/method /*, ...*/){
-		//	summary:
-		//		similar to hitch() except that the scope object is left to be
-		//		whatever the execution context eventually becomes.
-		//	description:
-		//		Calling dojo.partial is the functional equivalent of calling:
-		//		|	dojo.hitch(null, funcName, ...);
-		var arr = [ null ];
-		return d.hitch.apply(d, arr.concat(d._toArray(arguments))); // Function
-	}
-
-	var extraNames = d._extraNames, extraLen = extraNames.length, empty = {};
-
-	dojo.clone = function(/*anything*/ o){
-		// summary:
-		//		Clones objects (including DOM nodes) and all children.
-		//		Warning: do not clone cyclic structures.
-		if(!o || typeof o != "object" || d.isFunction(o)){
-			// null, undefined, any non-object, or function
-			return o;	// anything
-		}
-		if(o.nodeType && "cloneNode" in o){
-			// DOM Node
-			return o.cloneNode(true); // Node
-		}
-		if(o instanceof Date){
-			// Date
-			return new Date(o.getTime());	// Date
-		}
-		var r, i, l, s, name;
-		if(d.isArray(o)){
-			// array
-			r = [];
-			for(i = 0, l = o.length; i < l; ++i){
-				if(i in o){
-					r.push(d.clone(o[i]));
-				}
-			}
-// we don't clone functions for performance reasons
-//		}else if(d.isFunction(o)){
-//			// function
-//			r = function(){ return o.apply(this, arguments); };
-		}else{
-			// generic objects
-			r = o.constructor ? new o.constructor() : {};
-		}
-		for(name in o){
-			// the "tobj" condition avoid copying properties in "source"
-			// inherited from Object.prototype.  For example, if target has a custom
-			// toString() method, don't overwrite it with the toString() method
-			// that source inherited from Object.prototype
-			s = o[name];
-			if(!(name in r) || (r[name] !== s && (!(name in empty) || empty[name] !== s))){
-				r[name] = d.clone(s);
-			}
-		}
-				// IE doesn't recognize some custom functions in for..in
-		if(extraLen){
-			for(i = 0; i < extraLen; ++i){
-				name = extraNames[i];
-				s = o[name];
-				if(!(name in r) || (r[name] !== s && (!(name in empty) || empty[name] !== s))){
-					r[name] = s; // functions only, we don't clone them
-				}
-			}
-		}
-				return r; // Object
-	}
-
-	/*=====
-	dojo.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 selected for inclusion into the base due
-		//		to its compact size and relatively good performance
-		//		(see [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript)
-		//		Uses String.prototype.trim instead, if available.
-		//		The fastest but longest version of this function is located at
-		//		dojo.string.trim()
-		return "";	// String
-	}
-	=====*/
-
-	dojo.trim = String.prototype.trim ?
-		function(str){ return str.trim(); } :
-		function(str){ return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); };
-
-	/*=====
-	dojo.replace = function(tmpl, map, pattern){
-		//	summary:
-		//		Performs parameterized substitutions on a string. Throws an
-		//		exception if any parameter is unmatched. 
-		//	tmpl: String
-		//		String to be used as a template.
-		//	map: Object|Function
-		//		If an object, it is used as a dictionary to look up substitutions.
-		//		If a function, it is called for every substitution with following
-		//		parameters: a whole match, a name, an offset, and the whole template
-		//		string (see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/replace
-		//		for more details).
-		//	pattern: RegEx?
-		//		Optional regular expression objects that overrides the default pattern.
-		//		Must be global and match one item. The default is: /\{([^\}]+)\}/g,
-		//		which matches patterns like that: "{xxx}", where "xxx" is any sequence
-		//		of characters, which doesn't include "}".
-		//	returns: String
-		//		Returns the substituted string.
-		//	example:
-		//	|	// uses a dictionary for substitutions:
-		//	|	dojo.replace("Hello, {name.first} {name.last} AKA {nick}!",
-		//	|	  {
-		//	|	    nick: "Bob",
-		//	|	    name: {
-		//	|	      first:  "Robert",
-		//	|	      middle: "X",
-		//	|	      last:   "Cringely"
-		//	|	    }
-		//	|	  });
-		//	|	// returns: Hello, Robert Cringely AKA Bob!
-		//	example:
-		//	|	// uses an array for substitutions:
-		//	|	dojo.replace("Hello, {0} {2}!",
-		//	|	  ["Robert", "X", "Cringely"]);
-		//	|	// returns: Hello, Robert Cringely!
-		//	example:
-		//	|	// uses a function for substitutions:
-		//	|	function sum(a){
-		//	|	  var t = 0;
-		//	|	  dojo.forEach(a, function(x){ t += x; });
-		//	|	  return t;
-		//	|	}
-		//	|	dojo.replace(
-		//	|	  "{count} payments averaging {avg} USD per payment.",
-		//	|	  dojo.hitch(
-		//	|	    { payments: [11, 16, 12] },
-		//	|	    function(_, key){
-		//	|	      switch(key){
-		//	|	        case "count": return this.payments.length;
-		//	|	        case "min":   return Math.min.apply(Math, this.payments);
-		//	|	        case "max":   return Math.max.apply(Math, this.payments);
-		//	|	        case "sum":   return sum(this.payments);
-		//	|	        case "avg":   return sum(this.payments) / this.payments.length;
-		//	|	      }
-		//	|	    }
-		//	|	  )
-		//	|	);
-		//	|	// prints: 3 payments averaging 13 USD per payment.
-		//	example:
-		//	|	// uses an alternative PHP-like pattern for substitutions:
-		//	|	dojo.replace("Hello, ${0} ${2}!",
-		//	|	  ["Robert", "X", "Cringely"], /\$\{([^\}]+)\}/g);
-		//	|	// returns: Hello, Robert Cringely!
-		return "";	// String
-	}
-	=====*/
-
-	var _pattern = /\{([^\}]+)\}/g;
-	dojo.replace = function(tmpl, map, pattern){
-		return tmpl.replace(pattern || _pattern, d.isFunction(map) ?
-			map : function(_, k){ return d.getObject(k, false, map); });
-	};
-})();
-
-}
-
-if(!dojo._hasResource["dojo._base.array"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.array"] = true;
-
-dojo.provide("dojo._base.array");
-
-(function(){
-	var _getParts = function(arr, obj, cb){
-		return [ 
-			(typeof arr == "string") ? arr.split("") : arr, 
-			obj || dojo.global,
-			// FIXME: cache the anonymous functions we create here?
-			(typeof cb == "string") ? new Function("item", "index", "array", cb) : cb
-		];
-	};
-
-	var everyOrSome = function(/*Boolean*/every, /*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
-		var _p = _getParts(arr, thisObject, callback); arr = _p[0];
-		for(var i=0,l=arr.length; i<l; ++i){
-			var result = !!_p[2].call(_p[1], arr[i], i, arr);
-			if(every ^ result){
-				return result; // Boolean
-			}
-		}
-		return every; // Boolean
-	};
-
-	dojo.mixin(dojo, {
-		indexOf: function(	/*Array*/		array, 
-							/*Object*/		value,
-							/*Integer?*/	fromIndex,
-							/*Boolean?*/	findLast){
-			// summary:
-			//		locates the first index of the provided value in the
-			//		passed array. If the value is not found, -1 is returned.
-			// description:
-			//		This method corresponds to the JavaScript 1.6 Array.indexOf method, with one difference: when
-			//		run over sparse arrays, the Dojo function invokes the callback for every index whereas JavaScript 
-			//		1.6's indexOf skips the holes in the sparse array.
-			//		For details on this method, see:
-			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/indexOf
-
-			var step = 1, end = array.length || 0, i = 0;
-			if(findLast){
-				i = end - 1;
-				step = end = -1;
-			}
-			if(fromIndex != undefined){ i = fromIndex; }
-			if((findLast && i > end) || i < end){
-				for(; i != end; i += step){
-					if(array[i] == value){ return i; }
-				}
-			}
-			return -1;	// Number
-		},
-
-		lastIndexOf: function(/*Array*/array, /*Object*/value, /*Integer?*/fromIndex){
-			// summary:
-			//		locates the last index of the provided value in the passed
-			//		array. If the value is not found, -1 is returned.
-			// description:
-			//		This method corresponds to the JavaScript 1.6 Array.lastIndexOf method, with one difference: when
-			//		run over sparse arrays, the Dojo function invokes the callback for every index whereas JavaScript 
-			//		1.6's lastIndexOf skips the holes in the sparse array.
-			//		For details on this method, see:
-			// 			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/lastIndexOf
-			return dojo.indexOf(array, value, fromIndex, true); // Number
-		},
-
-		forEach: function(/*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
-			//	summary:
-			//		for every item in arr, callback is invoked. Return values are ignored.
-			//		If you want to break out of the loop, consider using dojo.every() or dojo.some().
-			//		forEach does not allow breaking out of the loop over the items in arr.
-			//	arr:
-			//		the array to iterate over. If a string, operates on individual characters.
-			//	callback:
-			//		a function is invoked with three arguments: item, index, and array
-			//	thisObject:
-			//		may be used to scope the call to callback
-			//	description:
-			//		This function corresponds to the JavaScript 1.6 Array.forEach() method, with one difference: when 
-			//		run over sparse arrays, this implemenation passes the "holes" in the sparse array to
-			//		the callback function with a value of undefined. JavaScript 1.6's forEach skips the holes in the sparse array.
-			//		For more details, see:
-			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/forEach
-			//	example:
-			//	|	// log out all members of the array:
-			//	|	dojo.forEach(
-			//	|		[ "thinger", "blah", "howdy", 10 ],
-			//	|		function(item){
-			//	|			console.log(item);
-			//	|		}
-			//	|	);
-			//	example:
-			//	|	// log out the members and their indexes
-			//	|	dojo.forEach(
-			//	|		[ "thinger", "blah", "howdy", 10 ],
-			//	|		function(item, idx, arr){
-			//	|			console.log(item, "at index:", idx);
-			//	|		}
-			//	|	);
-			//	example:
-			//	|	// use a scoped object member as the callback
-			//	|	
-			//	|	var obj = {
-			//	|		prefix: "logged via obj.callback:", 
-			//	|		callback: function(item){
-			//	|			console.log(this.prefix, item);
-			//	|		}
-			//	|	};
-			//	|	
-			//	|	// specifying the scope function executes the callback in that scope
-			//	|	dojo.forEach(
-			//	|		[ "thinger", "blah", "howdy", 10 ],
-			//	|		obj.callback,
-			//	|		obj
-			//	|	);
-			//	|	
-			//	|	// alternately, we can accomplish the same thing with dojo.hitch()
-			//	|	dojo.forEach(
-			//	|		[ "thinger", "blah", "howdy", 10 ],
-			//	|		dojo.hitch(obj, "callback")
-			//	|	);
-
-			// match the behavior of the built-in forEach WRT empty arrs
-			if(!arr || !arr.length){ return; }
-
-			// FIXME: there are several ways of handilng thisObject. Is
-			// dojo.global always the default context?
-			var _p = _getParts(arr, thisObject, callback); arr = _p[0];
-			for(var i=0,l=arr.length; i<l; ++i){ 
-				_p[2].call(_p[1], arr[i], i, arr);
-			}
-		},
-
-		every: function(/*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
-			// summary:
-			//		Determines whether or not every item in arr satisfies the
-			//		condition implemented by callback.
-			// arr:
-			//		the array to iterate on. If a string, operates on individual characters.
-			// callback:
-			//		a function is invoked with three arguments: item, index,
-			//		and array and returns true if the condition is met.
-			// thisObject:
-			//		may be used to scope the call to callback
-			// description:
-			//		This function corresponds to the JavaScript 1.6 Array.every() method, with one difference: when 
-			//		run over sparse arrays, this implemenation passes the "holes" in the sparse array to
-			//		the callback function with a value of undefined. JavaScript 1.6's every skips the holes in the sparse array.
-			//		For more details, see:
-			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/every
-			// example:
-			//	|	// returns false
-			//	|	dojo.every([1, 2, 3, 4], function(item){ return item>1; });
-			// example:
-			//	|	// returns true 
-			//	|	dojo.every([1, 2, 3, 4], function(item){ return item>0; });
-			return everyOrSome(true, arr, callback, thisObject); // Boolean
-		},
-
-		some: function(/*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
-			// summary:
-			//		Determines whether or not any item in arr satisfies the
-			//		condition implemented by callback.
-			// arr:
-			//		the array to iterate over. If a string, operates on individual characters.
-			// callback:
-			//		a function is invoked with three arguments: item, index,
-			//		and array and returns true if the condition is met.
-			// thisObject:
-			//		may be used to scope the call to callback
-			// description:
-			//		This function corresponds to the JavaScript 1.6 Array.some() method, with one difference: when 
-			//		run over sparse arrays, this implemenation passes the "holes" in the sparse array to
-			//		the callback function with a value of undefined. JavaScript 1.6's some skips the holes in the sparse array.
-			//		For more details, see:
-			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/some
-			// example:
-			//	|	// is true
-			//	|	dojo.some([1, 2, 3, 4], function(item){ return item>1; });
-			// example:
-			//	|	// is false
-			//	|	dojo.some([1, 2, 3, 4], function(item){ return item<1; });
-			return everyOrSome(false, arr, callback, thisObject); // Boolean
-		},
-
-		map: function(/*Array|String*/arr, /*Function|String*/callback, /*Function?*/thisObject){
-			// summary:
-			//		applies callback to each element of arr and returns
-			//		an Array with the results
-			// arr:
-			//		the array to iterate on. If a string, operates on
-			//		individual characters.
-			// callback:
-			//		a function is invoked with three arguments, (item, index,
-			//		array),  and returns a value
-			// thisObject:
-			//		may be used to scope the call to callback
-			// description:
-			//		This function corresponds to the JavaScript 1.6 Array.map() method, with one difference: when 
-			//		run over sparse arrays, this implemenation passes the "holes" in the sparse array to
-			//		the callback function with a value of undefined. JavaScript 1.6's map skips the holes in the sparse array.
-			//		For more details, see:
-			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
-			// example:
-			//	|	// returns [2, 3, 4, 5]
-			//	|	dojo.map([1, 2, 3, 4], function(item){ return item+1 });
-
-			var _p = _getParts(arr, thisObject, callback); arr = _p[0];
-			var outArr = (arguments[3] ? (new arguments[3]()) : []);
-			for(var i=0,l=arr.length; i<l; ++i){
-				outArr.push(_p[2].call(_p[1], arr[i], i, arr));
-			}
-			return outArr; // Array
-		},
-
-		filter: function(/*Array*/arr, /*Function|String*/callback, /*Object?*/thisObject){
-			// summary:
-			//		Returns a new Array with those items from arr that match the
-			//		condition implemented by callback.
-			// arr:
-			//		the array to iterate over.
-			// callback:
-			//		a function that is invoked with three arguments (item,
-			//		index, array). The return of this function is expected to
-			//		be a boolean which determines whether the passed-in item
-			//		will be included in the returned array.
-			// thisObject:
-			//		may be used to scope the call to callback
-			// description:
-			//		This function corresponds to the JavaScript 1.6 Array.filter() method, with one difference: when 
-			//		run over sparse arrays, this implemenation passes the "holes" in the sparse array to
-			//		the callback function with a value of undefined. JavaScript 1.6's filter skips the holes in the sparse array. 
-			//		For more details, see:
-			//			https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
-			// example:
-			//	|	// returns [2, 3, 4]
-			//	|	dojo.filter([1, 2, 3, 4], function(item){ return item>1; });
-
-			var _p = _getParts(arr, thisObject, callback); arr = _p[0];
-			var outArr = [];
-			for(var i=0,l=arr.length; i<l; ++i){
-				if(_p[2].call(_p[1], arr[i], i, arr)){
-					outArr.push(arr[i]);
-				}
-			}
-			return outArr; // Array
-		}
-	});
-})();
-/*
-*/
-
-}
-
-if(!dojo._hasResource["dojo._base.declare"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.declare"] = true;
-dojo.provide("dojo._base.declare");
-
-
-
-
-(function(){
-	var d = dojo, mix = d._mixin, op = Object.prototype, opts = op.toString,
-		xtor = new Function, counter = 0, cname = "constructor";
-
-	function err(msg){ throw new Error("declare: " + msg); }
-
-	// C3 Method Resolution Order (see http://www.python.org/download/releases/2.3/mro/)
-	function c3mro(bases){
-		var result = [], roots = [{cls: 0, refs: []}], nameMap = {}, clsCount = 1,
-			l = bases.length, i = 0, j, lin, base, top, proto, rec, name, refs;
-
-		// build a list of bases naming them if needed
-		for(; i < l; ++i){
-			base = bases[i];
-			if(!base){
-				err("mixin #" + i + " is null");
-			}
-			lin = base._meta ? base._meta.bases : [base];
-			top = 0;
-			// add bases to the name map
-			for(j = lin.length - 1; j >= 0; --j){
-				proto = lin[j].prototype;
-				if(!proto.hasOwnProperty("declaredClass")){
-					proto.declaredClass = "uniqName_" + (counter++);
-				}
-				name = proto.declaredClass;
-				if(!nameMap.hasOwnProperty(name)){
-					nameMap[name] = {count: 0, refs: [], cls: lin[j]};
-					++clsCount;
-				}
-				rec = nameMap[name];
-				if(top && top !== rec){
-					rec.refs.push(top);
-					++top.count;
-				}
-				top = rec;
-			}
-			++top.count;
-			roots[0].refs.push(top);
-		}
-
-		// remove classes without external references recursively
-		while(roots.length){
-			top = roots.pop();
-			result.push(top.cls);
-			--clsCount;
-			// optimization: follow a single-linked chain
-			while(refs = top.refs, refs.length == 1){
-				top = refs[0];
-				if(!top || --top.count){
-					// branch or end of chain => do not end to roots
-					top = 0;
-					break;
-				}
-				result.push(top.cls);
-				--clsCount;
-			}
-			if(top){
-				// branch
-				for(i = 0, l = refs.length; i < l; ++i){
-					top = refs[i];
-					if(!--top.count){
-						roots.push(top);
-					}
-				}
-			}
-		}
-		if(clsCount){
-			err("can't build consistent linearization");
-		}
-
-		// calculate the superclass offset
-		base = bases[0];
-		result[0] = base ?
-			base._meta && base === result[result.length - base._meta.bases.length] ?
-				base._meta.bases.length : 1 : 0;
-
-		return result;
-	}
-
-	function inherited(args, a, f){
-		var name, chains, bases, caller, meta, base, proto, opf, pos,
-			cache = this._inherited = this._inherited || {};
-
-		// crack arguments
-		if(typeof args == "string"){
-			name = args;
-			args = a;
-			a = f;
-		}
-		f = 0;
-
-		caller = args.callee;
-		name = name || caller.nom;
-		if(!name){
-			err("can't deduce a name to call inherited()");
-		}
-
-		meta = this.constructor._meta;
-		bases = meta.bases;
-
-		pos = cache.p;
-		if(name != cname){
-			// method
-			if(cache.c !== caller){
-				// cache bust
-				pos = 0;
-				base = bases[0];
-				meta = base._meta;
-				if(meta.hidden[name] !== caller){
-					// error detection
-					chains = meta.chains;
-					if(chains && typeof chains[name] == "string"){
-						err("calling chained method with inherited: " + name);
-					}
-					// find caller
-					do{
-						meta = base._meta;
-						proto = base.prototype;
-						if(meta && (proto[name] === caller && proto.hasOwnProperty(name) || meta.hidden[name] === caller)){
-							break;
-						}
-					}while(base = bases[++pos]); // intentional assignment
-					pos = base ? pos : -1;
-				}
-			}
-			// find next
-			base = bases[++pos];
-			if(base){
-				proto = base.prototype;
-				if(base._meta && proto.hasOwnProperty(name)){
-					f = proto[name];
-				}else{
-					opf = op[name];
-					do{
-						proto = base.prototype;
-						f = proto[name];
-						if(f && (base._meta ? proto.hasOwnProperty(name) : f !== opf)){
-							break;
-						}
-					}while(base = bases[++pos]); // intentional assignment
-				}
-			}
-			f = base && f || op[name];
-		}else{
-			// constructor
-			if(cache.c !== caller){
-				// cache bust
-				pos = 0;
-				meta = bases[0]._meta;
-				if(meta && meta.ctor !== caller){
-					// error detection
-					chains = meta.chains;
-					if(!chains || chains.constructor !== "manual"){
-						err("calling chained constructor with inherited");
-					}
-					// find caller
-					while(base = bases[++pos]){ // intentional assignment
-						meta = base._meta;
-						if(meta && meta.ctor === caller){
-							break;
-						}
-					};
-					pos = base ? pos : -1;
-				}
-			}
-			// find next
-			while(base = bases[++pos]){	// intentional assignment
-				meta = base._meta;
-				f = meta ? meta.ctor : base;
-				if(f){
-					break;
-				}
-			}
-			f = base && f;
-		}
-
-		// cache the found super method
-		cache.c = f;
-		cache.p = pos;
-
-		// now we have the result
-		if(f){
-			return a === true ? f : f.apply(this, a || args);
-		}
-		// intentionally if a super method was not found
-	}
-
-	function getInherited(name, args){
-		if(typeof name == "string"){
-			return this.inherited(name, args, true);
-		}
-		return this.inherited(name, true);
-	}
-
-	// emulation of "instanceof"
-	function isInstanceOf(cls){
-		var bases = this.constructor._meta.bases;
-		for(var i = 0, l = bases.length; i < l; ++i){
-			if(bases[i] === cls){
-				return true;
-			}
-		}
-		return this instanceof cls;
-	}
-
-	// imlementation of safe mixin function
-	function safeMixin(target, source){
-		var name, t, i = 0, l = d._extraNames.length;
-		// add props adding metadata for incoming functions skipping a constructor
-		for(name in source){
-			t = source[name];
-			if((t !== op[name] || !(name in op)) && name != cname){
-				if(opts.call(t) == "[object Function]"){
-					// non-trivial function method => attach its name
-					t.nom = name;
-				}
-				target[name] = t;
-			}
-		}
-		// process unenumerable methods on IE
-		for(; i < l; ++i){
-			name = d._extraNames[i];
-			t = source[name];
-			if((t !== op[name] || !(name in op)) && name != cname){
-				if(opts.call(t) == "[object Function]"){
-					// non-trivial function method => attach its name
-					t.nom = name;
-				}
-				target[name] = t;
-			}
-		}
-		return target;
-	}
-
-	function extend(source){
-		safeMixin(this.prototype, source);
-		return this;
-	}
-
-	// chained constructor compatible with the legacy dojo.declare()
-	function chainedConstructor(bases, ctorSpecial){
-		return function(){
-			var a = arguments, args = a, a0 = a[0], f, i, m,
-				l = bases.length, preArgs;
-			//this._inherited = {};
-			// perform the shaman's rituals of the original dojo.declare()
-			// 1) call two types of the preamble
-			if(ctorSpecial && (a0 && a0.preamble || this.preamble)){
-				// full blown ritual
-				preArgs = new Array(bases.length);
-				// prepare parameters
-				preArgs[0] = a;
-				for(i = 0;;){
-					// process the preamble of the 1st argument
-					a0 = a[0];
-					if(a0){
-						f = a0.preamble;
-						if(f){
-							a = f.apply(this, a) || a;
-						}
-					}
-					// process the preamble of this class
-					f = bases[i].prototype;
-					f = f.hasOwnProperty("preamble") && f.preamble;
-					if(f){
-						a = f.apply(this, a) || a;
-					}
-					// one pecularity of the preamble:
-					// it is called if it is not needed,
-					// e.g., there is no constructor to call
-					// let's watch for the last constructor
-					// (see ticket #9795)
-					if(++i == l){
-						break;
-					}
-					preArgs[i] = a;
-				}
-			}
-			// 2) call all non-trivial constructors using prepared arguments
-			for(i = l - 1; i >= 0; --i){
-				f = bases[i];
-				m = f._meta;
-				f = m ? m.ctor : f;
-				if(f){
-					f.apply(this, preArgs ? preArgs[i] : a);
-				}
-			}
-			// 3) continue the original ritual: call the postscript
-			f = this.postscript;
-			if(f){
-				f.apply(this, args);
-			}
-		};
-	}
-
-
-	// chained constructor compatible with the legacy dojo.declare()
-	function singleConstructor(ctor, ctorSpecial){
-		return function(){
-			var a = arguments, t = a, a0 = a[0], f;
-			//this._inherited = {};
-			// perform the shaman's rituals of the original dojo.declare()
-			// 1) call two types of the preamble
-			if(ctorSpecial){
-				// full blown ritual
-				if(a0){
-					// process the preamble of the 1st argument
-					f = a0.preamble;
-					if(f){
-						t = f.apply(this, t) || t;
-					}
-				}
-				f = this.preamble;
-				if(f){
-					// process the preamble of this class
-					f.apply(this, t);
-					// one pecularity of the preamble:
-					// it is called even if it is not needed,
-					// e.g., there is no constructor to call
-					// let's watch for the last constructor
-					// (see ticket #9795)
-				}
-			}
-			// 2) call a constructor
-			if(ctor){
-				ctor.apply(this, a);
-			}
-			// 3) continue the original ritual: call the postscript
-			f = this.postscript;
-			if(f){
-				f.apply(this, a);
-			}
-		};
-	}
-
-	// plain vanilla constructor (can use inherited() to call its base constructor)
-	function simpleConstructor(bases){
-		return function(){
-			var a = arguments, i = 0, f;
-			//this._inherited = {};
-			// perform the shaman's rituals of the original dojo.declare()
-			// 1) do not call the preamble
-			// 2) call the top constructor (it can use this.inherited())
-			for(; f = bases[i]; ++i){ // intentional assignment
-				m = f._meta;
-				f = m ? m.ctor : f;
-				if(f){
-					f.apply(this, a);
-					break;
-				}
-			}
-			// 3) call the postscript
-			f = this.postscript;
-			if(f){
-				f.apply(this, a);
-			}
-		};
-	}
-
-	function chain(name, bases, reversed){
-		return function(){
-			var b, m, f, i = 0, step = 1;
-			if(reversed){
-				i = bases.length - 1;
-				step = -1;
-			}
-			for(; b = bases[i]; i += step){ // intentional assignment
-				m = b._meta;
-				f = (m ? m.hidden : b.prototype)[name];
-				if(f){
-					f.apply(this, arguments);
-				}
-			}
-		};
-	}
-
-	d.declare = function(className, superclass, props){
-		var proto, i, t, ctor, name, bases, chains, mixins = 1, parents = superclass;
-
-		// crack parameters
-		if(typeof className != "string"){
-			props = superclass;
-			superclass = className;
-			className = "";
-		}
-		props = props || {};
-
-		// build a prototype
-		if(opts.call(superclass) == "[object Array]"){
-			// C3 MRO
-			bases = c3mro(superclass);
-			t = bases[0];
-			mixins = bases.length - t;
-			superclass = bases[mixins];
-		}else{
-			bases = [0];
-			if(superclass){
-				t = superclass._meta;
-				bases = bases.concat(t ? t.bases : superclass);
-			}
-		}
-		if(superclass){
-			for(i = mixins - 1;; --i){
-				// delegation
-				xtor.prototype = superclass.prototype;
-				proto = new xtor;
-				if(!i){
-					// stop if nothing to add (the last base)
-					break;
-				}
-				// mix in properties
-				t = bases[i];
-				mix(proto, t._meta ? t._meta.hidden : t.prototype);
-				// chain in new constructor
-				ctor = new Function;
-				ctor.superclass = superclass;
-				ctor.prototype = proto;
-				superclass = proto.constructor = ctor;
-			}
-		}else{
-			proto = {};
-		}
-		// add all properties
-		safeMixin(proto, props);
-		// add constructor
-		t = props.constructor;
-		if(t !== op.constructor){
-			t.nom = cname;
-			proto.constructor = t;
-		}
-		xtor.prototype = 0;	// cleanup
-
-		// collect chains and flags
-		for(i = mixins - 1; i; --i){ // intentional assignment
-			t = bases[i]._meta;
-			if(t && t.chains){
-				chains = mix(chains || {}, t.chains);
-			}
-		}
-		if(proto["-chains-"]){
-			chains = mix(chains || {}, proto["-chains-"]);
-		}
-
-		// build ctor
-		t = !chains || !chains.hasOwnProperty(cname);
-		bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) :
-			(bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t));
-
-		// add meta information to the constructor
-		ctor._meta  = {bases: bases, hidden: props, chains: chains,
-			parents: parents, ctor: props.constructor};
-		ctor.superclass = superclass && superclass.prototype;
-		ctor.extend = extend;
-		ctor.prototype = proto;
-		proto.constructor = ctor;
-
-		// add "standard" methods to the ptototype
-		proto.getInherited = getInherited;
-		proto.inherited = inherited;
-		proto.isInstanceOf = isInstanceOf;
-
-		// add name if specified
-		if(className){
-			proto.declaredClass = className;
-			d.setObject(className, ctor);
-		}
-
-		// build chains and add them to the prototype
-		if(chains){
-			for(name in chains){
-				if(proto[name] && typeof chains[name] == "string" && name != cname){
-					t = proto[name] = chain(name, bases, chains[name] === "after");
-					t.nom = name;
-				}
-			}
-		}
-		// chained methods do not return values
-		// no need to chain "invisible" functions
-
-		return ctor;	// Function
-	};
-
-	d.safeMixin = safeMixin;
-
-	/*=====
-	dojo.declare = function(className, superclass, props){
-		//	summary:
-		//		Create a feature-rich constructor from compact notation.
-		//	className: String?:
-		//		The optional name of the constructor (loosely, a "class")
-		//		stored in the "declaredClass" property in the created prototype.
-		//		It will be used as a global name for a created constructor.
-		//	superclass: Function|Function[]:
-		//		May be null, a Function, or an Array of Functions. This argument
-		//		specifies a list of bases (the left-most one is the most deepest
-		//		base).
-		//	props: Object:
-		//		An object whose properties are copied to the created prototype.
-		//		Add an instance-initialization function by making it a property
-		//		named "constructor".
-		//	returns:
-		//		New constructor function.
-		//	description:
-		//		Create a constructor using a compact notation for inheritance and
-		//		prototype extension.
-		//
-		//		Mixin ancestors provide a type of multiple inheritance.
-		//		Prototypes of mixin ancestors are copied to the new class:
-		//		changes to mixin prototypes will not affect classes to which
-		//		they have been mixed in.
-		//
-		//		Ancestors can be compound classes created by this version of
-		//		dojo.declare. In complex cases all base classes are going to be
-		//		linearized according to C3 MRO algorithm
-		//		(see http://www.python.org/download/releases/2.3/mro/ for more
-		//		details).
-		//
-		//		"className" is cached in "declaredClass" property of the new class,
-		//		if it was supplied. The immediate super class will be cached in
-		//		"superclass" property of the new class.
-		//
-		//		Methods in "props" will be copied and modified: "nom" property
-		//		(the declared name of the method) will be added to all copied
-		//		functions to help identify them for the internal machinery. Be
-		//		very careful, while reusing methods: if you use the same
-		//		function under different names, it can produce errors in some
-		//		cases.
-		//
-		//		It is possible to use constructors created "manually" (without
-		//		dojo.declare) as bases. They will be called as usual during the
-		//		creation of an instance, their methods will be chained, and even
-		//		called by "this.inherited()".
-		//
-		//		Special property "-chains-" governs how to chain methods. It is
-		//		a dictionary, which uses method names as keys, and hint strings
-		//		as values. If a hint string is "after", this method will be
-		//		called after methods of its base classes. If a hint string is
-		//		"before", this method will be called before methods of its base
-		//		classes.
-		//
-		//		If "constructor" is not mentioned in "-chains-" property, it will
-		//		be chained using the legacy mode: using "after" chaining,
-		//		calling preamble() method before each constructor, if available,
-		//		and calling postscript() after all constructors were executed.
-		//		If the hint is "after", it is chained as a regular method, but
-		//		postscript() will be called after the chain of constructors.
-		//		"constructor" cannot be chained "before", but it allows
-		//		a special hint string: "manual", which means that constructors
-		//		are not going to be chained in any way, and programmer will call
-		//		them manually using this.inherited(). In the latter case
-		//		postscript() will be called after the construction.
-		//
-		//		All chaining hints are "inherited" from base classes and
-		//		potentially can be overridden. Be very careful when overriding
-		//		hints! Make sure that all chained methods can work in a proposed
-		//		manner of chaining.
-		//
-		//		Once a method was chained, it is impossible to unchain it. The
-		//		only exception is "constructor". You don't need to define a
-		//		method in order to supply a chaining hint.
-		//
-		//		If a method is chained, it cannot use this.inherited() because
-		//		all other methods in the hierarchy will be called automatically.
-		//
-		//		Usually constructors and initializers of any kind are chained
-		//		using "after" and destructors of any kind are chained as
-		//		"before". Note that chaining assumes that chained methods do not
-		//		return any value: any returned value will be discarded.
-		//
-		//	example:
-		//	|	dojo.declare("my.classes.bar", my.classes.foo, {
-		//	|		// properties to be added to the class prototype
-		//	|		someValue: 2,
-		//	|		// initialization function
-		//	|		constructor: function(){
-		//	|			this.myComplicatedObject = new ReallyComplicatedObject();
-		//	|		},
-		//	|		// other functions
-		//	|		someMethod: function(){
-		//	|			doStuff();
-		//	|		}
-		//	|	});
-		//
-		//	example:
-		//	|	var MyBase = dojo.declare(null, {
-		//	|		// constructor, properties, and methods go here
-		//	|		// ...
-		//	|	});
-		//	|	var MyClass1 = dojo.declare(MyBase, {
-		//	|		// constructor, properties, and methods go here
-		//	|		// ...
-		//	|	});
-		//	|	var MyClass2 = dojo.declare(MyBase, {
-		//	|		// constructor, properties, and methods go here
-		//	|		// ...
-		//	|	});
-		//	|	var MyDiamond = dojo.declare([MyClass1, MyClass2], {
-		//	|		// constructor, properties, and methods go here
-		//	|		// ...
-		//	|	});
-		//
-		//	example:
-		//	|	var F = function(){ console.log("raw constructor"); };
-		//	|	F.prototype.method = function(){
-		//	|		console.log("raw method");
-		//	|	};
-		//	|	var A = dojo.declare(F, {
-		//	|		constructor: function(){
-		//	|			console.log("A.constructor");
-		//	|		},
-		//	|		method: function(){
-		//	|			console.log("before calling F.method...");
-		//	|			this.inherited(arguments);
-		//	|			console.log("...back in A");
-		//	|		}
-		//	|	});
-		//	|	new A().method();
-		//	|	// will print:
-		//	|	// raw constructor
-		//	|	// A.constructor
-		//	|	// before calling F.method...
-		//	|	// raw method
-		//	|	// ...back in A
-		//
-		//	example:
-		//	|	var A = dojo.declare(null, {
-		//	|		"-chains-": {
-		//	|			destroy: "before"
-		//	|		}
-		//	|	});
-		//	|	var B = dojo.declare(A, {
-		//	|		constructor: function(){
-		//	|			console.log("B.constructor");
-		//	|		},
-		//	|		destroy: function(){
-		//	|			console.log("B.destroy");
-		//	|		}
-		//	|	});
-		//	|	var C = dojo.declare(B, {
-		//	|		constructor: function(){
-		//	|			console.log("C.constructor");
-		//	|		},
-		//	|		destroy: function(){
-		//	|			console.log("C.destroy");
-		//	|		}
-		//	|	});
-		//	|	new C().destroy();
-		//	|	// prints:
-		//	|	// B.constructor
-		//	|	// C.constructor
-		//	|	// C.destroy
-		//	|	// B.destroy
-		//
-		//	example:
-		//	|	var A = dojo.declare(null, {
-		//	|		"-chains-": {
-		//	|			constructor: "manual"
-		//	|		}
-		//	|	});
-		//	|	var B = dojo.declare(A, {
-		//	|		constructor: function(){
-		//	|			// ...
-		//	|			// call the base constructor with new parameters
-		//	|			this.inherited(arguments, [1, 2, 3]);
-		//	|			// ...
-		//	|		}
-		//	|	});
-		//
-		//	example:
-		//	|	var A = dojo.declare(null, {
-		//	|		"-chains-": {
-		//	|			m1: "before"
-		//	|		},
-		//	|		m1: function(){
-		//	|			console.log("A.m1");
-		//	|		},
-		//	|		m2: function(){
-		//	|			console.log("A.m2");
-		//	|		}
-		//	|	});
-		//	|	var B = dojo.declare(A, {
-		//	|		"-chains-": {
-		//	|			m2: "after"
-		//	|		},
-		//	|		m1: function(){
-		//	|			console.log("B.m1");
-		//	|		},
-		//	|		m2: function(){
-		//	|			console.log("B.m2");
-		//	|		}
-		//	|	});
-		//	|	var x = new B();
-		//	|	x.m1();
-		//	|	// prints:
-		//	|	// B.m1
-		//	|	// A.m1
-		//	|	x.m2();
-		//	|	// prints:
-		//	|	// A.m2
-		//	|	// B.m2
-		return new Function(); // Function
-	};
-	=====*/
-
-	/*=====
-	dojo.safeMixin = function(target, source){
-		//	summary:
-		//		Mix in properties skipping a constructor and decorating functions
-		//		like it is done by dojo.declare.
-		//	target: Object
-		//		Target object to accept new properties.
-		//	source: Object
-		//		Source object for new properties.
-		//	description:
-		//		This function is used to mix in properties like dojo._mixin does,
-		//		but it skips a constructor property and decorates functions like
-		//		dojo.declare does.
-		//
-		//		It is meant to be used with classes and objects produced with
-		//		dojo.declare. Functions mixed in with dojo.safeMixin can use
-		//		this.inherited() like normal methods.
-		//
-		//		This function is used to implement extend() method of a constructor
-		//		produced with dojo.declare().
-		//
-		//	example:
-		//	|	var A = dojo.declare(null, {
-		//	|		m1: function(){
-		//	|			console.log("A.m1");
-		//	|		},
-		//	|		m2: function(){
-		//	|			console.log("A.m2");
-		//	|		}
-		//	|	});
-		//	|	var B = dojo.declare(A, {
-		//	|		m1: function(){
-		//	|			this.inherited(arguments);
-		//	|			console.log("B.m1");
-		//	|		}
-		//	|	});
-		//	|	B.extend({
-		//	|		m2: function(){
-		//	|			this.inherited(arguments);
-		//	|			console.log("B.m2");
-		//	|		}
-		//	|	});
-		//	|	var x = new B();
-		//	|	dojo.safeMixin(x, {
-		//	|		m1: function(){
-		//	|			this.inherited(arguments);
-		//	|			console.log("X.m1");
-		//	|		},
-		//	|		m2: function(){
-		//	|			this.inherited(arguments);
-		//	|			console.log("X.m2");
-		//	|		}
-		//	|	});
-		//	|	x.m2();
-		//	|	// prints:
-		//	|	// A.m1
-		//	|	// B.m1
-		//	|	// X.m1
-	};
-	=====*/
-
-	/*=====
-	Object.inherited = function(name, args, newArgs){
-		//	summary:
-		//		Calls a super method.
-		//	name: String?
-		//		The optional method name. Should be the same as the caller's
-		//		name. Usually "name" is specified in complex dynamic cases, when
-		//		the calling method was dynamically added, undecorated by
-		//		dojo.declare, and it cannot be determined.
-		//	args: Arguments
-		//		The caller supply this argument, which should be the original
-		//		"arguments".
-		//	newArgs: Object?
-		//		If "true", the found function will be returned without
-		//		executing it.
-		//		If Array, it will be used to call a super method. Otherwise
-		//		"args" will be used.
-		//	returns:
-		//		Whatever is returned by a super method, or a super method itself,
-		//		if "true" was specified as newArgs.
-		//	description:
-		//		This method is used inside method of classes produced with
-		//		dojo.declare to call a super method (next in the chain). It is
-		//		used for manually controlled chaining. Consider using the regular
-		//		chaining, because it is faster. Use "this.inherited()" only in
-		//		complex cases.
-		//
-		//		This method cannot me called from automatically chained
-		//		constructors including the case of a special (legacy)
-		//		constructor chaining. It cannot be called from chained methods.
-		//
-		//		If "this.inherited()" cannot find the next-in-chain method, it
-		//		does nothing and returns "undefined". The last method in chain
-		//		can be a default method implemented in Object, which will be
-		//		called last.
-		//
-		//		If "name" is specified, it is assumed that the method that
-		//		received "args" is the parent method for this call. It is looked
-		//		up in the chain list and if it is found the next-in-chain method
-		//		is called. If it is not found, the first-in-chain method is
-		//		called.
-		//
-		//		If "name" is not specified, it will be derived from the calling
-		//		method (using a methoid property "nom").
-		//
-		//	example:
-		//	|	var B = dojo.declare(A, {
-		//	|		method1: function(a, b, c){
-		//	|			this.inherited(arguments);
-		//	|		},
-		//	|		method2: function(a, b){
-		//	|			return this.inherited(arguments, [a + b]);
-		//	|		}
-		//	|	});
-		//	|	// next method is not in the chain list because it is added
-		//	|	// manually after the class was created.
-		//	|	B.prototype.method3 = function(){
-		//	|		console.log("This is a dynamically-added method.");
-		//	|		this.inherited("method3", arguments);
-		//	|	};
-		//	example:
-		//	|	var B = dojo.declare(A, {
-		//	|		method: function(a, b){
-		//	|			var super = this.inherited(arguments, true);
-		//	|			// ...
-		//	|			if(!super){
-		//	|				console.log("there is no super method");
-		//	|				return 0;
-		//	|			}
-		//	|			return super.apply(this, arguments);
-		//	|		}
-		//	|	});
-		return	{};	// Object
-	}
-	=====*/
-
-	/*=====
-	Object.getInherited = function(name, args){
-		//	summary:
-		//		Returns a super method.
-		//	name: String?
-		//		The optional method name. Should be the same as the caller's
-		//		name. Usually "name" is specified in complex dynamic cases, when
-		//		the calling method was dynamically added, undecorated by
-		//		dojo.declare, and it cannot be determined.
-		//	args: Arguments
-		//		The caller supply this argument, which should be the original
-		//		"arguments".
-		//	returns:
-		//		Returns a super method (Function) or "undefined".
-		//	description:
-		//		This method is a convenience method for "this.inherited()".
-		//		It uses the same algorithm but instead of executing a super
-		//		method, it returns it, or "undefined" if not found.
-		//
-		//	example:
-		//	|	var B = dojo.declare(A, {
-		//	|		method: function(a, b){
-		//	|			var super = this.getInherited(arguments);
-		//	|			// ...
-		//	|			if(!super){
-		//	|				console.log("there is no super method");
-		//	|				return 0;
-		//	|			}
-		//	|			return super.apply(this, arguments);
-		//	|		}
-		//	|	});
-		return	{};	// Object
-	}
-	=====*/
-
-	/*=====
-	Object.isInstanceOf = function(cls){
-		//	summary:
-		//		Checks the inheritance cahin to see if it is inherited from this
-		//		class.
-		//	cls: Function
-		//		Class constructor.
-		//	returns:
-		//		"true", if this object is inherited from this class, "false"
-		//		otherwise.
-		//	description:
-		//		This method is used with instances of classes produced with
-		//		dojo.declare to determine of they support a certain interface or
-		//		not. It models "instanceof" operator.
-		//
-		//	example:
-		//	|	var A = dojo.declare(null, {
-		//	|		// constructor, properties, and methods go here
-		//	|		// ...
-		//	|	});
-		//	|	var B = dojo.declare(null, {
-		//	|		// constructor, properties, and methods go here
-		//	|		// ...
-		//	|	});
-		//	|	var C = dojo.declare([A, B], {
-		//	|		// constructor, properties, and methods go here
-		//	|		// ...
-		//	|	});
-		//	|	var D = dojo.declare(A, {
-		//	|		// constructor, properties, and methods go here
-		//	|		// ...
-		//	|	});
-		//	|
-		//	|	var a = new A(), b = new B(), c = new C(), d = new D();
-		//	|
-		//	|	console.log(a.isInstanceOf(A)); // true
-		//	|	console.log(b.isInstanceOf(A)); // false
-		//	|	console.log(c.isInstanceOf(A)); // true
-		//	|	console.log(d.isInstanceOf(A)); // true
-		//	|
-		//	|	console.log(a.isInstanceOf(B)); // false
-		//	|	console.log(b.isInstanceOf(B)); // true
-		//	|	console.log(c.isInstanceOf(B)); // true
-		//	|	console.log(d.isInstanceOf(B)); // false
-		//	|
-		//	|	console.log(a.isInstanceOf(C)); // false
-		//	|	console.log(b.isInstanceOf(C)); // false
-		//	|	console.log(c.isInstanceOf(C)); // true
-		//	|	console.log(d.isInstanceOf(C)); // false
-		//	|
-		//	|	console.log(a.isInstanceOf(D)); // false
-		//	|	console.log(b.isInstanceOf(D)); // false
-		//	|	console.log(c.isInstanceOf(D)); // false
-		//	|	console.log(d.isInstanceOf(D)); // true
-		return	{};	// Object
-	}
-	=====*/
-
-	/*=====
-	Object.extend = function(source){
-		//	summary:
-		//		Adds all properties and methods of source to constructor's
-		//		prototype, making them available to all instances created with
-		//		constructor. This method is specific to constructors created with
-		//		dojo.declare.
-		//	source: Object
-		//		Source object which properties are going to be copied to the
-		//		constructor's prototype.
-		//	description:
-		//		Adds source properties to the constructor's prototype. It can
-		//		override existing properties.
-		//
-		//		This method is similar to dojo.extend function, but it is specific
-		//		to constructors produced by dojo.declare. It is implemented
-		//		using dojo.safeMixin, and it skips a constructor property,
-		//		and properly decorates copied functions.
-		//
-		//	example:
-		//	|	var A = dojo.declare(null, {
-		//	|		m1: function(){},
-		//	|		s1: "Popokatepetl"
-		//	|	});
-		//	|	A.extend({
-		//	|		m1: function(){},
-		//	|		m2: function(){},
-		//	|		f1: true,
-		//	|		d1: 42
-		//	|	});
-	};
-	=====*/
-})();
-
-}
-
-if(!dojo._hasResource["dojo._base.connect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.connect"] = true;
-dojo.provide("dojo._base.connect");
-
-
-// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
-
-// low-level delegation machinery
-dojo._listener = {
-	// create a dispatcher function
-	getDispatcher: function(){
-		// following comments pulled out-of-line to prevent cloning them 
-		// in the returned function.
-		// - indices (i) that are really in the array of listeners (ls) will 
-		//   not be in Array.prototype. This is the 'sparse array' trick
-		//   that keeps us safe from libs that take liberties with built-in 
-		//   objects
-		// - listener is invoked with current scope (this)
-		return function(){
-			var ap=Array.prototype, c=arguments.callee, ls=c._listeners, t=c.target;
-			// return value comes from original target function
-			var r = t && t.apply(this, arguments);
-			// make local copy of listener array so it is immutable during processing
-			var lls;
-											lls = [].concat(ls);
-							
-			// invoke listeners after target function
-			for(var i in lls){
-				if(!(i in ap)){
-					lls[i].apply(this, arguments);
-				}
-			}
-			// return value comes from original target function
-			return r;
-		}
-	},
-	// add a listener to an object
-	add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
-		// Whenever 'method' is invoked, 'listener' will have the same scope.
-		// Trying to supporting a context object for the listener led to 
-		// complexity. 
-		// Non trivial to provide 'once' functionality here
-		// because listener could be the result of a dojo.hitch call,
-		// in which case two references to the same hitch target would not
-		// be equivalent. 
-		source = source || dojo.global;
-		// The source method is either null, a dispatcher, or some other function
-		var f = source[method];
-		// Ensure a dispatcher
-		if(!f||!f._listeners){
-			var d = dojo._listener.getDispatcher();
-			// original target function is special
-			d.target = f;
-			// dispatcher holds a list of listeners
-			d._listeners = []; 
-			// redirect source to dispatcher
-			f = source[method] = d;
-		}
-		// The contract is that a handle is returned that can 
-		// identify this listener for disconnect. 
-		//
-		// The type of the handle is private. Here is it implemented as Integer. 
-		// DOM event code has this same contract but handle is Function 
-		// in non-IE browsers.
-		//
-		// We could have separate lists of before and after listeners.
-		return f._listeners.push(listener) ; /*Handle*/
-	},
-	// remove a listener from an object
-	remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
-		var f = (source||dojo.global)[method];
-		// remember that handle is the index+1 (0 is not a valid handle)
-		if(f && f._listeners && handle--){
-			delete f._listeners[handle];
-		}
-	}
-};
-
-// Multiple delegation for arbitrary methods.
-
-// This unit knows nothing about DOM, but we include DOM aware documentation
-// and dontFix argument here to help the autodocs. Actual DOM aware code is in
-// event.js.
-
-dojo.connect = function(/*Object|null*/ obj, 
-						/*String*/ event, 
-						/*Object|null*/ context, 
-						/*String|Function*/ method,
-						/*Boolean?*/ dontFix){
-	// summary:
-	//		`dojo.connect` is the core event handling and delegation method in
-	//		Dojo. It allows one function to "listen in" on the execution of
-	//		any other, triggering the second whenever the first is called. Many
-	//		listeners may be attached to a function, and source functions may
-	//		be either regular function calls or DOM events.
-	//
-	// description:
-	//		Connects listeners to actions, so that after event fires, a
-	//		listener is called with the same arguments passed to the orginal
-	//		function.
-	//
-	//		Since `dojo.connect` allows the source of events to be either a
-	//		"regular" JavaScript function or a DOM event, it provides a uniform
-	//		interface for listening to all the types of events that an
-	//		application is likely to deal with though a single, unified
-	//		interface. DOM programmers may want to think of it as
-	//		"addEventListener for everything and anything".
-	//
-	//		When setting up a connection, the `event` parameter must be a
-	//		string that is the name of the method/event to be listened for. If
-	//		`obj` is null, `dojo.global` is assumed, meaning that connections
-	//		to global methods are supported but also that you may inadvertantly
-	//		connect to a global by passing an incorrect object name or invalid
-	//		reference.
-	//
-	//		`dojo.connect` generally is forgiving. If you pass the name of a
-	//		function or method that does not yet exist on `obj`, connect will
-	//		not fail, but will instead set up a stub method. Similarly, null
-	//		arguments may simply be omitted such that fewer than 4 arguments
-	//		may be required to set up a connection See the examples for deails.
-	//
-	//		The return value is a handle that is needed to 
-	//		remove this connection with `dojo.disconnect`.
-	//
-	// obj: 
-	//		The source object for the event function. 
-	//		Defaults to `dojo.global` if null.
-	//		If obj is a DOM node, the connection is delegated 
-	//		to the DOM event manager (unless dontFix is true).
-	//
-	// event:
-	//		String name of the event function in obj. 
-	//		I.e. identifies a property `obj[event]`.
-	//
-	// context: 
-	//		The object that method will receive as "this".
-	//
-	//		If context is null and method is a function, then method
-	//		inherits the context of event.
-	//	
-	//		If method is a string then context must be the source 
-	//		object object for method (context[method]). If context is null,
-	//		dojo.global is used.
-	//
-	// method:
-	//		A function reference, or name of a function in context. 
-	//		The function identified by method fires after event does. 
-	//		method receives the same arguments as the event.
-	//		See context argument comments for information on method's scope.
-	//
-	// dontFix:
-	//		If obj is a DOM node, set dontFix to true to prevent delegation 
-	//		of this connection to the DOM event manager.
-	//
-	// example:
-	//		When obj.onchange(), do ui.update():
-	//	|	dojo.connect(obj, "onchange", ui, "update");
-	//	|	dojo.connect(obj, "onchange", ui, ui.update); // same
-	//
-	// example:
-	//		Using return value for disconnect:
-	//	|	var link = dojo.connect(obj, "onchange", ui, "update");
-	//	|	...
-	//	|	dojo.disconnect(link);
-	//
-	// example:
-	//		When onglobalevent executes, watcher.handler is invoked:
-	//	|	dojo.connect(null, "onglobalevent", watcher, "handler");
-	//
-	// example:
-	//		When ob.onCustomEvent executes, customEventHandler is invoked:
-	//	|	dojo.connect(ob, "onCustomEvent", null, "customEventHandler");
-	//	|	dojo.connect(ob, "onCustomEvent", "customEventHandler"); // same
-	//
-	// example:
-	//		When ob.onCustomEvent executes, customEventHandler is invoked
-	//		with the same scope (this):
-	//	|	dojo.connect(ob, "onCustomEvent", null, customEventHandler);
-	//	|	dojo.connect(ob, "onCustomEvent", customEventHandler); // same
-	//
-	// example:
-	//		When globalEvent executes, globalHandler is invoked
-	//		with the same scope (this):
-	//	|	dojo.connect(null, "globalEvent", null, globalHandler);
-	//	|	dojo.connect("globalEvent", globalHandler); // same
-
-	// normalize arguments
-	var a=arguments, args=[], i=0;
-	// if a[0] is a String, obj was ommited
-	args.push(dojo.isString(a[0]) ? null : a[i++], a[i++]);
-	// if the arg-after-next is a String or Function, context was NOT omitted
-	var a1 = a[i+1];
-	args.push(dojo.isString(a1)||dojo.isFunction(a1) ? a[i++] : null, a[i++]);
-	// absorb any additional arguments
-	for(var l=a.length; i<l; i++){	args.push(a[i]); }
-	// do the actual work
-	return dojo._connect.apply(this, args); /*Handle*/
-}
-
-// used by non-browser hostenvs. always overriden by event.js
-dojo._connect = function(obj, event, context, method){
-	var l=dojo._listener, h=l.add(obj, event, dojo.hitch(context, method)); 
-	return [obj, event, h, l]; // Handle
-}
-
-dojo.disconnect = function(/*Handle*/ handle){
-	// summary:
-	//		Remove a link created by dojo.connect.
-	// description:
-	//		Removes the connection between event and the method referenced by handle.
-	// handle:
-	//		the return value of the dojo.connect call that created the connection.
-	if(handle && handle[0] !== undefined){
-		dojo._disconnect.apply(this, handle);
-		// let's not keep this reference
-		delete handle[0];
-	}
-}
-
-dojo._disconnect = function(obj, event, handle, listener){
-	listener.remove(obj, event, handle);
-}
-
-// topic publish/subscribe
-
-dojo._topics = {};
-
-dojo.subscribe = function(/*String*/ topic, /*Object|null*/ context, /*String|Function*/ method){
-	//	summary:
-	//		Attach a listener to a named topic. The listener function is invoked whenever the
-	//		named topic is published (see: dojo.publish).
-	//		Returns a handle which is needed to unsubscribe this listener.
-	//	context:
-	//		Scope in which method will be invoked, or null for default scope.
-	//	method:
-	//		The name of a function in context, or a function reference. This is the function that
-	//		is invoked when topic is published.
-	//	example:
-	//	|	dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); });
-	//	|	dojo.publish("alerts", [ "read this", "hello world" ]);																	
-
-	// support for 2 argument invocation (omitting context) depends on hitch
-	return [topic, dojo._listener.add(dojo._topics, topic, dojo.hitch(context, method))]; /*Handle*/
-}
-
-dojo.unsubscribe = function(/*Handle*/ handle){
-	//	summary:
-	//	 	Remove a topic listener. 
-	//	handle:
-	//	 	The handle returned from a call to subscribe.
-	//	example:
-	//	|	var alerter = dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
-	//	|	...
-	//	|	dojo.unsubscribe(alerter);
-	if(handle){
-		dojo._listener.remove(dojo._topics, handle[0], handle[1]);
-	}
-}
-
-dojo.publish = function(/*String*/ topic, /*Array*/ args){
-	//	summary:
-	//	 	Invoke all listener method subscribed to topic.
-	//	topic:
-	//	 	The name of the topic to publish.
-	//	args:
-	//	 	An array of arguments. The arguments will be applied 
-	//	 	to each topic subscriber (as first class parameters, via apply).
-	//	example:
-	//	|	dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
-	//	|	dojo.publish("alerts", [ "read this", "hello world" ]);	
-
-	// Note that args is an array, which is more efficient vs variable length
-	// argument list.  Ideally, var args would be implemented via Array
-	// throughout the APIs.
-	var f = dojo._topics[topic];
-	if(f){
-		f.apply(this, args||[]);
-	}
-}
-
-dojo.connectPublisher = function(	/*String*/ topic, 
-									/*Object|null*/ obj, 
-									/*String*/ event){
-	//	summary:
-	//	 	Ensure that everytime obj.event() is called, a message is published
-	//	 	on the topic. Returns a handle which can be passed to
-	//	 	dojo.disconnect() to disable subsequent automatic publication on
-	//	 	the topic.
-	//	topic:
-	//	 	The name of the topic to publish.
-	//	obj: 
-	//	 	The source object for the event function. Defaults to dojo.global
-	//	 	if null.
-	//	event:
-	//	 	The name of the event function in obj. 
-	//	 	I.e. identifies a property obj[event].
-	//	example:
-	//	|	dojo.connectPublisher("/ajax/start", dojo, "xhrGet");
-	var pf = function(){ dojo.publish(topic, arguments); }
-	return (event) ? dojo.connect(obj, event, pf) : dojo.connect(obj, pf); //Handle
-};
-
-}
-
-if(!dojo._hasResource["dojo._base.Deferred"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.Deferred"] = true;
-dojo.provide("dojo._base.Deferred");
-
-
-dojo.Deferred = function(/*Function?*/ canceller){
-	// summary:
-	//		Encapsulates a sequence of callbacks in response to a value that
-	//		may not yet be available.  This is modeled after the Deferred class
-	//		from Twisted <http://twistedmatrix.com>.
-	// description:
-	//		JavaScript has no threads, and even if it did, threads are hard.
-	//		Deferreds are a way of abstracting non-blocking events, such as the
-	//		final response to an XMLHttpRequest. Deferreds create a promise to
-	//		return a response a some point in the future and an easy way to
-	//		register your interest in receiving that response.
-	//
-	//		The most important methods for Deffered users are:
-	//
-	//			* addCallback(handler)
-	//			* addErrback(handler)
-	//			* callback(result)
-	//			* errback(result)
-	//
-	//		In general, when a function returns a Deferred, users then "fill
-	//		in" the second half of the contract by registering callbacks and
-	//		error handlers. You may register as many callback and errback
-	//		handlers as you like and they will be executed in the order
-	//		registered when a result is provided. Usually this result is
-	//		provided as the result of an asynchronous operation. The code
-	//		"managing" the Deferred (the code that made the promise to provide
-	//		an answer later) will use the callback() and errback() methods to
-	//		communicate with registered listeners about the result of the
-	//		operation. At this time, all registered result handlers are called
-	//		*with the most recent result value*.
-	//
-	//		Deferred callback handlers are treated as a chain, and each item in
-	//		the chain is required to return a value that will be fed into
-	//		successive handlers. The most minimal callback may be registered
-	//		like this:
-	//
-	//		|	var d = new dojo.Deferred();
-	//		|	d.addCallback(function(result){ return result; });
-	//
-	//		Perhaps the most common mistake when first using Deferreds is to
-	//		forget to return a value (in most cases, the value you were
-	//		passed).
-	//
-	//		The sequence of callbacks is internally represented as a list of
-	//		2-tuples containing the callback/errback pair.  For example, the
-	//		following call sequence:
-	//		
-	//		|	var d = new dojo.Deferred();
-	//		|	d.addCallback(myCallback);
-	//		|	d.addErrback(myErrback);
-	//		|	d.addBoth(myBoth);
-	//		|	d.addCallbacks(myCallback, myErrback);
-	//
-	//		is translated into a Deferred with the following internal
-	//		representation:
-	//
-	//		|	[
-	//		|		[myCallback, null],
-	//		|		[null, myErrback],
-	//		|		[myBoth, myBoth],
-	//		|		[myCallback, myErrback]
-	//		|	]
-	//
-	//		The Deferred also keeps track of its current status (fired).  Its
-	//		status may be one of three things:
-	//
-	//			* -1: no value yet (initial condition)
-	//			* 0: success
-	//			* 1: error
-	//	
-	//		A Deferred will be in the error state if one of the following three
-	//		conditions are met:
-	//
-	//			1. The result given to callback or errback is "instanceof" Error
-	//			2. The previous callback or errback raised an exception while
-	//			   executing
-	//			3. The previous callback or errback returned a value
-	//			   "instanceof" Error
-	//
-	//		Otherwise, the Deferred will be in the success state. The state of
-	//		the Deferred determines the next element in the callback sequence
-	//		to run.
-	//
-	//		When a callback or errback occurs with the example deferred chain,
-	//		something equivalent to the following will happen (imagine
-	//		that exceptions are caught and returned):
-	//
-	//		|	// d.callback(result) or d.errback(result)
-	//		|	if(!(result instanceof Error)){
-	//		|		result = myCallback(result);
-	//		|	}
-	//		|	if(result instanceof Error){
-	//		|		result = myErrback(result);
-	//		|	}
-	//		|	result = myBoth(result);
-	//		|	if(result instanceof Error){
-	//		|		result = myErrback(result);
-	//		|	}else{
-	//		|		result = myCallback(result);
-	//		|	}
-	//
-	//		The result is then stored away in case another step is added to the
-	//		callback sequence.	Since the Deferred already has a value
-	//		available, any new callbacks added will be called immediately.
-	//
-	//		There are two other "advanced" details about this implementation
-	//		that are useful:
-	//
-	//		Callbacks are allowed to return Deferred instances themselves, so
-	//		you can build complicated sequences of events with ease.
-	//
-	//		The creator of the Deferred may specify a canceller.  The canceller
-	//		is a function that will be called if Deferred.cancel is called
-	//		before the Deferred fires. You can use this to implement clean
-	//		aborting of an XMLHttpRequest, etc. Note that cancel will fire the
-	//		deferred with a CancelledError (unless your canceller returns
-	//		another kind of error), so the errbacks should be prepared to
-	//		handle that error for cancellable Deferreds.
-	// example:
-	//	|	var deferred = new dojo.Deferred();
-	//	|	setTimeout(function(){ deferred.callback({success: true}); }, 1000);
-	//	|	return deferred;
-	// example:
-	//		Deferred objects are often used when making code asynchronous. It
-	//		may be easiest to write functions in a synchronous manner and then
-	//		split code using a deferred to trigger a response to a long-lived
-	//		operation. For example, instead of register a callback function to
-	//		denote when a rendering operation completes, the function can
-	//		simply return a deferred:
-	//
-	//		|	// callback style:
-	//		|	function renderLotsOfData(data, callback){
-	//		|		var success = false
-	//		|		try{
-	//		|			for(var x in data){
-	//		|				renderDataitem(data[x]);
-	//		|			}
-	//		|			success = true;
-	//		|		}catch(e){ }
-	//		|		if(callback){
-	//		|			callback(success);
-	//		|		}
-	//		|	}
-	//
-	//		|	// using callback style
-	//		|	renderLotsOfData(someDataObj, function(success){
-	//		|		// handles success or failure
-	//		|		if(!success){
-	//		|			promptUserToRecover();
-	//		|		}
-	//		|	});
-	//		|	// NOTE: no way to add another callback here!!
-	// example:
-	//		Using a Deferred doesn't simplify the sending code any, but it
-	//		provides a standard interface for callers and senders alike,
-	//		providing both with a simple way to service multiple callbacks for
-	//		an operation and freeing both sides from worrying about details
-	//		such as "did this get called already?". With Deferreds, new
-	//		callbacks can be added at any time.
-	//
-	//		|	// Deferred style:
-	//		|	function renderLotsOfData(data){
-	//		|		var d = new dojo.Deferred();
-	//		|		try{
-	//		|			for(var x in data){
-	//		|				renderDataitem(data[x]);
-	//		|			}
-	//		|			d.callback(true);
-	//		|		}catch(e){ 
-	//		|			d.errback(new Error("rendering failed"));
-	//		|		}
-	//		|		return d;
-	//		|	}
-	//
-	//		|	// using Deferred style
-	//		|	renderLotsOfData(someDataObj).addErrback(function(){
-	//		|		promptUserToRecover();
-	//		|	});
-	//		|	// NOTE: addErrback and addCallback both return the Deferred
-	//		|	// again, so we could chain adding callbacks or save the
-	//		|	// deferred for later should we need to be notified again.
-	// example:
-	//		In this example, renderLotsOfData is syncrhonous and so both
-	//		versions are pretty artificial. Putting the data display on a
-	//		timeout helps show why Deferreds rock:
-	//
-	//		|	// Deferred style and async func
-	//		|	function renderLotsOfData(data){
-	//		|		var d = new dojo.Deferred();
-	//		|		setTimeout(function(){
-	//		|			try{
-	//		|				for(var x in data){
-	//		|					renderDataitem(data[x]);
-	//		|				}
-	//		|				d.callback(true);
-	//		|			}catch(e){ 
-	//		|				d.errback(new Error("rendering failed"));
-	//		|			}
-	//		|		}, 100);
-	//		|		return d;
-	//		|	}
-	//
-	//		|	// using Deferred style
-	//		|	renderLotsOfData(someDataObj).addErrback(function(){
-	//		|		promptUserToRecover();
-	//		|	});
-	//
-	//		Note that the caller doesn't have to change his code at all to
-	//		handle the asynchronous case.
-
-	this.chain = [];
-	this.id = this._nextId();
-	this.fired = -1;
-	this.paused = 0;
-	this.results = [null, null];
-	this.canceller = canceller;
-	this.silentlyCancelled = false;
-	this.isFiring = false;
-};
-
-dojo.extend(dojo.Deferred, {
-	/*
-	makeCalled: function(){
-		// summary:
-		//		returns a new, empty deferred, which is already in the called
-		//		state. Calling callback() or errback() on this deferred will
-		//		yeild an error and adding new handlers to it will result in
-		//		them being called immediately.
-		var deferred = new dojo.Deferred();
-		deferred.callback();
-		return deferred;
-	},
-
-	toString: function(){
-		var state;
-		if(this.fired == -1){
-			state = 'unfired';
-		}else{
-			state = this.fired ? 'success' : 'error';
-		}
-		return 'Deferred(' + this.id + ', ' + state + ')';
-	},
-	*/
-
-	_nextId: (function(){
-		var n = 1;
-		return function(){ return n++; };
-	})(),
-
-	cancel: function(){
-		// summary:	
-		//		Cancels a Deferred that has not yet received a value, or is
-		//		waiting on another Deferred as its value.
-		// description:
-		//		If a canceller is defined, the canceller is called. If the
-		//		canceller did not return an error, or there was no canceller,
-		//		then the errback chain is started.
-		var err;
-		if(this.fired == -1){
-			if(this.canceller){
-				err = this.canceller(this);
-			}else{
-				this.silentlyCancelled = true;
-			}
-			if(this.fired == -1){
-				if(!(err instanceof Error)){
-					var res = err;
-					var msg = "Deferred Cancelled";
-					if(err && err.toString){
-						msg += ": " + err.toString();
-					}
-					err = new Error(msg);
-					err.dojoType = "cancel";
-					err.cancelResult = res;
-				}
-				this.errback(err);
-			}
-		}else if(	(this.fired == 0) &&
-					(this.results[0] instanceof dojo.Deferred)
-		){
-			this.results[0].cancel();
-		}
-	},
-			
-
-	_resback: function(res){
-		// summary:
-		//		The private primitive that means either callback or errback
-		this.fired = ((res instanceof Error) ? 1 : 0);
-		this.results[this.fired] = res;
-		this._fire();
-	},
-
-	_check: function(){
-		if(this.fired != -1){
-			if(!this.silentlyCancelled){
-				throw new Error("already called!");
-			}
-			this.silentlyCancelled = false;
-			return;
-		}
-	},
-
-	callback: function(res){
-		//	summary:	
-		//		Begin the callback sequence with a non-error value.
-		
-		/*
-		callback or errback should only be called once on a given
-		Deferred.
-		*/
-		this._check();
-		this._resback(res);
-	},
-
-	errback: function(/*Error*/res){
-		//	summary: 
-		//		Begin the callback sequence with an error result.
-		this._check();
-		if(!(res instanceof Error)){
-			res = new Error(res);
-		}
-		this._resback(res);
-	},
-
-	addBoth: function(/*Function|Object*/cb, /*String?*/cbfn){
-		//	summary:
-		//		Add the same function as both a callback and an errback as the
-		//		next element on the callback sequence.This is useful for code
-		//		that you want to guarantee to run, e.g. a finalizer.
-		var enclosed = dojo.hitch.apply(dojo, arguments);
-		return this.addCallbacks(enclosed, enclosed); // dojo.Deferred
-	},
-
-	addCallback: function(/*Function|Object*/cb, /*String?*/cbfn /*...*/){
-		//	summary: 
-		//		Add a single callback to the end of the callback sequence.
-		return this.addCallbacks(dojo.hitch.apply(dojo, arguments)); // dojo.Deferred
-	},
-
-	addErrback: function(cb, cbfn){
-		//	summary: 
-		//		Add a single callback to the end of the callback sequence.
-		return this.addCallbacks(null, dojo.hitch.apply(dojo, arguments)); // dojo.Deferred
-	},
-
-	addCallbacks: function(cb, eb){
-		// summary: 
-		//		Add separate callback and errback to the end of the callback
-		//		sequence.
-		this.chain.push([cb, eb])
-		if(this.fired >= 0 && !this.isFiring){
-			this._fire();
-		}
-		return this; // dojo.Deferred
-	},
-
-	_fire: function(){
-		// summary: 
-		//		Used internally to exhaust the callback sequence when a result
-		//		is available.
-		this.isFiring = true;
-		var chain = this.chain;
-		var fired = this.fired;
-		var res = this.results[fired];
-		var self = this;
-		var cb = null;
-		while(
-			(chain.length > 0) &&
-			(this.paused == 0)
-		){
-			// Array
-			var f = chain.shift()[fired];
-			if(!f){ continue; }
-			var func = function(){
-				var ret = f(res);
-				//If no response, then use previous response.
-				if(typeof ret != "undefined"){
-					res = ret;
-				}
-				fired = ((res instanceof Error) ? 1 : 0);
-				if(res instanceof dojo.Deferred){
-					cb = function(res){
-						self._resback(res);
-						// inlined from _pause()
-						self.paused--;
-						if(
-							(self.paused == 0) && 
-							(self.fired >= 0)
-						){
-							self._fire();
-						}
-					}
-					// inlined from _unpause
-					this.paused++;
-				}
-			};
-			if(dojo.config.debugAtAllCosts){
-				func.call(this);
-			}else{
-				try{
-					func.call(this);
-				}catch(err){
-					fired = 1;
-					res = err;
-				}
-			}
-		}
-		this.fired = fired;
-		this.results[fired] = res;
-		this.isFiring = false;
-		if((cb)&&(this.paused)){
-			// this is for "tail recursion" in case the dependent
-			// deferred is already fired
-			res.addBoth(cb);
-		}
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojo._base.json"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.json"] = true;
-dojo.provide("dojo._base.json");
-
-dojo.fromJson = function(/*String*/ json){
-	// summary:
-	// 		Parses a [JSON](http://json.org) string to return a JavaScript object.
-	// description:
-	// 		Throws for invalid JSON strings, but it does not use a strict JSON parser. It
-	// 		delegates to eval().
-	// json: 
-	//		a string literal of a JSON item, for instance:
-	//			`'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'`
-
-	return eval("(" + json + ")"); // Object
-}
-
-dojo._escapeString = function(/*String*/str){
-	//summary:
-	//		Adds escape sequences for non-visual characters, double quote and
-	//		backslash and surrounds with double quotes to form a valid string
-	//		literal.
-	return ('"' + str.replace(/(["\\])/g, '\\$1') + '"').
-		replace(/[\f]/g, "\\f").replace(/[\b]/g, "\\b").replace(/[\n]/g, "\\n").
-		replace(/[\t]/g, "\\t").replace(/[\r]/g, "\\r"); // string
-}
-
-dojo.toJsonIndentStr = "\t";
-dojo.toJson = function(/*Object*/ it, /*Boolean?*/ prettyPrint, /*String?*/ _indentStr){
-	//	summary:
-	//		Returns a [JSON](http://json.org) serialization of an object.
-	//	description:
-	//		Returns a [JSON](http://json.org) serialization of an object.
-	//		Note that this doesn't check for infinite recursion, so don't do that!
-	//	it:
-	//		an object to be serialized. Objects may define their own
-	//		serialization via a special "__json__" or "json" function
-	//		property. If a specialized serializer has been defined, it will
-	//		be used as a fallback.
-	//	prettyPrint:
-	//		if true, we indent objects and arrays to make the output prettier.
-	//		The variable `dojo.toJsonIndentStr` is used as the indent string --
-	//		to use something other than the default (tab), change that variable
-	//		before calling dojo.toJson().
-	//	_indentStr:
-	//		private variable for recursive calls when pretty printing, do not use.
-	//	example:
-	//		simple serialization of a trivial object
-	//		|	var jsonStr = dojo.toJson({ howdy: "stranger!", isStrange: true });
-	//		|	doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr);
-	//	example:
-	//		a custom serializer for an objects of a particular class:
-	//		|	dojo.declare("Furby", null, {
-	//		|		furbies: "are strange",
-	//		|		furbyCount: 10,
-	//		|		__json__: function(){
-	//		|		},
-	//		|	});
-
-	if(it === undefined){
-		return "undefined";
-	}
-	var objtype = typeof it;
-	if(objtype == "number" || objtype == "boolean"){
-		return it + "";
-	}
-	if(it === null){
-		return "null";
-	}
-	if(dojo.isString(it)){ 
-		return dojo._escapeString(it); 
-	}
-	// recurse
-	var recurse = arguments.callee;
-	// short-circuit for objects that support "json" serialization
-	// if they return "self" then just pass-through...
-	var newObj;
-	_indentStr = _indentStr || "";
-	var nextIndent = prettyPrint ? _indentStr + dojo.toJsonIndentStr : "";
-	var tf = it.__json__||it.json;
-	if(dojo.isFunction(tf)){
-		newObj = tf.call(it);
-		if(it !== newObj){
-			return recurse(newObj, prettyPrint, nextIndent);
-		}
-	}
-	if(it.nodeType && it.cloneNode){ // isNode
-		// we can't seriailize DOM nodes as regular objects because they have cycles
-		// DOM nodes could be serialized with something like outerHTML, but
-		// that can be provided by users in the form of .json or .__json__ function.
-		throw new Error("Can't serialize DOM nodes");
-	}
-
-	var sep = prettyPrint ? " " : "";
-	var newLine = prettyPrint ? "\n" : "";
-
-	// array
-	if(dojo.isArray(it)){
-		var res = dojo.map(it, function(obj){
-			var val = recurse(obj, prettyPrint, nextIndent);
-			if(typeof val != "string"){
-				val = "undefined";
-			}
-			return newLine + nextIndent + val;
-		});
-		return "[" + res.join("," + sep) + newLine + _indentStr + "]";
-	}
-	/*
-	// look in the registry
-	try {
-		window.o = it;
-		newObj = dojo.json.jsonRegistry.match(it);
-		return recurse(newObj, prettyPrint, nextIndent);
-	}catch(e){
-		// console.log(e);
-	}
-	// it's a function with no adapter, skip it
-	*/
-	if(objtype == "function"){
-		return null; // null
-	}
-	// generic object code path
-	var output = [], key;
-	for(key in it){
-		var keyStr, val;
-		if(typeof key == "number"){
-			keyStr = '"' + key + '"';
-		}else if(typeof key == "string"){
-			keyStr = dojo._escapeString(key);
-		}else{
-			// skip non-string or number keys
-			continue;
-		}
-		val = recurse(it[key], prettyPrint, nextIndent);
-		if(typeof val != "string"){
-			// skip non-serializable values
-			continue;
-		}
-		// FIXME: use += on Moz!!
-		//	 MOW NOTE: using += is a pain because you have to account for the dangling comma...
-		output.push(newLine + nextIndent + keyStr + ":" + sep + val);
-	}
-	return "{" + output.join("," + sep) + newLine + _indentStr + "}"; // String
-}
-
-}
-
-if(!dojo._hasResource["dojo._base.Color"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.Color"] = true;
-dojo.provide("dojo._base.Color");
-
-
-
-(function(){
-
-	var d = dojo;
-
-	dojo.Color = function(/*Array|String|Object*/ color){
-		// summary:
-		//	 	Takes a named string, hex string, array of rgb or rgba values,
-		//	 	an object with r, g, b, and a properties, or another `dojo.Color` object
-		//	 	and creates a new Color instance to work from.
-		//
-		// example:
-		//		Work with a Color instance:
-		//	 | var c = new dojo.Color();
-		//	 | c.setColor([0,0,0]); // black
-		//	 | var hex = c.toHex(); // #000000
-		//
-		// example:
-		//		Work with a node's color:
-		//	 | var color = dojo.style("someNode", "backgroundColor");
-		//	 | var n = new dojo.Color(color);
-		//	 | // adjust the color some
-		//	 | n.r *= .5;
-		//	 | console.log(n.toString()); // rgb(128, 255, 255);
-		if(color){ this.setColor(color); }
-	};
-
-	// FIXME:
-	// 	there's got to be a more space-efficient way to encode or discover
-	// 	these!!  Use hex?
-	dojo.Color.named = {
-		black:      [0,0,0],
-		silver:     [192,192,192],
-		gray:       [128,128,128],
-		white:      [255,255,255],
-		maroon:		[128,0,0],
-		red:        [255,0,0],
-		purple:		[128,0,128],
-		fuchsia:	[255,0,255],
-		green:	    [0,128,0],
-		lime:	    [0,255,0],
-		olive:		[128,128,0],
-		yellow:		[255,255,0],
-		navy:       [0,0,128],
-		blue:       [0,0,255],
-		teal:		[0,128,128],
-		aqua:		[0,255,255],
-		transparent: d.config.transparentColor || [255,255,255]
-	};
-
-	dojo.extend(dojo.Color, {
-		r: 255, g: 255, b: 255, a: 1,
-		_set: function(r, g, b, a){
-			var t = this; t.r = r; t.g = g; t.b = b; t.a = a;
-		},
-		setColor: function(/*Array|String|Object*/ color){
-			// summary:
-			//		Takes a named string, hex string, array of rgb or rgba values,
-			//		an object with r, g, b, and a properties, or another `dojo.Color` object
-			//		and sets this color instance to that value.
-			//
-			// example:
-			//	|	var c = new dojo.Color(); // no color
-			//	|	c.setColor("#ededed"); // greyish
-			if(d.isString(color)){
-				d.colorFromString(color, this);
-			}else if(d.isArray(color)){
-				d.colorFromArray(color, this);
-			}else{
-				this._set(color.r, color.g, color.b, color.a);
-				if(!(color instanceof d.Color)){ this.sanitize(); }
-			}
-			return this;	// dojo.Color
-		},
-		sanitize: function(){
-			// summary:
-			//		Ensures the object has correct attributes
-			// description:
-			//		the default implementation does nothing, include dojo.colors to
-			//		augment it with real checks
-			return this;	// dojo.Color
-		},
-		toRgb: function(){
-			// summary:
-			//		Returns 3 component array of rgb values
-			// example:
-			//	|	var c = new dojo.Color("#000000");
-			//	| 	console.log(c.toRgb()); // [0,0,0]
-			var t = this;
-			return [t.r, t.g, t.b];	// Array
-		},
-		toRgba: function(){
-			// summary:
-			//		Returns a 4 component array of rgba values from the color
-			//		represented by this object.
-			var t = this;
-			return [t.r, t.g, t.b, t.a];	// Array
-		},
-		toHex: function(){
-			// summary:
-			//		Returns a CSS color string in hexadecimal representation
-			// example:
-			//	| 	console.log(new dojo.Color([0,0,0]).toHex()); // #000000
-			var arr = d.map(["r", "g", "b"], function(x){
-				var s = this[x].toString(16);
-				return s.length < 2 ? "0" + s : s;
-			}, this);
-			return "#" + arr.join("");	// String
-		},
-		toCss: function(/*Boolean?*/ includeAlpha){
-			// summary:
-			//		Returns a css color string in rgb(a) representation
-			// example:
-			//	|	var c = new dojo.Color("#FFF").toCss();
-			//	|	console.log(c); // rgb('255','255','255')
-			var t = this, rgb = t.r + ", " + t.g + ", " + t.b;
-			return (includeAlpha ? "rgba(" + rgb + ", " + t.a : "rgb(" + rgb) + ")";	// String
-		},
-		toString: function(){
-			// summary:
-			//		Returns a visual representation of the color
-			return this.toCss(true); // String
-		}
-	});
-
-	dojo.blendColors = function(
-		/*dojo.Color*/ start,
-		/*dojo.Color*/ end,
-		/*Number*/ weight,
-		/*dojo.Color?*/ obj
-	){
-		// summary:
-		//		Blend colors end and start with weight from 0 to 1, 0.5 being a 50/50 blend,
-		//		can reuse a previously allocated dojo.Color object for the result
-		var t = obj || new d.Color();
-		d.forEach(["r", "g", "b", "a"], function(x){
-			t[x] = start[x] + (end[x] - start[x]) * weight;
-			if(x != "a"){ t[x] = Math.round(t[x]); }
-		});
-		return t.sanitize();	// dojo.Color
-	};
-
-	dojo.colorFromRgb = function(/*String*/ color, /*dojo.Color?*/ obj){
-		// summary:
-		//		Returns a `dojo.Color` instance from a string of the form
-		//		"rgb(...)" or "rgba(...)". Optionally accepts a `dojo.Color`
-		//		object to update with the parsed value and return instead of
-		//		creating a new object.
-		// returns:
-		//		A dojo.Color object. If obj is passed, it will be the return value.
-		var m = color.toLowerCase().match(/^rgba?\(([\s\.,0-9]+)\)/);
-		return m && dojo.colorFromArray(m[1].split(/\s*,\s*/), obj);	// dojo.Color
-	};
-
-	dojo.colorFromHex = function(/*String*/ color, /*dojo.Color?*/ obj){
-		// summary:
-		//		Converts a hex string with a '#' prefix to a color object.
-		//		Supports 12-bit #rgb shorthand. Optionally accepts a
-		//		`dojo.Color` object to update with the parsed value.
-		//
-		// returns:
-		//		A dojo.Color object. If obj is passed, it will be the return value.
-		//
-		// example:
-		//	 | var thing = dojo.colorFromHex("#ededed"); // grey, longhand
-		//
-		// example:
-		//	| var thing = dojo.colorFromHex("#000"); // black, shorthand
-		var t = obj || new d.Color(),
-			bits = (color.length == 4) ? 4 : 8,
-			mask = (1 << bits) - 1;
-		color = Number("0x" + color.substr(1));
-		if(isNaN(color)){
-			return null; // dojo.Color
-		}
-		d.forEach(["b", "g", "r"], function(x){
-			var c = color & mask;
-			color >>= bits;
-			t[x] = bits == 4 ? 17 * c : c;
-		});
-		t.a = 1;
-		return t;	// dojo.Color
-	};
-
-	dojo.colorFromArray = function(/*Array*/ a, /*dojo.Color?*/ obj){
-		// summary:
-		//		Builds a `dojo.Color` from a 3 or 4 element array, mapping each
-		//		element in sequence to the rgb(a) values of the color.
-		// example:
-		//		| var myColor = dojo.colorFromArray([237,237,237,0.5]); // grey, 50% alpha 
-		// returns:
-		//		A dojo.Color object. If obj is passed, it will be the return value.
-		var t = obj || new d.Color();
-		t._set(Number(a[0]), Number(a[1]), Number(a[2]), Number(a[3]));
-		if(isNaN(t.a)){ t.a = 1; }
-		return t.sanitize();	// dojo.Color
-	};
-
-	dojo.colorFromString = function(/*String*/ str, /*dojo.Color?*/ obj){
-		// summary:
-		//		Parses `str` for a color value. Accepts hex, rgb, and rgba
-		//		style color values.
-		// description:
-		//		Acceptable input values for str may include arrays of any form
-		//		accepted by dojo.colorFromArray, hex strings such as "#aaaaaa", or
-		//		rgb or rgba strings such as "rgb(133, 200, 16)" or "rgba(10, 10,
-		//		10, 50)"
-		// returns:
-		//		A dojo.Color object. If obj is passed, it will be the return value.
-		var a = d.Color.named[str];
-		return a && d.colorFromArray(a, obj) || d.colorFromRgb(str, obj) || d.colorFromHex(str, obj);
-	};
-})();
-
-}
-
-if(!dojo._hasResource["dojo._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base"] = true;
-dojo.provide("dojo._base");
-
-
-
-
-
-
-
-
-
-}
-
-if(!dojo._hasResource["dojo._base.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.window"] = true;
-dojo.provide("dojo._base.window");
-
-/*=====
-dojo.doc = {
-	// summary:
-	//		Alias for the current document. 'dojo.doc' can be modified
-	//		for temporary context shifting. Also see dojo.withDoc().
-	// description:
-	//    Refer to dojo.doc rather
-	//    than referring to 'window.document' to ensure your code runs
-	//    correctly in managed contexts.
-	// example:
-	// 	|	n.appendChild(dojo.doc.createElement('div'));
-}
-=====*/
-dojo.doc = window["document"] || null;
-
-dojo.body = function(){
-	// summary:
-	//		Return the body element of the document
-	//		return the body object associated with dojo.doc
-	// example:
-	// 	|	dojo.body().appendChild(dojo.doc.createElement('div'));
-
-	// Note: document.body is not defined for a strict xhtml document
-	// Would like to memoize this, but dojo.doc can change vi dojo.withDoc().
-	return dojo.doc.body || dojo.doc.getElementsByTagName("body")[0]; // Node
-}
-
-dojo.setContext = function(/*Object*/globalObject, /*DocumentElement*/globalDocument){
-	// summary:
-	//		changes the behavior of many core Dojo functions that deal with
-	//		namespace and DOM lookup, changing them to work in a new global
-	//		context (e.g., an iframe). The varibles dojo.global and dojo.doc
-	//		are modified as a result of calling this function and the result of
-	//		`dojo.body()` likewise differs.
-	dojo.global = globalObject;
-	dojo.doc = globalDocument;
-};
-
-dojo.withGlobal = function(	/*Object*/globalObject, 
-							/*Function*/callback, 
-							/*Object?*/thisObject, 
-							/*Array?*/cbArguments){
-	// summary:
-	//		Invoke callback with globalObject as dojo.global and
-	//		globalObject.document as dojo.doc.
-	// description:
-	//		Invoke callback with globalObject as dojo.global and
-	//		globalObject.document as dojo.doc. If provided, globalObject
-	//		will be executed in the context of object thisObject
-	//		When callback() returns or throws an error, the dojo.global
-	//		and dojo.doc will be restored to its previous state.
-
-	var oldGlob = dojo.global;
-	try{
-		dojo.global = globalObject;
-		return dojo.withDoc.call(null, globalObject.document, callback, thisObject, cbArguments);
-	}finally{
-		dojo.global = oldGlob;
-	}
-}
-
-dojo.withDoc = function(	/*DocumentElement*/documentObject, 
-							/*Function*/callback, 
-							/*Object?*/thisObject, 
-							/*Array?*/cbArguments){
-	// summary:
-	//		Invoke callback with documentObject as dojo.doc.
-	// description:
-	//		Invoke callback with documentObject as dojo.doc. If provided,
-	//		callback will be executed in the context of object thisObject
-	//		When callback() returns or throws an error, the dojo.doc will
-	//		be restored to its previous state.
-
-	var oldDoc = dojo.doc,
-		oldLtr = dojo._bodyLtr,
-		oldQ = dojo.isQuirks;
-
-	try{
-		dojo.doc = documentObject;
-		delete dojo._bodyLtr; // uncache
-		dojo.isQuirks = dojo.doc.compatMode == "BackCompat"; // no need to check for QuirksMode which was Opera 7 only
-
-		if(thisObject && typeof callback == "string"){
-			callback = thisObject[callback];
-		}
-
-		return callback.apply(thisObject, cbArguments || []);
-	}finally{
-		dojo.doc = oldDoc;
-		delete dojo._bodyLtr; // in case it was undefined originally, and set to true/false by the alternate document
-		if(oldLtr !== undefined){ dojo._bodyLtr = oldLtr; }
-		dojo.isQuirks = oldQ;
-	}
-};
-	
-
-}
-
-if(!dojo._hasResource["dojo._base.event"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.event"] = true;
-dojo.provide("dojo._base.event");
-
-
-// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
-
-(function(){
-	// DOM event listener machinery
-	var del = (dojo._event_listener = {
-		add: function(/*DOMNode*/ node, /*String*/ name, /*Function*/ fp){
-			if(!node){return;} 
-			name = del._normalizeEventName(name);
-			fp = del._fixCallback(name, fp);
-			var oname = name;
-			if(
-								!dojo.isIE && 
-								(name == "mouseenter" || name == "mouseleave")
-			){
-				var ofp = fp;
-				//oname = name;
-				name = (name == "mouseenter") ? "mouseover" : "mouseout";
-				fp = function(e){
-					if(!dojo.isDescendant(e.relatedTarget, node)){
-						// e.type = oname; // FIXME: doesn't take? SJM: event.type is generally immutable.
-						return ofp.call(this, e); 
-					}
-				}
-			}
-			node.addEventListener(name, fp, false);
-			return fp; /*Handle*/
-		},
-		remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
-			// summary:
-			//		clobbers the listener from the node
-			// node:
-			//		DOM node to attach the event to
-			// event:
-			//		the name of the handler to remove the function from
-			// handle:
-			//		the handle returned from add
-			if(node){
-				event = del._normalizeEventName(event);
-				if(!dojo.isIE && (event == "mouseenter" || event == "mouseleave")){
-					event = (event == "mouseenter") ? "mouseover" : "mouseout";
-				}
-
-				node.removeEventListener(event, handle, false);
-			}
-		},
-		_normalizeEventName: function(/*String*/ name){
-			// Generally, name should be lower case, unless it is special
-			// somehow (e.g. a Mozilla DOM event).
-			// Remove 'on'.
-			return name.slice(0,2) =="on" ? name.slice(2) : name;
-		},
-		_fixCallback: function(/*String*/ name, fp){
-			// By default, we only invoke _fixEvent for 'keypress'
-			// If code is added to _fixEvent for other events, we have
-			// to revisit this optimization.
-			// This also applies to _fixEvent overrides for Safari and Opera
-			// below.
-			return name != "keypress" ? fp : function(e){ return fp.call(this, del._fixEvent(e, this)); };
-		},
-		_fixEvent: function(evt, sender){
-			// _fixCallback only attaches us to keypress.
-			// Switch on evt.type anyway because we might 
-			// be called directly from dojo.fixEvent.
-			switch(evt.type){
-				case "keypress":
-					del._setKeyChar(evt);
-					break;
-			}
-			return evt;
-		},
-		_setKeyChar: function(evt){
-			evt.keyChar = evt.charCode ? String.fromCharCode(evt.charCode) : '';
-			evt.charOrCode = evt.keyChar || evt.keyCode;
-		},
-		// For IE and Safari: some ctrl-key combinations (mostly w/punctuation) do not emit a char code in IE
-		// we map those virtual key codes to ascii here
-		// not valid for all (non-US) keyboards, so maybe we shouldn't bother
-		_punctMap: { 
-			106:42, 
-			111:47, 
-			186:59, 
-			187:43, 
-			188:44, 
-			189:45, 
-			190:46, 
-			191:47, 
-			192:96, 
-			219:91, 
-			220:92, 
-			221:93, 
-			222:39 
-		}
-	});
-
-	// DOM events
-	
-	dojo.fixEvent = function(/*Event*/ evt, /*DOMNode*/ sender){
-		// summary:
-		//		normalizes properties on the event object including event
-		//		bubbling methods, keystroke normalization, and x/y positions
-		// evt: Event
-		//		native event object
-		// sender: DOMNode
-		//		node to treat as "currentTarget"
-		return del._fixEvent(evt, sender);
-	}
-
-	dojo.stopEvent = function(/*Event*/ evt){
-		// summary:
-		//		prevents propagation and clobbers the default action of the
-		//		passed event
-		// evt: Event
-		//		The event object. If omitted, window.event is used on IE.
-		evt.preventDefault();
-		evt.stopPropagation();
-		// NOTE: below, this method is overridden for IE
-	}
-
-	// the default listener to use on dontFix nodes, overriden for IE
-	var node_listener = dojo._listener;
-	
-	// Unify connect and event listeners
-	dojo._connect = function(obj, event, context, method, dontFix){
-		// FIXME: need a more strict test
-		var isNode = obj && (obj.nodeType||obj.attachEvent||obj.addEventListener);
-		// choose one of three listener options: raw (connect.js), DOM event on a Node, custom event on a Node
-		// we need the third option to provide leak prevention on broken browsers (IE)
-		var lid = isNode ? (dontFix ? 2 : 1) : 0, l = [dojo._listener, del, node_listener][lid];
-		// create a listener
-		var h = l.add(obj, event, dojo.hitch(context, method));
-		// formerly, the disconnect package contained "l" directly, but if client code
-		// leaks the disconnect package (by connecting it to a node), referencing "l" 
-		// compounds the problem.
-		// instead we return a listener id, which requires custom _disconnect below.
-		// return disconnect package
-		return [ obj, event, h, lid ];
-	}
-
-	dojo._disconnect = function(obj, event, handle, listener){
-		([dojo._listener, del, node_listener][listener]).remove(obj, event, handle);
-	}
-
-	// Constants
-
-	// Public: client code should test
-	// keyCode against these named constants, as the
-	// actual codes can vary by browser.
-	dojo.keys = {
-		// summary:
-		//		Definitions for common key values
-		BACKSPACE: 8,
-		TAB: 9,
-		CLEAR: 12,
-		ENTER: 13,
-		SHIFT: 16,
-		CTRL: 17,
-		ALT: 18,
-		META: dojo.isSafari ? 91 : 224,		// the apple key on macs
-		PAUSE: 19,
-		CAPS_LOCK: 20,
-		ESCAPE: 27,
-		SPACE: 32,
-		PAGE_UP: 33,
-		PAGE_DOWN: 34,
-		END: 35,
-		HOME: 36,
-		LEFT_ARROW: 37,
-		UP_ARROW: 38,
-		RIGHT_ARROW: 39,
-		DOWN_ARROW: 40,
-		INSERT: 45,
-		DELETE: 46,
-		HELP: 47,
-		LEFT_WINDOW: 91,
-		RIGHT_WINDOW: 92,
-		SELECT: 93,
-		NUMPAD_0: 96,
-		NUMPAD_1: 97,
-		NUMPAD_2: 98,
-		NUMPAD_3: 99,
-		NUMPAD_4: 100,
-		NUMPAD_5: 101,
-		NUMPAD_6: 102,
-		NUMPAD_7: 103,
-		NUMPAD_8: 104,
-		NUMPAD_9: 105,
-		NUMPAD_MULTIPLY: 106,
-		NUMPAD_PLUS: 107,
-		NUMPAD_ENTER: 108,
-		NUMPAD_MINUS: 109,
-		NUMPAD_PERIOD: 110,
-		NUMPAD_DIVIDE: 111,
-		F1: 112,
-		F2: 113,
-		F3: 114,
-		F4: 115,
-		F5: 116,
-		F6: 117,
-		F7: 118,
-		F8: 119,
-		F9: 120,
-		F10: 121,
-		F11: 122,
-		F12: 123,
-		F13: 124,
-		F14: 125,
-		F15: 126,
-		NUM_LOCK: 144,
-		SCROLL_LOCK: 145,
-		// virtual key mapping
-		copyKey: dojo.isMac && !dojo.isAIR ? (dojo.isSafari ? 91 : 224 ) : 17
-	};
-	
-	var evtCopyKey = dojo.isMac ? "metaKey" : "ctrlKey";
-	
-	dojo.isCopyKey = function(e){
-		// summary:
-		//		Checks an event for the copy key (meta on Mac, and ctrl anywhere else)
-		// e: Event
-		//		Event object to examine
-		return e[evtCopyKey];	// Boolean
-	};
-
-	// Public: decoding mouse buttons from events
-
-/*=====
-	dojo.mouseButtons = {
-		// LEFT: Number
-		//		Numeric value of the left mouse button for the platform.
-		LEFT:   0,
-		// MIDDLE: Number
-		//		Numeric value of the middle mouse button for the platform.
-		MIDDLE: 1,
-		// RIGHT: Number
-		//		Numeric value of the right mouse button for the platform.
-		RIGHT:  2,
-	
-		isButton: function(e, button){
-			// summary:
-			//		Checks an event object for a pressed button
-			// e: Event
-			//		Event object to examine
-			// button: Number
-			//		The button value (example: dojo.mouseButton.LEFT)
-			return e.button == button; // Boolean
-		},
-		isLeft: function(e){
-			// summary:
-			//		Checks an event object for the pressed left button
-			// e: Event
-			//		Event object to examine
-			return e.button == 0; // Boolean
-		},
-		isMiddle: function(e){
-			// summary:
-			//		Checks an event object for the pressed middle button
-			// e: Event
-			//		Event object to examine
-			return e.button == 1; // Boolean
-		},
-		isRight: function(e){
-			// summary:
-			//		Checks an event object for the pressed right button
-			// e: Event
-			//		Event object to examine
-			return e.button == 2; // Boolean
-		}
-	};
-=====*/
-
-		if(dojo.isIE){
-		dojo.mouseButtons = {
-			LEFT:   1,
-			MIDDLE: 4,
-			RIGHT:  2,
-			// helper functions
-			isButton: function(e, button){ return e.button & button; },
-			isLeft:   function(e){ return e.button & 1; },
-			isMiddle: function(e){ return e.button & 4; },
-			isRight:  function(e){ return e.button & 2; }
-		};
-	}else{
-			dojo.mouseButtons = {
-			LEFT:   0,
-			MIDDLE: 1,
-			RIGHT:  2,
-			// helper functions
-			isButton: function(e, button){ return e.button == button; },
-			isLeft:   function(e){ return e.button == 0; },
-			isMiddle: function(e){ return e.button == 1; },
-			isRight:  function(e){ return e.button == 2; }
-		};
-		}
-	
-		// IE event normalization
-	if(dojo.isIE){ 
-		var _trySetKeyCode = function(e, code){
-			try{
-				// squelch errors when keyCode is read-only
-				// (e.g. if keyCode is ctrl or shift)
-				return (e.keyCode = code);
-			}catch(e){
-				return 0;
-			}
-		}
-
-		// by default, use the standard listener
-		var iel = dojo._listener;
-		var listenersName = (dojo._ieListenersName = "_" + dojo._scopeName + "_listeners");
-		// dispatcher tracking property
-		if(!dojo.config._allow_leaks){
-			// custom listener that handles leak protection for DOM events
-			node_listener = iel = dojo._ie_listener = {
-				// support handler indirection: event handler functions are 
-				// referenced here. Event dispatchers hold only indices.
-				handlers: [],
-				// add a listener to an object
-				add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
-					source = source || dojo.global;
-					var f = source[method];
-					if(!f||!f[listenersName]){
-						var d = dojo._getIeDispatcher();
-						// original target function is special
-						d.target = f && (ieh.push(f) - 1);
-						// dispatcher holds a list of indices into handlers table
-						d[listenersName] = [];
-						// redirect source to dispatcher
-						f = source[method] = d;
-					}
-					return f[listenersName].push(ieh.push(listener) - 1) ; /*Handle*/
-				},
-				// remove a listener from an object
-				remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
-					var f = (source||dojo.global)[method], l = f && f[listenersName];
-					if(f && l && handle--){
-						delete ieh[l[handle]];
-						delete l[handle];
-					}
-				}
-			};
-			// alias used above
-			var ieh = iel.handlers;
-		}
-
-		dojo.mixin(del, {
-			add: function(/*DOMNode*/ node, /*String*/ event, /*Function*/ fp){
-				if(!node){return;} // undefined
-				event = del._normalizeEventName(event);
-				if(event=="onkeypress"){
-					// we need to listen to onkeydown to synthesize
-					// keypress events that otherwise won't fire
-					// on IE
-					var kd = node.onkeydown;
-					if(!kd || !kd[listenersName] || !kd._stealthKeydownHandle){
-						var h = del.add(node, "onkeydown", del._stealthKeyDown);
-						kd = node.onkeydown;
-						kd._stealthKeydownHandle = h;
-						kd._stealthKeydownRefs = 1;
-					}else{
-						kd._stealthKeydownRefs++;
-					}
-				}
-				return iel.add(node, event, del._fixCallback(fp));
-			},
-			remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
-				event = del._normalizeEventName(event);
-				iel.remove(node, event, handle); 
-				if(event=="onkeypress"){
-					var kd = node.onkeydown;
-					if(--kd._stealthKeydownRefs <= 0){
-						iel.remove(node, "onkeydown", kd._stealthKeydownHandle);
-						delete kd._stealthKeydownHandle;
-					}
-				}
-			},
-			_normalizeEventName: function(/*String*/ eventName){
-				// Generally, eventName should be lower case, unless it is
-				// special somehow (e.g. a Mozilla event)
-				// ensure 'on'
-				return eventName.slice(0,2) != "on" ? "on" + eventName : eventName;
-			},
-			_nop: function(){},
-			_fixEvent: function(/*Event*/ evt, /*DOMNode*/ sender){
-				// summary:
-				//		normalizes properties on the event object including event
-				//		bubbling methods, keystroke normalization, and x/y positions
-				// evt:
-				//		native event object
-				// sender:
-				//		node to treat as "currentTarget"
-				if(!evt){
-					var w = sender && (sender.ownerDocument || sender.document || sender).parentWindow || window;
-					evt = w.event; 
-				}
-				if(!evt){return(evt);}
-				evt.target = evt.srcElement; 
-				evt.currentTarget = (sender || evt.srcElement); 
-				evt.layerX = evt.offsetX;
-				evt.layerY = evt.offsetY;
-				// FIXME: scroll position query is duped from dojo.html to
-				// avoid dependency on that entire module. Now that HTML is in
-				// Base, we should convert back to something similar there.
-				var se = evt.srcElement, doc = (se && se.ownerDocument) || document;
-				// DO NOT replace the following to use dojo.body(), in IE, document.documentElement should be used
-				// here rather than document.body
-				var docBody = ((dojo.isIE < 6) || (doc["compatMode"] == "BackCompat")) ? doc.body : doc.documentElement;
-				var offset = dojo._getIeDocumentElementOffset();
-				evt.pageX = evt.clientX + dojo._fixIeBiDiScrollLeft(docBody.scrollLeft || 0) - offset.x;
-				evt.pageY = evt.clientY + (docBody.scrollTop || 0) - offset.y;
-				if(evt.type == "mouseover"){ 
-					evt.relatedTarget = evt.fromElement;
-				}
-				if(evt.type == "mouseout"){ 
-					evt.relatedTarget = evt.toElement;
-				}
-				evt.stopPropagation = del._stopPropagation;
-				evt.preventDefault = del._preventDefault;
-				return del._fixKeys(evt);
-			},
-			_fixKeys: function(evt){
-				switch(evt.type){
-					case "keypress":
-						var c = ("charCode" in evt ? evt.charCode : evt.keyCode);
-						if (c==10){
-							// CTRL-ENTER is CTRL-ASCII(10) on IE, but CTRL-ENTER on Mozilla
-							c=0;
-							evt.keyCode = 13;
-						}else if(c==13||c==27){
-							c=0; // Mozilla considers ENTER and ESC non-printable
-						}else if(c==3){
-							c=99; // Mozilla maps CTRL-BREAK to CTRL-c
-						}
-						// Mozilla sets keyCode to 0 when there is a charCode
-						// but that stops the event on IE.
-						evt.charCode = c;
-						del._setKeyChar(evt);
-						break;
-				}
-				return evt;
-			},
-			_stealthKeyDown: function(evt){
-				// IE doesn't fire keypress for most non-printable characters.
-				// other browsers do, we simulate it here.
-				var kp = evt.currentTarget.onkeypress;
-				// only works if kp exists and is a dispatcher
-				if(!kp || !kp[listenersName]){ return; }
-				// munge key/charCode
-				var k=evt.keyCode;
-				// These are Windows Virtual Key Codes
-				// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
-				var unprintable = k!=13 && k!=32 && k!=27 && (k<48||k>90) && (k<96||k>111) && (k<186||k>192) && (k<219||k>222);
-				// synthesize keypress for most unprintables and CTRL-keys
-				if(unprintable||evt.ctrlKey){
-					var c = unprintable ? 0 : k;
-					if(evt.ctrlKey){
-						if(k==3 || k==13){
-							return; // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively 
-						}else if(c>95 && c<106){ 
-							c -= 48; // map CTRL-[numpad 0-9] to ASCII
-						}else if((!evt.shiftKey)&&(c>=65&&c<=90)){ 
-							c += 32; // map CTRL-[A-Z] to lowercase
-						}else{ 
-							c = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
-						}
-					}
-					// simulate a keypress event
-					var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
-					kp.call(evt.currentTarget, faux);
-					evt.cancelBubble = faux.cancelBubble;
-					evt.returnValue = faux.returnValue;
-					_trySetKeyCode(evt, faux.keyCode);
-				}
-			},
-			// Called in Event scope
-			_stopPropagation: function(){
-				this.cancelBubble = true; 
-			},
-			_preventDefault: function(){
-				// Setting keyCode to 0 is the only way to prevent certain keypresses (namely
-				// ctrl-combinations that correspond to menu accelerator keys).
-				// Otoh, it prevents upstream listeners from getting this information
-				// Try to split the difference here by clobbering keyCode only for ctrl 
-				// combinations. If you still need to access the key upstream, bubbledKeyCode is
-				// provided as a workaround.
-				this.bubbledKeyCode = this.keyCode;
-				if(this.ctrlKey){_trySetKeyCode(this, 0);}
-				this.returnValue = false;
-			}
-		});
-				
-		// override stopEvent for IE
-		dojo.stopEvent = function(evt){
-			evt = evt || window.event;
-			del._stopPropagation.call(evt);
-			del._preventDefault.call(evt);
-		}
-	}
-	
-	del._synthesizeEvent = function(evt, props){
-			var faux = dojo.mixin({}, evt, props);
-			del._setKeyChar(faux);
-			// FIXME: would prefer to use dojo.hitch: dojo.hitch(evt, evt.preventDefault); 
-			// but it throws an error when preventDefault is invoked on Safari
-			// does Event.preventDefault not support "apply" on Safari?
-			faux.preventDefault = function(){ evt.preventDefault(); }; 
-			faux.stopPropagation = function(){ evt.stopPropagation(); }; 
-			return faux;
-	}
-	
-		// Opera event normalization
-	if(dojo.isOpera){
-		dojo.mixin(del, {
-			_fixEvent: function(evt, sender){
-				switch(evt.type){
-					case "keypress":
-						var c = evt.which;
-						if(c==3){
-							c=99; // Mozilla maps CTRL-BREAK to CTRL-c
-						}
-						// can't trap some keys at all, like INSERT and DELETE
-						// there is no differentiating info between DELETE and ".", or INSERT and "-"
-						c = c<41 && !evt.shiftKey ? 0 : c;
-						if(evt.ctrlKey && !evt.shiftKey && c>=65 && c<=90){
-							// lowercase CTRL-[A-Z] keys
-							c += 32;
-						}
-						return del._synthesizeEvent(evt, { charCode: c });
-				}
-				return evt;
-			}
-		});
-	}
-	
-		// Webkit event normalization
-	if(dojo.isWebKit){
-				del._add = del.add;
-		del._remove = del.remove;
-
-		dojo.mixin(del, {
-			add: function(/*DOMNode*/ node, /*String*/ event, /*Function*/ fp){
-				if(!node){return;} // undefined
-				var handle = del._add(node, event, fp);
-				if(del._normalizeEventName(event) == "keypress"){
-					// we need to listen to onkeydown to synthesize
-					// keypress events that otherwise won't fire
-					// in Safari 3.1+: https://lists.webkit.org/pipermail/webkit-dev/2007-December/002992.html
-					handle._stealthKeyDownHandle = del._add(node, "keydown", function(evt){
-						//A variation on the IE _stealthKeydown function
-						//Synthesize an onkeypress event, but only for unprintable characters.
-						var k=evt.keyCode;
-						// These are Windows Virtual Key Codes
-						// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
-						var unprintable = k!=13 && k!=32 && (k<48 || k>90) && (k<96 || k>111) && (k<186 || k>192) && (k<219 || k>222);
-						// synthesize keypress for most unprintables and CTRL-keys
-						if(unprintable || evt.ctrlKey){
-							var c = unprintable ? 0 : k;
-							if(evt.ctrlKey){
-								if(k==3 || k==13){
-									return; // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively 
-								}else if(c>95 && c<106){ 
-									c -= 48; // map CTRL-[numpad 0-9] to ASCII
-								}else if(!evt.shiftKey && c>=65 && c<=90){ 
-									c += 32; // map CTRL-[A-Z] to lowercase
-								}else{ 
-									c = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
-								}
-							}
-							// simulate a keypress event
-							var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
-							fp.call(evt.currentTarget, faux);
-						}
-					});
-				}
-				return handle; /*Handle*/
-			},
-
-			remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
-				if(node){
-					if(handle._stealthKeyDownHandle){
-						del._remove(node, "keydown", handle._stealthKeyDownHandle);
-					}
-					del._remove(node, event, handle);
-				}
-			},
-			_fixEvent: function(evt, sender){
-				switch(evt.type){
-					case "keypress":
-						if(evt.faux){ return evt; }
-						var c = evt.charCode;
-						c = c>=32 ? c : 0;
-						return del._synthesizeEvent(evt, {charCode: c, faux: true});
-				}
-				return evt;
-			}
-		});
-		}
-	})();
-
-if(dojo.isIE){
-	// keep this out of the closure
-	// closing over 'iel' or 'ieh' b0rks leak prevention
-	// ls[i] is an index into the master handler array
-	dojo._ieDispatcher = function(args, sender){
-		var ap = Array.prototype,
-			h = dojo._ie_listener.handlers,
-			c = args.callee,
-			ls = c[dojo._ieListenersName],
-			t = h[c.target];
-		// return value comes from original target function
-		var r = t && t.apply(sender, args);
-		// make local copy of listener array so it's immutable during processing
-		var lls = [].concat(ls);
-		// invoke listeners after target function
-		for(var i in lls){
-			var f = h[lls[i]];
-			if(!(i in ap) && f){
-				f.apply(sender, args);
-			}
-		}
-		return r;
-	}
-	dojo._getIeDispatcher = function(){
-		// ensure the returned function closes over nothing ("new Function" apparently doesn't close)
-		return new Function(dojo._scopeName + "._ieDispatcher(arguments, this)"); // function
-	}
-	// keep this out of the closure to reduce RAM allocation
-	dojo._event_listener._fixCallback = function(fp){
-		var f = dojo._event_listener._fixEvent;
-		return function(e){ return fp.call(this, f(e, this)); };
-	}
-}
-
-}
-
-if(!dojo._hasResource["dojo._base.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.html"] = true;
-
-dojo.provide("dojo._base.html");
-
-// FIXME: need to add unit tests for all the semi-public methods
-
-try{
-	document.execCommand("BackgroundImageCache", false, true);
-}catch(e){
-	// sane browsers don't have cache "issues"
-}
-
-// =============================
-// DOM Functions
-// =============================
-
-/*=====
-dojo.byId = function(id, doc){
-	//	summary:
-	//		Returns DOM node with matching `id` attribute or `null`
-	//		if not found. If `id` is a DomNode, this function is a no-op.
-	//
-	//	id: String|DOMNode
-	//	 	A string to match an HTML id attribute or a reference to a DOM Node
-	//
-	//	doc: Document?
-	//		Document to work in. Defaults to the current value of
-	//		dojo.doc.  Can be used to retrieve
-	//		node references from other documents.
-	//
-	//	example:
-	//	Look up a node by ID:
-	//	|	var n = dojo.byId("foo");
-	//
-	//	example:
-	//	Check if a node exists, and use it.
-	//	|	var n = dojo.byId("bar");
-	//	|	if(n){ doStuff() ... }
-	//
-	//	example:
-	//	Allow string or DomNode references to be passed to a custom function:
-	//	|	var foo = function(nodeOrId){
-	//	|		nodeOrId = dojo.byId(nodeOrId);
-	//	|		// ... more stuff
-	//	|	}
-=====*/
-
-if(dojo.isIE || dojo.isOpera){
-	dojo.byId = function(id, doc){
-		if(typeof id != "string"){
-			return id;
-		}
-		var _d = doc || dojo.doc, te = _d.getElementById(id);
-		// attributes.id.value is better than just id in case the 
-		// user has a name=id inside a form
-		if(te && (te.attributes.id.value == id || te.id == id)){
-			return te;
-		}else{
-			var eles = _d.all[id];
-			if(!eles || eles.nodeName){
-				eles = [eles];
-			}
-			// if more than 1, choose first with the correct id
-			var i=0;
-			while((te=eles[i++])){
-				if((te.attributes && te.attributes.id && te.attributes.id.value == id)
-					|| te.id == id){
-					return te;
-				}
-			}
-		}
-	};
-}else{
-	dojo.byId = function(id, doc){
-		// inline'd type check
-		return (typeof id == "string") ? (doc || dojo.doc).getElementById(id) : id; // DomNode
-	};
-}
-/*=====
-};
-=====*/
-
-(function(){
-	var d = dojo;
-	var byId = d.byId;
-
-	var _destroyContainer = null,
-		_destroyDoc;
-		d.addOnWindowUnload(function(){
-		_destroyContainer = null; //prevent IE leak
-	});
-	
-/*=====
-	dojo._destroyElement = function(node){
-		// summary:
-		// 		Existing alias for `dojo.destroy`. Deprecated, will be removed
-		// 		in 2.0
-	}
-=====*/
-	dojo._destroyElement = dojo.destroy = function(/*String|DomNode*/node){
-		//	summary:
-		//		Removes a node from its parent, clobbering it and all of its
-		//		children.
-		//
-		//	description:
-		//		Removes a node from its parent, clobbering it and all of its
-		//		children. Function only works with DomNodes, and returns nothing.
-		//
-		//	node:
-		//		A String ID or DomNode reference of the element to be destroyed
-		//
-		//	example:
-		//	Destroy a node byId:
-		//	|	dojo.destroy("someId");
-		//
-		//	example:
-		//	Destroy all nodes in a list by reference:
-		//	|	dojo.query(".someNode").forEach(dojo.destroy);
-
-		node = byId(node);
-		try{
-			var doc = node.ownerDocument;
-			// cannot use _destroyContainer.ownerDocument since this can throw an exception on IE
-			if(!_destroyContainer || _destroyDoc != doc){
-				_destroyContainer = doc.createElement("div");
-				_destroyDoc = doc;
-			}
-			_destroyContainer.appendChild(node.parentNode ? node.parentNode.removeChild(node) : node);
-			// NOTE: see http://trac.dojotoolkit.org/ticket/2931. This may be a bug and not a feature
-			_destroyContainer.innerHTML = "";
-		}catch(e){
-			/* squelch */
-		}
-	};
-
-	dojo.isDescendant = function(/*DomNode|String*/node, /*DomNode|String*/ancestor){
-		//	summary:
-		//		Returns true if node is a descendant of ancestor
-		//	node: string id or node reference to test
-		//	ancestor: string id or node reference of potential parent to test against
-		//
-		// example:
-		//	Test is node id="bar" is a descendant of node id="foo"
-		//	|	if(dojo.isDescendant("bar", "foo")){ ... }
-		try{
-			node = byId(node);
-			ancestor = byId(ancestor);
-			while(node){
-				if(node == ancestor){
-					return true; // Boolean
-				}
-				node = node.parentNode;
-			}
-		}catch(e){ /* squelch, return false */ }
-		return false; // Boolean
-	};
-
-	dojo.setSelectable = function(/*DomNode|String*/node, /*Boolean*/selectable){
-		//	summary: 
-		//		Enable or disable selection on a node
-		//	node:
-		//		id or reference to node
-		//	selectable:
-		//		state to put the node in. false indicates unselectable, true 
-		//		allows selection.
-		//	example:
-		//	Make the node id="bar" unselectable
-		//	|	dojo.setSelectable("bar"); 
-		//	example:
-		//	Make the node id="bar" selectable
-		//	|	dojo.setSelectable("bar", true);
-		node = byId(node);
-				if(d.isMozilla){
-			node.style.MozUserSelect = selectable ? "" : "none";
-		}else if(d.isKhtml || d.isWebKit){
-					node.style.KhtmlUserSelect = selectable ? "auto" : "none";
-				}else if(d.isIE){
-			var v = (node.unselectable = selectable ? "" : "on");
-			d.query("*", node).forEach("item.unselectable = '"+v+"'");
-		}
-				//FIXME: else?  Opera?
-	};
-
-	var _insertBefore = function(/*DomNode*/node, /*DomNode*/ref){
-		var parent = ref.parentNode;
-		if(parent){
-			parent.insertBefore(node, ref);
-		}
-	};
-
-	var _insertAfter = function(/*DomNode*/node, /*DomNode*/ref){
-		//	summary:
-		//		Try to insert node after ref
-		var parent = ref.parentNode;
-		if(parent){
-			if(parent.lastChild == ref){
-				parent.appendChild(node);
-			}else{
-				parent.insertBefore(node, ref.nextSibling);
-			}
-		}
-	};
-
-	dojo.place = function(node, refNode, position){
-		//	summary:
-		//		Attempt to insert node into the DOM, choosing from various positioning options.
-		//		Returns the first argument resolved to a DOM node.
-		//
-		//	node: String|DomNode
-		//		id or node reference, or HTML fragment starting with "<" to place relative to refNode
-		//
-		//	refNode: String|DomNode
-		//		id or node reference to use as basis for placement
-		//
-		//	position: String|Number?
-		//		string noting the position of node relative to refNode or a
-		//		number indicating the location in the childNodes collection of refNode.
-		//		Accepted string values are:
-		//	|	* before
-		//	|	* after
-		//	|	* replace
-		//	|	* only
-		//	|	* first
-		//	|	* last
-		//		"first" and "last" indicate positions as children of refNode, "replace" replaces refNode,
-		//		"only" replaces all children.  position defaults to "last" if not specified
-		//
-		//	returns: DomNode
-		//		Returned values is the first argument resolved to a DOM node.
-		//
-		//		.place() is also a method of `dojo.NodeList`, allowing `dojo.query` node lookups.
-		//
-		// example:
-		//		Place a node by string id as the last child of another node by string id:
-		//	|	dojo.place("someNode", "anotherNode");
-		//
-		// example:
-		//		Place a node by string id before another node by string id
-		//	|	dojo.place("someNode", "anotherNode", "before");
-		//
-		// example:
-		//		Create a Node, and place it in the body element (last child):
-		//	|	dojo.place("<div></div>", dojo.body());
-		//
-		// example:
-		//		Put a new LI as the first child of a list by id:
-		//	|	dojo.place("<li></li>", "someUl", "first");
-
-		refNode = byId(refNode);
-		if(typeof node == "string"){ // inline'd type check
-			node = node.charAt(0) == "<" ? d._toDom(node, refNode.ownerDocument) : byId(node);
-		}
-		if(typeof position == "number"){ // inline'd type check
-			var cn = refNode.childNodes;
-			if(!cn.length || cn.length <= position){
-				refNode.appendChild(node);
-			}else{
-				_insertBefore(node, cn[position < 0 ? 0 : position]);
-			}
-		}else{
-			switch(position){
-				case "before":
-					_insertBefore(node, refNode);
-					break;
-				case "after":
-					_insertAfter(node, refNode);
-					break;
-				case "replace":
-					refNode.parentNode.replaceChild(node, refNode);
-					break;
-				case "only":
-					d.empty(refNode);
-					refNode.appendChild(node);
-					break;
-				case "first":
-					if(refNode.firstChild){
-						_insertBefore(node, refNode.firstChild);
-						break;
-					}
-					// else fallthrough...
-				default: // aka: last
-					refNode.appendChild(node);
-			}
-		}
-		return node; // DomNode
-	}
-
-	// Box functions will assume this model.
-	// On IE/Opera, BORDER_BOX will be set if the primary document is in quirks mode.
-	// Can be set to change behavior of box setters.
-
-	// can be either:
-	//	"border-box"
-	//	"content-box" (default)
-	dojo.boxModel = "content-box";
-
-	// We punt per-node box mode testing completely.
-	// If anybody cares, we can provide an additional (optional) unit 
-	// that overrides existing code to include per-node box sensitivity.
-
-	// Opera documentation claims that Opera 9 uses border-box in BackCompat mode.
-	// but experiments (Opera 9.10.8679 on Windows Vista) indicate that it actually continues to use content-box.
-	// IIRC, earlier versions of Opera did in fact use border-box.
-	// Opera guys, this is really confusing. Opera being broken in quirks mode is not our fault.
-
-		if(d.isIE /*|| dojo.isOpera*/){
-		// client code may have to adjust if compatMode varies across iframes
-		d.boxModel = document.compatMode == "BackCompat" ? "border-box" : "content-box";
-	}
-	
-	// =============================
-	// Style Functions
-	// =============================
-
-	// getComputedStyle drives most of the style code.
-	// Wherever possible, reuse the returned object.
-	//
-	// API functions below that need to access computed styles accept an 
-	// optional computedStyle parameter.
-	// If this parameter is omitted, the functions will call getComputedStyle themselves.
-	// This way, calling code can access computedStyle once, and then pass the reference to 
-	// multiple API functions.
-
-/*=====
-	dojo.getComputedStyle = function(node){
-		//	summary:
-		//		Returns a "computed style" object.
-		//
-		//	description:
-		//		Gets a "computed style" object which can be used to gather
-		//		information about the current state of the rendered node.
-		//
-		//		Note that this may behave differently on different browsers.
-		//		Values may have different formats and value encodings across
-		//		browsers.
-		//
-		//		Note also that this method is expensive.  Wherever possible,
-		//		reuse the returned object.
-		//
-		//		Use the dojo.style() method for more consistent (pixelized)
-		//		return values.
-		//
-		//	node: DOMNode
-		//		A reference to a DOM node. Does NOT support taking an
-		//		ID string for speed reasons.
-		//	example:
-		//	|	dojo.getComputedStyle(dojo.byId('foo')).borderWidth;
-		//
-		//	example:
-		//	Reusing the returned object, avoiding multiple lookups:
-		//	|	var cs = dojo.getComputedStyle(dojo.byId("someNode"));
-		//	|	var w = cs.width, h = cs.height;
-		return; // CSS2Properties
-	}
-=====*/
-
-	// Although we normally eschew argument validation at this
-	// level, here we test argument 'node' for (duck)type,
-	// by testing nodeType, ecause 'document' is the 'parentNode' of 'body'
-	// it is frequently sent to this function even 
-	// though it is not Element.
-	var gcs;
-		if(d.isWebKit){
-			gcs = function(/*DomNode*/node){
-			var s;
-			if(node.nodeType == 1){
-				var dv = node.ownerDocument.defaultView;
-				s = dv.getComputedStyle(node, null);
-				if(!s && node.style){
-					node.style.display = "";
-					s = dv.getComputedStyle(node, null);
-				}
-			}
-			return s || {};
-		};
-		}else if(d.isIE){
-		gcs = function(node){
-			// IE (as of 7) doesn't expose Element like sane browsers
-			return node.nodeType == 1 /* ELEMENT_NODE*/ ? node.currentStyle : {};
-		};
-	}else{
-		gcs = function(node){
-			return node.nodeType == 1 ?
-				node.ownerDocument.defaultView.getComputedStyle(node, null) : {};
-		};
-	}
-		dojo.getComputedStyle = gcs;
-
-		if(!d.isIE){
-			d._toPixelValue = function(element, value){
-			// style values can be floats, client code may want
-			// to round for integer pixels.
-			return parseFloat(value) || 0;
-		};
-		}else{
-		d._toPixelValue = function(element, avalue){
-			if(!avalue){ return 0; }
-			// on IE7, medium is usually 4 pixels
-			if(avalue == "medium"){ return 4; }
-			// style values can be floats, client code may
-			// want to round this value for integer pixels.
-			if(avalue.slice && avalue.slice(-2) == 'px'){ return parseFloat(avalue); }
-			with(element){
-				var sLeft = style.left;
-				var rsLeft = runtimeStyle.left;
-				runtimeStyle.left = currentStyle.left;
-				try{
-					// 'avalue' may be incompatible with style.left, which can cause IE to throw
-					// this has been observed for border widths using "thin", "medium", "thick" constants
-					// those particular constants could be trapped by a lookup
-					// but perhaps there are more
-					style.left = avalue;
-					avalue = style.pixelLeft;
-				}catch(e){
-					avalue = 0;
-				}
-				style.left = sLeft;
-				runtimeStyle.left = rsLeft;
-			}
-			return avalue;
-		}
-	}
-		var px = d._toPixelValue;
-
-	// FIXME: there opacity quirks on FF that we haven't ported over. Hrm.
-	/*=====
-	dojo._getOpacity = function(node){
-			//	summary:
-			//		Returns the current opacity of the passed node as a
-			//		floating-point value between 0 and 1.
-			//	node: DomNode
-			//		a reference to a DOM node. Does NOT support taking an
-			//		ID string for speed reasons.
-			//	returns: Number between 0 and 1
-			return; // Number
-	}
-	=====*/
-
-		var astr = "DXImageTransform.Microsoft.Alpha";
-	var af = function(n, f){
-		try{
-			return n.filters.item(astr);
-		}catch(e){
-			return f ? {} : null;
-		}
-	};
-
-		dojo._getOpacity =
-			d.isIE ? function(node){
-			try{
-				return af(node).Opacity / 100; // Number
-			}catch(e){
-				return 1; // Number
-			}
-		} :
-			function(node){
-			return gcs(node).opacity;
-		};
-
-	/*=====
-	dojo._setOpacity = function(node, opacity){
-			//	summary:
-			//		set the opacity of the passed node portably. Returns the
-			//		new opacity of the node.
-			//	node: DOMNode
-			//		a reference to a DOM node. Does NOT support taking an
-			//		ID string for performance reasons.
-			//	opacity: Number
-			//		A Number between 0 and 1. 0 specifies transparent.
-			//	returns: Number between 0 and 1
-			return; // Number
-	}
-	=====*/
-
-	dojo._setOpacity =
-				d.isIE ? function(/*DomNode*/node, /*Number*/opacity){
-			var ov = opacity * 100;
-			node.style.zoom = 1.0;
-
-			// on IE7 Alpha(Filter opacity=100) makes text look fuzzy so disable it altogether (bug #2661),
-			//but still update the opacity value so we can get a correct reading if it is read later.
-			af(node, 1).Enabled = !(opacity == 1);
-
-			if(!af(node)){
-				node.style.filter += " progid:" + astr + "(Opacity=" + ov + ")";
-			}else{
-				af(node, 1).Opacity = ov;
-			}
-
-			if(node.nodeName.toLowerCase() == "tr"){
-				d.query("> td", node).forEach(function(i){
-					d._setOpacity(i, opacity);
-				});
-			}
-			return opacity;
-		} :
-				function(node, opacity){
-			return node.style.opacity = opacity;
-		};
-
-	var _pixelNamesCache = {
-		left: true, top: true
-	};
-	var _pixelRegExp = /margin|padding|width|height|max|min|offset/;  // |border
-	var _toStyleValue = function(node, type, value){
-		type = type.toLowerCase(); // FIXME: should we really be doing string case conversion here? Should we cache it? Need to profile!
-				if(d.isIE){
-			if(value == "auto"){
-				if(type == "height"){ return node.offsetHeight; }
-				if(type == "width"){ return node.offsetWidth; }
-			}
-			if(type == "fontweight"){
-				switch(value){
-					case 700: return "bold";
-					case 400:
-					default: return "normal";
-				}
-			}
-		}
-				if(!(type in _pixelNamesCache)){
-			_pixelNamesCache[type] = _pixelRegExp.test(type);
-		}
-		return _pixelNamesCache[type] ? px(node, value) : value;
-	};
-
-	var _floatStyle = d.isIE ? "styleFloat" : "cssFloat",
-		_floatAliases = { "cssFloat": _floatStyle, "styleFloat": _floatStyle, "float": _floatStyle }
-	;
-
-	// public API
-
-	dojo.style = function(	/*DomNode|String*/ node,
-							/*String?|Object?*/ style,
-							/*String?*/ value){
-		//	summary:
-		//		Accesses styles on a node. If 2 arguments are
-		//		passed, acts as a getter. If 3 arguments are passed, acts
-		//		as a setter.
-		//	description:
-		//		Getting the style value uses the computed style for the node, so the value
-		//		will be a calculated value, not just the immediate node.style value.
-		//		Also when getting values, use specific style names,
-		//		like "borderBottomWidth" instead of "border" since compound values like
-		//		"border" are not necessarily reflected as expected.
-		//		If you want to get node dimensions, use `dojo.marginBox()`, 
-		//		`dojo.contentBox()` or `dojo.position()`.
-		//	node:
-		//		id or reference to node to get/set style for
-		//	style:
-		//		the style property to set in DOM-accessor format
-		//		("borderWidth", not "border-width") or an object with key/value
-		//		pairs suitable for setting each property.
-		//	value:
-		//		If passed, sets value on the node for style, handling
-		//		cross-browser concerns.  When setting a pixel value,
-		//		be sure to include "px" in the value. For instance, top: "200px".
-		//		Otherwise, in some cases, some browsers will not apply the style.
-		//	example:
-		//		Passing only an ID or node returns the computed style object of
-		//		the node:
-		//	|	dojo.style("thinger");
-		//	example:
-		//		Passing a node and a style property returns the current
-		//		normalized, computed value for that property:
-		//	|	dojo.style("thinger", "opacity"); // 1 by default
-		//
-		//	example:
-		//		Passing a node, a style property, and a value changes the
-		//		current display of the node and returns the new computed value
-		//	|	dojo.style("thinger", "opacity", 0.5); // == 0.5
-		//
-		//	example:
-		//		Passing a node, an object-style style property sets each of the values in turn and returns the computed style object of the node:
-		//	|	dojo.style("thinger", {
-		//	|		"opacity": 0.5,
-		//	|		"border": "3px solid black",
-		//	|		"height": "300px"
-		//	|	});
-		//
-		// 	example:
-		//		When the CSS style property is hyphenated, the JavaScript property is camelCased.
-		//		font-size becomes fontSize, and so on.
-		//	|	dojo.style("thinger",{
-		//	|		fontSize:"14pt",
-		//	|		letterSpacing:"1.2em"
-		//	|	});
-		//
-		//	example:
-		//		dojo.NodeList implements .style() using the same syntax, omitting the "node" parameter, calling
-		//		dojo.style() on every element of the list. See: `dojo.query()` and `dojo.NodeList()`
-		//	|	dojo.query(".someClassName").style("visibility","hidden");
-		//	|	// or
-		//	|	dojo.query("#baz > div").style({
-		//	|		opacity:0.75,
-		//	|		fontSize:"13pt"
-		//	|	});
-
-		var n = byId(node), args = arguments.length, op = (style == "opacity");
-		style = _floatAliases[style] || style;
-		if(args == 3){
-			return op ? d._setOpacity(n, value) : n.style[style] = value; /*Number*/
-		}
-		if(args == 2 && op){
-			return d._getOpacity(n);
-		}
-		var s = gcs(n);
-		if(args == 2 && typeof style != "string"){ // inline'd type check
-			for(var x in style){
-				d.style(node, x, style[x]);
-			}
-			return s;
-		}
-		return (args == 1) ? s : _toStyleValue(n, style, s[style] || n.style[style]); /* CSS2Properties||String||Number */
-	}
-
-	// =============================
-	// Box Functions
-	// =============================
-
-	dojo._getPadExtents = function(/*DomNode*/n, /*Object*/computedStyle){
-		//	summary:
-		// 		Returns object with special values specifically useful for node
-		// 		fitting.
-		//	description:
-		//		Returns an object with `w`, `h`, `l`, `t` properties:
-		//	|		l/t = left/top padding (respectively)
-		//	|		w = the total of the left and right padding 
-		//	|		h = the total of the top and bottom padding
-		//		If 'node' has position, l/t forms the origin for child nodes.
-		//		The w/h are used for calculating boxes.
-		//		Normally application code will not need to invoke this
-		//		directly, and will use the ...box... functions instead.
-		var 
-			s = computedStyle||gcs(n),
-			l = px(n, s.paddingLeft),
-			t = px(n, s.paddingTop);
-		return {
-			l: l,
-			t: t,
-			w: l+px(n, s.paddingRight),
-			h: t+px(n, s.paddingBottom)
-		};
-	}
-
-	dojo._getBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){
-		//	summary:
-		//		returns an object with properties useful for noting the border
-		//		dimensions.
-		//	description:
-		// 		* l/t = the sum of left/top border (respectively)
-		//		* w = the sum of the left and right border
-		//		* h = the sum of the top and bottom border
-		//
-		//		The w/h are used for calculating boxes.
-		//		Normally application code will not need to invoke this
-		//		directly, and will use the ...box... functions instead.
-		var 
-			ne = "none",
-			s = computedStyle||gcs(n),
-			bl = (s.borderLeftStyle != ne ? px(n, s.borderLeftWidth) : 0),
-			bt = (s.borderTopStyle != ne ? px(n, s.borderTopWidth) : 0);
-		return {
-			l: bl,
-			t: bt,
-			w: bl + (s.borderRightStyle!=ne ? px(n, s.borderRightWidth) : 0),
-			h: bt + (s.borderBottomStyle!=ne ? px(n, s.borderBottomWidth) : 0)
-		};
-	}
-
-	dojo._getPadBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){
-		//	summary:
-		//		Returns object with properties useful for box fitting with
-		//		regards to padding.
-		// description:
-		//		* l/t = the sum of left/top padding and left/top border (respectively)
-		//		* w = the sum of the left and right padding and border
-		//		* h = the sum of the top and bottom padding and border
-		//
-		//		The w/h are used for calculating boxes.
-		//		Normally application code will not need to invoke this
-		//		directly, and will use the ...box... functions instead.
-		var 
-			s = computedStyle||gcs(n),
-			p = d._getPadExtents(n, s),
-			b = d._getBorderExtents(n, s);
-		return {
-			l: p.l + b.l,
-			t: p.t + b.t,
-			w: p.w + b.w,
-			h: p.h + b.h
-		};
-	}
-
-	dojo._getMarginExtents = function(n, computedStyle){
-		//	summary:
-		//		returns object with properties useful for box fitting with
-		//		regards to box margins (i.e., the outer-box).
-		//
-		//		* l/t = marginLeft, marginTop, respectively
-		//		* w = total width, margin inclusive
-		//		* h = total height, margin inclusive
-		//
-		//		The w/h are used for calculating boxes.
-		//		Normally application code will not need to invoke this
-		//		directly, and will use the ...box... functions instead.
-		var 
-			s = computedStyle||gcs(n),
-			l = px(n, s.marginLeft),
-			t = px(n, s.marginTop),
-			r = px(n, s.marginRight),
-			b = px(n, s.marginBottom);
-		if(d.isWebKit && (s.position != "absolute")){
-			// FIXME: Safari's version of the computed right margin
-			// is the space between our right edge and the right edge 
-			// of our offsetParent.
-			// What we are looking for is the actual margin value as 
-			// determined by CSS.
-			// Hack solution is to assume left/right margins are the same.
-			r = l;
-		}
-		return {
-			l: l,
-			t: t,
-			w: l+r,
-			h: t+b
-		};
-	}
-
-	// Box getters work in any box context because offsetWidth/clientWidth
-	// are invariant wrt box context
-	//
-	// They do *not* work for display: inline objects that have padding styles
-	// because the user agent ignores padding (it's bogus styling in any case)
-	//
-	// Be careful with IMGs because they are inline or block depending on 
-	// browser and browser mode.
-
-	// Although it would be easier to read, there are not separate versions of 
-	// _getMarginBox for each browser because:
-	// 1. the branching is not expensive
-	// 2. factoring the shared code wastes cycles (function call overhead)
-	// 3. duplicating the shared code wastes bytes
-
-	dojo._getMarginBox = function(/*DomNode*/node, /*Object*/computedStyle){
-		// summary:
-		//		returns an object that encodes the width, height, left and top
-		//		positions of the node's margin box.
-		var s = computedStyle || gcs(node), me = d._getMarginExtents(node, s);
-		var l = node.offsetLeft - me.l, t = node.offsetTop - me.t, p = node.parentNode;
-				if(d.isMoz){
-			// Mozilla:
-			// If offsetParent has a computed overflow != visible, the offsetLeft is decreased
-			// by the parent's border.
-			// We don't want to compute the parent's style, so instead we examine node's
-			// computed left/top which is more stable.
-			var sl = parseFloat(s.left), st = parseFloat(s.top);
-			if(!isNaN(sl) && !isNaN(st)){
-				l = sl, t = st;
-			}else{
-				// If child's computed left/top are not parseable as a number (e.g. "auto"), we
-				// have no choice but to examine the parent's computed style.
-				if(p && p.style){
-					var pcs = gcs(p);
-					if(pcs.overflow != "visible"){
-						var be = d._getBorderExtents(p, pcs);
-						l += be.l, t += be.t;
-					}
-				}
-			}
-		}else if(d.isOpera || (d.isIE > 7 && !d.isQuirks)){
-			// On Opera and IE 8, offsetLeft/Top includes the parent's border
-			if(p){
-				be = d._getBorderExtents(p);
-				l -= be.l;
-				t -= be.t;
-			}
-		}
-				return {
-			l: l,
-			t: t,
-			w: node.offsetWidth + me.w,
-			h: node.offsetHeight + me.h 
-		};
-	}
-
-	dojo._getContentBox = function(node, computedStyle){
-		// summary:
-		//		Returns an object that encodes the width, height, left and top
-		//		positions of the node's content box, irrespective of the
-		//		current box model.
-
-		// clientWidth/Height are important since the automatically account for scrollbars
-		// fallback to offsetWidth/Height for special cases (see #3378)
-		var s = computedStyle || gcs(node),
-			pe = d._getPadExtents(node, s),
-			be = d._getBorderExtents(node, s),
-			w = node.clientWidth,
-			h
-		;
-		if(!w){
-			w = node.offsetWidth, h = node.offsetHeight;
-		}else{
-			h = node.clientHeight, be.w = be.h = 0;
-		}
-		// On Opera, offsetLeft includes the parent's border
-				if(d.isOpera){ pe.l += be.l; pe.t += be.t; };
-				return {
-			l: pe.l,
-			t: pe.t,
-			w: w - pe.w - be.w,
-			h: h - pe.h - be.h
-		};
-	}
-
-	dojo._getBorderBox = function(node, computedStyle){
-		var s = computedStyle || gcs(node),
-			pe = d._getPadExtents(node, s),
-			cb = d._getContentBox(node, s)
-		;
-		return {
-			l: cb.l - pe.l,
-			t: cb.t - pe.t,
-			w: cb.w + pe.w,
-			h: cb.h + pe.h
-		};
-	}
-
-	// Box setters depend on box context because interpretation of width/height styles
-	// vary wrt box context.
-	//
-	// The value of dojo.boxModel is used to determine box context.
-	// dojo.boxModel can be set directly to change behavior.
-	//
-	// Beware of display: inline objects that have padding styles
-	// because the user agent ignores padding (it's a bogus setup anyway)
-	//
-	// Be careful with IMGs because they are inline or block depending on 
-	// browser and browser mode.
-	//
-	// Elements other than DIV may have special quirks, like built-in
-	// margins or padding, or values not detectable via computedStyle.
-	// In particular, margins on TABLE do not seems to appear 
-	// at all in computedStyle on Mozilla.
-
-	dojo._setBox = function(/*DomNode*/node, /*Number?*/l, /*Number?*/t, /*Number?*/w, /*Number?*/h, /*String?*/u){
-		//	summary:
-		//		sets width/height/left/top in the current (native) box-model
-		//		dimentions. Uses the unit passed in u.
-		//	node:
-		//		DOM Node reference. Id string not supported for performance
-		//		reasons.
-		//	l:
-		//		left offset from parent.
-		//	t:
-		//		top offset from parent.
-		//	w:
-		//		width in current box model.
-		//	h:
-		//		width in current box model.
-		//	u:
-		//		unit measure to use for other measures. Defaults to "px".
-		u = u || "px";
-		var s = node.style;
-		if(!isNaN(l)){ s.left = l + u; }
-		if(!isNaN(t)){ s.top = t + u; }
-		if(w >= 0){ s.width = w + u; }
-		if(h >= 0){ s.height = h + u; }
-	}
-
-	dojo._isButtonTag = function(/*DomNode*/node) {
-		// summary:
-		//		True if the node is BUTTON or INPUT.type="button".
-		return node.tagName == "BUTTON"
-			|| node.tagName=="INPUT" && (node.getAttribute("type")||'').toUpperCase() == "BUTTON"; // boolean
-	}
-
-	dojo._usesBorderBox = function(/*DomNode*/node){
-		//	summary:
-		//		True if the node uses border-box layout.
-
-		// We could test the computed style of node to see if a particular box
-		// has been specified, but there are details and we choose not to bother.
-
-		// TABLE and BUTTON (and INPUT type=button) are always border-box by default.
-		// If you have assigned a different box to either one via CSS then
-		// box functions will break.
-
-		var n = node.tagName;
-		return d.boxModel=="border-box" || n=="TABLE" || d._isButtonTag(node); // boolean
-	}
-
-	dojo._setContentSize = function(/*DomNode*/node, /*Number*/widthPx, /*Number*/heightPx, /*Object*/computedStyle){
-		//	summary:
-		//		Sets the size of the node's contents, irrespective of margins,
-		//		padding, or borders.
-		if(d._usesBorderBox(node)){
-			var pb = d._getPadBorderExtents(node, computedStyle);
-			if(widthPx >= 0){ widthPx += pb.w; }
-			if(heightPx >= 0){ heightPx += pb.h; }
-		}
-		d._setBox(node, NaN, NaN, widthPx, heightPx);
-	}
-
-	dojo._setMarginBox = function(/*DomNode*/node, 	/*Number?*/leftPx, /*Number?*/topPx,
-													/*Number?*/widthPx, /*Number?*/heightPx,
-													/*Object*/computedStyle){
-		//	summary:
-		//		sets the size of the node's margin box and placement
-		//		(left/top), irrespective of box model. Think of it as a
-		//		passthrough to dojo._setBox that handles box-model vagaries for
-		//		you.
-
-		var s = computedStyle || gcs(node),
-		// Some elements have special padding, margin, and box-model settings.
-		// To use box functions you may need to set padding, margin explicitly.
-		// Controlling box-model is harder, in a pinch you might set dojo.boxModel.
-			bb = d._usesBorderBox(node),
-			pb = bb ? _nilExtents : d._getPadBorderExtents(node, s)
-		;
-		if(d.isWebKit){
-			// on Safari (3.1.2), button nodes with no explicit size have a default margin
-			// setting an explicit size eliminates the margin.
-			// We have to swizzle the width to get correct margin reading.
-			if(d._isButtonTag(node)){
-				var ns = node.style;
-				if(widthPx >= 0 && !ns.width) { ns.width = "4px"; }
-				if(heightPx >= 0 && !ns.height) { ns.height = "4px"; }
-			}
-		}
-		var mb = d._getMarginExtents(node, s);
-		if(widthPx >= 0){ widthPx = Math.max(widthPx - pb.w - mb.w, 0); }
-		if(heightPx >= 0){ heightPx = Math.max(heightPx - pb.h - mb.h, 0); }
-		d._setBox(node, leftPx, topPx, widthPx, heightPx);
-	}
-
-	var _nilExtents = { l:0, t:0, w:0, h:0 };
-
-	// public API
-
-	dojo.marginBox = function(/*DomNode|String*/node, /*Object?*/box){
-		//	summary:
-		//		Getter/setter for the margin-box of node.
-		//	description:
-		//		Getter/setter for the margin-box of node.
-		//		Returns an object in the expected format of box (regardless
-		//		if box is passed). The object might look like:
-		//			`{ l: 50, t: 200, w: 300: h: 150 }`
-		//		for a node offset from its parent 50px to the left, 200px from
-		//		the top with a margin width of 300px and a margin-height of
-		//		150px.
-		//	node:
-		//		id or reference to DOM Node to get/set box for
-		//	box:
-		//		If passed, denotes that dojo.marginBox() should
-		//		update/set the margin box for node. Box is an object in the
-		//		above format. All properties are optional if passed.
-		//	example:
-		//	Retrieve the marginbox of a passed node
-		//	|	var box = dojo.marginBox("someNodeId");
-		//	|	console.dir(box);
-		//
-		//	example:
-		//	Set a node's marginbox to the size of another node
-		//	|	var box = dojo.marginBox("someNodeId");
-		//	|	dojo.marginBox("someOtherNode", box);
-		
-		var n = byId(node), s = gcs(n), b = box;
-		return !b ? d._getMarginBox(n, s) : d._setMarginBox(n, b.l, b.t, b.w, b.h, s); // Object
-	}
-
-	dojo.contentBox = function(/*DomNode|String*/node, /*Object?*/box){
-		//	summary:
-		//		Getter/setter for the content-box of node.
-		//	description:
-		//		Returns an object in the expected format of box (regardless if box is passed).
-		//		The object might look like:
-		//			`{ l: 50, t: 200, w: 300: h: 150 }`
-		//		for a node offset from its parent 50px to the left, 200px from
-		//		the top with a content width of 300px and a content-height of
-		//		150px. Note that the content box may have a much larger border
-		//		or margin box, depending on the box model currently in use and
-		//		CSS values set/inherited for node.
-		//	node:
-		//		id or reference to DOM Node to get/set box for
-		//	box:
-		//		If passed, denotes that dojo.contentBox() should
-		//		update/set the content box for node. Box is an object in the
-		//		above format. All properties are optional if passed.
-		var n = byId(node), s = gcs(n), b = box;
-		return !b ? d._getContentBox(n, s) : d._setContentSize(n, b.w, b.h, s); // Object
-	}
-
-	// =============================
-	// Positioning 
-	// =============================
-
-	var _sumAncestorProperties = function(node, prop){
-		if(!(node = (node||0).parentNode)){return 0}
-		var val, retVal = 0, _b = d.body();
-		while(node && node.style){
-			if(gcs(node).position == "fixed"){
-				return 0;
-			}
-			val = node[prop];
-			if(val){
-				retVal += val - 0;
-				// opera and khtml #body & #html has the same values, we only
-				// need one value
-				if(node == _b){ break; }
-			}
-			node = node.parentNode;
-		}
-		return retVal;	//	integer
-	}
-
-	dojo._docScroll = function(){
-		var n = d.global;
-		return "pageXOffset" in n? { x:n.pageXOffset, y:n.pageYOffset } :
-			(n=d.doc.documentElement, n.clientHeight? { x:d._fixIeBiDiScrollLeft(n.scrollLeft), y:n.scrollTop } :
-			(n=d.body(), { x:n.scrollLeft||0, y:n.scrollTop||0 }));
-	};
-
-	dojo._isBodyLtr = function(){
-		return "_bodyLtr" in d? d._bodyLtr :
-			d._bodyLtr = (d.body().dir || d.doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean 
-	}
-
-		dojo._getIeDocumentElementOffset = function(){
-		//	summary:
-		//		returns the offset in x and y from the document body to the
-		//		visual edge of the page
-		//	description:
-		// The following values in IE contain an offset:
-		//	|		event.clientX
-		//	|		event.clientY
-		//	|		node.getBoundingClientRect().left
-		//	|		node.getBoundingClientRect().top
-		//	 	But other position related values do not contain this offset,
-		//	 	such as node.offsetLeft, node.offsetTop, node.style.left and
-		//	 	node.style.top. The offset is always (2, 2) in LTR direction.
-		//	 	When the body is in RTL direction, the offset counts the width
-		//	 	of left scroll bar's width.  This function computes the actual
-		//	 	offset.
-
-		//NOTE: assumes we're being called in an IE browser
-
-		var de = d.doc.documentElement; // only deal with HTML element here, _abs handles body/quirks 
-
-		if(d.isIE < 8){
-			var r = de.getBoundingClientRect(); // works well for IE6+
-			//console.debug('rect left,top = ' + r.left+','+r.top + ', html client left/top = ' + de.clientLeft+','+de.clientTop + ', rtl = ' + (!d._isBodyLtr()) + ', quirks = ' + d.isQuirks);
-			var l = r.left,
-			    t = r.top;
-			if(d.isIE < 7){
-				l += de.clientLeft;	// scrollbar size in strict/RTL, or,
-				t += de.clientTop;	// HTML border size in strict
-			}
-			return {
-				x: l < 0? 0 : l, // FRAME element border size can lead to inaccurate negative values
-				y: t < 0? 0 : t
-			};
-		}else{
-			return {
-				x: 0,
-				y: 0
-			};
-		}
-
-	};
-	
-	dojo._fixIeBiDiScrollLeft = function(/*Integer*/ scrollLeft){
-		// In RTL direction, scrollLeft should be a negative value, but IE < 8
-		// returns a positive one. All codes using documentElement.scrollLeft
-		// must call this function to fix this error, otherwise the position
-		// will offset to right when there is a horizontal scrollbar.
-
-				var dd = d.doc;
-		if(d.isIE < 8 && !d._isBodyLtr()){
-			var de = d.isQuirks ? dd.body : dd.documentElement;
-			return scrollLeft + de.clientWidth - de.scrollWidth; // Integer
-		}
-				return scrollLeft; // Integer
-	}
-
-	// FIXME: need a setter for coords or a moveTo!!
-	dojo._abs = dojo.position = function(/*DomNode*/node, /*Boolean?*/includeScroll){
-		//	summary:
-		//		Gets the position and size of the passed element relative to
-		//		the viewport (if includeScroll==false), or relative to the
-		//		document root (if includeScroll==true).
-		//
-		//	description:
-		//		Returns an object of the form:
-		//			{ x: 100, y: 300, w: 20, h: 15 }
-		//		If includeScroll==true, the x and y values will include any
-		//		document offsets that may affect the position relative to the
-		//		viewport.
-		//		Uses the border-box model (inclusive of border and padding but
-		//		not margin).  Does not act as a setter.
-
-		var db = d.body(), dh = db.parentNode, ret;
-		node = byId(node);
-		if(node["getBoundingClientRect"]){
-			// IE6+, FF3+, super-modern WebKit, and Opera 9.6+ all take this branch
-			ret = node.getBoundingClientRect();
-			ret = { x: ret.left, y: ret.top, w: ret.right - ret.left, h: ret.bottom - ret.top };
-					if(d.isIE){
-				// On IE there's a 2px offset that we need to adjust for, see _getIeDocumentElementOffset()
-				var offset = d._getIeDocumentElementOffset();
-
-				// fixes the position in IE, quirks mode
-				ret.x -= offset.x + (d.isQuirks ? db.clientLeft+db.offsetLeft : 0);
-				ret.y -= offset.y + (d.isQuirks ? db.clientTop+db.offsetTop : 0);
-			}else if(d.isFF == 3){
-				// In FF3 you have to subtract the document element margins.
-				// Fixed in FF3.5 though.
-				var cs = gcs(dh);
-				ret.x -= px(dh, cs.marginLeft) + px(dh, cs.borderLeftWidth);
-				ret.y -= px(dh, cs.marginTop) + px(dh, cs.borderTopWidth);
-			}
-				}else{
-			// FF2 and older WebKit
-			ret = {
-				x: 0,
-				y: 0,
-				w: node.offsetWidth,
-				h: node.offsetHeight
-			};
-			if(node["offsetParent"]){
-				ret.x -= _sumAncestorProperties(node, "scrollLeft");
-				ret.y -= _sumAncestorProperties(node, "scrollTop");
-
-				var curnode = node;
-				do{
-					var n = curnode.offsetLeft,
-						t = curnode.offsetTop;
-					ret.x += isNaN(n) ? 0 : n;
-					ret.y += isNaN(t) ? 0 : t;
-
-					cs = gcs(curnode);
-					if(curnode != node){
-								if(d.isMoz){
-							// tried left+right with differently sized left/right borders
-							// it really is 2xleft border in FF, not left+right, even in RTL!
-							ret.x += 2 * px(curnode,cs.borderLeftWidth);
-							ret.y += 2 * px(curnode,cs.borderTopWidth);
-						}else{
-									ret.x += px(curnode, cs.borderLeftWidth);
-							ret.y += px(curnode, cs.borderTopWidth);
-								}
-							}
-					// static children in a static div in FF2 are affected by the div's border as well
-					// but offsetParent will skip this div!
-							if(d.isMoz && cs.position=="static"){
-						var parent=curnode.parentNode;
-						while(parent!=curnode.offsetParent){
-							var pcs=gcs(parent);
-							if(pcs.position=="static"){
-								ret.x += px(curnode,pcs.borderLeftWidth);
-								ret.y += px(curnode,pcs.borderTopWidth);
-							}
-							parent=parent.parentNode;
-						}
-					}
-							curnode = curnode.offsetParent;
-				}while((curnode != dh) && curnode);
-			}else if(node.x && node.y){
-				ret.x += isNaN(node.x) ? 0 : node.x;
-				ret.y += isNaN(node.y) ? 0 : node.y;
-			}
-		}
-		// account for document scrolling
-		// if offsetParent is used, ret value already includes scroll position
-		// so we may have to actually remove that value if !includeScroll
-		if(includeScroll){
-			var scroll = d._docScroll();
-			ret.x += scroll.x;
-			ret.y += scroll.y;
-		}
-
-		return ret; // Object
-	}
-
-	dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){
-		//	summary:
-		//		Deprecated: Use position() for border-box x/y/w/h
-		//		or marginBox() for margin-box w/h/l/t.
-		//		Returns an object representing a node's size and position.
-		//
-		//	description:
-		//		Returns an object that measures margin-box (w)idth/(h)eight
-		//		and absolute position x/y of the border-box. Also returned
-		//		is computed (l)eft and (t)op values in pixels from the
-		//		node's offsetParent as returned from marginBox().
-		//		Return value will be in the form:
-		//|			{ l: 50, t: 200, w: 300: h: 150, x: 100, y: 300 }
-		//		Does not act as a setter. If includeScroll is passed, the x and
-		//		y params are affected as one would expect in dojo.position().
-		var n = byId(node), s = gcs(n), mb = d._getMarginBox(n, s);
-		var abs = d.position(n, includeScroll);
-		mb.x = abs.x;
-		mb.y = abs.y;
-		return mb;
-	}
-
-	// =============================
-	// Element attribute Functions
-	// =============================
-
-	// dojo.attr() should conform to http://www.w3.org/TR/DOM-Level-2-Core/
-
-	var _propNames = {
-			// properties renamed to avoid clashes with reserved words
-			"class":   "className",
-			"for":     "htmlFor",
-			// properties written as camelCase
-			tabindex:  "tabIndex",
-			readonly:  "readOnly",
-			colspan:   "colSpan",
-			frameborder: "frameBorder",
-			rowspan:   "rowSpan",
-			valuetype: "valueType"
-		},
-		_attrNames = {
-			// original attribute names
-			classname: "class",
-			htmlfor:   "for",
-			// for IE
-			tabindex:  "tabIndex",
-			readonly:  "readOnly"
-		},
-		_forcePropNames = {
-			innerHTML: 1,
-			className: 1,
-			htmlFor:   d.isIE,
-			value:     1
-		};
-
-	var _fixAttrName = function(/*String*/ name){
-		return _attrNames[name.toLowerCase()] || name;
-	};
-
-	var _hasAttr = function(node, name){
-		var attr = node.getAttributeNode && node.getAttributeNode(name);
-		return attr && attr.specified; // Boolean
-	};
-
-	// There is a difference in the presence of certain properties and their default values
-	// between browsers. For example, on IE "disabled" is present on all elements,
-	// but it is value is "false"; "tabIndex" of <div> returns 0 by default on IE, yet other browsers
-	// can return -1.
-
-	dojo.hasAttr = function(/*DomNode|String*/node, /*String*/name){
-		//	summary:
-		//		Returns true if the requested attribute is specified on the
-		//		given element, and false otherwise.
-		//	node:
-		//		id or reference to the element to check
-		//	name:
-		//		the name of the attribute
-		//	returns:
-		//		true if the requested attribute is specified on the
-		//		given element, and false otherwise
-		var lc = name.toLowerCase();
-		return _forcePropNames[_propNames[lc] || name] || _hasAttr(byId(node), _attrNames[lc] || name);	// Boolean
-	}
-
-	var _evtHdlrMap = {}, _ctr = 0,
-		_attrId = dojo._scopeName + "attrid",
-		// the next dictionary lists elements with read-only innerHTML on IE
-		_roInnerHtml = {col: 1, colgroup: 1,
-			// frameset: 1, head: 1, html: 1, style: 1,
-			table: 1, tbody: 1, tfoot: 1, thead: 1, tr: 1, title: 1};
-
-	dojo.attr = function(/*DomNode|String*/node, /*String|Object*/name, /*String?*/value){
-		//	summary:
-		//		Gets or sets an attribute on an HTML element.
-		//	description:
-		//		Handles normalized getting and setting of attributes on DOM
-		//		Nodes. If 2 arguments are passed, and a the second argumnt is a
-		//		string, acts as a getter.
-		//
-		//		If a third argument is passed, or if the second argument is a
-		//		map of attributes, acts as a setter.
-		//
-		//		When passing functions as values, note that they will not be
-		//		directly assigned to slots on the node, but rather the default
-		//		behavior will be removed and the new behavior will be added
-		//		using `dojo.connect()`, meaning that event handler properties
-		//		will be normalized and that some caveats with regards to
-		//		non-standard behaviors for onsubmit apply. Namely that you
-		//		should cancel form submission using `dojo.stopEvent()` on the
-		//		passed event object instead of returning a boolean value from
-		//		the handler itself.
-		//	node:
-		//		id or reference to the element to get or set the attribute on
-		//	name:
-		//		the name of the attribute to get or set.
-		//	value:
-		//		The value to set for the attribute
-		//	returns:
-		//		when used as a getter, the value of the requested attribute
-		//		or null if that attribute does not have a specified or
-		//		default value;
-		//
-		//		when used as a setter, the DOM node
-		//
-		//	example:
-		//	|	// get the current value of the "foo" attribute on a node
-		//	|	dojo.attr(dojo.byId("nodeId"), "foo");
-		//	|	// or we can just pass the id:
-		//	|	dojo.attr("nodeId", "foo");
-		//
-		//	example:
-		//	|	// use attr() to set the tab index
-		//	|	dojo.attr("nodeId", "tabIndex", 3);
-		//	|
-		//
-		//	example:
-		//	Set multiple values at once, including event handlers:
-		//	|	dojo.attr("formId", {
-		//	|		"foo": "bar",
-		//	|		"tabIndex": -1,
-		//	|		"method": "POST",
-		//	|		"onsubmit": function(e){
-		//	|			// stop submitting the form. Note that the IE behavior
-		//	|			// of returning true or false will have no effect here
-		//	|			// since our handler is connect()ed to the built-in
-		//	|			// onsubmit behavior and so we need to use
-		//	|			// dojo.stopEvent() to ensure that the submission
-		//	|			// doesn't proceed.
-		//	|			dojo.stopEvent(e);
-		//	|
-		//	|			// submit the form with Ajax
-		//	|			dojo.xhrPost({ form: "formId" });
-		//	|		}
-		//	|	});
-		//
-		//	example:
-		//	Style is s special case: Only set with an object hash of styles
-		//	|	dojo.attr("someNode",{
-		//	|		id:"bar",
-		//	|		style:{
-		//	|			width:"200px", height:"100px", color:"#000"
-		//	|		}
-		//	|	});
-		//
-		//	example:
-		//	Again, only set style as an object hash of styles:
-		//	|	var obj = { color:"#fff", backgroundColor:"#000" };
-		//	|	dojo.attr("someNode", "style", obj);
-		//	|
-		//	|	// though shorter to use `dojo.style()` in this case:
-		//	|	dojo.style("someNode", obj);
-
-		node = byId(node);
-		var args = arguments.length, prop;
-		if(args == 2 && typeof name != "string"){ // inline'd type check
-			// the object form of setter: the 2nd argument is a dictionary
-			for(var x in name){
-				d.attr(node, x, name[x]);
-			}
-			return node; // DomNode
-		}
-		var lc = name.toLowerCase(),
-			propName = _propNames[lc] || name,
-			forceProp = _forcePropNames[propName],
-			attrName = _attrNames[lc] || name;
-		if(args == 3){
-			// setter
-			do{
-				if(propName == "style" && typeof value != "string"){ // inline'd type check
-					// special case: setting a style
-					d.style(node, value);
-					break;
-				}
-				if(propName == "innerHTML"){
-					// special case: assigning HTML
-										if(d.isIE && node.tagName.toLowerCase() in _roInnerHtml){
-						d.empty(node);
-						node.appendChild(d._toDom(value, node.ownerDocument));
-					}else{
-											node[propName] = value;
-										}
-										break;
-				}
-				if(d.isFunction(value)){
-					// special case: assigning an event handler
-					// clobber if we can
-					var attrId = d.attr(node, _attrId);
-					if(!attrId){
-						attrId = _ctr++;
-						d.attr(node, _attrId, attrId);
-					}
-					if(!_evtHdlrMap[attrId]){
-						_evtHdlrMap[attrId] = {};
-					}
-					var h = _evtHdlrMap[attrId][propName];
-					if(h){
-						d.disconnect(h);
-					}else{
-						try{
-							delete node[propName];
-						}catch(e){}
-					}
-					// ensure that event objects are normalized, etc.
-					_evtHdlrMap[attrId][propName] = d.connect(node, propName, value);
-					break;
-				}
-				if(forceProp || typeof value == "boolean"){
-					// special case: forcing assignment to the property
-					// special case: setting boolean to a property instead of attribute
-					node[propName] = value;
-					break;
-				}
-				// node's attribute
-				node.setAttribute(attrName, value);
-			}while(false);
-			return node; // DomNode
-		}
-		// getter
-		// should we access this attribute via a property or
-		// via getAttribute()?
-		value = node[propName];
-		if(forceProp && typeof value != "undefined"){
-			// node's property
-			return value;	// Anything
-		}
-		if(propName != "href" && (typeof value == "boolean" || d.isFunction(value))){
-			// node's property
-			return value;	// Anything
-		}
-		// node's attribute
-		// we need _hasAttr() here to guard against IE returning a default value
-		return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything
-	}
-
-	dojo.removeAttr = function(/*DomNode|String*/ node, /*String*/ name){
-		//	summary:
-		//		Removes an attribute from an HTML element.
-		//	node:
-		//		id or reference to the element to remove the attribute from
-		//	name:
-		//		the name of the attribute to remove
-		byId(node).removeAttribute(_fixAttrName(name));
-	}
-
-	dojo.getNodeProp = function(/*DomNode|String*/ node, /*String*/ name){
-		//	summary:
-		//		Returns an effective value of a property or an attribute.
-		//	node:
-		//		id or reference to the element to remove the attribute from
-		//	name:
-		//		the name of the attribute
-		node = byId(node);
-		var lc = name.toLowerCase(),
-			propName = _propNames[lc] || name;
-		if((propName in node) && propName != "href"){
-			// node's property
-			return node[propName];	// Anything
-		}
-		// node's attribute
-		var attrName = _attrNames[lc] || name;
-		return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything
-	}
-
-	dojo.create = function(tag, attrs, refNode, pos){
-		//	summary:
-		//		Create an element, allowing for optional attribute decoration
-		//		and placement.
-		//
-		// description:
-		//		A DOM Element creation function. A shorthand method for creating a node or
-		//		a fragment, and allowing for a convenient optional attribute setting step,
-		//		as well as an optional DOM placement reference.
-		//|
-		//		Attributes are set by passing the optional object through `dojo.attr`.
-		//		See `dojo.attr` for noted caveats and nuances, and API if applicable.
-		//|
-		//		Placement is done via `dojo.place`, assuming the new node to be the action 
-		//		node, passing along the optional reference node and position.
-		//
-		// tag: String|DomNode
-		//		A string of the element to create (eg: "div", "a", "p", "li", "script", "br"),
-		//		or an existing DOM node to process.
-		//
-		// attrs: Object
-		//		An object-hash of attributes to set on the newly created node.
-		//		Can be null, if you don't want to set any attributes/styles.
-		//		See: `dojo.attr` for a description of available attributes.
-		//
-		// refNode: String?|DomNode?
-		//		Optional reference node. Used by `dojo.place` to place the newly created
-		//		node somewhere in the dom relative to refNode. Can be a DomNode reference
-		//		or String ID of a node.
-		//
-		// pos: String?
-		//		Optional positional reference. Defaults to "last" by way of `dojo.place`,
-		//		though can be set to "first","after","before","last", "replace" or "only"
-		//		to further control the placement of the new node relative to the refNode.
-		//		'refNode' is required if a 'pos' is specified.
-		//
-		// returns: DomNode
-		//
-		// example:
-		//	Create a DIV:
-		//	|	var n = dojo.create("div");
-		//
-		// example:
-		//	Create a DIV with content:
-		//	|	var n = dojo.create("div", { innerHTML:"<p>hi</p>" });
-		//
-		// example:
-		//	Place a new DIV in the BODY, with no attributes set
-		//	|	var n = dojo.create("div", null, dojo.body());
-		//
-		// example:
-		//	Create an UL, and populate it with LI's. Place the list as the first-child of a 
-		//	node with id="someId":
-		//	|	var ul = dojo.create("ul", null, "someId", "first");
-		//	|	var items = ["one", "two", "three", "four"];
-		//	|	dojo.forEach(items, function(data){
-		//	|		dojo.create("li", { innerHTML: data }, ul);
-		//	|	});
-		//
-		// example:
-		//	Create an anchor, with an href. Place in BODY:
-		//	|	dojo.create("a", { href:"foo.html", title:"Goto FOO!" }, dojo.body());
-		//
-		// example:
-		//	Create a `dojo.NodeList()` from a new element (for syntatic sugar):
-		//	|	dojo.query(dojo.create('div'))
-		//	|		.addClass("newDiv")
-		//	|		.onclick(function(e){ console.log('clicked', e.target) })
-		//	|		.place("#someNode"); // redundant, but cleaner.
-
-		var doc = d.doc;
-		if(refNode){
-			refNode = byId(refNode);
-			doc = refNode.ownerDocument;
-		}
-		if(typeof tag == "string"){ // inline'd type check
-			tag = doc.createElement(tag);
-		}
-		if(attrs){ d.attr(tag, attrs); }
-		if(refNode){ d.place(tag, refNode, pos); }
-		return tag; // DomNode
-	}
-
-	/*=====
-	dojo.empty = function(node){
-			//	summary:
-			//		safely removes all children of the node.
-			//	node: DOMNode|String
-			//		a reference to a DOM node or an id.
-			//	example:
-			//	Destroy node's children byId:
-			//	|	dojo.empty("someId");
-			//
-			//	example:
-			//	Destroy all nodes' children in a list by reference:
-			//	|	dojo.query(".someNode").forEach(dojo.empty);
-	}
-	=====*/
-
-	d.empty =
-				d.isIE ?  function(node){
-			node = byId(node);
-			for(var c; c = node.lastChild;){ // intentional assignment
-				d.destroy(c);
-			}
-		} :
-				function(node){
-			byId(node).innerHTML = "";
-		};
-
-	/*=====
-	dojo._toDom = function(frag, doc){
-			//	summary:
-			//		instantiates an HTML fragment returning the corresponding DOM.
-			//	frag: String
-			//		the HTML fragment
-			//	doc: DocumentNode?
-			//		optional document to use when creating DOM nodes, defaults to
-			//		dojo.doc if not specified.
-			//	returns: DocumentFragment
-			//
-			//	example:
-			//	Create a table row:
-			//	|	var tr = dojo._toDom("<tr><td>First!</td></tr>");
-	}
-	=====*/
-
-	// support stuff for dojo._toDom
-	var tagWrap = {
-			option: ["select"],
-			tbody: ["table"],
-			thead: ["table"],
-			tfoot: ["table"],
-			tr: ["table", "tbody"],
-			td: ["table", "tbody", "tr"],
-			th: ["table", "thead", "tr"],
-			legend: ["fieldset"],
-			caption: ["table"],
-			colgroup: ["table"],
-			col: ["table", "colgroup"],
-			li: ["ul"]
-		},
-		reTag = /<\s*([\w\:]+)/,
-		masterNode = {}, masterNum = 0,
-		masterName = "__" + d._scopeName + "ToDomId";
-
-	// generate start/end tag strings to use
-	// for the injection for each special tag wrap case.
-	for(var param in tagWrap){
-		var tw = tagWrap[param];
-		tw.pre  = param == "option" ? '<select multiple="multiple">' : "<" + tw.join("><") + ">";
-		tw.post = "</" + tw.reverse().join("></") + ">";
-		// the last line is destructive: it reverses the array,
-		// but we don't care at this point
-	}
-
-	d._toDom = function(frag, doc){
-		//	summary:
-		// 		converts HTML string into DOM nodes.
-
-		doc = doc || d.doc;
-		var masterId = doc[masterName];
-		if(!masterId){
-			doc[masterName] = masterId = ++masterNum + "";
-			masterNode[masterId] = doc.createElement("div");
-		}
-
-		// make sure the frag is a string.
-		frag += "";
-
-		// find the starting tag, and get node wrapper
-		var match = frag.match(reTag),
-			tag = match ? match[1].toLowerCase() : "",
-			master = masterNode[masterId],
-			wrap, i, fc, df;
-		if(match && tagWrap[tag]){
-			wrap = tagWrap[tag];
-			master.innerHTML = wrap.pre + frag + wrap.post;
-			for(i = wrap.length; i; --i){
-				master = master.firstChild;
-			}
-		}else{
-			master.innerHTML = frag;
-		}
-
-		// one node shortcut => return the node itself
-		if(master.childNodes.length == 1){
-			return master.removeChild(master.firstChild); // DOMNode
-		}
-
-		// return multiple nodes as a document fragment
-		df = doc.createDocumentFragment();
-		while(fc = master.firstChild){ // intentional assignment
-			df.appendChild(fc);
-		}
-		return df; // DOMNode
-	}
-
-	// =============================
-	// (CSS) Class Functions
-	// =============================
-	var _className = "className";
-
-	dojo.hasClass = function(/*DomNode|String*/node, /*String*/classStr){
-		//	summary:
-		//		Returns whether or not the specified classes are a portion of the
-		//		class list currently applied to the node.
-		//
-		//	node:
-		//		String ID or DomNode reference to check the class for.
-		//
-		//	classStr:
-		//		A string class name to look for.
-		//
-		//	example:
-		//	Do something if a node with id="someNode" has class="aSillyClassName" present
-		//	|	if(dojo.hasClass("someNode","aSillyClassName")){ ... }
-
-		return ((" "+ byId(node)[_className] +" ").indexOf(" " + classStr + " ") >= 0);  // Boolean
-	};
-
-	var spaces = /\s+/, a1 = [""],
-		str2array = function(s){
-			if(typeof s == "string" || s instanceof String){
-				if(s.indexOf(" ") < 0){
-					a1[0] = s;
-					return a1;
-				}else{
-					return s.split(spaces);
-				}
-			}
-			// assumed to be an array
-			return s;
-		};
-
-	dojo.addClass = function(/*DomNode|String*/node, /*String|Array*/classStr){
-		//	summary:
-		//		Adds the specified classes to the end of the class list on the
-		//		passed node. Will not re-apply duplicate classes.
-		//
-		//	node:
-		//		String ID or DomNode reference to add a class string too
-		//
-		//	classStr:
-		//		A String class name to add, or several space-separated class names,
-		//		or an array of class names.
-		//
-		// example:
-		//	Add a class to some node:
-		//	|	dojo.addClass("someNode", "anewClass");
-		//
-		// example:
-		//	Add two classes at once:
-		//	|	dojo.addClass("someNode", "firstClass secondClass");
-		//
-		// example:
-		//	Add two classes at once (using array):
-		//	|	dojo.addClass("someNode", ["firstClass", "secondClass"]);
-		//
-		// example:
-		//	Available in `dojo.NodeList` for multiple additions
-		//	|	dojo.query("ul > li").addClass("firstLevel");
-
-		node = byId(node);
-		classStr = str2array(classStr);
-		var cls = " " + node[_className] + " ";
-		for(var i = 0, len = classStr.length, c; i < len; ++i){
-			c = classStr[i];
-			if(c && cls.indexOf(" " + c + " ") < 0){
-				cls += c + " ";
-			}
-		}
-		node[_className] = d.trim(cls);
-	};
-
-	dojo.removeClass = function(/*DomNode|String*/node, /*String|Array?*/classStr){
-		// summary:
-		//		Removes the specified classes from node. No `dojo.hasClass`
-		//		check is required.
-		//
-		// node:
-		// 		String ID or DomNode reference to remove the class from.
-		//
-		// classStr:
-		//		An optional String class name to remove, or several space-separated
-		//		class names, or an array of class names. If omitted, all class names
-		//		will be deleted.
-		//
-		// example:
-		//	Remove a class from some node:
-		//	|	dojo.removeClass("someNode", "firstClass");
-		//
-		// example:
-		//	Remove two classes from some node:
-		//	|	dojo.removeClass("someNode", "firstClass secondClass");
-		//
-		// example:
-		//	Remove two classes from some node (using array):
-		//	|	dojo.removeClass("someNode", ["firstClass", "secondClass"]);
-		//
-		// example:
-		//	Remove all classes from some node:
-		//	|	dojo.removeClass("someNode");
-		//
-		// example:
-		//	Available in `dojo.NodeList()` for multiple removal
-		//	|	dojo.query(".foo").removeClass("foo");
-
-		node = byId(node);
-		var cls;
-		if(classStr !== undefined){
-			classStr = str2array(classStr);
-			cls = " " + node[_className] + " ";
-			for(var i = 0, len = classStr.length; i < len; ++i){
-				cls = cls.replace(" " + classStr[i] + " ", " ");
-			}
-			cls = d.trim(cls);
-		}else{
-			cls = "";
-		}
-		if(node[_className] != cls){ node[_className] = cls; }
-	};
-
-	dojo.toggleClass = function(/*DomNode|String*/node, /*String|Array*/classStr, /*Boolean?*/condition){
-		//	summary:
-		//		Adds a class to node if not present, or removes if present.
-		//		Pass a boolean condition if you want to explicitly add or remove.
-		//	condition:
-		//		If passed, true means to add the class, false means to remove.
-		//
-		// example:
-		//	|	dojo.toggleClass("someNode", "hovered");
-		//
-		// example:
-		//	Forcefully add a class
-		//	|	dojo.toggleClass("someNode", "hovered", true);
-		//
-		// example:
-		//	Available in `dojo.NodeList()` for multiple toggles
-		//	|	dojo.query(".toggleMe").toggleClass("toggleMe");
-
-		if(condition === undefined){
-			condition = !d.hasClass(node, classStr);
-		}
-		d[condition ? "addClass" : "removeClass"](node, classStr);
-	};
-
-})();
-
-}
-
-if(!dojo._hasResource["dojo._base.NodeList"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.NodeList"] = true;
-dojo.provide("dojo._base.NodeList");
-
-
-
-(function(){
-
-	var d = dojo;
-
-	var ap = Array.prototype, aps = ap.slice, apc = ap.concat;
-
-	var tnl = function(/*Array*/ a, /*dojo.NodeList?*/ parent, /*Function?*/ NodeListCtor){
-		// summary:
-		// 		decorate an array to make it look like a `dojo.NodeList`.
-		// a:
-		// 		Array of nodes to decorate.
-		// parent:
-		// 		An optional parent NodeList that generated the current
-		// 		list of nodes. Used to call _stash() so the parent NodeList
-		// 		can be accessed via end() later.
-		// NodeListCtor:
-		// 		An optional constructor function to use for any
-		// 		new NodeList calls. This allows a certain chain of
-		// 		NodeList calls to use a different object than dojo.NodeList.
-		if(!a.sort){
-			// make sure it's a real array before we pass it on to be wrapped
-			a = aps.call(a, 0);
-		}
-		var ctor = NodeListCtor || this._NodeListCtor || d._NodeListCtor;
-		a.constructor = ctor;
-		dojo._mixin(a, ctor.prototype);
-		a._NodeListCtor = ctor;
-		return parent ? a._stash(parent) : a;
-	};
-
-	var loopBody = function(f, a, o){
-		a = [0].concat(aps.call(a, 0));
-		o = o || d.global;
-		return function(node){
-			a[0] = node;
-			return f.apply(o, a);
-		};
-	};
-
-	// adapters
-
-	var adaptAsForEach = function(f, o){
-		//	summary:
-		//		adapts a single node function to be used in the forEach-type
-		//		actions. The initial object is returned from the specialized
-		//		function.
-		//	f: Function
-		//		a function to adapt
-		//	o: Object?
-		//		an optional context for f
-		return function(){
-			this.forEach(loopBody(f, arguments, o));
-			return this;	// Object
-		};
-	};
-
-	var adaptAsMap = function(f, o){
-		//	summary:
-		//		adapts a single node function to be used in the map-type
-		//		actions. The return is a new array of values, as via `dojo.map`
-		//	f: Function
-		//		a function to adapt
-		//	o: Object?
-		//		an optional context for f
-		return function(){
-			return this.map(loopBody(f, arguments, o));
-		};
-	};
-
-	var adaptAsFilter = function(f, o){
-		//	summary:
-		//		adapts a single node function to be used in the filter-type actions
-		//	f: Function
-		//		a function to adapt
-		//	o: Object?
-		//		an optional context for f
-		return function(){
-			return this.filter(loopBody(f, arguments, o));
-		};
-	};
-
-	var adaptWithCondition = function(f, g, o){
-		//	summary:
-		//		adapts a single node function to be used in the map-type
-		//		actions, behaves like forEach() or map() depending on arguments
-		//	f: Function
-		//		a function to adapt
-		//	g: Function
-		//		a condition function, if true runs as map(), otherwise runs as forEach()
-		//	o: Object?
-		//		an optional context for f and g
-		return function(){
-			var a = arguments, body = loopBody(f, a, o);
-			if(g.call(o || d.global, a)){
-				return this.map(body);	// self
-			}
-			this.forEach(body);
-			return this;	// self
-		};
-	};
-
-	var magicGuard = function(a){
-		//	summary:
-		//		the guard function for dojo.attr() and dojo.style()
-		return a.length == 1 && (typeof a[0] == "string"); // inline'd type check
-	};
-
-	var orphan = function(node){
-		//	summary:
-		//		function to orphan nodes
-		var p = node.parentNode;
-		if(p){
-			p.removeChild(node);
-		}
-	};
-	// FIXME: should we move orphan() to dojo.html?
-
-	dojo.NodeList = function(){
-		//	summary:
-		//		dojo.NodeList is an of Array subclass which adds syntactic
-		//		sugar for chaining, common iteration operations, animation, and
-		//		node manipulation. NodeLists are most often returned as the
-		//		result of dojo.query() calls.
-		//	description:
-		//		dojo.NodeList instances provide many utilities that reflect
-		//		core Dojo APIs for Array iteration and manipulation, DOM
-		//		manipulation, and event handling. Instead of needing to dig up
-		//		functions in the dojo.* namespace, NodeLists generally make the
-		//		full power of Dojo available for DOM manipulation tasks in a
-		//		simple, chainable way.
-		//	example:
-		//		create a node list from a node
-		//		|	new dojo.NodeList(dojo.byId("foo"));
-		//	example:
-		//		get a NodeList from a CSS query and iterate on it
-		//		|	var l = dojo.query(".thinger");
-		//		|	l.forEach(function(node, index, nodeList){
-		//		|		console.log(index, node.innerHTML);
-		//		|	});
-		//	example:
-		//		use native and Dojo-provided array methods to manipulate a
-		//		NodeList without needing to use dojo.* functions explicitly:
-		//		|	var l = dojo.query(".thinger");
-		//		|	// since NodeLists are real arrays, they have a length
-		//		|	// property that is both readable and writable and
-		//		|	// push/pop/shift/unshift methods
-		//		|	console.log(l.length);
-		//		|	l.push(dojo.create("span"));
-		//		|
-		//		|	// dojo's normalized array methods work too:
-		//		|	console.log( l.indexOf(dojo.byId("foo")) );
-		//		|	// ...including the special "function as string" shorthand
-		//		|	console.log( l.every("item.nodeType == 1") );
-		//		|
-		//		|	// NodeLists can be [..] indexed, or you can use the at()
-		//		|	// function to get specific items wrapped in a new NodeList:
-		//		|	var node = l[3]; // the 4th element
-		//		|	var newList = l.at(1, 3); // the 2nd and 4th elements
-		//	example:
-		//		the style functions you expect are all there too:
-		//		|	// style() as a getter...
-		//		|	var borders = dojo.query(".thinger").style("border");
-		//		|	// ...and as a setter:
-		//		|	dojo.query(".thinger").style("border", "1px solid black");
-		//		|	// class manipulation
-		//		|	dojo.query("li:nth-child(even)").addClass("even");
-		//		|	// even getting the coordinates of all the items
-		//		|	var coords = dojo.query(".thinger").coords();
-		//	example:
-		//		DOM manipulation functions from the dojo.* namespace area also
-		//		available:
-		//		|	// remove all of the elements in the list from their
-		//		|	// parents (akin to "deleting" them from the document)
-		//		|	dojo.query(".thinger").orphan();
-		//		|	// place all elements in the list at the front of #foo
-		//		|	dojo.query(".thinger").place("foo", "first");
-		//	example:
-		//		Event handling couldn't be easier. `dojo.connect` is mapped in,
-		//		and shortcut handlers are provided for most DOM events:
-		//		|	// like dojo.connect(), but with implicit scope
-		//		|	dojo.query("li").connect("onclick", console, "log");
-		//		|
-		//		|	// many common event handlers are already available directly:
-		//		|	dojo.query("li").onclick(console, "log");
-		//		|	var toggleHovered = dojo.hitch(dojo, "toggleClass", "hovered");
-		//		|	dojo.query("p")
-		//		|		.onmouseenter(toggleHovered)
-		//		|		.onmouseleave(toggleHovered);
-		//	example:
-		//		chainability is a key advantage of NodeLists:
-		//		|	dojo.query(".thinger")
-		//		|		.onclick(function(e){ /* ... */ })
-		//		|		.at(1, 3, 8) // get a subset
-		//		|			.style("padding", "5px")
-		//		|			.forEach(console.log);
-
-		return tnl(Array.apply(null, arguments));
-	};
-
-	//Allow things that new up a NodeList to use a delegated or alternate NodeList implementation.
-	d._NodeListCtor = d.NodeList;
-
-	var nl = d.NodeList, nlp = nl.prototype;
-
-	// expose adapters and the wrapper as private functions
-
-	nl._wrap = nlp._wrap = tnl;
-	nl._adaptAsMap = adaptAsMap;
-	nl._adaptAsForEach = adaptAsForEach;
-	nl._adaptAsFilter  = adaptAsFilter;
-	nl._adaptWithCondition = adaptWithCondition;
-
-	// mass assignment
-
-	// add array redirectors
-	d.forEach(["slice", "splice"], function(name){
-		var f = ap[name];
-		//Use a copy of the this array via this.slice() to allow .end() to work right in the splice case.
-		// CANNOT apply ._stash()/end() to splice since it currently modifies
-		// the existing this array -- it would break backward compatibility if we copy the array before
-		// the splice so that we can use .end(). So only doing the stash option to this._wrap for slice.
-		nlp[name] = function(){ return this._wrap(f.apply(this, arguments), name == "slice" ? this : null); };
-	});
-	// concat should be here but some browsers with native NodeList have problems with it
-
-	// add array.js redirectors
-	d.forEach(["indexOf", "lastIndexOf", "every", "some"], function(name){
-		var f = d[name];
-		nlp[name] = function(){ return f.apply(d, [this].concat(aps.call(arguments, 0))); };
-	});
-
-	// add conditional methods
-	d.forEach(["attr", "style"], function(name){
-		nlp[name] = adaptWithCondition(d[name], magicGuard);
-	});
-
-	// add forEach actions
-	d.forEach(["connect", "addClass", "removeClass", "toggleClass", "empty", "removeAttr"], function(name){
-		nlp[name] = adaptAsForEach(d[name]);
-	});
-
-	dojo.extend(dojo.NodeList, {
-		_normalize: function(/*String||Element||Object||NodeList*/content, /*DOMNode?*/refNode){
-			// summary:
-			// 		normalizes data to an array of items to insert.
-			// description:
-			// 		If content is an object, it can have special properties "template" and
-			// 		"parse". If "template" is defined, then the template value is run through
-			// 		dojo.string.substitute (if dojo.string.substitute has been dojo.required elsewhere),
-			// 		or if templateFunc is a function on the content, that function will be used to
-			// 		transform the template into a final string to be used for for passing to dojo._toDom.
-			// 		If content.parse is true, then it is remembered for later, for when the content
-			// 		nodes are inserted into the DOM. At that point, the nodes will be parsed for widgets
-			// 		(if dojo.parser has been dojo.required elsewhere).
-
-			//Wanted to just use a DocumentFragment, but for the array/NodeList
-			//case that meant  using cloneNode, but we may not want that.
-			//Cloning should only happen if the node operations span
-			//multiple refNodes. Also, need a real array, not a NodeList from the
-			//DOM since the node movements could change those NodeLists.
-
-			var parse = content.parse === true ? true : false;
-
-			//Do we have an object that needs to be run through a template?
-			if(typeof content.template == "string"){
-				var templateFunc = content.templateFunc || (dojo.string && dojo.string.substitute);
-				content = templateFunc ? templateFunc(content.template, content) : content;
-			}
-
-			var type = (typeof content);
-			if(type == "string" || type == "number"){
-				content = dojo._toDom(content, (refNode && refNode.ownerDocument));
-				if(content.nodeType == 11){
-					//DocumentFragment. It cannot handle cloneNode calls, so pull out the children.
-					content = dojo._toArray(content.childNodes);
-				}else{
-					content = [content];
-				}
-			}else if(!dojo.isArrayLike(content)){
-				content = [content];
-			}else if(!dojo.isArray(content)){
-				//To get to this point, content is array-like, but
-				//not an array, which likely means a DOM NodeList. Convert it now.
-				content = dojo._toArray(content);
-			}
-
-			//Pass around the parse info
-			if(parse){
-				content._runParse = true;
-			}
-			return content; //Array
-		},
-
-		_cloneNode: function(/*DOMNode*/ node){
-			// summary:
-			// 		private utiltity to clone a node. Not very interesting in the vanilla
-			// 		dojo.NodeList case, but delegates could do interesting things like
-			// 		clone event handlers if that is derivable from the node.
-			return node.cloneNode(true);
-		},
-
-		_place: function(/*Array*/ary, /*DOMNode*/refNode, /*String*/position, /*Boolean*/useClone){
-			// summary:
-			// 		private utility to handle placing an array of nodes relative to another node.
-			// description:
-			// 		Allows for cloning the nodes in the array, and for
-			// 		optionally parsing widgets, if ary._runParse is true.
-
-			//Avoid a disallowed operation if trying to do an innerHTML on a non-element node.
-			if(refNode.nodeType != 1 && position == "only"){
-				return;
-			}
-			var rNode = refNode, tempNode;
-
-			//Always cycle backwards in case the array is really a
-			//DOM NodeList and the DOM operations take it out of the live collection.
-			var length = ary.length;
-			for(var i = length - 1; i >= 0; i--){
-				var node = (useClone ? this._cloneNode(ary[i]) : ary[i]);
-
-				//If need widget parsing, use a temp node, instead of waiting after inserting into
-				//real DOM because we need to start widget parsing at one node up from current node,
-				//which could cause some already parsed widgets to be parsed again.
-				if(ary._runParse && dojo.parser && dojo.parser.parse){
-					if(!tempNode){
-						tempNode = rNode.ownerDocument.createElement("div");
-					}
-					tempNode.appendChild(node);
-					dojo.parser.parse(tempNode);
-					node = tempNode.firstChild;
-					while(tempNode.firstChild){
-						tempNode.removeChild(tempNode.firstChild);
-					}
-				}
-
-				if(i == length - 1){
-					dojo.place(node, rNode, position);
-				}else{
-					rNode.parentNode.insertBefore(node, rNode);
-				}
-				rNode = node;
-			}
-		},
-
-		_stash: function(parent){
-			// summary:
-			// 		private function to hold to a parent NodeList. end() to return the parent NodeList.
-			//
-			// example:
-			// How to make a `dojo.NodeList` method that only returns the third node in
-			// the dojo.NodeList but allows access to the original NodeList by using this._stash:
-			//	|	dojo.extend(dojo.NodeList, {
-			//	|		third: function(){
-			//  |			var newNodeList = dojo.NodeList(this[2]);
-			//	|			return newNodeList._stash(this);
-			//	|		}
-			//	|	});
-			//	|	// then see how _stash applies a sub-list, to be .end()'ed out of
-			//	|	dojo.query(".foo")
-			//	|		.third()
-			//	|			.addClass("thirdFoo")
-			//	|		.end()
-			//	|		// access to the orig .foo list
-			//	|		.removeClass("foo")
-			//	|
-			//
-			this._parent = parent;
-			return this; //dojo.NodeList
-		},
-
-		end: function(){
-			// summary:
-			// 		Ends use of the current `dojo.NodeList` by returning the previous dojo.NodeList
-			// 		that generated the current dojo.NodeList.
-			// description:
-			// 		Returns the `dojo.NodeList` that generated the current `dojo.NodeList`. If there
-			// 		is no parent dojo.NodeList, an empty dojo.NodeList is returned.
-			// example:
-			//	|	dojo.query("a")
-			//	|		.filter(".disabled")
-			//	|			// operate on the anchors that only have a disabled class
-			//	|			.style("color", "grey")
-			//	|		.end()
-			//	|		// jump back to the list of anchors
-			//	|		.style(...)
-			//
-			if(this._parent){
-				return this._parent;
-			}else{
-				//Just return empy list.
-				return new this._NodeListCtor();
-			}
-		},
-
-		// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array#Methods
-
-		// FIXME: handle return values for #3244
-		//		http://trac.dojotoolkit.org/ticket/3244
-
-		// FIXME:
-		//		need to wrap or implement:
-		//			join (perhaps w/ innerHTML/outerHTML overload for toString() of items?)
-		//			reduce
-		//			reduceRight
-
-		/*=====
-		slice: function(begin, end){
-			// summary:
-			//		Returns a new NodeList, maintaining this one in place
-			// description:
-			//		This method behaves exactly like the Array.slice method
-			//		with the caveat that it returns a dojo.NodeList and not a
-			//		raw Array. For more details, see Mozilla's (slice
-			//		documentation)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:slice]
-			// begin: Integer
-			//		Can be a positive or negative integer, with positive
-			//		integers noting the offset to begin at, and negative
-			//		integers denoting an offset from the end (i.e., to the left
-			//		of the end)
-			// end: Integer?
-			//		Optional parameter to describe what position relative to
-			//		the NodeList's zero index to end the slice at. Like begin,
-			//		can be positive or negative.
-			return this._wrap(a.slice.apply(this, arguments));
-		},
-
-		splice: function(index, howmany, item){
-			// summary:
-			//		Returns a new NodeList, manipulating this NodeList based on
-			//		the arguments passed, potentially splicing in new elements
-			//		at an offset, optionally deleting elements
-			// description:
-			//		This method behaves exactly like the Array.splice method
-			//		with the caveat that it returns a dojo.NodeList and not a
-			//		raw Array. For more details, see Mozilla's (splice
-			//		documentation)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:splice]
-			// 		For backwards compatibility, calling .end() on the spliced NodeList
-			// 		does not return the original NodeList -- splice alters the NodeList in place.
-			// index: Integer
-			//		begin can be a positive or negative integer, with positive
-			//		integers noting the offset to begin at, and negative
-			//		integers denoting an offset from the end (i.e., to the left
-			//		of the end)
-			// howmany: Integer?
-			//		Optional parameter to describe what position relative to
-			//		the NodeList's zero index to end the slice at. Like begin,
-			//		can be positive or negative.
-			// item: Object...?
-			//		Any number of optional parameters may be passed in to be
-			//		spliced into the NodeList
-			// returns:
-			//		dojo.NodeList
-			return this._wrap(a.splice.apply(this, arguments));
-		},
-
-		indexOf: function(value, fromIndex){
-			//	summary:
-			//		see dojo.indexOf(). The primary difference is that the acted-on 
-			//		array is implicitly this NodeList
-			// value: Object:
-			//		The value to search for.
-			// fromIndex: Integer?:
-			//		The loction to start searching from. Optional. Defaults to 0.
-			//	description:
-			//		For more details on the behavior of indexOf, see Mozilla's
-			//		(indexOf
-			//		docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf]
-			//	returns:
-			//		Positive Integer or 0 for a match, -1 of not found.
-			return d.indexOf(this, value, fromIndex); // Integer
-		},
-
-		lastIndexOf: function(value, fromIndex){
-			// summary:
-			//		see dojo.lastIndexOf(). The primary difference is that the
-			//		acted-on array is implicitly this NodeList
-			//	description:
-			//		For more details on the behavior of lastIndexOf, see
-			//		Mozilla's (lastIndexOf
-			//		docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf]
-			// value: Object
-			//		The value to search for.
-			// fromIndex: Integer?
-			//		The loction to start searching from. Optional. Defaults to 0.
-			// returns:
-			//		Positive Integer or 0 for a match, -1 of not found.
-			return d.lastIndexOf(this, value, fromIndex); // Integer
-		},
-
-		every: function(callback, thisObject){
-			//	summary:
-			//		see `dojo.every()` and the (Array.every
-			//		docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every].
-			//		Takes the same structure of arguments and returns as
-			//		dojo.every() with the caveat that the passed array is
-			//		implicitly this NodeList
-			// callback: Function: the callback
-			// thisObject: Object?: the context
-			return d.every(this, callback, thisObject); // Boolean
-		},
-
-		some: function(callback, thisObject){
-			//	summary:
-			//		Takes the same structure of arguments and returns as
-			//		`dojo.some()` with the caveat that the passed array is
-			//		implicitly this NodeList.  See `dojo.some()` and Mozilla's
-			//		(Array.some
-			//		documentation)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some].
-			// callback: Function: the callback
-			// thisObject: Object?: the context
-			return d.some(this, callback, thisObject); // Boolean
-		},
-		=====*/
-
-		concat: function(item){
-			// summary:
-			//		Returns a new NodeList comprised of items in this NodeList
-			//		as well as items passed in as parameters
-			// description:
-			//		This method behaves exactly like the Array.concat method
-			//		with the caveat that it returns a `dojo.NodeList` and not a
-			//		raw Array. For more details, see the (Array.concat
-			//		docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:concat]
-			// item: Object?
-			//		Any number of optional parameters may be passed in to be
-			//		spliced into the NodeList
-			// returns:
-			//		dojo.NodeList
-
-			//return this._wrap(apc.apply(this, arguments));
-			// the line above won't work for the native NodeList :-(
-
-			// implementation notes:
-			// 1) Native NodeList is not an array, and cannot be used directly
-			// in concat() --- the latter doesn't recognize it as an array, and
-			// does not inline it, but append as a single entity.
-			// 2) On some browsers (e.g., Safari) the "constructor" property is
-			// read-only and cannot be changed. So we have to test for both
-			// native NodeList and dojo.NodeList in this property to recognize
-			// the node list.
-
-			var t = d.isArray(this) ? this : aps.call(this, 0),
-				m = d.map(arguments, function(a){
-					return a && !d.isArray(a) &&
-						(typeof NodeList != "undefined" && a.constructor === NodeList || a.constructor === this._NodeListCtor) ?
-							aps.call(a, 0) : a;
-				});
-			return this._wrap(apc.apply(t, m), this);	// dojo.NodeList
-		},
-
-		map: function(/*Function*/ func, /*Function?*/ obj){
-			//	summary:
-			//		see dojo.map(). The primary difference is that the acted-on
-			//		array is implicitly this NodeList and the return is a
-			//		dojo.NodeList (a subclass of Array)
-			///return d.map(this, func, obj, d.NodeList); // dojo.NodeList
-			return this._wrap(d.map(this, func, obj), this); // dojo.NodeList
-		},
-
-		forEach: function(callback, thisObj){
-			//	summary:
-			//		see `dojo.forEach()`. The primary difference is that the acted-on 
-			//		array is implicitly this NodeList. If you want the option to break out
-			//		of the forEach loop, use every() or some() instead.
-			d.forEach(this, callback, thisObj);
-			// non-standard return to allow easier chaining
-			return this; // dojo.NodeList 
-		},
-
-		/*=====
-		coords: function(){
-			//	summary:
-			//		Returns the box objects of all elements in a node list as
-			//		an Array (*not* a NodeList). Acts like `dojo.coords`, though assumes
-			//		the node passed is each node in this list.
-
-			return d.map(this, d.coords); // Array
-		},
-
-		position: function(){
-			//	summary:
-			//		Returns border-box objects (x/y/w/h) of all elements in a node list
-			//		as an Array (*not* a NodeList). Acts like `dojo.position`, though
-			//		assumes the node passed is each node in this list. 
-
-			return d.map(this, d.position); // Array
-		},
-
-		attr: function(property, value){
-			//	summary:
-			//		gets or sets the DOM attribute for every element in the
-			//		NodeList. See also `dojo.attr`
-			//	property: String
-			//		the attribute to get/set
-			//	value: String?
-			//		optional. The value to set the property to
-			//	returns:
-			//		if no value is passed, the result is an array of attribute values
-			//		If a value is passed, the return is this NodeList
-			//	example:
-			//		Make all nodes with a particular class focusabl:
-			//	|	dojo.query(".focusable").attr("tabIndex", -1);
-			//	example:
-			//		Disable a group of buttons:
-			//	|	dojo.query("button.group").attr("disalbed", true);
-			//	example:
-			//		innerHTML can be assigned or retreived as well:
-			//	|	// get the innerHTML (as an array) for each list item
-			//	|	var ih = dojo.query("li.replaceable").attr("innerHTML");
-			return; // dojo.NodeList
-			return; // Array
-		},
-
-		style: function(property, value){
-			//	summary:
-			//		gets or sets the CSS property for every element in the NodeList
-			//	property: String
-			//		the CSS property to get/set, in JavaScript notation
-			//		("lineHieght" instead of "line-height")
-			//	value: String?
-			//		optional. The value to set the property to
-			//	returns:
-			//		if no value is passed, the result is an array of strings.
-			//		If a value is passed, the return is this NodeList
-			return; // dojo.NodeList
-			return; // Array
-		},
-
-		addClass: function(className){
-			//	summary:
-			//		adds the specified class to every node in the list
-			//	className: String|Array
-			//		A String class name to add, or several space-separated class names,
-			//		or an array of class names.
-			return; // dojo.NodeList
-		},
-
-		removeClass: function(className){
-			//	summary:
-			//		removes the specified class from every node in the list
-			//	className: String|Array?
-			//		An optional String class name to remove, or several space-separated
-			//		class names, or an array of class names. If omitted, all class names
-			//		will be deleted.
-			//	returns:
-			//		dojo.NodeList, this list
-			return; // dojo.NodeList
-		},
-
-		toggleClass: function(className, condition){
-			//	summary:
-			//		Adds a class to node if not present, or removes if present.
-			//		Pass a boolean condition if you want to explicitly add or remove.
-			//	condition: Boolean?
-			//		If passed, true means to add the class, false means to remove.
-			//	className: String
-			//		the CSS class to add
-			return; // dojo.NodeList
-		},
-
-		connect: function(methodName, objOrFunc, funcName){
-			//	summary:
-			//		attach event handlers to every item of the NodeList. Uses dojo.connect()
-			//		so event properties are normalized
-			//	methodName: String
-			//		the name of the method to attach to. For DOM events, this should be
-			//		the lower-case name of the event
-			//	objOrFunc: Object|Function|String
-			//		if 2 arguments are passed (methodName, objOrFunc), objOrFunc should
-			//		reference a function or be the name of the function in the global
-			//		namespace to attach. If 3 arguments are provided
-			//		(methodName, objOrFunc, funcName), objOrFunc must be the scope to 
-			//		locate the bound function in
-			//	funcName: String?
-			//		optional. A string naming the function in objOrFunc to bind to the
-			//		event. May also be a function reference.
-			//	example:
-			//		add an onclick handler to every button on the page
-			//		|	dojo.query("div:nth-child(odd)").connect("onclick", function(e){
-			//		|		console.log("clicked!");
-			//		|	});
-			// example:
-			//		attach foo.bar() to every odd div's onmouseover
-			//		|	dojo.query("div:nth-child(odd)").connect("onmouseover", foo, "bar");
-		},
-
-		empty: function(){
-			//	summary:
-			//		clears all content from each node in the list. Effectively
-			//		equivalent to removing all child nodes from every item in
-			//		the list.
-			return this.forEach("item.innerHTML='';"); // dojo.NodeList
-			// FIXME: should we be checking for and/or disposing of widgets below these nodes?
-		},
-		=====*/
-
-		// useful html methods
-		coords:	adaptAsMap(d.coords),
-		position: adaptAsMap(d.position),
-
-		// FIXME: connectPublisher()? connectRunOnce()?
-
-		/*
-		destroy: function(){
-			//	summary:
-			//		destroys every item in 	the list.
-			this.forEach(d.destroy);
-			// FIXME: should we be checking for and/or disposing of widgets below these nodes?
-		},
-		*/
-
-		place: function(/*String||Node*/ queryOrNode, /*String*/ position){
-			//	summary:
-			//		places elements of this node list relative to the first element matched
-			//		by queryOrNode. Returns the original NodeList. See: `dojo.place`
-			//	queryOrNode:
-			//		may be a string representing any valid CSS3 selector or a DOM node.
-			//		In the selector case, only the first matching element will be used 
-			//		for relative positioning.
-			//	position:
-			//		can be one of:
-			//		|	"last" (default)
-			//		|	"first"
-			//		|	"before"
-			//		|	"after"
-			//		|	"only"
-			//		|	"replace"
-			// 		or an offset in the childNodes property
-			var item = d.query(queryOrNode)[0];
-			return this.forEach(function(node){ d.place(node, item, position); }); // dojo.NodeList
-		},
-
-		orphan: function(/*String?*/ simpleFilter){
-			//	summary:
-			//		removes elements in this list that match the simple filter
-			//		from their parents and returns them as a new NodeList.
-			//	simpleFilter:
-			//		single-expression CSS rule. For example, ".thinger" or
-			//		"#someId[attrName='value']" but not "div > span". In short,
-			//		anything which does not invoke a descent to evaluate but
-			//		can instead be used to test a single node is acceptable.
-			//	returns:
-			//		`dojo.NodeList` containing the orpahned elements 
-			return (simpleFilter ? d._filterQueryResult(this, simpleFilter) : this).forEach(orphan); // dojo.NodeList
-		},
-
-		adopt: function(/*String||Array||DomNode*/ queryOrListOrNode, /*String?*/ position){
-			//	summary:
-			//		places any/all elements in queryOrListOrNode at a
-			//		position relative to the first element in this list.
-			//		Returns a dojo.NodeList of the adopted elements.
-			//	queryOrListOrNode:
-			//		a DOM node or a query string or a query result.
-			//		Represents the nodes to be adopted relative to the
-			//		first element of this NodeList.
-			//	position:
-			//		can be one of:
-			//		|	"last" (default)
-			//		|	"first"
-			//		|	"before"
-			//		|	"after"
-			//		|	"only"
-			//		|	"replace"
-			// 		or an offset in the childNodes property
-			return d.query(queryOrListOrNode).place(this[0], position)._stash(this);	// dojo.NodeList
-		},
-
-		// FIXME: do we need this?
-		query: function(/*String*/ queryStr){
-			//	summary:
-			//		Returns a new list whose memebers match the passed query,
-			//		assuming elements of the current NodeList as the root for
-			//		each search.
-			//	example:
-			//		assume a DOM created by this markup:
-			//	|	<div id="foo">
-			//	|		<p>
-			//	|			bacon is tasty, <span>dontcha think?</span>
-			//	|		</p>
-			//	|	</div>
-			//	|	<div id="bar">
-			//	|		<p>great commedians may not be funny <span>in person</span></p>
-			//	|	</div>
-			//		If we are presented with the following defintion for a NodeList:
-			//	|	var l = new dojo.NodeList(dojo.byId("foo"), dojo.byId("bar"));
-			//		it's possible to find all span elements under paragraphs
-			//		contained by these elements with this sub-query:
-			//	| 	var spans = l.query("p span");
-
-			// FIXME: probably slow
-			if(!queryStr){ return this; }
-			var ret = this.map(function(node){
-				// FIXME: why would we ever get undefined here?
-				return d.query(queryStr, node).filter(function(subNode){ return subNode !== undefined; });
-			});
-			return this._wrap(apc.apply([], ret), this);	// dojo.NodeList
-		},
-
-		filter: function(/*String|Function*/ simpleFilter){
-			//	summary:
-			// 		"masks" the built-in javascript filter() method (supported
-			// 		in Dojo via `dojo.filter`) to support passing a simple
-			// 		string filter in addition to supporting filtering function
-			// 		objects.
-			//	simpleFilter:
-			//		If a string, a single-expression CSS rule. For example,
-			//		".thinger" or "#someId[attrName='value']" but not "div >
-			//		span". In short, anything which does not invoke a descent
-			//		to evaluate but can instead be used to test a single node
-			//		is acceptable.
-			//	example:
-			//		"regular" JS filter syntax as exposed in dojo.filter:
-			//		|	dojo.query("*").filter(function(item){
-			//		|		// highlight every paragraph
-			//		|		return (item.nodeName == "p");
-			//		|	}).style("backgroundColor", "yellow");
-			// example:
-			//		the same filtering using a CSS selector
-			//		|	dojo.query("*").filter("p").styles("backgroundColor", "yellow");
-
-			var a = arguments, items = this, start = 0;
-			if(typeof simpleFilter == "string"){ // inline'd type check
-				items = d._filterQueryResult(this, a[0]);
-				if(a.length == 1){
-					// if we only got a string query, pass back the filtered results
-					return items._stash(this); // dojo.NodeList
-				}
-				// if we got a callback, run it over the filtered items
-				start = 1;
-			}
-			return this._wrap(d.filter(items, a[start], a[start + 1]), this);	// dojo.NodeList
-		},
-
-		/*
-		// FIXME: should this be "copyTo" and include parenting info?
-		clone: function(){
-			// summary:
-			//		creates node clones of each element of this list
-			//		and returns a new list containing the clones
-		},
-		*/
-
-		addContent: function(/*String||DomNode||Object||dojo.NodeList*/ content, /*String||Integer?*/ position){
-			//	summary:
-			//		add a node, NodeList or some HTML as a string to every item in the
-			//		list.  Returns the original list.
-			//	description:
-			//		a copy of the HTML content is added to each item in the
-			//		list, with an optional position argument. If no position
-			//		argument is provided, the content is appended to the end of
-			//		each item.
-			//	content:
-			//		DOM node, HTML in string format, a NodeList or an Object. If a DOM node or
-			// 		NodeList, the content will be cloned if the current NodeList has more than one
-			// 		element. Only the DOM nodes are cloned, no event handlers. If it is an Object,
-			// 		it should be an object with at "template" String property that has the HTML string
-			// 		to insert. If dojo.string has already been dojo.required, then dojo.string.substitute
-			// 		will be used on the "template" to generate the final HTML string. Other allowed
-			// 		properties on the object are: "parse" if the HTML
-			// 		string should be parsed for widgets (dojo.require("dojo.parser") to get that
-			// 		option to work), and "templateFunc" if a template function besides dojo.string.substitute
-			// 		should be used to transform the "template".
-			//	position:
-			//		can be one of:
-			//		|	"last"||"end" (default)
-			//		|	"first||"start"
-			//		|	"before"
-			//		|	"after"
-			//		|	"replace" (replaces nodes in this NodeList with new content)
-			//		|	"only" (removes other children of the nodes so new content is hte only child)
-			// 		or an offset in the childNodes property
-			//	example:
-			//		appends content to the end if the position is ommitted
-			//	|	dojo.query("h3 > p").addContent("hey there!");
-			//	example:
-			//		add something to the front of each element that has a
-			//		"thinger" property:
-			//	|	dojo.query("[thinger]").addContent("...", "first");
-			//	example:
-			//		adds a header before each element of the list
-			//	|	dojo.query(".note").addContent("<h4>NOTE:</h4>", "before");
-			//	example:
-			//		add a clone of a DOM node to the end of every element in
-			//		the list, removing it from its existing parent.
-			//	|	dojo.query(".note").addContent(dojo.byId("foo"));
-			//  example:
-			//  	Append nodes from a templatized string.
-			// 		dojo.require("dojo.string");
-			// 		dojo.query(".note").addContent({
-			//  		template: '<b>${id}: </b><span>${name}</span>',
-			// 			id: "user332",
-			//  		name: "Mr. Anderson"
-			//  	});
-			//  example:
-			//  	Append nodes from a templatized string that also has widgets parsed.
-			//  	dojo.require("dojo.string");
-			//  	dojo.require("dojo.parser");
-			//  	var notes = dojo.query(".note").addContent({
-			//  		template: '<button dojoType="dijit.form.Button">${text}</button>',
-			//  		parse: true,
-			//  		text: "Send"
-			//  	});
-			content = this._normalize(content, this[0]);
-			for(var i = 0, node; node = this[i]; i++){
-				this._place(content, node, position, i > 0);
-			}
-			return this; //dojo.NodeList
-		},
-
-		instantiate: function(/*String|Object*/ declaredClass, /*Object?*/ properties){
-			//	summary:
-			//		Create a new instance of a specified class, using the
-			//		specified properties and each node in the nodeList as a
-			//		srcNodeRef.
-			//	example:
-			//		Grabs all buttons in the page and converts them to diji.form.Buttons.
-			//	|	var buttons = dojo.query("button").instantiate("dijit.form.Button", {showLabel: true});
-			var c = d.isFunction(declaredClass) ? declaredClass : d.getObject(declaredClass);
-			properties = properties || {};
-			return this.forEach(function(node){
-				new c(properties, node);
-			});	// dojo.NodeList
-		},
-
-		at: function(/*===== index =====*/){
-			//	summary:
-			//		Returns a new NodeList comprised of items in this NodeList
-			//		at the given index or indices.
-			//	index: Integer...
-			//		One or more 0-based indices of items in the current
-			//		NodeList.
-			//	returns:
-			//		dojo.NodeList
-			var t = new this._NodeListCtor();
-			d.forEach(arguments, function(i){ if(this[i]){ t.push(this[i]); }}, this);
-			return t._stash(this); // dojo.NodeList
-		}
-
-	});
-
-	nl.events = [
-		// summary: list of all DOM events used in NodeList
-		"blur", "focus", "change", "click", "error", "keydown", "keypress",
-		"keyup", "load", "mousedown", "mouseenter", "mouseleave", "mousemove",
-		"mouseout", "mouseover", "mouseup", "submit"
-	];
-
-	// syntactic sugar for DOM events
-	d.forEach(nl.events, function(evt){
-			var _oe = "on"+evt;
-			nlp[_oe] = function(a, b){
-				return this.connect(_oe, a, b);
-			}
-				// FIXME: should these events trigger publishes?
-				/*
-				return (a ? this.connect(_oe, a, b) :
-							this.forEach(function(n){
-								// FIXME:
-								//		listeners get buried by
-								//		addEventListener and can't be dug back
-								//		out to be triggered externally.
-								// see:
-								//		http://developer.mozilla.org/en/docs/DOM:element
-
-								console.log(n, evt, _oe);
-
-								// FIXME: need synthetic event support!
-								var _e = { target: n, faux: true, type: evt };
-								// dojo._event_listener._synthesizeEvent({}, { target: n, faux: true, type: evt });
-								try{ n[evt](_e); }catch(e){ console.log(e); }
-								try{ n[_oe](_e); }catch(e){ console.log(e); }
-							})
-				);
-				*/
-		}
-	);
-
-})();
-
-}
-
-if(!dojo._hasResource["dojo._base.query"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.query"] = true;
-if(typeof dojo != "undefined"){
-	dojo.provide("dojo._base.query");
-	
-	
-
-}
-
-/*
-	dojo.query() architectural overview:
-
-		dojo.query is a relatively full-featured CSS3 query library. It is
-		designed to take any valid CSS3 selector and return the nodes matching
-		the selector. To do this quickly, it processes queries in several
-		steps, applying caching where profitable.
-		
-		The steps (roughly in reverse order of the way they appear in the code):
-			1.) check to see if we already have a "query dispatcher"
-				- if so, use that with the given parameterization. Skip to step 4.
-			2.) attempt to determine which branch to dispatch the query to:
-				- JS (optimized DOM iteration)
-				- native (FF3.1+, Safari 3.1+, IE 8+)
-			3.) tokenize and convert to executable "query dispatcher"
-				- this is where the lion's share of the complexity in the
-				  system lies. In the DOM version, the query dispatcher is
-				  assembled as a chain of "yes/no" test functions pertaining to
-				  a section of a simple query statement (".blah:nth-child(odd)"
-				  but not "div div", which is 2 simple statements). Individual
-				  statement dispatchers are cached (to prevent re-definition)
-				  as are entire dispatch chains (to make re-execution of the
-				  same query fast)
-			4.) the resulting query dispatcher is called in the passed scope
-			    (by default the top-level document)
-				- for DOM queries, this results in a recursive, top-down
-				  evaluation of nodes based on each simple query section
-				- for native implementations, this may mean working around spec
-				  bugs. So be it.
-			5.) matched nodes are pruned to ensure they are unique (if necessary)
-*/
-
-;(function(d){
-	// define everything in a closure for compressability reasons. "d" is an
-	// alias to "dojo" (or the toolkit alias object, e.g., "acme").
-
-	////////////////////////////////////////////////////////////////////////
-	// Toolkit aliases
-	////////////////////////////////////////////////////////////////////////
-
-	// if you are extracing dojo.query for use in your own system, you will
-	// need to provide these methods and properties. No other porting should be
-	// necessary, save for configuring the system to use a class other than
-	// dojo.NodeList as the return instance instantiator
-	var trim = 			d.trim;
-	var each = 			d.forEach;
-	// 					d.isIE; // float
-	// 					d.isSafari; // float
-	// 					d.isOpera; // float
-	// 					d.isWebKit; // float
-	// 					d.doc ; // document element
-	var qlc = d._NodeListCtor = 		d.NodeList;
-
-	var getDoc = function(){ return d.doc; };
-	// NOTE(alex): the spec is idiotic. CSS queries should ALWAYS be case-sensitive, but nooooooo
-	var cssCaseBug = ((d.isWebKit||d.isMozilla) && ((getDoc().compatMode) == "BackCompat"));
-
-	////////////////////////////////////////////////////////////////////////
-	// Global utilities
-	////////////////////////////////////////////////////////////////////////
-
-
-	// on browsers that support the "children" collection we can avoid a lot of
-	// iteration on chaff (non-element) nodes.
-	// why.
-	var childNodesName = !!getDoc().firstChild["children"] ? "children" : "childNodes";
-
-	var specials = ">~+";
-
-	// global thunk to determine whether we should treat the current query as
-	// case sensitive or not. This switch is flipped by the query evaluator
-	// based on the document passed as the context to search.
-	var caseSensitive = false;
-
-	// how high?
-	var yesman = function(){ return true; };
-
-	////////////////////////////////////////////////////////////////////////
-	// Tokenizer
-	////////////////////////////////////////////////////////////////////////
-
-	var getQueryParts = function(query){
-		//	summary: 
-		//		state machine for query tokenization
-		//	description:
-		//		instead of using a brittle and slow regex-based CSS parser,
-		//		dojo.query implements an AST-style query representation. This
-		//		representation is only generated once per query. For example,
-		//		the same query run multiple times or under different root nodes
-		//		does not re-parse the selector expression but instead uses the
-		//		cached data structure. The state machine implemented here
-		//		terminates on the last " " (space) charachter and returns an
-		//		ordered array of query component structures (or "parts"). Each
-		//		part represents an operator or a simple CSS filtering
-		//		expression. The structure for parts is documented in the code
-		//		below.
-
-
-		// NOTE: 
-		//		this code is designed to run fast and compress well. Sacrifices
-		//		to readibility and maintainability have been made.  Your best
-		//		bet when hacking the tokenizer is to put The Donnas on *really*
-		//		loud (may we recommend their "Spend The Night" release?) and
-		//		just assume you're gonna make mistakes. Keep the unit tests
-		//		open and run them frequently. Knowing is half the battle ;-)
-		if(specials.indexOf(query.slice(-1)) >= 0){
-			// if we end with a ">", "+", or "~", that means we're implicitly
-			// searching all children, so make it explicit
-			query += " * "
-		}else{
-			// if you have not provided a terminator, one will be provided for
-			// you...
-			query += " ";
-		}
-
-		var ts = function(/*Integer*/ s, /*Integer*/ e){
-			// trim and slice. 
-
-			// take an index to start a string slice from and an end position
-			// and return a trimmed copy of that sub-string
-			return trim(query.slice(s, e));
-		}
-
-		// the overall data graph of the full query, as represented by queryPart objects
-		var queryParts = []; 
-
-
-		// state keeping vars
-		var inBrackets = -1, inParens = -1, inMatchFor = -1, 
-			inPseudo = -1, inClass = -1, inId = -1, inTag = -1, 
-			lc = "", cc = "", pStart;
-
-		// iteration vars
-		var x = 0, // index in the query
-			ql = query.length,
-			currentPart = null, // data structure representing the entire clause
-			_cp = null; // the current pseudo or attr matcher
-
-		// several temporary variables are assigned to this structure durring a
-		// potential sub-expression match:
-		//		attr:
-		//			a string representing the current full attribute match in a
-		//			bracket expression
-		//		type:
-		//			if there's an operator in a bracket expression, this is
-		//			used to keep track of it
-		//		value:
-		//			the internals of parenthetical expression for a pseudo. for
-		//			:nth-child(2n+1), value might be "2n+1"
-
-		var endTag = function(){
-			// called when the tokenizer hits the end of a particular tag name.
-			// Re-sets state variables for tag matching and sets up the matcher
-			// to handle the next type of token (tag or operator).
-			if(inTag >= 0){
-				var tv = (inTag == x) ? null : ts(inTag, x); // .toLowerCase();
-				currentPart[ (specials.indexOf(tv) < 0) ? "tag" : "oper" ] = tv;
-				inTag = -1;
-			}
-		}
-
-		var endId = function(){
-			// called when the tokenizer might be at the end of an ID portion of a match
-			if(inId >= 0){
-				currentPart.id = ts(inId, x).replace(/\\/g, "");
-				inId = -1;
-			}
-		}
-
-		var endClass = function(){
-			// called when the tokenizer might be at the end of a class name
-			// match. CSS allows for multiple classes, so we augment the
-			// current item with another class in its list
-			if(inClass >= 0){
-				currentPart.classes.push(ts(inClass+1, x).replace(/\\/g, ""));
-				inClass = -1;
-			}
-		}
-
-		var endAll = function(){
-			// at the end of a simple fragment, so wall off the matches
-			endId(); endTag(); endClass();
-		}
-
-		var endPart = function(){
-			endAll();
-			if(inPseudo >= 0){
-				currentPart.pseudos.push({ name: ts(inPseudo+1, x) });
-			}
-			// hint to the selector engine to tell it whether or not it
-			// needs to do any iteration. Many simple selectors don't, and
-			// we can avoid significant construction-time work by advising
-			// the system to skip them
-			currentPart.loops = (	
-					currentPart.pseudos.length || 
-					currentPart.attrs.length || 
-					currentPart.classes.length	);
-
-			currentPart.oquery = currentPart.query = ts(pStart, x); // save the full expression as a string
-
-
-			// otag/tag are hints to suggest to the system whether or not
-			// it's an operator or a tag. We save a copy of otag since the
-			// tag name is cast to upper-case in regular HTML matches. The
-			// system has a global switch to figure out if the current
-			// expression needs to be case sensitive or not and it will use
-			// otag or tag accordingly
-			currentPart.otag = currentPart.tag = (currentPart["oper"]) ? null : (currentPart.tag || "*");
-
-			if(currentPart.tag){
-				// if we're in a case-insensitive HTML doc, we likely want
-				// the toUpperCase when matching on element.tagName. If we
-				// do it here, we can skip the string op per node
-				// comparison
-				currentPart.tag = currentPart.tag.toUpperCase();
-			}
-
-			// add the part to the list
-			if(queryParts.length && (queryParts[queryParts.length-1].oper)){
-				// operators are always infix, so we remove them from the
-				// list and attach them to the next match. The evaluator is
-				// responsible for sorting out how to handle them.
-				currentPart.infixOper = queryParts.pop();
-				currentPart.query = currentPart.infixOper.query + " " + currentPart.query;
-				/*
-				console.debug(	"swapping out the infix", 
-								currentPart.infixOper, 
-								"and attaching it to", 
-								currentPart);
-				*/
-			}
-			queryParts.push(currentPart);
-
-			currentPart = null;
-		}
-
-		// iterate over the query, charachter by charachter, building up a 
-		// list of query part objects
-		for(; lc=cc, cc=query.charAt(x), x < ql; x++){
-			//		cc: the current character in the match
-			//		lc: the last charachter (if any)
-
-			// someone is trying to escape something, so don't try to match any
-			// fragments. We assume we're inside a literal.
-			if(lc == "\\"){ continue; } 
-			if(!currentPart){ // a part was just ended or none has yet been created
-				// NOTE: I hate all this alloc, but it's shorter than writing tons of if's
-				pStart = x;
-				//	rules describe full CSS sub-expressions, like:
-				//		#someId
-				//		.className:first-child
-				//	but not:
-				//		thinger > div.howdy[type=thinger]
-				//	the indidual components of the previous query would be
-				//	split into 3 parts that would be represented a structure
-				//	like:
-				//		[
-				//			{
-				//				query: "thinger",
-				//				tag: "thinger",
-				//			},
-				//			{
-				//				query: "div.howdy[type=thinger]",
-				//				classes: ["howdy"],
-				//				infixOper: {
-				//					query: ">",
-				//					oper: ">",
-				//				}
-				//			},
-				//		]
-				currentPart = {
-					query: null, // the full text of the part's rule
-					pseudos: [], // CSS supports multiple pseud-class matches in a single rule
-					attrs: [], 	// CSS supports multi-attribute match, so we need an array
-					classes: [], // class matches may be additive, e.g.: .thinger.blah.howdy
-					tag: null, 	// only one tag...
-					oper: null, // ...or operator per component. Note that these wind up being exclusive.
-					id: null, 	// the id component of a rule
-					getTag: function(){
-						return (caseSensitive) ? this.otag : this.tag;
-					}
-				};
-
-				// if we don't have a part, we assume we're going to start at
-				// the beginning of a match, which should be a tag name. This
-				// might fault a little later on, but we detect that and this
-				// iteration will still be fine.
-				inTag = x; 
-			}
-
-			if(inBrackets >= 0){
-				// look for a the close first
-				if(cc == "]"){ // if we're in a [...] clause and we end, do assignment
-					if(!_cp.attr){
-						// no attribute match was previously begun, so we
-						// assume this is an attribute existance match in the
-						// form of [someAttributeName]
-						_cp.attr = ts(inBrackets+1, x);
-					}else{
-						// we had an attribute already, so we know that we're
-						// matching some sort of value, as in [attrName=howdy]
-						_cp.matchFor = ts((inMatchFor||inBrackets+1), x);
-					}
-					var cmf = _cp.matchFor;
-					if(cmf){
-						// try to strip quotes from the matchFor value. We want
-						// [attrName=howdy] to match the same 
-						//	as [attrName = 'howdy' ]
-						if(	(cmf.charAt(0) == '"') || (cmf.charAt(0)  == "'") ){
-							_cp.matchFor = cmf.slice(1, -1);
-						}
-					}
-					// end the attribute by adding it to the list of attributes. 
-					currentPart.attrs.push(_cp);
-					_cp = null; // necessary?
-					inBrackets = inMatchFor = -1;
-				}else if(cc == "="){
-					// if the last char was an operator prefix, make sure we
-					// record it along with the "=" operator. 
-					var addToCc = ("|~^$*".indexOf(lc) >=0 ) ? lc : "";
-					_cp.type = addToCc+cc;
-					_cp.attr = ts(inBrackets+1, x-addToCc.length);
-					inMatchFor = x+1;
-				}
-				// now look for other clause parts
-			}else if(inParens >= 0){
-				// if we're in a parenthetical expression, we need to figure
-				// out if it's attached to a pseduo-selector rule like
-				// :nth-child(1)
-				if(cc == ")"){
-					if(inPseudo >= 0){
-						_cp.value = ts(inParens+1, x);
-					}
-					inPseudo = inParens = -1;
-				}
-			}else if(cc == "#"){
-				// start of an ID match
-				endAll();
-				inId = x+1;
-			}else if(cc == "."){
-				// start of a class match
-				endAll();
-				inClass = x;
-			}else if(cc == ":"){
-				// start of a pseudo-selector match
-				endAll();
-				inPseudo = x;
-			}else if(cc == "["){
-				// start of an attribute match. 
-				endAll();
-				inBrackets = x;
-				// provide a new structure for the attribute match to fill-in
-				_cp = {
-					/*=====
-					attr: null, type: null, matchFor: null
-					=====*/
-				};
-			}else if(cc == "("){
-				// we really only care if we've entered a parenthetical
-				// expression if we're already inside a pseudo-selector match
-				if(inPseudo >= 0){
-					// provide a new structure for the pseudo match to fill-in
-					_cp = { 
-						name: ts(inPseudo+1, x), 
-						value: null
-					}
-					currentPart.pseudos.push(_cp);
-				}
-				inParens = x;
-			}else if(
-				(cc == " ") && 
-				// if it's a space char and the last char is too, consume the
-				// current one without doing more work
-				(lc != cc)
-			){
-				endPart();
-			}
-		}
-		return queryParts;
-	};
-	
-
-	////////////////////////////////////////////////////////////////////////
-	// DOM query infrastructure
-	////////////////////////////////////////////////////////////////////////
-
-	var agree = function(first, second){
-		// the basic building block of the yes/no chaining system. agree(f1,
-		// f2) generates a new function which returns the boolean results of
-		// both of the passed functions to a single logical-anded result. If
-		// either are not possed, the other is used exclusively.
-		if(!first){ return second; }
-		if(!second){ return first; }
-
-		return function(){
-			return first.apply(window, arguments) && second.apply(window, arguments);
-		}
-	};
-
-	var getArr = function(i, arr){
-		// helps us avoid array alloc when we don't need it
-		var r = arr||[]; // FIXME: should this be 'new d._NodeListCtor()' ?
-		if(i){ r.push(i); }
-		return r;
-	};
-
-	var _isElement = function(n){ return (1 == n.nodeType); };
-
-	// FIXME: need to coalesce _getAttr with defaultGetter
-	var blank = "";
-	var _getAttr = function(elem, attr){
-		if(!elem){ return blank; }
-		if(attr == "class"){
-			return elem.className || blank;
-		}
-		if(attr == "for"){
-			return elem.htmlFor || blank;
-		}
-		if(attr == "style"){
-			return elem.style.cssText || blank;
-		}
-		return (caseSensitive ? elem.getAttribute(attr) : elem.getAttribute(attr, 2)) || blank;
-	};
-
-	var attrs = {
-		"*=": function(attr, value){
-			return function(elem){
-				// E[foo*="bar"]
-				//		an E element whose "foo" attribute value contains
-				//		the substring "bar"
-				return (_getAttr(elem, attr).indexOf(value)>=0);
-			}
-		},
-		"^=": function(attr, value){
-			// E[foo^="bar"]
-			//		an E element whose "foo" attribute value begins exactly
-			//		with the string "bar"
-			return function(elem){
-				return (_getAttr(elem, attr).indexOf(value)==0);
-			}
-		},
-		"$=": function(attr, value){
-			// E[foo$="bar"]	
-			//		an E element whose "foo" attribute value ends exactly
-			//		with the string "bar"
-			var tval = " "+value;
-			return function(elem){
-				var ea = " "+_getAttr(elem, attr);
-				return (ea.lastIndexOf(value)==(ea.length-value.length));
-			}
-		},
-		"~=": function(attr, value){
-			// E[foo~="bar"]	
-			//		an E element whose "foo" attribute value is a list of
-			//		space-separated values, one of which is exactly equal
-			//		to "bar"
-
-			// return "[contains(concat(' ',@"+attr+",' '), ' "+ value +" ')]";
-			var tval = " "+value+" ";
-			return function(elem){
-				var ea = " "+_getAttr(elem, attr)+" ";
-				return (ea.indexOf(tval)>=0);
-			}
-		},
-		"|=": function(attr, value){
-			// E[hreflang|="en"]
-			//		an E element whose "hreflang" attribute has a
-			//		hyphen-separated list of values beginning (from the
-			//		left) with "en"
-			var valueDash = " "+value+"-";
-			return function(elem){
-				var ea = " "+_getAttr(elem, attr);
-				return (
-					(ea == value) ||
-					(ea.indexOf(valueDash)==0)
-				);
-			}
-		},
-		"=": function(attr, value){
-			return function(elem){
-				return (_getAttr(elem, attr) == value);
-			}
-		}
-	};
-
-	// avoid testing for node type if we can. Defining this in the negative
-	// here to avoid negation in the fast path.
-	var _noNES = (typeof getDoc().firstChild.nextElementSibling == "undefined");
-	var _ns = !_noNES ? "nextElementSibling" : "nextSibling";
-	var _ps = !_noNES ? "previousElementSibling" : "previousSibling";
-	var _simpleNodeTest = (_noNES ? _isElement : yesman);
-
-	var _lookLeft = function(node){
-		// look left
-		while(node = node[_ps]){
-			if(_simpleNodeTest(node)){ return false; }
-		}
-		return true;
-	};
-
-	var _lookRight = function(node){
-		// look right
-		while(node = node[_ns]){
-			if(_simpleNodeTest(node)){ return false; }
-		}
-		return true;
-	};
-
-	var getNodeIndex = function(node){
-		var root = node.parentNode;
-		var i = 0,
-			tret = root[childNodesName],
-			ci = (node["_i"]||-1),
-			cl = (root["_l"]||-1);
-
-		if(!tret){ return -1; }
-		var l = tret.length;
-
-		// we calcuate the parent length as a cheap way to invalidate the
-		// cache. It's not 100% accurate, but it's much more honest than what
-		// other libraries do
-		if( cl == l && ci >= 0 && cl >= 0 ){
-			// if it's legit, tag and release
-			return ci;
-		}
-
-		// else re-key things
-		root["_l"] = l;
-		ci = -1;
-		for(var te = root["firstElementChild"]||root["firstChild"]; te; te = te[_ns]){
-			if(_simpleNodeTest(te)){ 
-				te["_i"] = ++i;
-				if(node === te){ 
-					// NOTE:
-					// 	shortcuting the return at this step in indexing works
-					// 	very well for benchmarking but we avoid it here since
-					// 	it leads to potential O(n^2) behavior in sequential
-					// 	getNodexIndex operations on a previously un-indexed
-					// 	parent. We may revisit this at a later time, but for
-					// 	now we just want to get the right answer more often
-					// 	than not.
-					ci = i;
-				}
-			}
-		}
-		return ci;
-	};
-
-	var isEven = function(elem){
-		return !((getNodeIndex(elem)) % 2);
-	};
-
-	var isOdd = function(elem){
-		return ((getNodeIndex(elem)) % 2);
-	};
-
-	var pseudos = {
-		"checked": function(name, condition){
-			return function(elem){
-				return !!("checked" in elem ? elem.checked : elem.selected);
-			}
-		},
-		"first-child": function(){ return _lookLeft; },
-		"last-child": function(){ return _lookRight; },
-		"only-child": function(name, condition){
-			return function(node){ 
-				if(!_lookLeft(node)){ return false; }
-				if(!_lookRight(node)){ return false; }
-				return true;
-			};
-		},
-		"empty": function(name, condition){
-			return function(elem){
-				// DomQuery and jQuery get this wrong, oddly enough.
-				// The CSS 3 selectors spec is pretty explicit about it, too.
-				var cn = elem.childNodes;
-				var cnl = elem.childNodes.length;
-				// if(!cnl){ return true; }
-				for(var x=cnl-1; x >= 0; x--){
-					var nt = cn[x].nodeType;
-					if((nt === 1)||(nt == 3)){ return false; }
-				}
-				return true;
-			}
-		},
-		"contains": function(name, condition){
-			var cz = condition.charAt(0);
-			if( cz == '"' || cz == "'" ){ //remove quote
-				condition = condition.slice(1, -1);
-			}
-			return function(elem){
-				return (elem.innerHTML.indexOf(condition) >= 0);
-			}
-		},
-		"not": function(name, condition){
-			var p = getQueryParts(condition)[0];
-			var ignores = { el: 1 }; 
-			if(p.tag != "*"){
-				ignores.tag = 1;
-			}
-			if(!p.classes.length){
-				ignores.classes = 1;
-			}
-			var ntf = getSimpleFilterFunc(p, ignores);
-			return function(elem){
-				return (!ntf(elem));
-			}
-		},
-		"nth-child": function(name, condition){
-			var pi = parseInt;
-			// avoid re-defining function objects if we can
-			if(condition == "odd"){
-				return isOdd;
-			}else if(condition == "even"){
-				return isEven;
-			}
-			// FIXME: can we shorten this?
-			if(condition.indexOf("n") != -1){
-				var tparts = condition.split("n", 2);
-				var pred = tparts[0] ? ((tparts[0] == '-') ? -1 : pi(tparts[0])) : 1;
-				var idx = tparts[1] ? pi(tparts[1]) : 0;
-				var lb = 0, ub = -1;
-				if(pred > 0){
-					if(idx < 0){
-						idx = (idx % pred) && (pred + (idx % pred));
-					}else if(idx>0){
-						if(idx >= pred){
-							lb = idx - idx % pred;
-						}
-						idx = idx % pred;
-					}
-				}else if(pred<0){
-					pred *= -1;
-					// idx has to be greater than 0 when pred is negative;
-					// shall we throw an error here?
-					if(idx > 0){
-						ub = idx;
-						idx = idx % pred;
-					}
-				}
-				if(pred > 0){
-					return function(elem){
-						var i = getNodeIndex(elem);
-						return (i>=lb) && (ub<0 || i<=ub) && ((i % pred) == idx);
-					}
-				}else{
-					condition = idx;
-				}
-			}
-			var ncount = pi(condition);
-			return function(elem){
-				return (getNodeIndex(elem) == ncount);
-			}
-		}
-	};
-
-	var defaultGetter = (d.isIE) ? function(cond){
-		var clc = cond.toLowerCase();
-		if(clc == "class"){ cond = "className"; }
-		return function(elem){
-			return (caseSensitive ? elem.getAttribute(cond) : elem[cond]||elem[clc]);
-		}
-	} : function(cond){
-		return function(elem){
-			return (elem && elem.getAttribute && elem.hasAttribute(cond));
-		}
-	};
-
-	var getSimpleFilterFunc = function(query, ignores){
-		// generates a node tester function based on the passed query part. The
-		// query part is one of the structures generatd by the query parser
-		// when it creates the query AST. The "ignores" object specifies which
-		// (if any) tests to skip, allowing the system to avoid duplicating
-		// work where it may have already been taken into account by other
-		// factors such as how the nodes to test were fetched in the first
-		// place
-		if(!query){ return yesman; }
-		ignores = ignores||{};
-
-		var ff = null;
-
-		if(!("el" in ignores)){
-			ff = agree(ff, _isElement);
-		}
-
-		if(!("tag" in ignores)){
-			if(query.tag != "*"){
-				ff = agree(ff, function(elem){
-					return (elem && (elem.tagName == query.getTag()));
-				});
-			}
-		}
-
-		if(!("classes" in ignores)){
-			each(query.classes, function(cname, idx, arr){
-				// get the class name
-				/*
-				var isWildcard = cname.charAt(cname.length-1) == "*";
-				if(isWildcard){
-					cname = cname.substr(0, cname.length-1);
-				}
-				// I dislike the regex thing, even if memozied in a cache, but it's VERY short
-				var re = new RegExp("(?:^|\\s)" + cname + (isWildcard ? ".*" : "") + "(?:\\s|$)");
-				*/
-				var re = new RegExp("(?:^|\\s)" + cname + "(?:\\s|$)");
-				ff = agree(ff, function(elem){
-					return re.test(elem.className);
-				});
-				ff.count = idx;
-			});
-		}
-
-		if(!("pseudos" in ignores)){
-			each(query.pseudos, function(pseudo){
-				var pn = pseudo.name;
-				if(pseudos[pn]){
-					ff = agree(ff, pseudos[pn](pn, pseudo.value));
-				}
-			});
-		}
-
-		if(!("attrs" in ignores)){
-			each(query.attrs, function(attr){
-				var matcher;
-				var a = attr.attr;
-				// type, attr, matchFor
-				if(attr.type && attrs[attr.type]){
-					matcher = attrs[attr.type](a, attr.matchFor);
-				}else if(a.length){
-					matcher = defaultGetter(a);
-				}
-				if(matcher){
-					ff = agree(ff, matcher);
-				}
-			});
-		}
-
-		if(!("id" in ignores)){
-			if(query.id){
-				ff = agree(ff, function(elem){ 
-					return (!!elem && (elem.id == query.id));
-				});
-			}
-		}
-
-		if(!ff){
-			if(!("default" in ignores)){
-				ff = yesman; 
-			}
-		}
-		return ff;
-	};
-
-	var _nextSibling = function(filterFunc){
-		return function(node, ret, bag){
-			while(node = node[_ns]){
-				if(_noNES && (!_isElement(node))){ continue; }
-				if(
-					(!bag || _isUnique(node, bag)) &&
-					filterFunc(node)
-				){
-					ret.push(node);
-				}
-				break;
-			}
-			return ret;
-		}
-	};
-
-	var _nextSiblings = function(filterFunc){
-		return function(root, ret, bag){
-			var te = root[_ns];
-			while(te){
-				if(_simpleNodeTest(te)){
-					if(bag && !_isUnique(te, bag)){
-						break;
-					}
-					if(filterFunc(te)){
-						ret.push(te);
-					}
-				}
-				te = te[_ns];
-			}
-			return ret;
-		}
-	};
-
-	// get an array of child *elements*, skipping text and comment nodes
-	var _childElements = function(filterFunc){
-		filterFunc = filterFunc||yesman;
-		return function(root, ret, bag){
-			// get an array of child elements, skipping text and comment nodes
-			var te, x = 0, tret = root[childNodesName];
-			while(te = tret[x++]){
-				if(
-					_simpleNodeTest(te) &&
-					(!bag || _isUnique(te, bag)) &&
-					(filterFunc(te, x))
-				){ 
-					ret.push(te);
-				}
-			}
-			return ret;
-		};
-	};
-	
-	/*
-	// thanks, Dean!
-	var itemIsAfterRoot = d.isIE ? function(item, root){
-		return (item.sourceIndex > root.sourceIndex);
-	} : function(item, root){
-		return (item.compareDocumentPosition(root) == 2);
-	};
-	*/
-
-	// test to see if node is below root
-	var _isDescendant = function(node, root){
-		var pn = node.parentNode;
-		while(pn){
-			if(pn == root){
-				break;
-			}
-			pn = pn.parentNode;
-		}
-		return !!pn;
-	};
-
-	var _getElementsFuncCache = {};
-
-	var getElementsFunc = function(query){
-		var retFunc = _getElementsFuncCache[query.query];
-		// if we've got a cached dispatcher, just use that
-		if(retFunc){ return retFunc; }
-		// else, generate a new on
-
-		// NOTE:
-		//		this function returns a function that searches for nodes and
-		//		filters them.  The search may be specialized by infix operators
-		//		(">", "~", or "+") else it will default to searching all
-		//		descendants (the " " selector). Once a group of children is
-		//		founde, a test function is applied to weed out the ones we
-		//		don't want. Many common cases can be fast-pathed. We spend a
-		//		lot of cycles to create a dispatcher that doesn't do more work
-		//		than necessary at any point since, unlike this function, the
-		//		dispatchers will be called every time. The logic of generating
-		//		efficient dispatchers looks like this in pseudo code:
-		//
-		//		# if it's a purely descendant query (no ">", "+", or "~" modifiers)
-		//		if infixOperator == " ":
-		//			if only(id):
-		//				return def(root):
-		//					return d.byId(id, root);
-		//
-		//			elif id:
-		//				return def(root):
-		//					return filter(d.byId(id, root));
-		//
-		//			elif cssClass && getElementsByClassName:
-		//				return def(root):
-		//					return filter(root.getElementsByClassName(cssClass));
-		//
-		//			elif only(tag):
-		//				return def(root):
-		//					return root.getElementsByTagName(tagName);
-		//
-		//			else:
-		//				# search by tag name, then filter
-		//				return def(root):
-		//					return filter(root.getElementsByTagName(tagName||"*"));
-		//
-		//		elif infixOperator == ">":
-		//			# search direct children
-		//			return def(root):
-		//				return filter(root.children);
-		//
-		//		elif infixOperator == "+":
-		//			# search next sibling
-		//			return def(root):
-		//				return filter(root.nextElementSibling);
-		//
-		//		elif infixOperator == "~":
-		//			# search rightward siblings
-		//			return def(root):
-		//				return filter(nextSiblings(root));
-
-		var io = query.infixOper;
-		var oper = (io ? io.oper : "");
-		// the default filter func which tests for all conditions in the query
-		// part. This is potentially inefficient, so some optimized paths may
-		// re-define it to test fewer things.
-		var filterFunc = getSimpleFilterFunc(query, { el: 1 });
-		var qt = query.tag;
-		var wildcardTag = ("*" == qt);
-		var ecs = getDoc()["getElementsByClassName"]; 
-
-		if(!oper){
-			// if there's no infix operator, then it's a descendant query. ID
-			// and "elements by class name" variants can be accelerated so we
-			// call them out explicitly:
-			if(query.id){
-				// testing shows that the overhead of yesman() is acceptable
-				// and can save us some bytes vs. re-defining the function
-				// everywhere.
-				filterFunc = (!query.loops && wildcardTag) ? 
-					yesman : 
-					getSimpleFilterFunc(query, { el: 1, id: 1 });
-
-				retFunc = function(root, arr){
-					var te = d.byId(query.id, (root.ownerDocument||root));
-					if(!te || !filterFunc(te)){ return; }
-					if(9 == root.nodeType){ // if root's a doc, we just return directly
-						return getArr(te, arr);
-					}else{ // otherwise check ancestry
-						if(_isDescendant(te, root)){
-							return getArr(te, arr);
-						}
-					}
-				}
-			}else if(
-				ecs && 
-				// isAlien check. Workaround for Prototype.js being totally evil/dumb.
-				/\{\s*\[native code\]\s*\}/.test(String(ecs)) && 
-				query.classes.length &&
-				!cssCaseBug
-			){
-				// it's a class-based query and we've got a fast way to run it.
-
-				// ignore class and ID filters since we will have handled both
-				filterFunc = getSimpleFilterFunc(query, { el: 1, classes: 1, id: 1 });
-				var classesString = query.classes.join(" ");
-				retFunc = function(root, arr, bag){
-					var ret = getArr(0, arr), te, x=0;
-					var tret = root.getElementsByClassName(classesString);
-					while((te = tret[x++])){
-						if(filterFunc(te, root) && _isUnique(te, bag)){
-							ret.push(te);
-						}
-					}
-					return ret;
-				};
-
-			}else if(!wildcardTag && !query.loops){
-				// it's tag only. Fast-path it.
-				retFunc = function(root, arr, bag){
-					var ret = getArr(0, arr), te, x=0;
-					var tret = root.getElementsByTagName(query.getTag());
-					while((te = tret[x++])){
-						if(_isUnique(te, bag)){
-							ret.push(te);
-						}
-					}
-					return ret;
-				};
-			}else{
-				// the common case:
-				//		a descendant selector without a fast path. By now it's got
-				//		to have a tag selector, even if it's just "*" so we query
-				//		by that and filter
-				filterFunc = getSimpleFilterFunc(query, { el: 1, tag: 1, id: 1 });
-				retFunc = function(root, arr, bag){
-					var ret = getArr(0, arr), te, x=0;
-					// we use getTag() to avoid case sensitivity issues
-					var tret = root.getElementsByTagName(query.getTag());
-					while((te = tret[x++])){
-						if(filterFunc(te, root) && _isUnique(te, bag)){
-							ret.push(te);
-						}
-					}
-					return ret;
-				};
-			}
-		}else{
-			// the query is scoped in some way. Instead of querying by tag we
-			// use some other collection to find candidate nodes
-			var skipFilters = { el: 1 };
-			if(wildcardTag){
-				skipFilters.tag = 1;
-			}
-			filterFunc = getSimpleFilterFunc(query, skipFilters);
-			if("+" == oper){
-				retFunc = _nextSibling(filterFunc);
-			}else if("~" == oper){
-				retFunc = _nextSiblings(filterFunc);
-			}else if(">" == oper){
-				retFunc = _childElements(filterFunc);
-			}
-		}
-		// cache it and return
-		return _getElementsFuncCache[query.query] = retFunc;
-	};
-
-	var filterDown = function(root, queryParts){
-		// NOTE:
-		//		this is the guts of the DOM query system. It takes a list of
-		//		parsed query parts and a root and finds children which match
-		//		the selector represented by the parts
-		var candidates = getArr(root), qp, x, te, qpl = queryParts.length, bag, ret;
-
-		for(var i = 0; i < qpl; i++){
-			ret = [];
-			qp = queryParts[i];
-			x = candidates.length - 1;
-			if(x > 0){
-				// if we have more than one root at this level, provide a new
-				// hash to use for checking group membership but tell the
-				// system not to post-filter us since we will already have been
-				// gauranteed to be unique
-				bag = {};
-				ret.nozip = true;
-			}
-			var gef = getElementsFunc(qp);
-			for(var j = 0; (te = candidates[j]); j++){
-				// for every root, get the elements that match the descendant
-				// selector, adding them to the "ret" array and filtering them
-				// via membership in this level's bag. If there are more query
-				// parts, then this level's return will be used as the next
-				// level's candidates
-				gef(te, ret, bag);
-			}
-			if(!ret.length){ break; }
-			candidates = ret;
-		}
-		return ret;
-	};
-
-	////////////////////////////////////////////////////////////////////////
-	// the query runner
-	////////////////////////////////////////////////////////////////////////
-
-	// these are the primary caches for full-query results. The query
-	// dispatcher functions are generated then stored here for hash lookup in
-	// the future
-	var _queryFuncCacheDOM = {},
-		_queryFuncCacheQSA = {};
-
-	// this is the second level of spliting, from full-length queries (e.g.,
-	// "div.foo .bar") into simple query expressions (e.g., ["div.foo",
-	// ".bar"])
-	var getStepQueryFunc = function(query){
-		var qparts = getQueryParts(trim(query));
-
-		// if it's trivial, avoid iteration and zipping costs
-		if(qparts.length == 1){
-			// we optimize this case here to prevent dispatch further down the
-			// chain, potentially slowing things down. We could more elegantly
-			// handle this in filterDown(), but it's slower for simple things
-			// that need to be fast (e.g., "#someId").
-			var tef = getElementsFunc(qparts[0]);
-			return function(root){
-				var r = tef(root, new qlc());
-				if(r){ r.nozip = true; }
-				return r;
-			}
-		}
-
-		// otherwise, break it up and return a runner that iterates over the parts recursively
-		return function(root){
-			return filterDown(root, qparts);
-		}
-	};
-
-	// NOTES:
-	//	* we can't trust QSA for anything but document-rooted queries, so
-	//	  caching is split into DOM query evaluators and QSA query evaluators
-	//	* caching query results is dirty and leak-prone (or, at a minimum,
-	//	  prone to unbounded growth). Other toolkits may go this route, but
-	//	  they totally destroy their own ability to manage their memory
-	//	  footprint. If we implement it, it should only ever be with a fixed
-	//	  total element reference # limit and an LRU-style algorithm since JS
-	//	  has no weakref support. Caching compiled query evaluators is also
-	//	  potentially problematic, but even on large documents the size of the
-	//	  query evaluators is often < 100 function objects per evaluator (and
-	//	  LRU can be applied if it's ever shown to be an issue).
-	//	* since IE's QSA support is currently only for HTML documents and even
-	//	  then only in IE 8's "standards mode", we have to detect our dispatch
-	//	  route at query time and keep 2 separate caches. Ugg.
-
-	// we need to determine if we think we can run a given query via
-	// querySelectorAll or if we'll need to fall back on DOM queries to get
-	// there. We need a lot of information about the environment and the query
-	// to make the determiniation (e.g. does it support QSA, does the query in
-	// question work in the native QSA impl, etc.).
-	var nua = navigator.userAgent;
-	// some versions of Safari provided QSA, but it was buggy and crash-prone.
-	// We need te detect the right "internal" webkit version to make this work.
-	var wk = "WebKit/";
-	var is525 = (
-		d.isWebKit && 
-		(nua.indexOf(wk) > 0) && 
-		(parseFloat(nua.split(wk)[1]) > 528)
-	);
-
-	// IE QSA queries may incorrectly include comment nodes, so we throw the
-	// zipping function into "remove" comments mode instead of the normal "skip
-	// it" which every other QSA-clued browser enjoys
-	var noZip = d.isIE ? "commentStrip" : "nozip";
-
-	var qsa = "querySelectorAll";
-	var qsaAvail = (
-		!!getDoc()[qsa] && 
-		// see #5832
-		(!d.isSafari || (d.isSafari > 3.1) || is525 )
-	);
-
-	//Don't bother with n+3 type of matches, IE complains if we modify those.
-	var infixSpaceRe = /n\+\d|([^ ])?([>~+])([^ =])?/g;
-	var infixSpaceFunc = function(match, pre, ch, post) {
-		return ch ? (pre ? pre + " " : "") + ch + (post ? " " + post : "") : /*n+3*/ match;
-	};
-
-	var getQueryFunc = function(query, forceDOM){
-		//Normalize query. The CSS3 selectors spec allows for omitting spaces around
-		//infix operators, >, ~ and +
-		//Do the work here since detection for spaces is used as a simple "not use QSA"
-		//test below.
-		query = query.replace(infixSpaceRe, infixSpaceFunc);
-
-		if(qsaAvail){
-			// if we've got a cached variant and we think we can do it, run it!
-			var qsaCached = _queryFuncCacheQSA[query];
-			if(qsaCached && !forceDOM){ return qsaCached; }
-		}
-
-		// else if we've got a DOM cached variant, assume that we already know
-		// all we need to and use it
-		var domCached = _queryFuncCacheDOM[query];
-		if(domCached){ return domCached; }
-
-		// TODO: 
-		//		today we're caching DOM and QSA branches separately so we
-		//		recalc useQSA every time. If we had a way to tag root+query
-		//		efficiently, we'd be in good shape to do a global cache.
-
-		var qcz = query.charAt(0);
-		var nospace = (-1 == query.indexOf(" "));
-
-		// byId searches are wicked fast compared to QSA, even when filtering
-		// is required
-		if( (query.indexOf("#") >= 0) && (nospace) ){
-			forceDOM = true;
-		}
-
-		var useQSA = ( 
-			qsaAvail && (!forceDOM) &&
-			// as per CSS 3, we can't currently start w/ combinator:
-			//		http://www.w3.org/TR/css3-selectors/#w3cselgrammar
-			(specials.indexOf(qcz) == -1) && 
-			// IE's QSA impl sucks on pseudos
-			(!d.isIE || (query.indexOf(":") == -1)) &&
-
-			(!(cssCaseBug && (query.indexOf(".") >= 0))) &&
-
-			// FIXME:
-			//		need to tighten up browser rules on ":contains" and "|=" to
-			//		figure out which aren't good
-			//		Latest webkit (around 531.21.8) does not seem to do well with :checked on option
-			//		elements, even though according to spec, selected options should
-			//		match :checked. So go nonQSA for it:
-			//		http://bugs.dojotoolkit.org/ticket/5179
-			(query.indexOf(":contains") == -1) && (query.indexOf(":checked") == -1) && 
-			(query.indexOf("|=") == -1) // some browsers don't grok it
-		);
-
-		// TODO: 
-		//		if we've got a descendant query (e.g., "> .thinger" instead of
-		//		just ".thinger") in a QSA-able doc, but are passed a child as a
-		//		root, it should be possible to give the item a synthetic ID and
-		//		trivially rewrite the query to the form "#synid > .thinger" to
-		//		use the QSA branch
-
-
-		if(useQSA){
-			var tq = (specials.indexOf(query.charAt(query.length-1)) >= 0) ? 
-						(query + " *") : query;
-			return _queryFuncCacheQSA[query] = function(root){
-				try{
-					// the QSA system contains an egregious spec bug which
-					// limits us, effectively, to only running QSA queries over
-					// entire documents.  See:
-					//		http://ejohn.org/blog/thoughts-on-queryselectorall/
-					//	despite this, we can also handle QSA runs on simple
-					//	selectors, but we don't want detection to be expensive
-					//	so we're just checking for the presence of a space char
-					//	right now. Not elegant, but it's cheaper than running
-					//	the query parser when we might not need to
-					if(!((9 == root.nodeType) || nospace)){ throw ""; }
-					var r = root[qsa](tq);
-					// skip expensive duplication checks and just wrap in a NodeList
-					r[noZip] = true;
-					return r;
-				}catch(e){
-					// else run the DOM branch on this query, ensuring that we
-					// default that way in the future
-					return getQueryFunc(query, true)(root);
-				}
-			}
-		}else{
-			// DOM branch
-			var parts = query.split(/\s*,\s*/);
-			return _queryFuncCacheDOM[query] = ((parts.length < 2) ? 
-				// if not a compound query (e.g., ".foo, .bar"), cache and return a dispatcher
-				getStepQueryFunc(query) : 
-				// if it *is* a complex query, break it up into its
-				// constituent parts and return a dispatcher that will
-				// merge the parts when run
-				function(root){
-					var pindex = 0, // avoid array alloc for every invocation
-						ret = [],
-						tp;
-					while((tp = parts[pindex++])){
-						ret = ret.concat(getStepQueryFunc(tp)(root));
-					}
-					return ret;
-				}
-			);
-		}
-	};
-
-	var _zipIdx = 0;
-
-	// NOTE:
-	//		this function is Moo inspired, but our own impl to deal correctly
-	//		with XML in IE
-	var _nodeUID = d.isIE ? function(node){
-		if(caseSensitive){
-			// XML docs don't have uniqueID on their nodes
-			return (node.getAttribute("_uid") || node.setAttribute("_uid", ++_zipIdx) || _zipIdx);
-
-		}else{
-			return node.uniqueID;
-		}
-	} : 
-	function(node){
-		return (node._uid || (node._uid = ++_zipIdx));
-	};
-
-	// determine if a node in is unique in a "bag". In this case we don't want
-	// to flatten a list of unique items, but rather just tell if the item in
-	// question is already in the bag. Normally we'd just use hash lookup to do
-	// this for us but IE's DOM is busted so we can't really count on that. On
-	// the upside, it gives us a built in unique ID function. 
-	var _isUnique = function(node, bag){
-		if(!bag){ return 1; }
-		var id = _nodeUID(node);
-		if(!bag[id]){ return bag[id] = 1; }
-		return 0;
-	};
-
-	// attempt to efficiently determine if an item in a list is a dupe,
-	// returning a list of "uniques", hopefully in doucment order
-	var _zipIdxName = "_zipIdx";
-	var _zip = function(arr){
-		if(arr && arr.nozip){ 
-			return (qlc._wrap) ? qlc._wrap(arr) : arr;
-		}
-		// var ret = new d._NodeListCtor();
-		var ret = new qlc();
-		if(!arr || !arr.length){ return ret; }
-		if(arr[0]){
-			ret.push(arr[0]);
-		}
-		if(arr.length < 2){ return ret; }
-
-		_zipIdx++;
-		
-		// we have to fork here for IE and XML docs because we can't set
-		// expandos on their nodes (apparently). *sigh*
-		if(d.isIE && caseSensitive){
-			var szidx = _zipIdx+"";
-			arr[0].setAttribute(_zipIdxName, szidx);
-			for(var x = 1, te; te = arr[x]; x++){
-				if(arr[x].getAttribute(_zipIdxName) != szidx){ 
-					ret.push(te);
-				}
-				te.setAttribute(_zipIdxName, szidx);
-			}
-		}else if(d.isIE && arr.commentStrip){
-			try{
-				for(var x = 1, te; te = arr[x]; x++){
-					if(_isElement(te)){ 
-						ret.push(te);
-					}
-				}
-			}catch(e){ /* squelch */ }
-		}else{
-			if(arr[0]){ arr[0][_zipIdxName] = _zipIdx; }
-			for(var x = 1, te; te = arr[x]; x++){
-				if(arr[x][_zipIdxName] != _zipIdx){ 
-					ret.push(te);
-				}
-				te[_zipIdxName] = _zipIdx;
-			}
-		}
-		return ret;
-	};
-
-	// the main executor
-	d.query = function(/*String*/ query, /*String|DOMNode?*/ root){
-		//	summary:
-		//		Returns nodes which match the given CSS3 selector, searching the
-		//		entire document by default but optionally taking a node to scope
-		//		the search by. Returns an instance of dojo.NodeList.
-		//	description:
-		//		dojo.query() is the swiss army knife of DOM node manipulation in
-		//		Dojo. Much like Prototype's "$$" (bling-bling) function or JQuery's
-		//		"$" function, dojo.query provides robust, high-performance
-		//		CSS-based node selector support with the option of scoping searches
-		//		to a particular sub-tree of a document.
-		//
-		//		Supported Selectors:
-		//		--------------------
-		//
-		//		dojo.query() supports a rich set of CSS3 selectors, including:
-		//
-		//			* class selectors (e.g., `.foo`)
-		//			* node type selectors like `span`
-		//			* ` ` descendant selectors
-		//			* `>` child element selectors 
-		//			* `#foo` style ID selectors
-		//			* `*` universal selector
-		//			* `~`, the immediately preceeded-by sibling selector
-		//			* `+`, the preceeded-by sibling selector
-		//			* attribute queries:
-		//			|	* `[foo]` attribute presence selector
-		//			|	* `[foo='bar']` attribute value exact match
-		//			|	* `[foo~='bar']` attribute value list item match
-		//			|	* `[foo^='bar']` attribute start match
-		//			|	* `[foo$='bar']` attribute end match
-		//			|	* `[foo*='bar']` attribute substring match
-		//			* `:first-child`, `:last-child`, and `:only-child` positional selectors
-		//			* `:empty` content emtpy selector
-		//			* `:checked` pseudo selector
-		//			* `:nth-child(n)`, `:nth-child(2n+1)` style positional calculations
-		//			* `:nth-child(even)`, `:nth-child(odd)` positional selectors
-		//			* `:not(...)` negation pseudo selectors
-		//
-		//		Any legal combination of these selectors will work with
-		//		`dojo.query()`, including compound selectors ("," delimited).
-		//		Very complex and useful searches can be constructed with this
-		//		palette of selectors and when combined with functions for
-		//		manipulation presented by dojo.NodeList, many types of DOM
-		//		manipulation operations become very straightforward.
-		//		
-		//		Unsupported Selectors:
-		//		----------------------
-		//
-		//		While dojo.query handles many CSS3 selectors, some fall outside of
-		//		what's resaonable for a programmatic node querying engine to
-		//		handle. Currently unsupported selectors include:
-		//		
-		//			* namespace-differentiated selectors of any form
-		//			* all `::` pseduo-element selectors
-		//			* certain pseduo-selectors which don't get a lot of day-to-day use:
-		//			|	* `:root`, `:lang()`, `:target`, `:focus`
-		//			* all visual and state selectors:
-		//			|	* `:root`, `:active`, `:hover`, `:visisted`, `:link`,
-		//				  `:enabled`, `:disabled`
-		//			* `:*-of-type` pseudo selectors
-		//		
-		//		dojo.query and XML Documents:
-		//		-----------------------------
-		//		
-		//		`dojo.query` (as of dojo 1.2) supports searching XML documents
-		//		in a case-sensitive manner. If an HTML document is served with
-		//		a doctype that forces case-sensitivity (e.g., XHTML 1.1
-		//		Strict), dojo.query() will detect this and "do the right
-		//		thing". Case sensitivity is dependent upon the document being
-		//		searched and not the query used. It is therefore possible to
-		//		use case-sensitive queries on strict sub-documents (iframes,
-		//		etc.) or XML documents while still assuming case-insensitivity
-		//		for a host/root document.
-		//
-		//		Non-selector Queries:
-		//		---------------------
-		//
-		//		If something other than a String is passed for the query,
-		//		`dojo.query` will return a new `dojo.NodeList` instance
-		//		constructed from that parameter alone and all further
-		//		processing will stop. This means that if you have a reference
-		//		to a node or NodeList, you can quickly construct a new NodeList
-		//		from the original by calling `dojo.query(node)` or
-		//		`dojo.query(list)`.
-		//
-		//	query:
-		//		The CSS3 expression to match against. For details on the syntax of
-		//		CSS3 selectors, see <http://www.w3.org/TR/css3-selectors/#selectors>
-		//	root:
-		//		A DOMNode (or node id) to scope the search from. Optional.
-		//	returns: dojo.NodeList
-		//		An instance of `dojo.NodeList`. Many methods are available on
-		//		NodeLists for searching, iterating, manipulating, and handling
-		//		events on the matched nodes in the returned list.
-		//	example:
-		//		search the entire document for elements with the class "foo":
-		//	|	dojo.query(".foo");
-		//		these elements will match:
-		//	|	<span class="foo"></span>
-		//	|	<span class="foo bar"></span>
-		//	|	<p class="thud foo"></p>
-		//	example:
-		//		search the entire document for elements with the classes "foo" *and* "bar":
-		//	|	dojo.query(".foo.bar");
-		//		these elements will match:
-		//	|	<span class="foo bar"></span>
-		//		while these will not:
-		//	|	<span class="foo"></span>
-		//	|	<p class="thud foo"></p>
-		//	example:
-		//		find `<span>` elements which are descendants of paragraphs and
-		//		which have a "highlighted" class:
-		//	|	dojo.query("p span.highlighted");
-		//		the innermost span in this fragment matches:
-		//	|	<p class="foo">
-		//	|		<span>...
-		//	|			<span class="highlighted foo bar">...</span>
-		//	|		</span>
-		//	|	</p>
-		//	example:
-		//		set an "odd" class on all odd table rows inside of the table
-		//		`#tabular_data`, using the `>` (direct child) selector to avoid
-		//		affecting any nested tables:
-		//	|	dojo.query("#tabular_data > tbody > tr:nth-child(odd)").addClass("odd");
-		//	example:
-		//		remove all elements with the class "error" from the document
-		//		and store them in a list:
-		//	|	var errors = dojo.query(".error").orphan();
-		//	example:
-		//		add an onclick handler to every submit button in the document
-		//		which causes the form to be sent via Ajax instead:
-		//	|	dojo.query("input[type='submit']").onclick(function(e){
-		//	|		dojo.stopEvent(e); // prevent sending the form
-		//	|		var btn = e.target;
-		//	|		dojo.xhrPost({
-		//	|			form: btn.form,
-		//	|			load: function(data){
-		//	|				// replace the form with the response
-		//	|				var div = dojo.doc.createElement("div");
-		//	|				dojo.place(div, btn.form, "after");
-		//	|				div.innerHTML = data;
-		//	|				dojo.style(btn.form, "display", "none");
-		//	|			}
-		//	|		});
-		//	|	});
-
-		//Set list constructor to desired value. This can change
-		//between calls, so always re-assign here.
-		qlc = d._NodeListCtor;
-
-		if(!query){
-			return new qlc();
-		}
-
-		if(query.constructor == qlc){
-			return query;
-		}
-		if(typeof query != "string"){ // inline'd type check
-			return new qlc(query); // dojo.NodeList
-		}
-		if(typeof root == "string"){ // inline'd type check
-			root = d.byId(root);
-			if(!root){ return new qlc(); }
-		}
-
-		root = root||getDoc();
-		var od = root.ownerDocument||root.documentElement;
-
-		// throw the big case sensitivity switch
-
-		// NOTE:
-		// 		Opera in XHTML mode doesn't detect case-sensitivity correctly
-		// 		and it's not clear that there's any way to test for it
-		caseSensitive = (root.contentType && root.contentType=="application/xml") || 
-						(d.isOpera && (root.doctype || od.toString() == "[object XMLDocument]")) ||
-						(!!od) && 
-						(d.isIE ? od.xml : (root.xmlVersion||od.xmlVersion));
-
-		// NOTE: 
-		//		adding "true" as the 2nd argument to getQueryFunc is useful for
-		//		testing the DOM branch without worrying about the
-		//		behavior/performance of the QSA branch.
-		var r = getQueryFunc(query)(root);
-
-		// FIXME:
-		//		need to investigate this branch WRT #8074 and #8075
-		if(r && r.nozip && !qlc._wrap){
-			return r;
-		}
-		return _zip(r); // dojo.NodeList
-	}
-
-	// FIXME: need to add infrastructure for post-filtering pseudos, ala :last
-	d.query.pseudos = pseudos;
-
-	// one-off function for filtering a NodeList based on a simple selector
-	d._filterQueryResult = function(nodeList, simpleFilter){
-		var tmpNodeList = new d._NodeListCtor();
-		var filterFunc = getSimpleFilterFunc(getQueryParts(simpleFilter)[0]);
-		for(var x = 0, te; te = nodeList[x]; x++){
-			if(filterFunc(te)){ tmpNodeList.push(te); }
-		}
-		return tmpNodeList;
-	}
-})(this["queryPortability"]||this["acme"]||dojo);
-
-/*
-*/
-
-}
-
-if(!dojo._hasResource["dojo._base.xhr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.xhr"] = true;
-dojo.provide("dojo._base.xhr");
-
-
-
-
-
-(function(){
-	var _d = dojo, cfg = _d.config;
-
-	function setValue(/*Object*/obj, /*String*/name, /*String*/value){
-		//summary:
-		//		For the named property in object, set the value. If a value
-		//		already exists and it is a string, convert the value to be an
-		//		array of values.
-
-		//Skip it if there is no value
-		if(value === null){
-			return;
-		}
-
-		var val = obj[name];
-		if(typeof val == "string"){ // inline'd type check
-			obj[name] = [val, value];
-		}else if(_d.isArray(val)){
-			val.push(value);
-		}else{
-			obj[name] = value;
-		}
-	}
-	
-	dojo.fieldToObject = function(/*DOMNode||String*/ inputNode){
-		// summary:
-		//		Serialize a form field to a JavaScript object.
-		//
-		// description:
-		//		Returns the value encoded in a form field as
-		//		as a string or an array of strings. Disabled form elements
-		//		and unchecked radio and checkboxes are skipped.	Multi-select
-		//		elements are returned as an array of string values.
-		var ret = null;
-		var item = _d.byId(inputNode);
-		if(item){
-			var _in = item.name;
-			var type = (item.type||"").toLowerCase();
-			if(_in && type && !item.disabled){
-				if(type == "radio" || type == "checkbox"){
-					if(item.checked){ ret = item.value }
-				}else if(item.multiple){
-					ret = [];
-					_d.query("option", item).forEach(function(opt){
-						if(opt.selected){
-							ret.push(opt.value);
-						}
-					});
-				}else{
-					ret = item.value;
-				}
-			}
-		}
-		return ret; // Object
-	}
-
-	dojo.formToObject = function(/*DOMNode||String*/ formNode){
-		// summary:
-		//		Serialize a form node to a JavaScript object.
-		// description:
-		//		Returns the values encoded in an HTML form as
-		//		string properties in an object which it then returns. Disabled form
-		//		elements, buttons, and other non-value form elements are skipped.
-		//		Multi-select elements are returned as an array of string values.
-		//
-		// example:
-		//		This form:
-		//		|	<form id="test_form">
-		//		|		<input type="text" name="blah" value="blah">
-		//		|		<input type="text" name="no_value" value="blah" disabled>
-		//		|		<input type="button" name="no_value2" value="blah">
-		//		|		<select type="select" multiple name="multi" size="5">
-		//		|			<option value="blah">blah</option>
-		//		|			<option value="thud" selected>thud</option>
-		//		|			<option value="thonk" selected>thonk</option>
-		//		|		</select>
-		//		|	</form>
-		//
-		//		yields this object structure as the result of a call to
-		//		formToObject():
-		//
-		//		|	{ 
-		//		|		blah: "blah",
-		//		|		multi: [
-		//		|			"thud",
-		//		|			"thonk"
-		//		|		]
-		//		|	};
-
-		var ret = {};
-		var exclude = "file|submit|image|reset|button|";
-		_d.forEach(dojo.byId(formNode).elements, function(item){
-			var _in = item.name;
-			var type = (item.type||"").toLowerCase();
-			if(_in && type && exclude.indexOf(type) == -1 && !item.disabled){
-				setValue(ret, _in, _d.fieldToObject(item));
-				if(type == "image"){
-					ret[_in+".x"] = ret[_in+".y"] = ret[_in].x = ret[_in].y = 0;
-				}
-			}
-		});
-		return ret; // Object
-	}
-
-	dojo.objectToQuery = function(/*Object*/ map){
-		//	summary:
-		//		takes a name/value mapping object and returns a string representing
-		//		a URL-encoded version of that object.
-		//	example:
-		//		this object:
-		//
-		//		|	{ 
-		//		|		blah: "blah",
-		//		|		multi: [
-		//		|			"thud",
-		//		|			"thonk"
-		//		|		]
-		//		|	};
-		//
-		//	yields the following query string:
-		//	
-		//	|	"blah=blah&multi=thud&multi=thonk"
-
-		// FIXME: need to implement encodeAscii!!
-		var enc = encodeURIComponent;
-		var pairs = [];
-		var backstop = {};
-		for(var name in map){
-			var value = map[name];
-			if(value != backstop[name]){
-				var assign = enc(name) + "=";
-				if(_d.isArray(value)){
-					for(var i=0; i < value.length; i++){
-						pairs.push(assign + enc(value[i]));
-					}
-				}else{
-					pairs.push(assign + enc(value));
-				}
-			}
-		}
-		return pairs.join("&"); // String
-	}
-
-	dojo.formToQuery = function(/*DOMNode||String*/ formNode){
-		// summary:
-		//		Returns a URL-encoded string representing the form passed as either a
-		//		node or string ID identifying the form to serialize
-		return _d.objectToQuery(_d.formToObject(formNode)); // String
-	}
-
-	dojo.formToJson = function(/*DOMNode||String*/ formNode, /*Boolean?*/prettyPrint){
-		// summary:
-		//		Create a serialized JSON string from a form node or string
-		//		ID identifying the form to serialize
-		return _d.toJson(_d.formToObject(formNode), prettyPrint); // String
-	}
-
-	dojo.queryToObject = function(/*String*/ str){
-		// summary:
-		//		Create an object representing a de-serialized query section of a
-		//		URL. Query keys with multiple values are returned in an array.
-		//
-		// example:
-		//		This string:
-		//
-		//	|		"foo=bar&foo=baz&thinger=%20spaces%20=blah&zonk=blarg&"
-		//		
-		//		results in this object structure:
-		//
-		//	|		{
-		//	|			foo: [ "bar", "baz" ],
-		//	|			thinger: " spaces =blah",
-		//	|			zonk: "blarg"
-		//	|		}
-		//	
-		//		Note that spaces and other urlencoded entities are correctly
-		//		handled.
-
-		// FIXME: should we grab the URL string if we're not passed one?
-		var ret = {};
-		var qp = str.split("&");
-		var dec = decodeURIComponent;
-		_d.forEach(qp, function(item){
-			if(item.length){
-				var parts = item.split("=");
-				var name = dec(parts.shift());
-				var val = dec(parts.join("="));
-				if(typeof ret[name] == "string"){ // inline'd type check
-					ret[name] = [ret[name]];
-				}
-
-				if(_d.isArray(ret[name])){
-					ret[name].push(val);
-				}else{
-					ret[name] = val;
-				}
-			}
-		});
-		return ret; // Object
-	}
-
-	// need to block async callbacks from snatching this thread as the result
-	// of an async callback might call another sync XHR, this hangs khtml forever
-	// must checked by watchInFlight()
-
-	dojo._blockAsync = false;
-
-	// MOW: remove dojo._contentHandlers alias in 2.0
-	var handlers = _d._contentHandlers = dojo.contentHandlers = {
-		// summary: 
-		//		A map of availble XHR transport handle types. Name matches the
-		//		`handleAs` attribute passed to XHR calls.
-		//
-		// description:
-		//		A map of availble XHR transport handle types. Name matches the
-		//		`handleAs` attribute passed to XHR calls. Each contentHandler is
-		//		called, passing the xhr object for manipulation. The return value
-		//		from the contentHandler will be passed to the `load` or `handle` 
-		//		functions defined in the original xhr call. 
-		//		
-		// example:
-		//		Creating a custom content-handler:
-		//	|	dojo.contentHandlers.makeCaps = function(xhr){
-		//	|		return xhr.responseText.toUpperCase();
-		//	|	}
-		//	|	// and later:
-		//	|	dojo.xhrGet({ 
-		//	|		url:"foo.txt",
-		//	|		handleAs:"makeCaps",
-		//	|		load: function(data){ /* data is a toUpper version of foo.txt */ }
-		//	|	});
-
-		text: function(xhr){ 
-			// summary: A contentHandler which simply returns the plaintext response data
-			return xhr.responseText; 
-		},
-		json: function(xhr){
-			// summary: A contentHandler which returns a JavaScript object created from the response data
-			return _d.fromJson(xhr.responseText || null);
-		},
-		"json-comment-filtered": function(xhr){ 
-			// summary: A contentHandler which expects comment-filtered JSON. 
-			// description: 
-			//		A contentHandler which expects comment-filtered JSON. 
-			//		the json-comment-filtered option was implemented to prevent
-			//		"JavaScript Hijacking", but it is less secure than standard JSON. Use
-			//		standard JSON instead. JSON prefixing can be used to subvert hijacking.
-			//		
-			//		Will throw a notice suggesting to use application/json mimetype, as
-			//		json-commenting can introduce security issues. To decrease the chances of hijacking,
-			//		use the standard `json` contentHandler, and prefix your "JSON" with: {}&& 
-			//		
-			//		use djConfig.useCommentedJson = true to turn off the notice
-			if(!dojo.config.useCommentedJson){
-				console.warn("Consider using the standard mimetype:application/json."
-					+ " json-commenting can introduce security issues. To"
-					+ " decrease the chances of hijacking, use the standard the 'json' handler and"
-					+ " prefix your json with: {}&&\n"
-					+ "Use djConfig.useCommentedJson=true to turn off this message.");
-			}
-
-			var value = xhr.responseText;
-			var cStartIdx = value.indexOf("\/*");
-			var cEndIdx = value.lastIndexOf("*\/");
-			if(cStartIdx == -1 || cEndIdx == -1){
-				throw new Error("JSON was not comment filtered");
-			}
-			return _d.fromJson(value.substring(cStartIdx+2, cEndIdx));
-		},
-		javascript: function(xhr){ 
-			// summary: A contentHandler which evaluates the response data, expecting it to be valid JavaScript
-
-			// FIXME: try Moz and IE specific eval variants?
-			return _d.eval(xhr.responseText);
-		},
-		xml: function(xhr){
-			// summary: A contentHandler returning an XML Document parsed from the response data
-			var result = xhr.responseXML;
-						if(_d.isIE && (!result || !result.documentElement)){
-				//WARNING: this branch used by the xml handling in dojo.io.iframe,
-				//so be sure to test dojo.io.iframe if making changes below.
-				var ms = function(n){ return "MSXML" + n + ".DOMDocument"; }
-				var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)];
-				_d.some(dp, function(p){
-					try{
-						var dom = new ActiveXObject(p);
-						dom.async = false;
-						dom.loadXML(xhr.responseText);
-						result = dom;
-					}catch(e){ return false; }
-					return true;
-				});
-			}
-						return result; // DOMDocument
-		},
-		"json-comment-optional": function(xhr){
-			// summary: A contentHandler which checks the presence of comment-filtered JSON and 
-			//		alternates between the `json` and `json-comment-filtered` contentHandlers.
-			if(xhr.responseText && /^[^{\[]*\/\*/.test(xhr.responseText)){
-				return handlers["json-comment-filtered"](xhr);
-			}else{
-				return handlers["json"](xhr);
-			}
-		}
-	};
-
-	/*=====
-	dojo.__IoArgs = function(){
-		//	url: String
-		//		URL to server endpoint.
-		//	content: Object?
-		//		Contains properties with string values. These
-		//		properties will be serialized as name1=value2 and
-		//		passed in the request.
-		//	timeout: Integer?
-		//		Milliseconds to wait for the response. If this time
-		//		passes, the then error callbacks are called.
-		//	form: DOMNode?
-		//		DOM node for a form. Used to extract the form values
-		//		and send to the server.
-		//	preventCache: Boolean?
-		//		Default is false. If true, then a
-		//		"dojo.preventCache" parameter is sent in the request
-		//		with a value that changes with each request
-		//		(timestamp). Useful only with GET-type requests.
-		//	handleAs: String?
-		//		Acceptable values depend on the type of IO
-		//		transport (see specific IO calls for more information).
-		// 	rawBody: String?
-		// 		Sets the raw body for an HTTP request. If this is used, then the content
-		// 		property is ignored. This is mostly useful for HTTP methods that have
-		// 		a body to their requests, like PUT or POST. This property can be used instead
-		// 		of postData and putData for dojo.rawXhrPost and dojo.rawXhrPut respectively.
-		//	ioPublish: Boolean?
-		//		Set this explicitly to false to prevent publishing of topics related to
-		// 		IO operations. Otherwise, if djConfig.ioPublish is set to true, topics
-		// 		will be published via dojo.publish for different phases of an IO operation.
-		// 		See dojo.__IoPublish for a list of topics that are published.
-		//	load: Function?
-		//		This function will be
-		//		called on a successful HTTP response code.
-		//	error: Function?
-		//		This function will
-		//		be called when the request fails due to a network or server error, the url
-		//		is invalid, etc. It will also be called if the load or handle callback throws an
-		//		exception, unless djConfig.debugAtAllCosts is true.  This allows deployed applications
-		//		to continue to run even when a logic error happens in the callback, while making
-		//		it easier to troubleshoot while in debug mode.
-		//	handle: Function?
-		//		This function will
-		//		be called at the end of every request, whether or not an error occurs.
-		this.url = url;
-		this.content = content;
-		this.timeout = timeout;
-		this.form = form;
-		this.preventCache = preventCache;
-		this.handleAs = handleAs;
-		this.ioPublish = ioPublish;
-		this.load = function(response, ioArgs){
-			// ioArgs: dojo.__IoCallbackArgs
-			//		Provides additional information about the request.
-			// response: Object
-			//		The response in the format as defined with handleAs.
-		}
-		this.error = function(response, ioArgs){
-			// ioArgs: dojo.__IoCallbackArgs
-			//		Provides additional information about the request.
-			// response: Object
-			//		The response in the format as defined with handleAs.
-		}
-		this.handle = function(loadOrError, response, ioArgs){
-			// loadOrError: String
-			//		Provides a string that tells you whether this function
-			//		was called because of success (load) or failure (error).
-			// response: Object
-			//		The response in the format as defined with handleAs.
-			// ioArgs: dojo.__IoCallbackArgs
-			//		Provides additional information about the request.
-		}
-	}
-	=====*/
-
-	/*=====
-	dojo.__IoCallbackArgs = function(args, xhr, url, query, handleAs, id, canDelete, json){
-		//	args: Object
-		//		the original object argument to the IO call.
-		//	xhr: XMLHttpRequest
-		//		For XMLHttpRequest calls only, the
-		//		XMLHttpRequest object that was used for the
-		//		request.
-		//	url: String
-		//		The final URL used for the call. Many times it
-		//		will be different than the original args.url
-		//		value.
-		//	query: String
-		//		For non-GET requests, the
-		//		name1=value1&name2=value2 parameters sent up in
-		//		the request.
-		//	handleAs: String
-		//		The final indicator on how the response will be
-		//		handled.
-		//	id: String
-		//		For dojo.io.script calls only, the internal
-		//		script ID used for the request.
-		//	canDelete: Boolean
-		//		For dojo.io.script calls only, indicates
-		//		whether the script tag that represents the
-		//		request can be deleted after callbacks have
-		//		been called. Used internally to know when
-		//		cleanup can happen on JSONP-type requests.
-		//	json: Object
-		//		For dojo.io.script calls only: holds the JSON
-		//		response for JSONP-type requests. Used
-		//		internally to hold on to the JSON responses.
-		//		You should not need to access it directly --
-		//		the same object should be passed to the success
-		//		callbacks directly.
-		this.args = args;
-		this.xhr = xhr;
-		this.url = url;
-		this.query = query;
-		this.handleAs = handleAs;
-		this.id = id;
-		this.canDelete = canDelete;
-		this.json = json;
-	}
-	=====*/
-
-
-	/*=====
-	dojo.__IoPublish = function(){
-		// 	summary:
-		// 		This is a list of IO topics that can be published
-		// 		if djConfig.ioPublish is set to true. IO topics can be
-		// 		published for any Input/Output, network operation. So,
-		// 		dojo.xhr, dojo.io.script and dojo.io.iframe can all
-		// 		trigger these topics to be published.
-		//	start: String
-		//		"/dojo/io/start" is sent when there are no outstanding IO
-		// 		requests, and a new IO request is started. No arguments
-		// 		are passed with this topic.
-		//	send: String
-		//		"/dojo/io/send" is sent whenever a new IO request is started.
-		// 		It passes the dojo.Deferred for the request with the topic.
-		//	load: String
-		//		"/dojo/io/load" is sent whenever an IO request has loaded
-		// 		successfully. It passes the response and the dojo.Deferred
-		// 		for the request with the topic.
-		//	error: String
-		//		"/dojo/io/error" is sent whenever an IO request has errored.
-		// 		It passes the error and the dojo.Deferred
-		// 		for the request with the topic.
-		//	done: String
-		//		"/dojo/io/done" is sent whenever an IO request has completed,
-		// 		either by loading or by erroring. It passes the error and
-		// 		the dojo.Deferred for the request with the topic.
-		//	stop: String
-		//		"/dojo/io/stop" is sent when all outstanding IO requests have
-		// 		finished. No arguments are passed with this topic.
-		this.start = "/dojo/io/start";
-		this.send = "/dojo/io/send";
-		this.load = "/dojo/io/load";
-		this.error = "/dojo/io/error";
-		this.done = "/dojo/io/done";
-		this.stop = "/dojo/io/stop";
-	}
-	=====*/
-
-
-	dojo._ioSetArgs = function(/*dojo.__IoArgs*/args,
-			/*Function*/canceller,
-			/*Function*/okHandler,
-			/*Function*/errHandler){
-		//	summary: 
-		//		sets up the Deferred and ioArgs property on the Deferred so it
-		//		can be used in an io call.
-		//	args:
-		//		The args object passed into the public io call. Recognized properties on
-		//		the args object are:
-		//	canceller:
-		//		The canceller function used for the Deferred object. The function
-		//		will receive one argument, the Deferred object that is related to the
-		//		canceller.
-		//	okHandler:
-		//		The first OK callback to be registered with Deferred. It has the opportunity
-		//		to transform the OK response. It will receive one argument -- the Deferred
-		//		object returned from this function.
-		//	errHandler:
-		//		The first error callback to be registered with Deferred. It has the opportunity
-		//		to do cleanup on an error. It will receive two arguments: error (the 
-		//		Error object) and dfd, the Deferred object returned from this function.
-
-		var ioArgs = {args: args, url: args.url};
-
-		//Get values from form if requestd.
-		var formObject = null;
-		if(args.form){ 
-			var form = _d.byId(args.form);
-			//IE requires going through getAttributeNode instead of just getAttribute in some form cases, 
-			//so use it for all.  See #2844
-			var actnNode = form.getAttributeNode("action");
-			ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null); 
-			formObject = _d.formToObject(form);
-		}
-
-		// set up the query params
-		var miArgs = [{}];
-	
-		if(formObject){
-			// potentially over-ride url-provided params w/ form values
-			miArgs.push(formObject);
-		}
-		if(args.content){
-			// stuff in content over-rides what's set by form
-			miArgs.push(args.content);
-		}
-		if(args.preventCache){
-			miArgs.push({"dojo.preventCache": new Date().valueOf()});
-		}
-		ioArgs.query = _d.objectToQuery(_d.mixin.apply(null, miArgs));
-	
-		// .. and the real work of getting the deferred in order, etc.
-		ioArgs.handleAs = args.handleAs || "text";
-		var d = new _d.Deferred(canceller);
-		d.addCallbacks(okHandler, function(error){
-			return errHandler(error, d);
-		});
-
-		//Support specifying load, error and handle callback functions from the args.
-		//For those callbacks, the "this" object will be the args object.
-		//The callbacks will get the deferred result value as the
-		//first argument and the ioArgs object as the second argument.
-		var ld = args.load;
-		if(ld && _d.isFunction(ld)){
-			d.addCallback(function(value){
-				return ld.call(args, value, ioArgs);
-			});
-		}
-		var err = args.error;
-		if(err && _d.isFunction(err)){
-			d.addErrback(function(value){
-				return err.call(args, value, ioArgs);
-			});
-		}
-		var handle = args.handle;
-		if(handle && _d.isFunction(handle)){
-			d.addBoth(function(value){
-				return handle.call(args, value, ioArgs);
-			});
-		}
-
-		//Plug in topic publishing, if dojo.publish is loaded.
-		if(cfg.ioPublish && _d.publish && ioArgs.args.ioPublish !== false){
-			d.addCallbacks(
-				function(res){
-					_d.publish("/dojo/io/load", [d, res]);
-					return res;
-				},
-				function(res){
-					_d.publish("/dojo/io/error", [d, res]);
-					return res;
-				}
-			);
-			d.addBoth(function(res){
-				_d.publish("/dojo/io/done", [d, res]);
-				return res;
-			});
-		}
-
-		d.ioArgs = ioArgs;
-	
-		// FIXME: need to wire up the xhr object's abort method to something
-		// analagous in the Deferred
-		return d;
-	}
-
-	var _deferredCancel = function(/*Deferred*/dfd){
-		// summary: canceller function for dojo._ioSetArgs call.
-		
-		dfd.canceled = true;
-		var xhr = dfd.ioArgs.xhr;
-		var _at = typeof xhr.abort;
-		if(_at == "function" || _at == "object" || _at == "unknown"){
-			xhr.abort();
-		}
-		var err = dfd.ioArgs.error;
-		if(!err){
-			err = new Error("xhr cancelled");
-			err.dojoType="cancel";
-		}
-		return err;
-	}
-	var _deferredOk = function(/*Deferred*/dfd){
-		// summary: okHandler function for dojo._ioSetArgs call.
-
-		var ret = handlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);
-		return ret === undefined ? null : ret;
-	}
-	var _deferError = function(/*Error*/error, /*Deferred*/dfd){
-		// summary: errHandler function for dojo._ioSetArgs call.
-
-		if(!dfd.ioArgs.args.failOk){
-			console.error(error);
-		}
-		return error;
-	}
-
-	// avoid setting a timer per request. It degrades performance on IE
-	// something fierece if we don't use unified loops.
-	var _inFlightIntvl = null;
-	var _inFlight = [];
-	
-	
-	//Use a separate count for knowing if we are starting/stopping io calls.
-	//Cannot use _inFlight.length since it can change at a different time than
-	//when we want to do this kind of test. We only want to decrement the count
-	//after a callback/errback has finished, since the callback/errback should be
-	//considered as part of finishing a request.
-	var _pubCount = 0;
-	var _checkPubCount = function(dfd){
-		if(_pubCount <= 0){
-			_pubCount = 0;
-			if(cfg.ioPublish && _d.publish && (!dfd || dfd && dfd.ioArgs.args.ioPublish !== false)){
-				_d.publish("/dojo/io/stop");
-			}
-		}
-	};
-
-	var _watchInFlight = function(){
-		//summary: 
-		//		internal method that checks each inflight XMLHttpRequest to see
-		//		if it has completed or if the timeout situation applies.
-		
-		var now = (new Date()).getTime();
-		// make sure sync calls stay thread safe, if this callback is called
-		// during a sync call and this results in another sync call before the
-		// first sync call ends the browser hangs
-		if(!_d._blockAsync){
-			// we need manual loop because we often modify _inFlight (and therefore 'i') while iterating
-			// note: the second clause is an assigment on purpose, lint may complain
-			for(var i = 0, tif; i < _inFlight.length && (tif = _inFlight[i]); i++){
-				var dfd = tif.dfd;
-				var func = function(){
-					if(!dfd || dfd.canceled || !tif.validCheck(dfd)){
-						_inFlight.splice(i--, 1); 
-						_pubCount -= 1;
-					}else if(tif.ioCheck(dfd)){
-						_inFlight.splice(i--, 1);
-						tif.resHandle(dfd);
-						_pubCount -= 1;
-					}else if(dfd.startTime){
-						//did we timeout?
-						if(dfd.startTime + (dfd.ioArgs.args.timeout || 0) < now){
-							_inFlight.splice(i--, 1);
-							var err = new Error("timeout exceeded");
-							err.dojoType = "timeout";
-							dfd.errback(err);
-							//Cancel the request so the io module can do appropriate cleanup.
-							dfd.cancel();
-							_pubCount -= 1;
-						}
-					}
-				};
-				if(dojo.config.debugAtAllCosts){
-					func.call(this);
-				}else{
-					try{
-						func.call(this);
-					}catch(e){
-						dfd.errback(e);
-					}
-				}
-			}
-		}
-
-		_checkPubCount(dfd);
-
-		if(!_inFlight.length){
-			clearInterval(_inFlightIntvl);
-			_inFlightIntvl = null;
-			return;
-		}
-	}
-
-	dojo._ioCancelAll = function(){
-		//summary: Cancels all pending IO requests, regardless of IO type
-		//(xhr, script, iframe).
-		try{
-			_d.forEach(_inFlight, function(i){
-				try{
-					i.dfd.cancel();
-				}catch(e){/*squelch*/}
-			});
-		}catch(e){/*squelch*/}
-	}
-
-	//Automatically call cancel all io calls on unload
-	//in IE for trac issue #2357.
-		if(_d.isIE){
-		_d.addOnWindowUnload(_d._ioCancelAll);
-	}
-	
-	_d._ioNotifyStart = function(/*Deferred*/dfd){
-		// summary:
-		// 		If dojo.publish is available, publish topics
-		// 		about the start of a request queue and/or the
-		// 		the beginning of request.
-		// description:
-		// 		Used by IO transports. An IO transport should
-		// 		call this method before making the network connection.
-		if(cfg.ioPublish && _d.publish && dfd.ioArgs.args.ioPublish !== false){
-			if(!_pubCount){
-				_d.publish("/dojo/io/start");
-			}
-			_pubCount += 1;
-			_d.publish("/dojo/io/send", [dfd]);
-		}
-	}
-
-	_d._ioWatch = function(dfd, validCheck, ioCheck, resHandle){
-		// summary: 
-		//		Watches the io request represented by dfd to see if it completes.
-		// dfd: Deferred
-		//		The Deferred object to watch.
-		// validCheck: Function
-		//		Function used to check if the IO request is still valid. Gets the dfd
-		//		object as its only argument.
-		// ioCheck: Function
-		//		Function used to check if basic IO call worked. Gets the dfd
-		//		object as its only argument.
-		// resHandle: Function
-		//		Function used to process response. Gets the dfd
-		//		object as its only argument.
-		var args = dfd.ioArgs.args;
-		if(args.timeout){
-			dfd.startTime = (new Date()).getTime();
-		}
-		
-		_inFlight.push({dfd: dfd, validCheck: validCheck, ioCheck: ioCheck, resHandle: resHandle});
-		if(!_inFlightIntvl){
-			_inFlightIntvl = setInterval(_watchInFlight, 50);
-		}
-		// handle sync requests
-		//A weakness: async calls in flight
-		//could have their handlers called as part of the
-		//_watchInFlight call, before the sync's callbacks
-		// are called.
-		if(args.sync){
-			_watchInFlight();
-		}
-	}
-
-	var _defaultContentType = "application/x-www-form-urlencoded";
-
-	var _validCheck = function(/*Deferred*/dfd){
-		return dfd.ioArgs.xhr.readyState; //boolean
-	}
-	var _ioCheck = function(/*Deferred*/dfd){
-		return 4 == dfd.ioArgs.xhr.readyState; //boolean
-	}
-	var _resHandle = function(/*Deferred*/dfd){
-		var xhr = dfd.ioArgs.xhr;
-		if(_d._isDocumentOk(xhr)){
-			dfd.callback(dfd);
-		}else{
-			var err = new Error("Unable to load " + dfd.ioArgs.url + " status:" + xhr.status);
-			err.status = xhr.status;
-			err.responseText = xhr.responseText;
-			dfd.errback(err);
-		}
-	}
-
-	dojo._ioAddQueryToUrl = function(/*dojo.__IoCallbackArgs*/ioArgs){
-		//summary: Adds query params discovered by the io deferred construction to the URL.
-		//Only use this for operations which are fundamentally GET-type operations.
-		if(ioArgs.query.length){
-			ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query;
-			ioArgs.query = null;
-		}		
-	}
-
-	/*=====
-	dojo.declare("dojo.__XhrArgs", dojo.__IoArgs, {
-		constructor: function(){
-			//	summary:
-			//		In addition to the properties listed for the dojo._IoArgs type,
-			//		the following properties are allowed for dojo.xhr* methods.
-			//	handleAs: String?
-			//		Acceptable values are: text (default), json, json-comment-optional,
-			//		json-comment-filtered, javascript, xml. See `dojo.contentHandlers`
-			//	sync: Boolean?
-			//		false is default. Indicates whether the request should
-			//		be a synchronous (blocking) request.
-			//	headers: Object?
-			//		Additional HTTP headers to send in the request.
-			//	failOk: Boolean?
-			//		false is default. Indicates whether a request should be
-			//		allowed to fail (and therefore no console error message in
-			//		the event of a failure)
-			this.handleAs = handleAs;
-			this.sync = sync;
-			this.headers = headers;
-			this.failOk = failOk;
-		}
-	});
-	=====*/
-
-	dojo.xhr = function(/*String*/ method, /*dojo.__XhrArgs*/ args, /*Boolean?*/ hasBody){
-		//	summary:
-		//		Sends an HTTP request with the given method.
-		//	description:
-		//		Sends an HTTP request with the given method.
-		//		See also dojo.xhrGet(), xhrPost(), xhrPut() and dojo.xhrDelete() for shortcuts
-		//		for those HTTP methods. There are also methods for "raw" PUT and POST methods
-		//		via dojo.rawXhrPut() and dojo.rawXhrPost() respectively.
-		//	method:
-		//		HTTP method to be used, such as GET, POST, PUT, DELETE.  Should be uppercase.
-		//	hasBody:
-		//		If the request has an HTTP body, then pass true for hasBody.
-
-		//Make the Deferred object for this xhr request.
-		var dfd = _d._ioSetArgs(args, _deferredCancel, _deferredOk, _deferError);
-		var ioArgs = dfd.ioArgs;
-
-		//Pass the args to _xhrObj, to allow alternate XHR calls based specific calls, like
-		//the one used for iframe proxies.
-		var xhr = ioArgs.xhr = _d._xhrObj(ioArgs.args);
-		//If XHR factory fails, cancel the deferred.
-		if(!xhr){
-			dfd.cancel();
-			return dfd;
-		}
-
-		//Allow for specifying the HTTP body completely.
-		if("postData" in args){
-			ioArgs.query = args.postData;
-		}else if("putData" in args){
-			ioArgs.query = args.putData;
-		}else if("rawBody" in args){
-			ioArgs.query = args.rawBody;
-		}else if((arguments.length > 2 && !hasBody) || "POST|PUT".indexOf(method.toUpperCase()) == -1){
-			//Check for hasBody being passed. If no hasBody,
-			//then only append query string if not a POST or PUT request.
-			_d._ioAddQueryToUrl(ioArgs);
-		}
-
-		// IE 6 is a steaming pile. It won't let you call apply() on the native function (xhr.open).
-		// workaround for IE6's apply() "issues"
-		xhr.open(method, ioArgs.url, args.sync !== true, args.user || undefined, args.password || undefined);
-		if(args.headers){
-			for(var hdr in args.headers){
-				if(hdr.toLowerCase() === "content-type" && !args.contentType){
-					args.contentType = args.headers[hdr];
-				}else if(args.headers[hdr]){
-					//Only add header if it has a value. This allows for instnace, skipping
-					//insertion of X-Requested-With by specifying empty value.
-					xhr.setRequestHeader(hdr, args.headers[hdr]);
-				}
-			}
-		}
-		// FIXME: is this appropriate for all content types?
-		xhr.setRequestHeader("Content-Type", args.contentType || _defaultContentType);
-		if(!args.headers || !("X-Requested-With" in args.headers)){
-			xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
-		}
-		// FIXME: set other headers here!
-		_d._ioNotifyStart(dfd);
-		if(dojo.config.debugAtAllCosts){
-			xhr.send(ioArgs.query);
-		}else{
-			try{
-				xhr.send(ioArgs.query);
-			}catch(e){
-				ioArgs.error = e;
-				dfd.cancel();
-			}
-		}
-		_d._ioWatch(dfd, _validCheck, _ioCheck, _resHandle);
-		xhr = null;
-		return dfd; // dojo.Deferred
-	}
-
-	dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){
-		//	summary: 
-		//		Sends an HTTP GET request to the server.
-		return _d.xhr("GET", args); // dojo.Deferred
-	}
-
-	dojo.rawXhrPost = dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){
-		//	summary:
-		//		Sends an HTTP POST request to the server. In addtion to the properties
-		//		listed for the dojo.__XhrArgs type, the following property is allowed:
-		//	postData:
-		//		String. Send raw data in the body of the POST request.
-		return _d.xhr("POST", args, true); // dojo.Deferred
-	}
-
-	dojo.rawXhrPut = dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){
-		//	summary:
-		//		Sends an HTTP PUT request to the server. In addtion to the properties
-		//		listed for the dojo.__XhrArgs type, the following property is allowed:
-		//	putData:
-		//		String. Send raw data in the body of the PUT request.
-		return _d.xhr("PUT", args, true); // dojo.Deferred
-	}
-
-	dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){
-		//	summary:
-		//		Sends an HTTP DELETE request to the server.
-		return _d.xhr("DELETE", args); //dojo.Deferred
-	}
-
-	/*
-	dojo.wrapForm = function(formNode){
-		//summary:
-		//		A replacement for FormBind, but not implemented yet.
-
-		// FIXME: need to think harder about what extensions to this we might
-		// want. What should we allow folks to do w/ this? What events to
-		// set/send?
-		throw new Error("dojo.wrapForm not yet implemented");
-	}
-	*/
-})();
-
-}
-
-if(!dojo._hasResource["dojo._base.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.fx"] = true;
-dojo.provide("dojo._base.fx");
-
-
-
-
-
-/*
-	Animation loosely package based on Dan Pupius' work, contributed under CLA: 
-		http://pupius.co.uk/js/Toolkit.Drawing.js
-*/
-(function(){ 
-	var d = dojo;
-	var _mixin = d._mixin;
-	
-	dojo._Line = function(/*int*/ start, /*int*/ end){
-		//	summary:
-		//		dojo._Line is the object used to generate values from a start value
-		//		to an end value
-		//	start: int
-		//		Beginning value for range
-		//	end: int
-		//		Ending value for range
-		this.start = start;
-		this.end = end;
-	};
-	
-	dojo._Line.prototype.getValue = function(/*float*/ n){
-		//	summary: Returns the point on the line
-		//	n: a floating point number greater than 0 and less than 1
-		return ((this.end - this.start) * n) + this.start; // Decimal
-	};
-	
-	dojo.Animation = function(args){
-		//	summary:
-		//		A generic animation class that fires callbacks into its handlers
-		//		object at various states. 
-		//	description:
-		//		A generic animation class that fires callbacks into its handlers
-		//		object at various states. Nearly all dojo animation functions
-		//		return an instance of this method, usually without calling the
-		//		.play() method beforehand. Therefore, you will likely need to
-		//		call .play() on instances of `dojo.Animation` when one is
-		//		returned.
-		// args: Object
-		//		The 'magic argument', mixing all the properties into this
-		//		animation instance. 
-		
-		_mixin(this, args);
-		if(d.isArray(this.curve)){
-			this.curve = new d._Line(this.curve[0], this.curve[1]);
-		}
-		
-	};
-	
-	// Alias to drop come 2.0:
-	d._Animation = d.Animation;
-	
-	d.extend(dojo.Animation, {
-		// duration: Integer
-		//		The time in milliseonds the animation will take to run
-		duration: 350,
-	
-	/*=====
-		// curve: dojo._Line|Array
-		//		A two element array of start and end values, or a `dojo._Line` instance to be
-		//		used in the Animation. 
-		curve: null,
-	
-		// easing: Function?
-		//		A Function to adjust the acceleration (or deceleration) of the progress 
-		//		across a dojo._Line
-		easing: null,
-	=====*/
-	
-		// repeat: Integer?
-		//		The number of times to loop the animation
-		repeat: 0,
-	
-		// rate: Integer?
-		//		the time in milliseconds to wait before advancing to next frame 
-		//		(used as a fps timer: 1000/rate = fps)
-		rate: 20 /* 50 fps */,
-	
-	/*===== 
-		// delay: Integer?
-		//		The time in milliseconds to wait before starting animation after it 
-		//		has been .play()'ed
-		delay: null,
-	
-		// beforeBegin: Event?
-		//		Synthetic event fired before a dojo.Animation begins playing (synchronous)
-		beforeBegin: null,
-	
-		// onBegin: Event?
-		//		Synthetic event fired as a dojo.Animation begins playing (useful?)
-		onBegin: null,
-	
-		// onAnimate: Event?
-		//		Synthetic event fired at each interval of a `dojo.Animation`
-		onAnimate: null,
-	
-		// onEnd: Event?
-		//		Synthetic event fired after the final frame of a `dojo.Animation`
-		onEnd: null,
-	
-		// onPlay: Event?
-		//		Synthetic event fired any time a `dojo.Animation` is play()'ed
-		onPlay: null,
-	
-		// onPause: Event?
-		//		Synthetic event fired when a `dojo.Animation` is paused
-		onPause: null,
-	
-		// onStop: Event
-		//		Synthetic event fires when a `dojo.Animation` is stopped
-		onStop: null,
-	
-	=====*/
-	
-		_percent: 0,
-		_startRepeatCount: 0,
-
-		_getStep: function(){
-			var _p = this._percent,
-				_e = this.easing
-			;
-			return _e ? _e(_p) : _p;
-		},
-		_fire: function(/*Event*/ evt, /*Array?*/ args){
-			//	summary:
-			//		Convenience function.  Fire event "evt" and pass it the
-			//		arguments specified in "args".
-			//	description:
-			//		Convenience function.  Fire event "evt" and pass it the
-			//		arguments specified in "args".
-			//		Fires the callback in the scope of the `dojo.Animation` 
-			//		instance.
-			//	evt:
-			//		The event to fire.
-			//	args:
-			//		The arguments to pass to the event.
-			var a = args||[];
-			if(this[evt]){
-				if(d.config.debugAtAllCosts){
-					this[evt].apply(this, a);
-				}else{
-					try{
-						this[evt].apply(this, a);
-					}catch(e){
-						// squelch and log because we shouldn't allow exceptions in
-						// synthetic event handlers to cause the internal timer to run
-						// amuck, potentially pegging the CPU. I'm not a fan of this
-						// squelch, but hopefully logging will make it clear what's
-						// going on
-						console.error("exception in animation handler for:", evt);
-						console.error(e);
-					}
-				}
-			}
-			return this; // dojo.Animation
-		},
-
-		play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
-			// summary:
-			//		Start the animation.
-			// delay:
-			//		How many milliseconds to delay before starting.
-			// gotoStart:
-			//		If true, starts the animation from the beginning; otherwise,
-			//		starts it from its current position.
-			// returns: dojo.Animation
-			//		The instance to allow chaining.
-
-			var _t = this;
-			if(_t._delayTimer){ _t._clearTimer(); }
-			if(gotoStart){
-				_t._stopTimer();
-				_t._active = _t._paused = false;
-				_t._percent = 0;
-			}else if(_t._active && !_t._paused){
-				return _t;
-			}
-	
-			_t._fire("beforeBegin", [_t.node]);
-	
-			var de = delay || _t.delay,
-				_p = dojo.hitch(_t, "_play", gotoStart);
-				
-			if(de > 0){
-				_t._delayTimer = setTimeout(_p, de);
-				return _t;
-			}
-			_p();
-			return _t;
-		},
-	
-		_play: function(gotoStart){
-			var _t = this;
-			if(_t._delayTimer){ _t._clearTimer(); }
-			_t._startTime = new Date().valueOf();
-			if(_t._paused){
-				_t._startTime -= _t.duration * _t._percent;
-			}
-			_t._endTime = _t._startTime + _t.duration;
-	
-			_t._active = true;
-			_t._paused = false;
-			var value = _t.curve.getValue(_t._getStep());
-			if(!_t._percent){
-				if(!_t._startRepeatCount){
-					_t._startRepeatCount = _t.repeat;
-				}
-				_t._fire("onBegin", [value]);
-			}
-	
-			_t._fire("onPlay", [value]);
-	
-			_t._cycle();
-			return _t; // dojo.Animation
-		},
-	
-		pause: function(){
-			// summary: Pauses a running animation.
-			var _t = this;
-			if(_t._delayTimer){ _t._clearTimer(); }
-			_t._stopTimer();
-			if(!_t._active){ return _t; /*dojo.Animation*/ }
-			_t._paused = true;
-			_t._fire("onPause", [_t.curve.getValue(_t._getStep())]);
-			return _t; // dojo.Animation
-		},
-	
-		gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay){
-			//	summary:
-			//		Sets the progress of the animation.
-			//	percent:
-			//		A percentage in decimal notation (between and including 0.0 and 1.0).
-			//	andPlay:
-			//		If true, play the animation after setting the progress.
-			var _t = this;
-			_t._stopTimer();
-			_t._active = _t._paused = true;
-			_t._percent = percent;
-			if(andPlay){ _t.play(); }
-			return _t; // dojo.Animation
-		},
-	
-		stop: function(/*boolean?*/ gotoEnd){
-			// summary: Stops a running animation.
-			// gotoEnd: If true, the animation will end.
-			var _t = this;
-			if(_t._delayTimer){ _t._clearTimer(); }
-			if(!_t._timer){ return _t; /* dojo.Animation */ }
-			_t._stopTimer();
-			if(gotoEnd){
-				_t._percent = 1;
-			}
-			_t._fire("onStop", [_t.curve.getValue(_t._getStep())]);
-			_t._active = _t._paused = false;
-			return _t; // dojo.Animation
-		},
-	
-		status: function(){
-			// summary: 
-			//		Returns a string token representation of the status of
-			//		the animation, one of: "paused", "playing", "stopped"
-			if(this._active){
-				return this._paused ? "paused" : "playing"; // String
-			}
-			return "stopped"; // String
-		},
-	
-		_cycle: function(){
-			var _t = this;
-			if(_t._active){
-				var curr = new Date().valueOf();
-				var step = (curr - _t._startTime) / (_t._endTime - _t._startTime);
-	
-				if(step >= 1){
-					step = 1;
-				}
-				_t._percent = step;
-	
-				// Perform easing
-				if(_t.easing){
-					step = _t.easing(step);
-				}
-	
-				_t._fire("onAnimate", [_t.curve.getValue(step)]);
-	
-				if(_t._percent < 1){
-					_t._startTimer();
-				}else{
-					_t._active = false;
-	
-					if(_t.repeat > 0){
-						_t.repeat--;
-						_t.play(null, true);
-					}else if(_t.repeat == -1){
-						_t.play(null, true);
-					}else{
-						if(_t._startRepeatCount){
-							_t.repeat = _t._startRepeatCount;
-							_t._startRepeatCount = 0;
-						}
-					}
-					_t._percent = 0;
-					_t._fire("onEnd", [_t.node]);
-					!_t.repeat && _t._stopTimer();
-				}
-			}
-			return _t; // dojo.Animation
-		},
-		
-		_clearTimer: function(){
-			// summary: Clear the play delay timer
-			clearTimeout(this._delayTimer);
-			delete this._delayTimer;
-		}
-		
-	});
-
-	// the local timer, stubbed into all Animation instances
-	var ctr = 0,
-		_globalTimerList = [],
-		timer = null,
-		runner = {
-			run: function(){}
-		};
-
-	d.extend(d.Animation, {
-
-		_startTimer: function(){
-			if(!this._timer){
-				this._timer = d.connect(runner, "run", this, "_cycle");
-				ctr++;
-			}
-			if(!timer){
-				timer = setInterval(d.hitch(runner, "run"), this.rate);
-			}
-		},
-
-		_stopTimer: function(){
-			if(this._timer){
-				d.disconnect(this._timer);
-				this._timer = null;
-				ctr--;
-			}
-			if(ctr <= 0){
-				clearInterval(timer);
-				timer = null;
-				ctr = 0;
-			}
-		}
-
-	});
-
-	var _makeFadeable = 
-				d.isIE ? function(node){
-			// only set the zoom if the "tickle" value would be the same as the
-			// default
-			var ns = node.style;
-			// don't set the width to auto if it didn't already cascade that way.
-			// We don't want to f anyones designs
-			if(!ns.width.length && d.style(node, "width") == "auto"){
-				ns.width = "auto";
-			}
-		} : 
-				function(){};
-
-	dojo._fade = function(/*Object*/ args){
-		//	summary: 
-		//		Returns an animation that will fade the node defined by
-		//		args.node from the start to end values passed (args.start
-		//		args.end) (end is mandatory, start is optional)
-
-		args.node = d.byId(args.node);
-		var fArgs = _mixin({ properties: {} }, args),
-		 	props = (fArgs.properties.opacity = {});
-		
-		props.start = !("start" in fArgs) ?
-			function(){ 
-				return +d.style(fArgs.node, "opacity")||0; 
-			} : fArgs.start;
-		props.end = fArgs.end;
-
-		var anim = d.animateProperty(fArgs);
-		d.connect(anim, "beforeBegin", d.partial(_makeFadeable, fArgs.node));
-
-		return anim; // dojo.Animation
-	};
-
-	/*=====
-	dojo.__FadeArgs = function(node, duration, easing){
-		// 	node: DOMNode|String
-		//		The node referenced in the animation
-		//	duration: Integer?
-		//		Duration of the animation in milliseconds.
-		//	easing: Function?
-		//		An easing function.
-		this.node = node;
-		this.duration = duration;
-		this.easing = easing;
-	}
-	=====*/
-
-	dojo.fadeIn = function(/*dojo.__FadeArgs*/ args){
-		// summary: 
-		//		Returns an animation that will fade node defined in 'args' from
-		//		its current opacity to fully opaque.
-		return d._fade(_mixin({ end: 1 }, args)); // dojo.Animation
-	};
-
-	dojo.fadeOut = function(/*dojo.__FadeArgs*/  args){
-		// summary: 
-		//		Returns an animation that will fade node defined in 'args'
-		//		from its current opacity to fully transparent.
-		return d._fade(_mixin({ end: 0 }, args)); // dojo.Animation
-	};
-
-	dojo._defaultEasing = function(/*Decimal?*/ n){
-		// summary: The default easing function for dojo.Animation(s)
-		return 0.5 + ((Math.sin((n + 1.5) * Math.PI)) / 2);
-	};
-
-	var PropLine = function(properties){
-		// PropLine is an internal class which is used to model the values of
-		// an a group of CSS properties across an animation lifecycle. In
-		// particular, the "getValue" function handles getting interpolated
-		// values between start and end for a particular CSS value.
-		this._properties = properties;
-		for(var p in properties){
-			var prop = properties[p];
-			if(prop.start instanceof d.Color){
-				// create a reusable temp color object to keep intermediate results
-				prop.tempColor = new d.Color();
-			}
-		}
-	};
-
-	PropLine.prototype.getValue = function(r){
-		var ret = {};
-		for(var p in this._properties){
-			var prop = this._properties[p],
-				start = prop.start;
-			if(start instanceof d.Color){
-				ret[p] = d.blendColors(start, prop.end, r, prop.tempColor).toCss();
-			}else if(!d.isArray(start)){
-				ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units || "px" : 0);
-			}
-		}
-		return ret;
-	};
-
-	/*=====
-	dojo.declare("dojo.__AnimArgs", [dojo.__FadeArgs], {
-		// Properties: Object?
-		//	A hash map of style properties to Objects describing the transition,
-		//	such as the properties of dojo._Line with an additional 'units' property
-		properties: {}
-		
-		//TODOC: add event callbacks
-	});
-	=====*/
-
-	dojo.animateProperty = function(/*dojo.__AnimArgs*/ args){
-		// summary: 
-		//		Returns an animation that will transition the properties of
-		//		node defined in `args` depending how they are defined in
-		//		`args.properties`
-		//
-		// description:
-		//		`dojo.animateProperty` is the foundation of most `dojo.fx`
-		//		animations. It takes an object of "properties" corresponding to
-		//		style properties, and animates them in parallel over a set
-		//		duration.
-		//	
-		// example:
-		//		A simple animation that changes the width of the specified node.
-		//	|	dojo.animateProperty({ 
-		//	|		node: "nodeId",
-		//	|		properties: { width: 400 },
-		//	|	}).play();
-		//		Dojo figures out the start value for the width and converts the
-		//		integer specified for the width to the more expressive but
-		//		verbose form `{ width: { end: '400', units: 'px' } }` which you
-		//		can also specify directly. Defaults to 'px' if ommitted.
-		//
-		// example:
-		//		Animate width, height, and padding over 2 seconds... the
-		//		pedantic way:
-		//	|	dojo.animateProperty({ node: node, duration:2000,
-		//	|		properties: {
-		//	|			width: { start: '200', end: '400', units:"px" },
-		//	|			height: { start:'200', end: '400', units:"px" },
-		//	|			paddingTop: { start:'5', end:'50', units:"px" } 
-		//	|		}
-		//	|	}).play();
-		//		Note 'paddingTop' is used over 'padding-top'. Multi-name CSS properties
-		//		are written using "mixed case", as the hyphen is illegal as an object key.
-		//		
-		// example:
-		//		Plug in a different easing function and register a callback for
-		//		when the animation ends. Easing functions accept values between
-		//		zero and one and return a value on that basis. In this case, an
-		//		exponential-in curve.
-		//	|	dojo.animateProperty({ 
-		//	|		node: "nodeId",
-		//	|		// dojo figures out the start value
-		//	|		properties: { width: { end: 400 } },
-		//	|		easing: function(n){
-		//	|			return (n==0) ? 0 : Math.pow(2, 10 * (n - 1));
-		//	|		},
-		//	|		onEnd: function(node){
-		//	|			// called when the animation finishes. The animation
-		//	|			// target is passed to this function
-		//	|		}
-		//	|	}).play(500); // delay playing half a second
-		//
-		// example:
-		//		Like all `dojo.Animation`s, animateProperty returns a handle to the
-		//		Animation instance, which fires the events common to Dojo FX. Use `dojo.connect`
-		//		to access these events outside of the Animation definiton:
-		//	|	var anim = dojo.animateProperty({
-		//	|		node:"someId",
-		//	|		properties:{
-		//	|			width:400, height:500
-		//	|		}
-		//	|	});
-		//	|	dojo.connect(anim,"onEnd", function(){
-		//	|		console.log("animation ended");
-		//	|	});
-		//	|	// play the animation now:
-		//	|	anim.play();
-		//
-		// example:
-		//		Each property can be a function whose return value is substituted along.
-		//		Additionally, each measurement (eg: start, end) can be a function. The node
-		//		reference is passed direcly to callbacks.
-		//	|	dojo.animateProperty({
-		//	|		node:"mine",
-		//	|		properties:{
-		//	|			height:function(node){
-		//	|				// shrink this node by 50%
-		//	|				return dojo.position(node).h / 2
-		//	|			},
-		//	|			width:{
-		//	|				start:function(node){ return 100; },
-		//	|				end:function(node){ return 200; }	
-		//	|			}
-		//	|		}
-		//	|	}).play();
-		//
-
-		var n = args.node = d.byId(args.node);
-		if(!args.easing){ args.easing = d._defaultEasing; }
-
-		var anim = new d.Animation(args);
-		d.connect(anim, "beforeBegin", anim, function(){
-			var pm = {};
-			for(var p in this.properties){
-				// Make shallow copy of properties into pm because we overwrite
-				// some values below. In particular if start/end are functions
-				// we don't want to overwrite them or the functions won't be
-				// called if the animation is reused.
-				if(p == "width" || p == "height"){
-					this.node.display = "block";
-				}
-				var prop = this.properties[p];
-				if(d.isFunction(prop)){
-					prop = prop(n);
-				}
-				prop = pm[p] = _mixin({}, (d.isObject(prop) ? prop: { end: prop }));
-
-				if(d.isFunction(prop.start)){
-					prop.start = prop.start(n);
-				}
-				if(d.isFunction(prop.end)){
-					prop.end = prop.end(n);
-				}
-				var isColor = (p.toLowerCase().indexOf("color") >= 0);
-				function getStyle(node, p){
-					// dojo.style(node, "height") can return "auto" or "" on IE; this is more reliable:
-					var v = { height: node.offsetHeight, width: node.offsetWidth }[p];
-					if(v !== undefined){ return v; }
-					v = d.style(node, p);
-					return (p == "opacity") ? +v : (isColor ? v : parseFloat(v));
-				}
-				if(!("end" in prop)){
-					prop.end = getStyle(n, p);
-				}else if(!("start" in prop)){
-					prop.start = getStyle(n, p);
-				}
-
-				if(isColor){
-					prop.start = new d.Color(prop.start);
-					prop.end = new d.Color(prop.end);
-				}else{
-					prop.start = (p == "opacity") ? +prop.start : parseFloat(prop.start);
-				}
-			}
-			this.curve = new PropLine(pm);
-		});
-		d.connect(anim, "onAnimate", d.hitch(d, "style", anim.node));
-		return anim; // dojo.Animation
-	};
-
-	dojo.anim = function(	/*DOMNode|String*/ 	node, 
-							/*Object*/ 			properties, 
-							/*Integer?*/		duration, 
-							/*Function?*/		easing, 
-							/*Function?*/		onEnd,
-							/*Integer?*/		delay){
-		//	summary:
-		//		A simpler interface to `dojo.animateProperty()`, also returns
-		//		an instance of `dojo.Animation` but begins the animation
-		//		immediately, unlike nearly every other Dojo animation API.
-		//	description:
-		//		`dojo.anim` is a simpler (but somewhat less powerful) version
-		//		of `dojo.animateProperty`.  It uses defaults for many basic properties
-		//		and allows for positional parameters to be used in place of the
-		//		packed "property bag" which is used for other Dojo animation
-		//		methods.
-		//
-		//		The `dojo.Animation` object returned from `dojo.anim` will be
-		//		already playing when it is returned from this function, so
-		//		calling play() on it again is (usually) a no-op.
-		//	node:
-		//		a DOM node or the id of a node to animate CSS properties on
-		//	duration:
-		//		The number of milliseconds over which the animation
-		//		should run. Defaults to the global animation default duration
-		//		(350ms).
-		//	easing:
-		//		An easing function over which to calculate acceleration
-		//		and deceleration of the animation through its duration.
-		//		A default easing algorithm is provided, but you may
-		//		plug in any you wish. A large selection of easing algorithms
-		//		are available in `dojo.fx.easing`.
-		//	onEnd:
-		//		A function to be called when the animation finishes
-		//		running.
-		//	delay:
-		//		The number of milliseconds to delay beginning the
-		//		animation by. The default is 0.
-		//	example:
-		//		Fade out a node
-		//	|	dojo.anim("id", { opacity: 0 });
-		//	example:
-		//		Fade out a node over a full second
-		//	|	dojo.anim("id", { opacity: 0 }, 1000);
-		return d.animateProperty({ // dojo.Animation
-			node: node,
-			duration: duration || d.Animation.prototype.duration,
-			properties: properties,
-			easing: easing,
-			onEnd: onEnd 
-		}).play(delay || 0);
-	};
-})();
-
-}
-
-if(!dojo._hasResource["dojo._base.browser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo._base.browser"] = true;
-dojo.provide("dojo._base.browser");
-
-
-
-
-
-
-
-
-
-
-//Need this to be the last code segment in base, so do not place any
-//dojo.requireIf calls in this file. Otherwise, due to how the build system
-//puts all requireIf dependencies after the current file, the require calls
-//could be called before all of base is defined.
-dojo.forEach(dojo.config.require, function(i){
-	dojo["require"](i);
-});
-
-}
-
-	//INSERT dojo.i18n._preloadLocalizations HERE
-
-	if(dojo.config.afterOnLoad && dojo.isBrowser){
-		//Dojo is being added to the page after page load, so just trigger
-		//the init sequence after a timeout. Using a timeout so the rest of this
-		//script gets evaluated properly. This work needs to happen after the
-		//dojo.config.require work done in dojo._base.
-		window.setTimeout(dojo._loadInit, 1000);
-	}
-
-})();
-
diff --git a/dojo/fx.js b/dojo/fx.js
index adf889f..9f0625e 100644
--- a/dojo/fx.js
+++ b/dojo/fx.js
@@ -1,252 +1,393 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.fx"]){
-dojo._hasResource["dojo.fx"]=true;
 dojo.provide("dojo.fx");
-dojo.require("dojo.fx.Toggler");
-(function(){
-var d=dojo,_1={_fire:function(_2,_3){
-if(this[_2]){
-this[_2].apply(this,_3||[]);
-}
-return this;
-}};
-var _4=function(_5){
-this._index=-1;
-this._animations=_5||[];
-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(_4,{_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{
-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(_6,_7){
-if(!this._current){
-this._current=this._animations[this._index=0];
-}
-if(!_7&&this._current.status()=="playing"){
-return this;
-}
-var _8=d.connect(this._current,"beforeBegin",this,function(){
-this._fire("beforeBegin");
-}),_9=d.connect(this._current,"onBegin",this,function(_a){
-this._fire("onBegin",arguments);
-}),_b=d.connect(this._current,"onPlay",this,function(_c){
-this._fire("onPlay",arguments);
-d.disconnect(_8);
-d.disconnect(_9);
-d.disconnect(_b);
-});
-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(_d){
-this._fire("onPause",arguments);
-d.disconnect(e);
-});
-this._current.pause();
-}
-return this;
-},gotoPercent:function(_e,_f){
-this.pause();
-var _10=this.duration*_e;
-this._current=null;
-d.some(this._animations,function(a){
-if(a.duration<=_10){
-this._current=a;
-return true;
-}
-_10-=a.duration;
-return false;
-});
-if(this._current){
-this._current.gotoPercent(_10/this._current.duration,_f);
-}
-return this;
-},stop:function(_11){
-if(this._current){
-if(_11){
-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(_4,_1);
-dojo.fx.chain=function(_12){
-return new _4(_12);
-};
-var _13=function(_14){
-this._animations=_14||[];
-this._connects=[];
-this._finished=0;
-this.duration=0;
-d.forEach(_14,function(a){
-var _15=a.duration;
-if(a.delay){
-_15+=a.delay;
-}
-if(this.duration<_15){
-this.duration=_15;
-}
-this._connects.push(d.connect(a,"onEnd",this,"_onEnd"));
-},this);
-this._pseudoAnimation=new d.Animation({curve:[0,1],duration:this.duration});
-var _16=this;
-d.forEach(["beforeBegin","onBegin","onPlay","onAnimate","onPause","onStop","onEnd"],function(evt){
-_16._connects.push(d.connect(_16._pseudoAnimation,evt,function(){
-_16._fire(evt,arguments);
-}));
-});
-};
-d.extend(_13,{_doAction:function(_17,_18){
-d.forEach(this._animations,function(a){
-a[_17].apply(a,_18);
-});
-return this;
-},_onEnd:function(){
-if(++this._finished>this._animations.length){
-this._fire("onEnd");
-}
-},_call:function(_19,_1a){
-var t=this._pseudoAnimation;
-t[_19].apply(t,_1a);
-},play:function(_1b,_1c){
-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(_1d,_1e){
-var ms=this.duration*_1d;
-d.forEach(this._animations,function(a){
-a.gotoPercent(a.duration<ms?1:(ms/a.duration),_1e);
-});
-this._call("gotoPercent",arguments);
-return this;
-},stop:function(_1f){
-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(_13,_1);
-dojo.fx.combine=function(_20){
-return new _13(_20);
-};
-dojo.fx.wipeIn=function(_21){
-var _22=_21.node=d.byId(_21.node),s=_22.style,o;
-var _23=d.animateProperty(d.mixin({properties:{height:{start:function(){
-o=s.overflow;
-s.overflow="hidden";
-if(s.visibility=="hidden"||s.display=="none"){
-s.height="1px";
-s.display="";
-s.visibility="";
-return 1;
-}else{
-var _24=d.style(_22,"height");
-return Math.max(_24,1);
-}
-},end:function(){
-return _22.scrollHeight;
-}}}},_21));
-d.connect(_23,"onEnd",function(){
-s.height="auto";
-s.overflow=o;
-});
-return _23;
-};
-dojo.fx.wipeOut=function(_25){
-var _26=_25.node=d.byId(_25.node),s=_26.style,o;
-var _27=d.animateProperty(d.mixin({properties:{height:{end:1}}},_25));
-d.connect(_27,"beforeBegin",function(){
-o=s.overflow;
-s.overflow="hidden";
-s.display="";
-});
-d.connect(_27,"onEnd",function(){
-s.overflow=o;
-s.height="auto";
-s.display="none";
-});
-return _27;
+dojo.require("dojo.fx.Toggler"); // FIXME: remove this back-compat require in 2.0 
+/*=====
+dojo.fx = {
+	// summary: Effects library on top of Base animations
 };
-dojo.fx.slideTo=function(_28){
-var _29=_28.node=d.byId(_28.node),top=null,_2a=null;
-var _2b=(function(n){
-return function(){
-var cs=d.getComputedStyle(n);
-var pos=cs.position;
-top=(pos=="absolute"?n.offsetTop:parseInt(cs.top)||0);
-_2a=(pos=="absolute"?n.offsetLeft:parseInt(cs.left)||0);
-if(pos!="absolute"&&pos!="relative"){
-var ret=d.position(n,true);
-top=ret.y;
-_2a=ret.x;
-n.style.position="absolute";
-n.style.top=top+"px";
-n.style.left=_2a+"px";
-}
-};
-})(_29);
-_2b();
-var _2c=d.animateProperty(d.mixin({properties:{top:_28.top||0,left:_28.left||0}},_28));
-d.connect(_2c,"beforeBegin",_2c,_2b);
-return _2c;
-};
-})();
-}
+=====*/
+(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
+		//
+		// description:
+		//		Return a `dojo.Animation` which will play all passed
+		//		`dojo.Animation` instances in sequence, firing its own
+		//		synthesized events simulating a single animation. (eg:
+		//		onEnd of this animation means the end of the chain, 
+		//		not the individual animations within)
+		//
+		// example:
+		//	Once `node` is faded out, fade in `otherNode`
+		//	|	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", "onEnd"], 
+			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 a list 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:
+		//	Fade out `node` while fading in `otherNode` simultaneously
+		//	|	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:
+		//		Expand a node to it's natural height.
+		//
+		// description:
+		//		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: Object
+		//		A hash-map of standard `dojo.Animation` constructor properties
+		//		(such as easing: node: duration: and so on)
+		//
+		// example:
+		//	|	dojo.fx.wipeIn({
+		//	|		node:"someId"
+		//	|	}).play()
+		var node = args.node = d.byId(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:
+		//		Shrink a node to nothing and hide it. 
+		//
+		// description:
+		//		Returns an animation that will shrink node defined in "args"
+		//		from it's current height to 1px, and then hide it.
+		//
+		// args: Object
+		//		A hash-map of standard `dojo.Animation` constructor properties
+		//		(such as easing: node: duration: and so on)
+		// 
+		// example:
+		//	|	dojo.fx.wipeOut({ node:"someId" }).play()
+		
+		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:
+		//		Slide a node to a new top/left position
+		//
+		// description:
+		//		Returns an animation that will slide "node" 
+		//		defined in args Object from its current position to
+		//		the position defined by (args.left, args.top).
+		//
+		// args: Object
+		//		A hash-map of standard `dojo.Animation` constructor properties
+		//		(such as easing: node: duration: and so on). Special args members
+		//		are `top` and `left`, which indicate the new position to slide to.
+		//
+		// example:
+		//	|	dojo.fx.slideTo({ node: node, left:"40", top:"50", units:"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.position(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
+	}
+
+})();
\ No newline at end of file
diff --git a/dojo/fx/Toggler.js b/dojo/fx/Toggler.js
index 51032d9..7ff0223 100644
--- a/dojo/fx/Toggler.js
+++ b/dojo/fx/Toggler.js
@@ -1,30 +1,96 @@
-/*
-	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
-*/
+dojo.provide("dojo.fx.Toggler");
 
+dojo.declare("dojo.fx.Toggler", null, {
+	// summary:
+	//		A simple `dojo.Animation` toggler API.
+	//
+	// description:
+	//		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. All available members are mixed into 
+	//		these animations from the constructor (for example, `node`, 
+	//		`showDuration`, `hideDuration`). 
+	//
+	// example:
+	//	|	var t = new dojo.fx.Toggler({
+	//	|		node: "nodeId",
+	//	|		showDuration: 500,
+	//	|		// hideDuration will default to "200"
+	//	|		showFunc: dojo.fx.wipeIn, 
+	//	|		// hideFunc will default to "fadeOut"
+	//	|	});
+	//	|	t.show(100); // delay showing for 100ms
+	//	|	// ...time passes...
+	//	|	t.hide();
 
-if(!dojo._hasResource["dojo.fx.Toggler"]){
-dojo._hasResource["dojo.fx.Toggler"]=true;
-dojo.provide("dojo.fx.Toggler");
-dojo.declare("dojo.fx.Toggler",null,{node:null,showFunc:dojo.fadeIn,hideFunc:dojo.fadeOut,showDuration:200,hideDuration:200,constructor:function(_1){
-var _2=this;
-dojo.mixin(_2,_1);
-_2.node=_1.node;
-_2._showArgs=dojo.mixin({},_1);
-_2._showArgs.node=_2.node;
-_2._showArgs.duration=_2.showDuration;
-_2.showAnim=_2.showFunc(_2._showArgs);
-_2._hideArgs=dojo.mixin({},_1);
-_2._hideArgs.node=_2.node;
-_2._hideArgs.duration=_2.hideDuration;
-_2.hideAnim=_2.hideFunc(_2._hideArgs);
-dojo.connect(_2.showAnim,"beforeBegin",dojo.hitch(_2.hideAnim,"stop",true));
-dojo.connect(_2.hideAnim,"beforeBegin",dojo.hitch(_2.showAnim,"stop",true));
-},show:function(_3){
-return this.showAnim.play(_3||0);
-},hide:function(_4){
-return this.hideAnim.play(_4||0);
-}});
-}
+	// node: DomNode
+	//		the node to target for the showing and hiding animations
+	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,
+
+	// 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.
+	// FIXME: also would be nice to specify individual showArgs/hideArgs mixed into
+	// each animation individually. 
+	// FIXME: also would be nice to have events from the animations exposed/bridged
+
+	/*=====
+	_showArgs: null,
+	_showAnim: null,
+
+	_hideArgs: null,
+	_hideAnim: null,
+
+	_isShowing: false,
+	_isHiding: false,
+	=====*/
+
+	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));
+	},
+
+	show: function(delay){
+		// summary: Toggle the node to showing
+		// delay: Integer?
+		//		Ammount of time to stall playing the show animation
+		return this.showAnim.play(delay || 0);
+	},
+
+	hide: function(delay){
+		// summary: Toggle the node to hidden
+		// delay: Integer?
+		//		Ammount of time to stall playing the hide animation
+		return this.hideAnim.play(delay || 0);
+	}
+});
diff --git a/dojo/fx/easing.js b/dojo/fx/easing.js
index 632d9eb..69af935 100644
--- a/dojo/fx/easing.js
+++ b/dojo/fx/easing.js
@@ -1,166 +1,275 @@
-/*
-	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
-*/
+dojo.provide("dojo.fx.easing");
 
+dojo.fx.easing = {
+	// summary: 
+	//		Collection of easing functions to use beyond the default 
+	//		`dojo._defaultEasing` function.
+	// 
+	// description:
+	//
+	//		Easing functions are used to manipulate the iteration through
+	//		an `dojo.Animation`s _Line. _Line being the properties of an Animation,
+	//		and the easing function progresses through that Line determing
+	//		how quickly (or slowly) it should go. Or more accurately: modify
+	//		the value of the _Line based on the percentage of animation completed.
+	//	
+	//		All functions follow a simple naming convention of "ease type" + "when".
+	//		If the name of the function ends in Out, the easing described appears
+	//		towards the end of the animation. "In" means during the beginning,
+	//		and InOut means both ranges of the Animation will applied, both
+	//		beginning and end. 
+	//
+	//		One does not call the easing function directly, it must be passed to 
+	//		the `easing` property of an animation.
+	//
+	//	example:
+	//	|	dojo.require("dojo.fx.easing");
+	//	|	var anim = dojo.fadeOut({
+	//	|		node: 'node',	
+	//	|		duration: 2000,
+	//	|		//	note there is no () 
+	//	|		easing: dojo.fx.easing.quadIn
+	//	|	}).play();
+	//
+	
+	linear: function(/* Decimal? */n){
+		// summary: A linear easing function
+		return n;
+	},
 
-if(!dojo._hasResource["dojo.fx.easing"]){
-dojo._hasResource["dojo.fx.easing"]=true;
-dojo.provide("dojo.fx.easing");
-dojo.fx.easing={linear:function(n){
-return n;
-},quadIn:function(n){
-return Math.pow(n,2);
-},quadOut:function(n){
-return n*(n-2)*-1;
-},quadInOut:function(n){
-n=n*2;
-if(n<1){
-return Math.pow(n,2)/2;
-}
-return -1*((--n)*(n-2)-1)/2;
-},cubicIn:function(n){
-return Math.pow(n,3);
-},cubicOut:function(n){
-return Math.pow(n-1,3)+1;
-},cubicInOut:function(n){
-n=n*2;
-if(n<1){
-return Math.pow(n,3)/2;
-}
-n-=2;
-return (Math.pow(n,3)+2)/2;
-},quartIn:function(n){
-return Math.pow(n,4);
-},quartOut:function(n){
-return -1*(Math.pow(n-1,4)-1);
-},quartInOut:function(n){
-n=n*2;
-if(n<1){
-return Math.pow(n,4)/2;
-}
-n-=2;
-return -1/2*(Math.pow(n,4)-2);
-},quintIn:function(n){
-return Math.pow(n,5);
-},quintOut:function(n){
-return Math.pow(n-1,5)+1;
-},quintInOut:function(n){
-n=n*2;
-if(n<1){
-return Math.pow(n,5)/2;
-}
-n-=2;
-return (Math.pow(n,5)+2)/2;
-},sineIn:function(n){
-return -1*Math.cos(n*(Math.PI/2))+1;
-},sineOut:function(n){
-return Math.sin(n*(Math.PI/2));
-},sineInOut:function(n){
-return -1*(Math.cos(Math.PI*n)-1)/2;
-},expoIn:function(n){
-return (n==0)?0:Math.pow(2,10*(n-1));
-},expoOut:function(n){
-return (n==1)?1:(-1*Math.pow(2,-10*n)+1);
-},expoInOut:function(n){
-if(n==0){
-return 0;
-}
-if(n==1){
-return 1;
-}
-n=n*2;
-if(n<1){
-return Math.pow(2,10*(n-1))/2;
-}
---n;
-return (-1*Math.pow(2,-10*n)+2)/2;
-},circIn:function(n){
-return -1*(Math.sqrt(1-Math.pow(n,2))-1);
-},circOut:function(n){
-n=n-1;
-return Math.sqrt(1-Math.pow(n,2));
-},circInOut:function(n){
-n=n*2;
-if(n<1){
-return -1/2*(Math.sqrt(1-Math.pow(n,2))-1);
-}
-n-=2;
-return 1/2*(Math.sqrt(1-Math.pow(n,2))+1);
-},backIn:function(n){
-var s=1.70158;
-return Math.pow(n,2)*((s+1)*n-s);
-},backOut:function(n){
-n=n-1;
-var s=1.70158;
-return Math.pow(n,2)*((s+1)*n+s)+1;
-},backInOut:function(n){
-var s=1.70158*1.525;
-n=n*2;
-if(n<1){
-return (Math.pow(n,2)*((s+1)*n-s))/2;
-}
-n-=2;
-return (Math.pow(n,2)*((s+1)*n+s)+2)/2;
-},elasticIn:function(n){
-if(n==0||n==1){
-return n;
-}
-var p=0.3;
-var s=p/4;
-n=n-1;
-return -1*Math.pow(2,10*n)*Math.sin((n-s)*(2*Math.PI)/p);
-},elasticOut:function(n){
-if(n==0||n==1){
-return n;
-}
-var p=0.3;
-var s=p/4;
-return Math.pow(2,-10*n)*Math.sin((n-s)*(2*Math.PI)/p)+1;
-},elasticInOut:function(n){
-if(n==0){
-return 0;
-}
-n=n*2;
-if(n==2){
-return 1;
-}
-var p=0.3*1.5;
-var s=p/4;
-if(n<1){
-n-=1;
-return -0.5*(Math.pow(2,10*n)*Math.sin((n-s)*(2*Math.PI)/p));
-}
-n-=1;
-return 0.5*(Math.pow(2,-10*n)*Math.sin((n-s)*(2*Math.PI)/p))+1;
-},bounceIn:function(n){
-return (1-dojo.fx.easing.bounceOut(1-n));
-},bounceOut:function(n){
-var s=7.5625;
-var p=2.75;
-var l;
-if(n<(1/p)){
-l=s*Math.pow(n,2);
-}else{
-if(n<(2/p)){
-n-=(1.5/p);
-l=s*Math.pow(n,2)+0.75;
-}else{
-if(n<(2.5/p)){
-n-=(2.25/p);
-l=s*Math.pow(n,2)+0.9375;
-}else{
-n-=(2.625/p);
-l=s*Math.pow(n,2)+0.984375;
-}
-}
-}
-return l;
-},bounceInOut:function(n){
-if(n<0.5){
-return dojo.fx.easing.bounceIn(n*2)/2;
-}
-return (dojo.fx.easing.bounceOut(n*2-1)/2)+0.5;
-}};
-}
+	quadIn: function(/* Decimal? */n){
+		return Math.pow(n, 2);
+	},
+
+	quadOut: function(/* Decimal? */n){
+		return n * (n - 2) * -1;
+	},
+
+	quadInOut: function(/* Decimal? */n){
+		n = n * 2;
+		if(n < 1){ return Math.pow(n, 2) / 2; }
+		return -1 * ((--n) * (n - 2) - 1) / 2;
+	},
+
+	cubicIn: function(/* Decimal? */n){
+		return Math.pow(n, 3);
+	},
+
+	cubicOut: function(/* Decimal? */n){
+		return Math.pow(n - 1, 3) + 1;
+	},
+
+	cubicInOut: function(/* Decimal? */n){
+		n = n * 2;
+		if(n < 1){ return Math.pow(n, 3) / 2; }
+		n -= 2;
+		return (Math.pow(n, 3) + 2) / 2;
+	},
+
+	quartIn: function(/* Decimal? */n){
+		return Math.pow(n, 4);
+	},
+
+	quartOut: function(/* Decimal? */n){
+		return -1 * (Math.pow(n - 1, 4) - 1);
+	},
+
+	quartInOut: function(/* Decimal? */n){
+		n = n * 2;
+		if(n < 1){ return Math.pow(n, 4) / 2; }
+		n -= 2;
+		return -1 / 2 * (Math.pow(n, 4) - 2);
+	},
+
+	quintIn: function(/* Decimal? */n){
+		return Math.pow(n, 5);
+	},
+
+	quintOut: function(/* Decimal? */n){
+		return Math.pow(n - 1, 5) + 1;
+	},
+
+	quintInOut: function(/* Decimal? */n){
+		n = n * 2;
+		if(n < 1){ return Math.pow(n, 5) / 2; };
+		n -= 2;
+		return (Math.pow(n, 5) + 2) / 2;
+	},
+
+	sineIn: function(/* Decimal? */n){
+		return -1 * Math.cos(n * (Math.PI / 2)) + 1;
+	},
+
+	sineOut: function(/* Decimal? */n){
+		return Math.sin(n * (Math.PI / 2));
+	},
+
+	sineInOut: function(/* Decimal? */n){
+		return -1 * (Math.cos(Math.PI * n) - 1) / 2;
+	},
+
+	expoIn: function(/* Decimal? */n){
+		return (n == 0) ? 0 : Math.pow(2, 10 * (n - 1));
+	},
+
+	expoOut: function(/* Decimal? */n){
+		return (n == 1) ? 1 : (-1 * Math.pow(2, -10 * n) + 1);
+	},
+
+	expoInOut: function(/* Decimal? */n){
+		if(n == 0){ return 0; }
+		if(n == 1){ return 1; }
+		n = n * 2;
+		if(n < 1){ return Math.pow(2, 10 * (n - 1)) / 2; }
+		--n;
+		return (-1 * Math.pow(2, -10 * n) + 2) / 2;
+	},
+
+	circIn: function(/* Decimal? */n){
+		return -1 * (Math.sqrt(1 - Math.pow(n, 2)) - 1);
+	},
+
+	circOut: function(/* Decimal? */n){
+		n = n - 1;
+		return Math.sqrt(1 - Math.pow(n, 2));
+	},
+
+	circInOut: function(/* Decimal? */n){
+		n = n * 2;
+		if(n < 1){ return -1 / 2 * (Math.sqrt(1 - Math.pow(n, 2)) - 1); }
+		n -= 2;
+		return 1 / 2 * (Math.sqrt(1 - Math.pow(n, 2)) + 1);
+	},
+
+	backIn: function(/* Decimal? */n){
+		// summary: 
+		//		An easing function that starts away from the target, 
+		//		and quickly accelerates towards the end value.
+		// 
+		//		Use caution when the easing will cause values to become 
+		//		negative as some properties cannot be set to negative values.
+		var s = 1.70158;
+		return Math.pow(n, 2) * ((s + 1) * n - s);
+	},
+
+	backOut: function(/* Decimal? */n){
+		// summary: 
+		//		An easing function that pops past the range briefly, and slowly comes back. 
+		//
+		// description:
+		//		An easing function that pops past the range briefly, and slowly comes back. 
+		//
+		//		Use caution when the easing will cause values to become negative as some 
+		//		properties cannot be set to negative values.
+		
+		n = n - 1;
+		var s = 1.70158;
+		return Math.pow(n, 2) * ((s + 1) * n + s) + 1;
+	},
+
+	backInOut: function(/* Decimal? */n){
+		// summary: 
+		//		An easing function combining the effects of `backIn` and `backOut`
+		//
+		// description:
+		//		An easing function combining the effects of `backIn` and `backOut`.
+		//		Use caution when the easing will cause values to become negative 
+		//		as some properties cannot be set to negative values.
+		var s = 1.70158 * 1.525;
+		n = n * 2;
+		if(n < 1){ return (Math.pow(n, 2) * ((s + 1) * n - s)) / 2; }
+		n-=2;
+		return (Math.pow(n, 2) * ((s + 1) * n + s) + 2) / 2;
+	},
+
+	elasticIn: function(/* Decimal? */n){
+		// summary: 
+		//		An easing function the elastically snaps from the start value
+		//
+		// description:
+		//		An easing function the elastically snaps from the start value
+		//	
+		//		Use caution when the elasticity will cause values to become negative 
+		//		as some properties cannot be set to negative values.
+		if(n == 0 || n == 1){ return n; }
+		var p = .3;
+		var s = p / 4;
+		n = n - 1;
+		return -1 * Math.pow(2, 10 * n) * Math.sin((n - s) * (2 * Math.PI) / p);
+	},
+
+	elasticOut: function(/* Decimal? */n){
+		// summary: 
+		//		An easing function that elasticly snaps around the target value,
+		//		near the end of the Animation
+		//
+		// description:
+		//		An easing function that elasticly snaps around the target value,
+		//		near the end of the Animation
+		//
+		//		Use caution when the elasticity will cause values to become 
+		//		negative as some properties cannot be set to negative values.
+		if(n==0 || n == 1){ return n; }
+		var p = .3;
+		var s = p / 4;
+		return Math.pow(2, -10 * n) * Math.sin((n - s) * (2 * Math.PI) / p) + 1;
+	},
+
+	elasticInOut: function(/* Decimal? */n){
+		// summary: 
+		//		An easing function that elasticly snaps around the value, near
+		//		the beginning and end of the Animation.
+		//
+		// description:
+		//		An easing function that elasticly snaps around the value, near
+		//		the beginning and end of the Animation.
+		//
+		//		Use caution when the elasticity will cause values to become 
+		//		negative as some properties cannot be set to negative values.
+		if(n == 0) return 0;
+		n = n * 2;
+		if(n == 2) return 1;
+		var p = .3 * 1.5;
+		var s = p / 4;
+		if(n < 1){
+			n -= 1;
+			return -.5 * (Math.pow(2, 10 * n) * Math.sin((n - s) * (2 * Math.PI) / p));
+		}
+		n -= 1;
+		return .5 * (Math.pow(2, -10 * n) * Math.sin((n - s) * (2 * Math.PI) / p)) + 1;
+	},
+
+	bounceIn: function(/* Decimal? */n){
+		// summary: 
+		//		An easing function that 'bounces' near the beginning of an Animation
+		return (1 - dojo.fx.easing.bounceOut(1 - n)); // Decimal
+	},
+
+	bounceOut: function(/* Decimal? */n){
+		// summary:
+		//		An easing function that 'bounces' near the end of an Animation
+		var s = 7.5625;
+		var p = 2.75;
+		var l; 
+		if(n < (1 / p)){
+			l = s * Math.pow(n, 2);
+		}else if(n < (2 / p)){
+			n -= (1.5 / p);
+			l = s * Math.pow(n, 2) + .75;
+		}else if(n < (2.5 / p)){
+			n -= (2.25 / p);
+			l = s * Math.pow(n, 2) + .9375;
+		}else{
+			n -= (2.625 / p);
+			l = s * Math.pow(n, 2) + .984375;
+		}
+		return l;
+	},
+
+	bounceInOut: function(/* Decimal? */n){
+		// summary: 
+		//		An easing function that 'bounces' at the beginning and end of the Animation
+		if(n < 0.5){ return dojo.fx.easing.bounceIn(n * 2) / 2; }
+		return (dojo.fx.easing.bounceOut(n * 2 - 1) / 2) + 0.5; // Decimal
+	}
+};
diff --git a/dojo/gears.js b/dojo/gears.js
index e8edb13..7819eea 100644
--- a/dojo/gears.js
+++ b/dojo/gears.js
@@ -1,45 +1,52 @@
-/*
-	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
-*/
+dojo.provide("dojo.gears");
 
+dojo.gears._gearsObject = function(){
+	// summary: 
+	//		factory method to get a Google Gears plugin instance to
+	//		expose in the browser runtime environment, if present
+	var factory;
+	var results;
+	
+	var gearsObj = dojo.getObject("google.gears");
+	if(gearsObj){ return gearsObj; } // already defined elsewhere
+	
+	if(typeof GearsFactory != "undefined"){ // Firefox
+		factory = new GearsFactory();
+	}else{
+		if(dojo.isIE){
+			// IE
+			try{
+				factory = new ActiveXObject("Gears.Factory");
+			}catch(e){
+				// ok to squelch; there's no gears factory.  move on.
+			}
+		}else if(navigator.mimeTypes["application/x-googlegears"]){
+			// Safari?
+			factory = document.createElement("object");
+			factory.setAttribute("type", "application/x-googlegears");
+			factory.setAttribute("width", 0);
+			factory.setAttribute("height", 0);
+			factory.style.display = "none";
+			document.documentElement.appendChild(factory);
+		}
+	}
 
-if(!dojo._hasResource["dojo.gears"]){
-dojo._hasResource["dojo.gears"]=true;
-dojo.provide("dojo.gears");
-dojo.gears._gearsObject=function(){
-var _1;
-var _2;
-var _3=dojo.getObject("google.gears");
-if(_3){
-return _3;
-}
-if(typeof GearsFactory!="undefined"){
-_1=new GearsFactory();
-}else{
-if(dojo.isIE){
-try{
-_1=new ActiveXObject("Gears.Factory");
-}
-catch(e){
-}
-}else{
-if(navigator.mimeTypes["application/x-googlegears"]){
-_1=document.createElement("object");
-_1.setAttribute("type","application/x-googlegears");
-_1.setAttribute("width",0);
-_1.setAttribute("height",0);
-_1.style.display="none";
-document.documentElement.appendChild(_1);
-}
-}
-}
-if(!_1){
-return null;
-}
-dojo.setObject("google.gears.factory",_1);
-return dojo.getObject("google.gears");
+	// still nothing?
+	if(!factory){ return null; }
+	
+	// define the global objects now; don't overwrite them though if they
+	// were somehow set internally by the Gears plugin, which is on their
+	// dev roadmap for the future
+	dojo.setObject("google.gears.factory", factory);
+	return dojo.getObject("google.gears");
+};
+
+/*=====
+dojo.gears.available = {
+	// summary: True if client is using Google Gears
 };
-dojo.gears.available=(!!dojo.gears._gearsObject())||0;
-}
+=====*/
+// see if we have Google Gears installed, and if
+// so, make it available in the runtime environment
+// and in the Google standard 'google.gears' global object
+dojo.gears.available = (!!dojo.gears._gearsObject())||0;
diff --git a/dojo/hash.js b/dojo/hash.js
index 9f2cebc..149e2b6 100644
--- a/dojo/hash.js
+++ b/dojo/hash.js
@@ -1,133 +1,228 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.hash"]){
-dojo._hasResource["dojo.hash"]=true;
 dojo.provide("dojo.hash");
+//TODOC: where does this go?
+// summary:
+//		Methods for monitoring and updating the hash in the browser URL.
+//
+// example:
+//		dojo.subscribe("/dojo/hashchange", context, callback);
+//
+//		function callback (hashValue){
+//			// do something based on the hash value.
+// 		}
+
 (function(){
-dojo.hash=function(_1,_2){
-if(!arguments.length){
-return _3();
-}
-if(_1.charAt(0)=="#"){
-_1=_1.substring(1);
-}
-if(_2){
-_4(_1);
-}else{
-location.href="#"+_1;
-}
-return _1;
-};
-var _5=null,_6=null,_7=dojo.config.hashPollFrequency||100;
-function _3(){
-var h=location.href,i=h.indexOf("#");
-return (i>=0)?h.substring(i+1):"";
-};
-function _8(){
-dojo.publish("/dojo/hashchange",[_3()]);
-};
-function _9(){
-if(_3()===_5){
-return;
-}
-_5=_3();
-_8();
-};
-function _4(_a){
-if(_6){
-if(_6.isTransitioning()){
-setTimeout(dojo.hitch(null,_4,_a),_7);
-return;
-}
-var _b=_6.iframe.location.href;
-var _c=_b.indexOf("?");
-_6.iframe.location.replace(_b.substring(0,_c)+"?"+_a);
-return;
-}
-location.replace("#"+_a);
-_9();
-};
-function _d(){
-var _e=document.createElement("iframe"),_f="dojo-hash-iframe",_10=dojo.config.dojoBlankHtmlUrl||dojo.moduleUrl("dojo","resources/blank.html");
-_e.id=_f;
-_e.src=_10+"?"+_3();
-_e.style.display="none";
-document.body.appendChild(_e);
-this.iframe=dojo.global[_f];
-var _11,_12,_13,_14,_15,_16=this.iframe.location,_17=dojo.global.location;
-function _18(){
-_5=_17.hash;
-_11=_15?_5:_16.search;
-_12=false;
-_13=null;
-};
-this.isTransitioning=function(){
-return _12;
-};
-this.pollLocation=function(){
-if(!_15){
-try{
-_16.search;
-if(document.title!=_14){
-_14=this.iframe.document.title=document.title;
-}
-}
-catch(e){
-_15=true;
-console.error("dojo.hash: Error adding history entry. Server unreachable.");
-}
-}
-if(_12&&_5===_17.hash){
-if(_15||_16.search===_13){
-_18();
-_8();
-}else{
-setTimeout(dojo.hitch(this,this.pollLocation),0);
-return;
-}
-}else{
-if(_5===_17.hash&&(_15||_11===_16.search)){
-}else{
-if(_5!==_17.hash){
-_5=_17.hash;
-_12=true;
-_13="?"+_3();
-_e.src=_10+_13;
-_15=false;
-setTimeout(dojo.hitch(this,this.pollLocation),0);
-return;
-}else{
-if(!_15){
-_17.href="#"+_16.search.substring(1);
-_18();
-_8();
-}
-}
-}
-}
-setTimeout(dojo.hitch(this,this.pollLocation),_7);
-};
-_18();
-setTimeout(dojo.hitch(this,this.pollLocation),_7);
-};
-dojo.addOnLoad(function(){
-if("onhashchange" in dojo.global&&(!dojo.isIE||(dojo.isIE>=8&&document.compatMode!="BackCompat"))){
-dojo.connect(dojo.global,"onhashchange",_8);
-}else{
-if(document.addEventListener){
-_5=_3();
-setInterval(_9,_7);
-}else{
-if(document.attachEvent){
-_6=new _d();
-}
-}
-}
-});
-})();
-}
+	dojo.hash = function(/* String? */ hash, /* Boolean? */ replace){
+		//	summary:
+		//		Gets or sets the hash string.
+		//	description:
+		//		Handles getting and setting of location.hash.
+		//		 - If no arguments are passed, acts as a getter.
+		//		 - If a string is passed, acts as a setter.
+		//	hash: 
+		//		String: the hash is set - #string.
+		//	replace:
+		//		Boolean: If true, updates the hash value in the current history 
+		//			state instead of creating a new history state.
+		//	returns:
+		//		when used as a getter, returns the current hash string.
+		//		when used as a setter, returns the new hash string.
+		
+		// getter
+		if(!arguments.length){
+			return _getHash();
+		}
+		// setter
+		if(hash.charAt(0) == "#"){
+			hash = hash.substring(1);
+		}
+		if(replace){
+			_replace(hash);
+		}else{
+			location.href = "#" + hash;
+		}
+		return hash; // String
+	}
+
+	// Global vars
+	var _recentHash = null,
+		_ieUriMonitor = null,
+		_pollFrequency = dojo.config.hashPollFrequency || 100;
+
+	//Internal functions
+	function _getSegment(str, delimiter){
+		var i = str.indexOf(delimiter);
+		return (i >= 0) ? str.substring(i+1) : "";  
+	}
+	
+	function _getHash(){
+		return _getSegment(location.href, "#");
+	}
+
+	function _dispatchEvent(){
+		dojo.publish("/dojo/hashchange", [_getHash()]);
+	}
+
+	function _pollLocation(){
+		if(_getHash() === _recentHash){
+			return;
+		}
+		_recentHash = _getHash();
+		_dispatchEvent();
+	}
+	
+	function _replace(hash){
+		if(_ieUriMonitor){
+			if(_ieUriMonitor.isTransitioning()){
+				setTimeout(dojo.hitch(null,_replace,hash), _pollFrequency);
+				return;
+			}
+			var href = _ieUriMonitor.iframe.location.href;
+			var index = href.indexOf('?');
+			// main frame will detect and update itself
+			_ieUriMonitor.iframe.location.replace(href.substring(0, index) + "?" + hash);
+			return;
+		}
+		location.replace("#"+hash);
+		_pollLocation();
+	}
+
+	function IEUriMonitor(){
+		// summary:
+		//		Determine if the browser's URI has changed or if the user has pressed the 
+		//		back or forward button. If so, call _dispatchEvent.
+		//
+		//	description:
+		//		IE doesn't add changes to the URI's hash into the history unless the hash
+		//		value corresponds to an actual named anchor in the document. To get around
+		//      this IE difference, we use a background IFrame to maintain a back-forward
+		//		history, by updating the IFrame's query string to correspond to the
+		//		value of the main browser location's hash value.
+		//
+		//		E.g. if the value of the browser window's location changes to
+		//
+		//		#action=someAction
+		//
+		//		... then we'd update the IFrame's source to:
+		//
+		//		?action=someAction
+		//
+		//		This design leads to a somewhat complex state machine, which is
+		//		described below:
+		//
+		//		s1: Stable state - neither the window's location has changed nor
+		//			has the IFrame's location. Note that this is the 99.9% case, so
+		//			we optimize for it.
+		//			Transitions: s1, s2, s3
+		//		s2: Window's location changed - when a user clicks a hyperlink or
+		//			code programmatically changes the window's URI.
+		//			Transitions: s4
+		//		s3: Iframe's location changed as a result of user pressing back or
+		//			forward - when the user presses back or forward, the location of
+		//			the background's iframe changes to the previous or next value in
+		//			its history.
+		//			Transitions: s1
+		//		s4: IEUriMonitor has programmatically changed the location of the
+		//			background iframe, but it's location hasn't yet changed. In this
+		//			case we do nothing because we need to wait for the iframe's
+		//			location to reflect its actual state.
+		//			Transitions: s4, s5
+		//		s5:	IEUriMonitor has programmatically changed the location of the
+		//			background iframe, and the iframe's location has caught up with
+		//			reality. In this case we need to transition to s1.
+		//			Transitions: s1
+		//
+		//		The hashchange event is always dispatched on the transition back to s1.
+		//
+
+		// create and append iframe
+		var ifr = document.createElement("iframe"),
+			IFRAME_ID = "dojo-hash-iframe",
+			ifrSrc = dojo.config.dojoBlankHtmlUrl || dojo.moduleUrl("dojo", "resources/blank.html");
+		ifr.id = IFRAME_ID;
+		ifr.src = ifrSrc + "?" + _getHash();
+		ifr.style.display = "none";
+		document.body.appendChild(ifr);
+
+		this.iframe = dojo.global[IFRAME_ID];
+		var recentIframeQuery, transitioning, expectedIFrameQuery, docTitle, ifrOffline,
+			iframeLoc = this.iframe.location;
+
+		function resetState(){
+			_recentHash = _getHash();
+			recentIframeQuery = ifrOffline ? _recentHash : _getSegment(iframeLoc.href, "?");
+			transitioning = false;
+			expectedIFrameQuery = null;
+		}
+
+		this.isTransitioning = function(){
+			return transitioning;
+		}
+		
+		this.pollLocation = function(){
+			if(!ifrOffline) {
+				try{
+					//see if we can access the iframe's location without a permission denied error
+					var iframeSearch = _getSegment(iframeLoc.href, "?");
+					//good, the iframe is same origin (no thrown exception)
+					if(document.title != docTitle){ //sync title of main window with title of iframe.
+						docTitle = this.iframe.document.title = document.title;
+					}
+				}catch(e){
+					//permission denied - server cannot be reached.
+					ifrOffline = true;
+					console.error("dojo.hash: Error adding history entry. Server unreachable.");
+				}
+			}
+			var hash = _getHash();
+			if(transitioning && _recentHash === hash){
+				// we're in an iframe transition (s4 or s5)
+				if(ifrOffline || iframeSearch === expectedIFrameQuery){
+					// s5 (iframe caught up to main window or iframe offline), transition back to s1
+					resetState();
+					_dispatchEvent();
+				}else{
+					// s4 (waiting for iframe to catch up to main window)
+					setTimeout(dojo.hitch(this,this.pollLocation),0);
+					return;
+				}
+			}else if(_recentHash === hash && (ifrOffline || recentIframeQuery === iframeSearch)){
+				// we're in stable state (s1, iframe query == main window hash), do nothing
+			}else{
+				// the user has initiated a URL change somehow.
+				// sync iframe query <-> main window hash
+				if(_recentHash !== hash){
+					// s2 (main window location changed), set iframe url and transition to s4
+					_recentHash = hash;
+					transitioning = true;
+					expectedIFrameQuery = hash;
+					ifr.src = ifrSrc + "?" + expectedIFrameQuery;
+					ifrOffline = false;	//we're updating the iframe src - set offline to false so we can check again on next poll.
+					setTimeout(dojo.hitch(this,this.pollLocation),0); //yielded transition to s4 while iframe reloads.
+					return;
+				}else if(!ifrOffline){
+					// s3 (iframe location changed via back/forward button), set main window url and transition to s1.
+					location.href = "#" + iframeLoc.search.substring(1);
+					resetState();
+					_dispatchEvent();
+				}
+			}
+			setTimeout(dojo.hitch(this,this.pollLocation), _pollFrequency);
+		}
+		resetState(); // initialize state (transition to s1)
+		setTimeout(dojo.hitch(this,this.pollLocation), _pollFrequency);
+	}
+	dojo.addOnLoad(function(){
+		if("onhashchange" in dojo.global && (!dojo.isIE || (dojo.isIE >= 8 && document.compatMode != "BackCompat"))){	//need this IE browser test because "onhashchange" exists in IE8 in IE7 mode
+			dojo.connect(dojo.global,"onhashchange",_dispatchEvent);
+		}else{
+			if(document.addEventListener){ // Non-IE
+				_recentHash = _getHash();
+				setInterval(_pollLocation, _pollFrequency); //Poll the window location for changes
+			}else if(document.attachEvent){ // IE7-
+				//Use hidden iframe in versions of IE that don't have onhashchange event
+				_ieUriMonitor = new IEUriMonitor();
+			} 
+			// else non-supported browser, do nothing.
+		}
+	});
+})();
\ No newline at end of file
diff --git a/dojo/html.js b/dojo/html.js
index 57700a7..f401a63 100644
--- a/dojo/html.js
+++ b/dojo/html.js
@@ -1,148 +1,320 @@
-/*
-	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
-*/
+dojo.provide("dojo.html");
 
+// the parser might be needed..
+dojo.require("dojo.parser"); 
 
-if(!dojo._hasResource["dojo.html"]){
-dojo._hasResource["dojo.html"]=true;
-dojo.provide("dojo.html");
-dojo.require("dojo.parser");
-(function(){
-var _1=0,d=dojo;
-dojo.html._secureForInnerHtml=function(_2){
-return _2.replace(/(?:\s*<!DOCTYPE\s[^>]+>|<title[^>]*>[\s\S]*?<\/title>)/ig,"");
-};
-dojo.html._emptyNode=dojo.empty;
-dojo.html._setNodeContent=function(_3,_4){
-d.empty(_3);
-if(_4){
-if(typeof _4=="string"){
-_4=d._toDom(_4,_3.ownerDocument);
-}
-if(!_4.nodeType&&d.isArrayLike(_4)){
-for(var _5=_4.length,i=0;i<_4.length;i=_5==_4.length?i+1:0){
-d.place(_4[i],_3,"last");
-}
-}else{
-d.place(_4,_3,"last");
-}
-}
-return _3;
-};
-dojo.declare("dojo.html._ContentSetter",null,{node:"",content:"",id:"",cleanContent:false,extractContent:false,parseContent:false,constructor:function(_6,_7){
-dojo.mixin(this,_6||{});
-_7=this.node=dojo.byId(this.node||_7);
-if(!this.id){
-this.id=["Setter",(_7)?_7.id||_7.tagName:"",_1++].join("_");
-}
-if(!(this.node||_7)){
-new Error(this.declaredClass+": no node provided to "+this.id);
-}
-},set:function(_8,_9){
-if(undefined!==_8){
-this.content=_8;
-}
-if(_9){
-this._mixin(_9);
-}
-this.onBegin();
-this.setContent();
-this.onEnd();
-return this.node;
-},setContent:function(){
-var _a=this.node;
-if(!_a){
-console.error("setContent given no node");
-}
-try{
-_a=dojo.html._setNodeContent(_a,this.content);
-}
-catch(e){
-var _b=this.onContentError(e);
-try{
-_a.innerHTML=_b;
-}
-catch(e){
-console.error("Fatal "+this.declaredClass+".setContent could not change content due to "+e.message,e);
-}
-}
-this.node=_a;
-},empty:function(){
-if(this.parseResults&&this.parseResults.length){
-dojo.forEach(this.parseResults,function(w){
-if(w.destroy){
-w.destroy();
-}
-});
-delete this.parseResults;
-}
-dojo.html._emptyNode(this.node);
-},onBegin:function(){
-var _c=this.content;
-if(dojo.isString(_c)){
-if(this.cleanContent){
-_c=dojo.html._secureForInnerHtml(_c);
-}
-if(this.extractContent){
-var _d=_c.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
-if(_d){
-_c=_d[1];
-}
-}
-}
-this.empty();
-this.content=_c;
-return this.node;
-},onEnd:function(){
-if(this.parseContent){
-this._parse();
-}
-return this.node;
-},tearDown:function(){
-delete this.parseResults;
-delete this.node;
-delete this.content;
-},onContentError:function(_e){
-return "Error occured setting content: "+_e;
-},_mixin:function(_f){
-var _10={},key;
-for(key in _f){
-if(key in _10){
-continue;
-}
-this[key]=_f[key];
-}
-},_parse:function(){
-var _11=this.node;
-try{
-this.parseResults=dojo.parser.parse(_11,true);
-}
-catch(e){
-this._onError("Content",e,"Error parsing in _ContentSetter#"+this.id);
-}
-},_onError:function(_12,err,_13){
-var _14=this["on"+_12+"Error"].call(this,err);
-if(_13){
-console.error(_13,err);
-}else{
-if(_14){
-dojo.html._setNodeContent(this.node,_14,true);
-}
-}
-}});
-dojo.html.set=function(_15,_16,_17){
-if(undefined==_16){
-console.warn("dojo.html.set: no cont argument provided, using empty string");
-_16="";
-}
-if(!_17){
-return dojo.html._setNodeContent(_15,_16,true);
-}else{
-var op=new dojo.html._ContentSetter(dojo.mixin(_17,{content:_16,node:_15}));
-return op.set();
-}
-};
+(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, 
+		d = dojo;
+	
+	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){
+		// summary:
+		//		inserts the given content into the given node
+		//	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
+		
+		// always empty
+		d.empty(node);
+
+		if(cont) {
+			if(typeof cont == "string") {
+				cont = d._toDom(cont, node.ownerDocument);
+			}
+			if(!cont.nodeType && d.isArrayLike(cont)) {
+				// handle as enumerable, but it may shrink as we enumerate it
+				for(var startlen=cont.length, i=0; i<cont.length; i=startlen==cont.length ? i+1 : 0) {
+					d.place( cont[i], node, "last");
+				}
+			} else {
+				// pass nodes, documentFragments and unknowns through to dojo.place
+				d.place(cont, node, "last");
+			}
+		}
+
+		// 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("_");
+				}
+			},
+			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) {
+				    // can't proceed
+					throw new Error(this.declaredClass + ": 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: rootNode,
+						dir: this.dir,
+						lang: this.lang
+					});
+				}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();
+		}
+	};
 })();
-}
diff --git a/dojo/i18n.js b/dojo/i18n.js
index 2b0f1a3..e83ac60 100644
--- a/dojo/i18n.js
+++ b/dojo/i18n.js
@@ -1,171 +1,247 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.i18n"]){
-dojo._hasResource["dojo.i18n"]=true;
 dojo.provide("dojo.i18n");
-dojo.i18n.getLocalization=function(_1,_2,_3){
-_3=dojo.i18n.normalizeLocale(_3);
-var _4=_3.split("-");
-var _5=[_1,"nls",_2].join(".");
-var _6=dojo._loadedModules[_5];
-if(_6){
-var _7;
-for(var i=_4.length;i>0;i--){
-var _8=_4.slice(0,i).join("_");
-if(_6[_8]){
-_7=_6[_8];
-break;
-}
-}
-if(!_7){
-_7=_6.ROOT;
-}
-if(_7){
-var _9=function(){
-};
-_9.prototype=_7;
-return new _9();
-}
-}
-throw new Error("Bundle not found: "+_2+" in "+_1+" , locale="+_3);
+
+/*=====
+dojo.i18n = {
+	// summary: Utility classes to enable loading of resources for internationalization (i18n)
 };
-dojo.i18n.normalizeLocale=function(_a){
-var _b=_a?_a.toLowerCase():dojo.locale;
-if(_b=="root"){
-_b="ROOT";
-}
-return _b;
+=====*/
+
+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._requireLocalization=function(_c,_d,_e,_f){
-var _10=dojo.i18n.normalizeLocale(_e);
-var _11=[_c,"nls",_d].join(".");
-var _12="";
-if(_f){
-var _13=_f.split(",");
-for(var i=0;i<_13.length;i++){
-if(_10["indexOf"](_13[i])==0){
-if(_13[i].length>_12.length){
-_12=_13[i];
-}
-}
-}
-if(!_12){
-_12="ROOT";
-}
-}
-var _14=_f?_12:_10;
-var _15=dojo._loadedModules[_11];
-var _16=null;
-if(_15){
-if(dojo.config.localizationComplete&&_15._built){
-return;
-}
-var _17=_14.replace(/-/g,"_");
-var _18=_11+"."+_17;
-_16=dojo._loadedModules[_18];
-}
-if(!_16){
-_15=dojo["provide"](_11);
-var _19=dojo._getModuleSymbols(_c);
-var _1a=_19.concat("nls").join("/");
-var _1b;
-dojo.i18n._searchLocalePath(_14,_f,function(loc){
-var _1c=loc.replace(/-/g,"_");
-var _1d=_11+"."+_1c;
-var _1e=false;
-if(!dojo._loadedModules[_1d]){
-dojo["provide"](_1d);
-var _1f=[_1a];
-if(loc!="ROOT"){
-_1f.push(loc);
-}
-_1f.push(_d);
-var _20=_1f.join("/")+".js";
-_1e=dojo._loadPath(_20,null,function(_21){
-var _22=function(){
+
+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
 };
-_22.prototype=_1b;
-_15[_1c]=new _22();
-for(var j in _21){
-_15[_1c][j]=_21[j];
-}
-});
-}else{
-_1e=true;
-}
-if(_1e&&_15[_1c]){
-_1b=_15[_1c];
-}else{
-_15[_1c]=_1b;
-}
-if(_f){
-return true;
-}
-});
-}
-if(_f&&_10!=_12){
-_15[_10.replace(/-/g,"_")]=_15[_12.replace(/-/g,"_")];
-}
+
+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(){
-var _23=dojo.config.extraLocale;
-if(_23){
-if(!_23 instanceof Array){
-_23=[_23];
-}
-var req=dojo.i18n._requireLocalization;
-dojo.i18n._requireLocalization=function(m,b,_24,_25){
-req(m,b,_24,_25);
-if(_24){
-return;
-}
-for(var i=0;i<_23.length;i++){
-req(m,b,_23[i],_25);
-}
-};
-}
+	// 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(_26,_27,_28){
-_26=dojo.i18n.normalizeLocale(_26);
-var _29=_26.split("-");
-var _2a=[];
-for(var i=_29.length;i>0;i--){
-_2a.push(_29.slice(0,i).join("-"));
-}
-_2a.push(false);
-if(_27){
-_2a.reverse();
-}
-for(var j=_2a.length-1;j>=0;j--){
-var loc=_2a[j]||"ROOT";
-var _2b=_28(loc);
-if(_2b){
-break;
-}
-}
-};
-dojo.i18n._preloadLocalizations=function(_2c,_2d){
-function _2e(_2f){
-_2f=dojo.i18n.normalizeLocale(_2f);
-dojo.i18n._searchLocalePath(_2f,true,function(loc){
-for(var i=0;i<_2d.length;i++){
-if(_2d[i]==loc){
-dojo["require"](_2c+"_"+loc);
-return true;
-}
-}
-return false;
-});
+
+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; }
+	}
 };
-_2e();
-var _30=dojo.config.extraLocale||[];
-for(var i=0;i<_30.length;i++){
-_2e(_30[i]);
-}
+
+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]);
+	}
 };
-}
diff --git a/dojo/io/iframe.js b/dojo/io/iframe.js
index 12068b4..04221a3 100644
--- a/dojo/io/iframe.js
+++ b/dojo/io/iframe.js
@@ -1,265 +1,400 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.io.iframe"]){
-dojo._hasResource["dojo.io.iframe"]=true;
 dojo.provide("dojo.io.iframe");
-dojo.io.iframe={create:function(_1,_2,_3){
-if(window[_1]){
-return window[_1];
-}
-if(window.frames[_1]){
-return window.frames[_1];
-}
-var _4=null;
-var _5=_3;
-if(!_5){
-if(dojo.config["useXDomain"]&&!dojo.config["dojoBlankHtmlUrl"]){
-console.warn("dojo.io.iframe.create: When using cross-domain Dojo builds,"+" please save dojo/resources/blank.html to your domain and set djConfig.dojoBlankHtmlUrl"+" to the path on your domain to blank.html");
-}
-_5=(dojo.config["dojoBlankHtmlUrl"]||dojo.moduleUrl("dojo","resources/blank.html"));
-}
-var _6=dojo.isIE?"<iframe name=\""+_1+"\" src=\""+_5+"\" onload=\""+_2+"\">":"iframe";
-_4=dojo.doc.createElement(_6);
-with(_4){
-name=_1;
-setAttribute("name",_1);
-id=_1;
-}
-dojo.body().appendChild(_4);
-window[_1]=_4;
-with(_4.style){
-if(!(dojo.isSafari<3)){
-position="absolute";
-}
-left=top="1px";
-height=width="1px";
-visibility="hidden";
-}
-if(!dojo.isIE){
-this.setSrc(_4,_5,true);
-_4.onload=new Function(_2);
-}
-return _4;
-},setSrc:function(_7,_8,_9){
-try{
-if(!_9){
-if(dojo.isWebKit){
-_7.location=_8;
-}else{
-frames[_7.name].location=_8;
-}
-}else{
-var _a;
-if(dojo.isIE||dojo.isWebKit>521){
-_a=_7.contentWindow.document;
-}else{
-if(dojo.isSafari){
-_a=_7.document;
-}else{
-_a=_7.contentWindow;
-}
-}
-if(!_a){
-_7.location=_8;
-return;
-}else{
-_a.location.replace(_8);
-}
-}
-}
-catch(e){
-}
-},doc:function(_b){
-var _c=_b.contentDocument||(((_b.name)&&(_b.document)&&(dojo.doc.getElementsByTagName("iframe")[_b.name].contentWindow)&&(dojo.doc.getElementsByTagName("iframe")[_b.name].contentWindow.document)))||((_b.name)&&(dojo.doc.frames[_b.name])&&(dojo.doc.frames[_b.name].document))||null;
-return _c;
-},send:function(_d){
-if(!this["_frame"]){
-this._frame=this.create(this._iframeName,dojo._scopeName+".io.iframe._iframeOnload();");
-}
-var _e=dojo._ioSetArgs(_d,function(_f){
-_f.canceled=true;
-_f.ioArgs._callNext();
-},function(dfd){
-var _10=null;
-try{
-var _11=dfd.ioArgs;
-var dii=dojo.io.iframe;
-var ifd=dii.doc(dii._frame);
-var _12=_11.handleAs;
-_10=ifd;
-if(_12!="html"){
-if(_12=="xml"){
-if(dojo.isIE){
-dojo.query("a",dii._frame.contentWindow.document.documentElement).orphan();
-var _13=(dii._frame.contentWindow.document).documentElement.innerText;
-_13=_13.replace(/>\s+</g,"><");
-_13=dojo.trim(_13);
-var _14={responseText:_13};
-_10=dojo._contentHandlers["xml"](_14);
-}
-}else{
-_10=ifd.getElementsByTagName("textarea")[0].value;
-if(_12=="json"){
-_10=dojo.fromJson(_10);
-}else{
-if(_12=="javascript"){
-_10=dojo.eval(_10);
-}
-}
-}
-}
-}
-catch(e){
-_10=e;
-}
-finally{
-_11._callNext();
-}
-return _10;
-},function(_15,dfd){
-dfd.ioArgs._hasError=true;
-dfd.ioArgs._callNext();
-return _15;
-});
-_e.ioArgs._callNext=function(){
-if(!this["_calledNext"]){
-this._calledNext=true;
-dojo.io.iframe._currentDfd=null;
-dojo.io.iframe._fireNextRequest();
-}
-};
-this._dfdQueue.push(_e);
-this._fireNextRequest();
-dojo._ioWatch(_e,function(dfd){
-return !dfd.ioArgs["_hasError"];
-},function(dfd){
-return (!!dfd.ioArgs["_finished"]);
-},function(dfd){
-if(dfd.ioArgs._finished){
-dfd.callback(dfd);
-}else{
-dfd.errback(new Error("Invalid dojo.io.iframe request state"));
-}
+
+/*=====
+dojo.declare("dojo.io.iframe.__ioArgs", dojo.__IoArgs, {
+	constructor: function(){
+		//	summary:
+		//		All the properties described in the dojo.__ioArgs type, apply
+		//		to this type. The following additional properties are allowed
+		//		for dojo.io.iframe.send():
+		//	method: String?
+		//		The HTTP method to use. "GET" or "POST" are the only supported
+		//		values.  It will try to read the value from the form node's
+		//		method, then try this argument. If neither one exists, then it
+		//		defaults to POST.
+		//	handleAs: String?
+		//		Specifies what format the result data should be given to the
+		//		load/handle callback. Valid values are: text, html, xml, json,
+		//		javascript. IMPORTANT: For all values EXCEPT html and xml, The
+		//		server response should be an HTML file with a textarea element.
+		//		The response data should be inside the textarea element. Using an
+		//		HTML document the only reliable, cross-browser way this
+		//		transport can know when the response has loaded. For the html
+		//		handleAs value, just return a normal HTML document.  NOTE: xml
+		//		is now supported with this transport (as of 1.1+); a known issue
+		//		is if the XML document in question is malformed, Internet Explorer
+		//		will throw an uncatchable error.
+		//	content: Object?
+		//		If "form" is one of the other args properties, then the content
+		//		object properties become hidden form form elements. For
+		//		instance, a content object of {name1 : "value1"} is converted
+		//		to a hidden form element with a name of "name1" and a value of
+		//		"value1". If there is not a "form" property, then the content
+		//		object is converted into a name=value&name=value string, by
+		//		using dojo.objectToQuery().
+		this.method = method;
+		this.handleAs = handleAs;
+		this.content = content;
+	}
 });
-return _e;
-},_currentDfd:null,_dfdQueue:[],_iframeName:dojo._scopeName+"IoIframe",_fireNextRequest:function(){
-try{
-if((this._currentDfd)||(this._dfdQueue.length==0)){
-return;
-}
-do{
-var dfd=this._currentDfd=this._dfdQueue.shift();
-}while(dfd&&dfd.canceled&&this._dfdQueue.length);
-if(!dfd||dfd.canceled){
-this._currentDfd=null;
-return;
-}
-var _16=dfd.ioArgs;
-var _17=_16.args;
-_16._contentToClean=[];
-var fn=dojo.byId(_17["form"]);
-var _18=_17["content"]||{};
-if(fn){
-if(_18){
-var _19=function(_1a,_1b){
-var tn;
-if(dojo.isIE){
-tn=dojo.doc.createElement("<input type='hidden' name='"+_1a+"'>");
-}else{
-tn=dojo.doc.createElement("input");
-tn.type="hidden";
-tn.name=_1a;
-}
-tn.value=_1b;
-fn.appendChild(tn);
-_16._contentToClean.push(_1a);
-};
-for(var x in _18){
-var val=_18[x];
-if(dojo.isArray(val)&&val.length>1){
-var i;
-for(i=0;i<val.length;i++){
-_19(x,val[i]);
-}
-}else{
-if(!fn[x]){
-_19(x,val);
-}else{
-fn[x].value=val;
-}
-}
-}
-}
-var _1c=fn.getAttributeNode("action");
-var _1d=fn.getAttributeNode("method");
-var _1e=fn.getAttributeNode("target");
-if(_17["url"]){
-_16._originalAction=_1c?_1c.value:null;
-if(_1c){
-_1c.value=_17.url;
-}else{
-fn.setAttribute("action",_17.url);
-}
-}
-if(!_1d||!_1d.value){
-if(_1d){
-_1d.value=(_17["method"])?_17["method"]:"post";
-}else{
-fn.setAttribute("method",(_17["method"])?_17["method"]:"post");
-}
-}
-_16._originalTarget=_1e?_1e.value:null;
-if(_1e){
-_1e.value=this._iframeName;
-}else{
-fn.setAttribute("target",this._iframeName);
-}
-fn.target=this._iframeName;
-dojo._ioNotifyStart(dfd);
-fn.submit();
-}else{
-var _1f=_17.url+(_17.url.indexOf("?")>-1?"&":"?")+_16.query;
-dojo._ioNotifyStart(dfd);
-this.setSrc(this._frame,_1f,true);
-}
-}
-catch(e){
-dfd.errback(e);
-}
-},_iframeOnload:function(){
-var dfd=this._currentDfd;
-if(!dfd){
-this._fireNextRequest();
-return;
-}
-var _20=dfd.ioArgs;
-var _21=_20.args;
-var _22=dojo.byId(_21.form);
-if(_22){
-var _23=_20._contentToClean;
-for(var i=0;i<_23.length;i++){
-var key=_23[i];
-for(var j=0;j<_22.childNodes.length;j++){
-var _24=_22.childNodes[j];
-if(_24.name==key){
-dojo.destroy(_24);
-break;
-}
-}
-}
-if(_20["_originalAction"]){
-_22.setAttribute("action",_20._originalAction);
-}
-if(_20["_originalTarget"]){
-_22.setAttribute("target",_20._originalTarget);
-_22.target=_20._originalTarget;
-}
-}
-_20._finished=true;
-}};
+=====*/
+
+dojo.io.iframe = {
+	// summary: 
+	//		Sends an Ajax I/O call using and Iframe (for instance, to upload files)
+	
+	create: function(/*String*/fname, /*String*/onloadstr, /*String?*/uri){
+		//	summary:
+		//		Creates a hidden iframe in the page. Used mostly for IO
+		//		transports.  You do not need to call this to start a
+		//		dojo.io.iframe request. Just call send().
+		//	fname: String
+		//		The name of the iframe. Used for the name attribute on the
+		//		iframe.
+		//	onloadstr: String
+		//		A string of JavaScript that will be executed when the content
+		//		in the iframe loads.
+		//	uri: String
+		//		The value of the src attribute on the iframe element. If a
+		//		value is not given, then dojo/resources/blank.html will be
+		//		used.
+		if(window[fname]){ return window[fname]; }
+		if(window.frames[fname]){ return window.frames[fname]; }
+		var cframe = null;
+		var turi = uri;
+		if(!turi){
+			if(dojo.config["useXDomain"] && !dojo.config["dojoBlankHtmlUrl"]){
+				console.warn("dojo.io.iframe.create: When using cross-domain Dojo builds,"
+					+ " please save dojo/resources/blank.html to your domain and set djConfig.dojoBlankHtmlUrl"
+					+ " to the path on your domain to blank.html");
+			}
+			turi = (dojo.config["dojoBlankHtmlUrl"]||dojo.moduleUrl("dojo", "resources/blank.html"));
+		}
+		var ifrstr = dojo.isIE ? '<iframe name="'+fname+'" src="'+turi+'" onload="'+onloadstr+'">' : 'iframe';
+		cframe = dojo.doc.createElement(ifrstr);
+		with(cframe){
+			name = fname;
+			setAttribute("name", fname);
+			id = fname;
+		}
+		dojo.body().appendChild(cframe);
+		window[fname] = cframe;
+	
+		with(cframe.style){
+			if(!(dojo.isSafari < 3)){
+				//We can't change the src in Safari 2.0.3 if absolute position. Bizarro.
+				position = "absolute";
+			}
+			left = top = "1px";
+			height = width = "1px";
+			visibility = "hidden";
+		}
+
+		if(!dojo.isIE){
+			this.setSrc(cframe, turi, true);
+			cframe.onload = new Function(onloadstr);
+		}
+
+		return cframe;
+	},
+
+	setSrc: function(/*DOMNode*/iframe, /*String*/src, /*Boolean*/replace){
+		//summary:
+		//		Sets the URL that is loaded in an IFrame. The replace parameter
+		//		indicates whether location.replace() should be used when
+		//		changing the location of the iframe.
+		try{
+			if(!replace){
+				if(dojo.isWebKit){
+					iframe.location = src;
+				}else{
+					frames[iframe.name].location = src;
+				}
+			}else{
+				// Fun with DOM 0 incompatibilities!
+				var idoc;
+				//WebKit > 521 corresponds with Safari 3, which started with 522 WebKit version.
+				if(dojo.isIE || dojo.isWebKit > 521){
+					idoc = iframe.contentWindow.document;
+				}else if(dojo.isSafari){
+					idoc = iframe.document;
+				}else{ //  if(d.isMozilla){
+					idoc = iframe.contentWindow;
+				}
+	
+				//For Safari (at least 2.0.3) and Opera, if the iframe
+				//has just been created but it doesn't have content
+				//yet, then iframe.document may be null. In that case,
+				//use iframe.location and return.
+				if(!idoc){
+					iframe.location = src;
+					return;
+				}else{
+					idoc.location.replace(src);
+				}
+			}
+		}catch(e){ 
+			console.log("dojo.io.iframe.setSrc: ", e); 
+		}
+	},
+
+	doc: function(/*DOMNode*/iframeNode){
+		//summary: Returns the document object associated with the iframe DOM Node argument.
+		var doc = iframeNode.contentDocument || // W3
+			(
+				(
+					(iframeNode.name) && (iframeNode.document) && 
+					(dojo.doc.getElementsByTagName("iframe")[iframeNode.name].contentWindow) &&
+					(dojo.doc.getElementsByTagName("iframe")[iframeNode.name].contentWindow.document)
+				)
+			) ||  // IE
+			(
+				(iframeNode.name)&&(dojo.doc.frames[iframeNode.name])&&
+				(dojo.doc.frames[iframeNode.name].document)
+			) || null;
+		return doc;
+	},
+
+	send: function(/*dojo.io.iframe.__ioArgs*/args){
+		//summary: 
+		//		Function that sends the request to the server.
+		//		This transport can only process one send() request at a time, so if send() is called
+		//multiple times, it will queue up the calls and only process one at a time.
+		if(!this["_frame"]){
+			this._frame = this.create(this._iframeName, dojo._scopeName + ".io.iframe._iframeOnload();");
+		}
+
+		//Set up the deferred.
+		var dfd = dojo._ioSetArgs(
+			args,
+			function(/*Deferred*/dfd){
+				//summary: canceller function for dojo._ioSetArgs call.
+				dfd.canceled = true;
+				dfd.ioArgs._callNext();
+			},
+			function(/*Deferred*/dfd){
+				//summary: okHandler function for dojo._ioSetArgs call.
+				var value = null;
+				try{
+					var ioArgs = dfd.ioArgs;
+					var dii = dojo.io.iframe;
+					var ifd = dii.doc(dii._frame);
+					var handleAs = ioArgs.handleAs;
+
+					//Assign correct value based on handleAs value.
+					value = ifd; //html
+					if(handleAs != "html"){
+						if(handleAs == "xml"){
+							//	FF, Saf 3+ and Opera all seem to be fine with ifd being xml.  We have to
+							//	do it manually for IE.  Refs #6334.
+							if(dojo.isIE){
+								dojo.query("a", dii._frame.contentWindow.document.documentElement).orphan();
+								var xmlText=(dii._frame.contentWindow.document).documentElement.innerText;
+								xmlText=xmlText.replace(/>\s+</g, "><");
+								xmlText=dojo.trim(xmlText);
+								//Reusing some code in base dojo for handling XML content.  Simpler and keeps
+								//Core from duplicating the effort needed to locate the XML Parser on IE.
+								var fauxXhr = { responseText: xmlText };
+								value = dojo._contentHandlers["xml"](fauxXhr); // DOMDocument
+							}
+						}else{
+							value = ifd.getElementsByTagName("textarea")[0].value; //text
+							if(handleAs == "json"){
+								value = dojo.fromJson(value); //json
+							}else if(handleAs == "javascript"){
+								value = dojo.eval(value); //javascript
+							}
+						}
+					}
+				}catch(e){
+					value = e;
+				}finally{
+					ioArgs._callNext();				
+				}
+				return value;
+			},
+			function(/*Error*/error, /*Deferred*/dfd){
+				//summary: errHandler function for dojo._ioSetArgs call.
+				dfd.ioArgs._hasError = true;
+				dfd.ioArgs._callNext();
+				return error;
+			}
+		);
+
+		//Set up a function that will fire the next iframe request. Make sure it only
+		//happens once per deferred.
+		dfd.ioArgs._callNext = function(){
+			if(!this["_calledNext"]){
+				this._calledNext = true;
+				dojo.io.iframe._currentDfd = null;
+				dojo.io.iframe._fireNextRequest();
+			}
+		}
+
+		this._dfdQueue.push(dfd);
+		this._fireNextRequest();
+		
+		//Add it the IO watch queue, to get things like timeout support.
+		dojo._ioWatch(
+			dfd,
+			function(/*Deferred*/dfd){
+				//validCheck
+				return !dfd.ioArgs["_hasError"];
+			},
+			function(dfd){
+				//ioCheck
+				return (!!dfd.ioArgs["_finished"]);
+			},
+			function(dfd){
+				//resHandle
+				if(dfd.ioArgs._finished){
+					dfd.callback(dfd);
+				}else{
+					dfd.errback(new Error("Invalid dojo.io.iframe request state"));
+				}
+			}
+		);
+
+		return dfd;
+	},
+
+	_currentDfd: null,
+	_dfdQueue: [],
+	_iframeName: dojo._scopeName + "IoIframe",
+
+	_fireNextRequest: function(){
+		//summary: Internal method used to fire the next request in the bind queue.
+		try{
+			if((this._currentDfd)||(this._dfdQueue.length == 0)){ return; }
+			//Find next deferred, skip the canceled ones.
+			do{
+				var dfd = this._currentDfd = this._dfdQueue.shift();
+			} while(dfd && dfd.canceled && this._dfdQueue.length);
+
+			//If no more dfds, cancel.
+			if(!dfd || dfd.canceled){
+				this._currentDfd =  null;
+				return;
+			}
+
+			var ioArgs = dfd.ioArgs;
+			var args = ioArgs.args;
+
+			ioArgs._contentToClean = [];
+			var fn = dojo.byId(args["form"]);
+			var content = args["content"] || {};
+			if(fn){
+				if(content){
+					// if we have things in content, we need to add them to the form
+					// before submission
+					var pHandler = function(name, value) {
+						var tn;
+						if(dojo.isIE){
+							tn = dojo.doc.createElement("<input type='hidden' name='"+name+"'>");
+						}else{
+							tn = dojo.doc.createElement("input");
+							tn.type = "hidden";
+							tn.name = name;
+						}
+						tn.value = value;
+						fn.appendChild(tn);
+						ioArgs._contentToClean.push(name);
+					};
+					for(var x in content){
+						var val = content[x];
+						if(dojo.isArray(val) && val.length > 1){
+							var i;
+							for (i = 0; i < val.length; i++) {
+								pHandler(x,val[i]);
+							}
+						}else{
+							if(!fn[x]){
+								pHandler(x,val);
+							}else{
+								fn[x].value = val;
+							}
+						}
+					}
+				}
+				//IE requires going through getAttributeNode instead of just getAttribute in some form cases, 
+				//so use it for all.  See #2844
+				var actnNode = fn.getAttributeNode("action");
+				var mthdNode = fn.getAttributeNode("method");
+				var trgtNode = fn.getAttributeNode("target");
+				if(args["url"]){
+					ioArgs._originalAction = actnNode ? actnNode.value : null;
+					if(actnNode){
+						actnNode.value = args.url;
+					}else{
+						fn.setAttribute("action",args.url);
+					}
+				}
+				if(!mthdNode || !mthdNode.value){
+					if(mthdNode){
+						mthdNode.value= (args["method"]) ? args["method"] : "post";
+					}else{
+						fn.setAttribute("method", (args["method"]) ? args["method"] : "post");
+					}
+				}
+				ioArgs._originalTarget = trgtNode ? trgtNode.value: null;
+				if(trgtNode){
+					trgtNode.value = this._iframeName;
+				}else{
+					fn.setAttribute("target", this._iframeName);
+				}
+				fn.target = this._iframeName;
+				dojo._ioNotifyStart(dfd);
+				fn.submit();
+			}else{
+				// otherwise we post a GET string by changing URL location for the
+				// iframe
+				var tmpUrl = args.url + (args.url.indexOf("?") > -1 ? "&" : "?") + ioArgs.query;
+				dojo._ioNotifyStart(dfd);
+				this.setSrc(this._frame, tmpUrl, true);
+			}
+		}catch(e){
+			dfd.errback(e);
+		}
+	},
+
+	_iframeOnload: function(){
+		var dfd = this._currentDfd;
+		if(!dfd){
+			this._fireNextRequest();
+			return;
+		}
+
+		var ioArgs = dfd.ioArgs;
+		var args = ioArgs.args;
+		var fNode = dojo.byId(args.form);
+	
+		if(fNode){
+			// remove all the hidden content inputs
+			var toClean = ioArgs._contentToClean;
+			for(var i = 0; i < toClean.length; i++) {
+				var key = toClean[i];
+				//Need to cycle over all nodes since we may have added
+				//an array value which means that more than one node could
+				//have the same .name value.
+				for(var j = 0; j < fNode.childNodes.length; j++){
+					var chNode = fNode.childNodes[j];
+					if(chNode.name == key){
+						dojo.destroy(chNode);
+						break;
+					}
+				}
+			}
+
+			// restore original action + target
+			if(ioArgs["_originalAction"]){
+				fNode.setAttribute("action", ioArgs._originalAction);
+			}
+			if(ioArgs["_originalTarget"]){
+				fNode.setAttribute("target", ioArgs._originalTarget);
+				fNode.target = ioArgs._originalTarget;
+			}
+		}
+
+		ioArgs._finished = true;
+	}
 }
diff --git a/dojo/io/script.js b/dojo/io/script.js
index c173d87..2265c1b 100644
--- a/dojo/io/script.js
+++ b/dojo/io/script.js
@@ -1,118 +1,249 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.io.script"]){
-dojo._hasResource["dojo.io.script"]=true;
 dojo.provide("dojo.io.script");
-(function(){
-var _1=dojo.isIE?"onreadystatechange":"load",_2=/complete|loaded/;
-dojo.io.script={get:function(_3){
-var _4=this._makeScriptDeferred(_3);
-var _5=_4.ioArgs;
-dojo._ioAddQueryToUrl(_5);
-dojo._ioNotifyStart(_4);
-if(this._canAttach(_5)){
-var _6=this.attach(_5.id,_5.url,_3.frameDoc);
-if(!_5.jsonp&&!_5.args.checkString){
-var _7=dojo.connect(_6,_1,function(_8){
-if(_8.type=="load"||_2.test(_6.readyState)){
-dojo.disconnect(_7);
-_5.scriptLoaded=_8;
-}
+
+/*=====
+dojo.declare("dojo.io.script.__ioArgs", dojo.__IoArgs, {
+	constructor: function(){
+		//	summary:
+		//		All the properties described in the dojo.__ioArgs type, apply to this
+		//		type as well, EXCEPT "handleAs". It is not applicable to
+		//		dojo.io.script.get() calls, since it is implied by the usage of
+		//		"jsonp" (response will be a JSONP call returning JSON)
+		//		or the response is pure JavaScript defined in
+		//		the body of the script that was attached.
+		//	callbackParamName: String
+		//		Deprecated as of Dojo 1.4 in favor of "jsonp", but still supported for
+		// 		legacy code. See notes for jsonp property.
+		//	jsonp: String
+		//		The URL parameter name that indicates the JSONP callback string.
+		//		For instance, when using Yahoo JSONP calls it is normally, 
+		//		jsonp: "callback". For AOL JSONP calls it is normally 
+		//		jsonp: "c".
+		//	checkString: String
+		//		A string of JavaScript that when evaluated like so: 
+		//		"typeof(" + checkString + ") != 'undefined'"
+		//		being true means that the script fetched has been loaded. 
+		//		Do not use this if doing a JSONP type of call (use callbackParamName instead).
+		//	frameDoc: Document
+		//		The Document object for a child iframe. If this is passed in, the script
+		//		will be attached to that document. This can be helpful in some comet long-polling
+		//		scenarios with Firefox and Opera.
+		this.callbackParamName = callbackParamName;
+		this.jsonp = jsonp;
+		this.checkString = checkString;
+		this.frameDoc = frameDoc;
+	}
 });
-}
-}
-dojo._ioWatch(_4,this._validCheck,this._ioCheck,this._resHandle);
-return _4;
-},attach:function(id,_9,_a){
-var _b=(_a||dojo.doc);
-var _c=_b.createElement("script");
-_c.type="text/javascript";
-_c.src=_9;
-_c.id=id;
-_c.charset="utf-8";
-return _b.getElementsByTagName("head")[0].appendChild(_c);
-},remove:function(id,_d){
-dojo.destroy(dojo.byId(id,_d));
-if(this["jsonp_"+id]){
-delete this["jsonp_"+id];
-}
-},_makeScriptDeferred:function(_e){
-var _f=dojo._ioSetArgs(_e,this._deferredCancel,this._deferredOk,this._deferredError);
-var _10=_f.ioArgs;
-_10.id=dojo._scopeName+"IoScript"+(this._counter++);
-_10.canDelete=false;
-_10.jsonp=_e.callbackParamName||_e.jsonp;
-if(_10.jsonp){
-_10.query=_10.query||"";
-if(_10.query.length>0){
-_10.query+="&";
-}
-_10.query+=_10.jsonp+"="+(_e.frameDoc?"parent.":"")+dojo._scopeName+".io.script.jsonp_"+_10.id+"._jsonpCallback";
-_10.frameDoc=_e.frameDoc;
-_10.canDelete=true;
-_f._jsonpCallback=this._jsonpCallback;
-this["jsonp_"+_10.id]=_f;
-}
-return _f;
-},_deferredCancel:function(dfd){
-dfd.canceled=true;
-if(dfd.ioArgs.canDelete){
-dojo.io.script._addDeadScript(dfd.ioArgs);
-}
-},_deferredOk:function(dfd){
-var _11=dfd.ioArgs;
-if(_11.canDelete){
-dojo.io.script._addDeadScript(_11);
-}
-return _11.json||_11.scriptLoaded||_11;
-},_deferredError:function(_12,dfd){
-if(dfd.ioArgs.canDelete){
-if(_12.dojoType=="timeout"){
-dojo.io.script.remove(dfd.ioArgs.id,dfd.ioArgs.frameDoc);
-}else{
-dojo.io.script._addDeadScript(dfd.ioArgs);
-}
-}
-return _12;
-},_deadScripts:[],_counter:1,_addDeadScript:function(_13){
-dojo.io.script._deadScripts.push({id:_13.id,frameDoc:_13.frameDoc});
-_13.frameDoc=null;
-},_validCheck:function(dfd){
-var _14=dojo.io.script;
-var _15=_14._deadScripts;
-if(_15&&_15.length>0){
-for(var i=0;i<_15.length;i++){
-_14.remove(_15[i].id,_15[i].frameDoc);
-_15[i].frameDoc=null;
-}
-dojo.io.script._deadScripts=[];
-}
-return true;
-},_ioCheck:function(dfd){
-var _16=dfd.ioArgs;
-if(_16.json||(_16.scriptLoaded&&!_16.args.checkString)){
-return true;
-}
-var _17=_16.args.checkString;
-if(_17&&eval("typeof("+_17+") != 'undefined'")){
-return true;
-}
-return false;
-},_resHandle:function(dfd){
-if(dojo.io.script._ioCheck(dfd)){
-dfd.callback(dfd);
-}else{
-dfd.errback(new Error("inconceivable dojo.io.script._resHandle error"));
-}
-},_canAttach:function(_18){
-return true;
-},_jsonpCallback:function(_19){
-this.ioArgs.json=_19;
-}};
-})();
-}
+=====*/
+;(function(){
+	var loadEvent = dojo.isIE ? "onreadystatechange" : "load",
+		readyRegExp = /complete|loaded/;
+
+	dojo.io.script = {
+		get: function(/*dojo.io.script.__ioArgs*/args){
+			//	summary:
+			//		sends a get request using a dynamically created script tag.
+			var dfd = this._makeScriptDeferred(args);
+			var ioArgs = dfd.ioArgs;
+			dojo._ioAddQueryToUrl(ioArgs);
+	
+			dojo._ioNotifyStart(dfd);
+
+			if(this._canAttach(ioArgs)){
+				var node = this.attach(ioArgs.id, ioArgs.url, args.frameDoc);
+
+				//If not a jsonp callback or a polling checkString case, bind
+				//to load event on the script tag.
+				if(!ioArgs.jsonp && !ioArgs.args.checkString){
+					var handle = dojo.connect(node, loadEvent, function(evt){
+						if(evt.type == "load" || readyRegExp.test(node.readyState)){
+							dojo.disconnect(handle);
+							ioArgs.scriptLoaded = evt;
+						}
+					});
+				}
+			}
+
+			dojo._ioWatch(dfd, this._validCheck, this._ioCheck, this._resHandle);
+			return dfd;
+		},
+	
+		attach: function(/*String*/id, /*String*/url, /*Document?*/frameDocument){
+			//	summary:
+			//		creates a new <script> tag pointing to the specified URL and
+			//		adds it to the document.
+			//	description:
+			//		Attaches the script element to the DOM.  Use this method if you
+			//		just want to attach a script to the DOM and do not care when or
+			//		if it loads.
+			var doc = (frameDocument || dojo.doc);
+			var element = doc.createElement("script");
+			element.type = "text/javascript";
+			element.src = url;
+			element.id = id;
+			element.charset = "utf-8";
+			return doc.getElementsByTagName("head")[0].appendChild(element);
+		},
+	
+		remove: function(/*String*/id, /*Document?*/frameDocument){
+			//summary: removes the script element with the given id, from the given frameDocument.
+			//If no frameDocument is passed, the current document is used.
+			dojo.destroy(dojo.byId(id, frameDocument));
+			
+			//Remove the jsonp callback on dojo.io.script, if it exists.
+			if(this["jsonp_" + id]){
+				delete this["jsonp_" + id];
+			}
+		},
+	
+		_makeScriptDeferred: function(/*Object*/args){
+			//summary: 
+			//		sets up a Deferred object for an IO request.
+			var dfd = dojo._ioSetArgs(args, this._deferredCancel, this._deferredOk, this._deferredError);
+	
+			var ioArgs = dfd.ioArgs;
+			ioArgs.id = dojo._scopeName + "IoScript" + (this._counter++);
+			ioArgs.canDelete = false;
+	
+			//Special setup for jsonp case
+			ioArgs.jsonp = args.callbackParamName || args.jsonp;
+			if(ioArgs.jsonp){
+				//Add the jsonp parameter.
+				ioArgs.query = ioArgs.query || "";
+				if(ioArgs.query.length > 0){
+					ioArgs.query += "&";
+				}
+				ioArgs.query += ioArgs.jsonp
+					+ "="
+					+ (args.frameDoc ? "parent." : "")
+					+ dojo._scopeName + ".io.script.jsonp_" + ioArgs.id + "._jsonpCallback";
+	
+				ioArgs.frameDoc = args.frameDoc;
+	
+				//Setup the Deferred to have the jsonp callback.
+				ioArgs.canDelete = true;
+				dfd._jsonpCallback = this._jsonpCallback;
+				this["jsonp_" + ioArgs.id] = dfd;
+			}
+			return dfd; // dojo.Deferred
+		},
+		
+		_deferredCancel: function(/*Deferred*/dfd){
+			//summary: canceller function for dojo._ioSetArgs call.
+	
+			//DO NOT use "this" and expect it to be dojo.io.script.
+			dfd.canceled = true;
+			if(dfd.ioArgs.canDelete){
+				dojo.io.script._addDeadScript(dfd.ioArgs);
+			}
+		},
+	
+		_deferredOk: function(/*Deferred*/dfd){
+			//summary: okHandler function for dojo._ioSetArgs call.
+	
+			//DO NOT use "this" and expect it to be dojo.io.script.
+			var ioArgs = dfd.ioArgs;
+	
+			//Add script to list of things that can be removed.		
+			if(ioArgs.canDelete){
+				dojo.io.script._addDeadScript(ioArgs);
+			}
+	
+			//Favor JSONP responses, script load events then lastly ioArgs.
+			//The ioArgs are goofy, but cannot return the dfd since that stops
+			//the callback chain in Deferred. The return value is not that important
+			//in that case, probably a checkString case.
+			return ioArgs.json || ioArgs.scriptLoaded || ioArgs;
+		},
+	
+		_deferredError: function(/*Error*/error, /*Deferred*/dfd){
+			//summary: errHandler function for dojo._ioSetArgs call.
+	
+			if(dfd.ioArgs.canDelete){
+				//DO NOT use "this" and expect it to be dojo.io.script.
+				if(error.dojoType == "timeout"){
+					//For timeouts, remove the script element immediately to
+					//avoid a response from it coming back later and causing trouble.
+					dojo.io.script.remove(dfd.ioArgs.id, dfd.ioArgs.frameDoc);
+				}else{
+					dojo.io.script._addDeadScript(dfd.ioArgs);
+				}
+			}
+			console.log("dojo.io.script error", error);
+			return error;
+		},
+	
+		_deadScripts: [],
+		_counter: 1,
+	
+		_addDeadScript: function(/*Object*/ioArgs){
+			//summary: sets up an entry in the deadScripts array.
+			dojo.io.script._deadScripts.push({id: ioArgs.id, frameDoc: ioArgs.frameDoc});
+			//Being extra paranoid about leaks:
+			ioArgs.frameDoc = null;
+		},
+	
+		_validCheck: function(/*Deferred*/dfd){
+			//summary: inflight check function to see if dfd is still valid.
+	
+			//Do script cleanup here. We wait for one inflight pass
+			//to make sure we don't get any weird things by trying to remove a script
+			//tag that is part of the call chain (IE 6 has been known to
+			//crash in that case).
+			var _self = dojo.io.script;
+			var deadScripts = _self._deadScripts;
+			if(deadScripts && deadScripts.length > 0){
+				for(var i = 0; i < deadScripts.length; i++){
+					//Remove the script tag
+					_self.remove(deadScripts[i].id, deadScripts[i].frameDoc);
+					deadScripts[i].frameDoc = null;
+				}
+				dojo.io.script._deadScripts = [];
+			}
+	
+			return true;
+		},
+	
+		_ioCheck: function(/*Deferred*/dfd){
+			//summary: inflight check function to see if IO finished.
+			var ioArgs = dfd.ioArgs;
+			//Check for finished jsonp
+			if(ioArgs.json || (ioArgs.scriptLoaded && !ioArgs.args.checkString)){
+				return true;
+			}
+	
+			//Check for finished "checkString" case.
+			var checkString = ioArgs.args.checkString;
+			if(checkString && eval("typeof(" + checkString + ") != 'undefined'")){
+				return true;
+			}
+	
+			return false;
+		},
+	
+		_resHandle: function(/*Deferred*/dfd){
+			//summary: inflight function to handle a completed response.
+			if(dojo.io.script._ioCheck(dfd)){
+				dfd.callback(dfd);
+			}else{
+				//This path should never happen since the only way we can get
+				//to _resHandle is if _ioCheck is true.
+				dfd.errback(new Error("inconceivable dojo.io.script._resHandle error"));
+			}
+		},
+	
+		_canAttach: function(/*Object*/ioArgs){
+			//summary: A method that can be overridden by other modules
+			//to control when the script attachment occurs.
+			return true;
+		},
+		
+		_jsonpCallback: function(/*JSON Object*/json){
+			//summary: 
+			//		generic handler for jsonp callback. A pointer to this function
+			//		is used for all jsonp callbacks.  NOTE: the "this" in this
+			//		function will be the Deferred object that represents the script
+			//		request.
+			this.ioArgs.json = json;
+		}
+	}
+})();
\ No newline at end of file
diff --git a/dojo/jaxer.js b/dojo/jaxer.js
index 43d8fce..feffcad 100644
--- a/dojo/jaxer.js
+++ b/dojo/jaxer.js
@@ -1,19 +1,11 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.jaxer"]){
-dojo._hasResource["dojo.jaxer"]=true;
 dojo.provide("dojo.jaxer");
-if(typeof print=="function"){
-console.debug=Jaxer.Log.debug;
-console.warn=Jaxer.Log.warn;
-console.error=Jaxer.Log.error;
-console.info=Jaxer.Log.info;
-console.log=Jaxer.Log.warn;
-}
-onserverload=dojo._loadInit;
+
+if(typeof print == "function"){
+	console.debug = Jaxer.Log.debug;
+	console.warn = Jaxer.Log.warn;
+	console.error = Jaxer.Log.error;
+	console.info = Jaxer.Log.info;
+	console.log = Jaxer.Log.warn;
 }
+
+onserverload = dojo._loadInit;
diff --git a/dojo/nls/ar/colors.js b/dojo/nls/ar/colors.js
index 50e4a12..a3306c6 100644
--- a/dojo/nls/ar/colors.js
+++ b/dojo/nls/ar/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"أزرق معدني فاتح","orangered":"أحمر مائل للبرتقالي","midnightblue":"أزرق بحري","cadetblue":"أزرق ملون بالرمادي","seashell":"أبيض مائل للأصفر فاتح","slategrey":"رمادي اردوازي","coral":"مرجاني","darkturquoise":"تركواز داكن","antiquewhite":"أبيض عتيق","mediumspringgreen":"أخضر ربيعي متوسط","salmon":"برتقالي وردي شاحب","darkgrey":"رمادي داكن","ivory":"عاجي","greenyellow":"أخضر مائل للأصفر","mistyrose":"وردي","lightsalmon":"فضي فاتح","silver":"فضي","dimgrey":"رمادي شاحب","o [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "أزرق فاتح",
+antiquewhite: "أبيض عتيق",
+aqua: "أزرق مائي",
+aquamarine: "أزرق مائل للأخضر (زبرجد)",
+azure: "أزرق سماوي",
+beige: "بيج",
+bisque: "أصفر برتقالي الى رمادي مصفر",
+black: "أسود",
+blanchedalmond: "أخضر مائل للبياض",
+blue: "أزرق",
+blueviolet: "أزرق-بنفسجي",
+brown: "بني",
+burlywood: "خشبي",
+cadetblue: "أزرق ملون بالرمادي",
+chartreuse: "أخضر مائل للصفرة",
+chocolate: "بني غامق",
+coral: "مرجاني",
+cornflowerblue: "أزرق عنبري",
+cornsilk: "حريري",
+crimson: "قرمزي",
+cyan: "أزرق سماوي",
+darkblue: "أزرق داكن",
+darkcyan: "أزرق سماوي داكن",
+darkgoldenrod: "أصفر ذهبي داكن",
+darkgray: "رمادي داكن",
+darkgreen: "أخضر داكن",
+darkgrey: "رمادي داكن", // same as darkgray
+darkkhaki: "كاكي داكن",
+darkmagenta: "قرمزي داكن",
+darkolivegreen: "أخضر زيتوني داكن",
+darkorange: "برتقالي داكن",
+darkorchid: "أرجواني داكن",
+darkred: "أحمر داكن",
+darksalmon: "فضي داكن",
+darkseagreen: "أخضر مائل للأزرق داكن",
+darkslateblue: "أزرق اردوازي داكن",
+darkslategray: "رمادي اردوازي داكن",
+darkslategrey: "رمادي اردوازي داكن", // same as darkslategray
+darkturquoise: "تركواز داكن",
+darkviolet: "بنفسجي داكن",
+deeppink: "أحمر وردي غامق",
+deepskyblue: "أزرق سماوي غامق",
+dimgray: "رمادي شاحب",
+dimgrey: "رمادي شاحب", // same as dimgray
+dodgerblue: "أزرق عنبري",
+firebrick: "أصفر زاهي",
+floralwhite: "أبيض زهري",
+forestgreen: "أخضر بلون أشجار الغابات",
+fuchsia: "فوشيا",
+gainsboro: "رمادي مائل للأزرق فاتح",
+ghostwhite: "أبيض شفاف",
+gold: "ذهبي",
+goldenrod: "أصفر ذهبي",
+gray: "رمادي",
+green: "أخضر",
+greenyellow: "أخضر مائل للأصفر",
+grey: "رمادي", // same as gray
+honeydew: "أبيض مائل للأخضر",
+hotpink: "أحمر وردي زاهي",
+indianred: "أحمر هندي",
+indigo: "نيلي",
+ivory: "عاجي",
+khaki: "كاكي",
+lavender: "أرجواني شاحب",
+lavenderblush: "أحمر أرجواني",
+lawngreen: "أخضر بلون العشب",
+lemonchiffon: "أصفر شفاف",
+lightblue: "أزرق فاتح",
+lightcoral: "مرجاني فاتح",
+lightcyan: "سماوي فاتح",
+lightgoldenrodyellow: "أصفر ذهبي فاتح",
+lightgray: "رمادي فاتح",
+lightgreen: "أخضر فاتح",
+lightgrey: "رمادي فاتح", // same as lightgray
+lightpink: "وردي فاتح",
+lightsalmon: "فضي فاتح",
+lightseagreen: "أخضر مائل للأزرق فاتح",
+lightskyblue: "أزرق سماوي فاتح",
+lightslategray: "رمادي اردوازي فاتح",
+lightslategrey: "رمادي اردوازي فاتح", // same as lightslategray
+lightsteelblue: "أزرق معدني فاتح",
+lightyellow: "أصفر فاتح",
+lime: "ليموني",
+limegreen: "أخضر ليموني",
+linen: "كتاني",
+magenta: "أحمر قرمزي",
+maroon: "أحمر داكن",
+mediumaquamarine: "أزرق مائل للأخضر (زبرجد) متوسط",
+mediumblue: "أزرق متوسط",
+mediumorchid: "أرجواني متوسط",
+mediumpurple: "قرمزي متوسط",
+mediumseagreen: "أخضر مائل للأزرق متوسط",
+mediumslateblue: "أزرق اردوازي متوسط",
+mediumspringgreen: "أخضر ربيعي متوسط",
+mediumturquoise: "تركواز متوسط",
+mediumvioletred: "أحمر-بنفسجي متوسط",
+midnightblue: "أزرق بحري",
+mintcream: "أصفر شاحب مائل للأخضر الزرعي",
+mistyrose: "وردي",
+moccasin: "نحاسي أحمر",
+navajowhite: "أبيض ملاحي",
+navy: "أزرق داكن",
+oldlace: "برتقالي مائل للأصفر شاحب",
+olive: "أخضر زيتوني داكن",
+olivedrab: "أسود فاتح",
+orange: "برتقالي",
+orangered: "أحمر مائل للبرتقالي",
+orchid: "أرجواني فاتح",
+palegoldenrod: "أصفر ذهبي شاحب",
+palegreen: "أخضر شاحب",
+paleturquoise: "تركواز شاحب",
+palevioletred: "أحمر-بنفسجي شاحب",
+papayawhip: "خوخي فاتح",
+peachpuff: "خوخي مائل للأصفر",
+peru: "بني جملي",
+pink: "وردي",
+plum: "أرجواني داكن",
+powderblue: "أزرق مائل للأصفر",
+purple: "ارجواني",
+red: "أحمر",
+rosybrown: "بني وردي",
+royalblue: "أزرق ملكي",
+saddlebrown: "بني فاتح",
+salmon: "برتقالي وردي شاحب",
+sandybrown: "بني مائل للصفرة",
+seagreen: "أخضر مائل للأزرق",
+seashell: "أبيض مائل للأصفر فاتح",
+sienna: "بني محروق",
+silver: "فضي",
+skyblue: "أزرق سماوي",
+slateblue: "أزرق اردوازي",
+slategray: "رمادي اردوازي",
+slategrey: "رمادي اردوازي", // same as slategray
+snow: "أبيض ثلجي",
+springgreen: "أخضر ربيعي",
+steelblue: "أزرق معدني",
+tan: "خمري",
+teal: "بترولي",
+thistle: "ارجواني شاحب",
+tomato: "أحمر مائل للأصفر",
+turquoise: "تركواز",
+violet: "بنفسجي",
+wheat: "أخضر قمحي",
+white: "أبيض",
+whitesmoke: "دخان أبيض",
+yellow: "أصفر",
+yellowgreen: "أخضر مائل للأصفر"
+})
diff --git a/dojo/nls/ca/colors.js b/dojo/nls/ca/colors.js
index 0f1461a..656402f 100644
--- a/dojo/nls/ca/colors.js
+++ b/dojo/nls/ca/colors.js
@@ -1 +1,155 @@
-({"lightsteelblue":"blau acer clar","orangered":"taronja vermellós","midnightblue":"blau mitjanit","cadetblue":"blau marí","seashell":"petxina marina","slategrey":"gris pissarra","coral":"corall","darkturquoise":"turquesa fosc","antiquewhite":"blanc antic","mediumspringgreen":"verd primavera mitjà","salmon":"salmó","darkgrey":"gris fosc","ivory":"marbre","greenyellow":"verd grogós","mistyrose":"rosa dens","lightsalmon":"salmó clar","silver":"argent","dimgrey":"gris fosc","orange":"taronj [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "blau cian clar",
+antiquewhite: "blanc antic",
+aqua: "aigua",
+aquamarine: "aiguamarina",
+azure: "atzur",
+beige: "beix",
+bisque: "crema",
+black: "negre",
+blanchedalmond: "ametlla pàl·lid",
+blue: "blau",
+blueviolet: "blau violeta",
+brown: "marró",
+burlywood: "marró arenós",
+cadetblue: "blau marí",
+chartreuse: "Llimona pàl·lid",
+chocolate: "xocolata",
+coral: "corall",
+cornflowerblue: "blau blauet",
+cornsilk: "cru",
+crimson: "carmesí",
+cyan: "cian",
+darkblue: "blau fosc",
+darkcyan: "cian fosc",
+darkgoldenrod: "ocre fosc",
+darkgray: "gris fosc",
+darkgreen: "verd fosc",
+darkgrey: "gris fosc", // same as darkgray
+darkkhaki: "caqui fosc",
+darkmagenta: "magenta fosc",
+darkolivegreen: "verd oliva fosc",
+darkorange: "taronja fosc",
+darkorchid: "orquídia fosc",
+darkred: "vermell fosc",
+darksalmon: "salmó fosc",
+darkseagreen: "verd marí fosc",
+darkslateblue: "blau pissarra fosc",
+darkslategray: "gris pissarra fosc",
+darkslategrey: "gris pissarra fosc", // same as darkslategray
+darkturquoise: "turquesa fosc",
+darkviolet: "violeta fosc",
+deeppink: "rosa profund",
+deepskyblue: "blau cel profund",
+dimgray: "gris fosc",
+dimgrey: "gris fosc", // same as dimgray
+dodgerblue: "blau Dodger",
+firebrick: "maó refractari",
+floralwhite: "blanc floral",
+forestgreen: "verd bosc",
+fuchsia: "fúcsia",
+gainsboro: "gainsboro",
+ghostwhite: "blanc fantasma",
+gold: "daurat",
+goldenrod: "ocre",
+gray: "gris",
+green: "verd",
+greenyellow: "verd grogós",
+grey: "gris", // same as gray
+honeydew: "rosada de mel",
+hotpink: "rosa fúcsia",
+indianred: "vermell indi",
+indigo: "índigo",
+ivory: "marbre",
+khaki: "caqui",
+lavender: "lavanda",
+lavenderblush: "lavanda vermellosa",
+lawngreen: "verd gespa",
+lemonchiffon: "groc brisa",
+lightblue: "blau clar",
+lightcoral: "corall clar",
+lightcyan: "cian clar",
+lightgoldenrodyellow: "groc ocre clar",
+lightgray: "gris clar",
+lightgreen: "verd clar",
+lightgrey: "gris clar", // same as lightgray
+lightpink: "rosa clar",
+lightsalmon: "salmó clar",
+lightseagreen: "verd marí clar",
+lightskyblue: "blau cel clar",
+lightslategray: "gris pissarra clar",
+lightslategrey: "gris pissarra clar", // same as lightslategray
+lightsteelblue: "blau acer clar",
+lightyellow: "groc clar",
+lime: "verd llimona",
+limegreen: "verd llimona verda",
+linen: "lli",
+magenta: "magenta",
+maroon: "marró vermellós",
+mediumaquamarine: "aiguamarina mitjana",
+mediumblue: "blau mitjà",
+mediumorchid: "orquídia mitjana",
+mediumpurple: "porpra mitjana",
+mediumseagreen: "verd marí mitjà",
+mediumslateblue: "blau pissarra mitjà",
+mediumspringgreen: "verd primavera mitjà",
+mediumturquoise: "turquesa mitjana",
+mediumvioletred: "vermell violeta mitjà",
+midnightblue: "blau mitjanit",
+mintcream: "menta pàl·lid",
+mistyrose: "rosa dens",
+moccasin: "mocassí",
+navajowhite: "blanc Navajo",
+navy: "blau marí",
+oldlace: "rosa cremós",
+olive: "oliva",
+olivedrab: "gris oliva",
+orange: "taronja",
+orangered: "taronja vermellós",
+orchid: "orquídia",
+palegoldenrod: "ocre pàl·lid",
+palegreen: "verd pàl·lid",
+paleturquoise: "turquesa pàl·lid",
+palevioletred: "vermell porpra pàl·lid",
+papayawhip: "préssec pastel",
+peachpuff: "préssec",
+peru: "Perú",
+pink: "rosa",
+plum: "pruna",
+powderblue: "blau grisós",
+purple: "porpra",
+red: "vermell",
+rosybrown: "marró rosat",
+royalblue: "blau marí intens",
+saddlebrown: "marró mitjà",
+salmon: "salmó",
+sandybrown: "marró arenós",
+seagreen: "verd marí",
+seashell: "petxina marina",
+sienna: "siena",
+silver: "argent",
+skyblue: "blau cel",
+slateblue: "blau pissarra",
+slategray: "gris pissarra",
+slategrey: "gris pissarra", // same as slategray
+snow: "neu",
+springgreen: "verd de primavera",
+steelblue: "blau acer",
+tan: "tan",
+teal: "verd blavós",
+thistle: "card",
+tomato: "tomàquet",
+turquoise: "turquesa",
+violet: "violeta",
+wheat: "blat",
+white: "blanc",
+whitesmoke: "blanc fumat",
+yellow: "groc",
+yellowgreen: "verd grogós"
+})
+
diff --git a/dojo/nls/colors.js b/dojo/nls/colors.js
index 454e644..07562cc 100644
--- a/dojo/nls/colors.js
+++ b/dojo/nls/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"light steel blue","orangered":"orange red","midnightblue":"midnight blue","cadetblue":"cadet blue","seashell":"seashell","slategrey":"slate gray","coral":"coral","darkturquoise":"dark turquoise","antiquewhite":"antique white","mediumspringgreen":"medium spring green","salmon":"salmon","darkgrey":"dark gray","ivory":"ivory","greenyellow":"green-yellow","mistyrose":"misty rose","lightsalmon":"light salmon","silver":"silver","dimgrey":"dim gray","orange":"orange","white" [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "alice blue",
+antiquewhite: "antique white",
+aqua: "aqua",
+aquamarine: "aquamarine",
+azure: "azure",
+beige: "beige",
+bisque: "bisque",
+black: "black",
+blanchedalmond: "blanched almond",
+blue: "blue",
+blueviolet: "blue-violet",
+brown: "brown",
+burlywood: "burlywood",
+cadetblue: "cadet blue",
+chartreuse: "chartreuse",
+chocolate: "chocolate",
+coral: "coral",
+cornflowerblue: "cornflower blue",
+cornsilk: "cornsilk",
+crimson: "crimson",
+cyan: "cyan",
+darkblue: "dark blue",
+darkcyan: "dark cyan",
+darkgoldenrod: "dark goldenrod",
+darkgray: "dark gray",
+darkgreen: "dark green",
+darkgrey: "dark gray", // same as darkgray
+darkkhaki: "dark khaki",
+darkmagenta: "dark magenta",
+darkolivegreen: "dark olive green",
+darkorange: "dark orange",
+darkorchid: "dark orchid",
+darkred: "dark red",
+darksalmon: "dark salmon",
+darkseagreen: "dark sea green",
+darkslateblue: "dark slate blue",
+darkslategray: "dark slate gray",
+darkslategrey: "dark slate gray", // same as darkslategray
+darkturquoise: "dark turquoise",
+darkviolet: "dark violet",
+deeppink: "deep pink",
+deepskyblue: "deep sky blue",
+dimgray: "dim gray",
+dimgrey: "dim gray", // same as dimgray
+dodgerblue: "dodger blue",
+firebrick: "fire brick",
+floralwhite: "floral white",
+forestgreen: "forest green",
+fuchsia: "fuchsia",
+gainsboro: "gainsboro",
+ghostwhite: "ghost white",
+gold: "gold",
+goldenrod: "goldenrod",
+gray: "gray",
+green: "green",
+greenyellow: "green-yellow",
+grey: "gray", // same as gray
+honeydew: "honeydew",
+hotpink: "hot pink",
+indianred: "indian red",
+indigo: "indigo",
+ivory: "ivory",
+khaki: "khaki",
+lavender: "lavender",
+lavenderblush: "lavender blush",
+lawngreen: "lawn green",
+lemonchiffon: "lemon chiffon",
+lightblue: "light blue",
+lightcoral: "light coral",
+lightcyan: "light cyan",
+lightgoldenrodyellow: "light goldenrod yellow",
+lightgray: "light gray",
+lightgreen: "light green",
+lightgrey: "light gray", // same as lightgray
+lightpink: "light pink",
+lightsalmon: "light salmon",
+lightseagreen: "light sea green",
+lightskyblue: "light sky blue",
+lightslategray: "light slate gray",
+lightslategrey: "light slate gray", // same as lightslategray
+lightsteelblue: "light steel blue",
+lightyellow: "light yellow",
+lime: "lime",
+limegreen: "lime green",
+linen: "linen",
+magenta: "magenta",
+maroon: "maroon",
+mediumaquamarine: "medium aquamarine",
+mediumblue: "medium blue",
+mediumorchid: "medium orchid",
+mediumpurple: "medium purple",
+mediumseagreen: "medium sea green",
+mediumslateblue: "medium slate blue",
+mediumspringgreen: "medium spring green",
+mediumturquoise: "medium turquoise",
+mediumvioletred: "medium violet-red",
+midnightblue: "midnight blue",
+mintcream: "mint cream",
+mistyrose: "misty rose",
+moccasin: "moccasin",
+navajowhite: "navajo white",
+navy: "navy",
+oldlace: "old lace",
+olive: "olive",
+olivedrab: "olive drab",
+orange: "orange",
+orangered: "orange red",
+orchid: "orchid",
+palegoldenrod: "pale goldenrod",
+palegreen: "pale green",
+paleturquoise: "pale turquoise",
+palevioletred: "pale violet-red",
+papayawhip: "papaya whip",
+peachpuff: "peach puff",
+peru: "peru",
+pink: "pink",
+plum: "plum",
+powderblue: "powder blue",
+purple: "purple",
+red: "red",
+rosybrown: "rosy brown",
+royalblue: "royal blue",
+saddlebrown: "saddle brown",
+salmon: "salmon",
+sandybrown: "sandy brown",
+seagreen: "sea green",
+seashell: "seashell",
+sienna: "sienna",
+silver: "silver",
+skyblue: "sky blue",
+slateblue: "slate blue",
+slategray: "slate gray",
+slategrey: "slate gray", // same as slategray
+snow: "snow",
+springgreen: "spring green",
+steelblue: "steel blue",
+tan: "tan",
+teal: "teal",
+thistle: "thistle",
+tomato: "tomato",
+turquoise: "turquoise",
+violet: "violet",
+wheat: "wheat",
+white: "white",
+whitesmoke: "white smoke",
+yellow: "yellow",
+yellowgreen: "yellow green"
+})
diff --git a/dojo/nls/cs/colors.js b/dojo/nls/cs/colors.js
index 7ae5d30..cd8536c 100644
--- a/dojo/nls/cs/colors.js
+++ b/dojo/nls/cs/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"světlá ocelová modrá","orangered":"oranžovočervená","midnightblue":"temně modrá","cadetblue":"šedomodrá","seashell":"lasturová","slategrey":"břidlicová šedá","coral":"korálová červená","darkturquoise":"tmavě tyrkysová","antiquewhite":"krémově bílá","mediumspringgreen":"střední jarní zelená","salmon":"lososová","darkgrey":"tmavě šedá","ivory":"slonovinová","greenyellow":"zelenožlutá","mistyrose":"růžovobílá","lightsalmon":"světle lososová","silver":"stříbrná","dimgrey" [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "modravá",
+antiquewhite: "krémově bílá",
+aqua: "azurová",
+aquamarine: "akvamarínová",
+azure: "bledě azurová",
+beige: "bledě béžová",
+bisque: "bledě oranžová",
+black: "černá",
+blanchedalmond: "mandlová",
+blue: "modrá",
+blueviolet: "modrofialová",
+brown: "červenohnědá",
+burlywood: "krémová",
+cadetblue: "šedomodrá",
+chartreuse: "chartreuska",
+chocolate: "hnědobéžová",
+coral: "korálová červená",
+cornflowerblue: "chrpově modrá",
+cornsilk: "režná",
+crimson: "karmínová",
+cyan: "azurová",
+darkblue: "tmavě modrá",
+darkcyan: "tmavě azurová",
+darkgoldenrod: "tmavě béžová",
+darkgray: "tmavě šedá",
+darkgreen: "tmavě zelená",
+darkgrey: "tmavě šedá", // same as darkgray
+darkkhaki: "pískově hnědá",
+darkmagenta: "tmavě purpurová",
+darkolivegreen: "tmavě olivová",
+darkorange: "tmavě oranžová",
+darkorchid: "tmavě orchidejová",
+darkred: "tmavě červená",
+darksalmon: "tmavě lososová",
+darkseagreen: "tmavá mořská zelená",
+darkslateblue: "tmavá břidlicová modrá",
+darkslategray: "tmavá břidlicová šedá",
+darkslategrey: "tmavá břidlicová šedá", // same as darkslategray
+darkturquoise: "tmavě tyrkysová",
+darkviolet: "tmavě fialová",
+deeppink: "sytě růžová",
+deepskyblue: "sytá nebeská modrá",
+dimgray: "kouřově šedá",
+dimgrey: "kouřově šedá", // same as dimgray
+dodgerblue: "jasně modrá",
+firebrick: "cihlová",
+floralwhite: "květinově bílá",
+forestgreen: "lesní zelená",
+fuchsia: "fuchsiová",
+gainsboro: "bledě šedá",
+ghostwhite: "modravě bílá",
+gold: "zlatá",
+goldenrod: "béžová",
+gray: "šedá",
+green: "zelená",
+greenyellow: "zelenožlutá",
+grey: "šedá", // same as gray
+honeydew: "nazelenalá",
+hotpink: "jasně růžová",
+indianred: "indiánská červená",
+indigo: "indigově modrá",
+ivory: "slonovinová",
+khaki: "písková",
+lavender: "levandulová",
+lavenderblush: "levandulová růžová",
+lawngreen: "jasně zelená",
+lemonchiffon: "světle citrónová",
+lightblue: "světle modrá",
+lightcoral: "světle korálová",
+lightcyan: "světle azurová",
+lightgoldenrodyellow: "světle žlutá",
+lightgray: "světle šedá",
+lightgreen: "světle zelená",
+lightgrey: "světle šedá", // same as lightgray
+lightpink: "světle růžová",
+lightsalmon: "světle lososová",
+lightseagreen: "světlá mořská zelená",
+lightskyblue: "světlá nebeská modrá",
+lightslategray: "světlá břidlicová šedá",
+lightslategrey: "světlá břidlicová šedá", // same as lightslategray
+lightsteelblue: "světlá ocelová modrá",
+lightyellow: "bledě žlutá",
+lime: "limetková",
+limegreen: "limetkově zelená",
+linen: "bledě šedobéžová",
+magenta: "purpurová",
+maroon: "kaštanová",
+mediumaquamarine: "střední akvamarínová",
+mediumblue: "středně modrá",
+mediumorchid: "středně orchidejová",
+mediumpurple: "středně nachová",
+mediumseagreen: "střední mořská zelená",
+mediumslateblue: "střední břidlicová modrá",
+mediumspringgreen: "střední jarní zelená",
+mediumturquoise: "středně tyrkysová",
+mediumvioletred: "středně fialovočervená",
+midnightblue: "temně modrá",
+mintcream: "mentolová",
+mistyrose: "růžovobílá",
+moccasin: "bledě krémová",
+navajowhite: "světle krémová",
+navy: "námořnická modrá",
+oldlace: "světle béžová",
+olive: "olivová",
+olivedrab: "khaki",
+orange: "oranžová",
+orangered: "oranžovočervená",
+orchid: "orchidejová",
+palegoldenrod: "bledě písková",
+palegreen: "bledě zelená",
+paleturquoise: "bledě tyrkysová",
+palevioletred: "bledě fialovočervená",
+papayawhip: "papájová",
+peachpuff: "broskvová",
+peru: "karamelová",
+pink: "růžová",
+plum: "švestková",
+powderblue: "bledě modrá",
+purple: "nachová",
+red: "červená",
+rosybrown: "růžovohnědá",
+royalblue: "královská modrá",
+saddlebrown: "hnědá",
+salmon: "lososová",
+sandybrown: "oranžovohnědá",
+seagreen: "mořská zelená",
+seashell: "lasturová",
+sienna: "siena",
+silver: "stříbrná",
+skyblue: "nebeská modrá",
+slateblue: "břidlicová modrá",
+slategray: "břidlicová šedá",
+slategrey: "břidlicová šedá", // same as slategray
+snow: "sněhobílá",
+springgreen: "jarní zelená",
+steelblue: "ocelová modrá",
+tan: "šedobéžová",
+teal: "šedozelená",
+thistle: "bodláková",
+tomato: "tomatová",
+turquoise: "tyrkysová",
+violet: "fialová",
+wheat: "zlatohnědá",
+white: "bílá",
+whitesmoke: "kouřově bílá",
+yellow: "žlutá",
+yellowgreen: "žlutozelená"
+})
diff --git a/dojo/nls/da/colors.js b/dojo/nls/da/colors.js
index 322154f..d346e56 100644
--- a/dojo/nls/da/colors.js
+++ b/dojo/nls/da/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"lys stålblå","orangered":"orangerød","midnightblue":"midnatsblå","cadetblue":"kadetblå","seashell":"muslingeskal","slategrey":"skifergrå","coral":"koralrød","darkturquoise":"mørk turkis","antiquewhite":"antikhvid","mediumspringgreen":"mellemforårsgrøn","salmon":"laksefarvet","darkgrey":"mørkegrå","ivory":"elfenben","greenyellow":"grøngul","mistyrose":"blegrosa","lightsalmon":"lys laksefarvet","silver":"sølv","dimgrey":"svag grå","orange":"orange","white":"hvid","navaj [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "babyblå",
+antiquewhite: "antikhvid",
+aqua: "akvablå",
+aquamarine: "akvamarin",
+azure: "azurblå",
+beige: "beige",
+bisque: "gulgrå",
+black: "sort",
+blanchedalmond: "blanceret mandel",
+blue: "blå",
+blueviolet: "blåviolet",
+brown: "brun",
+burlywood: "tobak",
+cadetblue: "kadetblå",
+chartreuse: "chartreuse",
+chocolate: "rust",
+coral: "koralrød",
+cornflowerblue: "kornblomstblå",
+cornsilk: "majs",
+crimson: "blodrød",
+cyan: "cyan",
+darkblue: "mørkeblå",
+darkcyan: "mørk cyan",
+darkgoldenrod: "mørk gyldenris",
+darkgray: "mørkegrå",
+darkgreen: "mørkegrøn",
+darkgrey: "mørkegrå", // same as darkgray
+darkkhaki: "mørk khaki",
+darkmagenta: "mørk magenta",
+darkolivegreen: "mørk olivengrøn",
+darkorange: "mørk orange",
+darkorchid: "mørk orkide",
+darkred: "mørkerød",
+darksalmon: "mørk laksefarvet",
+darkseagreen: "mørk havgrøn",
+darkslateblue: "mørk skiferblå",
+darkslategray: "mørk skifergrå",
+darkslategrey: "mørk skifergrå", // same as darkslategray
+darkturquoise: "mørk turkis",
+darkviolet: "mørkelilla",
+deeppink: "dyb pink",
+deepskyblue: "dyb himmelblå",
+dimgray: "svag grå",
+dimgrey: "svag grå", // same as dimgray
+dodgerblue: "dodgerblå",
+firebrick: "chamottesten",
+floralwhite: "blomsterhvid",
+forestgreen: "skovgrøn",
+fuchsia: "lyslilla",
+gainsboro: "gainsboro",
+ghostwhite: "spøgelseshvid",
+gold: "guld",
+goldenrod: "gyldenris",
+gray: "grå",
+green: "grøn",
+greenyellow: "grøngul",
+grey: "grå", // same as gray
+honeydew: "honningdug",
+hotpink: "mørk rosa",
+indianred: "lys rødbrun",
+indigo: "indigo",
+ivory: "elfenben",
+khaki: "khaki",
+lavender: "lysviolet",
+lavenderblush: "lavendelrød",
+lawngreen: "græsgrøn",
+lemonchiffon: "citronfromage",
+lightblue: "lyseblå",
+lightcoral: "lys koralrød",
+lightcyan: "lys cyan",
+lightgoldenrodyellow: "lys gyldenrisgul",
+lightgray: "lysegrå",
+lightgreen: "lysegrøn",
+lightgrey: "lysegrå", // same as lightgray
+lightpink: "lys pink",
+lightsalmon: "lys laksefarvet",
+lightseagreen: "lys havgrøn",
+lightskyblue: "lys himmelblå",
+lightslategray: "lys skifergrå",
+lightslategrey: "lys skifergrå", // same as lightslategray
+lightsteelblue: "lys stålblå",
+lightyellow: "lysegul",
+lime: "lime",
+limegreen: "limegrøn",
+linen: "lærred",
+magenta: "magenta",
+maroon: "rødbrun",
+mediumaquamarine: "mellem akvamarin",
+mediumblue: "mellemblå",
+mediumorchid: "mellem orkide",
+mediumpurple: "mellemlilla",
+mediumseagreen: "mellemhavgrøn",
+mediumslateblue: "mellemskiferblå",
+mediumspringgreen: "mellemforårsgrøn",
+mediumturquoise: "mellemturkis",
+mediumvioletred: "mellemviolet",
+midnightblue: "midnatsblå",
+mintcream: "pebermyntecreme",
+mistyrose: "blegrosa",
+moccasin: "fruesko",
+navajowhite: "navajo-hvid",
+navy: "marineblå",
+oldlace: "kniplingshvid",
+olive: "olivengrøn",
+olivedrab: "brungrøn",
+orange: "orange",
+orangered: "orangerød",
+orchid: "orkide",
+palegoldenrod: "bleg gyldenris",
+palegreen: "bleggrøn",
+paleturquoise: "bleg turkis",
+palevioletred: "blegviolet",
+papayawhip: "papaya",
+peachpuff: "fersken",
+peru: "peru",
+pink: "pink",
+plum: "blomme",
+powderblue: "pudderblå",
+purple: "lilla",
+red: "rød",
+rosybrown: "rosabrun",
+royalblue: "kongeblå",
+saddlebrown: "saddelbrun",
+salmon: "laksefarvet",
+sandybrown: "sandbrun",
+seagreen: "havgrøn",
+seashell: "muslingeskal",
+sienna: "sienna",
+silver: "sølv",
+skyblue: "himmelblå",
+slateblue: "skiferblå",
+slategray: "skifergrå",
+slategrey: "skifergrå", // same as slategray
+snow: "sne",
+springgreen: "forårsgrøn",
+steelblue: "metalblå",
+tan: "tan",
+teal: "blågrøn",
+thistle: "tidsel",
+tomato: "tomat",
+turquoise: "turkis",
+violet: "lilla",
+wheat: "korngul",
+white: "hvid",
+whitesmoke: "hvid røg",
+yellow: "gul",
+yellowgreen: "gulgrøn"
+})
diff --git a/dojo/nls/de/colors.js b/dojo/nls/de/colors.js
index 7ae21bf..beccf65 100644
--- a/dojo/nls/de/colors.js
+++ b/dojo/nls/de/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"Helles Stahlblau","orangered":"Orangerot","midnightblue":"Mitternachtblau","cadetblue":"Kadettenblau","seashell":"Muschelweiß","slategrey":"Schiefergrau","coral":"Koralle","darkturquoise":"Dunkeltürkis","antiquewhite":"Antikweiß","mediumspringgreen":"Mittelfrühlingsgrün","salmon":"Lachs","darkgrey":"Dunkelgrau","ivory":"Elfenbein","greenyellow":"Grüngelb","mistyrose":"Blassrose","lightsalmon":"Helllachs","silver":"Silbergrau","dimgrey":"Blassgrau","orange":"Orange","w [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "Alice-blau",
+antiquewhite: "Antikweiß",
+aqua: "Wasserblau",
+aquamarine: "Aquamarin",
+azure: "Azur",
+beige: "Beige",
+bisque: "Bisquit",
+black: "Schwarz",
+blanchedalmond: "Mandelweiß",
+blue: "Blau",
+blueviolet: "Blauviolett",
+brown: "Braun",
+burlywood: "Burlywood",
+cadetblue: "Kadettenblau",
+chartreuse: "Helles Gelbgrün",
+chocolate: "Schokoladenbraun",
+coral: "Koralle",
+cornflowerblue: "Kornblumenblau",
+cornsilk: "Kornseide",
+crimson: "Karmesinrot",
+cyan: "Zyan",
+darkblue: "Dunkelblau",
+darkcyan: "Dunkelzyan",
+darkgoldenrod: "Dunkelgoldgelb",
+darkgray: "Dunkelgrau",
+darkgreen: "Dunkelgrün",
+darkgrey: "Dunkelgrau", // same as darkgray
+darkkhaki: "Dunkelkhaki",
+darkmagenta: "Dunkelmagenta",
+darkolivegreen: "Dunkelolivgrün",
+darkorange: "Dunkelorange",
+darkorchid: "Dunkelorchidee",
+darkred: "Dunkelrot",
+darksalmon: "Dunkellachs",
+darkseagreen: "Dunkles Meergrün",
+darkslateblue: "Dunkelschieferblau",
+darkslategray: "Dunkelschiefergrau",
+darkslategrey: "Dunkelschiefergrau", // same as darkslategray
+darkturquoise: "Dunkeltürkis",
+darkviolet: "Dunkelviolett",
+deeppink: "Tiefrosa",
+deepskyblue: "Dunkles Himmelblau",
+dimgray: "Blassgrau",
+dimgrey: "Blassgrau", // same as dimgray
+dodgerblue: "Dodger-blau",
+firebrick: "Schamottestein",
+floralwhite: "Blütenweiß",
+forestgreen: "Forstgrün",
+fuchsia: "Fuchsia",
+gainsboro: "Gainsboro",
+ghostwhite: "Geisterweiß",
+gold: "Gold",
+goldenrod: "Goldgelb",
+gray: "Grau",
+green: "Grün",
+greenyellow: "Grüngelb",
+grey: "Grau", // same as gray
+honeydew: "Honigtau",
+hotpink: "Knallrosa",
+indianred: "Indischrot",
+indigo: "Indigoblau",
+ivory: "Elfenbein",
+khaki: "Khaki",
+lavender: "Lavendelblau",
+lavenderblush: "Lavendelhauch",
+lawngreen: "Grasgrün",
+lemonchiffon: "Zitronenchiffon",
+lightblue: "Hellblau",
+lightcoral: "Hellkoralle",
+lightcyan: "Hellzyan",
+lightgoldenrodyellow: "Hellgoldgelb",
+lightgray: "Hellgrau",
+lightgreen: "Hellgrün",
+lightgrey: "Hellgrau", // same as lightgray
+lightpink: "Hellrosa",
+lightsalmon: "Helllachs",
+lightseagreen: "Helles Meergrün",
+lightskyblue: "Helles Himmelblau",
+lightslategray: "Helles Schiefergrau",
+lightslategrey: "Helles Schiefergrau", // same as lightslategray
+lightsteelblue: "Helles Stahlblau",
+lightyellow: "Hellgelb",
+lime: "Limone",
+limegreen: "Limonengrün",
+linen: "Leinen",
+magenta: "Magenta",
+maroon: "Kastanienbraun",
+mediumaquamarine: "Mittelaquamarin",
+mediumblue: "Mittelblau",
+mediumorchid: "Mittelorchidee",
+mediumpurple: "Mittelpurpur",
+mediumseagreen: "Mittelmeeresgrün",
+mediumslateblue: "Mittelschieferblau ",
+mediumspringgreen: "Mittelfrühlingsgrün",
+mediumturquoise: "Mitteltürkis ",
+mediumvioletred: "Mittelviolettrot ",
+midnightblue: "Mitternachtblau",
+mintcream: "Mintcreme",
+mistyrose: "Blassrose",
+moccasin: "Mokassin",
+navajowhite: "Navajo-weiß",
+navy: "Marineblau",
+oldlace: "Alte Spitze",
+olive: "Oliv",
+olivedrab: "Olivgrau",
+orange: "Orange",
+orangered: "Orangerot",
+orchid: "Orchidee",
+palegoldenrod: "Blassgoldgelb",
+palegreen: "Blassgrün",
+paleturquoise: "Blasstürkis",
+palevioletred: "Blassviolettrot ",
+papayawhip: "Papayacreme",
+peachpuff: "Pfirsich",
+peru: "Peru",
+pink: "Rosa",
+plum: "Pflaume",
+powderblue: "Pulverblau",
+purple: "Purpurrot",
+red: "Rot",
+rosybrown: "Rosigbraun",
+royalblue: "Königsblau",
+saddlebrown: "Sattelbraun",
+salmon: "Lachs",
+sandybrown: "Sandbraun",
+seagreen: "Meeresgrün",
+seashell: "Muschelweiß",
+sienna: "Sienna",
+silver: "Silbergrau",
+skyblue: "Himmelblau",
+slateblue: "Schieferblau",
+slategray: "Schiefergrau",
+slategrey: "Schiefergrau", // same as slategray
+snow: "Schneeweiß",
+springgreen: "Frühlingsgrün",
+steelblue: "Stahlblau",
+tan: "Hautfarben",
+teal: "Smaragdgrün",
+thistle: "Distel",
+tomato: "Tomatenrot",
+turquoise: "Türkis",
+violet: "Violett",
+wheat: "Weizen",
+white: "Weiß",
+whitesmoke: "Rauchweiß",
+yellow: "Gelb",
+yellowgreen: "Gelbgrün"
+})
diff --git a/dojo/nls/el/colors.js b/dojo/nls/el/colors.js
index a80df97..8805ad1 100644
--- a/dojo/nls/el/colors.js
+++ b/dojo/nls/el/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"ανοιχτό μπλε ατσαλιού","orangered":"πορτοκαλοκόκκινο","midnightblue":"πολύ σκούρο μπλε","cadetblue":"μπλε του στρατού","seashell":"κοχύλι","slategrey":"μεταλλικό γκρι","coral":"κοραλί","darkturquoise":"σκούρο τυρκουάζ","antiquewhite":"ξεθωριασμένο λευκό","mediumspringgreen":"μεσαίο πράσινο της άνοιξης","salmon":"σομόν","darkgrey":"σκούρο γκρι","ivory":"ιβουάρ","greenyellow":"πρασινοκίτρινο","mistyrose":"τριανταφυλλί","lightsalmon":"ανοιχτό σομόν","silver":"ασημί","dim [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "σιέλ",
+antiquewhite: "ξεθωριασμένο λευκό",
+aqua: "γαλάζιο",
+aquamarine: "γαλαζοπράσινο",
+azure: "μπλε του ουρανού",
+beige: "μπεζ",
+bisque: "σκούρο κρεμ",
+black: "μαύρο",
+blanchedalmond: "ζαχαρί",
+blue: "μπλε",
+blueviolet: "βιολετί",
+brown: "καφέ",
+burlywood: "καφέ του ξύλου",
+cadetblue: "μπλε του στρατού",
+chartreuse: "φωτεινό κιτρινοπράσινο",
+chocolate: "σοκολατί",
+coral: "κοραλί",
+cornflowerblue: "μεσαίο μπλε",
+cornsilk: "ασημί του καλαμποκιού",
+crimson: "βαθύ κόκκινο",
+cyan: "κυανό",
+darkblue: "σκούρο μπλε",
+darkcyan: "σκούρο κυανό",
+darkgoldenrod: "σκούρο χρυσοκίτρινο",
+darkgray: "σκούρο γκρι",
+darkgreen: "σκούρο πράσινο",
+darkgrey: "σκούρο γκρι", // same as darkgray
+darkkhaki: "σκούρο χακί",
+darkmagenta: "σκούρο ματζέντα",
+darkolivegreen: "σκούρο πράσινο λαδί",
+darkorange: "σκούρο πορτοκαλί",
+darkorchid: "σκούρα ορχιδέα",
+darkred: "σκούρο κόκκινο",
+darksalmon: "σκούρο σομόν",
+darkseagreen: "σκούρο πράσινο της θάλασσας",
+darkslateblue: "σκούρο μεταλλικό μπλε",
+darkslategray: "σκούρο μεταλλικό γκρι",
+darkslategrey: "σκούρο μεταλλικό γκρι", // same as darkslategray
+darkturquoise: "σκούρο τυρκουάζ",
+darkviolet: "σκούρο βιολετί",
+deeppink: "βαθύ ροζ",
+deepskyblue: "βαθύ μπλε το ουρανού",
+dimgray: "αχνό γκρι",
+dimgrey: "αχνό γκρι", // same as dimgray
+dodgerblue: "σκούρο ελεκτρίκ",
+firebrick: "κεραμιδί",
+floralwhite: "λευκό των ανθών",
+forestgreen: "πράσινο του δάσους",
+fuchsia: "φούξια",
+gainsboro: "γκρι σιέλ",
+ghostwhite: "άσπρο",
+gold: "χρυσαφί",
+goldenrod: "χρυσοκίτρινο",
+gray: "γκρι",
+green: "πράσινο",
+greenyellow: "πρασινοκίτρινο",
+grey: "γκρι", // same as gray
+honeydew: "μελί",
+hotpink: "έντονο ροζ",
+indianred: "ινδικό κόκκινο",
+indigo: "λουλακί",
+ivory: "ιβουάρ",
+khaki: "χακί",
+lavender: "λίλα",
+lavenderblush: "μωβ λεβάντας",
+lawngreen: "σκούρο πράσινο",
+lemonchiffon: "λεμονί",
+lightblue: "ανοιχτό μπλε",
+lightcoral: "ανοιχτό κοραλί",
+lightcyan: "ανοιχτό κυανό",
+lightgoldenrodyellow: "ανοιχτό χρυσοκίτρινο",
+lightgray: "ανοιχτό γκρι",
+lightgreen: "ανοιχτό πράσινο",
+lightgrey: "ανοιχτό γκρι", // same as lightgray
+lightpink: "ανοιχτό ροζ",
+lightsalmon: "ανοιχτό σομόν",
+lightseagreen: "ανοιχτό πράσινο της θάλασσας",
+lightskyblue: "ανοιχτό μπλε το ουρανού",
+lightslategray: "ανοιχτό μεταλλικό γκρι",
+lightslategrey: "ανοιχτό μεταλλικό γκρι", // same as lightslategray
+lightsteelblue: "ανοιχτό μπλε ατσαλιού",
+lightyellow: "ανοιχτό κίτρινο",
+lime: "λαχανί",
+limegreen: "πράσινο λαχανί",
+linen: "σπαγγί",
+magenta: "ματζέντα",
+maroon: "βυσσινί",
+mediumaquamarine: "μεσαίο γαλαζοπράσινο",
+mediumblue: "μεσαίο μπλε",
+mediumorchid: "μεσαία ορχιδέα",
+mediumpurple: "μεσαίο μωβ",
+mediumseagreen: "μεσαίο πράσινο της θάλασσας",
+mediumslateblue: "μεσαίο μεταλλικό μπλε",
+mediumspringgreen: "μεσαίο πράσινο της άνοιξης",
+mediumturquoise: "μεσαίο τυρκουάζ",
+mediumvioletred: "μεσαίο κόκκινο βιολετί",
+midnightblue: "πολύ σκούρο μπλε",
+mintcream: "βεραμάν",
+mistyrose: "τριανταφυλλί",
+moccasin: "μόκα",
+navajowhite: "άσπρο Ναβάχο",
+navy: "μπλε του ναυτικού",
+oldlace: "εκρού",
+olive: "πράσινο λαδί",
+olivedrab: "λαδί",
+orange: "πορτοκαλί",
+orangered: "πορτοκαλοκόκκινο",
+orchid: "ορχιδέα",
+palegoldenrod: "αχνό χρυσοκίτρινο",
+palegreen: "αχνό πράσινο",
+paleturquoise: "αχνό τυρκουάζ",
+palevioletred: "αχνό κόκκινο βιολετί",
+papayawhip: "αχνό ροζ",
+peachpuff: "ροδακινί",
+peru: "περού",
+pink: "ροζ",
+plum: "δαμασκηνί",
+powderblue: "αχνό μπλε",
+purple: "μωβ",
+red: "κόκκινο",
+rosybrown: "καστανό",
+royalblue: "έντονο μπλε",
+saddlebrown: "βαθύ καφέ",
+salmon: "σομόν",
+sandybrown: "μπεζ της άμμου",
+seagreen: "πράσινο της θάλασσας",
+seashell: "κοχύλι",
+sienna: "καφεκίτρινο",
+silver: "ασημί",
+skyblue: "μπλε του ουρανού",
+slateblue: "μεταλλικό μπλε",
+slategray: "μεταλλικό γκρι",
+slategrey: "μεταλλικό γκρι", // same as slategray
+snow: "χιονί",
+springgreen: "πράσινο της άνοιξης",
+steelblue: "μπλε ατσαλιού",
+tan: "ώχρα",
+teal: "πετρόλ",
+thistle: "μωβ βιολετί",
+tomato: "κόκκινο της ντομάτας",
+turquoise: "τυρκουάζ",
+violet: "βιολετί",
+wheat: "σταρένιο",
+white: "λευκό",
+whitesmoke: "λευκός καπνός",
+yellow: "κίτρινο",
+yellowgreen: "κιτρινοπράσινο"
+})
diff --git a/dojo/nls/es/colors.js b/dojo/nls/es/colors.js
index 95bb23e..8a46937 100644
--- a/dojo/nls/es/colors.js
+++ b/dojo/nls/es/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"azul acero claro","orangered":"rojo anaranjado","midnightblue":"azul medianoche","cadetblue":"azul cadete","seashell":"blanco marfil","slategrey":"gris pizarra","coral":"coral","darkturquoise":"turquesa oscuro","antiquewhite":"blanco antiguo","mediumspringgreen":"verde primavera medio","salmon":"salmón","darkgrey":"gris oscuro","ivory":"marfil","greenyellow":"amarillo verdoso","mistyrose":"rosa difuminado","lightsalmon":"salmón claro","silver":"plateado","dimgrey":"gr [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "blanco azulado",
+antiquewhite: "blanco antiguo",
+aqua: "aguamarina",
+aquamarine: "aguamarina 2",
+azure: "blanco cielo",
+beige: "beige",
+bisque: "miel",
+black: "negro",
+blanchedalmond: "almendra pálido",
+blue: "azul",
+blueviolet: "azul violáceo",
+brown: "marrón",
+burlywood: "madera",
+cadetblue: "azul cadete",
+chartreuse: "verde pálido 2",
+chocolate: "chocolate",
+coral: "coral",
+cornflowerblue: "azul aciano",
+cornsilk: "crudo",
+crimson: "carmesí",
+cyan: "cian",
+darkblue: "azul oscuro",
+darkcyan: "cian oscuro",
+darkgoldenrod: "ocre oscuro",
+darkgray: "gris oscuro",
+darkgreen: "verde oscuro",
+darkgrey: "gris oscuro", // same as darkgray
+darkkhaki: "caqui oscuro",
+darkmagenta: "magenta oscuro",
+darkolivegreen: "verde oliva oscuro",
+darkorange: "naranja oscuro",
+darkorchid: "orquídea oscuro",
+darkred: "rojo oscuro",
+darksalmon: "salmón oscuro",
+darkseagreen: "verde mar oscuro",
+darkslateblue: "azul pizarra oscuro",
+darkslategray: "gris pizarra oscuro",
+darkslategrey: "gris pizarra oscuro", // same as darkslategray
+darkturquoise: "turquesa oscuro",
+darkviolet: "violeta oscuro",
+deeppink: "rosa fuerte",
+deepskyblue: "azul cielo fuerte",
+dimgray: "gris marengo",
+dimgrey: "gris marengo", // same as dimgray
+dodgerblue: "azul fuerte",
+firebrick: "teja",
+floralwhite: "blanco manteca",
+forestgreen: "verde pino",
+fuchsia: "fucsia",
+gainsboro: "azul gainsboro",
+ghostwhite: "blanco ligero",
+gold: "oro",
+goldenrod: "ocre",
+gray: "gris",
+green: "verde",
+greenyellow: "amarillo verdoso",
+grey: "gris", // same as gray
+honeydew: "flor de rocío",
+hotpink: "rosa oscuro",
+indianred: "rojo teja",
+indigo: "añil",
+ivory: "marfil",
+khaki: "caqui",
+lavender: "lavanda",
+lavenderblush: "lavanda rosácea",
+lawngreen: "verde césped",
+lemonchiffon: "amarillo pastel",
+lightblue: "azul claro",
+lightcoral: "coral claro",
+lightcyan: "cian claro",
+lightgoldenrodyellow: "ocre claro",
+lightgray: "gris claro",
+lightgreen: "verde claro",
+lightgrey: "gris claro", // same as lightgray
+lightpink: "rosa claro",
+lightsalmon: "salmón claro",
+lightseagreen: "verde mar claro",
+lightskyblue: "azul cielo claro",
+lightslategray: "gris pizarra claro",
+lightslategrey: "gris pizarra claro", // same as lightslategray
+lightsteelblue: "azul acero claro",
+lightyellow: "amarillo claro",
+lime: "lima",
+limegreen: "lima limón",
+linen: "blanco arena",
+magenta: "magenta",
+maroon: "granate",
+mediumaquamarine: "aguamarina medio",
+mediumblue: "azul medio",
+mediumorchid: "orquídea medio",
+mediumpurple: "púrpura medio",
+mediumseagreen: "verde mar medio",
+mediumslateblue: "azul pizarra medio",
+mediumspringgreen: "verde primavera medio",
+mediumturquoise: "turquesa medio",
+mediumvioletred: "rojo violáceo medio",
+midnightblue: "azul medianoche",
+mintcream: "crema menta",
+mistyrose: "rosa difuminado",
+moccasin: "arena",
+navajowhite: "blanco navajo",
+navy: "azul marino",
+oldlace: "encaje antiguo",
+olive: "verde oliva",
+olivedrab: "verde oliva pardusco",
+orange: "naranja",
+orangered: "rojo anaranjado",
+orchid: "orquídea",
+palegoldenrod: "ocre pálido",
+palegreen: "verde pálido",
+paleturquoise: "turquesa pálido",
+palevioletred: "rojo violáceo pálido",
+papayawhip: "papaya claro",
+peachpuff: "melocotón",
+peru: "perú",
+pink: "rosa",
+plum: "ciruela",
+powderblue: "azul suave",
+purple: "púrpura",
+red: "rojo",
+rosybrown: "marrón rosáceo",
+royalblue: "azul real",
+saddlebrown: "cuero",
+salmon: "salmón",
+sandybrown: "marrón arcilla",
+seagreen: "verde mar",
+seashell: "blanco marfil",
+sienna: "siena",
+silver: "plateado",
+skyblue: "azul cielo",
+slateblue: "azul pizarra",
+slategray: "gris pizarra",
+slategrey: "gris pizarra", // same as slategray
+snow: "nieve",
+springgreen: "verde fuerte",
+steelblue: "azul acero",
+tan: "canela",
+teal: "verde azulado",
+thistle: "cardo",
+tomato: "tomate",
+turquoise: "turquesa",
+violet: "violeta",
+wheat: "trigo",
+white: "blanco",
+whitesmoke: "blanco ahumado",
+yellow: "amarillo",
+yellowgreen: "verde amarillento"
+})
diff --git a/dojo/nls/fi/colors.js b/dojo/nls/fi/colors.js
index 454e644..07562cc 100644
--- a/dojo/nls/fi/colors.js
+++ b/dojo/nls/fi/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"light steel blue","orangered":"orange red","midnightblue":"midnight blue","cadetblue":"cadet blue","seashell":"seashell","slategrey":"slate gray","coral":"coral","darkturquoise":"dark turquoise","antiquewhite":"antique white","mediumspringgreen":"medium spring green","salmon":"salmon","darkgrey":"dark gray","ivory":"ivory","greenyellow":"green-yellow","mistyrose":"misty rose","lightsalmon":"light salmon","silver":"silver","dimgrey":"dim gray","orange":"orange","white" [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "alice blue",
+antiquewhite: "antique white",
+aqua: "aqua",
+aquamarine: "aquamarine",
+azure: "azure",
+beige: "beige",
+bisque: "bisque",
+black: "black",
+blanchedalmond: "blanched almond",
+blue: "blue",
+blueviolet: "blue-violet",
+brown: "brown",
+burlywood: "burlywood",
+cadetblue: "cadet blue",
+chartreuse: "chartreuse",
+chocolate: "chocolate",
+coral: "coral",
+cornflowerblue: "cornflower blue",
+cornsilk: "cornsilk",
+crimson: "crimson",
+cyan: "cyan",
+darkblue: "dark blue",
+darkcyan: "dark cyan",
+darkgoldenrod: "dark goldenrod",
+darkgray: "dark gray",
+darkgreen: "dark green",
+darkgrey: "dark gray", // same as darkgray
+darkkhaki: "dark khaki",
+darkmagenta: "dark magenta",
+darkolivegreen: "dark olive green",
+darkorange: "dark orange",
+darkorchid: "dark orchid",
+darkred: "dark red",
+darksalmon: "dark salmon",
+darkseagreen: "dark sea green",
+darkslateblue: "dark slate blue",
+darkslategray: "dark slate gray",
+darkslategrey: "dark slate gray", // same as darkslategray
+darkturquoise: "dark turquoise",
+darkviolet: "dark violet",
+deeppink: "deep pink",
+deepskyblue: "deep sky blue",
+dimgray: "dim gray",
+dimgrey: "dim gray", // same as dimgray
+dodgerblue: "dodger blue",
+firebrick: "fire brick",
+floralwhite: "floral white",
+forestgreen: "forest green",
+fuchsia: "fuchsia",
+gainsboro: "gainsboro",
+ghostwhite: "ghost white",
+gold: "gold",
+goldenrod: "goldenrod",
+gray: "gray",
+green: "green",
+greenyellow: "green-yellow",
+grey: "gray", // same as gray
+honeydew: "honeydew",
+hotpink: "hot pink",
+indianred: "indian red",
+indigo: "indigo",
+ivory: "ivory",
+khaki: "khaki",
+lavender: "lavender",
+lavenderblush: "lavender blush",
+lawngreen: "lawn green",
+lemonchiffon: "lemon chiffon",
+lightblue: "light blue",
+lightcoral: "light coral",
+lightcyan: "light cyan",
+lightgoldenrodyellow: "light goldenrod yellow",
+lightgray: "light gray",
+lightgreen: "light green",
+lightgrey: "light gray", // same as lightgray
+lightpink: "light pink",
+lightsalmon: "light salmon",
+lightseagreen: "light sea green",
+lightskyblue: "light sky blue",
+lightslategray: "light slate gray",
+lightslategrey: "light slate gray", // same as lightslategray
+lightsteelblue: "light steel blue",
+lightyellow: "light yellow",
+lime: "lime",
+limegreen: "lime green",
+linen: "linen",
+magenta: "magenta",
+maroon: "maroon",
+mediumaquamarine: "medium aquamarine",
+mediumblue: "medium blue",
+mediumorchid: "medium orchid",
+mediumpurple: "medium purple",
+mediumseagreen: "medium sea green",
+mediumslateblue: "medium slate blue",
+mediumspringgreen: "medium spring green",
+mediumturquoise: "medium turquoise",
+mediumvioletred: "medium violet-red",
+midnightblue: "midnight blue",
+mintcream: "mint cream",
+mistyrose: "misty rose",
+moccasin: "moccasin",
+navajowhite: "navajo white",
+navy: "navy",
+oldlace: "old lace",
+olive: "olive",
+olivedrab: "olive drab",
+orange: "orange",
+orangered: "orange red",
+orchid: "orchid",
+palegoldenrod: "pale goldenrod",
+palegreen: "pale green",
+paleturquoise: "pale turquoise",
+palevioletred: "pale violet-red",
+papayawhip: "papaya whip",
+peachpuff: "peach puff",
+peru: "peru",
+pink: "pink",
+plum: "plum",
+powderblue: "powder blue",
+purple: "purple",
+red: "red",
+rosybrown: "rosy brown",
+royalblue: "royal blue",
+saddlebrown: "saddle brown",
+salmon: "salmon",
+sandybrown: "sandy brown",
+seagreen: "sea green",
+seashell: "seashell",
+sienna: "sienna",
+silver: "silver",
+skyblue: "sky blue",
+slateblue: "slate blue",
+slategray: "slate gray",
+slategrey: "slate gray", // same as slategray
+snow: "snow",
+springgreen: "spring green",
+steelblue: "steel blue",
+tan: "tan",
+teal: "teal",
+thistle: "thistle",
+tomato: "tomato",
+turquoise: "turquoise",
+violet: "violet",
+wheat: "wheat",
+white: "white",
+whitesmoke: "white smoke",
+yellow: "yellow",
+yellowgreen: "yellow green"
+})
diff --git a/dojo/nls/fr/colors.js b/dojo/nls/fr/colors.js
index cf1e7e9..df31eac 100644
--- a/dojo/nls/fr/colors.js
+++ b/dojo/nls/fr/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"bleu acier clair","orangered":"rouge orangé","midnightblue":"bleu nuit","cadetblue":"bleu pétrole","seashell":"coquillage","slategrey":"gris ardoise","coral":"corail","darkturquoise":"turquoise foncé","antiquewhite":"blanc antique","mediumspringgreen":"vert printemps moyen","salmon":"saumon","darkgrey":"gris foncé","ivory":"ivoire","greenyellow":"vert-jaune","mistyrose":"rose pâle","lightsalmon":"saumon clair","silver":"argent","dimgrey":"gris soutenu","orange":"orang [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "bleu gris",
+antiquewhite: "blanc antique",
+aqua: "bleu-vert",
+aquamarine: "aigue-marine",
+azure: "bleu azur",
+beige: "beige",
+bisque: "beige rosé",
+black: "noir",
+blanchedalmond: "coquille d'oeuf",
+blue: "bleu",
+blueviolet: "bleu-violet",
+brown: "brun",
+burlywood: "bois précieux",
+cadetblue: "bleu pétrole",
+chartreuse: "vert vif",
+chocolate: "chocolat",
+coral: "corail",
+cornflowerblue: "bleuet",
+cornsilk: "vanille",
+crimson: "cramoisi",
+cyan: "cyan",
+darkblue: "bleu foncé",
+darkcyan: "cyan foncé",
+darkgoldenrod: "jaune paille foncé",
+darkgray: "gris foncé",
+darkgreen: "vert foncé",
+darkgrey: "gris foncé", // same as darkgray
+darkkhaki: "kaki foncé",
+darkmagenta: "magenta foncé",
+darkolivegreen: "olive foncé",
+darkorange: "orange foncé",
+darkorchid: "lilas foncé",
+darkred: "rouge foncé",
+darksalmon: "saumon foncé",
+darkseagreen: "vert d'eau foncé",
+darkslateblue: "bleu ardoise foncé",
+darkslategray: "gris ardoise foncé",
+darkslategrey: "gris ardoise foncé", // same as darkslategray
+darkturquoise: "turquoise foncé",
+darkviolet: "violet foncé",
+deeppink: "rose soutenu",
+deepskyblue: "bleu ciel soutenu",
+dimgray: "gris soutenu",
+dimgrey: "gris soutenu", // same as dimgray
+dodgerblue: "bleu France",
+firebrick: "rouge brique",
+floralwhite: "lys",
+forestgreen: "vert sapin",
+fuchsia: "fuchsia",
+gainsboro: "gris souris",
+ghostwhite: "blanc laiteux",
+gold: "or",
+goldenrod: "jaune paille",
+gray: "gris",
+green: "vert",
+greenyellow: "vert-jaune",
+grey: "gris", // same as gray
+honeydew: "opalin",
+hotpink: "rose intense",
+indianred: "rose indien",
+indigo: "indigo",
+ivory: "ivoire",
+khaki: "kaki",
+lavender: "lavande",
+lavenderblush: "lavandin",
+lawngreen: "vert prairie",
+lemonchiffon: "mousse de citron",
+lightblue: "bleu clair",
+lightcoral: "corail clair",
+lightcyan: "cyan clair",
+lightgoldenrodyellow: "jaune paille clair",
+lightgray: "gris clair",
+lightgreen: "vert clair",
+lightgrey: "gris clair", // same as lightgray
+lightpink: "rose clair",
+lightsalmon: "saumon clair",
+lightseagreen: "vert d'eau clair",
+lightskyblue: "bleu ciel clair",
+lightslategray: "gris ardoise clair",
+lightslategrey: "gris ardoise clair", // same as lightslategray
+lightsteelblue: "bleu acier clair",
+lightyellow: "jaune clair",
+lime: "vert citron",
+limegreen: "citron vert",
+linen: "écru",
+magenta: "magenta",
+maroon: "marron",
+mediumaquamarine: "aigue-marine moyen",
+mediumblue: "bleu moyen",
+mediumorchid: "lilas moyen",
+mediumpurple: "pourpre moyen",
+mediumseagreen: "vert d'eau moyen",
+mediumslateblue: "bleu ardoise moyen",
+mediumspringgreen: "vert printemps moyen",
+mediumturquoise: "turquoise moyen",
+mediumvioletred: "rouge violacé moyen",
+midnightblue: "bleu nuit",
+mintcream: "crème de menthe",
+mistyrose: "rose pâle",
+moccasin: "chamois",
+navajowhite: "chair",
+navy: "bleu marine",
+oldlace: "blanc cassé",
+olive: "olive",
+olivedrab: "brun verdâtre",
+orange: "orange",
+orangered: "rouge orangé",
+orchid: "lilas",
+palegoldenrod: "jaune paille pâle",
+palegreen: "vert pâle",
+paleturquoise: "turquoise pâle",
+palevioletred: "rouge violacé pâle",
+papayawhip: "crème de papaye",
+peachpuff: "pêche",
+peru: "caramel",
+pink: "rose",
+plum: "prune",
+powderblue: "bleu de smalt",
+purple: "pourpre",
+red: "rouge",
+rosybrown: "vieux rose",
+royalblue: "bleu roi",
+saddlebrown: "brun cuir",
+salmon: "saumon",
+sandybrown: "sable",
+seagreen: "vert d'eau",
+seashell: "coquillage",
+sienna: "terre de sienne",
+silver: "argent",
+skyblue: "bleu ciel",
+slateblue: "bleu ardoise",
+slategray: "gris ardoise",
+slategrey: "gris ardoise", // same as slategray
+snow: "neige",
+springgreen: "vert printemps",
+steelblue: "bleu acier",
+tan: "grège",
+teal: "sarcelle",
+thistle: "chardon",
+tomato: "tomate",
+turquoise: "turquoise",
+violet: "violet",
+wheat: "blé",
+white: "blanc",
+whitesmoke: "blanc cendré",
+yellow: "jaune",
+yellowgreen: "vert jaunâtre"
+})
diff --git a/dojo/nls/he/colors.js b/dojo/nls/he/colors.js
index a689ec6..eaa8748 100644
--- a/dojo/nls/he/colors.js
+++ b/dojo/nls/he/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"כחול פלדה בהיר","orangered":"כתום אדום","midnightblue":"כחול כהה","cadetblue":"כחול ים","seashell":"צדף","slategrey":"אפור צפחה","coral":"אלמוג","darkturquoise":"טורקיז כהה","antiquewhite":"לבן עתיק","mediumspringgreen":"ירוק אביב בינוני","salmon":"סלמון","darkgrey":"אפור כהה","ivory":"שנהב","greenyellow":"ירוק-צהוב","mistyrose":"ורוד מעורפל","lightsalmon":"סלמון בהיר","silver":"כסף","dimgrey":"אפור עמום","orange":"כתום","white":"לבן","navajowhite":"לבן נוואחו","royal [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "כחול פלדה",
+antiquewhite: "לבן עתיק",
+aqua: "אקווה",
+aquamarine: "אקוומארין",
+azure: "תכלת עז",
+beige: "בז'",
+bisque: "לבן שקד",
+black: "שחור",
+blanchedalmond: "שקד",
+blue: "כחול",
+blueviolet: "כחול-סגול",
+brown: "חום",
+burlywood: "חום דהוי",
+cadetblue: "כחול ים",
+chartreuse: "ירוק-צהוב",
+chocolate: "שוקולד",
+coral: "אלמוג",
+cornflowerblue: "כחול דרדר",
+cornsilk: "צהבהב",
+crimson: "ארגמן",
+cyan: "טורקיז",
+darkblue: "כחול כהה",
+darkcyan: "טורקיז כהה",
+darkgoldenrod: "זהוב כהה",
+darkgray: "אפור כהה",
+darkgreen: "ירוק כהה",
+darkgrey: "אפור כהה", // same as darkgray
+darkkhaki: "חאקי כהה",
+darkmagenta: "בורדו כהה",
+darkolivegreen: "ירוק זית כהה",
+darkorange: "כתום כהה",
+darkorchid: "סחלב כהה",
+darkred: "אדום כהה",
+darksalmon: "סלמון כהה",
+darkseagreen: "ירוק ים כהה",
+darkslateblue: "כחול צפחה כהה",
+darkslategray: "אפור צפחה כהה",
+darkslategrey: "אפור צפחה כהה", // same as darkslategray
+darkturquoise: "טורקיז כהה",
+darkviolet: "סגול כהה",
+deeppink: "ורוד עמוק",
+deepskyblue: "כחול שמיים עמוק",
+dimgray: "אפור עמום",
+dimgrey: "אפור עמום", // same as dimgray
+dodgerblue: "כחול",
+firebrick: "לבנה שרופה",
+floralwhite: "לבן פרחוני",
+forestgreen: "ירוק יער",
+fuchsia: "ורוד בהיר",
+gainsboro: "גיינסבורו",
+ghostwhite: "לבן רפאים",
+gold: "זהב",
+goldenrod: "זהוב",
+gray: "אפור",
+green: "ירוק",
+greenyellow: "ירוק-צהוב",
+grey: "אפור", // same as gray
+honeydew: "ירקרק",
+hotpink: "ורוד לוהט",
+indianred: "אדום דהוי",
+indigo: "אינדיגו",
+ivory: "שנהב",
+khaki: "חאקי",
+lavender: "לבנדר",
+lavenderblush: "סומק לבנדר",
+lawngreen: "ירוק דשא",
+lemonchiffon: "ירוק לימון",
+lightblue: "תכלת",
+lightcoral: "אלמוג בהיר",
+lightcyan: "טורקיז בהיר",
+lightgoldenrodyellow: "צהוב בהיר",
+lightgray: "אפור בהיר",
+lightgreen: "ירוק בהיר",
+lightgrey: "אפור בהיר", // same as lightgray
+lightpink: "ורוד בהיר",
+lightsalmon: "סלמון בהיר",
+lightseagreen: "ירוק ים בהיר",
+lightskyblue: "כחול שמיים בהיר",
+lightslategray: "אפור צפחה בהיר",
+lightslategrey: "אפור צפחה בהיר", // same as lightslategray
+lightsteelblue: "כחול פלדה בהיר",
+lightyellow: "צהוב בהיר",
+lime: "לימון",
+limegreen: "ירוק לימוני",
+linen: "פשתן",
+magenta: "בורדו",
+maroon: "חום אדמדם",
+mediumaquamarine: "כחול בינוני",
+mediumblue: "תכלת בינוני",
+mediumorchid: "סחלב בינוני",
+mediumpurple: "סגול בינוני",
+mediumseagreen: "ירוק ים בינוני",
+mediumslateblue: "כחול צפחה בינוני",
+mediumspringgreen: "ירוק אביב בינוני",
+mediumturquoise: "טורקיז בינוני",
+mediumvioletred: "סגול-אדום בינוני",
+midnightblue: "כחול כהה",
+mintcream: "קרם מנטה",
+mistyrose: "ורוד מעורפל",
+moccasin: "מוקסין",
+navajowhite: "לבן נוואחו",
+navy: "כחול כהה",
+oldlace: "תחרה עתיקה",
+olive: "זית",
+olivedrab: "זית עמום",
+orange: "כתום",
+orangered: "כתום אדום",
+orchid: "סחלב",
+palegoldenrod: "זהוב בהיר",
+palegreen: "ירוק בהיר",
+paleturquoise: "טורקיז בהיר",
+palevioletred: "סגול-אדום בהיר",
+papayawhip: "פפאיה",
+peachpuff: "קציפת אפרסק",
+peru: "פרו",
+pink: "ורוד",
+plum: "שזיף",
+powderblue: "כחול חיוור",
+purple: "סגול",
+red: "אדום",
+rosybrown: "חום ורדרד",
+royalblue: "כחול מלכותי",
+saddlebrown: "חום דהוי",
+salmon: "סלמון",
+sandybrown: "חום חולי",
+seagreen: "ירוק ים",
+seashell: "צדף",
+sienna: "סיינה",
+silver: "כסף",
+skyblue: "כחול שמיים",
+slateblue: "כחול צפחה",
+slategray: "אפור צפחה",
+slategrey: "אפור צפחה", // same as slategray
+snow: "שלג",
+springgreen: "ירוק אביב",
+steelblue: "כחול פלדה",
+tan: "חום אדמדם",
+teal: "כחול-ירוק כהה",
+thistle: "דרדר",
+tomato: "עגבניה",
+turquoise: "טורקיז",
+violet: "סגול",
+wheat: "חיוט",
+white: "לבן",
+whitesmoke: "עשן לבן",
+yellow: "צהוב",
+yellowgreen: "ירוק צהוב"
+})
diff --git a/dojo/nls/hu/colors.js b/dojo/nls/hu/colors.js
index c0bce74..b04b2c7 100644
--- a/dojo/nls/hu/colors.js
+++ b/dojo/nls/hu/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"világos acélkék","orangered":"narancsvörös","midnightblue":"éjkék","cadetblue":"kadétkék","seashell":"kagyló","slategrey":"palaszürke","coral":"korall","darkturquoise":"sötét türkizkék","antiquewhite":"antik fehér","mediumspringgreen":"közepes tavaszzöld","salmon":"lazacszín","darkgrey":"sötétszürke","ivory":"elefántcsont","greenyellow":"zöldessárga","mistyrose":"halvány rózsaszín","lightsalmon":"világos lazacszín","silver":"ezüst","dimgrey":"halványszürke","orange":" [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "Alice kék",
+antiquewhite: "antik fehér",
+aqua: "vízszín",
+aquamarine: "akvamarin",
+azure: "azúrkék",
+beige: "bézs",
+bisque: "porcelán",
+black: "fekete",
+blanchedalmond: "hámozott mandula",
+blue: "kék",
+blueviolet: "ibolyakék",
+brown: "barna",
+burlywood: "nyersfa",
+cadetblue: "kadétkék",
+chartreuse: "chartreuse",
+chocolate: "csokoládé",
+coral: "korall",
+cornflowerblue: "búzavirágkék",
+cornsilk: "kukoricahaj",
+crimson: "karmazsinvörös",
+cyan: "ciánkék",
+darkblue: "sötétkék",
+darkcyan: "sötét ciánkék",
+darkgoldenrod: "sötét aranyvessző",
+darkgray: "sötétszürke",
+darkgreen: "sötétzöld",
+darkgrey: "sötétszürke", // same as darkgray
+darkkhaki: "sötét khakiszín",
+darkmagenta: "sötétbíbor",
+darkolivegreen: "sötét olajzöld",
+darkorange: "sötét narancssárga",
+darkorchid: "sötét orchidea",
+darkred: "sötétvörös",
+darksalmon: "sötét lazacszín",
+darkseagreen: "sötét tengerzöld",
+darkslateblue: "sötét palakék",
+darkslategray: "sötét palaszürke",
+darkslategrey: "sötét palaszürke", // same as darkslategray
+darkturquoise: "sötét türkizkék",
+darkviolet: "sötét ibolyaszín",
+deeppink: "sötétrózsaszín",
+deepskyblue: "sötét égszínkék",
+dimgray: "halványszürke",
+dimgrey: "halványszürke", // same as dimgray
+dodgerblue: "dodger kék",
+firebrick: "téglavörös",
+floralwhite: "virágfehér",
+forestgreen: "erdőzöld",
+fuchsia: "fukszia",
+gainsboro: "gainsboro",
+ghostwhite: "szellemfehér",
+gold: "arany",
+goldenrod: "aranyvessző",
+gray: "szürke",
+green: "zöld",
+greenyellow: "zöldessárga",
+grey: "szürke", // same as gray
+honeydew: "mézharmat",
+hotpink: "meleg rózsaszín",
+indianred: "indiánvörös",
+indigo: "indigó",
+ivory: "elefántcsont",
+khaki: "khakiszín",
+lavender: "levendula",
+lavenderblush: "pirosas levendula",
+lawngreen: "fűzöld",
+lemonchiffon: "sárga műselyem",
+lightblue: "világoskék",
+lightcoral: "világos korall",
+lightcyan: "világos ciánkék",
+lightgoldenrodyellow: "világos aranyvessző sárga",
+lightgray: "világosszürke",
+lightgreen: "világoszöld",
+lightgrey: "világosszürke", // same as lightgray
+lightpink: "világos rózsaszín",
+lightsalmon: "világos lazacszín",
+lightseagreen: "világos tengerzöld",
+lightskyblue: "világos égszínkék",
+lightslategray: "világos palaszürke",
+lightslategrey: "világos palaszürke", // same as lightslategray
+lightsteelblue: "világos acélkék",
+lightyellow: "világossárga",
+lime: "lime",
+limegreen: "limezöld",
+linen: "vászonfehér",
+magenta: "bíbor",
+maroon: "gesztenyebarna",
+mediumaquamarine: "közepes akvamarin",
+mediumblue: "közepes kék",
+mediumorchid: "közepes orchidea",
+mediumpurple: "közepes lila",
+mediumseagreen: "közepes tengerzöld",
+mediumslateblue: "közepes palakék",
+mediumspringgreen: "közepes tavaszzöld",
+mediumturquoise: "közepes türkizkék",
+mediumvioletred: "közepes ibolyavörös",
+midnightblue: "éjkék",
+mintcream: "mentaszósz",
+mistyrose: "halvány rózsaszín",
+moccasin: "mokkaszín",
+navajowhite: "navajo fehér",
+navy: "tengerészkék",
+oldlace: "régi csipke",
+olive: "olajzöld",
+olivedrab: "olajzöld drapp",
+orange: "narancssárga",
+orangered: "narancsvörös",
+orchid: "orchidea",
+palegoldenrod: "halvány aranyvessző",
+palegreen: "halványzöld",
+paleturquoise: "halvány türkizkék",
+palevioletred: "halvány ibolyavörös",
+papayawhip: "papayahab",
+peachpuff: "barackszín",
+peru: "peru",
+pink: "rózsaszín",
+plum: "szilvakék",
+powderblue: "púderkék",
+purple: "lila",
+red: "vörös",
+rosybrown: "barnásrózsaszín",
+royalblue: "királykék",
+saddlebrown: "nyeregbarna",
+salmon: "lazacszín",
+sandybrown: "homokbarna",
+seagreen: "tengerzöld",
+seashell: "kagyló",
+sienna: "vörösesbarna",
+silver: "ezüst",
+skyblue: "égszínkék",
+slateblue: "palakék",
+slategray: "palaszürke",
+slategrey: "palaszürke", // same as slategray
+snow: "hó",
+springgreen: "tavaszzöld",
+steelblue: "acélkék",
+tan: "rozsdabarna",
+teal: "pávakék",
+thistle: "bogáncs",
+tomato: "paradicsom",
+turquoise: "türkizkék",
+violet: "ibolyaszín",
+wheat: "búza",
+white: "fehér",
+whitesmoke: "fehér füst",
+yellow: "sárga",
+yellowgreen: "sárgászöld"
+})
diff --git a/dojo/nls/it/colors.js b/dojo/nls/it/colors.js
index 8a53007..7920c52 100644
--- a/dojo/nls/it/colors.js
+++ b/dojo/nls/it/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"blu acciao chiaro","orangered":"vermiglio","midnightblue":"blu melanzana scuro","cadetblue":"verde acqua","seashell":"sabbia rosa","slategrey":"grigio ardesia","coral":"corallo","darkturquoise":"turchese scuro","antiquewhite":"bianco antico","mediumspringgreen":"verde primavera medio","salmon":"salmone","darkgrey":"grigio scuro","ivory":"avorio","greenyellow":"giallo verde","mistyrose":"rosa pallido","lightsalmon":"salmone chiaro","silver":"grigio 25%","dimgrey":"grig [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "blu alice",
+antiquewhite: "bianco antico",
+aqua: "acqua",
+aquamarine: "acquamarina",
+azure: "azzurro ghiaccio",
+beige: "beige",
+bisque: "incarnato",
+black: "nero",
+blanchedalmond: "mandorla chiaro",
+blue: "blu",
+blueviolet: "blu violetto",
+brown: "marrone",
+burlywood: "tabacco",
+cadetblue: "verde acqua",
+chartreuse: "verde brillante",
+chocolate: "cioccolato",
+coral: "corallo",
+cornflowerblue: "blu fiordaliso",
+cornsilk: "crema",
+crimson: "cremisi",
+cyan: "ciano",
+darkblue: "blu scuro",
+darkcyan: "ciano scuro",
+darkgoldenrod: "ocra scuro",
+darkgray: "grigio scuro",
+darkgreen: "verde scuro",
+darkgrey: "grigio scuro", // same as darkgray
+darkkhaki: "kaki scuro",
+darkmagenta: "magenta scuro",
+darkolivegreen: "verde oliva scuro",
+darkorange: "arancione scuro",
+darkorchid: "orchidea scuro",
+darkred: "rosso scuro",
+darksalmon: "salmone scuro",
+darkseagreen: "verde mare scuro",
+darkslateblue: "blu ardesia scuro",
+darkslategray: "grigio ardesia scuro",
+darkslategrey: "grigio ardesia scuro", // same as darkslategray
+darkturquoise: "turchese scuro",
+darkviolet: "viola scuro",
+deeppink: "ciclamino",
+deepskyblue: "azzurro cielo scuro",
+dimgray: "grigio 80%",
+dimgrey: "grigio 80%", // same as dimgray
+dodgerblue: "blu d'oriente",
+firebrick: "rosso mattone",
+floralwhite: "bianco giglio",
+forestgreen: "verde foresta",
+fuchsia: "fucsia",
+gainsboro: "grigio 10%",
+ghostwhite: "bianco gesso",
+gold: "oro",
+goldenrod: "ocra gialla",
+gray: "grigio",
+green: "verde",
+greenyellow: "giallo verde",
+grey: "grigio", // same as gray
+honeydew: "bianco germoglio",
+hotpink: "rosa acceso",
+indianred: "terra indiana",
+indigo: "indaco",
+ivory: "avorio",
+khaki: "kaki",
+lavender: "lavanda",
+lavenderblush: "bianco rosato",
+lawngreen: "verde prato",
+lemonchiffon: "caffelatte chiaro",
+lightblue: "azzurro",
+lightcoral: "rosa corallo",
+lightcyan: "ciano chiaro",
+lightgoldenrodyellow: "giallo tenue",
+lightgray: "grigio chiaro",
+lightgreen: "verde chiaro",
+lightgrey: "grigio chiaro", // same as lightgray
+lightpink: "rosa chiaro",
+lightsalmon: "salmone chiaro",
+lightseagreen: "verde mare chiaro",
+lightskyblue: "azzurro cielo chiaro",
+lightslategray: "grigio ardesia chiaro",
+lightslategrey: "grigio ardesia chiaro", // same as lightslategray
+lightsteelblue: "blu acciao chiaro",
+lightyellow: "giallo chiaro",
+lime: "verde fluorescente",
+limegreen: "verde lime",
+linen: "lino",
+magenta: "magenta",
+maroon: "scarlatto",
+mediumaquamarine: "acquamarina medio",
+mediumblue: "blu medio",
+mediumorchid: "orchidea medio",
+mediumpurple: "porpora medio",
+mediumseagreen: "verde mare medio",
+mediumslateblue: "blu ardesia medio",
+mediumspringgreen: "verde primavera medio",
+mediumturquoise: "turchese medio",
+mediumvioletred: "vinaccia",
+midnightblue: "blu melanzana scuro",
+mintcream: "bianco nuvola",
+mistyrose: "rosa pallido",
+moccasin: "mocassino",
+navajowhite: "pesca chiaro",
+navy: "blu notte",
+oldlace: "mandorla",
+olive: "verde oliva",
+olivedrab: "marrone oliva",
+orange: "arancione",
+orangered: "vermiglio",
+orchid: "orchidea",
+palegoldenrod: "giallo zolfo chiaro",
+palegreen: "verde pallido",
+paleturquoise: "turchese pallido",
+palevioletred: "vinaccia chiaro",
+papayawhip: "cipria",
+peachpuff: "pesca",
+peru: "marrone terra bruciata",
+pink: "rosa",
+plum: "prugna",
+powderblue: "azzurro polvere",
+purple: "porpora",
+red: "rosso",
+rosybrown: "marrone rosato",
+royalblue: "blu reale",
+saddlebrown: "cacao",
+salmon: "salmone",
+sandybrown: "marrone sabbia",
+seagreen: "verde mare",
+seashell: "sabbia rosa",
+sienna: "cuoio",
+silver: "grigio 25%",
+skyblue: "azzurro cielo",
+slateblue: "blu ardesia",
+slategray: "grigio ardesia",
+slategrey: "grigio ardesia", // same as slategray
+snow: "neve",
+springgreen: "verde primavera",
+steelblue: "blu acciao",
+tan: "grigio bruno",
+teal: "verde turchese",
+thistle: "rosa cenere",
+tomato: "pomodoro",
+turquoise: "turchese",
+violet: "viola",
+wheat: "sabbia",
+white: "bianco",
+whitesmoke: "bianco fumo",
+yellow: "giallo",
+yellowgreen: "giallo verde"
+})
diff --git a/dojo/nls/ja/colors.js b/dojo/nls/ja/colors.js
index 46aa1f2..b68b04c 100644
--- a/dojo/nls/ja/colors.js
+++ b/dojo/nls/ja/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"ライト・スチール・ブルー","orangered":"オレンジ・レッド","midnightblue":"ミッドナイト・ブルー","cadetblue":"くすんだ青","seashell":"シーシェル","slategrey":"スレート・グレイ","coral":"珊瑚","darkturquoise":"ダーク・ターコイズ","antiquewhite":"アンティーク・ホワイト","mediumspringgreen":"ミディアム・スプリング・グリーン","salmon":"サーモン","darkgrey":"ダーク・グレイ","ivory":"アイボリー","greenyellow":"緑黄色","mistyrose":"ミスティ・ローズ","lightsalmon":"ライト・サーモン","silver":"銀","dimgrey":"くすんだグレイ","orange":"オレンジ","white":"白","navajowhite":"ナバホ・ホワイト","royalblue":"藤色","deeppink":" [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "アリス・ブルー",
+antiquewhite: "アンティーク・ホワイト",
+aqua: "アクア",
+aquamarine: "碧緑",
+azure: "薄い空色",
+beige: "ベージュ",
+bisque: "ビスク",
+black: "黒",
+blanchedalmond: "皮なしアーモンド",
+blue: "青",
+blueviolet: "青紫",
+brown: "茶",
+burlywood: "バーリーウッド",
+cadetblue: "くすんだ青",
+chartreuse: "淡黄緑",
+chocolate: "チョコレート",
+coral: "珊瑚",
+cornflowerblue: "コーンフラワー・ブルー",
+cornsilk: "コーンシルク",
+crimson: "深紅",
+cyan: "シアン・ブルー",
+darkblue: "ダーク・ブルー",
+darkcyan: "ダーク・シアン・ブルー",
+darkgoldenrod: "ダーク・ゴールデン・ロッド",
+darkgray: "ダーク・グレイ",
+darkgreen: "ダーク・グリーン",
+darkgrey: "ダーク・グレイ", // same as darkgray
+darkkhaki: "ダーク・カーキー",
+darkmagenta: "ダーク・マジェンタ",
+darkolivegreen: "ダーク・オリーブ・グリーン",
+darkorange: "ダーク・オレンジ",
+darkorchid: "ダーク・オーキッド",
+darkred: "ダーク・レッド",
+darksalmon: "ダーク・サーモン",
+darkseagreen: "ダーク・シー・グリーン",
+darkslateblue: "ダーク・スレート・ブルー",
+darkslategray: "ダーク・スレート・グレイ",
+darkslategrey: "ダーク・スレート・グレイ", // same as darkslategray
+darkturquoise: "ダーク・ターコイズ",
+darkviolet: "ダーク・バイオレット",
+deeppink: "濃いピンク",
+deepskyblue: "濃い空色",
+dimgray: "くすんだグレイ",
+dimgrey: "くすんだグレイ", // same as dimgray
+dodgerblue: "ドッジャー・ブルー",
+firebrick: "赤煉瓦色",
+floralwhite: "フローラル・ホワイト",
+forestgreen: "フォレスト・グリーン",
+fuchsia: "紫紅色",
+gainsboro: "ゲインズボーロ",
+ghostwhite: "ゴースト・ホワイト",
+gold: "金",
+goldenrod: "ゴールデン・ロッド",
+gray: "グレイ",
+green: "緑",
+greenyellow: "緑黄色",
+grey: "グレイ", // same as gray
+honeydew: "ハニーデュー",
+hotpink: "ホット・ピンク",
+indianred: "インディアン・レッド",
+indigo: "藍色",
+ivory: "アイボリー",
+khaki: "カーキー",
+lavender: "ラベンダー",
+lavenderblush: "ラベンダー・ブラッシ",
+lawngreen: "ローン・グリーン",
+lemonchiffon: "レモン・シフォン",
+lightblue: "ライト・ブルー",
+lightcoral: "ライト・コーラル",
+lightcyan: "ライト・シアン",
+lightgoldenrodyellow: "ライト・ゴールデン・ロッド・イエロー",
+lightgray: "ライト・グレイ",
+lightgreen: "ライト・グリーン",
+lightgrey: "ライト・グレイ", // same as lightgray
+lightpink: "ライト・ピンク",
+lightsalmon: "ライト・サーモン",
+lightseagreen: "ライト・シー・グリーン",
+lightskyblue: "ライト・スカイ・ブルー",
+lightslategray: "ライト・スレート・グレイ",
+lightslategrey: "ライト・スレート・グレイ", // same as lightslategray
+lightsteelblue: "ライト・スチール・ブルー",
+lightyellow: "ライト・イエロー",
+lime: "ライム",
+limegreen: "ライム・グリーン",
+linen: "亜麻色",
+magenta: "赤紫",
+maroon: "えび茶",
+mediumaquamarine: "ミディアム・アクアマリーン",
+mediumblue: "ミディアム・ブルー",
+mediumorchid: "ミディアム・オーキッド",
+mediumpurple: "ミディアム・パープル",
+mediumseagreen: "ミディアム・シー・グリーン",
+mediumslateblue: "ミディアム・スレート・ブルー",
+mediumspringgreen: "ミディアム・スプリング・グリーン",
+mediumturquoise: "ミディアム・ターコイズ",
+mediumvioletred: "ミディアム・バイオレット・レッド",
+midnightblue: "ミッドナイト・ブルー",
+mintcream: "ミント・クリーム",
+mistyrose: "ミスティ・ローズ",
+moccasin: "モカシン",
+navajowhite: "ナバホ・ホワイト",
+navy: "濃紺",
+oldlace: "オールド・レイス",
+olive: "オリーブ",
+olivedrab: "濃黄緑",
+orange: "オレンジ",
+orangered: "オレンジ・レッド",
+orchid: "薄紫",
+palegoldenrod: "ペイル・ゴールデン・ロッド",
+palegreen: "ペイル・グリーン",
+paleturquoise: "ペイル・ターコイズ",
+palevioletred: "ペイル・バイオレット・レッド",
+papayawhip: "パパイア・ホイップ",
+peachpuff: "ピーチ・パフ",
+peru: "ペルー",
+pink: "ピンク",
+plum: "深紫",
+powderblue: "淡青",
+purple: "紫",
+red: "赤",
+rosybrown: "ロージー・ブラウン",
+royalblue: "藤色",
+saddlebrown: "サドル・ブラウン",
+salmon: "サーモン",
+sandybrown: "砂褐色",
+seagreen: "シー・グリーン",
+seashell: "シーシェル",
+sienna: "黄褐色",
+silver: "銀",
+skyblue: "スカイ・ブルー",
+slateblue: "スレート・ブルー",
+slategray: "スレート・グレイ",
+slategrey: "スレート・グレイ", // same as slategray
+snow: "雪色",
+springgreen: "スプリング・グリーン",
+steelblue: "鋼色",
+tan: "茶褐色",
+teal: "ティール",
+thistle: "シスル",
+tomato: "トマト色",
+turquoise: "ターコイズ",
+violet: "すみれ色",
+wheat: "小麦色",
+white: "白",
+whitesmoke: "ホワイト・スモーク",
+yellow: "黄",
+yellowgreen: "黄緑"
+})
diff --git a/dojo/nls/ko/colors.js b/dojo/nls/ko/colors.js
index 0c6576b..9894a5f 100644
--- a/dojo/nls/ko/colors.js
+++ b/dojo/nls/ko/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"라이트 스틸 블루(light steel blue)","orangered":"오렌지 레드(orange red)","midnightblue":"미드나잇 블루(midnight blue)","cadetblue":"카뎃 블루(cadet blue)","seashell":"씨쉘(seashell)","slategrey":"슬레이트 그레이(slate gray)","coral":"코랄(coral)","darkturquoise":"다크 터콰즈(dark turquoise)","antiquewhite":"앤틱 화이트(antique white)","mediumspringgreen":"미디엄 스프링 그린(medium spring green)","salmon":"샐몬(salmon)","darkgrey":"다크 그레이(dark gray)","ivory":"아이보리(ivory)","greenyellow":"그린 옐로우(green-yellow)","mistyrose" [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "앨리스 블루(alice blue)",
+antiquewhite: "앤틱 화이트(antique white)",
+aqua: "아쿠아(aqua)",
+aquamarine: "아쿠아마린(aquamarine)",
+azure: "애쥬어(azure)",
+beige: "베이지(beige)",
+bisque: "비스크(bisque)",
+black: "블랙(black)",
+blanchedalmond: "블랜치 아몬드(blanched almond)",
+blue: "블루(blue)",
+blueviolet: "블루 바이올렛(blue-violet)",
+brown: "브라운(brown)",
+burlywood: "벌리우드(burlywood)",
+cadetblue: "카뎃 블루(cadet blue)",
+chartreuse: "샤르트뢰즈(chartreuse)",
+chocolate: "초콜렛(chocolate)",
+coral: "코랄(coral)",
+cornflowerblue: "콘플라워 블루(cornflower blue)",
+cornsilk: "콘실크(cornsilk)",
+crimson: "크림슨(crimson)",
+cyan: "시안(cyan)",
+darkblue: "다크 블루(dark blue)",
+darkcyan: "다크 시안(dark cyan)",
+darkgoldenrod: "다크 골든로드(dark goldenrod)",
+darkgray: "다크 그레이(dark gray)",
+darkgreen: "다크 그린(dark green)",
+darkgrey: "다크 그레이(dark gray)", // same as darkgray
+darkkhaki: "다크 카키(dark khaki)",
+darkmagenta: "다크 마젠타(dark magenta)",
+darkolivegreen: "다크 올리브 그린(dark olive green)",
+darkorange: "다크 오렌지(dark orange)",
+darkorchid: "다크 오키드(dark orchid)",
+darkred: "다크 레드(dark red)",
+darksalmon: "다크 샐몬(dark salmon)",
+darkseagreen: "다크 씨 그린(dark sea green)",
+darkslateblue: "다크 슬레이트 블루(dark slate blue)",
+darkslategray: "다크 슬레이트 그레이(dark slate gray)",
+darkslategrey: "다크 슬레이트 그레이(dark slate gray)", // same as darkslategray
+darkturquoise: "다크 터콰즈(dark turquoise)",
+darkviolet: "다크 바이올렛(dark violet)",
+deeppink: "딥 핑크(deep pink)",
+deepskyblue: "딥 스카이 블루(deep sky blue)",
+dimgray: "딤 그레이(dim gray)",
+dimgrey: "딤 그레이(dim gray)", // same as dimgray
+dodgerblue: "다저 블루(dodger blue)",
+firebrick: "파이어 브릭(fire brick)",
+floralwhite: "플로랄 화이트(floral white)",
+forestgreen: "포레스트 그린(forest green)",
+fuchsia: "후크샤(fuchsia)",
+gainsboro: "게인스브로(gainsboro)",
+ghostwhite: "고스트 화이트(ghost white)",
+gold: "골드(gold)",
+goldenrod: "골든로드(goldenrod)",
+gray: "그레이(gray)",
+green: "그린(green)",
+greenyellow: "그린 옐로우(green-yellow)",
+grey: "그레이(gray)", // same as gray
+honeydew: "허니듀(honeydew)",
+hotpink: "핫 핑크(hot pink)",
+indianred: "인디안 레드(indian red)",
+indigo: "인디고(indigo)",
+ivory: "아이보리(ivory)",
+khaki: "카키(khaki)",
+lavender: "라벤더(lavender)",
+lavenderblush: "라벤더 블러쉬(lavender blush)",
+lawngreen: "론 그린(lawn green)",
+lemonchiffon: "레몬 쉬폰(lemon chiffon)",
+lightblue: "라이트 블루(light blue)",
+lightcoral: "라이트 코랄(light coral)",
+lightcyan: "라이트 시안(light cyan)",
+lightgoldenrodyellow: "라이트 골든로드 옐로우(light goldenrod yellow)",
+lightgray: "라이트 그레이(light gray)",
+lightgreen: "라이트 그린(light green)",
+lightgrey: "라이트 그레이(light gray)", // same as lightgray
+lightpink: "라이트 핑크(light pink)",
+lightsalmon: "라이트 샐몬(light salmon)",
+lightseagreen: "라이트 씨 그린(light sea green)",
+lightskyblue: "라이트 스카이 블루(light sky blue)",
+lightslategray: "라이트 슬레이트 그레이(light slate gray)",
+lightslategrey: "라이트 슬레이트 그레이(light slate gray)", // same as lightslategray
+lightsteelblue: "라이트 스틸 블루(light steel blue)",
+lightyellow: "라이트 옐로우(light yellow)",
+lime: "라임(lime)",
+limegreen: "라임 그린(lime green)",
+linen: "리넨(linen)",
+magenta: "마젠타(magenta)",
+maroon: "마룬(maroon)",
+mediumaquamarine: "미디엄 아쿠아마린(medium aquamarine)",
+mediumblue: "미디엄 블루(medium blue)",
+mediumorchid: "미디엄 오키드(medium orchid)",
+mediumpurple: "미디엄 퍼플(medium purple)",
+mediumseagreen: "미디엄 씨 그린(medium sea green)",
+mediumslateblue: "미디엄 슬레이트 블루(medium slate blue)",
+mediumspringgreen: "미디엄 스프링 그린(medium spring green)",
+mediumturquoise: "미디엄 터콰즈(medium turquoise)",
+mediumvioletred: "미디엄 바이올렛 레드(medium violet-red)",
+midnightblue: "미드나잇 블루(midnight blue)",
+mintcream: "민트 크림(mint cream)",
+mistyrose: "미스티 로즈(misty rose)",
+moccasin: "모카신(moccasin)",
+navajowhite: "나바호 화이트(navajo white)",
+navy: "네이비(navy)",
+oldlace: "올드 레이스(old lace)",
+olive: "올리브(olive)",
+olivedrab: "올리브 드랩(olive drab)",
+orange: "오렌지(orange)",
+orangered: "오렌지 레드(orange red)",
+orchid: "오키드(orchid)",
+palegoldenrod: "페일 골든로드(pale goldenrod)",
+palegreen: "페일 그린(pale green)",
+paleturquoise: "페일 터콰즈(pale turquoise)",
+palevioletred: "페일 바이올렛 레드(pale violet-red)",
+papayawhip: "파파야 휩(papaya whip)",
+peachpuff: "피치 퍼프(peach puff)",
+peru: "페루(peru)",
+pink: "핑크(pink)",
+plum: "플럼(plum)",
+powderblue: "파우더 블루(powder blue)",
+purple: "퍼플(purple)",
+red: "레드(red)",
+rosybrown: "로지 브라운(rosy brown)",
+royalblue: "로얄 블루(royal blue)",
+saddlebrown: "새들 브라운(saddle brown)",
+salmon: "샐몬(salmon)",
+sandybrown: "샌디 브라운(sandy brown)",
+seagreen: "씨 그린(sea green)",
+seashell: "씨쉘(seashell)",
+sienna: "시에나(sienna)",
+silver: "실버(silver)",
+skyblue: "스카이 블루(sky blue)",
+slateblue: "슬레이트 블루(slate blue)",
+slategray: "슬레이트 그레이(slate gray)",
+slategrey: "슬레이트 그레이(slate gray)", // same as slategray
+snow: "스노우(snow)",
+springgreen: "스프링 그린(spring green)",
+steelblue: "스틸 블루(steel blue)",
+tan: "탠(tan)",
+teal: "틸(teal)",
+thistle: "시슬(thistle)",
+tomato: "토마토(tomato)",
+turquoise: "터콰즈(turquoise)",
+violet: "바이올렛(violet)",
+wheat: "휘트(wheat)",
+white: "화이트(white)",
+whitesmoke: "화이트 스모크(white smoke)",
+yellow: "옐로우(yellow)",
+yellowgreen: "옐로우 그린(yellow green)"
+})
diff --git a/dojo/nls/nb/colors.js b/dojo/nls/nb/colors.js
index 15770a4..e347cbe 100644
--- a/dojo/nls/nb/colors.js
+++ b/dojo/nls/nb/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"lys stålblå","orangered":"rødoransje","midnightblue":"midnattsblå","cadetblue":"mørk grønnblå","seashell":"skjellhvit","slategrey":"skifergrå","coral":"korall","darkturquoise":"mørk turkis","antiquewhite":"antikk hvit","mediumspringgreen":"middels vårgrønn","salmon":"lakserosa","darkgrey":"mørk grå","ivory":"elfenbenshvit","greenyellow":"gulgrønn","mistyrose":"lys rosenrød","lightsalmon":"lys lakserosa","silver":"sølvfarget","dimgrey":"mørk mørkegrå","orange":"oransje [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "blåhvit",
+antiquewhite: "antikk hvit",
+aqua: "akva",
+aquamarine: "akvamarin",
+azure: "asur",
+beige: "beige",
+bisque: "gulrosa",
+black: "svart",
+blanchedalmond: "lys mandel",
+blue: "blå",
+blueviolet: "blåfiolett",
+brown: "brun",
+burlywood: "matt mellombrun",
+cadetblue: "mørk grønnblå",
+chartreuse: "løvgrønn",
+chocolate: "sjokolade",
+coral: "korall",
+cornflowerblue: "kornblå",
+cornsilk: "cornsilk",
+crimson: "karmosinrødt",
+cyan: "cyan",
+darkblue: "mørk blå",
+darkcyan: "mørk cyan",
+darkgoldenrod: "mørk gyldenris",
+darkgray: "mørk grå",
+darkgreen: "mørk grønn",
+darkgrey: "mørk grå", // same as darkgray
+darkkhaki: "mørk khaki",
+darkmagenta: "mørk magenta",
+darkolivegreen: "mørk olivengrønn",
+darkorange: "mørk oransje",
+darkorchid: "mørk orkide",
+darkred: "mørk rød",
+darksalmon: "mørk lakserosa",
+darkseagreen: "mørk sjøgrønn",
+darkslateblue: "mørk skiferblå",
+darkslategray: "mørk skifergrå",
+darkslategrey: "mørk skifergrå", // same as darkslategray
+darkturquoise: "mørk turkis",
+darkviolet: "mørk fiolett",
+deeppink: "dyp rosa",
+deepskyblue: "dyp himmelblå",
+dimgray: "mørk mørkegrå",
+dimgrey: "mørk mørkegrå", // same as dimgray
+dodgerblue: "lys havblå",
+firebrick: "mursteinsrød",
+floralwhite: "blomsterhvit",
+forestgreen: "skoggrønn",
+fuchsia: "fuksia",
+gainsboro: "lys lys grå",
+ghostwhite: "egghvit",
+gold: "gull",
+goldenrod: "gyldenris",
+gray: "grå",
+green: "grønn",
+greenyellow: "gulgrønn",
+grey: "grå", // same as gray
+honeydew: "grønnhvit",
+hotpink: "halvmørk rosa",
+indianred: "rustrød",
+indigo: "indigo",
+ivory: "elfenbenshvit",
+khaki: "khaki",
+lavender: "lavendel",
+lavenderblush: "lillahvit",
+lawngreen: "plengrønn",
+lemonchiffon: "ferskenfarget",
+lightblue: "lys blå",
+lightcoral: "lys korall",
+lightcyan: "lys cyan",
+lightgoldenrodyellow: "lys gyldenrisgul",
+lightgray: "lys grå",
+lightgreen: "lys grønn",
+lightgrey: "lys grå", // same as lightgray
+lightpink: "lys rosa",
+lightsalmon: "lys lakserosa",
+lightseagreen: "lys sjøgrønn",
+lightskyblue: "lys himmelblå",
+lightslategray: "lys skifergrå",
+lightslategrey: "lys skifergrå", // same as lightslategray
+lightsteelblue: "lys stålblå",
+lightyellow: "lys gul",
+lime: "lime",
+limegreen: "limegrønn",
+linen: "lin",
+magenta: "magenta",
+maroon: "rødbrun",
+mediumaquamarine: "middels akvamarin",
+mediumblue: "mellomblå",
+mediumorchid: "middels orkide",
+mediumpurple: "middels purpur",
+mediumseagreen: "middels sjøgrønn",
+mediumslateblue: "middels skiferblå",
+mediumspringgreen: "middels vårgrønn",
+mediumturquoise: "middels turkis",
+mediumvioletred: "middels fiolettrød",
+midnightblue: "midnattsblå",
+mintcream: "mintkrem",
+mistyrose: "lys rosenrød",
+moccasin: "lys gulbrun",
+navajowhite: "gulbrun",
+navy: "marineblå",
+oldlace: "kniplingshvit",
+olive: "oliven",
+olivedrab: "middels olivengrønn",
+orange: "oransje",
+orangered: "rødoransje",
+orchid: "orkide",
+palegoldenrod: "svak gyldenris",
+palegreen: "svak grønn",
+paleturquoise: "svak turkis",
+palevioletred: "svak fiolettrød",
+papayawhip: "lys papaya",
+peachpuff: "brunrosa",
+peru: "lys nøttebrun",
+pink: "rosa",
+plum: "plommefarget",
+powderblue: "lys grønnblå",
+purple: "purpur",
+red: "rød",
+rosybrown: "brunlilla",
+royalblue: "kongeblå",
+saddlebrown: "mørk nøttebrun",
+salmon: "lakserosa",
+sandybrown: "sandbrun",
+seagreen: "sjøgrønn",
+seashell: "skjellhvit",
+sienna: "nøttebrun",
+silver: "sølvfarget",
+skyblue: "himmelblå",
+slateblue: "skiferblå",
+slategray: "skifergrå",
+slategrey: "skifergrå", // same as slategray
+snow: "snøhvit",
+springgreen: "vårgrønn",
+steelblue: "stålblå",
+tan: "matt mellombrun",
+teal: "mørk grønnblå",
+thistle: "lys grålilla",
+tomato: "tomatrød",
+turquoise: "turkis",
+violet: "fiolett",
+wheat: "varm sienna",
+white: "hvit",
+whitesmoke: "røykhvit",
+yellow: "gul",
+yellowgreen: "gulgrønn"
+})
diff --git a/dojo/nls/nl/colors.js b/dojo/nls/nl/colors.js
index ae0ccbf..cbcb95f 100644
--- a/dojo/nls/nl/colors.js
+++ b/dojo/nls/nl/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"lichtstaalblauw","orangered":"oranjerood","midnightblue":"nachtblauw","cadetblue":"donkerstaalblauw","seashell":"schelp","slategrey":"leigrijs","coral":"koraalrood","darkturquoise":"donkerturquoise","antiquewhite":"antiekwit","mediumspringgreen":"midlentegroen","salmon":"zalm","darkgrey":"donkergrijs","ivory":"ivoorwit","greenyellow":"groengeel","mistyrose":"matroze","lightsalmon":"lichtzalm","silver":"zilvergrijs","dimgrey":"dofgrijs","orange":"oranje","white":"wit", [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "lichtblauw",
+antiquewhite: "antiekwit",
+aqua: "aqua",
+aquamarine: "aquamarijn",
+azure: "azuur",
+beige: "beige",
+bisque: "oranjegeel",
+black: "zwart",
+blanchedalmond: "amandel",
+blue: "blauw",
+blueviolet: "violet",
+brown: "bruin",
+burlywood: "lichtbruin",
+cadetblue: "donkerstaalblauw",
+chartreuse: "groengeel",
+chocolate: "chocoladebruin",
+coral: "koraalrood",
+cornflowerblue: "korenbloemblauw",
+cornsilk: "maïsgeel",
+crimson: "karmozijnrood",
+cyan: "cyaan",
+darkblue: "donkerblauw",
+darkcyan: "donkercyaan",
+darkgoldenrod: "donkergoud",
+darkgray: "donkergrijs",
+darkgreen: "donkergroen",
+darkgrey: "donkergrijs", // same as darkgray
+darkkhaki: "donkerkaki",
+darkmagenta: "donkermagenta",
+darkolivegreen: "donkerolijfgroen",
+darkorange: "donkeroranje",
+darkorchid: "donkerorchidee",
+darkred: "donkerrood",
+darksalmon: "donkerzalm",
+darkseagreen: "donkerzeegroen",
+darkslateblue: "donkergrijsblauw",
+darkslategray: "donkerblauwgrijs",
+darkslategrey: "donkerblauwgrijs", // same as darkslategray
+darkturquoise: "donkerturquoise",
+darkviolet: "donkerviolet",
+deeppink: "donkerroze",
+deepskyblue: "diephemelblauw",
+dimgray: "dofgrijs",
+dimgrey: "dofgrijs", // same as dimgray
+dodgerblue: "helderblauw",
+firebrick: "vuursteenrood",
+floralwhite: "rozewit",
+forestgreen: "bosgroen",
+fuchsia: "fuchsia",
+gainsboro: "lichtblauwgrijs",
+ghostwhite: "spierwit",
+gold: "goud",
+goldenrod: "goudbruin",
+gray: "grijs",
+green: "groen",
+greenyellow: "groengeel",
+grey: "grijs", // same as gray
+honeydew: "meloen",
+hotpink: "acaciaroze",
+indianred: "indisch rood",
+indigo: "indigo",
+ivory: "ivoorwit",
+khaki: "kaki",
+lavender: "lavendelblauw",
+lavenderblush: "lavendelblos",
+lawngreen: "grasgroen",
+lemonchiffon: "citroengeel",
+lightblue: "lichtblauw",
+lightcoral: "lichtkoraal",
+lightcyan: "lichtcyaan",
+lightgoldenrodyellow: "lichtgoudgeel",
+lightgray: "lichtgrijs",
+lightgreen: "lichtgroen",
+lightgrey: "lichtgrijs", // same as lightgray
+lightpink: "lichtroze",
+lightsalmon: "lichtzalm",
+lightseagreen: "lichtzeegroen",
+lightskyblue: "lichthemelsblauw",
+lightslategray: "lichtblauwgrijs",
+lightslategrey: "lichtblauwgrijs", // same as lightslategray
+lightsteelblue: "lichtstaalblauw",
+lightyellow: "lichtgeel",
+lime: "limoen",
+limegreen: "limoengroen",
+linen: "linnen",
+magenta: "magenta",
+maroon: "kastanjebruin",
+mediumaquamarine: "midaquamarijn",
+mediumblue: "midblauw",
+mediumorchid: "midorchidee",
+mediumpurple: "midpurper",
+mediumseagreen: "midzeegroen",
+mediumslateblue: "midgrijsblauw",
+mediumspringgreen: "midlentegroen",
+mediumturquoise: "midturquoise",
+mediumvioletred: "midvioletrood",
+midnightblue: "nachtblauw",
+mintcream: "mintroomgeel",
+mistyrose: "matroze",
+moccasin: "moccasin",
+navajowhite: "navajowit",
+navy: "marineblauw",
+oldlace: "kant",
+olive: "olijfgroen",
+olivedrab: "grijsbruin",
+orange: "oranje",
+orangered: "oranjerood",
+orchid: "orchidee",
+palegoldenrod: "bleekgeel",
+palegreen: "bleekgroen",
+paleturquoise: "bleekturquoise",
+palevioletred: "bleekvioletrood",
+papayawhip: "papajaroze",
+peachpuff: "perzikroze",
+peru: "bruin",
+pink: "roze",
+plum: "pruim",
+powderblue: "lichtblauw-wit",
+purple: "purper",
+red: "rood",
+rosybrown: "roodbruin",
+royalblue: "koningsblauw",
+saddlebrown: "leerbruin",
+salmon: "zalm",
+sandybrown: "zandbruin",
+seagreen: "zeegroen",
+seashell: "schelp",
+sienna: "sienna",
+silver: "zilvergrijs",
+skyblue: "hemelsblauw",
+slateblue: "leiblauw",
+slategray: "leigrijs",
+slategrey: "leigrijs", // same as slategray
+snow: "sneeuwwit",
+springgreen: "lentegroen",
+steelblue: "staalblauw",
+tan: "geelbruin",
+teal: "grijsblauw",
+thistle: "distel",
+tomato: "tomaat",
+turquoise: "turquoise",
+violet: "violet",
+wheat: "tarwebruin",
+white: "wit",
+whitesmoke: "rookwit",
+yellow: "geel",
+yellowgreen: "geelgroen"
+})
diff --git a/dojo/nls/pl/colors.js b/dojo/nls/pl/colors.js
index 852268c..c4cc3cd 100644
--- a/dojo/nls/pl/colors.js
+++ b/dojo/nls/pl/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"jasny stalowoniebieski","orangered":"pomarańczowoczerwony","midnightblue":"ciemnogranatowy","cadetblue":"niebieskoszary","seashell":"muszla","slategrey":"łupkowy szary","coral":"koralowy","darkturquoise":"ciemnoturkusowy","antiquewhite":"biel antyczna","mediumspringgreen":"średnia wiosenna zieleń","salmon":"łososiowy","darkgrey":"ciemnoszary","ivory":"kość słoniowa","greenyellow":"zielonożółty","mistyrose":"bladoróżany","lightsalmon":"jasnołososiowy","silver":"srebrny [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "bladoniebieski",
+antiquewhite: "biel antyczna",
+aqua: "wodny",
+aquamarine: "akwamaryna",
+azure: "lazur",
+beige: "beżowy",
+bisque: "biszkoptowy",
+black: "czarny",
+blanchedalmond: "migdałowy",
+blue: "niebieski",
+blueviolet: "niebieskofioletowy",
+brown: "brązowy",
+burlywood: "kolor drewna",
+cadetblue: "niebieskoszary",
+chartreuse: "jaskrawozielony",
+chocolate: "czekoladowy",
+coral: "koralowy",
+cornflowerblue: "chabrowy",
+cornsilk: "kukurydziany",
+crimson: "karmazynowy",
+cyan: "cyjan",
+darkblue: "ciemnoniebieski",
+darkcyan: "ciemny cyjan",
+darkgoldenrod: "ciemnogliniany",
+darkgray: "ciemnoszary",
+darkgreen: "ciemnozielony",
+darkgrey: "ciemnoszary", // same as darkgray
+darkkhaki: "ciemny khaki",
+darkmagenta: "ciemna magenta",
+darkolivegreen: "ciemnooliwkowy",
+darkorange: "ciemnopomarańczowy",
+darkorchid: "ciemna orchidea",
+darkred: "ciemnoczerwony",
+darksalmon: "ciemnołososiowy",
+darkseagreen: "ciemna morska zieleń",
+darkslateblue: "ciemny łupkowy niebieski",
+darkslategray: "ciemny łupkowy szary",
+darkslategrey: "ciemny łupkowy szary", // same as darkslategray
+darkturquoise: "ciemnoturkusowy",
+darkviolet: "ciemnofioletowy",
+deeppink: "głęboki różowy",
+deepskyblue: "intensywny błękit nieba",
+dimgray: "przytłumiony szary",
+dimgrey: "przytłumiony szary", // same as dimgray
+dodgerblue: "błękit Dodgers",
+firebrick: "ceglasty",
+floralwhite: "kwiatowa biel",
+forestgreen: "leśna zieleń",
+fuchsia: "fuksja",
+gainsboro: "bladoszary",
+ghostwhite: "bladobiały",
+gold: "złoty",
+goldenrod: "gliniany",
+gray: "szary",
+green: "zielony",
+greenyellow: "zielonożółty",
+grey: "szary", // same as gray
+honeydew: "melon",
+hotpink: "intensywny różowy",
+indianred: "kasztanowy",
+indigo: "indygo",
+ivory: "kość słoniowa",
+khaki: "khaki",
+lavender: "lawendowy",
+lavenderblush: "lawendoworóżowy",
+lawngreen: "trawiasty",
+lemonchiffon: "cytrynowy",
+lightblue: "jasnoniebieski",
+lightcoral: "jasnokoralowy",
+lightcyan: "jasny cyjan",
+lightgoldenrodyellow: "jasnogliniana żółć",
+lightgray: "jasnoszary",
+lightgreen: "jasnozielony",
+lightgrey: "jasnoszary", // same as lightgray
+lightpink: "jasnoróżowy",
+lightsalmon: "jasnołososiowy",
+lightseagreen: "jasna morska zieleń",
+lightskyblue: "jasny błękit nieba",
+lightslategray: "jasny łupkowy szary",
+lightslategrey: "jasny łupkowy szary", // same as lightslategray
+lightsteelblue: "jasny stalowoniebieski",
+lightyellow: "jasnożółty",
+lime: "limetkowy",
+limegreen: "limetkowozielony",
+linen: "lniany",
+magenta: "magenta",
+maroon: "bordowy",
+mediumaquamarine: "średnia akwamaryna",
+mediumblue: "średni niebieski",
+mediumorchid: "średnia orchidea",
+mediumpurple: "średnia purpura",
+mediumseagreen: "średnia morska zieleń",
+mediumslateblue: "średni łupkowy niebieski",
+mediumspringgreen: "średnia wiosenna zieleń",
+mediumturquoise: "średni turkusowy",
+mediumvioletred: "średni fioletowoczerwony",
+midnightblue: "ciemnogranatowy",
+mintcream: "jasnomiętowy",
+mistyrose: "bladoróżany",
+moccasin: "mokasynowy",
+navajowhite: "piaskowy",
+navy: "granatowy",
+oldlace: "bladopomarańczowy",
+olive: "oliwkowy",
+olivedrab: "oliwkowa zieleń",
+orange: "pomarańczowy",
+orangered: "pomarańczowoczerwony",
+orchid: "orchidea",
+palegoldenrod: "bladogliniany",
+palegreen: "bladozielony",
+paleturquoise: "bladoturkusowy",
+palevioletred: "blady fioletowoczerwony",
+papayawhip: "papaja",
+peachpuff: "brzoskwiniowy",
+peru: "jasnobrązowy",
+pink: "różowy",
+plum: "śliwkowy",
+powderblue: "pudrowy niebieski",
+purple: "purpurowy",
+red: "czerwony",
+rosybrown: "różowobrązowy",
+royalblue: "błękit królewski",
+saddlebrown: "skórzany brązowy",
+salmon: "łososiowy",
+sandybrown: "piaskowy brąz",
+seagreen: "morska zieleń",
+seashell: "muszla",
+sienna: "siena",
+silver: "srebrny",
+skyblue: "błękit nieba",
+slateblue: "łupkowy niebieski",
+slategray: "łupkowy szary",
+slategrey: "łupkowy szary", // same as slategray
+snow: "śnieżny",
+springgreen: "wiosenna zieleń",
+steelblue: "stalowy niebieski",
+tan: "kawowy",
+teal: "cyrankowy",
+thistle: "bladofioletowy",
+tomato: "pomidorowy",
+turquoise: "turkusowy",
+violet: "fioletowy",
+wheat: "pszeniczny",
+white: "biały",
+whitesmoke: "przydymiony biały",
+yellow: "żółty",
+yellowgreen: "żółtozielony"
+})
diff --git a/dojo/nls/pt-pt/colors.js b/dojo/nls/pt-pt/colors.js
index e01afd2..62be391 100644
--- a/dojo/nls/pt-pt/colors.js
+++ b/dojo/nls/pt-pt/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"azul-aço claro","orangered":"vermelho alaranjado","midnightblue":"azul meia-noite","cadetblue":"azul cadete","seashell":"concha","slategrey":"cinzento ardósia","coral":"coral","darkturquoise":"turquesa escuro","antiquewhite":"branco antigo","mediumspringgreen":"verde primavera médio","salmon":"salmão","darkgrey":"cinzento escuro","ivory":"marfim","greenyellow":"amarelo esverdeado","mistyrose":"rosa pálido","lightsalmon":"salmão claro","silver":"prateado","dimgrey":"ci [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "azul alice",
+antiquewhite: "branco antigo",
+aqua: "verde-água",
+aquamarine: "verde-azulado",
+azure: "azul-celeste",
+beige: "bege",
+bisque: "rosa-velho",
+black: "preto",
+blanchedalmond: "amêndoa claro",
+blue: "azul",
+blueviolet: "azul violeta",
+brown: "castanho",
+burlywood: "castanho pinho",
+cadetblue: "azul cadete",
+chartreuse: "amarelo esverdeado",
+chocolate: "chocolate",
+coral: "coral",
+cornflowerblue: "azul-violáceo",
+cornsilk: "branco seda",
+crimson: "carmesim",
+cyan: "ciano",
+darkblue: "azul escuro",
+darkcyan: "ciano escuro",
+darkgoldenrod: "ouro velho escuro",
+darkgray: "cinzento escuro",
+darkgreen: "verde escuro",
+darkgrey: "cinzento escuro", // same as darkgray
+darkkhaki: "caqui escuro",
+darkmagenta: "magenta escuro",
+darkolivegreen: "verde-azeitona escuro",
+darkorange: "laranja escuro",
+darkorchid: "orquídea escuro",
+darkred: "vermelho escuro",
+darksalmon: "salmão escuro",
+darkseagreen: "verde marinho escuro",
+darkslateblue: "azul ardósia escuro",
+darkslategray: "cinzento ardósia escuro",
+darkslategrey: "cinzento ardósia escuro",// same as darkslategray
+darkturquoise: "turquesa escuro",
+darkviolet: "violeta escuro",
+deeppink: "rosa profundo",
+deepskyblue: "azul céu profundo",
+dimgray: "cinzento escuro",
+dimgrey: "cinzento escuro", // same as dimgray
+dodgerblue: "azul furtivo",
+firebrick: "tijolo fogo",
+floralwhite: "branco floral",
+forestgreen: "verde floresta",
+fuchsia: "fúcsia",
+gainsboro: "cinzento azulado claro",
+ghostwhite: "branco sombreado",
+gold: "dourado",
+goldenrod: "ouro velho",
+gray: "cinzento",
+green: "verde",
+greenyellow: "amarelo esverdeado",
+grey: "cinzento", // same as gray
+honeydew: "mel",
+hotpink: "rosa forte",
+indianred: "almagre",
+indigo: "índigo",
+ivory: "marfim",
+khaki: "caqui",
+lavender: "alfazema",
+lavenderblush: "alfazema rosado",
+lawngreen: "verde relva",
+lemonchiffon: "limão chiffon",
+lightblue: "azul claro",
+lightcoral: "coral claro",
+lightcyan: "ciano claro",
+lightgoldenrodyellow: "ouro velho amarelado claro",
+lightgray: "cinzento claro",
+lightgreen: "verde claro",
+lightgrey: "cinzento claro", // same as lightgray
+lightpink: "rosa claro",
+lightsalmon: "salmão claro",
+lightseagreen: "verde marinho claro",
+lightskyblue: "azul céu claro",
+lightslategray: "cinzento ardósia claro",
+lightslategrey: "cinzento ardósia claro", // same as lightslategray
+lightsteelblue: "azul-aço claro",
+lightyellow: "amarelo claro",
+lime: "lima",
+limegreen: "verde-lima",
+linen: "linho",
+magenta: "magenta",
+maroon: "bordeaux",
+mediumaquamarine: "verde-azulado médio",
+mediumblue: "azul médio",
+mediumorchid: "orquídea médio",
+mediumpurple: "roxo médio",
+mediumseagreen: "verde marinho médio",
+mediumslateblue: "azul ardósia médio",
+mediumspringgreen: "verde primavera médio",
+mediumturquoise: "turquesa médio",
+mediumvioletred: "violeta avermelhado médio",
+midnightblue: "azul meia-noite",
+mintcream: "creme de menta",
+mistyrose: "rosa pálido",
+moccasin: "mocassim",
+navajowhite: "branco navajo",
+navy: "azul marinho",
+oldlace: "renda antiga",
+olive: "azeitona",
+olivedrab: "azeitona claro",
+orange: "laranja",
+orangered: "vermelho alaranjado",
+orchid: "orquídea",
+palegoldenrod: "ouro velho pálido",
+palegreen: "verde pálido",
+paleturquoise: "turquesa pálido",
+palevioletred: "violeta avermelhado pálido",
+papayawhip: "creme de papaia",
+peachpuff: "pêssego",
+peru: "peru",
+pink: "rosa",
+plum: "cor-de-ameixa",
+powderblue: "azul de esmalte",
+purple: "roxo",
+red: "vermelho",
+rosybrown: "castanho rosado",
+royalblue: "azul real",
+saddlebrown: "castanho sela",
+salmon: "salmão",
+sandybrown: "castanho areia",
+seagreen: "verde marinho",
+seashell: "concha",
+sienna: "castanho-avermelhado",
+silver: "prateado",
+skyblue: "azul céu",
+slateblue: "azul ardósia",
+slategray: "cinzento ardósia",
+slategrey: "cinzento ardósia", // same as slategray
+snow: "branco-neve",
+springgreen: "verde primavera",
+steelblue: "azul-aço",
+tan: "castanho claro",
+teal: "verde-azulado",
+thistle: "cardo",
+tomato: "vermelho tomate",
+turquoise: "turquesa",
+violet: "violeta",
+wheat: "trigo",
+white: "branco",
+whitesmoke: "fumo branco",
+yellow: "amarelo",
+yellowgreen: "verde amarelado"
+}) 
\ No newline at end of file
diff --git a/dojo/nls/pt/colors.js b/dojo/nls/pt/colors.js
index 897efc3..12471fa 100644
--- a/dojo/nls/pt/colors.js
+++ b/dojo/nls/pt/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"azul-aço claro","orangered":"vermelho alaranjado","midnightblue":"azul meia-noite","cadetblue":"azul cadet","seashell":"seashell","slategrey":"cinza-ardósia","coral":"coral","darkturquoise":"turquesa escuro","antiquewhite":"branco antigo","mediumspringgreen":"verde-primavera médio","salmon":"salmão","darkgrey":"cinza escuro","ivory":"marfim","greenyellow":"amarelo esverdeado","mistyrose":"rosa enevoado","lightsalmon":"salmão claro","silver":"prateado","dimgrey":"cinza [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "azul alice",
+antiquewhite: "branco antigo",
+aqua: "aqua",
+aquamarine: "água-marinha",
+azure: "azul-celeste",
+beige: "bege",
+bisque: "bisque",
+black: "preto",
+blanchedalmond: "amêndoa pelada",
+blue: "azul",
+blueviolet: "azul-violeta",
+brown: "marrom",
+burlywood: "burlywood",
+cadetblue: "azul cadet",
+chartreuse: "chartreuse",
+chocolate: "chocolate",
+coral: "coral",
+cornflowerblue: "azul centaurea",
+cornsilk: "cornsilk",
+crimson: "carmesim",
+cyan: "ciano",
+darkblue: "azul escuro",
+darkcyan: "ciano escuro",
+darkgoldenrod: "goldenrod escuro",
+darkgray: "cinza escuro",
+darkgreen: "verde escuro",
+darkgrey: "cinza escuro", // same as darkgray
+darkkhaki: "cáqui escuro",
+darkmagenta: "magenta escuro",
+darkolivegreen: "verde oliva escuro",
+darkorange: "laranja escuro",
+darkorchid: "orquídea escuro",
+darkred: "vermelho escuro",
+darksalmon: "salmão escuro",
+darkseagreen: "verde marinho escuro",
+darkslateblue: "azul-ardósia escuro",
+darkslategray: "cinza-ardósia escuro",
+darkslategrey: "cinza-ardósia escuro", // same as darkslategray
+darkturquoise: "turquesa escuro",
+darkviolet: "violeta escuro",
+deeppink: "rosa profundo",
+deepskyblue: "azul-céu intenso",
+dimgray: "cinza turvo",
+dimgrey: "cinza turvo", // same as dimgray
+dodgerblue: "azul dodger",
+firebrick: "firebrick",
+floralwhite: "branco floral",
+forestgreen: "verde floresta",
+fuchsia: "fúcsia",
+gainsboro: "gainsboro",
+ghostwhite: "branco ghost",
+gold: "dourado",
+goldenrod: "goldenrod",
+gray: "cinza",
+green: "verde",
+greenyellow: "amarelo esverdeado",
+grey: "cinza", // same as gray
+honeydew: "honeydew",
+hotpink: "rosa quente",
+indianred: "vermelho indiano",
+indigo: "índigo",
+ivory: "marfim",
+khaki: "cáqui",
+lavender: "lavanda",
+lavenderblush: "lavanda avermelhada",
+lawngreen: "verde grama",
+lemonchiffon: "limão chiffon",
+lightblue: "azul claro",
+lightcoral: "coral claro",
+lightcyan: "ciano claro",
+lightgoldenrodyellow: "amarelo goldenrod claro",
+lightgray: "cinza claro",
+lightgreen: "verde claro",
+lightgrey: "cinza claro", // same as lightgray
+lightpink: "rosa claro",
+lightsalmon: "salmão claro",
+lightseagreen: "verde marinho claro",
+lightskyblue: "azul-céu claro",
+lightslategray: "cinza-ardósia claro",
+lightslategrey: "cinza-ardósia claro", // same as lightslategray
+lightsteelblue: "azul-aço claro",
+lightyellow: "amarelo claro",
+lime: "lima",
+limegreen: "verde-lima",
+linen: "linho",
+magenta: "magenta",
+maroon: "marrom",
+mediumaquamarine: "água-marinha médio",
+mediumblue: "azul médio",
+mediumorchid: "orquídea médio",
+mediumpurple: "roxo médio",
+mediumseagreen: "verde-marinho médio",
+mediumslateblue: "azul-ardósia médio",
+mediumspringgreen: "verde-primavera médio",
+mediumturquoise: "turquesa médio",
+mediumvioletred: "vermelho-violeta médio",
+midnightblue: "azul meia-noite",
+mintcream: "creme de menta",
+mistyrose: "rosa enevoado",
+moccasin: "moccasin",
+navajowhite: "branco navajo",
+navy: "marinho",
+oldlace: "cadarço velho",
+olive: "oliva",
+olivedrab: "verde oliva",
+orange: "laranja",
+orangered: "vermelho alaranjado",
+orchid: "orquídea",
+palegoldenrod: "goldenrod esbranquiçado",
+palegreen: "verde esbranquiçado",
+paleturquoise: "turquesa esbranquiçado",
+palevioletred: "vermelho-violeta esbranquiçado",
+papayawhip: "creme de papaya",
+peachpuff: "peach puff",
+peru: "peru",
+pink: "rosa",
+plum: "ameixa",
+powderblue: "azul-talco",
+purple: "roxo",
+red: "vermelho",
+rosybrown: "marrom rosado",
+royalblue: "azul royal",
+saddlebrown: "marrom saddle",
+salmon: "salmão",
+sandybrown: "marrom cor de areia",
+seagreen: "verde-marinho",
+seashell: "seashell",
+sienna: "sienna",
+silver: "prateado",
+skyblue: "azul-céu",
+slateblue: "azul-ardósia",
+slategray: "cinza-ardósia",
+slategrey: "cinza-ardósia", // same as slategray
+snow: "branco neve",
+springgreen: "verde primavera",
+steelblue: "azul-aço",
+tan: "tan",
+teal: "azul esverdeado",
+thistle: "thistle",
+tomato: "tomate",
+turquoise: "turquesa",
+violet: "violeta",
+wheat: "trigo",
+white: "branco",
+whitesmoke: "fumaça branca",
+yellow: "amarelo",
+yellowgreen: "verde amarelado"
+})
diff --git a/dojo/nls/ro/colors.js b/dojo/nls/ro/colors.js
new file mode 100644
index 0000000..52a05a4
--- /dev/null
+++ b/dojo/nls/ro/colors.js
@@ -0,0 +1,155 @@
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "alice blue",
+antiquewhite: "antique white",
+aqua: "aqua",
+aquamarine: "aquamarine",
+azure: "azuriu",
+beige: "bej",
+bisque: "bisque",
+black: "negru",
+blanchedalmond: "blanched almond",
+blue: "albastru",
+blueviolet: "albastru-violet",
+brown: "maro",
+burlywood: "burlywood",
+cadetblue: "cadet blue",
+chartreuse: "chartreuse",
+chocolate: "ciocolată",
+coral: "coral",
+cornflowerblue: "cornflower blue",
+cornsilk: "cornsilk",
+crimson: "crimson",
+cyan: "cyan",
+darkblue: "albastru închis",
+darkcyan: "cyan închis",
+darkgoldenrod: "goldenrod închis",
+darkgray: "cenuşiu închis",
+darkgreen: "verde închis",
+darkgrey: "gri închis", // same as darkgray
+darkkhaki: "kaki închis",
+darkmagenta: "magenta închis",
+darkolivegreen: "verde oliv închis",
+darkorange: "portocaliu închis",
+darkorchid: "dark orchid",
+darkred: "roşu închis",
+darksalmon: "dark salmon",
+darkseagreen: "dark sea green",
+darkslateblue: "dark slate blue",
+darkslategray: "dark slate gray",
+darkslategrey: "dark slate gray", // same as darkslategray
+darkturquoise: "dark turquoise",
+darkviolet: "violet închis",
+deeppink: "roz închis",
+deepskyblue: "deep sky blue",
+dimgray: "dim gray",
+dimgrey: "dim gray", // same as dimgray
+dodgerblue: "dodger blue",
+firebrick: "fire brick",
+floralwhite: "floral white",
+forestgreen: "verde pădure",
+fuchsia: "fuchsia",
+gainsboro: "gainsboro",
+ghostwhite: "ghost white",
+gold: "auriu",
+goldenrod: "goldenrod",
+gray: "cenuşiu",
+green: "verde",
+greenyellow: "verde-galben",
+grey: "gri", // same as gray
+honeydew: "honeydew",
+hotpink: "roz aprins",
+indianred: "roşu indian",
+indigo: "indigo",
+ivory: "ivoriu",
+khaki: "kaki",
+lavender: "levănţică",
+lavenderblush: "lavender blush",
+lawngreen: "lawn green",
+lemonchiffon: "lemon chiffon",
+lightblue: "albastru deschis",
+lightcoral: "coral deschis",
+lightcyan: "cyan deschis",
+lightgoldenrodyellow: "light goldenrod yellow",
+lightgray: "gri deschis",
+lightgreen: "verde deschis",
+lightgrey: "gri deschis", // same as lightgray
+lightpink: "roz deschis",
+lightsalmon: "somon deschis",
+lightseagreen: "verde marin deschis",
+lightskyblue: "albastru cer deschis",
+lightslategray: "light slate gray",
+lightslategrey: "light slate gray", // same as lightslategray
+lightsteelblue: "light steel blue",
+lightyellow: "galben deschis",
+lime: "lime",
+limegreen: "verde lime",
+linen: "linen",
+magenta: "magenta",
+maroon: "maroon",
+mediumaquamarine: "medium aquamarine",
+mediumblue: "medium blue",
+mediumorchid: "medium orchid",
+mediumpurple: "medium purple",
+mediumseagreen: "medium sea green",
+mediumslateblue: "medium slate blue",
+mediumspringgreen: "medium spring green",
+mediumturquoise: "medium turquoise",
+mediumvioletred: "medium violet-red",
+midnightblue: "midnight blue",
+mintcream: "mint cream",
+mistyrose: "trandafiriu obscur",
+moccasin: "moccasin",
+navajowhite: "navajo white",
+navy: "navy",
+oldlace: "old lace",
+olive: "oliv",
+olivedrab: "maron-gălbui oliv",
+orange: "portocaliu",
+orangered: "roşu portocaliu",
+orchid: "orhidee",
+palegoldenrod: "solidago pal",
+palegreen: "verde pal",
+paleturquoise: "turquoise pal",
+palevioletred: "roşu violet pal",
+papayawhip: "papaya whip",
+peachpuff: "puf de piersică",
+peru: "peru",
+pink: "roz",
+plum: "prună",
+powderblue: "albastru pudră",
+purple: "purpură",
+red: "roşu",
+rosybrown: "maro trandafiriu",
+royalblue: "albastru regal",
+saddlebrown: "maro de şa",
+salmon: "somon",
+sandybrown: "maro nisipiu",
+seagreen: "verde marin",
+seashell: "cochilie",
+sienna: "sienna",
+silver: "argintiu",
+skyblue: "albastru de cer",
+slateblue: "albastru ardezie",
+slategray: "gri ardezie",
+slategrey: "gri ardezie", // same as slategray
+snow: "zăpadă",
+springgreen: "verde de primăvară",
+steelblue: "albastru metalic",
+tan: "tan",
+teal: "lişiţă",
+thistle: "ciulin",
+tomato: "roşie",
+turquoise: "turquoise",
+violet: "violet",
+wheat: "grâu",
+white: "alb",
+whitesmoke: "fum alb",
+yellow: "galben",
+yellowgreen: "verde galben"
+})
+
diff --git a/dojo/nls/ru/colors.js b/dojo/nls/ru/colors.js
index 4b67053..ce0b438 100644
--- a/dojo/nls/ru/colors.js
+++ b/dojo/nls/ru/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"светлый стальной","orangered":"оранжево-красный","midnightblue":"полуночно-синий","cadetblue":"серо-синий","seashell":"морская раковина","slategrey":"грифельно-серый","coral":"коралловый","darkturquoise":"темный бирюзовый","antiquewhite":"белый антик","mediumspringgreen":"нейтральный весенне-зеленый","salmon":"лососевый","darkgrey":"темно-серый","ivory":"слоновой кости","greenyellow":"зелено-желтый","mistyrose":"блекло-розовый","lightsalmon":"светло-лососевый","silver [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "серо-голубой",
+antiquewhite: "белый антик",
+aqua: "зеленовато-голубой",
+aquamarine: "аквамарин",
+azure: "лазурный",
+beige: "бежевый",
+bisque: "бисквитный",
+black: "черный",
+blanchedalmond: "светло-миндальный",
+blue: "синий",
+blueviolet: "сине-фиолетовый",
+brown: "коричневый",
+burlywood: "светло-коричневый",
+cadetblue: "серо-синий",
+chartreuse: "желто-салатный",
+chocolate: "шоколадный",
+coral: "коралловый",
+cornflowerblue: "фиолетово-синий",
+cornsilk: "шелковый оттенок",
+crimson: "малиновый",
+cyan: "циан",
+darkblue: "темно-синий",
+darkcyan: "темный циан",
+darkgoldenrod: "темно-золотистый",
+darkgray: "темно-серый",
+darkgreen: "темно-зеленый",
+darkgrey: "темно-серый", // same as darkgray
+darkkhaki: "темный хаки",
+darkmagenta: "темно-пурпурный",
+darkolivegreen: "темно-оливковый",
+darkorange: "темно-оранжевый",
+darkorchid: "темный орсель",
+darkred: "темно-красный",
+darksalmon: "темно-лососевый",
+darkseagreen: "темный морской волны",
+darkslateblue: "темный грифельно-синий",
+darkslategray: "темный грифельно-серый",
+darkslategrey: "темный грифельно-серый", // same as darkslategray
+darkturquoise: "темный бирюзовый",
+darkviolet: "темно-фиолетовый",
+deeppink: "темно-розовый",
+deepskyblue: "темный небесно-голубой",
+dimgray: "тускло-серый",
+dimgrey: "тускло-серый", // same as dimgray
+dodgerblue: "бледно-синий",
+firebrick: "кирпичный",
+floralwhite: "цветочно-белый",
+forestgreen: "зеленый лесной",
+fuchsia: "фуксин",
+gainsboro: "бледно-серый",
+ghostwhite: "призрачно-белый",
+gold: "золотой",
+goldenrod: "золотистый",
+gray: "серый",
+green: "зеленый",
+greenyellow: "зелено-желтый",
+grey: "серый", // same as gray
+honeydew: "медовый",
+hotpink: "красно-розовый",
+indianred: "индийский красный",
+indigo: "индиго",
+ivory: "слоновой кости",
+khaki: "хаки",
+lavender: "бледно-лиловый",
+lavenderblush: "розовато-лиловый",
+lawngreen: "зеленая лужайка",
+lemonchiffon: "бледно-лимонный",
+lightblue: "светло-синий",
+lightcoral: "светло-коралловый",
+lightcyan: "светлый циан",
+lightgoldenrodyellow: "светло-золотистый",
+lightgray: "светло-серый",
+lightgreen: "светло-зеленый",
+lightgrey: "светло-серый", // same as lightgray
+lightpink: "светло-розовый",
+lightsalmon: "светло-лососевый",
+lightseagreen: "светлый морской волны",
+lightskyblue: "светлый небесно-голубой",
+lightslategray: "светлый грифельно-серый",
+lightslategrey: "светлый грифельно-серый", // same as lightslategray
+lightsteelblue: "светлый стальной",
+lightyellow: "светло-желтый",
+lime: "лайм",
+limegreen: "зеленый лайм",
+linen: "хлопковый",
+magenta: "пурпурный",
+maroon: "темно-бордовый",
+mediumaquamarine: "нейтральный аквамарин",
+mediumblue: "нейтральный синий",
+mediumorchid: "нейтральный орсель",
+mediumpurple: "нейтральный фиолетовый",
+mediumseagreen: "нейтральный морской волны",
+mediumslateblue: "нейтральный грифельно-синий",
+mediumspringgreen: "нейтральный весенне-зеленый",
+mediumturquoise: "нейтральный бирюзовый",
+mediumvioletred: "нейтральный фиолетово-красный",
+midnightblue: "полуночно-синий",
+mintcream: "мятно-кремовый",
+mistyrose: "блекло-розовый",
+moccasin: "мокасин",
+navajowhite: "белый навахо",
+navy: "темно-синий",
+oldlace: "матово-белый",
+olive: "оливковый",
+olivedrab: "желтовато-серый",
+orange: "оранжевый",
+orangered: "оранжево-красный",
+orchid: "орсель",
+palegoldenrod: "бледно-золотистый",
+palegreen: "бледно-зеленый",
+paleturquoise: "бледно-бирюзовый",
+palevioletred: "бледный фиолетово-красный",
+papayawhip: "черенок папайи",
+peachpuff: "персиковый",
+peru: "перу",
+pink: "розовый",
+plum: "сливовый",
+powderblue: "пороховой",
+purple: "фиолетовый",
+red: "красный",
+rosybrown: "розово-коричневый",
+royalblue: "королевский голубой",
+saddlebrown: "кожано-коричневый",
+salmon: "лососевый",
+sandybrown: "коричнево-песчаный",
+seagreen: "морской волны",
+seashell: "морская раковина",
+sienna: "охра",
+silver: "серебристый",
+skyblue: "небесно-голубой",
+slateblue: "грифельно-синий",
+slategray: "грифельно-серый",
+slategrey: "грифельно-серый", // same as slategray
+snow: "белоснежный",
+springgreen: "весенний зеленый",
+steelblue: "стальной",
+tan: "рыжевато-коричневый",
+teal: "чирок",
+thistle: "чертополох",
+tomato: "помидор",
+turquoise: "бирюзовый",
+violet: "фиолетовый",
+wheat: "пшеница",
+white: "белый",
+whitesmoke: "дымчато-белый",
+yellow: "желтый",
+yellowgreen: "желто-зеленый"
+})
diff --git a/dojo/nls/sk/colors.js b/dojo/nls/sk/colors.js
index 9dbd8e6..b290091 100644
--- a/dojo/nls/sk/colors.js
+++ b/dojo/nls/sk/colors.js
@@ -1 +1,155 @@
-({"lightsteelblue":"oceľovo modrá svetlá","orangered":"oranžovo červená","midnightblue":"nočná modrá","cadetblue":"sivomodrá","seashell":"lastúrová","slategrey":"bridlicová sivá","coral":"koralová","darkturquoise":"tyrkysová tmavá","antiquewhite":"antická biela","mediumspringgreen":"jarná zelená stredná","salmon":"lososovo ružová","darkgrey":"tmavosivá","ivory":"slonovinová","greenyellow":"žltozelená","mistyrose":"zahmlená ruža","lightsalmon":"lososovo ružová svetlá","silver":"strieborná [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "modrá alice",
+antiquewhite: "antická biela",
+aqua: "svetlá zelenomodrá",
+aquamarine: "akvamarínová",
+azure: "azúrová",
+beige: "béžová",
+bisque: "biskvitová",
+black: "čierna",
+blanchedalmond: "lúpané mandle",
+blue: "modrá",
+blueviolet: "modrofialová",
+brown: "hnedá",
+burlywood: "pieskovo hnedá",
+cadetblue: "sivomodrá",
+chartreuse: "kartúza",
+chocolate: "čokoládovo hnedá",
+coral: "koralová",
+cornflowerblue: "nevädzovo modrá",
+cornsilk: "hodvábna žltá",
+crimson: "karmínová",
+cyan: "zelenomodrá",
+darkblue: "tmavomodrá",
+darkcyan: "tmavozelenomodrá",
+darkgoldenrod: "zlatobyľová tmavá",
+darkgray: "tmavosivá",
+darkgreen: "tmavozelená",
+darkgrey: "tmavosivá", // same as darkgray
+darkkhaki: "žltohnedá tmavá",
+darkmagenta: "tmavopurpurová",
+darkolivegreen: "olivovozelená tmavá",
+darkorange: "tmavooranžová",
+darkorchid: "orchideovo ružová tmavá",
+darkred: "tmavočervená",
+darksalmon: "lososovo ružová tmavá",
+darkseagreen: "morská zelená tmavá",
+darkslateblue: "bridlicová modrá tmavá",
+darkslategray: "bridlicová sivá tmavá",
+darkslategrey: "bridlicová sivá tmavá", // same as darkslategray
+darkturquoise: "tyrkysová tmavá",
+darkviolet: "tmavofialová",
+deeppink: "hlboká ružová",
+deepskyblue: "hlboká blankytná modrá",
+dimgray: "sivá matná",
+dimgrey: "sivá matná", // same as dimgray
+dodgerblue: "modrá dodger",
+firebrick: "pálená tehla",
+floralwhite: "kvetinová biela",
+forestgreen: "lesná zelená",
+fuchsia: "purpurová",
+gainsboro: "sivomodrá svetlá",
+ghostwhite: "biely tieň",
+gold: "zlatá",
+goldenrod: "zlatobyľ",
+gray: "sivá",
+green: "zelená",
+greenyellow: "žltozelená",
+grey: "sivá", // same as gray
+honeydew: "ambrózia",
+hotpink: "teplá ružová",
+indianred: "indická červená",
+indigo: "fialovo modrá",
+ivory: "slonovinová",
+khaki: "khaki",
+lavender: "levanduľová",
+lavenderblush: "levanduľový rumenec",
+lawngreen: "zelená tráva",
+lemonchiffon: "citrónový šifón",
+lightblue: "svetlomodrá",
+lightcoral: "koralová svetlá",
+lightcyan: "zelenomodrá svetlá",
+lightgoldenrodyellow: "zlatobyľová svetlá",
+lightgray: "svetlosivá",
+lightgreen: "svetlozelená",
+lightgrey: "svetlosivá", // same as lightgray
+lightpink: "svetloružová",
+lightsalmon: "lososovo ružová svetlá",
+lightseagreen: "morská zelená svetlá",
+lightskyblue: "blankytná modrá svetlá",
+lightslategray: "bridlicová sivá svetlá",
+lightslategrey: "bridlicová sivá svetlá", // same as lightslategray
+lightsteelblue: "oceľovo modrá svetlá",
+lightyellow: "svetložltá",
+lime: "lipová",
+limegreen: "lipová zelená",
+linen: "ľan",
+magenta: "purpurová",
+maroon: "gaštanovo hnedá",
+mediumaquamarine: "akvamarínová stredná",
+mediumblue: "stredne modrá",
+mediumorchid: "orchideovo ružová stredná",
+mediumpurple: "purpurová stredná",
+mediumseagreen: "morská zelená stredná",
+mediumslateblue: "bridlicová modrá stredná",
+mediumspringgreen: "jarná zelená stredná",
+mediumturquoise: "tyrkysová stredná",
+mediumvioletred: "fialovočervená stredná",
+midnightblue: "nočná modrá",
+mintcream: "mätová krémová",
+mistyrose: "zahmlená ruža",
+moccasin: "črievičníková",
+navajowhite: "navajská biela",
+navy: "vojenská zelená",
+oldlace: "stará čipka",
+olive: "olivovo zelená",
+olivedrab: "olivovo zelená fádna",
+orange: "oranžová",
+orangered: "oranžovo červená",
+orchid: "orchideovo ružová",
+palegoldenrod: "bledá zlatobyľová",
+palegreen: "bledozelená",
+paleturquoise: "bledo tyrkysová",
+palevioletred: "bledá fialovo červená",
+papayawhip: "papájový krém",
+peachpuff: "broskyňová pena",
+peru: "peru",
+pink: "ružová",
+plum: "slivková",
+powderblue: "prášková modrá",
+purple: "purpurová",
+red: "červená",
+rosybrown: "ružovo hnedá",
+royalblue: "kráľovská modrá",
+saddlebrown: "sedlová hnedá",
+salmon: "lososovo ružová",
+sandybrown: "pieskovo hnedá",
+seagreen: "morská zelená",
+seashell: "lastúrová",
+sienna: "sienská",
+silver: "strieborná",
+skyblue: "blankytná modrá",
+slateblue: "bridlicová modrá",
+slategray: "bridlicová sivá",
+slategrey: "bridlicová sivá", // same as slategray
+snow: "snehobiela",
+springgreen: "jarná zelená",
+steelblue: "oceľovo modrá",
+tan: "žltohnedá",
+teal: "tyrkysová",
+thistle: "bodliaková fialová",
+tomato: "paradajková červená",
+turquoise: "tyrkysová",
+violet: "fialová",
+wheat: "pšeničná",
+white: "biela",
+whitesmoke: "biely dym",
+yellow: "žltá",
+yellowgreen: "žltozelená"
+})
+
diff --git a/dojo/nls/sl/colors.js b/dojo/nls/sl/colors.js
index e009ce9..c0ecbf3 100644
--- a/dojo/nls/sl/colors.js
+++ b/dojo/nls/sl/colors.js
@@ -1 +1,155 @@
-({"lightsteelblue":"svetlo jeklena modra","orangered":"oranžno-rdeča","midnightblue":"polnočno modra","cadetblue":"zelenkasto modra","seashell":"morska školjka","slategrey":"skrilasto siva","coral":"koralna","darkturquoise":"temno turkizna","antiquewhite":"antično bela","mediumspringgreen":"srednje pomladno zelena","salmon":"lososova","darkgrey":"temno siva","ivory":"slonokoščena","greenyellow":"zeleno-rumena","mistyrose":"megleno rožnata","lightsalmon":"svetlo lososova","silver":"srebrn [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "alice modra",
+antiquewhite: "antično bela",
+aqua: "akva",
+aquamarine: "akvamarin",
+azure: "azurna",
+beige: "bež",
+bisque: "porcelanasta",
+black: "črna",
+blanchedalmond: "mandljeva",
+blue: "modra",
+blueviolet: "modro vijolična",
+brown: "rjava",
+burlywood: "grčav les",
+cadetblue: "zelenkasto modra",
+chartreuse: "svetlo rumena zelena",
+chocolate: "čokoladna",
+coral: "koralna",
+cornflowerblue: "plavično modra",
+cornsilk: "koruzni laski",
+crimson: "karminasta",
+cyan: "cijan",
+darkblue: "temno modra",
+darkcyan: "temno cijan",
+darkgoldenrod: "temno zlata rozga",
+darkgray: "temno siva",
+darkgreen: "temno zelena",
+darkgrey: "temno siva", // same as darkgray
+darkkhaki: "temno rumenkasto rjava",
+darkmagenta: "temno magenta",
+darkolivegreen: "temno olivno zelena",
+darkorange: "temno oranžna",
+darkorchid: "temno orhidejna",
+darkred: "temno rdeča",
+darksalmon: "temno lososova",
+darkseagreen: "temno morsko zelena",
+darkslateblue: "temno skrilasto modra",
+darkslategray: "temno skrilasto siva",
+darkslategrey: "temno skrilasto siva", // same as darkslategray
+darkturquoise: "temno turkizna",
+darkviolet: "temno vijolična",
+deeppink: "temno roza",
+deepskyblue: "temno nebesno modra",
+dimgray: "umazano siva",
+dimgrey: "umazano siva", // same as dimgray
+dodgerblue: "koruzno modra",
+firebrick: "opečnata",
+floralwhite: "cvetno bela",
+forestgreen: "gozdno zelena",
+fuchsia: "fuksija",
+gainsboro: "pepelnato siva",
+ghostwhite: "prosojno bela",
+gold: "zlata",
+goldenrod: "zlata rozga",
+gray: "siva",
+green: "zelena",
+greenyellow: "zeleno-rumena",
+grey: "siva", // same as gray
+honeydew: "medena rosa",
+hotpink: "živo roza",
+indianred: "indijansko rdeča",
+indigo: "indigo",
+ivory: "slonokoščena",
+khaki: "rumenkasto rjava",
+lavender: "sivka",
+lavenderblush: "bleščeča sivka",
+lawngreen: "travnato zelena",
+lemonchiffon: "limonina",
+lightblue: "svetlo modra",
+lightcoral: "svetlo koralna",
+lightcyan: "svetlo cijan",
+lightgoldenrodyellow: "svetlo rumena zlata rozga",
+lightgray: "svetlo siva",
+lightgreen: "svetlo zelena",
+lightgrey: "svetlo siva", // same as lightgray
+lightpink: "svetlo roza",
+lightsalmon: "svetlo lososova",
+lightseagreen: "svetlo morsko zelena",
+lightskyblue: "svetlo nebesno modra",
+lightslategray: "svetlo skrilasto siva",
+lightslategrey: "svetlo skrilasto siva", // same as lightslategray
+lightsteelblue: "svetlo jeklena modra",
+lightyellow: "svetlo rumena",
+lime: "rumeno zelena",
+limegreen: "citronsko zelena",
+linen: "lanena",
+magenta: "magenta",
+maroon: "kostanjeva",
+mediumaquamarine: "srednje akvamarin",
+mediumblue: "srednje modra",
+mediumorchid: "srednje orhidejna",
+mediumpurple: "srednje škrlatna",
+mediumseagreen: "srednje morsko zelena",
+mediumslateblue: "srednje skrilasto modra",
+mediumspringgreen: "srednje pomladno zelena",
+mediumturquoise: "srednje turkizna",
+mediumvioletred: "srednje vijolično-rdeča",
+midnightblue: "polnočno modra",
+mintcream: "mentolno smetanasta",
+mistyrose: "megleno rožnata",
+moccasin: "mokasinasta",
+navajowhite: "navajsko bela",
+navy: "mornarsko modra",
+oldlace: "stara čipka",
+olive: "olivna",
+olivedrab: "olivno sivo rjava",
+orange: "oranžna",
+orangered: "oranžno-rdeča",
+orchid: "orhidejna",
+palegoldenrod: "bleda zlata rozga",
+palegreen: "bledo zelena",
+paleturquoise: "bledo turkizna",
+palevioletred: "bledo vijolično-rdeča",
+papayawhip: "papaja",
+peachpuff: "breskova",
+peru: "perujska",
+pink: "roza",
+plum: "slivova",
+powderblue: "smodniško modra",
+purple: "škrlatna",
+red: "rdeča",
+rosybrown: "rožnato rjava",
+royalblue: "kraljevsko modra",
+saddlebrown: "sedlasto rjava",
+salmon: "lososova",
+sandybrown: "peščeno rjava",
+seagreen: "morsko zelena",
+seashell: "morska školjka",
+sienna: "siena",
+silver: "srebrna",
+skyblue: "nebesno modra",
+slateblue: "skrilasto modra",
+slategray: "skrilasto siva",
+slategrey: "skrilasto siva", // same as slategray
+snow: "snežena",
+springgreen: "pomladno zelena",
+steelblue: "jekleno modra",
+tan: "kožno rjava",
+teal: "zeleno modra",
+thistle: "osatna",
+tomato: "paradižnikova",
+turquoise: "turkizna",
+violet: "vijolična",
+wheat: "žitna",
+white: "bela",
+whitesmoke: "umazano bela",
+yellow: "rumena",
+yellowgreen: "rumeno zelena"
+})
+
diff --git a/dojo/nls/sv/colors.js b/dojo/nls/sv/colors.js
index 269e85c..5121db0 100644
--- a/dojo/nls/sv/colors.js
+++ b/dojo/nls/sv/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"ljust stålblått","orangered":"orangerött","midnightblue":"midnattsblått","cadetblue":"kadettblått","seashell":"snäckskal","slategrey":"skiffergrått","coral":"korall","darkturquoise":"mörkturkost","antiquewhite":"antikvitt","mediumspringgreen":"mellanvårgrönt","salmon":"laxfärgat","darkgrey":"mörkgrått","ivory":"elfenbensvitt","greenyellow":"gröngult","mistyrose":"dunkelrosa","lightsalmon":"ljust laxfärgat","silver":"silver","dimgrey":"smutsgrått","orange":"orange","wh [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "aliceblå",
+antiquewhite: "antikvitt",
+aqua: "akvamarin",
+aquamarine: "akvamarin",
+azure: "azurblått",
+beige: "beige",
+bisque: "biskvi",
+black: "svart",
+blanchedalmond: "skållad mandel",
+blue: "blått",
+blueviolet: "blåviolett",
+brown: "brunt",
+burlywood: "träfärgat",
+cadetblue: "kadettblått",
+chartreuse: "chartreuse",
+chocolate: "choklad",
+coral: "korall",
+cornflowerblue: "kornblått",
+cornsilk: "gulvitt",
+crimson: "karmosinrött",
+cyan: "cyan",
+darkblue: "mörkblått",
+darkcyan: "mörkt cyan",
+darkgoldenrod: "mörkt gullris",
+darkgray: "mörkgrått",
+darkgreen: "mörkgrönt",
+darkgrey: "mörkgrått", // same as darkgray
+darkkhaki: "mörkt kaki",
+darkmagenta: "mörk magenta",
+darkolivegreen: "mörkt olivgrönt",
+darkorange: "mörkorange",
+darkorchid: "mörkt orkidé",
+darkred: "mörkrött",
+darksalmon: "mörkt laxfärgat",
+darkseagreen: "mörkt havsgrönt",
+darkslateblue: "mörkt skifferblått",
+darkslategray: "mörkt skiffergrått",
+darkslategrey: "mörkt skiffergrått", // same as darkslategray
+darkturquoise: "mörkturkost",
+darkviolet: "mörkviolett",
+deeppink: "djuprosa",
+deepskyblue: "mörkt himmelsblått",
+dimgray: "smutsgrått",
+dimgrey: "smutsgrått", // same as dimgray
+dodgerblue: "dodgerblått",
+firebrick: "tegelstensrött",
+floralwhite: "blomvitt",
+forestgreen: "skogsgrönt",
+fuchsia: "fuchsia",
+gainsboro: "gainsboro",
+ghostwhite: "spökvitt",
+gold: "guld",
+goldenrod: "gullris",
+gray: "grått",
+green: "grönt",
+greenyellow: "gröngult",
+grey: "grått", // same as gray
+honeydew: "honungsdagg",
+hotpink: "varmrosa",
+indianred: "indianrött",
+indigo: "indigo",
+ivory: "elfenbensvitt",
+khaki: "kaki",
+lavender: "lavendel",
+lavenderblush: "lavendelskimrande",
+lawngreen: "gräsmattegrönt",
+lemonchiffon: "citronchiffong",
+lightblue: "ljusblått",
+lightcoral: "ljuskorall",
+lightcyan: "ljust cyan",
+lightgoldenrodyellow: "ljust gullrisgult",
+lightgray: "ljusgrått",
+lightgreen: "ljusgrönt",
+lightgrey: "ljusgrått", // same as lightgray
+lightpink: "ljusrosa",
+lightsalmon: "ljust laxfärgat",
+lightseagreen: "ljust havsgrönt",
+lightskyblue: "ljust himmelsblått",
+lightslategray: "ljust skiffergrått",
+lightslategrey: "ljust skiffergrått", // same as lightslategray
+lightsteelblue: "ljust stålblått",
+lightyellow: "ljusgult",
+lime: "lime",
+limegreen: "limegrönt",
+linen: "linne",
+magenta: "magenta",
+maroon: "rödbrunt",
+mediumaquamarine: "mellanakvamarin",
+mediumblue: "mellanblått",
+mediumorchid: "mellanorkidé",
+mediumpurple: "mellanlila",
+mediumseagreen: "mellanhavsgrönt",
+mediumslateblue: "mellanskifferblått",
+mediumspringgreen: "mellanvårgrönt",
+mediumturquoise: "mellanturkost",
+mediumvioletred: "mellanviolettrött",
+midnightblue: "midnattsblått",
+mintcream: "mintgrädde",
+mistyrose: "dunkelrosa",
+moccasin: "mockasin",
+navajowhite: "navajovitt",
+navy: "marinblått",
+oldlace: "spetsvitt",
+olive: "olivfärgat",
+olivedrab: "olivsmutsgult",
+orange: "orange",
+orangered: "orangerött",
+orchid: "orkidé",
+palegoldenrod: "blekt gullris",
+palegreen: "blekgrönt",
+paleturquoise: "blekturkost",
+palevioletred: "blekviolettrött",
+papayawhip: "papayaröra",
+peachpuff: "persika",
+peru: "peru",
+pink: "rosa",
+plum: "plommon",
+powderblue: "pulverblått",
+purple: "lila",
+red: "rött",
+rosybrown: "rosenbrunt",
+royalblue: "kungligt blått",
+saddlebrown: "sadelbrunt",
+salmon: "laxfärgat",
+sandybrown: "sandbrunt",
+seagreen: "havsgrönt",
+seashell: "snäckskal",
+sienna: "sienna",
+silver: "silver",
+skyblue: "himmelsblått",
+slateblue: "skifferblått",
+slategray: "skiffergrått",
+slategrey: "skiffergrått", // same as slategray
+snow: "snö",
+springgreen: "vårgrönt",
+steelblue: "stålblått",
+tan: "mellanbrunt",
+teal: "blågrönt",
+thistle: "tistel",
+tomato: "tomatrött",
+turquoise: "turkost",
+violet: "violett",
+wheat: "vete",
+white: "vitt",
+whitesmoke: "vit rök",
+yellow: "gult",
+yellowgreen: "gulgrönt"
+})
diff --git a/dojo/nls/th/colors.js b/dojo/nls/th/colors.js
index 706ed8a..e06c805 100644
--- a/dojo/nls/th/colors.js
+++ b/dojo/nls/th/colors.js
@@ -1 +1,155 @@
-({"lightsteelblue":"light steel blue","orangered":"ส้มแกมแดง","midnightblue":"midnight blue","cadetblue":"cadet blue","seashell":"seashell","slategrey":"slate gray","coral":"coral","darkturquoise":"dark turquoise","antiquewhite":"antique white","mediumspringgreen":"medium spring green","salmon":"salmon","darkgrey":"เทาเข้ม","ivory":"งาช้าง","greenyellow":"เขียวแกมเหลือง","mistyrose":"misty rose","lightsalmon":"light salmon","silver":"เงิน","dimgrey":"dim gray","orange":"ส้ม","white":"ขาว [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "alice blue",
+antiquewhite: "antique white",
+aqua: "ฟ้าน้ำทะเล",
+aquamarine: "aquamarine",
+azure: "น้ำเงินฟ้า",
+beige: "น้ำตาลเบจ",
+bisque: "bisque",
+black: "ดำ",
+blanchedalmond: "blanched almond",
+blue: "น้ำเงิน",
+blueviolet: "น้ำเงินม่วง",
+brown: "น้ำตาล",
+burlywood: "burlywood",
+cadetblue: "cadet blue",
+chartreuse: "chartreuse",
+chocolate: "ช็อกโกแลต",
+coral: "coral",
+cornflowerblue: "cornflower blue",
+cornsilk: "cornsilk",
+crimson: "แดงเลือดหมู",
+cyan: "เขียวแกมน้ำเงิน",
+darkblue: "น้ำเงินเข้ม",
+darkcyan: "เขียวแกมน้ำเงินเข้ม",
+darkgoldenrod: "dark goldenrod",
+darkgray: "เทาเข้ม",
+darkgreen: "เขียวเข้ม",
+darkgrey: "เทาเข้ม", // same as darkgray
+darkkhaki: "dark khaki",
+darkmagenta: "แดงแกมม่วงเข้ม",
+darkolivegreen: "เขียวโอลีฟเข้ม",
+darkorange: "ส้มเข้ม",
+darkorchid: "dark orchid",
+darkred: "แดงเข้ม",
+darksalmon: "dark salmon",
+darkseagreen: "dark sea green",
+darkslateblue: "dark slate blue",
+darkslategray: "dark slate gray",
+darkslategrey: "dark slate gray", // same as darkslategray
+darkturquoise: "dark turquoise",
+darkviolet: "ม่วงเข้ม",
+deeppink: "ชมพูเข้ม",
+deepskyblue: "deep sky blue",
+dimgray: "dim gray",
+dimgrey: "dim gray", // same as dimgray
+dodgerblue: "dodger blue",
+firebrick: "สีอิฐ",
+floralwhite: "floral white",
+forestgreen: "forest green",
+fuchsia: "fuchsia",
+gainsboro: "gainsboro",
+ghostwhite: "ghost white",
+gold: "ทอง",
+goldenrod: "goldenrod",
+gray: "เทา",
+green: "เขียว",
+greenyellow: "เขียวแกมเหลือง",
+grey: "เทา", // same as gray
+honeydew: "honeydew",
+hotpink: "hot pink",
+indianred: "indian red",
+indigo: "indigo",
+ivory: "งาช้าง",
+khaki: "khaki",
+lavender: "ม่วงลาเวนเดอร์",
+lavenderblush: "lavender blush",
+lawngreen: "lawn green",
+lemonchiffon: "lemon chiffon",
+lightblue: "น้ำเงินอ่อน",
+lightcoral: "light coral",
+lightcyan: "เขียวแกมน้ำเงินอ่อน",
+lightgoldenrodyellow: "light goldenrod yellow",
+lightgray: "เทาอ่อน",
+lightgreen: "เขียวอ่อน",
+lightgrey: "เทาอ่อน", // same as lightgray
+lightpink: "ชมพูอ่อน",
+lightsalmon: "light salmon",
+lightseagreen: "light sea green",
+lightskyblue: "ฟ้าอ่อน",
+lightslategray: "light slate gray",
+lightslategrey: "light slate gray", // same as lightslategray
+lightsteelblue: "light steel blue",
+lightyellow: "เหลืองอ่อน",
+lime: "เหลืองมะนาว",
+limegreen: "เขียวมะนาว",
+linen: "linen",
+magenta: "แดงแกมม่วง",
+maroon: "น้ำตาลแดง",
+mediumaquamarine: "medium aquamarine",
+mediumblue: "medium blue",
+mediumorchid: "medium orchid",
+mediumpurple: "medium purple",
+mediumseagreen: "medium sea green",
+mediumslateblue: "medium slate blue",
+mediumspringgreen: "medium spring green",
+mediumturquoise: "medium turquoise",
+mediumvioletred: "medium violet-red",
+midnightblue: "midnight blue",
+mintcream: "mint cream",
+mistyrose: "misty rose",
+moccasin: "ม็อคค่า",
+navajowhite: "navajo white",
+navy: "น้ำเงินเข้ม",
+oldlace: "old lace",
+olive: "โอลีฟ",
+olivedrab: "olive drab",
+orange: "ส้ม",
+orangered: "ส้มแกมแดง",
+orchid: "orchid",
+palegoldenrod: "pale goldenrod",
+palegreen: "pale green",
+paleturquoise: "pale turquoise",
+palevioletred: "pale violet-red",
+papayawhip: "papaya whip",
+peachpuff: "peach puff",
+peru: "peru",
+pink: "ชมพู",
+plum: "plum",
+powderblue: "powder blue",
+purple: "ม่วง",
+red: "แดง",
+rosybrown: "rosy brown",
+royalblue: "royal blue",
+saddlebrown: "saddle brown",
+salmon: "salmon",
+sandybrown: "sandy brown",
+seagreen: "sea green",
+seashell: "seashell",
+sienna: "sienna",
+silver: "เงิน",
+skyblue: "sky blue",
+slateblue: "slate blue",
+slategray: "slate gray",
+slategrey: "slate gray", // same as slategray
+snow: "snow",
+springgreen: "spring green",
+steelblue: "steel blue",
+tan: "tan",
+teal: "teal",
+thistle: "thistle",
+tomato: "tomato",
+turquoise: "turquoise",
+violet: "ม่วง",
+wheat: "wheat",
+white: "ขาว",
+whitesmoke: "ขาวควัน",
+yellow: "เหลือง",
+yellowgreen: "เหลืองแกมเขียว"
+})
+
diff --git a/dojo/nls/tr/colors.js b/dojo/nls/tr/colors.js
index a75f12f..027b679 100644
--- a/dojo/nls/tr/colors.js
+++ b/dojo/nls/tr/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"açık metalik mavi","orangered":"turuncu kırmızı","midnightblue":"gece mavisi","cadetblue":"denizci mavisi","seashell":"deniz kabuğu","slategrey":"arduvaz grisi","coral":"mercan","darkturquoise":"koyu turkuaz","antiquewhite":"antik beyaz","mediumspringgreen":"orta bahar yeşili","salmon":"somon","darkgrey":"koyu gri","ivory":"fildişi","greenyellow":"yeşil-sarı","mistyrose":"gülkurusu","lightsalmon":"açık somon","silver":"gümüş","dimgrey":"soluk gri","orange":"turuncu"," [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "alice mavisi",
+antiquewhite: "antik beyaz",
+aqua: "deniz mavisi",
+aquamarine: "akuamarin",
+azure: "azur mavisi",
+beige: "bej",
+bisque: "bisküvi",
+black: "siyah",
+blanchedalmond: "soluk badem",
+blue: "mavi",
+blueviolet: "mavi-mor",
+brown: "kahverengi",
+burlywood: "sarımsı kahverengi",
+cadetblue: "denizci mavisi",
+chartreuse: "chartreuse",
+chocolate: "çikolata",
+coral: "mercan",
+cornflowerblue: "peygamber çiçeği mavisi",
+cornsilk: "mısır rengi",
+crimson: "crimson",
+cyan: "camgöbeği",
+darkblue: "koyu mavi",
+darkcyan: "koyu camgöbeği",
+darkgoldenrod: "koyu sarı",
+darkgray: "koyu gri",
+darkgreen: "koyu yeşil",
+darkgrey: "koyu gri", // same as darkgray
+darkkhaki: "koyu haki",
+darkmagenta: "koyu mor",
+darkolivegreen: "koyu zeytin yeşili",
+darkorange: "koyu turuncu",
+darkorchid: "koyu orkide",
+darkred: "koyu kırmızı",
+darksalmon: "koyu somon",
+darkseagreen: "koyu deniz yeşili",
+darkslateblue: "koyu arduvaz mavisi",
+darkslategray: "koyu arduvaz grisi",
+darkslategrey: "koyu arduvaz grisi", // same as darkslategray
+darkturquoise: "koyu turkuaz",
+darkviolet: "koyu eflatun",
+deeppink: "koyu pembe",
+deepskyblue: "koyu gök mavisi",
+dimgray: "soluk gri",
+dimgrey: "soluk gri", // same as dimgray
+dodgerblue: "toz mavisi",
+firebrick: "canlı kiremit",
+floralwhite: "çiçek beyazı",
+forestgreen: "koyu deniz yeşili",
+fuchsia: "fuşya",
+gainsboro: "gainsboro",
+ghostwhite: "silik beyaz",
+gold: "altın",
+goldenrod: "sarısabır",
+gray: "gri",
+green: "yeşil",
+greenyellow: "yeşil-sarı",
+grey: "gri", // same as gray
+honeydew: "çam sakızı",
+hotpink: "sıcak pembe",
+indianred: "kızılderili kırmızısı",
+indigo: "çivit mavisi",
+ivory: "fildişi",
+khaki: "haki",
+lavender: "lavanta",
+lavenderblush: "lavanta pembesi",
+lawngreen: "çimen yeşili",
+lemonchiffon: "limoni",
+lightblue: "açık mavi",
+lightcoral: "açık mercan",
+lightcyan: "açık camgöbeği",
+lightgoldenrodyellow: "açık sarısabır",
+lightgray: "açık gri",
+lightgreen: "açık yeşil",
+lightgrey: "açık gri", // same as lightgray
+lightpink: "açık pembe",
+lightsalmon: "açık somon",
+lightseagreen: "açık deniz yeşili",
+lightskyblue: "açık gök mavisi",
+lightslategray: "açık arduvaz grisi",
+lightslategrey: "açık arduvaz grisi", // same as lightslategray
+lightsteelblue: "açık metalik mavi",
+lightyellow: "açık sarı",
+lime: "limon yeşili",
+limegreen: "küf yeşili",
+linen: "keten",
+magenta: "macenta",
+maroon: "kestane",
+mediumaquamarine: "orta akuamarin",
+mediumblue: "orta mavi",
+mediumorchid: "orta orkide",
+mediumpurple: "orta mor",
+mediumseagreen: "orta deniz yeşili",
+mediumslateblue: "orta arduvaz mavisi",
+mediumspringgreen: "orta bahar yeşili",
+mediumturquoise: "orta turkuaz",
+mediumvioletred: "orta menekşe kırmızısı",
+midnightblue: "gece mavisi",
+mintcream: "naneli krem",
+mistyrose: "gülkurusu",
+moccasin: "mokosen",
+navajowhite: "navajo beyazı",
+navy: "lacivert",
+oldlace: "eski dantel",
+olive: "zeytin",
+olivedrab: "asker yeşili",
+orange: "turuncu",
+orangered: "turuncu kırmızı",
+orchid: "orkide",
+palegoldenrod: "soluk sarısabır",
+palegreen: "soluk yeşil",
+paleturquoise: "soluk turkuaz",
+palevioletred: "soluk menekşe kırmızısı",
+papayawhip: "papaya sapı",
+peachpuff: "açık şeftali",
+peru: "peru",
+pink: "pembe",
+plum: "erik",
+powderblue: "pudra mavisi",
+purple: "mor",
+red: "kırmızı",
+rosybrown: "pembemsi kahverengi",
+royalblue: "parlak koyu mavi",
+saddlebrown: "açık kahve",
+salmon: "somon",
+sandybrown: "kum rengi",
+seagreen: "deniz yeşili",
+seashell: "deniz kabuğu",
+sienna: "koyu kahve",
+silver: "gümüş",
+skyblue: "gök mavisi",
+slateblue: "arduvaz mavisi",
+slategray: "arduvaz grisi",
+slategrey: "arduvaz grisi", // same as slategray
+snow: "kar",
+springgreen: "bahar yeşili",
+steelblue: "metalik mavi",
+tan: "güneş yanığı",
+teal: "Teal mavi",
+thistle: "devedikeni",
+tomato: "domates",
+turquoise: "turkuaz",
+violet: "eflatun",
+wheat: "buğday",
+white: "beyaz",
+whitesmoke: "beyaz duman",
+yellow: "sarı",
+yellowgreen: "sarı yeşil"
+})
diff --git a/dojo/nls/zh-tw/colors.js b/dojo/nls/zh-tw/colors.js
index 6ee6c5e..336e713 100644
--- a/dojo/nls/zh-tw/colors.js
+++ b/dojo/nls/zh-tw/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"淡鐵藍色","orangered":"橙紅色","midnightblue":"午夜藍","cadetblue":"軍服藍","seashell":"海貝色","slategrey":"岩灰色","coral":"珊瑚紅","darkturquoise":"暗松石綠","antiquewhite":"米白色","mediumspringgreen":"中春綠色","salmon":"鮭紅色","darkgrey":"暗灰色","ivory":"象牙色","greenyellow":"綠黃色","mistyrose":"霧玫瑰色","lightsalmon":"淡鮭紅","silver":"銀色","dimgrey":"昏灰色","orange":"橙色","white":"白色","navajowhite":"印地安黃色","royalblue":"品藍色","deeppink":"深粉紅色","lime":"檸檬色","oldlace":"舊蕾絲色","chartreuse":"淡黃綠色","darkcyan":"暗青色","y [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "愛麗絲藍",
+antiquewhite: "米白色",
+aqua: "水色",
+aquamarine: "碧綠色",
+azure: "天藍色",
+beige: "灰棕色",
+bisque: "橘黃色",
+black: "黑色",
+blanchedalmond: "杏仁白",
+blue: "藍色",
+blueviolet: "藍紫色",
+brown: "褐色",
+burlywood: "實木色",
+cadetblue: "軍服藍",
+chartreuse: "淡黃綠色",
+chocolate: "巧克力色",
+coral: "珊瑚紅",
+cornflowerblue: "矢車菊藍",
+cornsilk: "玉米黃",
+crimson: "暗深紅色",
+cyan: "青色",
+darkblue: "暗藍色",
+darkcyan: "暗青色",
+darkgoldenrod: "暗金菊色",
+darkgray: "暗灰色",
+darkgreen: "暗綠色",
+darkgrey: "暗灰色", // same as darkgray
+darkkhaki: "暗卡其色",
+darkmagenta: "暗紫紅色",
+darkolivegreen: "暗橄欖綠",
+darkorange: "暗橙色",
+darkorchid: "暗蘭花色",
+darkred: "暗紅色",
+darksalmon: "暗鮭紅",
+darkseagreen: "暗海綠色",
+darkslateblue: "暗岩藍色",
+darkslategray: "暗岩灰色",
+darkslategrey: "暗岩灰色", // same as darkslategray
+darkturquoise: "暗松石綠",
+darkviolet: "暗紫羅蘭色",
+deeppink: "深粉紅色",
+deepskyblue: "深天藍色",
+dimgray: "昏灰色",
+dimgrey: "昏灰色", // same as dimgray
+dodgerblue: "道奇藍",
+firebrick: "紅磚色",
+floralwhite: "花卉白",
+forestgreen: "森綠色",
+fuchsia: "海棠紅",
+gainsboro: "石板灰",
+ghostwhite: "幽靈色",
+gold: "金色",
+goldenrod: "金菊色",
+gray: "灰色",
+green: "綠色",
+greenyellow: "綠黃色",
+grey: "灰色", // same as gray
+honeydew: "密瓜色",
+hotpink: "暖粉紅色",
+indianred: "印度紅",
+indigo: "靛藍色",
+ivory: "象牙色",
+khaki: "卡其色",
+lavender: "薰衣草紫",
+lavenderblush: "薰衣草紫紅",
+lawngreen: "草綠色",
+lemonchiffon: "奶油黃",
+lightblue: "淡藍色",
+lightcoral: "淡珊瑚紅",
+lightcyan: "淡青色",
+lightgoldenrodyellow: "淡金菊黃",
+lightgray: "淡灰色",
+lightgreen: "淡綠色",
+lightgrey: "淡灰色", // same as lightgray
+lightpink: "淡粉紅色",
+lightsalmon: "淡鮭紅",
+lightseagreen: "淡海綠色",
+lightskyblue: "淡天藍色",
+lightslategray: "淡岩灰色",
+lightslategrey: "淡岩灰色", // same as lightslategray
+lightsteelblue: "淡鐵藍色",
+lightyellow: "淡黃色",
+lime: "檸檬色",
+limegreen: "檸檬綠",
+linen: "亞麻色",
+magenta: "紫紅色",
+maroon: "栗色",
+mediumaquamarine: "中碧綠色",
+mediumblue: "中藍色",
+mediumorchid: "中蘭紫色",
+mediumpurple: "中紫色",
+mediumseagreen: "中海綠色",
+mediumslateblue: "中岩藍色",
+mediumspringgreen: "中春綠色",
+mediumturquoise: "中松石綠",
+mediumvioletred: "中紫羅蘭紅",
+midnightblue: "午夜藍",
+mintcream: "薄荷乳白色",
+mistyrose: "霧玫瑰色",
+moccasin: "鹿皮黃色",
+navajowhite: "印地安黃色",
+navy: "海軍藍",
+oldlace: "舊蕾絲色",
+olive: "橄欖色",
+olivedrab: "橄欖綠",
+orange: "橙色",
+orangered: "橙紅色",
+orchid: "蘭花色",
+palegoldenrod: "灰金菊色",
+palegreen: "灰綠色",
+paleturquoise: "灰松石綠",
+palevioletred: "灰紫羅蘭紅",
+papayawhip: "番木瓜色",
+peachpuff: "粉撲桃色",
+peru: "祕魯色",
+pink: "粉紅色",
+plum: "李紫色",
+powderblue: "粉藍色",
+purple: "紫色",
+red: "紅色",
+rosybrown: "玫瑰褐",
+royalblue: "品藍色",
+saddlebrown: "鞍褐色",
+salmon: "鮭紅色",
+sandybrown: "沙褐色",
+seagreen: "海綠色",
+seashell: "海貝色",
+sienna: "黃土赭色",
+silver: "銀色",
+skyblue: "天藍色",
+slateblue: "岩藍色",
+slategray: "岩灰色",
+slategrey: "岩灰色", // same as slategray
+snow: "雪白色",
+springgreen: "春綠色",
+steelblue: "鐵藍色",
+tan: "皮革色",
+teal: "深藍綠色",
+thistle: "薊色",
+tomato: "蕃茄紅",
+turquoise: "松石綠",
+violet: "紫羅蘭色",
+wheat: "小麥色",
+white: "白色",
+whitesmoke: "白煙色",
+yellow: "黃色",
+yellowgreen: "黃綠色"
+})
diff --git a/dojo/nls/zh/colors.js b/dojo/nls/zh/colors.js
index 35368f3..c14cfb6 100644
--- a/dojo/nls/zh/colors.js
+++ b/dojo/nls/zh/colors.js
@@ -1 +1,154 @@
-({"lightsteelblue":"浅钢蓝色","orangered":"橙红色","midnightblue":"深蓝色","cadetblue":"灰蓝色","seashell":"海贝色","slategrey":"灰石色","coral":"珊瑚色","darkturquoise":"深粉蓝","antiquewhite":"古董白","mediumspringgreen":"间春绿色","salmon":"橙红","darkgrey":"深灰色","ivory":"象牙色","greenyellow":"绿黄色","mistyrose":"浅玫瑰色","lightsalmon":"淡橙色","silver":"银白色","dimgrey":"暗灰色","orange":"橙色","white":"白色","navajowhite":"纳瓦白","royalblue":"品蓝","deeppink":"深粉红色","lime":"淡黄绿色","oldlace":"老白色","chartreuse":"黄绿色","darkcyan":"深青绿","yellow [...]
\ No newline at end of file
+({
+// local representation of all CSS3 named colors, companion to dojo.colors.  To be used where descriptive information
+// is required for each color, such as a palette widget, and not for specifying color programatically.
+
+//Note: due to the SVG 1.0 spec additions, some of these are alternate spellings for the same color e.g. gray vs. gray. 
+//TODO: should we be using unique rgb values as keys instead and avoid these duplicates, or rely on the caller to do the reverse mapping?
+aliceblue: "爱丽丝蓝",
+antiquewhite: "古董白",
+aqua: "浅绿色",
+aquamarine: "碧绿色",
+azure: "天蓝色",
+beige: "米色",
+bisque: "桔黄色",
+black: "黑色",
+blanchedalmond: "白杏色",
+blue: "蓝色",
+blueviolet: "蓝紫色",
+brown: "棕色",
+burlywood: "实木色",
+cadetblue: "灰蓝色",
+chartreuse: "黄绿色",
+chocolate: "巧克力色",
+coral: "珊瑚色",
+cornflowerblue: "浅蓝色",
+cornsilk: "米绸色",
+crimson: "绯红色",
+cyan: "青蓝色",
+darkblue: "深蓝",
+darkcyan: "深青绿",
+darkgoldenrod: "深金黄",
+darkgray: "深灰色",
+darkgreen: "深绿色",
+darkgrey: "深灰色", // same as darkgray
+darkkhaki: "深卡其色",
+darkmagenta: "深洋红色",
+darkolivegreen: "深橄榄绿",
+darkorange: "深橙色",
+darkorchid: "深紫色",
+darkred: "深红色",
+darksalmon: "深橙红",
+darkseagreen: "深海藻绿",
+darkslateblue: "深青蓝",
+darkslategray: "深青灰",
+darkslategrey: "深青灰", // same as darkslategray
+darkturquoise: "深粉蓝",
+darkviolet: "深紫色",
+deeppink: "深粉红色",
+deepskyblue: "深天蓝色",
+dimgray: "暗灰色",
+dimgrey: "暗灰色", // same as dimgray
+dodgerblue: "闪蓝色",
+firebrick: "砖红",
+floralwhite: "花白色",
+forestgreen: "森林绿",
+fuchsia: "紫红色",
+gainsboro: "淡灰色",
+ghostwhite: "苍白",
+gold: "金黄色",
+goldenrod: "金麒麟色",
+gray: "灰色",
+green: "绿色",
+greenyellow: "绿黄色",
+grey: "灰色", // same as gray
+honeydew: "蜜汁色",
+hotpink: "深粉红",
+indianred: "印度红",
+indigo: "靛青",
+ivory: "象牙色",
+khaki: "卡其色",
+lavender: "淡紫色",
+lavenderblush: "淡紫红",
+lawngreen: "草绿色",
+lemonchiffon: "柠檬绸色",
+lightblue: "淡蓝色",
+lightcoral: "浅珊瑚色",
+lightcyan: "浅青色",
+lightgoldenrodyellow: "浅金黄色",
+lightgray: "浅灰色",
+lightgreen: "浅绿色",
+lightgrey: "浅灰色", // same as lightgray
+lightpink: "浅粉红色",
+lightsalmon: "淡橙色",
+lightseagreen: "浅海藻绿",
+lightskyblue: "浅天蓝色",
+lightslategray: "浅青灰",
+lightslategrey: "浅青灰", // same as lightslategray
+lightsteelblue: "浅钢蓝色",
+lightyellow: "浅黄色",
+lime: "淡黄绿色",
+limegreen: "橙绿色",
+linen: "亚麻色",
+magenta: "洋红色",
+maroon: "栗色",
+mediumaquamarine: "间绿色",
+mediumblue: "间蓝色",
+mediumorchid: "间紫色",
+mediumpurple: "间紫色",
+mediumseagreen: "间海蓝色",
+mediumslateblue: "间暗蓝色",
+mediumspringgreen: "间春绿色",
+mediumturquoise: "间绿宝石色",
+mediumvioletred: "间紫罗兰色",
+midnightblue: "深蓝色",
+mintcream: "薄荷色",
+mistyrose: "浅玫瑰色",
+moccasin: "鹿皮色",
+navajowhite: "纳瓦白",
+navy: "藏青色",
+oldlace: "老白色",
+olive: "橄榄绿",
+olivedrab: "草绿色",
+orange: "橙色",
+orangered: "橙红色",
+orchid: "紫色",
+palegoldenrod: "淡金黄色",
+palegreen: "淡绿色",
+paleturquoise: "苍绿色",
+palevioletred: "苍紫罗兰色",
+papayawhip: "木瓜色",
+peachpuff: "桃色",
+peru: "秘鲁色",
+pink: "粉红色",
+plum: "杨李色",
+powderblue: "铁蓝",
+purple: "紫色",
+red: "红色",
+rosybrown: "褐玫瑰红",
+royalblue: "品蓝",
+saddlebrown: "重褐色",
+salmon: "橙红",
+sandybrown: "沙褐色",
+seagreen: "海绿色",
+seashell: "海贝色",
+sienna: "赭色",
+silver: "银白色",
+skyblue: "天蓝色",
+slateblue: "石蓝色",
+slategray: "灰石色",
+slategrey: "灰石色", // same as slategray
+snow: "雪白色",
+springgreen: "春绿色",
+steelblue: "钢蓝色",
+tan: "棕褐色",
+teal: "水鸭色",
+thistle: "蓟色",
+tomato: "西红柿色",
+turquoise: "绿宝石色",
+violet: "紫色",
+wheat: "浅黄色",
+white: "白色",
+whitesmoke: "烟白色",
+yellow: "黄色",
+yellowgreen: "黄绿色"
+})
diff --git a/dojo/number.js b/dojo/number.js
index 7bb1129..b83d121 100644
--- a/dojo/number.js
+++ b/dojo/number.js
@@ -1,324 +1,573 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.number"]){
-dojo._hasResource["dojo.number"]=true;
 dojo.provide("dojo.number");
+
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojo.cldr","number",null,"ROOT,ar,ca,cs,da,de,de-de,el,en,en-au,en-gb,en-us,es,es-es,fi,fr,he,hu,it,ja,ja-jp,ko,ko-kr,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-cn,zh-tw");
+dojo.requireLocalization("dojo.cldr", "number");
 dojo.require("dojo.string");
 dojo.require("dojo.regexp");
-dojo.number.format=function(_1,_2){
-_2=dojo.mixin({},_2||{});
-var _3=dojo.i18n.normalizeLocale(_2.locale);
-var _4=dojo.i18n.getLocalization("dojo.cldr","number",_3);
-_2.customs=_4;
-var _5=_2.pattern||_4[(_2.type||"decimal")+"Format"];
-if(isNaN(_1)||Math.abs(_1)==Infinity){
-return null;
-}
-return dojo.number._applyPattern(_1,_5,_2);
-};
-dojo.number._numberPatternRE=/[#0,]*[#0](?:\.0*#*)?/;
-dojo.number._applyPattern=function(_6,_7,_8){
-_8=_8||{};
-var _9=_8.customs.group;
-var _a=_8.customs.decimal;
-var _b=_7.split(";");
-var _c=_b[0];
-_7=_b[(_6<0)?1:0]||("-"+_c);
-if(_7.indexOf("%")!=-1){
-_6*=100;
-}else{
-if(_7.indexOf("‰")!=-1){
-_6*=1000;
-}else{
-if(_7.indexOf("¤")!=-1){
-_9=_8.customs.currencyGroup||_9;
-_a=_8.customs.currencyDecimal||_a;
-_7=_7.replace(/\u00a4{1,3}/,function(_d){
-var _e=["symbol","currency","displayName"][_d.length-1];
-return _8[_e]||_8.currency||"";
-});
-}else{
-if(_7.indexOf("E")!=-1){
-throw new Error("exponential notation not supported");
-}
-}
-}
-}
-var _f=dojo.number._numberPatternRE;
-var _10=_c.match(_f);
-if(!_10){
-throw new Error("unable to find a number expression in pattern: "+_7);
-}
-if(_8.fractional===false){
-_8.places=0;
-}
-return _7.replace(_f,dojo.number._formatAbsolute(_6,_10[0],{decimal:_a,group:_9,places:_8.places,round:_8.round}));
-};
-dojo.number.round=function(_11,_12,_13){
-var _14=10/(_13||10);
-return (_14*+_11).toFixed(_12)/_14;
-};
-if((0.9).toFixed()==0){
-(function(){
-var _15=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 _15(v,p,m)+(v>0?d:-d);
-};
-})();
-}
-dojo.number._formatAbsolute=function(_16,_17,_18){
-_18=_18||{};
-if(_18.places===true){
-_18.places=0;
-}
-if(_18.places===Infinity){
-_18.places=6;
-}
-var _19=_17.split(".");
-var _1a=(_18.places>=0)?_18.places:(_19[1]&&_19[1].length)||0;
-if(!(_18.round<0)){
-_16=dojo.number.round(_16,_1a,_18.round);
-}
-var _1b=String(Math.abs(_16)).split(".");
-var _1c=_1b[1]||"";
-if(_18.places){
-var _1d=dojo.isString(_18.places)&&_18.places.indexOf(",");
-if(_1d){
-_18.places=_18.places.substring(_1d+1);
-}
-_1b[1]=dojo.string.pad(_1c.substr(0,_18.places),_18.places,"0",true);
-}else{
-if(_19[1]&&_18.places!==0){
-var pad=_19[1].lastIndexOf("0")+1;
-if(pad>_1c.length){
-_1b[1]=dojo.string.pad(_1c,pad,"0",true);
-}
-var _1e=_19[1].length;
-if(_1e<_1c.length){
-_1b[1]=_1c.substr(0,_1e);
-}
-}else{
-if(_1b[1]){
-_1b.pop();
-}
-}
-}
-var _1f=_19[0].replace(",","");
-pad=_1f.indexOf("0");
-if(pad!=-1){
-pad=_1f.length-pad;
-if(pad>_1b[0].length){
-_1b[0]=dojo.string.pad(_1b[0],pad);
-}
-if(_1f.indexOf("#")==-1){
-_1b[0]=_1b[0].substr(_1b[0].length-pad);
-}
-}
-var _20=_19[0].lastIndexOf(",");
-var _21,_22;
-if(_20!=-1){
-_21=_19[0].length-_20-1;
-var _23=_19[0].substr(0,_20);
-_20=_23.lastIndexOf(",");
-if(_20!=-1){
-_22=_23.length-_20-1;
-}
-}
-var _24=[];
-for(var _25=_1b[0];_25;){
-var off=_25.length-_21;
-_24.push((off>0)?_25.substr(off):_25);
-_25=(off>0)?_25.slice(0,off):"";
-if(_22){
-_21=_22;
-delete _22;
-}
-}
-_1b[0]=_24.reverse().join(_18.group||",");
-return _1b.join(_18.decimal||".");
-};
-dojo.number.regexp=function(_26){
-return dojo.number._parseInfo(_26).regexp;
-};
-dojo.number._parseInfo=function(_27){
-_27=_27||{};
-var _28=dojo.i18n.normalizeLocale(_27.locale);
-var _29=dojo.i18n.getLocalization("dojo.cldr","number",_28);
-var _2a=_27.pattern||_29[(_27.type||"decimal")+"Format"];
-var _2b=_29.group;
-var _2c=_29.decimal;
-var _2d=1;
-if(_2a.indexOf("%")!=-1){
-_2d/=100;
-}else{
-if(_2a.indexOf("‰")!=-1){
-_2d/=1000;
-}else{
-var _2e=_2a.indexOf("¤")!=-1;
-if(_2e){
-_2b=_29.currencyGroup||_2b;
-_2c=_29.currencyDecimal||_2c;
-}
-}
-}
-var _2f=_2a.split(";");
-if(_2f.length==1){
-_2f.push("-"+_2f[0]);
-}
-var re=dojo.regexp.buildGroupRE(_2f,function(_30){
-_30="(?:"+dojo.regexp.escapeString(_30,".")+")";
-return _30.replace(dojo.number._numberPatternRE,function(_31){
-var _32={signed:false,separator:_27.strict?_2b:[_2b,""],fractional:_27.fractional,decimal:_2c,exponent:false};
-var _33=_31.split(".");
-var _34=_27.places;
-if(_33.length==1||_34===0){
-_32.fractional=false;
-}else{
-if(_34===undefined){
-_34=_27.pattern?_33[1].lastIndexOf("0")+1:Infinity;
-}
-if(_34&&_27.fractional==undefined){
-_32.fractional=true;
-}
-if(!_27.places&&(_34<_33[1].length)){
-_34+=","+_33[1].length;
-}
-_32.places=_34;
-}
-var _35=_33[0].split(",");
-if(_35.length>1){
-_32.groupSize=_35.pop().length;
-if(_35.length>1){
-_32.groupSize2=_35.pop().length;
-}
-}
-return "("+dojo.number._realNumberRegexp(_32)+")";
-});
-},true);
-if(_2e){
-re=re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g,function(_36,_37,_38,_39){
-var _3a=["symbol","currency","displayName"][_38.length-1];
-var _3b=dojo.regexp.escapeString(_27[_3a]||_27.currency||"");
-_37=_37?"[\\s\\xa0]":"";
-_39=_39?"[\\s\\xa0]":"";
-if(!_27.strict){
-if(_37){
-_37+="*";
-}
-if(_39){
-_39+="*";
-}
-return "(?:"+_37+_3b+_39+")?";
-}
-return _37+_3b+_39;
-});
+
+
+/*=====
+dojo.number = {
+	// summary: localized formatting and parsing routines for Number
 }
-return {regexp:re.replace(/[\xa0 ]/g,"[\\s\\xa0]"),group:_2b,decimal:_2c,factor:_2d};
+
+dojo.number.__FormatOptions = function(){
+	//	pattern: String?
+	//		override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+	//		with this string.  Default value is based on locale.  Overriding this property will defeat
+	//		localization.  Literal characters in patterns are not supported.
+	//	type: String?
+	//		choose a format type based on the locale from the following:
+	//		decimal, scientific (not yet supported), 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.
+	//	locale: String?
+	//		override the locale used to determine formatting rules
+	//	fractional: Boolean?
+	//		If false, show no decimal places, overriding places and pattern settings.
+	this.pattern = pattern;
+	this.type = type;
+	this.places = places;
+	this.round = round;
+	this.locale = locale;
+	this.fractional = fractional;
+}
+=====*/
+
+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
+	//		[Common Locale Data Repository](http://unicode.org/cldr) as well as the appropriate symbols and
+	//		delimiters.
+	//		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),
+		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.parse=function(_3c,_3d){
-var _3e=dojo.number._parseInfo(_3d);
-var _3f=(new RegExp("^"+_3e.regexp+"$")).exec(_3c);
-if(!_3f){
-return NaN;
+
+//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,
+		decimal = options.customs.decimal,
+		patternList = pattern.split(';'),
+		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}));
 }
-var _40=_3f[1];
-if(!_3f[1]){
-if(!_3f[2]){
-return NaN;
+
+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
 }
-_40=_3f[2];
-_3e.factor*=-1;
+
+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);
+		}
+	})();
 }
-_40=_40.replace(new RegExp("["+_3e.group+"\\s\\xa0"+"]","g"),"").replace(_3e.decimal,".");
-return _40*_3e.factor;
+
+/*=====
+dojo.number.__FormatAbsoluteOptions = function(){
+	//	decimal: String?
+	//		the decimal separator
+	//	group: String?
+	//		the group separator
+	//	places: Number?|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("."),
+		comma = typeof options.places == "string" && options.places.indexOf(","),
+		maxPlaces = options.places;
+	if(comma){
+		maxPlaces = options.places.substring(comma + 1);
+	}else if(!(maxPlaces >= 0)){
+		maxPlaces = (patternParts[1] || []).length;
+	}
+	if(!(options.round < 0)){
+		value = dojo.number.round(value, maxPlaces, options.round);
+	}
+
+	var valueParts = String(Math.abs(value)).split("."),
+		fractional = valueParts[1] || "";
+	if(patternParts[1] || options.places){
+		if(comma){
+			options.places = options.places.substring(0, comma);
+		}
+		// Pad fractional with trailing zeros
+		var pad = options.places !== undefined ? options.places : (patternParts[1] && patternParts[1].lastIndexOf("0") + 1);
+		if(pad > fractional.length){
+			valueParts[1] = dojo.string.pad(fractional, pad, '0', true);
+		}
+
+		// Truncate fractional
+		if(maxPlaces < fractional.length){
+			valueParts[1] = fractional.substr(0, maxPlaces);
+		}
+	}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(','),
+		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._realNumberRegexp=function(_41){
-_41=_41||{};
-if(!("places" in _41)){
-_41.places=Infinity;
-}
-if(typeof _41.decimal!="string"){
-_41.decimal=".";
-}
-if(!("fractional" in _41)||/^0/.test(_41.places)){
-_41.fractional=[true,false];
-}
-if(!("exponent" in _41)){
-_41.exponent=[true,false];
-}
-if(!("eSigned" in _41)){
-_41.eSigned=[true,false];
-}
-var _42=dojo.number._integerRegexp(_41);
-var _43=dojo.regexp.buildGroupRE(_41.fractional,function(q){
-var re="";
-if(q&&(_41.places!==0)){
-re="\\"+_41.decimal;
-if(_41.places==Infinity){
-re="(?:"+re+"\\d+)?";
-}else{
-re+="\\d{"+_41.places+"}";
-}
-}
-return re;
-},true);
-var _44=dojo.regexp.buildGroupRE(_41.exponent,function(q){
-if(q){
-return "([eE]"+dojo.number._integerRegexp({signed:_41.eSigned})+")";
+
+/*=====
+dojo.number.__RegexpOptions = function(){
+	//	pattern: String?
+	//		override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+	//		with this string.  Default value is based on locale.  Overriding this property will defeat
+	//		localization.
+	//	type: String?
+	//		choose a format type based on the locale from the following:
+	//		decimal, scientific (not yet supported), percent, currency. decimal by default.
+	//	locale: String?
+	//		override the locale used to determine formatting rules
+	//	strict: Boolean?
+	//		strict parsing, false by default.  Strict parsing requires input as produced by the format() method.
+	//		Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
+	//	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
 }
-return "";
-});
-var _45=_42+_43;
-if(_43){
-_45="(?:(?:"+_45+")|(?:"+_43+"))";
+
+dojo.number._parseInfo = function(/*Object?*/options){
+	options = options || {};
+	var locale = dojo.i18n.normalizeLocale(options.locale),
+		bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale),
+		pattern = options.pattern || bundle[(options.type || "decimal") + "Format"],
+//TODO: memoize?
+		group = bundle.group,
+		decimal = bundle.decimal,
+		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
+				},
+
+				parts = format.split('.'),
+				places = options.places;
+
+			// special condition for percent (factor != 1)
+			// allow decimal places even if not specified in pattern
+			if(parts.length == 1 && factor != 1){
+			    parts[1] = "###";
+			}
+			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],
+				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
 }
-return _45+_44;
+
+/*=====
+dojo.number.__ParseOptions = function(){
+	//	pattern: String?
+	//		override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+	//		with this string.  Default value is based on locale.  Overriding this property will defeat
+	//		localization.  Literal characters in patterns are not supported.
+	//	type: String?
+	//		choose a format type based on the locale from the following:
+	//		decimal, scientific (not yet supported), percent, currency. decimal by default.
+	//	locale: String?
+	//		override the locale used to determine formatting rules
+	//	strict: Boolean?
+	//		strict parsing, false by default.  Strict parsing requires input as produced by the format() method.
+	//		Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
+	//	fractional: Boolean?|Array?
+	//		Whether to include the fractional portion, where the number of decimal places are implied by pattern
+	//		or explicit 'places' parameter.  The value [true,false] makes the fractional portion optional.
+	this.pattern = pattern;
+	this.type = type;
+	this.locale = locale;
+	this.strict = strict;
+	this.fractional = fractional;
+}
+=====*/
+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)
+    	//		Note that literal characters in patterns are not supported.
+	// expression:
+	//		A string representation of a Number
+	var info = dojo.number._parseInfo(options),
+		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._integerRegexp=function(_46){
-_46=_46||{};
-if(!("signed" in _46)){
-_46.signed=[true,false];
-}
-if(!("separator" in _46)){
-_46.separator="";
-}else{
-if(!("groupSize" in _46)){
-_46.groupSize=3;
-}
-}
-var _47=dojo.regexp.buildGroupRE(_46.signed,function(q){
-return q?"[-+]":"";
-},true);
-var _48=dojo.regexp.buildGroupRE(_46.separator,function(sep){
-if(!sep){
-return "(?:\\d+)";
-}
-sep=dojo.regexp.escapeString(sep);
-if(sep==" "){
-sep="\\s";
-}else{
-if(sep==" "){
-sep="\\s\\xa0";
-}
-}
-var grp=_46.groupSize,_49=_46.groupSize2;
-if(_49){
-var _4a="(?:0|[1-9]\\d{0,"+(_49-1)+"}(?:["+sep+"]\\d{"+_49+"})*["+sep+"]\\d{"+grp+"})";
-return ((grp-_49)>0)?"(?:"+_4a+"|(?:0|[1-9]\\d{0,"+(grp-1)+"}))":_4a;
-}
-return "(?:0|[1-9]\\d{0,"+(grp-1)+"}(?:["+sep+"]\\d{"+grp+"})*)";
-},true);
-return _47+_48;
+
+/*=====
+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 used.  Can be true, false, or [true,
+	//		false].  Default is [true, false] which means optional.
+	//	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 parameters
+	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]; }
+
+	var integerRE = dojo.number._integerRegexp(flags),
+		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
+	);
+
+	var exponentRE = dojo.regexp.buildGroupRE(flags.exponent,
+		function(q){ 
+			if(q){ return "([eE]" + dojo.number._integerRegexp({ signed: flags.eSigned}) + ")"; }
+			return ""; 
+		}
+	);
+
+	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 parameters
+	flags = flags || {};
+	if(!("signed" in flags)){ flags.signed = [true, false]; }
+	if(!("separator" in flags)){
+		flags.separator = "";
+	}else if(!("groupSize" in flags)){
+		flags.groupSize = 3;
+	}
+
+	var signRE = dojo.regexp.buildGroupRE(flags.signed,
+		function(q){ return q ? "[-+]" : ""; },
+		true
+	);
+
+	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
+	);
+
+	return signRE + numberRE; // String
 }
diff --git a/dojo/parser.js b/dojo/parser.js
index d7c753e..08dea88 100644
--- a/dojo/parser.js
+++ b/dojo/parser.js
@@ -1,222 +1,441 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.parser"]){
-dojo._hasResource["dojo.parser"]=true;
 dojo.provide("dojo.parser");
 dojo.require("dojo.date.stamp");
-dojo.parser=new function(){
-var d=dojo;
-this._attrName=d._scopeName+"Type";
-this._query="["+this._attrName+"]";
-function _1(_2){
-if(d.isString(_2)){
-return "string";
-}
-if(typeof _2=="number"){
-return "number";
-}
-if(typeof _2=="boolean"){
-return "boolean";
-}
-if(d.isFunction(_2)){
-return "function";
-}
-if(d.isArray(_2)){
-return "array";
-}
-if(_2 instanceof Date){
-return "date";
-}
-if(_2 instanceof d._Url){
-return "url";
-}
-return "object";
-};
-function _3(_4,_5){
-switch(_5){
-case "string":
-return _4;
-case "number":
-return _4.length?Number(_4):NaN;
-case "boolean":
-return typeof _4=="boolean"?_4:!(_4.toLowerCase()=="false");
-case "function":
-if(d.isFunction(_4)){
-_4=_4.toString();
-_4=d.trim(_4.substring(_4.indexOf("{")+1,_4.length-1));
-}
-try{
-if(_4.search(/[^\w\.]+/i)!=-1){
-return new Function(_4);
-}else{
-return d.getObject(_4,false);
-}
-}
-catch(e){
-return new Function();
-}
-case "array":
-return _4?_4.split(/\s*,\s*/):[];
-case "date":
-switch(_4){
-case "":
-return new Date("");
-case "now":
-return new Date();
-default:
-return d.date.stamp.fromISOString(_4);
-}
-case "url":
-return d.baseUrl+_4;
-default:
-return d.fromJson(_4);
-}
-};
-var _6={};
-dojo.connect(dojo,"extend",function(){
-_6={};
-});
-function _7(_8){
-if(!_6[_8]){
-var _9=d.getObject(_8);
-if(!d.isFunction(_9)){
-throw new Error("Could not load class '"+_8+"'. Did you spell the name correctly and use a full path, like 'dijit.form.Button'?");
-}
-var _a=_9.prototype;
-var _b={},_c={};
-for(var _d in _a){
-if(_d.charAt(0)=="_"){
-continue;
-}
-if(_d in _c){
-continue;
-}
-var _e=_a[_d];
-_b[_d]=_1(_e);
-}
-_6[_8]={cls:_9,params:_b};
-}
-return _6[_8];
-};
-this._functionFromScript=function(_f){
-var _10="";
-var _11="";
-var _12=_f.getAttribute("args");
-if(_12){
-d.forEach(_12.split(/\s*,\s*/),function(_13,idx){
-_10+="var "+_13+" = arguments["+idx+"]; ";
-});
-}
-var _14=_f.getAttribute("with");
-if(_14&&_14.length){
-d.forEach(_14.split(/\s*,\s*/),function(_15){
-_10+="with("+_15+"){";
-_11+="}";
-});
-}
-return new Function(_10+_f.innerHTML+_11);
-};
-this.instantiate=function(_16,_17,_18){
-var _19=[],dp=dojo.parser;
-_17=_17||{};
-_18=_18||{};
-d.forEach(_16,function(_1a){
-if(!_1a){
-return;
-}
-var _1b=dp._attrName in _17?_17[dp._attrName]:_1a.getAttribute(dp._attrName);
-if(!_1b||!_1b.length){
-return;
-}
-var _1c=_7(_1b),_1d=_1c.cls,ps=_1d._noScript||_1d.prototype._noScript;
-var _1e={},_1f=_1a.attributes;
-for(var _20 in _1c.params){
-var _21=_20 in _17?{value:_17[_20],specified:true}:_1f.getNamedItem(_20);
-if(!_21||(!_21.specified&&(!dojo.isIE||_20.toLowerCase()!="value"))){
-continue;
-}
-var _22=_21.value;
-switch(_20){
-case "class":
-_22="className" in _17?_17.className:_1a.className;
-break;
-case "style":
-_22="style" in _17?_17.style:(_1a.style&&_1a.style.cssText);
-}
-var _23=_1c.params[_20];
-if(typeof _22=="string"){
-_1e[_20]=_3(_22,_23);
-}else{
-_1e[_20]=_22;
-}
-}
-if(!ps){
-var _24=[],_25=[];
-d.query("> script[type^='dojo/']",_1a).orphan().forEach(function(_26){
-var _27=_26.getAttribute("event"),_1b=_26.getAttribute("type"),nf=d.parser._functionFromScript(_26);
-if(_27){
-if(_1b=="dojo/connect"){
-_24.push({event:_27,func:nf});
-}else{
-_1e[_27]=nf;
-}
-}else{
-_25.push(nf);
-}
-});
-}
-var _28=_1d.markupFactory||_1d.prototype&&_1d.prototype.markupFactory;
-var _29=_28?_28(_1e,_1a,_1d):new _1d(_1e,_1a);
-_19.push(_29);
-var _2a=_1a.getAttribute("jsId");
-if(_2a){
-d.setObject(_2a,_29);
-}
-if(!ps){
-d.forEach(_24,function(_2b){
-d.connect(_29,_2b.event,null,_2b.func);
-});
-d.forEach(_25,function(_2c){
-_2c.call(_29);
-});
-}
-});
-if(!_17._started){
-d.forEach(_19,function(_2d){
-if(!_18.noStart&&_2d&&_2d.startup&&!_2d._started&&(!_2d.getParent||!_2d.getParent())){
-_2d.startup();
-}
-});
-}
-return _19;
-};
-this.parse=function(_2e,_2f){
-var _30;
-if(!_2f&&_2e&&_2e.rootNode){
-_2f=_2e;
-_30=_2f.rootNode;
-}else{
-_30=_2e;
-}
-var _31=d.query(this._query,_30);
-return this.instantiate(_31,null,_2f);
-};
+
+new Date("X"); // workaround for #11279, new Date("") == NaN
+
+dojo.parser = new function(){
+	// summary: The Dom/Widget parsing package
+
+	var d = dojo;
+	this._attrName = d._scopeName + "Type";
+	this._query = "[" + this._attrName + "]";
+
+	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 === "" || value.search(/[^\w\.]+/i) != -1){
+						// The user has specified some text for a function like "return x+5"
+						return new Function(value);
+					}else{
+						// The user has specified the name of a function like "myOnClick"
+						// or a single word function "return"
+						return d.getObject(value, false) || new Function(value);
+					}
+				}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"} }
+	};
+
+	// Widgets like BorderContainer add properties to _Widget via dojo.extend().
+	// If BorderContainer is loaded after _Widget's parameter list has been cached,
+	// we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
+	dojo.connect(dojo, "extend", function(){
+		instanceClasses = {};
+	});
+
+	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(!cls){ return null; }		// class not defined [yet]
+
+			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, /* Object? */args){
+		// summary:
+		//		Takes array of nodes, and turns them into class instances and
+		//		potentially calls a startup method to allow them to connect with
+		//		any children.
+		// nodes: Array
+		//		Array of nodes or objects like
+		//	|		{
+		//	|			type: "dijit.form.Button",
+		//	|			node: DOMNode,
+		//	|			scripts: [ ... ],	// array of <script type="dojo/..."> children of node
+		//	|			inherited: { ... }	// settings inherited from ancestors like dir, theme, etc.
+		//	|		}
+		// 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.
+		// args: Object?
+		//		An object used to hold kwArgs for instantiation.
+		//		Supports 'noStart' and inherited.
+		var thelist = [], dp = dojo.parser;
+		mixin = mixin||{};
+		args = args||{};
+		
+		d.forEach(nodes, function(obj){
+			if(!obj){ return; }
+
+			// Get pointers to DOMNode, dojoType string, and clsInfo (metadata about the dojoType), etc.s
+			var node, type, clsInfo, clazz, scripts;
+			if(obj.node){
+				// new format of nodes[] array, object w/lots of properties pre-computed for me
+				node = obj.node;
+				type = obj.type;
+				clsInfo = obj.clsInfo || (type && getClassInfo(type));
+				clazz = clsInfo && clsInfo.cls;
+				scripts = obj.scripts;
+			}else{
+				// old (backwards compatible) format of nodes[] array, simple array of DOMNodes
+				node = obj;
+				type = dp._attrName in mixin ? mixin[dp._attrName] : node.getAttribute(dp._attrName);
+				clsInfo = type && getClassInfo(type);
+				clazz = clsInfo && clsInfo.cls;
+				scripts = (clazz && (clazz._noScript || clazz.prototype._noScript) ? [] : 
+							d.query("> script[type^='dojo/']", node));
+			}
+			if(!clsInfo){
+				throw new Error("Could not load class '" + type);
+			}
+
+			// Setup hash to hold parameter settings for this widget.   Start with the parameter
+			// settings inherited from ancestors ("dir" and "lang").
+			// Inherited setting may later be overridden by explicit settings on node itself.
+			var params = {},
+				attributes = node.attributes;
+			if(args.defaults){
+				// settings for the document itself (or whatever subtree is being parsed)
+				dojo.mixin(params, args.defaults);
+			}
+			if(obj.inherited){
+				// settings from dir=rtl or lang=... on a node above this node
+				dojo.mixin(params, obj.inherited);
+			}
+
+			// read parameters (ie, attributes) specified on DOMNode
+			// clsInfo.params lists expected params like {"checked": "boolean", "n": "number"}
+			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 />
+			var connects = [],	// functions to connect after instantiation
+				calls = [];		// functions to call after instantiation
+
+			d.forEach(scripts, function(script){
+				node.removeChild(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 || clazz.prototype && 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
+			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
+		if(!mixin._started){
+			// TODO: for 2.0, when old instantiate() API is desupported, store parent-child
+			// relationships in the nodes[] array so that no getParent() call is needed.
+			// Note that will  require a parse() call from ContentPane setting a param that the
+			// ContentPane is the parent widget (so that the parse doesn't call startup() on the
+			// ContentPane's children)
+			d.forEach(thelist, function(instance){
+				if(	!args.noStart && instance  && 
+					instance.startup &&
+					!instance._started && 
+					(!instance.getParent || !instance.getParent())
+				){
+					instance.startup();
+				}
+			});
+		}
+		return thelist;
+	};
+
+	this.parse = function(/*DomNode?*/ rootNode, /* Object? */ args){
+		// summary:
+		//		Scan the DOM for class instances, and instantiate them.
+		//
+		// description:
+		//		Search specified node (or root node) recursively for class instances,
+		//		and instantiate them Searches for
+		//		dojoType="qualified.class.name"
+		//
+		// rootNode: DomNode?
+		//		A default starting root node from which to start the parsing. Can be
+		//		omitted, defaulting to the entire document. If omitted, the `args`
+		//		object can be passed in this place. If the `args` object has a 
+		//		`rootNode` member, that is used.
+		//
+		// args:
+		//		a kwArgs object passed along to instantiate()
+		//		
+		//			* noStart: Boolean?
+		//				when set will prevent the parser from calling .startup()
+		//				when locating the nodes. 
+		//			* rootNode: DomNode?
+		//				identical to the function's `rootNode` argument, though
+		//				allowed to be passed in via this `args object. 
+		//			* inherited: Object
+		//				Hash possibly containing dir and lang settings to be applied to
+		//				parsed widgets, unless there's another setting on a sub-node that overrides
+		//
+		//
+		// example:
+		//		Parse all widgets on a page:
+		//	|		dojo.parser.parse();
+		//
+		// example:
+		//		Parse all classes within the node with id="foo"
+		//	|		dojo.parser.parse(dojo.byId(foo));
+		//
+		// example:
+		//		Parse all classes in a page, but do not call .startup() on any 
+		//		child
+		//	|		dojo.parser.parse({ noStart: true })
+		//
+		// example:
+		//		Parse all classes in a node, but do not call .startup()
+		//	|		dojo.parser.parse(someNode, { noStart:true });
+		//	|		// or
+		// 	|		dojo.parser.parse({ noStart:true, rootNode: someNode });
+
+		// determine the root node based on the passed arguments.
+		var root;
+		if(!args && rootNode && rootNode.rootNode){
+			args = rootNode;
+			root = args.rootNode;
+		}else{
+			root = rootNode;
+		}
+
+		var attrName = this._attrName;
+		function scan(parent, list){
+			// summary:
+			//		Parent is an Object representing a DOMNode, with or without a dojoType specified.
+			//		Scan parent's children looking for nodes with dojoType specified, storing in list[].
+			//		If parent has a dojoType, also collects <script type=dojo/*> children and stores in parent.scripts[].
+			// parent: Object
+			//		Object representing the parent node, like
+			//	|	{
+			//	|		node: DomNode, 			// scan children of this node
+			//	|		inherited: {dir: "rtl"},	// dir/lang setting inherited from above node
+			//	|
+			//	|		// attributes only set if node has dojoType specified
+			//	|		scripts: [],			// empty array, put <script type=dojo/*> in here
+			//	|		clsInfo: { cls: dijit.form.Button, ...}
+			//	|	}
+			// list: DomNode[]
+			//		Output array of objects (same format as parent) representing nodes to be turned into widgets
+
+			// Effective dir and lang settings on parent node, either set directly or inherited from grandparent
+			var inherited = dojo.clone(parent.inherited);
+			dojo.forEach(["dir", "lang"], function(name){
+				var val = parent.node.getAttribute(name);
+				if(val){
+					inherited[name] = val;
+				}
+			});
+
+			// if parent is a widget, then search for <script type=dojo/*> tags and put them in scripts[].
+			var scripts = parent.scripts;
+
+			// unless parent is a widget with the stopParser flag set, continue search for dojoType, recursively
+			var recurse = !parent.clsInfo || !parent.clsInfo.cls.prototype.stopParser;
+
+			// scan parent's children looking for dojoType and <script type=dojo/*>
+			for(var child = parent.node.firstChild; child; child = child.nextSibling){
+				if(child.nodeType == 1){
+					var type = recurse && child.getAttribute(attrName);
+					if(type){
+						// if dojoType specified, add to output array of nodes to instantiate
+						var params = {
+							"type": type,
+							clsInfo: getClassInfo(type),	// note: won't find classes declared via dojo.Declaration
+							node: child,
+							scripts: [], // <script> nodes that are parent's children
+							inherited: inherited // dir & lang attributes inherited from parent
+						};
+						list.push(params);
+
+						// Recurse, collecting <script type="dojo/..."> children, and also looking for
+						// descendant nodes with dojoType specified (unless the widget has the stopParser flag),
+						scan(params, list);
+					}else if(scripts && child.nodeName.toLowerCase() == "script"){
+						// if <script type="dojo/...">, save in scripts[]
+						type = child.getAttribute("type");
+						if (type && /^dojo\//i.test(type)) {
+							scripts.push(child);
+						}
+					}else if(recurse){
+						// Recurse, looking for grandchild nodes with dojoType specified
+						scan({
+							node: child,
+							inherited: inherited
+						}, list);
+					}
+				}
+			}
+		}
+
+		// Make list of all nodes on page w/dojoType specified
+		var list = [];
+		scan({
+			node: root ? dojo.byId(root) : dojo.body(),
+			inherited: (args && args.inherited) || {
+				dir: dojo._isBodyLtr() ? "ltr" : "rtl"
+			}
+		}, list);
+
+		// go build the object instances
+		return this.instantiate(list, null, args); // Array
+	};
 }();
+
+//Register the parser callback. It should be the first callback
+//after the a11y test.
+
 (function(){
-var _32=function(){
-if(dojo.config.parseOnLoad){
-dojo.parser.parse();
-}
-};
-if(dojo.exists("dijit.wai.onload")&&(dijit.wai.onload===dojo._loaders[0])){
-dojo._loaders.splice(1,0,_32);
-}else{
-dojo._loaders.unshift(_32);
-}
+	var parseRunner = function(){ 
+		if(dojo.config.parseOnLoad){
+			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);
+	}
 })();
-}
diff --git a/dojo/regexp.js b/dojo/regexp.js
index 834c72d..a670193 100644
--- a/dojo/regexp.js
+++ b/dojo/regexp.js
@@ -1,32 +1,64 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.regexp"]){
-dojo._hasResource["dojo.regexp"]=true;
 dojo.provide("dojo.regexp");
-dojo.regexp.escapeString=function(_1,_2){
-return _1.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g,function(ch){
-if(_2&&_2.indexOf(ch)!=-1){
-return ch;
-}
-return "\\"+ch;
-});
+
+/*=====
+dojo.regexp = {
+	// summary: Regular expressions and Builder resources
 };
-dojo.regexp.buildGroupRE=function(_3,re,_4){
-if(!(_3 instanceof Array)){
-return re(_3);
+=====*/
+
+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
 }
-var b=[];
-for(var i=0;i<_3.length;i++){
-b.push(re(_3[i]));
+
+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
 }
-return dojo.regexp.group(b.join("|"),_4);
-};
-dojo.regexp.group=function(_5,_6){
-return "("+(_6?"?:":"")+_5+")";
-};
+
+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
 }
diff --git a/dojo/resources/_modules.js b/dojo/resources/_modules.js
index 0b276e5..bfc6c76 100644
--- a/dojo/resources/_modules.js
+++ b/dojo/resources/_modules.js
@@ -1,7 +1,36 @@
-/*
-	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
-*/
+/*=====
+// Supplemental summaries for those hard-to-doc places your conventional doc parser can't reach.
+// Where possible, these summaries should appear inline in the code.
+//
+// this is "package level documentation"
 
+dojo.cldr = {
+	// summary: transformation of relevant pieces of the Unicode.org Common Locale Data Repository
+	// (see http://unicode.org/cldr) to JSON from the original XML with associated utility classes
+};
 
+dojo.data = {
+	// summary: A uniform data access layer
+};
+
+dojo.dnd = {
+	// summary: Drag and Drop resources
+};
+
+dojo.io = {
+	// summary: Additional I/O transports (Ajax)
+};
+
+dojo.rpc = {
+	// summary: Dojo remote-procedure-call resources
+};
+
+// "variables"
+
+dojo.baseUrl = {
+	// summary: The root relative path to dojo.js (as a string)
+	// example: 
+	//	if(typeof dojo != "undefined"){ console.log(dojo.baseUrl); }
+};
+
+=====*/
diff --git a/dojo/resources/dnd.css b/dojo/resources/dnd.css
index def28fc..b7f1651 100644
--- a/dojo/resources/dnd.css
+++ b/dojo/resources/dnd.css
@@ -1,4 +1,4 @@
-
+/* DnD avatar-specific settings */
 .dojoDndAvatar			{font-size: 75%; color: black;}
 .dojoDndAvatarHeader td	{padding-left: 20px; padding-right: 4px;}
 .dojoDndAvatarHeader	{background: #ccc;}
@@ -7,8 +7,10 @@
 .dojoDndCopy .dojoDndAvatarHeader	{background-image: url(images/dndNoCopy.png); background-repeat: no-repeat;}
 .dojoDndMove .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{background-image: url(images/dndMove.png); background-repeat: no-repeat;}
 .dojoDndCopy .dojoDndAvatarCanDrop .dojoDndAvatarHeader	{background-image: url(images/dndCopy.png); background-repeat: no-repeat;}
+
 .dojoDndHandle {cursor: move;}
 .dojoDndIgnore {cursor: default;}
+
 .dijit_a11y .dojoDndAvatar { font-size: 1em; font-weight:bold;}
 .dijit_a11y .dojoDndAvatarHeader td {padding-left:2px !important;}
 .dijit_a11y .dojoDndAvatarHeader td span {padding-right: 5px;}
diff --git a/dojo/resources/dojo.css b/dojo/resources/dojo.css
index 16e0950..fdaa842 100644
--- a/dojo/resources/dojo.css
+++ b/dojo/resources/dojo.css
@@ -1,28 +1,101 @@
+/*
+	dojo.css
+	Baseline CSS file for general usage.
+
+	This file is intended to be a "quick and dirty" stylesheet you can use to give
+	a straight-up web page some basic styling without having to do the dirty work
+	yourself.  It includes a modified version of YUI's reset.css (we pulled some
+	of the list reset definitions, among other things), and then provides some very
+	basic style rules to be applied to general HTML elements.
+
+	This stylesheet is NOT intended to serve as the foundation for more complex things--
+	including the use of a TABLE for layout purposes.  The table definitions in this
+	file make the assumption that you will be using tables for thier declared purpose:
+	displaying tabular data.
+
+	If you are looking for a baseline stylesheet using tables for grid layout, you will
+	need to supply your own layout rules to override the ones in this stylesheet.
+	
+	Applications using Dojo will function correctly without including this
+	file, but it should provide sane defaults for many common things that page
+	authors often need to set up manually.
+
+	The Dojo Core uses this stylesheet to quickly style HTML-based tests and demos.  Feel
+	free to use it as you will.
+*/
+
+/*****************************************************************************************/
+
+/*
+	The below are borrowed from YUI's reset style sheets for pages and fonts.
+	We've verified w/ the YUI development team that these are entirely
+	copyright Yahoo, written entirely by Nate Koechley and Matt Sweeney without
+	external contributions.
+
+	Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+	Code licensed under the BSD License:
+	http://developer.yahoo.net/yui/license.txt
+	version: 2.2.1
+*/
 
 body, div, dl, dt, dd, li, h1, h2, h3, h4, h5, h6, pre, form, fieldset, input, textarea, p, blockquote, th, td {
 	margin: 0;
 	padding: 0;
 }
+
 fieldset, img {
 	border: 0 none;
 }
+
 address, caption, cite, code, dfn, th, var {
 	font-style: normal; 
 	font-weight: normal;
 }
+
 caption, th {
 	text-align: left;
 }
+
 q:before, q:after {
 	content:"";
 }
+
 abbr, acronym {
 	border:0;
 }
+/* End YUI imported code. */
+
+/*****************************************************************************************/
+
+/* 
+	Begin Dojo additions.
+
+	Style definitions, based loosely on the Dijit Tundra theme.
+	Relative unit calculations based on "Compose to a Vertical Rhythm",
+	by Richard Rutter (http://24ways.org/2006/compose-to-a-vertical-rhythm)
+
+	If changing the font size, make sure you do it in both
+	percent and px (% for IE, px for everything else). 
+	% value based on default size of 16px (in most browsers).
+	So if you want the default size to be 14px, set the 
+	% to 87% (14 / 16 = 0.875).
+
+	Typical values:
+	10px: 62.5%
+	11px: 69% (68.75)
+	12px: 75%
+	13px: 81.25%
+	14px: 87.5%
+	16px: 100%
+
+	Default: 12px
+*/
 body { 
 	font: 12px Myriad,Helvetica,Tahoma,Arial,clean,sans-serif; 
 	*font-size: 75%;
 }
+
+/* Headings */
 h1 {
 	font-size: 1.5em; 
 	font-weight: normal;
@@ -30,6 +103,7 @@ h1 {
 	margin-top: 1em;
 	margin-bottom:0;
 }
+
 h2 { 
 	font-size: 1.1667em; 
 	font-weight: bold; 
@@ -37,6 +111,7 @@ h2 {
 	margin-top: 1.929em; 
 	margin-bottom:0.643em;
 }
+
 h3, h4, h5, h6 {
 	font-size: 1em; 
 	font-weight: bold; 
@@ -44,12 +119,15 @@ h3, h4, h5, h6 {
 	margin-top: 1.5em; 
 	margin-bottom: 0;
 }
+
+/* paragraphs, quotes and lists */
 p { 
 	font-size: 1em; 
 	margin-top: 1.5em; 
 	margin-bottom: 1.5em; 
 	line-height: 1.5em;
 }
+
 blockquote { 
 	font-size: 0.916em; 
 	margin-top: 3.272em; 
@@ -59,11 +137,14 @@ blockquote {
 	border-top: 1px solid #ccc; 
 	border-bottom: 1px solid #ccc;
 }
+
 ol li, ul li { 
 	font-size: 1em; 
 	line-height: 1.5em; 
 	margin: 0;
 }
+
+/* pre and code */
 pre, code { 
 	font-size:115%;
 	*font-size:100%;
@@ -71,29 +152,45 @@ pre, code {
 	background-color: #efefef; 
 	border: 1px solid #ccc;
 }
+
 pre { 
 	border-width: 1px 0; 
 	padding: 1.5em;
 }
+
+/*
+	Tables
+
+	Note that these table definitions make the assumption that you are using tables
+	to display tabular data, and NOT using tables as layout mechanisms.  If you are
+	using tables for layout, you will probably want to override these rules with
+	more specific ones.
+
+	These definitions make tabular data look presentable, particularly when presented
+	inline with paragraphs.
+*/
 table {  font-size:100%; }
-table.dojoTabular { 
+
+.dojoTabular { 
 	border-collapse: collapse; 
 	border-spacing: 0; 
 	border: 1px solid #ccc; 
 	margin: 0 1.5em;
 }
+
 .dojoTabular th { 
 	text-align: center; 
 	font-weight: bold;
 }
-table.dojoTabular thead, table.dojoTabular tfoot { 
+
+.dojoTabular thead,
+.dojoTabular tfoot { 
 	background-color: #efefef; 
 	border: 1px solid #ccc; 
 	border-width: 1px 0; 
 }
-table.dojoTabular thead tr th,
-table.dojoTabular thead tr td,
-table.dojoTabular tbody tr td,
-table.dojoTabular tfoot tr td { 
+
+.dojoTabular th,
+.dojoTabular td { 
 	padding: 0.25em 0.5em;
 }
diff --git a/dojo/robot.js b/dojo/robot.js
index 89949cb..c7db864 100644
--- a/dojo/robot.js
+++ b/dojo/robot.js
@@ -1,44 +1,174 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.robot"]){
-dojo._hasResource["dojo.robot"]=true;
 dojo.provide("dojo.robot");
 dojo.experimental("dojo.robot");
 dojo.require("doh.robot");
+dojo.require("dojo.window");
+
 (function(){
-dojo.mixin(doh.robot,{_resolveNode:function(n){
-if(typeof n=="function"){
-n=n();
-}
-return n?dojo.byId(n):null;
-},_scrollIntoView:function(_1){
-_1.scrollIntoView(false);
-},_position:function(n){
-return dojo.position(n,false);
-},scrollIntoView:function(_2,_3){
-doh.robot.sequence(function(){
-doh.robot._scrollIntoView(doh.robot._resolveNode(_2));
-},_3);
-},mouseMoveAt:function(_4,_5,_6,_7,_8){
-doh.robot._assertRobot();
-_6=_6||100;
-this.sequence(function(){
-_4=doh.robot._resolveNode(_4);
-doh.robot._scrollIntoView(_4);
-var _9=doh.robot._position(_4);
-if(_8===undefined){
-_7=_9.w/2;
-_8=_9.h/2;
-}
-var x=_9.x+_7;
-var y=_9.y+_8;
-doh.robot._mouseMove(x,y,false,_6);
-},_5,_6);
-}});
+// users who use doh+dojo get the added convenience of dojo.mouseMoveAt,
+// instead of computing the absolute coordinates of their elements themselves
+dojo.mixin(doh.robot,{
+
+	_resolveNode: function(/*String||DOMNode||Function*/ n){
+		if(typeof n == "function"){
+			// if the user passed a function returning a node, evaluate it
+			n = n();
+		}
+		return n? dojo.byId(n) : null;
+	},
+
+	_scrollIntoView: function(/*Node*/ n){
+		// scrolls the passed node into view, scrolling all ancester frames/windows as well.
+		// Assumes parent iframes can be made fully visible given the current browser window size
+		var d = dojo,
+			dr = doh.robot,
+			p = null;
+		d.forEach(dr._getWindowChain(n), function(w){
+			d.withGlobal(w, function(){
+				// get the position of the node wrt its parent window
+				// if it is a parent frame, its padding and border extents will get added in
+				var p2 = d.position(n, false),
+					b = d._getPadBorderExtents(n),
+					oldp = null;
+				// if p2 is the position of the original passed node, store the position away as p
+				// otherwise, node is actually an iframe. in this case, add the iframe's position wrt its parent window and also the iframe's padding and border extents
+				if(!p){
+					p = p2;
+				}else{
+					oldp = p;
+					p = {x: p.x+p2.x+b.l,
+						y: p.y+p2.y+b.t,
+						w: p.w,
+						h: p.h};
+
+				}
+				// scroll the parent window so that the node translated into the parent window's coordinate space is in view
+				dojo.window.scrollIntoView(n,p);
+				// adjust position for the new scroll offsets
+				p2 = d.position(n, false);
+				if(!oldp){
+					p = p2;
+				}else{
+					p = {x: oldp.x+p2.x+b.l,
+						y: oldp.y+p2.y+b.t,
+						w: p.w,
+						h: p.h};
+				}
+				// get the parent iframe so it can be scrolled too
+				n = w.frameElement;
+			});
+		});
+	},
+
+	_position: function(/*Node*/ n){
+		// Returns the dojo.position of the passed node wrt the passed window's viewport,
+		// following any parent iframes containing the node and clipping the node to each iframe.
+		// precondition: _scrollIntoView already called
+		var d = dojo, p = null, M = Math.max, m = Math.min;
+		// p: the returned position of the node
+		d.forEach(doh.robot._getWindowChain(n), function(w){
+			d.withGlobal(w, function(){
+				// get the position of the node wrt its parent window
+				// if it is a parent frame, its padding and border extents will get added in
+				var p2 = d.position(n, false), b = d._getPadBorderExtents(n);
+				// if p2 is the position of the original passed node, store the position away as p
+				// otherwise, node is actually an iframe. in this case, add the iframe's position wrt its parent window and also the iframe's padding and border extents
+				if(!p){
+					p = p2;
+				}else{
+					var view;
+					d.withGlobal(n.contentWindow,function(){
+						view=dojo.window.getBox();
+					});
+					p2.r = p2.x+view.w;
+					p2.b = p2.y+view.h;
+					p = {x: M(p.x+p2.x,p2.x)+b.l, // clip left edge of node wrt the iframe
+						y: M(p.y+p2.y,p2.y)+b.t,	// top edge
+						r: m(p.x+p2.x+p.w,p2.r)+b.l,	// right edge (to compute width)
+						b: m(p.y+p2.y+p.h,p2.b)+b.t}; // bottom edge (to compute height)
+					// save a few bytes by computing width and height from r and b
+					p.w = p.r-p.x;
+					p.h = p.b-p.y;
+				}
+				// the new node is now the old node's parent iframe
+				n=w.frameElement;
+			});
+		});
+		return p;
+	},
+
+	_getWindowChain : function(/*Node*/ n){
+		// Returns an array of windows starting from the passed node's parent window and ending at dojo's window
+		var cW = dojo.window.get(n.ownerDocument);
+		var arr=[cW];
+		var f = cW.frameElement;
+		return (cW == dojo.global || f == null)? arr : arr.concat(doh.robot._getWindowChain(f));
+	},
+
+	scrollIntoView : function(/*String||DOMNode||Function*/ node, /*Number, optional*/ delay){
+		// summary:
+		//		Scroll the passed node into view, if it is not.
+		//
+		// node:
+		//		The id of the node, or the node itself, to move the mouse to.
+		//		If you pass an id or a function that returns a node, the node will not be evaluated until the movement executes.
+		//		This is useful if you need to move the mouse to an node that is not yet present.
+		//
+		// delay:
+		//		Delay, in milliseconds, to wait before firing.
+		//		The delay is a delta with respect to the previous automation call.
+		//
+		doh.robot.sequence(function(){
+			doh.robot._scrollIntoView(doh.robot._resolveNode(node));
+		}, delay);
+	},
+
+	mouseMoveAt : function(/*String||DOMNode||Function*/ node, /*Integer, optional*/ delay, /*Integer, optional*/ duration, /*Number, optional*/ offsetX, /*Number, optional*/ offsetY){
+		// summary:
+		//		Moves the mouse over the specified node at the specified relative x,y offset.
+		//
+		// description:
+		// 		Moves the mouse over the specified node at the specified relative x,y offset.
+		// 		If you do not specify an offset, mouseMove will default to move to the middle of the node.
+		// 		Example: to move the mouse over a ComboBox's down arrow node, call doh.mouseMoveAt(dijit.byId('setvaluetest').downArrowNode);
+		//
+		// node:
+		//		The id of the node, or the node itself, to move the mouse to.
+		//		If you pass an id or a function that returns a node, the node will not be evaluated until the movement executes.
+		//		This is useful if you need to move the mouse to an node that is not yet present.
+		//
+		// delay:
+		//		Delay, in milliseconds, to wait before firing.
+		//		The delay is a delta with respect to the previous automation call.
+		//		For example, the following code ends after 600ms:
+		//			doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms
+		//			doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all
+		//
+		// duration:
+		//		Approximate time Robot will spend moving the mouse
+		//		The default is 100ms.
+		//
+		// offsetX:
+		//		x offset relative to the node, in pixels, to move the mouse. The default is half the node's width.
+		//
+		// offsetY:
+		//		y offset relative to the node, in pixels, to move the mouse. The default is half the node's height.
+		//
+
+		doh.robot._assertRobot();
+		duration = duration||100;
+		this.sequence(function(){
+			node=doh.robot._resolveNode(node);
+			doh.robot._scrollIntoView(node);
+			var pos = doh.robot._position(node);
+			if(offsetY === undefined){
+				offsetX=pos.w/2;
+				offsetY=pos.h/2;
+			}
+			var x = pos.x+offsetX;
+			var y = pos.y+offsetY;
+			doh.robot._mouseMove(x, y, false, duration);
+		}, delay, duration);
+	}
+});
+
 })();
-}
diff --git a/dojo/robotx.js b/dojo/robotx.js
index 9f68845..3fd5f2e 100644
--- a/dojo/robotx.js
+++ b/dojo/robotx.js
@@ -1,80 +1,129 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.robotx"]){
-dojo._hasResource["dojo.robotx"]=true;
 dojo.provide("dojo.robotx");
 dojo.require("dojo.robot");
 dojo.experimental("dojo.robotx");
+
+// loads an external app into an iframe and points dojo.doc to the iframe document, allowing the robot to control it
+// to use: set robotURL in djConfig to the URL you want to load
+// dojo.require this file
+
 (function(){
+// have to wait for test page to load before testing!
 doh.robot._runsemaphore.lock.push("dojo.robotx.lock");
-var _1=document.getElementById("robotapplication");
-var _2=dojo.connect(doh,"_groupStarted",function(){
-dojo.disconnect(_2);
-_1.style.visibility="visible";
+
+var iframe = document.getElementById('robotapplication');
+
+var groupStarted=dojo.connect(doh, '_groupStarted', function(){
+	dojo.disconnect(groupStarted);
+	iframe.style.visibility="visible";
 });
-var _3=function(){
-doh.robot._updateDocument();
-_3=null;
-var _4=(document.compatMode=="BackCompat")?document.body:document.documentElement;
-var _5=document.getElementById("robotconsole").offsetHeight;
-if(_5){
-_1.style.height=(_4.clientHeight-_5)+"px";
-}
-doh.run();
+
+var onIframeLoad=function(){
+	//iframe = document.getElementById('robotapplication');
+	doh.robot._updateDocument();
+	onIframeLoad = null;
+	var scrollRoot = (document.compatMode == 'BackCompat')? document.body : document.documentElement;
+	var consoleHeight = document.getElementById('robotconsole').offsetHeight;
+	if(consoleHeight){
+		iframe.style.height = (scrollRoot.clientHeight - consoleHeight)+"px";
+	}
+	doh.run();
 };
-var _6=function(){
-if(_3){
-_3();
-}
-var _7=dojo.connect(dojo.body(),"onunload",function(){
-dojo.global=window;
-dojo.doc=document;
-dojo.disconnect(_7);
-});
+
+var iframeLoad=function(){
+	if(onIframeLoad){
+		onIframeLoad();
+	}
+	var unloadConnect = dojo.connect(dojo.body(), 'onunload', function(){
+		dojo.global = window;
+		dojo.doc = document;
+		dojo.disconnect(unloadConnect);
+	});
 };
-dojo.config.debugContainerId="robotconsole";
-dojo.config.debugHeight=dojo.config.debugHeight||200;
-document.write("<div id=\"robotconsole\" style=\"position:absolute;left:0px;bottom:0px;width:100%;\"></div>");
-_1=document.createElement("iframe");
-_1.setAttribute("ALLOWTRANSPARENCY","true");
-_1.scrolling=dojo.isIE?"yes":"auto";
-dojo.style(_1,{visibility:"hidden",border:"0px none",padding:"0px",margin:"0px",position:"absolute",left:"0px",top:"0px",width:"100%",height:"100%"});
-if(_1["attachEvent"]!==undefined){
-_1.attachEvent("onload",_6);
+
+// write the firebug console to a place it will fit
+dojo.config.debugContainerId = "robotconsole";
+dojo.config.debugHeight = dojo.config.debugHeight || 200;
+document.write('<div id="robotconsole" style="position:absolute;left:0px;bottom:0px;width:100%;"></div>');
+
+// write the iframe
+//document.writeln('<iframe id="robotapplication" style="visibility:hidden; border:0px none; padding:0px; margin:0px; position:absolute; left:0px; top:0px; width:100%; height:100%; z-index: 1;" src="'+dojo.config.robotURL+'" onload="iframeLoad();" ></iframe>');
+iframe = document.createElement('iframe');
+iframe.setAttribute("ALLOWTRANSPARENCY","true");
+iframe.scrolling = dojo.isIE? "yes" : "auto";
+dojo.style(iframe,{visibility:'hidden', border:'0px none', padding:'0px', margin:'0px', position:'absolute', left:'0px', top:'0px', width:'100%', height:'100%'});
+if(iframe['attachEvent'] !== undefined){
+	iframe.attachEvent('onload', iframeLoad);
 }else{
-dojo.connect(_1,"onload",_6);
-}
-dojo.mixin(doh.robot,{_updateDocument:function(){
-dojo.setContext(_1.contentWindow,_1.contentWindow.document);
-var _8=dojo.global;
-if(_8["dojo"]){
-dojo._topics=_8.dojo._topics;
+	dojo.connect(iframe, 'onload', iframeLoad);
 }
-},initRobot:function(_9){
-_1.src=_9;
-dojo.addOnLoad(function(){
-var _a={overflow:dojo.isWebKit?"hidden":"visible",margin:"0px",borderWidth:"0px",height:"100%",width:"100%"};
-dojo.style(document.documentElement,_a);
-dojo.style(document.body,_a);
-document.body.appendChild(_1);
-var _b=document.createElement("base");
-_b.href=_9;
-document.getElementsByTagName("head")[0].appendChild(_b);
+
+dojo.mixin(doh.robot,{
+	_updateDocument: function(){
+		dojo.setContext(iframe.contentWindow, iframe.contentWindow.document);
+		var win = dojo.global;
+		if(win["dojo"]){
+			// allow the tests to subscribe to topics published by the iframe
+			dojo._topics = win.dojo._topics;
+		}
+		 
+	},
+
+	initRobot: function(/*String*/ url){
+		// summary:
+		//		Opens the application at the specified URL for testing, redirecting dojo to point to the application environment instead of the test environment.
+		//
+		// url:
+		//		URL to open. Any of the test's dojo.doc calls (e.g. dojo.byId()), and any dijit.registry calls (e.g. dijit.byId()) will point to elements and widgets inside this application.
+		//
+		iframe.src=url;
+		dojo.addOnLoad(function(){
+			var emptyStyle = {
+				overflow: dojo.isWebKit? 'hidden' : 'visible',
+				margin: '0px',
+				borderWidth: '0px',
+				height: '100%',
+				width: '100%'
+			};
+			dojo.style(document.documentElement, emptyStyle);
+			dojo.style(document.body, emptyStyle);
+			document.body.appendChild(iframe);
+			var base=document.createElement('base');
+			base.href=url;
+			document.getElementsByTagName("head")[0].appendChild(base);
+		});
+	},
+
+	waitForPageToLoad: function(/*Function*/ submitActions){
+		// summary:
+		// 		Notifies DOH that the doh.robot is about to make a page change in the application it is driving,
+		//		returning a doh.Deferred object the user should return in their runTest function as part of a DOH test.
+		//
+		// description:
+		// 		Notifies DOH that the doh.robot is about to make a page change in the application it is driving,
+		//		returning a doh.Deferred object the user should return in their runTest function as part of a DOH test.
+		//		Example:
+		//			runTest:function(){
+		//				return waitForPageLoad(function(){ doh.robot.keyPress(dojo.keys.ENTER, 500); });
+		//			}
+		//
+		// submitActions:
+		//		The doh.robot will execute the actions the test passes into the submitActions argument (like clicking the submit button),
+		//		expecting these actions to create a page change (like a form submit).
+		//		After these actions execute and the resulting page loads, the next test will start.
+		//
+
+		var d = new doh.Deferred();
+		// create iframe event handler to track submit progress
+		onIframeLoad = function(){
+			onIframeLoad = null;
+			// set dojo.doc on every page change to point to the iframe doc so the robot works
+			doh.robot._updateDocument();
+			d.callback(true);
+		};
+		submitActions();
+		return d;
+	}
+
 });
-},waitForPageToLoad:function(_c){
-var d=new doh.Deferred();
-_3=function(){
-_3=null;
-doh.robot._updateDocument();
-d.callback(true);
-};
-_c();
-return d;
-}});
+
 })();
-}
diff --git a/dojo/rpc/JsonService.js b/dojo/rpc/JsonService.js
index 989c931..fc2f5b6 100644
--- a/dojo/rpc/JsonService.js
+++ b/dojo/rpc/JsonService.js
@@ -1,37 +1,79 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.rpc.JsonService"]){
-dojo._hasResource["dojo.rpc.JsonService"]=true;
 dojo.provide("dojo.rpc.JsonService");
 dojo.require("dojo.rpc.RpcService");
-dojo.declare("dojo.rpc.JsonService",dojo.rpc.RpcService,{bustCache:false,contentType:"application/json-rpc",lastSubmissionId:0,callRemote:function(_1,_2){
-var _3=new dojo.Deferred();
-this.bind(_1,_2,_3);
-return _3;
-},bind:function(_4,_5,_6,_7){
-var _8=dojo.rawXhrPost({url:_7||this.serviceUrl,postData:this.createRequest(_4,_5),contentType:this.contentType,timeout:this.timeout,handleAs:"json-comment-optional"});
-_8.addCallbacks(this.resultCallback(_6),this.errorCallback(_6));
-},createRequest:function(_9,_a){
-var _b={"params":_a,"method":_9,"id":++this.lastSubmissionId};
-var _c=dojo.toJson(_b);
-return _c;
-},parseResults:function(_d){
-if(dojo.isObject(_d)){
-if("result" in _d){
-return _d.result;
-}
-if("Result" in _d){
-return _d.Result;
-}
-if("ResultSet" in _d){
-return _d.ResultSet;
-}
-}
-return _d;
-}});
-}
+
+dojo.declare("dojo.rpc.JsonService", dojo.rpc.RpcService, {
+		bustCache: false,
+		contentType: "application/json-rpc",
+		lastSubmissionId: 0,
+
+		callRemote: function(method, params){
+			// summary:
+			// 		call an arbitrary remote method without requiring it to be
+			// 		predefined with SMD
+			//	method: string
+			//		the name of the remote method you want to call.
+			//	params: array
+			//		array of parameters to pass to method
+
+			var deferred = new dojo.Deferred();
+			this.bind(method, params, deferred);
+			return deferred;
+		},
+
+		bind: function(method, parameters, deferredRequestHandler, url){
+			//summary:
+			//		JSON-RPC bind method. Takes remote method, parameters,
+			//		deferred, and a url, calls createRequest to make a JSON-RPC
+			//		envelope and passes that off with bind.
+			//	method: string
+			//		The name of the method we are calling
+			//	parameters: array
+			//		The parameters we are passing off to the method
+			//	deferredRequestHandler: deferred
+			//		The Deferred object for this particular request
+
+			var def = dojo.rawXhrPost({
+				url: url||this.serviceUrl,
+				postData: this.createRequest(method, parameters),
+				contentType: this.contentType,
+				timeout: this.timeout, 
+				handleAs: "json-comment-optional"
+			});
+			def.addCallbacks(this.resultCallback(deferredRequestHandler), this.errorCallback(deferredRequestHandler));
+		},
+
+		createRequest: function(method, params){
+			// summary:
+			//	create a JSON-RPC envelope for the request
+			//	method: string
+			//		The name of the method we are creating the requst for
+			//	params: array
+			//		The array of parameters for this request;
+			
+			var req = { "params": params, "method": method, "id": ++this.lastSubmissionId };
+			var data = dojo.toJson(req);
+			return data;
+		},
+
+		parseResults: function(/*anything*/obj){
+			//summary:
+			//		parse the result envelope and pass the results back to
+			//		the callback function
+			//	obj: Object
+			//		Object containing envelope of data we recieve from the server
+
+			if(dojo.isObject(obj)){
+				if("result" in obj){
+					return obj.result;
+				}
+				if("Result" in obj){
+					return obj.Result;
+				}
+				if("ResultSet" in obj){
+					return obj.ResultSet;
+				}
+			}
+			return obj;
+		}
+	}
+);
diff --git a/dojo/rpc/JsonpService.js b/dojo/rpc/JsonpService.js
index 1704364..8adcd38 100644
--- a/dojo/rpc/JsonpService.js
+++ b/dojo/rpc/JsonpService.js
@@ -1,32 +1,61 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.rpc.JsonpService"]){
-dojo._hasResource["dojo.rpc.JsonpService"]=true;
 dojo.provide("dojo.rpc.JsonpService");
 dojo.require("dojo.rpc.RpcService");
 dojo.require("dojo.io.script");
-dojo.declare("dojo.rpc.JsonpService",dojo.rpc.RpcService,{constructor:function(_1,_2){
-if(this.required){
-if(_2){
-dojo.mixin(this.required,_2);
-}
-dojo.forEach(this.required,function(_3){
-if(_3==""||_3==undefined){
-throw new Error("Required Service Argument not found: "+_3);
-}
+
+dojo.declare("dojo.rpc.JsonpService", dojo.rpc.RpcService, {
+	// summary:
+	//	Generic JSONP service.  Minimally extends RpcService to allow 
+	//	easy definition of nearly any JSONP style service. Example
+	//	SMD files exist in dojox.data
+
+	constructor: function(args, requiredArgs){
+		if(this.required) {
+			if(requiredArgs){
+				dojo.mixin(this.required, requiredArgs);
+			}
+
+			dojo.forEach(this.required, function(req){
+				if(req=="" || req==undefined){
+					throw new Error("Required Service Argument not found: "+req); 
+				}
+			});
+		}		
+	},
+
+	strictArgChecks: false,
+
+	bind: function(method, parameters, deferredRequestHandler, url){
+		//summary:
+		//              JSONP bind method. Takes remote method, parameters,
+		//              deferred, and a url, calls createRequest to make a JSON-RPC
+		//              envelope and passes that off with bind.
+		//      method: string
+		//              The name of the method we are calling
+		//      parameters: array
+		//              The parameters we are passing off to the method
+		//      deferredRequestHandler: deferred
+		//              The Deferred object for this particular request
+
+		var def = dojo.io.script.get({
+			url: url||this.serviceUrl,
+			callbackParamName: this.callbackParamName||"callback",
+			content: this.createRequest(parameters),
+			timeout: this.timeout,
+			handleAs: "json",	
+			preventCache: true
+		});
+		def.addCallbacks(this.resultCallback(deferredRequestHandler), this.errorCallback(deferredRequestHandler));
+	},
+
+	createRequest: function(parameters){
+		// summary:
+		//      create a JSONP req
+		//      params: array
+		//              The array of parameters for this request;
+
+		var params = (dojo.isArrayLike(parameters) && parameters.length==1) ?
+				parameters[0] : {};
+		dojo.mixin(params,this.required);
+		return params;
+	}
 });
-}
-},strictArgChecks:false,bind:function(_4,_5,_6,_7){
-var _8=dojo.io.script.get({url:_7||this.serviceUrl,callbackParamName:this.callbackParamName||"callback",content:this.createRequest(_5),timeout:this.timeout,handleAs:"json",preventCache:true});
-_8.addCallbacks(this.resultCallback(_6),this.errorCallback(_6));
-},createRequest:function(_9){
-var _a=(dojo.isArrayLike(_9)&&_9.length==1)?_9[0]:{};
-dojo.mixin(_a,this.required);
-return _a;
-}});
-}
diff --git a/dojo/rpc/RpcService.js b/dojo/rpc/RpcService.js
index f7f546a..4bd2995 100644
--- a/dojo/rpc/RpcService.js
+++ b/dojo/rpc/RpcService.js
@@ -1,89 +1,168 @@
-/*
-	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
-*/
+dojo.provide("dojo.rpc.RpcService");
 
+dojo.declare("dojo.rpc.RpcService", null, {
+	constructor: function(args){
+		//summary:
+		//Take a string as a url to retrieve an smd or an object that is an smd or partial smd to use
+		//as a definition for the service
+		//
+		//	args: object
+		//		Takes a number of properties as kwArgs for defining the service.  It also
+		//		accepts a string.  When passed a string, it is treated as a url from
+		//		which it should synchronously retrieve an smd file.  Otherwise it is a kwArgs
+		//		object.  It accepts serviceUrl, to manually define a url for the rpc service
+		//		allowing the rpc system to be used without an smd definition. strictArgChecks
+		//		forces the system to verify that the # of arguments provided in a call
+		//		matches those defined in the smd.  smdString allows a developer to pass
+		//		a jsonString directly, which will be converted into an object or alternatively
+		//		smdObject is accepts an smdObject directly.
+		//				
+		if(args){
+			//if the arg is a string, we assume it is a url to retrieve an smd definition from
+			if( (dojo.isString(args)) || (args instanceof dojo._Url)){
+				if (args instanceof dojo._Url){
+					var url = args + "";
+				}else{
+					url = args;
+				}
+				var def = dojo.xhrGet({
+					url: url,
+					handleAs: "json-comment-optional",
+					sync: true
+				});
+				
+				def.addCallback(this, "processSmd");
+				def.addErrback(function() {
+					throw new Error("Unable to load SMD from " + args);
+				});
 
-if(!dojo._hasResource["dojo.rpc.RpcService"]){
-dojo._hasResource["dojo.rpc.RpcService"]=true;
-dojo.provide("dojo.rpc.RpcService");
-dojo.declare("dojo.rpc.RpcService",null,{constructor:function(_1){
-if(_1){
-if((dojo.isString(_1))||(_1 instanceof dojo._Url)){
-if(_1 instanceof dojo._Url){
-var _2=_1+"";
-}else{
-_2=_1;
-}
-var _3=dojo.xhrGet({url:_2,handleAs:"json-comment-optional",sync:true});
-_3.addCallback(this,"processSmd");
-_3.addErrback(function(){
-throw new Error("Unable to load SMD from "+_1);
-});
-}else{
-if(_1.smdStr){
-this.processSmd(dojo.eval("("+_1.smdStr+")"));
-}else{
-if(_1.serviceUrl){
-this.serviceUrl=_1.serviceUrl;
-}
-this.timeout=_1.timeout||3000;
-if("strictArgChecks" in _1){
-this.strictArgChecks=_1.strictArgChecks;
-}
-this.processSmd(_1);
-}
-}
-}
-},strictArgChecks:true,serviceUrl:"",parseResults:function(_4){
-return _4;
-},errorCallback:function(_5){
-return function(_6){
-_5.errback(_6.message);
-};
-},resultCallback:function(_7){
-var tf=dojo.hitch(this,function(_8){
-if(_8.error!=null){
-var _9;
-if(typeof _8.error=="object"){
-_9=new Error(_8.error.message);
-_9.code=_8.error.code;
-_9.error=_8.error.error;
-}else{
-_9=new Error(_8.error);
-}
-_9.id=_8.id;
-_9.errorObject=_8;
-_7.errback(_9);
-}else{
-_7.callback(this.parseResults(_8));
-}
-});
-return tf;
-},generateMethod:function(_a,_b,_c){
-return dojo.hitch(this,function(){
-var _d=new dojo.Deferred();
-if((this.strictArgChecks)&&(_b!=null)&&(arguments.length!=_b.length)){
-throw new Error("Invalid number of parameters for remote method.");
-}else{
-this.bind(_a,dojo._toArray(arguments),_d,_c);
-}
-return _d;
+			}else if(args.smdStr){
+				this.processSmd(dojo.eval("("+args.smdStr+")"));
+			}else{
+				// otherwise we assume it's an arguments object with the following
+				// (optional) properties:
+				//      - serviceUrl
+				//      - strictArgChecks
+				//      - smdStr
+				//      - smdObj
+
+				if(args.serviceUrl){
+					this.serviceUrl = args.serviceUrl;
+				}
+
+				this.timeout = args.timeout || 3000;
+
+				if("strictArgChecks" in args){
+					this.strictArgChecks = args.strictArgChecks;
+				}
+
+				this.processSmd(args);
+			}
+		}
+	},
+
+	strictArgChecks: true,
+	serviceUrl: "",
+
+	parseResults: function(obj){
+		// summary
+		// 		parse the results coming back from an rpc request.  this
+		// 		base implementation, just returns the full object
+		// 		subclasses should parse and only return the actual results
+		//	obj: Object
+		//		Object that is the return results from an rpc request
+		return obj;
+	},
+
+	errorCallback: function(/* dojo.Deferred */ deferredRequestHandler){
+		// summary:
+		//		create callback that calls the Deferres errback method
+		//	deferredRequestHandler: Deferred
+		//		The deferred object handling a request.
+		return function(data){
+			deferredRequestHandler.errback(data.message);
+		};
+	},
+
+	resultCallback: function(/* dojo.Deferred */ deferredRequestHandler){
+		// summary:
+		// 		create callback that calls the Deferred's callback method
+		//	deferredRequestHandler: Deferred
+		//		The deferred object handling a request.
+
+		var tf = dojo.hitch(this, 
+			function(obj){
+				if(obj.error!=null){
+					var err;
+					if(typeof obj.error == 'object'){
+						err = new Error(obj.error.message);
+						err.code = obj.error.code;
+						err.error = obj.error.error;
+					}else{
+						err = new Error(obj.error);
+					}
+					err.id = obj.id;
+					err.errorObject = obj;
+					deferredRequestHandler.errback(err);
+				}else{
+					deferredRequestHandler.callback(this.parseResults(obj)); 
+				}
+			}
+		);
+		return tf;
+	},
+
+	generateMethod: function(/*string*/ method, /*array*/ parameters, /*string*/ url){
+		// summary:
+		// 		generate the local bind methods for the remote object
+		//	method: string
+		//		The name of the method we are generating
+		//	parameters: array
+		//		the array of parameters for this call.
+		//	url: string
+		//		the service url for this call
+
+		return dojo.hitch(this, function(){
+			var deferredRequestHandler = new dojo.Deferred();
+
+			// if params weren't specified, then we can assume it's varargs
+			if( (this.strictArgChecks) &&
+				(parameters != null) &&
+				(arguments.length != parameters.length)
+			){
+				// put error stuff here, no enough params
+				throw new Error("Invalid number of parameters for remote method.");
+			}else{
+				this.bind(method, dojo._toArray(arguments), deferredRequestHandler, url);
+			}
+
+			return deferredRequestHandler;
+		});
+	},
+
+	processSmd: function(object){
+		// summary:
+		// 		callback method for reciept of a smd object.  Parse the smd
+		// 		and generate functions based on the description
+		//	object:
+		//		smd object defining this service.
+
+		if(object.methods){
+			dojo.forEach(object.methods, function(m){
+				if(m && m.name){
+					this[m.name] = this.generateMethod(	m.name,
+										m.parameters, 
+										m.url||m.serviceUrl||m.serviceURL);
+					if(!dojo.isFunction(this[m.name])){
+						throw new Error("RpcService: Failed to create" + m.name + "()");
+						/*console.log("RpcService: Failed to create", m.name, "()");*/
+					}
+				}
+			}, this);
+		}
+
+		this.serviceUrl = object.serviceUrl||object.serviceURL;
+		this.required = object.required;
+		this.smd = object;
+	}
 });
-},processSmd:function(_e){
-if(_e.methods){
-dojo.forEach(_e.methods,function(m){
-if(m&&m.name){
-this[m.name]=this.generateMethod(m.name,m.parameters,m.url||m.serviceUrl||m.serviceURL);
-if(!dojo.isFunction(this[m.name])){
-throw new Error("RpcService: Failed to create"+m.name+"()");
-}
-}
-},this);
-}
-this.serviceUrl=_e.serviceUrl||_e.serviceURL;
-this.required=_e.required;
-this.smd=_e;
-}});
-}
diff --git a/dojo/string.js b/dojo/string.js
index 4ff946d..331433e 100644
--- a/dojo/string.js
+++ b/dojo/string.js
@@ -1,57 +1,153 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojo.string"]){
-dojo._hasResource["dojo.string"]=true;
 dojo.provide("dojo.string");
-dojo.string.rep=function(_1,_2){
-if(_2<=0||!_1){
-return "";
-}
-var _3=[];
-for(;;){
-if(_2&1){
-_3.push(_1);
-}
-if(!(_2>>=1)){
-break;
-}
-_1+=_1;
-}
-return _3.join("");
-};
-dojo.string.pad=function(_4,_5,ch,_6){
-if(!ch){
-ch="0";
-}
-var _7=String(_4),_8=dojo.string.rep(ch,Math.ceil((_5-_7.length)/ch.length));
-return _6?_7+_8:_8+_7;
+
+/*=====
+dojo.string = { 
+	// summary: String utilities for Dojo
 };
-dojo.string.substitute=function(_9,_a,_b,_c){
-_c=_c||dojo.global;
-_b=_b?dojo.hitch(_c,_b):function(v){
-return v;
+=====*/
+
+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
 };
-return _9.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g,function(_d,_e,_f){
-var _10=dojo.getObject(_e,false,_a);
-if(_f){
-_10=dojo.getObject(_f,false,_c).call(_c,_10,_e);
-}
-return _b(_10,_e).toString();
-});
+
+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.trim=String.prototype.trim?dojo.trim: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;
+
+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. mylib.encodeXML
+	//	thisObject: 
+	//		where to look for optional format function; default to the global
+	//		namespace
+	//	example:
+	//		Substitutes two expressions in a string from an Array or Object
+	//	|	// returns "File 'foo.html' is not found in directory '/temp'."
+	//	|	// by providing substitution data in an Array
+	//	|	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'."
+	//	|	// but provides substitution data in an Object structure.  Dotted
+	//	|	// notation may be used to traverse the structure.
+	//	|	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 ? 
+		dojo.hitch(thisObject, transform) : function(v){ return v; };
+
+	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;
+	};
diff --git a/dojo/tests.js b/dojo/tests.js
new file mode 100644
index 0000000..04d192a
--- /dev/null
+++ b/dojo/tests.js
@@ -0,0 +1,12 @@
+//This file is the command-line entry point for running the tests in
+//Rhino and Spidermonkey.
+
+/*=====
+dojo.tests = {
+	// summary: D.O.H. Test files for Dojo unit testing.
+};
+=====*/
+
+load("dojo.js");
+load("tests/runner.js");
+tests.run();
diff --git a/dojo/tests/AdapterRegistry.js b/dojo/tests/AdapterRegistry.js
new file mode 100644
index 0000000..c4bbc62
--- /dev/null
+++ b/dojo/tests/AdapterRegistry.js
@@ -0,0 +1,71 @@
+dojo.provide("tests.AdapterRegistry");
+dojo.require("dojo.AdapterRegistry");
+
+doh.register("tests.AdapterRegistry", 
+	[
+		function ctor(t){
+			var taa = new dojo.AdapterRegistry();
+			t.is(0, taa.pairs.length);
+			t.f(taa.returnWrappers);
+
+			var taa = new dojo.AdapterRegistry(true);
+			t.t(taa.returnWrappers);
+		},
+
+		function register(t){
+			var taa = new dojo.AdapterRegistry();
+			taa.register("blah", 
+				function(str){ return str == "blah"; },
+				function(){ return "blah"; }
+			);
+			t.is(1, taa.pairs.length);
+			t.is("blah", taa.pairs[0][0]);
+
+			taa.register("thinger");
+			taa.register("prepend", null, null, true, true);
+			t.is("prepend", taa.pairs[0][0]);
+			t.t(taa.pairs[0][3]);
+		},
+
+		/*
+		function match(t){
+		},
+		*/
+
+		function noMatch(t){
+			var taa = new dojo.AdapterRegistry();
+			var threw = false;
+			try{
+				taa.match("blah");
+			}catch(e){
+				threw = true;
+			}
+			t.t(threw);
+		},
+
+		function returnWrappers(t){
+			var taa = new dojo.AdapterRegistry();
+			taa.register("blah", 
+				function(str){ return str == "blah"; },
+				function(){ return "blah"; }
+			);
+			t.is("blah", taa.match("blah"));
+
+			taa.returnWrappers = true;
+			t.is("blah", taa.match("blah")());
+		},
+
+		function unregister(t){
+			var taa = new dojo.AdapterRegistry();
+			taa.register("blah", 
+				function(str){ return str == "blah"; },
+				function(){ return "blah"; }
+			);
+			taa.register("thinger");
+			taa.register("prepend", null, null, true, true);
+			taa.unregister("prepend");
+			t.is(2, taa.pairs.length);
+			t.is("blah", taa.pairs[0][0]);
+		}
+	]
+);
diff --git a/dojo/tests/DeferredList.js b/dojo/tests/DeferredList.js
new file mode 100644
index 0000000..3bfa829
--- /dev/null
+++ b/dojo/tests/DeferredList.js
@@ -0,0 +1,202 @@
+dojo.provide("tests.DeferredList");
+
+dojo.require("dojo.DeferredList");
+
+doh.register("tests.DeferredList", 
+	[
+		function callback(t){
+			var d1 = new dojo.Deferred();
+			var d2 = new dojo.Deferred();
+			var dl = new dojo.DeferredList([d1, d2]);
+			var fired = false;
+
+			dl.addCallback(function(res){
+				doh.debug("debug from dojo.DeferredList callback");
+				return res;
+			});
+			dl.addCallback(function(res){
+				console.log("res: ", res, res.length);
+				t.assertTrue(res.length == 2);
+				t.assertTrue(res[0][0]);
+				t.assertEqual(res[0][1], "foo");
+				t.assertTrue(res[1][0]);
+				t.assertEqual(res[1][1], "bar");
+				fired = true;
+				return res;
+			});
+			d1.callback("foo");
+			d2.callback("bar");
+			t.assertTrue(fired);
+		},
+
+		function errback(t){
+			var d1 = new dojo.Deferred();
+			var d2 = new dojo.Deferred();
+			var dl = new dojo.DeferredList([d1, d2]);
+			var fired = false;
+			var e1 = new Error("foo");
+			var e2 = new Error("bar");
+
+			dl.addCallback(function(res){
+				doh.debug("debug from dojo.DeferredList callback");
+				return res;
+			});
+			dl.addCallback(function(res){
+				t.assertTrue(res.length == 2);
+				t.assertTrue(!res[0][0]);
+
+				t.assertEqual(res[0][1], e1);
+				t.assertTrue(!res[1][0]);
+				t.assertEqual(res[1][1], e2);
+				fired = true;
+				return res;
+			});
+			d1.errback(e1);
+			d2.errback(e2);
+			t.assertTrue(fired);
+		},
+
+
+		function mixed(t){
+			var d1 = new dojo.Deferred();
+			var d2 = new dojo.Deferred();
+            var dl = new dojo.DeferredList([d1, d2]);
+            var fired = false;
+            var e = new Error("foo");
+
+			dl.addCallback(function(res){
+				doh.debug("debug from dojo.DeferredList callback");
+				return res;
+			});
+			dl.addCallback(function(res){
+                t.assertTrue(res.length == 2);
+                t.assertTrue(!res[0][0]);
+
+                t.assertEqual(res[0][1], e);
+                t.assertTrue(res[1][0]);
+                t.assertEqual(res[1][1], "bar");
+                fired = true;
+				return res;
+			});
+			d1.errback(e);
+			d2.callback("bar");
+            t.assertTrue(fired);
+		}, 
+
+        function gather(t){
+			var d1 = new dojo.Deferred();
+			var d2 = new dojo.Deferred();
+            var dl = dojo.DeferredList.prototype.gatherResults([d1, d2]);
+            var fired = false;
+			dl.addCallback(function(res){
+                t.assertEqual(res[0], "foo");
+                t.assertEqual(res[1], "bar");
+                fired = true;
+				return res;
+			});
+			d1.callback("foo");
+			d2.callback("bar");
+            t.assertTrue(fired);
+        }
+	]
+);
+dojo.provide("tests.DeferredList");
+
+dojo.require("dojo.DeferredList");
+
+doh.register("tests.DeferredList", 
+	[
+		function callback(t){
+			var d1 = new dojo.Deferred();
+			var d2 = new dojo.Deferred();
+            var dl = new dojo.DeferredList([d1, d2]);
+            var fired = false;
+			dl.addCallback(function(res){
+				doh.debug("debug from dojo.DeferredList callback");
+				return res;
+			});
+			dl.addCallback(function(res){
+                t.assertTrue(res.length == 2);
+                t.assertTrue(res[0][0]);
+                t.assertEqual(res[0][1], "foo");
+                t.assertTrue(res[1][0]);
+                t.assertEqual(res[1][1], "bar");
+                fired = true;
+				return res;
+			});
+			d1.callback("foo");
+			d2.callback("bar");
+            t.assertTrue(fired);
+		},
+
+		function errback(t){
+			var d1 = new dojo.Deferred();
+			var d2 = new dojo.Deferred();
+            var dl = new dojo.DeferredList([d1, d2]);
+            var fired = false;
+            var e1 = new Error("foo");
+            var e2 = new Error("bar");
+
+			dl.addCallback(function(res){
+				doh.debug("debug from dojo.DeferredList callback");
+				return res;
+			});
+			dl.addCallback(function(res){
+                t.assertTrue(res.length == 2);
+                t.assertTrue(!res[0][0]);
+
+                t.assertEqual(res[0][1], e1);
+                t.assertTrue(!res[1][0]);
+                t.assertEqual(res[1][1], e2);
+                fired = true;
+				return res;
+			});
+			d1.errback(e1);
+			d2.errback(e2);
+            t.assertTrue(fired);
+		},
+
+
+		function mixed(t){
+			var d1 = new dojo.Deferred();
+			var d2 = new dojo.Deferred();
+            var dl = new dojo.DeferredList([d1, d2]);
+            var fired = false;
+            var e = new Error("foo");
+
+			dl.addCallback(function(res){
+				doh.debug("debug from dojo.DeferredList callback");
+				return res;
+			});
+			dl.addCallback(function(res){
+                t.assertTrue(res.length == 2);
+                t.assertTrue(!res[0][0]);
+
+                t.assertEqual(res[0][1], e);
+                t.assertTrue(res[1][0]);
+                t.assertEqual(res[1][1], "bar");
+                fired = true;
+				return res;
+			});
+			d1.errback(e);
+			d2.callback("bar");
+            t.assertTrue(fired);
+		}, 
+
+        function gather(t){
+			var d1 = new dojo.Deferred();
+			var d2 = new dojo.Deferred();
+            var dl = dojo.DeferredList.prototype.gatherResults([d1, d2]);
+            var fired = false;
+			dl.addCallback(function(res){
+                t.assertEqual(res[0], "foo");
+                t.assertEqual(res[1], "bar");
+                fired = true;
+				return res;
+			});
+			d1.callback("foo");
+			d2.callback("bar");
+            t.assertTrue(fired);
+        }
+	]
+);
diff --git a/dojo/tests/NodeList-fx.html b/dojo/tests/NodeList-fx.html
new file mode 100644
index 0000000..4b8d279
--- /dev/null
+++ b/dojo/tests/NodeList-fx.html
@@ -0,0 +1,170 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Testing dojo.fx extensions to dojo.NodeList</title>
+		<style type="text/css">
+			@import "../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../dojo.js" djConfig="isDebug: true, popup: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.require("dojo.NodeList-fx");
+
+			dojo.addOnLoad(function(){
+				doh.register("NodeList-fx", 
+					[
+						function fadeOut(){
+							dojo.query("p").style("opacity", 1);
+							var anim = dojo.query("p").fadeOut();
+							var d = new doh.Deferred();
+							dojo.connect(anim, "onEnd", d.getTestCallback(function(){
+								dojo.query("p").forEach(function(item){ 
+									doh.is(0, dojo.style(item, "opacity"), "opacity for " + item);
+								});
+							}));
+							anim.play();
+							return d;
+						},
+						function fadeIn(){
+							dojo.query("p").style("opacity", 0);
+							var anim = dojo.query("p").fadeIn();
+							var d = new doh.Deferred();
+							dojo.connect(anim, "onEnd", d.getTestCallback(function(){
+								dojo.query("p").forEach(function(item){ 
+									doh.is(1, dojo.style(item, "opacity"), "opacity for " + item);
+								});
+							}));
+							anim.play();
+							return d;
+						},
+						function wipeOut(){
+							dojo.query("p").style("height", "");
+							var anim = dojo.query("p").wipeOut();
+							var d = new doh.Deferred();
+							dojo.connect(anim, "onEnd", d.getTestCallback(function(){
+								dojo.query("p").forEach(function(item){ 
+									doh.is(0, dojo.style(item, "height"), "height for " + item);
+								});
+							}));
+							anim.play();
+							return d;
+						},
+						function wipeIn(){
+							dojo.query("p").style("height", 0);
+							var anim = dojo.query("p").wipeIn();
+							var d = new doh.Deferred();
+							dojo.connect(anim, "onEnd", d.getTestCallback(function(){
+								dojo.query("p").forEach(function(item){ 
+									// FIXME: need a more robust test for "have wiped all the way in"
+									doh.isNot(0, dojo.style(item, "height"), "height for " + item);
+								});
+							}));
+							anim.play();
+							return d;
+						},
+						function slideTo(){
+							var anim = dojo.query("p").slideTo({
+								left: 500
+							});
+							var d = new doh.Deferred();
+							dojo.connect(anim, "onEnd", d.getTestCallback(function(){
+								dojo.query("p").forEach(function(item){ 
+									// FIXME: need a more robust test for "have wiped all the way in"
+									doh.is(500, dojo.style(item, "left"), "left for " + item);
+								});
+							}));
+							anim.play();
+							return d;
+						},
+						function anim(){
+							dojo.query("p").style("position", "");
+							dojo.query("p").style("left", "");
+							var anim = dojo.query("p").anim({
+								width: 500
+							});
+							console.debug(anim);
+							var d = new doh.Deferred();
+							dojo.connect(anim, "onEnd", d.getTestCallback(function(){
+								/*
+								dojo.query("p").forEach(function(item){ 
+									// FIXME: need a more robust test for "have wiped all the way in"
+									doh.is(500, dojo.style(item, "width"), "width for" + item);
+								}));
+								*/
+							}));
+							return d;
+						},
+						
+						function auto(){
+							
+							var d = new doh.Deferred(), x = 0;
+							var nl = dojo.query("p")
+								.fadeOut({ 
+									auto:true,
+									onEnd:function(){
+										if(!x){
+											// onend fires foreach in the list. only dfd once.
+											x++; d.callback(true);
+										}
+									}
+								})
+								// past here we're expecting a NodeList back, not an Animation
+								.at(0)
+								.forEach(d.getTestErrback(function(n){
+									// TODO: this test is meaningless
+									doh.t(true); // it worked.
+								}))
+							;
+							
+							doh.t(nl.length, "dojo.query() found some nodes"); // ensure we actually will do _something_ 
+							
+							return d;
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body>
+		<p>
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper
+		sagittis velit. Cras in mi. Duis porta mauris ut ligula.  Proin porta
+		rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+		Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+		Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+		risus.
+		</p>
+		<p>
+		Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+		imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+		nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+		massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+		pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+		quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+		felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+		quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+		rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+		semper velit ante id metus. Praesent massa dolor, porttitor sed,
+		pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+		tortor pharetra congue.	 Suspendisse pulvinar.
+		</p>
+		<p>
+		Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+		imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+		nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+		massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+		pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+		quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+		felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+		quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+		rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+		semper velit ante id metus. Praesent massa dolor, porttitor sed,
+		pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+		tortor pharetra congue.	 Suspendisse pulvinar.
+		</p>
+	</body>
+</html>
+
diff --git a/dojo/tests/NodeList-manipulate.html b/dojo/tests/NodeList-manipulate.html
new file mode 100644
index 0000000..81a3dd9
--- /dev/null
+++ b/dojo/tests/NodeList-manipulate.html
@@ -0,0 +1,380 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html id="html">
+	<head>
+		<title>Testing dojo.NodeList-manipulate extensions to dojo.NodeList</title>
+		<style type="text/css">
+			@import "../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../dojo.js"></script>
+		<script type="text/javascript" 
+			src="../NodeList-manipulate.js"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.require("dojo.NodeList-manipulate");
+
+			function verify(/*dojo.NodeList*/nl, /*Array*/ids){
+				for(var i = 0, node; node = nl[i]; i++){
+					doh.is(ids[i], node.id);
+				}
+				//Make sure lengths are equal.
+				doh.is(ids.length, i);
+			}
+
+			dojo.addOnLoad(function(){
+				var divs = dojo.query("div.testDiv");
+
+				doh.register("t", 
+					[
+						function innerHTML(t){
+							divs.innerHTML("<ul><li>Test</li></ul>");
+							dojo.forEach(divs, function(node){
+								doh.is(1, node.childNodes.length);
+								doh.is("ul", node.childNodes[0].nodeName.toLowerCase());
+							});
+
+							doh.is("<ul><li>test</li></ul>", divs.innerHTML().toLowerCase().replace(/[\r\n]/g, ""));
+						},
+
+
+						function html(t){
+							divs.html("<ul><li>Test</li></ul>");
+							dojo.forEach(divs, function(node){
+								doh.is(1, node.childNodes.length);
+								doh.is("ul", node.childNodes[0].nodeName.toLowerCase());
+							});
+
+							doh.is("<ul><li>test</li></ul>", divs.html().toLowerCase().replace(/[\r\n]/g, ""));
+						},
+
+						function text(t){
+							doh.is("TestTestTest", divs.text());
+
+							divs.text("Hello World");
+
+							dojo.forEach(divs, function(node){
+								doh.is(1, node.childNodes.length);
+								doh.is("Hello World", node.childNodes[0].nodeValue);
+							});
+
+							doh.is("Hello WorldHello WorldHello World", divs.text());
+						},
+
+						function val(t){
+							//Input text test.
+							dojo.query('[type="text"]').val("Hello");
+							doh.is("Hello", dojo.byId("inputText").value);
+							
+							//Textarea test.
+							dojo.query('textarea', "inputForm").val("World");
+							doh.is("World", dojo.byId("inputTextArea").value);
+
+							//Radio button test
+							dojo.query('[type="radio"]').val("radio2");
+							doh.f(dojo.byId("inputRadio1").checked);
+							doh.t(dojo.byId("inputRadio2").checked);
+							
+							//Checkbox test
+							dojo.query('[type="checkbox"]').val("checkbox2");
+							doh.f(dojo.byId("inputCheckBox1").checked);
+							doh.t(dojo.byId("inputCheckBox2").checked);
+							
+							var selects = dojo.query('select', 'inputForm');
+
+							//Single select test.
+							selects.at(0).val("two");
+							doh.is(1, dojo.byId("inputSelect1").selectedIndex);
+							dojo.query("option", "inputSelect1").forEach(function(node){
+								if(node.value == "two"){
+									doh.t(node.selected);
+								}else{
+									doh.f(node.selected);
+								}
+							});
+							
+							//Multiple select test.
+							selects.at(1).val(["four", "six"]);
+							dojo.query("option", "inputSelect2").forEach(function(node){
+								if(node.value == "four" || node.value == "six"){
+									doh.t(node.selected);
+								}else{
+									doh.f(node.selected);
+								}
+							});
+							
+						},
+
+						function append(t){
+							//Test string content
+							divs.append('<span class="foo">foo</span><span class="bar">bar</span>')
+								.forEach(function(node){
+									doh.is(3, node.childNodes.length);
+									doh.is("foo", node.childNodes[1].className);
+									doh.is("bar", node.childNodes[2].className);
+									
+								}
+							);
+							
+							//Test DOMNode content
+							divs.append(dojo.query("h1")[0]).forEach(function(node){
+								doh.is(4, node.childNodes.length);
+								doh.is("h1", node.childNodes[3].nodeName.toLowerCase());
+							});
+
+							var h1s = dojo.query("h1");
+							doh.is(3, h1s.length);
+
+							//Move all the h1s to one div to test NodeList content.
+							dojo.query("#t, #yeah").append(document.getElementsByTagName("h1")).forEach(function(node){
+								doh.is(6, node.childNodes.length);
+								doh.is("h1", node.childNodes[3].nodeName.toLowerCase());
+								doh.is("h1", node.childNodes[4].nodeName.toLowerCase());
+								doh.is("h1", node.childNodes[5].nodeName.toLowerCase());
+							});
+
+							//clean up
+							dojo.query("h1").remove();
+						},
+
+						function appendTo(t){
+							//Create some new things.
+							dojo.query("body").append('<p class="singer">bo</p><p class="singer">diddly</p>');
+
+							var ret = dojo.query(".foo").appendTo(".singer");
+							doh.is(6, ret.length);
+
+							dojo.query(".singer").forEach(function(node){
+								doh.is(4, node.childNodes.length);
+								doh.is("foo", node.childNodes[1].className);
+								doh.is("foo", node.childNodes[2].className);
+								doh.is("foo", node.childNodes[3].className);
+							});
+							
+							dojo.query("body").append('<p class="bands"></p><p class="drummer">john</p><p class="drummer">bonham</p>');
+							var bands = dojo.query(".bands");
+							dojo.query(".drummer").appendTo(bands);
+							bands.forEach(function(node){
+								doh.is(2, node.childNodes.length);
+								doh.is("drummer", node.childNodes[0].className);
+								doh.is("drummer", node.childNodes[1].className);
+								
+							});
+							
+							dojo.query("body").append('<p class="guitarist">jimmy</p><p class="guitarist">page</p>');
+							dojo.query(".guitarist").appendTo(bands[0]);
+							bands.forEach(function(node){
+								doh.is(4, node.childNodes.length);
+								doh.is("guitarist", node.childNodes[2].className);
+								doh.is("guitarist", node.childNodes[3].className);								
+							});
+
+							//Get rid of bands
+							bands.remove();
+						},
+
+						function prepend(t){
+							dojo.query(".singer").prepend('<span class="fry">layla</span>')
+								.forEach(function(node){
+									doh.is(5, node.childNodes.length);
+									doh.is("fry", node.childNodes[0].className);
+								}
+							);
+						},
+
+						function prependTo(t){
+							//Create some new things.
+							dojo.query("body").append('<p class="actor">steve</p><p class="actor">martin</p>');
+
+							var ret = dojo.query(".bar").prependTo(".actor");
+							doh.is(6, ret.length);
+
+							dojo.query(".actor").forEach(function(node){
+								doh.is(4, node.childNodes.length);
+								doh.is("bar", node.childNodes[0].className);
+								doh.is("bar", node.childNodes[1].className);
+								doh.is("bar", node.childNodes[2].className);
+							});
+							
+							//Clean up
+							dojo.query("p").remove();
+						},
+						
+						
+						function after(t){
+							divs.after('<span class="after">after</span>')
+								.forEach(function(node){
+									doh.is("after", node.nextSibling.className);
+								}
+							);
+							
+							dojo.query("form").after(dojo.query(".after")).forEach(function(node){
+								for(var i = 0; i < 3; i++){
+									doh.is("after", node.nextSibling.className);
+									node = node.nextSibling;
+								}
+							});
+						},
+
+						function insertAfter(t){
+							dojo.query("body").prepend('<h1>testing dojo.NodeList-manipulate</h1>');
+							var ret = dojo.query(".after").insertAfter("h1");
+							doh.is(3, ret.length);
+
+							dojo.query("h1").forEach(function(node){
+								for(var i = 0; i < 3; i++){
+									doh.is("after", node.nextSibling.className);
+									node = node.nextSibling;
+								}
+							});
+						},
+
+						function before(t){
+							divs.before('<span class="before">before</span>')
+								.forEach(function(node){
+									doh.is("before", node.previousSibling.className);
+								}
+							);
+							
+							dojo.query("form").before(dojo.query(".before")).forEach(function(node){
+								for(var i = 0; i < 3; i++){
+									doh.is("before", node.previousSibling.className);
+									node = node.previousSibling;
+								}
+							});
+						},
+
+						function insertBefore(t){
+							var ret = dojo.query(".before").insertBefore("h1");
+							doh.is(3, ret.length);
+
+							dojo.query("h1").forEach(function(node){
+								for(var i = 0; i < 3; i++){
+									doh.is("before", node.previousSibling.className);
+									node = node.previousSibling;
+								}
+							});
+						},
+						
+						function remove(t){
+							//Already did some removes, make sure they are not still here.
+							//This is also just an alias for orphan which has its own tests.
+							doh.is(0, dojo.query("p").length);
+						},
+						
+						function wrap(t){
+							dojo.query(".before").wrap("<b><i></i></b>").forEach(function(node){
+								doh.is("i", node.parentNode.nodeName.toLowerCase());
+								doh.is("b", node.parentNode.parentNode.nodeName.toLowerCase());
+							});
+							
+							dojo.query("b").wrap(dojo.query("h1")[0]).forEach(function(node){
+								doh.is("h1", node.parentNode.nodeName.toLowerCase());
+								doh.is(4, dojo.query("h1").length);
+							});
+						},
+						
+						function wrapAll(t){
+							dojo.query("h1").wrapAll('<h4></h4>');
+							var h4s = dojo.query("h4");
+							doh.is(1, h4s.length);
+							
+							var h4 = h4s[0];
+							doh.is(4, h4.childNodes.length);
+							dojo.query("h1").forEach(function(node){
+								doh.is("h4", node.parentNode.nodeName.toLowerCase());					
+							});
+							
+							//Complicated test that test for cloning of the wrap nodes in the right
+							//situation.
+							var div = dojo.create("div", {"class": "myClass"});
+							dojo.query("#inputForm").query("select").wrapAll(div).end().query("input").wrapAll(div);
+							var myClass = dojo.query(".myClass");
+
+							doh.is(2, myClass.length);
+							doh.is(5, dojo.query("input", myClass[0]).length);
+							doh.is(2, dojo.query("select", myClass[1]).length);
+						},
+
+						function wrapInner(t){
+							dojo.query("h4").wrapInner('<h3></h3>');
+							var h3s = dojo.query("h3");
+							doh.is(1, h3s.length);
+							
+							var h3 = h3s[0];
+							doh.is(4, h3.childNodes.length);
+							dojo.query("h1").forEach(function(node){
+								doh.is("h3", node.parentNode.nodeName.toLowerCase());					
+							});
+						},
+						
+						function replaceWith(t){
+							dojo.query("h1").replaceWith('<span class="replace">replace</span><b>hello</b>');
+							
+							dojo.query("h3").forEach(function(node){
+								doh.is(8, node.childNodes.length);
+								doh.is("replace", node.childNodes[0].className);
+								doh.is("b", node.childNodes[1].nodeName.toLowerCase());
+							});
+						},
+
+						function replaceAll(t){
+							dojo.query(".after").replaceAll("h4");
+
+							doh.is(3, dojo.query(".after").length);
+							doh.is(0, dojo.query("h4").length);
+
+							dojo.query("body").append('<i class="italics">italics</i>');
+							doh.is("i", dojo.query(".italics").replaceAll(".after")[0].nodeName.toLowerCase());
+							doh.is(0, dojo.query(".after").length);
+							doh.is(3, dojo.query(".italics").length);
+						},
+						
+						function clone(t){
+							dojo.query(".italics").clone().appendTo("body");
+							doh.is(6, dojo.query(".italics").length);
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body id="body" class="classy">
+		<h1>testing dojo.NodeList-manipulate</h1>
+		<div id="sq100" class="testDiv">
+			100px square, abs
+		</div>
+		<div id="t" class="testDiv">
+			<span id="c1">c1</span>
+		</div>
+		<div id="third" class="third testDiv">
+			<!-- This is the third top level div -->
+			<span id="crass">Crass, baby</span>
+			The third div
+			<span id="classy" class="classy">Classy, baby</span>
+			The third div, again
+			<!-- Another comment -->
+			<span id="yeah">Yeah, baby</span>
+		</div>
+		<form id="inputForm">
+			<input type="text" id="inputText">
+			<textarea id="inputTextArea"></textarea>
+			<input type="radio" name="inputRadio" id="inputRadio1" value="radio1" checked>
+			<input type="radio" name="inputRadio" id="inputRadio2" value="radio2">
+			<input type="checkbox" id="inputCheckBox1" value="checkbox1" checked>
+			<input type="checkbox" id="inputCheckBox2" value="checkbox2">
+			<select id="inputSelect1">
+				<option value="one">One</option>
+				<option value="two">Two</option>
+				<option value="three" selected>Three</option>
+			</select>
+			<select id="inputSelect2" multiple>
+				<option value="four">Four</option>
+				<option value="five" selected>Five</option>
+				<option value="six">Six</option>
+			</select>
+		</form>
+	</body>
+</html>
+
diff --git a/dojo/tests/NodeList-manipulate.js b/dojo/tests/NodeList-manipulate.js
new file mode 100644
index 0000000..d4ba02b
--- /dev/null
+++ b/dojo/tests/NodeList-manipulate.js
@@ -0,0 +1,4 @@
+dojo.provide("tests.NodeList-manipulate");
+if(dojo.isBrowser){
+	doh.registerUrl("tests.NodeList-manipulate", dojo.moduleUrl("tests", "NodeList-manipulate.html"));
+}
diff --git a/dojo/tests/NodeList-traverse.html b/dojo/tests/NodeList-traverse.html
new file mode 100644
index 0000000..55b602e
--- /dev/null
+++ b/dojo/tests/NodeList-traverse.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html id="html">
+	<head>
+		<title>Testing dojo.NodeList-traverse extensions to dojo.NodeList</title>
+		<style type="text/css">
+			@import "../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../dojo.js" djConfig="isDebug: true, popup: true"></script>
+		<script type="text/javascript" 
+			src="../NodeList-traverse.js"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.require("dojo.NodeList-traverse");
+
+			function verify(/*dojo.NodeList*/nl, /*Array*/ids){
+				for(var i = 0, node; node = nl[i]; i++){
+					doh.is(ids[i], node.id);
+				}
+				//Make sure lengths are equal.
+				doh.is(ids.length, i);
+			}
+
+			dojo.addOnLoad(function(){
+				var divs = dojo.query("div.testDiv");
+
+				doh.register("t", 
+					[
+						function children(t){
+							verify(divs.last().children(), ["crass", "classy", "yeah"]);
+						},
+
+						function closest(t){
+							var classy = dojo.query("#classy");
+							var closestDiv = classy.closest("div");
+							verify(closestDiv, ["third"]);
+							verify(closestDiv.end().closest(".classy"), ["classy"]);
+						},
+
+						function parent(t){
+							verify(dojo.query("#classy").parent(), ["third"]);
+						},
+
+						function parents(t){
+							var classy = dojo.query("#classy");
+							verify(classy.parents(), ["third", "body", "html"]);
+							verify(classy.parents(".third"), ["third"]);
+							verify(classy.parents("body"), ["body"]);
+						},
+
+						function siblings(t){
+							verify(dojo.query("#classy").siblings(), ["crass", "yeah"]);
+						},
+
+						function next(t){
+							verify(dojo.query("#crass").next(), ["classy"]);
+						},
+
+						function nextAll(t){
+							verify(dojo.query("#crass").nextAll(), ["classy", "yeah"]);
+							verify(dojo.query("#crass").nextAll("#yeah"), ["yeah"]);
+						},
+
+						function prev(t){
+							verify(dojo.query("#classy").prev(), ["crass"]);
+						},
+
+						function prevAll(t){
+							verify(dojo.query("#yeah").prevAll(), ["classy", "crass"]);
+							verify(dojo.query("#yeah").prevAll("#crass"), ["crass"]);
+						},
+
+						function andSelf(t){
+							verify(dojo.query("#yeah").prevAll().andSelf(), ["classy", "crass", "yeah"]);
+						},
+
+						function first(t){
+							verify(divs.first(), ["sq100"]);
+						},
+
+						function last(t){
+							verify(divs.last(), ["third"]);
+						},
+
+						function even(t){
+							var even = divs.even();
+							verify(even, ["t"]);
+							verify(even.end(), ["sq100", "t", "third"]);
+						},
+
+						function odd(t){
+							var odd = divs.odd();
+							verify(odd, ["sq100", "third"]);
+							verify(odd.end(), ["sq100", "t", "third"]);
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body id="body" class="classy">
+		<h1 id="firstH1">testing dojo.NodeList-traverse</h1>
+		<div id="sq100" class="testDiv">
+			100px square, abs
+		</div>
+		<div id="t" class="testDiv">
+			<span id="c1">c1</span>
+		</div>
+		<div id="third" class="third testDiv">
+			<!-- This is the third top level div -->
+			<span id="crass">Crass, baby</span>
+			The third div
+			<span id="classy" class="classy">Classy, baby</span>
+			The third div, again
+			<!-- Another comment -->
+			<span id="yeah">Yeah, baby</span>
+		</div>
+	</body>
+</html>
+
diff --git a/dojo/tests/NodeList-traverse.js b/dojo/tests/NodeList-traverse.js
new file mode 100644
index 0000000..810ce19
--- /dev/null
+++ b/dojo/tests/NodeList-traverse.js
@@ -0,0 +1,4 @@
+dojo.provide("tests.NodeList-traverse");
+if(dojo.isBrowser){
+	doh.registerUrl("tests.NodeList-traverse", dojo.moduleUrl("tests", "NodeList-traverse.html"));
+}
diff --git a/dojo/tests/Stateful.js b/dojo/tests/Stateful.js
new file mode 100644
index 0000000..1b253f8
--- /dev/null
+++ b/dojo/tests/Stateful.js
@@ -0,0 +1,36 @@
+dojo.provide("tests.Stateful");
+
+dojo.require("dojo.Stateful");
+
+doh.register("tests.Stateful", 
+	[
+		function getSetWatch(t){
+			var s = new dojo.Stateful({
+				foo: 3
+			});
+			doh.is(s.get("foo"), 3);
+			var watching = s.watch("foo", function(name, oldValue, value){
+				doh.is(name, "foo");
+				doh.is(oldValue, 3);
+				doh.is(value, 4);
+				doh.is(s.get("foo"), 4);
+			});
+			s.set("foo", 4);
+			doh.is(s.get("foo"), 4);
+			watching.unwatch();
+			s.set("foo", 5);
+			doh.is(s.get("foo"), 5);
+		},
+		function setHash(t){
+			var s = new dojo.Stateful();
+			s.set({
+				foo:3,
+				bar: 5
+			});
+			doh.is(s.get("foo"), 3);
+			doh.is(s.get("bar"), 5);
+		}		
+
+
+	]
+);
diff --git a/dojo/tests/TODO b/dojo/tests/TODO
new file mode 100644
index 0000000..4f66fa8
--- /dev/null
+++ b/dojo/tests/TODO
@@ -0,0 +1,10 @@
+This file lists tests that need to be implemented or expanded. See ticket #3121
+for changes related to things listed here.
+
+Tests to add:
+-------------
+	* add tests for dojo.place()
+
+Tests to improve:
+-----------------
+	* NodeList isn't testing several of its public methods (place, orphan, adopt, etc.)
diff --git a/dojo/tests/_base.js b/dojo/tests/_base.js
new file mode 100644
index 0000000..9de29aa
--- /dev/null
+++ b/dojo/tests/_base.js
@@ -0,0 +1,134 @@
+var testGlobal = this;
+try{
+	dojo.provide("tests._base");
+	testGlobal = dojo.global;
+}catch(e){ }
+
+// the test suite for the bootstrap. Requires hostenv and other base tests at
+// the end
+
+if(doh.selfTest){
+
+	doh.register("doh.smokeTest", 
+		[
+			function sanityCheckHarness(t){
+				// sanity checks
+				t.assertTrue(true);
+				t.assertFalse(false);
+				t.assertFalse(0);
+				t.assertFalse(null);
+				var tObj = { w00t: false, blarg: true };
+				t.assertEqual(
+					["thinger", "blah", tObj], 
+					["thinger", "blah", tObj]
+				);
+				t.assertEqual(tObj, tObj);
+			},
+			/*
+			// uncomment to tests exception handling
+			function sanityCheckassertTrue(t){
+				// should throw an error
+				t.assertTrue(false);
+			},
+			function sanityCheckassertFalse(t){
+				// should throw an error
+				t.assertFalse(true);
+			},
+			function sanityCheckassertEqual(t){
+				// should throw an error
+				t.assertEqual("foo", "bar");
+			},
+			*/
+			{
+				name: "eqTest",
+				// smoke test the fixture system
+				setUp: function(t){
+					this.foo = "blah";
+				},
+				runTest: function(t){
+					t.assertEqual("blah", this.foo);
+				},
+				tearDown: function(t){
+				}
+			}
+		]
+	);
+
+	if(testGlobal["dojo"]){
+		doh.register("tests._base", 
+			[
+				function dojoIsAvailable(t){
+					t.assertTrue(testGlobal["dojo"]);
+				}
+			]
+		);
+	}
+
+	if(testGlobal["setTimeout"]){
+		// a stone-stupid async test
+		doh.register("tests.async", 
+			[
+				{
+					name: "deferredSuccess",
+					runTest: function(t){
+						var d = new doh.Deferred();
+						setTimeout(d.getTestCallback(function(){
+							t.assertTrue(true);
+							t.assertFalse(false);
+						}), 50);
+						return d;
+					}
+				},
+				{
+					name: "deferredFailure",
+					runTest: function(t){
+						var d = new doh.Deferred();
+						setTimeout(function(){
+							d.errback(new Error("hrm..."));
+						}, 50);
+						return d;
+					}
+				},
+				{
+					name: "timeoutFailure",
+					timeout: 50,
+					runTest: function(t){
+						// timeout of 50
+						var d = new doh.Deferred();
+						setTimeout(function(){
+							d.callback(true);
+						}, 100);
+						return d;
+					}
+				}
+			]
+		);
+	}
+}
+
+try{
+	// go grab the others
+	dojo.require("tests._base._loader.bootstrap");
+	dojo.require("tests._base._loader.loader");
+	dojo.platformRequire({
+		browser: ["tests._base._loader.hostenv_browser"],
+		rhino: ["tests._base._loader.hostenv_rhino"],
+		spidermonkey: ["tests._base._loader.hostenv_spidermonkey"]
+	});
+	dojo.require("tests._base.array");
+	dojo.require("tests._base.Color");
+	dojo.require("tests._base.lang");
+	dojo.require("tests._base.declare");
+	dojo.require("tests._base.connect");
+	dojo.require("tests._base.Deferred");
+	dojo.require("tests._base.json");
+	dojo.require("tests._base.object");
+	// FIXME: add test includes for the rest of the Dojo Base groups here
+	dojo.requireIf(dojo.isBrowser, "tests._base.html");
+	dojo.requireIf(dojo.isBrowser, "tests._base.fx");
+	dojo.requireIf(dojo.isBrowser, "tests._base.query");
+	dojo.requireIf(dojo.isBrowser, "tests._base.xhr");
+	dojo.requireIf(dojo.isBrowser, "tests._base.window");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojo/tests/_base/Color.js b/dojo/tests/_base/Color.js
new file mode 100644
index 0000000..a0e85aa
--- /dev/null
+++ b/dojo/tests/_base/Color.js
@@ -0,0 +1,28 @@
+dojo.provide("tests._base.Color");
+
+(function(){
+	var white  = dojo.colorFromString("white").toRgba();
+	var maroon = dojo.colorFromString("maroon").toRgba();
+	var verifyColor = function(t, source, expected){
+		var color = new dojo.Color(source);
+		t.is(expected, color.toRgba());
+		dojo.forEach(color.toRgba(), function(n){ t.is("number", typeof(n)); });
+	}
+
+	doh.register("tests._base.Color", 
+		[
+			function testColor1(t){ verifyColor(t, "maroon", maroon); },
+			function testColor2(t){ verifyColor(t, "white", white); },
+			function testColor3(t){ verifyColor(t, "#fff", white); },
+			function testColor4(t){ verifyColor(t, "#ffffff", white); },
+			function testColor5(t){ verifyColor(t, "rgb(255,255,255)", white); },
+			function testColor6(t){ verifyColor(t, "#800000", maroon); },
+			function testColor7(t){ verifyColor(t, "rgb(128, 0, 0)", maroon); },
+			function testColor8(t){ verifyColor(t, "rgba(128, 0, 0, 0.5)", [128, 0, 0, 0.5]); },
+			function testColor9(t){ verifyColor(t, maroon, maroon); },
+			function testColor10(t){ verifyColor(t, [1, 2, 3], [1, 2, 3, 1]); },
+			function testColor11(t){ verifyColor(t, [1, 2, 3, 0.5], [1, 2, 3, 0.5]); },
+			function testColor12(t){ verifyColor(t, dojo.blendColors(new dojo.Color("black"), new dojo.Color("white"), 0.5), [128, 128, 128, 1]); }
+		]
+	);
+})();
diff --git a/dojo/tests/_base/Deferred.js b/dojo/tests/_base/Deferred.js
new file mode 100644
index 0000000..b9c1505
--- /dev/null
+++ b/dojo/tests/_base/Deferred.js
@@ -0,0 +1,180 @@
+dojo.provide("tests._base.Deferred");
+
+var delay = function(ms){
+	var d = new dojo.Deferred();
+	setTimeout(function(){
+		d.progress(0.5);
+	},ms/2);
+	setTimeout(function(){
+		d.resolve();
+	},ms);
+	return d.promise;
+};
+doh.register("tests._base.Deferred", 
+	[
+
+		function callback(t){
+			var nd = new dojo.Deferred();
+			var cnt = 0;
+			nd.addCallback(function(res){
+				doh.debug("debug from dojo.Deferred callback");
+				return res;
+			});
+			nd.addCallback(function(res){
+				// t.debug("val:", res);
+				cnt+=res;
+				return cnt;
+			});
+			nd.callback(5);
+			// t.debug("cnt:", cnt);
+			t.assertEqual(cnt, 5);
+		},
+
+		function callback_extra_args(t){
+			var nd = new dojo.Deferred();
+			var cnt = 0;
+			nd.addCallback(dojo.global, function(base, res){ cnt+=base; cnt+=res; return cnt; }, 30);
+			nd.callback(5);
+			t.assertEqual(cnt, 35);
+		},
+
+		function errback(t){
+			var nd = new dojo.Deferred();
+			var cnt = 0;
+			nd.addErrback(function(val){
+				return ++cnt;
+			});
+			nd.errback();
+			t.assertEqual(cnt, 1);
+		},
+
+		function callbackTwice(t){
+			var nd = new dojo.Deferred();
+			var cnt = 0;
+			nd.addCallback(function(res){
+				return ++cnt;
+			});
+			nd.callback();
+			t.assertEqual(cnt, 1);
+			var thrown = false;
+			try{
+				nd.callback();
+			}catch(e){
+				thrown = true;
+			}
+			t.assertTrue(thrown);
+		},
+
+		function addBoth(t){
+			var nd = new dojo.Deferred();
+			var cnt = 0;
+			nd.addBoth(function(res){
+				return ++cnt;
+			});
+			nd.callback();
+			t.assertEqual(cnt, 1);
+
+			// nd.callback();
+			// t.debug(cnt);
+			// t.assertEqual(cnt, 1);
+		},
+
+		function callbackNested(t){
+			var nd = new dojo.Deferred();
+			var nestedReturn = "yellow";
+			nd.addCallback(function(res){
+				nd.addCallback(function(res2){
+					nestedReturn = res2;
+				});
+				return "blue";
+			});
+			nd.callback("red");
+			t.assertEqual("blue", nestedReturn);
+		},
+		function simpleThen(t){
+			var td = new doh.Deferred();
+			delay().then(function(){
+				td.callback(true);
+			});
+			return td;
+		},
+		function thenChaining(t){
+			var td = new doh.Deferred();
+			var p = delay();
+			var p2 = p.then(function(){
+				return 1;
+			});
+			p3 = p2.then(function(){
+				return 2;
+			});
+			p3.then(function(){
+				p2.then(function(v){
+					t.assertEqual(v, 1);
+					p3.then(function(v){
+						t.assertEqual(v, 2);
+						td.callback(true);
+					});
+				});
+			});
+			return td;
+		},
+		function simpleWhen(t){
+			var td = new doh.Deferred();
+			dojo.when(delay(), function(){
+				td.callback(true);
+			});
+			return td;
+		},
+		function progress(t){
+			var td = new doh.Deferred();
+			var percentDone;
+			dojo.when(delay(), function(){
+				t.is(percentDone, 0.5);
+				td.callback(true);
+			},function(){},
+			function(completed){
+				percentDone = completed;
+			});
+			return td;
+		},
+		function errorHandler(t){
+			var def = new dojo.Deferred();
+			var handledError;
+			dojo.config.deferredOnError = function(e){
+				handledError = e;
+			};
+			def.reject(new Error("test"));
+			t.t(handledError instanceof Error);
+		},
+		function cancelThenDerivative(t){
+			var def = new dojo.Deferred();
+			var def2 = def.then();
+			try{
+				def2.cancel();
+				t.t(true); // Didn't throw an error
+			}catch(e){
+				t.t(false);
+			}
+		},
+		function cancelPromiseValue(t){
+			var cancelledDef;
+			var def = new dojo.Deferred(function(_def){ cancelledDef = _def; });
+			def.promise.cancel();
+			t.is(def, cancelledDef);
+		},
+		function errorResult(t){
+			var def = new dojo.Deferred();
+			var result = new Error("rejected");
+			def.reject(result);
+			t.is(def.fired, 1);
+			t.is(def.results[1], result);
+		},
+		function globalLeak(t){
+			var def = new dojo.Deferred();
+			def.then(function(){ return def; });
+			def.resolve(true);
+			t.is(dojo.global.results, undefined, "results is leaking into global");
+			t.is(dojo.global.fired, undefined, "fired is leaking into global");
+		}
+	]
+);
diff --git a/dojo/tests/_base/NodeList.html b/dojo/tests/_base/NodeList.html
new file mode 100644
index 0000000..64343b4
--- /dev/null
+++ b/dojo/tests/_base/NodeList.html
@@ -0,0 +1,617 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<!--
+	we use a strict-mode DTD to ensure that the box model is the same for these
+	basic tests
+-->
+<html>
+	<head>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+			html, body {
+				padding: 0px;
+				margin: 0px;
+				border: 0px;
+			}
+
+			#sq100 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 100px;
+				top: 100px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding: 0px;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+		</style>
+		<title>testing dojo.NodeList</title>
+		<script type="text/javascript" src="../../dojo.js"
+			djConfig="isDebug: false"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.addOnLoad(function(){
+				var c = dojo.byId("c1");
+				var t = dojo.byId("t");
+				var s = dojo.byId("sq100");
+				var fourElementNL = new dojo.NodeList(c, t, c, t);
+
+				function verify(/*dojo.NodeList*/nl, /*Array*/ids){
+					for(var i = 0, node; node = nl[i]; i++){
+						doh.is(ids[i], node.id);
+					}
+					//Make sure lengths are equal.
+					doh.is(ids.length, i);
+				}
+
+				doh.register("t",
+					[
+						// constructor tests
+						function ctor(){
+							var nl = new dojo.NodeList();
+							nl.push(c);
+							doh.is(1, nl.length);
+						},
+						function ctorArgs(){
+							var nl = new dojo.NodeList(4);
+							nl.push(c);
+							doh.is(5, nl.length);
+						},
+						function ctorArgs2(){
+							var nl = new dojo.NodeList(c, t);
+							doh.is(2, nl.length);
+							doh.is(c, nl[0]);
+							doh.is(t, nl[1]);
+						},
+						// iteration and array tests
+						function forEach(){
+							var lastItem;
+							var nl = new dojo.NodeList(c, t);
+							nl.forEach(function(i){ lastItem = i; });
+							doh.is(t, lastItem);
+
+							var r = nl.forEach(function(i, idx, arr){
+								doh.t(arr.constructor == dojo.NodeList);
+								doh.is(2, arr.length);
+							});
+							doh.t(r.constructor == dojo.NodeList);
+							doh.is(r, nl);
+						},
+
+						function indexOf(){
+							doh.is(0, fourElementNL.indexOf(c));
+							doh.is(1, fourElementNL.indexOf(t));
+							doh.is(-1, fourElementNL.indexOf(null));
+						},
+
+						function lastIndexOf(){
+							doh.is(2, fourElementNL.lastIndexOf(c));
+							doh.is(3, fourElementNL.lastIndexOf(t));
+							doh.is(-1, fourElementNL.lastIndexOf(null));
+						},
+
+						function every(){
+							var ctr = 0;
+							var ret = fourElementNL.every(function(){
+								ctr++;
+								return true;
+							});
+							doh.is(4, ctr);
+							doh.t(ret);
+
+							ctr = 0;
+							var ret = fourElementNL.every(function(){
+								ctr++;
+								return false;
+							});
+							doh.is(1, ctr);
+							doh.f(ret);
+						},
+
+						function some(){
+							var ret = fourElementNL.some(function(){
+								return true;
+							});
+							doh.t(ret);
+
+							var ret = fourElementNL.some(function(i){
+								return (i.id == "t");
+							});
+							doh.t(ret);
+						},
+
+						function map(){
+							var ret = fourElementNL.map(function(){
+								return true;
+							});
+
+							doh.is(ret, [true, true, true, true]);
+
+							verify(ret.end(), ["c1", "t", "c1", "t"]);
+
+							var cnt = 0;
+							var ret = fourElementNL.map(function(){
+								return cnt++;
+							});
+							// doh.is(ret, [0, 1, 2, 3]);
+
+							doh.t(ret.constructor == dojo.NodeList);
+
+							// make sure that map() returns a NodeList
+							var sum = 0;
+							fourElementNL.map(function(){ return 2; }).forEach( function(x){ sum += x; } );
+							doh.is(sum, 8);
+						},
+
+						function slice(){
+							var pnl = new dojo.NodeList(t, t, c);
+							doh.is(2, pnl.slice(1).length);
+							doh.is(3, pnl.length);
+							doh.is(c, pnl.slice(-1)[0]);
+							doh.is(2, pnl.slice(-2).length);
+							verify(pnl.slice(1).end(), ["t", "t", "c1"]);
+						},
+
+						function splice(){
+							var pnl = new dojo.NodeList(t, t, c);
+							console.debug(pnl.splice(1));
+
+							/*
+							doh.is(2, pnl.splice(1).length);
+							doh.is(1, pnl.length);
+							pnl = new dojo.NodeList(t, t, c);
+							doh.is(c, pnl.splice(-1)[0]);
+							doh.is(2, pnl.length);
+							pnl = new dojo.NodeList(t, t, c);
+							doh.is(2, pnl.splice(-2).length);
+							*/
+						},
+
+						function spliceInsert(){
+							// insert 1
+							var pnl = new dojo.NodeList(t, t, c);
+							pnl.splice(0, 0, c);
+							doh.is(4, pnl.length);
+							doh.is(c, pnl[0]);
+
+							// insert multiple
+							pnl = new dojo.NodeList(t, t, c);
+							pnl.splice(0, 0, c, s);
+							doh.is(5, pnl.length);
+							doh.is(c, pnl[0]);
+							doh.is(s, pnl[1]);
+							doh.is(t, pnl[2]);
+
+							// insert multiple at offset
+							pnl = new dojo.NodeList(t, t, c);
+							pnl.splice(1, 0, c, s);
+							doh.is(5, pnl.length);
+							doh.is(t, pnl[0]);
+							doh.is(c, pnl[1]);
+							doh.is(s, pnl[2]);
+							doh.is(t, pnl[3]);
+						},
+
+						function spliceDel(){
+							// clobbery 1
+							var pnl = new dojo.NodeList(c, t, s);
+							pnl.splice(0, 1);
+							doh.is(2, pnl.length);
+							doh.is(t, pnl[0]);
+
+							// clobber multiple
+							pnl = new dojo.NodeList(c, t, s);
+							pnl.splice(0, 2);
+							doh.is(1, pnl.length);
+							doh.is(s, pnl[0]);
+
+							// ...at an offset
+							pnl = new dojo.NodeList(c, t, s);
+							pnl.splice(1, 1);
+							doh.is(2, pnl.length);
+							doh.is(c, pnl[0]);
+							doh.is(s, pnl[1]);
+
+						},
+
+						function spliceInsertDel(){
+							// clobbery 1
+							var pnl = new dojo.NodeList(c, t, s);
+							pnl.splice(1, 1, s);
+							doh.is(3, pnl.length);
+							doh.is(dojo.NodeList(c, s, s), pnl);
+
+							pnl = new dojo.NodeList(c, t, s);
+							pnl.splice(1, 2, s);
+							doh.is(2, pnl.length);
+							doh.is(dojo.NodeList(c, s), pnl);
+						},
+
+						// sub-search
+						function query(){
+							var pnl = new dojo.NodeList(t);
+							doh.is(c, pnl.query("span")[0]);
+							doh.is(t, dojo.query("body").query(":last-child")[0]);
+							doh.is(c, dojo.query("body").query(":last-child")[1]);
+							doh.is(1, pnl.query().length);
+							verify(pnl.query("span").end(), ["t"]);
+						},
+
+						function filter(){
+							doh.is(dojo.query("body :first-child").filter(":last-child")[0], c);
+							doh.is(1, dojo.query("*").filter(function(n){ return (n.nodeName.toLowerCase() == "span"); }).length);
+
+							var filterObj = {
+								filterFunc: function(n){
+									return (n.nodeName.toLowerCase() == "span");
+								}
+							};
+							doh.is(1, dojo.query("*").filter(filterObj.filterFunc).length);
+							doh.is(1, dojo.query("*").filter(filterObj.filterFunc, filterObj).length);
+							verify((new dojo.NodeList(t)).filter("span").end(), ["t"]);
+						},
+
+						// layout DOM functions
+						function coords(){
+							var tnl = new dojo.NodeList(dojo.byId('sq100'))
+							doh.t(dojo.isArray(tnl));
+							doh.is(100, tnl.coords()[0].w);
+							doh.is(100, tnl.coords()[0].h);
+							doh.is(100, tnl.position()[0].w);
+							doh.is(100, tnl.position()[0].h);
+							doh.is(document.body.getElementsByTagName("*").length, dojo.query("body *").coords().length);
+							doh.is(document.body.getElementsByTagName("*").length, dojo.query("body *").position().length);
+						},
+
+						function styleGet(){
+							// test getting
+							var tnl = new dojo.NodeList(s);
+							doh.is(1, tnl.style("opacity")[0]);
+							tnl.push(t);
+							dojo.style(t, "opacity", 0.5);
+							doh.is(0.5, tnl.style("opacity").slice(-1)[0]);
+							tnl.style("opacity", 1);
+						},
+
+						function styleSet(){
+							// test setting
+							var tnl = new dojo.NodeList(s, t);
+							tnl.style("opacity", 0.5);
+							doh.is(0.5, dojo.style(tnl[0], "opacity"));
+							doh.is(0.5, dojo.style(tnl[1], "opacity"));
+							// reset
+							tnl.style("opacity", 1);
+						},
+
+						function style(){
+							var tnl = new dojo.NodeList(s, t);
+							tnl.style("opacity", 1);
+							doh.is(1, tnl.style("opacity")[0]);
+							dojo.style(t, "opacity", 0.5);
+							doh.is(1.0, tnl.style("opacity")[0]);
+							doh.is(0.5, tnl.style("opacity")[1]);
+							// reset things
+							tnl.style("opacity", 1);
+						},
+
+						function addRemoveClass(){
+							var tnl = new dojo.NodeList(s, t);
+							tnl.addClass("a");
+							doh.is("a", s.className);
+							doh.is("a", t.className);
+							tnl.addClass("a b");
+							doh.is("a b", s.className);
+							doh.is("a b", t.className);
+							tnl.addClass(["a", "c"]);
+							doh.is("a b c", s.className);
+							doh.is("a b c", t.className);
+							tnl.removeClass();
+							doh.is("", s.className);
+							doh.is("", t.className);
+							tnl.addClass("    a");
+							doh.is("a", s.className);
+							doh.is("a", t.className);
+							tnl.addClass(" a  b ");
+							doh.is("a b", s.className);
+							doh.is("a b", t.className);
+							tnl.addClass(" c  b a ");
+							doh.is("a b c", s.className);
+							doh.is("a b c", t.className);
+							tnl.removeClass(" b");
+							doh.is("a c", s.className);
+							doh.is("a c", t.className);
+							tnl.removeClass("a b ");
+							doh.is("c", s.className);
+							doh.is("c", t.className);
+							tnl.removeClass(["a", "c"]);
+							doh.is("", s.className);
+							doh.is("", t.className);
+						},
+
+						function concat(){
+							var spans = dojo.query("span");
+							var divs = dojo.query("div");
+							var cat = spans.concat(divs);
+							console.debug(cat);
+							doh.t(cat.constructor == dojo.NodeList || cat.constructor == NodeList);
+							doh.is((divs.length + spans.length), cat.length);
+							verify(cat.end(), ["c1"]);
+						},
+
+						function concat2(){
+							var spans = dojo.query("span");
+							var divs = dojo.query("div");
+							doh.is(spans.concat([]).constructor, dojo.NodeList);
+						},
+
+						function concat3(){
+							var spans = dojo.query("span");
+							var divs = dojo.query("div");
+							var cat = spans.concat(divs);
+
+							doh.t(typeof NodeList != "undefined" && cat.constructor === NodeList
+								|| cat.constructor === dojo.NodeList);
+						},
+
+						function place(){
+							var ih = "<div><span></span></div><span class='thud'><b>blah</b></span>";
+
+							var tn = document.createElement("div");
+							tn.innerHTML = ih;
+							dojo.body().appendChild(tn);
+							var nl = dojo.query("b", tn).place(tn, "first");
+							doh.t(nl.constructor == dojo.NodeList || nl.constructor == NodeList);
+							doh.is(1, nl.length);
+							doh.is("b", nl[0].nodeName.toLowerCase());
+							doh.is(tn, nl[0].parentNode);
+							doh.is(tn.firstChild, nl[0]);
+						},
+
+						function orphan(){
+							var ih = "<div><span></span></div><span class='thud'><b>blah</b></span>";
+
+							var tn = document.createElement("div");
+							tn.innerHTML = ih;
+							dojo.body().appendChild(tn);
+							var nl = dojo.query("span", tn).orphan();
+							doh.t(nl.constructor == dojo.NodeList || nl.constructor == NodeList);
+
+							doh.is(2, nl.length);
+							doh.is(1, tn.getElementsByTagName("*").length);
+
+							tn.innerHTML = ih;
+							var nl = dojo.query("*", tn).orphan("b");
+							doh.is(1, nl.length);
+							doh.is("blah", nl[0].innerHTML);
+						},
+
+						function adopt(){
+							var div = dojo.query(dojo.create("div"));
+							div.adopt(dojo.create("span"));
+							div.adopt(dojo.create("em"), "first");
+							doh.is(2, dojo.query("*", div[0]).length);
+							doh.is("em", div[0].firstChild.tagName.toLowerCase());
+							doh.is("span", div[0].lastChild.tagName.toLowerCase());
+						},
+
+						function addContent(){
+							//text content
+							var tn = document.createElement("div");
+							var nl = dojo.query(tn).addContent("some text content");
+
+							doh.is(1, nl[0].childNodes.length);
+							doh.is("some text content", nl[0].firstChild.nodeValue);
+
+							//move a node
+							var mNode = document.createElement("span");
+							mNode.id = "addContent1";
+							mNode.innerHTML = "hello";
+							dojo.body().appendChild(mNode);
+							doh.t(dojo.byId("addContent1"));
+
+							nl.addContent(mNode);
+							doh.f(dojo.byId("addContent1"));
+							doh.is("addContent1", nl[0].lastChild.id);
+
+							//put in multiple content/clone node
+							tn.innerHTML = '<select><option name="second"  value="second" selected>second</option></select>'
+							               '<select><option name="second"  value="second" selected>second</option></select>';
+							nl = dojo.query("select", tn).addContent('<option name="first" value="first">first</option>', "first");
+							nl.forEach(function(node){
+								doh.is("first", node.options[0].value);
+								doh.f(node.options[0].selected);
+							});
+
+							//Some divs to use for addContent template actions.
+							var templs = dojo._toDom('<div class="multitemplate"></div><div class="multitemplate"></div>');
+							dojo.body().appendChild(templs);
+							templs = dojo.query(".multitemplate");
+
+							//templateFunc test
+							templs.addContent({
+								template: '<b>[name]</b>',
+								templateFunc: function(str, obj){ return str.replace(/\[name\]/g, obj.name); },
+								name: "bar"
+							});
+
+							var bolds = templs.query("b");
+							doh.is(2, bolds.length);
+							bolds.forEach(function(node){
+								doh.is("bar", node.innerHTML);
+							});
+
+							//template with dojo.string.substitute used.
+							dojo.require("dojo.string");
+							templs.addContent({
+								template: "<p>${name}</p>",
+								name: "baz"
+							});
+
+							var ps = templs.query("p");
+							doh.is(2, ps.length);
+							ps.forEach(function(node){
+								doh.is("baz", node.innerHTML);
+							});
+
+							//Try a dojo.declared thing.
+							dojo.require("dojo.parser");
+							dojo.declare("dojo.tests.Mini", null, {
+								constructor: function(args, node){
+									dojo.mixin(this, args);
+									node.innerHTML = this.name;
+									this.domNode = node;
+								},
+								name: ""
+							});
+
+							templs.addContent({
+								template: '<i dojoType="dojo.tests.Mini" name="cool"></i>',
+								parse: true
+							});
+
+
+							var declaredNodes = templs.query("[dojoType]");
+
+							doh.is(2, declaredNodes.length);
+							dojo.forEach(declaredNodes, function(node){
+								doh.is("cool", node.innerHTML);
+							});
+
+							//Get rid of the junk used for template testing.
+							templs.orphan();
+						},
+
+						function connect(){
+							var ih = "<div><span></span></div><span class='thud'><button>blah</button></span>";
+
+							var tn = document.createElement("div");
+							tn.innerHTML = ih;
+							dojo.body().appendChild(tn);
+
+							var ctr = 0;
+							var nl = dojo.query("button", tn).connect("onclick", function(){
+								ctr++;
+							});
+							nl[0].click();
+							doh.is(1, ctr);
+							nl[0].click();
+							nl[0].click();
+							doh.is(3, ctr);
+						},
+
+						function at(){
+							var divs = dojo.query("body div");
+							var at0 = divs.at(0);
+							doh.is(divs[0], at0[0]);
+
+							var at1 = divs.at(1,3,5);
+							doh.is(divs[1], at1[0]);
+							doh.is(divs[3], at1[1]);
+							doh.is(divs[5], at1[2]);
+
+							var at2 = divs.at(3,6,9);
+							doh.is(at2.length, 2);
+
+							var at3 = divs.at(3,6).at(1);
+							doh.is(divs[6], at3[0]);
+
+							var ending = divs.at(0).end();
+							verify([ending[0], ending[1]], ["sq100", "t"]);
+							
+							var at4 = divs.at(-1);
+							doh.is(divs[divs.length - 1], at4[0]);
+							
+							var at5 = divs.at(1, -1);
+							doh.is(at5[0], divs[1]);
+							doh.is(at5[1], divs[divs.length - 1]);
+							
+						},
+
+						function attr(){
+							var divs = dojo.query("div");
+							var ids = divs.attr("id");
+						},
+
+						function _adaptAsForEach(t){
+							var passes = false;
+							var count = 0;
+							var i = {
+								setTrue: function(node){
+									count++;
+									passes = true;
+								}
+							};
+							dojo.NodeList.prototype.setTrue = dojo.NodeList._adaptAsForEach(i.setTrue, i);
+							var divs = dojo.query("div").setTrue();
+							doh.t(passes);
+							doh.is(count, divs.length);
+						},
+
+						function instantiate(){
+							//Insert some divs to use for test
+							dojo.place('<p id="thinger">Hi</p><p id="thinger2">Hi</p>', dojo.body());
+
+							var test = 0;
+							dojo.declare("tests._base.NodeList.some.Thing", null, {
+								foo:"baz",
+								constructor: function(props, node){
+									dojo.mixin(this, props);
+									doh.is("bar", this.foo, test++);
+								}
+							});
+
+							dojo.query("#thinger").instantiate(tests._base.NodeList.some.Thing, {
+								foo:"bar"
+							});
+
+							dojo.query("#thinger2").instantiate("tests._base.NodeList.some.Thing", {
+								foo:"bar"
+							});
+
+							doh.is(2, test);
+
+							//clean up the divs inserted for the test.
+							dojo.query("#thinger, #thinger2").orphan();
+						},
+						
+						function removeAttr(){
+							
+							// buildup
+							dojo.place('<p id="attr" title="Foobar">Hi</p>', dojo.body());
+							
+							var n = dojo.query("#attr");
+							
+							doh.t(dojo.hasAttr(n[0], "title"));
+							
+							var t = n.attr("title");
+							doh.is(t, "Foobar");
+							
+							n.removeAttr("title");
+							
+							t = dojo.hasAttr(n[0], "title");
+							doh.f(t);
+							
+							// cleanup
+							n.orphan();
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body>
+		<h1>testing dojo.NodeList</h1>
+		<div id="sq100">
+			100px square, abs
+		</div>
+		<div id="t">
+			<span id="c1">c1</span>
+		</div>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/_loader/8976.html b/dojo/tests/_base/_loader/8976.html
new file mode 100644
index 0000000..c8d55d1
--- /dev/null
+++ b/dojo/tests/_base/_loader/8976.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+        <script type="text/javascript" src="../../../dojo.js"
+                djConfig="parseOnLoad: false, isDebug: true"></script>
+</head>
+<body>
+<h1>Testcase for #8976</h1>
+<p>Test case for <a href="http://bugs.dojotoolkit.org/ticket/8976">#8976</a>, an async load issue with Firefox even though the loading should be synchronous. Click the button then check console log for output of test. If "count = 1, worked" shows up instead of an error, then the test is successful.</p>
+
+<script>
+var count = 0;
+function wait(count){
+	console.log("count = "+count+", calling addOnLoad");
+	dojo.addOnLoad(function(){
+		try{
+			console.log("count = "+count+", testing");
+			var i = dijit.layout.TabController.constructor;
+			console.log("count = "+count+", worked");
+		}catch(e){ alert("failed: " + e) }
+	});
+	console.log("count = "+count+", addOnLoad returned");
+}
+function load(count){
+	console.log("count = "+count+", calling require");
+	dojo.require("dijit.dijit");
+	dojo.require("dijit.dijit-all");
+	console.log("count = "+count+", require returned");
+}
+</script>
+<input type=button onmousedown="load(count++);return true" onmouseup="wait(count++);return true" value="click this button to load and wait">
+</body>
+</html>
diff --git a/dojo/tests/_base/_loader/addLoadEvents.html b/dojo/tests/_base/_loader/addLoadEvents.html
new file mode 100644
index 0000000..f9d4d23
--- /dev/null
+++ b/dojo/tests/_base/_loader/addLoadEvents.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Testing dojo.addOnLoad(), dojo.addOnUnload() and dojo.addOnWindowUnload()</title>
+		<script type="text/javascript" 
+			src="../../../dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				console.debug("addOnLoad(func) works");
+			});
+			var scope = {
+				named: function(){ console.debug("addOnLoad(obj, name) works"); },
+				refd: function(){ console.debug("addOnLoad(obj, func) works"); }
+			};
+			dojo.ready(scope, "named");
+			dojo.addOnLoad(scope, scope.refd);
+			// dojo.addOnLoad(scope, "named");
+			// dojo.addOnLoad(scope, scope.refd);
+
+			dojo.addOnWindowUnload(function(){
+				alert("addOnWindowUnload works");
+			});
+
+			dojo.addOnUnload(function(){
+				alert("addOnUnload works");
+			});
+		</script>
+	</head>
+	<body>
+		<h1>Testing dojo.addOnLoad(), dojo.addOnUnload() and dojo.addOnWindowUnload()</h1>
+
+		<p>This page has registers a function with dojo.addOnLoad(), dojo.addOnUnload() and dojo.addOnWindowUnload.</p>
+		
+		<p><b>dojo.addOnLoad()</b>: You should see 3 console messages about addOnLoad working.</p>
+		
+		<p><b>dojo.addOnUnload()</b>: You should see an alert if the page is reloaded, or if you navigate to a 
+		different web page ("addOnUnload works").</p>
+		
+		<p><b>dojo.addOnWindowUnload()</b>: You should see an alert if the page is reloaded, or if you navigate to a 
+		different web page ("addOnWindowUnload works").</p>
+		
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/_loader/afterOnLoad.html b/dojo/tests/_base/_loader/afterOnLoad.html
new file mode 100644
index 0000000..c5c0a2f
--- /dev/null
+++ b/dojo/tests/_base/_loader/afterOnLoad.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Testing afterOnLoad</title>
+
+		<link rel="stylesheet" type="text/css" href="../../../resources/dojo.css">
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/tests/css/dijitTests.css">
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/themes/tundra/tundra.css">
+
+		<script type="text/javascript">
+			function init(){
+				//Create global djConfig object first. We cannot use the djConfig attribute
+				//on the script tag since it may not be visible in some browsers at the time
+				//dojo.js executes. This causes problems when the "require" property is used
+				//as part of djConfig. Also note that you have to set baseUrl directly, since
+				//it cannot be detected as part of script tag.
+				djConfig = {
+					baseUrl: "../../../",
+					parseOnLoad: true,
+					afterOnLoad:true,
+					addOnLoad: function(){
+						//This function is registered with
+						//dojo.addOnLoad as Dojo is defined after
+						//being added to the DOM.
+						console.log("djConfig.addOnLoad callback fired OK: dojo.parser.parse is a "
+							+ (typeof dojo.parser.parse));
+					},
+					require: [
+						'dojo.parser',
+						'dijit.Calendar'
+					],
+					isDebug: true
+				};
+
+				var script = document.createElement("script");
+				script.type = "text/javascript";
+				script.src = "../../../dojo.js";
+				
+				document.getElementsByTagName("head")[0].appendChild(script);
+			}
+
+			function myHandler(id,newValue){
+				console.debug("onChange for id = " + id + ", value: " + newValue);
+			}
+			
+			//Register onload init function that will add Dojo to the page.
+			if(window.addEventListener){
+				window.addEventListener("load", init, false);
+			}else{
+				window.attachEvent("onload", init);
+			}
+
+		</script>
+	</head>
+	<body>
+		<h1>Testing afterOnLoad</h1>
+
+		<p><b>This page only works with a dojo build</b>. It will not work properly if you run it directly from the subversion source.</p>
+
+		<p>This page tests loading dojo after the page is loaded. </p>
+		
+		<p>When the window.onload fires, the dojo script tag will be added to the DOM 
+		and configured to fire the onload callbacks. If everything works, you should
+		see a Calendar below.</p>
+		
+		<p class="tundra">
+			<input id="calendar1" dojoType="dijit.Calendar" onChange="myHandler(this.id,arguments[0])">
+		</p>
+	</body>
+</html>
diff --git a/dojo/tests/_base/_loader/bootstrap.js b/dojo/tests/_base/_loader/bootstrap.js
new file mode 100644
index 0000000..24ae382
--- /dev/null
+++ b/dojo/tests/_base/_loader/bootstrap.js
@@ -0,0 +1,123 @@
+dojo.provide("tests._base._loader.bootstrap");
+
+tests.register("tests._base._loader.bootstrap", 
+	[
+
+		function hasConsole(t){
+			t.assertTrue("console" in dojo.global);
+			t.assertTrue("assert" in console);
+			t.assertEqual("function", typeof console.assert);
+		},
+
+		{
+			name: "getObject",
+			setUp: function(){
+				//Set an object in global scope.
+				dojo.global.globalValue = {
+					color: "blue",
+					size: 20
+				};
+				
+				//Set up an object in a specific scope.
+				this.foo = {
+					bar: {
+						color: "red",
+						size: 100
+					}
+				};
+			},
+			runTest: function(t){
+				//Test for existing object using global as root path.
+				var globalVar = dojo.getObject("globalValue");
+				t.is("object", (typeof globalVar));
+				t.assertEqual("blue", globalVar.color);
+				t.assertEqual(20, globalVar.size);
+				t.assertEqual("blue", dojo.getObject("globalValue.color"));
+				
+				//Test for non-existent object using global as root path.
+				//Then create it.
+				t.assertFalse(dojo.getObject("something.thatisNew"));
+				t.assertTrue(typeof(dojo.getObject("something.thatisNew", true)) == "object");
+				
+				//Test for existing object using another object as root path.
+				var scopedVar = dojo.getObject("foo.bar", false, this);
+				t.assertTrue(typeof(scopedVar) == "object");
+				t.assertEqual("red", scopedVar.color);
+				t.assertEqual(100, scopedVar.size);
+				t.assertEqual("red", dojo.getObject("foo.bar.color", true, this));
+				
+				//Test for existing object using another object as root path.
+				//Then create it.
+				t.assertFalse(dojo.getObject("something.thatisNew", false, this));
+				t.assertTrue(typeof(dojo.getObject("something.thatisNew", true, this)) == "object");
+			},
+			tearDown: function(){
+				//Clean up global object that should not exist if
+				//the test is re-run.
+				try{
+					delete dojo.global.something;
+					delete this.something;
+				}catch(e){}
+			}
+		},
+		
+		{
+			name: "exists",
+			setUp: function(){
+				this.foo = {
+					bar: {}
+				};
+			},
+			runTest: function(t){
+				t.assertTrue(dojo.exists("foo.bar", this));
+				t.assertFalse(dojo.exists("foo.bar"));
+			}
+		},
+
+		function evalWorks(t){
+			t.assertTrue(dojo.eval("(true)"));
+			t.assertFalse(dojo.eval("(false)"));
+		},
+		
+		function _mixin(t){
+			var a = {
+				x: 1,
+				y: function(){ return 2; },
+				z1: 99,
+				w: 2,
+				v: undefined
+			};
+			var b = {
+				x: 11,
+				y: function(){ return 12; },
+				z2: 33,
+				toString: function(){ return "bark!"; },
+				toLocaleString: function(){ return "le bark-s!"; },
+				w: undefined,
+				v: undefined,
+				u: undefined
+			};
+			t.is(1, a.x);
+			t.is(2, a.y());
+			t.is(99, a.z1);
+			t.t("w" in a);
+			t.is(2, a.w);
+			t.t("v" in a);
+			t.is(undefined, a.v);
+			t.f("u" in a);
+			dojo._mixin(a, b);
+			t.is(11, a.x);
+			t.is(12, a.y());
+			t.is("bark!", a.toString());
+			t.is("le bark-s!", a.toLocaleString());
+			t.is(99, a.z1);
+			t.is(33, a.z2);
+			t.t("w" in a);
+			t.is(undefined, a.w);
+			t.t("v" in a);
+			t.is(undefined, a.v);
+			t.t("u" in a);
+			t.is(undefined, a.u);
+		}
+	]
+);
diff --git a/dojo/tests/_base/_loader/debugConsole.html b/dojo/tests/_base/_loader/debugConsole.html
new file mode 100644
index 0000000..d9018cf
--- /dev/null
+++ b/dojo/tests/_base/_loader/debugConsole.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>testing debugging and logging functions</title>
+		<script type="text/javascript">
+			djConfig = {};
+			if( document.location.href.match(/\?ON/)) {
+				djConfig.isDebug = true;
+			} else {
+				djConfig.isDebug = false;
+			}
+		</script>
+		<script type="text/javascript" src="../../../dojo.js"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				var toggle = document.getElementById("toggle").innerHTML = djConfig.isDebug?"ON":"OFF";
+			});
+			
+			var aString = "this is my test string";
+			var anObject = {
+				aProperty: "aValue",
+				anotherProperty: "anotherValue",
+				aNumber: 1234
+			};
+			
+			var cn = ["debug","log",
+				"assert", "count", "dir", "dirxml", "error", "group",
+				"groupEnd", "info", "profile", "profileEnd", "time", "timeEnd",
+				"trace", "warn"
+			];
+			for(var i=0;i<cn.length;i++) {
+				console[cn[i]]( cn[i] + ": " + aString);
+				console[cn[i]]( cn[i] + ": " + anObject);
+			}
+		</script>
+	</head>
+	<body>
+		<p>
+			Testing console.* methods with djConfig.isDebug turned <span id="toggle"></span>
+		</p>
+		<p>
+			Append '?ON' to URL to try with djConfig.isDebug turned ON. Remove it to test djConfig.isDebug turned OFF
+		</p>
+		<p>
+			If isDebug is off (false), then make sure console functions go to a simple empty function. You may see 
+			errors in the console, since console.error is being tested as part of this test.
+		</p>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/_loader/fastbackTest.html b/dojo/tests/_base/_loader/fastbackTest.html
new file mode 100644
index 0000000..9bd8d34
--- /dev/null
+++ b/dojo/tests/_base/_loader/fastbackTest.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Testing dojo.addOnLoad()</title>
+		<script type="text/javascript" src="../../../dojo.js"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				console.log("addOnLoad(func) works");
+			});
+			// to test fastback, uncomment the next block and watch your server
+			// logs vs. with this block commented out. Browsers that support
+			// fastback should not re-request the resources when this block is
+			// commented it but will do so when addOnUnload is firing
+			/*
+			dojo.addOnUnLoad(function(){
+				console.log("addOnUnLoad(func) works");
+			});
+			*/
+		</script>
+	</head>
+	<body>
+		<h1>Testing dojo.addOnLoad() to determine if fastback is working</h1>
+		<p>
+			click one of the links below to try it out and then hit your back
+			button. Watch your server logs to see what's going on and view
+			source to understand the test.
+		</p>
+		<a href="http://dojotoolkit.org">The Dojo Toolkit</a><br>
+		<a href="http://dojocampus.org">Dojo Campus</a><br>
+		<a href="http://google.com">Google</a><br>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/_loader/getText.txt b/dojo/tests/_base/_loader/getText.txt
new file mode 100644
index 0000000..054e8e8
--- /dev/null
+++ b/dojo/tests/_base/_loader/getText.txt
@@ -0,0 +1 @@
+dojo._getText() test data
\ No newline at end of file
diff --git a/dojo/tests/_base/_loader/hostenv_browser.js b/dojo/tests/_base/_loader/hostenv_browser.js
new file mode 100644
index 0000000..a05318d
--- /dev/null
+++ b/dojo/tests/_base/_loader/hostenv_browser.js
@@ -0,0 +1,11 @@
+dojo.provide("tests._base._loader.hostenv_browser");
+
+tests.register("tests._base._loader.hostenv_browser", 
+	[
+		function getText(t){
+			var filePath = dojo.moduleUrl("tests._base._loader", "getText.txt");
+			var text = dojo._getText(filePath);
+			t.assertEqual("dojo._getText() test data", text);
+		}
+	]
+);
diff --git a/dojo/tests/_base/_loader/hostenv_rhino.js b/dojo/tests/_base/_loader/hostenv_rhino.js
new file mode 100644
index 0000000..35e0ac1
--- /dev/null
+++ b/dojo/tests/_base/_loader/hostenv_rhino.js
@@ -0,0 +1,13 @@
+dojo.provide("tests._base._loader.hostenv_rhino");
+
+tests.register("tests._base._loader.hostenv_rhino", 
+	[
+		function getText(t){
+			var filePath = dojo.moduleUrl("tests._base._loader", "getText.txt");
+			var text = (new String(readText(filePath)));
+			//The Java file read seems to add a line return.
+			text = text.replace(/[\r\n]+$/, "");
+			t.assertEqual("dojo._getText() test data", text);
+		}
+	]
+);
diff --git a/dojo/tests/_base/_loader/hostenv_spidermonkey.js b/dojo/tests/_base/_loader/hostenv_spidermonkey.js
new file mode 100644
index 0000000..80e91a9
--- /dev/null
+++ b/dojo/tests/_base/_loader/hostenv_spidermonkey.js
@@ -0,0 +1,11 @@
+dojo.provide("tests._base._loader.hostenv_spidermonkey");
+
+tests.register("tests._base._loader.hostenv_spidermonkey", 
+	[
+		function getText(t){
+			var filePath = dojo.moduleUrl("tests._base._loader", "getText.txt");
+			var text = readText(filePath);
+			t.assertEqual("dojo._getText() test data", text);
+		}
+	]
+);
diff --git a/dojo/tests/_base/_loader/loader.js b/dojo/tests/_base/_loader/loader.js
new file mode 100644
index 0000000..0067f5e
--- /dev/null
+++ b/dojo/tests/_base/_loader/loader.js
@@ -0,0 +1,115 @@
+dojo.provide("tests._base._loader.loader");
+
+tests.register("tests._base._loader.loader", 
+	[
+		function baseUrl(t){
+			var originalBaseUrl = dojo.config["baseUrl"] || "./";
+
+			t.assertEqual(originalBaseUrl, dojo.baseUrl);
+		},
+		
+		function modulePaths(t){
+			dojo.registerModulePath("mycoolmod", "../some/path/mycoolpath");
+			dojo.registerModulePath("mycoolmod.widget", "http://some.domain.com/another/path/mycoolpath/widget");
+
+			t.assertEqual("../some/path/mycoolpath/util", dojo._getModuleSymbols("mycoolmod.util").join("/"));
+			t.assertEqual("http://some.domain.com/another/path/mycoolpath/widget", dojo._getModuleSymbols("mycoolmod.widget").join("/"));
+			t.assertEqual("http://some.domain.com/another/path/mycoolpath/widget/thingy", dojo._getModuleSymbols("mycoolmod.widget.thingy").join("/"));
+		},
+		
+		function moduleUrls(t){
+			dojo.registerModulePath("mycoolmod", "some/path/mycoolpath");
+			dojo.registerModulePath("mycoolmod2", "/some/path/mycoolpath2");
+			dojo.registerModulePath("mycoolmod.widget", "http://some.domain.com/another/path/mycoolpath/widget");
+			dojo.registerModulePath("ipv4.widget", "http://ipv4user:ipv4passwd@some.domain.com:2357/another/path/ipv4/widget");
+			dojo.registerModulePath("ipv6.widget", "ftp://ipv6user:ipv6passwd@[::2001:0db8:3c4d:0015:0:0:abcd:ef12]:1113/another/path/ipv6/widget");
+			dojo.registerModulePath("ipv6.widget2", "https://[0:0:0:0:0:1]/another/path/ipv6/widget2");
+
+
+			var basePrefix = dojo.baseUrl;
+			//dojo._Uri will strip off "./" characters, so do the same here
+			if(basePrefix == "./"){
+				basePrefix = "";
+			}
+			
+			t.assertEqual(basePrefix + "some/path/mycoolpath/my/favorite.html",
+				dojo.moduleUrl("mycoolmod", "my/favorite.html").toString());
+			t.assertEqual(basePrefix + "some/path/mycoolpath/my/favorite.html",
+				dojo.moduleUrl("mycoolmod.my", "favorite.html").toString());
+
+			t.assertEqual("/some/path/mycoolpath2/my/favorite.html",
+				dojo.moduleUrl("mycoolmod2", "my/favorite.html").toString());
+			t.assertEqual("/some/path/mycoolpath2/my/favorite.html",
+				dojo.moduleUrl("mycoolmod2.my", "favorite.html").toString());
+
+			t.assertEqual("http://some.domain.com/another/path/mycoolpath/widget/my/favorite.html",
+				dojo.moduleUrl("mycoolmod.widget", "my/favorite.html").toString());
+			t.assertEqual("http://some.domain.com/another/path/mycoolpath/widget/my/favorite.html",
+				dojo.moduleUrl("mycoolmod.widget.my", "favorite.html").toString());
+
+			// individual component testing
+			t.assertEqual("http://ipv4user:ipv4passwd@some.domain.com:2357/another/path/ipv4/widget/components.html",
+				dojo.moduleUrl("ipv4.widget", "components.html").uri);
+			t.assertEqual("http",
+				dojo.moduleUrl("ipv4.widget", "components.html").scheme);
+			t.assertEqual("ipv4user:ipv4passwd at some.domain.com:2357",
+				dojo.moduleUrl("ipv4.widget", "components.html").authority);
+			t.assertEqual("ipv4user",
+				dojo.moduleUrl("ipv4.widget", "components.html").user);
+			t.assertEqual("ipv4passwd",
+				dojo.moduleUrl("ipv4.widget", "components.html").password);
+			t.assertEqual("some.domain.com",
+				dojo.moduleUrl("ipv4.widget", "components.html").host);
+			t.assertEqual("2357",
+				dojo.moduleUrl("ipv4.widget", "components.html").port);
+			t.assertEqual("/another/path/ipv4/widget/components.html",
+				dojo.moduleUrl("ipv4.widget", "components.html?query").path);
+			t.assertEqual("q=somequery",
+				dojo.moduleUrl("ipv4.widget", "components.html?q=somequery").query);
+			t.assertEqual("fragment",
+				dojo.moduleUrl("ipv4.widget", "components.html#fragment").fragment);
+
+			t.assertEqual("ftp://ipv6user:ipv6passwd@[::2001:0db8:3c4d:0015:0:0:abcd:ef12]:1113/another/path/ipv6/widget/components.html",
+				dojo.moduleUrl("ipv6.widget", "components.html").uri);
+			t.assertEqual("ftp",
+				dojo.moduleUrl("ipv6.widget", "components.html").scheme);
+			t.assertEqual("ipv6user:ipv6passwd@[::2001:0db8:3c4d:0015:0:0:abcd:ef12]:1113",
+				dojo.moduleUrl("ipv6.widget", "components.html").authority);
+			t.assertEqual("ipv6user",
+				dojo.moduleUrl("ipv6.widget", "components.html").user);
+			t.assertEqual("ipv6passwd",
+				dojo.moduleUrl("ipv6.widget", "components.html").password);
+			t.assertEqual("::2001:0db8:3c4d:0015:0:0:abcd:ef12",
+				dojo.moduleUrl("ipv6.widget", "components.html").host);
+			t.assertEqual("1113",
+				dojo.moduleUrl("ipv6.widget", "components.html").port);
+			t.assertEqual("/another/path/ipv6/widget/components.html",
+				dojo.moduleUrl("ipv6.widget", "components.html?query").path);
+			t.assertEqual("somequery",
+				dojo.moduleUrl("ipv6.widget", "components.html?somequery").query);
+			t.assertEqual("somefragment",
+				dojo.moduleUrl("ipv6.widget", "components.html?somequery#somefragment").fragment);
+
+			t.assertEqual("https://[0:0:0:0:0:1]/another/path/ipv6/widget2/components.html",
+				dojo.moduleUrl("ipv6.widget2", "components.html").uri);
+			t.assertEqual("https",
+				dojo.moduleUrl("ipv6.widget2", "components.html").scheme);
+			t.assertEqual("[0:0:0:0:0:1]",
+				dojo.moduleUrl("ipv6.widget2", "components.html").authority);
+			t.assertEqual(null,
+				dojo.moduleUrl("ipv6.widget2", "components.html").user);
+			t.assertEqual(null,
+				dojo.moduleUrl("ipv6.widget2", "components.html").password);
+			t.assertEqual("0:0:0:0:0:1",
+				dojo.moduleUrl("ipv6.widget2", "components.html").host);
+			t.assertEqual(null,
+				dojo.moduleUrl("ipv6.widget2", "components.html").port);
+			t.assertEqual("/another/path/ipv6/widget2/components.html",
+				dojo.moduleUrl("ipv6.widget2", "components.html").path);
+			t.assertEqual(null,
+				dojo.moduleUrl("ipv6.widget2", "components.html").query);
+			t.assertEqual(null,
+				dojo.moduleUrl("ipv6.widget2", "components.html").fragment);
+		}
+	]
+);
diff --git a/dojo/tests/_base/_loader/scope/scope04.html b/dojo/tests/_base/_loader/scope/scope04.html
new file mode 100644
index 0000000..b1dff98
--- /dev/null
+++ b/dojo/tests/_base/_loader/scope/scope04.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Multiversion Dojo: 0.4.3 and 1.0</title>
+
+		<link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/tests/css/dijitTests.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css">
+		
+		<script type="text/javascript">
+			//djConfig for 0.4.3 setup.
+			djConfig = {
+				isDebug: true
+			};
+		</script>
+		<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.4.3/dojo.js"></script>
+		
+		<script type="text/javascript">
+			//Need scope map defined in a script block. It will not work as part of the
+			//djConfig attribute on the script that loads Dojo.
+			//Also, just adding properties instead of redefining djConfig, since that
+			//will wipe out djConfig values set up by the 0.4.3 dojo.
+			djConfig.parseOnLoad = true;
+			djConfig.baseUrl = "../../../../";
+			djConfig.scopeMap = [
+				["dojo", "dojo10"],
+				["dijit", "dijit10"],
+				["dojox", "dojox10"]					
+			];
+		</script>
+		<script type="text/javascript" src="../../../../dojo.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.widget.DropdownDatePicker");
+			dojo10.require("dijit.Calendar");
+			dojo10.require("dojo.date.locale");
+			dojo10.require("dojo.parser"); // scan page for widgets
+
+			dojo.addOnLoad(function(){
+				dojo.byId("output043").innerHTML = dojo.version.toString();
+			});
+			dojo10.addOnLoad(function(){
+				dojo.byId("output10").innerHTML = dojo10.version.toString();
+			});
+
+			function myHandler(id,newValue){
+				console.debug("onChange for id = " + id + ", value: " + newValue);
+			}
+			
+			function foobar(){
+				dojo.byId("typeOut").innerHTML = (typeof dojo.addClass);
+			}
+			setTimeout(foobar, 2000);
+
+		</script>
+	</head>
+	<body>
+		<h1>Multiversion Dojo: 0.4.3 and 1.0</h1>
+	
+		<p><b>NOTE: This test only works with a built version of Dojo</b></p>
+
+		<p>This page loads Dojo 0.4.3 and Dojo 1.0.</p>
+		
+		<p>Dojo 0.4.3 version: <span id="output043"></span></p>
+		
+		<p>Dojo 1.0 version: <span id="output10"></span></p>
+		
+		<p><b>dojo.addClass should be undefined:</b> <span id="typeOut"></span></p>
+		
+		<p>
+			<input dojoType="dropdowndatepicker" value="2006-10-31" containerToggle="wipe" containerToggleDuration="300" >
+		</p>
+		
+		<p class="tundra">
+			<input id="calendar1" dojo10Type="dijit.Calendar" onChange="myHandler(this.id,arguments[0])">
+		</p>
+		
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/_loader/scope/scopeContained.html b/dojo/tests/_base/_loader/scope/scopeContained.html
new file mode 100644
index 0000000..67b74de
--- /dev/null
+++ b/dojo/tests/_base/_loader/scope/scopeContained.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Multiversion Dojo: 0.4.3 and 1.0</title>
+
+		<link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/tests/css/dijitTests.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css">
+		
+		<script type="text/javascript">
+			//djConfig for 0.4.3 setup.
+			djConfig = {
+				isDebug: true
+			};
+		</script>
+		<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.4.3/dojo.js"></script>
+		
+		<script type="text/javascript">
+			//Scope map for this page is "burned in" via a build command (see HTML notes below).
+			//Also, just adding properties instead of redefining djConfig, since that
+			//will wipe out djConfig values set up by the 0.4.3 dojo.
+			djConfig.parseOnLoad = true;
+			djConfig.baseUrl = "../../../../";
+		</script>
+		<script type="text/javascript" src="../../../../dojo.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.widget.DropdownDatePicker");
+
+			//Notice that dijit.Calendar is required, not jidit._Calendar.
+			//Same for the dojo resources (not jodo resources).
+			jodo.require("dijit.Calendar");
+			jodo.require("dojo.date.locale");
+			jodo.require("dojo.parser"); // scan page for widgets
+
+			dojo.addOnLoad(function(){
+				dojo.byId("output043").innerHTML = dojo.version.toString();
+			});
+			jodo.addOnLoad(function(){
+				dojo.byId("output10").innerHTML = jodo.version.toString();
+			});
+
+			function myHandler(id,newValue){
+				console.debug("onChange for id = " + id + ", value: " + newValue);
+			}
+		</script>
+	</head>
+	<body>
+		<h1>Multiversion Dojo: 0.4.3 and 1.0</h1>
+	
+		<p><b>NOTE: This test only works with a built version of Dojo, and it must be built with the scopeMap parameter (the backslashes below are required):</b></p>
+
+		<p style="color: blue; background-color: yellow">build.sh profile=standard action=release scopeMap=[[\"dojo\",\"jodo\"],[\"dijit\",\"jidit\"],[\"dojox\",\"jodox\"]]</p>
+		
+		<p>This page loads Dojo 0.4.3 and Dojo 1.0 (under the jodo scope)</p>
+		
+		<p>Dojo 0.4.3 version: <span id="output043"></span></p>
+		
+		<p>Jodo version: <span id="output10"></span></p>
+		
+		<p>
+			<input dojoType="dropdowndatepicker" value="2006-10-31" containerToggle="wipe" containerToggleDuration="300" >
+		</p>
+		
+		<p class="tundra">
+			<input id="calendar1" jodoType="dijit.Calendar" onChange="myHandler(this.id,arguments[0])">
+		</p>
+		
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/_loader/scope/scopeContainedXd.html b/dojo/tests/_base/_loader/scope/scopeContainedXd.html
new file mode 100644
index 0000000..8f4b15e
--- /dev/null
+++ b/dojo/tests/_base/_loader/scope/scopeContainedXd.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Multiversion Dojo: 0.4.3 and 1.0</title>
+
+		<link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/tests/css/dijitTests.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css">
+		
+		<script type="text/javascript">
+			//djConfig for 0.4.3 setup.
+			djConfig = {
+				isDebug: true
+			};
+		</script>
+		<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.4.3/dojo.js"></script>
+		
+		<script type="text/javascript">
+			//Scope map for this page is "burned in" via a build command (see HTML notes below).
+			//Also, just adding properties instead of redefining djConfig, since that
+			//will wipe out djConfig values set up by the 0.4.3 dojo.
+			djConfig.parseOnLoad = true;
+			djConfig.baseUrl = "../../../../";
+			djConfig.useXDomain = true; //Technically this was set already in the 0.4.3 xd dojo.js file.
+		</script>
+		<script type="text/javascript" src="../../../../dojo.xd.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.widget.DropdownDatePicker");
+
+			//Get base xd path
+			var xdPath = location.href;
+			var lastIndex = location.href.lastIndexOf("/");
+			xdPath = xdPath.substring(0, lastIndex + 1);
+			
+			//Set up xdomain locations for dojo/dijit/dojox.
+			jodo.registerModulePath("dojo", xdPath + "../../../../../dojo");
+			jodo.registerModulePath("dijit", xdPath + "../../../../../dijit");
+			jodo.registerModulePath("dojox", xdPath + "../../../../../dojox");
+			
+			//Notice that dijit.Calendar is required, not jidit._Calendar.
+			//Same for the dojo resources (not jodo resources).
+			jodo.require("dijit.Calendar");
+			jodo.require("dojo.date.locale");
+			jodo.require("dojo.parser"); // scan page for widgets
+
+			dojo.addOnLoad(function(){
+				dojo.byId("output043").innerHTML = dojo.version.toString();
+			});
+			jodo.addOnLoad(function(){
+				dojo.byId("output10").innerHTML = jodo.version.toString();
+			});
+
+			function myHandler(id,newValue){
+				console.debug("onChange for id = " + id + ", value: " + newValue);
+			}
+		</script>
+	</head>
+	<body>
+		<h1>XDomain Multiversion Dojo: 0.4.3 and 1.0</h1>
+	
+		<p><b>NOTE: This test only works with a built, xdomain version of Dojo, and it must be built with the scopeMap parameter (the backslashes below are required):</b></p>
+
+		<p style="color: blue; background-color: yellow">build.sh profile=standard action=release scopeMap=[[\"dojo\",\"jodo\"],[\"dijit\",\"jidit\"],[\"dojox\",\"jodox\"]] xdDojoScopeName=jodo loader=xdomain</p>
+		
+		<p><b>Only load this page from an http:// URL</b>. Otherwise, the xd loading will not happen.</p>
+
+		<p>This page xdomain loads Dojo 0.4.3 and Dojo 1.0 (under the jodo scope)</p>
+		
+		<p>Dojo 0.4.3 version: <span id="output043"></span></p>
+		
+		<p>Jodo version: <span id="output10"></span></p>
+		
+		<p>
+			<input dojoType="dropdowndatepicker" value="2006-10-31" containerToggle="wipe" containerToggleDuration="300" >
+		</p>
+		
+		<p class="tundra">
+			<input id="calendar1" jodoType="dijit.Calendar" onChange="myHandler(this.id,arguments[0])">
+		</p>
+		
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/_loader/scope/scopeDjConfig.html b/dojo/tests/_base/_loader/scope/scopeDjConfig.html
new file mode 100644
index 0000000..022b513
--- /dev/null
+++ b/dojo/tests/_base/_loader/scope/scopeDjConfig.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Multiversion Dojo: 0.4.3 and 1.0 (scoped djConfig)</title>
+
+		<link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/tests/css/dijitTests.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css">
+		
+		<script type="text/javascript">
+			//djConfig for 0.4.3 setup.
+			djConfig = {
+				isDebug: true
+			};
+		</script>
+		<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.4.3/dojo.js"></script>
+
+		<script type="text/javascript" src="../../../../dojo.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.widget.DropdownDatePicker");
+
+			//Notice that dijit.Calendar is required, not jidit._Calendar.
+			//Same for the dojo resources (not jodo resources).
+			jodo.require("dijit.Calendar");
+			jodo.require("dojo.date.locale");
+			jodo.require("dojo.parser"); // scan page for widgets
+
+			dojo.addOnLoad(function(){
+				dojo.byId("output043").innerHTML = djConfig.baseUrl;
+			});
+			jodo.addOnLoad(function(){
+				dojo.byId("output10").innerHTML = jodo.baseUrl;
+			});
+
+			function myHandler(id,newValue){
+				console.debug("onChange for id = " + id + ", value: " + newValue);
+			}
+		</script>
+	</head>
+	<body>
+		<h1>Multiversion Dojo: 0.4.3 and 1.0 (scoped djConfig)</h1>
+	
+		<p><b>NOTE: This test only works with a built version of Dojo, and it must be built with the scopeDjConfig parameter (the backslashes below are required):</b></p>
+
+		<p style="color: blue; background-color: yellow">build.sh profile=standard action=release scopeDjConfig=\{parseOnLoad:true,baseUrl:\"../../../../\",foo:\"bar\",scopeMap:[[\"dojo\",\"jodo\"],[\"dijit\",\"jidit\"],[\"dojox\",\"jodox\"]]\}</p>
+		
+		<p>This page loads Dojo 0.4.3 and Dojo 1.0 (under the jodo scope)</p>
+		
+		<p>djConfig.baseUrl should <b>not</b> exist: <span id="output043"></span></p>
+		
+		<p>jodo.baseUrl should be "../../../../": <span id="output10"></span></p>
+		
+		<p>
+			<input dojoType="dropdowndatepicker" value="2006-10-31" containerToggle="wipe" containerToggleDuration="300" >
+		</p>
+		
+		<p class="tundra">
+			<input id="calendar1" jodoType="dijit.Calendar" onChange="myHandler(this.id,arguments[0])">
+		</p>
+		
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/_loader/scope/scopeSingle.html b/dojo/tests/_base/_loader/scope/scopeSingle.html
new file mode 100644
index 0000000..98fc637
--- /dev/null
+++ b/dojo/tests/_base/_loader/scope/scopeSingle.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Using scope names inside dojo.require/dojoType</title>
+
+		<link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/tests/css/dijitTests.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css">
+		
+		<script type="text/javascript">
+			//djConfig for 0.4.3 setup.
+			djConfig = {
+				isDebug: true,
+				parseOnLoad: true,
+				baseUrl: "../../../../",
+				scopeMap: [
+					["dojo", "jodo"],
+					["dijit", "jidit"],
+					["dojox", "jodox"]					
+				]
+			};
+		</script>
+
+		<script type="text/javascript" src="../../../../dojo.js"></script>
+		<script type="text/javascript">
+
+			//Notice that dijit.Calendar is required, not jidit._Calendar.
+			//Same for the dojo resources (not jodo resources).
+			jodo.require("dijit.Calendar");
+			jodo.require("dojo.date.locale");
+			jodo.require("dojo.parser"); // scan page for widgets
+
+			jodo.addOnLoad(function(){
+				jodo.byId("output10").innerHTML = jodo.version.toString();
+			});
+
+			function myHandler(id,newValue){
+				console.debug("onChange for id = " + id + ", value: " + newValue);
+			}
+			function foobar(){
+				jodo.byId("typeOut").innerHTML = "typeof dojo: " + (typeof dojo) +  "<br>typeof dijit: " + (typeof dijit) + "<br>typeof dojox: " + (typeof dojox);
+			}
+			setTimeout(foobar, 2000);
+		</script>
+	</head>
+	<body>
+		<h1>Using scope names inside dojo.require/dojoType</h1>
+	
+		<p><b>NOTE: This test only works with a built version of Dojo.</b></p>
+
+		<p>Jodo version: <span id="output10"></span></p>
+
+		<p><b>typeof dojo, dijit and dojox should be undefined</b>: <br><span id="typeOut"></span></p>
+
+		<p class="tundra">
+			<input id="calendar1" jodoType="dijit.Calendar" onChange="myHandler(this.id,arguments[0])">
+		</p>
+		
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/_loader/scope/scopeSingleDaac.html b/dojo/tests/_base/_loader/scope/scopeSingleDaac.html
new file mode 100644
index 0000000..4dc3ecc
--- /dev/null
+++ b/dojo/tests/_base/_loader/scope/scopeSingleDaac.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Using scope names inside dojo.require/dojoType</title>
+
+		<link rel="stylesheet" type="text/css" href="../../../../resources/dojo.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/tests/css/dijitTests.css">
+		<link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css">
+		
+		<script type="text/javascript">
+			//djConfig for 0.4.3 setup.
+			djConfig = {
+				isDebug: true,
+				debugAtAllCosts: true,
+				parseOnLoad: true,
+				baseUrl: "../../../../",
+				scopeMap: [
+					["dojo", "jodo"],
+					["dijit", "jidit"],
+					["dojox", "jodox"]					
+				]
+			};
+		</script>
+
+		<script type="text/javascript" src="../../../../dojo.js"></script>
+		<script type="text/javascript">
+
+			//Notice that dijit.Calendar is required, not jidit._Calendar.
+			//Same for the dojo resources (not jodo resources).
+			jodo.require("dijit.Calendar");
+			jodo.require("dojo.date.locale");
+			jodo.require("dojo.parser"); // scan page for widgets
+
+			jodo.addOnLoad(function(){
+				jodo.byId("output10").innerHTML = jodo.version.toString();
+			});
+
+			function myHandler(id,newValue){
+				console.debug("onChange for id = " + id + ", value: " + newValue);
+			}
+			function foobar(){
+				jodo.byId("typeOut").innerHTML = "typeof dojo: " + (typeof dojo) +  "<br>typeof dijit: " + (typeof dijit) + "<br>typeof dojox: " + (typeof dojox);
+			}
+			setTimeout(foobar, 2000);
+		</script>
+	</head>
+	<body>
+		<h1>Using scope names inside dojo.require/dojoType</h1>
+	
+		<p><b>NOTE: This test only works with a built version of Dojo.</b></p>
+
+		<p>Jodo version: <span id="output10"></span></p>
+
+		<p><b>typeof dojo, dijit and dojox should be object, since debugAtAllCosts is ON</b>: <br><span id="typeOut"></span></p>
+
+		<p class="tundra">
+			<input id="calendar1" jodoType="jidit._Calendar" onChange="myHandler(this.id,arguments[0])">
+		</p>
+		
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/abs.html b/dojo/tests/_base/abs.html
new file mode 100644
index 0000000..906f602
--- /dev/null
+++ b/dojo/tests/_base/abs.html
@@ -0,0 +1,102 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>supplementary dojo.position() tests</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" 
+			djConfig="isDebug: false"></script>
+		<script type="text/javascript">
+			function onButtonClick(){
+				/* position a red square over pressed button */
+				var pos = dojo.position(this, true);
+				var marker = document.createElement('div');
+				document.body.appendChild(marker);
+				marker.className = "marker";
+				marker.style.position="absolute";
+				marker.style.top = pos.y+"px";
+				marker.style.left = pos.x+"px";
+				console.log(marker);
+				return false;
+			}
+				
+			dojo.addOnLoad(function(){
+				dojo.query("body")[0].scrollTop = 50;
+				dojo.query("div").forEach("item.scrollTop = 50;");
+				dojo.query("button").attr("onclick", onButtonClick);
+				
+				/***
+					benchmark code
+				var buttons = dojo.query("button");
+				var start = new Date();
+				for(var i=0; i<100; i++){
+					for(var j=0; j<buttons.length; j++) dojo.position(buttons[j]);
+				}
+				alert("benchmark: "  + (new Date() - start));
+				****/
+			});
+		</script>
+		<style type="text/css">
+			html {
+				padding: 3px;
+				margin: 3px;
+				border: 7px solid yellow;
+			}
+			body {
+				padding: 10px;
+				margin: 20px;
+				border: 9px solid blue;
+			}
+
+			.marker {
+				/* little red square that goes on top of button (assuming _abs() is working) */
+				position: absolute;
+				overflow: hidden;
+				width: 10px;
+				height: 10px;
+				border: none;
+				margin: 0px;
+				padding: 0px;
+				background-color: red;
+			}
+
+			button {
+				position: absolute;
+			}
+			
+			div {
+				position: absolute;
+				border: 17px solid gray;
+				padding: 37px;
+				margin: 29px;
+				overflow: auto;
+			}
+
+		</style>
+	</head>
+	<body>
+		<h1>supplementary dojo.position() tests</h1>
+		<button style="top: 100px; left: 200px;">click</button>
+		<button style="top: 900px; left: 200px;">click</button>
+		<div id="outer" style="position: absolute; top: 300px; left: 100px; height: 400px; width: 600px;">
+			<button style="top: 50px; left: 200px;">click2</button>
+			<div id="middle" style="position: absolute; top: 100px; left: 100px; height: 400px; width: 400px; border-width:13px 11px 23px 7px;">
+				<div id="staticDiv" style="position: static; margin-top: 20px;">
+					<button style="position: static;">click3</button>
+					<br><br><br><br><br>
+					<button style="top: 50px; left: 200px;">click4</button>
+				</div>					
+				<div id="inner" style="position: absolute; top: 150px; left: 100px; height: 470px; width: 200px;">
+					<button style="position: static;">click5</button>
+					<button style="top: 500px; left: 100px;">click6</button>
+				</div>
+				<button style="position: static;">click7</button>
+				<button style="position: relative; top: 10px; left: 10px;" id="click8">click8</button>
+				<button style="top: 300px; left: 200px;">click9</button>
+			</div>
+		</div>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/absQuirk.html b/dojo/tests/_base/absQuirk.html
new file mode 100644
index 0000000..fa525ec
--- /dev/null
+++ b/dojo/tests/_base/absQuirk.html
@@ -0,0 +1,101 @@
+<html>
+	<head>
+		<title>supplementary dojo.position() tests</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" 
+			djConfig="isDebug: false"></script>
+		<script type="text/javascript">
+			function onButtonClick(){
+				/* position a red square over pressed button */
+				var pos = dojo.position(this, true);
+				var marker = document.createElement('div');
+				document.body.appendChild(marker);
+				marker.className = "marker";
+				marker.style.position="absolute";
+				marker.style.top = pos.y+"px";
+				marker.style.left = pos.x+"px";
+				console.log(marker);
+				return false;
+			}
+				
+			dojo.addOnLoad(function(){
+				dojo.query("body")[0].scrollTop = 50;
+				dojo.query("div").forEach("item.scrollTop = 50;");
+				dojo.query("button").attr("onclick", onButtonClick);
+				
+				/***
+					benchmark code
+				var buttons = dojo.query("button");
+				var start = new Date();
+				for(var i=0; i<100; i++){
+					for(var j=0; j<buttons.length; j++) dojo.position(buttons[j]);
+				}
+				alert("benchmark: "  + (new Date() - start));
+				****/
+			});
+		</script>
+		<style type="text/css">
+			html {
+				padding: 3px;
+				margin: 3px;
+				border: 7px solid yellow;
+			}
+			body {
+				padding: 10px;
+				margin: 20px;
+				border: 9px solid blue;
+			}
+
+			.marker {
+				/* little red square that goes on top of button (assuming _abs() is working) */
+				position: absolute;
+				overflow: hidden;
+				width: 10px;
+				height: 10px;
+				border: none;
+				margin: 0px;
+				padding: 0px;
+				background-color: red;
+			}
+
+			button {
+				position: absolute;
+			}
+			
+			div {
+				position: absolute;
+				border: 17px solid gray;
+				padding: 37px;
+				margin: 29px;
+				overflow: auto;
+			}
+
+		</style>
+	</head>
+	<body>
+		<h1>supplementary dojo.position() tests</h1>
+		<button style="top: 100px; left: 200px;">click</button>
+		<button style="top: 900px; left: 200px;">click</button>
+		<div id="outer" style="position: absolute; top: 300px; left: 100px; height: 400px; width: 600px;">
+			<button style="top: 50px; left: 200px;">click2</button>
+			<div id="middle" style="position: absolute; top: 100px; left: 100px; height: 400px; width: 400px; border-width:13px 11px 23px 7px;">
+				<div id="staticDiv" style="position: static; margin-top: 20px;">
+					<button style="position: static;">click3</button>
+					<br><br><br><br><br>
+					<button style="top: 50px; left: 200px;">click4</button>
+				</div>					
+				<div id="inner" style="position: absolute; top: 150px; left: 100px; height: 470px; width: 200px;">
+					<button style="position: static;">click5</button>
+					<button style="top: 500px; left: 100px;">click6</button>
+				</div>
+				<button style="position: static;">click7</button>
+				<button style="position: relative; top: 10px; left: 10px;" id="click8">click8</button>
+				<button style="top: 300px; left: 200px;">click9</button>
+			</div>
+		</div>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/absQuirksIframe.html b/dojo/tests/_base/absQuirksIframe.html
new file mode 100644
index 0000000..9313aa4
--- /dev/null
+++ b/dojo/tests/_base/absQuirksIframe.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>
+<html dir="rtl" style="border:2px solid black;padding:3px;margin:4px;background-color:white;">
+<body style="border:2px solid blue;padding:3px;margin:4px;">
+	<nobr id='iframe_00_quirks' style="border:2px solid red;vertical-align:top;position:absolute;top:0px;left:0px;">
+		quirks iframe 0,0
+	</nobr>
+	<br>
+	<script> frameElement.win = window; </script>
+</body>
+</html>
diff --git a/dojo/tests/_base/absStrictIframe.html b/dojo/tests/_base/absStrictIframe.html
new file mode 100644
index 0000000..37f4cf2
--- /dev/null
+++ b/dojo/tests/_base/absStrictIframe.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html dir="rtl" style="border:0px solid black;padding:3px;margin:4px;background-color:white;overflow-y:scroll;">
+<body style="border:2px solid white;padding:3px;margin:4px;">
+	<nobr id='iframe_00_strict' style="border:2px solid red;vertical-align:top;position:absolute;top:0px;left:0px;">
+		strict iframe 0,0
+	</nobr>
+	<br>
+	<script> frameElement.win = window; </script>
+</body>
+</html>
diff --git a/dojo/tests/_base/array.js b/dojo/tests/_base/array.js
new file mode 100644
index 0000000..c07a8c6
--- /dev/null
+++ b/dojo/tests/_base/array.js
@@ -0,0 +1,304 @@
+dojo.provide("tests._base.array");
+
+tests.register("tests._base.array", 
+	[
+		function testIndexOf(t){
+			var foo = [128, 256, 512];
+			var bar = ["aaa", "bbb", "ccc"];
+			
+			t.assertEqual(1, dojo.indexOf([45, 56, 85], 56));
+			t.assertEqual(1, dojo.indexOf([Number, String, Date], String));
+			t.assertEqual(1, dojo.indexOf(foo, foo[1]));
+			t.assertEqual(2, dojo.indexOf(foo, foo[2]));
+			t.assertEqual(1, dojo.indexOf(bar, bar[1]));
+			t.assertEqual(2, dojo.indexOf(bar, bar[2]));
+			t.assertEqual(-1, dojo.indexOf({a:1}, "a"));
+
+			foo.push(bar);
+			t.assertEqual(3, dojo.indexOf(foo, bar));
+		},
+
+		function testIndexOfFromIndex(t){
+			var foo = [128, 256, 512];
+			var bar = ["aaa", "bbb", "ccc"];
+			
+			t.assertEqual(-1, dojo.indexOf([45, 56, 85], 56, 2));
+			t.assertEqual(1, dojo.indexOf([45, 56, 85], 56, 1));
+			t.assertEqual(1, dojo.indexOf([45, 56, 85], 56, -1));
+			// Make sure going out of bounds doesn't throw us in an infinite loop
+			t.assertEqual(-1, dojo.indexOf([45, 56, 85], 56, 3));
+		},
+
+		function testLastIndexOf(t){
+			var foo = [128, 256, 512];
+			var bar = ["aaa", "bbb", "aaa", "ccc"];
+			
+			t.assertEqual(1, dojo.indexOf([45, 56, 85], 56));
+			t.assertEqual(1, dojo.indexOf([Number, String, Date], String));
+			t.assertEqual(1, dojo.lastIndexOf(foo, foo[1]));
+			t.assertEqual(2, dojo.lastIndexOf(foo, foo[2]));
+			t.assertEqual(1, dojo.lastIndexOf(bar, bar[1]));
+			t.assertEqual(2, dojo.lastIndexOf(bar, bar[2]));
+			t.assertEqual(2, dojo.lastIndexOf(bar, bar[0]));
+		},
+
+		function testLastIndexOfFromIndex(t){
+			t.assertEqual(1, dojo.lastIndexOf([45, 56, 85], 56, 1));
+			t.assertEqual(-1, dojo.lastIndexOf([45, 56, 85], 85, 1));
+			t.assertEqual(-1, dojo.lastIndexOf([45, 56, 85], 85, -1));
+			t.assertEqual(0, dojo.lastIndexOf([45, 56, 45], 45, 0));
+		},
+
+		function testForEach(t){
+			var foo = [128, "bbb", 512];
+			dojo.forEach(foo, function(elt, idx, array){
+				switch(idx){
+					case 0: t.assertEqual(128, elt); break;
+					case 1: t.assertEqual("bbb", elt); break;
+					case 2: t.assertEqual(512, elt); break;
+					default: t.assertTrue(false);
+				}
+			});
+
+			var noException = true;
+			try{
+				dojo.forEach(undefined, function(){});
+			}catch(e){
+				noException = false;
+			}
+			t.assertTrue(noException);
+		},
+
+		function testForEach_str(t){
+			var bar = 'abc';
+			dojo.forEach(bar, function(elt, idx, array){
+				switch(idx){
+					case 0: t.assertEqual("a", elt); break;
+					case 1: t.assertEqual("b", elt); break;
+					case 2: t.assertEqual("c", elt); break;
+					default: t.assertTrue(false);
+				}
+			});
+		},
+		// FIXME: test forEach w/ a NodeList()?
+
+		function testForEach_string_callback(t){
+			// Test using strings as callback", which accept the parameters with
+			// the names "item", "index" and "array"!
+			var foo = [128, "bbb", 512];
+			// Test that the variable "item" contains the value of each item.
+			var obj = {
+				_res: ""
+			};
+			dojo.forEach(foo, "this._res += item", obj);
+			t.assertEqual(obj._res, "128bbb512");
+			// Test that the variable "index" contains each index.
+			obj._res = [];
+			dojo.forEach(foo, "this._res.push(index)", obj);
+			t.assertEqual(obj._res, [0,1,2]);
+			// Test that the variable "array" always contains the entire array.
+			obj._res = [];
+			dojo.forEach(foo, "this._res.push(array)", obj);
+			t.assertEqual(obj._res, [
+				[128, "bbb", 512],
+				[128, "bbb", 512],
+				[128, "bbb", 512]
+			]);
+			// Catch undefined variable usage (I used to use "i" :-)).
+			var caughtException = false;
+			try{
+				dojo.forEach(foo, "this._res += arr[i];", obj);
+			}catch(e){
+				caughtException = true;
+			}
+			t.assertTrue(caughtException);
+			return;
+		},
+
+		// FIXME: test forEach w/ a NodeList()?
+		function testEvery(t){
+			var foo = [128, "bbb", 512];
+
+			t.assertTrue(
+				dojo.every(foo, function(elt, idx, array){
+					t.assertEqual(Array, array.constructor);
+					t.assertTrue(dojo.isArray(array));
+					t.assertTrue(typeof idx == "number");
+					if(idx == 1){ t.assertEqual("bbb" , elt); }
+					return true;
+				})
+			);
+
+			t.assertTrue(
+				dojo.every(foo, function(elt, idx, array){
+					switch(idx){
+						case 0: t.assertEqual(128, elt); return true;
+						case 1: t.assertEqual("bbb", elt); return true;
+						case 2: t.assertEqual(512, elt); return true;
+						default: return false;
+					}
+				})
+			);
+
+			t.assertFalse(
+				dojo.every(foo, function(elt, idx, array){
+					switch(idx){
+						case 0: t.assertEqual(128, elt); return true;
+						case 1: t.assertEqual("bbb", elt); return true;
+						case 2: t.assertEqual(512, elt); return false;
+						default: return true;
+					}
+				})
+			);
+
+		},
+
+		function testEvery_str(t){
+			var bar = 'abc';
+			t.assertTrue(
+				dojo.every(bar, function(elt, idx, array){
+					switch(idx){
+						case 0: t.assertEqual("a", elt); return true;
+						case 1: t.assertEqual("b", elt); return true;
+						case 2: t.assertEqual("c", elt); return true;
+						default: return false;
+					}
+				})
+			);
+
+			t.assertFalse(
+				dojo.every(bar, function(elt, idx, array){
+					switch(idx){
+						case 0: t.assertEqual("a", elt); return true;
+						case 1: t.assertEqual("b", elt); return true;
+						case 2: t.assertEqual("c", elt); return false;
+						default: return true;
+					}
+				})
+			);
+		},
+		// FIXME: test NodeList for every()?
+
+		function testSome(t){
+			var foo = [128, "bbb", 512];
+			t.assertTrue(
+				dojo.some(foo, function(elt, idx, array){
+					t.assertEqual(3, array.length);
+					return true;
+				})
+			);
+
+			t.assertTrue(
+				dojo.some(foo, function(elt, idx, array){
+					if(idx < 1){ return true; }
+					return false;
+				})
+			);
+
+			t.assertFalse(
+				dojo.some(foo, function(elt, idx, array){
+					return false;
+				})
+			);
+
+			t.assertTrue(
+				dojo.some(foo, function(elt, idx, array){
+					t.assertEqual(Array, array.constructor);
+					t.assertTrue(dojo.isArray(array));
+					t.assertTrue(typeof idx == "number");
+					if(idx == 1){ t.assertEqual("bbb" , elt); }
+					return true;
+				})
+			);
+		},
+
+		function testSome_str(t){
+			var bar = 'abc';
+			t.assertTrue(
+				dojo.some(bar, function(elt, idx, array){
+					t.assertEqual(3, array.length);
+					switch(idx){
+						case 0: t.assertEqual("a", elt); return true;
+						case 1: t.assertEqual("b", elt); return true;
+						case 2: t.assertEqual("c", elt); return true;
+						default: return false;
+					}
+				})
+			);
+
+			t.assertTrue(
+				dojo.some(bar, function(elt, idx, array){
+					switch(idx){
+						case 0: t.assertEqual("a", elt); return true;
+						case 1: t.assertEqual("b", elt); return true;
+						case 2: t.assertEqual("c", elt); return false;
+						default: return true;
+					}
+				})
+			);
+
+			t.assertFalse(
+				dojo.some(bar, function(elt, idx, array){
+					return false;
+				})
+			);
+		},
+		// FIXME: need to add scoping tests for all of these!!!
+
+		function testFilter(t){
+			var foo = ["foo", "bar", 10];
+
+			t.assertEqual(["foo"],
+				dojo.filter(foo, function(elt, idx, array){
+					return idx < 1;
+				})
+			);
+
+			t.assertEqual(["foo"],
+				dojo.filter(foo, function(elt, idx, array){
+					return elt == "foo";
+				})
+			);
+
+			t.assertEqual([],
+				dojo.filter(foo, function(elt, idx, array){
+					return false;
+				})
+			);
+
+			t.assertEqual([10],
+				dojo.filter(foo, function(elt, idx, array){
+					return typeof elt == "number";
+				})
+			);
+		},
+
+		function testFilter_str(t){
+			var foo = "thinger blah blah blah";
+			t.assertEqual(["t", "h", "i"],
+				dojo.filter(foo, function(elt, idx, array){
+					return idx < 3;
+				})
+			);
+
+			t.assertEqual([],
+				dojo.filter(foo, function(elt, idx, array){
+					return false;
+				})
+			);
+		},
+
+		function testMap(t){
+			t.assertEqual([],
+				dojo.map([], function(){ return true; })
+			);
+
+			t.assertEqual([1, 2, 3],
+				dojo.map(["cat", "dog", "mouse"], function(elt, idx, array){
+					return idx+1;
+				})
+			);
+		}
+	]
+);
+
diff --git a/dojo/tests/_base/connect.js b/dojo/tests/_base/connect.js
new file mode 100644
index 0000000..d825bc0
--- /dev/null
+++ b/dojo/tests/_base/connect.js
@@ -0,0 +1,221 @@
+dojo.provide("tests._base.connect");
+
+hub = function(){
+}
+
+failures = 0;
+bad = function(){
+	failures++;
+}
+
+good = function(){
+}
+
+// make 'iterations' connections to hub
+// roughly half of which will be to 'good' and 
+// half to 'bad'
+// all connections to 'bad' are disconnected
+// test can then be performed on the values
+// 'failures' and 'successes'
+markAndSweepTest = function(iterations){
+	var marked = [];
+	// connections
+	for(var i=0; i<iterations; i++){
+		if(Math.random() < 0.5){
+			marked.push(dojo.connect('hub', bad));
+		}else{
+			dojo.connect('hub', good);
+		}
+	}
+	// Randomize markers (only if the count isn't very high)
+	if(i < Math.pow(10, 4)){
+		var rm = [ ];
+		while(marked.length){
+			var m = Math.floor(Math.random() * marked.length);
+			rm.push(marked[m]);
+			marked.splice(m, 1);
+		}
+		marked = rm;				
+	} 
+	for(var m=0; m<marked.length; m++){
+		dojo.disconnect(marked[m]);
+	}
+	// test
+	failures = 0;
+	hub();
+	// return number of disconnected functions that fired (should be 0)
+	return failures;
+}
+
+markAndSweepSubscribersTest = function(iterations){
+	var topic = "hubbins";
+	var marked = [];
+	// connections
+	for(var i=0; i<iterations; i++){
+		if(Math.random() < 0.5){
+			marked.push(dojo.subscribe(topic, bad));
+		}else{
+			dojo.subscribe(topic, good);
+		}
+	}
+	// Randomize markers (only if the count isn't very high)
+	if(i < Math.pow(10, 4)){
+		var rm = [ ];
+		while(marked.length){
+			var m = Math.floor(Math.random() * marked.length);
+			rm.push(marked[m]);
+			marked.splice(m, 1);
+		}
+		marked = rm;				
+	} 
+	for(var m=0; m<marked.length; m++){
+		dojo.unsubscribe(marked[m]);
+	}
+	// test
+	failures = 0;
+	dojo.publish(topic);
+	// return number of unsubscribed functions that fired (should be 0)
+	return failures;
+}
+
+tests.register("tests._base.connect",
+	[
+		function smokeTest(t){
+			// foo sets ok to false
+			var ok = false;
+			var foo = { "foo": function(){ ok=false; } };
+			// connected function sets ok to true
+			dojo.connect(foo, "foo", null, function(){ ok=true; });
+			foo.foo();
+			t.is(true, ok);
+		},
+		function basicTest(t) {
+			var out = '';
+			var obj = {
+				foo: function() {
+					out += 'foo';
+				},
+				bar: function() {
+					out += 'bar';
+				},
+				baz: function() {
+					out += 'baz';
+				}
+			};
+			//
+			var foobar = dojo.connect(obj, "foo", obj, "bar");
+			dojo.connect(obj, "bar", obj, "baz");
+			//
+			out = '';
+			obj.foo();
+			t.is('foobarbaz', out);
+			//
+			out = '';
+			obj.bar();
+			t.is('barbaz', out);
+			//
+			out = '';
+			obj.baz();
+			t.is('baz', out);
+			//
+			dojo.connect(obj, "foo", obj, "baz");
+			dojo.disconnect(foobar);
+			//
+			out = '';
+			obj.foo();
+			t.is('foobaz', out);
+			//
+			out = '';
+			obj.bar();
+			t.is('barbaz', out);
+			//
+			out = '';
+			obj.baz();
+			t.is('baz', out);
+		},
+		function hubConnectDisconnect1000(t){
+			t.is(0, markAndSweepTest(1000));
+		},
+		function args4Test(t){
+			// standard 4 args test
+			var ok, obj = { foo: function(){ok=false;}, bar: function(){ok=true} };
+			dojo.connect(obj, "foo", obj, "bar");
+			obj.foo();
+			t.is(true, ok);
+		},
+		function args3Test(t){
+			// make some globals
+			var ok;
+			dojo.global["gFoo"] = function(){ok=false;};
+			dojo.global["gOk"] = function(){ok=true;};
+			// 3 arg shorthand for globals (a)
+			var link = dojo.connect("gFoo", null, "gOk");
+			gFoo();
+			dojo.disconnect(link);
+			t.is(true, ok);
+			// 3 arg shorthand for globals (b)
+			link = dojo.connect(null, "gFoo", "gOk");
+			gFoo();
+			dojo.disconnect(link);
+			t.is(true, ok);
+			// verify disconnections 
+			gFoo();
+			t.is(false, ok);
+		},
+		function args2Test(t){
+			// make some globals
+			var ok;
+			dojo.global["gFoo"] = function(){ok=false;};
+			dojo.global["gOk"] = function(){ok=true;};
+			// 2 arg shorthand for globals 
+			var link = dojo.connect("gFoo", "gOk");
+			gFoo();
+			dojo.disconnect(link);
+			t.is(true, ok);
+			// 2 arg shorthand for globals, alternate scoping 
+			link = dojo.connect("gFoo", gOk);
+			gFoo();
+			dojo.disconnect(link);
+			t.is(true, ok);
+		},
+		function scopeTest1(t){
+			var foo = { ok: true, foo: function(){this.ok=false;} };
+			var bar = { ok: false, bar: function(){this.ok=true} };
+			// link foo.foo to bar.bar with natural scope
+			var link = dojo.connect(foo, "foo", bar, "bar");
+			foo.foo();
+			t.is(false, foo.ok);
+			t.is(true, bar.ok);
+		},		
+		function scopeTest2(t){
+			var foo = { ok: true, foo: function(){this.ok=false;} };
+			var bar = { ok: false, bar: function(){this.ok=true} };
+			// link foo.foo to bar.bar such that scope is always 'foo'
+			var link = dojo.connect(foo, "foo", bar.bar);
+			foo.foo();
+			t.is(true, foo.ok);
+			t.is(false, bar.ok);
+		},
+		function connectPublisher(t){
+			var foo = { inc: 0, foo: function(){ this.inc++; } };
+			var bar = { inc: 0, bar: function(){ this.inc++; } };
+			var c1h = dojo.connectPublisher("/blah", foo, "foo");
+			var c2h = dojo.connectPublisher("/blah", foo, "foo");
+			dojo.subscribe("/blah", bar, "bar");
+			foo.foo();
+			t.is(1, foo.inc);
+			t.is(2, bar.inc);
+			dojo.disconnect(c1h);
+			foo.foo();
+			t.is(2, foo.inc);
+			t.is(3, bar.inc);
+			dojo.disconnect(c2h);
+			foo.foo();
+			t.is(3, foo.inc);
+			t.is(3, bar.inc);
+		},
+		function publishSubscribe1000(t){
+			t.is(markAndSweepSubscribersTest(1000), 0);
+		}
+	]
+);
diff --git a/dojo/tests/_base/declare.js b/dojo/tests/_base/declare.js
new file mode 100644
index 0000000..10dea88
--- /dev/null
+++ b/dojo/tests/_base/declare.js
@@ -0,0 +1,470 @@
+dojo.provide("tests._base.declare");
+
+tests.register("tests._base.declare",
+	[
+		function smokeTest(t){
+			dojo.declare("tests._base.declare.tmp", null);
+			var tmp = new tests._base.declare.tmp();
+			dojo.declare("testsFoo", null);
+			var tmp = new testsFoo();
+		},
+		function smokeTest2(t){
+			dojo.declare("tests._base.declare.foo", null, {
+				foo: "thonk"
+			});
+			var tmp = new tests._base.declare.foo();
+			t.is("thonk", tmp.foo);
+
+			dojo.declare("testsFoo2", null, {
+				foo: "thonk"
+			});
+			var tmp2 = new testsFoo2();
+			t.is("thonk", tmp2.foo);
+		},
+		function smokeTestWithCtor(t){
+			dojo.declare("tests._base.declare.fooBar", null, {
+				constructor: function(){
+					this.foo = "blah";
+				},
+				foo: "thonk"
+			});
+			var tmp = new tests._base.declare.fooBar();
+			t.is("blah", tmp.foo);
+		},
+		function smokeTestCompactArgs(t){
+			dojo.declare("tests._base.declare.fooBar2", null, {
+				foo: "thonk"
+			});
+			var tmp = new tests._base.declare.fooBar2();
+			t.is("thonk", tmp.foo);
+		},
+		function subclass(t){
+			dojo.declare("tests._base.declare.tmp3", null, {
+				foo: "thonk"
+			});
+			dojo.declare("tests._base.declare.tmp4", tests._base.declare.tmp3);
+			var tmp = new tests._base.declare.tmp4();
+			t.is("thonk", tmp.foo);
+		},
+		function subclassWithCtor(t){
+			dojo.declare("tests._base.declare.tmp5", null, {
+				constructor: function(){
+					this.foo = "blah";
+				},
+				foo: "thonk"
+			});
+			dojo.declare("tests._base.declare.tmp6", tests._base.declare.tmp5);
+			var tmp = new tests._base.declare.tmp6();
+			t.is("blah", tmp.foo);
+		},
+		function mixinSubclass(t){
+			dojo.declare("tests._base.declare.tmp7", null, {
+				foo: "thonk"
+			});
+			dojo.declare("tests._base.declare.tmp8", null, {
+				constructor: function(){
+					this.foo = "blah";
+				}
+			});
+			var tmp = new tests._base.declare.tmp8();
+			t.is("blah", tmp.foo);
+			dojo.declare("tests._base.declare.tmp9",
+				[
+					tests._base.declare.tmp7, // prototypal
+					tests._base.declare.tmp8  // mixin
+				]);
+			var tmp2 = new tests._base.declare.tmp9();
+			t.is("blah", tmp2.foo);
+		},
+		function superclassRef(t){
+			dojo.declare("tests._base.declare.tmp10", null, {
+				foo: "thonk"
+			});
+			dojo.declare("tests._base.declare.tmp11", tests._base.declare.tmp10, {
+				constructor: function(){
+					this.foo = "blah";
+				}
+			});
+			var tmp = new tests._base.declare.tmp11();
+			t.is("blah", tmp.foo);
+			t.is("thonk", tests._base.declare.tmp11.superclass.foo);
+		},
+		function inheritedCall(t){
+			var foo = "xyzzy";
+			dojo.declare("tests._base.declare.tmp12", null, {
+				foo: "thonk",
+				bar: function(arg1, arg2){
+					if(arg1){
+						this.foo = arg1;
+					}
+					if(arg2){
+						foo = arg2;
+					}
+				}
+			});
+			dojo.declare("tests._base.declare.tmp13", tests._base.declare.tmp12, {
+				constructor: function(){
+					this.foo = "blah";
+				}
+			});
+			var tmp = new tests._base.declare.tmp13();
+			t.is("blah", tmp.foo);
+			t.is("xyzzy", foo);
+			tmp.bar("zot");
+			t.is("zot", tmp.foo);
+			t.is("xyzzy", foo);
+			tmp.bar("trousers", "squiggle");
+			t.is("trousers", tmp.foo);
+			t.is("squiggle", foo);
+		},
+		function inheritedExplicitCall(t){
+			var foo = "xyzzy";
+			dojo.declare("tests._base.declare.tmp14", null, {
+				foo: "thonk",
+				bar: function(arg1, arg2){
+					if(arg1){
+						this.foo = arg1;
+					}
+					if(arg2){
+						foo = arg2;
+					}
+				}
+			});
+			dojo.declare("tests._base.declare.tmp15", tests._base.declare.tmp14, {
+				constructor: function(){
+					this.foo = "blah";
+				},
+				bar: function(arg1, arg2){
+					this.inherited("bar", arguments, [arg2, arg1]);
+				},
+				baz: function(arg1, arg2){
+					tests._base.declare.tmp15.superclass.bar.apply(this, arguments);
+				}
+			});
+			var tmp = new tests._base.declare.tmp15();
+			t.is("blah", tmp.foo);
+			t.is("xyzzy", foo);
+			tmp.baz("zot");
+			t.is("zot", tmp.foo);
+			t.is("xyzzy", foo);
+			tmp.bar("trousers", "squiggle");
+			t.is("squiggle", tmp.foo);
+			t.is("trousers", foo);
+		},
+		function inheritedMixinCalls(t){
+			dojo.declare("tests._base.declare.tmp16", null, {
+				foo: "",
+				bar: function(){
+					this.foo += "tmp16";
+				}
+			});
+			dojo.declare("tests._base.declare.mixin16", null, {
+				bar: function(){
+					this.inherited(arguments);
+					this.foo += ".mixin16";
+				}
+			});
+			dojo.declare("tests._base.declare.mixin17", tests._base.declare.mixin16, {
+				bar: function(){
+					this.inherited(arguments);
+					this.foo += ".mixin17";
+				}
+			});
+			dojo.declare("tests._base.declare.tmp17", [tests._base.declare.tmp16, tests._base.declare.mixin17], {
+				bar: function(){
+					this.inherited(arguments);
+					this.foo += ".tmp17";
+				}
+			});
+			var tmp = new tests._base.declare.tmp17();
+			tmp.bar();
+			t.is("tmp16.mixin16.mixin17.tmp17", tmp.foo);
+		},
+		function mixinPreamble(t){
+			var passed = false;
+			dojo.declare("tests._base.declare.tmp16", null);
+			new tests._base.declare.tmp16({ preamble: function(){ passed = true; } });
+			t.t(passed);
+		},
+
+		function basicMixin(t){
+			// testing if a plain Class-like object can be inherited 
+			// by dojo.declare
+			var d = new doh.Deferred;
+
+			var Thing = function(args){
+				dojo.mixin(this, args);
+			}
+			Thing.prototype.method = function(){
+				t.t(true);
+				d.callback(true);
+			}
+
+			dojo.declare("Thinger", Thing, {
+				method: function(){
+					this.inherited(arguments);
+				}
+			});
+
+			var it = new Thinger();
+			it.method();
+
+			return d;
+		},
+
+		function mutatedMethods(t){
+			// testing if methods can be mutated (within a reason)
+			dojo.declare("tests._base.declare.tmp18", null, {
+				constructor: function(){ this.clear(); },
+				clear: function(){ this.flag = 0; },
+				foo: function(){ ++this.flag; },
+				bar: function(){ ++this.flag; },
+				baz: function(){ ++this.flag; }
+			});
+			dojo.declare("tests._base.declare.tmp19", tests._base.declare.tmp18, {
+				foo: function(){ ++this.flag; this.inherited(arguments); },
+				bar: function(){ ++this.flag; this.inherited(arguments); },
+				baz: function(){ ++this.flag; this.inherited(arguments); }
+			});
+			var x = new tests._base.declare.tmp19();
+			// smoke tests
+			t.is(0, x.flag);
+			x.foo();
+			t.is(2, x.flag);
+			x.clear();
+			t.is(0, x.flag);
+			var a = 0;
+			// dojo.connect() on a prototype method
+			dojo.connect(tests._base.declare.tmp19.prototype, "foo", function(){ a = 1; });
+			x.foo();
+			t.is(2, x.flag);
+			t.is(1, a);
+			x.clear();
+			a = 0;
+			// extra chaining
+			var old = tests._base.declare.tmp19.prototype.bar;
+			tests._base.declare.tmp19.prototype.bar = function(){
+				a = 1;
+				++this.flag;
+				old.call(this);
+			}
+			x.bar();
+			t.is(3, x.flag);
+			t.is(1, a);
+			x.clear();
+			a = 0;
+			// replacement
+			tests._base.declare.tmp19.prototype.baz = function(){
+				a = 1;
+				++this.flag;
+				this.inherited("baz", arguments);
+			}
+			x.baz();
+			t.is(2, x.flag);
+			t.is(1, a);
+		},
+
+		function modifiedInstance(t){
+			var stack;
+			dojo.declare("tests._base.declare.tmp20", null, {
+				foo: function(){ stack.push(20); }
+			});
+			dojo.declare("tests._base.declare.tmp21", null, {
+				foo: function(){
+					this.inherited(arguments);
+					stack.push(21);
+				}
+			});
+			dojo.declare("tests._base.declare.tmp22", tests._base.declare.tmp20, {
+				foo: function(){
+					this.inherited(arguments);
+					stack.push(22);
+				}
+			});
+			dojo.declare("tests._base.declare.tmp23",
+						[tests._base.declare.tmp20, tests._base.declare.tmp21], {
+				foo: function(){
+					this.inherited(arguments);
+					stack.push(22);
+				}
+			});
+			var a = new tests._base.declare.tmp22();
+			var b = new tests._base.declare.tmp23();
+			var c = {
+				foo: function(){
+					this.inherited("foo", arguments);
+					stack.push("INSIDE C");
+				}
+			};
+			stack = [];
+			a.foo();
+			t.is([20, 22], stack);
+
+			stack = [];
+			b.foo();
+			t.is([20, 21, 22], stack);
+
+			dojo.mixin(a, c);
+			dojo.mixin(b, c);
+
+			stack = [];
+			a.foo();
+			t.is([20, 22, "INSIDE C"], stack);
+
+			stack = [];
+			b.foo();
+			t.is([20, 21, 22, "INSIDE C"], stack);
+		},
+
+		function duplicatedBase(t){
+			var stack;
+			var A = dojo.declare(null, {
+				constructor: function(){
+					stack.push(1);
+				}
+			});
+			var B = dojo.declare([A, A, A], {
+				constructor: function(){
+					stack.push(2);
+				}
+			});
+			stack = [];
+			new A;
+			t.is([1], stack);
+			stack = [];
+			new B;
+			t.is([1, 2], stack);
+		},
+
+		function indirectlyDuplicatedBase(t){
+			var stack;
+			var A = dojo.declare(null, {
+				constructor: function(){
+					stack.push(1);
+				}
+			});
+			var B = dojo.declare(A, {
+				constructor: function(){
+					stack.push(2);
+				}
+			});
+			var C = dojo.declare([A, B], {
+				constructor: function(){
+					stack.push(3);
+				}
+			});
+			var D = dojo.declare([B, A], {
+				constructor: function(){
+					stack.push(4);
+				}
+			});
+			stack = [];
+			new C;
+			t.is([1, 2, 3], stack);
+			stack = [];
+			new D;
+			t.is([1, 2, 4], stack);
+		},
+
+		function wrongMultipleInheritance(t){
+			var stack;
+			var A = dojo.declare([], {
+				constructor: function(){
+					stack.push(1);
+				}
+			});
+			var B = dojo.declare([A], {
+				constructor: function(){
+					stack.push(2);
+				}
+			});
+			stack = [];
+			new A;
+			t.is([1], stack);
+			stack = [];
+			new B;
+			t.is([1, 2], stack);
+		},
+
+		function impossibleBases(t){
+			var A = dojo.declare(null);
+			var B = dojo.declare(null);
+			var C = dojo.declare([A, B]);
+			var D = dojo.declare([B, A]);
+
+			var flag = false;
+			try{
+				var E = dojo.declare([C, D]);
+			}catch(e){
+				flag = true;
+			}
+			t.t(flag);
+		},
+		
+		function noNew(t){
+			// all of the classes I create will use this as their
+			// pseudo-constructor function
+			function noNewConstructor(){
+				this.noNew_Value = 'instance value';
+			};
+
+			var g = dojo.global;
+			// this value will remain unchanged if the code for
+			// calling a constructor without 'new' works correctly.
+			g.noNew_Value = 'global value';
+
+			// perform the actual test
+			function noNewTest(cls){
+				// call class function without new
+				var obj = cls('instance value');
+				t.is(obj.noNew_Value, 'instance value');
+				t.is(g.noNew_Value, 'global value');
+			};
+
+			// There are three different functions that might be
+			// created by dojo.declare(), so I need to test all
+			// three.
+
+			// 1. Class with manual-chained constructor
+			noNewTest(
+				dojo.declare(null, {
+					constructor: noNewConstructor,
+					'-chains-': {constructor: 'manual'}
+				})
+			);
+
+			// 2. Class with no superclasses
+			var A = dojo.declare(null, {
+				constructor: noNewConstructor
+			});
+			noNewTest(A);
+
+			// 3. Class with at least one superclass
+			noNewTest(dojo.declare(A));
+
+			// Make sure multiple inheritance call works
+			var B = dojo.declare(A);
+			var C = dojo.declare(null, { ctest: function(){return true;} });
+			var D = dojo.declare([A, B, C], { dtest: function(){return true;} });
+			noNewTest(D);
+			// make sure I get the test functions from
+			// all superclasses
+			var d = D();
+			t.t(d.ctest());
+			t.t(d.dtest());
+
+			// Make sure call through an object works
+			var noNewClasses = {
+				D: D,
+				noNew_Value: 'unchanged'
+			};
+			var obj = noNewClasses.D();
+			t.is(obj.noNew_Value, 'instance value');
+			t.is(noNewClasses.noNew_Value, 'unchanged');
+		}
+
+		// FIXME: there are still some permutations to test like:
+		//	- ctor arguments
+		//	- multi-level inheritance + L/R conflict checks
+	]
+);
diff --git a/dojo/tests/_base/eventKeyPress.html b/dojo/tests/_base/eventKeyPress.html
new file mode 100644
index 0000000..1da1e5e
--- /dev/null
+++ b/dojo/tests/_base/eventKeyPress.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<html>
+<head>
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+	</style>
+	
+	<script type="text/javascript" djConfig="isDebug: true" src="../../dojo.js"></script>
+	
+	<script type="text/javascript">
+		dojo.addOnLoad(function() {
+			// Log of events on typer <input>, used by automated test harness
+			events = [];
+
+			kp1 = dojo.connect(dojo.byId("typer"), "onkeypress", function(evt){
+
+				// Keep log of events on <input>, skipping pressing of the control/shift/meta, since that's
+				// browsser dependent
+				if(evt.keyCode == dojo.keys.CTRL || evt.keyCode == dojo.keys.SHIFT || evt.keyCode == dojo.keys.META){
+					return;
+				}
+				events.push(evt);
+
+				console.log("1 onkeypress triggered: charOrCode: " + evt.charOrCode + ", keyChar: " + evt.keyChar + ", keyCode: " + evt.keyCode + ", charCode: " + evt.charCode +
+				(evt.ctrlKey ? " ctrl" : "") + (evt.shiftKey ? " shift" : ""), evt);
+
+				// Use this because many keystrokes, like CTRL-B or F5, make the browser do things like refreshing the page
+				dojo.stopEvent(evt);
+			});
+
+			kp2 = dojo.connect(dojo.byId("typer"), "onkeypress", function(evt){
+				console.log("2 onkeypress triggered: keyCode: " + evt.keyCode + ", charCode: " + evt.charCode);
+			});
+
+			kd1 = dojo.connect(dojo.byId("typer"), "onkeydown", function(evt){
+				console.log("onkeydown: charOrCode: " + evt.charOrCode + ", keyChar: " + evt.keyChar + ", keyCode: " + evt.keyCode + ", charCode: " + evt.charCode);
+			});
+
+			ku1 = dojo.connect(dojo.byId("typer"), "onkeyup", function(evt){
+				console.log("onkeyup: charOrCode: " + evt.charOrCode + ", keyChar: " + evt.keyChar + ", keyCode: " + evt.keyCode + ", charCode: " + evt.charCode);
+			});
+
+			m1 = dojo.connect(dojo.byId("typer"), "onmouseenter", function(evt){
+				console.log("mousentered");
+			});
+
+			m2 = dojo.connect(dojo.byId("typer"), "onmouseleave", function(evt){
+				console.log("onmouseleave");
+			});
+
+			c1 = dojo.connect(dojo.byId("typer"), "onclick", function(evt){
+				console.log("onclick");
+			});
+
+		});
+	</script>
+</head>
+<body class="tundra">
+<h1>onkeypress and disconnect test</h1>
+
+<p>This page tests the operation of keypress in a text input. Safari 3.1 changed its key model.
+Look in the console for log message about getting keypress events.</p>
+
+<p>This page also tests that we can dojo.disconnect correctly. Clicking on the Disconnect buttons
+should turn off the console logs associated with the matching connect calls.</p>
+
+<p>The input <input name="typer" type="text" id="typer" /></p>
+
+<p><button onclick="dojo.disconnect(kp1)">Disconnect first keypress</button>
+<button onclick="dojo.disconnect(kp2)">Disconnect second keypress</button></p>
+
+<p><button onclick="dojo.disconnect(kd1)">Disconnect keydown</button>
+<button onclick="dojo.disconnect(ku1)">Disconnect keyup</button></p>
+
+
+<p><button onclick="dojo.disconnect(m1)">Disconnect mouseentered</button>
+<button onclick="dojo.disconnect(m2)">Disconnect mouseleave</button></p>
+
+<p><button onclick="dojo.disconnect(c1)">Disconnect click</button></p>
+
+
+</body>
+</html>
diff --git a/dojo/tests/_base/eventKeyPressRobot.html b/dojo/tests/_base/eventKeyPressRobot.html
new file mode 100644
index 0000000..28541b1
--- /dev/null
+++ b/dojo/tests/_base/eventKeyPressRobot.html
@@ -0,0 +1,165 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot keypress event tests</title>
+
+		<style>
+			@import "../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+			
+		<script type="text/javascript">
+			dojo.require("dojo.robotx");
+
+			var navigation = [
+					"BACKSPACE",
+					"TAB",
+					"ENTER",
+					"ESCAPE",
+					"PAGE_UP",
+					"PAGE_DOWN",
+					"END",
+					"HOME",
+					"LEFT_ARROW",
+					"UP_ARROW",
+					"RIGHT_ARROW",
+					"DOWN_ARROW"
+					
+					/*
+						F1 to F10 are just too problematic to test; they have special meanings
+						on the browsers.
+						
+					// "F1",	// brings up help
+					"F2",
+					// "F3",	// brings up search
+					// "F4",	// address bar access on IE,
+					// "F5",	// refreshes the page
+					// "F6",	// address bar access on IE
+					// "F7",	// affects "caret browsing" on FF
+					"F8",
+					"F9",
+					// "F10",	// access File menu on IE
+					// "F11",	// full screen mode
+					// "F12"	// opens firebug console
+					*/
+				];
+
+				// Test a few normal keystrokes, but be careful about testing things
+				// that are entered using the SHIFT key as that produces two onkeypress
+				// events on IE (one for the SHIFT key and one for the character)
+				var printables = [" ", "n", "7"];
+
+				dojo.addOnLoad(function(){
+				doh.robot.initRobot('eventKeyPress.html');
+
+				var typer, 	// <input> that will receive keyboard events
+					events;	// array of events on typer, populated by dojo.connect() in eventKeyPress.html
+
+				doh.register("setup", function(){
+					typer = dojo.byId("typer");
+				});
+					
+				doh.register("navigation keys", dojo.map(navigation, function(code){
+					return {
+						name: code,
+						timeout: 1000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							events = dojo.global.events = [];
+							typer.focus();
+
+							// Send the keystroke
+							doh.robot.keyPress(dojo.keys[code], 50, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(1, events.length, "got (exactly) one onkeypress event");
+								doh.is(dojo.keys[code], events[0].charOrCode, "correct keycode");
+							}), 250);
+
+							return d;
+						}
+					};
+				}));
+
+				doh.register("normal keys", dojo.map(printables, function(c){
+					return {
+						name: "'" + c + "'",
+						timeout: 1000,
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							events = dojo.global.events = [];
+							typer.focus();
+
+							// Send the keystroke
+							doh.robot.keyPress(c, 50, {});
+
+							doh.robot.sequence(d.getTestCallback(function(){
+								doh.is(1, events.length, "got (exactly) one onkeypress event");
+								doh.is(c, events[0].charOrCode, "correct char");
+							}), 250);
+
+							return d;
+						}
+					};
+				}));
+
+				/*
+					TODO: test ctrl-key combinations if/when #9511 is fixed.
+					106:42, 
+					111:47, 
+					186:59, 
+					187:43, 
+					188:44, 
+					189:45, 
+					190:46, 
+					191:47, 
+					192:96, 
+					219:91, 
+					220:92, 
+					221:93, 
+					222:39 
+				*/
+
+				doh.register("ctrl-alphabetic", dojo.map("abcdefghijklmnopqrstuvwxyz", function(c){
+					return {
+						name: "ctrl-" + c,
+						timeout: 1000,
+						runTest: function(){
+							var d = new doh.Deferred();
+		
+							typer.focus();
+		
+							events = dojo.global.events = [];
+		
+							// Send the keystroke
+							doh.robot.keyPress(c, 50, {ctrl: true});
+		
+							doh.robot.sequence(d.getTestCallback(function(){
+								console.log("event is: ", events[0]);
+								doh.is(1, events.length, "got (exactly) one onkeypress event");
+								doh.is(c, events[0].charOrCode, "correct char");
+								doh.t(events[0].ctrlKey, "control key was pressed");
+							}), 250);
+		
+							return d;
+						}
+					};
+				}));
+
+				/* TODO: test preventDefault() of up/down arrows */
+				
+				/* TODO: ctrl-break, ctrl-enter */
+
+				/* TODO: Test preventDefault() (in eventKeyPress.html) stopping down arrow on <button> from scrolling page. */
+				
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dojo/tests/_base/fx.html b/dojo/tests/_base/fx.html
new file mode 100644
index 0000000..5cadb61
--- /dev/null
+++ b/dojo/tests/_base/fx.html
@@ -0,0 +1,567 @@
+<html>
+	<head>
+		<title>testing Core FX</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" 
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript" src="../../_base/fx.js"></script>
+		<script type="text/javascript">
+			var duration = 500;
+			var timeout = 750;
+			dojo.require("doh.runner");
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						{
+							name: "fadeOut",
+							timeout: timeout,
+							runTest: function(){
+								var opacity = dojo.style('foo', 'opacity');
+								doh.is(1, opacity);
+								var anim = dojo.fadeOut({ node: 'foo', duration: duration });
+								var d = new doh.Deferred();
+								dojo.connect(anim, "onEnd", d.getTestCallback(function(){
+									var opacity = dojo.style('foo', 'opacity');
+									var elapsed = (new Date()) - anim._start;
+									doh.is(0, opacity);
+									doh.t(elapsed >= duration);
+								}));
+								anim._start = new Date();
+								anim.play();
+								return d;
+							}
+						},
+						{
+							name: "fadeIn",
+							timeout: timeout,
+							runTest: function(){
+								var opacity = dojo.style('foo', 'opacity');
+								doh.is(0, opacity);
+								var anim = dojo.fadeIn({ node: 'foo', duration: duration });
+								var d = new doh.Deferred();
+								dojo.connect(anim, "onEnd", d.getTestCallback(function(){
+									var opacity = dojo.style('foo', 'opacity');
+									var elapsed = (new Date()) - anim._start;
+									doh.is(1, opacity);
+									doh.t(elapsed >= duration);
+								}));
+								anim._start = new Date();
+								anim.play();
+								return d;
+							}
+						},
+						{
+							name: "animateColor",
+							timeout: timeout,
+							runTest: function(){
+								var d = new doh.Deferred();
+								var anim = dojo.animateProperty({ 
+									node: "foo", 
+									duration: duration,
+									properties: { 
+										color: 				{ start: "black", end: "white" },
+										backgroundColor: 	{ start: "white", end: "black" } 
+									} 
+								});
+								dojo.connect(anim, "onEnd", anim, function(){
+									d.callback(true);
+								});
+								anim.play();
+								return d;
+							}
+						},
+						{
+							name: "animateColorBack",
+							timeout: timeout,
+							runTest: function(){
+								var d = new doh.Deferred();
+								var anim = dojo.animateProperty({ 
+									node: "foo", 
+									duration: duration,
+									properties: { 
+										color: 				{ end: "black" },
+										backgroundColor: 	{ end: "#5d81b4" }, 
+										letterSpacing: 		{ start: 0, end: 10 } 
+									} 
+								});
+								dojo.connect(anim, "onEnd", anim, function(){
+									d.callback(true);
+								});
+								anim.play();
+								return d;
+							}
+						},
+						{
+							name: "animateHeight",
+							timeout: timeout,
+							runTest: function(t){
+								dojo.byId("foo").style.height = "";
+								var startHeight = dojo.marginBox("foo").h; 
+								var endHeight = Math.round(startHeight / 2);
+								
+								var anim = dojo.animateProperty({
+									node: "foo",
+									properties: { height: { end: endHeight } },
+									duration: duration
+								});
+
+								var d = new doh.Deferred();
+
+								dojo.connect(anim, "onEnd", anim, d.getTestCallback(function(){
+									var elapsed = (new Date().valueOf()) - anim._startTime;
+									doh.t(elapsed >= duration);
+									var height = dojo.marginBox("foo").h; 
+									doh.is(height, endHeight);
+								}));
+								
+								anim.play();
+								return d;
+							}
+						},
+						{
+							name: "animateHeight_defaults_syntax",
+							timeout: timeout,
+							runTest: function(){
+								dojo.byId("foo").style.height = "";
+								var startHeight = dojo.marginBox("foo").h; 
+								var endHeight = Math.round(startHeight / 2);
+								
+								var anim = dojo.animateProperty({
+									node: "foo",
+									properties: { height: endHeight },
+									duration: duration
+								});
+
+								var d = new doh.Deferred();
+
+								dojo.connect(anim, "onEnd", anim, d.getTestCallback(function(){
+									var elapsed = (new Date().valueOf()) - anim._startTime;
+									doh.t(elapsed >= duration);
+									var height = dojo.marginBox("foo").h; 
+									doh.is(height, endHeight);
+								}));
+								
+								anim.play();
+								return d;
+							}
+						},
+						{
+							name: "inlineWidth",
+							timeout: timeout,
+							runTest: function(){
+								dojo.style("foo", "display", "none");
+								dojo.style("bar", "display", "");
+								var startWidth = dojo.marginBox("bar").w; 
+								var endWidth = Math.round(startWidth / 2);
+								
+								var anim = dojo.animateProperty({
+									node: "bar",
+									properties: { width: endWidth },
+									duration: duration
+								});
+
+								var d = new doh.Deferred();
+
+								dojo.connect(anim, "onEnd", anim, d.getTestCallback(function(){
+									var elapsed = (new Date().valueOf()) - anim._startTime;
+									doh.t(elapsed >= duration);
+									doh.is(dojo.marginBox("bar").w, endWidth);
+								}));
+								
+								anim.play();
+								return d;
+							}
+						},
+						{
+							name: "anim",
+							timeout: timeout+500,
+							runTest: function(){
+								var id = "baz";
+								dojo.style("bar", "display", "none");
+								dojo.style(id, "display", "");
+								var kickoff = new Date().valueOf();
+								var startWidth = dojo.marginBox(id).w; 
+								var endWidth = Math.round(startWidth / 2);
+
+								var d = new doh.Deferred();
+								var anim = dojo.anim(
+									id, 
+									{ 
+										width: endWidth,
+										opacity: 0
+									}, 
+									duration, 
+									null, 
+									d.getTestCallback(function(){
+										var curTime = (new Date().valueOf()),
+											elapsed = curTime - anim._startTime;
+										doh.t(elapsed >= duration, "test elapsed " + elapsed + " > duration " + duration);
+										
+										// -5 because on FF a setTimeout(foo, x) may fire a little before x
+										doh.t(curTime >= (kickoff+duration+500-5),
+											"curTime >= (kickoff+duration+500-5): " + curTime + " >= (" + kickoff + "+" + duration + "+500-5)");
+
+										doh.is(dojo.marginBox(id).w, endWidth, 
+											"width matches endWidth ");
+
+										doh.is(0, dojo.style(id, "opacity"), "opacity");
+									}),
+									500
+								);
+								return d;
+							}
+						},
+						{
+							name: "anim_defaults",
+							timeout: 1000,
+							runTest: function(){
+								var id = "thud";
+								dojo.style("baz", "display", "none");
+								dojo.style(id, "display", "");
+								var startWidth = dojo.marginBox(id).w; 
+								var endWidth = Math.round(startWidth / 2);
+
+								var d = new doh.Deferred();
+								var anim = dojo.anim(id, { width: endWidth });
+								dojo.connect(anim, "onEnd", d.getTestCallback(function(){
+									var elapsed = (new Date().valueOf()) - anim._startTime;
+									doh.t(elapsed >= dojo.Animation.prototype.duration); // the default
+									doh.is(dojo.marginBox(id).w, endWidth);
+								}));
+								anim.play();
+								return d;
+							}
+						},
+						{
+							// basic testing of a function for a property
+							name:"anim-fn-property",
+							timeout:1000,
+							runTest: function(){
+								
+								var d = new doh.Deferred();
+								dojo.animateProperty({
+									node: "thud",
+									properties:{
+										// also testing node passed to property function
+										padding: function(node){
+											d.getTestErrback(function(){
+												doh.is("thud", node.id);
+											});
+											return { end:15, start:22 };
+										}
+									},
+									duration:350,
+									onEnd: d.getTestCallback(function(){})
+								}).play();
+								return d;	
+							}
+						},
+						{
+							// just testing a property function which returns two other functions
+							name:"anim-fn-property-return-fn",
+							timeout:1000,
+							runTest: function(){
+								
+								var d = new doh.Deferred();
+								dojo.animateProperty({
+									node: "thud",
+									properties:{
+										// also testing node passed to property function
+										height: function(node){
+											d.getTestErrback(function(){
+												doh.is("thud", node.id);
+											});
+											return {
+												start: function(){ return 50; },
+												end: function(){ return 100; }
+											};
+										}
+									},
+									duration:350,
+									onEnd: d.getTestCallback(function(){})
+								}).play();
+								return d;	
+							}
+						},
+						{
+							// ensuring the end property can be a function
+							name:"anim-fn-prop-end",
+							timeout:1000,
+							runTest: function(){
+								
+								var d = new doh.Deferred();
+								dojo.animateProperty({
+									node: "thud",
+									properties:{
+										width: { 
+											// also testing node passed to end function
+											end: function(node){
+												d.getTestErrback(function(){
+													doh.is("thud", node.id);
+												});
+												return 100;
+											}
+										}
+									},
+									duration:50,
+									onEnd: d.getTestCallback(function(){})
+								}).play();
+								
+								return d;	
+							}
+						},
+						{
+							// ensuring the start property can be a function
+							name:"anim-fn-prop-start",
+							timeout:1000,
+							runTest: function(){
+								
+								var d = new doh.Deferred();
+								dojo.animateProperty({
+									node: "thud",
+									properties:{
+										width: { 
+											// also testing node passed to start function
+											start: function(node){
+												d.getTestErrback(function(){
+													doh.is("thud", node.id);
+												});
+												return 100;
+											},
+											end: 200
+										}
+									},
+									duration:50,
+									onEnd: d.getTestCallback(function(){})
+								}).play();
+								
+								return d;
+							}
+						},
+						{
+							// ensuring our node ref is passed onEnd:
+							name:"anim-onend-node",
+							timeout:1000,
+							runTest: function(){
+								
+								var d = new doh.Deferred();
+								dojo.animateProperty({
+									node: "thud",
+									properties:{
+										width: 200
+									},
+									duration:150,
+									onEnd:d.getTestCallback(function(node){
+										if(node){
+											doh.is("thud", node.id);
+										}
+									})
+								}).play();
+								
+								return d;	
+							}
+						},
+						{
+							// ensuring our node ref is passed to beforeBegin:
+							name:"anim-beforebegin-node",
+							timeout:1000,
+							runTest: function(){
+
+								var d = new doh.Deferred();
+								dojo.animateProperty({
+									node: "thud",
+									properties:{
+										width: 200
+									},
+									duration:50,
+									beforeBegin:d.getTestErrback(function(node){
+										doh.is("thud", node.id);
+									}),
+									onEnd:d.getTestCallback(function(node){})
+								}).play();
+
+								return d;	
+							}
+						},
+						{
+							name:"anim-onend-scope",
+							timeout:1000,
+							runTest: function(){
+								var d = new doh.Deferred();
+								dojo.declare("fx.Thinger", null, {
+									constructor: function(a){
+										this.bar = 10;
+									},
+									method: function(e){
+										d.callback(true);
+									}
+								});
+								
+								dojo.declare("fx.ThingerToo", fx.Thinger, {
+									method: function(){
+										var a = arguments;
+										dojo.fadeIn({
+											node:"thud",
+											onEnd: dojo.hitch(this, function(){
+												// to call inherited in a callback, stash the orig 'arguments'
+												this.inherited(a);
+											}),
+											duration:100
+										}).play()
+									}
+								});
+								
+								var x = new fx.ThingerToo();
+								x.method();
+								
+								return d;
+							}
+						},
+						{
+							name:"anim-onend-scope-natural",
+							timeout:1000,
+							runTest: function(){
+								var d = new doh.Deferred();
+
+								// testing vanilla inheritance
+								fx.NThinger = function(args){
+									dojo.mixin(this, args);
+								}
+								fx.NThinger.prototype.method = function(){
+									d.callback(true);
+								}
+								
+								
+								dojo.declare("fx.ThingerThree", fx.NThinger, {
+									method: function(){
+										var x = dojo.fadeOut({
+											node:"thud",
+											duration:100
+										});
+										
+										// to use with connect, pass a newArgs (arguements again) to override any 
+										// possible references passed from the orig function.
+										dojo.connect(x, "onEnd", dojo.hitch(this, "inherited", arguments, arguments));
+										
+										x.play();
+									}
+								});
+								
+								var x = new fx.ThingerThree();
+								x.method();
+								
+								return d;
+							}
+						}
+						
+					
+						
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css">
+			body {
+				margin: 1em;
+				background-color: #DEDEDE;
+			}
+
+			.box {
+				color: #292929;
+				/* color: #424242; */
+				/* text-align: left; */
+				width: 300px;
+				border: 1px solid #BABABA;
+				background-color: white;
+				padding-left: 10px;
+				padding-right: 10px;
+				margin-left: 10px;
+				-o-border-radius: 10px;
+				-moz-border-radius: 12px;
+				-webkit-border-radius: 10px;
+				/* -opera-border-radius: 10px; */
+				border-radius: 10px;
+				-moz-box-sizing: border-box;
+				-opera-sizing: border-box;
+				-webkit-box-sizing: border-box;
+				-khtml-box-sizing: border-box;
+				box-sizing: border-box;
+				overflow: hidden;
+				/* position: absolute; */
+			}
+		</style>
+	</head>
+	<body>
+		<h1>testing Core FX</h1>
+		<form name="testForm">
+		<input type="button" onClick="dojo.fadeOut({ node: 'foo', duration: 1000 }).play()" value="fade out"></input>
+		<input type="button" onClick="dojo.fadeIn({ node: 'foo', duration: 1000 }).play()" value="fade in"></input>
+		</form>
+		<div id="foo" class="box" style="float: left;">
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+			Proin porta rutrum lacus. Etiam consequat scelerisque quam. Nulla
+			facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+			semper iaculis.  Sed molestie tortor at ipsum. Morbi dictum rutrum
+			magna. Sed vitae risus.
+			</p>
+			<p>
+			Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer
+			lorem nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean
+			id mi in massa bibendum suscipit. Integer eros. Nullam suscipit
+			mauris. In pellentesque. Mauris ipsum est, pharetra semper,
+			pharetra in, viverra quis, tellus. Etiam purus. Quisque egestas,
+			tortor ac cursus lacinia, felis leo adipiscing nisi, et rhoncus
+			elit dolor eget eros. Fusce ut quam. Suspendisse eleifend leo vitae
+			ligula. Nulla facilisi. Nulla rutrum, erat vitae lacinia dictum,
+			pede purus imperdiet lacus, ut semper velit ante id metus. Praesent
+			massa dolor, porttitor sed, pulvinar in, consequat ut, leo. Nullam
+			nec est. Aenean id risus blandit tortor pharetra congue.
+			Suspendisse pulvinar.
+			</p>
+		</div>
+		<p id="bar" style="display: none;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper
+		sagittis velit. Cras in mi. Duis porta mauris ut ligula.  Proin porta
+		rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+		Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+		Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+		risus.
+		</p>
+		<p id="baz" style="display: none;">
+		Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+		imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+		nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+		massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+		pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+		quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+		felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+		quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+		rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+		semper velit ante id metus. Praesent massa dolor, porttitor sed,
+		pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+		tortor pharetra congue.  Suspendisse pulvinar.
+		</p>
+		<p id="thud" style="display: none;">
+		Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+		imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+		nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+		massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+		pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+		quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+		felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+		quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+		rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+		semper velit ante id metus. Praesent massa dolor, porttitor sed,
+		pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+		tortor pharetra congue.  Suspendisse pulvinar.
+		</p>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/fx.js b/dojo/tests/_base/fx.js
new file mode 100644
index 0000000..7b1174e
--- /dev/null
+++ b/dojo/tests/_base/fx.js
@@ -0,0 +1,4 @@
+dojo.provide("tests._base.fx");
+if(dojo.isBrowser){
+	doh.registerUrl("tests._base.fx", dojo.moduleUrl("tests", "_base/fx.html"), 15000);
+}
diff --git a/dojo/tests/_base/fx_delay.html b/dojo/tests/_base/fx_delay.html
new file mode 100644
index 0000000..c2a1cd9
--- /dev/null
+++ b/dojo/tests/_base/fx_delay.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<style type="text/css">
+#inner { width: 200px; height: 200px; background-color: #484}
+</style>
+<script type="text/javascript" src="../../dojo.js"></script>
+<script type="text/javascript">
+dojo.require("dojo._base.fx");
+dojo.require("dojo._base.html");
+dojo.addOnLoad(function(){
+	var box = dojo.byId("box");
+	dojo.connect(box, "onclick", function(){
+		dojo.style(box, "opacity", "0");
+		dojo.fadeIn({node:box, delay:1}).play();
+	});
+});
+</script>
+</head>
+<body>
+<div id="box"><button id="inner">click me</button></div>
+</body>
+</html>
diff --git a/dojo/tests/_base/html.html b/dojo/tests/_base/html.html
new file mode 100644
index 0000000..04e6285
--- /dev/null
+++ b/dojo/tests/_base/html.html
@@ -0,0 +1,797 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<!--
+	we use a strict-mode DTD to ensure that the box model is the same for these
+	basic tests
+-->
+<html>
+	<head>
+		<title>testing Core HTML/DOM/CSS/Style utils</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript"
+			src="../../dojo.js"
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+
+			function getIframeDocument(/*DOMNode*/iframeNode){
+				//summary: Returns the document object associated with the iframe DOM Node argument.
+				var doc = iframeNode.contentDocument || // W3
+					(
+						(iframeNode.contentWindow)&&(iframeNode.contentWindow.document)
+					) ||  // IE
+					(
+						(iframeNode.name)&&(document.frames[iframeNode.name])&&
+						(documendoh.frames[iframeNode.name].document)
+					) || null;
+				return doc;
+			}
+
+
+			dojo.addOnLoad(function(){
+				// IE gets confused by the iframe when you press Refresh so load them dynamically
+				var iframe_div = dojo.byId('iframe_div');
+				dojo.addOnWindowUnload(function(){
+					iframe_div.innerHTML = 'unloading';
+				});
+				setTimeout(function(){
+					iframe_div.innerHTML = '<iframe src="absStrictIframe.html" name="iframe_strict" id="iframe_strict" \
+						style="border:3px solid black; padding:4px; margin:5px; background-color:black;" \
+						scrolling=yes allowtransparency=true></iframe>\
+					<iframe src="absQuirksIframe.html" name="iframe_quirks" id="iframe_quirks" \
+						style="border:3px solid black; padding:4px; margin:5px; background-color:black;" \
+						scrolling=yes allowtransparency=true></iframe>'; //'balanced
+				}, 0);
+
+				doh.register("t",
+					[
+						"doh.is(null, dojo.byId('nonExistantId'));",
+						"doh.is(null, dojo.byId(null));",
+						"doh.is(null, dojo.byId(''));",
+						"doh.is(undefined, dojo.byId(undefined));",
+
+						"doh.is(100, dojo.marginBox('sq100').w);",
+						"doh.is(100, dojo.marginBox('sq100').h);",
+
+						"doh.is(120, dojo.marginBox('sq100margin10').w);",
+						"doh.is(120, dojo.marginBox('sq100margin10').h);",
+						"doh.is(100, dojo.contentBox('sq100margin10').w);",
+						"doh.is(100, dojo.contentBox('sq100margin10').h);",
+
+						"doh.is(140, dojo.marginBox('sq100margin10pad10').w);",
+						"doh.is(140, dojo.marginBox('sq100margin10pad10').h);",
+
+						"doh.is(120, dojo.marginBox('sq100pad10').w);",
+						"doh.is(120, dojo.marginBox('sq100pad10').h);",
+
+						"doh.is(110, dojo.marginBox('sq100ltpad10').w);",
+						"doh.is(110, dojo.marginBox('sq100ltpad10').h);",
+						"doh.is(100, dojo.contentBox('sq100ltpad10').w);",
+						"doh.is(100, dojo.contentBox('sq100ltpad10').h);",
+
+						"doh.is(120, dojo.marginBox('sq100ltpad10rbmargin10').w);",
+						"doh.is(120, dojo.marginBox('sq100ltpad10rbmargin10').h);",
+
+						"doh.is(120, dojo.marginBox('sq100border10').w);",
+						"doh.is(120, dojo.marginBox('sq100border10').h);",
+						"doh.is(100, dojo.contentBox('sq100border10').w);",
+						"doh.is(100, dojo.contentBox('sq100border10').h);",
+
+						"doh.is(140, dojo.marginBox('sq100border10margin10').w);",
+						"doh.is(140, dojo.marginBox('sq100border10margin10').h);",
+						"doh.is(100, dojo.contentBox('sq100border10margin10').w);",
+						"doh.is(100, dojo.contentBox('sq100border10margin10').h);",
+
+						"doh.is(160, dojo.marginBox('sq100border10margin10pad10').w);",
+						"doh.is(160, dojo.marginBox('sq100border10margin10pad10').h);",
+						"doh.is(100, dojo.contentBox('sq100border10margin10pad10').w);",
+						"doh.is(100, dojo.contentBox('sq100border10margin10pad10').h);",
+
+						// FIXME: the 'correct' w is not 100 on Safari WebKit (2.0.4 [419.3]), the right-margin extends to the document edge
+						// "doh.is(100, dojo.marginBox('sq100nopos').w);",
+						"doh.is(100, dojo.marginBox('sq100nopos').h);",
+
+						"doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).l);",
+						"doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).t);",
+						"doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).w);",
+						"doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).h);",
+
+						"doh.is(0, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).l);",
+						"doh.is(0, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).t);",
+						"doh.is(10, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).w);",
+						"doh.is(10, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).h);",
+
+						"doh.is(10, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).l);",
+						"doh.is(10, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).t);",
+						"doh.is(20, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).w);",
+						"doh.is(20, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).h);",
+
+						"doh.is(20, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).l);",
+						"doh.is(20, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).t);",
+						"doh.is(40, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).w);",
+						"doh.is(40, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).h);",
+
+						function scrollUp(){
+							dojo.doc.documentElement.scrollTop = 0;
+						},
+
+						function coordsBasic(t){
+							var pos = dojo.position("sq100", false);
+							// console.debug(pos);
+							doh.is(100, pos.x);
+							doh.is(100, pos.y);
+							doh.is(100, pos.w);
+							doh.is(100, pos.h);
+						},
+						function coordsMargin(t){
+							// position() is getting us the border-box location
+							var pos = dojo.position("sq100margin10", false);
+							doh.is(260, pos.x);
+							doh.is(110, pos.y);
+							doh.is(100, pos.w);
+							doh.is(100, pos.h);
+							pos = dojo.marginBox("sq100margin10");
+							doh.is(120, pos.w);
+							doh.is(120, pos.h);
+							// Though coords shouldn't be used, test it for backward compatibility.
+							// coords returns the border-box location and margin-box size
+							pos = dojo.coords("sq100margin10", false);
+							doh.is(260, pos.x);
+							doh.is(110, pos.y);
+							doh.is(120, pos.w);
+							doh.is(120, pos.h);
+						},
+						function coordsBorder(t){
+							var pos = dojo.position("sq100border10", false);
+							doh.is(100, pos.x);
+							doh.is(400, pos.y);
+						},
+						function sq100nopos(t){
+							var pos = dojo.position("sq100nopos", false);
+							// console.debug(pos);
+							doh.is(0, pos.x);
+							doh.t(pos.y > 0);
+							// FIXME: the 'correct' w is not 100 on Safari WebKit (2.0.4 [419.3]), the right-margin extends to the document edge
+							// doh.is(100, pos.w);
+							doh.is(100, pos.h);
+						},
+						function coordsScrolled(t) {
+							var s = document.createElement('div');
+							var c = document.createElement('div');
+							document.body.appendChild(s);
+							s.appendChild(c);
+							var x=257, y= 285;
+							with (s.style) {
+								position = 'absolute';
+								overflow = 'scroll';
+								border = "10px solid black";
+							}
+							dojo._setMarginBox(s, x, y, 100, 100);
+							dojo._setMarginBox(c, 0, 0, 500, 500);
+							s.scrollTop = 200;
+							var pos = dojo.position(s, true);
+							doh.is(x, pos.x);
+							doh.is(y, pos.y);
+						},
+						{
+							name: "coordsIframe",
+							timeout: 2000,
+							runTest: function(){
+								var def = new doh.Deferred();
+								setTimeout(function(){ try{
+									var oldLtr = dojo._isBodyLtr();
+									var oldQuirks = dojo.isQuirks;
+									dojo.withGlobal(dojo.byId('iframe_quirks').win, function(){
+										doh.t(dojo.isQuirks, "isQuirks == true in quirks/iframe");
+										doh.f(dojo._isBodyLtr(), "isBodyLtr == false in RTL/iframe");
+									        var pos = dojo.position('iframe_00_quirks');
+										doh.t(pos.x===0, "quirks iframe element x == 0 (x,y,w,h="+pos.x+","+pos.y+","+pos.w+","+pos.h+")");
+										doh.t(pos.y===0, "quirks iframe element y == 0 (x,y,w,h="+pos.x+","+pos.y+","+pos.w+","+pos.h+")");
+										doh.t(pos.w>0, "quirks iframe element w > 0 (x,y,w,h="+pos.x+","+pos.y+","+pos.w+","+pos.h+")");
+										doh.t(pos.h>0, "quirks iframe element h > 0 (x,y,w,h="+pos.x+","+pos.y+","+pos.w+","+pos.h+")");
+									});
+									dojo.withGlobal(dojo.byId('iframe_strict').win, function(){
+										doh.f(dojo.isQuirks, "isQuirks == false in strict/ifraee");
+										doh.f(dojo._isBodyLtr(), "isBodyLtr == false in RTL/iframe");
+									        var pos = dojo.position('iframe_00_strict');
+										doh.t(pos.x===0, "strict iframe element x == 0 (x,y,w,h="+pos.x+","+pos.y+","+pos.w+","+pos.h+")");
+										doh.t(pos.y===0, "strict iframe element y == 0 (x,y,w,h="+pos.x+","+pos.y+","+pos.w+","+pos.h+")");
+										doh.t(pos.w>0, "strict iframe element w > 0 (x,y,w,h="+pos.x+","+pos.y+","+pos.w+","+pos.h+")");
+										doh.t(pos.h>0, "strict iframe element h > 0 (x,y,w,h="+pos.x+","+pos.y+","+pos.w+","+pos.h+")");
+									});
+									doh.t(!oldLtr == !dojo._isBodyLtr(), "isBodyLtr restored after withGlobal");
+									doh.t(!oldQuirks == !dojo.isQuirks, "isQuirks restored after withGlobal");
+									def.callback(true);
+								}catch(e){ def.errback(e); } }, 1000);
+								return def;
+							}
+						},
+						"doh.is(1, dojo.style('sq100nopos', 'opacity'));",
+						"doh.is(0.1, dojo.style('sq100nopos', 'opacity', 0.1));",
+						"doh.is(0.8, dojo.style('sq100nopos', 'opacity', 0.8));",
+						function styleObject(){
+							dojo.style('sq100nopos', { 'opacity': 0.1 });
+							doh.is(0.1, dojo.style('sq100nopos', 'opacity'));
+							dojo.style('sq100nopos', { 'opacity': 0.8 });
+							doh.is(0.8, dojo.style('sq100nopos', 'opacity'));
+						},
+						"doh.is('static', dojo.style('sq100nopos', 'position'));",
+						function getBgcolor(t){
+							var bgc = dojo.style('sq100nopos', 'backgroundColor');
+							doh.t((bgc == "rgb(0, 0, 0)")||(bgc == "black")||(bgc == "#000000"));
+						},
+						function isDescendant(t){
+							doh.t(dojo.isDescendant("sq100", dojo.body()));
+							doh.t(dojo.isDescendant("sq100", dojo.doc));
+							doh.t(dojo.isDescendant("sq100", "sq100"));
+							doh.t(dojo.isDescendant(dojo.byId("sq100"), "sq100"));
+							doh.f(dojo.isDescendant("sq100", dojo.byId("sq100").firstChild));
+							doh.t(dojo.isDescendant(dojo.byId("sq100").firstChild, "sq100"));
+						},
+						function isDescendantIframe(t){
+							var bif = dojo.byId("blah");
+							// this test barely makes sense. disabling it for now.
+							// doh.t(dojo.isDescendant(bif.contentDocument.getElementById("subDiv"), bif.parentNode));
+							var subDiv = getIframeDocument(bif).getElementById("subDiv");
+							doh.t(dojo.isDescendant(subDiv, subDiv));
+							doh.t(dojo.isDescendant(subDiv, subDiv.parentNode));
+							doh.f(dojo.isDescendant(subDiv.parentNode, subDiv));
+
+						},
+						function testClassFunctions(t){
+							var node = dojo.byId("sq100");
+							dojo.addClass(node, "a");
+							doh.is("a", node.className, "class is a");
+							dojo.removeClass(node, "c");
+							doh.is("a", node.className, "class is still a");
+							t.assertTrue(dojo.hasClass(node, "a"), "class is a, test for a");
+							t.assertFalse(dojo.hasClass(node, "b"), "class is a, test for b");
+							dojo.addClass(node, "b");
+							doh.is("a b", node.className, "class is a b");
+							t.assertTrue(dojo.hasClass(node, "a"), "class is a b, test for a");
+							t.assertTrue(dojo.hasClass(node, "b"), "class is a b, test for b");
+							dojo.removeClass(node, "a");
+							doh.is("b", node.className, "class is b");
+							t.assertFalse(dojo.hasClass(node, "a"), "class is b, test for a");
+							t.assertTrue(dojo.hasClass(node, "b"), "class is b, test for b");
+							dojo.toggleClass(node, "a");
+							doh.is("b a", node.className, "class is b a");
+							t.assertTrue(dojo.hasClass(node, "a"), "class is b a, test for a");
+							t.assertTrue(dojo.hasClass(node, "b"), "class is b a, test for b");
+							dojo.toggleClass(node, "a");
+							doh.is("b", node.className, "class is b (again)");
+							t.assertFalse(dojo.hasClass(node, "a"), "class is b (again), test for a");
+							t.assertTrue(dojo.hasClass(node, "b"), "class is b (again), test for b");
+							dojo.toggleClass(node, "b");
+							doh.is("", node.className, "class is blank");
+							t.assertFalse(dojo.hasClass(node, "a"), "class is blank, test for a");
+							t.assertFalse(dojo.hasClass(node, "b"), "class is blank, test for b");
+							dojo.removeClass(node, "c");
+							t.assertTrue(!node.className, "no class");
+							var acuWorked = true;
+							try{
+								dojo.addClass(node);
+							}catch(e){
+								acuWorked = false;
+							}
+							doh.is(true, acuWorked, "addClass handles undefined class");
+						},
+						function testAddRemoveClassMultiple(t){
+							var node = dojo.byId("sq100");
+							dojo.addClass(node, "a");
+							t.is("a", node.className, "class is a");
+							dojo.addClass(node, "a b");
+							t.is("a b", node.className, "class is a b");
+							dojo.addClass(node, "b a");
+							t.is("a b", node.className, "class is still a b");
+							dojo.addClass(node, ["a", "c"]);
+							t.is("a b c", node.className, "class is a b c");
+							dojo.removeClass(node, "c a");
+							t.is("b", node.className, "class is b");
+							dojo.removeClass(node);
+							t.is("", node.className, "empty class");
+							dojo.addClass(node, "  c   b   a ");
+							t.is("c b a", node.className, "class is c b a");
+							dojo.removeClass(node, " c b ");
+							t.is("a", node.className, "class is a");
+							dojo.removeClass(node, ["a", "c"]);
+							t.is("", node.className, "empty class");
+						},
+						function getTypeInput(t){
+							doh.f(dojo.hasAttr(dojo.byId("input-no-type"), "type"));
+							doh.is(null, dojo.attr(dojo.byId("input-no-type"), "type"));
+							doh.t(dojo.hasAttr(dojo.byId("input-with-type"), "type"));
+							doh.is("checkbox", dojo.attr(dojo.byId("input-with-type"), "type"));
+						},
+						function getWithString(t){
+							doh.f(dojo.hasAttr("input-no-type", "type"));
+							doh.is(null, dojo.attr("input-no-type", "type"));
+							doh.t(dojo.hasAttr("input-with-type", "type"));
+							doh.is("checkbox", dojo.attr("input-with-type", "type"));
+						},
+						function attrId(t){
+							doh.t(dojo.hasAttr("div-no-tabindex", "id"));
+							doh.is("div-no-tabindex", dojo.attr("div-no-tabindex", "id"));
+							var div = document.createElement("div");
+							doh.f(dojo.hasAttr(div, "id"));
+							doh.is(null, dojo.attr(div, "id"));
+							dojo.attr(div, "id", "attrId1");
+							doh.t(dojo.hasAttr(div, "id"));
+							doh.is("attrId1", dojo.attr(div, "id"));
+							dojo.removeAttr(div, "id");
+							doh.f(dojo.hasAttr(div, "id"));
+							doh.is(null, dojo.attr(div, "id"));
+						},
+						function getTabindexDiv(t){
+							doh.f(dojo.hasAttr("div-no-tabindex", "tabIndex"));
+							doh.t(dojo.attr("div-no-tabindex", "tabIndex") <= 0);
+							doh.t(dojo.hasAttr("div-tabindex-minus-1", "tabIndex"));
+							if(!dojo.isOpera){
+								// Opera (at least <= 9) does not support tabIndex="-1"
+								doh.is(-1, dojo.attr("div-tabindex-minus-1", "tabIndex"));
+							}
+							doh.t(dojo.hasAttr("div-tabindex-0", "tabIndex"));
+							doh.is(0, dojo.attr("div-tabindex-0", "tabIndex"));
+							doh.is(1, dojo.attr("div-tabindex-1", "tabIndex"));
+						},
+						function getTabindexInput(t){
+							if(!dojo.isIE || dojo.isIE >= 8){
+								// IE6/7 always reports tabIndex as defined
+								doh.f(dojo.hasAttr("input-no-tabindex", "tabIndex"));
+								doh.f(dojo.attr("input-no-tabindex", "tabIndex"));
+							}
+							doh.t(dojo.hasAttr("input-tabindex-minus-1", "tabIndex"));
+							if(!dojo.isOpera){
+								// Opera (at least <= 9) does not support tabIndex="-1"
+								doh.is(-1, dojo.attr("input-tabindex-minus-1", "tabIndex"));
+							}
+							doh.t(dojo.hasAttr("input-tabindex-0", "tabIndex"));
+							doh.is(0, dojo.attr("input-tabindex-0", "tabIndex"));
+							doh.is(1, dojo.attr("input-tabindex-1", "tabIndex"));
+						},
+						function setTabindexDiv(t){
+							var div = document.createElement("div");
+							doh.is(null, dojo.attr(div, "tabIndex"));
+							dojo.attr(div, "tabIndex", -1);
+							if(!dojo.isOpera){
+								// Opera (at least <= 9) does not support tabIndex="-1"
+								doh.is(-1, dojo.attr(div, "tabIndex"));
+							}
+							dojo.attr(div, "tabIndex", 0);
+							doh.is(0, dojo.attr(div, "tabIndex"));
+							dojo.attr(div, "tabIndex", 1);
+							doh.is(1, dojo.attr(div, "tabIndex"));
+						},
+						function setTabindexInput(t){
+							var input = document.createElement("input");
+							doh.t(dojo.attr(input, "tabIndex") <= 0);
+							dojo.attr(input, "tabIndex", -1);
+							if(!dojo.isOpera){
+								// Opera (at least <= 9) does not support tabIndex="-1"
+								doh.is(-1, dojo.attr(input, "tabIndex"));
+							}
+							dojo.attr(input, "tabIndex", 0);
+							doh.is(0, dojo.attr(input, "tabIndex"));
+							dojo.attr(input, "tabIndex", 1);
+							doh.is(1, dojo.attr(input, "tabIndex"));
+						},
+						function removeTabindexFromDiv(t){
+							var div = document.createElement("div");
+							dojo.attr(div, "tabIndex", 1);
+							doh.is(1, dojo.attr(div, "tabIndex"));
+							dojo.removeAttr(div, "tabIndex");
+							doh.is(null, dojo.attr(div, "tabIndex"));
+						},
+						function removeDisabledFromInput(t){
+							var input = document.createElement("input");
+							dojo.attr(input, "disabled", true);
+							doh.t(dojo.attr(input, "disabled"));
+							dojo.removeAttr(input, "disabled");
+							doh.f(dojo.attr(input, "disabled"));
+						},
+						function removeTabindexFromInput(t){
+							var input = document.createElement("input");
+							dojo.attr(input, "tabIndex", 1);
+							doh.is(1, dojo.attr(input, "tabIndex"));
+							dojo.removeAttr(input, "tabIndex");
+							doh.is(null, dojo.attr(input, "tabIndex"));
+						},
+						function setReadonlyInput(t){
+							var input = document.createElement("input");
+							doh.f(dojo.attr(input, "readonly"));
+							dojo.attr(input, "readonly", true);
+							doh.is(true, dojo.attr(input, "readonly"));
+							dojo.attr(input, "readonly", false);
+							doh.is(false, dojo.attr(input, "readonly"));
+						},
+						function attr_map(t){
+							var input = document.createElement("input");
+							var ctr= 0;
+							dojo.attr(input, {
+								"class": "thinger blah",
+								"tabIndex": 1,
+								"type": "text",
+								"onfocus": function(e){
+									ctr++;
+								}
+							});
+							dojo.body().appendChild(input);
+							doh.is(1, dojo.attr(input, "tabIndex"), "tabIndex");
+							if(!dojo.isIE || dojo.isIE > 7){
+								// IE6/7 treats type="text" as missing, even if it was
+								// explicitly specified
+								doh.is("text", dojo.attr(input, "type"), "type");
+							}
+							doh.is(0, ctr, "onfocus ctr == 0");
+							doh.t(dojo.hasClass(input, "thinger"), "hasClass of thinger");
+							doh.t(dojo.hasClass(input, "blah"), "hasClass of blah");
+							var def = new doh.Deferred();
+							input.focus();
+							setTimeout(function(){
+								doh.is(1, ctr, "onfocus ctr == 1");
+								input.blur();
+								input.focus();
+								setTimeout(function(){
+									doh.is(2, ctr, "onfocus ctr == 2");
+									def.callback(true);
+								}, 10);
+							}, 10);
+							return def;
+						},
+						function attr_reconnect(t){
+							var input = document.createElement("input");
+							var ctr = 0;
+							dojo.attr(input, "type", "text");
+							dojo.attr(input, "onfocus", function(e){ ctr++; });
+							dojo.attr(input, "onfocus", function(e){ ctr++; });
+							dojo.attr(input, "onfocus", function(e){ ctr++; });
+							dojo.body().appendChild(input);
+							if(!dojo.isIE || dojo.isIE > 7){
+								// IE6/7 treats type="text" as missing, even if it was
+								// explicitly specified
+								doh.is("text", dojo.attr(input, "type"));
+							}
+							doh.is(0, ctr);
+							var def = new doh.Deferred();
+							input.focus();
+							setTimeout(function(){
+								doh.is(1, ctr);
+								input.blur();
+								input.focus();
+								setTimeout(function(){
+									doh.is(2, ctr);
+									def.callback(true);
+								}, 10);
+							}, 10);
+							return def;
+						},
+						function attrSpecials(){
+							var node = document.createElement("div");
+							dojo.body().appendChild(node);
+							dojo.attr(node, {
+								style: {
+									opacity: 0.5,
+									width: "30px",
+									border: "1px solid black"
+								}
+							});
+							doh.is(0.5, dojo.style(node, "opacity"));
+							doh.is(30, dojo.style(node, "width"));
+							doh.is(1, dojo.style(node, "borderWidth"));
+							dojo.attr(node, {
+								innerHTML: "howdy!"
+							});
+							doh.is("howdy!", node.innerHTML);
+							doh.is("howdy!", dojo.attr(node, "innerHTML"));
+							dojo.attr(node, "innerHTML", "<span>howdy!</span>");
+							doh.is(1, node.firstChild.nodeType);
+							doh.is("span", node.firstChild.nodeName.toLowerCase());
+							doh.is("<span>howdy!</span>", node.innerHTML.toLowerCase());
+							doh.is("<span>howdy!</span>", dojo.attr(node, "innerHTML").toLowerCase());
+						},
+						function testLabelForAttr(t){
+							// create label with no for attribute make sure requesting
+							// it as for and html for returns null
+							var label = document.createElement("label");
+							if(!dojo.isIE){
+								// IE always assumes that "for" is present
+								doh.f(dojo.attr(label, "for"));
+								doh.f(dojo.attr(label, "htmlFor"));
+							}
+							// add a for attribute and test that can get by requesting for
+							dojo.attr(label, "for", "testId");
+							doh.is("testId", dojo.attr(label, "for"));
+							// add as htmlFor and make sure it is returned when requested as htmlFor
+							var label2 = document.createElement("label");
+							dojo.attr(label2, "htmlFor", "testId2");
+							doh.is("testId2", dojo.attr(label2, "htmlFor"));
+							// check than when requested as for or htmlFor attribute is found
+							doh.t(dojo.hasAttr(label, "for"));
+							doh.t(dojo.hasAttr(label2, "htmlfor"));
+							// test from markup
+							var labelNoFor = dojo.byId("label-no-for");
+							// make sure testing if has attribute using for or htmlFor 
+							// both return null when no value set
+							if(!dojo.isIE){
+								// IE always assumes that "for" is present
+								doh.f(dojo.hasAttr(labelNoFor, "for"));
+								doh.f(dojo.hasAttr(labelNoFor, "htmlFor"));
+							}
+							var labelWithFor = dojo.byId("label-with-for");
+							// when markup includes for make certain testing if has attribute
+							// using for or htmlFor returns true
+							doh.t(dojo.hasAttr(labelWithFor, "for"));
+							doh.t(dojo.hasAttr(labelWithFor, "htmlFor"));
+							// when markup include for attrib make sure can retrieve using for or htmlFor
+							doh.is("input-with-label", dojo.attr(labelWithFor, "for"));
+							doh.is("input-with-label", dojo.attr(labelWithFor, "htmlFor"));
+						},
+						function attrInnerHtmlDiv(t){
+							var n = dojo.create("div", {
+									innerHTML: "1<em>2</em>3"
+								}, dojo.body());
+							doh.is("1<em>2</em>3", n.innerHTML.toLowerCase());
+							dojo.destroy(n);
+						},
+						function attrInnerHtmlTable(t){
+							var n = dojo.create("table", {
+									innerHTML: "<thead><tr><th>1st!</th></tr></thead><tbody></tbody>"
+								}, dojo.body());
+							doh.is("<thead><tr><th>1st!</th></tr></thead><tbody></tbody>",
+								n.innerHTML.toLowerCase().replace(/\s+/g, ""));
+							dojo.destroy(n);
+						},
+						function attrInputTextValue(t){
+							doh.is("123", dojo.byId("input-text-value").value);
+							doh.is("123", dojo.attr("input-text-value", "value"));
+							dojo.attr("input-text-value", "value", "abc");
+							doh.is("abc", dojo.byId("input-text-value").value);
+							doh.is("abc", dojo.attr("input-text-value", "value"));
+							dojo.byId("input-text-value").value = "xyz";
+							doh.is("xyz", dojo.byId("input-text-value").value);
+							doh.is("xyz", dojo.attr("input-text-value", "value"));
+							dojo.byId("input-text-value").value = "123"; // fixes initialization problem when the test is reloaded
+						},
+						function testInputDisabled(t){
+							doh.f(dojo.attr("input-no-disabled", "disabled"));
+							doh.t(dojo.attr("input-with-disabled", "disabled"));
+							doh.t(dojo.attr("input-with-disabled-true", "disabled"));
+						},
+						function testIframeDestroy10095(t){
+							var iframeWin = dojo.byId('10095_iframe').win;
+							doh.t(!iframeWin.document.getElementById('10095_textbox'), "reloaded iframe element destroyed");
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css">
+			html, body {
+				padding: 0px;
+				margin: 0px;
+				border: 0px;
+			}
+
+			#sq100 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 100px;
+				top: 100px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding: 0px;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#sq100margin10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 250px;
+				top: 100px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding: 0px;
+				margin: 10px;
+				overflow: hidden;
+			}
+
+			#sq100margin10pad10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 400px;
+				top: 100px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding: 10px;
+				margin: 10px;
+				overflow: hidden;
+			}
+
+			#sq100pad10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 100px;
+				top: 250px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding: 10px;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#sq100ltpad10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 250px;
+				top: 250px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding-left: 10px;
+				padding-top: 10px;
+				padding-right: 0px;
+				padding-bottom: 0px;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#sq100ltpad10rbmargin10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 400px;
+				top: 250px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding-left: 10px;
+				padding-top: 10px;
+				padding-right: 0px;
+				padding-bottom: 0px;
+				margin-left: 0px;
+				margin-top: 0px;
+				margin-right: 10px;
+				margin-bottom: 10px;
+				overflow: hidden;
+			}
+
+			#sq100border10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 100px;
+				top: 400px;
+				width: 100px;
+				height: 100px;
+				border: 10px solid yellow;
+				padding: 0px;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#sq100border10margin10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 250px;
+				top: 400px;
+				width: 100px;
+				height: 100px;
+				border: 10px solid yellow;
+				padding: 0px;
+				margin: 10px;
+				overflow: hidden;
+			}
+
+			#sq100border10margin10pad10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 400px;
+				top: 400px;
+				width: 100px;
+				height: 100px;
+				border: 10px solid yellow;
+				padding: 10px;
+				margin: 10px;
+				overflow: hidden;
+			}
+
+			#sq100nopos {
+				background-color: black;
+				color: white;
+				width: 100px;
+				height: 100px;
+				padding: 0px;
+				margin: 0px;
+			}
+
+		</style>
+	</head>
+	<body>
+		<h1>testing Core HTML/DOM/CSS/Style utils</h1>
+		<div id="sq100">
+			100px square, abs
+		</div>
+		<div id="sq100margin10">
+			100px square, abs, 10px margin
+		</div>
+		<div id="sq100margin10pad10">
+			100px square, abs, 10px margin, 10px padding
+		</div>
+		<div id="sq100pad10">
+			100px square, abs, 10px padding
+		</div>
+		<div id="sq100ltpad10">
+			100px square, abs, 10px left and top padding
+		</div>
+		<div id="sq100ltpad10rbmargin10">
+			100px square, abs, 10px left and top padding, 10px bottom and right margin
+		</div>
+		<div id="sq100border10">
+			100px square, abs, 10px yellow border
+		</div>
+		<div id="sq100border10margin10">
+			100px square, abs, 10px yellow border, 10px margin
+		</div>
+		<div id="sq100border10margin10pad10">
+			100px square, abs, 10px yellow border, 10px margin, 10px padding
+		</div>
+		<div id="sq100nopos">
+			100px square, no positioning
+		</div>
+
+		<iframe id="blah" name="blah" src="javascript:'<html&gt<body><div id=subDiv></div></body></html>'"></iframe>
+
+		<script type="text/javascript">
+		var reloaded = false;
+		function iframe10095loaded() {
+			var iframeWin = dojo.byId('10095_iframe').win;
+			dojo.withGlobal(iframeWin, function(){ dojo.destroy(dojo.byId('10095_textbox')) });
+			if(!reloaded){
+				reloaded = true;
+				dojo.byId('10095_iframe').src=iframeWin.frameElement.src;
+			}
+		}
+		</script>
+		<iframe id="10095_iframe" style="display:none;" src="javascript:'<html><head><script>frameElement.win=window</script></head><body><input id=10095_textbox></body></html>'" onload="dojo.addOnLoad(iframe10095loaded)"></iframe>
+
+		<div id='iframe_div' style="position:absolute;top:0;left:500px;"></div>
+
+		<div id="div-no-tabindex"></div>
+		<div id="div-tabindex-minus-1" tabIndex="-1"></div>
+		<div id="div-tabindex-0" tabIndex="0"></div>
+		<div id="div-tabindex-1" tabIndex="1"></div>
+
+		<div>
+			<input id="input-no-type">
+			<input id="input-with-type" type="checkbox">
+			<input id="input-no-tabindex">
+			<input id="input-tabindex-minus-1" tabIndex="-1">
+			<input id="input-tabindex-0" tabIndex="0">
+			<input id="input-tabindex-1" tabIndex="1">
+			<input id="input-text-value" type="text" value="123">
+			<input id="input-no-disabled" type="text">
+			<input id="input-with-disabled" type="text" disabled>
+			<input id="input-with-disabled-true" disabled="disabled">
+		</div>
+		<div>
+			<label id="label-no-for">label with no for </label><input type="text" id="label-test-input">
+			<label id="label-with-for" for="input-with-label">label with for </label><input type="text" id="input-with-label">
+		</div>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/html.js b/dojo/tests/_base/html.js
new file mode 100644
index 0000000..11fe36b
--- /dev/null
+++ b/dojo/tests/_base/html.js
@@ -0,0 +1,12 @@
+dojo.provide("tests._base.html");
+if(dojo.isBrowser){
+	doh.registerUrl("tests._base.html", dojo.moduleUrl("tests", "_base/html.html"), 15000);
+	doh.registerUrl("tests._base.html_id", dojo.moduleUrl("tests", "_base/html_id.html"), 15000);
+	doh.registerUrl("tests._base.html_element", dojo.moduleUrl("tests", "_base/html_element.html"), 15000);
+	doh.registerUrl("tests._base.html_rtl", dojo.moduleUrl("tests", "_base/html_rtl.html"), 15000);
+	doh.registerUrl("tests._base.html_quirks", dojo.moduleUrl("tests", "_base/html_quirks.html"), 15000);
+	doh.registerUrl("tests._base.html_box", dojo.moduleUrl("tests", "_base/html_box.html"), 35000);
+	doh.registerUrl("tests._base.html_box_quirks", dojo.moduleUrl("tests", "_base/html_box_quirks.html"), 35000);
+	doh.registerUrl("tests._base.html_isBodyLtr", dojo.moduleUrl("tests", "_base/html_isBodyLtr.html"), 35000);
+	doh.registerUrl("tests._base.html_docScroll", dojo.moduleUrl("tests", "_base/html_docScroll.html"), 35000);
+}
diff --git a/dojo/tests/_base/html_box.html b/dojo/tests/_base/html_box.html
new file mode 100644
index 0000000..6d34f9c
--- /dev/null
+++ b/dojo/tests/_base/html_box.html
@@ -0,0 +1,207 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"	"http://www.w3.org/TR/html4/strict.dtd">
+<!--
+	we use a strict-mode DTD to ensure that the box model is the same for these
+	basic tests
+-->
+<html>
+	<head>
+		<title> test html.js Box utils</title>
+		<style type="text/css">
+			/*@import "../../resources/dojo.css";*/
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" 
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			
+			var margin = '1px';
+			var border = '3px solid black';
+			var padding = '5px';
+			var defaultStyles = {
+				height: '100px',
+				width: '100px',
+				position: 'absolute',
+				backgroundColor: 'red'
+			};
+			
+			var defaultChildStyles = {
+				height: '20px',
+				width: '20px',
+				backgroundColor: 'blue'
+			}
+			
+			var testStyles = [
+				{},
+				{margin: margin},
+				{border: border},
+				{padding: padding},
+				{margin: margin, border: border},
+				{margin: margin, padding: padding},
+				{border: border, padding: padding},
+				{margin: margin, border: border, padding: padding}			
+			]
+			
+			
+			function sameBox(inBox1, inBox2) {
+				for (var i in inBox1)
+					if (inBox1[i] != inBox2[i]) {
+						console.log((arguments[2]||'box1') + '.' + i + ': ', inBox1[i], ' != ', (arguments[3]||'box2') + '.' + i + ': ', inBox2[i]);
+						return false;
+					}	
+				return true;		
+			}
+			
+			function reciprocalMarginBoxTest(inNode, inBox) {
+				var s = inBox || dojo.marginBox(inNode);
+				dojo.marginBox(inNode, s);
+				var e = dojo.marginBox(inNode);
+				return sameBox(s, e);
+			}
+			
+			function fitTest(inParent, inChild) {
+				var pcb = dojo.contentBox(inParent);
+				return reciprocalMarginBoxTest(inChild, pcb);
+			}
+			
+			function createStyledElement(inStyle, inParent, inElement, inNoDefault) {
+				inStyle = inStyle||{};
+				if (!inNoDefault) {
+					for (var i in defaultStyles)
+						if (!inStyle[i])
+							inStyle[i] = defaultStyles[i];
+				}			
+				var n = document.createElement(inElement || 'div');
+				(inParent||document.body).appendChild(n);
+				dojo.mixin(n.style, inStyle);
+				return n;				
+			}
+			
+			var _testTopInc = 0;
+			var _testTop = 150;
+			var _testInitTop = 250;
+			function styleIncTop(inStyle) {
+				inStyle = dojo.mixin({}, inStyle||{});
+				inStyle.top = (_testInitTop + _testTop*_testTopInc) + 'px';
+				_testTopInc++;
+				return inStyle;
+			}
+			
+			function removeTestNode(inNode) {
+				// leave nodes for inspection or don't return to delete them
+				return;
+				inNode = dojo.byId(inNode);
+				inNode.parentNode.removeChild(inNode);
+				_testTopInc--;
+			}
+			
+			function testAndCallback(inTest, inAssert, inComment, inOk, inErr) {
+				inTest.assertTrue('/* ' + inComment +  '*/' + inAssert);
+				if (inAssert)
+					inOk&&inOk();
+				else
+					inErr&&inErr();	
+			}
+			
+			// args are (styles, parent, element name, no default)
+			function mixCreateElementArgs(inMix, inArgs) {
+				args = [{}];
+				if (inArgs&&inArgs[0])
+					dojo.mixin(args[0], inArgs[0]);
+				if (inMix.length)
+					dojo.mixin(args[0], inMix[0]||{});
+				// parent comes from source
+				if (inMix.length > 1)
+					args[1] = inMix[1];
+				args[2] = inArgs[2];
+				args[3] = inArgs[3]	
+				return args;	
+			};
+			
+			function createStyledNodes(inArgs, inFunc) {
+				for (var i=0, n; (s=testStyles[i]); i++) {
+					n = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inArgs));
+					inFunc&&inFunc(n);
+				}	
+			}
+			
+			function createStyledParentChild(inParentArgs, inChildArgs, inFunc) {
+				for (var i=0, s, p, c; (s=testStyles[i]); i++) {
+					p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+					c = createStyledElement.apply(this, mixCreateElementArgs([{}, p], inChildArgs));
+					inFunc&&inFunc(p, c);
+				}	
+			}
+			
+			function createStyledParentChildren(inParentArgs, inChildArgs, inFunc) {
+				for (var i=0, s, p; (s=testStyles[i]); i++)
+					for (var j=0, sc, c, props; (sc=testStyles[j]); j++) {
+						p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+						c = createStyledElement.apply(this, mixCreateElementArgs([sc, p], inChildArgs));
+						inFunc&&inFunc(p, c);
+					}	
+				
+				for (var i=0, s, p, c; (s=testStyles[i]); i++) {
+					p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+					c = createStyledElement.apply(this, mixCreateElementArgs([{}, p], inChildArgs));
+					inFunc&&inFunc(p, c);
+				}	
+			}
+			
+			
+			function runFitTest(inTest, inParentStyles, inChildStyles) {
+				createStyledParentChildren([inParentStyles], [inChildStyles], function(p, c) {
+					testAndCallback(inTest, fitTest(p, c), '', function() {removeTestNode(p); });
+				});
+			}
+			
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						function reciprocalTests(t) {
+							createStyledNodes([], function(n) {
+								testAndCallback(t, reciprocalMarginBoxTest(n), '', function() {removeTestNode(n); });
+							});
+						},
+						function fitTests(t) {
+							runFitTest(t, null, dojo.mixin({}, defaultChildStyles));
+						},
+						function fitTestsOverflow(t) {
+							runFitTest(t, null, dojo.mixin({overflow:'hidden'}, defaultChildStyles));
+							runFitTest(t, {overflow: 'hidden'}, dojo.mixin({}, defaultChildStyles));
+							runFitTest(t, {overflow: 'hidden'}, dojo.mixin({overflow:'hidden'}, defaultChildStyles));
+						},
+						function fitTestsFloat(t) {
+							runFitTest(t, null, dojo.mixin({float: 'left'}, defaultChildStyles));
+							runFitTest(t, {float: 'left'}, dojo.mixin({}, defaultChildStyles));
+							runFitTest(t, {float: 'left'}, dojo.mixin({float: 'left'}, defaultChildStyles));
+						},
+						function reciprocalTestsInline(t) {
+							createStyledParentChild([], [{}, null, 'span'], function(p, c) {
+								c.innerHTML = 'Hello World';
+								testAndCallback(t, reciprocalMarginBoxTest(c), '', function() {removeTestNode(c); });
+							});
+						},
+						function reciprocalTestsButtonChild(t) {
+							createStyledParentChild([], [{}, null, 'button'], function(p, c) {
+								c.innerHTML = 'Hello World';
+								testAndCallback(t, reciprocalMarginBoxTest(c), '', function() {removeTestNode(c); });
+							});
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css">
+			html, body {
+				padding: 0px;
+				margin: 0px;
+				border: 0px;
+			}
+		</style>
+	</head>
+	<body>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/html_box_quirks.html b/dojo/tests/_base/html_box_quirks.html
new file mode 100644
index 0000000..34324a6
--- /dev/null
+++ b/dojo/tests/_base/html_box_quirks.html
@@ -0,0 +1,205 @@
+<!--
+	we use a quirks-mode DTD to check for quirks!
+-->
+<html>
+	<head>
+		<title> test html.js Box utils</title>
+		<style type="text/css">
+			/*@import "../../resources/dojo.css";*/
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" 
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			
+			var margin = '1px';
+			var border = '3px solid black';
+			var padding = '5px';
+			var defaultStyles = {
+				height: '100px',
+				width: '100px',
+				position: 'absolute',
+				backgroundColor: 'red'
+			};
+			
+			var defaultChildStyles = {
+				height: '20px',
+				width: '20px',
+				backgroundColor: 'blue'
+			}
+			
+			var testStyles = [
+				{},
+				{margin: margin},
+				{border: border},
+				{padding: padding},
+				{margin: margin, border: border},
+				{margin: margin, padding: padding},
+				{border: border, padding: padding},
+				{margin: margin, border: border, padding: padding}			
+			]
+			
+			
+			function sameBox(inBox1, inBox2) {
+				for (var i in inBox1)
+					if (inBox1[i] != inBox2[i]) {
+						console.log((arguments[2]||'box1') + '.' + i + ': ', inBox1[i], ' != ', (arguments[3]||'box2') + '.' + i + ': ', inBox2[i]);
+						return false;
+					}	
+				return true;		
+			}
+			
+			function reciprocalMarginBoxTest(inNode, inBox) {
+				var s = inBox || dojo.marginBox(inNode);
+				dojo.marginBox(inNode, s);
+				var e = dojo.marginBox(inNode);
+				return sameBox(s, e);
+			}
+			
+			function fitTest(inParent, inChild) {
+				var pcb = dojo.contentBox(inParent);
+				return reciprocalMarginBoxTest(inChild, pcb);
+			}
+			
+			function createStyledElement(inStyle, inParent, inElement, inNoDefault) {
+				inStyle = inStyle||{};
+				if (!inNoDefault) {
+					for (var i in defaultStyles)
+						if (!inStyle[i])
+							inStyle[i] = defaultStyles[i];
+				}			
+				var n = document.createElement(inElement || 'div');
+				(inParent||document.body).appendChild(n);
+				dojo.mixin(n.style, inStyle);
+				return n;				
+			}
+			
+			var _testTopInc = 0;
+			var _testTop = 150;
+			var _testInitTop = 250;
+			function styleIncTop(inStyle) {
+				inStyle = dojo.mixin({}, inStyle||{});
+				inStyle.top = (_testInitTop + _testTop*_testTopInc) + 'px';
+				_testTopInc++;
+				return inStyle;
+			}
+			
+			function removeTestNode(inNode) {
+				// leave nodes for inspection or don't return to delete them
+				return;
+				inNode = dojo.byId(inNode);
+				inNode.parentNode.removeChild(inNode);
+				_testTopInc--;
+			}
+			
+			function testAndCallback(inTest, inAssert, inComment, inOk, inErr) {
+				inTest.assertTrue('/* ' + inComment +  '*/' + inAssert);
+				if (inAssert)
+					inOk&&inOk();
+				else
+					inErr&&inErr();	
+			}
+			
+			// args are (styles, parent, element name, no default)
+			function mixCreateElementArgs(inMix, inArgs) {
+				args = [{}];
+				if (inArgs&&inArgs[0])
+					dojo.mixin(args[0], inArgs[0]);
+				if (inMix.length)
+					dojo.mixin(args[0], inMix[0]||{});
+				// parent comes from source
+				if (inMix.length > 1)
+					args[1] = inMix[1];
+				args[2] = inArgs[2];
+				args[3] = inArgs[3]	
+				return args;	
+			};
+			
+			function createStyledNodes(inArgs, inFunc) {
+				for (var i=0, n; (s=testStyles[i]); i++) {
+					n = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inArgs));
+					inFunc&&inFunc(n);
+				}	
+			}
+			
+			function createStyledParentChild(inParentArgs, inChildArgs, inFunc) {
+				for (var i=0, s, p, c; (s=testStyles[i]); i++) {
+					p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+					c = createStyledElement.apply(this, mixCreateElementArgs([{}, p], inChildArgs));
+					inFunc&&inFunc(p, c);
+				}	
+			}
+			
+			function createStyledParentChildren(inParentArgs, inChildArgs, inFunc) {
+				for (var i=0, s, p; (s=testStyles[i]); i++)
+					for (var j=0, sc, c, props; (sc=testStyles[j]); j++) {
+						p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+						c = createStyledElement.apply(this, mixCreateElementArgs([sc, p], inChildArgs));
+						inFunc&&inFunc(p, c);
+					}	
+				
+				for (var i=0, s, p, c; (s=testStyles[i]); i++) {
+					p = createStyledElement.apply(this, mixCreateElementArgs([styleIncTop(s)], inParentArgs));
+					c = createStyledElement.apply(this, mixCreateElementArgs([{}, p], inChildArgs));
+					inFunc&&inFunc(p, c);
+				}	
+			}
+			
+			
+			function runFitTest(inTest, inParentStyles, inChildStyles) {
+				createStyledParentChildren([inParentStyles], [inChildStyles], function(p, c) {
+					testAndCallback(inTest, fitTest(p, c), '', function() {removeTestNode(p); });
+				});
+			}
+			
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						function reciprocalTests(t) {
+							createStyledNodes([], function(n) {
+								testAndCallback(t, reciprocalMarginBoxTest(n), '', function() {removeTestNode(n); });
+							});
+						},
+						function fitTests(t) {
+							runFitTest(t, null, dojo.mixin({}, defaultChildStyles));
+						},
+						function fitTestsOverflow(t) {
+							runFitTest(t, null, dojo.mixin({overflow:'hidden'}, defaultChildStyles));
+							runFitTest(t, {overflow: 'hidden'}, dojo.mixin({}, defaultChildStyles));
+							runFitTest(t, {overflow: 'hidden'}, dojo.mixin({overflow:'hidden'}, defaultChildStyles));
+						},
+						function fitTestsFloat(t) {
+							runFitTest(t, null, dojo.mixin({float: 'left'}, defaultChildStyles));
+							runFitTest(t, {float: 'left'}, dojo.mixin({}, defaultChildStyles));
+							runFitTest(t, {float: 'left'}, dojo.mixin({float: 'left'}, defaultChildStyles));
+						},
+						function reciprocalTestsInline(t) {
+							createStyledParentChild([], [{}, null, 'span'], function(p, c) {
+								c.innerHTML = 'Hello World';
+								testAndCallback(t, reciprocalMarginBoxTest(c), '', function() {removeTestNode(c); });
+							});
+						},
+						function reciprocalTestsButtonChild(t) {
+							createStyledParentChild([], [{}, null, 'button'], function(p, c) {
+								c.innerHTML = 'Hello World';
+								testAndCallback(t, reciprocalMarginBoxTest(c), '', function() {removeTestNode(c); });
+							});
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css">
+			html, body {
+				padding: 0px;
+				margin: 0px;
+				border: 0px;
+			}
+		</style>
+	</head>
+	<body>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/html_docScroll.html b/dojo/tests/_base/html_docScroll.html
new file mode 100644
index 0000000..cf3247b
--- /dev/null
+++ b/dojo/tests/_base/html_docScroll.html
@@ -0,0 +1,102 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>testing Core _docScroll function</title>
+		<script type="text/javascript" 
+			src="../../dojo.js" 
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						function testNonScrolled(t){
+							dojo.global.scrollTo(0,0);
+							var s = dojo._docScroll();
+							t.is(0, s.x);
+							t.is(0, s.y);
+						},
+						function testScrolled(t){
+							dojo.global.scrollTo(1,2);
+							var s = dojo._docScroll();
+							t.is(1, s.x);
+							t.is(2, s.y);
+						},
+						function testQuirksNonScrolled(t){
+							var win = dojo.byId('iframe').iframeContentWindow;
+							win.scrollTo(0,0);
+							var s = dojo.withGlobal(win, "_docScroll", dojo);
+							t.is(0, s.x);
+							t.is(0, s.y);
+							var s = dojo._docScroll();
+							t.is(1, s.x);
+							t.is(2, s.y);
+						},
+						function testQuirksScrolled(t){
+							dojo.global.scrollTo(0,0);
+							var win = dojo.byId('iframe').iframeContentWindow;
+							win.scrollTo(10,20);
+							var s = dojo.withGlobal(win, "_docScroll", dojo);
+							t.is(10, s.x);
+							t.is(20, s.y);
+						},
+						function testSpeed(t){
+							var d = dojo;
+							var old_docScroll = function(){
+							        var
+							                _b = d.body(),
+							                _w = d.global,
+							                de = d.doc.documentElement;
+							        return {
+							                y: (_w.pageYOffset || de.scrollTop || _b.scrollTop || 0),
+							                x: (_w.pageXOffset || d._fixIeBiDiScrollLeft(de.scrollLeft) || _b.scrollLeft || 0)
+							        };
+							};
+							var count = 10000; // initial guess
+							var new_docScroll = dojo._docScroll;
+							var t0 = new Date().getTime();
+							for (var i=0; i < count; i++){
+							        var j = new_docScroll();
+							}
+							t0 = new Date().getTime() - t0;
+							// modify guess to get about 1 second of CPU crunching
+							if(t0 < 50){ // crazy short time
+								count *= 25;
+							}else{
+								count = Math.ceil(10000000/t0);
+							}
+							t0 = new Date().getTime();
+							for (i=0; i < count; i++){
+							        j = new_docScroll();
+							}
+							t0 = new Date().getTime() - t0;
+							var t1 = new Date().getTime();
+							for (var i=0; i < count; i++){
+							        j = old_docScroll();
+							}
+							t1 = new Date().getTime() - t1;
+							console.log(Math.floor(100*(t1-t0)/t1)+"% speed improvement");
+							t.is(true, t1 > t0);
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body>
+		<h1>testing Core _docScroll function</h1>
+		<div id='div' style="border:0px;padding:0px;margin:0px;">
+			<iframe id="iframe" src="javascript:'<html><head><script>frameElement.iframeContentWindow=window</script></head><body><div style=\'height:500px;width:500px;\'> </div></body>'"></iframe>
+		</div>
+		<script type="text/javascript">
+			// make sure div is too big to display
+			var div = dojo.byId('div');
+			div.style.height = (dojo.doc.documentElement.clientHeight + 2) + "px";
+			div.style.width = (dojo.doc.documentElement.clientWidth + 1) + "px";
+		</script>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/html_element.html b/dojo/tests/_base/html_element.html
new file mode 100644
index 0000000..a0dd3c8
--- /dev/null
+++ b/dojo/tests/_base/html_element.html
@@ -0,0 +1,308 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<!--
+	we use a strict-mode DTD to ensure that the box model is the same for these
+	basic tests
+-->
+<html>
+	<head>
+		<title>testing Core HTML/DOM/CSS/Style utils</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" 
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+					
+						function createBasic(t){
+							// test plain creation
+							var n = dojo.create("div");
+							dojo.byId("holder1").appendChild(n);
+							dojo.addClass(n, "testing");
+							var q = dojo.query(".testing");
+							
+							doh.is(1, q.length);
+							doh.is("div", n.nodeName.toLowerCase());
+						},
+						
+						function createAttrs(t){
+							// test attr creation, no placement
+							var n = dojo.create('div', {
+								"class":"hasClass",
+								title:"foo",
+								style:"border:2px solid #ededed; padding:3px"
+							});
+							// plain placement:
+							dojo.byId("holder1").appendChild(n);
+							
+							doh.t(dojo.hasClass(n, "hasClass"));
+							doh.is("foo", dojo.attr(n, "title"));
+							//FIXME: apparently attr(n, "style", "foo:bar; baz:bam;") doesn't work in IE?
+							// need to test further in attr or document.
+							//doh.is(3, dojo.style(n, "padding"));
+						},
+						
+						function createPlace(t){
+							// test only creation and placement, no attr
+							var n = dojo.create("div", null, dojo.body());
+							n.innerHTML = "<p class='bar'>a</p>";
+							var q = dojo.query("p", n);
+							
+							doh.is(1, q.length);
+							doh.t(dojo.hasClass(q[0], "bar"));
+						},
+						
+						function createHtml(t){
+							// test creation, placement, and attr (innerHTML)
+							var n = dojo.create("div", {
+								innerHTML: "<p class='bar2'>a</p>"
+							}, dojo.body());
+							var q = dojo.query("p", n);
+							
+							doh.is(1, q.length);
+							doh.t(dojo.hasClass(q[0], "bar2"));
+						},
+						
+						function createPlaceRef(t){
+							// test creation and referenced placement, with some attr
+							var ref = dojo.query("#holder2 > li.last")[0];
+							
+							var n = dojo.create("li", { 
+								innerHTML:"middle", "class":"middleNode"
+							}, ref, "before");
+							
+							doh.is(3, dojo.query("#holder2 li").length);
+							
+							var nn = dojo.create("li", { 
+								innerHTML:"afterLast", "class":"afterLast"
+							}, ref, "after");
+							
+							// FIXME: this is dependant on query() retaining DOM order. 
+							//		is that safe? nextSibling and friends are a PITA
+							var classes = ["first", "middleNode", "last", "afterLast"];
+							var q = dojo.query("#holder2 li");
+							doh.is(4, q.length);
+							
+							q.forEach(function(n, i){
+								doh.is(classes[i], n.className);
+							});
+							
+						},
+						
+						function destroyList(t){
+							// destroy node byId
+							dojo.destroy("holder2");
+							doh.f(dojo.byId("holder2"));
+							// destroyed because is child of holder
+							doh.is(0, dojo.query(".first").length);
+						},
+						
+						function createList(t){
+							// test creation/placement of a variety of node tags
+							var es = ["div", "a", "span", "br", "table", "ul", "dd", "img", "h2"];
+							dojo.forEach(es, function(el){
+								dojo.create(el, null, "holder3");
+							});
+							var q = dojo.query(">", "holder3");
+							doh.is(q.length, es.length);
+							
+							// destroy this list:
+							q.forEach(dojo.destroy);
+							q = dojo.query(">", "holder3");
+							doh.is(q.length, 0);
+							
+						},
+						
+						function destroyAll(t){
+							var c = function(){
+								// eg: don't destroy firebug lite in page
+								return dojo.query("body >").filter(function(n){
+									return !dojo.hasClass(n, "firebug");
+								})
+							}
+							c().forEach(dojo.destroy);
+
+							// check for deepest embeeded id
+							doh.f(dojo.byId("ancFoo"));
+							doh.is(0, c().length);
+						},
+
+						function recreateOneV1(t){
+							var n = dojo.create("h2", {
+								"class":"restored",
+								innerHTML:"<span>The End</span>"
+							}, dojo.body());
+							
+							doh.is(1, dojo.query(".restored").length);
+							dojo.destroy(n);
+						},
+
+						function recreateOneV2(t){
+							var n = dojo.place("<h2 class='restored'><span>The End</span></h2>", dojo.body());
+							doh.is(1, dojo.query(".restored").length);
+							dojo.destroy(n);
+						},
+
+						function emptyDiv(t){
+							var n = dojo.create("div", {
+								innerHTML: "1<span class='red'>2</span>3<em custom='x'>4</em>5"
+							});
+							doh.isNot("", n.innerHTML);
+							dojo.empty(n);
+							doh.is("", n.innerHTML);
+							dojo.destroy(n);
+						},
+
+						function emptyTable(t){
+							var table = dojo.create("table", null, dojo.body()),
+								tr1 = dojo.create("tr", null, table),
+								td1 = dojo.create("td", {innerHTML: "a"}, tr1),
+								td2 = dojo.create("td", {innerHTML: "b"}, tr1),
+								tr2 = dojo.create("tr", null, table),
+								td3 = dojo.create("td", {innerHTML: "c"}, tr2),
+								td4 = dojo.create("td", {innerHTML: "d"}, tr2);
+							doh.isNot("", table.innerHTML);
+							dojo.empty(table);
+							doh.is("", table.innerHTML);
+							dojo.destroy(table);
+						},
+
+						function toDomSpans(t){
+							var n = dojo._toDom("<span>1</span><span>2</span>");
+							doh.is(2, n.childNodes.length);
+							doh.is("span", n.firstChild.tagName.toLowerCase());
+							doh.is("1", n.firstChild.innerHTML);
+							doh.is("span", n.lastChild.tagName.toLowerCase());
+							doh.is("2", n.lastChild.innerHTML);
+						},
+
+						function toDomTr(t){
+							var n = dojo._toDom("<tr><td>First!</td></tr>");
+							doh.is("tr", n.tagName.toLowerCase());
+							doh.is(1, n.childNodes.length);
+							doh.is("td", n.firstChild.tagName.toLowerCase());
+							doh.is("First!", n.firstChild.innerHTML);
+						},
+
+						function toDomText(t){
+							var n = dojo._toDom("Hello, world!");
+							doh.is(3, n.nodeType);
+							doh.is("Hello, world!", n.nodeValue);
+						},
+
+						function toDomOption(t){
+							var n = dojo._toDom('<option value="1">First</option>');
+							doh.f(n.selected);
+
+							var n = dojo._toDom('<option value="1" selected="selected">First</option>');
+							doh.t(n.selected);
+
+							n = dojo._toDom('<option value="1">First</option><option value="2" selected>Second</option>');
+							doh.f(n.childNodes[0].selected);
+							doh.t(n.childNodes[1].selected);
+						},
+
+						function placeDivs(t){
+							dojo.place("<p class='disposable'>2</p>", dojo.body());
+							var n = dojo.query("body > .disposable")[0];
+							dojo.place("<p class='disposable'>0</p><p class='disposable'>1</p>", n, "before");
+							dojo.place("<p class='disposable'>3</p><p class='disposable'>4</p>", n, "after");
+							dojo.place("<span>a</span>", n, "first");
+							dojo.place("<span>z</span>", n, "last");
+							n = dojo.query("body > .disposable");
+							doh.is(5, n.length);
+							doh.is("0", n[0].innerHTML);
+							doh.is("1", n[1].innerHTML);
+							doh.is("3", n[3].innerHTML);
+							doh.is("4", n[4].innerHTML);
+							doh.is("<span>a</span>2<span>z</span>", n[2].innerHTML.toLowerCase());
+							n.forEach(dojo.destroy);
+						},
+
+						function placeTable(t){
+							dojo.place("<table class='disposable'><tbody></tbody></table>", dojo.body());
+							var n = dojo.query("body > table.disposable > tbody")[0];
+							dojo.place("<tr><td>2</td></tr>", n);
+							dojo.place("<tr><td>0</td></tr><tr><td>1</td></tr>", n, "first");
+							dojo.place("<tr><td>3</td></tr><tr><td>4</td></tr>", n, "last");
+							n = dojo.query("body > table.disposable tr");
+							doh.is(5, n.length);
+							doh.is("<td>0</td>", n[0].innerHTML.toLowerCase());
+							doh.is("<td>1</td>", n[1].innerHTML.toLowerCase());
+							doh.is("<td>2</td>", n[2].innerHTML.toLowerCase());
+							doh.is("<td>3</td>", n[3].innerHTML.toLowerCase());
+							doh.is("<td>4</td>", n[4].innerHTML.toLowerCase());
+							dojo.query("body > table.disposable").forEach(dojo.destroy);
+						},
+
+						function placeReplace(t){
+							dojo.place("<p class='disposable'>2</p>", dojo.body());
+							var n = dojo.query("body > .disposable")[0];
+							dojo.place("<p class='disposable'>0</p><p class='disposable'>1</p>", n, "replace");
+							n = dojo.query("body > .disposable");
+							doh.is(2, n.length);
+							doh.is("0", n[0].innerHTML);
+							doh.is("1", n[1].innerHTML);
+							n.forEach(dojo.destroy);
+						},
+
+						function placeOnly(t){
+							dojo.place("<p class='disposable'><em>1</em>2<strong>3</strong></p>", dojo.body());
+							var n = dojo.query("body > .disposable")[0];
+							dojo.place("<span>42</span>99", n, "only");
+							n = dojo.query("body > .disposable");
+							doh.is(1, n.length);
+							doh.is("<span>42</span>99", n[0].innerHTML.toLowerCase());
+							n.forEach(dojo.destroy);
+						},
+						
+						function placeNumber(t){
+							var n = dojo.place("<p><em>1</em><em>2</em></p>", dojo.body());
+							doh.is(2, n.childNodes.length);
+							dojo.place("<span>C</span>", n, 99);
+							doh.is(3, n.childNodes.length);
+							doh.is("span", n.childNodes[2].tagName.toLowerCase());
+							doh.is("C", n.childNodes[2].innerHTML);
+							dojo.place("<span>A</span>", n, -1);
+							doh.is(4, n.childNodes.length);
+							doh.is("span", n.childNodes[0].tagName.toLowerCase());
+							doh.is("A", n.childNodes[0].innerHTML);
+							dojo.place("<span>B</span>", n, 2);
+							doh.is(5, n.childNodes.length);
+							doh.is("span", n.childNodes[2].tagName.toLowerCase());
+							doh.is("B", n.childNodes[2].innerHTML);
+							dojo.destroy(n);
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body>
+		<h1>testing Core DOM utils</h1>
+		
+		<div id="holder1"></div>
+		<ul id="holder2">
+			<li class="first">first</li>
+			<li class="last">last</li>
+		</ul>
+		
+		<div id="holder3"></div>
+		
+		<p id="someId"></p>
+		
+		<div>
+			<div>
+				<a id="ancFoo" href="null.html">link</a>
+			</div>
+		</div>
+		
+	</body>
+</html>
diff --git a/dojo/tests/_base/html_id.html b/dojo/tests/_base/html_id.html
new file mode 100644
index 0000000..320f07f
--- /dev/null
+++ b/dojo/tests/_base/html_id.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<!--
+	we use a strict-mode DTD to ensure that the box model is the same for these
+	basic tests
+-->
+<html>
+	<head>
+		<title>testing Core HTML/DOM/CSS/Style utils: dojo.byId</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" 
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						function byId(t){
+							doh.f(dojo.byId(null));
+							doh.f(dojo.byId(undefined));
+
+							doh.f(dojo.byId("baz"));
+							doh.f(dojo.byId("foobar"));
+							doh.f(dojo.byId("dude"));
+							doh.f(dojo.byId("cattle"));
+							doh.f(dojo.byId("cattle2"));
+
+							doh.f(dojo.byId("lamps"));
+							doh.f(dojo.byId("blue"));
+							doh.t(dojo.byId("chairs"));
+							
+							doh.t(dojo.byId("ranch"));
+							doh.t(dojo.byId("cattle3"));
+							doh.is("span", dojo.byId("fish").nodeName.toLowerCase());
+							
+							var startNode = dojo.byId("start");
+							var clonedNode = dojo.clone(startNode);
+							clonedNode.id= "clonedStart";
+							clonedNode.innerHTML= "This is a cloned div";
+							dojo.body().appendChild(clonedNode);
+
+							doh.is("This is a cloned div", dojo.byId("clonedStart").innerHTML);
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body>
+		<h1>testing Core DOM utils: dojo.byId</h1>
+		
+		<form name="foobar">
+			<input type="text" name="baz" value="baz1">
+			<input type="text" name="baz" value="baz2">
+		</form>
+		
+		<form name="dude"></form>
+
+		<form name="ranch">
+			<input type="text" name="cattle" id="ranch" value="baz1">
+		</form>
+		
+		<form name="ranch2">
+			<input type="text" name="cattle2" value="baz1">
+		</form>
+		
+		<form name="ranch3">
+			<input type="text" name="cattle3" value="baz1">
+			<input type="text" name="cattle3" id="cattle3" value="cattle3">
+		</form>
+		
+		<form name="sea">
+			<input type="text" name="fish" value="fish">
+			<input type="text" name="turtle" value="turtle">
+		</form>
+		<span id="fish">Fish span</span>
+				
+		<form name="lamps">
+			<input type="text" name="id" value="blue">
+		</form>
+
+		<form name="chairs" id="chairs">
+			<input type="text" name="id" value="recliner">
+		</form>
+
+		<div id="start">a start node</div>
+		
+	</body>
+</html>
diff --git a/dojo/tests/_base/html_isBodyLtr.html b/dojo/tests/_base/html_isBodyLtr.html
new file mode 100644
index 0000000..bcb7cd8
--- /dev/null
+++ b/dojo/tests/_base/html_isBodyLtr.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html dir="LTR">
+	<head>
+		<title>testing Core _isBodyLtr function</title>
+		<script type="text/javascript" 
+			src="../../dojo.js" 
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						function testRtl(t){
+							t.is(false, dojo._isBodyLtr());
+						},
+						function testCache(t){
+							dojo.body().setAttribute("dir", "ltr");
+							t.is(false, dojo._isBodyLtr());
+							delete dojo._bodyLtr; // clear cache
+							t.is(true, dojo._isBodyLtr());
+						},
+						function testHtmlValue(t){
+							delete dojo._bodyLtr; // clear cache
+							dojo.body().setAttribute("dir", "RTL");
+							t.is(false, dojo._isBodyLtr());
+							delete dojo._bodyLtr; // clear cache
+							dojo.body().removeAttribute("dir");
+							t.is(true, dojo._isBodyLtr());
+						},
+						function testDefaultValue(t){
+							delete dojo._bodyLtr; // clear cache
+							dojo.doc.documentElement.setAttribute("dir", "rtl");
+							t.is(false, dojo._isBodyLtr());
+							delete dojo._bodyLtr; // clear cache
+							dojo.doc.documentElement.removeAttribute("dir");
+							t.is(true, dojo._isBodyLtr());
+						},
+						function testHiddenIframe(t){
+							delete dojo._bodyLtr; // clear cache
+							dojo.doc.documentElement.setAttribute("dir", "rtl");
+							t.is(false, dojo._isBodyLtr());
+							t.is(true, dojo.withGlobal(dojo.byId('iframe').iframeContentWindow, "_isBodyLtr", dojo));
+							dojo.doc.documentElement.setAttribute("dir", "ltr");
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body dir="rtl">
+		<h1>testing Core _isBodyLtr function</h1>
+		<div style="display:none;">
+			<iframe id="iframe" src="javascript:'<html><head><script>frameElement.iframeContentWindow=window</script></head><body></body>'"></iframe>
+		</div>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/html_quirks.html b/dojo/tests/_base/html_quirks.html
new file mode 100644
index 0000000..c33284b
--- /dev/null
+++ b/dojo/tests/_base/html_quirks.html
@@ -0,0 +1,331 @@
+<html>
+	<!--
+		we use a quirks-mode DTD on purpose to ensure that things go tilt. Wheee!!
+	-->
+	<head>
+		<title>testing Core HTML/DOM/CSS/Style utils in quirks mode</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" 
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						"t.is(100, dojo.marginBox('sq100').w);",
+						"t.is(100, dojo.marginBox('sq100').h);",
+
+						"t.is(120, dojo.marginBox('sq100margin10').w);",
+						"t.is(120, dojo.marginBox('sq100margin10').h);",
+						"t.is(100, dojo.contentBox('sq100margin10').w);",
+						"t.is(100, dojo.contentBox('sq100margin10').h);",
+
+						// FIXME: the 'correct' w is not 100 on Safari WebKit (2.0.4 [419.3]), the right-margin extends to the document edge
+						//"t.is(100, dojo.marginBox('sq100nopos').w);",
+						"t.is(100, dojo.marginBox('sq100nopos').h);",
+
+						function coordsBasic(t){
+							var pos = dojo.position("sq100", false);
+							// console.debug(pos);
+							t.is(100, pos.x);
+							t.is(100, pos.y);
+							t.is(100, pos.w);
+							t.is(100, pos.h);
+						},
+						function coordsMargin(t){
+							// position() is getting us the border-box location
+							var pos = dojo.position("sq100margin10", false);
+							t.is(260, pos.x);
+							t.is(110, pos.y);
+							t.is(100, pos.w);
+							t.is(100, pos.h);
+							pos = dojo.marginBox("sq100margin10");
+							t.is(120, pos.w);
+							t.is(120, pos.h);
+							// Though coords shouldn't be used, test it for backward compatibility.
+							// coords returns the border-box location and margin-box size
+							pos = dojo.coords("sq100margin10", false);
+							t.is(260, pos.x);
+							t.is(110, pos.y);
+							t.is(120, pos.w);
+							t.is(120, pos.h);
+						},
+						function coordsBorder(t){
+							var pos = dojo.position("sq100border10", false);
+							t.is(100, pos.x);
+							t.is(400, pos.y);
+						},
+						function sq100nopos(t){
+							var pos = dojo.position("sq100nopos", false);
+							// console.debug(pos);
+							t.is(0, pos.x);
+							t.t(pos.y > 0);
+							// FIXME: the 'correct' w is not 100 on Safari WebKit (2.0.4 [419.3]), the right-margin extends to the document edge
+							//t.is(100, pos.w);
+							t.is(100, pos.h);
+						}
+					]
+				);
+				if(dojo.isIE){ 
+					// IE collapses padding in quirks mode. We just report on it.
+					doh.register("t", 
+						[
+							"t.is(120, dojo.marginBox('sq100margin10pad10').w);",
+							"t.is(120, dojo.marginBox('sq100margin10pad10').h);",
+
+							"t.is(100, dojo.marginBox('sq100pad10').w);",
+							"t.is(100, dojo.marginBox('sq100pad10').h);",
+
+							"t.is(100, dojo.marginBox('sq100ltpad10').w);",
+							"t.is(100, dojo.marginBox('sq100ltpad10').h);",
+							"t.is(90, dojo.contentBox('sq100ltpad10').w);",
+							"t.is(90, dojo.contentBox('sq100ltpad10').h);",
+
+							"t.is(110, dojo.marginBox('sq100ltpad10rbmargin10').w);",
+							"t.is(110, dojo.marginBox('sq100ltpad10rbmargin10').h);",
+
+							"t.is(100, dojo.marginBox('sq100border10').w);",
+							"t.is(100, dojo.marginBox('sq100border10').h);",
+							"t.is(80, dojo.contentBox('sq100border10').w);",
+							"t.is(80, dojo.contentBox('sq100border10').h);",
+
+							"t.is(120, dojo.marginBox('sq100border10margin10').w);",
+							"t.is(120, dojo.marginBox('sq100border10margin10').h);",
+							"t.is(80, dojo.contentBox('sq100border10margin10').w);",
+							"t.is(80, dojo.contentBox('sq100border10margin10').h);",
+
+							"t.is(120, dojo.marginBox('sq100border10margin10pad10').w);",
+							"t.is(120, dojo.marginBox('sq100border10margin10pad10').h);",
+							"t.is(60, dojo.contentBox('sq100border10margin10pad10').w);",
+							"t.is(60, dojo.contentBox('sq100border10margin10pad10').h);"
+						]
+					);
+				}else{
+					doh.register("t", 
+						[
+							"t.is(140, dojo.marginBox('sq100margin10pad10').w);",
+							"t.is(140, dojo.marginBox('sq100margin10pad10').h);",
+
+							"t.is(120, dojo.marginBox('sq100pad10').w);",
+							"t.is(120, dojo.marginBox('sq100pad10').h);",
+
+							"t.is(110, dojo.marginBox('sq100ltpad10').w);",
+							"t.is(110, dojo.marginBox('sq100ltpad10').h);",
+							"t.is(100, dojo.contentBox('sq100ltpad10').w);",
+							"t.is(100, dojo.contentBox('sq100ltpad10').h);",
+
+							"t.is(120, dojo.marginBox('sq100ltpad10rbmargin10').w);",
+							"t.is(120, dojo.marginBox('sq100ltpad10rbmargin10').h);",
+
+							"t.is(120, dojo.marginBox('sq100border10').w);",
+							"t.is(120, dojo.marginBox('sq100border10').h);",
+							"t.is(100, dojo.contentBox('sq100border10').w);",
+							"t.is(100, dojo.contentBox('sq100border10').h);",
+
+							"t.is(140, dojo.marginBox('sq100border10margin10').w);",
+							"t.is(140, dojo.marginBox('sq100border10margin10').h);",
+							"t.is(100, dojo.contentBox('sq100border10margin10').w);",
+							"t.is(100, dojo.contentBox('sq100border10margin10').h);",
+
+							"t.is(160, dojo.marginBox('sq100border10margin10pad10').w);",
+							"t.is(160, dojo.marginBox('sq100border10margin10pad10').h);",
+							"t.is(100, dojo.contentBox('sq100border10margin10pad10').w);",
+							"t.is(100, dojo.contentBox('sq100border10margin10pad10').h);"
+						]
+					);
+				}
+
+				doh.run();
+			});
+		</script>
+		<style type="text/css">
+			html, body {
+				padding: 0px;
+				margin: 0px;
+				border: 0px;
+			}
+
+			#sq100 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 100px;
+				top: 100px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding: 0px;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#sq100margin10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 250px;
+				top: 100px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding: 0px;
+				margin: 10px;
+				overflow: hidden;
+			}
+
+			#sq100margin10pad10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 400px;
+				top: 100px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding: 10px;
+				margin: 10px;
+				overflow: hidden;
+			}
+
+			#sq100pad10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 100px;
+				top: 250px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding: 10px;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#sq100ltpad10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 250px;
+				top: 250px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding-left: 10px;
+				padding-top: 10px;
+				padding-right: 0px;
+				padding-bottom: 0px;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#sq100ltpad10rbmargin10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 400px;
+				top: 250px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding-left: 10px;
+				padding-top: 10px;
+				padding-right: 0px;
+				padding-bottom: 0px;
+				margin-left: 0px;
+				margin-top: 0px;
+				margin-right: 10px;
+				margin-bottom: 10px;
+				overflow: hidden;
+			}
+
+			#sq100border10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 100px;
+				top: 400px;
+				width: 100px;
+				height: 100px;
+				border: 10px solid yellow;
+				padding: 0px;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#sq100border10margin10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 250px;
+				top: 400px;
+				width: 100px;
+				height: 100px;
+				border: 10px solid yellow;
+				padding: 0px;
+				margin: 10px;
+				overflow: hidden;
+			}
+
+			#sq100border10margin10pad10 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 400px;
+				top: 400px;
+				width: 100px;
+				height: 100px;
+				border: 10px solid yellow;
+				padding: 10px;
+				margin: 10px;
+				overflow: hidden;
+			}
+
+			#sq100nopos {
+				background-color: black;
+				color: white;
+				width: 100px;
+				height: 100px;
+				padding: 0px;
+				margin: 0px;
+			}
+
+		</style>
+	</head>
+	<body>
+		<h1>testing Core HTML/DOM/CSS/Style utils</h1>
+		<div id="sq100">
+			100px square, abs
+		</div>
+		<div id="sq100margin10">
+			100px square, abs, 10px margin
+		</div>
+		<div id="sq100margin10pad10">
+			100px square, abs, 10px margin, 10px padding
+		</div>
+		<div id="sq100pad10">
+			100px square, abs, 10px padding
+		</div>
+		<div id="sq100ltpad10">
+			100px square, abs, 10px left and top padding
+		</div>
+		<div id="sq100ltpad10rbmargin10">
+			100px square, abs, 10px left and top padding, 10px bottom and right margin
+		</div>
+		<div id="sq100border10">
+			100px square, abs, 10px yellow border
+		</div>
+		<div id="sq100border10margin10">
+			100px square, abs, 10px yellow border, 10px margin
+		</div>
+		<div id="sq100border10margin10pad10">
+			100px square, abs, 10px yellow border, 10px margin, 10px padding
+		</div>
+		<div id="sq100nopos">
+			100px square, no positioning
+		</div>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/html_rtl.html b/dojo/tests/_base/html_rtl.html
new file mode 100644
index 0000000..8925c59
--- /dev/null
+++ b/dojo/tests/_base/html_rtl.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html dir="rtl">
+	<head>
+		<title>testing Core HTML/DOM/CSS/Style utils</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" 
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						function coordsWithVertScrollbar(t){
+							// show vertical scrollbar
+							dojo.byId("rect_vert").style.display = "";
+							scrollTo(0, 50);
+							var d = new doh.Deferred();
+							setTimeout(function(){ // need time to render
+								try{
+									t.is(100, dojo.position('rect100').x, "x pos should be 100 after vertical scroll");
+									t.is(50, dojo.position('rect100').y, "y pos should be 50 after vertical scroll");
+									d.callback(true);
+								}catch(e){
+									d.errback(e);
+								}finally{
+									dojo.byId("rect_vert").style.display = "none";
+								}
+							}, 100);
+							return d;
+						},
+
+						function coordsWithHorzScrollbar(t){
+							// show horizonal scrollbar & scroll a bit left
+							dojo.byId("rect_horz").style.display = "";
+							scrollTo(0, 0);
+							var d = new doh.Deferred();
+							setTimeout(function(){ // need time to render
+								try{
+									var pos = dojo.position('rect100');
+									t.is(100, pos.y, "position().y="+pos.y+" but should be 100 after horizontal scroll");
+									scrollBy(100, 0); // funny scrolling to account for different browsers
+									scrollBy(-50, 0);
+									t.is(50, Math.abs(dojo.position('rect100').x-pos.x), "position().x should have changed by 50 after horizontal scroll (actual change was " + Math.abs(dojo.position('rect100').x-pos.x) + ")");
+									scrollTo(0, 0); // reset horizontal scroll before hiding scrollbar for IE8's benefit
+									d.callback(true);
+								}catch(e){
+									d.errback(e);
+								}finally{
+									dojo.byId("rect_horz").style.display = "none";
+								}
+							}, 100);
+							return d;
+						},
+
+						function eventClientXY(t){ // IE only test
+							if(dojo.isIE){
+								// show vertical scrollbar
+								dojo.byId("rect_vert").style.display = "";
+
+								var rect = dojo.byId("rect100");
+								var assertException = null;
+
+								function rect_onclick(e){
+									// move the rectangle to the mouse point
+									rect.style.left = e.pageX + "px";
+									rect.style.top = e.pageY + "px";
+									window.alert("Do NOT move your mouse!!!\n\n" + 
+												"The black rectangle's top-left point should be under the mouse point.\n\n" +
+												"If not, you will see a failure in the test report later.\n\n" +
+												"Now press the space bar, but do NOT move your mouse.");
+									rect.fireEvent('ondblclick');
+								}
+
+								function rect_ondblclick(){
+									// test if the rectangle is really under the mouse point
+									try{
+										t.is(0, event.offsetX);
+										t.is(0, event.offsetY);
+									}catch(e){ // allow the exception in a event handler go to the event firer 
+										assertException = e;
+									}
+								}
+
+								dojo.connect(rect, "onclick", null, rect_onclick);
+								dojo.connect(rect, "ondblclick", null, rect_ondblclick);
+								window.alert("Move the mouse to anywhere in this page, and then press the space bar.");
+								rect.fireEvent('onclick');
+								if(assertException != null){
+									throw assertException;
+								}
+							}
+						}
+						
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css">
+			#rect100 {
+				background-color: black;
+				color: white;
+				position: absolute;
+				left: 100px;
+				top: 100px;
+				width: 100px;
+				height: 100px;
+				border: 0px;
+				padding: 0px;
+				margin: 0px;
+				overflow: hidden;
+			}
+		</style>
+	</head>
+	<body>
+		<h1>testing Core HTML/DOM/CSS/Style utils</h1>
+		<div id="rect100">
+			100px rect, abs, 
+			mouse point is at top-left after the test "eventClientXY"
+		</div>
+		<div id="rect_vert" style="height:1600px;display:none">show vertical scrollbar</div>
+		<div id="rect_horz" style="width:1600px;position:relative;right:-200px;display:none">show horizonal scrollbar</div>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/json.js b/dojo/tests/_base/json.js
new file mode 100644
index 0000000..157a5e0
--- /dev/null
+++ b/dojo/tests/_base/json.js
@@ -0,0 +1,33 @@
+dojo.provide("tests._base.json");
+
+tests.register("tests._base.json", 
+	[
+		//Not testing dojo.toJson() on its own since Rhino will output the object properties in a different order.
+		//Still valid json, but just in a different order than the source string.
+
+		// take a json-compatible object, convert it to a json string, then put it back into json.
+		function toAndFromJson(t){
+			var testObj = {a:"a", b:1, c:"c", d:"d", e:{e1:"e1", e2:2}, f:[1,2,3], g:"g",h:{h1:{h2:{h3:"h3"}}}};
+
+			var mirrorObj = dojo.fromJson(dojo.toJson(testObj));
+			t.assertEqual("a", mirrorObj.a);
+			t.assertEqual(1, mirrorObj.b);
+			t.assertEqual("c", mirrorObj.c);
+			t.assertEqual("d", mirrorObj.d);
+			t.assertEqual("e1", mirrorObj.e.e1);
+			t.assertEqual(2, mirrorObj.e.e2);
+			t.assertEqual(1, mirrorObj.f[0]);
+			t.assertEqual(2, mirrorObj.f[1]);
+			t.assertEqual(3, mirrorObj.f[2]);
+			t.assertEqual("g", mirrorObj.g);
+			t.assertEqual("h3", mirrorObj.h.h1.h2.h3);
+			var badJson;
+			try{
+				badJson = dojo.fromJson("bad json"); // this should throw an exception, and not set badJson
+			}catch(e){
+			}
+			t.assertEqual(undefined,badJson);
+		}
+	]
+);
+
diff --git a/dojo/tests/_base/lang.js b/dojo/tests/_base/lang.js
new file mode 100644
index 0000000..7017ba8
--- /dev/null
+++ b/dojo/tests/_base/lang.js
@@ -0,0 +1,279 @@
+dojo.provide("tests._base.lang");
+
+tests.register("tests._base.lang", 
+	[
+		function mixin(t){
+			t.assertEqual("object", typeof dojo.mixin());
+			t.assertEqual("object", typeof dojo.mixin(undefined));
+			t.assertEqual("object", typeof dojo.mixin(null));
+			var src = {
+				foo: function(){
+					t.debug("foo");
+				},
+				bar: "bar"
+			};
+			var dest = {};
+			dojo.mixin(dest, src);
+			t.assertEqual("function", typeof dest["foo"]);
+			t.assertEqual("string", typeof dest["bar"]);
+		},
+
+		function extend(t){
+			var src = {
+				foo: function(){
+					t.debug("foo");
+				},
+				bar: "bar"
+			};
+			function dest(){}
+			dojo.extend(dest, src);
+			var test = new dest();
+			t.assertEqual("function", typeof test["foo"]);
+			t.assertEqual("string", typeof test["bar"]);
+		},
+
+		function isFunction(t){
+			t.assertTrue(dojo.isFunction(new Function()));
+			t.assertTrue(dojo.isFunction(isFunction));
+			if(dojo.isBrowser){ // test the Safari workaround for NodeList
+				t.assertFalse(dojo.isFunction(dojo.doc.getElementsByName("html")));
+				t.assertFalse(dojo.isFunction(dojo.doc.createElement("object")));
+			}
+		},
+
+		function isObject(t){
+			t.assertFalse(dojo.isObject(true));
+			t.assertFalse(dojo.isObject(false));
+			t.assertFalse(dojo.isObject("foo"));
+			t.assertTrue(dojo.isObject(new String("foo")));
+			t.assertTrue(dojo.isObject(null));
+			t.assertTrue(dojo.isObject({}));
+			t.assertTrue(dojo.isObject([]));
+			t.assertTrue(dojo.isObject(new Array()));
+		},
+
+		function isArray(t){
+			t.assertTrue(dojo.isArray([]));
+			t.assertTrue(dojo.isArray(new Array()));
+			t.assertFalse(dojo.isArray({}));
+		},
+
+		function isArrayLike(t){
+			t.assertFalse(dojo.isArrayLike("thinger"));
+			t.assertTrue(dojo.isArrayLike(new Array()));
+			t.assertFalse(dojo.isArrayLike({}));
+			t.assertTrue(dojo.isArrayLike(arguments));
+		},
+
+		function isString(t){
+			t.assertFalse(dojo.isString(true));
+			t.assertFalse(dojo.isString(false));
+			t.assertTrue(dojo.isString("foo"));
+			t.assertTrue(dojo.isString(new String("foo")));
+			t.assertFalse(dojo.isString(null));
+			t.assertFalse(dojo.isString({}));
+			t.assertFalse(dojo.isString([]));
+		},
+
+		function partial(t){
+			var scope = { foo: "bar" };
+			var scope2 = { foo: "baz" };
+			function thinger(arg1, arg2){
+				return [this.foo, arg1, arg2];
+			}
+			
+			var st1 = dojo.partial(thinger);
+			t.assertEqual("bar", st1.call(scope)[0]);
+			t.assertEqual(undefined, st1()[0]);
+			var st2 = dojo.partial(thinger, "foo", "bar");
+			t.assertEqual("bar", st2()[2]);
+			var st3 = dojo.partial(thinger, "foo", "bar");
+		},
+
+		function nestedPartial(t){
+			function thinger(arg1, arg2){
+				return [arg1, arg2];
+			}
+			
+			var st1 = dojo.partial(thinger, "foo");
+			t.assertEqual(undefined, st1()[1]);
+			t.assertEqual("bar", st1("bar")[1]);
+
+			// partials can accumulate
+			var st2 = dojo.partial(st1, "thud");
+			t.assertEqual("foo", st2()[0]);
+			t.assertEqual("thud", st2()[1]);
+		},
+
+		function hitch(t){
+			var scope = { foo: "bar" };
+			var scope2 = { foo: "baz" };
+			function thinger(){
+				return [this.foo, arguments.length];
+			}
+			
+			var st1 = dojo.hitch(scope, thinger);
+			t.assertEqual("bar", st1()[0]);
+			t.assertEqual(0, st1()[1]);
+
+			var st2 = dojo.hitch(scope2, thinger);
+			t.assertEqual("baz", st2()[0]);
+			t.assertEqual(0, st1()[1]);
+			t.assertEqual(1, st1("blah")[1]);
+
+			// st2 should be "scope proof"
+			t.assertEqual("baz", st2.call(scope)[0]);
+		},
+
+		function hitchWithArgs(t){
+			var scope = { foo: "bar" };
+			var scope2 = { foo: "baz" };
+			function thinger(){
+				return [this.foo, arguments.length];
+			}
+			
+			var st1 = dojo.hitch(scope, thinger, "foo", "bar");
+			t.assertEqual("bar", st1()[0]);
+			t.assertEqual(2, st1()[1]);
+			var st2 = dojo.hitch(scope2, thinger, "foo", "bar");
+			t.assertEqual("baz", st2()[0]);
+			t.assertEqual(2, st2()[1]);
+		},
+
+		function hitchAsPartial(t){
+			var scope = { foo: "bar" };
+			var scope2 = { foo: "baz" };
+			function thinger(arg1, arg2){
+				return [this.foo, arg1, arg2];
+			}
+			
+			var st1 = dojo.hitch(null, thinger);
+			t.assertEqual("bar", st1.call(scope)[0]);
+			t.assertEqual(undefined, st1()[0]);
+			var st2 = dojo.hitch(null, thinger, "foo", "bar");
+			t.assertEqual("bar", st2()[2]);
+			var st3 = dojo.hitch(null, thinger, "foo", "bar");
+		},
+
+		function _toArray(t){
+			var obj1 = [ 'foo', 'bar', 'spam', 'ham' ];
+
+			function thinger(){
+				return dojo._toArray(arguments);
+			}
+			var obj2 = thinger.apply(this, obj1);
+			t.assertEqual(obj1[0], obj2[0]);
+
+			if(dojo.isBrowser){
+				//test DomCollection
+				var div = document.createElement('div');
+				div.innerHTML="<a href='#'>link</a>text";
+				var r=dojo._toArray(div.childNodes);
+				t.is(2,r.length);
+			}
+		},
+		
+		function clone(t) { 
+			var obj1 = {
+				foo: 'bar',
+				answer: 42,
+				jan102007: new Date(2007, 0, 10), 
+				baz: {
+					a: null, 
+					b: [1, "b", 2.3, true, false],
+					c: {
+						d: undefined,
+						e: 99,
+						f: function(){ console.log(42); return 42; },
+						g: /\d+/gm
+					}
+				},
+				toString: function(){ return "meow"; }
+			}; 
+			var obj2 = dojo.clone(obj1);
+			t.assertEqual(obj1.foo, obj2.foo);
+			t.assertEqual(obj1.answer, obj2.answer);
+			t.assertEqual(obj1.jan102007, obj2.jan102007);
+			t.assertEqual(obj1.baz.a, obj2.baz.a);
+			for(var i = 0; i < obj1.baz.b.length; ++i){
+				t.assertEqual(obj1.baz.b[i], obj2.baz.b[i]);
+			}
+			t.assertEqual(obj1.baz.c.d, obj2.baz.c.d);
+			t.assertEqual(obj1.baz.c.e, obj2.baz.c.e);
+			t.assertEqual(obj1.baz.c.f, obj2.baz.c.f);
+			t.assertEqual(obj1.baz.c.f(), obj2.baz.c.f());
+			t.assertEqual(obj1.baz.c.g, obj2.baz.c.g);
+			t.assertEqual(obj1.toString, obj2.toString);
+			t.assertEqual(obj1.toString(), obj2.toString());
+		},
+		
+		function delegate(t){
+			var a = {
+				x: 1,
+				y: function(){ return 2; },
+				z1: 99
+			};
+			var b = {
+				x: 11,
+				y: function(){ return 12; },
+				z2: 33,
+				toString: function(){ return "bark!"; },
+				toLocaleString: function(){ return "le bark-s!"; }
+			};
+			t.is(1, a.x);
+			t.is(2, a.y());
+			t.is(99, a.z1);
+			var c = dojo.delegate(a, b);
+			t.is(1, a.x);
+			t.is(2, a.y());
+			t.is(99, a.z1);
+			t.is(11, c.x);
+			t.is(12, c.y());
+			t.is("bark!", c.toString());
+			t.is("le bark-s!", c.toLocaleString());
+			t.is(99, c.z1);
+			t.is(33, c.z2);
+		},
+
+		function replace(t){
+			var s1 = dojo.replace("Hello, {name.first} {name.last} AKA {nick}!",
+				{
+					nick: "Bob",
+					name: {
+						first:  "Robert",
+						middle: "X",
+						last:   "Cringely"
+					}
+				});
+			t.is("Hello, Robert Cringely AKA Bob!", s1);
+
+			var s2 = dojo.replace("Hello, {0} {2}!", ["Robert", "X", "Cringely"]);
+			t.is("Hello, Robert Cringely!", s2);
+
+			function sum(a){
+				var t = 0;
+				dojo.forEach(a, function(x){ t += x; });
+				return t;
+			}
+			var s3 = dojo.replace(
+				"{count} payments averaging {avg} USD per payment.",
+				dojo.hitch(
+					{ payments: [11, 16, 12] },
+					function(_, key){
+						switch(key){
+							case "count": return this.payments.length;
+							case "min":   return Math.min.apply(Math, this.payments);
+							case "max":   return Math.max.apply(Math, this.payments);
+							case "sum":   return sum(this.payments);
+							case "avg":   return sum(this.payments) / this.payments.length;
+						}
+						return "";
+					}
+				));
+			t.is("3 payments averaging 13 USD per payment.", s3);
+
+			var s4 = dojo.replace("Hello, ${0} ${2}!", ["Robert", "X", "Cringely"], /\$\{([^\}]+)\}/g);
+			t.is("Hello, Robert Cringely!", s4);
+		}
+	]
+);
\ No newline at end of file
diff --git a/dojo/tests/_base/object.js b/dojo/tests/_base/object.js
new file mode 100644
index 0000000..bc0cea2
--- /dev/null
+++ b/dojo/tests/_base/object.js
@@ -0,0 +1,42 @@
+dojo.provide("tests._base.object");
+
+// setup the test object
+dojo.zoo = { a:1, c: { d:1 } };
+
+tests.register("tests._base.object",
+	[
+	
+		function getBasic(t){
+			var x = dojo.getObject('dojo.zoo.a');
+			t.is(1, x);
+		},
+			
+		function setObject2(t){
+			dojo.setObject("dojo.zoo.foo.bar", 42);
+			t.is(42, dojo.zoo.foo.bar);
+		},
+				
+		function setWithContext(t){
+			// c is already {}
+			dojo.setObject("zoo.c.x", "foo!", dojo);
+			t.is("foo!", dojo.zoo.c.x);
+		},
+				
+		function getUndefined(t){
+			var x = dojo.getObject('dojo.zoo.b');
+			t.is(undefined, x);
+		},
+				
+		function setDeep(t){
+			dojo.setObject("dojo.zoo.c.e.f.g.h.i", 42);
+			t.is(42, dojo.zoo.c.e.f.g.h.i);
+		},
+		
+		function getDeep(t){
+			dojo.getObject("dojo.zoo.bar.baz.bam", true);
+			dojo.zoo.bar.baz.bam.x = 10;
+			t.is(10, dojo.zoo.bar.baz.bam.x);
+		}
+
+	]
+);
diff --git a/dojo/tests/_base/query.html b/dojo/tests/_base/query.html
new file mode 100644
index 0000000..55c3f3c
--- /dev/null
+++ b/dojo/tests/_base/query.html
@@ -0,0 +1,325 @@
+<html>
+	<head>
+		<title>testing dojo.query()</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" src="../../dojo.js" 
+			djConfig="isDebug: true, debugAtAllCosts: false, popup: false, noFirebugLite: true"></script>
+		<!--
+		<script type="text/javascript" src="../_base/query.js"></script>
+		-->
+		<script type="text/javascript" src="../../../util/doh/runner.js"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+
+			function createDocument(xml){
+				var fauxXhr = { responseText: xml };
+				if("DOMParser" in dojo.global){
+					var parser = new DOMParser();
+					fauxXhr.responseXML = parser.parseFromString(xml, "text/xml");
+				}
+				// kludge: use dojo.xhr contentHandler for XML to process IE XMLDOC as needed
+				return dojo._contentHandlers["xml"](fauxXhr); // DOMDocument
+			}
+
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						// "doh.t(false, 'howdy!')",
+						// "doh.f(true, 'howdy!')",
+						// "doh.e(Error, window, function(){ throw new Error(); })",
+
+						// basic sanity checks
+						"doh.is(4, (dojo.query('h3')).length);",
+						"doh.is(1, (dojo.query('h1:first-child')).length);",
+						"doh.is(2, (dojo.query('h3:first-child')).length);",
+						"doh.is(1, (dojo.query('#t')).length);",
+						"doh.is(1, (dojo.query('#bug')).length);",
+						"doh.is(4, (dojo.query('#t h3')).length);",
+						"doh.is(1, (dojo.query('div#t')).length);",
+						"doh.is(4, (dojo.query('div#t h3')).length);",
+						"doh.is(0, (dojo.query('span#t')).length);",
+						"doh.is(0, (dojo.query('.bogus')).length);",
+						"doh.is(0, (dojo.query('.bogus', dojo.byId('container'))).length);",
+						"doh.is(0, (dojo.query('#bogus')).length);",
+						"doh.is(0, (dojo.query('#bogus', dojo.byId('container'))).length);",
+						"doh.is(1, (dojo.query('#t div > h3')).length);",
+						"doh.is(2, (dojo.query('.foo')).length);",
+						"doh.is(1, (dojo.query('.foo.bar')).length);",
+						"doh.is(2, (dojo.query('.baz')).length);",
+						"doh.is(3, (dojo.query('#t > h3')).length);",
+
+						"doh.is(2, (dojo.query('#baz,#foo,#t')).length);",
+
+						"doh.is(1, dojo.query('.fooBar').length);",
+
+						// syntactic equivalents
+						"doh.is(12, (dojo.query('#t > *')).length);",
+						"doh.is(12, (dojo.query('#t >')).length);",
+						"doh.is(3, (dojo.query('.foo >')).length);",
+						"doh.is(3, (dojo.query('.foo > *')).length);",
+
+						// with a root, by ID
+						"doh.is(3, (dojo.query('> *', 'container')).length);",
+						"doh.is(3, (dojo.query('> h3', 't')).length);",
+
+						// compound queries
+						"doh.is(2, (dojo.query('.foo, .bar')).length);",
+						"doh.is(2, (dojo.query('.foo,.bar')).length);",
+
+						// multiple class attribute
+						"doh.is(1, (dojo.query('.foo.bar')).length);",
+						"doh.is(2, (dojo.query('.foo')).length);",
+						"doh.is(2, (dojo.query('.baz')).length);",
+
+						// case sensitivity
+						"doh.is(1, (dojo.query('span.baz')).length);",
+						"doh.is(1, (dojo.query('sPaN.baz')).length);",
+						"doh.is(1, (dojo.query('SPAN.baz')).length);",
+						"doh.is(1, (dojo.query('[class = \"foo bar\"]')).length);",
+						"doh.is(2, (dojo.query('[foo~=\"bar\"]')).length);",
+						"doh.is(2, (dojo.query('[ foo ~= \"bar\" ]')).length);",
+
+						// "t.is(0, (dojo.query('[ foo ~= \"\\'bar\\'\" ]')).length);",
+						"doh.is(3, (dojo.query('[foo]')).length);",
+						"doh.is(1, (dojo.query('[foo$=\"thud\"]')).length);",
+						"doh.is(1, (dojo.query('[foo$=thud]')).length);",
+						"doh.is(1, (dojo.query('[foo$=\"thudish\"]')).length);",
+						"doh.is(1, (dojo.query('#t [foo$=thud]')).length);",
+						"doh.is(1, (dojo.query('#t [ title $= thud ]')).length);",
+						"doh.is(0, (dojo.query('#t span[ title $= thud ]')).length);",
+						"doh.is(1, (dojo.query('[foo|=\"bar\"]')).length);",
+						"doh.is(1, (dojo.query('[foo|=\"bar-baz\"]')).length);",
+						"doh.is(0, (dojo.query('[foo|=\"baz\"]')).length);",
+						"doh.is(dojo.byId('_foo'), dojo.query('.foo:nth-child(2)')[0]);",
+						"doh.is(dojo.query('style')[0], dojo.query(':nth-child(2)')[0]);",
+
+						// descendant selectors
+						"doh.is(3, dojo.query('>', 'container').length);",
+						"doh.is(3, dojo.query('> *', 'container').length);",
+						"doh.is(2, dojo.query('> [qux]', 'container').length);",
+						"doh.is('child1', dojo.query('> [qux]', 'container')[0].id);",
+						"doh.is('child3', dojo.query('> [qux]', 'container')[1].id);",
+						"doh.is(3, dojo.query('>', 'container').length);",
+						"doh.is(3, dojo.query('> *', 'container').length);",
+						"doh.is(3, dojo.query('>*', 'container').length);",
+						"doh.is('passed', dojo.query('#bug')[0].value);",
+
+						// bug 9071
+						"doh.is(2, (dojo.query('a', 't4')).length);",
+						"doh.is(2, (dojo.query('p a', 't4')).length);",
+						"doh.is(2, (dojo.query('div p', 't4')).length);",
+						"doh.is(2, (dojo.query('div p a', 't4')).length);",
+						"doh.is(2, (dojo.query('.subA', 't4')).length);",
+						"doh.is(2, (dojo.query('.subP .subA', 't4')).length);",
+						"doh.is(2, (dojo.query('.subDiv .subP', 't4')).length);",
+						"doh.is(2, (dojo.query('.subDiv .subP .subA', 't4')).length);",
+
+
+						// failed scope arg
+						"doh.is(0, (dojo.query('*', 'thinger')).length);",
+						"doh.is(0, (dojo.query('div#foo').length));",
+
+						// sibling selectors
+						"doh.is(1, dojo.query('+', 'container').length);",
+						"doh.is(3, dojo.query('~', 'container').length);",
+						"doh.is(1, (dojo.query('.foo+ span')).length);",
+						"doh.is(1, (dojo.query('.foo+span')).length);",
+						"doh.is(1, (dojo.query('.foo +span')).length);",
+						"doh.is(1, (dojo.query('.foo + span')).length);",
+						"doh.is(4, (dojo.query('.foo~ span')).length);",
+						"doh.is(4, (dojo.query('.foo~span')).length);",
+						"doh.is(4, (dojo.query('.foo ~span')).length);",
+						"doh.is(4, (dojo.query('.foo ~ span')).length);",
+						"doh.is(1, (dojo.query('#foo~ *')).length);",
+						"doh.is(1, (dojo.query('#foo ~*')).length);",
+						"doh.is(1, (dojo.query('#foo ~*')).length);",
+						"doh.is(1, (dojo.query('#foo ~ *')).length);",
+						"doh.is(1, (dojo.query('#foo ~')).length);",
+						"doh.is(1, (dojo.query('#foo~')).length);",
+
+						// sub-selector parsing
+						"doh.is(1, dojo.query('#t span.foo:not(span:first-child)').length);",
+						"doh.is(1, dojo.query('#t span.foo:not(:first-child)').length);",
+
+						// nth-child tests
+						"doh.is(2, dojo.query('#t > h3:nth-child(odd)').length);",
+						"doh.is(3, dojo.query('#t h3:nth-child(odd)').length);",
+						"doh.is(3, dojo.query('#t h3:nth-child(2n+1)').length);",
+						"doh.is(1, dojo.query('#t h3:nth-child(even)').length);",
+						"doh.is(1, dojo.query('#t h3:nth-child(2n)').length);",
+						"doh.is(1, dojo.query('#t h3:nth-child(2n+3)').length);",
+						"doh.is(2, dojo.query('#t h3:nth-child(1)').length);",
+						"doh.is(1, dojo.query('#t > h3:nth-child(1)').length);",
+						"doh.is(3, dojo.query('#t :nth-child(3)').length);",
+						"doh.is(0, dojo.query('#t > div:nth-child(1)').length);",
+						"doh.is(7, dojo.query('#t span').length);",
+						"doh.is(3, dojo.query('#t > *:nth-child(n+10)').length);",
+						"doh.is(1, dojo.query('#t > *:nth-child(n+12)').length);",
+						"doh.is(10, dojo.query('#t > *:nth-child(-n+10)').length);",
+						"doh.is(5, dojo.query('#t > *:nth-child(-2n+10)').length);",
+						"doh.is(6, dojo.query('#t > *:nth-child(2n+2)').length);",
+						"doh.is(5, dojo.query('#t > *:nth-child(2n+4)').length);",
+						"doh.is(5, dojo.query('#t > *:nth-child(2n+4)').length);",
+						"doh.is(5, dojo.query('#t> *:nth-child(2n+4)').length);",
+						"doh.is(12, dojo.query('#t > *:nth-child(n-5)').length);",
+						"doh.is(12, dojo.query('#t >*:nth-child(n-5)').length);",
+						"doh.is(6, dojo.query('#t > *:nth-child(2n-5)').length);",
+						"doh.is(6, dojo.query('#t>*:nth-child(2n-5)').length);",
+						
+						// :checked pseudo-selector
+						"doh.is(2, dojo.query('#t2 > :checked').length);",
+						"doh.is(dojo.byId('checkbox2'), dojo.query('#t2 > input[type=checkbox]:checked')[0]);",
+						"doh.is(dojo.byId('radio2'), dojo.query('#t2 > input[type=radio]:checked')[0]);",
+						"doh.is(2, dojo.query('#t2select option:checked').length);",
+						
+						// check for correct document order
+						function domOrder() {
+							var inputs = dojo.query(".upperclass .lowerclass input");
+							doh.is("notbug", inputs[0].id);
+							doh.is("bug", inputs[1].id);
+							doh.is("checkbox1", inputs[2].id);
+							doh.is("checkbox2", inputs[3].id);
+							doh.is("radio1", inputs[4].id);
+							doh.is("radio2", inputs[5].id);
+							doh.is("radio3", inputs[6].id);
+						},
+
+						// cross-document queries
+						{
+
+							name: "crossDocumentQuery",
+							setUp: function(){
+								dojo.require("dojo.io.iframe");
+								this.t3 = window.frames["t3"];
+								this.doc = dojo.io.iframe.doc(t3);
+								this.doc.open();
+								this.doc.write([
+									"<html><head>",
+									"<title>inner document</title>",
+									"</head>",
+									"<body>",
+									"<div id='st1'><h3>h3 <span>span <span> inner <span>inner-inner</span></span></span> endh3 </h3></div>",
+									"</body>",
+									"</html>"
+								].join(""));
+							},
+							runTest: function(){
+								doh.is(1, dojo.query('h3', dojo.byId("st1", this.doc)).length);
+								// use a long query to force a test of the XPath system on FF. see bug #7075
+								doh.is(1, dojo.query('h3 > span > span > span', dojo.byId("st1", this.doc)).length);
+								doh.is(1, dojo.query('h3 > span > span > span', this.doc.body.firstChild).length);
+							}
+						},
+
+						// :empty pseudo-selector
+						"doh.is(4, dojo.query('#t > span:empty').length);",
+						"doh.is(6, dojo.query('#t span:empty').length);",
+						"doh.is(0, dojo.query('h3 span:empty').length);",
+						"doh.is(1, dojo.query('h3 :not(:empty)').length);",
+
+						// escaping of ":" chars inside an ID
+						function silly_IDs1(){
+							doh.t(document.getElementById("silly:id::with:colons"));
+							doh.is(1, dojo.query("#silly\\:id\\:\\:with\\:colons").length);
+						},
+						function NodeList_identity(){
+							var foo = new dojo.NodeList([dojo.byId("container")]);
+							doh.is(foo, dojo.query(foo));
+						},
+						function xml(){
+							var doc = createDocument([
+								"<ResultSet>",
+									"<Result>One</Result>",
+									"<RESULT>Two</RESULT>",
+									"<result>Three</result>",
+									"<result>Four</result>",
+								"</ResultSet>"
+							].join("")
+							);
+							var de = doc.documentElement;
+
+							doh.is(2, dojo.query("result", de).length, "all lower");
+							doh.is(1, dojo.query("Result", de).length, "mixed case");
+							doh.is(1, dojo.query("RESULT", de).length, "all upper");
+							doh.is(0, dojo.query("resulT", de).length, "no match");
+							doh.is(0, dojo.query("rEsulT", de).length, "no match");
+						},
+						function xml_attrs(){
+							var doc = createDocument([
+								"<ResultSet>",
+									"<RESULT thinger='blah'>Two</RESULT>",
+									"<RESULT thinger='gadzooks'>Two</RESULT>",
+								"</ResultSet>"
+							].join(""));
+							var de = doc.documentElement;
+
+							doh.is(2, dojo.query("RESULT", de).length, "result elements");
+							doh.is(0, dojo.query("RESULT[THINGER]", de).length, "result elements with attrs (wrong)");
+							doh.is(2, dojo.query("RESULT[thinger]", de).length, "result elements with attrs");
+							doh.is(1, dojo.query("RESULT[thinger=blah]", de).length, "result elements with attr value");
+						},
+						function sort(){
+							var i = dojo.query("div");
+							// smoke test
+							i.sort(function(a,b){ return 1; })
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body class="upperclass">
+		<h1>testing dojo.query()</h1>
+		<div id="t" class="lowerclass">
+			<h3>h3 <span>span</span> endh3 </h3>
+			<!-- comment to throw things off -->
+			<div class="foo bar" id="_foo">
+				<h3>h3</h3>
+				<span id="foo"></span>
+				<span></span>
+			</div>
+			<h3>h3</h3>
+			<h3 class="baz foobar" title="thud">h3</h3>
+			<span class="fooBar baz foo"></span>
+			<span foo="bar"></span>
+			<span foo="baz bar thud"></span>
+			<!-- FIXME: should foo="bar-baz-thud" match? [foo$=thud] ??? -->
+			<span foo="bar-baz-thudish" id="silly:id::with:colons"></span>
+			<div id="container">
+				<div id="child1" qux="true"></div>
+				<div id="child2"></div>
+				<div id="child3" qux="true"></div>
+			</div>
+			<div qux="true"></div>
+			<input id="notbug" name="bug" type="hidden" value="failed"> 
+			<input id="bug" type="hidden" value="passed"> 
+		</div>
+		<div id="t2" class="lowerclass">
+			<input type="checkbox" name="checkbox1" id="checkbox1" value="foo">
+			<input type="checkbox" name="checkbox2" id="checkbox2" value="bar" checked>
+
+			<input type="radio" name="radio" id="radio1" value="thinger">
+			<input type="radio" name="radio" id="radio2" value="stuff" checked>
+			<input type="radio" name="radio" id="radio3" value="blah">
+		</div>
+		<select id="t2select" multiple="multiple">
+			<option>0</option>
+			<option selected="selected">1</option>
+			<option selected="selected">2</option>
+		</select>
+		
+		<iframe id="t3" name="t3" src="../../resources/blank.html"></iframe>
+		<div id="t4">
+			<div id="one" class="subDiv">
+				<p class="one subP"><a class="subA">one</a></p>
+				<div id="two" class="subDiv">
+					<p class="two subP"><a class="subA">two</a></p>
+				</div>
+			</div>
+		</div>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/query.js b/dojo/tests/_base/query.js
new file mode 100644
index 0000000..3cd6738
--- /dev/null
+++ b/dojo/tests/_base/query.js
@@ -0,0 +1,5 @@
+dojo.provide("tests._base.query");
+if(dojo.isBrowser){
+	doh.registerUrl("tests._base.query", dojo.moduleUrl("tests", "_base/query.html"));
+	doh.registerUrl("tests._base.NodeList", dojo.moduleUrl("tests", "_base/NodeList.html"));
+}
diff --git a/dojo/tests/_base/queryPortability.html b/dojo/tests/_base/queryPortability.html
new file mode 100644
index 0000000..56a47c8
--- /dev/null
+++ b/dojo/tests/_base/queryPortability.html
@@ -0,0 +1,24 @@
+<html>
+	<head>
+		<title>look ma! query, but no Dojo!</title>
+
+		<!-- we pull in query.js, but not the rest of Dojo -->
+		<script type="text/javascript" src="../../_base/query.js"></script>
+
+		<!-- test it out! -->
+		<script type="text/javascript">
+			$ = acme.query;
+			window.onload = function(){
+				alert($("p.stranger")[1].innerHTML + " stranger");
+			}
+		</script>
+	</head>
+	<body class="tundra">
+		<p>howdy!</p>
+		<p class="stranger">howdy!</p>
+		<p class="stranger">howdy</p>
+		<p>howdy!</p>
+		<div>thinger</div>
+		<!-- ... -->
+	</body>
+</html>
diff --git a/dojo/tests/_base/timeout.php b/dojo/tests/_base/timeout.php
new file mode 100644
index 0000000..560b0d3
--- /dev/null
+++ b/dojo/tests/_base/timeout.php
@@ -0,0 +1,7 @@
+<?php
+
+$callbackName = $_REQUEST["callback"];
+sleep(5);
+print "SuperXFooBarVariable = 'Oh no! SuperXFooBarVariable is defined (should not be for timeout case).'; {$callbackName}({Status: 'good'});";
+
+?>
diff --git a/dojo/tests/_base/window.js b/dojo/tests/_base/window.js
new file mode 100644
index 0000000..f57e37e
--- /dev/null
+++ b/dojo/tests/_base/window.js
@@ -0,0 +1,52 @@
+dojo.provide("tests._base.window");
+
+tests.register("tests._base.window", 
+	[
+		function withGlobal(t){
+			var arg1, arg2, innerThis, innerGlobal, innerDoc, finished,
+				globalObj = {test: "myGlobal", document: {test: "myDoc"}},
+				thisObj = {test: "myThis"};
+
+			try {
+				dojo.withGlobal(globalObj, function(a1, a2){
+					arg1 = a1;
+					arg2 = a2;
+					innerThis = this.test;
+					innerGlobal = dojo.global.test;
+					innerDoc = dojo.doc.test
+					finished = true;
+				}, thisObj, [1, 2])
+			}catch(e){}
+
+			t.assertTrue(finished);
+			t.assertEqual(1, arg1);
+			t.assertEqual(2, arg2);
+			t.assertEqual("myThis", innerThis);
+			t.assertEqual("myGlobal", innerGlobal);
+			t.assertEqual("myDoc", innerDoc);
+		},
+
+		function withDoc(t){
+			var arg1, arg2, innerThis, innerGlobal, innerDoc, finished,
+				docObj = {test: "myDoc"},
+				thisObj = {test: "myThis"};
+
+			try {
+				dojo.withDoc(docObj, function(a1, a2){
+					arg1 = a1;
+					arg2 = a2;
+					innerThis = this.test;
+					innerDoc = dojo.doc.test
+					finished = true;
+				}, thisObj, [1, 2])
+			}catch(e){}
+
+			t.assertTrue(finished);
+			t.assertEqual(1, arg1);
+			t.assertEqual(2, arg2);
+			t.assertEqual("myThis", innerThis);
+			t.assertEqual("myDoc", innerDoc);
+		}
+	]
+);
+
diff --git a/dojo/tests/_base/xhr.html b/dojo/tests/_base/xhr.html
new file mode 100644
index 0000000..6d275d1
--- /dev/null
+++ b/dojo/tests/_base/xhr.html
@@ -0,0 +1,519 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>testing form and xhr utils</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" djConfig="isDebug: true, ioPublish: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.addOnLoad(function(){
+				var f1NoValueObj = null;
+				var f1NoValue2Obj = 'blah';
+				var f2MultiObj = [ 'thud', 'thonk' ];
+				var f2TextareaObj = 'textarea_value';
+				var f2fileParam1Obj = '';
+				var f4ActionObj = 'Form with input named action';
+				var f6Checkbox1Obj = 'foo';
+				var f6Checkbox2Obj = null;
+				var f6Radio1Obj = null;
+				var f6Radio2Obj = 'bam';
+				
+				
+				var f1fo = { 'blah': "blah" };
+				var f1foStr = "blah=blah";
+				var f1foJson = '{"blah":"blah"}';
+
+				var f2fo = { 
+					blah: "blah",
+					multi: [
+						"thud",
+						"thonk"
+					],
+					textarea: "textarea_value"
+				};
+				var f2foStr = "blah=blah&multi=thud&multi=thonk&textarea=textarea_value";
+				var f2foJson = '{"blah":"blah","multi":["thud","thonk"],"textarea":"textarea_value"}';
+
+				var f3fo = { 
+					spaces: "string with spaces"
+				};
+				var f3foStr = "spaces=string%20with%20spaces&";
+				var f3foJson = '{"spaces":"string with spaces"}';
+
+				var f5fo = { 'blåh': "bláh" };
+				var f5foStr = "bl%C3%A5h=bl%C3%A1h";
+				var f5foJson = '{"blåh":"bláh"}';
+
+				var f6fo = {
+					cb_group: "foo",
+					radio_group: "bam"
+				};
+
+				var f6fo1 = {
+					cb_group: "boo",
+					radio_group: "baz"
+				};
+
+				var f6fo2 = {
+					cb_group: ["foo","boo"],
+					radio_group: "baz"
+				};
+
+				var topics = [
+					"/dojo/io/start",
+					"/dojo/io/send",
+					"/dojo/io/load",
+					"/dojo/io/error",
+					"/dojo/io/done",
+					"/dojo/io/stop"
+				];
+
+				var topicCount = {
+				};
+
+				dojo.forEach(topics, function(topic){
+					topicCount[topic] = 0;
+					dojo.subscribe(topic, function(){
+						topicCount[topic] += 1;
+						console.log("##"+ topic + ": " + topicCount[topic]);
+					});
+				});
+
+				doh.register("t", 
+					[
+						function inputNodeValueFromId(t){
+							t.is(f1NoValueObj, dojo.fieldToObject('f1_no_value'));
+							t.is(f1NoValue2Obj, dojo.fieldToObject('f1_no_value2'));
+							t.is(f2MultiObj, dojo.fieldToObject('f2_multi'));
+							t.is(f2TextareaObj, dojo.fieldToObject('f2_textarea'));
+							t.is(f2fileParam1Obj, dojo.fieldToObject('f2_fileParam1'));
+							t.is(f4ActionObj, dojo.fieldToObject('f4_action'));
+							t.is(f6Checkbox1Obj, dojo.fieldToObject('f6_checkbox1'));
+							t.is(f6Checkbox2Obj, dojo.fieldToObject('f6_checkbox2'));
+							t.is(f6Radio1Obj, dojo.fieldToObject('f6_radio1'));
+							t.is(f6Radio2Obj, dojo.fieldToObject('f6_radio2'));
+							t.is(null, dojo.fieldToObject('some_id_that_doesnt_exist'));
+						},
+						
+						function formNodeValueFromNode(t){
+							t.is(f1NoValueObj, dojo.fieldToObject(dojo.byId('f1_no_value')));
+							t.is(f1NoValue2Obj, dojo.fieldToObject(dojo.byId('f1_no_value2')));
+							t.is(f2MultiObj, dojo.fieldToObject(dojo.byId('f2_multi')));
+							t.is(f2TextareaObj, dojo.fieldToObject(dojo.byId('f2_textarea')));
+							t.is(f2fileParam1Obj, dojo.fieldToObject(dojo.byId('f2_fileParam1')));
+							t.is(f4ActionObj, dojo.fieldToObject(dojo.byId('f4_action')));
+							t.is(f6Checkbox1Obj, dojo.fieldToObject(dojo.byId('f6_checkbox1')));
+							t.is(f6Checkbox2Obj, dojo.fieldToObject(dojo.byId('f6_checkbox2')));
+							t.is(f6Radio1Obj, dojo.fieldToObject(dojo.byId('f6_radio1')));
+							t.is(f6Radio2Obj, dojo.fieldToObject(dojo.byId('f6_radio2')));
+							t.is(null, dojo.fieldToObject(dojo.byId('some_id_that_doesnt_exist')));
+						},
+						function formNodeToObject(t){
+							t.is(f1fo , dojo.formToObject(dojo.byId("f1")));
+							t.is(f5fo , dojo.formToObject(dojo.byId("f5")));
+						},
+						function formIdToObject(t){
+							t.is(f1fo , dojo.formToObject("f1"));
+							t.is(f5fo , dojo.formToObject("f5"));
+						},
+						function formToObjectRadioGroup(t){
+							t.is(f6fo , dojo.formToObject("f6"));
+							
+							dojo.byId('f6_checkbox1').checked = false;
+							dojo.byId('f6_checkbox2').checked = true;
+							dojo.byId('f6_radio1').checked = true;
+							t.is(f6fo1 , dojo.formToObject("f6"));
+
+							dojo.byId('f6_checkbox1').checked = true;
+							t.is(f6fo2 , dojo.formToObject("f6"));
+
+							dojo.byId('f6_checkbox2').checked = false; // reset back to defaults
+							dojo.byId('f6_radio2').checked = true;
+						},
+						function formToObjectWithMultiSelect(t){
+							t.is(f2fo , dojo.formToObject("f2"));
+						},
+						function objectToQuery(t){
+							t.is(f1foStr , dojo.objectToQuery(f1fo));
+							t.is(f5foStr , dojo.objectToQuery(f5fo));
+						},
+						function objectToQueryArr(t){
+							t.is(f2foStr, dojo.objectToQuery(f2fo));
+						},
+						function formToQuery(t){
+							t.is(f1foStr, dojo.formToQuery("f1"));
+							t.is(f5foStr, dojo.formToQuery("f5"));
+						},
+						function formToQueryArr(t){
+							t.is(f2foStr, dojo.formToQuery("f2"));
+						},
+						function formToJson(t){
+							t.is(f1foJson, dojo.formToJson("f1"));
+							t.is(f5foJson, dojo.formToJson("f5"));
+						},
+						function formToJsonArr(t){
+							t.is(f2foJson, dojo.formToJson("f2"));
+						},
+						function queryToObject(t){
+							t.is(f1fo , dojo.queryToObject(f1foStr));
+							t.is(f2fo , dojo.queryToObject(f2foStr));
+							t.is(f3fo , dojo.queryToObject(f3foStr));
+							t.is(f5fo , dojo.queryToObject(f5foStr));
+						},
+						function textContentHandler(t){
+							t.is("foo bar baz ", 
+								dojo._contentHandlers.text({
+									responseText: "foo bar baz "
+								})
+							);
+						},
+						function jsonContentHandler(t){
+							var jsonObj = {
+								foo: "bar",
+								baz: [
+									{ thonk: "blarg" },
+									"xyzzy!"
+								]
+							};
+							t.is(jsonObj, 
+								dojo._contentHandlers.json({
+									responseText: dojo.toJson(jsonObj)
+								})
+							);
+						},
+						function jsonCFContentHandler(t){
+							var jsonObj = {
+								foo: "bar",
+								baz: [
+									{ thonk: "blarg" },
+									"xyzzy!"
+								]
+							};
+							var e;
+							try{
+								dojo._contentHandlers["json-comment-filtered"]({
+									responseText: dojo.toJson(jsonObj)
+								})
+							}catch(ex){
+								e = ex;
+							}finally{
+								// did we fail closed?
+								t.is((typeof e), "object");
+							}
+							t.is(jsonObj,
+								dojo._contentHandlers["json-comment-filtered"]({
+									responseText: "\tblag\n/*"+dojo.toJson(jsonObj)+"*/\n\r\t\r"
+								})
+							);
+							t.is(jsonObj,
+								dojo._contentHandlers["json-comment-optional"]({
+									responseText: "\tblag\n/*"+dojo.toJson(jsonObj)+"*/\n\r\t\r"
+								})
+							);
+						},
+						function jsContentHandler(t){
+							var jsonObj = {
+								foo: "bar",
+								baz: [
+									{ thonk: "blarg" },
+									"xyzzy!"
+								]
+							};
+							t.is(jsonObj,
+								dojo._contentHandlers["javascript"]({
+									responseText: "("+dojo.toJson(jsonObj)+")"
+								})
+							);
+							t.t(dojo._contentHandlers["javascript"]({
+									responseText: "true;"
+								})
+							);
+							t.f(dojo._contentHandlers["javascript"]({
+									responseText: "false;"
+								})
+							);
+						},
+						function xmlContentHandler(t){
+							var fauxXhr = { responseText: "<foo><bar baz='thonk'>blarg</bar></foo>" };
+							if("DOMParser" in dojo.global){
+								var parser = new DOMParser();
+								fauxXhr.responseXML = parser.parseFromString(fauxXhr.responseText, "text/xml");
+							}
+							var xmlDoc = dojo._contentHandlers["xml"](fauxXhr);
+							t.is("foo", xmlDoc.documentElement.tagName);
+						},
+						function xhrGet(t){
+							var d = new doh.Deferred();
+							var td = dojo.xhrGet({
+								url: "xhr.html", // self
+								preventCache: true,
+								load: function(text, ioArgs){
+									t.is(4, ioArgs.xhr.readyState);
+									return text; //must return a value here or the parent test deferred fails.
+								}
+							});
+							t.t(td instanceof dojo.Deferred);
+							td.addCallback(d, "callback");
+							return d;
+						},
+						function xhrGet404(t){
+							var d = new doh.Deferred();
+							try{
+								var td = dojo.xhrGet({
+									url: "xhr_blarg.html", // doesn't exist
+									error: function(err, ioArgs){
+										t.is(404, ioArgs.xhr.status);
+										return err; //must return a value here or the parent test deferred fails.
+									}
+								});
+								// td.addErrback(d, "callback");
+							}catch(e){
+								d.callback(true);
+							}
+							// return d;
+						},
+						function xhrGetContent(t){
+							var d = new doh.Deferred();
+							var td = dojo.xhrGet({
+								url: "xhr.html?color=blue",
+								content: {
+									foo: [ "bar", "baz" ],
+									thud: "thonk",
+									xyzzy: 3
+								}
+							});
+							td.addCallback(function(text){
+								// console.debug(td, td.xhr, td.args);
+								t.is("xhr.html?color=blue&foo=bar&foo=baz&thud=thonk&xyzzy=3", 
+										td.ioArgs.url);
+								d.callback(true);
+							});
+							return d;
+						},
+						function xhrGetForm(t){
+							var d = new doh.Deferred();
+							var td = dojo.xhrGet({
+								url: "xhr.html", // self
+								form: "f3"
+							});
+							td.addCallback(function(xhr){
+								// console.debug(td.args.url);
+								t.is("xhr.html?spaces=string%20with%20spaces", td.ioArgs.url);
+								d.callback(true);
+							});
+							return d;
+						},
+						function xhrGetFormWithContent(t){
+							// ensure that stuff passed via content over-rides
+							// what's specified in the form
+							var d = new doh.Deferred();
+							var td = dojo.xhrGet({
+								url: "xhr.html", // self
+								form: "f3",
+								content: { spaces: "blah" }
+							});
+							td.addCallback(function(xhr){
+								// console.debug(td.args.url);
+								t.is("xhr.html?spaces=blah", td.ioArgs.url);
+								d.callback(true);
+							});
+							return d;
+						},
+						function xhrPost(t){
+							var d = new doh.Deferred();
+							var td = dojo.xhrPost({
+								url: "xhr.html?foo=bar", // self
+								content: { color: "blue"},
+								handle: function(res, ioArgs){
+									if((dojo._isDocumentOk(ioArgs.xhr))||
+										(ioArgs.xhr.status == 405)
+									){
+										d.callback(true);
+									}else{
+										d.errback(false);
+									}								
+								}
+							});
+							// t.t(td instanceof dojo.Deferred);
+							return d;
+						},
+						function xhrPostWithContent(t){
+							var d = new doh.Deferred();
+							var td = dojo.xhrPost({
+								url: "xhr.html",
+								content: {
+									foo: [ "bar", "baz" ],
+									thud: "thonk",
+									xyzzy: 3
+								}
+							});
+							td.addBoth(function(text){
+								t.is("foo=bar&foo=baz&thud=thonk&xyzzy=3", 
+										td.ioArgs.query);
+								if(	(dojo._isDocumentOk(td.ioArgs.xhr))||
+									(td.ioArgs.xhr.status == 405)
+								){
+									d.callback(true);
+								}else{
+									d.errback(false);
+								}
+							});
+							return d;
+						},
+						function xhrPostForm(t){
+							var d = new doh.Deferred();
+							var form = dojo.byId("f4");
+
+							//Make sure we can send a form to its 
+							//action URL.   See trac: #2844.
+							var td = dojo.xhrPost({
+								form: form
+							});
+							td.addCallback(function(){
+								d.callback(true);
+							});
+							td.addErrback(function(error){
+								d.callback(error);
+							});
+							// t.t(td instanceof dojo.Deferred);
+							return d;
+						},
+						function rawXhrPost(t){
+							var d = new doh.Deferred();
+							var td = dojo.rawXhrPost({
+								url: "xhr.html", // self
+								postData: "foo=bar&color=blue&height=average",
+								handle: function(res, ioArgs){
+									if((dojo._isDocumentOk(ioArgs.xhr))||
+										(ioArgs.xhr.status == 405)
+									){
+										d.callback(true);
+									}else{
+										d.errback(false);
+									}								
+								}
+							});
+							// t.t(td instanceof dojo.Deferred);
+							return d;
+						},
+						function xhrPut(t){
+							var d = new doh.Deferred();
+							var td = dojo.xhrPut({
+								url: "xhrDummyMethod.php?foo=bar", // self
+								content: { color: "blue"},
+								handle: function(res, ioArgs){
+									if((dojo._isDocumentOk(ioArgs.xhr))||
+										(ioArgs.xhr.status == 403)
+									){
+										d.callback(true);
+									}else{
+										d.errback(false);
+									}								
+								}
+							});
+							// t.t(td instanceof dojo.Deferred);
+							return d;
+						},
+						function xhrDelete(t){
+							var d = new doh.Deferred();
+							var td = dojo.xhrDelete({
+								url: "xhrDummyMethod.php", // self
+								preventCache: true,
+								handle: function(res, ioArgs){
+									if((dojo._isDocumentOk(ioArgs.xhr))||
+										(ioArgs.xhr.status == 403)
+									){
+										d.callback(true);
+									}else{
+										d.errback(false);
+									}								
+								}
+							});
+							// t.t(td instanceof dojo.Deferred);
+							return d;
+						},
+						function xhrCancel(t){
+							var d = new doh.Deferred();
+							var td = dojo.xhrPost({
+								url: "xhrDummyMethod.php", // self
+								handle: function(res, ioArgs){
+									if(res instanceof Error && res.dojoType == "cancel"){
+										d.callback(true);
+									}else{
+										d.errback(false);
+									}								
+								}
+							});
+							td.cancel();
+							// t.t(td instanceof dojo.Deferred);
+							return d;
+						},
+
+						function ioPublish(t){
+						
+							//These numbers will look a bit odd at this point, since
+							//some of the topics publish after this test is run.
+							
+							t.is(1, topicCount["/dojo/io/start"]);
+							t.is(12, topicCount["/dojo/io/send"]);
+							t.is(9, topicCount["/dojo/io/load"]);
+							t.is(2, topicCount["/dojo/io/error"]);
+							t.is(11, topicCount["/dojo/io/done"]);
+							t.is(0, topicCount["/dojo/io/stop"]);
+
+							/*
+							dojo.forEach(topics, function(topic){
+								console.log(topic + ": " + topicCount[topic]);
+							});
+							*/
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body>
+		<form id="f1" style="border: 1px solid black;">
+			<input id="f1_blah" type="text" name="blah" value="blah">
+			<input id="f1_no_value" type="text" name="no_value" value="blah" disabled>
+			<input  id="f1_no_value2" type="button" name="no_value2" value="blah">
+		</form>
+		<form id="f2" style="border: 1px solid black;">
+			<input id="f2_blah" type="text" name="blah" value="blah">
+			<input id="f2_no_value" type="text" name="no_value" value="blah" disabled>
+			<input  id="f2_no_value2" type="button" name="no_value2" value="blah">
+			<select  id="f2_multi" type="select" multiple name="multi" size="5">
+				<option value="blah">blah</option>
+				<option value="thud" selected>thud</option>
+				<option value="thonk" selected>thonk</option>
+			</select>
+			<textarea id="f2_textarea" name="textarea">textarea_value</textarea>
+			<button id="f2_button1" name="button1" value="buttonValue1">This is a button that should not be in formToObject.</button>
+			<input id="f2_fileParam1" type="file" name="fileParam1" value="fileValue1"> File input should not show up in formToObject.
+		</form>
+		<form id="f3" style="border: 1px solid black;">
+			<input id="f3_spaces" type="hidden" name="spaces" value="string with spaces">
+		</form>
+		<form id="f4" style="border: 1px solid black;" action="xhrDummyMethod.php">
+			<input id="f4_action" type="hidden" name="action" value="Form with input named action">
+		</form>
+		<form id="f5" style="border: 1px solid black;">
+			<input id="f5_blah" type="text" name="blåh" value="bláh">
+			<input id="f5_no_value" type="text" name="no_value" value="blah" disabled>
+			<input id="f5_no_value2" type="button" name="no_value2" value="blah">
+		</form>
+		<form id="f6" style="border: 1px solid black;">
+			<input id="f6_checkbox1" type="checkbox" name="cb_group" value="foo" checked>
+			<input id="f6_checkbox2" type="checkbox" name="cb_group" value="boo">
+			<input id="f6_radio1" type="radio" name="radio_group" value="baz">
+			<input id="f6_radio2" type="radio" name="radio_group" value="bam" checked>
+		</form>
+	</body>
+</html>
+
diff --git a/dojo/tests/_base/xhr.js b/dojo/tests/_base/xhr.js
new file mode 100644
index 0000000..bcbbc3e
--- /dev/null
+++ b/dojo/tests/_base/xhr.js
@@ -0,0 +1,4 @@
+dojo.provide("tests._base.xhr");
+if(dojo.isBrowser){
+	doh.registerUrl("tests._base.xhr", dojo.moduleUrl("tests", "_base/xhr.html"));
+}
diff --git a/dojo/tests/_base/xhr.xml b/dojo/tests/_base/xhr.xml
new file mode 100644
index 0000000..9f86784
--- /dev/null
+++ b/dojo/tests/_base/xhr.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<foo><bar baz='thonk'>blarg</bar></foo>
diff --git a/dojo/tests/_base/xhrDummyMethod.php b/dojo/tests/_base/xhrDummyMethod.php
new file mode 100644
index 0000000..c9206fe
--- /dev/null
+++ b/dojo/tests/_base/xhrDummyMethod.php
@@ -0,0 +1,7 @@
+<?php
+//Just a dummy end point to use in HTTP method calls like PUT and DELETE.
+//This avoids getting a 405 method not allowed calls for the tests that reference
+//this file.
+
+header("HTTP/1.1 200 OK");
+?>
diff --git a/dojo/tests/_base/xhtml.php b/dojo/tests/_base/xhtml.php
new file mode 100644
index 0000000..7134185
--- /dev/null
+++ b/dojo/tests/_base/xhtml.php
@@ -0,0 +1,29 @@
+<?
+	if(isset($_SERVER["HTTP_ACCEPT"]) && stristr( $_SERVER["HTTP_ACCEPT"], "application/xhtml+xml")){
+		header("Content-type: application/xhtml+xml");
+	}else{
+		header("Content-type: text/html");
+	}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml11-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+	<head>
+		<script type="text/javascript">
+			djConfig = { isDebug: true };
+		</script>
+		<script type="text/javascript" src="../../dojo.js"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				dojo.query("h1.thinger").forEach(function(n){
+					console.debug(n);
+				});
+			});
+		</script>
+	</head>
+	<body>
+		<h1 class="howdy thinger">hey there!</h1>
+		<h1 class="something else">...</h1>
+	</body>
+</html>
diff --git a/dojo/tests/back-hash.js b/dojo/tests/back-hash.js
new file mode 100644
index 0000000..82e7f8a
--- /dev/null
+++ b/dojo/tests/back-hash.js
@@ -0,0 +1,29 @@
+dojo.provide("tests.back-hash");
+
+dojo.require("dojo.back");
+
+(function(){
+	tests.register("tests.back.hash", [
+		function getAndSet(t) {
+			var cases = [
+				"test",
+				"test with spaces",
+				"test%20with%20encoded",
+				"test+with+pluses",
+				" leading",
+				"trailing ",
+				"under_score",
+				"extra#mark",
+				"extra?instring",
+				"extra&instring",
+				"#leadinghash"
+			];
+			var b = dojo.back;
+			function verify(s){
+				dojo.back.setHash(s);
+				t.is(s, dojo.back.getHash(s));
+			}
+			dojo.forEach(cases, verify);
+		}
+	]);
+})();
diff --git a/dojo/tests/back.html b/dojo/tests/back.html
new file mode 100644
index 0000000..1b9ca1c
--- /dev/null
+++ b/dojo/tests/back.html
@@ -0,0 +1,107 @@
+<html>
+<head>
+	<script language="JavaScript" type="text/javascript">
+		// Dojo configuration
+		djConfig = {
+			//debugAtAllCosts: true, //Don't normally need this in applications.
+			isDebug: true,
+			dojoIframeHistoryUrl: "../../resources/iframe_history.html" //for xdomain
+		};
+	</script>
+	<script type="text/javascript" 
+	        src="../dojo.js" 
+	        djConfig="isDebug:true, dojoIframeHistoryUrl: '../resources/iframe_history.html'"></script>
+	<script type="text/javascript" src="../back.js"></script>
+	<script type="text/javascript">	
+		ApplicationState = function(stateData, outputDivId, backForwardOutputDivId, bookmarkValue){
+			this.stateData = stateData;
+			this.outputDivId = outputDivId;
+			this.backForwardOutputDivId = backForwardOutputDivId;
+			this.changeUrl = bookmarkValue || false;
+		}
+	
+		dojo.extend(ApplicationState, {
+			back: function(){
+				this.showBackForwardMessage("BACK for State Data: " + this.stateData);
+				this.showStateData();
+			},
+			forward: function(){
+				this.showBackForwardMessage("FORWARD for State Data: " + this.stateData);
+				this.showStateData();
+			},
+			showStateData: function(){
+				dojo.byId(this.outputDivId).innerHTML += this.stateData + '<br />';
+			},
+			showBackForwardMessage: function(message){
+				dojo.byId(this.backForwardOutputDivId).innerHTML += message + '<br />';
+			}
+		});
+		
+		var data = {
+			link0: "This is the initial state (page first loaded)",
+			"link with spaces": "This is data for a state with spaces",
+			"link%20with%20encoded": "This is data for a state with encoded bits",
+			"link+with+pluses": "This is data for a state with pluses",
+			link1: "This is data for link 1",
+			link2: "This is data for link 2",
+			link3: "This is data for link 3",
+			link4: "This is data for link 4",
+			link5: "This is data for link 5",
+			link6: "This is data for link 6",
+			link7: "This is data for link 7"
+		};
+
+		function goNav(id){
+			var appState = new ApplicationState(data[id], "output", "dataOutput", id);
+			appState.showStateData();
+			dojo.back.addToHistory(appState);
+		}
+
+		dojo.addOnLoad(function(){
+			var appState = new ApplicationState(data["link0"], "output", "dataOutput");
+			appState.showStateData();
+			dojo.back.setInitialState(appState);
+		});
+	</script>
+</head>
+<body>
+	<script type="text/javascript">dojo.back.init();</script>
+	<div style="padding-bottom: 20px; width: 100%; border-bottom: 1px solid gray">
+	<h3>dojo.back test</h3>
+	
+	
+	<p>This page tests the dojo.back back/forward code.</p>
+	
+	<p>The buttons that start with "Link" on them don't use any dojo.xhr* calls,
+	just JS data already in the page.</p>
+	
+	<ul>
+		<li>Don't test this page using local disk for MSIE. MSIE will not
+		create a history list for iframe_history.html if served from a file:
+		URL. Serve the test pages from a web server to test in that browser.</li>
+		<li>Safari 2.0.3+ (and probably 1.3.2+): Only the back button works OK
+		(not the forward button).</li>
+		<li>Opera 8.5.3: Does not work.</li>
+		<li>Konqueror: Unknown. The latest may have Safari's behavior.</li>
+	</ul>
+	</div>
+	<div style="float:left; padding: 20px">
+		<button onclick="goNav('link1')">Link 1</button><br />
+		<button onclick="goNav('link with spaces')">Link with Spaces</button><br />
+		<button onclick="goNav('link%20with%20encoded')">Link with Encoded</button><br />
+		<button onclick="goNav('link+with+pluses')">Link with Pluses</button><br />
+		<button onclick="goNav('link3')">Link 3</button><br />
+		<button onclick="goNav('link4')">Link 4</button><br />
+		<button onclick="goNav('link5')">Link 5</button><br />
+		<button onclick="goNav('link6')">Link 6</button><br />
+		<button onclick="goNav('link7')">Link 7</button><br />
+	</div>
+	<div style="float: left; padding: 20px">
+		<b>Data Output:</b><br />
+		<div id="output"></div>
+		<hr />
+		<i>Back/Forward Info:</i><br />
+		<div id="dataOutput"></div>
+	</div>
+</body>
+</html>
diff --git a/dojo/tests/back.js b/dojo/tests/back.js
new file mode 100644
index 0000000..2647b7b
--- /dev/null
+++ b/dojo/tests/back.js
@@ -0,0 +1,4 @@
+dojo.provide("tests.back");
+if(dojo.isBrowser){
+	doh.registerUrl("tests.back", dojo.moduleUrl("tests", "back.html"));
+}
diff --git a/dojo/tests/behavior.html b/dojo/tests/behavior.html
new file mode 100644
index 0000000..280fc29
--- /dev/null
+++ b/dojo/tests/behavior.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Testing dojo.behavior</title>
+		<style type="text/css">
+			@import "../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../dojo.js" djConfig="isDebug: true, popup: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.require("dojo.behavior");
+
+			var applyCount = 0;
+
+			var behaviorObj = {
+				".bar": 		function(elem){ 
+					dojo.style(elem, "opacity", 0.5);
+					applyCount++;
+				},
+				".foo > span":	function(elem){ 
+					elem.style.fontStyle = "italic";
+					applyCount++;
+				}
+			}
+
+			topicCount = 0;
+			dojo.subscribe("/foo", function(){ topicCount++; });
+
+			// no behaviors should be executed when onload fires
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						function add(t){
+							t.f(dojo.behavior._behaviors[".bar"]);
+							t.f(dojo.behavior._behaviors[".foo > span"]);
+							dojo.behavior.add(behaviorObj);
+							// make sure they got plopped in
+							t.t(dojo.behavior._behaviors[".bar"]);
+							t.is(1, dojo.behavior._behaviors[".bar"].length);
+							t.t(dojo.behavior._behaviors[".foo > span"]);
+							t.is(1, dojo.behavior._behaviors[".foo > span"].length);
+						},
+						function apply(t){
+							t.is(0, applyCount);
+							dojo.behavior.apply();
+							t.is(2, applyCount);
+
+							// reapply and make sure we only match once
+							dojo.behavior.apply();
+							t.is(2, applyCount);
+						},
+						function reapply(t){
+							t.is(2, applyCount);
+							// add the rules again
+							dojo.behavior.add(behaviorObj);
+							dojo.behavior.apply();
+							t.is(4, applyCount);
+							// dojo.behavior.apply();
+							// t.is(4, applyCount);
+							// dojo.query(".bar").styles("opacity", 1.0);
+						},
+						function topics(t){
+							var d = new doh.Deferred();
+							t.is(0, topicCount);
+							dojo.behavior.add({ ".foo": "/foo" });
+							dojo.behavior.apply();
+							t.is(2, topicCount);
+
+							dojo.behavior.add({ ".foo": {
+									"onfocus": "/foo" 
+								}
+							});
+							dojo.behavior.apply();
+							t.is(2, topicCount);
+							dojo.byId("blah").focus();
+							dojo.byId("blah").blur();
+							dojo.byId("blah").focus();
+							setTimeout(function(){
+								// blur/focus event generation isn't synchronous on IE
+								try{
+									t.is(4, topicCount);
+									d.callback(true);
+								}catch(e){
+									d.errback(e);
+								}
+							}, 10);
+							return d;
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body>
+		<div class="foo" id="fooOne">
+			<span>.foo > span</span>	
+			<div class="bar">
+				<span>.foo > .bar > span</span>	
+			</div>
+		</div>
+		<input type="text" id="blah" class="foo blah" name="thinger" value="thinger" tabIndex="0">
+	</body>
+</html>
diff --git a/dojo/tests/behavior.js b/dojo/tests/behavior.js
new file mode 100644
index 0000000..e078f20
--- /dev/null
+++ b/dojo/tests/behavior.js
@@ -0,0 +1,4 @@
+dojo.provide("tests.behavior");
+if(dojo.isBrowser){
+	doh.registerUrl("tests.behavior", dojo.moduleUrl("tests", "behavior.html"));
+}
diff --git a/dojo/tests/cache.js b/dojo/tests/cache.js
new file mode 100644
index 0000000..b721899
--- /dev/null
+++ b/dojo/tests/cache.js
@@ -0,0 +1,33 @@
+dojo.provide("tests.cache");
+
+dojo.require("dojo.cache");
+
+tests.register("tests.cache", 
+	[
+		{
+			runTest: function(t){
+				var expected = "<h1>Hello World</h1>";
+
+				t.is(expected, dojo.trim(dojo.cache("dojo.tests.cache", "regular.html")));
+				t.is(expected, dojo.trim(dojo.cache("dojo.tests.cache", "sanitized.html", {sanitize: true})));
+				
+				//Test object variant for module.
+				var objPath = dojo.moduleUrl("dojo.tests.cache", "object.html").toString();
+				t.is(expected, dojo.trim(dojo.cache(new dojo._Url(objPath), {sanitize: true})));
+
+				//Just a couple of other passes just to make sure on manual inspection that the
+				//files are loaded over the network only once.
+				t.is(expected, dojo.trim(dojo.cache("dojo.tests.cache", "regular.html")));
+				t.is(expected, dojo.trim(dojo.cache("dojo.tests.cache", "sanitized.html", {sanitize: true})));
+				t.is(expected, dojo.trim(dojo.cache(new dojo._Url(objPath), {sanitize: true})));
+
+				//Make sure unset cache does not throw errors
+				t.is(null, dojo.cache("dojo.tests.cache", "regular.html", null));
+
+				//Set empty string as value
+				t.is("", dojo.cache("dojo.tests.cache", "regular.html", ""));
+				t.is("", dojo.cache("dojo.tests.cache", "regular.html"));
+			}
+		}
+	]
+);
diff --git a/dojo/tests/cache/object.html b/dojo/tests/cache/object.html
new file mode 100644
index 0000000..41762e0
--- /dev/null
+++ b/dojo/tests/cache/object.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+	<head>
+		<script type="text/javascript" src="../../dojo.js"></script>
+		<script type="text/javascript" src="../../cache.js"></script>
+	</head>
+	<body class="tundra">
+		<h1>Hello World</h1>
+	</body>
+</html>
diff --git a/dojo/tests/cache/regular.html b/dojo/tests/cache/regular.html
new file mode 100644
index 0000000..f3e333e
--- /dev/null
+++ b/dojo/tests/cache/regular.html
@@ -0,0 +1 @@
+<h1>Hello World</h1>
diff --git a/dojo/tests/cache/sanitized.html b/dojo/tests/cache/sanitized.html
new file mode 100644
index 0000000..41762e0
--- /dev/null
+++ b/dojo/tests/cache/sanitized.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+	<head>
+		<script type="text/javascript" src="../../dojo.js"></script>
+		<script type="text/javascript" src="../../cache.js"></script>
+	</head>
+	<body class="tundra">
+		<h1>Hello World</h1>
+	</body>
+</html>
diff --git a/dojo/tests/cldr.js b/dojo/tests/cldr.js
new file mode 100644
index 0000000..2655f8f
--- /dev/null
+++ b/dojo/tests/cldr.js
@@ -0,0 +1,15 @@
+dojo.provide("tests.cldr");
+
+dojo.require("dojo.cldr.supplemental");
+dojo.require("dojo.cldr.monetary");
+
+tests.register("tests.cldr", 
+	[
+		function test_date_getWeekend(t){
+			t.is(6, dojo.cldr.supplemental.getWeekend('en-us').start);
+			t.is(0, dojo.cldr.supplemental.getWeekend('en-us').end);
+			t.is(5, dojo.cldr.supplemental.getWeekend('he-il').start);
+			t.is(6, dojo.cldr.supplemental.getWeekend('he-il').end);
+		}
+	]
+);
diff --git a/dojo/tests/colors.js b/dojo/tests/colors.js
new file mode 100644
index 0000000..d081271
--- /dev/null
+++ b/dojo/tests/colors.js
@@ -0,0 +1,44 @@
+dojo.provide("tests.colors");
+dojo.require("dojo.colors");
+
+(function(){
+	var verifyColor = function(t, source, expected){
+		var source   = new dojo.Color(source);
+		var expected = new dojo.Color(expected);
+		t.is(expected.toRgba(), source.toRgba());
+		dojo.forEach(source.toRgba(), function(n){ t.is("number", typeof(n)); });
+	}
+
+	doh.register("tests.colors", 
+		[
+			// all tests below are taken from #4.2 of the CSS3 Color Module
+			function testColorEx01(t){ verifyColor(t, "black", [0, 0, 0]); },
+			function testColorEx02(t){ verifyColor(t, "white", [255, 255, 255]); },
+			function testColorEx03(t){ verifyColor(t, "maroon", [128, 0, 0]); },
+			function testColorEx04(t){ verifyColor(t, "olive", [128, 128, 0]); },
+			function testColorEx05(t){ verifyColor(t, "#f00", "red"); },
+			function testColorEx06(t){ verifyColor(t, "#ff0000", "red"); },
+			function testColorEx07(t){ verifyColor(t, "rgb(255, 0, 0)", "red"); },
+			function testColorEx08(t){ verifyColor(t, "rgb(100%, 0%, 0%)", "red"); },
+			function testColorEx09(t){ verifyColor(t, "rgb(300, 0, 0)", "red"); },
+			function testColorEx10(t){ verifyColor(t, "rgb(255, -10, 0)", "red"); },
+			function testColorEx11(t){ verifyColor(t, "rgb(110%, 0%, 0%)", "red"); },
+			function testColorEx12(t){ verifyColor(t, "rgba(255, 0, 0, 1)", "red"); },
+			function testColorEx13(t){ verifyColor(t, "rgba(100%, 0%, 0%, 1)", "red"); },
+			function testColorEx14(t){ verifyColor(t, "rgba(0, 0, 255, 0.5)", [0, 0, 255, 0.5]); },
+			function testColorEx15(t){ verifyColor(t, "rgba(100%, 50%, 0%, 0.1)", [255, 128, 0, 0.1]); },
+			function testColorEx16(t){ verifyColor(t, "hsl(0, 100%, 50%)", "red"); },
+			function testColorEx17(t){ verifyColor(t, "hsl(120, 100%, 50%)", "lime"); },
+			function testColorEx18(t){ verifyColor(t, "hsl(120, 100%, 25%)", "green"); },
+			function testColorEx19(t){ verifyColor(t, "hsl(120, 100%, 75%)", "#80ff80"); },
+			function testColorEx20(t){ verifyColor(t, "hsl(120, 50%, 50%)", "#40c040"); },
+			function testColorEx21(t){ verifyColor(t, "hsla(120, 100%, 50%, 1)", "lime"); },
+			function testColorEx22(t){ verifyColor(t, "hsla(240, 100%, 50%, 0.5)", [0, 0, 255, 0.5]); },
+			function testColorEx23(t){ verifyColor(t, "hsla(30, 100%, 50%, 0.1)", [255, 128, 0, 0.1]); },
+			function testColorEx24(t){ verifyColor(t, "transparent", [0, 0, 0, 0]); },
+			// all tests below test greyscale colors
+			function testColorEx25(t){ verifyColor(t, dojo.colors.makeGrey(5), [5, 5, 5, 1]); },
+			function testColorEx26(t){ verifyColor(t, dojo.colors.makeGrey(2, 0.3), [2, 2, 2, 0.3]); }
+		]
+	);
+})();
diff --git a/dojo/tests/cookie.html b/dojo/tests/cookie.html
new file mode 100644
index 0000000..a89b0f8
--- /dev/null
+++ b/dojo/tests/cookie.html
@@ -0,0 +1,84 @@
+<html>
+	<head>
+		<title>testing Cookies</title>
+		<style type="text/css">
+			@import "../resources/dojo.css";
+		</style>
+		<script type="text/javascript"
+			src="../dojo.js"
+			djConfig="isDebug:true"></script>
+		<script type="text/javascript" src="../cookie.js"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.addOnLoad(function(){
+				doh.register("t",
+					[
+						{
+							name: "basicSet",
+							runTest: function(t){
+								// make sure the cookie is dead
+								var old = new Date(1976, 8, 15);
+								document.cookie = "dojo_test=blah; expires=" + old.toUTCString();
+								t.is(-1, document.cookie.indexOf("dojo_test="));
+								
+								// set the new one
+								var n = "dojo_test";
+								var v = "test value";
+								dojo.cookie(n, v);
+								t.t(document.cookie.indexOf(n+"=") >= 0);
+								var start = document.cookie.indexOf(n+"=") + n.length + 1;
+								var end = document.cookie.indexOf(";", start);
+								if(end == -1){ end = document.cookie.length; }
+								t.is(v, decodeURIComponent(document.cookie.substring(start, end)));
+							}
+						},
+						{
+							name: "basicGet",
+							runTest: function(t){
+								// set the cookie
+								var n = "dojo_test";
+								var v = "foofoo";
+								document.cookie = n + "=" + v;
+								
+								t.is(v, dojo.cookie(n));
+							}
+						},
+						{
+							name: "daysAsNumber",
+							runTest: function(t){
+								// set a cookie with a numerical expires
+								dojo.cookie("dojo_num", "foo", { expires: 10 });
+								t.is("foo", dojo.cookie("dojo_num"));
+								
+								// remove the cookie by setting it with a negative
+								// numerical expires. value doesn't really matter here
+								dojo.cookie("dojo_num", "-deleted-", { expires: -10 });
+								t.is(null, dojo.cookie("dojo_num"));
+							}
+						},
+						{
+							name: "nameSuffix",
+							runTest: function(t){
+								// set two cookies with the same suffix
+								dojo.cookie("user", "123", { expires: 10 });
+								dojo.cookie("xuser", "abc", { expires: 10 });
+								t.is("123", dojo.cookie("user"));
+								t.is("abc", dojo.cookie("xuser"));
+
+								// remove the cookie by setting it with a negative
+								// numerical expires. value doesn't really matter here
+								dojo.cookie("user", "-deleted-", { expires: -10 });
+								t.is(null, dojo.cookie("user"));
+								dojo.cookie("xuser", "-deleted-", { expires: -10 });
+								t.is(null, dojo.cookie("xuser"));
+							}
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body>
+	</body>
+</html>
diff --git a/dojo/tests/cookie.js b/dojo/tests/cookie.js
new file mode 100644
index 0000000..af974b8
--- /dev/null
+++ b/dojo/tests/cookie.js
@@ -0,0 +1,4 @@
+dojo.provide("tests.cookie");
+if(dojo.isBrowser){
+	doh.registerUrl("tests.cookie", dojo.moduleUrl("tests", "cookie.html"));
+}
diff --git a/dojo/tests/currency.js b/dojo/tests/currency.js
new file mode 100644
index 0000000..63c5901
--- /dev/null
+++ b/dojo/tests/currency.js
@@ -0,0 +1,46 @@
+dojo.provide("tests.currency");
+
+dojo.require("dojo.currency");
+
+tests.register("tests.currency", 
+	[
+		{
+			// Test formatting and parsing of currencies in various locales pre-built in dojo.cldr
+			// NOTE: we can't set djConfig.extraLocale before bootstrapping unit tests, so directly
+			// load resources here for specific locales:
+
+			name: "currency",
+			setUp: function(){
+				var partLocaleList = ["en-us", "en-ca", "de-de"];
+				for(var i = 0 ; i < partLocaleList.length; i ++){
+					dojo.requireLocalization("dojo.cldr","currency",partLocaleList[i]);
+					dojo.requireLocalization("dojo.cldr","number",partLocaleList[i]);
+				}
+			},
+			runTest: function(t){
+				t.is("\u20ac123.45", dojo.currency.format(123.45, {currency: "EUR", locale: "en-us"}));
+				t.is("$123.45", dojo.currency.format(123.45, {currency: "USD", locale: "en-us"}));
+				t.is("$1,234.56", dojo.currency.format(1234.56, {currency: "USD", locale: "en-us"}));
+				t.is("US$123.45", dojo.currency.format(123.45, {currency: "USD", locale: "en-ca"}));
+				t.is("$123.45", dojo.currency.format(123.45, {currency: "CAD", locale: "en-ca"}));
+				t.is("CA$123.45", dojo.currency.format(123.45, {currency: "CAD", locale: "en-us"}));
+				t.is("123,45\xa0\u20ac", dojo.currency.format(123.45, {currency: "EUR", locale: "de-de"}));
+				t.is("1.234,56\xa0\u20ac", dojo.currency.format(1234.56, {currency: "EUR", locale: "de-de"}));
+				// There is no special currency symbol for ADP, so expect the ISO code instead
+				t.is("ADP123", dojo.currency.format(123, {currency: "ADP", locale: "en-us"}));
+				t.is("$1,234", dojo.currency.format(1234, {currency: "USD", fractional: false, locale: "en-us"}));
+
+				t.is(123.45, dojo.currency.parse("$123.45", {currency: "USD", locale: "en-us"}));
+				t.is(1234.56, dojo.currency.parse("$1,234.56", {currency: "USD", locale: "en-us"}));
+				t.is(123.45, dojo.currency.parse("123,45 \u20ac", {currency: "EUR", locale: "de-de"}));
+				t.is(123.45, dojo.currency.parse("123,45\xa0\u20ac", {currency: "EUR", locale: "de-de"}));
+				t.is(1234.56, dojo.currency.parse("1.234,56 \u20ac", {currency: "EUR", locale: "de-de"}));
+				t.is(1234.56, dojo.currency.parse("1.234,56\u20ac", {currency: "EUR", locale: "de-de"}));
+
+				t.is(1234, dojo.currency.parse("$1,234", {currency: "USD", locale: "en-us"}));
+				t.is(1234, dojo.currency.parse("$1,234", {currency: "USD", fractional: false, locale: "en-us"}));
+				t.t(isNaN(dojo.currency.parse("$1,234", {currency: "USD", fractional: true, locale: "en-us"})));
+			}
+		}
+	]
+);
diff --git a/dojo/tests/data.js b/dojo/tests/data.js
new file mode 100644
index 0000000..40cc7e1
--- /dev/null
+++ b/dojo/tests/data.js
@@ -0,0 +1,8 @@
+dojo.provide("tests.data");
+//Squelch any json comment messages for now, since the UT allows for both.
+dojo.config.usePlainJson = true;
+dojo.require("tests.data.utils");
+dojo.require("tests.data.ItemFileReadStore");
+dojo.require("tests.data.ItemFileWriteStore");
+
+
diff --git a/dojo/tests/data/ItemFileReadStore.js b/dojo/tests/data/ItemFileReadStore.js
new file mode 100644
index 0000000..dc61e39
--- /dev/null
+++ b/dojo/tests/data/ItemFileReadStore.js
@@ -0,0 +1,6 @@
+dojo.provide("tests.data.ItemFileReadStore");
+dojo.require("tests.data.readOnlyItemFileTestTemplates");
+dojo.require("dojo.data.ItemFileReadStore");
+
+tests.data.readOnlyItemFileTestTemplates.registerTestsForDatastore("dojo.data.ItemFileReadStore");
+
diff --git a/dojo/tests/data/ItemFileWriteStore.js b/dojo/tests/data/ItemFileWriteStore.js
new file mode 100644
index 0000000..9c18fa7
--- /dev/null
+++ b/dojo/tests/data/ItemFileWriteStore.js
@@ -0,0 +1,1586 @@
+dojo.provide("tests.data.ItemFileWriteStore");
+dojo.require("tests.data.readOnlyItemFileTestTemplates");
+
+dojo.require("dojo.data.ItemFileWriteStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+dojo.require("dojo.data.api.Write");
+dojo.require("dojo.data.api.Notification");
+
+
+// First, make sure ItemFileWriteStore can still pass all the same unit tests 
+// that we use for its superclass, ItemFileReadStore:
+tests.data.readOnlyItemFileTestTemplates.registerTestsForDatastore("dojo.data.ItemFileWriteStore");
+
+tests.data.ItemFileWriteStore.getTestData = function(name){
+	var data = {};
+	if(name === "reference_integrity"){
+		if(dojo.isBrowser){
+			data = {url: dojo.moduleUrl("tests", "data/reference_integrity.json").toString() };
+		}else{
+			data = 
+				{ data: { 
+					"identifier": "id",
+					"label": "name",
+					"items": [
+						{"id": 1, "name": "Item 1"},
+						{"id": 2, "name": "Item 2"},
+						{"id": 3, "name": "Item 3"},
+						{"id": 4, "name": "Item 4"},
+						{"id": 5, "name": "Item 5"},
+						{"id": 6, "name": "Item 6"},
+						{"id": 7, "name": "Item 7"},
+						{"id": 8, "name": "Item 8"},
+						{"id": 9, "name": "Item 9"},
+						{"id": 10, "name": "Item 10", "friends": [{"_reference": 1},{"_reference": 3},{"_reference": 5}]},
+						{"id": 11, "name": "Item 11", "friends": [{"_reference": 10}], "siblings": [{"_reference": 10}]},
+						{"id": 12, "name": "Item 12", "friends": [{"_reference": 3},{"_reference": 7}], "enemies": [{"_reference": 10}]},
+						{"id": 13, "name": "Item 13", "friends": [{"_reference": 10}]},
+						{"id": 14, "name": "Item 14", "friends": [{"_reference": 11}]},
+						{"id": 15, "name": "item 15", "friends": [{"id": 16, "name": "Item 16"}]}
+					]
+				}
+			};
+		}
+	}
+	return data;
+};
+
+
+// Now run some tests that are specific to the write-access features:
+doh.register("tests.data.ItemFileWriteStore", 
+	[
+		function test_getFeatures(){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var features = store.getFeatures(); 
+
+			// make sure we have the expected features:
+			doh.assertTrue(features["dojo.data.api.Read"] !== null);
+			doh.assertTrue(features["dojo.data.api.Identity"] !== null);
+			doh.assertTrue(features["dojo.data.api.Write"] !== null);
+			doh.assertTrue(features["dojo.data.api.Notification"] !== null);
+			doh.assertFalse(features["iggy"]);
+			
+			// and only the expected features:
+			var count = 0;
+			for(var i in features){
+				doh.assertTrue((i === "dojo.data.api.Read" || 
+					i === "dojo.data.api.Identity" || 
+					i === "dojo.data.api.Write" || 
+					i === "dojo.data.api.Notification"));
+				count++;
+			}
+			doh.assertEqual(count, 4);
+		},
+		function testWriteAPI_setValue(){
+			//	summary: 
+			//		Simple test of the setValue API
+			//	description:
+			//		Simple test of the setValue API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			var onComplete = function(items, request){
+				doh.assertEqual(1, items.length);
+				var item = items[0];
+				doh.assertTrue(store.containsValue(item, "capital", "Cairo"));
+				
+				// FIXME:  
+				//    Okay, so this seems very odd.  Maybe I'm just being dense.
+				//    These tests works:
+				doh.assertEqual(store.isDirty(item), false);
+				doh.assertTrue(store.isDirty(item) === false);
+				//    But these seemingly equivalent tests will not work:
+				// doh.assertFalse(store.isDirty(item));
+				// doh.assertTrue(!(store.isDirty(item)));
+				//   
+				//    All of which seems especially weird, given that this *does* work:
+				doh.assertFalse(store.isDirty());
+				
+				doh.assertTrue(store.isDirty(item) === false);
+				doh.assertTrue(!store.isDirty());
+				store.setValue(item, "capital", "New Cairo");
+				doh.assertTrue(store.isDirty(item));
+				doh.assertTrue(store.isDirty());
+				doh.assertEqual(store.getValue(item, "capital").toString(), "New Cairo");
+				deferred.callback(true);
+			};
+			var onError = function(error, request){
+				deferred.errback(error);
+			};
+			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_setValues(){
+			//	summary: 
+			//		Simple test of the setValues API
+			//	description:
+			//		Simple test of the setValues API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			function onComplete(items, request){
+				doh.assertEqual(1, items.length);
+				var item = items[0];
+				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+				doh.assertTrue(store.isDirty(item) === false);
+				doh.assertTrue(!store.isDirty());
+				store.setValues(item, "name", ["Egypt 1", "Egypt 2"]);
+				doh.assertTrue(store.isDirty(item));
+				doh.assertTrue(store.isDirty());
+				var values = store.getValues(item, "name");
+				doh.assertTrue(values[0] == "Egypt 1");
+				doh.assertTrue(values[1] == "Egypt 2");
+				deferred.callback(true);
+			}
+			function onError(error, request){
+				deferred.errback(error);
+			}
+			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_unsetAttribute(){
+			//	summary: 
+			//		Simple test of the unsetAttribute API
+			//	description:
+			//		Simple test of the unsetAttribute API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			function onComplete(items, request) {
+				doh.assertEqual(1, items.length);
+				var item = items[0];
+				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+				doh.assertTrue(store.isDirty(item) === false);
+				doh.assertTrue(!store.isDirty());
+				store.unsetAttribute(item, "name");
+				doh.assertTrue(store.isDirty(item));
+				doh.assertTrue(store.isDirty());
+				doh.assertTrue(!store.hasAttribute(item, "name"));
+				deferred.callback(true);
+			}
+			function onError(error, request) {
+				deferred.errback(error);
+			}
+			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_newItem(){
+			//	summary: 
+			//		Simple test of the newItem API
+			//	description:
+			//		Simple test of the newItem API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			doh.assertTrue(!store.isDirty());
+
+			var onNewInvoked = false;
+			store.onNew = function(newItem, parentInfo){
+
+				doh.assertTrue(newItem !== null);
+				doh.assertTrue(parentInfo === null);
+				doh.assertTrue(store.isItem(newItem));
+				onNewInvoked = true;
+			};
+			var canada = store.newItem({name: "Canada", abbr:"ca", capital:"Ottawa"});
+			doh.assertTrue(onNewInvoked);
+			
+			doh.assertTrue(store.isDirty(canada));
+			doh.assertTrue(store.isDirty());
+			doh.assertTrue(store.getValues(canada, "name") == "Canada");
+			function onComplete(items, request){
+				doh.assertEqual(1, items.length);
+				var item = items[0];
+				doh.assertTrue(store.containsValue(item, "name", "Canada"));
+				deferred.callback(true);
+			}
+			function onError(error, request){
+				deferred.errback(error);
+			}
+			store.fetch({query:{name:"Canada"}, onComplete: onComplete, onError: onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_newItem_withParent(){
+			//	summary: 
+			//		Simple test of the newItem API with a parent assignment
+			//	description:
+			//		Simple test of the newItem API with a parent assignment
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			doh.assertTrue(!store.isDirty());
+
+			var onError = function(error, request){
+				deferred.errback(error);
+			};
+
+			var onComplete = function(items, request){
+				doh.assertEqual(1, items.length);
+				var item = items[0];
+				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+
+				//Attach an onNew to validate we get expected values.
+				var onNewInvoked = false;
+				store.onNew = function(newItem, parentInfo){
+					doh.assertEqual(item, parentInfo.item);
+					doh.assertEqual("cities", parentInfo.attribute);
+					doh.assertTrue(parentInfo.oldValue === undefined);
+					doh.assertTrue(parentInfo.newValue === newItem);
+					onNewInvoked = true;
+				};
+
+				//Attach an onSet and verify onSet is NOT called in this case.
+				store.onSet = function(item, attribute, oldValue, newValue){
+					doh.assertTrue(false);
+				};
+
+
+
+				//See if we can add in a new item representing the city of Cairo.
+				//This should also call the onNew set above....
+				var newItem = store.newItem({name: "Cairo", abbr: "Cairo"}, {parent: item, attribute: "cities"});
+				doh.assertTrue(onNewInvoked);
+
+				function onCompleteNewItemShallow(items, request){
+					doh.assertEqual(0, items.length);
+					function onCompleteNewItemDeep(items, request){
+						doh.assertEqual(1, items.length);
+						var item = items[0];
+						doh.assertEqual("Cairo", store.getValue(item, "name"));
+						deferred.callback(true);
+					}
+					//Do a deep search now, should find the new item of the city with name attribute Cairo.
+					store.fetch({query:{name:"Cairo"}, onComplete: onCompleteNewItemDeep, onError: onError, queryOptions: {deep:true}});
+				}
+				//Do a shallow search first, should find nothing.
+				store.fetch({query:{name:"Cairo"}, onComplete: onCompleteNewItemShallow, onError: onError});
+			};
+			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+			return deferred; //Object
+		},
+		
+		function testWriteAPI_newItem_multiple_withParent(){
+			//	summary: 
+			//		Simple test of the newItem API with a parent assignment multiple times.
+			//	description:
+			//		Simple test of the newItem API with a parent assignment multiple times.
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			
+			doh.assertTrue(!store.isDirty());
+			
+			function onComplete(items, request){
+				doh.assertEqual(1, items.length);
+				var item = items[0];
+				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+
+				//Attach an onNew to validate we get expected values.
+				store.onNew = function(newItem, parentInfo){
+					doh.assertEqual(item, parentInfo.item);
+					doh.assertEqual("cities", parentInfo.attribute);
+					
+					doh.assertTrue(parentInfo.oldValue === undefined);
+					
+					doh.assertTrue(parentInfo.newValue === newItem);
+				};
+
+				//See if we can add in a new item representing the city of Cairo.
+				//This should also call the onNew set above....
+				var newItem1 = store.newItem({name: "Cairo", abbr: "Cairo"}, {parent: item, attribute: "cities"});
+				
+				//Attach a new onNew to validate we get expected values.
+				store.onNew = function(newItem, parentInfo){
+					doh.assertEqual(item, parentInfo.item);
+					doh.assertEqual("cities", parentInfo.attribute);
+					
+					console.log(parentInfo.oldValue);
+					doh.assertTrue(parentInfo.oldValue == newItem1);
+					
+					doh.assertTrue(parentInfo.newValue[0] == newItem1);
+					doh.assertTrue(parentInfo.newValue[1] == newItem);
+				};
+				var newItem2 = store.newItem({name: "Banha", abbr: "Banha"}, {parent: item, attribute: "cities"});
+				
+				//Attach a new onNew to validate we get expected values.
+				store.onNew = function(newItem, parentInfo){
+					doh.assertEqual(item, parentInfo.item);
+					doh.assertEqual("cities", parentInfo.attribute);
+					
+					doh.assertTrue(parentInfo.oldValue[0] == newItem1);
+					doh.assertTrue(parentInfo.oldValue[1] == newItem2);
+					
+					doh.assertTrue(parentInfo.newValue[0] == newItem1);
+					doh.assertTrue(parentInfo.newValue[1] == newItem2);
+					doh.assertTrue(parentInfo.newValue[2] == newItem);
+				};
+				var newItem3 = store.newItem({name: "Damanhur", abbr: "Damanhur"}, {parent: item, attribute: "cities"});
+				deferred.callback(true);
+			}
+			function onError(error, request){
+				deferred.errback(error);
+			}
+			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+			return deferred; //Object
+		},
+
+		function testWriteAPI_deleteItem(){
+			//	summary: 
+			//		Simple test of the deleteItem API
+			//	description:
+			//		Simple test of the deleteItem API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+
+			var onError = function(error, request){
+				deferred.errback(error);
+			};
+
+			var onComplete = function(items, request){
+				doh.assertEqual(1, items.length);
+				var item = items[0];
+				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+				doh.assertTrue(store.isDirty(item) === false);
+				doh.assertTrue(!store.isDirty());
+				store.deleteItem(item);
+				doh.assertTrue(store.isDirty(item));
+				doh.assertTrue(store.isDirty());
+				var onCompleteToo = function(itemsToo, requestToo) {
+					doh.assertEqual(0, itemsToo.length);
+					deferred.callback(true);
+				};
+				store.fetch({query:{name:"Egypt"}, onComplete: onCompleteToo, onError: onError});
+			};
+			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_isDirty(){
+			//	summary: 
+			//		Simple test of the isDirty API
+			//	description:
+			//		Simple test of the isDirty API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			function onComplete(items, request) {
+				doh.assertEqual(1, items.length);
+				var item = items[0];
+				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+				store.setValue(item, "name", "Egypt 2");
+				doh.assertTrue(store.getValue(item, "name") == "Egypt 2");
+				doh.assertTrue(store.isDirty(item));
+				deferred.callback(true);
+			}
+			function onError(error, request) {
+				deferred.errback(error);
+			}
+			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_revert(){
+			//	summary: 
+			//		Simple test of the revert API
+			//	description:
+			//		Simple test of the revert API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+
+			var onError = function(error, request){
+				deferred.errback(error);
+			};
+
+			var onComplete = function(items, request) {
+				doh.assertEqual(1, items.length);
+				var item = items[0];
+				doh.assertTrue(store.containsValue(item, "name", "Egypt"));
+				doh.assertTrue(store.isDirty(item) === false);
+				doh.assertTrue(!store.isDirty());
+				store.setValue(item, "name", "Egypt 2");
+				doh.assertTrue(store.getValue(item, "name") == "Egypt 2");
+				doh.assertTrue(store.isDirty(item));
+				doh.assertTrue(store.isDirty());
+				store.revert();
+				
+				//Fetch again to see if it reset the state.
+				var onCompleteToo = function(itemsToo, requestToo){
+					doh.assertEqual(1, itemsToo.length);
+					var itemToo = itemsToo[0];
+					doh.assertTrue(store.containsValue(itemToo, "name", "Egypt"));
+					deferred.callback(true);
+				};
+				store.fetch({query:{name:"Egypt"}, onComplete: onCompleteToo, onError: onError});
+			};
+			store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_save(){
+			//	summary: 
+			//		Simple test of the save API
+			//	description:
+			//		Simple test of the save API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			function onError(error){
+				deferred.errback(error);
+			}
+			function onItem(item){
+				store.setValue(item, "capital", "New Cairo");
+				function onComplete() {
+					deferred.callback(true);
+				}
+				store.save({onComplete:onComplete, onError:onError});
+			}
+			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_saveVerifyState(){
+			//	summary: 
+			//		Simple test of the save API
+			//	description:
+			//		Simple test of the save API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			function onError(error){
+				deferred.errback(error);
+			}
+			function onItem(item){
+				store.setValue(item, "capital", "New Cairo");
+				function onComplete() {
+					//Check internal state.  Note:  Users should NOT do this, this is a UT verification
+					//of internals in this case.  Ref tracker: #4394
+					doh.assertTrue(!store._saveInProgress);
+					deferred.callback(true);
+				}
+				store.save({onComplete:onComplete, onError:onError});
+			}
+			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_saveEverything(){
+			//	summary: 
+			//		Simple test of the save API
+			//	description:
+			//		Simple test of the save API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			var egypt;
+
+			var deferred = new doh.Deferred();
+			var onError = function(error){
+				deferred.errback(error);
+			};
+
+			store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+				var struct = dojo.fromJson(newFileContentString);
+				doh.assertEqual(struct.identifier, store.getIdentityAttributes(egypt)[0]);
+				doh.assertEqual(struct.label, store.getLabelAttributes(egypt)[0]);
+				doh.assertEqual(struct.items.length, 7);
+				
+				var cloneStore = new dojo.data.ItemFileWriteStore({data:struct});
+				var onItemClone = function(itemClone){
+					var egyptClone = itemClone;
+					doh.assertEqual(store.getIdentityAttributes(egypt)[0], cloneStore.getIdentityAttributes(egyptClone)[0]);
+					doh.assertEqual(store.getLabelAttributes(egypt)[0], cloneStore.getLabelAttributes(egyptClone)[0]);
+					doh.assertEqual(store.getValue(egypt, "name"), cloneStore.getValue(egyptClone, "name"));
+				};
+				cloneStore.fetchItemByIdentity({identity:"eg", onItem:onItemClone, onError:onError});
+				saveCompleteCallback();
+			};
+			var onItem = function(item){
+				egypt = item;
+				var onComplete = function() {
+					deferred.callback(true);
+				};
+				store.setValue(egypt, "capital", "New Cairo");
+				store.save({onComplete:onComplete, onError:onError});
+			};
+			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_saveEverything_HierarchyOff(){
+			//	summary: 
+			//		Simple test of the save API
+			//	description:
+			//		Simple test of the save API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+			store.hierarchical = false;
+			var africa;
+
+			var deferred = new doh.Deferred();
+			var onError = function(error){
+				deferred.errback(error);
+			};
+
+			store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+				var struct = dojo.fromJson(newFileContentString);
+				doh.assertEqual(struct.items.length, 3);
+				var cloneStore = new dojo.data.ItemFileWriteStore({data:struct, hierarchical: false});
+				var onItemClone = function(items, request){
+					var africaClone = items[0];
+					doh.assertEqual(store.getValue(africa, "name"), cloneStore.getValue(africaClone, "name"));
+				};
+				cloneStore.fetch({query: {name:"Africa"}, onComplete:onItemClone, onError:onError, queryOptions: {deep: true}});
+				saveCompleteCallback();
+			};
+			var onComplete = function(items, request){
+				africa = items[0];
+				var onComplete = function() {
+					deferred.callback(true);
+				};
+				store.setValue(africa, "size", "HUGE!");
+				store.save({onComplete:onComplete, onError:onError});
+			};
+			store.fetch({query: {name:"Africa"}, onComplete:onComplete, onError:onError, queryOptions: {deep: true}});
+			return deferred; //Object
+		},
+		function testWriteAPI_saveEverything_withDateType(){
+			//	summary: 
+			//		Simple test of the save API	with a non-atomic type (Date) that has a type mapping.
+			//	description:
+			//		Simple test of the save API	with a non-atomic type (Date) that has a type mapping.
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			
+			var deferred = new doh.Deferred();
+			store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+
+				//Now load the new data into a datastore and validate that it stored the date right.
+				var dataset = dojo.fromJson(newFileContentString);
+				var newStore = new dojo.data.ItemFileWriteStore({data: dataset});
+
+				function gotItem(item){
+					var independenceDate = newStore.getValue(item,"independence"); 
+					doh.assertTrue(independenceDate instanceof Date);
+					doh.assertTrue(dojo.date.compare(new Date(1993,4,24), independenceDate, "date") === 0);
+					saveCompleteCallback();
+				}
+				function failed(error, request){
+					deferred.errback(error);
+					saveFailedCallback();
+				}
+				newStore.fetchItemByIdentity({identity:"eg", onItem:gotItem, onError:failed});
+			};
+
+			var onError = function(error){
+				deferred.errback(error);
+			};
+			var onItem = function(item){
+				var onComplete = function() {
+					deferred.callback(true);
+				};
+				store.setValue(item, "independence", new Date(1993,4,24));
+				store.save({onComplete:onComplete, onError:onError});
+			};
+			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_saveEverything_withCustomColorTypeSimple(){
+			//	summary: 
+			//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
+			//	description:
+			//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
+
+			//Set up the store basics:  What data it has, and what to do when save is called for saveEverything
+			//And how to map the 'Color' type in and out of the format.
+			//(Test of saving all to a some location...)
+			var dataset = {
+				identifier:'name',
+				items: [
+					{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+					{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+				]
+			};
+
+			var customTypeMap = {'Color': dojo.Color };
+
+			var store = new dojo.data.ItemFileWriteStore({
+					data:dataset,
+					typeMap: customTypeMap
+			});
+			
+			var deferred = new doh.Deferred();
+			store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+				//Now load the new data into a datastore and validate that it stored the Color right.
+				var dataset = dojo.fromJson(newFileContentString);
+				var newStore = new dojo.data.ItemFileWriteStore({data: dataset, typeMap: customTypeMap});
+
+				var deferred = new doh.Deferred();
+				function gotItem(item){
+					var hairColor = newStore.getValue(item,"hairColor"); 
+					doh.assertTrue(hairColor instanceof dojo.Color);
+					doh.assertEqual("rgba(255, 255, 0, 1)", hairColor.toString());
+					saveCompleteCallback();
+				}
+				function failed(error, request){
+					deferred.errback(error);
+					saveFailedCallback();
+				}
+				newStore.fetchItemByIdentity({identity:"Animal", onItem:gotItem, onError:failed});
+			};
+
+			//Add a new item with a color type, then save it.
+            var onError = function(error){
+				deferred.errback(error);
+			};
+			var onComplete = function() {
+				deferred.callback(true);
+			};
+
+			var animal = store.newItem({name: "Animal", hairColor: new dojo.Color("yellow")});
+			store.save({onComplete:onComplete, onError:onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_saveEverything_withCustomColorTypeGeneral(){
+			//	summary: 
+			//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
+			//	description:
+			//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
+
+			//Set up the store basics:  What data it has, and what to do when save is called for saveEverything
+			//And how to map the 'Color' type in and out of the format.
+			//(Test of saving all to a some location...)
+			var dataset = {
+				identifier:'name',
+				items: [
+					{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+					{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+				]
+			};
+
+			var customTypeMap = {'Color': 	{	
+												type: dojo.Color,
+												deserialize: function(value){
+													return new dojo.Color(value);
+												},
+												serialize: function(obj){
+													return obj.toString();
+												}
+											}
+								};
+			var store = new dojo.data.ItemFileWriteStore({
+					data:dataset,
+					typeMap: customTypeMap
+			});
+			
+			var deferred = new doh.Deferred();
+			store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+				//Now load the new data into a datastore and validate that it stored the Color right.
+				var dataset = dojo.fromJson(newFileContentString);
+				var newStore = new dojo.data.ItemFileWriteStore({data: dataset, typeMap: customTypeMap});
+
+				var gotItem = function(item){
+					var hairColor = newStore.getValue(item,"hairColor"); 
+					doh.assertTrue(hairColor instanceof dojo.Color);
+					doh.assertEqual("rgba(255, 255, 0, 1)", hairColor.toString());
+					saveCompleteCallback();
+				};
+				var failed = function(error, request){
+					deferred.errback(error);
+					saveFailedCallback();
+				};
+				newStore.fetchItemByIdentity({identity:"Animal", onItem:gotItem, onError:failed});
+			};
+
+			//Add a new item with a color type, then save it.
+            var onError = function(error){
+				deferred.errback(error);
+			};
+			var onComplete = function() {
+				deferred.callback(true);
+			};
+
+			var animal = store.newItem({name: "Animal", hairColor: new dojo.Color("yellow")});
+			store.save({onComplete:onComplete, onError:onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_newItem_revert(){
+			//	summary: 
+			//		Test for bug #5357.  Ensure that the revert properly nulls the identity position
+			//      for a new item after revert.
+			var args = {data: {
+				label:"name",
+				items:[
+					{name:'Ecuador', capital:'Quito'},
+					{name:'Egypt', capital:'Cairo'},
+					{name:'El Salvador', capital:'San Salvador'},
+					{name:'Equatorial Guinea', capital:'Malabo'},
+					{name:'Eritrea', capital:'Asmara'},
+					{name:'Estonia', capital:'Tallinn'},
+					{name:'Ethiopia', capital:'Addis Ababa'}
+				]
+			} }; 
+			var store = new dojo.data.ItemFileWriteStore(args);
+
+			var newCountry = store.newItem({name: "Utopia", capitol: "Perfect"});
+
+			//DO NOT ACCESS THIS WAY.  THESE ARE INTERNAL VARIABLES.  DOING THIS FOR TEST PURPOSES.
+			var itemEntryNum = newCountry[store._itemNumPropName];
+			doh.assertTrue(store._arrayOfAllItems[itemEntryNum] === newCountry);
+			store.revert();
+			doh.assertTrue(store._arrayOfAllItems[itemEntryNum] === null);
+		},
+		function testWriteAPI_new_modify_revert(){
+			//	summary: 
+			//		Test of a new item, modify it, then revert, to ensure the state remains consistent.  Added due to #9022.
+			//	description:
+			//		Test of a new item, modify it, then revert, to ensure the state remains consistent.  Added due to #9022.
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			doh.assertTrue(!store.isDirty());
+
+			var onError = function(error, request){
+				deferred.errback(error);
+			};
+
+			var intialFetch = function(items, request){
+				var initialCount = items.length;
+				var canada = store.newItem({name: "Canada", abbr:"ca", capital:"Ottawa"});
+				store.setValue(canada, "someattribute", "modified a new item!");
+				var afterNewFetch = function(items, request){
+					var afterNewCount = items.length;
+					doh.assertEqual(afterNewCount, (initialCount + 1));
+					store.revert();
+					var afterRevertFetch = function(items, request){
+						var afterRevertCount = items.length;
+						doh.assertEqual(afterRevertCount, initialCount);
+						deferred.callback(true);
+					};
+					store.fetch({onComplete: afterRevertFetch, onError: onError});
+				};
+				store.fetch({onComplete: afterNewFetch, onError: onError});
+			};
+			store.fetch({onComplete: intialFetch, onError: onError});
+			return deferred; //Object
+		},
+		function testWriteAPI_new_modify_delete_revert(){
+			//	summary: 
+			//		Test of a new item, modify it, delete it, then revert, to ensure the state remains consistent.  Added due to #9022.
+			//	description:
+			//		Test of a new item, modify it, delete it, then revert, to ensure the state remains consistent.  Added due to #9022.
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			var i;
+			var found = false;
+
+			var deferred = new doh.Deferred();
+			doh.assertTrue(!store.isDirty());
+
+			var onError = function(error, request){
+				deferred.errback(error);
+			};
+
+			var intialFetch = function(items, request){
+				var initialCount = items.length;
+				var canada = store.newItem({name: "Canada", abbr:"ca", capital:"Ottawa"});
+				store.setValue(canada, "someattribute", "modified a new item!");
+				
+				// check that after new and modify, the total items count goes up by one.
+				var afterNewFetch = function(items, request){
+					var afterNewCount = items.length;
+					doh.assertEqual(afterNewCount, (initialCount + 1));
+					store.deleteItem(canada);
+					
+					//Check that after delete, the total items count goes back to initial count.  
+					//Also verify the item with abbr of ca is gone.
+					var afterDeleteFetch = function(items, request){
+						var afterDeleteCount = items.length;
+						doh.assertEqual(initialCount, afterDeleteCount);
+
+						for(i=0; i < items.length; i++){
+							found = (store.getIdentity(items[i]) === "ca");
+							if(found){ 
+								break;
+							}
+						}
+						if(found){
+							deferred.errback(new Error("Error: Found the supposedly deleted item!"));
+						}else{
+							store.revert();
+							//Check that after revert, we still have the same item count as the 
+							//original fetch.  Also verify the item with abbr of ca is gone.
+							var afterRevertFetch = function(items, request){
+								var afterRevertCount = items.length;
+								doh.assertEqual(afterRevertCount, initialCount);
+								for(i=0; i < items.length; i++){
+									found = (store.getIdentity(items[i]) === "ca");
+									if(found){ 
+										break;
+									}
+								}
+								if(found){
+									deferred.errback(new Error("Error: Found the 'new' item after revert!"));
+								}else{
+									deferred.callback(true);
+								}
+							};
+							store.fetch({onComplete: afterRevertFetch, onError: onError});
+						}
+					};
+					store.fetch({onComplete: afterDeleteFetch, onError: onError});
+				};
+				store.fetch({onComplete: afterNewFetch, onError: onError});
+			};
+			store.fetch({onComplete: intialFetch, onError: onError});
+			return deferred; //Object
+		},
+		function testNotificationAPI_onSet(){
+			//	summary: 
+			//		Simple test of the onSet API
+			//	description:
+			//		Simple test of the onSet API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			function onError(error){
+				deferred.errback(error);
+			}
+			function onItem(fetchedItem){
+				var egypt = fetchedItem;
+				var connectHandle = null;
+				function setValueHandler(item, attribute, oldValue, newValue){
+					doh.assertTrue(store.isItem(item));
+					doh.assertTrue(item == egypt);
+					doh.assertTrue(attribute == "capital");
+					doh.assertTrue(oldValue == "Cairo");
+					doh.assertTrue(newValue == "New Cairo");
+					deferred.callback(true);
+					dojo.disconnect(connectHandle);
+				}
+				connectHandle = dojo.connect(store, "onSet", setValueHandler);
+				store.setValue(egypt, "capital", "New Cairo");
+			}
+			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+		},
+		function testNotificationAPI_onNew(){
+			//	summary: 
+			//		Simple test of the onNew API
+			//	description:
+			//		Simple test of the onNew API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			var connectHandle = null;
+			function newItemHandler(item){
+				doh.assertTrue(store.isItem(item));
+				doh.assertTrue(store.getValue(item, "name") == "Canada");
+				deferred.callback(true);
+				dojo.disconnect(connectHandle);
+			}
+			connectHandle = dojo.connect(store, "onNew", newItemHandler);
+			var canada = store.newItem({name:"Canada", abbr:"ca", capital:"Ottawa"});
+		},
+		function testNotificationAPI_onDelete(){
+			//	summary: 
+			//		Simple test of the onDelete API
+			//	description:
+			//		Simple test of the onDelete API
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var deferred = new doh.Deferred();
+			function onError(error){
+				deferred.errback(error);
+			}
+			function onItem(fetchedItem){
+				var egypt = fetchedItem;
+				var connectHandle = null;
+				function deleteItemHandler(item){
+					doh.assertTrue(store.isItem(item) === false);
+					doh.assertTrue(item == egypt);
+					deferred.callback(true);
+					dojo.disconnect(connectHandle);
+				}
+				connectHandle = dojo.connect(store, "onDelete", deleteItemHandler);
+				store.deleteItem(egypt);
+			}
+			store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+		},
+		function testReadAPI_functionConformanceToo(){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(var functionName in readApi){
+				var member = readApi[functionName];
+				//Check that all the 'Read' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[functionName];
+					if(!(typeof testStoreMember === "function")){
+						passed = false;
+						break;
+					}
+				}
+			}
+			doh.assertTrue(passed);
+		},
+		function testWriteAPI_functionConformance(){
+			//	summary: 
+			//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
+			var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			var writeApi = new dojo.data.api.Write();
+			var passed = true;
+
+			for(var functionName in writeApi){
+				var member = writeApi[functionName];
+				//Check that all the 'Write' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[functionName];
+					if(!(typeof testStoreMember === "function")){
+						passed = false;
+						break;
+					}
+				}
+			}
+			doh.assertTrue(passed);
+		},
+		function testNotificationAPI_functionConformance(){
+			//	summary: 
+			//		Simple test Notification API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test Notification API conformance.  Checks to see all declared functions are actual functions on the instances.
+			var testStore = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			var api = new dojo.data.api.Notification();
+			var passed = true;
+
+			for(var functionName in api){
+				var member = api[functionName];
+				//Check that all the 'Write' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[functionName];
+					if(!(typeof testStoreMember === "function")){
+						passed = false;
+						break;
+					}
+				}
+			}
+			doh.assertTrue(passed);
+		},
+		function testIdentityAPI_noIdentifierSpecified(){
+			//	summary: 
+			//		Test for bug #3873. Given a datafile that does not specify an
+			//		identifier, make sure ItemFileWriteStore auto-creates identities 
+			//		that are unique even after calls to deleteItem() and newItem()
+			var args = {data: {
+				label:"name",
+				items:[
+					{name:'Ecuador', capital:'Quito'},
+					{name:'Egypt', capital:'Cairo'},
+					{name:'El Salvador', capital:'San Salvador'},
+					{name:'Equatorial Guinea', capital:'Malabo'},
+					{name:'Eritrea', capital:'Asmara'},
+					{name:'Estonia', capital:'Tallinn'},
+					{name:'Ethiopia', capital:'Addis Ababa'}
+				]
+			} }; 
+			var store = new dojo.data.ItemFileWriteStore(args);
+			var deferred = new doh.Deferred();
+			
+			var onError = function(error, request){
+				deferred.errback(error);
+			};
+			var onComplete = function(items, request){
+				doh.assertEqual(7, items.length);
+				
+				var lastItem = items[(items.length - 1)];
+				var idOfLastItem = store.getIdentity(lastItem);
+				store.deleteItem(lastItem);
+				store.newItem({name:'Canada', capital:'Ottawa'});
+				
+				var onCompleteAgain = function(itemsAgain, requestAgain){
+					doh.assertEqual(7, itemsAgain.length);
+					var identitiesInUse = {};
+					for(var i = 0; i < itemsAgain.length; ++i){
+						var item = itemsAgain[i];
+						var id = store.getIdentity(item);
+						if(identitiesInUse.hasOwnProperty(id)){
+							// there should not already be an entry for this id
+							doh.assertTrue(false);
+						}else{
+							// we want to add the entry now
+							identitiesInUse[id] = item;
+						}
+					}
+					deferred.callback(true);
+				};
+				store.fetch({onComplete:onCompleteAgain, onError:onError});
+			};
+			
+			store.fetch({onComplete:onComplete, onError:onError});
+			return deferred;
+		},
+		function testIdentityAPI_noIdentifierSpecified_revert(){
+			//	summary: 
+			//		Test for bug #4691  Given a datafile that does not specify an
+			//		identifier, make sure ItemFileWriteStore auto-creates identities 
+			//		that are unique even after calls to deleteItem() and newItem()
+			var args = {data: {
+				label:"name",
+				items:[
+					{name:'Ecuador', capital:'Quito'},
+					{name:'Egypt', capital:'Cairo'},
+					{name:'El Salvador', capital:'San Salvador'},
+					{name:'Equatorial Guinea', capital:'Malabo'},
+					{name:'Eritrea', capital:'Asmara'},
+					{name:'Estonia', capital:'Tallinn'},
+					{name:'Ethiopia', capital:'Addis Ababa'}
+				]
+			} }; 
+			var store = new dojo.data.ItemFileWriteStore(args);
+			var deferred = new doh.Deferred();
+			
+			var onError = function(error, request){
+				deferred.errback(error);
+			};
+			var onComplete = function(items, request){
+				doh.assertEqual(7, items.length);
+				
+				var lastItem = items[(items.length - 1)];
+				var idOfLastItem = store.getIdentity(lastItem);
+				store.deleteItem(lastItem);
+				store.newItem({name:'Canada', capital:'Ottawa'});
+				
+				var onCompleteAgain = function(itemsAgain, requestAgain){
+					doh.assertEqual(7, itemsAgain.length);
+					var identitiesInUse = {};
+					for(var i = 0; i < itemsAgain.length; ++i){
+						var item = itemsAgain[i];
+						var id = store.getIdentity(item);
+						if(identitiesInUse.hasOwnProperty(id)){
+							// there should not already be an entry for this id
+							doh.assertTrue(false);
+						}else{
+							// we want to add the entry now
+							identitiesInUse[id] = item;
+						}
+					}
+					//Last test, revert everything and check item sizes.
+					store.revert();
+
+					//Now call fetch again and verify store state.
+					var revertComplete = function(itemsReverted, request){
+						doh.assertEqual(7, itemsReverted.length);
+						deferred.callback(true);
+					};
+					store.fetch({onComplete:revertComplete, onError:onError});
+				};
+				store.fetch({onComplete:onCompleteAgain, onError:onError});
+			};
+			store.fetch({onComplete:onComplete, onError:onError});
+			return deferred;
+		},
+		function testReferenceIntegrity_checkReferences(){
+			//	summary: 
+			//		Simple test to verify the references were properly resolved.
+			//	description:
+			//		Simple test to verify the references were properly resolved.
+		
+			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+			var deferred = new doh.Deferred();
+			var onError = function(error, request){
+				deferred.errback(error);
+			};
+			var onComplete = function(items, request){
+
+				var item10 = null;
+				var item1  = null;
+				var item3  = null;
+				var item5  = null;
+
+				var i;
+				for (i = 0; i < items.length; i++) {
+					var ident = store.getIdentity(items[i]);
+					if (ident === 10) {
+						item10 = items[i];
+					}else if (ident === 1) {
+						item1 = items[i];
+					}else if (ident === 3) {
+						item3 = items[i];
+					}else if (ident === 5) {
+						item5 = items[i];
+					}
+				}
+				var friends = store.getValues(item10, "friends");
+				doh.assertTrue(friends !== null);
+				doh.assertTrue(friends !== undefined);
+
+				doh.assertTrue(store.isItem(item10));
+				doh.assertTrue(store.isItem(item1));
+				doh.assertTrue(store.isItem(item3));
+				doh.assertTrue(store.isItem(item5));
+				var found = 0;
+				try{
+					for (i = 0; i < friends.length; i++) {
+						if (i === 0) {
+							doh.assertTrue(store.isItem(friends[i]));
+							doh.assertEqual(friends[i], item1);
+							doh.assertEqual(store.getIdentity(friends[i]), 1);
+							found++;
+						}else if (i === 1) {
+							doh.assertTrue(store.isItem(friends[i]));
+							doh.assertEqual(friends[i], item3);
+							doh.assertEqual(store.getIdentity(friends[i]), 3);
+							found++;
+						}else if (i === 2) {
+							doh.assertTrue(store.isItem(friends[i]));
+							doh.assertEqual(friends[i], item5);
+							doh.assertEqual(store.getIdentity(friends[i]), 5);
+							found++;
+						}
+					}
+				}catch(e){
+					doh.errback(e);
+				}
+				doh.assertEqual(3, found);
+				deferred.callback(true);
+			};
+			store.fetch({onError: onError, onComplete: onComplete});
+			return deferred;
+		},
+		function testReferenceIntegrity_deleteReferencedItem(){
+			//	summary: 
+			//		Simple test to verify the references were properly deleted.
+			//	description:
+			//		Simple test to verify the references were properly deleted.
+		
+			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+			var deferred = new doh.Deferred();
+			var passed = true;
+			function onError(error, request){
+				deferred.errback(error);
+			}
+			function onItem(item, request){
+				try{
+					console.log("Before delete map state is: " + dojo.toJson(item[store._reverseRefMap]));
+					store.deleteItem(item);
+					console.log("After delete map state is: " + dojo.toJson(item[store._reverseRefMap]));
+					function verifyRefDelete(items, request){
+						var passed = true;
+						for(var i = 0; i < items.length; i++){
+							var curItem = items[i];
+							var attributes = store.getAttributes(curItem);
+							for(var j = 0; j < attributes.length; j++){
+								var values = store.getValues(curItem, attributes[j]);
+								var badRef = false;
+								for(var k = 0; k < values.length; k++){
+									var value = values[k];
+									try{
+										var id = store.getIdentity(value);
+										if(id == 10){
+											badRef = true;
+											break;
+										}
+									}catch(e){/*Not an item, even a dead one, just eat it.*/}
+								}
+								if(badRef){
+									deferred.errback(new Error("Found a reference remaining to a deleted item.  Failure."));
+									passed = false;
+									break;
+								}
+							}
+						}
+						if(passed){
+							deferred.callback(true);
+						}
+					}
+					store.fetch({onComplete: verifyRefDelete, onError: onError});
+				}catch(error){
+					deferred.errback(error);
+				}
+			}
+			store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+			return deferred;
+		},
+		function testReferenceIntegrity_deleteReferencedItemThenRevert(){
+			//	summary: 
+			//		Simple test to verify the references were properly deleted.
+			//	description:
+			//		Simple test to verify the references were properly deleted.
+		
+			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+			var deferred = new doh.Deferred();
+			var passed = true;
+			function onError(error, request){
+				deferred.errback(error);
+			}
+			function onItem(item, request){
+				try{
+					//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+					//THIS IS FOR TESTING INTERNAL STATE!
+					console.log("Map before delete:");
+					store._dumpReferenceMap();
+					var beforeDelete = dojo.toJson(item[store._reverseRefMap]);
+					store.deleteItem(item);
+					console.log("Map after delete:");
+					store._dumpReferenceMap();
+					var afterDelete = dojo.toJson(item[store._reverseRefMap]);
+					store.revert();
+					console.log("Map after revert:");
+					store._dumpReferenceMap();
+					var afterRevert = dojo.toJson(item[store._reverseRefMap]);
+					doh.assertTrue(afterRevert === beforeDelete);
+				}catch(e){
+					deferred.errback(e);
+					passed = false;
+				}
+				if(passed){
+					deferred.callback(true);
+				}
+			}
+			store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+			return deferred;
+		},
+		function testReferenceIntegrity_deleteMultipleItemsWithReferencesAndRevert(){
+			//	summary: 
+			//		Simple test to verify that a flow of deleting items with references and reverting does not damage the internal structure.
+			//		Created for tracker bug: #5743
+			//	description:
+			//		Simple test to verify that a flow of deleting items with references and reverting does not damage the internal structure.
+			//		Created for tracker bug: #5743
+		
+			var store = new dojo.data.ItemFileWriteStore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_references"));
+
+			var deferred = new doh.Deferred();
+			var passed = true;
+			function onError(error, request){
+				deferred.errback(error);
+				doh.assertTrue(false);
+			}
+			function onItem(item, request){
+				//Save off the located item, then locate another one (peer to Egypt)
+				doh.assertTrue(store.isItem(item));
+				var egypt = item;
+
+				function onItem2(item, request){
+					doh.assertTrue(store.isItem(item));
+					var nairobi = item;
+
+					//Delete them
+					store.deleteItem(egypt);
+					store.deleteItem(nairobi);
+					try{
+						//Revert, then do a fetch.  If the internals have been damaged, this will generally
+						//cause onError to fire instead of onComplete.
+						store.revert();
+						function onComplete(items, request){
+							deferred.callback(true);
+						}
+						store.fetch({query: {name: "*"}, start: 0, count: 20, onComplete: onComplete, onError: onError});
+					}catch(e){
+						deferred.errback(e);
+					}
+				}
+				store.fetchItemByIdentity({identity: "Nairobi", onError: onError, onItem: onItem2});
+			}
+			store.fetchItemByIdentity({identity: "Egypt", onError: onError, onItem: onItem});
+			return deferred;
+		},
+		function testReferenceIntegrity_removeReferenceFromAttribute(){
+			//	summary: 
+			//		Simple test to verify the reference removal updates the internal map.
+			//	description:
+			//		Simple test to verify the reference removal updates the internal map.
+		
+			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+			var deferred = new doh.Deferred();
+			var passed = true;
+			function onError(error, request){
+				deferred.errback(error);
+				doh.assertTrue(false);
+			}
+			function onItem(item, request){
+				try{
+					store.setValues(item, "friends", [null]);
+
+					function onItem2(item10, request){
+						//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+						//THIS IS FOR TESTING INTERNAL STATE!
+						var refMap = item10[store._reverseRefMap];
+						store._dumpReferenceMap();
+
+						console.log("MAP for Item 10 is: " + dojo.toJson(refMap));
+
+						//Assert there is no reference to item 10 in item 11's attribute 'friends'.
+						doh.assertTrue(!refMap["11"]["friends"]);
+						store.setValues(item, "siblings", [0, 1, 2]);
+						//Assert there are no more references to 10 in 11.  Ergo, "11"  should be a 'undefined' attribute for the map of items referencing '10'..
+						doh.assertTrue(!refMap["11"]);
+						deferred.callback(true);
+					}
+					store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem2});
+
+				}catch(e){
+					console.debug(e);
+					deferred.errback(e);
+					doh.assertTrue(false);
+				}
+			}
+			store.fetchItemByIdentity({identity: 11, onError: onError, onItem: onItem});
+			return deferred;
+		},
+		function testReferenceIntegrity_deleteReferencedItemNonParent(){
+			//	summary: 
+			//		Simple test to verify the references to a non-parent item was properly deleted.
+			//	description:
+			//		Simple test to verify the references to a non-parent item was properly deleted.
+		
+			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+			var deferred = new doh.Deferred();
+			var passed = true;
+			function onError(error, request){
+				deferred.errback(error);
+			}
+			function onItem(item, request){
+				try{
+					console.log("Reference state for item 16 is: " + dojo.toJson(item[store._reverseRefMap]));
+					store.deleteItem(item);
+					function verifyRefDelete(items, request){
+						var passed = true;
+						for(var i = 0; i < items.length; i++){
+							var curItem = items[i];
+							var attributes = store.getAttributes(curItem);
+							for(var j = 0; j < attributes.length; j++){
+								var values = store.getValues(curItem, attributes[j]);
+								var badRef = false;
+								for(var k = 0; k < values.length; k++){
+									var value = values[k];
+									try{
+										var id = store.getIdentity(value);
+										if(id == 16){
+											badRef = true;
+											break;
+										}
+									}catch(e){/*Not an item, even a dead one, just eat it.*/}
+								}
+								if(badRef){
+									deferred.errback(new Error("Found a reference remaining to a deleted item.  Failure."));
+									passed = false;
+									break;
+								}
+							}
+						}
+						if(passed){
+							deferred.callback(true);
+						}
+					}
+					store.fetch({onComplete: verifyRefDelete, onError: onError});
+				}catch(error){
+					deferred.errback(error);
+				}
+			}
+			store.fetchItemByIdentity({identity: 16, onError: onError, onItem: onItem});
+			return deferred;
+		},
+		function testReferenceIntegrity_addReferenceToAttribute(){
+			//	summary: 
+			//		Simple test to verify the reference additions can happen.
+			//	description:
+			//		Simple test to verify the reference additions can happen.
+		
+			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+			var deferred = new doh.Deferred();
+			var passed = true;
+			function onError(error, request){
+				deferred.errback(error);
+				doh.assertTrue(false);
+			}
+			function onComplete(items, request){
+
+				doh.assertTrue(items.length > 2);
+
+				var item1 = items[0];
+				var item2 = items[1];
+
+				//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+				//THIS IS FOR TESTING INTERNAL STATE!
+				console.log("Map state for Item 1 is: " + dojo.toJson(item1[store._reverseRefMap]));
+				console.log("Map state for Item 2 is: " + dojo.toJson(item2[store._reverseRefMap]));
+
+				store.setValue(item1, "siblings", item2);
+
+				//Emit the current map state for inspection.
+				console.log("Map state for Item 1 is: " + dojo.toJson(item1[store._reverseRefMap]));
+				console.log("Map state for Item 2 is: " + dojo.toJson(item2[store._reverseRefMap]));
+
+				doh.assertTrue(item2[store._reverseRefMap] !== null);
+
+				//Assert there is a recorded reference to item 2 in item 1's attribute 'sibling'.
+				doh.assertTrue(item2[store._reverseRefMap][store.getIdentity(item1)]["siblings"]);
+
+				deferred.callback(true);
+			}
+			store.fetch({onError: onError, onComplete: onComplete});
+			return deferred;
+		},
+		function testReferenceIntegrity_newItemWithParentReference(){
+			//	summary: 
+			//		Simple test to verify that newItems with a parent properly record the parent's reference in the map.
+			//	description:
+			//		Simple test to verify that newItems with a parent properly record the parent's reference in the map.
+		
+			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+			var deferred = new doh.Deferred();
+			var passed = true;
+			function onError(error, request){
+				deferred.errback(error);
+				doh.assertTrue(false);
+			}
+			function onItem(item, request){
+				try{
+					//Create a new item and set its parent to item 10's uncle attribute.
+					var newItem = store.newItem({id: 17, name: "Item 17"}, {parent: item, attribute: "uncles"}); 
+					
+					//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+					//THIS IS FOR TESTING INTERNAL STATE!
+					//Look up the references to 17, as item 10 has one now on attribute 'uncles'
+					var refs = newItem[store._reverseRefMap];
+
+					//Assert there is a reference from 10 to item 17, on attribute uncle
+					doh.assertTrue(refs["10"]["uncles"]);
+
+					console.log("State of map of item 17 after newItem: " + dojo.toJson(refs));
+				}catch(e){
+					console.debug(e);
+					deferred.errback(e);
+					doh.assertTrue(false);
+					passed = false;
+				}
+				if(passed){
+					deferred.callback(true);
+				}
+			}
+			store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+			return deferred;
+		},
+		function testReferenceIntegrity_newItemWithReferenceToExistingItem(){
+			//	summary: 
+			//		Simple test to verify that a new item with references to existing items properly record the references in the map.
+			//	description:
+			//		Simple test to verify that a new item with references to existing items properly record the references in the map.
+		
+			var store = new dojo.data.ItemFileWriteStore(tests.data.ItemFileWriteStore.getTestData("reference_integrity"));
+
+			var deferred = new doh.Deferred();
+			var passed = true;
+			function onError(error, request){
+				deferred.errback(error);
+				doh.assertTrue(false);
+			}
+			function onItem(item, request){
+				try{
+					//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+					//THIS IS FOR TESTING INTERNAL STATE!
+					console.log("State of reference map to item 10 before newItem: " + dojo.toJson(item[store._reverseRefMap]));
+					
+					//Create a new item and set its parent to item 10's uncle attribute.
+					var newItem = store.newItem({id: 17, name: "Item 17", friends: [item]});
+					
+					//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+					//THIS IS FOR TESTING INTERNAL STATE!
+					//Look up the references to 10, as item 17 has one on friends now.
+					var refs = item[store._reverseRefMap];
+					
+					//Assert there is a reference from 15 to item 10, on attribute friends
+					doh.assertTrue(refs["17"]["friends"]);
+
+					console.log("State of reference map to item 10 after newItem: " + dojo.toJson(refs));
+				}catch(e){
+					console.debug(e);
+					deferred.errback(e);
+					doh.assertTrue(false);
+					passed = false;
+				}
+				if(passed){
+					deferred.callback(true);
+				}
+			}
+			store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+			return deferred;
+		},
+		function testReferenceIntegrity_disableReferenceIntegrity(){
+			//	summary: 
+			//		Simple test to verify reference integrity can be disabled.
+			//	description:
+			//		Simple test to verify reference integrity can be disabled.
+		
+			var params = tests.data.ItemFileWriteStore.getTestData("reference_integrity");
+			params.referenceIntegrity = false;
+			var store = new dojo.data.ItemFileWriteStore(params);
+
+			var deferred = new doh.Deferred();
+			function onError(error, request){
+				deferred.errback(error);
+				doh.assertTrue(false);
+			}
+			function onItem(item, request){
+				//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+				//THIS IS FOR TESTING INTERNAL STATE!
+				if(item[store._reverseRefMap] === undefined){
+					deferred.callback(true);
+				}else{
+					deferred.errback(new Error("Disabling of reference integrity failed."));
+				}
+			}
+			store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+			return deferred;
+		}, 
+		function testReadAPI_close_dirty_failure(){
+			//	summary: 
+			//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+			if (dojo.isBrowser) {
+				var params = tests.data.readOnlyItemFileTestTemplates.getTestData("countries");
+				params.clearOnClose = true;
+				params.urlPreventCache = true;
+				var store = new dojo.data.ItemFileWriteStore(params);
+
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					var error = null;
+					try {
+						doh.assertTrue(item !== null);
+						var ec = item;
+						var val = store.getValue(ec, "name");
+						doh.assertEqual("Ecuador", val);
+						var newItem = store.newItem({abbr: "foo", name: "bar"});
+						
+						//Should throw an error...
+						store.close();
+					}catch (e){
+						error = e;
+					}
+					if (error === null) {
+						d.errback(new Error("Store was dirty, should have thrown an error on close!"));
+					}else{
+						d.callback(true);
+					}
+				};
+				var onError = function(errData){
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		}
+	]
+);
+
+
diff --git a/dojo/tests/data/countries.json b/dojo/tests/data/countries.json
new file mode 100644
index 0000000..71631da
--- /dev/null
+++ b/dojo/tests/data/countries.json
@@ -0,0 +1,11 @@
+{ identifier: 'abbr', 
+  label: 'name',
+  items: [
+	{ abbr:'ec', name:'Ecuador',           capital:'Quito' },
+	{ abbr:'eg', name:'Egypt',             capital:'Cairo' },
+	{ abbr:'sv', name:'El Salvador',       capital:'San Salvador' },
+	{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+	{ abbr:'er', name:'Eritrea',           capital:'Asmara' },
+	{ abbr:'ee', name:'Estonia',           capital:'Tallinn' },
+	{ abbr:'et', name:'Ethiopia',          capital:'Addis Ababa' }
+]}
diff --git a/dojo/tests/data/countries_commentFiltered.json b/dojo/tests/data/countries_commentFiltered.json
new file mode 100644
index 0000000..319e429
--- /dev/null
+++ b/dojo/tests/data/countries_commentFiltered.json
@@ -0,0 +1,12 @@
+/*
+{ identifier: 'abbr', 
+  items: [
+	{ abbr:'ec', name:'Ecuador',           capital:'Quito' },
+	{ abbr:'eg', name:'Egypt',             capital:'Cairo' },
+	{ abbr:'sv', name:'El Salvador',       capital:'San Salvador' },
+	{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+	{ abbr:'er', name:'Eritrea',           capital:'Asmara' },
+	{ abbr:'ee', name:'Estonia',           capital:'Tallinn' },
+	{ abbr:'et', name:'Ethiopia',          capital:'Addis Ababa' }
+]}
+*/
diff --git a/dojo/tests/data/countries_idcollision.json b/dojo/tests/data/countries_idcollision.json
new file mode 100644
index 0000000..a0c4a7b
--- /dev/null
+++ b/dojo/tests/data/countries_idcollision.json
@@ -0,0 +1,10 @@
+{ identifier: 'abbr', 
+  items: [
+		{ abbr:'ec', name:'Ecuador',           capital:'Quito' },
+		{ abbr:'sv', name:'El Salvador',       capital:'San Salvador' },
+		{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+		{ abbr:'er', name:'Eritrea',           capital:'Asmara' },
+		{ abbr:'ec', name:'Egypt',             capital:'Cairo' },
+		{ abbr:'ee', name:'Estonia',           capital:'Tallinn' },
+		{ abbr:'et', name:'Ethiopia',          capital:'Addis Ababa' }
+]}
diff --git a/dojo/tests/data/countries_references.json b/dojo/tests/data/countries_references.json
new file mode 100644
index 0000000..136f3c2
--- /dev/null
+++ b/dojo/tests/data/countries_references.json
@@ -0,0 +1,44 @@
+{ 'identifier': 'name',
+  'label': 'name',
+  'items': [
+	{ 'name':'Africa', 'type':'continent',
+		'children':[{'_reference':'Egypt'}, {'_reference':'Kenya'}, {'_reference':'Sudan'}] },
+	{ 'name':'Egypt', 'type':'country' },
+	{ 'name':'Kenya', 'type':'country',
+		 'children':[{'_reference':'Nairobi'}, {'_reference':'Mombasa'}] },
+	{ 'name':'Nairobi', 'type':'city' },
+	{ 'name':'Mombasa', 'type':'city' },
+	{ 'name':'Sudan', 'type':'country',
+		'children':{'_reference':'Khartoum'} },
+	{ 'name':'Khartoum', 'type':'city' },
+	{ 'name':'Asia', 'type':'continent',
+		'children':[{'_reference':'China'}, {'_reference':'India'}, {'_reference':'Russia'}, {'_reference':'Mongolia'}] },
+	{ 'name':'China', 'type':'country' },
+	{ 'name':'India', 'type':'country' },
+	{ 'name':'Russia', 'type':'country' },
+	{ 'name':'Mongolia', 'type':'country' },
+	{ 'name':'Australia', 'type':'continent', 'population':'21 million',
+		'children':{'_reference':'Commonwealth of Australia'}},
+	{ 'name':'Commonwealth of Australia', 'type':'country', 'population':'21 million'},
+	{ 'name':'Europe', 'type':'continent',
+		'children':[{'_reference':'Germany'}, {'_reference':'France'}, {'_reference':'Spain'}, {'_reference':'Italy'}] },
+	{ 'name':'Germany', 'type':'country' },
+	{ 'name':'France', 'type':'country' },
+	{ 'name':'Spain', 'type':'country' },
+	{ 'name':'Italy', 'type':'country' },
+	{ 'name':'North America', 'type':'continent',
+		'children':[{'_reference':'Mexico'}, {'_reference':'Canada'}, {'_reference':'United States of America'}] },
+	{ 'name':'Mexico', 'type':'country',  'population':'108 million', area:'1,972,550 sq km',
+		'children':[{'_reference':'Mexico City'}, {'_reference':'Guadalajara'}] },
+	{ 'name':'Mexico City', 'type':'city', 'population':'19 million', 'timezone':'-6 UTC'},
+	{ 'name':'Guadalajara', 'type':'city', 'population':'4 million', 'timezone':'-6 UTC' },
+	{ 'name':'Canada', 'type':'country',  'population':'33 million', area:'9,984,670 sq km',
+		'children':[{'_reference':'Ottawa'}, {'_reference':'Toronto'}] },
+	{ 'name':'Ottawa', 'type':'city', 'population':'0.9 million', 'timezone':'-5 UTC'},
+	{ 'name':'Toronto', 'type':'city', 'population':'2.5 million', 'timezone':'-5 UTC' },
+	{ 'name':'United States of America', 'type':'country' },
+	{ 'name':'South America', 'type':'continent',
+		'children':[{'_reference':'Brazil'}, {'_reference':'Argentina'}] },
+	{ 'name':'Brazil', 'type':'country', 'population':'186 million' },
+	{ 'name':'Argentina', 'type':'country', 'population':'40 million' }
+]}
diff --git a/dojo/tests/data/countries_withBoolean.json b/dojo/tests/data/countries_withBoolean.json
new file mode 100644
index 0000000..783d8a8
--- /dev/null
+++ b/dojo/tests/data/countries_withBoolean.json
@@ -0,0 +1,11 @@
+{ identifier: 'abbr', 
+  items: [
+	{ abbr:'ec', name:'Ecuador',           capital:'Quito',        real:true},
+	{ abbr:'eg', name:'Egypt',             capital:'Cairo',        real:true},
+	{ abbr:'sv', name:'El Salvador',       capital:'San Salvador', real:true},
+	{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo',       real:true},
+	{ abbr:'er', name:'Eritrea',           capital:'Asmara',       real:true},
+	{ abbr:'ee', name:'Estonia',           capital:'Tallinn',      real:true},
+	{ abbr:'et', name:'Ethiopia',          capital:'Addis Ababa',  real:true},
+	{ abbr:'ut', name:'Utopia',            capital:'Paradise',     real:false}
+]}
diff --git a/dojo/tests/data/countries_withDates.json b/dojo/tests/data/countries_withDates.json
new file mode 100644
index 0000000..fdd2153
--- /dev/null
+++ b/dojo/tests/data/countries_withDates.json
@@ -0,0 +1,21 @@
+{ identifier: 'abbr', 
+  label: 'name',
+  items: [
+	{ abbr:'ec', name:'Ecuador',           capital:'Quito' },
+	{ abbr:'eg', name:'Egypt',             capital:'Cairo' },
+	{ abbr:'sv', name:'El Salvador',       capital:'San Salvador' },
+	{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+	{ abbr:'er',
+	  name:'Eritrea',
+	  capital:'Asmara',
+	  independence:{_type:'Date', _value:"1993-05-24T00:00:00Z"} // May 24, 1993 in ISO-8601 standard  
+          },
+	{ abbr:'ee',
+	  name:'Estonia',
+	  capital:'Tallinn',
+	  independence:{_type:'Date', _value:"1991-08-20T00:00:00Z"} // August 20, 1991 in ISO-8601 standard
+	  },
+	{ abbr:'et',
+	  name:'Ethiopia',
+	  capital:'Addis Ababa' }
+]}
diff --git a/dojo/tests/data/countries_withNull.json b/dojo/tests/data/countries_withNull.json
new file mode 100644
index 0000000..a0a7a3f
--- /dev/null
+++ b/dojo/tests/data/countries_withNull.json
@@ -0,0 +1,10 @@
+{ identifier: 'abbr', 
+  items: [
+	{ abbr:'ec', name:null,                capital:'Quito' },
+	{ abbr:'eg', name:null,                capital:'Cairo' },
+	{ abbr:'sv', name:'El Salvador',       capital:'San Salvador' },
+	{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+	{ abbr:'er', name:'Eritrea',           capital:'Asmara' },
+	{ abbr:'ee', name:null,                capital:'Tallinn' },
+	{ abbr:'et', name:'Ethiopia',          capital:'Addis Ababa' }
+]}
diff --git a/dojo/tests/data/countries_withoutid.json b/dojo/tests/data/countries_withoutid.json
new file mode 100644
index 0000000..8db3046
--- /dev/null
+++ b/dojo/tests/data/countries_withoutid.json
@@ -0,0 +1,10 @@
+{ label: 'name',
+  items: [
+	{ abbr:'ec', name:'Ecuador',           capital:'Quito' },
+	{ abbr:'eg', name:'Egypt',             capital:'Cairo' },
+	{ abbr:'sv', name:'El Salvador',       capital:'San Salvador' },
+	{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+	{ abbr:'er', name:'Eritrea',           capital:'Asmara' },
+	{ abbr:'ee', name:'Estonia',           capital:'Tallinn' },
+	{ abbr:'et', name:'Ethiopia',          capital:'Addis Ababa' }
+]}
diff --git a/dojo/tests/data/data_multitype.json b/dojo/tests/data/data_multitype.json
new file mode 100644
index 0000000..449995a
--- /dev/null
+++ b/dojo/tests/data/data_multitype.json
@@ -0,0 +1,18 @@
+{ 
+	"identifier": "count",
+	"label": "count", 
+	"items": [
+		{ "count": 1,    "value": "true" },
+		{ "count": 2,    "value": true   },
+		{ "count": 3,    "value": "false"},
+		{ "count": 4,    "value": false  },
+		{ "count": 5,    "value": true   },
+		{ "count": 6,    "value": true   },
+		{ "count": 7,    "value": "true" },
+		{ "count": 8,    "value": "true" },
+		{ "count": 9,    "value": "false"},
+		{ "count": 10,   "value": false  },
+		{ "count": 11,   "value": [false, false]},
+		{ "count": "12", "value": [false, "true"]}
+	]
+}
diff --git a/dojo/tests/data/geography_hierarchy_large.json b/dojo/tests/data/geography_hierarchy_large.json
new file mode 100644
index 0000000..847c47b
--- /dev/null
+++ b/dojo/tests/data/geography_hierarchy_large.json
@@ -0,0 +1,44 @@
+{ identifier: 'name',
+  items: [
+	{ name:'Africa', type:'continent', children:[
+		{ name:'Egypt', type:'country' }, 
+		{ name:'Kenya', type:'country', children:[
+			{ name:'Nairobi', type:'city' },
+			{ name:'Mombasa', type:'city' } ]
+		},
+		{ name:'Sudan', type:'country', children:
+			{ name:'Khartoum', type:'city' } 
+		} ]
+	},
+	{ name:'Asia', type:'continent', children:[
+		{ name:'China', type:'country' },
+		{ name:'India', type:'country' },
+		{ name:'Russia', type:'country' },
+		{ name:'Mongolia', type:'country' } ]
+	},
+	{ name:'Australia', type:'continent', population:'21 million', children:
+		{ name:'Commonwealth of Australia', type:'country', population:'21 million'}
+	},
+	{ name:'Europe', type:'continent', children:[
+		{ name:'Germany', type:'country' },
+		{ name:'France', type:'country' },
+		{ name:'Spain', type:'country' },
+		{ name:'Italy', type:'country' } ]
+	},
+	{ name:'North America', type:'continent', children:[
+		{ name:'Mexico', type:'country',  population:'108 million', area:'1,972,550 sq km', children:[
+			{ name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
+			{ name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' } ]
+		},
+		{ name:'Canada', type:'country',  population:'33 million', area:'9,984,670 sq km', children:[
+			{ name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
+			{ name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' }]
+		},
+		{ name:'United States of America', type:'country' } ]
+	},
+	{ name:'South America', type:'continent', children:[
+		{ name:'Brazil', type:'country', population:'186 million' },
+		{ name:'Argentina', type:'country', population:'40 million' } ]
+	} ]
+}
+
diff --git a/dojo/tests/data/geography_hierarchy_small.json b/dojo/tests/data/geography_hierarchy_small.json
new file mode 100644
index 0000000..989e5f7
--- /dev/null
+++ b/dojo/tests/data/geography_hierarchy_small.json
@@ -0,0 +1,19 @@
+{ items:[
+	{ name:'Africa', countries:[
+		{ name:'Egypt', capital:'Cairo' },
+		{ name:'Kenya', capital:'Nairobi' },
+		{ name:'Sudan', capital:'Khartoum' }]},
+	{ name:'Australia', capital:'Canberra' },
+	{ name:'North America', countries:[
+		{ name:'Canada', population:'33 million', cities:[
+			{ name:'Toronto', population:'2.5 million' },
+			{ name:'Alberta', population:'1 million' }
+			]},
+		{ name: 'United States of America', capital: 'Washington DC', states:[
+			{ name: 'Missouri'},
+			{ name: 'Arkansas'}
+			]}
+		]}
+	]
+}
+
diff --git a/dojo/tests/data/readOnlyItemFileTestTemplates.js b/dojo/tests/data/readOnlyItemFileTestTemplates.js
new file mode 100644
index 0000000..848fc23
--- /dev/null
+++ b/dojo/tests/data/readOnlyItemFileTestTemplates.js
@@ -0,0 +1,3105 @@
+dojo.provide("tests.data.readOnlyItemFileTestTemplates");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+dojo.require("dojo.date");
+dojo.require("dojo.date.stamp");
+
+dojo.declare("tests.data.Wrapper", null, {
+	//	summary:
+	//		Simple class to use for typeMap in order to	test out 
+	//		'falsy' values for _value.
+	_wrapped: null,
+
+	constructor: function(obj){
+		this._wrapped = obj;
+	},
+
+	getValue: function() {
+		return this._wrapped;
+	},
+
+	setValue: function(obj) {
+		this._wrapped = obj;
+	},
+
+	toString: function(){
+		 return "WRAPPER: [" + this._wrapped + "]";
+	}
+});
+
+
+tests.data.readOnlyItemFileTestTemplates.registerTestsForDatastore = function(/* String */ datastoreClassName){
+	// summary:
+	//		Given the name of a datastore class to use, this function creates
+	//		a set of unit tests for that datastore, and registers the new test
+	//		group with the doh test framework.  The new unit tests are based
+	//		on a set of "template" unit tests.
+	var datastoreClass = dojo.getObject(datastoreClassName);
+	var testTemplates = tests.data.readOnlyItemFileTestTemplates.testTemplates;
+	var testsForDatastore = [];
+	var makeNewTestFunction = function(template){
+		return function(t){return template.runTest(datastoreClass, t);};
+	};
+	for(var i = 0; i < testTemplates.length; ++i) {
+		var testTemplate = testTemplates[i];
+		var test = {};
+		test.name = testTemplate.name;
+		test.runTest = makeNewTestFunction(testTemplate);
+		testsForDatastore.push(test);
+	}
+	var testGroupName = "IFSCommonTests: " + datastoreClassName;
+	doh.register(testGroupName, testsForDatastore);
+};
+
+
+//-----------------------------------------------------
+// testFile data-sets
+tests.data.readOnlyItemFileTestTemplates.getTestData = function(name){
+	var data = null;
+	if(name === "countries"){
+		if(dojo.isBrowser){
+			data = {url: dojo.moduleUrl("tests", "data/countries.json").toString() };
+		}else{
+			data = {data: { 
+				identifier:"abbr",
+				label:"name",
+				items:[
+					{abbr:"ec", name:"Ecuador", capital:"Quito"},
+					{abbr:'eg', name:'Egypt', capital:'Cairo'},
+					{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+					{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+					{abbr:'er', name:'Eritrea', capital:'Asmara'},
+					{abbr:'ee', name:'Estonia', capital:'Tallinn'},
+					{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+				]
+			} };
+		}	
+	}else if(name === "countries_withNull"){
+		if(dojo.isBrowser){
+			data = {url: dojo.moduleUrl("tests", "data/countries_withNull.json").toString() };
+		}else{
+			data = {data: { 
+				identifier:"abbr",
+				items:[
+					{abbr:"ec", name:null, capital:"Quito"},
+					{abbr:'eg', name:null, capital:'Cairo'},
+					{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+					{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+					{abbr:'er', name:'Eritrea', capital:'Asmara'},
+					{abbr:'ee', name:null, capital:'Tallinn'},
+					{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+				]
+			} };
+		}
+	}else if(name === "countries_withoutid"){
+		if(dojo.isBrowser){
+			data = {url: dojo.moduleUrl("tests", "data/countries_withoutid.json").toString() };
+		}else{
+			data = {data: { 
+				label: "name",
+				items:[
+					{abbr:"ec", name:null, capital:"Quito"},
+					{abbr:'eg', name:null, capital:'Cairo'},
+					{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+					{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+					{abbr:'er', name:'Eritrea', capital:'Asmara'},
+					{abbr:'ee', name:null, capital:'Tallinn'},
+					{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+				]
+			} };
+		}
+	}else if (name === "countries_withBoolean"){
+		if(dojo.isBrowser){
+			data = {url: dojo.moduleUrl("tests", "data/countries_withBoolean.json").toString() };
+		}else{
+			data = {data: { 
+				identifier:"abbr",
+				items:[
+					{abbr:"ec", name:"Ecuador", capital:"Quito", real:true},
+					{abbr:'eg', name:'Egypt', capital:'Cairo', real:true},
+					{abbr:'sv', name:'El Salvador', capital:'San Salvador', real:true},
+					{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo', real:true},
+					{abbr:'er', name:'Eritrea', capital:'Asmara', real:true},
+					{abbr:'ee', name:'Estonia', capital:'Tallinn', real:true},
+					{abbr:'et', name:'Ethiopia', capital:'Addis Ababa', real:true},
+					{abbr:'ut', name:'Utopia', capital:'Paradise', real:false}
+				]
+			} };
+		}
+	}else if (name === "countries_withDates"){
+		if(dojo.isBrowser){
+			data = {url: dojo.moduleUrl("tests", "data/countries_withDates.json").toString() };
+		}else{
+			data = {data: { 
+				identifier:"abbr",
+				items:[
+					{abbr:"ec", name:"Ecuador", capital:"Quito"},
+					{abbr:'eg', name:'Egypt', capital:'Cairo'},
+					{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+					{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+					{abbr:'er', name:'Eritrea', capital:'Asmara', independence:{_type:'Date', _value:"1993-05-24T00:00:00Z"}}, // May 24, 1993,
+					{abbr:'ee', name:'Estonia', capital:'Tallinn', independence:{_type:'Date', _value:"1991-08-20T00:00:00Z"}}, // August 20, 1991
+					{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+				]
+			} };
+		}
+	}else if (name === "geography_hierarchy_small"){
+		if(dojo.isBrowser){
+			data = {url: dojo.moduleUrl("tests", "data/geography_hierarchy_small.json").toString() };
+		}else{
+			data = {data: { 
+				items:[
+					{ name:'Africa', countries:[
+						{ name:'Egypt', capital:'Cairo' },
+						{ name:'Kenya', capital:'Nairobi' },
+						{ name:'Sudan', capital:'Khartoum' }]},
+					{ name:'Australia', capital:'Canberra' },
+					{ name:'North America', countries:[
+						{ name:'Canada', population:'33 million', cities:[
+							{ name:'Toronto', population:'2.5 million' },
+							{ name:'Alberta', population:'1 million' }
+							]},
+						{ name: 'United States of America', capital: 'Washington DC', states:[
+							{ name: 'Missouri'},
+							{ name: 'Arkansas'}
+							]}
+						]}
+				]
+			}};
+		}
+	}else if (name === "data_multitype"){
+		if(dojo.isBrowser){
+			data = {url: dojo.moduleUrl("tests", "data/data_multitype.json").toString() };
+		}else{
+			data = {data: { 
+							"identifier": "count",
+							"label": "count", 
+							items: [
+								{ count: 1,    value: "true" },
+								{ count: 2,    value: true   },
+								{ count: 3,    value: "false"},
+								{ count: 4,    value: false  },
+								{ count: 5,    value: true   },
+								{ count: 6,    value: true   },
+								{ count: 7,    value: "true" },
+								{ count: 8,    value: "true" },
+								{ count: 9,    value: "false"},
+								{ count: 10,   value: false  },
+								{ count: 11,   value: [false, false]},
+								{ count: "12", value: [false, "true"]}
+						   ]
+						} 
+					};
+		}
+	}else if (name === "countries_references"){
+		if(dojo.isBrowser){
+			data = {url: dojo.moduleUrl("tests", "data/countries_references.json").toString() };
+		}else{
+			data = {data: { identifier: 'name',
+							label: 'name',
+							items: [
+								{ name:'Africa', type:'continent',
+									children:[{_reference:'Egypt'}, {_reference:'Kenya'}, {_reference:'Sudan'}] },
+								{ name:'Egypt', type:'country' },
+								{ name:'Kenya', type:'country',
+									children:[{_reference:'Nairobi'}, {_reference:'Mombasa'}] },
+								{ name:'Nairobi', type:'city' },
+								{ name:'Mombasa', type:'city' },
+								{ name:'Sudan', type:'country',
+									children:{_reference:'Khartoum'} },
+								{ name:'Khartoum', type:'city' },
+								{ name:'Asia', type:'continent',
+									children:[{_reference:'China'}, {_reference:'India'}, {_reference:'Russia'}, {_reference:'Mongolia'}] },
+								{ name:'China', type:'country' },
+								{ name:'India', type:'country' },
+								{ name:'Russia', type:'country' },
+								{ name:'Mongolia', type:'country' },
+								{ name:'Australia', type:'continent', population:'21 million',
+									children:{_reference:'Commonwealth of Australia'}},
+								{ name:'Commonwealth of Australia', type:'country', population:'21 million'},
+								{ name:'Europe', type:'continent',
+									children:[{_reference:'Germany'}, {_reference:'France'}, {_reference:'Spain'}, {_reference:'Italy'}] },
+								{ name:'Germany', type:'country' },
+								{ name:'France', type:'country' },
+								{ name:'Spain', type:'country' },
+								{ name:'Italy', type:'country' },
+								{ name:'North America', type:'continent',
+									children:[{_reference:'Mexico'}, {_reference:'Canada'}, {_reference:'United States of America'}] },
+								{ name:'Mexico', type:'country',  population:'108 million', area:'1,972,550 sq km',
+									children:[{_reference:'Mexico City'}, {_reference:'Guadalajara'}] },
+								{ name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
+								{ name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' },
+								{ name:'Canada', type:'country',  population:'33 million', area:'9,984,670 sq km',
+									children:[{_reference:'Ottawa'}, {_reference:'Toronto'}] },
+								{ name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
+								{ name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' },
+								{ name:'United States of America', type:'country' },
+								{ name:'South America', type:'continent',
+									children:[{_reference:'Brazil'}, {_reference:'Argentina'}] },
+								{ name:'Brazil', type:'country', population:'186 million' },
+								{ name:'Argentina', type:'country', population:'40 million' }
+							]
+						}
+					};
+		}
+	}
+	return data;
+};
+
+//-----------------------------------------------------
+// testTemplates
+tests.data.readOnlyItemFileTestTemplates.testTemplates = [
+	{
+		name: "Identity API: fetchItemByIdentity()",
+		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				if(item !== null){
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, "El Salvador");
+				}
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Identity API: fetchItemByIdentity() preventCache",
+		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			var args = tests.data.readOnlyItemFileTestTemplates.getTestData("countries");
+			args.urlPreventCache = true;
+			var store = new datastore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				if(item !== null){
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, "El Salvador");
+				}
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Identity API: fetchItemByIdentity() notFound",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "sv_not", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Identity API: getIdentityAttributes()",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the getIdentityAttributes function.
+			//	description:
+			//		Simple test of the getIdentityAttributes function.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null)
+				var identifiers = store.getIdentityAttributes(item);
+				t.assertTrue(dojo.isArray(identifiers));
+				t.assertEqual(1, identifiers.length);
+				t.assertEqual("abbr", identifiers[0]);
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Identity API: fetchItemByIdentity() commentFilteredJson",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//		This tests loading a comment-filtered json file so that people using secure
+			//		data with this store can bypass the JavaSceipt hijack noted in Fortify's
+			//		paper.
+
+			if(dojo.isBrowser){
+                var store = new datastore({url: dojo.moduleUrl("tests", "data/countries_commentFiltered.json").toString()});
+
+				var d = new doh.Deferred();
+				function onItem(item){
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, "El Salvador");
+					d.callback(true);
+				}
+				function onError(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				}
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		}
+	},
+	{
+		name: "Identity API: fetchItemByIdentity() nullValue",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store, checling a null value.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store, checking a null value.
+			//		This tests handling attributes in json that were defined as null properly.
+			//		Introduced because of tracker: #3153
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withNull"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var name = store.getValue(item,"name");
+				t.assertEqual(name, null);
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "ec", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Identity API: fetchItemByIdentity() booleanValue",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store, checking a boolean value.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store, checking a boolean value.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withBoolean"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var name = store.getValue(item,"name");
+				t.assertEqual(name, "Utopia");
+				var real = store.getValue(item,"real");
+				t.assertEqual(real, false);
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "ut", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Identity API: fetchItemByIdentity() withoutSpecifiedIdInData",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of bug #4691, looking up something by assigned id, not one specified in the JSON data.
+			//	description:
+			//		Simple test of bug #4691, looking up something by assigned id, not one specified in the JSON data.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withoutid"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var name = store.getValue(item,"name");
+				t.assertEqual(name, "El Salvador");
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "2", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Identity API: getIdentity()",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the getIdentity function of the store.
+			//	description:
+			//		Simple test of the getIdentity function of the store.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(store.getIdentity(item) === "sv");
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Identity API: getIdentity() withoutSpecifiedId",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the #4691 bug
+			//	description:
+			//		Simple test of the #4691 bug
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withoutid"));
+
+			var d = new doh.Deferred();
+			function onItem(item, request){
+				t.assertTrue(item !== null);
+				t.assertTrue(store.getIdentity(item) === 2);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetch({ query:{abbr: "sv"}, onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: fetch() all",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore.
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			
+			var d = new doh.Deferred();
+			function completedAll(items, request){
+				t.is(7, items.length);
+				d.callback(true);
+			}
+			function error(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+
+			//Get everything...
+			store.fetch({ onComplete: completedAll, onError: error});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() all failOk",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore that fails quietly.
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore that fails quietly.
+			if(dojo.isBrowser){
+				var storeParams = {
+					url: "noSuchUrl",
+					failOk: true
+				}
+				var store = new datastore(storeParams);
+				console.log(store);
+                
+				var d = new doh.Deferred();
+				var completedAll = function(items, request){
+					d.errback(new Error("Should not be here, should have failed load."));
+				}
+				var error = function(errData, request){
+					d.callback(true);
+				}
+
+				//Get everything...
+				store.fetch({ onComplete: completedAll, onError: error});
+				return d;
+			}
+		}
+	},
+	{
+		name: "Read API: fetch() abort",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch abort on ItemFileReadStore.
+			//	description:
+			//		Simple test of a basic fetch abort on ItemFileReadStore.
+			//Can only async abort in a browser, so disable this test from rhino
+			if(dojo.isBrowser){
+				var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			
+				var d = new doh.Deferred();
+				var abortCalled = false;
+				function completedAll(items, request){
+					t.is(7, items.length);
+					if(abortCalled){
+						console.log("Made it to complete callback and abort was called.  Problem.");
+						d.errback(new Error("Should not be here."));
+					}else{
+						//We beat out calling abort, so this is okay.  Timing.
+						console.log("in onComplete and abort has not been called.  Timing.  This is okay.");
+						d.callback(true);
+					}
+				}
+				function error(errData, request){
+					//An abort should throw a cancel error, so we should
+					//reach this.
+					t.assertTrue(true);
+					d.callback(true);
+				}
+
+				//Get everything...
+				var req = store.fetch({ onComplete: completedAll, onError: error});
+				abortCalled=true;
+				console.log("Calling abort.");
+				req.abort();
+				return d;
+			}
+		}
+	},
+	{
+		name: "Read API: fetch() all (count === Infinity)",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore and with a count of Infinity.
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore and with a count of Infinity.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			
+			var d = new doh.Deferred();
+			function completedAll(items, request){
+				t.is(7, items.length);
+				d.callback(true);
+			}
+			function error(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+
+			//Get everything...
+			store.fetch({ onComplete: completedAll, onError: error, start: 0, count: Infinity});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() all PreventCache",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore.
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore.
+			var args = tests.data.readOnlyItemFileTestTemplates.getTestData("countries");
+			args.urlPreventCache = true;
+			var store = new datastore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items, request){
+				t.is(7, items.length);
+				d.callback(true);
+			}
+			function error(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+
+			//Get everything...
+			store.fetch({ onComplete: completedAll, onError: error});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() one",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore of a single item.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetch({ 	query: {abbr: "ec"}, 
+									onComplete: onComplete, 
+									onError: onError
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() shallow",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore of only toplevel items
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore of only toplevel items.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 2);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			//Find all items starting with A, only toplevel (root) items.
+			store.fetch({ 	query: {name: "A*"}, 
+									onComplete: onComplete, 
+									onError: onError
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() Multiple",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+			//	description:
+			//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+			
+			var d = new doh.Deferred();
+			var done = [false, false];
+
+			function onCompleteOne(items, request){
+				done[0] = true;
+				t.assertEqual(items.length, 2);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			function onCompleteTwo(items, request){
+				done[1] = true;
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			//Find all items starting with A, only toplevel (root) items.
+			store.fetch({ 	query: {name: "A*"}, 
+									onComplete: onCompleteOne, 
+									onError: onError
+								});
+
+			//Find all items starting with A, only toplevel (root) items.
+			store.fetch({ 	query: {name: "N*"}, 
+									onComplete: onCompleteTwo, 
+									onError: onError
+								});
+
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() MultipleMixedFetch",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+			//	description:
+			//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+			//		Tests an item fetch and an identity fetch.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			
+			var d = new doh.Deferred();
+			var done = [false, false];
+
+			function onComplete(items, request){
+				done[0] = true;
+				t.assertEqual(items.length, 1);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			function onItem(item){
+				done[1] = true;
+				t.assertTrue(item !== null);
+				var name = store.getValue(item,"name");
+				t.assertEqual(name, "El Salvador");
+				
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			
+			//Find all items starting with A, only toplevel (root) items.
+			store.fetch({ 	query: {name: "El*"}, 
+									onComplete: onComplete, 
+									onError: onError
+								});
+			
+			store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() deep",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore of all items (including children (nested))
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore of all items (including children (nested))
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 4);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			//Find all items starting with A, including child (nested) items.
+			store.fetch({ 	query: {name: "A*"}, 
+									onComplete: onComplete, 
+									onError: onError,
+									queryOptions: {deep:true}
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() hierarchy off",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore of all items with hierarchy disabled
+			//		This should turn off processing child objects as data store items.  It will still process
+			//		references and type maps.
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore of all items with hierarchy disabled
+			//		This should turn off processing child objects as data store items.  It will still process
+			//		references and type maps.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+			
+			//Set this as hierarchy off before fetch to make sure it traps and configs right.
+			store.hierarchical = false;
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				//With hierarchy off, this should only match 2, as only two data store items
+				//will be quertied
+				t.assertEqual(items.length, 2);
+				var i;
+				var passed = true;
+				for(i = 0; i < items.length; i++){
+					var countries = store.getValues(items[i], "countries");
+					if(countries){
+						var j;
+						//Make sure none of the child objects were processed into items.
+						for(j = 0; j<countries.length; j++){
+							passed = !store.isItem(countries[j]);
+							if(!passed){
+								break;
+							}
+						}
+					}
+					if(!passed){
+						break;
+					}
+				}
+				if(!passed){
+					d.errback(new Error("Located a child item with hierarchy off and no references in the data.  Error."));
+				}else{
+					d.callback(true);
+				}
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			//Find all items starting with A, including child (nested) items.
+			store.fetch({ 	query: {name: "A*"}, 
+									onComplete: onComplete, 
+									onError: onError,
+									queryOptions: {deep:true}
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() hierarchy off refs still parse",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore of all items with hierarchy disabled
+			//		This should turn off processing child objects as data store items.  It will still process
+			//		references and type maps.
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore of all items with hierarchy disabled
+			//		This should turn off processing child objects as data store items.  It will still process
+			//		references and type maps.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_references"));
+			
+			//Set this as hierarchy off before fetch to make sure it traps and configs right.
+			store.hierarchical = false;
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				//With hierarchy off, this should only match 2, as only two data store items
+				//will be quertied
+				t.assertEqual(items.length, 4);
+				var i;
+				var passed = true;
+				for(i = 0; i < items.length; i++){
+					var countries = store.getValues(items[i], "children");
+					if(countries){
+						var j;
+						//Make sure none of the child objects were processed into items.
+						for(j = 0; j<countries.length; j++){
+							passed = store.isItem(countries[j]);
+							if(!passed){
+								break;
+							}
+						}
+					}
+					if(!passed){
+						break;
+					}
+				}
+				if(!passed){
+					d.errback(new Error("Found a non-child item in a reference list in a references based input.  Error."));
+				}else{
+					d.callback(true);
+				}
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			//Find all items starting with A, including child (nested) items.
+			store.fetch({ 	query: {name: "A*"}, 
+									onComplete: onComplete, 
+									onError: onError,
+									queryOptions: {deep:true}
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() one_commentFilteredJson",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore of a single item.
+			//		This tests loading a comment-filtered json file so that people using secure
+			//		data with this store can bypass the JavaSceipt hijack noted in Fortify's
+			//		paper.
+			if(dojo.isBrowser){
+                var store = new datastore({url: dojo.moduleUrl("tests", "data/countries_commentFiltered.json").toString()});
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					d.callback(true);
+				}
+				function onError(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				}
+				store.fetch({ 	query: {abbr: "ec"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		}
+	},
+	{
+		name: "Read API: fetch() withNull",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore of a single item where some attributes are null.
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore of a single item where some attributes are null.
+			//		Introduced because of tracker: #3153
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withNull"));
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(4, items.length);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetch({ 	query: {name: "E*"}, 
+									onComplete: onComplete, 
+									onError: onError
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() all_streaming",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch on ItemFileReadStore.
+			//	description:
+			//		Simple test of a basic fetch on ItemFileReadStore.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			count = 0;
+
+			function onBegin(size, requestObj){
+				t.assertEqual(size, 7);
+			}
+			function onItem(item, requestObj){
+				t.assertTrue(store.isItem(item));
+				count++;
+			}
+			function onComplete(items, request){
+				t.assertEqual(count, 7);
+				t.assertTrue(items === null);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+
+			//Get everything...
+			store.fetch({	onBegin: onBegin,
+									onItem: onItem, 
+									onComplete: onComplete,
+									onError: onError
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() paging",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Test of multiple fetches on a single result.  Paging, if you will.
+			//	description:
+			//		Test of multiple fetches on a single result.  Paging, if you will.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			
+			var d = new doh.Deferred();
+			function dumpFirstFetch(items, request){
+				t.assertEqual(items.length, 5);
+				request.start = 3;
+				request.count = 1;
+				request.onComplete = dumpSecondFetch;
+				store.fetch(request);
+			}
+
+			function dumpSecondFetch(items, request){
+				t.assertEqual(items.length, 1);
+				request.start = 0;
+				request.count = 5;
+				request.onComplete = dumpThirdFetch;
+				store.fetch(request);
+			}
+
+			function dumpThirdFetch(items, request){
+				t.assertEqual(items.length, 5);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpFourthFetch;
+				store.fetch(request);
+			}
+
+			function dumpFourthFetch(items, request){
+				t.assertEqual(items.length, 5);
+				request.start = 9;
+				request.count = 100;
+				request.onComplete = dumpFifthFetch;
+				store.fetch(request);
+			}
+
+			function dumpFifthFetch(items, request){
+				t.assertEqual(items.length, 0);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpSixthFetch;
+				store.fetch(request);
+			}
+
+			function dumpSixthFetch(items, request){
+				t.assertEqual(items.length, 5);
+				d.callback(true);
+			}
+
+			function completed(items, request){
+				t.assertEqual(items.length, 7);
+				request.start = 1;
+				request.count = 5;
+				request.onComplete = dumpFirstFetch;
+				store.fetch(request);
+			}
+
+			function error(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetch({onComplete: completed, onError: error});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() with MultiType Match",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+			//	description:
+			//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+			//		Introduced because of tracker: #4931
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("data_multitype"));
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(4, items.length);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetch({ 	query: {count: "1*"}, 
+									onComplete: onComplete, 
+									onError: onError
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() with RegExp Match",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch using a RegExp works with IFRS
+			//	description:
+			//		Simple test of a basic fetch using a RegExp works with IFRS
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("data_multitype"));
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(4, items.length);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetch({ 	query: {count: new RegExp("^1.*$", "gi")}, 
+									onComplete: onComplete, 
+									onError: onError
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() with RegExp Match Inline",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch using a RegExp works with IFRS
+			//	description:
+			//		Simple test of a basic fetch using a RegExp works with IFRS
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("data_multitype"));
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(4, items.length);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetch({ 	query: {count: /^1.*$/gi}, 
+									onComplete: onComplete, 
+									onError: onError
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() with MultiType, MultiValue Match",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+			//	description:
+			//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+			//		Introduced because of tracker: #4931
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("data_multitype"));
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(7, items.length);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetch({ 	query: {value: "true"}, 
+									onComplete: onComplete, 
+									onError: onError
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: getLabel()",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = store.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				t.assertEqual("Ecuador", label);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetch({ 	query: {abbr: "ec"}, 
+									onComplete: onComplete, 
+									onError: onError
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: getLabelAttributes()",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var labelList = store.getLabelAttributes(items[0]);
+				t.assertTrue(dojo.isArray(labelList));
+				t.assertEqual("name", labelList[0]);
+				d.callback(true);
+			}
+			function onError(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetch({ 	query: {abbr: "ec"}, 
+									onComplete: onComplete, 
+									onError: onError
+								});
+			return d;
+		}
+	},
+	{
+		name: "Read API: getValue()",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var name = store.getValue(item,"name");
+				t.assertTrue(name === "El Salvador");
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: getValues()",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the getValues function of the store.
+			//	description:
+			//		Simple test of the getValues function of the store.
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var names = store.getValues(item,"name");
+				t.assertTrue(dojo.isArray(names));
+				t.assertEqual(names.length, 1);
+				t.assertEqual(names[0], "El Salvador");
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: isItem()",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the isItem function of the store
+			//	description:
+			//		Simple test of the isItem function of the store
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(store.isItem(item));
+				t.assertTrue(!store.isItem({}));
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: isItem() multistore",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the isItem function of the store
+			//		to verify two different store instances do not accept
+			//		items from each other.
+			//	description:
+			//		Simple test of the isItem function of the store
+			//		to verify two different store instances do not accept
+			//		items from each other.
+
+			// Two different instances, even  if they read from the same URL 
+			// should not accept items between each other!
+			var store1 = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			var store2 = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function onItem1(item1){
+				t.assertTrue(item1 !== null);
+				
+				function onItem2(item2){
+					t.assertTrue(item1 !== null);
+					t.assertTrue(item2 !== null);
+					t.assertTrue(store1.isItem(item1));
+					t.assertTrue(store2.isItem(item2));
+					t.assertTrue(!store1.isItem(item2));
+					t.assertTrue(!store2.isItem(item1));
+					d.callback(true);
+				}
+				store2.fetchItemByIdentity({identity: "sv", onItem: onItem2, onError: onError});
+
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store1.fetchItemByIdentity({identity: "sv", onItem: onItem1, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: hasAttribute()",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the hasAttribute function of the store
+			//	description:
+			//		Simple test of the hasAttribute function of the store
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				try{
+					t.assertTrue(item !== null);
+
+					t.assertTrue(store.hasAttribute(item, "abbr"));
+					t.assertTrue(!store.hasAttribute(item, "abbr_not"));
+
+					//Test that null attributes throw an exception
+					var passed = false;
+					try{
+						store.hasAttribute(item, null);
+					}catch (e){
+						passed = true;
+					}
+					t.assertTrue(passed);
+					d.callback(true);
+				}catch(e){
+					d.errback(e);
+				}
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: containsValue()",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the containsValue function of the store
+			//	description:
+			//		Simple test of the containsValue function of the store
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(store.containsValue(item, "abbr", "sv"));
+				t.assertTrue(!store.containsValue(item, "abbr", "sv1"));
+				t.assertTrue(!store.containsValue(item, "abbr", null));
+
+				//Test that null attributes throw an exception
+				var passed = false;
+				try{
+					store.containsValue(item, null, "foo");
+				}catch (e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: getAttributes()",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the getAttributes function of the store
+			//	description:
+			//		Simple test of the getAttributes function of the store
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(store.isItem(item));
+
+				var attributes = store.getAttributes(item);
+				t.assertEqual(attributes.length, 3);
+				for(var i = 0; i < attributes.length; i++){
+					t.assertTrue((attributes[i] === "name" || attributes[i] === "abbr" || attributes[i] === "capital"));
+				}
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: getFeatures()",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var features = store.getFeatures();
+			t.assertTrue(features["dojo.data.api.Read"] != null);
+			t.assertTrue(features["dojo.data.api.Identity"] != null);
+		}
+	},
+	{
+		name: "Read API: fetch() patternMatch0",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test pattern matching of everything starting with lowercase e
+			//	description:
+			//		Function to test pattern matching of everything starting with lowercase e
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+
+			var d = new doh.Deferred();
+			function completed(items, request) {
+				t.assertEqual(items.length, 5);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "abbr");
+					if(!(value === "ec" || value === "eg" || value === "er" || value === "ee" || value === "et")){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected abbreviation found, match failure."));
+				}
+			}
+			function error(error, request) {
+				t.assertTrue(false);
+				d.errback(error);
+			}
+			store.fetch({query: {abbr: "e*"}, onComplete: completed, onError: error});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() patternMatch1",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test pattern matching of everything with $ in it.
+			//	description:
+			//		Function to test pattern matching of everything with $ in it.
+
+			var store = new datastore({data: { identifier: "uniqueId", 
+											  items: [ {uniqueId: 1, value:"foo*bar"},
+												   {uniqueId: 2, value:"bar*foo"}, 
+												   {uniqueId: 3, value:"boomBam"},
+												   {uniqueId: 4, value:"bit$Bite"},
+												   {uniqueId: 5, value:"ouagadogou"},
+												   {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+												   {uniqueId: 7, value:"squawl"},
+												   {uniqueId: 8, value:"seaweed"},
+												   {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+												 ]
+										}
+								 });
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.assertEqual(items.length, 2);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(value === "bit$Bite" || value === "jfq4@#!$!@Rf14r14i5u")){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+				}
+			}
+			function error(error, request){
+				t.assertTrue(false);
+				d.errback(error);
+			}
+			store.fetch({query: {value: "*$*"}, onComplete: completed, onError: error});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() patternMatch2",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test exact pattern match
+			//	description:
+			//		Function to test exact pattern match
+
+			var store = new datastore({data: { identifier: "uniqueId", 
+											  items: [ {uniqueId: 1, value:"foo*bar"},
+												   {uniqueId: 2, value:"bar*foo"}, 
+												   {uniqueId: 3, value:"boomBam"},
+												   {uniqueId: 4, value:"bit$Bite"},
+												   {uniqueId: 5, value:"ouagadogou"},
+												   {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+												   {uniqueId: 7, value:"squawl"},
+												   {uniqueId: 8, value:"seaweed"},
+												   {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+												 ]
+										}
+								 });
+
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.assertEqual(items.length, 1);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(value === "bar*foo")){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected abbreviation found, match failure."));
+				}
+			}
+			function error(error, request){
+				t.assertTrue(false);
+				d.errback(error);
+			}
+			store.fetch({query: {value: "bar\*foo"}, onComplete: completed, onError: error});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() patternMatch_caseSensitive",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test pattern matching of a pattern case-sensitively
+			//	description:
+			//		Function to test pattern matching of a pattern case-sensitively
+
+			var store = new datastore({data: { identifier: "uniqueId", 
+											  items: [ {uniqueId: 1, value:"foo*bar"},
+												   {uniqueId: 2, value:"bar*foo"}, 
+												   {uniqueId: 3, value:"BAR*foo"},
+												   {uniqueId: 4, value:"BARBananafoo"}
+												 ]
+										}
+								 });
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.assertEqual(1, items.length);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(value === "bar*foo")){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+				}
+			}
+			function error(error, request){
+				t.assertTrue(false);
+				d.errback(error);
+			}
+			store.fetch({query: {value: "bar\\*foo"}, queryOptions: {ignoreCase: false} , onComplete: completed, onError: error});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() patternMatch_caseInsensitive",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test pattern matching of a pattern case-insensitively
+			//	description:
+			//		Function to test pattern matching of a pattern case-insensitively
+
+			var store = new datastore({data: { identifier: "uniqueId", 
+											  items: [ {uniqueId: 1, value:"foo*bar"},
+												   {uniqueId: 2, value:"bar*foo"}, 
+												   {uniqueId: 3, value:"BAR*foo"},
+												   {uniqueId: 4, value:"BARBananafoo"}
+												 ]
+										}
+								 });
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.assertEqual(items.length, 2);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(value === "BAR*foo" || value === "bar*foo")){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+				}
+			}
+			function error(error, request){
+				t.assertTrue(false);
+				d.errback(error);
+			}
+			store.fetch({query: {value: "bar\\*foo"}, queryOptions: {ignoreCase: true}, onComplete: completed, onError: error});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() sortNumeric",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test sorting numerically.
+			//	description:
+			//		Function to test sorting numerically.
+			
+			var store = new datastore({data: { identifier: "uniqueId", 
+											  items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+												   {uniqueId: 1, value:"ba|r*foo"}, 
+												   {uniqueId: 2, value:"boomBam"},
+												   {uniqueId: 3, value:"bit$Bite"},
+												   {uniqueId: 4, value:"ouagadogou"},
+												   {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+												   {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+												   {uniqueId: 7, value:"squawl"},
+												   {uniqueId: 9, value:"seaweed"},
+												   {uniqueId: 10, value:"zulu"},
+												   {uniqueId: 8, value:"seaweed"}
+												 ]
+										}
+								 });
+
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.assertEqual(items.length, 11);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(store.getValue(items[i], "uniqueId") === i)){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected sorting order found, sort failure."));
+				}
+			}
+
+			function error(error, request){
+				t.assertTrue(false);
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "uniqueId"}];
+			store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() sortNumericDescending",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test sorting numerically.
+			//	description:
+			//		Function to test sorting numerically.
+
+			var store = new datastore({data: { identifier: "uniqueId", 
+											  items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+												   {uniqueId: 1, value:"ba|r*foo"}, 
+												   {uniqueId: 2, value:"boomBam"},
+												   {uniqueId: 3, value:"bit$Bite"},
+												   {uniqueId: 4, value:"ouagadogou"},
+												   {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+												   {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+												   {uniqueId: 7, value:"squawl"},
+												   {uniqueId: 9, value:"seaweed"},
+												   {uniqueId: 10, value:"zulu"},
+												   {uniqueId: 8, value:"seaweed"}
+												 ]
+										}
+								 });
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.assertEqual(items.length, 11);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!((items.length - (store.getValue(items[i], "uniqueId") + 1)) === i)){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected sorting order found, sort failure."));
+				}
+			}
+
+			function error(error, request){
+				t.assertTrue(false);
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "uniqueId", descending: true}];
+			store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() sortNumericWithCount",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test sorting numerically in descending order, returning only a specified number of them.
+			//	description:
+			//		Function to test sorting numerically in descending order, returning only a specified number of them.
+		
+			var store = new datastore({data: { identifier: "uniqueId", 
+											 items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+												  {uniqueId: 1, value:"ba|r*foo"}, 
+												  {uniqueId: 2, value:"boomBam"},
+												  {uniqueId: 3, value:"bit$Bite"},
+												  {uniqueId: 4, value:"ouagadogou"},
+												  {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+												  {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+												  {uniqueId: 7, value:"squawl"},
+												  {uniqueId: 9, value:"seaweed"},
+												  {uniqueId: 10, value:"zulu"},
+												  {uniqueId: 8, value:"seaweed"}
+												]
+									   }
+								});
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.assertEqual(items.length, 5);
+				var itemId = 10;
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(store.getValue(items[i], "uniqueId") === itemId)){
+						passed=false;
+						break;
+					}
+					itemId--; // Decrement the item id.  We are descending sorted, so it should go 10, 9, 8, etc.
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected sorting order found, sort failure."));
+				}
+			}
+		
+			function error(error, request){
+				t.assertTrue(false);
+				d.errback(error);
+			}
+		
+			var sortAttributes = [{attribute: "uniqueId", descending: true}];
+			store.fetch({onComplete: completed, onError: error, sort: sortAttributes, count: 5});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() sortAlphabetic",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering.
+			//	description:
+			//		Function to test sorting alphabetic ordering.
+		
+			var store = new datastore({data: { identifier: "uniqueId", 
+											 items: [ {uniqueId: 0, value:"abc"},
+												  {uniqueId: 1, value:"bca"}, 
+												  {uniqueId: 2, value:"abcd"},
+												  {uniqueId: 3, value:"abcdefg"},
+												  {uniqueId: 4, value:"lmnop"},
+												  {uniqueId: 5, value:"foghorn"},
+												  {uniqueId: 6, value:"qberty"},
+												  {uniqueId: 7, value:"qwerty"},
+												  {uniqueId: 8, value:""},
+												  {uniqueId: 9, value:"seaweed"},
+												  {uniqueId: 10, value:"123abc"}
+		
+												]
+									   }
+								});
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ 	"",
+										"123abc",
+										"abc",
+										"abcd",
+										"abcdefg",
+										"bca",
+										"foghorn",
+										"lmnop",
+										"qberty",
+										"qwerty",
+										"seaweed"
+					];
+				t.assertEqual(items.length, 11);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(store.getValue(items[i], "value") === orderedArray[i])){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected sorting order found, sort failure."));
+				}
+			}
+		
+			function error(error, request) {
+				t.assertTrue(false);
+				d.errback(error);
+			}
+		
+			var sortAttributes = [{attribute: "value"}];
+			store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() sortAlphabeticDescending",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering in descending mode.
+			//	description:
+			//		Function to test sorting alphabetic ordering in descending mode.
+		
+			var store = new datastore({data: { identifier: "uniqueId", 
+											 items: [ {uniqueId: 0, value:"abc"},
+												  {uniqueId: 1, value:"bca"}, 
+												  {uniqueId: 2, value:"abcd"},
+												  {uniqueId: 3, value:"abcdefg"},
+												  {uniqueId: 4, value:"lmnop"},
+												  {uniqueId: 5, value:"foghorn"},
+												  {uniqueId: 6, value:"qberty"},
+												  {uniqueId: 7, value:"qwerty"},
+												  {uniqueId: 8, value:""},
+												  {uniqueId: 9, value:"seaweed"},
+												  {uniqueId: 10, value:"123abc"}
+		
+												]
+									   }
+								});
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ 	"",
+										"123abc",
+										"abc",
+										"abcd",
+										"abcdefg",
+										"bca",
+										"foghorn",
+										"lmnop",
+										"qberty",
+										"qwerty",
+										"seaweed"
+					];
+				orderedArray = orderedArray.reverse();
+				t.assertEqual(items.length, 11);
+
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(store.getValue(items[i], "value") === orderedArray[i])){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected sorting order found, sort failure."));
+				}
+			}
+		
+			function error(error, request) {
+				t.assertTrue(false);
+				d.errback(error);
+			}
+		
+			var sortAttributes = [{attribute: "value", descending: true}];
+			store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() sortDate",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test sorting date.
+			//	description:
+			//		Function to test sorting date.
+		
+			var store = new datastore({data: { identifier: "uniqueId", 
+											 items: [ {uniqueId: 0, value: new Date(0)},
+												  {uniqueId: 1, value: new Date(100)}, 
+												  {uniqueId: 2, value:new Date(1000)},
+												  {uniqueId: 3, value:new Date(2000)},
+												  {uniqueId: 4, value:new Date(3000)},
+												  {uniqueId: 5, value:new Date(4000)},
+												  {uniqueId: 6, value:new Date(5000)},
+												  {uniqueId: 7, value:new Date(6000)},
+												  {uniqueId: 8, value:new Date(7000)},
+												  {uniqueId: 9, value:new Date(8000)},
+												  {uniqueId: 10, value:new Date(9000)}
+		
+												]
+									   }
+								});
+			
+			var d = new doh.Deferred();
+			function completed(items,request){
+				var orderedArray =	[0,100,1000,2000,3000,4000,5000,6000,7000,8000,9000];
+				t.assertEqual(items.length, 11);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(store.getValue(items[i], "value").getTime() === orderedArray[i])){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected sorting order found, sort failure."));
+				}
+			}
+		
+			function error(error, request){
+				t.assertTrue(false);
+				d.errback(error);
+			}
+		
+			var sortAttributes = [{attribute: "value"}];
+			store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() sortDateDescending",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test sorting date in descending order.
+			//	description:
+			//		Function to test sorting date in descending order.
+		
+			var store = new datastore({data: { identifier: "uniqueId", 
+											 items: [ {uniqueId: 0, value: new Date(0)},
+												  {uniqueId: 1, value: new Date(100)}, 
+												  {uniqueId: 2, value:new Date(1000)},
+												  {uniqueId: 3, value:new Date(2000)},
+												  {uniqueId: 4, value:new Date(3000)},
+												  {uniqueId: 5, value:new Date(4000)},
+												  {uniqueId: 6, value:new Date(5000)},
+												  {uniqueId: 7, value:new Date(6000)},
+												  {uniqueId: 8, value:new Date(7000)},
+												  {uniqueId: 9, value:new Date(8000)},
+												  {uniqueId: 10, value:new Date(9000)}
+		
+												]
+									   }
+								});
+		
+			var d = new doh.Deferred();
+			function completed(items,request){
+				var orderedArray =	[0,100,1000,2000,3000,4000,5000,6000,7000,8000,9000];
+				orderedArray = orderedArray.reverse();
+				t.assertEqual(items.length, 11);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(store.getValue(items[i], "value").getTime() === orderedArray[i])){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected sorting order found, sort failure."));
+				}
+			}
+		
+			function error(error, request){
+				t.assertTrue(false);
+				d.errback(error);
+			}
+		
+			var sortAttributes = [{attribute: "value", descending: true}];
+			store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() sortMultiple",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test sorting on multiple attributes.
+			//	description:
+			//		Function to test sorting on multiple attributes.
+			
+			var store = new datastore({data: { identifier: "uniqueId", 
+											 items: [ {uniqueId: 1, value:"fo|o*b.ar"},
+												  {uniqueId: 2, value:"ba|r*foo"}, 
+												  {uniqueId: 3, value:"boomBam"},
+												  {uniqueId: 4, value:"bit$Bite"},
+												  {uniqueId: 5, value:"ouagadogou"},
+												  {uniqueId: 6, value:"jfq4@#!$!@|f1.$4r14i5u"},
+												  {uniqueId: 7, value:"BaB{aMa|SaRa***F}oo"},
+												  {uniqueId: 8, value:"squawl"},
+												  {uniqueId: 10, value:"seaweed"},
+												  {uniqueId: 12, value:"seaweed"},
+												  {uniqueId: 11, value:"zulu"},
+												  {uniqueId: 9, value:"seaweed"}
+												]
+									   }
+								});
+		
+			var d = new doh.Deferred();
+			function completed(items, request){
+				var orderedArray0 = [7,2,4,3,1,6,5,12,10,9,8,11];
+				var orderedArray1 = [	"BaB{aMa|SaRa***F}oo",
+										"ba|r*foo",
+										"bit$Bite",
+										"boomBam",
+										"fo|o*b.ar",
+										"jfq4@#!$!@|f1.$4r14i5u",
+										"ouagadogou",
+										"seaweed",
+										"seaweed",
+										"seaweed",
+										"squawl",
+										"zulu"
+									];
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(	(store.getValue(items[i], "uniqueId") === orderedArray0[i])&&
+							(store.getValue(items[i], "value") === orderedArray1[i]))
+						){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected sorting order found, sort failure."));
+				}
+			}
+		
+			function error(error, request){
+				t.assertTrue(false);
+				d.errback(error);
+			}
+		
+			var sortAttributes = [{ attribute: "value"}, { attribute: "uniqueId", descending: true}];
+			store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() sortMultipleSpecialComparator",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test sorting on multiple attributes with a custom comparator.
+			//	description:
+			//		Function to test sorting on multiple attributes with a custom comparator.
+
+			var store = new datastore({data: { identifier: "uniqueId", 
+											 items: [ {uniqueId: 1, status:"CLOSED"},
+												  {uniqueId: 2,  status:"OPEN"}, 
+												  {uniqueId: 3,  status:"PENDING"},
+												  {uniqueId: 4,  status:"BLOCKED"},
+												  {uniqueId: 5,  status:"CLOSED"},
+												  {uniqueId: 6,  status:"OPEN"},
+												  {uniqueId: 7,  status:"PENDING"},
+												  {uniqueId: 8,  status:"PENDING"},
+												  {uniqueId: 10, status:"BLOCKED"},
+												  {uniqueId: 12, status:"BLOCKED"},
+												  {uniqueId: 11, status:"OPEN"},
+												  {uniqueId: 9,  status:"CLOSED"}
+												]
+									   }
+								});
+		
+		
+			store.comparatorMap = {};
+			store.comparatorMap["status"] = function(a,b) { 
+				var ret = 0;
+				// We want to map these by what the priority of these items are, not by alphabetical.
+				// So, custom comparator.
+				var enumMap = { OPEN: 3, BLOCKED: 2, PENDING: 1, CLOSED: 0};
+				if (enumMap[a] > enumMap[b]) {
+					ret = 1;
+				}
+				if (enumMap[a] < enumMap[b]) {
+					ret = -1;
+				}
+				return ret;
+			};
+		
+			var sortAttributes = [{attribute: "status", descending: true}, { attribute: "uniqueId", descending: true}];
+		
+			var d = new doh.Deferred();
+			function completed(items, findResult){
+				var orderedArray = [11,6,2,12,10,4,8,7,3,9,5,1];
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					var value = store.getValue(items[i], "value");
+					if(!(store.getValue(items[i], "uniqueId") === orderedArray[i])){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected sorting order found, sort failure."));
+				}
+			}
+		
+			function error(errData, request){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+			return d;
+		}
+	},
+	{
+		name: "Read API: fetch() sortAlphabeticWithUndefined",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering.
+			//	description:
+			//		Function to test sorting alphabetic ordering.
+		
+			var store = new datastore({data: { identifier: "uniqueId", 
+											 items: [ {uniqueId: 0, value:"abc"},
+												  {uniqueId: 1, value:"bca"}, 
+												  {uniqueId: 2, value:"abcd"},
+												  {uniqueId: 3, value:"abcdefg"},
+												  {uniqueId: 4, value:"lmnop"},
+												  {uniqueId: 5, value:"foghorn"},
+												  {uniqueId: 6, value:"qberty"},
+												  {uniqueId: 7, value:"qwerty"},
+												  {uniqueId: 8 },  //Deliberate undefined value
+												  {uniqueId: 9, value:"seaweed"},
+												  {uniqueId: 10, value:"123abc"}
+		
+												]
+									   }
+								});
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [10,0,2,3,1,5,4,6,7,9,8];
+				t.assertEqual(items.length, 11);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					if(!(store.getValue(items[i], "uniqueId") === orderedArray[i])){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				if (passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected sorting order found, sort failure."));
+				}
+			}
+		
+			function error(error, request) {
+				t.assertTrue(false);
+				d.errback(error);
+			}
+		
+			var sortAttributes = [{attribute: "value"}];
+			store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+			return d;
+		}
+	},
+	{
+		name: "Read API: errorCondition_idCollision_inMemory",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the errors thrown when there is an id collision in the data.
+			//		Added because of tracker: #2546
+			//	description:
+			//		Simple test of the errors thrown when there is an id collision in the data.
+			//		Added because of tracker: #2546
+
+			var store = new datastore({	data: { identifier: "uniqueId", 
+																items: [{uniqueId: 12345, value:"foo"},
+																		{uniqueId: 123456, value:"bar"}, 
+																		{uniqueId: 12345, value:"boom"},
+																		{uniqueId: 123457, value:"bit"}
+																	]
+																}
+															});
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				//This is bad if this fires, this case should fail and not call onComplete.
+				t.assertTrue(false);
+				d.callback(false);
+			}
+		
+			function reportError(errData, request){
+				//This is good if this fires, it is expected.
+				t.assertTrue(true);
+				d.callback(true);
+			}
+			store.fetch({onComplete: onComplete, onError: reportError});
+			return d;
+		}
+	},
+	{
+		name: "Read API: errorCondition_idCollision_xhr",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test of the errors thrown when there is an id collision in the data.
+			//		Added because of tracker: #2546
+			//	description:
+			//		Simple test of the errors thrown when there is an id collision in the data.
+			//		Added because of tracker: #2546
+
+			if(dojo.isBrowser){
+				var store = new datastore({url: dojo.moduleUrl("tests", "data/countries_idcollision.json").toString() });
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					//This is bad if this fires, this case should fail and not call onComplete.
+					t.assertTrue(false);
+					d.callback(false);
+				}
+
+				function reportError(errData, request){
+					//This is good if this fires, it is expected.
+					t.assertTrue(true);
+					d.callback(true);
+				}
+				store.fetch({onComplete: onComplete, onError: reportError});
+				return d;
+			}
+		}
+	},
+	{
+		name: "Read API: Date_datatype",
+ 		runTest: function(datastore, t){
+			//var store = new datastore(tests.data.readOnlyItemFileTestTemplates.testFile["countries_withDates"]);
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries_withDates"));
+			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var independenceDate = store.getValue(item, "independence");
+				t.assertTrue(independenceDate instanceof Date);
+				//Check to see if the value was deserialized properly.  Since the store stores in UTC/GMT, it 
+				//should also be compared in the UTC/GMT mode
+				t.assertTrue(dojo.date.stamp.toISOString(independenceDate, {zulu:true}) === "1993-05-24T00:00:00Z");
+				d.callback(true);
+			}
+			function onError(errData){
+				t.assertTrue(false);
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity:"er", onItem:onItem, onError:onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: custom_datatype_Color_SimpleMapping",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test using literal values with custom datatypes
+			var dataset = {
+				identifier:'name',
+				items: [
+					{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+					{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+				]
+			};
+			var store = new datastore({
+					data:dataset,
+					typeMap:{'Color': dojo.Color}
+			});
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var beaker = item;
+				var hairColor = store.getValue(beaker, "hairColor");
+				t.assertTrue(hairColor instanceof dojo.Color);
+				t.assertTrue(hairColor.toHex() == "#ff0000");
+				d.callback(true);
+			}
+			function onError(errData){
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity:"Beaker", onItem:onItem, onError:onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: custom_datatype_Color_GeneralMapping",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test using literal values with custom datatypes
+			var dataset = {
+				identifier:'name',
+				items: [
+					{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+					{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+				]
+			};
+			var store = new datastore({
+					data:dataset,
+					typeMap:{'Color': 	{	
+											type: dojo.Color,
+											deserialize: function(value){
+												return new dojo.Color(value);
+											}
+										}
+							}
+			});
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var beaker = item;
+				var hairColor = store.getValue(beaker, "hairColor");
+				t.assertTrue(hairColor instanceof dojo.Color);
+				t.assertTrue(hairColor.toHex() == "#ff0000");
+				d.callback(true);
+			}
+			function onError(errData){
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity:"Beaker", onItem:onItem, onError:onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: custom_datatype_CustomObject 0 (False) value",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test type mapping and _values that are false-like
+			var dataset = {
+				identifier:'name',
+				items: [
+					{ name:'Bob', species:'human', age: {_type:'tests.data.Wrapper', _value:0} },
+					{ name:'Nancy', species:'human', age: {_type:'tests.data.Wrapper', _value:32} }
+				]
+			};
+			var store = new datastore({
+					data:dataset,
+					typeMap:{'tests.data.Wrapper': 	{	
+											type: tests.data.Wrapper,
+											deserialize: function(value){
+												return new tests.data.Wrapper(value);
+											}
+										}
+							}
+			});
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var bob = item;
+				var age = store.getValue(item, "age");
+				t.assertTrue(age instanceof tests.data.Wrapper);
+				t.assertTrue(age.toString() == "WRAPPER: [0]");
+				d.callback(true);
+			}
+			function onError(errData){
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity:"Bob", onItem:onItem, onError:onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: custom_datatype_CustomObject Boolean False values",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test type mapping and _values that are false-like
+			var dataset = {
+				identifier:'name',
+				items: [
+					{ name:'Bob', isHuman: {_type:'tests.data.Wrapper', _value:false} },
+					{ name:'Nancy', isHuman: {_type:'tests.data.Wrapper', _value: true} }
+				]
+			};
+			var store = new datastore({
+					data:dataset,
+					typeMap:{'tests.data.Wrapper': 	{	
+											type: tests.data.Wrapper,
+											deserialize: function(value){
+												return new tests.data.Wrapper(value);
+											}
+										}
+							}
+			});
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var bob = item;
+				var isHuman = store.getValue(item, "isHuman");
+				t.assertTrue(isHuman instanceof tests.data.Wrapper);
+				t.assertTrue(isHuman.toString() == "WRAPPER: [false]");
+				d.callback(true);
+			}
+			function onError(errData){
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity:"Bob", onItem:onItem, onError:onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: custom_datatype_CustomObject Empty String values",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test type mapping and _values that are false-like
+			var dataset = {
+				identifier:'name',
+				items: [
+					{ name:'Bob', lastName: {_type:'tests.data.Wrapper', _value:""} },
+					{ name:'Nancy', lastName: {_type:'tests.data.Wrapper', _value: "Doe"} }
+				]
+			};
+			var store = new datastore({
+					data:dataset,
+					typeMap:{'tests.data.Wrapper': 	{	
+											type: tests.data.Wrapper,
+											deserialize: function(value){
+												return new tests.data.Wrapper(value);
+											}
+										}
+							}
+			});
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var bob = item;
+				var lastName = store.getValue(item, "lastName");
+				t.assertTrue(lastName instanceof tests.data.Wrapper);
+				t.assertTrue(lastName.toString() == "WRAPPER: []");
+				d.callback(true);
+			}
+			function onError(errData){
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity:"Bob", onItem:onItem, onError:onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: custom_datatype_CustomObject explicit null values",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test type mapping and _values that are false-like
+			var dataset = {
+				identifier:'name',
+				items: [
+					{ name:'Bob', lastName: {_type:'tests.data.Wrapper', _value:null} },
+					{ name:'Nancy', lastName: {_type:'tests.data.Wrapper', _value: "Doe"} }
+				]
+			};
+			var store = new datastore({
+					data:dataset,
+					typeMap:{'tests.data.Wrapper': 	{	
+											type: tests.data.Wrapper,
+											deserialize: function(value){
+												return new tests.data.Wrapper(value);
+											}
+										}
+							}
+			});
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var bob = item;
+				var lastName = store.getValue(item, "lastName");
+				t.assertTrue(lastName instanceof tests.data.Wrapper);
+				t.assertTrue(lastName.toString() == "WRAPPER: [null]");
+				d.callback(true);
+			}
+			function onError(errData){
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity:"Bob", onItem:onItem, onError:onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: custom_datatype_CustomObject explicit undefined value",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test type mapping and _values that are false-like
+			var dataset = {
+				identifier:'name',
+				items: [
+					{ name:'Bob', lastName: {_type:'tests.data.Wrapper', _value: undefined} },
+					{ name:'Nancy', lastName: {_type:'tests.data.Wrapper', _value: "Doe"} }
+				]
+			};
+			var store = new datastore({
+					data:dataset,
+					typeMap:{'tests.data.Wrapper': 	{	
+											type: tests.data.Wrapper,
+											deserialize: function(value){
+												return new tests.data.Wrapper(value);
+											}
+										}
+							}
+			});
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var bob = item;
+				var lastName = store.getValue(item, "lastName");
+				t.assertTrue(lastName instanceof tests.data.Wrapper);
+				t.assertTrue(lastName.toString() == "WRAPPER: [undefined]");
+				d.callback(true);
+			}
+			function onError(errData){
+				d.errback(errData);
+			}
+			store.fetchItemByIdentity({identity:"Bob", onItem:onItem, onError:onError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: hierarchical_data",
+ 		runTest: function(datastore, t){
+			//var store = new datastore(tests.data.readOnlyItemFileTestTemplates.testFile["geography_hierarchy_small"]);
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var northAmerica = items[0];
+				var canada = store.getValue(northAmerica, "countries");
+				var toronto = store.getValue(canada, "cities");
+				t.assertEqual(store.getValue(canada, "name"), "Canada");
+				t.assertEqual(store.getValue(toronto, "name"), "Toronto");
+				d.callback(true);
+			}
+			function onError(errData){
+				d.errback(errData);
+			}
+			store.fetch({
+				query: {name: "North America"},
+				onComplete: onComplete,
+				onError: onError
+			});
+			
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: close (clearOnClose: true)",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+			if (dojo.isBrowser) {
+				var params = tests.data.readOnlyItemFileTestTemplates.getTestData("countries");
+				params.clearOnClose = true;
+				params.urlPreventCache = true;
+				var store = new datastore(params);
+
+				var d = new doh.Deferred();
+				function onItem(item){
+					var error = null;
+					try {
+						t.assertTrue(item !== null);
+						var ec = item;
+						var val = store.getValue(ec, "name");
+						t.assertEqual("Ecuador", val);
+
+						store.close();
+						//Check some internals here.  Do not normally access these!
+						t.assertTrue(store._arrayOfAllItems.length === 0);
+						t.assertTrue(store._loadFinished === false);
+					}catch (e){
+						error = e;
+					}
+					if (error) {
+						d.errback(error);
+					}else{
+						d.callback(true);
+					}
+				}
+				function onError(errData){
+					d.errback(errData);
+				}
+				store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		}
+	},
+	{
+		name: "Read API: close (clearOnClose: true, reset url.)",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+			if (dojo.isBrowser) {
+				var params = tests.data.readOnlyItemFileTestTemplates.getTestData("countries");
+				params.clearOnClose = true;
+				params.urlPreventCache = true;
+				var store = new datastore(params);
+
+				var d = new doh.Deferred();
+				function onItem(item){
+					var error = null;
+					try {
+						t.assertTrue(item !== null);
+						var ec = item;
+						var val = store.getValue(ec, "name");
+						t.assertEqual("Ecuador", val);
+
+						store.close();
+						//Check some internals here.  Do not normally access these!
+						t.assertTrue(store._arrayOfAllItems.length === 0);
+						t.assertTrue(store._loadFinished === false);
+						
+						store.url = dojo.moduleUrl("tests", "data/countries_withNull.json").toString();
+						function onItem2 (item){
+							var err;
+							try{
+								t.assertTrue(item !== null);
+                                var val = store.getValue(item, "name");
+								t.assertEqual(null, val);
+							}catch(e){
+								err = e;
+							}
+							if(err){
+								d.errback(err);
+							}else{
+								d.callback(true);
+							}
+						}
+						store.fetchItemByIdentity({identity:"ec", onItem:onItem2, onError:onError});
+					}catch (e){
+						error = e;
+					}
+					if (error) {
+						d.errback(error);
+					}
+				}
+				function onError(errData){
+					d.errback(errData);
+				}
+				store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		}
+	},
+	{
+		name: "Read API: fetch, close (clearOnClose: true, reset url.)",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+			if (dojo.isBrowser) {
+				var params = tests.data.readOnlyItemFileTestTemplates.getTestData("countries");
+				params.clearOnClose = true;
+				params.urlPreventCache = true;
+				var store = new datastore(params);
+
+				var d = new doh.Deferred();
+				function onItem(item){
+					var error = null;
+					try {
+						t.assertTrue(item !== null);
+						var ec = item;
+						var val = store.getValue(ec, "name");
+						t.assertEqual("Ecuador", val);
+
+						store.close();
+						//Check some internals here.  Do not normally access these!
+						t.assertTrue(store._arrayOfAllItems.length === 0);
+						t.assertTrue(store._loadFinished === false);
+						
+						store.url = dojo.moduleUrl("tests", "data/countries_withNull.json").toString();
+						function onComplete (items){
+                            var err;
+							try{
+								t.assertEqual(1, items.length);
+								var item = items[0];
+								t.assertTrue(item !== null);
+                                var val = store.getValue(item, "name");
+								t.assertEqual(null, val);
+							}catch(e){
+								err = e;
+							}
+							if(err){
+								d.errback(err);
+							}else{
+								d.callback(true);
+							}
+						}
+						store.fetch({query: {abbr:"ec"}, onComplete:onComplete, onError:onError});
+					}catch (e){
+						error = e;
+					}
+					if (error) {
+						d.errback(error);
+					}
+				}
+				function onError(errData){
+					d.errback(errData);
+				}
+				store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		}
+	},
+	{
+		name: "Read API: close (clearOnClose: true, reset _jsonFileUrl.)",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+			if (dojo.isBrowser) {
+				var params = tests.data.readOnlyItemFileTestTemplates.getTestData("countries");
+				params.clearOnClose = true;
+				params.urlPreventCache = true;
+				var store = new datastore(params);
+
+				var d = new doh.Deferred();
+				function onItem(item){
+					var error = null;
+					try {
+						t.assertTrue(item !== null);
+						var ec = item;
+						var val = store.getValue(ec, "name");
+						t.assertEqual("Ecuador", val);
+
+						store.close();
+						//Check some internals here.  Do not normally access these!
+						t.assertTrue(store._arrayOfAllItems.length === 0);
+						t.assertTrue(store._loadFinished === false);
+						
+						store._jsonFileUrl = dojo.moduleUrl("tests", "data/countries_withNull.json").toString();
+						function onItem2 (item){
+							var err;
+							try{
+								t.assertTrue(item !== null);
+                                var val = store.getValue(item, "name");
+								t.assertEqual(null, val);
+							}catch(e){
+								err = e;
+							}
+							if(err){
+								d.errback(err);
+							}else{
+								d.callback(true);
+							}
+						}
+						store.fetchItemByIdentity({identity:"ec", onItem:onItem2, onError:onError});
+					}catch (e){
+						error = e;
+					}
+					if (error) {
+						d.errback(error);
+					}
+				}
+				function onError(errData){
+					d.errback(errData);
+				}
+				store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		}
+	},
+	{
+		name: "Read API: close (clearOnClose: false)",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+			if (dojo.isBrowser) {
+				var params = tests.data.readOnlyItemFileTestTemplates.getTestData("countries");
+				params.urlPreventCache = true;
+				var store = new datastore(params);
+
+				var d = new doh.Deferred();
+				function onItem(item){
+					var error = null;
+					try {
+						t.assertTrue(item !== null);
+						var ec = item;
+						var val = store.getValue(ec, "name");
+						t.assertEqual("Ecuador", val);
+
+						store.close();
+						//Check some internals here.  Do not normally access these!
+						t.assertTrue(store._arrayOfAllItems.length !== 0);
+						t.assertTrue(store._loadFinished === true);
+					}catch (e){
+						error = e;
+					}
+					if (error) {
+						d.errback(error);
+					}else{
+						d.callback(true);
+					}
+				}
+				function onError(errData){
+					d.errback(errData);
+				}
+				store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		}
+	},
+	{
+		name: "Read API: close (clearOnClose: true, reset data.)",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Function to test that clear on close and reset of data works.
+			//	description:
+			//		Function to test that clear on close and reset of data works.
+			var store = new datastore({data: { identifier: "uniqueId", 
+											  items: [ {uniqueId: 1, value:"foo*bar"},
+												   {uniqueId: 2, value:"bar*foo"}, 
+												   {uniqueId: 3, value:"boomBam"},
+												   {uniqueId: 4, value:"bit$Bite"},
+												   {uniqueId: 5, value:"ouagadogou"},
+												   {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+												   {uniqueId: 7, value:"squawl"},
+												   {uniqueId: 8, value:"seaweed"},
+												   {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+												 ]
+										}
+								 });
+
+			var d = new doh.Deferred();
+			var firstComplete = function(items, request){
+				t.assertEqual(items.length, 1);
+				var firstItem = items[0];
+
+				//Set the store clearing options and the new data
+				store.clearOnClose = true;
+				store.data = { identifier: "uniqueId", 
+					items: [ {uniqueId: 1, value:"foo*bar"},
+						{uniqueId: 2, value:"bar*foo"}, 
+						{uniqueId: 3, value:"boomBam"},
+						{uniqueId: 4, value:"bit$Bite"},
+						{uniqueId: 5, value:"ouagadogou"},
+						{uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+						{uniqueId: 7, value:"squawl"},
+						{uniqueId: 8, value:"seaweed"},
+						{uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+					]
+				};
+                store.close();
+
+				//Do the next fetch and verify that the next item you get is not
+				//a reference to the same item (data cleared and reloaded.
+				var secondComplete = function(items, request){
+					try{
+						t.assertEqual(items.length, 1);
+						var secondItem = items[0];
+						t.assertTrue(firstItem != null);
+						t.assertTrue(secondItem != null);
+						t.assertTrue(firstItem != secondItem);
+						d.callback(true);
+					}catch(e){
+						d.errback(e);
+					}
+				}
+				store.fetch({query: {value: "bar\*foo"}, onComplete: secondComplete, onError: error});
+			}
+			function error(error, request){
+				t.assertTrue(false);
+				d.errback(error);
+			}
+			store.fetch({query: {value: "bar\*foo"}, onComplete: firstComplete, onError: error});
+			return d;
+		}
+	},
+	{
+		name: "Identity API: no_identifier_specified",
+ 		runTest: function(datastore, t){
+			var arrayOfItems = [
+				{name:"Kermit", color:"green"},
+				{name:"Miss Piggy", likes:"Kermit"}, 
+				{name:"Beaker", hairColor:"red"}
+			];
+			var store = new datastore({data:{items:arrayOfItems}});
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				var features = store.getFeatures();
+				var hasIdentityFeature = Boolean(features['dojo.data.api.Identity']);
+				t.assertTrue(hasIdentityFeature);
+				for(var i = 0; i < items.length; ++i){
+					var item = items[i];
+					var identifier = store.getIdentityAttributes(item);
+					t.assertTrue(identifier === null);
+					var identity = store.getIdentity(item);
+					t.assertTrue(typeof identity == "number");
+				}
+				d.callback(true);
+			}
+			function reportError(errData, request){
+				d.errback(true);
+			}
+			store.fetch({onComplete: onComplete, onError: reportError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Identity API: hierarchical_data",
+ 		runTest: function(datastore, t){
+			var store = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("geography_hierarchy_small"));
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				var features = store.getFeatures();
+				var hasIdentityFeature = Boolean(features['dojo.data.api.Identity']);
+				t.assertTrue(hasIdentityFeature);
+				for(var i = 0; i < items.length; ++i){
+					var item = items[i];
+					var identifier = store.getIdentityAttributes(item);
+					t.assertTrue(identifier === null);
+					var identity = store.getIdentity(item);
+					t.assertTrue(typeof identity == "number");
+				}
+				d.callback(true);
+			}
+			function reportError(errData, request){
+				d.errback(true);
+			}
+			store.fetch({onComplete: onComplete, onError: reportError});
+			return d; // Deferred
+		}
+	},
+	{
+		name: "Read API: functionConformance",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			var testStore = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	},
+	{
+		name: "Identity API: functionConformance",
+ 		runTest: function(datastore, t){
+			//	summary: 
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+			var testStore = new datastore(tests.data.readOnlyItemFileTestTemplates.getTestData("countries"));
+			var identityApi = new dojo.data.api.Identity();
+			var passed = true;
+
+			for(i in identityApi){
+
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = identityApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	}
+];
+
diff --git a/dojo/tests/data/reference_integrity.json b/dojo/tests/data/reference_integrity.json
new file mode 100644
index 0000000..bdc6767
--- /dev/null
+++ b/dojo/tests/data/reference_integrity.json
@@ -0,0 +1,27 @@
+/*
+{ 
+	"identifier": "id",
+	"label": "name",
+	"items":[
+		{"id": 1, "name": "Item 1"},
+		{"id": 2, "name": "Item 2"},
+		{"id": 3, "name": "Item 3"},
+		{"id": 4, "name": "Item 4"},
+		{"id": 5, "name": "Item 5"},
+		{"id": 6, "name": "Item 6"},
+		{"id": 7, "name": "Item 7"},
+		{"id": 8, "name": "Item 8"},
+		{"id": 9, "name": "Item 9"},
+		{"id": 10, "name": "Item 10", "friends": [{"_reference": 1},{"_reference": 3},{"_reference": 5}]},
+		{"id": 11, "name": "Item 11", "friends": [{"_reference": 10}], "siblings": [{"_reference": 10}]},
+		{"id": 12, "name": "Item 12", "friends": [{"_reference": 3},{"_reference": 7}], "enemies": [{"_reference": 10}]},
+		{"id": 13, "name": "Item 13", "friends": [{"_reference": 10}]},
+		{"id": 14, "name": "Item 14", "friends": [{"_reference": 11}]},
+		{"id": 15, "name": "item 15", "friends": [{"id": 16, "name": "Item 16"}]}
+	]
+}
+*/
+
+
+
+
diff --git a/dojo/tests/data/runTests.html b/dojo/tests/data/runTests.html
new file mode 100644
index 0000000..ee3d473
--- /dev/null
+++ b/dojo/tests/data/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>dojo.data D.O.H. Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=tests.data"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojo/tests/data/utils.js b/dojo/tests/data/utils.js
new file mode 100644
index 0000000..5af02ce
--- /dev/null
+++ b/dojo/tests/data/utils.js
@@ -0,0 +1,199 @@
+dojo.provide("tests.data.utils");
+dojo.require("dojo.data.util.filter");
+dojo.require("dojo.data.util.sorter");
+
+tests.register("tests.data.utils", 
+	[
+		function testWildcardFilter_1(t){
+			var pattern = "ca*";
+			var values = ["ca", "california", "Macca", "Macca*b", "Macca\\b"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testWildcardFilter_2(t){
+			var pattern = "*ca";
+			var values = ["ca", "california", "Macca", "Macca*b", "Macca\\b"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testWildcardFilter_3(t){
+			var pattern = "*ca*";
+			var values = ["ca", "california", "Macca", "Macca*b", "Macca\\b"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testWildcardFilter_4(t){
+			//Try and match <anything>c<anything>a*b
+			var pattern = "*c*a\\*b*";
+			var values = ["ca", "california", "Macca", "Macca*b", "Macca\\b"];
+
+			t.assertFalse(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testWildcardFilter_5(t){
+			var pattern = "*c*a\\\\*b";
+			var values = ["ca", "california", "Macca", "Macca*b", "Macca\\b"];
+
+			t.assertFalse(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testWildcardFilter_caseInsensitive(t){
+			var pattern = "ca*";
+			var values = ["CA", "california", "Macca", "Macca*b", "Macca\\b"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern, true))!== null);
+			t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern, true))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern, true))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern, true))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern, true))!== null);
+		},
+		function testSingleChar_1(t){
+			var pattern = "bob?le";
+			var values = ["bobble", "boble", "foo", "bobBle", "bar"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testSingleChar_2(t){
+			var pattern = "?ob?le";
+			var values = ["bobble", "cob1le", "foo", "bobBle", "bar"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testBracketChar(t){
+			//Make sure we don't treat this as regexp
+			var pattern = "*[*]*";
+			var values = ["bo[b]ble", "cob1le", "foo", "[bobBle]", "b[]ar"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testBraceChar(t){
+			//Make sure we don't treat this as regexp
+			var pattern = "*{*}*";
+			var values = ["bo{b}ble", "cob1le", "foo", "{bobBle}", "b{}ar"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testParenChar(t){
+			//Make sure we don't treat this as regexp
+			var pattern = "*(*)*";
+			var values = ["bo(b)ble", "cob1le", "foo", "{bobBle}", "b()ar"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testPlusChar(t){
+			//Make sure we don't treat this as regexp, so match anything with a + in it.
+			var pattern = "*+*";
+			var values = ["bo+ble", "cob1le", "foo", "{bobBle}", "b{}ar"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testPeriodChar(t){
+			//Make sure we don't treat this as regexp, so match anything with a period
+			var pattern = "*.*";
+			var values = ["bo.ble", "cob1le", "foo", "{bobBle}", "b{}ar"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testBarChar(t){
+			//Make sure we don't treat this as regexp, so match anything with a pipe bar
+			var pattern = "*|*";
+			var values = ["bo.ble", "cob|le", "foo", "{bobBle}", "b{}ar"];
+
+			t.assertFalse(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testDollarSignChar(t){
+			//Make sure we don't treat this as regexp, so match anything with a $ in it
+			var pattern = "*$*";
+			var values = ["bo$ble", "cob$le", "foo", "{bobBle}", "b{}ar"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testCarrotChar(t){
+			//Make sure we don't treat this as regexp, so match anything with a ^ in it
+			var pattern = "*^*";
+			var values = ["bo$ble", "cob$le", "f^oo", "{bobBle}", "b{}ar"];
+
+			t.assertFalse(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertTrue(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testEscapeChar(t){
+			//Make sure we escape properly, so match this single word.
+			var pattern = "bob\*ble";
+			var values = ["bob*ble", "cob$le", "f^oo", "{bobBle}", "b{}ar"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		},
+		function testAbsoluteMatch(t){
+			var pattern = "bobble";
+			var values = ["bobble", "cob$le", "f^oo", "{bobBle}", "b{}ar"];
+
+			t.assertTrue(values[0].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[1].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[2].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[3].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+			t.assertFalse(values[4].match(dojo.data.util.filter.patternToRegExp(pattern))!== null);
+		}
+	]
+);
+
diff --git a/dojo/tests/date.js b/dojo/tests/date.js
new file mode 100644
index 0000000..b75702a
--- /dev/null
+++ b/dojo/tests/date.js
@@ -0,0 +1,712 @@
+dojo.provide("tests.date");
+
+dojo.require("dojo.date");
+
+tests.register("tests.date.util", 
+	[
+
+/* Informational Functions
+ **************************/
+
+function test_date_getDaysInMonth(t){
+	// months other than February
+	t.is(31, dojo.date.getDaysInMonth(new Date(2006,0,1)));
+	t.is(31, dojo.date.getDaysInMonth(new Date(2006,2,1)));
+	t.is(30, dojo.date.getDaysInMonth(new Date(2006,3,1)));
+	t.is(31, dojo.date.getDaysInMonth(new Date(2006,4,1)));
+	t.is(30, dojo.date.getDaysInMonth(new Date(2006,5,1)));
+	t.is(31, dojo.date.getDaysInMonth(new Date(2006,6,1)));
+	t.is(31, dojo.date.getDaysInMonth(new Date(2006,7,1)));
+	t.is(30, dojo.date.getDaysInMonth(new Date(2006,8,1)));
+	t.is(31, dojo.date.getDaysInMonth(new Date(2006,9,1)));
+	t.is(30, dojo.date.getDaysInMonth(new Date(2006,10,1)));
+	t.is(31, dojo.date.getDaysInMonth(new Date(2006,11,1)));
+
+	// Februarys
+	t.is(28, dojo.date.getDaysInMonth(new Date(2006,1,1)));
+	t.is(29, dojo.date.getDaysInMonth(new Date(2004,1,1)));
+	t.is(29, dojo.date.getDaysInMonth(new Date(2000,1,1)));
+	t.is(28, dojo.date.getDaysInMonth(new Date(1900,1,1)));
+	t.is(28, dojo.date.getDaysInMonth(new Date(1800,1,1)));
+	t.is(28, dojo.date.getDaysInMonth(new Date(1700,1,1)));
+	t.is(29, dojo.date.getDaysInMonth(new Date(1600,1,1)));
+},
+
+function test_date_isLeapYear(t){
+	t.f(dojo.date.isLeapYear(new Date(2006,0,1)));
+	t.t(dojo.date.isLeapYear(new Date(2004,0,1)));
+	t.t(dojo.date.isLeapYear(new Date(2000,0,1)));
+	t.f(dojo.date.isLeapYear(new Date(1900,0,1)));
+	t.f(dojo.date.isLeapYear(new Date(1800,0,1)));
+	t.f(dojo.date.isLeapYear(new Date(1700,0,1)));
+	t.t(dojo.date.isLeapYear(new Date(1600,0,1)));
+},
+
+// The getTimezone function pulls from either the date's toString or
+// toLocaleString method -- it's really just a string-processing
+// function (assuming the Date obj passed in supporting both toString 
+// and toLocaleString) and as such can be tested for multiple browsers
+// by manually settting up fake Date objects with the actual strings
+// produced by various browser/OS combinations.
+// FIXME: the function and tests are not localized.
+function test_date_getTimezoneName(t){
+	
+	// Create a fake Date object with toString and toLocaleString
+	// results manually set to simulate tests for multiple browsers
+	function FakeDate(str, strLocale){
+		this.str = str || '';
+		this.strLocale = strLocale || '';
+		this.toString = function() {
+			return this.str;
+		};
+		this.toLocaleString = function(){
+			return this.strLocale;
+		};
+	}
+	var dt = new FakeDate();
+	
+	// FF 1.5 Ubuntu Linux (Breezy)
+	dt.str = 'Sun Sep 17 2006 22:25:51 GMT-0500 (CDT)';
+	dt.strLocale = 'Sun 17 Sep 2006 10:25:51 PM CDT';
+	t.is('CDT', dojo.date.getTimezoneName(dt));
+
+	// Safari 2.0 Mac OS X 10.4
+	dt.str = 'Sun Sep 17 2006 22:55:01 GMT-0500';
+	dt.strLocale = 'September 17, 2006 10:55:01 PM CDT';
+	t.is('CDT', dojo.date.getTimezoneName(dt));
+
+	// FF 1.5 Mac OS X 10.4
+	dt.str = 'Sun Sep 17 2006 22:57:18 GMT-0500 (CDT)';
+	dt.strLocale = 'Sun Sep 17 22:57:18 2006';
+	t.is('CDT', dojo.date.getTimezoneName(dt));
+
+	// Opera 9 Mac OS X 10.4 -- no TZ data expect empty string return
+	dt.str = 'Sun, 17 Sep 2006 22:58:06 GMT-0500';
+	dt.strLocale = 'Sunday September 17, 22:58:06 GMT-0500 2006';
+	t.is('', dojo.date.getTimezoneName(dt));
+	
+	// IE 6 Windows XP
+	dt.str = 'Mon Sep 18 11:21:07 CDT 2006';
+	dt.strLocale = 'Monday, September 18, 2006 11:21:07 AM';
+	t.is('CDT', dojo.date.getTimezoneName(dt));
+
+	// Opera 9 Ubuntu Linux (Breezy) -- no TZ data expect empty string return 
+	dt.str = 'Mon, 18 Sep 2006 13:30:32 GMT-0500';
+	dt.strLocale = 'Monday September 18, 13:30:32 GMT-0500 2006';
+	t.is('', dojo.date.getTimezoneName(dt));
+	
+	// IE 5.5 Windows 2000
+	dt.str = 'Mon Sep 18 13:49:22 CDT 2006';
+	dt.strLocale = 'Monday, September 18, 2006 1:49:22 PM';
+	t.is('CDT', dojo.date.getTimezoneName(dt));
+}
+	]
+);
+
+tests.register("tests.date.math", 
+	[
+function test_date_compare(t){
+	var d1=new Date();
+	d1.setHours(0);
+	var d2=new Date();
+	d2.setFullYear(2005);
+	d2.setHours(12);
+	t.is(0, dojo.date.compare(d1, d1));
+	t.is(1, dojo.date.compare(d1, d2, "date"));
+	t.is(-1, dojo.date.compare(d2, d1, "date"));
+	t.is(-1, dojo.date.compare(d1, d2, "time"));
+	t.is(1, dojo.date.compare(d1, d2, "datetime"));
+},
+function test_date_add(t){
+	var interv = ''; // Interval (e.g., year, month)
+	var dtA = null; // Date to increment
+	var dtB = null; // Expected result date
+	
+	interv = "year";
+	dtA = new Date(2005, 11, 27);
+	dtB = new Date(2006, 11, 27);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+	
+	dtA = new Date(2005, 11, 27);
+	dtB = new Date(2004, 11, 27);
+	t.is(dtB, dojo.date.add(dtA, interv, -1));
+	
+	dtA = new Date(2000, 1, 29);
+	dtB = new Date(2001, 1, 28);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+	
+	dtA = new Date(2000, 1, 29);
+	dtB = new Date(2005, 1, 28);
+	t.is(dtB, dojo.date.add(dtA, interv, 5));
+	
+	dtA = new Date(1900, 11, 31);
+	dtB = new Date(1930, 11, 31);
+	t.is(dtB, dojo.date.add(dtA, interv, 30));
+	
+	dtA = new Date(1995, 11, 31);
+	dtB = new Date(2030, 11, 31);
+	t.is(dtB, dojo.date.add(dtA, interv, 35));
+
+	interv = "quarter";
+	dtA = new Date(2000, 0, 1);
+	dtB = new Date(2000, 3, 1);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+	
+	dtA = new Date(2000, 1, 29);
+	dtB = new Date(2000, 7, 29);
+	t.is(dtB, dojo.date.add(dtA, interv, 2));
+	
+	dtA = new Date(2000, 1, 29);
+	dtB = new Date(2001, 1, 28);
+	t.is(dtB, dojo.date.add(dtA, interv, 4));
+	
+	interv = "month";
+	dtA = new Date(2000, 0, 1);
+	dtB = new Date(2000, 1, 1);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+	
+	dtA = new Date(2000, 0, 31);
+	dtB = new Date(2000, 1, 29);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+	
+	dtA = new Date(2000, 1, 29);
+	dtB = new Date(2001, 1, 28);
+	t.is(dtB, dojo.date.add(dtA, interv, 12));
+	
+	interv = "week";
+	dtA = new Date(2000, 0, 1);
+	dtB = new Date(2000, 0, 8);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+	interv = "day";
+	dtA = new Date(2000, 0, 1);
+	dtB = new Date(2000, 0, 2);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+	
+	dtA = new Date(2001, 0, 1);
+	dtB = new Date(2002, 0, 1);
+	t.is(dtB, dojo.date.add(dtA, interv, 365));
+	
+	dtA = new Date(2000, 0, 1);
+	dtB = new Date(2001, 0, 1);
+	t.is(dtB, dojo.date.add(dtA, interv, 366));
+	
+	dtA = new Date(2000, 1, 28);
+	dtB = new Date(2000, 1, 29);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+	
+	dtA = new Date(2001, 1, 28);
+	dtB = new Date(2001, 2, 1);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+	
+	dtA = new Date(2000, 2, 1);
+	dtB = new Date(2000, 1, 29);
+	t.is(dtB, dojo.date.add(dtA, interv, -1));
+	
+	dtA = new Date(2001, 2, 1);
+	dtB = new Date(2001, 1, 28);
+	t.is(dtB, dojo.date.add(dtA, interv, -1));
+	
+	dtA = new Date(2000, 0, 1);
+	dtB = new Date(1999, 11, 31);
+	t.is(dtB, dojo.date.add(dtA, interv, -1));
+	
+	interv = "weekday";
+	// Sat, Jan 1
+	dtA = new Date(2000, 0, 1);
+	// Should be Mon, Jan 3
+	dtB = new Date(2000, 0, 3);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+	
+	// Sun, Jan 2
+	dtA = new Date(2000, 0, 2);
+	// Should be Mon, Jan 3
+	dtB = new Date(2000, 0, 3);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+	
+	// Sun, Jan 2
+	dtA = new Date(2000, 0, 2);
+	// Should be Fri, Jan 7
+	dtB = new Date(2000, 0, 7);
+	t.is(dtB, dojo.date.add(dtA, interv, 5));
+	
+	// Sun, Jan 2
+	dtA = new Date(2000, 0, 2);
+	// Should be Mon, Jan 10
+	dtB = new Date(2000, 0, 10);
+	t.is(dtB, dojo.date.add(dtA, interv, 6));
+	
+	// Mon, Jan 3
+	dtA = new Date(2000, 0, 3);
+	// Should be Mon, Jan 17
+	dtB = new Date(2000, 0, 17);
+	t.is(dtB, dojo.date.add(dtA, interv, 10));
+	
+	// Sat, Jan 8
+	dtA = new Date(2000, 0, 8);
+	// Should be Mon, Jan 3
+	dtB = new Date(2000, 0, 3);
+	t.is(dtB, dojo.date.add(dtA, interv, -5));
+	
+	// Sun, Jan 9
+	dtA = new Date(2000, 0, 9);
+	// Should be Wed, Jan 5
+	dtB = new Date(2000, 0, 5);
+	t.is(dtB, dojo.date.add(dtA, interv, -3));
+	
+	// Sun, Jan 23
+	dtA = new Date(2000, 0, 23);
+	// Should be Fri, Jan 7
+	dtB = new Date(2000, 0, 7);
+	t.is(dtB, dojo.date.add(dtA, interv, -11));
+	
+	interv = "hour";
+	dtA = new Date(2000, 0, 1, 11);
+	dtB = new Date(2000, 0, 1, 12);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+	dtA = new Date(2001, 9, 28, 0);
+	dtB = new Date(dtA.getTime() + (60 * 60 * 1000));
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+	dtA = new Date(2001, 9, 28, 23);
+	dtB = new Date(2001, 9, 29, 0);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+	dtA = new Date(2001, 11, 31, 23);
+	dtB = new Date(2002, 0, 1, 0);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+	interv = "minute";
+	dtA = new Date(2000, 11, 31, 23, 59);
+	dtB = new Date(2001, 0, 1, 0, 0);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+	dtA = new Date(2000, 11, 27, 12, 2);
+	dtB = new Date(2000, 11, 27, 13, 2);
+	t.is(dtB, dojo.date.add(dtA, interv, 60));
+	
+	interv = "second";
+	dtA = new Date(2000, 11, 31, 23, 59, 59);
+	dtB = new Date(2001, 0, 1, 0, 0, 0);
+	t.is(dtB, dojo.date.add(dtA, interv, 1));
+
+	dtA = new Date(2000, 11, 27, 8, 10, 59);
+	dtB = new Date(2000, 11, 27, 8, 11, 59);
+	t.is(dtB, dojo.date.add(dtA, interv, 60));
+	
+	// Test environment JS Date doesn't support millisec?
+	//interv = "millisecond";
+	//
+	//dtA = new Date(2000, 11, 31, 23, 59, 59, 999);
+	//dtB = new Date(2001, 0, 1, 0, 0, 0, 0);
+	//t.is(dtB, dojo.date.add(dtA, interv, 1));
+	//
+	//dtA = new Date(2000, 11, 27, 8, 10, 53, 2);
+	//dtB = new Date(2000, 11, 27, 8, 10, 54, 2);
+	//t.is(dtB, dojo.date.add(dtA, interv, 1000));
+},
+function test_date_diff(t){
+	var dtA = null; // First date to compare
+	var dtB = null; // Second date to compare
+	var interv = ''; // Interval to compare on (e.g., year, month)
+	
+	interv = "year";
+	dtA = new Date(2005, 11, 27);
+	dtB = new Date(2006, 11, 27);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2000, 11, 31);
+	dtB = new Date(2001, 0, 1);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	interv = "quarter";
+	dtA = new Date(2000, 1, 29);
+	dtB = new Date(2001, 2, 1);
+	t.is(4, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2000, 11, 1);
+	dtB = new Date(2001, 0, 1);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	interv = "month";
+	dtA = new Date(2000, 1, 29);
+	dtB = new Date(2001, 2, 1);
+	t.is(13, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2000, 11, 1);
+	dtB = new Date(2001, 0, 1);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	interv = "week";
+	dtA = new Date(2000, 1, 1);
+	dtB = new Date(2000, 1, 8);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2000, 1, 28);
+	dtB = new Date(2000, 2, 6);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2000, 2, 6);
+	dtB = new Date(2000, 1, 28);
+	t.is(-1, dojo.date.difference(dtA, dtB, interv));
+	
+	interv = "day";
+	dtA = new Date(2000, 1, 29);
+	dtB = new Date(2000, 2, 1);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2000, 11, 31);
+	dtB = new Date(2001, 0, 1);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	// DST leap -- check for rounding err
+	// This is dependent on US calendar, but
+	// shouldn't break in other locales
+	dtA = new Date(2005, 3, 3);
+	dtB = new Date(2005, 3, 4);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	interv = "weekday";
+	dtA = new Date(2006, 7, 3);
+	dtB = new Date(2006, 7, 11);
+	t.is(6, dojo.date.difference(dtA, dtB, interv));
+	
+	// Positive diffs
+	dtA = new Date(2006, 7, 4);
+	dtB = new Date(2006, 7, 11);
+	t.is(5, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 5);
+	dtB = new Date(2006, 7, 11);
+	t.is(5, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 6);
+	dtB = new Date(2006, 7, 11);
+	t.is(5, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 7);
+	dtB = new Date(2006, 7, 11);
+	t.is(4, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 7);
+	dtB = new Date(2006, 7, 13);
+	t.is(4, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 7);
+	dtB = new Date(2006, 7, 14);
+	t.is(5, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 7);
+	dtB = new Date(2006, 7, 15);
+	t.is(6, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 7);
+	dtB = new Date(2006, 7, 28);
+	t.is(15, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 2, 2);
+	dtB = new Date(2006, 2, 28);
+	t.is(18, dojo.date.difference(dtA, dtB, interv));
+	
+	// Negative diffs
+	dtA = new Date(2006, 7, 11);
+	dtB = new Date(2006, 7, 4);
+	t.is(-5, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 11);
+	dtB = new Date(2006, 7, 5);
+	t.is(-4, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 11);
+	dtB = new Date(2006, 7, 6);
+	t.is(-4, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 11);
+	dtB = new Date(2006, 7, 7);
+	t.is(-4, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 13);
+	dtB = new Date(2006, 7, 7);
+	t.is(-5, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 14);
+	dtB = new Date(2006, 7, 7);
+	t.is(-5, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 15);
+	dtB = new Date(2006, 7, 7);
+	t.is(-6, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 7, 28);
+	dtB = new Date(2006, 7, 7);
+	t.is(-15, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2006, 2, 28);
+	dtB = new Date(2006, 2, 2);
+	t.is(-18, dojo.date.difference(dtA, dtB, interv));
+
+	// Two days on the same weekend -- no weekday diff
+	dtA = new Date(2006, 7, 5);
+	dtB = new Date(2006, 7, 6);
+	t.is(0, dojo.date.difference(dtA, dtB, interv));
+	
+	interv = "hour";
+	dtA = new Date(2000, 11, 31, 23);
+	dtB = new Date(2001, 0, 1, 0);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2000, 11, 31, 12);
+	dtB = new Date(2001, 0, 1, 0);
+	t.is(12, dojo.date.difference(dtA, dtB, interv));
+	
+	interv = "minute";
+	dtA = new Date(2000, 11, 31, 23, 59);
+	dtB = new Date(2001, 0, 1, 0, 0);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2000, 1, 28, 23, 59);
+	dtB = new Date(2000, 1, 29, 0, 0);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	interv = "second";
+	dtA = new Date(2000, 11, 31, 23, 59, 59);
+	dtB = new Date(2001, 0, 1, 0, 0, 0);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	interv = "millisecond";
+	dtA = new Date(2000, 11, 31, 23, 59, 59, 999);
+	dtB = new Date(2001, 0, 1, 0, 0, 0, 0);
+	t.is(1, dojo.date.difference(dtA, dtB, interv));
+	
+	dtA = new Date(2000, 11, 31, 23, 59, 59, 0);
+	dtB = new Date(2001, 0, 1, 0, 0, 0, 0);
+	t.is(1000, dojo.date.difference(dtA, dtB, interv));
+},
+function test_date_add_diff_year(t){
+	var interv = ''; // Interval (e.g., year, month)
+	var dtA = null; // Date to increment
+	var dtB = null; // Expected result date
+	
+	interv = "year";
+	dtA = new Date(2005, 11, 27);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+	
+	dtA = new Date(2005, 11, 27);
+	dtB = dojo.date.add(dtA, interv, -1);
+	t.is(dojo.date.difference(dtA, dtB, interv), -1);
+	
+	dtA = new Date(2000, 1, 29);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+	
+	dtA = new Date(2000, 1, 29);
+	dtB = dojo.date.add(dtA, interv, 5);
+	t.is(dojo.date.difference(dtA, dtB, interv), 5);
+	
+	dtA = new Date(1900, 11, 31);
+	dtB = dojo.date.add(dtA, interv, 30);
+	t.is(dojo.date.difference(dtA, dtB, interv), 30);
+	
+	dtA = new Date(1995, 11, 31);
+	dtB = dojo.date.add(dtA, interv, 35);
+	t.is(dojo.date.difference(dtA, dtB, interv), 35);
+},
+function test_date_add_diff_quarter(t){
+	var interv = ''; // Interval (e.g., year, month)
+	var dtA = null; // Date to increment
+	var dtB = null; // Expected result date
+	interv = "quarter";
+	dtA = new Date(2000, 0, 1);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+	
+	dtA = new Date(2000, 1, 29);
+	dtB = dojo.date.add(dtA, interv, 2);
+	t.is(dojo.date.difference(dtA, dtB, interv), 2);
+	
+	dtA = new Date(2000, 1, 29);
+	dtB = dojo.date.add(dtA, interv, 4);
+	t.is(dojo.date.difference(dtA, dtB, interv), 4);
+},
+function test_date_add_diff_month(t){
+	var interv = ''; // Interval (e.g., year, month)
+	var dtA = null; // Date to increment
+	var dtB = null; // Expected result date
+	interv = "month";
+	dtA = new Date(2000, 0, 1);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+	
+	dtA = new Date(2000, 0, 31);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+	
+	dtA = new Date(2000, 1, 29);
+	dtB = dojo.date.add(dtA, interv, 12);
+	t.is(dojo.date.difference(dtA, dtB, interv), 12);
+},
+function test_date_add_diff_week(t){
+	var interv = ''; // Interval (e.g., year, month)
+	var dtA = null; // Date to increment
+	var dtB = null; // Expected result date
+	interv = "week";
+	dtA = new Date(2000, 0, 1);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+},
+function test_date_add_diff_day(t){
+	var interv = ''; // Interval (e.g., year, month)
+	var dtA = null; // Date to increment
+	var dtB = null; // Expected result date
+	interv = "day";
+	dtA = new Date(2000, 0, 1);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+	
+	dtA = new Date(2001, 0, 1);
+	dtB = dojo.date.add(dtA, interv, 365);
+	t.is(dojo.date.difference(dtA, dtB, interv), 365);
+	
+	dtA = new Date(2000, 0, 1);
+	dtB = dojo.date.add(dtA, interv, 366);
+	t.is(dojo.date.difference(dtA, dtB, interv), 366);
+	
+	dtA = new Date(2000, 1, 28);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+	
+	dtA = new Date(2001, 1, 28);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+	
+	dtA = new Date(2000, 2, 1);
+	dtB = dojo.date.add(dtA, interv, -1);
+	t.is(dojo.date.difference(dtA, dtB, interv), -1);
+	
+	dtA = new Date(2001, 2, 1);
+	dtB = dojo.date.add(dtA, interv, -1);
+	t.is(dojo.date.difference(dtA, dtB, interv), -1);
+	
+	dtA = new Date(2000, 0, 1);
+	dtB = dojo.date.add(dtA, interv, -1);
+	t.is(dojo.date.difference(dtA, dtB, interv), -1);
+},
+function test_date_add_diff_weekday(t){
+	var interv = ''; // Interval (e.g., year, month)
+	var dtA = null; // Date to increment
+	var dtB = null; // Expected result date
+	interv = "weekday";
+	// Sat, Jan 1
+	dtA = new Date(2000, 0, 1);
+	// Should be Mon, Jan 3
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+	
+	// Sun, Jan 2
+	dtA = new Date(2000, 0, 2);
+	// Should be Mon, Jan 3
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+	
+	// Sun, Jan 2
+	dtA = new Date(2000, 0, 2);
+	// Should be Fri, Jan 7
+	dtB = dojo.date.add(dtA, interv, 5);
+	t.is(dojo.date.difference(dtA, dtB, interv), 5);
+	
+	// Sun, Jan 2
+	dtA = new Date(2000, 0, 2);
+	// Should be Mon, Jan 10
+	dtB = dojo.date.add(dtA, interv, 6);
+	t.is(dojo.date.difference(dtA, dtB, interv), 6);
+	
+	// Mon, Jan 3
+	dtA = new Date(2000, 0, 3);
+	// Should be Mon, Jan 17
+	dtB = dojo.date.add(dtA, interv, 10);
+	t.is(dojo.date.difference(dtA, dtB, interv), 10);
+	
+	// Sat, Jan 8
+	dtA = new Date(2000, 0, 8);
+	// Should be Mon, Jan 3
+	dtB = dojo.date.add(dtA, interv, -5);
+	t.is(dojo.date.difference(dtA, dtB, interv), -5);
+	
+	// Sun, Jan 9
+	dtA = new Date(2000, 0, 9);
+	// Should be Wed, Jan 5
+	dtB = dojo.date.add(dtA, interv, -3);
+	t.is(dojo.date.difference(dtA, dtB, interv), -3);
+	
+	// Sun, Jan 23
+	dtA = new Date(2000, 0, 23);
+	// Should be Fri, Jan 7
+	dtB = dojo.date.add(dtA, interv, -11);
+	t.is(dojo.date.difference(dtA, dtB, interv), -11);
+},
+function test_date_add_diff_hour(t){
+	var interv = ''; // Interval (e.g., year, month)
+	var dtA = null; // Date to increment
+	var dtB = null; // Expected result date
+	interv = "hour";
+	dtA = new Date(2000, 0, 1, 11);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+	dtA = new Date(2001, 9, 28, 0);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+	dtA = new Date(2001, 9, 28, 23);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+	dtA = new Date(2001, 11, 31, 23);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+},
+function test_date_add_diff_minute(t){
+	var interv = ''; // Interval (e.g., year, month)
+	var dtA = null; // Date to increment
+	var dtB = null; // Expected result date
+	interv = "minute";
+	dtA = new Date(2000, 11, 31, 23, 59);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+	dtA = new Date(2000, 11, 27, 12, 2);
+	dtB = dojo.date.add(dtA, interv, 60);
+	t.is(dojo.date.difference(dtA, dtB, interv), 60);
+},
+function test_date_add_diff_second(t){
+	var interv = ''; // Interval (e.g., year, month)
+	var dtA = null; // Date to increment
+	var dtB = null; // Expected result date
+	console.debug("second");
+	interv = "second";
+	dtA = new Date(2000, 11, 31, 23, 59, 59);
+	dtB = dojo.date.add(dtA, interv, 1);
+	t.is(dojo.date.difference(dtA, dtB, interv), 1);
+
+	dtA = new Date(2000, 11, 27, 8, 10, 59);
+	dtB = dojo.date.add(dtA, interv, 60);
+	t.is(dojo.date.difference(dtA, dtB, interv), 60);
+	
+	// Test environment JS Date doesn't support millisec?
+	//interv = "millisecond";
+	//
+	//dtA = new Date(2000, 11, 31, 23, 59, 59, 999);
+	//dtB = dojo.date.add(dtA, interv, 1);
+	//t.is(dojo.date.difference(dtA, dtB, interv), 1);
+	//
+	//dtA = new Date(2000, 11, 27, 8, 10, 53, 2);
+	//dtB = dojo.date.add(dtA, interv, 1000);
+	//t.is(dojo.date.difference(dtA, dtB, interv), 1000);
+}
+	]
+);
+
+dojo.require("tests.date.locale");
+dojo.require("tests.date.stamp");
diff --git a/dojo/tests/date/locale.js b/dojo/tests/date/locale.js
new file mode 100644
index 0000000..a7c0115
--- /dev/null
+++ b/dojo/tests/date/locale.js
@@ -0,0 +1,430 @@
+dojo.provide("tests.date.locale");
+
+dojo.require("dojo.date.locale");
+
+tests.register("tests.date.locale", 
+	[
+		{
+			// Test formatting and parsing of dates in various locales pre-built in dojo.cldr
+			// NOTE: we can't set djConfig.extraLocale before bootstrapping unit tests, so directly
+			// load resources here for specific locales:
+
+			name: "date.locale",
+			setUp: function(){
+				var partLocaleList = ["en-us", "fr-fr", "es", "de-at", "ja-jp", "zh-cn"];
+
+				dojo.forEach(partLocaleList, function(locale){
+					dojo.requireLocalization("dojo.cldr", "gregorian", locale);
+				});
+			},
+			runTest: function(t){
+			},
+			tearDown: function(){
+				//Clean up bundles that should not exist if
+				//the test is re-run.
+				delete dojo.cldr.nls.gregorian;
+			}
+		},
+		{
+			name: "isWeekend",
+			runTest: function(t){
+				var thursday = new Date(2006, 8, 21);
+				var friday = new Date(2006, 8, 22);
+				var saturday = new Date(2006, 8, 23);
+				var sunday = new Date(2006, 8, 24);
+				var monday = new Date(2006, 8, 25);
+				t.f(dojo.date.locale.isWeekend(thursday, 'en-us'));
+				t.t(dojo.date.locale.isWeekend(saturday, 'en-us'));
+				t.t(dojo.date.locale.isWeekend(sunday, 'en-us'));
+				t.f(dojo.date.locale.isWeekend(monday, 'en-us'));
+//	t.f(dojo.date.locale.isWeekend(saturday, 'en-in'));
+//	t.t(dojo.date.locale.isWeekend(sunday, 'en-in'));
+//	t.f(dojo.date.locale.isWeekend(monday, 'en-in'));
+//	t.t(dojo.date.locale.isWeekend(friday, 'he-il'));
+//	t.f(dojo.date.locale.isWeekend(sunday, 'he-il'));
+			}
+		},
+		{
+			name: "format",
+			runTest: function(t){
+
+	var date = new Date(2006, 7, 11, 0, 55, 12, 345);
+
+	t.is("Friday, August 11, 2006", dojo.date.locale.format(date, {formatLength:'full',selector:'date', locale:'en-us'}));
+	t.is("vendredi 11 ao\xFBt 2006", dojo.date.locale.format(date, {formatLength:'full',selector:'date', locale:'fr-fr'}));
+	t.is("Freitag, 11. August 2006", dojo.date.locale.format(date, {formatLength:'full',selector:'date', locale:'de-at'}));
+	t.is("2006\u5E748\u670811\u65E5\u91D1\u66DC\u65E5", dojo.date.locale.format(date, {formatLength:'full',selector:'date', locale:'ja-jp'}));
+
+	t.is("8/11/06", dojo.date.locale.format(date, {formatLength:'short',selector:'date', locale:'en-us'}));
+	t.is("11/08/06", dojo.date.locale.format(date, {formatLength:'short',selector:'date', locale:'fr-fr'}));
+	t.is("11.08.06", dojo.date.locale.format(date, {formatLength:'short',selector:'date', locale:'de-at'}));
+	t.is("06/08/11", dojo.date.locale.format(date, {formatLength:'short',selector:'date', locale:'ja-jp'}));
+
+	t.is("6", dojo.date.locale.format(date, {datePattern:'E', selector:'date'}));
+
+	t.is("12:55 AM", dojo.date.locale.format(date, {formatLength:'short',selector:'time', locale:'en-us'}));
+	t.is("12:55:12", dojo.date.locale.format(date, {timePattern:'h:m:s',selector:'time'}));
+	t.is("12:55:12.35", dojo.date.locale.format(date, {timePattern:'h:m:s.SS',selector:'time'}));
+	t.is("24:55:12.35", dojo.date.locale.format(date, {timePattern:'k:m:s.SS',selector:'time'}));
+	t.is("0:55:12.35", dojo.date.locale.format(date, {timePattern:'H:m:s.SS',selector:'time'}));
+	t.is("0:55:12.35", dojo.date.locale.format(date, {timePattern:'K:m:s.SS',selector:'time'}));
+
+	t.is("11082006", dojo.date.locale.format(date, {datePattern:"ddMMyyyy", selector:"date"}));
+
+	t.is("12 o'clock AM", dojo.date.locale.format(date, {datePattern:"hh 'o''clock' a", selector:"date", locale: 'en'}));
+
+	// compare without timezone
+	t.is("\u4e0a\u534812\u65f655\u520612\u79d2", dojo.date.locale.format(date, {formatLength:'full',selector:'time', locale:'zh-cn'}).replace(/^.*(\u4e0a\u5348.*)/,"$1"));
+			}
+		},
+		{
+			name: "parse_dates",
+			runTest: function(t){
+
+	var aug_11_2006 = new Date(2006, 7, 11, 0);
+
+	//en: 'short' fmt: M/d/yy
+	// Tolerate either 8 or 08 for month part.
+	t.is( aug_11_2006, dojo.date.locale.parse("08/11/06", {formatLength:'short', selector:'date', locale:'en'}));
+	t.is( aug_11_2006, dojo.date.locale.parse("8/11/06", {formatLength:'short', selector:'date', locale:'en'}));	
+	// Tolerate yyyy input in yy part...
+	t.is( aug_11_2006, dojo.date.locale.parse("8/11/2006", {formatLength:'short', selector:'date', locale:'en'}));
+	// ...but not in strict mode
+	t.f( Boolean(dojo.date.locale.parse("8/11/2006", {formatLength:'short', selector:'date', locale:'en', strict:true})));
+
+	// test dates with no spaces
+	t.is( aug_11_2006, dojo.date.locale.parse("11Aug2006", {selector: 'date', datePattern: 'ddMMMyyyy', locale: 'en'}));
+	t.is( new Date(2006, 7, 1), dojo.date.locale.parse("Aug2006", {selector: 'date', datePattern: 'MMMyyyy', locale: 'en'}));
+
+	//en: 'medium' fmt: MMM d, yyyy
+	// Tolerate either 8 or 08 for month part.
+	t.is( aug_11_2006, dojo.date.locale.parse("Aug 11, 2006", {formatLength:'medium', selector:'date', locale:'en'}));
+	t.is( aug_11_2006, dojo.date.locale.parse("Aug 11, 2006", {formatLength:'medium', selector:'date', locale:'en'}));	
+	// Tolerate abbreviating period in month part...
+	t.is( aug_11_2006, dojo.date.locale.parse("Aug. 11, 2006", {formatLength:'medium', selector:'date', locale:'en'}));
+	// ...but not in strict mode
+	t.f( Boolean(dojo.date.locale.parse("Aug. 11, 2006", {formatLength:'medium', selector:'date', locale:'en', strict:true})));
+
+	// Note: 06 for year part will be translated literally as the year 6 C.E.
+	var aug_11_06CE = new Date(2006, 7, 11, 0);
+	aug_11_06CE.setFullYear(6); //literally the year 6 C.E.
+	t.is( aug_11_06CE, dojo.date.locale.parse("Aug 11, 06", {selector:'date', datePattern:'MMM dd, yyyy', locale: 'en', strict:true}));
+
+	//en: 'long' fmt: MMMM d, yyyy
+	t.is( aug_11_2006, dojo.date.locale.parse("August 11, 2006", {formatLength:'long', selector:'date', locale:'en'}));
+
+	//en: 'full' fmt: EEEE, MMMM d, yyyy
+	t.is( aug_11_2006, dojo.date.locale.parse("Friday, August 11, 2006", {formatLength:'full', selector:'date', locale:'en'}));
+	//TODO: wrong day-of-week should fail
+	//t.f( Boolean(dojo.date.locale.parse("Thursday, August 11, 2006", {formatLength:'full', selector:'date', locale:'en'})));
+	//TODO: Whitespace tolerance
+	//	t.is( aug_11_2006, dojo.date.locale.parse(" August 11, 2006", {formatLength:'long', selector:'date', locale:'en'}));
+	//	t.is( aug_11_2006, dojo.date.locale.parse("August  11, 2006", {formatLength:'long', selector:'date', locale:'en'}));
+	//	t.is( aug_11_2006, dojo.date.locale.parse("August 11 , 2006", {formatLength:'long', selector:'date', locale:'en'}));
+	//	t.is( aug_11_2006, dojo.date.locale.parse("August 11,  2006", {formatLength:'long', selector:'date', locale:'en'}));
+	//	t.is( aug_11_2006, dojo.date.locale.parse("August 11, 2006 ", {formatLength:'long', selector:'date', locale:'en'}));
+
+	//Simple Validation Tests
+	//catch "month" > 12 (note: month/day reversals are common when user expectation isn't met wrt european versus US formats)
+	t.f( Boolean(dojo.date.locale.parse("15/1/2005", {formatLength:'short', selector:'date', locale:'en'})));
+	//day of month typo rolls over to the next month
+	t.f( Boolean(dojo.date.locale.parse("Aug 32, 2006", {formatLength:'medium', selector:'date', locale:'en'})));
+
+	//German (de)
+	t.is( aug_11_2006, dojo.date.locale.parse("11.08.06", {formatLength:'short', selector:'date', locale:'de'}));
+	t.f( Boolean(dojo.date.locale.parse("11.8/06", {formatLength:'short', selector:'date', locale:'de'})));
+	t.f( Boolean(dojo.date.locale.parse("11.8x06", {formatLength:'short', selector:'date', locale:'de'})));
+	t.f( Boolean(dojo.date.locale.parse("11.13.06", {formatLength:'short', selector:'date', locale:'de'})));
+	t.f( Boolean(dojo.date.locale.parse("11.0.06", {formatLength:'short', selector:'date', locale:'de'})));
+	t.f( Boolean(dojo.date.locale.parse("32.08.06", {formatLength:'short', selector:'date', locale:'de'})));
+
+	//Spanish (es)
+	//es: 'short' fmt: d/MM/yy
+	t.is( aug_11_2006, dojo.date.locale.parse("11/08/06", {formatLength:'short', selector:'date', locale:'es'}));
+	t.is( aug_11_2006, dojo.date.locale.parse("11/8/06", {formatLength:'short', selector:'date', locale:'es'}));	
+	// Tolerate yyyy input in yy part...
+	t.is( aug_11_2006, dojo.date.locale.parse("11/8/2006", {formatLength:'short', selector:'date', locale:'es'}));
+	// ...but not in strict mode
+	t.f( Boolean(dojo.date.locale.parse("11/8/2006", {formatLength:'short', selector:'date', locale:'es', strict:true})));
+	//es: 'medium' fmt: dd-MMM-yy (not anymore as of CLDR 1.5.1)
+//	t.is( aug_11_2006, dojo.date.locale.parse("11-ago-06", {formatLength:'medium', selector:'date', locale:'es'}));
+//	t.is( aug_11_2006, dojo.date.locale.parse("11-ago-2006", {formatLength:'medium', selector:'date', locale:'es'}));	
+	// Tolerate abbreviating period in month part...
+//	t.is( aug_11_2006, dojo.date.locale.parse("11-ago.-2006", {formatLength:'medium', selector:'date', locale:'es'}));
+	// ...but not in strict mode
+//	t.f( Boolean(dojo.date.locale.parse("11-ago.-2006", {formatLength:'medium', selector:'date', locale:'es', strict:true})));
+	//es: 'long' fmt: d' de 'MMMM' de 'yyyy
+	t.is( aug_11_2006, dojo.date.locale.parse("11 de agosto de 2006", {formatLength:'long', selector:'date', locale:'es'}));
+	//case-insensitive month...
+	t.is( aug_11_2006, dojo.date.locale.parse("11 de Agosto de 2006", {formatLength:'long', selector:'date', locale:'es'}));
+	//...but not in strict mode
+	t.f( Boolean(dojo.date.locale.parse("11 de Agosto de 2006", {formatLength:'long', selector:'date', locale:'es', strict:true})));
+	//es 'full' fmt: EEEE d' de 'MMMM' de 'yyyy
+	t.is( aug_11_2006, dojo.date.locale.parse("viernes 11 de agosto de 2006", {formatLength:'full', selector:'date', locale:'es'}));
+	//case-insensitive day-of-week...
+	t.is( aug_11_2006, dojo.date.locale.parse("Viernes 11 de agosto de 2006", {formatLength:'full', selector:'date', locale:'es'}));
+	//...but not in strict mode
+	t.f( Boolean(dojo.date.locale.parse("Viernes 11 de agosto de 2006", {formatLength:'full', selector:'date', locale:'es', strict:true})));
+
+	//Japanese (ja)
+	//note: to avoid garbling from non-utf8-aware editors that may touch this file, using the \uNNNN format 
+	//for expressing double-byte chars.
+	//toshi (year): \u5e74
+	//getsu (month): \u6708
+	//nichi (day): \u65e5
+	//kinyoubi (Friday): \u91d1\u66dc\u65e5
+	//zenkaku space: \u3000
+	
+	//ja: 'short' fmt: yy/MM/dd (note: the "short" fmt isn't actually defined in the CLDR data...)
+	t.is( aug_11_2006, dojo.date.locale.parse("06/08/11", {formatLength:'short', selector:'date', locale:'ja'}));
+	t.is( aug_11_2006, dojo.date.locale.parse("06/8/11", {formatLength:'short', selector:'date', locale:'ja'}));	
+ 	// Tolerate yyyy input in yy part...
+	t.is( aug_11_2006, dojo.date.locale.parse("2006/8/11", {formatLength:'short', selector:'date', locale:'ja'}));
+	// ...but not in strict mode
+	t.f( Boolean(dojo.date.locale.parse("2006/8/11", {formatLength:'short', selector:'date', locale:'ja', strict:true})));
+	//ja: 'medium' fmt: yyyy/MM/dd
+	t.is( aug_11_2006, dojo.date.locale.parse("2006/08/11", {formatLength:'medium', selector:'date', locale:'ja'}));
+	t.is( aug_11_2006, dojo.date.locale.parse("2006/8/11", {formatLength:'medium', selector:'date', locale:'ja'}));		
+	//ja: 'long' fmt: yyyy'\u5e74'\u6708'd'\u65e5'
+	t.is( aug_11_2006, dojo.date.locale.parse("2006\u5e748\u670811\u65e5", {formatLength:'long', selector:'date', locale:'ja'}));
+	//ja 'full' fmt: yyyy'\u5e74'M'\u6708'd'\u65e5'EEEE
+	t.is( aug_11_2006, dojo.date.locale.parse("2006\u5e748\u670811\u65e5\u91d1\u66dc\u65e5", {formatLength:'full', selector:'date', locale:'ja'}));
+
+	//TODO: Whitespace tolerance
+	//tolerate ascii space
+	//	t.is( aug_11_2006, dojo.date.locale.parse(" 2006\u5e748\u670811\u65e5\u91d1\u66dc\u65e5 ", {formatLength:'full', selector:'date', locale:'ja'}));
+	//	t.is( aug_11_2006, dojo.date.locale.parse("2006\u5e74 8\u670811\u65e5 \u91d1\u66dc\u65e5", {formatLength:'full', selector:'date', locale:'ja'}));
+	//tolerate zenkaku space
+	//	t.is( aug_11_2006, dojo.date.locale.parse("\u30002006\u5e748\u670811\u65e5\u91d1\u66dc\u65e5\u3000", {formatLength:'full', selector:'date', locale:'ja'}));
+	//	t.is( aug_11_2006, dojo.date.locale.parse("2006\u5e74\u30008\u670811\u65e5\u3000\u91d1\u66dc\u65e5", {formatLength:'full', selector:'date', locale:'ja'}));
+
+	var apr_11_2006 = new Date(2006, 3, 11, 0);
+	//Roundtrip
+	var options={formatLength:'medium',selector:'date', locale:'fr-fr'};
+	t.is(0, dojo.date.compare(apr_11_2006, dojo.date.locale.parse(dojo.date.locale.format(apr_11_2006, options), options)));
+
+	//Tolerance for abbreviations
+	t.is(0, dojo.date.compare(apr_11_2006, dojo.date.locale.parse("11 avr 06", options)));
+			}
+		},
+		{
+			name: "parse_dates_neg",
+			runTest: function(t){
+				t.f(Boolean(dojo.date.locale.parse("2/29/2007", {formatLength: 'short', selector: 'date', locale: 'en'})));
+				t.f(Boolean(dojo.date.locale.parse("4/31/2007", {formatLength: 'short', selector: 'date', locale: 'en'})));
+				t.f(Boolean(dojo.date.locale.parse("Decemb 30, 2007", {formatLength: 'long', selector: 'date', locale: 'en'})));
+			}
+		},
+		{
+			name: "parse_datetimes",
+			runTest: function(t){
+
+	var aug_11_2006_12_30_am = new Date(2006, 7, 11, 0, 30);
+	var aug_11_2006_12_30_pm = new Date(2006, 7, 11, 12, 30);
+
+	//en: 'short' datetime fmt: M/d/yy h:mm a
+	//note: this is concatenation of dateFormat-short and timeFormat-short, 
+	//cldr provisionally defines datetime fmts as well, but we're not using them at the moment
+	t.is( aug_11_2006_12_30_pm, dojo.date.locale.parse("08/11/06 12:30 PM", {formatLength:'short', locale:'en'}));
+	//case-insensitive
+	t.is( aug_11_2006_12_30_pm, dojo.date.locale.parse("08/11/06 12:30 pm", {formatLength:'short', locale:'en'}));
+	//...but not in strict mode
+	t.f( Boolean(dojo.date.locale.parse("08/11/06 12:30 pm", {formatLength:'short', locale:'en', strict:true})));
+
+	t.is( aug_11_2006_12_30_am, dojo.date.locale.parse("08/11/06 12:30 AM", {formatLength:'short', locale:'en'}));
+
+	t.is( new Date(2006, 7, 11), dojo.date.locale.parse("11082006", {datePattern:"ddMMyyyy", selector:"date"}));
+
+	t.is( new Date(2006, 7, 31), dojo.date.locale.parse("31Aug2006", {datePattern:"ddMMMyyyy", selector:"date"}));
+
+			}
+		},
+		{
+			name: "parse_times",
+			runTest: function(t){
+				var time = new Date(2006, 7, 11, 12, 30);
+				var tformat = {selector:'time', strict:true, timePattern:"h:mm a", locale:'en'};
+			
+				t.is(time.getHours(), dojo.date.locale.parse("12:30 PM", tformat).getHours());
+				t.is(time.getMinutes(), dojo.date.locale.parse("12:30 PM", tformat).getMinutes());
+			}
+		},
+		{
+			name: "format_patterns",
+			runTest: function(t){
+				var time = new Date(2006, 7, 11, 12, 30);
+				var tformat = {selector:'time', strict:true, timePattern:"h 'o''clock'", locale:'en'};
+				t.is(time.getHours(), dojo.date.locale.parse("12 o'clock", tformat).getHours());
+
+				tformat = {selector:'time', strict:true, timePattern:" 'Hour is' h", locale:'en'};
+				t.is(time.getHours(), dojo.date.locale.parse(" Hour is 12", tformat).getHours());
+
+				tformat = {selector:'time', strict:true, timePattern:"'Hour is' h", locale:'en'};
+				t.is(time.getHours(), dojo.date.locale.parse("Hour is 12", tformat).getHours());
+			}
+		},
+		{
+			name: "parse_patterns",
+			runTest: function(t){
+				var time = new Date(2006, 7, 11, 12, 30);
+				var tformat = {selector:'time', strict:true, timePattern:"h 'o''clock'", locale:'en'};
+				t.is(time.getHours(), dojo.date.locale.parse("12 o'clock", tformat).getHours());
+
+				tformat = {selector:'time', strict:true, timePattern:" 'Hour is' h", locale:'en'};
+				t.is(time.getHours(), dojo.date.locale.parse(" Hour is 12", tformat).getHours());
+				tformat = {selector:'time', strict:true, timePattern:"'Hour is' h", locale:'en'};
+				t.is(time.getHours(), dojo.date.locale.parse("Hour is 12", tformat).getHours());
+			}
+		},
+		{
+			name: "day_of_year",
+			runTest: function(t){
+
+//				t.is(23, dojo.date.setDayOfYear(new Date(2006,0,1), 23).getDate());
+				t.is(1, dojo.date.locale._getDayOfYear(new Date(2006,0,1)));
+				t.is(32, dojo.date.locale._getDayOfYear(new Date(2006,1,1)));
+				t.is(72, dojo.date.locale._getDayOfYear(new Date(2007,2,13,0,13)));
+				t.is(72, dojo.date.locale._getDayOfYear(new Date(2007,2,13,1,13)));
+			}
+		},
+		{
+			name: "week_of_year",
+			runTest: function(t){
+				t.is(0, dojo.date.locale._getWeekOfYear(new Date(2000,0,1)));
+				t.is(1, dojo.date.locale._getWeekOfYear(new Date(2000,0,2)));
+				t.is(0, dojo.date.locale._getWeekOfYear(new Date(2000,0,2), 1));
+				t.is(0, dojo.date.locale._getWeekOfYear(new Date(2007,0,1)));
+				t.is(1, dojo.date.locale._getWeekOfYear(new Date(2007,0,1), 1));
+				t.is(27, dojo.date.locale._getWeekOfYear(new Date(2007,6,14)));
+				t.is(28, dojo.date.locale._getWeekOfYear(new Date(2007,6,14), 1));
+			}
+		}
+	]
+);
+
+/*
+// workaround deprecated methods. Should decide whether we should convert the tests or add a helper method (in dojo.date?) to do this.
+
+dojo_validate_isValidTime = function(str, props){
+	props = props || {};
+	if(!props.format){props.format="h:mm:ss";}
+	if(!props.am){props.am="a.m.";}
+	if(!props.pm){props.pm="p.m.";}
+	var result = false;
+	if(/[hk]/.test(props.format) && props.format.indexOf('a') == -1){
+		result = dojo.date.locale.parse(str, {selector: 'time', timePattern: props.format + " a"});
+	}
+	return Boolean(result || dojo.date.locale.parse(str, {selector: 'time', timePattern: props.format}));
+}
+
+dojo_validate_is12HourTime = function(str){
+	return dojo_validate_isValidTime(str, {format: 'h:mm:ss'}) || 	dojo_validate_isValidTime(str, {format: 'h:mm'});
+}
+
+dojo_validate_is24HourTime = function(str){
+	return dojo_validate_isValidTime(str, {format: 'H:mm:ss'}) || 	dojo_validate_isValidTime(str, {format: 'H:mm'});
+}
+
+dojo_validate_isValidDate = function(str, fmt){
+	return Boolean(dojo.date.locale.parse(str, {selector: 'date', datePattern: fmt}));
+}
+
+function test_validate_datetime_isValidTime(){
+	jum.assertTrue("test1", dojo_validate_isValidTime('5:15:05 pm'));
+// FAILURE	jum.assertTrue("test2", dojo_validate_isValidTime('5:15:05 p.m.', {pm: "P.M."} ));
+	jum.assertFalse("test3", dojo_validate_isValidTime('5:15:05 f.m.'));
+	jum.assertTrue("test4", dojo_validate_isValidTime('5:15 pm', {format: "h:mm a"} ) );
+	jum.assertFalse("test5", dojo_validate_isValidTime('5:15 fm', {}) );
+	jum.assertTrue("test6", dojo_validate_isValidTime('15:15:00', {format: "H:mm:ss"} ) );
+// FAILURE	jum.assertFalse("test7", dojo_validate_isValidTime('15:15:00', {}) );
+	jum.assertTrue("test8", dojo_validate_isValidTime('17:01:30', {format: "H:mm:ss"} ) );
+	jum.assertFalse("test9", dojo_validate_isValidTime('17:1:30', {format: "H:mm:ss"} ) );
+// FAILURE	jum.assertFalse("test10", dojo_validate_isValidTime('17:01:30', {format: "H:m:ss"} ) );
+	// Greek
+// FAILURE	jum.assertTrue("test11", dojo_validate_isValidTime('5:01:30 \u0924\u0924', {am: "\u0928\u0924", pm: "\u0924\u0924"} ) );
+	// Italian
+	jum.assertTrue("test12", dojo_validate_isValidTime('17.01.30', {format: "H.mm.ss"} ) );
+	// Mexico
+// FAILURE	jum.assertTrue("test13", dojo_validate_isValidTime('05:01:30 p.m.', {format: "hh:mm:ss a", am: "a.m.", pm: "p.m."} ) );
+}
+
+
+function test_validate_datetime_is12HourTime(){
+	jum.assertTrue("test1", dojo_validate_is12HourTime('5:15:05 pm'));
+// FAILURE	jum.assertFalse("test2", dojo_validate_is12HourTime('05:15:05 pm'));
+	jum.assertFalse("test3", dojo_validate_is12HourTime('5:5:05 pm'));
+	jum.assertFalse("test4", dojo_validate_is12HourTime('5:15:5 pm'));
+// FAILURE	jum.assertFalse("test5", dojo_validate_is12HourTime('13:15:05 pm'));
+	jum.assertFalse("test6", dojo_validate_is12HourTime('5:60:05 pm'));
+	jum.assertFalse("test7", dojo_validate_is12HourTime('5:15:60 pm'));
+	jum.assertTrue("test8", dojo_validate_is12HourTime('5:59:05 pm'));
+	jum.assertTrue("test9", dojo_validate_is12HourTime('5:15:59 pm'));
+// FAILURE	jum.assertFalse("test10", dojo_validate_is12HourTime('5:15:05'));
+
+	// optional seconds
+	jum.assertTrue("test11", dojo_validate_is12HourTime('5:15 pm'));
+	jum.assertFalse("test12", dojo_validate_is12HourTime('5:15: pm'));
+}
+
+function test_validate_datetime_is24HourTime(){
+	jum.assertTrue("test1", dojo_validate_is24HourTime('00:03:59'));
+	jum.assertTrue("test2", dojo_validate_is24HourTime('22:03:59'));
+//FIXME: fix tests or code?
+//	jum.assertFalse("test3", dojo_validate_is24HourTime('22:03:59 pm'));
+//	jum.assertFalse("test4", dojo_validate_is24HourTime('2:03:59'));
+	jum.assertFalse("test5", dojo_validate_is24HourTime('0:3:59'));
+	jum.assertFalse("test6", dojo_validate_is24HourTime('00:03:5'));
+	jum.assertFalse("test7", dojo_validate_isValidTime('24:03:59', {format: 'kk:mm:ss'}));
+	jum.assertFalse("test8", dojo_validate_is24HourTime('02:60:59'));
+	jum.assertFalse("test9", dojo_validate_is24HourTime('02:03:60'));
+
+	// optional seconds
+	jum.assertTrue("test10", dojo_validate_is24HourTime('22:53'));
+	jum.assertFalse("test11", dojo_validate_is24HourTime('22:53:'));
+}
+
+function test_validate_datetime_isValidDate(){
+	
+	// Month date year
+	jum.assertTrue("test1", dojo_validate_isValidDate("08/06/2005", "MM/dd/yyyy"));
+	jum.assertTrue("test2", dojo_validate_isValidDate("08.06.2005", "MM.dd.yyyy"));
+	jum.assertTrue("test3", dojo_validate_isValidDate("08-06-2005", "MM-dd-yyyy"));
+	jum.assertTrue("test4", dojo_validate_isValidDate("8/6/2005", "M/d/yyyy"));
+	jum.assertTrue("test5", dojo_validate_isValidDate("8/6", "M/d"));
+	jum.assertFalse("test6", dojo_validate_isValidDate("09/31/2005", "MM/dd/yyyy"));
+	jum.assertFalse("test7", dojo_validate_isValidDate("02/29/2005", "MM/dd/yyyy"));
+	jum.assertTrue("test8", dojo_validate_isValidDate("02/29/2004", "MM/dd/yyyy"));
+
+	// year month date
+	jum.assertTrue("test9", dojo_validate_isValidDate("2005-08-06", "yyyy-MM-dd"));
+	jum.assertTrue("test10", dojo_validate_isValidDate("20050806", "yyyyMMdd"));
+
+	// year month
+	jum.assertTrue("test11", dojo_validate_isValidDate("2005-08", "yyyy-MM"));
+	jum.assertTrue("test12", dojo_validate_isValidDate("200508", "yyyyMM"));
+
+	// year
+	jum.assertTrue("test13", dojo_validate_isValidDate("2005", "yyyy"));
+
+	// year week day
+//TODO: need to support 'w'?
+//	jum.assertTrue("test14", dojo_validate_isValidDate("2005-W42-3", "yyyy-'W'ww-d"));
+//	jum.assertTrue("test15", dojo_validate_isValidDate("2005W423", "yyyy'W'wwd"));
+//	jum.assertFalse("test16", dojo_validate_isValidDate("2005-W42-8", "yyyy-'W'ww-d"));
+//	jum.assertFalse("test17", dojo_validate_isValidDate("2005-W54-3", "yyyy-'W'ww-d"));
+
+	// year week
+//	jum.assertTrue("test18", dojo_validate_isValidDate("2005-W42", "yyyy-'W'ww"));
+//	jum.assertTrue("test19", dojo_validate_isValidDate("2005W42", "yyyy'W'ww"));
+
+	// year ordinal-day
+	jum.assertTrue("test20", dojo_validate_isValidDate("2005-292", "yyyy-DDD"));
+	jum.assertTrue("test21", dojo_validate_isValidDate("2005292", "yyyyDDD"));
+	jum.assertFalse("test22", dojo_validate_isValidDate("2005-366", "yyyy-DDD"));
+	jum.assertTrue("test23", dojo_validate_isValidDate("2004-366", "yyyy-DDD"));
+
+	// date month year
+	jum.assertTrue("test24", dojo_validate_isValidDate("19.10.2005", "dd.MM.yyyy"));
+	jum.assertTrue("test25", dojo_validate_isValidDate("19-10-2005", "d-M-yyyy"));
+}
+*/
diff --git a/dojo/tests/date/stamp.js b/dojo/tests/date/stamp.js
new file mode 100644
index 0000000..a0db859
--- /dev/null
+++ b/dojo/tests/date/stamp.js
@@ -0,0 +1,98 @@
+dojo.provide("tests.date.stamp");
+
+dojo.require("dojo.date.stamp");
+
+tests.register("tests.date.stamp", 
+	[
+function test_date_iso(t){
+	var rfc  = "2005-06-29T08:05:00-07:00";
+	var date = dojo.date.stamp.fromISOString(rfc);
+	t.is(2005,date.getFullYear());
+	t.is(5,date.getMonth());
+	t.is(29,date.getUTCDate());
+	t.is(15,date.getUTCHours());
+	t.is(5,date.getUTCMinutes());
+	t.is(0,date.getSeconds());
+
+	rfc  = "2004-02-29";
+	date = dojo.date.stamp.fromISOString(rfc);
+	t.is(2004,date.getFullYear());
+	t.is(1,date.getMonth());
+	t.is(29,date.getDate());
+
+	rfc  = "2004-01";
+	date = dojo.date.stamp.fromISOString(rfc);
+	t.is(2004,date.getFullYear());
+	t.is(0,date.getMonth());
+	t.is(1,date.getDate());
+
+	// No TZ info means local time
+	rfc  = "2004-02-29T01:23:45";
+	date = dojo.date.stamp.fromISOString(rfc);
+	t.is(2004,date.getFullYear());
+	t.is(1,date.getMonth());
+	t.is(29,date.getDate());
+	t.is(1,date.getHours());
+
+	date = new Date(2005,5,29,8,5,0);
+	rfc = dojo.date.stamp.toISOString(date);
+	//truncate for comparison
+	t.is("2005-06",rfc.substring(0,7));
+
+	date = new Date(101,0,2);
+	date.setFullYear(101);
+	rfc = dojo.date.stamp.toISOString(date);
+	//truncate for comparison
+	t.is("0101-01",rfc.substring(0,7));
+
+	rfc  = "0101-01-01";
+	date = dojo.date.stamp.fromISOString(rfc);
+	t.is(101,date.getFullYear());
+	t.is(0,date.getMonth());
+	t.is(1,date.getDate());
+
+	rfc = "0001-01T00:00:00";
+	date = dojo.date.stamp.fromISOString(rfc);
+	t.is(1,date.getFullYear());
+
+	date = dojo.date.stamp.fromISOString("T18:46:39");
+	t.is(18, date.getHours());
+	t.is(46, date.getMinutes());
+	t.is(39, date.getSeconds());
+},
+
+function test_date_iso_tz(t){
+
+	//23:59:59.9942 or 235959.9942
+//	var date = dojo.date.stamp.fromISOString("T18:46:39.9942");
+//	t.is(18, date.getHours());
+//	t.is(46, date.getMinutes());
+//	t.is(39, date.getSeconds());
+//	t.is(994, date.getMilliseconds());
+	
+	//1995-02-04 24:00 = 1995-02-05 00:00
+
+	//timezone tests
+	var offset = new Date().getTimezoneOffset()/60;
+	date = dojo.date.stamp.fromISOString("T18:46:39+07:00");
+	t.is(11, date.getUTCHours());
+
+	date = dojo.date.stamp.fromISOString("T18:46:39+00:00");
+	t.is(18, date.getUTCHours());
+
+	date = dojo.date.stamp.fromISOString("T18:46:39Z");
+	t.is(18, date.getUTCHours());
+
+	date = dojo.date.stamp.fromISOString("T16:46:39-07:00");
+	t.is(23, date.getUTCHours());
+	
+	date = dojo.date.stamp.fromISOString("T00:00:00Z", new Date(2010,3,1));
+	t.is(0, date.getUTCHours());
+	t.is(2010, date.getFullYear());
+	
+	//+hh:mm, +hhmm, or +hh
+	
+	//-hh:mm, -hhmm, or -hh
+	}
+	]
+);
diff --git a/dojo/tests/dnd/dndDefault.css b/dojo/tests/dnd/dndDefault.css
new file mode 100644
index 0000000..d033239
--- /dev/null
+++ b/dojo/tests/dnd/dndDefault.css
@@ -0,0 +1,77 @@
+/*
+
+	there are basically all the classes you can set 
+	for the various dojo.dnd states and elements in
+	their simplest form. hacking welcome. 
+
+*/
+.container {
+	border: 3px solid #ccc;
+	padding: 1em 3em; 
+	cursor: default;
+	radius: 8pt;
+	background: #fff;
+	-moz-border-radius: 8pt 8pt;
+}
+
+.dojoDndContainerOver {
+	/* cursor:pointer; */
+	border: 3px solid #aaa;
+}
+
+.dojoDndTargetDisabled {
+	background: #eee;
+}
+
+.dojoDndItem { 
+	padding: 3px;
+}
+
+.dj_ff2 .dojoDndItem {
+	-moz-user-select: none; /* workaround FF2 dragging bug, see #6345, #4854, #6350 */
+} 
+
+.dojoDndItemOver {
+	background: #ededed;
+	cursor: pointer;
+}
+
+.dojoDndItemSelected {
+	background: #ccf; color: #444;
+}
+
+.dojoDndItemAnchor {
+	background: #ccf; color: black;
+}
+
+.dojoDndItemOver .dojoDndItemSelected {
+	background: #ededed;
+}
+
+.dojoDndItemOver .dojoDndItemAnchor {
+	background: #ededed;
+}
+
+.dojoDndItemBefore {
+	border-top: 2px solid #369;
+}
+
+.dojoDndItemAfter {
+	border-bottom: 2px solid #369;
+}
+
+.dojoDndAvatar {
+	border: 2px solid #ccc;
+	font-size: 75%;
+	-moz-border-radius: 8pt 8pt;
+	radius: 8pt;
+}
+	
+.dojoDndAvatarHeader {
+	background: #aaa;
+}
+
+.dojoDndAvatarItem {
+	background: #fff;
+	border-bottom: 1px solid #666;
+}
\ No newline at end of file
diff --git a/dojo/tests/dnd/flickr_viewer.html b/dojo/tests/dnd/flickr_viewer.html
new file mode 100644
index 0000000..4ede297
--- /dev/null
+++ b/dojo/tests/dnd/flickr_viewer.html
@@ -0,0 +1,168 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
+<html>
+<head>
+	<title>Sort Flickr images by tags</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "../../resources/dnd.css";
+		body {
+			padding: 1em;
+		}
+
+		/* application-specific settings */
+		#status					{font-weight: bold;}
+		.container				{padding: 5px; cursor: default; background: #f8f8ff;}
+		.wrap1					{float: left; width: 275px; height: 600px; overflow: auto; margin-right: 1em;}
+		.wrap1 div				{min-height: 100px;}
+		.wrap2					{width: 350px; height: 170px; overflow: auto;}
+		.wrap2 div				{min-height: 150px;}
+		.container .name		{font-weight: bold; padding-right: 4px;}
+		.container .image		{padding: 5px;}
+		body.dojoDndCopy, body.dojoDndMove	{color: #888;}
+		.dojoDndCopy .container, .dojoDndMove .container	{background: #ddf;}
+		
+		/* container-specific settings */
+		.dojoDndContainer		{border: 1px solid white; color: black;}
+		.dojoDndContainerOver	{border: 1px solid black; color: black;}
+		.container.dojoDndTargetDisabled	{background: #ccc; color: #888;}
+		
+		/* item-specific settings */
+		.dojoDndItemOver		{background: #feb;}
+		.dojoDndItemSelected	{background: #ccf; color: #444;}
+		.dojoDndItemAnchor		{background: #ccf; color: black;}
+		.dojoDndItemOver.dojoDndItemSelected	{background: #ec8;}
+		.dojoDndItemOver.dojoDndItemAnchor		{background: #ec8;}
+		.dojoDndItemBefore		{border-top:    3px solid red;}
+		.dojoDndItemAfter		{border-bottom: 3px solid red;}
+		.dojoDndHorizontal .dojoDndItemBefore		{border-top:    none;}
+		.dojoDndHorizontal .dojoDndItemAfter		{border-bottom: none;}
+		.dojoDndHorizontal .dojoDndItemBefore img	{border-left:  3px solid red;}
+		.dojoDndHorizontal .dojoDndItemAfter img	{border-right: 3px solid red;}
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../../dnd/common.js"></script>
+	<script type="text/javascript" src="../../dnd/autoscroll.js"></script>
+	<script type="text/javascript" src="../../dnd/Container.js"></script>
+	<script type="text/javascript" src="../../dnd/Selector.js"></script>
+	<script type="text/javascript" src="../../dnd/Source.js"></script>
+	<script type="text/javascript" src="../../dnd/Avatar.js"></script>
+	<script type="text/javascript" src="../../dnd/Manager.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojo.io.script");
+		dojo.require("dojo.dnd.Source");
+		
+		// The main image container creator
+		var main_creator = function(item, hint){
+			var type = [];
+			if(item.tags.search(/cat/i) >= 0){ type.push("cat"); }
+			if(item.tags.search(/dog/i) >= 0){ type.push("dog"); }
+			var node;
+			if(hint == "avatar"){
+				node = dojo.doc.createElement("span");
+				node.innerHTML = "<img src='" + item.media.m.replace(/_m\./, "_s.") + "'/>";
+			}else{
+				var t = ["<table border='0' cellpadding='0' cellspacing='0' width='250'>"];
+				t.push("<tr><td colspan='2' class='image' align='center' width='250'><img src='" + 
+					item.media.m + "'/></td></tr>");
+				t.push("<tr><td class='name' valign='top'>Title:</td><td class='value'><a href='" + 
+					item.link + "' target='_blank'>" + 
+					(item.title ? item.title : "<em>untitled</em>") + "</a></td></tr>");
+				t.push("<tr><td class='name' valign='top'>Author:</td><td class='value'>" + 
+					item.author + "</td></tr>");
+				t.push("<tr><td class='name' valign='top'>Tags:</td><td class='value'>" + 
+					item.tags + "</td></tr>");
+				t.push("</table>");
+				node = dojo.doc.createElement("div");
+				node.innerHTML = t.join("");
+			}
+			node.id = dojo.dnd.getUniqueId();
+			return {node: node, data: item, type: type};
+		};
+		
+		// The band image container creator
+		var band_creator = function(item, hint){
+			var type = [];
+			if(item.tags.search(/cat/i) >= 0){ type.push("cat"); }
+			if(item.tags.search(/dog/i) >= 0){ type.push("dog"); }
+			var src = item.media.m.replace(/_m\./, "_s.");
+			var node = dojo.doc.createElement("span");
+			node.innerHTML = "<img src='" + src + "'/>";
+			node.id = dojo.dnd.getUniqueId();
+			return {node: node, data: item, type: type};
+		};
+		
+		// Flickr's JSONP function
+		var jsonFlickrFeed = function(data){
+			if(!data.items || !data.items.length){
+				dojo.byId("status").innerHTML = "Flickr didn't return any images";
+				return;
+			}
+			dojo.byId("status").innerHTML = data.items.length + " images were retrieved";
+			// initialize sources
+			c1.selectAll().deleteSelectedNodes();
+			c2.selectAll().deleteSelectedNodes();
+			c3.selectAll().deleteSelectedNodes();
+			// populate the main source
+			c1.insertNodes(false, data.items);
+		};
+		
+		var init = function(){
+			// replace the avatar string to make it more human readable
+			dojo.dnd.Avatar.prototype._generateText = function(){
+				return (this.manager.copy ? "copy" : "mov") + 
+					"ing " + this.manager.nodes.length + " item" + 
+					(this.manager.nodes.length != 1 ? "s" : "");
+			};
+			// ask Flickr for images
+			var td = dojo.io.script.get({
+				url: "http://api.flickr.com/services/feeds/photos_public.gne",
+				content: {tags: "cat,dog,cow", tagmode: "any", format: "json"},
+				handleAs: "text/javascript",
+				preventCache: true
+			});
+			td.addErrback(function(){
+				dojo.byId("status").innerHTML = "Flickr failed to return images";
+			});
+		};
+		
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body>
+	<h1>Sort Flickr images by tags</h1>
+	<p>This simple web application retrieves public images from Flickr that were tagged either as "cat", "dog", or "cow".
+	You can copy/move images in different containers according to their tags.</p>
+	<p>Following selection modes are supported by default:</p>
+	<ul>
+		<li>Simple click — selects a single element, all other elements will be unselected.</li>
+		<li>Ctrl+click — toggles a selection state of an element (use Meta key on Mac).</li>
+		<li>Shift+click — selects a range of element from the previous anchor to the current element.</li>
+		<li>Ctrl+Shift+click — adds a range of element from the previous anchor to the current element (use Meta key on Mac).</li>
+	</ul>
+	<p>Following drop modes are supported by default:</p>
+	<ul>
+		<li>Simple drop — moves elements to the valid target removing them from the source. It can be used to reorganize elements within a single source/target.</li>
+		<li>Ctrl+drop — copies elements to the valid target (use Meta key on Mac).</li>
+	</ul>
+	<p>Now scroll down and start dragging and dropping, rearrange images using DnD, copy and move them back!</p>
+	<p>Status: <span id="status">retrieving a list of Flickr images...</span></p>
+	<div class="wrap1">
+		<div dojoType="dojo.dnd.Source" jsId="c1" accept="cat, dog, cow" class="container">
+			<script type="dojo/method" event="creator" args="item, hint">return main_creator(item, hint);</script>
+		</div>
+	</div>
+	<p>Tag: cat</p>
+	<div class="wrap2">
+		<div dojoType="dojo.dnd.Source" jsId="c2" accept="cat" horizontal="true" class="container">
+			<script type="dojo/method" event="creator" args="item, hint">return band_creator(item, hint);</script>
+		</div>
+	</div>
+	<p>Tag: dog</p>
+	<div class="wrap2">
+		<div dojoType="dojo.dnd.Source" jsId="c3" accept="dog" horizontal="true" class="container">
+			<script type="dojo/method" event="creator" args="item, hint">return band_creator(item, hint);</script>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojo/tests/dnd/robot/test_dnd.html b/dojo/tests/dnd/robot/test_dnd.html
new file mode 100644
index 0000000..761e91f
--- /dev/null
+++ b/dojo/tests/dnd/robot/test_dnd.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>doh.robot DnD Test</title>
+
+	<style>
+		@import "../../../../util/doh/robot/robot.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.robotx");
+
+		dojo.addOnLoad(function(){
+			var container1;
+			var container2;
+			var container3;
+			var container4;
+			var container5;
+
+			doh.robot.initRobot('../test_dnd.html');
+
+			doh.register('dojox.robot.AutoGeneratedTestGroup',{
+				name: 'autotest0',
+				timeout: 10000,
+				setUp: function(){
+					container1=dojo.byId('container1');
+					container2=dojo.query("div[jsid='c2']")[0];
+					container3=dojo.query("div[jsid='c3']")[0];
+					container4=dojo.query("div[jsid='c4']")[0];
+					container5=dojo.query("div[jsid='c5']")[0];
+				},
+				runTest: function(){
+					var count1=dojo.query("div", container1).length;
+					var count2=dojo.query("div", container2).length;
+					var d = new doh.Deferred();
+					doh.robot.mouseMoveAt('dojoUnique13', 500, 500, 10, 10);
+					doh.robot.mousePress({left:true}, 100);
+					doh.robot.mouseMoveAt(container2, 100, 1000);
+					doh.robot.mouseRelease({left:true}, 500);
+					doh.robot.sequence(d.getTestCallback(function(){
+						var actual = dojo.query("> div", container1).length;
+						count1--;
+						doh.is(count1, actual, "Wrong number of items ("+actual+") in container 1 (expected " + count1 + ")");
+						var actual = dojo.query("> div", container2).length;
+						count2++;
+						doh.is(count2, actual, "Wrong number of items ("+actual+") in container 2 (expected " + count2 + ")");
+					}), 1000);
+					return d;
+				}
+			});
+			doh.register('dojox.robot.AutoGeneratedTestGroup',{
+				name: 'autotest1',
+				timeout: 10000,
+				runTest: function(){
+					var count1=dojo.query("> div", container1).length;
+					var count2=dojo.query("> div", container2).length;
+					var d = new doh.Deferred();
+					doh.robot.mouseMoveAt('dojoUnique3', 500, 500, 10, 10);
+					doh.robot.mousePress({left:true}, 500);
+					doh.robot.mouseMoveAt(container1, 500, 1000);
+					doh.robot.mouseRelease({left:true}, 500);
+					doh.robot.sequence(d.getTestCallback(function(){
+						var actual = dojo.query("> div", container1).length;
+						count1++;
+						doh.is(count1, actual, "Wrong number of items ("+actual+") in container 1 (expected " + count1 + ")");
+						var actual = dojo.query("> div", container2).length;
+						doh.is(count2, actual, "Wrong number of items ("+actual+") in container 2 (expected " + count2 + ")");
+					}), 1000);
+					return d;
+				}
+			});
+			doh.register('dojox.robot.AutoGeneratedTestGroup',{
+				name: 'autotest2',
+				timeout: 10000,
+				runTest: function(){
+					var count2=dojo.query("> div", container2).length;
+					var count5=dojo.query("> div", container5).length;
+					var d = new doh.Deferred();
+					doh.robot.mouseMoveAt('dojoUnique11', 500, 500, 10, 10);
+					doh.robot.mousePress({left:true}, 500);
+					doh.robot.mouseMoveAt(container2, 500, 1000);
+					doh.robot.mouseRelease({left:true}, 500);
+					doh.robot.sequence(d.getTestCallback(function(){
+						var actual = dojo.query("> div", container2).length;
+						doh.is(count2, actual, "Wrong number of items ("+actual+") in container 2 (expected " + count2 + ")");
+						var actual = dojo.query("> div", container5).length;
+						doh.is(count5, actual, "Wrong number of items ("+actual+") in container 5 (expected " + count5 + ")");
+					}), 1000);
+					return d;
+				}
+			});
+			doh.run();
+		});
+	</script>
+</head>
+</html>
diff --git a/dojo/tests/dnd/test_box_constraints.html b/dojo/tests/dnd/test_box_constraints.html
new file mode 100644
index 0000000..6d08d99
--- /dev/null
+++ b/dojo/tests/dnd/test_box_constraints.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo box constraint test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "dndDefault.css"; 
+
+		body {
+			padding: 1em;
+		}
+
+		.moveable {
+			background: #FFFFBF;
+			border: 1px solid black;
+			width: 300px;
+			padding: 10px 20px;
+			cursor: pointer;
+		}
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../../dnd/move.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojo.dnd.move");
+		var m5, m6;
+		var init = function(){
+			m5 = new dojo.dnd.move.boxConstrainedMoveable("moveable5", {box: {l: 100, t: 100, w: 500, h: 500}});
+			m6 = new dojo.dnd.move.boxConstrainedMoveable("moveable6", {box: {l: 100, t: 100, w: 500, h: 500}, within: true});
+
+			// system-wide topics
+			dojo.subscribe("/dnd/move/start", function(node){ 
+				console.debug("Start move", node); 	
+			});
+			dojo.subscribe("/dnd/move/stop", function(node){ 
+				console.debug("Stop move", node); 	
+			});
+
+			// watching a particular moveable instance
+			dojo.connect(m5, "onDndMoveStart", function(mover){ 
+				console.debug("Start moving m5 with this mover:", mover); 	
+			});
+			dojo.connect(m5, "onDndMoveStop", function(mover){ 
+				console.debug("Stop moving m5 with this mover:", mover); 	
+			});
+		};
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body>
+	<h1>Dojo box constraint test</h1>
+	<p class="moveable" id="moveable5"><strong>Paragraph restricted to (100,100:500,500) box:</strong> Donec ac odio sed pede aliquet auctor. Donec et lectus. Praesent feugiat ultrices enim. Morbi lectus. Donec vestibulum posuere libero. Donec quam enim, nonummy a, auctor vitae, placerat id, massa. Vivamus vulputate luctus nibh. Donec dolor orci, sagittis ac, pretium sed, ornare sit amet, pede. Vestibulum leo justo, pellentesque sit amet, tristique sed, tempor eu, felis. Lorem ipsum dolor s [...]
+	<p class="moveable" id="moveable6"><strong>Paragraph restricted to (100,100:500,500) box, it cannot go outside of this box:</strong> In hac habitasse platea dictumst. Etiam rhoncus, leo quis hendrerit vestibulum, ipsum felis porta massa, vitae posuere nunc lorem ac enim. Nam neque turpis, aliquet quis, sollicitudin sit amet, dapibus sed, eros. Duis volutpat porttitor velit. Vivamus nibh metus, iaculis eget, malesuada eget, facilisis id, lorem. Sed turpis. Vestibulum aliquam mauris. Inte [...]
+	<p class="moveable" dojoType="dojo.dnd.move.boxConstrainedMoveable" box="{l: 100, t: 100, w: 500, h: 500}"><strong>Marked up paragraph restricted to (100,100:500,500) box:</strong> Donec ac odio sed pede aliquet auctor. Donec et lectus. Praesent feugiat ultrices enim. Morbi lectus. Donec vestibulum posuere libero. Donec quam enim, nonummy a, auctor vitae, placerat id, massa. Vivamus vulputate luctus nibh. Donec dolor orci, sagittis ac, pretium sed, ornare sit amet, pede. Vestibulum leo  [...]
+	</p>
+	<p class="moveable" dojoType="dojo.dnd.Moveable"><strong>Marked up paragraph restricted to (100,100:500,500) box, it cannot go outside of this box:</strong> In hac habitasse platea dictumst. Etiam rhoncus, leo quis hendrerit vestibulum, ipsum felis porta massa, vitae posuere nunc lorem ac enim. Nam neque turpis, aliquet quis, sollicitudin sit amet, dapibus sed, eros. Duis volutpat porttitor velit. Vivamus nibh metus, iaculis eget, malesuada eget, facilisis id, lorem. Sed turpis. Vestibu [...]
+		<!-- this is the obsolete way to do it -->
+		<script type="dojo/method">this.mover = dojo.dnd.boxConstrainedMover({l: 100, t: 100, w: 500, h: 500}, true);</script>
+	</p>
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_container.html b/dojo/tests/dnd/test_container.html
new file mode 100644
index 0000000..352aa7a
--- /dev/null
+++ b/dojo/tests/dnd/test_container.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo DnD container test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "dndDefault.css"; 
+
+		body {
+			padding: 20px;
+		}
+
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+	<script type="text/javascript" src="../../dnd/Container.js"></script>
+	<script type="text/javascript">
+		// dojo.require("dojo.dnd.Container");
+		var c1, c2, c3, c4, c5;
+		var init = function(){
+			c1 = new dojo.dnd.Container(dojo.byId("container1"));
+			c2 = new dojo.dnd.Container(dojo.byId("container2"));
+			c3 = new dojo.dnd.Container(dojo.byId("container3"));
+			c4 = new dojo.dnd.Container(dojo.byId("container4"));
+			c5 = new dojo.dnd.Container(dojo.byId("container5"));
+		};
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body>
+	<h1>Dojo DnD container test</h1>
+	<p>Containers have a notion of a "current container", and one element can be "current".</p>
+	<p>see <a href="dndDefault.css">dndDefault.css</a> for example styling</p>
+	<h2>DIV container</h2>
+	<div id="container1" class="container">
+		<div class="dojoDndItem">Item 1</div>
+		<div class="dojoDndItem">Item 2</div>
+		<div class="dojoDndItem">Item 3</div>
+	</div>
+	<h2>UL container</h2>
+	<ul id="container2" class="container">
+		<li class="dojoDndItem">Item 1</li>
+		<li class="dojoDndItem">Item 2</li>
+		<li class="dojoDndItem">Item 3</li>
+	</ul>
+	<h2>OL container</h2>
+	<ol id="container3" class="container">
+		<li class="dojoDndItem">Item 1</li>
+		<li class="dojoDndItem">Item 2</li>
+		<li class="dojoDndItem">Item 3</li>
+	</ol>
+	<h2>TABLE container</h2>
+	<table id="container4" class="container" border="1px solid black">
+		<tr class="dojoDndItem">
+			<td>A</td>
+			<td>row 1</td>
+		</tr>
+		<tr class="dojoDndItem">
+			<td>B</td>
+			<td>row 2</td>
+		</tr>
+		<tr class="dojoDndItem">
+			<td>C</td>
+			<td>row 3</td>
+		</tr>
+	</table>
+	<h2>P container with SPAN elements</h2>
+	<p>Elements of this container are layed out horizontally.</p>
+	<p id="container5" class="container">
+		<span class="dojoDndItem"> Item 1 </span>
+		<span class="dojoDndItem"> Item 2 </span>
+		<span class="dojoDndItem"> Item 3 </span>
+	</p>
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_container_markup.html b/dojo/tests/dnd/test_container_markup.html
new file mode 100644
index 0000000..4bde544
--- /dev/null
+++ b/dojo/tests/dnd/test_container_markup.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo DnD markup container test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "dndDefault.css"; 
+
+		body {
+			padding: 20px;
+		}
+
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../../dnd/Container.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojo.dnd.Container");
+	</script>
+</head>
+<body>
+	<h1>Dojo DnD markup container test</h1>
+	<p>This example is functionally equivalent to <a href="test_container.html">test_container.html</a> example but is done using the Dojo markup.</p>
+	<p>Containers have a notion of a "current container", and one element can be "current".</p>
+	<p>See <a href="dndDefault.css">dndDefault.css</a> for example styling</p>
+	<h2>DIV container</h2>
+	<div dojoType="dojo.dnd.Container" jsId="c1" class="container">
+		<div class="dojoDndItem">Item 1</div>
+		<div class="dojoDndItem">Item 2</div>
+		<div class="dojoDndItem">Item 3</div>
+	</div>
+	<h2>UL container</h2>
+	<ul dojoType="dojo.dnd.Container" jsId="c2" class="container">
+		<li class="dojoDndItem">Item 1</li>
+		<li class="dojoDndItem">Item 2</li>
+		<li class="dojoDndItem">Item 3</li>
+	</ul>
+	<h2>OL container</h2>
+	<ol dojoType="dojo.dnd.Container" jsId="c3" class="container">
+		<li class="dojoDndItem">Item 1</li>
+		<li class="dojoDndItem">Item 2</li>
+		<li class="dojoDndItem">Item 3</li>
+	</ol>
+	<h2>TABLE container</h2>
+	<table dojoType="dojo.dnd.Container" jsId="c4" class="container" border="1px solid black">
+		<tr class="dojoDndItem">
+			<td>A</td>
+			<td>row 1</td>
+		</tr>
+		<tr class="dojoDndItem">
+			<td>B</td>
+			<td>row 2</td>
+		</tr>
+		<tr class="dojoDndItem">
+			<td>C</td>
+			<td>row 3</td>
+		</tr>
+	</table>
+	<h2>P container with SPAN elements</h2>
+	<p>Elements of this container are layed out horizontally.</p>
+	<p dojoType="dojo.dnd.Container" jsId="c5" class="container">
+		<span class="dojoDndItem"> Item 1 </span>
+		<span class="dojoDndItem"> Item 2 </span>
+		<span class="dojoDndItem"> Item 3 </span>
+	</p>
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_custom_constraints.html b/dojo/tests/dnd/test_custom_constraints.html
new file mode 100644
index 0000000..bd261bb
--- /dev/null
+++ b/dojo/tests/dnd/test_custom_constraints.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo custom constraint test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+
+		body {
+			padding: 1em;
+		}
+
+		.moveable {
+			background: #FFFFBF;
+			border: 1px solid black;
+			width: 300px;
+			padding: 10px 20px;
+			margin: 0px;
+			cursor: pointer;
+		}
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+	<script type="text/javascript" src="../../dnd/move.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.dnd.move");
+		
+		var STEP = 50;
+		
+		var init = function(){
+			// 1st way
+			var m1 = new dojo.dnd.Moveable("moveable1");
+			m1.onMove = function(mover, leftTop){
+				leftTop.l -= leftTop.l % STEP;
+				leftTop.t -= leftTop.t % STEP;
+				dojo.marginBox(mover.node, leftTop);
+			};
+			// 2nd way
+			var m2 = new dojo.dnd.Moveable("moveable2");
+			dojo.connect(m2, "onMoving", function(mover, leftTop){
+				leftTop.l -= leftTop.l % STEP;
+				leftTop.t -= leftTop.t % STEP;
+			});
+		};
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body>
+	<h1>Dojo custom constraint test</h1>
+	<p class="moveable" id="moveable1"><strong>This paragraph stops at 50x50 grid knots:</strong> Donec ac odio sed pede aliquet auctor. Donec et lectus. Praesent feugiat ultrices enim. Morbi lectus. Donec vestibulum posuere libero. Donec quam enim, nonummy a, auctor vitae, placerat id, massa. Vivamus vulputate luctus nibh. Donec dolor orci, sagittis ac, pretium sed, ornare sit amet, pede. Vestibulum leo justo, pellentesque sit amet, tristique sed, tempor eu, felis. Lorem ipsum dolor sit am [...]
+	<p class="moveable" id="moveable2"><strong>This paragraph stops at 50x50 grid knots:</strong> Donec ac odio sed pede aliquet auctor. Donec et lectus. Praesent feugiat ultrices enim. Morbi lectus. Donec vestibulum posuere libero. Donec quam enim, nonummy a, auctor vitae, placerat id, massa. Vivamus vulputate luctus nibh. Donec dolor orci, sagittis ac, pretium sed, ornare sit amet, pede. Vestibulum leo justo, pellentesque sit amet, tristique sed, tempor eu, felis. Lorem ipsum dolor sit am [...]
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_dnd.html b/dojo/tests/dnd/test_dnd.html
new file mode 100644
index 0000000..5729b97
--- /dev/null
+++ b/dojo/tests/dnd/test_dnd.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo DnD test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "../../resources/dnd.css";
+		@import "dndDefault.css";
+		@import "../../../util/doh/robot/robot.css";
+
+		body {
+			padding: 1em;
+			background: #ededed;
+		}
+
+		.container {
+			width: 100px;
+			display: block;
+		}
+
+		.clear {
+			clear: both;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<script type="text/javascript" src="../../dnd/Container.js"></script>
+	<script type="text/javascript" src="../../dnd/Selector.js"></script>
+	<script type="text/javascript" src="../../dnd/Source.js"></script>
+	<script type="text/javascript" src="../../dnd/Avatar.js"></script>
+	<script type="text/javascript" src="../../dnd/Manager.js"></script>
+	<script type="text/javascript" src="../../../dijit/_base/wai.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojo.dnd.Source");
+
+		var c1;
+
+		function init(){
+			c1 = new dojo.dnd.Source("container1");
+			c1.insertNodes(false, [1, "A", [1, 2, 3],
+				function(x){ return x + x; },
+				{toString: function(){ return "CUSTOM!"; }},
+				null]);
+
+			// example subscribe to events
+			dojo.subscribe("/dnd/start", function(source){
+				console.debug("Starting the drop", source);
+			});
+			dojo.subscribe("/dnd/drop/before", function(source, nodes, copy, target){
+				if(target == c1){
+					console.debug(copy ? "Copying from" : "Moving from", source, "to", target, "before", target.before);
+				}
+			});
+			dojo.subscribe("/dnd/drop", function(source, nodes, copy, target){
+				if(target == c1){
+					console.debug(copy ? "Copying from" : "Moving from", source, "to", target, "before", target.before);
+				}
+			});
+			dojo.connect(c4, "onDndDrop", function(source, nodes, copy, target){
+				if(target == c4){
+					console.debug(copy ? "Copying from" : "Moving from", source);
+				}
+			});
+		};
+
+		dojo.addOnLoad(init);
+
+	</script>
+</head>
+<body>
+	<h1 class="testTitle">Dojo DnD test</h1>
+
+	<p>Elements of both sources/targets were created dynamically.</p>
+	<p>Following selection modes are supported by default:</p>
+	<ul>
+		<li>Simple click — selects a single element, all other elements will be unselected.</li>
+		<li>Ctrl+click — toggles a selection state of an element (use Meta key on Mac).</li>
+		<li>Shift+click — selects a range of element from the previous anchor to the current element.</li>
+		<li>Ctrl+Shift+click — adds a range of element from the previous anchor to the current element (use Meta key on Mac).</li>
+	</ul>
+	<p>Following drop modes are supported by default:</p>
+	<ul>
+		<li>Simple drop — moves elements to the valid target removing them from the source. It can be used to reorganize elements within a single source/target.</li>
+		<li>Ctrl+drop — copies elements to the valid target (use Meta key on Mac).</li>
+	</ul>
+
+	<div id="dragLists">
+		<div style="float: left; margin: 5px;">
+			<h3>Source 1</h3>
+			<div id="container1" class="container"></div>
+		</div>
+		<div style="float: left; margin: 5px;">
+			<h3>Source 2 (copyOnly)</h3>
+			<div dojoType="dojo.dnd.Source" jsId="c2" class="container" copyOnly="true">
+				<div class="dojoDndItem">Item <strong>X</strong></div>
+				<div class="dojoDndItem">Item <strong>Y</strong></div>
+				<div class="dojoDndItem">Item <strong>Z</strong></div>
+			</div>
+		</div>
+		<div style="float: left; margin: 5px;">
+			<h3>Source 3</h3>
+			<div dojoType="dojo.dnd.Source" jsId="c3" class="container">
+				<script type="dojo/method" event="creator" args="item, hint">
+					// this is custom creator, which changes the avatar representation
+					var node = dojo.doc.createElement("div"), s = String(item);
+					node.id = dojo.dnd.getUniqueId();
+					node.className = "dojoDndItem";
+					node.innerHTML = (hint != "avatar" || s.indexOf("Item") < 0) ?
+						s : "<strong style='color: darkred'>Special</strong> " + s;
+					return {node: node, data: item, type: ["text"]};
+				</script>
+				<div class="dojoDndItem">Item <strong>Alpha</strong></div>
+				<div class="dojoDndItem">Item <strong>Beta</strong></div>
+				<div class="dojoDndItem">Item <strong>Gamma</strong></div>
+				<div class="dojoDndItem">Item <strong>Delta</strong></div>
+			</div>
+		</div>
+		<div style="float: left; margin: 5px;">
+			<h3>Source 4 (copyOnly, selfAccept, delay=8)</h3>
+			<div dojoType="dojo.dnd.Source" jsId="c4" class="container" copyOnly="true" selfAccept="false" delay="8">
+				<div class="dojoDndItem">Item 1</div>
+				<div class="dojoDndItem">Item 2</div>
+				<div class="dojoDndItem">Item 3</div>
+			</div>
+		</div>
+		<div style="float: left; margin: 5px;">
+			<h3>Pure Target 5</h3>
+			<div dojoType="dojo.dnd.Target" jsId="c5" class="container">
+				<div class="dojoDndItem">One item</div>
+			</div>
+		</div>
+		<div class="clear"></div>
+	</div>
+
+	<p>HTML after</p>
+
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_dnd_handles.html b/dojo/tests/dnd/test_dnd_handles.html
new file mode 100644
index 0000000..9ab99bd
--- /dev/null
+++ b/dojo/tests/dnd/test_dnd_handles.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo DnD with handles test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "../../resources/dnd.css";
+		@import "dndDefault.css";
+
+		body { padding: 1em; background: #ededed; }
+
+		.container { width: 100px; display: block; }
+		.container.handles .dojoDndHandle { background: #fee; }
+		.clear { clear: both; }
+	</style>
+
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<script type="text/javascript" src="../../dnd/Container.js"></script>
+	<script type="text/javascript" src="../../dnd/Selector.js"></script>
+	<script type="text/javascript" src="../../dnd/Source.js"></script>
+	<script type="text/javascript" src="../../dnd/Avatar.js"></script>
+	<script type="text/javascript" src="../../dnd/Manager.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojo.dnd.Source");
+	</script>
+</head>
+<body>
+	<h1 class="testTitle">Dojo DnD with handles test</h1>
+
+	<p>Following selection modes are supported by default:</p>
+	<ul>
+		<li>Simple click — selects a single element, all other elements will be unselected.</li>
+		<li>Ctrl+click — toggles a selection state of an element (use Meta key on Mac).</li>
+		<li>Shift+click — selects a range of element from the previous anchor to the current element.</li>
+		<li>Ctrl+Shift+click — adds a range of element from the previous anchor to the current element (use Meta key on Mac).</li>
+	</ul>
+	<p>Following drop modes are supported by default:</p>
+	<ul>
+		<li>Simple drop — moves elements to the valid target removing them from the source. It can be used to reorganize elements within a single source/target.</li>
+		<li>Ctrl+drop — copies elements to the valid target (use Meta key on Mac).</li>
+	</ul>
+	
+	<p>Source with handles. Items should be draggable by the "em" of the word "Item" (and also see a 'move' cursor on it).</p>
+	<div dojoType="dojo.dnd.Source" jsId="c1" withHandles="true" class="container handles">
+		<div class="dojoDndItem"><span class="dojoDndHandle"><span class="dojoDndIgnore">It</span>em</span> <strong>Alpha</strong></div>
+		<div class="dojoDndItem"><span class="dojoDndHandle"><span class="dojoDndIgnore">It</span>em</span> <strong>Beta</strong></div>
+		<div class="dojoDndItem"><span class="dojoDndHandle"><span class="dojoDndIgnore">It</span>em</span> <strong>Gamma</strong></div>
+		<div class="dojoDndItem"><span class="dojoDndHandle"><span class="dojoDndIgnore">It</span>em</span> <strong>Delta</strong></div>
+	</div>
+
+	<p>Source without handles.</p>
+	<div dojoType="dojo.dnd.Source" jsId="c2" class="container">
+		<div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Epsilon</strong></div>
+		<div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Zeta</strong></div>
+		<div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Eta</strong></div>
+		<div class="dojoDndItem"><span class="dojoDndHandle">Item</span> <strong>Theta</strong></div>
+	</div>
+
+	<p>HTML after</p>
+
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_form.html b/dojo/tests/dnd/test_form.html
new file mode 100644
index 0000000..cac46c0
--- /dev/null
+++ b/dojo/tests/dnd/test_form.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo DnD form test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "../../resources/dnd.css";
+		@import "dndDefault.css";
+
+		body {
+			padding: 1em;
+			background:#ededed;
+		}
+
+		#container1,#container2 { width:300px; display:block; }
+		.clear { clear:both; } 
+
+	</style>
+
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<script type="text/javascript" src="../../dnd/Container.js"></script>
+	<script type="text/javascript" src="../../dnd/Selector.js"></script>
+	<script type="text/javascript" src="../../dnd/Source.js"></script>
+	<script type="text/javascript" src="../../dnd/Avatar.js"></script>
+	<script type="text/javascript" src="../../dnd/Manager.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		//dojo.require("dojo.dnd.Source");
+		//dojo.require("dojo.dnd.Manager");
+	
+		var c1, c2;
+	
+		function init(){
+
+			c1 = new dojo.dnd.Source("container1");
+			c1.insertNodes(false, [1, 2, 3, 4, 5, 6, [1, 2, 3], function(x){ return x + x; }]);
+			c2 = new dojo.dnd.Target("container2", {accept: ["money"]});
+
+			// example subscribe to events
+			dojo.subscribe("/dnd/start",function(foo){
+				console.debug(foo);
+			});
+
+		};
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body>
+	<h1 class="testTitle">Dojo DnD form test</h1>
+
+	<p>This is a test to confirm that the DnD container does not interfere with form elements.</p>
+
+	<div id="dragLists">
+	
+		<div style="float:left; margin:5px; ">
+			<h3>Target 1</h3>
+			<p id="container1" class="container"></p>
+		</div>
+
+		<div style="float:left; margin:5px; ">
+			<h3>Target 2: form controls galore</h3>
+			<form id="container2" class="container" action="http://dojotoolkit.org">
+				Input text: <input type="text" /><br />
+				Input checkbox: <input type="checkbox" /><br />
+				Input radio: <input type="radio" /><br />
+				Input password: <input type="password" /><br />
+				Input file: <input type="file" /><br />
+				Input button: <input type="button" value="Button" /><br />
+				Input reset: <input type="reset" /><br />
+				Input submit: <input type="submit" /><br />
+				Input image: <input type="image" src="http://dojotoolkit.org/misc/feed.png" /><br />
+				Button: <button>Button</button><br />
+				Select: <select><option>Yes</option><option>No</option></select><br />
+				Textarea: <textarea cols="20" rows="3">Some text.</textarea>
+			</form>
+		</div>
+		<div class="clear"></div>
+	</div>
+	
+	<p> </p>
+	
+	<div dojoType="dojo.dnd.Source" class="container">
+		<div>Source with <strong>skipForm = false</strong> (by default)</div>
+		<div class="dojoDndItem">Item <strong>X</strong>: <input type="text" value="1" /></div>
+		<div class="dojoDndItem">Item <strong>Y</strong>: <input type="text" value="2" /></div>
+		<div class="dojoDndItem">Item <strong>Z</strong>: <input type="text" value="3" /></div>
+	</div>
+
+	<p> </p>
+	
+	<div dojoType="dojo.dnd.Source" class="container" skipForm="true">
+		<div>Source with <strong>skipForm = true</strong></div>
+		<div class="dojoDndItem">Item <strong>A</strong>: <input type="text" value="a" /></div>
+		<div class="dojoDndItem">Item <strong>B</strong>: <input type="text" value="b" /></div>
+		<div class="dojoDndItem">Item <strong>C</strong>: <input type="text" value="c" /></div>
+	</div>
+
+	<p>HTML after</p>
+
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_moveable.html b/dojo/tests/dnd/test_moveable.html
new file mode 100644
index 0000000..2ed8620
--- /dev/null
+++ b/dojo/tests/dnd/test_moveable.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo Moveable test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "dndDefault.css"; 
+
+		body {
+			padding: 1em;
+			color:#666; 
+			background-color:#dedede;
+		}
+
+		#moveable1 {
+			background: #fff;
+			border: 1px solid black;
+			padding:8px; 
+		}
+		#handle1 {
+			background: #333;
+			color: #fff;
+			font-weight: bold;
+			cursor: pointer;
+			border: 1px solid black;
+		}
+		#moveable2 {
+			position: absolute;
+			background: #fff;
+			width:  200px;
+			height: 200px;
+			left: 100px;
+			top:  100px;
+			padding: 10px 20px;
+			margin: 10px 20px;
+			border: 10px solid black;
+			cursor: pointer;
+			radius:8pt;
+			-moz-border-radius:8pt 8pt; 
+		}
+		#moveable3 {
+			position: relative;
+			width: 150px;
+			height: 100px;
+			background: #ff8;
+			color: blue;
+			font-weight: bold;
+		}
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+	<script type="text/javascript" src="../../dnd/Mover.js"></script>
+	<script type="text/javascript" src="../../dnd/Moveable.js"></script>
+	<script type="text/javascript" src="../../dnd/move.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.dnd.move");
+		var m1, m2;
+		var init = function(){
+			m1 = new dojo.dnd.Moveable("moveable1", {handle: "handle1"});
+			m2 = new dojo.dnd.Moveable("moveable2");
+			m3 = new dojo.dnd.Moveable("moveable3");
+
+			dojo.subscribe("/dnd/move/start", function(mover){ 
+				console.debug("Start move", mover); 	
+			});
+			dojo.subscribe("/dnd/move/stop", function(mover){ 
+				console.debug("Stop move", mover); 	
+			});
+			
+			dojo.connect(m1, "onMoveStart", function(mover){
+				console.debug("Start moving m1", mover); 	
+			});
+			dojo.connect(m1, "onMoveStop", function(mover){
+				console.debug("Stop moving m1", mover); 	
+			});
+		};
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body>
+	<h1>Dojo Moveable test</h1>
+	<h2>1st run</h2>
+	<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. A [...]
+	<p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin s [...]
+	<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, el [...]
+	<p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante.  [...]
+	<p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa  [...]
+	<table id="moveable1">
+		<tr><td id="handle1" colspan="2">You can drag the table using this handle.</td></tr>
+		<tr><td>1</td><td>Lorem ipsum dolor sit amet...</td></tr>
+		<tr><td>2</td><td>Mauris vulputate elit a risus...</td></tr>
+		<tr><td>3</td><td>Pellentesque habitant morbi tristique senectus...</td></tr>
+		<tr><td>4</td><td>Duis ac augue rhoncus neque...</td></tr>
+		<tr><td>5</td><td>Quisque egestas turpis. Sed id...</td></tr>
+	</table>	
+	<h2>2nd run</h2>
+	<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. A [...]
+	<p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin s [...]
+	<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, el [...]
+	<p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante.  [...]
+	<p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa  [...]
+	<div id="moveable2">
+		<div>You can drag this whole object around.</div>
+		<div id="moveable3">You can move this paragraph. It is relatively positioned.</div>
+	</div>
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_moveable_markup.html b/dojo/tests/dnd/test_moveable_markup.html
new file mode 100644
index 0000000..9691f4c
--- /dev/null
+++ b/dojo/tests/dnd/test_moveable_markup.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo Moveable markup test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "dndDefault.css"; 
+
+		body {
+			padding: 1em;
+			color:#666; 
+			background-color:#dedede;
+		}
+
+		#moveable1 {
+			background: #fff;
+			border: 1px solid black;
+			padding:8px; 
+		}
+		#handle1 {
+			background: #333;
+			color: #fff;
+			font-weight:bold; 
+			cursor: pointer;
+			border: 1px solid black;
+		}
+		#moveable2 {
+			background: #fff;
+			position: absolute;
+			width:  200px;
+			height: 200px;
+			left: 100px;
+			top:  100px;
+			padding: 10px 20px;
+			margin: 10px 20px;
+			border: 10px solid black;
+			cursor: pointer;
+			radius:8pt;
+			-moz-border-radius:8pt 8pt; 
+		}
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../../dnd/move.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojo.dnd.move");
+
+		dojo.addOnLoad(function(){
+			dojo.subscribe("/dnd/move/start", function(node){ 
+				console.debug("Start move", node); 	
+			});
+
+			dojo.subscribe("/dnd/move/stop", function(node){ 
+				console.debug("Stop move", node); 	
+			});
+		});
+	</script>
+</head>
+<body>
+	<h1>Dojo Moveable markup test</h1>
+	<h2>1st run</h2>
+	<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. A [...]
+	<p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin s [...]
+	<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, el [...]
+	<p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante.  [...]
+	<p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa  [...]
+	<table id="moveable1" dojoType="dojo.dnd.Moveable" handle="handle1">
+		<tr><td id="handle1" colspan="2">You can drag the table using this handle.</td></tr>
+		<tr><td>1</td><td>Lorem ipsum dolor sit amet...</td></tr>
+		<tr><td>2</td><td>Mauris vulputate elit a risus...</td></tr>
+		<tr><td>3</td><td>Pellentesque habitant morbi tristique senectus...</td></tr>
+		<tr><td>4</td><td>Duis ac augue rhoncus neque...</td></tr>
+		<tr><td>5</td><td>Quisque egestas turpis. Sed id...</td></tr>
+	</table>	
+	<h2>2nd run</h2>
+	<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. A [...]
+	<p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin s [...]
+	<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, el [...]
+	<p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante.  [...]
+	<p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa  [...]
+	<div id="moveable2" dojoType="dojo.dnd.Moveable">You can drag this whole paragraph around.</div>	
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_params.html b/dojo/tests/dnd/test_params.html
new file mode 100644
index 0000000..8d5531b
--- /dev/null
+++ b/dojo/tests/dnd/test_params.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo DnD optional parameters test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+
+		body {
+			padding: 1em;
+		}
+
+		.moveable {
+			background: #FFFFBF;
+			border: 1px solid black;
+			width: 300px;
+			padding: 10px 20px;
+			cursor: pointer;
+		}
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+	<script type="text/javascript" src="../../dnd/move.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.dnd.move");
+		var m1, m2, m3, m4;
+		var init = function(){
+			m1 = new dojo.dnd.Moveable("moveable1");
+			m2 = new dojo.dnd.Moveable("moveable2", {delay: 10});
+			m3 = new dojo.dnd.Moveable("moveable3");
+			m4 = new dojo.dnd.Moveable("moveable4", {skip: true});
+		};
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body>
+	<h1>Dojo DnD optional parameters test</h1>
+	<p class="moveable" id="moveable1"><strong>Normal paragraph:</strong> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris augue augue, condimentum nec, viverra et, porttitor sit amet, ligula. Cras malesuada sollicitudin risus. Praesent tincidunt nunc ut enim. Aliquam sit amet libero ac lorem ornare vulputate. Nulla a mauris cursus erat rutrum condimentum. Vivamus sit amet pede in felis sodales adipiscing. Curabitur arcu turpis, pharetra ac, porttitor ac, ultrices nec, quam. [...]
+	<p class="moveable" id="moveable2"><strong>Delayed move by 10px:</strong> Quisque at urna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque ante sem, ullamcorper in, ornare vitae, placerat id, velit. Ut ut tortor vitae lectus dignissim fringilla. Praesent urna enim, laoreet in, lobortis eget, porttitor eget, lacus. Suspendisse et enim. Duis semper nulla a felis. Duis dolor odio, ultrices et, lobortis sed, posuere eu, dolor. Duis es [...]
+	<p class="moveable" id="moveable3"><strong>With form elements:</strong> 
+		<a href="http://dojotoolkit.org">dojotoolkit</a><br />
+		<input type="button" value="Button" />
+		<input type="text" value="abc" />
+		<input type="checkbox" checked />
+		<input type="radio" />
+		<select>
+			<option value="1">one</option>
+			<option value="2">two</option>
+		</select>
+	</p>
+	<p class="moveable" id="moveable4"><strong>With form elements and skip setting:</strong>
+		<a href="http://dojotoolkit.org">dojotoolkit</a>
+		<input type="button" value="Button" />
+		<input type="text" value="abc" />
+		<input type="checkbox" checked />
+		<input type="radio" />
+		<select>
+			<option value="1">one</option>
+			<option value="2">two</option>
+		</select>
+	</p>
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_parent_constraints.html b/dojo/tests/dnd/test_parent_constraints.html
new file mode 100644
index 0000000..31c2661
--- /dev/null
+++ b/dojo/tests/dnd/test_parent_constraints.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo parent constraint test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+
+		body {
+			padding: 1em;
+		}
+
+		.moveable {
+			background: #FFFFBF;
+			border: 1px solid black;
+			width: 300px;
+			padding: 10px 20px;
+			cursor: pointer;
+		}
+
+		.parent {
+			background: #BFECFF;
+			border: 10px solid lightblue;
+			width: 500px;
+			height: 500px;
+			padding: 10px;
+			margin: 10px;
+		}
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+	<script type="text/javascript" src="../../dnd/move.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.dnd.move");
+		var m1, m2, m3, m4;
+		var init = function(){
+			m1 = new dojo.dnd.move.parentConstrainedMoveable("moveable1", {area: "margin", within: true});
+			m2 = new dojo.dnd.move.parentConstrainedMoveable("moveable2", {area: "border", within: true});
+			m3 = new dojo.dnd.move.parentConstrainedMoveable("moveable3", {area: "padding", within: true});
+			m4 = new dojo.dnd.move.parentConstrainedMoveable("moveable4", {area: "content", within: true});
+		};
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body>
+	<h1>Dojo parent constraint test</h1>
+	<div class="parent" id="parent">
+		<div><strong>This is the parent element.</strong> All children will be restricted with <strong>within = true</strong>.</div>
+		<div class="moveable" id="moveable1">I am restricted within my parent's margins.</div>
+		<div class="moveable" id="moveable2">I am restricted within my parent's border.</div>
+		<div class="moveable" id="moveable3">I am restricted within my parent's paddings.</div>
+		<div class="moveable" id="moveable4">I am restricted within my parent's content.</div>
+	</div>
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_parent_constraints_margins.html b/dojo/tests/dnd/test_parent_constraints_margins.html
new file mode 100644
index 0000000..8c9d6dc
--- /dev/null
+++ b/dojo/tests/dnd/test_parent_constraints_margins.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo parent constraint test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+
+		body {
+			padding: 1em;
+		}
+
+		.moveable {
+			background: #FFFFBF;
+			border: 1px solid black;
+			width: 300px;
+			padding: 10px 20px;
+			cursor: pointer;
+			margin: 20px;
+		}
+
+		.parent {
+			background: #BFECFF;
+			border: 10px solid lightblue;
+			width: 500px;
+			height: 500px;
+			padding: 10px;
+			margin: 10px;
+			overflow: hidden;
+		}
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+	<script type="text/javascript" src="../../dnd/move.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.dnd.move");
+		var m7, m8;
+		var init = function(){
+			m7 = new dojo.dnd.move.parentConstrainedMoveable("moveable7", {area: "margin"});
+			m8 = new dojo.dnd.move.parentConstrainedMoveable("moveable8", {area: "margin", within: true});
+		};
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body>
+	<h1>Dojo parent constraint test</h1>
+	<div class="parent" id="parent">
+		<div><strong>This is the parent element.</strong></div>
+		<div class="moveable" id="moveable7"><strong>Paragraph restricted to its parent element:</strong> Sed hendrerit ornare justo. Maecenas ac urna. Maecenas in leo in tortor tincidunt pellentesque. Vivamus augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer eget ipsum vitae quam condimentum tempus. Phasellus augue tortor, pretium nec, bibendum eget, eleifend eget, quam. Nam sem mauris, volutpat eget, ultricies in, consequat nec, tortor. Nu [...]
+		<div class="moveable" id="moveable8"><strong>Paragraph restricted to its parent element (cannot go outside):</strong> Nam nibh. Mauris neque sem, pharetra ac, gravida ac, ultricies eget, quam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Vivamus scelerisque molestie mi. Duis eget ligula nec justo interdum hendrerit. Curabitur tempor convallis enim. In quis lorem. Proin nonummy consectetuer ligula. Curabitur tempor adipiscing lorem. Maecena [...]
+	</div>
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_selector.html b/dojo/tests/dnd/test_selector.html
new file mode 100644
index 0000000..bebdca9
--- /dev/null
+++ b/dojo/tests/dnd/test_selector.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo DnD selector test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "dndDefault.css"; 
+
+		body { padding: 20px; }
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+	<script type="text/javascript" src="../../dnd/common.js"></script>
+	<script type="text/javascript" src="../../dnd/Container.js"></script>
+	<script type="text/javascript" src="../../dnd/Selector.js"></script>
+	<script type="text/javascript">
+		//dojo.require("dojo.dnd.Selector");
+		var c1, c2, c3, c4, c5;
+		var init = function(){
+			c1 = new dojo.dnd.Selector(dojo.byId("container1"), {singular: true});
+			c2 = new dojo.dnd.Selector(dojo.byId("container2"));
+			c3 = new dojo.dnd.Selector(dojo.byId("container3"));
+			c4 = new dojo.dnd.Selector(dojo.byId("container4"));
+			c5 = new dojo.dnd.Selector(dojo.byId("container5"));
+		};
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body>
+	<h1>Dojo DnD selector test</h1>
+	<p>Containers have a notion of a "current container", and one element can be "current". All containers on this page are selectors that allow to select elements.</p>
+	<p>Following selection modes are supported by default:</p>
+	<ul>
+		<li>Simple click — selects a single element, all other elements will be unselected.</li>
+		<li>Ctrl+click — toggles a selection state of an element (use Meta key on Mac).</li>
+		<li>Shift+click — selects a range of elements from the previous anchor to the current element.</li>
+		<li>Ctrl+Shift+click — adds a range of elements from the previous anchor to the current element (use Meta key on Mac).</li>
+	</ul>
+	<h2>DIV selector</h2>
+	<p>This selector can select just one element a time. It was specified during the creation time.</p>
+	<div id="container1" class="container">
+		<div class="dojoDndItem">Item 1</div>
+		<div class="dojoDndItem">Item 2</div>
+		<div class="dojoDndItem">Item 3</div>
+	</div>
+	<h2>UL selector</h2>
+	<ul id="container2" class="container">
+		<li class="dojoDndItem">Item 1</li>
+		<li class="dojoDndItem">Item 2</li>
+		<li class="dojoDndItem">Item 3</li>
+	</ul>
+	<h2>OL selector</h2>
+	<ol id="container3" class="container">
+		<li class="dojoDndItem">Item 1</li>
+		<li class="dojoDndItem">Item 2</li>
+		<li class="dojoDndItem">Item 3</li>
+	</ol>
+	<h2>TABLE selector</h2>
+	<table id="container4" class="container" border="1px solid black">
+		<tr class="dojoDndItem">
+			<td>A</td>
+			<td>row 1</td>
+		</tr>
+		<tr class="dojoDndItem">
+			<td>B</td>
+			<td>row 2</td>
+		</tr>
+		<tr class="dojoDndItem">
+			<td>C</td>
+			<td>row 3</td>
+		</tr>
+	</table>
+	<h2>P selector with SPAN elements</h2>
+	<p>Elements of this container are layed out horizontally.</p>
+	<p id="container5" class="container">
+		<span class="dojoDndItem"> Item 1 </span>
+		<span class="dojoDndItem"> Item 2 </span>
+		<span class="dojoDndItem"> Item 3 </span>
+	</p>
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_selector_markup.html b/dojo/tests/dnd/test_selector_markup.html
new file mode 100644
index 0000000..43c8e9c
--- /dev/null
+++ b/dojo/tests/dnd/test_selector_markup.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo DnD markup selector test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "dndDefault.css"; 
+
+		body { padding: 20px; }
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../../dnd/Selector.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojo.dnd.Selector");
+	</script>
+</head>
+<body>
+	<h1>Dojo DnD markup selector test</h1>
+	<p>This example is functionally equivalent to <a href="test_selector.html">test_selector.html</a> example but is done using the Dojo markup.</p>
+	<p>Containers have a notion of a "current container", and one element can be "current". All containers on this page are selectors that allow to select elements.</p>
+	<p>Following selection modes are supported by default:</p>
+	<ul>
+		<li>Simple click — selects a single element, all other elements will be unselected.</li>
+		<li>Ctrl+click — toggles a selection state of an element (use Meta key on Mac).</li>
+		<li>Shift+click — selects a range of elements from the previous anchor to the current element.</li>
+		<li>Ctrl+Shift+click — adds a range of elements from the previous anchor to the current element (use Meta key on Mac).</li>
+	</ul>
+	<h2>DIV selector</h2>
+	<p>This selector can select just one element a time. It was specified during the creation time.</p>
+	<div dojoType="dojo.dnd.Selector" jsId="c1" singular="true" class="container">
+		<div class="dojoDndItem">Item 1</div>
+		<div class="dojoDndItem">Item 2</div>
+		<div class="dojoDndItem">Item 3</div>
+	</div>
+	<h2>UL selector</h2>
+	<ul dojoType="dojo.dnd.Selector" jsId="c2" class="container">
+		<li class="dojoDndItem">Item 1</li>
+		<li class="dojoDndItem">Item 2</li>
+		<li class="dojoDndItem">Item 3</li>
+	</ul>
+	<h2>OL selector</h2>
+	<ol dojoType="dojo.dnd.Selector" jsId="c3" class="container">
+		<li class="dojoDndItem">Item 1</li>
+		<li class="dojoDndItem">Item 2</li>
+		<li class="dojoDndItem">Item 3</li>
+	</ol>
+	<h2>TABLE selector</h2>
+	<table dojoType="dojo.dnd.Selector" jsId="c4" class="container" border="1px solid black">
+		<tr class="dojoDndItem">
+			<td>A</td>
+			<td>row 1</td>
+		</tr>
+		<tr class="dojoDndItem">
+			<td>B</td>
+			<td>row 2</td>
+		</tr>
+		<tr class="dojoDndItem">
+			<td>C</td>
+			<td>row 3</td>
+		</tr>
+	</table>
+	<h2>P selector with SPAN elements</h2>
+	<p>Elements of this container are layed out horizontally.</p>
+	<p dojoType="dojo.dnd.Selector" jsId="c5" class="container">
+		<span class="dojoDndItem"> Item 1 </span>
+		<span class="dojoDndItem"> Item 2 </span>
+		<span class="dojoDndItem"> Item 3 </span>
+	</p>
+</body>
+</html>
diff --git a/dojo/tests/dnd/test_timed_moveable.html b/dojo/tests/dnd/test_timed_moveable.html
new file mode 100644
index 0000000..fa9da06
--- /dev/null
+++ b/dojo/tests/dnd/test_timed_moveable.html
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo TimedMoveable test</title>
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		@import "dndDefault.css"; 
+
+		body {
+			padding: 1em;
+			color:#666; 
+			background-color:#dedede;
+		}
+
+		#moveable1 {
+			background: #fff;
+			border: 1px solid black;
+			padding:8px; 
+		}
+		#handle1 {
+			background: #333;
+			color: #fff;
+			font-weight:bold; 
+			cursor: pointer;
+			border: 1px solid black;
+		}
+		#moveable2 {
+			background: #fff;
+			position: absolute;
+			width:  200px;
+			height: 200px;
+			left: 100px;
+			top:  100px;
+			padding: 10px 20px;
+			margin: 10px 20px;
+			border: 10px solid black;
+			cursor: pointer;
+			radius:8pt;
+			-moz-border-radius:8pt 8pt; 
+		}
+		#moveable3 {
+			background: #fff;
+			position: absolute;
+			width:  200px;
+			height: 200px;
+			left: 350px;
+			top:  350px;
+			padding: 10px 20px;
+			margin: 10px 20px;
+			border: 10px solid green;
+			cursor: pointer;
+			radius:8pt;
+			-moz-border-radius:8pt 8pt; 
+		}
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug: true"></script>
+	<script type="text/javascript" src="../../dnd/Mover.js"></script>
+	<script type="text/javascript" src="../../dnd/Moveable.js"></script>
+	<script type="text/javascript" src="../../dnd/TimedMoveable.js"></script>
+	<script type="text/javascript" src="../../dnd/move.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.dnd.TimedMoveable");
+		var m1, m2;
+		var init = function(){
+			m1 = new dojo.dnd.TimedMoveable("moveable1", {handle: "handle1"});
+			m2 = new dojo.dnd.TimedMoveable("moveable2");
+			m3 = new dojo.dnd.TimedMoveable("moveable3", {timeout: 500});
+
+			dojo.subscribe("/dnd/move/start", function(mover){ 
+				console.debug("Start move", mover); 	
+			});
+			dojo.subscribe("/dnd/move/stop", function(mover){ 
+				console.debug("Stop move", mover); 	
+			});
+			
+			dojo.connect(m1, "onMoveStart", function(mover){
+				console.debug("Start moving m1", mover); 	
+			});
+			dojo.connect(m1, "onMoveStop", function(mover){
+				console.debug("Stop moving m1", mover); 	
+			});
+		};
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body>
+	<h1>Dojo TimedMoveable test</h1>
+	<p>One moveable (specially marked) is delayed by 500ms (2 fps). Other two are delayed by 40ms (25 fps) — this is the default value.</p>
+	<h2>1st run</h2>
+	<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. A [...]
+	<p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin s [...]
+	<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, el [...]
+	<p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante.  [...]
+	<p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa  [...]
+	<table id="moveable1">
+		<tr><td id="handle1" colspan="2">You can drag the table using this handle.</td></tr>
+		<tr><td>1</td><td>Lorem ipsum dolor sit amet...</td></tr>
+		<tr><td>2</td><td>Mauris vulputate elit a risus...</td></tr>
+		<tr><td>3</td><td>Pellentesque habitant morbi tristique senectus...</td></tr>
+		<tr><td>4</td><td>Duis ac augue rhoncus neque...</td></tr>
+		<tr><td>5</td><td>Quisque egestas turpis. Sed id...</td></tr>
+	</table>	
+	<h2>2nd run</h2>
+	<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. In malesuada ultricies velit. Vestibulum tempor odio vitae diam. Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam. Pellentesque ac lacus. Cras quis est. Etiam suscipit, quam at eleifend nonummy, elit nunc sollicitudin tellus, at mattis est ligula interdum urna. Vivamus id augue sed mi consectetuer dictum. Suspendisse dapibus elit non urna. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. A [...]
+	<p>Mauris vulputate elit a risus. Praesent pellentesque velit ac neque. Fusce ultrices augue vitae orci. Proin a ante. Nulla consectetuer arcu quis est. Suspendisse potenti. Aliquam erat volutpat. Morbi purus augue, eleifend eu, consectetuer sed, tristique ut, wisi. Cras ac tellus. Phasellus adipiscing, libero ac consequat volutpat, ligula purus mollis lectus, ac porttitor ipsum diam non urna. Donec lorem. Pellentesque diam tortor, posuere et, placerat vitae, iaculis et, sapien. Proin s [...]
+	<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec est. Cras semper nunc ut metus. Pellentesque blandit pede at erat. Quisque nonummy leo id metus. Donec mi mi, viverra id, adipiscing vitae, consectetuer ut, elit. In lectus augue, porttitor quis, viverra id, dignissim id, leo. Maecenas sapien. Nam adipiscing sem. Aenean ligula. Etiam vel velit. In mollis cursus dolor. Suspendisse ac nibh id leo tempor posuere. Aliquam sapien tellus, el [...]
+	<p>Duis ac augue rhoncus neque adipiscing feugiat. Donec pulvinar sem vitae neque. Donec commodo metus at ipsum. Cras vel magna vehicula lorem varius consequat. Morbi at enim vitae lectus mollis sodales. Sed tincidunt quam ut mi varius hendrerit. Sed porta arcu non libero. Quisque et wisi. Pellentesque lobortis. Ut enim felis, varius vitae, ornare quis, auctor ut, risus. Ut porta lorem vel quam. Etiam nunc purus, consectetuer non, lobortis eu, fermentum eu, magna. Aenean ultrices ante.  [...]
+	<p>Quisque egestas turpis. Sed id ipsum id libero euismod nonummy. Nam sed dolor. Mauris in turpis. Duis nec wisi eget ante ultrices varius. Ut eget neque. Suspendisse sagittis iaculis tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus at justo. Donec imperdiet, elit et commodo bibendum, leo augue pellentesque arcu, ac dapibus lorem nulla eget erat. In viverra, tellus eu luctus eleifend, urna nibh lobortis sapien, ac pulvinar massa  [...]
+	<div id="moveable2">You can drag this whole paragraph around.</div>
+	<div id="moveable3">My move is delayed by 500ms, which corresponds to 2 fps.</div>
+</body>
+</html>
diff --git a/dojo/tests/fx.html b/dojo/tests/fx.html
new file mode 100644
index 0000000..d8992d6
--- /dev/null
+++ b/dojo/tests/fx.html
@@ -0,0 +1,448 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Testing dojo.fx</title>
+		<script type="text/javascript" src="../dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.require("dojo.fx");
+			dojo.require("dojo.fx.easing");
+
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						function slideTo(t){
+							var s = dojo.fx.slideTo({
+								node: "foo",
+								duration: 500,
+								left: 500,
+								top: 50
+							}).play();
+							var d = new doh.Deferred();
+							dojo.connect(s, "onEnd", function(){
+								doh.is(dojo.style("foo", "left"), 500);
+								doh.is(dojo.style("foo", "top"), 50);
+								with(dojo.byId("foo").style){
+									position = left = top = "";
+								}
+								d.callback(true);
+							});
+							s.play();
+							return d;
+						},
+
+						function wipeOut(t){
+							dojo.byId("foo").style.height = "";
+							var d = new doh.Deferred();
+							var s = dojo.fx.wipeOut({
+								node: "foo",
+								onEnd: function(){
+									doh.t(dojo.style("foo", "height") < 5);
+									d.callback(true);
+								}
+							}).play();
+							return d;
+						},
+						
+						function wipeIn(t){
+							var d = new doh.Deferred();
+							setTimeout(function(){
+								dojo.fx.wipeIn({
+									node: "foo", 
+									onEnd: function(){
+										console.debug(dojo.style("foo", "height"));
+										doh.t(dojo.style("foo", "height") >  10);
+										d.callback(true);
+									}
+								}).play();
+							}, 10);
+							return d;
+						},
+
+						{
+							name: "chain",
+							timeout: 1500,
+							runTest: function(t){
+								dojo.byId("foo").style.height = "0px";
+								var d = new doh.Deferred();
+								var w = dojo.fx.wipeIn({
+									node: "foo",
+									duration: 500
+								});
+								var f = dojo.fadeOut({
+									node: "foo",
+									duration: 500
+								});
+								var a = dojo.fx.chain([w,f]);
+								dojo.connect(a, "onEnd", function(){
+									doh.t((w.status()=="stopped"&&f.status()=="stopped"));
+									d.callback(true);
+								});
+								a.play();
+								return d;
+							}
+						},
+						
+						{
+							name: "combine",
+							timeout: 1500,
+							runTest: function(t){
+								dojo.byId("foo").style.height = "0px";
+								var d = new doh.Deferred();
+								var w = dojo.fx.wipeIn({
+									node: "foo",
+									duration: 500
+								});
+								var f = dojo.fadeIn({
+									node: "foo",
+									duration: 1000
+								});
+								var a = dojo.fx.combine([w,f]);
+								dojo.connect(a, "onEnd", function(){
+									doh.t((w.status()=="stopped"&&f.status()=="stopped"));
+									d.callback(true);
+								});
+								a.play();
+								return d;
+							}
+						},
+						{
+							name:"combineBeforeBegin",
+							timeout:1500,
+							runTest: function(t){
+								var d = new doh.Deferred();
+								var a = dojo.fadeOut({ node:"foo2", duration:400 });
+								var b = dojo.fadeIn({ node:"foo2", duration:400 });
+								var chain = dojo.fx.combine([a,b]);
+								dojo.connect(chain,"beforeBegin",dojo.hitch(d,"callback",true));
+								chain.play();
+								return d;
+							}
+							
+						},
+						{
+							name:"delayTest",
+							timeout:2000,
+							runTest:function(t){
+								var d = new doh.Deferred();
+								var delay = 100;
+								var _anims = [];
+								var nodes = ["a","b","c","d"];
+								dojo.forEach(nodes,function(n){
+									_anims.push(dojo.fadeOut({ node:n, duration:100, delay: delay += 100 }));
+								});
+								var a = dojo.fx.combine(_anims);
+								var timer = (new Date()).getTime();
+								dojo.connect(a,"onEnd",function(){
+									console.warn("delayTest running time:", (new Date()).getTime() - timer, "ms, expected:", a.duration, "ms");
+									d.callback(true);
+								});
+								a.play();
+								return d;	
+							}
+						},
+						{
+							name:"delayTestChain",
+							timeout:2200,
+							runTest:function(t){
+								var d = new doh.Deferred();
+								var delay = 100;
+								var _anims = [];
+								var nodes = ["a","b","c","d"];
+								dojo.forEach(nodes,function(n){
+									_anims.push(dojo.fadeIn({ node:n, duration:100, delay: delay += 100 }));
+								});
+								var a = dojo.fx.chain(_anims);
+								var timer = (new Date()).getTime();
+								dojo.connect(a,"onEnd",function(){
+									console.warn("delayTestChain running time:", (new Date()).getTime() - timer, "ms, expected:", a.duration, "ms");
+									d.callback(true);
+								});
+								a.play();
+								return d;
+							}
+						},
+						{
+							name:"combineOnEnd",
+							timeout:1500,
+							runTest: function(t){
+								var d = new doh.Deferred();
+								var a = dojo.fadeOut({ node:"foo2", duration:400 });
+								var b = dojo.fadeIn({ node:"foo2", duration:400 });
+								var combine = dojo.fx.combine([a,b]);
+								dojo.connect(combine,"onEnd",dojo.hitch(d,"callback",true));
+								combine.play();
+								return d;
+							}
+							
+						},
+						{
+							name:"combineOnPlay",
+							timeout:1500,
+							runTest: function(t){
+								var d = new doh.Deferred();
+								var a = dojo.fadeOut({ node:"foo2", duration:400 });
+								var b = dojo.fadeIn({ node:"foo2", duration:400 });
+								var combine = dojo.fx.combine([a,b]);
+								dojo.connect(combine,"onPlay",dojo.hitch(d,"callback",true));
+								combine.play();
+								return d;
+							}
+							
+						},
+						{
+							name:"chainOnEnd",
+							timeout:1500,
+							runTest: function(t){
+								var d = new doh.Deferred();
+								var a = dojo.fadeOut({ node:"foo2", duration:400 });
+								var b = dojo.fadeIn({ node:"foo2", duration:400 });
+								var chain = dojo.fx.chain([a,b]);
+								dojo.connect(chain,"onEnd",dojo.hitch(d,"callback",true));
+								chain.play();
+								return d;
+							}
+							
+						},
+						{
+							name:"chainOnPlay",
+							timeout:1500,
+							runTest: function(t){
+
+								var d = new doh.Deferred();
+								var a = dojo.fadeOut({ node:"foo2", duration:200 });
+								var b = dojo.fadeIn({ node:"foo2", duration:200 });
+								var chain = dojo.fx.chain([a,b]);
+								dojo.connect(chain,"onPlay",dojo.hitch(d,"callback",true));
+								chain.play();
+								return d;
+							}
+							
+						},
+						
+						{
+							name:"stopDelay",
+							timeout:1500,
+							runTest: function(t){
+								
+								var d = new doh.Deferred();
+								var a = dojo.fadeOut({ node: "foo2", delay:400 });
+								dojo.connect(a, "onPlay", dojo.hitch(d, "errback", true));
+								a.play(); 
+								a.stop();
+								setTimeout(function(){
+									d.callback(true);
+								}, 500);
+								return d;
+							}
+						},
+						
+						{
+							name:"stopDelayPassed",
+							timeout:1500,
+							runTest: function(t){
+							
+								var d = new doh.Deferred();
+								var b = dojo.fadeIn({ node: "foo2" });
+								dojo.connect(b, "onPlay", dojo.hitch(d, "errback", true));
+								b.play(400); 
+								b.stop();
+								setTimeout(function(){
+									d.callback(true);
+								}, 600);
+								return d;
+							}
+							
+						},
+						
+						function Toggler(){
+							var d = new doh.Deferred();
+							var t = new dojo.fx.Toggler({
+							    node: "foo",
+							    hideDuration: 100,
+								hideFunc: dojo.fx.wipeOut,
+								showFunc: dojo.fx.wipeIn 
+							});
+							t.hide();
+							setTimeout(function(){
+								var sa = t.show();
+								dojo.connect(sa, "onEnd", dojo.hitch(d, "callback", true));
+							}, 50);
+							return d;
+						},
+						
+						function combineChain(t){
+							// test combining two chained() animations
+							var anim1 = dojo.fx.chain([
+								dojo.fadeIn({ node:"chained" }),
+								dojo.fadeOut({ node:"chained" })
+							]);
+							var anim2 = dojo.fx.chain([
+								dojo.fadeOut({ node:"chainedtoo" }),
+								dojo.fadeIn({ node:"chainedtoo" })
+							]);
+							
+							var anim = dojo.fx.combine([anim1, anim2]);
+
+							var d = new doh.Deferred();
+							dojo.connect(anim, "onEnd", dojo.hitch(d, "callback", true));
+							anim.play();
+						},
+						
+						function chainCombine(t){
+							// test chaining two combined() animations
+							var anim1 = dojo.fx.combine([
+								dojo.fadeIn({ node:"chained" }),
+								dojo.fadeOut({ node:"chainedtoo" })
+							]);
+							var anim2 = dojo.fx.combine([
+								dojo.fadeOut({ node:"chained" }),
+								dojo.fadeIn({ node:"chainedtoo" })
+							]);
+							
+							var anim = dojo.fx.chain([anim1, anim2]);
+
+							var d = new doh.Deferred();
+							dojo.connect(anim, "onEnd", dojo.hitch(d, "callback", true));
+							anim.play();
+
+						},
+						
+						function easingNames(t){
+							for(var i in dojo.fx.easing){
+								t.assertTrue(dojo.isFunction(dojo.fx.easing[i]));
+							}
+						},
+						
+						function easingReturns(t){
+							for(var i in dojo.fx.easing){
+								t.assertTrue(!isNaN(dojo.fx.easing[i](0.5)));
+							}
+						},
+						
+						{
+							name:"onendStatus-chain",
+							timeout:1500,
+							runTest: function(t){
+								var d = new doh.Deferred;
+								
+								var a1 = dojo.fadeOut({ node:"a1" });
+								var a2 = dojo.fadeOut({ node:"a2" });
+								
+								var anim = dojo.fx.chain([a1, a2]);
+								dojo.connect(anim, "onEnd", function(){
+									t.is("stopped", a1.status());
+									t.is("stopped", a2.status());
+									t.is("stopped", anim.status());
+									d.callback(true);
+								});
+								
+								anim.play();
+								
+								return d;
+							}
+						},	
+						{
+							name:"onendStatus-combine",
+							timeout:1500,
+							runTest: function(t){
+								var d = new doh.Deferred;
+
+								var a1 = dojo.fadeOut({ node:"a1" });
+								var a2 = dojo.fadeOut({ node:"a2" });
+
+								var anim = dojo.fx.combine([a1, a2]);
+								dojo.connect(anim, "onEnd", function(){
+									t.is("stopped", a1.status());
+									t.is("stopped", a2.status());
+									setTimeout(function(){
+										t.is("stopped", anim.status());
+										d.callback(true);	
+									}, 10);
+								});
+
+								anim.play();
+								return d;
+							}
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css">
+			@import "../resources/dojo.css";
+
+			body {
+				text-shadow: 0px 0px;
+				margin: 1em;
+				background-color: #DEDEDE;
+			}
+
+			.box {
+				color: #292929;
+				/* color: #424242; */
+				/* text-align: left; */
+				width: 300px;
+				border: 1px solid #BABABA;
+				background-color: white;
+				padding-left: 10px;
+				padding-right: 10px;
+				margin-left: 10px;
+				margin-bottom: 1em;
+				-o-border-radius: 10px;
+				-moz-border-radius: 12px;
+				-webkit-border-radius: 10px;
+				-webkit-box-shadow: 0px 3px 7px #adadad;
+				/* -opera-border-radius: 10px; */
+				border-radius: 10px;
+				-moz-box-sizing: border-box;
+				-opera-sizing: border-box;
+				-webkit-box-sizing: border-box;
+				-khtml-box-sizing: border-box;
+				box-sizing: border-box;
+				overflow: hidden;
+				/* position: absolute; */
+			}
+		</style>
+	</head>
+	<body>
+		<div class="box" id="a">a</div><div class="box" id="b">b</div>
+		<div class="box" id="c">c</div><div class="box" id="d">d</div>
+	
+		<div id="foo" class="box">
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+			Proin porta rutrum lacus. Etiam consequat scelerisque quam. Nulla
+			facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+			semper iaculis.  Sed molestie tortor at ipsum. Morbi dictum rutrum
+			magna. Sed vitae risus.
+			</p>
+			<p>
+			Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer
+			lorem nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean
+			id mi in massa bibendum suscipit. Integer eros. Nullam suscipit
+			mauris. In pellentesque. Mauris ipsum est, pharetra semper,
+			pharetra in, viverra quis, tellus. Etiam purus. Quisque egestas,
+			tortor ac cursus lacinia, felis leo adipiscing nisi, et rhoncus
+			elit dolor eget eros. Fusce ut quam. Suspendisse eleifend leo vitae
+			ligula. Nulla facilisi. Nulla rutrum, erat vitae lacinia dictum,
+			pede purus imperdiet lacus, ut semper velit ante id metus. Praesent
+			massa dolor, porttitor sed, pulvinar in, consequat ut, leo. Nullam
+			nec est. Aenean id risus blandit tortor pharetra congue.
+			Suspendisse pulvinar.
+			</p>
+		</div>
+		<div id="foo2">foo2</div>
+		
+		<div>
+			<p id="chained">foo</p><p id="chainedtoo">bar</p>
+		</div>
+		
+		<p id="a1">p</p><p id="a2">p</p>
+		
+	</body>
+</html>
diff --git a/dojo/tests/fx.js b/dojo/tests/fx.js
new file mode 100644
index 0000000..9d17b05
--- /dev/null
+++ b/dojo/tests/fx.js
@@ -0,0 +1,5 @@
+dojo.provide("tests.fx");
+if(dojo.isBrowser){
+	doh.registerUrl("tests.fx", dojo.moduleUrl("tests", "fx.html"), 30000);
+	doh.registerUrl("tests.NodeList-fx", dojo.moduleUrl("tests", "NodeList-fx.html"));
+}
diff --git a/dojo/tests/hash.js b/dojo/tests/hash.js
new file mode 100644
index 0000000..408e3f7
--- /dev/null
+++ b/dojo/tests/hash.js
@@ -0,0 +1,324 @@
+dojo.provide("tests.hash");
+dojo.require("dojo.hash");
+
+(function(){
+
+// utilities for the tests:
+	function setHash(h){
+		h = h || "";
+		location.replace('#'+h);
+	}
+	
+	function getHash(){
+		var h = location.href, i = h.indexOf("#");
+		return (i >= 0) ? h.substring(i + 1) : "";
+	}
+
+	tests.register("tests.hash", [
+		// hash as an empty string.
+		{
+			name: "Getting an empty hash",
+			setUp: function(){
+				setHash();
+			},
+			runTest: function(t){
+				t.is('', dojo.hash());
+			}
+		},
+		{
+			name: "Setting an empty hash",
+			setUp: function(){
+				dojo.hash('');
+			},
+			runTest: function(t){
+				t.is('', getHash());
+			}
+		},
+		// hash as "test"
+		{
+			name: "Getting the hash of 'test'",
+			setUp: function(){
+				setHash('test');
+			},
+			runTest: function(t){
+				t.is('test', dojo.hash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Setting the hash to 'test'",
+			setUp: function(){
+				dojo.hash('test');
+			},
+			runTest: function(t){
+				t.is('test', getHash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		// hash with spaces
+		{
+			name: "Getting the hash of 'test%20with%20spaces'",
+			setUp: function(){
+				setHash('test%20with%20spaces');
+			},
+			runTest: function(t){
+				t.is('test%20with%20spaces', dojo.hash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Setting the hash of 'test%20with%20spaces'",
+			setUp: function(){
+				setHash('test%20with%20spaces');
+			},
+			runTest: function(t){
+				t.is('test%20with%20spaces', getHash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		// hash with encoded hash
+		{
+			name: "Getting the hash of 'test%23with%23encoded%23hashes'",
+			setUp: function(){
+				setHash('test%23with%23encoded%23hashes');
+			},
+			runTest: function(t){
+				t.is('test%23with%23encoded%23hashes', dojo.hash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Setting the hash of 'test%23with%23encoded%23hashes'",
+			setUp: function(){
+				setHash('test%23with%23encoded%23hashes');
+			},
+			runTest: function(t){
+				t.is('test%23with%23encoded%23hashes', getHash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		// hash with plus character: test+with+pluses
+		{
+			name: "Getting the hash of 'test+with+pluses'",
+			setUp: function(){
+				setHash('test+with+pluses');
+			},
+			runTest: function(t){
+				t.is('test+with+pluses', dojo.hash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Setting the hash to 'test+with+pluses'",
+			setUp: function(){
+				dojo.hash('test+with+pluses');
+			},
+			runTest: function(t){
+				t.is('test+with+pluses', getHash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		// hash with leading space
+		{
+			name: "Getting the hash of '%20leadingSpace'",
+			setUp: function(){
+				setHash('%20leadingSpace');
+			},
+			runTest: function(t){
+				t.is('%20leadingSpace', dojo.hash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Setting the hash to '%20leadingSpace'",
+			setUp: function(){
+				dojo.hash('%20leadingSpace');
+			},
+			runTest: function(t){
+				t.is('%20leadingSpace', getHash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		
+		// hash with trailing space:
+		{
+			name: "Getting the hash of 'trailingSpace%20'",
+			setUp: function(){
+				setHash('trailingSpace%20');
+			},
+			runTest: function(t){
+				t.is('trailingSpace%20', dojo.hash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Setting the hash to 'trailingSpace%20'",
+			setUp: function(){
+				dojo.hash('trailingSpace%20');
+			},
+			runTest: function(t){
+				t.is('trailingSpace%20', getHash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		// hash with underscores.
+		{
+			name: "Getting the hash of 'under_score'",
+			setUp: function(){
+				setHash('under_score');
+			},
+			runTest: function(t){
+				t.is('under_score', dojo.hash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Setting the hash to 'under_score'",
+			setUp: function(){
+				dojo.hash('under_score');
+			},
+			runTest: function(t){
+				t.is('under_score', getHash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Getting the hash of 'extra&instring'",
+			setUp: function(){
+				setHash("extra&instring");
+			},
+			runTest: function(t){
+				t.is("extra&instring", dojo.hash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Setting the hash to 'extra&instring'",
+			setUp: function(){
+				dojo.hash('extra&instring');
+			},
+			runTest: function(t){
+				t.is('extra&instring', getHash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Getting the hash of 'extra?instring'",
+			setUp: function(){
+				setHash('extra?instring');
+			},
+			runTest: function(t){
+				t.is('extra?instring', dojo.hash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Setting the hash of 'extra?instring'",
+			setUp: function(){
+				dojo.hash('extra?instring');
+			},
+			runTest: function(t){
+				t.is('extra?instring', getHash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Getting the hash resembling a query parameter ('?testa=3&testb=test')",
+			setUp: function(){
+				setHash('?testa=3&testb=test');
+			},
+			runTest: function(t){
+				t.is('?testa=3&testb=test', dojo.hash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Setting the hash resembling a query parameter ('?testa=3&testb=test')",
+			setUp: function(){
+				dojo.hash('?testa=3&testb=test');
+			},
+			runTest: function(t){
+				t.is('?testa=3&testb=test', getHash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			name: "Setting the hash to '#leadingHash' should result in the hash being 'leadingHash'",
+			setUp: function(){
+				dojo.hash('#leadingHash');
+			},
+			runTest: function(t){
+				t.is('leadingHash', getHash());
+			},
+			tearDown: function(){
+				setHash();
+			}
+		},
+		{
+			_s: null, // used for the subscriber.
+		
+			name: "Hash change publishes to '/dojo/hashchange'",
+			setUp: function(t){
+				setHash();
+			},
+			runTest: function(t){
+				var d = new doh.Deferred();
+				this._s = dojo.subscribe('/dojo/hashchange', null, function(value){
+					try {
+						doh.assertEqual('test', value);
+						d.callback(true);
+					} catch(e){
+						d.errback(e);
+					}
+				});
+				
+				dojo.hash('test');
+				return d;
+			},
+			tearDown: function(){
+				dojo.unsubscribe(this._s);
+				setHash();
+			}
+		}	
+	]);
+})();
diff --git a/dojo/tests/html.js b/dojo/tests/html.js
new file mode 100644
index 0000000..4652004
--- /dev/null
+++ b/dojo/tests/html.js
@@ -0,0 +1,4 @@
+dojo.provide("tests.html");
+if(dojo.isBrowser){
+	doh.registerUrl("tests.html", dojo.moduleUrl("tests", "html/test_set.html"));
+}
diff --git a/dojo/tests/html/test_set.html b/dojo/tests/html/test_set.html
new file mode 100644
index 0000000..9f312b7
--- /dev/null
+++ b/dojo/tests/html/test_set.html
@@ -0,0 +1,500 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojo.html.set test</title>
+
+	<script src='../../dojo.js' djConfig='isDebug:true, parseOnLoad:false'></script>
+	<script src='../../html.js'></script>
+	<script src='../../../util/doh/runner.js'></script>
+	<script>
+		dojo.require('doh.runner');
+		dojo.require('dojo.html');
+		dojo.require('dojo.NodeList-html');
+
+		/* test goals
+		 * injecting content as string, node, nodelist. 
+		 * injecting exotic nodes/markup e.g. table rows, lists
+		 * injecting whole html documents (extractContent option)
+		 * parsing resulting content
+		 
+		 * cleanup when setting content
+		*/
+		dojo.declare("dojo.html.test.SimpleThing", null, {
+			constructor: function(params, node) {
+				node.setAttribute("test", "ok");
+			}
+		});
+		
+		dojo.declare("dojo.html.test.ParserInstantiateTester", null, {
+			constructor: function(params, node) {
+				node.setAttribute("test", "ok");
+			}
+		});
+		dojo.declare("dojo.html.test.DeclarativeContentSetter", dojo.html._ContentSetter, {
+			postscript: function() {
+				this.set();
+			}
+		});
+		
+		
+		dojo.addOnLoad(function(){
+
+			function ieTrimSpaceBetweenTags(str){
+				return str.replace(/(<[a-z]*[^>]*>)\s*/ig, "$1");
+			}
+
+
+			targetNode = null; 
+			
+			doh.register("basicChecks", [
+					{
+						name: 'set',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							targetNode = dojo.byId("pane1");
+							var msg = "Simple No-params Test";
+							console.log("targetNode has content: ", targetNode.innerHTML);
+							var result = "";
+							dojo.html.set(
+								targetNode,
+								msg
+							);
+							console.log("after set, targetNode has content: ", targetNode.innerHTML);
+							t.assertEqual(msg, targetNode.innerHTML);
+						}
+					},
+					{
+						name: 'setContentWithOnEnd',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							targetNode = dojo.byId("pane1");
+							var msg = "setContentWithOnEnd Test";
+							var result = false;
+							dojo.html.set(
+								targetNode,
+								msg, 
+								{
+									onEnd: function() {
+										dojo.getObject(this.declaredClass).prototype.onEnd.call(this);
+										result = true;
+									}
+								}
+							);
+							t.assertEqual(msg, targetNode.innerHTML);
+							t.assertTrue(result);
+						}
+					},
+					{
+						name: 'setContent_with_parsing',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var cont = '<div dojoType="dojo.html.test.SimpleThing" jsId="ifrs" data="{}"></div>';
+							dojo.html.set(
+								dojo.byId("pane1"),
+								cont,
+								{	
+									postscript: function() {
+										this.set();
+
+										t.assertTrue(typeof ifrs != "undefined" && ifrs.declaredClass=="dojo.html.test.SimpleThing");
+										t.assertTrue(this.parseResults.length > 0);
+									},
+									parseContent: true
+								}
+							);
+						}
+					},
+					{
+						name: 'emptyElement',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var msg = "setContentWithOnEnd Test";
+							var node = dojo.byId("pane1");
+							node.innerHTML = '<div><span>just</span>some test<br/></div>text';
+							var cNodes = node.childNodes.length;
+							
+							dojo.html._emptyNode(dojo.byId("pane1"));
+							t.assertTrue(node.childNodes.length == 0 && node.innerHTML == "");
+						}
+					},
+					// the following tests use the _emptyNode function, so ensure it passes before
+					// head-scratching over any failures that follow
+					{
+						name: 'changeContentTRHead',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							targetNode = dojo.query('table#tableTest > thead > tr')[0];
+							
+							var html = "<td><div>This</div>Should<u>Work</u></td>";
+							dojo.html.set(
+								targetNode, 
+								html, 
+								{
+									"testname": "basicChecks changeContentTRHead"
+								}
+							);
+							var res = ieTrimSpaceBetweenTags(targetNode.innerHTML.toLowerCase());
+							t.assertEqual(html.toLowerCase(), res);
+						},
+						tearDown: function(){
+							dojo.html._emptyNode(targetNode);
+						}
+					},
+					{
+						name: 'changeContentTHead',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							targetNode = dojo.query('table#tableTest > thead')[0];
+
+							var html = "<tr><td><div>This</div>Should<u>Work</u></td></tr>";
+							dojo.html.set(
+								targetNode, 
+								html, 
+								{
+									"testname": "basicChecks changeContentTHead"
+								}
+							);
+							var res = ieTrimSpaceBetweenTags(targetNode.innerHTML.toLowerCase());
+							t.assertEqual(html.toLowerCase(), res);
+						},
+						tearDown: function(){
+							dojo.html._emptyNode(targetNode);
+						}
+					},
+					{
+						name: 'changeContentTRBody',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							targetNode = dojo.query('table#tableTest > tbody > tr')[0];
+							var html = "<td><div>This</div>Should<u>Work</u></td>";
+							dojo.html.set(
+								targetNode,
+								html, 
+								{
+									"testname": "basicChecks changeContentTRBody"
+								});
+							var res = ieTrimSpaceBetweenTags(targetNode.innerHTML.toLowerCase());
+							t.assertEqual(html.toLowerCase(), res);
+						},
+						tearDown: function(){
+							dojo.html._emptyNode(targetNode);
+						}
+					},
+					{
+						name: 'changeContentTBody',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							targetNode = dojo.query('table#tableTest > tbody')[0];
+							var html = "<tr><td><div>This</div>Should<u>Work</u></td></tr>";
+							dojo.html.set(
+								targetNode, html, 
+								{
+									"testname": "basicChecks changeContentTBody"
+								});
+							var res = ieTrimSpaceBetweenTags(targetNode.innerHTML.toLowerCase());
+							t.assertEqual(html.toLowerCase(), res);
+						},
+						tearDown: function(){
+							dojo.html._emptyNode(targetNode);
+						}
+					},
+					{
+						name: 'changeContentTable',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							targetNode = dojo.query('table#tableTest')[0];
+							var html = "<tbody><tr><td><div>This</div>Should<u>Work</u></td></tr></tbody>";
+							dojo.html.set(
+								targetNode, html, 
+								{
+									"testname": "basicChecks changeContentTable"
+								});
+							var res = ieTrimSpaceBetweenTags(targetNode.innerHTML.toLowerCase());
+							t.assertEqual(html.toLowerCase(), res);
+						},
+						tearDown: function(){
+							dojo.html._emptyNode(targetNode);
+						}
+					},
+					{
+						name: 'setNodeList',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var tmpUL = dojo.create("ul");
+							dojo.create("li", { innerHTML: "item 1" }, tmpUL);
+							dojo.create("li", { innerHTML: "item 2" }, tmpUL);
+							console.log("ul content: ", tmpUL.innerHTML, tmpUL.childNodes.length);
+							targetNode = dojo.byId("pane1");
+							dojo.html.set(
+								targetNode, tmpUL.childNodes, 
+								{
+									"testname": "basicChecks setNodeList"
+								});
+							var res = dojo.query("li", dojo.byId("pane1")).length
+							t.assertEqual(2, res);
+						},
+						tearDown: function(){
+							dojo.html._emptyNode(targetNode);
+						}
+					},
+					{
+						name: 'setMixedContent',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							
+							targetNode = dojo.byId("pane1");
+							var html = '<h4>See Jane</h4>'
+							 + 'Look at her <span>Run</span>!';
+							dojo.html.set(
+								targetNode, html, 
+								{
+									"testname": "basicChecks setMixedContent"
+								});
+							var res = ieTrimSpaceBetweenTags(targetNode.innerHTML.toLowerCase());
+							t.assertEqual(html.toLowerCase(), res);
+						},
+						tearDown: function(){
+							dojo.html._emptyNode(targetNode);
+						}
+					},
+					{
+						name: 'extractContent',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							targetNode = dojo.byId("pane1");
+							var html = ''
+							+'<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">'
+							+'<html>											'
+							+'	<head>											'
+							+'		<title>										'
+							+'			the title									 '
+							+'		</title>									'
+							+'	</head>											'
+							+'	<body>											'
+							+'		<p>											'
+							+'			This is the <b>Good Stuff</b><br>		'
+							+'		</p>										'
+							+'	</body>											'
+							+'</html>											';
+							
+							dojo.html.set(
+								targetNode, html, 
+								{
+									"testname": "basicChecks changeContentTable", 
+									extractContent: true
+								});
+							t.assertTrue(targetNode.innerHTML.indexOf("title") == -1);
+							t.assertTrue(dojo.query("*", targetNode).length == 3);
+						},
+						tearDown: function(){
+							dojo.html._emptyNode(targetNode);
+						}
+					}
+				]); 
+				doh.register("nodelistExtension", [
+					{
+						name: 'nodelistHtml',
+						runTest: function(t){
+							console.log("nodelistExtension: " + this.name);
+
+							dojo.query(".zork").html("<li dojoType='dojo.html.test.ParserInstantiateTester'>1</li><li dojoType='dojo.html.test.ParserInstantiateTester'>2</li><li dojoType='dojo.html.test.ParserInstantiateTester'>3</li>", 
+							{ 
+								parseContent: true, 
+								onBegin: function() {
+									this.content = this.content.replace(/([0-9])/g, "MOOO");
+									this.inherited("onBegin", arguments);
+								}
+							}).removeClass("notdone").addClass("done");
+							
+							var liNodes = dojo.query(".zork > li");
+							
+							// test to make sure three li's were added to class="zork" node (3x 3 set li's)
+							t.assertEqual(9, liNodes.length);
+
+							// test the innerHTML's got replaced in our onBegin
+							t.assertTrue( liNodes.every(function(n) { return n.innerHTML.match(/MOOO/) }) ); 
+							console.log(this.name + ": innerHTML.match subtest was ok");
+							
+							// test the parent elements got the correct className
+							t.assertTrue( dojo.query(".zork").every(function(n) { return n.className == "zork done"; }) );
+							console.log(this.name + ": li.className subtest was ok");
+							
+							// and test the parser correctly created object from the child nodes 
+							// ...they should all have a test attribute now
+							t.assertTrue( liNodes.every(function(n) { return n.getAttribute("test") == "ok"; }) );
+							console.log(this.name + ": Tester instantiation subtest(getAttribute) was ok");
+							
+						},
+						tearDown: function(){
+							// dojo.html._emptyNode(targetNode);
+						}
+					}, 
+					{
+						name: "nodeListSimple",
+						runTest: function(t){
+							var txt = "foo";
+							dojo.query("#simpleText").html("<p>"+txt+"</p>");
+
+							// check if its there at all
+							var len = dojo.query("#simpleText p").length;
+							t.assertEqual(1, len);
+							
+							// check the inner html is right:
+							var p = dojo.query("#simpleText p")[0];
+							t.assertTrue( p && p.innerHTML == txt );
+						}
+					}
+				]);
+				doh.register("fromMarkup", [
+					{
+						name: 'contentOpFromMarkup',
+						runTest: function(t){
+							console.log("fromMarkup: " + this.name);
+
+							dojo.parser.parse("markupSetContentOp");
+							t.assertTrue(dojo.byId("markupPane").innerHTML == "markupSetContentOp: new node content");
+						},
+						tearDown: function(){
+							dojo.byId("markupPane").innerHTML = "initial content";
+						}
+					},
+					{
+						name: 'extendedContentOpFromMarkup',
+						runTest: function(t){
+							console.log("fromMarkup: " + this.name);
+
+							dojo.parser.parse("markupSetContentOpX");
+
+							t.assertTrue(dojo.byId("markupPane").innerHTML == "markupSetContentOpX: new node content".toUpperCase());
+						},
+						tearDown: function(){
+							dojo.byId("markupPane").innerHTML = "initial content";
+						}
+					}
+				]);
+				doh.register("reuse", [
+					{
+						name: 'ContentSetterReUse',
+						runTest: function(t){
+							console.log("fromMarkup: " + this.name);
+
+							targetNode = dojo.byId('pane1');
+							var args = [
+								[
+									"simple"
+								], 
+								[
+									'<div dojoType="dojo.html.test.SimpleThing" jsId="id00">parsed content</div>', 
+									{
+										parseContent: true
+									}
+								],
+								[
+									'<div dojoType="dojo.html.test.SimpleThing" jsId="id01">parsed content</div>',
+									{
+										parseContent: true
+									}
+								]
+							];
+							var setter = new dojo.html._ContentSetter({
+								node: targetNode
+							});
+							dojo.forEach(args, function(applyArgs) {
+								setter.node = targetNode; 
+								setter.set.apply(setter, applyArgs); 
+								setter.tearDown();
+							});
+							t.assertTrue(id00 && id01); 
+							// check we cleaned up after ourselves
+							t.assertFalse(setter.parseResults);
+						},
+						tearDown: function(){
+							dojo.byId("markupPane").innerHTML = "initial content";
+						}
+					}
+				]);
+
+
+
+			doh.run();
+		}); 
+	</script>
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+
+		.box {
+			border: 1px solid black;
+			height: 190px;
+			width: 80%;
+			overflow: auto;
+		}
+		.zork {
+			width: 200px;
+			margin: 10px;
+			list-style-type: none;
+		}
+		.notdone {
+			color: #999; background-color: #ccc;
+		}
+		.done {
+			color: #fff; background-color: #090;
+		}
+		.done li {
+			border: 1px; background-color: orange;
+			width: 180px;
+		}
+		.red {
+			color: red;
+		}
+
+	</style>
+</head>
+<body class='tundra'>
+	<h1>dojo.html.set</h1>
+
+	<div id="pane1"></div>
+	<div id="pane2"></div>
+	<table id='tableTest' class='box'>
+		<thead>
+			<tr>
+				<td></td>
+			</tr>
+		</thead>
+		<tbody>
+			<tr>
+				<td></td>
+			</tr>
+		<tbody>
+	</table>
+	<ul class="zork notdone">initial content</ul>
+	<ul class="zork notdone">initial content</ul>
+	<ul class="zork notdone">initial content</ul>
+
+	<div id="markupPane">initial content</div>
+	<div id="markupSetContentOp">
+		<div dojoType="dojo.html.test.DeclarativeContentSetter" node="markupPane" content="markupSetContentOp: new node content"></div>
+	</div>
+	<div id="markupSetContentOpX">
+		<div dojoType="dojo.html.test.DeclarativeContentSetter" jsId="markupSetContentOpX_setter" node="markupPane" content="markupSetContentOpX: new node content">
+		<script type="dojo/method" event="onBegin">
+			this.content = this.content.toUpperCase();
+			console.log(this.id + ", made my content look like this:" + this.content);
+		</script>
+		<script type="dojo/method" event="onFoo">
+			console.log("dojo/method supplied onBegin");
+			this.content = this.content.toUpperCase();
+		</script>
+		</div>
+	</div>
+	<div id="another">
+		<div id="myTest9" dojoType="dojo.html.test.DeclarativeContentSetter">
+			Some content
+			<script type="dojo/method">
+				console.log("parsed me!");
+			</script>
+		</div>
+	</div>
+	<h1 id="simpleText">test</h1>
+</body>
+</html>
diff --git a/dojo/tests/i18n.js b/dojo/tests/i18n.js
new file mode 100644
index 0000000..7997755
--- /dev/null
+++ b/dojo/tests/i18n.js
@@ -0,0 +1,84 @@
+dojo.provide("tests.i18n");
+
+dojo.require("dojo.i18n");
+
+(function(){
+	var setUp = function(locale){
+		return function(){
+			dojo.requireLocalization("tests","salutations",locale);
+		}
+	}
+
+	var getTest = function(value, locale){
+		return function(){
+			doh.assertEqual(value, dojo.i18n.getLocalization("tests", "salutations", locale).hello);
+		}
+	}
+
+	var getFixture = function(locale, value){
+		return {
+			name: "salutations-"+locale,
+			setUp: setUp(locale),
+			runTest: getTest(value, locale)
+		};
+	}
+
+	var testSet = [
+	/* needs dojo.string,
+		// This doesn't actually test anything, it just gives an impressive list of translated output to the console
+		// See the 'salutations' test for something verifyable
+		function fun(t){
+			var salutations_default = dojo.i18n.getLocalization("tests", "salutations");
+			console.debug("In the local language: "+salutations_default.hello);
+
+			var salutations_en = dojo.i18n.getLocalization("tests", "salutations", "en");
+
+			for (i in tests.nls.salutations) {
+				var loc = i.replace('_', '-');
+				var salutations = dojo.i18n.getLocalization("tests", "salutations", loc);
+				var language_as_english = salutations_en[loc];
+				var language_as_native = salutations[loc];
+				var hello_dojo = dojo.string.substitute(salutations.hello_dojo, salutations);
+				if (!dojo.i18n.isLeftToRight(loc)) {
+					var RLE = "\u202b";
+					var PDF = "\u202c";
+					hello_dojo = RLE + hello_dojo + PDF;					
+				}
+				hello_dojo += "\t[" + loc + "]";
+				if(language_as_english){hello_dojo += " " + language_as_english;}
+				if(language_as_native){hello_dojo += " (" + language_as_native + ")";}
+				console.debug(hello_dojo);
+			}
+
+			t.assertTrue(true);
+		},
+	*/
+
+		// Test on-the-fly loading of localized string bundles from different locales, and
+		// the expected inheritance behavior
+
+		// Locale which overrides root translation
+		getFixture("de", "Hallo"),
+		// Locale which does not override root translation
+		getFixture("en", "Hello"),
+		// Locale which overrides its parent
+		getFixture("en-au", "G'day"),
+		// Locale which does not override its parent
+		getFixture("en-us", "Hello"),
+		// Locale which overrides its parent
+		getFixture("en-us-texas", "Howdy"),
+		// 3rd level variant which overrides its parent
+		getFixture("en-us-new_york", "Hello"),
+		// Locale which overrides its grandparent
+		getFixture("en-us-new_york-brooklyn", "Yo"),
+		// Locale which does not have any translation available
+		getFixture("xx", "Hello"),
+		// A double-byte string.  Everything should be read in as UTF-8 and treated as unicode within Javascript.
+		getFixture("zh-cn", "\u4f60\u597d")
+	];
+	testSet[testSet.length-1].tearDown = function(){
+		// Clean up bundles that should not exist if the test is re-run.
+		delete tests.nls.salutations;
+	};
+	tests.register("tests.i18n", testSet);
+})();
diff --git a/dojo/tests/io/iframe.html b/dojo/tests/io/iframe.html
new file mode 100644
index 0000000..7e465ad
--- /dev/null
+++ b/dojo/tests/io/iframe.html
@@ -0,0 +1,164 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Testing dojo.io.iframe</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.require("dojo.io.iframe");
+
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						function ioIframeGetText(t){
+							var d = new doh.Deferred();
+							var td = dojo.io.iframe.send({
+								url: "iframeResponse.text.html",
+								method: "GET",
+								timeoutSeconds: 5,
+								preventCache: true,
+								handle: function(res, ioArgs){
+									if(!(res instanceof Error) && 
+										t.is("iframe succeeded", res)){
+										d.callback(true);
+									}else{
+										d.errback(false);
+									}								
+								}
+							});
+							return d;							
+						},
+
+						function ioIframeGetJson(t){
+							var d = new doh.Deferred();
+							var td = dojo.io.iframe.send({
+								url: "iframeResponse.json.html",
+								method: "GET",
+								timeoutSeconds: 5,
+								preventCache: true,
+								handleAs: "json",
+								handle: function(res, ioArgs){
+									if(!(res instanceof Error) && 
+										t.is("blue", res.color)){
+										d.callback(true);
+									}else{
+										d.errback(false);
+									}								
+								}
+							});
+							return d;							
+						},
+
+						function ioIframeGetJavascript(t){
+							var d = new doh.Deferred();
+							var td = dojo.io.iframe.send({
+								url: "iframeResponse.js.html",
+								method: "GET",
+								timeoutSeconds: 5,
+								preventCache: true,
+								handleAs: "javascript",
+								handle: function(res, ioArgs){
+									console.log("RES: ", res);
+									if(!(res instanceof Error) && 
+										t.is(42, window.iframeTestingFunction())){
+										d.callback(true);
+									}else{
+										d.errback(false);
+									}								
+								}
+							});
+							return d;							
+						},
+
+						function ioIframeGetHtml(t){
+							var d = new doh.Deferred();
+							var td = dojo.io.iframe.send({
+								url: "iframeResponse.html",
+								method: "GET",
+								timeoutSeconds: 5,
+								preventCache: true,
+								handleAs: "html",
+								handle: function(res, ioArgs){
+									if(!(res instanceof Error) && 
+										t.is("SUCCESSFUL HTML response", res.getElementsByTagName("h1")[0].innerHTML)){
+										d.callback(true);
+									}else{
+										d.errback(false);
+									}								
+								}
+							});
+							return d;							
+						},
+
+						function ioIframeGetXml(t){
+							var d = new doh.Deferred();
+							var td = dojo.io.iframe.send({
+								url: "iframeResponse.xml",
+								method: "GET",
+								timeoutSeconds: 5,
+								preventCache: true,
+								handleAs: "xml",
+								handle: function(res, ioArgs){
+									if(!(res instanceof Error) 
+										&& t.is(4, res.documentElement.getElementsByTagName("child").length)
+									){
+										d.callback(true);
+									} else {
+										d.errback(false);
+									}
+								}
+							});
+							return d;
+						},
+						function ioIframeContentArray(t){
+							//Tests if an array passed in content causes as an error on cleanup.
+							var d = new doh.Deferred();
+							var td = dojo.io.iframe.send({
+								url: "iframeResponse.text.html",
+								form: "contentArrayTest",
+								content: {"tag": ["value1","value2"]},
+								handle: function(res, ioArgs){
+									if(!(res instanceof Error)){
+										d.callback(true);
+									} else {
+										d.errback(false);
+									}
+								}
+							});
+							return d;
+						}
+					]
+				);
+				doh.run();
+			});
+
+/*
+dojo.addOnLoad(function(){
+	var td = dojo.io.iframe.get({
+		url: "iframeResponse.text.html",
+		timeoutSeconds: 5,
+		preventCache: true,
+		handle: function(res, ioArgs){
+			if(!(res instanceof Error) && 
+				"iframe succeeded" == res){
+				console.debug("OK");
+			}else{
+				console.debug("Error", res);
+			}								
+		}
+	});
+});
+*/
+		</script>
+	</head>
+	<body>
+
+		<form id="contentArrayTest" method="get" enctype="multipart/form-data">
+		</form>
+	</body>
+</html>
diff --git a/dojo/tests/io/iframe.js b/dojo/tests/io/iframe.js
new file mode 100644
index 0000000..7f880ef
--- /dev/null
+++ b/dojo/tests/io/iframe.js
@@ -0,0 +1,4 @@
+dojo.provide("tests.io.iframe");
+if(dojo.isBrowser){
+	doh.registerUrl("tests.io.iframe", dojo.moduleUrl("tests.io", "iframe.html"));
+}
diff --git a/dojo/tests/io/iframeResponse.html b/dojo/tests/io/iframeResponse.html
new file mode 100644
index 0000000..cd26e21
--- /dev/null
+++ b/dojo/tests/io/iframeResponse.html
@@ -0,0 +1,8 @@
+<html lang="en">
+	<head>
+	</head>
+	<body>
+		<h1>SUCCESSFUL HTML response</h1>
+	</body>
+</html>
+
diff --git a/dojo/tests/io/iframeResponse.js.html b/dojo/tests/io/iframeResponse.js.html
new file mode 100644
index 0000000..50c1855
--- /dev/null
+++ b/dojo/tests/io/iframeResponse.js.html
@@ -0,0 +1,7 @@
+<html>
+	<head>
+	</head>
+	<body>
+	    <textarea style="width: 100%; height: 100px;">window.iframeTestingFunction = function(){ return 42; };</textarea>
+	</body>
+</html>
diff --git a/dojo/tests/io/iframeResponse.json.html b/dojo/tests/io/iframeResponse.json.html
new file mode 100644
index 0000000..cb04ed7
--- /dev/null
+++ b/dojo/tests/io/iframeResponse.json.html
@@ -0,0 +1,7 @@
+<html>
+	<head>
+	</head>
+	<body>
+	    <textarea style="width: 100%; height: 100px;">{ color: "blue", size: 42 }</textarea>
+	</body>
+</html>
diff --git a/dojo/tests/io/iframeResponse.text.html b/dojo/tests/io/iframeResponse.text.html
new file mode 100644
index 0000000..2a05b83
--- /dev/null
+++ b/dojo/tests/io/iframeResponse.text.html
@@ -0,0 +1,7 @@
+<html>
+	<head>
+	</head>
+	<body>
+	    <textarea style="width: 100%; height: 100px;">iframe succeeded</textarea>
+	</body>
+</html>
diff --git a/dojo/tests/io/iframeResponse.xml b/dojo/tests/io/iframeResponse.xml
new file mode 100644
index 0000000..4d9c98a
--- /dev/null
+++ b/dojo/tests/io/iframeResponse.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Envelope title="Test of dojo.io.iframe xml test">
+	<Children>
+		<child>FOO</child>
+		<child>BAR</child>
+		<child>BAZ</child>
+		<child>BAT</child>
+	</Children>
+	<![CDATA[
+		function(){
+			for(var i=0; i<somethign; i++){
+				if(foo>bar){ /* whatever */ }
+			}
+		}
+	]]>
+	<a href="something">something else</a>
+</Envelope>
diff --git a/dojo/tests/io/iframeUploadTest.html b/dojo/tests/io/iframeUploadTest.html
new file mode 100644
index 0000000..6f6db6f
--- /dev/null
+++ b/dojo/tests/io/iframeUploadTest.html
@@ -0,0 +1,50 @@
+<html>
+	<head>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript"
+			djConfig="isDebug: true, dojoIframeHistoryUrl: '../../resource/blank.html'"
+			src="../../dojo.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.io.iframe");
+
+			var callCount = 0;
+			var ioResponse;
+
+			function sendIt(){
+				dojo.io.iframe.send({
+					form: dojo.byId("uploadForm"),
+					handleAs: "application/json",
+					content: {
+						increment: callCount++,
+						fileFields: "ul1"
+					},
+					handle: function(response, ioArgs){
+						if(response instanceof Error){
+							console.debug("Request FAILED: ", response);
+						}else{
+							console.debug("Request complete: ", response);
+						}
+						ioResponse = response; // to get at afterwards in debugger.
+					}
+				});
+			}
+		</script>
+	</head>
+	<body>
+		<p>This file tests dojo.io.iframe upload using a form POST with a file upload button.</p>
+
+		<p>
+		<b>Note:</b> This test makes a form POST to upload.cgi. This cgi needs to be made executable for this test to work, and it won't work from local disk.
+		</p>
+		<form action="upload.cgi" id="uploadForm" 
+			method="POST"  enctype="multipart/form-data">
+			<input type="text" name="foo" value="bar">
+			<input type="file" name="ul1">
+			<input type="button" onclick="sendIt(); return false;" value="send it!">
+		</form>
+	</body>
+</html>
+
diff --git a/dojo/tests/io/script.html b/dojo/tests/io/script.html
new file mode 100644
index 0000000..e806000
--- /dev/null
+++ b/dojo/tests/io/script.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Testing dojo.io.script</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript" 
+			src="../../io/script.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.require("dojo.io.script");
+
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						function ioScriptLoad(t){
+							//t.is("undefined", typeof(scriptLoad));
+							var d = new doh.Deferred();
+							var td = dojo.io.script.get({
+								url: "scriptLoad.js"
+							});
+							td.addBoth(function(res){
+								if(typeof(scriptLoad) != "undefined"
+									&& t.is("loaded", scriptLoad)){
+									d.callback(true);
+								}else{
+									d.errback(false);
+								}
+							});
+							return d;
+						},
+						function ioScriptSimple(t){
+							var d = new doh.Deferred();
+							var td = dojo.io.script.get({
+								url: "scriptSimple.js",
+								checkString: "myTasks"
+							});
+							td.addBoth(function(res){
+								if(typeof(myTasks) != "undefined"
+									&& t.is("Do dishes.", myTasks[1])){
+									d.callback(true);
+								}else{
+									d.errback(false);
+								}
+							});
+							return d;
+						},
+						function ioScriptJsonp(t){
+							var d = new doh.Deferred();
+							var td = dojo.io.script.get({
+								url: "scriptJsonp.js",
+								content: { foo: "bar" },
+								jsonp: "callback"
+							});
+							td.addBoth(function(res){
+								if(!(res instanceof Error) && 
+									t.is("mammal", res.animalType)){
+									d.callback(true);
+								}else{
+									d.errback(false);
+								}
+							});
+							return d;							
+						},
+						function ioScriptJsonpTimeout(t){
+							var d = new doh.Deferred();
+							var td = dojo.io.script.get({
+								url: "../_base/timeout.php",
+								callbackParamName: "callback",
+								content: {Foo: 'Bar'},
+								timeout: 500,
+								handleAs: "json",
+								preventCache: true,
+								handle: function(response, ioArgs){
+									if(response instanceof Error && response.dojoType == "timeout"){
+										console.debug("FOO OK TEST");
+										d.callback(true);
+									}else{
+										console.debug("FOO FAIL TEST");
+										d.errback(false);
+									}
+								}
+							});
+							return d;
+						}
+					]
+				);
+				doh.run();
+			});
+
+/*
+			dojo.addOnLoad(function(){
+				td = dojo.io.script.get({
+					url: "scriptSimple.js",
+					checkString: "myTasks"
+				});
+				td.addCallback(function(res){
+					alert(myTasks);
+					alert(myTasks[1]);
+					if(typeof(myTasks) != "undefined"
+						&& "Do dishes." == myTasks[1]){
+						alert("yeah");
+					}else{
+						alert("boo");
+					}
+				});
+			});
+*/
+
+		</script>
+	</head>
+	<body>
+
+	</body>
+</html>
diff --git a/dojo/tests/io/script.js b/dojo/tests/io/script.js
new file mode 100644
index 0000000..77bd580
--- /dev/null
+++ b/dojo/tests/io/script.js
@@ -0,0 +1,4 @@
+dojo.provide("tests.io.script");
+if(dojo.isBrowser){
+	doh.registerUrl("tests.io.script", dojo.moduleUrl("tests.io", "script.html"));
+}
diff --git a/dojo/tests/io/scriptJsonp.js b/dojo/tests/io/scriptJsonp.js
new file mode 100644
index 0000000..ad1a196
--- /dev/null
+++ b/dojo/tests/io/scriptJsonp.js
@@ -0,0 +1,57 @@
+function getJsonpCallback(url){
+	var result = null;
+	var idMatch = url.match(/jsonp=(.*?)(&|$)/);
+	if(idMatch){
+		result = idMatch[1];
+	}else{
+		//jsonp didn't match, so maybe it is the jsonCallback thing.
+		idMatch = url.match(/callback=(.*?)(&|$)/);
+		if(idMatch){
+			result = idMatch[1];
+		}
+	}
+	
+	if(result){
+		result = decodeURIComponent(result);
+	}
+	return result;
+}
+
+function findJsonpDone(){
+	var result = false;
+	var scriptUrls = getScriptUrls();
+	
+	for(var i = 0; i < scriptUrls.length; i++){
+		var jsonp = getJsonpCallback(scriptUrls[i]);
+		if(jsonp){
+			eval(jsonp + "({animalType: 'mammal'});");
+			result = true;
+			break;
+		}
+	}
+	return result;
+}
+
+function getScriptUrls(){
+	//Get the script tags in the page to figure what state we are in.
+	var scripts = document.getElementsByTagName('script');
+	var scriptUrls = new Array();
+	for(var i = 0; scripts && i < scripts.length; i++){
+		var scriptTag = scripts[i];
+		if(scriptTag.id.indexOf("dojoIoScript") == 0){
+			scriptUrls.push(scriptTag.src);
+		}
+	}
+
+	return scriptUrls;
+}
+
+function doJsonpCallback(){
+	if(!findJsonpDone()){
+		 alert('ERROR: Could not jsonp callback!');
+	}
+}
+
+//Set a timeout to do the callback check, since MSIE won't see the SCRIPT tag until
+//we complete processing of this page.
+setTimeout(function(){doJsonpCallback();}, 300);
diff --git a/dojo/tests/io/scriptLoad.js b/dojo/tests/io/scriptLoad.js
new file mode 100644
index 0000000..db3ceab
--- /dev/null
+++ b/dojo/tests/io/scriptLoad.js
@@ -0,0 +1,2 @@
+scriptLoad = "loaded";
+
diff --git a/dojo/tests/io/scriptSimple.js b/dojo/tests/io/scriptSimple.js
new file mode 100644
index 0000000..8ca316c
--- /dev/null
+++ b/dojo/tests/io/scriptSimple.js
@@ -0,0 +1,5 @@
+myTasks = new Array();
+myTasks[0] = 'Take out trash.';
+myTasks[1] = 'Do dishes.';
+myTasks[2] = 'Brush teeth.';
+
diff --git a/dojo/tests/io/scriptTimeout.html b/dojo/tests/io/scriptTimeout.html
new file mode 100644
index 0000000..563e37c
--- /dev/null
+++ b/dojo/tests/io/scriptTimeout.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Testing dojo.io.script</title>
+		<style type="text/css">
+			@import "../../resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.io.script");
+
+			function startTest(){
+				var td = dojo.io.script.get({
+					url: "../_base/timeout.php",
+					callbackParamName: "callback",
+					content: {Foo: 'Bar'},
+					timeout: 500,
+					handleAs: "json",
+					preventCache: true,
+					handle: function(response, ioArgs){
+						if(response instanceof Error && response.dojoType == "timeout"){
+							console.debug("TEST OK. No errors should be seen after this timeout error.");
+						}else{
+							console.debug("TEST FAILED: some other error or response received: ", response);
+						}
+					}
+				});
+			}
+		</script>
+	</head>
+	<body>
+		<h1>Timeout test</h1>
+		
+		<p>
+		This test page tests the timeout functionality of dojo.io.script, and to make
+		sure that requests that time out get removed quickly. If the server response
+		is received after the script has been timed out, there should not be weird 
+		errors as the browser tries to evaluate the responses after the desired time
+		period.
+		</p>
+		
+		<p>This test requires a server running PHP to work.</p>
+		
+		<p>
+		<p><strong>Firefox Oddity:</strong> Firefox
+		will print an error after the script response is received from the server:<br />
+		<span style="color: red">dojo.io.script.jsonp_dojoIoScript1 has no properties</span>
+		This is bad because Firefox goes ahead and evaluates the script contents in the page's
+		JavaScript space (this happens even when I turn off Firefox Add-Ons). All other browsers
+		do not evaluate the script (given the weird Opera 9.22 behavior below). You can test this
+		by clicking the <b>Test for SuperXFooBarVariable</b> button after receiving the response
+		for timeout.php (check Firebug Net tab to see when request is received). All other browsers
+		show an error or show the "undefined" value for SuperXFooBarVariable, but Firefox will show its
+		value as being: "Oh no! SuperXFooBarVariable is defined (should not be for timeout case)".
+		
+		<p><strong>Opera Oddity:</strong> Opera 9.22 does not seem to trigger the timeout case,
+		but rather it waits for the server to send a response to the script before continuing past the
+		point where the script is added to the DOM? That seems wrong. Dynamic script tags are no longer
+		an async operation?
+		</p>
+		
+		<button onclick="startTest()">Start Test</button>
+		<button onclick="alert(SuperXFooBarVariable)">Test for SuperXFooBarVariable</button>
+		</body>
+</html>
diff --git a/dojo/tests/io/upload.cgi b/dojo/tests/io/upload.cgi
new file mode 100755
index 0000000..baea1f2
--- /dev/null
+++ b/dojo/tests/io/upload.cgi
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+
+# FROM: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/273844
+
+import cgi
+import cgitb; cgitb.enable()
+import os, sys
+import string
+
+UPLOAD_DIR = "/tmp/upload/"
+form = cgi.FieldStorage()
+
+dbg = []
+
+def debug(dbgstr):
+	dbg.append(str(dbgstr))
+
+def save_uploaded_file(form_field, upload_dir):
+	global form
+	if not form.has_key(form_field): 
+		debug("didn't find it! (1)")
+		return
+	fileitem = form[form_field]
+	if not fileitem.file: 
+		debug(form.getvalue(form_field, ""))
+		debug(fileitem.__dict__)
+		debug("didn't find it! (2)")
+		return
+	fout = file(os.path.join(upload_dir, fileitem.filename), 'wb')
+	while 1:
+		chunk = fileitem.file.read(100000)
+		if not chunk: break
+		fout.write (chunk)
+	fout.close()
+
+retval = "false";
+fileFields = ""
+
+if form.has_key("fileFields"):
+	fval = str(form.getvalue("fileFields", ""))
+	fileFields = fval.split(",")
+	debug("'fileCount': '" + str(len(fileFields)) + "',")
+	for field in fileFields:
+		debug("'fileField' : '"+field + "',")
+		# Uncomment the line below to really test file save.
+		# You may need to modify UPLOAD_DIR above.
+		# save_uploaded_file(str(field).strip(), UPLOAD_DIR)
+	retval = "true";
+
+debug("'retval': " + retval)
+
+print """Content-Type: text/html
+
+
+<html>
+	<head>
+	</head>
+	<body>
+	    <textarea style="width: 100%%; height: 100px;">{ %s }</textarea>
+	</body>
+</html>
+""" % (string.join(dbg, "\n"))
diff --git a/dojo/tests/module.js b/dojo/tests/module.js
new file mode 100644
index 0000000..80e29f3
--- /dev/null
+++ b/dojo/tests/module.js
@@ -0,0 +1,34 @@
+dojo.provide("dojo.tests.module");
+
+try{
+	dojo.require("tests._base");
+	dojo.require("tests.i18n"); 
+	dojo.requireIf(dojo.isBrowser, "tests.back-hash");
+	dojo.requireIf(dojo.isBrowser, "tests.hash");
+	dojo.require("tests.cldr");
+	dojo.require("tests.data");
+	dojo.require("tests.date");
+	dojo.require("tests.number");
+	dojo.require("tests.currency");
+	dojo.require("tests.AdapterRegistry");
+	dojo.require("tests.io.script");
+	dojo.require("tests.io.iframe");
+	dojo.requireIf(dojo.isBrowser, "tests.rpc");
+	dojo.require("tests.regexp");
+	dojo.require("tests.string");
+	dojo.require("tests.behavior");
+	dojo.require("tests.parser");
+	dojo.require("tests.colors");
+	dojo.requireIf(dojo.isBrowser,"tests.cookie");
+	dojo.require("tests.fx");
+	dojo.require("tests.DeferredList");
+	dojo.require("tests.Stateful");
+	dojo.require("tests.html");
+	dojo.requireIf(dojo.isBrowser,"tests.NodeList-traverse");
+	dojo.requireIf(dojo.isBrowser,"tests.NodeList-manipulate");
+	dojo.require("tests.cache");
+	dojo.requireIf(dojo.isBrowser, "tests.uacss");
+	dojo.requireIf(dojo.isBrowser, "tests.window");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojo/tests/nls/ar/salutations.js b/dojo/tests/nls/ar/salutations.js
new file mode 100644
index 0000000..9b871bb
--- /dev/null
+++ b/dojo/tests/nls/ar/salutations.js
@@ -0,0 +1,8 @@
+/*<?xml version="1.0" encoding="UTF-8" ?>*/
+// The above is a workaround for Konqueror and Safari (see bug #1010)
+// The parentheses are optional, but make this file a valid JS expression for
+// tools to inspect
+({
+ ar: "العربية",
+ hello: "ﺎﺑﺣﺮﻣ"
+})
diff --git a/dojo/tests/nls/cs/salutations.js b/dojo/tests/nls/cs/salutations.js
new file mode 100644
index 0000000..7be97cd
--- /dev/null
+++ b/dojo/tests/nls/cs/salutations.js
@@ -0,0 +1,4 @@
+{
+ cs: "česky",
+ hello: "Ahoj"
+}
diff --git a/dojo/tests/nls/de/salutations.js b/dojo/tests/nls/de/salutations.js
new file mode 100644
index 0000000..fe9a8c3
--- /dev/null
+++ b/dojo/tests/nls/de/salutations.js
@@ -0,0 +1,4 @@
+{
+ de: "Deutsch",
+ hello: "Hallo"
+}
diff --git a/dojo/tests/nls/el/salutations.js b/dojo/tests/nls/el/salutations.js
new file mode 100644
index 0000000..89ab77a
--- /dev/null
+++ b/dojo/tests/nls/el/salutations.js
@@ -0,0 +1,4 @@
+{
+ el: "Ελληνικά",
+ hello: "Γειά"
+}
diff --git a/dojo/tests/nls/en-au/salutations.js b/dojo/tests/nls/en-au/salutations.js
new file mode 100644
index 0000000..a6bded0
--- /dev/null
+++ b/dojo/tests/nls/en-au/salutations.js
@@ -0,0 +1,3 @@
+{
+ hello: "G'day"
+}
diff --git a/dojo/tests/nls/en-us-hawaii/salutations.js b/dojo/tests/nls/en-us-hawaii/salutations.js
new file mode 100644
index 0000000..1c182d2
--- /dev/null
+++ b/dojo/tests/nls/en-us-hawaii/salutations.js
@@ -0,0 +1,3 @@
+{
+ hello: "Aloha"
+}
diff --git a/dojo/tests/nls/en-us-new_york-brooklyn/salutations.js b/dojo/tests/nls/en-us-new_york-brooklyn/salutations.js
new file mode 100644
index 0000000..df00353
--- /dev/null
+++ b/dojo/tests/nls/en-us-new_york-brooklyn/salutations.js
@@ -0,0 +1,3 @@
+{
+ hello: "Yo"
+}
diff --git a/dojo/tests/nls/en-us-texas/salutations.js b/dojo/tests/nls/en-us-texas/salutations.js
new file mode 100644
index 0000000..70bdfa4
--- /dev/null
+++ b/dojo/tests/nls/en-us-texas/salutations.js
@@ -0,0 +1,3 @@
+{
+ hello: "Howdy"
+}
diff --git a/dojo/tests/nls/es/salutations.js b/dojo/tests/nls/es/salutations.js
new file mode 100644
index 0000000..1bc5155
--- /dev/null
+++ b/dojo/tests/nls/es/salutations.js
@@ -0,0 +1,5 @@
+{
+ es: "Español",
+ hello: "Hola",
+ hello_dojo: "¡${hello}, ${dojo}!"
+}
diff --git a/dojo/tests/nls/fa/salutations.js b/dojo/tests/nls/fa/salutations.js
new file mode 100644
index 0000000..ca32a4d
--- /dev/null
+++ b/dojo/tests/nls/fa/salutations.js
@@ -0,0 +1,4 @@
+{
+ fa: "فارسی",
+ hello: "درود"
+}
diff --git a/dojo/tests/nls/fr/salutations.js b/dojo/tests/nls/fr/salutations.js
new file mode 100644
index 0000000..8c4b74f
--- /dev/null
+++ b/dojo/tests/nls/fr/salutations.js
@@ -0,0 +1,4 @@
+{
+ fr: "Français",
+ hello: "Bonjour"
+}
diff --git a/dojo/tests/nls/he/salutations.js b/dojo/tests/nls/he/salutations.js
new file mode 100644
index 0000000..0b2c441
--- /dev/null
+++ b/dojo/tests/nls/he/salutations.js
@@ -0,0 +1,4 @@
+{
+ he: "עברית",
+ hello: "שלום"
+}
diff --git a/dojo/tests/nls/hi/salutations.js b/dojo/tests/nls/hi/salutations.js
new file mode 100644
index 0000000..5f67686
--- /dev/null
+++ b/dojo/tests/nls/hi/salutations.js
@@ -0,0 +1,4 @@
+{
+ hi: "हिन्दी",
+ hello: "नमस्ते"
+}
diff --git a/dojo/tests/nls/it/salutations.js b/dojo/tests/nls/it/salutations.js
new file mode 100644
index 0000000..19cb22d
--- /dev/null
+++ b/dojo/tests/nls/it/salutations.js
@@ -0,0 +1,4 @@
+{
+ it: "italiano",
+ hello: "Ciao"
+}
diff --git a/dojo/tests/nls/ja/salutations.js b/dojo/tests/nls/ja/salutations.js
new file mode 100644
index 0000000..e009aa0
--- /dev/null
+++ b/dojo/tests/nls/ja/salutations.js
@@ -0,0 +1,4 @@
+{
+ ja: "\u65E5\u672C\u8A9E",
+ hello: "こにちは"
+}
diff --git a/dojo/tests/nls/ko/salutations.js b/dojo/tests/nls/ko/salutations.js
new file mode 100644
index 0000000..84f7010
--- /dev/null
+++ b/dojo/tests/nls/ko/salutations.js
@@ -0,0 +1,4 @@
+{
+ ko: "\uD55C\uAD6D\uC5B4",
+ hello: "\uc548\ub155"
+}
diff --git a/dojo/tests/nls/pl/salutations.js b/dojo/tests/nls/pl/salutations.js
new file mode 100644
index 0000000..440e24a
--- /dev/null
+++ b/dojo/tests/nls/pl/salutations.js
@@ -0,0 +1,4 @@
+{
+ pl: "Polski",
+ hello: "Dzièn dobry"
+}
diff --git a/dojo/tests/nls/pt/salutations.js b/dojo/tests/nls/pt/salutations.js
new file mode 100644
index 0000000..436b69d
--- /dev/null
+++ b/dojo/tests/nls/pt/salutations.js
@@ -0,0 +1,4 @@
+{
+ pt: "Português",
+ hello: "Olá"
+}
diff --git a/dojo/tests/nls/ru/salutations.js b/dojo/tests/nls/ru/salutations.js
new file mode 100644
index 0000000..5f8f073
--- /dev/null
+++ b/dojo/tests/nls/ru/salutations.js
@@ -0,0 +1,4 @@
+{
+ ru: "русский",
+ hello: "Привет"
+}
diff --git a/dojo/tests/nls/salutations.js b/dojo/tests/nls/salutations.js
new file mode 100644
index 0000000..b268a60
--- /dev/null
+++ b/dojo/tests/nls/salutations.js
@@ -0,0 +1,32 @@
+{
+ ar: "Arabic",
+ cs: "Czech",
+ de: "German",
+ el: "Greek",
+ en: "English",
+ 'en-au': "English (Australia)",
+ 'en-us-hawaii': "English (US-Hawaii)",
+ 'en-us-new_york-brooklyn': "English (Brooklynese)",
+ 'en-us-texas': "English (Texas)",
+ es: "Spanish",
+ fa: "Farsi",
+ fr: "French",
+ he: "Hebrew",
+ hi: "Hindi",
+ it: "Italian",
+ ja: "Japanese",
+ ko: "Korean",
+ pl: "Polish",
+ pt: "Portugese",
+ ru: "Russian",
+ sw: "Kiswahili",
+ th: "Thai",
+ tr: "Turkish",
+ yi: "Yiddish",
+ 'zh-cn': "Chinese (Simplified)",
+ 'zh-tw': "Chinese (Traditional)",
+ hello: "Hello",
+ dojo: "Dojo",
+ hello_dojo: "${hello}, ${dojo}!",
+ file_not_found:"The file you requested, ${0}, is not found."
+}
diff --git a/dojo/tests/nls/sw/salutations.js b/dojo/tests/nls/sw/salutations.js
new file mode 100644
index 0000000..8399757
--- /dev/null
+++ b/dojo/tests/nls/sw/salutations.js
@@ -0,0 +1,3 @@
+{
+ hello: "Hujambo"
+}
diff --git a/dojo/tests/nls/th/salutations.js b/dojo/tests/nls/th/salutations.js
new file mode 100644
index 0000000..2482533
--- /dev/null
+++ b/dojo/tests/nls/th/salutations.js
@@ -0,0 +1,4 @@
+{
+ th: "ქართული ენაქართული ენაქართული ენაสวัสดีครับ/คะ",
+ hello: "ภาษาไทย"
+}
diff --git a/dojo/tests/nls/tr/salutations.js b/dojo/tests/nls/tr/salutations.js
new file mode 100644
index 0000000..a8da48f
--- /dev/null
+++ b/dojo/tests/nls/tr/salutations.js
@@ -0,0 +1,4 @@
+{
+ tr: "Türkçe",
+ hello: "Merhaba"
+}
diff --git a/dojo/tests/nls/yi/salutations.js b/dojo/tests/nls/yi/salutations.js
new file mode 100644
index 0000000..826a997
--- /dev/null
+++ b/dojo/tests/nls/yi/salutations.js
@@ -0,0 +1,4 @@
+{
+ yi: "ייִדיש",
+ hello: "אַ גוטן טאָג"
+}
diff --git a/dojo/tests/nls/zh-cn/salutations.js b/dojo/tests/nls/zh-cn/salutations.js
new file mode 100644
index 0000000..51b55ac
--- /dev/null
+++ b/dojo/tests/nls/zh-cn/salutations.js
@@ -0,0 +1,4 @@
+{
+ 'zh-cn': "汉语",
+ hello: "你好"
+}
diff --git a/dojo/tests/nls/zh-tw/salutations.js b/dojo/tests/nls/zh-tw/salutations.js
new file mode 100644
index 0000000..f00c43e
--- /dev/null
+++ b/dojo/tests/nls/zh-tw/salutations.js
@@ -0,0 +1,4 @@
+{
+ 'zh-tw': "漢語",
+ hello: "你好"
+}
diff --git a/dojo/tests/number.js b/dojo/tests/number.js
new file mode 100644
index 0000000..a76a841
--- /dev/null
+++ b/dojo/tests/number.js
@@ -0,0 +1,1119 @@
+dojo.provide("tests.number");
+
+dojo.require("dojo.number");
+
+/**
+ * Refer to ICU4J's NumberFormatTest.expect(...) 
+ */
+tests.number.check=function(t,options,sourceInput,expectResult){
+	tests.number.checkFormatParseCycle(t, t,options,sourceInput,expectResult,false);
+	tests.number.checkParse(t, t,options,expectResult,sourceInput);	
+}
+
+/**
+ * Perform a single formatting check or a backward check
+ * backward check:number1 -(formatted)-> string1 -(parsed)-> number2 -(formated)-> string2
+ * then number should == number2; string1 should == string2
+ */
+tests.number.checkFormatParseCycle=function(t,options,sourceInput,expectResult,
+		 backwardCheck/*boolean,indicates whether need a backward chain check,like formate->parse->format*/){	
+	if(null != options){
+		var pattern = options.pattern;
+		var locale = options.locale;
+		//TODO: add more fields
+	}
+	
+	//print("\n");
+	var str = null==pattern?"default":pattern;
+	//print("pattern:" + str + "| locale:" + locale);
+	//print("input:" + sourceInput);
+	var result = dojo.number.format(sourceInput,options);
+	//print("result:" + result);
+	if(null != expectResult){
+	    t.is(expectResult,result);
+	}
+	if(backwardCheck){
+		var resultParsed = dojo.number.parse(result,options);
+		//print("resultParsed:" + resultParsed);		
+		if(!tests.number._decimalNumberDiff(sourceInput,resultParsed)){	
+		    t.is(sourceInput,resultParsed);
+		}		
+		var resultParsedReformatted = dojo.number.format(resultParsed,options);
+		//print("resultParsedReformatted:" + resultParsedReformatted);
+	    if(!tests.number._decimalNumberDiff(result,resultParsedReformatted)){
+			t.is(result,resultParsedReformatted);
+		}
+	}	
+}
+
+/**
+ * Perform a single parsing check
+ */
+tests.number.checkParse=function(t,options,sourceInput,expectResult){
+	var str = "default";
+	if(null != options && null != options.pattern){	
+		str = options.pattern;
+	}
+	//print("input:" + sourceInput);
+	var result = dojo.number.parse(sourceInput,options);
+	//print("result :" + result);
+	if(null != expectResult){
+	    t.is(expectResult,result);
+	}
+}
+
+/**
+ * //TODO:Round a given number
+ */
+tests.number.rounding = function(t,number,maxFractionDigits,expected){
+	var pattern="#0.";
+	for(var i=0; i<maxFractionDigits; i++){pattern += "#";}
+	var result = dojo.number.format(number,{locale:tests.number.locale, pattern:pattern});
+	t.is(expected,result);	
+}
+
+/**
+ * Run a batch parsing
+ */
+function runBatchParse(options,dataArray/*array*/,pass/*boolean*/){
+	var exception = null;
+	var result;
+	var i=0;
+	var str = (null==options.pattern)?"default":options.pattern;
+	
+	//print("\n");
+	for(; i<dataArray.length; i++){
+		try{
+			//print("["+i+"]"+"input:"+dataArray[i]);
+			result = dojo.number.parse(dataArray[i],options);			
+			if(isNaN(result)){
+				throw "\"" + dataArray[i] + "\" is parsed to NaN with pattern " + str;
+			}
+			//print("["+i+"]"+"output:"+result);	
+		}catch(e){
+			exception = e;
+			break;
+		}
+	}
+		
+	if(!pass && (exception == null)) {
+		throw "runBatchParse() - stric parse failed, no exception when parsing illegal data"; 
+	}else if(exception != null){
+		if(!pass && i == 0){
+			//strict parsing should fail for all the dataArray elements as expected
+			//pass condition for strict parsing
+			return;
+		}
+		throw "runBatchParse() failed: " + exception;		
+	}
+}
+
+/**
+ * Check whether the given two numbers differ under the decimal bound
+ * 
+ */
+tests.number._decimalNumberDiff = function(num1,num2){
+	//TODO: should be more accurate when dojo.number finish rounding in the future
+	var diffBound = 1e-3;
+	var diff = num1 - num2;
+	//print("Math.abs(diff) " + Math.abs(diff));
+	if(Math.abs(diff) < diffBound ){
+		return true;
+	}else if(isNaN(Math.abs(diff))){	
+		var s = num1.toString().split(num2);
+		s[1] = s[1].replace(",","0");
+		s[1] = s[1].replace('\u066b','0');
+		return (new Number(s[1])< diffBound);
+	}
+	return false;	
+}
+
+tests.register("tests.number", 
+	[
+		{
+			// Test formatting and parsing of currencies in various locales pre-built in dojo.cldr
+			// NOTE: we can't set djConfig.extraLocale before bootstrapping unit tests, so directly
+			// load resources here for specific locales:
+
+			name: "number",
+			setUp: function(){
+				var partLocaleList = ["en-us", "fr-fr", "de-de"];
+				tests.number.locale = "en-us";
+				for(var i = 0 ; i < partLocaleList.length; i ++){
+					dojo.requireLocalization("dojo.cldr","number",partLocaleList[i]);
+				}
+			},
+			runTest: function(t){
+			}
+		},
+		{
+			name: "invalid",
+			runTest: function(t){
+				t.t(null === dojo.number.format(NaN));
+				t.t(null === dojo.number.format(Number.NaN));
+				t.t(null === dojo.number.format(Infinity));
+				t.t(null === dojo.number.format(-Infinity));
+			}
+		},
+		{
+			name: "round",
+			runTest: function(t){
+				t.is(0, dojo.number.round(0));
+				t.is(1, dojo.number.round(0.5));
+				t.is(-1, dojo.number.round(-0.5));
+				t.is(0.1, dojo.number.round(0.05, 1));
+				t.is(-0.1, dojo.number.round(-0.05, 1));
+				t.is(1.1, dojo.number.round(1.05, 1));
+				t.is(-1.1, dojo.number.round(-1.05, 1));
+//				t.is(-162.29, dojo.number.round(-162.295, 2)); // see ticket #7930, dojox.math.round
+//				t.is(162.29, dojo.number.round(162.295, 2)); // ibid
+			}
+		},
+		{
+			name: "round_multiple",
+			runTest: function(t){
+				t.is("123.455", dojo.number.round(123.4525, 2, 5));
+				t.is("123.45", dojo.number.round(123.452, 2, 5));
+				t.is("123.455", dojo.number.round(123.454, 2, 5));
+				t.is("123.455", dojo.number.round(123.456, 2, 5));
+				t.is("-123.45", dojo.number.round(-123.452, 2, 5));
+				t.is("-123.455", dojo.number.round(-123.4525, 2, 5));
+				t.is("-123.455", dojo.number.round(-123.454, 2, 5));
+				t.is("-123.455", dojo.number.round(-123.456, 2, 5));
+			}
+		},
+		{
+			name: "round_speleotrove",
+			runTest: function(t){
+				// submitted Mike Cowlishaw (IBM, CCLA), see http://speleotrove.com/decimal/#testcases
+				t.is(12345, dojo.number.round(12345 + -0.1), "radx200");
+				t.is(12345, dojo.number.round(12345 + -0.01), "radx201");
+				t.is(12345, dojo.number.round(12345 + -0.001), "radx202");
+				t.is(12345, dojo.number.round(12345 + -0.00001), "radx203");
+				t.is(12345, dojo.number.round(12345 + -0.000001), "radx204");
+				t.is(12345, dojo.number.round(12345 + -0.0000001), "radx205");
+				t.is(12345, dojo.number.round(12345 +  0), "radx206");
+				t.is(12345, dojo.number.round(12345 +  0.0000001), "radx207");
+				t.is(12345, dojo.number.round(12345 +  0.000001), "radx208");
+				t.is(12345, dojo.number.round(12345 +  0.00001), "radx209");
+				t.is(12345, dojo.number.round(12345 +  0.0001), "radx210");
+				t.is(12345, dojo.number.round(12345 +  0.001), "radx211");
+				t.is(12345, dojo.number.round(12345 +  0.01), "radx212");
+				t.is(12345, dojo.number.round(12345 +  0.1), "radx213");
+
+				t.is(12346, dojo.number.round(12346 +  0.49999), "radx215");
+				t.is(12347, dojo.number.round(12346 +  0.5), "radx216");
+				t.is(12347, dojo.number.round(12346 +  0.50001), "radx217");
+				
+				t.is(12345, dojo.number.round(12345 +  0.4), "radx220");
+				t.is(12345, dojo.number.round(12345 +  0.49), "radx221");
+				t.is(12345, dojo.number.round(12345 +  0.499), "radx222");
+				t.is(12345, dojo.number.round(12345 +  0.49999), "radx223");
+				t.is(12346, dojo.number.round(12345 +  0.5), "radx224");
+				t.is(12346, dojo.number.round(12345 +  0.50001), "radx225");
+				t.is(12346, dojo.number.round(12345 +  0.5001), "radx226");
+				t.is(12346, dojo.number.round(12345 +  0.501), "radx227");
+				t.is(12346, dojo.number.round(12345 +  0.51), "radx228");
+				t.is(12346, dojo.number.round(12345 +  0.6), "radx229");
+				
+				//negatives
+				t.is(-12345, dojo.number.round(-12345 + -0.1), "rsux200");
+				t.is(-12345, dojo.number.round(-12345 + -0.01), "rsux201");
+				t.is(-12345, dojo.number.round(-12345 + -0.001), "rsux202");
+				t.is(-12345, dojo.number.round(-12345 + -0.00001), "rsux203");
+				t.is(-12345, dojo.number.round(-12345 + -0.000001), "rsux204");
+				t.is(-12345, dojo.number.round(-12345 + -0.0000001), "rsux205");
+				t.is(-12345, dojo.number.round(-12345 +  0), "rsux206");
+				t.is(-12345, dojo.number.round(-12345 +  0.0000001), "rsux207");
+				t.is(-12345, dojo.number.round(-12345 +  0.000001), "rsux208");
+				t.is(-12345, dojo.number.round(-12345 +  0.00001), "rsux209");
+				t.is(-12345, dojo.number.round(-12345 +  0.0001), "rsux210");
+				t.is(-12345, dojo.number.round(-12345 +  0.001), "rsux211");
+				t.is(-12345, dojo.number.round(-12345 +  0.01), "rsux212");
+				t.is(-12345, dojo.number.round(-12345 +  0.1), "rsux213");
+				
+				t.is(-12346, dojo.number.round(-12346 +  0.49999), "rsux215");
+				t.is(-12346, dojo.number.round(-12346 +  0.5), "rsux216");
+				t.is(-12345, dojo.number.round(-12346 +  0.50001   ), "rsux217");
+				
+				t.is(-12345, dojo.number.round(-12345 +  0.4), "rsux220");
+				t.is(-12345, dojo.number.round(-12345 +  0.49), "rsux221");
+				t.is(-12345, dojo.number.round(-12345 +  0.499), "rsux222");
+				t.is(-12345, dojo.number.round(-12345 +  0.49999), "rsux223");
+				t.is(-12345, dojo.number.round(-12345 +  0.5), "rsux224");
+				t.is(-12344, dojo.number.round(-12345 +  0.50001), "rsux225");
+				t.is(-12344, dojo.number.round(-12345 +  0.5001), "rsux226");
+				t.is(-12344, dojo.number.round(-12345 +  0.501), "rsux227");
+				t.is(-12344, dojo.number.round(-12345 +  0.51), "rsux228");
+				t.is(-12344, dojo.number.round(-12345 +  0.6), "rsux229");
+				
+				t.is(12345, dojo.number.round(  12345 /  1), "rdvx401");
+				t.is(12344, dojo.number.round(  12345 /  1.0001), "rdvx402");
+				t.is(12333, dojo.number.round(  12345 /  1.001), "rdvx403");
+				t.is(12223, dojo.number.round(  12345 /  1.01), "rdvx404");
+				t.is(11223, dojo.number.round(  12345 /  1.1), "rdvx405");
+
+				t.is(3088.8, dojo.number.round( 12355 /  4, 1), "rdvx406");
+				t.is(3086.3, dojo.number.round( 12345 /  4, 1), "rdvx407");
+				t.is(3088.7, dojo.number.round( 12355 /  4.0001, 1), "rdvx408");
+				t.is(3086.2, dojo.number.round( 12345 /  4.0001, 1), "rdvx409");
+				t.is(2519.4, dojo.number.round( 12345 /  4.9, 1), "rdvx410");
+				t.is(2473.9, dojo.number.round( 12345 /  4.99, 1), "rdvx411");
+				t.is(2469.5, dojo.number.round( 12345 /  4.999, 1), "rdvx412");
+				t.is(2469.0, dojo.number.round( 12345 /  4.9999, 1), "rdvx413");
+				t.is(2469, dojo.number.round( 12345 /  5, 1), "rdvx414");
+				t.is(2469.0, dojo.number.round( 12345 /  5.0001, 1), "rdvx415");
+				t.is(2468.5, dojo.number.round( 12345 /  5.001, 1), "rdvx416");
+				t.is(2464.1, dojo.number.round( 12345 /  5.01, 1), "rdvx417");
+				t.is(2420.6, dojo.number.round( 12345 /  5.1, 1), "rdvx418");
+
+				t.is(12345, dojo.number.round(  12345 *  1), "rmux401");
+				t.is(12346, dojo.number.round(  12345 *  1.0001), "rmux402");
+				t.is(12357, dojo.number.round(  12345 *  1.001), "rmux403");
+				t.is(12468, dojo.number.round(  12345 *  1.01), "rmux404");
+				t.is(13580, dojo.number.round(  12345 *  1.1), "rmux405");
+				t.is(49380, dojo.number.round(  12345 *  4), "rmux406");
+				t.is(49381, dojo.number.round(  12345 *  4.0001), "rmux407");
+				t.is(60491, dojo.number.round(  12345 *  4.9), "rmux408");
+				t.is(61602, dojo.number.round(  12345 *  4.99), "rmux409");
+				t.is(61713, dojo.number.round(  12345 *  4.999), "rmux410");
+				t.is(61724, dojo.number.round(  12345 *  4.9999), "rmux411");
+				t.is(61725, dojo.number.round(  12345 *  5), "rmux412");
+				t.is(61726, dojo.number.round(  12345 *  5.0001), "rmux413");
+				t.is(61737, dojo.number.round(  12345 *  5.001), "rmux414");
+				t.is(61848, dojo.number.round(  12345 *  5.01), "rmux415");
+/*
+				t.is(1.4814E+5, dojo.number.round(  12345 *  12), "rmux416");
+				t.is(1.6049E+5, dojo.number.round(  12345 *  13), "rmux417");
+				t.is(1.4826E+5, dojo.number.round(  12355 *  12), "rmux418");
+				t.is(1.6062E+5, dojo.number.round(  12355 *  13), "rmux419");
+*/
+			}
+		},
+		{
+			name: "format", // old tests
+			runTest: function(t){
+
+	t.is("0123", dojo.number.format(123, {pattern: "0000"}));
+	t.is("-12,34,567.890", dojo.number.format(-1234567.89, {pattern: "#,##,##0.000##", locale: 'en-us'}));
+	t.is("-12,34,567.89012", dojo.number.format(-1234567.890123, {pattern: "#,##,##0.000##", locale: 'en-us'}));
+	t.is("(1,234,567.89012)", dojo.number.format(-1234567.890123, {pattern: "#,##0.000##;(#,##0.000##)", locale: 'en-us'}));
+	t.is("(1,234,567.89012)", dojo.number.format(-1234567.890123, {pattern: "#,##0.000##;(#)", locale: 'en-us'}));
+	t.is("50.1%", dojo.number.format(0.501, {pattern: "#0.#%", locale: 'en-us'}));
+	t.is("98", dojo.number.format(1998, {pattern: "00"}));
+	t.is("01998", dojo.number.format(1998, {pattern: "00000"}));
+	t.is("0.13", dojo.number.format(0.125, {pattern: "0.##", locale: 'en-us'})); //NOTE: expects round_half_up, not round_half_even
+	t.is("0.1250", dojo.number.format(0.125, {pattern: "0.0000", locale: 'en-us'}));
+	t.is("0.1", dojo.number.format(0.100004, {pattern: "0.####", locale: 'en-us'}));
+
+	t.is("-12", dojo.number.format(-12.3, {places:0, locale: "en-us"}));
+	t.is("-1,234,567.89", dojo.number.format(-1234567.89, {locale: "en-us"}));
+//	t.is("-12,34,567.89", dojo.number.format(-1234567.89, {locale: "en-in"}));
+	t.is("-1,234,568", dojo.number.format(-1234567.89, {places:0, locale: "en-us"}));
+//	t.is("-12,34,568", dojo.number.format(-1234567.89, {places:0, locale: "en-in"}));
+	t.is("-1\xa0000,10", dojo.number.format(-1000.1, {places:2, locale: "fr-fr"}));
+	t.is("-1,000.10", dojo.number.format(-1000.1, {places:2, locale: "en-us"}));
+	t.is("-1\xa0000,10", dojo.number.format(-1000.1, {places:2, locale: "fr-fr"}));
+	t.is("-1.234,56", dojo.number.format(-1234.56, {places:2, locale: "de-de"}));
+	t.is("-1,000.10", dojo.number.format(-1000.1, {places:2, locale: "en-us"}));
+	t.is("123.46%", dojo.number.format(1.23456, {places:2, locale: "en-us", type: "percent"}));
+	t.is("123.4", dojo.number.format(123.4, {places:'1,3', locale: 'en-us'}));
+	t.is("123.45", dojo.number.format(123.45, {places:'1,3', locale: 'en-us'}));
+	t.is("123.456", dojo.number.format(123.456, {places:'1,3', locale: 'en-us'}));
+
+	//rounding
+	t.is("-1,234,568", dojo.number.format(-1234567.89, {places:0, locale: "en-us"}));
+//	t.is("-12,34,568", dojo.number.format(-1234567.89, {places:0, locale: "en-in"}));
+	t.is("-1,000.11", dojo.number.format(-1000.114, {places:2, locale: "en-us"}));
+	t.is("-1,000.12", dojo.number.format(-1000.115, {places:2, locale: "en-us"}));
+	t.is("-1,000.12", dojo.number.format(-1000.116, {places:2, locale: "en-us"}));
+	t.is("-0.00", dojo.number.format(-0.0001, {places:2, locale: "en-us"}));
+	t.is("0.00", dojo.number.format(0, {places:2, locale: "en-us"}));
+
+	//change decimal places
+	t.is("-1\xa0000,100", dojo.number.format(-1000.1, {places:3, locale: "fr-fr"}));
+	t.is("-1,000.100", dojo.number.format(-1000.1, {places:3, locale: "en-us"}));
+			}
+		},
+		{
+			name: "parse", // old tests
+			runTest: function(t){
+	t.is(1000, dojo.number.parse("1000", {locale: "en-us"}));
+	t.is(1000.123, dojo.number.parse("1000.123", {locale: "en-us"}));
+	t.is(1000, dojo.number.parse("1,000", {locale: "en-us"}));
+	t.is(-1000, dojo.number.parse("-1000", {locale: "en-us"}));
+	t.is(-1000.123, dojo.number.parse("-1000.123", {locale: "en-us"}));
+	t.is(-1234567.89, dojo.number.parse("-1,234,567.89", {locale: "en-us"}));
+	t.is(-1234567.89, dojo.number.parse("-1 234 567,89", {locale: "fr-fr"}));
+	t.t(isNaN(dojo.number.parse("-1 234 567,89", {locale: "en-us"})));
+
+	t.is(123, dojo.number.parse("0123", {pattern: "0000"}));
+
+	t.t(isNaN(dojo.number.parse("10,00", {locale: "en-us"})));
+	t.t(isNaN(dojo.number.parse("1000.1", {locale: "fr-fr"})));
+
+	t.t(isNaN(dojo.number.parse("")));
+	t.t(isNaN(dojo.number.parse("abcd")));
+
+	// should allow unlimited precision, by default
+	t.is(1.23456789, dojo.number.parse("1.23456789", {locale: "en-us"}));
+
+	//test whitespace
+//	t.is(-1234567, dojo.number.parse("  -1,234,567  ", {locale: "en-us"}));
+
+//	t.t(dojo.number.parse("9.1093826E-31"));
+	t.is(1.23, dojo.number.parse("123%", {locale: "en-us", type: "percent"}));
+	t.is(1.23, dojo.number.parse("123%", {places:0, locale: "en-us", type: "percent"}));
+	t.t(isNaN(dojo.number.parse("123.46%", {places:0, locale: "en-us", type: "percent"})));
+	t.is(1.2346, dojo.number.parse("123.46%", {places:2, locale: "en-us", type: "percent"}));
+	t.is(0.501, dojo.number.parse("50.1%", {pattern: "#0.#%", locale: 'en-us'}));
+
+	t.is(123.4, dojo.number.parse("123.4", {pattern: "#0.#", locale: 'en-us'}));
+	t.is(-123.4, dojo.number.parse("-123.4", {pattern: "#0.#", locale: 'en-us'}));
+	t.is(123.4, dojo.number.parse("123.4", {pattern: "#0.#;(#0.#)", locale: 'en-us'}));
+	t.is(-123.4, dojo.number.parse("(123.4)", {pattern: "#0.#;(#0.#)", locale: 'en-us'}));
+
+	t.is(null, dojo.number.format("abcd", {pattern: "0000"}));
+	
+	t.is(123, dojo.number.parse("123", {places:0}));
+	t.is(123, dojo.number.parse("123", {places:'0'}));
+	t.is(123.4, dojo.number.parse("123.4", {places:1, locale: 'en-us'}));
+	t.is(123.45, dojo.number.parse("123.45", {places:'1,3', locale: 'en-us'}));
+	t.is(123.45, dojo.number.parse("123.45", {places:'0,2', locale: 'en-us'}));
+			}
+		},
+		{
+			name: "format_icu4j3_6",
+			runTest: function(t){
+
+/*************************************************************************************************
+ * Evan:The following test cases are referred from ICU4J 3.6 (NumberFormatTest etc.) 
+ * see http://icu.sourceforge.net/download/3.6.html#ICU4J
+ *************************************************************************************************/
+
+
+/**
+ * In ICU4J, testing logic for NumberFormat.format() is seperated into 
+ * differernt single tese cases. So part of these logic are 
+ * collected together in this single method.
+ * 
+ * !!Failed cases are as follows:
+ * 1.1234567890987654321234567890987654321 should be formatted as 
+ *   1,234,567,890,987,654,321,234,567,890,987,654,321 with all the default parameters,
+ *   but got 1.234 instead, may due to the unimplemeted exponent.
+ * 2.\u00a4 and ' are not replaced
+ * 	 with pattern "'*&'' '\u00a4' ''&*' #,##0.00"
+ *   1.0 should be formatted to "*&' Re. '&* 1.00",but got "'*&'' '\u00a4' ''&*' 1.00" instead
+ *   etc.   
+ * 		
+ */
+	//print("test_number_format_icu4j3_6() start..............");
+	/* !!Failed case, 1.234 returned instead
+	//refer to ICU4J's NumberFormatTest.TestCoverage() 
+	var bigNum = 1234567890987654321234567890987654321;
+	var expectResult = "1,234,567,890,987,654,321,234,567,890,987,654,321";
+	tests.number.checkFormatParseCycle(t, null,bigNum,expectResult,false);
+	*/	
+	
+	//in icu4j should throw out an exception when formatting a string,
+	//but it seems dojo.number.format can deal with strings
+	//return 123,456,789
+	dojo.number.format("123456789");
+	
+	//!!Failed case, \u00a4 and ' are not replaced
+	/*
+	var options = {pattern:"'*&'' '\u00a4' ''&*' #,##0.00",locale:"en-us"};
+	tests.number.check(t, options,1.0, "*&' Re. '&* 1.00");
+	tests.number.check(t, options,-2.0, "-*&' Rs. '&* 2.00");	
+
+	options = {pattern:"#,##0.00 '*&'' '\u00a4' ''&*'",locale:"en-us"};
+	tests.number.check(t, options,1.0,"1.00 *&' Re. '&*");
+	tests.number.check(t, options,-2.0,"-2.00 *&' Rs. '&*");
+	*/
+	//print("test_number_format_icu4j3_6() end..............\n");
+			}
+		},
+		{
+			name: "format_patterns",
+			runTest: function(t){
+
+/**
+ * Refer to ICU4J's NumberFormatTest.TestPatterns() which now only coveres us locale	
+ */
+	//print("test_number_format_Patterns() start..............");
+	var patterns = (["#0.#", "#0.", "#.0", "#"]);
+	var patternsLength = patterns.length;    
+	var num = (["0","0", "0.0", "0"]);
+	var options;
+	//icu4j result seems doesn't work as:
+	//var num = (["0","0.", ".0", "0"]);      
+	for (var i=0; i<patternsLength; ++i)
+	{	
+		options = {pattern:patterns[i], locale: 'en-us'};
+		tests.number.checkFormatParseCycle(t, options,0,num[i],false);       
+	}
+	
+	//!!Failed case
+	//In ICU4J:
+	//        unquoted special characters in the suffix are illegal
+	//        so "000.000|###" is illegal; "000.000'|###'" is legal
+	//dojo.number.format:
+	//        when formatting 1.2 with illegal pattern "000.000|###"
+	//		  no exception was thrown but got "001.200|###" instead.
+	
+	/*
+	patterns = (["000.000|###","000.000'|###'"]);
+	var exception = false;
+	var result;
+	for(var i = 0; i < patterns.length; i ++){
+		try{
+			//"001.200'|###'" is return for "000.000'|###'"
+			//"001.200|###" is return for "000.000|###"
+			result = dojo.number.format(1.2,{pattern:patterns[i]});
+			print("["+i+"] 1.2 is formatted to " + result + " with pattern " + patterns[i]);
+		}catch(e){
+			exception = true;
+		}
+		if(exception && i==1){
+			throw "["+i+"]Failed when formatting 1.2 using legal pattern " + patterns[i];
+		}else if(!exception && i==0){
+			throw "["+i+"]Failed when formatting 1.2 using illegal pattern  " + patterns[i];
+		}
+	}*/	
+	//print("test_number_format_Patterns() end..............\n");
+			}
+		},
+		{
+			name: "exponential",
+			runTest: function(t){
+/**
+ * TODO: For dojo.number future version 
+ * Refer to ICU4J's NumberFormatTest.TestExponential()
+ */
+			}
+		},
+		{
+			name: "format_quotes",
+			runTest: function(t){
+/**
+ * TODO: Failed case
+ * Refer to ICU4J's NumberFormatTest.TestQuotes()
+ */
+	//print("test_number_format_Quotes() start..............");
+	//TODO: add more locales 
+	
+	//TODO:!!Failed case	
+	//Pattern "s'aa''s'c#" should format 6666 to "saa'sc6666", but got s'aa''s'c6666 instead
+	// is this case necessary?
+	/*
+	var pattern = "s'aa''s'c#";   
+	var result = dojo.number.format(6666,{pattern:pattern,locale:"en-us"});
+	var expectResult = "saa'sc6666";
+	t.is(expectResult,result);
+	*/
+	//print("test_number_format_Quotes() end..............");     
+			}
+		},
+		{
+			name: "format_rounding",
+			runTest: function(t){
+/**
+ * Refer to ICU4J's NumberFormatTest.TestRounding487() and NumberFormatTest.TestRounding()
+ */
+	//print("test_number_format_rounding() start..............");
+	tests.number.rounding(t,0.000179999, 5, "0.00018");
+	tests.number.rounding(t,0.00099, 4, "0.001");
+	tests.number.rounding(t,17.6995, 3, "17.7");
+	tests.number.rounding(t,15.3999, 0, "15");
+	tests.number.rounding(t,-29.6, 0, "-30");
+	
+	//TODO refer to NumberFormatTest.TestRounding()
+	
+	//print("test_number_format_rounding() end..............");
+			}
+		},
+		{
+			name: "format_scientific",
+			runTest: function(t){
+/**
+ * TODO: For dojo.number future version
+ * Refer to ICU4J's NumberFormatTest.TestScientific()- Exponential testing 
+ * Refer to ICU4J's NumberFormatTest.TestScientific2() 
+ * Refer to ICU4J's NumberFormatTest.TestScientificGrouping()
+ */
+			}
+		},
+		{
+			name: "format_perMill",
+			runTest: function(t){
+/**
+ * TODO: Failed case 
+ * Refer to ICU4J's NumberFormatTest.TestPerMill()
+ */
+	//print("test_number_format_PerMill() start..............");
+	var pattern;
+	var result;
+	var expectResult;
+	
+    //TODO: !!Failed case - ###.###\u2030(\u2030 is ‰)
+	//Pattern ###.###\u2030 should format 0.4857 as 485.7\u2030,but got 485.700\u2030 instead    
+	pattern = "###.###\u2030";
+	expectResult = "485.7\u2030";
+	result = dojo.number.format(0.4857,{pattern:pattern, locale: 'en-us'});
+	t.is(expectResult,result);
+
+    //TODO: !!Failed mile percent case - ###.###m
+	//Pattern "###.###m" should format 0.4857 to 485.7m, but got 0.485m instead
+	/*
+	pattern = "###.###m";
+	expectResult = "485.7m";
+	result = dojo.number.format(0.4857,{pattern:pattern,locale:"en"});
+	t.is(expectResult,result);	
+	*/
+	//print("test_number_format_PerMill() end..............\n");
+			}
+		},
+		{
+			name: "format_grouping",
+			runTest: function(t){
+/**
+ * Only test en-us and en-in 
+ * Refer to ICU4J's NumberFormatTest.TestSecondaryGrouping()
+ */
+	//print("test_number_format_Grouping() start..............");
+	//primary grouping
+	var sourceInput = 123456789;
+	var expectResult = "12,34,56,789";
+	var options = {pattern:"#,##,###",locale:"en-us"};	
+
+	//step1: 123456789 formated=> 12,34,56,789
+	//step2:12,34,56,789 parsed=> 123456789 => formated => 12,34,56,789
+	tests.number.checkFormatParseCycle(t, options,sourceInput,expectResult,true);
+						  
+	//TODO: sencondary grouping not implemented yet ?
+	//Pattern "#,###" and secondaryGroupingSize=4 should format 123456789 to "12,3456,789"			
+	
+	//Special case for "en-in" locale
+	//1876543210 should be formated as 1,87,65,43,210 in "en-in" (India)
+/*
+	sourceInput = 1876543210;
+	expectResult = "1,87,65,43,210";
+	var result = dojo.number.format(sourceInput,{locale:"en-in"});
+	t.is(expectResult,result);   
+*/
+	//print("test_number_format_Grouping() end..............\n");    
+			}
+		},
+		{
+			name: "format_pad",
+			runTest: function(t){
+/**
+ * TODO:!!Failed cases:
+ * According to ICU4J test criteria:
+ * 1.with pattern "*^##.##":
+ * 	 0 should be formatted to "^^^^0",but got "*^0" instead,
+ *   -1.3 should be formatted to "^-1.3",but got "-*^1.3" instead.
+ *   
+ * 2.with pattern "##0.0####*_ 'g-m/s^2'" :
+ *   0 should be formatted to "0.0______ g-m/s^2",but got ":0.0*_ 'g-m/s^2'" instead
+ *   1.0/3 should be formatted to "0.33333__ g-m/s^2",but got "0.33333*_ 'g-m/s^2'" instead
+ *   
+ * 3.with pattern "*x#,###,###,##0.0#;*x(###,###,##0.0#)":
+ * 	 -10 should be formatted to "xxxxxxxxxx(10.0)",but got "*x(10.0)" instead.
+ *   10 should be formatted to "xxxxxxxxxxxx10.0",but got "*x10.0" instead.
+ *   ......
+ *   -1120456.37 should be formatted to "xx(1,120,456.37)",but got "*x(1,120,456.37)" instead.
+ *   1120456.37 should be formatted to "xxxx1,120,456.37",but got "*x1,120,456.37" instead.
+ *   -1252045600.37 should be formatted to "(1,252,045,600.37)",but got "*x(1,252,045,600.37)" instead.
+ *   1252045600.37 should be formatted to "10,252,045,600.37",but got "*x10,252,045,600.37" instead.
+ *   
+ * 4.with pattern "#,###,###,##0.0#*x;(###,###,##0.0#*x)"
+ * 	 -10 should be formatted to (10.0xxxxxxxxxx),but got "(10.0*x)" instead.
+ *   10 should be formatted to "10.0xxxxxxxxxxxx",but got "10.0*x" instead.
+ *   ......
+ *   -1120456.37 should be formatted to "(1,120,456.37xx)",but got "(1,120,456.37*x)" instead.
+ *   1120456.37 should be formatted to "xxxx1,120,456.37",but got "1,120,456.37*x" instead.
+ *   -1252045600.37 should be formatted to "(1,252,045,600.37)",but got "(1,252,045,600.37*x)" instead.
+ *   1252045600.37 should be formatted to ""10,252,045,600.37"",but got "10,252,045,600.37*x" instead.*   
+ * 
+ * Refer to ICU4J's NumberFormatTest.TestPad()
+ */
+/*
+function test_number_format_pad(){
+	var locale = "en-us";
+	print("test_number_format_Pad() start..............");
+	var options = {pattern:"*^##.##",locale:locale};
+
+	tests.number.check(t, options,0,"^^^^0");
+	tests.number.check(t, options,-1.3,"^-1.3");	
+	
+	
+	options = {pattern:"##0.0####*_ 'g-m/s^2'",locale:locale};
+	tests.number.check(t, options,0,"0.0______ g-m/s^2");	
+	tests.number.checkFormatParseCycle(t, options,1.0/3,"0.33333__ g-m/s^2",true);	
+	
+	//exponent not implemented
+	//options = {pattern:"##0.0####E0*_ 'g-m/s^2'",locale:locale};
+	//tests.number.check(t, options,0,"0.0E0______ g-m/s^2");
+	//tests.number.checkFormatParseCycle(t, options,1.0/3,"333.333E-3_ g-m/s^2",true);
+	
+	// Test padding before a sign
+	options = {pattern:"*x#,###,###,##0.0#;*x(###,###,##0.0#)",locale:locale};
+
+	tests.number.check(t, options,-10,"xxxxxxxxxx(10.0)");
+	tests.number.check(t, options,-1000, "xxxxxxx(1,000.0)");
+	tests.number.check(t, options,-1000000, "xxx(1,000,000.0)");
+	tests.number.check(t, options,-100.37, "xxxxxxxx(100.37)");
+	tests.number.check(t, options,-10456.37, "xxxxx(10,456.37)");
+	tests.number.check(t, options,-1120456.37, "xx(1,120,456.37)");
+	tests.number.check(t, options,-112045600.37, "(112,045,600.37)");    
+	tests.number.check(t, options,-1252045600.37, "(1,252,045,600.37)");
+
+
+	tests.number.check(t, options,10, "xxxxxxxxxxxx10.0");
+	tests.number.check(t, options,1000, "xxxxxxxxx1,000.0");
+	tests.number.check(t, options,1000000, "xxxxx1,000,000.0");
+	tests.number.check(t, options,100.37, "xxxxxxxxxx100.37");
+	tests.number.check(t, options,10456.37, "xxxxxxx10,456.37");        
+	tests.number.check(t, options,1120456.37, "xxxx1,120,456.37");
+	tests.number.check(t, options,112045600.37, "xx112,045,600.37");
+	tests.number.check(t, options,10252045600.37, "10,252,045,600.37");
+
+	// Test padding between a sign and a number
+	options = {pattern:"#,###,###,##0.0#*x;(###,###,##0.0#*x)",locale:locale};
+	tests.number.check(t, options, -10, "(10.0xxxxxxxxxx)");
+	tests.number.check(t, options, -1000, "(1,000.0xxxxxxx)");
+	tests.number.check(t, options, -1000000, "(1,000,000.0xxx)");
+	tests.number.check(t, options, -100.37, "(100.37xxxxxxxx)");
+	tests.number.check(t, options, -10456.37, "(10,456.37xxxxx)");    
+	tests.number.check(t, options, -1120456.37, "(1,120,456.37xx)");
+	tests.number.check(t, options, -112045600.37, "(112,045,600.37)");   
+	tests.number.check(t, options, -1252045600.37, "(1,252,045,600.37)");  
+
+	tests.number.check(t, options, 10, "10.0xxxxxxxxxxxx");
+	tests.number.check(t, options, 1000, "1,000.0xxxxxxxxx");
+	tests.number.check(t, options, 1000000, "1,000,000.0xxxxx");
+	tests.number.check(t, options, 100.37, "100.37xxxxxxxxxx");
+	tests.number.check(t, options, 10456.37, "10,456.37xxxxxxx");
+	tests.number.check(t, options, 1120456.37, "1,120,456.37xxxx");
+	tests.number.check(t, options, 112045600.37, "112,045,600.37xx");
+	tests.number.check(t, options, 10252045600.37, "10,252,045,600.37");	
+	
+	//Not implemented yet,refer to NumberFormatTest.TestPatterns2()
+	//For future use - maily test pad patterns
+	print("test_number_format_Pad() end..............");
+}
+*/
+			}
+		},
+		{
+			name: "parse_icu4j3_6",
+			runTest: function(t){
+/**
+ * In ICU4J, testing logic for NumberFormat.parse() is seperated into 
+ * differernt single tese cases. So part of these logic are 
+ * collected together in this test case. * 
+ */
+	//print("test_number_parse_icu4j3_6() start..............");
+	//Refer to ICU4J's NumberFormatTest.TestParse() which is only a rudimentary version
+	var pattern = "00";
+	var str = "0.0";	
+	var result = dojo.number.parse(str,{pattern:pattern, locale: 'en-us'});
+	//TODO: add more locales
+//FIXME: is this a valid test?
+//	t.is(0,result);
+
+	/**************************************** tolerant parse *****************************************
+	 * refers to ICU4J's NumberFormatTest.TestStrictParse()??
+	 * TODO: Seems dojo.number parses string in a tolerant way.  
+	 */
+	 var options = {locale:"en-us"};
+	/*
+	 * TODO: !!Failed case,Should all pass,
+	 * but the following elements failed (all parsed to NaN):
+	 * [1]-"0 ",[2]-"0.",[3]-"0,",[5]-"0. ",[6]-"0.100,5",
+	 * [7]-".00",[9]-"12345, ",[10]-"1,234, ",[12]-"0E" 
+	 */
+	var passData = ([
+		"0",           //[0] single zero before end of text is not leading
+        //"0 ",        //[1] single zero at end of number is not leading
+        //"0.",        //[2] single zero before period (or decimal, it's ambiguous) is not leading
+        //"0,",          //[3] single zero before comma (not group separator) is not leading
+        "0.0",         //[4] single zero before decimal followed by digit is not leading
+        //"0. ",       //[5] same as above before period (or decimal) is not leading
+        //"0.100,5",   //[6] comma stops parse of decimal (no grouping)
+        //".00",       //[7] leading decimal is ok, even with zeros
+        "1234567",     //[8] group separators are not required
+        //"12345, ",   //[9] comma not followed by digit is not a group separator, but end of number
+        //"1,234, ",   //[10] if group separator is present, group sizes must be appropriate
+        "1,234,567"   //[11] ...secondary too
+        //,"0E"         //[12]not implemented yet,an exponnent not followed by zero or digits is not an exponent 
+         ]);
+	runBatchParse(options,passData,true/*tolerant parse*/);	
+	
+	/* 
+	 * TODO:!!Failed case,should all pass,
+	 * but the following failed,
+	 * [10]-"1,45 that" implies that we partially parse input
+	 */
+	var failData = ([        
+// leading zeros without separators are tolerated #6933   
+//		"00",          //[0] leading zero before zero
+//		"012",         //[1] leading zero before digit
+        "0,456",       //[2] leading zero before group separator
+        "1,2",         //[3] wrong number of digits after group separator
+        ",0",          //[4] leading group separator before zero
+        ",1",          //[5] leading group separator before digit
+        ",.02",        //[6] leading group separator before decimal
+        "1,.02",       //[7] group separator before decimal
+        "1,,200",      //[8] multiple group separators
+        "1,45",        //[9] wrong number of digits in primary group
+        //"1,45 that",   //[10] wrong number of digits in primary group
+        "1,45.34",     //[11] wrong number of digits in primary group
+        "1234,567",    //[12] wrong number of digits in secondary group
+        "12,34,567",   //[13] wrong number of digits in secondary group
+        "1,23,456,7890" //[14] wrong number of digits in primary and secondary groups
+		]);
+	runBatchParse(options,failData,false);
+	
+	 options = {pattern:"#,##,##0.#",locale:"en-us"};
+	/*
+	 * TODO:!!Failed case,shoudl all pass.
+	 
+	 * but [1] [2] and [3] failed
+	 * should be parsed to 1234567,but NaN instead 
+	 */
+	var mixedPassData = ([            
+		"12,34,567"    	//[0]
+        //,"12,34,567,"		//[1]
+        //"12,34,567, that",//[2]
+        //"12,34,567 that"	//[3]
+		]);	
+	runBatchParse(options,mixedPassData,true/*tolerant parse*/);
+	
+	/*
+	 * TODO:!!Failed case,should all pass,
+	 * but actually mixedFailData[2] and mixedFailData[3] passed.
+	 * "12,34,56, that " and [3]-"12,34,56 that" should be parsed to 123456,but NaN instead
+	 */
+	var mixedFailData = ([
+        "12,34,56",			//[0]
+        "12,34,56,"		//[1]
+        //,"12,34,56, that ",//[2]
+        //"12,34,56 that",	//[3]
+		]);			
+	runBatchParse(options,mixedFailData,false);
+	
+
+	/**************************************** strict parse ******************************************
+	 * TODO:May need to test strict parsing in the future?
+	 * e.g. A strict parsing like (with pattern "#,##0.#") 
+	 * 1.Leading zeros
+	 * 		'00', '0123' fail the parse, but '0' and '0.001' pass
+	 * 2.Leading or doubled grouping separators
+	 * 		',123' and '1,,234" fail
+	 * 3.Groups of incorrect length when grouping is used
+	 * 		'1,23' and '1234,567' fail, but '1234' passes
+	 * 4.Grouping separators used in numbers followed by exponents
+	 * 		'1,234E5' fails, but '1234E5' and '1,234E' pass
+	 */	
+	//options={locale:"en",strict:true};
+	//runBatchParse(options,passData,false/*strict parse*/);
+	//runBatchParse(options,failData,false/*strict parse*/);	
+	
+	//options = {pattern:"#,##,##0.#",locale:"en-us",strict:true};
+	//runBatchParse(options,mixedPassData,false/*strict parse*/);
+	//runBatchParse(options,mixedFailData,false/*strict parse*/);		
+
+	//print("test_number_parse_icu4j3_6() end..............\n");
+			}
+		},
+		{
+			name: "parse_whitespace",
+			runTest: function(t){
+/**
+ * TODO:!!Failed case
+ * With pattern "a  b#0c  ",both "a b3456c " and and "a   b1234c   " should be parsed to 3456,but got NaN instead.
+ * 
+ * Refer to ICU4J's NumberFormatTest.TestWhiteSpaceParsing
+ */
+    /*
+	print("test_number_parse_WhiteSpace() start..............");
+   	var pattern = "a  b#0c  ";
+	var expectResult = 3456;   
+	result =  dojo.number.parse("a b3456c ",{pattern:pattern,locale:"en-us"});
+   	t.is(expectResult,result);	
+	result =  dojo.number.parse("a   b3456c   ",{pattern:pattern,locale:"en-us"});
+	t.is(expectResult,result);
+	print("test_number_parse_WhiteSpace() end..............\n");
+	*/   
+			}
+		},
+/*************************************************************************************************
+ *                            Regression test cases
+ * These test cases are referred to ICU4J's NumberFormatRegressionTest and NumberFormatRegression.
+ * The regression cases in ICU4J are used as unit test cases for bug fixing, 
+ * They are inluced here so that dojo.number may avoid those similar bugs. 
+ *************************************************************************************************/
+		{
+			name: "number_regression_1",
+			runTest: function(t){
+/**
+ * Refer to ICU4J's NumberFormatRegressionTest.Test4161100()
+ */
+	tests.number.checkFormatParseCycle(t, {pattern:"#0.#", locale: 'en-us'},-0.09,"-0.1",false);
+			}
+		},
+		{
+			name: "number_regression_2",
+			runTest: function(t){
+/**
+ * !!Failed case,rounding hasn't been implemented yet.
+ * Refer to ICU4J's NumberFormatRegressionTest.Test4408066()
+ */
+	/*
+	var data =   ([-3.75, -2.5, -1.5, 
+                   -1.25, 0,    1.0, 
+                   1.25,  1.5,  2.5, 
+                   3.75,  10.0, 255.5]);
+	var expected = (["-4", "-2", "-2",
+                    "-1", "0",  "1",
+                	"1",  "2",  "2",
+                	"4",  "10", "256"]);
+	var options = {locale:"zh-cn",round:true};
+	for(var i =0; i < data.length; i++){
+		tests.number.checkFormatParseCycle(t, options,data[i],expected[i],false);
+	}	
+
+	data = ([ 	"-3.75", "-2.5", "-1.5", 
+              	"-1.25", "0",    "1.0", 
+              	"1.25",  "1.5",  "2.5", 
+              	"3.75",  "10.0", "255.5"]);
+	expected =([ -3, -2, -1,
+                 -1, 0,  1,
+                 1,  1,  2,
+                 3,  10, 255]);
+	
+	for(var i =0; i < data.length; i++){
+		tests.number.checkParse(t, options,data[i],expected[i]);
+	}
+	*/
+			}
+		},
+		{
+			name: "number_regression_3",
+			runTest: function(t){
+/**
+ * Refer to ICU4J's NumberRegression.Test4087535() and Test4243108()
+ */
+	tests.number.checkFormatParseCycle(t, {places:0},0,"0",false);
+	//TODO:in icu4j,0.1 should be formatted to ".1" when minimumIntegerDigits=0
+	tests.number.checkFormatParseCycle(t, {places:0},0.1,"0",false);	
+	tests.number.checkParse(t, {pattern:"#0.#####", locale: 'en-us'},123.55456,123.55456);
+//!! fails because default pattern only has 3 decimal places
+//	tests.number.checkParse(t, null,123.55456,123.55456);
+	
+	//See whether it fails first format 0.0 ,parse "99.99",and then reformat 0.0 
+	tests.number.checkFormatParseCycle(t, {pattern:"#.#"},0.0,"0",false);
+	tests.number.checkParse(t, {locale: 'en-us'},"99.99",99.99);
+	tests.number.checkFormatParseCycle(t, {pattern:"#.#"},0.0,"0",false);
+			}
+		},
+		{
+			name: "number_regression_4",
+			runTest: function(t){
+/**
+ * TODO:
+ * In ICU -0.0 and -0.0001 should be formatted to "-0" with FieldPosition(0)
+ * dojo.i18n.number format -0.0 to "-0"; -0.0001 to "-0.000100" 
+ * 
+ * Refer to ICU4J's NumberRegression.Test4088503() and Test4106658()
+ */
+	tests.number.checkFormatParseCycle(t, {places:0},123,"123",false);
+	
+	//TODO: differernt from ICU where -0.0 is formatted to "-0"
+	tests.number.checkFormatParseCycle(t, {locale:"en-us"},-0.0,"0",false);
+	
+	//TODO: differernt from ICU where -0.0001 is formatted to "-0"
+	tests.number.checkFormatParseCycle(t, {locale:"en-us",places:6},-0.0001,"-0.000100",false);
+			}
+		},
+		{
+			name: "number_regression_5",
+			runTest: function(t){
+/**
+ * !!Failed case,rounding has not implemented yet.
+ * 0.00159999 should be formatted as 0.0016 but got 0.0015 instead.
+ * Refer to ICU4J's NumberRegression.Test4071492()
+ */
+	//tests.number.checkFormatParseCycle(t, {places:4,round:true},0.00159999,"0.0016",false);	
+			}
+		},
+		{
+			name: "number_regression_6",
+			runTest: function(t){
+/**
+ * Refer to ICU4J's NumberRegression.Test4086575()
+ */
+	var pattern = "###.00;(###.00)";
+	var locale = "fr";
+	var options = {pattern:pattern,locale:locale};
+	
+	//no group separator
+	tests.number.checkFormatParseCycle(t, options,1234,"1234,00",false);
+	tests.number.checkFormatParseCycle(t, options,-1234,"(1234,00)",false);	
+	
+	//space as group separator
+	pattern = "#,###.00;(#,###.00)";
+	options = {pattern:pattern,locale:locale};
+	tests.number.checkFormatParseCycle(t, options,1234,"1\u00a0234,00",false);// Expect 1 234,00
+	tests.number.checkFormatParseCycle(t, options,-1234,"(1\u00a0234,00)",false);  // Expect (1 234,00)
+			}
+		},
+		{
+			name: "number_regression_7",
+			runTest: function(t){
+/**
+ * !!Failed case - expontent has not implemented yet 
+ * shuold format 1.000000000000001E7 to 10000000.00000001, but got 10,000,000.000 instead
+ * Refer to ICU4J's NumberRegression.Test4090489() - loses precision
+ */
+	//tests.number.checkFormatParseCycle(t, null,1.000000000000001E7,"10000000.00000001",false);	
+			}
+		},
+		{
+			name: "number_regression_8",
+			runTest: function(t){
+/** 
+ * !!Failed case
+ * 1.with pattern "#,#00.00 p''ieces;-#,#00.00 p''ieces"
+ *   3456.78 should be formated to "3,456.78 p'ieces",
+ *   but got "3,456.78 p''ieces","''" should be replaced with "'"
+ * 2.with illegal pattern "000.0#0"
+ * 	 no error for the illegal pattern, and 3456.78 is formatted to 456.780
+ * 3.with illegal pattern "0#0.000"
+ * 	 no error for the illegal pattern, and 3456.78 is formatted to 3456.780
+ * 
+ * Refer to ICU4J's NumberRegression.Test4092480(),Test4074454() 
+ */
+	var patterns = (["#0000","#000","#00","#0","#"]);
+	var expect = (["0042","042","42","42","42"]);
+	
+	for(var i =0; i < patterns.length; i ++){
+		tests.number.checkFormatParseCycle(t, {pattern:patterns[i]},42,expect[i],false);
+		tests.number.checkFormatParseCycle(t, {pattern:patterns[i]},-42,"-"+expect[i],false);	
+	}
+	
+	tests.number.checkFormatParseCycle(t, {pattern:"#,#00.00;-#.#", locale: 'en-us'},3456.78,"3,456.78",false);
+	//!!Failed case
+	//tests.number.checkFormatParseCycle(t, {pattern:"#,#00.00 p''ieces;-#,#00.00 p''ieces"},3456.78,"3,456.78 p'ieces",false);	
+	//tests.number.checkFormatParseCycle(t, {pattern:"000.0#0"},3456.78,null,false);
+	//tests.number.checkFormatParseCycle(t, {pattern:"0#0.000"},3456.78,null,false);	
+			}
+		},
+		{
+			name: "number_regression_9",
+			runTest: function(t){
+/**
+ * TODO
+ * Refer to ICU4J's NumberRegression.Test4052223()
+ */
+	//TODO:only got NaN,need an illegal pattern exception? 
+	tests.number.checkParse(t, {pattern:"#,#00.00"},"abc3");	
+	
+	//TODO: got NaN instead of 1.222, is it ok?
+	//tests.number.checkParse(t, {pattern:"#,##0.###",locale:"en-us"},"1.222,111",1.222);
+	//tests.number.checkParse(t, {pattern:"#,##0.###",locale:"en-us"},"1.222x111",1.222);
+	
+	//got NaN for illeal input,ok
+	tests.number.checkParse(t, null,"hello: ,.#$@^&**10x");	
+			}
+		},
+		{
+			name: "number_regression_10",
+			runTest: function(t){
+/**
+ * Refer to ICU4J's NumberRegression.Test4125885()
+ */
+	tests.number.checkFormatParseCycle(t, {pattern:"000.00", locale: 'en-us'},12.34,"012.34",false);
+	tests.number.checkFormatParseCycle(t, {pattern:"+000.00%;-000.00%", locale: 'en-us'},0.1234,"+012.34%",false);
+	tests.number.checkFormatParseCycle(t, {pattern:"##,###,###.00", locale: 'en-us'},9.02,"9.02",false);
+	
+	var patterns =(["#.00", "0.00", "00.00", "#0.0#", "#0.00"]);
+	var expect =  (["1.20", "1.20", "01.20", "1.2",   "1.20" ]);
+	for(var i =0 ; i < patterns.length; i ++){
+		tests.number.checkFormatParseCycle(t, {pattern:patterns[i], locale: 'en-us'},1.2,expect[i],false);
+	}
+			}
+		},
+		{
+			name: "number_regression_11",
+			runTest: function(t){
+/**
+ * TODO:!!Failed case
+ * Make sure that all special characters, when quoted in a suffix or prefix, lose their special meaning.
+ * The detail error info :  
+ * for input 123
+ * pattern:'0'#0'0'; expect:"01230"; but got "'3'#0'0'" instead
+ * pattern:','#0','; expect:",123,"; but got "','123','" instead
+ * pattern:'.'#0'.'; expect:".123."; but got "'.'123'.'" instead
+ * pattern:'‰'#0'‰'; expect:"‰123‰"; but got "'‰'123000'‰'" instead
+ * pattern:'%'#0'%'; expect:"%123%"; but got "'%'12300'%'" instead
+ * pattern:'#'#0'#'; expect:"#123#"; but got "'123'#0'#'" instead
+ * pattern:';'#0';'; expect:";123;"; but got "[dojo-test] FATAL exception raised: 
+ * 											  unable to find a number expression in pattern: '"
+ * pattern:'E'#0'E'; expect:"E123E"; not implemeted yet
+ * pattern:'*'#0'*'; expect:"*123*"; but got "'*'123'*'" instead
+ * pattern:'+'#0'+'; expect:"+123+"; but got "'+'123'+'" instead
+ * pattern:'-'#0'-'; expect:"-123-"; but got "'-'123'-'" instead
+ * 
+ * TODO: is it ok to remain "'" in the formatted result as above??
+ * 
+ * Refer to ICU4J's NumberRegression.Test4212072()
+ */
+/*
+	var specials = ([ '0', ',', '.', '\u2030', '%', '#',';', 'E', '*', '+', '-']);
+	var pattern; 
+	var expect;
+	
+	for(var i=0; i < specials.length; i ++){
+		pattern = "'" + specials[i] + "'#0'" + specials[i] + "'";
+		expect = "" +  specials[i] + "123" +  specials[i];
+		tests.number.checkFormatParseCycle(t, {pattern:pattern,locale:"en-us"},123,expect,false);
+	}
+*/
+			}
+		},
+		{
+			name: "number_regression_12",
+			runTest: function(t){
+/**
+ * TODO: add more rounding test cases, refer to ICU4J's NumberRegression.Test4071005(),Test4071014() etc.. 
+ */
+
+/**
+ * TODO:Decimal format doesnt round a double properly when the number is less than 1
+ * 
+ * Refer to ICU4J's NumberRegression.test4241880()
+ */
+/*
+	var input = ([ .019, .009, .015, .016, .014,
+                	.004, .005, .006, .007, .008,
+                	.5, 1.5, .05, .15, .005,
+                	.015, .0005, .0015]);
+	var patterns = (["##0%", "##0%", "##0%", "##0%", "##0%",
+                	 "##0%", "##0%", "##0%", "##0%", "##0%",
+                	 "#,##0", "#,##0", "#,##0.0", "#,##0.0", "#,##0.00",
+                	 "#,##0.00", "#,##0.000", "#,##0.000"]);
+	var expect =([   "2%", "1%", "2%", "2%", "1%",
+                	 "0%", "0%", "1%", "1%", "1%",
+                	 "0", "2", "0.0", "0.2", "0.00",
+                	 "0.02", "0.000", "0.002"]);
+	for(var i = 0; i <input.length; i ++){
+		tests.number.checkFormatParseCycle(t, {pattern:patterns[i],round:true},input[i],expect[i],false);
+	}
+*/
+			}
+		}
+	]
+);
diff --git a/dojo/tests/parser.html b/dojo/tests/parser.html
new file mode 100644
index 0000000..5e4f100
--- /dev/null
+++ b/dojo/tests/parser.html
@@ -0,0 +1,408 @@
+<html>
+	<head>
+		<title>Parser Unit Test</title>
+		<style type="text/css">
+			@import "../resources/dojo.css";
+		</style>
+		<script type="text/javascript"
+			src="../dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("doh.runner");
+
+			dojo.declare("tests.parser.Class1", null, {
+				constructor: function(args, node){
+					this.params = args;
+					dojo.mixin(this, args);
+				}, 
+				preambleTestProp: 1,
+				preamble: function(){
+					this.preambleTestProp++;
+				},
+				intProp: 1,
+				callCount: 0, // for connect testing
+				callInc: function(){ this.callCount++; },
+				callCount2: 0, // for assignment testing
+				strProp1: "original1",
+				strProp2: "original2",
+				arrProp: [],
+				arrProp2: ["foo"],
+				boolProp1: false,
+				boolProp2: true,
+				boolProp3: false,
+				boolProp4: true,
+				dateProp1: dojo.date.stamp.fromISOString('2007-01-01'),
+				dateProp2: dojo.date.stamp.fromISOString('2007-01-01'),
+				dateProp3: dojo.date.stamp.fromISOString('2007-01-01'),
+				funcProp: function(){},
+				funcProp2: function(){},
+				funcProp3: function(){},
+				onclick: function(){ this.prototypeOnclick=true; }
+				// FIXME: have to test dates!!
+				// FIXME: need to test the args property!!
+			});
+
+			dojo.declare("tests.parser.Class2", null, {
+				constructor: function(){
+					this.fromMarkup = false;
+				}, 
+				fromMarkup: false,
+				markupFactory: function(args, node, classCtor){
+					var i = new tests.parser.Class2();
+					i.fromMarkup = true;
+					return i;
+				}
+			});
+
+
+			dojo.declare("tests.parser.Class3", tests.parser.Class2, {
+				fromMarkup: false,
+				markupFactory: function(args, node, classCtor){
+					var i = new classCtor();
+					i.classCtor = classCtor;
+					i.params = args;
+					return i;
+				}
+			});
+			
+			dojo.declare("tests.parser.inputClass", null, {
+				constructor: function(args, node){ dojo.mixin(this, args); },
+				// these attributes are special in HTML, they don't have a value specified
+				disabled: false,
+				checked: false
+			});
+
+			// Test that dir attribute can be inherited from ancestor node
+			dojo.declare("tests.parser.DirClass", null, {
+				constructor: function(args, node){ dojo.mixin(this, args); },
+				dir: "",
+				name: ""
+			});
+
+			// For testing that parser recurses correctly, except when the prototype has a
+			// stopParser flag
+			dojo.declare("tests.parser.NormalContainer", null, {
+				constructor: function(args, node){ dojo.mixin(this, args); }
+			});
+			dojo.declare("tests.parser.ShieldedContainer", null, {
+				constructor: function(args, node){ dojo.mixin(this, args); },
+				
+				// flag to tell parser not to instantiate nodes inside of me
+				stopParser: true
+			});
+
+			deepTestProp = {
+				blah: {
+					thinger: 1
+				}
+			};
+
+			dojo.addOnLoad(function(){
+				doh.register("t",
+					[
+						function testJsId(t){
+							// console.debug(obj);
+							t.t(typeof obj == "object");
+						},
+
+						// Attribute parsing tests
+						function testStrProp(t){
+							// normal string parameter
+							t.t(dojo.isString(obj.strProp1));
+							t.is("text", obj.strProp1);
+							
+							// make sure that you override a string value like "foo" to a blank value
+							t.t(dojo.isString(obj.strProp2));
+							t.is("", obj.strProp2);
+						},
+						function testIntProp(t){
+							t.is("number", (typeof obj.intProp));
+							t.is(5, obj.intProp);
+						},
+						function testArrProp(t){
+							t.is(3, obj.arrProp.length);
+							t.is(3, obj.arrProp[1].length);
+							t.is(["foo", "bar", "baz"], obj.arrProp);
+
+							// make sure empty arrays are possible
+							t.is([], obj.arrProp2);
+						},
+						function testBoolProp(t){
+							// make sure that both true and false get read correctly,
+							// and that unspecified attributes' values don't change
+							
+							// boolProp1 specified at true
+							t.is("boolean", (typeof obj.boolProp1));
+							t.t(obj.boolProp1);
+							
+							// boolProp2 specified as false
+							t.is("boolean", (typeof obj.boolProp2));
+							t.f(obj.boolProp2);
+							
+							// boolProp3 not specified (prototype says false)
+							t.is("boolean", (typeof obj.boolProp3));
+							t.f(obj.boolProp3);
+							
+							// boolProp4 not specified (prototype says true)
+							t.is("boolean", (typeof obj.boolProp4));
+							t.t(obj.boolProp4);
+						},
+						function testDateProp(t){
+							// dateProp1 specified as 2006-1-1
+							t.is("2006-01-01", dojo.date.stamp.toISOString(obj.dateProp1, {selector: 'date'}));
+							
+							// dateProp2="", should map to NaN (a blank value on DateTextBox)
+							t.t(isNaN(obj.dateProp2));
+							
+							// dateProp3="now", should map to current date
+							t.is(dojo.date.stamp.toISOString(new Date(), {selector: 'date'}),
+								dojo.date.stamp.toISOString(obj.dateProp3, {selector: 'date'}));
+						},
+						function testUnwantedParams(t){
+							// Make sure that parser doesn't pass any unwanted parameters to
+							// widget constructor, especially "toString" or "constructor".
+							// Make exception for dir/lang which parser gleans from document itself.
+							for(var param in obj.params){
+								doh.t(dojo.indexOf(
+									["strProp1", "strProp2",
+									"intProp",
+									"arrProp", "arrProp2",
+									"boolProp1", "boolProp2",
+									"dateProp1", "dateProp2", "dateProp3",
+									"funcProp2", "funcProp3",
+									"preamble",
+									"callInc1", "callInc2", "dir", "lang"],
+									param) >= 0, param);
+							}
+						},
+						function testDisabledFlag(t){
+							t.is("boolean", (typeof disabledObj.disabled));
+							t.t(disabledObj.disabled);
+							t.f(disabledObj.checked);
+						},
+						function testCheckedFlag(t){
+							t.is("boolean", (typeof checkedObj.checked));
+							t.f(checkedObj.disabled);
+							t.t(checkedObj.checked);
+						},
+						function testFunctionProp(t){
+							// make sure that unspecified functions (even with common names)
+							// don't get overridden (bug #3074)
+							obj.onclick();
+							t.t(obj.prototypeOnclick);
+							
+							// funcProp2="foo"
+							obj.funcProp2();
+							t.t(obj.fooCalled);
+							
+							// funcProp3="this.func3Called=true;"
+							obj.funcProp3();
+							t.t(obj.func3Called);
+						},
+
+						// test <script> tags inside innerHTML of source node
+						"t.is(4, obj.preambleTestProp);",
+						"t.is(deepTestProp, obj.deepProp);",
+						function testConnect(t){
+							obj.callInc();
+							t.is(2, obj.callCount);
+						},
+						function testFunctionAssignment(t){
+							obj.callInc2();
+							t.is(1, obj.callCount2);
+						},
+						function testSubNodeParse(t){
+							t.f(dojo.exists("obj2"));
+							var toParse = dojo.byId("toParse");
+							toParse.setAttribute("dojoType", toParse.getAttribute("type"));
+							dojo.parser.parse(toParse.parentNode);
+							t.t(dojo.exists("obj2"));
+							t.is("tests.parser.Class1", obj2.declaredClass);
+						},
+						function testMarkupFactory(t){
+							t.t(dojo.exists("obj3"));
+							t.t(obj3.fromMarkup);
+						},
+						function testMarkupFactoryClass(t){
+							t.t(dojo.exists("obj4"));
+							t.is(obj4.classCtor, tests.parser.Class3);
+							t.t(obj4 instanceof tests.parser.Class3);
+							t.t(obj4 instanceof tests.parser.Class2);
+						},
+						function testnostart(t){
+						  
+							var started = false;
+							dojo.declare("SampleThinger", null, {
+								startup: function(){
+									started = true;
+								}
+							});
+						  
+							dojo.create("div", { dojoType:"SampleThinger" }, "parsertest");
+							dojo.parser.parse("parsertest", { noStart:true });
+							
+							t.f(started);
+							
+							dojo.empty("parsertest");
+							
+							started = false;
+							
+							dojo.create("div", { dojoType:"SampleThinger" }, "parsertest");
+							dojo.parser.parse({ noStart:true, rootNode:"parsertest" });
+			  				
+							t.f(started);
+						},
+						
+						// test the various iterations of parser test
+						function rootTest(t){
+						  
+							var handle = function(sel, root){
+								t.is("parsertest2", root);
+							}
+							var tmp = dojo.connect(dojo, "query", handle);
+							
+							dojo.parser.parse("parsertest2");
+							dojo.parser.parse({ rootNode: "parsertest2" });
+							dojo.parser.parse("parsertest2", { noStart:true });
+							
+							dojo.disconnect(tmp);
+							
+						},
+
+						// Test that when BorderContainer etc. extends _Widget,
+						// parser is aware of the new parameters added (to _Widget
+						// and all of it's subclasses)
+						function cacheRefresh(t){
+							// Add new node to be parsed, referencing a widget that the parser has already
+							// dealt with (and thus cached)
+							var wrapper = dojo.place("<div><div dojoType='tests.parser.Class3' newParam=12345>hi</div></div>", dojo.body(), "last");
+							
+							// Modify Class3's superclass widget to have new parameter (thus Class3 inherits it)
+							dojo.extend(tests.parser.Class2, {
+								newParam: 0
+							});
+							
+							// Run the parser and see if it reads in newParam
+							var widgets = dojo.parser.parse({rootNode: wrapper});
+							doh.is(1, widgets.length, "parsed newly inserted parserTest widget");
+							doh.is(12345, widgets[0].params.newParam, "new parameter parsed");
+						},
+
+						// Test that dir=rtl or dir=ltr setting trickles down from root node
+						function dir(){				
+							doh.is("rtl", setRtl.dir, "direct setting of dir=rtl works");
+							doh.is("rtl", inheritRtl.dir, "inherited rtl works");
+							doh.is("ltr", inheritLtr.dir, "inherited ltr works (closest ancestor wins)");
+							doh.is("rtl", inheritRtl2.dir, "inherited rtl works, from grandparent");
+							doh.is("ltr", setLtr.dir, "direct setting of dir=ltr overrides inherited RTL");
+						},
+						
+						// Test that parser recurses correctly, except when there's a stopParser flag not to
+						function recurse(){
+							doh.t(container1, "normal container created");
+							doh.t(container1.incr, "script tag works too")
+							doh.t(window.contained1, "child widget also created");
+							doh.t(window.contained2, "child widget 2 also created");
+
+							doh.t(container2, "shielded container created");
+							doh.t(container2.incr, "script tag works too")
+							doh.f(window.contained3, "child widget not created");
+							doh.f(window.contained4, "child widget 2 not created");
+						}
+					]
+				);
+				doh.run();
+			})
+		</script>
+	</head>
+	<body>
+		<h1>Parser Unit Test</h1>
+		<script>
+			function foo(){ this.fooCalled=true; }
+		</script>
+		<div dojoType="tests.parser.Class1" jsId="obj" 
+			strProp1="text" strProp2=""
+			intProp="5"
+			arrProp="foo, bar, baz"
+			arrProp2=""
+			boolProp1="true" boolProp2="false"
+			dateProp1="2006-01-01" dateProp2="" dateProp3="now"
+			funcProp2="foo" funcProp3="this.func3Called=true;"
+		>
+			<script type="dojo/method" event="preamble">
+				this.preambleTestProp = 3;
+			</script>
+			<script type="dojo/method">
+				// this should be run immediately
+				this.deepProp = deepTestProp;
+			</script>
+			<script type="dojo/connect" event="callInc">
+				this.callCount++;
+			</script>
+			<script type="dojo/method" event="callInc2">
+				this.callCount2++;
+			</script>
+		</div>
+		<div>
+			<div type="tests.parser.Class1" jsId="obj2" id="toParse">
+			</div>
+		</div>
+		<div dojoType="tests.parser.Class2" jsId="obj3">
+		</div>
+		<div dojoType="tests.parser.Class3" jsId="obj4">
+		</div>
+		<input dojoType="tests.parser.inputClass" jsId="checkedObj" checked type="checkbox">
+		<button dojoType="tests.parser.inputClass" jsId="disabledObj" disabled>hi</button>
+		
+		<div id="parsertest"></div>
+		<div id="parsertest2"></div>
+
+		<!-- section for testing that dir attribute trickles down from ancestor -->
+		<div dojoType="tests.parser.DirClass" jsId="setRtl" dir="rtl" name="RTL setting"></div>
+		<div dir="rtl">
+			<div dojoType="tests.parser.DirClass" jsId="inheritRtl" name="inherited RTL from parent"></div>
+			<div dir="ltr">
+				<div dojoType="tests.parser.DirClass" jsId="inheritLtr" name="inherited LTR from parent"></div>
+			</div>
+			<div>
+				<div dojoType="tests.parser.DirClass" jsId="inheritRtl2" name="inherited RTL from grandparent"></div>
+			</div>
+			<div dojoType="tests.parser.DirClass" jsId="setLtr" dir="ltr" name="LTR setting overrides inherited RTL"></div>
+		</div>
+		<div dojoType="tests.parser.DirClass" jsId="noDir" name="dir not inherited or set"></div>
+		
+		<!-- section for testing parser recursion -->
+
+		<div>
+			<div dojoType="tests.parser.NormalContainer" jsId="container1">
+				<!-- this script tag should get passed as param to NormalContainer constructor -->
+				<script type="dojo/method" event="incr" args="x">
+					return x+1;
+				</script>
+				
+				<!-- and these contained widgets should get instantiated -->
+				<div dojoType="tests.parser.Class1" jsId="contained1"></div>
+				<div>
+					<div dojoType="tests.parser.Class1" jsId="contained2"></div>			
+				</div>
+			</div>
+		</div>
+
+		<div>
+			<div dojoType="tests.parser.ShieldedContainer" jsId="container2">
+				<!-- this script tag should get passed as param to NormalContainer constructor -->
+				<script type="dojo/method" event="incr" args="x">
+					return x+1;
+				</script>
+				
+				<!-- but these contained widgets should *not* get instantiated -->
+				<div dojoType="tests.parser.Class1" jsId="contained3"></div>
+				<div>
+					<div dojoType="tests.parser.Class1" jsId="contained4"></div>			
+				</div>
+			</div>
+		</div>
+
+	</body>
+</html>
diff --git a/dojo/tests/parser.js b/dojo/tests/parser.js
new file mode 100644
index 0000000..02cb856
--- /dev/null
+++ b/dojo/tests/parser.js
@@ -0,0 +1,4 @@
+dojo.provide("tests.parser");
+if(dojo.isBrowser){
+	doh.registerUrl("tests.parser", dojo.moduleUrl("tests", "parser.html"));
+}
diff --git a/dojo/tests/regexp.js b/dojo/tests/regexp.js
new file mode 100644
index 0000000..ea156d5
--- /dev/null
+++ b/dojo/tests/regexp.js
@@ -0,0 +1,12 @@
+dojo.provide("tests.regexp");
+
+dojo.require("dojo.regexp");
+
+tests.register("tests.regexp", 
+	[
+		function test_regexp_escape(t){
+			t.assertTrue(new RegExp(dojo.regexp.escapeString("\f\b\n\t\r+.$?*|{}()[]\\/^")).test("TEST\f\b\n\t\r+.$?*|{}()[]\\/^TEST"));
+			t.assertTrue(new RegExp(dojo.regexp.escapeString("\f\b\n\t\r+.$?*|{}()[]\\/^", ".")).test("TEST\f\b\n\t\r+X$?*|{}()[]\\/^TEST"));
+		}
+	]
+);
diff --git a/dojo/tests/resources/ApplicationState.js b/dojo/tests/resources/ApplicationState.js
new file mode 100644
index 0000000..a25e7ff
--- /dev/null
+++ b/dojo/tests/resources/ApplicationState.js
@@ -0,0 +1,28 @@
+/*
+ApplicationState is an object that represents the application state.
+It will be given to dojo.undo.browser to represent the current application state.
+*/
+ApplicationState = function(stateData, outputDivId, backForwardOutputDivId, bookmarkValue){
+	this.stateData = stateData;
+	this.outputDivId = outputDivId;
+	this.backForwardOutputDivId = backForwardOutputDivId;
+	this.changeUrl = bookmarkValue;
+}
+
+ApplicationState.prototype.back = function(){
+	this.showBackForwardMessage("BACK for State Data: " + this.stateData);
+	this.showStateData();
+}
+
+ApplicationState.prototype.forward = function(){
+	this.showBackForwardMessage("FORWARD for State Data: " + this.stateData);
+	this.showStateData();
+}
+
+ApplicationState.prototype.showStateData = function(){
+	dojo.byId(this.outputDivId).innerHTML += this.stateData + '<br />';
+}
+
+ApplicationState.prototype.showBackForwardMessage = function(message){
+	dojo.byId(this.backForwardOutputDivId).innerHTML += message + '<br />';
+}
diff --git a/dojo/tests/resources/JSON.php b/dojo/tests/resources/JSON.php
new file mode 100755
index 0000000..e87e4d0
--- /dev/null
+++ b/dojo/tests/resources/JSON.php
@@ -0,0 +1,724 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/** 
+ * Converts to and from JSON format.
+ * 
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
+ * format. It is easy for humans to read and write. It is easy for machines
+ * to parse and generate. It is based on a subset of the JavaScript
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+ * This feature can also be found in  Python. JSON is a text format that is
+ * completely language independent but uses conventions that are familiar
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
+ * ideal data-interchange language.
+ * 
+ * This package provides a simple encoder and decoder for JSON notation. It
+ * is intended for use with client-side Javascript applications that make
+ * use of HTTPRequest to perform server communication functions - data can
+ * be encoded into JSON notation for use in a client-side javascript, or
+ * decoded from incoming Javascript requests. JSON format is native to
+ * Javascript, and can be directly eval()'ed with no further parsing
+ * overhead
+ *
+ * All strings should be in ASCII or UTF-8 format!
+ *
+ * LICENSE: Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met: Redistributions of source code must retain the
+ * above copyright notice, this list of conditions and the following
+ * disclaimer. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * 
+ * @category   
+ * @package     Services_JSON
+ * @author      Michal Migurski <mike-json at teczno.com>
+ * @author      Matt Knapp <mdknapp[at]gmail[dot]com>
+ * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+ * @copyright   2005 Michal Migurski
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+ */
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_SLICE',   1);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_STR',  2);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_ARR',  4);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_OBJ',  8);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_CMT', 16);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_LOOSE_TYPE', 10);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_STRICT_TYPE', 11);
+
+/** 
+ * Converts to and from JSON format.
+ *
+ * Brief example of use:
+ *
+ * <code>
+ * // create a new instance of Services_JSON
+ * $json = new Services_JSON();
+ * 
+ * // convert a complexe value to JSON notation, and send it to the browser
+ * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
+ * $output = $json->encode($value);
+ *
+ * print($output);
+ * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
+ * 
+ * // accept incoming POST data, assumed to be in JSON notation
+ * $input = file_get_contents('php://input', 1000000);
+ * $value = $json->decode($input);
+ * </code>
+ */
+class Services_JSON
+{
+   /**
+    * constructs a new JSON instance
+    *
+    * @param    int     $use    object behavior: when encoding or decoding,
+    *                           be loose or strict about object/array usage
+    *
+    *                           possible values:
+    *                           - SERVICES_JSON_STRICT_TYPE: strict typing, default.
+    *                                                        "{...}" syntax creates objects in decode().
+    *                           - SERVICES_JSON_LOOSE_TYPE:  loose typing.
+    *                                                        "{...}" syntax creates associative arrays in decode().
+    */
+    function Services_JSON($use = SERVICES_JSON_STRICT_TYPE)
+    {
+        $this->use = $use;
+    }
+
+   /**
+    * convert a string from one UTF-16 char to one UTF-8 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf16  UTF-16 character
+    * @return   string  UTF-8 character
+    * @access   private
+    */
+    function utf162utf8($utf16)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding'))
+            return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
+        
+        $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
+
+        switch(true) {
+            case ((0x7F & $bytes) == $bytes):
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x7F & $bytes);
+
+            case (0x07FF & $bytes) == $bytes:
+                // return a 2-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xC0 | (($bytes >> 6) & 0x1F))
+                     . chr(0x80 | ($bytes & 0x3F));
+
+            case (0xFFFF & $bytes) == $bytes:
+                // return a 3-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xE0 | (($bytes >> 12) & 0x0F))
+                     . chr(0x80 | (($bytes >> 6) & 0x3F))
+                     . chr(0x80 | ($bytes & 0x3F));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }        
+
+   /**
+    * convert a string from one UTF-8 char to one UTF-16 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf8   UTF-8 character
+    * @return   string  UTF-16 character
+    * @access   private
+    */
+    function utf82utf16($utf8)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding'))
+            return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+        
+        switch(strlen($utf8)) {
+            case 1:
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return $utf8;
+
+            case 2:
+                // return a UTF-16 character from a 2-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x07 & (ord($utf8{0}) >> 2))
+                     . chr((0xC0 & (ord($utf8{0}) << 6))
+                         | (0x3F & ord($utf8{1})));
+                
+            case 3:
+                // return a UTF-16 character from a 3-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr((0xF0 & (ord($utf8{0}) << 4))
+                         | (0x0F & (ord($utf8{1}) >> 2)))
+                     . chr((0xC0 & (ord($utf8{1}) << 6))
+                         | (0x7F & ord($utf8{2})));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }        
+
+   /**
+    * encodes an arbitrary variable into JSON format
+    *
+    * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
+    *                           see argument 1 to Services_JSON() above for array-parsing behavior.
+    *                           if var is a strng, note that encode() always expects it
+    *                           to be in ASCII or UTF-8 format!
+    *
+    * @return   string  JSON string representation of input var
+    * @access   public
+    */
+    function encode($var)
+    {
+        switch (gettype($var)) {
+            case 'boolean':
+                return $var ? 'true' : 'false';
+            
+            case 'NULL':
+                return 'null';
+            
+            case 'integer':
+                return (int) $var;
+                
+            case 'double':
+            case 'float':
+                return (float) $var;
+                
+            case 'string':
+                // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+                $ascii = '';
+                $strlen_var = strlen($var);
+
+               /*
+                * Iterate over every character in the string,
+                * escaping with a slash or encoding to UTF-8 where necessary
+                */
+                for ($c = 0; $c < $strlen_var; ++$c) {
+                    
+                    $ord_var_c = ord($var{$c});
+                    
+                    switch (true) {
+                        case $ord_var_c == 0x08:
+                            $ascii .= '\b';
+                            break;
+                        case $ord_var_c == 0x09:
+                            $ascii .= '\t';
+                            break;
+                        case $ord_var_c == 0x0A:
+                            $ascii .= '\n';
+                            break;
+                        case $ord_var_c == 0x0C:
+                            $ascii .= '\f';
+                            break;
+                        case $ord_var_c == 0x0D:
+                            $ascii .= '\r';
+                            break;
+
+                        case $ord_var_c == 0x22:
+                        case $ord_var_c == 0x2F:
+                        case $ord_var_c == 0x5C:
+                            // double quote, slash, slosh
+                            $ascii .= '\\'.$var{$c};
+                            break;
+                            
+                        case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+                            // characters U-00000000 - U-0000007F (same as ASCII)
+                            $ascii .= $var{$c};
+                            break;
+                        
+                        case (($ord_var_c & 0xE0) == 0xC0):
+                            // characters U-00000080 - U-000007FF, mask 110XXXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+                            $c += 1;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xF0) == 0xE0):
+                            // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}));
+                            $c += 2;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xF8) == 0xF0):
+                            // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}));
+                            $c += 3;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xFC) == 0xF8):
+                            // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}));
+                            $c += 4;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xFE) == 0xFC):
+                            // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}),
+                                         ord($var{$c + 5}));
+                            $c += 5;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+                    }
+                }
+                
+                return '"'.$ascii.'"';
+                
+            case 'array':
+               /*
+                * As per JSON spec if any array key is not an integer
+                * we must treat the the whole array as an object. We
+                * also try to catch a sparsely populated associative
+                * array with numeric keys here because some JS engines
+                * will create an array with empty indexes up to
+                * max_index which can cause memory issues and because
+                * the keys, which may be relevant, will be remapped
+                * otherwise.
+                * 
+                * As per the ECMA and JSON specification an object may
+                * have any string as a property. Unfortunately due to
+                * a hole in the ECMA specification if the key is a
+                * ECMA reserved word or starts with a digit the
+                * parameter is only accessible using ECMAScript's
+                * bracket notation.
+                */
+                
+                // treat as a JSON object  
+                if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+                    return '{' .
+                           join(',', array_map(array($this, 'name_value'),
+                                               array_keys($var),
+                                               array_values($var)))
+                           . '}';
+                }
+
+                // treat it like a regular array
+                return '[' . join(',', array_map(array($this, 'encode'), $var)) . ']';
+                
+            case 'object':
+                $vars = get_object_vars($var);
+                return '{' .
+                       join(',', array_map(array($this, 'name_value'),
+                                           array_keys($vars),
+                                           array_values($vars)))
+                       . '}';
+
+            default:
+                return '';
+        }
+    }
+    
+   /**
+    * array-walking function for use in generating JSON-formatted name-value pairs
+    *
+    * @param    string  $name   name of key to use
+    * @param    mixed   $value  reference to an array element to be encoded
+    *
+    * @return   string  JSON-formatted name-value pair, like '"name":value'
+    * @access   private
+    */
+    function name_value($name, $value)
+    {
+        return $this->encode(strval($name)) . ':' . $this->encode($value);
+    }        
+
+   /**
+    * reduce a string by removing leading and trailing comments and whitespace
+    *
+    * @param    $str    string      string value to strip of comments and whitespace
+    *
+    * @return   string  string value stripped of comments and whitespace
+    * @access   private
+    */
+    function reduce_string($str)
+    {
+        $str = preg_replace(array(
+        
+                // eliminate single line comments in '// ...' form
+                '#^\s*//(.+)$#m',
+    
+                // eliminate multi-line comments in '/* ... */' form, at start of string
+                '#^\s*/\*(.+)\*/#Us',
+    
+                // eliminate multi-line comments in '/* ... */' form, at end of string
+                '#/\*(.+)\*/\s*$#Us'
+    
+            ), '', $str);
+        
+        // eliminate extraneous space
+        return trim($str);
+    }
+
+   /**
+    * decodes a JSON string into appropriate variable
+    *
+    * @param    string  $str    JSON-formatted string
+    *
+    * @return   mixed   number, boolean, string, array, or object
+    *                   corresponding to given JSON input string.
+    *                   See argument 1 to Services_JSON() above for object-output behavior.
+    *                   Note that decode() always returns strings
+    *                   in ASCII or UTF-8 format!
+    * @access   public
+    */
+    function decode($str)
+    {
+        $str = $this->reduce_string($str);
+    
+        switch (strtolower($str)) {
+            case 'true':
+                return true;
+
+            case 'false':
+                return false;
+            
+            case 'null':
+                return null;
+            
+            default:
+                if (is_numeric($str)) {
+                    // Lookie-loo, it's a number
+
+                    // This would work on its own, but I'm trying to be
+                    // good about returning integers where appropriate:
+                    // return (float)$str;
+
+                    // Return float or int, as appropriate
+                    return ((float)$str == (integer)$str)
+                        ? (integer)$str
+                        : (float)$str;
+                    
+                } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
+                    // STRINGS RETURNED IN UTF-8 FORMAT
+                    $delim = substr($str, 0, 1);
+                    $chrs = substr($str, 1, -1);
+                    $utf8 = '';
+                    $strlen_chrs = strlen($chrs);
+                    
+                    for ($c = 0; $c < $strlen_chrs; ++$c) {
+                    
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                        $ord_chrs_c = ord($chrs{$c});
+                        
+                        switch (true) {
+                            case $substr_chrs_c_2 == '\b':
+                                $utf8 .= chr(0x08);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\t':
+                                $utf8 .= chr(0x09);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\n':
+                                $utf8 .= chr(0x0A);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\f':
+                                $utf8 .= chr(0x0C);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\r':
+                                $utf8 .= chr(0x0D);
+                                ++$c;
+                                break;
+
+                            case $substr_chrs_c_2 == '\\"':
+                            case $substr_chrs_c_2 == '\\\'':
+                            case $substr_chrs_c_2 == '\\\\':
+                            case $substr_chrs_c_2 == '\\/':
+                                if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
+                                   ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
+                                    $utf8 .= $chrs{++$c};
+                                }
+                                break;
+                                
+                            case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
+                                // single, escaped unicode character
+                                $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
+                                       . chr(hexdec(substr($chrs, ($c + 4), 2)));
+                                $utf8 .= $this->utf162utf8($utf16);
+                                $c += 5;
+                                break;
+        
+                            case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
+                                $utf8 .= $chrs{$c};
+                                break;
+        
+                            case ($ord_chrs_c & 0xE0) == 0xC0:
+                                // characters U-00000080 - U-000007FF, mask 110XXXXX
+                                //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 2);
+                                ++$c;
+                                break;
+    
+                            case ($ord_chrs_c & 0xF0) == 0xE0:
+                                // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 3);
+                                $c += 2;
+                                break;
+    
+                            case ($ord_chrs_c & 0xF8) == 0xF0:
+                                // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 4);
+                                $c += 3;
+                                break;
+    
+                            case ($ord_chrs_c & 0xFC) == 0xF8:
+                                // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 5);
+                                $c += 4;
+                                break;
+    
+                            case ($ord_chrs_c & 0xFE) == 0xFC:
+                                // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 6);
+                                $c += 5;
+                                break;
+
+                        }
+
+                    }
+                    
+                    return $utf8;
+                
+                } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
+                    // array, or object notation
+
+                    if ($str{0} == '[') {
+                        $stk = array(SERVICES_JSON_IN_ARR);
+                        $arr = array();
+                    } else {
+                        if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = array();
+                        } else {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = new stdClass();
+                        }
+                    }
+                    
+                    array_push($stk, array('what'  => SERVICES_JSON_SLICE,
+                                           'where' => 0,
+                                           'delim' => false));
+
+                    $chrs = substr($str, 1, -1);
+                    $chrs = $this->reduce_string($chrs);
+                    
+                    if ($chrs == '') {
+                        if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                            return $arr;
+
+                        } else {
+                            return $obj;
+
+                        }
+                    }
+
+                    //print("\nparsing {$chrs}\n");
+                    
+                    $strlen_chrs = strlen($chrs);
+                    
+                    for ($c = 0; $c <= $strlen_chrs; ++$c) {
+                    
+                        $top = end($stk);
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                    
+                        if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
+                            // found a comma that is not inside a string, array, etc.,
+                            // OR we've reached the end of the character list
+                            $slice = substr($chrs, $top['where'], ($c - $top['where']));
+                            array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
+                            //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                            if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                                // we are in an array, so just push an element onto the stack
+                                array_push($arr, $this->decode($slice));
+
+                            } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                                // we are in an object, so figure
+                                // out the property name and set an
+                                // element in an associative array,
+                                // for now
+                                if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // "name":value pair
+                                    $key = $this->decode($parts[1]);
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // name:value pair, where name is unquoted
+                                    $key = $parts[1];
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                }
+
+                            }
+
+                        } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
+                            // found a quote, and we are not inside a string
+                            array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
+                            //print("Found start of string at {$c}\n");
+
+                        } elseif (($chrs{$c} == $top['delim']) &&
+                                 ($top['what'] == SERVICES_JSON_IN_STR) &&
+                                 (($chrs{$c - 1} != '\\') ||
+                                 ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) {
+                            // found a quote, we're in a string, and it's not escaped
+                            array_pop($stk);
+                            //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '[') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-bracket, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
+                            //print("Found start of array at {$c}\n");
+
+                        } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
+                            // found a right-bracket, and we're in an array
+                            array_pop($stk);
+                            //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '{') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-brace, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
+                            //print("Found start of object at {$c}\n");
+
+                        } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
+                            // found a right-brace, and we're in an object
+                            array_pop($stk);
+                            //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($substr_chrs_c_2 == '/*') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a comment start, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
+                            $c++;
+                            //print("Found start of comment at {$c}\n");
+
+                        } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
+                            // found a comment end, and we're in one now
+                            array_pop($stk);
+                            $c++;
+                            
+                            for ($i = $top['where']; $i <= $c; ++$i)
+                                $chrs = substr_replace($chrs, ' ', $i, 1);
+                            
+                            //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        }
+                    
+                    }
+                    
+                    if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                        return $arr;
+
+                    } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                        return $obj;
+
+                    }
+                
+                }
+        }
+    }
+    
+}
+    
+?>
\ No newline at end of file
diff --git a/dojo/tests/resources/testClass.php b/dojo/tests/resources/testClass.php
new file mode 100755
index 0000000..acf7f16
--- /dev/null
+++ b/dojo/tests/resources/testClass.php
@@ -0,0 +1,20 @@
+<?php
+class testClass {
+
+	function myecho ($somestring) {
+		return "<P>" . $somestring . "</P>";
+	}
+
+	function contentB () {
+		return "<P>Content B</P>";
+	}
+
+	function contentC () {
+		return "<P>Content C</P>";
+	}
+
+	function add($x,$y) {
+		return $x + $y;
+	}
+}
+?>
diff --git a/dojo/tests/resources/testClass.smd b/dojo/tests/resources/testClass.smd
new file mode 100755
index 0000000..85f4794
--- /dev/null
+++ b/dojo/tests/resources/testClass.smd
@@ -0,0 +1,39 @@
+{
+	"SMDVersion":".1",
+	"objectName":"testClass",
+	"serviceType":"JSON-RPC",
+	"serviceURL":"../../dojo/tests/resources/test_JsonRPCMediator.php",
+	"methods":[
+		{
+			"name":"myecho",
+			"parameters":[
+				{
+					"name":"somestring",
+					"type":"STRING"
+				}
+			]
+		},
+		{
+			"name":"contentB"
+		},
+		{
+			"name":"contentC"
+		},
+		{
+			"name":"add",
+			"parameters":[
+				{
+					"name":"x",
+					"type":"STRING"
+				},
+				{
+					"name":"y",
+					"type":"STRING"
+				}
+			]
+		},
+		{
+			"name":"triggerRpcError"
+		}
+	]
+}
diff --git a/dojo/tests/resources/test_JsonRPCMediator.php b/dojo/tests/resources/test_JsonRPCMediator.php
new file mode 100755
index 0000000..42a9711
--- /dev/null
+++ b/dojo/tests/resources/test_JsonRPCMediator.php
@@ -0,0 +1,43 @@
+<?php
+	require_once("./JSON.php");
+	
+	// FIXME: doesn't look like we really need Pear at all
+	// which decreases the testing burden. 
+	// Commenting out.the require and the new File() call.
+
+	// NOTE: File.php is installed via Pear using:
+	//	%> sudo pear install File
+	// Your server will also need the Pear library directory included in PHP's
+	// include_path configuration directive
+	// require_once('File.php');
+
+	// ensure that we don't try to send "html" down to the client
+	header("Content-Type: text/plain");
+
+	$json = new Services_JSON;
+	//$fp = new File();
+
+	$results = array();
+	$results['error'] = null;
+
+	$jsonRequest = file_get_contents('php://input');
+	//$jsonRequest = '{"params":["Blah"],"method":"myecho","id":86}';
+
+	$req = $json->decode($jsonRequest);
+
+	include("./testClass.php");
+	$testObject = new testClass();
+
+	$method = $req->method;
+	if ($method != "triggerRpcError") {
+		$ret = call_user_func_array(array($testObject,$method),$req->params);
+		$results['result'] = $ret;
+	} else {
+		$results['error'] = "Triggered RPC Error test";
+	}
+	$results['id'] = $req->id;
+
+	$encoded = $json->encode($results);
+
+	print $encoded;
+?>
diff --git a/dojo/tests/resources/test_css.html b/dojo/tests/resources/test_css.html
new file mode 100644
index 0000000..46617e5
--- /dev/null
+++ b/dojo/tests/resources/test_css.html
@@ -0,0 +1,100 @@
+<html>
+	<head>
+		<title>Dojo CSS Stylesheet Test</title>
+		<link rel="stylesheet" type="text/css" href="../../resources/dojo.css">
+	</head>
+	<body>
+		<h1>Lorem ipsum dolor sit amet.</h1>
+		<p>Lorem ipsum dolor sit amet, <a href="">consectetuer adipiscing elit</a>. In porta. Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus,  [...]
+		<q>Donec eu nunc vitae lorem egestas convallis <code>var test=null;</code> Nullam at enim id mauris vestibulum ornare. Cras facilisis tellus at risus. Phasellus ut pede at erat posuere vehicula. Donec auctor sodales risus. Maecenas dictum erat at justo. Nullam fringilla dictum orci. Ut vitae erat. Fusce nunc. Duis quis orci. Morbi faucibus. Ut fermentum augue ac nulla. Duis cursus eleifend felis. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris tincidunt, justo quis ven [...]
+		<h2>Donec eu nunc vitae lorem.</h2>
+		<p>Donec eu nunc vitae lorem egestas convallis. Nullam at enim id mauris vestibulum ornare. Cras facilisis tellus at risus. Phasellus ut pede at erat posuere vehicula. Donec auctor sodales risus. Maecenas dictum erat at justo. Nullam fringilla dictum orci. Ut vitae erat. Fusce nunc. Duis quis orci. Morbi faucibus. Ut fermentum augue ac nulla. Duis cursus eleifend felis. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris tincidunt, justo quis venenatis congue, nisi purus d [...]
+		<p>Vestibulum ultricies bibendum tortor. Nam auctor dignissim neque. Cras vehicula. Nulla facilisi. Duis quis tellus in est aliquet condimentum. Sed elementum, felis vel pharetra bibendum, neque lorem pulvinar nulla, consequat tempor libero enim vel nulla. Nulla eleifend, lorem accumsan convallis lobortis, diam dui eleifend urna, eu imperdiet purus urna nec nibh. Nullam pede odio, molestie eu, interdum sagittis, imperdiet ac, lectus. Sed pede nisl, vulputate at, pellentesque id, consec [...]
+		<ol>
+			<li>A List item.</li>
+			<li>A List item.</li>
+			<li>A List item.</li>
+			<li>A List item.</li>
+			<li>A List item.</li>
+			<li>A List item.</li>
+		</ol>
+		<h2>Cras pellentesque</h2>
+		<h3>Aliquam dapibus</h3>
+		<pre>
+var test = someVariable;
+function foo(bar){
+	alert(baz);
+} </pre>
+		<p>Cras pellentesque tristique lorem. Aliquam dapibus, massa id posuere volutpat, sem sem nonummy turpis, ut ultricies nibh neque sed dolor. Duis commodo elit et massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed eu urna. Donec sit amet odio sit amet turpis facilisis molestie. In id mi. Nulla consequat ante ut elit. In risus urna, venenatis imperdiet, consequat vel, porttitor et, quam. In hac habitasse platea dictumst. Vestibulum id velit [...]
+		<h4>An unstyled table.</h4>
+		<table>
+			<thead>
+				<tr>
+					<th>Foo</th>
+					<th>Bar</th>
+					<th>Baz</th>
+				</tr>
+			</thead>
+			<tbody>
+				<tr>
+					<td>baz</td>
+					<td>foo</td>
+					<td>bar</td>
+				</tr>
+				<tr>
+					<td>bar</td>
+					<td>baz</td>
+					<td>foo</td>
+				</tr>
+				<tr>
+					<td>foo</td>
+					<td>bar</td>
+					<td>baz</td>
+				</tr>
+			</tbody>
+			<tfoot>
+				<tr>
+					<td>Foo</td>
+					<td>Bar</td>
+					<td>Baz</td>
+				</tr>
+			</tfoot>
+		</table>
+		<h4>The same table, styled with dojoTabular.</h4>
+		<table class="dojoTabular">
+			<thead>
+				<tr>
+					<th>Foo</th>
+					<th>Bar</th>
+					<th>Baz</th>
+				</tr>
+			</thead>
+			<tbody>
+				<tr>
+					<td>baz</td>
+					<td>foo</td>
+					<td>bar</td>
+				</tr>
+				<tr>
+					<td>bar</td>
+					<td>baz</td>
+					<td>foo</td>
+				</tr>
+				<tr>
+					<td>foo</td>
+					<td>bar</td>
+					<td>baz</td>
+				</tr>
+			</tbody>
+			<tfoot>
+				<tr>
+					<td>Foo</td>
+					<td>Bar</td>
+					<td>Baz</td>
+				</tr>
+			</tfoot>
+		</table>
+		<blockquote>Donec eu nunc vitae lorem egestas convallis. Nullam at enim id mauris vestibulum ornare. Cras facilisis tellus at risus. Phasellus ut pede at erat posuere vehicula. Donec auctor sodales risus. Maecenas dictum erat at justo. Nullam fringilla dictum orci. Ut vitae erat. Fusce nunc. Duis quis orci. Morbi faucibus. Ut fermentum augue ac nulla. Duis cursus eleifend felis. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris tincidunt, justo quis venenatis congue, nis [...]
+		<p>Phasellus quis velit. Curabitur porta dolor in arcu. Maecenas mollis purus. Donec nec erat et tellus laoreet elementum. Pellentesque vitae mi. Aenean pharetra libero ultricies augue. Vestibulum et nibh. Proin nibh quam, rutrum faucibus, auctor eget, mollis vel, orci. Duis tortor quam, tincidunt eu, lacinia id, fermentum at, turpis. Mauris at augue. Nulla facilisi. Pellentesque ut enim.</p>
+	</body>
+</html>
diff --git a/dojo/tests/resources/yahoo_smd_v1.smd b/dojo/tests/resources/yahoo_smd_v1.smd
new file mode 100755
index 0000000..a22241b
--- /dev/null
+++ b/dojo/tests/resources/yahoo_smd_v1.smd
@@ -0,0 +1,268 @@
+{
+	"SMDVersion":".1",
+	"objectName":"yahoo",
+	"serviceType":"JSON-P",
+	"required": {
+		"appid": "dojotoolkit",
+		"output": "json"
+	},
+	"methods":[
+		//
+		// MAPS 
+		//
+		{
+			// http://developer.yahoo.com/maps/rest/V1/mapImage.html
+			"name":"mapImage",
+			"serviceURL": "http://api.local.yahoo.com/MapsService/V1/mapImage",
+			"parameters":[
+				{ "name":"street", "type":"STRING" },
+				{ "name":"city", "type":"STRING" },
+				{ "name":"zip", "type":"INTEGER" },
+				{ "name":"location", "type":"STRING" },
+				{ "name":"longitude", "type":"FLOAT" },
+				{ "name":"latitude", "type":"FLOAT" },
+				{ "name":"image_type", "type":"STRING" },
+				{ "name":"image_width", "type":"INTEGER" },
+				{ "name":"image_height", "type":"INTEGER" },
+				{ "name":"zoom", "type":"INTEGER" },
+				{ "name":"radius", "type":"INTEGER" }
+			]
+		},
+		{
+			// http://developer.yahoo.com/traffic/rest/V1/index.html
+			"name":"trafficData",
+			"serviceURL": "http://api.local.yahoo.com/MapsService/V1/trafficData",
+			"parameters":[
+				{ "name":"street", "type":"STRING" },
+				{ "name":"city", "type":"STRING" },
+				{ "name":"zip", "type":"INTEGER" },
+				{ "name":"location", "type":"STRING" },
+				{ "name":"longitude", "type":"FLOAT" },
+				{ "name":"latitude", "type":"FLOAT" },
+				{ "name":"severity", "type":"INTEGER" },
+				{ "name":"include_map", "type":"INTEGER" },
+				{ "name":"image_type", "type":"STRING" },
+				{ "name":"image_width", "type":"INTEGER" },
+				{ "name":"image_height", "type":"INTEGER" },
+				{ "name":"zoom", "type":"INTEGER" },
+				{ "name":"radius", "type":"INTEGER" }
+			]
+		},
+		//
+		// LOCAL SEARCH
+		//
+		{
+			// http://developer.yahoo.com/search/local/V3/localSearch.html
+			"name":"localSearch",
+			"serviceURL": "http://api.local.yahoo.com/LocalSearchService/V3/localSearch",
+			"parameters":[
+				{ "name":"street", "type":"STRING" },
+				{ "name":"city", "type":"STRING" },
+				{ "name":"zip", "type":"INTEGER" },
+				{ "name":"location", "type":"STRING" },
+				{ "name":"listing_id", "type":"STRING" },
+				{ "name":"sort", "type":"STRING" }, // "relevence", "title", "distance", or "rating"
+				{ "name":"start", "type":"INTEGER" },
+				{ "name":"radius", "type":"FLOAT" },
+				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+				{ "name":"longitude", "type":"FLOAT" },
+				{ "name":"latitude", "type":"FLOAT" },
+				{ "name":"category", "type":"INTEGER" },
+				{ "name":"omit_category", "type":"INTEGER" },
+				{ "name":"minimum_rating", "type":"INTEGER" }
+			]
+		},
+		//
+		// WEB SEARCH
+		//
+		{
+			// http://developer.yahoo.com/search/web/V1/webSearch.html 
+			"name":"webSearch",
+			"serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/webSearch",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // defaults to "all"
+				{ "name":"region", "type":"STRING" }, // defaults to "us"
+				{ "name":"results", "type":"INTEGER" }, // defaults to 10
+				{ "name":"start", "type":"INTEGER" }, // defaults to 1
+				{ "name":"format", "type":"STRING" }, // defaults to "any", can be "html", "msword", "pdf", "ppt", "rst", "txt", or "xls"
+				{ "name":"adult_ok", "type":"INTEGER" }, // defaults to null
+				{ "name":"similar_ok", "type":"INTEGER" }, // defaults to null
+				{ "name":"language", "type":"STRING" }, // defaults to null
+				{ "name":"country", "type":"STRING" }, // defaults to null
+				{ "name":"site", "type":"STRING" }, // defaults to null
+				{ "name":"subscription", "type":"STRING" }, // defaults to null
+				{ "name":"license", "type":"STRING" } // defaults to "any"
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/web/V1/spellingSuggestion.html
+			"name":"spellingSuggestion",
+			"serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/spellingSuggestion",
+			"parameters":[ { "name":"query", "type":"STRING" } ]
+		},
+		{
+			// http://developer.yahoo.com/search/web/V1/relatedSuggestion.html
+			"name":"relatedSuggestion",
+			"serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/relatedSuggestion",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"results", "type":"INTEGER" } // 1-50, defaults to 10
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/content/V1/termExtraction.html
+			"name":"termExtraction",
+			"serviceURL": "http://search.yahooapis.com/ContentAnalysisService/V1/termExtraction",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"context", "type":"STRING" },
+				{ "name":"results", "type":"INTEGER" } // 1-50, defaults to 10
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/web/V1/contextSearch.html
+			"name":"contextSearch",
+			"serviceURL": "http://search.yahooapis.com/WebSearchService/V1/contextSearch",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"context", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // defaults to "all"
+				{ "name":"results", "type":"INTEGER" }, // defaults to 10
+				{ "name":"start", "type":"INTEGER" }, // defaults to 1
+				{ "name":"format", "type":"STRING" }, // defaults to "any", can be "html", "msword", "pdf", "ppt", "rst", "txt", or "xls"
+				{ "name":"adult_ok", "type":"INTEGER" }, // defaults to null
+				{ "name":"similar_ok", "type":"INTEGER" }, // defaults to null
+				{ "name":"language", "type":"STRING" }, // defaults to null
+				{ "name":"country", "type":"STRING" }, // defaults to null
+				{ "name":"site", "type":"STRING" }, // defaults to null
+				{ "name":"license", "type":"STRING" } // defaults to "any", could be "cc_any", "cc_commercial", "cc_modifiable"
+			]
+		},
+		//
+		// IMAGE SEARCH
+		//
+		{
+			// http://developer.yahoo.com/search/image/V1/imageSearch.html
+			"name":"imageSearch",
+			"serviceURL": "http://api.search.yahoo.com/ImageSearchService/V1/imageSearch",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+				{ "name":"results", "type":"INTEGER" }, // defaults to 10
+				{ "name":"start", "type":"INTEGER" }, // defaults to 1
+				{ "name":"format", "type":"STRING" }, // defaults to "any", can be "bmp", "gif", "jpeg", or "png"
+				{ "name":"adult_ok", "type":"INTEGER" }, // defaults to null
+				{ "name":"coloration", "type":"STRING" }, // "any", "color", or "bw"
+				{ "name":"site", "type":"STRING" } // defaults to null
+			]
+		},
+		//
+		// SITE EXPLORER
+		//
+		{
+			// http://developer.yahoo.com/search/siteexplorer/V1/inlinkData.html 
+			"name":"inlinkData",
+			"serviceURL": "http://api.search.yahoo.com/SiteExplorerService/V1/inlinkData",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+				{ "name":"entire_site", "type":"INTEGER" }, // defaults to null
+				{ "name":"omit_inlinks", "type":"STRING" }, // "domain" or "subdomain", defaults to null
+				{ "name":"results", "type":"INTEGER" }, // defaults to 50
+				{ "name":"start", "type":"INTEGER" }, // defaults to 1
+				{ "name":"site", "type":"STRING" } // defaults to null
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/siteexplorer/V1/pageData.html
+			"name":"pageData",
+			"serviceURL": "http://api.search.yahoo.com/SiteExplorerService/V1/pageData",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+				{ "name":"domain_only", "type":"INTEGER" }, // defaults to null
+				{ "name":"results", "type":"INTEGER" }, // defaults to 50
+				{ "name":"start", "type":"INTEGER" }, // defaults to 1
+				{ "name":"site", "type":"STRING" } // defaults to null
+			]
+		},
+		//
+		// MUSIC SEARCH
+		//
+		{
+			// http://developer.yahoo.com/search/audio/V1/artistSearch.html
+			"name":"artistSearch",
+			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/artistSearch",
+			"parameters":[
+				{ "name":"artist", "type":"STRING" },
+				{ "name":"artistid", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+				{ "name":"start", "type":"INTEGER" } // defaults to 1
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/audio/V1/albumSearch.html
+			"name":"albumSearch",
+			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/albumSearch",
+			"parameters":[
+				{ "name":"artist", "type":"STRING" },
+				{ "name":"artistid", "type":"STRING" },
+				{ "name":"album", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+				{ "name":"start", "type":"INTEGER" } // defaults to 1
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/audio/V1/songSearch.html
+			"name":"songSearch",
+			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/songSearch",
+			"parameters":[
+				{ "name":"artist", "type":"STRING" },
+				{ "name":"artistid", "type":"STRING" },
+				{ "name":"album", "type":"STRING" },
+				{ "name":"albumid", "type":"STRING" },
+				{ "name":"song", "type":"STRING" },
+				{ "name":"songid", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+				{ "name":"start", "type":"INTEGER" } // defaults to 1
+			]
+		},
+		{
+			// http://developer.yahoo.com/search/audio/V1/songDownloadLocation.html
+			"name":"songDownloadLocation",
+			"serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/songDownloadLocation",
+			"parameters":[
+				{ "name":"songid", "type":"STRING" },
+				// "source" can contain:
+				//	audiolunchbox artistdirect buymusic dmusic
+				//	emusic epitonic garageband itunes yahoo
+				//	livedownloads mp34u msn musicmatch mapster passalong
+				//	rhapsody soundclick theweb
+				{ "name":"source", "type":"STRING" },
+				{ "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+				{ "name":"start", "type":"INTEGER" } // defaults to 1
+			]
+		},
+		//
+		// NEWS SEARCH
+		//
+		{
+			// http://developer.yahoo.com/search/news/V1/newsSearch.html
+			"name":"newsSearch",
+			"serviceURL": "http://api.search.yahoo.com/NewsSearchService/V1/newsSearch",
+			"parameters":[
+				{ "name":"query", "type":"STRING" },
+				{ "name":"type", "type":"STRING" }, // defaults to "all"
+				{ "name":"results", "type":"INTEGER" }, // defaults to 10
+				{ "name":"start", "type":"INTEGER" }, // defaults to 1
+				{ "name":"sort", "type":"STRING" }, // "rank" or "date"
+				{ "name":"language", "type":"STRING" }, // defaults to null
+				{ "name":"site", "type":"STRING" } // defaults to null
+			]
+		}
+	]
+}
diff --git a/dojo/tests/rpc.js b/dojo/tests/rpc.js
new file mode 100644
index 0000000..5dc3895
--- /dev/null
+++ b/dojo/tests/rpc.js
@@ -0,0 +1,147 @@
+dojo.provide("tests.rpc");
+
+dojo.require("dojo.rpc.RpcService");
+dojo.require("dojo.rpc.JsonService");
+dojo.require("dojo.rpc.JsonpService");
+
+doh.register("tests.rpc", 
+	[ 
+
+		{
+			name: "JsonRPC-EchoTest",
+			timeout: 2000,
+			setUp: function(){
+
+				var testSmd = {
+					serviceURL:"../../dojo/tests/resources/test_JsonRPCMediator.php",
+					methods:[
+						{
+							name:"myecho",
+							parameters:[
+								{
+									name:"somestring",
+									type:"STRING"
+								}
+							]
+						}
+					]	
+				}
+			
+				this.svc = new dojo.rpc.JsonService(testSmd);
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+				var td = this.svc.myecho("RPC TEST");
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and PHP and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				td.addCallbacks(function(result) {
+					if(result=="<P>RPC TEST</P>"){
+						return true;
+					}else{
+						return new Error("JsonRpc-EchoTest test failed, resultant content didn't match");
+					}
+				}, function(result){
+					return new Error(result);
+				});
+
+				td.addBoth(d, "callback");
+
+				return d;
+			}
+
+		},
+
+		{
+			name: "JsonRPC-EmptyParamTest",
+			timeout: 2000,
+			setUp: function(){
+				var testSmd={
+					serviceURL:"../../dojo/tests/resources/test_JsonRPCMediator.php",
+					methods:[ { name:"contentB" } ]	
+				}
+			
+				this.svc = new dojo.rpc.JsonService(testSmd);
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+				var td = this.svc.contentB();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and PHP and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				td.addCallbacks(function(result){
+					if(result=="<P>Content B</P>"){
+						return true;
+					}else{
+						return new Error("JsonRpc-EmpytParamTest test failed, resultant content didn't match");
+					}
+				}, function(result){
+					return new Error(result);
+				});
+
+				td.addBoth(d, "callback");
+
+				return d;
+			}
+		},
+
+		{
+			name: "JsonRPC_SMD_Loading_test",
+			setUp: function(){
+				this.svc = new dojo.rpc.JsonService("../../dojo/tests/resources/testClass.smd");
+			},
+			runTest: function(){
+
+				if (this.svc.objectName=="testClass") {
+					return true;
+				} else {
+					return new Error("Error loading and/or parsing an smd file");
+				}
+			}
+		},
+
+		{
+			name: "JsonP_test",
+			timeout: 10000,
+			setUp: function(){
+				this.svc = new dojo.rpc.JsonpService(dojo.moduleUrl("dojo.tests.resources","yahoo_smd_v1.smd"), {appid: "foo"});
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				var td = this.svc.webSearch({query:"dojotoolkit"});
+
+				td.addCallbacks(function(result){
+					return true;
+					if (result["ResultSet"]["Result"][0]["DisplayUrl"]=="dojotoolkit.org/") {
+						return true;
+					}else{
+						return new Error("JsonRpc_SMD_Loading_Test failed, resultant content didn't match");
+					}
+				}, function(result){
+					return new Error(result);
+				});
+
+				td.addBoth(d, "callback");
+
+				return d;
+			}
+		}
+	]
+);
+
+
diff --git a/dojo/tests/runTests.html b/dojo/tests/runTests.html
new file mode 100644
index 0000000..a83f534
--- /dev/null
+++ b/dojo/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojo CORE and BASE D.O.H. Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../util/doh/runner.html?testModule=dojo.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojo/tests/string.js b/dojo/tests/string.js
new file mode 100644
index 0000000..bb69939
--- /dev/null
+++ b/dojo/tests/string.js
@@ -0,0 +1,92 @@
+dojo.provide("tests.string");
+
+dojo.require("dojo.string");
+
+tests.register("tests.string", 
+	[
+		function test_string_pad(t){
+			t.is("00001", dojo.string.pad("1", 5));
+			t.is("000001", dojo.string.pad("000001", 5));
+			t.is("10000", dojo.string.pad("1", 5, null, true));
+		},
+
+		function test_string_substitute(t){
+			t.is("File 'foo.html' is not found in directory '/temp'.", 
+				dojo.string.substitute(
+					"File '${0}' is not found in directory '${1}'.", 
+					["foo.html","/temp"]
+				)
+			);
+			t.is("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" }
+					}
+				)
+			);
+			// Verify that an error is thrown!
+			t.assertError(Error, dojo.string, "substitute", ["${x}", {y:1}]);
+		},
+		
+		function test_string_substitute_transform(t){
+			var getPrefix = function(str){
+				// try to figure out the type
+				var prefix = (str.charAt(0) == "/") ? "directory": "file";
+				if(this.____prefix){
+					prefix = this.____prefix + prefix;
+				}
+				return prefix + " '" + str + "'";
+			}
+
+			var obj = {
+				____prefix: "...",
+				getPrefix: getPrefix
+			};
+
+			t.is("file 'foo.html' is not found in directory '/temp'.", 
+				dojo.string.substitute(
+					"${0} is not found in ${1}.",
+					["foo.html","/temp"],
+					getPrefix
+				)
+			);
+
+			t.is("...file 'foo.html' is not found in ...directory '/temp'.", 
+				dojo.string.substitute(
+					"${0} is not found in ${1}.",
+					["foo.html","/temp"],
+					obj.getPrefix, obj
+				)
+			);
+		},
+
+		function test_string_substitute_formatter(t){
+			t.is("thinger -- howdy", 
+				dojo.string.substitute(
+					"${0:postfix}", ["thinger"], null, {
+						postfix: function(value, key){
+							return value + " -- howdy";
+						}
+					}
+				)
+			);
+		},
+		
+		function test_string_trim(t){
+			t.is("astoria", dojo.string.trim("   \f\n\r\t      astoria           "));
+			t.is("astoria", dojo.string.trim("astoria                            "));
+			t.is("astoria", dojo.string.trim("                            astoria"));
+			t.is("astoria", dojo.string.trim("astoria"));
+			t.is("a", dojo.string.trim("   a   "));
+		},
+		
+		function test_string_rep(t){
+			t.is("aaaaa", dojo.string.rep("a", 5));
+			t.is("abababab", dojo.string.rep("ab", 4));
+			t.is("", dojo.string.rep("ab", 0));
+			t.is("", dojo.string.rep("", 3));
+		}
+	]
+);
diff --git a/dojo/tests/test_FirebugLite.html b/dojo/tests/test_FirebugLite.html
new file mode 100644
index 0000000..f87f01b
--- /dev/null
+++ b/dojo/tests/test_FirebugLite.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+	<title>Firebug Lite Tests</title>
+	<script type="text/javascript">
+		// enable Lite in Firefox:
+		console = null;
+		var djConfig = {
+			isDebug: true,
+			debugHeight: 100,
+			popup:false 
+		};
+	</script>
+
+	<script type="text/javascript" src="../dojo.js"></script>
+	<script type="text/javascript">
+		obj = { // a long object to test scrolling in object inspector
+			mobby:{d:"objectify", e:"erroroneous", f:"functastic", obby:{lilOb:"moOb"}},
+			a:"Dojo",
+			b:2,
+			c:[0,8],
+			id:"MyCoolObject",
+			extra:{d:"objectify2", e:"erroroneous2", f:"functastic2", obby:{lilOb:"moOb2"}},
+			aaa:"Dojo",
+			bbb:22,
+			ccc:[10,18],
+			idDeedYee:"MyCoolObjectie"
+		}
+		
+		obj2 = {
+			a:"Dojo",
+			b:2,
+			c:[0,8],
+			id:"MyCoolObject"
+		}
+		
+		obj3 = {
+			a:"Dojo",
+			b:2,
+			c:[0,8]
+		}
+		
+		outputText = function(){
+			for ( var i = 0; i < 20 ; i++){
+				console.log (i+":: foo");
+			}
+		}
+		doStuff = function(){
+			console.log("FOO! More FOO! Gotta have some FOO MAN!")
+		}
+		
+		doStuffLots = function(){
+			for ( var i = 0; i < 5 ; i++){
+				console.log("xxxxxxxx")
+				doStuff();
+			}}
+		dojo.addOnLoad(function(){
+			console.time("foo time")
+			// test objects
+			console.log(obj3, "::", [1,2,3,4,5,6,7,8,9,0]);
+			console.log("Dojo was here", obj, "object over", obj2);
+			
+			// test that tracing dom node does not break (due to lack of support)
+			console.log(dojo.byId("foo"))
+			
+			// test error functionality
+			console.error( new Error("There was a dummy error") );
+			
+			//throws exception:
+			//console.assert(true == false)
+			
+			console.group("myGroup");
+			console.log("group me 1");
+			console.log("group me 2");
+			console.log("group me 3");
+			console.groupEnd();
+			
+			// testing log styling
+			console.log("foo");
+			console.debug("foo");
+			console.info("foo");
+			console.warn("foo");
+			console.error("foo");
+			//timer end
+			console.timeEnd("foo time")
+		})
+		
+		function doCon(){
+		}
+	</script>
+</head>
+<body>
+	<div id="foo" font="Arial" style="display:none;">Dojo was here</div>
+		<button onclick="doStuff()">Do Foo Stuff</button>
+		<button onclick="doStuffLots()">Do Stuff Lots</button>
+		<div id="trc"></div>
+	</body>
+</html>
diff --git a/dojo/tests/test_FirebugLitePopup.html b/dojo/tests/test_FirebugLitePopup.html
new file mode 100644
index 0000000..926713e
--- /dev/null
+++ b/dojo/tests/test_FirebugLitePopup.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+	<title>Firebug Lite Tests</title>
+	<script type="text/javascript">
+		// enable Lite in Firefox:
+		console = null;
+		var djConfig = {
+			isDebug: true,
+			debugHeight: 100,
+			popup:true // who knew?
+		};
+	</script>
+
+	<script type="text/javascript" src="../dojo.js"></script>
+	<script type="text/javascript">
+		obj = { // a long object to test scrolling in object inspector
+			mobby:{d:"objectify", e:"erroroneous", f:"functastic", obby:{lilOb:"moOb"}},
+			a:"Dojo",
+			b:2,
+			c:[0,8],
+			id:"MyCoolObject",
+			extra:{d:"objectify2", e:"erroroneous2", f:"functastic2", obby:{lilOb:"moOb2"}},
+			aaa:"Dojo",
+			bbb:22,
+			ccc:[10,18],
+			idDeedYee:"MyCoolObjectie"
+		}
+		
+		obj2 = {
+			a:"Dojo",
+			b:2,
+			c:[0,8],
+			id:"MyCoolObject"
+		}
+		
+		obj3 = {
+			a:"Dojo",
+			b:2,
+			c:[0,8]
+		}
+		
+		outputText = function(){
+			for ( var i = 0; i < 20 ; i++){
+				console.log (i+":: foo");
+			}
+		}
+		doStuff = function(){
+			console.log("FOO! More FOO! Gotta have some FOO MAN!")
+		}
+		
+		doStuffLots = function(){
+			for ( var i = 0; i < 5 ; i++){
+				console.log("xxxxxxxx")
+				doStuff();
+			}}
+		dojo.addOnLoad(function(){
+			console.time("foo time")
+			// test objects
+			console.log(obj3, "::", [1,2,3,4,5,6,7,8,9,0]);
+			console.log("Dojo was here", obj, "object over", obj2);
+			
+			// test that tracing dom node does not break (due to lack of support)
+			console.log(dojo.byId("foo"))
+			
+			// test error functionality
+			console.error( new Error("There was a dummy error") );
+			
+			//throws exception:
+			//console.assert(true == false)
+			
+			console.group("myGroup");
+			console.log("group me 1");
+			console.log("group me 2");
+			console.log("group me 3");
+			console.groupEnd();
+			
+			// testing log styling
+			console.log("foo");
+			console.debug("foo");
+			console.info("foo");
+			console.warn("foo");
+			console.error("foo");
+			//timer end
+			console.timeEnd("foo time")
+		})
+		
+		function doCon(){
+		}
+	</script>
+</head>
+<body>
+	<h1>test Firebug popup window</h1>
+	<div id="foo" font="Arial" style="display:none;">Dojo was here</div>
+		<button onclick="doStuff()">Do Foo Stuff</button>
+		<button onclick="doStuffLots()">Do Stuff Lots</button>
+		<div id="trc"></div>
+	</body>
+</html>
diff --git a/dojo/tests/test_fx.html b/dojo/tests/test_fx.html
new file mode 100644
index 0000000..4e6b586
--- /dev/null
+++ b/dojo/tests/test_fx.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<style type="text/css">
+			@import "../resources/dojo.css";
+		</style>
+		<style type="text/css">
+			@import "../resources/dojo.css";
+
+			body {
+				text-shadow: 0px 0px;
+				margin: 1em;
+				background-color: #DEDEDE;
+			}
+
+			.box {
+				color: #292929;
+				/* color: #424242; */
+				/* text-align: left; */
+				width: 300px;
+				border: 1px solid #BABABA;
+				background-color: white;
+				padding-left: 10px;
+				padding-right: 10px;
+				margin-left: 10px;
+				margin-bottom: 1em;
+				-o-border-radius: 10px;
+				-moz-border-radius: 12px;
+				-webkit-border-radius: 10px;
+				-webkit-box-shadow: 0px 3px 7px #adadad;
+				/* -opera-border-radius: 10px; */
+				border-radius: 10px;
+				-moz-box-sizing: border-box;
+				-opera-sizing: border-box;
+				-webkit-box-sizing: border-box;
+				-khtml-box-sizing: border-box;
+				box-sizing: border-box;
+				overflow: hidden;
+				/* position: absolute; */
+			}
+		</style>
+		<script type="text/javascript" src="../dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript" src="../fx.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.fx");
+			dojo.addOnLoad(function(){
+				dojo.byId("foo").style.height = "0px";
+				var w1 = dojo.fx.wipeIn({
+					node: "foo",
+					duration: 500
+				});
+				var f1 = dojo.fadeOut({
+					node: "foo",
+					duration: 500
+				});
+				var a1 = dojo.fx.chain([w1, f1]);
+
+				dojo.byId("foo").style.height = "0px";
+				var w2 = dojo.fx.wipeIn({
+					node: "foo",
+					duration: 500
+				});
+				var f2 = dojo.fadeIn({
+					node: "foo",
+					duration: 1000
+				});
+				var a2 = dojo.fx.combine([w2, f2]);
+				
+				dojo.connect(a1, "onEnd", function(){
+					console.log("finish1");
+					a2.play();
+				});
+				dojo.connect(a2, "onEnd", function(){
+					console.log("finish2");
+				});
+				a1.play();
+			});
+		</script>
+	</head>
+	<body>
+		<div id="foo" class="box">
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+			Proin porta rutrum lacus. Etiam consequat scelerisque quam. Nulla
+			facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+			semper iaculis.  Sed molestie tortor at ipsum. Morbi dictum rutrum
+			magna. Sed vitae risus.
+			</p>
+			<p>
+			Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer
+			lorem nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean
+			id mi in massa bibendum suscipit. Integer eros. Nullam suscipit
+			mauris. In pellentesque. Mauris ipsum est, pharetra semper,
+			pharetra in, viverra quis, tellus. Etiam purus. Quisque egestas,
+			tortor ac cursus lacinia, felis leo adipiscing nisi, et rhoncus
+			elit dolor eget eros. Fusce ut quam. Suspendisse eleifend leo vitae
+			ligula. Nulla facilisi. Nulla rutrum, erat vitae lacinia dictum,
+			pede purus imperdiet lacus, ut semper velit ante id metus. Praesent
+			massa dolor, porttitor sed, pulvinar in, consequat ut, leo. Nullam
+			nec est. Aenean id risus blandit tortor pharetra congue.
+			Suspendisse pulvinar.
+			</p>
+		</div>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojo/tests/uacss.js b/dojo/tests/uacss.js
new file mode 100644
index 0000000..644e06b
--- /dev/null
+++ b/dojo/tests/uacss.js
@@ -0,0 +1,10 @@
+dojo.provide("tests.uacss");
+
+// Run tests for sniffer browser and setting corresponding class name on <html>
+
+try{
+	doh.registerUrl("tests.uacss.sniffQuirks", dojo.moduleUrl("dojo", "tests/uacss/sniffQuirks.html"));
+	doh.registerUrl("tests.uacss.sniffStandards", dojo.moduleUrl("dojo", "tests/uacss/sniffStandards.html"));
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojo/tests/uacss/sniffQuirks.html b/dojo/tests/uacss/sniffQuirks.html
new file mode 100644
index 0000000..f6d0b92
--- /dev/null
+++ b/dojo/tests/uacss/sniffQuirks.html
@@ -0,0 +1,65 @@
+<!-- quirks mode -->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+	<title>Sniffing for Box Model (quirks)</title>
+	<style type="text/css">
+		.box {
+			width: 48px;
+			padding: 25px;
+			background-color: yellow;
+			border: 1px solid black;
+		}
+		.dj_borderbox .box {
+			background-color: orange;
+			width: 100px;
+		}
+		.ruler {
+			background: url('http://sam-i-am.com/work/sandbox/measuring/ruler.gif') no-repeat;
+			height: 60px;
+		}
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug:true"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojo.uacss");
+
+		dojo.addOnLoad(function() {
+			var node = dojo.byId("box1");
+			var reportNode = dojo.byId("log")
+			var inner = (reportNode.textContent) ? "textContent": "innerText";
+			reportNode.innerHTML = dojo.toJson({
+				boxModel: dojo.boxModel,
+				isQuirks: dojo.isQuirks,
+				width: dojo.style(node, "width"),
+				marginBoxWidth: dojo.marginBox(node).w,
+				htmlClassName: dojo.doc.documentElement.className
+			}, 1);
+			doh.register("tests.window.sniffQuirks", [
+				function test_boxModel(t) {
+					// ensure the box-model correction in the stylesheet have been correctly applied
+					// we measure the node - it should be 100px
+				    t.is(100, node.offsetWidth);
+				}
+			]);
+			doh.run();
+		});
+	</script>
+</head>
+
+<body>
+	<h1>CSS Sniff test dj_boxmodel in quirks mode</h1>
+	<div style="background-color: orange; float:left">
+		<div id="box1" class="box">
+			<div style="background-color: white; height: 20px"></div>
+		</div>
+	</div>
+	<div style="clear:both"></div>
+	<div class="ruler"></div>
+	<div style="border: 1px solid #666; background-color: #dedede"><xmp id="log"></xmp></div>
+</body>
+</html>
diff --git a/dojo/tests/uacss/sniffStandards.html b/dojo/tests/uacss/sniffStandards.html
new file mode 100644
index 0000000..94e21f1
--- /dev/null
+++ b/dojo/tests/uacss/sniffStandards.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+	<title>Sniffing for Box Model (standards mode)</title>
+	<style type="text/css">
+		.box {
+			width: 48px;
+			padding: 25px;
+			background-color: yellow;
+			border: 1px solid black;
+		}
+		.dj_borderbox .box {
+			background-color: orange;
+			width: 100px;
+		}
+		.ruler {
+			background: url('http://sam-i-am.com/work/sandbox/measuring/ruler.gif') no-repeat;
+			height: 60px;
+		}
+	</style>
+	<script type="text/javascript" src="../../dojo.js" djConfig="isDebug:true"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojo.uacss");
+		dojo.addOnLoad(function() {
+			var node = dojo.byId("box1");
+			var reportNode = dojo.byId("log")
+			var inner = (reportNode.textContent) ? "textContent": "innerText";
+			reportNode.innerHTML = dojo.toJson({
+				boxModel: dojo.boxModel,
+				isQuirks: dojo.isQuirks,
+				width: dojo.style(node, "width"),
+				marginBoxWidth: dojo.marginBox(node).w,
+				htmlClassName: dojo.doc.documentElement.className
+			}, 1);
+			doh.register("tests.window.sniffStandards", [
+				function test_boxModel(t) {
+					// ensure the box-model correction in the stylesheet have been correctly applied
+					// we measure the node - it should be 100px
+				    t.is(100, node.offsetWidth);
+				}
+			]);
+			doh.run();
+		});
+	</script>
+</head>
+
+<body>
+	<h1>CSS Sniff test dj_boxmodel in standards mode</h1>
+	<div style="background-color: orange; float:left">
+		<div id="box1" class="box">
+			<div style="background-color: white; height: 20px"></div>
+		</div>
+	</div>
+	<div style="clear:both"></div>
+	<div class="ruler"></div>
+	<div style="border: 1px solid #666; background-color: #dedede"><xmp id="log"></xmp></div>
+</body>
+</html>
diff --git a/dojo/tests/window.js b/dojo/tests/window.js
new file mode 100755
index 0000000..1365bf3
--- /dev/null
+++ b/dojo/tests/window.js
@@ -0,0 +1,11 @@
+dojo.provide("tests.window");
+
+// Run viewport related functions test
+
+try{
+	doh.registerUrl("tests.window.viewport", dojo.moduleUrl("dojo", "tests/window/viewport.html"));
+	doh.registerUrl("tests.window.viewportQuirks", dojo.moduleUrl("dojo", "tests/window/viewportQuirks.html"));
+	doh.registerUrl("tests.window.scroll", dojo.moduleUrl("dojo", "tests/window/test_scroll.html"), 99999999);
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojo/tests/window/test_scroll.html b/dojo/tests/window/test_scroll.html
new file mode 100644
index 0000000..4a4d4ba
--- /dev/null
+++ b/dojo/tests/window/test_scroll.html
@@ -0,0 +1,640 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+                "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+        <title>dojo.window.scrollIntoView Test</title>
+
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+		FIELDSET { border:2px groove black; display:inline; padding:2px; }
+		FIELDSET IFRAME { width:100px; height:100px; }
+	</style>
+	<script type="text/javascript" src="../../dojo.js"
+		djConfig="isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojo.window");
+
+		var usingNative = !(dojo.isMoz || dojo.isIE || dojo.isWebKit || dojo.isOpera);
+		dojo.addOnLoad(function(){
+		        doh.register("dojo.window.scroll",
+	                [
+				function checkAttrs(){
+					var body = dojo.body();
+					dojo.window.scrollIntoView(body);
+					doh.f(dojo.hasAttr(body,'_offsetParent'));
+					doh.f(dojo.hasAttr(body,'_parent'));
+				},
+				function test_8249(){
+					generateTest('8249_strict', '(0,-10)', '(0,+10)');
+					generateTest('8249_quirks', '(0,-10)', '(0,+10)');
+					generateTest('8249_loose_rtl', '(0,-10)', '(0,+10)');
+					generateTest('8249_quirks_rtl', '(0,-10)', '(0,+10)');
+				},
+				function test_8284(){
+					var minScroll, maxScroll, fudge=0;
+					if(dojo.isIE){
+						minScroll = maxScroll = 11;
+						if(dojo.isIE <= 6){
+							fudge = dojo.byId('8284_quirks').contentWindow.document.body.clientHeight-100; // needed for running inside DOH runner
+						}
+					}else{
+						minScroll = maxScroll = 10;
+					}
+					generateTestXY('8284_quirks', "0", -maxScroll+fudge, "0", minScroll-fudge);
+					generateTestXY('8284_quirks_rtl', "0", -maxScroll+fudge, "0", minScroll-fudge);
+					if(dojo.isIE >= 8){
+						maxScroll--;
+						minScroll--;
+					}
+					generateTestXY('8284_strict', "0", -maxScroll, "0", minScroll);
+					generateTestXY('8284_loose_rtl', "0", -maxScroll, "0", minScroll);
+				},
+				function test_absContent(){
+					var minScrollX, minScrollY, maxScrollX, maxScrollY;
+					if(dojo.isIE){
+						maxScrollX = -10 - sb;
+						maxScrollY = (dojo.isIE >= 8)? maxScrollX : (-38 - sb);
+					}else{
+						maxScrollX = maxScrollY = -10 - sb;
+					}
+					minScrollX = minScrollY = sb + 10;
+					generateTestXY('absContent_strict', maxScrollX, maxScrollY, minScrollX, minScrollY);
+					if(dojo.isIE < 7){
+						maxScrollX -= (sb & 1); // odd sized sb adds 1 more
+						minScrollX -= (sb & 1); // odd sized sb adds 1 more
+					}
+					if(dojo.isIE == 7){ minScrollX = -90; }
+					if(dojo.isOpera){
+						maxScrollX = 90;
+					}
+					generateTestXY('absContent_loose_rtl', maxScrollX, maxScrollY, minScrollX, minScrollY);
+					if(dojo.isIE){
+						maxScrollX = (dojo.isIE >= 7? -10 : -6) - sb;
+						maxScrollY = (dojo.isIE >= 7? -38 : -34) - sb;
+						minScrollY = minScrollX = -maxScrollX;
+					}else{
+						maxScrollX = maxScrollY = -(sb+10);
+						minScrollX = minScrollY = sb+10;
+					}
+					generateTestXY('absContent_quirks', maxScrollX, maxScrollY, minScrollX, minScrollY);
+					if(dojo.isIE < 8){
+						maxScrollX = (dojo.isIE >= 7 ? -10 : -6) - sb - (sb & 1);
+						minScrollX = "+" + ((dojo.isIE >= 7? 10 : 6) + sb - (sb & 1));
+					}
+					if(dojo.isOpera){
+						maxScrollX = 90;
+					}
+					generateTestXY('absContent_quirks_rtl', maxScrollX, maxScrollY, minScrollX, minScrollY);
+				},
+				function test_fixedNode(){
+					if(!(dojo.isIE <= 6)){
+						generateTest('fixedNode_strict', "(-1,-1)", "(+1,+1)");
+						generateTest('fixedNode_loose_rtl', "(-1,-1)", "(+1,+1)");
+					}
+					if(!dojo.isIE){
+						generateTest('fixedNode_quirks', "(-1,-1)", "(+1,+1)");
+						generateTest('fixedNode_quirks_rtl', "(-1,-1)", "(+1,+1)");
+					}
+				},
+				function test_fixedScrollable(){
+					if(!(dojo.isIE <= 6)){
+						generateTest('fixedScrollable_strict', dojo.isIE == 7? "(0,-54)(0,-1)" : "(0,-39)(0,-1)", dojo.isIE == 7? "(0,+39)(0,+1)" : "(0,+38)(0,+1)");
+						generateTest('fixedScrollable_loose_rtl', dojo.isIE == 7? "(0,-54)(0,-1)" : "(0,-39)(0,-1)", dojo.isIE == 7? "(0,+39)(0,+1)" : "(0,+38)(0,+1)");
+					}
+					if(!dojo.isIE){
+						generateTest('fixedScrollable_quirks', "(0,-39)(0,-1)", "(0,+38)(0,+1)");
+						generateTest('fixedScrollable_quirks_rtl', "(0,-39)(0,-1)", "(0,+38)(0,+1)");
+					}
+				},
+				function test_7036_8665(){
+					var maxScroll;
+					var minScroll;
+					if(dojo.isIE <= 7){
+						maxScroll = 54;
+						minScroll = 39;
+					}else{
+						maxScroll = 39;
+						minScroll = 38;
+					}
+					generateTest('7036_8665_strict', "(0,-"+maxScroll+")(0,-1)", "(0,+"+minScroll+")(0,+1)");
+					if(dojo.isIE){
+						maxScroll = 54;
+						minScroll = 39;
+					}else{
+						maxScroll = 39;
+						minScroll = 38;
+					}
+					generateTest('7036_8665_quirks', "(0,-"+maxScroll+")(0,-1)", "(0,+"+minScroll+")(0,+1)");
+					generateTest('7036_8665_quirks_rtl', "(0,-"+maxScroll+")(0,-1)", "(0,+"+minScroll+")(0,+1)");
+					if(dojo.isIE >= 8){
+						maxScroll = 39;
+						minScroll = 38;
+					}
+					generateTest('7036_8665_loose_rtl', "(0,-"+maxScroll+")(0,-1)", "(0,+"+minScroll+")(0,+1)");
+				},
+				function test_innerNoScrollBars(){
+					var scroll;
+					if(dojo.isIE <= 6){
+						scroll = 53;
+					}else if(dojo.isIE == 7){
+						scroll = 46;
+					}else{
+						scroll = 39;
+					}
+					generateTestXY('innerNoScrollBars_strict', scroll, -29, scroll, -29);
+					if(dojo.isIE){
+						scroll = -38;
+					}
+					generateTestXY('innerNoScrollBars_quirks', scroll, -29, scroll, -29);
+					if(dojo.isIE <= 6){
+						scroll = 53;
+					}else if(dojo.isIE == 7){
+						scroll = 46;
+					}else if(dojo.isIE >= 8 || dojo.isOpera){
+						scroll = "+0";
+					}else if(dojo.isWebKit){
+						scroll = "-0";
+					}else{
+						scroll = 39;
+					}
+					generateTestXY('innerNoScrollBars_loose_rtl', scroll, -29, scroll, -29);
+					if(dojo.isIE){
+						scroll = -38;
+					}
+					generateTestXY('innerNoScrollBars_quirks_rtl', scroll, -29, scroll, -29);
+				},
+				function test_noScrollBars(){
+					generateTest('noScrollBars_strict', "(0,0)", "(0,0)");
+					generateTest('noScrollBars_quirks', "(0,0)", "(0,0)");
+					generateTest('noScrollBars_loose_rtl', "(0,0)", "(0,0)");
+					generateTest('noScrollBars_quirks_rtl', "(0,0)", "(0,0)");
+				},
+				function test_bottomFloated(){
+					generateTest('bottomFloated_strict', "(+0,-0)", "(+0,-0)");
+					generateTest('bottomFloated_quirks', "(+0,-0)", "(+0,-0)");
+					generateTest('bottomFloated_loose_rtl', "("+(dojo.isOpera? -1 : (((dojo.isIE >= 8 || dojo.isWebKit)? "+" : "-")+0))+",-0)", "("+(dojo.isOpera? (sb+20) : (((dojo.isIE < 8 || dojo.isMoz)?"-":"+")+0))+",-0)");
+					generateTest('bottomFloated_quirks_rtl', "("+(dojo.isOpera? -1 : ((dojo.isWebKit? "+" : "-")+0))+",-0)", "("+(dojo.isOpera? (sb+20) : (((dojo.isIE || dojo.isMoz)?"-":"+")+0))+",-0)");
+				},
+				function test_table(){
+					var minScroll, maxScroll;
+					minScroll = "(0,+15)";
+					maxScroll = "(0,-15)";
+					generateTest('table_strict', maxScroll, minScroll);
+					generateTest('table_loose_rtl', maxScroll, minScroll);
+					if(dojo.isIE <= 6){
+						var fudge = dojo.byId('table_quirks').contentWindow.document.body.clientHeight-100; // needed for running inside DOH runner
+						maxScroll = "(0,-"+(15-fudge)+")";
+						minScroll = "(0,+"+(15-fudge)+")";
+					}
+					generateTest('table_quirks', maxScroll, minScroll);
+					generateTest('table_quirks_rtl', maxScroll, minScroll);
+				},
+				function test_innerScrollbars(){
+					var scroll = sb - 5;
+					generateTestXY('innerScrollbars_strict', -scroll, -scroll, scroll, scroll);
+					generateTestXY('innerScrollbars_loose_rtl', -scroll, -scroll, dojo.isIE == 7 ? -25 : scroll, scroll);
+					generateTestXY('innerScrollbars_quirks', -scroll, -scroll, scroll, scroll);
+					generateTestXY('innerScrollbars_quirks_rtl', -scroll, -scroll, scroll, scroll);
+				},
+				function test_8542(){
+					var fudge = 0;
+					if(dojo.isIE <= 6){
+						fudge = dojo.byId('8542_quirks').contentWindow.document.body.clientHeight-100; // needed for running inside DOH runner
+					}
+					generateTest('8542_strict', "(0,-10)", "(0,+20)");
+					generateTest('8542_quirks', "(0,-"+(10-fudge)+")", "(0,+"+(20-fudge)+")");
+					generateTest('8542_loose_rtl', "(0,-10)", "(0,+20)");
+					generateTest('8542_quirks_rtl', "(0,-"+(10-fudge)+")", "(0,+"+(20-fudge)+")");
+				},
+				function test_tooBig(){
+					var fudge = 0;
+					if(dojo.isIE <= 6){
+						fudge = dojo.byId('tooBig_quirks').contentWindow.document.body.clientHeight-100+sb; // needed for running inside DOH runner
+					}
+					var minScroll, maxScroll;
+					generateTestXY('tooBig_strict', sb+10,sb+20, 1,1);
+					generateTestXY('tooBig_quirks', sb+10-fudge,sb+20-fudge, 1,1);
+					if(dojo.isIE <= 7 || dojo.isMoz){
+						maxScroll = -1;
+					}else if(dojo.isIE){
+						maxScroll = +20;
+					}else if(dojo.isOpera){
+						maxScroll = -90;
+					}else{
+						maxScroll = sb+10;
+					}
+					if(dojo.isIE <= 7 || dojo.isMoz){
+						minScroll = -20;
+					}else if(dojo.isOpera){
+						minScroll = 80 + sb;
+					}else{
+						minScroll = 1;
+					}
+					generateTestXY('tooBig_loose_rtl', maxScroll,sb+20, minScroll,1);
+					if(dojo.isIE >= 8){
+						maxScroll = -1;
+						minScroll = -20;
+					}
+					generateTestXY('tooBig_quirks_rtl', maxScroll,sb+20-fudge, minScroll,1);
+				},
+				function test_htmlPadding(){
+					var fudge = 0;
+					if(dojo.isIE <= 6){
+						fudge = dojo.byId('tooBig_quirks').contentWindow.document.body.clientHeight-100+sb; // needed for running inside DOH runner
+					}
+					var minScroll, maxScroll;
+					if(dojo.isIE <= 7){
+						maxScroll = minScroll = 84;
+					}else{
+						maxScroll = minScroll = 70;
+					}
+					generateTest('htmlPadding_strict', "(0,-"+maxScroll+")", "(0,+"+minScroll+")");
+					generateTest('htmlPadding_loose_rtl', "(0,-"+maxScroll+")", "(0,+"+minScroll+")");
+					if(dojo.isIE){
+						maxScroll = minScroll = 34;
+					}
+					generateTest('htmlPadding_quirks', "(0,-"+(maxScroll-fudge)+")", "(0,+"+(minScroll-fudge)+")");
+					generateTest('htmlPadding_quirks_rtl', "(0,-"+(maxScroll-fudge)+")", "(0,+"+(minScroll-fudge)+")");
+				}
+			]);
+		        doh.run();
+		});
+		function generateTest(id, maxVal, minVal){
+			var expectedScroll, actualScroll, compare = usingNative? "isNot" : "is";
+			with(dojo.byId(id)){
+				scrollMin();
+				scrollMax();
+				scrollIntoView();
+				actualScroll = getScroll();
+				expectedScroll = usingNative? "(-1,-1)" : maxVal;
+				doh[compare](expectedScroll, actualScroll, id+" max failed");
+				scrollIntoView(); // make sure the value sticks
+				actualScroll = getScroll();
+				doh[compare](expectedScroll, actualScroll, id+" repeat max failed");
+				scrollMin();
+				scrollIntoView();
+				actualScroll = getScroll();
+				expectedScroll = usingNative? "(+1,+1)" : minVal;
+				doh[compare](expectedScroll, actualScroll, id+" min failed");
+			}
+		}
+		function generateTestXY(id, maxScrollX, maxScrollY, minScrollX, minScrollY){
+			if(typeof maxScrollX == "number" && maxScrollX > 0){ maxScrollX = "+" + maxScrollX; }
+			if(typeof maxScrollY == "number" && maxScrollY > 0){ maxScrollY = "+" + maxScrollY; }
+			if(typeof minScrollX == "number" && minScrollX > 0){ minScrollX = "+" + minScrollX; }
+			if(typeof minScrollY == "number" && minScrollY > 0){ minScrollY = "+" + minScrollY; }
+			generateTest(id, "("+maxScrollX+","+maxScrollY+")", "("+minScrollX+","+minScrollY+")");
+		}
+	</script>
+</head>
+<body>
+<h1>Automated scrollIntoView tests with 3 different DOCTYPEs as well as right-to-left</h1>
+<!-- compute scrollbar size for test result computations -->
+<table style="visibility:hidden;table-layout:fixed;">
+<tr><td><div id="nonscroll"  style="width:100px;overflow:hidden;border:1px solid blue;"> </div></td></tr>
+<tr><td><div id="withscroll" style="width:100px;overflow-x:hidden;overflow-y:scroll;border:1px solid red;"> </div></td></tr>
+</table>
+<script type="text/javascript">
+sb = dojo.byId("nonscroll").clientWidth - dojo.byId("withscroll").clientWidth;
+console.debug('!!!!!!!!!!!! scrollbar size = ' + sb);
+</script>
+<!--	The test templates are below -->
+<fieldset>
+<label for="8249">Scrollable parent != offsetParent:</label>
+<div type="testIframe" id="8249">
+	<iframestyle>INPUT { float:left; }</iframestyle>
+	<div style="border-width:13px;"
+		><ul style="height:70px;"
+			><li><input style="background-color:white;"></li
+			><li><input style="background-color:white;"></li
+			><li><input style="background-color:white;"></li
+			><li><input id=it></li
+			><li><input style="background-color:white;"></li
+			><li><input style="background-color:white;"></li
+			><li><input style="background-color:white;"></li
+		></ul
+	></div>
+</div>
+</fieldset>
+<fieldset>
+<label for="8284">Absolute positioned overflow container:</label>
+<div type="testIframe" id="8284">
+	<iframestyle>HTML { overflow-x:hidden !important; /*IE6*/ }</iframestyle>
+	<hr style="height:200px;width:20px;"/>
+	<div style="position:absolute;top:0px;left:0px;height:200px;width:20px;">
+		<input id=it style="margin:90px 0px;">
+	</div>
+</div>
+</fieldset>
+<fieldset>
+<label for="absContent">Absolute-positioned content:</label>
+<div type="testIframe" id="absContent">
+	<iframestyle>INPUT { L_left:90px; R_right:90px; WKR_FF2R_left:90px; WKR_FF2R_right:auto; }
+		HTML { overflow:scroll !important; /*IE6*/ }</iframestyle>
+	<hr style="height:100px;width:200px;float:left;"/>
+	<hr style="height:100px;width:200px;float:right;"/>
+	<input id=it style="position:absolute;top:90px;">
+</div>
+</fieldset>
+<fieldset>
+<label for="fixedNode">Fixed-positioned node:</label>
+<div type="testIframe" id="fixedNode">
+	<hr style="height:50px;float:left;"/>
+	<hr style="height:50px;float:right;"/>
+	<input id=it style="position:fixed;top:75px;left:-5px;">
+</div>
+</fieldset>
+<fieldset>
+<label for="fixedScrollable">Fixed-positioned scrollable content:</label>
+<div type="testIframe" id="fixedScrollable">
+	<iframestyle>HTML { overflow-x:hidden !important; /*IE6*/ }
+		INPUT { height:20px; MZT_MZQ_WKT_WKQ_IEQ_OPQ_OPT_height:28px; width:20px; MZT_MZQ_WKT_WKQ_IEQ_OPQ_OPT_width:28px; }</iframestyle>
+	<div style="height:120px;width:70px;overflow-y:scroll;position:fixed;margin:-10px 0px 0px 0px;">
+		<input id=it style="margin:120px 0px;border:1px solid red;padding:3px;">
+		<hr style="width:10px;">
+	</div>
+	<hr style="height:200px;width:20px;"/>
+</div>
+</fieldset>
+<fieldset>
+<label for="7036_8665">Double scrollbars with absolute positioned content:</label>
+<div type="testIframe" id="7036_8665">
+	<iframestyle>INPUT { height:20px; MZT_MZQ_WKT_WKQ_IEQ_OPQ_OPT_height:28px; width:20px; MZT_MZQ_WKT_WKQ_IEQ_OPQ_OPT_width:28px; }</iframestyle>
+	<div style="height:70px;width:70px;overflow-y:scroll;position:absolute;top:26px;left:5px;"
+		><input id=it style="margin:80px 0px 80px 0px;border:1px solid red;padding:3px;"
+		><hr style="width:10px;"
+	></div>
+	<div style="height:26px;width:10px;position:absolute;top:96px;left:10px;"></div>
+</div>
+</fieldset>
+<fieldset>
+<label for="innerNoScrollBars">Complex scrollable inner content, no scrollbars:</label>
+<div type="testIframe" id="innerNoScrollBars">
+	<iframestyle>DIV { width:20px; IEQ_width:26px; height:20px; IEQ_height:24px; }</iframestyle>
+	<div style="overflow:hidden; margin:10px;border:1px solid red;border-width:1px 2px 3px 4px;"
+		><fieldset style="width:59px;overflow:visible;"
+			><input style="background-color:green;height:15px;float:left;"
+			><nobr style="margin:7px;padding:3px;border:5px solid pink;overflow:visible;display:block;width:90px;float:left;"
+				><input style="background-color:black;display:inline;width:24px;height:24px;float:left;"
+				><input id=it style="background-color:red;display:inline;float:left;"
+				><input style="background-color:blue;display:inline;width:16px;height:16px;float:left;"
+			></nobr
+			><input style="background-color:cyan;height:10px;float:left;"
+		></fieldset
+	></div>
+</div>
+</fieldset>
+<fieldset>
+<label for="noScrollBars">Nothing to do:</label>
+<div type="testIframe" id="noScrollBars">
+	<input id=it style="margin:25px;">
+</div>
+</fieldset>
+<fieldset>
+<label for="bottomFloated">Bottom, floated:</label>
+<div type="testIframe" id="bottomFloated">
+	<iframestyle>INPUT { L_float:left; R_float:right; WKR_FF2R_float:left; }</iframestyle>
+	<hr style="float:left;height:50px;"/>
+	<hr style="float:right;height:50px;"/>
+	<input id=it style="clear:both;">
+</div>
+</fieldset>
+<fieldset>
+<label for="table">Table:</label>
+<div type="testIframe" id="table">
+	<iframestyle>HTML { overflow-x:hidden !important; /*IE6*/ }</iframestyle>
+	<table style="border-width:75px 5px 75px 5px;float:left;" cellspacing="0" cellpadding="0" rules="none">
+		<tr><td><input id=it style="height:40px;width:40px;float:left;"></td></tr>
+	</table>
+</div>
+</fieldset>
+<fieldset>
+<label for="innerScrollbars">Inner scrollable content with scrollbars:</label>
+<div type="testIframe" id="innerScrollbars">
+	<iframestyle>
+		HTML { overflow:hidden !important; /*IE6*/ }
+		BODY { padding:10px; }
+		TABLE { OPR_float:left; }
+	</iframestyle>
+	<div style="overflow:scroll;height:80px;width:80px;"
+		><fieldset
+			><table cellspacing="25" cellpadding="0" border="0"
+				><tr><td><input id=it style="width:50px;height:50px;float:left;"></td></tr
+			></table
+		></fieldset
+	></div>
+</div>
+</fieldset>
+<fieldset>
+<label for="8542">position:absolute TD content:</label>
+<div type="testIframe" id="8542">
+	<div style="position:absolute;padding:100px 20px;left:5px;">
+		<table style="width:10px;height:10px;max-height:10px;table-layout:fixed;" cellspacing="0" cellpadding="0">
+			<tr><td><div style="position:relative;height:10px;width:10px;"><input id=it style="position:absolute;"></div></td></tr>
+		</table>
+	</div>
+</div>
+</fieldset>
+<fieldset>
+<label for="tooBig">Oversized content:</label>
+<div type="testIframe" id="tooBig">
+	<iframestyle>
+		HTML { IEZ_overflow:scroll !important; /*IE6*/ }
+		BODY { OPT_overflow:scroll !important; }
+	</iframestyle>
+	<input id=it style="position:absolute;margin:-10px 0px 0px 0px;left:-20px;width:130px;height:130px;">
+	<hr style="height:100px;width:200px;float:left;"/>
+	<hr style="height:100px;width:200px;float:right;"/>
+</div>
+</fieldset>
+<fieldset>
+<label for="htmlPadding">HTML/BODY padding:</label>
+<div type="testIframe" id="htmlPadding">
+	<iframestyle>HTML, BODY { padding:50px 9px; }
+		HTML { overflow-x:hidden !important; /*IE6*/ }</iframestyle>
+	<hr style="height:50px;width:20px;"/>
+	<input id=it style="display:block;clear:both;float:left;">
+	<hr style="clear:both;height:50px;width:20px;"/>
+</div>
+</fieldset>
+<br>
+<!--	Below is the magic code that creates the iframes from the given template.
+	This should be generalized for other files to include. -->
+<script>
+	function _findInput(win){
+		return win.document.getElementById('it');
+	}
+	function _scrollMin(win){
+		var n = _findInput(win);
+		while(n && n.tagName){
+			n.scrollTop = -9999;
+			n.scrollLeft = -9999;
+			n._scrollMinY = n.scrollTop;
+			n._scrollMinX = n.scrollLeft;
+			n.scrollTop++;
+			if(((n._scrollMaxX||0)-n._scrollMinX) == sb && (n.scrollWidth <= n.clientWidth || n.scrollWidth <= n.offsetWidth)){ // ignore fake scrolls
+			}else if((n._scrollMaxX||0) > n._scrollMinX){
+				n.scrollLeft++;
+			}
+			if(n.tagName == "BODY" && (n.scrollLeft || n.scrollTop)){ break; }
+			n = n.parentNode;
+		}
+	}
+	function _scrollMax(win){
+		var n = _findInput(win);
+		while(n && n.tagName){
+			n.scrollTop = 9999;
+			n.scrollLeft = 9999;
+			n._scrollMaxY = n.scrollTop;
+			n._scrollMaxX = n.scrollLeft;
+			n.scrollTop--;
+			if((n._scrollMaxX-(n._scrollMinX||0)) == sb && (n.scrollWidth <= n.clientWidth || n.scrollWidth <= n.offsetWidth)){
+				n._scrollMaxX = n.scrollLeft = (n._scrollMinX || 0); // ignore fake scrolls
+			}else{
+				n.scrollLeft--;
+			}
+			if(n.tagName == "BODY" && (n.scrollLeft || n.scrollTop || n._scrollMaxY || n._scrollMaxX)){
+				break; // skip HTML
+			}
+			n = n.parentNode;
+		}
+	}
+	function _getScroll(win){
+		var n = _findInput(win), scroll = '';
+		while(n && n.tagName){
+			var left = n.scrollLeft - n._scrollMinX,
+			top = n.scrollTop - n._scrollMinY,
+			right = n._scrollMaxX - n.scrollLeft,
+			bottom = n._scrollMaxY - n.scrollTop;
+			if(left || top || n._scrollMinX || n._scrollMaxX || n._scrollMinY || n._scrollMaxY){
+				scroll += '('+(left<=right?((left==right?'':'+')+left):(right<0 ? '0' : ('-'+right)))+','+(top<=bottom?((top==bottom?'':'+')+top):(bottom<0 ? '0' : ('-'+bottom)))+')';
+			}
+			n = n.parentNode;
+		}
+		return scroll || '(0,0)';
+	}
+	function _scrollIntoView(win){
+		var n = _findInput(win);
+		dojo.withGlobal(win, 'scrollIntoView', dojo.window, [n]);
+	}
+	function _onClick(win){
+		_scrollIntoView(win);
+		alert(_getScroll(win));
+	}
+	function initIframeMethods(iframeWin, parentWin){
+		iframeWin.frameElement.findInput = function(){ return parentWin._findInput(iframeWin) };
+		iframeWin.frameElement.scrollMin = function(){ parentWin._scrollMin(iframeWin) };
+		iframeWin.frameElement.scrollMax = function(){ parentWin._scrollMax(iframeWin) };
+		iframeWin.frameElement.getScroll = function(){ return parentWin._getScroll(iframeWin) };
+		iframeWin.frameElement.scrollIntoView = function(){ parentWin._scrollIntoView(iframeWin) };
+		iframeWin.frameElement.onClick = function(){ parentWin._onClick(iframeWin) };
+	}
+	function getIframeSrc(content, doctype, rtl){
+		content = content.replace(/"/g/*balance"*/,"'").replace(/iframe.javascript/g,"text/javascript").replace(/<input\b/ig,"<INPUT readOnly ");
+		var iframeSrc = 'javascript:"';
+		// find browser specific CSS attributes
+		if(dojo.isIE){
+			content = content.replace(/IE([A-Z]_)/g, "$1");
+		}else if(dojo.isWebKit){
+			content = content.replace(/WK([A-Z]_)/g, "$1");
+		}else if(dojo.isMoz){
+			content = content.replace(/MZ([A-Z]_)/g, "$1");
+		}else if(dojo.isOpera){
+			content = content.replace(/OP([A-Z]_)/g, "$1");
+		}
+		// find DOCTYPE specific CSS attributes
+		if(doctype=="strict"){
+			iframeSrc += "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>\n";
+			content = content.replace(/[A-Z0-9_]*(\b|_)[SZ]_[A-Z0-9_]*/g, "");
+		}else if(doctype=="loose"){
+			iframeSrc += "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>\n";
+			content = content.replace(/[A-Z0-9_]*(\b|_)[TZ]_[A-Z0-9_]*/g, "");
+		}else{
+			if(dojo.isWebKit){
+				iframeSrc += "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>\n"; // quirks: needed for WebKit's javascript: protocol
+			}
+			content = content.replace(/[A-Z0-9_]*(\b|_)[QZ]_[A-Z0-9_]*/g, "");
+		}
+		if(rtl){
+			content = content.replace(/[A-Z0-9_]*(\b|_)R_[A-Z0-9_]*/g, "");
+		}else{
+			content = content.replace(/[A-Z0-9_]*(\b|_)L_[A-Z0-9_]*/g, "");
+		}
+		content = content.replace(/\s*<(\/?)iframestyle>\s*/ig,"<$1"+"STYLE>");
+		var i = content.indexOf('<STYLE>');
+		var style = '';
+		if(i >= 0){
+			var j = content.indexOf('</STYLE>');
+			if(j >= 0){
+				style = content.substring(i+7, j);
+				content = content.substr(j+8);
+			}
+		}
+		iframeSrc +=
+		'<HTML dir='+(rtl?'rtl':'ltr')+'>'+
+		'<HEAD>'+
+			'<STYLE>'+
+				'* { border:0px solid white;padding:0px;margin:0px;font-style:normal;font-family:monospace;font-size:0px;line-height:normal; }\n'+
+				'INPUT { display:block;background-color:#ff0000;font-size:0px;line-height:0px;overflow:hidden;width:20px;height:20px; }\n'+
+				'UL { list-style-type: none;line-height:0px;width:45px;overflow:auto; }\n'+
+				'LI { list-style-type: none;line-height:20px;overflow:visible;max-width:20px;max-height:20px;height:20px;width:20px;float:left; }\n'+
+				'HR { width:120px;height:1px;visibility:hidden;display:block; }\n'+
+				style+
+			'<\/STYLE>'+
+			'<SCRIPT type=text/javascript>'+
+				'var win = frameElement.ownerDocument.defaultView||frameElement.document.parentWindow;'+
+				'win.initIframeMethods(window, win);'+
+			'<\/SCRIPT>'+
+		'<\/HEAD>'+
+		'<BODY BGCOLOR=#ffffff onclick=\'frameElement.onClick()\'>'+
+			content+
+		'<\/BODY>'+
+		'<\/HTML>"';
+		return iframeSrc;
+	}
+
+	function makeIframe(doctype, rtl){
+		var iframeSrc = getIframeSrc(content, doctype, rtl);
+		var container = document.createElement('fieldset');
+		var text = (doctype=="strict"? 'strict': (doctype=="loose"? 'loose' : 'quirks')) + (rtl? ' RTL' : '');
+		var color = (rtl? 'medium': '') + (doctype=="strict"? 'SpringGreen': (doctype=="loose"? 'Turquoise' : 'Aquamarine'));
+		var idSuffix = (doctype=="strict"? '_strict': (doctype=="loose"? '_loose': '_quirks')) + (rtl? '_rtl' : '');
+		dojo.style(container, "cssText", "display:inline;border:1px ridge gray;padding:0px;margin:0px;background-color:"+color+";text-align:"+(rtl?"right;":"left;"));
+		container.appendChild(document.createTextNode(text));
+		var iframe = document.createElement('iframe');
+		if(dojo.isOpera){ iframe.setAttribute('src', iframeSrc); }
+		iframe.setAttribute('frameBorder', "0");
+		iframe.setAttribute('scrolling', "auto");
+		iframe.setAttribute('allowTransparency', "true");
+		iframe.setAttribute('id', id + idSuffix);
+		iframe.setAttribute('name', id + idSuffix);
+		iframe.className = className;
+		dojo.style(iframe, "cssText", "display:block;border:2px solid "+color+";background-color:transparent;margin:0px;padding:3px;"+style);
+		container.appendChild(iframe);
+		srcNode.appendChild(container);
+		if(!dojo.isOpera){ iframe.setAttribute('src', iframeSrc); }
+	}
+	var testIframes = dojo.query('DIV[type="testIframe"]');
+	for(var i=0; i < testIframes.length; i++){
+		var srcNode = testIframes[i];
+		var content = srcNode.innerHTML || '';
+		var id = srcNode.id || "";
+		var style = srcNode.getAttribute('style') || "";
+		var className = srcNode.getAttribute('class') || srcNode.className || "";
+		if(typeof style == "object"){
+			style = style.cssText || "";
+		}
+		srcNode.innerHTML = "";
+		srcNode.removeAttribute('style');
+		srcNode.className = "";
+
+		makeIframe("strict", false);
+		makeIframe("quirks", false);
+		makeIframe("loose", true);
+		makeIframe("quirks", true);
+	}
+</script>
+</body>
+</html>
diff --git a/dojo/tests/window/test_scrollNoDTD.html b/dojo/tests/window/test_scrollNoDTD.html
new file mode 100644
index 0000000..1b5f222
--- /dev/null
+++ b/dojo/tests/window/test_scrollNoDTD.html
@@ -0,0 +1,74 @@
+<html>
+<head>
+		<title>dojo.window.scrollIntoView Test with No DTD</title>
+
+	<style type="text/css">
+		@import "../../resources/dojo.css";
+	</style>
+	<script type="text/javascript" src="../../dojo.js"
+		djConfig="isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojo.window");
+
+		dojo.addOnLoad(function(){
+			doh.register("window.scrollNoDTD",
+				function scrollIntoView(){
+					dojo.global.scrollTo(100,100);
+					var s2 = dojo.byId('s2');
+					s2.scrollTop = s2.scrollLeft = 10;
+					dojo.window.scrollIntoView('q2');
+					doh.is((dojo.isMoz && !dojo._isBodyLtr())? -87 : 87, s2.scrollLeft);
+					doh.is(113, s2.scrollTop);
+					doh.f(dojo.hasAttr(s2,'_offsetParent'));
+					doh.f(dojo.hasAttr(s2,'_parent'));
+					doh.f(dojo.hasAttr(s2,'_child'));
+					dojo.global.scrollTo(!dojo._isBodyLtr() ? 4000 : 0, 4000);
+				}
+			);
+			doh.run();
+		});
+	</script>
+</head>
+<body>
+	<center><h1>Manually scroll and click elements that have a border<br>and they should scroll into view</h1></center>
+	<input style="float:left;display:block;border:1px solid black;padding:50px;" onclick="dojo.window.scrollIntoView(this);return false;" value="">
+	<input style="float:right;display:block;border:100px solid black;" onclick="dojo.window.scrollIntoView(this);return false;" size="20" value="">
+	<br>
+	<table style="display:block;margin:200px;border:0 solid white;border-width:0 300px 0 200px;"><tr><td><div style="background-color:white;border:2px solid black;width:400px;" onclick="dojo.window.scrollIntoView(this)"> </div></td></tr>
+	<tr><td><div style="width:1000px;background-color:white;border:1px solid black;" onclick="dojo.window.scrollIntoView(this)"> </div></td></tr></table>
+	<div style="height:70px;width:200px;overflow-y:scroll;position:absolute;top:50%;left:50%;">
+		<p> </p>
+		<p style="padding:5px;border:2px solid black;" onclick="dojo.window.scrollIntoView(this)"> </p>
+		<p> </p>
+		<p> </p>
+	</div>
+	<div style="height:70px;width:70px;position:absolute;top:600px;left:100px;padding:20px;border:10px solid black;" onclick="dojo.window.scrollIntoView(this)"> </div>
+	<div style="border:0px solid red;border:50px solid white;">
+		<img src="../../../dojo/resources/blank.gif" style="height:300px;width:1px;display:block;background-color:white;">
+		<div id="s1" style="width:600px;height:500px;overflow:scroll;background-color:white;border:0px solid white;margin:0px;padding:30px;"
+			><img src="../../../dojo/resources/blank.gif" style="border:1px solid black;height:100px;width:498px;display:block;margin:0 300px 0 0;" onclick="dojo.window.scrollIntoView(this)"
+			><nobr id="p1" style="display:block;border:0px;padding:0px;margin:0px;"
+				><img id="c1" src="../../../dojo/resources/blank.gif" style="height:400px;width:100px;display:inline;border:1px solid black;" onclick="dojo.window.scrollIntoView(this)"
+				><img id="q1" src="../../../dojo/resources/blank.gif" width=500 height=400 style="background-color:white;display:inline;border:50px solid black;" onclick="dojo.window.scrollIntoView(this)"
+				><img id="t1" src="../../../dojo/resources/blank.gif" style="height:400px;width:200px;display:inline;border:5px solid black;" onclick="dojo.window.scrollIntoView(this)"
+			></nobr
+			><img src="../../../dojo/resources/blank.gif" style="border:1px solid black;height:200px;width:598px;margin:0 0 0 300px;display:block;" onclick="dojo.window.scrollIntoView(this)"
+		></div>
+		<img src="../../../dojo/resources/blank.gif" style="height:200px;width:1px;display:block;">
+		<div style="width:2000px;"> </div>
+	</div>
+	<div id="s2" style="width:550px;height:550px;overflow:hidden;background-color:white;border:0px solid white;margin:0px;padding:0px;border-width:45px 35px 15px 25px;"
+		><img src="../../../dojo/resources/blank.gif" style="border:1px solid black;height:111px;width:548px;display:block;" onclick="dojo.window.scrollIntoView(this)"
+		><nobr id="p2" style="display:block;border:0px solid cyan;padding:0px;margin:0px;"
+			><img id="c2" src="../../../dojo/resources/blank.gif" style="height:548px;width:85px;display:inline;border:1px solid black;" onclick="dojo.window.scrollIntoView(this)"
+			><img id="q2" src="../../../dojo/resources/blank.gif" style="width:548px;height:548px;display:inline;border:1px solid black;" onclick="dojo.window.scrollIntoView(this)"
+			><img id="t2" src="../../../dojo/resources/blank.gif" style="height:548px;width:85px;display:inline;border:1px solid black;" onclick="dojo.window.scrollIntoView(this)"
+		></nobr
+		><img src="../../../dojo/resources/blank.gif" style="border:1px solid black;height:100px;width:498px;display:block;" onclick="dojo.window.scrollIntoView(this)"
+	></div>
+	<img src="../../../dojo/resources/blank.gif" style="height:255px;width:1px;display:block;">
+	<div style="width:2222px;"> </div>
+</body>
+</html>
diff --git a/dojo/tests/window/test_scrollStrictDTD.html b/dojo/tests/window/test_scrollStrictDTD.html
new file mode 100644
index 0000000..ee9a1f7
--- /dev/null
+++ b/dojo/tests/window/test_scrollStrictDTD.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+				"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+		<title>dojo.window.scrollIntoView Test with Strict DTD</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojo.window");
+
+		dojo.addOnLoad(function(){
+			doh.register("dojo.window.scroll",
+				function scrollIntoView(){
+					dojo.global.scrollTo(100,100);
+					var s2 = dojo.byId('s2');
+					s2.scrollTop = s2.scrollLeft = 10;
+					dojo.window.scrollIntoView('q2');
+					doh.is((dojo.isMoz && !dojo._isBodyLtr())? -87 : 87, s2.scrollLeft);
+					doh.is(113, s2.scrollTop);
+					doh.f(dojo.hasAttr(s2,'_offsetParent'));
+					doh.f(dojo.hasAttr(s2,'_parent'));
+					doh.f(dojo.hasAttr(s2,'_child'));
+					dojo.global.scrollTo(!dojo._isBodyLtr() ? 4000 : 0, 4000);
+				}
+			);
+			doh.run();
+		});
+	</script>
+</head>
+<body>
+	<center><h1>Manually scroll and click elements that have a border<br>and they should scroll into view</h1></center>
+	<input style="float:left;display:block;border:1px solid black;padding:50px;" onclick="dojo.window.scrollIntoView(this);return false;" value="">
+	<input style="float:right;display:block;border:100px solid black;" onclick="dojo.window.scrollIntoView(this);return false;" size="20" value="">
+	<br>
+	<table style="display:block;margin:200px;border:0 solid white;border-width:0 300px 0 200px;"><tr><td><div style="background-color:white;border:2px solid black;width:400px;" onclick="dojo.window.scrollIntoView(this)"> </div></td></tr>
+	<tr><td><div style="width:1000px;background-color:white;border:1px solid black;" onclick="dojo.window.scrollIntoView(this)"> </div></td></tr></table>
+	<div style="height:70px;width:200px;overflow-y:scroll;position:absolute;top:50%;left:50%;">
+		<p> </p>
+		<p style="padding:5px;border:2px solid black;" onclick="dojo.window.scrollIntoView(this)"> </p>
+		<p> </p>
+		<p> </p>
+	</div>
+	<div style="height:70px;width:70px;position:absolute;top:600px;left:100px;padding:20px;border:10px solid black;" onclick="dojo.window.scrollIntoView(this)"> </div>
+	<div style="border:0px solid red;border:50px solid white;">
+		<img src="../../../dojo/resources/blank.gif" style="height:300px;width:1px;display:block;background-color:white;">
+		<div id="s1" style="width:600px;height:500px;overflow:scroll;background-color:white;border:0px solid white;margin:0px;padding:30px;"
+			><img src="../../../dojo/resources/blank.gif" style="border:1px solid black;height:100px;width:498px;display:block;margin:0 300px 0 0;" onclick="dojo.window.scrollIntoView(this)"
+			><nobr id="p1" style="display:block;border:0px;padding:0px;margin:0px;"
+				><img id="c1" src="../../../dojo/resources/blank.gif" style="height:400px;width:100px;display:inline;border:1px solid black;" onclick="dojo.window.scrollIntoView(this)"
+				><img id="q1" src="../../../dojo/resources/blank.gif" width=500 height=400 style="background-color:white;display:inline;border:50px solid black;" onclick="dojo.window.scrollIntoView(this)"
+				><img id="t1" src="../../../dojo/resources/blank.gif" style="height:400px;width:200px;display:inline;border:5px solid black;" onclick="dojo.window.scrollIntoView(this)"
+			></nobr
+			><img src="../../../dojo/resources/blank.gif" style="border:1px solid black;height:200px;width:598px;margin:0 0 0 300px;display:block;" onclick="dojo.window.scrollIntoView(this)"
+		></div>
+		<img src="../../../dojo/resources/blank.gif" style="height:200px;width:1px;display:block;">
+		<div style="width:2000px;"> </div>
+	</div>
+	<div id="s2" style="width:550px;height:550px;overflow:hidden;background-color:white;border:0px solid white;margin:0px;padding:0px;border-width:45px 35px 15px 25px;"
+		><img src="../../../dojo/resources/blank.gif" style="border:1px solid black;height:111px;width:548px;display:block;" onclick="dojo.window.scrollIntoView(this)"
+		><nobr id="p2" style="display:block;border:0px solid cyan;padding:0px;margin:0px;"
+			><img id="c2" src="../../../dojo/resources/blank.gif" style="height:548px;width:85px;display:inline;border:1px solid black;" onclick="dojo.window.scrollIntoView(this)"
+			><img id="q2" src="../../../dojo/resources/blank.gif" style="width:548px;height:548px;display:inline;border:1px solid black;" onclick="dojo.window.scrollIntoView(this)"
+			><img id="t2" src="../../../dojo/resources/blank.gif" style="height:548px;width:85px;display:inline;border:1px solid black;" onclick="dojo.window.scrollIntoView(this)"
+		></nobr
+		><img src="../../../dojo/resources/blank.gif" style="border:1px solid black;height:100px;width:498px;display:block;" onclick="dojo.window.scrollIntoView(this)"
+	></div>
+	<img src="../../../dojo/resources/blank.gif" style="height:255px;width:1px;display:block;">
+	<div style="width:2222px;"> </div>
+</body>
+</html>
diff --git a/dojo/tests/window/viewport.html b/dojo/tests/window/viewport.html
new file mode 100644
index 0000000..10b2c0f
--- /dev/null
+++ b/dojo/tests/window/viewport.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojo.window.getBox() test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		html, body { margin: 0px; padding: 0px; }
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: false"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojo.window");
+
+		function compute(){
+			var d = dojo.marginBox(dojo.byId("documentBorder")),
+				v = dojo.window.getBox();
+			dojo.byId("results").innerHTML +=
+				"Document is " + d.w + "px x " + d.h + "px" +
+				", viewport is " + v.w + "px x " + v.h + "px" +
+				 ", with scroll offset of (" + v.l + ", " + v.t + ")<br>";
+		}
+
+		function addText(){
+			dojo.byId("results").innerHTML += "Adding text...<br><br>";
+			var text=[];
+			for(var i=0;i<100;i++){
+				text.push("<span style='white-space: nowrap'>");
+				for(var j=0;j<3;j++){ text.push("Now is the time for all good men to come to the aid of their country."); }
+				text.push("</span><br>");
+			}
+			dojo.byId("documentBorder").innerHTML += text.join("\n");
+		}
+
+		dojo.addOnLoad(function(){
+			doh.register("dojo.window.viewport",
+				[
+					function initial(t){
+						console.log("calling compute");
+						compute();
+						console.log("called compute");
+						var d = dojo.marginBox(dojo.byId("documentBorder")),
+							v = dojo.window.getBox();
+						doh.t(v.h > d.h, "test that viewport is bigger than document");
+						console.log("v.h is " + v.h + " and d.h is " + d.h);
+					},
+					function expand(t){
+						var v = dojo.window.getBox();
+						console.log("calling addText");
+						addText();
+						compute();
+						var v2 = dojo.window.getBox();
+						doh.t(v2.h <= v.h, "test that viewport didn't increase in size due to text added to document");
+						doh.t(v2.h+20 >= v.h, "test that viewport didn't shrink, except for space taken by scrollbars");
+						console.log("end");
+					}
+				]
+			);
+			doh.run();
+		});
+
+	</script>
+</head>
+<body>
+	<div id="documentBorder" style="border: solid red 2px;">
+		<h1>dojo.window.getBox() test</h1>
+		<div style="padding: 10px; border: solid blue 1px;">padding div</div>
+		<button onclick="addText(); compute();">add text and compute size</button>
+		<button onclick="compute();">recompute size</button>
+		<ol>
+			<li>check results div below to see that before adding text, document is smaller than viewport
+			<li>after adding text, document should be bigger than viewport,and check that viewport size hasn't changed,
+				except maybe being a little bit smaller (about 15px) because of the size of the scrollbars
+			<li>resize browser window and click the "recompute size" button; reported viewport size should change
+			<li>scroll the window and click "recompute size" to see that the scroll position is taken into effect
+		</ol>
+		<div id=results style="border: 5px solid blue;"></div>
+	</div>
+</body>
+</html>
diff --git a/dojo/tests/window/viewportQuirks.html b/dojo/tests/window/viewportQuirks.html
new file mode 100644
index 0000000..5fd3d8c
--- /dev/null
+++ b/dojo/tests/window/viewportQuirks.html
@@ -0,0 +1,5 @@
+<html>
+<head>
+<script type="text/javascript" src="../../../dijit/tests/_loadTest.js" file="viewport.html"></script>
+</head>
+</html>
diff --git a/dojo/uacss.js b/dojo/uacss.js
new file mode 100644
index 0000000..f5da940
--- /dev/null
+++ b/dojo/uacss.js
@@ -0,0 +1,63 @@
+dojo.provide("dojo.uacss");
+
+(function(){
+	// 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.
+
+	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_ie6: maj(ie) == 6,
+			dj_ie7: maj(ie) == 7,
+			dj_ie8: maj(ie) == 8,
+			dj_quirks: d.isQuirks,
+			dj_iequirks: ie && d.isQuirks,
+
+			// NOTE: Opera not supported by dijit
+			dj_opera: opera,
+
+			dj_khtml: d.isKhtml,
+
+			dj_webkit: d.isWebKit,
+			dj_safari: d.isSafari,
+			dj_chrome: d.isChrome,
+
+			dj_gecko: d.isMozilla,
+			dj_ff3: maj(ff) == 3
+		}; // no dojo unsupported browsers
+
+	classes["dj_" + boxModel] = true;
+
+	// apply browser, browser version, and box model class names
+	var classStr = "";
+	for(var clz in classes){
+		if(classes[clz]){
+			classStr += clz + " ";
+		}
+	}
+	html.className = d.trim(html.className + " " + classStr);
+
+	// If RTL mode, then add dj_rtl flag plus repeat existing classes with -rtl extension.
+	// We can't run the code below until the <body> tag has loaded (so we can check for dir=rtl).  
+	// Unshift() is to run sniff code before the parser.
+	dojo._loaders.unshift(function(){
+		if(!dojo._isBodyLtr()){
+			var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ")
+			html.className = d.trim(html.className + " " + rtlClassStr);
+		}
+	});
+})();
diff --git a/dojo/window.js b/dojo/window.js
new file mode 100644
index 0000000..e2c498b
--- /dev/null
+++ b/dojo/window.js
@@ -0,0 +1,132 @@
+dojo.provide("dojo.window");
+
+dojo.window.getBox = 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 };
+};
+
+dojo.window.get = 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){
+		/*
+		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.defaultView;	//	Window
+};
+
+dojo.window.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
+	// summary:
+	//		Scroll the passed node into view, if it is not already.
+	
+	// don't rely on node.scrollIntoView working just because the function is there
+
+	try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
+		node = dojo.byId(node);
+		var doc = node.ownerDocument || dojo.doc,
+			body = doc.body || dojo.body(),
+			html = doc.documentElement || body.parentNode,
+			isIE = dojo.isIE, isWK = dojo.isWebKit;
+		// if an untested browser, then use the native method
+		if((!(dojo.isMoz || isIE || isWK || dojo.isOpera) || node == body || node == html) && (typeof node.scrollIntoView != "undefined")){
+			node.scrollIntoView(false); // short-circuit to native if possible
+			return;
+		}
+		var backCompat = doc.compatMode == 'BackCompat',
+			clientAreaRoot = backCompat? body : html,
+			scrollRoot = isWK ? body : clientAreaRoot,
+			rootWidth = clientAreaRoot.clientWidth,
+			rootHeight = clientAreaRoot.clientHeight,
+			rtl = !dojo._isBodyLtr(),
+			nodePos = pos || dojo.position(node),
+			el = node.parentNode,
+			isFixed = function(el){
+				return ((isIE <= 6 || (isIE && backCompat))? false : (dojo.style(el, 'position').toLowerCase() == "fixed"));
+			};
+		if(isFixed(node)){ return; } // nothing to do
+
+		while(el){
+			if(el == body){ el = scrollRoot; }
+			var elPos = dojo.position(el),
+				fixedPos = isFixed(el);
+	
+			if(el == scrollRoot){
+				elPos.w = rootWidth; elPos.h = rootHeight;
+				if(scrollRoot == html && isIE && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x
+				if(elPos.x < 0 || !isIE){ elPos.x = 0; } // IE can have values > 0
+				if(elPos.y < 0 || !isIE){ elPos.y = 0; }
+			}else{
+				var pb = dojo._getPadBorderExtents(el);
+				elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t;
+			}
+	
+			if(el != scrollRoot){ // body, html sizes already have the scrollbar removed
+				var clientSize = el.clientWidth,
+					scrollBarSize = elPos.w - clientSize;
+				if(clientSize > 0 && scrollBarSize > 0){
+					elPos.w = clientSize;
+					if(isIE && rtl){ elPos.x += scrollBarSize; }
+				}
+				clientSize = el.clientHeight;
+				scrollBarSize = elPos.h - clientSize;
+				if(clientSize > 0 && scrollBarSize > 0){
+					elPos.h = clientSize;
+				}
+			}
+			if(fixedPos){ // bounded by viewport, not parents
+				if(elPos.y < 0){
+					elPos.h += elPos.y; elPos.y = 0;
+				}
+				if(elPos.x < 0){
+					elPos.w += elPos.x; elPos.x = 0;
+				}
+				if(elPos.y + elPos.h > rootHeight){
+					elPos.h = rootHeight - elPos.y;
+				}
+				if(elPos.x + elPos.w > rootWidth){
+					elPos.w = rootWidth - elPos.x;
+				}
+			}
+			// calculate overflow in all 4 directions
+			var l = nodePos.x - elPos.x, // beyond left: < 0
+				t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0
+				r = l + nodePos.w - elPos.w, // beyond right: > 0
+				bot = t + nodePos.h - elPos.h; // beyond bottom: > 0
+			if(r * l > 0){
+				var s = Math[l < 0? "max" : "min"](l, r);
+				nodePos.x += el.scrollLeft;
+				el.scrollLeft += (isIE >= 8 && !backCompat && rtl)? -s : s;
+				nodePos.x -= el.scrollLeft;
+			}
+			if(bot * t > 0){
+				nodePos.y += el.scrollTop;
+				el.scrollTop += Math[t < 0? "max" : "min"](t, bot);
+				nodePos.y -= el.scrollTop;
+			}
+			el = (el != scrollRoot) && !fixedPos && el.parentNode;
+		}	
+	}catch(error){
+		console.error('scrollIntoView: ' + error);
+		node.scrollIntoView(false);
+	}
+};
diff --git a/dojox/LICENSE b/dojox/LICENSE
index ad1676a..4c93ded 100644
--- a/dojox/LICENSE
+++ b/dojox/LICENSE
@@ -13,7 +13,7 @@ The text of the AFL and BSD licenses is reproduced below.
 The "New" BSD License:
 **********************
 
-Copyright (c) 2005-2009, The Dojo Foundation
+Copyright (c) 2005-2010, The Dojo Foundation
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/dojox/analytics.js b/dojox/analytics.js
index e07a131..3367412 100644
--- a/dojox/analytics.js
+++ b/dojox/analytics.js
@@ -1,12 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.analytics"]){
-dojo._hasResource["dojox.analytics"]=true;
 dojo.provide("dojox.analytics");
 dojo.require("dojox.analytics._base");
-}
+
diff --git a/dojox/analytics/Urchin.js b/dojox/analytics/Urchin.js
index 31d6cfc..08e1625 100644
--- a/dojox/analytics/Urchin.js
+++ b/dojox/analytics/Urchin.js
@@ -1,31 +1,130 @@
-/*
-	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
-*/
+dojo.provide("dojox.analytics.Urchin");
+
+/*=====
+dojo.mixin(djConfig,{
+	// urchin: String
+	//		Used by `dojox.analytics.Urchin` as the default UA-123456-7 account
+	//		number used when being created. Alternately, you can pass an acct:"" 
+	//		parameter to the constructor a la: new dojox.analytics.Urchin({ acct:"UA-123456-7" });
+	urchin: ""
+});
+=====*/
 
+dojo.declare("dojox.analytics.Urchin", null, {
+	// summary: A Google-analytics helper, for post-onLoad inclusion of the tracker, and 
+	//		dynamic tracking during long-lived page cycles. 
+	//
+	// description:
+	//		A small class object will allows for lazy-loading the Google Analytics API
+	//		at any point during a page lifecycle. Most commonly, Google-Analytics is loaded
+	//		via a synchronous script tag in the body, which causes `dojo.addOnLoad` to 
+	//		stall until the external API has been completely loaded. The Urchin helper
+	//		will load the API on the fly, and provide a convenient API to use, wrapping
+	//		Analytics for Ajaxy or single page applications.
+	//
+	//		The class can be instantiated two ways: Programatically, by passing an
+	//		`acct:` parameter, or via Markup / dojoType and defining a djConfig 
+	//		parameter `urchin:`
+	//
+	//		IMPORTANT: 
+	//		This module will not work simultaneously with the core dojox.analytics 
+	//		package. If you need the ability to run Google Analytics AND your own local
+	//		analytics system, you MUST include dojox.analytics._base BEFORE dojox.analytics.Urchin
+	//
+	//	example:
+	//	|	// create the tracker programatically:
+	//	|	var tracker = new dojox.analytics.Urchin({ acct:"UA-123456-7" });
+	//
+	//	example: 
+	//	|	// define the urchin djConfig option:
+	//	|	var djConfig = { urchin: "UA-123456-7" };
+	//	|
+	//	|	// and in markup:
+	//	|	<div dojoType="dojox.analytics.Urchin"></div>
+	//	|	// or code:
+	//	|	new dojox.analytics.Urchin();
+	//
+	//	example:
+	//	|	// create and define all analytics with one tag. 
+	//	|	<div dojoType="dojox.analytics.Urchin" acct="UA-12345-67"></div>
+	//
+	// acct: String
+	//		your GA urchin tracker account number. Overrides `djConfig.urchin`
+	acct: "",
 
-if(!dojo._hasResource["dojox.analytics.Urchin"]){
-dojo._hasResource["dojox.analytics.Urchin"]=true;
-dojo.provide("dojox.analytics.Urchin");
-dojo.declare("dojox.analytics.Urchin",null,{acct:"",constructor:function(_1){
-this.tracker=null;
-dojo.mixin(this,_1);
-this.acct=this.acct||dojo.config.urchin;
-var re=/loaded|complete/,_2=("https:"==dojo.doc.location.protocol)?"https://ssl.":"http://www.",h=dojo.doc.getElementsByTagName("head")[0],n=dojo.create("script",{src:_2+"google-analytics.com/ga.js"},h);
-n.onload=n.onreadystatechange=dojo.hitch(this,function(e){
-if(e&&e.type=="load"||re.test(n.readyState)){
-n.onload=n.onreadystatechange=null;
-this._gotGA();
-h.removeChild(n);
-}
+	constructor: function(args){
+		// summary: 
+		//		Initialize this Urchin instance. Immediately starts the load
+		//		sequence, so defer construction until (ideally) after onLoad and
+		//		potentially widget parsing.
+		this.tracker = null;
+		dojo.mixin(this, args);
+		this.acct = this.acct || dojo.config.urchin;
+
+		var re = /loaded|complete/,
+			gaHost = ("https:" == dojo.doc.location.protocol) ? "https://ssl." : "http://www.",
+			h = dojo.doc.getElementsByTagName("head")[0],
+			n = dojo.create('script', {
+				src: gaHost + "google-analytics.com/ga.js"
+			}, h);
+
+		n.onload = n.onreadystatechange = dojo.hitch(this, function(e){
+			if(e && e.type == "load" || re.test(n.readyState)){
+				n.onload = n.onreadystatechange = null;
+				this._gotGA();
+				h.removeChild(n);
+			}
+		});
+
+	},
+
+	_gotGA: function(){
+		// summary: initialize the tracker
+		this.tracker = _gat._getTracker(this.acct);
+		this.GAonLoad.apply(this, arguments);
+	},
+	
+	GAonLoad: function(){
+		// summary: 
+		//		Stub function to fire when urchin is complete
+		//	description:
+		//		This function is executed when the tracker variable is 
+		//		complete and initialized. The initial trackPageView (with
+		//		no arguments) is called here as well, so remeber to call 
+		//		manually if overloading this method.
+		//
+		//	example:
+		//	Create an Urchin tracker that will track a specific page on init
+		//	after page load (or parsing, if parseOnLoad is true)
+		//	|	dojo.addOnLoad(function(){
+		//	|		new dojox.ananlytics.Urchin({
+		//	|			acct:"UA-12345-67", 
+		//	|			GAonLoad: function(){
+		//	|				this.trackPageView("/custom-page");
+		//	|			}
+		//	|		});
+		//	|	});
+		
+		this.trackPageView();
+	},
+	
+	trackPageView: function(/* string */url){
+		// summary: A public API attached to this widget instance, allowing you 
+		//		Ajax-like notification of updates. 
+		//
+		//	url: String
+		//		A location to tell the tracker to track, eg: "/my-ajaxy-endpoint"
+		//
+		//	example:
+		//	Track clicks from a container of anchors and populate a `ContentPane`
+		//	|	// 'tracker' is our `Urchin` instance, pane is the `ContentPane` ref.
+		//	|	dojo.connect(container, "onclick", function(e){
+		//	|		var ref = dojo.attr(e.target, "href");
+		//	|		tracker.trackPageView(ref);
+		//	|		pane.attr("href", ref); 
+		//	|	});
+		
+		this.tracker._trackPageview.apply(this, arguments);
+	}
+	
 });
-},_gotGA:function(){
-this.tracker=_gat._getTracker(this.acct);
-this.GAonLoad.apply(this,arguments);
-},GAonLoad:function(){
-this.trackPageView();
-},trackPageView:function(_3){
-this.tracker._trackPageview.apply(this,arguments);
-}});
-}
diff --git a/dojox/analytics/_base.js b/dojox/analytics/_base.js
index f7db8a2..a22d9b4 100644
--- a/dojox/analytics/_base.js
+++ b/dojox/analytics/_base.js
@@ -1,82 +1,132 @@
-/*
-	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
-*/
+dojo.provide("dojox.analytics._base");
 
+dojox.analytics = function(){
+	// summary: TODOC
+	//		where we store data until we're ready to send it off.
+	//
+	//the data queue;
+	this._data = [];
 
-if(!dojo._hasResource["dojox.analytics._base"]){
-dojo._hasResource["dojox.analytics._base"]=true;
-dojo.provide("dojox.analytics._base");
-dojox.analytics=function(){
-this._data=[];
-this._id=1;
-this.sendInterval=dojo.config["sendInterval"]||5000;
-this.inTransitRetry=dojo.config["inTransitRetry"]||200;
-this.dataUrl=dojo.config["analyticsUrl"]||dojo.moduleUrl("dojox.analytics.logger","dojoxAnalytics.php");
-this.sendMethod=dojo.config["sendMethod"]||"xhrPost";
-this.maxRequestSize=dojo.isIE?2000:dojo.config["maxRequestSize"]||4000;
-dojo.addOnLoad(this,"schedulePusher");
-dojo.addOnUnload(this,"pushData",true);
+	//id of messages for this session/page
+	this._id = 1;
+
+	//some default values
+	this.sendInterval = dojo.config["sendInterval"] || 5000;
+	this.inTransitRetry = dojo.config["inTransitRetry"] || 200;
+	this.dataUrl = dojo.config["analyticsUrl"] || dojo.moduleUrl("dojox.analytics.logger", "dojoxAnalytics.php");
+	this.sendMethod = dojo.config["sendMethod"] || "xhrPost";
+	this.maxRequestSize = dojo.isIE ? 2000 : dojo.config["maxRequestSize"] || 4000;
+
+	//while we can go ahead and being logging as soon as this constructor is completed
+	//we're not going to schedule pushing data to the server until after the page
+	//has completed loading
+	dojo.addOnLoad(this, "schedulePusher");
+	dojo.addOnUnload(this, "pushData", true);
 };
-dojo.extend(dojox.analytics,{schedulePusher:function(_1){
-setTimeout(dojo.hitch(this,"checkData"),_1||this.sendInterval);
-},addData:function(_2,_3){
-if(arguments.length>2){
-var c=[];
-for(var i=1;i<arguments.length;i++){
-c.push(arguments[i]);
-}
-_3=c;
-}
-this._data.push({plugin:_2,data:_3});
-},checkData:function(){
-if(this._inTransit){
-this.schedulePusher(this.inTransitRetry);
-return;
-}
-if(this.pushData()){
-return;
-}
-this.schedulePusher();
-},pushData:function(){
-if(this._data.length){
-this._inTransit=this._data;
-this._data=[];
-var _4;
-switch(this.sendMethod){
-case "script":
-_4=dojo.io.script.get({url:this.getQueryPacket(),preventCache:1,callbackParamName:"callback"});
-break;
-case "xhrPost":
-default:
-_4=dojo.xhrPost({url:this.dataUrl,content:{id:this._id++,data:dojo.toJson(this._inTransit)}});
-break;
-}
-_4.addCallback(this,"onPushComplete");
-return _4;
-}
-return false;
-},getQueryPacket:function(){
-while(true){
-var _5={id:this._id++,data:dojo.toJson(this._inTransit)};
-var _6=this.dataUrl+"?"+dojo.objectToQuery(_5);
-if(_6.length>this.maxRequestSize){
-this._data.unshift(this._inTransit.pop());
-this._split=1;
-}else{
-return _6;
-}
-}
-},onPushComplete:function(_7){
-if(this._inTransit){
-delete this._inTransit;
-}
-if(this._data.length>0){
-this.schedulePusher(this.inTransitRetry);
-}else{
-this.schedulePusher();
-}
-}});
-dojox.analytics=new dojox.analytics();
-}
+
+dojo.extend(dojox.analytics, {
+	schedulePusher: function(/* Int */interval){
+		// summary: Schedule the data pushing routines to happen in interval ms
+		setTimeout(dojo.hitch(this, "checkData"), interval || this.sendInterval); 
+	},
+
+	addData: function(dataType, data){
+		// summary:
+		//	add data to the queue. Will be pusshed to the server on the next
+		//	data push
+
+		if(arguments.length > 2){
+			// FIXME: var c = dojo._toArray(arguments) ?
+			var c = [];
+			for(var i = 1; i < arguments.length; i++){
+				c.push(arguments[i]);
+			}
+			data = c;
+		}
+
+		this._data.push({ plugin: dataType, data: data });
+	},
+
+	checkData: function(){
+		// summary: TODOC?
+		if(this._inTransit){
+			this.schedulePusher(this.inTransitRetry);
+			return;
+		}
+		
+		if(this.pushData()){ return; }
+		this.schedulePusher();
+	},
+
+	pushData: function(){
+		// summary:
+		//	pushes data to the server if any exists.  If a push is done, return
+		//	the deferred after hooking up completion callbacks.  If there is no data
+		//	to be pushed, return false;
+		if(this._data.length){
+			//clear the queue
+			this._inTransit = this._data;
+			this._data = [];
+			var def;
+			switch(this.sendMethod){
+				case "script":
+					def = dojo.io.script.get({
+						url: this.getQueryPacket(),
+						preventCache: 1,
+						callbackParamName: "callback"
+					});
+					break;
+				case "xhrPost":
+				default:
+					def = dojo.xhrPost({
+						url:this.dataUrl,
+						content:{
+							id: this._id++,
+							data: dojo.toJson(this._inTransit)
+						}
+					});
+					break;
+			}
+			def.addCallback(this, "onPushComplete");
+			return def;
+		}
+		return false;
+	},
+
+	getQueryPacket: function(){
+		// summary: TODOC
+		while(true){
+			var content = {
+				id: this._id++,
+				data: dojo.toJson(this._inTransit)
+			};
+			
+			//FIXME would like a much better way to get the query down to lenght
+			var query = this.dataUrl + '?' + dojo.objectToQuery(content);
+			if(query.length > this.maxRequestSize){
+				this._data.unshift(this._inTransit.pop());
+				this._split = 1;
+			}else{
+				return query;
+			}
+		}
+	},
+
+	onPushComplete: function(results){
+		// summary:
+		//	If our data push was successfully, remove the _inTransit data and schedule the next
+		//	parser run.
+		if(this._inTransit){
+			delete this._inTransit;
+		}
+
+		if(this._data.length > 0){
+			this.schedulePusher(this.inTransitRetry);
+		}else{
+			this.schedulePusher();
+		}
+	}
+});
+
+//create the analytics  singleton
+dojox.analytics = new dojox.analytics();
diff --git a/dojox/analytics/logger/JSON.php b/dojox/analytics/logger/JSON.php
new file mode 100755
index 0000000..e87e4d0
--- /dev/null
+++ b/dojox/analytics/logger/JSON.php
@@ -0,0 +1,724 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/** 
+ * Converts to and from JSON format.
+ * 
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
+ * format. It is easy for humans to read and write. It is easy for machines
+ * to parse and generate. It is based on a subset of the JavaScript
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+ * This feature can also be found in  Python. JSON is a text format that is
+ * completely language independent but uses conventions that are familiar
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
+ * ideal data-interchange language.
+ * 
+ * This package provides a simple encoder and decoder for JSON notation. It
+ * is intended for use with client-side Javascript applications that make
+ * use of HTTPRequest to perform server communication functions - data can
+ * be encoded into JSON notation for use in a client-side javascript, or
+ * decoded from incoming Javascript requests. JSON format is native to
+ * Javascript, and can be directly eval()'ed with no further parsing
+ * overhead
+ *
+ * All strings should be in ASCII or UTF-8 format!
+ *
+ * LICENSE: Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met: Redistributions of source code must retain the
+ * above copyright notice, this list of conditions and the following
+ * disclaimer. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * 
+ * @category   
+ * @package     Services_JSON
+ * @author      Michal Migurski <mike-json at teczno.com>
+ * @author      Matt Knapp <mdknapp[at]gmail[dot]com>
+ * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+ * @copyright   2005 Michal Migurski
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+ */
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_SLICE',   1);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_STR',  2);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_ARR',  4);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_OBJ',  8);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_CMT', 16);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_LOOSE_TYPE', 10);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_STRICT_TYPE', 11);
+
+/** 
+ * Converts to and from JSON format.
+ *
+ * Brief example of use:
+ *
+ * <code>
+ * // create a new instance of Services_JSON
+ * $json = new Services_JSON();
+ * 
+ * // convert a complexe value to JSON notation, and send it to the browser
+ * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
+ * $output = $json->encode($value);
+ *
+ * print($output);
+ * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
+ * 
+ * // accept incoming POST data, assumed to be in JSON notation
+ * $input = file_get_contents('php://input', 1000000);
+ * $value = $json->decode($input);
+ * </code>
+ */
+class Services_JSON
+{
+   /**
+    * constructs a new JSON instance
+    *
+    * @param    int     $use    object behavior: when encoding or decoding,
+    *                           be loose or strict about object/array usage
+    *
+    *                           possible values:
+    *                           - SERVICES_JSON_STRICT_TYPE: strict typing, default.
+    *                                                        "{...}" syntax creates objects in decode().
+    *                           - SERVICES_JSON_LOOSE_TYPE:  loose typing.
+    *                                                        "{...}" syntax creates associative arrays in decode().
+    */
+    function Services_JSON($use = SERVICES_JSON_STRICT_TYPE)
+    {
+        $this->use = $use;
+    }
+
+   /**
+    * convert a string from one UTF-16 char to one UTF-8 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf16  UTF-16 character
+    * @return   string  UTF-8 character
+    * @access   private
+    */
+    function utf162utf8($utf16)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding'))
+            return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
+        
+        $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
+
+        switch(true) {
+            case ((0x7F & $bytes) == $bytes):
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x7F & $bytes);
+
+            case (0x07FF & $bytes) == $bytes:
+                // return a 2-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xC0 | (($bytes >> 6) & 0x1F))
+                     . chr(0x80 | ($bytes & 0x3F));
+
+            case (0xFFFF & $bytes) == $bytes:
+                // return a 3-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xE0 | (($bytes >> 12) & 0x0F))
+                     . chr(0x80 | (($bytes >> 6) & 0x3F))
+                     . chr(0x80 | ($bytes & 0x3F));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }        
+
+   /**
+    * convert a string from one UTF-8 char to one UTF-16 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf8   UTF-8 character
+    * @return   string  UTF-16 character
+    * @access   private
+    */
+    function utf82utf16($utf8)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding'))
+            return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+        
+        switch(strlen($utf8)) {
+            case 1:
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return $utf8;
+
+            case 2:
+                // return a UTF-16 character from a 2-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x07 & (ord($utf8{0}) >> 2))
+                     . chr((0xC0 & (ord($utf8{0}) << 6))
+                         | (0x3F & ord($utf8{1})));
+                
+            case 3:
+                // return a UTF-16 character from a 3-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr((0xF0 & (ord($utf8{0}) << 4))
+                         | (0x0F & (ord($utf8{1}) >> 2)))
+                     . chr((0xC0 & (ord($utf8{1}) << 6))
+                         | (0x7F & ord($utf8{2})));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }        
+
+   /**
+    * encodes an arbitrary variable into JSON format
+    *
+    * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
+    *                           see argument 1 to Services_JSON() above for array-parsing behavior.
+    *                           if var is a strng, note that encode() always expects it
+    *                           to be in ASCII or UTF-8 format!
+    *
+    * @return   string  JSON string representation of input var
+    * @access   public
+    */
+    function encode($var)
+    {
+        switch (gettype($var)) {
+            case 'boolean':
+                return $var ? 'true' : 'false';
+            
+            case 'NULL':
+                return 'null';
+            
+            case 'integer':
+                return (int) $var;
+                
+            case 'double':
+            case 'float':
+                return (float) $var;
+                
+            case 'string':
+                // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+                $ascii = '';
+                $strlen_var = strlen($var);
+
+               /*
+                * Iterate over every character in the string,
+                * escaping with a slash or encoding to UTF-8 where necessary
+                */
+                for ($c = 0; $c < $strlen_var; ++$c) {
+                    
+                    $ord_var_c = ord($var{$c});
+                    
+                    switch (true) {
+                        case $ord_var_c == 0x08:
+                            $ascii .= '\b';
+                            break;
+                        case $ord_var_c == 0x09:
+                            $ascii .= '\t';
+                            break;
+                        case $ord_var_c == 0x0A:
+                            $ascii .= '\n';
+                            break;
+                        case $ord_var_c == 0x0C:
+                            $ascii .= '\f';
+                            break;
+                        case $ord_var_c == 0x0D:
+                            $ascii .= '\r';
+                            break;
+
+                        case $ord_var_c == 0x22:
+                        case $ord_var_c == 0x2F:
+                        case $ord_var_c == 0x5C:
+                            // double quote, slash, slosh
+                            $ascii .= '\\'.$var{$c};
+                            break;
+                            
+                        case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+                            // characters U-00000000 - U-0000007F (same as ASCII)
+                            $ascii .= $var{$c};
+                            break;
+                        
+                        case (($ord_var_c & 0xE0) == 0xC0):
+                            // characters U-00000080 - U-000007FF, mask 110XXXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+                            $c += 1;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xF0) == 0xE0):
+                            // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}));
+                            $c += 2;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xF8) == 0xF0):
+                            // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}));
+                            $c += 3;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xFC) == 0xF8):
+                            // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}));
+                            $c += 4;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xFE) == 0xFC):
+                            // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}),
+                                         ord($var{$c + 5}));
+                            $c += 5;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+                    }
+                }
+                
+                return '"'.$ascii.'"';
+                
+            case 'array':
+               /*
+                * As per JSON spec if any array key is not an integer
+                * we must treat the the whole array as an object. We
+                * also try to catch a sparsely populated associative
+                * array with numeric keys here because some JS engines
+                * will create an array with empty indexes up to
+                * max_index which can cause memory issues and because
+                * the keys, which may be relevant, will be remapped
+                * otherwise.
+                * 
+                * As per the ECMA and JSON specification an object may
+                * have any string as a property. Unfortunately due to
+                * a hole in the ECMA specification if the key is a
+                * ECMA reserved word or starts with a digit the
+                * parameter is only accessible using ECMAScript's
+                * bracket notation.
+                */
+                
+                // treat as a JSON object  
+                if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+                    return '{' .
+                           join(',', array_map(array($this, 'name_value'),
+                                               array_keys($var),
+                                               array_values($var)))
+                           . '}';
+                }
+
+                // treat it like a regular array
+                return '[' . join(',', array_map(array($this, 'encode'), $var)) . ']';
+                
+            case 'object':
+                $vars = get_object_vars($var);
+                return '{' .
+                       join(',', array_map(array($this, 'name_value'),
+                                           array_keys($vars),
+                                           array_values($vars)))
+                       . '}';
+
+            default:
+                return '';
+        }
+    }
+    
+   /**
+    * array-walking function for use in generating JSON-formatted name-value pairs
+    *
+    * @param    string  $name   name of key to use
+    * @param    mixed   $value  reference to an array element to be encoded
+    *
+    * @return   string  JSON-formatted name-value pair, like '"name":value'
+    * @access   private
+    */
+    function name_value($name, $value)
+    {
+        return $this->encode(strval($name)) . ':' . $this->encode($value);
+    }        
+
+   /**
+    * reduce a string by removing leading and trailing comments and whitespace
+    *
+    * @param    $str    string      string value to strip of comments and whitespace
+    *
+    * @return   string  string value stripped of comments and whitespace
+    * @access   private
+    */
+    function reduce_string($str)
+    {
+        $str = preg_replace(array(
+        
+                // eliminate single line comments in '// ...' form
+                '#^\s*//(.+)$#m',
+    
+                // eliminate multi-line comments in '/* ... */' form, at start of string
+                '#^\s*/\*(.+)\*/#Us',
+    
+                // eliminate multi-line comments in '/* ... */' form, at end of string
+                '#/\*(.+)\*/\s*$#Us'
+    
+            ), '', $str);
+        
+        // eliminate extraneous space
+        return trim($str);
+    }
+
+   /**
+    * decodes a JSON string into appropriate variable
+    *
+    * @param    string  $str    JSON-formatted string
+    *
+    * @return   mixed   number, boolean, string, array, or object
+    *                   corresponding to given JSON input string.
+    *                   See argument 1 to Services_JSON() above for object-output behavior.
+    *                   Note that decode() always returns strings
+    *                   in ASCII or UTF-8 format!
+    * @access   public
+    */
+    function decode($str)
+    {
+        $str = $this->reduce_string($str);
+    
+        switch (strtolower($str)) {
+            case 'true':
+                return true;
+
+            case 'false':
+                return false;
+            
+            case 'null':
+                return null;
+            
+            default:
+                if (is_numeric($str)) {
+                    // Lookie-loo, it's a number
+
+                    // This would work on its own, but I'm trying to be
+                    // good about returning integers where appropriate:
+                    // return (float)$str;
+
+                    // Return float or int, as appropriate
+                    return ((float)$str == (integer)$str)
+                        ? (integer)$str
+                        : (float)$str;
+                    
+                } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
+                    // STRINGS RETURNED IN UTF-8 FORMAT
+                    $delim = substr($str, 0, 1);
+                    $chrs = substr($str, 1, -1);
+                    $utf8 = '';
+                    $strlen_chrs = strlen($chrs);
+                    
+                    for ($c = 0; $c < $strlen_chrs; ++$c) {
+                    
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                        $ord_chrs_c = ord($chrs{$c});
+                        
+                        switch (true) {
+                            case $substr_chrs_c_2 == '\b':
+                                $utf8 .= chr(0x08);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\t':
+                                $utf8 .= chr(0x09);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\n':
+                                $utf8 .= chr(0x0A);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\f':
+                                $utf8 .= chr(0x0C);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\r':
+                                $utf8 .= chr(0x0D);
+                                ++$c;
+                                break;
+
+                            case $substr_chrs_c_2 == '\\"':
+                            case $substr_chrs_c_2 == '\\\'':
+                            case $substr_chrs_c_2 == '\\\\':
+                            case $substr_chrs_c_2 == '\\/':
+                                if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
+                                   ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
+                                    $utf8 .= $chrs{++$c};
+                                }
+                                break;
+                                
+                            case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
+                                // single, escaped unicode character
+                                $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
+                                       . chr(hexdec(substr($chrs, ($c + 4), 2)));
+                                $utf8 .= $this->utf162utf8($utf16);
+                                $c += 5;
+                                break;
+        
+                            case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
+                                $utf8 .= $chrs{$c};
+                                break;
+        
+                            case ($ord_chrs_c & 0xE0) == 0xC0:
+                                // characters U-00000080 - U-000007FF, mask 110XXXXX
+                                //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 2);
+                                ++$c;
+                                break;
+    
+                            case ($ord_chrs_c & 0xF0) == 0xE0:
+                                // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 3);
+                                $c += 2;
+                                break;
+    
+                            case ($ord_chrs_c & 0xF8) == 0xF0:
+                                // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 4);
+                                $c += 3;
+                                break;
+    
+                            case ($ord_chrs_c & 0xFC) == 0xF8:
+                                // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 5);
+                                $c += 4;
+                                break;
+    
+                            case ($ord_chrs_c & 0xFE) == 0xFC:
+                                // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 6);
+                                $c += 5;
+                                break;
+
+                        }
+
+                    }
+                    
+                    return $utf8;
+                
+                } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
+                    // array, or object notation
+
+                    if ($str{0} == '[') {
+                        $stk = array(SERVICES_JSON_IN_ARR);
+                        $arr = array();
+                    } else {
+                        if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = array();
+                        } else {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = new stdClass();
+                        }
+                    }
+                    
+                    array_push($stk, array('what'  => SERVICES_JSON_SLICE,
+                                           'where' => 0,
+                                           'delim' => false));
+
+                    $chrs = substr($str, 1, -1);
+                    $chrs = $this->reduce_string($chrs);
+                    
+                    if ($chrs == '') {
+                        if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                            return $arr;
+
+                        } else {
+                            return $obj;
+
+                        }
+                    }
+
+                    //print("\nparsing {$chrs}\n");
+                    
+                    $strlen_chrs = strlen($chrs);
+                    
+                    for ($c = 0; $c <= $strlen_chrs; ++$c) {
+                    
+                        $top = end($stk);
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                    
+                        if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
+                            // found a comma that is not inside a string, array, etc.,
+                            // OR we've reached the end of the character list
+                            $slice = substr($chrs, $top['where'], ($c - $top['where']));
+                            array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
+                            //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                            if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                                // we are in an array, so just push an element onto the stack
+                                array_push($arr, $this->decode($slice));
+
+                            } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                                // we are in an object, so figure
+                                // out the property name and set an
+                                // element in an associative array,
+                                // for now
+                                if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // "name":value pair
+                                    $key = $this->decode($parts[1]);
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // name:value pair, where name is unquoted
+                                    $key = $parts[1];
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                }
+
+                            }
+
+                        } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
+                            // found a quote, and we are not inside a string
+                            array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
+                            //print("Found start of string at {$c}\n");
+
+                        } elseif (($chrs{$c} == $top['delim']) &&
+                                 ($top['what'] == SERVICES_JSON_IN_STR) &&
+                                 (($chrs{$c - 1} != '\\') ||
+                                 ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) {
+                            // found a quote, we're in a string, and it's not escaped
+                            array_pop($stk);
+                            //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '[') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-bracket, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
+                            //print("Found start of array at {$c}\n");
+
+                        } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
+                            // found a right-bracket, and we're in an array
+                            array_pop($stk);
+                            //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '{') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-brace, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
+                            //print("Found start of object at {$c}\n");
+
+                        } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
+                            // found a right-brace, and we're in an object
+                            array_pop($stk);
+                            //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($substr_chrs_c_2 == '/*') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a comment start, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
+                            $c++;
+                            //print("Found start of comment at {$c}\n");
+
+                        } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
+                            // found a comment end, and we're in one now
+                            array_pop($stk);
+                            $c++;
+                            
+                            for ($i = $top['where']; $i <= $c; ++$i)
+                                $chrs = substr_replace($chrs, ' ', $i, 1);
+                            
+                            //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        }
+                    
+                    }
+                    
+                    if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                        return $arr;
+
+                    } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                        return $obj;
+
+                    }
+                
+                }
+        }
+    }
+    
+}
+    
+?>
\ No newline at end of file
diff --git a/dojox/analytics/logger/dojoxAnalytics.php b/dojox/analytics/logger/dojoxAnalytics.php
new file mode 100644
index 0000000..dfc7ac8
--- /dev/null
+++ b/dojox/analytics/logger/dojoxAnalytics.php
@@ -0,0 +1,31 @@
+<?php
+	require_once("./JSON.php");
+
+	$filename = "./logs/analytics.log";
+	$json = new Services_JSON;
+
+	$id = $_REQUEST["id"];
+	$items = $json->decode($_REQUEST["data"]);
+
+	if (!$handle = fopen($filename, 'a+')) {
+		print '{error: "server error"}';
+		exit;
+	}
+
+	foreach($items as $i=>$item){
+		$item->_analyticsId = $id;
+		$item->_analyticsTimeStamp = time();
+		$log = $json->encode($item) . "\n";
+		fwrite($handle, $log);
+	}
+	
+	fclose($handle);
+
+	$response = "{'eventsRecieved': '" . sizeof($items) . "', 'id': '" . $id . "'}";
+	if ($_REQUEST["callback"]){
+		print htmlentities($_REQUEST["callback"]) . "(" . $response . ");";
+	}else{
+		print $response;
+	}
+	
+?>
diff --git a/dojox/analytics/plugins/consoleMessages.js b/dojox/analytics/plugins/consoleMessages.js
index 013df09..5a47d70 100644
--- a/dojox/analytics/plugins/consoleMessages.js
+++ b/dojox/analytics/plugins/consoleMessages.js
@@ -1,26 +1,21 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.analytics.plugins.consoleMessages"]){
-dojo._hasResource["dojox.analytics.plugins.consoleMessages"]=true;
 dojo.require("dojox.analytics._base");
 dojo.provide("dojox.analytics.plugins.consoleMessages");
-dojox.analytics.plugins.consoleMessages=new (function(){
-this.addData=dojo.hitch(dojox.analytics,"addData","consoleMessages");
-var _1=dojo.config["consoleLogFuncs"]||["error","warn","info","rlog"];
-if(!console){
-console={};
-}
-for(var i=0;i<_1.length;i++){
-if(console[_1[i]]){
-dojo.connect(console,_1[i],dojo.hitch(this,"addData",_1[i]));
-}else{
-console[_1[i]]=dojo.hitch(this,"addData",_1[i]);
-}
-}
+
+dojox.analytics.plugins.consoleMessages = new (function(){
+	// summary:
+	//	plugin to have analyitcs return the base info dojo collects
+	this.addData = dojo.hitch(dojox.analytics, "addData", "consoleMessages");
+
+	var lvls = dojo.config["consoleLogFuncs"] || ["error", "warn", "info", "rlog"];
+	if(!console){
+		console = {};
+	}
+
+	for(var i=0; i < lvls.length; i++){
+		if(console[lvls[i]]){
+			dojo.connect(console, lvls[i], dojo.hitch(this, "addData", lvls[i]));
+		}else{
+			console[lvls[i]] = dojo.hitch(this, "addData", lvls[i]);	
+		}
+	}
 })();
-}
diff --git a/dojox/analytics/plugins/dojo.js b/dojox/analytics/plugins/dojo.js
index bf431ee..04990ae 100644
--- a/dojox/analytics/plugins/dojo.js
+++ b/dojox/analytics/plugins/dojo.js
@@ -1,5 +1,3 @@
-if(!dojo._hasResource["dojox.analytics.plugins.dojo"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.analytics.plugins.dojo"] = true;
 dojo.require("dojox.analytics._base");
 dojo.provide("dojox.analytics.plugins.dojo");
 
@@ -19,5 +17,3 @@ dojox.analytics.plugins.dojo = new (function(){
 		this.addData(data);
 	}));
 })();
-
-}
diff --git a/dojox/analytics/plugins/idle.js b/dojox/analytics/plugins/idle.js
index 7a3a6fd..b8572a8 100644
--- a/dojox/analytics/plugins/idle.js
+++ b/dojox/analytics/plugins/idle.js
@@ -1,36 +1,31 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.analytics.plugins.idle"]){
-dojo._hasResource["dojox.analytics.plugins.idle"]=true;
 dojo.require("dojox.analytics._base");
 dojo.provide("dojox.analytics.plugins.idle");
-dojox.analytics.plugins.idle=new (function(){
-this.addData=dojo.hitch(dojox.analytics,"addData","idle");
-this.idleTime=dojo.config["idleTime"]||60000;
-this.idle=true;
-this.setIdle=function(){
-this.addData("isIdle");
-this.idle=true;
-};
-dojo.addOnLoad(dojo.hitch(this,function(){
-var _1=["onmousemove","onkeydown","onclick","onscroll"];
-for(var i=0;i<_1.length;i++){
-dojo.connect(dojo.doc,_1[i],this,function(e){
-if(this.idle){
-this.idle=false;
-this.addData("isActive");
-this.idleTimer=setTimeout(dojo.hitch(this,"setIdle"),this.idleTime);
-}else{
-clearTimeout(this.idleTimer);
-this.idleTimer=setTimeout(dojo.hitch(this,"setIdle"),this.idleTime);
-}
-});
-}
-}));
+
+// window startup data
+dojox.analytics.plugins.idle = new (function(){
+	this.addData = dojo.hitch(dojox.analytics, "addData", "idle");
+	this.idleTime=dojo.config["idleTime"] || 60000;
+	this.idle=true;
+
+	this.setIdle = function(){
+		this.addData("isIdle");
+		this.idle=true;
+
+	}
+	
+	dojo.addOnLoad(dojo.hitch(this, function(){
+		var idleResets=["onmousemove","onkeydown","onclick","onscroll"];
+		for (var i=0;i<idleResets.length;i++){
+			dojo.connect(dojo.doc,idleResets[i],this, function(e){ 
+				if (this.idle){
+					this.idle=false;
+					this.addData("isActive");
+					this.idleTimer=setTimeout(dojo.hitch(this,"setIdle"), this.idleTime);
+				}else{
+					clearTimeout(this.idleTimer);
+					this.idleTimer=setTimeout(dojo.hitch(this,"setIdle"), this.idleTime);
+				}
+			});
+		}
+	}));
 })();
-}
diff --git a/dojox/analytics/plugins/mouseClick.js b/dojox/analytics/plugins/mouseClick.js
index c8142a5..52ba1f5 100644
--- a/dojox/analytics/plugins/mouseClick.js
+++ b/dojox/analytics/plugins/mouseClick.js
@@ -1,52 +1,46 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.analytics.plugins.mouseClick"]){
-dojo._hasResource["dojox.analytics.plugins.mouseClick"]=true;
 dojo.require("dojox.analytics._base");
 dojo.provide("dojox.analytics.plugins.mouseClick");
-dojox.analytics.plugins.mouseClick=new (function(){
-this.addData=dojo.hitch(dojox.analytics,"addData","mouseClick");
-this.onClick=function(e){
-this.addData(this.trimEvent(e));
-};
-dojo.connect(dojo.doc,"onclick",this,"onClick");
-this.trimEvent=function(e){
-var t={};
-for(var i in e){
-switch(i){
-case "target":
-case "originalTarget":
-case "explicitOriginalTarget":
-var _1=["id","className","nodeName","localName","href","spellcheck","lang"];
-t[i]={};
-for(var j=0;j<_1.length;j++){
-if(e[i][_1[j]]){
-if(_1[j]=="text"||_1[j]=="textContent"){
-if((e[i]["localName"]!="HTML")&&(e[i]["localName"]!="BODY")){
-t[i][_1[j]]=e[i][_1[j]].substr(0,50);
-}
-}else{
-t[i][_1[j]]=e[i][_1[j]];
-}
-}
-}
-break;
-case "clientX":
-case "clientY":
-case "pageX":
-case "pageY":
-case "screenX":
-case "screenY":
-t[i]=e[i];
-break;
-}
-}
-return t;
-};
+
+// window startup data
+dojox.analytics.plugins.mouseClick = new (function(){
+	this.addData = dojo.hitch(dojox.analytics, "addData", "mouseClick");
+
+	this.onClick=function(e){
+		this.addData(this.trimEvent(e));
+	}
+	dojo.connect(dojo.doc, "onclick", this, "onClick");
+
+	this.trimEvent=function(e){
+		var t = {};
+		for (var i in e){
+			switch(i){
+				case "target":
+				case "originalTarget":
+				case "explicitOriginalTarget":
+					var props=["id","className","nodeName", "localName","href", "spellcheck", "lang"];
+					t[i]={};
+					for(var j=0;j<props.length;j++){
+						if(e[i][props[j]]){
+							if (props[j]=="text" || props[j]=="textContent"){
+								if ((e[i]["localName"]!="HTML")&&(e[i]["localName"]!="BODY")){
+									t[i][props[j]]=e[i][props[j]].substr(0,50);
+								}
+							}else{
+								t[i][props[j]]=e[i][props[j]];
+							}
+						}
+					}
+					break;
+				case "clientX":
+				case "clientY":
+				case "pageX":
+				case "pageY":
+				case "screenX":
+				case "screenY":
+					t[i]=e[i];
+					break;
+			}
+		}
+		return t;
+	}
 })();
-}
diff --git a/dojox/analytics/plugins/mouseOver.js b/dojox/analytics/plugins/mouseOver.js
index 1b187cc..53cea9a 100644
--- a/dojox/analytics/plugins/mouseOver.js
+++ b/dojox/analytics/plugins/mouseOver.js
@@ -1,77 +1,87 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.analytics.plugins.mouseOver"]){
-dojo._hasResource["dojox.analytics.plugins.mouseOver"]=true;
 dojo.require("dojox.analytics._base");
 dojo.provide("dojox.analytics.plugins.mouseOver");
-dojox.analytics.plugins.mouseOver=new (function(){
-this.watchMouse=dojo.config["watchMouseOver"]||true;
-this.mouseSampleDelay=dojo.config["sampleDelay"]||2500;
-this.addData=dojo.hitch(dojox.analytics,"addData","mouseOver");
-this.targetProps=dojo.config["targetProps"]||["id","className","localName","href","spellcheck","lang","textContent","value"];
-this.toggleWatchMouse=function(){
-if(this._watchingMouse){
-dojo.disconnect(this._watchingMouse);
-delete this._watchingMouse;
-return;
-}
-dojo.connect(dojo.doc,"onmousemove",this,"sampleMouse");
-};
-if(this.watchMouse){
-dojo.connect(dojo.doc,"onmouseover",this,"toggleWatchMouse");
-dojo.connect(dojo.doc,"onmouseout",this,"toggleWatchMouse");
-}
-this.sampleMouse=function(e){
-if(!this._rateLimited){
-this.addData("sample",this.trimMouseEvent(e));
-this._rateLimited=true;
-setTimeout(dojo.hitch(this,function(){
-if(this._rateLimited){
-this.trimMouseEvent(this._lastMouseEvent);
-delete this._lastMouseEvent;
-delete this._rateLimited;
-}
-}),this.mouseSampleDelay);
-}
-this._lastMouseEvent=e;
-return e;
-};
-this.trimMouseEvent=function(e){
-var t={};
-for(var i in e){
-switch(i){
-case "target":
-var _1=this.targetProps;
-t[i]={};
-for(var j=0;j<_1.length;j++){
-if(dojo.isObject(e[i])&&_1[j] in e[i]){
-if(_1[j]=="text"||_1[j]=="textContent"){
-if(e[i]["localName"]&&(e[i]["localName"]!="HTML")&&(e[i]["localName"]!="BODY")){
-t[i][_1[j]]=e[i][_1[j]].substr(0,50);
-}
-}else{
-t[i][_1[j]]=e[i][_1[j]];
-}
-}
-}
-break;
-case "x":
-case "y":
-if(e[i]){
-var _2=e[i];
-t[i]=_2+"";
-}
-break;
-default:
-break;
-}
-}
-return t;
-};
+
+dojox.analytics.plugins.mouseOver = new (function(){
+	this.watchMouse = dojo.config["watchMouseOver"] || true;
+	this.mouseSampleDelay = dojo.config["sampleDelay"] || 2500;
+	this.addData = dojo.hitch(dojox.analytics, "addData", "mouseOver");
+	this.targetProps = dojo.config["targetProps"] || ["id","className","localName","href", "spellcheck", "lang", "textContent", "value" ];
+
+	this.toggleWatchMouse=function(){
+		if (this._watchingMouse){
+			dojo.disconnect(this._watchingMouse);
+			delete this._watchingMouse;
+			return;
+		}	
+		dojo.connect(dojo.doc, "onmousemove", this, "sampleMouse");
+	}
+
+	if (this.watchMouse){
+		dojo.connect(dojo.doc, "onmouseover", this, "toggleWatchMouse");	
+		dojo.connect(dojo.doc, "onmouseout", this, "toggleWatchMouse");
+	}
+
+	this.sampleMouse=function(e){
+		if (!this._rateLimited){
+			this.addData("sample",this.trimMouseEvent(e));	
+			this._rateLimited=true;
+			setTimeout(dojo.hitch(this, function(){
+				if (this._rateLimited){
+					//this.addData("sample", this.trimMouseEvent(this._lastMouseEvent));
+					this.trimMouseEvent(this._lastMouseEvent);
+					delete this._lastMouseEvent;
+					delete this._rateLimited;
+				}
+			}), this.mouseSampleDelay);
+		}	
+		this._lastMouseEvent = e;
+		return e;
+	}
+
+	this.trimMouseEvent=function(e){
+		var t = {};
+		for (var i in e){
+			switch(i){
+				//case "currentTarget":
+				case "target":
+				//case "originalTarget":
+				//case "explicitOriginalTarget":
+					var props=this.targetProps;
+					t[i]={};
+					//console.log(e, i, e[i]);
+					for(var j=0;j<props.length;j++){
+						if(dojo.isObject(e[i]) && props[j] in e[i]){
+							 
+							if (props[j]=="text" || props[j]=="textContent"){
+								if (e[i]["localName"] && (e[i]["localName"]!="HTML")&&(e[i]["localName"]!="BODY")){
+									t[i][props[j]]=e[i][props[j]].substr(0,50);
+								}
+							}else{
+								t[i][props[j]]=e[i][props[j]];
+							}
+						}
+					}
+					break;
+				//case "clientX":
+				//case "clientY":
+				//case "pageX":
+				//case "pageY":
+				//case "screenX":
+				//case "screenY":
+				case "x":
+				case "y":
+					if (e[i]) {
+						//console.log("Attempting: " + i);
+						var val = e[i];
+						//console.log("val: " +  val); console.log(i + "e of i: " + val);
+						t[i]=val + '';							
+					}
+					break;
+				default: 
+					//console.log("Skipping: ", i);
+					break;
+			}
+		}
+		return t;
+	}	
 })();
-}
diff --git a/dojox/analytics/plugins/window.js b/dojox/analytics/plugins/window.js
index a7d2f56..48033cf 100644
--- a/dojox/analytics/plugins/window.js
+++ b/dojox/analytics/plugins/window.js
@@ -1,37 +1,31 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.analytics.plugins.window"]){
-dojo._hasResource["dojox.analytics.plugins.window"]=true;
 dojo.require("dojox.analytics._base");
 dojo.provide("dojox.analytics.plugins.window");
-dojox.analytics.plugins.window=new (function(){
-this.addData=dojo.hitch(dojox.analytics,"addData","window");
-this.windowConnects=dojo.config["windowConnects"]||["open","onerror"];
-for(var i=0;i<this.windowConnects.length;i++){
-dojo.connect(window,this.windowConnects[i],dojo.hitch(this,"addData",this.windowConnects[i]));
-}
-dojo.addOnLoad(dojo.hitch(this,function(){
-var _1={};
-for(var i in window){
-if(dojo.isObject(window[i])){
-switch(i){
-case "location":
-case "console":
-_1[i]=window[i];
-break;
-default:
-break;
-}
-}else{
-_1[i]=window[i];
-}
-}
-this.addData(_1);
-}));
+
+// window startup data
+dojox.analytics.plugins.window = new (function(){
+	this.addData = dojo.hitch(dojox.analytics, "addData", "window");
+	this.windowConnects = dojo.config["windowConnects"] || ["open", "onerror"];
+
+	for(var i=0; i<this.windowConnects.length;i++){
+		dojo.connect(window, this.windowConnects[i], dojo.hitch(this, "addData", this.windowConnects[i]));
+	}
+
+	dojo.addOnLoad(dojo.hitch(this, function(){
+		var data = {};
+		for(var i in window){
+			if (dojo.isObject(window[i])){
+				switch(i){
+					case "location":
+					case "console":
+						data[i]=window[i];	
+						break;
+					default:	
+						break;
+				}
+			}else{
+				data[i]=window[i];
+			}
+		}
+		this.addData(data);
+	}));
 })();
-}
diff --git a/dojox/analytics/profiles/analytics.profile.js b/dojox/analytics/profiles/analytics.profile.js
index 95e99be..a484da2 100644
--- a/dojox/analytics/profiles/analytics.profile.js
+++ b/dojox/analytics/profiles/analytics.profile.js
@@ -1,8 +1,21 @@
-/*
-	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
-*/
+dependencies = {
+        layers: [
+                {
+			name: "../dojox/analytics.js",
+                        dependencies: [
+                                "dojox.analytics",
+				"dojox.analytics.plugins.dojo",
+				"dojox.analytics.plugins.window",
+				"dojox.analytics.plugins.consoleMessages",
+				"dojox.analytics.plugins.mouseOver",
+				"dojox.analytics.plugins.mouseClick",
+				"dojox.analytics.plugins.idle"
+                        ]
+                }        
+	],
 
-
-dependencies={layers:[{name:"../dojox/analytics.js",dependencies:["dojox.analytics","dojox.analytics.plugins.dojo","dojox.analytics.plugins.window","dojox.analytics.plugins.consoleMessages","dojox.analytics.plugins.mouseOver","dojox.analytics.plugins.mouseClick","dojox.analytics.plugins.idle"]}],prefixes:[["dojox","../dojox"],["dijit","../dijit"]]};
+	prefixes: [
+                [ "dojox", "../dojox" ],
+                [ "dijit", "../dijit" ]
+        ]
+}
diff --git a/dojox/analytics/profiles/analyticsInBase.profile.js b/dojox/analytics/profiles/analyticsInBase.profile.js
index 83ead70..22dbbd3 100644
--- a/dojox/analytics/profiles/analyticsInBase.profile.js
+++ b/dojox/analytics/profiles/analyticsInBase.profile.js
@@ -1,8 +1,22 @@
-/*
-	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
-*/
+dependencies = {
+        layers: [
+                {
+			//name: "../dojox/analytics.js",
+			name: "dojo.js",
+                        dependencies: [
+                                "dojox.analytics",
+				"dojox.analytics.plugins.dojo",
+				"dojox.analytics.plugins.window",
+				"dojox.analytics.plugins.consoleMessages",
+				"dojox.analytics.plugins.mouseOver",
+				"dojox.analytics.plugins.mouseClick",
+				"dojox.analytics.plugins.idle"
+                        ]
+                }        
+	],
 
-
-dependencies={layers:[{name:"dojo.js",dependencies:["dojox.analytics","dojox.analytics.plugins.dojo","dojox.analytics.plugins.window","dojox.analytics.plugins.consoleMessages","dojox.analytics.plugins.mouseOver","dojox.analytics.plugins.mouseClick","dojox.analytics.plugins.idle"]}],prefixes:[["dojox","../dojox"],["dijit","../dijit"]]};
+	prefixes: [
+                [ "dojox", "../dojox" ],
+                [ "dijit", "../dijit" ]
+        ]
+}
diff --git a/dojox/analytics/tests/test_GoogleAnalytics.html b/dojox/analytics/tests/test_GoogleAnalytics.html
new file mode 100644
index 0000000..dab18fa
--- /dev/null
+++ b/dojox/analytics/tests/test_GoogleAnalytics.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox Analytics Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css" />
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true, usePlainJson: true, sendMethod: 'script', sendInterval: 5000, analyticsUrl: 'http://dojotoolkit.org/~dmachi/dojo-1.0/dojox/analytics/logger/dojoxAnalytics.php'"></script>
+
+	<!-- do not use: only for testing alternate themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	<script type="text/javascript" src="../Urchin.js"></script>
+	
+
+	<script language="JavaScript" type="text/javascript">
+		// include the analytics system
+		dojo.require("dojox.analytics.Urchin");
+		var tracker = null; 
+
+//	can run onLoad, too: 
+//		dojo.addOnLoad(function(){
+		var createTracker = function(){	
+			if(tracker) return;
+			// create and initialize Urchin after onLoad. You need a _real_ UA number
+			// available from http://google.com/analytics
+			tracker = new dojox.analytics.Urchin({ 
+				acct:"UA-123456-7",
+				GAonLoad: function(){
+					this.inherited("GAonLoad", arguments);
+					dojo.attr("lazy", "disabled", false);
+				}
+			});
+//		});
+		}
+		
+		var trackRandom = function(){
+			// FIXME: there is a small window (10ms to 'however long it took to load')
+			//	that trackPageView is unavailable. use tracker.GAonLoad function to 
+			// 	reliably know when the tracker is available.
+			tracker.trackPageView("/some-ajax-taggr");
+		}
+	</script>
+
+</head>
+<body class="tundra">
+
+	<h1>Simple Lazy loading of Google Analytics Code</h1>
+	
+	<button id="galoader" onclick="createTracker()">Create Tracker</button>
+	
+	<button id="lazy" onclick="trackRandom()" disabled="disabled">Track something</button>
+	
+</body>
+</html>
diff --git a/dojox/analytics/tests/test_GoogleAnalyticsMarkup.html b/dojox/analytics/tests/test_GoogleAnalyticsMarkup.html
new file mode 100644
index 0000000..96a95d3
--- /dev/null
+++ b/dojox/analytics/tests/test_GoogleAnalyticsMarkup.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox Analytics Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript">
+		var djConfig = { 
+			parseOnLoad: true, 
+			isDebug: true //,
+			// ALERT: you need a _real_ UA number, obtainable from
+			// signup @ http://google.com/analytics
+//			urchin: "UA-123456-7"
+		};
+	</script>
+	<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+
+	<!-- do not use: only for testing alternate themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	<script type="text/javascript" src="../Urchin.js"></script>
+	
+	<script language="JavaScript" type="text/javascript">
+		// include the analytics system
+		dojo.require("dojo.parser");
+		dojo.require("dojox.analytics.Urchin");
+		dojo.addOnLoad(function(){
+			// NOTE: this method does not permit you to do Ajax-style page tracking
+			// 	you will need to manually create a tracker programatically, and save
+			//	a reference. This is done to avoid taking in _Widget overhead for
+			// this simple class.
+			console.log("dom ready, now loading Urchin in background");
+			console.log("passed:", inmarkup.acct == "UA-12345-6785");
+			console.log("passed:", fromconfig.acct == "UA-123456-7");
+		});
+	</script>
+
+</head>
+<body>
+
+	<h1>Simple Lazy loading of Google Analytics Code</h1>
+	
+	<div jsId="fromconfig" dojoType="dojox.analytics.Urchin" acct="UA-123456-7"></div>
+	<div jsId="inmarkup" dojoType="dojox.analytics.Urchin" acct="UA-12345-6785"></div>
+
+</body>
+</html>
diff --git a/dojox/analytics/tests/test_analytics.html b/dojox/analytics/tests/test_analytics.html
new file mode 100644
index 0000000..42ef027
--- /dev/null
+++ b/dojox/analytics/tests/test_analytics.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox Analytics Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true, usePlainJson: true, sendMethod: 'script', sendInterval: 5000, analyticsUrl: 'http://dojotoolkit.org/~dmachi/dojo-1.0/dojox/analytics/logger/dojoxAnalytics.php'"></script>
+
+	<!-- do not use: only for testing alternate themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		// include the analytics system
+		dojo.require("dojox.analytics");
+
+		// this plugin returns the informatin dojo collects when it launches 
+		dojo.require("dojox.analytics.plugins.dojo");
+
+		// this plugin return the information the window has when it launches
+		// and it also ties to a few events such as window.option
+		dojo.require("dojox.analytics.plugins.window");
+
+		// this plugin tracks console. message, It logs console.error, warn, and 
+		// info messages to the tracker.  It also defines console.rlog() which 
+		// can be used to log only to the server.  Note that if isDebug() is disabled
+		// you will still see the console messages on the sever, but not in the actual
+		// browser console.
+		dojo.require("dojox.analytics.plugins.consoleMessages");
+
+		// tracks where a mouse is on a page an what it is over, periodically sampling
+		// and storing this data
+		dojo.require("dojox.analytics.plugins.mouseOver");
+
+		//tracks mouse clicks on the page
+		dojo.require("dojox.analytics.plugins.mouseClick");
+
+		//tracks when the user has gone idle
+		dojo.require("dojox.analytics.plugins.idle");
+		
+		dojo.require("dijit.TitlePane");
+		dojo.require("dojo.parser");
+		dojo.require("dojo.io.script");
+
+		// widgets used inside subpage loaded via href=
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.ComboBox");
+
+		dojo.addOnLoad(function(){console.info("Page Loaded Sample Message");});
+	</script>
+
+</head>
+<body class="tundra">
+	<table>
+		<tr>
+			<td colspan=3>
+				<h1 class="testTitle">Dijit TitlePane Test</h1>
+			</td>
+		</tr>
+		<tr>
+			<td width="20%"></td>
+			<td>
+				<div dojoType="dijit.TitlePane" title="digg" style="width: 300px;">
+					Lorem Ipsum Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque
+					iaculis, nulla id semper faucibus, pede tellus nonummy magna, vitae adipiscing
+					orci arcu ut augue. Nunc condimentum, magna a vestibulum convallis, libero purus
+					pulvinar orci, sed vestibulum urna sem ut pede. More Ipsum...
+					Sed sollicitudin suscipit risus. Nam ullamcorper. Sed nisl lectus, pellentesque
+					nec, malesuada eget, ornare a, libero. Lorem ipsum dolor sit amet,
+					consectetuer adipiscing elit.
+
+					<a href="http://cometdaily.com">cometdaily.com</a>
+				</div>
+
+				<div dojoType="dijit.TitlePane" title="Article 1" style="width: 300px;">
+					Lorem Ipsum Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque
+					iaculis, nulla id semper faucibus, pede tellus nonummy magna, vitae adipiscing
+					orci arcu ut augue. Nunc condimentum, magna a vestibulum convallis, libero purus
+					pulvinar orci, sed vestibulum urna sem ut pede. More Ipsum...
+					Sed sollicitudin suscipit risus. Nam ullamcorper. Sed nisl lectus, pellentesque
+					nec, malesuada eget, ornare a, libero. Lorem ipsum dolor sit amet,
+					consectetuer adipiscing elit.
+
+					<a href="http://dojotoolkit.org">dojotoolkit.org</a>
+				</div>
+			</td>
+			<td width="20%"></td>
+		</tr>
+	</table>
+</body>
+</html>
diff --git a/dojox/atom/io/Connection.js b/dojox/atom/io/Connection.js
old mode 100644
new mode 100755
index 369d0e1..f950f5f
--- a/dojox/atom/io/Connection.js
+++ b/dojox/atom/io/Connection.js
@@ -1,255 +1,432 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.atom.io.Connection"]){
-dojo._hasResource["dojox.atom.io.Connection"]=true;
-dojo.provide("dojox.atom.io.Connection");
-dojo.require("dojox.atom.io.model");
-dojo.declare("dojox.atom.io.Connection",null,{constructor:function(_1,_2){
-this.sync=_1;
-this.preventCache=_2;
-},preventCache:false,alertsEnabled:false,getFeed:function(_3,_4,_5,_6){
-this._getXmlDoc(_3,"feed",new dojox.atom.io.model.Feed(),dojox.atom.io.model._Constants.ATOM_NS,_4,_5,_6);
-},getService:function(_7,_8,_9,_a){
-this._getXmlDoc(_7,"service",new dojox.atom.io.model.Service(_7),dojox.atom.io.model._Constants.APP_NS,_8,_9,_a);
-},getEntry:function(_b,_c,_d,_e){
-this._getXmlDoc(_b,"entry",new dojox.atom.io.model.Entry(),dojox.atom.io.model._Constants.ATOM_NS,_c,_d,_e);
-},_getXmlDoc:function(_f,_10,_11,_12,_13,_14,_15){
-if(!_15){
-_15=dojo.global;
-}
-var ae=this.alertsEnabled;
-var _16={url:_f,handleAs:"xml",sync:this.sync,preventCache:this.preventCache,load:function(_17,_18){
-var _19=null;
-var _1a=_17;
-var _1b;
-if(_1a){
-if(typeof (_1a.getElementsByTagNameNS)!="undefined"){
-_1b=_1a.getElementsByTagNameNS(_12,_10);
-if(_1b&&_1b.length>0){
-_19=_1b.item(0);
-}else{
-if(_1a.lastChild){
-_19=_1a.lastChild;
-}
-}
-}else{
-if(typeof (_1a.getElementsByTagName)!="undefined"){
-_1b=_1a.getElementsByTagName(_10);
-if(_1b&&_1b.length>0){
-for(var i=0;i<_1b.length;i++){
-if(_1b[i].namespaceURI==_12){
-_19=_1b[i];
-break;
-}
-}
-}else{
-if(_1a.lastChild){
-_19=_1a.lastChild;
-}
-}
-}else{
-if(_1a.lastChild){
-_19=_1a.lastChild;
-}else{
-_13.call(_15,null,null,_18);
-return;
-}
-}
-}
-_11.buildFromDom(_19);
-if(_13){
-_13.call(_15,_11,_1a,_18);
-}else{
-if(ae){
-throw new Error("The callback value does not exist.");
-}
-}
-}else{
-_13.call(_15,null,null,_18);
-}
-}};
-if(this.user&&this.user!==null){
-_16.user=this.user;
-}
-if(this.password&&this.password!==null){
-_16.password=this.password;
-}
-if(_14){
-_16.error=function(_1c,_1d){
-_14.call(_15,_1c,_1d);
-};
-}else{
-_16.error=function(){
-throw new Error("The URL requested cannot be accessed");
-};
-}
-dojo.xhrGet(_16);
-},updateEntry:function(_1e,_1f,_20,_21,_22,_23){
-if(!_23){
-_23=dojo.global;
-}
-_1e.updated=new Date();
-var url=_1e.getEditHref();
-if(!url){
-throw new Error("A URL has not been specified for editing this entry.");
-}
-var _24=this;
-var ae=this.alertsEnabled;
-var _25={url:url,handleAs:"text",contentType:"text/xml",sync:this.sync,preventCache:this.preventCache,load:function(_26,_27){
-var _28=null;
-if(_21){
-_28=_27.xhr.getResponseHeader("Location");
-if(!_28){
-_28=url;
-}
-var _29=function(_2a,dom,_2b){
-if(_1f){
-_1f.call(_23,_2a,_28,_2b);
-}else{
-if(ae){
-throw new Error("The callback value does not exist.");
-}
-}
-};
-_24.getEntry(_28,_29);
-}else{
-if(_1f){
-_1f.call(_23,_1e,_27.xhr.getResponseHeader("Location"),_27);
-}else{
-if(ae){
-throw new Error("The callback value does not exist.");
-}
-}
-}
-return _26;
-}};
-if(this.user&&this.user!==null){
-_25.user=this.user;
-}
-if(this.password&&this.password!==null){
-_25.password=this.password;
-}
-if(_20){
-_25.error=function(_2c,_2d){
-_20.call(_23,_2c,_2d);
-};
-}else{
-_25.error=function(){
-throw new Error("The URL requested cannot be accessed");
-};
-}
-if(_22){
-_25.postData=_1e.toString(true);
-_25.headers={"X-Method-Override":"PUT"};
-dojo.rawXhrPost(_25);
-}else{
-_25.putData=_1e.toString(true);
-var xhr=dojo.rawXhrPut(_25);
-}
-},addEntry:function(_2e,url,_2f,_30,_31,_32){
-if(!_32){
-_32=dojo.global;
-}
-_2e.published=new Date();
-_2e.updated=new Date();
-var _33=_2e.feedUrl;
-var ae=this.alertsEnabled;
-if(!url&&_33){
-url=_33;
-}
-if(!url){
-if(ae){
-throw new Error("The request cannot be processed because the URL parameter is missing.");
-}
-return;
-}
-var _34=this;
-var _35={url:url,handleAs:"text",contentType:"text/xml",sync:this.sync,preventCache:this.preventCache,postData:_2e.toString(true),load:function(_36,_37){
-var _38=_37.xhr.getResponseHeader("Location");
-if(!_38){
-_38=url;
-}
-if(!_37.retrieveEntry){
-if(_2f){
-_2f.call(_32,_2e,_38,_37);
-}else{
-if(ae){
-throw new Error("The callback value does not exist.");
-}
-}
-}else{
-var _39=function(_3a,dom,_3b){
-if(_2f){
-_2f.call(_32,_3a,_38,_3b);
-}else{
-if(ae){
-throw new Error("The callback value does not exist.");
-}
-}
-};
-_34.getEntry(_38,_39);
-}
-return _36;
-}};
-if(this.user&&this.user!==null){
-_35.user=this.user;
-}
-if(this.password&&this.password!==null){
-_35.password=this.password;
-}
-if(_30){
-_35.error=function(_3c,_3d){
-_30.call(_32,_3c,_3d);
-};
-}else{
-_35.error=function(){
-throw new Error("The URL requested cannot be accessed");
-};
-}
-dojo.rawXhrPost(_35);
-},deleteEntry:function(_3e,_3f,_40,_41,_42){
-if(!_42){
-_42=dojo.global;
-}
-var url=null;
-if(typeof (_3e)=="string"){
-url=_3e;
-}else{
-url=_3e.getEditHref();
-}
-if(!url){
-_3f.call(_42,false,null);
-throw new Error("The request cannot be processed because the URL parameter is missing.");
-}
-var _43={url:url,handleAs:"text",sync:this.sync,preventCache:this.preventCache,load:function(_44,_45){
-_3f.call(_42,_45);
-return _44;
-}};
-if(this.user&&this.user!==null){
-_43.user=this.user;
-}
-if(this.password&&this.password!==null){
-_43.password=this.password;
-}
-if(_40){
-_43.error=function(_46,_47){
-_40.call(_42,_46,_47);
-};
-}else{
-_43.error=function(){
-throw new Error("The URL requested cannot be accessed");
-};
-}
-if(_41){
-_43.headers={"X-Method-Override":"DELETE"};
-dojo.xhrPost(_43);
-}else{
-dojo.xhrDelete(_43);
-}
-}});
-}
+dojo.provide('dojox.atom.io.Connection');
+dojo.require('dojox.atom.io.model');
+
+dojo.declare("dojox.atom.io.Connection",null,{
+	// summary: This object implements a transport layer for working with ATOM feeds and ATOM publishing protocols.
+	// description: This object implements a transport layer for working with ATOM feeds and ATOM publishing protocols.
+	//   Specifically, it provides a mechanism by which feeds can be fetched and entries can be fetched, created
+	//   deleted, and modified.  It also provides access to the introspection data.
+
+	constructor: function(/* Boolean */sync, /* Boolean */preventCache){
+		// 	summary: 
+		//		initializer
+		this.sync = sync;
+		this.preventCache = preventCache;
+	},
+
+	preventCache: false, //Flag to denote if the instance should use the xhr prevent cache mechanism
+
+	alertsEnabled: false, //Flag to turn on alerts instead of throwing errors.
+
+	getFeed: function(/*String*/url, /*Function*/callback, /*Function*/errorCallback, scope){
+		// 	summary: 
+		//		Function to obtain a s specific ATOM feed from a given ATOM Feed url.
+		//	description: 
+		//		This function takes the URL for a specific ATOM feed and returns 
+		//		the data from that feed to the caller through the use of a callback
+		//		handler.
+		//
+		// 	url: String
+		//		The URL of the ATOM feed to fetch.
+		//	callback: 
+		//		Function
+		//		A function reference that will handle the feed when it has been retrieved.
+		//		The callback should accept two parameters:  The feed object and the original complete DOM object.
+		//	scope: Object
+		//		The scope to use for all callbacks.
+		//
+		//	returns:  
+		//		Nothing. The return is handled through the callback handler.
+		this._getXmlDoc(url, "feed", new dojox.atom.io.model.Feed(), dojox.atom.io.model._Constants.ATOM_NS, callback, /*handleDocumentRetrieved,*/ errorCallback, scope);
+	},
+	
+	getService: function(url, callback, errorCallback, scope){
+		//	summary: 
+		//		Function to retrieve an introspection document from the given URL.
+		// 	description: 
+		//		This function takes the URL for an ATOM item and feed and returns 
+		//		the introspection document.
+		//
+		//	url: 
+		//		String
+		//		The URL of the ATOM document to obtain the introspection document of.
+		//	callback: 
+		//		Function 
+		//		A function reference that will handle the introspection document when it has been retrieved.
+		//		The callback should accept two parameters:  The introspection document object and the original complete DOM object.
+		//
+		//	returns:  
+		//		Nothing. The return is handled through the callback handler.
+		this._getXmlDoc(url, "service", new dojox.atom.io.model.Service(url), dojox.atom.io.model._Constants.APP_NS, callback, errorCallback, scope);
+	},
+	
+	getEntry: function(url, callback, errorCallback, scope){
+		//	summary: 
+		//		Function to retrieve a single entry from an ATOM feed from the given URL.
+		//	description: 
+		//		This function takes the URL for an ATOM entry and returns the constructed dojox.atom.io.model.Entry object through
+		//		the specified callback.
+		//
+		//	url: 
+		//		String
+		//		The URL of the ATOM Entry document to parse.
+		//	callback: 
+		//		Function
+		//		A function reference that will handle the Entry object obtained.   
+		//		The callback should accept two parameters, the dojox.atom.io.model.Entry object and the original dom.
+		//
+		//	returns:  
+		//		Nothing. The return is handled through the callback handler.
+		this._getXmlDoc(url, "entry", new dojox.atom.io.model.Entry(), dojox.atom.io.model._Constants.ATOM_NS, callback, errorCallback, scope);
+	},
+
+	_getXmlDoc: function(url, nodeName, newNode, namespace, callback, errorCallback, scope){
+		//	summary: 
+		//		Internal Function to retrieve an XML document and pass the results to a callback.
+		//	description: 
+		//		This internal function takes the URL for an XML document and and passes the 
+		//		parsed contents to a specified callback.
+		//
+		//	url: 
+		//		String
+		//		The URL of the XML document to retrieve
+		//	callback: 
+		//		Function
+		//		A function reference that will handle the retrieved XML data.
+		//		The callback should accept one parameter, the DOM of the parsed XML document.
+		//
+		//	returns:  
+		//		Nothing. The return is handled through the callback handler.
+		if(!scope){
+			scope = dojo.global;
+		}
+		var ae = this.alertsEnabled;
+		var xhrArgs = {
+			url: url,
+			handleAs: "xml",
+			sync: this.sync,
+			preventCache: this.preventCache,
+			load: function(data, args){
+				var node	 = null;
+				var evaldObj = data;
+				var nodes;
+				if(evaldObj){
+					//find the first node of the appropriate name
+					if(typeof(evaldObj.getElementsByTagNameNS)!= "undefined"){
+						nodes = evaldObj.getElementsByTagNameNS(namespace,nodeName);
+						if(nodes && nodes.length > 0){
+							node = nodes.item(0);
+						}else if(evaldObj.lastChild){
+							// name_spaces can be used without declaration of atom (for example
+							// gooogle feeds often returns iTunes name_space qualifiers on elements)
+							// Treat this situation like name_spaces not enabled.
+							node = evaldObj.lastChild;
+						} 
+					}else if(typeof(evaldObj.getElementsByTagName)!= "undefined"){
+						// Find the first eith the correct tag name and correct namespace.
+						nodes = evaldObj.getElementsByTagName(nodeName);
+						if(nodes && nodes.length > 0){
+							for(var i=0; i<nodes.length; i++){
+								if(nodes[i].namespaceURI == namespace){
+									node = nodes[i];
+									break;
+								}
+							}
+						}else if(evaldObj.lastChild){
+							node = evaldObj.lastChild;
+						}
+					}else if(evaldObj.lastChild){
+						node = evaldObj.lastChild;
+					}else{
+						callback.call(scope, null, null, args);
+						return;
+					}
+					newNode.buildFromDom(node);
+					if(callback){
+						callback.call(scope, newNode, evaldObj, args);
+					}else if(ae){
+						throw new Error("The callback value does not exist.");
+					}
+				}else{
+					callback.call(scope, null, null, args);
+				}
+			}
+		};
+
+		if(this.user && this.user !== null){
+			xhrArgs.user = this.user;
+		}
+		if(this.password && this.password !== null){
+			xhrArgs.password = this.password;
+		}
+
+		if(errorCallback){
+			xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
+		}else{
+			xhrArgs.error = function(){
+				throw new Error("The URL requested cannot be accessed");
+			};
+		}
+		dojo.xhrGet(xhrArgs);
+	},
+
+	updateEntry: function(entry, callback, errorCallback, retrieveUpdated, xmethod, scope){
+		//	summary: 
+		//		Function to update a specific ATOM entry by putting the new changes via APP.
+		//	description: 
+		//		This function takes a specific dojox.atom.io.model.Entry object and pushes the 
+		//		changes back to the provider of the Entry.
+		//		The entry MUST have a link tag with rel="edit" for this to work.
+		//
+		//	entry: 
+		//		Object
+		//		The dojox.atom.io.model.Entry object to update.
+		//	callback: 
+		//		Function
+		//		A function reference that will handle the results from the entry update.
+		//		The callback should accept two parameters:  The first is an Entry object, and the second is the URL of that Entry
+		//		Either can be null, depending on the value of retrieveUpdated.
+		//	retrieveUpdated: 
+		//		boolean
+		//		A boolean flag denoting if the entry that was updated should then be 
+		//		retrieved and returned to the caller via the callback.
+		//	xmethod: 
+		//		boolean
+		//		Whether to use POST for PUT/DELETE items and send the X-Method-Override header.
+		//	scope: 
+		//		Object
+		//		The scope to use for all callbacks.
+		//
+		//	returns:  
+		//		Nothing. The return is handled through the callback handler.
+		if(!scope){
+			scope = dojo.global;
+		}
+		entry.updated = new Date();
+		var url = entry.getEditHref();
+		if(!url){
+			throw new Error("A URL has not been specified for editing this entry.");
+		}
+
+		var self = this;
+		var ae = this.alertsEnabled;
+		var xhrArgs = {
+			url: url,
+			handleAs: "text",
+			contentType: "text/xml",
+			sync: this.sync,
+			preventCache: this.preventCache,
+			load: function(data, args){
+				var location = null;
+				if(retrieveUpdated){
+					location = args.xhr.getResponseHeader("Location");
+					if(!location){location = url;}
+
+					//Function to handle the callback mapping of a getEntry after an update to return the
+					//entry and location.
+					var handleRetrieve = function(entry, dom, args){
+						if(callback){
+							callback.call(scope, entry, location, args);
+						}else if(ae){
+							throw new Error("The callback value does not exist.");
+						}
+					};
+					self.getEntry(location,handleRetrieve);
+				}else{
+					if(callback){
+						callback.call(scope, entry, args.xhr.getResponseHeader("Location"), args);
+					}else if(ae){
+						throw new Error("The callback value does not exist.");
+					}
+				}
+				return data;
+			}
+		};
+		
+		if(this.user && this.user !== null){
+			xhrArgs.user = this.user;
+		}
+		if(this.password && this.password !== null){
+			xhrArgs.password = this.password;
+		}
+
+		if(errorCallback){
+			xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
+		}else{
+			xhrArgs.error = function(){
+				throw new Error("The URL requested cannot be accessed");
+			};
+		}
+
+		if(xmethod){
+			xhrArgs.postData = entry.toString(true); //Set the content to send.
+			xhrArgs.headers = {"X-Method-Override": "PUT"};
+			dojo.rawXhrPost(xhrArgs);
+		}else{
+			xhrArgs.putData = entry.toString(true); //Set the content to send.
+			var xhr = dojo.rawXhrPut(xhrArgs);
+		}
+	},
+
+	addEntry: function(entry, url, callback, errorCallback, retrieveEntry, scope){
+		//	summary: 
+		//		Function to add a new ATOM entry by posting the new entry via APP.
+		//	description: 
+		//		This function takes a specific dojox.atom.io.model.Entry object and pushes the 
+		//		changes back to the provider of the Entry.
+		//
+		//	entry: 
+		//		Object
+		//		The dojox.atom.io.model.Entry object to publish.
+		//	callback: 
+		//		Function
+		//		A function reference that will handle the results from the entry publish.
+		//		The callback should accept two parameters:   The first is an dojox.atom.io.model.Entry object, and the second is the location of the entry
+		//		Either can be null, depending on the value of retrieveUpdated.
+		//	retrieveEntry: 
+		//		boolean
+		//		A boolean flag denoting if the entry that was created should then be 
+		//		retrieved and returned to the caller via the callback.
+		//	scope: 
+		//		Object
+		//	 	The scope to use for all callbacks.
+		//
+		//	returns:  
+		//		Nothing. The return is handled through the callback handler.
+		if(!scope){
+			scope = dojo.global;
+		}
+
+		entry.published = new Date();
+		entry.updated = new Date();
+
+		var feedUrl = entry.feedUrl;
+		var ae = this.alertsEnabled;
+
+		//Determine which URL to use for the post.
+		if(!url && feedUrl){url = feedUrl;}
+		if(!url){
+			if(ae){
+				throw new Error("The request cannot be processed because the URL parameter is missing.");
+			}
+			return;
+		}
+
+		var self = this;
+		var xhrArgs = {
+			url: url,
+			handleAs: "text",
+			contentType: "text/xml",
+			sync: this.sync,
+			preventCache: this.preventCache,
+			postData: entry.toString(true),
+			load: function(data, args){
+				var location = args.xhr.getResponseHeader("Location");
+				if(!location){
+					location = url;
+				}
+				if(!args.retrieveEntry){
+					if(callback){
+						callback.call(scope, entry, location, args);
+					}else if(ae){
+						throw new Error("The callback value does not exist.");
+					}
+				}else{
+					//Function to handle the callback mapping of a getEntry after an update to return the
+					//entry and location.
+					var handleRetrieve = function(entry, dom, args){
+						if(callback){
+							callback.call(scope, entry, location, args);
+						}else if(ae){
+							throw new Error("The callback value does not exist.");
+						}
+					};
+					self.getEntry(location,handleRetrieve);
+				}
+				return data;
+			}
+		};
+
+		if(this.user && this.user !== null){
+			xhrArgs.user = this.user;
+		}
+		if(this.password && this.password !== null){
+			xhrArgs.password = this.password;
+		}
+
+		if(errorCallback){
+			xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
+		}else{
+			xhrArgs.error = function(){
+				throw new Error("The URL requested cannot be accessed");
+			};
+		}
+		dojo.rawXhrPost(xhrArgs);
+	},
+
+	deleteEntry: function(entry,callback,errorCallback,xmethod,scope){
+		//	summary: 
+		//		Function to delete a specific ATOM entry via APP.
+		//	description: 
+		//		This function takes a specific dojox.atom.io.model.Entry object and calls for a delete on the
+		//		service housing the ATOM Entry database.
+		//		The entry MUST have a link tag with rel="edit" for this to work.
+		//
+		//	entry: 
+		//		Object
+		//		The dojox.atom.io.model.Entry object to delete.
+		//	callback: 
+		//		Function
+		//		A function reference that will handle the results from the entry delete.
+		//		The callback is called only if the delete is successful.
+		//
+		//	returns:  
+		//		Nothing. The return is handled through the callback handler.
+		if(!scope){
+			scope = dojo.global;
+		}
+
+		var url = null;
+		if(typeof(entry) == "string"){
+			url = entry;
+		}else{
+			url = entry.getEditHref();
+		}
+		if(!url){
+			callback.call(scope, false, null);
+			throw new Error("The request cannot be processed because the URL parameter is missing.");
+		}
+
+		var xhrArgs = {
+			url: url,
+			handleAs: "text",
+			sync: this.sync,
+			preventCache: this.preventCache,
+			load: function(data, args){
+				callback.call(scope, args);
+				return data;
+			}
+		};
+
+		if(this.user && this.user !== null){
+			xhrArgs.user = this.user;
+		}
+		if(this.password && this.password !== null){
+			xhrArgs.password = this.password;
+		}
+
+		if(errorCallback){
+			xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
+		}else{
+			xhrArgs.error = function(){
+				throw new Error("The URL requested cannot be accessed");
+			};
+		}
+		if(xmethod){
+			xhrArgs.headers = {"X-Method-Override": "DELETE"};
+			dojo.xhrPost(xhrArgs);
+		}else{
+			dojo.xhrDelete(xhrArgs);
+		}
+	} 
+});
diff --git a/dojox/atom/io/model.js b/dojox/atom/io/model.js
index d89bdf0..ff0ea63 100644
--- a/dojox/atom/io/model.js
+++ b/dojox/atom/io/model.js
@@ -1,949 +1,1293 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.atom.io.model"]){
-dojo._hasResource["dojox.atom.io.model"]=true;
 dojo.provide("dojox.atom.io.model");
+
 dojo.require("dojox.xml.parser");
 dojo.require("dojo.string");
 dojo.require("dojo.date.stamp");
-dojox.atom.io.model._Constants={"ATOM_URI":"http://www.w3.org/2005/Atom","ATOM_NS":"http://www.w3.org/2005/Atom","PURL_NS":"http://purl.org/atom/app#","APP_NS":"http://www.w3.org/2007/app"};
-dojox.atom.io.model._actions={"link":function(_1,_2){
-if(_1.links===null){
-_1.links=[];
-}
-var _3=new dojox.atom.io.model.Link();
-_3.buildFromDom(_2);
-_1.links.push(_3);
-},"author":function(_4,_5){
-if(_4.authors===null){
-_4.authors=[];
-}
-var _6=new dojox.atom.io.model.Person("author");
-_6.buildFromDom(_5);
-_4.authors.push(_6);
-},"contributor":function(_7,_8){
-if(_7.contributors===null){
-_7.contributors=[];
-}
-var _9=new dojox.atom.io.model.Person("contributor");
-_9.buildFromDom(_8);
-_7.contributors.push(_9);
-},"category":function(_a,_b){
-if(_a.categories===null){
-_a.categories=[];
-}
-var _c=new dojox.atom.io.model.Category();
-_c.buildFromDom(_b);
-_a.categories.push(_c);
-},"icon":function(_d,_e){
-_d.icon=dojox.xml.parser.textContent(_e);
-},"id":function(_f,_10){
-_f.id=dojox.xml.parser.textContent(_10);
-},"rights":function(obj,_11){
-obj.rights=dojox.xml.parser.textContent(_11);
-},"subtitle":function(obj,_12){
-var cnt=new dojox.atom.io.model.Content("subtitle");
-cnt.buildFromDom(_12);
-obj.subtitle=cnt;
-},"title":function(obj,_13){
-var cnt=new dojox.atom.io.model.Content("title");
-cnt.buildFromDom(_13);
-obj.title=cnt;
-},"updated":function(obj,_14){
-obj.updated=dojox.atom.io.model.util.createDate(_14);
-},"issued":function(obj,_15){
-obj.issued=dojox.atom.io.model.util.createDate(_15);
-},"modified":function(obj,_16){
-obj.modified=dojox.atom.io.model.util.createDate(_16);
-},"published":function(obj,_17){
-obj.published=dojox.atom.io.model.util.createDate(_17);
-},"entry":function(obj,_18){
-if(obj.entries===null){
-obj.entries=[];
-}
-var _19=obj.createEntry?obj.createEntry():new dojox.atom.io.model.Entry();
-_19.buildFromDom(_18);
-obj.entries.push(_19);
-},"content":function(obj,_1a){
-var cnt=new dojox.atom.io.model.Content("content");
-cnt.buildFromDom(_1a);
-obj.content=cnt;
-},"summary":function(obj,_1b){
-var _1c=new dojox.atom.io.model.Content("summary");
-_1c.buildFromDom(_1b);
-obj.summary=_1c;
-},"name":function(obj,_1d){
-obj.name=dojox.xml.parser.textContent(_1d);
-},"email":function(obj,_1e){
-obj.email=dojox.xml.parser.textContent(_1e);
-},"uri":function(obj,_1f){
-obj.uri=dojox.xml.parser.textContent(_1f);
-},"generator":function(obj,_20){
-obj.generator=new dojox.atom.io.model.Generator();
-obj.generator.buildFromDom(_20);
-}};
-dojox.atom.io.model.util={createDate:function(_21){
-var _22=dojox.xml.parser.textContent(_21);
-if(_22){
-return dojo.date.stamp.fromISOString(dojo.trim(_22));
-}
-return null;
-},escapeHtml:function(str){
-return str.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,""").replace(/'/gm,"'");
-},unEscapeHtml:function(str){
-return str.replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,"\"").replace(/'/gm,"'").replace(/&/gm,"&");
-},getNodename:function(_23){
-var _24=null;
-if(_23!==null){
-_24=_23.localName?_23.localName:_23.nodeName;
-if(_24!==null){
-var _25=_24.indexOf(":");
-if(_25!==-1){
-_24=_24.substring((_25+1),_24.length);
-}
-}
-}
-return _24;
-}};
-dojo.declare("dojox.atom.io.model.Node",null,{constructor:function(_26,_27,_28,_29,_2a){
-this.name_space=_26;
-this.name=_27;
-this.attributes=[];
-if(_28){
-this.attributes=_28;
-}
-this.content=[];
-this.rawNodes=[];
-this.textContent=null;
-if(_29){
-this.content.push(_29);
-}
-this.shortNs=_2a;
-this._objName="Node";
-},buildFromDom:function(_2b){
-this._saveAttributes(_2b);
-this.name_space=_2b.namespaceURI;
-this.shortNs=_2b.prefix;
-this.name=dojox.atom.io.model.util.getNodename(_2b);
-for(var x=0;x<_2b.childNodes.length;x++){
-var c=_2b.childNodes[x];
-if(dojox.atom.io.model.util.getNodename(c)!="#text"){
-this.rawNodes.push(c);
-var n=new dojox.atom.io.model.Node();
-n.buildFromDom(c,true);
-this.content.push(n);
-}else{
-this.content.push(c.nodeValue);
-}
-}
-this.textContent=dojox.xml.parser.textContent(_2b);
-},_saveAttributes:function(_2c){
-if(!this.attributes){
-this.attributes=[];
-}
-var _2d=function(_2e){
-var _2f=_2e.attributes;
-if(_2f===null){
-return false;
-}
-return (_2f.length!==0);
+
+dojox.atom.io.model._Constants = {
+	//	summary: 
+	//		Container for general constants.
+	//	description: 
+	//		Container for general constants.
+	"ATOM_URI": "http://www.w3.org/2005/Atom",
+	"ATOM_NS": "http://www.w3.org/2005/Atom",
+	"PURL_NS": "http://purl.org/atom/app#",
+	"APP_NS": "http://www.w3.org/2007/app"
+};
+
+dojox.atom.io.model._actions = {
+	//	summary: 
+	//		Container for tag handling functions.
+	//	description: 
+	//		Container for tag handling functions.  Each child of this container is
+	//		a handler function for the given type of node. Each accepts two parameters:
+	//	obj:  Object.
+	//		  The object to insert data into.
+	//	node: DOM Node.
+	//		  The dom node containing the data
+	"link": function(obj,node){
+		if(obj.links === null){obj.links = [];}
+		var link = new dojox.atom.io.model.Link();
+		link.buildFromDom(node);
+		obj.links.push(link);
+	},
+	"author": function(obj,node){
+		if(obj.authors === null){obj.authors = [];}
+		var person = new dojox.atom.io.model.Person("author");
+		person.buildFromDom(node);
+		obj.authors.push(person);
+	},
+	"contributor": function(obj,node){
+		if(obj.contributors === null){obj.contributors = [];}
+		var person = new dojox.atom.io.model.Person("contributor");
+		person.buildFromDom(node);
+		obj.contributors.push(person);
+	},
+	"category": function(obj,node){
+		if(obj.categories === null){obj.categories = [];}
+		var cat = new dojox.atom.io.model.Category();
+		cat.buildFromDom(node);
+		obj.categories.push(cat);
+	},
+	"icon": function(obj,node){
+		obj.icon = dojox.xml.parser.textContent(node);
+	},
+	"id": function(obj,node){
+		obj.id = dojox.xml.parser.textContent(node);
+	},
+	"rights": function(obj,node){
+		obj.rights = dojox.xml.parser.textContent(node);
+	},
+	"subtitle": function(obj,node){
+		var cnt = new dojox.atom.io.model.Content("subtitle");
+		cnt.buildFromDom(node);
+		obj.subtitle = cnt;
+	},
+	"title": function(obj,node){
+		var cnt = new dojox.atom.io.model.Content("title");
+		cnt.buildFromDom(node);
+		obj.title = cnt;
+	},
+	"updated": function(obj,node){
+		obj.updated = dojox.atom.io.model.util.createDate(node);
+	},
+	// Google news
+	"issued": function(obj,node){
+		obj.issued = dojox.atom.io.model.util.createDate(node);
+	},
+	// Google news
+	"modified": function(obj,node){
+		obj.modified = dojox.atom.io.model.util.createDate(node);
+	},
+	"published": function(obj,node){
+		obj.published = dojox.atom.io.model.util.createDate(node);	  
+	},
+	"entry": function(obj,node){
+		if(obj.entries === null){obj.entries = [];}
+		//The object passed in should be a Feed object, since only feeds can contain Entries
+		var entry = obj.createEntry ? obj.createEntry() : new dojox.atom.io.model.Entry();
+		entry.buildFromDom(node);
+		obj.entries.push(entry);	
+	}, 
+	"content": function(obj, node){
+		var cnt = new dojox.atom.io.model.Content("content");
+		cnt.buildFromDom(node);
+		obj.content = cnt;
+	}, 
+	"summary": function(obj, node){
+		var summary = new dojox.atom.io.model.Content("summary");
+		summary.buildFromDom(node);
+		obj.summary = summary;
+	}, 
+
+	"name": function(obj,node){
+		obj.name = dojox.xml.parser.textContent(node);
+	},
+	"email" : function(obj,node){
+		obj.email = dojox.xml.parser.textContent(node);
+	},
+	"uri" : function(obj,node){
+		obj.uri = dojox.xml.parser.textContent(node);
+	},
+	"generator" : function(obj,node){
+		obj.generator = new dojox.atom.io.model.Generator();
+		obj.generator.buildFromDom(node);
+	}
+};
+
+dojox.atom.io.model.util = {
+	createDate: function(/*DOM node*/node){
+		//	summary: 
+		//		Utility function to create a date from a DOM node's text content.
+		//	description: 
+		//		Utility function to create a date from a DOM node's text content.
+		//
+		//	node: 
+		//		The DOM node to inspect.
+		//	returns: 
+		//		Date object from a DOM Node containing a ISO-8610 string.
+		var textContent = dojox.xml.parser.textContent(node);
+		if(textContent){
+			return dojo.date.stamp.fromISOString(dojo.trim(textContent));
+		}
+		return null;
+	},
+	escapeHtml: function(/*String*/str){
+		//	summary: 
+		//		Utility function to escape XML special characters in an HTML string.
+		//	description: 
+		//		Utility function to escape XML special characters in an HTML string.
+		//
+		//	str: 
+		//		The string to escape
+		//	returns: 
+		//		HTML String with special characters (<,>,&, ", etc,) escaped.
+		return str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """)
+			.replace(/'/gm, "'"); // String
+	},
+	unEscapeHtml: function(/*String*/str){
+		//	summary: 
+		//		Utility function to un-escape XML special characters in an HTML string.
+		//	description: 
+		//		Utility function to un-escape XML special characters in an HTML string.
+		//
+		//	str: 
+		//		The string to un-escape.
+		//	returns: 
+		//		HTML String converted back to the normal text (unescaped) characters (<,>,&, ", etc,).
+		return str.replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, "\"")
+			.replace(/'/gm, "'").replace(/&/gm, "&"); // String
+	},
+	getNodename: function(/*DOM node*/node){
+		//	summary: 
+		//		Utility function to get a node name and deal with IE's bad handling of namespaces
+		//		on tag names.
+		//	description: 
+		//		Utility function to get a node name and deal with IE's bad handling of namespaces
+		//		on tag names.
+		//
+		//	node: 
+		//		The DOM node whose name to retrieve.
+		//	returns: 
+		//		String
+		//	The name without namespace prefixes.
+		var name = null;
+		if(node !== null){
+			name = node.localName ? node.localName: node.nodeName;
+			if(name !== null){
+				var nsSep = name.indexOf(":");
+				if(nsSep !== -1){
+					name = name.substring((nsSep + 1), name.length);
+				}
+			}
+		}
+		return name;
+	}
 };
-if(_2d(_2c)&&this._getAttributeNames){
-var _30=this._getAttributeNames(_2c);
-if(_30&&_30.length>0){
-for(var x in _30){
-var _31=_2c.getAttribute(_30[x]);
-if(_31){
-this.attributes[_30[x]]=_31;
-}
-}
-}
-}
-},addAttribute:function(_32,_33){
-this.attributes[_32]=_33;
-},getAttribute:function(_34){
-return this.attributes[_34];
-},_getAttributeNames:function(_35){
-var _36=[];
-for(var i=0;i<_35.attributes.length;i++){
-_36.push(_35.attributes[i].nodeName);
-}
-return _36;
-},toString:function(){
-var xml=[];
-var x;
-var _37=(this.shortNs?this.shortNs+":":"")+this.name;
-var _38=(this.name=="#cdata-section");
-if(_38){
-xml.push("<![CDATA[");
-xml.push(this.textContent);
-xml.push("]]>");
-}else{
-xml.push("<");
-xml.push(_37);
-if(this.name_space){
-xml.push(" xmlns='"+this.name_space+"'");
-}
-if(this.attributes){
-for(x in this.attributes){
-xml.push(" "+x+"='"+this.attributes[x]+"'");
-}
-}
-if(this.content){
-xml.push(">");
-for(x in this.content){
-xml.push(this.content[x]);
-}
-xml.push("</"+_37+">\n");
-}else{
-xml.push("/>\n");
-}
-}
-return xml.join("");
-},addContent:function(_39){
-this.content.push(_39);
-}});
-dojo.declare("dojox.atom.io.model.AtomItem",dojox.atom.io.model.Node,{constructor:function(_3a){
-this.ATOM_URI=dojox.atom.io.model._Constants.ATOM_URI;
-this.links=null;
-this.authors=null;
-this.categories=null;
-this.contributors=null;
-this.icon=this.id=this.logo=this.xmlBase=this.rights=null;
-this.subtitle=this.title=null;
-this.updated=this.published=null;
-this.issued=this.modified=null;
-this.content=null;
-this.extensions=null;
-this.entries=null;
-this.name_spaces={};
-this._objName="AtomItem";
-},_getAttributeNames:function(){
-return null;
-},_accepts:{},accept:function(tag){
-return Boolean(this._accepts[tag]);
-},_postBuild:function(){
-},buildFromDom:function(_3b){
-var i,c,n;
-for(i=0;i<_3b.attributes.length;i++){
-c=_3b.attributes.item(i);
-n=dojox.atom.io.model.util.getNodename(c);
-if(c.prefix=="xmlns"&&c.prefix!=n){
-this.addNamespace(c.nodeValue,n);
-}
-}
-c=_3b.childNodes;
-for(i=0;i<c.length;i++){
-if(c[i].nodeType==1){
-var _3c=dojox.atom.io.model.util.getNodename(c[i]);
-if(!_3c){
-continue;
-}
-if(c[i].namespaceURI!=dojox.atom.io.model._Constants.ATOM_NS&&_3c!="#text"){
-if(!this.extensions){
-this.extensions=[];
-}
-var _3d=new dojox.atom.io.model.Node();
-_3d.buildFromDom(c[i]);
-this.extensions.push(_3d);
-}
-if(!this.accept(_3c.toLowerCase())){
-continue;
-}
-var fn=dojox.atom.io.model._actions[_3c];
-if(fn){
-fn(this,c[i]);
-}
-}
-}
-this._saveAttributes(_3b);
-if(this._postBuild){
-this._postBuild();
-}
-},addNamespace:function(_3e,_3f){
-if(_3e&&_3f){
-this.name_spaces[_3f]=_3e;
-}
-},addAuthor:function(_40,_41,uri){
-if(!this.authors){
-this.authors=[];
-}
-this.authors.push(new dojox.atom.io.model.Person("author",_40,_41,uri));
-},addContributor:function(_42,_43,uri){
-if(!this.contributors){
-this.contributors=[];
-}
-this.contributors.push(new dojox.atom.io.model.Person("contributor",_42,_43,uri));
-},addLink:function(_44,rel,_45,_46,_47){
-if(!this.links){
-this.links=[];
-}
-this.links.push(new dojox.atom.io.model.Link(_44,rel,_45,_46,_47));
-},removeLink:function(_48,rel){
-if(!this.links||!dojo.isArray(this.links)){
-return;
-}
-var _49=0;
-for(var i=0;i<this.links.length;i++){
-if((!_48||this.links[i].href===_48)&&(!rel||this.links[i].rel===rel)){
-this.links.splice(i,1);
-_49++;
-}
-}
-return _49;
-},removeBasicLinks:function(){
-if(!this.links){
-return;
-}
-var _4a=0;
-for(var i=0;i<this.links.length;i++){
-if(!this.links[i].rel){
-this.links.splice(i,1);
-_4a++;
-i--;
-}
-}
-return _4a;
-},addCategory:function(_4b,_4c,_4d){
-if(!this.categories){
-this.categories=[];
-}
-this.categories.push(new dojox.atom.io.model.Category(_4b,_4c,_4d));
-},getCategories:function(_4e){
-if(!_4e){
-return this.categories;
-}
-var arr=[];
-for(var x in this.categories){
-if(this.categories[x].scheme===_4e){
-arr.push(this.categories[x]);
-}
-}
-return arr;
-},removeCategories:function(_4f,_50){
-if(!this.categories){
-return;
-}
-var _51=0;
-for(var i=0;i<this.categories.length;i++){
-if((!_4f||this.categories[i].scheme===_4f)&&(!_50||this.categories[i].term===_50)){
-this.categories.splice(i,1);
-_51++;
-i--;
-}
-}
-return _51;
-},setTitle:function(str,_52){
-if(!str){
-return;
-}
-this.title=new dojox.atom.io.model.Content("title");
-this.title.value=str;
-if(_52){
-this.title.type=_52;
-}
-},addExtension:function(_53,_54,_55,_56,_57){
-if(!this.extensions){
-this.extensions=[];
-}
-this.extensions.push(new dojox.atom.io.model.Node(_53,_54,_55,_56,_57||"ns"+this.extensions.length));
-},getExtensions:function(_58,_59){
-var arr=[];
-if(!this.extensions){
-return arr;
-}
-for(var x in this.extensions){
-if((this.extensions[x].name_space===_58||this.extensions[x].shortNs===_58)&&(!_59||this.extensions[x].name===_59)){
-arr.push(this.extensions[x]);
-}
-}
-return arr;
-},removeExtensions:function(_5a,_5b){
-if(!this.extensions){
-return;
-}
-for(var i=0;i<this.extensions.length;i++){
-if((this.extensions[i].name_space==_5a||this.extensions[i].shortNs===_5a)&&this.extensions[i].name===_5b){
-this.extensions.splice(i,1);
-i--;
-}
-}
-},destroy:function(){
-this.links=null;
-this.authors=null;
-this.categories=null;
-this.contributors=null;
-this.icon=this.id=this.logo=this.xmlBase=this.rights=null;
-this.subtitle=this.title=null;
-this.updated=this.published=null;
-this.issued=this.modified=null;
-this.content=null;
-this.extensions=null;
-this.entries=null;
-}});
-dojo.declare("dojox.atom.io.model.Category",dojox.atom.io.model.Node,{constructor:function(_5c,_5d,_5e){
-this.scheme=_5c;
-this.term=_5d;
-this.label=_5e;
-this._objName="Category";
-},_postBuild:function(){
-},_getAttributeNames:function(){
-return ["label","scheme","term"];
-},toString:function(){
-var s=[];
-s.push("<category ");
-if(this.label){
-s.push(" label=\""+this.label+"\" ");
-}
-if(this.scheme){
-s.push(" scheme=\""+this.scheme+"\" ");
-}
-if(this.term){
-s.push(" term=\""+this.term+"\" ");
-}
-s.push("/>\n");
-return s.join("");
-},buildFromDom:function(_5f){
-this._saveAttributes(_5f);
-this.label=this.attributes.label;
-this.scheme=this.attributes.scheme;
-this.term=this.attributes.term;
-if(this._postBuild){
-this._postBuild();
-}
-}});
-dojo.declare("dojox.atom.io.model.Content",dojox.atom.io.model.Node,{constructor:function(_60,_61,src,_62,_63){
-this.tagName=_60;
-this.value=_61;
-this.src=src;
-this.type=_62;
-this.xmlLang=_63;
-this.HTML="html";
-this.TEXT="text";
-this.XHTML="xhtml";
-this.XML="xml";
-this._useTextContent="true";
-},_getAttributeNames:function(){
-return ["type","src"];
-},_postBuild:function(){
-},buildFromDom:function(_64){
-var _65=_64.getAttribute("type");
-if(_65){
-_65=_65.toLowerCase();
-if(_65=="xml"||"text/xml"){
-_65=this.XML;
-}
-}else{
-_65="text";
-}
-if(_65===this.XML){
-if(_64.firstChild){
-var i;
-this.value="";
-for(i=0;i<_64.childNodes.length;i++){
-var c=_64.childNodes[i];
-if(c){
-this.value+=dojox.xml.parser.innerXML(c);
-}
-}
-}
-}else{
-if(_64.innerHTML){
-this.value=_64.innerHTML;
-}else{
-this.value=dojox.xml.parser.textContent(_64);
-}
-}
-this._saveAttributes(_64);
-if(this.attributes){
-this.type=this.attributes.type;
-this.scheme=this.attributes.scheme;
-this.term=this.attributes.term;
-}
-if(!this.type){
-this.type="text";
-}
-var _66=this.type.toLowerCase();
-if(_66==="html"||_66==="text/html"||_66==="xhtml"||_66==="text/xhtml"){
-this.value=dojox.atom.io.model.util.unEscapeHtml(this.value);
-}
-if(this._postBuild){
-this._postBuild();
-}
-},toString:function(){
-var s=[];
-s.push("<"+this.tagName+" ");
-if(!this.type){
-this.type="text";
-}
-if(this.type){
-s.push(" type=\""+this.type+"\" ");
-}
-if(this.xmlLang){
-s.push(" xml:lang=\""+this.xmlLang+"\" ");
-}
-if(this.xmlBase){
-s.push(" xml:base=\""+this.xmlBase+"\" ");
-}
-if(this.type.toLowerCase()==this.HTML){
-s.push(">"+dojox.atom.io.model.util.escapeHtml(this.value)+"</"+this.tagName+">\n");
-}else{
-s.push(">"+this.value+"</"+this.tagName+">\n");
-}
-var ret=s.join("");
-return ret;
-}});
-dojo.declare("dojox.atom.io.model.Link",dojox.atom.io.model.Node,{constructor:function(_67,rel,_68,_69,_6a){
-this.href=_67;
-this.hrefLang=_68;
-this.rel=rel;
-this.title=_69;
-this.type=_6a;
-},_getAttributeNames:function(){
-return ["href","jrefLang","rel","title","type"];
-},_postBuild:function(){
-},buildFromDom:function(_6b){
-this._saveAttributes(_6b);
-this.href=this.attributes.href;
-this.hrefLang=this.attributes.hreflang;
-this.rel=this.attributes.rel;
-this.title=this.attributes.title;
-this.type=this.attributes.type;
-if(this._postBuild){
-this._postBuild();
-}
-},toString:function(){
-var s=[];
-s.push("<link ");
-if(this.href){
-s.push(" href=\""+this.href+"\" ");
-}
-if(this.hrefLang){
-s.push(" hrefLang=\""+this.hrefLang+"\" ");
-}
-if(this.rel){
-s.push(" rel=\""+this.rel+"\" ");
-}
-if(this.title){
-s.push(" title=\""+this.title+"\" ");
-}
-if(this.type){
-s.push(" type = \""+this.type+"\" ");
-}
-s.push("/>\n");
-return s.join("");
-}});
-dojo.declare("dojox.atom.io.model.Person",dojox.atom.io.model.Node,{constructor:function(_6c,_6d,_6e,uri){
-this.author="author";
-this.contributor="contributor";
-if(!_6c){
-_6c=this.author;
-}
-this.personType=_6c;
-this.name=_6d||"";
-this.email=_6e||"";
-this.uri=uri||"";
-this._objName="Person";
-},_getAttributeNames:function(){
-return null;
-},_postBuild:function(){
-},accept:function(tag){
-return Boolean(this._accepts[tag]);
-},buildFromDom:function(_6f){
-var c=_6f.childNodes;
-for(var i=0;i<c.length;i++){
-var _70=dojox.atom.io.model.util.getNodename(c[i]);
-if(!_70){
-continue;
-}
-if(c[i].namespaceURI!=dojox.atom.io.model._Constants.ATOM_NS&&_70!="#text"){
-if(!this.extensions){
-this.extensions=[];
-}
-var _71=new dojox.atom.io.model.Node();
-_71.buildFromDom(c[i]);
-this.extensions.push(_71);
-}
-if(!this.accept(_70.toLowerCase())){
-continue;
-}
-var fn=dojox.atom.io.model._actions[_70];
-if(fn){
-fn(this,c[i]);
-}
-}
-this._saveAttributes(_6f);
-if(this._postBuild){
-this._postBuild();
-}
-},_accepts:{"name":true,"uri":true,"email":true},toString:function(){
-var s=[];
-s.push("<"+this.personType+">\n");
-if(this.name){
-s.push("\t<name>"+this.name+"</name>\n");
-}
-if(this.email){
-s.push("\t<email>"+this.email+"</email>\n");
-}
-if(this.uri){
-s.push("\t<uri>"+this.uri+"</uri>\n");
-}
-s.push("</"+this.personType+">\n");
-return s.join("");
-}});
-dojo.declare("dojox.atom.io.model.Generator",dojox.atom.io.model.Node,{constructor:function(uri,_72,_73){
-this.uri=uri;
-this.version=_72;
-this.value=_73;
-},_postBuild:function(){
-},buildFromDom:function(_74){
-this.value=dojox.xml.parser.textContent(_74);
-this._saveAttributes(_74);
-this.uri=this.attributes.uri;
-this.version=this.attributes.version;
-if(this._postBuild){
-this._postBuild();
-}
-},toString:function(){
-var s=[];
-s.push("<generator ");
-if(this.uri){
-s.push(" uri=\""+this.uri+"\" ");
-}
-if(this.version){
-s.push(" version=\""+this.version+"\" ");
-}
-s.push(">"+this.value+"</generator>\n");
-var ret=s.join("");
-return ret;
-}});
-dojo.declare("dojox.atom.io.model.Entry",dojox.atom.io.model.AtomItem,{constructor:function(id){
-this.id=id;
-this._objName="Entry";
-this.feedUrl=null;
-},_getAttributeNames:function(){
-return null;
-},_accepts:{"author":true,"content":true,"category":true,"contributor":true,"created":true,"id":true,"link":true,"published":true,"rights":true,"summary":true,"title":true,"updated":true,"xmlbase":true,"issued":true,"modified":true},toString:function(_75){
-var s=[];
-var i;
-if(_75){
-s.push("<?xml version='1.0' encoding='UTF-8'?>");
-s.push("<entry xmlns='"+dojox.atom.io.model._Constants.ATOM_URI+"'");
-}else{
-s.push("<entry");
-}
-if(this.xmlBase){
-s.push(" xml:base=\""+this.xmlBase+"\" ");
-}
-for(i in this.name_spaces){
-s.push(" xmlns:"+i+"=\""+this.name_spaces[i]+"\"");
-}
-s.push(">\n");
-s.push("<id>"+(this.id?this.id:"")+"</id>\n");
-if(this.issued&&!this.published){
-this.published=this.issued;
-}
-if(this.published){
-s.push("<published>"+dojo.date.stamp.toISOString(this.published)+"</published>\n");
-}
-if(this.created){
-s.push("<created>"+dojo.date.stamp.toISOString(this.created)+"</created>\n");
-}
-if(this.issued){
-s.push("<issued>"+dojo.date.stamp.toISOString(this.issued)+"</issued>\n");
-}
-if(this.modified){
-s.push("<modified>"+dojo.date.stamp.toISOString(this.modified)+"</modified>\n");
-}
-if(this.modified&&!this.updated){
-this.updated=this.modified;
-}
-if(this.updated){
-s.push("<updated>"+dojo.date.stamp.toISOString(this.updated)+"</updated>\n");
-}
-if(this.rights){
-s.push("<rights>"+this.rights+"</rights>\n");
-}
-if(this.title){
-s.push(this.title.toString());
-}
-if(this.summary){
-s.push(this.summary.toString());
-}
-var _76=[this.authors,this.categories,this.links,this.contributors,this.extensions];
-for(var x in _76){
-if(_76[x]){
-for(var y in _76[x]){
-s.push(_76[x][y]);
-}
-}
-}
-if(this.content){
-s.push(this.content.toString());
-}
-s.push("</entry>\n");
-return s.join("");
-},getEditHref:function(){
-if(this.links===null||this.links.length===0){
-return null;
-}
-for(var x in this.links){
-if(this.links[x].rel&&this.links[x].rel=="edit"){
-return this.links[x].href;
-}
-}
-return null;
-},setEditHref:function(url){
-if(this.links===null){
-this.links=[];
-}
-for(var x in this.links){
-if(this.links[x].rel&&this.links[x].rel=="edit"){
-this.links[x].href=url;
-return;
-}
-}
-this.addLink(url,"edit");
-}});
-dojo.declare("dojox.atom.io.model.Feed",dojox.atom.io.model.AtomItem,{_accepts:{"author":true,"content":true,"category":true,"contributor":true,"created":true,"id":true,"link":true,"published":true,"rights":true,"summary":true,"title":true,"updated":true,"xmlbase":true,"entry":true,"logo":true,"issued":true,"modified":true,"icon":true,"subtitle":true},addEntry:function(_77){
-if(!_77.id){
-throw new Error("The entry object must be assigned an ID attribute.");
-}
-if(!this.entries){
-this.entries=[];
-}
-_77.feedUrl=this.getSelfHref();
-this.entries.push(_77);
-},getFirstEntry:function(){
-if(!this.entries||this.entries.length===0){
-return null;
-}
-return this.entries[0];
-},getEntry:function(_78){
-if(!this.entries){
-return null;
-}
-for(var x in this.entries){
-if(this.entries[x].id==_78){
-return this.entries[x];
-}
-}
-return null;
-},removeEntry:function(_79){
-if(!this.entries){
-return;
-}
-var _7a=0;
-for(var i=0;i<this.entries.length;i++){
-if(this.entries[i]===_79){
-this.entries.splice(i,1);
-_7a++;
-}
-}
-return _7a;
-},setEntries:function(_7b){
-for(var x in _7b){
-this.addEntry(_7b[x]);
-}
-},toString:function(){
-var s=[];
-var i;
-s.push("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
-s.push("<feed xmlns=\""+dojox.atom.io.model._Constants.ATOM_URI+"\"");
-if(this.xmlBase){
-s.push(" xml:base=\""+this.xmlBase+"\"");
-}
-for(i in this.name_spaces){
-s.push(" xmlns:"+i+"=\""+this.name_spaces[i]+"\"");
-}
-s.push(">\n");
-s.push("<id>"+(this.id?this.id:"")+"</id>\n");
-if(this.title){
-s.push(this.title);
-}
-if(this.copyright&&!this.rights){
-this.rights=this.copyright;
-}
-if(this.rights){
-s.push("<rights>"+this.rights+"</rights>\n");
-}
-if(this.issued){
-s.push("<issued>"+dojo.date.stamp.toISOString(this.issued)+"</issued>\n");
-}
-if(this.modified){
-s.push("<modified>"+dojo.date.stamp.toISOString(this.modified)+"</modified>\n");
-}
-if(this.modified&&!this.updated){
-this.updated=this.modified;
-}
-if(this.updated){
-s.push("<updated>"+dojo.date.stamp.toISOString(this.updated)+"</updated>\n");
-}
-if(this.published){
-s.push("<published>"+dojo.date.stamp.toISOString(this.published)+"</published>\n");
-}
-if(this.icon){
-s.push("<icon>"+this.icon+"</icon>\n");
-}
-if(this.language){
-s.push("<language>"+this.language+"</language>\n");
-}
-if(this.logo){
-s.push("<logo>"+this.logo+"</logo>\n");
-}
-if(this.subtitle){
-s.push(this.subtitle.toString());
-}
-if(this.tagline){
-s.push(this.tagline.toString());
-}
-var _7c=[this.alternateLinks,this.authors,this.categories,this.contributors,this.otherLinks,this.extensions,this.entries];
-for(i in _7c){
-if(_7c[i]){
-for(var x in _7c[i]){
-s.push(_7c[i][x]);
-}
-}
-}
-s.push("</feed>");
-return s.join("");
-},createEntry:function(){
-var _7d=new dojox.atom.io.model.Entry();
-_7d.feedUrl=this.getSelfHref();
-return _7d;
-},getSelfHref:function(){
-if(this.links===null||this.links.length===0){
-return null;
-}
-for(var x in this.links){
-if(this.links[x].rel&&this.links[x].rel=="self"){
-return this.links[x].href;
-}
-}
-return null;
-}});
-dojo.declare("dojox.atom.io.model.Service",dojox.atom.io.model.AtomItem,{constructor:function(_7e){
-this.href=_7e;
-},buildFromDom:function(_7f){
-var i;
-this.workspaces=[];
-if(_7f.tagName!="service"){
-return;
-}
-if(_7f.namespaceURI!=dojox.atom.io.model._Constants.PURL_NS&&_7f.namespaceURI!=dojox.atom.io.model._Constants.APP_NS){
-return;
-}
-var ns=_7f.namespaceURI;
-this.name_space=_7f.namespaceURI;
-var _80;
-if(typeof (_7f.getElementsByTagNameNS)!="undefined"){
-_80=_7f.getElementsByTagNameNS(ns,"workspace");
-}else{
-_80=[];
-var _81=_7f.getElementsByTagName("workspace");
-for(i=0;i<_81.length;i++){
-if(_81[i].namespaceURI==ns){
-_80.push(_81[i]);
-}
-}
-}
-if(_80&&_80.length>0){
-var _82=0;
-var _83;
-for(i=0;i<_80.length;i++){
-_83=(typeof (_80.item)==="undefined"?_80[i]:_80.item(i));
-var _84=new dojox.atom.io.model.Workspace();
-_84.buildFromDom(_83);
-this.workspaces[_82++]=_84;
-}
-}
-},getCollection:function(url){
-for(var i=0;i<this.workspaces.length;i++){
-var _85=this.workspaces[i].collections;
-for(var j=0;j<_85.length;j++){
-if(_85[j].href==url){
-return _85;
-}
-}
-}
-return null;
-}});
-dojo.declare("dojox.atom.io.model.Workspace",dojox.atom.io.model.AtomItem,{constructor:function(_86){
-this.title=_86;
-this.collections=[];
-},buildFromDom:function(_87){
-var _88=dojox.atom.io.model.util.getNodename(_87);
-if(_88!="workspace"){
-return;
-}
-var c=_87.childNodes;
-var len=0;
-for(var i=0;i<c.length;i++){
-var _89=c[i];
-if(_89.nodeType===1){
-_88=dojox.atom.io.model.util.getNodename(_89);
-if(_89.namespaceURI==dojox.atom.io.model._Constants.PURL_NS||_89.namespaceURI==dojox.atom.io.model._Constants.APP_NS){
-if(_88==="collection"){
-var _8a=new dojox.atom.io.model.Collection();
-_8a.buildFromDom(_89);
-this.collections[len++]=_8a;
-}
-}else{
-if(_89.namespaceURI===dojox.atom.io.model._Constants.ATOM_NS){
-if(_88==="title"){
-this.title=dojox.xml.parser.textContent(_89);
-}
-}
-}
-}
-}
-}});
-dojo.declare("dojox.atom.io.model.Collection",dojox.atom.io.model.AtomItem,{constructor:function(_8b,_8c){
-this.href=_8b;
-this.title=_8c;
-this.attributes=[];
-this.features=[];
-this.children=[];
-this.memberType=null;
-this.id=null;
-},buildFromDom:function(_8d){
-this.href=_8d.getAttribute("href");
-var c=_8d.childNodes;
-for(var i=0;i<c.length;i++){
-var _8e=c[i];
-if(_8e.nodeType===1){
-var _8f=dojox.atom.io.model.util.getNodename(_8e);
-if(_8e.namespaceURI==dojox.atom.io.model._Constants.PURL_NS||_8e.namespaceURI==dojox.atom.io.model._Constants.APP_NS){
-if(_8f==="member-type"){
-this.memberType=dojox.xml.parser.textContent(_8e);
-}else{
-if(_8f=="feature"){
-if(_8e.getAttribute("id")){
-this.features.push(_8e.getAttribute("id"));
-}
-}else{
-var _90=new dojox.atom.io.model.Node();
-_90.buildFromDom(_8e);
-this.children.push(_90);
-}
-}
-}else{
-if(_8e.namespaceURI===dojox.atom.io.model._Constants.ATOM_NS){
-if(_8f==="id"){
-this.id=dojox.xml.parser.textContent(_8e);
-}else{
-if(_8f==="title"){
-this.title=dojox.xml.parser.textContent(_8e);
-}
-}
-}
-}
-}
-}
-}});
-}
+
+dojo.declare('dojox.atom.io.model.Node', null, {
+	constructor: function(name_space,name, attributes,content, shortNs){
+		this.name_space = name_space;
+		this.name = name;
+		this.attributes = [];
+		if(attributes){
+			this.attributes = attributes;
+		}
+		this.content = [];
+		this.rawNodes = [];
+		this.textContent = null;
+		if(content){
+			this.content.push(content);
+		}
+		this.shortNs = shortNs;
+		this._objName = "Node";//for debugging purposes
+	},
+	buildFromDom: function(node){
+		this._saveAttributes(node);
+		this.name_space = node.namespaceURI;
+		this.shortNs = node.prefix;
+		this.name = dojox.atom.io.model.util.getNodename(node);
+		for(var x=0; x < node.childNodes.length; x++){
+			var c = node.childNodes[x];
+			if(dojox.atom.io.model.util.getNodename(c) != "#text" ){
+				this.rawNodes.push(c);
+				var n = new dojox.atom.io.model.Node();
+				n.buildFromDom(c, true);
+				this.content.push(n);
+			}else{
+				this.content.push(c.nodeValue);
+			}
+		}
+		this.textContent = dojox.xml.parser.textContent(node);
+	},
+	_saveAttributes: function(node){
+		if(!this.attributes){this.attributes = [];}
+		// Work around lack of hasAttributes() in IE
+		var hasAttributes = function(node){
+			var attrs = node.attributes;
+			if(attrs === null){return false;}
+			return (attrs.length !== 0);
+		};
+	
+		if(hasAttributes(node) && this._getAttributeNames){
+			var names = this._getAttributeNames(node);
+			if(names && names.length > 0){
+				for(var x in names){
+					var attrib = node.getAttribute(names[x]);
+					if(attrib){this.attributes[names[x]] = attrib;}
+				}
+			}
+		}
+	},
+	addAttribute: function(name, value){
+		this.attributes[name]=value;
+	},
+	getAttribute: function(name){
+		return this.attributes[name];
+	},
+	//if child objects want their attributes parsed, they should override
+	//to return an array of attrib names
+	_getAttributeNames: function(node){
+		var names = [];
+		for(var i =0; i<node.attributes.length; i++){
+			names.push(node.attributes[i].nodeName);
+		}
+		return names;
+	},
+	toString: function(){
+		var xml = [];
+		var x;
+		var name = (this.shortNs?this.shortNs+":":'')+this.name;
+		var cdata = (this.name == "#cdata-section");
+		if(cdata){ 
+			xml.push("<![CDATA[");
+			xml.push(this.textContent);
+			xml.push("]]>");
+		}else{
+			xml.push("<");
+			xml.push(name);
+			if(this.name_space){
+				xml.push(" xmlns='" + this.name_space + "'");
+			}
+			if(this.attributes){
+				for(x in this.attributes){
+					xml.push(" " + x + "='" + this.attributes[x] + "'");
+				}
+			}
+			if(this.content){
+				xml.push(">");
+				for(x in this.content){ 
+					xml.push(this.content[x]);
+				}
+				xml.push("</" + name + ">\n");
+			}else{
+				xml.push("/>\n");
+			}
+		}
+		return xml.join('');
+	},
+	addContent: function(content){
+		this.content.push(content);
+	}
+});
+//Types are as follows: links: array of Link, authors: array of Person, categories: array of Category
+//contributors: array of Person, ico
+dojo.declare("dojox.atom.io.model.AtomItem",dojox.atom.io.model.Node,{
+	 constructor: function(args){
+		this.ATOM_URI = dojox.atom.io.model._Constants.ATOM_URI;
+		this.links = null;						//Array of Link
+		this.authors = null;					//Array of Person
+		this.categories = null;					//Array of Category
+		this.contributors = null;				//Array of Person   
+		this.icon = this.id = this.logo = this.xmlBase = this.rights = null; //String
+		this.subtitle = this.title = null;		//Content
+		this.updated = this.published = null;	//Date
+		// Google news
+		this.issued = this.modified = null;		//Date
+		this.content =  null;					//Content
+		this.extensions = null;					//Array of Node, non atom based
+		this.entries = null;					//Array of Entry
+		this.name_spaces = {};
+		this._objName = "AtomItem";			 //for debugging purposes
+	},
+	// summary: Class container for generic Atom items.
+	// description: Class container for generic Atom items.
+	_getAttributeNames: function(){return null;},
+	_accepts: {},
+	accept: function(tag){return Boolean(this._accepts[tag]);},
+	_postBuild: function(){},//child objects can override this if they want to be called after a Dom build
+	buildFromDom: function(node){
+		var i, c, n;
+		for(i=0; i<node.attributes.length; i++){
+			c = node.attributes.item(i);
+			n = dojox.atom.io.model.util.getNodename(c);
+			if(c.prefix == "xmlns" && c.prefix != n){
+				this.addNamespace(c.nodeValue, n);
+			}
+		}
+		c = node.childNodes;
+		for(i = 0; i< c.length; i++){
+			if(c[i].nodeType == 1) {
+				var name = dojox.atom.io.model.util.getNodename(c[i]);
+				if(!name){continue;}
+				if(c[i].namespaceURI != dojox.atom.io.model._Constants.ATOM_NS && name != "#text"){
+					if(!this.extensions){this.extensions = [];}
+					var extensionNode = new dojox.atom.io.model.Node();
+					extensionNode.buildFromDom(c[i]);
+					this.extensions.push(extensionNode);
+				}
+				if(!this.accept(name.toLowerCase())){
+					continue;
+				}
+				var fn = dojox.atom.io.model._actions[name];
+				if(fn) {
+					fn(this,c[i]);
+				}
+			}
+		}
+		this._saveAttributes(node); 
+		if(this._postBuild){this._postBuild();}
+	},
+	addNamespace: function(fullName, shortName){
+		if(fullName && shortName){
+			this.name_spaces[shortName] = fullName;
+		}
+	},
+	addAuthor: function(/*String*/name, /*String*/email, /*String*/uri){
+		//	summary: 
+		//		Function to add in an author to the list of authors.
+		//	description: 
+		//		Function to add in an author to the list of authors.
+		//
+		//	name: 
+		//		The author's name.
+		//	email: 
+		//		The author's e-mail address.
+		//	uri: 
+		//		A URI associated with the author.
+		if(!this.authors){this.authors = [];}
+		this.authors.push(new dojox.atom.io.model.Person("author",name,email,uri));
+	},
+	addContributor: function(/*String*/name, /*String*/email, /*String*/uri){
+		//	summary: 
+		//		Function to add in an author to the list of authors.
+		//	description: 
+		//		Function to add in an author to the list of authors.
+		//
+		//	name: 
+		//		The author's name.
+		//	email: 
+		//		The author's e-mail address.
+		//	uri: 
+		//		A URI associated with the author.
+		if(!this.contributors){this.contributors = [];}
+		this.contributors.push(new dojox.atom.io.model.Person("contributor",name,email,uri));
+	},
+	addLink: function(/*String*/href,/*String*/rel,/*String*/hrefLang,/*String*/title,/*String*/type){
+		//	summary: 
+		//		Function to add in a link to the list of links.
+		//	description: 
+		//		Function to add in a link to the list of links.
+		//
+		//	href: 
+		//		The href.
+		//	rel: 
+		//		String
+		//	hrefLang: 
+		//		String
+		//	title: 
+		//		A title to associate with the link.
+		//	type: 
+		//		The type of link is is.
+		if(!this.links){this.links=[];}
+		this.links.push(new dojox.atom.io.model.Link(href,rel,hrefLang,title,type));
+	},
+	removeLink: function(/*String*/href, /*String*/rel){
+		//	summary: 
+		//		Function to remove a link from the list of links.
+		//	description: 
+		//		Function to remove a link from the list of links.
+		//
+		//	href: 
+		//		The href.
+		//	rel: 
+		//		String
+		if(!this.links || !dojo.isArray(this.links)){return;}
+		var count = 0;
+		for(var i = 0; i < this.links.length; i++){
+			if((!href || this.links[i].href === href) && (!rel || this.links[i].rel === rel)){
+				this.links.splice(i,1); count++;
+			}
+		}
+		return count;
+	},
+	removeBasicLinks: function(){
+		//	summary: 
+		//		Function to remove all basic links from the list of links.
+		//	description: 
+		//		Function to remove all basic link from the list of links.
+		if(!this.links){return;}
+		var count = 0;
+		for(var i = 0; i < this.links.length; i++){
+			if(!this.links[i].rel){this.links.splice(i,1); count++; i--;}
+		}
+		return count;
+	},
+	addCategory: function(/*String*/scheme, /*String*/term, /*String*/label){
+		//	summary: 
+		//		Function to add in a category to the list of categories.
+		//	description: 
+		//		Function to add in a category to the list of categories.
+		//
+		//	scheme: 
+		//		String
+		//	term: 
+		//		String
+		//	label: 
+		//		String
+		if(!this.categories){this.categories = [];}
+		this.categories.push(new dojox.atom.io.model.Category(scheme,term,label));
+	},
+	getCategories: function(/*String*/scheme){
+		//	summary: 
+		//		Function to get all categories that match a particular scheme.
+		//	description: 
+		//		Function to get all categories that match a particular scheme.
+		//
+		//	scheme: 
+		//		String
+		//		The scheme to filter on.
+		if(!scheme){return this.categories;}
+		//If categories belonging to a particular scheme are required, then create a new array containing these
+		var arr = [];
+		for(var x in this.categories){
+			if(this.categories[x].scheme === scheme){arr.push(this.categories[x]);}
+		}
+		return arr;
+	},
+	removeCategories: function(/*String*/scheme, /*String*/term){
+		//	summary: 
+		//		Function to remove all categories that match a particular scheme and term.
+		//	description: 
+		//		Function to remove all categories that match a particular scheme and term.
+		//
+		//	scheme: 
+		//		The scheme to filter on.
+		//	term: 
+		//		The term to filter on.
+		if(!this.categories){return;}
+		var count = 0;
+		for(var i=0; i<this.categories.length; i++){
+			if((!scheme || this.categories[i].scheme === scheme) && (!term || this.categories[i].term === term)){
+				this.categories.splice(i, 1); count++; i--;
+			}
+		}
+		return count;
+	},
+	setTitle: function(/*String*/str, /*String*/type){
+		//	summary: 
+		//		Function to set the title of the item.
+		//	description: 
+		//		Function to set the title of the item.
+		//
+		//	str: 
+		//		The title to set.
+		//	type: 
+		//		The type of title format, text, xml, xhtml, etc.
+		if(!str){return;}
+		this.title = new dojox.atom.io.model.Content("title");
+		this.title.value = str;
+		if(type){this.title.type = type;}
+	},
+	addExtension: function(/*String*/name_space,/*String*/name, /*Array*/attributes, /*String*/content, /*String*/shortNS){
+		//	summary: 
+		//		Function to add in an extension namespace into the item.
+		//	description: 
+		//		Function to add in an extension namespace into the item.
+		//
+		//	name_space: 
+		//		The namespace of the extension.
+		//	name: 
+		//		The name of the extension
+		//	attributes: 
+		//		The attributes associated with the extension.
+		//	content: 
+		//		The content of the extension.
+		if(!this.extensions){this.extensions=[];}
+		this.extensions.push(new dojox.atom.io.model.Node(name_space,name,attributes,content, shortNS || "ns"+this.extensions.length));
+	},
+	getExtensions: function(/*String*/name_space, /*String*/name){
+		//	summary: 
+		//		Function to get extensions that match a namespace and name.
+		//	description: 
+		//		Function to get extensions that match a namespace and name.
+		//
+		//	name_space: 
+		//		The namespace of the extension.
+		//	name: 
+		//		The name of the extension
+		var arr = [];
+		if(!this.extensions){return arr;}
+		for(var x in this.extensions){
+			if((this.extensions[x].name_space === name_space || this.extensions[x].shortNs === name_space) && (!name || this.extensions[x].name === name)){
+				arr.push(this.extensions[x]);
+			}
+		}
+		return arr;
+	},
+	removeExtensions: function(/*String*/name_space, /*String*/name){
+		//	summary: 
+		//		Function to remove extensions that match a namespace and name.
+		//	description: 
+		//		Function to remove extensions that match a namespace and name.
+		//
+		//	name_space: 
+		//		The namespace of the extension.
+		//	name: 
+		//		The name of the extension
+		if(!this.extensions){return;}
+		for(var i=0; i< this.extensions.length; i++){
+			if((this.extensions[i].name_space == name_space || this.extensions[i].shortNs === name_space) && this.extensions[i].name === name){
+				this.extensions.splice(i,1);
+				i--;
+			}
+		}
+	},
+	destroy: function() {
+		this.links = null;
+		this.authors = null;
+		this.categories = null;
+		this.contributors = null;
+		this.icon = this.id = this.logo = this.xmlBase = this.rights = null;
+		this.subtitle = this.title = null;
+		this.updated = this.published = null;
+		// Google news
+		this.issued = this.modified = null;
+		this.content =  null;
+		this.extensions = null;
+		this.entries = null;
+	}
+});
+
+dojo.declare("dojox.atom.io.model.Category",dojox.atom.io.model.Node,{
+	//	summary: 
+	//		Class container for 'Category' types. 
+	//	description: 
+	//		Class container for 'Category' types.
+	constructor: function(/*String*/scheme, /*String*/term, /*String*/label){
+		this.scheme = scheme; this.term = term; this.label = label;
+		this._objName = "Category";//for debugging
+	},
+	_postBuild: function(){},
+	_getAttributeNames: function(){
+		return ["label","scheme","term"];
+	},
+	toString: function(){
+		//	summary: 
+		//		Function to construct string form of the category tag, which is an XML structure.
+		//	description: 
+		//		Function to construct string form of the category tag, which is an XML structure.
+		var s = [];
+		s.push('<category ');
+		if(this.label){s.push(' label="'+this.label+'" ');}
+		if(this.scheme){s.push(' scheme="'+this.scheme+'" ');}
+		if(this.term){s.push(' term="'+this.term+'" ');}
+		s.push('/>\n');
+		return s.join('');
+	},
+	buildFromDom: function(/*DOM node*/node){
+		//	summary: 
+		//		Function to do construction of the Category data from the DOM node containing it.
+		//	description: 
+		//		Function to do construction of the Category data from the DOM node containing it.
+		//
+		//	node: 
+		//		The DOM node to process for content.
+		this._saveAttributes(node);//just get the attributes from the node
+		this.label = this.attributes.label;
+		this.scheme = this.attributes.scheme;
+		this.term = this.attributes.term;
+		if(this._postBuild){this._postBuild();}
+	}
+});
+
+dojo.declare("dojox.atom.io.model.Content",dojox.atom.io.model.Node,{
+	//	summary: 
+	//		Class container for 'Content' types. Such as summary, content, username, and so on types of data.
+	//	description: 
+	//		Class container for 'Content' types. Such as summary, content, username, and so on types of data.
+	constructor: function(tagName, value, src, type,xmlLang){
+		this.tagName = tagName; this.value = value; this.src = src; this.type=type; this.xmlLang = xmlLang;
+		this.HTML = "html"; this.TEXT = "text"; this.XHTML = "xhtml"; this.XML="xml";
+		this._useTextContent = "true";
+	},
+	_getAttributeNames: function(){return ["type","src"];},
+	_postBuild: function(){},
+	buildFromDom: function(/*DOM node*/node){
+		//	summary: 
+		//		Function to do construction of the Content data from the DOM node containing it.
+		//	description: 
+		//		Function to do construction of the Content data from the DOM node containing it.
+		//
+		//	node: 
+		//		The DOM node to process for content.
+		//Handle checking for XML content as the content type
+		var type = node.getAttribute("type");
+		if(type){
+			type = type.toLowerCase();
+			if(type == "xml" || "text/xml"){
+				type = this.XML;
+			}
+		}else{
+			type="text";
+		}
+		if(type === this.XML){
+			if(node.firstChild){
+				var i;
+				this.value = "";
+				for(i = 0; i < node.childNodes.length; i++){
+					var c = node.childNodes[i];
+					if(c){
+						this.value += dojox.xml.parser.innerXML(c);
+					}
+				}
+			}
+		} else if(node.innerHTML){
+			this.value = node.innerHTML;
+		}else{
+			this.value = dojox.xml.parser.textContent(node);
+		}
+
+		this._saveAttributes(node);
+
+		if(this.attributes){
+			this.type = this.attributes.type;
+			this.scheme = this.attributes.scheme;
+			this.term = this.attributes.term;
+		}
+		if(!this.type){this.type = "text";}
+
+		//We need to unescape the HTML content here so that it can be displayed correctly when the value is fetched.
+		var lowerType = this.type.toLowerCase();
+		if(lowerType === "html" || lowerType === "text/html" || lowerType === "xhtml" || lowerType === "text/xhtml"){
+			this.value = this.value?dojox.atom.io.model.util.unEscapeHtml(this.value):"";
+		}
+
+		if(this._postBuild){this._postBuild();}
+	},
+	toString: function(){
+		//	summary: 
+		//		Function to construct string form of the content tag, which is an XML structure.
+		//	description: 
+		//		Function to construct string form of the content tag, which is an XML structure.
+		var s = [];
+		s.push('<'+this.tagName+' ');
+		if(!this.type){this.type = "text";}
+		if(this.type){s.push(' type="'+this.type+'" ');}
+		if(this.xmlLang){s.push(' xml:lang="'+this.xmlLang+'" ');}
+		if(this.xmlBase){s.push(' xml:base="'+this.xmlBase+'" ');}
+		
+		//all HTML must be escaped
+		if(this.type.toLowerCase() == this.HTML){
+			s.push('>'+dojox.atom.io.model.util.escapeHtml(this.value)+'</'+this.tagName+'>\n');
+		}else{
+			s.push('>'+this.value+'</'+this.tagName+'>\n');
+		}
+		var ret = s.join('');
+		return ret;
+	}
+});
+
+dojo.declare("dojox.atom.io.model.Link",dojox.atom.io.model.Node,{
+	//	summary: 
+	//		Class container for 'link' types.
+	//	description: 
+	//		Class container for 'link' types.
+	constructor: function(href,rel,hrefLang,title,type){
+		this.href = href; this.hrefLang = hrefLang; this.rel = rel; this.title = title;this.type = type;
+	},
+	_getAttributeNames: function(){return ["href","jrefLang","rel","title","type"];},
+	_postBuild: function(){},
+	buildFromDom: function(node){
+		//	summary: 
+		//		Function to do construction of the link data from the DOM node containing it.
+		//	description: 
+		//		Function to do construction of the link data from the DOM node containing it.
+		//
+		//	node: 
+		//		The DOM node to process for link data.
+		this._saveAttributes(node);//just get the attributes from the node
+		this.href = this.attributes.href;
+		this.hrefLang = this.attributes.hreflang;
+		this.rel = this.attributes.rel;
+		this.title = this.attributes.title;
+		this.type = this.attributes.type;
+		if(this._postBuild){this._postBuild();}
+	},
+	toString: function(){
+		//	summary: 
+		//		Function to construct string form of the link tag, which is an XML structure.
+		//	description: 
+		//		Function to construct string form of the link tag, which is an XML structure.
+		var s = []; 
+		s.push('<link ');
+		if(this.href){s.push(' href="'+this.href+'" ');}
+		if(this.hrefLang){s.push(' hrefLang="'+this.hrefLang+'" ');}
+		if(this.rel){s.push(' rel="'+this.rel+'" ');}
+		if(this.title){s.push(' title="'+this.title+'" ');}
+		if(this.type){s.push(' type = "'+this.type+'" ');}
+		s.push('/>\n');
+		return s.join('');
+	}
+});
+
+dojo.declare("dojox.atom.io.model.Person",dojox.atom.io.model.Node,{
+	//	summary: 
+	//		Class container for 'person' types, such as Author, controbutors, and so on.
+	//	description: 
+	//		Class container for 'person' types, such as Author, controbutors, and so on.
+	constructor: function(personType, name, email, uri){
+		this.author = "author";
+		this.contributor = "contributor";
+		if(!personType){
+			personType = this.author;
+		}
+		this.personType = personType;
+		this.name = name || '';
+		this.email = email || '';
+		this.uri = uri || '';
+		this._objName = "Person";//for debugging
+	},
+	_getAttributeNames: function(){return null;},
+	_postBuild: function(){},
+	accept: function(tag){return Boolean(this._accepts[tag]);},
+	buildFromDom: function(node){
+		//	summary: 
+		//		Function to do construction of the person data from the DOM node containing it.
+		//	description: 
+		//		Function to do construction of the person data from the DOM node containing it.
+		//
+		//	node: 
+		//		The DOM node to process for person data.
+		var c = node.childNodes;
+		for(var i = 0; i< c.length; i++){
+			var name = dojox.atom.io.model.util.getNodename(c[i]);
+			
+			if(!name){continue;}
+
+			if(c[i].namespaceURI != dojox.atom.io.model._Constants.ATOM_NS && name != "#text"){
+				if(!this.extensions){this.extensions = [];}
+				var extensionNode = new dojox.atom.io.model.Node();
+				extensionNode.buildFromDom(c[i]);
+				this.extensions.push(extensionNode);
+			}
+			if(!this.accept(name.toLowerCase())){
+				continue;
+			}
+			var fn = dojox.atom.io.model._actions[name];
+			if(fn) {
+				fn(this,c[i]);
+			}
+		}
+		this._saveAttributes(node); 
+		if(this._postBuild){this._postBuild();}
+	},
+	_accepts: {
+		'name': true,
+		'uri': true,
+		'email': true
+	},
+	toString: function(){
+		//	summary: 
+		//		Function to construct string form of the Person tag, which is an XML structure.
+		//	description: 
+		//		Function to construct string form of the Person tag, which is an XML structure.
+		var s = [];
+		s.push('<'+this.personType+'>\n');
+		if(this.name){s.push('\t<name>'+this.name+'</name>\n');}
+		if(this.email){s.push('\t<email>'+this.email+'</email>\n');}
+		if(this.uri){s.push('\t<uri>'+this.uri+'</uri>\n');}
+		s.push('</'+this.personType+'>\n');
+		return s.join('');
+	}
+});
+
+dojo.declare("dojox.atom.io.model.Generator",dojox.atom.io.model.Node,{
+	//	summary: 
+	//		Class container for 'Generator' types.
+	//	description: 
+	//		Class container for 'Generator' types.
+	constructor: function(/*String*/uri, /*String*/version, /*String*/value){
+		this.uri = uri;
+		this.version = version;
+		this.value = value;
+	},
+	_postBuild: function(){},
+	buildFromDom: function(node){
+		//	summary: 
+		//		Function to do construction of the generator data from the DOM node containing it.
+		//	description: 
+		//		Function to do construction of the generator data from the DOM node containing it.
+		//
+		//	node: 
+		//		The DOM node to process for link data.
+
+		this.value = dojox.xml.parser.textContent(node);
+		this._saveAttributes(node);
+
+		this.uri = this.attributes.uri; 
+		this.version = this.attributes.version;
+
+		if(this._postBuild){this._postBuild();}
+	},
+	toString: function(){
+		//	summary: 
+		//		Function to construct string form of the Generator tag, which is an XML structure.
+		//	description: 
+		//		Function to construct string form of the Generator tag, which is an XML structure.
+		var s = [];
+		s.push('<generator ');
+		if(this.uri){s.push(' uri="'+this.uri+'" ');}
+		if(this.version){s.push(' version="'+this.version+'" ');}
+		s.push('>'+this.value+'</generator>\n');
+		var ret = s.join('');
+		return ret;
+	}
+});
+
+dojo.declare("dojox.atom.io.model.Entry",dojox.atom.io.model.AtomItem,{
+	//	summary: 
+	//		Class container for 'Entry' types.
+	//	description: 
+	//		Class container for 'Entry' types.
+	constructor: function(/*String*/id){
+		this.id = id; this._objName = "Entry"; this.feedUrl = null;
+	},
+	_getAttributeNames: function(){return null;},
+	_accepts: {
+		'author': true,
+		'content': true,
+		'category': true,
+		'contributor': true,
+		'created': true,
+		'id': true,
+		'link': true,
+		'published': true,
+		'rights': true,
+		'summary': true,
+		'title': true,
+		'updated': true,
+		'xmlbase': true,
+		'issued': true,
+		'modified': true
+	},
+	toString: function(amPrimary){
+		//	summary: 
+		//		Function to construct string form of the entry tag, which is an XML structure.
+		//	description: 
+		//		Function to construct string form of the entry tag, which is an XML structure.
+		var s = [];
+		var i;
+		if(amPrimary){
+			s.push("<?xml version='1.0' encoding='UTF-8'?>");
+			s.push("<entry xmlns='"+dojox.atom.io.model._Constants.ATOM_URI+"'");
+		}else{s.push("<entry");}
+		if(this.xmlBase){s.push(' xml:base="'+this.xmlBase+'" ');}
+		for(i in this.name_spaces){s.push(' xmlns:'+i+'="'+this.name_spaces[i]+'"');}
+		s.push('>\n');
+		s.push('<id>' + (this.id ? this.id: '') + '</id>\n'); 
+		if(this.issued && !this.published){this.published = this.issued;}
+		if(this.published){s.push('<published>'+dojo.date.stamp.toISOString(this.published)+'</published>\n');}
+		if(this.created){s.push('<created>'+dojo.date.stamp.toISOString(this.created)+'</created>\n');}
+		//Google News
+		if(this.issued){s.push('<issued>'+dojo.date.stamp.toISOString(this.issued)+'</issued>\n');}
+
+		//Google News
+		if(this.modified){s.push('<modified>'+dojo.date.stamp.toISOString(this.modified)+'</modified>\n');}
+
+		if(this.modified && !this.updated){this.updated = this.modified;}
+		if(this.updated){s.push('<updated>'+dojo.date.stamp.toISOString(this.updated)+'</updated>\n');}
+		if(this.rights){s.push('<rights>'+this.rights+'</rights>\n');}
+		if(this.title){s.push(this.title.toString());}
+		if(this.summary){s.push(this.summary.toString());}
+		var arrays = [this.authors,this.categories,this.links,this.contributors,this.extensions];
+		for(var x in arrays){
+			if(arrays[x]){
+				for(var y in arrays[x]){
+					s.push(arrays[x][y]);
+				}
+			}
+		}
+		if(this.content){s.push(this.content.toString());}
+		s.push("</entry>\n");
+		return s.join(''); //string
+	},
+	getEditHref: function(){
+		//	summary: 
+		//		Function to get the href that allows editing of this feed entry.
+		//	description: 
+		//		Function to get the href that allows editing of this feed entry.
+		//
+		//	returns: 
+		//		The href that specifies edit capability.
+		if(this.links === null || this.links.length === 0){
+			return null;
+		}
+		for(var x in this.links){
+			if(this.links[x].rel && this.links[x].rel == "edit"){
+				return this.links[x].href; //string
+			}
+		}
+		return null;
+	},
+	setEditHref: function(url){
+		if(this.links === null){
+			this.links = [];
+		}
+		for(var x in this.links){
+			if(this.links[x].rel && this.links[x].rel == "edit"){
+				this.links[x].href = url;
+				return;
+			}
+		}
+		this.addLink(url, 'edit');
+	}
+});
+
+dojo.declare("dojox.atom.io.model.Feed",dojox.atom.io.model.AtomItem,{
+	//	summary: 
+	//		Class container for 'Feed' types.
+	//	description: 
+	//		Class container for 'Feed' types.
+	_accepts: {
+		'author': true,
+		'content': true,
+		'category': true,
+		'contributor': true,
+		'created': true,
+		'id': true,
+		'link': true,
+		'published': true,
+		'rights': true,
+		'summary': true,
+		'title': true,
+		'updated': true,
+		'xmlbase': true,
+		'entry': true,
+		'logo': true,
+		'issued': true,
+		'modified': true,
+		'icon': true,
+		'subtitle': true
+	},
+	addEntry: function(/*object*/entry){
+		//	summary: 
+		//		Function to add an entry to this feed.
+		//	description: 
+		//		Function to add an entry to this feed.
+		//	entry: 
+		//		The entry object to add.
+		if(!entry.id){
+			throw new Error("The entry object must be assigned an ID attribute.");
+		}
+		if(!this.entries){this.entries = [];}
+		entry.feedUrl = this.getSelfHref();
+		this.entries.push(entry);
+	},
+	getFirstEntry: function(){
+		//	summary: 
+		//		Function to get the first entry of the feed.
+		//	description: 
+		//		Function to get the first entry of the feed.
+		//
+		//	returns: 
+		//		The first entry in the feed.
+		if(!this.entries || this.entries.length === 0){return null;}
+		return this.entries[0]; //object
+	},
+	getEntry: function(/*String*/entryId){
+		//	summary: 
+		//		Function to get an entry by its id.
+		//	description: 
+		//		Function to get an entry by its id.
+		//
+		//	returns: 
+		//		The entry desired, or null if none.
+		if(!this.entries){return null;}
+		for(var x in this.entries){
+			if(this.entries[x].id == entryId){
+				return this.entries[x];
+			}
+		}
+		return null;
+	},
+	removeEntry: function(/*object*/entry){
+		//	summary: 
+		//		Function to remove an entry from the list of links.
+		//	description: 
+		//		Function to remove an entry from the list of links.
+		//
+		//	entry: 
+		//		The entry.
+		if(!this.entries){return;}
+		var count = 0;
+		for(var i = 0; i < this.entries.length; i++){
+			if(this.entries[i] === entry){
+				this.entries.splice(i,1);
+				count++;
+			}
+		}
+		return count;
+	},
+	setEntries: function(/*array*/arrayOfEntry){
+		//	summary: 
+		//		Function to add a set of entries to the feed.
+		//	description: 
+		//		Function to get an entry by its id.
+		//
+		//	arrayOfEntry: 
+		//		An array of entry objects to add to the feed.
+		for(var x in arrayOfEntry){
+			this.addEntry(arrayOfEntry[x]);
+		}
+	},
+	toString: function(){
+		//	summary: 
+		//		Function to construct string form of the feed tag, which is an XML structure.
+		//	description: 
+		//		Function to construct string form of the feed tag, which is an XML structure.
+		var s = [];
+		var i;
+		s.push('<?xml version="1.0" encoding="utf-8"?>\n');
+		s.push('<feed xmlns="'+dojox.atom.io.model._Constants.ATOM_URI+'"');
+		if(this.xmlBase){s.push(' xml:base="'+this.xmlBase+'"');}
+		for(i in this.name_spaces){s.push(' xmlns:'+i+'="'+this.name_spaces[i]+'"');}
+		s.push('>\n');
+		s.push('<id>' + (this.id ? this.id: '') + '</id>\n'); 
+		if(this.title){s.push(this.title);}
+		if(this.copyright && !this.rights){this.rights = this.copyright;}
+		if(this.rights){s.push('<rights>' + this.rights + '</rights>\n');}
+		
+		// Google news
+		if(this.issued){s.push('<issued>'+dojo.date.stamp.toISOString(this.issued)+'</issued>\n');}
+		if(this.modified){s.push('<modified>'+dojo.date.stamp.toISOString(this.modified)+'</modified>\n');}
+
+		if(this.modified && !this.updated){this.updated=this.modified;}
+		if(this.updated){s.push('<updated>'+dojo.date.stamp.toISOString(this.updated)+'</updated>\n');}
+		if(this.published){s.push('<published>'+dojo.date.stamp.toISOString(this.published)+'</published>\n');}
+		if(this.icon){s.push('<icon>'+this.icon+'</icon>\n');}
+		if(this.language){s.push('<language>'+this.language+'</language>\n');}
+		if(this.logo){s.push('<logo>'+this.logo+'</logo>\n');}
+		if(this.subtitle){s.push(this.subtitle.toString());}
+		if(this.tagline){s.push(this.tagline.toString());}
+		//TODO: need to figure out what to do with xmlBase
+		var arrays = [this.alternateLinks,this.authors,this.categories,this.contributors,this.otherLinks,this.extensions,this.entries];
+		for(i in arrays){
+			if(arrays[i]){
+				for(var x in arrays[i]){
+					s.push(arrays[i][x]);
+				}
+			}
+		}
+		s.push('</feed>');
+		return s.join('');
+	},
+	createEntry: function(){
+		//	summary: 
+		//		Function to Create a new entry object in the feed.
+		//	description: 
+		//		Function to Create a new entry object in the feed.
+		//	returns: 
+		//		An empty entry object in the feed.
+		var entry = new dojox.atom.io.model.Entry();
+		entry.feedUrl = this.getSelfHref();
+		return entry; //object
+	},
+	getSelfHref: function(){
+		//	summary: 
+		//		Function to get the href that refers to this feed.
+		//	description: 
+		//		Function to get the href that refers to this feed.
+		//	returns: 
+		//		The href that refers to this feed or null if none.
+		if(this.links === null || this.links.length === 0){
+			return null;
+		}
+		for(var x in this.links){
+			if(this.links[x].rel && this.links[x].rel == "self"){
+				return this.links[x].href; //string
+			}
+		}
+		return null;
+	}
+});
+
+dojo.declare("dojox.atom.io.model.Service",dojox.atom.io.model.AtomItem,{
+	//	summary: 
+	//		Class container for 'Feed' types.
+	//	description: 
+	//		Class container for 'Feed' types.
+	constructor: function(href){
+		this.href = href;
+	},
+	//builds a Service document.  each element of this, except for the namespace, is the href of 
+	//a service that the server supports.  Some of the common services are:
+	//"create-entry" , "user-prefs" , "search-entries" , "edit-template" , "categories"
+	buildFromDom: function(/*DOM node*/node){
+		//	summary: 
+		//		Function to do construction of the Service data from the DOM node containing it.
+		//	description: 
+		//		Function to do construction of the Service data from the DOM node containing it.
+		//
+		//	node: 
+		//		The DOM node to process for content.
+		var i;
+		this.workspaces = [];
+		if(node.tagName != "service"){
+			// FIXME: Need 0.9 DOM util...
+			//node = dojox.xml.parser.firstElement(node,"service");
+			//if(!node){return;}
+			return;
+		}
+		if(node.namespaceURI != dojox.atom.io.model._Constants.PURL_NS && node.namespaceURI != dojox.atom.io.model._Constants.APP_NS){return;}
+		var ns = node.namespaceURI;
+		this.name_space = node.namespaceURI;
+		//find all workspaces, and create them
+		var workspaces ;
+		if(typeof(node.getElementsByTagNameNS)!= "undefined"){
+			workspaces = node.getElementsByTagNameNS(ns,"workspace");
+		}else{
+			// This block is IE only, which doesn't have a 'getElementsByTagNameNS' function
+			workspaces = [];
+			var temp = node.getElementsByTagName('workspace');
+			for(i=0; i<temp.length; i++){
+				if(temp[i].namespaceURI == ns){
+					workspaces.push(temp[i]);
+				}
+			}
+		}
+		if(workspaces && workspaces.length > 0){
+			var wkLen = 0;
+			var workspace;
+			for(i = 0; i< workspaces.length; i++){
+				workspace = (typeof(workspaces.item)==="undefined"?workspaces[i]:workspaces.item(i));
+				var wkspace = new dojox.atom.io.model.Workspace();
+				wkspace.buildFromDom(workspace);
+				this.workspaces[wkLen++] = wkspace;
+			}
+		}
+	},
+	getCollection: function(/*String*/url){
+		//	summary: 
+		//		Function to collections that match a specific url.
+		//	description: 
+		//		Function to collections that match a specific url.
+		//
+		//	url: 
+		//		e URL to match collections against.
+		for(var i=0;i<this.workspaces.length;i++){
+			var coll=this.workspaces[i].collections;
+			for(var j=0;j<coll.length;j++){
+				if(coll[j].href == url){
+					return coll;
+				}
+			}
+		}
+		return null;
+	}
+});
+
+dojo.declare("dojox.atom.io.model.Workspace",dojox.atom.io.model.AtomItem,{
+	//	summary: 
+	//		Class container for 'Workspace' types.
+	//	description: 
+	//		Class container for 'Workspace' types.
+	constructor: function(title){
+		this.title = title;
+		this.collections = [];
+	},
+
+	buildFromDom: function(/*DOM node*/node){
+		//	summary: 
+		//		Function to do construction of the Workspace data from the DOM node containing it.
+		//	description: 
+		//		Function to do construction of the Workspace data from the DOM node containing it.
+		//
+		//	node: 
+		//		The DOM node to process for content.
+		var name = dojox.atom.io.model.util.getNodename(node);
+		if(name != "workspace"){return;}
+		var c = node.childNodes;
+		var len = 0;
+		for(var i = 0; i< c.length; i++){
+			var child = c[i];
+			if(child.nodeType === 1){
+				name = dojox.atom.io.model.util.getNodename(child);
+				if(child.namespaceURI == dojox.atom.io.model._Constants.PURL_NS || child.namespaceURI == dojox.atom.io.model._Constants.APP_NS){
+					if(name === "collection"){
+						var coll = new dojox.atom.io.model.Collection();
+						coll.buildFromDom(child);
+						this.collections[len++] = coll;
+					}
+				}else if(child.namespaceURI === dojox.atom.io.model._Constants.ATOM_NS){
+					if(name === "title"){
+						this.title = dojox.xml.parser.textContent(child);
+					}
+				}
+				//FIXME: Add an extension point so others can impl different namespaces.  For now just
+				//ignore unknown namespace tags.
+			}
+		}
+	}
+});
+
+dojo.declare("dojox.atom.io.model.Collection",dojox.atom.io.model.AtomItem,{
+	//	summary: 
+	//		Class container for 'Collection' types.
+	//	description: 
+	//		Class container for 'Collection' types.
+	constructor: function(href, title){
+		this.href = href;
+		this.title = title;
+		this.attributes = [];
+		this.features = [];
+		this.children = [];
+		this.memberType = null;
+		this.id = null;
+	},
+
+	buildFromDom: function(/*DOM node*/node){
+		//	summary: 
+		//		Function to do construction of the Collection data from the DOM node containing it.
+		//	description: 
+		//		Function to do construction of the Collection data from the DOM node containing it.
+		//
+		//	node: 
+		//		The DOM node to process for content.
+		this.href = node.getAttribute("href");
+		var c = node.childNodes;
+		for(var i = 0; i< c.length; i++){
+			var child = c[i];
+			if(child.nodeType === 1){
+				var name = dojox.atom.io.model.util.getNodename(child);
+				if(child.namespaceURI == dojox.atom.io.model._Constants.PURL_NS || child.namespaceURI == dojox.atom.io.model._Constants.APP_NS){
+					if(name === "member-type"){
+						this.memberType = dojox.xml.parser.textContent(child);
+					}else if(name == "feature"){//this IF stmt might need some more work
+						if(child.getAttribute("id")){this.features.push(child.getAttribute("id"));}
+					}else{
+						var unknownTypeChild = new dojox.atom.io.model.Node();
+						unknownTypeChild.buildFromDom(child);
+						this.children.push(unknownTypeChild);
+					}
+				}else if(child.namespaceURI === dojox.atom.io.model._Constants.ATOM_NS){
+					if(name === "id"){
+						this.id = dojox.xml.parser.textContent(child);
+					}else if(name === "title"){
+						this.title = dojox.xml.parser.textContent(child);
+					}
+				}
+			}
+		}
+	}
+});
diff --git a/dojox/atom/tests/io/app.php b/dojox/atom/tests/io/app.php
new file mode 100644
index 0000000..e16902d
--- /dev/null
+++ b/dojox/atom/tests/io/app.php
@@ -0,0 +1,5 @@
+<?php
+if($_SERVER['REQUEST_METHOD'] == 'POST'){
+	header('Location: http://example.com/samplefeed.xml/entry/10', true, 201);
+}
+?>
diff --git a/dojox/atom/tests/io/appFail.php b/dojox/atom/tests/io/appFail.php
new file mode 100644
index 0000000..12d879e
--- /dev/null
+++ b/dojox/atom/tests/io/appFail.php
@@ -0,0 +1,8 @@
+<?php
+if($_SERVER['REQUEST_METHOD'] == "PUT" || $_SERVER['REQUEST_METHOD'] == 'DELETE'){
+	header($_SERVER["SERVER_PROTOCOL"]." 403 Forbidden", true, 403);
+	print("Modification forbidden, resource doesn't exist");
+}else if($_SERVER['REQUEST_METHOD'] == 'POST'){
+	header($_SERVER["SERVER_PROTOCOL"]." 400 Bad Request", true, 400);
+}
+?>
\ No newline at end of file
diff --git a/dojox/atom/tests/io/module.js b/dojox/atom/tests/io/module.js
new file mode 100644
index 0000000..c83e914
--- /dev/null
+++ b/dojox/atom/tests/io/module.js
@@ -0,0 +1,517 @@
+dojo.provide("dojox.atom.tests.io.module");
+dojo.require("dojox.atom.io.model");
+dojo.require("dojox.atom.io.Connection");
+dojo.require("dojox.data.dom");
+dojo.require("dojo.date.stamp");
+dojo.require("dojo.date");
+
+doh.register("dojox.atom.tests.io.module", [
+	// Public utility functions
+	// dojox.atom.io.model.util.createDate
+	function checkCreateDate(t){
+		var node = document.createElement("div");
+		var knownDate = "2007-08-06T20:00:00-04:00";
+		var date = dojo.date.stamp.fromISOString(knownDate);
+
+		//Make sure this function handles creating dates right with spaces and such in the text.
+		node.innerHTML = "  " + knownDate + "  ";
+		var dateWithSpaces = dojox.atom.io.model.util.createDate(node);
+
+		var res = dojo.date.compare(dateWithSpaces, date);
+		t.t(res === 0);
+	},
+
+	// dojox.atom.io.model.util.escapeHtml
+	function checkEscapeHTML(t){
+		var original = "<html><head><title>This is a \"Test Title\"</title></head><body class=\"tundra\">Woo hoo, this is an awesome & exciting test case!</body></html>";
+		var escaped = dojox.atom.io.model.util.escapeHtml(original);
+		var expected = "<html><head><title>This is a "Test Title"</title></head><body class="tundra">Woo hoo, this is an awesome & exciting test case!</body></html>";
+		t.is(expected, escaped);
+	},
+	
+	// dojox.atom.io.model.util.unEscapeHtml
+	function checkUnEscapeHtml(t){
+		var original = "<html><head><title>This is a "Test Title"</title></head><body class="tundra">Woo hoo, this is an awesome & exciting test case!</body></html>";
+		var unescaped = dojox.atom.io.model.util.unEscapeHtml(original);
+		var expected = "<html><head><title>This is a \"Test Title\"</title></head><body class=\"tundra\">Woo hoo, this is an awesome & exciting test case!</body></html>";
+		t.is(expected, unescaped);
+		t.is("<", dojox.atom.io.model.util.unEscapeHtml("&lt;"));
+	},
+
+	// dojox.atom.io.model.util.getNodename
+	function checkGetNodename(t){
+		var node = document.createElement("div");
+		t.is("div", dojox.atom.io.model.util.getNodename(node).toLowerCase());
+		
+		node = dojox.data.dom.createDocument("<root><first/><second/><third/></root>").firstChild;
+		t.is("root", dojox.atom.io.model.util.getNodename(node));
+		var n = node.firstChild;
+		dojo.forEach(["first", "second", "third"], function(name){
+			t.is(name, dojox.atom.io.model.util.getNodename(n));
+			node.removeChild(n);
+			n = node.firstChild;
+		});
+	},
+
+	// Feed parsing, feed attributes (title, id, etc.) and functions, including all generic AtomItem methods
+	// Incidently, also tests AtomIO.getFeed success, as well as all members of the Category, Content, Link, 
+	// and Person classes.  
+	{
+		name: "checkFeed",
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getFeed(dojo.moduleUrl('dojox.atom.tests.widget', 'samplefeed.xml').toString(), function(feed){
+				var i;
+				// regular callback
+				// Feed variables
+				t.is('Example.com', feed.title.value);
+				feed.setTitle('Example.com Atom Feed', 'text');
+				t.is('Example.com Atom Feed', feed.title.value);
+				t.is('Example.com\'s Sample Feed', feed.subtitle.value);
+				t.is('Copyright Example.com', feed.rights);
+				t.is('http://example.com/samplefeed.xml', feed.id);
+				t.is(dojo.date.stamp.fromISOString('2007-08-07T20:00:00-05:00'), feed.updated);
+
+				// AtomItem methods
+				feed.addNamespace('http://www.test.com');
+				t.is({}, feed.name_spaces);
+				feed.addNamespace('', 'test');
+				t.is({}, feed.name_spaces);
+				feed.addNamespace('http://www.test.com', 'test');
+				t.is({'test': 'http://www.test.com'}, feed.name_spaces);
+
+				t.is(null, feed.authors);
+				feed.addAuthor('John');
+				feed.addAuthor('Matt', 'matt at example.com');
+				feed.addAuthor('Joe', 'joe at example.com', 'http://joe.example.com');
+				t.t(dojo.isArray(feed.authors));
+				t.t(feed.authors.length === 3);
+
+				t.is(null, feed.contributors);
+				feed.addContributor('Sam');
+				feed.addContributor('Dave', 'Dave at example.com');
+				feed.addContributor('Harry', 'harry at example.com', 'http://harry.example.com');
+				t.t(dojo.isArray(feed.contributors));
+				t.t(feed.contributors.length === 3);
+
+				t.t(dojo.isArray(feed.links));
+				t.t(feed.links.length === 2);
+				feed.removeLink('http://example.com/', 'alternate');
+				t.t(feed.links.length === 1);
+				feed.addLink('http://www.example.com/', 'alternate', 'en', 'Example.com', 'text/html');
+				t.t(feed.links.length === 2);
+				feed.addLink('http://test.example.com/', '', 'en', 'Example.com', 'text/html');
+				t.t(feed.links.length === 3);
+				feed.removeBasicLinks();
+				t.t(feed.links.length === 2);
+
+				t.is(null, feed.categories);
+				feed.addCategory("scheme", "term", "label");
+				feed.addCategory("scheme", "term2", "label2");
+				feed.addCategory("scheme2", "term", "label");
+				t.t(dojo.isArray(feed.categories));
+				t.t(feed.categories.length === 3);
+				var c = feed.getCategories("scheme");
+				t.t(c.length === 2);
+				c = feed.getCategories("scheme2");
+				t.t(c.length === 1);
+				feed.removeCategories("scheme", "term2");
+				t.t(feed.categories.length === 2);
+				feed.removeCategories("scheme", "term");
+				t.t(feed.categories.length === 1);
+				feed.removeCategories("scheme2", "term");
+				t.t(feed.categories.length === 0);
+
+				t.is(null, feed.extensions);
+				t.is([], feed.getExtensions());
+				feed.addExtension('nameSpace', 'element', [], 'A Test Element', 'sns');
+				feed.addExtension('nameSpace', 'element2', [], 'Another Test Element', 'sns');
+				feed.addExtension('anotherNameSpace', 'element', [], 'A Test Element', 'asns');
+				t.t(feed.extensions.length === 3);
+				t.t(feed.getExtensions('nameSpace').length === 2);
+				t.t(feed.getExtensions('nameSpace', 'element').length === 1);
+				t.t(feed.getExtensions('anotherNameSpace', 'element').length === 1);
+				t.t(feed.getExtensions('sns').length === 2);
+				feed.removeExtensions('anotherNameSpace', 'element');
+				feed.removeExtensions('sns', 'element2');
+				t.t(feed.getExtensions('anotherNameSpace').length === 0);
+				t.t(feed.getExtensions('sns').length === 1);
+
+				// Feed methods
+				t.t(feed.accept('title'));
+				t.t(feed.accept('entry'));
+				t.f(feed.accept('workspace'));
+
+				var e = feed.getFirstEntry();
+				t.f(e === null);
+				t.t(e.id === 'http://example.com/samplefeed.xml/entry/1');
+				t.t(feed.entries.length === 6);
+				feed.removeEntry(e);
+				t.t(feed.entries.length === 5);
+				t.t(feed.getEntry('http://example.com/samplefeed.xml/entry/1') === null);
+				e = feed.getFirstEntry();
+				t.t(e.id === 'http://example.com/samplefeed.xml/entry/2');
+				e = feed.getEntry('http://example.com/samplefeed.xml/entry/4');
+				t.f(e === null);
+				t.t(e.title.value === 'Test Entry #4');
+				e = new dojox.atom.io.model.Entry();
+				t.e(Error, feed, 'addEntry', [e]);
+				t.t(feed.entries.length === 5);
+				e.id = 'http://example.com/samplefeed.xml/newentry/1';
+				feed.addEntry(e);
+				t.t(feed.entries.length === 6);
+				var entries = [];
+				for(i=2; i<5; i++){
+					e = new dojox.atom.io.model.Entry();
+					e.id = 'http://example.com/samplefeed.xml/newentry/'+i;
+					entries.push(e);
+				}
+				feed.setEntries(entries);
+				t.t(feed.entries.length === 9);
+				
+				e = feed.getSelfHref();
+				t.t(e === 'http://www.example.com/samplefeed.xml');
+				e = feed.createEntry();
+				t.t(e.feedUrl === 'http://www.example.com/samplefeed.xml');
+				
+
+				for(i=2; i<7; i++){
+					e = feed.getEntry('http://example.com/samplefeed.xml/entry/'+i);
+					feed.removeEntry(e);
+				}
+				t.t(feed.entries.length === 4);
+
+				//Make this test work in different timezones.
+				var isoString = dojo.date.stamp.toISOString(dojo.date.stamp.fromISOString('2007-08-07T20:00:00-05:00'));
+				var str = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:test=\"http://www.test.com\">\n<id>http://example.com/samplefeed.xml</id>\n<title  type=\"text\" >Example.com Atom Feed</title>\n<rights>Copyright Example.com</rights>\n"
+				str +="<updated>" + isoString + "</updated>\n<subtitle  type=\"text\" >Example.com's Sample Feed</subtitle>\n<author>\n\t<name>John</name>\n</author>\n<author>\n\t<name>Matt</name>\n\t<email>matt at example.com</email>\n</author>\n<author>\n\t<name>Joe</name>\n\t<email>joe at example.com</email>\n\t<uri>http://joe.example.com</uri>\n</author>\n<contributor>\n\t<name>Sam</name>\n</contributor>\n<contributor>\n\t<name>Dave</name>\n\t<email>Dave at example.com</email>\n</contributor>\n<contribut [...]
+				t.t(feed.toString() == str);
+
+				d.callback(true);
+			}, function(e){
+				// error callback
+				console.debug(e);
+				d.errback("Feed fetching failed");
+			});
+			return d;
+		}
+	},
+
+	// Entry parsing, entry functions that are unique (not AtomItem)
+	// Incidently, also tests success of AtomIO.getEntry
+	{
+		name: "checkEntry",
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getFeed(dojo.moduleUrl('dojox.atom.tests.widget', 'samplefeedEdit.xml').toString(), function(feed){
+				t.is('Example.com', feed.title.value);
+				var e = feed.createEntry();
+				var str = e.getEditHref();
+				t.t(str === null);
+
+				e = feed.getFirstEntry();
+				str = e.getEditHref();
+				t.t(str === null);
+
+				e = feed.getEntry('http://example.com/samplefeedEdit.xml/entry/10');
+				str = e.getEditHref();
+				t.t(str === 'http://example.com/samplefeedEdit.xml/entry/edit/10');
+
+				d.callback(true);
+			}, function(){
+				// error callback
+				d.errback("Feed fetching failed");
+			});
+			return d;
+		}
+	},
+
+	// Entry parsing, entry functions that are unique (not AtomItem)
+	// Incidently, also tests success of AtomIO.getEntry
+	{
+		name: "checkXmlEntry",
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getFeed(dojo.moduleUrl('dojox.atom.tests.io', 'sampleFeedXMLContent.xml'), function(feed){
+				try{
+					t.is('Example.com', feed.title.value);
+					var e = feed.getFirstEntry();
+					t.t(e.title.value == "Test Entry #1");
+					var c = e.content.value;
+					c = dojo.trim(c);
+					t.t(c.indexOf("<rootNode ") === 0);
+					d.callback(true);
+				}catch(err){
+					d.errback(err);
+				}
+			}, function(){
+				// error callback
+				d.errback("Feed fetching failed");
+			});
+			return d;
+		}
+	},
+
+	{
+		name: "checkEntry_preventCache",
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection(false, true);
+			atomio.getFeed(dojo.moduleUrl('dojox.atom.tests.widget', 'samplefeedEdit.xml').toString(), function(feed){
+				t.is('Example.com', feed.title.value);
+				var e = feed.createEntry();
+				var str = e.getEditHref();
+				t.t(str === null);
+
+				e = feed.getFirstEntry();
+				str = e.getEditHref();
+				t.t(str === null);
+
+				e = feed.getEntry('http://example.com/samplefeedEdit.xml/entry/10');
+				str = e.getEditHref();
+				t.t(str === 'http://example.com/samplefeedEdit.xml/entry/edit/10');
+
+				d.callback(true);
+			}, function(){
+                                // error callback
+			d.errback("Feed fetching failed");
+			});
+			return d;
+		}
+	},
+
+	// AtomIO tests
+	{
+		name: "checkAtomIOGetFeedFail",
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getFeed(dojo.moduleUrl('dojox.atom.tests.widget', 'samplefee.xml').toString(), function(feed){
+				d.errback("Feed fetching succeeded when it should've failed");
+			}, function(error, args){
+				// error callback
+				t.t(error.name === 'Error');
+				t.t(error.status === 404);
+				d.callback(true);
+			});
+			return d;
+		}
+	},{
+		name: "checkAtomIOGetFeedSuccess",
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getFeed(dojo.moduleUrl('dojox.atom.tests.widget', 'samplefeed.xml').toString(), function(feed){
+				// Feed Fetching succeeded
+				t.t(feed.title.value === 'Example.com');
+				d.callback(true);
+			}, function(error, args){
+				// error callback
+				d.errback("Feed fetching failed");
+			});
+			return d;
+		}
+	},{
+		name: "checkAtomIOGetEntryFail",
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getEntry(dojo.moduleUrl('dojox.atom.tests.io', 'sampleEntr.xml').toString(), function(entry){
+				d.errback("Feed fetching succeeded when it should've failed");
+			}, function(error, args){
+				// error callback
+				t.t(error.name === 'Error');
+				t.t(error.status === 404);
+				d.callback(true);
+			});
+			return d;
+		}
+	},{
+		name: "checkAtomIOGetEntrySuccess",
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getEntry(dojo.moduleUrl('dojox.atom.tests.io', 'sampleEntry.xml').toString(), function(entry){
+				t.t(entry.title.value === 'Test Entry #1');
+				t.t(entry.id === 'http://example.com/sampleEntry.xml/entry/1');
+				d.callback(true);
+			}, function(error, args){
+				// error callback
+				d.errback("Feed fetching failed");
+			});
+			return d;
+		}
+	},{
+		name: "checkAtomIOGetEntryFeedSuccess",
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getEntry(dojo.moduleUrl('dojox.atom.tests.widget', 'samplefeed.xml').toString(), function(entry){
+				// Using getEntry on a Feed URL yields the first Entry in the Feed.
+				t.t(entry.title.value === 'Test Entry #1');
+				t.t(entry.id === 'http://example.com/samplefeed.xml/entry/1');
+				d.callback(true);
+			}, function(error, args){
+				// error callback
+				d.errback("Feed fetching failed");
+			});
+			return d;
+		}
+	},{
+		name: "checkGetService",
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getService(dojo.moduleUrl('dojox.atom.tests.io', 'service.xml').toString(), function(service, domNode){
+				var collection = service.getCollection("http://example.com/feed");
+				t.t(collection[0].href === 'http://example.com/feed');
+				t.t(collection[0].title === 'Test Collection');
+				d.callback(true);
+			}, function(error, args){
+				// error callback
+				d.errback("Service fetching failed");
+			});
+			return d;
+		}
+	},{
+		name: "checkAtomIOUpdateEntrySuccess",
+		timeout: 5000,
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getEntry(dojo.moduleUrl('dojox.atom.tests.widget', 'samplefeed.xml').toString(), function(entry){
+				// Using getEntry on a Feed URL yields the first Entry in the Feed.
+				t.t(entry.title.value === 'Test Entry #1');
+				t.t(entry.id === 'http://example.com/samplefeed.xml/entry/1');
+				entry.setEditHref(dojo.moduleUrl('dojox.atom.tests.io', 'app.php'));
+				entry.setTitle('<h1>New Editable Title!</h1>', 'xhtml');
+				atomio.updateEntry(entry, function(e, dom, args){
+					t.t(e.title.value === '<h1>New Editable Title!</h1>');
+					t.t(e.id === 'http://example.com/samplefeed.xml/entry/1');
+					d.callback(true);
+				}, function(error, args){
+					d.errback("Updating entry failed");
+				});
+			}, function(error, args){
+				// error callback
+				d.errback("Feed fetching failed");
+			});
+			return d;
+		}
+	},{
+		name: "checkAtomIOUpdateEntryFail",
+		timeout: 5000,
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getEntry(dojo.moduleUrl('dojox.atom.tests.widget', 'samplefeed.xml').toString(), function(entry){
+				// Using getEntry on a Feed URL yields the first Entry in the Feed.
+				t.t(entry.title.value === 'Test Entry #1');
+				t.t(entry.id === 'http://example.com/samplefeed.xml/entry/1');
+				entry.setEditHref(dojo.moduleUrl('dojox.atom.tests.io', 'appFail.php'));
+				entry.setTitle('<h1>New Editable Title!</h1>', 'xhtml');
+				atomio.updateEntry(entry, function(e, dom, args){
+					d.errback("Updating entry succeeded");
+				}, function(error, args){
+					d.callback(true);
+				});
+			}, function(error, args){
+				// error callback
+				d.errback("Updating entry failed.");
+			});
+			return d;
+		}
+	},{
+		name: "checkAtomIOAddEntrySuccess",
+		timeout: 5000,
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var entry = new dojox.atom.io.model.Entry();
+			entry.setTitle('Test Editable Entry #1', 'text');
+			entry.addAuthor('Test Person', 'test at example.com');
+			entry.content = new dojox.atom.io.model.Content('content', 'This is the content of my test new entry!', null, 'text');
+			var atomio = new dojox.atom.io.Connection();
+			atomio.addEntry(entry, dojo.moduleUrl('dojox.atom.tests.io', 'app.php').toString(), function(entry, url){
+				t.t(entry.title.value === 'Test Editable Entry #1');
+				t.t(url === 'http://example.com/samplefeed.xml/entry/10');
+				d.callback(true);
+			}, function(error, args){
+				// error callback
+				d.errback("Adding entry failed.");
+			});
+			return d;
+		}
+	},{
+		name: "checkAtomIOAddEntryFail",
+		timeout: 5000,
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var entry = new dojox.atom.io.model.Entry();
+			// Missing title, author
+			entry.content = new dojox.atom.io.model.Content('content', 'This is the content of my test new entry!', null, 'text');
+			var atomio = new dojox.atom.io.Connection();
+			atomio.addEntry(entry, dojo.moduleUrl('dojox.atom.tests.io', 'appFail.php').toString(), function(entry, url){
+				// error callback
+				d.errback("Adding entry succeeded when it shouldn't!");
+			}, function(error, args){
+				d.callback(true);
+			});
+			return d;
+		}
+	},{
+		name: "checkAtomIODeleteEntrySuccess",
+		timeout: 5000,
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getEntry(dojo.moduleUrl('dojox.atom.tests.widget', 'samplefeed.xml').toString(), function(entry){
+				// Using getEntry on a Feed URL yields the first Entry in the Feed.
+				t.t(entry.title.value === 'Test Entry #1');
+				t.t(entry.id === 'http://example.com/samplefeed.xml/entry/1');
+				entry.setEditHref(dojo.moduleUrl('dojox.atom.tests.io', 'app.php'));
+				atomio.deleteEntry(entry, function(result){
+					if (result) {
+						d.callback(true);
+					}else{
+						d.errback("Deleting entry failed");
+					}
+				}, function(error, args){
+					d.errback("Deleting entry failed");
+				});
+			}, function(error, args){
+				// error callback
+				d.errback("Retreiving the entry failed.");
+			});
+			return d;
+		}
+	},{
+		name: "checkAtomIODeleteEntryFail",
+		timeout: 5000,
+		runTest: function(t){
+			var d = new doh.Deferred();
+			var atomio = new dojox.atom.io.Connection();
+			atomio.getEntry(dojo.moduleUrl('dojox.atom.tests.widget', 'samplefeed.xml').toString(), function(entry){
+				// Using getEntry on a Feed URL yields the first Entry in the Feed.
+				t.t(entry.title.value === 'Test Entry #1');
+				t.t(entry.id === 'http://example.com/samplefeed.xml/entry/1');
+				entry.setEditHref(dojo.moduleUrl('dojox.atom.tests.io', 'appFail.php'));
+				atomio.deleteEntry(entry, function(result){
+					if (result) {
+						d.errback("Deleting entry succeeded but it shouldn't have");
+					}else{
+						d.errback("The callback was called but it shouldn't have");
+					}
+				}, function(error, args){
+						d.callback(true);
+				});
+			}, function(error, args){
+				// error callback
+				d.errback("Retreiving the entry failed.");
+			});
+			return d;
+		}
+	}
+]);
diff --git a/dojox/atom/tests/io/runTests.html b/dojox/atom/tests/io/runTests.html
new file mode 100644
index 0000000..3f256ae
--- /dev/null
+++ b/dojox/atom/tests/io/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../../util/doh/runner.html?testModule=dojox.atom.tests.io.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/atom/tests/io/sampleEntry.xml b/dojox/atom/tests/io/sampleEntry.xml
new file mode 100644
index 0000000..5e64033
--- /dev/null
+++ b/dojox/atom/tests/io/sampleEntry.xml
@@ -0,0 +1,21 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<entry xmlns='http://www.w3.org/2005/Atom'>
+		<title>Test Entry #1</title>
+		<id>http://example.com/sampleEntry.xml/entry/1</id>
+		<link rel='alternate' href='http://example.com/1.html'/>
+		<summary type='html'>
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary.</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+		</summary>
+		<author>
+			<name>Test User</name>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T04:00:00-05:00</updated>
+</entry>
\ No newline at end of file
diff --git a/dojox/atom/tests/io/sampleFeedXMLContent.xml b/dojox/atom/tests/io/sampleFeedXMLContent.xml
new file mode 100755
index 0000000..66b52c3
--- /dev/null
+++ b/dojox/atom/tests/io/sampleFeedXMLContent.xml
@@ -0,0 +1,42 @@
+<?xml version='1.0' encoding='utf-8'?>
+<feed xmlns='http://www.w3.org/2005/Atom' xml:lang='en-US'>
+	<title>Example.com</title>
+	<link rel="alternate" type="text/html" href="http://example.com/" hreflang="en" title="Example.com" />
+	<subtitle type='text'>Example.com's Sample Feed</subtitle>
+	<rights>Copyright Example.com</rights>
+	<id>http://example.com/samplefeed.xml</id>
+	<updated>2007-08-07T20:00:00-05:00</updated>
+	<link rel="self" type="application/atom+xml" href="http://www.example.com/samplefeed.xml"/>
+	<entry xmlns="http://www.w3.org/2005/Atom">
+    		<title>Test Entry #1</title>
+    		<id>http://example.com/samplefeed.xml/entry/1</id>
+    		<link rel='alternate' href='http://example.com/1.html'/>
+    		<summary type='html'>This is entry #1</summary>
+    		<author>
+    			<name>Test User</name>
+    			<email>test at example.com</email>
+    		</author>
+    		<updated>2007-08-07T04:00:00-05:00</updated>
+		<content type="text/xml">
+			<rootNode>
+				<textContainer>Some Random Text #1</textContainer>
+			</rootNode>
+		</content>
+	</entry>
+	<entry xmlns="http://www.w3.org/2005/Atom">
+    		<title>Test Entry #2</title>
+    		<id>http://example.com/samplefeed.xml/entry/1</id>
+    		<link rel='alternate' href='http://example.com/1.html'/>
+    		<summary type='html'>This is entry #2</summary>
+    		<author>
+    			<name>Test User</name>
+    			<email>test at example.com</email>
+    		</author>
+    		<updated>2007-08-07T04:00:00-05:00</updated>
+		<content type="text/xml">
+			<rootNode>
+				<textContainer>Some Random Text #2</textContainer>
+			</rootNode>
+		</content>
+	</entry>
+</feed>
diff --git a/dojox/atom/tests/io/samplefeedEdit.xml b/dojox/atom/tests/io/samplefeedEdit.xml
new file mode 100644
index 0000000..2722ee9
--- /dev/null
+++ b/dojox/atom/tests/io/samplefeedEdit.xml
@@ -0,0 +1,54 @@
+<?xml version='1.0' encoding='utf-8'?>
+<feed xmlns='http://www.w3.org/2005/Atom' xml:lang='en-US'>
+	<title>Example.com</title>
+	<link rel="alternate" type="text/html" href="http://example.com/" hreflang="en" title="Example.com" />
+	<subtitle type='text'>Example.com's Sample Feed</subtitle>
+	<rights>Copyright Example.com</rights>
+	<id>http://example.com/samplefeedEdit.xml</id>
+	<updated>2007-08-07T20:00:00-05:00</updated>
+	<link rel="self" type="application/atom+xml" href="http://www.example.com/samplefeedEdit.xml"/>
+	<entry>
+		<title>Test Editable Entry #1</title>
+		<id>http://example.com/samplefeedEdit.xml/entry/10</id>
+		<link rel='alternate' href='http://example.com/10.html'/>
+		<link rel='edit' href='http://example.com/samplefeedEdit.xml/entry/edit/10'/>
+		<summary type='text/html'>
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary. This entry is also 
+			editable!</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+		</summary>
+		<author>
+			<name>Test User</name>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T06:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Editable Entry #2</title>
+		<id>http://example.com/samplefeedEdit.xml/entry/11</id>
+		<link rel='alternate' href='http://example.com/11.html'/>
+		<link rel='edit' href='http://example.com/samplefeedEdit.xml/entry/edit/11'/>
+		<summary type='html'>
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary. This entry is also 
+			editable!</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+		</summary>
+		<author>
+			<name>Test User</name>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T14:00:00-05:00</updated>
+	</entry>
+</feed>
diff --git a/dojox/atom/tests/io/service.xml b/dojox/atom/tests/io/service.xml
new file mode 100644
index 0000000..159196e
--- /dev/null
+++ b/dojox/atom/tests/io/service.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" ?> 
+<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
+	<workspace>
+		<atom:title type="text">Test Service</atom:title>
+		<collection href="http://example.com/feed">
+			<atom:title type="text">Test Collection</atom:title> 
+			<accept>application/*,image/*,*/*</accept> 
+		</collection>
+	</workspace>
+</service>
diff --git a/dojox/atom/tests/widget/samplefeed.xml b/dojox/atom/tests/widget/samplefeed.xml
new file mode 100644
index 0000000..4659949
--- /dev/null
+++ b/dojox/atom/tests/widget/samplefeed.xml
@@ -0,0 +1,130 @@
+<?xml version='1.0' encoding='utf-8'?>
+<feed xmlns='http://www.w3.org/2005/Atom' xml:lang='en-US'>
+	<title>Example.com</title>
+	<link rel="alternate" type="text/html" href="http://example.com/" hreflang="en" title="Example.com" />
+	<subtitle type='text'>Example.com's Sample Feed</subtitle>
+	<rights>Copyright Example.com</rights>
+	<id>http://example.com/samplefeed.xml</id>
+	<updated>2007-08-07T20:00:00-05:00</updated>
+	<link rel="self" type="application/atom+xml" href="http://www.example.com/samplefeed.xml"/>
+	<entry>
+		<title>Test Entry #1</title>
+		<id>http://example.com/samplefeed.xml/entry/1</id>
+		<link rel='alternate' href='http://example.com/1.html'/>
+		<summary type='html'>
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary.</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+		</summary>
+		<author>
+			<name>Test User</name>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T04:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Entry #2</title>
+		<id>http://example.com/samplefeed.xml/entry/2</id>
+		<link rel='alternate' href='http://example.com/2.html'/>
+		<summary type='text'>
+			This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary. This is straight text.
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.
+		</summary>
+		<author>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T06:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Entry #3</title>
+		<id>http://example.com/samplefeed.xml/entry/3</id>
+		<link rel='alternate' href='http://example.com/3.html'/>
+		<summary type='xhtml'>
+			<div xmlns="http://www.w3.org/1999/xhtml">
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary.</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+			</div>
+		</summary>
+		<author>
+			<name>Test User</name>
+		</author>
+		<updated>2007-08-07T08:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Entry #4</title>
+		<id>http://example.com/samplefeed.xml/entry/4</id>
+		<link rel='alternate' href='http://example.com/4.html'/>
+		<summary type='text/xhtml'>
+			<div xmlns="http://www.w3.org/1999/xhtml">
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary.</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+			</div>
+		</summary>
+		<author>
+			<name>Test User</name>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T10:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Entry #5</title>
+		<id>http://example.com/samplefeed.xml/entry/5</id>
+		<link rel='alternate' href='http://example.com/5.html'/>
+		<summary type='text'>
+			This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary. This is straight text.
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.
+		</summary>
+		<author>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T12:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Entry #6</title>
+		<id>http://example.com/samplefeed.xml/entry/6</id>
+		<link rel='alternate' href='http://example.com/6.html'/>
+		<summary type='text/html'>
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary.</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+		</summary>
+		<author>
+			<name>Test User</name>
+		</author>
+		<updated>2007-08-07T14:00:00-05:00</updated>
+	</entry>
+</feed>
diff --git a/dojox/atom/tests/widget/samplefeedEdit.xml b/dojox/atom/tests/widget/samplefeedEdit.xml
new file mode 100644
index 0000000..d13820d
--- /dev/null
+++ b/dojox/atom/tests/widget/samplefeedEdit.xml
@@ -0,0 +1,175 @@
+<?xml version='1.0' encoding='utf-8'?>
+<feed xmlns='http://www.w3.org/2005/Atom' xml:lang='en-US'>
+	<title>Example.com</title>
+	<link rel="alternate" type="text/html" href="http://example.com/" hreflang="en" title="Example.com" />
+	<subtitle type='text'>Example.com's Sample Feed</subtitle>
+	<rights>Copyright Example.com</rights>
+	<id>http://example.com/samplefeedEdit.xml</id>
+	<updated>2007-08-07T20:00:00-05:00</updated>
+	<link rel="self" type="application/atom+xml" href="http://www.example.com/samplefeedEdit.xml"/>
+	<entry>
+		<title>Test Entry #1</title>
+		<id>http://example.com/samplefeedEdit.xml/entry/1</id>
+		<link rel='alternate' href='http://example.com/1.html'/>
+		<summary type='html'>
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary.</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+		</summary>
+		<author>
+			<name>Test User</name>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T04:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Editable Entry #1</title>
+		<id>http://example.com/samplefeedEdit.xml/entry/10</id>
+		<link rel='alternate' href='http://example.com/10.html'/>
+		<link rel='edit' href='http://example.com/samplefeedEdit.xml/entry/edit/10'/>
+		<summary type='text/html'>
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary. This entry is also 
+			editable!</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+		</summary>
+		<author>
+			<name>Test User</name>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T06:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Entry #2</title>
+		<id>http://example.com/samplefeedEdit.xml/entry/2</id>
+		<link rel='alternate' href='http://example.com/2.html'/>
+		<summary type='text'>
+			This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary. This is straight text.
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.
+		</summary>
+		<author>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T08:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Entry #3</title>
+		<id>http://example.com/samplefeedEdit.xml/entry/3</id>
+		<link rel='alternate' href='http://example.com/3.html'/>
+		<summary type='xhtml'>
+			<div xmlns="http://www.w3.org/1999/xhtml">
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary.</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+			</div>
+		</summary>
+		<author>
+			<name>Test User</name>
+		</author>
+		<updated>2007-08-07T10:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Entry #4</title>
+		<id>http://example.com/samplefeedEdit.xml/entry/4</id>
+		<link rel='alternate' href='http://example.com/4.html'/>
+		<summary type='text/xhtml'>
+			<div xmlns="http://www.w3.org/1999/xhtml">
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary.</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+			</div>
+		</summary>
+		<author>
+			<name>Test User</name>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T12:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Editable Entry #2</title>
+		<id>http://example.com/samplefeedEdit.xml/entry/11</id>
+		<link rel='alternate' href='http://example.com/11.html'/>
+		<link rel='edit' href='http://example.com/samplefeedEdit.xml/entry/edit/11'/>
+		<summary type='html'>
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary. This entry is also 
+			editable!</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+		</summary>
+		<author>
+			<name>Test User</name>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T14:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Entry #5</title>
+		<id>http://example.com/samplefeedEdit.xml/entry/5</id>
+		<link rel='alternate' href='http://example.com/5.html'/>
+		<summary type='text'>
+			This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary. This is straight text.
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.
+		</summary>
+		<author>
+			<email>test at example.com</email>
+		</author>
+		<updated>2007-08-07T16:00:00-05:00</updated>
+	</entry>
+	<entry>
+		<title>Test Entry #6</title>
+		<id>http://example.com/samplefeedEdit.xml/entry/6</id>
+		<link rel='alternate' href='http://example.com/6.html'/>
+		<summary type='text/html'>
+			<p>This is a sample entry in our Atom feed.  It is simply a bunch of stuff in the summary.</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras cursus. Aliquam eget metus sed leo lacinia 
+			rutrum. Nunc lacus lacus, viverra placerat, laoreet nec, placerat vel, eros. Donec nec magna id sem commodo rutrum. 
+			Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Aenean pede. Quisque vel 
+			leo. In vitae nisi. Curabitur sodales congue nibh. Maecenas ultrices ante nec ipsum. Aenean quis nibh. Aenean semper, 
+			quam vitae ullamcorper euismod, arcu leo tincidunt nunc, vel pulvinar turpis dolor a elit. Praesent nonummy nunc 
+			faucibus nibh. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus laoreet, 
+			ante auctor condimentum venenatis, magna quam varius elit, at feugiat dolor metus id quam. Etiam enim.</p>
+		</summary>
+		<author>
+			<name>Test User</name>
+		</author>
+		<updated>2007-08-07T18:00:00-05:00</updated>
+	</entry>
+
+</feed>
diff --git a/dojox/atom/tests/widget/test_FeedViewer_bind.html b/dojox/atom/tests/widget/test_FeedViewer_bind.html
new file mode 100644
index 0000000..86ed5dd
--- /dev/null
+++ b/dojox/atom/tests/widget/test_FeedViewer_bind.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Test the Feed Viewer (using ATOM)</title>
+<style type="text/css">
+	@import "../../widget/templates/css/EntryHeader.css";
+	@import "../../widget/templates/css/HtmlFeedViewer.css";
+	@import "../../widget/templates/css/HtmlFeedViewerGrouping.css";
+	@import "../../widget/templates/css/HtmlFeedViewerEntry.css";
+	@import "../../widget/templates/css/HtmlFeedEntryViewer.css";
+</style>
+<script type="text/javascript">
+  var djConfig = {isDebug: true, parseOnLoad: true};
+</script>
+<script type="text/javascript" src="../../../../dojo/dojo.js"></script>
+<script language="JavaScript" type="text/javascript">
+	dojo.require("dojox.atom.widget.FeedViewer");
+	dojo.require("dijit.layout.ContentPane");
+	var feedViewer = null;
+	var feedPane = null;
+	var feedTitle = null;
+	var feedURI = "samplefeed.xml";
+	function init(){
+		feedViewer = dijit.byId("fv1");
+		feedPane = dijit.byId("feedPane");	
+		feedTitle = dojo.byId("feedTitle"); 
+
+		var atomIO = new dojox.atom.io.Connection();
+		atomIO.getFeed(feedURI,dojo.hitch(feedViewer,feedViewer.setFeed));
+
+		dojo.connect(feedViewer,"onEntrySelected",function (entry){
+			feedTitle.textContent = entry.title.value;
+			if (entry.content){
+				feedPane.setContent(entry.content.value);
+				feedPane.setContent(entry.content.toString());
+			} else if (entry.summary){
+				feedPane.setContent(entry.summary.value);
+			}
+		});
+	}
+	dojo.addOnLoad(init);
+</script>
+</head>
+<body>
+	<div> 
+		<div dojoType="dojox.atom.widget.FeedViewer" id="fv1"></div>
+	</div>  
+	<div>  
+		<div id="feedTitle" style="font-size: large;font-weight: bold;"></div>  
+		<div dojoType="dijit.layout.ContentPane" id="feedPane"></div>
+	</div>
+</body>
+</html>
diff --git a/dojox/atom/tests/widget/test_FeedViewer_bind_split_declarative.html b/dojox/atom/tests/widget/test_FeedViewer_bind_split_declarative.html
new file mode 100644
index 0000000..cb728df
--- /dev/null
+++ b/dojox/atom/tests/widget/test_FeedViewer_bind_split_declarative.html
@@ -0,0 +1,131 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Test the Feed Viewer (using ATOM)</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/themes/tundra/tundra.css";
+	@import "../../widget/templates/css/EntryHeader.css";
+	@import "../../widget/templates/css/HtmlFeedViewer.css";
+	@import "../../widget/templates/css/HtmlFeedViewerGrouping.css";
+	@import "../../widget/templates/css/HtmlFeedViewerEntry.css";
+	@import "../../widget/templates/css/HtmlFeedEntryViewer.css";
+</style>
+<script type="text/javascript">
+  var djConfig = {isDebug: true, parseOnLoad: true};
+</script>
+<script type="text/javascript" src="../../../../dojo/dojo.js"></script>
+<script language="JavaScript" type="text/javascript">
+	dojo.require("dojox.atom.widget.FeedViewer");
+	dojo.require("dojox.atom.widget.FeedEntryViewer");
+	dojo.require("dojox.atom.widget.FeedEntryEditor");
+	dojo.require("dijit.layout.ContentPane");
+	dojo.require("dijit.layout.SplitContainer");
+	dojo.require("dojo.parser");
+	
+</script>
+<style>
+	html, body, #main {	  
+			width: 100%;	
+			height: 100%;
+			/*overflow: hidden;*/
+			padding: 0 0 0 0;
+			margin: 0 0 0 0;
+			font-family: Myriad,Tahoma,Verdana,sans-serif;
+			font-size:  small;
+			background: #FFF;
+	}
+
+	#ViewPane{
+			overflow: auto;
+			overflow-x: auto;
+			overflow-y: auto;
+			padding: 5px;
+			font-family: Myriad,Tahoma,Verdana,sans-serif;
+			font-size:  small;
+			/*background: lightgrey;*/
+			background:#FFF;
+			word-wrap: normal;
+	}
+	
+	#EditorPane {
+			overflow: auto;	   /* We want scrolling*/
+			overflow-x: auto;
+			overflow-y: auto;
+			padding: 0px;
+			background: #FFF;
+	}
+	
+	#ActionContainer {
+		height: 1024px;
+	}
+	
+</style>
+</head>
+<body class="tundra">
+
+<!-- Actual layout and display section -->
+<div id="ActionContainer"
+	 dojoType="dijit.layout.SplitContainer"
+	 orientation="horizontal"
+	 sizerWidth="1"
+	 activeSizing="false"
+>
+		<div dojoType="dijit.layout.ContentPane"
+			 id="ViewPaneID"
+			 executeScripts="true" 
+		>
+			<div dojoType="dojox.atom.widget.FeedViewer" 
+				 id="fv1"
+				 url="samplefeed.xml"
+				 entrySelectionTopic="atomfeed.entry.topic">
+			</div>
+		</div>
+
+		<div dojoType="dijit.layout.ContentPane"
+			 id="ViewPaneID2"
+			 executeScripts="true" 
+		>
+			<div dojoType="dojox.atom.widget.FeedViewer" 
+				 id="fv2"
+				 xmethod="true"
+				 localSaveOnly="true"
+				 url="samplefeedEdit.xml"
+				 entrySelectionTopic="atomfeed2.entry.topic">
+			</div>
+		</div>
+		
+		<div dojoType="dijit.layout.ContentPane"
+			 id="EditorPaneID2"
+			 executeScripts="true" 
+		>
+			<div dojoType="dojox.atom.widget.FeedEntryEditor" 
+				 id="feedEditor2"
+				 enableMenu="true"
+				 enableMenuFade="true"
+				 enableEdit="true"
+				 displayEntrySections="title,authors,summary,content,id"
+				 entrySelectionTopic="atomfeed2.entry.topic">
+			</div>
+		</div>
+
+
+		<div dojoType="dijit.layout.ContentPane"
+			 id="EditorPaneID"
+			 executeScripts="true" 
+		>
+			<div dojoType="dojox.atom.widget.FeedEntryViewer" 
+				 id="feedEditor"
+				 enableMenu="true"
+				 enableMenuFade="true"
+				 enableEdit="true"
+				 displayEntrySections="title,authors,summary,content"
+				 entrySelectionTopic="atomfeed.entry.topic">
+			</div>
+		</div>
+		
+</div>
+
+	
+</body>
+</html>
diff --git a/dojox/atom/tests/widget/test_FeedViewer_bind_sync.html b/dojox/atom/tests/widget/test_FeedViewer_bind_sync.html
new file mode 100644
index 0000000..4fba464
--- /dev/null
+++ b/dojox/atom/tests/widget/test_FeedViewer_bind_sync.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Test the Feed Viewer (using ATOM)</title>
+<style type="text/css">
+	@import "../../widget/templates/css/EntryHeader.css";
+	@import "../../widget/templates/css/HtmlFeedViewer.css";
+	@import "../../widget/templates/css/HtmlFeedViewerGrouping.css";
+	@import "../../widget/templates/css/HtmlFeedViewerEntry.css";
+	@import "../../widget/templates/css/HtmlFeedEntryViewer.css";
+</style>
+<script type="text/javascript">
+  var djConfig = {isDebug: true, parseOnLoad: true};
+</script>
+<script type="text/javascript" src="../../../../dojo/dojo.js"></script>
+<script language="JavaScript" type="text/javascript">
+	dojo.require("dojox.atom.widget.FeedViewer");
+	dojo.require("dijit.layout.ContentPane");
+	var feedViewer = null;
+	var feedPane = null;
+	var feedTitle = null;
+	var feedURI = "samplefeed.xml";
+	function init(){
+		feedViewer = dijit.byId("fv1");   
+		feedPane = dijit.byId("feedPane");	
+		feedTitle = dojo.byId("feedTitle"); 
+
+		var atomIO = new dojox.atom.io.Connection(true);
+		atomIO.getFeed(feedURI,dojo.hitch(feedViewer,feedViewer.setFeed),true);
+
+		dojo.connect(feedViewer,"onEntrySelected",function (entry){
+			feedTitle.textContent = entry.title.value;
+			if (entry.content){
+				feedPane.setContent(entry.content.value);
+				feedPane.setContent(entry.content.toString());
+			} else if (entry.summary){
+				feedPane.setContent(entry.summary.value);
+			}
+		});
+	}
+	dojo.addOnLoad(init);
+</script>
+</head>
+<body>
+	<div> 
+		<div dojoType="dojox.atom.widget.FeedViewer" id="fv1"></div>
+	</div>  
+	<div>  
+		<div id="feedTitle" style="font-size: large;font-weight: bold;"></div>  
+		<div dojoType="dijit.layout.ContentPane" id="feedPane"></div>
+	</div>
+</body>
+</html>
diff --git a/dojox/atom/tests/widget/test_FeedViewer_local.html b/dojox/atom/tests/widget/test_FeedViewer_local.html
new file mode 100644
index 0000000..1c0f579
--- /dev/null
+++ b/dojox/atom/tests/widget/test_FeedViewer_local.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Test the Feed Viewer (using ATOM)</title>
+<style type="text/css">
+	@import "../../widget/templates/css/EntryHeader.css";
+	@import "../../widget/templates/css/HtmlFeedViewer.css";
+	@import "../../widget/templates/css/HtmlFeedViewerGrouping.css";
+	@import "../../widget/templates/css/HtmlFeedViewerEntry.css";
+	@import "../../widget/templates/css/HtmlFeedEntryViewer.css";
+</style>
+<script type="text/javascript">
+  var djConfig = {isDebug: true, parseOnLoad: true};
+</script>
+<script type="text/javascript" src="../../../../dojo/dojo.js"></script>
+<script language="JavaScript" type="text/javascript">
+	dojo.require("dojox.atom.widget.FeedViewer");
+	dojo.require("dijit.layout.ContentPane");
+	dojo.require("dijit.layout.SplitContainer");
+	var feedViewer = null;
+	var feedPane = null;
+	var feedTitle = null;
+	var feedURI = "../widget/samplefeed.xml";
+	function init(){
+		feedViewer = dijit.byId("fv1");
+		feedPane = dijit.byId("feedPane");
+		feedTitle = dojo.byId("feedTitle");
+		dojo.connect(feedViewer,"onEntrySelected",function (entry){
+			feedTitle.textContent = entry.title.value;
+			if (entry.content)
+				feedPane.setContent(entry.content.toString());
+			else if(entry.summary)
+				feedPane.setContent(entry.summary.toString());
+		});
+	}
+	function feedHandler(feed,domNode){
+		feedViewer = dijit.byId("fv1");
+		feedViewer.setFeed(feed);
+	}
+	dojo.addOnLoad(init);
+</script>
+</head>
+<body>
+	<div> 
+		<div dojoType="dojox.atom.widget.FeedViewer" id="fv1" url="samplefeed.xml"></div>
+	</div>  
+	<div>  
+		<div id="feedTitle" style="font-size: large;font-weight: bold;"></div>  
+		<div dojoType="dijit.layout.ContentPane" id="feedPane"></div>
+	</div>
+</body>
+</html>
diff --git a/dojox/atom/tests/widget/test_FeedViewer_local_declarative.html b/dojox/atom/tests/widget/test_FeedViewer_local_declarative.html
new file mode 100644
index 0000000..8f9f945
--- /dev/null
+++ b/dojox/atom/tests/widget/test_FeedViewer_local_declarative.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Test the Feed Viewer (using ATOM)</title>
+<style type="text/css">
+	@import "../../widget/templates/css/EntryHeader.css";
+	@import "../../widget/templates/css/HtmlFeedViewer.css";
+	@import "../../widget/templates/css/HtmlFeedViewerGrouping.css";
+	@import "../../widget/templates/css/HtmlFeedViewerEntry.css";
+	@import "../../widget/templates/css/HtmlFeedEntryViewer.css";
+</style>
+<script type="text/javascript">
+  var djConfig = {isDebug: true, parseOnLoad: true};
+</script>
+<script type="text/javascript" src="../../../../dojo/dojo.js"></script>
+<script language="JavaScript" type="text/javascript">
+	dojo.require("dojox.atom.widget.FeedViewer");
+	dojo.require("dojox.atom.widget.FeedEntryViewer");
+	dojo.require("dijit.layout.ContentPane");
+	dojo.require("dijit.layout.SplitContainer");
+	
+</script>
+</head>
+<body>
+	<div> 
+		<div dojoType="dojox.atom.widget.FeedViewer" 
+			 widgetId="fv1"
+			 url="samplefeed.xml"
+			 entrySelectionTopic="atomfeed/entry/topic">
+		 </div>
+	</div>  
+	
+	<div dojoType="dojox.atom.widget.FeedEntryViewer" 
+		 widgetId="feedEditor"
+		 enableMenu="true"
+		 enableMenuFade="true"
+		 enableEdit="true"
+		 displayEntrySections="title,authors,summary"
+		 entrySelectionTopic="atomfeed/entry/topic">
+	</div>
+	
+</body>
+</html>
+
+
diff --git a/dojox/atom/widget/FeedEntryEditor.js b/dojox/atom/widget/FeedEntryEditor.js
index ff585f3..b4eb5fa 100644
--- a/dojox/atom/widget/FeedEntryEditor.js
+++ b/dojox/atom/widget/FeedEntryEditor.js
@@ -1,13 +1,5 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.atom.widget.FeedEntryEditor"]){
-dojo._hasResource["dojox.atom.widget.FeedEntryEditor"]=true;
 dojo.provide("dojox.atom.widget.FeedEntryEditor");
+
 dojo.require("dojox.atom.widget.FeedEntryViewer");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
@@ -15,721 +7,1213 @@ dojo.require("dijit._Container");
 dojo.require("dijit.Editor");
 dojo.require("dijit.form.TextBox");
 dojo.require("dijit.form.SimpleTextarea");
-dojo.requireLocalization("dojox.atom.widget","FeedEntryEditor",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.requireLocalization("dojox.atom.widget","PeopleEditor",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
+dojo.requireLocalization("dojox.atom.widget", "FeedEntryEditor");
+dojo.requireLocalization("dojox.atom.widget", "PeopleEditor");
+
 dojo.experimental("dojox.atom.widget.FeedEntryEditor");
-dojo.declare("dojox.atom.widget.FeedEntryEditor",dojox.atom.widget.FeedEntryViewer,{_contentEditor:null,_oldContent:null,_setObject:null,enableEdit:false,_contentEditorCreator:null,_editors:{},entryNewButton:null,_editable:false,templateString:dojo.cache("dojox.atom","widget/templates/FeedEntryEditor.html","<div class=\"feedEntryViewer\">\n    <table border=\"0\" width=\"100%\" class=\"feedEntryViewerMenuTable\" dojoAttachPoint=\"feedEntryViewerMenu\" style=\"display: none;\">\n        < [...]
-if(this.entrySelectionTopic!==""){
-this._subscriptions=[dojo.subscribe(this.entrySelectionTopic,this,"_handleEvent")];
-}
-var _1=dojo.i18n.getLocalization("dojox.atom.widget","FeedEntryViewer");
-this.displayOptions.innerHTML=_1.displayOptions;
-this.feedEntryCheckBoxLabelTitle.innerHTML=_1.title;
-this.feedEntryCheckBoxLabelAuthors.innerHTML=_1.authors;
-this.feedEntryCheckBoxLabelContributors.innerHTML=_1.contributors;
-this.feedEntryCheckBoxLabelId.innerHTML=_1.id;
-this.close.innerHTML=_1.close;
-this.feedEntryCheckBoxLabelUpdated.innerHTML=_1.updated;
-this.feedEntryCheckBoxLabelSummary.innerHTML=_1.summary;
-this.feedEntryCheckBoxLabelContent.innerHTML=_1.content;
-_1=dojo.i18n.getLocalization("dojox.atom.widget","FeedEntryEditor");
-this.doNew.innerHTML=_1.doNew;
-this.edit.innerHTML=_1.edit;
-this.save.innerHTML=_1.save;
-this.cancel.innerHTML=_1.cancel;
-},setEntry:function(_2,_3,_4){
-if(this._entry!==_2){
-this._editMode=false;
-_4=false;
-}else{
-_4=true;
-}
-dojox.atom.widget.FeedEntryEditor.superclass.setEntry.call(this,_2,_3);
-this._editable=this._isEditable(_2);
-if(!_4&&!this._editable){
-dojo.style(this.entryEditButton,"display","none");
-dojo.style(this.entrySaveCancelButtons,"display","none");
-}
-if(this._editable&&this.enableEdit){
-if(!_4){
-dojo.style(this.entryEditButton,"display","");
-if(this.enableMenuFade&&this.entrySaveCancelButton){
-dojo.fadeOut({node:this.entrySaveCancelButton,duration:250}).play();
-}
-}
-}
-},_toggleEdit:function(){
-if(this._editable&&this.enableEdit){
-dojo.style(this.entryEditButton,"display","none");
-dojo.style(this.entrySaveCancelButtons,"display","");
-this._editMode=true;
-this.setEntry(this._entry,this._feed,true);
-}
-},_handleEvent:function(_5){
-if(_5.source!=this&&_5.action=="delete"&&_5.entry&&_5.entry==this._entry){
-dojo.style(this.entryEditButton,"display","none");
-}
-dojox.atom.widget.FeedEntryEditor.superclass._handleEvent.call(this,_5);
-},_isEditable:function(_6){
-var _7=false;
-if(_6&&_6!==null&&_6.links&&_6.links!==null){
-for(var x in _6.links){
-if(_6.links[x].rel&&_6.links[x].rel=="edit"){
-_7=true;
-break;
-}
-}
-}
-return _7;
-},setTitle:function(_8,_9,_a){
-if(!_9){
-dojox.atom.widget.FeedEntryEditor.superclass.setTitle.call(this,_8,_9,_a);
-if(_a.title&&_a.title.value&&_a.title.value!==null){
-this.setFieldValidity("title",true);
-}
-}else{
-if(_a.title&&_a.title.value&&_a.title.value!==null){
-if(!this._toLoad){
-this._toLoad=[];
-}
-this.entryTitleSelect.value=_a.title.type;
-var _b=this._createEditor(_8,_a.title,true,_a.title.type==="html"||_a.title.type==="xhtml");
-_b.name="title";
-this._toLoad.push(_b);
-this.setFieldValidity("titleedit",true);
-this.setFieldValidity("title",true);
-}
-}
-},setAuthors:function(_c,_d,_e){
-if(!_d){
-dojox.atom.widget.FeedEntryEditor.superclass.setAuthors.call(this,_c,_d,_e);
-if(_e.authors&&_e.authors.length>0){
-this.setFieldValidity("authors",true);
-}
-}else{
-if(_e.authors&&_e.authors.length>0){
-this._editors.authors=this._createPeopleEditor(this.entryAuthorNode,{data:_e.authors,name:"Author"});
-this.setFieldValidity("authors",true);
-}
-}
-},setContributors:function(_f,_10,_11){
-if(!_10){
-dojox.atom.widget.FeedEntryEditor.superclass.setContributors.call(this,_f,_10,_11);
-if(_11.contributors&&_11.contributors.length>0){
-this.setFieldValidity("contributors",true);
-}
-}else{
-if(_11.contributors&&_11.contributors.length>0){
-this._editors.contributors=this._createPeopleEditor(this.entryContributorNode,{data:_11.contributors,name:"Contributor"});
-this.setFieldValidity("contributors",true);
-}
-}
-},setId:function(_12,_13,_14){
-if(!_13){
-dojox.atom.widget.FeedEntryEditor.superclass.setId.call(this,_12,_13,_14);
-if(_14.id&&_14.id!==null){
-this.setFieldValidity("id",true);
-}
-}else{
-if(_14.id&&_14.id!==null){
-this._editors.id=this._createEditor(_12,_14.id);
-this.setFieldValidity("id",true);
-}
-}
-},setUpdated:function(_15,_16,_17){
-if(!_16){
-dojox.atom.widget.FeedEntryEditor.superclass.setUpdated.call(this,_15,_16,_17);
-if(_17.updated&&_17.updated!==null){
-this.setFieldValidity("updated",true);
-}
-}else{
-if(_17.updated&&_17.updated!==null){
-this._editors.updated=this._createEditor(_15,_17.updated);
-this.setFieldValidity("updated",true);
-}
-}
-},setSummary:function(_18,_19,_1a){
-if(!_19){
-dojox.atom.widget.FeedEntryEditor.superclass.setSummary.call(this,_18,_19,_1a);
-if(_1a.summary&&_1a.summary.value&&_1a.summary.value!==null){
-this.setFieldValidity("summary",true);
-}
-}else{
-if(_1a.summary&&_1a.summary.value&&_1a.summary.value!==null){
-if(!this._toLoad){
-this._toLoad=[];
-}
-this.entrySummarySelect.value=_1a.summary.type;
-var _1b=this._createEditor(_18,_1a.summary,true,_1a.summary.type==="html"||_1a.summary.type==="xhtml");
-_1b.name="summary";
-this._toLoad.push(_1b);
-this.setFieldValidity("summaryedit",true);
-this.setFieldValidity("summary",true);
-}
-}
-},setContent:function(_1c,_1d,_1e){
-if(!_1d){
-dojox.atom.widget.FeedEntryEditor.superclass.setContent.call(this,_1c,_1d,_1e);
-if(_1e.content&&_1e.content.value&&_1e.content.value!==null){
-this.setFieldValidity("content",true);
-}
-}else{
-if(_1e.content&&_1e.content.value&&_1e.content.value!==null){
-if(!this._toLoad){
-this._toLoad=[];
-}
-this.entryContentSelect.value=_1e.content.type;
-var _1f=this._createEditor(_1c,_1e.content,true,_1e.content.type==="html"||_1e.content.type==="xhtml");
-_1f.name="content";
-this._toLoad.push(_1f);
-this.setFieldValidity("contentedit",true);
-this.setFieldValidity("content",true);
-}
-}
-},_createEditor:function(_20,_21,_22,rte){
-var _23;
-var box;
-if(!_21){
-if(rte){
-return {anchorNode:_20,entryValue:"",editor:null,generateEditor:function(){
-var _24=document.createElement("div");
-_24.innerHTML=this.entryValue;
-this.anchorNode.appendChild(_24);
-var _25=new dijit.Editor({},_24);
-this.editor=_25;
-return _25;
-}};
-}
-if(_22){
-_23=document.createElement("textarea");
-_20.appendChild(_23);
-dojo.style(_23,"width","90%");
-box=new dijit.form.SimpleTextarea({},_23);
-}else{
-_23=document.createElement("input");
-_20.appendChild(_23);
-dojo.style(_23,"width","95%");
-box=new dijit.form.TextBox({},_23);
-}
-box.attr("value","");
-return box;
-}
-var _26;
-if(_21.value!==undefined){
-_26=_21.value;
-}else{
-if(_21.attr){
-_26=_21.attr("value");
-}else{
-_26=_21;
-}
-}
-if(rte){
-if(_26.indexOf("<")!=-1){
-_26=_26.replace(/</g,"<");
-}
-return {anchorNode:_20,entryValue:_26,editor:null,generateEditor:function(){
-var _27=document.createElement("div");
-_27.innerHTML=this.entryValue;
-this.anchorNode.appendChild(_27);
-var _28=new dijit.Editor({},_27);
-this.editor=_28;
-return _28;
-}};
-}
-if(_22){
-_23=document.createElement("textarea");
-_20.appendChild(_23);
-dojo.style(_23,"width","90%");
-box=new dijit.form.SimpleTextarea({},_23);
-}else{
-_23=document.createElement("input");
-_20.appendChild(_23);
-dojo.style(_23,"width","95%");
-box=new dijit.form.TextBox({},_23);
-}
-box.attr("value",_26);
-return box;
-},_switchEditor:function(_29){
-var _2a=null;
-var _2b=null;
-var _2c=null;
-if(dojo.isIE){
-_2b=_29.srcElement;
-}else{
-_2b=_29.target;
-}
-if(_2b===this.entryTitleSelect){
-_2c=this.entryTitleNode;
-_2a="title";
-}else{
-if(_2b===this.entrySummarySelect){
-_2c=this.entrySummaryNode;
-_2a="summary";
-}else{
-_2c=this.entryContentNode;
-_2a="content";
-}
-}
-var _2d=this._editors[_2a];
-var _2e;
-var _2f;
-if(_2b.value==="text"){
-if(_2d.declaredClass==="dijit.Editor"){
-_2f=_2d.attr("value",false);
-_2d.close(false,true);
-_2d.destroy();
-while(_2c.firstChild){
-dojo.destroy(_2c.firstChild);
-}
-_2e=this._createEditor(_2c,{value:_2f},true,false);
-this._editors[_2a]=_2e;
-}
-}else{
-if(_2d.declaredClass!="dijit.Editor"){
-_2f=_2d.attr("value");
-_2d.destroy();
-while(_2c.firstChild){
-dojo.destroy(_2c.firstChild);
-}
-_2e=this._createEditor(_2c,{value:_2f},true,true);
-_2e=dojo.hitch(_2e,_2e.generateEditor)();
-this._editors[_2a]=_2e;
-}
-}
-},_createPeopleEditor:function(_30,_31){
-var _32=document.createElement("div");
-_30.appendChild(_32);
-return new dojox.atom.widget.PeopleEditor(_31,_32);
-},saveEdits:function(){
-dojo.style(this.entrySaveCancelButtons,"display","none");
-dojo.style(this.entryEditButton,"display","");
-dojo.style(this.entryNewButton,"display","");
-var _33=false;
-var _34;
-var i;
-var _35;
-var _36;
-var _37;
-var _38;
-if(!this._new){
-_36=this.getEntry();
-if(this._editors.title&&(this._editors.title.attr("value")!=_36.title.value||this.entryTitleSelect.value!=_36.title.type)){
-_34=this._editors.title.attr("value");
-if(this.entryTitleSelect.value==="xhtml"){
-_34=this._enforceXhtml(_34);
-if(_34.indexOf("<div xmlns=\"http://www.w3.org/1999/xhtml\">")!==0){
-_34="<div xmlns=\"http://www.w3.org/1999/xhtml\">"+_34+"</div>";
-}
-}
-_36.title=new dojox.atom.io.model.Content("title",_34,null,this.entryTitleSelect.value);
-_33=true;
-}
-if(this._editors.id.attr("value")!=_36.id){
-_36.id=this._editors.id.attr("value");
-_33=true;
-}
-if(this._editors.summary&&(this._editors.summary.attr("value")!=_36.summary.value||this.entrySummarySelect.value!=_36.summary.type)){
-_34=this._editors.summary.attr("value");
-if(this.entrySummarySelect.value==="xhtml"){
-_34=this._enforceXhtml(_34);
-if(_34.indexOf("<div xmlns=\"http://www.w3.org/1999/xhtml\">")!==0){
-_34="<div xmlns=\"http://www.w3.org/1999/xhtml\">"+_34+"</div>";
-}
-}
-_36.summary=new dojox.atom.io.model.Content("summary",_34,null,this.entrySummarySelect.value);
-_33=true;
-}
-if(this._editors.content&&(this._editors.content.attr("value")!=_36.content.value||this.entryContentSelect.value!=_36.content.type)){
-_34=this._editors.content.attr("value");
-if(this.entryContentSelect.value==="xhtml"){
-_34=this._enforceXhtml(_34);
-if(_34.indexOf("<div xmlns=\"http://www.w3.org/1999/xhtml\">")!==0){
-_34="<div xmlns=\"http://www.w3.org/1999/xhtml\">"+_34+"</div>";
-}
-}
-_36.content=new dojox.atom.io.model.Content("content",_34,null,this.entryContentSelect.value);
-_33=true;
-}
-if(this._editors.authors){
-if(_33){
-_36.authors=[];
-_37=this._editors.authors.getValues();
-for(i in _37){
-if(_37[i].name||_37[i].email||_37[i].uri){
-_36.addAuthor(_37[i].name,_37[i].email,_37[i].uri);
-}
-}
-}else{
-var _39=_36.authors;
-var _3a=function(_3b,_3c,uri){
-for(i in _39){
-if(_39[i].name===_3b&&_39[i].email===_3c&&_39[i].uri===uri){
-return true;
-}
-}
-return false;
-};
-_37=this._editors.authors.getValues();
-_35=false;
-for(i in _37){
-if(!_3a(_37[i].name,_37[i].email,_37[i].uri)){
-_35=true;
-break;
-}
-}
-if(_35){
-_36.authors=[];
-for(i in _37){
-if(_37[i].name||_37[i].email||_37[i].uri){
-_36.addAuthor(_37[i].name,_37[i].email,_37[i].uri);
-}
-}
-_33=true;
-}
-}
-}
-if(this._editors.contributors){
-if(_33){
-_36.contributors=[];
-_38=this._editors.contributors.getValues();
-for(i in _38){
-if(_38[i].name||_38[i].email||_38[i].uri){
-_36.addAuthor(_38[i].name,_38[i].email,_38[i].uri);
-}
-}
-}else{
-var _3d=_36.contributors;
-var _3e=function(_3f,_40,uri){
-for(i in _3d){
-if(_3d[i].name===_3f&&_3d[i].email===_40&&_3d[i].uri===uri){
-return true;
-}
-}
-return false;
-};
-_38=this._editors.contributors.getValues();
-_35=false;
-for(i in _38){
-if(_3e(_38[i].name,_38[i].email,_38[i].uri)){
-_35=true;
-break;
-}
-}
-if(_35){
-_36.contributors=[];
-for(i in _38){
-if(_38[i].name||_38[i].email||_38[i].uri){
-_36.addContributor(_38[i].name,_38[i].email,_38[i].uri);
-}
-}
-_33=true;
-}
-}
-}
-if(_33){
-dojo.publish(this.entrySelectionTopic,[{action:"update",source:this,entry:_36,callback:this._handleSave}]);
-}
-}else{
-this._new=false;
-_36=new dojox.atom.io.model.Entry();
-_34=this._editors.title.attr("value");
-if(this.entryTitleSelect.value==="xhtml"){
-_34=this._enforceXhtml(_34);
-_34="<div xmlns=\"http://www.w3.org/1999/xhtml\">"+_34+"</div>";
-}
-_36.setTitle(_34,this.entryTitleSelect.value);
-_36.id=this._editors.id.attr("value");
-_37=this._editors.authors.getValues();
-for(i in _37){
-if(_37[i].name||_37[i].email||_37[i].uri){
-_36.addAuthor(_37[i].name,_37[i].email,_37[i].uri);
-}
-}
-_38=this._editors.contributors.getValues();
-for(i in _38){
-if(_38[i].name||_38[i].email||_38[i].uri){
-_36.addContributor(_38[i].name,_38[i].email,_38[i].uri);
-}
-}
-_34=this._editors.summary.attr("value");
-if(this.entrySummarySelect.value==="xhtml"){
-_34=this._enforceXhtml(_34);
-_34="<div xmlns=\"http://www.w3.org/1999/xhtml\">"+_34+"</div>";
-}
-_36.summary=new dojox.atom.io.model.Content("summary",_34,null,this.entrySummarySelect.value);
-_34=this._editors.content.attr("value");
-if(this.entryContentSelect.value==="xhtml"){
-_34=this._enforceXhtml(_34);
-_34="<div xmlns=\"http://www.w3.org/1999/xhtml\">"+_34+"</div>";
-}
-_36.content=new dojox.atom.io.model.Content("content",_34,null,this.entryContentSelect.value);
-dojo.style(this.entryNewButton,"display","");
-dojo.publish(this.entrySelectionTopic,[{action:"post",source:this,entry:_36}]);
-}
-this._editMode=false;
-this.setEntry(_36,this._feed,true);
-},_handleSave:function(_41,_42){
-this._editMode=false;
-this.clear();
-this.setEntry(_41,this.getFeed(),true);
-},cancelEdits:function(){
-this._new=false;
-dojo.style(this.entrySaveCancelButtons,"display","none");
-if(this._editable){
-dojo.style(this.entryEditButton,"display","");
-}
-dojo.style(this.entryNewButton,"display","");
-this._editMode=false;
-this.clearEditors();
-this.setEntry(this.getEntry(),this.getFeed(),true);
-},clear:function(){
-this._editable=false;
-this.clearEditors();
-dojox.atom.widget.FeedEntryEditor.superclass.clear.apply(this);
-if(this._contentEditor){
-this._contentEditor=this._setObject=this._oldContent=this._contentEditorCreator=null;
-this._editors={};
-}
-},clearEditors:function(){
-for(var key in this._editors){
-if(this._editors[key].declaredClass==="dijit.Editor"){
-this._editors[key].close(false,true);
-}
-this._editors[key].destroy();
-}
-this._editors={};
-},_enforceXhtml:function(_43){
-var _44=null;
-if(_43){
-var _45=/<br>/g;
-_44=_43.replace(_45,"<br/>");
-_44=this._closeTag(_44,"hr");
-_44=this._closeTag(_44,"img");
-}
-return _44;
-},_closeTag:function(_46,tag){
-var _47="<"+tag;
-var _48=_46.indexOf(_47);
-if(_48!==-1){
-while(_48!==-1){
-var _49="";
-var _4a=false;
-for(var i=0;i<_46.length;i++){
-var c=_46.charAt(i);
-if(i<=_48||_4a){
-_49+=c;
-}else{
-if(c===">"){
-_49+="/";
-_4a=true;
-}
-_49+=c;
-}
-}
-_46=_49;
-_48=_46.indexOf(_47,_48+1);
-}
-}
-return _46;
-},_toggleNew:function(){
-dojo.style(this.entryNewButton,"display","none");
-dojo.style(this.entryEditButton,"display","none");
-dojo.style(this.entrySaveCancelButtons,"display","");
-this.entrySummarySelect.value="text";
-this.entryContentSelect.value="text";
-this.entryTitleSelect.value="text";
-this.clearNodes();
-this._new=true;
-var _4b=dojo.i18n.getLocalization("dojox.atom.widget","FeedEntryViewer");
-var _4c=new dojox.atom.widget.EntryHeader({title:_4b.title});
-this.entryTitleHeader.appendChild(_4c.domNode);
-this._editors.title=this._createEditor(this.entryTitleNode,null);
-this.setFieldValidity("title",true);
-var _4d=new dojox.atom.widget.EntryHeader({title:_4b.authors});
-this.entryAuthorHeader.appendChild(_4d.domNode);
-this._editors.authors=this._createPeopleEditor(this.entryAuthorNode,{name:"Author"});
-this.setFieldValidity("authors",true);
-var _4e=new dojox.atom.widget.EntryHeader({title:_4b.contributors});
-this.entryContributorHeader.appendChild(_4e.domNode);
-this._editors.contributors=this._createPeopleEditor(this.entryContributorNode,{name:"Contributor"});
-this.setFieldValidity("contributors",true);
-var _4f=new dojox.atom.widget.EntryHeader({title:_4b.id});
-this.entryIdHeader.appendChild(_4f.domNode);
-this._editors.id=this._createEditor(this.entryIdNode,null);
-this.setFieldValidity("id",true);
-var _50=new dojox.atom.widget.EntryHeader({title:_4b.updated});
-this.entryUpdatedHeader.appendChild(_50.domNode);
-this._editors.updated=this._createEditor(this.entryUpdatedNode,null);
-this.setFieldValidity("updated",true);
-var _51=new dojox.atom.widget.EntryHeader({title:_4b.summary});
-this.entrySummaryHeader.appendChild(_51.domNode);
-this._editors.summary=this._createEditor(this.entrySummaryNode,null,true);
-this.setFieldValidity("summaryedit",true);
-this.setFieldValidity("summary",true);
-var _52=new dojox.atom.widget.EntryHeader({title:_4b.content});
-this.entryContentHeader.appendChild(_52.domNode);
-this._editors.content=this._createEditor(this.entryContentNode,null,true);
-this.setFieldValidity("contentedit",true);
-this.setFieldValidity("content",true);
-this._displaySections();
-},_displaySections:function(){
-dojo.style(this.entrySummarySelect,"display","none");
-dojo.style(this.entryContentSelect,"display","none");
-dojo.style(this.entryTitleSelect,"display","none");
-if(this.isFieldValid("contentedit")){
-dojo.style(this.entryContentSelect,"display","");
-}
-if(this.isFieldValid("summaryedit")){
-dojo.style(this.entrySummarySelect,"display","");
-}
-if(this.isFieldValid("titleedit")){
-dojo.style(this.entryTitleSelect,"display","");
-}
-dojox.atom.widget.FeedEntryEditor.superclass._displaySections.apply(this);
-if(this._toLoad){
-for(var i in this._toLoad){
-var _53;
-if(this._toLoad[i].generateEditor){
-_53=dojo.hitch(this._toLoad[i],this._toLoad[i].generateEditor)();
-}else{
-_53=this._toLoad[i];
-}
-this._editors[this._toLoad[i].name]=_53;
-this._toLoad[i]=null;
-}
-this._toLoad=null;
-}
-}});
-dojo.declare("dojox.atom.widget.PeopleEditor",[dijit._Widget,dijit._Templated,dijit._Container],{templateString:dojo.cache("dojox.atom","widget/templates/PeopleEditor.html","<div class=\"peopleEditor\">\n\t<table style=\"width: 100%\">\n\t\t<tbody dojoAttachPoint=\"peopleEditorEditors\"></tbody>\n\t</table>\n\t<span class=\"peopleEditorButton\" dojoAttachPoint=\"peopleEditorButton\" dojoAttachEvent=\"onclick:_add\"></span>\n</div>\n"),_rows:[],_editors:[],_index:0,_numRows:0,postCreate:f [...]
-var _54=dojo.i18n.getLocalization("dojox.atom.widget","PeopleEditor");
-if(this.name){
-if(this.name=="Author"){
-this.peopleEditorButton.appendChild(document.createTextNode("["+_54.addAuthor+"]"));
-}else{
-if(this.name=="Contributor"){
-this.peopleEditorButton.appendChild(document.createTextNode("["+_54.addContributor+"]"));
-}
-}
-}else{
-this.peopleEditorButton.appendChild(document.createTextNode("["+_54.add+"]"));
-}
-this._editors=[];
-if(!this.data||this.data.length===0){
-this._createEditors(null,null,null,0,this.name);
-this._index=1;
-}else{
-for(var i in this.data){
-this._createEditors(this.data[i].name,this.data[i].email,this.data[i].uri,i);
-this._index++;
-this._numRows++;
-}
-}
-},destroy:function(){
-for(var key in this._editors){
-for(var _55 in this._editors[key]){
-this._editors[key][_55].destroy();
-}
-}
-this._editors=[];
-},_createEditors:function(_56,_57,uri,_58,_59){
-var row=document.createElement("tr");
-this.peopleEditorEditors.appendChild(row);
-row.id="removeRow"+_58;
-var _5a=document.createElement("td");
-_5a.setAttribute("align","right");
-row.appendChild(_5a);
-_5a.colSpan=2;
-if(this._numRows>0){
-var hr=document.createElement("hr");
-_5a.appendChild(hr);
-hr.id="hr"+_58;
-}
-row=document.createElement("span");
-_5a.appendChild(row);
-row.className="peopleEditorButton";
-dojo.style(row,"font-size","x-small");
-dojo.connect(row,"onclick",this,"_removeEditor");
-row.id="remove"+_58;
-_5a=document.createTextNode("[X]");
-row.appendChild(_5a);
-row=document.createElement("tr");
-this.peopleEditorEditors.appendChild(row);
-row.id="editorsRow"+_58;
-var _5b=document.createElement("td");
-row.appendChild(_5b);
-dojo.style(_5b,"width","20%");
-_5a=document.createElement("td");
-row.appendChild(_5a);
-row=document.createElement("table");
-_5b.appendChild(row);
-dojo.style(row,"width","100%");
-_5b=document.createElement("tbody");
-row.appendChild(_5b);
-row=document.createElement("table");
-_5a.appendChild(row);
-dojo.style(row,"width","100%");
-_5a=document.createElement("tbody");
-row.appendChild(_5a);
-this._editors[_58]=[];
-this._editors[_58].push(this._createEditor(_56,_59+"name"+_58,"Name:",_5b,_5a));
-this._editors[_58].push(this._createEditor(_57,_59+"email"+_58,"Email:",_5b,_5a));
-this._editors[_58].push(this._createEditor(uri,_59+"uri"+_58,"URI:",_5b,_5a));
-},_createEditor:function(_5c,id,_5d,_5e,_5f){
-var row=document.createElement("tr");
-_5e.appendChild(row);
-var _60=document.createElement("label");
-_60.setAttribute("for",id);
-_60.appendChild(document.createTextNode(_5d));
-_5e=document.createElement("td");
-_5e.appendChild(_60);
-row.appendChild(_5e);
-row=document.createElement("tr");
-_5f.appendChild(row);
-_5f=document.createElement("td");
-row.appendChild(_5f);
-var _61=document.createElement("input");
-_61.setAttribute("id",id);
-_5f.appendChild(_61);
-dojo.style(_61,"width","95%");
-var box=new dijit.form.TextBox({},_61);
-box.attr("value",_5c);
-return box;
-},_removeEditor:function(_62){
-var _63=null;
-if(dojo.isIE){
-_63=_62.srcElement;
-}else{
-_63=_62.target;
-}
-var id=_63.id;
-id=id.substring(6);
-for(var key in this._editors[id]){
-this._editors[id][key].destroy();
-}
-var _64=dojo.byId("editorsRow"+id);
-var _65=_64.parentNode;
-_65.removeChild(_64);
-_64=dojo.byId("removeRow"+id);
-_65=_64.parentNode;
-_65.removeChild(_64);
-this._numRows--;
-if(this._numRows===1&&_65.firstChild.firstChild.firstChild.tagName.toLowerCase()==="hr"){
-_64=_65.firstChild.firstChild;
-_64.removeChild(_64.firstChild);
-}
-this._editors[id]=null;
-},_add:function(){
-this._createEditors(null,null,null,this._index);
-this._index++;
-this._numRows++;
-},getValues:function(){
-var _66=[];
-for(var i in this._editors){
-if(this._editors[i]){
-_66.push({name:this._editors[i][0].attr("value"),email:this._editors[i][1].attr("value"),uri:this._editors[i][2].attr("value")});
-}
-}
-return _66;
-}});
-}
+
+dojo.declare("dojox.atom.widget.FeedEntryEditor",dojox.atom.widget.FeedEntryViewer,{
+	//	summary:  
+	//		An ATOM feed entry editor that allows viewing of the individual attributes of an entry.
+	//	description:  
+	//		An ATOM feed entry editor that allows viewing of the individual attributes of an entry.
+	_contentEditor: null,
+	_oldContent: null,
+	_setObject: null,
+	enableEdit: false,
+	_contentEditorCreator: null,
+	_editors: {},
+	entryNewButton: null,
+	_editable: false,		//Flag denoting if the current entry is editable or not.
+
+	//Templates for the HTML rendering.  Need to figure these out better, admittedly.
+	templateString: dojo.cache("dojox.atom", "widget/templates/FeedEntryEditor.html"),
+
+	postCreate: function(){
+		if(this.entrySelectionTopic !== ""){
+			this._subscriptions = [dojo.subscribe(this.entrySelectionTopic, this, "_handleEvent")];
+		}
+		var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedEntryViewer");
+		this.displayOptions.innerHTML = _nlsResources.displayOptions;
+		this.feedEntryCheckBoxLabelTitle.innerHTML = _nlsResources.title;
+		this.feedEntryCheckBoxLabelAuthors.innerHTML = _nlsResources.authors;
+		this.feedEntryCheckBoxLabelContributors.innerHTML = _nlsResources.contributors;
+		this.feedEntryCheckBoxLabelId.innerHTML = _nlsResources.id;
+		this.close.innerHTML = _nlsResources.close;
+		this.feedEntryCheckBoxLabelUpdated.innerHTML = _nlsResources.updated;
+		this.feedEntryCheckBoxLabelSummary.innerHTML = _nlsResources.summary;
+		this.feedEntryCheckBoxLabelContent.innerHTML = _nlsResources.content;
+
+		_nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedEntryEditor");
+		this.doNew.innerHTML = _nlsResources.doNew;
+		this.edit.innerHTML = _nlsResources.edit;
+		this.save.innerHTML = _nlsResources.save;
+		this.cancel.innerHTML = _nlsResources.cancel;
+	},
+	
+	setEntry: function(/*object*/entry, /*object*/feed, /*boolean*/leaveMenuState){
+		//	summary:  
+		//		Function to set the current entry that is being edited.
+		//	description:
+		//		Function to set the current entry that is being edited.
+		//
+		//	entry: 
+		//		Instance of dojox.atom.io.model.Entry to display for reading/editing.
+		if(this._entry !== entry){
+			//If we swap entries, we don't want to keep the menu states and modes.
+			this._editMode=false;
+			leaveMenuState=false;
+		}else{
+			leaveMenuState = true;
+		}
+		dojox.atom.widget.FeedEntryEditor.superclass.setEntry.call(this, entry, feed);
+		this._editable = this._isEditable(entry);
+		if(!leaveMenuState && !this._editable){
+			dojo.style(this.entryEditButton, 'display', 'none');
+			dojo.style(this.entrySaveCancelButtons, 'display', 'none');
+		}
+		if(this._editable && this.enableEdit){
+			if(!leaveMenuState){
+				dojo.style(this.entryEditButton, 'display', '');
+				//TODO double check this &&...
+				if(this.enableMenuFade && this.entrySaveCancelButton){
+					dojo.fadeOut({node: this.entrySaveCancelButton,duration: 250}).play();
+				}
+			}
+		}
+	},
+
+	_toggleEdit: function(){
+		//	summary: 
+		//		Internal function for toggling/enabling the display of edit mode
+		//	description: 
+		//		Internal function for toggling/enabling the display of edit mode
+		//
+		//	returns:  
+		//		Nothing.
+		if(this._editable && this.enableEdit){
+			dojo.style(this.entryEditButton, 'display', 'none');
+			dojo.style(this.entrySaveCancelButtons, 'display', '');
+			this._editMode = true;
+
+			//Rebuild the view using the same entry and feed.
+			this.setEntry(this._entry, this._feed, true);
+		}
+	},
+
+	_handleEvent: function(/*object*/entrySelectionEvent){
+		//	summary: 
+		//		Internal function for listening to a topic that will handle entry notification.
+		//	description:
+		//		Internal function for listening to a topic that will handle entry notification.
+		//
+		//	entrySelectionEvent: 
+		//		The topic message containing the entry that was selected for view.
+		//
+		//	returns:  
+		//		Nothing.
+		if(entrySelectionEvent.source != this && entrySelectionEvent.action == "delete" && 
+			entrySelectionEvent.entry && entrySelectionEvent.entry == this._entry){
+				dojo.style(this.entryEditButton, 'display', 'none');
+		}
+		dojox.atom.widget.FeedEntryEditor.superclass._handleEvent.call(this, entrySelectionEvent);
+	},
+
+	_isEditable: function(/*object*/entry){
+		//	summary: 
+		//		Internal function for determining of a particular entry is editable.
+		//	description:
+		//		Internal function for determining of a particular entry is editable.
+		//		This is used for determining if the delete action should be displayed or not.
+		//
+		//	entry:
+		//		The dojox.atom.io.model.Entry object to examine
+		//
+		//	returns:
+		//		Boolean denoting if the entry seems editable or not.. 
+		var retVal = false;
+		if(entry && entry !== null && entry.links && entry.links !== null){
+			for(var x in entry.links){
+				if(entry.links[x].rel && entry.links[x].rel == "edit"){
+					retVal = true;
+					break;
+				}
+			}
+		}
+		return retVal;
+	},
+	
+	// The following set<Attribute> functions override the corresponding functions in FeedEntryViewer.  These handle
+	// the editMode flag by inserting appropriate editor widgets inside of just splashing the content in the page.
+	setTitle: function(/*DOM node*/titleAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:  
+		//		Function to set the contents of the title node in the template to some value from the entry.
+		//	description: 
+		//		Function to set the contents of the title node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	titleAnchorNode:
+		//		The DOM node to attach the title data to.
+		//	editMode:
+		// 		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		//
+		if(!editMode){
+			dojox.atom.widget.FeedEntryEditor.superclass.setTitle.call(this, titleAnchorNode, editMode, entry);
+			if(entry.title && entry.title.value && entry.title.value !== null){
+				this.setFieldValidity("title", true);
+			}
+		}else{
+			if(entry.title && entry.title.value && entry.title.value !== null){
+				if(!this._toLoad){
+					this._toLoad = [];
+				}
+				this.entryTitleSelect.value = entry.title.type;
+				
+				var editor = this._createEditor(titleAnchorNode, entry.title, true, entry.title.type === "html" || entry.title.type === "xhtml");
+				editor.name = "title";
+				this._toLoad.push(editor);
+				this.setFieldValidity("titleedit",true);
+				this.setFieldValidity("title",true);
+			}
+		}
+	},
+
+	setAuthors: function(/*DOM node*/authorsAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:  
+		//		Function to set the contents of the author node in the template to some value from the entry.
+		//	description: 
+		//		Function to set the contents of the author node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	authorsAnchorNode:
+		//		The DOM node to attach the author data to.
+		//	editMode: 
+		// 		Boolean to indicate if the display should be in edit mode or not.
+		//	entry: 
+		// 		The Feed Entry to work with.
+		if(!editMode){
+			dojox.atom.widget.FeedEntryEditor.superclass.setAuthors.call(this, authorsAnchorNode, editMode, entry);
+			if(entry.authors && entry.authors.length > 0){
+				this.setFieldValidity("authors", true);
+			}
+		}else{
+			if(entry.authors && entry.authors.length > 0){
+				this._editors.authors = this._createPeopleEditor(this.entryAuthorNode, {data: entry.authors, name: "Author"});
+				this.setFieldValidity("authors", true);
+			}
+		}
+	},
+
+
+	setContributors: function(/*DOM node*/contributorsAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:  
+		//		Function to set the contents of the contributor node in the template to some value from the entry.
+		//	description: 
+		//		Function to set the contents of the contributor node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	contributorsAnchorNode:
+		//		The DOM node to attach the contributor data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(!editMode){
+			dojox.atom.widget.FeedEntryEditor.superclass.setContributors.call(this, contributorsAnchorNode, editMode, entry);
+			if(entry.contributors && entry.contributors.length > 0){
+				this.setFieldValidity("contributors", true);
+			}
+		}else{
+			if(entry.contributors && entry.contributors.length > 0){
+				this._editors.contributors = this._createPeopleEditor(this.entryContributorNode, {data: entry.contributors, name: "Contributor"});
+				this.setFieldValidity("contributors", true);
+			}
+		}
+	},
+
+
+	setId: function(/*DOM node*/idAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:  
+		//		Function to set the contents of the ID  node in the template to some value from the entry.
+		//	description: 
+		//		Function to set the contents of the ID node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	idAnchorNode:
+		//		The DOM node to attach the ID data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(!editMode){
+			dojox.atom.widget.FeedEntryEditor.superclass.setId.call(this, idAnchorNode, editMode, entry);
+			if(entry.id && entry.id !== null){
+				this.setFieldValidity("id", true);
+			}
+		}else{
+			if(entry.id && entry.id !== null){
+				this._editors.id = this._createEditor(idAnchorNode, entry.id);
+				this.setFieldValidity("id",true);
+			}
+		}
+	},
+
+	setUpdated: function(/*DOM node*/updatedAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:  
+		//		Function to set the contents of the updated  node in the template to some value from the entry.
+		//	description: 
+		//		Function to set the contents of the updated node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	updatedAnchorNode:
+		//		The DOM node to attach the udpated data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(!editMode){
+			dojox.atom.widget.FeedEntryEditor.superclass.setUpdated.call(this, updatedAnchorNode, editMode, entry);
+			if(entry.updated && entry.updated !== null){
+				this.setFieldValidity("updated", true);
+			}
+		}else{
+			if(entry.updated && entry.updated !== null){
+				this._editors.updated = this._createEditor(updatedAnchorNode, entry.updated);
+				this.setFieldValidity("updated",true);
+			}
+		}
+	},
+
+
+	setSummary: function(/*DOM node*/summaryAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:  
+		//		Function to set the contents of the summary  node in the template to some value from the entry.
+		//	description: 
+		//		Function to set the contents of the summary node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	summaryAnchorNode:
+		//		The DOM node to attach the summary data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(!editMode){
+			dojox.atom.widget.FeedEntryEditor.superclass.setSummary.call(this, summaryAnchorNode, editMode, entry);
+			if(entry.summary && entry.summary.value && entry.summary.value !== null){
+				this.setFieldValidity("summary", true);
+			}
+		}else{
+			if(entry.summary && entry.summary.value && entry.summary.value !== null){
+				if(!this._toLoad){
+					this._toLoad = [];
+				}
+				this.entrySummarySelect.value = entry.summary.type;
+				
+				var editor = this._createEditor(summaryAnchorNode, entry.summary, true, entry.summary.type === "html" || entry.summary.type === "xhtml");
+				editor.name = "summary";
+				this._toLoad.push(editor);
+				this.setFieldValidity("summaryedit",true);
+				this.setFieldValidity("summary",true);
+			}
+		}
+	},
+
+	setContent: function(/*DOM node*/contentAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:  
+		//		Function to set the contents of the content node in the template to some value from the entry.
+		//	description: 
+		//		Function to set the contents of the content node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	summaryAnchorNode:
+		//		The DOM node to attach the content data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		// 	entry: 
+		//		The Feed Entry to work with.
+		if(!editMode){
+			dojox.atom.widget.FeedEntryEditor.superclass.setContent.call(this, contentAnchorNode, editMode, entry);
+			if(entry.content && entry.content.value && entry.content.value !== null){
+				this.setFieldValidity("content",true);
+			}
+		}else{
+			if(entry.content && entry.content.value && entry.content.value !== null){
+				if(!this._toLoad){
+					this._toLoad = [];
+				}
+				this.entryContentSelect.value = entry.content.type;
+				var editor = this._createEditor(contentAnchorNode, entry.content, true, entry.content.type === "html" || entry.content.type === "xhtml");
+				editor.name = "content";
+				this._toLoad.push(editor);
+				this.setFieldValidity("contentedit",true);
+				this.setFieldValidity("content",true);
+			}
+		}
+	},
+	
+	_createEditor: function(/*DOM node*/anchorNode, /*DOM node*/node, /*boolean*/multiline, /*object*/rte){
+		//	summary:  
+		//		Function to create an appropriate text editor widget based on the given parameters.
+		//	description: 
+		//		Function to create an appropriate text editor widget based on the given parameters.
+		//
+		//	anchorNode:
+		//		The DOM node to attach the editor widget to.
+		//	node: 
+		//		An object containing the value to be put into the editor.  This ranges from an anonymous object
+		//		with a value parameter to a dojox.atom.io.model.Content object.
+		//	multiline:
+		//		A boolean indicating whether the content should be multiline (such as a textarea) instead of a 
+		//		single line (such as a textbox).
+		//	rte:
+		//		A boolean indicating whether the content should be a rich text editor widget.
+		//
+		//	returns:
+		//		Either a widget (for textarea or textbox widgets) or an anonymous object to be used to create a 
+		//		rich text area widget.
+		var viewNode;
+		var box;
+		if(!node){
+			if(rte){
+				// Returns an anonymous object which would then be loaded later, after the containing element 
+				// exists on the page.
+				return {anchorNode: anchorNode,
+						entryValue: "",
+						editor: null,
+						generateEditor: function(){
+							// The only way I found I could get the editor to behave consistently was to 
+							// create the content on a span, and allow the content editor to replace it.  
+							// This gets around the dynamic/delayed way in which content editors get created.
+							var node = document.createElement("div");
+							node.innerHTML = this.entryValue;
+							this.anchorNode.appendChild(node);
+							var _editor = new dijit.Editor({}, node);
+							this.editor = _editor;
+							return _editor;
+						} 
+				};
+			}
+			if(multiline){
+				// If multiline, create a textarea
+				viewNode = document.createElement("textarea");
+				anchorNode.appendChild(viewNode);
+				dojo.style(viewNode, 'width', '90%');
+				box = new dijit.form.SimpleTextarea({},viewNode);
+			}else{
+				// If single line, create a textbox.
+				viewNode = document.createElement("input");
+				anchorNode.appendChild(viewNode);
+				dojo.style(viewNode, 'width', '95%');
+				box = new dijit.form.TextBox({},viewNode);
+			}
+			box.attr('value', '');
+			return box;
+		}
+
+		// Check through the node parameter to get the value to be used.
+		var value;
+		if(node.value !== undefined){
+			value = node.value;
+		}else if(node.attr){
+			value = node.attr('value');
+		}else{
+			value = node;
+		}
+		if(rte){
+			// Returns an anonymous object which would then be loaded later, after the containing element 
+			// exists on the page.
+			if(value.indexOf("<") != -1){
+				value = value.replace(/</g, "<");
+			}
+			return {anchorNode: anchorNode,
+					entryValue: value,
+					editor: null,
+					generateEditor: function(){
+						// The only way I found I could get the editor to behave consistently was to 
+						// create the content on a span, and allow the content editor to replace it.  
+						// This gets around the dynamic/delayed way in which content editors get created.
+						var node = document.createElement("div");
+						node.innerHTML = this.entryValue;
+						this.anchorNode.appendChild(node);
+						var _editor = new dijit.Editor({}, node);
+						this.editor = _editor;
+						return _editor;
+					}
+			};
+		}
+		if(multiline){
+			// If multiline, create a textarea
+			viewNode = document.createElement("textarea");
+			anchorNode.appendChild(viewNode);
+			dojo.style(viewNode, 'width', '90%');
+			box = new dijit.form.SimpleTextarea({},viewNode);
+		}else{
+			// If single line, create a textbox.
+			viewNode = document.createElement("input");
+			anchorNode.appendChild(viewNode);
+			dojo.style(viewNode, 'width', '95%');
+			box = new dijit.form.TextBox({},viewNode);
+		}
+		box.attr('value', value);
+		return box;
+	},
+	
+	_switchEditor: function(/*object*/event){
+		//	summary:  
+		//		Function to switch between editor types.
+		//	description: 
+		//		Function to switch between a rich text editor and a textarea widget.  Used for title, summary,
+		//		And content when switching between text and html/xhtml content.
+		//
+		//	event:
+		//		The event generated by the change in the select box on the page.
+		var type = null;
+		var target = null;
+		var parent = null;
+		
+		// Determine the source/target of this event (to determine which editor we're switching)
+		if(dojo.isIE){
+			target = event.srcElement;
+		}else{
+			target = event.target;
+		}
+			
+		// Determine which editor (title, summary, or content)
+		if(target === this.entryTitleSelect){
+			parent = this.entryTitleNode;
+			type = "title";
+		} else if(target === this.entrySummarySelect){
+			parent = this.entrySummaryNode;
+			type = "summary";
+		}else{
+			parent = this.entryContentNode;
+			type = "content";
+		}
+
+		// Grab the existing editor.
+		var editor = this._editors[type];
+		var newEditor;
+		var value;
+		
+		if(target.value === "text"){
+			if(editor.declaredClass === "dijit.Editor"){
+				// If we're changing the type to text and our existing editor is a rich text editor, we need to destroy
+				// it and switch to a multiline editor.
+				value = editor.attr('value', false);
+				editor.close(false,true);
+				editor.destroy();
+				while(parent.firstChild){
+					dojo.destroy(parent.firstChild);
+				}
+				newEditor = this._createEditor(parent, {value: value}, true, false);
+				this._editors[type] = newEditor;
+			}
+		}else{
+			if(editor.declaredClass != "dijit.Editor"){
+				// Otherwise, we're switching to a html or xhtml type, but we currently have a textarea widget.  We need
+				// to destroy the existing RTE and create a multiline textarea widget.
+				value = editor.attr('value');
+				editor.destroy();
+				while(parent.firstChild){
+					dojo.destroy(parent.firstChild);
+				}
+				newEditor = this._createEditor(parent, {value: value}, true, true);
+				newEditor = dojo.hitch(newEditor, newEditor.generateEditor)();
+				this._editors[type] = newEditor;
+			}
+		}
+	},
+	
+	_createPeopleEditor: function(/*DOM node*/anchorNode, /*DOM node*/node){
+		//	summary: 
+		//		Creates a People Editor widget and returns it.
+		//	description: 
+		//		Creates a People Editor widget, sets its value, and returns it.
+		//
+		//	anchorNode:
+		//		The node to attach the editor to.
+		//	node:
+		//		An object containing the value to be put into the editor. Typically, this is an 
+		//		dojox.atom.io.model.Person object.
+		//
+		// returns: A new People Editor object.
+		var viewNode = document.createElement("div");
+		anchorNode.appendChild(viewNode);
+		return new dojox.atom.widget.PeopleEditor(node,viewNode);
+	},
+
+	saveEdits: function(){
+		//	summary: 
+		//		Saves edits submitted when the 'save' button is pressed.
+		//	description: 
+		//		Saves edits submitted when the 'save' button is pressed.  Distinguishes between new and existing
+		//		entries and saves appropriately.  Fetches the values of the editors, and, if existing, compares them to 
+		//		the existing values and submits the updates, otherwise creates a new entry and posts it as a new entry.
+		//
+		//	returns:
+		//		Nothing.
+		dojo.style(this.entrySaveCancelButtons, 'display', 'none');
+		dojo.style(this.entryEditButton, 'display', '');
+		dojo.style(this.entryNewButton, 'display', '');
+		var modifiedEntry = false;
+		var value;
+		var i;
+		var changed;
+		var entry;
+		var authors;
+		var contributors;
+		if(!this._new){
+			entry = this.getEntry();
+			if(this._editors.title && (this._editors.title.attr('value') != entry.title.value || this.entryTitleSelect.value != entry.title.type)){
+				value = this._editors.title.attr('value');
+				if(this.entryTitleSelect.value === "xhtml"){
+					value = this._enforceXhtml(value);
+					if(value.indexOf('<div xmlns="http://www.w3.org/1999/xhtml">') !== 0){
+						value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>';
+					}
+				}
+				entry.title = new dojox.atom.io.model.Content("title", value, null, this.entryTitleSelect.value);
+				modifiedEntry = true;
+			}
+			
+			if(this._editors.id.attr('value') != entry.id){
+				entry.id = this._editors.id.attr('value');
+				modifiedEntry = true;
+			}
+			
+			if(this._editors.summary && (this._editors.summary.attr('value') != entry.summary.value || this.entrySummarySelect.value != entry.summary.type)){
+				value = this._editors.summary.attr('value');
+				if(this.entrySummarySelect.value === "xhtml"){
+					value = this._enforceXhtml(value);
+					if(value.indexOf('<div xmlns="http://www.w3.org/1999/xhtml">') !== 0){
+						value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>';
+					}
+				}
+				entry.summary = new dojox.atom.io.model.Content("summary", value, null, this.entrySummarySelect.value);
+				modifiedEntry = true;
+			}
+			
+			if(this._editors.content && (this._editors.content.attr('value') != entry.content.value || this.entryContentSelect.value != entry.content.type)){
+				value = this._editors.content.attr('value');
+				if(this.entryContentSelect.value === "xhtml"){
+					value = this._enforceXhtml(value);
+					if(value.indexOf('<div xmlns="http://www.w3.org/1999/xhtml">') !== 0){
+						value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>';
+					}
+				}
+				entry.content = new dojox.atom.io.model.Content("content", value, null, this.entryContentSelect.value);
+				modifiedEntry = true;
+			}
+			
+			if(this._editors.authors){
+				if(modifiedEntry){
+					entry.authors = [];
+					authors = this._editors.authors.getValues();
+					for(i in authors){
+						if(authors[i].name || authors[i].email || authors[i].uri){
+							entry.addAuthor(authors[i].name, authors[i].email, authors[i].uri);
+						}
+					}
+				}else{
+					var currentAuthors = entry.authors;
+					var searchAuthors = function(name, email, uri){
+						for(i in currentAuthors){
+							if(currentAuthors[i].name === name && currentAuthors[i].email === email && currentAuthors[i].uri === uri){
+								return true;
+							}
+						}
+						return false;
+					};
+					authors = this._editors.authors.getValues();
+					changed = false;
+					for(i in authors){
+						if(!searchAuthors(authors[i].name, authors[i].email, authors[i].uri)){
+							changed = true;
+							break;
+						}
+					}
+					if(changed){
+						entry.authors = [];
+						for(i in authors){
+							if(authors[i].name || authors[i].email || authors[i].uri){
+								entry.addAuthor(authors[i].name, authors[i].email, authors[i].uri);
+							}
+						}
+						modifiedEntry = true;
+					}
+				}
+			}
+			
+			if(this._editors.contributors){
+    			if(modifiedEntry){
+					entry.contributors = [];
+					contributors = this._editors.contributors.getValues();
+					for(i in contributors){
+						if(contributors[i].name || contributors[i].email || contributors[i].uri){
+							entry.addAuthor(contributors[i].name, contributors[i].email, contributors[i].uri);
+						}
+					}
+				}else{
+					var currentContributors = entry.contributors;
+					var searchContributors = function(name, email, uri){
+						for(i in currentContributors){
+							if(currentContributors[i].name === name && currentContributors[i].email === email && currentContributors[i].uri === uri){
+								return true;
+							}
+						}
+						return false;
+					};
+					contributors = this._editors.contributors.getValues();
+					changed = false;
+					for(i in contributors){
+						if(searchContributors(contributors[i].name, contributors[i].email, contributors[i].uri)){
+							changed = true;
+							break;
+						}
+					}
+					if(changed){
+						entry.contributors = [];
+						for(i in contributors){
+							if(contributors[i].name || contributors[i].email || contributors[i].uri){
+								entry.addContributor(contributors[i].name, contributors[i].email, contributors[i].uri);
+							}
+						}
+						modifiedEntry = true;
+					}
+				}
+			}
+
+			if(modifiedEntry){
+				dojo.publish(this.entrySelectionTopic, [{action: "update", source: this, entry: entry, callback: this._handleSave }]);
+				//TODO: REMOVE BELOW
+				//var atomIO = new dojox.atom.io.Connection();
+				//atomIO.updateEntry(entry, dojo.hitch(this,this._handleSave));
+				//WARNING: Use above when testing with SimpleProxy (or any other servlet which
+				// 			doesn't actually create a new entry and return it properly)
+				//atomIO.updateEntry(entry, dojo.hitch(this,this._handleSave), true);
+			}
+		}else{
+			this._new = false;
+			entry = new dojox.atom.io.model.Entry();
+			
+			value = this._editors.title.attr('value');
+			if(this.entryTitleSelect.value === "xhtml"){
+				value = this._enforceXhtml(value);
+				value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>';
+			}
+			entry.setTitle(value, this.entryTitleSelect.value);
+			entry.id = this._editors.id.attr('value');
+			
+			authors = this._editors.authors.getValues();
+			for(i in authors){
+				if(authors[i].name || authors[i].email || authors[i].uri){
+					entry.addAuthor(authors[i].name, authors[i].email, authors[i].uri);
+				}
+			}
+					
+			contributors = this._editors.contributors.getValues();
+			for(i in contributors){
+				if(contributors[i].name || contributors[i].email || contributors[i].uri){
+					entry.addContributor(contributors[i].name, contributors[i].email, contributors[i].uri);
+				}
+			}
+
+			
+			value = this._editors.summary.attr('value');
+			if(this.entrySummarySelect.value === "xhtml"){
+				value = this._enforceXhtml(value);
+				value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>';
+			}
+			entry.summary = new dojox.atom.io.model.Content("summary", value, null, this.entrySummarySelect.value);
+
+			value = this._editors.content.attr('value');
+			if(this.entryContentSelect.value === "xhtml"){
+				value = this._enforceXhtml(value);
+				value = '<div xmlns="http://www.w3.org/1999/xhtml">' + value + '</div>';
+			}
+			entry.content = new dojox.atom.io.model.Content("content", value, null, this.entryContentSelect.value);
+
+			dojo.style(this.entryNewButton, 'display', '');
+			dojo.publish(this.entrySelectionTopic, [{action: "post", source: this, entry: entry }]);
+		}
+		this._editMode = false;
+		
+		//Rebuild the view using the same entry and feed.
+		this.setEntry(entry, this._feed, true);
+	},
+	
+	_handleSave: function(/*object*/entry, /*string*/location){
+		//	summary: 
+		//		Function for handling the save of an entry, cleaning up the display after the edit is completed.
+		//	description: 
+		//		Function for handling the save of an entry, cleaning up the display after the edit is completed.
+		//
+		//	entry: dojox.atom.io.model.Entry object
+		//		The entry that was saved.
+		//	Location: String
+		//		A URL to be used, not used here, but part of the call back from the AtomIO 
+		//	returns:
+		//		Nothing.
+		//Close the editor and revert out.
+		this._editMode = false;
+		
+		//Rebuild the view using the same entry and feed.
+		this.clear();
+		this.setEntry(entry, this.getFeed(), true);
+	},
+
+	cancelEdits: function(){
+		//	summary: 
+		//		Cancels edits and reverts the editor to its previous state (display mode)
+		//	description:
+		//		Cancels edits and reverts the editor to its previous state (display mode)
+		//
+		//	returns:
+		//		Nothing.
+		this._new = false;
+		dojo.style(this.entrySaveCancelButtons, 'display', 'none');
+		if(this._editable){
+			dojo.style(this.entryEditButton, 'display', '');
+		}
+		dojo.style(this.entryNewButton, 'display', '');
+		this._editMode = false;
+		
+		//Rebuild the view using the same entry and feed.
+		this.clearEditors();
+		this.setEntry(this.getEntry(), this.getFeed(), true);
+	},
+
+	clear: function(){
+		//	summary: 
+		//		Clears the editor, destorys all editors, leaving the editor completely clear
+		//	description: 
+		//		Clears the editor, destorys all editors, leaving the editor completely clear
+		this._editable=false;
+		this.clearEditors();
+		dojox.atom.widget.FeedEntryEditor.superclass.clear.apply(this);
+		if(this._contentEditor){
+			// Note that the superclass clear destroys the widget since it's in the child widget list, 
+			// so this is just ref clearing.
+			this._contentEditor = this._setObject = this._oldContent = this._contentEditorCreator = null;
+			this._editors = {};
+		}
+	},
+	
+	clearEditors: function(){
+		for(var key in this._editors){
+			if(this._editors[key].declaredClass === "dijit.Editor"){
+				this._editors[key].close(false, true);
+			}
+			this._editors[key].destroy();
+		}
+		this._editors = {};
+	},
+
+	_enforceXhtml: function(/*string*/html){
+		//	summary: 
+		//		Function for cleaning up/enforcing the XHTML standard in HTML returned from the editor2 widget.
+		//	description: 
+		//		Function for cleaning up/enforcing the XHTML standard in HTML returned from the editor2 widget.
+		//
+		// 	html:
+		//		HTML string to be enforced as xhtml.
+		//
+		// 	returns:  
+		//		string of cleaned up HTML.
+		var xhtml = null;
+		if(html){
+			//Handle <BR>
+			var brRegExp = /<br>/g;
+			xhtml = html.replace(brRegExp, "<br/>");
+
+			//Handle <HR>
+			xhtml = this._closeTag(xhtml, "hr");
+
+			//Handle <img>
+			xhtml = this._closeTag(xhtml, "img");
+		}
+		return xhtml;
+	},
+
+	_closeTag: function(/*string*/xhtml, /*string*/tag){
+		//	summary: 
+		//		Function for closing tags in a text of HTML/XHTML
+		//	description: 
+		//		Function for closing tags in a text of HTML/XHTML
+		//
+		//	xhtml: String
+		//		XHTML string which needs the closing tag.
+		//	tag:
+		//		The tag to close.
+		//
+		//	returns:  string of cleaned up HTML.
+		//
+		// NOTE:  Probably should redo this function in a more efficient way.  This could get expensive.
+		var tagStart = "<" + tag;
+		var tagIndex = xhtml.indexOf(tagStart);
+		if(tagIndex !== -1){
+			while (tagIndex !== -1){
+				var tempString = "";
+				var foundTagEnd = false;
+				for (var i = 0; i < xhtml.length; i++){
+					var c = xhtml.charAt(i);
+					if(i <= tagIndex ||foundTagEnd){
+						tempString += c;
+					}
+					else
+					{
+						if(c === '>'){
+							tempString += "/";
+							foundTagEnd = true;
+						}
+						tempString +=c;
+					}
+				}
+				xhtml = tempString;
+				tagIndex = xhtml.indexOf(tagStart, tagIndex + 1);
+			}
+		}
+		return xhtml;
+	},
+	
+	_toggleNew: function(){
+		//	summary: 
+		//		Function to put the editor into a state to create a new entry.
+		//	description: 
+		//		Function to put the editor into a state to create a new entry.
+		
+		// Hide the edit/new buttons and show the save/cancel buttons.
+		dojo.style(this.entryNewButton, 'display', 'none');
+		dojo.style(this.entryEditButton, 'display', 'none');
+		dojo.style(this.entrySaveCancelButtons, 'display', '');
+		
+		// Reset the type select boxes to text.
+		this.entrySummarySelect.value = "text";
+		this.entryContentSelect.value = "text";
+		this.entryTitleSelect.value = "text";
+		
+		// Clear all nodes.
+		this.clearNodes();
+		this._new = true;
+		
+		var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedEntryViewer");
+		// Create all headers and editors.
+		var titleHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.title});
+		this.entryTitleHeader.appendChild(titleHeader.domNode);
+		
+		this._editors.title = this._createEditor(this.entryTitleNode, null);
+		this.setFieldValidity("title",true);
+		
+		var authorHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.authors});
+		this.entryAuthorHeader.appendChild(authorHeader.domNode);
+
+		this._editors.authors = this._createPeopleEditor(this.entryAuthorNode, {name: "Author"});
+		this.setFieldValidity("authors", true);
+		
+		var contributorHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.contributors});
+		this.entryContributorHeader.appendChild(contributorHeader.domNode);
+
+		this._editors.contributors = this._createPeopleEditor(this.entryContributorNode, {name: "Contributor"});
+		this.setFieldValidity("contributors", true);
+		
+		var idHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.id});
+		this.entryIdHeader.appendChild(idHeader.domNode);
+		
+		this._editors.id = this._createEditor(this.entryIdNode, null);
+		this.setFieldValidity("id",true);
+
+		var updatedHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.updated});
+		this.entryUpdatedHeader.appendChild(updatedHeader.domNode);
+		
+		this._editors.updated = this._createEditor(this.entryUpdatedNode, null);
+		this.setFieldValidity("updated",true);
+
+		var summaryHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.summary});
+		this.entrySummaryHeader.appendChild(summaryHeader.domNode);
+		
+		this._editors.summary = this._createEditor(this.entrySummaryNode, null, true);
+		this.setFieldValidity("summaryedit",true);
+		this.setFieldValidity("summary",true);
+
+		var contentHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.content});
+		this.entryContentHeader.appendChild(contentHeader.domNode);
+		
+		this._editors.content = this._createEditor(this.entryContentNode, null, true);
+		this.setFieldValidity("contentedit",true);
+		this.setFieldValidity("content",true);
+
+		// Show the sections.
+		this._displaySections();
+	},
+	
+	_displaySections: function(){
+		// summary: Function to display the appropriate sections based on validity.
+		// description: Function to display the appropriate sections based on validity.
+		
+		// Hide select boxes.
+		dojo.style(this.entrySummarySelect, 'display', 'none');
+		dojo.style(this.entryContentSelect, 'display', 'none');
+		dojo.style(this.entryTitleSelect, 'display', 'none');
+
+		// Show select boxes if the flags are set.
+		if(this.isFieldValid("contentedit")){
+			dojo.style(this.entryContentSelect, 'display', '');
+		}
+		if(this.isFieldValid("summaryedit")){
+			dojo.style(this.entrySummarySelect, 'display', '');
+		}
+		if(this.isFieldValid("titleedit")){
+			dojo.style(this.entryTitleSelect, 'display', '');
+		}
+		// Call super's _displaySections.
+		dojox.atom.widget.FeedEntryEditor.superclass._displaySections.apply(this);
+		
+		// If we have editors to load after the nodes are created on the page, execute those now.
+		if(this._toLoad){
+			for(var i in this._toLoad){
+				var editor;
+				if(this._toLoad[i].generateEditor){
+					editor = dojo.hitch(this._toLoad[i], this._toLoad[i].generateEditor)();
+				}else{
+					editor = this._toLoad[i];
+				}
+				this._editors[this._toLoad[i].name] = editor;
+				this._toLoad[i] = null;
+			}
+			this._toLoad = null;
+		}
+	}
+});
+
+dojo.declare("dojox.atom.widget.PeopleEditor",[dijit._Widget, dijit._Templated, dijit._Container],{
+		//	summary: 
+		//		An editor for dojox.atom.io.model.Person objects. 
+		//	description: 
+		//		An editor for dojox.atom.io.model.Person objects.  Displays multiple rows for the respective arrays
+		//		of people.  Can add/remove rows on the fly.
+		templateString: dojo.cache("dojox.atom", "widget/templates/PeopleEditor.html"),
+
+		_rows: [],
+		_editors: [],
+		_index: 0,
+		_numRows: 0,
+		
+		postCreate: function(){
+			// Initializer function for the PeopleEditor widget.
+			var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "PeopleEditor");
+			if(this.name){
+				if(this.name == "Author"){
+					this.peopleEditorButton.appendChild(document.createTextNode("["+_nlsResources.addAuthor+"]"));
+				}else if(this.name == "Contributor"){
+					this.peopleEditorButton.appendChild(document.createTextNode("["+_nlsResources.addContributor+"]"));
+				}
+			}else{
+				this.peopleEditorButton.appendChild(document.createTextNode("["+_nlsResources.add+"]"));
+			}
+			this._editors = [];
+
+			if(!this.data || this.data.length===0){
+				this._createEditors(null, null, null, 0, this.name);
+				this._index = 1;
+			}else{
+				for(var i in this.data){
+					this._createEditors(this.data[i].name, this.data[i].email, this.data[i].uri, i);
+					this._index++;
+					this._numRows++;
+				}
+			}
+		},
+		
+		destroy: function(){
+			for(var key in this._editors){
+				for(var key2 in this._editors[key]){
+					this._editors[key][key2].destroy();
+				}
+			}
+			this._editors = [];
+		},
+		
+		_createEditors: function(/*string*/name, /*string*/email, /*string*/uri, /*int*/index, /*string*/widgetName){
+			//	summary: 
+			//		creates editor boxes (textbox widgets) for the individual values of a Person.
+			//	description: 
+			//		creates editor boxes (textbox widgets) for the individual values of a Person.
+			//
+			//	name:
+			//		The name of this Person.
+			//	email:
+			//		The email of this Person.
+			//	uri:
+			//		The Person's URI.
+			//	index: 
+			//		The row index to use for this Person.
+			var row = document.createElement("tr");
+			this.peopleEditorEditors.appendChild(row);
+			row.id = "removeRow"+index;
+			
+			var node = document.createElement("td");
+			node.setAttribute('align', 'right');
+			row.appendChild(node);
+			node.colSpan = 2;
+			
+			if(this._numRows>0){
+				var hr = document.createElement("hr");
+				node.appendChild(hr);
+				hr.id = "hr"+index;
+			}
+			
+			row = document.createElement("span");
+			node.appendChild(row);
+			row.className = "peopleEditorButton";
+			dojo.style(row, 'font-size', 'x-small');
+			dojo.connect(row, "onclick", this, "_removeEditor");
+			row.id = "remove"+index;
+			
+			node = document.createTextNode("[X]");
+			row.appendChild(node);
+			
+			row = document.createElement("tr");
+			this.peopleEditorEditors.appendChild(row);
+			row.id = "editorsRow"+index;
+			
+			var labelNode = document.createElement("td");
+			row.appendChild(labelNode);
+			dojo.style(labelNode, 'width', '20%');
+			
+			node = document.createElement("td");
+			row.appendChild(node);
+			
+			row = document.createElement("table");
+			labelNode.appendChild(row);
+			dojo.style(row, 'width', '100%');
+			
+			labelNode = document.createElement("tbody");
+			row.appendChild(labelNode);
+			
+			row = document.createElement("table");
+			node.appendChild(row);
+			dojo.style(row, 'width', '100%');
+			
+			node = document.createElement("tbody");
+			row.appendChild(node);
+
+			this._editors[index] = [];
+			this._editors[index].push(this._createEditor(name, widgetName+'name'+index, 'Name:', labelNode, node));
+			this._editors[index].push(this._createEditor(email, widgetName+'email'+index, 'Email:', labelNode, node));
+			this._editors[index].push(this._createEditor(uri, widgetName+'uri'+index, 'URI:', labelNode, node));
+		},
+		
+		_createEditor: function(/*string*/value, /*string*/id, /*string*/name, /*DOM node*/labelNode, /*DOM node*/node){
+			//	summary: 
+			//		Creates an individual editor widget (textbox) for a value.
+			// 	description: 
+			//		Creates an individual editor widget (textbox) for a value.
+			//
+			// 	value: 
+			//		The initial value of the textbox
+			// 	id:
+			//		The id the textbox should have.
+			// 	name: 
+			//		The text to put in the label element for this textbox.
+			//	labelNode:
+			//		The node to attach the label to.
+			//	node:
+			//		The node to attach the editor rows to.
+			//
+			//	returns: 
+			//		Editor widget.
+			var row = document.createElement("tr");
+			labelNode.appendChild(row);
+			
+			var label = document.createElement("label");
+			label.setAttribute('for', id);
+			label.appendChild(document.createTextNode(name));
+			labelNode = document.createElement("td");
+			labelNode.appendChild(label);
+			row.appendChild(labelNode);
+			
+			row = document.createElement("tr");
+			node.appendChild(row);
+				
+			node = document.createElement("td");
+			row.appendChild(node);
+			
+			var viewNode = document.createElement("input");
+			viewNode.setAttribute('id', id);
+			node.appendChild(viewNode);
+			dojo.style(viewNode, 'width', '95%');
+			
+			var box = new dijit.form.TextBox({},viewNode);
+			box.attr('value', value);
+			return box;
+		},
+		
+		_removeEditor: function(/*object*/event){
+			//	summary: 
+			//		Removes a Person from our list of editors.
+			//	description: 
+			//		Removes a Person from our list of editors by removing the block of editors that 
+			//		make up that Person.
+			//
+			//	event:
+			//		The event generated when the remove button is pressed on the page.
+			var target = null;
+		
+			if(dojo.isIE){
+				target = event.srcElement;
+			}else{
+				target = event.target;
+			}
+				
+			var id = target.id;
+			id = id.substring(6);
+			for(var key in this._editors[id]){
+				this._editors[id][key].destroy();
+			}
+			
+			var node = dojo.byId("editorsRow"+id);
+			var parent = node.parentNode;
+			parent.removeChild(node);
+			
+			node = dojo.byId("removeRow"+id);
+			parent = node.parentNode;
+			parent.removeChild(node);
+
+			this._numRows--;
+			if(this._numRows === 1 && parent.firstChild.firstChild.firstChild.tagName.toLowerCase() === "hr"){
+				node = parent.firstChild.firstChild;
+				node.removeChild(node.firstChild);
+			}
+			this._editors[id] = null;
+		},
+		
+		_add: function(){
+			//	summary: 
+			//		Adds a new block of blank editors to represent a Person.
+			//	description: 
+			//		Adds a new block of blank editors to represent a Person.
+			this._createEditors(null, null, null, this._index);
+			this._index++;
+			this._numRows++;
+		},
+		
+		getValues: function(){
+			//	summary: 
+			//		Gets the values of this editor in an array.
+			//	description: 
+			//		Gets the values of this editor in an array, with each Person as an object within the array.
+			//
+			//	returns: 
+			//		An array of anonymous objects representing dojox.atom.io.model.Persons.
+			var values = [];
+			for(var i in this._editors){
+				if(this._editors[i]){
+					values.push({name: this._editors[i][0].attr('value'), email: this._editors[i][1].attr('value'), uri: this._editors[i][2].attr('value')});
+				}
+			}
+			return values;
+		}
+});
diff --git a/dojox/atom/widget/FeedEntryViewer.js b/dojox/atom/widget/FeedEntryViewer.js
index f0c3a22..95c1e84 100644
--- a/dojox/atom/widget/FeedEntryViewer.js
+++ b/dojox/atom/widget/FeedEntryViewer.js
@@ -1,396 +1,783 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.atom.widget.FeedEntryViewer"]){
-dojo._hasResource["dojox.atom.widget.FeedEntryViewer"]=true;
 dojo.provide("dojox.atom.widget.FeedEntryViewer");
+
 dojo.require("dojo.fx");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Container");
 dojo.require("dijit.layout.ContentPane");
 dojo.require("dojox.atom.io.Connection");
-dojo.requireLocalization("dojox.atom.widget","FeedEntryViewer",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
+dojo.requireLocalization("dojox.atom.widget", "FeedEntryViewer");
+
 dojo.experimental("dojox.atom.widget.FeedEntryViewer");
-dojo.declare("dojox.atom.widget.FeedEntryViewer",[dijit._Widget,dijit._Templated,dijit._Container],{entrySelectionTopic:"",_validEntryFields:{},displayEntrySections:"",_displayEntrySections:null,enableMenu:false,enableMenuFade:false,_optionButtonDisplayed:true,templateString:dojo.cache("dojox.atom","widget/templates/FeedEntryViewer.html","<div class=\"feedEntryViewer\">\n    <table border=\"0\" width=\"100%\" class=\"feedEntryViewerMenuTable\" dojoAttachPoint=\"feedEntryViewerMenu\" styl [...]
-if(this.entrySelectionTopic!==""){
-this._subscriptions=[dojo.subscribe(this.entrySelectionTopic,this,"_handleEvent")];
-}
-var _1=dojo.i18n.getLocalization("dojox.atom.widget","FeedEntryViewer");
-this.displayOptions.innerHTML=_1.displayOptions;
-this.feedEntryCheckBoxLabelTitle.innerHTML=_1.title;
-this.feedEntryCheckBoxLabelAuthors.innerHTML=_1.authors;
-this.feedEntryCheckBoxLabelContributors.innerHTML=_1.contributors;
-this.feedEntryCheckBoxLabelId.innerHTML=_1.id;
-this.close.innerHTML=_1.close;
-this.feedEntryCheckBoxLabelUpdated.innerHTML=_1.updated;
-this.feedEntryCheckBoxLabelSummary.innerHTML=_1.summary;
-this.feedEntryCheckBoxLabelContent.innerHTML=_1.content;
-},startup:function(){
-if(this.displayEntrySections===""){
-this._displayEntrySections=["title","authors","contributors","summary","content","id","updated"];
-}else{
-this._displayEntrySections=this.displayEntrySections.split(",");
-}
-this._setDisplaySectionsCheckboxes();
-if(this.enableMenu){
-dojo.style(this.feedEntryViewerMenu,"display","");
-if(this.entryCheckBoxRow&&this.entryCheckBoxRow2){
-if(this.enableMenuFade){
-dojo.fadeOut({node:this.entryCheckBoxRow,duration:250}).play();
-dojo.fadeOut({node:this.entryCheckBoxRow2,duration:250}).play();
-}
-}
-}
-},clear:function(){
-this.destroyDescendants();
-this._entry=null;
-this._feed=null;
-this.clearNodes();
-},clearNodes:function(){
-dojo.forEach(["entryTitleRow","entryAuthorRow","entryContributorRow","entrySummaryRow","entryContentRow","entryIdRow","entryUpdatedRow"],function(_2){
-dojo.style(this[_2],"display","none");
-},this);
-dojo.forEach(["entryTitleNode","entryTitleHeader","entryAuthorHeader","entryContributorHeader","entryContributorNode","entrySummaryHeader","entrySummaryNode","entryContentHeader","entryContentNode","entryIdNode","entryIdHeader","entryUpdatedHeader","entryUpdatedNode"],function(_3){
-while(this[_3].firstChild){
-dojo.destroy(this[_3].firstChild);
-}
-},this);
-},setEntry:function(_4,_5,_6){
-this.clear();
-this._validEntryFields={};
-this._entry=_4;
-this._feed=_5;
-if(_4!==null){
-if(this.entryTitleHeader){
-this.setTitleHeader(this.entryTitleHeader,_4);
-}
-if(this.entryTitleNode){
-this.setTitle(this.entryTitleNode,this._editMode,_4);
-}
-if(this.entryAuthorHeader){
-this.setAuthorsHeader(this.entryAuthorHeader,_4);
-}
-if(this.entryAuthorNode){
-this.setAuthors(this.entryAuthorNode,this._editMode,_4);
-}
-if(this.entryContributorHeader){
-this.setContributorsHeader(this.entryContributorHeader,_4);
-}
-if(this.entryContributorNode){
-this.setContributors(this.entryContributorNode,this._editMode,_4);
-}
-if(this.entryIdHeader){
-this.setIdHeader(this.entryIdHeader,_4);
-}
-if(this.entryIdNode){
-this.setId(this.entryIdNode,this._editMode,_4);
-}
-if(this.entryUpdatedHeader){
-this.setUpdatedHeader(this.entryUpdatedHeader,_4);
-}
-if(this.entryUpdatedNode){
-this.setUpdated(this.entryUpdatedNode,this._editMode,_4);
-}
-if(this.entrySummaryHeader){
-this.setSummaryHeader(this.entrySummaryHeader,_4);
-}
-if(this.entrySummaryNode){
-this.setSummary(this.entrySummaryNode,this._editMode,_4);
-}
-if(this.entryContentHeader){
-this.setContentHeader(this.entryContentHeader,_4);
-}
-if(this.entryContentNode){
-this.setContent(this.entryContentNode,this._editMode,_4);
-}
-}
-this._displaySections();
-},setTitleHeader:function(_7,_8){
-if(_8.title&&_8.title.value&&_8.title.value!==null){
-var _9=dojo.i18n.getLocalization("dojox.atom.widget","FeedEntryViewer");
-var _a=new dojox.atom.widget.EntryHeader({title:_9.title});
-_7.appendChild(_a.domNode);
-}
-},setTitle:function(_b,_c,_d){
-if(_d.title&&_d.title.value&&_d.title.value!==null){
-if(_d.title.type=="text"){
-var _e=document.createTextNode(_d.title.value);
-_b.appendChild(_e);
-}else{
-var _f=document.createElement("span");
-var _10=new dijit.layout.ContentPane({refreshOnShow:true,executeScripts:false},_f);
-_10.attr("content",_d.title.value);
-_b.appendChild(_10.domNode);
-}
-this.setFieldValidity("title",true);
-}
-},setAuthorsHeader:function(_11,_12){
-if(_12.authors&&_12.authors.length>0){
-var _13=dojo.i18n.getLocalization("dojox.atom.widget","FeedEntryViewer");
-var _14=new dojox.atom.widget.EntryHeader({title:_13.authors});
-_11.appendChild(_14.domNode);
-}
-},setAuthors:function(_15,_16,_17){
-_15.innerHTML="";
-if(_17.authors&&_17.authors.length>0){
-for(var i in _17.authors){
-if(_17.authors[i].name){
-var _18=_15;
-if(_17.authors[i].uri){
-var _19=document.createElement("a");
-_18.appendChild(_19);
-_19.href=_17.authors[i].uri;
-_18=_19;
-}
-var _1a=_17.authors[i].name;
-if(_17.authors[i].email){
-_1a=_1a+" ("+_17.authors[i].email+")";
-}
-var _1b=document.createTextNode(_1a);
-_18.appendChild(_1b);
-var _1c=document.createElement("br");
-_15.appendChild(_1c);
-this.setFieldValidity("authors",true);
-}
-}
-}
-},setContributorsHeader:function(_1d,_1e){
-if(_1e.contributors&&_1e.contributors.length>0){
-var _1f=dojo.i18n.getLocalization("dojox.atom.widget","FeedEntryViewer");
-var _20=new dojox.atom.widget.EntryHeader({title:_1f.contributors});
-_1d.appendChild(_20.domNode);
-}
-},setContributors:function(_21,_22,_23){
-if(_23.contributors&&_23.contributors.length>0){
-for(var i in _23.contributors){
-var _24=document.createTextNode(_23.contributors[i].name);
-_21.appendChild(_24);
-var _25=document.createElement("br");
-_21.appendChild(_25);
-this.setFieldValidity("contributors",true);
-}
-}
-},setIdHeader:function(_26,_27){
-if(_27.id&&_27.id!==null){
-var _28=dojo.i18n.getLocalization("dojox.atom.widget","FeedEntryViewer");
-var _29=new dojox.atom.widget.EntryHeader({title:_28.id});
-_26.appendChild(_29.domNode);
-}
-},setId:function(_2a,_2b,_2c){
-if(_2c.id&&_2c.id!==null){
-var _2d=document.createTextNode(_2c.id);
-_2a.appendChild(_2d);
-this.setFieldValidity("id",true);
-}
-},setUpdatedHeader:function(_2e,_2f){
-if(_2f.updated&&_2f.updated!==null){
-var _30=dojo.i18n.getLocalization("dojox.atom.widget","FeedEntryViewer");
-var _31=new dojox.atom.widget.EntryHeader({title:_30.updated});
-_2e.appendChild(_31.domNode);
-}
-},setUpdated:function(_32,_33,_34){
-if(_34.updated&&_34.updated!==null){
-var _35=document.createTextNode(_34.updated);
-_32.appendChild(_35);
-this.setFieldValidity("updated",true);
-}
-},setSummaryHeader:function(_36,_37){
-if(_37.summary&&_37.summary.value&&_37.summary.value!==null){
-var _38=dojo.i18n.getLocalization("dojox.atom.widget","FeedEntryViewer");
-var _39=new dojox.atom.widget.EntryHeader({title:_38.summary});
-_36.appendChild(_39.domNode);
-}
-},setSummary:function(_3a,_3b,_3c){
-if(_3c.summary&&_3c.summary.value&&_3c.summary.value!==null){
-var _3d=document.createElement("span");
-var _3e=new dijit.layout.ContentPane({refreshOnShow:true,executeScripts:false},_3d);
-_3e.attr("content",_3c.summary.value);
-_3a.appendChild(_3e.domNode);
-this.setFieldValidity("summary",true);
-}
-},setContentHeader:function(_3f,_40){
-if(_40.content&&_40.content.value&&_40.content.value!==null){
-var _41=dojo.i18n.getLocalization("dojox.atom.widget","FeedEntryViewer");
-var _42=new dojox.atom.widget.EntryHeader({title:_41.content});
-_3f.appendChild(_42.domNode);
-}
-},setContent:function(_43,_44,_45){
-if(_45.content&&_45.content.value&&_45.content.value!==null){
-var _46=document.createElement("span");
-var _47=new dijit.layout.ContentPane({refreshOnShow:true,executeScripts:false},_46);
-_47.attr("content",_45.content.value);
-_43.appendChild(_47.domNode);
-this.setFieldValidity("content",true);
-}
-},_displaySections:function(){
-dojo.style(this.entryTitleRow,"display","none");
-dojo.style(this.entryAuthorRow,"display","none");
-dojo.style(this.entryContributorRow,"display","none");
-dojo.style(this.entrySummaryRow,"display","none");
-dojo.style(this.entryContentRow,"display","none");
-dojo.style(this.entryIdRow,"display","none");
-dojo.style(this.entryUpdatedRow,"display","none");
-for(var i in this._displayEntrySections){
-var _48=this._displayEntrySections[i].toLowerCase();
-if(_48==="title"&&this.isFieldValid("title")){
-dojo.style(this.entryTitleRow,"display","");
-}
-if(_48==="authors"&&this.isFieldValid("authors")){
-dojo.style(this.entryAuthorRow,"display","");
-}
-if(_48==="contributors"&&this.isFieldValid("contributors")){
-dojo.style(this.entryContributorRow,"display","");
-}
-if(_48==="summary"&&this.isFieldValid("summary")){
-dojo.style(this.entrySummaryRow,"display","");
-}
-if(_48==="content"&&this.isFieldValid("content")){
-dojo.style(this.entryContentRow,"display","");
-}
-if(_48==="id"&&this.isFieldValid("id")){
-dojo.style(this.entryIdRow,"display","");
-}
-if(_48==="updated"&&this.isFieldValid("updated")){
-dojo.style(this.entryUpdatedRow,"display","");
-}
-}
-},setDisplaySections:function(_49){
-if(_49!==null){
-this._displayEntrySections=_49;
-this._displaySections();
-}else{
-this._displayEntrySections=["title","authors","contributors","summary","content","id","updated"];
-}
-},_setDisplaySectionsCheckboxes:function(){
-var _4a=["title","authors","contributors","summary","content","id","updated"];
-for(var i in _4a){
-if(dojo.indexOf(this._displayEntrySections,_4a[i])==-1){
-dojo.style(this["feedEntryCell"+_4a[i]],"display","none");
-}else{
-this["feedEntryCheckBox"+_4a[i].substring(0,1).toUpperCase()+_4a[i].substring(1)].checked=true;
-}
-}
-},_readDisplaySections:function(){
-var _4b=[];
-if(this.feedEntryCheckBoxTitle.checked){
-_4b.push("title");
-}
-if(this.feedEntryCheckBoxAuthors.checked){
-_4b.push("authors");
-}
-if(this.feedEntryCheckBoxContributors.checked){
-_4b.push("contributors");
-}
-if(this.feedEntryCheckBoxSummary.checked){
-_4b.push("summary");
-}
-if(this.feedEntryCheckBoxContent.checked){
-_4b.push("content");
-}
-if(this.feedEntryCheckBoxId.checked){
-_4b.push("id");
-}
-if(this.feedEntryCheckBoxUpdated.checked){
-_4b.push("updated");
-}
-this._displayEntrySections=_4b;
-},_toggleCheckbox:function(_4c){
-if(_4c.checked){
-_4c.checked=false;
-}else{
-_4c.checked=true;
-}
-this._readDisplaySections();
-this._displaySections();
-},_toggleOptions:function(_4d){
-if(this.enableMenu){
-var _4e=null;
-var _4f;
-var _50;
-if(this._optionButtonDisplayed){
-if(this.enableMenuFade){
-_4f=dojo.fadeOut({node:this.entryCheckBoxDisplayOptions,duration:250});
-dojo.connect(_4f,"onEnd",this,function(){
-dojo.style(this.entryCheckBoxDisplayOptions,"display","none");
-dojo.style(this.entryCheckBoxRow,"display","");
-dojo.style(this.entryCheckBoxRow2,"display","");
-dojo.fadeIn({node:this.entryCheckBoxRow,duration:250}).play();
-dojo.fadeIn({node:this.entryCheckBoxRow2,duration:250}).play();
+
+dojo.declare("dojox.atom.widget.FeedEntryViewer",[dijit._Widget, dijit._Templated, dijit._Container],{
+	//	summary:
+	//		An ATOM feed entry editor for publishing updated ATOM entries, or viewing non-editable entries.
+	//	description:
+	//		An ATOM feed entry editor for publishing updated ATOM entries, or viewing non-editable entries.
+	entrySelectionTopic: "",	//The topic to listen on for entries to edit.
+
+	_validEntryFields: {},		//The entry fields that were present on the entry and are being displayed.
+								//This works in conjuntion with what is selected to be displayed.
+	displayEntrySections: "", //What current sections of the entries to display as a comma separated list.
+	_displayEntrySections: null,
+	
+	//Control options for the display options menu.
+	enableMenu: false,
+	enableMenuFade: false,
+	_optionButtonDisplayed: true,
+
+	//Templates for the HTML rendering.  Need to figure these out better, admittedly.
+	templateString: dojo.cache("dojox.atom", "widget/templates/FeedEntryViewer.html"),
+	
+	_entry: null, //The entry that is being viewed/edited.
+	_feed: null, //The feed the entry came from.
+
+	_editMode: false, //Flag denoting the state of the widget, in edit mode or not.
+	
+	postCreate: function(){
+		if(this.entrySelectionTopic !== ""){
+			this._subscriptions = [dojo.subscribe(this.entrySelectionTopic, this, "_handleEvent")];
+		}
+		var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedEntryViewer");
+		this.displayOptions.innerHTML = _nlsResources.displayOptions;
+		this.feedEntryCheckBoxLabelTitle.innerHTML = _nlsResources.title;
+		this.feedEntryCheckBoxLabelAuthors.innerHTML = _nlsResources.authors;
+		this.feedEntryCheckBoxLabelContributors.innerHTML = _nlsResources.contributors;
+		this.feedEntryCheckBoxLabelId.innerHTML = _nlsResources.id;
+		this.close.innerHTML = _nlsResources.close;
+		this.feedEntryCheckBoxLabelUpdated.innerHTML = _nlsResources.updated;
+		this.feedEntryCheckBoxLabelSummary.innerHTML = _nlsResources.summary;
+		this.feedEntryCheckBoxLabelContent.innerHTML = _nlsResources.content;
+	},
+
+	startup: function(){
+		if(this.displayEntrySections === ""){
+			this._displayEntrySections = ["title","authors","contributors","summary","content","id","updated"];
+		}else{
+			this._displayEntrySections = this.displayEntrySections.split(",");
+		}
+		this._setDisplaySectionsCheckboxes();
+
+		if(this.enableMenu){
+			dojo.style(this.feedEntryViewerMenu, 'display', '');
+			if(this.entryCheckBoxRow && this.entryCheckBoxRow2){
+				if(this.enableMenuFade){
+					dojo.fadeOut({node: this.entryCheckBoxRow,duration: 250}).play();
+					dojo.fadeOut({node: this.entryCheckBoxRow2,duration: 250}).play();
+				}
+			}
+		}
+	},
+
+	clear: function(){
+		//	summary:
+		//		Function to clear the state of the widget.
+		//	description:
+		//		Function to clear the state of the widget.
+		this.destroyDescendants();
+		this._entry=null;
+		this._feed=null;
+		this.clearNodes();
+	},
+	
+	clearNodes: function(){
+		//	summary:
+		//		Function to clear all the display nodes for the ATOM entry from the viewer.
+		//	description:
+		//		Function to clear all the display nodes for the ATOM entry from the viewer.
+
+		dojo.forEach([
+			"entryTitleRow", "entryAuthorRow", "entryContributorRow", "entrySummaryRow", "entryContentRow", 
+			"entryIdRow", "entryUpdatedRow"
+			], function(node){
+				dojo.style(this[node], "display", "none");
+			}, this);
+
+		dojo.forEach([
+			"entryTitleNode", "entryTitleHeader", "entryAuthorHeader", "entryContributorHeader",
+			"entryContributorNode", "entrySummaryHeader", "entrySummaryNode", "entryContentHeader",
+			"entryContentNode", "entryIdNode", "entryIdHeader", "entryUpdatedHeader", "entryUpdatedNode"
+			], function(part){
+				while(this[part].firstChild){
+					dojo.destroy(this[part].firstChild);
+				}
+			}
+		,this);
+		
+	},
+
+	setEntry: function(/*object*/entry, /*object*/feed, /*boolean*/leaveMenuState){
+		//	summary:
+		//		Function to set the current entry that is being edited.
+		//	description:
+		//		Function to set the current entry that is being edited.
+		//
+		//	entry:
+		//		Instance of dojox.atom.io.model.Entry to display for reading/editing.
+		this.clear();
+		this._validEntryFields = {};
+		this._entry = entry;
+		this._feed = feed;
+
+		if(entry !== null){
+			// Handle the title.
+			if(this.entryTitleHeader){
+				this.setTitleHeader(this.entryTitleHeader, entry);
+			}
+			
+			if(this.entryTitleNode){
+				this.setTitle(this.entryTitleNode, this._editMode, entry);
+			}
+
+			if(this.entryAuthorHeader){
+				this.setAuthorsHeader(this.entryAuthorHeader, entry);
+			}
+
+			if(this.entryAuthorNode){
+				this.setAuthors(this.entryAuthorNode, this._editMode, entry);
+			}
+			
+			if(this.entryContributorHeader){
+				this.setContributorsHeader(this.entryContributorHeader, entry);
+			}
+
+			if(this.entryContributorNode){
+				this.setContributors(this.entryContributorNode, this._editMode, entry);
+			}
+
+			if(this.entryIdHeader){
+				this.setIdHeader(this.entryIdHeader, entry);
+			}
+
+			if(this.entryIdNode){
+				this.setId(this.entryIdNode, this._editMode, entry);
+			}
+
+			if(this.entryUpdatedHeader){
+				this.setUpdatedHeader(this.entryUpdatedHeader, entry); 
+			}
+
+			if(this.entryUpdatedNode){
+				this.setUpdated(this.entryUpdatedNode, this._editMode, entry); 
+			}
+
+			if(this.entrySummaryHeader){
+				this.setSummaryHeader(this.entrySummaryHeader, entry); 
+			}
+
+			if(this.entrySummaryNode){
+				this.setSummary(this.entrySummaryNode, this._editMode, entry); 
+			}
+
+			if(this.entryContentHeader){
+				this.setContentHeader(this.entryContentHeader, entry); 
+			}
+
+			if(this.entryContentNode){
+				this.setContent(this.entryContentNode, this._editMode, entry); 
+			}
+		}
+		this._displaySections();
+	},
+
+	setTitleHeader: function(/*DOM node*/titleHeaderNode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the title header node in the template to some value.
+		//	description:
+		//		Function to set the contents of the title header node in the template to some value.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	titleAchorNode:
+		//		The DOM node to attach the title data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		//
+		if(entry.title && entry.title.value && entry.title.value !== null){
+			var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedEntryViewer");
+			var titleHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.title});
+			titleHeaderNode.appendChild(titleHeader.domNode);
+		}
+	},
+
+	setTitle: function(titleAnchorNode, editMode, entry){
+		//	summary:
+		//		Function to set the contents of the title node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the title node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	titleAchorNode:
+		//		The DOM node to attach the title data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.title && entry.title.value && entry.title.value !== null){
+			if(entry.title.type == "text"){
+				var titleNode = document.createTextNode(entry.title.value);
+				titleAnchorNode.appendChild(titleNode);
+			}else{
+				var titleViewNode = document.createElement("span");
+				var titleView = new dijit.layout.ContentPane({refreshOnShow: true, executeScripts: false}, titleViewNode);
+				titleView.attr('content', entry.title.value);
+				titleAnchorNode.appendChild(titleView.domNode);
+			}
+			this.setFieldValidity("title", true);
+		}
+	},
+
+	setAuthorsHeader: function(/*DOM node*/authorHeaderNode, /*object*/entry){
+		//	summary:
+		//		Function to set the title format for the authors section of the author row in the template to some value from the entry.
+		//	description:
+		//		Function to set the title format for the authors section of the author row in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the author data is filled out from an entry.
+		//
+		//	authorHeaderNode:
+		//		The DOM node to attach the author section header data to.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.authors && entry.authors.length > 0){
+			var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedEntryViewer");
+			var authorHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.authors});
+			authorHeaderNode.appendChild(authorHeader.domNode);
+		}
+	},
+
+	setAuthors: function(/*DOM node*/authorsAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the author node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the author node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	authorsAchorNode:
+		//		The DOM node to attach the author data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		authorsAnchorNode.innerHTML = "";
+		if(entry.authors && entry.authors.length > 0){
+			for(var i in entry.authors){
+				if(entry.authors[i].name){
+					var anchor = authorsAnchorNode;
+					if(entry.authors[i].uri){
+						var link = document.createElement("a");
+						anchor.appendChild(link);
+						link.href = entry.authors[i].uri;
+						anchor = link;
+					}
+					var name = entry.authors[i].name;
+					if(entry.authors[i].email){
+						name = name + " (" + entry.authors[i].email + ")";
+					}
+					var authorNode = document.createTextNode(name);
+					anchor.appendChild(authorNode);
+					var breakNode = document.createElement("br");
+					authorsAnchorNode.appendChild(breakNode);
+					this.setFieldValidity("authors", true);
+				}
+			}
+		}
+	},
+
+	setContributorsHeader: function(/*DOM node*/contributorsHeaderNode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the contributor header node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the contributor header node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	contributorsHeaderNode:
+		//		The DOM node to attach the contributor title to.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.contributors && entry.contributors.length > 0){
+			var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedEntryViewer");
+			var contributorHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.contributors});
+			contributorsHeaderNode.appendChild(contributorHeader.domNode);
+		}
+	},
+
+
+	setContributors: function(/*DOM node*/contributorsAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the contributor node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the contributor node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	contributorsAnchorNode:
+		//		The DOM node to attach the contributor data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.contributors && entry.contributors.length > 0){
+			for(var i in entry.contributors){
+				var contributorNode = document.createTextNode(entry.contributors[i].name);
+				contributorsAnchorNode.appendChild(contributorNode);
+				var breakNode = document.createElement("br");
+				contributorsAnchorNode.appendChild(breakNode);
+				this.setFieldValidity("contributors", true);
+			}
+		}
+	},
+
+				 
+	setIdHeader: function(/*DOM node*/idHeaderNode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the ID  node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the ID node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	idAnchorNode:
+		//		The DOM node to attach the ID data to.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.id && entry.id !== null){
+			var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedEntryViewer");
+			var idHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.id});
+			idHeaderNode.appendChild(idHeader.domNode);
+		}
+	},
+
+
+	setId: function(/*DOM node*/idAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the ID  node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the ID node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	idAnchorNode:
+		//		The DOM node to attach the ID data to.
+		// 	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.id && entry.id !== null){
+			var idNode = document.createTextNode(entry.id);
+			idAnchorNode.appendChild(idNode);
+			this.setFieldValidity("id", true);
+		}
+	},
+	
+	setUpdatedHeader: function(/*DOM node*/updatedHeaderNode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the updated header node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the updated header node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	updatedHeaderNode:
+		//		The DOM node to attach the updated header data to.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.updated && entry.updated !== null){
+			var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedEntryViewer");
+			var updatedHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.updated});
+			updatedHeaderNode.appendChild(updatedHeader.domNode);
+		}
+	},
+
+	setUpdated: function(/*DOM node*/updatedAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the updated  node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the updated node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	updatedAnchorNode:
+		//		The DOM node to attach the udpated data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.updated && entry.updated !== null){
+			var updatedNode = document.createTextNode(entry.updated);
+			updatedAnchorNode.appendChild(updatedNode);
+			this.setFieldValidity("updated", true);
+		}
+	},
+
+	setSummaryHeader: function(/*DOM node*/summaryHeaderNode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the summary  node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the summary node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	summaryHeaderNode:
+		//		The DOM node to attach the summary title to.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.summary && entry.summary.value && entry.summary.value !== null){
+			var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedEntryViewer");
+			var summaryHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.summary});
+			summaryHeaderNode.appendChild(summaryHeader.domNode);
+		}
+	},
+
+
+	setSummary: function(/*DOM node*/summaryAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the summary  node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the summary node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	summaryAnchorNode:
+		//		The DOM node to attach the summary data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.summary && entry.summary.value && entry.summary.value !== null){
+			var summaryViewNode = document.createElement("span");
+			var summaryView = new dijit.layout.ContentPane({refreshOnShow: true, executeScripts: false}, summaryViewNode);
+			summaryView.attr('content', entry.summary.value);
+			summaryAnchorNode.appendChild(summaryView.domNode);
+			this.setFieldValidity("summary", true);
+		}
+	},
+
+	setContentHeader: function(/*DOM node*/contentHeaderNode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the content node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the content node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	contentHeaderNode:
+		//		The DOM node to attach the content data to.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.content && entry.content.value && entry.content.value !== null){
+			var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedEntryViewer");
+			var contentHeader = new dojox.atom.widget.EntryHeader({title: _nlsResources.content});
+			contentHeaderNode.appendChild(contentHeader.domNode);
+		}
+	},
+
+	setContent: function(/*DOM node*/contentAnchorNode, /*boolean*/editMode, /*object*/entry){
+		//	summary:
+		//		Function to set the contents of the content node in the template to some value from the entry.
+		//	description:
+		//		Function to set the contents of the content node in the template to some value from the entry.
+		//		This exists specifically so users can over-ride how the title data is filled out from an entry.
+		//
+		//	contentAnchorNode:
+		//		The DOM node to attach the content data to.
+		//	editMode:
+		//		Boolean to indicate if the display should be in edit mode or not.
+		//	entry:
+		//		The Feed Entry to work with.
+		if(entry.content && entry.content.value && entry.content.value !== null){
+			var contentViewNode = document.createElement("span");
+			var contentView = new dijit.layout.ContentPane({refreshOnShow: true, executeScripts: false},contentViewNode);
+			contentView.attr('content', entry.content.value);
+			contentAnchorNode.appendChild(contentView.domNode);
+			this.setFieldValidity("content", true);
+		}
+	},
+
+
+	_displaySections: function(){
+		//	summary:
+		//		Internal function for determining which sections of the view to actually display.
+		//	description:
+		//		Internal function for determining which sections of the view to actually display.
+		//
+		//	returns:
+		//		Nothing. 
+		dojo.style(this.entryTitleRow, 'display', 'none');
+		dojo.style(this.entryAuthorRow, 'display', 'none');
+		dojo.style(this.entryContributorRow, 'display', 'none');
+		dojo.style(this.entrySummaryRow, 'display', 'none');
+		dojo.style(this.entryContentRow, 'display', 'none');
+		dojo.style(this.entryIdRow, 'display', 'none');
+		dojo.style(this.entryUpdatedRow, 'display', 'none');
+
+		for(var i in this._displayEntrySections){
+			var section = this._displayEntrySections[i].toLowerCase();
+			if(section === "title" && this.isFieldValid("title")){
+				dojo.style(this.entryTitleRow, 'display', '');
+			}
+			if(section === "authors" && this.isFieldValid("authors")){
+				dojo.style(this.entryAuthorRow, 'display', '');
+			}
+			if(section === "contributors" && this.isFieldValid("contributors")){
+				dojo.style(this.entryContributorRow, 'display', '');
+			}
+			if(section === "summary" && this.isFieldValid("summary")){
+				dojo.style(this.entrySummaryRow, 'display', '');
+			}
+			if(section === "content" && this.isFieldValid("content")){
+				dojo.style(this.entryContentRow, 'display', '');
+			}
+			if(section === "id" && this.isFieldValid("id")){
+				dojo.style(this.entryIdRow, 'display', '');
+			}
+			if(section === "updated" && this.isFieldValid("updated")){
+				dojo.style(this.entryUpdatedRow, 'display', '');
+			}
+
+		}
+	},
+
+	setDisplaySections: function(/*array*/sectionsArray){
+		//	summary:
+		//		Function for setting which sections of the entry should be displayed.
+		//	description:
+		//		Function for setting which sections of the entry should be displayed.
+		//
+		//	sectionsArray:
+		//		Array of string names that indicate which sections to display.
+		//
+		//	returns:
+		//		Nothing.
+		if(sectionsArray !== null){
+			this._displayEntrySections = sectionsArray;
+			this._displaySections();
+		}else{
+			this._displayEntrySections = ["title","authors","contributors","summary","content","id","updated"];
+		}
+	},
+
+	_setDisplaySectionsCheckboxes: function(){
+		//	summary:
+		//		Internal function for setting which checkboxes on the display are selected.
+		//	description:
+		//		Internal function for setting which checkboxes on the display are selected.
+		//
+		//	returns:
+		//		Nothing.
+		var items = ["title","authors","contributors","summary","content","id","updated"];
+		for(var i in items){
+			if(dojo.indexOf(this._displayEntrySections, items[i]) == -1){
+				dojo.style(this["feedEntryCell"+items[i]], 'display', 'none');
+			}else{
+				this["feedEntryCheckBox"+items[i].substring(0,1).toUpperCase()+items[i].substring(1)].checked=true;
+			}
+		}
+	},
+
+	_readDisplaySections: function(){
+		//	summary:
+		//		Internal function for reading what is currently checked for display and generating the display list from it.
+		//	description:
+		//		Internal function for reading what is currently checked for display and generating the display list from it.
+		//
+		//	returns:
+		//		Nothing.
+		var checkedList = [];
+
+		if(this.feedEntryCheckBoxTitle.checked){
+			checkedList.push("title");
+		}
+		if(this.feedEntryCheckBoxAuthors.checked){
+			checkedList.push("authors");
+		}
+		if(this.feedEntryCheckBoxContributors.checked){
+			checkedList.push("contributors");
+		}
+		if(this.feedEntryCheckBoxSummary.checked){
+			checkedList.push("summary");
+		}
+		if(this.feedEntryCheckBoxContent.checked){
+			checkedList.push("content");
+		}
+		if(this.feedEntryCheckBoxId.checked){
+			checkedList.push("id");
+		}
+		if(this.feedEntryCheckBoxUpdated.checked){
+			checkedList.push("updated");
+		}
+		this._displayEntrySections = checkedList;
+	},
+
+	_toggleCheckbox: function(/*object*/checkBox){
+		//	summary:
+		//		Internal function for determining of a particular entry is editable.
+		//	description:
+		//		Internal function for determining of a particular entry is editable.
+		//		This is used for determining if the delete action should be displayed or not.
+		//
+		//	checkBox:
+		//		The checkbox object to toggle the selection on.
+		//
+		//	returns:
+		//		Nothing
+		if(checkBox.checked){
+			checkBox.checked=false;
+		}else{
+			checkBox.checked=true;
+		}
+		this._readDisplaySections();
+		this._displaySections();
+	},
+
+	_toggleOptions: function(/*object*/checkBox){
+		//	summary:
+		//		Internal function for determining of a particular entry is editable.
+		//	description:
+		//		Internal function for determining of a particular entry is editable.
+		//		This is used for determining if the delete action should be displayed or not.
+		//
+		//	checkBox:
+		//		The checkbox object to toggle the selection on.
+		//
+		//	returns:
+		//		Nothing
+		if(this.enableMenu){
+			var fade = null;
+			var anim;
+			var anim2;
+			if(this._optionButtonDisplayed){
+				if(this.enableMenuFade){
+					anim = dojo.fadeOut({node: this.entryCheckBoxDisplayOptions,duration: 250});
+					dojo.connect(anim, "onEnd", this, function(){
+						dojo.style(this.entryCheckBoxDisplayOptions, 'display', 'none');
+						dojo.style(this.entryCheckBoxRow, 'display', '');
+						dojo.style(this.entryCheckBoxRow2, 'display', '');
+						dojo.fadeIn({node: this.entryCheckBoxRow, duration: 250}).play();
+						dojo.fadeIn({node: this.entryCheckBoxRow2, duration: 250}).play();
+					});
+					anim.play();
+				}else{
+					dojo.style(this.entryCheckBoxDisplayOptions, 'display', 'none');
+					dojo.style(this.entryCheckBoxRow, 'display', '');
+					dojo.style(this.entryCheckBoxRow2, 'display', '');
+				}
+				this._optionButtonDisplayed=false;
+			}else{
+				if(this.enableMenuFade){
+					anim = dojo.fadeOut({node: this.entryCheckBoxRow,duration: 250});
+					anim2 = dojo.fadeOut({node: this.entryCheckBoxRow2,duration: 250});
+					dojo.connect(anim, "onEnd", this, function(){
+						dojo.style(this.entryCheckBoxRow, 'display', 'none');
+						dojo.style(this.entryCheckBoxRow2, 'display', 'none');
+						dojo.style(this.entryCheckBoxDisplayOptions, 'display', '');
+						dojo.fadeIn({node: this.entryCheckBoxDisplayOptions, duration: 250}).play();
+					});
+					anim.play();
+					anim2.play();
+				}else{
+					dojo.style(this.entryCheckBoxRow, 'display', 'none');
+					dojo.style(this.entryCheckBoxRow2, 'display', 'none');
+					dojo.style(this.entryCheckBoxDisplayOptions, 'display', '');
+				}
+				this._optionButtonDisplayed=true;
+			}
+		}
+	},
+
+	_handleEvent: function(/*object*/entrySelectionEvent){
+		//	summary:
+		//		Internal function for listening to a topic that will handle entry notification.
+		//	description:
+		//		Internal function for listening to a topic that will handle entry notification.
+		//
+		//	entrySelectionEvent:
+		//		The topic message containing the entry that was selected for view.
+		//
+		//	returns:
+		//		Nothing.
+		if(entrySelectionEvent.source != this){
+			if(entrySelectionEvent.action == "set" && entrySelectionEvent.entry){
+				this.setEntry(entrySelectionEvent.entry, entrySelectionEvent.feed);
+			}else if(entrySelectionEvent.action == "delete" && entrySelectionEvent.entry && entrySelectionEvent.entry == this._entry){
+				this.clear();
+			}
+		}
+	},
+
+	setFieldValidity: function(/*string*/field, /*boolean*/isValid){
+		//	summary:
+		//		Function to set whether a field in the view is valid and displayable.
+		//	description:
+		//		Function to set whether a field in the view is valid and displayable.
+		//		This is needed for over-riding of the set* functions and customization of how data is displayed in the attach point.
+		//		So if custom implementations use their own display logic, they can still enable the field.
+		//
+		//	field:
+		//		The field name to set the valid parameter on.  Such as 'content', 'id', etc.
+		//	isValid:
+		//		Flag denoting if the field is valid or not.
+		//
+		//	returns:
+		//		Nothing.
+		if(field){
+			var lowerField = field.toLowerCase();
+			this._validEntryFields[field] = isValid;
+		}
+	},
+	
+	isFieldValid: function(/*string*/field){
+		//	summary:
+		//		Function to return if a displayable field is valid or not
+		//	description:
+		//		Function to return if a displayable field is valid or not
+		//
+		//	field:
+		//		The field name to get the valid parameter of.  Such as 'content', 'id', etc.
+		//
+		//	returns:
+		//		boolean denoting if the field is valid and set.
+		return this._validEntryFields[field.toLowerCase()];
+	},
+
+	getEntry: function(){
+		return this._entry;
+	},
+
+	getFeed: function(){
+		 return this._feed;
+	},
+
+	destroy: function(){
+		this.clear();
+		dojo.forEach(this._subscriptions, dojo.unsubscribe);
+	}
 });
-_4f.play();
-}else{
-dojo.style(this.entryCheckBoxDisplayOptions,"display","none");
-dojo.style(this.entryCheckBoxRow,"display","");
-dojo.style(this.entryCheckBoxRow2,"display","");
-}
-this._optionButtonDisplayed=false;
-}else{
-if(this.enableMenuFade){
-_4f=dojo.fadeOut({node:this.entryCheckBoxRow,duration:250});
-_50=dojo.fadeOut({node:this.entryCheckBoxRow2,duration:250});
-dojo.connect(_4f,"onEnd",this,function(){
-dojo.style(this.entryCheckBoxRow,"display","none");
-dojo.style(this.entryCheckBoxRow2,"display","none");
-dojo.style(this.entryCheckBoxDisplayOptions,"display","");
-dojo.fadeIn({node:this.entryCheckBoxDisplayOptions,duration:250}).play();
+
+dojo.declare("dojox.atom.widget.EntryHeader",[dijit._Widget, dijit._Templated, dijit._Container],{
+	//	summary:
+	//		Widget representing a header in a FeedEntryViewer/Editor
+	//	description:
+	//		Widget representing a header in a FeedEntryViewer/Editor
+	title: "",
+	templateString: dojo.cache("dojox.atom", "widget/templates/EntryHeader.html"),
+
+	postCreate: function(){
+		this.setListHeader();
+	},
+
+	setListHeader: function(/*string*/title){
+		this.clear();
+		if(title){
+			this.title = title;
+		}
+		var textNode = document.createTextNode(this.title);
+		this.entryHeaderNode.appendChild(textNode);
+	},
+
+	clear: function(){
+		this.destroyDescendants();
+		 if(this.entryHeaderNode){
+			 for(var i = 0; i < this.entryHeaderNode.childNodes.length; i++){
+				 this.entryHeaderNode.removeChild(this.entryHeaderNode.childNodes[i]);
+			 }
+		 }
+	},
+
+	destroy: function(){
+		this.clear();
+	}
 });
-_4f.play();
-_50.play();
-}else{
-dojo.style(this.entryCheckBoxRow,"display","none");
-dojo.style(this.entryCheckBoxRow2,"display","none");
-dojo.style(this.entryCheckBoxDisplayOptions,"display","");
-}
-this._optionButtonDisplayed=true;
-}
-}
-},_handleEvent:function(_51){
-if(_51.source!=this){
-if(_51.action=="set"&&_51.entry){
-this.setEntry(_51.entry,_51.feed);
-}else{
-if(_51.action=="delete"&&_51.entry&&_51.entry==this._entry){
-this.clear();
-}
-}
-}
-},setFieldValidity:function(_52,_53){
-if(_52){
-var _54=_52.toLowerCase();
-this._validEntryFields[_52]=_53;
-}
-},isFieldValid:function(_55){
-return this._validEntryFields[_55.toLowerCase()];
-},getEntry:function(){
-return this._entry;
-},getFeed:function(){
-return this._feed;
-},destroy:function(){
-this.clear();
-dojo.forEach(this._subscriptions,dojo.unsubscribe);
-}});
-dojo.declare("dojox.atom.widget.EntryHeader",[dijit._Widget,dijit._Templated,dijit._Container],{title:"",templateString:dojo.cache("dojox.atom","widget/templates/EntryHeader.html","<span dojoAttachPoint=\"entryHeaderNode\" class=\"entryHeaderNode\"></span>\n"),postCreate:function(){
-this.setListHeader();
-},setListHeader:function(_56){
-this.clear();
-if(_56){
-this.title=_56;
-}
-var _57=document.createTextNode(this.title);
-this.entryHeaderNode.appendChild(_57);
-},clear:function(){
-this.destroyDescendants();
-if(this.entryHeaderNode){
-for(var i=0;i<this.entryHeaderNode.childNodes.length;i++){
-this.entryHeaderNode.removeChild(this.entryHeaderNode.childNodes[i]);
-}
-}
-},destroy:function(){
-this.clear();
-}});
-}
diff --git a/dojox/atom/widget/FeedViewer.js b/dojox/atom/widget/FeedViewer.js
index 61fc72f..b23129f 100644
--- a/dojox/atom/widget/FeedViewer.js
+++ b/dojox/atom/widget/FeedViewer.js
@@ -1,410 +1,798 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.atom.widget.FeedViewer"]){
-dojo._hasResource["dojox.atom.widget.FeedViewer"]=true;
 dojo.provide("dojox.atom.widget.FeedViewer");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Container");
 dojo.require("dojox.atom.io.Connection");
-dojo.requireLocalization("dojox.atom.widget","FeedViewerEntry",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
+dojo.requireLocalization("dojox.atom.widget", "FeedViewerEntry");
+
 dojo.experimental("dojox.atom.widget.FeedViewer");
-dojo.declare("dojox.atom.widget.FeedViewer",[dijit._Widget,dijit._Templated,dijit._Container],{feedViewerTableBody:null,feedViewerTable:null,entrySelectionTopic:"",url:"",xmethod:false,localSaveOnly:false,templateString:dojo.cache("dojox.atom","widget/templates/FeedViewer.html","<div class=\"feedViewerContainer\" dojoAttachPoint=\"feedViewerContainerNode\">\n\t<table cellspacing=\"0\" cellpadding=\"0\" class=\"feedViewerTable\">\n\t\t<tbody dojoAttachPoint=\"feedViewerTableBody\" class=\ [...]
-this._includeFilters=[];
-if(this.entrySelectionTopic!==""){
-this._subscriptions=[dojo.subscribe(this.entrySelectionTopic,this,"_handleEvent")];
-}
-this.atomIO=new dojox.atom.io.Connection();
-this.childWidgets=[];
-},startup:function(){
-this.containerNode=this.feedViewerTableBody;
-var _1=this.getDescendants();
-for(var i in _1){
-var _2=_1[i];
-if(_2&&_2.isFilter){
-this._includeFilters.push(new dojox.atom.widget.FeedViewer.CategoryIncludeFilter(_2.scheme,_2.term,_2.label));
-_2.destroy();
-}
-}
-if(this.url!==""){
-this.setFeedFromUrl(this.url);
-}
-},clear:function(){
-this.destroyDescendants();
-},setFeedFromUrl:function(_3){
-if(_3!==""){
-if(this._isRelativeURL(_3)){
-var _4="";
-if(_3.charAt(0)!=="/"){
-_4=this._calculateBaseURL(window.location.href,true);
-}else{
-_4=this._calculateBaseURL(window.location.href,false);
-}
-this.url=_4+_3;
-}
-this.atomIO.getFeed(_3,dojo.hitch(this,this.setFeed));
-}
-},setFeed:function(_5){
-this._feed=_5;
-this.clear();
-var _6=function(a,b){
-var _7=this._displayDateForEntry(a);
-var _8=this._displayDateForEntry(b);
-if(_7>_8){
-return -1;
-}
-if(_7<_8){
-return 1;
-}
-return 0;
-};
-var _9=function(_a){
-var _b=_a.split(",");
-_b.pop();
-return _b.join(",");
-};
-var _c=_5.entries.sort(dojo.hitch(this,_6));
-if(_5){
-var _d=null;
-for(var i=0;i<_c.length;i++){
-var _e=_c[i];
-if(this._isFilterAccepted(_e)){
-var _f=this._displayDateForEntry(_e);
-var _10="";
-if(_f!==null){
-_10=_9(_f.toLocaleString());
-if(_10===""){
-_10=""+(_f.getMonth()+1)+"/"+_f.getDate()+"/"+_f.getFullYear();
-}
-}
-if((_d===null)||(_d!=_10)){
-this.appendGrouping(_10);
-_d=_10;
-}
-this.appendEntry(_e);
-}
-}
-}
-},_displayDateForEntry:function(_11){
-if(_11.updated){
-return _11.updated;
-}
-if(_11.modified){
-return _11.modified;
-}
-if(_11.issued){
-return _11.issued;
-}
-return new Date();
-},appendGrouping:function(_12){
-var _13=new dojox.atom.widget.FeedViewerGrouping({});
-_13.setText(_12);
-this.addChild(_13);
-this.childWidgets.push(_13);
-},appendEntry:function(_14){
-var _15=new dojox.atom.widget.FeedViewerEntry({"xmethod":this.xmethod});
-_15.setTitle(_14.title.value);
-_15.setTime(this._displayDateForEntry(_14).toLocaleTimeString());
-_15.entrySelectionTopic=this.entrySelectionTopic;
-_15.feed=this;
-this.addChild(_15);
-this.childWidgets.push(_15);
-this.connect(_15,"onClick","_rowSelected");
-_14.domNode=_15.entryNode;
-_14._entryWidget=_15;
-_15.entry=_14;
-},deleteEntry:function(_16){
-if(!this.localSaveOnly){
-this.atomIO.deleteEntry(_16.entry,dojo.hitch(this,this._removeEntry,_16),null,this.xmethod);
-}else{
-this._removeEntry(_16,true);
-}
-dojo.publish(this.entrySelectionTopic,[{action:"delete",source:this,entry:_16.entry}]);
-},_removeEntry:function(_17,_18){
-if(_18){
-var idx=dojo.indexOf(this.childWidgets,_17);
-var _19=this.childWidgets[idx-1];
-var _1a=this.childWidgets[idx+1];
-if(_19.declaredClass==="dojox.atom.widget.FeedViewerGrouping"&&(_1a===undefined||_1a.declaredClass==="dojox.atom.widget.FeedViewerGrouping")){
-_19.destroy();
-}
-_17.destroy();
-}else{
-}
-},_rowSelected:function(evt){
-var _1b=evt.target;
-while(_1b){
-if(_1b.attributes){
-var _1c=_1b.attributes.getNamedItem("widgetid");
-if(_1c&&_1c.value.indexOf("FeedViewerEntry")!=-1){
-break;
-}
-}
-_1b=_1b.parentNode;
-}
-for(var i=0;i<this._feed.entries.length;i++){
-var _1d=this._feed.entries[i];
-if((_1b===_1d.domNode)&&(this._currentSelection!==_1d)){
-dojo.addClass(_1d.domNode,"feedViewerEntrySelected");
-dojo.removeClass(_1d._entryWidget.timeNode,"feedViewerEntryUpdated");
-dojo.addClass(_1d._entryWidget.timeNode,"feedViewerEntryUpdatedSelected");
-this.onEntrySelected(_1d);
-if(this.entrySelectionTopic!==""){
-dojo.publish(this.entrySelectionTopic,[{action:"set",source:this,feed:this._feed,entry:_1d}]);
-}
-if(this._isEditable(_1d)){
-_1d._entryWidget.enableDelete();
-}
-this._deselectCurrentSelection();
-this._currentSelection=_1d;
-break;
-}else{
-if((_1b===_1d.domNode)&&(this._currentSelection===_1d)){
-dojo.publish(this.entrySelectionTopic,[{action:"delete",source:this,entry:_1d}]);
-this._deselectCurrentSelection();
-break;
-}
-}
-}
-},_deselectCurrentSelection:function(){
-if(this._currentSelection){
-dojo.addClass(this._currentSelection._entryWidget.timeNode,"feedViewerEntryUpdated");
-dojo.removeClass(this._currentSelection.domNode,"feedViewerEntrySelected");
-dojo.removeClass(this._currentSelection._entryWidget.timeNode,"feedViewerEntryUpdatedSelected");
-this._currentSelection._entryWidget.disableDelete();
-this._currentSelection=null;
-}
-},_isEditable:function(_1e){
-var _1f=false;
-if(_1e&&_1e!==null&&_1e.links&&_1e.links!==null){
-for(var x in _1e.links){
-if(_1e.links[x].rel&&_1e.links[x].rel=="edit"){
-_1f=true;
-break;
-}
-}
-}
-return _1f;
-},onEntrySelected:function(_20){
-},_isRelativeURL:function(url){
-var _21=function(url){
-var _22=false;
-if(url.indexOf("file://")===0){
-_22=true;
-}
-return _22;
-};
-var _23=function(url){
-var _24=false;
-if(url.indexOf("http://")===0){
-_24=true;
-}
-return _24;
-};
-var _25=false;
-if(url!==null){
-if(!_21(url)&&!_23(url)){
-_25=true;
-}
-}
-return _25;
-},_calculateBaseURL:function(_26,_27){
-var _28=null;
-if(_26!==null){
-var _29=_26.indexOf("?");
-if(_29!=-1){
-_26=_26.substring(0,_29);
-}
-if(_27){
-_29=_26.lastIndexOf("/");
-if((_29>0)&&(_29<_26.length)&&(_29!==(_26.length-1))){
-_28=_26.substring(0,(_29+1));
-}else{
-_28=_26;
-}
-}else{
-_29=_26.indexOf("://");
-if(_29>0){
-_29=_29+3;
-var _2a=_26.substring(0,_29);
-var _2b=_26.substring(_29,_26.length);
-_29=_2b.indexOf("/");
-if((_29<_2b.length)&&(_29>0)){
-_28=_2a+_2b.substring(0,_29);
-}else{
-_28=_2a+_2b;
-}
-}
-}
-}
-return _28;
-},_isFilterAccepted:function(_2c){
-var _2d=false;
-if(this._includeFilters&&(this._includeFilters.length>0)){
-for(var i=0;i<this._includeFilters.length;i++){
-var _2e=this._includeFilters[i];
-if(_2e.match(_2c)){
-_2d=true;
-break;
-}
-}
-}else{
-_2d=true;
-}
-return _2d;
-},addCategoryIncludeFilter:function(_2f){
-if(_2f){
-var _30=_2f.scheme;
-var _31=_2f.term;
-var _32=_2f.label;
-var _33=true;
-if(!_30){
-_30=null;
-}
-if(!_31){
-_30=null;
-}
-if(!_32){
-_30=null;
-}
-if(this._includeFilters&&this._includeFilters.length>0){
-for(var i=0;i<this._includeFilters.length;i++){
-var _34=this._includeFilters[i];
-if((_34.term===_31)&&(_34.scheme===_30)&&(_34.label===_32)){
-_33=false;
-break;
-}
-}
-}
-if(_33){
-this._includeFilters.push(dojox.atom.widget.FeedViewer.CategoryIncludeFilter(_30,_31,_32));
-}
-}
-},removeCategoryIncludeFilter:function(_35){
-if(_35){
-var _36=_35.scheme;
-var _37=_35.term;
-var _38=_35.label;
-if(!_36){
-_36=null;
-}
-if(!_37){
-_36=null;
-}
-if(!_38){
-_36=null;
-}
-var _39=[];
-if(this._includeFilters&&this._includeFilters.length>0){
-for(var i=0;i<this._includeFilters.length;i++){
-var _3a=this._includeFilters[i];
-if(!((_3a.term===_37)&&(_3a.scheme===_36)&&(_3a.label===_38))){
-_39.push(_3a);
-}
-}
-this._includeFilters=_39;
-}
-}
-},_handleEvent:function(_3b){
-if(_3b.source!=this){
-if(_3b.action=="update"&&_3b.entry){
-var evt=_3b;
-if(!this.localSaveOnly){
-this.atomIO.updateEntry(evt.entry,dojo.hitch(evt.source,evt.callback),null,true);
-}
-this._currentSelection._entryWidget.setTime(this._displayDateForEntry(evt.entry).toLocaleTimeString());
-this._currentSelection._entryWidget.setTitle(evt.entry.title.value);
-}else{
-if(_3b.action=="post"&&_3b.entry){
-if(!this.localSaveOnly){
-this.atomIO.addEntry(_3b.entry,this.url,dojo.hitch(this,this._addEntry));
-}else{
-this._addEntry(_3b.entry);
-}
-}
-}
-}
-},_addEntry:function(_3c){
-this._feed.addEntry(_3c);
-this.setFeed(this._feed);
-dojo.publish(this.entrySelectionTopic,[{action:"set",source:this,feed:this._feed,entry:_3c}]);
-},destroy:function(){
-this.clear();
-dojo.forEach(this._subscriptions,dojo.unsubscribe);
-}});
-dojo.declare("dojox.atom.widget.FeedViewerEntry",[dijit._Widget,dijit._Templated],{templateString:dojo.cache("dojox.atom","widget/templates/FeedViewerEntry.html","<tr class=\"feedViewerEntry\" dojoAttachPoint=\"entryNode\" dojoAttachEvent=\"onclick:onClick\">\n    <td class=\"feedViewerEntryUpdated\" dojoAttachPoint=\"timeNode\">\n    </td>\n    <td>\n        <table border=\"0\" width=\"100%\" dojoAttachPoint=\"titleRow\">\n            <tr padding=\"0\" border=\"0\">\n                <td [...]
-var _3d=dojo.i18n.getLocalization("dojox.atom.widget","FeedViewerEntry");
-this.deleteButton.innerHTML=_3d.deleteButton;
-},setTitle:function(_3e){
-if(this.titleNode.lastChild){
-this.titleNode.removeChild(this.titleNode.lastChild);
-}
-var _3f=document.createElement("div");
-_3f.innerHTML=_3e;
-this.titleNode.appendChild(_3f);
-},setTime:function(_40){
-if(this.timeNode.lastChild){
-this.timeNode.removeChild(this.timeNode.lastChild);
-}
-var _41=document.createTextNode(_40);
-this.timeNode.appendChild(_41);
-},enableDelete:function(){
-if(this.deleteButton!==null){
-this.deleteButton.style.display="inline";
-}
-},disableDelete:function(){
-if(this.deleteButton!==null){
-this.deleteButton.style.display="none";
-}
-},deleteEntry:function(_42){
-_42.preventDefault();
-_42.stopPropagation();
-this.feed.deleteEntry(this);
-},onClick:function(e){
-}});
-dojo.declare("dojox.atom.widget.FeedViewerGrouping",[dijit._Widget,dijit._Templated],{templateString:dojo.cache("dojox.atom","widget/templates/FeedViewerGrouping.html","<tr dojoAttachPoint=\"groupingNode\" class=\"feedViewerGrouping\">\n\t<td colspan=\"2\" dojoAttachPoint=\"titleNode\" class=\"feedViewerGroupingTitle\">\n\t</td>\n</tr>\n"),groupingNode:null,titleNode:null,setText:function(_43){
-if(this.titleNode.lastChild){
-this.titleNode.removeChild(this.titleNode.lastChild);
-}
-var _44=document.createTextNode(_43);
-this.titleNode.appendChild(_44);
-}});
-dojo.declare("dojox.atom.widget.AtomEntryCategoryFilter",[dijit._Widget,dijit._Templated],{scheme:"",term:"",label:"",isFilter:true});
-dojo.declare("dojox.atom.widget.FeedViewer.CategoryIncludeFilter",null,{constructor:function(_45,_46,_47){
-this.scheme=_45;
-this.term=_46;
-this.label=_47;
-},match:function(_48){
-var _49=false;
-if(_48!==null){
-var _4a=_48.categories;
-if(_4a!==null){
-for(var i=0;i<_4a.length;i++){
-var _4b=_4a[i];
-if(this.scheme!==""){
-if(this.scheme!==_4b.scheme){
-break;
-}
-}
-if(this.term!==""){
-if(this.term!==_4b.term){
-break;
-}
-}
-if(this.label!==""){
-if(this.label!==_4b.label){
-break;
-}
-}
-_49=true;
-}
-}
-}
-return _49;
-}});
-}
+
+dojo.declare("dojox.atom.widget.FeedViewer",[dijit._Widget, dijit._Templated, dijit._Container],{
+	//	summary:  
+	//		An ATOM feed viewer that allows for viewing a feed, deleting entries, and editing entries.
+	//	description:  
+	//		An ATOM feed viewer that allows for viewing a feed, deleting entries, and editing entries.
+	feedViewerTableBody: null,	//The body of the feed viewer table so we can access it and populate it.  Will be assigned via template.
+	feedViewerTable: null,		//The overal table container which contains the feed viewer table.  Will be assigned via template.
+	entrySelectionTopic: "",	//The topic to broadcast when any entry is clicked so that a listener can pick up it and display it.
+	url: "",					//The URL to which to connect to initially on creation.
+	xmethod: false,
+	localSaveOnly: false,
+
+	//Templates for the HTML rendering.  Need to figure these out better, admittedly.
+	templateString: dojo.cache("dojox.atom", "widget/templates/FeedViewer.html"),
+
+	_feed: null,
+	_currentSelection: null, // Currently selected entry
+
+	_includeFilters: null,
+
+	alertsEnabled: false,
+
+	postCreate: function(){
+		//	summary: 
+		//		The postCreate function.  
+		//	description: 
+		//		The postCreate function.  Creates our AtomIO object for future interactions and subscribes to the 
+		//		event given in markup/creation.
+		this._includeFilters = [];
+
+		if(this.entrySelectionTopic !== ""){
+			this._subscriptions = [dojo.subscribe(this.entrySelectionTopic, this, "_handleEvent")];
+		}
+		this.atomIO = new dojox.atom.io.Connection();
+		this.childWidgets = [];
+	},
+	
+	startup: function(){
+		//	summary: 
+		//		The startup function.
+		//	description: 
+		//		The startup function.  Parses the filters and sets the feed based on the given url.
+		this.containerNode = this.feedViewerTableBody;
+		var children = this.getDescendants();
+		for(var i in children){
+			var child = children[i];
+			if(child && child.isFilter){
+				this._includeFilters.push(new dojox.atom.widget.FeedViewer.CategoryIncludeFilter(child.scheme, child.term, child.label));
+				child.destroy();
+			}
+		}
+		
+		if(this.url !== ""){
+			this.setFeedFromUrl(this.url);
+		}
+	},
+
+	clear: function(){
+		//	summary:
+		//		Function clearing all current entries in the feed view.
+		//	description: 
+		//		Function clearing all current entries in the feed view.
+		//
+		//	returns:  
+		//		Nothing. 
+		this.destroyDescendants();
+	},
+
+	setFeedFromUrl: function(/*string*/url){
+		//	summary: 
+		//		Function setting the feed from a URL which to get the feed.
+		//	description: 
+		//		Function setting the dojox.atom.io.model.Feed data into the view.
+		//
+		//	url:
+		//		The URL to the feed to load.
+		//
+		//	returns:  
+		//		Nothing.
+		if(url !== ""){
+			if(this._isRelativeURL(url)){
+				var baseUrl = "";
+				if(url.charAt(0) !== '/'){
+					baseUrl = this._calculateBaseURL(window.location.href, true);
+				}else{
+					baseUrl = this._calculateBaseURL(window.location.href, false);
+				}
+				this.url = baseUrl + url;
+			}
+
+			this.atomIO.getFeed(url,dojo.hitch(this,this.setFeed));
+		}
+	},
+
+
+	setFeed: function(/*object*/feed){
+		//	summary: 
+		//		Function setting the dojox.atom.io.model.Feed data into the view.
+		//	description: 
+		//		Function setting the dojox.atom.io.model.Feed data into the view.
+		//
+		//	entry:
+		//		The dojox.atom.io.model.Feed object to process
+		//
+		//	returns:
+		//		Nothing.
+		this._feed = feed;
+		this.clear();
+		var entrySorter=function(a,b){
+			var dispA = this._displayDateForEntry(a);
+			var dispB = this._displayDateForEntry(b);
+			if(dispA > dispB){return -1;}
+			if(dispA < dispB){return 1;}
+			return 0; 
+		};
+
+		// This function may not be safe in different locales.
+		var groupingStr = function(dateStr){
+			var dpts = dateStr.split(',');
+			
+			dpts.pop(); // remove year and time
+			return dpts.join(",");
+		};
+		var sortedEntries = feed.entries.sort(dojo.hitch(this,entrySorter));
+		if(feed){
+			var lastSectionTitle = null;
+			for(var i=0;i<sortedEntries.length;i++){
+				
+				var entry = sortedEntries[i];
+
+				if(this._isFilterAccepted(entry)){
+					var time = this._displayDateForEntry(entry);
+					var sectionTitle = "";
+
+					if(time !== null){
+						sectionTitle = groupingStr(time.toLocaleString());
+
+						if(sectionTitle === "" ){
+							//Generally an issue on Opera with how its toLocaleString() works, so do a quick and dirty date construction M/D/Y
+							sectionTitle = "" + (time.getMonth() + 1) + "/" + time.getDate() + "/" + time.getFullYear();
+						}
+					}
+					if((lastSectionTitle === null) || (lastSectionTitle != sectionTitle)){
+						this.appendGrouping(sectionTitle);
+						lastSectionTitle = sectionTitle;
+					}
+					this.appendEntry(entry);
+				}
+			}
+		}
+	},
+
+	_displayDateForEntry: function(/*object*/entry){
+		//	summary: 
+		//		Internal function for determining the appropriate date to display.
+		//		description: Internal function for determining of a particular entry is editable.
+		//
+		//	entry:
+		//		The dojox.atom.io.model.Entry object to examine.
+		//
+		//	returns:  
+		//		An appropriate date for the feed viewer display.
+		if(entry.updated){return entry.updated;}
+		if(entry.modified){return entry.modified;}
+		if(entry.issued){return entry.issued;}
+		return new Date();
+	},
+
+	appendGrouping: function(/*string*/titleText){
+		//	summary: 
+		//		Function for appending a new grouping of entries to the feed view.
+		//	description: 
+		//		Function for appending a grouping of entries to the feed view.
+		//
+		//	entry:
+		//		The title of the new grouping to create on the view.
+		//
+		//	returns:  
+		//		Nothing. 
+		var entryWidget = new dojox.atom.widget.FeedViewerGrouping({});
+		entryWidget.setText(titleText);
+		this.addChild(entryWidget);
+		this.childWidgets.push(entryWidget);
+	},
+
+	appendEntry: function(/*object*/entry){
+		//	summary: 
+		//		Function for appending an entry to the feed view.
+		//	description: 
+		//		Function for appending an entry to the feed view.
+		//
+		//	entry:
+		//		The dojox.atom.io.model.Entry object to append
+		//
+		//	returns:
+		//		Nothing.
+		var entryWidget = new dojox.atom.widget.FeedViewerEntry({"xmethod": this.xmethod});
+		entryWidget.setTitle(entry.title.value);
+		entryWidget.setTime(this._displayDateForEntry(entry).toLocaleTimeString());
+		entryWidget.entrySelectionTopic = this.entrySelectionTopic;
+		entryWidget.feed = this;
+		this.addChild(entryWidget);
+		this.childWidgets.push(entryWidget);
+		this.connect(entryWidget, "onClick", "_rowSelected");
+		entry.domNode = entryWidget.entryNode;
+		
+		//Need to set up a bi-directional reference here to control events between the two.
+		entry._entryWidget = entryWidget;
+		entryWidget.entry = entry;
+	},
+	
+	deleteEntry: function(/*object*/entryRow){
+		//	summary: 
+		//		Function for deleting a row from the view
+		//	description: 
+		//		Function for deleting a row from the view
+		if(!this.localSaveOnly){
+			this.atomIO.deleteEntry(entryRow.entry, dojo.hitch(this, this._removeEntry, entryRow), null, this.xmethod);
+		}else{
+			this._removeEntry(entryRow, true);
+		}
+		dojo.publish(this.entrySelectionTopic, [{ action: "delete", source: this, entry: entryRow.entry }]);
+	},
+
+	_removeEntry: function(/*FeedViewerEntry*/ entry, /* boolean */success){
+		//	summary: 
+		//		callback for when an entry is deleted from a feed.
+		//	description: 
+		//		callback for when an entry is deleted from a feed.
+		if(success){
+			/* Check if this is the last Entry beneath the given date */
+			var idx = dojo.indexOf(this.childWidgets, entry);
+			var before = this.childWidgets[idx-1];
+			var after = this.childWidgets[idx+1];
+			if( before.declaredClass === 'dojox.atom.widget.FeedViewerGrouping' && 
+				(after === undefined || after.declaredClass === 'dojox.atom.widget.FeedViewerGrouping')){
+				before.destroy();
+			}
+			
+			/* Destroy the FeedViewerEntry to remove it from the view */
+			entry.destroy();
+		}else{}
+	},
+	
+	_rowSelected: function(/*object*/evt){
+		//	summary: 
+		//		Internal function for handling the selection of feed entries.
+		//	description: 
+		//		Internal function for handling the selection of feed entries.
+		//
+		//	evt:
+		//		The click event that triggered a selection.
+		//
+		//	returns:  
+		//		Nothing.
+		var selectedNode = evt.target;
+		while(selectedNode){
+			if(selectedNode.attributes){
+				var widgetid = selectedNode.attributes.getNamedItem("widgetid");
+				if(widgetid && widgetid.value.indexOf("FeedViewerEntry") != -1){
+					break;
+				}
+			}
+			selectedNode = selectedNode.parentNode;
+		}
+
+		for(var i=0;i<this._feed.entries.length;i++){
+			var entry = this._feed.entries[i];
+			if( (selectedNode === entry.domNode) && (this._currentSelection !== entry) ){
+				//Found it and it isn't already selected.
+				dojo.addClass(entry.domNode, "feedViewerEntrySelected");
+				dojo.removeClass(entry._entryWidget.timeNode, "feedViewerEntryUpdated");
+				dojo.addClass(entry._entryWidget.timeNode, "feedViewerEntryUpdatedSelected");
+
+				this.onEntrySelected(entry);
+				if(this.entrySelectionTopic !== ""){
+					dojo.publish(this.entrySelectionTopic, [{ action: "set", source: this, feed: this._feed, entry: entry }]);
+				}
+				if(this._isEditable(entry)){
+					entry._entryWidget.enableDelete();
+				}
+
+				this._deselectCurrentSelection();
+				this._currentSelection = entry;
+				break;
+			}else if( (selectedNode === entry.domNode) && (this._currentSelection === entry) ){
+				//Found it and it is the current selection, we just want to de-select it so users can 'unselect rows' if they want.
+				dojo.publish(this.entrySelectionTopic, [{ action: "delete", source: this, entry: entry }]);
+				this._deselectCurrentSelection();
+				break;
+			}
+		}
+	},
+
+	_deselectCurrentSelection: function(){
+		//	summary: 
+		//		Internal function for unselecting the current selection.
+		//	description: 
+		//		Internal function for unselecting the current selection.
+		//
+		//	returns:  
+		//		Nothing. 
+		if(this._currentSelection){
+			dojo.addClass(this._currentSelection._entryWidget.timeNode, "feedViewerEntryUpdated");
+			dojo.removeClass(this._currentSelection.domNode, "feedViewerEntrySelected");
+			dojo.removeClass(this._currentSelection._entryWidget.timeNode, "feedViewerEntryUpdatedSelected");
+			this._currentSelection._entryWidget.disableDelete();
+			this._currentSelection = null;
+		}
+	}, 
+
+
+	_isEditable: function(/*object*/entry){
+		//	summary: 
+		//		Internal function for determining of a particular entry is editable.
+		//	description: 
+		//		Internal function for determining of a particular entry is editable.
+		//		This is used for determining if the delete action should be displayed or not.
+		//
+		//	entry: 
+		//		The dojox.atom.io.model.Entry object to examine
+		//
+		//	returns:  
+		//		Boolean denoting if the entry seems editable or not.. 
+		var retVal = false;
+		if(entry && entry !== null && entry.links && entry.links !== null){
+			for(var x in entry.links){
+				if(entry.links[x].rel && entry.links[x].rel == "edit"){
+					retVal = true;
+					break;
+				}
+			}
+		}
+		return retVal;
+	},
+
+	onEntrySelected: function(/*object*/entry){
+		//	summary: 
+		//		Function intended for over-riding/replacement as an attachpoint to for other items to recieve
+		//		selection notification.
+		//	description: Function intended for over0-riding/replacement as an attachpoint to for other items to recieve
+		//		selection notification.
+		//
+		//	entry:
+		//		The dojox.atom.io.model.Entry object selected.
+		//
+		//	returns:  
+		//		Nothing. 
+	},
+
+	_isRelativeURL: function(/*string*/url){
+		//	summary: 
+		//		Method to determine if the URL is relative or absolute.
+		//	description: 
+		//		Method to determine if the URL is relative or absolute.  Basic assumption is if it doesn't start 
+		//		with http:// or file://, it's relative to the current document.
+		//
+		//	url: 
+		//		The URL to inspect.
+		//
+		//	returns: 
+		//		boolean indicating whether it's a relative url or not.
+		var isFileURL = function(url){
+			var retVal = false;
+			if(url.indexOf("file://") === 0){
+				retVal = true;
+			}
+			return retVal;
+		}
+
+		var isHttpURL = function(url){
+			var retVal = false;
+			if(url.indexOf("http://") === 0){
+				retVal = true;
+			}
+			return retVal;
+		}
+
+		var retVal = false;
+		if(url !== null){
+			if(!isFileURL(url) && !isHttpURL(url)){
+				retVal = true;
+			}
+		}
+		return retVal;
+	},
+
+	_calculateBaseURL: function(/*string*/fullURL, /*boolean*/currentPageRelative){
+		//	summary: 
+		//		Internal function to calculate a baseline URL from the provided full URL.
+		//	description: 
+		//		Internal function to calculate a baseline URL from the provided full URL.
+		//
+		//	fullURL:
+		//		The full URL as a string.
+		//	currentPageRelative:
+		//		Flag to denote of the base URL should be calculated as just the server base, or relative to the current page/location in the URL.
+		//
+		//	returns: 
+		//		String of the baseline URL
+		var baseURL = null;
+		if(fullURL !== null){
+			//Check to see if we need to strip off any query parameters from the URL.
+			var index = fullURL.indexOf("?");
+			if(index != -1){
+				fullURL = fullURL.substring(0,index);
+				//console.debug("Removed query parameters.  URL now: " + fullURL);
+			}
+
+			if(currentPageRelative){
+				//Relative to the 'current page' in the URL, so we need to trim that off.
+				//Now we need to trim if necessary.  If it ends in /, then we don't have a filename to trim off
+				//so we can return.
+				index = fullURL.lastIndexOf("/");
+				if((index > 0) && (index < fullURL.length) && (index !== (fullURL.length -1))){
+					//We want to include the terminating /
+					baseURL = fullURL.substring(0,(index + 1));
+				}else{
+					baseURL = fullURL;
+				}
+			}else{
+				//We want to find the first occurance of / after the <protocol>://
+				index = fullURL.indexOf("://");
+				if(index > 0){
+					index = index + 3;
+					var protocol = fullURL.substring(0,index);
+					var fragmentURL = fullURL.substring(index, fullURL.length);
+					index = fragmentURL.indexOf("/");
+					if((index < fragmentURL.length) && (index > 0) ){
+						baseURL = protocol + fragmentURL.substring(0,index);
+					}else{
+						baseURL = protocol + fragmentURL;
+					}
+				}
+			}
+		}
+		return baseURL;
+	},
+
+	_isFilterAccepted: function(/*object*/entry) {
+		//	summary:
+		//		Internal function to do matching of category filters to widgets.
+		//	description: 
+		//		Internal function to do matching of category filters to widgets.
+		//
+		//	returns: 
+		//		boolean denoting if this entry matched one of the accept filters.
+		var accepted = false;
+		if (this._includeFilters && (this._includeFilters.length > 0)) {
+			for (var i = 0; i < this._includeFilters.length; i++) {
+				var filter = this._includeFilters[i];
+				if (filter.match(entry)) {
+					accepted = true;
+					break;
+				}
+			}
+		}
+		else {
+			accepted = true;
+		}
+		return accepted;
+	},
+
+	addCategoryIncludeFilter: function(/*object*/filter) {
+		//	summary: 
+		//		Function to add a filter for entry inclusion in the feed view.
+		//	description: 
+		//		Function to add a filter for entry inclusion in the feed view.
+		// 
+		//	filter: 
+		//		The basic items to filter on and the values.  
+		//		Should be of format: {scheme: <some text or null>, term: <some text or null>, label: <some text or null>}
+		//
+		//	returns: 
+		//		Nothing.
+		if (filter) {
+			var scheme = filter.scheme;
+			var term = filter.term;
+			var label = filter.label;
+			var addIt = true;
+
+			if (!scheme) {
+				scheme = null;
+			}
+			if (!term) {
+				scheme = null;
+			}
+			if (!label) {
+				scheme = null;
+			}
+			
+			if (this._includeFilters && this._includeFilters.length > 0) {
+				for (var i = 0; i < this._includeFilters.length; i++) {
+					var eFilter = this._includeFilters[i];
+					if ((eFilter.term === term) && (eFilter.scheme === scheme) && (eFilter.label === label)) {
+						//Verify we don't have this filter already.
+						addIt = false;
+						break;
+					}
+				}
+			}
+
+			if (addIt) {
+				this._includeFilters.push(dojox.atom.widget.FeedViewer.CategoryIncludeFilter(scheme, term, label));
+			}
+		}
+	},
+
+	removeCategoryIncludeFilter: function(/*object*/filter) {
+		//	summary: 
+		//		Function to remove a filter for entry inclusion in the feed view.
+		//	description: 
+		//		Function to remove a filter for entry inclusion in the feed view.
+		// 
+		//	filter:
+		//		The basic items to identify the filter that is present.
+		//		Should be of format: {scheme: <some text or null>, term: <some text or null>, label: <some text or null>}
+		//
+		//	returns: 
+		//		Nothing.
+		if (filter) {
+			var scheme = filter.scheme;
+			var term = filter.term;
+			var label = filter.label;
+
+			if (!scheme) {
+				scheme = null;
+			}
+			if (!term) {
+				scheme = null;
+			}
+			if (!label) {
+				scheme = null;
+			}
+			
+			var newFilters = [];
+			if (this._includeFilters && this._includeFilters.length > 0) {
+				for (var i = 0; i < this._includeFilters.length; i++) {
+					var eFilter = this._includeFilters[i];
+					if (!((eFilter.term === term) && (eFilter.scheme === scheme) && (eFilter.label === label))) {
+						//Keep only filters that do not match
+						newFilters.push(eFilter);
+					}
+				}
+				this._includeFilters = newFilters;
+			}
+		}
+	},
+
+	_handleEvent: function(/*object*/entrySelectionEvent) {
+		//	summary: 
+		//		Internal function for listening to a topic that will handle entry notification.
+		//	description: 
+		//		Internal function for listening to a topic that will handle entry notification.
+		//
+		//	entrySelectionEvent:
+		//		The topic message containing the entry that was selected for view.
+		//
+		//	returns:
+		//		Nothing.
+		if(entrySelectionEvent.source != this) {
+			if(entrySelectionEvent.action == "update" && entrySelectionEvent.entry) {
+                var evt = entrySelectionEvent;
+				if(!this.localSaveOnly){
+					this.atomIO.updateEntry(evt.entry, dojo.hitch(evt.source,evt.callback), null, true);
+				}
+				this._currentSelection._entryWidget.setTime(this._displayDateForEntry(evt.entry).toLocaleTimeString());
+				this._currentSelection._entryWidget.setTitle(evt.entry.title.value);
+			} else if(entrySelectionEvent.action == "post" && entrySelectionEvent.entry) {
+				if(!this.localSaveOnly){
+					this.atomIO.addEntry(entrySelectionEvent.entry, this.url, dojo.hitch(this,this._addEntry));
+				}else{
+					this._addEntry(entrySelectionEvent.entry);
+				}
+			}
+		}
+	},
+	
+	_addEntry: function(/*object*/entry) {
+		//	summary: 
+		//		callback function used when adding an entry to the feed.
+		//	description: 
+		//		callback function used when adding an entry to the feed.  After the entry has been posted to the feed,
+		//		we add it to our feed representation (to show it on the page) and publish an event to update any entry viewers.
+		this._feed.addEntry(entry);
+		this.setFeed(this._feed);
+		dojo.publish(this.entrySelectionTopic, [{ action: "set", source: this, feed: this._feed, entry: entry }]);
+	},
+
+	destroy: function(){
+		//	summary: 
+		//		Destroys this widget, including all descendants and subscriptions.
+		//	description: 
+		//		Destroys this widget, including all descendants and subscriptions.
+		this.clear();
+		dojo.forEach(this._subscriptions, dojo.unsubscribe);
+	}
+});
+
+dojo.declare("dojox.atom.widget.FeedViewerEntry",[dijit._Widget, dijit._Templated],{
+	//	summary: 
+	//		Widget for handling the display of an entry and specific events associated with it.
+	//		description: Widget for handling the display of an entry and specific events associated with it.
+
+	templateString: dojo.cache("dojox.atom", "widget/templates/FeedViewerEntry.html"),
+
+	entryNode: null,
+	timeNode: null,
+	deleteButton: null,
+	entry: null,
+	feed: null,
+
+	postCreate: function(){
+		var _nlsResources = dojo.i18n.getLocalization("dojox.atom.widget", "FeedViewerEntry");
+		this.deleteButton.innerHTML = _nlsResources.deleteButton;
+	},
+
+	setTitle: function(/*string*/text){
+		//	summary: 
+		//		Function to set the title of the entry.
+		//	description: 
+		//		Function to set the title of the entry.
+		//
+		//	text: 
+		//		The title.
+		//
+		//	returns:
+		//		Nothing. 
+		if (this.titleNode.lastChild){this.titleNode.removeChild(this.titleNode.lastChild);}
+		
+		var titleTextNode = document.createElement("div");
+		titleTextNode.innerHTML = text;
+		this.titleNode.appendChild(titleTextNode);
+	},
+
+	setTime: function(/*string*/timeText){
+		//	summary: 
+		//		Function to set the time of the entry.
+		//	description: 
+		//		Function to set the time of the entry.
+		//
+		//	timeText: 
+		//		The string form of the date.
+		//
+		//	returns:
+		//		Nothing. 
+		if (this.timeNode.lastChild){this.timeNode.removeChild(this.timeNode.lastChild);}
+		var timeTextNode = document.createTextNode(timeText);
+		this.timeNode.appendChild(timeTextNode);
+	},
+
+	enableDelete: function(){
+		//	summary: 
+		//		Function to enable the delete action on this entry.
+		//	description:
+		//		Function to enable the delete action on this entry.
+		//
+		//	returns:
+		//		Nothing. 
+		if (this.deleteButton !== null) {
+			//TODO Fix this
+			this.deleteButton.style.display = 'inline';
+		}
+	},
+
+	disableDelete: function(){
+		//	summary: 
+		//		Function to disable the delete action on this entry.
+		//	description: 
+		//		Function to disable the delete action on this entry.
+		//
+		// 	returns:  
+		//		Nothing. 
+		if (this.deleteButton !== null) {
+			this.deleteButton.style.display = 'none';
+		}
+	},
+
+	deleteEntry: function(/*object*/event) {
+		//	summary: 
+		//		Function to handle the delete event and delete the entry.
+		// 	description: 
+		//		Function to handle the delete event and delete the entry.
+		//
+		//	returns:
+		//		Nothing.
+		event.preventDefault();
+		event.stopPropagation();
+		this.feed.deleteEntry(this);
+	},
+
+	onClick: function(/*object*/e){
+		//	summary: 
+		//		Attach point for when a row is clicked on.
+		// 	description: 
+		//		Attach point for when a row is clicked on.
+		//
+		// 	e: 
+		//		The event generated by the click.
+	}
+});
+
+dojo.declare("dojox.atom.widget.FeedViewerGrouping",[dijit._Widget, dijit._Templated],{
+	//	summary: 
+	//		Grouping of feed entries.
+	//	description: 
+	//		Grouping of feed entries.
+	templateString: dojo.cache("dojox.atom", "widget/templates/FeedViewerGrouping.html"),
+	
+	groupingNode: null,
+	titleNode: null,
+
+	setText: function(text){
+		//	summary: 
+		//		Sets the text to be shown above this grouping.
+		//	description: 
+		//		Sets the text to be shown above this grouping.
+		//
+		//	text:
+		//		The text to show.
+		if (this.titleNode.lastChild){this.titleNode.removeChild(this.titleNode.lastChild);}
+		var textNode = document.createTextNode(text);
+		this.titleNode.appendChild(textNode);
+	}
+});
+
+dojo.declare("dojox.atom.widget.AtomEntryCategoryFilter",[dijit._Widget, dijit._Templated],{
+	//	summary: 
+	//		A filter to be applied to the list of entries.
+	//	description: 
+	//		A filter to be applied to the list of entries.
+	scheme: "",
+	term: "",
+	label: "",
+	isFilter: true
+});			
+
+dojo.declare("dojox.atom.widget.FeedViewer.CategoryIncludeFilter",null,{
+	constructor: function(scheme, term, label){
+		//	summary:
+		//		The initializer function.
+		//	description:
+		//		The initializer function.
+		this.scheme = scheme; 
+		this.term = term; 
+		this.label = label;
+	},
+
+	match: function(entry) {
+		//	summary: 
+		//		Function to determine if this category filter matches against a category on an atom entry
+		//	description: 
+		//		Function to determine if this category filter matches against a category on an atom entry
+		//
+		//	returns:
+		//		boolean denoting if this category filter matched to this entry.
+		var matched = false;
+		if (entry !== null) {
+			var categories = entry.categories;
+			if (categories !== null) {
+				for (var i = 0; i < categories.length; i++) {
+					var category = categories[i];
+
+					if (this.scheme !== "") {
+						if (this.scheme !== category.scheme) {
+							break;
+						}
+					}
+					
+					if (this.term !== "") {
+						if (this.term !== category.term) {
+							break;
+						}
+					}
+
+					if (this.label !== "") {
+						if (this.label !== category.label) {
+							break;
+						}
+					}
+					//Made it this far, everything matched.
+					matched = true;
+				}
+			}
+		}
+		return matched;
+	}
+});
diff --git a/dojox/atom/widget/nls/FeedEntryEditor.js b/dojox/atom/widget/nls/FeedEntryEditor.js
index f7f1558..934e7a0 100644
--- a/dojox/atom/widget/nls/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[edit]","save":"[save]","cancel":"[cancel]","doNew":"[new]"})
\ No newline at end of file
+({
+	doNew: "[new]",
+	edit: "[edit]",
+	save: "[save]",
+	cancel: "[cancel]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/FeedEntryViewer.js b/dojox/atom/widget/nls/FeedEntryViewer.js
index b294695..3346210 100644
--- a/dojox/atom/widget/nls/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[close]","title":"Title","authors":"Authors","summary":"Summary","content":"Content","contributors":"Contributors","updated":"Updated","displayOptions":"[display options]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[display options]",
+	title: "Title",
+	authors: "Authors",
+	contributors: "Contributors",
+	id: "ID",
+	close: "[close]",
+	updated: "Updated",
+	summary: "Summary",
+	content: "Content"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/FeedViewerEntry.js b/dojox/atom/widget/nls/FeedViewerEntry.js
index 6c686ff..f84abba 100644
--- a/dojox/atom/widget/nls/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Delete]"})
\ No newline at end of file
+({
+	deleteButton: "[Delete]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/PeopleEditor.js b/dojox/atom/widget/nls/PeopleEditor.js
index 0f56092..e51cbd1 100644
--- a/dojox/atom/widget/nls/PeopleEditor.js
+++ b/dojox/atom/widget/nls/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Add","addAuthor":"Add Author","addContributor":"Add Contributor"})
\ No newline at end of file
+({
+	add: "Add",
+	addAuthor: "Add Author",
+	addContributor: "Add Contributor"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ar/FeedEntryEditor.js b/dojox/atom/widget/nls/ar/FeedEntryEditor.js
index e6c013f..e88af28 100644
--- a/dojox/atom/widget/nls/ar/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/ar/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[تحرير]","save":"[حفظ]","cancel":"[الغاء]","doNew":"[جديد]"})
\ No newline at end of file
+({
+	doNew: "[جديد]",
+	edit: "[تحرير]",
+	save: "[حفظ]",
+	cancel: "[الغاء]"
+})
diff --git a/dojox/atom/widget/nls/ar/FeedEntryViewer.js b/dojox/atom/widget/nls/ar/FeedEntryViewer.js
index fdaea31..234f9c9 100644
--- a/dojox/atom/widget/nls/ar/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/ar/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[اغلاق]","title":"العنوان","authors":"المؤلفين","summary":"الملخص","content":"محتويات","contributors":"المساهمين","updated":"تعديل في","displayOptions":"[اختيارات العرض]","id":"الكود"})
\ No newline at end of file
+({
+	displayOptions: "[اختيارات العرض]",
+	title: "العنوان",
+	authors: "المؤلفين",
+	contributors: "المساهمين",
+	id: "الكود",
+	close: "[اغلاق]",
+	updated: "تعديل في",
+	summary: "الملخص",
+	content: "محتويات"
+})
diff --git a/dojox/atom/widget/nls/ar/FeedViewerEntry.js b/dojox/atom/widget/nls/ar/FeedViewerEntry.js
index 3f7a4bd..6a569fc 100644
--- a/dojox/atom/widget/nls/ar/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/ar/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[حذف]"})
\ No newline at end of file
+({
+	deleteButton: "[حذف]"
+})
diff --git a/dojox/atom/widget/nls/ar/PeopleEditor.js b/dojox/atom/widget/nls/ar/PeopleEditor.js
index dd79bf3..a5dee0c 100644
--- a/dojox/atom/widget/nls/ar/PeopleEditor.js
+++ b/dojox/atom/widget/nls/ar/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"اضافة","addAuthor":"اضافة مؤلف","addContributor":"اضافة مشارك "})
\ No newline at end of file
+({
+	add: "اضافة",
+	addAuthor: "اضافة مؤلف",
+	addContributor: "اضافة مشارك "
+})
diff --git a/dojox/atom/widget/nls/ca/FeedEntryEditor.js b/dojox/atom/widget/nls/ca/FeedEntryEditor.js
index 961d3bc..8e866c5 100644
--- a/dojox/atom/widget/nls/ca/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/ca/FeedEntryEditor.js
@@ -1 +1,7 @@
-({"edit":"[edita]","save":"[desa]","cancel":"[cancel·la]","doNew":"[nou]"})
\ No newline at end of file
+({
+	doNew: "[nou]",
+	edit: "[edita]",
+	save: "[desa]",
+	cancel: "[cancel·la]"
+})
+
diff --git a/dojox/atom/widget/nls/ca/FeedEntryViewer.js b/dojox/atom/widget/nls/ca/FeedEntryViewer.js
index 7f546a9..f938907 100644
--- a/dojox/atom/widget/nls/ca/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/ca/FeedEntryViewer.js
@@ -1 +1,12 @@
-({"close":"[tanca]","title":"Títol","authors":"Autors","summary":"Resum","content":"Contingut","contributors":"Col·laboradors","updated":"Actualitzat","displayOptions":"[opcions de visualització]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[opcions de visualització]",
+	title: "Títol",
+	authors: "Autors",
+	contributors: "Col·laboradors",
+	id: "ID",
+	close: "[tanca]",
+	updated: "Actualitzat",
+	summary: "Resum",
+	content: "Contingut"
+})
+
diff --git a/dojox/atom/widget/nls/ca/FeedViewerEntry.js b/dojox/atom/widget/nls/ca/FeedViewerEntry.js
index 169d596..8d918ba 100644
--- a/dojox/atom/widget/nls/ca/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/ca/FeedViewerEntry.js
@@ -1 +1,4 @@
-({"deleteButton":"[Suprimeix]"})
\ No newline at end of file
+({
+	deleteButton: "[Suprimeix]"
+})
+
diff --git a/dojox/atom/widget/nls/ca/PeopleEditor.js b/dojox/atom/widget/nls/ca/PeopleEditor.js
index ca16393..7362731 100644
--- a/dojox/atom/widget/nls/ca/PeopleEditor.js
+++ b/dojox/atom/widget/nls/ca/PeopleEditor.js
@@ -1 +1,6 @@
-({"add":"Afegeix","addAuthor":"Afegeix un autor","addContributor":"Afegeix un col·laborador"})
\ No newline at end of file
+({
+	add: "Afegeix",
+	addAuthor: "Afegeix un autor",
+	addContributor: "Afegeix un col·laborador"
+})
+
diff --git a/dojox/atom/widget/nls/cs/FeedEntryEditor.js b/dojox/atom/widget/nls/cs/FeedEntryEditor.js
index 45f2997..6929359 100644
--- a/dojox/atom/widget/nls/cs/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/cs/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[upravit]","save":"[uložit]","cancel":"[storno]","doNew":"[nové]"})
\ No newline at end of file
+({
+	doNew: "[nové]",
+	edit: "[upravit]",
+	save: "[uložit]",
+	cancel: "[storno]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/cs/FeedEntryViewer.js b/dojox/atom/widget/nls/cs/FeedEntryViewer.js
index 98e8851..25ed64f 100644
--- a/dojox/atom/widget/nls/cs/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/cs/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[zavřít]","title":"Název","authors":"Autoři","summary":"Souhrn","content":"Obsah","contributors":"Přispěvatelé","updated":"Aktualizováno","displayOptions":"[volby zobrazení]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[volby zobrazení]",
+	title: "Název",
+	authors: "Autoři",
+	contributors: "Přispěvatelé",
+	id: "ID",
+	close: "[zavřít]",
+	updated: "Aktualizováno",
+	summary: "Souhrn",
+	content: "Obsah"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/cs/FeedViewerEntry.js b/dojox/atom/widget/nls/cs/FeedViewerEntry.js
index af02c93..61ba923 100644
--- a/dojox/atom/widget/nls/cs/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/cs/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Odstranit]"})
\ No newline at end of file
+({
+	deleteButton: "[Odstranit]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/cs/PeopleEditor.js b/dojox/atom/widget/nls/cs/PeopleEditor.js
index d437043..3aa2fb3 100644
--- a/dojox/atom/widget/nls/cs/PeopleEditor.js
+++ b/dojox/atom/widget/nls/cs/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Přidat","addAuthor":"Přidat autora","addContributor":"Přidat přispěvatele"})
\ No newline at end of file
+({
+	add: "Přidat",
+	addAuthor: "Přidat autora",
+	addContributor: "Přidat přispěvatele"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/da/FeedEntryEditor.js b/dojox/atom/widget/nls/da/FeedEntryEditor.js
index 0acccc0..b3d88f9 100644
--- a/dojox/atom/widget/nls/da/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/da/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[redigér]","save":"[gem]","cancel":"[annullér]","doNew":"[ny]"})
\ No newline at end of file
+({
+	doNew: "[ny]",
+	edit: "[redigér]",
+	save: "[gem]",
+	cancel: "[annullér]"
+})
diff --git a/dojox/atom/widget/nls/da/FeedEntryViewer.js b/dojox/atom/widget/nls/da/FeedEntryViewer.js
index 932e79b..cd2a6a6 100644
--- a/dojox/atom/widget/nls/da/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/da/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[luk]","title":"Titel","authors":"Forfattere","summary":"Summary","content":"Indhold","contributors":"Bidragydere","updated":"Opdateret","displayOptions":"[fremvisningsvalg]","id":"Id"})
\ No newline at end of file
+({
+	displayOptions: "[fremvisningsvalg]",
+	title: "Titel",
+	authors: "Forfattere",
+	contributors: "Bidragydere",
+	id: "Id",
+	close: "[luk]",
+	updated: "Opdateret",
+	summary: "Summary",
+	content: "Indhold"
+})
diff --git a/dojox/atom/widget/nls/da/FeedViewerEntry.js b/dojox/atom/widget/nls/da/FeedViewerEntry.js
index 8a161c2..5506efa 100644
--- a/dojox/atom/widget/nls/da/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/da/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Slet]"})
\ No newline at end of file
+({
+	deleteButton: "[Slet]"
+})
diff --git a/dojox/atom/widget/nls/da/PeopleEditor.js b/dojox/atom/widget/nls/da/PeopleEditor.js
index 43aaa23..13e9be1 100644
--- a/dojox/atom/widget/nls/da/PeopleEditor.js
+++ b/dojox/atom/widget/nls/da/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Tilføj","addAuthor":"Tilføj forfatter","addContributor":"Tilføj bidragyder"})
\ No newline at end of file
+({
+	add: "Tilføj",
+	addAuthor: "Tilføj forfatter",
+	addContributor: "Tilføj bidragyder"
+})
diff --git a/dojox/atom/widget/nls/de/FeedEntryEditor.js b/dojox/atom/widget/nls/de/FeedEntryEditor.js
index c5a85ae..b2a39b2 100644
--- a/dojox/atom/widget/nls/de/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/de/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[Bearbeiten]","save":"[Speichern]","cancel":"[Abbrechen]","doNew":"[Neu]"})
\ No newline at end of file
+({
+	doNew: "[Neu]",
+	edit: "[Bearbeiten]",
+	save: "[Speichern]",
+	cancel: "[Abbrechen]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/de/FeedEntryViewer.js b/dojox/atom/widget/nls/de/FeedEntryViewer.js
index 68976fb..dbb1ce7 100644
--- a/dojox/atom/widget/nls/de/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/de/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[Schließen]","title":"Titel","authors":"Autoren","summary":"Zusammenfassung","content":"Inhalt","contributors":"Mitwirkende","updated":"Aktualisiert","displayOptions":"[Anzeigeoptionen]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[Anzeigeoptionen]",
+	title: "Titel",
+	authors: "Autoren",
+	contributors: "Mitwirkende",
+	id: "ID",
+	close: "[Schließen]",
+	updated: "Aktualisiert",
+	summary: "Zusammenfassung",
+	content: "Inhalt"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/de/FeedViewerEntry.js b/dojox/atom/widget/nls/de/FeedViewerEntry.js
index 4bc5c03..0128ad1 100644
--- a/dojox/atom/widget/nls/de/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/de/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Löschen]"})
\ No newline at end of file
+({
+	deleteButton: "[Löschen]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/de/PeopleEditor.js b/dojox/atom/widget/nls/de/PeopleEditor.js
index fdaff2f..1fd8057 100644
--- a/dojox/atom/widget/nls/de/PeopleEditor.js
+++ b/dojox/atom/widget/nls/de/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Hinzufügen","addAuthor":"Autor hinzufügen","addContributor":"Mitwirkenden hinzufügen"})
\ No newline at end of file
+({
+	add: "Hinzufügen",
+	addAuthor: "Autor hinzufügen",
+	addContributor: "Mitwirkenden hinzufügen"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/el/FeedEntryEditor.js b/dojox/atom/widget/nls/el/FeedEntryEditor.js
index 3cf776b..a4cbefd 100644
--- a/dojox/atom/widget/nls/el/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/el/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[τροποποίηση]","save":"[αποθήκευση]","cancel":"[ακύρωση]","doNew":"[δημιουργία]"})
\ No newline at end of file
+({
+	doNew: "[δημιουργία]",
+	edit: "[τροποποίηση]",
+	save: "[αποθήκευση]",
+	cancel: "[ακύρωση]"
+})
diff --git a/dojox/atom/widget/nls/el/FeedEntryViewer.js b/dojox/atom/widget/nls/el/FeedEntryViewer.js
index 45d95c6..a5200dc 100644
--- a/dojox/atom/widget/nls/el/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/el/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[κλείσιμο]","title":"Τίτλος","authors":"Συντάκτες","summary":"Περίληψη","content":"Περιεχόμενο","contributors":"Συνεισφέροντες","updated":"Ενημερώθηκε","displayOptions":"[επιλογές παρουσίασης]","id":"Ταυτότητα"})
\ No newline at end of file
+({
+	displayOptions: "[επιλογές παρουσίασης]",
+	title: "Τίτλος",
+	authors: "Συντάκτες",
+	contributors: "Συνεισφέροντες",
+	id: "Ταυτότητα",
+	close: "[κλείσιμο]",
+	updated: "Ενημερώθηκε",
+	summary: "Περίληψη",
+	content: "Περιεχόμενο"
+})
diff --git a/dojox/atom/widget/nls/el/FeedViewerEntry.js b/dojox/atom/widget/nls/el/FeedViewerEntry.js
index db087e4..8345e30 100644
--- a/dojox/atom/widget/nls/el/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/el/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Διαγραφή]"})
\ No newline at end of file
+({
+	deleteButton: "[Διαγραφή]"
+})
diff --git a/dojox/atom/widget/nls/el/PeopleEditor.js b/dojox/atom/widget/nls/el/PeopleEditor.js
index 74604b0..726d426 100644
--- a/dojox/atom/widget/nls/el/PeopleEditor.js
+++ b/dojox/atom/widget/nls/el/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Προσθήκη","addAuthor":"Προσθήκη συντάκτη","addContributor":"Προσθήκη συνεισφέροντα"})
\ No newline at end of file
+({
+	add: "Προσθήκη",
+	addAuthor: "Προσθήκη συντάκτη",
+	addContributor: "Προσθήκη συνεισφέροντα"
+})
diff --git a/dojox/atom/widget/nls/es/FeedEntryEditor.js b/dojox/atom/widget/nls/es/FeedEntryEditor.js
index 426e7ad..6b08c6d 100644
--- a/dojox/atom/widget/nls/es/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/es/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[editar]","save":"[guardar]","cancel":"[cancelar]","doNew":"[nuevo]"})
\ No newline at end of file
+({
+	doNew: "[nuevo]",
+	edit: "[editar]",
+	save: "[guardar]",
+	cancel: "[cancelar]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/es/FeedEntryViewer.js b/dojox/atom/widget/nls/es/FeedEntryViewer.js
index d0d7a9a..cb63dda 100644
--- a/dojox/atom/widget/nls/es/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/es/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[cerrar]","title":"Título","authors":"Autores","summary":"Resumen","content":"Contenido","contributors":"Colaboradores","updated":"Actualizado","displayOptions":"[opciones de visualización]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[opciones de visualización]",
+	title: "Título",
+	authors: "Autores",
+	contributors: "Colaboradores",
+	id: "ID",
+	close: "[cerrar]",
+	updated: "Actualizado",
+	summary: "Resumen",
+	content: "Contenido"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/es/FeedViewerEntry.js b/dojox/atom/widget/nls/es/FeedViewerEntry.js
index c33cee5..ef2b449 100644
--- a/dojox/atom/widget/nls/es/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/es/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Suprimir]"})
\ No newline at end of file
+({
+	deleteButton: "[Suprimir]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/es/PeopleEditor.js b/dojox/atom/widget/nls/es/PeopleEditor.js
index 6ed1de3..ee1427a 100644
--- a/dojox/atom/widget/nls/es/PeopleEditor.js
+++ b/dojox/atom/widget/nls/es/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Añadir","addAuthor":"Añadir autor","addContributor":"Añadir colaborador"})
\ No newline at end of file
+({
+	add: "Añadir",
+	addAuthor: "Añadir autor",
+	addContributor: "Añadir colaborador"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/fi/FeedEntryEditor.js b/dojox/atom/widget/nls/fi/FeedEntryEditor.js
index 0bc76af..812b604 100644
--- a/dojox/atom/widget/nls/fi/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/fi/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[muokkaa]","save":"[tallenna]","cancel":"[peruuta]","doNew":"[uusi]"})
\ No newline at end of file
+({
+	doNew: "[uusi]",
+	edit: "[muokkaa]",
+	save: "[tallenna]",
+	cancel: "[peruuta]"
+})
diff --git a/dojox/atom/widget/nls/fi/FeedEntryViewer.js b/dojox/atom/widget/nls/fi/FeedEntryViewer.js
index 7e08399..639b219 100644
--- a/dojox/atom/widget/nls/fi/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/fi/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[sulje]","title":"Otsikko","authors":"Tekijät","summary":"Yhteenveto","content":"Sisältö","contributors":"Osallistujat","updated":"Päivitetty","displayOptions":"[näyttöasetukset]","id":"Tunnus"})
\ No newline at end of file
+({
+	displayOptions: "[näyttöasetukset]",
+	title: "Otsikko",
+	authors: "Tekijät",
+	contributors: "Osallistujat",
+	id: "Tunnus",
+	close: "[sulje]",
+	updated: "Päivitetty",
+	summary: "Yhteenveto",
+	content: "Sisältö"
+})
diff --git a/dojox/atom/widget/nls/fi/FeedViewerEntry.js b/dojox/atom/widget/nls/fi/FeedViewerEntry.js
index 832e2c4..0ce2a17 100644
--- a/dojox/atom/widget/nls/fi/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/fi/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Poista]"})
\ No newline at end of file
+({
+	deleteButton: "[Poista]"
+})
diff --git a/dojox/atom/widget/nls/fi/PeopleEditor.js b/dojox/atom/widget/nls/fi/PeopleEditor.js
index a436742..c8dd991 100644
--- a/dojox/atom/widget/nls/fi/PeopleEditor.js
+++ b/dojox/atom/widget/nls/fi/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Lisää","addAuthor":"Lisää tekijä","addContributor":"Lisää osallistuja"})
\ No newline at end of file
+({
+	add: "Lisää",
+	addAuthor: "Lisää tekijä",
+	addContributor: "Lisää osallistuja"
+})
diff --git a/dojox/atom/widget/nls/fr/FeedEntryEditor.js b/dojox/atom/widget/nls/fr/FeedEntryEditor.js
index ff19654..8e68668 100644
--- a/dojox/atom/widget/nls/fr/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/fr/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[éditer]","save":"[sauvegarder]","cancel":"[annuler]","doNew":"[nouveau]"})
\ No newline at end of file
+({
+	doNew: "[nouveau]",
+	edit: "[éditer]",
+	save: "[sauvegarder]",
+	cancel: "[annuler]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/fr/FeedEntryViewer.js b/dojox/atom/widget/nls/fr/FeedEntryViewer.js
index 93c0cbc..41462dd 100644
--- a/dojox/atom/widget/nls/fr/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/fr/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[fermer]","title":"Titre","authors":"Auteurs","summary":"Récapitulatif","content":"Contenu","contributors":"Collaborateurs","updated":"Mis à jour","displayOptions":"[options d'affichage]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[options d'affichage]",
+	title: "Titre",
+	authors: "Auteurs",
+	contributors: "Collaborateurs",
+	id: "ID",
+	close: "[fermer]",
+	updated: "Mis à jour",
+	summary: "Récapitulatif",
+	content: "Contenu"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/fr/FeedViewerEntry.js b/dojox/atom/widget/nls/fr/FeedViewerEntry.js
index 8003cbb..a051693 100644
--- a/dojox/atom/widget/nls/fr/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/fr/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Supprimer]"})
\ No newline at end of file
+({
+	deleteButton: "[Supprimer]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/fr/PeopleEditor.js b/dojox/atom/widget/nls/fr/PeopleEditor.js
index 5b7d866..7bf8b0f 100644
--- a/dojox/atom/widget/nls/fr/PeopleEditor.js
+++ b/dojox/atom/widget/nls/fr/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Ajouter","addAuthor":"Ajouter un auteur","addContributor":"Ajouter un collaborateur"})
\ No newline at end of file
+({
+	add: "Ajouter",
+	addAuthor: "Ajouter un auteur",
+	addContributor: "Ajouter un collaborateur"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/he/FeedEntryEditor.js b/dojox/atom/widget/nls/he/FeedEntryEditor.js
index 569ea3b..5cb7f4d 100644
--- a/dojox/atom/widget/nls/he/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/he/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[עריכה]","save":"[שמירה]","cancel":"[ביטול]","doNew":"[חדש]"})
\ No newline at end of file
+({
+	doNew: "[חדש]",
+	edit: "[עריכה]",
+	save: "[שמירה]",
+	cancel: "[ביטול]"
+})
diff --git a/dojox/atom/widget/nls/he/FeedEntryViewer.js b/dojox/atom/widget/nls/he/FeedEntryViewer.js
index 3c60372..9e1bfd5 100644
--- a/dojox/atom/widget/nls/he/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/he/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[סגירה]","title":"כותרת","authors":"מחברים","summary":"סיכום","content":"תוכן","contributors":"תורמים","updated":"עודכן","displayOptions":"[הצגת אפשרויות]","id":"זיהוי"})
\ No newline at end of file
+({
+	displayOptions: "[הצגת אפשרויות]",
+	title: "כותרת",
+	authors: "מחברים",
+	contributors: "תורמים",
+	id: "זיהוי",
+	close: "[סגירה]",
+	updated: "עודכן",
+	summary: "סיכום",
+	content: "תוכן"
+})
diff --git a/dojox/atom/widget/nls/he/FeedViewerEntry.js b/dojox/atom/widget/nls/he/FeedViewerEntry.js
index 4bb6ba0..ccff392 100644
--- a/dojox/atom/widget/nls/he/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/he/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[מחיקה]"})
\ No newline at end of file
+({
+	deleteButton: "[מחיקה]"
+})
diff --git a/dojox/atom/widget/nls/he/PeopleEditor.js b/dojox/atom/widget/nls/he/PeopleEditor.js
index 00120d8..3fe44b7 100644
--- a/dojox/atom/widget/nls/he/PeopleEditor.js
+++ b/dojox/atom/widget/nls/he/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"הוספה","addAuthor":"הוספת מחבר","addContributor":"הוספת תורם"})
\ No newline at end of file
+({
+	add: "הוספה",
+	addAuthor: "הוספת מחבר",
+	addContributor: "הוספת תורם"
+})
diff --git a/dojox/atom/widget/nls/hu/FeedEntryEditor.js b/dojox/atom/widget/nls/hu/FeedEntryEditor.js
index 9686e11..d8dcb23 100644
--- a/dojox/atom/widget/nls/hu/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/hu/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[szerkesztés]","save":"[mentés]","cancel":"[mégse]","doNew":"[új]"})
\ No newline at end of file
+({
+	doNew: "[új]",
+	edit: "[szerkesztés]",
+	save: "[mentés]",
+	cancel: "[mégse]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/hu/FeedEntryViewer.js b/dojox/atom/widget/nls/hu/FeedEntryViewer.js
index c0f4853..36e40af 100644
--- a/dojox/atom/widget/nls/hu/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/hu/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[bezárás]","title":"Cím","authors":"Szerzők","summary":"Összegzés","content":"Tartalom","contributors":"Közreműködők","updated":"Frissítve","displayOptions":"[megjelenítési beállítások]","id":"Azonosító"})
\ No newline at end of file
+({
+	displayOptions: "[megjelenítési beállítások]",
+	title: "Cím",
+	authors: "Szerzők",
+	contributors: "Közreműködők",
+	id: "Azonosító",
+	close: "[bezárás]",
+	updated: "Frissítve",
+	summary: "Összegzés",
+	content: "Tartalom"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/hu/FeedViewerEntry.js b/dojox/atom/widget/nls/hu/FeedViewerEntry.js
index a826114..6997454 100644
--- a/dojox/atom/widget/nls/hu/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/hu/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Törlés]"})
\ No newline at end of file
+({
+	deleteButton: "[Törlés]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/hu/PeopleEditor.js b/dojox/atom/widget/nls/hu/PeopleEditor.js
index 6ffe97c..b0244f9 100644
--- a/dojox/atom/widget/nls/hu/PeopleEditor.js
+++ b/dojox/atom/widget/nls/hu/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Hozzáadás","addAuthor":"Szerző hozzáadása","addContributor":"Közreműködő hozzáadása"})
\ No newline at end of file
+({
+	add: "Hozzáadás",
+	addAuthor: "Szerző hozzáadása",
+	addContributor: "Közreműködő hozzáadása"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/it/FeedEntryEditor.js b/dojox/atom/widget/nls/it/FeedEntryEditor.js
index 408de78..c01d49d 100644
--- a/dojox/atom/widget/nls/it/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/it/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[modifica]","save":"[salva]","cancel":"[annulla]","doNew":"[nuovo]"})
\ No newline at end of file
+({
+	doNew: "[nuovo]",
+	edit: "[modifica]",
+	save: "[salva]",
+	cancel: "[annulla]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/it/FeedEntryViewer.js b/dojox/atom/widget/nls/it/FeedEntryViewer.js
index 3cc33ac..28d09cb 100644
--- a/dojox/atom/widget/nls/it/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/it/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[chiudi]","title":"Titolo","authors":"Autori","summary":"Riepilogo","content":"Indice","contributors":"Collaboratori","updated":"Aggiornato","displayOptions":"[visualizza opzioni]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[visualizza opzioni]",
+	title: "Titolo",
+	authors: "Autori",
+	contributors: "Collaboratori",
+	id: "ID",
+	close: "[chiudi]",
+	updated: "Aggiornato",
+	summary: "Riepilogo",
+	content: "Indice"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/it/FeedViewerEntry.js b/dojox/atom/widget/nls/it/FeedViewerEntry.js
index 3a0fa24..7521930 100644
--- a/dojox/atom/widget/nls/it/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/it/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Cancella]"})
\ No newline at end of file
+({
+	deleteButton: "[Cancella]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/it/PeopleEditor.js b/dojox/atom/widget/nls/it/PeopleEditor.js
index 82b4f5b..b5bd262 100644
--- a/dojox/atom/widget/nls/it/PeopleEditor.js
+++ b/dojox/atom/widget/nls/it/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Aggiungi","addAuthor":"Aggiungi autore","addContributor":"Aggiungi collaboratori"})
\ No newline at end of file
+({
+	add: "Aggiungi",
+	addAuthor: "Aggiungi autore",
+	addContributor: "Aggiungi collaboratori"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ja/FeedEntryEditor.js b/dojox/atom/widget/nls/ja/FeedEntryEditor.js
index ca8986a..95666e2 100644
--- a/dojox/atom/widget/nls/ja/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/ja/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[編集]","save":"[保存]","cancel":"[キャンセル]","doNew":"[新規]"})
\ No newline at end of file
+({
+	doNew: "[新規]",
+	edit: "[編集]",
+	save: "[保存]",
+	cancel: "[キャンセル]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ja/FeedEntryViewer.js b/dojox/atom/widget/nls/ja/FeedEntryViewer.js
index b935c62..c4b39f4 100644
--- a/dojox/atom/widget/nls/ja/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/ja/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[閉じる]","title":"タイトル","authors":"作成者","summary":"要約","content":"内容","contributors":"貢献者","updated":"更新","displayOptions":"[表示オプション]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[表示オプション]",
+	title: "タイトル",
+	authors: "作成者",
+	contributors: "貢献者",
+	id: "ID",
+	close: "[閉じる]",
+	updated: "更新",
+	summary: "要約",
+	content: "内容"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ja/FeedViewerEntry.js b/dojox/atom/widget/nls/ja/FeedViewerEntry.js
index 6dcdea0..bad586b 100644
--- a/dojox/atom/widget/nls/ja/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/ja/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[削除]"})
\ No newline at end of file
+({
+	deleteButton: "[削除]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ja/PeopleEditor.js b/dojox/atom/widget/nls/ja/PeopleEditor.js
index 203fc3f..ba4a2b6 100644
--- a/dojox/atom/widget/nls/ja/PeopleEditor.js
+++ b/dojox/atom/widget/nls/ja/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"追加","addAuthor":"作成者の追加","addContributor":"貢献者の追加"})
\ No newline at end of file
+({
+	add: "追加",
+	addAuthor: "作成者の追加",
+	addContributor: "貢献者の追加"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ko/FeedEntryEditor.js b/dojox/atom/widget/nls/ko/FeedEntryEditor.js
index 227d37f..2254b9c 100644
--- a/dojox/atom/widget/nls/ko/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/ko/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[편집]","save":"[저장]","cancel":"[취소]","doNew":"[새로 작성]"})
\ No newline at end of file
+({
+	doNew: "[새로 작성]",
+	edit: "[편집]",
+	save: "[저장]",
+	cancel: "[취소]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ko/FeedEntryViewer.js b/dojox/atom/widget/nls/ko/FeedEntryViewer.js
index 39caa6d..b7e07c5 100644
--- a/dojox/atom/widget/nls/ko/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/ko/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[닫기]","title":"제목","authors":"작성자","summary":"요약","content":"컨텐츠","contributors":"속성","updated":"갱신","displayOptions":"[옵션 표시]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[옵션 표시]",
+	title: "제목",
+	authors: "작성자",
+	contributors: "속성",
+	id: "ID",
+	close: "[닫기]",
+	updated: "갱신",
+	summary: "요약",
+	content: "컨텐츠"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ko/FeedViewerEntry.js b/dojox/atom/widget/nls/ko/FeedViewerEntry.js
index 98b1b3f..72bf740 100644
--- a/dojox/atom/widget/nls/ko/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/ko/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[삭제]"})
\ No newline at end of file
+({
+	deleteButton: "[삭제]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ko/PeopleEditor.js b/dojox/atom/widget/nls/ko/PeopleEditor.js
index ac52411..269e032 100644
--- a/dojox/atom/widget/nls/ko/PeopleEditor.js
+++ b/dojox/atom/widget/nls/ko/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"추가","addAuthor":"작성자 추가","addContributor":"제공자 추가"})
\ No newline at end of file
+({
+	add: "추가",
+	addAuthor: "작성자 추가",
+	addContributor: "제공자 추가"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/nb/FeedEntryEditor.js b/dojox/atom/widget/nls/nb/FeedEntryEditor.js
index 3b482ed..0d4d8cd 100644
--- a/dojox/atom/widget/nls/nb/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/nb/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[rediger]","save":"[lagre]","cancel":"[avbryt]","doNew":"[ny(tt)]"})
\ No newline at end of file
+({
+	doNew: "[ny(tt)]",
+	edit: "[rediger]",
+	save: "[lagre]",
+	cancel: "[avbryt]"
+})
diff --git a/dojox/atom/widget/nls/nb/FeedEntryViewer.js b/dojox/atom/widget/nls/nb/FeedEntryViewer.js
index f888d28..574f7bc 100644
--- a/dojox/atom/widget/nls/nb/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/nb/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[lukk]","title":"Tittel","authors":"Forfattere","summary":"Sammendrag","content":"Innhold","contributors":"Bidragsytere","updated":"Oppdatert","displayOptions":"[visningsalternativer]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[visningsalternativer]",
+	title: "Tittel",
+	authors: "Forfattere",
+	contributors: "Bidragsytere",
+	id: "ID",
+	close: "[lukk]",
+	updated: "Oppdatert",
+	summary: "Sammendrag",
+	content: "Innhold"
+})
diff --git a/dojox/atom/widget/nls/nb/FeedViewerEntry.js b/dojox/atom/widget/nls/nb/FeedViewerEntry.js
index 8e38e59..057ebf7 100644
--- a/dojox/atom/widget/nls/nb/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/nb/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Slett]"})
\ No newline at end of file
+({
+	deleteButton: "[Slett]"
+})
diff --git a/dojox/atom/widget/nls/nb/PeopleEditor.js b/dojox/atom/widget/nls/nb/PeopleEditor.js
index 05ac102..0a725d4 100644
--- a/dojox/atom/widget/nls/nb/PeopleEditor.js
+++ b/dojox/atom/widget/nls/nb/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Legg til","addAuthor":"Legg til forfatter","addContributor":"Legg til bidragsyter"})
\ No newline at end of file
+({
+	add: "Legg til",
+	addAuthor: "Legg til forfatter",
+	addContributor: "Legg til bidragsyter"
+})
diff --git a/dojox/atom/widget/nls/nl/FeedEntryEditor.js b/dojox/atom/widget/nls/nl/FeedEntryEditor.js
index 0714571..4263173 100644
--- a/dojox/atom/widget/nls/nl/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/nl/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[bewerken]","save":"[opslaan]","cancel":"[annuleren]","doNew":"[nieuw]"})
\ No newline at end of file
+({
+	doNew: "[nieuw]",
+	edit: "[bewerken]",
+	save: "[opslaan]",
+	cancel: "[annuleren]"
+})
diff --git a/dojox/atom/widget/nls/nl/FeedEntryViewer.js b/dojox/atom/widget/nls/nl/FeedEntryViewer.js
index 294f590..f6a5552 100644
--- a/dojox/atom/widget/nls/nl/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/nl/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[sluiten]","title":"Titel","authors":"Auteurs","summary":"Overzicht","content":"Content","contributors":"Deelnemers","updated":"Bijgewerkt","displayOptions":"[weergaveopties]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[weergaveopties]",
+	title: "Titel",
+	authors: "Auteurs",
+	contributors: "Deelnemers",
+	id: "ID",
+	close: "[sluiten]",
+	updated: "Bijgewerkt",
+	summary: "Overzicht",
+	content: "Content"
+})
diff --git a/dojox/atom/widget/nls/nl/FeedViewerEntry.js b/dojox/atom/widget/nls/nl/FeedViewerEntry.js
index 31a12d7..4ec7dc6 100644
--- a/dojox/atom/widget/nls/nl/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/nl/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Wissen]"})
\ No newline at end of file
+({
+	deleteButton: "[Wissen]"
+})
diff --git a/dojox/atom/widget/nls/nl/PeopleEditor.js b/dojox/atom/widget/nls/nl/PeopleEditor.js
index e8dd783..5a9521f 100644
--- a/dojox/atom/widget/nls/nl/PeopleEditor.js
+++ b/dojox/atom/widget/nls/nl/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Toevoegen","addAuthor":"Auteur toevoegen","addContributor":"Deelnemer toevoegen"})
\ No newline at end of file
+({
+	add: "Toevoegen",
+	addAuthor: "Auteur toevoegen",
+	addContributor: "Deelnemer toevoegen"
+})
diff --git a/dojox/atom/widget/nls/pl/FeedEntryEditor.js b/dojox/atom/widget/nls/pl/FeedEntryEditor.js
index 2fc51b5..5780e6d 100644
--- a/dojox/atom/widget/nls/pl/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/pl/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[Edytuj]","save":"[Zapisz]","cancel":"[Anuluj]","doNew":"[Nowy]"})
\ No newline at end of file
+({
+	doNew: "[Nowy]",
+	edit: "[Edytuj]",
+	save: "[Zapisz]",
+	cancel: "[Anuluj]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/pl/FeedEntryViewer.js b/dojox/atom/widget/nls/pl/FeedEntryViewer.js
index 9b52a9c..8dbf4d0 100644
--- a/dojox/atom/widget/nls/pl/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/pl/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[Zamknij]","title":"Tytuł","authors":"Autorzy","summary":"Podsumowanie","content":"Treść","contributors":"Kontrybutorzy","updated":"Zaktualizowano","displayOptions":"[Opcje wyświetlania]","id":"Identyfikator"})
\ No newline at end of file
+({
+	displayOptions: "[Opcje wyświetlania]",
+	title: "Tytuł",
+	authors: "Autorzy",
+	contributors: "Kontrybutorzy",
+	id: "Identyfikator",
+	close: "[Zamknij]",
+	updated: "Zaktualizowano",
+	summary: "Podsumowanie",
+	content: "Treść"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/pl/FeedViewerEntry.js b/dojox/atom/widget/nls/pl/FeedViewerEntry.js
index b6a347e..e0fca80 100644
--- a/dojox/atom/widget/nls/pl/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/pl/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Usuń]"})
\ No newline at end of file
+({
+	deleteButton: "[Usuń]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/pl/PeopleEditor.js b/dojox/atom/widget/nls/pl/PeopleEditor.js
index baa45b1..dd58dbc 100644
--- a/dojox/atom/widget/nls/pl/PeopleEditor.js
+++ b/dojox/atom/widget/nls/pl/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Dodaj","addAuthor":"Dodaj autora","addContributor":"Dodaj kontrybutora"})
\ No newline at end of file
+({
+	add: "Dodaj",
+	addAuthor: "Dodaj autora",
+	addContributor: "Dodaj kontrybutora"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/pt-pt/FeedEntryEditor.js b/dojox/atom/widget/nls/pt-pt/FeedEntryEditor.js
index c87f234..1ef0598 100644
--- a/dojox/atom/widget/nls/pt-pt/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/pt-pt/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[editar]","save":"[guardar]","cancel":"[cancelar]","doNew":"[novo]"})
\ No newline at end of file
+({
+	doNew: "[novo]",
+	edit: "[editar]",
+	save: "[guardar]",
+	cancel: "[cancelar]"
+})
diff --git a/dojox/atom/widget/nls/pt-pt/FeedEntryViewer.js b/dojox/atom/widget/nls/pt-pt/FeedEntryViewer.js
index 40b3f60..81b3509 100644
--- a/dojox/atom/widget/nls/pt-pt/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/pt-pt/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[fechar]","title":"Título","authors":"Autores","summary":"Resumo","content":"Conteúdo","contributors":"Contribuintes","updated":"Actualizado","displayOptions":"[opções de visualização]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[opções de visualização]",
+	title: "Título",
+	authors: "Autores",
+	contributors: "Contribuintes",
+	id: "ID",
+	close: "[fechar]",
+	updated: "Actualizado",
+	summary: "Resumo",
+	content: "Conteúdo"
+})
diff --git a/dojox/atom/widget/nls/pt-pt/FeedViewerEntry.js b/dojox/atom/widget/nls/pt-pt/FeedViewerEntry.js
index de9f60e..690bdfe 100644
--- a/dojox/atom/widget/nls/pt-pt/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/pt-pt/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Eliminar]"})
\ No newline at end of file
+({
+	deleteButton: "[Eliminar]"
+})
diff --git a/dojox/atom/widget/nls/pt-pt/PeopleEditor.js b/dojox/atom/widget/nls/pt-pt/PeopleEditor.js
index e89d433..ee90a8e 100644
--- a/dojox/atom/widget/nls/pt-pt/PeopleEditor.js
+++ b/dojox/atom/widget/nls/pt-pt/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Adicionar","addAuthor":"Adicionar autor","addContributor":"Adicionar contribuinte"})
\ No newline at end of file
+({
+	add: "Adicionar",
+	addAuthor: "Adicionar autor",
+	addContributor: "Adicionar contribuinte"
+})
diff --git a/dojox/atom/widget/nls/pt/FeedEntryEditor.js b/dojox/atom/widget/nls/pt/FeedEntryEditor.js
index ab9981a..48526dd 100644
--- a/dojox/atom/widget/nls/pt/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/pt/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[editar]","save":"[salvar]","cancel":"[cancelar]","doNew":"[novo]"})
\ No newline at end of file
+({
+	doNew: "[novo]",
+	edit: "[editar]",
+	save: "[salvar]",
+	cancel: "[cancelar]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/pt/FeedEntryViewer.js b/dojox/atom/widget/nls/pt/FeedEntryViewer.js
index bc12eea..b4d531f 100644
--- a/dojox/atom/widget/nls/pt/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/pt/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[fechar]","title":"Título","authors":"Autores","summary":"Resumo","content":"Conteúdo","contributors":"Contribuidores","updated":"Atualizado","displayOptions":"[exibir opções]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[exibir opções]",
+	title: "Título",
+	authors: "Autores",
+	contributors: "Contribuidores",
+	id: "ID",
+	close: "[fechar]",
+	updated: "Atualizado",
+	summary: "Resumo",
+	content: "Conteúdo"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/pt/FeedViewerEntry.js b/dojox/atom/widget/nls/pt/FeedViewerEntry.js
index 74e0657..7240c20 100644
--- a/dojox/atom/widget/nls/pt/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/pt/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Excluir]"})
\ No newline at end of file
+({
+	deleteButton: "[Excluir]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/pt/PeopleEditor.js b/dojox/atom/widget/nls/pt/PeopleEditor.js
index 76752ef..c572661 100644
--- a/dojox/atom/widget/nls/pt/PeopleEditor.js
+++ b/dojox/atom/widget/nls/pt/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Adicionar","addAuthor":"Adicionar Autor","addContributor":"Adicionar Contribuidor"})
\ No newline at end of file
+({
+	add: "Adicionar",
+	addAuthor: "Adicionar Autor",
+	addContributor: "Adicionar Contribuidor"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ro/FeedEntryEditor.js b/dojox/atom/widget/nls/ro/FeedEntryEditor.js
new file mode 100644
index 0000000..e54a345
--- /dev/null
+++ b/dojox/atom/widget/nls/ro/FeedEntryEditor.js
@@ -0,0 +1,7 @@
+({
+	doNew: "[nou]",
+	edit: "[editare]",
+	save: "[salvare]",
+	cancel: "[anulare]"
+})
+
diff --git a/dojox/atom/widget/nls/ro/FeedEntryViewer.js b/dojox/atom/widget/nls/ro/FeedEntryViewer.js
new file mode 100644
index 0000000..8840053
--- /dev/null
+++ b/dojox/atom/widget/nls/ro/FeedEntryViewer.js
@@ -0,0 +1,12 @@
+({
+	displayOptions: "[opţiuni afişare]",
+	title: "Titlu",
+	authors: "Autori",
+	contributors: "Contribuitori",
+	id: "ID",
+	close: "[închidere]",
+	updated: "Actualizat",
+	summary: "Sumar",
+	content: "Conţinut"
+})
+
diff --git a/dojox/atom/widget/nls/ro/FeedViewerEntry.js b/dojox/atom/widget/nls/ro/FeedViewerEntry.js
new file mode 100644
index 0000000..98786b8
--- /dev/null
+++ b/dojox/atom/widget/nls/ro/FeedViewerEntry.js
@@ -0,0 +1,4 @@
+({
+	deleteButton: "[Ştergere]"
+})
+
diff --git a/dojox/atom/widget/nls/ro/PeopleEditor.js b/dojox/atom/widget/nls/ro/PeopleEditor.js
new file mode 100644
index 0000000..3f06c05
--- /dev/null
+++ b/dojox/atom/widget/nls/ro/PeopleEditor.js
@@ -0,0 +1,6 @@
+({
+	add: "Adăugare",
+	addAuthor: "Adăugare autor",
+	addContributor: "Adăugare contribuitor"
+})
+
diff --git a/dojox/atom/widget/nls/ru/FeedEntryEditor.js b/dojox/atom/widget/nls/ru/FeedEntryEditor.js
index c3a9380..8a5838c 100644
--- a/dojox/atom/widget/nls/ru/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/ru/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[изменить]","save":"[сохранить]","cancel":"[отмена]","doNew":"[создать]"})
\ No newline at end of file
+({
+	doNew: "[создать]",
+	edit: "[изменить]",
+	save: "[сохранить]",
+	cancel: "[отмена]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ru/FeedEntryViewer.js b/dojox/atom/widget/nls/ru/FeedEntryViewer.js
index 80bf42f..7eb06e5 100644
--- a/dojox/atom/widget/nls/ru/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/ru/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[закрыть]","title":"Название","authors":"Авторы","summary":"Сводка","content":"Информационное наполнение","contributors":"Участники","updated":"Обновлено","displayOptions":"[показать опции]","id":"ИД"})
\ No newline at end of file
+({
+	displayOptions: "[показать опции]",
+	title: "Название",
+	authors: "Авторы",
+	contributors: "Участники",
+	id: "ИД",
+	close: "[закрыть]",
+	updated: "Обновлено",
+	summary: "Сводка",
+	content: "Информационное наполнение"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ru/FeedViewerEntry.js b/dojox/atom/widget/nls/ru/FeedViewerEntry.js
index 39247e2..0800cfa 100644
--- a/dojox/atom/widget/nls/ru/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/ru/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Удалить]"})
\ No newline at end of file
+({
+	deleteButton: "[Удалить]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/ru/PeopleEditor.js b/dojox/atom/widget/nls/ru/PeopleEditor.js
index 1b8f136..a7e0faa 100644
--- a/dojox/atom/widget/nls/ru/PeopleEditor.js
+++ b/dojox/atom/widget/nls/ru/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Добавить","addAuthor":"Добавить автора","addContributor":"Добавить участника"})
\ No newline at end of file
+({
+	add: "Добавить",
+	addAuthor: "Добавить автора",
+	addContributor: "Добавить участника"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/sk/FeedEntryEditor.js b/dojox/atom/widget/nls/sk/FeedEntryEditor.js
index abc3a1b..fa60ba9 100644
--- a/dojox/atom/widget/nls/sk/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/sk/FeedEntryEditor.js
@@ -1 +1,7 @@
-({"edit":"[upraviť]","save":"[uložiť]","cancel":"[zrušiť]","doNew":"[nový]"})
\ No newline at end of file
+({
+	doNew: "[nový]",
+	edit: "[upraviť]",
+	save: "[uložiť]",
+	cancel: "[zrušiť]"
+})
+
diff --git a/dojox/atom/widget/nls/sk/FeedEntryViewer.js b/dojox/atom/widget/nls/sk/FeedEntryViewer.js
index fbaea41..bf47a34 100644
--- a/dojox/atom/widget/nls/sk/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/sk/FeedEntryViewer.js
@@ -1 +1,12 @@
-({"close":"[zatvoriť]","title":"Nadpis","authors":"Autori","summary":"Súhrn","content":"Obsah","contributors":"Prispievatelia","updated":"Aktualizovaný","displayOptions":"[zobraziť voľby]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[zobraziť voľby]",
+	title: "Nadpis",
+	authors: "Autori",
+	contributors: "Prispievatelia",
+	id: "ID",
+	close: "[zatvoriť]",
+	updated: "Aktualizovaný",
+	summary: "Súhrn",
+	content: "Obsah"
+})
+
diff --git a/dojox/atom/widget/nls/sk/FeedViewerEntry.js b/dojox/atom/widget/nls/sk/FeedViewerEntry.js
index ff7123d..6838279 100644
--- a/dojox/atom/widget/nls/sk/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/sk/FeedViewerEntry.js
@@ -1 +1,4 @@
-({"deleteButton":"[Vymazať]"})
\ No newline at end of file
+({
+	deleteButton: "[Vymazať]"
+})
+
diff --git a/dojox/atom/widget/nls/sk/PeopleEditor.js b/dojox/atom/widget/nls/sk/PeopleEditor.js
index 5a727c1..08f96c0 100644
--- a/dojox/atom/widget/nls/sk/PeopleEditor.js
+++ b/dojox/atom/widget/nls/sk/PeopleEditor.js
@@ -1 +1,6 @@
-({"add":"Pridať","addAuthor":"Pridať autora","addContributor":"Pridať prispievateľa"})
\ No newline at end of file
+({
+	add: "Pridať",
+	addAuthor: "Pridať autora",
+	addContributor: "Pridať prispievateľa"
+})
+
diff --git a/dojox/atom/widget/nls/sl/FeedEntryEditor.js b/dojox/atom/widget/nls/sl/FeedEntryEditor.js
index 8610736..ff71162 100644
--- a/dojox/atom/widget/nls/sl/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/sl/FeedEntryEditor.js
@@ -1 +1,7 @@
-({"edit":"[urejanje]","save":"[shrani]","cancel":"[prekliči]","doNew":"[novo]"})
\ No newline at end of file
+({
+	doNew: "[novo]",
+	edit: "[urejanje]",
+	save: "[shrani]",
+	cancel: "[prekliči]"
+})
+
diff --git a/dojox/atom/widget/nls/sl/FeedEntryViewer.js b/dojox/atom/widget/nls/sl/FeedEntryViewer.js
index 943aeff..2fb1081 100644
--- a/dojox/atom/widget/nls/sl/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/sl/FeedEntryViewer.js
@@ -1 +1,12 @@
-({"close":"[zapri]","title":"Naslov","authors":"Avtorji","summary":"Povzetek","content":"Vsebina","contributors":"Kontributorji","updated":"Posodobljeno","displayOptions":"[možnosti prikaza]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[možnosti prikaza]",
+	title: "Naslov",
+	authors: "Avtorji",
+	contributors: "Kontributorji",
+	id: "ID",
+	close: "[zapri]",
+	updated: "Posodobljeno",
+	summary: "Povzetek",
+	content: "Vsebina"
+})
+
diff --git a/dojox/atom/widget/nls/sl/FeedViewerEntry.js b/dojox/atom/widget/nls/sl/FeedViewerEntry.js
index 020d9bd..a668341 100644
--- a/dojox/atom/widget/nls/sl/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/sl/FeedViewerEntry.js
@@ -1 +1,4 @@
-({"deleteButton":"[Izbriši]"})
\ No newline at end of file
+({
+	deleteButton: "[Izbriši]"
+})
+
diff --git a/dojox/atom/widget/nls/sl/PeopleEditor.js b/dojox/atom/widget/nls/sl/PeopleEditor.js
index 0609ea8..28ad1fc 100644
--- a/dojox/atom/widget/nls/sl/PeopleEditor.js
+++ b/dojox/atom/widget/nls/sl/PeopleEditor.js
@@ -1 +1,6 @@
-({"add":"Dodaj","addAuthor":"Dodaj avtorja","addContributor":"Dodaj kontributorja,"})
\ No newline at end of file
+({
+	add: "Dodaj",
+	addAuthor: "Dodaj avtorja",
+	addContributor: "Dodaj kontributorja,"
+})
+
diff --git a/dojox/atom/widget/nls/sv/FeedEntryEditor.js b/dojox/atom/widget/nls/sv/FeedEntryEditor.js
index e880f80..1b8edcc 100644
--- a/dojox/atom/widget/nls/sv/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/sv/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[Redigera]","save":"[Spara]","cancel":"[Avbryt]","doNew":"[Nytt]"})
\ No newline at end of file
+({
+	doNew: "[Nytt]",
+	edit: "[Redigera]",
+	save: "[Spara]",
+	cancel: "[Avbryt]"
+})
diff --git a/dojox/atom/widget/nls/sv/FeedEntryViewer.js b/dojox/atom/widget/nls/sv/FeedEntryViewer.js
index 3b58866..e2ccfed 100644
--- a/dojox/atom/widget/nls/sv/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/sv/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[Stäng]","title":"Rubrik","authors":"Författare","summary":"Sammanfattning","content":"Innehåll","contributors":"Medverkande","updated":"Uppdaterat","displayOptions":"[Visningsalternativ]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[Visningsalternativ]",
+	title: "Rubrik",
+	authors: "Författare",
+	contributors: "Medverkande",
+	id: "ID",
+	close: "[Stäng]",
+	updated: "Uppdaterat",
+	summary: "Sammanfattning",
+	content: "Innehåll"
+})
diff --git a/dojox/atom/widget/nls/sv/FeedViewerEntry.js b/dojox/atom/widget/nls/sv/FeedViewerEntry.js
index 41de9cb..7efab23 100644
--- a/dojox/atom/widget/nls/sv/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/sv/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Ta bort]"})
\ No newline at end of file
+({
+	deleteButton: "[Ta bort]"
+})
diff --git a/dojox/atom/widget/nls/sv/PeopleEditor.js b/dojox/atom/widget/nls/sv/PeopleEditor.js
index 875908f..379162d 100644
--- a/dojox/atom/widget/nls/sv/PeopleEditor.js
+++ b/dojox/atom/widget/nls/sv/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Lägg til ","addAuthor":"Lägg till författare","addContributor":"Lägg till medverkande"})
\ No newline at end of file
+({
+	add: "Lägg til ",
+	addAuthor: "Lägg till författare",
+	addContributor: "Lägg till medverkande"
+})
diff --git a/dojox/atom/widget/nls/th/FeedEntryEditor.js b/dojox/atom/widget/nls/th/FeedEntryEditor.js
index 586f01b..d02b7b5 100644
--- a/dojox/atom/widget/nls/th/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/th/FeedEntryEditor.js
@@ -1 +1,7 @@
-({"edit":"[แก้ไข]","save":"[บันทึก]","cancel":"[ยกเลิก]","doNew":"[สร้าง]"})
\ No newline at end of file
+({
+	doNew: "[สร้าง]",
+	edit: "[แก้ไข]",
+	save: "[บันทึก]",
+	cancel: "[ยกเลิก]"
+})
+
diff --git a/dojox/atom/widget/nls/th/FeedEntryViewer.js b/dojox/atom/widget/nls/th/FeedEntryViewer.js
index eda9eb7..ed3b078 100644
--- a/dojox/atom/widget/nls/th/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/th/FeedEntryViewer.js
@@ -1 +1,12 @@
-({"close":"[ปิด]","title":"ชื่อเรื่อง","authors":"ผู้เขียน","summary":"สรุป","content":"เนื้อหา","contributors":"ผู้อนุเคราะห์","updated":"อัพเดต","displayOptions":"[อ็อพชันการแสดงผล]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[อ็อพชันการแสดงผล]",
+	title: "ชื่อเรื่อง",
+	authors: "ผู้เขียน",
+	contributors: "ผู้อนุเคราะห์",
+	id: "ID",
+	close: "[ปิด]",
+	updated: "อัพเดต",
+	summary: "สรุป",
+	content: "เนื้อหา"
+})
+
diff --git a/dojox/atom/widget/nls/th/FeedViewerEntry.js b/dojox/atom/widget/nls/th/FeedViewerEntry.js
index ce0cb07..b773a9e 100644
--- a/dojox/atom/widget/nls/th/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/th/FeedViewerEntry.js
@@ -1 +1,4 @@
-({"deleteButton":"[ลบ]"})
\ No newline at end of file
+({
+	deleteButton: "[ลบ]"
+})
+
diff --git a/dojox/atom/widget/nls/th/PeopleEditor.js b/dojox/atom/widget/nls/th/PeopleEditor.js
index aaac340..3d88781 100644
--- a/dojox/atom/widget/nls/th/PeopleEditor.js
+++ b/dojox/atom/widget/nls/th/PeopleEditor.js
@@ -1 +1,6 @@
-({"add":"เพิ่ม","addAuthor":"เพิ่มผู้เขียน","addContributor":"เพิ่มผู้อนุเคราะห์"})
\ No newline at end of file
+({
+	add: "เพิ่ม",
+	addAuthor: "เพิ่มผู้เขียน",
+	addContributor: "เพิ่มผู้อนุเคราะห์"
+})
+
diff --git a/dojox/atom/widget/nls/tr/FeedEntryEditor.js b/dojox/atom/widget/nls/tr/FeedEntryEditor.js
index fbe9891..d77ca45 100644
--- a/dojox/atom/widget/nls/tr/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/tr/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[düzenle]","save":"[kaydet]","cancel":"[iptal]","doNew":"[yeni]"})
\ No newline at end of file
+({
+	doNew: "[yeni]",
+	edit: "[düzenle]",
+	save: "[kaydet]",
+	cancel: "[iptal]"
+})
diff --git a/dojox/atom/widget/nls/tr/FeedEntryViewer.js b/dojox/atom/widget/nls/tr/FeedEntryViewer.js
index 03a11d3..3ce5abf 100644
--- a/dojox/atom/widget/nls/tr/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/tr/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[kapat]","title":"Başlık","authors":"Yazarlar","summary":"Özet","content":"İçerik","contributors":"Katkıda Bulunanlar","updated":"Güncelleştirildi","displayOptions":"[görüntüleme seçenekleri]","id":"Kimlik"})
\ No newline at end of file
+({
+	displayOptions: "[görüntüleme seçenekleri]",
+	title: "Başlık",
+	authors: "Yazarlar",
+	contributors: "Katkıda Bulunanlar",
+	id: "Kimlik",
+	close: "[kapat]",
+	updated: "Güncelleştirildi",
+	summary: "Özet",
+	content: "İçerik"
+})
diff --git a/dojox/atom/widget/nls/tr/FeedViewerEntry.js b/dojox/atom/widget/nls/tr/FeedViewerEntry.js
index ce6c932..fe7dd85 100644
--- a/dojox/atom/widget/nls/tr/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/tr/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[Sil]"})
\ No newline at end of file
+({
+	deleteButton: "[Sil]"
+})
diff --git a/dojox/atom/widget/nls/tr/PeopleEditor.js b/dojox/atom/widget/nls/tr/PeopleEditor.js
index 26bade5..4bd2f04 100644
--- a/dojox/atom/widget/nls/tr/PeopleEditor.js
+++ b/dojox/atom/widget/nls/tr/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"Ekle","addAuthor":"Yazar Ekle","addContributor":"Katkıda Bulunan Ekle"})
\ No newline at end of file
+({
+	add: "Ekle",
+	addAuthor: "Yazar Ekle",
+	addContributor: "Katkıda Bulunan Ekle"
+})
diff --git a/dojox/atom/widget/nls/zh-tw/FeedEntryEditor.js b/dojox/atom/widget/nls/zh-tw/FeedEntryEditor.js
index 64e5ba5..1f8e5e4 100644
--- a/dojox/atom/widget/nls/zh-tw/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/zh-tw/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[編輯]","save":"[儲存]","cancel":"[取消]","doNew":"[新建]"})
\ No newline at end of file
+({
+	doNew: "[新建]",
+	edit: "[編輯]",
+	save: "[儲存]",
+	cancel: "[取消]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/zh-tw/FeedEntryViewer.js b/dojox/atom/widget/nls/zh-tw/FeedEntryViewer.js
index 67f9fed..22b3181 100644
--- a/dojox/atom/widget/nls/zh-tw/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/zh-tw/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[關閉]","title":"標題","authors":"作者","summary":"摘要","content":"內容","contributors":"提出者","updated":"已更新","displayOptions":"[顯示選項]","id":"ID"})
\ No newline at end of file
+({
+	displayOptions: "[顯示選項]",
+	title: "標題",
+	authors: "作者",
+	contributors: "提出者",
+	id: "ID",
+	close: "[關閉]",
+	updated: "已更新",
+	summary: "摘要",
+	content: "內容"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/zh-tw/FeedViewerEntry.js b/dojox/atom/widget/nls/zh-tw/FeedViewerEntry.js
index 9a535ed..070cb0e 100644
--- a/dojox/atom/widget/nls/zh-tw/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/zh-tw/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[刪除]"})
\ No newline at end of file
+({
+	deleteButton: "[刪除]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/zh-tw/PeopleEditor.js b/dojox/atom/widget/nls/zh-tw/PeopleEditor.js
index bd39377..af77df9 100644
--- a/dojox/atom/widget/nls/zh-tw/PeopleEditor.js
+++ b/dojox/atom/widget/nls/zh-tw/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"新增","addAuthor":"新增作者","addContributor":"新增提出者"})
\ No newline at end of file
+({
+	add: "新增",
+	addAuthor: "新增作者",
+	addContributor: "新增提出者"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/zh/FeedEntryEditor.js b/dojox/atom/widget/nls/zh/FeedEntryEditor.js
index 4d3c31d..4c95c26 100644
--- a/dojox/atom/widget/nls/zh/FeedEntryEditor.js
+++ b/dojox/atom/widget/nls/zh/FeedEntryEditor.js
@@ -1 +1,6 @@
-({"edit":"[编辑]","save":"[保存]","cancel":"[取消]","doNew":"[新建]"})
\ No newline at end of file
+({
+	doNew: "[新建]",
+	edit: "[编辑]",
+	save: "[保存]",
+	cancel: "[取消]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/zh/FeedEntryViewer.js b/dojox/atom/widget/nls/zh/FeedEntryViewer.js
index fe64bb3..0ada9c3 100644
--- a/dojox/atom/widget/nls/zh/FeedEntryViewer.js
+++ b/dojox/atom/widget/nls/zh/FeedEntryViewer.js
@@ -1 +1,11 @@
-({"close":"[关闭]","title":"标题","authors":"作者","summary":"摘要","content":"内容","contributors":"内容添加者","updated":"更新时间","displayOptions":"[显示选项]","id":"标识"})
\ No newline at end of file
+({
+	displayOptions: "[显示选项]",
+	title: "标题",
+	authors: "作者",
+	contributors: "内容添加者",
+	id: "标识",
+	close: "[关闭]",
+	updated: "更新时间",
+	summary: "摘要",
+	content: "内容"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/zh/FeedViewerEntry.js b/dojox/atom/widget/nls/zh/FeedViewerEntry.js
index b7ceb52..2eff4e3 100644
--- a/dojox/atom/widget/nls/zh/FeedViewerEntry.js
+++ b/dojox/atom/widget/nls/zh/FeedViewerEntry.js
@@ -1 +1,3 @@
-({"deleteButton":"[删除]"})
\ No newline at end of file
+({
+	deleteButton: "[删除]"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/nls/zh/PeopleEditor.js b/dojox/atom/widget/nls/zh/PeopleEditor.js
index fd7eef6..069e327 100644
--- a/dojox/atom/widget/nls/zh/PeopleEditor.js
+++ b/dojox/atom/widget/nls/zh/PeopleEditor.js
@@ -1 +1,5 @@
-({"add":"添加","addAuthor":"添加作者","addContributor":"添加内容添加者"})
\ No newline at end of file
+({
+	add: "添加",
+	addAuthor: "添加作者",
+	addContributor: "添加内容添加者"
+})
\ No newline at end of file
diff --git a/dojox/atom/widget/templates/css/EntryHeader.css b/dojox/atom/widget/templates/css/EntryHeader.css
index 5375fef..6403b61 100644
--- a/dojox/atom/widget/templates/css/EntryHeader.css
+++ b/dojox/atom/widget/templates/css/EntryHeader.css
@@ -5,6 +5,12 @@
 .graphic-tab-lgray {
 		margin-bottom: 10px;
 }
+/*
+        background: #d9d9d9;
+        border-bottom: #d9d9d9 solid 7px;
+}*/
+
+/* headers for listview */
 .newgraphic-tab-lgray {
         border-bottom: #d9d9d9 solid 7px;
 }
@@ -14,14 +20,16 @@ td.lp {
         background: #d9d9d9;
         border-bottom: #d9d9d9 solid 7px;
 }
+
 td.lp2 { 
         background: #FFFFFF;
         border-bottom: #d9d9d9 solid 7px;
 }
+
 span.lp {
         padding: 0px 13px 0px 10px;
         font-weight: bold;
         background: #d9d9d9;
         border-bottom: #d9d9d9 solid 7px;
 		width: auto;
-}
+}
\ No newline at end of file
diff --git a/dojox/atom/widget/templates/css/HtmlFeedEntryEditor.css b/dojox/atom/widget/templates/css/HtmlFeedEntryEditor.css
index f31be85..a6fa3c3 100644
--- a/dojox/atom/widget/templates/css/HtmlFeedEntryEditor.css
+++ b/dojox/atom/widget/templates/css/HtmlFeedEntryEditor.css
@@ -2,6 +2,7 @@
         color:#000000;
         background: #FFFFFF;
 }
+
 .feedEntryEditorMenuTable {
         background: #C0C0C0;      
         border:2px solid;
@@ -10,19 +11,23 @@
         border-right-color: darkgray;
         border-bottom-color: darkgray;
 }
+
 .feedEntryEditorMenu {
         cursor: pointer;
         color:#0000FF;
         text-align: left;
         font-size:  small;
 }
+
 .feedEntryEditorDisplayCheckbox {
         font-size:  small;
         text-align: left;
 }
+
 .feedEntryEditorMenu:hover {
         text-decoration: underline;
 }
+
 .feedEntryEditorTitle {
         color:#000000;
         background: #FFFFFF;
@@ -31,10 +36,12 @@
         font-size:  125%;
         font-weight: bold; 
 }
+
 .feedEntryEditorAuthor {
         color:#000000;
         background: #FFFFFF;
 }
+
 .feedEntryEditorAuthorNames {
         color:#000000;
         background: #FFFFFF;
@@ -44,14 +51,17 @@
         font-style: italic;
         font-weight: normal;
 }
+
 .feedEntryEditorSummary {
         color:#000000;
         background: #FFFFFF;
 }
+
 .feedEntryEditorUpdated {
         color:#000000;
         background: #FFFFFF;
 }
+
 .feedEntryEditorUpdatedText {
         color:#000000;
         background: #FFFFFF;
@@ -59,10 +69,12 @@
         font-style: italic;
         font-weight: normal;
 }
+
 .feedEntryEditorId {
         color:#000000;
         background: #FFFFFF;
 }
+
 .feedEntryEditorIdText {
         color:#000000;
         background: #FFFFFF;
@@ -70,10 +82,12 @@
         font-size:  110%;
         font-weight: normal;
 }
+
 .feedEntryEditorContent {
         color:#000000;
         background: #FFFFFF;
 }
+
 .feedEntryEditorContributorNames {
         color:#000000;
         text-align: left;
diff --git a/dojox/atom/widget/templates/css/HtmlFeedEntryViewer.css b/dojox/atom/widget/templates/css/HtmlFeedEntryViewer.css
index 7ab9cbb..36400c9 100644
--- a/dojox/atom/widget/templates/css/HtmlFeedEntryViewer.css
+++ b/dojox/atom/widget/templates/css/HtmlFeedEntryViewer.css
@@ -1,7 +1,9 @@
 .feedEntryViewer {
         color:#000000;
         background: #FFFFFF;
+/*		overflow: auto;*/
 }
+
 .feedEntryViewerMenuTable {
         background: #C0C0C0;      
         border:2px solid;
@@ -11,52 +13,62 @@
         border-bottom-color: darkgray;
 		margin: 0;
 }
+
 .feedEntryViewerMenu, .peopleEditorButton {
         cursor: pointer;
         color:#0000FF;
         text-align: left;
         font-size:  small;
 }
+
 .feedEntryViewerDisplayCheckbox {
         font-size:  small;
         text-align: left;
 }
+
 .feedEntryViewerMenu:hover, .peopleEditorButton:hover {
         text-decoration: underline;
 }
+
 .feedEntryViewerContainer, .feedEntryViewerContainer table {
 		border-width: 0;
 		margin: 0;
 }
+
 .feedEntryViewerTitle {
         color:#000000;
         background: #FFFFFF;
         text-align: left;
-        
+        /*padding-left: 10px;*/
         font-size:  125%;
         font-weight: bold; 
 }
+
 .feedEntryViewerAuthor {
         color:#000000;
         background: #FFFFFF;
 }
+
 .feedEntryViewerAuthorNames {
         color:#000000;
         background: #FFFFFF;
         text-align: left;
-        
+        /*padding-left: 10px;*/
         font-size:  110%;
         font-style: italic;
         font-weight: normal;
 }
+
 .feedEntryViewerSummary {
         color:#000000;
         background: #FFFFFF;
 }
+
 .feedEntryViewerUpdated {
         color:#000000;
         background: #FFFFFF;
 }
+
 .feedEntryViewerUpdatedText {
         color:#000000;
         background: #FFFFFF;
@@ -64,10 +76,12 @@
         font-style: italic;
         font-weight: normal;
 }
+
 .feedEntryViewerId {
         color:#000000;
         background: #FFFFFF;
 }
+
 .feedEntryViewerIdText {
         color:#000000;
         background: #FFFFFF;
@@ -75,16 +89,19 @@
         font-size:  110%;
         font-weight: normal;
 }
+
 .feedEntryViewerContent {
         color:#000000;
         background: #FFFFFF;
 }
+
 .feedEntryViewerContributorNames {
         color:#000000;
         text-align: left;
-        
+        /*padding-left: 10px;*/
         font-size:  125%;
         font-weight: normal;
 }
+
 .feedEntryViewer table {
-}
+}
\ No newline at end of file
diff --git a/dojox/atom/widget/templates/css/HtmlFeedViewer.css b/dojox/atom/widget/templates/css/HtmlFeedViewer.css
index 70d3a57..395df3d 100644
--- a/dojox/atom/widget/templates/css/HtmlFeedViewer.css
+++ b/dojox/atom/widget/templates/css/HtmlFeedViewer.css
@@ -4,10 +4,12 @@
 	cursor:default;
 	padding:2px;
 }
+
 .feedViewerTable, .feedViewerTable table {
 	border-width: 0;
 	margin: 0;
 }
+
 .feedViewerTableBody {
 	overflow-x: auto;
 	overflow-y: auto;
diff --git a/dojox/atom/widget/templates/css/HtmlFeedViewerEntry.css b/dojox/atom/widget/templates/css/HtmlFeedViewerEntry.css
index 8318b31..49a7f6c 100644
--- a/dojox/atom/widget/templates/css/HtmlFeedViewerEntry.css
+++ b/dojox/atom/widget/templates/css/HtmlFeedViewerEntry.css
@@ -5,10 +5,12 @@
         overflow-y: auto;
         cursor: pointer;   
 }
+
 .feedViewerEntry:hover {
         background: #a6c2e7;
         padding: 2px;
 }
+
 .feedViewerEntrySelected {
         color: #000000;
         background: #C0C0C0;
@@ -17,10 +19,13 @@
         padding-bottom: 2px;
         padding: 2px;
 }
+
 .feedViewerEntrySelected:hover {
         background: #a6c2e7;
         padding: 2px;
 }
+
+
 .feedViewerEntryUpdated {
         text-align: left;
         vertical-align: top;
@@ -28,6 +33,7 @@
         padding-bottom: 2px;
         padding: 2px;
 }
+
 .feedViewerEntryUpdatedSelected {
         text-align: left;
         vertical-align: top;
@@ -35,6 +41,8 @@
         padding-bottom: 2px;
         padding: 2px;
 }
+
+
 .feedViewerEntryTitle {
         color:#000000;
         text-align: left;
@@ -49,12 +57,14 @@
         padding-left: 4px;
         padding-bottom: 2px;
 }
+
 .feedViewerDeleteButton {
         cursor: pointer;
         color:#0000FF;
         text-align: left;
         font-size:  small;
 }
+
 .feedViewerDeleteButton:hover {
         text-decoration: underline;
 }
diff --git a/dojox/charting/Chart2D.js b/dojox/charting/Chart2D.js
index 35eb86b..60244e7 100644
--- a/dojox/charting/Chart2D.js
+++ b/dojox/charting/Chart2D.js
@@ -1,20 +1,18 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.Chart2D"]){
-dojo._hasResource["dojox.charting.Chart2D"]=true;
 dojo.provide("dojox.charting.Chart2D");
+
 dojo.require("dojox.gfx");
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.fold");
 dojo.require("dojox.lang.functional.reversed");
+
 dojo.require("dojox.charting.Theme");
 dojo.require("dojox.charting.Series");
+
+// require all axes to support references by name
 dojo.require("dojox.charting.axis2d.Default");
+dojo.require("dojox.charting.axis2d.Invisible");
+
+// require all plots to support references by name
 dojo.require("dojox.charting.plot2d.Default");
 dojo.require("dojox.charting.plot2d.Lines");
 dojo.require("dojox.charting.plot2d.Areas");
@@ -35,341 +33,1025 @@ dojo.require("dojox.charting.plot2d.Pie");
 dojo.require("dojox.charting.plot2d.Bubble");
 dojo.require("dojox.charting.plot2d.Candlesticks");
 dojo.require("dojox.charting.plot2d.OHLC");
-(function(){
-var df=dojox.lang.functional,dc=dojox.charting,_1=df.lambda("item.clear()"),_2=df.lambda("item.purgeGroup()"),_3=df.lambda("item.destroy()"),_4=df.lambda("item.dirty = false"),_5=df.lambda("item.dirty = true");
-dojo.declare("dojox.charting.Chart2D",null,{constructor:function(_6,_7){
-if(!_7){
-_7={};
-}
-this.margins=_7.margins?_7.margins:{l:10,t:10,r:10,b:10};
-this.stroke=_7.stroke;
-this.fill=_7.fill;
-this.theme=null;
-this.axes={};
-this.stack=[];
-this.plots={};
-this.series=[];
-this.runs={};
-this.dirty=true;
-this.coords=null;
-this.node=dojo.byId(_6);
-var _8=dojo.marginBox(_6);
-this.surface=dojox.gfx.createSurface(this.node,_8.w,_8.h);
-},destroy:function(){
-dojo.forEach(this.series,_3);
-dojo.forEach(this.stack,_3);
-df.forIn(this.axes,_3);
-this.surface.destroy();
-},getCoords:function(){
-if(!this.coords){
-this.coords=dojo.coords(this.node,true);
-}
-return this.coords;
-},setTheme:function(_9){
-this.theme=_9._clone();
-this.dirty=true;
-return this;
-},addAxis:function(_a,_b){
-var _c;
-if(!_b||!("type" in _b)){
-_c=new dc.axis2d.Default(this,_b);
-}else{
-_c=typeof _b.type=="string"?new dc.axis2d[_b.type](this,_b):new _b.type(this,_b);
-}
-_c.name=_a;
-_c.dirty=true;
-if(_a in this.axes){
-this.axes[_a].destroy();
-}
-this.axes[_a]=_c;
-this.dirty=true;
-return this;
-},getAxis:function(_d){
-return this.axes[_d];
-},removeAxis:function(_e){
-if(_e in this.axes){
-this.axes[_e].destroy();
-delete this.axes[_e];
-this.dirty=true;
-}
-return this;
-},addPlot:function(_f,_10){
-var _11;
-if(!_10||!("type" in _10)){
-_11=new dc.plot2d.Default(this,_10);
-}else{
-_11=typeof _10.type=="string"?new dc.plot2d[_10.type](this,_10):new _10.type(this,_10);
-}
-_11.name=_f;
-_11.dirty=true;
-if(_f in this.plots){
-this.stack[this.plots[_f]].destroy();
-this.stack[this.plots[_f]]=_11;
-}else{
-this.plots[_f]=this.stack.length;
-this.stack.push(_11);
-}
-this.dirty=true;
-return this;
-},removePlot:function(_12){
-if(_12 in this.plots){
-var _13=this.plots[_12];
-delete this.plots[_12];
-this.stack[_13].destroy();
-this.stack.splice(_13,1);
-df.forIn(this.plots,function(idx,_14,_15){
-if(idx>_13){
-_15[_14]=idx-1;
-}
-});
-this.dirty=true;
-}
-return this;
-},addSeries:function(_16,_17,_18){
-var run=new dc.Series(this,_17,_18);
-if(_16 in this.runs){
-this.series[this.runs[_16]].destroy();
-this.series[this.runs[_16]]=run;
-}else{
-this.runs[_16]=this.series.length;
-this.series.push(run);
-}
-run.name=_16;
-this.dirty=true;
-if(!("ymin" in run)&&"min" in run){
-run.ymin=run.min;
-}
-if(!("ymax" in run)&&"max" in run){
-run.ymax=run.max;
-}
-return this;
-},removeSeries:function(_19){
-if(_19 in this.runs){
-var _1a=this.runs[_19],_1b=this.series[_1a].plot;
-delete this.runs[_19];
-this.series[_1a].destroy();
-this.series.splice(_1a,1);
-df.forIn(this.runs,function(idx,_1c,_1d){
-if(idx>_1a){
-_1d[_1c]=idx-1;
-}
-});
-this.dirty=true;
-}
-return this;
-},updateSeries:function(_1e,_1f){
-if(_1e in this.runs){
-var run=this.series[this.runs[_1e]];
-run.data=_1f;
-run.dirty=true;
-this._invalidateDependentPlots(run.plot,false);
-this._invalidateDependentPlots(run.plot,true);
-}
-return this;
-},resize:function(_20,_21){
-var box;
-switch(arguments.length){
-case 0:
-box=dojo.marginBox(this.node);
-break;
-case 1:
-box=_20;
-break;
-default:
-box={w:_20,h:_21};
-break;
-}
-dojo.marginBox(this.node,box);
-this.surface.setDimensions(box.w,box.h);
-this.dirty=true;
-this.coords=null;
-return this.render();
-},getGeometry:function(){
-var ret={};
-df.forIn(this.axes,function(_22){
-if(_22.initialized()){
-ret[_22.name]={name:_22.name,vertical:_22.vertical,scaler:_22.scaler,ticks:_22.ticks};
-}
-});
-return ret;
-},setAxisWindow:function(_23,_24,_25){
-var _26=this.axes[_23];
-if(_26){
-_26.setWindow(_24,_25);
-}
-return this;
-},setWindow:function(sx,sy,dx,dy){
-if(!("plotArea" in this)){
-this.calculateGeometry();
-}
-df.forIn(this.axes,function(_27){
-var _28,_29,_2a=_27.getScaler().bounds,s=_2a.span/(_2a.upper-_2a.lower);
-if(_27.vertical){
-_28=sy;
-_29=dy/s/_28;
-}else{
-_28=sx;
-_29=dx/s/_28;
-}
-_27.setWindow(_28,_29);
-});
-return this;
-},calculateGeometry:function(){
-if(this.dirty){
-return this.fullGeometry();
-}
-dojo.forEach(this.stack,function(_2b){
-if(_2b.dirty||(_2b.hAxis&&this.axes[_2b.hAxis].dirty)||(_2b.vAxis&&this.axes[_2b.vAxis].dirty)){
-_2b.calculateAxes(this.plotArea);
-}
-},this);
-return this;
-},fullGeometry:function(){
-this._makeDirty();
-dojo.forEach(this.stack,_1);
-if(!this.theme){
-this.setTheme(new dojox.charting.Theme(dojox.charting._def));
-}
-dojo.forEach(this.series,function(run){
-if(!(run.plot in this.plots)){
-var _2c=new dc.plot2d.Default(this,{});
-_2c.name=run.plot;
-this.plots[run.plot]=this.stack.length;
-this.stack.push(_2c);
-}
-this.stack[this.plots[run.plot]].addSeries(run);
-},this);
-dojo.forEach(this.stack,function(_2d){
-if(_2d.hAxis){
-_2d.setAxis(this.axes[_2d.hAxis]);
-}
-if(_2d.vAxis){
-_2d.setAxis(this.axes[_2d.vAxis]);
-}
-},this);
-var dim=this.dim=this.surface.getDimensions();
-dim.width=dojox.gfx.normalizedLength(dim.width);
-dim.height=dojox.gfx.normalizedLength(dim.height);
-df.forIn(this.axes,_1);
-dojo.forEach(this.stack,function(p){
-p.calculateAxes(dim);
-});
-var _2e=this.offsets={l:0,r:0,t:0,b:0};
-df.forIn(this.axes,function(_2f){
-df.forIn(_2f.getOffsets(),function(o,i){
-_2e[i]+=o;
-});
-});
-df.forIn(this.margins,function(o,i){
-_2e[i]+=o;
-});
-this.plotArea={width:dim.width-_2e.l-_2e.r,height:dim.height-_2e.t-_2e.b};
-df.forIn(this.axes,_1);
-dojo.forEach(this.stack,function(_30){
-_30.calculateAxes(this.plotArea);
-},this);
-return this;
-},render:function(){
-if(this.theme){
-this.theme.clear();
-}
-if(this.dirty){
-return this.fullRender();
-}
-this.calculateGeometry();
-df.forEachRev(this.stack,function(_31){
-_31.render(this.dim,this.offsets);
-},this);
-df.forIn(this.axes,function(_32){
-_32.render(this.dim,this.offsets);
-},this);
-this._makeClean();
-if(this.surface.render){
-this.surface.render();
-}
-return this;
-},fullRender:function(){
-this.fullGeometry();
-var _33=this.offsets,dim=this.dim;
-var _34=df.foldl(this.stack,"z + plot.getRequiredColors()",0);
-this.theme.defineColors({num:_34,cache:false});
-dojo.forEach(this.series,_2);
-df.forIn(this.axes,_2);
-dojo.forEach(this.stack,_2);
-this.surface.clear();
-var t=this.theme,_35=t.plotarea&&t.plotarea.fill,_36=t.plotarea&&t.plotarea.stroke;
-if(_35){
-this.surface.createRect({x:_33.l,y:_33.t,width:dim.width-_33.l-_33.r,height:dim.height-_33.t-_33.b}).setFill(_35);
-}
-if(_36){
-this.surface.createRect({x:_33.l,y:_33.t,width:dim.width-_33.l-_33.r-1,height:dim.height-_33.t-_33.b-1}).setStroke(_36);
-}
-df.foldr(this.stack,function(z,_37){
-return _37.render(dim,_33),0;
-},0);
-_35=this.fill?this.fill:(t.chart&&t.chart.fill);
-_36=this.stroke?this.stroke:(t.chart&&t.chart.stroke);
-if(_35=="inherit"){
-var _38=this.node,_35=new dojo.Color(dojo.style(_38,"backgroundColor"));
-while(_35.a==0&&_38!=document.documentElement){
-_35=new dojo.Color(dojo.style(_38,"backgroundColor"));
-_38=_38.parentNode;
-}
-}
-if(_35){
-if(_33.l){
-this.surface.createRect({width:_33.l,height:dim.height+1}).setFill(_35);
-}
-if(_33.r){
-this.surface.createRect({x:dim.width-_33.r,width:_33.r+1,height:dim.height+1}).setFill(_35);
-}
-if(_33.t){
-this.surface.createRect({width:dim.width+1,height:_33.t}).setFill(_35);
-}
-if(_33.b){
-this.surface.createRect({y:dim.height-_33.b,width:dim.width+1,height:_33.b+2}).setFill(_35);
-}
-}
-if(_36){
-this.surface.createRect({width:dim.width-1,height:dim.height-1}).setStroke(_36);
-}
-df.forIn(this.axes,function(_39){
-_39.render(dim,_33);
-});
-this._makeClean();
-if(this.surface.render){
-this.surface.render();
-}
-return this;
-},connectToPlot:function(_3a,_3b,_3c){
-return _3a in this.plots?this.stack[this.plots[_3a]].connect(_3b,_3c):null;
-},_makeClean:function(){
-dojo.forEach(this.axes,_4);
-dojo.forEach(this.stack,_4);
-dojo.forEach(this.series,_4);
-this.dirty=false;
-},_makeDirty:function(){
-dojo.forEach(this.axes,_5);
-dojo.forEach(this.stack,_5);
-dojo.forEach(this.series,_5);
-this.dirty=true;
-},_invalidateDependentPlots:function(_3d,_3e){
-if(_3d in this.plots){
-var _3f=this.stack[this.plots[_3d]],_40,_41=_3e?"vAxis":"hAxis";
-if(_3f[_41]){
-_40=this.axes[_3f[_41]];
-if(_40&&_40.dependOnData()){
-_40.dirty=true;
-dojo.forEach(this.stack,function(p){
-if(p[_41]&&p[_41]==_3f[_41]){
-p.dirty=true;
-}
-});
-}
-}else{
-_3f.dirty=true;
-}
+
+/*=====
+dojox.charting.__Chart2DCtorArgs = function(margins, stroke, fill, delayInMs){
+	//	summary:
+	//		The keyword arguments that can be passed in a Chart2D constructor.
+	//
+	//	margins: Object?
+	//		Optional margins for the chart, in the form of { l, t, r, b}.
+	//	stroke: dojox.gfx.Stroke?
+	//		An optional outline/stroke for the chart.
+	//	fill: dojox.gfx.Fill?
+	//		An optional fill for the chart.
+	//	delayInMs: Number
+	//		Delay in ms for delayedRender(). Default: 200.
+	this.margins = margins;
+	this.stroke = stroke;
+	this.fill = fill;
+	this.delayInMs = delayInMs;
 }
-}});
+ =====*/
+(function(){
+	var df = dojox.lang.functional, dc = dojox.charting,
+		clear = df.lambda("item.clear()"),
+		purge = df.lambda("item.purgeGroup()"),
+		destroy = df.lambda("item.destroy()"),
+		makeClean = df.lambda("item.dirty = false"),
+		makeDirty = df.lambda("item.dirty = true"),
+		getName = df.lambda("item.name");
+
+	dojo.declare("dojox.charting.Chart2D", null, {
+		//	summary:
+		//		The main chart object in dojox.charting.  This will create a two dimensional
+		//		chart based on dojox.gfx.
+		//
+		//	description:
+		//		dojox.charting.Chart2D is the primary object used for any kind of charts.  It
+		//		is simple to create--just pass it a node reference, which is used as the
+		//		container for the chart--and a set of optional keyword arguments and go.
+		//
+		//		Note that like most of dojox.gfx, most of dojox.charting.Chart2D's methods are
+		//		designed to return a reference to the chart itself, to allow for functional
+		//		chaining.  This makes defining everything on a Chart very easy to do.
+		//
+		//	example:
+		//		Create an area chart, with smoothing.
+		//	|	new dojox.charting.Chart2D(node))
+		//	|		.addPlot("default", { type: "Areas", tension: "X" })
+		//	|		.setTheme(dojox.charting.themes.Shrooms)
+		//	|		.addSeries("Series A", [1, 2, 0.5, 1.5, 1, 2.8, 0.4])
+		//	|		.addSeries("Series B", [2.6, 1.8, 2, 1, 1.4, 0.7, 2])
+		//	|		.addSeries("Series C", [6.3, 1.8, 3, 0.5, 4.4, 2.7, 2])
+		//	|		.render();
+		//
+		//	example:
+		//		The form of data in a data series can take a number of forms: a simple array,
+		//		an array of objects {x,y}, or something custom (as determined by the plot).
+		//		Here's an example of a Candlestick chart, which expects an object of
+		//		{ open, high, low, close }.
+		//	|	new dojox.charting.Chart2D(node))
+		//	|		.addPlot("default", {type: "Candlesticks", gap: 1})
+		//	|		.addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true})
+		//	|		.addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true})
+		//	|		.addSeries("Series A", [
+		//	|				{ open: 20, close: 16, high: 22, low: 8 },
+		//	|				{ open: 16, close: 22, high: 26, low: 6, mid: 18 },
+		//	|				{ open: 22, close: 18, high: 22, low: 11, mid: 21 },
+		//	|				{ open: 18, close: 29, high: 32, low: 14, mid: 27 },
+		//	|				{ open: 29, close: 24, high: 29, low: 13, mid: 27 },
+		//	|				{ open: 24, close: 8, high: 24, low: 5 },
+		//	|				{ open: 8, close: 16, high: 22, low: 2 },
+		//	|				{ open: 16, close: 12, high: 19, low: 7 },
+		//	|				{ open: 12, close: 20, high: 22, low: 8 },
+		//	|				{ open: 20, close: 16, high: 22, low: 8 },
+		//	|				{ open: 16, close: 22, high: 26, low: 6, mid: 18 },
+		//	|				{ open: 22, close: 18, high: 22, low: 11, mid: 21 },
+		//	|				{ open: 18, close: 29, high: 32, low: 14, mid: 27 },
+		//	|				{ open: 29, close: 24, high: 29, low: 13, mid: 27 },
+		//	|				{ open: 24, close: 8, high: 24, low: 5 },
+		//	|				{ open: 8, close: 16, high: 22, low: 2 },
+		//	|				{ open: 16, close: 12, high: 19, low: 7 },
+		//	|				{ open: 12, close: 20, high: 22, low: 8 },
+		//	|				{ open: 20, close: 16, high: 22, low: 8 },
+		//	|				{ open: 16, close: 22, high: 26, low: 6 },
+		//	|				{ open: 22, close: 18, high: 22, low: 11 },
+		//	|				{ open: 18, close: 29, high: 32, low: 14 },
+		//	|				{ open: 29, close: 24, high: 29, low: 13 },
+		//	|				{ open: 24, close: 8, high: 24, low: 5 },
+		//	|				{ open: 8, close: 16, high: 22, low: 2 },
+		//	|				{ open: 16, close: 12, high: 19, low: 7 },
+		//	|				{ open: 12, close: 20, high: 22, low: 8 },
+		//	|				{ open: 20, close: 16, high: 22, low: 8 }
+		//	|			],
+		//	|			{ stroke: { color: "green" }, fill: "lightgreen" }
+		//	|		)
+		//	|		.render();
+		//
+		//	theme: dojox.charting.Theme?
+		//		An optional theme to use for styling the chart.
+		//	axes: dojox.charting.Axis{}?
+		//		A map of axes for use in plotting a chart.
+		//	stack: dojox.charting.plot2d.Base[]
+		//		A stack of plotters.
+		//	plots: dojox.charting.plot2d.Base{}
+		//		A map of plotter indices
+		//	series: dojox.charting.Series[]
+		//		The stack of data runs used to create plots.
+		//	runs: dojox.charting.Series{}
+		//		A map of series indices
+		//	margins: Object?
+		//		The margins around the chart. Default is { l:10, t:10, r:10, b:10 }.
+		//	stroke: dojox.gfx.Stroke?
+		//		The outline of the chart (stroke in vector graphics terms).
+		//	fill: dojox.gfx.Fill?
+		//		The color for the chart.
+		//	node: DOMNode
+		//		The container node passed to the constructor.
+		//	surface: dojox.gfx.Surface
+		//		The main graphics surface upon which a chart is drawn.
+		//	dirty: Boolean
+		//		A boolean flag indicating whether or not the chart needs to be updated/re-rendered.
+		//	coords: Object
+		//		The coordinates on a page of the containing node, as returned from dojo.coords.
+
+		constructor: function(/* DOMNode */node, /* dojox.charting.__Chart2DCtorArgs? */kwArgs){
+			//	summary:
+			//		The constructor for a new Chart2D.  Initializes all parameters used for a chart.
+			//	returns: dojox.charting.Chart2D
+			//		The newly created chart.
+
+			// initialize parameters
+			if(!kwArgs){ kwArgs = {}; }
+			this.margins   = kwArgs.margins ? kwArgs.margins : {l: 10, t: 10, r: 10, b: 10};
+			this.stroke    = kwArgs.stroke;
+			this.fill      = kwArgs.fill;
+			this.delayInMs = kwArgs.delayInMs || 200;
+
+			// default initialization
+			this.theme = null;
+			this.axes = {};		// map of axes
+			this.stack = [];	// stack of plotters
+			this.plots = {};	// map of plotter indices
+			this.series = [];	// stack of data runs
+			this.runs = {};		// map of data run indices
+			this.dirty = true;
+			this.coords = null;
+
+			// create a surface
+			this.node = dojo.byId(node);
+			var box = dojo.marginBox(node);
+			this.surface = dojox.gfx.createSurface(this.node, box.w || 400, box.h || 300);
+		},
+		destroy: function(){
+			//	summary:
+			//		Cleanup when a chart is to be destroyed.
+			//	returns: void
+			dojo.forEach(this.series, destroy);
+			dojo.forEach(this.stack,  destroy);
+			df.forIn(this.axes, destroy);
+			this.surface.destroy();
+		},
+		getCoords: function(){
+			//	summary:
+			//		Get the coordinates and dimensions of the containing DOMNode, as
+			//		returned by dojo.coords.
+			//	returns: Object
+			//		The resulting coordinates of the chart.  See dojo.coords for details.
+			if(!this.coords){
+				this.coords = dojo.coords(this.node, true);
+			}
+			return this.coords;	//	Object
+		},
+		setTheme: function(theme){
+			//	summary:
+			//		Set a theme of the chart.
+			//	theme: dojox.charting.Theme
+			//		The theme to be used for visual rendering.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			this.theme = theme.clone();
+			this.dirty = true;
+			return this;	//	dojox.charting.Chart2D
+		},
+		addAxis: function(name, kwArgs){
+			//	summary:
+			//		Add an axis to the chart, for rendering.
+			//	name: String
+			//		The name of the axis.
+			//	kwArgs: dojox.charting.axis2d.__AxisCtorArgs?
+			//		An optional keyword arguments object for use in defining details of an axis.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			var axis;
+			if(!kwArgs || !("type" in kwArgs)){
+				axis = new dc.axis2d.Default(this, kwArgs);
+			}else{
+				axis = typeof kwArgs.type == "string" ?
+					new dc.axis2d[kwArgs.type](this, kwArgs) :
+					new kwArgs.type(this, kwArgs);
+			}
+			axis.name = name;
+			axis.dirty = true;
+			if(name in this.axes){
+				this.axes[name].destroy();
+			}
+			this.axes[name] = axis;
+			this.dirty = true;
+			return this;	//	dojox.charting.Chart2D
+		},
+		getAxis: function(name){
+			//	summary:
+			//		Get the given axis, by name.
+			//	name: String
+			//		The name the axis was defined by.
+			//	returns: dojox.charting.axis2d.Default
+			//		The axis as stored in the chart's axis map.
+			return this.axes[name];	//	dojox.charting.axis2d.Default
+		},
+		removeAxis: function(name){
+			//	summary:
+			//		Remove the axis that was defined using name.
+			//	name: String
+			//		The axis name, as defined in addAxis.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(name in this.axes){
+				// destroy the axis
+				this.axes[name].destroy();
+				delete this.axes[name];
+				// mark the chart as dirty
+				this.dirty = true;
+			}
+			return this;	//	dojox.charting.Chart2D
+		},
+		addPlot: function(name, kwArgs){
+			//	summary:
+			//		Add a new plot to the chart, defined by name and using the optional keyword arguments object.
+			//		Note that dojox.charting assumes the main plot to be called "default"; if you do not have
+			//		a plot called "default" and attempt to add data series to the chart without specifying the
+			//		plot to be rendered on, you WILL get errors.
+			//	name: String
+			//		The name of the plot to be added to the chart.  If you only plan on using one plot, call it "default".
+			//	kwArgs: dojox.charting.plot2d.__PlotCtorArgs
+			//		An object with optional parameters for the plot in question.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			var plot;
+			if(!kwArgs || !("type" in kwArgs)){
+				plot = new dc.plot2d.Default(this, kwArgs);
+			}else{
+				plot = typeof kwArgs.type == "string" ?
+					new dc.plot2d[kwArgs.type](this, kwArgs) :
+					new kwArgs.type(this, kwArgs);
+			}
+			plot.name = name;
+			plot.dirty = true;
+			if(name in this.plots){
+				this.stack[this.plots[name]].destroy();
+				this.stack[this.plots[name]] = plot;
+			}else{
+				this.plots[name] = this.stack.length;
+				this.stack.push(plot);
+			}
+			this.dirty = true;
+			return this;	//	dojox.charting.Chart2D
+		},
+		removePlot: function(name){
+			//	summary:
+			//		Remove the plot defined using name from the chart's plot stack.
+			//	name: String
+			//		The name of the plot as defined using addPlot.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(name in this.plots){
+				// get the index and remove the name
+				var index = this.plots[name];
+				delete this.plots[name];
+				// destroy the plot
+				this.stack[index].destroy();
+				// remove the plot from the stack
+				this.stack.splice(index, 1);
+				// update indices to reflect the shift
+				df.forIn(this.plots, function(idx, name, plots){
+					if(idx > index){
+						plots[name] = idx - 1;
+					}
+				});
+				// mark the chart as dirty
+				this.dirty = true;
+			}
+			return this;	//	dojox.charting.Chart2D
+		},
+		getPlotOrder: function(){
+			//	summary:
+			//		Returns an array of plot names in the current order
+			//		(the top-most plot is the first).
+			//	returns: Array
+			return df.map(this.stack, getName); // Array
+		},
+		setPlotOrder: function(newOrder){
+			//	summary:
+			//		Sets new order of plots. newOrder cannot add or remove
+			//		plots. Wrong names, or dups are ignored.
+			//	newOrder: Array:
+			//		Array of plot names compatible with getPlotOrder().
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			var names = {},
+				order = df.filter(newOrder, function(name){
+					if(!(name in this.plots) || (name in names)){
+						return false;
+					}
+					names[name] = 1;
+					return true;
+				}, this);
+			if(order.length < this.stack.length){
+				df.forEach(this.stack, function(plot){
+					var name = plot.name;
+					if(!(name in names)){
+						order.push(name);
+					}
+				});
+			}
+			var newStack = df.map(order, function(name){
+					return this.stack[this.plots[name]];
+				}, this);
+			df.forEach(newStack, function(plot, i){
+				this.plots[plot.name] = i;
+			}, this);
+			this.stack = newStack;
+			this.dirty = true;
+			return this;	//	dojox.charting.Chart2D
+		},
+		movePlotToFront: function(name){
+			//	summary:
+			//		Moves a given plot to front.
+			//	name: String:
+			//		Plot's name to move.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(name in this.plots){
+				var index = this.plots[name];
+				if(index){
+					var newOrder = this.getPlotOrder();
+					newOrder.splice(index, 1);
+					newOrder.unshift(name);
+					return this.setPlotOrder(newOrder);	//	dojox.charting.Chart2D
+				}
+			}
+			return this;	//	dojox.charting.Chart2D
+		},
+		movePlotToBack: function(name){
+			//	summary:
+			//		Moves a given plot to back.
+			//	name: String:
+			//		Plot's name to move.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(name in this.plots){
+				var index = this.plots[name];
+				if(index < this.stack.length - 1){
+					var newOrder = this.getPlotOrder();
+					newOrder.splice(index, 1);
+					newOrder.push(name);
+					return this.setPlotOrder(newOrder);	//	dojox.charting.Chart2D
+				}
+			}
+			return this;	//	dojox.charting.Chart2D
+		},
+		addSeries: function(name, data, kwArgs){
+			//	summary:
+			//		Add a data series to the chart for rendering.
+			//	name: String:
+			//		The name of the data series to be plotted.
+			//	data: Array|Object:
+			//		The array of data points (either numbers or objects) that
+			//		represents the data to be drawn. Or it can be an object. In
+			//		the latter case, it should have a property "data" (an array),
+			//		destroy(), and setSeriesObject().
+			//	kwArgs: dojox.charting.__SeriesCtorArgs?:
+			//		An optional keyword arguments object that will be mixed into
+			//		the resultant series object.
+			//	returns: dojox.charting.Chart2D:
+			//		A reference to the current chart for functional chaining.
+			var run = new dc.Series(this, data, kwArgs);
+			run.name = name;
+			if(name in this.runs){
+				this.series[this.runs[name]].destroy();
+				this.series[this.runs[name]] = run;
+			}else{
+				this.runs[name] = this.series.length;
+				this.series.push(run);
+			}
+			this.dirty = true;
+			// fix min/max
+			if(!("ymin" in run) && "min" in run){ run.ymin = run.min; }
+			if(!("ymax" in run) && "max" in run){ run.ymax = run.max; }
+			return this;	//	dojox.charting.Chart2D
+		},
+		removeSeries: function(name){
+			//	summary:
+			//		Remove the series defined by name from the chart.
+			//	name: String
+			//		The name of the series as defined by addSeries.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(name in this.runs){
+				// get the index and remove the name
+				var index = this.runs[name],
+					plotName = this.series[index].plot;
+				delete this.runs[name];
+				// destroy the run
+				this.series[index].destroy();
+				// remove the run from the stack of series
+				this.series.splice(index, 1);
+				// update indices to reflect the shift
+				df.forIn(this.runs, function(idx, name, runs){
+					if(idx > index){
+						runs[name] = idx - 1;
+					}
+				});
+				this.dirty = true;
+			}
+			return this;	//	dojox.charting.Chart2D
+		},
+		updateSeries: function(name, data){
+			//	summary:
+			//		Update the given series with a new set of data points.
+			//	name: String
+			//		The name of the series as defined in addSeries.
+			//	data: Array|Object:
+			//		The array of data points (either numbers or objects) that
+			//		represents the data to be drawn. Or it can be an object. In
+			//		the latter case, it should have a property "data" (an array),
+			//		destroy(), and setSeriesObject().
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(name in this.runs){
+				var run = this.series[this.runs[name]];
+				run.update(data);
+				this._invalidateDependentPlots(run.plot, false);
+				this._invalidateDependentPlots(run.plot, true);
+			}
+			return this;	//	dojox.charting.Chart2D
+		},
+		getSeriesOrder: function(plotName){
+			//	summary:
+			//		Returns an array of series names in the current order
+			//		(the top-most series is the first) within a plot.
+			//	plotName: String:
+			//		Plot's name.
+			//	returns: Array
+			return df.map(df.filter(this.series, function(run){
+					return run.plot == plotName;
+				}), getName);
+		},
+		setSeriesOrder: function(newOrder){
+			//	summary:
+			//		Sets new order of series within a plot. newOrder cannot add
+			//		or remove series. Wrong names, or dups are ignored.
+			//	newOrder: Array:
+			//		Array of series names compatible with getPlotOrder(). All
+			//		series should belong to the same plot.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			var plotName, names = {},
+				order = df.filter(newOrder, function(name){
+					if(!(name in this.runs) || (name in names)){
+						return false;
+					}
+					var run = this.series[this.runs[name]];
+					if(plotName){
+						if(run.plot != plotName){
+							return false;
+						}
+					}else{
+						plotName = run.plot;
+					}
+					names[name] = 1;
+					return true;
+				}, this);
+			df.forEach(this.series, function(run){
+				var name = run.name;
+				if(!(name in names) && run.plot == plotName){
+					order.push(name);
+				}
+			});
+			var newSeries = df.map(order, function(name){
+					return this.series[this.runs[name]];
+				}, this);
+			this.series = newSeries.concat(df.filter(this.series, function(run){
+				return run.plot != plotName;
+			}));
+			df.forEach(this.series, function(run, i){
+				this.runs[run.name] = i;
+			}, this);
+			this.dirty = true;
+			return this;	//	dojox.charting.Chart2D
+		},
+		moveSeriesToFront: function(name){
+			//	summary:
+			//		Moves a given series to front of a plot.
+			//	name: String:
+			//		Series' name to move.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(name in this.runs){
+				var index = this.runs[name],
+					newOrder = this.getSeriesOrder(this.series[index].plot);
+				if(name != newOrder[0]){
+					newOrder.splice(index, 1);
+					newOrder.unshift(name);
+					return this.setSeriesOrder(newOrder);	//	dojox.charting.Chart2D
+				}
+			}
+			return this;	//	dojox.charting.Chart2D
+		},
+		moveSeriesToBack: function(name){
+			//	summary:
+			//		Moves a given series to back of a plot.
+			//	name: String:
+			//		Series' name to move.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(name in this.runs){
+				var index = this.runs[name],
+					newOrder = this.getSeriesOrder(this.series[index].plot);
+				if(name != newOrder[newOrder.length - 1]){
+					newOrder.splice(index, 1);
+					newOrder.push(name);
+					return this.setSeriesOrder(newOrder);	//	dojox.charting.Chart2D
+				}
+			}
+			return this;	//	dojox.charting.Chart2D
+		},
+		resize: function(width, height){
+			//	summary:
+			//		Resize the chart to the dimensions of width and height.
+			//	width: Number
+			//		The new width of the chart.
+			//	height: Number
+			//		The new height of the chart.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			var box;
+			switch(arguments.length){
+				case 0:
+					box = dojo.marginBox(this.node);
+					break;
+				case 1:
+					box = width;
+					break;
+				default:
+					box = { w: width, h: height };
+					break;
+			}
+			dojo.marginBox(this.node, box);
+			this.surface.setDimensions(box.w, box.h);
+			this.dirty = true;
+			this.coords = null;
+			return this.render();	//	dojox.charting.Chart2D
+		},
+		getGeometry: function(){
+			//	summary:
+			//		Returns a map of information about all axes in a chart and what they represent
+			//		in terms of scaling (see dojox.charting.axis2d.Default.getScaler).
+			//	returns: Object
+			//		An map of geometry objects, a one-to-one mapping of axes.
+			var ret = {};
+			df.forIn(this.axes, function(axis){
+				if(axis.initialized()){
+					ret[axis.name] = {
+						name:		axis.name,
+						vertical:	axis.vertical,
+						scaler:		axis.scaler,
+						ticks:		axis.ticks
+					};
+				}
+			});
+			return ret;	//	Object
+		},
+		setAxisWindow: function(name, scale, offset, zoom){
+			//	summary:
+			//		Zooms an axis and all dependent plots. Can be used to zoom in 1D.
+			//	name: String
+			//		The name of the axis as defined by addAxis.
+			//	scale: Number
+			//		The scale on the target axis.
+			//	offset: Number
+			//		Any offest, as measured by axis tick
+			//	zoom: Boolean|Object?
+			//		The chart zooming animation trigger.  This is null by default,
+			//		e.g. {duration: 1200}, or just set true.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			var axis = this.axes[name];
+			if(axis){
+				axis.setWindow(scale, offset);
+				dojo.forEach(this.stack,function(plot){
+					if(plot.hAxis == name || plot.vAxis == name){
+						plot.zoom = zoom;
+					}
+				})
+			}
+			return this;	//	dojox.charting.Chart2D
+		},
+		setWindow: function(sx, sy, dx, dy, zoom){
+			//	summary:
+			//		Zooms in or out any plots in two dimensions.
+			//	sx: Number
+			//		The scale for the x axis.
+			//	sy: Number
+			//		The scale for the y axis.
+			//	dx: Number
+			//		The pixel offset on the x axis.
+			//	dy: Number
+			//		The pixel offset on the y axis.
+			//	zoom: Boolean|Object?
+			//		The chart zooming animation trigger.  This is null by default,
+			//		e.g. {duration: 1200}, or just set true.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(!("plotArea" in this)){
+				this.calculateGeometry();
+			}
+			df.forIn(this.axes, function(axis){
+				var scale, offset, bounds = axis.getScaler().bounds,
+					s = bounds.span / (bounds.upper - bounds.lower);
+				if(axis.vertical){
+					scale  = sy;
+					offset = dy / s / scale;
+				}else{
+					scale  = sx;
+					offset = dx / s / scale;
+				}
+				axis.setWindow(scale, offset);
+			});
+			dojo.forEach(this.stack, function(plot){ plot.zoom = zoom; });
+			return this;	//	dojox.charting.Chart2D
+		},
+		zoomIn:	function(name, range){
+			//	summary:
+			//		Zoom the chart to a specific range on one axis.  This calls render()
+			//		directly as a convenience method.
+			//	name: String
+			//		The name of the axis as defined by addAxis.
+			//	range: Array
+			//		The end points of the zoom range, measured in axis ticks.
+			var axis = this.axes[name];
+			if(axis){
+				var scale, offset, bounds = axis.getScaler().bounds;
+				var lower = Math.min(range[0],range[1]);
+				var upper = Math.max(range[0],range[1]);
+				lower = range[0] < bounds.lower ? bounds.lower : lower;
+				upper = range[1] > bounds.upper ? bounds.upper : upper;
+				scale = (bounds.upper - bounds.lower) / (upper - lower);
+				offset = lower - bounds.lower;
+				this.setAxisWindow(name, scale, offset);
+				this.render();
+			}
+		},
+		calculateGeometry: function(){
+			//	summary:
+			//		Calculate the geometry of the chart based on the defined axes of
+			//		a chart.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(this.dirty){
+				return this.fullGeometry();
+			}
+
+			// calculate geometry
+			var dirty = dojo.filter(this.stack, function(plot){
+					return plot.dirty ||
+						(plot.hAxis && this.axes[plot.hAxis].dirty) ||
+						(plot.vAxis && this.axes[plot.vAxis].dirty);
+				}, this);
+			calculateAxes(dirty, this.plotArea);
+
+			return this;	//	dojox.charting.Chart2D
+		},
+		fullGeometry: function(){
+			//	summary:
+			//		Calculate the full geometry of the chart.  This includes passing
+			//		over all major elements of a chart (plots, axes, series, container)
+			//		in order to ensure proper rendering.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			this._makeDirty();
+
+			// clear old values
+			dojo.forEach(this.stack, clear);
+
+			// rebuild new connections, and add defaults
+
+			// set up a theme
+			if(!this.theme){
+				this.setTheme(new dojox.charting.Theme(dojox.charting._def));
+			}
+
+			// assign series
+			dojo.forEach(this.series, function(run){
+				if(!(run.plot in this.plots)){
+					var plot = new dc.plot2d.Default(this, {});
+					plot.name = run.plot;
+					this.plots[run.plot] = this.stack.length;
+					this.stack.push(plot);
+				}
+				this.stack[this.plots[run.plot]].addSeries(run);
+			}, this);
+			// assign axes
+			dojo.forEach(this.stack, function(plot){
+				if(plot.hAxis){
+					plot.setAxis(this.axes[plot.hAxis]);
+				}
+				if(plot.vAxis){
+					plot.setAxis(this.axes[plot.vAxis]);
+				}
+			}, this);
+
+			// calculate geometry
+
+			// 1st pass
+			var dim = this.dim = this.surface.getDimensions();
+			dim.width  = dojox.gfx.normalizedLength(dim.width);
+			dim.height = dojox.gfx.normalizedLength(dim.height);
+			df.forIn(this.axes, clear);
+			calculateAxes(this.stack, dim);
+
+			// assumption: we don't have stacked axes yet
+			var offsets = this.offsets = { l: 0, r: 0, t: 0, b: 0 };
+			df.forIn(this.axes, function(axis){
+				df.forIn(axis.getOffsets(), function(o, i){ offsets[i] += o; });
+			});
+			// add margins
+			df.forIn(this.margins, function(o, i){ offsets[i] += o; });
+
+			// 2nd pass with realistic dimensions
+			this.plotArea = {
+				width: dim.width - offsets.l - offsets.r,
+				height: dim.height - offsets.t - offsets.b
+			};
+			df.forIn(this.axes, clear);
+			calculateAxes(this.stack, this.plotArea);
+
+			return this;	//	dojox.charting.Chart2D
+		},
+		render: function(){
+			//	summary:
+			//		Render the chart according to the current information defined.  This should
+			//		be the last call made when defining/creating a chart, or if data within the
+			//		chart has been changed.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(this.theme){
+				this.theme.clear();
+			}
+
+			if(this.dirty){
+				return this.fullRender();
+			}
+
+			this.calculateGeometry();
+
+			// go over the stack backwards
+			df.forEachRev(this.stack, function(plot){ plot.render(this.dim, this.offsets); }, this);
+
+			// go over axes
+			df.forIn(this.axes, function(axis){ axis.render(this.dim, this.offsets); }, this);
+
+			this._makeClean();
+
+			// BEGIN FOR HTML CANVAS
+			if(this.surface.render){ this.surface.render(); };
+			// END FOR HTML CANVAS
+
+			return this;	//	dojox.charting.Chart2D
+		},
+		fullRender: function(){
+			//	summary:
+			//		Force a full rendering of the chart, including full resets on the chart itself.
+			//		You should not call this method directly unless absolutely necessary.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+
+			// calculate geometry
+			this.fullGeometry();
+			var offsets = this.offsets, dim = this.dim;
+
+			// get required colors
+			//var requiredColors = df.foldl(this.stack, "z + plot.getRequiredColors()", 0);
+			//this.theme.defineColors({num: requiredColors, cache: false});
+
+			// clear old shapes
+			dojo.forEach(this.series, purge);
+			df.forIn(this.axes, purge);
+			dojo.forEach(this.stack,  purge);
+			this.surface.clear();
+
+			// generate shapes
+
+			// draw a plot background
+			var t = this.theme,
+				fill   = t.plotarea && t.plotarea.fill,
+				stroke = t.plotarea && t.plotarea.stroke;
+			if(fill){
+				this.surface.createRect({
+					x: offsets.l - 1, y: offsets.t - 1,
+					width:  dim.width  - offsets.l - offsets.r + 2,
+					height: dim.height - offsets.t - offsets.b + 2
+				}).setFill(fill);
+			}
+			if(stroke){
+				this.surface.createRect({
+					x: offsets.l, y: offsets.t,
+					width:  dim.width  - offsets.l - offsets.r + 1,
+					height: dim.height - offsets.t - offsets.b + 1
+				}).setStroke(stroke);
+			}
+
+			// go over the stack backwards
+			df.foldr(this.stack, function(z, plot){ return plot.render(dim, offsets), 0; }, 0);
+
+			// pseudo-clipping: matting
+			fill   = this.fill   !== undefined ? this.fill   : (t.chart && t.chart.fill);
+			stroke = this.stroke !== undefined ? this.stroke : (t.chart && t.chart.stroke);
+
+			//	TRT: support for "inherit" as a named value in a theme.
+			if(fill == "inherit"){
+				//	find the background color of the nearest ancestor node, and use that explicitly.
+				var node = this.node, fill = new dojo.Color(dojo.style(node, "backgroundColor"));
+				while(fill.a==0 && node!=document.documentElement){
+					fill = new dojo.Color(dojo.style(node, "backgroundColor"));
+					node = node.parentNode;
+				}
+			}
+
+			if(fill){
+				if(offsets.l){	// left
+					this.surface.createRect({
+						width:  offsets.l,
+						height: dim.height + 1
+					}).setFill(fill);
+				}
+				if(offsets.r){	// right
+					this.surface.createRect({
+						x: dim.width - offsets.r,
+						width:  offsets.r + 1,
+						height: dim.height + 2
+					}).setFill(fill);
+				}
+				if(offsets.t){	// top
+					this.surface.createRect({
+						width:  dim.width + 1,
+						height: offsets.t
+					}).setFill(fill);
+				}
+				if(offsets.b){	// bottom
+					this.surface.createRect({
+						y: dim.height - offsets.b,
+						width:  dim.width + 1,
+						height: offsets.b + 2
+					}).setFill(fill);
+				}
+			}
+			if(stroke){
+				this.surface.createRect({
+					width:  dim.width - 1,
+					height: dim.height - 1
+				}).setStroke(stroke);
+			}
+
+			// go over axes
+			df.forIn(this.axes, function(axis){ axis.render(dim, offsets); });
+
+			this._makeClean();
+
+			// BEGIN FOR HTML CANVAS
+			if(this.surface.render){ this.surface.render(); };
+			// END FOR HTML CANVAS
+
+			return this;	//	dojox.charting.Chart2D
+		},
+		delayedRender: function(){
+			//	summary:
+			//		Delayed render, which is used to collect multiple updates
+			//		within a delayInMs time window.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+
+			if(!this._delayedRenderHandle){
+				this._delayedRenderHandle = setTimeout(
+					dojo.hitch(this, function(){
+						clearTimeout(this._delayedRenderHandle);
+						this._delayedRenderHandle = null;
+						this.render();
+					}),
+					this.delayInMs
+				);
+			}
+
+			return this;	//	dojox.charting.Chart2D
+		},
+		connectToPlot: function(name, object, method){
+			//	summary:
+			//		A convenience method to connect a function to a plot.
+			//	name: String
+			//		The name of the plot as defined by addPlot.
+			//	object: Object
+			//		The object to be connected.
+			//	method: Function
+			//		The function to be executed.
+			//	returns: Array
+			//		A handle to the connection, as defined by dojo.connect (see dojo.connect).
+			return name in this.plots ? this.stack[this.plots[name]].connect(object, method) : null;	//	Array
+		},
+		fireEvent: function(seriesName, eventName, index){
+			//	summary:
+			//		Fires a synthetic event for a series item.
+			//	seriesName: String:
+			//		Series name.
+			//	eventName: String:
+			//		Event name to simulate: onmouseover, onmouseout, onclick.
+			//	index: Number:
+			//		Valid data value index for the event.
+			//	returns: dojox.charting.Chart2D
+			//		A reference to the current chart for functional chaining.
+			if(seriesName in this.runs){
+				var plotName = this.series[this.runs[seriesName]].plot;
+				if(plotName in this.plots){
+					var plot = this.stack[this.plots[plotName]];
+					if(plot){
+						plot.fireEvent(seriesName, eventName, index);
+					}
+				}
+			}
+			return this;	//	dojox.charting.Chart2D
+		},
+		_makeClean: function(){
+			// reset dirty flags
+			dojo.forEach(this.axes,   makeClean);
+			dojo.forEach(this.stack,  makeClean);
+			dojo.forEach(this.series, makeClean);
+			this.dirty = false;
+		},
+		_makeDirty: function(){
+			// reset dirty flags
+			dojo.forEach(this.axes,   makeDirty);
+			dojo.forEach(this.stack,  makeDirty);
+			dojo.forEach(this.series, makeDirty);
+			this.dirty = true;
+		},
+		_invalidateDependentPlots: function(plotName, /* Boolean */ verticalAxis){
+			if(plotName in this.plots){
+				var plot = this.stack[this.plots[plotName]], axis,
+					axisName = verticalAxis ? "vAxis" : "hAxis";
+				if(plot[axisName]){
+					axis = this.axes[plot[axisName]];
+					if(axis && axis.dependOnData()){
+						axis.dirty = true;
+						// find all plots and mark them dirty
+						dojo.forEach(this.stack, function(p){
+							if(p[axisName] && p[axisName] == plot[axisName]){
+								p.dirty = true;
+							}
+						});
+					}
+				}else{
+					plot.dirty = true;
+				}
+			}
+		}
+	});
+
+	function hSection(stats){
+		return {min: stats.hmin, max: stats.hmax};
+	}
+
+	function vSection(stats){
+		return {min: stats.vmin, max: stats.vmax};
+	}
+
+	function hReplace(stats, h){
+		stats.hmin = h.min;
+		stats.hmax = h.max;
+	}
+
+	function vReplace(stats, v){
+		stats.vmin = v.min;
+		stats.vmax = v.max;
+	}
+
+	function combineStats(target, source){
+		if(target && source){
+			target.min = Math.min(target.min, source.min);
+			target.max = Math.max(target.max, source.max);
+		}
+		return target || source;
+	}
+
+	function calculateAxes(stack, plotArea){
+		var plots = {}, axes = {};
+		dojo.forEach(stack, function(plot){
+			var stats = plots[plot.name] = plot.getSeriesStats();
+			if(plot.hAxis){
+				axes[plot.hAxis] = combineStats(axes[plot.hAxis], hSection(stats));
+			}
+			if(plot.vAxis){
+				axes[plot.vAxis] = combineStats(axes[plot.vAxis], vSection(stats));
+			}
+		});
+		dojo.forEach(stack, function(plot){
+			var stats = plots[plot.name];
+			if(plot.hAxis){
+				hReplace(stats, axes[plot.hAxis]);
+			}
+			if(plot.vAxis){
+				vReplace(stats, axes[plot.vAxis]);
+			}
+			plot.initializeScalers(plotArea, stats);
+		});
+	}
 })();
-}
diff --git a/dojox/charting/Chart3D.js b/dojox/charting/Chart3D.js
index ecd9137..1c26ab4 100644
--- a/dojox/charting/Chart3D.js
+++ b/dojox/charting/Chart3D.js
@@ -1,73 +1,82 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.Chart3D"]){
-dojo._hasResource["dojox.charting.Chart3D"]=true;
 dojo.provide("dojox.charting.Chart3D");
+
 dojo.require("dojox.gfx3d");
+
 (function(){
-var _1={x:0,y:0,z:1},v=dojox.gfx3d.vector,n=dojox.gfx.normalizedLength;
-dojo.declare("dojox.charting.Chart3D",null,{constructor:function(_2,_3,_4,_5){
-this.node=dojo.byId(_2);
-this.surface=dojox.gfx.createSurface(this.node,n(this.node.style.width),n(this.node.style.height));
-this.view=this.surface.createViewport();
-this.view.setLights(_3.lights,_3.ambient,_3.specular);
-this.view.setCameraTransform(_4);
-this.theme=_5;
-this.walls=[];
-this.plots=[];
-},generate:function(){
-return this._generateWalls()._generatePlots();
-},invalidate:function(){
-this.view.invalidate();
-return this;
-},render:function(){
-this.view.render();
-return this;
-},addPlot:function(_6){
-return this._add(this.plots,_6);
-},removePlot:function(_7){
-return this._remove(this.plots,_7);
-},addWall:function(_8){
-return this._add(this.walls,_8);
-},removeWall:function(_9){
-return this._remove(this.walls,_9);
-},_add:function(_a,_b){
-if(!dojo.some(_a,function(i){
-return i==_b;
-})){
-_a.push(_b);
-this.view.invalidate();
-}
-return this;
-},_remove:function(_c,_d){
-var a=dojo.filter(_c,function(i){
-return i!=_d;
-});
-return a.length<_c.length?(_c=a,this.invalidate()):this;
-},_generateWalls:function(){
-for(var i=0;i<this.walls.length;++i){
-if(v.dotProduct(_1,this.walls[i].normal)>0){
-this.walls[i].generate(this);
-}
-}
-return this;
-},_generatePlots:function(){
-var _e=0,m=dojox.gfx3d.matrix,i=0;
-for(;i<this.plots.length;++i){
-_e+=this.plots[i].getDepth();
-}
-for(--i;i>=0;--i){
-var _f=this.view.createScene();
-_f.setTransform(m.translate(0,0,-_e));
-this.plots[i].generate(this,_f);
-_e-=this.plots[i].getDepth();
-}
-return this;
-}});
+	var observerVector = {x: 0, y: 0, z: 1}, v = dojox.gfx3d.vector, n = dojox.gfx.normalizedLength;
+
+	dojo.declare("dojox.charting.Chart3D", null, {
+		constructor: function(node, lights, camera, theme){
+			// setup a view
+			this.node = dojo.byId(node);
+			this.surface = dojox.gfx.createSurface(this.node, n(this.node.style.width), n(this.node.style.height));
+			this.view = this.surface.createViewport();
+			this.view.setLights(lights.lights, lights.ambient, lights.specular);
+			this.view.setCameraTransform(camera);
+			this.theme = theme;
+			
+			// initialize internal variables
+			this.walls = [];
+			this.plots = [];
+		},
+		
+		// public API
+		generate: function(){
+			return this._generateWalls()._generatePlots();
+		},
+		invalidate: function(){
+			this.view.invalidate();
+			return this;
+		},
+		render: function(){
+			this.view.render();
+			return this;
+		},
+		addPlot: function(plot){
+			return this._add(this.plots, plot);
+		},
+		removePlot: function(plot){
+			return this._remove(this.plots, plot);
+		},
+		addWall: function(wall){
+			return this._add(this.walls, wall);
+		},
+		removeWall: function(wall){
+			return this._remove(this.walls, wall);
+		},
+		
+		// internal API
+		_add: function(array, item){
+			if(!dojo.some(array, function(i){ return i == item; })){
+				array.push(item);
+				this.view.invalidate();
+			}
+			return this;
+		},
+		_remove: function(array, item){
+			var a = dojo.filter(array, function(i){ return i != item; });
+			return a.length < array.length ? (array = a, this.invalidate()) : this;
+		},
+		_generateWalls: function(){
+			for(var i = 0; i < this.walls.length; ++i){
+				if(v.dotProduct(observerVector, this.walls[i].normal) > 0){
+					this.walls[i].generate(this);
+				}
+			}
+			return this;
+		},
+		_generatePlots: function(){
+			var depth = 0, m = dojox.gfx3d.matrix, i = 0;
+			for(; i < this.plots.length; ++i){
+				depth += this.plots[i].getDepth();
+			}
+			for(--i; i >= 0; --i){
+				var scene = this.view.createScene();
+				scene.setTransform(m.translate(0, 0, -depth));
+				this.plots[i].generate(this, scene);
+				depth -= this.plots[i].getDepth();
+			}
+			return this;
+		}
+	});
 })();
-}
diff --git a/dojox/charting/DataChart.js b/dojox/charting/DataChart.js
index 5dd0bf3..1b357d2 100644
--- a/dojox/charting/DataChart.js
+++ b/dojox/charting/DataChart.js
@@ -1,224 +1,517 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.DataChart"]){
-dojo._hasResource["dojox.charting.DataChart"]=true;
 dojo.provide("dojox.charting.DataChart");
 dojo.require("dojox.charting.Chart2D");
 dojo.require("dojox.charting.themes.PlotKit.blue");
 dojo.experimental("dojox.charting.DataChart");
+
 (function(){
-var _1={vertical:true,min:0,max:10,majorTickStep:5,minorTickStep:1,natural:false,stroke:"black",majorTick:{stroke:"black",length:8},minorTick:{stroke:"gray",length:2},majorLabels:true};
-var _2={natural:true,majorLabels:true,includeZero:false,majorTickStep:1,majorTick:{stroke:"black",length:8},fixUpper:"major",stroke:"black",htmlLabels:true,from:1};
-var _3={markers:true,tension:2,gap:2};
-dojo.declare("dojox.charting.DataChart",[dojox.charting.Chart2D],{scroll:true,comparative:false,query:"*",queryOptions:"",fieldName:"value",chartTheme:dojox.charting.themes.PlotKit.blue,displayRange:0,stretchToFit:true,minWidth:200,minHeight:100,showing:true,label:"name",constructor:function(_4,_5){
-this.domNode=dojo.byId(_4);
-dojo.mixin(this,_5);
-this.xaxis=dojo.mixin(dojo.mixin({},_2),_5.xaxis);
-if(this.xaxis.labelFunc=="seriesLabels"){
-this.xaxis.labelFunc=dojo.hitch(this,"seriesLabels");
-}
-this.yaxis=dojo.mixin(dojo.mixin({},_1),_5.yaxis);
-if(this.yaxis.labelFunc=="seriesLabels"){
-this.yaxis.labelFunc=dojo.hitch(this,"seriesLabels");
-}
-this.convertLabels(this.yaxis);
-this.convertLabels(this.xaxis);
-this.onSetItems={};
-this.onSetInterval=0;
-this.dataLength=0;
-this.seriesData={};
-this.seriesDataBk={};
-this.firstRun=true;
-this.dataOffset=0;
-this.chartTheme.plotarea.stroke={color:"gray",width:3};
-this.setTheme(this.chartTheme);
-if(this.displayRange){
-this.stretchToFit=false;
-}
-if(!this.stretchToFit){
-this.xaxis.to=this.displayRange;
-}
-this.addAxis("x",this.xaxis);
-this.addAxis("y",this.yaxis);
-_3.type=_5.type||"Markers";
-this.addPlot("default",dojo.mixin(_3,_5.chartPlot));
-this.addPlot("grid",dojo.mixin(_5.grid||{},{type:"Grid",hMinorLines:true}));
-if(this.showing){
-this.render();
-}
-if(_5.store){
-this.setStore(_5.store,_5.query,_5.fieldName,_5.queryOptions);
-}
-},setStore:function(_6,_7,_8,_9){
-this.firstRun=true;
-this.store=_6||this.store;
-this.query=_7||this.query;
-this.fieldName=_8||this.fieldName;
-this.label=this.store.getLabelAttributes();
-this.queryOptions=_9||_9;
-dojo.connect(this.store,"onSet",this,"onSet");
-dojo.connect(this.store,"onError",this,"onError");
-this.fetch();
-},show:function(){
-if(!this.showing){
-dojo.style(this.domNode,"display","");
-this.showing=true;
-this.render();
-}
-},hide:function(){
-if(this.showing){
-dojo.style(this.domNode,"display","none");
-this.showing=false;
-}
-},onSet:function(_a){
-var nm=this.getProperty(_a,this.label);
-if(nm in this.runs||this.comparative){
-clearTimeout(this.onSetInterval);
-if(!this.onSetItems[nm]){
-this.onSetItems[nm]=_a;
-}
-this.onSetInterval=setTimeout(dojo.hitch(this,function(){
-clearTimeout(this.onSetInterval);
-var _b=[];
-for(var nm in this.onSetItems){
-_b.push(this.onSetItems[nm]);
-}
-this.onData(_b);
-this.onSetItems={};
-}),200);
-}
-},onError:function(_c){
-console.error("DataChart Error:",_c);
-},onDataReceived:function(_d){
-},getProperty:function(_e,_f){
-if(_f==this.label){
-return this.store.getLabel(_e);
-}
-if(_f=="id"){
-return this.store.getIdentity(_e);
-}
-var _10=this.store.getValues(_e,_f);
-if(_10.length<2){
-_10=this.store.getValue(_e,_f);
-}
-return _10;
-},onData:function(_11){
-if(!_11||!_11.length){
-return;
-}
-if(this.items&&this.items.length!=_11.length){
-dojo.forEach(_11,function(m){
-var id=this.getProperty(m,"id");
-dojo.forEach(this.items,function(m2,i){
-if(this.getProperty(m2,"id")==id){
-this.items[i]=m2;
-}
-},this);
-},this);
-_11=this.items;
-}
-if(this.stretchToFit){
-this.displayRange=_11.length;
-}
-this.onDataReceived(_11);
-this.items=_11;
-if(this.comparative){
-var nm="default";
-this.seriesData[nm]=[];
-this.seriesDataBk[nm]=[];
-dojo.forEach(_11,function(m,i){
-var _12=this.getProperty(m,this.fieldName);
-this.seriesData[nm].push(_12);
-},this);
-}else{
-dojo.forEach(_11,function(m,i){
-var nm=this.store.getLabel(m);
-if(!this.seriesData[nm]){
-this.seriesData[nm]=[];
-this.seriesDataBk[nm]=[];
-}
-var _13=this.getProperty(m,this.fieldName);
-if(dojo.isArray(_13)){
-this.seriesData[nm]=_13;
-}else{
-if(!this.scroll){
-var ar=dojo.map(new Array(i+1),function(){
-return 0;
-});
-ar.push(Number(_13));
-this.seriesData[nm]=ar;
-}else{
-if(this.seriesDataBk[nm].length>this.seriesData[nm].length){
-this.seriesData[nm]=this.seriesDataBk[nm];
-}
-this.seriesData[nm].push(Number(_13));
-}
-this.seriesDataBk[nm].push(Number(_13));
-}
-},this);
-}
-var _14;
-if(this.firstRun){
-this.firstRun=false;
-for(nm in this.seriesData){
-this.addSeries(nm,this.seriesData[nm]);
-_14=this.seriesData[nm];
-}
-}else{
-for(nm in this.seriesData){
-_14=this.seriesData[nm];
-if(this.scroll&&_14.length>this.displayRange){
-this.dataOffset=_14.length-this.displayRange-1;
-_14=_14.slice(_14.length-this.displayRange,_14.length);
-}
-this.updateSeries(nm,_14);
-}
-}
-this.dataLength=_14.length;
-if(this.showing){
-this.render();
-}
-},fetch:function(){
-if(!this.store){
-return;
-}
-this.store.fetch({query:this.query,queryOptions:this.queryOptions,start:this.start,count:this.count,sort:this.sort,onComplete:dojo.hitch(this,function(_15){
-setTimeout(dojo.hitch(this,function(){
-this.onData(_15);
-}),0);
-}),onError:dojo.hitch(this,"onError")});
-},convertLabels:function(_16){
-if(!_16.labels||dojo.isObject(_16.labels[0])){
-return null;
-}
-_16.labels=dojo.map(_16.labels,function(ele,i){
-return {value:i,text:ele};
-});
-return null;
-},seriesLabels:function(val){
-val--;
-if(this.series.length<1||(!this.comparative&&val>this.series.length)){
-return "-";
-}
-if(this.comparative){
-return this.store.getLabel(this.items[val]);
-}else{
-for(var i=0;i<this.series.length;i++){
-if(this.series[i].data[val]>0){
-return this.series[i].name;
-}
-}
-}
-return "-";
-},resizeChart:function(dim){
-var w=Math.max(dim.w,this.minWidth);
-var h=Math.max(dim.h,this.minHeight);
-this.resize(w,h);
-}});
-})();
-}
+
+	// Defaults for axes
+	//	to be mixed in with xaxis/yaxis custom properties
+	// see dojox.charting.axis2d.Default for details.
+	var _yaxis = {
+		vertical: true,
+		min: 0,
+		max: 10,
+		majorTickStep: 5,
+		minorTickStep: 1,
+		natural:false,
+		stroke: "black",
+		majorTick: {stroke: "black", length: 8},
+		minorTick: {stroke: "gray", length: 2},
+		majorLabels:true
+	};
+
+	var _xaxis = {
+		natural: true, 		// true - no fractions
+		majorLabels: true, 	//show labels on major ticks
+		includeZero: false, // do not change on upating chart
+		majorTickStep: 1,
+		majorTick: {stroke: "black", length: 8},
+		fixUpper:"major",
+		stroke: "black",
+		htmlLabels: true,
+		from:1
+	};
+
+	// default for chart elements
+	var chartPlot = {
+		markers: true,
+		tension:2,
+		gap:2
+	};
+
+	dojo.declare("dojox.charting.DataChart", [dojox.charting.Chart2D], {
+		//	summary:
+		//		DataChart
+		//		Extension to the 2D chart that connects to a data store in
+		//		a simple manner. Convenience methods have been added for
+		//		connecting store item labels to the chart labels.
+		//
+		//	description:
+		//		This code should be considered very experimental and the APIs subject
+		//		to change. This is currently an alpha version and will need some testing
+		//		and review.
+		//
+		//		The main reason for this extension is to create animated charts, generally
+		//		available with scroll=true, and a property field that gets continually updated.
+		//		The previous property settings are kept in memory and displayed until scrolled
+		//		off the chart.
+		//
+		//		Although great effort was made to maintain the integrity of the current
+		//		charting APIs, some things have been added or modified in order to get
+		//		the store to connect and also to get the data to scroll/animate.
+		//		"displayRange" in particular is used to force the xaxis to a specific
+		//		size and keep the chart from stretching or squashing to fit the data.
+		//
+		//		Currently, plot lines can only be set at initialization. Setting
+		//		a new store query will have no effect (although using setStore
+		//		may work but its untested).
+		//
+		//	example:
+		//
+		//	|	var chart = new dojox.charting.DataChart("myNode", {
+		//	|		displayRange:8,
+		//	|		store:dataStore,
+		//	|		query:{symbol:"*"},
+		//	|		fieldName:"price"
+		//	|		type: dojox.charting.plot2d.Columns
+		//	|	});
+		//
+		//	properties:
+		//
+		//	scroll: Boolean
+		//		Whether live data updates and changes display, like columns moving
+		//		up and down, or whether it scrolls to the left as data is added
+		scroll:true,
+		//
+		//	comparative: Boolean
+		//		If false, all items are each their own series.
+		//		If true, the items are combined into one series
+		//		so that their charted properties can be compared.
+		comparative:false,
+		//
+		//		query: String
+		//			Used for fetching items. Will vary depending upon store.
+		query: "*",
+		//
+		//		queryOptions: String
+		//			Option used for fetching items
+		queryOptions: "",
+		//
+		/*=====
+			//	start:Number
+			//		first item to fetch from store
+			//	count:Number
+			//		Total amount of items to fetch from store
+			//	sort:Object
+			//		Paramaters to sort the fetched items from store
+		=====*/
+		//
+		//		fieldName: String
+		//			The field in the store item that is getting charted
+		fieldName: "value",
+		//
+		//		chartTheme: dojox.charting.themes.*
+		//			The theme to style the chart. Defaults to PlotKit.blue.
+		chartTheme: dojox.charting.themes.PlotKit.blue,
+		//
+		//		displayRange: Number
+		//			The number of major ticks to show on the xaxis
+		displayRange:0,
+		//
+		// 		stretchToFit: Boolean
+		//			If true, chart is sized to data. If false, chart is a
+		//			fixed size. Note, is overridden by displayRange.
+		//			TODO: Stretch for the y-axis?
+		stretchToFit:true,
+		//
+		//		minWidth: Number
+		//			The the smallest the chart width can be
+		minWidth:200,
+		//
+		//		minHeight: Number
+		//			The the smallest the chart height can be
+		minHeight:100,
+		//
+		//		showing: Boolean
+		//			Whether the chart is showing (default) on
+		//			initialization or hidden.
+		showing: true,
+		//
+		//		label: String
+		//			The name field of the store item
+		//			DO NOT SET: Set from store.labelAttribute
+		label: "name",
+
+		constructor: function(node, kwArgs){
+			// summary:
+			//		Set up properties and initialize chart build.
+			//
+			//	arguments:
+			//		node: DomNode
+			//			The node to attach the chart to.
+			//		kwArgs:	Object
+			//			xaxis: Object
+			//				optional parameters for xaxis (see above)
+			//			yaxis: Object
+			//				optional parameters for yaxis (see above)
+			//			store: Object
+			//				dojo.data store (currently nly supports Persevere)
+			//			xaxis: Object
+			//				First query for store
+			//			grid: Object
+			//				Options for the grid plot
+			//			chartPlot: Object
+			//				Options for chart elements (lines, bars, etc)
+
+			this.domNode = dojo.byId(node);
+
+			dojo.mixin(this, kwArgs);
+
+			this.xaxis = dojo.mixin(dojo.mixin({}, _xaxis), kwArgs.xaxis);
+			if(this.xaxis.labelFunc == "seriesLabels"){
+				this.xaxis.labelFunc = dojo.hitch(this, "seriesLabels");
+			}
+
+			this.yaxis = dojo.mixin(dojo.mixin({}, _yaxis), kwArgs.yaxis);
+			if(this.yaxis.labelFunc == "seriesLabels"){
+				this.yaxis.labelFunc = dojo.hitch(this, "seriesLabels");
+			}
+
+			// potential event's collector
+			this._events = [];
+
+			this.convertLabels(this.yaxis);
+			this.convertLabels(this.xaxis);
+
+			this.onSetItems = {};
+			this.onSetInterval = 0;
+			this.dataLength = 0;
+			this.seriesData = {};
+			this.seriesDataBk = {};
+			this.firstRun =  true;
+
+			this.dataOffset = 0;
+
+			// FIXME: looks better with this, but it's custom
+			this.chartTheme.plotarea.stroke = {color: "gray", width: 3};
+
+			this.setTheme(this.chartTheme);
+
+			// displayRange overrides stretchToFit
+			if(this.displayRange){
+				this.stretchToFit = false;
+			}
+			if(!this.stretchToFit){
+				this.xaxis.to = this.displayRange;
+			}
+			this.addAxis("x", this.xaxis);
+			this.addAxis("y", this.yaxis);
+			chartPlot.type = kwArgs.type || "Markers"
+			this.addPlot("default", dojo.mixin(chartPlot, kwArgs.chartPlot));
+
+			this.addPlot("grid", dojo.mixin(kwArgs.grid || {}, {type: "Grid", hMinorLines: true}));
+
+			if(this.showing){
+				this.render();
+			}
+
+			if(kwArgs.store){
+				this.setStore(kwArgs.store, kwArgs.query, kwArgs.fieldName, kwArgs.queryOptions);
+			}
+		},
+
+		destroy: function(){
+			dojo.forEach(this._events, dojo.disconnect);
+			this.inherited(arguments);
+		},
+
+		setStore: function(/*Object*/store, /* ? String*/query, /* ? String*/fieldName, /* ? Object */queryOptions){
+			//	 summary:
+			//		Sets the chart store and query
+			//		then does the first fetch and
+			//		connects to subsequent changes.
+			//
+			// TODO: Not handling resetting store
+			//
+			this.firstRun = true;
+			this.store = store || this.store;
+			this.query = query || this.query;
+			this.fieldName = fieldName || this.fieldName;
+			this.label = this.store.getLabelAttributes();
+			this.queryOptions = queryOptions || queryOptions;
+
+			dojo.forEach(this._events, dojo.disconnect);
+			this._events = [
+				dojo.connect(this.store, "onSet", this, "onSet"),
+				dojo.connect(this.store, "onError", this, "onError")
+			];
+			this.fetch();
+		},
+
+		show: function(){
+			// summary:
+			//		If chart is hidden, show it
+			if(!this.showing){
+				dojo.style(this.domNode, "display", "");
+				this.showing = true;
+				this.render();
+			}
+		},
+		hide: function(){
+			// 	summary:
+			//		If chart is showing, hide it
+			//		Prevents rendering while hidden
+			if(this.showing){
+				dojo.style(this.domNode, "display", "none");
+				this.showing = false;
+			}
+		},
+
+		onSet: function(/*storeObject*/item){
+			//	summary:
+			//		Fired when a store item changes.
+			//		Collects the item calls and when
+			//		done (after 200ms), sends item
+			//		array to onData().
+			//
+			// FIXME: Using labels instead of IDs for item
+			//	identifiers here and in the chart series. This
+			//	is obviously short sighted, but currently used
+			//	for seriesLabels. Workaround for potential bugs
+			//	is to assign a label for which all items are unique.
+
+			var nm = this.getProperty(item, this.label);
+
+			// FIXME: why the check for if-in-runs?
+			if(nm in this.runs || this.comparative){
+				clearTimeout(this.onSetInterval);
+				if(!this.onSetItems[nm]){
+					this.onSetItems[nm] = item;
+				}
+				this.onSetInterval = setTimeout(dojo.hitch(this, function(){
+					clearTimeout(this.onSetInterval);
+					var items = [];
+					for(var nm in this.onSetItems){
+						items.push(this.onSetItems[nm]);
+					}
+					this.onData(items);
+					this.onSetItems = {};
+				}),200);
+			}
+		},
+
+		onError: function(/*Error*/err){
+			// stub
+			//	Fires on fetch error
+			console.error("DataChart Error:", err);
+		},
+
+		onDataReceived: function(/*Array*/items){
+			// summary:
+			//		stub. Fires after data is received but
+			//		before data is parsed and rendered
+		},
+
+		getProperty: function(/*storeObject*/item, prop){
+			// summary:
+			//		The main use of this function is to determine
+			//		between a single value and an array of values.
+			//		Other property types included for convenience.
+			//
+			if(prop==this.label){
+				return this.store.getLabel(item);
+			}
+			if(prop=="id"){
+				return this.store.getIdentity(item);
+			}
+			var value = this.store.getValues(item, prop);
+			if(value.length < 2){
+				value = this.store.getValue(item, prop);
+			}
+			return value;
+		},
+		onData: function(/*Array*/items){
+			//	summary:
+			//		Called after a completed fetch
+			//		or when store items change.
+			//		On first run, sets the chart data,
+			//		then updates chart and legends.
+			//
+			//console.log("Store:", store);console.log("items: (", items.length+")", items);console.log("Chart:", this);
+			if(!items || !items.length){ return; }
+
+			if(this.items && this.items.length != items.length){
+				dojo.forEach(items, function(m){
+					var id = this.getProperty(m, "id");
+					dojo.forEach(this.items, function(m2, i){
+						if(this.getProperty(m2, "id") == id){
+							this.items[i] = m2;
+						}
+					},this);
+				}, this);
+				items = this.items;
+			}
+			if(this.stretchToFit){
+				this.displayRange = items.length;
+			}
+			this.onDataReceived(items);
+			this.items = items;
+
+
+			if(this.comparative){
+				// all items are gathered together and used as one
+				//	series so their properties can be compared.
+				var nm = "default";
+
+				this.seriesData[nm] = [];
+				this.seriesDataBk[nm] = [];
+				dojo.forEach(items, function(m, i){
+					var field = this.getProperty(m, this.fieldName);
+					this.seriesData[nm].push(field);
+				}, this);
+
+			}else{
+
+				// each item is a seperate series.
+				dojo.forEach(items, function(m, i){
+					var nm = this.store.getLabel(m);
+					if(!this.seriesData[nm]){
+						this.seriesData[nm] = [];
+						this.seriesDataBk[nm] = [];
+					}
+
+					// the property in the item we are using
+					var field = this.getProperty(m, this.fieldName);
+					if(dojo.isArray(field)){
+						// Data is an array, so it's a snapshot, and not
+						//	live, updating data
+						//
+						this.seriesData[nm] = field;
+
+					}else{
+						if(!this.scroll){
+							// Data updates, and "moves in place". Columns and
+							//	line markers go up and down
+							//
+							// create empty chart elements by starting an array
+							//	with zeros until we reach our relevant data
+							var ar = dojo.map(new Array(i+1), function(){ return 0; });
+							ar.push(Number(field));
+							this.seriesData[nm] = ar;
+
+						}else{
+							// Data updates and scrolls to the left
+							if(this.seriesDataBk[nm].length > this.seriesData[nm].length){
+								this.seriesData[nm] = this.seriesDataBk[nm];
+							}
+							// Collecting and storing series data. The items come in
+							//	only one at a time, but we need to display historical
+							//	data, so it is kept in memory.
+							this.seriesData[nm].push(Number(field));
+						}
+						this.seriesDataBk[nm].push(Number(field));
+					}
+				}, this);
+			}
+
+			// displayData is the segment of the data array that is within
+			// the chart boundaries
+			var displayData;
+			if(this.firstRun){
+				// First time around we need to add the series (chart lines)
+				//	to the chart.
+				this.firstRun = false;
+				for(nm in this.seriesData){
+					this.addSeries(nm, this.seriesData[nm]);
+					displayData = this.seriesData[nm];
+				}
+
+			}else{
+
+				// update existing series
+				for(nm in this.seriesData){
+					displayData = this.seriesData[nm];
+
+					if(this.scroll && displayData.length > this.displayRange){
+						// chart lines have gone beyond the right boundary.
+						this.dataOffset = displayData.length-this.displayRange - 1;
+						displayData = displayData.slice(displayData.length-this.displayRange, displayData.length);
+					}
+					this.updateSeries(nm, displayData);
+				}
+			}
+			this.dataLength = displayData.length;
+
+			if(this.showing){
+				this.render();
+			}
+
+		},
+
+		fetch: function(){
+			// summary:
+			//		Fetches initial data. Subsequent changes
+			//		are received via onSet in data store.
+			//
+			if(!this.store){ return; }
+			this.store.fetch({query:this.query, queryOptions:this.queryOptions, start:this.start, count:this.count, sort:this.sort,
+				onComplete:dojo.hitch(this, function(data){
+					setTimeout(dojo.hitch(this, function(){
+						this.onData(data)
+					}),0);
+				}),
+				onError:dojo.hitch(this, "onError")
+			});
+		},
+
+		convertLabels: function(axis){
+			// summary:
+			//		Convenience method to convert a label array of strings
+			//		into an array of objects
+			//
+			if(!axis.labels || dojo.isObject(axis.labels[0])){ return null; }
+
+			axis.labels = dojo.map(axis.labels, function(ele, i){
+				return {value:i, text:ele};
+			});
+			return null; // null
+		},
+
+		seriesLabels: function(/*Number*/val){
+			// summary:
+			//		Convenience method that sets series labels based on item labels.
+			val--;
+			if(this.series.length<1 || (!this.comparative && val>this.series.length)){ return "-"; }
+			if(this.comparative){
+				return this.store.getLabel(this.items[val]);// String
+
+			}else{
+				// FIXME:
+				// Here we are setting the label base on if there is data in the array slot.
+				//	A typical series may look like: [0,0,3.1,0,0,0] which mean the data is populated in the
+				//	3rd row or column. This works well and keeps the labels aligned but has a side effect
+				//	of not showing the label is the data is zero. Work around is to not go lower than
+				//	0.01 or something.
+				for(var i=0;i<this.series.length; i++){
+					if(this.series[i].data[val]>0){
+						return this.series[i].name; // String
+					}
+				}
+			}
+			return "-"; // String
+
+		},
+
+		resizeChart: function(/*Object*/dim){
+			//	summary:
+			//		Call this function to change the chart size.
+			//		Can be connected to a layout widget that calls
+			//		resize.
+			//
+			var w = Math.max(dim.w, this.minWidth);
+			var h = Math.max(dim.h, this.minHeight);
+			this.resize(w, h);
+		}
+	});
+})();
\ No newline at end of file
diff --git a/dojox/charting/DataSeries.js b/dojox/charting/DataSeries.js
new file mode 100644
index 0000000..c8ef156
--- /dev/null
+++ b/dojox/charting/DataSeries.js
@@ -0,0 +1,183 @@
+dojo.provide("dojox.charting.DataSeries");
+
+dojo.require("dojox.lang.functional");
+
+dojo.declare("dojox.charting.DataSeries", null, {
+	constructor: function(store, kwArgs, value){
+		//	summary:
+		//		Series adapter for dojo.data stores.
+		//	store: Object:
+		//		A dojo.data store object.
+		//	kwArgs: Object:
+		//		A store-specific keyword parameters used for fetching items.
+		//		See dojo.data.api.Read.fetch().
+		//	value: Function|Object|String|Null:
+		//		Function, which takes a store, and an object handle, and
+		//		produces an output possibly inspecting the store's item. Or
+		//		a dictionary object, which tells what names to extract from
+		//		an object and how to map them to an output. Or a string, which
+		//		is a numeric field name to use for plotting. If undefined, null
+		//		or empty string (the default), "value" field is extracted.
+		this.store = store;
+		this.kwArgs = kwArgs;
+
+		if(value){
+			if(dojo.isFunction(value)){
+				this.value = value;
+			}else if(dojo.isObject(value)){
+				this.value = dojo.hitch(this, "_dictValue",
+					dojox.lang.functional.keys(value), value);
+			}else{
+				this.value = dojo.hitch(this, "_fieldValue", value);
+			}
+		}else{
+			this.value = dojo.hitch(this, "_defaultValue");
+		}
+
+		this.data = [];
+
+		this._events = [];
+
+		if(this.store.getFeatures()["dojo.data.api.Notification"]){
+			this._events.push(
+				dojo.connect(this.store, "onNew", this, "_onStoreNew"),
+				dojo.connect(this.store, "onDelete", this, "_onStoreDelete"),
+				dojo.connect(this.store, "onSet", this, "_onStoreSet")
+			);
+		}
+
+		this.fetch();
+	},
+
+	destroy: function(){
+		//	summary:
+		//		Clean up before GC.
+		dojo.forEach(this._events, dojo.disconnect);
+	},
+
+	setSeriesObject: function(series){
+		//	summary:
+		//		Sets a dojox.charting.Series object we will be working with.
+		//	series: dojox.charting.Series:
+		//		Our interface to the chart.
+		this.series = series;
+	},
+
+	// value transformers
+
+	_dictValue: function(keys, dict, store, item){
+		var o = {};
+		dojo.forEach(keys, function(key){
+			o[key] = store.getValue(item, dict[key]);
+		});
+		return o;
+	},
+
+	_fieldValue: function(field, store, item){
+		return store.getValue(item, field);
+	},
+
+	_defaultValue: function(store, item){
+		return store.getValue(item, "value");
+	},
+
+	// store fetch loop
+
+	fetch: function(){
+		//	summary:
+		//		Fetches data from the store and updates a chart.
+		if(!this._inFlight){
+			this._inFlight = true;
+			var kwArgs = dojo.delegate(this.kwArgs);
+			kwArgs.onComplete = dojo.hitch(this, "_onFetchComplete");
+			kwArgs.onError = dojo.hitch(this, "onFetchError");
+			this.store.fetch(kwArgs);
+		}
+	},
+
+	_onFetchComplete: function(items, request){
+		this.items = items;
+		this._buildItemMap();
+		this.data = dojo.map(this.items, function(item){
+			return this.value(this.store, item);
+		}, this);
+		this._pushDataChanges();
+		this._inFlight = false;
+	},
+
+	onFetchError: function(errorData, request){
+		//	summary:
+		//		As stub to process fetch errors. Provide so user can attach to
+		//		it with dojo.connect(). See dojo.data.api.Read fetch() for
+		//		details: onError property.
+		this._inFlight = false;
+	},
+
+	_buildItemMap: function(){
+		if(this.store.getFeatures()["dojo.data.api.Identity"]){
+			var itemMap = {};
+			dojo.forEach(this.items, function(item, index){
+				itemMap[this.store.getIdentity(item)] = index;
+			}, this);
+			this.itemMap = itemMap;
+		}
+	},
+
+	_pushDataChanges: function(){
+		if(this.series){
+			this.series.chart.updateSeries(this.series.name, this);
+			this.series.chart.delayedRender();
+		}
+	},
+
+	// store notification handlers
+
+	_onStoreNew: function(){
+		// the only thing we can do is to re-fetch items
+		this.fetch();
+	},
+
+	_onStoreDelete: function(item){
+		// we cannot do anything with deleted item, the only way is to compare
+		// items for equality
+		if(this.items){
+			var flag = dojo.some(this.items, function(it, index){
+				if(it === item){
+					this.items.splice(index, 1);
+					this._buildItemMap();
+					this.data.splice(index, 1);
+					return true;
+				}
+				return false;
+			}, this);
+			if(flag){
+				this._pushDataChanges();
+			}
+		}
+	},
+
+	_onStoreSet: function(item){
+		if(this.itemMap){
+			// we can use our handy item map, if the store supports Identity
+			var id = this.store.getIdentity(item), index = this.itemMap[id];
+			if(typeof index == "number"){
+				this.data[index] = this.value(this.store, this.items[index]);
+				this._pushDataChanges();
+			}
+		}else{
+			// otherwise we have to rely on item's equality
+			if(this.items){
+				var flag = dojo.some(this.items, function(it, index){
+					if(it === item){
+						this.data[index] = this.value(this.store, it);
+						return true;
+					}
+					return false;
+				}, this);
+				if(flag){
+					this._pushDataChanges();
+				}
+			}
+		}
+	}
+});
diff --git a/dojox/charting/Element.js b/dojox/charting/Element.js
index 70268f3..b640b61 100644
--- a/dojox/charting/Element.js
+++ b/dojox/charting/Element.js
@@ -1,53 +1,245 @@
-/*
-	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
-*/
+dojo.provide("dojox.charting.Element");
 
+dojo.require("dojox.gfx");
 
-if(!dojo._hasResource["dojox.charting.Element"]){
-dojo._hasResource["dojox.charting.Element"]=true;
-dojo.provide("dojox.charting.Element");
-dojo.declare("dojox.charting.Element",null,{constructor:function(_1){
-this.chart=_1;
-this.group=null;
-this.htmlElements=[];
-this.dirty=true;
-},createGroup:function(_2){
-if(!_2){
-_2=this.chart.surface;
-}
-if(!this.group){
-this.group=_2.createGroup();
-}
-return this;
-},purgeGroup:function(){
-this.destroyHtmlElements();
-if(this.group){
-this.group.clear();
-this.group.removeShape();
-this.group=null;
-}
-this.dirty=true;
-return this;
-},cleanGroup:function(_3){
-this.destroyHtmlElements();
-if(!_3){
-_3=this.chart.surface;
-}
-if(this.group){
-this.group.clear();
-}else{
-this.group=_3.createGroup();
-}
-this.dirty=true;
-return this;
-},destroyHtmlElements:function(){
-if(this.htmlElements.length){
-dojo.forEach(this.htmlElements,dojo.destroy);
-this.htmlElements=[];
-}
-},destroy:function(){
-this.purgeGroup();
-}});
-}
+dojo.declare("dojox.charting.Element", null, {
+	//	summary:
+	//		A base class that is used to build other elements of a chart, such as
+	//		a series.
+	//	chart: dojox.charting.Chart2D
+	//		The parent chart for this element.
+	//	group: dojox.gfx.Group
+	//		The visual GFX group representing this element.
+	//	htmlElement: Array
+	//		Any DOMNodes used as a part of this element (such as HTML-based labels).
+	//	dirty: Boolean
+	//		A flag indicating whether or not this element needs to be rendered.
+
+	chart: null,
+	group: null,
+	htmlElements: null,
+	dirty: true,
+
+	constructor: function(chart){
+		//	summary:
+		//		Creates a new charting element.
+		//	chart: dojox.charting.Chart2D
+		//		The chart that this element belongs to.
+		this.chart = chart;
+		this.group = null;
+		this.htmlElements = [];
+		this.dirty = true;
+	},
+	createGroup: function(creator){
+		//	summary:
+		//		Convenience function to create a new dojox.gfx.Group.
+		//	creator: dojox.gfx.Surface?
+		//		An optional surface in which to create this group.
+		//	returns: dojox.charting.Element
+		//		A reference to this object for functional chaining.
+		if(!creator){ creator = this.chart.surface; }
+		if(!this.group){
+			this.group = creator.createGroup();
+		}
+		return this;	//	dojox.charting.Element
+	},
+	purgeGroup: function(){
+		//	summary:
+		//		Clear any elements out of our group, and destroy the group.
+		//	returns: dojox.charting.Element
+		//		A reference to this object for functional chaining.
+		this.destroyHtmlElements();
+		if(this.group){
+			this.group.clear();
+			this.group.removeShape();
+			this.group = null;
+		}
+		this.dirty = true;
+		return this;	//	dojox.charting.Element
+	},
+	cleanGroup: function(creator){
+		//	summary:
+		//		Clean any elements (HTML or GFX-based) out of our group, and create a new one.
+		//	creator: dojox.gfx.Surface?
+		//		An optional surface to work with.
+		//	returns: dojox.charting.Element
+		//		A reference to this object for functional chaining.
+		this.destroyHtmlElements();
+		if(!creator){ creator = this.chart.surface; }
+		if(this.group){
+			this.group.clear();
+		}else{
+			this.group = creator.createGroup();
+		}
+		this.dirty = true;
+		return this;	//	dojox.charting.Element
+	},
+	destroyHtmlElements: function(){
+		//	summary:
+		//		Destroy any DOMNodes that may have been created as a part of this element.
+		if(this.htmlElements.length){
+			dojo.forEach(this.htmlElements, dojo.destroy);
+			this.htmlElements = [];
+		}
+	},
+	destroy: function(){
+		//	summary:
+		//		API addition to conform to the rest of the Dojo Toolkit's standard.
+		this.purgeGroup();
+	},
+	// fill utilities
+	_plotFill: function(fill, dim, offsets){
+		// process a plot-wide fill
+		if(!fill || !fill.type || !fill.space){
+			return fill;
+		}
+		var space = fill.space;
+		switch(fill.type){
+			case "linear":
+				if(space === "plot" || space === "shapeX" || space === "shapeY"){
+					// clone a fill so we can modify properly directly
+					fill = dojox.gfx.makeParameters(dojox.gfx.defaultLinearGradient, fill);
+					fill.space = space;
+					// process dimensions
+					if(space === "plot" || space === "shapeX"){
+						// process Y
+						var span = dim.height - offsets.t - offsets.b;
+						fill.y1 = offsets.t + span * fill.y1 / 100;
+						fill.y2 = offsets.t + span * fill.y2 / 100;
+					}
+					if(space === "plot" || space === "shapeY"){
+						// process X
+						var span = dim.width - offsets.l - offsets.r;
+						fill.x1 = offsets.l + span * fill.x1 / 100;
+						fill.x2 = offsets.l + span * fill.x2 / 100;
+					}
+				}
+				break;
+			case "radial":
+				if(space === "plot"){
+					// this one is used exclusively for scatter charts
+					// clone a fill so we can modify properly directly
+					fill = dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient, fill);
+					fill.space = space;
+					// process both dimensions
+					var spanX = dim.width  - offsets.l - offsets.r,
+						spanY = dim.height - offsets.t - offsets.b;
+					fill.cx = offsets.l + spanX * fill.cx / 100;
+					fill.cy = offsets.t + spanY * fill.cy / 100;
+					fill.r  = fill.r * Math.sqrt(spanX * spanX + spanY * spanY) / 200;
+				}
+				break;
+			case "pattern":
+				if(space === "plot" || space === "shapeX" || space === "shapeY"){
+					// clone a fill so we can modify properly directly
+					fill = dojox.gfx.makeParameters(dojox.gfx.defaultPattern, fill);
+					fill.space = space;
+					// process dimensions
+					if(space === "plot" || space === "shapeX"){
+						// process Y
+						var span = dim.height - offsets.t - offsets.b;
+						fill.y = offsets.t + span * fill.y / 100;
+						fill.height = span * fill.height / 100;
+					}
+					if(space === "plot" || space === "shapeY"){
+						// process X
+						var span = dim.width - offsets.l - offsets.r;
+						fill.x = offsets.l + span * fill.x / 100;
+						fill.width = span * fill.width / 100;
+					}
+				}
+				break;
+		}
+		return fill;
+	},
+	_shapeFill: function(fill, bbox){
+		// process shape-specific fill
+		if(!fill || !fill.space){
+			return fill;
+		}
+		var space = fill.space;
+		switch(fill.type){
+			case "linear":
+				if(space === "shape" || space === "shapeX" || space === "shapeY"){
+					// clone a fill so we can modify properly directly
+					fill = dojox.gfx.makeParameters(dojox.gfx.defaultLinearGradient, fill);
+					fill.space = space;
+					// process dimensions
+					if(space === "shape" || space === "shapeX"){
+						// process X
+						var span = bbox.width;
+						fill.x1 = bbox.x + span * fill.x1 / 100;
+						fill.x2 = bbox.x + span * fill.x2 / 100;
+					}
+					if(space === "shape" || space === "shapeY"){
+						// process Y
+						var span = bbox.height;
+						fill.y1 = bbox.y + span * fill.y1 / 100;
+						fill.y2 = bbox.y + span * fill.y2 / 100;
+					}
+				}
+				break;
+			case "radial":
+				if(space === "shape"){
+					// this one is used exclusively for bubble charts and pie charts
+					// clone a fill so we can modify properly directly
+					fill = dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient, fill);
+					fill.space = space;
+					// process both dimensions
+					fill.cx = bbox.x + bbox.width  / 2;
+					fill.cy = bbox.y + bbox.height / 2;
+					fill.r  = fill.r * bbox.width  / 200;
+				}
+				break;
+			case "pattern":
+				if(space === "shape" || space === "shapeX" || space === "shapeY"){
+					// clone a fill so we can modify properly directly
+					fill = dojox.gfx.makeParameters(dojox.gfx.defaultPattern, fill);
+					fill.space = space;
+					// process dimensions
+					if(space === "shape" || space === "shapeX"){
+						// process X
+						var span = bbox.width;
+						fill.x = bbox.x + span * fill.x / 100;
+						fill.width = span * fill.width / 100;
+					}
+					if(space === "shape" || space === "shapeY"){
+						// process Y
+						var span = bbox.height;
+						fill.y = bbox.y + span * fill.y / 100;
+						fill.height = span * fill.height / 100;
+					}
+				}
+				break;
+		}
+		return fill;
+	},
+	_pseudoRadialFill: function(fill, center, radius, start, end){
+		// process pseudo-radial fills
+		if(!fill || fill.type !== "radial" || fill.space !== "shape"){
+			return fill;
+		}
+		// clone and normalize fill
+		var space = fill.space;
+		fill = dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient, fill);
+		fill.space = space;
+		if(arguments.length < 4){
+			// process both dimensions
+			fill.cx = center.x;
+			fill.cy = center.y;
+			fill.r  = fill.r * radius / 100;
+			return fill;
+		}
+		// convert to a linear gradient
+		var angle = arguments.length < 5 ? start : (end + start) / 2;
+		return {
+			type: "linear",
+			x1: center.x,
+			y1: center.y,
+			x2: center.x + fill.r * radius * Math.cos(angle) / 100,
+			y2: center.y + fill.r * radius * Math.sin(angle) / 100,
+			colors: fill.colors
+		};
+		return fill;
+	}
+});
diff --git a/dojox/charting/Series.js b/dojox/charting/Series.js
index 19b2038..edd1b44 100644
--- a/dojox/charting/Series.js
+++ b/dojox/charting/Series.js
@@ -1,23 +1,59 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.Series"]){
-dojo._hasResource["dojox.charting.Series"]=true;
 dojo.provide("dojox.charting.Series");
+
 dojo.require("dojox.charting.Element");
-dojo.declare("dojox.charting.Series",dojox.charting.Element,{constructor:function(_1,_2,_3){
-dojo.mixin(this,_3);
-if(typeof this.plot!="string"){
-this.plot="default";
-}
-this.data=_2;
-this.dirty=true;
-this.clear();
-},clear:function(){
-this.dyn={};
-}});
-}
+/*=====
+dojox.charting.__SeriesCtorArgs = function(plot){
+	//	summary:
+	//		An optional arguments object that can be used in the Series constructor.
+	//	plot: String?
+	//		The plot (by name) that this series belongs to.
+	this.plot = plot;
+} 
+=====*/
+dojo.declare("dojox.charting.Series", dojox.charting.Element, {
+	//	summary:
+	//		An object representing a series of data for plotting on a chart.
+	constructor: function(chart, data, kwArgs){
+		//	summary:
+		//		Create a new data series object for use within charting.
+		//	chart: dojox.charting.Chart2D
+		//		The chart that this series belongs to.
+		//	data: Array|Object:
+		//		The array of data points (either numbers or objects) that
+		//		represents the data to be drawn. Or it can be an object. In
+		//		the latter case, it should have a property "data" (an array),
+		//		destroy(), and setSeriesObject().
+		//	kwArgs: dojox.charting.__SeriesCtorArgs?
+		//		An optional keyword arguments object to set details for this series.
+		dojo.mixin(this, kwArgs);
+		if(typeof this.plot != "string"){ this.plot = "default"; }
+		this.update(data);
+	},
+
+	clear: function(){
+		//	summary:
+		//		Clear the calculated additional parameters set on this series.
+		this.dyn = {};
+	},
+	
+	update: function(data){
+		//	summary:
+		//		Set data and make this object dirty, so it can be redrawn.
+		//	data: Array|Object:
+		//		The array of data points (either numbers or objects) that
+		//		represents the data to be drawn. Or it can be an object. In
+		//		the latter case, it should have a property "data" (an array),
+		//		destroy(), and setSeriesObject().
+		if(dojo.isArray(data)){
+			this.data = data;
+		}else{
+			this.source = data;
+			this.data = this.source.data;
+			if(this.source.setSeriesObject){
+				this.source.setSeriesObject(this);
+			}
+		}
+		this.dirty = true;
+		this.clear();
+	}
+});
diff --git a/dojox/charting/Theme.js b/dojox/charting/Theme.js
index 78b6520..63703c8 100644
--- a/dojox/charting/Theme.js
+++ b/dojox/charting/Theme.js
@@ -1,82 +1,612 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.Theme"]){
-dojo._hasResource["dojox.charting.Theme"]=true;
 dojo.provide("dojox.charting.Theme");
+
 dojo.require("dojox.color");
 dojo.require("dojox.color.Palette");
-(function(){
-var _1=dojox.charting;
-_1.Theme=function(_2){
-_2=_2||{};
-var _3=_1.Theme._def;
-dojo.forEach(["chart","plotarea","axis","series","marker"],function(n){
-this[n]=dojo.delegate(_3[n],_2[n]||{});
-},this);
-this.markers=dojo.delegate(_1.Theme.Markers,_2.markers||{});
-this.colors=[];
-this.antiAlias=("antiAlias" in _2)?_2.antiAlias:true;
-this.assignColors=("assignColors" in _2)?_2.assignColors:true;
-this.assignMarkers=("assignMarkers" in _2)?_2.assignMarkers:true;
-_2.colors=_2.colors||_3.colors;
-dojo.forEach(_2.colors,function(_4){
-this.colors.push(_4);
-},this);
-this._current={color:0,marker:0};
-this._markers=[];
-this._buildMarkerArray();
-};
-_1.Theme.Markers={CIRCLE:"m-3,0 c0,-4 6,-4 6,0 m-6,0 c0,4 6,4 6,0",SQUARE:"m-3,-3 l0,6 6,0 0,-6 z",DIAMOND:"m0,-3 l3,3 -3,3 -3,-3 z",CROSS:"m0,-3 l0,6 m-3,-3 l6,0",X:"m-3,-3 l6,6 m0,-6 l-6,6",TRIANGLE:"m-3,3 l3,-6 3,6 z",TRIANGLE_INVERTED:"m-3,-3 l3,6 3,-6 z"};
-_1.Theme._def={chart:{stroke:null,fill:"white"},plotarea:{stroke:null,fill:"white"},axis:{stroke:{color:"#333",width:1},majorTick:{color:"#666",width:1,length:6,position:"center"},minorTick:{color:"#666",width:0.8,length:3,position:"center"},microTick:{color:"#666",width:0.5,length:1,position:"center"},font:"normal normal normal 7pt Tahoma",fontColor:"#333"},series:{outline:{width:0.1,color:"#ccc"},stroke:{width:1.5,color:"#333"},fill:"#ccc",font:"normal normal normal 7pt Tahoma",fontCol [...]
-dojo.extend(_1.Theme,{defineColors:function(_5){
-var _6=_5||{};
-var c=[],n=_6.num||5;
-if(_6.colors){
-var l=_6.colors.length;
-for(var i=0;i<n;i++){
-c.push(_6.colors[i%l]);
-}
-this.colors=c;
-}else{
-if(_6.hue){
-var s=_6.saturation||100;
-var st=_6.low||30;
-var _7=_6.high||90;
-var l=(_7+st)/2;
-this.colors=dojox.color.Palette.generate(dojox.color.fromHsv(_6.hue,s,l),"monochromatic").colors;
-}else{
-if(_6.generator){
-this.colors=dojox.color.Palette.generate(_6.base,_6.generator).colors;
-}
-}
-}
-},_buildMarkerArray:function(){
-this._markers=[];
-for(var p in this.markers){
-this._markers.push(this.markers[p]);
-}
-this._current.marker=0;
-},_clone:function(){
-return new _1.Theme({chart:this.chart,plotarea:this.plotarea,axis:this.axis,series:this.series,marker:this.marker,antiAlias:this.antiAlias,assignColors:this.assignColors,assignMarkers:this.assigneMarkers,colors:dojo.delegate(this.colors)});
-},addMarker:function(_8,_9){
-this.markers[_8]=_9;
-this._buildMarkerArray();
-},setMarkers:function(_a){
-this.markers=_a;
-this._buildMarkerArray();
-},next:function(_b){
-if(_b=="marker"){
-return this._markers[this._current.marker++%this._markers.length];
-}else{
-return this.colors[this._current.color++%this.colors.length];
-}
-},clear:function(){
-this._current={color:0,marker:0};
-}});
-})();
+dojo.require("dojox.lang.utils");
+dojo.require("dojox.gfx.gradutils");
+
+dojo.declare("dojox.charting.Theme", null, {
+	//	summary:
+	//		A Theme is a pre-defined object, primarily JSON-based, that makes up the definitions to
+	//		style a chart.
+	//
+	//	description:
+	//		While you can set up style definitions on a chart directly (usually through the various add methods
+	//		on a dojox.charting.Chart2D object), a Theme simplifies this manual setup by allowing you to
+	//		pre-define all of the various visual parameters of each element in a chart.
+	//
+	//		Most of the properties of a Theme are straight-forward; if something is line-based (such as
+	//		an axis or the ticks on an axis), they will be defined using basic stroke parameters.  Likewise,
+	//		if an element is primarily block-based (such as the background of a chart), it will be primarily
+	//		fill-based.
+	//
+	//		In addition (for convenience), a Theme definition does not have to contain the entire JSON-based
+	//		structure.  Each theme is built on top of a default theme (which serves as the basis for the theme
+	//		"GreySkies"), and is mixed into the default theme object.  This allows you to create a theme based,
+	//		say, solely on colors for data series.
+	//
+	//		Defining a new theme is relatively easy; see any of the themes in dojox.charting.themes for examples
+	//		on how to define your own.
+	//
+	//		When you set a theme on a chart, the theme itself is deep-cloned.  This means that you cannot alter
+	//		the theme itself after setting the theme value on a chart, and expect it to change your chart.  If you
+	//		are looking to make alterations to a theme for a chart, the suggestion would be to create your own
+	//		theme, based on the one you want to use, that makes those alterations before it is applied to a chart.
+	//
+	//		Finally, a Theme contains a number of functions to facilitate rendering operations on a chart--the main
+	//		helper of which is the ~next~ method, in which a chart asks for the information for the next data series
+	//		to be rendered.
+	//
+	//		A note on colors:
+	//		The Theme constructor was on the use of dojox.color.Palette (in general) for creating a visually distinct
+	//		set of colors for usage in a chart.  A palette is usually comprised of 5 different color definitions, and
+	//		no more.  If you have a need to render a chart with more than 5 data elements, you can simply "push"
+	//		new color definitions into the theme's .color array.  Make sure that you do that with the actual
+	//		theme object from a Chart, and not in the theme itself (i.e. either do that before using .setTheme
+	//		on a chart).
+	//
+	//		example:
+	//			The default theme (and structure) looks like so:
+	//	|	// all objects are structs used directly in dojox.gfx
+	//	|	chart:{
+	//	|		stroke: null,
+	//	|		fill: "white",
+	//	|		pageStyle: null // suggested page style as an object suitable for dojo.style()
+	//	|	},
+	//	|	plotarea:{
+	//	|		stroke: null,
+	//	|		fill: "white"
+	//	|	},
+	//	|	axis:{
+	//	|		stroke:	{ // the axis itself
+	//	|			color: "#333",
+	//	|			width: 1
+	//	|		},
+	//	|		tick: {	// used as a foundation for all ticks
+	//	|			color:     "#666",
+	//	|			position:  "center",
+	//	|			font:      "normal normal normal 7pt Tahoma",	// labels on axis
+	//	|			fontColor: "#333"								// color of labels
+	//	|		},
+	//	|		majorTick:	{ // major ticks on axis, and used for major gridlines
+	//	|			width:  1,
+	//	|			length: 6
+	//	|		},
+	//	|		minorTick:	{ // minor ticks on axis, and used for minor gridlines
+	//	|			width:  0.8,
+	//	|			length: 3
+	//	|		},
+	//	|		microTick:	{ // minor ticks on axis, and used for minor gridlines
+	//	|			width:  0.5,
+	//	|			length: 1
+	//	|		}
+	//	|	},
+	//	|	series: {
+	//	|		stroke:  {width: 1.5, color: "#333"},		// line
+	//	|		outline: {width: 0.1, color: "#ccc"},		// outline
+	//	|		//shadow:  {dx: 1, dy: 1, width: 2, color: [0, 0, 0, 0.3]},
+	//	|		shadow: null,								// no shadow
+	//	|		fill:    "#ccc",							// fill, if appropriate
+	//	|		font:    "normal normal normal 8pt Tahoma",	// if there's a label
+	//	|		fontColor: "#000"							// color of labels
+	//	|	},
+	//	|	marker: {	// any markers on a series
+	//	|		symbol:  "m-3,3 l3,-6 3,6 z",				// symbol
+	//	|		stroke:  {width: 1.5, color: "#333"},		// stroke
+	//	|		outline: {width: 0.1, color: "#ccc"},		// outline
+	//	|		shadow: null,								// no shadow
+	//	|		fill:    "#ccc",							// fill if needed
+	//	|		font:    "normal normal normal 8pt Tahoma",	// label
+	//	|		fontColor: "#000"
+	//	|	}
+	//
+	//	example:
+	//		Defining a new theme is pretty simple:
+	//	|	dojox.charting.themes.Grasslands = new dojox.charting.Theme({
+	//	|		colors: [ "#70803a", "#dde574", "#788062", "#b1cc5d", "#eff2c2" ]
+	//	|	});
+	//	|
+	//	|	myChart.setTheme(dojox.charting.themes.Grasslands);
+
+	shapeSpaces: {shape: 1, shapeX: 1, shapeY: 1},
+
+	constructor: function(kwArgs){
+		//	summary:
+		//		Initialize a theme using the keyword arguments.  Note that the arguments
+		//		look like the example (above), and may include a few more parameters.
+		kwArgs = kwArgs || {};
+
+		// populate theme with defaults updating them if needed
+		var def = dojox.charting.Theme.defaultTheme;
+		dojo.forEach(["chart", "plotarea", "axis", "series", "marker"], function(name){
+			this[name] = dojo.delegate(def[name], kwArgs[name]);
+		}, this);
+
+		// personalize theme
+		if(kwArgs.seriesThemes && kwArgs.seriesThemes.length){
+			this.colors  = null;
+			this.seriesThemes = kwArgs.seriesThemes.slice(0);
+		}else{
+			this.seriesThemes = null;
+			this.colors = (kwArgs.colors || dojox.charting.Theme.defaultColors).slice(0);
+		}
+		this.markerThemes = null;
+		if(kwArgs.markerThemes && kwArgs.markerThemes.length){
+			this.markerThemes = kwArgs.markerThemes.slice(0);
+		}
+		this.markers = dojo.delegate(dojox.charting.Theme.defaultMarkers, kwArgs.markers);
+
+		// set flags
+		this.noGradConv = kwArgs.noGradConv;
+		this.noRadialConv = kwArgs.noRadialConv;
+		if(kwArgs.reverseFills){
+			this.reverseFills();
+		}
+
+		//	private housekeeping
+		this._current = 0;
+		this._buildMarkerArray();
+	},
+
+	clone: function(){
+		//	summary:
+		//		Clone the current theme.
+		//	returns: dojox.charting.Theme
+		//		The cloned theme; any alterations made will not affect the original.
+		var theme = new dojox.charting.Theme({
+			// theme components
+			chart: this.chart,
+			plotarea: this.plotarea,
+			axis: this.axis,
+			series: this.series,
+			marker: this.marker,
+			// individual arrays
+			colors: this.colors,
+			markers: this.markers,
+			seriesThemes: this.seriesThemes,
+			markerThemes: this.markerThemes,
+			// flags
+			noGradConv: this.noGradConv,
+			noRadialConv: this.noRadialConv
+		});
+		// copy custom methods
+		dojo.forEach(
+			["clone", "clear", "next", "skip", "addMixin", "post", "getTick"],
+			function(name){
+				if(this.hasOwnProperty(name)){
+					theme[name] = this[name];
+				}
+			},
+			this
+		);
+		return theme;	//	dojox.charting.Theme
+	},
+
+	clear: function(){
+		//	summary:
+		//		Clear and reset the internal pointer to start fresh.
+		this._current = 0;
+	},
+
+	next: function(elementType, mixin, doPost){
+		//	summary:
+		//		Get the next color or series theme.
+		//	elementType: String?
+		//		An optional element type (for use with series themes)
+		//	mixin: Object?
+		//		An optional object to mix into the theme.
+		//	doPost: Boolean?
+		//		A flag to post-process the results.
+		//	returns: Object
+		//		An object of the structure { series, marker, symbol }
+		var merge = dojox.lang.utils.merge, series, marker;
+		if(this.colors){
+			series = dojo.delegate(this.series);
+			marker = dojo.delegate(this.marker);
+			var color = new dojo.Color(this.colors[this._current % this.colors.length]), old;
+			// modify the stroke
+			if(series.stroke && series.stroke.color){
+				series.stroke = dojo.delegate(series.stroke);
+				old = new dojo.Color(series.stroke.color);
+				series.stroke.color = new dojo.Color(color);
+				series.stroke.color.a = old.a;
+			}else{
+				series.stroke = {color: color};
+			}
+			if(marker.stroke && marker.stroke.color){
+				marker.stroke = dojo.delegate(marker.stroke);
+				old = new dojo.Color(marker.stroke.color);
+				marker.stroke.color = new dojo.Color(color);
+				marker.stroke.color.a = old.a;
+			}else{
+				marker.stroke = {color: color};
+			}
+			// modify the fill
+			if(!series.fill || series.fill.type){
+				series.fill = color;
+			}else{
+				old = new dojo.Color(series.fill);
+				series.fill = new dojo.Color(color);
+				series.fill.a = old.a;
+			}
+			if(!marker.fill || marker.fill.type){
+				marker.fill = color;
+			}else{
+				old = new dojo.Color(marker.fill);
+				marker.fill = new dojo.Color(color);
+				marker.fill.a = old.a;
+			}
+		}else{
+			series = this.seriesThemes ?
+				merge(this.series, this.seriesThemes[this._current % this.seriesThemes.length]) :
+				this.series;
+			marker = this.markerThemes ?
+				merge(this.marker, this.markerThemes[this._current % this.markerThemes.length]) :
+				series;
+		}
+
+		var symbol = marker && marker.symbol || this._markers[this._current % this._markers.length];
+
+		var theme = {series: series, marker: marker, symbol: symbol};
+		
+		// advance the counter
+		++this._current;
+
+		if(mixin){
+			theme = this.addMixin(theme, elementType, mixin);
+		}
+		if(doPost){
+			theme = this.post(theme, elementType);
+		}
+
+		return theme;	//	Object
+	},
+
+	skip: function(){
+		//	summary:
+		//		Skip the next internal color.
+		++this._current;
+	},
+
+	addMixin: function(theme, elementType, mixin, doPost){
+		//	summary:
+		//		Add a mixin object to the passed theme and process.
+		//	theme: dojox.charting.Theme
+		//		The theme to mixin to.
+		//	elementType: String
+		//		The type of element in question. Can be "line", "bar" or "circle"
+		//	mixin: Object|Array
+		//		The object or objects to mix into the theme.
+		//	doPost: Boolean
+		//		If true, run the new theme through the post-processor.
+		//	returns: dojox.charting.Theme
+		//		The new theme.
+		if(dojo.isArray(mixin)){
+			dojo.forEach(mixin, function(m){
+				theme = this.addMixin(theme, elementType, m);
+			}, this);
+		}else{
+			var t = {};
+			if("color" in mixin){
+				if(elementType == "line" || elementType == "area"){
+					dojo.setObject("series.stroke.color", mixin.color, t);
+					dojo.setObject("marker.stroke.color", mixin.color, t);
+				}else{
+					dojo.setObject("series.fill", mixin.color, t);
+				}
+			}
+			dojo.forEach(["stroke", "outline", "shadow", "fill", "font", "fontColor"], function(name){
+				var markerName = "marker" + name.charAt(0).toUpperCase() + name.substr(1),
+					b = markerName in mixin;
+				if(name in mixin){
+					dojo.setObject("series." + name, mixin[name], t);
+					if(!b){
+						dojo.setObject("marker." + name, mixin[name], t);
+					}
+				}
+				if(b){
+					dojo.setObject("marker." + name, mixin[markerName], t);
+				}
+			});
+			if("marker" in mixin){
+				t.symbol = mixin.marker;
+			}
+			theme = dojox.lang.utils.merge(theme, t);
+		}
+		if(doPost){
+			theme = this.post(theme, elementType);
+		}
+		return theme;	//	dojox.charting.Theme
+	},
+
+	post: function(theme, elementType){
+		//	summary:
+		//		Process any post-shape fills.
+		//	theme: dojox.charting.Theme
+		//		The theme to post process with.
+		//	elementType: String
+		//		The type of element being filled.  Can be "bar" or "circle".
+		//	returns: dojox.charting.Theme
+		//		The post-processed theme.
+		var fill = theme.series.fill, t;
+		if(!this.noGradConv && this.shapeSpaces[fill.space] && fill.type == "linear"){
+			if(elementType == "bar"){
+				// transpose start and end points
+				t = {
+					x1: fill.y1,
+					y1: fill.x1,
+					x2: fill.y2,
+					y2: fill.x2
+				};
+			}else if(!this.noRadialConv && fill.space == "shape" && (elementType == "slice" || elementType == "circle")){
+				// switch to radial
+				t = {
+					type: "radial",
+					cx: 0,
+					cy: 0,
+					r:  100
+				};
+			}
+			if(t){
+				return dojox.lang.utils.merge(theme, {series: {fill: t}});
+			}
+		}
+		return theme;	//	dojox.charting.Theme
+	},
+
+	getTick: function(name, mixin){
+		//	summary:
+		//		Calculates and merges tick parameters.
+		//	name: String
+		//		Tick name, can be "major", "minor", or "micro".
+		//	mixin: Object?
+		//		Optional object to mix in to the tick.
+		var tick = this.axis.tick, tickName = name + "Tick";
+			merge = dojox.lang.utils.merge;
+		if(tick){
+			if(this.axis[tickName]){
+				tick = merge(tick, this.axis[tickName]);
+			}
+		}else{
+			tick = this.axis[tickName];
+		}
+		if(mixin){
+			if(tick){
+				if(mixin[tickName]){
+					tick = merge(tick, mixin[tickName]);
+				}
+			}else{
+				tick = mixin[tickName];
+			}
+		}
+		return tick;	//	Object
+	},
+
+	inspectObjects: function(f){
+		dojo.forEach(["chart", "plotarea", "axis", "series", "marker"], function(name){
+			f(this[name]);
+		}, this);
+		if(this.seriesThemes){
+			dojo.forEach(this.seriesThemes, f);
+		}
+		if(this.markerThemes){
+			dojo.forEach(this.markerThemes, f);
+		}
+	},
+
+	reverseFills: function(){
+		this.inspectObjects(function(o){
+			if(o && o.fill){
+				o.fill = dojox.gfx.gradutils.reverse(o.fill);
+			}
+		});
+	},
+
+	addMarker:function(/*String*/ name, /*String*/ segment){
+		//	summary:
+		//		Add a custom marker to this theme.
+		//	example:
+		//	|	myTheme.addMarker("Ellipse", foo);
+		this.markers[name] = segment;
+		this._buildMarkerArray();
+	},
+
+	setMarkers:function(/*Object*/ obj){
+		//	summary:
+		//		Set all the markers of this theme at once.  obj should be a
+		//		dictionary of keys and path segments.
+		//
+		//	example:
+		//	|	myTheme.setMarkers({ "CIRCLE": foo });
+		this.markers = obj;
+		this._buildMarkerArray();
+	},
+
+	_buildMarkerArray: function(){
+		this._markers = [];
+		for(var p in this.markers){
+			this._markers.push(this.markers[p]);
+		}
+	}
+});
+
+/*=====
+dojox.charting.Theme.__DefineColorArgs = function(num, colors, hue, saturation, low, high, base, generator){
+	//	summary:
+	//		The arguments object that can be passed to define colors for a theme.
+	//	num: Number?
+	//		The number of colors to generate.  Defaults to 5.
+	//	colors: String[]|dojo.Color[]?
+	//		A pre-defined set of colors; this is passed through to the Theme directly.
+	//	hue: Number?
+	//		A hue to base the generated colors from (a number from 0 - 359).
+	//	saturation: Number?
+	//		If a hue is passed, this is used for the saturation value (0 - 100).
+	//	low: Number?
+	//		An optional value to determine the lowest value used to generate a color (HSV model)
+	//	high: Number?
+	//		An optional value to determine the highest value used to generate a color (HSV model)
+	//	base: String|dojo.Color?
+	//		A base color to use if we are defining colors using dojox.color.Palette
+	//	generator: String?
+	//		The generator function name from dojox.color.Palette.
+	this.num = num;
+	this.colors = colors;
+	this.hue = hue;
+	this.saturation = saturation;
+	this.low = low;
+	this.high = high;
+	this.base = base;
+	this.generator = generator;
 }
+=====*/
+dojo.mixin(dojox.charting.Theme, {
+	defaultMarkers: {
+		CIRCLE:   "m-3,0 c0,-4 6,-4 6,0 m-6,0 c0,4 6,4 6,0",
+		SQUARE:   "m-3,-3 l0,6 6,0 0,-6 z",
+		DIAMOND:  "m0,-3 l3,3 -3,3 -3,-3 z",
+		CROSS:    "m0,-3 l0,6 m-3,-3 l6,0",
+		X:        "m-3,-3 l6,6 m0,-6 l-6,6",
+		TRIANGLE: "m-3,3 l3,-6 3,6 z",
+		TRIANGLE_INVERTED: "m-3,-3 l3,6 3,-6 z"
+	},
+
+	defaultColors:[
+		// gray skies
+		"#54544c", "#858e94", "#6e767a", "#948585", "#474747"
+	],
+
+	defaultTheme: {
+		// all objects are structs used directly in dojox.gfx
+		chart:{
+			stroke: null,
+			fill: "white",
+			pageStyle: null
+		},
+		plotarea:{
+			stroke: null,
+			fill: "white"
+		},
+		// TODO: label rotation on axis
+		axis:{
+			stroke:	{ // the axis itself
+				color: "#333",
+				width: 1
+			},
+			tick: {	// used as a foundation for all ticks
+				color:     "#666",
+				position:  "center",
+				font:      "normal normal normal 7pt Tahoma",	// labels on axis
+				fontColor: "#333"								// color of labels
+			},
+			majorTick:	{ // major ticks on axis, and used for major gridlines
+				width:  1,
+				length: 6
+			},
+			minorTick:	{ // minor ticks on axis, and used for minor gridlines
+				width:  0.8,
+				length: 3
+			},
+			microTick:	{ // minor ticks on axis, and used for minor gridlines
+				width:  0.5,
+				length: 1
+			}
+		},
+		series: {
+			// used as a "main" theme for series, sThemes augment it
+			stroke:  {width: 1.5, color: "#333"},		// line
+			outline: {width: 0.1, color: "#ccc"},		// outline
+			//shadow:  {dx: 1, dy: 1, width: 2, color: [0, 0, 0, 0.3]},
+			shadow: null,								// no shadow
+			fill:    "#ccc",							// fill, if appropriate
+			font:    "normal normal normal 8pt Tahoma",	// if there's a label
+			fontColor: "#000"							// color of labels
+		},
+		marker: {	// any markers on a series
+			stroke:  {width: 1.5, color: "#333"},		// stroke
+			outline: {width: 0.1, color: "#ccc"},		// outline
+			//shadow:  {dx: 1, dy: 1, width: 2, color: [0, 0, 0, 0.3]},
+			shadow: null,								// no shadow
+			fill:    "#ccc",							// fill if needed
+			font:    "normal normal normal 8pt Tahoma",	// label
+			fontColor: "#000"
+		}
+	},
+
+	defineColors: function(kwArgs){
+		//	summary:
+		//		Generate a set of colors for the theme based on keyword
+		//		arguments.
+		//	kwArgs: dojox.charting.Theme.__DefineColorArgs
+		//		The arguments object used to define colors.
+		//	returns: dojo.Color[]
+		//		An array of colors for use in a theme.
+		//
+		//	example:
+		//	|	var colors = dojox.charting.Theme.defineColors({
+		//	|		base: "#369",
+		//	|		generator: "compound"
+		//	|	});
+		//
+		//	example:
+		//	|	var colors = dojox.charting.Theme.defineColors({
+		//	|		hue: 60,
+		//	|		saturation: 90,
+		//	|		low: 30,
+		//	|		high: 80
+		//	|	});
+		kwArgs = kwArgs || {};
+		var c = [], n = kwArgs.num || 5;	// the number of colors to generate
+		if(kwArgs.colors){
+			// we have an array of colors predefined, so fix for the number of series.
+			var l = kwArgs.colors.length;
+			for(var i = 0; i < n; i++){
+				c.push(kwArgs.colors[i % l]);
+			}
+			return c;	//	dojo.Color[]
+		}
+		if(kwArgs.hue){
+			// single hue, generate a set based on brightness
+			var s = kwArgs.saturation || 100;	// saturation
+			var st = kwArgs.low || 30;
+			var end = kwArgs.high || 90;
+			// we'd like it to be a little on the darker side.
+			var l = (end + st) / 2;
+			// alternately, use "shades"
+			return dojox.color.Palette.generate(
+				dojox.color.fromHsv(kwArgs.hue, s, l), "monochromatic"
+			).colors;
+		}
+		if(kwArgs.generator){
+			//	pass a base color and the name of a generator
+			return dojox.color.Palette.generate(kwArgs.base, kwArgs.generator).colors;
+		}
+		return c;	//	dojo.Color[]
+	},
+	
+	generateGradient: function(fillPattern, colorFrom, colorTo){
+		var fill = dojo.delegate(fillPattern);
+		fill.colors = [
+			{offset: 0, color: colorFrom},
+			{offset: 1, color: colorTo}
+		];
+		return fill;
+	},
+	
+	generateHslColor: function(color, luminance){
+		color = new dojox.color.Color(color);
+		var hsl    = color.toHsl(),
+			result = dojox.color.fromHsl(hsl.h, hsl.s, luminance);
+		result.a = color.a;	// add missing opacity
+		return result;
+	},
+
+	generateHslGradient: function(color, fillPattern, lumFrom, lumTo){
+		color = new dojox.color.Color(color);
+		var hsl       = color.toHsl(),
+			colorFrom = dojox.color.fromHsl(hsl.h, hsl.s, lumFrom),
+			colorTo   = dojox.color.fromHsl(hsl.h, hsl.s, lumTo);
+		colorFrom.a = colorTo.a = color.a;	// add missing opacity
+		return dojox.charting.Theme.generateGradient(fillPattern, colorFrom, colorTo);	// Object
+	}
+});
diff --git a/dojox/charting/action2d/Base.js b/dojox/charting/action2d/Base.js
index 0b63494..598de23 100644
--- a/dojox/charting/action2d/Base.js
+++ b/dojox/charting/action2d/Base.js
@@ -1,45 +1,80 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.action2d.Base"]){
-dojo._hasResource["dojox.charting.action2d.Base"]=true;
 dojo.provide("dojox.charting.action2d.Base");
+
 dojo.require("dojo.fx.easing");
 dojo.require("dojox.lang.functional.object");
 dojo.require("dojox.gfx.fx");
-(function(){
-var _1=400,_2=dojo.fx.easing.backOut,df=dojox.lang.functional;
-dojo.declare("dojox.charting.action2d.Base",null,{overOutEvents:{onmouseover:1,onmouseout:1},constructor:function(_3,_4,_5){
-this.chart=_3;
-this.plot=_4?_4:"default";
-this.anim={};
-if(!_5){
-_5={};
-}
-this.duration=_5.duration?_5.duration:_1;
-this.easing=_5.easing?_5.easing:_2;
-},connect:function(){
-this.handle=this.chart.connectToPlot(this.plot,this,"process");
-},disconnect:function(){
-if(this.handle){
-dojo.disconnect(this.handle);
-this.handle=null;
-}
-},reset:function(){
-},destroy:function(){
-if(this.handle){
-this.disconnect();
+
+/*=====
+dojox.charting.action2d.__BaseCtorArgs = function(duration, easing){
+ 	//	summary:
+	//		The base keyword arguments object for creating an action2d.
+	//	duration: Number?
+	//		The amount of time in milliseconds for an animation to last.  Default is 400.
+	//	easing: dojox.fx.easing.*?
+	//		An easing object (see dojo.fx.easing) for use in an animation.  The
+	//		default is dojox.fx.easing.backOut.
+	this.duration = duration;
+	this.easing = easing;
 }
-df.forIn(this.anim,function(o){
-df.forIn(o,function(_6){
-_6.action.stop(true);
-});
-});
-this.anim={};
-}});
+=====*/
+(function(){
+	var DEFAULT_DURATION = 400,	// ms
+		DEFAULT_EASING   = dojo.fx.easing.backOut,
+		df = dojox.lang.functional;
+
+	dojo.declare("dojox.charting.action2d.Base", null, {
+
+		overOutEvents: {onmouseover: 1, onmouseout: 1},
+
+		constructor: function(chart, plot, kwargs){
+			//	summary:
+			//		Create a new base Action.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this action applies to.
+			//	plot: String?
+			//		The name of the plot this action belongs to.  If none is passed "default" is assumed.
+			//	kwargs: dojox.charting.action2d.__BaseCtorArgs?
+			//		Optional arguments for the action.
+			this.chart = chart;
+			this.plot = plot || "default";
+			this.anim = {};
+
+			// process common optional named parameters
+			if(!kwargs){ kwargs = {}; }
+			this.duration = kwargs.duration ? kwargs.duration : DEFAULT_DURATION;
+			this.easing   = kwargs.easing   ? kwargs.easing   : DEFAULT_EASING;
+		},
+
+		connect: function(){
+			//	summary:
+			//		Connect this action to the given plot.
+			this.handle = this.chart.connectToPlot(this.plot, this, "process");
+		},
+
+		disconnect: function(){
+			//	summary:
+			//		Disconnect this action from the given plot, if connected.
+			if(this.handle){
+				dojo.disconnect(this.handle);
+				this.handle = null;
+			}
+		},
+
+		reset: function(){
+			//	summary:
+			//		Reset the action.
+		},
+
+		destroy: function(){
+			//	summary:
+			//		Do any cleanup needed when destroying parent elements.
+			this.disconnect();
+			df.forIn(this.anim, function(o){
+				df.forIn(o, function(anim){
+					anim.action.stop(true);
+				});
+			});
+			this.anim = {};
+		}
+	});
 })();
-}
diff --git a/dojox/charting/action2d/Highlight.js b/dojox/charting/action2d/Highlight.js
index 1c45dbd..776f850 100644
--- a/dojox/charting/action2d/Highlight.js
+++ b/dojox/charting/action2d/Highlight.js
@@ -1,76 +1,128 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.action2d.Highlight"]){
-dojo._hasResource["dojox.charting.action2d.Highlight"]=true;
 dojo.provide("dojox.charting.action2d.Highlight");
+
 dojo.require("dojox.charting.action2d.Base");
 dojo.require("dojox.color");
-(function(){
-var _1=100,_2=75,_3=50,c=dojox.color,cc=function(_4){
-return function(){
-return _4;
-};
-},hl=function(_5){
-var a=new c.Color(_5),x=a.toHsl();
-if(x.s==0){
-x.l=x.l<50?100:0;
-}else{
-x.s=_1;
-if(x.l<_3){
-x.l=_2;
-}else{
-if(x.l>_2){
-x.l=_3;
-}else{
-x.l=x.l-_3>_2-x.l?_3:_2;
-}
-}
-}
-return c.fromHsl(x);
-};
-dojo.declare("dojox.charting.action2d.Highlight",dojox.charting.action2d.Base,{defaultParams:{duration:400,easing:dojo.fx.easing.backOut},optionalParams:{highlight:"red"},constructor:function(_6,_7,_8){
-var a=_8&&_8.highlight;
-this.colorFun=a?(dojo.isFunction(a)?a:cc(a)):hl;
-this.connect();
-},process:function(o){
-if(!o.shape||!(o.type in this.overOutEvents)){
-return;
-}
-var _9=o.run.name,_a=o.index,_b,_c,_d;
-if(_9 in this.anim){
-_b=this.anim[_9][_a];
-}else{
-this.anim[_9]={};
-}
-if(_b){
-_b.action.stop(true);
-}else{
-var _e=o.shape.getFill();
-if(!_e||!(_e instanceof dojo.Color)){
-return;
-}
-this.anim[_9][_a]=_b={start:_e,end:this.colorFun(_e)};
-}
-var _f=_b.start,end=_b.end;
-if(o.type=="onmouseout"){
-var t=_f;
-_f=end;
-end=t;
-}
-_b.action=dojox.gfx.fx.animateFill({shape:o.shape,duration:this.duration,easing:this.easing,color:{start:_f,end:end}});
-if(o.type=="onmouseout"){
-dojo.connect(_b.action,"onEnd",this,function(){
-if(this.anim[_9]){
-delete this.anim[_9][_a];
-}
+
+/*=====
+dojo.declare("dojox.charting.action2d.__HighlightCtorArgs", dojox.charting.action2d.__BaseCtorArgs, {
+	//	summary:
+	//		Additional arguments for highlighting actions.
+
+	//	highlight: String|dojo.Color|Function?
+	//		Either a color or a function that creates a color when highlighting happens.
+	highlight: null
 });
-}
-_b.action.play();
-}});
+=====*/
+(function(){
+	var DEFAULT_SATURATION  = 100,	// %
+		DEFAULT_LUMINOSITY1 = 75,	// %
+		DEFAULT_LUMINOSITY2 = 50,	// %
+
+		c = dojox.color,
+
+		cc = function(color){
+			return function(){ return color; };
+		},
+
+		hl = function(color){
+			var a = new c.Color(color),
+				x = a.toHsl();
+			if(x.s == 0){
+				x.l = x.l < 50 ? 100 : 0;
+			}else{
+				x.s = DEFAULT_SATURATION;
+				if(x.l < DEFAULT_LUMINOSITY2){
+					x.l = DEFAULT_LUMINOSITY1;
+				}else if(x.l > DEFAULT_LUMINOSITY1){
+					x.l = DEFAULT_LUMINOSITY2;
+				}else{
+					x.l = x.l - DEFAULT_LUMINOSITY2 > DEFAULT_LUMINOSITY1 - x.l ?
+						DEFAULT_LUMINOSITY2 : DEFAULT_LUMINOSITY1;
+				}
+			}
+			return c.fromHsl(x);
+		};
+
+	dojo.declare("dojox.charting.action2d.Highlight", dojox.charting.action2d.Base, {
+		//	summary:
+		//		Creates a highlighting action on a plot, where an element on that plot
+		//		has a highlight on it.
+
+		// the data description block for the widget parser
+		defaultParams: {
+			duration: 400,	// duration of the action in ms
+			easing:   dojo.fx.easing.backOut	// easing for the action
+		},
+		optionalParams: {
+			highlight: "red"	// name for the highlight color
+								// programmatic instantiation can use functions and color objects
+		},
+
+		constructor: function(chart, plot, kwArgs){
+			//	summary:
+			//		Create the highlighting action and connect it to the plot.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this action belongs to.
+			//	plot: String?
+			//		The plot this action is attached to.  If not passed, "default" is assumed.
+			//	kwArgs: dojox.charting.action2d.__HighlightCtorArgs?
+			//		Optional keyword arguments object for setting parameters.
+			var a = kwArgs && kwArgs.highlight;
+			this.colorFun = a ? (dojo.isFunction(a) ? a : cc(a)) : hl;
+
+			this.connect();
+		},
+
+		process: function(o){
+			//	summary:
+			//		Process the action on the given object.
+			//	o: dojox.gfx.Shape
+			//		The object on which to process the highlighting action.
+			if(!o.shape || !(o.type in this.overOutEvents)){ return; }
+
+			var runName = o.run.name, index = o.index, anim, startFill, endFill;
+
+			if(runName in this.anim){
+				anim = this.anim[runName][index];
+			}else{
+				this.anim[runName] = {};
+			}
+
+			if(anim){
+				anim.action.stop(true);
+			}else{
+				var color = o.shape.getFill();
+				if(!color || !(color instanceof dojo.Color)){
+					return;
+				}
+				this.anim[runName][index] = anim = {
+					start: color,
+					end:   this.colorFun(color)
+				};
+			}
+
+			var start = anim.start, end = anim.end;
+			if(o.type == "onmouseout"){
+				// swap colors
+				var t = start;
+				start = end;
+				end = t;
+			}
+
+			anim.action = dojox.gfx.fx.animateFill({
+				shape:    o.shape,
+				duration: this.duration,
+				easing:   this.easing,
+				color:    {start: start, end: end}
+			});
+			if(o.type == "onmouseout"){
+				dojo.connect(anim.action, "onEnd", this, function(){
+					if(this.anim[runName]){
+						delete this.anim[runName][index];
+					}
+				});
+			}
+			anim.action.play();
+		}
+	});
 })();
-}
diff --git a/dojox/charting/action2d/Magnify.js b/dojox/charting/action2d/Magnify.js
index 73b0df8..7044ff7 100644
--- a/dojox/charting/action2d/Magnify.js
+++ b/dojox/charting/action2d/Magnify.js
@@ -1,68 +1,117 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.action2d.Magnify"]){
-dojo._hasResource["dojox.charting.action2d.Magnify"]=true;
 dojo.provide("dojox.charting.action2d.Magnify");
+
 dojo.require("dojox.charting.action2d.Base");
 dojo.require("dojox.gfx.matrix");
 dojo.require("dojo.fx");
-(function(){
-var _1=2,m=dojox.gfx.matrix,gf=dojox.gfx.fx;
-dojo.declare("dojox.charting.action2d.Magnify",dojox.charting.action2d.Base,{defaultParams:{duration:400,easing:dojo.fx.easing.backOut,scale:_1},optionalParams:{},constructor:function(_2,_3,_4){
-this.scale=_4&&typeof _4.scale=="number"?_4.scale:_1;
-this.connect();
-},process:function(o){
-if(!o.shape||!(o.type in this.overOutEvents)||!("cx" in o)||!("cy" in o)){
-return;
-}
-var _5=o.run.name,_6=o.index,_7=[],_8,_9,_a;
-if(_5 in this.anim){
-_8=this.anim[_5][_6];
-}else{
-this.anim[_5]={};
-}
-if(_8){
-_8.action.stop(true);
-}else{
-this.anim[_5][_6]=_8={};
-}
-if(o.type=="onmouseover"){
-_9=m.identity;
-_a=this.scale;
-}else{
-_9=m.scaleAt(this.scale,o.cx,o.cy);
-_a=1/this.scale;
-}
-var _b={shape:o.shape,duration:this.duration,easing:this.easing,transform:[{name:"scaleAt",start:[1,o.cx,o.cy],end:[_a,o.cx,o.cy]},_9]};
-if(o.shape){
-_7.push(gf.animateTransform(_b));
-}
-if(o.oultine){
-_b.shape=o.outline;
-_7.push(gf.animateTransform(_b));
-}
-if(o.shadow){
-_b.shape=o.shadow;
-_7.push(gf.animateTransform(_b));
-}
-if(!_7.length){
-delete this.anim[_5][_6];
-return;
-}
-_8.action=dojo.fx.combine(_7);
-if(o.type=="onmouseout"){
-dojo.connect(_8.action,"onEnd",this,function(){
-if(this.anim[_5]){
-delete this.anim[_5][_6];
-}
+
+/*=====
+dojo.declare("dojox.charting.action2d.__MagnifyCtorArgs", dojox.charting.action2d.__BaseCtorArgs, {
+	//	summary:
+	//		Additional arguments for highlighting actions.
+
+	//	scale: Number?
+	//		The amount to magnify the given object to.  Default is 2.
+	scale: 2
 });
-}
-_8.action.play();
-}});
+=====*/
+(function(){
+	var DEFAULT_SCALE = 2,
+		m = dojox.gfx.matrix,
+		gf = dojox.gfx.fx;
+
+	dojo.declare("dojox.charting.action2d.Magnify", dojox.charting.action2d.Base, {
+		//	summary:
+		//		Create an action that magnifies the object the action is applied to.
+
+		// the data description block for the widget parser
+		defaultParams: {
+			duration: 400,	// duration of the action in ms
+			easing:   dojo.fx.easing.backOut,	// easing for the action
+			scale:    DEFAULT_SCALE	// scale of magnification
+		},
+		optionalParams: {},	// no optional parameters
+
+		constructor: function(chart, plot, kwArgs){
+			//	summary:
+			//		Create the magnifying action.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this action belongs to.
+			//	plot: String?
+			//		The plot to apply the action to. If not passed, "default" is assumed.
+			//	kwArgs: dojox.charting.action2d.__MagnifyCtorArgs?
+			//		Optional keyword arguments for this action.
+
+			// process optional named parameters
+			this.scale = kwArgs && typeof kwArgs.scale == "number" ? kwArgs.scale : DEFAULT_SCALE;
+
+			this.connect();
+		},
+
+		process: function(o){
+			//	summary:
+			//		Process the action on the given object.
+			//	o: dojox.gfx.Shape
+			//		The object on which to process the magnifying action.
+			if(!o.shape || !(o.type in this.overOutEvents) ||
+				!("cx" in o) || !("cy" in o)){ return; }
+
+			var runName = o.run.name, index = o.index, vector = [], anim, init, scale;
+
+			if(runName in this.anim){
+				anim = this.anim[runName][index];
+			}else{
+				this.anim[runName] = {};
+			}
+
+			if(anim){
+				anim.action.stop(true);
+			}else{
+				this.anim[runName][index] = anim = {};
+			}
+
+			if(o.type == "onmouseover"){
+				init  = m.identity;
+				scale = this.scale;
+			}else{
+				init  = m.scaleAt(this.scale, o.cx, o.cy);
+				scale = 1 / this.scale;
+			}
+
+			var kwArgs = {
+				shape:    o.shape,
+				duration: this.duration,
+				easing:   this.easing,
+				transform: [
+					{name: "scaleAt", start: [1, o.cx, o.cy], end: [scale, o.cx, o.cy]},
+					init
+				]
+			};
+			if(o.shape){
+				vector.push(gf.animateTransform(kwArgs));
+			}
+			if(o.oultine){
+				kwArgs.shape = o.outline;
+				vector.push(gf.animateTransform(kwArgs));
+			}
+			if(o.shadow){
+				kwArgs.shape = o.shadow;
+				vector.push(gf.animateTransform(kwArgs));
+			}
+
+			if(!vector.length){
+				delete this.anim[runName][index];
+				return;
+			}
+
+			anim.action = dojo.fx.combine(vector);
+			if(o.type == "onmouseout"){
+				dojo.connect(anim.action, "onEnd", this, function(){
+					if(this.anim[runName]){
+						delete this.anim[runName][index];
+					}
+				});
+			}
+			anim.action.play();
+		}
+	});
 })();
-}
diff --git a/dojox/charting/action2d/MoveSlice.js b/dojox/charting/action2d/MoveSlice.js
index 11d2747..5142ab7 100644
--- a/dojox/charting/action2d/MoveSlice.js
+++ b/dojox/charting/action2d/MoveSlice.js
@@ -1,65 +1,128 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.action2d.MoveSlice"]){
-dojo._hasResource["dojox.charting.action2d.MoveSlice"]=true;
 dojo.provide("dojox.charting.action2d.MoveSlice");
+
 dojo.require("dojox.charting.action2d.Base");
 dojo.require("dojox.gfx.matrix");
+
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.scan");
 dojo.require("dojox.lang.functional.fold");
-(function(){
-var _1=1.05,_2=7,m=dojox.gfx.matrix,gf=dojox.gfx.fx,df=dojox.lang.functional;
-dojo.declare("dojox.charting.action2d.MoveSlice",dojox.charting.action2d.Base,{defaultParams:{duration:400,easing:dojo.fx.easing.backOut,scale:_1,shift:_2},optionalParams:{},constructor:function(_3,_4,_5){
-if(!_5){
-_5={};
-}
-this.scale=typeof _5.scale=="number"?_5.scale:_1;
-this.shift=typeof _5.shift=="number"?_5.shift:_2;
-this.connect();
-},process:function(o){
-if(!o.shape||o.element!="slice"||!(o.type in this.overOutEvents)){
-return;
-}
-if(!this.angles){
-if(typeof o.run.data[0]=="number"){
-this.angles=df.map(df.scanl(o.run.data,"+",0),"* 2 * Math.PI / this",df.foldl(o.run.data,"+",0));
-}else{
-this.angles=df.map(df.scanl(o.run.data,"a + b.y",0),"* 2 * Math.PI / this",df.foldl(o.run.data,"a + b.y",0));
-}
-}
-var _6=o.index,_7,_8,_9,_a,_b,_c=(this.angles[_6]+this.angles[_6+1])/2,_d=m.rotateAt(-_c,o.cx,o.cy),_e=m.rotateAt(_c,o.cx,o.cy);
-_7=this.anim[_6];
-if(_7){
-_7.action.stop(true);
-}else{
-this.anim[_6]=_7={};
-}
-if(o.type=="onmouseover"){
-_a=0;
-_b=this.shift;
-_8=1;
-_9=this.scale;
-}else{
-_a=this.shift;
-_b=0;
-_8=this.scale;
-_9=1;
-}
-_7.action=dojox.gfx.fx.animateTransform({shape:o.shape,duration:this.duration,easing:this.easing,transform:[_e,{name:"translate",start:[_a,0],end:[_b,0]},{name:"scaleAt",start:[_8,o.cx,o.cy],end:[_9,o.cx,o.cy]},_d]});
-if(o.type=="onmouseout"){
-dojo.connect(_7.action,"onEnd",this,function(){
-delete this.anim[_6];
+
+/*=====
+dojo.declare("dojox.charting.action2d.__MoveSliceCtorArgs", dojox.charting.action2d.__BaseCtorArgs, {
+	//	summary:
+	//		Additional arguments for highlighting actions.
+
+	//	scale: Number?
+	//		The amount to scale the pie slice.  Default is 1.05.
+	scale: 1.05,
+
+	//	shift: Number?
+	//		The amount in pixels to shift the pie slice.  Default is 7.
+	shift: 7
 });
-}
-_7.action.play();
-},reset:function(){
-delete this.angles;
-}});
+=====*/
+(function(){
+	var DEFAULT_SCALE = 1.05,
+		DEFAULT_SHIFT = 7,	// px
+		m = dojox.gfx.matrix,
+		gf = dojox.gfx.fx,
+		df = dojox.lang.functional;
+
+	dojo.declare("dojox.charting.action2d.MoveSlice", dojox.charting.action2d.Base, {
+		//	summary:
+		//		Create an action for a pie chart that moves and scales a pie slice.
+
+		// the data description block for the widget parser
+		defaultParams: {
+			duration: 400,	// duration of the action in ms
+			easing:   dojo.fx.easing.backOut,	// easing for the action
+			scale:    DEFAULT_SCALE,	// scale of magnification
+			shift:    DEFAULT_SHIFT		// shift of the slice
+		},
+		optionalParams: {},	// no optional parameters
+
+		constructor: function(chart, plot, kwArgs){
+			//	summary:
+			//		Create the slice moving action and connect it to the plot.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this action belongs to.
+			//	plot: String?
+			//		The plot this action is attached to.  If not passed, "default" is assumed.
+			//	kwArgs: dojox.charting.action2d.__MoveSliceCtorArgs?
+			//		Optional keyword arguments object for setting parameters.
+			if(!kwArgs){ kwArgs = {}; }
+			this.scale = typeof kwArgs.scale == "number" ? kwArgs.scale : DEFAULT_SCALE;
+			this.shift = typeof kwArgs.shift == "number" ? kwArgs.shift : DEFAULT_SHIFT;
+
+			this.connect();
+		},
+
+		process: function(o){
+			//	summary:
+			//		Process the action on the given object.
+			//	o: dojox.gfx.Shape
+			//		The object on which to process the slice moving action.
+			if(!o.shape || o.element != "slice" || !(o.type in this.overOutEvents)){ return; }
+
+			if(!this.angles){
+				// calculate the running total of slice angles
+				var startAngle = m._degToRad(o.plot.opt.startAngle);
+				if(typeof o.run.data[0] == "number"){
+					this.angles = df.map(df.scanl(o.run.data, "+", startAngle),
+						"* 2 * Math.PI / this", df.foldl(o.run.data, "+", 0));
+				}else{
+					this.angles = df.map(df.scanl(o.run.data, "a + b.y", startAngle),
+						"* 2 * Math.PI / this", df.foldl(o.run.data, "a + b.y", 0));
+				}
+			}
+
+			var index = o.index, anim, startScale, endScale, startOffset, endOffset,
+				angle = (this.angles[index] + this.angles[index + 1]) / 2,
+				rotateTo0  = m.rotateAt(-angle, o.cx, o.cy),
+				rotateBack = m.rotateAt( angle, o.cx, o.cy);
+
+			anim = this.anim[index];
+
+			if(anim){
+				anim.action.stop(true);
+			}else{
+				this.anim[index] = anim = {};
+			}
+
+			if(o.type == "onmouseover"){
+				startOffset = 0;
+				endOffset   = this.shift;
+				startScale  = 1;
+				endScale    = this.scale;
+			}else{
+				startOffset = this.shift;
+				endOffset   = 0;
+				startScale  = this.scale;
+				endScale    = 1;
+			}
+
+			anim.action = dojox.gfx.fx.animateTransform({
+				shape:    o.shape,
+				duration: this.duration,
+				easing:   this.easing,
+				transform: [
+					rotateBack,
+					{name: "translate", start: [startOffset, 0], end: [endOffset, 0]},
+					{name: "scaleAt",   start: [startScale, o.cx, o.cy],  end: [endScale, o.cx, o.cy]},
+					rotateTo0
+				]
+			});
+
+			if(o.type == "onmouseout"){
+				dojo.connect(anim.action, "onEnd", this, function(){
+					delete this.anim[index];
+				});
+			}
+			anim.action.play();
+		},
+
+		reset: function(){
+			delete this.angles;
+		}
+	});
 })();
-}
diff --git a/dojox/charting/action2d/Shake.js b/dojox/charting/action2d/Shake.js
index 4863b30..089f562 100644
--- a/dojox/charting/action2d/Shake.js
+++ b/dojox/charting/action2d/Shake.js
@@ -1,65 +1,111 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.action2d.Shake"]){
-dojo._hasResource["dojox.charting.action2d.Shake"]=true;
 dojo.provide("dojox.charting.action2d.Shake");
+
 dojo.require("dojox.charting.action2d.Base");
 dojo.require("dojox.gfx.matrix");
 dojo.require("dojo.fx");
-(function(){
-var _1=3,m=dojox.gfx.matrix,gf=dojox.gfx.fx;
-dojo.declare("dojox.charting.action2d.Shake",dojox.charting.action2d.Base,{defaultParams:{duration:400,easing:dojo.fx.easing.backOut,shiftX:_1,shiftY:_1},optionalParams:{},constructor:function(_2,_3,_4){
-if(!_4){
-_4={};
-}
-this.shiftX=typeof _4.shiftX=="number"?_4.shiftX:_1;
-this.shiftY=typeof _4.shiftY=="number"?_4.shiftY:_1;
-this.connect();
-},process:function(o){
-if(!o.shape||!(o.type in this.overOutEvents)){
-return;
-}
-var _5=o.run.name,_6=o.index,_7=[],_8,_9=o.type=="onmouseover"?this.shiftX:-this.shiftX,_a=o.type=="onmouseover"?this.shiftY:-this.shiftY;
-if(_5 in this.anim){
-_8=this.anim[_5][_6];
-}else{
-this.anim[_5]={};
-}
-if(_8){
-_8.action.stop(true);
-}else{
-this.anim[_5][_6]=_8={};
-}
-var _b={shape:o.shape,duration:this.duration,easing:this.easing,transform:[{name:"translate",start:[this.shiftX,this.shiftY],end:[0,0]},m.identity]};
-if(o.shape){
-_7.push(gf.animateTransform(_b));
-}
-if(o.oultine){
-_b.shape=o.outline;
-_7.push(gf.animateTransform(_b));
-}
-if(o.shadow){
-_b.shape=o.shadow;
-_7.push(gf.animateTransform(_b));
-}
-if(!_7.length){
-delete this.anim[_5][_6];
-return;
-}
-_8.action=dojo.fx.combine(_7);
-if(o.type=="onmouseout"){
-dojo.connect(_8.action,"onEnd",this,function(){
-if(this.anim[_5]){
-delete this.anim[_5][_6];
-}
+
+/*=====
+dojo.declare("dojox.charting.action2d.__ShakeCtorArgs", dojox.charting.action2d.__BaseCtorArgs, {
+	//	summary:
+	//		Additional arguments for highlighting actions.
+
+	//	shift: Number?
+	//		The amount in pixels to shift the pie slice.  Default is 3.
+	shift: 3
 });
-}
-_8.action.play();
-}});
+=====*/
+(function(){
+	var DEFAULT_SHIFT = 3,
+		m = dojox.gfx.matrix,
+		gf = dojox.gfx.fx;
+
+	dojo.declare("dojox.charting.action2d.Shake", dojox.charting.action2d.Base, {
+		//	summary:
+		//		Create a shaking action for use on an element in a chart.
+
+		// the data description block for the widget parser
+		defaultParams: {
+			duration: 400,	// duration of the action in ms
+			easing:   dojo.fx.easing.backOut,	// easing for the action
+			shiftX:   DEFAULT_SHIFT,	// shift of the element along the X axis
+			shiftY:   DEFAULT_SHIFT		// shift of the element along the Y axis
+		},
+		optionalParams: {},	// no optional parameters
+
+		constructor: function(chart, plot, kwArgs){
+			//	summary:
+			//		Create the shaking action and connect it to the plot.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this action belongs to.
+			//	plot: String?
+			//		The plot this action is attached to.  If not passed, "default" is assumed.
+			//	kwArgs: dojox.charting.action2d.__ShakeCtorArgs?
+			//		Optional keyword arguments object for setting parameters.
+			if(!kwArgs){ kwArgs = {}; }
+			this.shiftX = typeof kwArgs.shiftX == "number" ? kwArgs.shiftX : DEFAULT_SHIFT;
+			this.shiftY = typeof kwArgs.shiftY == "number" ? kwArgs.shiftY : DEFAULT_SHIFT;
+
+			this.connect();
+		},
+
+		process: function(o){
+			//	summary:
+			//		Process the action on the given object.
+			//	o: dojox.gfx.Shape
+			//		The object on which to process the slice moving action.
+			if(!o.shape || !(o.type in this.overOutEvents)){ return; }
+
+			var runName = o.run.name, index = o.index, vector = [], anim,
+				shiftX = o.type == "onmouseover" ? this.shiftX : -this.shiftX,
+				shiftY = o.type == "onmouseover" ? this.shiftY : -this.shiftY;
+
+			if(runName in this.anim){
+				anim = this.anim[runName][index];
+			}else{
+				this.anim[runName] = {};
+			}
+
+			if(anim){
+				anim.action.stop(true);
+			}else{
+				this.anim[runName][index] = anim = {};
+			}
+
+			var kwArgs = {
+				shape:     o.shape,
+				duration:  this.duration,
+				easing:    this.easing,
+				transform: [
+					{name: "translate", start: [this.shiftX, this.shiftY], end: [0, 0]},
+					m.identity
+				]
+			};
+			if(o.shape){
+				vector.push(gf.animateTransform(kwArgs));
+			}
+			if(o.oultine){
+				kwArgs.shape = o.outline;
+				vector.push(gf.animateTransform(kwArgs));
+			}
+			if(o.shadow){
+				kwArgs.shape = o.shadow;
+				vector.push(gf.animateTransform(kwArgs));
+			}
+
+			if(!vector.length){
+				delete this.anim[runName][index];
+				return;
+			}
+
+			anim.action = dojo.fx.combine(vector);
+			if(o.type == "onmouseout"){
+				dojo.connect(anim.action, "onEnd", this, function(){
+					if(this.anim[runName]){
+						delete this.anim[runName][index];
+					}
+				});
+			}
+			anim.action.play();
+		}
+	});
 })();
-}
diff --git a/dojox/charting/action2d/Tooltip.js b/dojox/charting/action2d/Tooltip.js
index 58cd265..e619e34 100644
--- a/dojox/charting/action2d/Tooltip.js
+++ b/dojox/charting/action2d/Tooltip.js
@@ -1,102 +1,323 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.action2d.Tooltip"]){
-dojo._hasResource["dojox.charting.action2d.Tooltip"]=true;
 dojo.provide("dojox.charting.action2d.Tooltip");
+
 dojo.require("dojox.charting.action2d.Base");
+dojo.require("dojox.gfx.matrix");
 dojo.require("dijit.Tooltip");
+
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.scan");
 dojo.require("dojox.lang.functional.fold");
+
+/*=====
+dojo.declare("dojox.charting.action2d.__TooltipCtorArgs", dojox.charting.action2d.__BaseCtorArgs, {
+	//	summary:
+	//		Additional arguments for tooltip actions.
+
+	//	text: Function?
+	//		The function that produces the text to be shown within a tooltip.  By default this will be 
+	//		set by the plot in question, by returning the value of the element.
+	text: null
+});
+=====*/
 (function(){
-var _1=function(o){
-var t=o.run&&o.run.data&&o.run.data[o.index];
-if(t&&typeof t!="number"&&(t.tooltip||t.text)){
-return t.tooltip||t.text;
-}
-if(o.element=="candlestick"){
-return "<table cellpadding=\"1\" cellspacing=\"0\" border=\"0\" style=\"font-size:0.9em;\">"+"<tr><td>Open:</td><td align=\"right\"><strong>"+o.data.open+"</strong></td></tr>"+"<tr><td>High:</td><td align=\"right\"><strong>"+o.data.high+"</strong></td></tr>"+"<tr><td>Low:</td><td align=\"right\"><strong>"+o.data.low+"</strong></td></tr>"+"<tr><td>Close:</td><td align=\"right\"><strong>"+o.data.close+"</strong></td></tr>"+(o.data.mid!==undefined?"<tr><td>Mid:</td><td align=\"right\"><stro [...]
-}
-return o.element=="bar"?o.x:o.y;
-};
-var df=dojox.lang.functional,_2=Math.PI/4,_3=Math.PI/2;
-dojo.declare("dojox.charting.action2d.Tooltip",dojox.charting.action2d.Base,{defaultParams:{text:_1},optionalParams:{},constructor:function(_4,_5,_6){
-this.text=_6&&_6.text?_6.text:_1;
-this.connect();
-},process:function(o){
-if(o.type==="onplotreset"||o.type==="onmouseout"){
-dijit.hideTooltip(this.aroundRect);
-this.aroundRect=null;
-return;
-}
-if(!o.shape||o.type!=="onmouseover"){
-return;
-}
-var _7={type:"rect"},_8=["after","before"];
-switch(o.element){
-case "marker":
-_7.x=o.cx;
-_7.y=o.cy;
-_7.width=_7.height=1;
-break;
-case "circle":
-_7.x=o.cx-o.cr;
-_7.y=o.cy-o.cr;
-_7.width=_7.height=2*o.cr;
-break;
-case "column":
-_8=["above","below"];
-case "bar":
-_7=dojo.clone(o.shape.getShape());
-break;
-case "candlestick":
-_7.x=o.x;
-_7.y=o.y;
-_7.width=o.width;
-_7.height=o.height;
-break;
-default:
-if(!this.angles){
-if(typeof o.run.data[0]=="number"){
-this.angles=df.map(df.scanl(o.run.data,"+",0),"* 2 * Math.PI / this",df.foldl(o.run.data,"+",0));
-}else{
-this.angles=df.map(df.scanl(o.run.data,"a + b.y",0),"* 2 * Math.PI / this",df.foldl(o.run.data,"a + b.y",0));
-}
-}
-var _9=(this.angles[o.index]+this.angles[o.index+1])/2;
-_7.x=o.cx+o.cr*Math.cos(_9);
-_7.y=o.cy+o.cr*Math.sin(_9);
-_7.width=_7.height=1;
-if(_9<_2){
-}else{
-if(_9<_3+_2){
-_8=["below","above"];
-}else{
-if(_9<Math.PI+_2){
-_8=["before","after"];
-}else{
-if(_9<2*Math.PI-_2){
-_8=["above","below"];
-}
-}
-}
-}
-break;
-}
-var lt=dojo.coords(this.chart.node,true);
-_7.x+=lt.x;
-_7.y+=lt.y;
-_7.x=Math.round(_7.x);
-_7.y=Math.round(_7.y);
-_7.width=Math.ceil(_7.width);
-_7.height=Math.ceil(_7.height);
-this.aroundRect=_7;
-dijit.showTooltip(this.text(o),this.aroundRect,_8);
-}});
+	var DEFAULT_TEXT = function(o){
+		var t = o.run && o.run.data && o.run.data[o.index];
+		if(t && typeof t != "number" && (t.tooltip || t.text)){
+			return t.tooltip || t.text;
+		}
+		if(o.element == "candlestick"){
+			return '<table cellpadding="1" cellspacing="0" border="0" style="font-size:0.9em;">'
+				+ '<tr><td>Open:</td><td align="right"><strong>' + o.data.open + '</strong></td></tr>'
+				+ '<tr><td>High:</td><td align="right"><strong>' + o.data.high + '</strong></td></tr>'
+				+ '<tr><td>Low:</td><td align="right"><strong>' + o.data.low + '</strong></td></tr>'
+				+ '<tr><td>Close:</td><td align="right"><strong>' + o.data.close + '</strong></td></tr>'
+				+ (o.data.mid !== undefined ? '<tr><td>Mid:</td><td align="right"><strong>' + o.data.mid + '</strong></td></tr>' : '')
+				+ '</table>';
+		}
+		return o.element == "bar" ? o.x : o.y;
+	};
+
+	var df = dojox.lang.functional, m = dojox.gfx.matrix, pi4 = Math.PI / 4, pi2 = Math.PI / 2;
+	
+	dojo.declare("dojox.charting.action2d.Tooltip", dojox.charting.action2d.Base, {
+		//	summary:
+		//		Create an action on a plot where a tooltip is shown when hovering over an element.
+
+		// the data description block for the widget parser
+		defaultParams: {
+			text: DEFAULT_TEXT	// the function to produce a tooltip from the object
+		},
+		optionalParams: {},	// no optional parameters
+
+		constructor: function(chart, plot, kwArgs){
+			//	summary:
+			//		Create the tooltip action and connect it to the plot.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this action belongs to.
+			//	plot: String?
+			//		The plot this action is attached to.  If not passed, "default" is assumed.
+			//	kwArgs: dojox.charting.action2d.__TooltipCtorArgs?
+			//		Optional keyword arguments object for setting parameters.
+			this.text = kwArgs && kwArgs.text ? kwArgs.text : DEFAULT_TEXT;
+			
+			this.connect();
+		},
+		
+		process: function(o){
+			//	summary:
+			//		Process the action on the given object.
+			//	o: dojox.gfx.Shape
+			//		The object on which to process the highlighting action.
+			if(o.type === "onplotreset" || o.type === "onmouseout"){
+				hideChartingTooltip(this.aroundRect);
+				this.aroundRect = null;
+				return;
+			}
+			
+			if(!o.shape || o.type !== "onmouseover"){ return; }
+			
+			// calculate relative coordinates and the position
+			var aroundRect = {type: "rect"}, position = ["after", "before"];
+			switch(o.element){
+				case "marker":
+					aroundRect.x = o.cx;
+					aroundRect.y = o.cy;
+					aroundRect.width = aroundRect.height = 1;
+					break;
+				case "circle":
+					aroundRect.x = o.cx - o.cr;
+					aroundRect.y = o.cy - o.cr;
+					aroundRect.width = aroundRect.height = 2 * o.cr;
+					break;
+				case "column":
+					position = ["above", "below"];
+					// intentional fall down
+				case "bar":
+					aroundRect = dojo.clone(o.shape.getShape());
+					break;
+				case "candlestick":
+					aroundRect.x = o.x;
+					aroundRect.y = o.y;
+					aroundRect.width = o.width;
+					aroundRect.height = o.height;
+					break;
+				default:
+				//case "slice":
+					if(!this.angles){
+						// calculate the running total of slice angles
+						if(typeof o.run.data[0] == "number"){
+							this.angles = df.map(df.scanl(o.run.data, "+", 0),
+								"* 2 * Math.PI / this", df.foldl(o.run.data, "+", 0));
+						}else{
+							this.angles = df.map(df.scanl(o.run.data, "a + b.y", 0),
+								"* 2 * Math.PI / this", df.foldl(o.run.data, "a + b.y", 0));
+						}
+					}
+					var startAngle = m._degToRad(o.plot.opt.startAngle),
+						angle = (this.angles[o.index] + this.angles[o.index + 1]) / 2 + startAngle;
+					aroundRect.x = o.cx + o.cr * Math.cos(angle);
+					aroundRect.y = o.cy + o.cr * Math.sin(angle);
+					aroundRect.width = aroundRect.height = 1;
+					// calculate the position
+					if(angle < pi4){
+						// do nothing: the position is right
+					}else if(angle < pi2 + pi4){
+						position = ["below", "above"];
+					}else if(angle < Math.PI + pi4){
+						position = ["before", "after"];
+					}else if(angle < 2 * Math.PI - pi4){
+						position = ["above", "below"];
+					}
+					/*
+					else{
+						// do nothing: the position is right
+					}
+					*/
+					break;
+			}
+			
+			// adjust relative coordinates to absolute, and remove fractions
+			var lt = dojo.coords(this.chart.node, true);
+			aroundRect.x += lt.x;
+			aroundRect.y += lt.y;
+			aroundRect.x = Math.round(aroundRect.x);
+			aroundRect.y = Math.round(aroundRect.y);
+			aroundRect.width = Math.ceil(aroundRect.width);
+			aroundRect.height = Math.ceil(aroundRect.height);
+			this.aroundRect = aroundRect;
+			
+			showChartingTooltip(this.text(o), this.aroundRect, position, "center");
+		}
+	});
+	
+	//TODO: make the charting tooltip a generic one so it can be used with
+	// dojox.gfx shapes without charting.
+	
+	var MasterTooltip = dojo.declare(dijit._MasterTooltip, {
+		
+		show: function(/*String*/ innerHTML, /*DomNode*/ aroundNode, /*String[]?*/ position, /*String*/alignment){
+			// 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)
+			// alignment: String
+			//		"center":   tooltip center alignment
+			//      "default":  tooltip default alignment (left, right, top, bottom)
+
+			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";
+			
+			if(!this.connectorNode) this.connectorNode = dojo.query(".dijitTooltipConnector", this.domNode)[0];
+			var connectorPos = dojo.coords(this.connectorNode);
+			this.arrowWidth = connectorPos.w, this.arrowHeight = connectorPos.h;
+			this.place = (alignment && alignment == "center") ? this.placeChartingTooltip : dijit.placeOnScreenAroundElement,
+			this.place(
+				this.domNode,
+				aroundNode,
+				dijit.getPopupAroundAlignment(
+					(position && position.length) ? position : dijit.Tooltip.defaultPosition,
+					this.isLeftToRight()
+				),
+				dojo.hitch(this, "orient")
+			);
+
+			// show it
+			dojo.style(this.domNode, "opacity", 0);
+			this.fadeIn.play();
+			this.isShowingNow = true;
+			this.aroundNode = aroundNode;
+		},
+		
+		placeChartingTooltip: function(node, aroundRect, aroundCorners, layoutNode){
+			return this._placeOnScreenAroundRect(node, 
+				aroundRect.x, aroundRect.y, aroundRect.width, aroundRect.height,	// rectangle
+				aroundCorners, layoutNode);
+		},
+		
+		_placeOnScreenAroundRect: function(node, x, y, width, height, aroundCorners, layoutNode){
+			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),
+		                w: width,
+		                h: height
+		            }
+		        });
+		    }
+		    return this._place(node, choices, layoutNode);
+		},
+		
+		_place: function(/* DomNode */node, /* Array */ choices, /* Function */ layoutNode){
+		    var view = dijit.getViewport();
+		    
+		    if (!node.parentNode ||
+		    String(node.parentNode.tagName).toLowerCase() != "body") {
+		        dojo.body().appendChild(node);
+		    }
+		    
+		    var best = null;
+		    
+		    var arrowLeft = null, arrowTop = null;
+		    dojo.some(choices, function(choice){
+		        var corner = choice.corner;
+		        var aroundCorner = choice.aroundCorner;
+		        var pos = choice.pos;
+		        
+		        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;
+		        
+		        var startX, startY, endX, endY, width, height, overflow;
+		        
+		        arrowLeft = null, arrowTop = null;
+		        if (aroundCorner.charAt(0) == corner.charAt(0)) { //left, right
+		            startX = (corner.charAt(1) == 'L' ? pos.x : Math.max(view.l, pos.x - mb.w)), 
+					startY = (corner.charAt(0) == 'T' ? (pos.y + pos.h / 2 - mb.h / 2) : (pos.y - pos.h / 2 - mb.h / 2)), 
+					endX = (corner.charAt(1) == 'L' ? Math.min(view.l + view.w, startX + mb.w) : pos.x), 
+					endY = startY + mb.h, 
+					width = endX - startX, 
+					height = endY - startY, 
+					overflow = (mb.w - width) + (mb.h - height);
+		            arrowTop = (mb.h - this.arrowHeight) / 2;
+		        }
+		        else { //top, bottom
+		            startX = (corner.charAt(1) == 'L' ? (pos.x + pos.w / 2 - mb.w / 2) : (pos.x - pos.w / 2 - mb.w / 2)), 
+					startY = (corner.charAt(0) == 'T' ? pos.y : Math.max(view.t, pos.y - mb.h)), 
+					endX = startX + mb.w, 
+					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);
+		            arrowLeft = (mb.w - this.arrowWidth) / 2;
+		        }
+		        
+		        if (best == null || overflow < best.overflow) {
+		            best = {
+		                corner: corner,
+		                aroundCorner: choice.aroundCorner,
+		                x: startX,
+		                y: startY,
+		                w: width,
+		                h: height,
+		                overflow: overflow
+		            };
+		        }
+		        return !overflow;
+		    }, this);
+		    
+		    node.style.left = best.x + "px";
+		    node.style.top = best.y + "px";
+		    
+			this.connectorNode.style.top = "";
+	        this.connectorNode.style.left = "";
+	        if (arrowTop){
+				this.connectorNode.style.top = arrowTop + "px";
+			}
+	        if (arrowLeft){
+				this.connectorNode.style.left = arrowLeft + "px";
+			}
+	        
+		    if (best.overflow && layoutNode) {
+		        layoutNode(node, best.aroundCorner, best.corner);
+		    }
+		    return best;
+		}
+	});
+	
+	var masterTT = null;
+	
+	function showChartingTooltip(innerHTML, aroundNode, position, alignment){
+		if(!masterTT){ masterTT = new MasterTooltip(); }
+		return masterTT.show(innerHTML, aroundNode, position, alignment);
+	}
+	
+	function hideChartingTooltip(aroundNode){
+		if(!masterTT){ masterTT = new MasterTooltip(); }
+		return masterTT.hide(aroundNode);
+	}
 })();
-}
diff --git a/dojox/charting/axis2d/Base.js b/dojox/charting/axis2d/Base.js
index f03e903..53c3679 100644
--- a/dojox/charting/axis2d/Base.js
+++ b/dojox/charting/axis2d/Base.js
@@ -1,29 +1,69 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.axis2d.Base"]){
-dojo._hasResource["dojox.charting.axis2d.Base"]=true;
 dojo.provide("dojox.charting.axis2d.Base");
+
 dojo.require("dojox.charting.Element");
-dojo.declare("dojox.charting.axis2d.Base",dojox.charting.Element,{constructor:function(_1,_2){
-this.vertical=_2&&_2.vertical;
-},clear:function(){
-return this;
-},initialized:function(){
-return false;
-},calculate:function(_3,_4,_5){
-return this;
-},getScaler:function(){
-return null;
-},getTicks:function(){
-return null;
-},getOffsets:function(){
-return {l:0,r:0,t:0,b:0};
-},render:function(_6,_7){
-return this;
-}});
-}
+
+dojo.declare("dojox.charting.axis2d.Base", dojox.charting.Element, {
+	//	summary:
+	//		The base class for any axis.  This is more of an interface/API
+	//		definition than anything else; see dojox.charting.axis2d.Default
+	//		for more details.
+	constructor: function(chart, kwArgs){
+		//	summary:
+		//		Return a new base axis.
+		//	chart: dojox.charting.Chart2D
+		//		The chart this axis belongs to.
+		//	kwArgs: dojox.charting.axis2d.__AxisCtorArgs?
+		//		An optional arguments object to define the axis parameters.
+		this.vertical = kwArgs && kwArgs.vertical;
+	},
+	clear: function(){
+		//	summary:
+		//		Stub function for clearing the axis.
+		//	returns: dojox.charting.axis2d.Base
+		//		A reference to the axis for functional chaining.
+		return this;	//	dojox.charting.axis2d.Base
+	},
+	initialized: function(){
+		//	summary:
+		//		Return a flag as to whether or not this axis has been initialized.
+		//	returns: Boolean
+		//		If the axis is initialized or not.
+		return false;	//	Boolean
+	},
+	calculate: function(min, max, span){
+		//	summary:
+		//		Stub function to run the calcuations needed for drawing this axis.
+		//	returns: dojox.charting.axis2d.Base
+		//		A reference to the axis for functional chaining.
+		return this;	//	dojox.charting.axis2d.Base
+	},
+	getScaler: function(){
+		//	summary:
+		//		A stub function to return the scaler object created during calculate.
+		//	returns: Object
+		//		The scaler object (see dojox.charting.scaler.linear for more information)
+		return null;	//	Object
+	},
+	getTicks: function(){
+		//	summary:
+		//		A stub function to return the object that helps define how ticks are rendered.
+		//	returns: Object
+		//		The ticks object.
+		return null;	//	Object
+	},
+	getOffsets: function(){
+		//	summary:
+		//		A stub function to return any offsets needed for axis and series rendering.
+		//	returns: Object
+		//		An object of the form { l, r, t, b }.
+		return {l: 0, r: 0, t: 0, b: 0};	//	Object
+	},
+	render: function(dim, offsets){
+		//	summary:
+		//		Stub function to render this axis.
+		//	returns: dojox.charting.axis2d.Base
+		//		A reference to the axis for functional chaining.
+		this.dirty = false;
+		return this;	//	dojox.charting.axis2d.Base
+	}
+});
diff --git a/dojox/charting/axis2d/Default.js b/dojox/charting/axis2d/Default.js
index 45a975c..894bd54 100644
--- a/dojox/charting/axis2d/Default.js
+++ b/dojox/charting/axis2d/Default.js
@@ -1,245 +1,596 @@
-/*
-	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
-*/
+dojo.provide("dojox.charting.axis2d.Default");
 
+dojo.require("dojox.charting.axis2d.Invisible");
 
-if(!dojo._hasResource["dojox.charting.axis2d.Default"]){
-dojo._hasResource["dojox.charting.axis2d.Default"]=true;
-dojo.provide("dojox.charting.axis2d.Default");
 dojo.require("dojox.charting.scaler.linear");
 dojo.require("dojox.charting.axis2d.common");
-dojo.require("dojox.charting.axis2d.Base");
+
 dojo.require("dojo.colors");
 dojo.require("dojo.string");
 dojo.require("dojox.gfx");
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.utils");
+
+/*=====
+	dojox.charting.axis2d.__AxisCtorArgs = function(
+		vertical, fixUpper, fixLower, natural, leftBottom,
+		includeZero, fixed, majorLabels, minorTicks, minorLabels, microTicks, htmlLabels,
+		min, max, from, to, majorTickStep, minorTickStep, microTickStep,
+		labels, labelFunc, maxLabelSize,
+		stroke, majorTick, minorTick, microTick, tick,
+		font, fontColor
+	){
+	//	summary:
+	//		Optional arguments used in the definition of an axis.
+	//
+	//	vertical: Boolean?
+	//		A flag that says whether an axis is vertical (i.e. y axis) or horizontal. Default is false (horizontal).
+	//	fixUpper: String?
+	//		Align the greatest value on the axis with the specified tick level. Options are "major", "minor", "micro", or "none".  Defaults to "none".
+	//	fixLower: String?
+	//		Align the smallest value on the axis with the specified tick level. Options are "major", "minor", "micro", or "none".  Defaults to "none".
+	//	natural: Boolean?
+	//		Ensure tick marks are made on "natural" numbers. Defaults to false.
+	//	leftBottom: Boolean?
+	//		The position of a vertical axis; if true, will be placed against the left-bottom corner of the chart.  Defaults to true.
+	//	includeZero: Boolean?
+	//		Include 0 on the axis rendering.  Default is false.
+	//	fixed: Boolean?
+	//		Force all axis labels to be fixed numbers.  Default is true.
+	//	majorLabels: Boolean?
+	//		Flag to draw all labels at major ticks. Default is true.
+	//	minorTicks: Boolean?
+	//		Flag to draw minor ticks on an axis.  Default is true.
+	//	minorLabels: Boolean?
+	//		Flag to draw labels on minor ticks. Default is true.
+	//	microTicks: Boolean?
+	//		Flag to draw micro ticks on an axis. Default is false.
+	//	htmlLabels: Boolean?
+	//		Flag to use HTML (as opposed to the native vector graphics engine) to draw labels. Default is true.
+	//	min: Number?
+	//		The smallest value on an axis. Default is 0.
+	//	max: Number?
+	//		The largest value on an axis. Default is 1.
+	//	from: Number?
+	//		Force the chart to render data visible from this value. Default is 0.
+	//	to: Number?
+	//		Force the chart to render data visible to this value. Default is 1.
+	//	majorTickStep: Number?
+	//		The amount to skip before a major tick is drawn.  Default is 4.
+	//	minorTickStep: Number?
+	//		The amount to skip before a minor tick is drawn. Default is 2.
+	//	microTickStep: Number?
+	//		The amount to skip before a micro tick is drawn. Default is 1.
+	//	labels: Object[]?
+	//		An array of labels for major ticks, with corresponding numeric values, ordered by value.
+	//	labelFunc: Function?
+	//		An optional function used to compute label values.
+	//	maxLabelSize: Number?
+	//		The maximum size, in pixels, for a label.  To be used with the optional label function.
+	//	stroke: dojox.gfx.Stroke?
+	//		An optional stroke to be used for drawing an axis.
+	//	majorTick: Object?
+	//		An object containing a dojox.gfx.Stroke, and a length (number) for a major tick.
+	//	minorTick: Object?
+	//		An object containing a dojox.gfx.Stroke, and a length (number) for a minor tick.
+	//	microTick: Object?
+	//		An object containing a dojox.gfx.Stroke, and a length (number) for a micro tick.
+	//	tick: Object?
+	//		An object containing a dojox.gfx.Stroke, and a length (number) for a tick.
+	//	font: String?
+	//		An optional font definition (as used in the CSS font property) for labels.
+	//	fontColor: String|dojo.Color?
+	//		An optional color to be used in drawing labels.
+
+	this.vertical = vertical;
+	this.fixUpper = fixUpper;
+	this.fixLower = fixLower;
+	this.natural = natural;
+	this.leftBottom = leftBottom;
+	this.includeZero = includeZero;
+	this.fixed = fixed;
+	this.majorLabels = majorLabels;
+	this.minorTicks = minorTicks;
+	this.minorLabels = minorLabels;
+	this.microTicks = microTicks;
+	this.htmlLabels = htmlLabels;
+	this.min = min;
+	this.max = max;
+	this.from = from;
+	this.to = to;
+	this.majorTickStep = majorTickStep;
+	this.minorTickStep = minorTickStep;
+	this.microTickStep = microTickStep;
+	this.labels = labels;
+	this.labelFunc = labelFunc;
+	this.maxLabelSize = maxLabelSize;
+	this.stroke = stroke;
+	this.majorTick = majorTick;
+	this.minorTick = minorTick;
+	this.microTick = microTick;
+	this.tick = tick;
+	this.font = font;
+	this.fontColor = fontColor;
+}
+=====*/
 (function(){
-var dc=dojox.charting,df=dojox.lang.functional,du=dojox.lang.utils,g=dojox.gfx,_1=dc.scaler.linear,_2=4;
-dojo.declare("dojox.charting.axis2d.Default",dojox.charting.axis2d.Base,{defaultParams:{vertical:false,fixUpper:"none",fixLower:"none",natural:false,leftBottom:true,includeZero:false,fixed:true,majorLabels:true,minorTicks:true,minorLabels:true,microTicks:false,htmlLabels:true},optionalParams:{min:0,max:1,from:0,to:1,majorTickStep:4,minorTickStep:2,microTickStep:1,labels:[],labelFunc:null,maxLabelSize:0,stroke:{},majorTick:{},minorTick:{},microTick:{},font:"",fontColor:""},constructor:fun [...]
-this.opt=dojo.delegate(this.defaultParams,_4);
-du.updateWithPattern(this.opt,_4,this.optionalParams);
-},dependOnData:function(){
-return !("min" in this.opt)||!("max" in this.opt);
-},clear:function(){
-delete this.scaler;
-delete this.ticks;
-this.dirty=true;
-return this;
-},initialized:function(){
-return "scaler" in this&&!(this.dirty&&this.dependOnData());
-},setWindow:function(_5,_6){
-this.scale=_5;
-this.offset=_6;
-return this.clear();
-},getWindowScale:function(){
-return "scale" in this?this.scale:1;
-},getWindowOffset:function(){
-return "offset" in this?this.offset:0;
-},_groupLabelWidth:function(_7,_8){
-if(_7[0]["text"]){
-_7=df.map(_7,function(_9){
-return _9.text;
-});
-}
-var s=_7.join("<br>");
-return dojox.gfx._base._getTextBox(s,{font:_8}).w||0;
-},calculate:function(_a,_b,_c,_d){
-if(this.initialized()){
-return this;
-}
-var o=this.opt;
-this.labels="labels" in o?o.labels:_d;
-this.scaler=_1.buildScaler(_a,_b,_c,o);
-var _e=this.scaler.bounds;
-if("scale" in this){
-o.from=_e.lower+this.offset;
-o.to=(_e.upper-_e.lower)/this.scale+o.from;
-if(!isFinite(o.from)||isNaN(o.from)||!isFinite(o.to)||isNaN(o.to)||o.to-o.from>=_e.upper-_e.lower){
-delete o.from;
-delete o.to;
-delete this.scale;
-delete this.offset;
-}else{
-if(o.from<_e.lower){
-o.to+=_e.lower-o.from;
-o.from=_e.lower;
-}else{
-if(o.to>_e.upper){
-o.from+=_e.upper-o.to;
-o.to=_e.upper;
-}
-}
-this.offset=o.from-_e.lower;
-}
-this.scaler=_1.buildScaler(_a,_b,_c,o);
-_e=this.scaler.bounds;
-if(this.scale==1&&this.offset==0){
-delete this.scale;
-delete this.offset;
-}
-}
-var _f=0,ta=this.chart.theme.axis,_10="font" in o?o.font:ta.font,_11=_10?g.normalizedLength(g.splitFontString(_10).size):0;
-if(this.vertical){
-if(_11){
-_f=_11+_2;
-}
-}else{
-if(_11){
-var _12,i;
-if(o.labelFunc&&o.maxLabelSize){
-_12=o.maxLabelSize;
-}else{
-if(this.labels){
-_12=this._groupLabelWidth(this.labels,_10);
-}else{
-var _13=Math.ceil(Math.log(Math.max(Math.abs(_e.from),Math.abs(_e.to)))/Math.LN10),t=[];
-if(_e.from<0||_e.to<0){
-t.push("-");
-}
-t.push(dojo.string.rep("9",_13));
-var _14=Math.floor(Math.log(_e.to-_e.from)/Math.LN10);
-if(_14>0){
-t.push(".");
-for(i=0;i<_14;++i){
-t.push("9");
-}
-}
-_12=dojox.gfx._base._getTextBox(t.join(""),{font:_10}).w;
-}
-}
-_f=_12+_2;
-}
-}
-this.scaler.minMinorStep=_f;
-this.ticks=_1.buildTicks(this.scaler,o);
-return this;
-},getScaler:function(){
-return this.scaler;
-},getTicks:function(){
-return this.ticks;
-},getOffsets:function(){
-var o=this.opt;
-var _15={l:0,r:0,t:0,b:0},_16,a,b,c,d,gl=dc.scaler.common.getNumericLabel,_17=0,ta=this.chart.theme.axis,_18="font" in o?o.font:ta.font,_19="majorTick" in o?o.majorTick:ta.majorTick,_1a="minorTick" in o?o.minorTick:ta.minorTick,_1b=_18?g.normalizedLength(g.splitFontString(_18).size):0,s=this.scaler;
-if(!s){
-return _15;
-}
-var ma=s.major,mi=s.minor;
-if(this.vertical){
-if(_1b){
-if(o.labelFunc&&o.maxLabelSize){
-_16=o.maxLabelSize;
-}else{
-if(this.labels){
-_16=this._groupLabelWidth(this.labels,_18);
-}else{
-_16=this._groupLabelWidth([gl(ma.start,ma.prec,o),gl(ma.start+ma.count*ma.tick,ma.prec,o),gl(mi.start,mi.prec,o),gl(mi.start+mi.count*mi.tick,mi.prec,o)],_18);
-}
-}
-_17=_16+_2;
-}
-_17+=_2+Math.max(_19.length,_1a.length);
-_15[o.leftBottom?"l":"r"]=_17;
-_15.t=_15.b=_1b/2;
-}else{
-if(_1b){
-_17=_1b+_2;
-}
-_17+=_2+Math.max(_19.length,_1a.length);
-_15[o.leftBottom?"b":"t"]=_17;
-if(_1b){
-if(o.labelFunc&&o.maxLabelSize){
-_16=o.maxLabelSize;
-}else{
-if(this.labels){
-_16=this._groupLabelWidth(this.labels,_18);
-}else{
-_16=this._groupLabelWidth([gl(ma.start,ma.prec,o),gl(ma.start+ma.count*ma.tick,ma.prec,o),gl(mi.start,mi.prec,o),gl(mi.start+mi.count*mi.tick,mi.prec,o)],_18);
-}
-}
-_15.l=_15.r=_16/2;
-}
-}
-if(_16){
-this._cachedLabelWidth=_16;
-}
-return _15;
-},render:function(dim,_1c){
-if(!this.dirty){
-return this;
-}
-var o=this.opt;
-var _1d,_1e,_1f,_20,_21,_22,ta=this.chart.theme.axis,_23="stroke" in o?o.stroke:ta.stroke,_24="majorTick" in o?o.majorTick:ta.majorTick,_25="minorTick" in o?o.minorTick:ta.minorTick,_26="microTick" in o?o.microTick:ta.minorTick,_27="font" in o?o.font:ta.font,_28="fontColor" in o?o.fontColor:ta.fontColor,_29=Math.max(_24.length,_25.length),_2a=_27?g.normalizedLength(g.splitFontString(_27).size):0;
-if(this.vertical){
-_1d={y:dim.height-_1c.b};
-_1e={y:_1c.t};
-_1f={x:0,y:-1};
-if(o.leftBottom){
-_1d.x=_1e.x=_1c.l;
-_20={x:-1,y:0};
-_22="end";
-}else{
-_1d.x=_1e.x=dim.width-_1c.r;
-_20={x:1,y:0};
-_22="start";
-}
-_21={x:_20.x*(_29+_2),y:_2a*0.4};
-}else{
-_1d={x:_1c.l};
-_1e={x:dim.width-_1c.r};
-_1f={x:1,y:0};
-_22="middle";
-if(o.leftBottom){
-_1d.y=_1e.y=dim.height-_1c.b;
-_20={x:0,y:1};
-_21={y:_29+_2+_2a};
-}else{
-_1d.y=_1e.y=_1c.t;
-_20={x:0,y:-1};
-_21={y:-_29-_2};
-}
-_21.x=0;
-}
-this.cleanGroup();
-try{
-var s=this.group,c=this.scaler,t=this.ticks,_2b,f=_1.getTransformerFromModel(this.scaler),_2c=(dojox.gfx.renderer=="canvas"),_2d=_2c||this.opt.htmlLabels&&!dojo.isIE&&!dojo.isOpera?"html":"gfx",dx=_20.x*_24.length,dy=_20.y*_24.length;
-s.createLine({x1:_1d.x,y1:_1d.y,x2:_1e.x,y2:_1e.y}).setStroke(_23);
-dojo.forEach(t.major,function(_2e){
-var _2f=f(_2e.value),_30,x=_1d.x+_1f.x*_2f,y=_1d.y+_1f.y*_2f;
-s.createLine({x1:x,y1:y,x2:x+dx,y2:y+dy}).setStroke(_24);
-if(_2e.label){
-_30=dc.axis2d.common.createText[_2d](this.chart,s,x+_21.x,y+_21.y,_22,_2e.label,_27,_28,this._cachedLabelWidth);
-if(_2d=="html"){
-this.htmlElements.push(_30);
-}
-}
-},this);
-dx=_20.x*_25.length;
-dy=_20.y*_25.length;
-_2b=c.minMinorStep<=c.minor.tick*c.bounds.scale;
-dojo.forEach(t.minor,function(_31){
-var _32=f(_31.value),_33,x=_1d.x+_1f.x*_32,y=_1d.y+_1f.y*_32;
-s.createLine({x1:x,y1:y,x2:x+dx,y2:y+dy}).setStroke(_25);
-if(_2b&&_31.label){
-_33=dc.axis2d.common.createText[_2d](this.chart,s,x+_21.x,y+_21.y,_22,_31.label,_27,_28,this._cachedLabelWidth);
-if(_2d=="html"){
-this.htmlElements.push(_33);
-}
-}
-},this);
-dx=_20.x*_26.length;
-dy=_20.y*_26.length;
-dojo.forEach(t.micro,function(_34){
-var _35=f(_34.value),_36,x=_1d.x+_1f.x*_35,y=_1d.y+_1f.y*_35;
-s.createLine({x1:x,y1:y,x2:x+dx,y2:y+dy}).setStroke(_26);
-},this);
-}
-catch(e){
-}
-this.dirty=false;
-return this;
-}});
+	var dc = dojox.charting,
+		du = dojox.lang.utils,
+		g = dojox.gfx,
+		lin = dc.scaler.linear,
+		labelGap = 4,			// in pixels
+		centerAnchorLimit = 45;	// in degrees
+
+	dojo.declare("dojox.charting.axis2d.Default", dojox.charting.axis2d.Invisible, {
+		//	summary:
+		//		The default axis object used in dojox.charting.  See dojox.charting.Chart2D.addAxis for details.
+		//
+		//	defaultParams: Object
+		//		The default parameters used to define any axis.
+		//	optionalParams: Object
+		//		Any optional parameters needed to define an axis.
+
+		/*
+		//	TODO: the documentation tools need these to be pre-defined in order to pick them up
+		//	correctly, but the code here is partially predicated on whether or not the properties
+		//	actually exist.  For now, we will leave these undocumented but in the code for later. -- TRT
+
+		//	opt: Object
+		//		The actual options used to define this axis, created at initialization.
+		//	scalar: Object
+		//		The calculated helper object to tell charts how to draw an axis and any data.
+		//	ticks: Object
+		//		The calculated tick object that helps a chart draw the scaling on an axis.
+		//	dirty: Boolean
+		//		The state of the axis (whether it needs to be redrawn or not)
+		//	scale: Number
+		//		The current scale of the axis.
+		//	offset: Number
+		//		The current offset of the axis.
+
+		opt: null,
+		scalar: null,
+		ticks: null,
+		dirty: true,
+		scale: 1,
+		offset: 0,
+		*/
+		defaultParams: {
+			vertical:    false,		// true for vertical axis
+			fixUpper:    "none",	// align the upper on ticks: "major", "minor", "micro", "none"
+			fixLower:    "none",	// align the lower on ticks: "major", "minor", "micro", "none"
+			natural:     false,		// all tick marks should be made on natural numbers
+			leftBottom:  true,		// position of the axis, used with "vertical"
+			includeZero: false,		// 0 should be included
+			fixed:       true,		// all labels are fixed numbers
+			majorLabels: true,		// draw major labels
+			minorTicks:  true,		// draw minor ticks
+			minorLabels: true,		// draw minor labels
+			microTicks:  false,		// draw micro ticks
+			rotation:    0,			// label rotation angle in degrees
+			htmlLabels:  true		// use HTML to draw labels
+		},
+		optionalParams: {
+			min:			0,	// minimal value on this axis
+			max:			1,	// maximal value on this axis
+			from:			0,	// visible from this value
+			to:				1,	// visible to this value
+			majorTickStep:	4,	// major tick step
+			minorTickStep:	2,	// minor tick step
+			microTickStep:	1,	// micro tick step
+			labels:			[],	// array of labels for major ticks
+								// with corresponding numeric values
+								// ordered by values
+			labelFunc:		null, // function to compute label values
+			maxLabelSize:	0,	// size in px. For use with labelFunc
+
+			// TODO: add support for minRange!
+			// minRange:		1,	// smallest distance from min allowed on the axis
+
+			// theme components
+			stroke:			{},	// stroke for an axis
+			majorTick:		{},	// stroke + length for a tick
+			minorTick:		{},	// stroke + length for a tick
+			microTick:		{},	// stroke + length for a tick
+			tick:           {},	// stroke + length for a tick
+			font:			"",	// font for labels
+			fontColor:		""	// color for labels as a string
+		},
+
+		constructor: function(chart, kwArgs){
+			//	summary:
+			//		The constructor for an axis.
+			//	chart: dojox.charting.Chart2D
+			//		The chart the axis belongs to.
+			//	kwArgs: dojox.charting.axis2d.__AxisCtorArgs?
+			//		Any optional keyword arguments to be used to define this axis.
+			this.opt = dojo.delegate(this.defaultParams, kwArgs);
+			// du.updateWithObject(this.opt, kwArgs);
+			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
+		},
+		getOffsets: function(){
+			//	summary:
+			//		Get the physical offset values for this axis (used in drawing data series).
+			//	returns: Object
+			//		The calculated offsets in the form of { l, r, t, b } (left, right, top, bottom).
+			var s = this.scaler, offsets = { l: 0, r: 0, t: 0, b: 0 };
+			if(!s){
+				return offsets;
+			}
+			var o = this.opt, labelWidth = 0, a, b, c, d,
+				gl = dc.scaler.common.getNumericLabel,
+				offset = 0, ma = s.major, mi = s.minor,
+				ta = this.chart.theme.axis,
+				// TODO: we use one font --- of major tick, we need to use major and minor fonts
+				taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font),
+				taMajorTick = this.chart.theme.getTick("major", o),
+				taMinorTick = this.chart.theme.getTick("minor", o),
+				size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
+				rotation = o.rotation % 360, leftBottom = o.leftBottom,
+				cosr = Math.abs(Math.cos(rotation * Math.PI / 180)),
+				sinr = Math.abs(Math.sin(rotation * Math.PI / 180));
+			if(rotation < 0){
+				rotation += 360;
+			}
+
+			if(size){
+				// we need width of all labels
+				if(o.maxLabelSize){
+					labelWidth = o.maxLabelSize;
+				}else if(this.labels){
+					labelWidth = this._groupLabelWidth(this.labels, taFont);
+				}else{
+					labelWidth = this._groupLabelWidth([
+						gl(ma.start, ma.prec, o),
+						gl(ma.start + ma.count * ma.tick, ma.prec, o),
+						gl(mi.start, mi.prec, o),
+						gl(mi.start + mi.count * mi.tick, mi.prec, o)
+					], taFont);
+				}
+				if(this.vertical){
+					var side = leftBottom ? "l" : "r";
+					switch(rotation){
+						case 0:
+						case 180:
+							offsets[side] = labelWidth;
+							offsets.t = offsets.b = size / 2;
+							break;
+						case 90:
+						case 270:
+							offsets[side] = size;
+							offsets.t = offsets.b = labelWidth / 2;
+							break;
+						default:
+							if(rotation <= centerAnchorLimit || (180 < rotation && rotation <= (180 + centerAnchorLimit))){
+								offsets[side] = size * sinr / 2 + labelWidth * cosr;
+								offsets[leftBottom ? "t" : "b"] = size * cosr / 2 + labelWidth * sinr;
+								offsets[leftBottom ? "b" : "t"] = size * cosr / 2;
+							}else if(rotation > (360 - centerAnchorLimit) || (180 > rotation && rotation > (180 - centerAnchorLimit))){
+								offsets[side] = size * sinr / 2 + labelWidth * cosr;
+								offsets[leftBottom ? "b" : "t"] = size * cosr / 2 + labelWidth * sinr;
+								offsets[leftBottom ? "t" : "b"] = size * cosr / 2;
+							}else if(rotation < 90 || (180 < rotation && rotation < 270)){
+								offsets[side] = size * sinr + labelWidth * cosr;
+								offsets[leftBottom ? "t" : "b"] = size * cosr + labelWidth * sinr;
+							}else{
+								offsets[side] = size * sinr + labelWidth * cosr;
+								offsets[leftBottom ? "b" : "t"] = size * cosr + labelWidth * sinr;
+							}
+							break;
+					}
+					offsets[side] += labelGap + Math.max(taMajorTick.length, taMinorTick.length);
+				}else{
+					var side = leftBottom ? "b" : "t";
+					switch(rotation){
+						case 0:
+						case 180:
+							offsets[side] = size;
+							offsets.l = offsets.r = labelWidth / 2;
+							break;
+						case 90:
+						case 270:
+							offsets[side] = labelWidth;
+							offsets.l = offsets.r = size / 2;
+							break;
+						default:
+							if((90 - centerAnchorLimit) <= rotation && rotation <= 90 || (270 - centerAnchorLimit) <= rotation && rotation <= 270){
+								offsets[side] = size * sinr / 2 + labelWidth * cosr;
+								offsets[leftBottom ? "r" : "l"] = size * cosr / 2 + labelWidth * sinr;
+								offsets[leftBottom ? "l" : "r"] = size * cosr / 2;
+							}else if(90 <= rotation && rotation <= (90 + centerAnchorLimit) || 270 <= rotation && rotation <= (270 + centerAnchorLimit)){
+								offsets[side] = size * sinr / 2 + labelWidth * cosr;
+								offsets[leftBottom ? "l" : "r"] = size * cosr / 2 + labelWidth * sinr;
+								offsets[leftBottom ? "r" : "l"] = size * cosr / 2;
+							}else if(rotation < centerAnchorLimit || (180 < rotation && rotation < (180 - centerAnchorLimit))){
+								offsets[side] = size * sinr + labelWidth * cosr;
+								offsets[leftBottom ? "r" : "l"] = size * cosr + labelWidth * sinr;
+							}else{
+								offsets[side] = size * sinr + labelWidth * cosr;
+								offsets[leftBottom ? "l" : "r"] = size * cosr + labelWidth * sinr;
+							}
+							break;
+					}
+					offsets[side] += labelGap + Math.max(taMajorTick.length, taMinorTick.length);
+				}
+			}
+			if(labelWidth){
+				this._cachedLabelWidth = labelWidth;
+			}
+			return offsets;	//	Object
+		},
+		render: function(dim, offsets){
+			//	summary:
+			//		Render/draw the axis.
+			//	dim: Object
+			//		An object of the form { width, height}.
+			//	offsets: Object
+			//		An object of the form { l, r, t, b }.
+			//	returns: dojox.charting.axis2d.Default
+			//		The reference to the axis for functional chaining.
+			if(!this.dirty){
+				return this;	//	dojox.charting.axis2d.Default
+			}
+			// prepare variable
+			var o = this.opt, ta = this.chart.theme.axis, leftBottom = o.leftBottom, rotation = o.rotation % 360,
+				start, stop, axisVector, tickVector, anchorOffset, labelOffset, labelAlign,
+
+				// TODO: we use one font --- of major tick, we need to use major and minor fonts
+				taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font),
+				// TODO: we use one font color --- we need to use different colors
+				taFontColor = o.fontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) || "black",
+				taMajorTick = this.chart.theme.getTick("major", o),
+				taMinorTick = this.chart.theme.getTick("minor", o),
+				taMicroTick = this.chart.theme.getTick("micro", o),
+
+				tickSize = Math.max(taMajorTick.length, taMinorTick.length, taMicroTick.length),
+				taStroke = "stroke" in o ? o.stroke : ta.stroke,
+				size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0;
+			if(rotation < 0){
+				rotation += 360;
+			}
+			if(this.vertical){
+				start = {y: dim.height - offsets.b};
+				stop  = {y: offsets.t};
+				axisVector = {x: 0, y: -1};
+				labelOffset = {x: 0, y: 0};
+				tickVector = {x: 1, y: 0};
+				anchorOffset = {x: labelGap, y: 0};
+				switch(rotation){
+					case 0:
+						labelAlign = "end";
+						labelOffset.y = size * 0.4;
+						break;
+					case 90:
+						labelAlign = "middle";
+						labelOffset.x = -size;
+						break;
+					case 180:
+						labelAlign = "start";
+						labelOffset.y = -size * 0.4;
+						break;
+					case 270:
+						labelAlign = "middle";
+						break;
+					default:
+						if(rotation < centerAnchorLimit){
+							labelAlign = "end";
+							labelOffset.y = size * 0.4;
+						}else if(rotation < 90){
+							labelAlign = "end";
+							labelOffset.y = size * 0.4;
+						}else if(rotation < (180 - centerAnchorLimit)){
+							labelAlign = "start";
+						}else if(rotation < (180 + centerAnchorLimit)){
+							labelAlign = "start";
+							labelOffset.y = -size * 0.4;
+						}else if(rotation < 270){
+							labelAlign = "start";
+							labelOffset.x = leftBottom ? 0 : size * 0.4;
+						}else if(rotation < (360 - centerAnchorLimit)){
+							labelAlign = "end";
+							labelOffset.x = leftBottom ? 0 : size * 0.4;
+						}else{
+							labelAlign = "end";
+							labelOffset.y = size * 0.4;
+						}
+				}
+				if(leftBottom){
+					start.x = stop.x = offsets.l;
+					tickVector.x = -1;
+					anchorOffset.x = -anchorOffset.x;
+				}else{
+					start.x = stop.x = dim.width - offsets.r;
+					switch(labelAlign){
+						case "start":
+							labelAlign = "end";
+							break;
+						case "end":
+							labelAlign = "start";
+							break;
+						case "middle":
+							labelOffset.x += size;
+							break;
+					}
+				}
+			}else{
+				start = {x: offsets.l};
+				stop  = {x: dim.width - offsets.r};
+				axisVector = {x: 1, y: 0};
+				labelOffset = {x: 0, y: 0};
+				tickVector = {x: 0, y: 1};
+				anchorOffset = {x: 0, y: labelGap};
+				switch(rotation){
+					case 0:
+						labelAlign = "middle";
+						labelOffset.y = size;
+						break;
+					case 90:
+						labelAlign = "start";
+						labelOffset.x = -size * 0.4;
+						break;
+					case 180:
+						labelAlign = "middle";
+						break;
+					case 270:
+						labelAlign = "end";
+						labelOffset.x = size * 0.4;
+						break;
+					default:
+						if(rotation < (90 - centerAnchorLimit)){
+							labelAlign = "start";
+							labelOffset.y = leftBottom ? size : 0;
+						}else if(rotation < (90 + centerAnchorLimit)){
+							labelAlign = "start";
+							labelOffset.x = -size * 0.4;
+						}else if(rotation < 180){
+							labelAlign = "start";
+							labelOffset.y = leftBottom ? 0 : -size;
+						}else if(rotation < (270 - centerAnchorLimit)){
+							labelAlign = "end";
+							labelOffset.y = leftBottom ? 0 : -size;
+						}else if(rotation < (270 + centerAnchorLimit)){
+							labelAlign = "end";
+							labelOffset.y = leftBottom ? size * 0.4 : 0;
+						}else{
+							labelAlign = "end";
+							labelOffset.y = leftBottom ? size : 0;
+						}
+				}
+				if(leftBottom){
+					start.y = stop.y = dim.height - offsets.b;
+				}else{
+					start.y = stop.y = offsets.t;
+					tickVector.y = -1;
+					anchorOffset.y = -anchorOffset.y;
+					switch(labelAlign){
+						case "start":
+							labelAlign = "end";
+							break;
+						case "end":
+							labelAlign = "start";
+							break;
+						case "middle":
+							labelOffset.y -= size;
+							break;
+					}
+				}
+			}
+
+			// render shapes
+
+			this.cleanGroup();
+
+			try{
+				var s = this.group,
+					c = this.scaler,
+					t = this.ticks,
+					canLabel,
+					f = lin.getTransformerFromModel(this.scaler),
+					forceHtmlLabels = (dojox.gfx.renderer == "canvas"),
+					labelType = forceHtmlLabels || !rotation && this.opt.htmlLabels && !dojo.isIE && !dojo.isOpera ? "html" : "gfx",
+					dx = tickVector.x * taMajorTick.length,
+					dy = tickVector.y * taMajorTick.length;
+
+				s.createLine({
+					x1: start.x,
+					y1: start.y,
+					x2: stop.x,
+					y2: stop.y
+				}).setStroke(taStroke);
+
+				dojo.forEach(t.major, function(tick){
+					var offset = f(tick.value), elem,
+						x = start.x + axisVector.x * offset,
+						y = start.y + axisVector.y * offset;
+						s.createLine({
+							x1: x, y1: y,
+							x2: x + dx,
+							y2: y + dy
+						}).setStroke(taMajorTick);
+						if(tick.label){
+							elem = dc.axis2d.common.createText[labelType](
+								this.chart,
+								s,
+								x + dx + anchorOffset.x + (rotation ? 0 : labelOffset.x),
+								y + dy + anchorOffset.y + (rotation ? 0 : labelOffset.y),
+								labelAlign,
+								tick.label,
+								taFont,
+								taFontColor
+								//this._cachedLabelWidth
+							);
+							if(labelType == "html"){
+								this.htmlElements.push(elem);
+							}else if(rotation){
+								elem.setTransform([
+									{dx: labelOffset.x, dy: labelOffset.y},
+									g.matrix.rotategAt(
+										rotation,
+										x + dx + anchorOffset.x,
+										y + dy + anchorOffset.y
+									)
+								]);
+							}
+						}
+				}, this);
+
+				dx = tickVector.x * taMinorTick.length;
+				dy = tickVector.y * taMinorTick.length;
+				canLabel = c.minMinorStep <= c.minor.tick * c.bounds.scale;
+				dojo.forEach(t.minor, function(tick){
+					var offset = f(tick.value), elem,
+						x = start.x + axisVector.x * offset,
+						y = start.y + axisVector.y * offset;
+						s.createLine({
+							x1: x, y1: y,
+							x2: x + dx,
+							y2: y + dy
+						}).setStroke(taMinorTick);
+						if(canLabel && tick.label){
+							elem = dc.axis2d.common.createText[labelType](
+								this.chart,
+								s,
+								x + dx + anchorOffset.x + (rotation ? 0 : labelOffset.x),
+								y + dy + anchorOffset.y + (rotation ? 0 : labelOffset.y),
+								labelAlign,
+								tick.label,
+								taFont,
+								taFontColor
+								//this._cachedLabelWidth
+							);
+							if(labelType == "html"){
+								this.htmlElements.push(elem);
+							}else if(rotation){
+								elem.setTransform([
+									{dx: labelOffset.x, dy: labelOffset.y},
+									g.matrix.rotategAt(
+										rotation,
+										x + dx + anchorOffset.x,
+										y + dy + anchorOffset.y
+									)
+								]);
+							}
+						}
+				}, this);
+
+				dx = tickVector.x * taMicroTick.length;
+				dy = tickVector.y * taMicroTick.length;
+				dojo.forEach(t.micro, function(tick){
+					var offset = f(tick.value), elem,
+						x = start.x + axisVector.x * offset,
+						y = start.y + axisVector.y * offset;
+						s.createLine({
+							x1: x, y1: y,
+							x2: x + dx,
+							y2: y + dy
+						}).setStroke(taMicroTick);
+				}, this);
+			}catch(e){
+				// squelch
+			}
+
+			this.dirty = false;
+			return this;	//	dojox.charting.axis2d.Default
+		}
+	});
 })();
-}
diff --git a/dojox/charting/axis2d/Invisible.js b/dojox/charting/axis2d/Invisible.js
new file mode 100644
index 0000000..a54f800
--- /dev/null
+++ b/dojox/charting/axis2d/Invisible.js
@@ -0,0 +1,290 @@
+dojo.provide("dojox.charting.axis2d.Invisible");
+
+dojo.require("dojox.charting.scaler.linear");
+dojo.require("dojox.charting.axis2d.common");
+dojo.require("dojox.charting.axis2d.Base");
+
+dojo.require("dojo.string");
+dojo.require("dojox.gfx");
+dojo.require("dojox.lang.functional");
+dojo.require("dojox.lang.utils");
+
+(function(){
+	var dc = dojox.charting,
+		df = dojox.lang.functional,
+		du = dojox.lang.utils,
+		g = dojox.gfx,
+		lin = dc.scaler.linear,
+		merge = du.merge,
+		labelGap = 4,			// in pixels
+		centerAnchorLimit = 45;	// in degrees
+
+	dojo.declare("dojox.charting.axis2d.Invisible", dojox.charting.axis2d.Base, {
+		//	summary:
+		//		The default axis object used in dojox.charting.  See dojox.charting.Chart2D.addAxis for details.
+		//
+		//	defaultParams: Object
+		//		The default parameters used to define any axis.
+		//	optionalParams: Object
+		//		Any optional parameters needed to define an axis.
+
+		/*
+		//	TODO: the documentation tools need these to be pre-defined in order to pick them up
+		//	correctly, but the code here is partially predicated on whether or not the properties
+		//	actually exist.  For now, we will leave these undocumented but in the code for later. -- TRT
+
+		//	opt: Object
+		//		The actual options used to define this axis, created at initialization.
+		//	scalar: Object
+		//		The calculated helper object to tell charts how to draw an axis and any data.
+		//	ticks: Object
+		//		The calculated tick object that helps a chart draw the scaling on an axis.
+		//	dirty: Boolean
+		//		The state of the axis (whether it needs to be redrawn or not)
+		//	scale: Number
+		//		The current scale of the axis.
+		//	offset: Number
+		//		The current offset of the axis.
+
+		opt: null,
+		scalar: null,
+		ticks: null,
+		dirty: true,
+		scale: 1,
+		offset: 0,
+		*/
+		defaultParams: {
+			vertical:    false,		// true for vertical axis
+			fixUpper:    "none",	// align the upper on ticks: "major", "minor", "micro", "none"
+			fixLower:    "none",	// align the lower on ticks: "major", "minor", "micro", "none"
+			natural:     false,		// all tick marks should be made on natural numbers
+			leftBottom:  true,		// position of the axis, used with "vertical"
+			includeZero: false,		// 0 should be included
+			fixed:       true,		// all labels are fixed numbers
+			majorLabels: true,		// draw major labels
+			minorTicks:  true,		// draw minor ticks
+			minorLabels: true,		// draw minor labels
+			microTicks:  false,		// draw micro ticks
+			rotation:    0			// label rotation angle in degrees
+		},
+		optionalParams: {
+			min:			0,	// minimal value on this axis
+			max:			1,	// maximal value on this axis
+			from:			0,	// visible from this value
+			to:				1,	// visible to this value
+			majorTickStep:	4,	// major tick step
+			minorTickStep:	2,	// minor tick step
+			microTickStep:	1,	// micro tick step
+			labels:			[],	// array of labels for major ticks
+								// with corresponding numeric values
+								// ordered by values
+			labelFunc:		null, // function to compute label values
+			maxLabelSize:	0	// size in px. For use with labelFunc
+
+			// TODO: add support for minRange!
+			// minRange:		1,	// smallest distance from min allowed on the axis
+		},
+
+		constructor: function(chart, kwArgs){
+			//	summary:
+			//		The constructor for an axis.
+			//	chart: dojox.charting.Chart2D
+			//		The chart the axis belongs to.
+			//	kwArgs: dojox.charting.axis2d.__AxisCtorArgs?
+			//		Any optional keyword arguments to be used to define this axis.
+			this.opt = dojo.delegate(this.defaultParams, kwArgs);
+			// du.updateWithObject(this.opt, kwArgs);
+			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
+		},
+		dependOnData: function(){
+			//	summary:
+			//		Find out whether or not the axis options depend on the data in the axis.
+			return !("min" in this.opt) || !("max" in this.opt);	//	Boolean
+		},
+		clear: function(){
+			//	summary:
+			//		Clear out all calculated properties on this axis;
+			//	returns: dojox.charting.axis2d.Default
+			//		The reference to the axis for functional chaining.
+			delete this.scaler;
+			delete this.ticks;
+			this.dirty = true;
+			return this;	//	dojox.charting.axis2d.Default
+		},
+		initialized: function(){
+			//	summary:
+			//		Finds out if this axis has been initialized or not.
+			//	returns: Boolean
+			//		Whether a scaler has been calculated and if the axis is not dirty.
+			return "scaler" in this && !(this.dirty && this.dependOnData());
+		},
+		setWindow: function(scale, offset){
+			//	summary:
+			//		Set the drawing "window" for the axis.
+			//	scale: Number
+			//		The new scale for the axis.
+			//	offset: Number
+			//		The new offset for the axis.
+			//	returns: dojox.charting.axis2d.Default
+			//		The reference to the axis for functional chaining.
+			this.scale  = scale;
+			this.offset = offset;
+			return this.clear();	//	dojox.charting.axis2d.Default
+		},
+		getWindowScale: function(){
+			//	summary:
+			//		Get the current windowing scale of the axis.
+			return "scale" in this ? this.scale : 1;	//	Number
+		},
+		getWindowOffset: function(){
+			//	summary:
+			//		Get the current windowing offset for the axis.
+			return "offset" in this ? this.offset : 0;	//	Number
+		},
+		_groupLabelWidth: function(labels, font){
+			if(!labels.length){
+				return 0;
+			}
+			if(dojo.isObject(labels[0])){
+				labels = df.map(labels, function(label){ return label.text; });
+			}
+			var s = labels.join("<br>");
+			return dojox.gfx._base._getTextBox(s, {font: font}).w || 0;
+		},
+		calculate: function(min, max, span, labels){
+			//	summary:
+			//		Perform all calculations needed to render this axis.
+			//	min: Number
+			//		The smallest value represented on this axis.
+			//	max: Number
+			//		The largest value represented on this axis.
+			//	span: Number
+			//		The span in pixels over which axis calculations are made.
+			//	labels: String[]
+			//		Optional list of labels.
+			//	returns: dojox.charting.axis2d.Default
+			//		The reference to the axis for functional chaining.
+			if(this.initialized()){
+				return this;
+			}
+			var o = this.opt;
+			this.labels = "labels" in o  ? o.labels : labels;
+			this.scaler = lin.buildScaler(min, max, span, o);
+			var tsb = this.scaler.bounds;
+			if("scale" in this){
+				// calculate new range
+				o.from = tsb.lower + this.offset;
+				o.to   = (tsb.upper - tsb.lower) / this.scale + o.from;
+				// make sure that bounds are correct
+				if( !isFinite(o.from) ||
+					isNaN(o.from) ||
+					!isFinite(o.to) ||
+					isNaN(o.to) ||
+					o.to - o.from >= tsb.upper - tsb.lower
+				){
+					// any error --- remove from/to bounds
+					delete o.from;
+					delete o.to;
+					delete this.scale;
+					delete this.offset;
+				}else{
+					// shift the window, if we are out of bounds
+					if(o.from < tsb.lower){
+						o.to += tsb.lower - o.from;
+						o.from = tsb.lower;
+					}else if(o.to > tsb.upper){
+						o.from += tsb.upper - o.to;
+						o.to = tsb.upper;
+					}
+					// update the offset
+					this.offset = o.from - tsb.lower;
+				}
+				// re-calculate the scaler
+				this.scaler = lin.buildScaler(min, max, span, o);
+				tsb = this.scaler.bounds;
+				// cleanup
+				if(this.scale == 1 && this.offset == 0){
+					delete this.scale;
+					delete this.offset;
+				}
+			}
+
+			var ta = this.chart.theme.axis, labelWidth = 0, rotation = o.rotation % 360,
+				// TODO: we use one font --- of major tick, we need to use major and minor fonts
+				taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font),
+				size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
+				cosr = Math.abs(Math.cos(rotation * Math.PI / 180)),
+				sinr = Math.abs(Math.sin(rotation * Math.PI / 180));
+
+			if(rotation < 0){
+				rotation += 360;
+			}
+
+			if(size){
+				if(this.vertical ? rotation != 0 && rotation != 180 : rotation != 90 && rotation != 270){
+					// we need width of all labels
+					if(o.maxLabelSize){
+						labelWidth = o.maxLabelSize;
+					}else if(this.labels){
+						labelWidth = this._groupLabelWidth(this.labels, taFont);
+					}else{
+						var labelLength = Math.ceil(
+								Math.log(
+									Math.max(
+										Math.abs(tsb.from),
+										Math.abs(tsb.to)
+									)
+								) / Math.LN10
+							),
+							t = [];
+						if(tsb.from < 0 || tsb.to < 0){
+							t.push("-");
+						}
+						t.push(dojo.string.rep("9", labelLength));
+						var precision = Math.floor(
+							Math.log( tsb.to - tsb.from ) / Math.LN10
+						);
+						if(precision > 0){
+							t.push(".");
+							t.push(dojo.string.rep("9", precision));
+						}
+						labelWidth = dojox.gfx._base._getTextBox(
+							t.join(""),
+							{ font: taFont }
+						).w;
+					}
+				}else{
+					labelWidth = size;
+				}
+				switch(rotation){
+					case 0:
+					case 90:
+					case 180:
+					case 270:
+						// trivial cases: use labelWidth
+						break;
+					default:
+						// rotated labels
+						var gap1 = Math.sqrt(labelWidth * labelWidth + size * size),									// short labels
+							gap2 = this.vertical ? size * cosr + labelWidth * sinr : labelWidth * cosr + size * sinr;	// slanted labels
+						labelWidth = Math.min(gap1, gap2);
+						break;
+				}
+			}
+
+			this.scaler.minMinorStep = labelWidth + labelGap;
+			this.ticks = lin.buildTicks(this.scaler, o);
+			return this;	//	dojox.charting.axis2d.Default
+		},
+		getScaler: function(){
+			//	summary:
+			//		Get the pre-calculated scaler object.
+			return this.scaler;	//	Object
+		},
+		getTicks: function(){
+			//	summary:
+			//		Get the pre-calculated ticks object.
+			return this.ticks;	//	Object
+		}
+	});
+})();
diff --git a/dojox/charting/axis2d/common.js b/dojox/charting/axis2d/common.js
index 66529c0..b0153c7 100644
--- a/dojox/charting/axis2d/common.js
+++ b/dojox/charting/axis2d/common.js
@@ -1,92 +1,154 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.axis2d.common"]){
-dojo._hasResource["dojox.charting.axis2d.common"]=true;
 dojo.provide("dojox.charting.axis2d.common");
+
 dojo.require("dojox.gfx");
+
 (function(){
-var g=dojox.gfx;
-var _1=function(s){
-s.marginLeft="0px";
-s.marginTop="0px";
-s.marginRight="0px";
-s.marginBottom="0px";
-s.paddingLeft="0px";
-s.paddingTop="0px";
-s.paddingRight="0px";
-s.paddingBottom="0px";
-s.borderLeftWidth="0px";
-s.borderTopWidth="0px";
-s.borderRightWidth="0px";
-s.borderBottomWidth="0px";
-};
-var _2=function(n){
-if(n["getBoundingClientRect"]){
-var _3=n.getBoundingClientRect();
-return _3.width||(_3.right-_3.left);
-}else{
-return dojo.marginBox(n).w;
-}
-};
-dojo.mixin(dojox.charting.axis2d.common,{createText:{gfx:function(_4,_5,x,y,_6,_7,_8,_9){
-return _5.createText({x:x,y:y,text:_7,align:_6}).setFont(_8).setFill(_9);
-},html:function(_a,_b,x,y,_c,_d,_e,_f,_10){
-var p=dojo.doc.createElement("div"),s=p.style,_11;
-_1(s);
-s.font=_e;
-p.innerHTML=String(_d).replace(/\s/g," ");
-s.color=_f;
-s.position="absolute";
-s.left="-10000px";
-dojo.body().appendChild(p);
-var _12=g.normalizedLength(g.splitFontString(_e).size);
-if(!_10){
-_11=_2(p);
-}
-dojo.body().removeChild(p);
-s.position="relative";
-if(_10){
-s.width=_10+"px";
-switch(_c){
-case "middle":
-s.textAlign="center";
-s.left=(x-_10/2)+"px";
-break;
-case "end":
-s.textAlign="right";
-s.left=(x-_10)+"px";
-break;
-default:
-s.left=x+"px";
-s.textAlign="left";
-break;
-}
-}else{
-switch(_c){
-case "middle":
-s.left=Math.floor(x-_11/2)+"px";
-break;
-case "end":
-s.left=Math.floor(x-_11)+"px";
-break;
-default:
-s.left=Math.floor(x)+"px";
-break;
-}
-}
-s.top=Math.floor(y-_12)+"px";
-var _13=dojo.doc.createElement("div"),w=_13.style;
-_1(w);
-w.width="0px";
-w.height="0px";
-_13.appendChild(p);
-_a.node.insertBefore(_13,_a.node.firstChild);
-return _13;
-}}});
+	var g = dojox.gfx;
+
+	var clearNode = function(s){
+		s.marginLeft   = "0px";
+		s.marginTop    = "0px";
+		s.marginRight  = "0px";
+		s.marginBottom = "0px";
+		s.paddingLeft   = "0px";
+		s.paddingTop    = "0px";
+		s.paddingRight  = "0px";
+		s.paddingBottom = "0px";
+		s.borderLeftWidth   = "0px";
+		s.borderTopWidth    = "0px";
+		s.borderRightWidth  = "0px";
+		s.borderBottomWidth = "0px";
+	};
+
+	var getBoxWidth = function(n){
+		// marginBox is incredibly slow, so avoid it if we can
+		if(n["getBoundingClientRect"]){
+			var bcr = n.getBoundingClientRect();
+			return bcr.width || (bcr.right - bcr.left);
+		}else{
+			return dojo.marginBox(n).w;
+		}
+	};
+
+	dojo.mixin(dojox.charting.axis2d.common, {
+		//	summary:
+		//		Common methods to be used by any axis.  This is considered "static".
+		createText: {
+			gfx: function(chart, creator, x, y, align, text, font, fontColor){
+				//	summary:
+				//		Use dojox.gfx to create any text.
+				//	chart: dojox.charting.Chart2D
+				//		The chart to create the text into.
+				//	creator: dojox.gfx.Surface
+				//		The graphics surface to use for creating the text.
+				//	x: Number
+				//		Where to create the text along the x axis (CSS left).
+				//	y: Number
+				//		Where to create the text along the y axis (CSS top).
+				//	align: String
+				//		How to align the text.  Can be "left", "right", "center".
+				//	text: String
+				//		The text to render.
+				//	font: String
+				//		The font definition, a la CSS "font".
+				//	fontColor: String|dojo.Color
+				//		The color of the resultant text.
+				//	returns: dojox.gfx.Text
+				//		The resultant GFX object.
+				return creator.createText({
+					x: x, y: y, text: text, align: align
+				}).setFont(font).setFill(fontColor);	//	dojox.gfx.Text
+			},
+			html: function(chart, creator, x, y, align, text, font, fontColor, labelWidth){
+				//	summary:
+				//		Use the HTML DOM to create any text.
+				//	chart: dojox.charting.Chart2D
+				//		The chart to create the text into.
+				//	creator: dojox.gfx.Surface
+				//		The graphics surface to use for creating the text.
+				//	x: Number
+				//		Where to create the text along the x axis (CSS left).
+				//	y: Number
+				//		Where to create the text along the y axis (CSS top).
+				//	align: String
+				//		How to align the text.  Can be "left", "right", "center".
+				//	text: String
+				//		The text to render.
+				//	font: String
+				//		The font definition, a la CSS "font".
+				//	fontColor: String|dojo.Color
+				//		The color of the resultant text.
+				//	labelWidth: Number?
+				//		The maximum width of the resultant DOM node.
+				//	returns: DOMNode
+				//		The resultant DOMNode (a "div" element).
+
+				// setup the text node
+				var p = dojo.doc.createElement("div"), s = p.style, boxWidth;
+				clearNode(s);
+				s.font = font;
+				p.innerHTML = String(text).replace(/\s/g, " ");
+				s.color = fontColor;
+				// measure the size
+				s.position = "absolute";
+				s.left = "-10000px";
+				dojo.body().appendChild(p);
+				var size = g.normalizedLength(g.splitFontString(font).size);
+
+				// do we need to calculate the label width?
+				if(!labelWidth){
+					boxWidth = getBoxWidth(p);
+				}
+
+				// new settings for the text node
+				dojo.body().removeChild(p);
+
+				s.position = "relative";
+				if(labelWidth){
+					s.width = labelWidth + "px";
+					// s.border = "1px dotted grey";
+					switch(align){
+						case "middle":
+							s.textAlign = "center";
+							s.left = (x - labelWidth / 2) + "px";
+							break;
+						case "end":
+							s.textAlign = "right";
+							s.left = (x - labelWidth) + "px";
+							break;
+						default:
+							s.left = x + "px";
+							s.textAlign = "left";
+							break;
+					}
+				}else{
+					switch(align){
+						case "middle":
+							s.left = Math.floor(x - boxWidth / 2) + "px";
+							// s.left = Math.floor(x - p.offsetWidth / 2) + "px";
+							break;
+						case "end":
+							s.left = Math.floor(x - boxWidth) + "px";
+							// s.left = Math.floor(x - p.offsetWidth) + "px";
+							break;
+						//case "start":
+						default:
+							s.left = Math.floor(x) + "px";
+							break;
+					}
+				}
+				s.top = Math.floor(y - size) + "px";
+				s.whiteSpace = "nowrap";	// hack for WebKit
+				// setup the wrapper node
+				var wrap = dojo.doc.createElement("div"), w = wrap.style;
+				clearNode(w);
+				w.width = "0px";
+				w.height = "0px";
+				// insert nodes
+				wrap.appendChild(p)
+				chart.node.insertBefore(wrap, chart.node.firstChild);
+				return wrap;	//	DOMNode
+			}
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/Areas.js b/dojox/charting/plot2d/Areas.js
index 231ec8a..365cd9d 100644
--- a/dojox/charting/plot2d/Areas.js
+++ b/dojox/charting/plot2d/Areas.js
@@ -1,16 +1,12 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Areas"]){
-dojo._hasResource["dojox.charting.plot2d.Areas"]=true;
 dojo.provide("dojox.charting.plot2d.Areas");
+
 dojo.require("dojox.charting.plot2d.Default");
-dojo.declare("dojox.charting.plot2d.Areas",dojox.charting.plot2d.Default,{constructor:function(){
-this.opt.lines=true;
-this.opt.areas=true;
-}});
-}
+
+dojo.declare("dojox.charting.plot2d.Areas", dojox.charting.plot2d.Default, {
+	//	summary:
+	//		Represents an area chart.  See dojox.charting.plot2d.Default for details.
+	constructor: function(){
+		this.opt.lines = true;
+		this.opt.areas = true;
+	}
+});
diff --git a/dojox/charting/plot2d/Bars.js b/dojox/charting/plot2d/Bars.js
index ca2f862..74f63e7 100644
--- a/dojox/charting/plot2d/Bars.js
+++ b/dojox/charting/plot2d/Bars.js
@@ -1,104 +1,176 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Bars"]){
-dojo._hasResource["dojox.charting.plot2d.Bars"]=true;
 dojo.provide("dojox.charting.plot2d.Bars");
+
 dojo.require("dojox.charting.plot2d.common");
 dojo.require("dojox.charting.plot2d.Base");
 dojo.require("dojox.gfx.fx");
+
 dojo.require("dojox.lang.utils");
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.reversed");
-(function(){
-var df=dojox.lang.functional,du=dojox.lang.utils,dc=dojox.charting.plot2d.common,_1=df.lambda("item.purgeGroup()");
-dojo.declare("dojox.charting.plot2d.Bars",dojox.charting.plot2d.Base,{defaultParams:{hAxis:"x",vAxis:"y",gap:0,shadows:null,animate:null},optionalParams:{minBarSize:1,maxBarSize:1},constructor:function(_2,_3){
-this.opt=dojo.clone(this.defaultParams);
-du.updateWithObject(this.opt,_3);
-du.updateWithPattern(this.opt,_3,this.optionalParams);
-this.series=[];
-this.hAxis=this.opt.hAxis;
-this.vAxis=this.opt.vAxis;
-this.animate=this.opt.animate;
-},calculateAxes:function(_4){
-var _5=dc.collectSimpleStats(this.series),t;
-_5.hmin-=0.5;
-_5.hmax+=0.5;
-t=_5.hmin,_5.hmin=_5.vmin,_5.vmin=t;
-t=_5.hmax,_5.hmax=_5.vmax,_5.vmax=t;
-this._calc(_4,_5);
-return this;
-},render:function(_6,_7){
-this.dirty=this.isDirty();
-if(this.dirty){
-dojo.forEach(this.series,_1);
-this.cleanGroup();
-var s=this.group;
-df.forEachRev(this.series,function(_8){
-_8.cleanGroup(s);
+/*=====
+dojo.declare("dojox.charting.plot2d.__BarCtorArgs", dojox.charting.plot2d.__DefaultCtorArgs, {
+	//	summary:
+	//		Additional keyword arguments for bar charts.
+
+	//	minBarSize: Number?
+	//		The minimum size for a bar in pixels.  Default is 1.
+	minBarSize: 1,
+
+	//	maxBarSize: Number?
+	//		The maximum size for a bar in pixels.  Default is 1.
+	maxBarSize: 1
 });
-}
-var t=this.chart.theme,_9,_a,_b,f,_c,_d,ht=this._hScaler.scaler.getTransformerFromModel(this._hScaler),vt=this._vScaler.scaler.getTransformerFromModel(this._vScaler),_e=Math.max(0,this._hScaler.bounds.lower),_f=ht(_e),_10=this.events();
-f=dc.calculateBarSize(this._vScaler.bounds.scale,this.opt);
-_c=f.gap;
-_d=f.size;
-this.resetEvents();
-for(var i=this.series.length-1;i>=0;--i){
-var run=this.series[i];
-if(!this.dirty&&!run.dirty){
-continue;
-}
-run.cleanGroup();
-var s=run.group;
-if(!run.fill||!run.stroke){
-_9=run.dyn.color=new dojo.Color(t.next("color"));
-}
-_a=run.stroke?run.stroke:dc.augmentStroke(t.series.stroke,_9);
-_b=run.fill?run.fill:dc.augmentFill(t.series.fill,_9);
-for(var j=0;j<run.data.length;++j){
-var _11=run.data[j],v=typeof _11=="number"?_11:_11.y,hv=ht(v),_12=hv-_f,w=Math.abs(_12),_13=_9,_14=_b,_15=_a;
-if(typeof _11!="number"){
-if(_11.color){
-_13=new dojo.Color(_11.color);
-}
-if("fill" in _11){
-_14=_11.fill;
-}else{
-if(_11.color){
-_14=dc.augmentFill(t.series.fill,_13);
-}
-}
-if("stroke" in _11){
-_15=_11.stroke;
-}else{
-if(_11.color){
-_15=dc.augmentStroke(t.series.stroke,_13);
-}
-}
-}
-if(w>=1&&_d>=1){
-var _16=s.createRect({x:_7.l+(v<_e?hv:_f),y:_6.height-_7.b-vt(j+1.5)+_c,width:w,height:_d}).setFill(_14).setStroke(_15);
-run.dyn.fill=_16.getFill();
-run.dyn.stroke=_16.getStroke();
-if(_10){
-var o={element:"bar",index:j,run:run,plot:this,hAxis:this.hAxis||null,vAxis:this.vAxis||null,shape:_16,x:v,y:j+1.5};
-this._connectEvents(_16,o);
-}
-if(this.animate){
-this._animateBar(_16,_7.l+_f,-w);
-}
-}
-}
-run.dirty=false;
-}
-this.dirty=false;
-return this;
-},_animateBar:function(_17,_18,_19){
-dojox.gfx.fx.animateTransform(dojo.delegate({shape:_17,duration:1200,transform:[{name:"translate",start:[_18-(_18/_19),0],end:[0,0]},{name:"scale",start:[1/_19,1],end:[1,1]},{name:"original"}]},this.animate)).play();
-}});
+=====*/
+(function(){
+	var df = dojox.lang.functional, du = dojox.lang.utils,
+		dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	dojo.declare("dojox.charting.plot2d.Bars", dojox.charting.plot2d.Base, {
+		//	summary:
+		//		The plot object representing a bar chart (horizontal bars).
+		defaultParams: {
+			hAxis: "x",		// use a horizontal axis named "x"
+			vAxis: "y",		// use a vertical axis named "y"
+			gap:	0,		// gap between columns in pixels
+			animate: null   // animate bars into place
+		},
+		optionalParams: {
+			minBarSize:	1,	// minimal bar width in pixels
+			maxBarSize:	1,	// maximal bar width in pixels
+			// theme component
+			stroke:		{},
+			outline:	{},
+			shadow:		{},
+			fill:		{},
+			font:		"",
+			fontColor:	""
+		},
+
+		constructor: function(chart, kwArgs){
+			//	summary:
+			//		The constructor for a bar chart.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this plot belongs to.
+			//	kwArgs: dojox.charting.plot2d.__BarCtorArgs?
+			//		An optional keyword arguments object to help define the plot.
+			this.opt = dojo.clone(this.defaultParams);
+			du.updateWithObject(this.opt, kwArgs);
+			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
+			this.series = [];
+			this.hAxis = this.opt.hAxis;
+			this.vAxis = this.opt.vAxis;
+			this.animate = this.opt.animate;
+		},
+
+		getSeriesStats: function(){
+			//	summary:
+			//		Calculate the min/max on all attached series in both directions.
+			//	returns: Object
+			//		{hmin, hmax, vmin, vmax} min/max in both directions.
+			var stats = dc.collectSimpleStats(this.series), t;
+			stats.hmin -= 0.5;
+			stats.hmax += 0.5;
+			t = stats.hmin, stats.hmin = stats.vmin, stats.vmin = t;
+			t = stats.hmax, stats.hmax = stats.vmax, stats.vmax = t;
+			return stats;
+		},
+
+		render: function(dim, offsets){
+			//	summary:
+			//		Run the calculations for any axes for this plot.
+			//	dim: Object
+			//		An object in the form of { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b}.
+			//	returns: dojox.charting.plot2d.Bars
+			//		A reference to this plot for functional chaining.
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+			this.dirty = this.isDirty();
+			this.resetEvents();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+			var t = this.chart.theme, f, gap, height,
+				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
+				baseline = Math.max(0, this._hScaler.bounds.lower),
+				baselineWidth = ht(baseline),
+				events = this.events();
+			f = dc.calculateBarSize(this._vScaler.bounds.scale, this.opt);
+			gap = f.gap;
+			height = f.size;
+			for(var i = this.series.length - 1; i >= 0; --i){
+				var run = this.series[i];
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				var theme = t.next("bar", [this.opt, run]), s = run.group,
+					eventSeries = new Array(run.data.length);
+				for(var j = 0; j < run.data.length; ++j){
+					var value = run.data[j];
+					if(value !== null){
+						var v = typeof value == "number" ? value : value.y,
+							hv = ht(v),
+							width = hv - baselineWidth,
+							w = Math.abs(width),
+							finalTheme = typeof value != "number" ?
+								t.addMixin(theme, "bar", value, true) :
+								t.post(theme, "bar");
+						if(w >= 1 && height >= 1){
+							var rect = {
+								x: offsets.l + (v < baseline ? hv : baselineWidth),
+								y: dim.height - offsets.b - vt(j + 1.5) + gap,
+								width: w, height: height
+							};
+							var specialFill = this._plotFill(finalTheme.series.fill, dim, offsets);
+							specialFill = this._shapeFill(specialFill, rect);
+							var shape = s.createRect(rect).setFill(specialFill).setStroke(finalTheme.series.stroke);
+							run.dyn.fill   = shape.getFill();
+							run.dyn.stroke = shape.getStroke();
+							if(events){
+								var o = {
+									element: "bar",
+									index:   j,
+									run:     run,
+									shape:   shape,
+									x:       v,
+									y:       j + 1.5
+								};
+								this._connectEvents(o);
+								eventSeries[j] = o;
+							}
+							if(this.animate){
+								this._animateBar(shape, offsets.l + baselineWidth, -w);
+							}
+						}
+					}
+				}
+				this._eventSeries[run.name] = eventSeries;
+				run.dirty = false;
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.Bars
+		},
+		_animateBar: function(shape, hoffset, hsize){
+			dojox.gfx.fx.animateTransform(dojo.delegate({
+				shape: shape,
+				duration: 1200,
+				transform: [
+					{name: "translate", start: [hoffset - (hoffset/hsize), 0], end: [0, 0]},
+					{name: "scale", start: [1/hsize, 1], end: [1, 1]},
+					{name: "original"}
+				]
+			}, this.animate)).play();
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/Base.js b/dojox/charting/plot2d/Base.js
index 1faff35..b17fffb 100644
--- a/dojox/charting/plot2d/Base.js
+++ b/dojox/charting/plot2d/Base.js
@@ -1,90 +1,192 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Base"]){
-dojo._hasResource["dojox.charting.plot2d.Base"]=true;
 dojo.provide("dojox.charting.plot2d.Base");
+
 dojo.require("dojox.charting.scaler.primitive");
 dojo.require("dojox.charting.Element");
 dojo.require("dojox.charting.plot2d.common");
-dojo.declare("dojox.charting.plot2d.Base",dojox.charting.Element,{destroy:function(){
-this.resetEvents();
-this.inherited(arguments);
-},clear:function(){
-this.series=[];
-this._hAxis=null;
-this._vAxis=null;
-this.dirty=true;
-return this;
-},setAxis:function(_1){
-if(_1){
-this[_1.vertical?"_vAxis":"_hAxis"]=_1;
-}
-return this;
-},addSeries:function(_2){
-this.series.push(_2);
-return this;
-},calculateAxes:function(_3){
-return this;
-},isDirty:function(){
-return this.dirty||this._hAxis&&this._hAxis.dirty||this._vAxis&&this._vAxis.dirty;
-},render:function(_4,_5){
-return this;
-},getRequiredColors:function(){
-return this.series.length;
-},plotEvent:function(o){
-},connect:function(_6,_7){
-this.dirty=true;
-return dojo.connect(this,"plotEvent",_6,_7);
-},events:function(){
-var ls=this.plotEvent._listeners;
-if(!ls||!ls.length){
-return false;
-}
-for(var i in ls){
-if(!(i in Array.prototype)){
-return true;
-}
-}
-return false;
-},resetEvents:function(){
-this.plotEvent({type:"onplotreset",plot:this});
-},_calc:function(_8,_9){
-if(this._hAxis){
-if(!this._hAxis.initialized()){
-this._hAxis.calculate(_9.hmin,_9.hmax,_8.width);
-}
-this._hScaler=this._hAxis.getScaler();
-}else{
-this._hScaler=dojox.charting.scaler.primitive.buildScaler(_9.hmin,_9.hmax,_8.width);
-}
-if(this._vAxis){
-if(!this._vAxis.initialized()){
-this._vAxis.calculate(_9.vmin,_9.vmax,_8.height);
-}
-this._vScaler=this._vAxis.getScaler();
-}else{
-this._vScaler=dojox.charting.scaler.primitive.buildScaler(_9.vmin,_9.vmax,_8.height);
+dojo.require("dojox.charting.plot2d._PlotEvents");
+
+/*=====
+dojox.charting.plot2d.__PlotCtorArgs = function(){
+	//	summary:
+	//		The base keyword arguments object for plot constructors.
+	//		Note that the parameters for this may change based on the
+	//		specific plot type (see the corresponding plot type for
+	//		details).
 }
-},_connectEvents:function(_a,o){
-_a.connect("onmouseover",this,function(e){
-o.type="onmouseover";
-o.event=e;
-this.plotEvent(o);
-});
-_a.connect("onmouseout",this,function(e){
-o.type="onmouseout";
-o.event=e;
-this.plotEvent(o);
-});
-_a.connect("onclick",this,function(e){
-o.type="onclick";
-o.event=e;
-this.plotEvent(o);
+=====*/
+dojo.declare("dojox.charting.plot2d.Base", [dojox.charting.Element, dojox.charting.plot2d._PlotEvents], {
+	constructor: function(chart, kwArgs){
+		//	summary:
+		//		Create a base plot for charting.
+		//	chart: dojox.chart.Chart2D
+		//		The chart this plot belongs to.
+		//	kwArgs: dojox.charting.plot2d.__PlotCtorArgs?
+		//		An optional arguments object to help define the plot.
+		this.zoom = null,
+		this.zoomQueue = [];	// zooming action task queue
+		this.lastWindow = {vscale: 1, hscale: 1, xoffset: 0, yoffset: 0};
+	},
+	clear: function(){
+		//	summary:
+		//		Clear out all of the information tied to this plot.
+		//	returns: dojox.charting.plot2d.Base
+		//		A reference to this plot for functional chaining.
+		this.series = [];
+		this._hAxis = null;
+		this._vAxis = null;
+		this.dirty = true;
+		return this;	//	dojox.charting.plot2d.Base
+	},
+	setAxis: function(axis){
+		//	summary:
+		//		Set an axis for this plot.
+		//	axis: dojox.charting.axis2d.Base
+		//		The axis to set.
+		//	returns: dojox.charting.plot2d.Base
+		//		A reference to this plot for functional chaining.
+		if(axis){
+			this[axis.vertical ? "_vAxis" : "_hAxis"] = axis;
+		}
+		return this;	//	dojox.charting.plot2d.Base
+	},
+	addSeries: function(run){
+		//	summary:
+		//		Add a data series to this plot.
+		//	run: dojox.charting.Series
+		//		The series to be added.
+		//	returns: dojox.charting.plot2d.Base
+		//		A reference to this plot for functional chaining.
+		this.series.push(run);
+		return this;	//	dojox.charting.plot2d.Base
+	},
+	getSeriesStats: function(){
+		//	summary:
+		//		Calculate the min/max on all attached series in both directions.
+		//	returns: Object
+		//		{hmin, hmax, vmin, vmax} min/max in both directions.
+		return dojox.charting.plot2d.common.collectSimpleStats(this.series);
+	},
+	calculateAxes: function(dim){
+		//	summary:
+		//		Stub function for running the axis calculations (depricated).
+		//	dim: Object
+		//		An object of the form { width, height }
+		//	returns: dojox.charting.plot2d.Base
+		//		A reference to this plot for functional chaining.
+		this.initializeScalers(dim, this.getSeriesStats());
+		return this;	//	dojox.charting.plot2d.Base
+	},
+	isDirty: function(){
+		//	summary:
+		//		Returns whether or not this plot needs to be rendered.
+		//	returns: Boolean
+		//		The state of the plot.
+		return this.dirty || this._hAxis && this._hAxis.dirty || this._vAxis && this._vAxis.dirty;	//	Boolean
+	},
+	isDataDirty: function(){
+		//	summary:
+		//		Returns whether or not any of this plot's data series need to be rendered.
+		//	returns: Boolean
+		//		Flag indicating if any of this plot's series are invalid and need rendering.
+		return dojo.some(this.series, function(item){ return item.dirty; });	//	Boolean
+	},
+	performZoom: function(dim, offsets){
+		//	summary:
+		//		Create/alter any zooming windows on this plot.
+		//	dim: Object
+		//		An object of the form { width, height }.
+		//	offsets: Object
+		//		An object of the form { l, r, t, b }.
+		//	returns: dojox.charting.plot2d.Base
+		//		A reference to this plot for functional chaining.
+
+		// get current zooming various
+		var vs = this._vAxis.scale || 1,
+			hs = this._hAxis.scale || 1,
+			vOffset = dim.height - offsets.b,
+			hBounds = this._hScaler.bounds,
+			xOffset = (hBounds.from - hBounds.lower) * hBounds.scale,
+			vBounds = this._vScaler.bounds,
+			yOffset = (vBounds.from - vBounds.lower) * vBounds.scale;
+			// get incremental zooming various
+			rVScale = vs / this.lastWindow.vscale,
+			rHScale = hs / this.lastWindow.hscale,
+			rXOffset = (this.lastWindow.xoffset - xOffset)/
+				((this.lastWindow.hscale == 1)? hs : this.lastWindow.hscale),
+			rYOffset = (yOffset - this.lastWindow.yoffset)/
+				((this.lastWindow.vscale == 1)? vs : this.lastWindow.vscale),
+
+			shape = this.group,
+			anim = dojox.gfx.fx.animateTransform(dojo.delegate({
+				shape: shape,
+				duration: 1200,
+				transform:[
+					{name:"translate", start:[0, 0], end: [offsets.l * (1 - rHScale), vOffset * (1 - rVScale)]},
+					{name:"scale", start:[1, 1], end: [rHScale, rVScale]},
+					{name:"original"},
+					{name:"translate", start: [0, 0], end: [rXOffset, rYOffset]}
+				]}, this.zoom));
+
+		dojo.mixin(this.lastWindow, {vscale: vs, hscale: hs, xoffset: xOffset, yoffset: yOffset});
+		//add anim to zooming action queue,
+		//in order to avoid several zooming action happened at the same time
+		this.zoomQueue.push(anim);
+		//perform each anim one by one in zoomQueue
+		dojo.connect(anim, "onEnd", this, function(){
+			this.zoom = null;
+			this.zoomQueue.shift();
+			if(this.zoomQueue.length > 0){
+				this.zoomQueue[0].play();
+			}
+		});
+		if(this.zoomQueue.length == 1){
+			this.zoomQueue[0].play();
+		}
+		return this;	//	dojox.charting.plot2d.Base
+	},
+	render: function(dim, offsets){
+		//	summary:
+		//		Render the plot on the chart.
+		//	dim: Object
+		//		An object of the form { width, height }.
+		//	offsets: Object
+		//		An object of the form { l, r, t, b }.
+		//	returns: dojox.charting.plot2d.Base
+		//		A reference to this plot for functional chaining.
+		return this;	//	dojox.charting.plot2d.Base
+	},
+	getRequiredColors: function(){
+		//	summary:
+		//		Get how many data series we have, so we know how many colors to use.
+		//	returns: Number
+		//		The number of colors needed.
+		return this.series.length;	//	Number
+	},
+	initializeScalers: function(dim, stats){
+		//	summary:
+		//		Initializes scalers using attached axes.
+		//	dim: Object:
+		//		Size of a plot area in pixels as {width, height}.
+		//	stats: Object:
+		//		Min/max of data in both directions as {hmin, hmax, vmin, vmax}.
+		//	returns: dojox.charting.plot2d.Base
+		//		A reference to this plot for functional chaining.
+		if(this._hAxis){
+			if(!this._hAxis.initialized()){
+				this._hAxis.calculate(stats.hmin, stats.hmax, dim.width);
+			}
+			this._hScaler = this._hAxis.getScaler();
+		}else{
+			this._hScaler = dojox.charting.scaler.primitive.buildScaler(stats.hmin, stats.hmax, dim.width);
+		}
+		if(this._vAxis){
+			if(!this._vAxis.initialized()){
+				this._vAxis.calculate(stats.vmin, stats.vmax, dim.height);
+			}
+			this._vScaler = this._vAxis.getScaler();
+		}else{
+			this._vScaler = dojox.charting.scaler.primitive.buildScaler(stats.vmin, stats.vmax, dim.height);
+		}
+		return this;	//	dojox.charting.plot2d.Base
+	}
 });
-}});
-}
diff --git a/dojox/charting/plot2d/Bubble.js b/dojox/charting/plot2d/Bubble.js
index 134ecee..568ef5b 100644
--- a/dojox/charting/plot2d/Bubble.js
+++ b/dojox/charting/plot2d/Bubble.js
@@ -1,98 +1,217 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Bubble"]){
-dojo._hasResource["dojox.charting.plot2d.Bubble"]=true;
 dojo.provide("dojox.charting.plot2d.Bubble");
+
 dojo.require("dojox.charting.plot2d.Base");
 dojo.require("dojox.lang.functional");
+
 (function(){
-var df=dojox.lang.functional,du=dojox.lang.utils,dc=dojox.charting.plot2d.common,_1=df.lambda("item.purgeGroup()");
-dojo.declare("dojox.charting.plot2d.Bubble",dojox.charting.plot2d.Base,{defaultParams:{hAxis:"x",vAxis:"y"},optionalParams:{},constructor:function(_2,_3){
-this.opt=dojo.clone(this.defaultParams);
-du.updateWithObject(this.opt,_3);
-this.series=[];
-this.hAxis=this.opt.hAxis;
-this.vAxis=this.opt.vAxis;
-},calculateAxes:function(_4){
-this._calc(_4,dc.collectSimpleStats(this.series));
-return this;
-},render:function(_5,_6){
-this.dirty=this.isDirty();
-if(this.dirty){
-dojo.forEach(this.series,_1);
-this.cleanGroup();
-var s=this.group;
-df.forEachRev(this.series,function(_7){
-_7.cleanGroup(s);
-});
-}
-var t=this.chart.theme,_8,_9,_a,_b,_c,ht=this._hScaler.scaler.getTransformerFromModel(this._hScaler),vt=this._vScaler.scaler.getTransformerFromModel(this._vScaler),_d=this.events();
-this.resetEvents();
-for(var i=this.series.length-1;i>=0;--i){
-var _e=this.series[i];
-if(!this.dirty&&!_e.dirty){
-continue;
-}
-_e.cleanGroup();
-if(!_e.data.length){
-_e.dirty=false;
-continue;
-}
-if(typeof _e.data[0]=="number"){
-console.warn("dojox.charting.plot2d.Bubble: the data in the following series cannot be rendered as a bubble chart; ",_e);
-continue;
-}
-var s=_e.group,_f=dojo.map(_e.data,function(v,i){
-return {x:ht(v.x)+_6.l,y:_5.height-_6.b-vt(v.y),radius:this._vScaler.bounds.scale*(v.size/2)};
-},this);
-if(_e.fill){
-_a=_e.fill;
-}else{
-if(_e.stroke){
-_a=_e.stroke;
-}else{
-_a=_e.dyn.color=new dojo.Color(t.next("color"));
-}
-}
-_e.dyn.fill=_a;
-_8=_e.dyn.stroke=_e.stroke?dc.makeStroke(_e.stroke):dc.augmentStroke(t.series.stroke,_a);
-var _10=null,_11=null,_12=null;
-if(this.opt.shadows&&_8){
-var sh=this.opt.shadows,_c=new dojo.Color([0,0,0,0.2]),_b=dojo.clone(_9?_9:_8);
-_b.color=_c;
-_b.width+=sh.dw?sh.dw:0;
-_e.dyn.shadow=_b;
-var _13=dojo.map(_f,function(_14){
-var sh=this.opt.shadows;
-return s.createCircle({cx:_14.x+sh.dx,cy:_14.y+sh.dy,r:_14.radius}).setStroke(_b).setFill(_c);
-},this);
-}
-if(_e.outline||t.series.outline){
-_9=dc.makeStroke(_e.outline?_e.outline:t.series.outline);
-_9.width=2*_9.width+_8.width;
-_e.dyn.outline=_9;
-_11=dojo.map(_f,function(_15){
-s.createCircle({cx:_15.x,cy:_15.y,r:_15.radius}).setStroke(_9);
-},this);
-}
-_10=dojo.map(_f,function(_16){
-return s.createCircle({cx:_16.x,cy:_16.y,r:_16.radius}).setStroke(_8).setFill(_a);
-},this);
-if(_d){
-dojo.forEach(_10,function(s,i){
-var o={element:"circle",index:i,run:_e,plot:this,hAxis:this.hAxis||null,vAxis:this.vAxis||null,shape:s,outline:_11&&_11[i]||null,shadow:_12&&_12[i]||null,x:_e.data[i].x,y:_e.data[i].y,r:_e.data[i].size/2,cx:_f[i].x,cy:_f[i].y,cr:_f[i].radius};
-this._connectEvents(s,o);
-},this);
-}
-_e.dirty=false;
-}
-this.dirty=false;
-return this;
-}});
+	var df = dojox.lang.functional, du = dojox.lang.utils,
+		dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	dojo.declare("dojox.charting.plot2d.Bubble", dojox.charting.plot2d.Base, {
+		//	summary:
+		//		A plot representing bubbles.  Note that data for Bubbles requires 3 parameters,
+		//		in the form of:  { x, y, size }, where size determines the size of the bubble.
+		defaultParams: {
+			hAxis: "x",		// use a horizontal axis named "x"
+			vAxis: "y",		// use a vertical axis named "y"
+			animate: null   // animate bars into place
+		},
+		optionalParams: {
+			// theme component
+			stroke:		{},
+			outline:	{},
+			shadow:		{},
+			fill:		{},
+			font:		"",
+			fontColor:	""
+		},
+
+		constructor: function(chart, kwArgs){
+			//	summary:
+			//		Create a plot of bubbles.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this plot belongs to.
+			//	kwArgs: dojox.charting.plot2d.__DefaultCtorArgs?
+			//		Optional keyword arguments object to help define plot parameters.
+			this.opt = dojo.clone(this.defaultParams);
+			du.updateWithObject(this.opt, kwArgs);
+			this.series = [];
+			this.hAxis = this.opt.hAxis;
+			this.vAxis = this.opt.vAxis;
+			this.animate = this.opt.animate;
+		},
+
+		//	override the render so that we are plotting only circles.
+		render: function(dim, offsets){
+			//	summary:
+			//		Run the calculations for any axes for this plot.
+			//	dim: Object
+			//		An object in the form of { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b}.
+			//	returns: dojox.charting.plot2d.Bubble
+			//		A reference to this plot for functional chaining.
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+			this.resetEvents();
+			this.dirty = this.isDirty();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+
+			var t = this.chart.theme,
+				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
+				events = this.events();
+
+			for(var i = this.series.length - 1; i >= 0; --i){
+				var run = this.series[i];
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				if(!run.data.length){
+					run.dirty = false;
+					t.skip();
+					continue;
+				}
+
+				if(typeof run.data[0] == "number"){
+					console.warn("dojox.charting.plot2d.Bubble: the data in the following series cannot be rendered as a bubble chart; ", run);
+					continue;
+				}
+
+				var theme = t.next("circle", [this.opt, run]), s = run.group,
+					points = dojo.map(run.data, function(v, i){
+						return v ? {
+							x: ht(v.x) + offsets.l,
+							y: dim.height - offsets.b - vt(v.y),
+							radius: this._vScaler.bounds.scale * (v.size / 2)
+						} : null;
+					}, this);
+
+				var frontCircles = null, outlineCircles = null, shadowCircles = null;
+
+				// make shadows if needed
+				if(theme.series.shadow){
+					shadowCircles = dojo.map(points, function(item){
+						if(item !== null){
+							var finalTheme = t.addMixin(theme, "circle", item, true),
+								shadow = finalTheme.series.shadow;
+							var shape = s.createCircle({
+								cx: item.x + shadow.dx, cy: item.y + shadow.dy, r: item.radius
+							}).setStroke(shadow).setFill(shadow.color);
+							if(this.animate){
+								this._animateBubble(shape, dim.height - offsets.b, item.radius);
+							}
+							return shape;
+						}
+						return null;
+					}, this);
+					if(shadowCircles.length){
+						run.dyn.shadow = shadowCircles[shadowCircles.length - 1].getStroke();
+					}
+				}
+
+				// make outlines if needed
+				if(theme.series.outline){
+					outlineCircles = dojo.map(points, function(item){
+						if(item !== null){
+							var finalTheme = t.addMixin(theme, "circle", item, true),
+								outline = dc.makeStroke(finalTheme.series.outline);
+							outline.width = 2 * outline.width + theme.series.stroke.width;
+							var shape = s.createCircle({
+								cx: item.x, cy: item.y, r: item.radius
+							}).setStroke(outline);
+							if(this.animate){
+								this._animateBubble(shape, dim.height - offsets.b, item.radius);
+							}
+							return shape;
+						}
+						return null;
+					}, this);
+					if(outlineCircles.length){
+						run.dyn.outline = outlineCircles[outlineCircles.length - 1].getStroke();
+					}
+				}
+
+				//	run through the data and add the circles.
+				frontCircles = dojo.map(points, function(item){
+					if(item !== null){
+						var finalTheme = t.addMixin(theme, "circle", item, true),
+							rect = {
+								x: item.x - item.radius,
+								y: item.y - item.radius,
+								width:  2 * item.radius,
+								height: 2 * item.radius
+							};
+						var specialFill = this._plotFill(finalTheme.series.fill, dim, offsets);
+						specialFill = this._shapeFill(specialFill, rect);
+						var shape = s.createCircle({
+							cx: item.x, cy: item.y, r: item.radius
+						}).setFill(specialFill).setStroke(finalTheme.series.stroke);
+						if(this.animate){
+							this._animateBubble(shape, dim.height - offsets.b, item.radius);
+						}
+						return shape;
+					}
+					return null;
+				}, this);
+				if(frontCircles.length){
+					run.dyn.fill   = frontCircles[frontCircles.length - 1].getFill();
+					run.dyn.stroke = frontCircles[frontCircles.length - 1].getStroke();
+				}
+
+				if(events){
+					var eventSeries = new Array(frontCircles.length);
+					dojo.forEach(frontCircles, function(s, i){
+						if(s !== null){
+							var o = {
+								element: "circle",
+								index:   i,
+								run:     run,
+								shape:   s,
+								outline: outlineCircles && outlineCircles[i] || null,
+								shadow:  shadowCircles && shadowCircles[i] || null,
+								x:       run.data[i].x,
+								y:       run.data[i].y,
+								r:       run.data[i].size / 2,
+								cx:      points[i].x,
+								cy:      points[i].y,
+								cr:      points[i].radius
+							};
+							this._connectEvents(o);
+							eventSeries[i] = o;
+						}
+					}, this);
+					this._eventSeries[run.name] = eventSeries;
+				}else{
+					delete this._eventSeries[run.name];
+				}
+
+				run.dirty = false;
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.Bubble
+		},
+		_animateBubble: function(shape, offset, size){
+			dojox.gfx.fx.animateTransform(dojo.delegate({
+				shape: shape,
+				duration: 1200,
+				transform: [
+					{name: "translate", start: [0, offset], end: [0, 0]},
+					{name: "scale", start: [0, 1/size], end: [1, 1]},
+					{name: "original"}
+				]
+			}, this.animate)).play();
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/Candlesticks.js b/dojox/charting/plot2d/Candlesticks.js
index 7dc74e8..8e000a6 100644
--- a/dojox/charting/plot2d/Candlesticks.js
+++ b/dojox/charting/plot2d/Candlesticks.js
@@ -1,119 +1,233 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Candlesticks"]){
-dojo._hasResource["dojox.charting.plot2d.Candlesticks"]=true;
 dojo.provide("dojox.charting.plot2d.Candlesticks");
+
 dojo.require("dojox.charting.plot2d.common");
 dojo.require("dojox.charting.plot2d.Base");
+
 dojo.require("dojox.lang.utils");
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.reversed");
+
 (function(){
-var df=dojox.lang.functional,du=dojox.lang.utils,dc=dojox.charting.plot2d.common,_1=df.lambda("item.purgeGroup()");
-dojo.declare("dojox.charting.plot2d.Candlesticks",dojox.charting.plot2d.Base,{defaultParams:{hAxis:"x",vAxis:"y",gap:2,shadows:null},optionalParams:{minBarSize:1,maxBarSize:1},constructor:function(_2,_3){
-this.opt=dojo.clone(this.defaultParams);
-du.updateWithObject(this.opt,_3);
-du.updateWithPattern(this.opt,_3,this.optionalParams);
-this.series=[];
-this.hAxis=this.opt.hAxis;
-this.vAxis=this.opt.vAxis;
-},collectStats:function(_4){
-var _5=dojo.clone(dc.defaultStats);
-for(var i=0;i<_4.length;i++){
-var _6=_4[i];
-if(!_6.data.length){
-continue;
-}
-var _7=_5.vmin,_8=_5.vmax;
-if(!("ymin" in _6)||!("ymax" in _6)){
-dojo.forEach(_6.data,function(_9,_a){
-var x=_9.x||_a+1;
-_5.hmin=Math.min(_5.hmin,x);
-_5.hmax=Math.max(_5.hmax,x);
-_5.vmin=Math.min(_5.vmin,_9.open,_9.close,_9.high,_9.low);
-_5.vmax=Math.max(_5.vmax,_9.open,_9.close,_9.high,_9.low);
-});
-}
-if("ymin" in _6){
-_5.vmin=Math.min(_7,_6.ymin);
-}
-if("ymax" in _6){
-_5.vmax=Math.max(_8,_6.ymax);
-}
-}
-return _5;
-},calculateAxes:function(_b){
-var _c=this.collectStats(this.series),t;
-_c.hmin-=0.5;
-_c.hmax+=0.5;
-this._calc(_b,_c);
-return this;
-},render:function(_d,_e){
-this.dirty=this.isDirty();
-if(this.dirty){
-dojo.forEach(this.series,_1);
-this.cleanGroup();
-var s=this.group;
-df.forEachRev(this.series,function(_f){
-_f.cleanGroup(s);
-});
-}
-var t=this.chart.theme,_10,_11,_12,f,gap,_13,ht=this._hScaler.scaler.getTransformerFromModel(this._hScaler),vt=this._vScaler.scaler.getTransformerFromModel(this._vScaler),_14=Math.max(0,this._vScaler.bounds.lower),_15=vt(_14),_16=this.events();
-f=dc.calculateBarSize(this._hScaler.bounds.scale,this.opt);
-gap=f.gap;
-_13=f.size;
-this.resetEvents();
-for(var i=this.series.length-1;i>=0;--i){
-var run=this.series[i];
-if(!this.dirty&&!run.dirty){
-continue;
-}
-run.cleanGroup();
-var s=run.group;
-if(!run.fill||!run.stroke){
-_10=run.dyn.color=new dojo.Color(t.next("color"));
-}
-_11=run.stroke?run.stroke:dc.augmentStroke(t.series.stroke,_10);
-_12=run.fill?run.fill:dc.augmentFill(t.series.fill,_10);
-for(var j=0;j<run.data.length;++j){
-var v=run.data[j];
-var x=ht(v.x||(j+0.5))+_e.l+gap,y=_d.height-_e.b,_17=vt(v.open),_18=vt(v.close),_19=vt(v.high),low=vt(v.low);
-if("mid" in v){
-var mid=vt(v.mid);
-}
-if(low>_19){
-var tmp=_19;
-_19=low;
-low=tmp;
-}
-if(_13>=1){
-var _1a=_17>_18;
-var _1b={x1:_13/2,x2:_13/2,y1:y-_19,y2:y-low},_1c={x:0,y:y-Math.max(_17,_18),width:_13,height:Math.max(_1a?_17-_18:_18-_17,1)};
-shape=s.createGroup();
-shape.setTransform({dx:x,dy:0});
-var _1d=shape.createGroup();
-_1d.createLine(_1b).setStroke(_11);
-_1d.createRect(_1c).setStroke(_11).setFill(_1a?_12:"white");
-if("mid" in v){
-_1d.createLine({x1:(_11.width||1),x2:_13-(_11.width||1),y1:y-mid,y2:y-mid}).setStroke(_1a?{color:"white"}:_11);
-}
-run.dyn.fill=_12;
-run.dyn.stroke=_11;
-if(_16){
-var o={element:"candlestick",index:j,run:run,plot:this,hAxis:this.hAxis||null,vAxis:this.vAxis||null,shape:_1d,x:x,y:y-Math.max(_17,_18),cx:_13/2,cy:(y-Math.max(_17,_18))+(Math.max(_1a?_17-_18:_18-_17,1)/2),width:_13,height:Math.max(_1a?_17-_18:_18-_17,1),data:v};
-this._connectEvents(shape,o);
-}
-}
-}
-run.dirty=false;
-}
-this.dirty=false;
-return this;
-}});
+	var df = dojox.lang.functional, du = dojox.lang.utils,
+		dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	//	Candlesticks are based on the Bars plot type; we expect the following passed
+	//	as values in a series:
+	//	{ x?, open, close, high, low, mid? }
+	//	if x is not provided, the array index is used.
+	//	failing to provide the OHLC values will throw an error.
+	dojo.declare("dojox.charting.plot2d.Candlesticks", dojox.charting.plot2d.Base, {
+		//	summary:
+		//		A plot that represents typical candlesticks (financial reporting, primarily).
+		//		Unlike most charts, the Candlestick expects data points to be represented by
+		//		an object of the form { x?, open, close, high, low, mid? }, where both
+		//		x and mid are optional parameters.  If x is not provided, the index of the
+		//		data array is used.
+		defaultParams: {
+			hAxis: "x",		// use a horizontal axis named "x"
+			vAxis: "y",		// use a vertical axis named "y"
+			gap:	2,		// gap between columns in pixels
+			animate: null   // animate bars into place
+		},
+		optionalParams: {
+			minBarSize:	1,	// minimal candle width in pixels
+			maxBarSize:	1,	// maximal candle width in pixels
+			// theme component
+			stroke:		{},
+			outline:	{},
+			shadow:		{},
+			fill:		{},
+			font:		"",
+			fontColor:	""
+		},
+
+		constructor: function(chart, kwArgs){
+			//	summary:
+			//		The constructor for a candlestick chart.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this plot belongs to.
+			//	kwArgs: dojox.charting.plot2d.__BarCtorArgs?
+			//		An optional keyword arguments object to help define the plot.
+			this.opt = dojo.clone(this.defaultParams);
+			du.updateWithObject(this.opt, kwArgs);
+			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
+			this.series = [];
+			this.hAxis = this.opt.hAxis;
+			this.vAxis = this.opt.vAxis;
+			this.animate = this.opt.animate;
+		},
+
+		collectStats: function(series){
+			//	summary:
+			//		Collect all statistics for drawing this chart.  Since the common
+			//		functionality only assumes x and y, Candlesticks must create it's own
+			//		stats (since data has no y value, but open/close/high/low instead).
+			//	series: dojox.charting.Series[]
+			//		The data series array to be drawn on this plot.
+			//	returns: Object
+			//		Returns an object in the form of { hmin, hmax, vmin, vmax }.
+
+			//	we have to roll our own, since we need to use all four passed
+			//	values to figure out our stats, and common only assumes x and y.
+			var stats = dojo.delegate(dc.defaultStats);
+			for(var i=0; i<series.length; i++){
+				var run = series[i];
+				if(!run.data.length){ continue; }
+				var old_vmin = stats.vmin, old_vmax = stats.vmax;
+				if(!("ymin" in run) || !("ymax" in run)){
+					dojo.forEach(run.data, function(val, idx){
+						if(val !== null){
+							var x = val.x || idx + 1;
+							stats.hmin = Math.min(stats.hmin, x);
+							stats.hmax = Math.max(stats.hmax, x);
+							stats.vmin = Math.min(stats.vmin, val.open, val.close, val.high, val.low);
+							stats.vmax = Math.max(stats.vmax, val.open, val.close, val.high, val.low);
+						}
+					});
+				}
+				if("ymin" in run){ stats.vmin = Math.min(old_vmin, run.ymin); }
+				if("ymax" in run){ stats.vmax = Math.max(old_vmax, run.ymax); }
+			}
+			return stats;	//	Object
+		},
+
+		getSeriesStats: function(){
+			//	summary:
+			//		Calculate the min/max on all attached series in both directions.
+			//	returns: Object
+			//		{hmin, hmax, vmin, vmax} min/max in both directions.
+			var stats = this.collectStats(this.series);
+			stats.hmin -= 0.5;
+			stats.hmax += 0.5;
+			return stats;
+		},
+
+		render: function(dim, offsets){
+			//	summary:
+			//		Run the calculations for any axes for this plot.
+			//	dim: Object
+			//		An object in the form of { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b}.
+			//	returns: dojox.charting.plot2d.Candlesticks
+			//		A reference to this plot for functional chaining.
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+			this.resetEvents();
+			this.dirty = this.isDirty();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+			var t = this.chart.theme, f, gap, width,
+				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
+				baseline = Math.max(0, this._vScaler.bounds.lower),
+				baselineHeight = vt(baseline),
+				events = this.events();
+			f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt);
+			gap = f.gap;
+			width = f.size;
+			for(var i = this.series.length - 1; i >= 0; --i){
+				var run = this.series[i];
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				var theme = t.next("candlestick", [this.opt, run]), s = run.group,
+					eventSeries = new Array(run.data.length);
+				for(var j = 0; j < run.data.length; ++j){
+					var v = run.data[j];
+					if(v !== null){
+						var finalTheme = t.addMixin(theme, "candlestick", v, true);
+
+						//	calculate the points we need for OHLC
+						var x = ht(v.x || (j+0.5)) + offsets.l + gap,
+							y = dim.height - offsets.b,
+							open = vt(v.open),
+							close = vt(v.close),
+							high = vt(v.high),
+							low = vt(v.low);
+						if("mid" in v){
+							var mid = vt(v.mid);
+						}
+						if(low > high){
+							var tmp = high;
+							high = low;
+							low = tmp;
+						}
+
+						if(width >= 1){
+							//	draw the line and rect, set up as a group and pass that to the events.
+							var doFill = open > close;
+							var line = { x1: width/2, x2: width/2, y1: y - high, y2: y - low },
+								rect = {
+									x: 0, y: y-Math.max(open, close),
+									width: width, height: Math.max(doFill ? open-close : close-open, 1)
+								};
+							shape = s.createGroup();
+							shape.setTransform({dx: x, dy: 0 });
+							var inner = shape.createGroup();
+							inner.createLine(line).setStroke(finalTheme.series.stroke);
+							inner.createRect(rect).setStroke(finalTheme.series.stroke).
+								setFill(doFill ? finalTheme.series.fill : "white");
+							if("mid" in v){
+								//	add the mid line.
+								inner.createLine({
+									x1: (finalTheme.series.stroke.width||1), x2: width - (finalTheme.series.stroke.width || 1),
+									y1: y - mid, y2: y - mid
+								}).setStroke(doFill ? "white" : finalTheme.series.stroke);
+							}
+
+							//	TODO: double check this.
+							run.dyn.fill   = finalTheme.series.fill;
+							run.dyn.stroke = finalTheme.series.stroke;
+							if(events){
+								var o = {
+									element: "candlestick",
+									index:   j,
+									run:     run,
+									shape:   inner,
+									x:       x,
+									y:       y-Math.max(open, close),
+									cx:		 width/2,
+									cy:		 (y-Math.max(open, close)) + (Math.max(doFill ? open-close : close-open, 1)/2),
+									width:	 width,
+									height:  Math.max(doFill ? open-close : close-open, 1),
+									data:	 v
+								};
+								this._connectEvents(o);
+								eventSeries[j] = o;
+							}
+						}
+						if(this.animate){
+							this._animateCandlesticks(shape, y - low, high - low);
+						}
+					}
+				}
+				this._eventSeries[run.name] = eventSeries;
+				run.dirty = false;
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.Candlesticks
+		},
+		_animateCandlesticks: function(shape, voffset, vsize){
+			dojox.gfx.fx.animateTransform(dojo.delegate({
+				shape: shape,
+				duration: 1200,
+				transform: [
+					{name: "translate", start: [0, voffset - (voffset/vsize)], end: [0, 0]},
+					{name: "scale", start: [1, 1/vsize], end: [1, 1]},
+					{name: "original"}
+				]
+			}, this.animate)).play();
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/ClusteredBars.js b/dojox/charting/plot2d/ClusteredBars.js
index 4187590..ced6f4b 100644
--- a/dojox/charting/plot2d/ClusteredBars.js
+++ b/dojox/charting/plot2d/ClusteredBars.js
@@ -1,84 +1,102 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.ClusteredBars"]){
-dojo._hasResource["dojox.charting.plot2d.ClusteredBars"]=true;
 dojo.provide("dojox.charting.plot2d.ClusteredBars");
+
 dojo.require("dojox.charting.plot2d.common");
 dojo.require("dojox.charting.plot2d.Bars");
+
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.reversed");
+
 (function(){
-var df=dojox.lang.functional,dc=dojox.charting.plot2d.common,_1=df.lambda("item.purgeGroup()");
-dojo.declare("dojox.charting.plot2d.ClusteredBars",dojox.charting.plot2d.Bars,{render:function(_2,_3){
-this.dirty=this.isDirty();
-if(this.dirty){
-dojo.forEach(this.series,_1);
-this.cleanGroup();
-var s=this.group;
-df.forEachRev(this.series,function(_4){
-_4.cleanGroup(s);
-});
-}
-var t=this.chart.theme,_5,_6,_7,f,_8,_9,_a,ht=this._hScaler.scaler.getTransformerFromModel(this._hScaler),vt=this._vScaler.scaler.getTransformerFromModel(this._vScaler),_b=Math.max(0,this._hScaler.bounds.lower),_c=ht(_b),_d=this.events();
-f=dc.calculateBarSize(this._vScaler.bounds.scale,this.opt,this.series.length);
-_8=f.gap;
-_9=_a=f.size;
-this.resetEvents();
-for(var i=this.series.length-1;i>=0;--i){
-var _e=this.series[i],_f=_a*(this.series.length-i-1);
-if(!this.dirty&&!_e.dirty){
-continue;
-}
-_e.cleanGroup();
-var s=_e.group;
-if(!_e.fill||!_e.stroke){
-_5=_e.dyn.color=new dojo.Color(t.next("color"));
-}
-_6=_e.stroke?_e.stroke:dc.augmentStroke(t.series.stroke,_5);
-_7=_e.fill?_e.fill:dc.augmentFill(t.series.fill,_5);
-for(var j=0;j<_e.data.length;++j){
-var _10=_e.data[j],v=typeof _10=="number"?_10:_10.y,hv=ht(v),_11=hv-_c,w=Math.abs(_11),_12=_5,_13=_7,_14=_6;
-if(typeof _10!="number"){
-if(_10.color){
-_12=new dojo.Color(_10.color);
-}
-if("fill" in _10){
-_13=_10.fill;
-}else{
-if(_10.color){
-_13=dc.augmentFill(t.series.fill,_12);
-}
-}
-if("stroke" in _10){
-_14=_10.stroke;
-}else{
-if(_10.color){
-_14=dc.augmentStroke(t.series.stroke,_12);
-}
-}
-}
-if(w>=1&&_9>=1){
-var _15=s.createRect({x:_3.l+(v<_b?hv:_c),y:_2.height-_3.b-vt(j+1.5)+_8+_f,width:w,height:_9}).setFill(_13).setStroke(_14);
-_e.dyn.fill=_15.getFill();
-_e.dyn.stroke=_15.getStroke();
-if(_d){
-var o={element:"bar",index:j,run:_e,plot:this,hAxis:this.hAxis||null,vAxis:this.vAxis||null,shape:_15,x:v,y:j+1.5};
-this._connectEvents(_15,o);
-}
-if(this.animate){
-this._animateBar(_15,_3.l+_c,-_11);
-}
-}
-}
-_e.dirty=false;
-}
-this.dirty=false;
-return this;
-}});
+	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	dojo.declare("dojox.charting.plot2d.ClusteredBars", dojox.charting.plot2d.Bars, {
+		//	summary:
+		//		A plot representing grouped or clustered bars (horizontal bars)
+		render: function(dim, offsets){
+			//	summary:
+			//		Run the calculations for any axes for this plot.
+			//	dim: Object
+			//		An object in the form of { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b}.
+			//	returns: dojox.charting.plot2d.ClusteredBars
+			//		A reference to this plot for functional chaining.
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+			this.resetEvents();
+			this.dirty = this.isDirty();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+			var t = this.chart.theme, f, gap, height, thickness,
+				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
+				baseline = Math.max(0, this._hScaler.bounds.lower),
+				baselineWidth = ht(baseline),
+				events = this.events();
+			f = dc.calculateBarSize(this._vScaler.bounds.scale, this.opt, this.series.length);
+			gap = f.gap;
+			height = thickness = f.size;
+			for(var i = this.series.length - 1; i >= 0; --i){
+				var run = this.series[i], shift = thickness * (this.series.length - i - 1);
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				var theme = t.next("bar", [this.opt, run]), s = run.group,
+					eventSeries = new Array(run.data.length);
+				for(var j = 0; j < run.data.length; ++j){
+					var value = run.data[j];
+					if(value !== null){
+						var v = typeof value == "number" ? value : value.y,
+							hv = ht(v),
+							width = hv - baselineWidth,
+							w = Math.abs(width),
+							finalTheme = typeof value != "number" ?
+								t.addMixin(theme, "bar", value, true) :
+								t.post(theme, "bar");
+						if(w >= 1 && height >= 1){
+							var rect = {
+								x: offsets.l + (v < baseline ? hv : baselineWidth),
+								y: dim.height - offsets.b - vt(j + 1.5) + gap + shift,
+								width: w, height: height
+							};
+							var specialFill = this._plotFill(finalTheme.series.fill, dim, offsets);
+							specialFill = this._shapeFill(specialFill, rect);
+							var shape = s.createRect(rect).setFill(specialFill).setStroke(finalTheme.series.stroke);
+							run.dyn.fill   = shape.getFill();
+							run.dyn.stroke = shape.getStroke();
+							if(events){
+								var o = {
+									element: "bar",
+									index:   j,
+									run:     run,
+									shape:   shape,
+									x:       v,
+									y:       j + 1.5
+								};
+								this._connectEvents(o);
+								eventSeries[j] = o;
+							}
+							if(this.animate){
+								this._animateBar(shape, offsets.l + baselineWidth, -width);
+							}
+						}
+					}
+				}
+				this._eventSeries[run.name] = eventSeries;
+				run.dirty = false;
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.ClusteredBars
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/ClusteredColumns.js b/dojox/charting/plot2d/ClusteredColumns.js
index cba2af4..8c19146 100644
--- a/dojox/charting/plot2d/ClusteredColumns.js
+++ b/dojox/charting/plot2d/ClusteredColumns.js
@@ -1,84 +1,102 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.ClusteredColumns"]){
-dojo._hasResource["dojox.charting.plot2d.ClusteredColumns"]=true;
 dojo.provide("dojox.charting.plot2d.ClusteredColumns");
+
 dojo.require("dojox.charting.plot2d.common");
 dojo.require("dojox.charting.plot2d.Columns");
+
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.reversed");
+
 (function(){
-var df=dojox.lang.functional,dc=dojox.charting.plot2d.common,_1=df.lambda("item.purgeGroup()");
-dojo.declare("dojox.charting.plot2d.ClusteredColumns",dojox.charting.plot2d.Columns,{render:function(_2,_3){
-this.dirty=this.isDirty();
-if(this.dirty){
-dojo.forEach(this.series,_1);
-this.cleanGroup();
-var s=this.group;
-df.forEachRev(this.series,function(_4){
-_4.cleanGroup(s);
-});
-}
-var t=this.chart.theme,_5,_6,_7,f,_8,_9,_a,ht=this._hScaler.scaler.getTransformerFromModel(this._hScaler),vt=this._vScaler.scaler.getTransformerFromModel(this._vScaler),_b=Math.max(0,this._vScaler.bounds.lower),_c=vt(_b),_d=this.events();
-f=dc.calculateBarSize(this._hScaler.bounds.scale,this.opt,this.series.length);
-_8=f.gap;
-_9=_a=f.size;
-this.resetEvents();
-for(var i=0;i<this.series.length;++i){
-var _e=this.series[i],_f=_a*i;
-if(!this.dirty&&!_e.dirty){
-continue;
-}
-_e.cleanGroup();
-var s=_e.group;
-if(!_e.fill||!_e.stroke){
-_5=_e.dyn.color=new dojo.Color(t.next("color"));
-}
-_6=_e.stroke?_e.stroke:dc.augmentStroke(t.series.stroke,_5);
-_7=_e.fill?_e.fill:dc.augmentFill(t.series.fill,_5);
-for(var j=0;j<_e.data.length;++j){
-var _10=_e.data[j],v=typeof _10=="number"?_10:_10.y,vv=vt(v),_11=vv-_c,h=Math.abs(_11),_12=_5,_13=_7,_14=_6;
-if(typeof _10!="number"){
-if(_10.color){
-_12=new dojo.Color(_10.color);
-}
-if("fill" in _10){
-_13=_10.fill;
-}else{
-if(_10.color){
-_13=dc.augmentFill(t.series.fill,_12);
-}
-}
-if("stroke" in _10){
-_14=_10.stroke;
-}else{
-if(_10.color){
-_14=dc.augmentStroke(t.series.stroke,_12);
-}
-}
-}
-if(_9>=1&&h>=1){
-var _15=s.createRect({x:_3.l+ht(j+0.5)+_8+_f,y:_2.height-_3.b-(v>_b?vv:_c),width:_9,height:h}).setFill(_13).setStroke(_14);
-_e.dyn.fill=_15.getFill();
-_e.dyn.stroke=_15.getStroke();
-if(_d){
-var o={element:"column",index:j,run:_e,plot:this,hAxis:this.hAxis||null,vAxis:this.vAxis||null,shape:_15,x:j+0.5,y:v};
-this._connectEvents(_15,o);
-}
-if(this.animate){
-this._animateColumn(_15,_2.height-_3.b-_c,h);
-}
-}
-}
-_e.dirty=false;
-}
-this.dirty=false;
-return this;
-}});
+	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	dojo.declare("dojox.charting.plot2d.ClusteredColumns", dojox.charting.plot2d.Columns, {
+		//	summary:
+		//		A plot representing grouped or clustered columns (vertical bars).
+		render: function(dim, offsets){
+			//	summary:
+			//		Run the calculations for any axes for this plot.
+			//	dim: Object
+			//		An object in the form of { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b}.
+			//	returns: dojox.charting.plot2d.ClusteredColumns
+			//		A reference to this plot for functional chaining.
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+			this.resetEvents();
+			this.dirty = this.isDirty();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+			var t = this.chart.theme, f, gap, width, thickness,
+				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
+				baseline = Math.max(0, this._vScaler.bounds.lower),
+				baselineHeight = vt(baseline),
+				events = this.events();
+			f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt, this.series.length);
+			gap = f.gap;
+			width = thickness = f.size;
+			for(var i = 0; i < this.series.length; ++i){
+				var run = this.series[i], shift = thickness * i;
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				var theme = t.next("column", [this.opt, run]), s = run.group,
+					eventSeries = new Array(run.data.length);
+				for(var j = 0; j < run.data.length; ++j){
+					var value = run.data[j];
+					if(value !== null){
+						var v = typeof value == "number" ? value : value.y,
+							vv = vt(v),
+							height = vv - baselineHeight,
+							h = Math.abs(height),
+							finalTheme = typeof value != "number" ?
+								t.addMixin(theme, "column", value, true) :
+								t.post(theme, "column");
+						if(width >= 1 && h >= 1){
+							var rect = {
+								x: offsets.l + ht(j + 0.5) + gap + shift,
+								y: dim.height - offsets.b - (v > baseline ? vv : baselineHeight),
+								width: width, height: h
+							};
+							var specialFill = this._plotFill(finalTheme.series.fill, dim, offsets);
+							specialFill = this._shapeFill(specialFill, rect);
+							var shape = s.createRect(rect).setFill(specialFill).setStroke(finalTheme.series.stroke);
+							run.dyn.fill   = shape.getFill();
+							run.dyn.stroke = shape.getStroke();
+							if(events){
+								var o = {
+									element: "column",
+									index:   j,
+									run:     run,
+									shape:   shape,
+									x:       j + 0.5,
+									y:       v
+								};
+								this._connectEvents(o);
+								eventSeries[j] = o;
+							}
+							if(this.animate){
+								this._animateColumn(shape, dim.height - offsets.b - baselineHeight, h);
+							}
+						}
+					}
+				}
+				this._eventSeries[run.name] = eventSeries;
+				run.dirty = false;
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.ClusteredColumns
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/Columns.js b/dojox/charting/plot2d/Columns.js
index b68e9ed..c636689 100644
--- a/dojox/charting/plot2d/Columns.js
+++ b/dojox/charting/plot2d/Columns.js
@@ -1,102 +1,161 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Columns"]){
-dojo._hasResource["dojox.charting.plot2d.Columns"]=true;
 dojo.provide("dojox.charting.plot2d.Columns");
+
 dojo.require("dojox.charting.plot2d.common");
 dojo.require("dojox.charting.plot2d.Base");
 dojo.require("dojox.gfx.fx");
+
 dojo.require("dojox.lang.utils");
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.reversed");
+
 (function(){
-var df=dojox.lang.functional,du=dojox.lang.utils,dc=dojox.charting.plot2d.common,_1=df.lambda("item.purgeGroup()");
-dojo.declare("dojox.charting.plot2d.Columns",dojox.charting.plot2d.Base,{defaultParams:{hAxis:"x",vAxis:"y",gap:0,shadows:null,animate:null},optionalParams:{minBarSize:1,maxBarSize:1},constructor:function(_2,_3){
-this.opt=dojo.clone(this.defaultParams);
-du.updateWithObject(this.opt,_3);
-du.updateWithPattern(this.opt,_3,this.optionalParams);
-this.series=[];
-this.hAxis=this.opt.hAxis;
-this.vAxis=this.opt.vAxis;
-this.animate=this.opt.animate;
-},calculateAxes:function(_4){
-var _5=dc.collectSimpleStats(this.series);
-_5.hmin-=0.5;
-_5.hmax+=0.5;
-this._calc(_4,_5);
-return this;
-},render:function(_6,_7){
-this.dirty=this.isDirty();
-if(this.dirty){
-dojo.forEach(this.series,_1);
-this.cleanGroup();
-var s=this.group;
-df.forEachRev(this.series,function(_8){
-_8.cleanGroup(s);
-});
-}
-var t=this.chart.theme,_9,_a,_b,f,_c,_d,ht=this._hScaler.scaler.getTransformerFromModel(this._hScaler),vt=this._vScaler.scaler.getTransformerFromModel(this._vScaler),_e=Math.max(0,this._vScaler.bounds.lower),_f=vt(_e),_10=this.events();
-f=dc.calculateBarSize(this._hScaler.bounds.scale,this.opt);
-_c=f.gap;
-_d=f.size;
-this.resetEvents();
-for(var i=this.series.length-1;i>=0;--i){
-var run=this.series[i];
-if(!this.dirty&&!run.dirty){
-continue;
-}
-run.cleanGroup();
-var s=run.group;
-if(!run.fill||!run.stroke){
-_9=run.dyn.color=new dojo.Color(t.next("color"));
-}
-_a=run.stroke?run.stroke:dc.augmentStroke(t.series.stroke,_9);
-_b=run.fill?run.fill:dc.augmentFill(t.series.fill,_9);
-for(var j=0;j<run.data.length;++j){
-var _11=run.data[j],v=typeof _11=="number"?_11:_11.y,vv=vt(v),_12=vv-_f,h=Math.abs(_12),_13=_9,_14=_b,_15=_a;
-if(typeof _11!="number"){
-if(_11.color){
-_13=new dojo.Color(_11.color);
-}
-if("fill" in _11){
-_14=_11.fill;
-}else{
-if(_11.color){
-_14=dc.augmentFill(t.series.fill,_13);
-}
-}
-if("stroke" in _11){
-_15=_11.stroke;
-}else{
-if(_11.color){
-_15=dc.augmentStroke(t.series.stroke,_13);
-}
-}
-}
-if(_d>=1&&h>=1){
-var _16=s.createRect({x:_7.l+ht(j+0.5)+_c,y:_6.height-_7.b-(v>_e?vv:_f),width:_d,height:h}).setFill(_14).setStroke(_15);
-run.dyn.fill=_16.getFill();
-run.dyn.stroke=_16.getStroke();
-if(_10){
-var o={element:"column",index:j,run:run,plot:this,hAxis:this.hAxis||null,vAxis:this.vAxis||null,shape:_16,x:j+0.5,y:v};
-this._connectEvents(_16,o);
-}
-if(this.animate){
-this._animateColumn(_16,_6.height-_7.b-_f,h);
-}
-}
-}
-run.dirty=false;
-}
-this.dirty=false;
-return this;
-},_animateColumn:function(_17,_18,_19){
-dojox.gfx.fx.animateTransform(dojo.delegate({shape:_17,duration:1200,transform:[{name:"translate",start:[0,_18-(_18/_19)],end:[0,0]},{name:"scale",start:[1,1/_19],end:[1,1]},{name:"original"}]},this.animate)).play();
-}});
+	var df = dojox.lang.functional, du = dojox.lang.utils,
+		dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	dojo.declare("dojox.charting.plot2d.Columns", dojox.charting.plot2d.Base, {
+		//	summary:
+		//		The plot object representing a column chart (vertical bars).
+		defaultParams: {
+			hAxis: "x",		// use a horizontal axis named "x"
+			vAxis: "y",		// use a vertical axis named "y"
+			gap:	0,		// gap between columns in pixels
+			animate: null   // animate bars into place
+		},
+		optionalParams: {
+			minBarSize:	1,	// minimal column width in pixels
+			maxBarSize:	1,	// maximal column width in pixels
+			// theme component
+			stroke:		{},
+			outline:	{},
+			shadow:		{},
+			fill:		{},
+			font:		"",
+			fontColor:	""
+		},
+
+		constructor: function(chart, kwArgs){
+			//	summary:
+			//		The constructor for a columns chart.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this plot belongs to.
+			//	kwArgs: dojox.charting.plot2d.__BarCtorArgs?
+			//		An optional keyword arguments object to help define the plot.
+			this.opt = dojo.clone(this.defaultParams);
+			du.updateWithObject(this.opt, kwArgs);
+			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
+			this.series = [];
+			this.hAxis = this.opt.hAxis;
+			this.vAxis = this.opt.vAxis;
+			this.animate = this.opt.animate;
+		},
+
+		getSeriesStats: function(){
+			//	summary:
+			//		Calculate the min/max on all attached series in both directions.
+			//	returns: Object
+			//		{hmin, hmax, vmin, vmax} min/max in both directions.
+			var stats = dc.collectSimpleStats(this.series);
+			stats.hmin -= 0.5;
+			stats.hmax += 0.5;
+			return stats;
+		},
+
+		render: function(dim, offsets){
+			//	summary:
+			//		Run the calculations for any axes for this plot.
+			//	dim: Object
+			//		An object in the form of { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b}.
+			//	returns: dojox.charting.plot2d.Columns
+			//		A reference to this plot for functional chaining.
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+			this.resetEvents();
+			this.dirty = this.isDirty();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+			var t = this.chart.theme, f, gap, width,
+				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
+				baseline = Math.max(0, this._vScaler.bounds.lower),
+				baselineHeight = vt(baseline),
+				events = this.events();
+			f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt);
+			gap = f.gap;
+			width = f.size;
+			for(var i = this.series.length - 1; i >= 0; --i){
+				var run = this.series[i];
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				var theme = t.next("column", [this.opt, run]), s = run.group,
+					eventSeries = new Array(run.data.length);
+				for(var j = 0; j < run.data.length; ++j){
+					var value = run.data[j];
+					if(value !== null){
+						var v = typeof value == "number" ? value : value.y,
+							vv = vt(v),
+							height = vv - baselineHeight,
+							h = Math.abs(height),
+							finalTheme = typeof value != "number" ?
+								t.addMixin(theme, "column", value, true) :
+								t.post(theme, "column");
+						if(width >= 1 && h >= 1){
+							var rect = {
+								x: offsets.l + ht(j + 0.5) + gap,
+								y: dim.height - offsets.b - (v > baseline ? vv : baselineHeight),
+								width: width, height: h
+							};
+							var specialFill = this._plotFill(finalTheme.series.fill, dim, offsets);
+							specialFill = this._shapeFill(specialFill, rect);
+							var shape = s.createRect(rect).setFill(specialFill).setStroke(finalTheme.series.stroke);
+							run.dyn.fill   = shape.getFill();
+							run.dyn.stroke = shape.getStroke();
+							if(events){
+								var o = {
+									element: "column",
+									index:   j,
+									run:     run,
+									shape:   shape,
+									x:       j + 0.5,
+									y:       v
+								};
+								this._connectEvents(o);
+								eventSeries[j] = o;
+							}
+							if(this.animate){
+								this._animateColumn(shape, dim.height - offsets.b - baselineHeight, h);
+							}
+						}
+					}
+				}
+				this._eventSeries[run.name] = eventSeries;
+				run.dirty = false;
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.Columns
+		},
+		_animateColumn: function(shape, voffset, vsize){
+			dojox.gfx.fx.animateTransform(dojo.delegate({
+				shape: shape,
+				duration: 1200,
+				transform: [
+					{name: "translate", start: [0, voffset - (voffset/vsize)], end: [0, 0]},
+					{name: "scale", start: [1, 1/vsize], end: [1, 1]},
+					{name: "original"}
+				]
+			}, this.animate)).play();
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/Default.js b/dojox/charting/plot2d/Default.js
index 7ba5628..7ca5bbf 100644
--- a/dojox/charting/plot2d/Default.js
+++ b/dojox/charting/plot2d/Default.js
@@ -1,150 +1,348 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Default"]){
-dojo._hasResource["dojox.charting.plot2d.Default"]=true;
 dojo.provide("dojox.charting.plot2d.Default");
+
 dojo.require("dojox.charting.plot2d.common");
 dojo.require("dojox.charting.plot2d.Base");
+
 dojo.require("dojox.lang.utils");
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.reversed");
-(function(){
-var df=dojox.lang.functional,du=dojox.lang.utils,dc=dojox.charting.plot2d.common,_1=df.lambda("item.purgeGroup()");
-dojo.declare("dojox.charting.plot2d.Default",dojox.charting.plot2d.Base,{defaultParams:{hAxis:"x",vAxis:"y",lines:true,areas:false,markers:false,shadows:0,tension:0},optionalParams:{},constructor:function(_2,_3){
-this.opt=dojo.clone(this.defaultParams);
-du.updateWithObject(this.opt,_3);
-this.series=[];
-this.hAxis=this.opt.hAxis;
-this.vAxis=this.opt.vAxis;
-},calculateAxes:function(_4){
-this._calc(_4,dc.collectSimpleStats(this.series));
-return this;
-},render:function(_5,_6){
-this.dirty=this.isDirty();
-if(this.dirty){
-dojo.forEach(this.series,_1);
-this.cleanGroup();
-var s=this.group;
-df.forEachRev(this.series,function(_7){
-_7.cleanGroup(s);
+dojo.require("dojox.gfx.fx");
+
+/*=====
+dojo.declare("dojox.charting.plot2d.__DefaultCtorArgs", dojox.charting.plot2d.__PlotCtorArgs, {
+	//	summary:
+	//		The arguments used for any/most plots.
+
+	//	hAxis: String?
+	//		The horizontal axis name.
+	hAxis: "x",
+
+	//	vAxis: String?
+	//		The vertical axis name
+	vAxis: "y",
+
+	//	lines: Boolean?
+	//		Whether or not to draw lines on this plot.  Defaults to true.
+	lines:   true,
+
+	//	areas: Boolean?
+	//		Whether or not to draw areas on this plot. Defaults to false.
+	areas:   false,
+
+	//	markers: Boolean?
+	//		Whether or not to draw markers at data points on this plot. Default is false.
+	markers: false,
+
+	//	tension: Number|String?
+	//		Whether or not to apply 'tensioning' to the lines on this chart.
+	//		Options include a number, "X", "x", or "S"; if a number is used, the
+	//		simpler bezier curve calculations are used to draw the lines.  If X, x or S
+	//		is used, the more accurate smoothing algorithm is used.
+	tension: "",
+
+	//	animate: Boolean?
+	//		Whether or not to animate the chart to place.
+	animate: false,
+
+	//	stroke: dojox.gfx.Stroke?
+	//		An optional stroke to use for any series on the plot.
+	stroke:		{},
+
+	//	outline: dojox.gfx.Stroke?
+	//		An optional stroke used to outline any series on the plot.
+	outline:	{},
+
+	//	shadow: dojox.gfx.Stroke?
+	//		An optional stroke to use to draw any shadows for a series on a plot.
+	shadow:		{},
+
+	//	fill: dojox.gfx.Fill?
+	//		Any fill to be used for elements on the plot (such as areas).
+	fill:		{},
+
+	//	font: String?
+	//		A font definition to be used for labels and other text-based elements on the plot.
+	font:		"",
+
+	//	fontColor: String|dojo.Color?
+	//		The color to be used for any text-based elements on the plot.
+	fontColor:	"",
+
+	//	markerStroke: dojo.gfx.Stroke?
+	//		An optional stroke to use for any markers on the plot.
+	markerStroke:		{},
+
+	//	markerOutline: dojo.gfx.Stroke?
+	//		An optional outline to use for any markers on the plot.
+	markerOutline:		{},
+
+	//	markerShadow: dojo.gfx.Stroke?
+	//		An optional shadow to use for any markers on the plot.
+	markerShadow:		{},
+
+	//	markerFill: dojo.gfx.Fill?
+	//		An optional fill to use for any markers on the plot.
+	markerFill:			{},
+
+	//	markerFont: String?
+	//		An optional font definition to use for any markers on the plot.
+	markerFont:			"",
+
+	//	markerFontColor: String|dojo.Color?
+	//		An optional color to use for any marker text on the plot.
+	markerFontColor:	""
 });
-}
-var t=this.chart.theme,_8,_9,_a,_b,_c=this.events();
-this.resetEvents();
-for(var i=this.series.length-1;i>=0;--i){
-var _d=this.series[i];
-if(!this.dirty&&!_d.dirty){
-continue;
-}
-_d.cleanGroup();
-if(!_d.data.length){
-_d.dirty=false;
-continue;
-}
-var s=_d.group,_e,ht=this._hScaler.scaler.getTransformerFromModel(this._hScaler),vt=this._vScaler.scaler.getTransformerFromModel(this._vScaler);
-if(typeof _d.data[0]=="number"){
-_e=dojo.map(_d.data,function(v,i){
-return {x:ht(i+1)+_6.l,y:_5.height-_6.b-vt(v)};
-},this);
-}else{
-_e=dojo.map(_d.data,function(v,i){
-return {x:ht(v.x)+_6.l,y:_5.height-_6.b-vt(v.y)};
-},this);
-}
-if(!_d.fill||!_d.stroke){
-_a=_d.dyn.color=new dojo.Color(t.next("color"));
-}
-var _f=this.opt.tension?dc.curve(_e,this.opt.tension):"";
-if(this.opt.areas){
-var _10=_d.fill?_d.fill:dc.augmentFill(t.series.fill,_a);
-var _11=dojo.clone(_e);
-if(this.opt.tension){
-var _12="L"+_11[_11.length-1].x+","+(_5.height-_6.b)+" L"+_11[0].x+","+(_5.height-_6.b)+" L"+_11[0].x+","+_11[0].y;
-_d.dyn.fill=s.createPath(_f+" "+_12).setFill(_10).getFill();
-}else{
-_11.push({x:_e[_e.length-1].x,y:_5.height-_6.b});
-_11.push({x:_e[0].x,y:_5.height-_6.b});
-_11.push(_e[0]);
-_d.dyn.fill=s.createPolyline(_11).setFill(_10).getFill();
-}
-}
-if(this.opt.lines||this.opt.markers){
-_8=_d.dyn.stroke=_d.stroke?dc.makeStroke(_d.stroke):dc.augmentStroke(t.series.stroke,_a);
-if(_d.outline||t.series.outline){
-_9=_d.dyn.outline=dc.makeStroke(_d.outline?_d.outline:t.series.outline);
-_9.width=2*_9.width+_8.width;
-}
-}
-if(this.opt.markers){
-_b=_d.dyn.marker=_d.marker?_d.marker:t.next("marker");
-}
-var _13=null,_14=null,_15=null;
-if(this.opt.shadows&&_8){
-var sh=this.opt.shadows,_16=new dojo.Color([0,0,0,0.3]),_17=dojo.map(_e,function(c){
-return {x:c.x+sh.dx,y:c.y+sh.dy};
-}),_18=dojo.clone(_9?_9:_8);
-_18.color=_16;
-_18.width+=sh.dw?sh.dw:0;
-if(this.opt.lines){
-if(this.opt.tension){
-_d.dyn.shadow=s.createPath(dc.curve(_17,this.opt.tension)).setStroke(_18).getStroke();
-}else{
-_d.dyn.shadow=s.createPolyline(_17).setStroke(_18).getStroke();
-}
-}
-if(this.opt.markers){
-_15=dojo.map(_17,function(c){
-return s.createPath("M"+c.x+" "+c.y+" "+_b).setStroke(_18).setFill(_16);
-},this);
-}
-}
-if(this.opt.lines){
-if(_9){
-if(this.opt.tension){
-_d.dyn.outline=s.createPath(_f).setStroke(_9).getStroke();
-}else{
-_d.dyn.outline=s.createPolyline(_e).setStroke(_9).getStroke();
-}
-}
-if(this.opt.tension){
-_d.dyn.stroke=s.createPath(_f).setStroke(_8).getStroke();
-}else{
-_d.dyn.stroke=s.createPolyline(_e).setStroke(_8).getStroke();
-}
-}
-if(this.opt.markers){
-_13=new Array(_e.length);
-_14=new Array(_e.length);
-dojo.forEach(_e,function(c,i){
-var _19="M"+c.x+" "+c.y+" "+_b;
-if(_9){
-_14[i]=s.createPath(_19).setStroke(_9);
-}
-_13[i]=s.createPath(_19).setStroke(_8).setFill(_8.color);
-},this);
-if(_c){
-dojo.forEach(_13,function(s,i){
-var o={element:"marker",index:i,run:_d,plot:this,hAxis:this.hAxis||null,vAxis:this.vAxis||null,shape:s,outline:_14[i]||null,shadow:_15&&_15[i]||null,cx:_e[i].x,cy:_e[i].y};
-if(typeof _d.data[0]=="number"){
-o.x=i+1;
-o.y=_d.data[i];
-}else{
-o.x=_d.data[i].x;
-o.y=_d.data[i].y;
-}
-this._connectEvents(s,o);
-},this);
-}
-}
-_d.dirty=false;
-}
-this.dirty=false;
-return this;
-}});
+=====*/
+(function(){
+	var df = dojox.lang.functional, du = dojox.lang.utils,
+		dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	var DEFAULT_ANIMATION_LENGTH = 1200;	// in ms
+
+	dojo.declare("dojox.charting.plot2d.Default", dojox.charting.plot2d.Base, {
+		defaultParams: {
+			hAxis: "x",		// use a horizontal axis named "x"
+			vAxis: "y",		// use a vertical axis named "y"
+			lines:   true,	// draw lines
+			areas:   false,	// draw areas
+			markers: false,	// draw markers
+			tension: "",	// draw curved lines (tension is "X", "x", or "S")
+			animate: false	// animate chart to place
+		},
+		optionalParams: {
+			// theme component
+			stroke:		{},
+			outline:	{},
+			shadow:		{},
+			fill:		{},
+			font:		"",
+			fontColor:	"",
+			markerStroke:		{},
+			markerOutline:		{},
+			markerShadow:		{},
+			markerFill:			{},
+			markerFont:			"",
+			markerFontColor:	""
+		},
+
+		constructor: function(chart, kwArgs){
+			//	summary:
+			//		Return a new plot.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this plot belongs to.
+			//	kwArgs: dojox.charting.plot2d.__DefaultCtorArgs?
+			//		An optional arguments object to help define this plot.
+			this.opt = dojo.clone(this.defaultParams);
+			du.updateWithObject(this.opt, kwArgs);
+			this.series = [];
+			this.hAxis = this.opt.hAxis;
+			this.vAxis = this.opt.vAxis;
+
+			// animation properties
+			this.animate = this.opt.animate;
+		},
+
+		render: function(dim, offsets){
+			//	summary:
+			//		Render/draw everything on this plot.
+			//	dim: Object
+			//		An object of the form { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b }
+			//	returns: dojox.charting.plot2d.Default
+			//		A reference to this plot for functional chaining.
+
+			// make sure all the series is not modified
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+
+			this.resetEvents();
+			this.dirty = this.isDirty();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				this.group.setTransform(null);
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+			var t = this.chart.theme, stroke, outline, marker, events = this.events();
+
+			for(var i = this.series.length - 1; i >= 0; --i){
+				var run = this.series[i];
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				if(!run.data.length){
+					run.dirty = false;
+					t.skip();
+					continue;
+				}
+
+				var theme = t.next(this.opt.areas ? "area" : "line", [this.opt, run], true),
+					s = run.group, rsegments = [], startindexes = [], rseg = null, lpoly,
+					ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+					vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
+					eventSeries = this._eventSeries[run.name] = new Array(run.data.length);
+
+                // split the run data into dense segments (each containing no nulls)
+                for(var j = 0; j < run.data.length; j++){
+                    if(run.data[j] != null){
+                        if(!rseg){
+                            rseg = [];
+                            startindexes.push(j);
+                            rsegments.push(rseg)
+                        }
+                        rseg.push(run.data[j]);
+                    }else{
+                        rseg = null;
+                    }
+                }
+
+                for(var seg = 0; seg < rsegments.length; seg++){
+					if(typeof rsegments[seg][0] == "number"){
+						lpoly = dojo.map(rsegments[seg], function(v, i){
+							return {
+								x: ht(i + startindexes[seg] + 1) + offsets.l,
+								y: dim.height - offsets.b - vt(v)
+							};
+						}, this);
+					}else{
+						lpoly = dojo.map(rsegments[seg], function(v, i){
+							return {
+								x: ht(v.x) + offsets.l,
+								y: dim.height - offsets.b - vt(v.y)
+							};
+						}, this);
+					}
+
+					var lpath = this.opt.tension ? dc.curve(lpoly, this.opt.tension) : "";
+
+					if(this.opt.areas && lpoly.length > 1){
+						var fill = theme.series.fill;
+						var apoly = dojo.clone(lpoly);
+						if(this.opt.tension){
+							var apath = "L" + apoly[apoly.length-1].x + "," + (dim.height - offsets.b) +
+								" L" + apoly[0].x + "," + (dim.height - offsets.b) +
+								" L" + apoly[0].x + "," + apoly[0].y;
+							run.dyn.fill = s.createPath(lpath + " " + apath).setFill(fill).getFill();
+						} else {
+							apoly.push({x: lpoly[lpoly.length - 1].x, y: dim.height - offsets.b});
+							apoly.push({x: lpoly[0].x, y: dim.height - offsets.b});
+							apoly.push(lpoly[0]);
+							run.dyn.fill = s.createPolyline(apoly).setFill(fill).getFill();
+						}
+					}
+					if(this.opt.lines || this.opt.markers){
+						// need a stroke
+						stroke = theme.series.stroke;
+						if(theme.series.outline){
+							outline = run.dyn.outline = dc.makeStroke(theme.series.outline);
+							outline.width = 2 * outline.width + stroke.width;
+						}
+					}
+					if(this.opt.markers){
+						run.dyn.marker = theme.symbol;
+					}
+					var frontMarkers = null, outlineMarkers = null, shadowMarkers = null;
+					if(stroke && theme.series.shadow && lpoly.length > 1){
+						var shadow = theme.series.shadow,
+							spoly = dojo.map(lpoly, function(c){
+								return {x: c.x + shadow.dx, y: c.y + shadow.dy};
+							});
+						if(this.opt.lines){
+							if(this.opt.tension){
+								run.dyn.shadow = s.createPath(dc.curve(spoly, this.opt.tension)).setStroke(shadow).getStroke();
+							} else {
+								run.dyn.shadow = s.createPolyline(spoly).setStroke(shadow).getStroke();
+							}
+						}
+						if(this.opt.markers && theme.marker.shadow){
+							shadow = theme.marker.shadow;
+							shadowMarkers = dojo.map(spoly, function(c){
+								return s.createPath("M" + c.x + " " + c.y + " " + theme.symbol).
+									setStroke(shadow).setFill(shadow.color);
+							}, this);
+						}
+					}
+					if(this.opt.lines && lpoly.length > 1){
+						if(outline){
+							if(this.opt.tension){
+								run.dyn.outline = s.createPath(lpath).setStroke(outline).getStroke();
+							} else {
+								run.dyn.outline = s.createPolyline(lpoly).setStroke(outline).getStroke();
+							}
+						}
+						if(this.opt.tension){
+							run.dyn.stroke = s.createPath(lpath).setStroke(stroke).getStroke();
+						} else {
+							run.dyn.stroke = s.createPolyline(lpoly).setStroke(stroke).getStroke();
+						}
+					}
+					if(this.opt.markers){
+						frontMarkers = new Array(lpoly.length);
+						outlineMarkers = new Array(lpoly.length);
+						outline = null;
+						if(theme.marker.outline){
+							outline = dc.makeStroke(theme.marker.outline);
+							outline.width = 2 * outline.width + (theme.marker.stroke ? theme.marker.stroke.width : 0);
+						}
+						dojo.forEach(lpoly, function(c, i){
+							var path = "M" + c.x + " " + c.y + " " + theme.symbol;
+							if(outline){
+								outlineMarkers[i] = s.createPath(path).setStroke(outline);
+							}
+							frontMarkers[i] = s.createPath(path).setStroke(theme.marker.stroke).setFill(theme.marker.fill);
+						}, this);
+						if(events){
+							dojo.forEach(frontMarkers, function(s, i){
+								var o = {
+									element: "marker",
+									index:   i + startindexes[seg],
+									run:     run,
+									shape:   s,
+									outline: outlineMarkers[i] || null,
+									shadow:  shadowMarkers && shadowMarkers[i] || null,
+									cx:      lpoly[i].x,
+									cy:      lpoly[i].y
+								};
+								if(typeof rsegments[seg][0] == "number"){
+									o.x = i + startindexes[seg] + 1;
+									o.y = rsegments[seg][i];
+								}else{
+									o.x = rsegments[seg][i].x;
+									o.y = rsegments[seg][i].y;
+								}
+								this._connectEvents(o);
+								eventSeries[i + startindexes[seg]] = o;
+							}, this);
+						}else{
+							delete this._eventSeries[run.name];
+						}
+					}
+                }
+				run.dirty = false;
+			}
+			if(this.animate){
+				// grow from the bottom
+				var plotGroup = this.group;
+				dojox.gfx.fx.animateTransform(dojo.delegate({
+					shape: plotGroup,
+					duration: DEFAULT_ANIMATION_LENGTH,
+					transform:[
+						{name:"translate", start: [0, dim.height - offsets.b], end: [0, 0]},
+						{name:"scale", start: [1, 0], end:[1, 1]},
+						{name:"original"}
+					]
+				}, this.animate)).play();
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.Default
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/Grid.js b/dojox/charting/plot2d/Grid.js
index f905407..928d38a 100644
--- a/dojox/charting/plot2d/Grid.js
+++ b/dojox/charting/plot2d/Grid.js
@@ -1,85 +1,287 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Grid"]){
-dojo._hasResource["dojox.charting.plot2d.Grid"]=true;
 dojo.provide("dojox.charting.plot2d.Grid");
+
 dojo.require("dojox.charting.Element");
 dojo.require("dojox.charting.plot2d.common");
 dojo.require("dojox.lang.functional");
-(function(){
-var du=dojox.lang.utils;
-dojo.declare("dojox.charting.plot2d.Grid",dojox.charting.Element,{defaultParams:{hAxis:"x",vAxis:"y",hMajorLines:true,hMinorLines:false,vMajorLines:true,vMinorLines:false,hStripes:"none",vStripes:"none"},optionalParams:{},constructor:function(_1,_2){
-this.opt=dojo.clone(this.defaultParams);
-du.updateWithObject(this.opt,_2);
-this.hAxis=this.opt.hAxis;
-this.vAxis=this.opt.vAxis;
-this.dirty=true;
-},clear:function(){
-this._hAxis=null;
-this._vAxis=null;
-this.dirty=true;
-return this;
-},setAxis:function(_3){
-if(_3){
-this[_3.vertical?"_vAxis":"_hAxis"]=_3;
-}
-return this;
-},addSeries:function(_4){
-return this;
-},calculateAxes:function(_5){
-return this;
-},isDirty:function(){
-return this.dirty||this._hAxis&&this._hAxis.dirty||this._vAxis&&this._vAxis.dirty;
-},getRequiredColors:function(){
-return 0;
-},render:function(_6,_7){
-this.dirty=this.isDirty();
-if(!this.dirty){
-return this;
-}
-this.cleanGroup();
-var s=this.group,ta=this.chart.theme.axis;
-try{
-var _8=this._vAxis.getScaler(),vt=_8.scaler.getTransformerFromModel(_8),_9=this._vAxis.getTicks();
-if(this.opt.hMinorLines){
-dojo.forEach(_9.minor,function(_a){
-var y=_6.height-_7.b-vt(_a.value);
-s.createLine({x1:_7.l,y1:y,x2:_6.width-_7.r,y2:y}).setStroke(ta.minorTick);
-});
-}
-if(this.opt.hMajorLines){
-dojo.forEach(_9.major,function(_b){
-var y=_6.height-_7.b-vt(_b.value);
-s.createLine({x1:_7.l,y1:y,x2:_6.width-_7.r,y2:y}).setStroke(ta.majorTick);
-});
-}
-}
-catch(e){
-}
-try{
-var _c=this._hAxis.getScaler(),ht=_c.scaler.getTransformerFromModel(_c),_9=this._hAxis.getTicks();
-if(_9&&this.opt.vMinorLines){
-dojo.forEach(_9.minor,function(_d){
-var x=_7.l+ht(_d.value);
-s.createLine({x1:x,y1:_7.t,x2:x,y2:_6.height-_7.b}).setStroke(ta.minorTick);
-});
-}
-if(_9&&this.opt.vMajorLines){
-dojo.forEach(_9.major,function(_e){
-var x=_7.l+ht(_e.value);
-s.createLine({x1:x,y1:_7.t,x2:x,y2:_6.height-_7.b}).setStroke(ta.majorTick);
+dojo.require("dojox.lang.utils");
+
+/*=====
+dojo.declare("dojox.charting.plot2d.__GridCtorArgs", dojox.charting.plot2d.__DefaultCtorArgs, {
+	//	summary:
+	//		A special keyword arguments object that is specific to a grid "plot".
+
+	//	hMajorLines: Boolean?
+	//		Whether to show lines at the major ticks along the horizontal axis. Default is true.
+	hMajorLines: true,
+
+	//	hMinorLines: Boolean?
+	//		Whether to show lines at the minor ticks along the horizontal axis. Default is false.
+	hMinorLines: false,
+
+	//	vMajorLines: Boolean?
+	//		Whether to show lines at the major ticks along the vertical axis. Default is true.
+	vMajorLines: true,
+
+	//	vMinorLines: Boolean?
+	//		Whether to show lines at the major ticks along the vertical axis. Default is false.
+	vMinorLines: false,
+
+	//	hStripes: String?
+	//		Whether or not to show stripes (alternating fills) along the horizontal axis. Default is "none".
+	hStripes: "none",
+
+	//	vStripes: String?
+	//		Whether or not to show stripes (alternating fills) along the vertical axis. Default is "none".
+	vStripes: "none"
 });
-}
-}
-catch(e){
-}
-this.dirty=false;
-return this;
-}});
+=====*/
+(function(){
+	var du = dojox.lang.utils, dc = dojox.charting.plot2d.common;
+
+	dojo.declare("dojox.charting.plot2d.Grid", dojox.charting.Element, {
+		//	summary:
+		//		A "faux" plot that can be placed behind other plots to represent
+		//		a grid against which other plots can be easily measured.
+		defaultParams: {
+			hAxis: "x",			// use a horizontal axis named "x"
+			vAxis: "y",			// use a vertical axis named "y"
+			hMajorLines: true,	// draw horizontal major lines
+			hMinorLines: false,	// draw horizontal minor lines
+			vMajorLines: true,	// draw vertical major lines
+			vMinorLines: false,	// draw vertical minor lines
+			hStripes: "none",	// TBD
+			vStripes: "none",	// TBD
+			animate: null   // animate bars into place
+		},
+		optionalParams: {},	// no optional parameters
+
+		constructor: function(chart, kwArgs){
+			//	summary:
+			//		Create the faux Grid plot.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this plot belongs to.
+			//	kwArgs: dojox.charting.plot2d.__GridCtorArgs?
+			//		An optional keyword arguments object to help define the parameters of the underlying grid.
+			this.opt = dojo.clone(this.defaultParams);
+			du.updateWithObject(this.opt, kwArgs);
+			this.hAxis = this.opt.hAxis;
+			this.vAxis = this.opt.vAxis;
+			this.dirty = true;
+			this.animate = this.opt.animate;
+			this.zoom = null,
+			this.zoomQueue = [];	// zooming action task queue
+			this.lastWindow = {vscale: 1, hscale: 1, xoffset: 0, yoffset: 0};
+		},
+		clear: function(){
+			//	summary:
+			//		Clear out any parameters set on this plot.
+			//	returns: dojox.charting.plot2d.Grid
+			//		The reference to this plot for functional chaining.
+			this._hAxis = null;
+			this._vAxis = null;
+			this.dirty = true;
+			return this;	//	dojox.charting.plot2d.Grid
+		},
+		setAxis: function(axis){
+			//	summary:
+			//		Set an axis for this plot.
+			//	returns: dojox.charting.plot2d.Grid
+			//		The reference to this plot for functional chaining.
+			if(axis){
+				this[axis.vertical ? "_vAxis" : "_hAxis"] = axis;
+			}
+			return this;	//	dojox.charting.plot2d.Grid
+		},
+		addSeries: function(run){
+			//	summary:
+			//		Ignored but included as a dummy method.
+			//	returns: dojox.charting.plot2d.Grid
+			//		The reference to this plot for functional chaining.
+			return this;	//	dojox.charting.plot2d.Grid
+		},
+		getSeriesStats: function(){
+			//	summary:
+			//		Returns default stats (irrelevant for this type of plot).
+			//	returns: Object
+			//		{hmin, hmax, vmin, vmax} min/max in both directions.
+			return dojo.delegate(dc.defaultStats);
+		},
+		initializeScalers: function(){
+			//	summary:
+			//		Does nothing (irrelevant for this type of plot).
+			return this;
+		},
+		isDirty: function(){
+			//	summary:
+			//		Return whether or not this plot needs to be redrawn.
+			//	returns: Boolean
+			//		If this plot needs to be rendered, this will return true.
+			return this.dirty || this._hAxis && this._hAxis.dirty || this._vAxis && this._vAxis.dirty;	//	Boolean
+		},
+		performZoom: function(dim, offsets){
+			//	summary:
+			//		Create/alter any zooming windows on this plot.
+			//	dim: Object
+			//		An object of the form { width, height }.
+			//	offsets: Object
+			//		An object of the form { l, r, t, b }.
+			//	returns: dojox.charting.plot2d.Grid
+			//		A reference to this plot for functional chaining.
+
+			// get current zooming various
+			var vs = this._vAxis.scale || 1,
+				hs = this._hAxis.scale || 1,
+				vOffset = dim.height - offsets.b,
+				hBounds = this._hAxis.getScaler().bounds,
+				xOffset = (hBounds.from - hBounds.lower) * hBounds.scale,
+				vBounds = this._vAxis.getScaler().bounds,
+				yOffset = (vBounds.from - vBounds.lower) * vBounds.scale;
+				// get incremental zooming various
+				rVScale = vs / this.lastWindow.vscale,
+				rHScale = hs / this.lastWindow.hscale,
+				rXOffset = (this.lastWindow.xoffset - xOffset)/
+					((this.lastWindow.hscale == 1)? hs : this.lastWindow.hscale),
+				rYOffset = (yOffset - this.lastWindow.yoffset)/
+					((this.lastWindow.vscale == 1)? vs : this.lastWindow.vscale),
+
+				shape = this.group,
+				anim = dojox.gfx.fx.animateTransform(dojo.delegate({
+					shape: shape,
+					duration: 1200,
+					transform:[
+						{name:"translate", start:[0, 0], end: [offsets.l * (1 - rHScale), vOffset * (1 - rVScale)]},
+						{name:"scale", start:[1, 1], end: [rHScale, rVScale]},
+						{name:"original"},
+						{name:"translate", start: [0, 0], end: [rXOffset, rYOffset]}
+					]}, this.zoom));
+
+			dojo.mixin(this.lastWindow, {vscale: vs, hscale: hs, xoffset: xOffset, yoffset: yOffset});
+			//add anim to zooming action queue,
+			//in order to avoid several zooming action happened at the same time
+			this.zoomQueue.push(anim);
+			//perform each anim one by one in zoomQueue
+			dojo.connect(anim, "onEnd", this, function(){
+				this.zoom = null;
+				this.zoomQueue.shift();
+				if(this.zoomQueue.length > 0){
+					this.zoomQueue[0].play();
+				}
+			});
+			if(this.zoomQueue.length == 1){
+				this.zoomQueue[0].play();
+			}
+			return this;	//	dojox.charting.plot2d.Grid
+		},
+		getRequiredColors: function(){
+			//	summary:
+			//		Ignored but included as a dummy method.
+			//	returns: Number
+			//		Returns 0, since there are no series associated with this plot type.
+			return 0;	//	Number
+		},
+		render: function(dim, offsets){
+			//	summary:
+			//		Render the plot on the chart.
+			//	dim: Object
+			//		An object of the form { width, height }.
+			//	offsets: Object
+			//		An object of the form { l, r, t, b }.
+			//	returns: dojox.charting.plot2d.Grid
+			//		A reference to this plot for functional chaining.
+			if(this.zoom){
+				return this.performZoom(dim, offsets);
+			}
+			this.dirty = this.isDirty();
+			if(!this.dirty){ return this; }
+			this.cleanGroup();
+			var s = this.group, ta = this.chart.theme.axis;
+			// draw horizontal stripes and lines
+			try{
+				var vScaler = this._vAxis.getScaler(),
+					vt = vScaler.scaler.getTransformerFromModel(vScaler),
+					ticks = this._vAxis.getTicks();
+				if(this.opt.hMinorLines){
+					dojo.forEach(ticks.minor, function(tick){
+						var y = dim.height - offsets.b - vt(tick.value);
+						var hMinorLine = s.createLine({
+							x1: offsets.l,
+							y1: y,
+							x2: dim.width - offsets.r,
+							y2: y
+						}).setStroke(ta.minorTick);
+						if(this.animate){
+							this._animateGrid(hMinorLine, "h", offsets.l, offsets.r + offsets.l - dim.width);
+						}
+					}, this);
+				}
+				if(this.opt.hMajorLines){
+					dojo.forEach(ticks.major, function(tick){
+						var y = dim.height - offsets.b - vt(tick.value);
+						var hMajorLine = s.createLine({
+							x1: offsets.l,
+							y1: y,
+							x2: dim.width - offsets.r,
+							y2: y
+						}).setStroke(ta.majorTick);
+						if(this.animate){
+							this._animateGrid(hMajorLine, "h", offsets.l, offsets.r + offsets.l - dim.width);
+						}
+					}, this);
+				}
+			}catch(e){
+				// squelch
+			}
+			// draw vertical stripes and lines
+			try{
+				var hScaler = this._hAxis.getScaler(),
+					ht = hScaler.scaler.getTransformerFromModel(hScaler),
+					ticks = this._hAxis.getTicks();
+				if(ticks && this.opt.vMinorLines){
+					dojo.forEach(ticks.minor, function(tick){
+						var x = offsets.l + ht(tick.value);
+						var vMinorLine = s.createLine({
+							x1: x,
+							y1: offsets.t,
+							x2: x,
+							y2: dim.height - offsets.b
+						}).setStroke(ta.minorTick);
+						if(this.animate){
+							this._animateGrid(vMinorLine, "v", dim.height - offsets.b, dim.height - offsets.b - offsets.t);
+						}
+					}, this);
+				}
+				if(ticks && this.opt.vMajorLines){
+					dojo.forEach(ticks.major, function(tick){
+						var x = offsets.l + ht(tick.value);
+						var vMajorLine = s.createLine({
+							x1: x,
+							y1: offsets.t,
+							x2: x,
+							y2: dim.height - offsets.b
+						}).setStroke(ta.majorTick);
+						if(this.animate){
+							this._animateGrid(vMajorLine, "v", dim.height - offsets.b, dim.height - offsets.b - offsets.t);
+						}
+					}, this);
+				}
+			}catch(e){
+				// squelch
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.Grid
+		},
+		_animateGrid: function(shape, type, offset, size){
+			var transStart = type == "h" ? [offset, 0] : [0, offset];
+			var scaleStart = type == "h" ? [1/size, 1] : [1, 1/size];
+			dojox.gfx.fx.animateTransform(dojo.delegate({
+				shape: shape,
+				duration: 1200,
+				transform: [
+					{name: "translate", start: transStart, end: [0, 0]},
+					{name: "scale", start: scaleStart, end: [1, 1]},
+					{name: "original"}
+				]
+			}, this.animate)).play();
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/Lines.js b/dojox/charting/plot2d/Lines.js
index 0026744..7d6c859 100644
--- a/dojox/charting/plot2d/Lines.js
+++ b/dojox/charting/plot2d/Lines.js
@@ -1,15 +1,13 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Lines"]){
-dojo._hasResource["dojox.charting.plot2d.Lines"]=true;
 dojo.provide("dojox.charting.plot2d.Lines");
+
 dojo.require("dojox.charting.plot2d.Default");
-dojo.declare("dojox.charting.plot2d.Lines",dojox.charting.plot2d.Default,{constructor:function(){
-this.opt.lines=true;
-}});
-}
+
+dojo.declare("dojox.charting.plot2d.Lines", dojox.charting.plot2d.Default, {
+	//	summary:
+	//		A convenience constructor to create a typical line chart.
+	constructor: function(){
+		//	summary:
+		//		Preset our default plot to be line-based.
+		this.opt.lines = true;
+	}
+});
diff --git a/dojox/charting/plot2d/Markers.js b/dojox/charting/plot2d/Markers.js
index bee2125..b7c6c5b 100644
--- a/dojox/charting/plot2d/Markers.js
+++ b/dojox/charting/plot2d/Markers.js
@@ -1,15 +1,13 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Markers"]){
-dojo._hasResource["dojox.charting.plot2d.Markers"]=true;
 dojo.provide("dojox.charting.plot2d.Markers");
+
 dojo.require("dojox.charting.plot2d.Default");
-dojo.declare("dojox.charting.plot2d.Markers",dojox.charting.plot2d.Default,{constructor:function(){
-this.opt.markers=true;
-}});
-}
+
+dojo.declare("dojox.charting.plot2d.Markers", dojox.charting.plot2d.Default, {
+	//	summary:
+	//		A convenience plot to draw a line chart with markers.
+	constructor: function(){
+		//	summary:
+		//		Set up the plot for lines and markers.
+		this.opt.markers = true;
+	}
+});
diff --git a/dojox/charting/plot2d/MarkersOnly.js b/dojox/charting/plot2d/MarkersOnly.js
index cdb0985..b5a8784 100644
--- a/dojox/charting/plot2d/MarkersOnly.js
+++ b/dojox/charting/plot2d/MarkersOnly.js
@@ -1,16 +1,14 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.MarkersOnly"]){
-dojo._hasResource["dojox.charting.plot2d.MarkersOnly"]=true;
 dojo.provide("dojox.charting.plot2d.MarkersOnly");
+
 dojo.require("dojox.charting.plot2d.Default");
-dojo.declare("dojox.charting.plot2d.MarkersOnly",dojox.charting.plot2d.Default,{constructor:function(){
-this.opt.lines=false;
-this.opt.markers=true;
-}});
-}
+
+dojo.declare("dojox.charting.plot2d.MarkersOnly", dojox.charting.plot2d.Default, {
+	//	summary:
+	//		A convenience object to draw only markers (like a scatter but not quite).
+	constructor: function(){
+		//	summary:
+		//		Set up our default plot to only have markers and no lines.
+		this.opt.lines   = false;
+		this.opt.markers = true;
+	}
+});
diff --git a/dojox/charting/plot2d/OHLC.js b/dojox/charting/plot2d/OHLC.js
index 49ac45b..e8d81ec 100644
--- a/dojox/charting/plot2d/OHLC.js
+++ b/dojox/charting/plot2d/OHLC.js
@@ -1,113 +1,218 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.OHLC"]){
-dojo._hasResource["dojox.charting.plot2d.OHLC"]=true;
 dojo.provide("dojox.charting.plot2d.OHLC");
+
 dojo.require("dojox.charting.plot2d.common");
 dojo.require("dojox.charting.plot2d.Base");
+
 dojo.require("dojox.lang.utils");
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.reversed");
+
 (function(){
-var df=dojox.lang.functional,du=dojox.lang.utils,dc=dojox.charting.plot2d.common,_1=df.lambda("item.purgeGroup()");
-dojo.declare("dojox.charting.plot2d.OHLC",dojox.charting.plot2d.Base,{defaultParams:{hAxis:"x",vAxis:"y",gap:2,shadows:null},optionalParams:{minBarSize:1,maxBarSize:1},constructor:function(_2,_3){
-this.opt=dojo.clone(this.defaultParams);
-du.updateWithObject(this.opt,_3);
-du.updateWithPattern(this.opt,_3,this.optionalParams);
-this.series=[];
-this.hAxis=this.opt.hAxis;
-this.vAxis=this.opt.vAxis;
-},collectStats:function(_4){
-var _5=dojo.clone(dc.defaultStats);
-for(var i=0;i<_4.length;i++){
-var _6=_4[i];
-if(!_6.data.length){
-continue;
-}
-var _7=_5.vmin,_8=_5.vmax;
-if(!("ymin" in _6)||!("ymax" in _6)){
-dojo.forEach(_6.data,function(_9,_a){
-var x=_9.x||_a+1;
-_5.hmin=Math.min(_5.hmin,x);
-_5.hmax=Math.max(_5.hmax,x);
-_5.vmin=Math.min(_5.vmin,_9.open,_9.close,_9.high,_9.low);
-_5.vmax=Math.max(_5.vmax,_9.open,_9.close,_9.high,_9.low);
-});
-}
-if("ymin" in _6){
-_5.vmin=Math.min(_7,_6.ymin);
-}
-if("ymax" in _6){
-_5.vmax=Math.max(_8,_6.ymax);
-}
-}
-return _5;
-},calculateAxes:function(_b){
-var _c=this.collectStats(this.series),t;
-_c.hmin-=0.5;
-_c.hmax+=0.5;
-this._calc(_b,_c);
-return this;
-},render:function(_d,_e){
-this.dirty=this.isDirty();
-if(this.dirty){
-dojo.forEach(this.series,_1);
-this.cleanGroup();
-var s=this.group;
-df.forEachRev(this.series,function(_f){
-_f.cleanGroup(s);
-});
-}
-var t=this.chart.theme,_10,_11,_12,f,gap,_13,ht=this._hScaler.scaler.getTransformerFromModel(this._hScaler),vt=this._vScaler.scaler.getTransformerFromModel(this._vScaler),_14=Math.max(0,this._vScaler.bounds.lower),_15=vt(_14),_16=this.events();
-f=dc.calculateBarSize(this._hScaler.bounds.scale,this.opt);
-gap=f.gap;
-_13=f.size;
-this.resetEvents();
-for(var i=this.series.length-1;i>=0;--i){
-var run=this.series[i];
-if(!this.dirty&&!run.dirty){
-continue;
-}
-run.cleanGroup();
-var s=run.group;
-if(!run.fill||!run.stroke){
-_10=run.dyn.color=new dojo.Color(t.next("color"));
-}
-_11=run.stroke?run.stroke:dc.augmentStroke(t.series.stroke,_10);
-_12=run.fill?run.fill:dc.augmentFill(t.series.fill,_10);
-for(var j=0;j<run.data.length;++j){
-var v=run.data[j];
-var x=ht(v.x||(j+0.5))+_e.l+gap,y=_d.height-_e.b,_17=vt(v.open),_18=vt(v.close),_19=vt(v.high),low=vt(v.low);
-if(low>_19){
-var tmp=_19;
-_19=low;
-low=tmp;
-}
-if(_13>=1){
-var hl={x1:_13/2,x2:_13/2,y1:y-_19,y2:y-low},op={x1:0,x2:((_13/2)+((_11.width||1)/2)),y1:y-_17,y2:y-_17},cl={x1:((_13/2)-((_11.width||1)/2)),x2:_13,y1:y-_18,y2:y-_18};
-shape=s.createGroup();
-shape.setTransform({dx:x,dy:0});
-var _1a=shape.createGroup();
-_1a.createLine(hl).setStroke(_11);
-_1a.createLine(op).setStroke(_11);
-_1a.createLine(cl).setStroke(_11);
-run.dyn.fill=_12;
-run.dyn.stroke=_11;
-if(_16){
-var o={element:"candlestick",index:j,run:run,plot:this,hAxis:this.hAxis||null,vAxis:this.vAxis||null,shape:_1a,x:x,y:y-Math.max(_17,_18),cx:_13/2,cy:(y-Math.max(_17,_18))+(Math.max(_17>_18?_17-_18:_18-_17,1)/2),width:_13,height:Math.max(_17>_18?_17-_18:_18-_17,1),data:v};
-this._connectEvents(shape,o);
-}
-}
-}
-run.dirty=false;
-}
-this.dirty=false;
-return this;
-}});
+	var df = dojox.lang.functional, du = dojox.lang.utils,
+		dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	//	Candlesticks are based on the Bars plot type; we expect the following passed
+	//	as values in a series:
+	//	{ x?, open, close, high, low }
+	//	if x is not provided, the array index is used.
+	//	failing to provide the OHLC values will throw an error.
+	dojo.declare("dojox.charting.plot2d.OHLC", dojox.charting.plot2d.Base, {
+		//	summary:
+		//		A plot that represents typical open/high/low/close (financial reporting, primarily).
+		//		Unlike most charts, the Candlestick expects data points to be represented by
+		//		an object of the form { x?, open, close, high, low, mid? }, where both
+		//		x and mid are optional parameters.  If x is not provided, the index of the
+		//		data array is used.
+		defaultParams: {
+			hAxis: "x",		// use a horizontal axis named "x"
+			vAxis: "y",		// use a vertical axis named "y"
+			gap:	2,		// gap between columns in pixels
+			animate: null	// animate chart to place
+		},
+		optionalParams: {
+			minBarSize: 1,	// minimal bar size in pixels
+			maxBarSize: 1,	// maximal bar size in pixels
+			// theme component
+			stroke:		{},
+			outline:	{},
+			shadow:		{},
+			fill:		{},
+			font:		"",
+			fontColor:	""
+		},
+
+		constructor: function(chart, kwArgs){
+			//	summary:
+			//		The constructor for a candlestick chart.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this plot belongs to.
+			//	kwArgs: dojox.charting.plot2d.__BarCtorArgs?
+			//		An optional keyword arguments object to help define the plot.
+			this.opt = dojo.clone(this.defaultParams);
+			du.updateWithObject(this.opt, kwArgs);
+			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
+			this.series = [];
+			this.hAxis = this.opt.hAxis;
+			this.vAxis = this.opt.vAxis;
+			this.animate = this.opt.animate;
+		},
+
+		collectStats: function(series){
+			//	summary:
+			//		Collect all statistics for drawing this chart.  Since the common
+			//		functionality only assumes x and y, OHLC must create it's own
+			//		stats (since data has no y value, but open/close/high/low instead).
+			//	series: dojox.charting.Series[]
+			//		The data series array to be drawn on this plot.
+			//	returns: Object
+			//		Returns an object in the form of { hmin, hmax, vmin, vmax }.
+
+			//	we have to roll our own, since we need to use all four passed
+			//	values to figure out our stats, and common only assumes x and y.
+			var stats = dojo.delegate(dc.defaultStats);
+			for(var i=0; i<series.length; i++){
+				var run = series[i];
+				if(!run.data.length){ continue; }
+				var old_vmin = stats.vmin, old_vmax = stats.vmax;
+				if(!("ymin" in run) || !("ymax" in run)){
+					dojo.forEach(run.data, function(val, idx){
+						if(val !== null){
+							var x = val.x || idx + 1;
+							stats.hmin = Math.min(stats.hmin, x);
+							stats.hmax = Math.max(stats.hmax, x);
+							stats.vmin = Math.min(stats.vmin, val.open, val.close, val.high, val.low);
+							stats.vmax = Math.max(stats.vmax, val.open, val.close, val.high, val.low);
+						}
+					});
+				}
+				if("ymin" in run){ stats.vmin = Math.min(old_vmin, run.ymin); }
+				if("ymax" in run){ stats.vmax = Math.max(old_vmax, run.ymax); }
+			}
+			return stats;
+		},
+
+		getSeriesStats: function(){
+			//	summary:
+			//		Calculate the min/max on all attached series in both directions.
+			//	returns: Object
+			//		{hmin, hmax, vmin, vmax} min/max in both directions.
+			var stats = this.collectStats(this.series);
+			stats.hmin -= 0.5;
+			stats.hmax += 0.5;
+			return stats;
+		},
+
+		render: function(dim, offsets){
+			//	summary:
+			//		Run the calculations for any axes for this plot.
+			//	dim: Object
+			//		An object in the form of { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b}.
+			//	returns: dojox.charting.plot2d.OHLC
+			//		A reference to this plot for functional chaining.
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+			this.resetEvents();
+			this.dirty = this.isDirty();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+			var t = this.chart.theme, f, gap, width,
+				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
+				baseline = Math.max(0, this._vScaler.bounds.lower),
+				baselineHeight = vt(baseline),
+				events = this.events();
+			f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt);
+			gap = f.gap;
+			width = f.size;
+			for(var i = this.series.length - 1; i >= 0; --i){
+				var run = this.series[i];
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				var theme = t.next("candlestick", [this.opt, run]), s = run.group,
+					eventSeries = new Array(run.data.length);
+				for(var j = 0; j < run.data.length; ++j){
+					var v = run.data[j];
+					if(v !== null){
+						var finalTheme = t.addMixin(theme, "candlestick", v, true);
+
+						//	calculate the points we need for OHLC
+						var x = ht(v.x || (j+0.5)) + offsets.l + gap,
+							y = dim.height - offsets.b,
+							open = vt(v.open),
+							close = vt(v.close),
+							high = vt(v.high),
+							low = vt(v.low);
+						if(low > high){
+							var tmp = high;
+							high = low;
+							low = tmp;
+						}
+
+						if(width >= 1){
+							var hl = {x1: width/2, x2: width/2, y1: y - high, y2: y - low},
+								op = {x1: 0, x2: ((width/2) + ((finalTheme.series.stroke.width||1)/2)), y1: y-open, y2: y-open},
+								cl = {x1: ((width/2) - ((finalTheme.series.stroke.width||1)/2)), x2: width, y1: y-close, y2: y-close};
+							shape = s.createGroup();
+							shape.setTransform({dx: x, dy: 0});
+							var inner = shape.createGroup();
+							inner.createLine(hl).setStroke(finalTheme.series.stroke);
+							inner.createLine(op).setStroke(finalTheme.series.stroke);
+							inner.createLine(cl).setStroke(finalTheme.series.stroke);
+
+							//	TODO: double check this.
+							run.dyn.stroke = finalTheme.series.stroke;
+							if(events){
+								var o = {
+									element: "candlestick",
+									index:   j,
+									run:     run,
+									shape:	 inner,
+									x:       x,
+									y:       y-Math.max(open, close),
+									cx:		 width/2,
+									cy:		 (y-Math.max(open, close)) + (Math.max(open > close ? open-close : close-open, 1)/2),
+									width:	 width,
+									height:  Math.max(open > close ? open-close : close-open, 1),
+									data:	 v
+								};
+								this._connectEvents(o);
+								eventSeries[j] = o;
+							}
+						}
+						if(this.animate){
+							this._animateOHLC(shape, y - low, high - low);
+						}
+					}
+				}
+				this._eventSeries[run.name] = eventSeries;
+				run.dirty = false;
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.OHLC
+		},
+		_animateOHLC: function(shape, voffset, vsize){
+			dojox.gfx.fx.animateTransform(dojo.delegate({
+				shape: shape,
+				duration: 1200,
+				transform: [
+					{name: "translate", start: [0, voffset - (voffset/vsize)], end: [0, 0]},
+					{name: "scale", start: [1, 1/vsize], end: [1, 1]},
+					{name: "original"}
+				]
+			}, this.animate)).play();
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/Pie.js b/dojox/charting/plot2d/Pie.js
index f859134..c3209c7 100644
--- a/dojox/charting/plot2d/Pie.js
+++ b/dojox/charting/plot2d/Pie.js
@@ -1,207 +1,399 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Pie"]){
-dojo._hasResource["dojox.charting.plot2d.Pie"]=true;
 dojo.provide("dojox.charting.plot2d.Pie");
+
 dojo.require("dojox.charting.Element");
 dojo.require("dojox.charting.axis2d.common");
 dojo.require("dojox.charting.plot2d.common");
+dojo.require("dojox.charting.plot2d._PlotEvents");
+
 dojo.require("dojox.lang.functional");
+dojo.require("dojox.lang.utils");
 dojo.require("dojox.gfx");
-(function(){
-var df=dojox.lang.functional,du=dojox.lang.utils,dc=dojox.charting.plot2d.common,da=dojox.charting.axis2d.common,g=dojox.gfx;
-dojo.declare("dojox.charting.plot2d.Pie",dojox.charting.Element,{defaultParams:{labels:true,ticks:false,fixed:true,precision:1,labelOffset:20,labelStyle:"default",htmlLabels:true},optionalParams:{font:"",fontColor:"",radius:0},constructor:function(_1,_2){
-this.opt=dojo.clone(this.defaultParams);
-du.updateWithObject(this.opt,_2);
-du.updateWithPattern(this.opt,_2,this.optionalParams);
-this.run=null;
-this.dyn=[];
-},destroy:function(){
-this.resetEvents();
-this.inherited(arguments);
-},clear:function(){
-this.dirty=true;
-this.dyn=[];
-this.run=null;
-return this;
-},setAxis:function(_3){
-return this;
-},addSeries:function(_4){
-this.run=_4;
-return this;
-},calculateAxes:function(_5){
-return this;
-},getRequiredColors:function(){
-return this.run?this.run.data.length:0;
-},plotEvent:function(o){
-},connect:function(_6,_7){
-this.dirty=true;
-return dojo.connect(this,"plotEvent",_6,_7);
-},events:function(){
-var ls=this.plotEvent._listeners;
-if(!ls||!ls.length){
-return false;
-}
-for(var i in ls){
-if(!(i in Array.prototype)){
-return true;
-}
-}
-return false;
-},resetEvents:function(){
-this.plotEvent({type:"onplotreset",plot:this});
-},_connectEvents:function(_8,o){
-_8.connect("onmouseover",this,function(e){
-o.type="onmouseover";
-o.event=e;
-this.plotEvent(o);
-});
-_8.connect("onmouseout",this,function(e){
-o.type="onmouseout";
-o.event=e;
-this.plotEvent(o);
-});
-_8.connect("onclick",this,function(e){
-o.type="onclick";
-o.event=e;
-this.plotEvent(o);
+
+dojo.require("dojo.number");
+
+/*=====
+dojo.declare("dojox.charting.plot2d.__PieCtorArgs", dojox.charting.plot2d.__DefaultCtorArgs, {
+	//	summary:
+	//		Specialized keyword arguments object for use in defining parameters on a Pie chart.
+
+	//	labels: Boolean?
+	//		Whether or not to draw labels within each pie slice.  Default is true.
+	labels:			true,
+
+	//	ticks: Boolean?
+	//		Whether or not to draw ticks to labels within each slice. Default is false.
+	ticks:			false,
+
+	//	fixed: Boolean?
+	//		TODO
+	fixed:			true,
+
+	//	precision: Number?
+	//		The precision at which to sum/add data values. Default is 1.
+	precision:		1,
+
+	//	labelOffset: Number?
+	//		The amount in pixels by which to offset labels.  Default is 20.
+	labelOffset:	20,
+
+	//	labelStyle: String?
+	//		Options as to where to draw labels.  Values include "default", "rows", and "auto". Default is "default".
+	labelStyle:		"default",	// default/rows/auto
+
+	//	htmlLabels: Boolean?
+	//		Whether or not to use HTML to render slice labels. Default is true.
+	htmlLabels:		true,
+
+	//	radGrad: String?
+	//		The type of radial gradient to use in rendering.  Default is "native".
+	radGrad:        "native",
+
+	//	fanSize: Number?
+	//		The amount for a radial gradient.  Default is 5.
+	fanSize:		5,
+
+	//	startAngle: Number?
+	//		Where to being rendering gradients in slices, in degrees.  Default is 0.
+	startAngle:     0,
+
+	//	radius: Number?
+	//		The size of the radial gradient.  Default is 0.
+	radius:		0
 });
-},render:function(_9,_a){
-if(!this.dirty){
-return this;
-}
-this.dirty=false;
-this.cleanGroup();
-var s=this.group,_b,t=this.chart.theme;
-this.resetEvents();
-if(!this.run||!this.run.data.length){
-return this;
-}
-var rx=(_9.width-_a.l-_a.r)/2,ry=(_9.height-_a.t-_a.b)/2,r=Math.min(rx,ry),_c="font" in this.opt?this.opt.font:t.axis.font,_d=_c?g.normalizedLength(g.splitFontString(_c).size):0,_e="fontColor" in this.opt?this.opt.fontColor:t.axis.fontColor,_f=0,_10,_11,_12,_13,_14,_15,run=this.run.data,_16=this.events();
-if(typeof run[0]=="number"){
-_11=df.map(run,"Math.max(x, 0)");
-if(df.every(_11,"<= 0")){
-return this;
-}
-_12=df.map(_11,"/this",df.foldl(_11,"+",0));
-if(this.opt.labels){
-_13=dojo.map(_12,function(x){
-return x>0?this._getLabel(x*100)+"%":"";
-},this);
-}
-}else{
-_11=df.map(run,"Math.max(x.y, 0)");
-if(df.every(_11,"<= 0")){
-return this;
-}
-_12=df.map(_11,"/this",df.foldl(_11,"+",0));
-if(this.opt.labels){
-_13=dojo.map(_12,function(x,i){
-if(x<=0){
-return "";
-}
-var v=run[i];
-return "text" in v?v.text:this._getLabel(x*100)+"%";
-},this);
-}
-}
-if(this.opt.labels){
-_14=df.foldl1(df.map(_13,function(_17){
-return dojox.gfx._base._getTextBox(_17,{font:_c}).w;
-},this),"Math.max(a, b)")/2;
-if(this.opt.labelOffset<0){
-r=Math.min(rx-2*_14,ry-_d)+this.opt.labelOffset;
-}
-_15=r-this.opt.labelOffset;
-}
-if("radius" in this.opt){
-r=this.opt.radius;
-_15=r-this.opt.labelOffset;
-}
-var _18={cx:_a.l+rx,cy:_a.t+ry,r:r};
-this.dyn=[];
-dojo.some(_12,function(_19,i){
-if(_19<=0){
-return false;
-}
-var v=run[i];
-if(_19>=1){
-var _1a,_1b,_1c;
-if(typeof v=="object"){
-_1a="color" in v?v.color:new dojo.Color(t.next("color"));
-_1b="fill" in v?v.fill:dc.augmentFill(t.series.fill,_1a);
-_1c="stroke" in v?v.stroke:dc.augmentStroke(t.series.stroke,_1a);
-}else{
-_1a=new dojo.Color(t.next("color"));
-_1b=dc.augmentFill(t.series.fill,_1a);
-_1c=dc.augmentStroke(t.series.stroke,_1a);
-}
-var _1d=s.createCircle(_18).setFill(_1b).setStroke(_1c);
-this.dyn.push({color:_1a,fill:_1b,stroke:_1c});
-if(_16){
-var o={element:"slice",index:i,run:this.run,plot:this,shape:_1d,x:i,y:typeof v=="number"?v:v.y,cx:_18.cx,cy:_18.cy,cr:r};
-this._connectEvents(_1d,o);
-}
-return true;
-}
-var end=_f+_19*2*Math.PI;
-if(i+1==_12.length){
-end=2*Math.PI;
-}
-var _1e=end-_f,x1=_18.cx+r*Math.cos(_f),y1=_18.cy+r*Math.sin(_f),x2=_18.cx+r*Math.cos(end),y2=_18.cy+r*Math.sin(end);
-var _1a,_1b,_1c;
-if(typeof v=="object"){
-_1a="color" in v?v.color:new dojo.Color(t.next("color"));
-_1b="fill" in v?v.fill:dc.augmentFill(t.series.fill,_1a);
-_1c="stroke" in v?v.stroke:dc.augmentStroke(t.series.stroke,_1a);
-}else{
-_1a=new dojo.Color(t.next("color"));
-_1b=dc.augmentFill(t.series.fill,_1a);
-_1c=dc.augmentStroke(t.series.stroke,_1a);
-}
-var _1d=s.createPath({}).moveTo(_18.cx,_18.cy).lineTo(x1,y1).arcTo(r,r,0,_1e>Math.PI,true,x2,y2).lineTo(_18.cx,_18.cy).closePath().setFill(_1b).setStroke(_1c);
-this.dyn.push({color:_1a,fill:_1b,stroke:_1c});
-if(_16){
-var o={element:"slice",index:i,run:this.run,plot:this,shape:_1d,x:i,y:typeof v=="number"?v:v.y,cx:_18.cx,cy:_18.cy,cr:r};
-this._connectEvents(_1d,o);
-}
-_f=end;
-return false;
-},this);
-if(this.opt.labels){
-_f=0;
-dojo.some(_12,function(_1f,i){
-if(_1f<=0){
-return false;
-}
-if(_1f>=1){
-var v=run[i],_20=da.createText[this.opt.htmlLabels&&dojox.gfx.renderer!="vml"?"html":"gfx"](this.chart,s,_18.cx,_18.cy+_d/2,"middle",_13[i],_c,(typeof v=="object"&&"fontColor" in v)?v.fontColor:_e);
-if(this.opt.htmlLabels){
-this.htmlElements.push(_20);
-}
-return true;
-}
-var end=_f+_1f*2*Math.PI,v=run[i];
-if(i+1==_12.length){
-end=2*Math.PI;
-}
-var _21=(_f+end)/2,x=_18.cx+_15*Math.cos(_21),y=_18.cy+_15*Math.sin(_21)+_d/2;
-var _20=da.createText[this.opt.htmlLabels&&dojox.gfx.renderer!="vml"?"html":"gfx"](this.chart,s,x,y,"middle",_13[i],_c,(typeof v=="object"&&"fontColor" in v)?v.fontColor:_e);
-if(this.opt.htmlLabels){
-this.htmlElements.push(_20);
-}
-_f=end;
-return false;
-},this);
-}
-return this;
-},_getLabel:function(_22){
-return this.opt.fixed?_22.toFixed(this.opt.precision):_22.toString();
-}});
+=====*/
+(function(){
+	var df = dojox.lang.functional, du = dojox.lang.utils,
+		dc = dojox.charting.plot2d.common,
+		da = dojox.charting.axis2d.common,
+		g = dojox.gfx, m = g.matrix,
+		FUDGE_FACTOR = 0.2; // use to overlap fans
+
+	dojo.declare("dojox.charting.plot2d.Pie", [dojox.charting.Element, dojox.charting.plot2d._PlotEvents], {
+		//	summary:
+		//		The plot that represents a typical pie chart.
+		defaultParams: {
+			labels:			true,
+			ticks:			false,
+			fixed:			true,
+			precision:		1,
+			labelOffset:	20,
+			labelStyle:		"default",	// default/rows/auto
+			htmlLabels:		true,		// use HTML to draw labels
+			radGrad:        "native",	// or "linear", or "fan"
+			fanSize:		5,			// maximum fan size in degrees
+			startAngle:     0			// start angle for slices in degrees
+		},
+		optionalParams: {
+			radius:		0,
+			// theme components
+			stroke:		{},
+			outline:	{},
+			shadow:		{},
+			fill:		{},
+			font:		"",
+			fontColor:	""
+		},
+
+		constructor: function(chart, kwArgs){
+			//	summary:
+			//		Create a pie plot.
+			this.opt = dojo.clone(this.defaultParams);
+			du.updateWithObject(this.opt, kwArgs);
+			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
+			this.run = null;
+			this.dyn = [];
+		},
+		clear: function(){
+			//	summary:
+			//		Clear out all of the information tied to this plot.
+			//	returns: dojox.charting.plot2d.Pie
+			//		A reference to this plot for functional chaining.
+			this.dirty = true;
+			this.dyn = [];
+			this.run = null;
+			return this;	//	dojox.charting.plot2d.Pie
+		},
+		setAxis: function(axis){
+			//	summary:
+			//		Dummy method, since axes are irrelevant with a Pie chart.
+			//	returns: dojox.charting.plot2d.Pie
+			//		The reference to this plot for functional chaining.
+			return this;	//	dojox.charting.plot2d.Pie
+		},
+		addSeries: function(run){
+			//	summary:
+			//		Add a series of data to this plot.
+			//	returns: dojox.charting.plot2d.Pie
+			//		The reference to this plot for functional chaining.
+			this.run = run;
+			return this;	//	dojox.charting.plot2d.Pie
+		},
+		getSeriesStats: function(){
+			//	summary:
+			//		Returns default stats (irrelevant for this type of plot).
+			//	returns: Object
+			//		{hmin, hmax, vmin, vmax} min/max in both directions.
+			return dojo.delegate(dc.defaultStats);
+		},
+		initializeScalers: function(){
+			//	summary:
+			//		Does nothing (irrelevant for this type of plot).
+			return this;
+		},
+		getRequiredColors: function(){
+			//	summary:
+			//		Return the number of colors needed to draw this plot.
+			return this.run ? this.run.data.length : 0;
+		},
+
+		render: function(dim, offsets){
+			//	summary:
+			//		Render the plot on the chart.
+			//	dim: Object
+			//		An object of the form { width, height }.
+			//	offsets: Object
+			//		An object of the form { l, r, t, b }.
+			//	returns: dojox.charting.plot2d.Pie
+			//		A reference to this plot for functional chaining.
+			if(!this.dirty){ return this; }
+			this.resetEvents();
+			this.dirty = false;
+			this._eventSeries = {};
+			this.cleanGroup();
+			var s = this.group, t = this.chart.theme;
+
+			if(!this.run || !this.run.data.length){
+				return this;
+			}
+
+			// calculate the geometry
+			var rx = (dim.width  - offsets.l - offsets.r) / 2,
+				ry = (dim.height - offsets.t - offsets.b) / 2,
+				r  = Math.min(rx, ry),
+				taFont = "font" in this.opt ? this.opt.font : t.axis.font,
+				size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
+				taFontColor = "fontColor" in this.opt ? this.opt.fontColor : t.axis.fontColor,
+				startAngle = m._degToRad(this.opt.startAngle),
+				start = startAngle, step, filteredRun, slices, labels, shift, labelR,
+				run = this.run.data,
+				events = this.events();
+			if(typeof run[0] == "number"){
+				filteredRun = df.map(run, "x ? Math.max(x, 0) : 0");
+				if(df.every(filteredRun, "<= 0")){
+					return this;
+				}
+				slices = df.map(filteredRun, "/this", df.foldl(filteredRun, "+", 0));
+				if(this.opt.labels){
+					labels = dojo.map(slices, function(x){
+						return x > 0 ? this._getLabel(x * 100) + "%" : "";
+					}, this);
+				}
+			}else{
+				filteredRun = df.map(run, "x ? Math.max(x.y, 0) : 0");
+				if(df.every(filteredRun, "<= 0")){
+					return this;
+				}
+				slices = df.map(filteredRun, "/this", df.foldl(filteredRun, "+", 0));
+				if(this.opt.labels){
+					labels = dojo.map(slices, function(x, i){
+						if(x <= 0){ return ""; }
+						var v = run[i];
+						return "text" in v ? v.text : this._getLabel(x * 100) + "%";
+					}, this);
+				}
+			}
+			var themes = df.map(run, function(v, i){
+				if(v === null || typeof v == "number"){
+					return t.next("slice", [this.opt, this.run], true);
+				}
+				return t.next("slice", [this.opt, this.run, v], true);
+			}, this);
+			if(this.opt.labels){
+				shift = df.foldl1(df.map(labels, function(label, i){
+					var font = themes[i].series.font;
+					return dojox.gfx._base._getTextBox(label, {font: font}).w;
+				}, this), "Math.max(a, b)") / 2;
+				if(this.opt.labelOffset < 0){
+					r = Math.min(rx - 2 * shift, ry - size) + this.opt.labelOffset;
+				}
+				labelR = r - this.opt.labelOffset;
+			}
+			if("radius" in this.opt){
+				r = this.opt.radius;
+				labelR = r - this.opt.labelOffset;
+			}
+			var	circle = {
+					cx: offsets.l + rx,
+					cy: offsets.t + ry,
+					r:  r
+				};
+
+			this.dyn = [];
+			// draw slices
+			var eventSeries = new Array(slices.length);
+			dojo.some(slices, function(slice, i){
+				if(slice <= 0){
+					// degenerated slice
+					return false;	// continue
+				}
+				var v = run[i], theme = themes[i], specialFill;
+				if(slice >= 1){
+					// whole pie
+					specialFill = this._plotFill(theme.series.fill, dim, offsets);
+					specialFill = this._shapeFill(specialFill,
+						{
+							x: circle.cx - circle.r, y: circle.cy - circle.r,
+							width: 2 * circle.r, height: 2 * circle.r
+						});
+					specialFill = this._pseudoRadialFill(specialFill, {x: circle.cx, y: circle.cy}, circle.r);
+					var shape = s.createCircle(circle).setFill(specialFill).setStroke(theme.series.stroke);
+					this.dyn.push({fill: specialFill, stroke: theme.series.stroke});
+
+					if(events){
+						var o = {
+							element: "slice",
+							index:   i,
+							run:     this.run,
+							shape:   shape,
+							x:       i,
+							y:       typeof v == "number" ? v : v.y,
+							cx:      circle.cx,
+							cy:      circle.cy,
+							cr:      r
+						};
+						this._connectEvents(o);
+						eventSeries[i] = o;
+					}
+
+					return true;	// stop iteration
+				}
+				// calculate the geometry of the slice
+				var end = start + slice * 2 * Math.PI;
+				if(i + 1 == slices.length){
+					end = startAngle + 2 * Math.PI;
+				}
+				var	step = end - start,
+					x1 = circle.cx + r * Math.cos(start),
+					y1 = circle.cy + r * Math.sin(start),
+					x2 = circle.cx + r * Math.cos(end),
+					y2 = circle.cy + r * Math.sin(end);
+				// draw the slice
+				var fanSize = m._degToRad(this.opt.fanSize);
+				if(theme.series.fill && theme.series.fill.type === "radial" && this.opt.radGrad === "fan" && step > fanSize){
+					var group = s.createGroup(), nfans = Math.ceil(step / fanSize), delta = step / nfans;
+					specialFill = this._shapeFill(theme.series.fill,
+						{x: circle.cx - circle.r, y: circle.cy - circle.r, width: 2 * circle.r, height: 2 * circle.r});
+					for(var j = 0; j < nfans; ++j){
+						var fansx = j == 0 ? x1 : circle.cx + r * Math.cos(start + (j - FUDGE_FACTOR) * delta),
+							fansy = j == 0 ? y1 : circle.cy + r * Math.sin(start + (j - FUDGE_FACTOR) * delta),
+							fanex = j == nfans - 1 ? x2 : circle.cx + r * Math.cos(start + (j + 1 + FUDGE_FACTOR) * delta),
+							faney = j == nfans - 1 ? y2 : circle.cy + r * Math.sin(start + (j + 1 + FUDGE_FACTOR) * delta),
+							fan = group.createPath({}).
+								moveTo(circle.cx, circle.cy).
+								lineTo(fansx, fansy).
+								arcTo(r, r, 0, delta > Math.PI, true, fanex, faney).
+								lineTo(circle.cx, circle.cy).
+								closePath().
+								setFill(this._pseudoRadialFill(specialFill, {x: circle.cx, y: circle.cy}, r, start + (j + 0.5) * delta, start + (j + 0.5) * delta));
+					}
+					group.createPath({}).
+						moveTo(circle.cx, circle.cy).
+						lineTo(x1, y1).
+						arcTo(r, r, 0, step > Math.PI, true, x2, y2).
+						lineTo(circle.cx, circle.cy).
+						closePath().
+						setStroke(theme.series.stroke);
+					shape = group;
+				}else{
+					shape = s.createPath({}).
+						moveTo(circle.cx, circle.cy).
+						lineTo(x1, y1).
+						arcTo(r, r, 0, step > Math.PI, true, x2, y2).
+						lineTo(circle.cx, circle.cy).
+						closePath().
+						setStroke(theme.series.stroke);
+					var specialFill = theme.series.fill;
+					if(specialFill && specialFill.type === "radial"){
+						specialFill = this._shapeFill(specialFill, {x: circle.cx - circle.r, y: circle.cy - circle.r, width: 2 * circle.r, height: 2 * circle.r});
+						if(this.opt.radGrad === "linear"){
+							specialFill = this._pseudoRadialFill(specialFill, {x: circle.cx, y: circle.cy}, r, start, end);
+						}
+					}else if(specialFill && specialFill.type === "linear"){
+						specialFill = this._plotFill(specialFill, dim, offsets);
+						specialFill = this._shapeFill(specialFill, shape.getBoundingBox());
+					}
+					shape.setFill(specialFill);
+				}
+				this.dyn.push({fill: specialFill, stroke: theme.series.stroke});
+
+				if(events){
+					var o = {
+						element: "slice",
+						index:   i,
+						run:     this.run,
+						shape:   shape,
+						x:       i,
+						y:       typeof v == "number" ? v : v.y,
+						cx:      circle.cx,
+						cy:      circle.cy,
+						cr:      r
+					};
+					this._connectEvents(o);
+					eventSeries[i] = o;
+				}
+
+				start = end;
+
+				return false;	// continue
+			}, this);
+			// draw labels
+			if(this.opt.labels){
+				start = startAngle;
+				dojo.some(slices, function(slice, i){
+					if(slice <= 0){
+						// degenerated slice
+						return false;	// continue
+					}
+					var theme = themes[i];
+					if(slice >= 1){
+						// whole pie
+						var v = run[i], elem = da.createText[this.opt.htmlLabels && dojox.gfx.renderer != "vml" ? "html" : "gfx"](
+								this.chart, s, circle.cx, circle.cy + size / 2, "middle", labels[i],
+								theme.series.font, theme.series.fontColor);
+						if(this.opt.htmlLabels){
+							this.htmlElements.push(elem);
+						}
+						return true;	// stop iteration
+					}
+					// calculate the geometry of the slice
+					var end = start + slice * 2 * Math.PI, v = run[i];
+					if(i + 1 == slices.length){
+						end = startAngle + 2 * Math.PI;
+					}
+					var	labelAngle = (start + end) / 2,
+						x = circle.cx + labelR * Math.cos(labelAngle),
+						y = circle.cy + labelR * Math.sin(labelAngle) + size / 2;
+					// draw the label
+					var elem = da.createText[this.opt.htmlLabels && dojox.gfx.renderer != "vml" ? "html" : "gfx"]
+							(this.chart, s, x, y, "middle", labels[i], theme.series.font, theme.series.fontColor);
+					if(this.opt.htmlLabels){
+						this.htmlElements.push(elem);
+					}
+					start = end;
+					return false;	// continue
+				}, this);
+			}
+			// post-process events to restore the original indexing
+			var esi = 0;
+			this._eventSeries[this.run.name] = df.map(run, function(v){
+				return v <= 0 ? null : eventSeries[esi++];
+			});
+			return this;	//	dojox.charting.plot2d.Pie
+		},
+
+		// utilities
+		_getLabel: function(number){
+			return this.opt.fixed ? dojo.number.format(number, {places: this.opt.precision}) : number.toString();
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/Scatter.js b/dojox/charting/plot2d/Scatter.js
index d4caae2..775fe8a 100644
--- a/dojox/charting/plot2d/Scatter.js
+++ b/dojox/charting/plot2d/Scatter.js
@@ -1,16 +1,196 @@
-/*
-	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
-*/
+dojo.provide("dojox.charting.plot2d.Scatter");
 
+dojo.require("dojox.charting.plot2d.common");
+dojo.require("dojox.charting.plot2d.Base");
 
-if(!dojo._hasResource["dojox.charting.plot2d.Scatter"]){
-dojo._hasResource["dojox.charting.plot2d.Scatter"]=true;
-dojo.provide("dojox.charting.plot2d.Scatter");
-dojo.require("dojox.charting.plot2d.Default");
-dojo.declare("dojox.charting.plot2d.Scatter",dojox.charting.plot2d.Default,{constructor:function(){
-this.opt.lines=false;
-this.opt.markers=true;
-}});
-}
+dojo.require("dojox.lang.utils");
+dojo.require("dojox.lang.functional");
+dojo.require("dojox.lang.functional.reversed");
+
+dojo.require("dojox.gfx.gradutils");
+
+
+(function(){
+	var df = dojox.lang.functional, du = dojox.lang.utils,
+		dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	dojo.declare("dojox.charting.plot2d.Scatter", dojox.charting.plot2d.Base, {
+		//	summary:
+		//		A plot object representing a typical scatter chart.
+		defaultParams: {
+			hAxis: "x",		// use a horizontal axis named "x"
+			vAxis: "y",		// use a vertical axis named "y"
+			shadows: null,	// draw shadows
+			animate: null	// animate chart to place
+		},
+		optionalParams: {
+			// theme component
+			markerStroke:		{},
+			markerOutline:		{},
+			markerShadow:		{},
+			markerFill:			{},
+			markerFont:			"",
+			markerFontColor:	""
+		},
+
+		constructor: function(chart, kwArgs){
+			//	summary:
+			//		Create the scatter plot.
+			//	chart: dojox.charting.Chart2D
+			//		The chart this plot belongs to.
+			//	kwArgs: dojox.charting.plot2d.__DefaultCtorArgs?
+			//		An optional keyword arguments object to help define this plot's parameters.
+			this.opt = dojo.clone(this.defaultParams);
+			du.updateWithObject(this.opt, kwArgs);
+			this.series = [];
+			this.hAxis = this.opt.hAxis;
+			this.vAxis = this.opt.vAxis;
+			this.animate = this.opt.animate;
+		},
+
+		render: function(dim, offsets){
+			//	summary:
+			//		Run the calculations for any axes for this plot.
+			//	dim: Object
+			//		An object in the form of { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b}.
+			//	returns: dojox.charting.plot2d.Scatter
+			//		A reference to this plot for functional chaining.
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+			this.resetEvents();
+			this.dirty = this.isDirty();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+			var t = this.chart.theme, events = this.events();
+			for(var i = this.series.length - 1; i >= 0; --i){
+				var run = this.series[i];
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				if(!run.data.length){
+					run.dirty = false;
+					t.skip();
+					continue;
+				}
+
+				var theme = t.next("marker", [this.opt, run]), s = run.group, lpoly,
+					ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+					vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler);
+				if(typeof run.data[0] == "number"){
+					lpoly = dojo.map(run.data, function(v, i){
+						return {
+							x: ht(i + 1) + offsets.l,
+							y: dim.height - offsets.b - vt(v)
+						};
+					}, this);
+				}else{
+					lpoly = dojo.map(run.data, function(v, i){
+						return {
+							x: ht(v.x) + offsets.l,
+							y: dim.height - offsets.b - vt(v.y)
+						};
+					}, this);
+				}
+
+				var shadowMarkers  = new Array(lpoly.length),
+					frontMarkers   = new Array(lpoly.length),
+					outlineMarkers = new Array(lpoly.length);
+
+				dojo.forEach(lpoly, function(c, i){
+					var finalTheme = typeof run.data[i] == "number" ?
+							t.post(theme, "marker") :
+							t.addMixin(theme, "marker", run.data[i], true),
+						path = "M" + c.x + " " + c.y + " " + finalTheme.symbol;
+					if(finalTheme.marker.shadow){
+						shadowMarkers[i] = s.createPath("M" + (c.x + finalTheme.marker.shadow.dx) + " " +
+							(c.y + finalTheme.marker.shadow.dy) + " " + finalTheme.symbol).
+							setStroke(finalTheme.marker.shadow).setFill(finalTheme.marker.shadow.color);
+						if(this.animate){
+							this._animateScatter(shadowMarkers[i], dim.height - offsets.b);
+						}
+					}
+					if(finalTheme.marker.outline){
+						var outline = dc.makeStroke(finalTheme.marker.outline);
+						outline.width = 2 * outline.width + finalTheme.marker.stroke.width;
+						outlineMarkers[i] = s.createPath(path).setStroke(outline);
+						if(this.animate){
+							this._animateScatter(outlineMarkers[i], dim.height - offsets.b);
+						}
+					}
+					var stroke = dc.makeStroke(finalTheme.marker.stroke),
+						fill = this._plotFill(finalTheme.marker.fill, dim, offsets);
+					if(fill && (fill.type === "linear" || fill.type == "radial")){
+						var color = dojox.gfx.gradutils.getColor(fill, {x: c.x, y: c.y});
+						if(stroke){
+							stroke.color = color;
+						}
+						frontMarkers[i] = s.createPath(path).setStroke(stroke).setFill(color);
+					}else{
+						frontMarkers[i] = s.createPath(path).setStroke(stroke).setFill(fill);
+					}
+					if(this.animate){
+						this._animateScatter(frontMarkers[i], dim.height - offsets.b);
+					}
+				}, this);
+				if(frontMarkers.length){
+					run.dyn.stroke = frontMarkers[frontMarkers.length - 1].getStroke();
+					run.dyn.fill   = frontMarkers[frontMarkers.length - 1].getFill();
+				}
+
+				if(events){
+					var eventSeries = new Array(frontMarkers.length);
+					dojo.forEach(frontMarkers, function(s, i){
+						var o = {
+							element: "marker",
+							index:   i,
+							run:     run,
+							shape:   s,
+							outline: outlineMarkers && outlineMarkers[i] || null,
+							shadow:  shadowMarkers && shadowMarkers[i] || null,
+							cx:      lpoly[i].x,
+							cy:      lpoly[i].y
+						};
+						if(typeof run.data[0] == "number"){
+							o.x = i + 1;
+							o.y = run.data[i];
+						}else{
+							o.x = run.data[i].x;
+							o.y = run.data[i].y;
+						}
+						this._connectEvents(o);
+						eventSeries[i] = o;
+					}, this);
+					this._eventSeries[run.name] = eventSeries;
+				}else{
+					delete this._eventSeries[run.name];
+				}
+				run.dirty = false;
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.Scatter
+		},
+		_animateScatter: function(shape, offset){
+			dojox.gfx.fx.animateTransform(dojo.delegate({
+				shape: shape,
+				duration: 1200,
+				transform: [
+					{name: "translate", start: [0, offset], end: [0, 0]},
+					{name: "scale", start: [0, 0], end: [1, 1]},
+					{name: "original"}
+				]
+			}, this.animate)).play();
+		}
+	});
+})();
diff --git a/dojox/charting/plot2d/Stacked.js b/dojox/charting/plot2d/Stacked.js
index 4f07fe6..3f603c5 100644
--- a/dojox/charting/plot2d/Stacked.js
+++ b/dojox/charting/plot2d/Stacked.js
@@ -1,150 +1,201 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.Stacked"]){
-dojo._hasResource["dojox.charting.plot2d.Stacked"]=true;
 dojo.provide("dojox.charting.plot2d.Stacked");
+
 dojo.require("dojox.charting.plot2d.common");
 dojo.require("dojox.charting.plot2d.Default");
+
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.sequence");
 dojo.require("dojox.lang.functional.reversed");
+
 (function(){
-var df=dojox.lang.functional,dc=dojox.charting.plot2d.common,_1=df.lambda("item.purgeGroup()");
-dojo.declare("dojox.charting.plot2d.Stacked",dojox.charting.plot2d.Default,{calculateAxes:function(_2){
-var _3=dc.collectStackedStats(this.series);
-this._maxRunLength=_3.hmax;
-this._calc(_2,_3);
-return this;
-},render:function(_4,_5){
-if(this._maxRunLength<=0){
-return this;
-}
-var _6=df.repeat(this._maxRunLength,"-> 0",0);
-for(var i=0;i<this.series.length;++i){
-var _7=this.series[i];
-for(var j=0;j<_7.data.length;++j){
-var v=_7.data[j];
-if(isNaN(v)){
-v=0;
-}
-_6[j]+=v;
-}
-}
-this.dirty=this.isDirty();
-if(this.dirty){
-dojo.forEach(this.series,_1);
-this.cleanGroup();
-var s=this.group;
-df.forEachRev(this.series,function(_8){
-_8.cleanGroup(s);
-});
-}
-var t=this.chart.theme,_9,_a,_b,_c,_d=this.events(),ht=this._hScaler.scaler.getTransformerFromModel(this._hScaler),vt=this._vScaler.scaler.getTransformerFromModel(this._vScaler);
-this.resetEvents();
-for(var i=this.series.length-1;i>=0;--i){
-var _7=this.series[i];
-if(!this.dirty&&!_7.dirty){
-continue;
-}
-_7.cleanGroup();
-var s=_7.group,_e=dojo.map(_6,function(v,i){
-return {x:ht(i+1)+_5.l,y:_4.height-_5.b-vt(v)};
-},this);
-if(!_7.fill||!_7.stroke){
-_b=new dojo.Color(t.next("color"));
-}
-var _f=this.opt.tension?dc.curve(_e,this.opt.tension):"";
-if(this.opt.areas){
-var _10=dojo.clone(_e);
-var _11=_7.fill?_7.fill:dc.augmentFill(t.series.fill,_b);
-if(this.opt.tension){
-var p=dc.curve(_10,this.opt.tension);
-p+=" L"+_e[_e.length-1].x+","+(_4.height-_5.b)+" L"+_e[0].x+","+(_4.height-_5.b)+" L"+_e[0].x+","+_e[0].y;
-_7.dyn.fill=s.createPath(p).setFill(_11).getFill();
-}else{
-_10.push({x:_e[_e.length-1].x,y:_4.height-_5.b});
-_10.push({x:_e[0].x,y:_4.height-_5.b});
-_10.push(_e[0]);
-_7.dyn.fill=s.createPolyline(_10).setFill(_11).getFill();
-}
-}
-if(this.opt.lines||this.opt.markers){
-_9=_7.stroke?dc.makeStroke(_7.stroke):dc.augmentStroke(t.series.stroke,_b);
-if(_7.outline||t.series.outline){
-_a=dc.makeStroke(_7.outline?_7.outline:t.series.outline);
-_a.width=2*_a.width+_9.width;
-}
-}
-if(this.opt.markers){
-_c=_7.dyn.marker=_7.marker?_7.marker:t.next("marker");
-}
-var _12,_13,_14;
-if(this.opt.shadows&&_9){
-var sh=this.opt.shadows,_15=new dojo.Color([0,0,0,0.3]),_16=dojo.map(_e,function(c){
-return {x:c.x+sh.dx,y:c.y+sh.dy};
-}),_17=dojo.clone(_a?_a:_9);
-_17.color=_15;
-_17.width+=sh.dw?sh.dw:0;
-if(this.opt.lines){
-if(this.opt.tension){
-_7.dyn.shadow=s.createPath(dc.curve(_16,this.opt.tension)).setStroke(_17).getStroke();
-}else{
-_7.dyn.shadow=s.createPolyline(_16).setStroke(_17).getStroke();
-}
-}
-if(this.opt.markers){
-_14=dojo.map(_16,function(c){
-return s.createPath("M"+c.x+" "+c.y+" "+_c).setStroke(_17).setFill(_15);
-},this);
-}
-}
-if(this.opt.lines){
-if(_a){
-if(this.opt.tension){
-_7.dyn.outline=s.createPath(_f).setStroke(_a).getStroke();
-}else{
-_7.dyn.outline=s.createPolyline(_e).setStroke(_a).getStroke();
-}
-}
-if(this.opt.tension){
-_7.dyn.stroke=s.createPath(_f).setStroke(_9).getStroke();
-}else{
-_7.dyn.stroke=s.createPolyline(_e).setStroke(_9).getStroke();
-}
-}
-if(this.opt.markers){
-_12=new Array(_e.length);
-_13=new Array(_e.length);
-dojo.forEach(_e,function(c,i){
-var _18="M"+c.x+" "+c.y+" "+_c;
-if(_a){
-_13[i]=s.createPath(_18).setStroke(_a);
-}
-_12[i]=s.createPath(_18).setStroke(_9).setFill(_9.color);
-},this);
-if(_d){
-dojo.forEach(_12,function(s,i){
-var o={element:"marker",index:i,run:_7,plot:this,hAxis:this.hAxis||null,vAxis:this.vAxis||null,shape:s,outline:_13[i]||null,shadow:_14&&_14[i]||null,cx:_e[i].x,cy:_e[i].y,x:i+1,y:_7.data[i]};
-this._connectEvents(s,o);
-},this);
-}
-}
-_7.dirty=false;
-for(var j=0;j<_7.data.length;++j){
-var v=_7.data[j];
-if(isNaN(v)){
-v=0;
-}
-_6[j]-=v;
-}
-}
-this.dirty=false;
-return this;
-}});
+	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	dojo.declare("dojox.charting.plot2d.Stacked", dojox.charting.plot2d.Default, {
+		//	summary:
+		//		Like the default plot, Stacked sets up lines, areas and markers
+		//		in a stacked fashion (values on the y axis added to each other)
+		//		as opposed to a direct one.
+		getSeriesStats: function(){
+			//	summary:
+			//		Calculate the min/max on all attached series in both directions.
+			//	returns: Object
+			//		{hmin, hmax, vmin, vmax} min/max in both directions.
+			var stats = dc.collectStackedStats(this.series);
+			this._maxRunLength = stats.hmax;
+			return stats;
+		},
+		render: function(dim, offsets){
+			//	summary:
+			//		Run the calculations for any axes for this plot.
+			//	dim: Object
+			//		An object in the form of { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b}.
+			//	returns: dojox.charting.plot2d.Stacked
+			//		A reference to this plot for functional chaining.
+			if(this._maxRunLength <= 0){
+				return this;
+			}
+
+			// stack all values
+			var acc = df.repeat(this._maxRunLength, "-> 0", 0);
+			for(var i = 0; i < this.series.length; ++i){
+				var run = this.series[i];
+				for(var j = 0; j < run.data.length; ++j){
+					var v = run.data[j];
+					if(v !== null){
+						if(isNaN(v)){ v = 0; }
+						acc[j] += v;
+					}
+				}
+			}
+			// draw runs in backwards
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+			this.resetEvents();
+			this.dirty = this.isDirty();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+
+			var t = this.chart.theme, events = this.events(),
+				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler);
+
+			for(var i = this.series.length - 1; i >= 0; --i){
+				var run = this.series[i];
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				var theme = t.next(this.opt.areas ? "area" : "line", [this.opt, run], true),
+					s = run.group, outline,
+					lpoly = dojo.map(acc, function(v, i){
+						return {
+							x: ht(i + 1) + offsets.l,
+							y: dim.height - offsets.b - vt(v)
+						};
+					}, this);
+
+				var lpath = this.opt.tension ? dc.curve(lpoly, this.opt.tension) : "";
+
+				if(this.opt.areas){
+					var apoly = dojo.clone(lpoly);
+					if(this.opt.tension){
+						var p=dc.curve(apoly, this.opt.tension);
+						p += " L" + lpoly[lpoly.length - 1].x + "," + (dim.height - offsets.b) +
+							" L" + lpoly[0].x + "," + (dim.height - offsets.b) +
+							" L" + lpoly[0].x + "," + lpoly[0].y;
+						run.dyn.fill = s.createPath(p).setFill(theme.series.fill).getFill();
+					} else {
+						apoly.push({x: lpoly[lpoly.length - 1].x, y: dim.height - offsets.b});
+						apoly.push({x: lpoly[0].x, y: dim.height - offsets.b});
+						apoly.push(lpoly[0]);
+						run.dyn.fill = s.createPolyline(apoly).setFill(theme.series.fill).getFill();
+					}
+				}
+				if(this.opt.lines || this.opt.markers){
+					if(theme.series.outline){
+						outline = dc.makeStroke(theme.series.outline);
+						outline.width = 2 * outline.width + theme.series.stroke.width;
+					}
+				}
+				if(this.opt.markers){
+					run.dyn.marker = theme.symbol;
+				}
+				var frontMarkers, outlineMarkers, shadowMarkers;
+				if(theme.series.shadow && theme.series.stroke){
+					var shadow = theme.series.shadow,
+						spoly = dojo.map(lpoly, function(c){
+							return {x: c.x + shadow.dx, y: c.y + shadow.dy};
+						});
+					if(this.opt.lines){
+						if(this.opt.tension){
+							run.dyn.shadow = s.createPath(dc.curve(spoly, this.opt.tension)).setStroke(shadow).getStroke();
+						} else {
+							run.dyn.shadow = s.createPolyline(spoly).setStroke(shadow).getStroke();
+						}
+					}
+					if(this.opt.markers){
+						shadow = theme.marker.shadow;
+						shadowMarkers = dojo.map(spoly, function(c){
+							return s.createPath("M" + c.x + " " + c.y + " " + theme.symbol).
+								setStroke(shadow).setFill(shadow.color);
+						}, this);
+					}
+				}
+				if(this.opt.lines){
+					if(outline){
+						if(this.opt.tension){
+							run.dyn.outline = s.createPath(lpath).setStroke(outline).getStroke();
+						} else {
+							run.dyn.outline = s.createPolyline(lpoly).setStroke(outline).getStroke();
+						}
+					}
+					if(this.opt.tension){
+						run.dyn.stroke = s.createPath(lpath).setStroke(theme.series.stroke).getStroke();
+					} else {
+						run.dyn.stroke = s.createPolyline(lpoly).setStroke(theme.series.stroke).getStroke();
+					}
+				}
+				if(this.opt.markers){
+					frontMarkers = new Array(lpoly.length);
+					outlineMarkers = new Array(lpoly.length);
+					outline = null;
+					if(theme.marker.outline){
+						outline = dc.makeStroke(theme.marker.outline);
+						outline.width = 2 * outline.width + (theme.marker.stroke ? theme.marker.stroke.width : 0);
+					}
+					dojo.forEach(lpoly, function(c, i){
+						var path = "M" + c.x + " " + c.y + " " + theme.symbol;
+						if(outline){
+							outlineMarkers[i] = s.createPath(path).setStroke(outline);
+						}
+						frontMarkers[i] = s.createPath(path).setStroke(theme.marker.stroke).setFill(theme.marker.fill);
+					}, this);
+					if(events){
+						var eventSeries = new Array(frontMarkers.length);
+						dojo.forEach(frontMarkers, function(s, i){
+							var o = {
+								element: "marker",
+								index:   i,
+								run:     run,
+								shape:   s,
+								outline: outlineMarkers[i] || null,
+								shadow:  shadowMarkers && shadowMarkers[i] || null,
+								cx:      lpoly[i].x,
+								cy:      lpoly[i].y,
+								x:       i + 1,
+								y:       run.data[i]
+							};
+							this._connectEvents(o);
+							eventSeries[i] = o;
+						}, this);
+						this._eventSeries[run.name] = eventSeries;
+					}else{
+						delete this._eventSeries[run.name];
+					}
+				}
+				run.dirty = false;
+				// update the accumulator
+				for(var j = 0; j < run.data.length; ++j){
+					var v = run.data[j];
+					if(v !== null){
+						if(isNaN(v)){ v = 0; }
+						acc[j] -= v;
+					}
+				}
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.Stacked
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/StackedAreas.js b/dojox/charting/plot2d/StackedAreas.js
index 85ecfa9..d5c5590 100644
--- a/dojox/charting/plot2d/StackedAreas.js
+++ b/dojox/charting/plot2d/StackedAreas.js
@@ -1,16 +1,14 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.StackedAreas"]){
-dojo._hasResource["dojox.charting.plot2d.StackedAreas"]=true;
 dojo.provide("dojox.charting.plot2d.StackedAreas");
+
 dojo.require("dojox.charting.plot2d.Stacked");
-dojo.declare("dojox.charting.plot2d.StackedAreas",dojox.charting.plot2d.Stacked,{constructor:function(){
-this.opt.lines=true;
-this.opt.areas=true;
-}});
-}
+
+dojo.declare("dojox.charting.plot2d.StackedAreas", dojox.charting.plot2d.Stacked, {
+	//	summary:
+	//		A convenience object to set up a stacked area plot.
+	constructor: function(){
+		//	summary:
+		//		Force our Stacked plotter to include both lines and areas.
+		this.opt.lines = true;
+		this.opt.areas = true;
+	}
+});
diff --git a/dojox/charting/plot2d/StackedBars.js b/dojox/charting/plot2d/StackedBars.js
index 8422f33..b57b073 100644
--- a/dojox/charting/plot2d/StackedBars.js
+++ b/dojox/charting/plot2d/StackedBars.js
@@ -1,114 +1,138 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.StackedBars"]){
-dojo._hasResource["dojox.charting.plot2d.StackedBars"]=true;
 dojo.provide("dojox.charting.plot2d.StackedBars");
+
 dojo.require("dojox.charting.plot2d.common");
 dojo.require("dojox.charting.plot2d.Bars");
+
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.reversed");
+
 (function(){
-var df=dojox.lang.functional,dc=dojox.charting.plot2d.common,_1=df.lambda("item.purgeGroup()");
-dojo.declare("dojox.charting.plot2d.StackedBars",dojox.charting.plot2d.Bars,{calculateAxes:function(_2){
-var _3=dc.collectStackedStats(this.series),t;
-this._maxRunLength=_3.hmax;
-_3.hmin-=0.5;
-_3.hmax+=0.5;
-t=_3.hmin,_3.hmin=_3.vmin,_3.vmin=t;
-t=_3.hmax,_3.hmax=_3.vmax,_3.vmax=t;
-this._calc(_2,_3);
-return this;
-},render:function(_4,_5){
-if(this._maxRunLength<=0){
-return this;
-}
-var _6=df.repeat(this._maxRunLength,"-> 0",0);
-for(var i=0;i<this.series.length;++i){
-var _7=this.series[i];
-for(var j=0;j<_7.data.length;++j){
-var _8=_7.data[j],v=typeof _8=="number"?_8:_8.y;
-if(isNaN(v)){
-v=0;
-}
-_6[j]+=v;
-}
-}
-this.dirty=this.isDirty();
-if(this.dirty){
-dojo.forEach(this.series,_1);
-this.cleanGroup();
-var s=this.group;
-df.forEachRev(this.series,function(_9){
-_9.cleanGroup(s);
-});
-}
-var t=this.chart.theme,_a,_b,_c,f,_d,_e,ht=this._hScaler.scaler.getTransformerFromModel(this._hScaler),vt=this._vScaler.scaler.getTransformerFromModel(this._vScaler),_f=this.events();
-f=dc.calculateBarSize(this._vScaler.bounds.scale,this.opt);
-_d=f.gap;
-_e=f.size;
-this.resetEvents();
-for(var i=this.series.length-1;i>=0;--i){
-var _7=this.series[i];
-if(!this.dirty&&!_7.dirty){
-continue;
-}
-_7.cleanGroup();
-var s=_7.group;
-if(!_7.fill||!_7.stroke){
-_a=_7.dyn.color=new dojo.Color(t.next("color"));
-}
-_b=_7.stroke?_7.stroke:dc.augmentStroke(t.series.stroke,_a);
-_c=_7.fill?_7.fill:dc.augmentFill(t.series.fill,_a);
-for(var j=0;j<_6.length;++j){
-var v=_6[j],_10=ht(v),_8=_7.data[j],_11=_a,_12=_c,_13=_b;
-if(typeof _8!="number"){
-if(_8.color){
-_11=new dojo.Color(_8.color);
-}
-if("fill" in _8){
-_12=_8.fill;
-}else{
-if(_8.color){
-_12=dc.augmentFill(t.series.fill,_11);
-}
-}
-if("stroke" in _8){
-_13=_8.stroke;
-}else{
-if(_8.color){
-_13=dc.augmentStroke(t.series.stroke,_11);
-}
-}
-}
-if(_10>=1&&_e>=1){
-var _14=s.createRect({x:_5.l,y:_4.height-_5.b-vt(j+1.5)+_d,width:_10,height:_e}).setFill(_12).setStroke(_13);
-_7.dyn.fill=_14.getFill();
-_7.dyn.stroke=_14.getStroke();
-if(_f){
-var o={element:"bar",index:j,run:_7,plot:this,hAxis:this.hAxis||null,vAxis:this.vAxis||null,shape:_14,x:v,y:j+1.5};
-this._connectEvents(_14,o);
-}
-if(this.animate){
-this._animateBar(_14,_5.l,-_10);
-}
-}
-}
-_7.dirty=false;
-for(var j=0;j<_7.data.length;++j){
-var _8=_7.data[j],v=typeof _8=="number"?_8:_8.y;
-if(isNaN(v)){
-v=0;
-}
-_6[j]-=v;
-}
-}
-this.dirty=false;
-return this;
-}});
+	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	dojo.declare("dojox.charting.plot2d.StackedBars", dojox.charting.plot2d.Bars, {
+		//	summary:
+		//		The plot object representing a stacked bar chart (horizontal bars).
+		getSeriesStats: function(){
+			//	summary:
+			//		Calculate the min/max on all attached series in both directions.
+			//	returns: Object
+			//		{hmin, hmax, vmin, vmax} min/max in both directions.
+			var stats = dc.collectStackedStats(this.series), t;
+			this._maxRunLength = stats.hmax;
+			stats.hmin -= 0.5;
+			stats.hmax += 0.5;
+			t = stats.hmin, stats.hmin = stats.vmin, stats.vmin = t;
+			t = stats.hmax, stats.hmax = stats.vmax, stats.vmax = t;
+			return stats;
+		},
+		render: function(dim, offsets){
+			//	summary:
+			//		Run the calculations for any axes for this plot.
+			//	dim: Object
+			//		An object in the form of { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b}.
+			//	returns: dojox.charting.plot2d.StackedBars
+			//		A reference to this plot for functional chaining.
+			if(this._maxRunLength <= 0){
+				return this;
+			}
+
+			// stack all values
+			var acc = df.repeat(this._maxRunLength, "-> 0", 0);
+			for(var i = 0; i < this.series.length; ++i){
+				var run = this.series[i];
+				for(var j = 0; j < run.data.length; ++j){
+					var value = run.data[j];
+					if(value !== null){
+						var v = typeof value == "number" ? value : value.y;
+						if(isNaN(v)){ v = 0; }
+						acc[j] += v;
+					}
+				}
+			}
+			// draw runs in backwards
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+			this.resetEvents();
+			this.dirty = this.isDirty();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+			var t = this.chart.theme, f, gap, height,
+				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
+				events = this.events();
+			f = dc.calculateBarSize(this._vScaler.bounds.scale, this.opt);
+			gap = f.gap;
+			height = f.size;
+			for(var i = this.series.length - 1; i >= 0; --i){
+				var run = this.series[i];
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				var theme = t.next("bar", [this.opt, run]), s = run.group,
+					eventSeries = new Array(acc.length);
+				for(var j = 0; j < acc.length; ++j){
+					var value = run.data[j];
+					if(value !== null){
+						var v = acc[j],
+							width = ht(v),
+							finalTheme = typeof value != "number" ?
+								t.addMixin(theme, "bar", value, true) :
+								t.post(theme, "bar");
+						if(width >= 1 && height >= 1){
+							var rect = {
+								x: offsets.l,
+								y: dim.height - offsets.b - vt(j + 1.5) + gap,
+								width: width, height: height
+							};
+							var specialFill = this._plotFill(finalTheme.series.fill, dim, offsets);
+							specialFill = this._shapeFill(specialFill, rect);
+							var shape = s.createRect(rect).setFill(specialFill).setStroke(finalTheme.series.stroke);
+							run.dyn.fill   = shape.getFill();
+							run.dyn.stroke = shape.getStroke();
+							if(events){
+								var o = {
+									element: "bar",
+									index:   j,
+									run:     run,
+									shape:   shape,
+									x:       v,
+									y:       j + 1.5
+								};
+								this._connectEvents(o);
+								eventSeries[j] = o;
+							}
+							if(this.animate){
+								this._animateBar(shape, offsets.l, -width);
+							}
+						}
+					}
+				}
+				this._eventSeries[run.name] = eventSeries;
+				run.dirty = false;
+				// update the accumulator
+				for(var j = 0; j < run.data.length; ++j){
+					var value = run.data[j];
+					if(value !== null){
+						var v = typeof value == "number" ? value : value.y;
+						if(isNaN(v)){ v = 0; }
+						acc[j] -= v;
+					}
+				}
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.StackedBars
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/StackedColumns.js b/dojox/charting/plot2d/StackedColumns.js
index edee16c..3bd4a71 100644
--- a/dojox/charting/plot2d/StackedColumns.js
+++ b/dojox/charting/plot2d/StackedColumns.js
@@ -1,112 +1,136 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.StackedColumns"]){
-dojo._hasResource["dojox.charting.plot2d.StackedColumns"]=true;
 dojo.provide("dojox.charting.plot2d.StackedColumns");
+
 dojo.require("dojox.charting.plot2d.common");
 dojo.require("dojox.charting.plot2d.Columns");
+
 dojo.require("dojox.lang.functional");
 dojo.require("dojox.lang.functional.reversed");
+
 (function(){
-var df=dojox.lang.functional,dc=dojox.charting.plot2d.common,_1=df.lambda("item.purgeGroup()");
-dojo.declare("dojox.charting.plot2d.StackedColumns",dojox.charting.plot2d.Columns,{calculateAxes:function(_2){
-var _3=dc.collectStackedStats(this.series);
-this._maxRunLength=_3.hmax;
-_3.hmin-=0.5;
-_3.hmax+=0.5;
-this._calc(_2,_3);
-return this;
-},render:function(_4,_5){
-if(this._maxRunLength<=0){
-return this;
-}
-var _6=df.repeat(this._maxRunLength,"-> 0",0);
-for(var i=0;i<this.series.length;++i){
-var _7=this.series[i];
-for(var j=0;j<_7.data.length;++j){
-var _8=_7.data[j],v=typeof _8=="number"?_8:_8.y;
-if(isNaN(v)){
-v=0;
-}
-_6[j]+=v;
-}
-}
-this.dirty=this.isDirty();
-if(this.dirty){
-dojo.forEach(this.series,_1);
-this.cleanGroup();
-var s=this.group;
-df.forEachRev(this.series,function(_9){
-_9.cleanGroup(s);
-});
-}
-var t=this.chart.theme,_a,_b,_c,f,_d,_e,ht=this._hScaler.scaler.getTransformerFromModel(this._hScaler),vt=this._vScaler.scaler.getTransformerFromModel(this._vScaler),_f=this.events();
-f=dc.calculateBarSize(this._hScaler.bounds.scale,this.opt);
-_d=f.gap;
-_e=f.size;
-this.resetEvents();
-for(var i=this.series.length-1;i>=0;--i){
-var _7=this.series[i];
-if(!this.dirty&&!_7.dirty){
-continue;
-}
-_7.cleanGroup();
-var s=_7.group;
-if(!_7.fill||!_7.stroke){
-_a=_7.dyn.color=new dojo.Color(t.next("color"));
-}
-_b=_7.stroke?_7.stroke:dc.augmentStroke(t.series.stroke,_a);
-_c=_7.fill?_7.fill:dc.augmentFill(t.series.fill,_a);
-for(var j=0;j<_6.length;++j){
-var v=_6[j],_10=vt(v),_8=_7.data[j],_11=_a,_12=_c,_13=_b;
-if(typeof _8!="number"){
-if(_8.color){
-_11=new dojo.Color(_8.color);
-}
-if("fill" in _8){
-_12=_8.fill;
-}else{
-if(_8.color){
-_12=dc.augmentFill(t.series.fill,_11);
-}
-}
-if("stroke" in _8){
-_13=_8.stroke;
-}else{
-if(_8.color){
-_13=dc.augmentStroke(t.series.stroke,_11);
-}
-}
-}
-if(_e>=1&&_10>=1){
-var _14=s.createRect({x:_5.l+ht(j+0.5)+_d,y:_4.height-_5.b-vt(v),width:_e,height:_10}).setFill(_12).setStroke(_13);
-_7.dyn.fill=_14.getFill();
-_7.dyn.stroke=_14.getStroke();
-if(_f){
-var o={element:"column",index:j,run:_7,plot:this,hAxis:this.hAxis||null,vAxis:this.vAxis||null,shape:_14,x:j+0.5,y:v};
-this._connectEvents(_14,o);
-}
-if(this.animate){
-this._animateColumn(_14,_4.height-_5.b,_10);
-}
-}
-}
-_7.dirty=false;
-for(var j=0;j<_7.data.length;++j){
-var _8=_7.data[j],v=typeof _8=="number"?_8:_8.y;
-if(isNaN(v)){
-v=0;
-}
-_6[j]-=v;
-}
-}
-this.dirty=false;
-return this;
-}});
+	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common,
+		purgeGroup = df.lambda("item.purgeGroup()");
+
+	dojo.declare("dojox.charting.plot2d.StackedColumns", dojox.charting.plot2d.Columns, {
+		//	summary:
+		//		The plot object representing a stacked column chart (vertical bars).
+		getSeriesStats: function(){
+			//	summary:
+			//		Calculate the min/max on all attached series in both directions.
+			//	returns: Object
+			//		{hmin, hmax, vmin, vmax} min/max in both directions.
+			var stats = dc.collectStackedStats(this.series);
+			this._maxRunLength = stats.hmax;
+			stats.hmin -= 0.5;
+			stats.hmax += 0.5;
+			return stats;
+		},
+		render: function(dim, offsets){
+			//	summary:
+			//		Run the calculations for any axes for this plot.
+			//	dim: Object
+			//		An object in the form of { width, height }
+			//	offsets: Object
+			//		An object of the form { l, r, t, b}.
+			//	returns: dojox.charting.plot2d.StackedColumns
+			//		A reference to this plot for functional chaining.
+			if(this._maxRunLength <= 0){
+				return this;
+			}
+
+			// stack all values
+			var acc = df.repeat(this._maxRunLength, "-> 0", 0);
+			for(var i = 0; i < this.series.length; ++i){
+				var run = this.series[i];
+				for(var j = 0; j < run.data.length; ++j){
+					var value = run.data[j];
+					if(value !== null){
+						var v = typeof value == "number" ? value : value.y;
+						if(isNaN(v)){ v = 0; }
+						acc[j] += v;
+					}
+				}
+			}
+			// draw runs in backwards
+			if(this.zoom && !this.isDataDirty()){
+				return this.performZoom(dim, offsets);
+			}
+			this.resetEvents();
+			this.dirty = this.isDirty();
+			if(this.dirty){
+				dojo.forEach(this.series, purgeGroup);
+				this._eventSeries = {};
+				this.cleanGroup();
+				var s = this.group;
+				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
+			}
+			var t = this.chart.theme, f, gap, width,
+				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
+				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
+				events = this.events();
+			f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt);
+			gap = f.gap;
+			width = f.size;
+			for(var i = this.series.length - 1; i >= 0; --i){
+				var run = this.series[i];
+				if(!this.dirty && !run.dirty){
+					t.skip();
+					this._reconnectEvents(run.name);
+					continue;
+				}
+				run.cleanGroup();
+				var theme = t.next("column", [this.opt, run]), s = run.group,
+					eventSeries = new Array(acc.length);
+				for(var j = 0; j < acc.length; ++j){
+					var value = run.data[j];
+					if(value !== null){
+						var v = acc[j],
+							height = vt(v),
+							finalTheme = typeof value != "number" ?
+								t.addMixin(theme, "column", value, true) :
+								t.post(theme, "column");
+						if(width >= 1 && height >= 1){
+							var rect = {
+								x: offsets.l + ht(j + 0.5) + gap,
+								y: dim.height - offsets.b - vt(v),
+								width: width, height: height
+							};
+							var specialFill = this._plotFill(finalTheme.series.fill, dim, offsets);
+							specialFill = this._shapeFill(specialFill, rect);
+							var shape = s.createRect(rect).setFill(specialFill).setStroke(finalTheme.series.stroke);
+							run.dyn.fill   = shape.getFill();
+							run.dyn.stroke = shape.getStroke();
+							if(events){
+								var o = {
+									element: "column",
+									index:   j,
+									run:     run,
+									shape:   shape,
+									x:       j + 0.5,
+									y:       v
+								};
+								this._connectEvents(o);
+								eventSeries[j] = o;
+							}
+							if(this.animate){
+								this._animateColumn(shape, dim.height - offsets.b, height);
+							}
+						}
+					}
+				}
+				this._eventSeries[run.name] = eventSeries;
+				run.dirty = false;
+				// update the accumulator
+				for(var j = 0; j < run.data.length; ++j){
+					var value = run.data[j];
+					if(value !== null){
+						var v = typeof value == "number" ? value : value.y;
+						if(isNaN(v)){ v = 0; }
+						acc[j] -= v;
+					}
+				}
+			}
+			this.dirty = false;
+			return this;	//	dojox.charting.plot2d.StackedColumns
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot2d/StackedLines.js b/dojox/charting/plot2d/StackedLines.js
index 8396132..6e42c49 100644
--- a/dojox/charting/plot2d/StackedLines.js
+++ b/dojox/charting/plot2d/StackedLines.js
@@ -1,15 +1,13 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.StackedLines"]){
-dojo._hasResource["dojox.charting.plot2d.StackedLines"]=true;
 dojo.provide("dojox.charting.plot2d.StackedLines");
+
 dojo.require("dojox.charting.plot2d.Stacked");
-dojo.declare("dojox.charting.plot2d.StackedLines",dojox.charting.plot2d.Stacked,{constructor:function(){
-this.opt.lines=true;
-}});
-}
+
+dojo.declare("dojox.charting.plot2d.StackedLines", dojox.charting.plot2d.Stacked, {
+	//	summary:
+	//		A convenience object to create a stacked line chart.
+	constructor: function(){
+		//	summary:
+		//		Force our Stacked base to be lines only.
+		this.opt.lines = true;
+	}
+});
diff --git a/dojox/charting/plot2d/_PlotEvents.js b/dojox/charting/plot2d/_PlotEvents.js
new file mode 100644
index 0000000..0bd29a9
--- /dev/null
+++ b/dojox/charting/plot2d/_PlotEvents.js
@@ -0,0 +1,123 @@
+dojo.provide("dojox.charting.plot2d._PlotEvents");
+
+dojo.declare("dojox.charting.plot2d._PlotEvents", null, {
+	constructor: function(){
+		this._shapeEvents = [];
+		this._eventSeries = {};
+	},
+	destroy: function(){
+		//	summary:
+		//		Destroy any internal elements and event handlers.
+		this.resetEvents();
+		this.inherited(arguments);
+	},
+	plotEvent: function(o){
+		//	summary:
+		//		Stub function for use by specific plots.
+		//	o: Object
+		//		An object intended to represent event parameters.
+	},
+	raiseEvent: function(o){
+		//	summary:
+		//		Raises events in predefined order
+		//	o: Object
+		//		An object intended to represent event parameters.
+		this.plotEvent(o);
+		var t = dojo.delegate(o);
+		t.originalEvent = o.type;
+		t.originalPlot  = o.plot;
+		t.type = "onindirect";
+		dojo.forEach(this.chart.stack, function(plot){
+			if(plot !== this && plot.plotEvent){
+				t.plot = plot;
+				plot.plotEvent(t);
+			}
+		}, this);
+	},
+	connect: function(object, method){
+		//	summary:
+		//		Helper function to connect any object's method to our plotEvent.
+		//	object: Object
+		//		The object to connect to.
+		//	method: String|Function
+		//		The method to fire when our plotEvent is fired.
+		//	returns: Array
+		//		The handle as returned from dojo.connect (see dojo.connect).
+		this.dirty = true;
+		return dojo.connect(this, "plotEvent", object, method);	//	Array
+	},
+	events: function(){
+		//	summary:
+		//		Find out if any event handlers have been connected to our plotEvent.
+		//	returns: Boolean
+		//		A flag indicating that there are handlers attached.
+		var ls = this.plotEvent._listeners;
+		if(!ls || !ls.length){ return false; }
+		for(var i in ls){
+			if(!(i in Array.prototype)){
+				return true;
+			}
+		}
+		return false;
+	},
+	resetEvents: function(){
+		//	summary:
+		//		Reset all events attached to our plotEvent (i.e. disconnect).
+		if(this._shapeEvents.length){
+			dojo.forEach(this._shapeEvents, function(item){
+				item.shape.disconnect(item.handle);
+			});
+			this._shapeEvents = [];
+		}
+		this.raiseEvent({type: "onplotreset", plot: this});
+	},
+	_connectSingleEvent: function(o, eventName){
+		this._shapeEvents.push({
+			shape:  o.eventMask,
+			handle: o.eventMask.connect(eventName, this, function(e){
+				o.type  = eventName;
+				o.event = e;
+				this.raiseEvent(o);
+				o.event = null;
+			})
+		});
+	},
+	_connectEvents: function(o){
+		o.chart = this.chart;
+		o.plot  = this;
+		o.hAxis = this.hAxis || null;
+		o.vAxis = this.vAxis || null;
+		o.eventMask = o.eventMask || o.shape;
+		this._connectSingleEvent(o, "onmouseover");
+		this._connectSingleEvent(o, "onmouseout");
+		this._connectSingleEvent(o, "onclick");
+	},
+	_reconnectEvents: function(seriesName){
+		var a = this._eventSeries[seriesName];
+		if(a){
+			dojo.forEach(a, this._connectEvents, this);
+		}
+	},
+	fireEvent: function(seriesName, eventName, index, eventObject){
+		//	summary:
+		//		Emulates firing an event for a given data value (specified by
+		//		an index) of a given series.
+		//	seriesName: String:
+		//		Series name.
+		//	eventName: String:
+		//		Event name to emulate.
+		//	index:	Number:
+		//		Valid data value index used to raise an event.
+		//	eventObject: Object?:
+		//		Optional event object. Especially useful for synthetic events.
+		//		Default: null.
+		var s = this._eventSeries[seriesName];
+		if(s && s.length && index < s.length){
+			var o = s[index];
+			o.type  = eventName;
+			o.event = eventObject || null;
+			this.raiseEvent(o);
+			o.event = null;
+		}
+	}
+});
diff --git a/dojox/charting/plot2d/common.js b/dojox/charting/plot2d/common.js
index d7b8dc3..e464b0b 100644
--- a/dojox/charting/plot2d/common.js
+++ b/dojox/charting/plot2d/common.js
@@ -1,210 +1,207 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot2d.common"]){
-dojo._hasResource["dojox.charting.plot2d.common"]=true;
 dojo.provide("dojox.charting.plot2d.common");
+
 dojo.require("dojo.colors");
 dojo.require("dojox.gfx");
 dojo.require("dojox.lang.functional");
+
 (function(){
-var df=dojox.lang.functional,dc=dojox.charting.plot2d.common;
-dojo.mixin(dojox.charting.plot2d.common,{makeStroke:function(_1){
-if(!_1){
-return _1;
-}
-if(typeof _1=="string"||_1 instanceof dojo.Color){
-_1={color:_1};
-}
-return dojox.gfx.makeParameters(dojox.gfx.defaultStroke,_1);
-},augmentColor:function(_2,_3){
-var t=new dojo.Color(_2),c=new dojo.Color(_3);
-c.a=t.a;
-return c;
-},augmentStroke:function(_4,_5){
-var s=dc.makeStroke(_4);
-if(s){
-s.color=dc.augmentColor(s.color,_5);
-}
-return s;
-},augmentFill:function(_6,_7){
-var fc,c=new dojo.Color(_7);
-if(typeof _6=="string"||_6 instanceof dojo.Color){
-return dc.augmentColor(_6,_7);
-}
-return _6;
-},defaultStats:{hmin:Number.POSITIVE_INFINITY,hmax:Number.NEGATIVE_INFINITY,vmin:Number.POSITIVE_INFINITY,vmax:Number.NEGATIVE_INFINITY},collectSimpleStats:function(_8){
-var _9=dojo.clone(dc.defaultStats);
-for(var i=0;i<_8.length;++i){
-var _a=_8[i];
-if(!_a.data.length){
-continue;
-}
-if(typeof _a.data[0]=="number"){
-var _b=_9.vmin,_c=_9.vmax;
-if(!("ymin" in _a)||!("ymax" in _a)){
-dojo.forEach(_a.data,function(_d,i){
-var x=i+1,y=_d;
-if(isNaN(y)){
-y=0;
-}
-_9.hmin=Math.min(_9.hmin,x);
-_9.hmax=Math.max(_9.hmax,x);
-_9.vmin=Math.min(_9.vmin,y);
-_9.vmax=Math.max(_9.vmax,y);
-});
-}
-if("ymin" in _a){
-_9.vmin=Math.min(_b,_a.ymin);
-}
-if("ymax" in _a){
-_9.vmax=Math.max(_c,_a.ymax);
-}
-}else{
-var _e=_9.hmin,_f=_9.hmax,_b=_9.vmin,_c=_9.vmax;
-if(!("xmin" in _a)||!("xmax" in _a)||!("ymin" in _a)||!("ymax" in _a)){
-dojo.forEach(_a.data,function(val,i){
-var x="x" in val?val.x:i+1,y=val.y;
-if(isNaN(x)){
-x=0;
-}
-if(isNaN(y)){
-y=0;
-}
-_9.hmin=Math.min(_9.hmin,x);
-_9.hmax=Math.max(_9.hmax,x);
-_9.vmin=Math.min(_9.vmin,y);
-_9.vmax=Math.max(_9.vmax,y);
-});
-}
-if("xmin" in _a){
-_9.hmin=Math.min(_e,_a.xmin);
-}
-if("xmax" in _a){
-_9.hmax=Math.max(_f,_a.xmax);
-}
-if("ymin" in _a){
-_9.vmin=Math.min(_b,_a.ymin);
-}
-if("ymax" in _a){
-_9.vmax=Math.max(_c,_a.ymax);
-}
-}
-}
-return _9;
-},calculateBarSize:function(_10,opt,_11){
-if(!_11){
-_11=1;
-}
-var gap=opt.gap,_12=(_10-2*gap)/_11;
-if("minBarSize" in opt){
-_12=Math.max(_12,opt.minBarSize);
-}
-if("maxBarSize" in opt){
-_12=Math.min(_12,opt.maxBarSize);
-}
-_12=Math.max(_12,1);
-gap=(_10-_12*_11)/2;
-return {size:_12,gap:gap};
-},collectStackedStats:function(_13){
-var _14=dojo.clone(dc.defaultStats);
-if(_13.length){
-_14.hmin=Math.min(_14.hmin,1);
-_14.hmax=df.foldl(_13,"seed, run -> Math.max(seed, run.data.length)",_14.hmax);
-for(var i=0;i<_14.hmax;++i){
-var v=_13[0].data[i];
-if(isNaN(v)){
-v=0;
-}
-_14.vmin=Math.min(_14.vmin,v);
-for(var j=1;j<_13.length;++j){
-var t=_13[j].data[i];
-if(isNaN(t)){
-t=0;
-}
-v+=t;
-}
-_14.vmax=Math.max(_14.vmax,v);
-}
-}
-return _14;
-},curve:function(a,_15){
-var arr=a.slice(0);
-if(_15=="x"){
-arr[arr.length]=arr[0];
-}
-var p=dojo.map(arr,function(_16,i){
-if(i==0){
-return "M"+_16.x+","+_16.y;
-}
-if(!isNaN(_15)){
-var dx=_16.x-arr[i-1].x,dy=arr[i-1].y;
-return "C"+(_16.x-(_15-1)*(dx/_15))+","+dy+" "+(_16.x-(dx/_15))+","+_16.y+" "+_16.x+","+_16.y;
-}else{
-if(_15=="X"||_15=="x"||_15=="S"){
-var p0,p1=arr[i-1],p2=arr[i],p3;
-var _17,_18,_19,_1a;
-var f=1/6;
-if(i==1){
-if(_15=="x"){
-p0=arr[arr.length-2];
-}else{
-p0=p1;
-}
-f=1/3;
-}else{
-p0=arr[i-2];
-}
-if(i==(arr.length-1)){
-if(_15=="x"){
-p3=arr[1];
-}else{
-p3=p2;
-}
-f=1/3;
-}else{
-p3=arr[i+1];
-}
-var _1b=Math.sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
-var _1c=Math.sqrt((p2.x-p0.x)*(p2.x-p0.x)+(p2.y-p0.y)*(p2.y-p0.y));
-var _1d=Math.sqrt((p3.x-p1.x)*(p3.x-p1.x)+(p3.y-p1.y)*(p3.y-p1.y));
-var _1e=_1c*f;
-var _1f=_1d*f;
-if(_1e>_1b/2&&_1f>_1b/2){
-_1e=_1b/2;
-_1f=_1b/2;
-}else{
-if(_1e>_1b/2){
-_1e=_1b/2;
-_1f=_1b/2*_1d/_1c;
-}else{
-if(_1f>_1b/2){
-_1f=_1b/2;
-_1e=_1b/2*_1c/_1d;
-}
-}
-}
-if(_15=="S"){
-if(p0==p1){
-_1e=0;
-}
-if(p2==p3){
-_1f=0;
-}
-}
-_17=p1.x+_1e*(p2.x-p0.x)/_1c;
-_18=p1.y+_1e*(p2.y-p0.y)/_1c;
-_19=p2.x-_1f*(p3.x-p1.x)/_1d;
-_1a=p2.y-_1f*(p3.y-p1.y)/_1d;
-}
-}
-return "C"+(_17+","+_18+" "+_19+","+_1a+" "+p2.x+","+p2.y);
-});
-return p.join(" ");
-}});
+	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common;
+
+	dojo.mixin(dojox.charting.plot2d.common, {
+		makeStroke: function(stroke){
+			if(!stroke){ return stroke; }
+			if(typeof stroke == "string" || stroke instanceof dojo.Color){
+				stroke = {color: stroke};
+			}
+			return dojox.gfx.makeParameters(dojox.gfx.defaultStroke, stroke);
+		},
+		augmentColor: function(target, color){
+			var t = new dojo.Color(target),
+				c = new dojo.Color(color);
+			c.a = t.a;
+			return c;
+		},
+		augmentStroke: function(stroke, color){
+			var s = dc.makeStroke(stroke);
+			if(s){
+				s.color = dc.augmentColor(s.color, color);
+			}
+			return s;
+		},
+		augmentFill: function(fill, color){
+			var fc, c = new dojo.Color(color);
+			if(typeof fill == "string" || fill instanceof dojo.Color){
+				return dc.augmentColor(fill, color);
+			}
+			return fill;
+		},
+
+		defaultStats: {
+			hmin: Number.POSITIVE_INFINITY, hmax: Number.NEGATIVE_INFINITY,
+			vmin: Number.POSITIVE_INFINITY, vmax: Number.NEGATIVE_INFINITY
+		},
+
+		collectSimpleStats: function(series){
+			var stats = dojo.delegate(dc.defaultStats);
+			for(var i = 0; i < series.length; ++i){
+				var run = series[i];
+				for(var j = 0; j < run.data.length; j++){
+					if(run.data[j] !== null){
+						if(typeof run.data[j] == "number"){
+							// 1D case
+							var old_vmin = stats.vmin, old_vmax = stats.vmax;
+							if(!("ymin" in run) || !("ymax" in run)){
+								dojo.forEach(run.data, function(val, i){
+									if(val !== null){
+										var x = i + 1, y = val;
+										if(isNaN(y)){ y = 0; }
+										stats.hmin = Math.min(stats.hmin, x);
+										stats.hmax = Math.max(stats.hmax, x);
+										stats.vmin = Math.min(stats.vmin, y);
+										stats.vmax = Math.max(stats.vmax, y);
+									}
+								});
+							}
+							if("ymin" in run){ stats.vmin = Math.min(old_vmin, run.ymin); }
+							if("ymax" in run){ stats.vmax = Math.max(old_vmax, run.ymax); }
+						}else{
+							// 2D case
+							var old_hmin = stats.hmin, old_hmax = stats.hmax,
+								old_vmin = stats.vmin, old_vmax = stats.vmax;
+							if(!("xmin" in run) || !("xmax" in run) || !("ymin" in run) || !("ymax" in run)){
+								dojo.forEach(run.data, function(val, i){
+									if(val !== null){
+										var x = "x" in val ? val.x : i + 1, y = val.y;
+										if(isNaN(x)){ x = 0; }
+										if(isNaN(y)){ y = 0; }
+										stats.hmin = Math.min(stats.hmin, x);
+										stats.hmax = Math.max(stats.hmax, x);
+										stats.vmin = Math.min(stats.vmin, y);
+										stats.vmax = Math.max(stats.vmax, y);
+									}
+								});
+							}
+							if("xmin" in run){ stats.hmin = Math.min(old_hmin, run.xmin); }
+							if("xmax" in run){ stats.hmax = Math.max(old_hmax, run.xmax); }
+							if("ymin" in run){ stats.vmin = Math.min(old_vmin, run.ymin); }
+							if("ymax" in run){ stats.vmax = Math.max(old_vmax, run.ymax); }
+						}
+
+						break;
+					}
+				}
+			}
+			return stats;
+		},
+
+		calculateBarSize: function(/* Number */ availableSize, /* Object */ opt, /* Number? */ clusterSize){
+			if(!clusterSize){
+				clusterSize = 1;
+			}
+			var gap = opt.gap, size = (availableSize - 2 * gap) / clusterSize;
+			if("minBarSize" in opt){
+				size = Math.max(size, opt.minBarSize);
+			}
+			if("maxBarSize" in opt){
+				size = Math.min(size, opt.maxBarSize);
+			}
+			size = Math.max(size, 1);
+			gap = (availableSize - size * clusterSize) / 2;
+			return {size: size, gap: gap};	// Object
+		},
+
+		collectStackedStats: function(series){
+			// collect statistics
+			var stats = dojo.clone(dc.defaultStats);
+			if(series.length){
+				// 1st pass: find the maximal length of runs
+				stats.hmin = Math.min(stats.hmin, 1);
+				stats.hmax = df.foldl(series, "seed, run -> Math.max(seed, run.data.length)", stats.hmax);
+				// 2nd pass: stack values
+				for(var i = 0; i < stats.hmax; ++i){
+					var v = series[0].data[i];
+					if(isNaN(v)){ v = 0; }
+					stats.vmin = Math.min(stats.vmin, v);
+					for(var j = 1; j < series.length; ++j){
+						var t = series[j].data[i];
+						if(isNaN(t)){ t = 0; }
+						v += t;
+					}
+					stats.vmax = Math.max(stats.vmax, v);
+				}
+			}
+			return stats;
+		},
+
+		curve: function(/* Number[] */a, /* Number|String */tension){
+			//	FIX for #7235, submitted by Enzo Michelangeli.
+			//	Emulates the smoothing algorithms used in a famous, unnamed spreadsheet
+			//		program ;)
+			var arr = a.slice(0);
+			if(tension == "x") {
+				arr[arr.length] = arr[0];   // add a last element equal to the first, closing the loop
+			}
+			var p=dojo.map(arr, function(item, i){
+				if(i==0){ return "M" + item.x + "," + item.y; }
+				if(!isNaN(tension)) { // use standard Dojo smoothing in tension is numeric
+					var dx=item.x-arr[i-1].x, dy=arr[i-1].y;
+					return "C"+(item.x-(tension-1)*(dx/tension))+","+dy+" "+(item.x-(dx/tension))+","+item.y+" "+item.x+","+item.y;
+				} else if(tension == "X" || tension == "x" || tension == "S") {
+					// use Excel "line smoothing" algorithm (http://xlrotor.com/resources/files.shtml)
+					var p0, p1 = arr[i-1], p2 = arr[i], p3;
+					var bz1x, bz1y, bz2x, bz2y;
+					var f = 1/6;
+					if(i==1) {
+						if(tension == "x") {
+							p0 = arr[arr.length-2];
+						} else { // "tension == X || tension == "S"
+							p0 = p1;
+						}
+						f = 1/3;
+					} else {
+						p0 = arr[i-2];
+					}
+					if(i==(arr.length-1)) {
+						if(tension == "x") {
+							p3 = arr[1];
+						} else { // "tension == X || tension == "S"
+							p3 = p2;
+						}
+						f = 1/3;
+					} else {
+						p3 = arr[i+1];
+					}
+					var p1p2 = Math.sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
+					var p0p2 = Math.sqrt((p2.x-p0.x)*(p2.x-p0.x)+(p2.y-p0.y)*(p2.y-p0.y));
+					var p1p3 = Math.sqrt((p3.x-p1.x)*(p3.x-p1.x)+(p3.y-p1.y)*(p3.y-p1.y));
+
+					var p0p2f = p0p2 * f;
+					var p1p3f = p1p3 * f;
+
+					if(p0p2f > p1p2/2 && p1p3f > p1p2/2) {
+						p0p2f = p1p2/2;
+						p1p3f = p1p2/2;
+					} else if(p0p2f > p1p2/2) {
+						p0p2f = p1p2/2;
+						p1p3f = p1p2/2 * p1p3/p0p2;
+					} else if(p1p3f > p1p2/2) {
+						p1p3f = p1p2/2;
+						p0p2f = p1p2/2 * p0p2/p1p3;
+					}
+
+					if(tension == "S") {
+						if(p0 == p1) { p0p2f = 0; }
+						if(p2 == p3) { p1p3f = 0; }
+					}
+
+					bz1x = p1.x + p0p2f*(p2.x - p0.x)/p0p2;
+					bz1y = p1.y + p0p2f*(p2.y - p0.y)/p0p2;
+					bz2x = p2.x - p1p3f*(p3.x - p1.x)/p1p3;
+					bz2y = p2.y - p1p3f*(p3.y - p1.y)/p1p3;
+				}
+				return "C"+(bz1x+","+bz1y+" "+bz2x+","+bz2y+" "+p2.x+","+p2.y);
+			});
+			return p.join(" ");
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot3d/Bars.js b/dojox/charting/plot3d/Bars.js
index 73dc48e..efec9ea 100644
--- a/dojox/charting/plot3d/Bars.js
+++ b/dojox/charting/plot3d/Bars.js
@@ -1,64 +1,62 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot3d.Bars"]){
-dojo._hasResource["dojox.charting.plot3d.Bars"]=true;
 dojo.provide("dojox.charting.plot3d.Bars");
+
 dojo.require("dojox.charting.plot3d.Base");
+
 (function(){
-var _1=function(a,f,o){
-a=typeof a=="string"?a.split(""):a;
-o=o||dojo.global;
-var z=a[0];
-for(var i=1;i<a.length;z=f.call(o,z,a[i++])){
-}
-return z;
-};
-dojo.declare("dojox.charting.plot3d.Bars",dojox.charting.plot3d.Base,{constructor:function(_2,_3,_4){
-this.depth="auto";
-this.gap=0;
-this.data=[];
-this.material={type:"plastic",finish:"dull",color:"lime"};
-if(_4){
-if("depth" in _4){
-this.depth=_4.depth;
-}
-if("gap" in _4){
-this.gap=_4.gap;
-}
-if("material" in _4){
-var m=_4.material;
-if(typeof m=="string"||m instanceof dojo.Color){
-this.material.color=m;
-}else{
-this.material=m;
-}
-}
-}
-},getDepth:function(){
-if(this.depth=="auto"){
-var w=this.width;
-if(this.data&&this.data.length){
-w=w/this.data.length;
-}
-return w-2*this.gap;
-}
-return this.depth;
-},generate:function(_5,_6){
-if(!this.data){
-return this;
-}
-var _7=this.width/this.data.length,_8=0,_9=this.depth=="auto"?_7-2*this.gap:this.depth,_a=this.height/_1(this.data,Math.max);
-if(!_6){
-_6=_5.view;
-}
-for(var i=0;i<this.data.length;++i,_8+=_7){
-_6.createCube({bottom:{x:_8+this.gap,y:0,z:0},top:{x:_8+_7-this.gap,y:this.data[i]*_a,z:_9}}).setFill(this.material);
-}
-}});
+
+	// reduce function borrowed from dojox.fun
+	var reduce = function(/*Array*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+		// summary: repeatedly applies a binary function to an array from left 
+		//	to right; returns the final value.
+		a = typeof a == "string" ? a.split("") : a; o = o || dojo.global;
+		var z = a[0];
+		for(var i = 1; i < a.length; z = f.call(o, z, a[i++]));
+		return z;	// Object
+	};
+
+	dojo.declare("dojox.charting.plot3d.Bars", dojox.charting.plot3d.Base, {
+		constructor: function(width, height, kwArgs){
+			this.depth = "auto";
+			this.gap   = 0;
+			this.data  = [];
+			this.material = {type: "plastic", finish: "dull", color: "lime"};
+			if(kwArgs){
+				if("depth" in kwArgs){ this.depth = kwArgs.depth; }
+				if("gap"   in kwArgs){ this.gap   = kwArgs.gap; }
+				if("material" in kwArgs){
+					var m = kwArgs.material;
+					if(typeof m == "string" || m instanceof dojo.Color){
+						this.material.color = m;
+					}else{
+						this.material = m;
+					}
+				}
+			}
+		},
+		getDepth: function(){
+			if(this.depth == "auto"){
+				var w = this.width;
+				if(this.data && this.data.length){
+					w = w / this.data.length;
+				}
+				return w - 2 * this.gap;
+			}
+			return this.depth;
+		},
+		generate: function(chart, creator){
+			if(!this.data){ return this; }
+			var step = this.width / this.data.length, org = 0,
+				depth = this.depth == "auto" ? step - 2 * this.gap : this.depth,
+				scale = this.height / reduce(this.data, Math.max);
+			if(!creator){ creator = chart.view; }
+			for(var i = 0; i < this.data.length; ++i, org += step){
+				creator
+					.createCube({
+						bottom: {x: org + this.gap, y: 0, z: 0}, 
+						top:    {x: org + step - this.gap, y: this.data[i] * scale, z: depth}
+					})
+					.setFill(this.material);
+			}
+		}
+	});
 })();
-}
diff --git a/dojox/charting/plot3d/Base.js b/dojox/charting/plot3d/Base.js
index 452e0b0..28b2b79 100644
--- a/dojox/charting/plot3d/Base.js
+++ b/dojox/charting/plot3d/Base.js
@@ -1,22 +1,20 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot3d.Base"]){
-dojo._hasResource["dojox.charting.plot3d.Base"]=true;
 dojo.provide("dojox.charting.plot3d.Base");
+
 dojo.require("dojox.charting.Chart3D");
-dojo.declare("dojox.charting.plot3d.Base",null,{constructor:function(_1,_2,_3){
-this.width=_1;
-this.height=_2;
-},setData:function(_4){
-this.data=_4?_4:[];
-return this;
-},getDepth:function(){
-return this.depth;
-},generate:function(_5,_6){
-}});
-}
+
+dojo.declare("dojox.charting.plot3d.Base", null, {
+	constructor: function(width, height, kwArgs){
+		this.width  = width;
+		this.height = height;
+	},
+	setData: function(data){
+		this.data = data ? data : [];
+		return this;
+	},
+	getDepth: function(){
+		return this.depth;
+	},
+	generate: function(chart, creator){
+	}
+});
+
diff --git a/dojox/charting/plot3d/Cylinders.js b/dojox/charting/plot3d/Cylinders.js
index ed528a1..4464abe 100644
--- a/dojox/charting/plot3d/Cylinders.js
+++ b/dojox/charting/plot3d/Cylinders.js
@@ -1,68 +1,66 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.plot3d.Cylinders"]){
-dojo._hasResource["dojox.charting.plot3d.Cylinders"]=true;
 dojo.provide("dojox.charting.plot3d.Cylinders");
+
 dojo.require("dojox.charting.plot3d.Base");
+
 (function(){
-var _1=function(a,f,o){
-a=typeof a=="string"?a.split(""):a;
-o=o||dojo.global;
-var z=a[0];
-for(var i=1;i<a.length;z=f.call(o,z,a[i++])){
-}
-return z;
-};
-dojo.declare("dojox.charting.plot3d.Cylinders",dojox.charting.plot3d.Base,{constructor:function(_2,_3,_4){
-this.depth="auto";
-this.gap=0;
-this.data=[];
-this.material={type:"plastic",finish:"shiny",color:"lime"};
-this.outline=null;
-if(_4){
-if("depth" in _4){
-this.depth=_4.depth;
-}
-if("gap" in _4){
-this.gap=_4.gap;
-}
-if("material" in _4){
-var m=_4.material;
-if(typeof m=="string"||m instanceof dojo.Color){
-this.material.color=m;
-}else{
-this.material=m;
-}
-}
-if("outline" in _4){
-this.outline=_4.outline;
-}
-}
-},getDepth:function(){
-if(this.depth=="auto"){
-var w=this.width;
-if(this.data&&this.data.length){
-w=w/this.data.length;
-}
-return w-2*this.gap;
-}
-return this.depth;
-},generate:function(_5,_6){
-if(!this.data){
-return this;
-}
-var _7=this.width/this.data.length,_8=0,_9=this.height/_1(this.data,Math.max);
-if(!_6){
-_6=_5.view;
-}
-for(var i=0;i<this.data.length;++i,_8+=_7){
-_6.createCylinder({center:{x:_8+_7/2,y:0,z:0},radius:_7/2-this.gap,height:this.data[i]*_9}).setTransform(dojox.gfx3d.matrix.rotateXg(-90)).setFill(this.material).setStroke(this.outline);
-}
-}});
+
+	// reduce function borrowed from dojox.fun
+	var reduce = function(/*Array*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+		// summary: repeatedly applies a binary function to an array from left 
+		//	to right; returns the final value.
+		a = typeof a == "string" ? a.split("") : a; o = o || dojo.global;
+		var z = a[0];
+		for(var i = 1; i < a.length; z = f.call(o, z, a[i++]));
+		return z;	// Object
+	};
+
+	dojo.declare("dojox.charting.plot3d.Cylinders", dojox.charting.plot3d.Base, {
+		constructor: function(width, height, kwArgs){
+			this.depth = "auto";
+			this.gap   = 0;
+			this.data  = [];
+			this.material = {type: "plastic", finish: "shiny", color: "lime"};
+			this.outline  = null;
+			if(kwArgs){
+				if("depth" in kwArgs){ this.depth = kwArgs.depth; }
+				if("gap"   in kwArgs){ this.gap   = kwArgs.gap; }
+				if("material" in kwArgs){
+					var m = kwArgs.material;
+					if(typeof m == "string" || m instanceof dojo.Color){
+						this.material.color = m;
+					}else{
+						this.material = m;
+					}
+				}
+				if("outline" in kwArgs){ this.outline = kwArgs.outline; }
+			}
+		},
+		getDepth: function(){
+			if(this.depth == "auto"){
+				var w = this.width;
+				if(this.data && this.data.length){
+					w = w / this.data.length;
+				}
+				return w - 2 * this.gap;
+			}
+			return this.depth;
+		},
+		generate: function(chart, creator){
+			if(!this.data){ return this; }
+			var step = this.width / this.data.length, org = 0,
+				scale = this.height / reduce(this.data, Math.max);
+			if(!creator){ creator = chart.view; }
+			for(var i = 0; i < this.data.length; ++i, org += step){
+				creator
+					.createCylinder({
+						center: {x: org + step / 2, y: 0, z: 0}, 
+						radius: step / 2 - this.gap, 
+						height: this.data[i] * scale
+					})
+					.setTransform(dojox.gfx3d.matrix.rotateXg(-90))
+					.setFill(this.material).setStroke(this.outline);
+			}
+		}
+	});
 })();
-}
+
diff --git a/dojox/charting/scaler/common.js b/dojox/charting/scaler/common.js
index 47cfa05..45c46ad 100644
--- a/dojox/charting/scaler/common.js
+++ b/dojox/charting/scaler/common.js
@@ -1,56 +1,54 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.scaler.common"]){
-dojo._hasResource["dojox.charting.scaler.common"]=true;
 dojo.provide("dojox.charting.scaler.common");
+
 (function(){
-var eq=function(a,b){
-return Math.abs(a-b)<=0.000001*(Math.abs(a)+Math.abs(b));
-};
-dojo.mixin(dojox.charting.scaler.common,{findString:function(_1,_2){
-_1=_1.toLowerCase();
-for(var i=0;i<_2.length;++i){
-if(_1==_2[i]){
-return true;
-}
-}
-return false;
-},getNumericLabel:function(_3,_4,_5){
-var _6=_5.fixed?_3.toFixed(_4<0?-_4:0):_3.toString();
-if(_5.labelFunc){
-var r=_5.labelFunc(_6,_3,_4);
-if(r){
-return r;
-}
-}
-if(_5.labels){
-var l=_5.labels,lo=0,hi=l.length;
-while(lo<hi){
-var _7=Math.floor((lo+hi)/2),_8=l[_7].value;
-if(_8<_3){
-lo=_7+1;
-}else{
-hi=_7;
-}
-}
-if(lo<l.length&&eq(l[lo].value,_3)){
-return l[lo].text;
-}
---lo;
-if(lo>=0&&lo<l.length&&eq(l[lo].value,_3)){
-return l[lo].text;
-}
-lo+=2;
-if(lo<l.length&&eq(l[lo].value,_3)){
-return l[lo].text;
-}
-}
-return _6;
-}});
+	var eq = function(/*Number*/ a, /*Number*/ b){
+		// summary: compare two FP numbers for equality
+		return Math.abs(a - b) <= 1e-6 * (Math.abs(a) + Math.abs(b));	// Boolean
+	};
+	
+	dojo.mixin(dojox.charting.scaler.common, {
+		findString: function(/*String*/ val, /*Array*/ text){
+			val = val.toLowerCase();
+			for(var i = 0; i < text.length; ++i){
+				if(val == text[i]){ return true; }
+			}
+			return false;
+		},
+		getNumericLabel: function(/*Number*/ number, /*Number*/ precision, /*Object*/ kwArgs){
+			var def = kwArgs.fixed ? 
+						number.toFixed(precision < 0 ? -precision : 0) : 
+						number.toString();
+			if(kwArgs.labelFunc){
+				var r = kwArgs.labelFunc(def, number, precision);
+				if(r){ return r; }
+				// else fall through to the regular labels search
+			}
+			if(kwArgs.labels){
+				// classic binary search
+				var l = kwArgs.labels, lo = 0, hi = l.length;
+				while(lo < hi){
+					var mid = Math.floor((lo + hi) / 2), val = l[mid].value;
+					if(val < number){
+						lo = mid + 1;
+					}else{
+						hi = mid;
+					}
+				}
+				// lets take into account FP errors
+				if(lo < l.length && eq(l[lo].value, number)){
+					return l[lo].text;
+				}
+				--lo;
+				if(lo >= 0 && lo < l.length && eq(l[lo].value, number)){
+					return l[lo].text;
+				}
+				lo += 2;
+				if(lo < l.length && eq(l[lo].value, number)){
+					return l[lo].text;
+				}
+				// otherwise we will produce a number
+			}
+			return def;
+		}
+	});
 })();
-}
diff --git a/dojox/charting/scaler/linear.js b/dojox/charting/scaler/linear.js
index a2edac9..be0408a 100644
--- a/dojox/charting/scaler/linear.js
+++ b/dojox/charting/scaler/linear.js
@@ -1,217 +1,251 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.scaler.linear"]){
-dojo._hasResource["dojox.charting.scaler.linear"]=true;
 dojo.provide("dojox.charting.scaler.linear");
 dojo.require("dojox.charting.scaler.common");
+
 (function(){
-var _1=3,dc=dojox.charting,_2=dc.scaler,_3=_2.common,_4=_3.findString,_5=_3.getNumericLabel;
-var _6=function(_7,_8,_9,_a,_b,_c,_d){
-_9=dojo.delegate(_9);
-if(!_a){
-if(_9.fixUpper=="major"){
-_9.fixUpper="minor";
-}
-if(_9.fixLower=="major"){
-_9.fixLower="minor";
-}
-}
-if(!_b){
-if(_9.fixUpper=="minor"){
-_9.fixUpper="micro";
-}
-if(_9.fixLower=="minor"){
-_9.fixLower="micro";
-}
-}
-if(!_c){
-if(_9.fixUpper=="micro"){
-_9.fixUpper="none";
-}
-if(_9.fixLower=="micro"){
-_9.fixLower="none";
-}
-}
-var _e=_4(_9.fixLower,["major"])?Math.floor(_9.min/_a)*_a:_4(_9.fixLower,["minor"])?Math.floor(_9.min/_b)*_b:_4(_9.fixLower,["micro"])?Math.floor(_9.min/_c)*_c:_9.min,_f=_4(_9.fixUpper,["major"])?Math.ceil(_9.max/_a)*_a:_4(_9.fixUpper,["minor"])?Math.ceil(_9.max/_b)*_b:_4(_9.fixUpper,["micro"])?Math.ceil(_9.max/_c)*_c:_9.max;
-if(_9.useMin){
-_7=_e;
-}
-if(_9.useMax){
-_8=_f;
-}
-var _10=(!_a||_9.useMin&&_4(_9.fixLower,["major"]))?_7:Math.ceil(_7/_a)*_a,_11=(!_b||_9.useMin&&_4(_9.fixLower,["major","minor"]))?_7:Math.ceil(_7/_b)*_b,_12=(!_c||_9.useMin&&_4(_9.fixLower,["major","minor","micro"]))?_7:Math.ceil(_7/_c)*_c,_13=!_a?0:(_9.useMax&&_4(_9.fixUpper,["major"])?Math.round((_8-_10)/_a):Math.floor((_8-_10)/_a))+1,_14=!_b?0:(_9.useMax&&_4(_9.fixUpper,["major","minor"])?Math.round((_8-_11)/_b):Math.floor((_8-_11)/_b))+1,_15=!_c?0:(_9.useMax&&_4(_9.fixUpper,["major" [...]
-if(!isFinite(_1a)){
-_1a=1;
-}
-return {bounds:{lower:_e,upper:_f,from:_7,to:_8,scale:_1a,span:_d},major:{tick:_a,start:_10,count:_13,prec:_18},minor:{tick:_b,start:_11,count:_14,prec:_19},micro:{tick:_c,start:_12,count:_15,prec:0},minorPerMajor:_16,microPerMinor:_17,scaler:_2.linear};
-};
-dojo.mixin(dojox.charting.scaler.linear,{buildScaler:function(min,max,_1b,_1c){
-var h={fixUpper:"none",fixLower:"none",natural:false};
-if(_1c){
-if("fixUpper" in _1c){
-h.fixUpper=String(_1c.fixUpper);
-}
-if("fixLower" in _1c){
-h.fixLower=String(_1c.fixLower);
-}
-if("natural" in _1c){
-h.natural=Boolean(_1c.natural);
-}
-}
-if("min" in _1c){
-min=_1c.min;
-}
-if("max" in _1c){
-max=_1c.max;
-}
-if(_1c.includeZero){
-if(min>0){
-min=0;
-}
-if(max<0){
-max=0;
-}
-}
-h.min=min;
-h.useMin=true;
-h.max=max;
-h.useMax=true;
-if("from" in _1c){
-min=_1c.from;
-h.useMin=false;
-}
-if("to" in _1c){
-max=_1c.to;
-h.useMax=false;
-}
-if(max<=min){
-return _6(min,max,h,0,0,0,_1b);
-}
-var mag=Math.floor(Math.log(max-min)/Math.LN10),_1d=_1c&&("majorTickStep" in _1c)?_1c.majorTickStep:Math.pow(10,mag),_1e=0,_1f=0,_20;
-if(_1c&&("minorTickStep" in _1c)){
-_1e=_1c.minorTickStep;
-}else{
-do{
-_1e=_1d/10;
-if(!h.natural||_1e>0.9){
-_20=_6(min,max,h,_1d,_1e,0,_1b);
-if(_20.bounds.scale*_20.minor.tick>_1){
-break;
-}
-}
-_1e=_1d/5;
-if(!h.natural||_1e>0.9){
-_20=_6(min,max,h,_1d,_1e,0,_1b);
-if(_20.bounds.scale*_20.minor.tick>_1){
-break;
-}
-}
-_1e=_1d/2;
-if(!h.natural||_1e>0.9){
-_20=_6(min,max,h,_1d,_1e,0,_1b);
-if(_20.bounds.scale*_20.minor.tick>_1){
-break;
-}
-}
-return _6(min,max,h,_1d,0,0,_1b);
-}while(false);
-}
-if(_1c&&("microTickStep" in _1c)){
-_1f=_1c.microTickStep;
-_20=_6(min,max,h,_1d,_1e,_1f,_1b);
-}else{
-do{
-_1f=_1e/10;
-if(!h.natural||_1f>0.9){
-_20=_6(min,max,h,_1d,_1e,_1f,_1b);
-if(_20.bounds.scale*_20.micro.tick>_1){
-break;
-}
-}
-_1f=_1e/5;
-if(!h.natural||_1f>0.9){
-_20=_6(min,max,h,_1d,_1e,_1f,_1b);
-if(_20.bounds.scale*_20.micro.tick>_1){
-break;
-}
-}
-_1f=_1e/2;
-if(!h.natural||_1f>0.9){
-_20=_6(min,max,h,_1d,_1e,_1f,_1b);
-if(_20.bounds.scale*_20.micro.tick>_1){
-break;
-}
-}
-_1f=0;
-}while(false);
-}
-return _1f?_20:_6(min,max,h,_1d,_1e,0,_1b);
-},buildTicks:function(_21,_22){
-var _23,_24,_25,_26=_21.major.start,_27=_21.minor.start,_28=_21.micro.start;
-if(_22.microTicks&&_21.micro.tick){
-_23=_21.micro.tick,_24=_28;
-}else{
-if(_22.minorTicks&&_21.minor.tick){
-_23=_21.minor.tick,_24=_27;
-}else{
-if(_21.major.tick){
-_23=_21.major.tick,_24=_26;
-}else{
-return null;
-}
-}
-}
-var _29=1/_21.bounds.scale;
-if(_21.bounds.to<=_21.bounds.from||isNaN(_29)||!isFinite(_29)||_23<=0||isNaN(_23)||!isFinite(_23)){
-return null;
-}
-var _2a=[],_2b=[],_2c=[];
-while(_24<=_21.bounds.to+_29){
-if(Math.abs(_26-_24)<_23/2){
-_25={value:_26};
-if(_22.majorLabels){
-_25.label=_5(_26,_21.major.prec,_22);
-}
-_2a.push(_25);
-_26+=_21.major.tick;
-_27+=_21.minor.tick;
-_28+=_21.micro.tick;
-}else{
-if(Math.abs(_27-_24)<_23/2){
-if(_22.minorTicks){
-_25={value:_27};
-if(_22.minorLabels&&(_21.minMinorStep<=_21.minor.tick*_21.bounds.scale)){
-_25.label=_5(_27,_21.minor.prec,_22);
-}
-_2b.push(_25);
-}
-_27+=_21.minor.tick;
-_28+=_21.micro.tick;
-}else{
-if(_22.microTicks){
-_2c.push({value:_28});
-}
-_28+=_21.micro.tick;
-}
-}
-_24+=_23;
-}
-return {major:_2a,minor:_2b,micro:_2c};
-},getTransformerFromModel:function(_2d){
-var _2e=_2d.bounds.from,_2f=_2d.bounds.scale;
-return function(x){
-return (x-_2e)*_2f;
-};
-},getTransformerFromPlot:function(_30){
-var _31=_30.bounds.from,_32=_30.bounds.scale;
-return function(x){
-return x/_32+_31;
-};
-}});
+	var deltaLimit = 3,	// pixels
+		dc = dojox.charting, dcs = dc.scaler, dcsc = dcs.common,
+		findString = dcsc.findString,
+		getLabel = dcsc.getNumericLabel;
+	
+	var calcTicks = function(min, max, kwArgs, majorTick, minorTick, microTick, span){
+		kwArgs = dojo.delegate(kwArgs);
+		if(!majorTick){
+			if(kwArgs.fixUpper == "major"){ kwArgs.fixUpper = "minor"; }
+			if(kwArgs.fixLower == "major"){ kwArgs.fixLower = "minor"; }
+		}
+		if(!minorTick){
+			if(kwArgs.fixUpper == "minor"){ kwArgs.fixUpper = "micro"; }
+			if(kwArgs.fixLower == "minor"){ kwArgs.fixLower = "micro"; }
+		}
+		if(!microTick){
+			if(kwArgs.fixUpper == "micro"){ kwArgs.fixUpper = "none"; }
+			if(kwArgs.fixLower == "micro"){ kwArgs.fixLower = "none"; }
+		}
+		var lowerBound = findString(kwArgs.fixLower, ["major"]) ?
+				Math.floor(kwArgs.min / majorTick) * majorTick :
+					findString(kwArgs.fixLower, ["minor"]) ?
+						Math.floor(kwArgs.min / minorTick) * minorTick :
+							findString(kwArgs.fixLower, ["micro"]) ?
+								Math.floor(kwArgs.min / microTick) * microTick : kwArgs.min,
+			upperBound = findString(kwArgs.fixUpper, ["major"]) ?
+				Math.ceil(kwArgs.max / majorTick) * majorTick :
+					findString(kwArgs.fixUpper, ["minor"]) ?
+						Math.ceil(kwArgs.max / minorTick) * minorTick :
+							findString(kwArgs.fixUpper, ["micro"]) ?
+								Math.ceil(kwArgs.max / microTick) * microTick : kwArgs.max;
+								
+		if(kwArgs.useMin){ min = lowerBound; }
+		if(kwArgs.useMax){ max = upperBound; }
+		
+		var majorStart = (!majorTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major"])) ?
+				min : Math.ceil(min / majorTick) * majorTick,
+			minorStart = (!minorTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major", "minor"])) ?
+				min : Math.ceil(min / minorTick) * minorTick,
+			microStart = (! microTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major", "minor", "micro"])) ?
+				min : Math.ceil(min / microTick) * microTick,
+			majorCount = !majorTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major"]) ?
+				Math.round((max - majorStart) / majorTick) :
+				Math.floor((max - majorStart) / majorTick)) + 1,
+			minorCount = !minorTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major", "minor"]) ?
+				Math.round((max - minorStart) / minorTick) :
+				Math.floor((max - minorStart) / minorTick)) + 1,
+			microCount = !microTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major", "minor", "micro"]) ?
+				Math.round((max - microStart) / microTick) :
+				Math.floor((max - microStart) / microTick)) + 1,
+			minorPerMajor  = minorTick ? Math.round(majorTick / minorTick) : 0,
+			microPerMinor  = microTick ? Math.round(minorTick / microTick) : 0,
+			majorPrecision = majorTick ? Math.floor(Math.log(majorTick) / Math.LN10) : 0,
+			minorPrecision = minorTick ? Math.floor(Math.log(minorTick) / Math.LN10) : 0,
+			scale = span / (max - min);	
+		if(!isFinite(scale)){ scale = 1; }
+		
+		return {
+			bounds: {
+				lower:	lowerBound,
+				upper:	upperBound,
+				from:	min,
+				to:		max,
+				scale:	scale,
+				span:	span
+			},
+			major: {
+				tick:	majorTick,
+				start:	majorStart,
+				count:	majorCount,
+				prec:	majorPrecision
+			},
+			minor: {
+				tick:	minorTick,
+				start:	minorStart,
+				count:	minorCount,
+				prec:	minorPrecision
+			},
+			micro: {
+				tick:	microTick,
+				start:	microStart,
+				count:	microCount,
+				prec:	0
+			},
+			minorPerMajor:	minorPerMajor,
+			microPerMinor:	microPerMinor,
+			scaler:			dcs.linear
+		};
+	};
+	
+	dojo.mixin(dojox.charting.scaler.linear, {
+		buildScaler: function(/*Number*/ min, /*Number*/ max, /*Number*/ span, /*Object*/ kwArgs){
+			var h = {fixUpper: "none", fixLower: "none", natural: false};
+			if(kwArgs){
+				if("fixUpper" in kwArgs){ h.fixUpper = String(kwArgs.fixUpper); }
+				if("fixLower" in kwArgs){ h.fixLower = String(kwArgs.fixLower); }
+				if("natural"  in kwArgs){ h.natural  = Boolean(kwArgs.natural); }
+			}
+			
+			// update bounds
+			if("min" in kwArgs){ min = kwArgs.min; }
+			if("max" in kwArgs){ max = kwArgs.max; }
+			if(kwArgs.includeZero){
+				if(min > 0){ min = 0; }
+				if(max < 0){ max = 0; }
+			}
+			h.min = min;
+			h.useMin = true;
+			h.max = max;
+			h.useMax = true;
+			
+			if("from" in kwArgs){
+				min = kwArgs.from;
+				h.useMin = false;
+			}
+			if("to" in kwArgs){
+				max = kwArgs.to;
+				h.useMax = false;
+			}
+			
+			// check for erroneous condition
+			if(max <= min){
+				return calcTicks(min, max, h, 0, 0, 0, span);	// Object
+			}
+			
+			var mag = Math.floor(Math.log(max - min) / Math.LN10),
+				major = kwArgs && ("majorTickStep" in kwArgs) ? kwArgs.majorTickStep : Math.pow(10, mag), 
+				minor = 0, micro = 0, ticks;
+				
+			// calculate minor ticks
+			if(kwArgs && ("minorTickStep" in kwArgs)){
+				minor = kwArgs.minorTickStep;
+			}else{
+				do{
+					minor = major / 10;
+					if(!h.natural || minor > 0.9){
+						ticks = calcTicks(min, max, h, major, minor, 0, span);
+						if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
+					}
+					minor = major / 5;
+					if(!h.natural || minor > 0.9){
+						ticks = calcTicks(min, max, h, major, minor, 0, span);
+						if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
+					}
+					minor = major / 2;
+					if(!h.natural || minor > 0.9){
+						ticks = calcTicks(min, max, h, major, minor, 0, span);
+						if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
+					}
+					return calcTicks(min, max, h, major, 0, 0, span);	// Object
+				}while(false);
+			}
+	
+			// calculate micro ticks
+			if(kwArgs && ("microTickStep" in kwArgs)){
+				micro = kwArgs.microTickStep;
+				ticks = calcTicks(min, max, h, major, minor, micro, span);
+			}else{
+				do{
+					micro = minor / 10;
+					if(!h.natural || micro > 0.9){
+						ticks = calcTicks(min, max, h, major, minor, micro, span);
+						if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
+					}
+					micro = minor / 5;
+					if(!h.natural || micro > 0.9){
+						ticks = calcTicks(min, max, h, major, minor, micro, span);
+						if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
+					}
+					micro = minor / 2;
+					if(!h.natural || micro > 0.9){
+						ticks = calcTicks(min, max, h, major, minor, micro, span);
+						if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
+					}
+					micro = 0;
+				}while(false);
+			}
+	
+			return micro ? ticks : calcTicks(min, max, h, major, minor, 0, span);	// Object
+		},
+		buildTicks: function(/*Object*/ scaler, /*Object*/ kwArgs){
+			var step, next, tick,
+				nextMajor = scaler.major.start, 
+				nextMinor = scaler.minor.start, 
+				nextMicro = scaler.micro.start;
+			if(kwArgs.microTicks && scaler.micro.tick){
+				step = scaler.micro.tick, next = nextMicro;
+			}else if(kwArgs.minorTicks && scaler.minor.tick){
+				step = scaler.minor.tick, next = nextMinor;
+			}else if(scaler.major.tick){
+				step = scaler.major.tick, next = nextMajor;
+			}else{
+				// no ticks
+				return null;
+			}
+			// make sure that we have finite bounds
+			var revScale = 1 / scaler.bounds.scale;
+			if(scaler.bounds.to <= scaler.bounds.from || isNaN(revScale) || !isFinite(revScale) ||
+					step <= 0 || isNaN(step) || !isFinite(step)){
+				// no ticks
+				return null;
+			}
+			// loop over all ticks
+			var majorTicks = [], minorTicks = [], microTicks = [];
+			while(next <= scaler.bounds.to + revScale){
+				if(Math.abs(nextMajor - next) < step / 2){
+					// major tick
+					tick = {value: nextMajor};
+					if(kwArgs.majorLabels){
+						tick.label = getLabel(nextMajor, scaler.major.prec, kwArgs);
+					}
+					majorTicks.push(tick);
+					nextMajor += scaler.major.tick;
+					nextMinor += scaler.minor.tick;
+					nextMicro += scaler.micro.tick;
+				}else if(Math.abs(nextMinor - next) < step / 2){
+					// minor tick
+					if(kwArgs.minorTicks){
+						tick = {value: nextMinor};
+						if(kwArgs.minorLabels && (scaler.minMinorStep <= scaler.minor.tick * scaler.bounds.scale)){
+							tick.label = getLabel(nextMinor, scaler.minor.prec, kwArgs);
+						}
+						minorTicks.push(tick);
+					}
+					nextMinor += scaler.minor.tick;
+					nextMicro += scaler.micro.tick;
+				}else{
+					// micro tick
+					if(kwArgs.microTicks){
+						microTicks.push({value: nextMicro});
+					}
+					nextMicro += scaler.micro.tick;
+				}
+				next += step;
+			}
+			return {major: majorTicks, minor: minorTicks, micro: microTicks};	// Object
+		},
+		getTransformerFromModel: function(/*Object*/ scaler){
+			var offset = scaler.bounds.from, scale = scaler.bounds.scale;
+			return function(x){ return (x - offset) * scale; };	// Function
+		},
+		getTransformerFromPlot: function(/*Object*/ scaler){
+			var offset = scaler.bounds.from, scale = scaler.bounds.scale;
+			return function(x){ return x / scale + offset; };	// Function
+		}
+	});
 })();
-}
diff --git a/dojox/charting/scaler/primitive.js b/dojox/charting/scaler/primitive.js
index bfea710..4828815 100644
--- a/dojox/charting/scaler/primitive.js
+++ b/dojox/charting/scaler/primitive.js
@@ -1,26 +1,34 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.scaler.primitive"]){
-dojo._hasResource["dojox.charting.scaler.primitive"]=true;
 dojo.provide("dojox.charting.scaler.primitive");
-dojox.charting.scaler.primitive={buildScaler:function(_1,_2,_3,_4){
-return {bounds:{lower:_1,upper:_2,from:_1,to:_2,scale:_3/(_2-_1),span:_3},scaler:dojox.charting.scaler.primitive};
-},buildTicks:function(_5,_6){
-return {major:[],minor:[],micro:[]};
-},getTransformerFromModel:function(_7){
-var _8=_7.bounds.from,_9=_7.bounds.scale;
-return function(x){
-return (x-_8)*_9;
-};
-},getTransformerFromPlot:function(_a){
-var _b=_a.bounds.from,_c=_a.bounds.scale;
-return function(x){
-return x/_c+_b;
+
+dojox.charting.scaler.primitive = {
+	buildScaler: function(/*Number*/ min, /*Number*/ max, /*Number*/ span, /*Object*/ kwArgs){
+		if(min == max){
+			// artificially extend bounds
+			min -= 0.5;
+			max += 0.5;
+			// now the line will be centered
+		}
+		return {
+			bounds: {
+				lower: min,
+				upper: max,
+				from:  min,
+				to:    max,
+				scale: span / (max - min),
+				span:  span
+			},
+			scaler: dojox.charting.scaler.primitive
+		};
+	},
+	buildTicks: function(/*Object*/ scaler, /*Object*/ kwArgs){
+		return {major: [], minor: [], micro: []};	// Object
+	},
+	getTransformerFromModel: function(/*Object*/ scaler){
+		var offset = scaler.bounds.from, scale = scaler.bounds.scale;
+		return function(x){ return (x - offset) * scale; };	// Function
+	},
+	getTransformerFromPlot: function(/*Object*/ scaler){
+		var offset = scaler.bounds.from, scale = scaler.bounds.scale;
+		return function(x){ return x / scale + offset; };	// Function
+	}
 };
-}};
-}
diff --git a/dojox/charting/tests/Theme.js b/dojox/charting/tests/Theme.js
new file mode 100644
index 0000000..65cac10
--- /dev/null
+++ b/dojox/charting/tests/Theme.js
@@ -0,0 +1,67 @@
+dojo.provide("dojox.charting.tests.Theme");
+dojo.require("dojox.charting.Theme");
+dojo.require("dojox.charting.themes.PlotKit.blue");
+
+(function(){
+	var dxc=dojox.charting;
+	var blue=dxc.themes.PlotKit.blue;
+	tests.register("dojox.charting.tests.Theme", [
+		function testDefineColor(t){
+			var args={ num:16, cache:false };
+			blue.defineColors(args);
+			var a=blue.colors;
+			var s="<table border=1>";
+			for(var i=0; i<a.length; i++){
+				if(i%8==0){
+					if(i>0) s+="</tr>";
+					s+="<tr>";
+				}
+				s+='<td width=16 bgcolor='+a[i]+'> </td>';
+			}
+			s+="</tr></table>";
+			doh.debug(s);
+
+			var args={ num:32, cache: false };
+			blue.defineColors(args);
+			var a=blue.colors;
+			var s="<table border=1 style=margin-top:12px;>";
+			for(var i=0; i<a.length; i++){
+				if(i%8==0){
+					if(i>0) s+="</tr>";
+					s+="<tr>";
+				}
+				s+='<td width=16 bgcolor='+a[i]+'> </td>';
+			}
+			s+="</tr></table>";
+			doh.debug(s);
+
+			var args={ saturation:20, num:32, cache:false };
+			blue.defineColors(args);
+			var a=blue.colors;
+			var s="<table border=1 style=margin-top:12px;>";
+			for(var i=0; i<a.length; i++){
+				if(i%8==0){
+					if(i>0) s+="</tr>";
+					s+="<tr>";
+				}
+				s+='<td width=16 bgcolor='+a[i]+'> </td>';
+			}
+			s+="</tr></table>";
+			doh.debug(s);
+
+			var args={ low:10, high:90, num:32, cache: false };
+			blue.defineColors(args);
+			var a=blue.colors;
+			var s="<table border=1 style=margin-top:12px;>";
+			for(var i=0; i<a.length; i++){
+				if(i%8==0){
+					if(i>0) s+="</tr>";
+					s+="<tr>";
+				}
+				s+='<td width=16 bgcolor='+a[i]+'> </td>';
+			}
+			s+="</tr></table>";
+			doh.debug(s);
+		}
+	]);
+})();
diff --git a/dojox/charting/tests/charting.js b/dojox/charting/tests/charting.js
new file mode 100644
index 0000000..f9cff0a
--- /dev/null
+++ b/dojox/charting/tests/charting.js
@@ -0,0 +1,7 @@
+dojo.provide("dojox.charting.tests.charting");
+
+try{
+	dojo.require("dojox.charting.tests.Theme");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/charting/tests/data/goog_prices.csv b/dojox/charting/tests/data/goog_prices.csv
new file mode 100644
index 0000000..901a6d2
--- /dev/null
+++ b/dojox/charting/tests/data/goog_prices.csv
@@ -0,0 +1,796 @@
+Date,Open,High,Low,Close,Volume,Adj Close
+2008-02-29,471.87,479.74,464.65,471.18,9425400,471.18
+2008-02-28,470.50,479.09,467.36,475.39,6586900,475.39
+2008-02-27,460.13,475.49,459.64,472.86,10121900,472.86
+2008-02-26,461.20,466.47,446.85,464.19,23287300,464.19
+2008-02-25,505.95,506.50,485.74,486.44,8350800,486.44
+2008-02-22,502.06,509.00,497.55,507.80,5515900,507.80
+2008-02-21,512.85,513.21,499.50,502.86,5677800,502.86
+2008-02-20,503.51,511.01,498.82,509.00,6662200,509.00
+2008-02-19,534.94,535.06,506.50,508.95,6350400,508.95
+2008-02-15,528.31,532.66,524.33,529.64,5240100,529.64
+2008-02-14,538.35,541.04,531.00,532.25,6476700,532.25
+2008-02-13,522.50,534.99,518.69,534.62,6624700,534.62
+2008-02-12,523.39,530.60,513.03,518.09,6662300,518.09
+2008-02-11,520.52,523.71,513.40,521.16,5826000,521.16
+2008-02-08,509.41,517.73,508.70,516.69,6828900,516.69
+2008-02-07,496.86,514.19,494.76,504.95,7928900,504.95
+2008-02-06,511.14,511.17,497.93,501.71,7636400,501.71
+2008-02-05,489.43,509.00,488.52,506.80,11203300,506.80
+2008-02-04,509.07,512.78,492.55,495.43,13157100,495.43
+2008-02-01,528.67,536.67,510.00,515.90,17600500,515.90
+2008-01-31,539.01,573.00,534.29,564.30,14871300,564.30
+2008-01-30,549.19,560.43,543.51,548.27,7939600,548.27
+2008-01-29,560.47,561.33,540.67,550.52,6283000,550.52
+2008-01-28,570.97,572.24,548.60,555.98,5816700,555.98
+2008-01-25,591.81,595.00,566.18,566.40,6966000,566.40
+2008-01-24,558.80,579.69,554.14,574.49,9400900,574.49
+2008-01-23,560.71,568.00,519.00,548.62,16965700,548.62
+2008-01-22,562.03,597.50,561.20,584.35,9501500,584.35
+2008-01-18,608.36,609.99,598.45,600.25,8539600,600.25
+2008-01-17,620.76,625.74,598.01,600.79,8216800,600.79
+2008-01-16,628.97,639.99,601.93,615.95,10560000,615.95
+2008-01-15,645.90,649.05,635.38,637.65,5568200,637.65
+2008-01-14,651.14,657.40,645.25,653.82,4447500,653.82
+2008-01-11,642.70,649.47,630.11,638.25,4977000,638.25
+2008-01-10,645.01,657.20,640.11,646.73,6334200,646.73
+2008-01-09,630.04,653.34,622.51,653.20,6739700,653.20
+2008-01-08,653.00,659.96,631.00,631.68,5339100,631.68
+2008-01-07,653.94,662.28,637.35,649.25,6403400,649.25
+2008-01-04,679.69,680.96,655.00,657.00,5359800,657.00
+2008-01-03,685.26,686.85,676.52,685.33,3252500,685.33
+2008-01-02,692.87,697.37,677.73,685.19,4306900,685.19
+2007-12-31,698.57,702.49,690.58,691.48,2376200,691.48
+2007-12-28,704.93,707.95,696.54,702.53,2562700,702.53
+2007-12-27,707.07,716.00,700.74,700.74,2942500,700.74
+2007-12-26,698.99,713.22,698.21,710.84,2530000,710.84
+2007-12-24,694.99,700.73,693.06,700.73,1628400,700.73
+2007-12-21,697.88,699.26,693.24,696.69,5382000,696.69
+2007-12-20,685.83,691.00,680.61,689.69,4422200,689.69
+2007-12-19,674.21,679.50,669.00,677.37,4421100,677.37
+2007-12-18,674.16,676.71,652.50,673.35,7166700,673.35
+2007-12-17,688.00,695.42,663.67,669.23,5486000,669.23
+2007-12-14,687.51,699.70,687.26,689.96,3673500,689.96
+2007-12-13,696.31,697.62,681.21,694.05,5040800,694.05
+2007-12-12,714.00,714.32,688.50,699.35,6159100,699.35
+2007-12-11,719.94,720.99,698.78,699.20,6139100,699.20
+2007-12-10,715.99,724.80,714.00,718.42,3856200,718.42
+2007-12-07,714.99,718.00,710.50,714.87,3852100,714.87
+2007-12-06,697.80,716.56,697.01,715.26,4909000,715.26
+2007-12-05,692.73,698.93,687.50,698.51,4209600,698.51
+2007-12-04,678.31,692.00,677.12,684.16,4231800,684.16
+2007-12-03,691.01,695.00,681.14,681.53,4325100,681.53
+2007-11-30,711.00,711.06,682.11,693.00,7895500,693.00
+2007-11-29,690.75,702.79,687.77,697.00,6208000,697.00
+2007-11-28,682.11,694.30,672.14,692.26,7916500,692.26
+2007-11-27,674.80,676.43,650.26,673.57,8904500,673.57
+2007-11-26,680.20,693.40,665.00,666.00,6790100,666.00
+2007-11-23,670.00,678.28,668.11,676.70,2738700,676.70
+2007-11-21,643.77,669.97,642.08,660.52,7013500,660.52
+2007-11-20,636.48,659.10,632.87,648.54,9840600,648.54
+2007-11-19,629.59,636.77,618.50,625.85,5527400,625.85
+2007-11-16,633.94,635.49,616.02,633.63,9042800,633.63
+2007-11-15,638.57,647.50,624.00,629.65,6967700,629.65
+2007-11-14,673.28,675.49,636.27,641.68,8094700,641.68
+2007-11-13,644.99,660.92,632.07,660.55,8426100,660.55
+2007-11-12,657.74,669.93,626.21,632.07,10227300,632.07
+2007-11-09,675.78,681.88,661.21,663.97,11388100,663.97
+2007-11-08,734.60,734.89,677.18,693.84,16512200,693.84
+2007-11-07,741.13,747.24,723.14,732.94,8252900,732.94
+2007-11-06,737.56,741.79,725.00,741.79,8436300,741.79
+2007-11-05,706.99,730.23,706.07,725.65,8883700,725.65
+2007-11-02,710.51,713.58,697.34,711.25,5841500,711.25
+2007-11-01,702.79,713.72,701.78,703.21,6527200,703.21
+2007-10-31,700.69,707.00,696.04,707.00,6876800,707.00
+2007-10-30,677.51,699.91,677.51,694.77,6900600,694.77
+2007-10-29,677.77,680.00,672.09,679.23,3066300,679.23
+2007-10-26,674.03,676.54,668.06,674.60,3353900,674.60
+2007-10-25,678.68,678.97,663.55,668.51,5795500,668.51
+2007-10-24,672.71,677.47,659.56,675.82,7404200,675.82
+2007-10-23,661.25,677.60,660.00,675.77,6793700,675.77
+2007-10-22,638.67,655.00,636.28,650.75,6664400,650.75
+2007-10-19,654.56,658.49,643.23,644.71,15789000,644.71
+2007-10-18,635.41,641.37,628.50,639.62,12289200,639.62
+2007-10-17,630.45,634.00,621.59,633.48,6030500,633.48
+2007-10-16,618.49,625.92,611.99,616.00,6025300,616.00
+2007-10-15,638.47,639.86,615.55,620.11,6943800,620.11
+2007-10-12,623.98,638.40,618.24,637.39,6823700,637.39
+2007-10-11,633.64,641.41,609.00,622.00,11799000,622.00
+2007-10-10,621.36,625.68,616.80,625.39,5385600,625.39
+2007-10-09,615.11,623.78,608.39,615.18,8767800,615.18
+2007-10-08,595.00,610.26,593.95,609.62,5028000,609.62
+2007-10-05,587.11,596.00,587.01,594.05,5068700,594.05
+2007-10-04,585.09,585.09,577.06,579.03,2986700,579.03
+2007-10-03,586.25,588.99,580.36,584.02,3879500,584.02
+2007-10-02,583.38,596.81,580.01,584.39,7067500,584.39
+2007-10-01,569.97,584.35,569.61,582.55,4711300,582.55
+2007-09-28,567.00,569.55,564.12,567.27,2639500,567.27
+2007-09-27,571.73,571.74,565.78,567.50,2056300,567.50
+2007-09-26,570.40,571.79,563.81,568.16,3346100,568.16
+2007-09-25,564.00,569.56,562.86,569.00,2730600,569.00
+2007-09-24,561.00,571.46,560.00,568.02,5297000,568.02
+2007-09-21,556.34,560.79,552.83,560.10,8011700,560.10
+2007-09-20,547.00,556.80,546.03,552.83,5525000,552.83
+2007-09-19,539.27,549.45,538.86,546.85,5526900,546.85
+2007-09-18,526.52,537.25,524.27,535.27,4215700,535.27
+2007-09-17,526.53,529.28,524.07,525.30,2197500,525.30
+2007-09-14,523.20,530.27,522.22,528.75,2764900,528.75
+2007-09-13,524.06,527.21,523.22,524.78,1891100,524.78
+2007-09-12,520.53,527.98,519.00,522.65,2986000,522.65
+2007-09-11,516.99,521.65,515.73,521.33,2703600,521.33
+2007-09-10,521.28,522.07,510.88,514.48,3225800,514.48
+2007-09-07,517.86,521.24,516.80,519.35,3663600,519.35
+2007-09-06,529.36,529.83,518.24,523.52,3625900,523.52
+2007-09-05,523.40,529.48,522.25,527.80,3312900,527.80
+2007-09-04,515.02,528.00,514.62,525.15,3693700,525.15
+2007-08-31,513.10,516.50,511.47,515.25,2977600,515.25
+2007-08-30,512.36,515.40,510.58,511.40,2651700,511.40
+2007-08-29,507.84,513.30,507.23,512.88,2549300,512.88
+2007-08-28,511.53,514.98,505.79,506.40,3273900,506.40
+2007-08-27,514.43,517.45,511.40,513.26,2325100,513.26
+2007-08-24,512.61,515.55,508.50,515.00,2472700,515.00
+2007-08-23,516.00,516.13,507.00,512.19,3076700,512.19
+2007-08-22,509.96,516.25,509.25,512.75,3252700,512.75
+2007-08-21,498.94,508.16,497.77,506.61,3610600,506.61
+2007-08-20,502.46,502.56,496.00,497.92,2697300,497.92
+2007-08-17,497.44,501.00,491.65,500.04,5479400,500.04
+2007-08-16,492.02,496.43,480.46,491.52,8645600,491.52
+2007-08-15,509.00,511.69,496.71,497.55,5409500,497.55
+2007-08-14,515.72,517.40,508.00,508.60,3633700,508.60
+2007-08-13,519.54,519.75,513.03,515.50,3179300,515.50
+2007-08-10,510.18,518.72,505.63,515.75,5875200,515.75
+2007-08-09,520.80,526.82,514.63,514.73,4846500,514.73
+2007-08-08,519.34,525.78,517.09,525.78,4068800,525.78
+2007-08-07,509.75,519.88,509.04,516.02,4264300,516.02
+2007-08-06,503.00,510.15,502.50,510.00,3651500,510.00
+2007-08-03,510.05,513.20,503.00,503.00,3176200,503.00
+2007-08-02,513.72,514.99,509.00,511.01,3154900,511.01
+2007-08-01,510.50,516.51,508.14,512.94,4421500,512.94
+2007-07-31,520.23,520.44,510.00,510.00,4270500,510.00
+2007-07-30,512.92,519.34,510.50,516.11,3963300,516.11
+2007-07-27,508.53,516.62,505.50,511.89,5509100,511.89
+2007-07-26,508.74,512.59,498.88,508.00,6883400,508.00
+2007-07-25,516.98,517.02,505.56,509.76,5545000,509.76
+2007-07-24,509.30,518.69,507.11,514.00,5572100,514.00
+2007-07-23,519.01,520.00,512.15,512.51,6356700,512.51
+2007-07-20,511.90,523.18,509.50,520.12,17772300,520.12
+2007-07-19,553.46,553.52,542.24,548.59,11127200,548.59
+2007-07-18,553.89,554.50,543.81,549.50,6080000,549.50
+2007-07-17,555.04,557.73,552.38,555.00,4328600,555.00
+2007-07-16,550.30,558.58,549.31,552.99,6599500,552.99
+2007-07-13,547.91,552.67,547.25,552.16,5237100,552.16
+2007-07-12,545.86,547.32,540.22,545.33,3441600,545.33
+2007-07-11,543.61,546.50,540.01,544.47,3309300,544.47
+2007-07-10,543.79,547.00,541.65,543.34,3856000,543.34
+2007-07-09,543.00,548.74,540.26,542.56,3729800,542.56
+2007-07-06,541.25,543.87,538.73,539.40,2747000,539.40
+2007-07-05,535.56,544.40,532.15,541.63,4942900,541.63
+2007-07-03,531.06,534.40,527.50,534.34,1871800,534.34
+2007-07-02,525.49,531.85,524.20,530.38,3487600,530.38
+2007-06-29,526.02,527.40,519.46,522.70,3880600,522.70
+2007-06-28,524.88,529.50,523.80,525.01,4168400,525.01
+2007-06-27,525.00,527.99,519.56,526.29,6123100,526.29
+2007-06-26,532.73,533.20,526.24,530.26,5689500,530.26
+2007-06-25,528.98,534.99,523.38,527.42,7925000,527.42
+2007-06-22,516.42,524.99,516.10,524.98,7203700,524.98
+2007-06-21,510.98,515.29,506.28,514.11,4409700,514.11
+2007-06-20,516.96,518.75,509.06,509.97,4338200,509.97
+2007-06-19,514.01,517.25,511.54,514.31,4355300,514.31
+2007-06-18,506.18,516.00,504.24,515.20,4835900,515.20
+2007-06-15,508.19,509.00,501.23,505.89,6174100,505.89
+2007-06-14,505.38,505.88,501.70,502.84,4621200,502.84
+2007-06-13,507.09,508.54,498.69,505.24,7034000,505.24
+2007-06-12,508.71,511.67,503.17,504.77,6419500,504.77
+2007-06-11,514.02,518.25,510.00,511.34,4647700,511.34
+2007-06-08,516.20,519.64,509.46,515.49,6358200,515.49
+2007-06-07,519.75,526.50,512.51,515.06,10630500,515.06
+2007-06-06,516.75,520.78,515.26,518.25,7886700,518.25
+2007-06-05,509.75,519.00,506.61,518.84,10447100,518.84
+2007-06-04,497.91,510.51,497.59,507.07,7101000,507.07
+2007-06-01,501.00,505.02,497.93,500.40,4799000,500.40
+2007-05-31,500.56,508.78,497.06,497.91,8924300,497.91
+2007-05-30,484.50,498.84,483.00,498.60,7245800,498.60
+2007-05-29,485.00,491.80,484.00,487.11,5218000,487.11
+2007-05-25,479.70,484.95,477.27,483.52,5348500,483.52
+2007-05-24,475.15,479.20,471.50,474.33,4173600,474.33
+2007-05-23,480.82,483.41,473.75,473.97,5060200,473.97
+2007-05-22,473.00,479.01,473.00,475.86,3839000,475.86
+2007-05-21,469.53,479.20,466.72,470.60,6159300,470.60
+2007-05-18,472.03,472.70,469.75,470.32,3695900,470.32
+2007-05-17,472.46,475.22,470.81,470.96,4660600,470.96
+2007-05-16,462.00,473.14,459.02,472.61,6554200,472.61
+2007-05-15,461.96,462.54,457.41,458.00,4119000,458.00
+2007-05-14,465.48,467.51,460.00,461.78,3872700,461.78
+2007-05-11,461.83,467.00,461.00,466.74,2944100,466.74
+2007-05-10,467.04,469.49,461.02,461.47,3686300,461.47
+2007-05-09,466.15,471.73,463.88,469.25,3889900,469.25
+2007-05-08,466.13,468.17,464.73,466.81,2905100,466.81
+2007-05-07,472.14,472.82,466.47,467.27,3020100,467.27
+2007-05-04,470.12,474.84,465.88,471.12,3950000,471.12
+2007-05-03,466.22,474.07,465.29,473.23,3594200,473.23
+2007-05-02,468.65,471.08,465.73,465.78,3062700,465.78
+2007-05-01,472.19,472.81,464.17,469.00,3658200,469.00
+2007-04-30,479.15,481.35,471.38,471.38,3641200,471.38
+2007-04-27,480.07,482.40,478.33,479.01,2925700,479.01
+2007-04-26,478.10,484.45,477.11,481.18,4124900,481.18
+2007-04-25,480.00,481.37,476.11,477.99,3966800,477.99
+2007-04-24,478.61,479.98,475.55,477.53,3694700,477.53
+2007-04-23,480.10,485.00,478.26,479.08,5674600,479.08
+2007-04-20,490.52,492.50,482.02,482.48,12161500,482.48
+2007-04-19,474.50,481.95,469.59,471.65,11009600,471.65
+2007-04-18,471.26,479.90,469.53,476.01,5670500,476.01
+2007-04-17,473.80,476.39,471.60,472.80,3210100,472.80
+2007-04-16,468.46,476.99,468.15,474.27,5077900,474.27
+2007-04-13,468.45,468.77,463.36,466.29,2794800,466.29
+2007-04-12,464.00,468.00,462.24,467.39,2707900,467.39
+2007-04-11,466.06,469.40,462.61,464.53,3812000,464.53
+2007-04-10,467.09,470.79,465.16,466.50,2979300,466.50
+2007-04-09,472.98,473.00,465.59,468.21,3062100,468.21
+2007-04-05,471.30,472.09,469.62,471.51,2715800,471.51
+2007-04-04,472.14,473.00,469.58,471.02,3778800,471.02
+2007-04-03,464.05,474.25,464.00,472.60,6501800,472.60
+2007-04-02,457.76,458.53,452.12,458.53,3448500,458.53
+2007-03-30,462.10,463.40,456.14,458.16,3380200,458.16
+2007-03-29,464.55,466.00,455.00,460.92,3988500,460.92
+2007-03-28,461.87,465.44,460.15,461.88,4591600,461.88
+2007-03-27,463.55,465.23,460.34,463.62,3741200,463.62
+2007-03-26,460.55,465.00,455.62,465.00,4710300,465.00
+2007-03-23,461.45,463.39,457.08,461.83,4111300,461.83
+2007-03-22,455.61,462.17,452.53,462.04,5680700,462.04
+2007-03-21,445.30,456.57,445.21,456.55,5798300,456.55
+2007-03-20,445.79,447.60,443.60,445.28,3421500,445.28
+2007-03-19,443.25,448.50,440.63,447.23,5197700,447.23
+2007-03-16,445.65,446.70,439.89,440.85,5659100,440.85
+2007-03-15,447.86,449.82,443.94,446.19,3944200,446.19
+2007-03-14,443.23,448.66,439.00,448.00,8016900,448.00
+2007-03-13,450.11,451.93,442.83,443.03,6377300,443.03
+2007-03-12,452.57,455.25,451.11,454.75,3465400,454.75
+2007-03-09,458.00,458.40,450.10,452.96,4977700,452.96
+2007-03-08,459.22,465.50,454.10,454.72,5362800,454.72
+2007-03-07,462.69,463.14,454.29,455.64,6534100,455.64
+2007-03-06,447.47,459.00,447.38,457.55,7533700,457.55
+2007-03-05,437.02,445.50,437.00,440.95,6355100,440.95
+2007-03-02,445.11,448.70,438.68,438.68,6583600,438.68
+2007-03-01,442.67,452.42,440.00,448.23,8685200,448.23
+2007-02-28,450.41,453.67,443.04,449.45,8032300,449.45
+2007-02-27,455.00,459.80,447.17,448.77,9312800,448.77
+2007-02-26,472.83,475.25,463.75,464.93,3969900,464.93
+2007-02-23,475.75,476.95,467.80,470.62,3882600,470.62
+2007-02-22,478.69,484.24,474.39,475.85,5743900,475.85
+2007-02-21,469.84,478.68,467.74,475.86,5640600,475.86
+2007-02-20,468.47,472.75,464.71,472.10,4067600,472.10
+2007-02-16,462.80,470.15,462.06,469.94,6177000,469.94
+2007-02-15,466.00,466.13,460.72,461.47,4042400,461.47
+2007-02-14,460.00,469.13,459.22,465.93,5698800,465.93
+2007-02-13,459.15,462.78,457.26,459.10,4062600,459.10
+2007-02-12,460.68,462.39,455.02,458.29,5754500,458.29
+2007-02-09,471.65,472.68,461.50,461.89,4858600,461.89
+2007-02-08,468.05,473.75,465.15,471.03,4076700,471.03
+2007-02-07,473.82,474.35,468.78,470.01,4119800,470.01
+2007-02-06,468.10,473.30,467.26,471.48,5321900,471.48
+2007-02-05,477.50,478.00,466.19,467.16,7206900,467.16
+2007-02-02,482.61,485.00,477.81,481.50,6286500,481.50
+2007-02-01,506.00,506.01,481.53,481.75,15658700,481.75
+2007-01-31,496.49,505.00,495.51,501.50,12206100,501.50
+2007-01-30,494.00,498.00,491.22,494.32,4180500,494.32
+2007-01-29,498.00,498.75,490.50,492.47,4775700,492.47
+2007-01-26,490.93,497.90,487.03,495.84,5496500,495.84
+2007-01-25,501.00,504.50,485.66,488.09,6368500,488.09
+2007-01-24,484.45,499.54,483.29,499.07,6059300,499.07
+2007-01-23,480.79,484.75,477.29,479.05,4665500,479.05
+2007-01-22,492.50,492.65,478.50,480.84,5404300,480.84
+2007-01-19,487.98,490.76,486.74,489.75,4978300,489.75
+2007-01-18,494.52,496.48,487.43,487.83,5932000,487.83
+2007-01-17,503.39,507.77,494.38,497.28,6699100,497.28
+2007-01-16,507.55,513.00,503.30,504.28,7568900,504.28
+2007-01-12,501.99,505.00,500.00,505.00,4473700,505.00
+2007-01-11,497.20,501.75,496.18,499.72,7208200,499.72
+2007-01-10,484.43,493.55,482.04,489.46,5968500,489.46
+2007-01-09,485.45,488.25,481.20,485.50,5381400,485.50
+2007-01-08,487.69,489.87,482.20,483.58,4754400,483.58
+2007-01-05,482.50,487.50,478.11,487.19,6872100,487.19
+2007-01-04,469.00,483.95,468.35,483.26,7887600,483.26
+2007-01-03,466.00,476.66,461.11,467.59,7706500,467.59
+2006-12-29,462.10,464.47,459.86,460.48,2559200,460.48
+2006-12-28,467.12,468.58,462.25,462.56,3116200,462.56
+2006-12-27,460.00,468.08,459.10,468.03,4231500,468.03
+2006-12-26,456.52,459.47,454.59,457.53,2074300,457.53
+2006-12-22,457.50,458.64,452.73,455.58,3988300,455.58
+2006-12-21,464.18,465.25,452.34,456.20,6953300,456.20
+2006-12-20,470.00,471.50,462.33,462.90,4367800,462.90
+2006-12-19,461.72,469.31,458.50,468.63,6587000,468.63
+2006-12-18,482.51,482.74,460.72,462.80,8016600,462.80
+2006-12-15,482.64,484.11,479.84,480.30,5190800,480.30
+2006-12-14,480.25,483.75,477.26,482.12,4748900,482.12
+2006-12-13,484.69,485.50,477.02,478.99,4662100,478.99
+2006-12-12,483.85,486.36,480.28,481.78,4181000,481.78
+2006-12-11,484.92,488.90,483.80,483.93,3263400,483.93
+2006-12-08,481.94,488.60,480.00,484.11,3974900,484.11
+2006-12-07,490.23,491.80,482.42,482.64,4664300,482.64
+2006-12-06,486.96,492.40,484.52,488.71,4450300,488.71
+2006-12-05,487.40,489.44,484.89,487.00,4103000,487.00
+2006-12-04,483.00,487.43,479.35,484.85,4899900,484.85
+2006-12-01,485.98,488.39,478.50,480.80,5631400,480.80
+2006-11-30,484.19,490.40,481.55,484.81,5577500,484.81
+2006-11-29,494.24,494.74,482.25,484.65,6315300,484.65
+2006-11-28,481.13,489.86,477.03,489.50,7797600,489.50
+2006-11-27,501.37,501.78,484.75,484.75,7324700,484.75
+2006-11-24,504.50,507.50,504.00,505.00,1732700,505.00
+2006-11-22,510.97,513.00,505.78,508.01,4500700,508.01
+2006-11-21,496.54,510.00,495.83,509.65,8427500,509.65
+2006-11-20,498.40,498.40,492.65,495.05,5124500,495.05
+2006-11-17,493.25,499.66,493.00,498.79,5511000,498.79
+2006-11-16,495.00,497.68,492.56,495.90,5092600,495.90
+2006-11-15,493.43,499.85,491.93,491.93,8370700,491.93
+2006-11-14,480.70,489.95,480.50,489.30,7223400,489.30
+2006-11-13,474.90,481.17,474.14,481.03,4341900,481.03
+2006-11-10,473.78,474.72,470.29,473.55,2796700,473.55
+2006-11-09,476.50,479.49,471.86,472.63,4879200,472.63
+2006-11-08,470.35,481.74,468.60,475.00,7965000,475.00
+2006-11-07,476.95,479.02,471.77,472.57,4897100,472.57
+2006-11-06,473.77,479.66,472.33,476.95,4991500,476.95
+2006-11-03,472.23,473.75,465.06,471.80,4907700,471.80
+2006-11-02,467.50,473.73,466.38,469.91,5236700,469.91
+2006-11-01,478.76,479.13,465.26,467.50,5426300,467.50
+2006-10-31,478.06,482.16,473.84,476.39,6285400,476.39
+2006-10-30,474.82,480.46,470.01,476.57,6563100,476.57
+2006-10-27,483.90,485.24,472.49,475.20,6604000,475.20
+2006-10-26,487.68,491.96,484.20,485.10,7031700,485.10
+2006-10-25,477.49,488.50,475.11,486.60,9187500,486.60
+2006-10-24,476.28,477.86,471.41,473.31,8660200,473.31
+2006-10-23,462.28,484.64,460.37,480.78,15104500,480.78
+2006-10-20,458.99,460.10,453.59,459.67,11647900,459.67
+2006-10-19,420.23,429.50,419.57,426.06,11503500,426.06
+2006-10-18,422.99,424.75,417.50,419.31,6017300,419.31
+2006-10-17,420.30,423.75,416.70,420.64,5211000,420.64
+2006-10-16,427.70,429.20,421.34,421.75,4319400,421.75
+2006-10-13,427.76,429.50,425.56,427.30,3622500,427.30
+2006-10-12,428.56,429.68,424.00,427.44,4844000,427.44
+2006-10-11,425.02,429.91,423.76,426.50,5635400,426.50
+2006-10-10,431.56,437.85,422.39,426.65,9788600,426.65
+2006-10-09,424.80,431.95,423.42,429.00,7583300,429.00
+2006-10-06,410.22,421.91,409.75,420.50,7336500,420.50
+2006-10-05,414.70,418.24,410.86,411.81,5789800,411.81
+2006-10-04,404.97,415.77,403.05,415.70,6661800,415.70
+2006-10-03,401.29,406.46,398.19,404.04,5464700,404.04
+2006-10-02,401.90,406.00,400.80,401.44,3651900,401.44
+2006-09-29,405.13,405.62,401.41,401.90,3310900,401.90
+2006-09-28,404.08,406.98,400.54,403.58,5107400,403.58
+2006-09-27,406.30,411.22,402.37,402.92,5876700,402.92
+2006-09-26,405.50,407.68,401.77,406.87,5289400,406.87
+2006-09-25,405.58,409.45,402.50,403.98,5737300,403.98
+2006-09-22,404.98,407.45,401.36,403.78,4649600,403.78
+2006-09-21,400.30,408.45,399.86,406.85,10692100,406.85
+2006-09-20,407.10,407.39,394.62,397.00,9147800,397.00
+2006-09-19,415.46,415.49,392.74,403.81,14292900,403.81
+2006-09-18,410.00,418.69,409.47,414.69,7106700,414.69
+2006-09-15,407.48,410.05,406.74,409.88,7838200,409.88
+2006-09-14,404.30,406.28,401.93,403.98,5366100,403.98
+2006-09-13,395.15,406.76,395.10,406.57,9768200,406.57
+2006-09-12,385.00,392.73,384.88,391.90,5442200,391.90
+2006-09-11,378.26,384.69,377.77,384.09,4529200,384.09
+2006-09-08,376.72,380.79,376.72,377.85,3083400,377.85
+2006-09-07,379.39,381.75,377.40,378.49,3842000,378.49
+2006-09-06,382.10,383.19,379.66,380.14,3724100,380.14
+2006-09-05,379.87,385.40,377.44,384.36,4074300,384.36
+2006-09-01,380.99,381.28,377.19,378.60,2672900,378.60
+2006-08-31,381.49,382.15,378.20,378.53,2959900,378.53
+2006-08-30,379.21,384.65,378.51,380.75,4044400,380.75
+2006-08-29,380.78,382.32,377.20,378.95,4460000,378.95
+2006-08-28,375.61,380.95,375.00,380.95,4164000,380.95
+2006-08-25,373.08,375.32,372.50,373.26,2466700,373.26
+2006-08-24,374.44,376.40,372.26,373.73,3482500,373.73
+2006-08-23,377.64,378.27,372.66,373.43,3642300,373.43
+2006-08-22,377.73,379.26,374.84,378.29,4164100,378.29
+2006-08-21,378.10,379.00,375.22,377.30,4023300,377.30
+2006-08-18,386.31,387.09,380.75,383.36,4952200,383.36
+2006-08-17,386.39,390.00,383.92,385.80,5080200,385.80
+2006-08-16,383.48,388.45,382.12,387.72,5853200,387.72
+2006-08-15,374.11,381.67,372.60,380.97,6698200,380.97
+2006-08-14,371.50,375.13,368.67,369.43,4968300,369.43
+2006-08-11,374.40,375.28,368.00,368.50,3766500,368.50
+2006-08-10,373.88,377.67,372.46,374.20,4261900,374.20
+2006-08-09,382.80,384.68,376.36,376.94,4311000,376.94
+2006-08-08,382.82,384.50,379.09,381.00,5743200,381.00
+2006-08-07,371.50,379.73,371.15,377.95,3946900,377.95
+2006-08-04,379.56,380.68,371.75,373.85,5095200,373.85
+2006-08-03,364.98,377.91,363.36,375.39,6327000,375.39
+2006-08-02,375.60,377.17,365.20,367.23,7097800,367.23
+2006-08-01,385.11,385.77,375.51,375.51,5463200,375.51
+2006-07-31,388.00,389.17,383.31,386.60,4595300,386.60
+2006-07-28,382.00,389.56,381.73,388.12,4083600,388.12
+2006-07-27,387.37,387.49,377.95,382.40,5641100,382.40
+2006-07-26,388.20,391.91,383.00,385.50,5531900,385.50
+2006-07-25,385.02,391.31,383.80,389.36,5761100,389.36
+2006-07-24,392.82,393.89,381.21,390.90,8086100,390.90
+2006-07-21,386.14,391.75,377.69,390.11,11754600,390.11
+2006-07-20,404.28,404.44,385.66,387.12,12538700,387.12
+2006-07-19,395.01,401.14,394.66,399.00,8518500,399.00
+2006-07-18,409.75,410.57,397.74,403.05,8536800,403.05
+2006-07-17,404.63,411.00,403.72,407.89,5811900,407.89
+2006-07-14,410.33,411.49,398.61,403.50,7552100,403.50
+2006-07-13,414.00,418.34,406.83,408.83,6924500,408.83
+2006-07-12,422.09,422.74,416.73,417.25,4906700,417.25
+2006-07-11,418.51,425.05,413.03,424.56,5971300,424.56
+2006-07-10,423.44,425.23,416.38,418.20,4436400,418.20
+2006-07-07,426.05,427.89,415.88,420.45,6041900,420.45
+2006-07-06,423.38,425.38,421.98,423.19,3687100,423.19
+2006-07-05,421.52,422.80,415.64,421.46,4985600,421.46
+2006-07-03,420.04,423.77,419.45,423.20,2156700,423.20
+2006-06-30,415.60,419.33,412.33,419.33,6258000,419.33
+2006-06-29,407.99,418.20,405.82,417.81,6658200,417.81
+2006-06-28,404.01,406.48,401.13,406.11,3710500,406.11
+2006-06-27,405.71,408.00,401.01,402.32,4107100,402.32
+2006-06-26,406.75,408.30,403.25,404.22,3551200,404.22
+2006-06-23,402.76,409.75,400.74,404.86,5314800,404.86
+2006-06-22,401.58,406.00,388.00,399.95,5911900,399.95
+2006-06-21,391.06,404.00,389.75,402.13,8744400,402.13
+2006-06-20,388.03,391.87,386.51,387.17,4039900,387.17
+2006-06-19,390.85,394.80,386.98,388.14,7633100,388.14
+2006-06-16,389.10,390.93,388.00,390.70,5304600,390.70
+2006-06-15,386.62,392.25,383.00,391.00,6785700,391.00
+2006-06-14,389.83,391.10,378.52,384.39,7772000,384.39
+2006-06-13,380.90,387.00,378.12,386.52,7659100,386.52
+2006-06-12,388.34,390.49,381.00,381.54,5019100,381.54
+2006-06-09,392.19,395.43,385.35,386.57,6157500,386.57
+2006-06-08,387.75,394.27,378.59,393.30,10359500,393.30
+2006-06-07,393.24,394.86,386.50,386.51,8911300,386.51
+2006-06-06,376.58,390.00,376.30,389.99,10259800,389.99
+2006-06-05,376.18,381.45,374.15,374.44,5558500,374.44
+2006-06-02,386.84,387.08,377.45,379.44,6386400,379.44
+2006-06-01,373.54,382.99,371.60,382.62,6278000,382.62
+2006-05-31,373.80,378.25,366.78,371.82,7981300,371.82
+2006-05-30,378.28,381.00,371.45,371.94,4316000,371.94
+2006-05-26,384.55,385.88,380.03,381.35,3667000,381.35
+2006-05-25,379.08,383.00,372.31,382.99,8194600,382.99
+2006-05-24,377.35,383.44,371.61,381.25,9553800,381.25
+2006-05-23,374.21,383.88,373.56,375.58,8983000,375.58
+2006-05-22,367.85,373.03,365.25,370.95,8604400,370.95
+2006-05-19,373.28,374.50,360.57,370.02,11398200,370.02
+2006-05-18,378.78,381.81,370.71,370.99,5835000,370.99
+2006-05-17,370.61,379.84,370.22,374.50,10643800,374.50
+2006-05-16,375.99,376.86,369.89,371.30,6491100,371.30
+2006-05-15,375.93,380.15,368.25,376.20,8590100,376.20
+2006-05-12,383.54,384.87,373.55,374.13,10087600,374.13
+2006-05-11,403.42,404.71,384.98,387.00,8892800,387.00
+2006-05-10,408.31,411.71,401.86,402.98,6187200,402.98
+2006-05-09,395.70,409.00,393.75,408.80,9140600,408.80
+2006-05-08,395.11,397.12,390.05,394.78,5118600,394.78
+2006-05-05,397.60,400.68,391.78,394.30,6065000,394.30
+2006-05-04,395.03,398.87,392.21,394.75,4652000,394.75
+2006-05-03,396.35,401.50,390.88,394.17,8072200,394.17
+2006-05-02,401.08,402.49,388.40,394.80,13104300,394.80
+2006-05-01,418.47,419.44,398.55,398.90,10361200,398.90
+2006-04-28,418.63,425.73,416.30,417.94,7421300,417.94
+2006-04-27,422.91,426.91,419.39,420.03,8337900,420.03
+2006-04-26,427.74,430.04,423.53,425.97,7277800,425.97
+2006-04-25,439.63,441.04,426.00,427.16,9569000,427.16
+2006-04-24,439.40,444.70,436.52,440.50,8836400,440.50
+2006-04-21,448.90,450.72,436.17,437.10,22551300,437.10
+2006-04-20,411.01,416.00,408.20,415.00,12271500,415.00
+2006-04-19,412.57,413.64,406.73,410.50,6781700,410.50
+2006-04-18,407.93,409.83,401.50,404.24,8137600,404.24
+2006-04-17,403.45,412.50,400.84,406.82,8259500,406.82
+2006-04-13,408.63,409.76,400.50,402.16,6552900,402.16
+2006-04-12,409.00,411.33,405.19,408.95,6017000,408.95
+2006-04-11,416.42,419.10,406.22,409.66,11107200,409.66
+2006-04-10,407.08,417.17,405.25,416.38,9320100,416.38
+2006-04-07,412.41,412.85,404.02,406.16,7025900,406.16
+2006-04-06,406.49,413.89,405.43,411.18,8598500,411.18
+2006-04-05,408.20,414.57,402.82,407.99,13410500,407.99
+2006-04-04,389.90,404.90,388.14,404.34,15715700,404.34
+2006-04-03,389.53,392.47,387.93,389.70,8122700,389.70
+2006-03-31,388.74,391.87,384.03,390.00,36521400,390.00
+2006-03-30,389.19,393.50,383.61,388.44,14711700,388.44
+2006-03-29,379.94,399.00,379.51,394.98,19027500,394.98
+2006-03-28,371.71,377.86,371.17,377.20,8945800,377.20
+2006-03-27,367.09,371.71,365.00,369.69,7023700,369.69
+2006-03-24,368.62,370.09,362.51,365.80,15180600,365.80
+2006-03-23,342.35,345.75,340.20,341.89,7434700,341.89
+2006-03-22,339.75,344.10,337.50,340.22,7596000,340.22
+2006-03-21,350.01,351.66,339.08,339.92,9831100,339.92
+2006-03-20,342.34,350.09,341.54,348.19,10407600,348.19
+2006-03-17,338.80,341.78,334.93,339.79,8551700,339.79
+2006-03-16,348.61,348.75,337.90,338.77,10016700,338.77
+2006-03-15,350.77,352.30,340.53,344.50,12768800,344.50
+2006-03-14,337.14,352.37,332.62,351.16,18450700,351.16
+2006-03-13,340.93,346.10,335.45,337.06,13642400,337.06
+2006-03-10,343.50,344.50,331.55,337.50,19325600,337.50
+2006-03-09,355.39,358.53,341.50,343.00,13910400,343.00
+2006-03-08,353.93,360.03,350.54,353.88,11745600,353.88
+2006-03-07,365.02,368.45,358.15,364.45,10378800,364.45
+2006-03-06,380.91,383.40,367.14,368.10,8939700,368.10
+2006-03-03,384.30,387.24,375.76,378.18,11962000,378.18
+2006-03-02,364.28,381.10,362.20,376.45,18330300,376.45
+2006-03-01,368.56,369.45,361.30,364.80,12061200,364.80
+2006-02-28,393.20,397.54,338.51,362.62,39437600,362.62
+2006-02-27,381.27,391.70,380.28,390.38,10212200,390.38
+2006-02-24,377.30,380.07,373.49,377.40,6484300,377.40
+2006-02-23,365.61,381.24,365.39,378.07,12551600,378.07
+2006-02-22,367.15,368.95,363.86,365.49,6476200,365.49
+2006-02-21,366.44,373.54,365.11,366.59,8686000,366.59
+2006-02-17,369.86,372.14,363.62,368.75,14320200,368.75
+2006-02-16,345.67,367.00,344.49,366.46,21315500,366.46
+2006-02-15,341.27,346.00,337.83,342.38,12947000,342.38
+2006-02-14,345.33,351.69,342.40,343.32,14654000,343.32
+2006-02-13,346.64,350.60,341.89,345.70,19717800,345.70
+2006-02-10,361.95,364.50,353.14,362.61,15223500,362.61
+2006-02-09,371.20,374.40,356.11,358.77,11912400,358.77
+2006-02-08,368.48,370.69,354.67,369.08,20804100,369.08
+2006-02-07,382.99,383.70,363.35,367.92,16630200,367.92
+2006-02-06,385.31,389.90,379.56,385.10,8940400,385.10
+2006-02-03,393.62,393.90,372.57,381.55,18281800,381.55
+2006-02-02,403.82,406.50,395.98,396.04,11807700,396.04
+2006-02-01,389.03,402.00,387.52,401.78,27122500,401.78
+2006-01-31,430.57,439.60,423.97,432.66,22066000,432.66
+2006-01-30,429.23,433.28,425.00,426.82,8588900,426.82
+2006-01-27,435.00,438.22,428.98,433.49,8452200,433.49
+2006-01-26,439.54,439.99,423.56,434.27,12926100,434.27
+2006-01-25,451.26,454.23,429.22,433.00,18739800,433.00
+2006-01-24,436.03,444.95,434.48,443.03,15464600,443.03
+2006-01-23,407.38,428.39,405.73,427.50,22741400,427.50
+2006-01-20,438.70,440.03,394.74,399.46,41116700,399.46
+2006-01-19,451.17,453.49,433.00,436.45,14537300,436.45
+2006-01-18,447.30,457.36,443.25,444.91,20485700,444.91
+2006-01-17,463.06,469.90,462.53,467.11,8270300,467.11
+2006-01-13,464.31,466.89,461.61,466.25,7656600,466.25
+2006-01-12,473.72,474.99,461.50,463.63,10125300,463.63
+2006-01-11,471.27,475.11,469.18,471.63,9007400,471.63
+2006-01-10,464.42,470.25,462.04,469.76,9097100,469.76
+2006-01-09,466.41,473.40,460.94,466.90,12791900,466.90
+2006-01-06,456.87,470.50,453.24,465.66,17756900,465.66
+2006-01-05,446.00,451.55,441.50,451.24,10808300,451.24
+2006-01-04,443.90,448.96,439.75,445.24,15286400,445.24
+2006-01-03,422.52,435.67,418.22,435.23,13121200,435.23
+2005-12-30,417.27,418.21,413.74,414.86,7587100,414.86
+2005-12-29,427.98,428.73,419.17,420.15,6945800,420.15
+2005-12-28,424.34,427.78,421.26,426.69,7117900,426.69
+2005-12-27,431.86,431.86,422.76,424.64,6702800,424.64
+2005-12-23,432.15,432.50,428.78,430.93,4595100,430.93
+2005-12-22,431.77,432.86,425.93,432.04,7546600,432.04
+2005-12-21,433.55,436.86,420.71,426.33,11221900,426.33
+2005-12-20,427.86,432.20,424.67,429.74,10084700,429.74
+2005-12-19,432.20,446.21,420.11,424.60,21936800,424.60
+2005-12-16,425.34,432.50,422.75,430.15,16330500,430.15
+2005-12-15,419.11,423.14,416.50,422.55,6045800,422.55
+2005-12-14,417.04,419.73,415.49,418.96,6630400,418.96
+2005-12-13,412.50,418.00,411.64,417.49,8157000,417.49
+2005-12-12,414.63,415.21,409.95,412.61,6950100,412.61
+2005-12-09,415.00,415.78,408.56,409.20,7643400,409.20
+2005-12-08,405.30,410.65,402.64,410.65,8910100,410.65
+2005-12-07,406.16,406.70,399.01,404.22,11665900,404.22
+2005-12-06,408.70,416.41,401.70,404.54,15114700,404.54
+2005-12-05,417.00,417.50,404.28,405.85,10289400,405.85
+2005-12-02,416.94,419.53,413.86,417.70,7543500,417.70
+2005-12-01,409.20,415.44,408.29,414.09,9744900,414.09
+2005-11-30,404.26,408.45,395.56,404.91,15596600,404.91
+2005-11-29,424.46,426.40,402.14,403.54,21495800,403.54
+2005-11-28,429.82,431.24,422.44,423.48,11008400,423.48
+2005-11-25,425.78,428.75,425.30,428.62,4840100,428.62
+2005-11-23,417.04,424.72,415.78,422.86,10085000,422.86
+2005-11-22,408.65,417.31,406.23,416.47,9596000,416.47
+2005-11-21,399.17,409.98,393.49,409.36,10335100,409.36
+2005-11-18,403.49,404.50,399.85,400.21,7025700,400.21
+2005-11-17,401.80,403.81,399.53,403.45,9212200,403.45
+2005-11-16,396.20,398.85,394.11,398.15,8695200,398.15
+2005-11-15,394.38,397.00,390.95,392.80,8624900,392.80
+2005-11-14,392.12,398.22,391.53,396.97,7807900,396.97
+2005-11-11,395.12,396.90,388.85,390.40,7063900,390.40
+2005-11-10,378.36,391.35,377.43,391.10,9128700,391.10
+2005-11-09,386.67,388.29,378.03,379.15,10466900,379.15
+2005-11-08,394.25,395.59,388.58,389.90,7897500,389.90
+2005-11-07,395.10,397.47,392.15,395.03,9591500,395.03
+2005-11-04,389.98,391.79,385.45,390.43,8824900,390.43
+2005-11-03,382.41,386.58,381.38,385.95,7448400,385.95
+2005-11-02,381.70,385.00,377.17,379.68,10565400,379.68
+2005-11-01,371.86,383.90,369.01,379.38,16356100,379.38
+2005-10-31,360.24,374.75,359.51,372.14,14342900,372.14
+2005-10-28,355.27,358.95,355.02,358.17,5903500,358.17
+2005-10-27,356.60,357.09,351.68,353.06,5134400,353.06
+2005-10-26,346.28,356.00,346.19,355.44,8907500,355.44
+2005-10-25,345.78,347.40,342.86,346.91,6878300,346.91
+2005-10-24,343.37,349.30,342.19,348.65,9431700,348.65
+2005-10-21,345.80,346.43,333.00,339.90,22892400,339.90
+2005-10-20,309.99,311.13,301.21,303.20,13911700,303.20
+2005-10-19,304.00,309.87,303.96,308.70,7010700,308.70
+2005-10-18,304.96,307.96,302.74,303.28,7077800,303.28
+2005-10-17,297.50,305.20,294.56,305.00,7566700,305.00
+2005-10-14,299.90,300.23,292.54,296.14,8519100,296.14
+2005-10-13,302.00,302.00,290.68,297.44,10567700,297.44
+2005-10-12,305.20,307.19,299.00,300.97,9306200,300.97
+2005-10-11,310.61,312.65,304.86,306.10,8542600,306.10
+2005-10-10,313.31,314.82,309.15,310.65,5572200,310.65
+2005-10-07,314.79,316.67,310.54,312.99,6770300,312.99
+2005-10-06,314.14,314.48,310.09,312.75,7993800,312.75
+2005-10-05,312.69,314.90,308.00,310.71,8328400,310.71
+2005-10-04,319.95,321.28,310.74,311.00,9144300,311.00
+2005-10-03,313.63,320.11,312.79,318.68,9160300,318.68
+2005-09-30,314.22,317.50,312.29,316.46,9151300,316.46
+2005-09-29,306.68,310.72,306.08,309.62,5613800,309.62
+2005-09-28,314.22,315.10,305.60,306.00,7997400,306.00
+2005-09-27,314.95,318.41,313.38,313.94,6873100,313.94
+2005-09-26,319.50,320.95,312.56,314.28,9894400,314.28
+2005-09-23,313.00,317.21,312.59,315.36,8483800,315.36
+2005-09-22,311.50,319.22,310.17,311.37,13006400,311.37
+2005-09-21,308.41,313.76,305.96,311.90,10119700,311.90
+2005-09-20,306.15,311.30,305.23,307.91,9351000,307.91
+2005-09-19,301.00,306.00,300.71,303.79,5761900,303.79
+2005-09-16,304.02,304.50,299.87,300.20,7579800,300.20
+2005-09-15,299.52,306.75,297.91,302.62,15466200,302.62
+2005-09-14,308.73,313.28,300.30,303.00,11275800,303.00
+2005-09-13,309.00,315.53,306.17,311.68,10299900,311.68
+2005-09-12,301.75,311.42,301.00,309.74,10386500,309.74
+2005-09-09,297.28,299.10,296.56,299.09,4390500,299.09
+2005-09-08,294.83,299.28,293.36,295.39,6613300,295.39
+2005-09-07,285.89,295.50,285.28,294.87,7499500,294.87
+2005-09-06,289.00,289.39,286.80,287.11,4212300,287.11
+2005-09-02,286.51,289.99,286.44,288.45,3434500,288.45
+2005-09-01,285.91,287.50,285.00,286.25,2742100,286.25
+2005-08-31,288.23,288.50,284.36,286.00,5034000,286.00
+2005-08-30,287.39,289.51,285.88,287.27,4792000,287.27
+2005-08-29,282.24,289.12,282.24,288.45,5903000,288.45
+2005-08-26,283.48,285.02,282.66,283.58,3755300,283.58
+2005-08-25,282.55,284.00,279.97,282.59,4376600,282.59
+2005-08-24,277.57,284.75,276.45,282.57,8593100,282.57
+2005-08-23,276.16,279.74,274.12,279.58,5821700,279.58
+2005-08-22,281.24,281.47,273.35,274.01,6813000,274.01
+2005-08-19,280.99,281.45,279.62,280.00,5542900,280.00
+2005-08-18,275.91,280.50,275.00,279.99,11872800,279.99
+2005-08-17,285.51,286.57,284.00,285.10,3883300,285.10
+2005-08-16,284.88,287.79,283.34,285.65,7109200,285.65
+2005-08-15,289.80,292.77,283.77,284.00,8174700,284.00
+2005-08-12,283.36,290.20,281.64,289.72,6585900,289.72
+2005-08-11,285.89,286.58,280.62,284.05,7514900,284.05
+2005-08-10,291.30,292.33,284.88,285.68,6879000,285.68
+2005-08-09,291.96,292.68,288.51,291.57,5779300,291.57
+2005-08-08,293.60,295.65,290.49,291.25,4481800,291.25
+2005-08-05,297.50,298.51,291.31,292.35,5939700,292.35
+2005-08-04,295.55,299.00,295.25,297.73,5236500,297.73
+2005-08-03,298.00,299.72,295.60,297.30,5930600,297.30
+2005-08-02,291.60,299.52,291.12,299.19,7290200,299.19
+2005-08-01,288.12,292.50,288.10,291.61,5662400,291.61
+2005-07-29,292.14,292.84,286.99,287.76,8363300,287.76
+2005-07-28,297.41,297.41,293.28,293.50,5925600,293.50
+2005-07-27,297.74,298.23,292.40,296.93,7217900,296.93
+2005-07-26,295.01,298.00,292.09,296.09,9816900,296.09
+2005-07-25,302.39,303.29,294.96,295.85,9658800,295.85
+2005-07-22,306.37,309.25,296.33,302.40,23386800,302.40
+2005-07-21,314.05,317.80,311.21,313.94,19789400,313.94
+2005-07-20,305.57,312.61,301.80,312.00,14310400,312.00
+2005-07-19,302.10,310.35,301.80,309.90,12621400,309.90
+2005-07-18,300.00,301.90,297.75,299.54,6207800,299.54
+2005-07-15,301.24,303.40,299.78,301.19,8438400,301.19
+2005-07-14,305.34,306.75,300.07,300.89,10667700,300.89
+2005-07-13,292.51,299.24,292.10,298.86,11437900,298.86
+2005-07-12,293.39,294.40,290.93,291.78,5864900,291.78
+2005-07-11,296.40,296.60,291.02,293.35,8390300,293.35
+2005-07-08,296.25,297.50,294.05,296.23,7457600,296.23
+2005-07-07,289.39,295.80,288.51,295.54,10672100,295.54
+2005-07-06,297.30,297.60,291.38,291.52,8000300,291.52
+2005-07-05,292.10,295.98,290.23,295.71,7494000,295.71
+2005-07-01,295.04,296.24,289.22,291.25,9227600,291.25
+2005-06-30,294.34,298.93,291.04,294.15,15094400,294.15
+2005-06-29,302.50,304.38,292.15,292.72,18298700,292.72
+2005-06-28,306.28,309.25,302.00,302.00,19036500,302.00
+2005-06-27,298.90,304.47,293.86,304.10,17802900,304.10
+2005-06-24,290.90,298.00,289.58,297.25,17771200,297.25
+2005-06-23,288.00,294.81,286.50,289.71,14056400,289.71
+2005-06-22,289.67,292.32,288.67,289.30,10474000,289.30
+2005-06-21,288.07,290.30,284.97,287.84,15132300,287.84
+2005-06-20,276.09,287.67,271.73,286.70,21024700,286.70
+2005-06-17,279.00,280.30,275.90,280.30,10434400,280.30
+2005-06-16,274.26,278.30,273.07,277.44,12462400,277.44
+2005-06-15,275.00,277.30,267.43,274.80,20883100,274.80
+2005-06-14,278.59,281.24,277.75,278.35,10091900,278.35
+2005-06-13,279.82,284.19,276.52,282.75,12803200,282.75
+2005-06-10,286.99,287.28,280.02,282.50,12696600,282.50
+2005-06-09,284.72,288.50,280.56,286.31,16441100,286.31
+2005-06-08,292.85,293.19,278.00,279.56,25700900,279.56
+2005-06-07,297.10,299.59,290.30,293.12,24323000,293.12
+2005-06-06,282.39,293.75,281.83,290.94,22525900,290.94
+2005-06-03,286.79,289.30,277.41,280.26,18782300,280.26
+2005-06-02,288.73,289.78,284.60,287.90,17974100,287.90
+2005-06-01,283.20,292.89,282.02,288.00,35191700,288.00
+2005-05-31,269.43,278.40,269.37,277.27,22236800,277.27
+2005-05-27,260.46,266.05,259.25,266.00,12184100,266.00
+2005-05-26,260.96,263.76,258.30,259.20,13546600,259.20
+2005-05-25,252.73,260.98,250.63,260.81,18057900,260.81
+2005-05-24,256.96,265.44,253.50,256.00,29043100,256.00
+2005-05-23,243.16,258.10,242.71,255.45,21388300,255.45
+2005-05-20,241.21,241.67,239.65,241.61,8163500,241.61
+2005-05-19,240.34,241.17,238.27,239.18,9716500,239.18
+2005-05-18,233.61,239.97,233.52,239.16,12312000,239.16
+2005-05-17,230.56,233.45,230.20,233.13,7808900,233.13
+2005-05-16,229.68,231.62,228.57,231.05,5681400,231.05
+2005-05-13,229.18,231.09,227.32,229.24,7415500,229.24
+2005-05-12,230.81,232.23,228.20,228.72,8948200,228.72
+2005-05-11,228.97,231.98,227.93,231.29,11478800,231.29
+2005-05-10,225.47,227.80,224.72,227.80,6345800,227.80
+2005-05-09,228.00,228.50,225.43,226.02,5536800,226.02
+2005-05-06,228.40,229.25,226.47,228.02,6763900,228.02
+2005-05-05,228.62,228.62,225.88,226.98,7509600,226.98
+2005-05-04,227.23,229.88,227.00,228.50,12083500,228.50
+2005-05-03,221.85,228.15,221.32,226.19,17780200,226.19
+2005-05-02,222.05,223.70,220.21,222.29,9767400,222.29
+2005-04-29,221.91,222.25,217.82,220.00,9170200,220.00
+2005-04-28,219.50,222.08,217.71,219.45,8682800,219.45
+2005-04-27,217.99,220.85,216.74,219.78,10264800,219.78
+2005-04-26,220.22,222.00,218.29,218.75,17272000,218.75
+2005-04-25,217.82,224.74,217.52,223.53,19840000,223.53
+2005-04-22,222.90,224.00,214.26,215.81,33205100,215.81
+2005-04-21,200.42,205.00,199.32,204.22,17751900,204.22
+2005-04-20,198.58,200.50,195.91,198.10,15451500,198.10
+2005-04-19,189.33,192.00,188.03,191.40,8430000,191.40
+2005-04-18,184.58,187.88,183.49,186.97,6550300,186.97
+2005-04-15,190.10,190.34,184.66,185.00,11577400,185.00
+2005-04-14,193.27,194.36,190.10,191.45,6152700,191.45
+2005-04-13,193.47,194.32,189.73,192.93,6555800,192.93
+2005-04-12,193.00,194.42,189.41,193.96,7319600,193.96
+2005-04-11,193.09,194.80,192.32,193.23,5410500,193.23
+2005-04-08,193.69,195.10,191.45,192.05,5116600,192.05
+2005-04-07,188.78,194.62,188.64,193.76,9692200,193.76
+2005-04-06,189.24,189.65,187.58,189.22,5252600,189.22
+2005-04-05,187.73,190.26,187.57,188.57,8736700,188.57
+2005-04-04,179.95,185.32,179.84,185.29,8076400,185.29
+2005-04-01,181.76,182.95,179.99,180.04,6182000,180.04
+2005-03-31,177.95,181.39,177.64,180.51,6768600,180.51
+2005-03-30,180.64,181.45,179.60,180.45,6236100,180.45
+2005-03-29,181.05,183.28,178.07,179.57,6473000,179.57
+2005-03-28,181.68,184.80,180.95,181.42,8738000,181.42
+2005-03-24,180.70,180.86,179.20,179.25,3705200,179.25
+2005-03-23,177.97,180.24,177.97,178.98,4845000,178.98
+2005-03-22,181.18,181.94,177.85,178.60,5631700,178.60
+2005-03-21,179.27,182.17,177.25,180.88,7483700,180.88
+2005-03-18,178.81,180.40,178.31,180.04,7090000,180.04
+2005-03-17,177.13,179.64,175.80,179.29,8260600,179.29
+2005-03-16,176.70,178.61,175.01,175.60,7106300,175.60
+2005-03-15,175.30,180.00,174.21,178.61,10422100,178.61
+2005-03-14,178.33,178.40,172.57,174.99,11146600,174.99
+2005-03-11,180.44,180.95,177.15,177.80,8028300,177.80
+2005-03-10,181.01,181.20,177.40,179.98,10960500,179.98
+2005-03-09,184.21,184.65,180.16,181.35,11360400,181.35
+2005-03-08,189.10,189.85,184.97,185.20,8046100,185.20
+2005-03-07,187.78,189.60,187.03,188.81,8667400,188.81
+2005-03-04,186.70,187.25,185.07,185.90,6774100,185.90
+2005-03-03,186.13,187.75,184.31,187.01,7608600,187.01
+2005-03-02,185.95,187.67,184.36,185.18,7285500,185.18
+2005-03-01,189.29,189.75,182.00,186.06,9311200,186.06
+2005-02-28,186.00,189.87,185.85,187.99,7818400,187.99
+2005-02-25,189.15,189.92,185.51,185.87,9973500,185.87
+2005-02-24,183.37,189.85,182.23,188.89,25814300,188.89
+2005-02-23,193.30,194.48,188.66,193.95,15586000,193.95
+2005-02-22,196.50,198.90,190.39,191.37,13483700,191.37
+2005-02-18,198.51,198.84,196.66,197.95,8485900,197.95
+2005-02-17,197.83,199.75,196.81,197.90,10414400,197.90
+2005-02-16,194.70,199.33,194.30,198.41,16532300,198.41
+2005-02-15,193.60,199.84,193.08,195.23,25782800,195.23
+2005-02-14,182.85,193.08,181.00,192.99,38562200,192.99
+2005-02-11,186.66,192.32,186.07,187.40,13116000,187.40
+2005-02-10,191.97,192.21,185.25,187.98,18982700,187.98
+2005-02-09,200.76,201.60,189.46,191.58,17171500,191.58
+2005-02-08,196.96,200.02,194.53,198.64,11480000,198.64
+2005-02-07,205.26,206.40,195.51,196.03,12960400,196.03
+2005-02-04,206.47,207.75,202.60,204.36,14819300,204.36
+2005-02-03,205.99,213.37,205.81,210.86,12988100,210.86
+2005-02-02,215.55,216.80,203.66,205.96,32799300,205.96
+2005-02-01,194.38,196.66,190.63,191.90,18839000,191.90
+2005-01-31,193.69,196.36,191.72,195.62,9596700,195.62
+2005-01-28,190.02,194.70,186.34,190.34,12208200,190.34
+2005-01-27,188.76,188.86,185.20,188.08,6627400,188.08
+2005-01-26,179.27,189.41,179.15,189.24,12307900,189.24
+2005-01-25,181.94,182.24,176.29,177.12,10659200,177.12
+2005-01-24,188.69,189.33,180.32,180.72,14022700,180.72
+2005-01-21,194.54,195.36,188.12,188.28,9258400,188.28
+2005-01-20,192.50,196.25,192.00,193.92,9001600,193.92
+2005-01-19,204.65,205.30,196.71,197.30,11257700,197.30
+2005-01-18,200.97,205.02,198.66,203.90,13172600,203.90
+2005-01-14,196.00,200.01,194.13,199.97,9640300,199.97
+2005-01-13,195.38,197.39,194.05,195.33,6849400,195.33
+2005-01-12,194.33,195.93,190.50,195.38,8177800,195.38
+2005-01-11,195.62,197.71,193.18,193.54,6958700,193.54
+2005-01-10,194.50,198.10,191.83,195.06,7539600,195.06
+2005-01-07,190.64,194.25,188.78,193.85,9662900,193.85
+2005-01-06,195.08,195.90,187.72,188.55,10387100,188.55
+2005-01-05,193.45,196.90,192.23,193.51,8236600,193.51
+2005-01-04,201.40,202.93,193.48,194.50,13755900,194.50
+2005-01-03,197.40,203.64,195.46,202.71,15844200,202.71
diff --git a/dojox/charting/tests/data/msft_prices.csv b/dojox/charting/tests/data/msft_prices.csv
new file mode 100644
index 0000000..a0c1e90
--- /dev/null
+++ b/dojox/charting/tests/data/msft_prices.csv
@@ -0,0 +1,796 @@
+Date,Open,High,Low,Close,Volume,Adj Close
+2008-02-29,27.69,27.83,27.02,27.20,117394000,27.20
+2008-02-28,28.02,28.27,27.80,27.93,83002900,27.93
+2008-02-27,28.19,28.68,28.10,28.26,75187200,28.26
+2008-02-26,27.74,28.86,27.67,28.38,108923500,28.38
+2008-02-25,27.65,28.24,27.48,27.84,109945200,27.84
+2008-02-22,28.24,28.39,27.20,27.68,125705400,27.68
+2008-02-21,28.62,28.96,27.96,28.10,98776500,28.10
+2008-02-20,28.15,28.26,27.92,28.22,92830000,28.22
+2008-02-19,28.80,28.84,28.07,28.17,68261200,28.17
+2008-02-15,28.31,28.64,28.25,28.42,68166100,28.31
+2008-02-14,28.88,29.04,28.46,28.50,68191600,28.39
+2008-02-13,28.62,29.05,28.53,28.96,88986200,28.85
+2008-02-12,28.43,28.62,28.11,28.34,84365900,28.23
+2008-02-11,28.52,28.61,27.91,28.21,156814100,28.10
+2008-02-08,28.29,29.08,28.24,28.56,124872000,28.45
+2008-02-07,28.34,28.78,27.90,28.12,164964900,28.01
+2008-02-06,29.28,29.35,28.29,28.52,138315600,28.41
+2008-02-05,29.91,29.94,28.89,29.07,137534100,28.96
+2008-02-04,30.49,30.72,30.11,30.19,119998600,30.07
+2008-02-01,31.06,33.25,30.25,30.45,291138900,30.33
+2008-01-31,31.91,32.74,31.72,32.60,103642200,32.47
+2008-01-30,32.56,32.80,32.05,32.20,106432600,32.08
+2008-01-29,32.85,32.89,32.35,32.60,68023000,32.47
+2008-01-28,33.02,33.10,32.42,32.72,81019000,32.59
+2008-01-25,34.90,35.00,32.87,32.94,196992300,32.81
+2008-01-24,32.35,33.36,32.12,33.25,155640400,33.12
+2008-01-23,31.48,32.05,31.04,31.93,137597400,31.81
+2008-01-22,31.54,32.53,31.50,31.96,108521400,31.84
+2008-01-18,33.16,34.00,32.97,33.01,117062000,32.88
+2008-01-17,33.54,33.80,32.97,33.11,94247800,32.98
+2008-01-16,33.42,33.65,32.51,33.23,120778500,33.10
+2008-01-15,34.03,34.38,34.00,34.00,61606200,33.87
+2008-01-14,34.46,34.57,34.08,34.39,52792200,34.26
+2008-01-11,34.14,34.24,33.72,33.91,55187900,33.78
+2008-01-10,34.35,34.50,33.78,34.33,72446000,34.20
+2008-01-09,33.36,34.54,33.35,34.44,74305500,34.31
+2008-01-08,34.71,34.71,33.40,33.45,79148300,33.32
+2008-01-07,34.55,34.80,34.25,34.61,80164300,34.48
+2008-01-04,35.19,35.20,34.09,34.38,72090800,34.25
+2008-01-03,35.22,35.65,34.86,35.37,49599600,35.23
+2008-01-02,35.79,35.96,35.00,35.22,63004200,35.08
+2007-12-31,35.90,35.99,35.52,35.60,35229700,35.46
+2007-12-28,36.10,36.23,35.67,36.12,33447200,35.98
+2007-12-27,36.35,36.55,35.94,35.97,33311100,35.83
+2007-12-26,36.41,36.64,36.26,36.61,30252400,36.47
+2007-12-24,36.13,36.72,36.05,36.58,29622600,36.44
+2007-12-21,35.90,36.06,35.75,36.06,83240500,35.92
+2007-12-20,35.29,35.79,35.08,35.52,59345000,35.38
+2007-12-19,34.69,35.14,34.38,34.79,58469100,34.66
+2007-12-18,34.64,35.00,34.21,34.74,52791800,34.61
+2007-12-17,35.03,35.13,34.36,34.39,58121200,34.26
+2007-12-14,35.05,35.84,35.01,35.31,71126200,35.17
+2007-12-13,34.48,35.45,34.28,35.22,73913200,35.08
+2007-12-12,34.61,35.09,33.93,34.47,63345400,34.34
+2007-12-11,34.73,34.99,33.93,34.10,55070700,33.97
+2007-12-10,34.64,34.95,34.47,34.76,36083500,34.63
+2007-12-07,34.61,34.70,34.22,34.53,40771000,34.40
+2007-12-06,34.26,34.61,33.87,34.55,49209700,34.42
+2007-12-05,33.14,34.52,33.03,34.15,84894700,34.02
+2007-12-04,32.74,33.24,32.63,32.77,54801500,32.64
+2007-12-03,33.50,33.64,32.68,32.92,61770600,32.79
+2007-11-30,33.92,34.12,33.19,33.60,71027800,33.47
+2007-11-29,33.58,33.93,33.31,33.59,53633600,33.46
+2007-11-28,33.38,33.89,32.90,33.70,88585000,33.57
+2007-11-27,33.27,33.60,32.68,33.06,84178400,32.93
+2007-11-26,34.09,34.37,32.93,32.97,80335000,32.84
+2007-11-23,34.36,34.44,33.71,34.11,33467200,33.98
+2007-11-21,34.40,34.73,34.18,34.23,89518700,34.10
+2007-11-20,34.23,34.97,34.10,34.58,100009400,34.45
+2007-11-19,33.96,34.24,33.87,33.96,63000300,33.83
+2007-11-16,33.86,34.26,33.71,34.09,71113800,33.96
+2007-11-15,33.76,34.10,33.55,33.76,63111200,33.63
+2007-11-14,34.62,34.75,33.75,33.93,83840100,33.80
+2007-11-13,33.54,34.67,33.38,34.46,104261100,34.33
+2007-11-12,33.32,33.71,33.02,33.38,84719000,33.14
+2007-11-09,34.18,34.54,33.65,33.73,125111400,33.49
+2007-11-08,35.60,35.90,34.40,34.74,133742400,34.49
+2007-11-07,36.04,36.16,35.45,35.52,74873600,35.27
+2007-11-06,36.59,36.66,35.87,36.41,100966700,36.15
+2007-11-05,36.76,37.10,36.63,36.73,75485400,36.47
+2007-11-02,37.22,37.50,36.42,37.06,96389800,36.79
+2007-11-01,36.53,37.49,36.36,37.06,152078800,36.79
+2007-10-31,35.52,37.00,35.51,36.81,185635800,36.55
+2007-10-30,34.37,35.59,34.35,35.57,107297300,35.32
+2007-10-29,34.85,35.29,34.45,34.57,114655600,34.32
+2007-10-26,36.01,36.03,34.56,35.03,287270900,34.78
+2007-10-25,31.57,32.22,31.49,31.99,169588700,31.76
+2007-10-24,30.85,31.30,30.50,31.25,77979200,31.03
+2007-10-23,30.71,31.12,30.71,30.90,49956200,30.68
+2007-10-22,30.12,30.70,30.12,30.51,58785100,30.29
+2007-10-19,31.09,31.09,30.11,30.17,75200200,29.95
+2007-10-18,31.22,31.23,30.63,31.16,49208600,30.94
+2007-10-17,30.75,31.23,30.65,31.08,86092400,30.86
+2007-10-16,30.24,30.58,30.23,30.32,56286200,30.10
+2007-10-15,30.10,30.33,30.00,30.04,47150500,29.83
+2007-10-12,30.03,30.40,29.95,30.17,31121100,29.95
+2007-10-11,30.30,30.63,29.79,29.91,50788400,29.70
+2007-10-10,30.04,30.37,30.03,30.23,32251500,30.01
+2007-10-09,30.03,30.39,30.00,30.10,63603100,29.88
+2007-10-08,29.66,29.85,29.60,29.84,30265400,29.63
+2007-10-05,29.89,29.99,29.73,29.84,45012300,29.63
+2007-10-04,29.56,29.77,29.44,29.71,37868000,29.50
+2007-10-03,29.71,29.85,29.29,29.45,37633900,29.24
+2007-10-02,29.70,29.85,29.57,29.70,33700900,29.49
+2007-10-01,29.46,29.79,29.41,29.77,43875100,29.56
+2007-09-28,29.49,29.69,29.23,29.46,45819100,29.25
+2007-09-27,29.70,29.72,29.44,29.49,43407100,29.28
+2007-09-26,29.68,29.85,29.48,29.50,60337000,29.29
+2007-09-25,29.14,29.56,29.11,29.56,75621000,29.35
+2007-09-24,28.81,29.61,28.80,29.08,104459800,28.87
+2007-09-21,28.69,28.81,28.44,28.65,135636100,28.45
+2007-09-20,28.48,28.58,28.34,28.42,67168900,28.22
+2007-09-19,28.87,28.91,28.30,28.67,94242200,28.46
+2007-09-18,28.70,28.97,28.27,28.93,77462400,28.72
+2007-09-17,28.79,28.88,28.62,28.73,39536500,28.52
+2007-09-14,28.98,29.11,28.88,29.04,33496600,28.83
+2007-09-13,29.12,29.26,28.96,29.16,35288600,28.95
+2007-09-12,28.81,29.17,28.80,28.93,42364700,28.72
+2007-09-11,28.63,28.95,28.58,28.93,34380800,28.72
+2007-09-10,28.67,28.75,28.41,28.48,37247600,28.28
+2007-09-07,28.62,28.83,28.32,28.44,52160900,28.24
+2007-09-06,28.56,29.01,28.55,28.91,45430800,28.70
+2007-09-05,28.65,28.73,28.42,28.48,47669800,28.28
+2007-09-04,28.50,29.10,28.48,28.81,45689600,28.60
+2007-08-31,28.70,28.92,28.36,28.73,42511900,28.52
+2007-08-30,28.42,28.93,28.32,28.45,33690700,28.25
+2007-08-29,28.13,28.61,27.82,28.59,45753700,28.39
+2007-08-28,28.30,28.49,27.91,27.93,43924400,27.73
+2007-08-27,28.61,28.77,28.40,28.49,32789500,28.29
+2007-08-24,28.21,28.84,28.07,28.81,45158900,28.60
+2007-08-23,28.28,28.33,28.10,28.30,33886600,28.10
+2007-08-22,28.27,28.32,28.01,28.22,44763500,28.02
+2007-08-21,28.10,28.32,27.87,28.07,50786200,27.87
+2007-08-20,28.18,28.49,28.08,28.26,49952000,28.06
+2007-08-17,28.09,28.25,27.82,28.25,76747700,28.05
+2007-08-16,27.88,28.35,27.51,27.81,81447400,27.61
+2007-08-15,28.24,28.99,28.05,28.10,48117700,27.90
+2007-08-14,28.77,28.89,28.20,28.27,42944100,28.07
+2007-08-13,28.94,28.99,28.44,28.63,55492300,28.33
+2007-08-10,28.90,29.05,28.26,28.71,76576200,28.41
+2007-08-09,29.64,30.10,28.92,29.30,72964500,28.99
+2007-08-08,29.72,30.01,29.21,30.00,52898600,29.68
+2007-08-07,29.33,29.79,29.05,29.55,49163000,29.24
+2007-08-06,29.05,29.54,28.75,29.54,59530500,29.23
+2007-08-03,29.45,29.78,28.90,28.96,61535500,28.65
+2007-08-02,29.19,29.79,29.02,29.52,47938300,29.21
+2007-08-01,28.95,29.55,28.82,29.30,80006300,28.99
+2007-07-31,29.71,29.72,28.98,28.99,66554000,28.68
+2007-07-30,29.41,29.49,28.95,29.40,67499600,29.09
+2007-07-27,29.93,30.00,29.36,29.39,69214600,29.08
+2007-07-26,30.24,30.53,29.51,29.98,87025300,29.66
+2007-07-25,30.99,31.30,30.37,30.71,54950100,30.38
+2007-07-24,31.01,31.48,30.71,30.80,59729300,30.47
+2007-07-23,31.36,31.52,31.12,31.19,48910600,30.86
+2007-07-20,31.15,31.20,30.79,31.16,98292600,30.83
+2007-07-19,31.05,31.84,30.93,31.51,121159300,31.18
+2007-07-18,30.51,30.97,30.50,30.92,64414400,30.59
+2007-07-17,30.02,30.88,30.01,30.78,77539600,30.45
+2007-07-16,29.76,30.24,29.72,30.03,48023200,29.71
+2007-07-13,29.94,30.02,29.66,29.82,42173000,29.50
+2007-07-12,29.56,30.11,29.44,30.07,54302400,29.75
+2007-07-11,29.24,29.65,29.21,29.49,48017000,29.18
+2007-07-10,29.70,29.99,29.18,29.33,66013500,29.02
+2007-07-09,29.86,29.95,29.81,29.87,33831400,29.55
+2007-07-06,29.91,30.04,29.66,29.97,57541000,29.65
+2007-07-05,30.05,30.22,29.83,29.99,47838500,29.67
+2007-07-03,29.79,30.22,29.78,30.02,35202600,29.70
+2007-07-02,29.67,29.80,29.49,29.74,47316000,29.42
+2007-06-29,29.87,29.93,29.04,29.47,71193900,29.16
+2007-06-28,29.86,29.97,29.68,29.83,46055200,29.51
+2007-06-27,29.36,29.95,29.36,29.87,53468600,29.55
+2007-06-26,29.55,29.80,29.50,29.52,48340300,29.21
+2007-06-25,29.47,29.77,29.38,29.49,53905800,29.18
+2007-06-22,30.00,30.10,29.45,29.49,86219900,29.18
+2007-06-21,29.98,30.30,29.91,30.22,56564800,29.90
+2007-06-20,30.44,30.51,29.96,30.01,46861600,29.69
+2007-06-19,30.48,30.66,30.38,30.46,46802600,30.14
+2007-06-18,30.69,30.72,30.42,30.51,45412600,30.19
+2007-06-15,30.86,30.88,30.43,30.49,100933000,30.17
+2007-06-14,30.35,30.71,30.30,30.52,59065700,30.20
+2007-06-13,29.97,30.41,29.85,30.39,64435600,30.07
+2007-06-12,29.96,30.24,29.77,29.85,56981800,29.53
+2007-06-11,29.94,30.25,29.93,30.02,48467400,29.70
+2007-06-08,29.58,30.06,29.41,30.05,61346200,29.73
+2007-06-07,30.02,30.29,29.59,29.62,71971400,29.31
+2007-06-06,30.37,30.53,30.25,30.29,38217500,29.97
+2007-06-05,30.62,30.63,30.33,30.58,44265000,30.26
+2007-06-04,30.42,30.76,30.40,30.72,41434500,30.39
+2007-06-01,30.79,30.90,30.55,30.59,39469400,30.27
+2007-05-31,31.12,31.16,30.61,30.69,85290500,30.36
+2007-05-30,30.55,31.13,30.51,31.11,57376800,30.78
+2007-05-29,30.49,30.83,30.39,30.79,42373100,30.46
+2007-05-25,30.28,30.66,30.18,30.48,47726500,30.16
+2007-05-24,30.54,30.80,29.96,30.17,64046400,29.85
+2007-05-23,30.84,30.84,30.57,30.58,46322500,30.26
+2007-05-22,30.90,30.93,30.66,30.69,39999500,30.36
+2007-05-21,30.73,31.16,30.73,31.05,41836400,30.72
+2007-05-18,30.97,30.99,30.58,30.83,58453000,30.50
+2007-05-17,31.03,31.14,30.96,30.98,41045600,30.65
+2007-05-16,31.00,31.09,30.81,31.07,45833600,30.74
+2007-05-15,30.90,31.09,30.84,30.90,75013900,30.57
+2007-05-14,30.84,30.99,30.81,30.97,70188500,30.54
+2007-05-11,30.57,30.98,30.55,30.89,43425300,30.46
+2007-05-10,30.68,30.93,30.53,30.58,55398600,30.16
+2007-05-09,30.70,30.93,30.57,30.78,51735000,30.35
+2007-05-08,30.68,30.94,30.58,30.75,60551700,30.33
+2007-05-07,30.52,30.76,30.48,30.71,59889100,30.29
+2007-05-04,30.68,30.70,30.29,30.56,104385900,30.14
+2007-05-03,30.60,31.00,30.53,30.97,82036800,30.54
+2007-05-02,30.39,30.69,30.30,30.61,80686700,30.19
+2007-05-01,29.94,30.42,29.90,30.40,73539300,29.98
+2007-04-30,30.13,30.37,29.94,29.94,67788800,29.53
+2007-04-27,30.17,30.74,30.00,30.12,128298800,29.70
+2007-04-26,29.09,29.35,28.91,29.10,68760300,28.70
+2007-04-25,28.86,29.00,28.69,28.99,39475000,28.59
+2007-04-24,28.79,28.96,28.59,28.79,34236700,28.39
+2007-04-23,28.96,28.99,28.67,28.78,41739100,28.38
+2007-04-20,28.98,29.10,28.70,29.02,60311500,28.62
+2007-04-19,28.34,28.89,28.26,28.69,43648800,28.29
+2007-04-18,28.61,28.67,28.36,28.60,41778400,28.20
+2007-04-17,28.63,28.89,28.56,28.85,33170200,28.45
+2007-04-16,28.60,28.75,28.21,28.73,30740100,28.33
+2007-04-13,28.43,28.70,28.10,28.61,36002900,28.21
+2007-04-12,28.06,28.62,28.04,28.54,43762100,28.15
+2007-04-11,28.30,28.57,27.99,28.11,44050200,27.72
+2007-04-10,28.50,28.64,28.22,28.40,38643100,28.01
+2007-04-09,28.58,28.72,28.39,28.57,31384600,28.18
+2007-04-05,28.32,28.65,28.30,28.55,30131200,28.16
+2007-04-04,28.01,28.78,27.90,28.50,63244200,28.11
+2007-04-03,27.86,28.06,27.75,27.87,39821300,27.48
+2007-04-02,27.89,27.93,27.56,27.74,41977600,27.36
+2007-03-30,27.75,27.95,27.50,27.87,47061000,27.48
+2007-03-29,27.84,27.85,27.49,27.75,42629900,27.37
+2007-03-28,27.58,28.00,27.40,27.64,46947000,27.26
+2007-03-27,28.04,28.16,27.65,27.72,58979800,27.34
+2007-03-26,27.94,28.22,27.70,28.22,47491500,27.83
+2007-03-23,28.22,28.27,27.80,28.02,50519800,27.63
+2007-03-22,28.52,28.55,28.01,28.27,47934900,27.88
+2007-03-21,27.90,28.52,27.56,28.52,72808200,28.13
+2007-03-20,27.93,28.16,27.76,27.84,47902400,27.46
+2007-03-19,27.34,27.83,27.20,27.83,49412000,27.45
+2007-03-16,27.35,27.48,27.20,27.33,65055300,26.95
+2007-03-15,27.32,27.47,27.20,27.28,51757100,26.90
+2007-03-14,26.82,27.40,26.73,27.40,75730300,27.02
+2007-03-13,27.25,27.40,26.71,26.72,75169500,26.35
+2007-03-12,27.18,27.48,27.13,27.44,36516400,27.06
+2007-03-09,27.42,27.48,27.03,27.29,80125000,26.91
+2007-03-08,27.72,27.85,26.60,27.32,72175200,26.94
+2007-03-07,27.76,27.90,27.55,27.61,52044700,27.23
+2007-03-06,27.80,27.94,27.65,27.83,49361800,27.45
+2007-03-05,27.49,27.91,27.41,27.55,56454300,27.17
+2007-03-02,28.02,28.16,27.76,27.76,63254700,27.38
+2007-03-01,27.82,28.33,27.73,28.09,80175700,27.70
+2007-02-28,27.95,28.25,27.92,28.17,86333300,27.78
+2007-02-27,28.71,28.97,27.79,27.87,87143300,27.48
+2007-02-26,28.96,29.09,28.82,29.07,63481900,28.67
+2007-02-23,29.22,29.28,28.89,28.90,63787100,28.50
+2007-02-22,29.31,29.54,29.16,29.39,57754400,28.98
+2007-02-21,28.75,29.39,28.74,29.35,68604900,28.94
+2007-02-20,28.63,28.86,28.47,28.83,53978200,28.43
+2007-02-16,28.91,28.94,28.65,28.74,109340300,28.34
+2007-02-15,29.58,29.65,29.22,29.46,63858100,29.05
+2007-02-14,29.17,29.69,29.15,29.40,55588600,28.99
+2007-02-13,29.04,29.20,28.96,29.01,50348100,28.61
+2007-02-12,28.89,29.09,28.83,28.94,52774400,28.44
+2007-02-09,29.35,29.40,28.93,28.98,69823100,28.48
+2007-02-08,29.24,29.80,29.20,29.26,48749000,28.76
+2007-02-07,29.64,29.70,29.25,29.37,65145500,28.86
+2007-02-06,29.59,29.75,29.22,29.51,79281100,29.00
+2007-02-05,29.97,30.02,29.41,29.61,99102100,29.10
+2007-02-02,30.82,30.84,30.13,30.19,60401700,29.67
+2007-02-01,30.84,30.94,30.37,30.56,55355800,30.03
+2007-01-31,30.41,31.10,30.35,30.86,73968400,30.33
+2007-01-30,30.57,30.64,30.14,30.48,61900400,29.96
+2007-01-29,30.65,30.78,30.34,30.53,57605900,30.00
+2007-01-26,31.22,31.23,30.60,30.60,96103700,30.07
+2007-01-25,31.08,31.48,30.45,30.45,97378700,29.93
+2007-01-24,30.78,31.30,30.65,31.09,58527800,30.55
+2007-01-23,30.63,30.96,30.52,30.74,49171200,30.21
+2007-01-22,31.06,31.12,30.51,30.72,56143900,30.19
+2007-01-19,30.73,31.11,30.69,31.11,75826900,30.57
+2007-01-18,31.15,31.37,30.80,31.00,56364300,30.47
+2007-01-17,31.26,31.44,31.01,31.10,58519600,30.56
+2007-01-16,31.26,31.45,31.03,31.16,62379600,30.62
+2007-01-12,30.65,31.39,30.64,31.21,103972500,30.67
+2007-01-11,29.76,30.75,29.65,30.70,99464300,30.17
+2007-01-10,29.80,29.89,29.43,29.66,55017400,29.15
+2007-01-09,30.00,30.18,29.73,29.96,44636600,29.44
+2007-01-08,29.65,30.10,29.53,29.93,50220200,29.41
+2007-01-05,29.63,29.75,29.45,29.64,44607200,29.13
+2007-01-04,29.70,29.97,29.44,29.81,45774500,29.30
+2007-01-03,29.91,30.25,29.40,29.86,76935100,29.35
+2006-12-29,29.86,30.15,29.83,29.86,41739800,29.35
+2006-12-28,29.86,30.03,29.81,29.98,26690600,29.46
+2006-12-27,29.99,30.13,29.91,30.02,31248400,29.50
+2006-12-26,29.53,30.00,29.40,29.99,37098300,29.47
+2006-12-22,29.83,29.86,29.62,29.64,37971700,29.13
+2006-12-21,30.13,30.14,29.89,29.98,32270500,29.46
+2006-12-20,29.99,30.24,29.97,30.09,31202100,29.57
+2006-12-19,29.71,30.17,29.53,29.99,53822100,29.47
+2006-12-18,30.19,30.26,29.78,29.89,56986800,29.38
+2006-12-15,30.14,30.23,30.03,30.19,102783700,29.67
+2006-12-14,29.54,30.08,29.52,30.07,85866500,29.55
+2006-12-13,29.60,29.60,29.32,29.55,46002500,29.04
+2006-12-12,29.56,29.63,29.22,29.43,68529400,28.92
+2006-12-11,29.19,29.75,29.11,29.54,107712000,29.03
+2006-12-08,28.82,29.40,28.80,29.40,108854900,28.89
+2006-12-07,28.96,29.07,28.81,28.85,46831100,28.35
+2006-12-06,29.10,29.13,28.87,28.99,48564100,28.49
+2006-12-05,29.36,29.40,29.03,29.13,45606000,28.63
+2006-12-04,29.23,29.52,29.17,29.33,55123400,28.82
+2006-12-01,29.23,29.30,28.90,29.12,72257000,28.62
+2006-11-30,29.42,29.57,29.33,29.36,53297400,28.85
+2006-11-29,29.44,29.78,29.43,29.57,58775100,29.06
+2006-11-28,29.34,29.42,29.13,29.39,52602300,28.88
+2006-11-27,29.69,29.74,29.33,29.48,72722100,28.97
+2006-11-24,29.66,29.84,29.64,29.76,20456700,29.25
+2006-11-22,29.97,30.00,29.82,29.92,43907200,29.40
+2006-11-21,29.91,30.00,29.79,29.92,66446600,29.40
+2006-11-20,29.52,30.00,29.50,29.89,85703800,29.38
+2006-11-17,29.31,29.54,29.28,29.40,49356700,28.89
+2006-11-16,29.14,29.64,29.13,29.47,64328500,28.96
+2006-11-15,29.13,29.36,29.11,29.12,63943200,28.62
+2006-11-14,29.28,29.42,29.07,29.23,63012500,28.73
+2006-11-13,29.19,29.46,29.16,29.35,47271800,28.75
+2006-11-10,29.17,29.29,29.15,29.24,37855100,28.64
+2006-11-09,29.11,29.40,29.00,29.26,89407500,28.66
+2006-11-08,28.78,29.23,28.66,28.98,77403300,28.38
+2006-11-07,28.86,29.07,28.80,28.95,56511200,28.35
+2006-11-06,28.77,29.05,28.76,28.84,60446200,28.25
+2006-11-03,28.85,28.93,28.61,28.73,41124500,28.14
+2006-11-02,28.71,28.86,28.58,28.77,58674400,28.18
+2006-11-01,28.78,28.99,28.70,28.81,75895900,28.22
+2006-10-31,28.66,28.85,28.56,28.71,61861700,28.12
+2006-10-30,28.35,28.84,28.32,28.53,47296800,27.94
+2006-10-27,28.49,28.79,28.25,28.34,89060100,27.76
+2006-10-26,28.33,28.41,28.04,28.35,69964200,27.77
+2006-10-25,28.28,28.46,28.14,28.31,40717100,27.73
+2006-10-24,28.43,28.43,28.13,28.28,61409600,27.70
+2006-10-23,28.30,28.69,28.18,28.45,48525000,27.86
+2006-10-20,28.48,28.49,28.17,28.43,48887800,27.85
+2006-10-19,28.35,28.45,28.12,28.29,44730800,27.71
+2006-10-18,28.50,28.70,28.26,28.52,40630800,27.93
+2006-10-17,28.24,28.51,28.17,28.44,40122600,27.85
+2006-10-16,28.48,28.60,28.33,28.45,49744800,27.86
+2006-10-13,28.34,28.69,28.31,28.37,129751900,27.79
+2006-10-12,27.58,28.29,27.54,28.22,120174900,27.64
+2006-10-11,27.46,27.67,27.42,27.54,37219600,26.97
+2006-10-10,27.69,27.75,27.44,27.69,34598500,27.12
+2006-10-09,27.80,27.93,27.62,27.72,33366300,27.15
+2006-10-06,27.76,28.00,27.65,27.87,36452200,27.30
+2006-10-05,27.92,28.11,27.78,27.92,81967200,27.35
+2006-10-04,27.39,27.96,27.37,27.94,82191200,27.37
+2006-10-03,27.37,27.48,27.21,27.37,39386200,26.81
+2006-10-02,27.32,27.49,27.15,27.36,52908100,26.80
+2006-09-29,27.35,27.42,27.21,27.35,34283500,26.79
+2006-09-28,27.47,27.52,27.26,27.40,44179700,26.84
+2006-09-27,27.18,27.47,27.12,27.44,66233900,26.88
+2006-09-26,26.91,27.32,26.88,27.20,54766500,26.64
+2006-09-25,26.81,27.19,26.79,26.95,67903900,26.40
+2006-09-22,26.83,26.85,26.48,26.66,47712500,26.11
+2006-09-21,27.24,27.25,26.85,26.90,58495100,26.35
+2006-09-20,27.01,27.23,26.99,27.18,71676400,26.62
+2006-09-19,26.74,26.94,26.72,26.86,43039100,26.31
+2006-09-18,26.74,27.04,26.67,26.79,49135000,26.24
+2006-09-15,26.58,26.94,26.49,26.85,126057700,26.30
+2006-09-14,25.99,26.50,25.98,26.33,74324500,25.79
+2006-09-13,25.82,26.10,25.82,25.98,37706700,25.45
+2006-09-12,25.90,25.98,25.72,25.93,52248800,25.40
+2006-09-11,25.43,25.95,25.42,25.91,55608200,25.38
+2006-09-08,25.53,25.79,25.46,25.60,36866800,25.07
+2006-09-07,25.48,25.70,25.39,25.43,51266900,24.91
+2006-09-06,25.51,25.72,25.51,25.61,50160400,25.08
+2006-09-05,25.69,25.96,25.56,25.61,44222400,25.08
+2006-09-01,25.89,25.97,25.64,25.84,31594600,25.31
+2006-08-31,25.87,25.98,25.68,25.70,26380500,25.17
+2006-08-30,25.85,25.89,25.64,25.80,30283100,25.27
+2006-08-29,25.92,25.98,25.63,25.84,42711200,25.31
+2006-08-28,25.84,26.00,25.69,25.95,34190900,25.42
+2006-08-25,25.71,26.00,25.69,25.85,33115900,25.32
+2006-08-24,25.82,25.86,25.50,25.74,35933300,25.21
+2006-08-23,25.65,25.95,25.52,25.67,44648500,25.14
+2006-08-22,26.01,26.25,25.62,25.62,89312400,25.09
+2006-08-21,25.66,26.13,25.56,26.12,88398300,25.58
+2006-08-18,25.05,25.80,24.98,25.79,128414800,25.26
+2006-08-17,24.70,24.75,24.61,24.70,45674800,24.19
+2006-08-16,24.61,24.73,24.47,24.70,52373600,24.19
+2006-08-15,24.55,24.65,24.44,24.62,48994500,24.11
+2006-08-14,24.52,24.60,24.35,24.53,47831900,23.94
+2006-08-11,24.43,24.45,24.20,24.43,30255500,23.84
+2006-08-10,24.37,24.60,24.34,24.46,31753400,23.87
+2006-08-09,24.49,24.64,24.34,24.44,44405700,23.85
+2006-08-08,24.39,24.52,24.20,24.34,58171300,23.75
+2006-08-07,24.28,24.48,24.19,24.22,36862400,23.63
+2006-08-04,24.40,24.49,24.15,24.29,45690400,23.70
+2006-08-03,24.19,24.48,24.15,24.21,43155300,23.62
+2006-08-02,24.12,24.40,24.03,24.30,46462000,23.71
+2006-08-01,24.02,24.20,23.85,23.99,49168700,23.41
+2006-07-31,24.07,24.42,24.01,24.06,40254400,23.48
+2006-07-28,24.08,24.28,24.06,24.25,51705800,23.66
+2006-07-27,24.58,24.60,23.77,23.87,85386800,23.29
+2006-07-26,24.12,24.53,24.10,24.37,54942100,23.78
+2006-07-25,24.00,24.29,23.90,24.22,60075800,23.63
+2006-07-24,24.01,24.11,23.79,24.00,59586700,23.42
+2006-07-21,24.08,24.15,23.00,23.87,175483800,23.29
+2006-07-20,23.44,23.45,22.78,22.85,76605200,22.30
+2006-07-19,22.82,23.46,22.72,23.40,82188200,22.83
+2006-07-18,22.59,22.76,22.48,22.74,65047300,22.19
+2006-07-17,22.29,22.61,22.26,22.48,37053500,21.94
+2006-07-14,22.28,22.55,22.23,22.29,67499400,21.75
+2006-07-13,22.37,22.61,22.25,22.26,73099500,21.72
+2006-07-12,22.79,22.88,22.62,22.64,77379300,22.09
+2006-07-11,23.37,23.37,22.74,23.10,88676300,22.54
+2006-07-10,23.43,23.66,23.38,23.50,50565100,22.93
+2006-07-07,23.39,23.55,23.30,23.30,63168800,22.74
+2006-07-06,23.45,23.61,23.42,23.48,44775200,22.91
+2006-07-05,23.48,23.52,23.30,23.35,53093500,22.79
+2006-07-03,23.53,23.72,23.45,23.70,25711400,23.13
+2006-06-30,23.54,23.65,23.30,23.30,73048800,22.74
+2006-06-29,23.32,23.63,23.22,23.47,121395500,22.90
+2006-06-28,22.96,23.25,22.91,23.16,71906500,22.60
+2006-06-27,22.89,23.16,22.84,22.86,84759100,22.31
+2006-06-26,22.65,22.89,22.63,22.82,53644100,22.27
+2006-06-23,22.85,22.87,22.50,22.50,60532600,21.96
+2006-06-22,23.06,23.17,22.78,22.88,76590600,22.33
+2006-06-21,22.61,23.15,22.53,23.08,91660300,22.52
+2006-06-20,22.54,22.76,22.50,22.56,90598500,22.01
+2006-06-19,22.14,22.60,22.12,22.55,129640900,22.01
+2006-06-16,21.97,22.28,21.79,22.10,147506500,21.57
+2006-06-15,22.01,22.13,21.80,22.07,121577300,21.54
+2006-06-14,21.59,21.94,21.55,21.88,86081500,21.35
+2006-06-13,21.73,22.03,21.46,21.51,113175300,20.99
+2006-06-12,21.96,22.10,21.70,21.71,74309700,21.19
+2006-06-09,22.15,22.19,21.89,21.92,52573800,21.39
+2006-06-08,22.03,22.21,21.97,22.11,104126900,21.58
+2006-06-07,22.15,22.39,22.01,22.04,73827500,21.51
+2006-06-06,22.55,22.56,21.98,22.13,126601300,21.60
+2006-06-05,22.72,22.73,22.49,22.50,63914100,21.96
+2006-06-02,22.87,22.99,22.67,22.76,73935600,22.21
+2006-06-01,22.74,22.84,22.62,22.82,80230800,22.27
+2006-05-31,23.26,23.35,22.65,22.65,120202000,22.10
+2006-05-30,23.55,23.76,23.14,23.15,52497500,22.59
+2006-05-26,23.77,23.88,23.56,23.72,46861600,23.15
+2006-05-25,23.57,23.92,23.54,23.74,83052700,23.17
+2006-05-24,22.99,23.54,22.98,23.50,107356700,22.93
+2006-05-23,23.11,23.38,22.77,22.79,79986300,22.24
+2006-05-22,22.48,23.02,22.45,22.88,87322300,22.33
+2006-05-19,22.79,22.90,22.52,22.56,100071200,22.01
+2006-05-18,22.84,23.14,22.76,22.83,95476400,22.28
+2006-05-17,22.89,23.08,22.73,22.73,98598300,22.18
+2006-05-16,23.16,24.00,22.91,23.01,82095100,22.45
+2006-05-15,23.10,23.23,23.03,23.15,67314800,22.59
+2006-05-12,23.14,23.37,23.05,23.17,83115900,22.52
+2006-05-11,23.71,23.79,23.15,23.22,92916700,22.57
+2006-05-10,23.67,23.79,23.59,23.77,76563300,23.11
+2006-05-09,23.75,24.00,23.49,23.62,75345900,22.96
+2006-05-08,23.85,25.00,23.51,23.73,80693500,23.07
+2006-05-05,23.66,23.95,23.52,23.80,131604300,23.13
+2006-05-04,23.35,23.67,23.14,23.44,171257400,22.78
+2006-05-03,23.99,24.02,23.15,23.17,211527100,22.52
+2006-05-02,24.49,25.00,23.90,24.01,190533500,23.34
+2006-05-01,24.32,25.00,24.09,24.29,174800900,23.61
+2006-04-28,24.23,24.50,24.00,24.15,591052200,23.47
+2006-04-27,26.97,27.63,26.94,27.25,96509600,26.49
+2006-04-26,27.08,27.23,27.00,27.10,39190000,26.34
+2006-04-25,27.09,27.21,27.02,27.11,49222500,26.35
+2006-04-24,27.07,27.25,26.98,27.11,42318400,26.35
+2006-04-21,27.05,27.39,27.00,27.15,58528000,26.39
+2006-04-20,27.05,27.19,26.70,27.03,45648300,26.27
+2006-04-19,27.11,27.19,26.96,27.03,45111100,26.27
+2006-04-18,26.94,27.50,26.82,27.22,56272700,26.46
+2006-04-17,27.03,27.05,26.73,26.84,35796200,26.09
+2006-04-13,27.08,27.20,27.00,27.07,28160000,26.31
+2006-04-12,27.10,27.20,26.97,27.20,32183000,26.44
+2006-04-11,27.29,27.32,27.00,27.13,42953400,26.37
+2006-04-10,27.23,27.44,27.20,27.29,39432000,26.53
+2006-04-07,27.61,27.72,27.23,27.25,47249400,26.49
+2006-04-06,27.66,27.72,27.37,27.56,51885500,26.79
+2006-04-05,27.88,27.94,27.64,27.74,41539300,26.96
+2006-04-04,27.60,27.80,27.47,27.64,45470000,26.87
+2006-04-03,27.67,27.73,27.44,27.56,57605300,26.79
+2006-03-31,27.30,27.54,27.21,27.21,62190500,26.45
+2006-03-30,27.03,27.39,27.00,27.23,54612000,26.47
+2006-03-29,26.95,27.20,26.92,27.02,53150300,26.26
+2006-03-28,27.01,27.21,26.81,26.90,58520500,26.15
+2006-03-27,27.01,27.30,27.00,27.01,59908600,26.25
+2006-03-24,26.71,27.21,26.62,27.01,69157600,26.25
+2006-03-23,27.08,27.10,26.66,26.85,73682900,26.10
+2006-03-22,27.08,27.50,26.80,27.15,145696100,26.39
+2006-03-21,27.74,28.22,27.68,27.74,73199600,26.96
+2006-03-20,27.70,27.99,27.67,27.89,67094100,27.11
+2006-03-17,27.35,27.66,27.27,27.50,120615000,26.73
+2006-03-16,27.34,27.48,27.22,27.27,73793700,26.51
+2006-03-15,27.20,27.45,27.01,27.36,57152000,26.60
+2006-03-14,27.04,27.38,26.99,27.23,39821800,26.47
+2006-03-13,27.18,27.29,26.94,27.11,40342600,26.35
+2006-03-10,27.06,27.22,26.88,27.17,41297200,26.41
+2006-03-09,27.27,27.42,27.00,27.00,45360700,26.25
+2006-03-08,26.99,27.50,26.97,27.25,57547400,26.49
+2006-03-07,26.90,27.10,26.81,27.06,51613900,26.30
+2006-03-06,26.92,27.15,26.83,26.91,53054100,26.16
+2006-03-03,26.81,27.16,26.74,26.93,45218800,26.18
+2006-03-02,27.02,27.10,26.90,26.97,41850300,26.22
+2006-03-01,26.98,27.20,26.95,27.14,53061200,26.38
+2006-02-28,26.95,27.30,26.87,26.87,65036100,26.12
+2006-02-27,26.75,27.26,26.67,27.05,51301500,26.29
+2006-02-24,26.59,26.74,26.52,26.63,44753800,25.89
+2006-02-23,26.73,26.89,26.54,26.66,47359100,25.91
+2006-02-22,26.53,26.86,26.47,26.72,43043100,25.97
+2006-02-21,26.72,26.72,26.34,26.54,50216100,25.80
+2006-02-17,26.67,26.81,26.56,26.70,41513200,25.95
+2006-02-16,26.85,26.90,26.57,26.81,48868500,26.06
+2006-02-15,26.60,26.93,26.50,26.88,62808900,26.13
+2006-02-14,26.41,26.68,26.35,26.65,58432900,25.82
+2006-02-13,26.63,26.70,26.34,26.39,46707000,25.57
+2006-02-10,26.62,26.89,26.51,26.69,52127000,25.86
+2006-02-09,26.96,27.03,26.65,26.66,52861700,25.83
+2006-02-08,27.01,27.08,26.71,26.91,51795200,26.07
+2006-02-07,26.95,27.15,26.81,26.94,72159500,26.10
+2006-02-06,27.51,27.54,27.09,27.17,60170500,26.32
+2006-02-03,27.48,27.70,27.34,27.54,75022700,26.68
+2006-02-02,27.97,27.99,27.55,27.68,55073400,26.82
+2006-02-01,27.96,28.07,27.76,28.04,68448800,27.16
+2006-01-31,27.91,28.38,27.87,28.15,94841300,27.27
+2006-01-30,27.82,28.18,27.78,28.00,103999200,27.13
+2006-01-27,27.23,27.95,27.19,27.79,134520700,26.92
+2006-01-26,26.56,26.72,26.31,26.50,69509300,25.67
+2006-01-25,26.41,26.57,26.23,26.40,59072100,25.58
+2006-01-24,26.34,26.45,26.22,26.28,63040700,25.46
+2006-01-23,26.41,26.53,26.30,26.35,47925600,25.53
+2006-01-20,27.01,27.01,26.26,26.41,79165900,25.58
+2006-01-19,26.87,27.24,26.85,27.02,60367600,26.18
+2006-01-18,26.74,26.98,26.70,26.83,52376200,25.99
+2006-01-17,26.90,27.19,26.90,26.99,58566600,26.15
+2006-01-13,27.03,27.25,27.01,27.19,41418000,26.34
+2006-01-12,27.25,27.26,26.97,27.14,45994800,26.29
+2006-01-11,27.01,27.39,26.90,27.29,70120700,26.44
+2006-01-10,26.65,27.02,26.59,27.00,64921900,26.16
+2006-01-09,26.93,27.07,26.76,26.86,55625000,26.02
+2006-01-06,26.89,27.00,26.49,26.91,100963000,26.07
+2006-01-05,26.96,27.13,26.91,26.99,48245500,26.15
+2006-01-04,26.77,27.08,26.77,26.97,57975600,26.13
+2006-01-03,26.25,27.00,26.10,26.84,79973000,26.00
+2005-12-30,26.15,26.31,26.10,26.15,49044600,25.33
+2005-12-29,26.41,26.50,26.26,26.27,34495500,25.45
+2005-12-28,26.51,26.66,26.35,26.39,35444400,25.57
+2005-12-27,26.68,26.85,26.45,26.46,37819000,25.63
+2005-12-23,26.52,26.67,26.44,26.64,30689200,25.81
+2005-12-22,26.71,26.78,26.42,26.59,91276900,25.76
+2005-12-21,26.87,26.91,26.71,26.73,75800900,25.89
+2005-12-20,26.76,26.88,26.67,26.86,62960600,26.02
+2005-12-19,26.82,26.87,26.65,26.83,68680100,25.99
+2005-12-16,26.88,27.08,26.81,26.90,88542500,26.06
+2005-12-15,27.08,27.11,26.81,26.92,79018100,26.08
+2005-12-14,27.00,27.24,26.85,27.09,65076200,26.24
+2005-12-13,27.29,27.43,27.00,27.13,104285500,26.28
+2005-12-12,27.70,27.75,27.33,27.45,63757200,26.59
+2005-12-09,27.71,27.83,27.64,27.71,48467000,26.84
+2005-12-08,27.71,27.81,27.60,27.69,63931600,26.83
+2005-12-07,27.67,27.75,27.55,27.75,55583200,26.88
+2005-12-06,27.90,27.92,27.68,27.69,65980000,26.83
+2005-12-05,27.93,28.02,27.71,27.85,47517300,26.98
+2005-12-02,27.82,28.10,27.79,28.01,42319600,27.14
+2005-12-01,27.73,28.10,27.73,27.89,61006100,27.02
+2005-11-30,27.68,27.77,27.63,27.68,55904700,26.82
+2005-11-29,27.79,27.79,27.60,27.68,62220400,26.82
+2005-11-28,27.79,27.85,27.53,27.75,57517200,26.88
+2005-11-25,27.80,27.94,27.47,27.76,44082500,26.89
+2005-11-23,27.92,28.09,27.74,27.92,70541300,27.05
+2005-11-22,28.06,28.08,27.86,27.91,104253300,27.04
+2005-11-21,28.07,28.24,27.84,28.16,65794400,27.28
+2005-11-18,28.12,28.25,27.90,28.07,75431200,27.19
+2005-11-17,27.85,28.00,27.76,27.97,91351000,27.10
+2005-11-16,27.48,27.88,27.44,27.74,86277000,26.87
+2005-11-15,27.33,27.54,27.25,27.50,65081000,26.64
+2005-11-14,27.36,27.44,27.20,27.37,67152200,26.44
+2005-11-11,27.15,27.39,27.13,27.28,51945600,26.35
+2005-11-10,26.94,27.15,26.64,27.09,73314800,26.17
+2005-11-09,26.98,27.15,26.94,26.96,59562100,26.04
+2005-11-08,26.94,27.18,26.77,27.05,60091700,26.13
+2005-11-07,26.72,27.08,26.70,27.01,77104800,26.09
+2005-11-04,26.53,26.71,26.45,26.66,57464000,25.75
+2005-11-03,26.60,26.64,26.25,26.44,73421600,25.54
+2005-11-02,25.93,26.50,25.93,26.46,75067100,25.56
+2005-11-01,25.61,26.10,25.61,25.96,71370400,25.08
+2005-10-31,25.61,25.80,25.50,25.70,75122100,24.82
+2005-10-28,25.10,25.60,25.10,25.53,106559300,24.66
+2005-10-27,25.22,25.27,24.85,24.85,61566100,24.00
+2005-10-26,24.97,25.33,24.93,25.11,58178100,24.25
+2005-10-25,24.95,25.13,24.83,25.03,41310500,24.18
+2005-10-24,24.89,25.10,24.68,25.10,51868000,24.24
+2005-10-21,24.91,25.00,24.57,24.78,69431200,23.94
+2005-10-20,25.05,25.13,24.74,24.79,58830600,23.95
+2005-10-19,24.56,25.09,24.50,25.09,66574500,24.24
+2005-10-18,24.49,24.83,24.45,24.57,69328200,23.73
+2005-10-17,24.68,24.69,24.44,24.53,46924400,23.69
+2005-10-14,24.71,24.73,24.50,24.67,53846700,23.83
+2005-10-13,24.31,24.73,24.27,24.59,70192000,23.75
+2005-10-12,24.49,24.70,24.27,24.30,71294400,23.47
+2005-10-11,24.51,24.55,24.25,24.41,76567300,23.58
+2005-10-10,24.67,24.68,24.35,24.46,48880900,23.63
+2005-10-07,24.77,24.84,24.52,24.59,50768700,23.75
+2005-10-06,24.66,24.95,24.53,24.73,81724600,23.89
+2005-10-05,25.04,25.05,24.67,24.67,73684700,23.83
+2005-10-04,25.36,25.39,24.75,24.98,151666300,24.13
+2005-10-03,25.71,25.73,25.44,25.50,55341300,24.63
+2005-09-30,25.91,25.95,25.61,25.73,57644500,24.85
+2005-09-29,25.61,26.00,25.50,25.94,66807100,25.06
+2005-09-28,25.39,25.87,25.38,25.67,71019400,24.80
+2005-09-27,25.37,25.45,25.30,25.34,48797900,24.48
+2005-09-26,25.40,25.49,25.21,25.27,56203700,24.41
+2005-09-23,25.31,25.54,25.12,25.27,66396800,24.41
+2005-09-22,25.49,25.60,25.15,25.34,71314900,24.48
+2005-09-21,25.80,25.90,25.43,25.49,68281800,24.62
+2005-09-20,26.07,26.22,25.69,25.84,61043400,24.96
+2005-09-19,26.09,26.27,25.86,26.00,61832300,25.11
+2005-09-16,26.34,26.40,25.97,26.07,187384300,25.18
+2005-09-15,26.37,26.43,26.22,26.27,60357200,25.37
+2005-09-14,26.52,26.64,26.30,26.31,54969600,25.41
+2005-09-13,26.54,26.76,26.37,26.48,63422900,25.58
+2005-09-12,26.62,26.75,26.52,26.61,40550500,25.70
+2005-09-09,26.62,26.82,26.53,26.58,41515800,25.67
+2005-09-08,26.80,26.88,26.52,26.61,52552300,25.70
+2005-09-07,26.94,27.11,26.82,26.85,44656100,25.94
+2005-09-06,27.06,27.29,26.98,27.00,46089000,26.08
+2005-09-02,27.21,27.27,26.97,27.02,52047500,26.10
+2005-09-01,27.38,27.39,27.15,27.20,75974500,26.27
+2005-08-31,27.17,27.44,27.04,27.38,65210200,26.45
+2005-08-30,27.06,27.23,26.96,27.18,55163200,26.25
+2005-08-29,26.81,27.23,26.81,27.15,52307700,26.22
+2005-08-26,27.06,27.08,26.87,26.97,36774600,26.05
+2005-08-25,26.90,27.09,26.85,27.03,39306300,26.11
+2005-08-24,26.84,27.16,26.78,26.81,63645000,25.90
+2005-08-23,26.84,27.07,26.74,26.87,48296700,25.95
+2005-08-22,26.79,27.17,26.77,26.91,41691700,25.99
+2005-08-19,26.85,26.91,26.70,26.72,36043500,25.81
+2005-08-18,26.89,27.08,26.80,26.82,40861900,25.91
+2005-08-17,26.82,27.15,26.66,26.95,52413100,26.03
+2005-08-16,27.03,27.14,26.70,26.74,46894600,25.83
+2005-08-15,26.98,27.30,26.69,27.13,45976600,26.21
+2005-08-12,27.08,27.14,26.90,27.05,52006500,26.05
+2005-08-11,26.98,27.30,26.89,27.27,48646800,26.26
+2005-08-10,27.41,27.50,26.85,26.95,62818800,25.95
+2005-08-09,27.22,27.51,27.01,27.35,64761800,26.34
+2005-08-08,27.80,27.84,27.08,27.13,77207200,26.13
+2005-08-05,27.29,27.94,27.25,27.76,82212400,26.73
+2005-08-04,27.16,27.50,27.05,27.32,91461400,26.31
+2005-08-03,26.76,27.43,26.73,27.25,139422400,26.24
+2005-08-02,25.90,26.90,25.87,26.81,137510100,25.82
+2005-08-01,25.81,26.05,25.76,25.92,61346800,24.96
+2005-07-29,25.78,26.00,25.59,25.61,59524400,24.66
+2005-07-28,25.75,25.85,25.66,25.75,44738700,24.80
+2005-07-27,25.61,25.80,25.53,25.72,57977300,24.77
+2005-07-26,25.72,25.74,25.53,25.54,51476400,24.60
+2005-07-25,25.69,25.90,25.65,25.69,45174600,24.74
+2005-07-22,25.99,26.34,25.63,25.68,97558900,24.73
+2005-07-21,26.30,26.48,26.00,26.44,112932100,25.46
+2005-07-20,26.00,26.23,25.88,26.19,71424800,25.22
+2005-07-19,25.79,26.25,25.75,26.16,113290100,25.19
+2005-07-18,25.71,25.79,25.55,25.55,39668000,24.61
+2005-07-15,26.04,26.10,25.75,25.79,56472800,24.84
+2005-07-14,25.79,26.10,25.79,25.97,69506800,25.01
+2005-07-13,25.53,25.75,25.48,25.66,44749200,24.71
+2005-07-12,25.24,25.62,25.20,25.61,63384800,24.66
+2005-07-11,25.15,25.38,25.11,25.29,61525400,24.36
+2005-07-08,24.64,25.12,24.63,25.09,56104000,24.16
+2005-07-07,24.58,24.71,24.50,24.65,80082900,23.74
+2005-07-06,24.97,25.08,24.69,24.70,64214600,23.79
+2005-07-05,24.66,25.19,24.62,24.98,61883500,24.06
+2005-07-01,24.85,24.99,24.67,24.71,69718400,23.80
+2005-06-30,25.06,25.14,24.82,24.84,82018200,23.92
+2005-06-29,25.22,25.32,25.00,25.09,55859900,24.16
+2005-06-28,25.09,25.20,25.03,25.07,53058100,24.14
+2005-06-27,25.07,25.25,25.03,25.05,61636200,24.12
+2005-06-24,25.22,25.40,25.04,25.04,57970700,24.12
+2005-06-23,25.17,25.62,25.15,25.31,105159800,24.38
+2005-06-22,25.11,25.26,25.03,25.07,60492700,24.14
+2005-06-21,25.08,25.19,25.04,25.15,81084000,24.22
+2005-06-20,24.98,25.28,24.93,25.11,50538900,24.18
+2005-06-17,25.27,25.29,24.92,25.04,90821300,24.12
+2005-06-16,25.22,25.23,24.95,25.04,65918800,24.12
+2005-06-15,25.40,25.41,25.11,25.26,50764800,24.33
+2005-06-14,25.31,25.44,25.24,25.36,44243300,24.42
+2005-06-13,25.36,25.49,25.26,25.31,49104100,24.38
+2005-06-10,25.49,25.52,25.34,25.43,39459800,24.49
+2005-06-09,25.40,25.61,25.35,25.51,52767900,24.57
+2005-06-08,25.55,25.62,25.34,25.40,45369700,24.46
+2005-06-07,25.33,25.83,25.31,25.51,54511400,24.57
+2005-06-06,25.38,25.50,25.31,25.37,40756900,24.43
+2005-06-03,25.70,25.81,25.34,25.43,79659500,24.49
+2005-06-02,25.71,25.86,25.64,25.79,27212500,24.84
+2005-06-01,25.73,26.00,25.61,25.81,54621000,24.86
+2005-05-31,25.99,26.03,25.75,25.80,46131100,24.85
+2005-05-27,25.83,26.09,25.81,26.07,54978000,25.11
+2005-05-26,25.75,26.00,25.73,25.90,50579200,24.94
+2005-05-25,25.68,25.77,25.50,25.71,35749000,24.76
+2005-05-24,25.80,25.88,25.72,25.75,61287700,24.80
+2005-05-23,25.74,26.07,25.74,25.85,75421100,24.90
+2005-05-20,25.88,25.92,25.73,25.74,64444500,24.79
+2005-05-19,25.75,26.05,25.70,25.92,52120800,24.96
+2005-05-18,25.50,25.84,25.42,25.70,71182400,24.75
+2005-05-17,25.31,25.50,25.25,25.46,39983200,24.52
+2005-05-16,25.23,25.50,25.19,25.49,50577300,24.55
+2005-05-13,25.03,25.38,24.99,25.30,77204300,24.29
+2005-05-12,24.84,25.11,24.83,25.00,74540700,24.00
+2005-05-11,24.89,24.97,24.64,24.91,59463300,23.91
+2005-05-10,25.04,25.08,24.82,24.90,62235100,23.90
+2005-05-09,25.23,25.33,25.05,25.11,61872400,24.11
+2005-05-06,25.33,25.48,25.19,25.22,64322600,24.21
+2005-05-05,25.20,25.33,25.08,25.23,59362300,24.22
+2005-05-04,25.34,25.40,25.11,25.21,86864200,24.20
+2005-05-03,25.13,25.40,25.09,25.36,67867800,24.35
+2005-05-02,25.23,25.36,24.95,25.23,54376700,24.22
+2005-04-29,24.88,25.30,24.79,25.30,98641200,24.29
+2005-04-28,24.82,24.92,24.44,24.45,83623100,23.47
+2005-04-27,24.66,25.15,24.63,24.99,47732800,23.99
+2005-04-26,24.95,25.25,24.74,24.76,60464300,23.77
+2005-04-25,25.07,25.28,24.86,24.99,75457900,23.99
+2005-04-22,25.05,25.25,24.78,24.98,80087500,23.98
+2005-04-21,24.48,25.39,24.47,25.28,93562300,24.27
+2005-04-20,24.66,24.70,24.30,24.32,91923500,23.35
+2005-04-19,24.71,24.80,24.45,24.63,65956200,23.65
+2005-04-18,24.45,24.84,24.40,24.65,75766400,23.66
+2005-04-15,24.58,24.90,24.41,24.46,100251600,23.48
+2005-04-14,25.01,25.14,24.83,24.84,66754400,23.85
+2005-04-13,25.23,25.45,24.99,25.04,60929300,24.04
+2005-04-12,24.92,25.35,24.80,25.32,67517800,24.31
+2005-04-11,25.03,25.11,24.86,24.97,47791800,23.97
+2005-04-08,25.07,25.25,24.91,24.94,47956300,23.94
+2005-04-07,24.66,25.13,24.63,25.10,77451500,24.10
+2005-04-06,24.47,24.94,24.45,24.67,78020200,23.68
+2005-04-05,24.22,24.50,24.12,24.47,73549600,23.49
+2005-04-04,24.11,24.26,23.94,24.23,62196400,23.26
+2005-04-01,24.24,24.35,24.10,24.12,64619600,23.16
+2005-03-31,24.25,24.31,24.12,24.17,62382300,23.20
+2005-03-30,24.04,24.19,24.00,24.16,59585700,23.19
+2005-03-29,24.14,24.24,23.82,23.92,74231700,22.96
+2005-03-28,24.40,24.47,24.18,24.20,49802000,23.23
+2005-03-24,24.24,24.47,24.20,24.28,78820900,23.31
+2005-03-23,23.99,24.39,23.96,24.18,79293300,23.21
+2005-03-22,24.19,24.27,23.96,23.99,102113300,23.03
+2005-03-21,24.35,24.36,24.15,24.20,71446200,23.23
+2005-03-18,24.53,24.91,24.28,24.31,135904000,23.34
+2005-03-17,24.64,24.68,24.53,24.54,60573200,23.56
+2005-03-16,24.82,24.97,24.56,24.63,74841400,23.65
+2005-03-15,25.10,25.24,24.89,24.91,71469400,23.91
+2005-03-14,25.08,25.15,24.96,25.11,65550500,24.11
+2005-03-11,25.45,25.48,25.06,25.09,60617900,24.09
+2005-03-10,25.43,25.48,25.25,25.43,59132900,24.41
+2005-03-09,25.39,25.57,25.28,25.31,62991800,24.30
+2005-03-08,25.40,25.62,25.34,25.40,52871800,24.38
+2005-03-07,25.17,25.79,25.16,25.47,80407400,24.45
+2005-03-04,25.21,25.30,25.13,25.17,63058200,24.16
+2005-03-03,25.30,25.31,25.14,25.17,52183600,24.16
+2005-03-02,25.19,25.48,25.16,25.26,67739000,24.25
+2005-03-01,25.19,25.41,25.13,25.28,56394800,24.27
+2005-02-28,25.22,25.37,25.13,25.16,82728000,24.15
+2005-02-25,25.33,25.38,25.15,25.25,62467700,24.24
+2005-02-24,25.18,25.44,25.15,25.37,85236300,24.36
+2005-02-23,25.24,25.35,25.17,25.20,83689400,24.19
+2005-02-22,25.25,25.49,25.20,25.23,96419200,24.22
+2005-02-18,25.64,25.65,25.40,25.48,77091100,24.46
+2005-02-17,25.71,25.86,25.60,25.65,67024800,24.62
+2005-02-16,25.87,25.93,25.67,25.79,57506600,24.76
+2005-02-15,26.00,26.08,25.86,25.93,76551600,24.89
+2005-02-14,25.93,26.12,25.91,26.01,58694000,24.89
+2005-02-11,26.03,26.12,25.81,25.97,83835900,24.86
+2005-02-10,26.10,26.13,26.00,26.06,71796400,24.94
+2005-02-09,26.25,26.31,26.04,26.07,77874800,24.95
+2005-02-08,26.19,26.34,26.16,26.24,61343700,25.11
+2005-02-07,26.27,26.30,26.06,26.16,57763400,25.04
+2005-02-04,26.17,26.37,26.14,26.32,61246500,25.19
+2005-02-03,26.37,26.40,26.10,26.18,62545400,25.06
+2005-02-02,26.42,26.50,26.28,26.46,79329500,25.32
+2005-02-01,26.25,26.43,26.22,26.39,57981700,25.26
+2005-01-31,26.35,26.52,26.16,26.28,71442100,25.15
+2005-01-28,26.54,26.65,25.96,26.18,110466500,25.06
+2005-01-27,25.95,26.16,25.85,26.11,93204100,24.99
+2005-01-26,26.07,26.17,25.90,26.01,64974500,24.89
+2005-01-25,25.76,26.19,25.75,26.02,67580700,24.90
+2005-01-24,25.76,26.00,25.64,25.67,69010900,24.57
+2005-01-21,25.95,26.13,25.64,25.65,76501000,24.55
+2005-01-20,25.84,26.10,25.74,25.86,58380100,24.75
+2005-01-19,26.21,26.26,25.92,25.98,58114100,24.86
+2005-01-18,26.03,26.35,25.84,26.32,69146400,25.19
+2005-01-14,26.40,26.45,26.04,26.12,92180800,25.00
+2005-01-13,26.68,26.80,26.16,26.27,89861600,25.14
+2005-01-12,26.77,26.85,26.62,26.78,72940600,25.63
+2005-01-11,26.69,26.82,26.61,26.73,64712000,25.58
+2005-01-10,26.60,26.86,26.54,26.80,70376600,25.65
+2005-01-07,26.82,26.89,26.62,26.67,68723300,25.53
+2005-01-06,26.85,27.06,26.64,26.75,76890500,25.60
+2005-01-05,26.84,27.10,26.76,26.78,72463500,25.63
+2005-01-04,26.87,27.10,26.66,26.84,109442100,25.69
+2005-01-03,26.80,26.95,26.65,26.74,65002900,25.59
diff --git a/dojox/charting/tests/data/yahoo_prices.csv b/dojox/charting/tests/data/yahoo_prices.csv
new file mode 100644
index 0000000..261889b
--- /dev/null
+++ b/dojox/charting/tests/data/yahoo_prices.csv
@@ -0,0 +1,796 @@
+Date,Open,High,Low,Close,Volume,Adj Close
+2008-02-29,27.94,28.41,27.50,27.78,23860500,27.78
+2008-02-28,27.98,28.82,27.96,28.15,30113200,28.15
+2008-02-27,28.33,28.49,27.75,28.37,27664100,28.37
+2008-02-26,27.93,28.55,27.81,28.22,26013000,28.22
+2008-02-25,28.42,28.57,27.75,28.13,32470600,28.13
+2008-02-22,28.36,28.64,27.98,28.42,26157800,28.42
+2008-02-21,28.76,29.17,28.25,28.42,34494000,28.42
+2008-02-20,28.71,29.04,28.39,28.83,29274700,28.83
+2008-02-19,29.34,29.42,28.75,29.01,38679600,29.01
+2008-02-15,29.95,30.15,29.43,29.66,40125200,29.66
+2008-02-14,29.98,30.25,29.75,29.98,38045600,29.98
+2008-02-13,29.78,30.07,29.60,29.88,57047700,29.88
+2008-02-12,29.81,29.84,29.40,29.57,42445600,29.57
+2008-02-11,29.89,30.05,29.32,29.87,67253700,29.87
+2008-02-08,28.98,29.22,28.71,29.20,55618900,29.20
+2008-02-07,28.63,29.19,28.60,29.04,44248800,29.04
+2008-02-06,29.11,29.33,28.53,28.57,55648800,28.57
+2008-02-05,28.78,29.57,28.75,28.98,68583700,28.98
+2008-02-04,28.33,29.50,28.33,29.33,144814000,29.33
+2008-02-01,28.68,29.83,27.34,28.38,438248800,28.38
+2008-01-31,18.87,19.35,18.72,19.18,41449800,19.18
+2008-01-30,18.62,20.81,18.58,19.05,115993300,19.05
+2008-01-29,20.87,20.90,20.05,20.81,79230000,20.81
+2008-01-28,21.56,21.90,20.42,20.78,32473100,20.78
+2008-01-25,22.24,22.37,21.32,21.94,28386800,21.94
+2008-01-24,20.44,21.75,20.42,21.69,39823300,21.69
+2008-01-23,19.25,20.34,18.72,20.01,42064200,20.01
+2008-01-22,19.29,21.03,19.26,19.86,38126200,19.86
+2008-01-18,21.27,21.61,20.07,20.78,41239300,20.78
+2008-01-17,22.00,22.17,21.14,21.22,28812600,21.22
+2008-01-16,22.20,22.75,21.73,21.95,38155300,21.95
+2008-01-15,23.00,23.49,22.57,22.91,31911000,22.91
+2008-01-14,23.51,23.76,23.18,23.70,18552900,23.70
+2008-01-11,23.81,24.13,22.98,23.36,27297400,23.36
+2008-01-10,23.19,24.57,22.83,24.09,52342100,24.09
+2008-01-09,22.47,22.80,21.37,22.56,46662700,22.56
+2008-01-08,23.28,23.65,22.50,22.61,22974000,22.61
+2008-01-07,23.12,23.56,22.73,23.18,24769400,23.18
+2008-01-04,23.81,23.81,23.10,23.16,20745800,23.16
+2008-01-03,23.86,24.19,23.70,23.84,20179700,23.84
+2008-01-02,23.80,24.15,23.60,23.72,25671700,23.72
+2007-12-31,23.22,23.43,23.11,23.26,14782600,23.26
+2007-12-28,23.66,23.71,23.21,23.45,13773000,23.45
+2007-12-27,23.60,24.15,23.57,23.71,16041500,23.71
+2007-12-26,23.85,24.25,23.85,23.96,9821600,23.96
+2007-12-24,24.01,24.19,23.94,24.05,24861800,24.05
+2007-12-21,23.88,24.10,23.74,24.01,24094600,24.01
+2007-12-20,23.50,23.80,23.24,23.64,21030700,23.64
+2007-12-19,22.92,23.69,22.92,23.31,26547300,23.31
+2007-12-18,23.22,23.35,22.80,23.02,27735600,23.02
+2007-12-17,23.80,24.03,22.94,23.04,37877100,23.04
+2007-12-14,24.13,24.47,24.00,24.06,15125500,24.06
+2007-12-13,24.39,24.75,24.19,24.38,23787400,24.38
+2007-12-12,24.82,25.00,24.11,24.54,20241200,24.54
+2007-12-11,25.15,25.65,24.36,24.47,28579100,24.47
+2007-12-10,25.51,25.57,24.92,25.20,26074900,25.20
+2007-12-07,25.86,26.11,25.50,25.63,11443200,25.63
+2007-12-06,25.88,26.02,25.39,25.96,19236500,25.96
+2007-12-05,26.63,26.73,25.73,25.98,21170900,25.98
+2007-12-04,26.14,26.73,26.11,26.42,14668800,26.42
+2007-12-03,26.64,27.20,26.56,26.61,15250100,26.61
+2007-11-30,26.96,27.33,26.51,26.81,23994000,26.81
+2007-11-29,26.01,26.71,25.91,26.63,17929700,26.63
+2007-11-28,26.03,26.70,25.93,26.20,23239300,26.20
+2007-11-27,25.18,26.00,25.17,25.59,19484500,25.59
+2007-11-26,26.08,26.25,25.20,25.22,24174600,25.22
+2007-11-23,25.98,26.40,25.76,26.13,9249400,26.13
+2007-11-21,26.11,26.58,25.52,25.71,23320100,25.71
+2007-11-20,26.93,27.25,25.98,26.72,25672500,26.72
+2007-11-19,27.11,27.35,26.35,26.76,33066200,26.76
+2007-11-16,25.66,27.13,25.10,26.82,53013100,26.82
+2007-11-15,24.94,25.75,24.90,25.42,27920800,25.42
+2007-11-14,26.42,26.44,25.00,25.07,38154800,25.07
+2007-11-13,25.53,26.24,25.30,26.10,34123300,26.10
+2007-11-12,25.80,26.20,24.69,24.78,31264200,24.78
+2007-11-09,26.13,26.38,25.40,25.79,45199700,25.79
+2007-11-08,28.11,28.24,25.82,26.70,58160600,26.70
+2007-11-07,29.27,29.30,27.56,27.63,57069800,27.63
+2007-11-06,31.76,31.79,29.00,29.93,63664400,29.93
+2007-11-05,30.71,32.37,30.35,31.36,43520300,31.36
+2007-11-02,30.54,31.21,29.64,31.11,34090300,31.11
+2007-11-01,30.86,31.10,30.04,30.22,26913300,30.22
+2007-10-31,31.50,31.75,30.50,31.10,34762000,31.10
+2007-10-30,31.55,31.64,30.12,30.83,52417300,30.83
+2007-10-29,34.07,34.08,31.18,31.79,83685800,31.79
+2007-10-26,32.43,33.99,31.61,33.63,66018100,33.63
+2007-10-25,30.75,31.62,30.50,31.34,38706600,31.34
+2007-10-24,30.68,30.98,30.00,30.68,33603100,30.68
+2007-10-23,30.12,30.88,30.03,30.64,45406200,30.64
+2007-10-22,28.93,30.00,28.80,29.85,27750100,29.85
+2007-10-19,29.36,29.96,28.85,29.03,41933000,29.03
+2007-10-18,28.59,29.60,28.47,29.35,28152200,29.35
+2007-10-17,29.10,29.20,28.00,28.82,75067700,28.82
+2007-10-16,27.37,27.48,26.55,26.69,56275300,26.69
+2007-10-15,28.32,28.40,27.46,27.86,22994100,27.86
+2007-10-12,27.76,28.51,27.65,28.48,22130500,28.48
+2007-10-11,28.44,28.68,27.50,27.65,25298300,27.65
+2007-10-10,28.43,28.70,27.90,28.36,14847100,28.36
+2007-10-09,28.35,28.76,27.94,28.37,19539500,28.37
+2007-10-08,28.01,28.17,27.75,28.05,15060700,28.05
+2007-10-05,27.78,28.16,27.75,27.88,28389600,27.88
+2007-10-04,27.19,27.29,26.90,27.15,19203600,27.15
+2007-10-03,27.16,27.38,26.82,27.17,18052500,27.17
+2007-10-02,27.20,27.24,26.62,26.95,15133400,26.95
+2007-10-01,26.76,27.10,26.73,27.04,16938700,27.04
+2007-09-28,26.49,26.89,26.20,26.84,22155600,26.84
+2007-09-27,26.95,26.95,26.17,26.27,21365200,26.27
+2007-09-26,26.70,27.07,26.50,26.70,18692400,26.70
+2007-09-25,25.70,26.65,25.63,26.51,33721300,26.51
+2007-09-24,26.13,26.40,25.51,25.73,27597800,25.73
+2007-09-21,25.54,26.21,25.29,26.05,53074900,26.05
+2007-09-20,25.28,25.61,25.16,25.29,17312000,25.29
+2007-09-19,25.09,25.37,24.81,25.29,25867900,25.29
+2007-09-18,25.06,25.21,24.53,25.06,28121000,25.06
+2007-09-17,24.50,25.10,24.38,24.95,20594000,24.95
+2007-09-14,23.69,25.00,23.65,24.73,28868600,24.73
+2007-09-13,23.60,23.96,23.60,23.72,10309000,23.72
+2007-09-12,23.64,23.94,23.53,23.56,16553700,23.56
+2007-09-11,23.31,23.84,23.31,23.71,17207500,23.71
+2007-09-10,23.85,23.85,23.10,23.30,15246000,23.30
+2007-09-07,23.76,24.05,23.60,23.76,12591900,23.76
+2007-09-06,24.22,24.32,23.62,24.15,13922100,24.15
+2007-09-05,24.10,24.40,23.91,24.10,23071000,24.10
+2007-09-04,23.30,24.50,23.20,23.97,43598600,23.97
+2007-08-31,22.81,22.83,22.51,22.73,13052500,22.73
+2007-08-30,22.49,22.91,22.38,22.61,18172500,22.61
+2007-08-29,22.60,22.69,22.27,22.55,24599900,22.55
+2007-08-28,22.95,23.10,22.50,22.52,18030600,22.52
+2007-08-27,23.59,23.76,23.01,23.03,16523800,23.03
+2007-08-24,23.03,23.73,23.03,23.59,11191100,23.59
+2007-08-23,23.35,23.36,22.95,23.13,15603000,23.13
+2007-08-22,23.22,23.52,23.18,23.23,18763700,23.23
+2007-08-21,23.25,23.48,22.91,23.04,25962900,23.04
+2007-08-20,23.64,23.74,23.18,23.34,13338900,23.34
+2007-08-17,23.26,23.63,22.76,23.54,19528200,23.54
+2007-08-16,23.00,23.15,22.50,22.76,29652200,22.76
+2007-08-15,23.56,24.00,23.25,23.32,18767700,23.32
+2007-08-14,24.69,24.70,23.69,23.72,18707100,23.72
+2007-08-13,24.21,24.74,24.01,24.57,21317600,24.57
+2007-08-10,23.93,24.22,23.52,23.94,22939800,23.94
+2007-08-09,23.67,24.45,23.51,23.80,24052500,23.80
+2007-08-08,23.46,23.87,23.43,23.87,17198000,23.87
+2007-08-07,22.75,23.70,22.69,23.44,20075300,23.44
+2007-08-06,23.03,23.15,22.44,22.97,28948000,22.97
+2007-08-03,23.20,23.39,22.87,22.92,19702100,22.92
+2007-08-02,22.65,23.70,22.65,23.36,21098900,23.36
+2007-08-01,23.17,23.40,22.85,23.25,22030400,23.25
+2007-07-31,23.88,23.93,23.24,23.25,21575800,23.25
+2007-07-30,23.55,23.88,23.38,23.62,20976600,23.62
+2007-07-27,23.98,24.49,23.47,23.49,35783800,23.49
+2007-07-26,24.40,24.49,23.62,24.03,33373300,24.03
+2007-07-25,25.01,25.32,24.59,24.68,21882400,24.68
+2007-07-24,24.80,25.34,24.73,24.84,28981000,24.84
+2007-07-23,25.43,25.46,24.98,24.99,26631500,24.99
+2007-07-20,25.70,25.89,25.20,25.35,38056100,25.35
+2007-07-19,26.32,26.34,25.92,26.03,29537900,26.03
+2007-07-18,26.07,26.72,26.02,26.20,65125900,26.20
+2007-07-17,26.74,27.80,26.70,27.53,53656100,27.53
+2007-07-16,26.48,26.74,26.13,26.70,30804500,26.70
+2007-07-13,26.87,26.97,26.50,26.58,18522700,26.58
+2007-07-12,26.70,26.97,26.34,26.96,20082300,26.96
+2007-07-11,27.03,27.05,26.55,26.69,21970700,26.69
+2007-07-10,27.09,27.57,26.96,26.97,24635500,26.97
+2007-07-09,26.92,27.33,26.82,27.20,17515800,27.20
+2007-07-06,27.01,27.14,26.93,27.10,12284500,27.10
+2007-07-05,26.92,27.14,26.90,26.99,16071900,26.99
+2007-07-03,26.95,27.25,26.90,27.00,11643400,27.00
+2007-07-02,27.19,27.27,26.76,26.86,21011000,26.86
+2007-06-29,27.21,27.38,26.93,27.13,13842500,27.13
+2007-06-28,27.44,27.49,27.12,27.25,17124500,27.25
+2007-06-27,27.51,27.66,27.40,27.58,13997000,27.58
+2007-06-26,27.73,28.18,27.36,27.71,25324000,27.71
+2007-06-25,27.60,27.77,27.34,27.64,21232200,27.64
+2007-06-22,27.68,27.79,27.31,27.38,33796900,27.38
+2007-06-21,27.69,27.94,27.55,27.67,17885800,27.67
+2007-06-20,27.89,28.17,27.66,27.66,33496400,27.66
+2007-06-19,29.40,29.40,27.54,27.63,65967500,27.63
+2007-06-18,27.72,28.34,27.50,28.12,70919400,28.12
+2007-06-15,27.49,27.52,27.19,27.31,23816900,27.31
+2007-06-14,27.38,27.64,27.15,27.30,18919400,27.30
+2007-06-13,27.12,27.41,26.61,27.38,31210700,27.38
+2007-06-12,27.30,27.66,26.98,27.05,22203600,27.05
+2007-06-11,27.27,27.52,27.15,27.35,14856500,27.35
+2007-06-08,27.02,27.45,26.96,27.39,18618500,27.39
+2007-06-07,27.34,27.73,26.98,26.98,34232300,26.98
+2007-06-06,28.05,28.11,27.30,27.44,33508200,27.44
+2007-06-05,28.40,28.59,28.10,28.23,20494800,28.23
+2007-06-04,28.60,28.78,28.40,28.59,13428800,28.59
+2007-06-01,28.90,29.13,28.61,28.78,12398800,28.78
+2007-05-31,28.76,28.85,28.49,28.70,15859100,28.70
+2007-05-30,28.19,28.38,28.00,28.38,16046800,28.38
+2007-05-29,28.36,28.73,28.20,28.40,13981500,28.40
+2007-05-25,28.44,28.73,28.34,28.58,10334600,28.58
+2007-05-24,28.65,28.88,28.25,28.41,19122900,28.41
+2007-05-23,29.10,29.37,28.53,28.61,27964400,28.61
+2007-05-22,29.33,29.35,28.78,28.92,19131300,28.92
+2007-05-21,29.62,29.86,29.32,29.35,18955900,29.35
+2007-05-18,28.90,29.80,28.78,29.75,35487200,29.75
+2007-05-17,28.99,29.13,28.49,28.57,23535000,28.57
+2007-05-16,28.89,29.37,28.25,29.21,32944800,29.21
+2007-05-15,29.16,29.42,28.75,28.81,22226800,28.81
+2007-05-14,29.79,30.00,29.08,29.31,20895900,29.31
+2007-05-11,29.62,30.08,29.53,30.05,13838800,30.05
+2007-05-10,30.52,30.69,29.61,29.70,26570200,29.70
+2007-05-09,30.17,30.44,29.95,30.22,23533100,30.22
+2007-05-08,30.24,31.10,30.21,30.41,28018200,30.41
+2007-05-07,30.13,30.98,29.86,30.38,41243900,30.38
+2007-05-04,33.27,33.61,29.58,30.98,245611400,30.98
+2007-05-03,28.25,28.50,28.01,28.18,20119500,28.18
+2007-05-02,27.72,28.26,27.72,28.12,16911800,28.12
+2007-05-01,28.25,28.35,27.53,27.73,18310900,27.73
+2007-04-30,28.32,28.50,28.00,28.04,17596300,28.04
+2007-04-27,28.35,28.86,28.17,28.34,21097000,28.34
+2007-04-26,27.98,28.65,27.73,28.49,32331000,28.49
+2007-04-25,28.22,28.27,27.68,28.06,35568600,28.06
+2007-04-24,28.03,28.26,27.69,28.02,25964000,28.02
+2007-04-23,27.53,28.14,27.37,27.88,27262400,27.88
+2007-04-20,27.86,27.86,27.37,27.46,39123300,27.46
+2007-04-19,28.10,28.23,27.46,27.51,45664700,27.51
+2007-04-18,28.42,28.90,27.89,28.31,127875300,28.31
+2007-04-17,31.98,32.14,31.71,32.09,43223800,32.09
+2007-04-16,31.68,31.79,31.24,31.61,14359100,31.61
+2007-04-13,31.15,31.50,30.96,31.41,12006300,31.41
+2007-04-12,31.26,31.42,31.10,31.21,13904800,31.21
+2007-04-11,31.65,31.73,30.90,31.17,16141100,31.17
+2007-04-10,31.64,32.02,31.60,31.69,12797600,31.69
+2007-04-09,32.01,32.24,31.60,31.64,12408000,31.64
+2007-04-05,32.00,32.09,31.72,31.96,13878100,31.96
+2007-04-04,31.61,31.87,31.48,31.62,7836200,31.62
+2007-04-03,31.41,32.00,31.41,31.72,12324600,31.72
+2007-04-02,31.22,31.40,30.93,31.28,8668800,31.28
+2007-03-30,31.21,31.60,31.02,31.29,9425000,31.29
+2007-03-29,31.71,31.73,30.83,31.34,13815000,31.34
+2007-03-28,31.45,31.70,31.25,31.41,13162500,31.41
+2007-03-27,31.56,31.66,31.24,31.55,9403100,31.55
+2007-03-26,31.25,31.74,31.24,31.66,12907000,31.66
+2007-03-23,31.33,31.70,31.16,31.36,12727900,31.36
+2007-03-22,31.36,31.44,30.85,31.26,12989800,31.26
+2007-03-21,30.33,31.39,30.21,31.29,26667300,31.29
+2007-03-20,30.00,30.35,29.94,30.33,12203800,30.33
+2007-03-19,30.00,30.19,29.92,30.03,9983800,30.03
+2007-03-16,30.02,30.11,29.72,29.88,19799300,29.88
+2007-03-15,29.81,30.07,29.78,30.06,15440900,30.06
+2007-03-14,29.63,30.04,29.26,29.86,23604900,29.86
+2007-03-13,29.77,30.24,29.42,29.56,18263800,29.56
+2007-03-12,29.30,30.11,29.29,29.99,35991600,29.99
+2007-03-09,29.85,30.15,28.79,29.12,72749900,29.12
+2007-03-08,30.82,31.04,30.58,30.71,13715100,30.71
+2007-03-07,30.95,31.03,30.33,30.39,16014300,30.39
+2007-03-06,30.89,31.06,30.52,30.80,33472600,30.80
+2007-03-05,30.18,31.90,30.14,30.31,21469000,30.31
+2007-03-02,30.54,30.89,30.28,30.42,18136600,30.42
+2007-03-01,30.13,31.23,30.00,30.86,24012900,30.86
+2007-02-28,30.86,31.47,30.09,30.86,30487800,30.86
+2007-02-27,31.38,31.64,30.24,30.95,31505200,30.95
+2007-02-26,32.80,32.84,30.85,32.11,28295200,32.11
+2007-02-23,31.60,32.18,31.41,32.10,21533500,32.10
+2007-02-22,31.60,32.08,31.32,31.60,15485100,31.60
+2007-02-21,31.74,31.77,31.22,31.65,27999200,31.65
+2007-02-20,31.80,32.21,31.39,32.01,20026500,32.01
+2007-02-16,31.00,32.00,31.00,31.91,36774800,31.91
+2007-02-15,30.82,31.65,30.69,31.25,28160300,31.25
+2007-02-14,29.69,30.86,29.64,30.66,30821100,30.66
+2007-02-13,29.37,29.68,29.26,29.56,12802300,29.56
+2007-02-12,29.29,29.77,29.05,29.17,18316200,29.17
+2007-02-09,30.07,30.16,29.51,29.74,18172200,29.74
+2007-02-08,29.75,30.24,29.73,30.08,15561700,30.08
+2007-02-07,29.35,30.15,29.12,29.89,29162600,29.89
+2007-02-06,28.61,29.56,28.60,29.35,24506800,29.35
+2007-02-05,28.67,28.80,28.36,28.56,11163300,28.56
+2007-02-02,28.57,28.92,28.45,28.77,16483100,28.77
+2007-02-01,28.68,28.71,28.15,28.35,17905200,28.35
+2007-01-31,28.04,28.48,27.82,28.31,14100300,28.31
+2007-01-30,27.87,28.39,27.61,28.04,13576600,28.04
+2007-01-29,28.05,28.21,27.73,27.87,16859000,27.87
+2007-01-26,28.33,28.52,27.96,28.04,21334800,28.04
+2007-01-25,28.68,29.05,28.13,28.21,28356200,28.21
+2007-01-24,28.34,29.20,28.22,28.94,81017500,28.94
+2007-01-23,27.42,27.54,26.88,26.96,43728100,26.96
+2007-01-22,27.85,27.90,27.18,27.42,23199800,27.42
+2007-01-19,27.93,28.34,27.55,27.64,24757700,27.64
+2007-01-18,28.92,28.99,27.82,28.12,23869400,28.12
+2007-01-17,29.40,29.40,28.81,29.05,17796100,29.05
+2007-01-16,29.88,29.88,28.79,29.29,24448400,29.29
+2007-01-12,28.98,29.50,28.49,29.45,20971100,29.45
+2007-01-11,28.76,29.37,28.70,29.20,28457500,29.20
+2007-01-10,27.48,28.92,27.44,28.70,40240000,28.70
+2007-01-09,28.00,28.05,27.41,27.58,25621500,27.58
+2007-01-08,27.70,28.04,27.43,27.92,25713700,27.92
+2007-01-05,26.70,27.87,26.66,27.74,64264600,27.74
+2007-01-04,25.64,26.92,25.52,26.85,32512200,26.85
+2007-01-03,25.85,26.26,25.26,25.61,26352700,25.61
+2006-12-29,25.42,25.82,25.33,25.54,16297800,25.54
+2006-12-28,25.62,25.72,25.30,25.36,11908400,25.36
+2006-12-27,25.47,25.88,25.45,25.75,12421800,25.75
+2006-12-26,25.49,25.61,25.34,25.45,8400500,25.45
+2006-12-22,25.67,25.88,25.45,25.55,14666100,25.55
+2006-12-21,25.71,25.75,25.13,25.48,27050600,25.48
+2006-12-20,26.24,26.31,25.54,25.59,24905600,25.59
+2006-12-19,26.05,26.50,25.91,26.41,18973800,26.41
+2006-12-18,26.89,26.97,26.07,26.30,19431200,26.30
+2006-12-15,27.00,27.22,26.76,26.90,27227300,26.90
+2006-12-14,26.63,26.97,26.50,26.87,14400300,26.87
+2006-12-13,27.05,27.23,26.51,26.60,20428600,26.60
+2006-12-12,26.63,27.38,26.60,26.75,31971600,26.75
+2006-12-11,26.37,26.70,26.12,26.49,12916900,26.49
+2006-12-08,26.65,26.78,26.27,26.34,19262200,26.34
+2006-12-07,26.95,27.16,26.60,26.63,22407000,26.63
+2006-12-06,27.25,27.45,26.60,26.86,35202800,26.86
+2006-12-05,26.87,27.61,26.86,27.43,27118200,27.43
+2006-12-04,26.49,27.30,26.49,26.89,28012700,26.89
+2006-12-01,27.00,27.25,26.00,26.49,20055800,26.49
+2006-11-30,27.00,27.15,26.73,27.01,14916300,27.01
+2006-11-29,27.40,27.40,26.71,27.04,19375100,27.04
+2006-11-28,27.03,27.24,26.85,27.00,14940800,27.00
+2006-11-27,27.50,28.50,27.17,27.27,19922300,27.27
+2006-11-24,28.22,28.49,27.70,28.03,9384400,28.03
+2006-11-22,27.51,28.56,27.29,28.49,32055800,28.49
+2006-11-21,26.50,27.34,26.50,27.14,21138300,27.14
+2006-11-20,26.96,27.04,26.63,26.72,20272000,26.72
+2006-11-17,26.68,27.05,26.63,26.91,17955200,26.91
+2006-11-16,27.31,27.33,26.20,26.64,38508500,26.64
+2006-11-15,27.18,27.50,27.03,27.15,22112700,27.15
+2006-11-14,27.40,27.50,27.11,27.24,20145700,27.24
+2006-11-13,27.17,27.62,27.15,27.40,16876500,27.40
+2006-11-10,27.40,27.50,27.03,27.39,21366600,27.39
+2006-11-09,27.18,27.65,26.96,27.45,27428600,27.45
+2006-11-08,26.36,27.25,26.31,26.90,23384800,26.90
+2006-11-07,26.69,27.15,26.58,26.61,28442700,26.61
+2006-11-06,26.34,26.70,26.10,26.59,22563600,26.59
+2006-11-03,26.63,26.70,26.04,26.18,15313800,26.18
+2006-11-02,25.94,26.60,25.77,26.53,34824500,26.53
+2006-11-01,26.50,26.62,25.82,25.99,26300200,25.99
+2006-10-31,26.44,26.70,26.10,26.34,33492800,26.34
+2006-10-30,25.87,26.40,25.66,25.95,35295800,25.95
+2006-10-27,25.23,25.60,24.90,25.34,29647200,25.34
+2006-10-26,24.70,25.33,24.36,25.28,38435800,25.28
+2006-10-25,23.73,24.64,23.69,24.49,40110600,24.49
+2006-10-24,23.35,23.64,23.15,23.53,31704000,23.53
+2006-10-23,23.14,23.50,23.10,23.37,26301200,23.37
+2006-10-20,23.22,23.27,22.65,23.21,49795600,23.21
+2006-10-19,23.02,23.59,23.00,23.14,42280400,23.14
+2006-10-18,24.57,24.75,22.88,22.99,111660900,22.99
+2006-10-17,23.74,24.35,23.68,24.15,67417200,24.15
+2006-10-16,24.34,24.52,23.75,24.18,36496400,24.18
+2006-10-13,23.90,24.50,23.57,24.42,51338900,24.42
+2006-10-12,24.32,24.38,24.10,24.12,25824500,24.12
+2006-10-11,24.29,24.64,23.80,24.24,39356300,24.24
+2006-10-10,24.94,25.03,24.32,24.47,30371900,24.47
+2006-10-09,25.45,25.72,25.00,25.03,15729500,25.03
+2006-10-06,25.09,25.50,25.01,25.47,20847000,25.47
+2006-10-05,25.16,25.25,24.88,25.18,17634000,25.18
+2006-10-04,24.89,25.26,24.74,25.21,21717900,25.21
+2006-10-03,24.81,25.00,24.70,24.84,21148300,24.84
+2006-10-02,25.45,25.46,24.75,24.88,19641300,24.88
+2006-09-29,25.50,25.59,25.24,25.28,18982600,25.28
+2006-09-28,24.87,25.50,24.84,25.33,35331200,25.33
+2006-09-27,25.00,25.01,24.60,24.65,29835900,24.65
+2006-09-26,25.44,25.48,24.81,25.05,34950100,25.05
+2006-09-25,25.64,25.87,25.20,25.29,19992400,25.29
+2006-09-22,25.34,25.69,25.18,25.52,20667400,25.52
+2006-09-21,25.53,25.95,25.21,25.34,28584500,25.34
+2006-09-20,26.04,26.09,25.38,25.64,55636600,25.64
+2006-09-19,29.09,29.13,25.10,25.75,127718600,25.75
+2006-09-18,29.37,29.39,28.58,29.00,15685000,29.00
+2006-09-15,29.30,29.57,29.22,29.32,19550300,29.32
+2006-09-14,29.10,29.24,28.89,29.03,9565500,29.03
+2006-09-13,29.06,29.37,28.80,29.17,15248400,29.17
+2006-09-12,28.55,29.22,28.46,29.09,10005000,29.09
+2006-09-11,28.05,28.73,27.67,28.61,12936000,28.61
+2006-09-08,28.04,28.32,27.97,28.14,9781800,28.14
+2006-09-07,28.40,28.51,27.82,27.86,18434400,27.86
+2006-09-06,28.94,29.01,28.49,28.50,12800600,28.50
+2006-09-05,29.45,29.48,28.95,29.07,11425600,29.07
+2006-09-01,28.91,29.53,28.91,29.49,11573600,29.49
+2006-08-31,28.99,29.02,28.59,28.83,8879300,28.83
+2006-08-30,29.00,29.14,28.71,29.02,13119300,29.02
+2006-08-29,28.86,29.01,28.51,28.96,9888800,28.96
+2006-08-28,28.75,29.25,28.70,28.91,10404700,28.91
+2006-08-25,28.95,29.28,28.74,28.77,6203800,28.77
+2006-08-24,28.75,29.13,28.70,28.99,8983600,28.99
+2006-08-23,29.34,29.47,28.68,28.70,8837400,28.70
+2006-08-22,28.84,29.65,28.80,29.26,10891800,29.26
+2006-08-21,29.22,29.52,28.83,28.90,11575200,28.90
+2006-08-18,28.90,29.97,28.77,29.78,19611300,29.78
+2006-08-17,28.38,29.32,28.34,28.91,17251600,28.91
+2006-08-16,28.35,28.46,27.97,28.39,12589400,28.39
+2006-08-15,27.58,28.20,27.48,28.17,15298500,28.17
+2006-08-14,27.71,27.80,27.00,27.26,10640100,27.26
+2006-08-11,27.52,27.72,27.40,27.50,9252200,27.50
+2006-08-10,26.95,27.80,26.85,27.49,12597900,27.49
+2006-08-09,27.75,27.85,27.00,27.22,14736100,27.22
+2006-08-08,26.95,27.70,26.63,27.44,19332800,27.44
+2006-08-07,26.92,27.11,26.58,27.08,12847200,27.08
+2006-08-04,27.20,27.58,26.83,26.99,11607900,26.99
+2006-08-03,26.50,27.05,26.40,26.90,15468500,26.90
+2006-08-02,27.01,27.10,26.45,26.63,18116200,26.63
+2006-08-01,27.06,27.12,26.74,26.94,18613100,26.94
+2006-07-31,27.46,27.55,26.99,27.14,16492600,27.14
+2006-07-28,26.90,27.50,26.33,27.47,21584800,27.47
+2006-07-27,27.35,27.50,26.64,26.70,25153000,26.70
+2006-07-26,26.78,27.51,26.57,27.08,20073800,27.08
+2006-07-25,26.75,27.19,26.57,26.95,21388800,26.95
+2006-07-24,26.24,27.23,25.89,26.94,42631300,26.94
+2006-07-21,24.99,26.06,24.91,25.89,36187100,25.89
+2006-07-20,25.55,26.21,24.91,25.27,54659700,25.27
+2006-07-19,26.41,26.70,25.04,25.20,204339000,25.20
+2006-07-18,32.08,32.26,31.25,32.24,39767700,32.24
+2006-07-17,31.98,32.40,31.69,31.84,16369600,31.84
+2006-07-14,32.34,32.48,31.85,32.08,12484700,32.08
+2006-07-13,32.85,33.16,32.07,32.23,19463500,32.23
+2006-07-12,33.03,33.74,32.99,33.38,18708400,33.38
+2006-07-11,32.79,33.35,32.32,33.17,11285900,33.17
+2006-07-10,32.91,33.14,32.73,32.85,15317600,32.85
+2006-07-07,32.94,33.05,32.37,32.50,12372500,32.50
+2006-07-06,32.77,33.22,32.70,33.11,13801500,33.11
+2006-07-05,32.85,32.99,32.33,32.47,13453900,32.47
+2006-07-03,32.90,33.44,32.90,33.30,8067100,33.30
+2006-06-30,33.01,33.12,32.54,33.00,22566600,33.00
+2006-06-29,32.26,33.00,32.20,32.97,15745900,32.97
+2006-06-28,31.75,32.17,31.70,31.92,14032800,31.92
+2006-06-27,31.85,32.22,31.32,31.51,16589400,31.51
+2006-06-26,31.45,31.70,31.16,31.55,11457000,31.55
+2006-06-23,31.08,31.76,30.82,31.37,17378500,31.37
+2006-06-22,30.85,31.16,30.44,30.68,11500300,30.68
+2006-06-21,30.77,31.54,30.65,31.06,18252900,31.06
+2006-06-20,30.42,30.65,30.10,30.60,12613200,30.60
+2006-06-19,30.51,30.75,30.06,30.35,12236700,30.35
+2006-06-16,30.70,30.86,30.15,30.36,12951700,30.36
+2006-06-15,29.98,30.96,29.72,30.79,22375000,30.79
+2006-06-14,29.81,30.00,29.25,29.62,19257500,29.62
+2006-06-13,29.77,30.20,29.51,29.65,16435700,29.65
+2006-06-12,30.37,30.65,29.66,29.78,14344600,29.78
+2006-06-09,30.70,30.80,30.23,30.37,10044700,30.37
+2006-06-08,30.43,30.99,29.83,30.45,20538600,30.45
+2006-06-07,30.80,31.25,30.36,30.54,17470100,30.54
+2006-06-06,30.83,30.97,30.35,30.70,15615600,30.70
+2006-06-05,31.19,31.43,30.79,30.82,17188500,30.82
+2006-06-02,32.11,32.19,31.30,31.52,16470900,31.52
+2006-06-01,31.83,32.00,31.49,31.99,16652400,31.99
+2006-05-31,32.19,32.32,31.11,31.59,21306700,31.59
+2006-05-30,32.73,32.89,31.79,32.00,16247600,32.00
+2006-05-26,32.86,33.02,32.35,33.02,13842600,33.02
+2006-05-25,32.94,33.50,32.50,32.92,34732700,32.92
+2006-05-24,30.95,32.02,30.71,31.79,27286300,31.79
+2006-05-23,31.04,31.63,30.76,30.76,28583400,30.76
+2006-05-22,30.42,30.98,29.89,30.46,35089300,30.46
+2006-05-19,29.05,29.75,28.60,29.53,33121900,29.53
+2006-05-18,30.10,30.36,28.93,29.00,38254000,29.00
+2006-05-17,30.61,31.26,30.04,30.11,39847500,30.11
+2006-05-16,31.10,31.22,30.63,30.97,15333700,30.97
+2006-05-15,30.85,31.25,30.60,31.03,13350700,31.03
+2006-05-12,30.71,31.18,30.38,30.81,16745600,30.81
+2006-05-11,31.96,32.17,30.87,30.99,24277000,30.99
+2006-05-10,32.48,32.56,32.00,32.09,13797500,32.09
+2006-05-09,32.68,34.00,32.35,32.49,13396400,32.49
+2006-05-08,33.09,33.43,32.63,32.87,18188200,32.87
+2006-05-05,32.63,32.75,32.22,32.66,14689200,32.66
+2006-05-04,32.40,32.56,32.08,32.19,10402300,32.19
+2006-05-03,32.40,33.00,31.75,32.17,23292600,32.17
+2006-05-02,32.20,32.91,31.72,31.85,16276000,31.85
+2006-05-01,32.99,33.10,31.86,32.08,19752200,32.08
+2006-04-28,32.88,33.45,32.78,32.78,13283500,32.78
+2006-04-27,32.79,33.50,32.40,33.20,19635700,33.20
+2006-04-26,32.30,33.09,32.10,33.00,24426400,33.00
+2006-04-25,32.99,33.06,31.88,31.99,22363200,31.99
+2006-04-24,33.01,33.45,32.90,33.01,15441600,33.01
+2006-04-21,33.36,34.09,32.70,32.89,25215000,32.89
+2006-04-20,33.48,33.70,32.93,33.37,23403900,33.37
+2006-04-19,33.47,33.98,32.76,33.54,77253600,33.54
+2006-04-18,31.17,31.38,30.53,31.30,38604500,31.30
+2006-04-17,31.16,31.79,30.66,30.97,18239900,30.97
+2006-04-13,31.14,31.40,30.85,31.13,15609800,31.13
+2006-04-12,31.44,31.50,30.89,31.10,14926900,31.10
+2006-04-11,32.45,32.60,31.15,31.39,22105600,31.39
+2006-04-10,32.28,32.63,32.12,32.55,9618000,32.55
+2006-04-07,32.85,32.97,32.21,32.27,12980200,32.27
+2006-04-06,32.12,33.14,32.11,32.79,21572600,32.79
+2006-04-05,32.30,32.50,31.96,32.11,11982500,32.11
+2006-04-04,31.69,32.25,31.66,32.10,16232700,32.10
+2006-04-03,32.41,32.53,31.79,31.89,14887900,31.89
+2006-03-31,32.45,32.63,32.01,32.26,12677300,32.26
+2006-03-30,32.75,32.83,32.09,32.42,14314000,32.42
+2006-03-29,32.44,32.91,32.14,32.56,25508200,32.56
+2006-03-28,31.45,32.50,31.41,32.39,25981500,32.39
+2006-03-27,31.84,32.08,31.30,31.45,14858500,31.45
+2006-03-24,32.28,32.31,31.53,31.77,17816500,31.77
+2006-03-23,31.52,31.95,31.48,31.83,33834000,31.83
+2006-03-22,30.33,30.91,30.31,30.75,23147400,30.75
+2006-03-21,30.11,30.78,30.02,30.11,18876400,30.11
+2006-03-20,30.38,30.93,30.20,30.44,21455200,30.44
+2006-03-17,30.35,30.36,29.83,30.07,23629700,30.07
+2006-03-16,30.77,30.88,30.10,30.13,17108000,30.13
+2006-03-15,31.25,31.28,30.47,30.53,20758000,30.53
+2006-03-14,30.10,31.00,30.10,30.99,19294700,30.99
+2006-03-13,30.72,30.97,30.12,30.15,18437700,30.15
+2006-03-10,30.40,31.10,29.75,30.58,28991400,30.58
+2006-03-09,31.05,31.32,30.25,30.28,18277000,30.28
+2006-03-08,31.31,31.55,30.82,30.99,20910200,30.99
+2006-03-07,31.42,32.20,31.31,31.43,23365100,31.43
+2006-03-06,31.53,31.94,31.45,31.57,17211200,31.57
+2006-03-03,31.70,32.07,31.38,31.45,23196000,31.45
+2006-03-02,32.01,32.11,31.58,31.70,23487300,31.70
+2006-03-01,32.21,32.42,31.72,32.18,18466100,32.18
+2006-02-28,32.63,32.98,31.34,32.06,39926200,32.06
+2006-02-27,33.11,33.21,32.57,32.74,11821900,32.74
+2006-02-24,33.20,33.34,32.92,33.01,10136400,33.01
+2006-02-23,33.01,33.66,32.88,33.15,14947600,33.15
+2006-02-22,32.49,33.34,32.40,33.16,18433500,33.16
+2006-02-21,32.90,33.07,32.38,32.39,14328100,32.39
+2006-02-17,32.88,33.14,32.71,32.76,12620200,32.76
+2006-02-16,33.30,33.40,32.60,32.75,19500100,32.75
+2006-02-15,32.62,33.33,32.55,33.02,19542100,33.02
+2006-02-14,32.14,32.83,32.05,32.72,26198600,32.72
+2006-02-13,32.21,32.44,31.70,32.04,26139300,32.04
+2006-02-10,32.58,32.60,32.10,32.51,19628600,32.51
+2006-02-09,33.01,33.36,32.40,32.50,25335200,32.50
+2006-02-08,33.24,33.40,32.51,33.00,28112900,33.00
+2006-02-07,33.01,33.10,32.32,33.02,37236800,33.02
+2006-02-06,33.90,33.95,32.78,32.92,23523100,32.92
+2006-02-03,34.00,34.05,33.26,33.54,32639600,33.54
+2006-02-02,35.01,35.10,34.10,34.25,18323500,34.25
+2006-02-01,34.45,35.00,34.35,35.00,43600400,35.00
+2006-01-31,35.20,35.20,34.31,34.38,36538000,34.38
+2006-01-30,35.09,35.23,34.88,35.05,29030600,35.05
+2006-01-27,35.26,35.27,34.66,35.09,24317400,35.09
+2006-01-26,34.94,35.25,34.49,35.17,28471400,35.17
+2006-01-25,35.43,35.48,34.38,34.49,23779200,34.49
+2006-01-24,34.55,35.20,34.51,34.87,31667800,34.87
+2006-01-23,34.22,34.40,33.98,34.17,30887600,34.17
+2006-01-20,34.44,34.66,33.21,33.74,57644600,33.74
+2006-01-19,35.82,35.84,34.24,34.33,60913000,34.33
+2006-01-18,35.01,36.16,34.74,35.18,118556100,35.18
+2006-01-17,39.09,40.39,38.96,40.11,41797000,40.11
+2006-01-13,41.00,41.08,39.62,39.90,30960800,39.90
+2006-01-12,41.92,41.99,40.76,40.89,18921700,40.89
+2006-01-11,42.19,42.31,41.72,41.87,26191400,41.87
+2006-01-10,42.96,43.34,42.34,42.98,16287200,42.98
+2006-01-09,43.10,43.66,42.82,43.42,16266900,43.42
+2006-01-06,42.88,43.57,42.80,43.21,29418400,43.21
+2006-01-05,40.93,41.73,40.85,41.53,12829100,41.53
+2006-01-04,41.22,41.90,40.77,40.97,20549000,40.97
+2006-01-03,39.69,41.22,38.79,40.91,24227700,40.91
+2005-12-30,39.40,39.56,39.05,39.18,12233000,39.18
+2005-12-29,40.25,40.35,39.41,39.56,10116600,39.56
+2005-12-28,40.10,40.48,39.77,40.25,11567900,40.25
+2005-12-27,40.65,40.94,39.85,39.94,11672900,39.94
+2005-12-23,41.09,41.10,40.45,40.63,5070200,40.63
+2005-12-22,40.69,41.68,40.55,40.83,9548300,40.83
+2005-12-21,40.52,41.05,40.35,40.47,11626900,40.47
+2005-12-20,41.26,41.36,40.48,40.68,15269500,40.68
+2005-12-19,42.16,42.89,40.88,41.05,18563700,41.05
+2005-12-16,41.86,42.67,41.75,42.32,21805000,42.32
+2005-12-15,41.23,41.84,41.14,41.75,20900800,41.75
+2005-12-14,41.12,41.68,40.84,41.30,23034200,41.30
+2005-12-13,40.01,41.40,40.00,41.20,17264700,41.20
+2005-12-12,40.41,40.54,39.81,40.08,9776300,40.08
+2005-12-09,40.50,40.87,40.20,40.31,11116900,40.31
+2005-12-08,40.25,40.54,39.95,40.35,12851600,40.35
+2005-12-07,40.31,40.63,39.57,40.11,15644900,40.11
+2005-12-06,40.78,41.18,40.12,40.19,16356800,40.19
+2005-12-05,40.88,41.03,40.37,40.47,15389400,40.47
+2005-12-02,41.22,41.85,40.89,41.21,14411400,41.21
+2005-12-01,40.74,41.25,40.54,41.07,20069600,41.07
+2005-11-30,39.38,40.84,39.09,40.23,31608700,40.23
+2005-11-29,41.01,41.59,39.82,40.19,28698200,40.19
+2005-11-28,41.63,41.77,40.66,41.11,23190900,41.11
+2005-11-25,42.71,42.84,41.94,42.13,8253000,42.13
+2005-11-23,42.21,43.45,42.17,42.50,21471000,42.50
+2005-11-22,41.73,42.65,41.65,42.36,26389500,42.36
+2005-11-21,41.26,42.98,41.21,42.27,27915500,42.27
+2005-11-18,42.04,42.41,41.29,41.54,30747600,41.54
+2005-11-17,40.32,42.50,40.03,42.23,44796000,42.23
+2005-11-16,37.90,40.07,37.86,40.04,39464600,40.04
+2005-11-15,38.26,38.61,37.54,37.65,11981600,37.65
+2005-11-14,38.43,38.72,37.96,38.45,10112500,38.45
+2005-11-11,38.69,39.05,38.34,38.49,12234400,38.49
+2005-11-10,37.52,38.75,37.52,38.69,13722400,38.69
+2005-11-09,37.76,38.04,37.43,37.75,12217600,37.75
+2005-11-08,37.75,38.50,37.60,37.97,14434400,37.97
+2005-11-07,37.69,38.18,37.41,37.90,11652700,37.90
+2005-11-04,37.59,37.99,37.37,37.87,11656100,37.87
+2005-11-03,38.26,38.28,37.33,37.45,16880800,37.45
+2005-11-02,37.49,38.04,37.43,37.99,17886200,37.99
+2005-11-01,36.62,38.71,36.59,37.72,41932100,37.72
+2005-10-31,35.60,37.27,35.60,36.97,24867100,36.97
+2005-10-28,35.62,35.92,35.25,35.58,14123800,35.58
+2005-10-27,35.34,35.66,35.30,35.45,11605000,35.45
+2005-10-26,35.06,35.75,34.97,35.46,17125600,35.46
+2005-10-25,35.19,35.38,34.89,35.12,14441100,35.12
+2005-10-24,35.30,35.49,34.94,35.28,19591900,35.28
+2005-10-21,35.99,36.33,35.19,35.29,28423400,35.29
+2005-10-20,35.90,36.94,35.05,35.26,29267000,35.26
+2005-10-19,34.62,35.94,34.59,35.91,63254000,35.91
+2005-10-18,34.40,34.76,33.64,33.70,35010300,33.70
+2005-10-17,33.85,34.30,33.80,34.16,21994600,34.16
+2005-10-14,33.62,33.62,32.77,33.52,17425200,33.52
+2005-10-13,33.80,33.85,32.97,33.37,16254600,33.37
+2005-10-12,33.99,34.71,33.91,33.93,16089600,33.93
+2005-10-11,34.55,34.84,33.66,34.10,16504700,34.10
+2005-10-10,34.20,34.90,34.12,34.53,15227800,34.53
+2005-10-07,34.03,34.29,33.97,34.16,12253200,34.16
+2005-10-06,33.95,34.30,33.54,33.80,21836100,33.80
+2005-10-05,33.79,33.93,33.36,33.49,14642000,33.49
+2005-10-04,33.75,34.37,33.51,33.57,14331000,33.57
+2005-10-03,33.80,34.12,33.71,33.77,13184500,33.77
+2005-09-30,33.59,34.10,33.56,33.84,15697000,33.84
+2005-09-29,32.40,33.70,32.12,33.46,22209100,33.46
+2005-09-28,32.67,32.80,32.27,32.35,11622800,32.35
+2005-09-27,32.17,32.61,32.17,32.48,12246900,32.48
+2005-09-26,32.48,32.55,31.99,32.18,13548200,32.18
+2005-09-23,32.12,32.25,31.75,32.13,14903700,32.13
+2005-09-22,32.09,32.41,31.76,32.04,18259400,32.04
+2005-09-21,32.53,33.10,31.60,31.97,21896000,31.97
+2005-09-20,32.88,33.11,32.36,32.64,14578900,32.64
+2005-09-19,33.27,33.47,32.25,32.75,15429900,32.75
+2005-09-16,33.74,33.77,33.05,33.17,20858300,33.17
+2005-09-15,33.95,33.99,33.50,33.57,10404800,33.57
+2005-09-14,34.30,34.50,33.64,33.80,15017400,33.80
+2005-09-13,33.93,34.71,33.73,34.30,19346600,34.30
+2005-09-12,33.42,34.34,33.41,33.91,18580300,33.91
+2005-09-09,33.35,33.60,33.02,33.46,15247900,33.46
+2005-09-08,33.74,33.93,33.20,33.34,17464400,33.34
+2005-09-07,33.50,34.26,33.30,34.06,12545300,34.06
+2005-09-06,33.18,33.78,33.18,33.68,12513300,33.68
+2005-09-02,33.20,33.37,33.10,33.17,6849000,33.17
+2005-09-01,33.28,33.51,33.04,33.24,11848500,33.24
+2005-08-31,33.23,33.39,32.99,33.32,13035500,33.32
+2005-08-30,33.50,33.67,33.00,33.18,13496000,33.18
+2005-08-29,33.40,33.78,33.31,33.68,11427600,33.68
+2005-08-26,33.51,33.81,33.38,33.57,9833400,33.57
+2005-08-25,33.54,33.62,33.20,33.48,12564900,33.48
+2005-08-24,32.92,33.68,32.88,33.47,23249500,33.47
+2005-08-23,33.29,33.33,32.65,33.11,16912700,33.11
+2005-08-22,34.07,34.10,33.07,33.20,21054400,33.20
+2005-08-19,34.39,34.47,33.98,34.00,12810400,34.00
+2005-08-18,34.13,34.73,34.12,34.36,12154200,34.36
+2005-08-17,34.30,34.73,34.23,34.39,10443700,34.39
+2005-08-16,34.57,34.66,34.21,34.23,11867100,34.23
+2005-08-15,34.80,34.87,34.49,34.60,11244500,34.60
+2005-08-12,34.86,34.88,34.45,34.60,13306100,34.60
+2005-08-11,34.54,35.00,34.32,34.94,22391900,34.94
+2005-08-10,34.28,34.77,34.00,34.19,18047900,34.19
+2005-08-09,34.15,34.32,33.91,34.06,9987400,34.06
+2005-08-08,33.86,34.18,33.66,33.94,13066200,33.94
+2005-08-05,34.09,34.28,33.49,33.52,11873800,33.52
+2005-08-04,34.26,34.60,34.00,34.06,11143400,34.06
+2005-08-03,33.75,34.68,33.73,34.51,18240600,34.51
+2005-08-02,33.46,34.20,33.39,33.88,17581900,33.88
+2005-08-01,33.63,33.69,33.31,33.33,12637100,33.33
+2005-07-29,34.01,34.06,33.34,33.34,16236100,33.34
+2005-07-28,34.23,34.31,33.98,34.01,11871600,34.01
+2005-07-27,34.22,34.37,33.95,34.29,20497500,34.29
+2005-07-26,34.05,34.30,33.91,34.15,16819200,34.15
+2005-07-25,33.88,34.08,33.59,33.85,23252600,33.85
+2005-07-22,33.35,33.77,33.17,33.53,27561500,33.53
+2005-07-21,33.75,33.76,32.75,32.94,37778500,32.94
+2005-07-20,34.21,34.35,33.31,33.40,82623300,33.40
+2005-07-19,37.02,38.02,36.56,37.73,32685500,37.73
+2005-07-18,36.45,36.78,36.37,36.58,11019300,36.58
+2005-07-15,37.05,37.16,36.50,36.58,12372200,36.58
+2005-07-14,37.40,37.50,36.77,36.86,14722200,36.86
+2005-07-13,36.42,36.98,36.41,36.73,16897500,36.73
+2005-07-12,36.20,36.49,35.94,36.23,19665800,36.23
+2005-07-11,34.90,35.81,34.78,35.76,20233000,35.76
+2005-07-08,34.77,34.87,34.25,34.62,15515400,34.62
+2005-07-07,33.87,34.77,33.72,34.63,16354300,34.63
+2005-07-06,34.64,34.97,34.03,34.12,13585700,34.12
+2005-07-05,34.25,35.08,34.20,34.60,16086700,34.60
+2005-07-01,34.76,34.85,34.22,34.44,9861600,34.44
+2005-06-30,34.84,35.17,34.44,34.65,16699500,34.65
+2005-06-29,35.80,35.94,34.88,34.94,16481900,34.94
+2005-06-28,35.95,36.24,35.51,35.80,13346200,35.80
+2005-06-27,35.88,36.11,35.20,35.68,12044700,35.68
+2005-06-24,36.26,36.40,35.60,36.09,13468200,36.09
+2005-06-23,36.85,37.31,36.20,36.20,15547700,36.20
+2005-06-22,36.91,37.32,36.84,36.90,12148100,36.90
+2005-06-21,36.37,37.31,36.36,36.95,16219200,36.95
+2005-06-20,35.96,36.84,35.79,36.45,12753200,36.45
+2005-06-17,36.76,36.98,36.12,36.30,15952800,36.30
+2005-06-16,36.46,36.74,36.22,36.40,12228700,36.40
+2005-06-15,36.97,37.11,35.91,36.32,22753900,36.32
+2005-06-14,36.56,37.05,36.43,36.80,12781200,36.80
+2005-06-13,36.66,37.51,36.53,36.90,11586300,36.90
+2005-06-10,37.48,37.50,36.32,36.81,14216900,36.81
+2005-06-09,36.81,37.48,36.38,37.45,18455100,37.45
+2005-06-08,37.42,37.45,36.32,36.63,20121100,36.63
+2005-06-07,38.72,38.95,37.32,37.44,22848300,37.44
+2005-06-06,37.79,38.74,37.75,38.52,12416000,38.52
+2005-06-03,38.24,38.79,37.60,37.92,12813300,37.92
+2005-06-02,38.20,38.71,38.13,38.50,13150700,38.50
+2005-06-01,37.31,38.90,37.17,38.42,28153800,38.42
+2005-05-31,37.03,37.35,36.85,37.20,12498300,37.20
+2005-05-27,36.98,37.47,36.95,37.27,10256600,37.27
+2005-05-26,36.45,37.19,36.35,37.14,15547700,37.14
+2005-05-25,36.25,36.42,36.06,36.27,14995100,36.27
+2005-05-24,36.87,37.10,36.45,36.63,17421300,36.63
+2005-05-23,36.10,37.10,36.04,36.80,21616200,36.80
+2005-05-20,36.60,36.64,36.13,36.33,13771900,36.33
+2005-05-19,36.13,36.99,36.11,36.75,21267100,36.75
+2005-05-18,35.79,36.58,35.69,35.95,23769000,35.95
+2005-05-17,35.20,35.80,35.14,35.68,13178400,35.68
+2005-05-16,34.78,35.50,34.74,35.45,15473900,35.45
+2005-05-13,34.71,35.35,34.35,34.82,15855900,34.82
+2005-05-12,34.95,35.37,34.54,34.71,18906700,34.71
+2005-05-11,34.09,34.88,33.69,34.88,19537100,34.88
+2005-05-10,34.30,34.37,33.86,34.06,13227000,34.06
+2005-05-09,34.48,34.65,34.25,34.59,9991700,34.59
+2005-05-06,35.00,35.08,34.45,34.52,14202200,34.52
+2005-05-05,35.10,35.29,34.43,34.71,16926300,34.71
+2005-05-04,34.43,35.50,34.38,35.18,23410900,35.18
+2005-05-03,34.05,34.60,33.90,34.28,22042800,34.28
+2005-05-02,34.44,34.85,34.03,34.38,13231500,34.38
+2005-04-29,34.60,34.75,33.92,34.50,15666100,34.50
+2005-04-28,34.70,34.93,34.02,34.33,16159300,34.33
+2005-04-27,34.70,35.14,34.59,34.95,14861300,34.95
+2005-04-26,35.12,35.42,34.80,35.00,17921200,35.00
+2005-04-25,34.58,35.59,34.58,35.49,23883600,35.49
+2005-04-22,35.21,35.88,34.50,34.87,31869800,34.87
+2005-04-21,35.12,35.91,34.71,35.87,27731600,35.87
+2005-04-20,34.96,35.25,34.36,34.65,50104400,34.65
+2005-04-19,32.96,33.33,32.42,33.22,34158500,33.22
+2005-04-18,32.43,33.09,32.40,32.55,19201200,32.55
+2005-04-15,32.96,33.41,32.29,32.46,27008500,32.46
+2005-04-14,33.63,34.20,33.40,33.46,19855300,33.46
+2005-04-13,34.16,34.46,33.40,33.60,16886100,33.60
+2005-04-12,34.35,34.50,33.74,34.28,22681900,34.28
+2005-04-11,34.97,35.09,34.54,34.60,11758500,34.60
+2005-04-08,35.04,35.14,34.65,34.76,11106300,34.76
+2005-04-07,34.45,35.25,34.45,35.07,20575000,35.07
+2005-04-06,35.14,35.42,34.12,34.49,23574000,34.49
+2005-04-05,35.15,35.40,34.84,35.15,20275900,35.15
+2005-04-04,34.34,35.27,33.75,35.07,27853300,35.07
+2005-04-01,34.18,34.77,34.15,34.28,27955400,34.28
+2005-03-31,33.55,34.20,33.20,33.90,25390000,33.90
+2005-03-30,32.31,33.60,32.27,33.48,28267900,33.48
+2005-03-29,32.18,32.84,31.79,32.16,23544700,32.16
+2005-03-28,32.21,32.50,32.10,32.25,20624400,32.25
+2005-03-24,31.94,32.09,31.41,31.41,23162000,31.41
+2005-03-23,30.91,31.33,30.85,30.87,13917100,30.87
+2005-03-22,31.70,31.98,30.86,30.99,19570600,30.99
+2005-03-21,31.29,31.77,30.98,31.62,18449400,31.62
+2005-03-18,31.53,31.73,30.91,31.11,20796400,31.11
+2005-03-17,31.80,31.98,31.54,31.61,13760200,31.61
+2005-03-16,31.87,32.35,31.40,31.58,17952000,31.58
+2005-03-15,31.61,32.28,31.53,31.94,20880800,31.94
+2005-03-14,31.74,31.83,30.65,31.32,19762000,31.32
+2005-03-11,31.86,32.21,31.65,31.65,13364800,31.65
+2005-03-10,32.43,32.56,31.60,31.91,19381200,31.91
+2005-03-09,33.01,33.15,32.01,32.32,21824400,32.32
+2005-03-08,33.55,33.73,33.14,33.16,17839300,33.16
+2005-03-07,32.40,33.31,32.36,33.09,17679200,33.09
+2005-03-04,32.36,32.57,31.76,32.36,17499800,32.36
+2005-03-03,32.25,32.48,31.80,32.31,17896100,32.31
+2005-03-02,32.07,32.60,31.75,32.23,15357200,32.23
+2005-03-01,32.37,32.67,32.05,32.30,20222500,32.30
+2005-02-28,31.74,33.77,31.62,32.27,25266400,32.27
+2005-02-25,31.53,31.96,31.43,31.73,20114900,31.73
+2005-02-24,30.43,31.49,30.30,31.48,55457300,31.48
+2005-02-23,32.82,32.92,31.40,32.12,34757100,32.12
+2005-02-22,33.25,33.82,32.66,32.79,18142600,32.79
+2005-02-18,33.84,33.98,33.38,33.60,12436100,33.60
+2005-02-17,34.42,34.79,33.76,33.82,16203500,33.82
+2005-02-16,33.81,34.82,33.75,34.42,22176200,34.42
+2005-02-15,34.34,34.92,33.81,33.98,20391900,33.98
+2005-02-14,34.01,34.41,33.78,34.33,20065300,34.33
+2005-02-11,33.45,34.70,33.31,34.15,20005800,34.15
+2005-02-10,33.72,33.72,32.47,33.44,32637400,33.44
+2005-02-09,34.60,34.66,33.45,33.59,18285100,33.59
+2005-02-08,34.64,34.91,34.32,34.36,17321500,34.36
+2005-02-07,35.07,35.19,34.36,34.47,14588900,34.47
+2005-02-04,34.71,35.30,34.71,35.02,16850200,35.02
+2005-02-03,35.27,35.67,35.00,35.09,16742400,35.09
+2005-02-02,36.02,36.34,35.29,35.54,33495200,35.54
+2005-02-01,35.13,35.28,34.46,34.75,18633600,34.75
+2005-01-31,35.04,35.44,34.53,35.21,20712200,35.21
+2005-01-28,34.90,35.24,34.12,34.62,17853700,34.62
+2005-01-27,35.38,35.49,34.35,34.73,21450800,34.73
+2005-01-26,34.71,35.74,34.39,35.47,25767500,35.47
+2005-01-25,34.55,34.76,33.94,34.04,26521400,34.04
+2005-01-24,35.48,35.52,33.75,33.93,31477400,33.93
+2005-01-21,36.07,36.11,35.29,35.30,26608000,35.30
+2005-01-20,35.39,36.42,35.05,35.78,30239100,35.78
+2005-01-19,38.08,38.20,36.42,36.45,44303200,36.45
+2005-01-18,37.10,37.46,36.60,37.18,42709600,37.18
+2005-01-14,35.86,36.70,35.83,36.70,27697700,36.70
+2005-01-13,36.12,36.32,35.26,35.33,18526500,35.33
+2005-01-12,35.88,36.18,34.80,36.14,23274700,36.14
+2005-01-11,36.31,36.58,35.39,35.66,19711900,35.66
+2005-01-10,36.00,36.76,35.51,36.32,17482800,36.32
+2005-01-07,35.99,36.46,35.41,35.96,18596300,35.96
+2005-01-06,36.32,36.50,35.21,35.43,20835300,35.43
+2005-01-05,36.69,36.98,36.06,36.13,18469100,36.13
+2005-01-04,38.45,38.54,36.46,36.58,26625300,36.58
+2005-01-03,38.36,38.90,37.65,38.18,25482800,38.18
diff --git a/dojox/charting/tests/gradients/test_grad_bars1.html b/dojox/charting/tests/gradients/test_grad_bars1.html
new file mode 100644
index 0000000..a6cd0a2
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_bars1.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Bars #1</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#ed0" }, { offset: 0.5, color: "#eda" }, { offset: 1, color: "#ed0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#e00" }, { offset: 0.5, color: "#eaa" }, { offset: 1, color: "#e00" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#0e0" }, { offset: 0.5, color: "#aea" }, { offset: 1, color: "#0e0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#00e" }, { offset: 0.5, color: "#aae" }, { offset: 1, color: "#00e" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "Bars"}).
+                addSeries("Series A", [1, 2, 3, 4, 5]).
+                addSeries("Series B", [5, 4, 3, 2, 1]).
+                render();
+
+            var chart2 = new dojox.charting.Chart2D("c2").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "StackedBars"}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+
+            var chart3 = new dojox.charting.Chart2D("c3").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "ClusteredBars", gap: 5}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>plot-space left-to-right gradient</h1>
+	<p>Bars</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Stacked Bars</p>
+    <div id="c2" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Clustered Bars</p>
+    <div id="c3" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_bars2.html b/dojox/charting/tests/gradients/test_grad_bars2.html
new file mode 100644
index 0000000..307e7e6
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_bars2.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Bars #2</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 100, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.2}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "Bars"}).
+                addSeries("Series A", [1, 2, 3, 4, 5]).
+                addSeries("Series B", [5, 4, 3, 2, 1]).
+                render();
+
+            var chart2 = new dojox.charting.Chart2D("c2").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "StackedBars"}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+
+            var chart3 = new dojox.charting.Chart2D("c3").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "ClusteredBars", gap: 5}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>plot-space diagonal gradient</h1>
+	<p>Bars</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Stacked Bars</p>
+    <div id="c2" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Clustered Bars</p>
+    <div id="c3" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_bars3.html b/dojox/charting/tests/gradients/test_grad_bars3.html
new file mode 100644
index 0000000..120f7a2
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_bars3.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Bars #3</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 0, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.2}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "Bars"}).
+                addSeries("Series A", [1, 2, 3, 4, 5]).
+                addSeries("Series B", [5, 4, 3, 2, 1]).
+                render();
+
+            var chart2 = new dojox.charting.Chart2D("c2").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "StackedBars"}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+
+            var chart3 = new dojox.charting.Chart2D("c3").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "ClusteredBars", gap: 5}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>shape-space gradient</h1>
+	<p>Bars</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Stacked Bars</p>
+    <div id="c2" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Clustered Bars</p>
+    <div id="c3" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_bars4.html b/dojox/charting/tests/gradients/test_grad_bars4.html
new file mode 100644
index 0000000..51fcf7a
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_bars4.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Bars #4</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "shapeX", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shapeX", x1: 0, y1: 0, x2: 0, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shapeY", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.2}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "Bars"}).
+                addSeries("Series A", [1, 2, 3, 4, 5]).
+                addSeries("Series B", [5, 4, 3, 2, 1]).
+                render();
+
+            var chart2 = new dojox.charting.Chart2D("c2").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "StackedBars"}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+
+            var chart3 = new dojox.charting.Chart2D("c3").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "ClusteredBars", gap: 5}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>1D shape-space gradient</h1>
+	<p>Bars</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Stacked Bars</p>
+    <div id="c2" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Clustered Bars</p>
+    <div id="c3" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_bars5.html b/dojox/charting/tests/gradients/test_grad_bars5.html
new file mode 100644
index 0000000..acf98a0
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_bars5.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Bars #5</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: { // red plastic cylinder
+                                type: "linear", space: "shapeY", x1: 0, y1: 0, x2: 100, y2: 0,
+                                //colors: [{"offset":0,"color":{"r":174,"g":0,"b":0,"a":1}},{"offset":9.992007221626409e-16,"color":{"r":174,"g":0,"b":0,"a":1}},{"offset":0.013851578375197016,"color":{"r":215,"g":0,"b":0,"a":1}},{"offset":0.031369214560646785,"color":{"r":221,"g":0,"b":0,"a":1}},{"offset":0.052730424013296195,"color":{"r":227,"g":0,"b":0,"a":1}},{"offset":0.07793466262473725,"color":{"r":231,"g":0,"b":0,"a":1}},{"offset":0.10686548826723474,"color":{"r":235,"g":0,"b":0," [...]
+                                colors: [{"offset":0,"color":{"r":174,"g":0,"b":0,"a":1}},{"offset":0.08,"color":{"r":231,"g":0,"b":0,"a":1}},{"offset":0.18,"color":{"r":237,"g":150,"b":150,"a":1}},{"offset":0.3,"color":{"r":231,"g":0,"b":0,"a":1}},{"offset":0.39,"color":{"r":221,"g":0,"b":0,"a":1}},{"offset":0.49,"color":{"r":206,"g":0,"b":0,"a":1}},{"offset":0.58,"color":{"r":187,"g":0,"b":0,"a":1}},{"offset":0.68,"color":{"r":165,"g":0,"b":0,"a":1}},{"offset":0.8,"color":{"r":128,"g": [...]
+                            }
+                        },
+                        {
+                            fill: { // yellow plastic cylinder
+                                type: "linear", space: "shapeY", x1: 0, y1: 0, x2: 100, y2: 0,
+                                //colors: [{"offset":0,"color":{"r":174,"g":174,"b":0,"a":1}},{"offset":9.992007221626409e-16,"color":{"r":174,"g":174,"b":0,"a":1}},{"offset":0.01385157837519746,"color":{"r":215,"g":215,"b":0,"a":1}},{"offset":0.03136921456064723,"color":{"r":221,"g":221,"b":0,"a":1}},{"offset":0.05273042401329664,"color":{"r":227,"g":227,"b":0,"a":1}},{"offset":0.07793466262473725,"color":{"r":231,"g":231,"b":0,"a":1}},{"offset":0.10686548826723508,"color":{"r":235,"g": [...]
+                                colors: [{"offset":0,"color":{"r":174,"g":174,"b":0,"a":1}},{"offset":0.08,"color":{"r":231,"g":231,"b":0,"a":1}},{"offset":0.18,"color":"white"},{"offset":0.3,"color":{"r":231,"g":231,"b":0,"a":1}},{"offset":0.39,"color":{"r":221,"g":221,"b":0,"a":1}},{"offset":0.49,"color":{"r":206,"g":206,"b":0,"a":1}},{"offset":0.58,"color":{"r":187,"g":187,"b":0,"a":1}},{"offset":0.68,"color":{"r":165,"g":165,"b":0,"a":1}},{"offset":0.8,"color":{"r":128,"g":128,"b":0, [...]
+                            }
+                        },
+                        {
+                            fill: { // blue plastic cylinder
+                                type: "linear", space: "shapeY", x1: 0, y1: 0, x2: 100, y2: 0,
+                                //colors: [{"offset":0,"color":{"r":0,"g":0,"b":174,"a":1}},{"offset":5.551115123125783e-16,"color":{"r":0,"g":0,"b":174,"a":1}},{"offset":0.013851578375196572,"color":{"r":0,"g":0,"b":215,"a":1}},{"offset":0.03136921456064645,"color":{"r":0,"g":0,"b":221,"a":1}},{"offset":0.052730424013296195,"color":{"r":0,"g":0,"b":227,"a":1}},{"offset":0.0779346626247368,"color":{"r":0,"g":0,"b":231,"a":1}},{"offset":0.10686548826723419,"color":{"r":0,"g":0,"b":235,"a" [...]
+                                colors: [{"offset":0,"color":{"r":0,"g":0,"b":174,"a":1}},{"offset":0.08,"color":{"r":0,"g":0,"b":231,"a":1}},{"offset":0.18,"color":{"r":150,"g":150,"b":237,"a":1}},{"offset":0.3,"color":{"r":0,"g":0,"b":231,"a":1}},{"offset":0.39,"color":{"r":0,"g":0,"b":221,"a":1}},{"offset":0.49,"color":{"r":0,"g":0,"b":206,"a":1}},{"offset":0.58,"color":{"r":0,"g":0,"b":187,"a":1}},{"offset":0.68,"color":{"r":0,"g":0,"b":165,"a":1}},{"offset":0.8,"color":{"r":0,"g":0, [...]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.2}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "Bars"}).
+                addSeries("Series A", [1, 2, 3, 4, 5]).
+                addSeries("Series B", [5, 4, 3, 2, 1]).
+                render();
+
+            var chart2 = new dojox.charting.Chart2D("c2").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "StackedBars"}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+
+            var chart3 = new dojox.charting.Chart2D("c3").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+                addPlot("default", {type: "ClusteredBars", gap: 5}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>1D shape-space pseudo-3D gradient</h1>
+	<p>Bars</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Stacked Bars</p>
+    <div id="c2" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Clustered Bars</p>
+    <div id="c3" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_bubble1.html b/dojox/charting/tests/gradients/test_grad_bubble1.html
new file mode 100644
index 0000000..764779e
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_bubble1.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Bubble #1</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#ed0" }, { offset: 0.5, color: "#eda" }, { offset: 1, color: "#ed0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#e00" }, { offset: 0.5, color: "#eaa" }, { offset: 1, color: "#e00" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#0e0" }, { offset: 0.5, color: "#aea" }, { offset: 1, color: "#0e0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#00e" }, { offset: 0.5, color: "#aae" }, { offset: 1, color: "#00e" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {minorLabels: false}).
+                addAxis("y", {vertical: true, minorLabels: false, max: 10}).
+                addPlot("default", {type: "Bubble"}).
+				addSeries("Series A", [
+					{ x: 0.5, y: 5, size: 1.4 },
+					{ x: 1.5, y: 1.5, size: 4.5 },
+					{ x: 2, y: 9, size:1.5 },
+					{ x: 5, y: 0.3, size:0.8 }
+				]).
+				addSeries("Series B", [
+					{ x: 0.3, y: 8, size: 2.5 },
+					{ x: 4, y: 8, size:1.1 },
+					{ x: 5.5, y: 2, size: 3.2 },
+					{ x: 3, y: 6, size: 3.2 }
+				]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>plot-space left-to-right gradient</h1>
+	<p>Bubble</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_bubble2.html b/dojox/charting/tests/gradients/test_grad_bubble2.html
new file mode 100644
index 0000000..f2b2ba7
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_bubble2.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Bubble #2</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 100, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {minorLabels: false}).
+                addAxis("y", {vertical: true, minorLabels: false, max: 10}).
+                addPlot("default", {type: "Bubble"}).
+				addSeries("Series A", [
+					{ x: 0.5, y: 5, size: 1.4 },
+					{ x: 1.5, y: 1.5, size: 4.5 },
+					{ x: 2, y: 9, size:1.5 },
+					{ x: 5, y: 0.3, size:0.8 }
+				]).
+				addSeries("Series B", [
+					{ x: 0.3, y: 8, size: 2.5 },
+					{ x: 4, y: 8, size:1.1 },
+					{ x: 5.5, y: 2, size: 3.2 },
+					{ x: 3, y: 6, size: 3.2 }
+				]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>plot-space diagonal gradient</h1>
+	<p>Bubble</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_bubble3.html b/dojox/charting/tests/gradients/test_grad_bubble3.html
new file mode 100644
index 0000000..814548a
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_bubble3.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Bubble #3</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ],
+					noRadialConv: true
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {minorLabels: false}).
+                addAxis("y", {vertical: true, minorLabels: false, max: 10}).
+                addPlot("default", {type: "Bubble"}).
+				addSeries("Series A", [
+					{ x: 0.5, y: 5, size: 1.4 },
+					{ x: 1.5, y: 1.5, size: 4.5 },
+					{ x: 2, y: 9, size:1.5 },
+					{ x: 5, y: 0.3, size:0.8 }
+				]).
+				addSeries("Series B", [
+					{ x: 0.3, y: 8, size: 2.5 },
+					{ x: 4, y: 8, size:1.1 },
+					{ x: 5.5, y: 2, size: 3.2 },
+					{ x: 3, y: 6, size: 3.2 }
+				]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>shape-space gradient</h1>
+	<p>Bubble</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_bubble4.html b/dojox/charting/tests/gradients/test_grad_bubble4.html
new file mode 100644
index 0000000..1b5f057
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_bubble4.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Bubble #4</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "shapeX", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shapeX", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shapeY", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {minorLabels: false}).
+                addAxis("y", {vertical: true, minorLabels: false, max: 10}).
+                addPlot("default", {type: "Bubble"}).
+				addSeries("Series A", [
+					{ x: 0.5, y: 5, size: 1.4 },
+					{ x: 1.5, y: 1.5, size: 4.5 },
+					{ x: 2, y: 9, size:1.5 },
+					{ x: 5, y: 0.3, size:0.8 }
+				]).
+				addSeries("Series B", [
+					{ x: 0.3, y: 8, size: 2.5 },
+					{ x: 4, y: 8, size:1.1 },
+					{ x: 5.5, y: 2, size: 3.2 },
+					{ x: 3, y: 6, size: 3.2 }
+				]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>1D shape-space gradient</h1>
+	<p>Bubble</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_bubble6.html b/dojox/charting/tests/gradients/test_grad_bubble6.html
new file mode 100644
index 0000000..b49ec91
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_bubble6.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Bubble #6</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "#ed0" }, { offset: 0.5, color: "white" }, { offset: 1, color: "#ed0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "#e00" }, { offset: 0.5, color: "#eaa" }, { offset: 1, color: "#e00" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "#0e0" }, { offset: 0.5, color: "#aea" }, { offset: 1, color: "#0e0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "#00e" }, { offset: 0.5, color: "#aae" }, { offset: 1, color: "#00e" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {minorLabels: false}).
+                addAxis("y", {vertical: true, minorLabels: false, max: 10}).
+                addPlot("default", {type: "Bubble"}).
+				addSeries("Series A", [
+					{ x: 0.5, y: 5, size: 1.4 },
+					{ x: 1.5, y: 1.5, size: 4.5 },
+					{ x: 2, y: 9, size:1.5 },
+					{ x: 5, y: 0.3, size:0.8 }
+				]).
+				addSeries("Series B", [
+					{ x: 0.3, y: 8, size: 2.5 },
+					{ x: 4, y: 8, size:1.1 },
+					{ x: 5.5, y: 2, size: 3.2 },
+					{ x: 3, y: 6, size: 3.2 }
+				]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>radial gradient</h1>
+	<p>Bubble</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_columns1.html b/dojox/charting/tests/gradients/test_grad_columns1.html
new file mode 100644
index 0000000..8f3506a
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_columns1.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Columns #1</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#ed0" }, { offset: 0.5, color: "#eda" }, { offset: 1, color: "#ed0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#e00" }, { offset: 0.5, color: "#eaa" }, { offset: 1, color: "#e00" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#0e0" }, { offset: 0.5, color: "#aea" }, { offset: 1, color: "#0e0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#00e" }, { offset: 0.5, color: "#aae" }, { offset: 1, color: "#00e" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "Columns"}).
+                addSeries("Series A", [1, 2, 3, 4, 5]).
+                addSeries("Series B", [5, 4, 3, 2, 1]).
+                render();
+
+            var chart2 = new dojox.charting.Chart2D("c2").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "StackedColumns"}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+
+            var chart3 = new dojox.charting.Chart2D("c3").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "ClusteredColumns", gap: 5}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>plot-space left-to-right gradient</h1>
+	<p>Columns</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Stacked Columns</p>
+    <div id="c2" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Clustered Columns</p>
+    <div id="c3" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_columns2.html b/dojox/charting/tests/gradients/test_grad_columns2.html
new file mode 100644
index 0000000..065b29b
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_columns2.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Columns #2</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 100, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "Columns"}).
+                addSeries("Series A", [1, 2, 3, 4, 5]).
+                addSeries("Series B", [5, 4, 3, 2, 1]).
+                render();
+
+            var chart2 = new dojox.charting.Chart2D("c2").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "StackedColumns"}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+
+            var chart3 = new dojox.charting.Chart2D("c3").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "ClusteredColumns", gap: 5}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>plot-space diagonal gradient</h1>
+	<p>Columns</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Stacked Columns</p>
+    <div id="c2" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Clustered Columns</p>
+    <div id="c3" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_columns3.html b/dojox/charting/tests/gradients/test_grad_columns3.html
new file mode 100644
index 0000000..1dbd4f5
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_columns3.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Columns #3</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "Columns"}).
+                addSeries("Series A", [1, 2, 3, 4, 5]).
+                addSeries("Series B", [5, 4, 3, 2, 1]).
+                render();
+
+            var chart2 = new dojox.charting.Chart2D("c2").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "StackedColumns"}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+
+            var chart3 = new dojox.charting.Chart2D("c3").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "ClusteredColumns", gap: 5}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>shape-space gradient</h1>
+	<p>Columns</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Stacked Columns</p>
+    <div id="c2" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Clustered Columns</p>
+    <div id="c3" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_columns4.html b/dojox/charting/tests/gradients/test_grad_columns4.html
new file mode 100644
index 0000000..366a19c
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_columns4.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Columns #4</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "shapeX", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shapeX", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shapeY", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "Columns"}).
+                addSeries("Series A", [1, 2, 3, 4, 5]).
+                addSeries("Series B", [5, 4, 3, 2, 1]).
+                render();
+
+            var chart2 = new dojox.charting.Chart2D("c2").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "StackedColumns"}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+
+            var chart3 = new dojox.charting.Chart2D("c3").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "ClusteredColumns", gap: 5}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>1D shape-space gradient</h1>
+	<p>Columns</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Stacked Columns</p>
+    <div id="c2" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Clustered Columns</p>
+    <div id="c3" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_columns5.html b/dojox/charting/tests/gradients/test_grad_columns5.html
new file mode 100644
index 0000000..b1bdc1b
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_columns5.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Columns #5</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: { // red plastic cylinder
+                                type: "linear", space: "shapeX", x1: 0, y1: 0, x2: 100, y2: 0,
+                                //colors: [{"offset":0,"color":{"r":174,"g":0,"b":0,"a":1}},{"offset":9.992007221626409e-16,"color":{"r":174,"g":0,"b":0,"a":1}},{"offset":0.013851578375197016,"color":{"r":215,"g":0,"b":0,"a":1}},{"offset":0.031369214560646785,"color":{"r":221,"g":0,"b":0,"a":1}},{"offset":0.052730424013296195,"color":{"r":227,"g":0,"b":0,"a":1}},{"offset":0.07793466262473725,"color":{"r":231,"g":0,"b":0,"a":1}},{"offset":0.10686548826723474,"color":{"r":235,"g":0,"b":0," [...]
+                                colors: [{"offset":0,"color":{"r":174,"g":0,"b":0,"a":1}},{"offset":0.08,"color":{"r":231,"g":0,"b":0,"a":1}},{"offset":0.18,"color":{"r":237,"g":150,"b":150,"a":1}},{"offset":0.3,"color":{"r":231,"g":0,"b":0,"a":1}},{"offset":0.39,"color":{"r":221,"g":0,"b":0,"a":1}},{"offset":0.49,"color":{"r":206,"g":0,"b":0,"a":1}},{"offset":0.58,"color":{"r":187,"g":0,"b":0,"a":1}},{"offset":0.68,"color":{"r":165,"g":0,"b":0,"a":1}},{"offset":0.8,"color":{"r":128,"g": [...]
+                            }
+                        },
+                        {
+                            fill: { // yellow plastic cylinder
+                                type: "linear", space: "shapeX", x1: 0, y1: 0, x2: 100, y2: 0,
+                                //colors: [{"offset":0,"color":{"r":174,"g":174,"b":0,"a":1}},{"offset":9.992007221626409e-16,"color":{"r":174,"g":174,"b":0,"a":1}},{"offset":0.01385157837519746,"color":{"r":215,"g":215,"b":0,"a":1}},{"offset":0.03136921456064723,"color":{"r":221,"g":221,"b":0,"a":1}},{"offset":0.05273042401329664,"color":{"r":227,"g":227,"b":0,"a":1}},{"offset":0.07793466262473725,"color":{"r":231,"g":231,"b":0,"a":1}},{"offset":0.10686548826723508,"color":{"r":235,"g": [...]
+                                colors: [{"offset":0,"color":{"r":174,"g":174,"b":0,"a":1}},{"offset":0.08,"color":{"r":231,"g":231,"b":0,"a":1}},{"offset":0.18,"color":"white"},{"offset":0.3,"color":{"r":231,"g":231,"b":0,"a":1}},{"offset":0.39,"color":{"r":221,"g":221,"b":0,"a":1}},{"offset":0.49,"color":{"r":206,"g":206,"b":0,"a":1}},{"offset":0.58,"color":{"r":187,"g":187,"b":0,"a":1}},{"offset":0.68,"color":{"r":165,"g":165,"b":0,"a":1}},{"offset":0.8,"color":{"r":128,"g":128,"b":0, [...]
+                            }
+                        },
+                        {
+                            fill: { // blue plastic cylinder
+                                type: "linear", space: "shapeX", x1: 0, y1: 0, x2: 100, y2: 0,
+                                //colors: [{"offset":0,"color":{"r":0,"g":0,"b":174,"a":1}},{"offset":5.551115123125783e-16,"color":{"r":0,"g":0,"b":174,"a":1}},{"offset":0.013851578375196572,"color":{"r":0,"g":0,"b":215,"a":1}},{"offset":0.03136921456064645,"color":{"r":0,"g":0,"b":221,"a":1}},{"offset":0.052730424013296195,"color":{"r":0,"g":0,"b":227,"a":1}},{"offset":0.0779346626247368,"color":{"r":0,"g":0,"b":231,"a":1}},{"offset":0.10686548826723419,"color":{"r":0,"g":0,"b":235,"a" [...]
+                                colors: [{"offset":0,"color":{"r":0,"g":0,"b":174,"a":1}},{"offset":0.08,"color":{"r":0,"g":0,"b":231,"a":1}},{"offset":0.18,"color":{"r":150,"g":150,"b":237,"a":1}},{"offset":0.3,"color":{"r":0,"g":0,"b":231,"a":1}},{"offset":0.39,"color":{"r":0,"g":0,"b":221,"a":1}},{"offset":0.49,"color":{"r":0,"g":0,"b":206,"a":1}},{"offset":0.58,"color":{"r":0,"g":0,"b":187,"a":1}},{"offset":0.68,"color":{"r":0,"g":0,"b":165,"a":1}},{"offset":0.8,"color":{"r":0,"g":0, [...]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "Columns"}).
+                addSeries("Series A", [1, 2, 3, 4, 5]).
+                addSeries("Series B", [5, 4, 3, 2, 1]).
+                render();
+
+            var chart2 = new dojox.charting.Chart2D("c2").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "StackedColumns"}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+
+            var chart3 = new dojox.charting.Chart2D("c3").
+                setTheme(theme1).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true,  minorTickStep: 0.5}).
+                addPlot("default", {type: "ClusteredColumns", gap: 5}).
+                addSeries("Series A", [2, 3, 3, 3, 5]).
+                addSeries("Series B", [1, 4, 5, 2, 1]).
+                addSeries("Series C", [2, 1, 2, 1, 3]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>1D shape-space pseudo-3D gradient</h1>
+	<p>Columns</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Stacked Columns</p>
+    <div id="c2" style="position: relative; width: 600px; height: 400px;"></div>
+	<p>Clustered Columns</p>
+    <div id="c3" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_pie1.html b/dojox/charting/tests/gradients/test_grad_pie1.html
new file mode 100644
index 0000000..838da9a
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_pie1.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Pie #1</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#ed0" }, { offset: 0.5, color: "#eda" }, { offset: 1, color: "#ed0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#e00" }, { offset: 0.5, color: "#eaa" }, { offset: 1, color: "#e00" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#0e0" }, { offset: 0.5, color: "#aea" }, { offset: 1, color: "#0e0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#00e" }, { offset: 0.5, color: "#aae" }, { offset: 1, color: "#00e" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addPlot("default", {type: "Pie", radius: 180}).
+                addSeries("Series A", [2, 3, 4]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>plot-space left-to-right gradient</h1>
+	<p>Pie</p>
+    <div id="c1" style="position: relative; width: 400px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_pie2.html b/dojox/charting/tests/gradients/test_grad_pie2.html
new file mode 100644
index 0000000..85e9c04
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_pie2.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Pie #2</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 100, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addPlot("default", {type: "Pie", radius: 180}).
+                addSeries("Series A", [2, 3, 4]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>plot-space diagonal gradient</h1>
+	<p>Pie</p>
+    <div id="c1" style="position: relative; width: 400px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_pie3.html b/dojox/charting/tests/gradients/test_grad_pie3.html
new file mode 100644
index 0000000..a66840a
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_pie3.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Pie #3</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ],
+					noRadialConv: true
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addPlot("default", {type: "Pie", radius: 180}).
+                addSeries("Series A", [2, 3, 4]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>shape-space gradient</h1>
+	<p>Pie</p>
+    <div id="c1" style="position: relative; width: 400px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_pie4.html b/dojox/charting/tests/gradients/test_grad_pie4.html
new file mode 100644
index 0000000..7e7665a
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_pie4.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Pie #4</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "shapeX", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shapeX", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "shapeY", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addPlot("default", {type: "Pie", radius: 180}).
+                addSeries("Series A", [2, 3, 4]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>1D shape-space gradient</h1>
+	<p>Pie</p>
+    <div id="c1" style="position: relative; width: 400px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_pie7.html b/dojox/charting/tests/gradients/test_grad_pie7.html
new file mode 100644
index 0000000..96eb579
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_pie7.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Pie #7</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "#faa" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "#afa" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "#aaf" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addPlot("default", {type: "Pie", radius: 180, radGrad: "linear"}).
+                addSeries("Series A", [2, 3, 4]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>radial-to-linear pie slice gradient</h1>
+	<p>Pie</p>
+    <div id="c1" style="position: relative; width: 400px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_pie8.html b/dojox/charting/tests/gradients/test_grad_pie8.html
new file mode 100644
index 0000000..e900ff8
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_pie8.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Pie #8</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "red" }, { offset: 1, color: "white" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "green" }, { offset: 1, color: "white" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "blue" }, { offset: 1, color: "white" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addPlot("default", {type: "Pie", radius: 180, radGrad: "linear"}).
+                addSeries("Series A", [2, 3, 4]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>radial-to-linear pie slice gradient</h1>
+	<p>Pie</p>
+    <div id="c1" style="position: relative; width: 400px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_pie9.html b/dojox/charting/tests/gradients/test_grad_pie9.html
new file mode 100644
index 0000000..1a622b3
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_pie9.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Pie #9</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "#faa" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "#afa" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "#aaf" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addPlot("default", {type: "Pie", radius: 180, radGrad: "fan"}).
+                addSeries("Series A", [2, 3, 4]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>radial-to-fan pie slice gradient</h1>
+	<p>Pie</p>
+    <div id="c1" style="position: relative; width: 400px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_pieA.html b/dojox/charting/tests/gradients/test_grad_pieA.html
new file mode 100644
index 0000000..5115998
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_pieA.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Pie #A</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "red" }, { offset: 1, color: "white" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "green" }, { offset: 1, color: "white" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "radial", space: "shape", cx: 0, cy: 0, r: 100,
+                                colors: [{ offset: 0, color: "blue" }, { offset: 1, color: "white" }]
+                            }
+                        }
+                    ]
+                });
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addPlot("default", {type: "Pie", radius: 180, radGrad: "fan", fanSize: 3}).
+                addSeries("Series A", [2, 3, 4]).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>radial-to-fan pie slice gradient</h1>
+	<p>Pie</p>
+    <div id="c1" style="position: relative; width: 400px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_scatter1.html b/dojox/charting/tests/gradients/test_grad_scatter1.html
new file mode 100644
index 0000000..6a5c2a1
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_scatter1.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Scatter #1</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#ed0" }, { offset: 0.5, color: "#eda" }, { offset: 1, color: "#ed0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#e00" }, { offset: 0.5, color: "#eaa" }, { offset: 1, color: "#e00" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#0e0" }, { offset: 0.5, color: "#aea" }, { offset: 1, color: "#0e0" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "#00e" }, { offset: 0.5, color: "#aae" }, { offset: 1, color: "#00e" }]
+                            }
+                        }
+                    ]
+                });
+			
+			var run1 = [], run2 = [], run3 = [];
+			for(var i = 0; i < 12; ++i){
+				for(var j = 0; j < 8; ++j){
+					run1.push({x: i + 0.7, y: j + 0.7});
+					run2.push({x: i + 1.3, y: j + 1.3});
+					run3.push({x: i + 0.7, y: j + 1.3});
+				}
+			}
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {includeZero: true,  minorLabels: false}).
+                addAxis("y", {vertical: true, includeZero: true,  minorLabels: false}).
+                addPlot("default", {type: "Scatter"}).
+                addSeries("Series A", run1).
+                addSeries("Series B", run2).
+                addSeries("Series C", run3).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>plot-space left-to-right gradient</h1>
+	<p>Scatter</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_scatter2.html b/dojox/charting/tests/gradients/test_grad_scatter2.html
new file mode 100644
index 0000000..1d2fcb0
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_scatter2.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Scatter #2</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "red" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 100, x2: 100, y2: 0,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "blue" }]
+                            }
+                        },
+                        {
+                            fill: {
+                                type: "linear", space: "plot", x1: 0, y1: 0, x2: 100, y2: 100,
+                                colors: [{ offset: 0, color: "white" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+			
+			var run1 = [], run2 = [], run3 = [];
+			for(var i = 0; i < 12; ++i){
+				for(var j = 0; j < 8; ++j){
+					run1.push({x: i + 0.7, y: j + 0.7});
+					run2.push({x: i + 1.3, y: j + 1.3});
+					run3.push({x: i + 0.7, y: j + 1.3});
+				}
+			}
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {includeZero: true,  minorLabels: false}).
+                addAxis("y", {vertical: true, includeZero: true,  minorLabels: false}).
+                addPlot("default", {type: "Scatter"}).
+                addSeries("Series A", run1).
+                addSeries("Series B", run2).
+                addSeries("Series C", run3).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>plot-space diagonal gradient</h1>
+	<p>Scatter</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/gradients/test_grad_scatterB.html b/dojox/charting/tests/gradients/test_grad_scatterB.html
new file mode 100644
index 0000000..ac4206b
--- /dev/null
+++ b/dojox/charting/tests/gradients/test_grad_scatterB.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Gradient: Scatter #2</title>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+		dojo.require("dojox.charting.Chart2D");
+        
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            
+            var theme1 = new dojox.charting.Theme({
+                    seriesThemes: [
+                        {
+                            shadow: null,
+                            fill: {
+                                type: "radial", space: "plot", cx: 50, cy: 50, r: 75,
+                                colors: [{ offset: 0, color: "red" }, { offset: 0.5, color: "yellow" }, { offset: 1, color: "green" }]
+                            }
+                        }
+                    ]
+                });
+			
+			var run1 = [], run2 = [], run3 = [];
+			for(var i = 0; i < 12; ++i){
+				for(var j = 0; j < 8; ++j){
+					run1.push({x: i + 0.7, y: j + 0.7});
+					run2.push({x: i + 1.3, y: j + 1.3});
+					run3.push({x: i + 0.7, y: j + 1.3});
+				}
+			}
+
+            var chart1 = new dojox.charting.Chart2D("c1").
+                setTheme(theme1).
+                addAxis("x", {includeZero: true,  minorLabels: false}).
+                addAxis("y", {vertical: true, includeZero: true,  minorLabels: false}).
+                addPlot("default", {type: "Scatter"}).
+                addSeries("Series A", run1).
+                addSeries("Series B", run2).
+                addSeries("Series C", run3).
+                render();
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body>
+    <p><button id="start" onclick="run();">Start!</button></p>
+	<h1>plot-space radial gradient</h1>
+	<p>Scatter</p>
+    <div id="c1" style="position: relative; width: 600px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/runTests.html b/dojox/charting/tests/runTests.html
new file mode 100644
index 0000000..6e13c2a
--- /dev/null
+++ b/dojox/charting/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox.wire Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.charting.tests.charting"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/charting/tests/stock.json b/dojox/charting/tests/stock.json
new file mode 100644
index 0000000..746d025
--- /dev/null
+++ b/dojox/charting/tests/stock.json
@@ -0,0 +1,8 @@
+{ "identifier": "symbol", "idAttribute":"symbol", "label": "symbol","items": [
+	{ "symbol":"ANDT", "name":"Anduct",           	"historicPrice":[0.01,3.52,3.66,3.11,3.90,3.11,3.11], "open":3.13,  "price":3.52, "updown":"^",  "change":"+0.39 (+21%)", "low":3.13, "high":3.69 },
+	{ "symbol":"ATEU", "name":"Ations Europe",		"historicPrice":[6.72,6.76,6.61,6.41,6.31,6.99,7.20], "open":6.72,  "price":6.76, "updown":"^",  "change":"+0.04 (+01%)", "low":6.56, "high":6.77 },
+	{ "symbol":"BGCN", "name":"Bagies Consulting",	"historicPrice":[4.11,3.98,4.05,4.20,4.16,4.22,3.80], "open":4.11,  "price":3.98, "updown":"v",  "change":"-0.13 (-05%)", "low":3.77, "high":4.11 },
+	{ "symbol":"BAYC", "name":"BAY Corporation",	"historicPrice":[9.79,9.60,9.50,2.23,9.45,9.76,9.99], "open":9.79,  "price":9.60, "updown":"v",  "change":"-0.19 (+14%)", "low":9.60, "high":9.81 },
+	{ "symbol":"CRCR", "name":"Corcor PLC",			"historicPrice":[8.44,8.44,8.54,8.60,9.65,8.42,8.44], "open":8.44,  "price":8.44, "updown":"--", "change":"+0.00 (+00%)", "low":8.22, "high":8.44 },
+	{ "symbol":"DTOA", "name":"Datio PLC",			"historicPrice":[2.11,2.47,3.11,3.06,3.01,3.01,3.00], "open":2.11,  "price":2.47, "updown":"^",  "change":"+0.36 (+36%)", "low":2.11, "high":3.01 }
+]}
diff --git a/dojox/charting/tests/test_DataChart.html b/dojox/charting/tests/test_DataChart.html
new file mode 100644
index 0000000..5f054f9
--- /dev/null
+++ b/dojox/charting/tests/test_DataChart.html
@@ -0,0 +1,199 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>DataChart Test</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	@import "../../../dijit/themes/tundra/form/Button.css";
+	@import "../../../dijit/themes/tundra/form/Common.css";
+	@import "../../../dijit/themes/tundra/Common.css";
+	@import "../../../dijit/themes/dijit.css";
+	
+	#spinners{
+		clear:both;
+	}
+	#spinners label{
+		width:60px;
+		line-height:30px;
+		margin-top:10px;
+	}
+	.tundra #spinners .dijitSpinner	{
+		width:70px !important;
+		margin:5px !important;
+	}
+	.tundra #spinners .dijitSpinner{
+		width:80px !important;
+	}
+	.dijitSpinner{
+		padding:0px !important;
+	}
+	#spinners .dijitSpinnerButtonContainer{
+		line-height:23px;
+	}
+	.dj_ie #spinners .dijitSpinnerButtonContainer{
+		height:25px;
+	}
+	.dijitInputLayoutContainer .dijitInputField input{
+		padding:5px 0px 0px 5px;
+	}
+	.dj_webkit .dijitInputLayoutContainer .dijitInputField input{
+		padding:10px 0px 0px 5px;
+	}
+	
+	
+
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: false, parseOnLoad:true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.charting.DataChart");
+dojo.require("dojo.data.ItemFileWriteStore");
+dojo.require("dijit.form.NumberSpinner");
+
+var store = new dojo.data.ItemFileWriteStore({ url:"stock.json" });
+		
+makeCharts = function(){
+	
+	
+	
+	var lines = new dojox.charting.DataChart("lines", {
+		displayRange:7,
+		xaxis:{labels:["0", "A","B","C","D","E","F","G","H","I","J"]},
+		type: dojox.charting.plot2d.Lines
+	});
+	lines.setStore(store, {symbol:"*"}, "historicPrice");
+	
+	var linesC = new dojox.charting.DataChart("linesC", {
+		displayRange:6,
+		xaxis:{labelFunc:"seriesLabels"},
+		yaxis:{minorLabels:true},
+		type: dojox.charting.plot2d.Lines,
+		comparative:true
+	});
+	linesC.setStore(store, {symbol:"*"}, "price");
+	
+	var cols = new dojox.charting.DataChart("cols", {
+		displayRange:8,
+		scroll:false,
+		xaxis:{labelFunc:"seriesLabels"},
+		type: dojox.charting.plot2d.Columns
+	});
+	cols.setStore(store, {symbol:"*"}, "price");
+	
+	var bars = new dojox.charting.DataChart("bars", {
+		displayRange:10,
+		yaxis:{max:8,min:1, majorTickStep:1, labelFunc:"seriesLabels", maxLabelSize:30},
+		scroll:false,
+		type: dojox.charting.plot2d.Bars
+	});
+	bars.setStore(store, {symbol:"*"}, "price");
+				 
+	var pie = new dojox.charting.DataChart("pie", {
+		type: dojox.charting.plot2d.Pie,
+		comparative:true
+	});
+	pie.setStore(store, {symbol:"*"}, "price");
+};
+makeSpinners = function(items){
+	dojo.forEach(items, function(m){
+		var nm = store.getLabel(m);
+		var num = store.getValue(m, "price");
+		console.log(nm, num);
+		var w = new dijit.form.NumberSpinner({
+			onChange:function(val){
+				val = val===0 ? 0.01 : val; //HACKS the no label-when-zero bug
+				console.log("OC:", nm, val);
+				store.setValue(m, "price", val);
+				//store.setValues(m, "historicPrice", store.getValues("historicPrice").push(val));
+				console.log("OC:", nm, val);
+			},
+			value:num,
+			constraints:{min:0, max:10,places:2},
+			className:"myField"
+		});
+		dojo.place('<label>'+nm+'</label>', dojo.byId("spinners"), "last")
+		dojo.place(w.domNode, "spinners", "last")
+	});
+}
+dojo.addOnLoad(function(){
+	makeCharts();
+	console.log(store.getFeatures())
+	store.fetch({query:{symbol:"*"}, onComplete: makeSpinners, onError:function(err){console.error(err)}})
+});
+
+handleSpinner = function(){
+	console.log(arguments)
+}
+</script>
+
+<style>
+	#charts{
+		clear:both;
+		margin-bottom:50px;
+	}
+	#charts span{
+		padding:0 10px;
+		display:block;
+		font-size:10px;
+	}
+	.lines, .linesC, .cols, .bars, .pie{
+		float:left;
+		border:1px solid #ccc;
+	}
+	.lines, #lines, .linesC, #linesC, .cols, #cols, .bars, #bars, .pie, #pie{
+		width:200px;
+		height:200px;
+	}
+	.lines, .linesC, .cols, .bars, .pie{
+		height:250px;
+		margin:3px;
+	}
+	.cols, #cols{
+		width:280px;
+	}
+	.linesC, #linesC{
+		width:260px;
+	}
+	.lines, #lines,.bars, #bars{
+		width:260px;
+	}
+</style>
+</head>
+<body class="tundra">
+	<h1>DataChart</h1>
+	<p>
+		DataChart extends dojox.charting.Chart2D and allows for a simple connection to a data store. When adding a store to a chart, it is necessary to also supply which
+		item property you wish charted. There are two types of properties supported: numbers and arrays of numbers (bubble charts take an array of objects and are not currently
+		supported). If the property is an array, a segment of the array is taken from the end that fits in the display range of the chart. Animated charts are also possible.
+	</p>
+	<p>
+		Use the spinner fields at the bottom to change the data. The charts listen to store changes an update automatically.
+	</p>
+	<div id="charts">
+		<div class="lines">
+			<div id="lines"></div>
+			<span>This line chart uses a different data field than the rest, which is an array. This chart will not upate using the spinners.</span>	
+		</div>
+		<div class="linesC">
+			<div id="linesC"></div>
+			<span>This chart uses <em>comparitive</em> to compare the price of each item. Without compartive, the items would each be a separate series and not be connected. Will update.</span>	
+		</div>
+		<div class="cols">
+			<div id="cols"></div>
+			<span>Each column in this chart is a separate series. Will update. </span>	
+		</div>	
+		<div class="bars">
+			<div id="bars"></div>
+			<span>Each bar in this chart is a separate series. Will update.</span>			
+		</div>
+		<div class="pie">
+			<div id="pie"></div>
+			<span>This chart also uses <em>comparitive</em> to create one series from several items. Will update.</span>	
+		</div>
+	</div>
+	<div id="spinners"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_DataSeries.html b/dojox/charting/tests/test_DataSeries.html
new file mode 100644
index 0000000..7ad9c44
--- /dev/null
+++ b/dojox/charting/tests/test_DataSeries.html
@@ -0,0 +1,216 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>DataSeries Test</title>
+
+<style>
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	@import "../../../dijit/themes/dijit.css";
+    @import "../../../dijit/themes/tundra/tundra.css";
+	
+	#spinners{
+		clear:both;
+	}
+	#spinners label{
+		width:60px;
+		line-height:30px;
+		margin-top:10px;
+	}
+	.tundra #spinners .dijitSpinner	{
+		width:70px !important;
+		margin:5px !important;
+	}
+	.tundra #spinners .dijitSpinner{
+		width:80px !important;
+	}
+	.dijitSpinner{
+		padding:0px !important;
+	}
+	#spinners .dijitSpinnerButtonContainer{
+		line-height:23px;
+	}
+	.dj_ie #spinners .dijitSpinnerButtonContainer{
+		height:25px;
+	}
+	.dijitInputLayoutContainer .dijitInputField input{
+		padding:5px 0px 0px 5px;
+	}
+	.dj_webkit .dijitInputLayoutContainer .dijitInputField input{
+		padding:10px 0px 0px 5px;
+	}
+
+    .dojoxLegendNode {border: 1px solid #ccc; margin: 5px 10px 5px 10px; padding: 3px;}
+    .dojoxLegendText {vertical-align: text-top; padding-right: 10px}
+    
+	#charts {
+		clear: both;
+		margin-bottom: 50px;
+	}
+	.chart-area {
+		float: left;
+		border: 1px solid #ccc;
+		width:  450px;
+        height: 350px;
+		margin: 3px;
+	}
+	.chart {
+		width:  450px;
+		height: 300px;
+	}
+</style>
+
+<script src="../../../dojo/dojo.js" djConfig="isDebug: false, parseOnLoad: true"></script>
+
+<script>
+    
+    dojo.require("dojox.charting.Chart2D");
+    dojo.require("dojox.charting.DataSeries");
+    dojo.require("dojox.charting.themes.ThreeD");
+    dojo.require("dojox.charting.widget.Legend");
+    
+    dojo.require("dojox.charting.plot2d.Markers");
+    dojo.require("dojox.charting.plot2d.Columns");
+    dojo.require("dojox.charting.plot2d.Pie");
+    
+    dojo.require("dojox.charting.action2d.Tooltip");
+    dojo.require("dojox.charting.action2d.MoveSlice");
+    dojo.require("dojox.charting.action2d.Magnify");
+    dojo.require("dojox.charting.action2d.Shake");
+
+    dojo.require("dojo.data.ItemFileWriteStore");
+
+    dojo.require("dijit.form.NumberSpinner");
+    
+    var store = new dojo.data.ItemFileWriteStore({url: "stock.json"});
+    
+    function addLegend(chart, node){
+        var legend = new dojox.charting.widget.Legend({chart: chart}, node);
+        dojo.connect(chart, "render", legend, "refresh");
+    }
+    
+    var templates = {
+        low:   "<strong>{0}</strong>: <strong>low {1}</strong> – {2} – {3}",
+        price: "<strong>{0}</strong>: {1} – <strong>price {2}</strong> – {3}",
+        high:  "<strong>{0}</strong>: {1} – {2} – <strong>high {3}</strong>"
+    };
+    
+    function valTrans(value, store, item){
+        return {
+            y: store.getValue(item, value),
+            tooltip: dojo.replace(
+                templates[value],
+                dojo.map(["symbol", "low", "price", "high"], function(field){
+                    return store.getValue(item, field);
+                })
+            )
+        };
+    }
+    
+    var chartL, chartC, chartP;
+    
+    makeCharts = function(){
+        chartL = new dojox.charting.Chart2D("lines").
+                setTheme(dojox.charting.themes.ThreeD).
+                addAxis("x", {fixLower: "major", fixUpper: "major", natural: true, majorTickStep: 5}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true}).
+                addPlot("default", {type: dojox.charting.plot2d.Markers}).
+                addSeries("Price", new dojox.charting.DataSeries(
+                    store, {query: {symbol: "*"}}, "price")).
+                render();
+        addLegend(chartL, "lines_legend");
+        new dojox.charting.action2d.Magnify(chartL);
+        new dojox.charting.action2d.Tooltip(chartL);
+
+        chartC = new dojox.charting.Chart2D("cols").
+                setTheme(dojox.charting.themes.ThreeD).
+                addAxis("x", {natural: true}).
+                addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true}).
+                addPlot("default", {type: dojox.charting.plot2d.Columns}).
+                addSeries("Low", new dojox.charting.DataSeries(
+                    store, {query: {symbol: "*"}}, dojo.hitch(null, valTrans, "low"))).
+                addSeries("Price", new dojox.charting.DataSeries(
+                    store, {query: {symbol: "*"}}, dojo.hitch(null, valTrans, "price"))).
+                addSeries("High", new dojox.charting.DataSeries(
+                    store, {query: {symbol: "*"}}, dojo.hitch(null, valTrans, "high"))).
+                render();
+        addLegend(chartC, "cols_legend");
+        new dojox.charting.action2d.Shake(chartC, "default", {shiftY: 0});
+        new dojox.charting.action2d.Tooltip(chartC);
+        
+        chartP = new dojox.charting.Chart2D("pie").
+                setTheme(dojox.charting.themes.ThreeD).
+                addPlot("default", {type: dojox.charting.plot2d.Pie, radius: 125}).
+                addSeries("Price", new dojox.charting.DataSeries(
+                    store, {query: {symbol: "*"}}, {y: "price", text: "symbol", tooltip: "price"})).
+                render();
+        addLegend(chartP, "pie_legend");
+        new dojox.charting.action2d.Tooltip(chartP);
+        new dojox.charting.action2d.MoveSlice(chartP);
+    };
+
+    makeSpinners = function(items){
+        dojo.forEach(items, function(m){
+            var nm = store.getLabel(m);
+            var num = store.getValue(m, "price");
+            console.log(nm, num);
+            var w = new dijit.form.NumberSpinner({
+                onChange: function(val){
+                    val = val===0 ? 0.01 : val; //HACKS the no label-when-zero bug
+                    console.log("OC:", nm, val);
+                    store.setValue(m, "price", val);
+                    //store.setValues(m, "historicPrice", store.getValues("historicPrice").push(val));
+                    console.log("OC:", nm, val);
+                },
+                value: num,
+                constraints: {min:0, max:10,places:2},
+                className: "myField",
+                intermediateChanges: true
+            });
+            dojo.place('<label>'+nm+'</label>', dojo.byId("spinners"), "last")
+            dojo.place(w.domNode, "spinners", "last")
+        });
+        
+        var labels = dojo.map(items, function(item, index){
+                return {
+                    value: index + 1,
+                    text:  store.getLabel(item)
+                }
+            });
+        chartC.addAxis("x", {natural: true, labels: labels}).render();
+    }
+
+    dojo.addOnLoad(function(){
+        makeCharts();
+        console.log(store.getFeatures())
+        store.fetch({query:{symbol:"*"}, onComplete: makeSpinners, onError:function(err){console.error(err)}})
+    });
+</script>
+
+</head>
+
+<body class="tundra">
+	<h1>DataSeries Test</h1>
+	<p>
+		Use the spinner fields at the bottom to change the data. The charts listen to store changes an update automatically.
+	</p>
+	<div id="charts">
+		<div class="chart-area">
+            <div id="lines_legend"></div>
+			<div id="lines" class="chart"></div>
+		</div>
+		<div class="chart-area">
+            <div id="cols_legend"></div>
+			<div id="cols" class="chart"></div>
+		</div>	
+		<div class="chart-area">
+            <div id="pie_legend"></div>
+			<div id="pie" class="chart"></div>
+		</div>
+	</div>
+	<div id="spinners"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_anim2d.html b/dojox/charting/tests/test_anim2d.html
new file mode 100644
index 0000000..b42db10
--- /dev/null
+++ b/dojox/charting/tests/test_anim2d.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+	<title>Chart 2D: Animation tests</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+	<!--
+	<script type="text/javascript" src="../../lang/functional.js"></script>
+	<script type="text/javascript" src="../../lang/utils.js"></script>
+	<script type="text/javascript" src="../Theme.js"></script>
+	<script type="text/javascript" src="../scaler/primitive.js"></script>
+	<script type="text/javascript" src="../scaler/linear.js"></script>
+	<script type="text/javascript" src="../Element.js"></script>
+	<script type="text/javascript" src="../axis2d/common.js"></script>
+	<script type="text/javascript" src="../axis2d/Base.js"></script>
+	<script type="text/javascript" src="../axis2d/Default.js"></script>
+	<script type="text/javascript" src="../plot2d/common.js"></script>
+	<script type="text/javascript" src="../plot2d/Base.js"></script>
+	<script type="text/javascript" src="../plot2d/Default.js"></script>
+	<script type="text/javascript" src="../plot2d/Lines.js"></script>
+	<script type="text/javascript" src="../plot2d/Areas.js"></script>
+	<script type="text/javascript" src="../plot2d/Markers.js"></script>
+	<script type="text/javascript" src="../plot2d/MarkersOnly.js"></script>
+	<script type="text/javascript" src="../plot2d/Scatter.js"></script>
+	<script type="text/javascript" src="../plot2d/Stacked.js"></script>
+	<script type="text/javascript" src="../plot2d/StackedLines.js"></script>
+	<script type="text/javascript" src="../plot2d/StackedAreas.js"></script>
+	<script type="text/javascript" src="../plot2d/Columns.js"></script>
+	<script type="text/javascript" src="../plot2d/StackedColumns.js"></script>
+	<script type="text/javascript" src="../plot2d/ClusteredColumns.js"></script>
+	<script type="text/javascript" src="../plot2d/Bars.js"></script>
+	<script type="text/javascript" src="../plot2d/StackedBars.js"></script>
+	<script type="text/javascript" src="../plot2d/ClusteredBars.js"></script>
+	<script type="text/javascript" src="../plot2d/Bubble.js"></script>
+	<script type="text/javascript" src="../plot2d/Grid.js"></script>
+	<script type="text/javascript" src="../plot2d/Pie.js"></script>
+	<script type="text/javascript" src="../Chart2D.js"></script>
+	-->
+	<script type="text/javascript">
+
+		dojo.require("dojox.charting.Chart2D");
+		dojo.require("dojox.charting.themes.Shrooms");
+		dojo.require("dojox.charting.themes.PlotKit.blue");
+		dojo.require("dojox.charting.themes.PlotKit.cyan");
+		dojo.require("dojox.charting.themes.PlotKit.green");
+		dojo.require("dojox.charting.themes.Ireland");
+		dojo.require("dojox.charting.themes.SageToLime");
+		dojo.require("dojox.charting.themes.Minty");
+		dojo.require("dojox.charting.themes.Tufte");
+
+		dojo.require("dojox.dtl");
+		dojo.require("dojox.dtl.Context");
+		charts = [
+			{
+				description: "Clustered columns with positive and negative values, readable theme, 1-second animate-in.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						setTheme(dojox.charting.themes.Tufte).
+						addAxis("x", { fixLower: "minor", fixUpper: "minor", natural: true }).
+						addAxis("y", { vertical: true, fixLower: "major", fixUpper: "major", includeZero: true }).
+						addPlot("default", { type: "ClusteredColumns", gap: 10, animate: { duration: 1000 } }).
+						addSeries("Series A", [ 2, 1, 0.5, -1, -2 ] ).
+						addSeries("Series B", [ -2, -1, -0.5, 1, 2 ] ).
+						addSeries("Series C", [ 1, 0.5, -1, -2, -3 ] ).
+						addSeries("Series D", [ 0.7, 1.5, -1.2, -1.25, 3 ] ).
+						render();
+				}
+			}
+		];
+		var now = function(){
+			return (new Date()).getTime();
+		};
+
+
+		dojo.addOnLoad(function(){
+			var defaultStyle = { width: "400px", height: "200px" };
+			var tmpl = new dojox.dtl.Template(dojo.byId("template").value);
+			var context = new dojox.dtl.Context({ charts: charts });
+			dojo.byId("charts").innerHTML = tmpl.render(context);
+
+			dojo.forEach(charts, function(item, idx){
+				var start = now();
+				var n = dojo.byId("chart_"+idx);
+				dojo.style(n, item.style||defaultStyle);
+				item.makeChart(n);
+				console.debug((now()-start), "ms to create:", (idx+1)+":", item.description);
+			});
+		});
+
+	</script>
+</head>
+<body>
+	<textarea id="template" style="display: none;">
+		{% for item in charts %}
+			<p>{{ forloop.counter }}: {{ item.description }}</p>
+			<div id="chart_{{ forloop.counter0 }}"></div>
+		{% endfor %}
+	</textarea>
+
+	<h1>Chart 2D: Animation tests</h1>
+
+	<div id="charts"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_axes.html b/dojox/charting/tests/test_axes.html
new file mode 100644
index 0000000..f7af683
--- /dev/null
+++ b/dojox/charting/tests/test_axes.html
@@ -0,0 +1,81 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Testing Axes</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script>
+
+dojo.require("dojox.charting.Chart2D");
+dojo.require("dojox.charting.themes.ThreeD");
+
+makeObjects = function(){
+    dojo.query("button").style("disabled", true);
+    
+    var customTheme = dojox.charting.themes.ThreeD.clone();
+    customTheme.plotarea.fill = "#fed";
+
+	var chart1 = new dojox.charting.Chart2D("test1").
+            setTheme(customTheme).
+            addAxis("x", {fixLower: "major", fixUpper: "major", natural: true, includeZero: true}).
+            addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true, includeZero: true}).
+            addPlot("default", {type: "Markers"}).
+            addSeries("Series A", [{x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y: 1}]).
+            addSeries("Series B", [{x: 3, y: 2}, {x: 4, y: 3}, {x: 5, y: 2}]).
+            addSeries("Series C", [{x: 5, y: 3}, {x: 6, y: 4}, {x: 7, y: 3}]).
+            render();
+
+	var chart2 = new dojox.charting.Chart2D("test2").
+            setTheme(customTheme).
+            addAxis("x", {fixLower: "major", fixUpper: "major", natural: true, includeZero: true}).
+            addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true, includeZero: true}).
+            addPlot("p1", {type: "Markers"}).
+            addPlot("p2", {type: "Markers"}).
+            addPlot("p3", {type: "Markers"}).
+            addSeries("Series A", [{x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y: 1}], {plot: "p1"}).
+            addSeries("Series B", [{x: 3, y: 2}, {x: 4, y: 3}, {x: 5, y: 2}], {plot: "p2"}).
+            addSeries("Series C", [{x: 5, y: 3}, {x: 6, y: 4}, {x: 7, y: 3}], {plot: "p3"}).
+            render();
+
+	var chart3 = new dojox.charting.Chart2D("test3").
+            setTheme(customTheme).
+            addAxis("x", {type: "Invisible", fixLower: "major", fixUpper: "major", natural: true, includeZero: true}).
+            addAxis("y", {type: "Invisible",vertical: true, fixLower: "major", fixUpper: "major", natural: true, includeZero: true}).
+            addPlot("default", {type: "Markers"}).
+            addSeries("Series A", [{x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y: 1}]).
+            addSeries("Series B", [{x: 3, y: 2}, {x: 4, y: 3}, {x: 5, y: 2}]).
+            addSeries("Series C", [{x: 5, y: 3}, {x: 6, y: 4}, {x: 7, y: 3}]).
+            render();
+
+	var chart4 = new dojox.charting.Chart2D("test4").
+            setTheme(customTheme).
+            addPlot("default", {type: "Markers"}).
+            addSeries("Series A", [{x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y: 1}]).
+            addSeries("Series B", [{x: 3, y: 2}, {x: 4, y: 3}, {x: 5, y: 2}]).
+            addSeries("Series C", [{x: 5, y: 3}, {x: 6, y: 4}, {x: 7, y: 3}]).
+            render();
+};
+
+dojo.ready(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Testing Axes</h1>
+<!--<p><button onclick="makeObjects();">Go</button></p>-->
+<p>1: Shared axes and three series</p>
+<div id="test1" style="width: 200px; height: 200px;"></div>
+<p>2: Shared axes and three plots.</p>
+<div id="test2" style="width: 200px; height: 200px;"></div>
+<p>3: Like #1 but invisible axes.</p>
+<div id="test3" style="width: 200px; height: 200px;"></div>
+<p>4: Like #1 but no axes.</p>
+<div id="test4" style="width: 200px; height: 200px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_axisZoomControl.html b/dojox/charting/tests/test_axisZoomControl.html
new file mode 100644
index 0000000..434d95e
--- /dev/null
+++ b/dojox/charting/tests/test_axisZoomControl.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML>
+<html>
+	<head>
+	    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+		<title>Axis Zoom Control</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+			@import "../../form/resources/RangeSlider.css";
+			#hrXAxisSlider .dijitSliderProgressBar{
+				height: 12px;
+				overflow: visible;
+				margin-top: -5px;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript" src="../Theme.js"></script>
+		<script type="text/javascript" src="../axis2d/Default.js"></script>
+		<script type="text/javascript" src="../plot2d/Default.js"></script>
+		<script type="text/javascript" src="../plot2d/Grid.js"></script>
+		<script type="text/javascript" src="../Chart2D.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("dojox.charting.Chart2D");
+			dojo.require("dojox.charting.themes.PlotKit.orange");
+			dojo.require("dojox.charting.action2d.Tooltip");
+			dojo.require("dojox.charting.action2d.Magnify");
+			dojo.require("dojox.form.RangeSlider");
+			dojo.require("dijit.form.HorizontalRuleLabels");
+			dojo.require("dijit.form.HorizontalRule");
+			
+			var chart;
+			makeObjects = function(){
+				chart = new dojox.charting.Chart2D("chart");
+				chart.setTheme(dojox.charting.themes.PlotKit.orange);
+				chart.addAxis("x", {fixLower: "minor", natural: true, stroke: "grey",
+					majorTick: {stroke: "black", length: 4}, minorTick: {stroke: "gray", length: 2}});
+				chart.addAxis("y", {vertical: true, min: 0, max: 100, majorTickStep: 5, minorTickStep: 1, stroke: "grey",
+					majorTick: {stroke: "black", length: 4}, minorTick: {stroke: "gray", length: 2}});
+				chart.addPlot("default", {type: "Lines",markers: true});
+				chart.addSeries("Series A", [
+					 8,  7,  3,  2,  5,  7,  9, 10,  2, 10,
+					14, 16, 18, 13, 16, 15, 20, 19, 15, 12,
+					24, 20, 20, 26, 28, 26, 28, 29, 24, 29,
+					31, 35, 37, 31, 35, 37, 37, 36, 31, 30,
+					50, 49, 42, 46, 44, 40, 47, 43, 48, 47,
+					51, 52, 52, 51, 54, 57, 58, 50, 54, 51,
+					62, 68, 67, 62, 62, 65, 61, 66, 65, 62,
+					74, 78, 78, 77, 74, 74, 72, 74, 70, 78,
+					84, 83, 85, 86, 86, 89, 89, 85, 86, 86,
+					98, 97, 93, 91, 92, 92, 99, 93, 94, 92
+				]);
+				chart.addPlot("grid", {type:"Grid", hMinorLines:true});
+				new dojox.charting.action2d.Tooltip(chart, "default");
+				new dojox.charting.action2d.Magnify(chart,"default");
+				chart.render();
+			};
+			zoomXAxis = function(){
+				chart.zoomIn("x",arguments[0]);
+				dojo.byId('minValue').value = arguments[0][0];
+				dojo.byId('maxValue').value = arguments[0][1];
+			}
+			dojo.addOnLoad(makeObjects);
+		</script>
+	</head>
+	<body class="tundra">
+		<h1>Axis Zoom Control</h1>
+		 Try to drag the slider endpoints and the bar to zoom X axis of the chart.
+		<div style="margin:20px">
+			<div id="chart" style="width: 800px; height: 400px;"></div>
+			<div id="hrXAxisSlider"
+				discreteValues="21"
+				onChange="zoomXAxis"
+				intermediateChanges="false"
+				dojoType="dojox.form.HorizontalRangeSlider"
+				showButtons="false"
+				style="width:748px;margin-left:40px"
+				value="0,100">
+				<ol dojoType="dijit.form.HorizontalRuleLabels" container="topDecoration" style="height:1.2em;font-size:75%;color:gray;" count="11">
+					<li>0</li><li>10</li><li>20</li><li>30</li><li>40</li><li>50</li><li>60</li><li>70</li><li>80</li><li>90</li><li>100</li>
+				</ol>
+				<div dojoType="dijit.form.HorizontalRule" container="topDecoration" count=11 style="height:10px;"></div>
+			</div>
+		</div>
+		<p>X Axis Lower Value: <input readonly id="minValue" size="10" value="0"/></p>
+		<p>X Axis Upper Value: <input readonly id="maxValue" size="10" value="100"/></p>
+		<p>That's all Folks!</p>
+	</body>
+</html>
diff --git a/dojox/charting/tests/test_bars.html b/dojox/charting/tests/test_bars.html
new file mode 100644
index 0000000..45d951b
--- /dev/null
+++ b/dojox/charting/tests/test_bars.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Bar chart</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<!--
+The next line should include Microsoft's Silverligth.js, if you plan to use the silverlight backend
+<script type="text/javascript" src="Silverlight.js"></script>
+-->
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../Chart3D.js"></script>
+<script type="text/javascript" src="../plot3d/Base.js"></script>
+<script type="text/javascript" src="../plot3d/Bars.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.charting.Chart3D");
+dojo.require("dojox.charting.plot3d.Bars");
+
+makeObjects = function(){
+	var m = dojox.gfx3d.matrix;
+	var chart = new dojox.charting.Chart3D("test", 
+		{
+			lights:   [{direction: {x: 5, y: 5, z: -5}, color: "white"}],
+			ambient:  {color:"white", intensity: 2},
+			specular: "white"
+		},
+		[m.cameraRotateXg(10), m.cameraRotateYg(-10), m.scale(0.8), m.cameraTranslate(-50, -50, 0)]
+	);
+	
+	var plot1 = new dojox.charting.plot3d.Bars(500, 500, {gap: 10, material: "yellow"});
+	plot1.setData([1,2,3,2,1,2,3,4,5]);
+	chart.addPlot(plot1);
+	
+	var plot2 = new dojox.charting.plot3d.Bars(500, 500, {gap: 10, material: "red"});
+	plot2.setData([2,3,4,3,2,3,4,5,5]);
+	chart.addPlot(plot2);
+	
+	var plot3 = new dojox.charting.plot3d.Bars(500, 500, {gap: 10, material: "blue"});
+	plot3.setData([3,4,5,4,3,4,5,5,5]);
+	chart.addPlot(plot3);
+	
+	chart.generate().render();
+	
+	//dojo.byId("out1").value = dojo.byId("test").innerHTML;
+	//dojo.byId("out2").value = dojox.gfx.utils.toJson(surface, true);
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Bar chart</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<!--
+<p><button onclick="makeObjects();">Go</button></p>
+<p><textarea id="out1" cols="40" rows="5"></textarea></p>
+<p><textarea id="out2" cols="40" rows="5"></textarea></p>
+-->
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_chart2d.html b/dojox/charting/tests/test_chart2d.html
new file mode 100644
index 0000000..5e27c71
--- /dev/null
+++ b/dojox/charting/tests/test_chart2d.html
@@ -0,0 +1,851 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+	<title>Chart 2D</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+	<!--
+	<script type="text/javascript" src="../../lang/functional.js"></script>
+	<script type="text/javascript" src="../../lang/utils.js"></script>
+	<script type="text/javascript" src="../Theme.js"></script>
+	<script type="text/javascript" src="../scaler/primitive.js"></script>
+	<script type="text/javascript" src="../scaler/linear.js"></script>
+	<script type="text/javascript" src="../Element.js"></script>
+	<script type="text/javascript" src="../axis2d/common.js"></script>
+	<script type="text/javascript" src="../axis2d/Base.js"></script>
+	<script type="text/javascript" src="../axis2d/Default.js"></script>
+	<script type="text/javascript" src="../plot2d/common.js"></script>
+	<script type="text/javascript" src="../plot2d/Base.js"></script>
+	<script type="text/javascript" src="../plot2d/Default.js"></script>
+	<script type="text/javascript" src="../plot2d/Lines.js"></script>
+	<script type="text/javascript" src="../plot2d/Areas.js"></script>
+	<script type="text/javascript" src="../plot2d/Markers.js"></script>
+	<script type="text/javascript" src="../plot2d/MarkersOnly.js"></script>
+	<script type="text/javascript" src="../plot2d/Scatter.js"></script>
+	<script type="text/javascript" src="../plot2d/Stacked.js"></script>
+	<script type="text/javascript" src="../plot2d/StackedLines.js"></script>
+	<script type="text/javascript" src="../plot2d/StackedAreas.js"></script>
+	<script type="text/javascript" src="../plot2d/Columns.js"></script>
+	<script type="text/javascript" src="../plot2d/StackedColumns.js"></script>
+	<script type="text/javascript" src="../plot2d/ClusteredColumns.js"></script>
+	<script type="text/javascript" src="../plot2d/Bars.js"></script>
+	<script type="text/javascript" src="../plot2d/StackedBars.js"></script>
+	<script type="text/javascript" src="../plot2d/ClusteredBars.js"></script>
+	<script type="text/javascript" src="../plot2d/Bubble.js"></script>
+	<script type="text/javascript" src="../plot2d/Grid.js"></script>
+	<script type="text/javascript" src="../plot2d/Pie.js"></script>
+	<script type="text/javascript" src="../Chart2D.js"></script>
+	-->
+	<script type="text/javascript">
+
+		dojo.require("dojox.charting.Chart2D");
+		dojo.require("dojox.charting.themes.Shrooms");
+		dojo.require("dojox.charting.themes.PlotKit.blue");
+		dojo.require("dojox.charting.themes.PlotKit.cyan");
+		dojo.require("dojox.charting.themes.PlotKit.green");
+		dojo.require("dojox.charting.themes.Ireland");
+		dojo.require("dojox.charting.themes.SageToLime");
+		dojo.require("dojox.charting.themes.Minty");
+		dojo.require("dojox.charting.themes.Tufte");
+
+		dojo.require("dojox.dtl");
+		dojo.require("dojox.dtl.Context");
+		charts = [
+			{
+				description: "Clustered columns with positive and negative values, readable theme.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						setTheme(dojox.charting.themes.Tufte).
+						addAxis("x", { fixLower: "minor", fixUpper: "minor", natural: true }).
+						addAxis("y", { vertical: true, fixLower: "major", fixUpper: "major", includeZero: true }).
+						addPlot("default", { type: "ClusteredColumns", gap: 10 }).
+						addSeries("Series A", [ 2, 1, 0.5, -1, -2 ] ).
+						addSeries("Series B", [ -2, -1, -0.5, 1, 2 ] ).
+						addSeries("Series C", [ 1, 0.5, -1, -2, -3 ] ).
+						addSeries("Series D", [ 0.7, 1.5, -1.2, -1.25, 3 ] ).
+						render();
+				}
+			},
+			{
+				description: "Bubble chart, green theme.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						setTheme(dojox.charting.themes.SageToLime).
+						addPlot("default", { type: "Bubble", shadow:  {dx: 1, dy: 1, width: 2, color: [0, 0, 0, 0.3]} }).
+						addAxis("x", {
+							min: 0,
+							max: 6,
+							majorTick: { stroke: "black", length: 3 },
+							minorTick: { stroke: "gray", length: 3 }
+						}).
+						addAxis("y", {
+							vertical: true,
+							min: 0,
+							max: 10,
+							majorTick: { stroke: "black", length: 3 },
+							minorTick: { stroke: "gray", length: 3 }
+						}).
+						addSeries("Series A", [
+							{ x: 0.5, y: 5, size: 1.4 },
+							{ x: 1.5, y: 1.5, size: 4.5 },
+							{ x: 2, y: 9, size:1.5 },
+							{ x: 5, y: 0.3, size:0.8 }
+						]).
+						addSeries("Series B", [
+							{ x: 0.3, y: 8, size: 2.5 },
+							{ x: 4, y: 6, size:1.1 },
+							{ x: 5.5, y: 2, size: 3.2 }
+						]).
+						render();
+				}
+			},
+			{
+				description: "Lines, calculated labels",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x", {
+							majorLabels: true, 
+							minorLabels: true, 
+							includeZero: true, 
+							minorTicks: false, 
+							microTicks: false,
+							majorTickStep: 2,
+							htmlLabels: true,                                                                    
+							labelFunc: function(value){
+								return value + " s";
+							},
+							maxLabelSize: 30,
+							fixUpper: "major", fixLower: "major",                                                
+							majorTick: { length: 3 }
+						}).
+						addAxis("y", {
+							labelFunc: function(value){
+								return value + " thingers";
+							},
+							maxLabelSize: 50,
+							vertical: true,
+							// htmlLabels: false,
+							microTicks: true,
+							minorTicks: true, 
+							majorTick: { stroke: "black", length: 3 }
+						}).
+						addSeries("Series A", [ 1, 2, 1, 2, 1, 2, 1 ]).
+						addSeries("Series B", [ 2, 1, 2, 1, 2, 1, 2 ]).
+						render();
+				}
+			},
+			{
+				description: "Lines, pre-computed labels",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x", {
+							majorLabels: true, 
+							minorLabels: true, 
+							includeZero: true, 
+							minorTicks: false, 
+							microTicks: false,
+							majorTickStep: 2,
+							labels: [
+								{ value: 0, text: "nada" },
+								{ value: 2, text: "2 units" },
+								{ value: 4, text: "4 units" },
+								{ value: 8, text: "2*4 units" }
+							],
+							htmlLabels: true,                                                                    
+							fixUpper: "major", fixLower: "major",                                                
+							majorTick: { length: 3 }
+						}).
+						addAxis("y", {
+							labels: [
+								{ value: 0, text: "nada" },
+								{ value: 1.1, text: "hrmm" },
+								{ value: 1.2, text: "?" },
+								{ value: 2, text: "2!" }
+							],
+							vertical: true,
+							// htmlLabels: false,
+							microTicks: true,
+							minorTicks: true, 
+							majorTick: { stroke: "black", length: 3 }
+						}).
+						addSeries("Series A", [ 1, 2, 1, 2, 1, 2, 1 ]).
+						addSeries("Series B", [ 2, 1, 2, 1, 2, 1, 2 ]).
+						render();
+				}
+			},
+			{
+				description: "Defaults: lines, no axes.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addSeries("Series A", [ 1, 2, 1, 2, 1, 2, 1 ]).
+						addSeries("Series B", [ 2, 1, 2, 1, 2, 1, 2 ]).
+						render();
+				}
+			},
+			{
+				description: "Defaults: lines, no axes, and custom strokes.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addSeries("Series A", [ 1, 2, 1, 2, 1, 2, 1 ], {stroke: "red"}).
+						addSeries("Series B", [ 2, 1, 2, 1, 2, 1, 2 ], {stroke: "blue"}).
+						render();
+				}
+			},
+			{
+				description: "Areas, Happy theme, no axes.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addPlot("default", {type: "Areas", tension:"X"}).
+						setTheme(dojox.charting.themes.Shrooms).
+						addSeries("Series A", [1, 2, 0.5, 1.5, 1, 2.8, 0.4]).
+						addSeries("Series B", [2.6, 1.8, 2, 1, 1.4, 0.7, 2]).
+						addSeries("Series C", [6.3, 1.8, 3, 0.5, 4.4, 2.7, 2]).
+						render();
+				}
+			},
+			{
+				description: "Areas, no axes, custom strokes and fills.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addPlot("default", {type: "Areas"}).
+						addSeries("Series A",
+							[1, 2, 1, 2, 1, 2, 1],
+							{
+								stroke: {color: "red", width: 2 },
+								fill: "lightpink"
+							}
+						).
+						addSeries("Series B",
+							[ 2, 1, 2, 1, 2, 1, 2 ],
+							{
+								stroke: { color: "blue", width: 2 },
+								fill: "lightblue"
+							}
+						).
+						render();
+				}
+			},
+			{
+				description: "Lines, axes, blue theme.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						setTheme(dojox.charting.themes.PlotKit.blue).
+						addAxis("x").
+						addAxis("y", {vertical: true}).
+						addSeries("Series A", [1, 2, 1, 2, 1, 2, 1]).
+						addSeries("Series B", [2, 1, 2, 1, 2, 1, 2]).
+						render();
+				}
+			},
+			{
+				description: "Lines, axes (aligned on minor ticks), cyan theme.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						setTheme(dojox.charting.themes.PlotKit.cyan).
+						addAxis("x", {
+							fixLower: "minor", fixUpper: "minor"
+						}).
+						addAxis("y", {
+							vertical: true, fixLower: "minor", fixUpper: "minor"
+						}).
+						addSeries("Series A", [1, 2, 1, 2, 1, 2, 1]).
+						addSeries("Series B", [2, 1, 2, 1, 2, 1, 2]).
+						render();
+				}
+			},
+			{
+				description: "Lines, axes (aligned on major ticks), green theme.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						setTheme(dojox.charting.themes.PlotKit.green).
+						addAxis("x", {
+							fixLower: "major", fixUpper: "major"
+						}).
+						addAxis("y", {
+							vertical: true, fixLower: "major", fixUpper: "major"
+						}).
+						addSeries("Series A", [1, 2, 1, 2, 1, 2, 1]).
+						addSeries("Series B", [2, 1, 2, 1, 2, 1, 2]).
+						render();
+				}
+			},
+			{
+				description: "Lines and markers, no axes, purple theme, custom min/max.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						setTheme(dojox.charting.themes.SageToLime).
+						addPlot("default", {type: "Markers"}).
+						addSeries("Series A", [1, 2, 1, 2, 1, 2, 1], {min: 0, max: 3}).
+						addSeries("Series B", [2, 1, 2, 1, 2, 1, 2]).
+						render();
+				}
+			},
+			{
+				description: "Markers only, no axes, custom theme, custom markers, custom min/max.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addPlot("default", { type: "MarkersOnly" }).
+						addSeries("Series A",
+							[ 1, 2, 1, 2, 1, 2, 1 ],
+							{
+								min: 0,
+								max: 3,
+								stroke: {color: "red", width: 2},
+								fill:   "red",
+								marker: "m-3,0 c0,-4 6,-4 6,0 m-6,0 c0,4 6,4 6,0"
+							}
+						).
+						addSeries("Series B",
+							[ 2, 1, 2, 1, 2, 1, 2 ],
+							{
+								stroke: {color: "blue", width: 2},
+								fill:   "blue",
+								marker: "m-3,-3 l0,6 6,0 0,-6 z"
+							}
+						).
+						render();
+				}
+			},
+			{
+				description: "Lines and markers, shadows, no axes, custom theme, custom markers, custom min/max.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addPlot("default", {
+							type: "Markers", shadow:  {dx: 1, dy: 1, width: 2, color: [0, 0, 0, 0.3]}
+						}).
+						addSeries("Series A",
+							[ 1, 2, 1, 2, 1, 2, 1 ],
+							{
+								min: 0,
+								max: 3,
+								stroke: {color: "red", width: 2, join: "round"},
+								fill:   "red",
+								marker: "m-3,0 c0,-4 6,-4 6,0 m-6,0 c0,4 6,4 6,0"
+							}
+						).
+						addSeries("Series B",
+							[ 2, 1, 2, 1, 2, 1, 2 ],
+							{
+								stroke: {color: "blue", width: 2, join: "round"},
+								fill:   "blue",
+								marker: "m-3,-3 l0,6 6,0 0,-6 z"
+							}
+						).
+						render();
+				}
+			},
+			{
+				description: "Stacked lines, markers, shadows, no axes, custom strokes, fills, and markers.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addPlot("default", {
+							type: "StackedLines",
+							markers: true,
+							tension:"S",
+							shadow:  {dx: 1, dy: 1, width: 2, color: [0, 0, 0, 0.3]}
+						}).
+						addSeries("Series A",
+							[ 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6 ],
+							{
+								stroke: { color: "red", width: 2 },
+								fill: "lightpink",
+								marker: "m-3,-3 l0,6 6,0 0,-6 z"
+							}
+						).
+						addSeries("Series B",
+							[ 1, 1.6, 1.3, 1.4, 1.1, 1.5, 1.1 ],
+							{
+								stroke: { color: "blue", width: 2 },
+								fill: "lightblue",
+								marker: "m-3,0 c0,-4 6,-4 6,0 m-6,0 c0,4 6,4 6,0"
+							}
+						).
+						addSeries("Series C",
+							[ 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6 ],
+							{
+								stroke: { color: "green", width: 2 },
+								fill: "lightgreen",
+								marker: "m0,-3 l3,3 -3,3 -3,-3 z"
+							}
+						).
+						render();
+				}
+			},
+			{
+				description: "Stacked areas, axes (aligned on major ticks), custom strokes and fills.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x", {fixLower: "major", fixUpper: "major"}).
+						addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", min: 0}).
+						addPlot("default", { type: "StackedAreas", tension:"S" }).
+						addSeries("Series A",
+							[ -2, 1.1, 1.2, 1.3, 1.4, 1.5, -1.6 ],
+							{ stroke: {color: "red", width: 2}, fill: "lightpink" }
+						).
+						addSeries("Series B",
+							[ 1, 1.6, 1.3, 1.4, 1.1, 1.5, 1.1 ],
+							{ stroke: {color: "blue", width: 2}, fill: "lightblue" }
+						).
+						addSeries("Series C",
+							[ 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6 ],
+							{ stroke: {color: "green", width: 2}, fill: "lightgreen" }
+						).
+						render();
+				}
+			},
+			{
+				description: "Candlesticks with gaps, custom strokes and fills, optional mid points.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addPlot("default", {type: "Candlesticks", gap: 1}).
+						addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true}).
+						addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+						addSeries("Series A", [
+								{ open: 20, close: 16, high: 22, low: 8 },
+								{ open: 16, close: 22, high: 26, low: 6, mid: 18 },
+								{ open: 22, close: 18, high: 22, low: 11, mid: 21 },
+								{ open: 18, close: 29, high: 32, low: 14, mid: 27 },
+								{ open: 29, close: 24, high: 29, low: 13, mid: 27 },
+								{ open: 24, close: 8, high: 24, low: 5 },
+								{ open: 8, close: 16, high: 22, low: 2 },
+								{ open: 16, close: 12, high: 19, low: 7 },
+								{ open: 12, close: 20, high: 22, low: 8 },
+								{ open: 20, close: 16, high: 22, low: 8 },
+								{ open: 16, close: 22, high: 26, low: 6, mid: 18 },
+								{ open: 22, close: 18, high: 22, low: 11, mid: 21 },
+								{ open: 18, close: 29, high: 32, low: 14, mid: 27 },
+								{ open: 29, close: 24, high: 29, low: 13, mid: 27 },
+								{ open: 24, close: 8, high: 24, low: 5 },
+								{ open: 8, close: 16, high: 22, low: 2 },
+								{ open: 16, close: 12, high: 19, low: 7 },
+								{ open: 12, close: 20, high: 22, low: 8 },
+								{ open: 20, close: 16, high: 22, low: 8 },
+								{ open: 16, close: 22, high: 26, low: 6 },
+								{ open: 22, close: 18, high: 22, low: 11 },
+								{ open: 18, close: 29, high: 32, low: 14 },
+								{ open: 29, close: 24, high: 29, low: 13 },
+								{ open: 24, close: 8, high: 24, low: 5 },
+								{ open: 8, close: 16, high: 22, low: 2 },
+								{ open: 16, close: 12, high: 19, low: 7 },
+								{ open: 12, close: 20, high: 22, low: 8 },
+								{ open: 20, close: 16, high: 22, low: 8 }
+							],
+							{ stroke: { color: "green" }, fill: "lightgreen" }
+						).
+						render();
+				}
+			},
+			{
+				description: "Open/High/Low/Close with gaps, custom strokes and fills.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addPlot("default", {type: "OHLC", gap: 2}).
+						addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true}).
+						addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+						addSeries("Series A", [
+								{ open: 20, close: 16, high: 22, low: 8 },
+								{ open: 16, close: 22, high: 26, low: 6 },
+								{ open: 22, close: 18, high: 22, low: 11 },
+								{ open: 18, close: 29, high: 32, low: 14 },
+								{ open: 29, close: 24, high: 29, low: 13 },
+								{ open: 24, close: 8, high: 24, low: 5 },
+								{ open: 8, close: 16, high: 22, low: 2 },
+								{ open: 16, close: 12, high: 19, low: 7 },
+								{ open: 12, close: 20, high: 22, low: 8 },
+								{ open: 20, close: 16, high: 22, low: 8 },
+								{ open: 16, close: 22, high: 26, low: 6 },
+								{ open: 22, close: 18, high: 22, low: 11 },
+								{ open: 18, close: 29, high: 32, low: 14 },
+								{ open: 29, close: 24, high: 29, low: 13 },
+								{ open: 24, close: 8, high: 24, low: 5 },
+								{ open: 8, close: 16, high: 22, low: 2 },
+								{ open: 16, close: 12, high: 19, low: 7 },
+								{ open: 12, close: 20, high: 22, low: 8 },
+								{ open: 20, close: 16, high: 22, low: 8 },
+								{ open: 16, close: 22, high: 26, low: 6 },
+								{ open: 22, close: 18, high: 22, low: 11 },
+								{ open: 18, close: 29, high: 32, low: 14 },
+								{ open: 29, close: 24, high: 29, low: 13 },
+								{ open: 24, close: 8, high: 24, low: 5 },
+								{ open: 8, close: 16, high: 22, low: 2 },
+								{ open: 16, close: 12, high: 19, low: 7 },
+								{ open: 12, close: 20, high: 22, low: 8 },
+								{ open: 20, close: 16, high: 22, low: 8 }
+							],
+							{ stroke: { color: "blue" }, fill: "blue" }
+						).
+						render();
+				}
+			},
+			{
+				description: "Columns, no axes, custom strokes and fills.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addPlot("default", {type: "Columns"}).
+						addSeries("Series A", [ 1, 2, 3, 4, 5 ], { stroke: { color: "red" }, fill: "lightpink" }).
+						addSeries("Series B", [ 5, 4, 3, 2, 1 ], { stroke: {color: "blue"}, fill: "lightblue" }).
+						render();
+				}
+			},
+			{
+				description: "Columns with gaps beetwen them, vertical axis aligned on major ticks, custom strokes, fills.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major"}).
+						addPlot("default", {type: "Columns", gap: 2}).
+						addSeries("Series A", [ 1, 2, 3, 4, 5 ], { stroke: {color: "red"}, fill: "lightpink" }).
+						addSeries("Series B", [ 5, 4, 3, 2, 1 ], { stroke: {color: "blue"}, fill: "lightblue" }).
+						render();
+				}
+			},
+			{
+				description: "Stacked columns, no axes, custom strokes and fills.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addPlot("default", {type: "StackedColumns"}).
+						addSeries("Series A", [ 1, 2, 3, 4, 5 ], {stroke: { color: "red" }, fill: "lightpink" }).
+						addSeries("Series B", [ 2, 1, 2, 1, 2 ], {stroke: { color: "blue" }, fill: "lightblue" }).
+						render();
+				}
+			},
+			{
+				description: "Bars, axes aligned on major ticks, no minor ticks, custom strokes and fills.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true}).
+						addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+						addPlot("default", {type: "Bars"}).
+						addSeries("Series A",
+							[1, 2, 3, 4, 5],
+							{ stroke: {color: "red"}, fill: "lightpink" }
+						).
+						addSeries("Series B",
+							[5, 4, 3, 2, 1],
+							{ stroke: {color: "blue"}, fill: "lightblue" }
+						).
+						render();
+				}
+			},
+			{
+				description: "Stacked bars, no axes, custom strokes and fills.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addPlot("default", {type: "StackedBars"}).
+						addSeries("Series A", [ 1, 2, 3, 4, 5 ], { stroke: { color: "red" }, fill: "lightpink" }).
+						addSeries("Series B", [ 2, 1, 2, 1, 2 ], { stroke: { color: "blue" }, fill: "lightblue" }).
+						render();
+				}
+			},
+			{
+				description: "Clustered columns, custom axes, custom strokes, fills, and gap.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x", {
+							fixLower: "minor", fixUpper: "minor", natural: true
+						}).
+						addAxis("y", {
+							vertical: true, fixLower: "major", fixUpper: "major", includeZero: true
+						}).
+						addPlot("default", {type: "ClusteredColumns", gap: 10}).
+						addSeries("Series A",
+							[ 1, 2, 3, 4, 5 ],
+							{ stroke: {color: "red"}, fill: "lightpink" }
+						).
+						addSeries("Series B", [5, 4, 3, 2, 1], {stroke: {color: "blue"}, fill: "lightblue"}).
+						render();
+				}
+			},
+			{
+				description: "Clustered bars, custom axes, custom strokes, fills, and gap.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true}).
+						addAxis("y", {vertical: true, fixLower: "minor", fixUpper: "minor", natural: true}).
+						addPlot("default", { type: "ClusteredBars", gap: 5 }).
+						addSeries("Series A", [ 1, 2, 3, 4, 5 ], { stroke: { color: "red" }, fill: "lightpink" }).
+						addSeries("Series B", [ 2, 1, 2, 1, 2 ], { stroke: { color: "blue" }, fill: "lightblue" }).
+						render();
+				}
+			},
+			{
+				description: "Columns with gaps beetwen them, grids, custom strokes, fills, axes.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x", { fixLower: "minor", fixUpper: "minor", natural: true }).
+						addAxis("y", {
+							vertical: true,
+							fixLower: "major",
+							fixUpper: "major",
+							minorTicks: false,
+							includeZero: true
+						}).
+						addPlot("front_grid", { type: "Grid", hMajorLines: true, vMajorLines: false }).
+						addPlot("default", { type: "Columns", gap: 10 }).
+						addPlot("back_grid", { type: "Grid", hMajorLines: false, vMajorLines: true }).
+						addSeries("Series A",
+							[ 1, 2, 3, 4, 5 ],
+							{ stroke: { color: "red" }, fill: "lightpink" }
+						).
+						addSeries("Series B",
+							[ 5, 4, 3, 2, 1 ],
+							{ stroke: { color: "blue" }, fill: "lightblue" }
+						).
+						render();
+				}
+			},
+			{
+				description: "Columns with gaps beetwen them, grids, custom strokes, fills, axes, with min=0, max=8, and manually specified ticks on the vertical axis.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x", {fixLower: "minor", fixUpper: "minor", natural: true}).
+						addAxis("y", {
+							vertical: true, fixLower: "major", fixUpper: "major",
+							includeZero: true, min: 0, max: 8, minorLabels: false,
+							majorTicks: true, minorTicks: true, microTicks: false,
+							majorTickStep: 2, minorTickStep: 1, microTickStep: 0.5
+						}).
+						addPlot("front_grid", {
+							type: "Grid", hMajorLines: true, vMajorLines: false
+						}).
+						addPlot("default", {type: "Columns", gap: 10}).
+						addPlot("back_grid", {
+							type: "Grid", hMajorLines: false, vMajorLines: true
+						}).
+						addSeries("Series A",
+							[ 1, 2, 3, 4, 5 ],
+							{ stroke: {color: "red"}, fill: "lightpink" }
+						).
+						addSeries("Series B",
+							[ 5, 4, 3, 2, 1 ],
+							{ stroke: {color: "blue"}, fill: "lightblue" }
+						).
+						render();
+				}
+			},
+			{
+				description: "Columns with positive and negative values, axes, and grid.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x").
+						addAxis("y", { vertical: true }).
+						addPlot("default", { type: "Columns", gap: 10 }).
+						addPlot("grid", { type: "Grid" }).
+						addSeries("Series A",
+							[ 2, 1, 0.5, -1, -2 ],
+							{ stroke: {color: "red"}, fill: "lightpink" }
+						).
+						addSeries("Series B",
+							[ -2, -1, -0.5, 1, 2 ],
+							{ stroke: {color: "blue"}, fill: "lightblue" }
+						).
+						render();
+				}
+			},
+			{
+				description: "Clustered columns with positive and negative values, axes, and grid.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x").
+						addAxis("y", { vertical: true }).
+						addPlot("default", { type: "ClusteredColumns", gap: 10 }).
+						addPlot("grid", { type: "Grid" }).
+						addSeries("Series A",
+							[ 2, 1, 0.5, -1, -2 ],
+							{ stroke: {color: "red"}, fill: "lightpink" }
+						).
+						addSeries("Series B",
+							[ -2, -1, -0.5, 1, 2 ],
+							{ stroke: {color: "blue"}, fill: "lightblue" }
+						).
+						addSeries("Series C",
+							[ 1, 0.5, -1, -2, -3 ],
+							{ stroke: {color: "green"}, fill: "lightgreen" }
+						).
+						render();
+				}
+			},
+			{
+				description: "Bars with positive and negative values, axes, and grid.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x").
+						addAxis("y", { vertical: true }).
+						addPlot("default", { type: "Bars", gap: 10 }).
+						addPlot("grid", { type: "Grid" }).
+						addSeries("Series A",
+							[ 2, 1, 0.5, -1, -2 ],
+							{ stroke: {color: "red"}, fill: "lightpink" }
+						).
+						addSeries("Series B",
+							[ -2, -1, -0.5, 1, 2 ],
+							{ stroke: {color: "blue"}, fill: "lightblue" }
+						).
+						render();
+				}
+			},
+			{
+				description: "Clustered bars with positive and negative values, axes, and grid.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						addAxis("x").
+						addAxis("y", { vertical: true }).
+						addPlot("default", { type: "ClusteredBars", gap: 10 }).
+						addPlot("grid", { type: "Grid" }).
+						addSeries("Series A",
+							[ 2, 1, 0.5, -1, -2 ],
+							{ stroke: { color: "red" }, fill: "lightpink" }
+						).
+						addSeries("Series B",
+							[ -2, -1, -0.5, 1, 2 ],
+							{ stroke: { color: "blue" }, fill: "lightblue" }
+						).
+						addSeries("Series C",
+							[ 1, 0.5, -1, -2, -3 ],
+							{ stroke: { color: "green" }, fill: "lightgreen" }
+						).
+						render();
+				}
+			},
+			{
+				description: "Default lines with 2D data, custom axis, red theme.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						setTheme(dojox.charting.themes.Minty).
+						addAxis("x", {
+							min: 0,
+							max: 6,
+							majorTick: { stroke: "black", length: 3 },
+							minorTick: { stroke: "gray", length: 3 }
+						}).
+						addAxis("y", {
+							vertical: true,
+							min: 0,
+							max: 10,
+							majorTick: { stroke: "black", length: 3 },
+							minorTick: { stroke: "gray", length: 3 }
+						}).
+						addSeries("Series A", [
+							{ x: 0.5, y: 5 },
+							{ x: 1.5, y: 1.5 },
+							{ x: 2, y: 9 },
+							{ x: 5, y: 0.3 }
+						]).
+						addSeries("Series B", [
+							{ x: 0.3, y: 8 },
+							{ x: 4, y: 6 },
+							{ x: 5.5, y: 2 }
+						]).
+						render();
+				}
+			},
+			{
+				description: "Scatter chart, custom axis, purple theme.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						setTheme(dojox.charting.themes.Ireland).
+						addPlot("default", {type: "Scatter"}).
+						addAxis("x", {
+							min: 0,
+							max: 6,
+							majorTick: { stroke: "black", length: 3 },
+							minorTick: { stroke: "gray", length: 3 }
+						}).
+						addAxis("y", {
+							vertical: true,
+							min: 0,
+							max: 10,
+							majorTick: { stroke: "black", length: 3 },
+							minorTick: { stroke: "gray", length: 3 }
+						}).
+						addSeries("Series A", [
+							{ x: 0.5, y: 5 },
+							{ x: 1.5, y: 1.5 },
+							{ x: 2, y: 9 },
+							{ x: 5, y: 0.3 }
+						]).
+						addSeries("Series B", [
+							{ x: 0.3, y: 8 },
+							{ x: 4, y: 6 },
+							{ x: 5.5, y: 2 }
+						]).
+						render();
+				}
+			},
+			{
+				description: "Markers, lines, 2D data, custom axis, blue theme.",
+				makeChart: function(node){
+					(new dojox.charting.Chart2D(node)).
+						setTheme(dojox.charting.themes.PlotKit.blue).
+						addPlot("default", {
+							type: "Default",
+							lines: true,
+							markers: true,
+							tension: 2
+						}).
+						addAxis("x", {
+							min: 0,
+							max: 6,
+							majorTick: { stroke: "black", length: 3 },
+							minorTick: { stroke: "gray", length: 3 }
+						}).
+						addAxis("y", {
+							vertical: true,
+							min: 0,
+							max: 10,
+							majorTick: { stroke: "black", length: 3 },
+							minorTick: { stroke: "gray", length: 3 }
+						}).
+						addSeries("Series A", [
+							{ x: 0.5, y: 5 },
+							{ x: 1.5, y: 1.5 },
+							{ x: 2, y: 9 },
+							{ x: 5, y: 0.3 }
+						]).
+						addSeries("Series B", [
+							{ x: 0.3, y: 8 },
+							{ x: 4, y: 6 },
+							{ x: 5.5, y: 2 }
+						]).
+						render();
+				}
+			}
+		];
+		var now = function(){
+			return (new Date()).getTime();
+		};
+
+
+		dojo.addOnLoad(function(){
+			var defaultStyle = { width: "400px", height: "200px" };
+			var tmpl = new dojox.dtl.Template(dojo.byId("template").value);
+			var context = new dojox.dtl.Context({ charts: charts });
+			dojo.byId("charts").innerHTML = tmpl.render(context);
+
+			dojo.forEach(charts, function(item, idx){
+				var start = now();
+				var n = dojo.byId("chart_"+idx);
+				dojo.style(n, item.style||defaultStyle);
+				item.makeChart(n);
+				console.debug((now()-start), "ms to create:", (idx+1)+":", item.description);
+			});
+		});
+
+	</script>
+</head>
+<body>
+	<textarea id="template" style="display: none;">
+		{% for item in charts %}
+			<p>{{ forloop.counter }}: {{ item.description }}</p>
+			<div id="chart_{{ forloop.counter0 }}"></div>
+		{% endfor %}
+	</textarea>
+
+	<h1>Chart 2D</h1>
+
+	<div id="charts"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_chart2d_dynamics.html b/dojox/charting/tests/test_chart2d_dynamics.html
new file mode 100644
index 0000000..98d5388
--- /dev/null
+++ b/dojox/charting/tests/test_chart2d_dynamics.html
@@ -0,0 +1,236 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Chart 2D: dynamics</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+
+	.dojoxLegendNode {border: 1px solid #ccc; margin: 5px 10px 5px 10px; padding: 3px}
+	.dojoxLegendText {vertical-align: text-top; padding-right: 10px}
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+<script type="text/javascript" src="../Chart2D.js"></script>
+<script type="text/javascript">
+dojo.require("dijit.form.Button");
+dojo.require("dijit.form.CheckBox");
+dojo.require("dijit.form.ComboBox");
+
+dojo.require("dojox.charting.Chart2D");
+dojo.require("dojox.charting.themes.CubanShirts");
+dojo.require("dojox.charting.widget.Legend");
+
+dojo.require("dojox.lang.functional.sequence");
+
+var chart, legend, size = 10, magnitude = 30;
+
+var getData = function(){
+	var data = new Array(size);
+	for(var i = 0; i < size; ++i){
+		data[i] = Math.random() * magnitude;
+	}
+	return data;
+};
+
+var getZeroes = function(){
+	return dojox.lang.functional.repeat(size, "-> 0", 0);
+};
+
+var makeObjects = function(){
+	chart = new dojox.charting.Chart2D("test");
+	chart.setTheme(dojox.charting.themes.CubanShirts);
+
+	if(dijit.byId("hAxis").attr("checked")){
+		chart.addAxis("x", {natural: true, includeZero: true, fixUpper: "minor"});
+	}
+
+	if(dijit.byId("vAxis").attr("checked")){
+		chart.addAxis("y", {vertical: true, natural: true, includeZero: true, fixUpper: "minor"});
+	}
+
+	chart.addPlot("default", {type: dijit.byId("plot").attr("value"), gap: 2});
+
+	if(dijit.byId("grid").attr("checked")){
+		chart.addPlot("grid", {type: "Grid", hMinorLines: true, vMinorLines: true});
+	}
+
+	for(var i = 1; i <= 5; ++i){
+		if(dijit.byId("s" + i).attr("checked")){
+			chart.addSeries("Series " + i, getData(), {stroke: {color: "black", width: 1}});
+		}
+	}
+	if(dijit.byId("s6").attr("checked")){
+		chart.addSeries("Series 6", getZeroes(), {stroke: {color: "black", width: 1}});
+	}
+
+	chart.render();
+	
+	legend = new dojox.charting.widget.Legend({chart: chart}, "legend");
+};
+
+dojo.addOnLoad(makeObjects);
+
+changePlot = function(){
+	var type = dijit.byId("plot").attr("value");
+	chart.addPlot("default", {type: type, gap: 2});
+	chart.render();
+	legend.refresh();
+};
+
+changeGrid = function(){
+	if(dijit.byId("grid").attr("checked")){
+		chart.addPlot("grid", {type: "Grid", hMinorLines: true, vMinorLines: true});
+	}else{
+		chart.removePlot("grid");
+	}
+	chart.render();
+};
+
+changeX = function(){
+	if(dijit.byId("hAxis").attr("checked")){
+		chart.addAxis("x", {natural: true, includeZero: true, fixUpper: "minor"});
+	}else{
+		chart.removeAxis("x");
+	}
+	chart.render();
+};
+
+changeY = function(){
+	if(dijit.byId("vAxis").attr("checked")){
+		chart.addAxis("y", {vertical: true, natural: true, includeZero: true, fixUpper: "minor"});
+	}else{
+		chart.removeAxis("y");
+	}
+	chart.render();
+};
+
+changeSeries = function(n){
+	if(n == 6){
+		// special case
+		if(dijit.byId("s6").attr("checked")){
+			chart.addSeries("Series 6", getZeroes(), {stroke: {color: "black", width: 1}});
+		}else{
+			chart.removeSeries("Series 6");
+		}
+	}else{
+		if(dijit.byId("s" + n).attr("checked")){
+			chart.addSeries("Series " + n, getData(), {stroke: {color: "black", width: 1}});
+			dijit.byId("sb" + n).attr("disabled", false);
+		}else{
+			chart.removeSeries("Series " + n);
+			dijit.byId("sb" + n).attr("disabled", true);
+		}
+	}
+	chart.render();
+	legend.refresh();
+};
+
+addSeries = function(n){
+	chart.addSeries("Series " + n, getData(), {stroke: {color: "black", width: 1}});
+	chart.render();
+	legend.refresh();
+};
+
+</script>
+</head>
+<body class="tundra">
+<h1>Chart 2D: dynamics</h1>
+<table>
+	<tr>
+		<td>Plot:</td>
+		<td>
+			<select dojoType="dijit.form.ComboBox" id="plot" onChange="changePlot()">
+				<option value="Columns">Columns</option>
+				<option value="ClusteredColumns">ClusteredColumns</option>
+				<option value="StackedColumns">StackedColumns</option>
+				<option value="Bars">Bars</option>
+				<option value="ClusteredBars">ClusteredBars</option>
+				<option value="StackedBars">StackedBars</option>
+				<option value="Areas">Areas</option>
+				<option value="StackedAreas">StackedAreas</option>
+				<option value="Pie">Pie</option>
+			</select>
+		</td>
+	</tr>
+	<tr>
+		<td>Grid:</td>
+		<td>
+			<input type="checkbox" dojoType="dijit.form.CheckBox" checked="true" id="grid" onChange="changeGrid()">
+			<label for="grid">include</label>
+		</td>
+	</tr>
+	<tr>
+		<td>X axis:</td>
+		<td>
+			<input type="checkbox" dojoType="dijit.form.CheckBox" checked="true" id="hAxis" onChange="changeX()">
+			<label for="hAxis">include</label>
+		</td>
+	</tr>
+	<tr>
+		<td>Y axis:</td>
+		<td>
+			<input type="checkbox" dojoType="dijit.form.CheckBox" checked="true" id="vAxis" onChange="changeY()">
+			<label for="vAxis">include</label>
+		</td>
+	</tr>
+	<tr>
+		<td>Series 1:</td>
+		<td>
+			<input type="checkbox" dojoType="dijit.form.CheckBox" checked="true" id="s1" onChange="changeSeries(1)">
+			<label for="s1">include</label>
+			 
+			<button dojoType="dijit.form.Button" id="sb1" onClick="addSeries(1)">Randomize</button>
+		</td>
+	</tr>
+	<tr>
+		<td>Series 2:</td>
+		<td>
+			<input type="checkbox" dojoType="dijit.form.CheckBox" checked="true" id="s2" onChange="changeSeries(2)">
+			<label for="s2">include</label>
+			 
+			<button dojoType="dijit.form.Button" id="sb2" onClick="addSeries(2)">Randomize</button>
+		</td>
+	</tr>
+	<tr>
+		<td>Series 3:</td>
+		<td>
+			<input type="checkbox" dojoType="dijit.form.CheckBox" checked="true" id="s3" onChange="changeSeries(3)">
+			<label for="s3">include</label>
+			 
+			<button dojoType="dijit.form.Button" id="sb3" onClick="addSeries(3)">Randomize</button>
+		</td>
+	</tr>
+	<tr>
+		<td>Series 4:</td>
+		<td>
+			<input type="checkbox" dojoType="dijit.form.CheckBox" checked="true" id="s4" onChange="changeSeries(4)">
+			<label for="s4">include</label>
+			 
+			<button dojoType="dijit.form.Button" id="sb4" onClick="addSeries(4)">Randomize</button>
+		</td>
+	</tr>
+	<tr>
+		<td>Series 5:</td>
+		<td>
+			<input type="checkbox" dojoType="dijit.form.CheckBox" checked="true" id="s5" onChange="changeSeries(5)">
+			<label for="s5">include</label>
+			 
+			<button dojoType="dijit.form.Button" id="sb5" onClick="addSeries(5)">Randomize</button>
+		</td>
+	</tr>
+	<tr>
+		<td>Series 6:</td>
+		<td>
+			<input type="checkbox" dojoType="dijit.form.CheckBox" checked="false" id="s6" onChange="changeSeries(6)">
+			<label for="s6">include</label>
+			 this series contains all 0 values
+		</td>
+	</tr>
+</table>
+<div id="test" style="width: 600px; height: 400px;"></div>
+<div id="legend"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_chart2d_updating.html b/dojox/charting/tests/test_chart2d_updating.html
new file mode 100644
index 0000000..ddb5ef0
--- /dev/null
+++ b/dojox/charting/tests/test_chart2d_updating.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+	<title>Chart 2D</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug: true"></script>
+	<!--
+	<script type="text/javascript" src="../../lang/functional.js"></script>
+	<script type="text/javascript" src="../Theme.js"></script>
+	<script type="text/javascript" src="../scaler/linear.js"></script>
+	<script type="text/javascript" src="../axis2d/Default.js"></script>
+	<script type="text/javascript" src="../Chart2D.js"></script>
+	-->
+	<script type="text/javascript">
+
+		dojo.require("dojox.charting.Chart2D");
+		dojo.require("dojox.charting.themes.PlotKit.orange");
+		dojo.require("dojox.charting.themes.Tufte");
+
+		var chart, limit = 10, magnitude = 30, counter = [0, 0, 0];
+
+		var randomValue = function(nCounter){
+			return {x: ++counter[nCounter], y: Math.random() * magnitude};
+		};
+
+		var makeSeries = function(len, nCounter){
+			var s = [];
+			do{
+				s.push(randomValue(nCounter));
+			}while(s.length < len);
+			return s;
+		};
+
+		var seriesA = makeSeries(limit, 0),
+			seriesB = makeSeries(limit, 1),
+			seriesC = makeSeries(limit, 2);
+
+		var makeObjects = function(){
+			chart = new dojox.charting.Chart2D("test");
+			chart.setTheme(dojox.charting.themes.Tufte);
+			chart.addAxis("x", {
+				fixLower: "minor", 
+				natural: true
+			});
+			chart.addAxis("y", {
+				vertical: true, 
+				min: 0, 
+				max: 30, 
+				majorTickStep: 5, 
+				minorTickStep: 1
+			});
+			chart.addPlot("default", {type: "Areas"});
+			chart.addSeries("Series A", seriesA);
+			chart.addSeries("Series B", seriesB);
+			chart.addSeries("Series C", seriesC);
+			chart.addPlot("grid", {
+				type: "Grid", hMinorLines: true
+			});
+			chart.render();
+
+			setInterval(function(){updateTest();}, 500);
+		};
+
+		var updateTest = function(){
+			seriesA.shift();
+			seriesA.push(randomValue(0));
+			chart.updateSeries("Series A", seriesA);
+
+			seriesB.shift();
+			seriesB.push(randomValue(1));
+			chart.updateSeries("Series B", seriesB);
+
+			seriesC.shift();
+			seriesC.push(randomValue(2));
+			chart.updateSeries("Series C", seriesC);
+
+			chart.render();
+		};
+
+		dojo.addOnLoad(makeObjects);
+
+	</script>
+</head>
+<body>
+	<h1>Chart 2D Updating Data</h1>
+	<p>
+		Areas, grey theme, axes, grid. Very crude example to show a chart
+		with updating values.
+	</p>
+	<div id="test" style="width: 400px; height: 400px;"></div>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_cylinders.html b/dojox/charting/tests/test_cylinders.html
new file mode 100644
index 0000000..b7b6c42
--- /dev/null
+++ b/dojox/charting/tests/test_cylinders.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Cylinder chart</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<!--
+The next line should include Microsoft's Silverligth.js, if you plan to use the silverlight backend
+<script type="text/javascript" src="Silverlight.js"></script>
+-->
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../Chart3D.js"></script>
+<script type="text/javascript" src="../plot3d/Base.js"></script>
+<script type="text/javascript" src="../plot3d/Cylinders.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.charting.Chart3D");
+dojo.require("dojox.charting.plot3d.Cylinders");
+
+makeObjects = function(){
+	var m = dojox.gfx3d.matrix;
+	var chart = new dojox.charting.Chart3D("test", 
+		{
+			lights:   [{direction: {x: 5, y: 5, z: -5}, color: "white"}],
+			ambient:  {color:"white", intensity: 2},
+			specular: "white"
+		},
+		[m.cameraRotateXg(10), m.cameraRotateYg(-10), m.scale(0.8), m.cameraTranslate(-50, -50, 0)]
+	);
+	
+	var plot1 = new dojox.charting.plot3d.Cylinders(500, 500, {gap: 10, material: "yellow"});
+	plot1.setData([1,2,3,2,1,2,3,4,5]);
+	chart.addPlot(plot1);
+	
+	var plot2 = new dojox.charting.plot3d.Cylinders(500, 500, {gap: 10, material: "red"});
+	plot2.setData([2,3,4,3,2,3,4,5,5]);
+	chart.addPlot(plot2);
+	
+	var plot3 = new dojox.charting.plot3d.Cylinders(500, 500, {gap: 10, material: "blue"});
+	plot3.setData([3,4,5,4,3,4,5,5,5]);
+	chart.addPlot(plot3);
+	
+	chart.generate().render();
+	
+	//dojo.byId("out1").value = dojo.byId("test").innerHTML;
+	//dojo.byId("out2").value = dojox.gfx.utils.toJson(surface, true);
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Cylinder chart</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<!--
+<p><button onclick="makeObjects();">Go</button></p>
+<p><textarea id="out1" cols="40" rows="5"></textarea></p>
+<p><textarea id="out2" cols="40" rows="5"></textarea></p>
+-->
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_event2d.html b/dojox/charting/tests/test_event2d.html
new file mode 100644
index 0000000..f41233b
--- /dev/null
+++ b/dojox/charting/tests/test_event2d.html
@@ -0,0 +1,270 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Event 2D</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- required for Tooltip: a default dijit theme: -->
+<link rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+<style>
+.dojoxLegendNode {border: 1px solid #ccc; margin: 5px 10px 5px 10px; padding: 3px}
+.dojoxLegendText {vertical-align: text-top; padding-right: 10px}
+</style>
+<!--
+The next line should include Microsoft's Silverligth.js, if you plan to use the silverlight backend
+<script type="text/javascript" src="Silverlight.js"></script>
+-->
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../../../dojo/_base/connect.js"></script>
+<script type="text/javascript" src="../../../dojo/fx.js"></script>
+<script type="text/javascript" src="../../lang/functional.js"></script>
+<script type="text/javascript" src="../../lang/utils.js"></script>
+<script type="text/javascript" src="../../gfx/fx.js"></script>
+<script type="text/javascript" src="../Theme.js"></script>
+<script type="text/javascript" src="../scaler/primitive.js"></script>
+<script type="text/javascript" src="../scaler/linear.js"></script>
+<script type="text/javascript" src="../Element.js"></script>
+<script type="text/javascript" src="../axis2d/common.js"></script>
+<script type="text/javascript" src="../axis2d/Base.js"></script>
+<script type="text/javascript" src="../axis2d/Default.js"></script>
+<script type="text/javascript" src="../plot2d/common.js"></script>
+<script type="text/javascript" src="../plot2d/Base.js"></script>
+<script type="text/javascript" src="../plot2d/Default.js"></script>
+<script type="text/javascript" src="../plot2d/Lines.js"></script>
+<script type="text/javascript" src="../plot2d/Areas.js"></script>
+<script type="text/javascript" src="../plot2d/Markers.js"></script>
+<script type="text/javascript" src="../plot2d/MarkersOnly.js"></script>
+<script type="text/javascript" src="../plot2d/Scatter.js"></script>
+<script type="text/javascript" src="../plot2d/Stacked.js"></script>
+<script type="text/javascript" src="../plot2d/StackedLines.js"></script>
+<script type="text/javascript" src="../plot2d/StackedAreas.js"></script>
+<script type="text/javascript" src="../plot2d/Columns.js"></script>
+<script type="text/javascript" src="../plot2d/StackedColumns.js"></script>
+<script type="text/javascript" src="../plot2d/ClusteredColumns.js"></script>
+<script type="text/javascript" src="../plot2d/Bars.js"></script>
+<script type="text/javascript" src="../plot2d/StackedBars.js"></script>
+<script type="text/javascript" src="../plot2d/ClusteredBars.js"></script>
+<script type="text/javascript" src="../plot2d/Bubble.js"></script>
+<script type="text/javascript" src="../plot2d/Grid.js"></script>
+<script type="text/javascript" src="../plot2d/Pie.js"></script>
+<script type="text/javascript" src="../Chart2D.js"></script>
+<script type="text/javascript" src="../action2d/Highlight.js"></script>
+<script type="text/javascript" src="../action2d/Magnify.js"></script>
+<script type="text/javascript" src="../action2d/MoveSlice.js"></script>
+<script type="text/javascript" src="../action2d/Shake.js"></script>
+<script type="text/javascript" src="../action2d/Tooltip.js"></script>
+<script type="text/javascript" src="../widget/Legend.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.charting.Chart2D");
+dojo.require("dojox.charting.themes.PlotKit.green");
+
+dojo.require("dojox.charting.action2d.Highlight");
+dojo.require("dojox.charting.action2d.Magnify");
+dojo.require("dojox.charting.action2d.MoveSlice");
+dojo.require("dojox.charting.action2d.Shake");
+dojo.require("dojox.charting.action2d.Tooltip");
+
+dojo.require("dojox.charting.widget.Legend");
+
+dojo.require("dojo.colors");
+dojo.require("dojo.fx.easing");
+
+var dc = dojox.charting;
+
+var dur = 450;
+
+makeObjects = function(){
+	var chart1 = new dc.Chart2D("test1");
+	chart1.setTheme(dc.themes.PlotKit.green);
+	chart1.addPlot("default", {type: "Default", lines: true, markers: true, tension:2});
+	chart1.addAxis("x", {min: 0, max: 6, majorTick: {stroke: "black", length: 3}, minorTick: {stroke: "gray", length: 3}});
+	chart1.addAxis("y", {vertical: true, min: 0, max: 10, majorTick: {stroke: "black", length: 3}, minorTick: {stroke: "gray", length: 3}});
+	chart1.addSeries("Series A", [{x: 0.5, y: 5}, {x: 1.5, y: 1.5}, {x: 2, y: 9}, {x: 5, y: 0.3}]);
+	chart1.addSeries("Series B", [{x: 0.3, y: 8}, {x: 4, y: 6, tooltip: "Custom tooltip"}, {x: 5.5, y: 2}]);
+	var anim1a = new dc.action2d.Magnify(chart1, "default");
+	var anim1b = new dc.action2d.Tooltip(chart1, "default");
+	chart1.render();
+	var legend1 = new dojox.charting.widget.Legend({chart: chart1, horizontal: false}, "legend1");
+
+	var chart2 = new dc.Chart2D("test2");
+	chart2.setTheme(dc.themes.PlotKit.green);
+	chart2.addPlot("default", {type: "StackedLines", markers: true, tension:3, shadows: {dx: 2, dy: 2, dw: 2}});
+	chart2.addSeries("Series A", [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6], {stroke: {color: "red", width: 2}, fill: "lightpink", marker: "m-3,-3 l0,6 6,0 0,-6 z"});
+	chart2.addSeries("Series B", [1, 1.6, 1.3, 1.4, 1.1, 1.5, 1.1], {stroke: {color: "blue", width: 2}, fill: "lightblue", marker: "m-3,0 c0,-4 6,-4 6,0 m-6,0 c0,4 6,4 6,0"});
+	chart2.addSeries("Series C", [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6], {stroke: {color: "green", width: 2}, fill: "lightgreen", marker: "m0,-3 l3,3 -3,3 -3,-3 z"});
+	var anim2a = new dc.action2d.Magnify(chart2, "default", {
+		scale: 3
+	});
+	var anim2b = new dc.action2d.Highlight(chart2, "default");
+	chart2.render();
+	var legend2 = new dojox.charting.widget.Legend({chart: chart2}, "legend2");
+
+	var chart3 = new dc.Chart2D("test3");
+	chart3.setTheme(dc.themes.PlotKit.green);
+	chart3.addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major"});
+	chart3.addPlot("default", {type: "Columns", gap: 2});
+	chart3.addSeries("Series A", [1, 2, 3, 4, 5], {stroke: {color: "black"}, fill: "red"});
+	chart3.addSeries("Series B", [5, 4, 3, 2, 1], {stroke: {color: "black"}, fill: "blue"});
+	var anim3a = new dc.action2d.Highlight(chart3, "default");
+	var anim3b = new dc.action2d.Tooltip(chart3, "default");
+	chart3.render();
+	var legend3 = new dojox.charting.widget.Legend({chart: chart3, horizontal: false}, "legend3");
+
+	var chart4 = new dc.Chart2D("test4");
+	chart4.setTheme(dc.themes.PlotKit.green);
+	chart4.addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true});
+	chart4.addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true});
+	chart4.addPlot("default", {type: "Bars"});
+	chart4.addSeries("Series A", [1, 2, 3, 4, 5], {stroke: {color: "black"}, fill: "red"});
+	chart4.addSeries("Series B", [5, 4, 3, 2, 1], {stroke: {color: "black"}, fill: "blue"});
+	var anim4a = new dc.action2d.Highlight(chart4, "default", {
+		highlight: "gold"
+	});
+	var anim4b = new dc.action2d.Tooltip(chart4, "default");
+	chart4.render();
+	var legend4 = new dojox.charting.widget.Legend({chart: chart4}, "legend4");
+
+	var chart5 = new dc.Chart2D("test5");
+	chart5.setTheme(dc.themes.PlotKit.green);
+	chart5.addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true});
+	chart5.addAxis("y", {vertical: true, fixLower: "minor", fixUpper: "minor", natural: true});
+	chart5.addPlot("default", {type: "ClusteredBars", gap: 5});
+	chart5.addSeries("Series A", [{y: 1, tooltip: "one/custom yellow", fill: "yellow"}, {y: 2}, {y: 3, tooltip: "three"}, {y: 4}, {y: 5, tooltip: "five"}], {stroke: {color: "black"}, fill: "red"});
+	chart5.addSeries("Series B", [{y: 5}, {y: 4, tooltip: "four"}, {y: 3, fill: "black", stroke: {width: 2, color: "#f80"}, tooltip: "custom black"}, {y: 2, tooltip: "two"}, {y: 1}], {stroke: {color: "black"}, fill: "blue"});
+	var anim5a = new dc.action2d.Highlight(chart5, "default", {
+		duration: dur,
+		easing:   dojo.fx.easing.bounceOut
+	});
+	var anim5b = new dc.action2d.Tooltip(chart5, "default");
+	chart5.render();
+	var legend5 = new dojox.charting.widget.Legend({chart: chart5, horizontal: false}, "legend5");
+
+	var chart6 = new dc.Chart2D("test6");
+	chart6.setTheme(dc.themes.PlotKit.green);
+	chart6.addAxis("x");
+	chart6.addAxis("y", {vertical: true});
+	chart6.addPlot("default", {type: "ClusteredColumns", gap: 10});
+	chart6.addPlot("grid", {type: "Grid"});
+	chart6.addSeries("Series A", [2, 1, 0.5, -1, -2], {stroke: {color: "black"}, fill: "red"});
+	chart6.addSeries("Series B", [-2, -1, -0.5, 1, 2], {stroke: {color: "black"}, fill: "blue"});
+	chart6.addSeries("Series C", [1, 0.5, -1, -2, -3], {stroke: {color: "black"}, fill: "green"});
+	var anim6a = new dc.action2d.Highlight(chart6, "default", {
+		duration: dur,
+		easing:   dojo.fx.easing.sineOut
+	});
+	var anim6b = new dc.action2d.Shake(chart6, "default");
+	var anim6c = new dc.action2d.Tooltip(chart6, "default");
+	chart6.render();
+	var legend6 = new dojox.charting.widget.Legend({chart: chart6}, "legend6");
+
+	var chart7 = new dc.Chart2D("test7");
+	chart7.setTheme(dc.themes.PlotKit.green);
+	chart7.addPlot("default", {type: "StackedColumns"});
+	chart7.addSeries("Series A", [1, 2, 3, 4, 5], {stroke: {color: "black"}, fill: "red"});
+	chart7.addSeries("Series B", [2, 1, 2, 1, 2], {stroke: {color: "black"}, fill: "blue"});
+	var anim7a = new dc.action2d.Highlight(chart7, "default", {
+		duration: dur,
+		easing:   dojo.fx.easing.bounceOut
+	});
+	var anim7b = new dc.action2d.Shake(chart7, "default");
+	var anim7c = new dc.action2d.Tooltip(chart7, "default");
+	chart7.render();
+	var legend7 = new dojox.charting.widget.Legend({chart: chart7, horizontal: false}, "legend7");
+
+	var chart8 = new dc.Chart2D("test8");
+	chart8.setTheme(dc.themes.PlotKit.green);
+	chart8.addPlot("default", {type: "StackedBars"});
+	chart8.addSeries("Series A", [1, 2, 3, 4, 5], {stroke: {color: "black"}, fill: "red"});
+	chart8.addSeries("Series B", [2, 1, 2, 1, 2], {stroke: {color: "black"}, fill: "blue"});
+	var anim8a = new dc.action2d.Highlight(chart8, "default");
+	var anim8b = new dc.action2d.Shake(chart8, "default");
+	var anim8c = new dc.action2d.Tooltip(chart8, "default");
+	chart8.render();
+	var legend8 = new dojox.charting.widget.Legend({chart: chart8}, "legend8");
+
+	var chart9 = new dc.Chart2D("test9");
+	chart9.setTheme(dc.themes.PlotKit.green);
+	chart9.addPlot("default", {type: "Bubble", shadows: {dx: 2, dy: 2, dw: 2}});
+	chart9.addAxis("x", {min: 0, max: 6, majorTick: {stroke: "black", length: 3}, minorTick: {stroke: "gray", length: 3}});
+	chart9.addAxis("y", {vertical: true, min: 0, max: 10, majorTick: {stroke: "black", length: 3}, minorTick: {stroke: "gray", length: 3}});
+	chart9.addSeries("Series A", [{x: 0.5, y: 5, size: 1.4}, {x: 1.5, y: 1.5, size:4.5}, {x: 2, y: 9, size:1.5}, {x: 5, y: 0.3, size:0.8}],
+		{stroke: {color: "black"}, fill: "red"});
+	chart9.addSeries("Series B", [{x: 0.3, y: 8, size: 2.5}, {x: 4, y: 6, size:1.1}, {x: 5.5, y: 2, size: 3.2}],
+		{stroke: {color: "black"}, fill: "blue"});
+	var anim9a = new dc.action2d.Magnify(chart9, "default", {
+		scale: 1.1
+	});
+	var anim9b = new dc.action2d.Highlight(chart9, "default");
+	var anim9c = new dc.action2d.Tooltip(chart9, "default");
+	chart9.render();
+	var legend9 = new dojox.charting.widget.Legend({chart: chart9, horizontal: false}, "legend9");
+
+	var chart10 = new dc.Chart2D("test10");
+	chart10.setTheme(dc.themes.PlotKit.green);
+	chart10.addPlot("default", {
+		type: "Pie", 
+		font: "normal normal 11pt Tahoma", 
+		fontColor: "black", 
+		labelOffset: -30,
+		radius: 80,
+		startAngle: 45
+	});
+	chart10.addSeries("Series A", [
+		{y: 4, text: "Red",   color: "red",   stroke: "black", tooltip: "Red is 50%"},
+		{y: 2, text: "Green", color: "green", stroke: "black", tooltip: "Green is 25%"},
+		{y: 1, text: "Blue",  color: "blue",  stroke: "black", tooltip: "I am feeling Blue!"},
+		{y: 1, text: "Other", color: "white", stroke: "black", tooltip: "Mighty <strong>strong</strong><br>With two lines!"}
+	]);
+	var anim10a = new dc.action2d.MoveSlice(chart10, "default");
+	var anim10b = new dc.action2d.Highlight(chart10, "default");
+	var anim10c = new dc.action2d.Tooltip(chart10, "default");
+	chart10.render();
+	var legend10 = new dojox.charting.widget.Legend({chart: chart10}, "legend10");
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body class="tundra">
+<h1>Event 2D</h1>
+<!--<p><button onclick="makeObjects();">Go</button></p>-->
+<p>Hover over markers, bars, columns, slices, and so on.</p>
+<p>1: Markers, lines, 2D data, custom axis. Actions: Magnify, Tooltip.</p>
+<div id="test1" style="width: 400px; height: 200px;"></div>
+<div id="legend1"></div>
+<p>2: Stacked lines, markers, shadows, no axes, custom strokes, fills, and markers. Actions: Magnify, Highlight.</p>
+<div id="test2" style="width: 400px; height: 200px;"></div>
+<div id="legend2"></div>
+<p>3: Columns with gaps beetwen them, vertical axis aligned on major ticks, custom strokes, fills. Actions: Highlight, Tooltip.</p>
+<div id="test3" style="width: 400px; height: 200px;"></div>
+<div id="legend3"></div>
+<p>4: Bars, axes aligned on major ticks, no minor ticks, custom strokes and fills. Actions: Highlight, Tooltip.</p>
+<div id="test4" style="width: 400px; height: 200px;"></div>
+<div id="legend4"></div>
+<p>5: Clustered bars, custom axes, custom strokes, fills, custom tooltips, and gap. Actions: Highlight, Tooltip.</p>
+<div id="test5" style="width: 400px; height: 200px;"></div>
+<div id="legend5"></div>
+<p>6: Clustered columns with positive and negative values, axes, and grid. Actions: Highlight, Shake, Tooltip.</p>
+<div id="test6" style="width: 400px; height: 200px;"></div>
+<div id="legend6"></div>
+<p>7: Stacked columns, no axes, custom strokes and fills. Actions: Highlight, Shake, Tooltip.</p>
+<div id="test7" style="width: 400px; height: 200px;"></div>
+<div id="legend7"></div>
+<p>8: Stacked bars, no axes, custom strokes and fills. Actions: Highlight, Shake, Tooltip.</p>
+<div id="test8" style="width: 400px; height: 200px;"></div>
+<div id="legend8"></div>
+<p>9: Bubble chart, axes. Actions: Magnify, Highlight, Tooltip.</p>
+<div id="test9" style="width: 400px; height: 300px;"></div>
+<div id="legend9"></div>
+<p>10: Rotated pie with internal custom labels, custom colors, and custom tooltips. Actions: MoveSlice, Highlight, Tooltip.</p>
+<div id="test10" style="width: 300px; height: 300px;"></div>
+<div id="legend10"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_fireEvent.html b/dojox/charting/tests/test_fireEvent.html
new file mode 100644
index 0000000..e2b6f42
--- /dev/null
+++ b/dojox/charting/tests/test_fireEvent.html
@@ -0,0 +1,204 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Chart 2D: fireEvent test</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+
+	.dojoxLegendNode {border: 1px solid #ccc; margin: 5px 10px 5px 10px; padding: 3px}
+	.dojoxLegendText {vertical-align: text-top; padding-right: 10px}
+
+    .events {font-size: 11pt;}
+    .events th, .events td {padding: 0.25em 1em;}
+    .events th {font-weight: bold;}
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+<script type="text/javascript" src="../Chart2D.js"></script>
+<script type="text/javascript">
+dojo.require("dijit.form.Button");
+dojo.require("dijit.form.Select");
+dojo.require("dijit.form.NumberSpinner");
+
+dojo.require("dojox.charting.Chart2D");
+dojo.require("dojox.charting.themes.CubanShirts");
+dojo.require("dojox.charting.widget.Legend");
+
+dojo.require("dojox.charting.action2d.Base");
+dojo.require("dojox.charting.action2d.Highlight");
+dojo.require("dojox.charting.action2d.Magnify");
+dojo.require("dojox.charting.action2d.MoveSlice");
+dojo.require("dojox.charting.action2d.Shake");
+dojo.require("dojox.charting.action2d.Tooltip");
+
+dojo.require("dojox.lang.functional.sequence");
+
+var chart, legend, size = 10, magnitude = 30, none = "<em>none</em>";
+
+
+var Listener = dojo.declare(dojox.charting.action2d.Base, {
+    constructor: function(chart, plot, tr){
+        this.tr = dojo.byId(tr);
+        this.connect();
+    },
+
+    process: function(o){
+        var t = [
+                o.plot ? o.plot.name : none,
+                o.type === "onindirect" ? o.type + " (" + (o.originalPlot ? o.originalPlot.name : none) + " : " + o.originalEvent + ")" : o.type,
+                o.event ? "object" : none,
+                o.hAxis || none,
+                o.vAxis || none,
+                o.run ? o.run.name : none,
+                "index" in o ? o.index : none,
+                "x" in o ? o.x : none,
+                "y" in o ? o.y : none
+            ];
+        dojo.query("td", this.tr).forEach(function(td, i){
+            td.innerHTML = t[i] + "";
+        });
+    }
+});
+
+function getData(){
+	var data = new Array(size);
+	for(var i = 0; i < size; ++i){
+		data[i] = Math.random() * magnitude;
+	}
+	return data;
+};
+
+function getZeroes(){
+	return dojox.lang.functional.repeat(size, "-> 0", 0);
+};
+
+var actions = [];
+
+function addActions(chart){
+	dojox.lang.functional.forEach(actions, ".destroy()");
+	actions = [
+		new dojox.charting.action2d.Highlight(chart),
+		new dojox.charting.action2d.Magnify(chart),
+		new dojox.charting.action2d.MoveSlice(chart),
+		new dojox.charting.action2d.Tooltip(chart),
+		new Listener(chart, "default", "def")
+	];
+}
+
+function makeObjects(){
+	chart = new dojox.charting.Chart2D("test");
+	chart.setTheme(dojox.charting.themes.CubanShirts);
+
+	chart.addAxis("x", {natural: true, includeZero: true, fixUpper: "minor"});
+
+	chart.addAxis("y", {vertical: true, natural: true, includeZero: true, fixUpper: "minor"});
+
+	chart.addPlot("default", {type: dijit.byId("plot").get("value"), gap: 2});
+    addActions(chart);
+
+	chart.addPlot("empty"); // just to see indirect events
+    new Listener(chart, "empty", "emp");
+
+
+	chart.addPlot("grid", {type: "Grid", hMinorLines: true, vMinorLines: true});
+
+	for(var i = 1; i <= 5; ++i){
+		chart.addSeries("Series " + i, getData(), {stroke: {color: "black", width: 1}});
+	}
+
+	chart.render();
+
+	legend = new dojox.charting.widget.Legend({chart: chart}, "legend");
+};
+
+dojo.addOnLoad(makeObjects);
+
+changePlot = function(){
+	var type = dijit.byId("plot").get("value"),
+        opts = {type: type, gap: 2};
+    switch(type){
+        case "Lines":
+        case "StackedAreas":
+            opts.markers = true;
+            break;
+        case "Pie":
+            opts.radius = 150;
+            break;
+    }
+	chart.addPlot("default", opts);
+    addActions(chart);
+	chart.render();
+	legend.refresh();
+};
+
+fireEvent = function(type){
+    chart.fireEvent(
+        dijit.byId("series").get("value"),
+        type,
+        dijit.byId("index").get("value")
+    );
+}
+
+</script>
+</head>
+<body class="tundra">
+
+<h1>Chart 2D: fireEvent test</h1>
+
+<p>
+    <span>Plot: </span>
+    <select dojoType="dijit.form.Select" id="plot" onChange="changePlot()">
+        <option value="Columns">Columns</option>
+        <option value="ClusteredColumns">ClusteredColumns</option>
+        <option value="StackedColumns">StackedColumns</option>
+        <option value="Bars">Bars</option>
+        <option value="ClusteredBars">ClusteredBars</option>
+        <option value="StackedBars">StackedBars</option>
+        <option value="Lines">Lines</option>
+        <option value="StackedAreas">StackedAreas</option>
+        <option value="Pie">Pie</option>
+    </select>
+</p>
+
+<table class="events" border="1">
+    <thead>
+        <tr>
+            <th>Plot</th><th>Event</th><th>Event Object</th><th>H. axis</th><th>V. axis</th><th>Series</th><th>Index</th><th>X value</th><th>Y value</th>
+        </tr>
+    </thead>
+    <tbody>
+        <tr id="def">
+            <td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td>
+        </tr>
+        <tr id="emp">
+            <td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td>
+        </tr>
+    </tbody>
+</table>
+
+<p>
+    <span>Fire event: </span>
+    <select dojoType="dijit.form.Select" id="series">
+        <option value="Series 1">Series 1</option>
+        <option value="Series 2">Series 2</option>
+        <option value="Series 3">Series 3</option>
+        <option value="Series 4">Series 4</option>
+        <option value="Series 5">Series 5</option>
+    </select>
+    <span> on index: </span>
+	<input dojoType="dijit.form.NumberSpinner" id="index" value="0" constraints="{min: 0, max: 9, fractional: false}" style="width: 5em;">
+     <button dojoType="dijit.form.Button" onClick="fireEvent('onmouseover')">onmouseover</button>
+     <button dojoType="dijit.form.Button" onClick="fireEvent('onmouseout')">onmouseout</button>
+     <button dojoType="dijit.form.Button" onClick="fireEvent('onclick')">onclick</button>
+</p>
+
+<p><em>Warning: the pie chart shows only the last series (Series 5).</em></p>
+
+<div id="test" style="width: 600px; height: 400px;"></div>
+<div id="legend"></div>
+
+</body>
+</html>
diff --git a/dojox/charting/tests/test_labels2d.html b/dojox/charting/tests/test_labels2d.html
new file mode 100644
index 0000000..11736ca
--- /dev/null
+++ b/dojox/charting/tests/test_labels2d.html
@@ -0,0 +1,214 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Chart 2D labels</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<!--
+The next line should include Microsoft's Silverligth.js, if you plan to use the silverlight backend
+<script type="text/javascript" src="Silverlight.js"></script>
+-->
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../../lang/functional.js"></script>
+<script type="text/javascript" src="../../lang/utils.js"></script>
+<script type="text/javascript" src="../Theme.js"></script>
+<script type="text/javascript" src="../scaler/linear.js"></script>
+<script type="text/javascript" src="../Element.js"></script>
+<script type="text/javascript" src="../axis2d/common.js"></script>
+<script type="text/javascript" src="../axis2d/Base.js"></script>
+<script type="text/javascript" src="../axis2d/Default.js"></script>
+<script type="text/javascript" src="../plot2d/common.js"></script>
+<script type="text/javascript" src="../plot2d/Base.js"></script>
+<script type="text/javascript" src="../plot2d/Default.js"></script>
+<script type="text/javascript" src="../plot2d/Lines.js"></script>
+<script type="text/javascript" src="../plot2d/Areas.js"></script>
+<script type="text/javascript" src="../plot2d/Markers.js"></script>
+<script type="text/javascript" src="../plot2d/MarkersOnly.js"></script>
+<script type="text/javascript" src="../plot2d/Stacked.js"></script>
+<script type="text/javascript" src="../plot2d/StackedLines.js"></script>
+<script type="text/javascript" src="../plot2d/StackedAreas.js"></script>
+<script type="text/javascript" src="../plot2d/Columns.js"></script>
+<script type="text/javascript" src="../plot2d/StackedColumns.js"></script>
+<script type="text/javascript" src="../plot2d/ClusteredColumns.js"></script>
+<script type="text/javascript" src="../plot2d/Bars.js"></script>
+<script type="text/javascript" src="../plot2d/StackedBars.js"></script>
+<script type="text/javascript" src="../plot2d/ClusteredBars.js"></script>
+<script type="text/javascript" src="../plot2d/Grid.js"></script>
+<script type="text/javascript" src="../plot2d/Pie.js"></script>
+<script type="text/javascript" src="../Chart2D.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.charting.Chart2D");
+dojo.require("dojox.charting.themes.PlotKit.blue");
+dojo.require("dojox.charting.themes.PlotKit.cyan");
+dojo.require("dojox.charting.themes.PlotKit.green");
+dojo.require("dojox.charting.themes.PlotKit.orange");
+dojo.require("dojox.charting.themes.PlotKit.purple");
+dojo.require("dojox.charting.themes.PlotKit.red");
+
+makeObjects = function(){
+	var chart1 = new dojox.charting.Chart2D("test1");
+	chart1.addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true});
+	chart1.addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true});
+	chart1.addPlot("default", {type: "Bars"});
+	chart1.addSeries("Series A", [1, 2, 3, 4, 5], {stroke: {color: "red"}, fill: "lightpink"});
+	chart1.addSeries("Series B", [5, 4, 3, 2, 1], {stroke: {color: "blue"}, fill: "lightblue"});
+	chart1.render();
+	
+	var chart2 = new dojox.charting.Chart2D("test2");
+	chart2.addAxis("x", {
+		fixLower: "major", fixUpper: "major", includeZero: true, 
+		labels: [
+			//{value: 0, text: "zero"},
+			{value: 2, text: "two"},
+			{value: 4, text: "four"}
+		]
+	});
+	chart2.addAxis("y", {
+		vertical: true, fixLower: "major", fixUpper: "major", natural: true,
+		labels: [{value: 0, text: ""},
+			{value: 1, text: "Jan"}, {value: 2, text: "Feb"},
+			{value: 3, text: "Mar"}, {value: 4, text: "Apr"},
+			{value: 5, text: "May"}, {value: 6, text: "Jun"}]
+	});
+	chart2.addPlot("default", {type: "Bars"});
+	chart2.addSeries("Series A", [1, 2, 3, 4, 5], {stroke: {color: "red"}, fill: "lightpink"});
+	chart2.addSeries("Series B", [5, 4, 3, 2, 1], {stroke: {color: "blue"}, fill: "lightblue"});
+	chart2.render();
+
+	
+	var chart3 = new dojox.charting.Chart2D("test3");
+	chart3.addAxis("x", {
+		fixLower: "major", fixUpper: "major", includeZero: true, 
+		labels: [{value: 0, text: "z e r o"}, {value: 2, text: "t w o"}, {value: 4, text: "f o u r"}]
+	});
+	chart3.addAxis("y", {
+		vertical: true, fixLower: "major", fixUpper: "major", natural: true,
+		labels: [{value: 0, text: ""},
+			{value: 1, text: "J A N"}, {value: 2, text: "F E B"},
+			{value: 3, text: "M A R"}, {value: 4, text: "A P R"},
+			{value: 5, text: "M A Y"}, {value: 6, text: "J U N"}]
+	});
+	chart3.addPlot("default", {type: "Bars"});
+	chart3.addSeries("Series A", [1, 2, 3, 4, 5], {stroke: {color: "red"}, fill: "lightpink"});
+	chart3.addSeries("Series B", [5, 4, 3, 2, 1], {stroke: {color: "blue"}, fill: "lightblue"});
+	chart3.render();
+	
+	var chart4 = new dojox.charting.Chart2D("test4");
+	chart4.addAxis("x", {
+		majorLabels: false,
+		includeZero: true, 
+		minorTicks: false, 
+		microTicks: false, 
+		majorTick: { length: 0 }
+	});
+	chart4.addAxis("y", {
+		vertical: true, 
+		fixLower: "none", 
+		fixUpper: "none", 
+		natural: true,
+		majorTick: { length: 3 },
+		labels: [
+			{value: 0, text: ""},
+			{value: 1, text: "January"}, 
+			{value: 2, text: "Febuary"},
+			{value: 3, text: "March"}, 
+			{value: 4, text: "April"},
+			{value: 5, text: "May"} 
+		]
+	});
+	chart4.addPlot("default", { type: "Bars", gap: 3 });
+	chart4.addSeries(
+		"Series A", 
+		[ 1, 6, 9, 4, 5, 2 ],
+		{
+			stroke: {width: 0}, 
+			// fill: "#ffcc2d",
+			fill: {
+				type: "linear",
+				x1: 0, y1: 0,
+				x2: 150, y2: 0,
+				colors: [
+					{ offset: 0,   color: "#ffe495" },
+					{ offset: 1,   color: "#ffcc2d" }
+				]
+			}
+		}
+	);
+	chart4.render();
+
+	var chart5 = new dojox.charting.Chart2D("test5").
+			addAxis("x", {
+				fixLower: "major", fixUpper: "major", includeZero: true, 
+				labels: [
+					{value: 0, text: "zero"},
+					{value: 2, text: "two"},
+					{value: 4, text: "four"}
+				],
+				rotation: 30
+			}).
+			addAxis("y", {
+				vertical: true, fixLower: "major", fixUpper: "major", natural: true,
+				labels: [{value: 0, text: ""},
+					{value: 1, text: "January"}, {value: 2, text: "February"},
+					{value: 3, text: "March"}, {value: 4, text: "April"},
+					{value: 5, text: "May"}, {value: 6, text: "June"}
+				],
+				rotation: -30
+			}).
+			addPlot("default", {type: "Bars"}).
+			addSeries("Series A", [1, 2, 3, 4, 5], {stroke: {color: "red"}, fill: "lightpink"}).
+			addSeries("Series B", [5, 4, 3, 2, 1], {stroke: {color: "blue"}, fill: "lightblue"}).
+			render();
+
+	var chart6 = new dojox.charting.Chart2D("test6").
+			addAxis("x", {
+				fixLower: "major", fixUpper: "major", includeZero: true, 
+				labels: [
+					{value: 0, text: "zero"},
+					{value: 2, text: "two"},
+					{value: 4, text: "four"}
+				],
+				rotation: 180
+			}).
+			addAxis("y", {
+				vertical: true, fixLower: "major", fixUpper: "major", natural: true, majorTickStep: 2,
+				labels: [{value: 0, text: ""},
+					{value: 1, text: "January"}, {value: 2, text: "February"},
+					{value: 3, text: "March"}, {value: 4, text: "April"},
+					{value: 5, text: "May"}, {value: 6, text: "June"}
+				],
+				rotation: 90
+			}).
+			addPlot("default", {type: "Bars"}).
+			addSeries("Series A", [1, 2, 3, 4, 5], {stroke: {color: "red"}, fill: "lightpink"}).
+			addSeries("Series B", [5, 4, 3, 2, 1], {stroke: {color: "blue"}, fill: "lightblue"}).
+			render();
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Chart 2D labels</h1>
+<!--<p><button onclick="makeObjects();">Go</button></p>-->
+<p>1: Bars, axes aligned on major ticks, no minor ticks, custom strokes and fills.</p>
+<div id="test1" style="width: 200px; height: 200px;"></div>
+<p>2: Bars, axes aligned on major ticks, no minor ticks, custom strokes and fills, custom labels.</p>
+<div id="test2" style="width: 200px; height: 200px;"></div>
+<p>3: Bars, axes aligned on major ticks, no minor ticks, custom strokes and fills, custom labels with spaces.</p>
+<div id="test3" style="width: 200px; height: 200px;"></div>
+<p>4: Trying to make it look good.</p>
+<div id="test4" style="width: 200px; height: 200px;"></div>
+<p>5: Label rotation.</p>
+<div id="test5" style="width: 200px; height: 200px;"></div>
+<p>6: Label rotation (opposite).</p>
+<div id="test6" style="width: 200px; height: 200px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_nulls.html b/dojox/charting/tests/test_nulls.html
new file mode 100644
index 0000000..7423650
--- /dev/null
+++ b/dojox/charting/tests/test_nulls.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Chart 2D nulls</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<style>
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script>
+
+dojo.require("dojox.charting.Chart2D");
+
+makeObjects = function(){
+
+	var types = [ "Areas", "Bars", "ClusteredBars", "ClusteredColumns", "Lines", "Markers", "StackedAreas", "StackedBars", "StackedColumns", "StackedLines" ];
+
+	dojo.forEach(types, function(type, i){
+		new dojox.charting.Chart2D("test" + (i + 1))
+		.addAxis("x", { vertical: false, min: 0, max: 15 })
+		.addAxis("y", { vertical: true, min: 0, max: 15 })
+		.addPlot("default", { type: type })
+		.addSeries("Series A", [3, 5, null, 4, 0, 4, null, 1, 6, 5], { stroke: {color: "blue"}, fill: "lightblue" })
+		.addSeries("Series B", [6, 9, null, 5, 10, 7, 6, 3, 8, 6], { stroke: {color: "red"}, fill: "lightpink" })
+		.render();
+	});
+	
+	new dojox.charting.Chart2D("test10")
+	.addAxis("x", { vertical: false, min: 0, max: 15 })
+	.addAxis("y", { vertical: true, min: 0, max: 15 })
+	.addPlot("default", { type: "Candlesticks" })
+	.addSeries("Series A", [
+		{ low: 2, open: 3, close: 4, high: 9 },
+		{ low: 2, open: 5, close: 7, high: 8 },
+		null, 
+		{ low: 2, open: 4, close: 2, high: 5 },
+		{ low: 0, open: 0, close: 3, high: 3 },
+		{ low: 3, open: 4, close: 6, high: 7 },
+		null, 
+		{ low: 1, open: 1, close: 1, high: 1 },
+		{ low: 2, open: 6, close: 3, high: 8 },
+		{ low: 3, open: 5, close: 9, high: 10 }
+	], { stroke: {color: "blue"}, fill: "lightblue" })
+	.render();
+	
+	new dojox.charting.Chart2D("test11")
+	.addPlot("default", { type: "Pie" })
+	.addSeries("Series A", [3, 5, null, 4, 0, 4, null, 1, 6, 5])
+	.render();
+	
+	new dojox.charting.Chart2D("test12")
+	.addAxis("x", { vertical: false, min: 0, max: 15 })
+	.addAxis("y", { vertical: true, min: 0, max: 15 })
+	.addPlot("default", { type: "Bubble" })
+	.addSeries("Series A", [
+		{ x: 2, y: 5, size: 2 },
+		null,
+		{ x: 8, y: 6, size: 5 },
+		{ x: 5, y: 9, size: 4 },
+		null,
+		{ x: 5, y: 1, size: 1 }
+	])
+	.render();
+	
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Chart 2D nulls in series</h1>
+<div id="test1" style="width: 200px; height: 200px;"></div>
+<div id="test2" style="width: 200px; height: 200px;"></div>
+<div id="test3" style="width: 200px; height: 200px;"></div>
+<div id="test4" style="width: 200px; height: 200px;"></div>
+<div id="test5" style="width: 200px; height: 200px;"></div>
+<div id="test6" style="width: 200px; height: 200px;"></div>
+<div id="test7" style="width: 200px; height: 200px;"></div>
+<div id="test8" style="width: 200px; height: 200px;"></div>
+<div id="test9" style="width: 200px; height: 200px;"></div>
+<div id="test10" style="width: 200px; height: 200px;"></div>
+<div id="test11" style="width: 200px; height: 200px;"></div>
+<div id="test12" style="width: 200px; height: 200px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_pie2d.html b/dojox/charting/tests/test_pie2d.html
new file mode 100644
index 0000000..bc72f77
--- /dev/null
+++ b/dojox/charting/tests/test_pie2d.html
@@ -0,0 +1,164 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Pie 2D</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<!--
+The next line should include Microsoft's Silverligth.js, if you plan to use the silverlight backend
+<script type="text/javascript" src="Silverlight.js"></script>
+-->
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../../lang/functional.js"></script>
+<script type="text/javascript" src="../../lang/functional/fold.js"></script>
+<script type="text/javascript" src="../../lang/utils.js"></script>
+<script type="text/javascript" src="../Theme.js"></script>
+<script type="text/javascript" src="../scaler/linear.js"></script>
+<script type="text/javascript" src="../Element.js"></script>
+<script type="text/javascript" src="../plot2d/Pie.js"></script>
+<script type="text/javascript" src="../Chart2D.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.charting.Chart2D");
+dojo.require("dojox.charting.themes.PlotKit.blue");
+dojo.require("dojox.charting.themes.PlotKit.green");
+dojo.require("dojox.charting.themes.PlotKit.red");
+dojo.require("dojox.charting.themes.Adobebricks");
+dojo.require("dojox.charting.themes.Algae");
+
+makeObjects = function(){
+	var chart1 = new dojox.charting.Chart2D("test1");
+	chart1.setTheme(dojox.charting.themes.PlotKit.blue);
+	chart1.addPlot("default", {
+		type: "Pie",
+		font: "normal normal bold 12pt Tahoma",
+		fontColor: "white",
+		labelOffset: 40
+	});
+	chart1.addSeries("Series A", [4, 2, 1, 1]);
+	chart1.render();
+
+	var chart2 = new dojox.charting.Chart2D("test2");
+	chart2.setTheme(dojox.charting.themes.PlotKit.blue);
+	chart2.addPlot("default", {
+		type: "Pie",
+		font: "normal normal bold 12pt Tahoma",
+		fontColor: "black",
+		labelOffset: -25,
+		precision: 0
+	});
+	chart2.addSeries("Series A", [4, 2, 1, 1]);
+	chart2.render();
+
+	var chart3 = new dojox.charting.Chart2D("test3");
+	chart3.setTheme(dojox.charting.themes.PlotKit.green);
+	chart3.addPlot("default", {
+		type: "Pie",
+		font: "normal normal bold 10pt Tahoma",
+		fontColor: "white",
+		labelOffset: 25,
+		radius: 90
+	});
+	chart3.addSeries("Series A", [4, 2, 1, 1]);
+	chart3.render();
+
+	var chart4 = new dojox.charting.Chart2D("test4");
+	chart4.setTheme(dojox.charting.themes.PlotKit.green);
+	chart4.addPlot("default", {
+		type: "Pie",
+		font: "normal normal bold 10pt Tahoma",
+		fontColor: "black",
+		labelOffset: -25,
+		radius: 90
+	});
+	chart4.addSeries("Series A", [4, 2, 1, 1]);
+	chart4.render();
+
+	var chart5 = new dojox.charting.Chart2D("test5");
+	chart5.setTheme(dojox.charting.themes.PlotKit.red);
+	chart5.addPlot("default", {
+		type: "Pie",
+		font: "normal normal bold 14pt Tahoma",
+		fontColor: "white",
+		labelOffset: 40
+	});
+	chart5.addSeries("Series A", [{y: 4, text: "Red"}, {y: 2, text: "Green"}, {y: 1, text: "Blue"}, {y: 1, text: "Other"}]);
+	chart5.render();
+
+	var chart6 = new dojox.charting.Chart2D("test6");
+	chart6.setTheme(dojox.charting.themes.PlotKit.red);
+	chart6.addPlot("default", {
+		type: "Pie",
+		font: "normal normal bold 14pt Tahoma",
+		fontColor: "white",
+		labelOffset: 40,
+		startAngle: -45
+	});
+	chart6.addSeries("Series A", [
+		{y: 4, text: "Red", color: "red"},
+		{y: 2, text: "Green", color: "green"},
+		{y: 1, text: "Blue", color: "blue"},
+		{y: 1, text: "Other", color: "white", fontColor: "black"}
+	]);
+	chart6.render();
+
+	var chart7 = new dojox.charting.Chart2D("test7");
+	chart7.setTheme(dojox.charting.themes.Adobebricks);
+	chart7.addPlot("default", {
+		type: "Pie",
+		font: "normal normal bold 12pt Tahoma",
+		fontColor: "white",
+		radius: 80
+	});
+	chart7.addSeries("Series A", [4]);
+	chart7.render();
+
+	var chart8 = new dojox.charting.Chart2D("test8");
+	chart8.setTheme(dojox.charting.themes.Algae);
+	chart8.addPlot("default", {
+		type: "Pie",
+		font: "normal normal bold 12pt Tahoma",
+		fontColor: "white",
+		radius: 80
+	});
+	chart8.addSeries("Series A", [
+		{y: -1, text: "Red", color: "red"},
+		{y: 5, text: "Green", color: "green"},
+		{y: 0, text: "Blue", color: "blue"},
+		{y: 0, text: "Other", color: "white", fontColor: "black"}
+	]);
+	chart8.render();
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Pie 2D</h1>
+<!--<p><button onclick="makeObjects();">Go</button></p>-->
+<p>1: Pie with internal labels.</p>
+<div id="test1" style="width: 300px; height: 300px;"></div>
+<p>2: Pie with external labels and precision=0.</p>
+<div id="test2" style="width: 300px; height: 300px;"></div>
+<p>3/4: Two pies with internal and external labels with a constant radius.</p>
+<table border="1"><tr>
+	<td><div id="test3" style="width: 300px; height: 300px;"></div></td>
+	<td><div id="test4" style="width: 300px; height: 300px;"></div></td>
+</tr></table>
+<p>5/6: Pie with internal custom labels and custom colors (#6 is rotated).</p>
+<table border="1"><tr>
+	<td><div id="test5" style="width: 300px; height: 300px;"></div></td>
+	<td><div id="test6" style="width: 300px; height: 300px;"></div></td>
+</tr></table>
+<p>7: Degenerated pie with 1 element.</p>
+<div id="test7" style="width: 200px; height: 200px;"></div>
+<p>8: Degenerated pie with 1 positive elements (out of 5).</p>
+<div id="test8" style="width: 200px; height: 200px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_plot_order.html b/dojox/charting/tests/test_plot_order.html
new file mode 100644
index 0000000..ecf61c5
--- /dev/null
+++ b/dojox/charting/tests/test_plot_order.html
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Testing plot order</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dojo/resources/dnd.css";
+	@import "../../../dojo/tests/dnd/dndDefault.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script>
+
+dojo.require("dojox.charting.Chart2D");
+dojo.require("dojox.charting.themes.ThreeD");
+dojo.require("dojox.charting.widget.Legend");
+
+dojo.require("dojo.dnd.Source");
+
+makeObjects = function(){
+    dojo.query("button").style("disabled", true);
+    
+	var chart1 = new dojox.charting.Chart2D("chart1").
+            setTheme(dojox.charting.themes.ThreeD).
+            addAxis("x", {min: 0, max: 10}).
+            addAxis("y", {vertical: true, min: 0, max: 10}).
+            addPlot("Plot 1", {type: "Bubble"}).
+            addSeries("Plot 1 / Series A", [{x: 3, y: 3, size: 4}], {plot: "Plot 1"}).
+            addPlot("Plot 2", {type: "Bubble"}).
+            addSeries("Plot 2 / Series B", [{x: 5, y: 5, size: 4}], {plot: "Plot 2"}).
+            //addSeries("Plot 2 / Series B1", [{x: 5, y: 6, size: 3}], {plot: "Plot 2"}).
+            //addSeries("Plot 2 / Series B2", [{x: 4, y: 4, size: 3}], {plot: "Plot 2"}).
+            //addSeries("Plot 2 / Series B3", [{x: 6, y: 4, size: 3}], {plot: "Plot 2"}).
+            addPlot("Plot 3", {type: "Bubble"}).
+            addSeries("Plot 3 / Series C", [{x: 7, y: 7, size: 4}], {plot: "Plot 3"}).
+            render();
+
+	var legend1 = new dojox.charting.widget.Legend({chart: chart1, horizontal: false}, "legend1");
+    dojo.connect(chart1, "render", legend1, "refresh");
+    
+    var plots = new dojo.dnd.Source("dnd1"), noUpdate = false;
+    plots.insertNodes(false, chart1.getPlotOrder());
+    dojo.connect(plots, "onDropInternal", function(){
+        var newOrder = this.getAllNodes().map(function(node){
+                return node.innerHTML;
+            })
+        chart1.setPlotOrder(newOrder);
+        noUpdate = true;
+        chart1.render();
+        noUpdate = false;
+    });
+    dojo.connect(chart1, "render", function(){
+        if(!noUpdate){
+            plots.getAllNodes().orphan();
+            plots.sync();
+            plots.insertNodes(false, chart1.getPlotOrder());
+        }
+    });
+
+    dojo.forEach(["p1", "p2", "p3"], function(id, i){
+        dojo.query("button", id).forEach(function(btn){
+            if(btn.innerHTML == "Front"){
+                dojo.connect(btn, "onclick", function(){
+                    chart1.movePlotToFront("Plot " + (i + 1));
+                    chart1.render();
+                });
+            }else{
+                dojo.connect(btn, "onclick", function(){
+                    chart1.movePlotToBack("Plot " + (i + 1));
+                    chart1.render();
+                });
+            }
+        });
+    });
+};
+
+dojo.ready(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Testing plot order</h1>
+<!--<p><button onclick="makeObjects();">Go</button></p>-->
+<p>Chart:</p>
+<div id="chart1" style="width: 200px; height: 200px;"></div>
+<div id="legend1"></div>
+<p id="p1">Plot 1: <button>Front</button> <button>Back</button></p>
+<p id="p2">Plot 2: <button>Front</button> <button>Back</button></p>
+<p id="p3">Plot 3: <button>Front</button> <button>Back</button></p>
+<p>Plots (rearrange using drag-and-drop):</p>
+<div id="dnd1" class="container"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_rotatedLabels.html b/dojox/charting/tests/test_rotatedLabels.html
new file mode 100644
index 0000000..1499a81
--- /dev/null
+++ b/dojox/charting/tests/test_rotatedLabels.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Chart 2D rotated labels</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+<script type="text/javascript">
+
+dojo.require("dijit.form.Button");
+dojo.require("dijit.form.NumberSpinner");
+
+dojo.require("dojox.charting.Chart2D");
+dojo.require("dojox.charting.themes.PrimaryColors");
+
+var chart;
+
+makeObjects = function(){
+	chart = new dojox.charting.Chart2D("test1").
+        setTheme(dojox.charting.themes.PrimaryColors).
+        addPlot("default").
+        addSeries("Series A", [1, 3, 2, 5, 4]).
+        addPlot("default2", {hAxis: "x2", vAxis: "y2"}).
+        addSeries("Series B", [5, 3, 4, 1, 2], {plot: "default2"});
+    updateAxes();
+};
+
+dojo.addOnLoad(makeObjects);
+
+updateAxes = function(){
+    var rotation = dijit.byId("rotation").get("value");
+	chart.
+        addAxis("x", {
+            htmlLabels: false, fixLower: "major", fixUpper: "major", min: 0, max: 6,
+            labels: [
+                {value: 0, text: "zero"},
+                {value: 1, text: "one"},
+                {value: 2, text: "two"},
+                {value: 3, text: "three"},
+                {value: 4, text: "four"},
+                {value: 5, text: "five"},
+                {value: 6, text: "six"}
+            ],
+            rotation: rotation
+        }).
+        addAxis("y", {
+            htmlLabels: false, vertical: true, fixLower: "major", fixUpper: "major", natural: true,  min: 0, max: 6,
+            labels: [{value: 0, text: ""},
+                {value: 1, text: "January"}, {value: 2, text: "February"},
+                {value: 3, text: "March"}, {value: 4, text: "April"},
+                {value: 5, text: "May"}, {value: 6, text: "June"}
+            ],
+            rotation: rotation
+        }).
+        addAxis("x2", {
+            htmlLabels: false, fixLower: "major", fixUpper: "major", min: 0, max: 6, leftBottom: false,
+            rotation: rotation
+        }).
+        addAxis("y2", {
+            htmlLabels: false, vertical: true, fixLower: "major", fixUpper: "major", min: 0, max: 6, leftBottom: false,
+            rotation: rotation
+        }).
+        render();
+}
+
+</script>
+</head>
+<body class="tundra">
+<h1>Chart 2D rotated labels</h1>
+<!--<p><button onclick="makeObjects();">Go</button></p>-->
+<p>
+    Rotation: 
+    <input dojoType="dijit.form.NumberSpinner" id="rotation" value="0" constraints="{min: 0, max: 360, fractional: false}" style="width: 8em;">
+     
+    <button dojoType="dijit.form.Button" onClick="updateAxes()">Apply</button>
+</p>
+<div id="test1" style="width: 600px; height: 400px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_scaler.html b/dojox/charting/tests/test_scaler.html
new file mode 100644
index 0000000..c7812d3
--- /dev/null
+++ b/dojox/charting/tests/test_scaler.html
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Scaler/tick generator</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<!--
+The next line should include Microsoft's Silverligth.js, if you plan to use the silverlight backend
+<script type="text/javascript" src="Silverlight.js"></script>
+-->
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../scaler/linear.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.charting.scaler.linear");
+
+calc = function(){
+	var min = parseFloat(dojo.byId("imin").value);
+	var max = parseFloat(dojo.byId("imax").value);
+	var span = parseFloat(dojo.byId("ispan").value);
+	
+	var o = dojox.charting.scaler.linear.buildScaler(
+		min, max, span, {
+			fixLower: dojo.byId("ifl").value,
+			fixUpper: dojo.byId("ifu").value,
+			natural:  Boolean(dojo.byId("inat").checked)
+		}
+	);
+	
+	dojo.byId("imin").value = min;
+	dojo.byId("imax").value = max;
+	dojo.byId("ispan").value = span;
+	
+	dojo.byId("olb").innerHTML = o.bounds.lower;
+	dojo.byId("oub").innerHTML = o.bounds.upper;
+	
+	dojo.byId("omajt").innerHTML = o.major.tick;
+	dojo.byId("omajs").innerHTML = o.major.start;
+	dojo.byId("omajc").innerHTML = o.major.count;
+	dojo.byId("omajp").innerHTML = o.major.prec;
+	
+	dojo.byId("omint").innerHTML = o.minor.tick;
+	dojo.byId("omins").innerHTML = o.minor.start;
+	dojo.byId("ominc").innerHTML = o.minor.count;
+	dojo.byId("ominp").innerHTML = o.minor.prec;
+	
+	dojo.byId("omict").innerHTML = o.micro.tick;
+	dojo.byId("omics").innerHTML = o.micro.start;
+	dojo.byId("omicc").innerHTML = o.micro.count;
+	dojo.byId("omicp").innerHTML = o.micro.prec;
+	
+	dojo.byId("oscale").innerHTML = o.scale;
+	dojo.byId("ospan").innerHTML  = o.span;
+};
+
+</script>
+</head>
+<body>
+<h1>Scaler/tick generator</h1>
+<h2>Input</h2>
+<table>
+	<tr><th>Name</th><th>Value</th></tr>
+	<tr><td>min</td><td><input type="text" id="imin" /></td></tr>
+	<tr><td>max</td><td><input type="text" id="imax" /></td></tr>
+	<tr><td>span</td><td><input type="text" id="ispan" /></td></tr>
+	<tr><td>natural</td><td><input type="checkbox" id="inat" /></td></tr>
+	<tr><td>fixLower</td><td><input type="text" id="ifl" /></td></tr>
+	<tr><td>fixUpper</td><td><input type="text" id="ifu" /></td></tr>
+</table>
+<p><button onclick="calc()">Calculate!</button></p>
+<h2>Output</h2>
+<table>
+	<tr><th>Name</th><th>Value</th></tr>
+	
+	<tr><td>lowerBound</td><td><span id="olb"> </span></td></tr>
+	<tr><td>upperBound</td><td><span id="oub"> </span></td></tr>
+	
+	<tr><td>major.tick</td><td><span id="omajt"> </span></td></tr>
+	<tr><td>major.start</td><td><span id="omajs"> </span></td></tr>
+	<tr><td>major.count</td><td><span id="omajc"> </span></td></tr>
+	<tr><td>major.prec</td><td><span id="omajp"> </span></td></tr>
+
+	<tr><td>minor.tick</td><td><span id="omint"> </span></td></tr>
+	<tr><td>minor.start</td><td><span id="omins"> </span></td></tr>
+	<tr><td>minor.count</td><td><span id="ominc"> </span></td></tr>
+	<tr><td>minor.prec</td><td><span id="ominp"> </span></td></tr>
+
+	<tr><td>micro.tick</td><td><span id="omict"> </span></td></tr>
+	<tr><td>micro.start</td><td><span id="omics"> </span></td></tr>
+	<tr><td>micro.count</td><td><span id="omicc"> </span></td></tr>
+	<tr><td>micro.prec</td><td><span id="omicp"> </span></td></tr>
+
+	<tr><td>scale</td><td><span id="oscale"> </span></td></tr>
+	<tr><td>span</td><td><span id="ospan"> </span></td></tr>
+</table>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_series_order.html b/dojox/charting/tests/test_series_order.html
new file mode 100644
index 0000000..272554f
--- /dev/null
+++ b/dojox/charting/tests/test_series_order.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Testing series order</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dojo/resources/dnd.css";
+	@import "../../../dojo/tests/dnd/dndDefault.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script>
+
+dojo.require("dojox.charting.Chart2D");
+dojo.require("dojox.charting.themes.ThreeD");
+dojo.require("dojox.charting.widget.Legend");
+
+dojo.require("dojo.dnd.Source");
+
+makeObjects = function(){
+    dojo.query("button").style("disabled", true);
+    
+	var chart1 = new dojox.charting.Chart2D("chart1").
+            setTheme(dojox.charting.themes.ThreeD).
+            addAxis("x", {min: 0, max: 10}).
+            addAxis("y", {vertical: true, min: 0, max: 10}).
+            addPlot("Plot 1", {type: "Bubble"}).
+            addSeries("Series A", [{x: 3, y: 3, size: 4}], {plot: "Plot 1", color: "red"}).
+            addSeries("Series B", [{x: 5, y: 5, size: 4}], {plot: "Plot 1", color: "green"}).
+            addSeries("Series C", [{x: 7, y: 7, size: 4}], {plot: "Plot 1", color: "blue"}).
+            render();
+
+    var series = new dojo.dnd.Source("dnd1"), noUpdate = false;
+    series.insertNodes(false, chart1.getSeriesOrder("Plot 1"));
+    dojo.connect(series, "onDropInternal", function(){
+        var newOrder = this.getAllNodes().map(function(node){
+                return node.innerHTML;
+            })
+        chart1.setSeriesOrder(newOrder);
+        noUpdate = true;
+        chart1.render();
+        noUpdate = false;
+    });
+    dojo.connect(chart1, "render", function(){
+        if(!noUpdate){
+            series.getAllNodes().orphan();
+            series.sync();
+            series.insertNodes(false, chart1.getSeriesOrder("Plot 1"));
+        }
+    });
+
+    dojo.forEach(["s1", "s2", "s3"], function(id, i){
+        dojo.query("button", id).forEach(function(btn){
+            if(btn.innerHTML == "Front"){
+                dojo.connect(btn, "onclick", function(){
+                    chart1.moveSeriesToFront("Series " + "ABCDEFG".charAt(i));
+                    chart1.render();
+                });
+            }else{
+                dojo.connect(btn, "onclick", function(){
+                    chart1.moveSeriesToBack("Series " + "ABCDEFG".charAt(i));
+                    chart1.render();
+                });
+            }
+        });
+    });
+};
+
+dojo.ready(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Testing series order</h1>
+<!--<p><button onclick="makeObjects();">Go</button></p>-->
+<p>Chart:</p>
+<div id="chart1" style="width: 200px; height: 200px;"></div>
+<div id="legend1"></div>
+<p id="s1">Series A: <button>Front</button> <button>Back</button></p>
+<p id="s2">Series B: <button>Front</button> <button>Back</button></p>
+<p id="s3">Series C: <button>Front</button> <button>Back</button></p>
+<p>Series (rearrange using drag-and-drop):</p>
+<div id="dnd1" class="container"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_sparklines.html b/dojox/charting/tests/test_sparklines.html
new file mode 100644
index 0000000..953383f
--- /dev/null
+++ b/dojox/charting/tests/test_sparklines.html
@@ -0,0 +1,203 @@
+<!DOCTYPE HTML>
+<html>
+	<head>
+	    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+		<title>Chart 2D -- Sparklines Edition</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+			.volume { color: #666666; }
+
+			.label { 
+				text-align: right;
+				line-height: 1.5em;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" 
+			djConfig="isDebug: false, parseOnLoad: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.charting.widget.Chart2D");
+			dojo.require("dojox.charting.widget.Sparkline");
+			dojo.require("dojox.charting.themes.Tufte");
+			dojo.require("dojox.data.HtmlStore");
+			dojo.require("dojox.data.CsvStore");
+			dojo.require("dojo.parser");
+		</script>
+
+	</head>
+	<body>
+		<h1>Chart 2D</h1>
+		<p>Sparkline-style charts using dojox.charting</p>
+		<p><em>This is a particularly brutal example with <strong>lots and lots</strong> of data. 
+			It may cause laggyness in lesser browsers.</em></p>
+		
+		<div dojoType="dojox.data.HtmlStore" dataId="tableExample" jsId="tableStore"></div>
+		<table id="tableExample" style="display: none;">
+			<thead>
+				<tr><th>value</th></tr>
+			</thead>
+			<tbody>
+				<tr><td>6.3</td></tr>
+				<tr><td>1.8</td></tr>
+				<tr><td>3  </td></tr>
+				<tr><td>0.5</td></tr>
+				<tr><td>4.4</td></tr>
+				<tr><td>2.7</td></tr>
+				<tr><td>2  </td></tr>
+			</tbody>
+		</table>
+
+		<table cellpadding="0" cellspacing="3" border="0">
+			<tr>
+				<td class="label">
+					Simple Sparkline:
+				</td>
+				<td>
+					<div dojoType="dojox.charting.widget.Chart2D" 
+						theme="dojox.charting.themes.Tufte" 
+						margins="{ l: 0, r: 0, t: 0, b: 0 }"
+						style="width: 100px; height: 15px;">
+						<div class="plot" name="default" type="Lines"></div>
+						<div class="series" name="Series A" store="tableStore" valueFn="Number(x)"></div>
+					</div>
+				</td>
+				<td>
+					7 arbitrary data points
+				</td>
+			</tr>
+			<tr>
+				<td class="label">
+					<a href="http://finance.google.com/finance?q=Google">Google </a> Closing Price & <span class="volume">Volume</span>:
+				</td>
+				<td>
+
+					<div dojoType="dojox.data.CsvStore" jsId="googStore" 
+						url="data/goog_prices.csv"></div>
+					<div dojoType="dojox.charting.widget.Chart2D" 
+						theme="dojox.charting.themes.Tufte" 
+						margins="{ l: 0, r: 0, t: 0, b: 0 }"
+						style="width: 100px; height: 15px;">
+						<div class="plot" name="default" type="Lines"></div>
+						<div class="series" 
+							name="Closing Price" 
+							plot="default"
+							store="googStore" 
+							count="Infinity"
+							field="Close"
+							sort="[{ attribute: 'Date', descending: false }]"
+							valueFn="Number(x)"></div>
+						<div class="plot" name="volume" type="Areas"></div>
+						<div class="series" 
+							name="Volume" 
+							plot="volume"
+							store="googStore" 
+							count="Infinity"
+							field="Volume"
+							sort="[{ attribute: 'Date', descending: false }]"
+							stroke="{ color: '#666666', width: 0 }"
+							fill="'#b3b3b3'"
+							valueFn="Number(x/100000)"></div>
+					</div>
+					
+				</td>
+				<td>
+					~1400 data points, all trading days since Jan '05
+				</td>
+			</tr>
+			<tr>
+				<td class="label">
+					<a href="http://finance.google.com/finance?q=Yahoo">Yahoo</a> Closing Price & <span class="volume">Volume</span>:
+				</td>
+				<td>
+
+					<div dojoType="dojox.data.CsvStore" jsId="yahooStore" 
+						url="data/yahoo_prices.csv"></div>
+					<div dojoType="dojox.charting.widget.Chart2D" 
+						theme="dojox.charting.themes.Tufte" 
+						margins="{ l: 0, r: 0, t: 0, b: 0 }"
+						style="width: 100px; height: 15px;">
+						<div class="plot" name="default" type="Lines"></div>
+						<div class="series" 
+							name="Closing Price" 
+							plot="default"
+							store="yahooStore" 
+							count="Infinity"
+							field="Close"
+							sort="[{ attribute: 'Date', descending: false }]"
+							valueFn="Number(x)"></div>
+						<div class="plot" name="volume" type="Areas"></div>
+						<div class="series" 
+							name="Volume" 
+							plot="volume"
+							store="yahooStore" 
+							count="Infinity"
+							field="Volume"
+							sort="[{ attribute: 'Date', descending: false }]"
+							stroke="{ color: '#666666', width: 0 }"
+							fill="'#b3b3b3'"
+							valueFn="Number(x/100000)"></div>
+					</div>
+					
+				</td>
+				<td>
+				</td>
+			</tr>
+			<tr>
+				<td class="label">
+					<a href="http://finance.google.com/finance?q=Microsoft">Microsoft</a> Closing Price & <span class="volume">Volume</span>:
+				</td>
+				<td>
+					<div dojoType="dojox.data.CsvStore" jsId="msftStore" 
+						url="data/msft_prices.csv"></div>
+					<div dojoType="dojox.charting.widget.Chart2D" 
+						theme="dojox.charting.themes.Tufte" 
+						margins="{ l: 0, r: 0, t: 0, b: 0 }"
+						style="width: 100px; height: 15px;">
+						<div class="plot" name="default" type="Lines"></div>
+						<div class="series" 
+							name="Closing Price" 
+							plot="default"
+							store="msftStore" 
+							count="Infinity"
+							field="Close"
+							sort="[{ attribute: 'Date', descending: false }]"
+							valueFn="Number(x)"></div>
+						<div class="plot" name="volume" type="Areas"></div>
+						<div class="series" 
+							name="Volume" 
+							plot="volume"
+							store="msftStore" 
+							count="Infinity"
+							field="Volume"
+							sort="[{ attribute: 'Date', descending: false }]"
+							stroke="{ color: '#666666', width: 0 }"
+							fill="'#b3b3b3'"
+							valueFn="Number(x/100000)"></div>
+					</div>
+					
+				</td>
+				<td>
+				</td>
+			</tr>
+			<tr>
+				<td class="label">
+					<a href="http://finance.google.com/finance?q=Microsoft">Microsoft</a> Closing Price:
+				</td>
+				<td>
+					<div dojoType="dojox.charting.widget.Sparkline" 
+						style="width: 100px; height: 15px;"
+						store="msftStore"
+						field="Close"
+						count="100"
+						sort="[{ attribute: 'Date', descending: false }]"
+						valueFn="Number(x)"
+					></div>
+				</td>
+				<td>
+					100 points using Sparkline widget
+				</td>
+			</tr>
+
+		</table>
+	</body>
+</html>
diff --git a/dojox/charting/tests/test_tension.html b/dojox/charting/tests/test_tension.html
new file mode 100644
index 0000000..10ecc14
--- /dev/null
+++ b/dojox/charting/tests/test_tension.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+    <title>Tension test.</title>
+    <style>
+        @import "../../../dojo/resources/dojo.css";
+        @import "../../../dijit/themes/tundra/tundra.css";
+        @import "../../../dijit/tests/css/dijitTests.css";
+    </style>
+    <style>
+        .dojoxLegendNode {border: 1px solid #ccc; margin: 5px 10px 5px 10px; padding: 3px}
+        .dojoxLegendText {vertical-align: text-top; padding-right: 10px}
+    </style>
+    <script src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script>
+        dojo.require("dojox.charting.Chart2D");
+        dojo.require("dojox.charting.widget.Legend");
+        
+        var data = [{x: 1, y: 1}, {x: 1, y: 2}, {x: 2, y: 2}, {x: 2, y: 1}];
+        
+        makeObjects = function(){
+            var theme = new dojox.charting.Theme({
+                    chart:    {fill: null}, // no background
+                    plotarea: {fill: null}, // no background
+                    colors: ["red", "green", "blue", "orange"]
+                });
+            var chart = new dojox.charting.Chart2D("test_chart").
+                    setTheme(theme).
+                    addAxis("x", {natural: true, min: 0, max: 3}).
+                    addAxis("y", {vertical: true, natural: true, min: 0, max: 3}).
+                    addPlot("S tension", {tension: "S"}).
+                    addSeries("\"S\" tension", data, {plot: "S tension"}).
+                    addPlot("x tension", {tension: "x"}).
+                    addSeries("\"x\" tension", data, {plot: "x tension"}).
+                    addPlot("X tension", {tension: "X"}).
+                    addSeries("\"X\" tension", data, {plot: "X tension"}).
+                    addPlot("no tension", {markers: true, tension: ""}).
+                    addSeries("No Tension", data, {plot: "no tension"}).
+                    render();
+            var legend = new dojox.charting.widget.Legend({chart: chart}, "test_legend");
+        };
+        
+        dojo.addOnLoad(makeObjects);
+    </script>
+</head>
+<body class="tundra">
+    <h1>Tension test.</h1>
+    <!--<p><button onclick="makeObjects();">Go</button></p>-->
+    <div id="test_chart" style="width: 400px; height: 400px;"></div>
+    <div id="test_legend"></div>
+    <p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_themes.html b/dojox/charting/tests/test_themes.html
new file mode 100644
index 0000000..a7baab0
--- /dev/null
+++ b/dojox/charting/tests/test_themes.html
@@ -0,0 +1,296 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="chrome=1"/>
+<title>Example Dojo Chart Types</title>
+<style>
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	#chartContainer {
+		position: relative;
+		height: 660px;
+	}
+	.chart {
+		position: absolute;
+		top:    0;
+		left:   0;
+		width:  300px;
+		height: 200px;
+	}
+	#lines, #area, #columns {
+		left: 320px;
+	}
+	#bubbles, #area, #pieLin {
+		top: 220px;
+	}
+	#pieLin, #pieFan, #ohlc {
+		left:  640px;
+	}
+	#candle, #columns, #ohlc {
+		top: 440px;
+	}
+
+</style>
+<script src="../../../dojo/dojo.js" djConfig="isDebug: false, gfxRenderer: 'svg,silverlight,vml,canvas'"></script>
+<script>
+	dojo.require("dojox.charting.Chart2D");
+
+	var charts = {}, backgroundImage, backgroundColor, color, lastThemeName = "";
+
+	function update(name){
+		// change the theme based on the select change.
+		var select = dojo.byId("themeChooser"),
+			usePageStyle = dojo.byId("pageStyleChooser").checked;
+
+		var test = false;
+		if(name){
+			//	make sure it's in the list first.
+			for(var i=0, l=select.options.length; i<l; i++){
+				if(select.options[i].value == name){
+					select.options[i].selected = true;
+					test = true;
+					break;
+				}
+			}
+		}
+
+		if(!test){
+			name = select.options[select.selectedIndex].value;
+		}
+
+		dojo.require("dojox.charting.themes." + name);
+
+		var theme = dojo.getObject('dojox.charting.themes.' + name);
+		var chartStyle = theme.chart;
+
+		// set the suggested page style
+		if(usePageStyle && chartStyle.pageStyle){
+			dojo.style(dojo.body(), chartStyle.pageStyle);
+		}else{
+			dojo.style(dojo.body(), {
+				backgroundColor: backgroundColor,
+				backgroundImage: backgroundImage,
+				color: color
+			});
+		}
+		// set the theme
+		if(lastThemeName != name){
+			lastThemeName = name;
+			if(theme){
+				for(var chartName in charts){
+					charts[chartName].setTheme(theme).render();
+				}
+			}
+		}
+	}
+
+	function init(){
+		// retrieve initial values for fg/bg
+		backgroundImage = dojo.style(dojo.body(), "backgroundImage");
+		backgroundColor = dojo.style(dojo.body(), "backgroundColor");
+		color = dojo.style(dojo.body(), "color");
+
+		charts.bars = new dojox.charting.Chart2D("bars").
+			addAxis("y", {fixLower: "minor", fixUpper: "minor", natural: true}).
+			addAxis("x", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true}).
+			addPlot("default", {type: "ClusteredBars", gap: 5}).
+			addSeries("Series A", [0.53, 0.51]).
+			addSeries("Series B", [0.84, 0.79]).
+			addSeries("Series C", [0.68, 0.95]).
+			addSeries("Series D", [0.77, 0.66]);
+
+		charts.columns = new dojox.charting.Chart2D("columns").
+			addAxis("x", {fixLower: "minor", fixUpper: "minor", natural: true}).
+			addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true}).
+			addPlot("default", {type: "ClusteredColumns", gap: 5}).
+			addSeries("Series A", [0.53, 0.51]).
+			addSeries("Series B", [0.84, 0.79]).
+			addSeries("Series C", [0.68, 0.95]).
+			addSeries("Series D", [0.77, 0.66]);
+
+		charts.lines = new dojox.charting.Chart2D("lines").
+			addAxis("x", {min: 0, max: 6, fixLower: "minor", fixUpper: "minor", natural: true}).
+			addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true, max: 1}).
+			addPlot("default", {type: "Default", lines: true, markers: true, tension: "X"}).
+			addSeries("Series A", [{x: 0.5, y: 0.2}, {x: 1.5, y: 0.4}, {x: 2.0, y: 0.1}, {x: 5.0, y: 0.9}]).
+			addSeries("Series B", [{x: 0.3, y: 0.6}, {x: 3.0, y: 0.5}, {x: 4.0, y: 0.9}, {x: 5.5, y: 0.7}]).
+			addSeries("Series C", [{x: 0.8, y: 0.8}, {x: 3.4, y: 0.2}, {x: 5.3, y: 0.3}]).
+			addSeries("Series D", [{x: 0.6, y: 0.9}, {x: 3.2, y: 0.8}, {x: 5.0, y: 0.1}]);
+
+		charts.pieFan = new dojox.charting.Chart2D("pieFan").
+			addPlot("default", {type: "Pie", radius: 60, labelOffset: -20, radGrad: dojox.gfx.renderer == "vml" ? "fan" : "native"}).
+			addSeries("Series A", [0.35, 0.25, 0.42, 0.53, 0.69]);
+
+		charts.bubbles = new dojox.charting.Chart2D("bubbles").
+			addAxis("x", {min: 0, max: 6, fixLower: "minor", fixUpper: "minor", natural: true}).
+			addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", includeZero: true}).
+			addPlot("default", {type: "Bubble"}).
+			addSeries("Series A", [{x: 0.5, y: 5.0, size: 1.4}, {x: 1.5, y: 1.5, size: 4.5}, {x: 2.0, y: 9.0, size: 1.5}, {x: 5.0, y: 0.3, size: 0.8}]).
+			addSeries("Series B", [{x: 0.3, y: 8.0, size: 2.5}, {x: 4.0, y: 6.0, size: 2.1}, {x: 5.5, y: 2.0, size: 3.2}]).
+			addSeries("Series C", [{x: 2.0, y: 5.5, size: 2.5}, {x: 3.5, y: 2.5, size: 3.5}, {x: 5.2, y: 7.0, size: 3.0}]).
+			addSeries("Series D", [{x: 3.2, y: 8.0, size: 2.0}]);
+
+		charts.area = new dojox.charting.Chart2D("area").
+			addAxis("x", {fixLower: "major", fixUpper: "major"}).
+			addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", min: 0}).
+			addPlot("default", {type: "StackedAreas", tension: "X"}).
+			addSeries("Series A", [-2, 1.1, 1.2, 1.3, 1.4, 1.5, -1.6]).
+			addSeries("Series B", [1, 1.6, 1.3, 1.4, 1.1, 1.5, 1.1]).
+			addSeries("Series C", [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6]);
+
+		charts.pieLin = new dojox.charting.Chart2D("pieLin").
+			addPlot("default", {type: "Pie", radius: 60, labelOffset: -20, radGrad: "linear"}).
+			addSeries("Series A", [0.35, 0.25, 0.42, 0.53, 0.69]);
+
+		charts.candle = new dojox.charting.Chart2D("candle").
+			addPlot("default", {type: "Candlesticks", gap: 1}).
+			addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true}).
+			addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+			addSeries("Series A", [
+					{ open: 20, close: 16, high: 22, low: 8 },
+					{ open: 16, close: 22, high: 26, low: 6, mid: 18 },
+					{ open: 22, close: 18, high: 22, low: 11, mid: 21 },
+					{ open: 18, close: 29, high: 32, low: 14, mid: 27 },
+					{ open: 29, close: 24, high: 29, low: 13, mid: 27 },
+					{ open: 24, close: 8, high: 24, low: 5 },
+					{ open: 8, close: 16, high: 22, low: 2 },
+					{ open: 16, close: 12, high: 19, low: 7 },
+					{ open: 12, close: 20, high: 22, low: 8 },
+					{ open: 20, close: 16, high: 22, low: 8 },
+					{ open: 16, close: 22, high: 26, low: 6, mid: 18 },
+					{ open: 22, close: 18, high: 22, low: 11, mid: 21 },
+					{ open: 18, close: 29, high: 32, low: 14, mid: 27 },
+					{ open: 29, close: 24, high: 29, low: 13, mid: 27 },
+					{ open: 24, close: 8, high: 24, low: 5 },
+					{ open: 8, close: 16, high: 22, low: 2 },
+					{ open: 16, close: 12, high: 19, low: 7 },
+					{ open: 12, close: 20, high: 22, low: 8 },
+					{ open: 20, close: 16, high: 22, low: 8 },
+					{ open: 16, close: 22, high: 26, low: 6 },
+					{ open: 22, close: 18, high: 22, low: 11 },
+					{ open: 18, close: 29, high: 32, low: 14 },
+					{ open: 29, close: 24, high: 29, low: 13 },
+					{ open: 24, close: 8, high: 24, low: 5 },
+					{ open: 8, close: 16, high: 22, low: 2 },
+					{ open: 16, close: 12, high: 19, low: 7 },
+					{ open: 12, close: 20, high: 22, low: 8 },
+					{ open: 20, close: 16, high: 22, low: 8 }]);
+		charts.ohlc = new dojox.charting.Chart2D("ohlc").
+			addPlot("default", {type: "OHLC", gap: 1}).
+			addAxis("x", {fixLower: "major", fixUpper: "major", includeZero: true}).
+			addAxis("y", {vertical: true, fixLower: "major", fixUpper: "major", natural: true}).
+			addSeries("Series A", [
+					{ open: 20, close: 16, high: 22, low: 8 },
+					{ open: 16, close: 22, high: 26, low: 6 },
+					{ open: 22, close: 18, high: 22, low: 11 },
+					{ open: 18, close: 29, high: 32, low: 14 },
+					{ open: 29, close: 24, high: 29, low: 13 },
+					{ open: 24, close: 8, high: 24, low: 5 },
+					{ open: 8, close: 16, high: 22, low: 2 },
+					{ open: 16, close: 12, high: 19, low: 7 },
+					{ open: 12, close: 20, high: 22, low: 8 },
+					{ open: 20, close: 16, high: 22, low: 8 },
+					{ open: 16, close: 22, high: 26, low: 6 },
+					{ open: 22, close: 18, high: 22, low: 11 },
+					{ open: 18, close: 29, high: 32, low: 14 },
+					{ open: 29, close: 24, high: 29, low: 13 },
+					{ open: 24, close: 8, high: 24, low: 5 },
+					{ open: 8, close: 16, high: 22, low: 2 },
+					{ open: 16, close: 12, high: 19, low: 7 },
+					{ open: 12, close: 20, high: 22, low: 8 },
+					{ open: 20, close: 16, high: 22, low: 8 },
+					{ open: 16, close: 22, high: 26, low: 6 },
+					{ open: 22, close: 18, high: 22, low: 11 },
+					{ open: 18, close: 29, high: 32, low: 14 },
+					{ open: 29, close: 24, high: 29, low: 13 },
+					{ open: 24, close: 8, high: 24, low: 5 },
+					{ open: 8, close: 16, high: 22, low: 2 },
+					{ open: 16, close: 12, high: 19, low: 7 },
+					{ open: 12, close: 20, high: 22, low: 8 },
+					{ open: 20, close: 16, high: 22, low: 8 }]);
+		var name;
+		if(window.location.search.indexOf("?")>-1){
+			name = window.location.search.substring(1);
+			dojo.create("span", {
+				style: "display: inline-block; margin-left: 1em;",
+				innerHTML: '<a href="theme_preview.html">Back to the Theme Previewer »»</a>'
+			}, dojo.query("p.controls")[0]);
+		}
+
+		update(name);
+
+		dojo.connect(dojo.byId("themeChooser"), "onchange", update);
+		dojo.connect(dojo.byId("pageStyleChooser"), "onclick", update);
+	}
+	dojo.addOnLoad(init);
+</script>
+</head>
+<body>
+	<h1>Example Dojo Chart Types</h1>
+	<p>Choose a theme from the list below, a theme will be loaded dynamically, and the charts will be rendered using it.</p>
+	<p class="controls"><label for="themeChooser">Available themes: </label>
+		<select id="themeChooser">
+			<optgroup label="Gradients">
+				<option value="Julie" selected="selected">Julie</option>
+				<option value="ThreeD">ThreeD</option>
+				<option value="Chris">Chris</option>
+				<option value="Tom">Tom</option>
+				<option value="PrimaryColors">PrimaryColors</option>
+				<option value="Electric">Electric</option>
+				<option value="Charged">Charged</option>
+				<option value="Renkoo">Renkoo</option>
+			</optgroup>
+			<optgroup label="Classic">
+				<option value="Adobebricks">Adobebricks</option>
+				<option value="Algae">Algae</option>
+				<option value="Bahamation">Bahamation</option>
+				<option value="BlueDusk">BlueDusk</option>
+				<option value="CubanShirts">CubanShirts</option>
+				<option value="Desert">Desert</option>
+				<option value="Distinctive">Distinctive</option>
+				<option value="Dollar">Dollar</option>
+				<option value="Grasshopper">Grasshopper</option>
+				<option value="Grasslands">Grasslands</option>
+				<option value="GreySkies">GreySkies</option>
+				<option value="Harmony">Harmony</option>
+				<option value="IndigoNation">IndigoNation</option>
+				<option value="Ireland">Ireland</option>
+				<option value="MiamiNice">MiamiNice</option>
+				<option value="Midwest">Midwest</option>
+				<option value="Minty">Minty</option>
+				<option value="PurpleRain">PurpleRain</option>
+				<option value="RoyalPurples">RoyalPurples</option>
+				<option value="SageToLime">SageToLime</option>
+				<option value="Shrooms">Shrooms</option>
+				<option value="Tufte">Tufte</option>
+				<option value="WatersEdge">WatersEdge</option>
+				<option value="Wetland">Wetland</option>
+			</optgroup>
+			<optgroup label="PlotKit">
+				<option value="PlotKit.blue">PlotKit.blue</option>
+				<option value="PlotKit.cyan">PlotKit.cyan</option>
+				<option value="PlotKit.green">PlotKit.green</option>
+				<option value="PlotKit.orange">PlotKit.orange</option>
+				<option value="PlotKit.purple">PlotKit.purple</option>
+				<option value="PlotKit.red">PlotKit.red</option>
+			</optgroup>
+		</select>
+		   
+		<input id="pageStyleChooser" type="checkbox" checked="checked" value="">
+		<label for="pageStyleChooser"> use suggested page style</label>
+	</p>
+	<div id="chartContainer">
+		<div class="chart" id="bars"></div>
+		<div class="chart" id="lines"></div>
+		<div class="chart" id="pieFan"></div>
+		<div class="chart" id="bubbles"></div>
+		<div class="chart" id="area"></div>
+		<div class="chart" id="pieLin"></div>
+		<div class="chart" id="columns"></div>
+		<div class="chart" id="candle"></div>
+		<div class="chart" id="ohlc"></div>
+		<div class="chart" id="scatter"></div>
+	</div>
+</body>
+</html>
diff --git a/dojox/charting/tests/test_widget2d.html b/dojox/charting/tests/test_widget2d.html
new file mode 100644
index 0000000..9a78f15
--- /dev/null
+++ b/dojox/charting/tests/test_widget2d.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML>
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+	    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+		<title>Chart 2D</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+		</style>
+		<!-- required for Tooltip: a default dijit theme: -->
+		<link rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+		<style>
+			.dojoxLegendNode {border: 1px solid #ccc; margin: 5px 10px 5px 10px; padding: 3px}
+			.dojoxLegendText {vertical-align: text-top; padding-right: 10px}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" 
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!--
+		<script type="text/javascript" src="../../lang/functional.js"></script>
+		<script type="text/javascript" src="../Theme.js"></script>
+		<script type="text/javascript" src="../scaler/linear.js"></script>
+		<script type="text/javascript" src="../action2d/Tooltip.js"></script>
+		<script type="text/javascript" src="../Chart2D.js"></script>
+		<script type="text/javascript" src="../widget/Chart2D.js"></script>
+		<script type="text/javascript" src="../widget/Sparkline.js"></script>
+		<script type="text/javascript" src="../widget/Legend.js"></script>
+		-->
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit");
+			dojo.require("dojox.charting.widget.Chart2D");
+			dojo.require("dojox.charting.widget.Sparkline");
+			dojo.require("dojox.charting.widget.Legend");
+			dojo.require("dojox.charting.themes.PlotKit.orange");
+			dojo.require("dojox.charting.themes.PlotKit.blue");
+			dojo.require("dojox.charting.themes.PlotKit.green");
+			dojo.require("dojox.data.HtmlStore");
+			
+			seriesB = [2.6, 1.8, 2, 1, 1.4, 0.7, 2];
+			
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+		</script>
+
+	</head>
+	<body class="tundra">
+		<h1>Chart 2D</h1>
+		<p>Examples of charts using widgets.</p>
+		<div dojoType="dojox.data.HtmlStore" dataId="tableExample" jsId="tableStore"></div>
+		<table id="tableExample" style="display: none;">
+			<thead>
+				<tr><th>value</th></tr>
+			</thead>
+			<tbody>
+				<tr><td>6.3</td></tr>
+				<tr><td>1.8</td></tr>
+				<tr><td>3  </td></tr>
+				<tr><td>0.5</td></tr>
+				<tr><td>4.4</td></tr>
+				<tr><td>2.7</td></tr>
+				<tr><td>2  </td></tr>
+			</tbody>
+		</table>
+		<table border="0" cellspacing="30">
+			<tr>
+				<td>
+					<div dojoType="dojox.charting.widget.Chart2D" id="chart1" style="width: 300px; height: 300px;">
+						<div class="axis" name="x" font="italic normal normal 8pt Tahoma"></div>
+						<div class="axis" name="y" vertical="true" fixUpper="major" includeZero="true" 
+							font="italic normal normal 8pt Tahoma"></div>
+						<div class="plot" name="default" type="Areas"></div>
+						<div class="plot" name="grid" type="Grid"></div>
+						<div class="series" name="Run A" data="1, 2, 0.5, 1.5, 1, 2.8, 0.4"></div>
+						<div class="series" name="Run B" array="seriesB" legend="<em>Custom</em> legend"></div>
+						<div class="series" name="Run C" store="tableStore" valueFn="Number(x)"></div>
+					</div>
+					<div dojoType="dojox.charting.widget.Legend" chartRef="chart1"></div>
+				</td>
+				<td>
+					<div dojoType="dojox.charting.widget.Chart2D" id="chart2" theme="dojox.charting.themes.PlotKit.orange" 
+							fill="'lightgrey'" style="width: 300px; height: 300px;">
+						<div class="axis" name="x" font="italic normal bold 10pt Tahoma"></div>
+						<div class="axis" name="y" vertical="true" fixUpper="major" includeZero="true" 
+							font="italic normal bold 10pt Tahoma"></div>
+						<div class="plot" name="default" type="Areas"></div>
+						<div class="plot" name="grid" type="Grid"></div>
+						<div class="series" name="Series A" data="1, 2, 0.5, 1.5, 1, 2.8, 0.4"></div>
+						<div class="series" name="Series B" array="seriesB"></div>
+						<div class="series" name="Series C" store="tableStore" valueFn="Number(x)" stroke="'#666666'" fill="'#b3b3b3'"></div>
+					</div>
+					<div dojoType="dojox.charting.widget.Legend" chartRef="chart2"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<div dojoType="dojox.charting.widget.Chart2D" id="chart3" theme="dojox.charting.themes.PlotKit.blue"
+							 style="width: 300px; height: 300px;">
+						<div class="plot" name="default" type="Pie" radius="100" fontColor="white"></div>
+						<div class="series" name="Series B" array="seriesB"></div>
+						<div class="action" type="Tooltip"></div>
+					</div>
+				</td>
+				<td>
+					<div dojoType="dojox.charting.widget.Chart2D" id="chart4" theme="dojox.charting.themes.PlotKit.green"
+							 style="width: 300px; height: 300px;">
+						<div class="plot" name="default" type="Pie" radius="100" fontColor="black" labelOffset="-20"></div>
+						<div class="series" name="Series C" store="tableStore" valueFn="Number(x)"></div>
+						<div class="action" type="Tooltip"></div>
+						<div class="action" type="MoveSlice" shift="2"></div>
+					</div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<div dojoType="dojox.charting.widget.Sparkline"></div>
+				</td>
+				<td>
+				</td>
+			</tr>
+		</table>
+		<p>That's all Folks!</p>
+	</body>
+</html>
diff --git a/dojox/charting/tests/test_win2d.html b/dojox/charting/tests/test_win2d.html
new file mode 100644
index 0000000..e58f7dd
--- /dev/null
+++ b/dojox/charting/tests/test_win2d.html
@@ -0,0 +1,210 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
+<title>Scaling, scrolling, and panning.</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<!--
+The next line should include Microsoft's Silverligth.js, if you plan to use the silverlight backend
+<script type="text/javascript" src="Silverlight.js"></script>
+-->
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+<script type="text/javascript" src="../Theme.js"></script>
+<script type="text/javascript" src="../scaler/linear.js"></script>
+<script type="text/javascript" src="../axis2d/Default.js"></script>
+<script type="text/javascript" src="../plot2d/Default.js"></script>
+<script type="text/javascript" src="../plot2d/Grid.js"></script>
+<script type="text/javascript" src="../Chart2D.js"></script>
+<script type="text/javascript" src="../../lang/functional/object.js"></script>
+
+<script type="text/javascript">
+
+dojo.require("dijit.form.HorizontalSlider");
+dojo.require("dijit.form.HorizontalRule");
+dojo.require("dijit.form.HorizontalRuleLabels");
+dojo.require("dojo.parser"); // scan page for widgets
+
+dojo.require("dojox.charting.Chart2D");
+dojo.require("dojox.charting.themes.PlotKit.orange");
+
+dojo.require("dojox.lang.functional.object");
+
+var df = dojox.lang.functional;
+var chart, moveable, scaleX = 1, scaleY = 1, offsetX = 0, offsetY = 0;
+
+var reflect = function(){
+	df.forIn(chart.axes, function(axis){
+		var scale  = axis.getWindowScale(),
+			offset = Math.round(axis.getWindowOffset() * axis.getScaler().bounds.scale);
+		if(axis.vertical){
+			scaleY  = scale;
+			offsetY = offset;
+		}else{
+			scaleX  = scale;
+			offsetX = offset;
+		}
+	});
+	setTimeout(function(){
+		dijit.byId("scaleXSlider").setValue(scaleX);
+		dijit.byId("offsetXSlider").setValue(offsetX);
+		dijit.byId("scaleYSlider").setValue(scaleY);
+		dijit.byId("offsetYSlider").setValue(offsetY);
+	}, 25);
+};
+
+var update = function(){
+	chart.setWindow(scaleX, scaleY, offsetX, offsetY, {duration: 1500}).render();
+	reflect();
+};
+
+var scaleXEvent = function(value){
+	scaleX = value;
+	dojo.byId("scaleXValue").innerHTML = value;
+	update();
+};
+
+var scaleYEvent = function(value){
+	scaleY = value;
+	dojo.byId("scaleYValue").innerHTML = value;
+	update();
+};
+
+var offsetXEvent = function(value){
+	offsetX = value;
+	dojo.byId("offsetXValue").innerHTML = value;
+	update();
+};
+
+var offsetYEvent = function(value){
+	offsetY = value;
+	dojo.byId("offsetYValue").innerHTML = value;
+	update();
+};
+
+var _init = null;
+var onMouseDown = function(e){
+	_init = {x: e.clientX, y: e.clientY, ox: offsetX, oy: offsetY};
+	dojo.stopEvent(e);
+};
+
+var onMouseUp = function(e){
+	if(_init){
+		_init = null;
+		reflect();
+		dojo.stopEvent(e);
+	}
+};
+
+var onMouseMove = function(e){
+	if(_init){
+		var dx = e.clientX - _init.x,
+			dy = e.clientY - _init.y;
+		offsetX = _init.ox - dx;
+		offsetY = _init.oy + dy;
+		chart.setWindow(scaleX, scaleY, offsetX, offsetY).render();
+		dojo.stopEvent(e);
+	}
+};
+
+makeObjects = function(){
+	chart = new dojox.charting.Chart2D("test");
+	chart.setTheme(dojox.charting.themes.PlotKit.orange);
+	chart.addAxis("x", {fixLower: "minor", natural: true, stroke: "grey",
+		majorTick: {stroke: "black", length: 4}, minorTick: {stroke: "gray", length: 2}});
+	chart.addAxis("y", {vertical: true, min: 0, max: 30, majorTickStep: 5, minorTickStep: 1, stroke: "grey",
+		majorTick: {stroke: "black", length: 4}, minorTick: {stroke: "gray", length: 2}});
+	chart.addPlot("default", {type: "Areas", animate: {duration: 1800}});
+	chart.addSeries("Series A", [0, 25, 5, 20, 10, 15, 5, 20, 0, 25]);
+	chart.addAxis("x2", {fixLower: "minor", natural: true, leftBottom: false, stroke: "grey",
+		majorTick: {stroke: "black", length: 4}, minorTick: {stroke: "gray", length: 2}});
+	chart.addAxis("y2", {vertical: true, min: 0, max: 20, leftBottom: false, stroke: "grey",
+		majorTick: {stroke: "black", length: 4}, minorTick: {stroke: "gray", length: 2}});
+	chart.addPlot("plot2", {type: "Areas", hAxis: "x2", vAxis: "y2", animate: {duration: 1800}});
+	chart.addSeries("Series B", [15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15], {plot: "plot2"});
+	chart.addPlot("grid", {type: "Grid", hMinorLines: true});
+	chart.render();
+	
+    dojo.connect(dijit.byId("scaleXSlider"), "onChange", scaleXEvent);
+    dojo.connect(dijit.byId("scaleYSlider"), "onChange", scaleYEvent);
+    dojo.connect(dijit.byId("offsetXSlider"), "onChange", offsetXEvent);
+    dojo.connect(dijit.byId("offsetYSlider"), "onChange", offsetYEvent);
+
+    dojo.connect(dojo.byId("test"), "onmousedown", onMouseDown);
+    dojo.connect(dojo.byId("test"), "onmousemove", onMouseMove);
+    dojo.connect(dojo.byId("test"), "onmouseup",   onMouseUp);
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body class="tundra">
+<h1>Scaling, scrolling, and panning.</h1>
+<!--<p><button onclick="makeObjects();">Go</button></p>-->
+<p>UI explained:</p>
+<ul>
+	<li>Use Scale X and Scale Y to zoom in the chart. You can scale the chart anisotropically.</li>
+	<li>Use Offset X and Offset Y to move the origin of the chart.</li>
+	<li>You cannot move the chart outside its boundaries.
+		<ul>
+			<li>Example: if both scale factors are 1, you cannot move the origin — you should zoom in first.</li>
+		</ul>
+	</li>
+	<li>After applying scale/offset to the chart, sliders' positions change to reflect actual values.</li>
+	<li>When you zoomed in, you can grab chart with mouse and move around (pan).
+		<ul>
+			<li>Warning: can be slow on some browsers.</li>
+		</ul>
+	</li>
+</ul>
+<table>
+	<tr><td align="center" class="pad">Scale X (<span id="scaleXValue">1</span>)</td></tr>
+	<tr><td>
+		<div id="scaleXSlider" dojoType="dijit.form.HorizontalSlider" 
+				value="1" minimum="1" maximum="10" discreteValues="10" showButtons="false"
+				style="width: 600px;">
+			<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="10" style="height:5px;"></div>
+			<div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" minimum="1" maximum="10" count="10"
+				constraints="{pattern: '##'}" style="height:1.2em;font-size:75%;color:gray;"></div>
+		</div>
+	</td></tr>
+	<tr><td align="center" class="pad">Scale Y (<span id="scaleYValue">1</span>)</td></tr>
+	<tr><td>
+		<div id="scaleYSlider" dojoType="dijit.form.HorizontalSlider" 
+				value="1" minimum="1" maximum="10" discreteValues="10" showButtons="false"
+				style="width: 600px;">
+			<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="10" style="height:5px;"></div>
+			<div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" minimum="1" maximum="10" count="10"
+				constraints="{pattern: '##'}" style="height:1.2em;font-size:75%;color:gray;"></div>
+		</div>
+	</td></tr>
+	<tr><td align="center" class="pad">Offset X (<span id="offsetXValue">0</span>)</td></tr>
+	<tr><td>
+		<div id="offsetXSlider" dojoType="dijit.form.HorizontalSlider" 
+				value="1" minimum="0" maximum="1000" discreteValues="1001" showButtons="false"
+				style="width: 600px;">
+			<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="11" style="height:5px;"></div>
+			<div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" minimum="0" maximum="1000" count="11"
+				constraints="{pattern: '####'}" style="height:1.2em;font-size:75%;color:gray;"></div>
+		</div>
+	</td></tr>
+	<tr><td align="center" class="pad">Offset Y (<span id="offsetYValue">0</span>)</td></tr>
+	<tr><td>
+		<div id="offsetYSlider" dojoType="dijit.form.HorizontalSlider" 
+				value="1" minimum="0" maximum="1000" discreteValues="1001" showButtons="false"
+				style="width: 600px;">
+			<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="11" style="height:5px;"></div>
+			<div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" minimum="0" maximum="1000" count="11"
+				constraints="{pattern: '####'}" style="height:1.2em;font-size:75%;color:gray;"></div>
+		</div>
+	</td></tr>
+</table>
+<div id="test" style="width: 500px; height: 300px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/charting/tests/theme_preview.html b/dojox/charting/tests/theme_preview.html
new file mode 100644
index 0000000..93afd0c
--- /dev/null
+++ b/dojox/charting/tests/theme_preview.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<meta http-equiv="X-UA-Compatible" content="chrome=1"/> 
+		<title>DojoX Charting Theme Previewer</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			body {
+				padding: 1.5em;
+			}
+			div.container {
+				position: relative;
+				width: 180px;
+				height: 200px;
+				float: left;
+				border: 1px solid #ccc;
+				margin: 12px;
+			}
+			div.container div.chart {
+				width: 180px;
+				height: 180px;
+			}
+			div.container div.title {
+				position: absolute;
+				bottom: 4px;
+				font-size: 11px;
+				width: 180px;
+				text-align: center;
+			}
+			div.container div.title a { text-decoration: none; }
+			div.container div.title a:hover { text-decoration: underline; }
+		</style>
+<script src="../../../dojo/dojo.js" djConfig="isDebug: false, gfxRenderer: 'svg,silverlight,vml,canvas'"></script>
+<script type="text/javascript">
+	dojo.require("dojox.charting.Chart2D");
+
+	var themes = [
+		"Julie", "ThreeD", "Chris", "Tom", "PrimaryColors", "Electric", "Charged", "Renkoo",
+		"Adobebricks", "Algae", "Bahamation", "BlueDusk", "CubanShirts", "Desert", "Distinctive", "Dollar",
+		"Grasshopper", "Grasslands", "GreySkies", "Harmony", "IndigoNation", "Ireland", "MiamiNice",
+		"Minty", "PurpleRain", "RoyalPurples", "SageToLime", "Shrooms", "Tufte", "WatersEdge", "Wetland",
+		"PlotKit.blue", "PlotKit.cyan", "PlotKit.green", "PlotKit.orange", "PlotKit.purple", "PlotKit.red"
+	];
+
+	dojo.forEach(themes, function(theme){ dojo.require("dojox.charting.themes." + theme); })
+
+	dojo.ready(function(){
+		dojo.forEach(themes, function(theme){
+			var container = dojo.create("div", { className: "container" }, "main");
+			var chart = dojo.create("div", { className: "chart" }, container);
+			var title = dojo.create("div", { 
+				className: "title", 
+				innerHTML: 'See more of "<a href="test_themes.html?' + theme + '">' + theme + '</a>"' 
+			}, container);
+			var c = new dojox.charting.Chart2D(chart).
+				setTheme(dojo.getObject("dojox.charting.themes." + theme)).
+				addPlot("default", {type: "Pie", radius: 60, labelOffset: -20, radGrad: dojox.gfx.renderer == "vml" ? "fan" : "native"}).
+				addSeries("Series A", [0.35, 0.25, 0.42, 0.53, 0.69]).
+				render();
+		});
+	});
+</script>
+</head>
+<body>
+	<h1>DojoX Charting Theme Preview</h1>
+	<div id="main"></div>
+</body>
+</html>
diff --git a/dojox/charting/themes/Adobebricks.js b/dojox/charting/themes/Adobebricks.js
index 010b4ec..a0b7088 100644
--- a/dojox/charting/themes/Adobebricks.js
+++ b/dojox/charting/themes/Adobebricks.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Adobebricks"]){
-dojo._hasResource["dojox.charting.themes.Adobebricks"]=true;
 dojo.provide("dojox.charting.themes.Adobebricks");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Adobebricks=new _1.Theme({colors:["#7f2518","#3e170c","#cc3927","#651f0e","#8c271c"]});
+	var dxc=dojox.charting;
+	dxc.themes.Adobebricks=new dxc.Theme({
+		colors: [
+			"#7f2518",
+			"#3e170c",
+			"#cc3927",
+			"#651f0e",
+			"#8c271c"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Algae.js b/dojox/charting/themes/Algae.js
index 2ff4db2..4b6c8fe 100644
--- a/dojox/charting/themes/Algae.js
+++ b/dojox/charting/themes/Algae.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Algae"]){
-dojo._hasResource["dojox.charting.themes.Algae"]=true;
 dojo.provide("dojox.charting.themes.Algae");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Algae=new _1.Theme({colors:["#57808f","#506885","#4f7878","#558f7f","#508567"]});
+	var dxc=dojox.charting;
+	dxc.themes.Algae=new dxc.Theme({
+		colors: [
+			"#57808f",
+			"#506885",
+			"#4f7878",
+			"#558f7f",
+			"#508567"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Bahamation.js b/dojox/charting/themes/Bahamation.js
index 9e5e497..5a00ccb 100644
--- a/dojox/charting/themes/Bahamation.js
+++ b/dojox/charting/themes/Bahamation.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Bahamation"]){
-dojo._hasResource["dojox.charting.themes.Bahamation"]=true;
 dojo.provide("dojox.charting.themes.Bahamation");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Bahamation=new _1.Theme({colors:["#3f9998","#3fc0c3","#70c058","#ef446f","#c663a6"]});
+	var dxc=dojox.charting;
+	dxc.themes.Bahamation=new dxc.Theme({
+		colors: [
+			"#3f9998",
+			"#3fc0c3",
+			"#70c058",
+			"#ef446f",
+			"#c663a6"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/BlueDusk.js b/dojox/charting/themes/BlueDusk.js
index 86bf3aa..075a4ac 100644
--- a/dojox/charting/themes/BlueDusk.js
+++ b/dojox/charting/themes/BlueDusk.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.BlueDusk"]){
-dojo._hasResource["dojox.charting.themes.BlueDusk"]=true;
 dojo.provide("dojox.charting.themes.BlueDusk");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.BlueDusk=new _1.Theme({colors:["#292e76","#3e56a6","#10143f","#33449c","#798dcd"]});
+	var dxc=dojox.charting;
+	dxc.themes.BlueDusk=new dxc.Theme({
+		colors: [
+			"#292e76",
+			"#3e56a6",
+			"#10143f",
+			"#33449c",
+			"#798dcd"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Charged.js b/dojox/charting/themes/Charged.js
new file mode 100644
index 0000000..b213ff2
--- /dev/null
+++ b/dojox/charting/themes/Charged.js
@@ -0,0 +1,91 @@
+dojo.provide("dojox.charting.themes.Charged");
+
+dojo.require("dojox.gfx.gradutils");
+dojo.require("dojox.charting.Theme");
+
+// created by Tom Trenka
+
+(function(){
+	var dc = dojox.charting, themes = dc.themes, Theme = dc.Theme, g = Theme.generateGradient,
+		defaultFill = {type: "linear", space: "shape", x1: 0, y1: 0, x2: 0, y2: 75};
+	
+	themes.Charged = new dc.Theme({
+		chart: {
+			fill: "#ededdf",
+			pageStyle: {backgroundColor: "#ededdf", backgroundImage: "none", color: "inherit"}
+		},
+		plotarea: {
+			fill: "transparent"
+		},
+		axis:{
+			stroke:	{ // the axis itself
+				color: "#808078",
+				width: 1
+			},
+			tick: {	// used as a foundation for all ticks
+				color:     "#b3b3a8",
+				position:  "center",
+				font:      "normal normal normal 7pt Helvetica, Arial, sans-serif",	// labels on axis
+				fontColor: "#808078"								// color of labels
+			}
+		},
+		series: {
+			stroke:  {width: 2, color: "#595954"},
+			outline: null,
+			font: "normal normal normal 8pt Helvetica, Arial, sans-serif",
+			fontColor: "#808078"
+		},
+		marker: {
+			stroke:  {width: 3, color: "#595954"},
+			outline: null,
+			font: "normal normal normal 8pt Helvetica, Arial, sans-serif",
+			fontColor: "#808078"
+		},
+		seriesThemes: [
+			{fill: g(defaultFill, "#004cbf", "#06f")},
+			{fill: g(defaultFill, "#bf004c", "#f06")},	
+			{fill: g(defaultFill, "#43bf00", "#6f0")},	
+			{fill: g(defaultFill, "#7300bf", "#90f")},	
+			{fill: g(defaultFill, "#bf7300", "#f90")},	
+			{fill: g(defaultFill, "#00bf73", "#0f9")}	
+		],
+		markerThemes: [
+			{fill: "#06f", stroke: {color: "#06f"}},	
+			{fill: "#f06", stroke: {color: "#f06"}},
+			{fill: "#6f0", stroke: {color: "#6f0"}},	
+			{fill: "#90f", stroke: {color: "#90f"}},	
+			{fill: "#f90", stroke: {color: "#f90"}},	
+			{fill: "#0f9", stroke: {color: "#0f9"}}	
+		]
+	});
+	
+	themes.Charged.next = function(elementType, mixin, doPost){
+		var isLine = elementType == "line";
+		if(isLine || elementType == "area"){
+			// custom processing for lines: substitute colors
+			var s = this.seriesThemes[this._current % this.seriesThemes.length];
+			s.fill.space = "plot";
+			if(isLine){
+				s.stroke  = { width: 2.5, color: s.fill.colors[1].color};
+			}
+			if(elementType == "area"){
+				s.fill.y2 = 90;
+			}
+			var theme = Theme.prototype.next.apply(this, arguments);
+			// cleanup
+			delete s.stroke;
+			s.fill.y2 = 75;
+			s.fill.space = "shape";
+			return theme;
+		}
+		return Theme.prototype.next.apply(this, arguments);
+	};
+	
+	themes.Charged.post = function(theme, elementType){
+		theme = Theme.prototype.post.apply(this, arguments);
+		if((elementType == "slice" || elementType == "circle") && theme.series.fill && theme.series.fill.type == "radial"){
+			theme.series.fill = dojox.gfx.gradutils.reverse(theme.series.fill);
+		}
+		return theme;
+	};
+})();
diff --git a/dojox/charting/themes/Chris.js b/dojox/charting/themes/Chris.js
new file mode 100644
index 0000000..0340ed0
--- /dev/null
+++ b/dojox/charting/themes/Chris.js
@@ -0,0 +1,77 @@
+dojo.provide("dojox.charting.themes.Chris");
+
+dojo.require("dojox.gfx.gradutils");
+dojo.require("dojox.charting.Theme");
+
+// created by Christopher Anderson
+
+(function(){
+	var dc = dojox.charting, themes = dc.themes, Theme = dc.Theme, g = Theme.generateGradient,
+		defaultFill = {type: "linear", space: "shape", x1: 0, y1: 0, x2: 0, y2: 100};
+	
+	themes.Chris = new dc.Theme({
+		chart: {
+			fill:   "#c1c1c1",
+			stroke: {color: "#666"}
+		},
+		plotarea: {
+			fill: "#c1c1c1"
+		},
+		series: {
+			stroke:  {width: 2, color: "white"},
+			outline: null,
+			fontColor: "#333"
+		},
+		marker: {
+			stroke:  {width: 2, color: "white"},
+			outline: {width: 2, color: "white"},
+			fontColor: "#333"
+		},
+		seriesThemes: [
+			{fill: g(defaultFill, "#01b717", "#238c01")},	// green
+			{fill: g(defaultFill, "#d04918", "#7c0344")},	// red
+			{fill: g(defaultFill, "#0005ec", "#002578")},	// blue
+			{fill: g(defaultFill, "#f9e500", "#786f00")},	// yellow
+			{fill: g(defaultFill, "#e27d00", "#773e00")},	// orange
+			{fill: g(defaultFill, "#00b5b0", "#005f5d")},	// teal
+			{fill: g(defaultFill, "#ac00cb", "#590060")}	// purple
+		],
+		markerThemes: [
+			{fill: "#01b717", stroke: {color: "#238c01"}},	// green
+			{fill: "#d04918", stroke: {color: "#7c0344"}},	// red
+			{fill: "#0005ec", stroke: {color: "#002578"}},	// blue
+			{fill: "#f9e500", stroke: {color: "#786f00"}},	// yellow
+			{fill: "#e27d00", stroke: {color: "#773e00"}},	// orange
+			{fill: "#00b5b0", stroke: {color: "#005f5d"}},	// teal
+			{fill: "#ac00cb", stroke: {color: "#590060"}}	// purple
+		]
+	});
+	
+	themes.Chris.next = function(elementType, mixin, doPost){
+		var isLine = elementType == "line";
+		if(isLine || elementType == "area"){
+			// custom processing for lines: substitute colors
+			var s = this.seriesThemes[this._current % this.seriesThemes.length];
+			s.fill.space = "plot";
+			if(isLine){
+				s.stroke  = {color: s.fill.colors[1].color};
+				s.outline = {width: 2, color: "white"};
+			}
+			var theme = Theme.prototype.next.apply(this, arguments);
+			// cleanup
+			delete s.outline;
+			delete s.stroke;
+			s.fill.space = "shape";
+			return theme;
+		}
+		return Theme.prototype.next.apply(this, arguments);
+	};
+	
+	themes.Chris.post = function(theme, elementType){
+		theme = Theme.prototype.post.apply(this, arguments);
+		if((elementType == "slice" || elementType == "circle") && theme.series.fill && theme.series.fill.type == "radial"){
+			theme.series.fill = dojox.gfx.gradutils.reverse(theme.series.fill);
+		}
+		return theme;
+	};
+})();
diff --git a/dojox/charting/themes/CubanShirts.js b/dojox/charting/themes/CubanShirts.js
index b849905..f0521af 100644
--- a/dojox/charting/themes/CubanShirts.js
+++ b/dojox/charting/themes/CubanShirts.js
@@ -1,16 +1,17 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.CubanShirts"]){
-dojo._hasResource["dojox.charting.themes.CubanShirts"]=true;
 dojo.provide("dojox.charting.themes.CubanShirts");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.CubanShirts=new _1.Theme({colors:["#d42d2a","#004f80","#989736","#2085c7","#7f7f33"]});
+	//	notes: colors generated by moving in 30 degree increments around the hue circle,
+	//		at 90% saturation, using a B value of 75 (HSB model).
+	var dxc=dojox.charting;
+	dxc.themes.CubanShirts=new dxc.Theme({
+		colors: [
+			"#d42d2a",
+			"#004f80",
+			"#989736",
+			"#2085c7",
+			"#7f7f33"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Desert.js b/dojox/charting/themes/Desert.js
index c731b74..ce99efd 100644
--- a/dojox/charting/themes/Desert.js
+++ b/dojox/charting/themes/Desert.js
@@ -1,16 +1,17 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Desert"]){
-dojo._hasResource["dojox.charting.themes.Desert"]=true;
 dojo.provide("dojox.charting.themes.Desert");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Desert=new _1.Theme({colors:["#ffebd5","#806544","#fdc888","#80766b","#cda26e"]});
+	//	notes: colors generated by moving in 30 degree increments around the hue circle,
+	//		at 90% saturation, using a B value of 75 (HSB model).
+	var dxc=dojox.charting;
+	dxc.themes.Desert=new dxc.Theme({
+		colors: [
+			"#ffebd5",
+			"#806544",
+			"#fdc888",
+			"#80766b",
+			"#cda26e"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Distinctive.js b/dojox/charting/themes/Distinctive.js
index bc053ea..6f4d9e2 100644
--- a/dojox/charting/themes/Distinctive.js
+++ b/dojox/charting/themes/Distinctive.js
@@ -1,16 +1,42 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Distinctive"]){
-dojo._hasResource["dojox.charting.themes.Distinctive"]=true;
 dojo.provide("dojox.charting.themes.Distinctive");
 dojo.require("dojox.charting.Theme");
 (function(){
-var _1=dojox.charting;
-_1.themes.Distinctive=new _1.Theme({colors:["#497c91","#ada9d6","#768b4e","#eeea99","#b39c53","#c28b69","#815454","#bebebe","#59a0bd","#c9c6e4","#677e13","#f0eebb","#e9c756","#cfb09b","#a05a5a","#d8d8d8","#9dc7d9","#7b78a4","#a8c179","#b7b35c","#ebcf81","#956649","#c99999","#868686","#c7e0e9","#8d88c7","#c0d0a0","#e8e667","#efdeb0","#b17044","#ddc0c0","#a5a5a5"]});
-})();
-}
+	var dxc=dojox.charting;
+	dxc.themes.Distinctive=new dxc.Theme({  
+		colors: [
+			"#497c91",
+			"#ada9d6",
+			"#768b4e",
+			"#eeea99",
+			"#b39c53",
+			"#c28b69",
+			"#815454",
+			"#bebebe",
+			"#59a0bd",
+			"#c9c6e4",
+			"#677e13",
+			"#f0eebb",
+			"#e9c756",
+			"#cfb09b",
+			"#a05a5a",
+			"#d8d8d8",
+			"#9dc7d9",
+			"#7b78a4",
+			"#a8c179",
+			"#b7b35c",
+			"#ebcf81",
+			"#956649",
+			"#c99999",
+			"#868686",
+			"#c7e0e9",
+			"#8d88c7",
+			"#c0d0a0",
+			"#e8e667",
+			"#efdeb0",
+			"#b17044",
+			"#ddc0c0",
+			"#a5a5a5" 
+		
+		]
+	});
+})();
\ No newline at end of file
diff --git a/dojox/charting/themes/Dollar.js b/dojox/charting/themes/Dollar.js
index 2342282..7997efc 100644
--- a/dojox/charting/themes/Dollar.js
+++ b/dojox/charting/themes/Dollar.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Dollar"]){
-dojo._hasResource["dojox.charting.themes.Dollar"]=true;
 dojo.provide("dojox.charting.themes.Dollar");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Dollar=new _1.Theme({colors:["#A4CE67","#739363","#6B824A","#343434","#636563"]});
+	var dxc=dojox.charting;
+	dxc.themes.Dollar=new dxc.Theme({
+		colors: [
+			"#A4CE67",
+            "#739363",
+            "#6B824A",
+            "#343434",
+            "#636563"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/ET/greys.js b/dojox/charting/themes/ET/greys.js
index fb54b5e..774d462 100644
--- a/dojox/charting/themes/ET/greys.js
+++ b/dojox/charting/themes/ET/greys.js
@@ -1,17 +1,55 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.ET.greys"]){
-dojo._hasResource["dojox.charting.themes.ET.greys"]=true;
 dojo.provide("dojox.charting.themes.ET.greys");
 dojo.require("dojox.charting.Theme");
-dojo.deprecated("dojox.charting.themes.ET.greys","1.3");
+dojo.deprecated("dojox.charting.themes.ET.greys", "1.3");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.ET.greys=new _1.Theme({antiAlias:false,chart:{stroke:null,fill:"inherit"},plotarea:{stroke:null,fill:"transparent"},axis:{stroke:{width:0},line:{width:0},majorTick:{color:"#666666",width:1,length:5},minorTick:{color:"black",width:0.5,length:2},font:"normal normal normal 8pt Tahoma",fontColor:"#999999"},series:{outline:{width:0,color:"black"},stroke:{width:1,color:"black"},fill:dojo.colorFromHex("#3b444b"),font:"normal normal normal 7pt Tahoma",fontColor:"#717171"},marker:{strok [...]
+	var dxc=dojox.charting;
+	dxc.themes.ET.greys = new dxc.Theme({
+		antiAlias: false,
+		chart: {
+			stroke: null,
+			fill: "inherit"
+		},
+		plotarea: {
+			// stroke: { width: 0.2, color: "#666666" },
+			stroke: null,
+			fill: "transparent"
+		},
+		axis:{
+			stroke:{ width:	0 },
+			line:{ width:	0 },
+			majorTick:{ 
+				color:	"#666666", 
+				width:	1,
+				length: 5
+			},
+			minorTick: { 
+				color:	"black", 
+				width:	0.5, 
+				length:	2
+			},
+			font:"normal normal normal 8pt Tahoma",
+			fontColor:"#999999"
+		},
+		series:{
+			outline:{ width: 0, color: "black" },
+			stroke:	{ width: 1, color: "black" },
+			fill:	dojo.colorFromHex("#3b444b"),
+			font: "normal normal normal 7pt Tahoma",	//	label
+			fontColor: "#717171"
+		},
+		marker:{	//	any markers on a series.
+			stroke:{ width:1 },
+			fill:"#333",
+			font:"normal normal normal 7pt Tahoma",	//	label
+			fontColor:"#000"
+		},
+		colors:[
+			dojo.colorFromHex("#8a8c8f"), 
+			dojo.colorFromHex("#4b4b4b"),
+			dojo.colorFromHex("#3b444b"), 
+			dojo.colorFromHex("#2e2d30"),
+			dojo.colorFromHex("#000000") 
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Electric.js b/dojox/charting/themes/Electric.js
new file mode 100644
index 0000000..652ae4c
--- /dev/null
+++ b/dojox/charting/themes/Electric.js
@@ -0,0 +1,92 @@
+dojo.provide("dojox.charting.themes.Electric");
+
+dojo.require("dojox.gfx.gradutils");
+dojo.require("dojox.charting.Theme");
+
+// created by Tom Trenka
+
+(function(){
+	var dc = dojox.charting, themes = dc.themes, Theme = dc.Theme, g = Theme.generateGradient,
+		defaultFill = {type: "linear", space: "shape", x1: 0, y1: 0, x2: 0, y2: 75};
+	
+	themes.Electric = new dc.Theme({
+		chart: {
+			fill:      "#252525",
+			stroke:    {color: "#252525"},
+			pageStyle: {backgroundColor: "#252525", backgroundImage: "none", color: "#ccc"}
+		},
+		plotarea: {
+			fill: "#252525"
+		},
+		axis:{
+			stroke:	{ // the axis itself
+				color: "#aaa",
+				width: 1
+			},
+			tick: {	// used as a foundation for all ticks
+				color:     "#777",
+				position:  "center",
+				font:      "normal normal normal 7pt Helvetica, Arial, sans-serif",	// labels on axis
+				fontColor: "#777"								// color of labels
+			}
+		},
+		series: {
+			stroke:  {width: 2, color: "#ccc"},
+			outline: null,
+			font: "normal normal normal 8pt Helvetica, Arial, sans-serif",
+			fontColor: "#ccc"
+		},
+		marker: {
+			stroke:  {width: 3, color: "#ccc"},
+			outline: null,
+			font: "normal normal normal 8pt Helvetica, Arial, sans-serif",
+			fontColor: "#ccc"
+		},
+		seriesThemes: [
+			{fill: g(defaultFill, "#004cbf", "#06f")},
+			{fill: g(defaultFill, "#bf004c", "#f06")},	
+			{fill: g(defaultFill, "#43bf00", "#6f0")},	
+			{fill: g(defaultFill, "#7300bf", "#90f")},	
+			{fill: g(defaultFill, "#bf7300", "#f90")},	
+			{fill: g(defaultFill, "#00bf73", "#0f9")}	
+		],
+		markerThemes: [
+			{fill: "#06f", stroke: {color: "#06f"}},	
+			{fill: "#f06", stroke: {color: "#f06"}},
+			{fill: "#6f0", stroke: {color: "#6f0"}},	
+			{fill: "#90f", stroke: {color: "#90f"}},	
+			{fill: "#f90", stroke: {color: "#f90"}},	
+			{fill: "#0f9", stroke: {color: "#0f9"}}	
+		]
+	});
+	
+	themes.Electric.next = function(elementType, mixin, doPost){
+		var isLine = elementType == "line";
+		if(isLine || elementType == "area"){
+			// custom processing for lines: substitute colors
+			var s = this.seriesThemes[this._current % this.seriesThemes.length];
+			s.fill.space = "plot";
+			if(isLine){
+				s.stroke  = { width: 2.5, color: s.fill.colors[1].color};
+			}
+			if(elementType == "area"){
+				s.fill.y2 = 90;
+			}
+			var theme = Theme.prototype.next.apply(this, arguments);
+			// cleanup
+			delete s.stroke;
+			s.fill.y2 = 75;
+			s.fill.space = "shape";
+			return theme;
+		}
+		return Theme.prototype.next.apply(this, arguments);
+	};
+	
+	themes.Electric.post = function(theme, elementType){
+		theme = Theme.prototype.post.apply(this, arguments);
+		if((elementType == "slice" || elementType == "circle") && theme.series.fill && theme.series.fill.type == "radial"){
+			theme.series.fill = dojox.gfx.gradutils.reverse(theme.series.fill);
+		}
+		return theme;
+	};
+})();
diff --git a/dojox/charting/themes/Grasshopper.js b/dojox/charting/themes/Grasshopper.js
index 85f3484..f6b8106 100644
--- a/dojox/charting/themes/Grasshopper.js
+++ b/dojox/charting/themes/Grasshopper.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Grasshopper"]){
-dojo._hasResource["dojox.charting.themes.Grasshopper"]=true;
 dojo.provide("dojox.charting.themes.Grasshopper");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Grasshopper=new _1.Theme({colors:["#208040","#40b657","#78c25e","#14401f","#64bd5f"]});
+	var dxc=dojox.charting;
+	dxc.themes.Grasshopper=new dxc.Theme({
+		colors: [
+			"#208040",
+			"#40b657",
+			"#78c25e",
+			"#14401f",
+			"#64bd5f"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Grasslands.js b/dojox/charting/themes/Grasslands.js
index 611bc98..cf7f589 100644
--- a/dojox/charting/themes/Grasslands.js
+++ b/dojox/charting/themes/Grasslands.js
@@ -1,16 +1,17 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Grasslands"]){
-dojo._hasResource["dojox.charting.themes.Grasslands"]=true;
 dojo.provide("dojox.charting.themes.Grasslands");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Grasslands=new _1.Theme({colors:["#70803a","#dde574","#788062","#b1cc5d","#eff2c2"]});
+	//	notes: colors generated by moving in 30 degree increments around the hue circle,
+	//		at 90% saturation, using a B value of 75 (HSB model).
+	var dxc=dojox.charting;
+	dxc.themes.Grasslands=new dxc.Theme({
+		colors: [
+			"#70803a",
+			"#dde574",
+			"#788062",
+			"#b1cc5d",
+			"#eff2c2"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/GreySkies.js b/dojox/charting/themes/GreySkies.js
index eb3cba5..b4f9f64 100644
--- a/dojox/charting/themes/GreySkies.js
+++ b/dojox/charting/themes/GreySkies.js
@@ -1,16 +1,7 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.GreySkies"]){
-dojo._hasResource["dojox.charting.themes.GreySkies"]=true;
 dojo.provide("dojox.charting.themes.GreySkies");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.GreySkies=new _1.Theme(_1.Theme._def);
+	var dxc=dojox.charting;
+	dxc.themes.GreySkies=new dxc.Theme(dxc.Theme._def);
 })();
-}
diff --git a/dojox/charting/themes/Harmony.js b/dojox/charting/themes/Harmony.js
index 21dcfc3..986f991 100644
--- a/dojox/charting/themes/Harmony.js
+++ b/dojox/charting/themes/Harmony.js
@@ -1,16 +1,42 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Harmony"]){
-dojo._hasResource["dojox.charting.themes.Harmony"]=true;
 dojo.provide("dojox.charting.themes.Harmony");
 dojo.require("dojox.charting.Theme");
 (function(){
-var _1=dojox.charting;
-_1.themes.Harmony=new _1.Theme({colors:["#497c91","#59a0bd","#9dc7d9","#c7e0e9","#7b78a4","#8d88c7","#ada9d6","#c9c6e4","#768b4e","#677e13","#a8c179","#c0d0a0","#b7b35c","#e8e667","#eeea99","#f0eebb","#b39c53","#e9c756","#ebcf81","#efdeb0","#956649","#b17044","#c28b69","#cfb09b","#815454","#a05a5a","#c99999","#ddc0c0","#868686","#a5a5a5","#bebebe","#d8d8d8"]});
-})();
-}
+	var dxc=dojox.charting;
+		dxc.themes.Harmony=new dxc.Theme({ 
+		colors: [
+			"#497c91",
+			"#59a0bd",
+			"#9dc7d9",
+			"#c7e0e9",
+			"#7b78a4",
+			"#8d88c7",
+			"#ada9d6",
+			"#c9c6e4",
+			"#768b4e",
+			"#677e13",
+			"#a8c179",
+			"#c0d0a0",
+			"#b7b35c",
+			"#e8e667",
+			"#eeea99",
+			"#f0eebb",
+			"#b39c53",
+			"#e9c756",
+			"#ebcf81",
+			"#efdeb0",
+			"#956649",
+			"#b17044",
+			"#c28b69",
+			"#cfb09b",
+			"#815454",
+			"#a05a5a",
+			"#c99999",
+			"#ddc0c0",
+			"#868686",
+			"#a5a5a5",
+			"#bebebe",
+			"#d8d8d8"
+			
+		]
+	});
+})();
\ No newline at end of file
diff --git a/dojox/charting/themes/IndigoNation.js b/dojox/charting/themes/IndigoNation.js
index 706d637..2553f7b 100644
--- a/dojox/charting/themes/IndigoNation.js
+++ b/dojox/charting/themes/IndigoNation.js
@@ -1,16 +1,17 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.IndigoNation"]){
-dojo._hasResource["dojox.charting.themes.IndigoNation"]=true;
 dojo.provide("dojox.charting.themes.IndigoNation");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.IndigoNation=new _1.Theme({colors:["#93a4d0","#3b4152","#687291","#9faed9","#8290b8"]});
+	//	notes: colors generated by moving in 30 degree increments around the hue circle,
+	//		at 90% saturation, using a B value of 75 (HSB model).
+	var dxc=dojox.charting;
+	dxc.themes.IndigoNation=new dxc.Theme({
+		colors: [
+			"#93a4d0",
+			"#3b4152",
+			"#687291",
+			"#9faed9",
+			"#8290b8"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Ireland.js b/dojox/charting/themes/Ireland.js
index bec47ad..72d2d63 100644
--- a/dojox/charting/themes/Ireland.js
+++ b/dojox/charting/themes/Ireland.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Ireland"]){
-dojo._hasResource["dojox.charting.themes.Ireland"]=true;
 dojo.provide("dojox.charting.themes.Ireland");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Ireland=new _1.Theme({colors:["#abdbcb","#435a51","#70998b","#78q596","#5f8074"]});
+	var dxc=dojox.charting;
+	dxc.themes.Ireland=new dxc.Theme({
+		colors: [
+			"#abdbcb",
+			"#435a51",
+			"#70998b",
+			"#78d596",
+			"#5f8074"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Julie.js b/dojox/charting/themes/Julie.js
new file mode 100644
index 0000000..1268521
--- /dev/null
+++ b/dojox/charting/themes/Julie.js
@@ -0,0 +1,70 @@
+dojo.provide("dojox.charting.themes.Julie");
+
+dojo.require("dojox.gfx.gradutils");
+dojo.require("dojox.charting.Theme");
+
+// created by Julie Santilli
+
+(function(){
+	var dc = dojox.charting, themes = dc.themes, Theme = dc.Theme, g = Theme.generateGradient,
+		defaultFill = {type: "linear", space: "shape", x1: 0, y1: 0, x2: 0, y2: 100};
+	
+	themes.Julie = new dc.Theme({
+		seriesThemes: [
+			{fill: g(defaultFill, "#59a0bd", "#497c91"), stroke: {color: "#22627d"}},	// blue
+			{fill: g(defaultFill, "#8d88c7", "#6c6d8e"), stroke: {color: "#8a84c5"}},	// purple
+			{fill: g(defaultFill, "#85a54a", "#768b4e"), stroke: {color: "#5b6d1f"}},	// green
+			{fill: g(defaultFill, "#e8e667", "#c6c361"), stroke: {color: "#918e38"}},	// yellow
+			{fill: g(defaultFill, "#e9c756", "#c7a223"), stroke: {color: "#947b30"}},	// orange
+			{fill: g(defaultFill, "#a05a5a", "#815454"), stroke: {color: "#572828"}},	// red
+			{fill: g(defaultFill, "#b17044", "#72543e"), stroke: {color: "#74482e"}},	// brown
+			{fill: g(defaultFill, "#a5a5a5", "#727272"), stroke: {color: "#535353"}},	// grey
+
+			{fill: g(defaultFill, "#9dc7d9", "#59a0bd"), stroke: {color: "#22627d"}},	// blue
+			{fill: g(defaultFill, "#b7b3da", "#8681b3"), stroke: {color: "#8a84c5"}},	// purple
+			{fill: g(defaultFill, "#a8c179", "#85a54a"), stroke: {color: "#5b6d1f"}},	// green
+			{fill: g(defaultFill, "#eeea99", "#d6d456"), stroke: {color: "#918e38"}},	// yellow
+			{fill: g(defaultFill, "#ebcf81", "#e9c756"), stroke: {color: "#947b30"}},	// orange
+			{fill: g(defaultFill, "#c99999", "#a05a5a"), stroke: {color: "#572828"}},	// red
+			{fill: g(defaultFill, "#c28b69", "#7d5437"), stroke: {color: "#74482e"}},	// brown
+			{fill: g(defaultFill, "#bebebe", "#8c8c8c"), stroke: {color: "#535353"}},	// grey
+
+			{fill: g(defaultFill, "#c7e0e9", "#92baca"), stroke: {color: "#22627d"}},	// blue
+			{fill: g(defaultFill, "#c9c6e4", "#ada9d6"), stroke: {color: "#8a84c5"}},	// purple
+			{fill: g(defaultFill, "#c0d0a0", "#98ab74"), stroke: {color: "#5b6d1f"}},	// green
+			{fill: g(defaultFill, "#f0eebb", "#dcd87c"), stroke: {color: "#918e38"}},	// yellow
+			{fill: g(defaultFill, "#efdeb0", "#ebcf81"), stroke: {color: "#947b30"}},	// orange
+			{fill: g(defaultFill, "#ddc0c0", "#c99999"), stroke: {color: "#572828"}},	// red
+			{fill: g(defaultFill, "#cfb09b", "#c28b69"), stroke: {color: "#74482e"}},	// brown
+			{fill: g(defaultFill, "#d8d8d8", "#bebebe"), stroke: {color: "#535353"}},	// grey
+
+			{fill: g(defaultFill, "#ddeff5", "#a5c4cd"), stroke: {color: "#22627d"}},	// blue
+			{fill: g(defaultFill, "#dedcf0", "#b3afd3"), stroke: {color: "#8a84c5"}},	// purple
+			{fill: g(defaultFill, "#dfe9ca", "#c0d0a0"), stroke: {color: "#5b6d1f"}},	// green
+			{fill: g(defaultFill, "#f8f7db", "#e5e28f"), stroke: {color: "#918e38"}},	// yellow
+			{fill: g(defaultFill, "#f7f0d8", "#cfbd88"), stroke: {color: "#947b30"}},	// orange
+			{fill: g(defaultFill, "#eedede", "#caafaf"), stroke: {color: "#572828"}},	// red
+			{fill: g(defaultFill, "#e3cdbf", "#cfb09b"), stroke: {color: "#74482e"}},	// brown
+			{fill: g(defaultFill, "#efefef", "#cacaca"), stroke: {color: "#535353"}}	// grey
+		]
+	});
+	
+	themes.Julie.next = function(elementType, mixin, doPost){
+		if(elementType == "line" || elementType == "area"){
+			var s = this.seriesThemes[this._current % this.seriesThemes.length];
+			s.fill.space = "plot";
+			var theme = Theme.prototype.next.apply(this, arguments);
+			s.fill.space = "shape";
+			return theme;
+		}
+		return Theme.prototype.next.apply(this, arguments);
+	};
+
+	themes.Julie.post = function(theme, elementType){
+		theme = Theme.prototype.post.apply(this, arguments);
+		if(elementType == "slice" && theme.series.fill && theme.series.fill.type == "radial"){
+			theme.series.fill = dojox.gfx.gradutils.reverse(theme.series.fill);
+		}
+		return theme;
+	};
+})();
diff --git a/dojox/charting/themes/MiamiNice.js b/dojox/charting/themes/MiamiNice.js
index 1a1714a..f989ea0 100644
--- a/dojox/charting/themes/MiamiNice.js
+++ b/dojox/charting/themes/MiamiNice.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.MiamiNice"]){
-dojo._hasResource["dojox.charting.themes.MiamiNice"]=true;
 dojo.provide("dojox.charting.themes.MiamiNice");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.MiamiNice=new _1.Theme({colors:["#7f9599","#45b8cc","#8ecfb0","#f8acac","#cc4482"]});
+	var dxc=dojox.charting;
+	dxc.themes.MiamiNice=new dxc.Theme({
+		colors: [
+			"#7f9599",
+			"#45b8cc",
+			"#8ecfb0",
+			"#f8acac",
+			"#cc4482"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Midwest.js b/dojox/charting/themes/Midwest.js
index f1d48b7..0458c06 100644
--- a/dojox/charting/themes/Midwest.js
+++ b/dojox/charting/themes/Midwest.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Midwest"]){
-dojo._hasResource["dojox.charting.themes.Midwest"]=true;
 dojo.provide("dojox.charting.themes.Midwest");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Midwest=new _1.Theme({colors:["#927b51","#a89166","#80c31c","#bcdd5a","#aebc21"]});
+	var dxc=dojox.charting;
+	dxc.themes.Midwest=new dxc.Theme({
+		colors: [
+			"#927b51", 
+			"#a89166",
+			"#80c31c",
+			"#bcdd5a",
+			"#aebc21"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Minty.js b/dojox/charting/themes/Minty.js
index 5a290ce..18e03d9 100644
--- a/dojox/charting/themes/Minty.js
+++ b/dojox/charting/themes/Minty.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Minty"]){
-dojo._hasResource["dojox.charting.themes.Minty"]=true;
 dojo.provide("dojox.charting.themes.Minty");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Minty=new _1.Theme({colors:["#80ccbb","#539e8b","#335f54","#8dd1c2","#68c5ad"]});
+	var dxc=dojox.charting;
+	dxc.themes.Minty=new dxc.Theme({
+		colors: [
+			"#80ccbb", 
+			"#539e8b",
+			"#335f54",
+			"#8dd1c2",
+			"#68c5ad"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/PlotKit/base.js b/dojox/charting/themes/PlotKit/base.js
new file mode 100644
index 0000000..3ab91bc
--- /dev/null
+++ b/dojox/charting/themes/PlotKit/base.js
@@ -0,0 +1,53 @@
+dojo.provide("dojox.charting.themes.PlotKit.base");
+
+dojo.require("dojox.charting.Theme");
+
+// the baseline theme for all PlotKIt themes
+(function(){
+	var dc = dojox.charting, pk = dc.themes.PlotKit;
+
+	pk.base = new dc.Theme({
+		chart:{
+			stroke: null,
+			fill:   "yellow"
+		},
+		plotarea:{
+			stroke: null,
+			fill:   "yellow"
+		},
+		axis:{
+			stroke:    {color:"#fff", width:1},
+			line:      {color:"#fff", width:.5},
+			majorTick: {color: "#fff", width: .5, length: 6},
+			minorTick: {color: "#fff", width: .5, length: 3},
+			tick:      {font: "normal normal normal 7pt Helvetica,Arial,sans-serif", fontColor: "#999"}
+		},
+		series:{
+			stroke:    {width: 2.5, color:"#fff"},
+			fill:      "#666",
+			font:      "normal normal normal 7.5pt Helvetica,Arial,sans-serif",	//	label
+			fontColor: "#666"
+		},
+		marker:{	//	any markers on a series.
+			stroke:    {width: 2},
+			fill:      "#333",
+			font:      "normal normal normal 7pt Helvetica,Arial,sans-serif",	//	label
+			fontColor: "#666"
+		},
+		colors: ["red", "green", "blue"]
+	});
+
+	pk.base.next = function(elementType, mixin, doPost){
+		var theme = dc.Theme.prototype.next.apply(this, arguments);
+		if(elementType == "line"){
+			theme.marker.outline = {width: 2, color: "#fff"};
+			theme.series.stroke.width = 3.5;
+			theme.marker.stroke.width = 2;
+		} else if (elementType == "candlestick"){
+			theme.series.stroke.width = 1;
+		} else {
+			theme.series.stroke.color = "#fff";
+		}
+		return theme;
+	};
+})();
diff --git a/dojox/charting/themes/PlotKit/blue.js b/dojox/charting/themes/PlotKit/blue.js
index 733b23b..b5e2f98 100644
--- a/dojox/charting/themes/PlotKit/blue.js
+++ b/dojox/charting/themes/PlotKit/blue.js
@@ -1,17 +1,10 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.PlotKit.blue"]){
-dojo._hasResource["dojox.charting.themes.PlotKit.blue"]=true;
 dojo.provide("dojox.charting.themes.PlotKit.blue");
-dojo.require("dojox.charting.Theme");
+dojo.require("dojox.charting.themes.PlotKit.base");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.PlotKit.blue=new _1.Theme({chart:{stroke:null,fill:"white"},plotarea:{stroke:null,fill:"#e7eef6"},axis:{stroke:{color:"#fff",width:2},line:{color:"#fff",width:1},majorTick:{color:"#fff",width:2,length:12},minorTick:{color:"#fff",width:1,length:8},font:"normal normal normal 8pt Tahoma",fontColor:"#999"},series:{outline:{width:0.1,color:"#fff"},stroke:{width:1.5,color:"#666"},fill:new dojo.Color([102,102,102,0.8]),font:"normal normal normal 7pt Tahoma",fontColor:"#000"},marker:{s [...]
-_1.themes.PlotKit.blue.defineColors({hue:217,saturation:60,low:40,high:88});
+	var dc = dojox.charting, pk = dc.themes.PlotKit;
+
+	pk.blue = pk.base.clone();
+	pk.blue.chart.fill = pk.blue.plotarea.fill = "#e7eef6";
+	pk.blue.colors = dc.Theme.defineColors({hue: 217, saturation: 60, low: 40, high: 88});
 })();
-}
diff --git a/dojox/charting/themes/PlotKit/cyan.js b/dojox/charting/themes/PlotKit/cyan.js
index c97d371..5f534ca 100644
--- a/dojox/charting/themes/PlotKit/cyan.js
+++ b/dojox/charting/themes/PlotKit/cyan.js
@@ -1,17 +1,10 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.PlotKit.cyan"]){
-dojo._hasResource["dojox.charting.themes.PlotKit.cyan"]=true;
 dojo.provide("dojox.charting.themes.PlotKit.cyan");
-dojo.require("dojox.charting.Theme");
+dojo.require("dojox.charting.themes.PlotKit.base");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.PlotKit.cyan=new _1.Theme({chart:{stroke:null,fill:"white"},plotarea:{stroke:null,fill:"#e6f1f5"},axis:{stroke:{color:"#fff",width:2},line:{color:"#fff",width:1},majorTick:{color:"#fff",width:2,length:12},minorTick:{color:"#fff",width:1,length:8},font:"normal normal normal 8pt Tahoma",fontColor:"#999"},series:{outline:{width:1,color:"#fff"},stroke:{width:2,color:"#666"},fill:new dojo.Color([102,102,102,0.8]),font:"normal normal normal 7pt Tahoma",fontColor:"#000"},marker:{strok [...]
-_1.themes.PlotKit.cyan.defineColors({hue:194,saturation:60,low:40,high:88});
+	var dc = dojox.charting, pk = dc.themes.PlotKit;
+
+	pk.cyan = pk.base.clone();
+	pk.cyan.chart.fill = pk.cyan.plotarea.fill = "#e6f1f5";
+	pk.cyan.colors = dc.Theme.defineColors({hue: 194, saturation: 60, low: 40, high: 88});
 })();
-}
diff --git a/dojox/charting/themes/PlotKit/green.js b/dojox/charting/themes/PlotKit/green.js
index 1955efd..48269ad 100644
--- a/dojox/charting/themes/PlotKit/green.js
+++ b/dojox/charting/themes/PlotKit/green.js
@@ -1,17 +1,10 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.PlotKit.green"]){
-dojo._hasResource["dojox.charting.themes.PlotKit.green"]=true;
 dojo.provide("dojox.charting.themes.PlotKit.green");
-dojo.require("dojox.charting.Theme");
+dojo.require("dojox.charting.themes.PlotKit.base");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.PlotKit.green=new _1.Theme({chart:{stroke:null,fill:"white"},plotarea:{stroke:null,fill:"#eff5e6"},axis:{stroke:{color:"#fff",width:2},line:{color:"#fff",width:1},majorTick:{color:"#fff",width:2,length:12},minorTick:{color:"#fff",width:1,length:8},font:"normal normal normal 8pt Tahoma",fontColor:"#999"},series:{outline:{width:1,color:"#fff"},stroke:{width:2,color:"#666"},fill:new dojo.Color([102,102,102,0.8]),font:"normal normal normal 7pt Tahoma",fontColor:"#000"},marker:{stro [...]
-_1.themes.PlotKit.green.defineColors({hue:82,saturation:60,low:40,high:88});
+	var dc = dojox.charting, pk = dc.themes.PlotKit;
+
+	pk.green = pk.base.clone();
+	pk.green.chart.fill = pk.green.plotarea.fill = "#eff5e6";
+	pk.green.colors = dc.Theme.defineColors({hue: 82, saturation: 60, low: 40, high: 88});
 })();
-}
diff --git a/dojox/charting/themes/PlotKit/orange.js b/dojox/charting/themes/PlotKit/orange.js
index 3f45bf6..294b9a4 100644
--- a/dojox/charting/themes/PlotKit/orange.js
+++ b/dojox/charting/themes/PlotKit/orange.js
@@ -1,17 +1,10 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.PlotKit.orange"]){
-dojo._hasResource["dojox.charting.themes.PlotKit.orange"]=true;
 dojo.provide("dojox.charting.themes.PlotKit.orange");
-dojo.require("dojox.charting.Theme");
+dojo.require("dojox.charting.themes.PlotKit.base");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.PlotKit.orange=new _1.Theme({chart:{stroke:null,fill:"white"},plotarea:{stroke:null,fill:"#f5eee6"},axis:{stroke:{color:"#fff",width:2},line:{color:"#fff",width:1},majorTick:{color:"#fff",width:2,length:12},minorTick:{color:"#fff",width:1,length:8},font:"normal normal normal 8pt Tahoma",fontColor:"#999"},series:{outline:{width:0.15,color:"#fff"},stroke:{width:1.5,color:"#666"},fill:new dojo.Color([102,102,102,0.8]),font:"normal normal normal 7pt Tahoma",fontColor:"#000"},marker [...]
-_1.themes.PlotKit.orange.defineColors({hue:31,saturation:60,low:40,high:88});
+	var dc = dojox.charting, pk = dc.themes.PlotKit;
+
+	pk.orange = pk.base.clone();
+	pk.orange.chart.fill = pk.orange.plotarea.fill = "#f5eee6";
+	pk.orange.colors = dc.Theme.defineColors({hue: 31, saturation: 60, low: 40, high: 88});
 })();
-}
diff --git a/dojox/charting/themes/PlotKit/purple.js b/dojox/charting/themes/PlotKit/purple.js
index 2ca8a18..5d92011 100644
--- a/dojox/charting/themes/PlotKit/purple.js
+++ b/dojox/charting/themes/PlotKit/purple.js
@@ -1,17 +1,10 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.PlotKit.purple"]){
-dojo._hasResource["dojox.charting.themes.PlotKit.purple"]=true;
 dojo.provide("dojox.charting.themes.PlotKit.purple");
-dojo.require("dojox.charting.Theme");
+dojo.require("dojox.charting.themes.PlotKit.base");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.PlotKit.purple=new _1.Theme({chart:{stroke:null,fill:"white"},plotarea:{stroke:null,fill:"#eee6f5"},axis:{stroke:{color:"#fff",width:2},line:{color:"#fff",width:1},majorTick:{color:"#fff",width:2,length:12},minorTick:{color:"#fff",width:1,length:8},font:"normal normal normal 8pt Tahoma",fontColor:"#999"},series:{outline:{width:1,color:"#fff"},stroke:{width:2,color:"#666"},fill:new dojo.Color([102,102,102,0.8]),font:"normal normal normal 7pt Tahoma",fontColor:"#000"},marker:{str [...]
-_1.themes.PlotKit.purple.defineColors({hue:271,saturation:60,low:40,high:88});
+	var dc = dojox.charting, pk = dc.themes.PlotKit;
+
+	pk.purple = pk.base.clone();
+	pk.purple.chart.fill = pk.purple.plotarea.fill = "#eee6f5";
+	pk.purple.colors = dc.Theme.defineColors({hue: 271, saturation: 60, low: 40, high: 88});
 })();
-}
diff --git a/dojox/charting/themes/PlotKit/red.js b/dojox/charting/themes/PlotKit/red.js
index b47a330..7ac8169 100644
--- a/dojox/charting/themes/PlotKit/red.js
+++ b/dojox/charting/themes/PlotKit/red.js
@@ -1,17 +1,10 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.PlotKit.red"]){
-dojo._hasResource["dojox.charting.themes.PlotKit.red"]=true;
 dojo.provide("dojox.charting.themes.PlotKit.red");
-dojo.require("dojox.charting.Theme");
+dojo.require("dojox.charting.themes.PlotKit.base");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.PlotKit.red=new _1.Theme({chart:{stroke:null,fill:"white"},plotarea:{stroke:null,fill:"#f5e6e6"},axis:{stroke:{color:"#fff",width:2},line:{color:"#fff",width:1},majorTick:{color:"#fff",width:2,length:12},minorTick:{color:"#fff",width:1,length:8},font:"normal normal normal 8pt Tahoma",fontColor:"#999"},series:{outline:{width:1,color:"#fff"},stroke:{width:2,color:"#666"},fill:new dojo.Color([102,102,102,0.8]),font:"normal normal normal 7pt Tahoma",fontColor:"#000"},marker:{stroke [...]
-_1.themes.PlotKit.red.defineColors({hue:1,saturation:60,low:40,high:88});
+	var dc = dojox.charting, pk = dc.themes.PlotKit;
+
+	pk.red = pk.base.clone();
+	pk.red.chart.fill = pk.red.plotarea.fill = "#f5e6e6";
+	pk.red.colors = dc.Theme.defineColors({hue: 1, saturation: 60, low: 40, high: 88});
 })();
-}
diff --git a/dojox/charting/themes/PrimaryColors.js b/dojox/charting/themes/PrimaryColors.js
new file mode 100644
index 0000000..5a230ec
--- /dev/null
+++ b/dojox/charting/themes/PrimaryColors.js
@@ -0,0 +1,14 @@
+dojo.provide("dojox.charting.themes.PrimaryColors");
+
+dojo.require("dojox.charting.Theme");
+dojo.require("dojox.charting.themes.gradientGenerator");
+
+(function(){
+	var dc = dojox.charting, themes = dc.themes,
+		colors = ["#f00", "#0f0", "#00f", "#ff0", "#0ff", "#f0f"],
+		defaultFill = {type: "linear", space: "plot", x1: 0, y1: 0, x2: 0, y2: 100};
+
+	themes.PrimaryColors = new dc.Theme({
+		seriesThemes: themes.gradientGenerator.generateMiniTheme(colors, defaultFill, 90, 40, 25)
+	});
+})();
diff --git a/dojox/charting/themes/PurpleRain.js b/dojox/charting/themes/PurpleRain.js
index d755fcf..94fcea6 100644
--- a/dojox/charting/themes/PurpleRain.js
+++ b/dojox/charting/themes/PurpleRain.js
@@ -1,16 +1,17 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.PurpleRain"]){
-dojo._hasResource["dojox.charting.themes.PurpleRain"]=true;
 dojo.provide("dojox.charting.themes.PurpleRain");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.PurpleRain=new _1.Theme({colors:["#4879bc","#ef446f","#3f58a7","#8254a2","#4956a6"]});
+	//	notes: colors generated by moving in 30 degree increments around the hue circle,
+	//		at 90% saturation, using a B value of 75 (HSB model).
+	var dxc=dojox.charting;
+	dxc.themes.PurpleRain=new dxc.Theme({
+		colors: [
+			"#4879bc",
+			"#ef446f",
+			"#3f58a7",
+			"#8254a2",
+			"#4956a6"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Renkoo.js b/dojox/charting/themes/Renkoo.js
new file mode 100644
index 0000000..cf602cb
--- /dev/null
+++ b/dojox/charting/themes/Renkoo.js
@@ -0,0 +1,85 @@
+dojo.provide("dojox.charting.themes.Renkoo");
+
+dojo.require("dojox.gfx.gradutils");
+dojo.require("dojox.charting.Theme");
+
+// created by Tom Trenka
+
+(function(){
+	var dc = dojox.charting, themes = dc.themes, Theme = dc.Theme, g = Theme.generateGradient,
+		defaultFill = {type: "linear", space: "shape", x1: 0, y1: 0, x2: 0, y2: 150};
+	
+	themes.Renkoo = new dc.Theme({
+		chart: {
+			fill:      "#123666",
+			pageStyle: {backgroundColor: "#123666", backgroundImage: "none", color: "#95afdb"}
+		},
+		plotarea: {
+			fill: "#123666"
+		},
+		axis:{
+			stroke:	{ // the axis itself
+				color: "#95afdb",
+				width: 1
+			},
+			tick: {	// used as a foundation for all ticks
+				color:     "#95afdb",
+				position:  "center",
+				font:      "normal normal normal 7pt Lucida Grande, Helvetica, Arial, sans-serif",	// labels on axis
+				fontColor: "#95afdb"								// color of labels
+			}
+		},
+		series: {
+			stroke:  {width: 2.5, color: "#123666"},
+			outline: null,
+			font:      "normal normal normal 8pt Lucida Grande, Helvetica, Arial, sans-serif",	// labels on axis
+			fontColor: "#95afdb"
+		},
+		marker: {
+			stroke:  {width: 2.5, color: "#ccc"},
+			outline: null,
+			font:      "normal normal normal 8pt Lucida Grande, Helvetica, Arial, sans-serif",	// labels on axis
+			fontColor: "#95afdb"
+		},
+		seriesThemes: [
+			{fill: g(defaultFill, "#e7e391", "#f8f7de")},
+			{fill: g(defaultFill, "#ffb6b6", "#ffe8e8")},	
+			{fill: g(defaultFill, "#bcda7d", "#eef7da")},	
+			{fill: g(defaultFill, "#d5d5d5", "#f4f4f4")},	
+			{fill: g(defaultFill, "#c1e3fd", "#e4f3ff")}	
+		],
+		markerThemes: [
+			{fill: "#fcfcf3", stroke: {color: "#e7e391"}},	
+			{fill: "#fff1f1", stroke: {color: "#ffb6b6"}},	
+			{fill: "#fafdf4", stroke: {color: "#bcda7d"}},
+			{fill: "#fbfbfb", stroke: {color: "#d5d5d5"}},	
+			{fill: "#f3faff", stroke: {color: "#c1e3fd"}}	
+		]
+	});
+	
+	themes.Renkoo.next = function(elementType, mixin, doPost){
+		if("slice,column,bar".indexOf(elementType) == -1){
+			// custom processing to substitute colors
+			var s = this.seriesThemes[this._current % this.seriesThemes.length];
+			s.fill.space = "plot";
+			s.stroke  = { width: 2, color: s.fill.colors[0].color};
+			if(elementType == "line" || elementType == "area"){
+				s.stroke.width = 4;
+			}
+			var theme = Theme.prototype.next.apply(this, arguments);
+			// cleanup
+			delete s.stroke;
+			s.fill.space = "shape";
+			return theme;
+		}
+		return Theme.prototype.next.apply(this, arguments);
+	};
+	
+	themes.Renkoo.post = function(theme, elementType){
+		theme = Theme.prototype.post.apply(this, arguments);
+		if((elementType == "slice" || elementType == "circle") && theme.series.fill && theme.series.fill.type == "radial"){
+			theme.series.fill = dojox.gfx.gradutils.reverse(theme.series.fill);
+		}
+		return theme;
+	};
+})();
diff --git a/dojox/charting/themes/RoyalPurples.js b/dojox/charting/themes/RoyalPurples.js
index a44ae8b..e09229e 100644
--- a/dojox/charting/themes/RoyalPurples.js
+++ b/dojox/charting/themes/RoyalPurples.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.RoyalPurples"]){
-dojo._hasResource["dojox.charting.themes.RoyalPurples"]=true;
 dojo.provide("dojox.charting.themes.RoyalPurples");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.RoyalPurples=new _1.Theme({colors:["#473980","#685aa7","#7970b3","#231c3f","#7267ae"]});
+	var dxc=dojox.charting;
+	dxc.themes.RoyalPurples=new dxc.Theme({
+		colors: [
+			"#473980",
+			"#685aa7",
+			"#7970b3",
+			"#231c3f",
+			"#7267ae"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/SageToLime.js b/dojox/charting/themes/SageToLime.js
index 38db603..8391dea 100644
--- a/dojox/charting/themes/SageToLime.js
+++ b/dojox/charting/themes/SageToLime.js
@@ -1,16 +1,20 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.SageToLime"]){
-dojo._hasResource["dojox.charting.themes.SageToLime"]=true;
 dojo.provide("dojox.charting.themes.SageToLime");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.SageToLime=new _1.Theme({colors:["#abdbcb","#435a51","#70998b","#5f8074","#80ccbb","#539e8b","#78a596","#335f54","#8dd1c2","#68c5ad"]});
+	var dxc=dojox.charting;
+	dxc.themes.SageToLime=new dxc.Theme({
+		colors: [
+			"#abdbcb", 
+			"#435a51",
+			"#70998b",
+			"#5f8074",
+			"#80ccbb",
+			"#539e8b",
+			"#78a596",
+			"#335f54",
+			"#8dd1c2",
+			"#68c5ad"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Shrooms.js b/dojox/charting/themes/Shrooms.js
index 8524b61..f0afd32 100644
--- a/dojox/charting/themes/Shrooms.js
+++ b/dojox/charting/themes/Shrooms.js
@@ -1,16 +1,24 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Shrooms"]){
-dojo._hasResource["dojox.charting.themes.Shrooms"]=true;
 dojo.provide("dojox.charting.themes.Shrooms");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Shrooms=new _1.Theme({colors:["#bf1313","#69bf13","#13bfbf","#6913bf","#bf6913","#13bf13","#1369bf","#bf13bf","#bfbf13","#13bf69","#1313bf","#bf1369"]});
+	//	notes: colors generated by moving in 30 degree increments around the hue circle,
+	//		at 90% saturation, using a B value of 75 (HSB model).
+	var dxc=dojox.charting;
+	dxc.themes.Shrooms=new dxc.Theme({
+		colors: [
+			"#bf1313", // 0
+			"#69bf13", // 90
+			"#13bfbf", // 180
+			"#6913bf", // 270
+			"#bf6913", // 30
+			"#13bf13", // 120
+			"#1369bf", // 210
+			"#bf13bf", // 300
+			"#bfbf13", // 60
+			"#13bf69", // 150
+			"#1313bf", // 240
+			"#bf1369"  // 330
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/ThreeD.js b/dojox/charting/themes/ThreeD.js
new file mode 100644
index 0000000..64368e0
--- /dev/null
+++ b/dojox/charting/themes/ThreeD.js
@@ -0,0 +1,49 @@
+dojo.provide("dojox.charting.themes.ThreeD");
+
+dojo.require("dojo.colors"); // for dojo.Color.sanitize()
+dojo.require("dojox.charting.Theme");
+dojo.require("dojox.charting.themes.gradientGenerator");
+
+dojo.require("dojox.charting.themes.PrimaryColors"); // as a baseline theme
+
+(function(){
+	var dc = dojox.charting, themes = dc.themes, Theme = dc.Theme,
+		gi = themes.gradientGenerator.generateGradientByIntensity,
+		colors = ["#f00", "#0f0", "#00f", "#ff0", "#0ff", "#f0f"],	// the same is in PrimaryColors
+		defaultFill = {type: "linear", space: "shape", x1: 0, y1: 0, x2: 100, y2: 0},
+		// 3D cylinder map is calculated using dojox.gfx3d
+		cyl3dMap = [
+			{o: 0.00, i: 174}, {o: 0.08, i: 231}, {o: 0.18, i: 237}, {o: 0.30, i: 231},
+			{o: 0.39, i: 221}, {o: 0.49, i: 206}, {o: 0.58, i: 187}, {o: 0.68, i: 165},
+			{o: 0.80, i: 128}, {o: 0.90, i: 102}, {o: 1.00, i: 174}
+		],
+		hiliteIndex = 2, hiliteIntensity = 100, lumStroke = 50,
+		cyl3dFills = dojo.map(colors, function(c){
+			var fill = dojo.delegate(defaultFill),
+				colors = fill.colors = themes.gradientGenerator.generateGradientByIntensity(c, cyl3dMap),
+				hilite = colors[hiliteIndex].color;
+			// add highlight
+			hilite.r += hiliteIntensity;
+			hilite.g += hiliteIntensity;
+			hilite.b += hiliteIntensity;
+			hilite.sanitize();
+			return fill;
+		});
+
+	themes.ThreeD = themes.PrimaryColors.clone();
+	themes.ThreeD.series.shadow = {dx: 1, dy: 1, width: 3, color: [0, 0, 0, 0.15]};
+
+	themes.ThreeD.next = function(elementType, mixin, doPost){
+		if(elementType == "bar" || elementType == "column"){
+			// custom processing for bars and columns: substitute fills
+			var index = this._current % this.seriesThemes.length,
+				s = this.seriesThemes[index], old = s.fill;
+			s.fill = cyl3dFills[index];
+			var theme = Theme.prototype.next.apply(this, arguments);
+			// cleanup
+			s.fill = old;
+			return theme;
+		}
+		return Theme.prototype.next.apply(this, arguments);
+	};
+})();
diff --git a/dojox/charting/themes/Tom.js b/dojox/charting/themes/Tom.js
new file mode 100644
index 0000000..9426c85
--- /dev/null
+++ b/dojox/charting/themes/Tom.js
@@ -0,0 +1,87 @@
+dojo.provide("dojox.charting.themes.Tom");
+
+dojo.require("dojox.gfx.gradutils");
+dojo.require("dojox.charting.Theme");
+
+// created by Tom Trenka
+
+(function(){
+	var dc = dojox.charting, themes = dc.themes, Theme = dc.Theme, g = Theme.generateGradient,
+		defaultFill = {type: "linear", space: "shape", x1: 0, y1: 0, x2: 0, y2: 100};
+	
+	themes.Tom = new dc.Theme({
+		chart: {
+			fill:      "#181818",
+			stroke:    {color: "#181818"},
+			pageStyle: {backgroundColor: "#181818", backgroundImage: "none", color: "#eaf2cb"}
+		},
+		plotarea: {
+			fill: "#181818"
+		},
+		axis:{
+			stroke:	{ // the axis itself
+				color: "#a0a68b",
+				width: 1
+			},
+			tick: {	// used as a foundation for all ticks
+				color:     "#888c76",
+				position:  "center",
+				font:      "normal normal normal 7pt Helvetica, Arial, sans-serif",	// labels on axis
+				fontColor: "#888c76"								// color of labels
+			}
+		},
+		series: {
+			stroke:  {width: 2.5, color: "#eaf2cb"},
+			outline: null,
+			font: "normal normal normal 8pt Helvetica, Arial, sans-serif",
+			fontColor: "#eaf2cb"
+		},
+		marker: {
+			stroke:  {width: 1.25, color: "#eaf2cb"},
+			outline: {width: 1.25, color: "#eaf2cb"},
+			font: "normal normal normal 8pt Helvetica, Arial, sans-serif",
+			fontColor: "#eaf2cb"
+		},
+		seriesThemes: [
+			{fill: g(defaultFill, "#bf9e0a", "#ecc20c")},
+			{fill: g(defaultFill, "#73b086", "#95e5af")},	
+			{fill: g(defaultFill, "#c7212d", "#ed2835")},	
+			{fill: g(defaultFill, "#87ab41", "#b6e557")},	
+			{fill: g(defaultFill, "#b86c25", "#d37d2a")}	
+		],
+		markerThemes: [
+			{fill: "#bf9e0a", stroke: {color: "#ecc20c"}},	
+			{fill: "#73b086", stroke: {color: "#95e5af"}},
+			{fill: "#c7212d", stroke: {color: "#ed2835"}},	
+			{fill: "#87ab41", stroke: {color: "#b6e557"}},	
+			{fill: "#b86c25", stroke: {color: "#d37d2a"}}	
+		]
+	});
+	
+	themes.Tom.next = function(elementType, mixin, doPost){
+		var isLine = elementType == "line";
+		if(isLine || elementType == "area"){
+			// custom processing for lines: substitute colors
+			var s = this.seriesThemes[this._current % this.seriesThemes.length];
+			s.fill.space = "plot";
+			if(isLine){
+				s.stroke  = { width: 4, color: s.fill.colors[0].color};
+			}
+			var theme = Theme.prototype.next.apply(this, arguments);
+			// cleanup
+			delete s.outline;
+			delete s.stroke;
+			s.fill.space = "shape";
+			return theme;
+		}
+		return Theme.prototype.next.apply(this, arguments);
+	};
+	
+	themes.Tom.post = function(theme, elementType){
+		theme = Theme.prototype.post.apply(this, arguments);
+		if((elementType == "slice" || elementType == "circle") && theme.series.fill && theme.series.fill.type == "radial"){
+			theme.series.fill = dojox.gfx.gradutils.reverse(theme.series.fill);
+		}
+		return theme;
+	};
+})();
diff --git a/dojox/charting/themes/Tufte.js b/dojox/charting/themes/Tufte.js
index 5677bc2..56ab4e1 100644
--- a/dojox/charting/themes/Tufte.js
+++ b/dojox/charting/themes/Tufte.js
@@ -1,16 +1,54 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Tufte"]){
-dojo._hasResource["dojox.charting.themes.Tufte"]=true;
 dojo.provide("dojox.charting.themes.Tufte");
 dojo.require("dojox.charting.Theme");
-(function(){
-var _1=dojox.charting;
-_1.themes.Tufte=new _1.Theme({antiAlias:false,chart:{stroke:null,fill:"inherit"},plotarea:{stroke:null,fill:"transparent"},axis:{stroke:{width:0},line:{width:0},majorTick:{color:"#666666",width:1,length:5},minorTick:{color:"black",width:1,length:2},font:"normal normal normal 8pt Tahoma",fontColor:"#999999"},series:{outline:{width:0,color:"black"},stroke:{width:1,color:"black"},fill:new dojo.Color([59,68,75,0.85]),font:"normal normal normal 7pt Tahoma",fontColor:"#717171"},marker:{stroke: [...]
-})();
-}
+
+/*
+	A charting theme based on the principles championed by
+	Edward Tufte.  By Alex Russell, Dojo Project Lead.
+*/
+dojox.charting.themes.Tufte = new dojox.charting.Theme({
+	chart: {
+		stroke: null,
+		fill: "inherit"
+	},
+	plotarea: {
+		// stroke: { width: 0.2, color: "#666666" },
+		stroke: null,
+		fill: "transparent"
+	},
+	axis: {
+		stroke: {width: 1, color: "#ccc"},
+		majorTick:{ 
+			color:	"black", 
+			width:	1,
+			length: 5
+		},
+		minorTick: { 
+			color:	"#666", 
+			width:	1, 
+			length:	2
+		},
+		font: "normal normal normal 8pt Tahoma",
+		fontColor: "#999"
+	},
+	series: {
+		outline:   null,
+		stroke:	   {width: 1, color: "black"},
+		// fill:   "#3b444b",
+		fill:      new dojo.Color([0x3b, 0x44, 0x4b, 0.85]),
+		font: "normal normal normal 7pt Tahoma",
+		fontColor: "#717171"
+	},
+	marker: {
+		stroke:    {width: 1, color: "black"},
+		fill:      "#333",
+		font: "normal normal normal 7pt Tahoma",
+		fontColor: "black"
+	},
+	colors:[
+		dojo.colorFromHex("#8a8c8f"), 
+		dojo.colorFromHex("#4b4b4b"),
+		dojo.colorFromHex("#3b444b"), 
+		dojo.colorFromHex("#2e2d30"),
+		dojo.colorFromHex("#000000") 
+	]
+});
diff --git a/dojox/charting/themes/WatersEdge.js b/dojox/charting/themes/WatersEdge.js
index 3c1469e..31e80ef 100644
--- a/dojox/charting/themes/WatersEdge.js
+++ b/dojox/charting/themes/WatersEdge.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.WatersEdge"]){
-dojo._hasResource["dojox.charting.themes.WatersEdge"]=true;
 dojo.provide("dojox.charting.themes.WatersEdge");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.WatersEdge=new _1.Theme({colors:["#437cc0","#6256a5","#4552a3","#43c4f2","#4b66b0"]});
+	var dxc=dojox.charting;
+	dxc.themes.WatersEdge=new dxc.Theme({
+		colors: [
+			"#437cc0",
+			"#6256a5",
+			"#4552a3",
+			"#43c4f2",
+			"#4b66b0"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/Wetland.js b/dojox/charting/themes/Wetland.js
index a3ff02c..654a65b 100644
--- a/dojox/charting/themes/Wetland.js
+++ b/dojox/charting/themes/Wetland.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.themes.Wetland"]){
-dojo._hasResource["dojox.charting.themes.Wetland"]=true;
 dojo.provide("dojox.charting.themes.Wetland");
 dojo.require("dojox.charting.Theme");
+
 (function(){
-var _1=dojox.charting;
-_1.themes.Wetland=new _1.Theme({colors:["#bfbc64","#737130","#73373b","#7dafca","#8d3c42"]});
+	var dxc=dojox.charting;
+	dxc.themes.Wetland=new dxc.Theme({
+		colors: [
+			"#bfbc64",
+			"#737130",
+			"#73373b",
+			"#7dafca",
+			"#8d3c42"
+		]
+	});
 })();
-}
diff --git a/dojox/charting/themes/gradientGenerator.js b/dojox/charting/themes/gradientGenerator.js
new file mode 100644
index 0000000..c86d34e
--- /dev/null
+++ b/dojox/charting/themes/gradientGenerator.js
@@ -0,0 +1,83 @@
+dojo.provide("dojox.charting.themes.gradientGenerator");
+dojo.require("dojox.charting.Theme");
+
+(function(){
+	var gg = dojox.charting.themes.gradientGenerator;
+
+	gg.generateFills = function(colors, fillPattern, lumFrom, lumTo){
+		//	summary:
+		//		generates 2-color gradients using pure colors, a fill pattern, and two luminance values
+		//	colors: Array:
+		//		Array of colors to generate gradients for each.
+		//	fillPattern: Object:
+		//		Gradient fill descriptor which colors list will be generated.
+		//	lumFrom: Number:
+		//		Initial luminance value (0-100).
+		//	lumTo: Number:
+		//		Final luminance value (0-100).
+		var Theme = dojox.charting.Theme;
+		return dojo.map(colors, function(c){	// Array
+			return Theme.generateHslGradient(c, fillPattern, lumFrom, lumTo);
+		});
+	};
+	
+	gg.updateFills = function(themes, fillPattern, lumFrom, lumTo){
+		//	summary:
+		//		transforms solid color fills into 2-color gradients using a fill pattern, and two luminance values
+		//	themes: Array:
+		//		Array of mini-themes (usually series themes or marker themes), which fill will be transformed.
+		//	fillPattern: Object:
+		//		Gradient fill descriptor which colors list will be generated.
+		//	lumFrom: Number:
+		//		Initial luminance value (0-100).
+		//	lumTo: Number:
+		//		Final luminance value (0-100).
+		var Theme = dojox.charting.Theme;
+		dojo.forEach(themes, function(t){
+			if(t.fill && !t.fill.type){
+				t.fill = Theme.generateHslGradient(t.fill, fillPattern, lumFrom, lumTo);
+			}
+		});
+	};
+	
+	gg.generateMiniTheme = function(colors, fillPattern, lumFrom, lumTo, lumStroke){
+		//	summary:
+		//		generates mini-themes with 2-color gradients using colors, a fill pattern, and three luminance values
+		//	colors: Array:
+		//		Array of colors to generate gradients for each.
+		//	fillPattern: Object:
+		//		Gradient fill descriptor which colors list will be generated.
+		//	lumFrom: Number:
+		//		Initial luminance value (0-100).
+		//	lumTo: Number:
+		//		Final luminance value (0-100).
+		//	lumStroke: Number:
+		//		Stroke luminance value (0-100).
+		var Theme = dojox.charting.Theme;
+		return dojo.map(colors, function(c){	// Array
+			c = new dojox.color.Color(c);
+			return {
+				fill:   Theme.generateHslGradient(c, fillPattern, lumFrom, lumTo),
+				stroke: {color: Theme.generateHslColor(c, lumStroke)}
+			}
+		});
+	};
+	
+	gg.generateGradientByIntensity = function(color, intensityMap){
+		//	summary:
+		//		generates gradient colors using an intensity map
+		//	color: dojo.Color:
+		//		Color to use to generate gradients.
+		//	intensityMap: Array:
+		//		Array of tuples {o, i}, where o is a gradient offset (0-1),
+		//		and i is an intensity (0-255).
+		color = new dojo.Color(color);
+		return dojo.map(intensityMap, function(stop){	// Array
+			var s = stop.i / 255;
+			return {
+				offset: stop.o,
+				color:  new dojo.Color([color.r * s, color.g * s, color.b * s, color.a])
+			};
+		});
+	}
+})();
\ No newline at end of file
diff --git a/dojox/charting/widget/Chart2D.js b/dojox/charting/widget/Chart2D.js
index f89f548..607b982 100644
--- a/dojox/charting/widget/Chart2D.js
+++ b/dojox/charting/widget/Chart2D.js
@@ -1,16 +1,270 @@
-/*
-	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
-*/
+dojo.provide("dojox.charting.widget.Chart2D");
 
-/*
-	This is a compiled version of Dojo, built for deployment and not for
-	development. To get an editable version, please visit:
+dojo.require("dijit._Widget");
+dojo.require("dojox.charting.Chart2D");
+dojo.require("dojox.lang.functional");
 
-		http://dojotoolkit.org
+// require all actions to support references by name
+dojo.require("dojox.charting.action2d.Highlight");
+dojo.require("dojox.charting.action2d.Magnify");
+dojo.require("dojox.charting.action2d.MoveSlice");
+dojo.require("dojox.charting.action2d.Shake");
+dojo.require("dojox.charting.action2d.Tooltip");
 
-	for documentation and information on getting the source.
-*/
+(function(){
+	var collectParams, collectAxisParams, collectPlotParams,
+		collectActionParams, collectDataParams,
+		notNull = function(o){ return o; },
+		df = dojox.lang.functional,
+		du = dojox.lang.utils,
+		dc = dojox.charting,
+		d = dojo;
+	
+	dojo.declare("dojox.charting.widget.Chart2D", dijit._Widget, {
+		// parameters for the markup
+		
+		// theme for the chart
+		theme: null,
+		
+		// margins for the chart: {l: 10, r: 10, t: 10, b: 10}
+		margins: null,
+		
+		// chart area
+		stroke: null,
+		fill:   null,
+		
+		// methods
+		
+		buildRendering: function(){
+			var n = this.domNode = this.srcNodeRef;
+			
+			// collect chart parameters
+			var axes    = d.query("> .axis", n).map(collectAxisParams).filter(notNull),
+				plots   = d.query("> .plot", n).map(collectPlotParams).filter(notNull),
+				actions = d.query("> .action", n).map(collectActionParams).filter(notNull),
+				series  = d.query("> .series", n).map(collectDataParams).filter(notNull);
+			
+			// build the chart
+			n.innerHTML = "";
+			var c = this.chart = new dc.Chart2D(n, {
+				margins: this.margins, 
+				stroke:  this.stroke,
+				fill:    this.fill
+			});
+			
+			// add collected parameters
+			if(this.theme){
+				c.setTheme(this.theme);
+			}
+			axes.forEach(function(axis){
+				c.addAxis(axis.name, axis.kwArgs);
+			});
+			plots.forEach(function(plot){
+				c.addPlot(plot.name, plot.kwArgs);
+			});
+			
+			this.actions = actions.map(function(action){
+				return new action.action(c, action.plot, action.kwArgs)
+			});
+			
+			var render = df.foldl(series, function(render, series){
+				if(series.type == "data"){
+					c.addSeries(series.name, series.data, series.kwArgs);
+					render = true;
+				}else{
+					c.addSeries(series.name, [0], series.kwArgs);
+					var kw = {};
+					du.updateWithPattern(
+						kw, 
+						series.kwArgs, 
+						{
+							"query": "", 
+							"queryOptions": null, 
+							"start": 0, 
+							"count": 1 //, 
+							// "sort": []
+						}, 
+						true
+					);
+					if(series.kwArgs.sort){
+						// sort is a complex object type and doesn't survive coercian
+						kw.sort = dojo.clone(series.kwArgs.sort);
+					}
+					d.mixin(kw, {
+						onComplete: function(data){
+							var values;
+							if("valueFn" in series.kwArgs){
+								var fn = series.kwArgs.valueFn;
+								values = d.map(data, function(x){
+									return fn(series.data.getValue(x, series.field, 0));
+								});
+							}else{
+								values = d.map(data, function(x){
+									return series.data.getValue(x, series.field, 0);
+								});
+							}
+							c.addSeries(series.name, values, series.kwArgs).render();
+						}
+					});
+					series.data.fetch(kw);
+				}
+				return render;
+			}, false);
+			if(render){ c.render(); }
+		},
+		destroy: function(){
+			// summary: properly destroy the widget
+			this.chart.destroy();
+			this.inherited(arguments);
+		},
+		resize: function(box){
+			// summary: resize the widget
+			if(box.w > 0 && box.h > 0){
+				dojo.marginBox(this.domNode, box);
+				this.chart.resize();
+			}
+		}
+	});
+	
+	collectParams = function(node, type, kw){
+		var dp = eval("(" + type + ".prototype.defaultParams)");
+		var x, attr;
+		for(x in dp){
+			if(x in kw){ continue; }
+			attr = node.getAttribute(x);
+			kw[x] = du.coerceType(dp[x], attr == null || typeof attr == "undefined" ? dp[x] : attr);
+		}
+		var op = eval("(" + type + ".prototype.optionalParams)");
+		for(x in op){
+			if(x in kw){ continue; }
+			attr = node.getAttribute(x);
+			if(attr != null){
+				kw[x] = du.coerceType(op[x], attr);
+			}
+		}
+	};
+	
+	collectAxisParams = function(node){
+		var name = node.getAttribute("name"), type = node.getAttribute("type");
+		if(!name){ return null; }
+		var o = {name: name, kwArgs: {}}, kw = o.kwArgs;
+		if(type){
+			if(dc.axis2d[type]){
+				type = dojox._scopeName + ".charting.axis2d." + type;
+			}
+			var axis = eval("(" + type + ")");
+			if(axis){ kw.type = axis; } 
+		}else{
+			type = dojox._scopeName + ".charting.axis2d.Default";
+		}
+		collectParams(node, type, kw);
+		// compatibility conversions
+		if(kw.font || kw.fontColor){
+			if(!kw.tick){
+				kw.tick = {};
+			}
+			if(kw.font){
+				kw.tick.font = kw.font;
+			}
+			if(kw.fontColor){
+				kw.tick.fontColor = kw.fontColor;
+			}
+		}
+		return o;
+	};
+	
+	collectPlotParams = function(node){
+		// var name = d.attr(node, "name"), type = d.attr(node, "type");
+		var name = node.getAttribute("name"), type = node.getAttribute("type");
+		if(!name){ return null; }
+		var o = {name: name, kwArgs: {}}, kw = o.kwArgs;
+		if(type){
+			if(dc.plot2d[type]){
+				type = dojox._scopeName + ".charting.plot2d." + type;
+			}
+			var plot = eval("(" + type + ")");
+			if(plot){ kw.type = plot; } 
+		}else{
+			type = dojox._scopeName + ".charting.plot2d.Default";
+		}
+		collectParams(node, type, kw);
+		return o;
+	};
+	
+	collectActionParams = function(node){
+		// var plot = d.attr(node, "plot"), type = d.attr(node, "type");
+		var plot = node.getAttribute("plot"), type = node.getAttribute("type");
+		if(!plot){ plot = "default"; }
+		var o = {plot: plot, kwArgs: {}}, kw = o.kwArgs;
+		if(type){
+			if(dc.action2d[type]){
+				type = dojox._scopeName + ".charting.action2d." + type;
+			}
+			var action = eval("(" + type + ")");
+			if(!action){ return null; }
+			o.action = action;
+		}else{
+			return null;
+		}
+		collectParams(node, type, kw);
+		return o;
+	};
 
-if(!dojo._hasResource["dijit._base.manager"]){dojo._hasResource["dijit._base.manager"]=true;dojo.provide("dijit._base.manager");dojo.declare("dijit.WidgetSet",null,{constructor:function(){this._hash={};this.length=0;},add:function(_1){if(this._hash[_1.id]){throw new Error("Tried to register widget with id=="+_1.id+" but that id is already registered");}this._hash[_1.id]=_1;this.length++;},remove:function(id){if(this._hash[id]){delete this._hash[id];this.length--;}},forEach:function(_2,_3 [...]
+	collectDataParams = function(node){
+		var ga = d.partial(d.attr, node);
+		var name = ga("name");
+		if(!name){ return null; }
+		var o = { name: name, kwArgs: {} }, kw = o.kwArgs, t;
+		t = ga("plot");
+		if(t != null){ kw.plot = t; }
+		t = ga("marker");
+		if(t != null){ kw.marker = t; }
+		t = ga("stroke");
+		if(t != null){ kw.stroke = eval("(" + t + ")"); }
+		t = ga("outline");
+		if(t != null){ kw.outline = eval("(" + t + ")"); }
+		t = ga("shadow");
+		if(t != null){ kw.shadow = eval("(" + t + ")"); }
+		t = ga("fill");
+		if(t != null){ kw.fill = eval("(" + t + ")"); }
+		t = ga("font");
+		if(t != null){ kw.font = t; }
+		t = ga("fontColor");
+		if(t != null){ kw.fontColor = eval("(" + t + ")"); }
+		t = ga("legend");
+		if(t != null){ kw.legend = t; }
+		t = ga("data");
+		if(t != null){
+			o.type = "data";
+			o.data = t ? dojo.map(String(t).split(','), Number) : [];
+			return o;
+		}
+		t = ga("array");
+		if(t != null){
+			o.type = "data";
+			o.data = eval("(" + t + ")");
+			return o;
+		}
+		t = ga("store");
+		if(t != null){
+			o.type = "store";
+			o.data = eval("(" + t + ")");
+			t = ga("field");
+			o.field = t != null ? t : "value";
+			t = ga("query");
+			if(!!t){ kw.query = t; }
+			t = ga("queryOptions");
+			if(!!t){ kw.queryOptions = eval("(" + t + ")"); }
+			t = ga("start");
+			if(!!t){ kw.start = Number(t); }
+			t = ga("count");
+			if(!!t){ kw.count = Number(t); }
+			t = ga("sort");
+			if(!!t){ kw.sort = eval("("+t+")"); }
+			t = ga("valueFn");
+			if(!!t){ kw.valueFn = df.lambda(t); }
+			return o;
+		}
+		return null;
+	};
+})();
diff --git a/dojox/charting/widget/Chart2D.js.uncompressed.js b/dojox/charting/widget/Chart2D.js.uncompressed.js
deleted file mode 100644
index 9543db5..0000000
--- a/dojox/charting/widget/Chart2D.js.uncompressed.js
+++ /dev/null
@@ -1,13949 +0,0 @@
-/*
-	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["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 = {};
-		this.length = 0;
-	},
-
-	add: function(/*dijit._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;
-		this.length++;
-	},
-
-	remove: function(/*String*/ id){
-		// summary:
-		//		Remove a widget from this WidgetSet. Does not destroy the widget; simply
-		//		removes the reference.
-		if(this._hash[id]){
-			delete this._hash[id];
-			this.length--;
-		}
-	},
-
-	forEach: function(/*Function*/ func, /* Object? */thisObj){
-		// summary:
-		//		Call specified function for each widget in this set.
-		//
-		// func:
-		//		A callback function to run for each item. Is passed the widget, the index
-		//		in the iteration, and the full hash, similar to `dojo.forEach`.
-		//
-		// thisObj:
-		//		An optional scope parameter
-		//
-		// example:
-		//		Using the default `dijit.registry` instance:
-		//		|	dijit.registry.forEach(function(widget){
-		//		|		console.log(widget.declaredClass);
-		//		|	});
-		//
-		// returns:
-		//		Returns self, in order to allow for further chaining.
-
-		thisObj = thisObj || dojo.global;
-		var i = 0, id;
-		for(id in this._hash){
-			func.call(thisObj, this._hash[id], i++, this._hash);
-		}
-		return this;	// dijit.WidgetSet
-	},
-
-	filter: function(/*Function*/ filter, /* Object? */thisObj){
-		// 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. Is passed the widget
-		//		reference and the pseudo-index in the object.
-		//
-		// thisObj: Object?
-		//		Option scope to use for the filter function.
-		//
-		// example:
-		//		Arbitrary: select the odd widgets in this list
-		//		|	dijit.registry.filter(function(w, i){
-		//		|		return i % 2 == 0;
-		//		|	}).forEach(function(w){ /* odd ones */ });
-
-		thisObj = thisObj || dojo.global;
-		var res = new dijit.WidgetSet(), i = 0, id;
-		for(id in this._hash){
-			var w = this._hash[id];
-			if(filter.call(thisObj, w, i++, this._hash)){
-				res.add(w);
-			}
-		}
-		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`
-		//
-		// cls: String
-		//		The Class to scan for. Full dot-notated string.
-		//
-		// example:
-		//		Find all `dijit.TitlePane`s in a page:
-		//		|	dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); });
-
-		var res = new dijit.WidgetSet(), id, widget;
-		for(id in this._hash){
-			widget = this._hash[id];
-			if(widget.declaredClass == cls){
-				res.add(widget);
-			}
-		 }
-		 return res; // dijit.WidgetSet
-},
-
-	toArray: function(){
-		// summary:
-		//		Convert this WidgetSet into a true Array
-		//
-		// example:
-		//		Work with the widget .domNodes in a real Array
-		//		|	dojo.map(dijit.registry.toArray(), function(w){ return w.domNode; });
-
-		var ar = [];
-		for(var id in this._hash){
-			ar.push(this._hash[id]);
-		}
-		return ar;	// dijit._Widget[]
-},
-
-	map: function(/* Function */func, /* Object? */thisObj){
-		// summary:
-		//		Create a new Array from this WidgetSet, following the same rules as `dojo.map`
-		// example:
-		//		|	var nodes = dijit.registry.map(function(w){ return w.domNode; });
-		//
-		// returns:
-		//		A new array of the returned values.
-		return dojo.map(this.toArray(), func, thisObj); // Array
-	},
-
-	every: function(func, thisObj){
-		// summary:
-		// 		A synthetic clone of `dojo.every` acting explictly on this WidgetSet
-		//
-		// func: Function
-		//		A callback function run for every widget in this list. Exits loop
-		//		when the first false return is encountered.
-		//
-		// thisObj: Object?
-		//		Optional scope parameter to use for the callback
-
-		thisObj = thisObj || dojo.global;
-		var x = 0, i;
-		for(i in this._hash){
-			if(!func.call(thisObj, this._hash[i], x++, this._hash)){
-				return false; // Boolean
-			}
-		}
-		return true; // Boolean
-	},
-
-	some: function(func, thisObj){
-		// summary:
-		// 		A synthetic clone of `dojo.some` acting explictly on this WidgetSet
-		//
-		// func: Function
-		//		A callback function run for every widget in this list. Exits loop
-		//		when the first true return is encountered.
-		//
-		// thisObj: Object?
-		//		Optional scope parameter to use for the callback
-
-		thisObj = thisObj || dojo.global;
-		var x = 0, i;
-		for(i in this._hash){
-			if(func.call(thisObj, this._hash[i], x++, this._hash)){
-				return true; // Boolean
-			}
-		}
-		return false; // Boolean
-	}
-
-});
-
-/*=====
-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 dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
-};
-
-dijit.findWidgets = function(/*DomNode*/ root){
-	// summary:
-	//		Search subtree under root returning widgets found.
-	//		Doesn't search for nested widgets (ie, widgets inside other widgets).
-
-	var outAry = [];
-
-	function getChildrenHelper(root){
-		for(var node = root.firstChild; node; node = node.nextSibling){
-			if(node.nodeType == 1){
-				var widgetId = node.getAttribute("widgetId");
-				if(widgetId){
-					var widget = dijit.byId(widgetId);
-					outAry.push(widget);
-				}else{
-					getChildrenHelper(node);
-				}
-			}
-		}
-	}
-
-	getChildrenHelper(root);
-	return outAry;
-};
-
-dijit._destroyAll = function(){
-	// summary:
-	//		Code to destroy all widgets and do other cleanup on page unload
-
-	// Clean up focus manager lingering references to widgets and nodes
-	dijit._curFocus = null;
-	dijit._prevFocus = null;
-	dijit._activeStack = [];
-
-	// Destroy all the widgets, top down
-	dojo.forEach(dijit.findWidgets(dojo.body()), function(widget){
-		// Avoid double destroy of widgets like Menu that are attached to <body>
-		// even though they are logically children of other widgets.
-		if(!widget._destroyed){
-			if(widget.destroyRecursive){
-				widget.destroyRecursive();
-			}else if(widget.destroy){
-				widget.destroy();
-			}
-		}
-	});
-};
-
-if(dojo.isIE){
-	// Only run _destroyAll() 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(){
-		dijit._destroyAll();
-	});
-}
-
-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 typeof id == "string" ? dijit.registry._hash[id] : id; // dijit._Widget
-};
-
-dijit.byNode = function(/* DOMNode */ node){
-	// summary:
-	//		Returns the widget corresponding to the given DOMNode
-	return dijit.registry.byId(node.getAttribute("widgetId")); // dijit._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){
-		var id = node.getAttribute && node.getAttribute("widgetId");
-		if(id){
-			return dijit.byId(id);
-		}
-		node = node.parentNode;
-	}
-	return null;
-};
-
-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
-
-	// TODO: convert (and rename method) to return effectivite tabIndex; will save time in _getTabNavigable()
-	if(dojo.attr(elem, "disabled")){
-		return false;
-	}else if(dojo.hasAttr(elem, "tabIndex")){
-		// Explicit tab index setting
-		return dojo.attr(elem, "tabIndex") >= 0; // boolean
-	}else{
-		// No explicit tabIndex setting, need to investigate node type
-		switch(elem.nodeName.toLowerCase()){
-			case "a":
-				// An <a> w/out a tabindex is only navigable if it has an href
-				return dojo.hasAttr(elem, "href");
-			case "area":
-			case "button":
-			case "input":
-			case "object":
-			case "select":
-			case "textarea":
-				// These are navigable by default
-				return true;
-			case "iframe":
-				// If it's an editor <iframe> then it's tab navigable.
-				if(dojo.isMoz){
-					return elem.contentDocument.designMode == "on";
-				}else if(dojo.isWebKit){
-					var doc = elem.contentDocument,
-						body = doc && doc.body;
-					return body && body.contentEditable == 'true';
-				}else{
-					// contentWindow.document isn't accessible within IE7/8
-					// if the iframe.src points to a foreign url and this
-					// page contains an element, that could get focus
-					try{
-						doc = elem.contentWindow.document;
-						body = doc && doc.body;
-						return body && body.firstChild && body.firstChild.contentEditable == 'true';
-					}catch(e){
-						return false;
-					}
-				}
-			default:
-				return elem.contentEditable == 'true';
-		}
-	}
-};
-
-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["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");
-
-	// for dijit.isTabNavigable()
-
-// summary:
-//		These functions are used to query or set the focus and selection.
-//
-//		Also, they trace when widgets become activated/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
-		return dijit.getBookmark().isCollapsed;
-	},
-
-	getBookmark: function(){
-		// summary:
-		//		Retrieves a bookmark that can be used with moveToBookmark to return to the same range
-		var bm, rg, tg, sel = dojo.doc.selection, cf = dijit._curFocus;
-
-		if(dojo.global.getSelection){
-			//W3C Range API for selections.
-			sel = dojo.global.getSelection();
-			if(sel){
-				if(sel.isCollapsed){
-					tg = cf? cf.tagName : "";
-					if(tg){
-						//Create a fake rangelike item to restore selections.
-						tg = tg.toLowerCase();
-						if(tg == "textarea" ||
-								(tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
-							sel = {
-								start: cf.selectionStart,
-								end: cf.selectionEnd,
-								node: cf,
-								pRange: true
-							};
-							return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
-						}
-					}
-					bm = {isCollapsed:true};
-				}else{
-					rg = sel.getRangeAt(0);
-					bm = {isCollapsed: false, mark: rg.cloneRange()};
-				}
-			}
-		}else if(sel){
-			// If the current focus was a input of some sort and no selection, don't bother saving
-			// a native bookmark.  This is because it causes issues with dialog/page selection restore.
-			// So, we need to create psuedo bookmarks to work with.
-			tg = cf ? cf.tagName : "";
-			tg = tg.toLowerCase();
-			if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
-				if(sel.type && sel.type.toLowerCase() == "none"){
-					return {
-						isCollapsed: true,
-						mark: null
-					}
-				}else{
-					rg = sel.createRange();
-					return {
-						isCollapsed: rg.text && rg.text.length?false:true,
-						mark: {
-							range: rg,
-							pRange: true
-						}
-					};
-				}
-			}
-			bm = {};
-
-			//'IE' way for selections.
-			try{
-				// createRange() throws exception when dojo in iframe
-				//and nothing selected, see #9632
-				rg = sel.createRange();
-				bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
-			}catch(e){
-				bm.isCollapsed = true;
-				return bm;
-			}
-			if(sel.type.toUpperCase() == 'CONTROL'){
-				if(rg.length){
-					bm.mark=[];
-					var i=0,len=rg.length;
-					while(i<len){
-						bm.mark.push(rg.item(i++));
-					}
-				}else{
-					bm.isCollapsed = true;
-					bm.mark = null;
-				}
-			}else{
-				bm.mark = rg.getBookmark();
-			}
-		}else{
-			console.warn("No idea how to store the current selection for this browser!");
-		}
-		return bm; // Object
-	},
-
-	moveToBookmark: function(/*Object*/bookmark){
-		// summary:
-		//		Moves current selection to a bookmark
-		// bookmark:
-		//		This should be a returned object from dijit.getBookmark()
-
-		var _doc = dojo.doc,
-			mark = bookmark.mark;
-		if(mark){
-			if(dojo.global.getSelection){
-				//W3C Rangi API (FF, WebKit, Opera, etc)
-				var sel = dojo.global.getSelection();
-				if(sel && sel.removeAllRanges){
-					if(mark.pRange){
-						var r = mark;
-						var n = r.node;
-						n.selectionStart = r.start;
-						n.selectionEnd = r.end;
-					}else{
-						sel.removeAllRanges();
-						sel.addRange(mark);
-					}
-				}else{
-					console.warn("No idea how to restore selection for this browser!");
-				}
-			}else if(_doc.selection && mark){
-				//'IE' way.
-				var rg;
-				if(mark.pRange){
-					rg = mark.range;
-				}else if(dojo.isArray(mark)){
-					rg = _doc.body.createControlRange();
-					//rg.addElement does not have call/apply method, so can not call it directly
-					//rg is not available in "range.addElement(item)", so can't use that either
-					dojo.forEach(mark, function(n){
-						rg.addElement(n);
-					});
-				}else{
-					rg = _doc.body.createTextRange();
-					rg.moveToBookmark(mark);
-				}
-				rg.select();
-			}
-		}
-	},
-
-	getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){
-		// summary:
-		//		Called as getFocus(), this returns an Object showing the current focus
-		//		and selected text.
-		//
-		//		Called as getFocus(widget), where widget is a (widget representing) a button
-		//		that was just pressed, it returns where focus was before that button
-		//		was pressed.   (Pressing the button may have either shifted focus to the button,
-		//		or removed focus altogether.)   In this case the selected text is not returned,
-		//		since it can't be accurately determined.
-		//
-		// menu: dijit._Widget or {domNode: DomNode} structure
-		//		The button that was just pressed.  If focus has disappeared or moved
-		//		to this button, returns the previous focus.  In this case the bookmark
-		//		information is already lost, and null is returned.
-		//
-		// openedForWindow:
-		//		iframe in which menu was opened
-		//
-		// returns:
-		//		A handle to restore focus/selection, to be passed to `dijit.focus`
-		var node = !dijit._curFocus || (menu && dojo.isDescendant(dijit._curFocus, menu.domNode)) ? dijit._prevFocus : dijit._curFocus;
-		return {
-			node: node,
-			bookmark: (node == dijit._curFocus) && dojo.withGlobal(openedForWindow || dojo.global, dijit.getBookmark),
-			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,
-			collapsed = bookmark ? bookmark.isCollapsed : false;
-
-		// 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) or if previous selection was collapsed
-		// as it may cause focus shift (Esp in IE).
-		if(bookmark && dojo.withGlobal(openedForWindow || dojo.global, dijit.isCollapsed) && !collapsed){
-			if(openedForWindow){
-				openedForWindow.focus();
-			}
-			try{
-				dojo.withGlobal(openedForWindow || dojo.global, dijit.moveToBookmark, null, [bookmark]);
-			}catch(e2){
-				/*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
-			}
-		}
-	},
-
-	// _activeStack: dijit._Widget[]
-	//		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.
-		// returns:
-		//		Handle to pass to unregisterIframe()
-		return dijit.registerWin(iframe.contentWindow, iframe);
-	},
-
-	unregisterIframe: function(/*Object*/ handle){
-		// summary:
-		//		Unregisters listeners on the specified iframe created by registerIframe.
-		//		After calling be sure to delete or null out the handle itself.
-		// handle:
-		//		Handle returned by registerIframe()
-
-		dijit.unregisterWin(handle);
-	},
-
-	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.
-		// returns:
-		//		Handle to pass to unregisterWin()
-
-		// TODO: make this function private in 2.0; Editor/users should call registerIframe(),
-
-		var mousedownListener = function(evt){
-			dijit._justMouseDowned = true;
-			setTimeout(function(){ dijit._justMouseDowned = false; }, 0);
-			dijit._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse");
-		};
-		//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.
-		// Connect to <html> (rather than document) on IE to avoid memory leaks, but document on other browsers because
-		// (at least for FF) the focus event doesn't fire on <html> or <body>.
-		var doc = dojo.isIE ? targetWindow.document.documentElement : targetWindow.document;
-		if(doc){
-			if(dojo.isIE){
-				doc.attachEvent('onmousedown', mousedownListener);
-				var activateListener = function(evt){
-					// IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
-					// Should consider those more like a mouse-click than a focus....
-					if(evt.srcElement.tagName.toLowerCase() != "#document" &&
-						dijit.isTabNavigable(evt.srcElement)){
-						dijit._onFocusNode(effectiveNode || evt.srcElement);
-					}else{
-						dijit._onTouchNode(effectiveNode || evt.srcElement);
-					}
-				};
-				doc.attachEvent('onactivate', activateListener);
-				var deactivateListener =  function(evt){
-					dijit._onBlurNode(effectiveNode || evt.srcElement);
-				};
-				doc.attachEvent('ondeactivate', deactivateListener);
-
-				return function(){
-					doc.detachEvent('onmousedown', mousedownListener);
-					doc.detachEvent('onactivate', activateListener);
-					doc.detachEvent('ondeactivate', deactivateListener);
-					doc = null;	// prevent memory leak (apparent circular reference via closure)
-				};
-			}else{
-				doc.addEventListener('mousedown', mousedownListener, true);
-				var focusListener = function(evt){
-					dijit._onFocusNode(effectiveNode || evt.target);
-				};
-				doc.addEventListener('focus', focusListener, true);
-				var blurListener = function(evt){
-					dijit._onBlurNode(effectiveNode || evt.target);
-				};
-				doc.addEventListener('blur', blurListener, true);
-
-				return function(){
-					doc.removeEventListener('mousedown', mousedownListener, true);
-					doc.removeEventListener('focus', focusListener, true);
-					doc.removeEventListener('blur', blurListener, true);
-					doc = null;	// prevent memory leak (apparent circular reference via closure)
-				};
-			}
-		}
-	},
-
-	unregisterWin: function(/*Handle*/ handle){
-		// summary:
-		//		Unregisters listeners on the specified window (either the main
-		//		window or an iframe's window) according to handle returned from registerWin().
-		//		After calling be sure to delete or null out the handle itself.
-
-		// Currently our handle is actually a function
-		handle && handle();
-	},
-
-	_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, /*String*/ by){
-		// summary:
-		//		Callback when node is focused or mouse-downed
-		// node:
-		//		The node that was touched.
-		// by:
-		//		"mouse" if the focus/touch was caused by a mouse down event
-
-		// 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){
-				var popupParent = dojo.attr(node, "dijitPopupParent");
-				if(popupParent){
-					node=dijit.byId(popupParent).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, by);
-	},
-
-	_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(/*String[]*/ newStack, /*String*/ by){
-		// summary:
-		//		The stack of active widgets has changed.  Send out appropriate events and records new stack.
-		// newStack:
-		//		array of widget id's, starting from the top (outermost) widget
-		// by:
-		//		"mouse" if the focus/touch was caused by a mouse down event
-
-		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;
-			}
-		}
-
-		var widget;
-		// for all elements that have gone out of focus, send blur event
-		for(var i=oldStack.length-1; i>=nCommon; i--){
-			widget = dijit.byId(oldStack[i]);
-			if(widget){
-				widget._focused = false;
-				widget._hasBeenBlurred = true;
-				if(widget._onBlur){
-					widget._onBlur(by);
-				}
-				if(widget._setStateClass){
-					widget._setStateClass();
-				}
-				dojo.publish("widgetBlur", [widget, by]);
-			}
-		}
-
-		// 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(by);
-				}
-				if(widget._setStateClass){
-					widget._setStateClass();
-				}
-				dojo.publish("widgetFocus", [widget, by]);
-			}
-		}
-	}
-});
-
-// register top window and all the iframes it contains
-dojo.addOnLoad(function(){
-	var handle = dijit.registerWin(window);
-	if(dojo.isIE){
-		dojo.addOnWindowUnload(function(){
-			dijit.unregisterWin(handle);
-			handle = null;
-		})
-	}
-});
-
-}
-
-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 = Math.max(view.l, corner.charAt(1) == 'L' ? pos.x : (pos.x - mb.w)),
-			startY = Math.max(view.t, corner.charAt(0) == 'T' ? pos.y : (pos.y - mb.h)),
-			endX = Math.min(view.l + view.w, corner.charAt(1) == 'L' ? (startX + mb.w) : pos.x),
-			endY = Math.min(view.t + view.h, corner.charAt(0) == 'T' ? (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 aroundNodePos = dojo.position(aroundNode, true);
-	aroundNode.style.display=oldDisplay;
-
-	// place the node around the calculated rectangle
-	return dijit._placeOnScreenAroundRect(node,
-		aroundNodePos.x, aroundNodePos.y, aroundNodePos.w, aroundNodePos.h,	// 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
-
-	this.x = x;
-	this.y = y;
-	this.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);
-};
-
-dijit.getPopupAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
-	// summary:
-	//		Transforms the passed array of preferred positions into a format suitable for passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
-	//
-	// position: String[]
-	//		This variable controls the position of the drop down.
-	//		It's an array of strings with the following values:
-	//
-	//			* before: places drop down to the left of the target node/widget, or to the right in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* after: places drop down to the right of the target node/widget, or to the left in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* above: drop down goes above target node
-	//			* below: drop down goes below target node
-	//
-	//		The list is positions is tried, in order, until a position is found where the drop down fits
-	//		within the viewport.
-	//
-	// leftToRight: Boolean
-	//		Whether the popup will be displaying in leftToRight mode.
-	//
-	var align = {};
-	dojo.forEach(position, function(pos){
-		switch(pos){
-			case "after":
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
-				break;
-			case "before":
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
-				break;
-			case "below":
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "TL" : "TR";
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "TR" : "TL";
-				break;
-			case "above":
-			default:
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "TL" : "TR"] = leftToRight ? "BL" : "BR";
-				align[leftToRight ? "TR" : "TL"] = leftToRight ? "BR" : "BL";
-				break;
-		}
-	});
-	return align;
-};
-dijit.getPopupAroundAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
-	// summary:
-	//		Transforms the passed array of preferred positions into a format suitable for passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
-	//
-	// position: String[]
-	//		This variable controls the position of the drop down.
-	//		It's an array of strings with the following values:
-	//
-	//			* before: places drop down to the left of the target node/widget, or to the right in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* after: places drop down to the right of the target node/widget, or to the left in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* above: drop down goes above target node
-	//			* below: drop down goes below target node
-	//
-	//		The list is positions is tried, in order, until a position is found where the drop down fits
-	//		within the viewport.
-	//
-	// leftToRight: Boolean
-	//		Whether the popup will be displaying in leftToRight mode.
-	//
-	var align = {};
-	dojo.forEach(position, function(pos){
-		switch(pos){
-			case "after":
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
-				break;
-			case "before":
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
-				break;
-			case "below":
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "TL" : "TR";
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "TR" : "TL";
-				break;
-			case "above":
-			default:
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "TL" : "TR"] = leftToRight ? "BL" : "BR";
-				align[leftToRight ? "TR" : "TL"] = leftToRight ? "BR" : "BL";
-				break;
-		}
-	});
-	return align;
-};
-
-}
-
-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.moveOffScreen = function(/*DomNode*/ node){
-		// summary:
-		//		Moves node offscreen without hiding it (so that all layout widgets included 
-		//		in this node can still layout properly)
-		//
-		// 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;
-}
-=====*/
-
-	// 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];
-	};
-
-	var wrappers=[];
-	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 || (
-				dojo._isBodyLtr() ?
-				{'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'} :
-				{'BR':'TR', 'BL':'TL', 'TR':'BR', '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 wrapperobj = wrappers.pop(), wrapper, iframe;
-		if(!wrapperobj){
-			wrapper = dojo.create("div",{
-				"class":"dijitPopup"
-			}, dojo.body());
-			dijit.setWaiRole(wrapper, "presentation");
-		}else{
-			// recycled a old wrapper, so that we don't need to reattach the iframe
-			// which is slow even if the iframe is empty, see #10167
-			wrapper = wrapperobj[0];
-			iframe = wrapperobj[1];
-		}
-
-		dojo.attr(wrapper,{
-			id: id,
-			style:{
-				zIndex: beginZIndex + stack.length,
-				visibility:"hidden",
-				// prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
-				top: "-9999px"
-			},
-			dijitPopupParent: args.parent ? args.parent.id : ""
-		});
-
-		var s = widget.domNode.style;
-		s.display = "";
-		s.visibility = "";
-		s.position = "";
-		s.top = "0px";
-		wrapper.appendChild(widget.domNode);
-
-		if(!iframe){
-			iframe = new dijit.BackgroundIframe(wrapper);
-		}else{
-			iframe.resize(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 = [];
-
-		// 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", args.onCancel));
-		}
-
-		handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", 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){
-			// TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here)
-			widget.onOpen(best);
-		}
-
-		return best;
-	};
-
-	this.close = function(/*dijit._Widget*/ popup){
-		// summary:
-		//		Close specified popup and any popups that it parented
-		
-		// Basically work backwards from the top of the stack closing popups
-		// until we hit the specified popup, but IIRC there was some issue where closing
-		// a popup would cause others to close too.  Thus if we are trying to close B in [A,B,C]
-		// closing C might close B indirectly and then the while() condition will run where stack==[A]...
-		// so the while condition is constructed defensively.
-		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){
-				// TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here)
-				widget.onClose();
-			}
-			dojo.forEach(top.handlers, dojo.disconnect);
-
-			// Move the widget offscreen, unless it has already been destroyed in above onClose() etc.
-			if(widget && widget.domNode){
-				this.moveOffScreen(widget.domNode);
-			}
-                        
-			// recycle the wrapper plus iframe, so we prevent reattaching iframe everytime an popup opens
-			// don't use moveOffScreen which would also reattach the wrapper to body, which causes reloading of iframe
-			wrapper.style.top = "-9999px";
-			wrapper.style.visibility = "hidden";
-			wrappers.push([wrapper,iframe]);
-
-			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";
-				dojo.style(iframe, "opacity", 0.1);
-			}
-			iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didnt work.
-		}
-		return iframe;
-	};
-
-	this.push = function(iframe){
-		iframe.style.display="none";
-		queue.push(iframe);
-	}
-}();
-
-
-dijit.BackgroundIframe = function(/* DomNode */node){
-	// summary:
-	//		For IE/FF 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 || dojo.isMoz){
-		var iframe = dijit._frames.pop();
-		node.appendChild(iframe);
-		if(dojo.isIE<7){
-			this.resize(node);
-			this._conn = dojo.connect(node, 'onresize', this, function(){
-				this.resize(node);
-			});
-		}else{
-			dojo.style(iframe, {
-				width: '100%',
-				height: '100%'
-			});
-		}
-		this.iframe = iframe;
-	}
-};
-
-dojo.extend(dijit.BackgroundIframe, {
-	resize: function(node){
-		// summary:
-		// 		resize the iframe so its the same size as node
-		// description:
-		//		this function is a no-op in all browsers except
-		//		IE6, which does not support 100% width/height 
-		//		of absolute positioned iframes
-		if(this.iframe && dojo.isIE<7){
-			dojo.style(this.iframe, {
-				width: node.offsetWidth + 'px',
-				height: node.offsetHeight + 'px'
-			});
-		}
-	},
-	destroy: function(){
-		// summary:
-		//		destroy the iframe
-		if(this._conn){
-			dojo.disconnect(this._conn);
-			this._conn = null;
-		}
-		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, /*Object?*/ pos){
-	// summary:
-	//		Scroll the passed node into view, if it is not already.
-	
-	// don't rely on that node.scrollIntoView works just because the function is there
-
-	try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
-	node = dojo.byId(node);
-	var doc = node.ownerDocument || dojo.doc,
-		body = doc.body || dojo.body(),
-		html = doc.documentElement || body.parentNode,
-		isIE = dojo.isIE, isWK = dojo.isWebKit;
-	// if an untested browser, then use the native method
-	if((!(dojo.isMoz || isIE || isWK) || node == body || node == html) && (typeof node.scrollIntoView != "undefined")){
-		node.scrollIntoView(false); // short-circuit to native if possible
-		return;
-	}
-	var backCompat = doc.compatMode == 'BackCompat',
-		clientAreaRoot = backCompat? body : html,
-		scrollRoot = isWK ? body : clientAreaRoot,
-		rootWidth = clientAreaRoot.clientWidth,
-		rootHeight = clientAreaRoot.clientHeight,
-		rtl = !dojo._isBodyLtr(),
-		nodePos = pos || dojo.position(node),
-		el = node.parentNode,
-		isFixed = function(el){
-			return ((isIE <= 6 || (isIE && backCompat))? false : (dojo.style(el, 'position').toLowerCase() == "fixed"));
-		};
-	if(isFixed(node)){ return; } // nothing to do
-	while(el){
-		if(el == body){ el = scrollRoot; }
-		var elPos = dojo.position(el),
-			fixedPos = isFixed(el);
-		with(elPos){
-			if(el == scrollRoot){
-				w = rootWidth, h = rootHeight;
-				if(scrollRoot == html && isIE && rtl){ x += scrollRoot.offsetWidth-w; } // IE workaround where scrollbar causes negative x
-				if(x < 0 || !isIE){ x = 0; } // IE can have values > 0
-				if(y < 0 || !isIE){ y = 0; }
-			}else{
-				var pb = dojo._getPadBorderExtents(el);
-				w -= pb.w; h -= pb.h; x += pb.l; y += pb.t;
-			}
-			with(el){
-				if(el != scrollRoot){ // body, html sizes already have the scrollbar removed
-					var clientSize = clientWidth,
-						scrollBarSize = w - clientSize;
-					if(clientSize > 0 && scrollBarSize > 0){
-						w = clientSize;
-						if(isIE && rtl){ x += scrollBarSize; }
-					}
-					clientSize = clientHeight;
-					scrollBarSize = h - clientSize;
-					if(clientSize > 0 && scrollBarSize > 0){
-						h = clientSize;
-					}
-				}
-				if(fixedPos){ // bounded by viewport, not parents
-					if(y < 0){
-						h += y, y = 0;
-					}
-					if(x < 0){
-						w += x, x = 0;
-					}
-					if(y + h > rootHeight){
-						h = rootHeight - y;
-					}
-					if(x + w > rootWidth){
-						w = rootWidth - x;
-					}
-				}
-				// calculate overflow in all 4 directions
-				var l = nodePos.x - x, // beyond left: < 0
-					t = nodePos.y - Math.max(y, 0), // beyond top: < 0
-					r = l + nodePos.w - w, // beyond right: > 0
-					bot = t + nodePos.h - h; // beyond bottom: > 0
-				if(r * l > 0){
-					var s = Math[l < 0? "max" : "min"](l, r);
-					nodePos.x += scrollLeft;
-					scrollLeft += (isIE >= 8 && !backCompat && rtl)? -s : s;
-					nodePos.x -= scrollLeft;
-				}
-				if(bot * t > 0){
-					nodePos.y += scrollTop;
-					scrollTop += Math[t < 0? "max" : "min"](t, bot);
-					nodePos.y -= scrollTop;
-				}
-			}
-		}
-		el = (el != scrollRoot) && !fixedPos && el.parentNode;
-	}
-	}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_ie6: maj(ie) == 6,
-			dj_ie7: maj(ie) == 7,
-			dj_ie8: maj(ie) == 8,
-			dj_iequirks: ie && d.isQuirks,
-
-			// NOTE: Opera not supported by dijit
-			dj_opera: opera,
-
-			dj_khtml: d.isKhtml,
-
-			dj_webkit: d.isWebKit,
-			dj_safari: d.isSafari,
-			dj_chrome: d.isChrome,
-
-			dj_gecko: d.isMozilla,
-			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);
-		
-		// Schedule next event, reducing the timer a little bit each iteration, bottoming-out at 10 to avoid
-		// browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup)
-		this._currentTimeout = Math.max(
-			this._currentTimeout < 0 ? this._initialDelay :
-				(this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)),
-			10);
-		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.altKey) &&
-				(keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey
-				(keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){
-					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:
-		//		Replace existing role attribute with new role.
-		//		If elem already has an XHTML role, append this role to XHTML role
-		//		and remove other ARIA roles.
-
-		var curRole = dojo.attr(elem, "role") || "";
-		if(!this._XhtmlRoles.test(curRole)){
-			dojo.attr(elem, "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 t = dojo.trim((" " + roleValue + " ").replace(" " + role + " ", " "));
-			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:
-		//		Checks for an attribute called "aria-"+state.
-		// returns:
-		//		true if elem has a value for the given state and
-		//		false if it does not.
-
-		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:
-		//		Checks 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.
-
-		return elem.getAttribute("aria-"+state) || "";
-	},
-
-	setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
-		// summary:
-		//		Sets a state on an element.
-		// description:
-		//		Sets an attribute called "aria-"+state.
-
-		elem.setAttribute("aria-"+state, value);
-	},
-
-	removeWaiState: function(/*Element*/ elem, /*String*/ state){
-		// summary:
-		//		Removes a state from an element.
-		// description:
-		//		Sets an attribute called "aria-"+state.
-
-		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" );
-
-
-// This code is to assist deferring dojo.connect() calls in widgets (connecting to events on the widgets'
-// DOM nodes) until someone actually needs to monitor that event.
-dojo.connect(dojo, "_connect",
-	function(/*dijit._Widget*/ widget, /*String*/ event){
-		if(widget && dojo.isFunction(widget._onConnect)){
-			widget._onConnect(event);
-		}
-	});
-
-dijit._connectOnUseEventHandler = function(/*Event*/ event){};
-
-// Keep track of where the last keydown event was, to help avoid generating
-// spurious ondijitclick events when:
-// 1. focus is on a <button> or <a>
-// 2. user presses then releases the ENTER key
-// 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
-// 4. onkeyup event fires, causing the ondijitclick handler to fire
-dijit._lastKeyDownNode = null;
-if(dojo.isIE){
-	(function(){
-		var keydownCallback = function(evt){
-			dijit._lastKeyDownNode = evt.srcElement;
-		};
-		dojo.doc.attachEvent('onkeydown', keydownCallback);
-		dojo.addOnWindowUnload(function(){
-			dojo.doc.detachEvent('onkeydown', keydownCallback);
-		});
-	})();
-}else{
-	dojo.doc.addEventListener('keydown', function(evt){
-		dijit._lastKeyDownNode = evt.target;
-	}, true);
-}
-
-(function(){
-
-var _attrReg = {},	// cached results from getSetterAttributes
-	getSetterAttributes = function(widget){
-		// summary:
-		//		Returns list of attributes with custom setters for specified widget
-		var dc = widget.declaredClass;
-		if(!_attrReg[dc]){
-			var r = [],
-				attrs,
-				proto = widget.constructor.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] || [];	// String[]
-	};
-
-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.
-	//
-	//		For form widgets this specifies a tooltip to display when hovering over
-	//		the widget (just like the native HTML title attribute).
-	//
-	//		For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
-	//		etc., it's used to specify the tab label, accordion pane title, etc.
-	title: "",
-
-	// tooltip: String
-	//		When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
-	//		this specifies the tooltip to appear when the mouse is hovered over that text.
-	tooltip: "",
-
-	// 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,
-
-/*=====
-	// _started: Boolean
-	//		startup() has completed.
-	_started: false,
-=====*/
-
-	// 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 innerText
-	//	|		title: { node: "titleNode", type: "innerText" }
-	//		Maps this.title to this.titleNode.innerText
-	//
-	//		- 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] String
-	//		Path to a blank 1x1 image.
-	//		Used by <img> nodes in templates that really get their image via CSS background-image.
-	_blankGif: (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")).toString(),
-
-	//////////// 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:
-		//		Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
-		//		etc.), some of which of you'll want to override. See http://docs.dojocampus.org/dijit/_Widget
-		//		for a discussion of the widget creation lifecycle.
-		//
-		//		Of course, adventurous developers could override create entirely, but this should
-		//		only be done as a last resort.
-		// 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 = [];
-
-		// For garbage collection.  An array of handles returned by Widget.subscribe()
-		// The handle returned from Widget.subscribe() is the handle returned from dojo.subscribe()
-		this._subscribes = [];
-
-		// 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]);
-			}
-		};
-
-		// Do the attributes in attributeMap
-		for(var attr in this.attributeMap){
-			condAttrApply(attr, this);
-		}
-
-		// And also any attributes with custom setters
-		dojo.forEach(getSetterAttributes(this), 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
-		// description:
-		//		Most widgets will mixin `dijit._Templated`, which implements this
-		//		method.
-		// tags:
-		//		protected
-		this.domNode = this.srcNodeRef || dojo.create('div');
-	},
-
-	postCreate: function(){
-		// summary:
-		//		Processing after the DOM fragment is created
-		// description:
-		//		Called after the DOM fragment has been created, but not necessarily
-		//		added to the document.  Do not include any operations which rely on
-		//		node dimensions or placement.
-		// tags:
-		//		protected
-	},
-
-	startup: function(){
-		// summary:
-		//		Processing after the DOM fragment is added to the document
-		// description:
-		//		Called after a widget and its children have been created and added to the page,
-		//		and all related widgets have finished their create() cycle, up through postCreate().
-		//		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 its descendants
-		// description:
-		//		This is the generic "destructor" function that all widget users
-		// 		should call to cleanly discard with a widget. Once a widget is
-		// 		destroyed, it is 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._beingDestroyed = true;
-		this.destroyDescendants(preserveDom);
-		this.destroy(preserveDom);
-	},
-
-	destroy: function(/*Boolean*/ preserveDom){
-		// summary:
-		// 		Destroy this widget, but not its descendants.
-		//		This method 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._beingDestroyed = true;
-		this.uninitialize();
-		var d = dojo,
-			dfe = d.forEach,
-			dun = d.unsubscribe;
-		dfe(this._connects, function(array){
-			dfe(array, d.disconnect);
-		});
-		dfe(this._subscribes, function(handle){
-			dun(handle);
-		});
-
-		// destroy widgets created as part of template, etc.
-		dfe(this._supportingWidgets || [], function(w){
-			if(w.destroyRecursive){
-				w.destroyRecursive();
-			}else if(w.destroy){
-				w.destroy();
-			}
-		});
-
-		this.destroyRendering(preserveDom);
-		dijit.registry.remove(this.id);
-		this._destroyed = true;
-	},
-
-	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, innerText, or attribute
-
-			switch(type){
-				case "attribute":
-					if(dojo.isFunction(value)){ // functions execute in the context of the widget
-						value = dojo.hitch(this, value);
-					}
-
-					// Get the name of the DOM node attribute; usually it's the same
-					// as the name of the attribute in the widget (attr), but can be overridden.
-					// Also maps handler names to lowercase, like onSubmit --> onsubmit
-					var attrName = command.attribute ? command.attribute :
-						(/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
-
-					dojo.attr(mapNode, attrName, value);
-					break;
-				case "innerText":
-					mapNode.innerHTML = "";
-					mapNode.appendChild(dojo.doc.createTextNode(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
-				args = dojo._toArray(arguments, 1);
-				return this[names.s].apply(this, args) || 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
-			return this[names.g] ? this[names.g]() : 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
-		// description:
-		//		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 reversible
-		//		serialization.
-		return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
-	},
-
-	getDescendants: function(){
-		// summary:
-		//		Returns all the widgets 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.
-
-		return this.containerNode ? dojo.query('[widgetId]', this.containerNode).map(dijit.byNode) : []; // dijit._Widget[]
-	},
-
-	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.
-		return this.containerNode ? dijit.findWidgets(this.containerNode) : []; // dijit._Widget[]
-	},
-
-	// 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 or enter keyup
-		// returns:
-		//		A handle that can be passed to `disconnect` in order to disconnect before
-		//		the widget is destroyed.
-		// 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(){
-		//	|		console.debug(this.toString());
-		//	|	});
-		// tags:
-		//		protected
-
-		var d = dojo,
-			dc = d._connect,
-			handles = [];
-		if(event == "ondijitclick"){
-			// add key based click activation for unsupported nodes.
-			// do all processing onkey up to prevent spurious clicks
-			// for details see comments at top of this file where _lastKeyDownNode is defined
-			if(!this.nodesWithKeyClick[obj.tagName.toLowerCase()]){
-				var m = d.hitch(this, method);
-				handles.push(
-					dc(obj, "onkeydown", this, function(e){
-						//console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
-						if((e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
-							!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
-							// needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
-							dijit._lastKeyDownNode = e.target;
-							d.stopEvent(e);		// stop event to prevent scrolling on space key in IE
-						}
-			 		}),
-					dc(obj, "onkeyup", this, function(e){
-						//console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
-						if( (e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
-							e.target === dijit._lastKeyDownNode &&
-							!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
-								//need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
-								dijit._lastKeyDownNode = null;
-								return m(e);
-						}
-					})
-				);
-			}
-			event = "onclick";
-		}
-		handles.push(dc(obj, event, this, method));
-
-		this._connects.push(handles);
-		return handles;		// _Widget.Handle
-	},
-
-	disconnect: function(/* _Widget.Handle */ handles){
-		// summary:
-		//		Disconnects handle created by `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;
-			}
-		}
-	},
-
-	subscribe: function(
-			/*String*/ topic,
-			/*String|Function*/ method){
-		// summary:
-		//		Subscribes to the specified topic and calls the specified method
-		//		of this object and registers for unsubscribe() on widget destroy.
-		// description:
-		//		Provide widget-specific analog to dojo.subscribe, except with the
-		//		implicit use of this widget as the target object.
-		// example:
-		//	|	var btn = new dijit.form.Button();
-		//	|	// when /my/topic is published, this button changes its label to
-		//	|   // be the parameter of the topic.
-		//	|	btn.subscribe("/my/topic", function(v){
-		//	|		this.attr("label", v);
-		//	|	});
-		var d = dojo,
-			handle = d.subscribe(topic, this, method);
-
-		// return handles for Any widget that may need them
-		this._subscribes.push(handle);
-		return handle;
-	},
-
-	unsubscribe: function(/*Object*/ handle){
-		// summary:
-		//		Unsubscribes handle created by this.subscribe.
-		//		Also removes handle from this widget's list of subscriptions
-		for(var i=0; i<this._subscribes.length; i++){
-			if(this._subscribes[i] == handle){
-				dojo.unsubscribe(handle);
-				this._subscribes.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){ console.log('click'); });
-		//
-		// 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;
-	},
-
-	_onShow: function(){
-		// summary:
-		//		Internal method called when this widget is made visible.
-		//		See `onShow` for details.
-		this.onShow();
-	},
-
-	onShow: function(){
-		// summary:
-		//		Called when this widget becomes the selected pane in a
-		//		`dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
-		//		`dijit.layout.AccordionContainer`, etc.
-		//
-		//		Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
-		// tags:
-		//		callback
-	},
-
-	onHide: function(){
-		// summary:
-			//		Called when another widget becomes the selected pane in a
-			//		`dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
-			//		`dijit.layout.AccordionContainer`, etc.
-			//
-			//		Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
-			// tags:
-			//		callback
-	}
-});
-
-})();
-
-}
-
-if(!dojo._hasResource["dojox.gfx.matrix"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.gfx.matrix"] = true;
-dojo.provide("dojox.gfx.matrix");
-
-(function(){
-	var m = dojox.gfx.matrix;
-
-	// candidates for dojox.math:
-	var _degToRadCache = {};
-	m._degToRad = function(degree){
-		return _degToRadCache[degree] || (_degToRadCache[degree] = (Math.PI * degree / 180));
-	};
-	m._radToDeg = function(radian){ return radian / Math.PI * 180; };
-
-	m.Matrix2D = function(arg){
-		// summary: a 2D matrix object
-		// description: Normalizes a 2D matrix-like object. If arrays is passed,
-		//		all objects of the array are normalized and multiplied sequentially.
-		// arg: Object
-		//		a 2D matrix-like object, a number, or an array of such objects
-		if(arg){
-			if(typeof arg == "number"){
-				this.xx = this.yy = arg;
-			}else if(arg instanceof Array){
-				if(arg.length > 0){
-					var matrix = m.normalize(arg[0]);
-					// combine matrices
-					for(var i = 1; i < arg.length; ++i){
-						var l = matrix, r = dojox.gfx.matrix.normalize(arg[i]);
-						matrix = new m.Matrix2D();
-						matrix.xx = l.xx * r.xx + l.xy * r.yx;
-						matrix.xy = l.xx * r.xy + l.xy * r.yy;
-						matrix.yx = l.yx * r.xx + l.yy * r.yx;
-						matrix.yy = l.yx * r.xy + l.yy * r.yy;
-						matrix.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
-						matrix.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
-					}
-					dojo.mixin(this, matrix);
-				}
-			}else{
-				dojo.mixin(this, arg);
-			}
-		}
-	};
-
-	// the default (identity) matrix, which is used to fill in missing values
-	dojo.extend(m.Matrix2D, {xx: 1, xy: 0, yx: 0, yy: 1, dx: 0, dy: 0});
-
-	dojo.mixin(m, {
-		// summary: class constants, and methods of dojox.gfx.matrix
-
-		// matrix constants
-
-		// identity: dojox.gfx.matrix.Matrix2D
-		//		an identity matrix constant: identity * (x, y) == (x, y)
-		identity: new m.Matrix2D(),
-
-		// flipX: dojox.gfx.matrix.Matrix2D
-		//		a matrix, which reflects points at x = 0 line: flipX * (x, y) == (-x, y)
-		flipX:    new m.Matrix2D({xx: -1}),
-
-		// flipY: dojox.gfx.matrix.Matrix2D
-		//		a matrix, which reflects points at y = 0 line: flipY * (x, y) == (x, -y)
-		flipY:    new m.Matrix2D({yy: -1}),
-
-		// flipXY: dojox.gfx.matrix.Matrix2D
-		//		a matrix, which reflects points at the origin of coordinates: flipXY * (x, y) == (-x, -y)
-		flipXY:   new m.Matrix2D({xx: -1, yy: -1}),
-
-		// matrix creators
-
-		translate: function(a, b){
-			// summary: forms a translation matrix
-			// description: The resulting matrix is used to translate (move) points by specified offsets.
-			// a: Number: an x coordinate value
-			// b: Number: a y coordinate value
-			if(arguments.length > 1){
-				return new m.Matrix2D({dx: a, dy: b}); // dojox.gfx.matrix.Matrix2D
-			}
-			// branch
-			// a: dojox.gfx.Point: a point-like object, which specifies offsets for both dimensions
-			// b: null
-			return new m.Matrix2D({dx: a.x, dy: a.y}); // dojox.gfx.matrix.Matrix2D
-		},
-		scale: function(a, b){
-			// summary: forms a scaling matrix
-			// description: The resulting matrix is used to scale (magnify) points by specified offsets.
-			// a: Number: a scaling factor used for the x coordinate
-			// b: Number: a scaling factor used for the y coordinate
-			if(arguments.length > 1){
-				return new m.Matrix2D({xx: a, yy: b}); // dojox.gfx.matrix.Matrix2D
-			}
-			if(typeof a == "number"){
-				// branch
-				// a: Number: a uniform scaling factor used for the both coordinates
-				// b: null
-				return new m.Matrix2D({xx: a, yy: a}); // dojox.gfx.matrix.Matrix2D
-			}
-			// branch
-			// a: dojox.gfx.Point: a point-like object, which specifies scale factors for both dimensions
-			// b: null
-			return new m.Matrix2D({xx: a.x, yy: a.y}); // dojox.gfx.matrix.Matrix2D
-		},
-		rotate: function(angle){
-			// summary: forms a rotating matrix
-			// description: The resulting matrix is used to rotate points
-			//		around the origin of coordinates (0, 0) by specified angle.
-			// angle: Number: an angle of rotation in radians (>0 for CW)
-			var c = Math.cos(angle);
-			var s = Math.sin(angle);
-			return new m.Matrix2D({xx: c, xy: -s, yx: s, yy: c}); // dojox.gfx.matrix.Matrix2D
-		},
-		rotateg: function(degree){
-			// summary: forms a rotating matrix
-			// description: The resulting matrix is used to rotate points
-			//		around the origin of coordinates (0, 0) by specified degree.
-			//		See dojox.gfx.matrix.rotate() for comparison.
-			// degree: Number: an angle of rotation in degrees (>0 for CW)
-			return m.rotate(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
-		},
-		skewX: function(angle) {
-			// summary: forms an x skewing matrix
-			// description: The resulting matrix is used to skew points in the x dimension
-			//		around the origin of coordinates (0, 0) by specified angle.
-			// angle: Number: an skewing angle in radians
-			return new m.Matrix2D({xy: Math.tan(angle)}); // dojox.gfx.matrix.Matrix2D
-		},
-		skewXg: function(degree){
-			// summary: forms an x skewing matrix
-			// description: The resulting matrix is used to skew points in the x dimension
-			//		around the origin of coordinates (0, 0) by specified degree.
-			//		See dojox.gfx.matrix.skewX() for comparison.
-			// degree: Number: an skewing angle in degrees
-			return m.skewX(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
-		},
-		skewY: function(angle){
-			// summary: forms a y skewing matrix
-			// description: The resulting matrix is used to skew points in the y dimension
-			//		around the origin of coordinates (0, 0) by specified angle.
-			// angle: Number: an skewing angle in radians
-			return new m.Matrix2D({yx: Math.tan(angle)}); // dojox.gfx.matrix.Matrix2D
-		},
-		skewYg: function(degree){
-			// summary: forms a y skewing matrix
-			// description: The resulting matrix is used to skew points in the y dimension
-			//		around the origin of coordinates (0, 0) by specified degree.
-			//		See dojox.gfx.matrix.skewY() for comparison.
-			// degree: Number: an skewing angle in degrees
-			return m.skewY(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
-		},
-		reflect: function(a, b){
-			// summary: forms a reflection matrix
-			// description: The resulting matrix is used to reflect points around a vector,
-			//		which goes through the origin.
-			// a: dojox.gfx.Point: a point-like object, which specifies a vector of reflection
-			// b: null
-			if(arguments.length == 1){
-				b = a.y;
-				a = a.x;
-			}
-			// branch
-			// a: Number: an x coordinate value
-			// b: Number: a y coordinate value
-
-			// make a unit vector
-			var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = 2 * a * b / n2;
-			return new m.Matrix2D({xx: 2 * a2 / n2 - 1, xy: xy, yx: xy, yy: 2 * b2 / n2 - 1}); // dojox.gfx.matrix.Matrix2D
-		},
-		project: function(a, b){
-			// summary: forms an orthogonal projection matrix
-			// description: The resulting matrix is used to project points orthogonally on a vector,
-			//		which goes through the origin.
-			// a: dojox.gfx.Point: a point-like object, which specifies a vector of projection
-			// b: null
-			if(arguments.length == 1){
-				b = a.y;
-				a = a.x;
-			}
-			// branch
-			// a: Number: an x coordinate value
-			// b: Number: a y coordinate value
-
-			// make a unit vector
-			var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = a * b / n2;
-			return new m.Matrix2D({xx: a2 / n2, xy: xy, yx: xy, yy: b2 / n2}); // dojox.gfx.matrix.Matrix2D
-		},
-
-		// ensure matrix 2D conformance
-		normalize: function(matrix){
-			// summary: converts an object to a matrix, if necessary
-			// description: Converts any 2D matrix-like object or an array of
-			//		such objects to a valid dojox.gfx.matrix.Matrix2D object.
-			// matrix: Object: an object, which is converted to a matrix, if necessary
-			return (matrix instanceof m.Matrix2D) ? matrix : new m.Matrix2D(matrix); // dojox.gfx.matrix.Matrix2D
-		},
-
-		// common operations
-
-		clone: function(matrix){
-			// summary: creates a copy of a 2D matrix
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to be cloned
-			var obj = new m.Matrix2D();
-			for(var i in matrix){
-				if(typeof(matrix[i]) == "number" && typeof(obj[i]) == "number" && obj[i] != matrix[i]) obj[i] = matrix[i];
-			}
-			return obj; // dojox.gfx.matrix.Matrix2D
-		},
-		invert: function(matrix){
-			// summary: inverts a 2D matrix
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to be inverted
-			var M = m.normalize(matrix),
-				D = M.xx * M.yy - M.xy * M.yx,
-				M = new m.Matrix2D({
-					xx: M.yy/D, xy: -M.xy/D,
-					yx: -M.yx/D, yy: M.xx/D,
-					dx: (M.xy * M.dy - M.yy * M.dx) / D,
-					dy: (M.yx * M.dx - M.xx * M.dy) / D
-				});
-			return M; // dojox.gfx.matrix.Matrix2D
-		},
-		_multiplyPoint: function(matrix, x, y){
-			// summary: applies a matrix to a point
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
-			// x: Number: an x coordinate of a point
-			// y: Number: a y coordinate of a point
-			return {x: matrix.xx * x + matrix.xy * y + matrix.dx, y: matrix.yx * x + matrix.yy * y + matrix.dy}; // dojox.gfx.Point
-		},
-		multiplyPoint: function(matrix, /* Number||Point */ a, /* Number, optional */ b){
-			// summary: applies a matrix to a point
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
-			// a: Number: an x coordinate of a point
-			// b: Number: a y coordinate of a point
-			var M = m.normalize(matrix);
-			if(typeof a == "number" && typeof b == "number"){
-				return m._multiplyPoint(M, a, b); // dojox.gfx.Point
-			}
-			// branch
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
-			// a: dojox.gfx.Point: a point
-			// b: null
-			return m._multiplyPoint(M, a.x, a.y); // dojox.gfx.Point
-		},
-		multiply: function(matrix){
-			// summary: combines matrices by multiplying them sequentially in the given order
-			// matrix: dojox.gfx.matrix.Matrix2D...: a 2D matrix-like object,
-			//		all subsequent arguments are matrix-like objects too
-			var M = m.normalize(matrix);
-			// combine matrices
-			for(var i = 1; i < arguments.length; ++i){
-				var l = M, r = m.normalize(arguments[i]);
-				M = new m.Matrix2D();
-				M.xx = l.xx * r.xx + l.xy * r.yx;
-				M.xy = l.xx * r.xy + l.xy * r.yy;
-				M.yx = l.yx * r.xx + l.yy * r.yx;
-				M.yy = l.yx * r.xy + l.yy * r.yy;
-				M.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
-				M.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
-			}
-			return M; // dojox.gfx.matrix.Matrix2D
-		},
-
-		// high level operations
-
-		_sandwich: function(matrix, x, y){
-			// summary: applies a matrix at a centrtal point
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object, which is applied at a central point
-			// x: Number: an x component of the central point
-			// y: Number: a y component of the central point
-			return m.multiply(m.translate(x, y), matrix, m.translate(-x, -y)); // dojox.gfx.matrix.Matrix2D
-		},
-		scaleAt: function(a, b, c, d){
-			// summary: scales a picture using a specified point as a center of scaling
-			// description: Compare with dojox.gfx.matrix.scale().
-			// a: Number: a scaling factor used for the x coordinate
-			// b: Number: a scaling factor used for the y coordinate
-			// c: Number: an x component of a central point
-			// d: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) uniform scale factor, Point
-			//	2) uniform scale factor, x, y
-			//	3) x scale, y scale, Point
-			//	4) x scale, y scale, x, y
-
-			switch(arguments.length){
-				case 4:
-					// a and b are scale factor components, c and d are components of a point
-					return m._sandwich(m.scale(a, b), c, d); // dojox.gfx.matrix.Matrix2D
-				case 3:
-					if(typeof c == "number"){
-						// branch
-						// a: Number: a uniform scaling factor used for both coordinates
-						// b: Number: an x component of a central point
-						// c: Number: a y component of a central point
-						// d: null
-						return m._sandwich(m.scale(a), b, c); // dojox.gfx.matrix.Matrix2D
-					}
-					// branch
-					// a: Number: a scaling factor used for the x coordinate
-					// b: Number: a scaling factor used for the y coordinate
-					// c: dojox.gfx.Point: a central point
-					// d: null
-					return m._sandwich(m.scale(a, b), c.x, c.y); // dojox.gfx.matrix.Matrix2D
-			}
-			// branch
-			// a: Number: a uniform scaling factor used for both coordinates
-			// b: dojox.gfx.Point: a central point
-			// c: null
-			// d: null
-			return m._sandwich(m.scale(a), b.x, b.y); // dojox.gfx.matrix.Matrix2D
-		},
-		rotateAt: function(angle, a, b){
-			// summary: rotates a picture using a specified point as a center of rotation
-			// description: Compare with dojox.gfx.matrix.rotate().
-			// angle: Number: an angle of rotation in radians (>0 for CW)
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) rotation angle in radians, Point
-			//	2) rotation angle in radians, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.rotate(angle), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// angle: Number: an angle of rotation in radians (>0 for CCW)
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.rotate(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		},
-		rotategAt: function(degree, a, b){
-			// summary: rotates a picture using a specified point as a center of rotation
-			// description: Compare with dojox.gfx.matrix.rotateg().
-			// degree: Number: an angle of rotation in degrees (>0 for CW)
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) rotation angle in degrees, Point
-			//	2) rotation angle in degrees, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.rotateg(degree), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// degree: Number: an angle of rotation in degrees (>0 for CCW)
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.rotateg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		},
-		skewXAt: function(angle, a, b){
-			// summary: skews a picture along the x axis using a specified point as a center of skewing
-			// description: Compare with dojox.gfx.matrix.skewX().
-			// angle: Number: an skewing angle in radians
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) skew angle in radians, Point
-			//	2) skew angle in radians, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.skewX(angle), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// angle: Number: an skewing angle in radians
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.skewX(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		},
-		skewXgAt: function(degree, a, b){
-			// summary: skews a picture along the x axis using a specified point as a center of skewing
-			// description: Compare with dojox.gfx.matrix.skewXg().
-			// degree: Number: an skewing angle in degrees
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) skew angle in degrees, Point
-			//	2) skew angle in degrees, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.skewXg(degree), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// degree: Number: an skewing angle in degrees
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.skewXg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		},
-		skewYAt: function(angle, a, b){
-			// summary: skews a picture along the y axis using a specified point as a center of skewing
-			// description: Compare with dojox.gfx.matrix.skewY().
-			// angle: Number: an skewing angle in radians
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) skew angle in radians, Point
-			//	2) skew angle in radians, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.skewY(angle), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// angle: Number: an skewing angle in radians
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.skewY(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		},
-		skewYgAt: function(/* Number */ degree, /* Number||Point */ a, /* Number, optional */ b){
-			// summary: skews a picture along the y axis using a specified point as a center of skewing
-			// description: Compare with dojox.gfx.matrix.skewYg().
-			// degree: Number: an skewing angle in degrees
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) skew angle in degrees, Point
-			//	2) skew angle in degrees, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.skewYg(degree), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// degree: Number: an skewing angle in degrees
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.skewYg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		}
-
-		//TODO: rect-to-rect mapping, scale-to-fit (isotropic and anisotropic versions)
-
-	});
-})();
-
-// propagate Matrix2D up
-dojox.gfx.Matrix2D = dojox.gfx.matrix.Matrix2D;
-
-}
-
-if(!dojo._hasResource["dojox.gfx._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.gfx._base"] = true;
-dojo.provide("dojox.gfx._base");
-
-(function(){
-	var g = dojox.gfx, b = g._base;
-
-	// candidates for dojox.style (work on VML and SVG nodes)
-	g._hasClass = function(/*DomNode*/node, /*String*/classStr){
-		//	summary:
-		//		Returns whether or not the specified classes are a portion of the
-		//		class list currently applied to the node.
-		// return (new RegExp('(^|\\s+)'+classStr+'(\\s+|$)')).test(node.className)	// Boolean
-		var cls = node.getAttribute("className");
-		return cls && (" " + cls + " ").indexOf(" " + classStr + " ") >= 0;  // Boolean
-	}
-	g._addClass = function(/*DomNode*/node, /*String*/classStr){
-		//	summary:
-		//		Adds the specified classes to the end of the class list on the
-		//		passed node.
-		var cls = node.getAttribute("className") || "";
-		if(!cls || (" " + cls + " ").indexOf(" " + classStr + " ") < 0){
-			node.setAttribute("className", cls + (cls ? " " : "") + classStr);
-		}
-	}
-	g._removeClass = function(/*DomNode*/node, /*String*/classStr){
-		//	summary: Removes classes from node.
-		var cls = node.getAttribute("className");
-		if(cls){
-			node.setAttribute(
-				"className", 
-				cls.replace(new RegExp('(^|\\s+)' + classStr + '(\\s+|$)'), "$1$2")
-			);
-		}
-	}
-
-	// candidate for dojox.html.metrics (dynamic font resize handler is not implemented here)
-
-	//	derived from Morris John's emResized measurer
-	b._getFontMeasurements = function(){
-		//	summary:
-		//		Returns an object that has pixel equivilents of standard font
-		//		size values.
-		var heights = {
-			'1em': 0, '1ex': 0, '100%': 0, '12pt': 0, '16px': 0, 'xx-small': 0,
-			'x-small': 0, 'small': 0, 'medium': 0, 'large': 0, 'x-large': 0,
-			'xx-large': 0
-		};
-
-		if(dojo.isIE){
-			//	we do a font-size fix if and only if one isn't applied already.
-			//	NOTE: If someone set the fontSize on the HTML Element, this will kill it.
-			dojo.doc.documentElement.style.fontSize="100%";
-		}
-
-		//	set up the measuring node.
-		var div = dojo.doc.createElement("div");
-		var s = div.style;
-		s.position = "absolute";
-		s.left = "-100px";
-		s.top = "0px";
-		s.width = "30px";
-		s.height = "1000em";
-		s.border = "0px";
-		s.margin = "0px";
-		s.padding = "0px";
-		s.outline = "none";
-		s.lineHeight = "1";
-		s.overflow = "hidden";
-		dojo.body().appendChild(div);
-
-		//	do the measurements.
-		for(var p in heights){
-			div.style.fontSize = p;
-			heights[p] = Math.round(div.offsetHeight * 12/16) * 16/12 / 1000;
-		}
-
-		dojo.body().removeChild(div);
-		div = null;
-		return heights; 	//	object
-	};
-
-	var fontMeasurements = null;
-
-	b._getCachedFontMeasurements = function(recalculate){
-		if(recalculate || !fontMeasurements){
-			fontMeasurements = b._getFontMeasurements();
-		}
-		return fontMeasurements;
-	};
-
-	// candidate for dojox.html.metrics
-
-	var measuringNode = null, empty = {};
-	b._getTextBox = function(	/*String*/ text,
-								/*Object*/ style,
-								/*String?*/ className){
-		var m, s, al = arguments.length;
-		if(!measuringNode){
-			m = measuringNode = dojo.doc.createElement("div");
-			s = m.style;
-			s.position = "absolute";
-			s.left = "-10000px";
-			s.top = "0";
-			dojo.body().appendChild(m);
-		}else{
-			m = measuringNode;
-			s = m.style;
-		}
-		// reset styles
-		m.className = "";
-		s.border = "0";
-		s.margin = "0";
-		s.padding = "0";
-		s.outline = "0";
-		// set new style
-		if(al > 1 && style){
-			for(var i in style){
-				if(i in empty){ continue; }
-				s[i] = style[i];
-			}
-		}
-		// set classes
-		if(al > 2 && className){
-			m.className = className;
-		}
-		// take a measure
-		m.innerHTML = text;
-
-		if(m["getBoundingClientRect"]){
-			var bcr = m.getBoundingClientRect();
-			return {l: bcr.left, t: bcr.top, w: bcr.width || (bcr.right - bcr.left), h: bcr.height || (bcr.bottom - bcr.top)};
-		}else{
-			return dojo.marginBox(m);
-		}
-	};
-
-	// candidate for dojo.dom
-
-	var uniqueId = 0;
-	b._getUniqueId = function(){
-		// summary: returns a unique string for use with any DOM element
-		var id;
-		do{
-			id = dojo._scopeName + "Unique" + (++uniqueId);
-		}while(dojo.byId(id));
-		return id;
-	};
-})();
-
-dojo.mixin(dojox.gfx, {
-	//	summary:
-	// 		defines constants, prototypes, and utility functions
-
-	// default shapes, which are used to fill in missing parameters
-	defaultPath: {
-		type: "path", path: ""
-	},
-	defaultPolyline: {
-		type: "polyline", points: []
-	},
-	defaultRect: {
-		type: "rect", x: 0, y: 0, width: 100, height: 100, r: 0
-	},
-	defaultEllipse: {
-		type: "ellipse", cx: 0, cy: 0, rx: 200, ry: 100
-	},
-	defaultCircle: {
-		type: "circle", cx: 0, cy: 0, r: 100
-	},
-	defaultLine: {
-		type: "line", x1: 0, y1: 0, x2: 100, y2: 100
-	},
-	defaultImage: {
-		type: "image", x: 0, y: 0, width: 0, height: 0, src: ""
-	},
-	defaultText: {
-		type: "text", x: 0, y: 0, text: "", align: "start",
-		decoration: "none", rotated: false, kerning: true
-	},
-	defaultTextPath: {
-		type: "textpath", text: "", align: "start",
-		decoration: "none", rotated: false, kerning: true
-	},
-
-	// default geometric attributes
-	defaultStroke: {
-		type: "stroke", color: "black", style: "solid", width: 1, 
-		cap: "butt", join: 4
-	},
-	defaultLinearGradient: {
-		type: "linear", x1: 0, y1: 0, x2: 100, y2: 100,
-		colors: [
-			{ offset: 0, color: "black" }, { offset: 1, color: "white" }
-		]
-	},
-	defaultRadialGradient: {
-		type: "radial", cx: 0, cy: 0, r: 100,
-		colors: [
-			{ offset: 0, color: "black" }, { offset: 1, color: "white" }
-		]
-	},
-	defaultPattern: {
-		type: "pattern", x: 0, y: 0, width: 0, height: 0, src: ""
-	},
-	defaultFont: {
-		type: "font", style: "normal", variant: "normal", 
-		weight: "normal", size: "10pt", family: "serif"
-	},
-
-	getDefault: (function(){
-		var typeCtorCache = {};
-		// a memoized delegate()
-		return function(/*String*/ type){
-			var t = typeCtorCache[type];
-			if(t){
-				return new t();
-			}
-			t = typeCtorCache[type] = new Function;
-			t.prototype = dojox.gfx[ "default" + type ];
-			return new t();
-		}
-	})(),
-
-	normalizeColor: function(/*Color*/ color){
-		//	summary:
-		// 		converts any legal color representation to normalized
-		// 		dojo.Color object
-		return (color instanceof dojo.Color) ? color : new dojo.Color(color); // dojo.Color
-	},
-	normalizeParameters: function(existed, update){
-		//	summary:
-		// 		updates an existing object with properties from an "update"
-		// 		object
-		//	existed: Object
-		//		the "target" object to be updated
-		//	update:  Object
-		//		the "update" object, whose properties will be used to update
-		//		the existed object
-		if(update){
-			var empty = {};
-			for(var x in existed){
-				if(x in update && !(x in empty)){
-					existed[x] = update[x];
-				}
-			}
-		}
-		return existed;	// Object
-	},
-	makeParameters: function(defaults, update){
-		//	summary:
-		// 		copies the original object, and all copied properties from the
-		// 		"update" object
-		//	defaults: Object
-		//		the object to be cloned before updating
-		//	update:   Object
-		//		the object, which properties are to be cloned during updating
-		if(!update){
-			// return dojo.clone(defaults);
-			return dojo.delegate(defaults);
-		}
-		var result = {};
-		for(var i in defaults){
-			if(!(i in result)){
-				result[i] = dojo.clone((i in update) ? update[i] : defaults[i]);
-			}
-		}
-		return result; // Object
-	},
-	formatNumber: function(x, addSpace){
-		// summary: converts a number to a string using a fixed notation
-		// x:			Number:		number to be converted
-		// addSpace:	Boolean?:	if it is true, add a space before a positive number
-		var val = x.toString();
-		if(val.indexOf("e") >= 0){
-			val = x.toFixed(4);
-		}else{
-			var point = val.indexOf(".");
-			if(point >= 0 && val.length - point > 5){
-				val = x.toFixed(4);
-			}
-		}
-		if(x < 0){
-			return val; // String
-		}
-		return addSpace ? " " + val : val; // String
-	},
-	// font operations
-	makeFontString: function(font){
-		// summary: converts a font object to a CSS font string
-		// font:	Object:	font object (see dojox.gfx.defaultFont)
-		return font.style + " " + font.variant + " " + font.weight + " " + font.size + " " + font.family; // Object
-	},
-	splitFontString: function(str){
-		// summary:
-		//		converts a CSS font string to a font object
-		// description:
-		//		Converts a CSS font string to a gfx font object. The CSS font
-		//		string components should follow the W3C specified order
-		//		(see http://www.w3.org/TR/CSS2/fonts.html#font-shorthand):
-		//		style, variant, weight, size, optional line height (will be
-		//		ignored), and family.
-		// str: String
-		//		a CSS font string
-		var font = dojox.gfx.getDefault("Font");
-		var t = str.split(/\s+/);
-		do{
-			if(t.length < 5){ break; }
-			font.style   = t[0];
-			font.variant = t[1];
-			font.weight  = t[2];
-			var i = t[3].indexOf("/");
-			font.size = i < 0 ? t[3] : t[3].substring(0, i);
-			var j = 4;
-			if(i < 0){
-				if(t[4] == "/"){
-					j = 6;
-				}else if(t[4].charAt(0) == "/"){
-					j = 5;
-				}
-			}
-			if(j < t.length){
-				font.family = t.slice(j).join(" ");
-			}
-		}while(false);
-		return font;	// Object
-	},
-	// length operations
-	cm_in_pt: 72 / 2.54,	// Number: points per centimeter
-	mm_in_pt: 7.2 / 2.54,	// Number: points per millimeter
-	px_in_pt: function(){
-		// summary: returns a number of pixels per point
-		return dojox.gfx._base._getCachedFontMeasurements()["12pt"] / 12;	// Number
-	},
-	pt2px: function(len){
-		// summary: converts points to pixels
-		// len: Number: a value in points
-		return len * dojox.gfx.px_in_pt();	// Number
-	},
-	px2pt: function(len){
-		// summary: converts pixels to points
-		// len: Number: a value in pixels
-		return len / dojox.gfx.px_in_pt();	// Number
-	},
-	normalizedLength: function(len) {
-		// summary: converts any length value to pixels
-		// len: String: a length, e.g., "12pc"
-		if(len.length == 0) return 0;
-		if(len.length > 2){
-			var px_in_pt = dojox.gfx.px_in_pt();
-			var val = parseFloat(len);
-			switch(len.slice(-2)){
-				case "px": return val;
-				case "pt": return val * px_in_pt;
-				case "in": return val * 72 * px_in_pt;
-				case "pc": return val * 12 * px_in_pt;
-				case "mm": return val * dojox.gfx.mm_in_pt * px_in_pt;
-				case "cm": return val * dojox.gfx.cm_in_pt * px_in_pt;
-			}
-		}
-		return parseFloat(len);	// Number
-	},
-
-	// a constant used to split a SVG/VML path into primitive components
-	pathVmlRegExp: /([A-Za-z]+)|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,
-	pathSvgRegExp: /([A-Za-z])|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,
-
-	equalSources: function(a, b){
-		// summary: compares event sources, returns true if they are equal
-		return a && b && a == b;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.gfx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.gfx"] = true;
-dojo.provide("dojox.gfx");
-
-
-
-
-dojo.loadInit(function(){
-	//Since loaderInit can be fired before any dojo.provide/require calls,
-	//make sure the dojox.gfx object exists and only run this logic if dojox.gfx.renderer
-	//has not been defined yet.
-	var gfx = dojo.getObject("dojox.gfx", true), sl, flag, match;
-	if(!gfx.renderer){
-		//Have a way to force a GFX renderer, if so desired.
-		//Useful for being able to serialize GFX data in a particular format.
-		if(dojo.config.forceGfxRenderer){
-			dojox.gfx.renderer = dojo.config.forceGfxRenderer;
-			return;
-		}
-		var renderers = (typeof dojo.config.gfxRenderer == "string" ?
-			dojo.config.gfxRenderer : "svg,vml,silverlight,canvas").split(",");
-
-		// mobile platform detection
-		// TODO: move to the base?
-
-		var ua = navigator.userAgent, iPhoneOsBuild = 0, androidVersion = 0;
-		if(dojo.isSafari >= 3){
-			// detect mobile version of WebKit starting with "version 3"
-
-			//	comprehensive iPhone test.  Have to figure out whether it's SVG or Canvas based on the build.
-			//	iPhone OS build numbers from en.wikipedia.org.
-			if(ua.indexOf("iPhone") >= 0 || ua.indexOf("iPod") >= 0){
-				//	grab the build out of this.  Expression is a little nasty because we want
-				//		to be sure we have the whole version string.
-				match = ua.match(/Version\/(\d(\.\d)?(\.\d)?)\sMobile\/([^\s]*)\s?/);
-				if(match){
-					//	grab the build out of the match.  Only use the first three because of specific builds.
-					iPhoneOsBuild = parseInt(match[4].substr(0,3), 16);
-				}
-			}
-		}
-		if(dojo.isWebKit){
-			// Android detection
-			if(!iPhoneOsBuild){
-				match = ua.match(/Android\s+(\d+\.\d+)/);
-				if(match){
-					androidVersion = parseFloat(match[1]);
-					// Android 1.0-1.1 doesn't support SVG but supports Canvas
-				}
-			}
-		}
-
-		for(var i = 0; i < renderers.length; ++i){
-			switch(renderers[i]){
-				case "svg":
-					//	iPhone OS builds greater than 5F1 should have SVG.
-					if(!dojo.isIE && (!iPhoneOsBuild || iPhoneOsBuild >= 0x5f1) && !androidVersion && !dojo.isAIR){
-						dojox.gfx.renderer = "svg";
-					}
-					break;
-				case "vml":
-					if(dojo.isIE){
-						dojox.gfx.renderer = "vml";
-					}
-					break;
-				case "silverlight":
-					try{
-						if(dojo.isIE){
-							sl = new ActiveXObject("AgControl.AgControl");
-							if(sl && sl.IsVersionSupported("1.0")){
-								flag = true;
-							}
-						}else{
-							if(navigator.plugins["Silverlight Plug-In"]){
-								flag = true;
-							}
-						}
-					}catch(e){
-						flag = false;
-					}finally{
-						sl = null;
-					}
-					if(flag){ dojox.gfx.renderer = "silverlight"; }
-					break;
-				case "canvas":
-					//TODO: need more comprehensive test for Canvas
-					if(!dojo.isIE){
-						dojox.gfx.renderer = "canvas";
-					}
-					break;
-			}
-			if(dojox.gfx.renderer){ break; }
-		}
-		if(dojo.config.isDebug){
-			console.log("gfx renderer = " + dojox.gfx.renderer);
-		}
-	}
-});
-
-// include a renderer conditionally
-dojo.requireIf(dojox.gfx.renderer == "svg", "dojox.gfx.svg");
-dojo.requireIf(dojox.gfx.renderer == "vml", "dojox.gfx.vml");
-dojo.requireIf(dojox.gfx.renderer == "silverlight", "dojox.gfx.silverlight");
-dojo.requireIf(dojox.gfx.renderer == "canvas", "dojox.gfx.canvas");
-
-}
-
-if(!dojo._hasResource["dojox.lang.functional.lambda"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.lang.functional.lambda"] = true;
-dojo.provide("dojox.lang.functional.lambda");
-
-// This module adds high-level functions and related constructs:
-//	- anonymous functions built from the string
-
-// Acknoledgements:
-//	- lambda() is based on work by Oliver Steele 
-//		(http://osteele.com/sources/javascript/functional/functional.js)
-//		which was published under MIT License
-
-// Notes:
-//	- lambda() produces functions, which after the compilation step are 
-//		as fast as regular JS functions (at least theoretically).
-
-// Lambda input values:
-//	- returns functions unchanged
-//	- converts strings to functions
-//	- converts arrays to a functional composition
-
-(function(){
-	var df = dojox.lang.functional, lcache = {};
-
-	// split() is augmented on IE6 to ensure the uniform behavior
-	var split = "ab".split(/a*/).length > 1 ? String.prototype.split :
-			function(sep){
-				 var r = this.split.call(this, sep),
-					 m = sep.exec(this);
-				 if(m && m.index == 0){ r.unshift(""); }
-				 return r;
-			};
-			
-	var lambda = function(/*String*/ s){
-		var args = [], sects = split.call(s, /\s*->\s*/m);
-		if(sects.length > 1){
-			while(sects.length){
-				s = sects.pop();
-				args = sects.pop().split(/\s*,\s*|\s+/m);
-				if(sects.length){ sects.push("(function(" + args + "){return (" + s + ")})"); }
-			}
-		}else if(s.match(/\b_\b/)){
-			args = ["_"];
-		}else{
-			var l = s.match(/^\s*(?:[+*\/%&|\^\.=<>]|!=)/m),
-				r = s.match(/[+\-*\/%&|\^\.=<>!]\s*$/m);
-			if(l || r){
-				if(l){
-					args.push("$1");
-					s = "$1" + s;
-				}
-				if(r){
-					args.push("$2");
-					s = s + "$2";
-				}
-			}else{
-				// the point of the long regex below is to exclude all well-known 
-				// lower-case words from the list of potential arguments
-				var vars = s.
-					replace(/(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_$\d]*:|this|true|false|null|undefined|typeof|instanceof|in|delete|new|void|arguments|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|isFinite|isNaN|parseFloat|parseInt|unescape|dojo|dijit|dojox|window|document|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g, "").
-					match(/([a-z_$][a-z_$\d]*)/gi) || [], t = {};
-				dojo.forEach(vars, function(v){
-					if(!(v in t)){
-						args.push(v);
-						t[v] = 1;
-					}
-				});
-			}
-		}
-		return {args: args, body: s};	// Object
-	};
-
-	var compose = function(/*Array*/ a){
-		return a.length ? 
-					function(){
-						var i = a.length - 1, x = df.lambda(a[i]).apply(this, arguments);
-						for(--i; i >= 0; --i){ x = df.lambda(a[i]).call(this, x); }
-						return x;
-					}
-				: 
-					// identity
-					function(x){ return x; };
-	};
-
-	dojo.mixin(df, {
-		// lambda
-		rawLambda: function(/*String*/ s){
-			// summary:
-			//		builds a function from a snippet, or array (composing),
-			//		returns an object describing the function; functions are
-			//		passed through unmodified.
-			// description:
-			//		This method is to normalize a functional representation (a
-			//		text snippet) to an object that contains an array of
-			//		arguments, and a body , which is used to calculate the
-			//		returning value.
-			return lambda(s);	// Object
-		},
-		buildLambda: function(/*String*/ s){
-			// summary:
-			//		builds a function from a snippet, returns a string, which
-			//		represents the function.
-			// description:
-			//		This method returns a textual representation of a function
-			//		built from the snippet. It is meant to be evaled in the
-			//		proper context, so local variables can be pulled from the
-			//		environment.
-			s = lambda(s);
-			return "function(" + s.args.join(",") + "){return (" + s.body + ");}";	// String
-		},
-		lambda: function(/*Function|String|Array*/ s){
-			// summary:
-			//		builds a function from a snippet, or array (composing),
-			//		returns a function object; functions are passed through
-			//		unmodified.
-			// description:
-			//		This method is used to normalize a functional
-			//		representation (a text snippet, an array, or a function) to
-			//		a function object.
-			if(typeof s == "function"){ return s; }
-			if(s instanceof Array){ return compose(s); }
-			if(s in lcache){ return lcache[s]; }
-			s = lambda(s);
-			return lcache[s] = new Function(s.args, "return (" + s.body + ");");	// Function
-		},
-		clearLambdaCache: function(){
-			// summary:
-			//		clears internal cache of lambdas
-			lcache = {};
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.lang.functional.array"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.lang.functional.array"] = true;
-dojo.provide("dojox.lang.functional.array");
-
-
-
-// This module adds high-level functions and related constructs:
-//	- array-processing functions similar to standard JS functions
-
-// Notes:
-//	- this module provides JS standard methods similar to high-level functions in dojo/_base/array.js: 
-//		forEach, map, filter, every, some
-
-// Defined methods:
-//	- take any valid lambda argument as the functional argument
-//	- operate on dense arrays
-//	- take a string as the array argument
-//	- take an iterator objects as the array argument
-
-(function(){
-	var d = dojo, df = dojox.lang.functional, empty = {};
-
-	d.mixin(df, {
-		// JS 1.6 standard array functions, which can take a lambda as a parameter.
-		// Consider using dojo._base.array functions, if you don't need the lambda support.
-		filter: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: creates a new array with all elements that pass the test 
-			//	implemented by the provided function.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var t = [], v, i, n;
-			if(d.isArray(a)){
-				// array
-				for(i = 0, n = a.length; i < n; ++i){
-					v = a[i];
-					if(f.call(o, v, i, a)){ t.push(v); }
-				}
-			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
-				// iterator
-				for(i = 0; a.hasNext();){
-					v = a.next();
-					if(f.call(o, v, i++, a)){ t.push(v); }
-				}
-			}else{
-				// object/dictionary
-				for(i in a){
-					if(!(i in empty)){
-						v = a[i];
-						if(f.call(o, v, i, a)){ t.push(v); }
-					}
-				}
-			}
-			return t;	// Array
-		},
-		forEach: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: executes a provided function once per array element.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var i, n;
-			if(d.isArray(a)){
-				// array
-				for(i = 0, n = a.length; i < n; f.call(o, a[i], i, a), ++i);
-			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
-				// iterator
-				for(i = 0; a.hasNext(); f.call(o, a.next(), i++, a));
-			}else{
-				// object/dictionary
-				for(i in a){
-					if(!(i in empty)){
-						f.call(o, a[i], i, a);
-					}
-				}
-			}
-			return o;	// Object
-		},
-		map: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: creates a new array with the results of calling 
-			//	a provided function on every element in this array.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var t, n, i;
-			if(d.isArray(a)){
-				// array
-				t = new Array(n = a.length);
-				for(i = 0; i < n; t[i] = f.call(o, a[i], i, a), ++i);
-			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
-				// iterator
-				t = [];
-				for(i = 0; a.hasNext(); t.push(f.call(o, a.next(), i++, a)));
-			}else{
-				// object/dictionary
-				t = [];
-				for(i in a){
-					if(!(i in empty)){
-						t.push(f.call(o, a[i], i, a));
-					}
-				}
-			}
-			return t;	// Array
-		},
-		every: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: tests whether all elements in the array pass the test 
-			//	implemented by the provided function.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var i, n;
-			if(d.isArray(a)){
-				// array
-				for(i = 0, n = a.length; i < n; ++i){
-					if(!f.call(o, a[i], i, a)){
-						return false;	// Boolean
-					}
-				}
-			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
-				// iterator
-				for(i = 0; a.hasNext();){
-					if(!f.call(o, a.next(), i++, a)){
-						return false;	// Boolean
-					}
-				}
-			}else{
-				// object/dictionary
-				for(i in a){
-					if(!(i in empty)){
-						if(!f.call(o, a[i], i, a)){
-							return false;	// Boolean
-						}
-					}
-				}
-			}
-			return true;	// Boolean
-		},
-		some: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: tests whether some element in the array passes the test 
-			//	implemented by the provided function.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var i, n;
-			if(d.isArray(a)){
-				// array
-				for(i = 0, n = a.length; i < n; ++i){
-					if(f.call(o, a[i], i, a)){
-						return true;	// Boolean
-					}
-				}
-			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
-				// iterator
-				for(i = 0; a.hasNext();){
-					if(f.call(o, a.next(), i++, a)){
-						return true;	// Boolean
-					}
-				}
-			}else{
-				// object/dictionary
-				for(i in a){
-					if(!(i in empty)){
-						if(f.call(o, a[i], i, a)){
-							return true;	// Boolean
-						}
-					}
-				}
-			}
-			return false;	// Boolean
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.lang.functional.object"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.lang.functional.object"] = true;
-dojo.provide("dojox.lang.functional.object");
-
-
-
-// This module adds high-level functions and related constructs:
-//	- object/dictionary helpers
-
-// Defined methods:
-//	- take any valid lambda argument as the functional argument
-//	- skip all attributes that are present in the empty object 
-//		(IE and/or 3rd-party libraries).
-
-(function(){
-	var d = dojo, df = dojox.lang.functional, empty = {};
-
-	d.mixin(df, {
-		// object helpers
-		keys: function(/*Object*/ obj){
-			// summary: returns an array of all keys in the object
-			var t = [];
-			for(var i in obj){
-				if(!(i in empty)){
-					t.push(i);
-				}
-			}
-			return	t; // Array
-		},
-		values: function(/*Object*/ obj){
-			// summary: returns an array of all values in the object
-			var t = [];
-			for(var i in obj){
-				if(!(i in empty)){
-					t.push(obj[i]);
-				}
-			}
-			return	t; // Array
-		},
-		filterIn: function(/*Object*/ obj, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: creates new object with all attributes that pass the test 
-			//	implemented by the provided function.
-			o = o || d.global; f = df.lambda(f);
-			var t = {}, v, i;
-			for(i in obj){
-				if(!(i in empty)){
-					v = obj[i];
-					if(f.call(o, v, i, obj)){ t[i] = v; }
-				}
-			}
-			return t;	// Object
-		},
-		forIn: function(/*Object*/ obj, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: iterates over all object attributes.
-			o = o || d.global; f = df.lambda(f);
-			for(var i in obj){
-				if(!(i in empty)){
-					f.call(o, obj[i], i, obj);
-				}
-			}
-			return o;	// Object
-		},
-		mapIn: function(/*Object*/ obj, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: creates new object with the results of calling 
-			//	a provided function on every attribute in this object.
-			o = o || d.global; f = df.lambda(f);
-			var t = {}, i;
-			for(i in obj){
-				if(!(i in empty)){
-					t[i] = f.call(o, obj[i], i, obj);
-				}
-			}
-			return t;	// Object
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.lang.functional"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.lang.functional"] = true;
-dojo.provide("dojox.lang.functional");
-
-
-
-
-
-}
-
-if(!dojo._hasResource["dojox.lang.functional.fold"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.lang.functional.fold"] = true;
-dojo.provide("dojox.lang.functional.fold");
-
-
-
-// This module adds high-level functions and related constructs:
-//	- "fold" family of functions
-
-// Notes:
-//	- missing high-level functions are provided with the compatible API: 
-//		foldl, foldl1, foldr, foldr1
-//	- missing JS standard functions are provided with the compatible API: 
-//		reduce, reduceRight
-//	- the fold's counterpart: unfold
-
-// Defined methods:
-//	- take any valid lambda argument as the functional argument
-//	- operate on dense arrays
-//	- take a string as the array argument
-//	- take an iterator objects as the array argument (only foldl, foldl1, and reduce)
-
-(function(){
-	var d = dojo, df = dojox.lang.functional, empty = {};
-
-	d.mixin(df, {
-		// classic reduce-class functions
-		foldl: function(/*Array|String|Object*/ a, /*Function*/ f, /*Object*/ z, /*Object?*/ o){
-			// summary: repeatedly applies a binary function to an array from left
-			//	to right using a seed value as a starting point; returns the final
-			//	value.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var i, n;
-			if(d.isArray(a)){
-				// array
-				for(i = 0, n = a.length; i < n; z = f.call(o, z, a[i], i, a), ++i);
-			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
-				// iterator
-				for(i = 0; a.hasNext(); z = f.call(o, z, a.next(), i++, a));
-			}else{
-				// object/dictionary
-				for(i in a){
-					if(!(i in empty)){
-						z = f.call(o, z, a[i], i, a);
-					}
-				}
-			}
-			return z;	// Object
-		},
-		foldl1: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: repeatedly applies a binary function to an array from left
-			//	to right; returns the final value.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var z, i, n;
-			if(d.isArray(a)){
-				// array
-				z = a[0];
-				for(i = 1, n = a.length; i < n; z = f.call(o, z, a[i], i, a), ++i);
-			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
-				// iterator
-				if(a.hasNext()){
-					z = a.next();
-					for(i = 1; a.hasNext(); z = f.call(o, z, a.next(), i++, a));
-				}
-			}else{
-				// object/dictionary
-				var first = true;
-				for(i in a){
-					if(!(i in empty)){
-						if(first){
-							z = a[i];
-							first = false;
-						}else{
-							z = f.call(o, z, a[i], i, a);
-						}
-					}
-				}
-			}
-			return z;	// Object
-		},
-		foldr: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
-			// summary: repeatedly applies a binary function to an array from right
-			//	to left using a seed value as a starting point; returns the final 
-			//	value.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			for(var i = a.length; i > 0; --i, z = f.call(o, z, a[i], i, a));
-			return z;	// Object
-		},
-		foldr1: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: repeatedly applies a binary function to an array from right
-			//	to left; returns the final value.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var n = a.length, z = a[n - 1], i = n - 1;
-			for(; i > 0; --i, z = f.call(o, z, a[i], i, a));
-			return z;	// Object
-		},
-		// JS 1.8 standard array functions, which can take a lambda as a parameter.
-		reduce: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ z){
-			// summary: apply a function simultaneously against two values of the array
-			//	(from left-to-right) as to reduce it to a single value.
-			return arguments.length < 3 ? df.foldl1(a, f) : df.foldl(a, f, z);	// Object
-		},
-		reduceRight: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ z){
-			// summary: apply a function simultaneously against two values of the array
-			//	(from right-to-left) as to reduce it to a single value.
-			return arguments.length < 3 ? df.foldr1(a, f) : df.foldr(a, f, z);	// Object
-		},
-		// the fold's counterpart: unfold
-		unfold: function(/*Function|String|Array*/ pr, /*Function|String|Array*/ f,
-						/*Function|String|Array*/ g, /*Object*/ z, /*Object?*/ o){
-			// summary: builds an array by unfolding a value
-			o = o || d.global; f = df.lambda(f); g = df.lambda(g); pr = df.lambda(pr);
-			var t = [];
-			for(; !pr.call(o, z); t.push(f.call(o, z)), z = g.call(o, z));
-			return t;	// Array
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.lang.functional.reversed"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.lang.functional.reversed"] = true;
-dojo.provide("dojox.lang.functional.reversed");
-
-
-
-// This module adds high-level functions and related constructs:
-//	- reversed versions of array-processing functions similar to standard JS functions
-
-// Notes:
-//	- this module provides reversed versions of standard array-processing functions: 
-//		forEachRev, mapRev, filterRev
-
-// Defined methods:
-//	- take any valid lambda argument as the functional argument
-//	- operate on dense arrays
-//	- take a string as the array argument
-
-(function(){
-	var d = dojo, df = dojox.lang.functional;
-
-	d.mixin(df, {
-		// JS 1.6 standard array functions, which can take a lambda as a parameter.
-		// Consider using dojo._base.array functions, if you don't need the lambda support.
-		filterRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: creates a new array with all elements that pass the test 
-			//	implemented by the provided function.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var t = [], v, i = a.length - 1;
-			for(; i >= 0; --i){
-				v = a[i];
-				if(f.call(o, v, i, a)){ t.push(v); }
-			}
-			return t;	// Array
-		},
-		forEachRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: executes a provided function once per array element.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			for(var i = a.length - 1; i >= 0; f.call(o, a[i], i, a), --i);
-		},
-		mapRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: creates a new array with the results of calling 
-			//	a provided function on every element in this array.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var n = a.length, t = new Array(n), i = n - 1, j = 0;
-			for(; i >= 0; t[j++] = f.call(o, a[i], i, a), --i);
-			return t;	// Array
-		},
-		everyRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: tests whether all elements in the array pass the test 
-			//	implemented by the provided function.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			for(var i = a.length - 1; i >= 0; --i){
-				if(!f.call(o, a[i], i, a)){
-					return false;	// Boolean
-				}
-			}
-			return true;	// Boolean
-		},
-		someRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: tests whether some element in the array passes the test 
-			//	implemented by the provided function.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			for(var i = a.length - 1; i >= 0; --i){
-				if(f.call(o, a[i], i, a)){
-					return true;	// Boolean
-				}
-			}
-			return false;	// Boolean
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojo.colors"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.colors"] = true;
-dojo.provide("dojo.colors");
-
-//TODO: this module appears to break naming conventions
-
-/*=====
-dojo.colors = {
-	// summary: Color utilities
-}
-=====*/
-
-(function(){
-	// this is a standard conversion prescribed by the CSS3 Color Module
-	var hue2rgb = function(m1, m2, h){
-		if(h < 0){ ++h; }
-		if(h > 1){ --h; }
-		var h6 = 6 * h;
-		if(h6 < 1){ return m1 + (m2 - m1) * h6; }
-		if(2 * h < 1){ return m2; }
-		if(3 * h < 2){ return m1 + (m2 - m1) * (2 / 3 - h) * 6; }
-		return m1;
-	};
-	
-	dojo.colorFromRgb = function(/*String*/ color, /*dojo.Color?*/ obj){
-		// summary:
-		//		get rgb(a) array from css-style color declarations
-		// description:
-		//		this function can handle all 4 CSS3 Color Module formats: rgb,
-		//		rgba, hsl, hsla, including rgb(a) with percentage values.
-		var m = color.toLowerCase().match(/^(rgba?|hsla?)\(([\s\.\-,%0-9]+)\)/);
-		if(m){
-			var c = m[2].split(/\s*,\s*/), l = c.length, t = m[1], a;
-			if((t == "rgb" && l == 3) || (t == "rgba" && l == 4)){
-				var r = c[0];
-				if(r.charAt(r.length - 1) == "%"){
-					// 3 rgb percentage values
-					a = dojo.map(c, function(x){
-						return parseFloat(x) * 2.56;
-					});
-					if(l == 4){ a[3] = c[3]; }
-					return dojo.colorFromArray(a, obj);	// dojo.Color
-				}
-				return dojo.colorFromArray(c, obj);	// dojo.Color
-			}
-			if((t == "hsl" && l == 3) || (t == "hsla" && l == 4)){
-				// normalize hsl values
-				var H = ((parseFloat(c[0]) % 360) + 360) % 360 / 360,
-					S = parseFloat(c[1]) / 100,
-					L = parseFloat(c[2]) / 100,
-					// calculate rgb according to the algorithm 
-					// recommended by the CSS3 Color Module 
-					m2 = L <= 0.5 ? L * (S + 1) : L + S - L * S, 
-					m1 = 2 * L - m2;
-				a = [
-					hue2rgb(m1, m2, H + 1 / 3) * 256,
-					hue2rgb(m1, m2, H) * 256,
-					hue2rgb(m1, m2, H - 1 / 3) * 256,
-					1
-				];
-				if(l == 4){ a[3] = c[3]; }
-				return dojo.colorFromArray(a, obj);	// dojo.Color
-			}
-		}
-		return null;	// dojo.Color
-	};
-	
-	var confine = function(c, low, high){
-		// summary:
-		//		sanitize a color component by making sure it is a number,
-		//		and clamping it to valid values
-		c = Number(c);
-		return isNaN(c) ? high : c < low ? low : c > high ? high : c;	// Number
-	};
-	
-	dojo.Color.prototype.sanitize = function(){
-		// summary: makes sure that the object has correct attributes
-		var t = this;
-		t.r = Math.round(confine(t.r, 0, 255));
-		t.g = Math.round(confine(t.g, 0, 255));
-		t.b = Math.round(confine(t.b, 0, 255));
-		t.a = confine(t.a, 0, 1);
-		return this;	// dojo.Color
-	};
-})();
-
-
-dojo.colors.makeGrey = function(/*Number*/ g, /*Number?*/ a){
-	// summary: creates a greyscale color with an optional alpha
-	return dojo.colorFromArray([g, g, g, a]);
-};
-
-// mixin all CSS3 named colors not already in _base, along with SVG 1.0 variant spellings
-dojo.mixin(dojo.Color.named, {
-	aliceblue:	[240,248,255],
-	antiquewhite:	[250,235,215],
-	aquamarine:	[127,255,212],
-	azure:	[240,255,255],
-	beige:	[245,245,220],
-	bisque:	[255,228,196],
-	blanchedalmond:	[255,235,205],
-	blueviolet:	[138,43,226],
-	brown:	[165,42,42],
-	burlywood:	[222,184,135],
-	cadetblue:	[95,158,160],
-	chartreuse:	[127,255,0],
-	chocolate:	[210,105,30],
-	coral:	[255,127,80],
-	cornflowerblue:	[100,149,237],
-	cornsilk:	[255,248,220],
-	crimson:	[220,20,60],
-	cyan:	[0,255,255],
-	darkblue:	[0,0,139],
-	darkcyan:	[0,139,139],
-	darkgoldenrod:	[184,134,11],
-	darkgray:	[169,169,169],
-	darkgreen:	[0,100,0],
-	darkgrey:	[169,169,169],
-	darkkhaki:	[189,183,107],
-	darkmagenta:	[139,0,139],
-	darkolivegreen:	[85,107,47],
-	darkorange:	[255,140,0],
-	darkorchid:	[153,50,204],
-	darkred:	[139,0,0],
-	darksalmon:	[233,150,122],
-	darkseagreen:	[143,188,143],
-	darkslateblue:	[72,61,139],
-	darkslategray:	[47,79,79],
-	darkslategrey:	[47,79,79],
-	darkturquoise:	[0,206,209],
-	darkviolet:	[148,0,211],
-	deeppink:	[255,20,147],
-	deepskyblue:	[0,191,255],
-	dimgray:	[105,105,105],
-	dimgrey:	[105,105,105],
-	dodgerblue:	[30,144,255],
-	firebrick:	[178,34,34],
-	floralwhite:	[255,250,240],
-	forestgreen:	[34,139,34],
-	gainsboro:	[220,220,220],
-	ghostwhite:	[248,248,255],
-	gold:	[255,215,0],
-	goldenrod:	[218,165,32],
-	greenyellow:	[173,255,47],
-	grey:	[128,128,128],
-	honeydew:	[240,255,240],
-	hotpink:	[255,105,180],
-	indianred:	[205,92,92],
-	indigo:	[75,0,130],
-	ivory:	[255,255,240],
-	khaki:	[240,230,140],
-	lavender:	[230,230,250],
-	lavenderblush:	[255,240,245],
-	lawngreen:	[124,252,0],
-	lemonchiffon:	[255,250,205],
-	lightblue:	[173,216,230],
-	lightcoral:	[240,128,128],
-	lightcyan:	[224,255,255],
-	lightgoldenrodyellow:	[250,250,210],
-	lightgray:	[211,211,211],
-	lightgreen:	[144,238,144],
-	lightgrey:	[211,211,211],
-	lightpink:	[255,182,193],
-	lightsalmon:	[255,160,122],
-	lightseagreen:	[32,178,170],
-	lightskyblue:	[135,206,250],
-	lightslategray:	[119,136,153],
-	lightslategrey:	[119,136,153],
-	lightsteelblue:	[176,196,222],
-	lightyellow:	[255,255,224],
-	limegreen:	[50,205,50],
-	linen:	[250,240,230],
-	magenta:	[255,0,255],
-	mediumaquamarine:	[102,205,170],
-	mediumblue:	[0,0,205],
-	mediumorchid:	[186,85,211],
-	mediumpurple:	[147,112,219],
-	mediumseagreen:	[60,179,113],
-	mediumslateblue:	[123,104,238],
-	mediumspringgreen:	[0,250,154],
-	mediumturquoise:	[72,209,204],
-	mediumvioletred:	[199,21,133],
-	midnightblue:	[25,25,112],
-	mintcream:	[245,255,250],
-	mistyrose:	[255,228,225],
-	moccasin:	[255,228,181],
-	navajowhite:	[255,222,173],
-	oldlace:	[253,245,230],
-	olivedrab:	[107,142,35],
-	orange:	[255,165,0],
-	orangered:	[255,69,0],
-	orchid:	[218,112,214],
-	palegoldenrod:	[238,232,170],
-	palegreen:	[152,251,152],
-	paleturquoise:	[175,238,238],
-	palevioletred:	[219,112,147],
-	papayawhip:	[255,239,213],
-	peachpuff:	[255,218,185],
-	peru:	[205,133,63],
-	pink:	[255,192,203],
-	plum:	[221,160,221],
-	powderblue:	[176,224,230],
-	rosybrown:	[188,143,143],
-	royalblue:	[65,105,225],
-	saddlebrown:	[139,69,19],
-	salmon:	[250,128,114],
-	sandybrown:	[244,164,96],
-	seagreen:	[46,139,87],
-	seashell:	[255,245,238],
-	sienna:	[160,82,45],
-	skyblue:	[135,206,235],
-	slateblue:	[106,90,205],
-	slategray:	[112,128,144],
-	slategrey:	[112,128,144],
-	snow:	[255,250,250],
-	springgreen:	[0,255,127],
-	steelblue:	[70,130,180],
-	tan:	[210,180,140],
-	thistle:	[216,191,216],
-	tomato:	[255,99,71],
-	transparent: [0, 0, 0, 0],
-	turquoise:	[64,224,208],
-	violet:	[238,130,238],
-	wheat:	[245,222,179],
-	whitesmoke:	[245,245,245],
-	yellowgreen:	[154,205,50]
-});
-
-}
-
-if(!dojo._hasResource["dojox.color._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.color._base"] = true;
-dojo.provide("dojox.color._base");
-
-
-//	alias all the dojo.Color mechanisms
-dojox.color.Color=dojo.Color;
-dojox.color.blend=dojo.blendColors;
-dojox.color.fromRgb=dojo.colorFromRgb;
-dojox.color.fromHex=dojo.colorFromHex;
-dojox.color.fromArray=dojo.colorFromArray;
-dojox.color.fromString=dojo.colorFromString;
-
-//	alias the dojo.colors mechanisms
-dojox.color.greyscale=dojo.colors.makeGrey;
-
-//	static methods
-dojo.mixin(dojox.color, {
-	fromCmy: function(/* Object|Array|int */cyan, /*int*/magenta, /*int*/yellow){
-		//	summary
-		//	Create a dojox.color.Color from a CMY defined color.
-		//	All colors should be expressed as 0-100 (percentage)
-
-		if(dojo.isArray(cyan)){
-			magenta=cyan[1], yellow=cyan[2], cyan=cyan[0];
-		} else if(dojo.isObject(cyan)){
-			magenta=cyan.m, yellow=cyan.y, cyan=cyan.c;
-		}
-		cyan/=100, magenta/=100, yellow/=100;
-
-		var r=1-cyan, g=1-magenta, b=1-yellow;
-		return new dojox.color.Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) });	//	dojox.color.Color
-	},
-
-	fromCmyk: function(/* Object|Array|int */cyan, /*int*/magenta, /*int*/yellow, /*int*/black){
-		//	summary
-		//	Create a dojox.color.Color from a CMYK defined color.
-		//	All colors should be expressed as 0-100 (percentage)
-
-		if(dojo.isArray(cyan)){
-			magenta=cyan[1], yellow=cyan[2], black=cyan[3], cyan=cyan[0];
-		} else if(dojo.isObject(cyan)){
-			magenta=cyan.m, yellow=cyan.y, black=cyan.b, cyan=cyan.c;
-		}
-		cyan/=100, magenta/=100, yellow/=100, black/=100;
-		var r,g,b;
-		r = 1-Math.min(1, cyan*(1-black)+black);
-		g = 1-Math.min(1, magenta*(1-black)+black);
-		b = 1-Math.min(1, yellow*(1-black)+black);
-		return new dojox.color.Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) });	//	dojox.color.Color
-	},
-	
-	fromHsl: function(/* Object|Array|int */hue, /* int */saturation, /* int */luminosity){
-		//	summary
-		//	Create a dojox.color.Color from an HSL defined color.
-		//	hue from 0-359 (degrees), saturation and luminosity 0-100.
-
-		if(dojo.isArray(hue)){
-			saturation=hue[1], luminosity=hue[2], hue=hue[0];
-		} else if(dojo.isObject(hue)){
-			saturation=hue.s, luminosity=hue.l, hue=hue.h;
-		}
-		saturation/=100;
-		luminosity/=100;
-
-		while(hue<0){ hue+=360; }
-		while(hue>=360){ hue-=360; }
-		
-		var r, g, b;
-		if(hue<120){
-			r=(120-hue)/60, g=hue/60, b=0;
-		} else if (hue<240){
-			r=0, g=(240-hue)/60, b=(hue-120)/60;
-		} else {
-			r=(hue-240)/60, g=0, b=(360-hue)/60;
-		}
-		
-		r=2*saturation*Math.min(r, 1)+(1-saturation);
-		g=2*saturation*Math.min(g, 1)+(1-saturation);
-		b=2*saturation*Math.min(b, 1)+(1-saturation);
-		if(luminosity<0.5){
-			r*=luminosity, g*=luminosity, b*=luminosity;
-		}else{
-			r=(1-luminosity)*r+2*luminosity-1;
-			g=(1-luminosity)*g+2*luminosity-1;
-			b=(1-luminosity)*b+2*luminosity-1;
-		}
-		return new dojox.color.Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) });	//	dojox.color.Color
-	},
-	
-	fromHsv: function(/* Object|Array|int */hue, /* int */saturation, /* int */value){
-		//	summary
-		//	Create a dojox.color.Color from an HSV defined color.
-		//	hue from 0-359 (degrees), saturation and value 0-100.
-
-		if(dojo.isArray(hue)){
-			saturation=hue[1], value=hue[2], hue=hue[0];
-		} else if (dojo.isObject(hue)){
-			saturation=hue.s, value=hue.v, hue=hue.h;
-		}
-		
-		if(hue==360){ hue=0; }
-		saturation/=100;
-		value/=100;
-		
-		var r, g, b;
-		if(saturation==0){
-			r=value, b=value, g=value;
-		}else{
-			var hTemp=hue/60, i=Math.floor(hTemp), f=hTemp-i;
-			var p=value*(1-saturation);
-			var q=value*(1-(saturation*f));
-			var t=value*(1-(saturation*(1-f)));
-			switch(i){
-				case 0:{ r=value, g=t, b=p; break; }
-				case 1:{ r=q, g=value, b=p; break; }
-				case 2:{ r=p, g=value, b=t; break; }
-				case 3:{ r=p, g=q, b=value; break; }
-				case 4:{ r=t, g=p, b=value; break; }
-				case 5:{ r=value, g=p, b=q; break; }
-			}
-		}
-		return new dojox.color.Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) });	//	dojox.color.Color
-	}
-});
-
-//	Conversions directly on dojox.color.Color
-dojo.extend(dojox.color.Color, {
-	toCmy: function(){
-		//	summary
-		//	Convert this Color to a CMY definition.
-		var cyan=1-(this.r/255), magenta=1-(this.g/255), yellow=1-(this.b/255);
-		return { c:Math.round(cyan*100), m:Math.round(magenta*100), y:Math.round(yellow*100) };		//	Object
-	},
-	
-	toCmyk: function(){
-		//	summary
-		//	Convert this Color to a CMYK definition.
-		var cyan, magenta, yellow, black;
-		var r=this.r/255, g=this.g/255, b=this.b/255;
-		black = Math.min(1-r, 1-g, 1-b);
-		cyan = (1-r-black)/(1-black);
-		magenta = (1-g-black)/(1-black);
-		yellow = (1-b-black)/(1-black);
-		return { c:Math.round(cyan*100), m:Math.round(magenta*100), y:Math.round(yellow*100), b:Math.round(black*100) };	//	Object
-	},
-	
-	toHsl: function(){
-		//	summary
-		//	Convert this Color to an HSL definition.
-		var r=this.r/255, g=this.g/255, b=this.b/255;
-		var min = Math.min(r, b, g), max = Math.max(r, g, b);
-		var delta = max-min;
-		var h=0, s=0, l=(min+max)/2;
-		if(l>0 && l<1){
-			s = delta/((l<0.5)?(2*l):(2-2*l));
-		}
-		if(delta>0){
-			if(max==r && max!=g){
-				h+=(g-b)/delta;
-			}
-			if(max==g && max!=b){
-				h+=(2+(b-r)/delta);
-			}
-			if(max==b && max!=r){
-				h+=(4+(r-g)/delta);
-			}
-			h*=60;
-		}
-		return { h:h, s:Math.round(s*100), l:Math.round(l*100) };	//	Object
-	},
-
-	toHsv: function(){
-		//	summary
-		//	Convert this Color to an HSV definition.
-		var r=this.r/255, g=this.g/255, b=this.b/255;
-		var min = Math.min(r, b, g), max = Math.max(r, g, b);
-		var delta = max-min;
-		var h = null, s = (max==0)?0:(delta/max);
-		if(s==0){
-			h = 0;
-		}else{
-			if(r==max){
-				h = 60*(g-b)/delta;
-			}else if(g==max){
-				h = 120 + 60*(b-r)/delta;
-			}else{
-				h = 240 + 60*(r-g)/delta;
-			}
-
-			if(h<0){ h+=360; }
-		}
-		return { h:h, s:Math.round(s*100), v:Math.round(max*100) };	//	Object
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.color"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.color"] = true;
-dojo.provide("dojox.color");
-
-
-}
-
-if(!dojo._hasResource["dojox.color.Palette"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.color.Palette"] = true;
-dojo.provide("dojox.color.Palette");
-
-
-(function(){
-	var dxc = dojox.color;
-	/***************************************************************
-	*	dojox.color.Palette
-	*
-	*	The Palette object is loosely based on the color palettes
-	*	at Kuler (http://kuler.adobe.com).  They are 5 color palettes
-	*	with the base color considered to be the third color in the
-	*	palette (for generation purposes).
-	*
-	*	Palettes can be generated from well-known algorithms or they
-	* 	can be manually created by passing an array to the constructor.
-	*
-	*	Palettes can be transformed, using a set of specific params
-	*	similar to the way shapes can be transformed with dojox.gfx.
-	*	However, unlike with transformations in dojox.gfx, transforming
-	* 	a palette will return you a new Palette object, in effect
-	* 	a clone of the original.
-	***************************************************************/
-
-	//	ctor ----------------------------------------------------------------------------
-	dxc.Palette = function(/* String|Array|dojox.color.Color|dojox.color.Palette */base){
-		//	summary
-		//		An object that represents a palette of colors.
-		//	description
-		//		A Palette is a representation of a set of colors.  While the standard
-		//		number of colors contained in a palette is 5, it can really handle any
-		//		number of colors.
-		//
-		//		A palette is useful for the ability to transform all the colors in it
-		//		using a simple object-based approach.  In addition, you can generate
-		//		palettes using dojox.color.Palette.generate; these generated palettes
-		//		are based on the palette generators at http://kuler.adobe.com.
-		//
-		//	colors: dojox.color.Color[]
-		//		The actual color references in this palette.
-		this.colors = [];
-		if(base instanceof dojox.color.Palette){
-			this.colors = base.colors.slice(0);
-		}
-		else if(base instanceof dojox.color.Color){
-			this.colors = [ null, null, base, null, null ];
-		}
-		else if(dojo.isArray(base)){
-			this.colors = dojo.map(base.slice(0), function(item){
-				if(dojo.isString(item)){ return new dojox.color.Color(item); }
-				return item;
-			});
-		}
-		else if (dojo.isString(base)){
-			this.colors = [ null, null, new dojox.color.Color(base), null, null ];
-		}
-	}
-
-	//	private functions ---------------------------------------------------------------
-
-	//	transformations
-	function tRGBA(p, param, val){
-		var ret = new dojox.color.Palette();
-		ret.colors = [];
-		dojo.forEach(p.colors, function(item){
-			var r=(param=="dr")?item.r+val:item.r,
-				g=(param=="dg")?item.g+val:item.g,
-				b=(param=="db")?item.b+val:item.b,
-				a=(param=="da")?item.a+val:item.a
-			ret.colors.push(new dojox.color.Color({
-				r: Math.min(255, Math.max(0, r)),
-				g: Math.min(255, Math.max(0, g)),
-				b: Math.min(255, Math.max(0, b)),
-				a: Math.min(1, Math.max(0, a))
-			}));
-		});
-		console.log("The return colors are ", ret.colors, " from the original colors ", p.colors);
-		return ret;
-	}
-
-	function tCMY(p, param, val){
-		var ret = new dojox.color.Palette();
-		ret.colors = [];
-		dojo.forEach(p.colors, function(item){
-			var o=item.toCmy(), 
-				c=(param=="dc")?o.c+val:o.c,
-				m=(param=="dm")?o.m+val:o.m,
-				y=(param=="dy")?o.y+val:o.y;
-			ret.colors.push(dojox.color.fromCmy(
-				Math.min(100, Math.max(0, c)),
-				Math.min(100, Math.max(0, m)),
-				Math.min(100, Math.max(0, y))
-			));
-		});
-		return ret;
-	}
-
-	function tCMYK(p, param, val){
-		var ret = new dojox.color.Palette();
-		ret.colors = [];
-		dojo.forEach(p.colors, function(item){
-			var o=item.toCmyk(), 
-				c=(param=="dc")?o.c+val:o.c,
-				m=(param=="dm")?o.m+val:o.m,
-				y=(param=="dy")?o.y+val:o.y,
-				k=(param=="dk")?o.b+val:o.b;
-			ret.colors.push(dojox.color.fromCmyk(
-				Math.min(100, Math.max(0, c)),
-				Math.min(100, Math.max(0, m)),
-				Math.min(100, Math.max(0, y)),
-				Math.min(100, Math.max(0, k))
-			));
-		});
-		return ret;
-	}
-
-	function tHSL(p, param, val){
-		var ret = new dojox.color.Palette();
-		ret.colors = [];
-		dojo.forEach(p.colors, function(item){
-			var o=item.toHsl(), 
-				h=(param=="dh")?o.h+val:o.h,
-				s=(param=="ds")?o.s+val:o.s,
-				l=(param=="dl")?o.l+val:o.l;
-			ret.colors.push(dojox.color.fromHsl(h%360, Math.min(100, Math.max(0, s)), Math.min(100, Math.max(0, l))));
-		});
-		return ret;
-	}
-
-	function tHSV(p, param, val){
-		var ret = new dojox.color.Palette();
-		ret.colors = [];
-		dojo.forEach(p.colors, function(item){
-			var o=item.toHsv(), 
-				h=(param=="dh")?o.h+val:o.h,
-				s=(param=="ds")?o.s+val:o.s,
-				v=(param=="dv")?o.v+val:o.v;
-			ret.colors.push(dojox.color.fromHsv(h%360, Math.min(100, Math.max(0, s)), Math.min(100, Math.max(0, v))));
-		});
-		return ret;
-	}
-
-	//	helper functions
-	function rangeDiff(val, low, high){
-		//	given the value in a range from 0 to high, find the equiv
-		//		using the range low to high.
-		return high-((high-val)*((high-low)/high));
-	}
-
-	//	object methods ---------------------------------------------------------------
-	dojo.extend(dxc.Palette, {
-		transform: function(/* Object */kwArgs){
-			//	summary
-			//		Transform the palette using a specific transformation function
-			//		and a set of transformation parameters.
-			//	description
-			//		{palette}.transform is a simple way to uniformly transform
-			//		all of the colors in a palette using any of 5 formulae:
-			//		RGBA, HSL, HSV, CMYK or CMY.
-			//
-			//		Once the forumula to be used is determined, you can pass any
-			//		number of parameters based on the formula "d"[param]; for instance,
-			//		{ use: "rgba", dr: 20, dg: -50 } will take all of the colors in
-			//		palette, add 20 to the R value and subtract 50 from the G value.
-			//
-			//		Unlike other types of transformations, transform does *not* alter
-			//		the original palette but will instead return a new one.
-			var fn=tRGBA;	//	the default transform function.
-			if(kwArgs.use){
-				//	we are being specific about the algo we want to use.
-				var use=kwArgs.use.toLowerCase();
-				if(use.indexOf("hs")==0){
-					if(use.charAt(2)=="l"){ fn=tHSL; }
-					else { fn=tHSV; }
-				}
-				else if(use.indexOf("cmy")==0){
-					if(use.charAt(3)=="k"){ fn=tCMYK; }
-					else { fn=tCMY; }
-				}
-			}
-			//	try to guess the best choice.
-			else if("dc" in kwArgs || "dm" in kwArgs || "dy" in kwArgs){
-				if("dk" in kwArgs){ fn = tCMYK; }
-				else { fn = tCMY; }
-			}
-			else if("dh" in kwArgs || "ds" in kwArgs){
-				if("dv" in kwArgs){ fn = tHSV; }
-				else { fn = tHSL; }
-			}
-
-			var palette = this;
-			for(var p in kwArgs){
-				//	ignore use
-				if(p=="use"){ continue; }
-				palette = fn(palette, p, kwArgs[p]);
-			}
-			return palette;		//	dojox.color.Palette
-		},
-		clone: function(){
-			//	summary
-			//		Clones the current palette.
-			return new dxc.Palette(this);	//	dojox.color.Palette
-		}
-	});
-
-	//	static methods ---------------------------------------------------------------
-	dojo.mixin(dxc.Palette, {
-		generators: {
-			analogous:function(/* Object */args){
-				var high=args.high||60, 	//	delta between base hue and highest hue (subtracted from base)
-					low=args.low||18,		//	delta between base hue and lowest hue (added to base)
-					base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
-					hsv=base.toHsv();
-
-				//	generate our hue angle differences
-				var h=[
-					(hsv.h+low+360)%360,
-					(hsv.h+Math.round(low/2)+360)%360,
-					hsv.h,
-					(hsv.h-Math.round(high/2)+360)%360,
-					(hsv.h-high+360)%360
-				];
-
-				var s1=Math.max(10, (hsv.s<=95)?hsv.s+5:(100-(hsv.s-95))),
-					s2=(hsv.s>1)?hsv.s-1:21-hsv.s,
-					v1=(hsv.v>=92)?hsv.v-9:Math.max(hsv.v+9, 20),
-					v2=(hsv.v<=90)?Math.max(hsv.v+5, 20):(95+Math.ceil((hsv.v-90)/2)),
-					s=[ s1, s2, hsv.s, s1, s1 ],
-					v=[ v1, v2, hsv.v, v1, v2 ]
-
-				return new dxc.Palette(dojo.map(h, function(hue, i){
-					return dojox.color.fromHsv(hue, s[i], v[i]);
-				}));		//	dojox.color.Palette
-			},
-
-			monochromatic: function(/* Object */args){
-				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
-					hsv = base.toHsv();
-				
-				//	figure out the saturation and value
-				var s1 = (hsv.s-30>9)?hsv.s-30:hsv.s+30,
-					s2 = hsv.s,
-					v1 = rangeDiff(hsv.v, 20, 100),
-					v2 = (hsv.v-20>20)?hsv.v-20:hsv.v+60,
-					v3 = (hsv.v-50>20)?hsv.v-50:hsv.v+30;
-
-				return new dxc.Palette([
-					dojox.color.fromHsv(hsv.h, s1, v1),
-					dojox.color.fromHsv(hsv.h, s2, v3),
-					base,
-					dojox.color.fromHsv(hsv.h, s1, v3),
-					dojox.color.fromHsv(hsv.h, s2, v2)
-				]);		//	dojox.color.Palette
-			},
-
-			triadic: function(/* Object */args){
-				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
-					hsv = base.toHsv();
-
-				var h1 = (hsv.h+57+360)%360,
-					h2 = (hsv.h-157+360)%360,
-					s1 = (hsv.s>20)?hsv.s-10:hsv.s+10,
-					s2 = (hsv.s>90)?hsv.s-10:hsv.s+10,
-					s3 = (hsv.s>95)?hsv.s-5:hsv.s+5,
-					v1 = (hsv.v-20>20)?hsv.v-20:hsv.v+20,
-					v2 = (hsv.v-30>20)?hsv.v-30:hsv.v+30,
-					v3 = (hsv.v-30>70)?hsv.v-30:hsv.v+30;
-
-				return new dxc.Palette([
-					dojox.color.fromHsv(h1, s1, hsv.v),
-					dojox.color.fromHsv(hsv.h, s2, v2),
-					base,
-					dojox.color.fromHsv(h2, s2, v1),
-					dojox.color.fromHsv(h2, s3, v3)
-				]);		//	dojox.color.Palette
-			},
-
-			complementary: function(/* Object */args){
-				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
-					hsv = base.toHsv();
-
-				var h1 = ((hsv.h*2)+137<360)?(hsv.h*2)+137:Math.floor(hsv.h/2)-137,
-					s1 = Math.max(hsv.s-10, 0),
-					s2 = rangeDiff(hsv.s, 10, 100),
-					s3 = Math.min(100, hsv.s+20),
-					v1 = Math.min(100, hsv.v+30),
-					v2 = (hsv.v>20)?hsv.v-30:hsv.v+30;
-
-				return new dxc.Palette([
-					dojox.color.fromHsv(hsv.h, s1, v1),
-					dojox.color.fromHsv(hsv.h, s2, v2),
-					base,
-					dojox.color.fromHsv(h1, s3, v2),
-					dojox.color.fromHsv(h1, hsv.s, hsv.v)
-				]);		//	dojox.color.Palette
-			},
-
-			splitComplementary: function(/* Object */args){
-				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
-					dangle = args.da || 30,
-					hsv = base.toHsv();
-
-				var baseh = ((hsv.h*2)+137<360)?(hsv.h*2)+137:Math.floor(hsv.h/2)-137,
-					h1 = (baseh-dangle+360)%360,
-					h2 = (baseh+dangle)%360,
-					s1 = Math.max(hsv.s-10, 0),
-					s2 = rangeDiff(hsv.s, 10, 100),
-					s3 = Math.min(100, hsv.s+20),
-					v1 = Math.min(100, hsv.v+30),
-					v2 = (hsv.v>20)?hsv.v-30:hsv.v+30;
-
-				return new dxc.Palette([
-					dojox.color.fromHsv(h1, s1, v1),
-					dojox.color.fromHsv(h1, s2, v2),
-					base,
-					dojox.color.fromHsv(h2, s3, v2),
-					dojox.color.fromHsv(h2, hsv.s, hsv.v)
-				]);		//	dojox.color.Palette
-			},
-
-			compound: function(/* Object */args){
-				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
-					hsv = base.toHsv();
-
-				var h1 = ((hsv.h*2)+18<360)?(hsv.h*2)+18:Math.floor(hsv.h/2)-18,
-					h2 = ((hsv.h*2)+120<360)?(hsv.h*2)+120:Math.floor(hsv.h/2)-120,
-					h3 = ((hsv.h*2)+99<360)?(hsv.h*2)+99:Math.floor(hsv.h/2)-99,
-					s1 = (hsv.s-40>10)?hsv.s-40:hsv.s+40,
-					s2 = (hsv.s-10>80)?hsv.s-10:hsv.s+10,
-					s3 = (hsv.s-25>10)?hsv.s-25:hsv.s+25,
-					v1 = (hsv.v-40>10)?hsv.v-40:hsv.v+40,
-					v2 = (hsv.v-20>80)?hsv.v-20:hsv.v+20,
-					v3 = Math.max(hsv.v, 20);
-
-				return new dxc.Palette([
-					dojox.color.fromHsv(h1, s1, v1),
-					dojox.color.fromHsv(h1, s2, v2),
-					base,
-					dojox.color.fromHsv(h2, s3, v3),
-					dojox.color.fromHsv(h3, s2, v2)
-				]);		//	dojox.color.Palette
-			},
-
-			shades: function(/* Object */args){
-				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
-					hsv = base.toHsv();
-
-				var s  = (hsv.s==100 && hsv.v==0)?0:hsv.s,
-					v1 = (hsv.v-50>20)?hsv.v-50:hsv.v+30,
-					v2 = (hsv.v-25>=20)?hsv.v-25:hsv.v+55,
-					v3 = (hsv.v-75>=20)?hsv.v-75:hsv.v+5,
-					v4 = Math.max(hsv.v-10, 20);
-
-				return new dxc.Palette([
-					new dojox.color.fromHsv(hsv.h, s, v1),
-					new dojox.color.fromHsv(hsv.h, s, v2),
-					base,
-					new dojox.color.fromHsv(hsv.h, s, v3),
-					new dojox.color.fromHsv(hsv.h, s, v4)
-				]);		//	dojox.color.Palette
-			}
-		},
-		generate: function(/* String|dojox.color.Color */base, /* Function|String */type){
-			//	summary
-			//		Generate a new Palette using any of the named functions in
-			//		dojox.color.Palette.generators or an optional function definition.
-			if(dojo.isFunction(type)){
-				return type({ base: base });	//	dojox.color.Palette
-			}
-			else if(dxc.Palette.generators[type]){
-				return dxc.Palette.generators[type]({ base: base });	//	dojox.color.Palette
-			}
-			throw new Error("dojox.color.Palette.generate: the specified generator ('" + type + "') does not exist.");
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.Theme"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.Theme"] = true;
-dojo.provide("dojox.charting.Theme");
-
-
-
-(function(){
-	var dxc=dojox.charting;
-	//	TODO: Legend information
-
-	dxc.Theme = function(/*Object?*/ kwArgs){
-		kwArgs=kwArgs||{};
-		var def = dxc.Theme._def;
-		dojo.forEach(["chart", "plotarea", "axis", "series", "marker"], function(n){
-			this[n] = dojo.delegate(def[n], kwArgs[n]||{});
-		}, this);
-		this.markers = dojo.delegate(dxc.Theme.Markers, kwArgs.markers||{});
-		this.colors = [];
-		this.antiAlias = ("antiAlias" in kwArgs)?kwArgs.antiAlias:true;
-		this.assignColors = ("assignColors" in kwArgs)?kwArgs.assignColors:true;
-		this.assignMarkers = ("assignMarkers" in kwArgs)?kwArgs.assignMarkers:true;
-
-		//	push the colors, use _def colors if none passed.
-		kwArgs.colors = kwArgs.colors||def.colors;
-		dojo.forEach(kwArgs.colors, function(item){ 
-			this.colors.push(item); 
-		}, this);
-
-		//	private variables for color and marker indexing
-		this._current = { color:0, marker: 0 };
-		this._markers = [];
-		this._buildMarkerArray();
-	};
-
-	//	"static" fields
-	//	default markers.
-	//	A marker is defined by an SVG path segment; it should be defined as
-	//		relative motion, and with the assumption that the path segment
-	//		will be moved to the value point (i.e prepend Mx,y)
-	dxc.Theme.Markers={
-		CIRCLE:		"m-3,0 c0,-4 6,-4 6,0 m-6,0 c0,4 6,4 6,0", 
-		SQUARE:		"m-3,-3 l0,6 6,0 0,-6 z", 
-		DIAMOND:	"m0,-3 l3,3 -3,3 -3,-3 z", 
-		CROSS:		"m0,-3 l0,6 m-3,-3 l6,0", 
-		X:			"m-3,-3 l6,6 m0,-6 l-6,6", 
-		TRIANGLE:	"m-3,3 l3,-6 3,6 z", 
-		TRIANGLE_INVERTED:"m-3,-3 l3,6 3,-6 z"
-	};
-	dxc.Theme._def={
-		//	all objects are structs used directly in dojox.gfx
-		chart:{ 
-			stroke:null,
-			fill: "white"
-		},
-		plotarea:{ 
-			stroke:null,
-			fill: "white"
-		},
-		//	TODO: label rotation on axis
-		axis:{
-			stroke:	{ //	the axis itself
-				color:"#333",
-				width:1
-			},
-			/*
-			line:	{ //	in the future can be used for gridlines
-				color:"#ccc",
-				width:1,
-				style:"Dot",
-				cap:"round"
-			},
-			*/
-			majorTick:	{ //	major ticks on axis, and used for major gridlines
-				color:"#666",
-				width:1, 
-				length:6, 
-				position:"center"
-			},
-			minorTick:	{ //	minor ticks on axis, and used for minor gridlines
-				color:"#666", 
-				width:0.8, 
-				length:3, 
-				position:"center"
-			},	
-			microTick:	{ //	minor ticks on axis, and used for minor gridlines
-				color:"#666", 
-				width:0.5, 
-				length:1, 
-				position:"center"
-			},	
-			font: "normal normal normal 7pt Tahoma", //	labels on axis
-			fontColor:"#333"						//	color of labels
-		},
-		series:{
-			outline: {width: 0.1, color: "#ccc"},							//	line or outline
-			stroke: {width: 1.5, color: "#333"},							//	line or outline
-			fill: "#ccc",												//	fill, if appropriate
-			font: "normal normal normal 7pt Tahoma",					//	if there's a label
-			fontColor: "#000"											// 	color of labels
-		},
-		marker:{	//	any markers on a series.
-			stroke: {width:1},											//	stroke or outline
-			fill: "#333",												//	fill if needed
-			font: "normal normal normal 7pt Tahoma",					//	label
-			fontColor: "#000"
-		},
-		colors:[ "#54544c","#858e94","#6e767a","#948585","#474747" ]
-	};
-	
-	//	prototype methods
-	dojo.extend(dxc.Theme, {
-		defineColors: function(obj){
-			//	summary:
-			//		Generate a set of colors for the theme based on keyword
-			//		arguments
-			var kwArgs=obj||{};
-
-			//	note that we've changed the default number from 32 to 4 colors
-			//	are cycled anyways.
-			var c=[], n=kwArgs.num||5;	//	the number of colors to generate
-			if(kwArgs.colors){
-				//	we have an array of colors predefined, so fix for the number of series.
-				var l=kwArgs.colors.length;
-				for(var i=0; i<n; i++){
-					c.push(kwArgs.colors[i%l]);
-				}
-				this.colors=c;
-			}else if(kwArgs.hue){
-				//	single hue, generate a set based on brightness
-				var s=kwArgs.saturation||100;	//	saturation
-				var st=kwArgs.low||30;
-				var end=kwArgs.high||90;
-				//	we'd like it to be a little on the darker side.
-				var l=(end+st)/2;
-
-				//	alternately, use "shades"
-				this.colors = dojox.color.Palette.generate(
-					dojox.color.fromHsv(kwArgs.hue, s, l), "monochromatic"
-				).colors;
-			}else if(kwArgs.generator){
-				//	pass a base color and the name of a generator
-				this.colors=dojox.color.Palette.generate(kwArgs.base, kwArgs.generator).colors;
-			}
-		},
-	
-		_buildMarkerArray: function(){
-			this._markers = [];
-			for(var p in this.markers){ this._markers.push(this.markers[p]); }
-			//	reset the position
-			this._current.marker=0;
-		},
-
-		_clone: function(){
-			//	summary:
-			//		Return a clone of this theme, with the position vars reset to 0.
-			return new dxc.Theme({
-				chart: this.chart,
-				plotarea: this.plotarea,
-				axis: this.axis,
-				series: this.series,
-				marker: this.marker,
-				antiAlias: this.antiAlias,
-				assignColors: this.assignColors,
-				assignMarkers: this.assigneMarkers,
-				colors: dojo.delegate(this.colors)
-			});
-		},
-
-		addMarker:function(/*String*/ name, /*String*/ segment){
-			//	summary:
-			//		Add a custom marker to this theme.
-			//	example:
-			//	|	myTheme.addMarker("Ellipse", foo);
-			this.markers[name]=segment;
-			this._buildMarkerArray();
-		},
-		setMarkers:function(/*Object*/ obj){
-			//	summary:
-			//		Set all the markers of this theme at once.  obj should be a
-			//		dictionary of keys and path segments.
-			//
-			//	example:
-			//	|	myTheme.setMarkers({ "CIRCLE": foo });
-			this.markers=obj;
-			this._buildMarkerArray();
-		},
-
-		next: function(/*String?*/ type){
-			//	summary:
-			//		get either the next color or the next marker, depending on
-			//		what was passed. If type is not passed, it assumes color.
-			//	type:
-			//		Optional. One of either "color" or "marker". Defaults to
-			//		"color".
-			//	example:
-			//	|	var color = myTheme.next();
-			//	|	var color = myTheme.next("color");
-			//	|	var marker = myTheme.next("marker");
-			if(type == "marker"){
-				return this._markers[ this._current.marker++ % this._markers.length ];
-			}else{
-				return this.colors[ this._current.color++ % this.colors.length ];
-			}
-		},
-		clear: function(){
-			// summary:
-			//		resets both marker and color counters back to the start.
-			//		Subsequent calls to `next` will retrievie the first value
-			//		of each depending on the passed type.
-			this._current = {color: 0, marker: 0};
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.Element"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.Element"] = true;
-dojo.provide("dojox.charting.Element");
-
-dojo.declare("dojox.charting.Element", null, {
-	constructor: function(chart){
-		this.chart = chart;
-		this.group = null;
-		this.htmlElements = [];
-		this.dirty = true;
-	},
-	createGroup: function(creator){
-		if(!creator){ creator = this.chart.surface; }
-		if(!this.group){
-			this.group = creator.createGroup();
-		}
-		return this;
-	},
-	purgeGroup: function(){
-		this.destroyHtmlElements();
-		if(this.group){
-			this.group.clear();
-			this.group.removeShape();
-			this.group = null;
-		}
-		this.dirty = true;
-		return this;
-	},
-	cleanGroup: function(creator){
-		this.destroyHtmlElements();
-		if(!creator){ creator = this.chart.surface; }
-		if(this.group){
-			this.group.clear();
-		}else{
-			this.group = creator.createGroup();
-		}
-		this.dirty = true;
-		return this;
-	},
-	destroyHtmlElements: function(){
-		if(this.htmlElements.length){
-			dojo.forEach(this.htmlElements, dojo.destroy);
-			this.htmlElements = [];
-		}
-	},
-	destroy: function(){
-		this.purgeGroup();
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.charting.Series"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.Series"] = true;
-dojo.provide("dojox.charting.Series");
-
-
-
-dojo.declare("dojox.charting.Series", dojox.charting.Element, {
-	constructor: function(chart, data, kwArgs){
-		dojo.mixin(this, kwArgs);
-		if(typeof this.plot != "string"){ this.plot = "default"; }
-		this.data = data;
-		this.dirty = true;
-		this.clear();
-	},
-	clear: function(){
-		this.dyn = {};
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.charting.scaler.common"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.scaler.common"] = true;
-dojo.provide("dojox.charting.scaler.common");
-
-(function(){
-	var eq = function(/*Number*/ a, /*Number*/ b){
-		// summary: compare two FP numbers for equality
-		return Math.abs(a - b) <= 1e-6 * (Math.abs(a) + Math.abs(b));	// Boolean
-	};
-	
-	dojo.mixin(dojox.charting.scaler.common, {
-		findString: function(/*String*/ val, /*Array*/ text){
-			val = val.toLowerCase();
-			for(var i = 0; i < text.length; ++i){
-				if(val == text[i]){ return true; }
-			}
-			return false;
-		},
-		getNumericLabel: function(/*Number*/ number, /*Number*/ precision, /*Object*/ kwArgs){
-			var def = kwArgs.fixed ? 
-						number.toFixed(precision < 0 ? -precision : 0) : 
-						number.toString();
-			if(kwArgs.labelFunc){
-				var r = kwArgs.labelFunc(def, number, precision);
-				if(r){ return r; }
-				// else fall through to the regular labels search
-			}
-			if(kwArgs.labels){
-				// classic binary search
-				var l = kwArgs.labels, lo = 0, hi = l.length;
-				while(lo < hi){
-					var mid = Math.floor((lo + hi) / 2), val = l[mid].value;
-					if(val < number){
-						lo = mid + 1;
-					}else{
-						hi = mid;
-					}
-				}
-				// lets take into account FP errors
-				if(lo < l.length && eq(l[lo].value, number)){
-					return l[lo].text;
-				}
-				--lo;
-				if(lo >= 0 && lo < l.length && eq(l[lo].value, number)){
-					return l[lo].text;
-				}
-				lo += 2;
-				if(lo < l.length && eq(l[lo].value, number)){
-					return l[lo].text;
-				}
-				// otherwise we will produce a number
-			}
-			return def;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.scaler.linear"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.scaler.linear"] = true;
-dojo.provide("dojox.charting.scaler.linear");
-
-
-(function(){
-	var deltaLimit = 3,	// pixels
-		dc = dojox.charting, dcs = dc.scaler, dcsc = dcs.common,
-		findString = dcsc.findString,
-		getLabel = dcsc.getNumericLabel;
-	
-	var calcTicks = function(min, max, kwArgs, majorTick, minorTick, microTick, span){
-		kwArgs = dojo.delegate(kwArgs);
-		if(!majorTick){
-			if(kwArgs.fixUpper == "major"){ kwArgs.fixUpper = "minor"; }
-			if(kwArgs.fixLower == "major"){ kwArgs.fixLower = "minor"; }
-		}
-		if(!minorTick){
-			if(kwArgs.fixUpper == "minor"){ kwArgs.fixUpper = "micro"; }
-			if(kwArgs.fixLower == "minor"){ kwArgs.fixLower = "micro"; }
-		}
-		if(!microTick){
-			if(kwArgs.fixUpper == "micro"){ kwArgs.fixUpper = "none"; }
-			if(kwArgs.fixLower == "micro"){ kwArgs.fixLower = "none"; }
-		}
-		var lowerBound = findString(kwArgs.fixLower, ["major"]) ?
-				Math.floor(kwArgs.min / majorTick) * majorTick :
-					findString(kwArgs.fixLower, ["minor"]) ?
-						Math.floor(kwArgs.min / minorTick) * minorTick :
-							findString(kwArgs.fixLower, ["micro"]) ?
-								Math.floor(kwArgs.min / microTick) * microTick : kwArgs.min,
-			upperBound = findString(kwArgs.fixUpper, ["major"]) ?
-				Math.ceil(kwArgs.max / majorTick) * majorTick :
-					findString(kwArgs.fixUpper, ["minor"]) ?
-						Math.ceil(kwArgs.max / minorTick) * minorTick :
-							findString(kwArgs.fixUpper, ["micro"]) ?
-								Math.ceil(kwArgs.max / microTick) * microTick : kwArgs.max;
-								
-		if(kwArgs.useMin){ min = lowerBound; }
-		if(kwArgs.useMax){ max = upperBound; }
-		
-		var majorStart = (!majorTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major"])) ?
-				min : Math.ceil(min / majorTick) * majorTick,
-			minorStart = (!minorTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major", "minor"])) ?
-				min : Math.ceil(min / minorTick) * minorTick,
-			microStart = (! microTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major", "minor", "micro"])) ?
-				min : Math.ceil(min / microTick) * microTick,
-			majorCount = !majorTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major"]) ?
-				Math.round((max - majorStart) / majorTick) :
-				Math.floor((max - majorStart) / majorTick)) + 1,
-			minorCount = !minorTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major", "minor"]) ?
-				Math.round((max - minorStart) / minorTick) :
-				Math.floor((max - minorStart) / minorTick)) + 1,
-			microCount = !microTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major", "minor", "micro"]) ?
-				Math.round((max - microStart) / microTick) :
-				Math.floor((max - microStart) / microTick)) + 1,
-			minorPerMajor  = minorTick ? Math.round(majorTick / minorTick) : 0,
-			microPerMinor  = microTick ? Math.round(minorTick / microTick) : 0,
-			majorPrecision = majorTick ? Math.floor(Math.log(majorTick) / Math.LN10) : 0,
-			minorPrecision = minorTick ? Math.floor(Math.log(minorTick) / Math.LN10) : 0,
-			scale = span / (max - min);	
-		if(!isFinite(scale)){ scale = 1; }
-		
-		return {
-			bounds: {
-				lower:	lowerBound,
-				upper:	upperBound,
-				from:	min,
-				to:		max,
-				scale:	scale,
-				span:	span
-			},
-			major: {
-				tick:	majorTick,
-				start:	majorStart,
-				count:	majorCount,
-				prec:	majorPrecision
-			},
-			minor: {
-				tick:	minorTick,
-				start:	minorStart,
-				count:	minorCount,
-				prec:	minorPrecision
-			},
-			micro: {
-				tick:	microTick,
-				start:	microStart,
-				count:	microCount,
-				prec:	0
-			},
-			minorPerMajor:	minorPerMajor,
-			microPerMinor:	microPerMinor,
-			scaler:			dcs.linear
-		};
-	};
-	
-	dojo.mixin(dojox.charting.scaler.linear, {
-		buildScaler: function(/*Number*/ min, /*Number*/ max, /*Number*/ span, /*Object*/ kwArgs){
-			var h = {fixUpper: "none", fixLower: "none", natural: false};
-			if(kwArgs){
-				if("fixUpper" in kwArgs){ h.fixUpper = String(kwArgs.fixUpper); }
-				if("fixLower" in kwArgs){ h.fixLower = String(kwArgs.fixLower); }
-				if("natural"  in kwArgs){ h.natural  = Boolean(kwArgs.natural); }
-			}
-			
-			// update bounds
-			if("min" in kwArgs){ min = kwArgs.min; }
-			if("max" in kwArgs){ max = kwArgs.max; }
-			if(kwArgs.includeZero){
-				if(min > 0){ min = 0; }
-				if(max < 0){ max = 0; }
-			}
-			h.min = min;
-			h.useMin = true;
-			h.max = max;
-			h.useMax = true;
-			
-			if("from" in kwArgs){
-				min = kwArgs.from;
-				h.useMin = false;
-			}
-			if("to" in kwArgs){
-				max = kwArgs.to;
-				h.useMax = false;
-			}
-			
-			// check for erroneous condition
-			if(max <= min){
-				return calcTicks(min, max, h, 0, 0, 0, span);	// Object
-			}
-			
-			var mag = Math.floor(Math.log(max - min) / Math.LN10),
-				major = kwArgs && ("majorTickStep" in kwArgs) ? kwArgs.majorTickStep : Math.pow(10, mag), 
-				minor = 0, micro = 0, ticks;
-				
-			// calculate minor ticks
-			if(kwArgs && ("minorTickStep" in kwArgs)){
-				minor = kwArgs.minorTickStep;
-			}else{
-				do{
-					minor = major / 10;
-					if(!h.natural || minor > 0.9){
-						ticks = calcTicks(min, max, h, major, minor, 0, span);
-						if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
-					}
-					minor = major / 5;
-					if(!h.natural || minor > 0.9){
-						ticks = calcTicks(min, max, h, major, minor, 0, span);
-						if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
-					}
-					minor = major / 2;
-					if(!h.natural || minor > 0.9){
-						ticks = calcTicks(min, max, h, major, minor, 0, span);
-						if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
-					}
-					return calcTicks(min, max, h, major, 0, 0, span);	// Object
-				}while(false);
-			}
-	
-			// calculate micro ticks
-			if(kwArgs && ("microTickStep" in kwArgs)){
-				micro = kwArgs.microTickStep;
-				ticks = calcTicks(min, max, h, major, minor, micro, span);
-			}else{
-				do{
-					micro = minor / 10;
-					if(!h.natural || micro > 0.9){
-						ticks = calcTicks(min, max, h, major, minor, micro, span);
-						if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
-					}
-					micro = minor / 5;
-					if(!h.natural || micro > 0.9){
-						ticks = calcTicks(min, max, h, major, minor, micro, span);
-						if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
-					}
-					micro = minor / 2;
-					if(!h.natural || micro > 0.9){
-						ticks = calcTicks(min, max, h, major, minor, micro, span);
-						if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
-					}
-					micro = 0;
-				}while(false);
-			}
-	
-			return micro ? ticks : calcTicks(min, max, h, major, minor, 0, span);	// Object
-		},
-		buildTicks: function(/*Object*/ scaler, /*Object*/ kwArgs){
-			var step, next, tick,
-				nextMajor = scaler.major.start, 
-				nextMinor = scaler.minor.start, 
-				nextMicro = scaler.micro.start;
-			if(kwArgs.microTicks && scaler.micro.tick){
-				step = scaler.micro.tick, next = nextMicro;
-			}else if(kwArgs.minorTicks && scaler.minor.tick){
-				step = scaler.minor.tick, next = nextMinor;
-			}else if(scaler.major.tick){
-				step = scaler.major.tick, next = nextMajor;
-			}else{
-				// no ticks
-				return null;
-			}
-			// make sure that we have finite bounds
-			var revScale = 1 / scaler.bounds.scale;
-			if(scaler.bounds.to <= scaler.bounds.from || isNaN(revScale) || !isFinite(revScale) ||
-					step <= 0 || isNaN(step) || !isFinite(step)){
-				// no ticks
-				return null;
-			}
-			// loop over all ticks
-			var majorTicks = [], minorTicks = [], microTicks = [];
-			while(next <= scaler.bounds.to + revScale){
-				if(Math.abs(nextMajor - next) < step / 2){
-					// major tick
-					tick = {value: nextMajor};
-					if(kwArgs.majorLabels){
-						tick.label = getLabel(nextMajor, scaler.major.prec, kwArgs);
-					}
-					majorTicks.push(tick);
-					nextMajor += scaler.major.tick;
-					nextMinor += scaler.minor.tick;
-					nextMicro += scaler.micro.tick;
-				}else if(Math.abs(nextMinor - next) < step / 2){
-					// minor tick
-					if(kwArgs.minorTicks){
-						tick = {value: nextMinor};
-						if(kwArgs.minorLabels && (scaler.minMinorStep <= scaler.minor.tick * scaler.bounds.scale)){
-							tick.label = getLabel(nextMinor, scaler.minor.prec, kwArgs);
-						}
-						minorTicks.push(tick);
-					}
-					nextMinor += scaler.minor.tick;
-					nextMicro += scaler.micro.tick;
-				}else{
-					// micro tick
-					if(kwArgs.microTicks){
-						microTicks.push({value: nextMicro});
-					}
-					nextMicro += scaler.micro.tick;
-				}
-				next += step;
-			}
-			return {major: majorTicks, minor: minorTicks, micro: microTicks};	// Object
-		},
-		getTransformerFromModel: function(/*Object*/ scaler){
-			var offset = scaler.bounds.from, scale = scaler.bounds.scale;
-			return function(x){ return (x - offset) * scale; };	// Function
-		},
-		getTransformerFromPlot: function(/*Object*/ scaler){
-			var offset = scaler.bounds.from, scale = scaler.bounds.scale;
-			return function(x){ return x / scale + offset; };	// Function
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.axis2d.common"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.axis2d.common"] = true;
-dojo.provide("dojox.charting.axis2d.common");
-
-
-
-(function(){
-	var g = dojox.gfx;
-	
-	var clearNode = function(s){
-		s.marginLeft   = "0px";
-		s.marginTop    = "0px";
-		s.marginRight  = "0px";
-		s.marginBottom = "0px";
-		s.paddingLeft   = "0px";
-		s.paddingTop    = "0px";
-		s.paddingRight  = "0px";
-		s.paddingBottom = "0px";
-		s.borderLeftWidth   = "0px";
-		s.borderTopWidth    = "0px";
-		s.borderRightWidth  = "0px";
-		s.borderBottomWidth = "0px";
-	};
-	
-	var getBoxWidth = function(n){
-		// marginBox is incredibly slow, so avoid it if we can
-		if(n["getBoundingClientRect"]){
-			var bcr = n.getBoundingClientRect();
-			return bcr.width || (bcr.right - bcr.left);
-		}else{
-			return dojo.marginBox(n).w;
-		}
-	};
-	
-	dojo.mixin(dojox.charting.axis2d.common, {
-		createText: {
-			gfx: function(chart, creator, x, y, align, text, font, fontColor){
-				return creator.createText({
-					x: x, y: y, text: text, align: align
-				}).setFont(font).setFill(fontColor);
-			},
-			html: function(chart, creator, x, y, align, text, font, fontColor, labelWidth){
-				// setup the text node
-				var p = dojo.doc.createElement("div"), s = p.style, boxWidth;
-				clearNode(s);
-				s.font = font;
-				p.innerHTML = String(text).replace(/\s/g, " ");
-				s.color = fontColor;
-				// measure the size
-				s.position = "absolute";
-				s.left = "-10000px";
-				dojo.body().appendChild(p);
-				var size = g.normalizedLength(g.splitFontString(font).size);
-				
-				// do we need to calculate the label width?
-				if(!labelWidth){
-					boxWidth = getBoxWidth(p);
-				}
-
-				// new settings for the text node
-				dojo.body().removeChild(p);
-				
-				s.position = "relative";
-				if(labelWidth){
-					s.width = labelWidth + "px";
-					// s.border = "1px dotted grey";
-					switch(align){
-						case "middle":
-							s.textAlign = "center";
-							s.left = (x - labelWidth / 2) + "px";
-							break;
-						case "end":
-							s.textAlign = "right";
-							s.left = (x - labelWidth) + "px";
-							break;
-						default:
-							s.left = x + "px";
-							s.textAlign = "left";
-							break;
-					}
-				}else{
-					switch(align){
-						case "middle":
-							s.left = Math.floor(x - boxWidth / 2) + "px";
-							// s.left = Math.floor(x - p.offsetWidth / 2) + "px";
-							break;
-						case "end":
-							s.left = Math.floor(x - boxWidth) + "px";
-							// s.left = Math.floor(x - p.offsetWidth) + "px";
-							break;
-						//case "start":
-						default:
-							s.left = Math.floor(x) + "px";
-							break;
-					}
-				}
-				s.top = Math.floor(y - size) + "px";
-				// setup the wrapper node
-				var wrap = dojo.doc.createElement("div"), w = wrap.style;
-				clearNode(w);
-				w.width = "0px";
-				w.height = "0px";
-				// insert nodes
-				wrap.appendChild(p)
-				chart.node.insertBefore(wrap, chart.node.firstChild);
-				return wrap;
-			}
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.axis2d.Base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.axis2d.Base"] = true;
-dojo.provide("dojox.charting.axis2d.Base");
-
-
-
-dojo.declare("dojox.charting.axis2d.Base", dojox.charting.Element, {
-	constructor: function(chart, kwArgs){
-		this.vertical = kwArgs && kwArgs.vertical;
-	},
-	clear: function(){
-		return this;
-	},
-	initialized: function(){
-		return false;
-	},
-	calculate: function(min, max, span){
-		return this;
-	},
-	getScaler: function(){
-		return null;
-	},
-	getTicks: function(){
-		return null;
-	},
-	getOffsets: function(){
-		return {l: 0, r: 0, t: 0, b: 0};
-	},
-	render: function(dim, offsets){
-		return this;
-	}
-});
-
-}
-
-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. mylib.encodeXML
-	//	thisObject: 
-	//		where to look for optional format function; default to the global
-	//		namespace
-	//	example:
-	//		Substitutes two expressions in a string from an Array or Object
-	//	|	// returns "File 'foo.html' is not found in directory '/temp'."
-	//	|	// by providing substitution data in an Array
-	//	|	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'."
-	//	|	// but provides substitution data in an Object structure.  Dotted
-	//	|	// notation may be used to traverse the structure.
-	//	|	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 ? 
-		dojo.hitch(thisObject, transform) : function(v){ return v; };
-
-	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["dojox.lang.utils"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.lang.utils"] = true;
-dojo.provide("dojox.lang.utils");
-
-(function(){
-	var empty = {}, du = dojox.lang.utils;
-
-	var clone = function(o){
-		if(dojo.isArray(o)){
-			return dojo._toArray(o);
-		}
-		if(!dojo.isObject(o) || dojo.isFunction(o)){
-			return o;
-		}
-		return dojo.delegate(o);
-	}
-	
-	dojo.mixin(du, {
-		coerceType: function(target, source){
-			switch(typeof target){
-				case "number":	return Number(eval("(" + source + ")"));
-				case "string":	return String(source);
-				case "boolean":	return Boolean(eval("(" + source + ")"));
-			}
-			return eval("(" + source + ")");
-		},
-		
-		updateWithObject: function(target, source, conv){
-			// summary: updates an existing object in place with properties from an "source" object.
-			// target: Object: the "target" object to be updated
-			// source: Object: the "source" object, whose properties will be used to source the existed object.
-			// conv: Boolean?: force conversion to the original type
-			if(!source){ return target; }
-			for(var x in target){
-				if(x in source && !(x in empty)){
-					var t = target[x];
-					if(t && typeof t == "object"){
-						du.updateWithObject(t, source[x], conv);
-					}else{
-						target[x] = conv ? du.coerceType(t, source[x]) : clone(source[x]);
-					}
-				}
-			}
-			return target;	// Object
-		},
-	
-		updateWithPattern: function(target, source, pattern, conv){
-			// summary: updates an existing object in place with properties from an "source" object.
-			// target: Object: the "target" object to be updated
-			// source: Object: the "source" object, whose properties will be used to source the existed object.
-			// pattern: Array: an array of properties to be copied
-			// conv: Boolean?: force conversion to the original type
-			if(!source || !pattern){ return target; }
-			for(var x in pattern){
-				if(x in source && !(x in empty)){
-					target[x] = conv ? du.coerceType(pattern[x], source[x]) : clone(source[x]);
-				}
-			}
-			return target;	// Object
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.axis2d.Default"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.axis2d.Default"] = true;
-dojo.provide("dojox.charting.axis2d.Default");
-
-
-
-
-
-
-
-
-
-
-
-(function(){
-	var dc = dojox.charting,
-		df = dojox.lang.functional,
-		du = dojox.lang.utils,
-		g = dojox.gfx,
-		lin = dc.scaler.linear,
-		labelGap = 4;	// in pixels
-
-	dojo.declare("dojox.charting.axis2d.Default", dojox.charting.axis2d.Base, {
-		 defaultParams: {
-			vertical:    false,		// true for vertical axis
-			fixUpper:    "none",	// align the upper on ticks: "major", "minor", "micro", "none"
-			fixLower:    "none",	// align the lower on ticks: "major", "minor", "micro", "none"
-			natural:     false,		// all tick marks should be made on natural numbers
-			leftBottom:  true,		// position of the axis, used with "vertical"
-			includeZero: false,		// 0 should be included
-			fixed:       true,		// all labels are fixed numbers
-			majorLabels: true,		// draw major labels
-			minorTicks:  true,		// draw minor ticks
-			minorLabels: true,		// draw minor labels
-			microTicks:  false,		// draw micro ticks
-			htmlLabels:  true		// use HTML to draw labels
-		},
-		optionalParams: {
-			min:			0,	// minimal value on this axis
-			max:			1,	// maximal value on this axis
-			from:			0,	// visible from this value
-			to:				1,	// visible to this value
-			majorTickStep:	4,	// major tick step
-			minorTickStep:	2,	// minor tick step
-			microTickStep:	1,	// micro tick step
-			labels:			[],	// array of labels for major ticks
-								// with corresponding numeric values
-								// ordered by values
-			labelFunc:		null, // function to compute label values
-			maxLabelSize:	0,	// size in px. For use with labelFunc
-
-			// TODO: add support for minRange!
-			// minRange:		1,	// smallest distance from min allowed on the axis
-
-			// theme components
-			stroke:			{},	// stroke for an axis
-			majorTick:		{},	// stroke + length for a tick
-			minorTick:		{},	// stroke + length for a tick
-			microTick:		{},	// stroke + length for a tick
-			font:			"",	// font for labels
-			fontColor:		""	// color for labels as a string
-		},
-
-		constructor: function(chart, kwArgs){
-			this.opt = dojo.delegate(this.defaultParams, kwArgs);
-			// du.updateWithObject(this.opt, kwArgs);
-			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
-		},
-		dependOnData: function(){
-			return !("min" in this.opt) || !("max" in this.opt);
-		},
-		clear: function(){
-			delete this.scaler;
-			delete this.ticks;
-			this.dirty = true;
-			return this;
-		},
-		initialized: function(){
-			return "scaler" in this && !(this.dirty && this.dependOnData());
-		},
-		setWindow: function(scale, offset){
-			this.scale  = scale;
-			this.offset = offset;
-			return this.clear();
-		},
-		getWindowScale: function(){
-			return "scale" in this ? this.scale : 1;
-		},
-		getWindowOffset: function(){
-			return "offset" in this ? this.offset : 0;
-		},
-		_groupLabelWidth: function(labels, font){
-			if(labels[0]["text"]){
-				labels = df.map(labels, function(label){ return label.text; });
-			}
-			var s = labels.join("<br>");
-			return dojox.gfx._base._getTextBox(s, {font: font}).w || 0;
-		},
-		calculate: function(min, max, span, labels){
-			if(this.initialized()){
-				return this;
-			}
-			var o = this.opt;
-			this.labels = "labels" in o  ? o.labels : labels;
-			this.scaler = lin.buildScaler(min, max, span, o);
-			var tsb = this.scaler.bounds;
-			if("scale" in this){
-				// calculate new range
-				o.from = tsb.lower + this.offset;
-				o.to   = (tsb.upper - tsb.lower) / this.scale + o.from;
-				// make sure that bounds are correct
-				if( !isFinite(o.from) ||
-					isNaN(o.from) ||
-					!isFinite(o.to) ||
-					isNaN(o.to) ||
-					o.to - o.from >= tsb.upper - tsb.lower
-				){
-					// any error --- remove from/to bounds
-					delete o.from;
-					delete o.to;
-					delete this.scale;
-					delete this.offset;
-				}else{
-					// shift the window, if we are out of bounds
-					if(o.from < tsb.lower){
-						o.to += tsb.lower - o.from;
-						o.from = tsb.lower;
-					}else if(o.to > tsb.upper){
-						o.from += tsb.upper - o.to;
-						o.to = tsb.upper;
-					}
-					// update the offset
-					this.offset = o.from - tsb.lower;
-				}
-				// re-calculate the scaler
-				this.scaler = lin.buildScaler(min, max, span, o);
-				tsb = this.scaler.bounds;
-				// cleanup
-				if(this.scale == 1 && this.offset == 0){
-					delete this.scale;
-					delete this.offset;
-				}
-			}
-			var minMinorStep = 0, ta = this.chart.theme.axis,
-				taFont = "font" in o ? o.font : ta.font,
-				size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0;
-			if(this.vertical){
-				if(size){
-					minMinorStep = size + labelGap;
-				}
-			}else{
-				if(size){
-					var labelWidth, i;
-					if(o.labelFunc && o.maxLabelSize){
-						labelWidth = o.maxLabelSize;
-					}else if(this.labels){
-						labelWidth = this._groupLabelWidth(this.labels, taFont);
-					}else{
-						var labelLength = Math.ceil(
-								Math.log(
-									Math.max(
-										Math.abs(tsb.from),
-										Math.abs(tsb.to)
-									)
-								) / Math.LN10
-							),
-							t = [];
-						if(tsb.from < 0 || tsb.to < 0){
-							t.push("-");
-						}
-						t.push(dojo.string.rep("9", labelLength));
-						var precision = Math.floor(
-							Math.log( tsb.to - tsb.from ) / Math.LN10
-						);
-						if(precision > 0){
-							t.push(".");
-							for(i = 0; i < precision; ++i){
-								t.push("9");
-							}
-						}
-						labelWidth = dojox.gfx._base._getTextBox(
-							t.join(""),
-							{ font: taFont }
-						).w;
-					}
-					minMinorStep = labelWidth + labelGap;
-				}
-			}
-			this.scaler.minMinorStep = minMinorStep;
-			this.ticks = lin.buildTicks(this.scaler, o);
-			return this;
-		},
-		getScaler: function(){
-			return this.scaler;
-		},
-		getTicks: function(){
-			return this.ticks;
-		},
-		getOffsets: function(){
-			var o = this.opt;
-			var offsets = { l: 0, r: 0, t: 0, b: 0 },
-				labelWidth,
-				a,
-				b,
-				c,
-				d,
-				gl = dc.scaler.common.getNumericLabel,
-				offset = 0,
-				ta = this.chart.theme.axis,
-				taFont = "font" in o ? o.font : ta.font,
-				taMajorTick = "majorTick" in o ? o.majorTick : ta.majorTick,
-				taMinorTick = "minorTick" in o ? o.minorTick : ta.minorTick,
-				size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
-				s = this.scaler;
-			if(!s){
-				return offsets;
-			}
-			var ma = s.major, mi = s.minor;
-			if(this.vertical){
-				if(size){
-					if(o.labelFunc && o.maxLabelSize){
-						labelWidth = o.maxLabelSize;
-					}else if(this.labels){
-						labelWidth = this._groupLabelWidth(
-							this.labels,
-							taFont
-						);
-					}else{
-						labelWidth = this._groupLabelWidth([
-							gl(ma.start, ma.prec, o),
-							gl(ma.start + ma.count * ma.tick, ma.prec, o),
-							gl(mi.start, mi.prec, o),
-							gl(mi.start + mi.count * mi.tick, mi.prec, o)
-						], taFont);
-					}
-					offset = labelWidth + labelGap;
-				}
-				offset += labelGap + Math.max(taMajorTick.length, taMinorTick.length);
-				offsets[o.leftBottom ? "l" : "r"] = offset;
-				offsets.t = offsets.b = size / 2;
-			}else{
-				if(size){
-					offset = size + labelGap;
-				}
-				offset += labelGap + Math.max(taMajorTick.length, taMinorTick.length);
-				offsets[o.leftBottom ? "b" : "t"] = offset;
-				if(size){
-					if(o.labelFunc && o.maxLabelSize){
-						labelWidth = o.maxLabelSize;
-					}else if(this.labels){
-						labelWidth = this._groupLabelWidth(this.labels, taFont);
-					}else{
-						labelWidth = this._groupLabelWidth([
-							gl(ma.start, ma.prec, o),
-							gl(ma.start + ma.count * ma.tick, ma.prec, o),
-							gl(mi.start, mi.prec, o),
-							gl(mi.start + mi.count * mi.tick, mi.prec, o)
-						], taFont);
-					}
-					offsets.l = offsets.r = labelWidth / 2;
-				}
-			}
-			if(labelWidth){
-				this._cachedLabelWidth = labelWidth;
-			}
-			return offsets;
-		},
-		render: function(dim, offsets){
-			if(!this.dirty){
-				return this;
-			}
-			// prepare variable
-			var o = this.opt;
-			var start,
-				stop,
-				axisVector,
-				tickVector,
-				labelOffset,
-				labelAlign,
-				ta = this.chart.theme.axis,
-				taStroke = "stroke" in o ? o.stroke : ta.stroke,
-				taMajorTick = "majorTick" in o ? o.majorTick : ta.majorTick,
-				taMinorTick = "minorTick" in o ? o.minorTick : ta.minorTick,
-				taMicroTick = "microTick" in o ? o.microTick : ta.minorTick,
-				taFont = "font" in o ? o.font : ta.font,
-				taFontColor = "fontColor" in o ? o.fontColor : ta.fontColor,
-				tickSize = Math.max(taMajorTick.length, taMinorTick.length),
-				size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0;
-			if(this.vertical){
-				start = { y: dim.height - offsets.b };
-				stop  = { y: offsets.t };
-				axisVector = { x: 0, y: -1 };
-				if(o.leftBottom){
-					start.x = stop.x = offsets.l;
-					tickVector = { x: -1, y: 0 };
-					labelAlign = "end";
-				}else{
-					start.x = stop.x = dim.width - offsets.r;
-					tickVector = { x: 1, y: 0 };
-					labelAlign = "start";
-				}
-				labelOffset = {
-					x: tickVector.x * (tickSize + labelGap),
-					y: size * 0.4
-				};
-			}else{
-				start = { x: offsets.l };
-				stop  = { x: dim.width - offsets.r };
-				axisVector = { x: 1, y: 0 };
-				labelAlign = "middle";
-				if(o.leftBottom){
-					start.y = stop.y = dim.height - offsets.b;
-					tickVector = { x: 0, y: 1 };
-					labelOffset = { y: tickSize + labelGap + size };
-				}else{
-					start.y = stop.y = offsets.t;
-					tickVector = { x: 0, y: -1 };
-					labelOffset = { y: -tickSize - labelGap };
-				}
-				labelOffset.x = 0;
-			}
-
-			// render shapes
-
-			this.cleanGroup();
-
-			try{
-				var s = this.group,
-					c = this.scaler,
-					t = this.ticks,
-					canLabel,
-					f = lin.getTransformerFromModel(this.scaler),
-					forceHtmlLabels = (dojox.gfx.renderer == "canvas"),
-					labelType = forceHtmlLabels || this.opt.htmlLabels && !dojo.isIE && !dojo.isOpera ? "html" : "gfx",
-					dx = tickVector.x * taMajorTick.length,
-					dy = tickVector.y * taMajorTick.length;
-
-				s.createLine({
-					x1: start.x,
-					y1: start.y,
-					x2: stop.x,
-					y2: stop.y
-				}).setStroke(taStroke);
-
-				dojo.forEach(t.major, function(tick){
-					var offset = f(tick.value), elem,
-						x = start.x + axisVector.x * offset,
-						y = start.y + axisVector.y * offset;
-						s.createLine({
-							x1: x, y1: y,
-							x2: x + dx,
-							y2: y + dy
-						}).setStroke(taMajorTick);
-						if(tick.label){
-							elem = dc.axis2d.common.createText[labelType](
-								this.chart,
-								s,
-								x + labelOffset.x,
-								y + labelOffset.y,
-								labelAlign,
-								tick.label,
-								taFont,
-								taFontColor,
-								this._cachedLabelWidth
-							);
-							if(labelType == "html"){
-								this.htmlElements.push(elem);
-							}
-						}
-				}, this);
-
-				dx = tickVector.x * taMinorTick.length;
-				dy = tickVector.y * taMinorTick.length;
-				canLabel = c.minMinorStep <= c.minor.tick * c.bounds.scale;
-				dojo.forEach(t.minor, function(tick){
-					var offset = f(tick.value), elem,
-						x = start.x + axisVector.x * offset,
-						y = start.y + axisVector.y * offset;
-						s.createLine({
-							x1: x, y1: y,
-							x2: x + dx,
-							y2: y + dy
-						}).setStroke(taMinorTick);
-						if(canLabel && tick.label){
-							elem = dc.axis2d.common.createText[labelType](
-								this.chart,
-								s,
-								x + labelOffset.x,
-								y + labelOffset.y,
-								labelAlign,
-								tick.label,
-								taFont,
-								taFontColor,
-								this._cachedLabelWidth
-							);
-							if(labelType == "html"){
-								this.htmlElements.push(elem);
-							}
-						}
-				}, this);
-
-				dx = tickVector.x * taMicroTick.length;
-				dy = tickVector.y * taMicroTick.length;
-				dojo.forEach(t.micro, function(tick){
-					var offset = f(tick.value), elem,
-						x = start.x + axisVector.x * offset,
-						y = start.y + axisVector.y * offset;
-						s.createLine({
-							x1: x, y1: y,
-							x2: x + dx,
-							y2: y + dy
-						}).setStroke(taMicroTick);
-				}, this);
-			}catch(e){
-				// squelch
-			}
-
-			this.dirty = false;
-			return this;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.common"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.common"] = true;
-dojo.provide("dojox.charting.plot2d.common");
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common;
-
-	dojo.mixin(dojox.charting.plot2d.common, {
-		makeStroke: function(stroke){
-			if(!stroke){ return stroke; }
-			if(typeof stroke == "string" || stroke instanceof dojo.Color){
-				stroke = {color: stroke};
-			}
-			return dojox.gfx.makeParameters(dojox.gfx.defaultStroke, stroke);
-		},
-		augmentColor: function(target, color){
-			var t = new dojo.Color(target),
-				c = new dojo.Color(color);
-			c.a = t.a;
-			return c;
-		},
-		augmentStroke: function(stroke, color){
-			var s = dc.makeStroke(stroke);
-			if(s){
-				s.color = dc.augmentColor(s.color, color);
-			}
-			return s;
-		},
-		augmentFill: function(fill, color){
-			var fc, c = new dojo.Color(color);
-			if(typeof fill == "string" || fill instanceof dojo.Color){
-				return dc.augmentColor(fill, color);
-			}
-			return fill;
-		},
-
-		defaultStats: {
-			hmin: Number.POSITIVE_INFINITY, hmax: Number.NEGATIVE_INFINITY,
-			vmin: Number.POSITIVE_INFINITY, vmax: Number.NEGATIVE_INFINITY
-		},
-
-		collectSimpleStats: function(series){
-			var stats = dojo.clone(dc.defaultStats);
-			for(var i = 0; i < series.length; ++i){
-				var run = series[i];
-				if(!run.data.length){ continue; }
-				if(typeof run.data[0] == "number"){
-					// 1D case
-					var old_vmin = stats.vmin, old_vmax = stats.vmax;
-					if(!("ymin" in run) || !("ymax" in run)){
-						dojo.forEach(run.data, function(val, i){
-							var x = i + 1, y = val;
-							if(isNaN(y)){ y = 0; }
-							stats.hmin = Math.min(stats.hmin, x);
-							stats.hmax = Math.max(stats.hmax, x);
-							stats.vmin = Math.min(stats.vmin, y);
-							stats.vmax = Math.max(stats.vmax, y);
-						});
-					}
-					if("ymin" in run){ stats.vmin = Math.min(old_vmin, run.ymin); }
-					if("ymax" in run){ stats.vmax = Math.max(old_vmax, run.ymax); }
-				}else{
-					// 2D case
-					var old_hmin = stats.hmin, old_hmax = stats.hmax,
-						old_vmin = stats.vmin, old_vmax = stats.vmax;
-					if(!("xmin" in run) || !("xmax" in run) || !("ymin" in run) || !("ymax" in run)){
-						dojo.forEach(run.data, function(val, i){
-							var x = "x" in val ? val.x : i + 1, y = val.y;
-							if(isNaN(x)){ x = 0; }
-							if(isNaN(y)){ y = 0; }
-							stats.hmin = Math.min(stats.hmin, x);
-							stats.hmax = Math.max(stats.hmax, x);
-							stats.vmin = Math.min(stats.vmin, y);
-							stats.vmax = Math.max(stats.vmax, y);
-						});
-					}
-					if("xmin" in run){ stats.hmin = Math.min(old_hmin, run.xmin); }
-					if("xmax" in run){ stats.hmax = Math.max(old_hmax, run.xmax); }
-					if("ymin" in run){ stats.vmin = Math.min(old_vmin, run.ymin); }
-					if("ymax" in run){ stats.vmax = Math.max(old_vmax, run.ymax); }
-				}
-			}
-			return stats;
-		},
-
-		calculateBarSize: function(/* Number */ availableSize, /* Object */ opt, /* Number? */ clusterSize){
-			if(!clusterSize){
-				clusterSize = 1;
-			}
-			var gap = opt.gap, size = (availableSize - 2 * gap) / clusterSize;
-			if("minBarSize" in opt){
-				size = Math.max(size, opt.minBarSize);
-			}
-			if("maxBarSize" in opt){
-				size = Math.min(size, opt.maxBarSize);
-			}
-			size = Math.max(size, 1);
-			gap = (availableSize - size * clusterSize) / 2;
-			return {size: size, gap: gap};	// Object
-		},
-
-		collectStackedStats: function(series){
-			// collect statistics
-			var stats = dojo.clone(dc.defaultStats);
-			if(series.length){
-				// 1st pass: find the maximal length of runs
-				stats.hmin = Math.min(stats.hmin, 1);
-				stats.hmax = df.foldl(series, "seed, run -> Math.max(seed, run.data.length)", stats.hmax);
-				// 2nd pass: stack values
-				for(var i = 0; i < stats.hmax; ++i){
-					var v = series[0].data[i];
-					if(isNaN(v)){ v = 0; }
-					stats.vmin = Math.min(stats.vmin, v);
-					for(var j = 1; j < series.length; ++j){
-						var t = series[j].data[i];
-						if(isNaN(t)){ t = 0; }
-						v += t;
-					}
-					stats.vmax = Math.max(stats.vmax, v);
-				}
-			}
-			return stats;
-		},
-
-		curve: function(/* Number[] */a, /* Number|String */tension){
-			//	FIX for #7235, submitted by Enzo Michelangeli.
-			//	Emulates the smoothing algorithms used in a famous, unnamed spreadsheet
-			//		program ;)
-			var arr = a.slice(0);
-			if(tension == "x") {
-				arr[arr.length] = arr[0];   // add a last element equal to the first, closing the loop
-			}
-			var p=dojo.map(arr, function(item, i){
-				if(i==0){ return "M" + item.x + "," + item.y; }
-				if(!isNaN(tension)) { // use standard Dojo smoothing in tension is numeric
-					var dx=item.x-arr[i-1].x, dy=arr[i-1].y;
-					return "C"+(item.x-(tension-1)*(dx/tension))+","+dy+" "+(item.x-(dx/tension))+","+item.y+" "+item.x+","+item.y;
-				} else if(tension == "X" || tension == "x" || tension == "S") {
-					// use Excel "line smoothing" algorithm (http://xlrotor.com/resources/files.shtml)
-					var p0, p1 = arr[i-1], p2 = arr[i], p3;
-					var bz1x, bz1y, bz2x, bz2y;
-					var f = 1/6;
-					if(i==1) {
-						if(tension == "x") {
-							p0 = arr[arr.length-2];
-						} else { // "tension == X || tension == "S"
-							p0 = p1;
-						}
-						f = 1/3;
-					} else {
-						p0 = arr[i-2];
-					}
-					if(i==(arr.length-1)) {
-						if(tension == "x") {
-							p3 = arr[1];
-						} else { // "tension == X || tension == "S"
-							p3 = p2;
-						}
-						f = 1/3;
-					} else {
-						p3 = arr[i+1];
-					}
-					var p1p2 = Math.sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
-					var p0p2 = Math.sqrt((p2.x-p0.x)*(p2.x-p0.x)+(p2.y-p0.y)*(p2.y-p0.y));
-					var p1p3 = Math.sqrt((p3.x-p1.x)*(p3.x-p1.x)+(p3.y-p1.y)*(p3.y-p1.y));
-
-					var p0p2f = p0p2 * f;
-					var p1p3f = p1p3 * f;
-
-					if(p0p2f > p1p2/2 && p1p3f > p1p2/2) {
-						p0p2f = p1p2/2;
-						p1p3f = p1p2/2;
-					} else if(p0p2f > p1p2/2) {
-						p0p2f = p1p2/2;
-						p1p3f = p1p2/2 * p1p3/p0p2;
-					} else if(p1p3f > p1p2/2) {
-						p1p3f = p1p2/2;
-						p0p2f = p1p2/2 * p0p2/p1p3;
-					}
-
-					if(tension == "S") {
-						if(p0 == p1) { p0p2f = 0; }
-						if(p2 == p3) { p1p3f = 0; }
-					}
-
-					bz1x = p1.x + p0p2f*(p2.x - p0.x)/p0p2;
-					bz1y = p1.y + p0p2f*(p2.y - p0.y)/p0p2;
-					bz2x = p2.x - p1p3f*(p3.x - p1.x)/p1p3;
-					bz2y = p2.y - p1p3f*(p3.y - p1.y)/p1p3;
-				}
-				return "C"+(bz1x+","+bz1y+" "+bz2x+","+bz2y+" "+p2.x+","+p2.y);
-			});
-			return p.join(" ");
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.scaler.primitive"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.scaler.primitive"] = true;
-dojo.provide("dojox.charting.scaler.primitive");
-
-dojox.charting.scaler.primitive = {
-	buildScaler: function(/*Number*/ min, /*Number*/ max, /*Number*/ span, /*Object*/ kwArgs){
-		return {
-			bounds: {
-				lower: min,
-				upper: max,
-				from:  min,
-				to:    max,
-				scale: span / (max - min),
-				span:  span
-			},
-			scaler: dojox.charting.scaler.primitive
-		};
-	},
-	buildTicks: function(/*Object*/ scaler, /*Object*/ kwArgs){
-		return {major: [], minor: [], micro: []};	// Object
-	},
-	getTransformerFromModel: function(/*Object*/ scaler){
-		var offset = scaler.bounds.from, scale = scaler.bounds.scale;
-		return function(x){ return (x - offset) * scale; };	// Function
-	},
-	getTransformerFromPlot: function(/*Object*/ scaler){
-		var offset = scaler.bounds.from, scale = scaler.bounds.scale;
-		return function(x){ return x / scale + offset; };	// Function
-	}
-};
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Base"] = true;
-dojo.provide("dojox.charting.plot2d.Base");
-
-
-
-
-
-dojo.declare("dojox.charting.plot2d.Base", dojox.charting.Element, {
-	destroy: function(){
-		this.resetEvents();
-		this.inherited(arguments);
-	},
-	clear: function(){
-		this.series = [];
-		this._hAxis = null;
-		this._vAxis = null;
-		this.dirty = true;
-		return this;
-	},
-	setAxis: function(axis){
-		if(axis){
-			this[axis.vertical ? "_vAxis" : "_hAxis"] = axis;
-		}
-		return this;
-	},
-	addSeries: function(run){
-		this.series.push(run);
-		return this;
-	},
-	calculateAxes: function(dim){
-		return this;
-	},
-	isDirty: function(){
-		return this.dirty || this._hAxis && this._hAxis.dirty || this._vAxis && this._vAxis.dirty;
-	},
-	render: function(dim, offsets){
-		return this;
-	},
-	getRequiredColors: function(){
-		return this.series.length;
-	},
-
-	// events
-	plotEvent: function(o){
-		// intentionally empty --- used for events
-	},
-	connect: function(object, method){
-		this.dirty = true;
-		return dojo.connect(this, "plotEvent", object, method);
-	},
-	events: function(){
-		var ls = this.plotEvent._listeners;
-		if(!ls || !ls.length){ return false; }
-		for(var i in ls){
-			if(!(i in Array.prototype)){
-				return true;
-			}
-		}
-		return false;
-	},
-	resetEvents: function(){
-		this.plotEvent({type: "onplotreset", plot: this});
-	},
-
-	// utilities
-	_calc: function(dim, stats){
-		// calculate scaler
-		if(this._hAxis){
-			if(!this._hAxis.initialized()){
-				this._hAxis.calculate(stats.hmin, stats.hmax, dim.width);
-			}
-			this._hScaler = this._hAxis.getScaler();
-		}else{
-			this._hScaler = dojox.charting.scaler.primitive.buildScaler(stats.hmin, stats.hmax, dim.width);
-		}
-		if(this._vAxis){
-			if(!this._vAxis.initialized()){
-				this._vAxis.calculate(stats.vmin, stats.vmax, dim.height);
-			}
-			this._vScaler = this._vAxis.getScaler();
-		}else{
-			this._vScaler = dojox.charting.scaler.primitive.buildScaler(stats.vmin, stats.vmax, dim.height);
-		}
-	},
-
-	_connectEvents: function(shape, o){
-		shape.connect("onmouseover", this, function(e){
-			o.type  = "onmouseover";
-			o.event = e;
-			this.plotEvent(o);
-		});
-		shape.connect("onmouseout", this, function(e){
-			o.type  = "onmouseout";
-			o.event = e;
-			this.plotEvent(o);
-		});
-		shape.connect("onclick", this, function(e){
-			o.type  = "onclick";
-			o.event = e;
-			this.plotEvent(o);
-		});
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Default"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Default"] = true;
-dojo.provide("dojox.charting.plot2d.Default");
-
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, du = dojox.lang.utils,
-		dc = dojox.charting.plot2d.common,
-		purgeGroup = df.lambda("item.purgeGroup()");
-
-	dojo.declare("dojox.charting.plot2d.Default", dojox.charting.plot2d.Base, {
-		defaultParams: {
-			hAxis: "x",		// use a horizontal axis named "x"
-			vAxis: "y",		// use a vertical axis named "y"
-			lines:   true,	// draw lines
-			areas:   false,	// draw areas
-			markers: false,	// draw markers
-			shadows: 0,		// draw shadows
-			tension: 0		// draw curved lines (tension>0)
-		},
-		optionalParams: {},	// no optional parameters
-		
-		constructor: function(chart, kwArgs){
-			this.opt = dojo.clone(this.defaultParams);
-			du.updateWithObject(this.opt, kwArgs);
-			this.series = [];
-			this.hAxis = this.opt.hAxis;
-			this.vAxis = this.opt.vAxis;
-		},
-		
-		calculateAxes: function(dim){
-			this._calc(dim, dc.collectSimpleStats(this.series));
-			return this;
-		},
-		render: function(dim, offsets){
-			this.dirty = this.isDirty();
-			if(this.dirty){
-				dojo.forEach(this.series, purgeGroup);
-				this.cleanGroup();
-				var s = this.group;
-				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
-			}
-			var t = this.chart.theme, stroke, outline, color, marker, events = this.events();
-			this.resetEvents();
-			for(var i = this.series.length - 1; i >= 0; --i){
-				var run = this.series[i];
-				if(!this.dirty && !run.dirty){ continue; }
-				run.cleanGroup();
-				if(!run.data.length){
-					run.dirty = false;
-					continue;
-				}
-
-				var s = run.group, lpoly, 
-					ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
-					vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler);
-				if(typeof run.data[0] == "number"){
-					lpoly = dojo.map(run.data, function(v, i){
-						return {
-							x: ht(i + 1) + offsets.l,
-							y: dim.height - offsets.b - vt(v)
-						};
-					}, this);
-				}else{
-					lpoly = dojo.map(run.data, function(v, i){
-						return {
-							x: ht(v.x) + offsets.l,
-							y: dim.height - offsets.b - vt(v.y)
-						};
-					}, this);
-				}
-				if(!run.fill || !run.stroke){
-					// need autogenerated color
-					color = run.dyn.color = new dojo.Color(t.next("color"));
-				}
-
-				var lpath = this.opt.tension ? dc.curve(lpoly, this.opt.tension) : "";
-
-				if(this.opt.areas){
-					var fill = run.fill ? run.fill : dc.augmentFill(t.series.fill, color);
-					var apoly = dojo.clone(lpoly);
-					if(this.opt.tension){
-						var apath = "L" + apoly[apoly.length-1].x + "," + (dim.height - offsets.b) +
-							" L" + apoly[0].x + "," + (dim.height - offsets.b) +
-							" L" + apoly[0].x + "," + apoly[0].y;
-						run.dyn.fill = s.createPath(lpath + " " + apath).setFill(fill).getFill();
-					} else {
-						apoly.push({x: lpoly[lpoly.length - 1].x, y: dim.height - offsets.b});
-						apoly.push({x: lpoly[0].x, y: dim.height - offsets.b});
-						apoly.push(lpoly[0]);
-						run.dyn.fill = s.createPolyline(apoly).setFill(fill).getFill();
-					}
-				}
-				if(this.opt.lines || this.opt.markers){
-					// need a stroke
-					stroke = run.dyn.stroke = run.stroke ? dc.makeStroke(run.stroke) : dc.augmentStroke(t.series.stroke, color);
-					if(run.outline || t.series.outline){
-						outline = run.dyn.outline = dc.makeStroke(run.outline ? run.outline : t.series.outline);
-						outline.width = 2 * outline.width + stroke.width;
-					}
-				}
-				if(this.opt.markers){
-					// need a marker
-					marker = run.dyn.marker = run.marker ? run.marker : t.next("marker");
-				}
-				var frontMarkers = null, outlineMarkers = null, shadowMarkers = null;
-				if(this.opt.shadows && stroke){
-					var sh = this.opt.shadows, shadowColor = new dojo.Color([0, 0, 0, 0.3]),
-						spoly = dojo.map(lpoly, function(c){
-							return {x: c.x + sh.dx, y: c.y + sh.dy};
-						}),
-						shadowStroke = dojo.clone(outline ? outline : stroke);
-					shadowStroke.color = shadowColor;
-					shadowStroke.width += sh.dw ? sh.dw : 0;
-					if(this.opt.lines){
-						if(this.opt.tension){
-							run.dyn.shadow = s.createPath(dc.curve(spoly, this.opt.tension)).setStroke(shadowStroke).getStroke();
-						} else {
-							run.dyn.shadow = s.createPolyline(spoly).setStroke(shadowStroke).getStroke();
-						}
-					}
-					if(this.opt.markers){
-						shadowMarkers = dojo.map(spoly, function(c){
-							return s.createPath("M" + c.x + " " + c.y + " " + marker).
-								setStroke(shadowStroke).setFill(shadowColor);
-						}, this);
-					}
-				}
-				if(this.opt.lines){
-					if(outline){
-						if(this.opt.tension){
-							run.dyn.outline = s.createPath(lpath).setStroke(outline).getStroke();
-						} else {
-							run.dyn.outline = s.createPolyline(lpoly).setStroke(outline).getStroke();
-						}
-					}
-					if(this.opt.tension){
-						run.dyn.stroke = s.createPath(lpath).setStroke(stroke).getStroke();
-					} else {
-						run.dyn.stroke = s.createPolyline(lpoly).setStroke(stroke).getStroke();
-					}
-				}
-				if(this.opt.markers){
-					frontMarkers = new Array(lpoly.length);
-					outlineMarkers = new Array(lpoly.length);
-					dojo.forEach(lpoly, function(c, i){
-						var path = "M" + c.x + " " + c.y + " " + marker;
-						if(outline){
-							outlineMarkers[i] = s.createPath(path).setStroke(outline);
-						}
-						frontMarkers[i] = s.createPath(path).setStroke(stroke).setFill(stroke.color);
-					}, this);
-					if(events){
-						dojo.forEach(frontMarkers, function(s, i){
-							var o = {
-								element: "marker",
-								index:   i,
-								run:     run,
-								plot:    this,
-								hAxis:   this.hAxis || null,
-								vAxis:   this.vAxis || null,
-								shape:   s,
-								outline: outlineMarkers[i] || null,
-								shadow:  shadowMarkers && shadowMarkers[i] || null,
-								cx:      lpoly[i].x,
-								cy:      lpoly[i].y
-							};
-							if(typeof run.data[0] == "number"){
-								o.x = i + 1;
-								o.y = run.data[i];
-							}else{
-								o.x = run.data[i].x;
-								o.y = run.data[i].y;
-							}
-							this._connectEvents(s, o);
-						}, this);
-					}
-				}
-				run.dirty = false;
-			}
-			this.dirty = false;
-			return this;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Lines"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Lines"] = true;
-dojo.provide("dojox.charting.plot2d.Lines");
-
-
-
-dojo.declare("dojox.charting.plot2d.Lines", dojox.charting.plot2d.Default, {
-	constructor: function(){
-		this.opt.lines = true;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Areas"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Areas"] = true;
-dojo.provide("dojox.charting.plot2d.Areas");
-
-
-
-dojo.declare("dojox.charting.plot2d.Areas", dojox.charting.plot2d.Default, {
-	constructor: function(){
-		this.opt.lines = true;
-		this.opt.areas = true;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Markers"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Markers"] = true;
-dojo.provide("dojox.charting.plot2d.Markers");
-
-
-
-dojo.declare("dojox.charting.plot2d.Markers", dojox.charting.plot2d.Default, {
-	constructor: function(){
-		this.opt.markers = true;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.MarkersOnly"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.MarkersOnly"] = true;
-dojo.provide("dojox.charting.plot2d.MarkersOnly");
-
-
-
-dojo.declare("dojox.charting.plot2d.MarkersOnly", dojox.charting.plot2d.Default, {
-	constructor: function(){
-		this.opt.lines   = false;
-		this.opt.markers = true;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Scatter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Scatter"] = true;
-dojo.provide("dojox.charting.plot2d.Scatter");
-
-
-
-dojo.declare("dojox.charting.plot2d.Scatter", dojox.charting.plot2d.Default, {
-	constructor: function(){
-		this.opt.lines   = false;
-		this.opt.markers = true;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.lang.functional.sequence"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.lang.functional.sequence"] = true;
-dojo.provide("dojox.lang.functional.sequence");
-
-
-
-// This module adds high-level functions and related constructs:
-//	- sequence generators
-
-// If you want more general sequence builders check out listcomp.js and
-// unfold() (in fold.js).
-
-// Defined methods:
-//	- take any valid lambda argument as the functional argument
-
-(function(){
-	var d = dojo, df = dojox.lang.functional;
-
-	d.mixin(df, {
-		// sequence generators
-		repeat: function(/*Number*/ n, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
-			// summary: builds an array by repeatedly applying a unary function N times
-			//	with a seed value Z. N should be greater than 0.
-			o = o || d.global; f = df.lambda(f);
-			var t = new Array(n), i = 1;
-			t[0] = z;
-			for(; i < n; t[i] = z = f.call(o, z), ++i);
-			return t;	// Array
-		},
-		until: function(/*Function|String|Array*/ pr, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
-			// summary: builds an array by repeatedly applying a unary function with
-			//	a seed value Z until the predicate is satisfied.
-			o = o || d.global; f = df.lambda(f); pr = df.lambda(pr);
-			var t = [];
-			for(; !pr.call(o, z); t.push(z), z = f.call(o, z));
-			return t;	// Array
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Stacked"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Stacked"] = true;
-dojo.provide("dojox.charting.plot2d.Stacked");
-
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common,
-		purgeGroup = df.lambda("item.purgeGroup()");
-
-	dojo.declare("dojox.charting.plot2d.Stacked", dojox.charting.plot2d.Default, {
-		calculateAxes: function(dim){
-			var stats = dc.collectStackedStats(this.series);
-			this._maxRunLength = stats.hmax;
-			this._calc(dim, stats);
-			return this;
-		},
-		render: function(dim, offsets){
-			if(this._maxRunLength <= 0){
-				return this;
-			}
-
-			// stack all values
-			var acc = df.repeat(this._maxRunLength, "-> 0", 0);
-			for(var i = 0; i < this.series.length; ++i){
-				var run = this.series[i];
-				for(var j = 0; j < run.data.length; ++j){
-					var v = run.data[j];
-					if(isNaN(v)){ v = 0; }
-					acc[j] += v;
-				}
-			}
-			// draw runs in backwards
-			this.dirty = this.isDirty();
-			if(this.dirty){
-				dojo.forEach(this.series, purgeGroup);
-				this.cleanGroup();
-				var s = this.group;
-				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
-			}
-
-			var t = this.chart.theme, stroke, outline, color, marker, events = this.events(),
-				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
-				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler);
-			this.resetEvents();
-
-			for(var i = this.series.length - 1; i >= 0; --i){
-				var run = this.series[i];
-				if(!this.dirty && !run.dirty){ continue; }
-				run.cleanGroup();
-				var s = run.group,
-					lpoly = dojo.map(acc, function(v, i){
-						return {
-							x: ht(i + 1) + offsets.l,
-							y: dim.height - offsets.b - vt(v)
-						};
-					}, this);
-				if(!run.fill || !run.stroke){
-					// need autogenerated color
-					color = new dojo.Color(t.next("color"));
-				}
-
-				var lpath = this.opt.tension ? dc.curve(lpoly, this.opt.tension) : "";
-				
-				if(this.opt.areas){
-					var apoly = dojo.clone(lpoly);
-					var fill = run.fill ? run.fill : dc.augmentFill(t.series.fill, color);
-					if(this.opt.tension){
-						var p=dc.curve(apoly, this.opt.tension);
-						p += " L" + lpoly[lpoly.length - 1].x + "," + (dim.height - offsets.b) +
-							" L" + lpoly[0].x + "," + (dim.height - offsets.b) +
-							" L" + lpoly[0].x + "," + lpoly[0].y;
-						run.dyn.fill = s.createPath(p).setFill(fill).getFill();
-					} else {
-						apoly.push({x: lpoly[lpoly.length - 1].x, y: dim.height - offsets.b});
-						apoly.push({x: lpoly[0].x, y: dim.height - offsets.b});
-						apoly.push(lpoly[0]);
-						run.dyn.fill = s.createPolyline(apoly).setFill(fill).getFill();
-					}
-				}
-				if(this.opt.lines || this.opt.markers){
-					// need a stroke
-					stroke = run.stroke ? dc.makeStroke(run.stroke) : dc.augmentStroke(t.series.stroke, color);
-					if(run.outline || t.series.outline){
-						outline = dc.makeStroke(run.outline ? run.outline : t.series.outline);
-						outline.width = 2 * outline.width + stroke.width;
-					}
-				}
-				if(this.opt.markers){
-					// need a marker
-					marker = run.dyn.marker = run.marker ? run.marker : t.next("marker");
-				}
-				var frontMarkers, outlineMarkers, shadowMarkers;
-				if(this.opt.shadows && stroke){
-					var sh = this.opt.shadows, shadowColor = new dojo.Color([0, 0, 0, 0.3]),
-						spoly = dojo.map(lpoly, function(c){
-							return {x: c.x + sh.dx, y: c.y + sh.dy};
-						}),
-						shadowStroke = dojo.clone(outline ? outline : stroke);
-					shadowStroke.color = shadowColor;
-					shadowStroke.width += sh.dw ? sh.dw : 0;
-					if(this.opt.lines){
-						if(this.opt.tension){
-							run.dyn.shadow = s.createPath(dc.curve(spoly, this.opt.tension)).setStroke(shadowStroke).getStroke();
-						} else {
-							run.dyn.shadow = s.createPolyline(spoly).setStroke(shadowStroke).getStroke();
-						}
-					}
-					if(this.opt.markers){
-						shadowMarkers = dojo.map(spoly, function(c){
-							return s.createPath("M" + c.x + " " + c.y + " " + marker).
-								setStroke(shadowStroke).setFill(shadowColor);
-						}, this);
-					}
-				}
-				if(this.opt.lines){
-					if(outline){
-						if(this.opt.tension){
-							run.dyn.outline = s.createPath(lpath).setStroke(outline).getStroke();
-						} else {
-							run.dyn.outline = s.createPolyline(lpoly).setStroke(outline).getStroke();
-						}
-					}
-					if(this.opt.tension){
-						run.dyn.stroke = s.createPath(lpath).setStroke(stroke).getStroke();
-					} else {
-						run.dyn.stroke = s.createPolyline(lpoly).setStroke(stroke).getStroke();
-					}
-				}
-				if(this.opt.markers){
-					frontMarkers = new Array(lpoly.length);
-					outlineMarkers = new Array(lpoly.length);
-					dojo.forEach(lpoly, function(c, i){
-						var path = "M" + c.x + " " + c.y + " " + marker;
-						if(outline){
-							outlineMarkers[i] = s.createPath(path).setStroke(outline);
-						}
-						frontMarkers[i] = s.createPath(path).setStroke(stroke).setFill(stroke.color);
-					}, this);
-					if(events){
-						dojo.forEach(frontMarkers, function(s, i){
-							var o = {
-								element: "marker",
-								index:   i,
-								run:     run,
-								plot:    this,
-								hAxis:   this.hAxis || null,
-								vAxis:   this.vAxis || null,
-								shape:   s,
-								outline: outlineMarkers[i] || null,
-								shadow:  shadowMarkers && shadowMarkers[i] || null,
-								cx:      lpoly[i].x,
-								cy:      lpoly[i].y,
-								x:       i + 1,
-								y:       run.data[i]
-							};
-							this._connectEvents(s, o);
-						}, this);
-					}
-				}
-				run.dirty = false;
-				// update the accumulator
-				for(var j = 0; j < run.data.length; ++j){
-					var v = run.data[j];
-					if(isNaN(v)){ v = 0; }
-					acc[j] -= v;
-				}
-			}
-			this.dirty = false;
-			return this;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.StackedLines"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.StackedLines"] = true;
-dojo.provide("dojox.charting.plot2d.StackedLines");
-
-
-
-dojo.declare("dojox.charting.plot2d.StackedLines", dojox.charting.plot2d.Stacked, {
-	constructor: function(){
-		this.opt.lines = true;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.StackedAreas"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.StackedAreas"] = true;
-dojo.provide("dojox.charting.plot2d.StackedAreas");
-
-
-
-dojo.declare("dojox.charting.plot2d.StackedAreas", dojox.charting.plot2d.Stacked, {
-	constructor: function(){
-		this.opt.lines = true;
-		this.opt.areas = true;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.gfx.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.gfx.fx"] = true;
-dojo.provide("dojox.gfx.fx");
-
-
-
-(function(){
-	var d = dojo, g = dojox.gfx, m = g.matrix;
-
-	// Generic interpolators. Should they be moved to dojox.fx?
-
-	var InterpolNumber = function(start, end){
-		this.start = start, this.end = end;
-	};
-	d.extend(InterpolNumber, {
-		getValue: function(r){
-			return (this.end - this.start) * r + this.start;
-		}
-	});
-
-	var InterpolUnit = function(start, end, units){
-		this.start = start, this.end = end;
-		this.units = units;
-	};
-	d.extend(InterpolUnit, {
-		getValue: function(r){
-			return (this.end - this.start) * r + this.start + this.units;
-		}
-	});
-
-	var InterpolColor = function(start, end){
-		this.start = start, this.end = end;
-		this.temp = new dojo.Color();
-	};
-	d.extend(InterpolColor, {
-		getValue: function(r){
-			return d.blendColors(this.start, this.end, r, this.temp);
-		}
-	});
-
-	var InterpolValues = function(values){
-		this.values = values;
-		this.length = values.length;
-	};
-	d.extend(InterpolValues, {
-		getValue: function(r){
-			return this.values[Math.min(Math.floor(r * this.length), this.length - 1)];
-		}
-	});
-
-	var InterpolObject = function(values, def){
-		this.values = values;
-		this.def = def ? def : {};
-	};
-	d.extend(InterpolObject, {
-		getValue: function(r){
-			var ret = dojo.clone(this.def);
-			for(var i in this.values){
-				ret[i] = this.values[i].getValue(r);
-			}
-			return ret;
-		}
-	});
-
-	var InterpolTransform = function(stack, original){
-		this.stack = stack;
-		this.original = original;
-	};
-	d.extend(InterpolTransform, {
-		getValue: function(r){
-			var ret = [];
-			dojo.forEach(this.stack, function(t){
-				if(t instanceof m.Matrix2D){
-					ret.push(t);
-					return;
-				}
-				if(t.name == "original" && this.original){
-					ret.push(this.original);
-					return;
-				}
-				if(!(t.name in m)){ return; }
-				var f = m[t.name];
-				if(typeof f != "function"){
-					// constant
-					ret.push(f);
-					return;
-				}
-				var val = dojo.map(t.start, function(v, i){
-								return (t.end[i] - v) * r + v;
-							}),
-					matrix = f.apply(m, val);
-				if(matrix instanceof m.Matrix2D){
-					ret.push(matrix);
-				}
-			}, this);
-			return ret;
-		}
-	});
-
-	var transparent = new d.Color(0, 0, 0, 0);
-
-	var getColorInterpol = function(prop, obj, name, def){
-		if(prop.values){
-			return new InterpolValues(prop.values);
-		}
-		var value, start, end;
-		if(prop.start){
-			start = g.normalizeColor(prop.start);
-		}else{
-			start = value = obj ? (name ? obj[name] : obj) : def;
-		}
-		if(prop.end){
-			end = g.normalizeColor(prop.end);
-		}else{
-			if(!value){
-				value = obj ? (name ? obj[name] : obj) : def;
-			}
-			end = value;
-		}
-		return new InterpolColor(start, end);
-	};
-
-	var getNumberInterpol = function(prop, obj, name, def){
-		if(prop.values){
-			return new InterpolValues(prop.values);
-		}
-		var value, start, end;
-		if(prop.start){
-			start = prop.start;
-		}else{
-			start = value = obj ? obj[name] : def;
-		}
-		if(prop.end){
-			end = prop.end;
-		}else{
-			if(typeof value != "number"){
-				value = obj ? obj[name] : def;
-			}
-			end = value;
-		}
-		return new InterpolNumber(start, end);
-	};
-
-	g.fx.animateStroke = function(/*Object*/ args){
-		// summary:
-		//	Returns an animation which will change stroke properties over time
-		// example:
-		//	|	dojox.gfx.fx.animateStroke{{
-		//	|		shape: shape,
-		//	|		duration: 500,
-		//	|		color: {start: "red", end: "green"},
-		//	|		width: {end: 15},
-		//	|		join:  {values: ["miter", "bevel", "round"]}
-		//	|	}).play();
-		if(!args.easing){ args.easing = d._defaultEasing; }
-		var anim = new d.Animation(args), shape = args.shape, stroke;
-		d.connect(anim, "beforeBegin", anim, function(){
-			stroke = shape.getStroke();
-			var prop = args.color, values = {}, value, start, end;
-			if(prop){
-				values.color = getColorInterpol(prop, stroke, "color", transparent);
-			}
-			prop = args.style;
-			if(prop && prop.values){
-				values.style = new InterpolValues(prop.values);
-			}
-			prop = args.width;
-			if(prop){
-				values.width = getNumberInterpol(prop, stroke, "width", 1);
-			}
-			prop = args.cap;
-			if(prop && prop.values){
-				values.cap = new InterpolValues(prop.values);
-			}
-			prop = args.join;
-			if(prop){
-				if(prop.values){
-					values.join = new InterpolValues(prop.values);
-				}else{
-					start = prop.start ? prop.start : (stroke && stroke.join || 0);
-					end = prop.end ? prop.end : (stroke && stroke.join || 0);
-					if(typeof start == "number" && typeof end == "number"){
-						values.join = new InterpolNumber(start, end);
-					}
-				}
-			}
-			this.curve = new InterpolObject(values, stroke);
-		});
-		d.connect(anim, "onAnimate", shape, "setStroke");
-		return anim; // dojo.Animation
-	};
-
-	g.fx.animateFill = function(/*Object*/ args){
-		// summary:
-		//	Returns an animation which will change fill color over time.
-		//	Only solid fill color is supported at the moment
-		// example:
-		//	|	dojox.gfx.fx.animateFill{{
-		//	|		shape: shape,
-		//	|		duration: 500,
-		//	|		color: {start: "red", end: "green"}
-		//	|	}).play();
-		if(!args.easing){ args.easing = d._defaultEasing; }
-		var anim = new d.Animation(args), shape = args.shape, fill;
-		d.connect(anim, "beforeBegin", anim, function(){
-			fill = shape.getFill();
-			var prop = args.color, values = {};
-			if(prop){
-				this.curve = getColorInterpol(prop, fill, "", transparent);
-			}
-		});
-		d.connect(anim, "onAnimate", shape, "setFill");
-		return anim; // dojo.Animation
-	};
-
-	g.fx.animateFont = function(/*Object*/ args){
-		// summary:
-		//	Returns an animation which will change font properties over time
-		// example:
-		//	|	dojox.gfx.fx.animateFont{{
-		//	|		shape: shape,
-		//	|		duration: 500,
-		//	|		variant: {values: ["normal", "small-caps"]},
-		//	|		size:  {end: 10, units: "pt"}
-		//	|	}).play();
-		if(!args.easing){ args.easing = d._defaultEasing; }
-		var anim = new d.Animation(args), shape = args.shape, font;
-		d.connect(anim, "beforeBegin", anim, function(){
-			font = shape.getFont();
-			var prop = args.style, values = {}, value, start, end;
-			if(prop && prop.values){
-				values.style = new InterpolValues(prop.values);
-			}
-			prop = args.variant;
-			if(prop && prop.values){
-				values.variant = new InterpolValues(prop.values);
-			}
-			prop = args.weight;
-			if(prop && prop.values){
-				values.weight = new InterpolValues(prop.values);
-			}
-			prop = args.family;
-			if(prop && prop.values){
-				values.family = new InterpolValues(prop.values);
-			}
-			prop = args.size;
-			if(prop && prop.units){
-				start = parseFloat(prop.start ? prop.start : (shape.font && shape.font.size || "0"));
-				end = parseFloat(prop.end ? prop.end : (shape.font && shape.font.size || "0"));
-				values.size = new InterpolUnit(start, end, prop.units);
-			}
-			this.curve = new InterpolObject(values, font);
-		});
-		d.connect(anim, "onAnimate", shape, "setFont");
-		return anim; // dojo.Animation
-	};
-
-	g.fx.animateTransform = function(/*Object*/ args){
-		// summary:
-		//	Returns an animation which will change transformation over time
-		// example:
-		//	|	dojox.gfx.fx.animateTransform{{
-		//	|		shape: shape,
-		//	|		duration: 500,
-		//	|		transform: [
-		//	|			{name: "translate", start: [0, 0], end: [200, 200]},
-		//	|			{name: "original"}
-		//	|		]
-		//	|	}).play();
-		if(!args.easing){ args.easing = d._defaultEasing; }
-		var anim = new d.Animation(args), shape = args.shape, original;
-		d.connect(anim, "beforeBegin", anim, function(){
-			original = shape.getTransform();
-			this.curve = new InterpolTransform(args.transform, original);
-		});
-		d.connect(anim, "onAnimate", shape, "setTransform");
-		return anim; // dojo.Animation
-	};
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Columns"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Columns"] = true;
-dojo.provide("dojox.charting.plot2d.Columns");
-
-
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, du = dojox.lang.utils,
-		dc = dojox.charting.plot2d.common,
-		purgeGroup = df.lambda("item.purgeGroup()");
-
-	dojo.declare("dojox.charting.plot2d.Columns", dojox.charting.plot2d.Base, {
-		defaultParams: {
-			hAxis: "x",		// use a horizontal axis named "x"
-			vAxis: "y",		// use a vertical axis named "y"
-			gap:	0,		// gap between columns in pixels
-			shadows: null,	// draw shadows
-			animate: null   // animate bars into place
-		},
-		optionalParams: {
-			minBarSize: 1,	// minimal bar size in pixels
-			maxBarSize: 1	// maximal bar size in pixels
-		},
-
-		constructor: function(chart, kwArgs){
-			this.opt = dojo.clone(this.defaultParams);
-			du.updateWithObject(this.opt, kwArgs);
-			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
-			this.series = [];
-			this.hAxis = this.opt.hAxis;
-			this.vAxis = this.opt.vAxis;
-			this.animate = this.opt.animate;
-		},
-
-		calculateAxes: function(dim){
-			var stats = dc.collectSimpleStats(this.series);
-			stats.hmin -= 0.5;
-			stats.hmax += 0.5;
-			this._calc(dim, stats);
-			return this;
-		},
-		render: function(dim, offsets){
-			this.dirty = this.isDirty();
-			if(this.dirty){
-				dojo.forEach(this.series, purgeGroup);
-				this.cleanGroup();
-				var s = this.group;
-				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
-			}
-			var t = this.chart.theme, color, stroke, fill, f, gap, width,
-				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
-				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
-				baseline = Math.max(0, this._vScaler.bounds.lower),
-				baselineHeight = vt(baseline),
-				events = this.events();
-			f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt);
-			gap = f.gap;
-			width = f.size;
-			this.resetEvents();
-			for(var i = this.series.length - 1; i >= 0; --i){
-				var run = this.series[i];
-				if(!this.dirty && !run.dirty){ continue; }
-				run.cleanGroup();
-				var s = run.group;
-				if(!run.fill || !run.stroke){
-					// need autogenerated color
-					color = run.dyn.color = new dojo.Color(t.next("color"));
-				}
-				stroke = run.stroke ? run.stroke : dc.augmentStroke(t.series.stroke, color);
-				fill = run.fill ? run.fill : dc.augmentFill(t.series.fill, color);
-				for(var j = 0; j < run.data.length; ++j){
-					var value = run.data[j],
-						v = typeof value == "number" ? value : value.y,
-						vv = vt(v),
-						height = vv - baselineHeight,
-						h = Math.abs(height),
-						specialColor  = color,
-						specialFill   = fill,
-						specialStroke = stroke;
-					if(typeof value != "number"){
-						if(value.color){
-							specialColor = new dojo.Color(value.color);
-						}
-						if("fill" in value){
-							specialFill = value.fill;
-						}else if(value.color){
-							specialFill = dc.augmentFill(t.series.fill, specialColor);
-						}
-						if("stroke" in value){
-							specialStroke = value.stroke;
-						}else if(value.color){
-							specialStroke = dc.augmentStroke(t.series.stroke, specialColor);
-						}
-					}
-					if(width >= 1 && h >= 1){
-						var shape = s.createRect({
-								x: offsets.l + ht(j + 0.5) + gap,
-								y: dim.height - offsets.b - (v > baseline ? vv : baselineHeight),
-								width: width, height: h
-							}).setFill(specialFill).setStroke(specialStroke);
-						run.dyn.fill   = shape.getFill();
-						run.dyn.stroke = shape.getStroke();
-						if(events){
-							var o = {
-								element: "column",
-								index:   j,
-								run:     run,
-								plot:    this,
-								hAxis:   this.hAxis || null,
-								vAxis:   this.vAxis || null,
-								shape:   shape,
-								x:       j + 0.5,
-								y:       v
-							};
-							this._connectEvents(shape, o);
-						}
-						if(this.animate){
-							this._animateColumn(shape, dim.height - offsets.b - baselineHeight, h);
-						}
-					}
-				}
-				run.dirty = false;
-			}
-			this.dirty = false;
-			return this;
-		},
-		_animateColumn: function(shape, voffset, vsize){
-			dojox.gfx.fx.animateTransform(dojo.delegate({
-				shape: shape,
-				duration: 1200,
-				transform: [
-					{name: "translate", start: [0, voffset - (voffset/vsize)], end: [0, 0]},
-					{name: "scale", start: [1, 1/vsize], end: [1, 1]},
-					{name: "original"}
-				]
-			}, this.animate)).play();
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.StackedColumns"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.StackedColumns"] = true;
-dojo.provide("dojox.charting.plot2d.StackedColumns");
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common,
-		purgeGroup = df.lambda("item.purgeGroup()");
-
-	dojo.declare("dojox.charting.plot2d.StackedColumns", dojox.charting.plot2d.Columns, {
-		calculateAxes: function(dim){
-			var stats = dc.collectStackedStats(this.series);
-			this._maxRunLength = stats.hmax;
-			stats.hmin -= 0.5;
-			stats.hmax += 0.5;
-			this._calc(dim, stats);
-			return this;
-		},
-		render: function(dim, offsets){
-			if(this._maxRunLength <= 0){
-				return this;
-			}
-
-			// stack all values
-			var acc = df.repeat(this._maxRunLength, "-> 0", 0);
-			for(var i = 0; i < this.series.length; ++i){
-				var run = this.series[i];
-				for(var j = 0; j < run.data.length; ++j){
-					var value = run.data[j], v = typeof value == "number" ? value : value.y;
-					if(isNaN(v)){ v = 0; }
-					acc[j] += v;
-				}
-			}
-			// draw runs in backwards
-			this.dirty = this.isDirty();
-			if(this.dirty){
-				dojo.forEach(this.series, purgeGroup);
-				this.cleanGroup();
-				var s = this.group;
-				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
-			}
-			var t = this.chart.theme, color, stroke, fill, f, gap, width,
-				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
-				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
-				events = this.events();
-			f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt);
-			gap = f.gap;
-			width = f.size;
-			this.resetEvents();
-			for(var i = this.series.length - 1; i >= 0; --i){
-				var run = this.series[i];
-				if(!this.dirty && !run.dirty){ continue; }
-				run.cleanGroup();
-				var s = run.group;
-				if(!run.fill || !run.stroke){
-					// need autogenerated color
-					color = run.dyn.color = new dojo.Color(t.next("color"));
-				}
-				stroke = run.stroke ? run.stroke : dc.augmentStroke(t.series.stroke, color);
-				fill = run.fill ? run.fill : dc.augmentFill(t.series.fill, color);
-				for(var j = 0; j < acc.length; ++j){
-					var v = acc[j],
-						height = vt(v),
-						value = run.data[j],
-						specialColor  = color,
-						specialFill   = fill,
-						specialStroke = stroke;
-					if(typeof value != "number"){
-						if(value.color){
-							specialColor = new dojo.Color(value.color);
-						}
-						if("fill" in value){
-							specialFill = value.fill;
-						}else if(value.color){
-							specialFill = dc.augmentFill(t.series.fill, specialColor);
-						}
-						if("stroke" in value){
-							specialStroke = value.stroke;
-						}else if(value.color){
-							specialStroke = dc.augmentStroke(t.series.stroke, specialColor);
-						}
-					}
-					if(width >= 1 && height >= 1){
-						var shape = s.createRect({
-							x: offsets.l + ht(j + 0.5) + gap,
-							y: dim.height - offsets.b - vt(v),
-							width: width, height: height
-						}).setFill(specialFill).setStroke(specialStroke);
-						run.dyn.fill   = shape.getFill();
-						run.dyn.stroke = shape.getStroke();
-						if(events){
-							var o = {
-								element: "column",
-								index:   j,
-								run:     run,
-								plot:    this,
-								hAxis:   this.hAxis || null,
-								vAxis:   this.vAxis || null,
-								shape:   shape,
-								x:       j + 0.5,
-								y:       v
-							};
-							this._connectEvents(shape, o);
-						}
-						if(this.animate){
-							this._animateColumn(shape, dim.height - offsets.b, height);
-						}
-					}
-				}
-				run.dirty = false;
-				// update the accumulator
-				for(var j = 0; j < run.data.length; ++j){
-					var value = run.data[j], v = typeof value == "number" ? value : value.y;
-					if(isNaN(v)){ v = 0; }
-					acc[j] -= v;
-				}
-			}
-			this.dirty = false;
-			return this;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.ClusteredColumns"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.ClusteredColumns"] = true;
-dojo.provide("dojox.charting.plot2d.ClusteredColumns");
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common,
-		purgeGroup = df.lambda("item.purgeGroup()");
-
-	dojo.declare("dojox.charting.plot2d.ClusteredColumns", dojox.charting.plot2d.Columns, {
-		render: function(dim, offsets){
-			this.dirty = this.isDirty();
-			if(this.dirty){
-				dojo.forEach(this.series, purgeGroup);
-				this.cleanGroup();
-				var s = this.group;
-				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
-			}
-			var t = this.chart.theme, color, stroke, fill, f, gap, width, thickness,
-				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
-				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
-				baseline = Math.max(0, this._vScaler.bounds.lower),
-				baselineHeight = vt(baseline),
-				events = this.events();
-			f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt, this.series.length);
-			gap = f.gap;
-			width = thickness = f.size;
-			this.resetEvents();
-			for(var i = 0; i < this.series.length; ++i){
-				var run = this.series[i], shift = thickness * i;
-				if(!this.dirty && !run.dirty){ continue; }
-				run.cleanGroup();
-				var s = run.group;
-				if(!run.fill || !run.stroke){
-					// need autogenerated color
-					color = run.dyn.color = new dojo.Color(t.next("color"));
-				}
-				stroke = run.stroke ? run.stroke : dc.augmentStroke(t.series.stroke, color);
-				fill = run.fill ? run.fill : dc.augmentFill(t.series.fill, color);
-				for(var j = 0; j < run.data.length; ++j){
-					var value = run.data[j],
-						v = typeof value == "number" ? value : value.y,
-						vv = vt(v),
-						height = vv - baselineHeight,
-						h = Math.abs(height),
-						specialColor  = color,
-						specialFill   = fill,
-						specialStroke = stroke;
-					if(typeof value != "number"){
-						if(value.color){
-							specialColor = new dojo.Color(value.color);
-						}
-						if("fill" in value){
-							specialFill = value.fill;
-						}else if(value.color){
-							specialFill = dc.augmentFill(t.series.fill, specialColor);
-						}
-						if("stroke" in value){
-							specialStroke = value.stroke;
-						}else if(value.color){
-							specialStroke = dc.augmentStroke(t.series.stroke, specialColor);
-						}
-					}
-					if(width >= 1 && h >= 1){
-						var shape = s.createRect({
-							x: offsets.l + ht(j + 0.5) + gap + shift,
-							y: dim.height - offsets.b - (v > baseline ? vv : baselineHeight),
-							width: width, height: h
-						}).setFill(specialFill).setStroke(specialStroke);
-						run.dyn.fill   = shape.getFill();
-						run.dyn.stroke = shape.getStroke();
-						if(events){
-							var o = {
-								element: "column",
-								index:   j,
-								run:     run,
-								plot:    this,
-								hAxis:   this.hAxis || null,
-								vAxis:   this.vAxis || null,
-								shape:   shape,
-								x:       j + 0.5,
-								y:       v
-							};
-							this._connectEvents(shape, o);
-						}
-						if(this.animate){
-							this._animateColumn(shape, dim.height - offsets.b - baselineHeight, h);
-						}
-					}
-				}
-				run.dirty = false;
-			}
-			this.dirty = false;
-			return this;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Bars"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Bars"] = true;
-dojo.provide("dojox.charting.plot2d.Bars");
-
-
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, du = dojox.lang.utils,
-		dc = dojox.charting.plot2d.common,
-		purgeGroup = df.lambda("item.purgeGroup()");
-
-	dojo.declare("dojox.charting.plot2d.Bars", dojox.charting.plot2d.Base, {
-		defaultParams: {
-			hAxis: "x",		// use a horizontal axis named "x"
-			vAxis: "y",		// use a vertical axis named "y"
-			gap:	0,		// gap between columns in pixels
-			shadows: null,	// draw shadows
-			animate: null   // animate bars into place
-		},
-		optionalParams: {
-			minBarSize: 1,	// minimal bar size in pixels
-			maxBarSize: 1	// maximal bar size in pixels
-		},
-
-		constructor: function(chart, kwArgs){
-			this.opt = dojo.clone(this.defaultParams);
-			du.updateWithObject(this.opt, kwArgs);
-			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
-			this.series = [];
-			this.hAxis = this.opt.hAxis;
-			this.vAxis = this.opt.vAxis;
-			this.animate = this.opt.animate;
-		},
-
-		calculateAxes: function(dim){
-			var stats = dc.collectSimpleStats(this.series), t;
-			stats.hmin -= 0.5;
-			stats.hmax += 0.5;
-			t = stats.hmin, stats.hmin = stats.vmin, stats.vmin = t;
-			t = stats.hmax, stats.hmax = stats.vmax, stats.vmax = t;
-			this._calc(dim, stats);
-			return this;
-		},
-		render: function(dim, offsets){
-			this.dirty = this.isDirty();
-			if(this.dirty){
-				dojo.forEach(this.series, purgeGroup);
-				this.cleanGroup();
-				var s = this.group;
-				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
-			}
-			var t = this.chart.theme, color, stroke, fill, f, gap, height,
-				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
-				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
-				baseline = Math.max(0, this._hScaler.bounds.lower),
-				baselineWidth = ht(baseline),
-				events = this.events();
-			f = dc.calculateBarSize(this._vScaler.bounds.scale, this.opt);
-			gap = f.gap;
-			height = f.size;
-			this.resetEvents();
-			for(var i = this.series.length - 1; i >= 0; --i){
-				var run = this.series[i];
-				if(!this.dirty && !run.dirty){ continue; }
-				run.cleanGroup();
-				var s = run.group;
-				if(!run.fill || !run.stroke){
-					// need autogenerated color
-					color = run.dyn.color = new dojo.Color(t.next("color"));
-				}
-				stroke = run.stroke ? run.stroke : dc.augmentStroke(t.series.stroke, color);
-				fill = run.fill ? run.fill : dc.augmentFill(t.series.fill, color);
-				for(var j = 0; j < run.data.length; ++j){
-					var value = run.data[j],
-						v = typeof value == "number" ? value : value.y,
-						hv = ht(v),
-						width = hv - baselineWidth,
-						w = Math.abs(width),
-						specialColor  = color,
-						specialFill   = fill,
-						specialStroke = stroke;
-					if(typeof value != "number"){
-						if(value.color){
-							specialColor = new dojo.Color(value.color);
-						}
-						if("fill" in value){
-							specialFill = value.fill;
-						}else if(value.color){
-							specialFill = dc.augmentFill(t.series.fill, specialColor);
-						}
-						if("stroke" in value){
-							specialStroke = value.stroke;
-						}else if(value.color){
-							specialStroke = dc.augmentStroke(t.series.stroke, specialColor);
-						}
-					}
-					if(w >= 1 && height >= 1){
-						var shape = s.createRect({
-							x: offsets.l + (v < baseline ? hv : baselineWidth),
-							y: dim.height - offsets.b - vt(j + 1.5) + gap,
-							width: w, height: height
-						}).setFill(specialFill).setStroke(specialStroke);
-						run.dyn.fill   = shape.getFill();
-						run.dyn.stroke = shape.getStroke();
-						if(events){
-							var o = {
-								element: "bar",
-								index:   j,
-								run:     run,
-								plot:    this,
-								hAxis:   this.hAxis || null,
-								vAxis:   this.vAxis || null,
-								shape:   shape,
-								x:       v,
-								y:       j + 1.5
-							};
-							this._connectEvents(shape, o);
-						}
-						if(this.animate){
-							this._animateBar(shape, offsets.l + baselineWidth, -w);
-						}
-					}
-				}
-				run.dirty = false;
-			}
-			this.dirty = false;
-			return this;
-		},
-		_animateBar: function(shape, hoffset, hsize){
-			dojox.gfx.fx.animateTransform(dojo.delegate({
-				shape: shape,
-				duration: 1200,
-				transform: [
-					{name: "translate", start: [hoffset - (hoffset/hsize), 0], end: [0, 0]},
-					{name: "scale", start: [1/hsize, 1], end: [1, 1]},
-					{name: "original"}
-				]
-			}, this.animate)).play();
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.StackedBars"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.StackedBars"] = true;
-dojo.provide("dojox.charting.plot2d.StackedBars");
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common,
-		purgeGroup = df.lambda("item.purgeGroup()");
-
-	dojo.declare("dojox.charting.plot2d.StackedBars", dojox.charting.plot2d.Bars, {
-		calculateAxes: function(dim){
-			var stats = dc.collectStackedStats(this.series), t;
-			this._maxRunLength = stats.hmax;
-			stats.hmin -= 0.5;
-			stats.hmax += 0.5;
-			t = stats.hmin, stats.hmin = stats.vmin, stats.vmin = t;
-			t = stats.hmax, stats.hmax = stats.vmax, stats.vmax = t;
-			this._calc(dim, stats);
-			return this;
-		},
-		render: function(dim, offsets){
-			if(this._maxRunLength <= 0){
-				return this;
-			}
-
-			// stack all values
-			var acc = df.repeat(this._maxRunLength, "-> 0", 0);
-			for(var i = 0; i < this.series.length; ++i){
-				var run = this.series[i];
-				for(var j = 0; j < run.data.length; ++j){
-					var value = run.data[j], v = typeof value == "number" ? value : value.y;
-					if(isNaN(v)){ v = 0; }
-					acc[j] += v;
-				}
-			}
-			// draw runs in backwards
-			this.dirty = this.isDirty();
-			if(this.dirty){
-				dojo.forEach(this.series, purgeGroup);
-				this.cleanGroup();
-				var s = this.group;
-				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
-			}
-			var t = this.chart.theme, color, stroke, fill, f, gap, height,
-				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
-				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
-				events = this.events();
-			f = dc.calculateBarSize(this._vScaler.bounds.scale, this.opt);
-			gap = f.gap;
-			height = f.size;
-			this.resetEvents();
-			for(var i = this.series.length - 1; i >= 0; --i){
-				var run = this.series[i];
-				if(!this.dirty && !run.dirty){ continue; }
-				run.cleanGroup();
-				var s = run.group;
-				if(!run.fill || !run.stroke){
-					// need autogenerated color
-					color = run.dyn.color = new dojo.Color(t.next("color"));
-				}
-				stroke = run.stroke ? run.stroke : dc.augmentStroke(t.series.stroke, color);
-				fill = run.fill ? run.fill : dc.augmentFill(t.series.fill, color);
-				for(var j = 0; j < acc.length; ++j){
-					var v = acc[j],
-						width = ht(v),
-						value = run.data[j],
-						specialColor  = color,
-						specialFill   = fill,
-						specialStroke = stroke;
-					if(typeof value != "number"){
-						if(value.color){
-							specialColor = new dojo.Color(value.color);
-						}
-						if("fill" in value){
-							specialFill = value.fill;
-						}else if(value.color){
-							specialFill = dc.augmentFill(t.series.fill, specialColor);
-						}
-						if("stroke" in value){
-							specialStroke = value.stroke;
-						}else if(value.color){
-							specialStroke = dc.augmentStroke(t.series.stroke, specialColor);
-						}
-					}
-					if(width >= 1 && height >= 1){
-						var shape = s.createRect({
-							x: offsets.l,
-							y: dim.height - offsets.b - vt(j + 1.5) + gap,
-							width: width, height: height
-						}).setFill(specialFill).setStroke(specialStroke);
-						run.dyn.fill   = shape.getFill();
-						run.dyn.stroke = shape.getStroke();
-						if(events){
-							var o = {
-								element: "bar",
-								index:   j,
-								run:     run,
-								plot:    this,
-								hAxis:   this.hAxis || null,
-								vAxis:   this.vAxis || null,
-								shape:   shape,
-								x:       v,
-								y:       j + 1.5
-							};
-							this._connectEvents(shape, o);
-						}
-						if(this.animate){
-							this._animateBar(shape, offsets.l, -width);
-						}
-					}
-				}
-				run.dirty = false;
-				// update the accumulator
-				for(var j = 0; j < run.data.length; ++j){
-					var value = run.data[j], v = typeof value == "number" ? value : value.y;
-					if(isNaN(v)){ v = 0; }
-					acc[j] -= v;
-				}
-			}
-			this.dirty = false;
-			return this;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.ClusteredBars"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.ClusteredBars"] = true;
-dojo.provide("dojox.charting.plot2d.ClusteredBars");
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, dc = dojox.charting.plot2d.common,
-		purgeGroup = df.lambda("item.purgeGroup()");
-
-	dojo.declare("dojox.charting.plot2d.ClusteredBars", dojox.charting.plot2d.Bars, {
-		render: function(dim, offsets){
-			this.dirty = this.isDirty();
-			if(this.dirty){
-				dojo.forEach(this.series, purgeGroup);
-				this.cleanGroup();
-				var s = this.group;
-				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
-			}
-			var t = this.chart.theme, color, stroke, fill, f, gap, height, thickness,
-				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
-				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
-				baseline = Math.max(0, this._hScaler.bounds.lower),
-				baselineWidth = ht(baseline),
-				events = this.events();
-			f = dc.calculateBarSize(this._vScaler.bounds.scale, this.opt, this.series.length);
-			gap = f.gap;
-			height = thickness = f.size;
-			this.resetEvents();
-			for(var i = this.series.length - 1; i >= 0; --i){
-				var run = this.series[i], shift = thickness * (this.series.length - i - 1);
-				if(!this.dirty && !run.dirty){ continue; }
-				run.cleanGroup();
-				var s = run.group;
-				if(!run.fill || !run.stroke){
-					// need autogenerated color
-					color = run.dyn.color = new dojo.Color(t.next("color"));
-				}
-				stroke = run.stroke ? run.stroke : dc.augmentStroke(t.series.stroke, color);
-				fill = run.fill ? run.fill : dc.augmentFill(t.series.fill, color);
-				for(var j = 0; j < run.data.length; ++j){
-					var value = run.data[j],
-						v = typeof value == "number" ? value : value.y,
-						hv = ht(v),
-						width = hv - baselineWidth,
-						w = Math.abs(width),
-						specialColor  = color,
-						specialFill   = fill,
-						specialStroke = stroke;
-					if(typeof value != "number"){
-						if(value.color){
-							specialColor = new dojo.Color(value.color);
-						}
-						if("fill" in value){
-							specialFill = value.fill;
-						}else if(value.color){
-							specialFill = dc.augmentFill(t.series.fill, specialColor);
-						}
-						if("stroke" in value){
-							specialStroke = value.stroke;
-						}else if(value.color){
-							specialStroke = dc.augmentStroke(t.series.stroke, specialColor);
-						}
-					}
-					if(w >= 1 && height >= 1){
-						var shape = s.createRect({
-							x: offsets.l + (v < baseline ? hv : baselineWidth),
-							y: dim.height - offsets.b - vt(j + 1.5) + gap + shift,
-							width: w, height: height
-						}).setFill(specialFill).setStroke(specialStroke);
-						run.dyn.fill   = shape.getFill();
-						run.dyn.stroke = shape.getStroke();
-						if(events){
-							var o = {
-								element: "bar",
-								index:   j,
-								run:     run,
-								plot:    this,
-								hAxis:   this.hAxis || null,
-								vAxis:   this.vAxis || null,
-								shape:   shape,
-								x:       v,
-								y:       j + 1.5
-							};
-							this._connectEvents(shape, o);
-						}
-						if(this.animate){
-							this._animateBar(shape, offsets.l + baselineWidth, -width);
-						}
-					}
-				}
-				run.dirty = false;
-			}
-			this.dirty = false;
-			return this;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Grid"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Grid"] = true;
-dojo.provide("dojox.charting.plot2d.Grid");
-
-
-
-
-
-(function(){
-	var du = dojox.lang.utils;
-
-	dojo.declare("dojox.charting.plot2d.Grid", dojox.charting.Element, {
-		defaultParams: {
-			hAxis: "x",			// use a horizontal axis named "x"
-			vAxis: "y",			// use a vertical axis named "y"
-			hMajorLines: true,	// draw horizontal major lines
-			hMinorLines: false,	// draw horizontal minor lines
-			vMajorLines: true,	// draw vertical major lines
-			vMinorLines: false,	// draw vertical minor lines
-			hStripes: "none",	// TBD
-			vStripes: "none"	// TBD
-		},
-		optionalParams: {},	// no optional parameters
-
-		constructor: function(chart, kwArgs){
-			this.opt = dojo.clone(this.defaultParams);
-			du.updateWithObject(this.opt, kwArgs);
-			this.hAxis = this.opt.hAxis;
-			this.vAxis = this.opt.vAxis;
-			this.dirty = true;
-		},
-		clear: function(){
-			this._hAxis = null;
-			this._vAxis = null;
-			this.dirty = true;
-			return this;
-		},
-		setAxis: function(axis){
-			if(axis){
-				this[axis.vertical ? "_vAxis" : "_hAxis"] = axis;
-			}
-			return this;
-		},
-		addSeries: function(run){
-			// nothing
-			return this;
-		},
-		calculateAxes: function(dim){
-			// nothing
-			return this;
-		},
-		isDirty: function(){
-			return this.dirty || this._hAxis && this._hAxis.dirty || this._vAxis && this._vAxis.dirty;
-		},
-		getRequiredColors: function(){
-			return 0;
-		},
-		render: function(dim, offsets){
-			this.dirty = this.isDirty();
-			if(!this.dirty){ return this; }
-			this.cleanGroup();
-			var s = this.group, ta = this.chart.theme.axis;
-			// draw horizontal stripes and lines
-			try{
-				var vScaler = this._vAxis.getScaler(),
-					vt = vScaler.scaler.getTransformerFromModel(vScaler),
-					ticks = this._vAxis.getTicks();
-				if(this.opt.hMinorLines){
-					dojo.forEach(ticks.minor, function(tick){
-						var y = dim.height - offsets.b - vt(tick.value);
-						s.createLine({
-							x1: offsets.l,
-							y1: y,
-							x2: dim.width - offsets.r,
-							y2: y
-						}).setStroke(ta.minorTick);
-					});
-				}
-				if(this.opt.hMajorLines){
-					dojo.forEach(ticks.major, function(tick){
-						var y = dim.height - offsets.b - vt(tick.value);
-						s.createLine({
-							x1: offsets.l,
-							y1: y,
-							x2: dim.width - offsets.r,
-							y2: y
-						}).setStroke(ta.majorTick);
-					});
-				}
-			}catch(e){
-				// squelch
-			}
-			// draw vertical stripes and lines
-			try{
-				var hScaler = this._hAxis.getScaler(),
-					ht = hScaler.scaler.getTransformerFromModel(hScaler),
-					ticks = this._hAxis.getTicks();
-				if(ticks && this.opt.vMinorLines){
-					dojo.forEach(ticks.minor, function(tick){
-						var x = offsets.l + ht(tick.value);
-						s.createLine({
-							x1: x,
-							y1: offsets.t,
-							x2: x,
-							y2: dim.height - offsets.b
-						}).setStroke(ta.minorTick);
-					});
-				}
-				if(ticks && this.opt.vMajorLines){
-					dojo.forEach(ticks.major, function(tick){
-						var x = offsets.l + ht(tick.value);
-						s.createLine({
-							x1: x,
-							y1: offsets.t,
-							x2: x,
-							y2: dim.height - offsets.b
-						}).setStroke(ta.majorTick);
-					});
-				}
-			}catch(e){
-				// squelch
-			}
-			this.dirty = false;
-			return this;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Pie"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Pie"] = true;
-dojo.provide("dojox.charting.plot2d.Pie");
-
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, du = dojox.lang.utils,
-		dc = dojox.charting.plot2d.common,
-		da = dojox.charting.axis2d.common,
-		g = dojox.gfx;
-
-	dojo.declare("dojox.charting.plot2d.Pie", dojox.charting.Element, {
-		defaultParams: {
-			labels:			true,
-			ticks:			false,
-			fixed:			true,
-			precision:		1,
-			labelOffset:	20,
-			labelStyle:		"default",	// default/rows/auto
-			htmlLabels:		true		// use HTML to draw labels
-		},
-		optionalParams: {
-			font:		"",
-			fontColor:	"",
-			radius:		0
-		},
-
-		constructor: function(chart, kwArgs){
-			this.opt = dojo.clone(this.defaultParams);
-			du.updateWithObject(this.opt, kwArgs);
-			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
-			this.run = null;
-			this.dyn = [];
-		},
-		destroy: function(){
-			this.resetEvents();
-			this.inherited(arguments);
-		},
-		clear: function(){
-			this.dirty = true;
-			this.dyn = [];
-			this.run = null;
-			return this;
-		},
-		setAxis: function(axis){
-			// nothing
-			return this;
-		},
-		addSeries: function(run){
-			this.run = run;
-			return this;
-		},
-		calculateAxes: function(dim){
-			// nothing
-			return this;
-		},
-		getRequiredColors: function(){
-			return this.run ? this.run.data.length : 0;
-		},
-
-		// events
-		plotEvent: function(o){
-			// intentionally empty --- used for events
-		},
-		connect: function(object, method){
-			this.dirty = true;
-			return dojo.connect(this, "plotEvent", object, method);
-		},
-		events: function(){
-			var ls = this.plotEvent._listeners;
-			if(!ls || !ls.length){ return false; }
-			for(var i in ls){
-				if(!(i in Array.prototype)){
-					return true;
-				}
-			}
-			return false;
-		},
-		resetEvents: function(){
-			this.plotEvent({type: "onplotreset", plot: this});
-		},
-		_connectEvents: function(shape, o){
-			shape.connect("onmouseover", this, function(e){
-				o.type  = "onmouseover";
-				o.event = e;
-				this.plotEvent(o);
-			});
-			shape.connect("onmouseout", this, function(e){
-				o.type  = "onmouseout";
-				o.event = e;
-				this.plotEvent(o);
-			});
-			shape.connect("onclick", this, function(e){
-				o.type  = "onclick";
-				o.event = e;
-				this.plotEvent(o);
-			});
-		},
-
-		render: function(dim, offsets){
-			if(!this.dirty){ return this; }
-			this.dirty = false;
-			this.cleanGroup();
-			var s = this.group, color, t = this.chart.theme;
-			this.resetEvents();
-
-			if(!this.run || !this.run.data.length){
-				return this;
-			}
-
-			// calculate the geometry
-			var rx = (dim.width  - offsets.l - offsets.r) / 2,
-				ry = (dim.height - offsets.t - offsets.b) / 2,
-				r  = Math.min(rx, ry),
-				taFont = "font" in this.opt ? this.opt.font : t.axis.font,
-				size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
-				taFontColor = "fontColor" in this.opt ? this.opt.fontColor : t.axis.fontColor,
-				start = 0, step, filteredRun, slices, labels, shift, labelR,
-				run = this.run.data,
-				events = this.events();
-			if(typeof run[0] == "number"){
-				filteredRun = df.map(run, "Math.max(x, 0)");
-				if(df.every(filteredRun, "<= 0")){
-					return this;
-				}
-				slices = df.map(filteredRun, "/this", df.foldl(filteredRun, "+", 0));
-				if(this.opt.labels){
-					labels = dojo.map(slices, function(x){
-						return x > 0 ? this._getLabel(x * 100) + "%" : "";
-					}, this);
-				}
-			}else{
-				filteredRun = df.map(run, "Math.max(x.y, 0)");
-				if(df.every(filteredRun, "<= 0")){
-					return this;
-				}
-				slices = df.map(filteredRun, "/this", df.foldl(filteredRun, "+", 0));
-				if(this.opt.labels){
-					labels = dojo.map(slices, function(x, i){
-						if(x <= 0){ return ""; }
-						var v = run[i];
-						return "text" in v ? v.text : this._getLabel(x * 100) + "%";
-					}, this);
-				}
-			}
-			if(this.opt.labels){
-				shift = df.foldl1(df.map(labels, function(label){
-					return dojox.gfx._base._getTextBox(label, {font: taFont}).w;
-				}, this), "Math.max(a, b)") / 2;
-				if(this.opt.labelOffset < 0){
-					r = Math.min(rx - 2 * shift, ry - size) + this.opt.labelOffset;
-				}
-				labelR = r - this.opt.labelOffset;
-			}
-			if("radius" in this.opt){
-				r = this.opt.radius;
-				labelR = r - this.opt.labelOffset;
-			}
-			var	circle = {
-					cx: offsets.l + rx,
-					cy: offsets.t + ry,
-					r:  r
-				};
-
-			this.dyn = [];
-			// draw slices
-			dojo.some(slices, function(slice, i){
-				if(slice <= 0){
-					// degenerated slice
-					return false;	// continue
-				}
-				var v = run[i];
-				if(slice >= 1){
-					// whole pie
-					var color, fill, stroke;
-					if(typeof v == "object"){
-						color  = "color"  in v ? v.color  : new dojo.Color(t.next("color"));
-						fill   = "fill"   in v ? v.fill   : dc.augmentFill(t.series.fill, color);
-						stroke = "stroke" in v ? v.stroke : dc.augmentStroke(t.series.stroke, color);
-					}else{
-						color  = new dojo.Color(t.next("color"));
-						fill   = dc.augmentFill(t.series.fill, color);
-						stroke = dc.augmentStroke(t.series.stroke, color);
-					}
-					var shape = s.createCircle(circle).setFill(fill).setStroke(stroke);
-					this.dyn.push({color: color, fill: fill, stroke: stroke});
-
-					if(events){
-						var o = {
-							element: "slice",
-							index:   i,
-							run:     this.run,
-							plot:    this,
-							shape:   shape,
-							x:       i,
-							y:       typeof v == "number" ? v : v.y,
-							cx:      circle.cx,
-							cy:      circle.cy,
-							cr:      r
-						};
-						this._connectEvents(shape, o);
-					}
-
-					return true;	// stop iteration
-				}
-				// calculate the geometry of the slice
-				var end = start + slice * 2 * Math.PI;
-				if(i + 1 == slices.length){
-					end = 2 * Math.PI;
-				}
-				var	step = end - start,
-					x1 = circle.cx + r * Math.cos(start),
-					y1 = circle.cy + r * Math.sin(start),
-					x2 = circle.cx + r * Math.cos(end),
-					y2 = circle.cy + r * Math.sin(end);
-				// draw the slice
-				var color, fill, stroke;
-				if(typeof v == "object"){
-					color  = "color"  in v ? v.color  : new dojo.Color(t.next("color"));
-					fill   = "fill"   in v ? v.fill   : dc.augmentFill(t.series.fill, color);
-					stroke = "stroke" in v ? v.stroke : dc.augmentStroke(t.series.stroke, color);
-				}else{
-					color  = new dojo.Color(t.next("color"));
-					fill   = dc.augmentFill(t.series.fill, color);
-					stroke = dc.augmentStroke(t.series.stroke, color);
-				}
-				var shape = s.createPath({}).
-						moveTo(circle.cx, circle.cy).
-						lineTo(x1, y1).
-						arcTo(r, r, 0, step > Math.PI, true, x2, y2).
-						lineTo(circle.cx, circle.cy).
-						closePath().
-						setFill(fill).
-						setStroke(stroke);
-				this.dyn.push({color: color, fill: fill, stroke: stroke});
-
-				if(events){
-					var o = {
-						element: "slice",
-						index:   i,
-						run:     this.run,
-						plot:    this,
-						shape:   shape,
-						x:       i,
-						y:       typeof v == "number" ? v : v.y,
-						cx:      circle.cx,
-						cy:      circle.cy,
-						cr:      r
-					};
-					this._connectEvents(shape, o);
-				}
-
-				start = end;
-
-				return false;	// continue
-			}, this);
-			// draw labels
-			if(this.opt.labels){
-				start = 0;
-				dojo.some(slices, function(slice, i){
-					if(slice <= 0){
-						// degenerated slice
-						return false;	// continue
-					}
-					if(slice >= 1){
-						// whole pie
-						var v = run[i], elem = da.createText[this.opt.htmlLabels && dojox.gfx.renderer != "vml" ? "html" : "gfx"]
-									(this.chart, s, circle.cx, circle.cy + size / 2, "middle",
-										labels[i], taFont, (typeof v == "object" && "fontColor" in v) ? v.fontColor : taFontColor);
-						if(this.opt.htmlLabels){ this.htmlElements.push(elem); }
-						return true;	// stop iteration
-					}
-					// calculate the geometry of the slice
-					var end = start + slice * 2 * Math.PI, v = run[i];
-					if(i + 1 == slices.length){
-						end = 2 * Math.PI;
-					}
-					var	labelAngle = (start + end) / 2,
-						x = circle.cx + labelR * Math.cos(labelAngle),
-						y = circle.cy + labelR * Math.sin(labelAngle) + size / 2;
-					// draw the label
-					var elem = da.createText[this.opt.htmlLabels && dojox.gfx.renderer != "vml" ? "html" : "gfx"]
-									(this.chart, s, x, y, "middle",
-										labels[i], taFont,
-										(typeof v == "object" && "fontColor" in v)
-											? v.fontColor : taFontColor);
-					if(this.opt.htmlLabels){ this.htmlElements.push(elem); }
-					start = end;
-					return false;	// continue
-				}, this);
-			}
-			return this;
-		},
-
-		// utilities
-		_getLabel: function(number){
-			return this.opt.fixed ? number.toFixed(this.opt.precision) : number.toString();
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Bubble"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Bubble"] = true;
-dojo.provide("dojox.charting.plot2d.Bubble");
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, du = dojox.lang.utils,
-		dc = dojox.charting.plot2d.common,
-		purgeGroup = df.lambda("item.purgeGroup()");
-
-	dojo.declare("dojox.charting.plot2d.Bubble", dojox.charting.plot2d.Base, {
-		defaultParams: {
-			hAxis: "x",		// use a horizontal axis named "x"
-			vAxis: "y"		// use a vertical axis named "y"
-		},
-		optionalParams: {},	// no optional parameters
-
-		constructor: function(chart, kwArgs){
-			this.opt = dojo.clone(this.defaultParams);
-			du.updateWithObject(this.opt, kwArgs);
-			this.series = [];
-			this.hAxis = this.opt.hAxis;
-			this.vAxis = this.opt.vAxis;
-		},
-		
-		calculateAxes: function(dim){
-			this._calc(dim, dc.collectSimpleStats(this.series));
-			return this;
-		},
-
-		//	override the render so that we are plotting only circles.
-		render: function(dim, offsets){
-			this.dirty = this.isDirty();
-			if(this.dirty){
-				dojo.forEach(this.series, purgeGroup);
-				this.cleanGroup();
-				var s = this.group;
-				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
-			}
-		
-			var t = this.chart.theme, stroke, outline, color, shadowStroke, shadowColor,
-				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
-				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
-				events = this.events();
-
-			this.resetEvents();
-
-			for(var i = this.series.length - 1; i >= 0; --i){
-				var run = this.series[i];
-				if(!this.dirty && !run.dirty){ continue; }
-				run.cleanGroup();
-				if(!run.data.length){
-					run.dirty = false;
-					continue;
-				}
-
-				if(typeof run.data[0] == "number"){
-					console.warn("dojox.charting.plot2d.Bubble: the data in the following series cannot be rendered as a bubble chart; ", run);
-					continue;
-				}
-				
-				var s = run.group,
-					points = dojo.map(run.data, function(v, i){
-						return {
-							x: ht(v.x) + offsets.l,
-							y: dim.height - offsets.b - vt(v.y),
-							radius: this._vScaler.bounds.scale * (v.size / 2)
-						};
-					}, this);
-
-				if(run.fill){
-					color = run.fill;
-				}else if(run.stroke){
-					color = run.stroke;
-				}else{
-					color = run.dyn.color = new dojo.Color(t.next("color"));
-				}
-				run.dyn.fill = color;
-
-				stroke = run.dyn.stroke = run.stroke ? dc.makeStroke(run.stroke) : dc.augmentStroke(t.series.stroke, color);
-
-				var frontCircles = null, outlineCircles = null, shadowCircles = null;
-
-				// make shadows if needed
-				if(this.opt.shadows && stroke){
-					var sh = this.opt.shadows, shadowColor = new dojo.Color([0, 0, 0, 0.2]),
-						shadowStroke = dojo.clone(outline ? outline : stroke);
-					shadowStroke.color = shadowColor;
-					shadowStroke.width += sh.dw ? sh.dw : 0;
-					run.dyn.shadow = shadowStroke;
-					var shadowMarkers = dojo.map(points, function(item){
-						var sh = this.opt.shadows;
-						return s.createCircle({
-							cx: item.x + sh.dx, cy: item.y + sh.dy, r: item.radius
-						}).setStroke(shadowStroke).setFill(shadowColor);
-					}, this);
-				}
-
-				// make outlines if needed
-				if(run.outline || t.series.outline){
-					outline = dc.makeStroke(run.outline ? run.outline : t.series.outline);
-					outline.width = 2 * outline.width + stroke.width;
-					run.dyn.outline = outline;
-					outlineCircles = dojo.map(points, function(item){
-						s.createCircle({ cx: item.x, cy: item.y, r: item.radius }).setStroke(outline);
-					}, this);
-				}
-
-				//	run through the data and add the circles.
-				frontCircles = dojo.map(points, function(item){
-					return s.createCircle({ cx: item.x, cy: item.y, r: item.radius }).setStroke(stroke).setFill(color);
-				}, this);
-				
-				if(events){
-					dojo.forEach(frontCircles, function(s, i){
-						var o = {
-							element: "circle",
-							index:   i,
-							run:     run,
-							plot:    this,
-							hAxis:   this.hAxis || null,
-							vAxis:   this.vAxis || null,
-							shape:   s,
-							outline: outlineCircles && outlineCircles[i] || null,
-							shadow:  shadowCircles && shadowCircles[i] || null,
-							x:       run.data[i].x,
-							y:       run.data[i].y,
-							r:       run.data[i].size / 2,
-							cx:      points[i].x,
-							cy:      points[i].y,
-							cr:      points[i].radius
-						};
-						this._connectEvents(s, o);
-					}, this);
-				}
-				
-				run.dirty = false;
-			}
-			this.dirty = false;
-			return this;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.Candlesticks"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.Candlesticks"] = true;
-dojo.provide("dojox.charting.plot2d.Candlesticks");
-
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, du = dojox.lang.utils,
-		dc = dojox.charting.plot2d.common,
-		purgeGroup = df.lambda("item.purgeGroup()");
-
-	//	Candlesticks are based on the Bars plot type; we expect the following passed
-	//	as values in a series: 
-	//	{ x?, open, close, high, low, mid? }
-	//	if x is not provided, the array index is used.
-	//	failing to provide the OHLC values will throw an error.
-	dojo.declare("dojox.charting.plot2d.Candlesticks", dojox.charting.plot2d.Base, {
-		defaultParams: {
-			hAxis: "x",		// use a horizontal axis named "x"
-			vAxis: "y",		// use a vertical axis named "y"
-			gap:	2,		// gap between columns in pixels
-			shadows: null	// draw shadows
-		},
-		optionalParams: {
-			minBarSize: 1,	// minimal bar size in pixels
-			maxBarSize: 1	// maximal bar size in pixels
-		},
-
-		constructor: function(chart, kwArgs){
-			this.opt = dojo.clone(this.defaultParams);
-			du.updateWithObject(this.opt, kwArgs);
-			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
-			this.series = [];
-			this.hAxis = this.opt.hAxis;
-			this.vAxis = this.opt.vAxis;
-		},
-
-		collectStats: function(series){
-			//	we have to roll our own, since we need to use all four passed
-			//	values to figure out our stats, and common only assumes x and y.
-			var stats = dojo.clone(dc.defaultStats);
-			for(var i=0; i<series.length; i++){
-				var run = series[i];
-				if(!run.data.length){ continue; }
-				var old_vmin = stats.vmin, old_vmax = stats.vmax;
-				if(!("ymin" in run) || !("ymax" in run)){
-					dojo.forEach(run.data, function(val, idx){
-						var x = val.x || idx + 1;
-						stats.hmin = Math.min(stats.hmin, x);
-						stats.hmax = Math.max(stats.hmax, x);
-						stats.vmin = Math.min(stats.vmin, val.open, val.close, val.high, val.low);
-						stats.vmax = Math.max(stats.vmax, val.open, val.close, val.high, val.low);
-					});
-				}
-				if("ymin" in run){ stats.vmin = Math.min(old_vmin, run.ymin); }
-				if("ymax" in run){ stats.vmax = Math.max(old_vmax, run.ymax); }
-			}
-			return stats;
-		},
-
-		calculateAxes: function(dim){
-			var stats = this.collectStats(this.series), t;
-			stats.hmin -= 0.5;
-			stats.hmax += 0.5;
-			this._calc(dim, stats);
-			return this;
-		},
-
-		render: function(dim, offsets){
-			this.dirty = this.isDirty();
-			if(this.dirty){
-				dojo.forEach(this.series, purgeGroup);
-				this.cleanGroup();
-				var s = this.group;
-				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
-			}
-			var t = this.chart.theme, color, stroke, fill, f, gap, width,
-				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
-				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
-				baseline = Math.max(0, this._vScaler.bounds.lower),
-				baselineHeight = vt(baseline),
-				events = this.events();
-			f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt);
-			gap = f.gap;
-			width = f.size;
-			this.resetEvents();
-			for(var i = this.series.length - 1; i >= 0; --i){
-				var run = this.series[i];
-				if(!this.dirty && !run.dirty){ continue; }
-				run.cleanGroup();
-				var s = run.group;
-				if(!run.fill || !run.stroke){
-					// need autogenerated color
-					color = run.dyn.color = new dojo.Color(t.next("color"));
-				}
-				stroke = run.stroke ? run.stroke : dc.augmentStroke(t.series.stroke, color);
-				fill = run.fill ? run.fill : dc.augmentFill(t.series.fill, color);
-
-				for(var j = 0; j < run.data.length; ++j){
-					var v = run.data[j];
-
-					//	calculate the points we need for OHLC
-					var x = ht(v.x || (j+0.5)) + offsets.l + gap,
-						y = dim.height - offsets.b,
-						open = vt(v.open),
-						close = vt(v.close),
-						high = vt(v.high),
-						low = vt(v.low);
-					if("mid" in v){
-						var mid = vt(v.mid);
-					}
-					if(low > high){
-						var tmp = high;
-						high = low;
-						low = tmp;
-					}
-
-					if(width >= 1){
-						//	draw the line and rect, set up as a group and pass that to the events.
-						var doFill = open > close;
-						var line = { x1: width/2, x2: width/2, y1: y - high, y2: y - low },
-							rect = {
-								x: 0, y: y-Math.max(open, close),
-								width: width, height: Math.max(doFill ? open-close : close-open, 1)
-							};
-						shape = s.createGroup();
-						shape.setTransform({dx: x, dy: 0 });
-						var inner = shape.createGroup();
-						inner.createLine(line).setStroke(stroke);
-						inner.createRect(rect).setStroke(stroke).setFill(doFill?fill:"white");
-						if("mid" in v){
-							//	add the mid line.
-							inner.createLine({ x1: (stroke.width||1), x2: width-(stroke.width||1), y1: y - mid, y2: y - mid})
-								.setStroke(doFill?{color:"white"}:stroke);
-						}
-
-						//	TODO: double check this.
-						run.dyn.fill   = fill;
-						run.dyn.stroke = stroke;
-						if(events){
-							var o = {
-								element: "candlestick",
-								index:   j,
-								run:     run,
-								plot:    this,
-								hAxis:   this.hAxis || null,
-								vAxis:   this.vAxis || null,
-								shape:   inner,
-								x:       x,
-								y:       y-Math.max(open, close),
-								cx:		 width/2,
-								cy:		 (y-Math.max(open, close)) + (Math.max(doFill ? open-close : close-open, 1)/2),
-								width:	 width,
-								height:  Math.max(doFill ? open-close : close-open, 1),
-								data:	 v
-							};
-							this._connectEvents(shape, o);
-						}
-					}
-				}
-				run.dirty = false;
-			}
-			this.dirty = false;
-			return this;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.plot2d.OHLC"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.plot2d.OHLC"] = true;
-dojo.provide("dojox.charting.plot2d.OHLC");
-
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, du = dojox.lang.utils,
-		dc = dojox.charting.plot2d.common,
-		purgeGroup = df.lambda("item.purgeGroup()");
-
-	//	Candlesticks are based on the Bars plot type; we expect the following passed
-	//	as values in a series: 
-	//	{ x?, open, close, high, low }
-	//	if x is not provided, the array index is used.
-	//	failing to provide the OHLC values will throw an error.
-	dojo.declare("dojox.charting.plot2d.OHLC", dojox.charting.plot2d.Base, {
-		defaultParams: {
-			hAxis: "x",		// use a horizontal axis named "x"
-			vAxis: "y",		// use a vertical axis named "y"
-			gap:	2,		// gap between columns in pixels
-			shadows: null	// draw shadows
-		},
-		optionalParams: {
-			minBarSize: 1,	// minimal bar size in pixels
-			maxBarSize: 1	// maximal bar size in pixels
-		},
-
-		constructor: function(chart, kwArgs){
-			this.opt = dojo.clone(this.defaultParams);
-			du.updateWithObject(this.opt, kwArgs);
-			du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
-			this.series = [];
-			this.hAxis = this.opt.hAxis;
-			this.vAxis = this.opt.vAxis;
-		},
-
-		collectStats: function(series){
-			//	we have to roll our own, since we need to use all four passed
-			//	values to figure out our stats, and common only assumes x and y.
-			var stats = dojo.clone(dc.defaultStats);
-			for(var i=0; i<series.length; i++){
-				var run = series[i];
-				if(!run.data.length){ continue; }
-				var old_vmin = stats.vmin, old_vmax = stats.vmax;
-				if(!("ymin" in run) || !("ymax" in run)){
-					dojo.forEach(run.data, function(val, idx){
-						var x = val.x || idx + 1;
-						stats.hmin = Math.min(stats.hmin, x);
-						stats.hmax = Math.max(stats.hmax, x);
-						stats.vmin = Math.min(stats.vmin, val.open, val.close, val.high, val.low);
-						stats.vmax = Math.max(stats.vmax, val.open, val.close, val.high, val.low);
-					});
-				}
-				if("ymin" in run){ stats.vmin = Math.min(old_vmin, run.ymin); }
-				if("ymax" in run){ stats.vmax = Math.max(old_vmax, run.ymax); }
-			}
-			return stats;
-		},
-
-		calculateAxes: function(dim){
-			var stats = this.collectStats(this.series), t;
-			stats.hmin -= 0.5;
-			stats.hmax += 0.5;
-			this._calc(dim, stats);
-			return this;
-		},
-
-		render: function(dim, offsets){
-			this.dirty = this.isDirty();
-			if(this.dirty){
-				dojo.forEach(this.series, purgeGroup);
-				this.cleanGroup();
-				var s = this.group;
-				df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
-			}
-			var t = this.chart.theme, color, stroke, fill, f, gap, width,
-				ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
-				vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
-				baseline = Math.max(0, this._vScaler.bounds.lower),
-				baselineHeight = vt(baseline),
-				events = this.events();
-			f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt);
-			gap = f.gap;
-			width = f.size;
-			this.resetEvents();
-			for(var i = this.series.length - 1; i >= 0; --i){
-				var run = this.series[i];
-				if(!this.dirty && !run.dirty){ continue; }
-				run.cleanGroup();
-				var s = run.group;
-				if(!run.fill || !run.stroke){
-					// need autogenerated color
-					color = run.dyn.color = new dojo.Color(t.next("color"));
-				}
-				//	note that fill does not get used with this
-				stroke = run.stroke ? run.stroke : dc.augmentStroke(t.series.stroke, color);
-				fill = run.fill ? run.fill : dc.augmentFill(t.series.fill, color);
-
-				for(var j = 0; j < run.data.length; ++j){
-					var v = run.data[j];
-
-					//	calculate the points we need for OHLC
-					var x = ht(v.x || (j+0.5)) + offsets.l + gap,
-						y = dim.height - offsets.b,
-						open = vt(v.open),
-						close = vt(v.close),
-						high = vt(v.high),
-						low = vt(v.low);
-					if(low > high){
-						var tmp = high;
-						high = low;
-						low = tmp;
-					}
-
-					if(width >= 1){
-						var hl = { x1: width/2, x2: width/2, y1: y - high, y2: y - low },
-							op = { x1: 0, x2: ((width/2) + ((stroke.width||1)/2)), y1: y-open, y2: y-open},
-							cl = { x1: ((width/2) - ((stroke.width||1)/2)), x2: width, y1: y-close, y2: y-close };
-						shape = s.createGroup();
-						shape.setTransform({dx: x, dy: 0 });
-						var inner = shape.createGroup();
-						inner.createLine(hl).setStroke(stroke);
-						inner.createLine(op).setStroke(stroke);
-						inner.createLine(cl).setStroke(stroke);
-
-						//	TODO: double check this.
-						run.dyn.fill   = fill;
-						run.dyn.stroke = stroke;
-						if(events){
-							var o = {
-								element: "candlestick",
-								index:   j,
-								run:     run,
-								plot:    this,
-								hAxis:   this.hAxis || null,
-								vAxis:   this.vAxis || null,
-								shape:	 inner,
-								x:       x,
-								y:       y-Math.max(open, close),
-								cx:		 width/2,
-								cy:		 (y-Math.max(open, close)) + (Math.max(open > close ? open-close : close-open, 1)/2),
-								width:	 width,
-								height:  Math.max(open > close ? open-close : close-open, 1),
-								data:	 v
-							};
-							this._connectEvents(shape, o);
-						}
-					}
-				}
-				run.dirty = false;
-			}
-			this.dirty = false;
-			return this;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.Chart2D"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.Chart2D"] = true;
-dojo.provide("dojox.charting.Chart2D");
-
-
-
-
-
-
-
-
-
-// require all axes to support references by name
-
-
-// require all plots to support references by name
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-(function(){
-	var df = dojox.lang.functional, dc = dojox.charting,
-		clear = df.lambda("item.clear()"),
-		purge = df.lambda("item.purgeGroup()"),
-		destroy = df.lambda("item.destroy()"),
-		makeClean = df.lambda("item.dirty = false"),
-		makeDirty = df.lambda("item.dirty = true");
-
-	dojo.declare("dojox.charting.Chart2D", null, {
-		constructor: function(node, kwArgs){
-			// initialize parameters
-			if(!kwArgs){ kwArgs = {}; }
-			this.margins = kwArgs.margins ? kwArgs.margins : {l: 10, t: 10, r: 10, b: 10};
-			this.stroke  = kwArgs.stroke;
-			this.fill    = kwArgs.fill;
-
-			// default initialization
-			this.theme = null;
-			this.axes = {};		// map of axes
-			this.stack = [];	// stack of plotters
-			this.plots = {};	// map of plotter indices
-			this.series = [];	// stack of data runs
-			this.runs = {};		// map of data run indices
-			this.dirty = true;
-			this.coords = null;
-
-			// create a surface
-			this.node = dojo.byId(node);
-			var box = dojo.marginBox(node);
-			this.surface = dojox.gfx.createSurface(this.node, box.w, box.h);
-		},
-		destroy: function(){
-			dojo.forEach(this.series, destroy);
-			dojo.forEach(this.stack,  destroy);
-			df.forIn(this.axes, destroy);
-			this.surface.destroy();
-		},
-		getCoords: function(){
-			if(!this.coords){
-				this.coords = dojo.coords(this.node, true);
-			}
-			return this.coords;
-		},
-		setTheme: function(theme){
-			this.theme = theme._clone();
-			this.dirty = true;
-			return this;
-		},
-		addAxis: function(name, kwArgs){
-			var axis;
-			if(!kwArgs || !("type" in kwArgs)){
-				axis = new dc.axis2d.Default(this, kwArgs);
-			}else{
-				axis = typeof kwArgs.type == "string" ?
-					new dc.axis2d[kwArgs.type](this, kwArgs) :
-					new kwArgs.type(this, kwArgs);
-			}
-			axis.name = name;
-			axis.dirty = true;
-			if(name in this.axes){
-				this.axes[name].destroy();
-			}
-			this.axes[name] = axis;
-			this.dirty = true;
-			return this;
-		},
-		getAxis: function(name){
-			return this.axes[name];
-		},
-		removeAxis: function(name){
-			if(name in this.axes){
-				// destroy the axis
-				this.axes[name].destroy();
-				delete this.axes[name];
-				// mark the chart as dirty
-				this.dirty = true;
-			}
-			return this;	// self
-		},
-		addPlot: function(name, kwArgs){
-			var plot;
-			if(!kwArgs || !("type" in kwArgs)){
-				plot = new dc.plot2d.Default(this, kwArgs);
-			}else{
-				plot = typeof kwArgs.type == "string" ?
-					new dc.plot2d[kwArgs.type](this, kwArgs) :
-					new kwArgs.type(this, kwArgs);
-			}
-			plot.name = name;
-			plot.dirty = true;
-			if(name in this.plots){
-				this.stack[this.plots[name]].destroy();
-				this.stack[this.plots[name]] = plot;
-			}else{
-				this.plots[name] = this.stack.length;
-				this.stack.push(plot);
-			}
-			this.dirty = true;
-			return this;
-		},
-		removePlot: function(name){
-			if(name in this.plots){
-				// get the index and remove the name
-				var index = this.plots[name];
-				delete this.plots[name];
-				// destroy the plot
-				this.stack[index].destroy();
-				// remove the plot from the stack
-				this.stack.splice(index, 1);
-				// update indices to reflect the shift
-				df.forIn(this.plots, function(idx, name, plots){
-					if(idx > index){
-						plots[name] = idx - 1;
-					}
-				});
-				// mark the chart as dirty
-				this.dirty = true;
-			}
-			return this;	// self
-		},
-		addSeries: function(name, data, kwArgs){
-			var run = new dc.Series(this, data, kwArgs);
-			if(name in this.runs){
-				this.series[this.runs[name]].destroy();
-				this.series[this.runs[name]] = run;
-			}else{
-				this.runs[name] = this.series.length;
-				this.series.push(run);
-			}
-			run.name = name;
-			this.dirty = true;
-			// fix min/max
-			if(!("ymin" in run) && "min" in run){ run.ymin = run.min; }
-			if(!("ymax" in run) && "max" in run){ run.ymax = run.max; }
-			return this;
-		},
-		removeSeries: function(name){
-			if(name in this.runs){
-				// get the index and remove the name
-				var index = this.runs[name],
-					plotName = this.series[index].plot;
-				delete this.runs[name];
-				// destroy the run
-				this.series[index].destroy();
-				// remove the run from the stack of series
-				this.series.splice(index, 1);
-				// update indices to reflect the shift
-				df.forIn(this.runs, function(idx, name, runs){
-					if(idx > index){
-						runs[name] = idx - 1;
-					}
-				});
-				this.dirty = true;
-			}
-			return this;	// self
-		},
-		updateSeries: function(name, data){
-			if(name in this.runs){
-				var run = this.series[this.runs[name]];
-				run.data = data;
-				run.dirty = true;
-				this._invalidateDependentPlots(run.plot, false);
-				this._invalidateDependentPlots(run.plot, true);
-			}
-			return this;
-		},
-		resize: function(width, height){
-			var box;
-			switch(arguments.length){
-				case 0:
-					box = dojo.marginBox(this.node);
-					break;
-				case 1:
-					box = width;
-					break;
-				default:
-					box = { w: width, h: height };
-					break;
-			}
-			dojo.marginBox(this.node, box);
-			this.surface.setDimensions(box.w, box.h);
-			this.dirty = true;
-			this.coords = null;
-			return this.render();
-		},
-		getGeometry: function(){
-			var ret = {};
-			df.forIn(this.axes, function(axis){
-				if(axis.initialized()){
-					ret[axis.name] = {
-						name:		axis.name,
-						vertical:	axis.vertical,
-						scaler:		axis.scaler,
-						ticks:		axis.ticks
-					};
-				}
-			});
-			return ret;
-		},
-		setAxisWindow: function(name, scale, offset){
-			var axis = this.axes[name];
-			if(axis){
-				axis.setWindow(scale, offset);
-			}
-			return this;
-		},
-		setWindow: function(sx, sy, dx, dy){
-			if(!("plotArea" in this)){
-				this.calculateGeometry();
-			}
-			df.forIn(this.axes, function(axis){
-				var scale, offset, bounds = axis.getScaler().bounds,
-					s = bounds.span / (bounds.upper - bounds.lower);
-				if(axis.vertical){
-					scale  = sy;
-					offset = dy / s / scale;
-				}else{
-					scale  = sx;
-					offset = dx / s / scale;
-				}
-				axis.setWindow(scale, offset);
-			});
-			return this;
-		},
-		calculateGeometry: function(){
-			if(this.dirty){
-				return this.fullGeometry();
-			}
-
-			// calculate geometry
-			dojo.forEach(this.stack, function(plot){
-				if(	plot.dirty ||
-					(plot.hAxis && this.axes[plot.hAxis].dirty) ||
-					(plot.vAxis && this.axes[plot.vAxis].dirty)
-				){
-					plot.calculateAxes(this.plotArea);
-				}
-			}, this);
-
-			return this;
-		},
-		fullGeometry: function(){
-			this._makeDirty();
-
-			// clear old values
-			dojo.forEach(this.stack, clear);
-
-			// rebuild new connections, and add defaults
-
-			// set up a theme
-			if(!this.theme){
-				this.setTheme(new dojox.charting.Theme(dojox.charting._def));
-			}
-
-			// assign series
-			dojo.forEach(this.series, function(run){
-				if(!(run.plot in this.plots)){
-					var plot = new dc.plot2d.Default(this, {});
-					plot.name = run.plot;
-					this.plots[run.plot] = this.stack.length;
-					this.stack.push(plot);
-				}
-				this.stack[this.plots[run.plot]].addSeries(run);
-			}, this);
-			// assign axes
-			dojo.forEach(this.stack, function(plot){
-				if(plot.hAxis){
-					plot.setAxis(this.axes[plot.hAxis]);
-				}
-				if(plot.vAxis){
-					plot.setAxis(this.axes[plot.vAxis]);
-				}
-			}, this);
-
-			// calculate geometry
-
-			// 1st pass
-			var dim = this.dim = this.surface.getDimensions();
-			dim.width  = dojox.gfx.normalizedLength(dim.width);
-			dim.height = dojox.gfx.normalizedLength(dim.height);
-			df.forIn(this.axes, clear);
-			dojo.forEach(this.stack, function(p){ p.calculateAxes(dim); });
-
-			// assumption: we don't have stacked axes yet
-			var offsets = this.offsets = { l: 0, r: 0, t: 0, b: 0 };
-			df.forIn(this.axes, function(axis){
-				df.forIn(axis.getOffsets(), function(o, i){ offsets[i] += o; });
-			});
-			// add margins
-			df.forIn(this.margins, function(o, i){ offsets[i] += o; });
-
-			// 2nd pass with realistic dimensions
-			this.plotArea = {
-				width: dim.width - offsets.l - offsets.r,
-				height: dim.height - offsets.t - offsets.b
-			};
-			df.forIn(this.axes, clear);
-			dojo.forEach(this.stack, function(plot){ plot.calculateAxes(this.plotArea); }, this);
-
-			return this;
-		},
-		render: function(){
-			if(this.theme){
-				this.theme.clear();
-			}
-
-			if(this.dirty){
-				return this.fullRender();
-			}
-
-			this.calculateGeometry();
-
-			// go over the stack backwards
-			df.forEachRev(this.stack, function(plot){ plot.render(this.dim, this.offsets); }, this);
-
-			// go over axes
-			df.forIn(this.axes, function(axis){ axis.render(this.dim, this.offsets); }, this);
-
-			this._makeClean();
-
-			// BEGIN FOR HTML CANVAS
-			if(this.surface.render){ this.surface.render(); };
-			// END FOR HTML CANVAS
-
-			return this;
-		},
-		fullRender: function(){
-			// calculate geometry
-			this.fullGeometry();
-			var offsets = this.offsets, dim = this.dim;
-
-			// get required colors
-			var requiredColors = df.foldl(this.stack, "z + plot.getRequiredColors()", 0);
-			this.theme.defineColors({num: requiredColors, cache: false});
-
-			// clear old shapes
-			dojo.forEach(this.series, purge);
-			df.forIn(this.axes, purge);
-			dojo.forEach(this.stack,  purge);
-			this.surface.clear();
-
-			// generate shapes
-
-			// draw a plot background
-			var t = this.theme,
-				fill   = t.plotarea && t.plotarea.fill,
-				stroke = t.plotarea && t.plotarea.stroke;
-			if(fill){
-				this.surface.createRect({
-					x: offsets.l, y: offsets.t,
-					width:  dim.width  - offsets.l - offsets.r,
-					height: dim.height - offsets.t - offsets.b
-				}).setFill(fill);
-			}
-			if(stroke){
-				this.surface.createRect({
-					x: offsets.l, y: offsets.t,
-					width:  dim.width  - offsets.l - offsets.r - 1,
-					height: dim.height - offsets.t - offsets.b - 1
-				}).setStroke(stroke);
-			}
-
-			// go over the stack backwards
-			df.foldr(this.stack, function(z, plot){ return plot.render(dim, offsets), 0; }, 0);
-
-			// pseudo-clipping: matting
-			fill   = this.fill   ? this.fill   : (t.chart && t.chart.fill);
-			stroke = this.stroke ? this.stroke : (t.chart && t.chart.stroke);
-
-			//	TRT: support for "inherit" as a named value in a theme.
-			if(fill == "inherit"){
-				//	find the background color of the nearest ancestor node, and use that explicitly.
-				var node = this.node, fill = new dojo.Color(dojo.style(node, "backgroundColor"));
-				while(fill.a==0 && node!=document.documentElement){
-					fill = new dojo.Color(dojo.style(node, "backgroundColor"));
-					node = node.parentNode;
-				}
-			}
-
-			if(fill){
-				if(offsets.l){	// left
-					this.surface.createRect({
-						width:  offsets.l,
-						height: dim.height + 1
-					}).setFill(fill);
-				}
-				if(offsets.r){	// right
-					this.surface.createRect({
-						x: dim.width - offsets.r,
-						width:  offsets.r + 1,
-						height: dim.height + 1
-					}).setFill(fill);
-				}
-				if(offsets.t){	// top
-					this.surface.createRect({
-						width:  dim.width + 1,
-						height: offsets.t
-					}).setFill(fill);
-				}
-				if(offsets.b){	// bottom
-					this.surface.createRect({
-						y: dim.height - offsets.b,
-						width:  dim.width + 1,
-						height: offsets.b + 2
-					}).setFill(fill);
-				}
-			}
-			if(stroke){
-				this.surface.createRect({
-					width:  dim.width - 1,
-					height: dim.height - 1
-				}).setStroke(stroke);
-			}
-
-			// go over axes
-			df.forIn(this.axes, function(axis){ axis.render(dim, offsets); });
-
-			this._makeClean();
-
-			// BEGIN FOR HTML CANVAS
-			if(this.surface.render){ this.surface.render(); };
-			// END FOR HTML CANVAS
-
-			return this;
-		},
-		connectToPlot: function(name, object, method){
-			return name in this.plots ? this.stack[this.plots[name]].connect(object, method) : null;
-		},
-		_makeClean: function(){
-			// reset dirty flags
-			dojo.forEach(this.axes,   makeClean);
-			dojo.forEach(this.stack,  makeClean);
-			dojo.forEach(this.series, makeClean);
-			this.dirty = false;
-		},
-		_makeDirty: function(){
-			// reset dirty flags
-			dojo.forEach(this.axes,   makeDirty);
-			dojo.forEach(this.stack,  makeDirty);
-			dojo.forEach(this.series, makeDirty);
-			this.dirty = true;
-		},
-		_invalidateDependentPlots: function(plotName, /* Boolean */ verticalAxis){
-			if(plotName in this.plots){
-				var plot = this.stack[this.plots[plotName]], axis,
-					axisName = verticalAxis ? "vAxis" : "hAxis";
-				if(plot[axisName]){
-					axis = this.axes[plot[axisName]];
-					if(axis && axis.dependOnData()){
-						axis.dirty = true;
-						// find all plots and mark them dirty
-						dojo.forEach(this.stack, function(p){
-							if(p[axisName] && p[axisName] == plot[axisName]){
-								p.dirty = true;
-							}
-						});
-					}
-				}else{
-					plot.dirty = true;
-				}
-			}
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojo.fx.easing"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.fx.easing"] = true;
-dojo.provide("dojo.fx.easing");
-
-dojo.fx.easing = {
-	// summary: 
-	//		Collection of easing functions to use beyond the default 
-	//		`dojo._defaultEasing` function.
-	// 
-	// description:
-	//
-	//		Easing functions are used to manipulate the iteration through
-	//		an `dojo.Animation`s _Line. _Line being the properties of an Animation,
-	//		and the easing function progresses through that Line determing
-	//		how quickly (or slowly) it should go. Or more accurately: modify
-	//		the value of the _Line based on the percentage of animation completed.
-	//	
-	//		All functions follow a simple naming convention of "ease type" + "when".
-	//		If the name of the function ends in Out, the easing described appears
-	//		towards the end of the animation. "In" means during the beginning,
-	//		and InOut means both ranges of the Animation will applied, both
-	//		beginning and end. 
-	//
-	//		One does not call the easing function directly, it must be passed to 
-	//		the `easing` property of an animation.
-	//
-	//	example:
-	//	|	
-	//	|	var anim = dojo.fadeOut({
-	//	|		node: 'node',	
-	//	|		duration: 2000,
-	//	|		//	note there is no () 
-	//	|		easing: dojo.fx.easing.quadIn
-	//	|	}).play();
-	//
-	
-	linear: function(/* Decimal? */n){
-		// summary: A linear easing function
-		return n;
-	},
-
-	quadIn: function(/* Decimal? */n){
-		return Math.pow(n, 2);
-	},
-
-	quadOut: function(/* Decimal? */n){
-		return n * (n - 2) * -1;
-	},
-
-	quadInOut: function(/* Decimal? */n){
-		n = n * 2;
-		if(n < 1){ return Math.pow(n, 2) / 2; }
-		return -1 * ((--n) * (n - 2) - 1) / 2;
-	},
-
-	cubicIn: function(/* Decimal? */n){
-		return Math.pow(n, 3);
-	},
-
-	cubicOut: function(/* Decimal? */n){
-		return Math.pow(n - 1, 3) + 1;
-	},
-
-	cubicInOut: function(/* Decimal? */n){
-		n = n * 2;
-		if(n < 1){ return Math.pow(n, 3) / 2; }
-		n -= 2;
-		return (Math.pow(n, 3) + 2) / 2;
-	},
-
-	quartIn: function(/* Decimal? */n){
-		return Math.pow(n, 4);
-	},
-
-	quartOut: function(/* Decimal? */n){
-		return -1 * (Math.pow(n - 1, 4) - 1);
-	},
-
-	quartInOut: function(/* Decimal? */n){
-		n = n * 2;
-		if(n < 1){ return Math.pow(n, 4) / 2; }
-		n -= 2;
-		return -1 / 2 * (Math.pow(n, 4) - 2);
-	},
-
-	quintIn: function(/* Decimal? */n){
-		return Math.pow(n, 5);
-	},
-
-	quintOut: function(/* Decimal? */n){
-		return Math.pow(n - 1, 5) + 1;
-	},
-
-	quintInOut: function(/* Decimal? */n){
-		n = n * 2;
-		if(n < 1){ return Math.pow(n, 5) / 2; };
-		n -= 2;
-		return (Math.pow(n, 5) + 2) / 2;
-	},
-
-	sineIn: function(/* Decimal? */n){
-		return -1 * Math.cos(n * (Math.PI / 2)) + 1;
-	},
-
-	sineOut: function(/* Decimal? */n){
-		return Math.sin(n * (Math.PI / 2));
-	},
-
-	sineInOut: function(/* Decimal? */n){
-		return -1 * (Math.cos(Math.PI * n) - 1) / 2;
-	},
-
-	expoIn: function(/* Decimal? */n){
-		return (n == 0) ? 0 : Math.pow(2, 10 * (n - 1));
-	},
-
-	expoOut: function(/* Decimal? */n){
-		return (n == 1) ? 1 : (-1 * Math.pow(2, -10 * n) + 1);
-	},
-
-	expoInOut: function(/* Decimal? */n){
-		if(n == 0){ return 0; }
-		if(n == 1){ return 1; }
-		n = n * 2;
-		if(n < 1){ return Math.pow(2, 10 * (n - 1)) / 2; }
-		--n;
-		return (-1 * Math.pow(2, -10 * n) + 2) / 2;
-	},
-
-	circIn: function(/* Decimal? */n){
-		return -1 * (Math.sqrt(1 - Math.pow(n, 2)) - 1);
-	},
-
-	circOut: function(/* Decimal? */n){
-		n = n - 1;
-		return Math.sqrt(1 - Math.pow(n, 2));
-	},
-
-	circInOut: function(/* Decimal? */n){
-		n = n * 2;
-		if(n < 1){ return -1 / 2 * (Math.sqrt(1 - Math.pow(n, 2)) - 1); }
-		n -= 2;
-		return 1 / 2 * (Math.sqrt(1 - Math.pow(n, 2)) + 1);
-	},
-
-	backIn: function(/* Decimal? */n){
-		// summary: 
-		//		An easing function that starts away from the target, 
-		//		and quickly accelerates towards the end value.
-		// 
-		//		Use caution when the easing will cause values to become 
-		//		negative as some properties cannot be set to negative values.
-		var s = 1.70158;
-		return Math.pow(n, 2) * ((s + 1) * n - s);
-	},
-
-	backOut: function(/* Decimal? */n){
-		// summary: 
-		//		An easing function that pops past the range briefly, and slowly comes back. 
-		//
-		// description:
-		//		An easing function that pops past the range briefly, and slowly comes back. 
-		//
-		//		Use caution when the easing will cause values to become negative as some 
-		//		properties cannot be set to negative values.
-		
-		n = n - 1;
-		var s = 1.70158;
-		return Math.pow(n, 2) * ((s + 1) * n + s) + 1;
-	},
-
-	backInOut: function(/* Decimal? */n){
-		// summary: 
-		//		An easing function combining the effects of `backIn` and `backOut`
-		//
-		// description:
-		//		An easing function combining the effects of `backIn` and `backOut`.
-		//		Use caution when the easing will cause values to become negative 
-		//		as some properties cannot be set to negative values.
-		var s = 1.70158 * 1.525;
-		n = n * 2;
-		if(n < 1){ return (Math.pow(n, 2) * ((s + 1) * n - s)) / 2; }
-		n-=2;
-		return (Math.pow(n, 2) * ((s + 1) * n + s) + 2) / 2;
-	},
-
-	elasticIn: function(/* Decimal? */n){
-		// summary: 
-		//		An easing function the elastically snaps from the start value
-		//
-		// description:
-		//		An easing function the elastically snaps from the start value
-		//	
-		//		Use caution when the elasticity will cause values to become negative 
-		//		as some properties cannot be set to negative values.
-		if(n == 0 || n == 1){ return n; }
-		var p = .3;
-		var s = p / 4;
-		n = n - 1;
-		return -1 * Math.pow(2, 10 * n) * Math.sin((n - s) * (2 * Math.PI) / p);
-	},
-
-	elasticOut: function(/* Decimal? */n){
-		// summary: 
-		//		An easing function that elasticly snaps around the target value,
-		//		near the end of the Animation
-		//
-		// description:
-		//		An easing function that elasticly snaps around the target value,
-		//		near the end of the Animation
-		//
-		//		Use caution when the elasticity will cause values to become 
-		//		negative as some properties cannot be set to negative values.
-		if(n==0 || n == 1){ return n; }
-		var p = .3;
-		var s = p / 4;
-		return Math.pow(2, -10 * n) * Math.sin((n - s) * (2 * Math.PI) / p) + 1;
-	},
-
-	elasticInOut: function(/* Decimal? */n){
-		// summary: 
-		//		An easing function that elasticly snaps around the value, near
-		//		the beginning and end of the Animation.
-		//
-		// description:
-		//		An easing function that elasticly snaps around the value, near
-		//		the beginning and end of the Animation.
-		//
-		//		Use caution when the elasticity will cause values to become 
-		//		negative as some properties cannot be set to negative values.
-		if(n == 0) return 0;
-		n = n * 2;
-		if(n == 2) return 1;
-		var p = .3 * 1.5;
-		var s = p / 4;
-		if(n < 1){
-			n -= 1;
-			return -.5 * (Math.pow(2, 10 * n) * Math.sin((n - s) * (2 * Math.PI) / p));
-		}
-		n -= 1;
-		return .5 * (Math.pow(2, -10 * n) * Math.sin((n - s) * (2 * Math.PI) / p)) + 1;
-	},
-
-	bounceIn: function(/* Decimal? */n){
-		// summary: 
-		//		An easing function that 'bounces' near the beginning of an Animation
-		return (1 - dojo.fx.easing.bounceOut(1 - n)); // Decimal
-	},
-
-	bounceOut: function(/* Decimal? */n){
-		// summary:
-		//		An easing function that 'bounces' near the end of an Animation
-		var s = 7.5625;
-		var p = 2.75;
-		var l; 
-		if(n < (1 / p)){
-			l = s * Math.pow(n, 2);
-		}else if(n < (2 / p)){
-			n -= (1.5 / p);
-			l = s * Math.pow(n, 2) + .75;
-		}else if(n < (2.5 / p)){
-			n -= (2.25 / p);
-			l = s * Math.pow(n, 2) + .9375;
-		}else{
-			n -= (2.625 / p);
-			l = s * Math.pow(n, 2) + .984375;
-		}
-		return l;
-	},
-
-	bounceInOut: function(/* Decimal? */n){
-		// summary: 
-		//		An easing function that 'bounces' at the beginning and end of the Animation
-		if(n < 0.5){ return dojo.fx.easing.bounceIn(n * 2) / 2; }
-		return (dojo.fx.easing.bounceOut(n * 2 - 1) / 2) + 0.5; // Decimal
-	}
-};
-
-}
-
-if(!dojo._hasResource["dojox.charting.action2d.Base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.action2d.Base"] = true;
-dojo.provide("dojox.charting.action2d.Base");
-
-
-
-
-
-(function(){
-	var DEFAULT_DURATION = 400,	// ms
-		DEFAULT_EASING   = dojo.fx.easing.backOut,
-		df = dojox.lang.functional;
-
-	dojo.declare("dojox.charting.action2d.Base", null, {
-
-		overOutEvents: {onmouseover: 1, onmouseout: 1},
-
-		constructor: function(chart, plot, kwargs){
-			this.chart = chart;
-			this.plot = plot ? plot : "default";
-			this.anim = {};
-
-			// process common optional named parameters
-			if(!kwargs){ kwargs = {}; }
-			this.duration = kwargs.duration ? kwargs.duration : DEFAULT_DURATION;
-			this.easing   = kwargs.easing   ? kwargs.easing   : DEFAULT_EASING;
-		},
-
-		connect: function(){
-			this.handle = this.chart.connectToPlot(this.plot, this, "process");
-		},
-
-		disconnect: function(){
-			if(this.handle){
-				dojo.disconnect(this.handle);
-				this.handle = null;
-			}
-		},
-
-		reset: function(){
-			// nothing by default
-		},
-
-		destroy: function(){
-			if(this.handle){
-				this.disconnect();
-			}
-			df.forIn(this.anim, function(o){
-				df.forIn(o, function(anim){
-					anim.action.stop(true);
-				});
-			});
-			this.anim = {};
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.action2d.Highlight"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.action2d.Highlight"] = true;
-dojo.provide("dojox.charting.action2d.Highlight");
-
-
-
-
-(function(){
-	var DEFAULT_SATURATION  = 100,	// %
-		DEFAULT_LUMINOSITY1 = 75,	// %
-		DEFAULT_LUMINOSITY2 = 50,	// %
-
-		c = dojox.color,
-		
-		cc = function(color){
-			return function(){ return color; };
-		},
-		
-		hl = function(color){
-			var a = new c.Color(color),
-				x = a.toHsl();
-			if(x.s == 0){
-				x.l = x.l < 50 ? 100 : 0;
-			}else{
-				x.s = DEFAULT_SATURATION;
-				if(x.l < DEFAULT_LUMINOSITY2){
-					x.l = DEFAULT_LUMINOSITY1;
-				}else if(x.l > DEFAULT_LUMINOSITY1){
-					x.l = DEFAULT_LUMINOSITY2;
-				}else{
-					x.l = x.l - DEFAULT_LUMINOSITY2 > DEFAULT_LUMINOSITY1 - x.l ?
-						DEFAULT_LUMINOSITY2 : DEFAULT_LUMINOSITY1;
-				}
-			}
-			return c.fromHsl(x);
-		};
-	
-	dojo.declare("dojox.charting.action2d.Highlight", dojox.charting.action2d.Base, {
-		// the data description block for the widget parser
-		defaultParams: {
-			duration: 400,	// duration of the action in ms
-			easing:   dojo.fx.easing.backOut	// easing for the action
-		},
-		optionalParams: {
-			highlight: "red"	// name for the highlight color
-								// programmatic instantiation can use functions and color objects
-		},
-		
-		constructor: function(chart, plot, kwArgs){
-			// process optional named parameters
-			var a = kwArgs && kwArgs.highlight;
-			this.colorFun = a ? (dojo.isFunction(a) ? a : cc(a)) : hl;
-			
-			this.connect();
-		},
-		
-		process: function(o){
-			if(!o.shape || !(o.type in this.overOutEvents)){ return; }
-			
-			var runName = o.run.name, index = o.index, anim, startFill, endFill;
-	
-			if(runName in this.anim){
-				anim = this.anim[runName][index];
-			}else{
-				this.anim[runName] = {};
-			}
-			
-			if(anim){
-				anim.action.stop(true);
-			}else{
-				var color = o.shape.getFill();
-				if(!color || !(color instanceof dojo.Color)){
-					return;
-				}
-				this.anim[runName][index] = anim = {
-					start: color,
-					end:   this.colorFun(color)
-				};
-			}
-			
-			var start = anim.start, end = anim.end;
-			if(o.type == "onmouseout"){
-				// swap colors
-				var t = start;
-				start = end;
-				end = t;
-			}
-			
-			anim.action = dojox.gfx.fx.animateFill({
-				shape:    o.shape,
-				duration: this.duration,
-				easing:   this.easing,
-				color:    {start: start, end: end}
-			});
-			if(o.type == "onmouseout"){
-				dojo.connect(anim.action, "onEnd", this, function(){
-					if(this.anim[runName]){
-						delete this.anim[runName][index];
-					}
-				});
-			}
-			anim.action.play();
-		}
-	});
-})();
-
-}
-
-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:
-	//		A simple `dojo.Animation` toggler API.
-	//
-	// description:
-	//		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. All available members are mixed into 
-	//		these animations from the constructor (for example, `node`, 
-	//		`showDuration`, `hideDuration`). 
-	//
-	// example:
-	//	|	var t = new dojo.fx.Toggler({
-	//	|		node: "nodeId",
-	//	|		showDuration: 500,
-	//	|		// hideDuration will default to "200"
-	//	|		showFunc: dojo.fx.wipeIn, 
-	//	|		// hideFunc will default to "fadeOut"
-	//	|	});
-	//	|	t.show(100); // delay showing for 100ms
-	//	|	// ...time passes...
-	//	|	t.hide();
-
-	// node: DomNode
-	//		the node to target for the showing and hiding animations
-	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,
-
-	// 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.
-	// FIXME: also would be nice to specify individual showArgs/hideArgs mixed into
-	// each animation individually. 
-	// FIXME: also would be nice to have events from the animations exposed/bridged
-
-	/*=====
-	_showArgs: null,
-	_showAnim: null,
-
-	_hideArgs: null,
-	_hideAnim: null,
-
-	_isShowing: false,
-	_isHiding: false,
-	=====*/
-
-	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));
-	},
-
-	show: function(delay){
-		// summary: Toggle the node to showing
-		// delay: Integer?
-		//		Ammount of time to stall playing the show animation
-		return this.showAnim.play(delay || 0);
-	},
-
-	hide: function(delay){
-		// summary: Toggle the node to hidden
-		// delay: Integer?
-		//		Ammount of time to stall playing the hide animation
-		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");
- // FIXME: remove this back-compat require in 2.0 
-/*=====
-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
-		//
-		// description:
-		//		Return a `dojo.Animation` which will play all passed
-		//		`dojo.Animation` instances in sequence, firing its own
-		//		synthesized events simulating a single animation. (eg:
-		//		onEnd of this animation means the end of the chain, 
-		//		not the individual animations within)
-		//
-		// example:
-		//	Once `node` is faded out, fade in `otherNode`
-		//	|	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", "onEnd"], 
-			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 a list 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:
-		//	Fade out `node` while fading in `otherNode` simultaneously
-		//	|	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:
-		//		Expand a node to it's natural height.
-		//
-		// description:
-		//		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: Object
-		//		A hash-map of standard `dojo.Animation` constructor properties
-		//		(such as easing: node: duration: and so on)
-		//
-		// example:
-		//	|	dojo.fx.wipeIn({
-		//	|		node:"someId"
-		//	|	}).play()
-		var node = args.node = d.byId(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:
-		//		Shrink a node to nothing and hide it. 
-		//
-		// description:
-		//		Returns an animation that will shrink node defined in "args"
-		//		from it's current height to 1px, and then hide it.
-		//
-		// args: Object
-		//		A hash-map of standard `dojo.Animation` constructor properties
-		//		(such as easing: node: duration: and so on)
-		// 
-		// example:
-		//	|	dojo.fx.wipeOut({ node:"someId" }).play()
-		
-		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:
-		//		Slide a node to a new top/left position
-		//
-		// description:
-		//		Returns an animation that will slide "node" 
-		//		defined in args Object from its current position to
-		//		the position defined by (args.left, args.top).
-		//
-		// args: Object
-		//		A hash-map of standard `dojo.Animation` constructor properties
-		//		(such as easing: node: duration: and so on). Special args members
-		//		are `top` and `left`, which indicate the new position to slide to.
-		//
-		// example:
-		//	|	dojo.fx.slideTo({ node: node, left:"40", top:"50", units:"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.position(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["dojox.charting.action2d.Magnify"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.action2d.Magnify"] = true;
-dojo.provide("dojox.charting.action2d.Magnify");
-
-
-
-
-
-(function(){
-	var DEFAULT_SCALE = 2,
-		m = dojox.gfx.matrix,
-		gf = dojox.gfx.fx;
-	
-	dojo.declare("dojox.charting.action2d.Magnify", dojox.charting.action2d.Base, {
-		// the data description block for the widget parser
-		defaultParams: {
-			duration: 400,	// duration of the action in ms
-			easing:   dojo.fx.easing.backOut,	// easing for the action
-			scale:    DEFAULT_SCALE	// scale of magnification
-		},
-		optionalParams: {},	// no optional parameters
-		
-		constructor: function(chart, plot, kwArgs){
-			// process optional named parameters
-			this.scale = kwArgs && typeof kwArgs.scale == "number" ? kwArgs.scale : DEFAULT_SCALE;
-			
-			this.connect();
-		},
-		
-		process: function(o){
-			if(!o.shape || !(o.type in this.overOutEvents) || 
-				!("cx" in o) || !("cy" in o)){ return; }
-			
-			var runName = o.run.name, index = o.index, vector = [], anim, init, scale;
-	
-			if(runName in this.anim){
-				anim = this.anim[runName][index];
-			}else{
-				this.anim[runName] = {};
-			}
-			
-			if(anim){
-				anim.action.stop(true);
-			}else{
-				this.anim[runName][index] = anim = {};
-			}
-			
-			if(o.type == "onmouseover"){
-				init  = m.identity;
-				scale = this.scale;
-			}else{
-				init  = m.scaleAt(this.scale, o.cx, o.cy);
-				scale = 1 / this.scale;
-			}
-			
-			var kwArgs = {
-				shape:    o.shape,
-				duration: this.duration,
-				easing:   this.easing,
-				transform: [
-					{name: "scaleAt", start: [1, o.cx, o.cy], end: [scale, o.cx, o.cy]},
-					init
-				]
-			};
-			if(o.shape){
-				vector.push(gf.animateTransform(kwArgs));
-			}
-			if(o.oultine){
-				kwArgs.shape = o.outline;
-				vector.push(gf.animateTransform(kwArgs));
-			}
-			if(o.shadow){
-				kwArgs.shape = o.shadow;
-				vector.push(gf.animateTransform(kwArgs));
-			}
-			
-			if(!vector.length){
-				delete this.anim[runName][index];
-				return;
-			}
-			
-			anim.action = dojo.fx.combine(vector);
-			if(o.type == "onmouseout"){
-				dojo.connect(anim.action, "onEnd", this, function(){
-					if(this.anim[runName]){
-						delete this.anim[runName][index];
-					}
-				});
-			}
-			anim.action.play();
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.lang.functional.scan"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.lang.functional.scan"] = true;
-dojo.provide("dojox.lang.functional.scan");
-
-
-
-// This module adds high-level functions and related constructs:
-//	- "scan" family of functions
-
-// Notes:
-//	- missing high-level functions are provided with the compatible API: 
-//		scanl, scanl1, scanr, scanr1
-
-// Defined methods:
-//	- take any valid lambda argument as the functional argument
-//	- operate on dense arrays
-//	- take a string as the array argument
-//	- take an iterator objects as the array argument (only scanl, and scanl1)
-
-(function(){
-	var d = dojo, df = dojox.lang.functional, empty = {};
-
-	d.mixin(df, {
-		// classic reduce-class functions
-		scanl: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
-			// summary: repeatedly applies a binary function to an array from left 
-			//	to right using a seed value as a starting point; returns an array
-			//	of values produced by foldl() at that point.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var t, n, i;
-			if(d.isArray(a)){
-				// array
-				t = new Array((n = a.length) + 1);
-				t[0] = z;
-				for(i = 0; i < n; z = f.call(o, z, a[i], i, a), t[++i] = z);
-			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
-				// iterator
-				t = [z];
-				for(i = 0; a.hasNext(); t.push(z = f.call(o, z, a.next(), i++, a)));
-			}else{
-				// object/dictionary
-				t = [z];
-				for(i in a){
-					if(!(i in empty)){
-						t.push(z = f.call(o, z, a[i], i, a));
-					}
-				}
-			}
-			return t;	// Array
-		},
-		scanl1: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: repeatedly applies a binary function to an array from left 
-			//	to right; returns an array of values produced by foldl1() at that 
-			//	point.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var t, n, z, first = true;
-			if(d.isArray(a)){
-				// array
-				t = new Array(n = a.length);
-				t[0] = z = a[0];
-				for(var i = 1; i < n; t[i] = z = f.call(o, z, a[i], i, a), ++i);
-			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
-				// iterator
-				if(a.hasNext()){
-					t = [z = a.next()];
-					for(var i = 1; a.hasNext(); t.push(z = f.call(o, z, a.next(), i++, a)));
-				}
-			}else{
-				// object/dictionary
-				for(var i in a){
-					if(!(i in empty)){
-						if(first){
-							t = [z = a[i]];
-							first = false;
-						}else{
-							t.push(z = f.call(o, z, a[i], i, a));
-						}
-					}
-				}
-			}
-			return t;	// Array
-		},
-		scanr: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
-			// summary: repeatedly applies a binary function to an array from right
-			//	to left using a seed value as a starting point; returns an array
-			//	of values produced by foldr() at that point.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var n = a.length, t = new Array(n + 1), i = n;
-			t[n] = z;
-			for(; i > 0; --i, z = f.call(o, z, a[i], i, a), t[i] = z);
-			return t;	// Array
-		},
-		scanr1: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
-			// summary: repeatedly applies a binary function to an array from right
-			//	to left; returns an array of values produced by foldr1() at that 
-			//	point.
-			if(typeof a == "string"){ a = a.split(""); }
-			o = o || d.global; f = df.lambda(f);
-			var n = a.length, t = new Array(n), z = a[n - 1], i = n - 1;
-			t[i] = z;
-			for(; i > 0; --i, z = f.call(o, z, a[i], i, a), t[i] = z);
-			return t;	// Array
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.action2d.MoveSlice"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.action2d.MoveSlice"] = true;
-dojo.provide("dojox.charting.action2d.MoveSlice");
-
-
-
-
-
-
-
-
-(function(){
-	var DEFAULT_SCALE = 1.05,
-		DEFAULT_SHIFT = 7,	// px
-		m = dojox.gfx.matrix,
-		gf = dojox.gfx.fx,
-		df = dojox.lang.functional;
-	
-	dojo.declare("dojox.charting.action2d.MoveSlice", dojox.charting.action2d.Base, {
-		// the data description block for the widget parser
-		defaultParams: {
-			duration: 400,	// duration of the action in ms
-			easing:   dojo.fx.easing.backOut,	// easing for the action
-			scale:    DEFAULT_SCALE,	// scale of magnification
-			shift:    DEFAULT_SHIFT		// shift of the slice
-		},
-		optionalParams: {},	// no optional parameters
-
-		constructor: function(chart, plot, kwArgs){
-			// process optional named parameters
-			if(!kwArgs){ kwArgs = {}; }
-			this.scale = typeof kwArgs.scale == "number" ? kwArgs.scale : DEFAULT_SCALE;
-			this.shift = typeof kwArgs.shift == "number" ? kwArgs.shift : DEFAULT_SHIFT;
-			
-			this.connect();
-		},
-		
-		process: function(o){
-			if(!o.shape || o.element != "slice" || !(o.type in this.overOutEvents)){ return; }
-			
-			if(!this.angles){
-				// calculate the running total of slice angles
-				if(typeof o.run.data[0] == "number"){
-					this.angles = df.map(df.scanl(o.run.data, "+", 0),
-						"* 2 * Math.PI / this", df.foldl(o.run.data, "+", 0));
-				}else{
-					this.angles = df.map(df.scanl(o.run.data, "a + b.y", 0),
-						"* 2 * Math.PI / this", df.foldl(o.run.data, "a + b.y", 0));
-				}
-			}
-
-			var index = o.index, anim, startScale, endScale, startOffset, endOffset,
-				angle = (this.angles[index] + this.angles[index + 1]) / 2,
-				rotateTo0  = m.rotateAt(-angle, o.cx, o.cy),
-				rotateBack = m.rotateAt( angle, o.cx, o.cy);
-	
-			anim = this.anim[index];
-			
-			if(anim){
-				anim.action.stop(true);
-			}else{
-				this.anim[index] = anim = {};
-			}
-			
-			if(o.type == "onmouseover"){
-				startOffset = 0;
-				endOffset   = this.shift;
-				startScale  = 1;
-				endScale    = this.scale;
-			}else{
-				startOffset = this.shift;
-				endOffset   = 0;
-				startScale  = this.scale;
-				endScale    = 1;
-			}
-			
-			anim.action = dojox.gfx.fx.animateTransform({
-				shape:    o.shape,
-				duration: this.duration,
-				easing:   this.easing,
-				transform: [
-					rotateBack,
-					{name: "translate", start: [startOffset, 0], end: [endOffset, 0]},
-					{name: "scaleAt",   start: [startScale, o.cx, o.cy],  end: [endScale, o.cx, o.cy]},
-					rotateTo0
-				]
-			});
-
-			if(o.type == "onmouseout"){
-				dojo.connect(anim.action, "onEnd", this, function(){
-					delete this.anim[index];
-				});
-			}
-			anim.action.play();
-		},
-		
-		reset: function(){
-			delete this.angles;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.action2d.Shake"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.action2d.Shake"] = true;
-dojo.provide("dojox.charting.action2d.Shake");
-
-
-
-
-
-(function(){
-	var DEFAULT_SHIFT = 3,
-		m = dojox.gfx.matrix,
-		gf = dojox.gfx.fx;
-	
-	dojo.declare("dojox.charting.action2d.Shake", dojox.charting.action2d.Base, {
-		// the data description block for the widget parser
-		defaultParams: {
-			duration: 400,	// duration of the action in ms
-			easing:   dojo.fx.easing.backOut,	// easing for the action
-			shiftX:   DEFAULT_SHIFT,	// shift of the element along the X axis
-			shiftY:   DEFAULT_SHIFT		// shift of the element along the Y axis
-		},
-		optionalParams: {},	// no optional parameters
-
-		constructor: function(chart, plot, kwArgs){
-			// process optional named parameters
-			if(!kwArgs){ kwArgs = {}; }
-			this.shiftX = typeof kwArgs.shiftX == "number" ? kwArgs.shiftX : DEFAULT_SHIFT;
-			this.shiftY = typeof kwArgs.shiftY == "number" ? kwArgs.shiftY : DEFAULT_SHIFT;
-			
-			this.connect();
-		},
-		
-		process: function(o){
-			if(!o.shape || !(o.type in this.overOutEvents)){ return; }
-			
-			var runName = o.run.name, index = o.index, vector = [], anim, 
-				shiftX = o.type == "onmouseover" ? this.shiftX : -this.shiftX,
-				shiftY = o.type == "onmouseover" ? this.shiftY : -this.shiftY;
-	
-			if(runName in this.anim){
-				anim = this.anim[runName][index];
-			}else{
-				this.anim[runName] = {};
-			}
-			
-			if(anim){
-				anim.action.stop(true);
-			}else{
-				this.anim[runName][index] = anim = {};
-			}
-			
-			var kwArgs = {
-				shape:     o.shape,
-				duration:  this.duration,
-				easing:    this.easing,
-				transform: [
-					{name: "translate", start: [this.shiftX, this.shiftY], end: [0, 0]},
-					m.identity
-				]
-			};
-			if(o.shape){
-				vector.push(gf.animateTransform(kwArgs));
-			}
-			if(o.oultine){
-				kwArgs.shape = o.outline;
-				vector.push(gf.animateTransform(kwArgs));
-			}
-			if(o.shadow){
-				kwArgs.shape = o.shadow;
-				vector.push(gf.animateTransform(kwArgs));
-			}
-			
-			if(!vector.length){
-				delete this.anim[runName][index];
-				return;
-			}
-			
-			anim.action = dojo.fx.combine(vector);
-			if(o.type == "onmouseout"){
-				dojo.connect(anim.action, "onEnd", this, function(){
-					if(this.anim[runName]){
-						delete this.anim[runName][index];
-					}
-				});
-			}
-			anim.action.play();
-		}
-	});
-})();
-
-}
-
-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),
-		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); //TODO: UTC defaults
-		if(match[0] < 100){
-			result.setFullYear(match[0] || 1970);
-		}
-
-		var offset = 0,
-			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 = [],
-		getter = options.zulu ? "getUTC" : "get",
-		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;
-	this._attrName = d._scopeName + "Type";
-	this._query = "[" + this._attrName + "]";
-
-	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){
-						// The user has specified some text for a function like "return x+5"
-						return new Function(value);
-					}else{
-						// The user has specified the name of a function like "myOnClick"
-						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"} }
-	};
-
-	// Widgets like BorderContainer add properties to _Widget via dojo.extend().
-	// If BorderContainer is loaded after _Widget's parameter list has been cached,
-	// we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
-	dojo.connect(dojo, "extend", function(){
-		instanceClasses = {};
-	});
-
-	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, /* Object? */args){
-		// 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.
-		// args: Object?
-		//		An object used to hold kwArgs for instantiation.
-		//		Only supports 'noStart' currently.
-		var thelist = [], dp = dojo.parser;
-		mixin = mixin||{};
-		args = args||{};
-		
-		d.forEach(nodes, function(node){
-			if(!node){ return; }
-			var type = dp._attrName in mixin?mixin[dp._attrName]:node.getAttribute(dp._attrName);
-			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 || clazz.prototype && 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
-		if(!mixin._started){
-			d.forEach(thelist, function(instance){
-				if(	!args.noStart && instance  && 
-					instance.startup &&
-					!instance._started && 
-					(!instance.getParent || !instance.getParent())
-				){
-					instance.startup();
-				}
-			});
-		}
-		return thelist;
-	};
-
-	this.parse = function(/*DomNode?*/ rootNode, /* Object? */ args){
-		// summary:
-		//		Scan the DOM for class instances, and instantiate them.
-		//
-		// description:
-		//		Search specified node (or root node) recursively for class instances,
-		//		and instantiate them Searches for
-		//		dojoType="qualified.class.name"
-		//
-		// rootNode: DomNode?
-		//		A default starting root node from which to start the parsing. Can be
-		//		omitted, defaulting to the entire document. If omitted, the `args`
-		//		object can be passed in this place. If the `args` object has a 
-		//		`rootNode` member, that is used.
-		//
-		// args:
-		//		a kwArgs object passed along to instantiate()
-		//		
-		//			* noStart: Boolean?
-		//				when set will prevent the parser from calling .startup()
-		//				when locating the nodes. 
-		//			* rootNode: DomNode?
-		//				identical to the function's `rootNode` argument, though
-		//				allowed to be passed in via this `args object. 
-		//
-		// example:
-		//		Parse all widgets on a page:
-		//	|		dojo.parser.parse();
-		//
-		// example:
-		//		Parse all classes within the node with id="foo"
-		//	|		dojo.parser.parse(dojo.byId(foo));
-		//
-		// example:
-		//		Parse all classes in a page, but do not call .startup() on any 
-		//		child
-		//	|		dojo.parser.parse({ noStart: true })
-		//
-		// example:
-		//		Parse all classes in a node, but do not call .startup()
-		//	|		dojo.parser.parse(someNode, { noStart:true });
-		//	|		// or
-		// 	|		dojo.parser.parse({ noStart:true, rootNode: someNode });
-
-		// determine the root node based on the passed arguments.
-		var root;
-		if(!args && rootNode && rootNode.rootNode){
-			args = rootNode;
-			root = args.rootNode;
-		}else{
-			root = rootNode;
-		}
-
-		var	list = d.query(this._query, root);
-			// go build the object instances
-		return this.instantiate(list, null, args); // Array
-
-	};
-}();
-
-//Register the parser callback. It should be the first callback
-//after the a11y test.
-
-(function(){
-	var parseRunner = function(){ 
-		if(dojo.config.parseOnLoad){
-			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.cache"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.cache"] = true;
-dojo.provide("dojo.cache");
-
-/*=====
-dojo.cache = { 
-	// summary:
-	// 		A way to cache string content that is fetchable via `dojo.moduleUrl`.
-};
-=====*/
-
-(function(){
-	var cache = {};
-	dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
-		// summary:
-		// 		A getter and setter for storing the string content associated with the
-		// 		module and url arguments.
-		// description:
-		// 		module and url are used to call `dojo.moduleUrl()` to generate a module URL.
-		// 		If value is specified, the cache value for the moduleUrl will be set to
-		// 		that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
-		// 		in its internal cache and return that cached value for the URL. To clear
-		// 		a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
-		// 		the URL contents, only modules on the same domain of the page can use this capability.
-		// 		The build system can inline the cache values though, to allow for xdomain hosting.
-		// module: String||Object
-		// 		If a String, the module name to use for the base part of the URL, similar to module argument
-		// 		to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
-		// 		generates a valid path for the cache item. For example, a dojo._Url object.
-		// url: String
-		// 		The rest of the path to append to the path derived from the module argument. If
-		// 		module is an object, then this second argument should be the "value" argument instead.
-		// value: String||Object?
-		// 		If a String, the value to use in the cache for the module/url combination.
-		// 		If an Object, it can have two properties: value and sanitize. The value property
-		// 		should be the value to use in the cache, and sanitize can be set to true or false,
-		// 		to indicate if XML declarations should be removed from the value and if the HTML
-		// 		inside a body tag in the value should be extracted as the real value. The value argument
-		// 		or the value property on the value argument are usually only used by the build system
-		// 		as it inlines cache content.
-		//	example:
-		//		To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
-		// 		of call is used to avoid an issue with the build system erroneously trying to intern
-		// 		this example. To get the build system to intern your dojo.cache calls, use the
-		// 		"dojo.cache" style of call):
-		// 		|	//If template.html contains "<h1>Hello</h1>" that will be
-		// 		|	//the value for the text variable.
-		//		|	var text = dojo["cache"]("my.module", "template.html");
-		//	example:
-		//		To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
-		// 		 (the dojo["cache"] style of call is used to avoid an issue with the build system 
-		// 		erroneously trying to intern this example. To get the build system to intern your
-		// 		dojo.cache calls, use the "dojo.cache" style of call):
-		// 		|	//If template.html contains "<html><body><h1>Hello</h1></body></html>", the
-		// 		|	//text variable will contain just "<h1>Hello</h1>".
-		//		|	var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
-		//	example:
-		//		Same example as previous, but demostrates how an object can be passed in as
-		//		the first argument, then the value argument can then be the second argument.
-		// 		|	//If template.html contains "<html><body><h1>Hello</h1></body></html>", the
-		// 		|	//text variable will contain just "<h1>Hello</h1>".
-		//		|	var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
-
-		//Module could be a string, or an object that has a toString() method
-		//that will return a useful path. If it is an object, then the "url" argument
-		//will actually be the value argument.
-		if(typeof module == "string"){
-			var pathObj = dojo.moduleUrl(module, url);
-		}else{
-			pathObj = module;
-			value = url;
-		}
-		var key = pathObj.toString();
-
-		var val = value;
-		if(value !== undefined && !dojo.isString(value)){
-			val = ("value" in value ? value.value : undefined);
-		}
-
-		var sanitize = value && value.sanitize ? true : false;
-
-		if(val || val === null){
-			//We have a value, either clear or set the cache value.
-			if(val == null){
-				delete cache[key];
-			}else{
-				val = cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
-			}
-		}else{
-			//Allow cache values to be empty strings. If key property does
-			//not exist, fetch it.
-			if(!(key in cache)){
-				val = dojo._getText(key);
-				cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
-			}
-			val = cache[key];
-		}
-		return val; //String
-	};
-
-	dojo.cache._sanitize = function(/*String*/val){
-		// 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.
-		// description:
-		// 		Copied from dijit._Templated._sanitizeTemplateString.
-		if(val){
-			val = val.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
-			var matches = val.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
-			if(matches){
-				val = matches[1];
-			}
-		}else{
-			val = "";
-		}
-		return val; //String
-	};
-})();
-
-}
-
-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.
-		//
-		//		Use in conjunction with dojo.cache() to load from a file.
-		templateString: null,
-
-		// templatePath: [protected deprecated] String
-		//		Path to template (HTML file) for this widget relative to dojo.baseUrl.
-		//		Deprecated: use templateString with dojo.cache() instead.
-		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,
-
-		// _earlyTemplatedStartup: Boolean
-		//		A fallback to preserve the 1.0 - 1.3 behavior of children in
-		//		templates having their startup called before the parent widget
-		//		fires postCreate. Defaults to 'false', causing child widgets to
-		//		have their .startup() called immediately before a parent widget
-		//		.startup(), but always after the parent .postCreate(). Set to
-		//		'true' to re-enable to previous, arguably broken, behavior.
-		_earlyTemplatedStartup: false,
-
-		// _attachPoints: [private] String[]
-		//		List of widget attribute names associated with dojoAttachPoint=... in the
-		//		template, ex: ["containerNode", "labelNode"]
-/*=====
- 		_attachPoints: [],
- =====*/
-
-		constructor: function(){
-			this._attachPoints = [];
-		},
-
-		_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,"""); //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));
-				if(node.nodeType != 1){
-					// Flag common problems such as templates with multiple top level nodes (nodeType == 11)
-					throw new Error("Invalid template: " + 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){
-				// Make sure dojoType is used for parsing widgets in template.
-				// The dojo.parser.query could be changed from multiversion support.
-				var parser = dojo.parser, qry, attr;
-				if(parser._query != "[dojoType]"){
-					qry = parser._query;
-					attr = parser._attrName;
-					parser._query = "[dojoType]";
-					parser._attrName = "dojoType";
-				}
-
-				// Store widgets that we need to start at a later point in time
-				var cw = (this._startupWidgets = dojo.parser.parse(node, {
-					noStart: !this._earlyTemplatedStartup
-				}));
-
-				// Restore the query.
-				if(qry){
-					parser._query = qry;
-					parser._attrName = attr;
-				}
-
-				this._supportingWidgets = dijit.findWidgets(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;
-						}
-						this._attachPoints.push(point);
-					}
-				}
-
-				// 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]);
-						}
-					});
-				}
-			}
-		},
-
-		startup: function(){
-			dojo.forEach(this._startupWidgets, function(w){
-				if(w && !w._started && w.startup){
-					w.startup();
-				}
-			});
-			this.inherited(arguments);
-		},
-
-		destroyRendering: function(){
-			// Delete all attach points to prevent IE6 memory leaks.
-			dojo.forEach(this._attachPoints, function(point){
-				delete this[point];
-			}, this);
-			this._attachPoints = [];
-
-			this.inherited(arguments);
-		}
-	}
-);
-
-// 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||dojo.uri.Uri
-	//		The URL to get the template from.
-	// 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){
-		try{
-			// if the cached value is an innerHTML string (no ownerDocument) or a DOM tree created within the current document, then use the current cached value
-			if(!cached.ownerDocument || cached.ownerDocument == dojo.doc){
-				// string or node of the same document
-				return cached;
-			}
-		}catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded
-		dojo.destroy(cached);
-	}
-
-	// If necessary, load template string from template path
-	if(!templateString){
-		templateString = dojo.cache(templatePath, {sanitize: true});
-	}
-	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
-		var node = dojo._toDom(templateString);
-		if(node.nodeType != 1){
-			throw new Error("Invalid template: " + templateString);
-		}
-		return (tmplts[key] = node); //Node
-	}
-};
-
-if(dojo.isIE){
-	dojo.addOnWindowUnload(function(){
-		var cache = dijit._Templated._templateCache;
-		for(var key in cache){
-			var value = cache[key];
-			if(typeof value == "object"){ // value is either a string or a DOM node template
-				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.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: dojo.cache("dijit", "templates/Tooltip.html", "<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";
-
-			var pos = dijit.placeOnScreenAroundElement(this.domNode, aroundNode, dijit.getPopupAroundAlignment((position && position.length) ? position : dijit.Tooltip.defaultPosition, this.isLeftToRight()), 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: [],
-
-		constructor: function(){
-			// Map id's of nodes I'm connected to to a list of the this.connect() handles
-			this._nodeConnectionsById = {};
-		},
-
-		_setConnectIdAttr: function(newIds){
-			for(var oldId in this._nodeConnectionsById){
-				this.removeTarget(oldId);
-			}
-			dojo.forEach(dojo.isArrayLike(newIds) ? newIds : [newIds], this.addTarget, this);
-		},
-
-		_getConnectIdAttr: function(){
-			var ary = [];
-			for(var id in this._nodeConnectionsById){
-				ary.push(id);
-			}
-			return ary;
-		},
-
-		addTarget: function(/*DOMNODE || String*/ id){
-			// summary:
-			//		Attach tooltip to specified node, if it's not already connected
-			var node = dojo.byId(id);
-			if(!node){ return; }
-			if(node.id in this._nodeConnectionsById){ return; }//Already connected
-
-			this._nodeConnectionsById[node.id] = [
-				this.connect(node, "onmouseenter", "_onTargetMouseEnter"),
-				this.connect(node, "onmouseleave", "_onTargetMouseLeave"),
-				this.connect(node, "onfocus", "_onTargetFocus"),
-				this.connect(node, "onblur", "_onTargetBlur")
-			];
-			if(dojo.isIE && !node.style.zoom){//preserve zoom
-				// BiDi workaround
-				node.style.zoom = 1;
-			}
-		},
-
-		removeTarget: function(/*DOMNODE || String*/ node){
-			// summary:
-			//		Detach tooltip from specified node
-
-			// map from DOMNode back to plain id string
-			var id = node.id || node;
-
-			if(id in this._nodeConnectionsById){
-				dojo.forEach(this._nodeConnectionsById[id], this.disconnect, this);
-				delete this._nodeConnectionsById[id];
-			}
-		},
-
-		postCreate: function(){
-			dojo.addClass(this.domNode,"dijitTooltipData");
-		},
-
-		startup: function(){
-			this.inherited(arguments);
-
-			// If this tooltip was created in a template, or for some other reason the specified connectId[s]
-			// didn't exist during the widget's initialization, then connect now.
-			var ids = this.connectId;
-			dojo.forEach(dojo.isArrayLike(ids) ? ids : [ids], this.addTarget, this);
-		},
-
-		_onTargetMouseEnter: function(/*Event*/ e){
-			// summary:
-			//		Handler for mouseenter event on the target node
-			// tags:
-			//		private
-			this._onHover(e);
-		},
-
-		_onTargetMouseLeave: function(/*Event*/ e){
-			// summary:
-			//		Handler for mouseleave event on the target node
-			// tags:
-			//		private
-			this._onUnHover(e);
-		},
-
-		_onTargetFocus: function(/*Event*/ e){
-			// summary:
-			//		Handler for focus event on the target node
-			// tags:
-			//		private
-
-			this._focus = true;
-			this._onHover(e);
-		},
-
-		_onTargetBlur: function(/*Event*/ e){
-			// summary:
-			//		Handler for blur event on the target node
-			// tags:
-			//		private
-
-			this._focus = false;
-			this._onUnHover(e);
-		},
-
-		_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
-
-			if(this._showTimer){
-				clearTimeout(this._showTimer);
-				delete this._showTimer;
-			}
-			dijit.showTooltip(this.label || this.domNode.innerHTML, target, this.position);
-
-			this._connectNode = target;
-			this.onShow(target, this.position);
-		},
-
-		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;
-				this.onHide();
-			}
-			if(this._showTimer){
-				// if tooltip is scheduled to be shown (after a brief delay)
-				clearTimeout(this._showTimer);
-				delete this._showTimer;
-			}
-		},
-
-		onShow: function(target, position){
-			// summary:
-			//		Called when the tooltip is shown
-			// tags:
-			//		callback
-		},
-
-		onHide: function(){
-			// summary:
-			//		Called when the tooltip is hidden
-			// tags:
-			//		callback
-		},
-
-		uninitialize: function(){
-			this.close();
-			this.inherited(arguments);
-		}
-	}
-);
-
-// 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["dojox.charting.action2d.Tooltip"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.action2d.Tooltip"] = true;
-dojo.provide("dojox.charting.action2d.Tooltip");
-
-
-
-
-
-
-
-
-(function(){
-	var DEFAULT_TEXT = function(o){
-		var t = o.run && o.run.data && o.run.data[o.index];
-		if(t && typeof t != "number" && (t.tooltip || t.text)){
-			return t.tooltip || t.text;
-		}
-		if(o.element == "candlestick"){
-			return '<table cellpadding="1" cellspacing="0" border="0" style="font-size:0.9em;">'
-				+ '<tr><td>Open:</td><td align="right"><strong>' + o.data.open + '</strong></td></tr>'
-				+ '<tr><td>High:</td><td align="right"><strong>' + o.data.high + '</strong></td></tr>'
-				+ '<tr><td>Low:</td><td align="right"><strong>' + o.data.low + '</strong></td></tr>'
-				+ '<tr><td>Close:</td><td align="right"><strong>' + o.data.close + '</strong></td></tr>'
-				+ (o.data.mid !== undefined ? '<tr><td>Mid:</td><td align="right"><strong>' + o.data.mid + '</strong></td></tr>' : '')
-				+ '</table>';
-		}
-		return o.element == "bar" ? o.x : o.y;
-	};
-	
-	var df = dojox.lang.functional, pi4 = Math.PI / 4, pi2 = Math.PI / 2;
-	
-	dojo.declare("dojox.charting.action2d.Tooltip", dojox.charting.action2d.Base, {
-		// the data description block for the widget parser
-		defaultParams: {
-			text: DEFAULT_TEXT	// the function to produce a tooltip from the object
-		},
-		optionalParams: {},	// no optional parameters
-
-		constructor: function(chart, plot, kwArgs){
-			// process optional named parameters
-			this.text = kwArgs && kwArgs.text ? kwArgs.text : DEFAULT_TEXT;
-			
-			this.connect();
-		},
-		
-		process: function(o){
-			if(o.type === "onplotreset" || o.type === "onmouseout"){
-				dijit.hideTooltip(this.aroundRect);
-				this.aroundRect = null;
-				return;
-			}
-			
-			if(!o.shape || o.type !== "onmouseover"){ return; }
-			
-			// calculate relative coordinates and the position
-			var aroundRect = {type: "rect"}, position = ["after", "before"];
-			switch(o.element){
-				case "marker":
-					aroundRect.x = o.cx;
-					aroundRect.y = o.cy;
-					aroundRect.width = aroundRect.height = 1;
-					break;
-				case "circle":
-					aroundRect.x = o.cx - o.cr;
-					aroundRect.y = o.cy - o.cr;
-					aroundRect.width = aroundRect.height = 2 * o.cr;
-					break;
-				case "column":
-					position = ["above", "below"];
-					// intentional fall down
-				case "bar":
-					aroundRect = dojo.clone(o.shape.getShape());
-					break;
-				case "candlestick":
-					aroundRect.x = o.x;
-					aroundRect.y = o.y;
-					aroundRect.width = o.width;
-					aroundRect.height = o.height;
-					break;
-				default:
-				//case "slice":
-					if(!this.angles){
-						// calculate the running total of slice angles
-						if(typeof o.run.data[0] == "number"){
-							this.angles = df.map(df.scanl(o.run.data, "+", 0),
-								"* 2 * Math.PI / this", df.foldl(o.run.data, "+", 0));
-						}else{
-							this.angles = df.map(df.scanl(o.run.data, "a + b.y", 0),
-								"* 2 * Math.PI / this", df.foldl(o.run.data, "a + b.y", 0));
-						}
-					}
-					var angle = (this.angles[o.index] + this.angles[o.index + 1]) / 2;
-					aroundRect.x = o.cx + o.cr * Math.cos(angle);
-					aroundRect.y = o.cy + o.cr * Math.sin(angle);
-					aroundRect.width = aroundRect.height = 1;
-					// calculate the position
-					if(angle < pi4){
-						// do nothing: the position is right
-					}else if(angle < pi2 + pi4){
-						position = ["below", "above"];
-					}else if(angle < Math.PI + pi4){
-						position = ["before", "after"];
-					}else if(angle < 2 * Math.PI - pi4){
-						position = ["above", "below"];
-					}
-					/*
-					else{
-						// do nothing: the position is right
-					}
-					 */
-					break;
-			}
-			
-			// adjust relative coordinates to absolute, and remove fractions
-			var lt = dojo.coords(this.chart.node, true);
-			aroundRect.x += lt.x;
-			aroundRect.y += lt.y;
-			aroundRect.x = Math.round(aroundRect.x);
-			aroundRect.y = Math.round(aroundRect.y);
-			aroundRect.width = Math.ceil(aroundRect.width);
-			aroundRect.height = Math.ceil(aroundRect.height);
-			this.aroundRect = aroundRect;
-			
-			dijit.showTooltip(this.text(o), this.aroundRect, position);
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.widget.Chart2D"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.widget.Chart2D"] = true;
-dojo.provide("dojox.charting.widget.Chart2D");
-
-
-
-
-
-// require all actions to support references by name
-
-
-
-
-
-
-(function(){
-	var collectParams, collectAxisParams, collectPlotParams,
-		collectActionParams, collectDataParams,
-		notNull = function(o){ return o; },
-		df = dojox.lang.functional,
-		du = dojox.lang.utils,
-		dc = dojox.charting,
-		d = dojo;
-	
-	dojo.declare("dojox.charting.widget.Chart2D", dijit._Widget, {
-		// parameters for the markup
-		
-		// theme for the chart
-		theme: null,
-		
-		// margins for the chart: {l: 10, r: 10, t: 10, b: 10}
-		margins: null,
-		
-		// chart area
-		stroke: null,
-		fill:   null,
-		
-		// methods
-		
-		buildRendering: function(){
-			var n = this.domNode = this.srcNodeRef;
-			
-			// collect chart parameters
-			var axes    = d.query("> .axis", n).map(collectAxisParams).filter(notNull),
-				plots   = d.query("> .plot", n).map(collectPlotParams).filter(notNull),
-				actions = d.query("> .action", n).map(collectActionParams).filter(notNull),
-				series  = d.query("> .series", n).map(collectDataParams).filter(notNull);
-			
-			// build the chart
-			n.innerHTML = "";
-			var c = this.chart = new dc.Chart2D(n, {
-				margins: this.margins, 
-				stroke:  this.stroke,
-				fill:    this.fill
-			});
-			
-			// add collected parameters
-			if(this.theme){
-				c.setTheme(this.theme);
-			}
-			axes.forEach(function(axis){
-				c.addAxis(axis.name, axis.kwArgs);
-			});
-			plots.forEach(function(plot){
-				c.addPlot(plot.name, plot.kwArgs);
-			});
-			
-			this.actions = actions.map(function(action){
-				return new action.action(c, action.plot, action.kwArgs)
-			});
-			
-			var render = df.foldl(series, function(render, series){
-				if(series.type == "data"){
-					c.addSeries(series.name, series.data, series.kwArgs);
-					render = true;
-				}else{
-					c.addSeries(series.name, [0], series.kwArgs);
-					var kw = {};
-					du.updateWithPattern(
-						kw, 
-						series.kwArgs, 
-						{
-							"query": "", 
-							"queryOptions": null, 
-							"start": 0, 
-							"count": 1 //, 
-							// "sort": []
-						}, 
-						true
-					);
-					if(series.kwArgs.sort){
-						// sort is a complex object type and doesn't survive coercian
-						kw.sort = dojo.clone(series.kwArgs.sort);
-					}
-					d.mixin(kw, {
-						onComplete: function(data){
-							var values;
-							if("valueFn" in series.kwArgs){
-								var fn = series.kwArgs.valueFn;
-								values = d.map(data, function(x){
-									return fn(series.data.getValue(x, series.field, 0));
-								});
-							}else{
-								values = d.map(data, function(x){
-									return series.data.getValue(x, series.field, 0);
-								});
-							}
-							c.addSeries(series.name, values, series.kwArgs).render();
-						}
-					});
-					series.data.fetch(kw);
-				}
-				return render;
-			}, false);
-			if(render){ c.render(); }
-		},
-		destroy: function(){
-			// summary: properly destroy the widget
-			this.chart.destroy();
-			this.inherited(arguments);
-		},
-		resize: function(box){
-			// summary: resize the widget
-			if(box.w > 0 && box.h > 0){
-				dojo.marginBox(this.domNode, box);
-				this.chart.resize();
-			}
-		}
-	});
-	
-	collectParams = function(node, type, kw){
-		var dp = eval("(" + type + ".prototype.defaultParams)");
-		var x, attr;
-		for(x in dp){
-			if(x in kw){ continue; }
-			attr = node.getAttribute(x);
-			kw[x] = du.coerceType(dp[x], attr == null || typeof attr == "undefined" ? dp[x] : attr);
-		}
-		var op = eval("(" + type + ".prototype.optionalParams)");
-		for(x in op){
-			if(x in kw){ continue; }
-			attr = node.getAttribute(x);
-			if(attr != null){
-				kw[x] = du.coerceType(op[x], attr);
-			}
-		}
-	};
-	
-	collectAxisParams = function(node){
-		var name = node.getAttribute("name"), type = node.getAttribute("type");
-		if(!name){ return null; }
-		var o = {name: name, kwArgs: {}}, kw = o.kwArgs;
-		if(type){
-			if(dc.axis2d[type]){
-				type = dojox._scopeName + ".charting.axis2d." + type;
-			}
-			var axis = eval("(" + type + ")");
-			if(axis){ kw.type = axis; } 
-		}else{
-			type = dojox._scopeName + ".charting.axis2d.Default";
-		}
-		collectParams(node, type, kw);
-		return o;
-	};
-	
-	collectPlotParams = function(node){
-		// var name = d.attr(node, "name"), type = d.attr(node, "type");
-		var name = node.getAttribute("name"), type = node.getAttribute("type");
-		if(!name){ return null; }
-		var o = {name: name, kwArgs: {}}, kw = o.kwArgs;
-		if(type){
-			if(dc.plot2d[type]){
-				type = dojox._scopeName + ".charting.plot2d." + type;
-			}
-			var plot = eval("(" + type + ")");
-			if(plot){ kw.type = plot; } 
-		}else{
-			type = dojox._scopeName + ".charting.plot2d.Default";
-		}
-		collectParams(node, type, kw);
-		return o;
-	};
-	
-	collectActionParams = function(node){
-		// var plot = d.attr(node, "plot"), type = d.attr(node, "type");
-		var plot = node.getAttribute("plot"), type = node.getAttribute("type");
-		if(!plot){ plot = "default"; }
-		var o = {plot: plot, kwArgs: {}}, kw = o.kwArgs;
-		if(type){
-			if(dc.action2d[type]){
-				type = dojox._scopeName + ".charting.action2d." + type;
-			}
-			var action = eval("(" + type + ")");
-			if(!action){ return null; }
-			o.action = action;
-		}else{
-			return null;
-		}
-		collectParams(node, type, kw);
-		return o;
-	};
-
-	collectDataParams = function(node){
-		var ga = d.partial(d.attr, node);
-		var name = ga("name");
-		if(!name){ return null; }
-		var o = { name: name, kwArgs: {} }, kw = o.kwArgs, t;
-		t = ga("plot");
-		if(t != null){ kw.plot = t; }
-		t = ga("marker");
-		if(t != null){ kw.marker = t; }
-		t = ga("stroke");
-		if(t != null){ kw.stroke = eval("(" + t + ")"); }
-		t = ga("fill");
-		if(t != null){ kw.fill = eval("(" + t + ")"); }
-		t = ga("legend");
-		if(t != null){ kw.legend = t; }
-		t = ga("data");
-		if(t != null){
-			o.type = "data";
-			o.data = dojo.map(String(t).split(','), Number);
-			return o;
-		}
-		t = ga("array");
-		if(t != null){
-			o.type = "data";
-			o.data = eval("(" + t + ")");
-			return o;
-		}
-		t = ga("store");
-		if(t != null){
-			o.type = "store";
-			o.data = eval("(" + t + ")");
-			t = ga("field");
-			o.field = t != null ? t : "value";
-			t = ga("query");
-			if(!!t){ kw.query = t; }
-			t = ga("queryOptions");
-			if(!!t){ kw.queryOptions = eval("(" + t + ")"); }
-			t = ga("start");
-			if(!!t){ kw.start = Number(t); }
-			t = ga("count");
-			if(!!t){ kw.count = Number(t); }
-			t = ga("sort");
-			if(!!t){ kw.sort = eval("("+t+")"); }
-			t = ga("valueFn");
-			if(!!t){ kw.valueFn = df.lambda(t); }
-			return o;
-		}
-		return null;
-	};
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.themes.ET.greys"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.themes.ET.greys"] = true;
-dojo.provide("dojox.charting.themes.ET.greys");
-
-dojo.deprecated("dojox.charting.themes.ET.greys", "1.3");
-
-(function(){
-	var dxc=dojox.charting;
-	dxc.themes.ET.greys = new dxc.Theme({
-		antiAlias: false,
-		chart: {
-			stroke: null,
-			fill: "inherit"
-		},
-		plotarea: {
-			// stroke: { width: 0.2, color: "#666666" },
-			stroke: null,
-			fill: "transparent"
-		},
-		axis:{
-			stroke:{ width:	0 },
-			line:{ width:	0 },
-			majorTick:{ 
-				color:	"#666666", 
-				width:	1,
-				length: 5
-			},
-			minorTick: { 
-				color:	"black", 
-				width:	0.5, 
-				length:	2
-			},
-			font:"normal normal normal 8pt Tahoma",
-			fontColor:"#999999"
-		},
-		series:{
-			outline:{ width: 0, color: "black" },
-			stroke:	{ width: 1, color: "black" },
-			fill:	dojo.colorFromHex("#3b444b"),
-			font: "normal normal normal 7pt Tahoma",	//	label
-			fontColor: "#717171"
-		},
-		marker:{	//	any markers on a series.
-			stroke:{ width:1 },
-			fill:"#333",
-			font:"normal normal normal 7pt Tahoma",	//	label
-			fontColor:"#000"
-		},
-		colors:[
-			dojo.colorFromHex("#8a8c8f"), 
-			dojo.colorFromHex("#4b4b4b"),
-			dojo.colorFromHex("#3b444b"), 
-			dojo.colorFromHex("#2e2d30"),
-			dojo.colorFromHex("#000000") 
-		]
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.widget.Sparkline"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.widget.Sparkline"] = true;
-dojo.provide("dojox.charting.widget.Sparkline");
-
-
-
-
-(function(){
-
-	var d = dojo;
-
-	dojo.declare("dojox.charting.widget.Sparkline",
-		dojox.charting.widget.Chart2D,
-		{
-			theme: dojox.charting.themes.ET.greys,
-			margins: { l: 0, r: 0, t: 0, b: 0 },
-			type: "Lines",
-			valueFn: "Number(x)",
-			store: "",
-			field: "",
-			query: "",
-			queryOptions: "",
-			start: "0",
-			count: "Infinity",
-			sort: "",
-			data: "",
-			name: "default",
-			buildRendering: function(){
-				var n = this.srcNodeRef;
-				if(	!n.childNodes.length || // shortcut the query
-					!d.query("> .axis, > .plot, > .action, > .series", n).length){
-					var plot = document.createElement("div");
-					d.attr(plot, {
-						"class": "plot",
-						"name": "default",
-						"type": this.type
-					});
-					n.appendChild(plot);
-
-					var series = document.createElement("div");
-					d.attr(series, {
-						"class": "series",
-						plot: "default",
-						name: this.name,
-						start: this.start,
-						count: this.count,
-						valueFn: this.valueFn
-					});
-					d.forEach(
-						["store", "field", "query", "queryOptions", "sort", "data"],
-						function(i){
-							if(this[i].length){
-								d.attr(series, i, this[i]);
-							}
-						},
-						this
-					);
-					n.appendChild(series);
-				}
-				this.inherited(arguments);
-			}
-		}
-	);
-
-})();
-
-}
-
-if(!dojo._hasResource["dojox.charting.widget.Legend"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.charting.widget.Legend"] = true;
-dojo.provide("dojox.charting.widget.Legend");
-
-
-
-
-
-
-
-dojo.declare("dojox.charting.widget.Legend", [dijit._Widget, dijit._Templated], {
-	// summary: A legend for a chart. A legend contains summary labels for 
-	// each series of data contained in the chart.
-	//
-	// Set the boolean horizontal attribute to false to layout legend labels vertically.
-	//
-	// (Line or Scatter charts (colored lines with shape symbols) )
-	// -o- Series1		-X- Series2		-v- Series3
-	//
-	// (Area/Bar/Pie charts (letters represent colors))
-	// [a] Series1		[b] Series2		[c] Series3
-	
-	chartRef:   "",
-	horizontal: true,
-	swatchSize: 18,
-	
-	templateString: "<table dojoAttachPoint='legendNode' class='dojoxLegendNode'><tbody dojoAttachPoint='legendBody'></tbody></table>",
-	
-	legendNode: null,
-	legendBody: null,
-	
-	postCreate: function(){
-		if(!this.chart){
-			if(!this.chartRef){ return; }
-			this.chart = dijit.byId(this.chartRef);
-			if(!this.chart){
-				var node = dojo.byId(this.chartRef);
-				if(node){
-					this.chart = dijit.byNode(node);
-				}else{
-					console.log("Could not find chart instance with id: " + this.chartRef);
-					return;
-				}
-			}
-			this.series = this.chart.chart.series;
-		}else{
-			this.series = this.chart.series;
-		}
-		
-		this.refresh();
-	},
-	refresh: function(){
-		// summary: regenerates the legend to reflect changes to the chart
-		
-		var df = dojox.lang.functional;
-
-		// cleanup
-		if(this._surfaces){
-			dojo.forEach(this._surfaces, function(surface){
-				surface.destroy();
-			});
-		}
-		this._surfaces = [];
-		while(this.legendBody.lastChild){
-			dojo.destroy(this.legendBody.lastChild);
-		}
-
-		if(this.horizontal){
-			dojo.addClass(this.legendNode, "dojoxLegendHorizontal");
-			// make a container <tr>
-			this._tr = dojo.doc.createElement("tr");
-			this.legendBody.appendChild(this._tr);
-		}
-		
-		var s = this.series;
-		if(s.length == 0){
-			return;
-		}
-		if(s[0].chart.stack[0].declaredClass == "dojox.charting.plot2d.Pie"){
-			var t = s[0].chart.stack[0];
-			if(typeof t.run.data[0] == "number"){
-				var filteredRun = df.map(t.run.data, "Math.max(x, 0)");
-				if(df.every(filteredRun, "<= 0")){
-					return;
-				}
-				var slices = df.map(filteredRun, "/this", df.foldl(filteredRun, "+", 0));
-				dojo.forEach(slices, function(x, i){
-					this._addLabel(t.dyn[i], t._getLabel(x * 100) + "%");
-				}, this);
-			}else{
-				dojo.forEach(t.run.data, function(x, i){
-					this._addLabel(t.dyn[i], x.legend || x.text || x.y);
-				}, this);
-			}
-		}else{
-			dojo.forEach(s, function(x){
-				this._addLabel(x.dyn, x.legend || x.name);
-			}, this);
-		}
-	},
-	_addLabel: function(dyn, label){
-		// create necessary elements
-		var icon = dojo.doc.createElement("td"),
-			text = dojo.doc.createElement("td"),
-			div  = dojo.doc.createElement("div");
-		dojo.addClass(icon, "dojoxLegendIcon");
-		dojo.addClass(text, "dojoxLegendText");
-		div.style.width  = this.swatchSize + "px";
-		div.style.height = this.swatchSize + "px";
-		icon.appendChild(div);
-		
-		// create a skeleton
-		if(this._tr){
-			// horizontal
-			this._tr.appendChild(icon);
-			this._tr.appendChild(text);
-		}else{
-			// vertical
-			var tr = dojo.doc.createElement("tr");
-			this.legendBody.appendChild(tr);
-			tr.appendChild(icon);
-			tr.appendChild(text);
-		}
-		
-		// populate the skeleton
-		this._makeIcon(div, dyn);
-		text.innerHTML = String(label);
-	},
-	_makeIcon: function(div, dyn){
-		var mb = { h: this.swatchSize, w: this.swatchSize };
-		var surface = dojox.gfx.createSurface(div, mb.w, mb.h);
-		this._surfaces.push(surface);
-		if(dyn.fill){
-			// regions
-			surface.createRect({x: 2, y: 2, width: mb.w - 4, height: mb.h - 4}).
-				setFill(dyn.fill).setStroke(dyn.stroke);
-		}else if(dyn.stroke || dyn.marker){
-			// draw line
-			var line = {x1: 0, y1: mb.h / 2, x2: mb.w, y2: mb.h / 2};
-			if(dyn.stroke){
-				surface.createLine(line).setStroke(dyn.stroke);
-			}
-			if(dyn.marker){
-				// draw marker on top
-				var c = {x: mb.w / 2, y: mb.h / 2};
-				if(dyn.stroke){
-					surface.createPath({path: "M" + c.x + " " + c.y + " " + dyn.marker}).
-						setFill(dyn.stroke.color).setStroke(dyn.stroke);
-				}else{
-					surface.createPath({path: "M" + c.x + " " + c.y + " " + dyn.marker}).
-						setFill(dyn.color).setStroke(dyn.color);
-				}
-			}
-		}else{
-			// nothing
-			surface.createRect({x: 2, y: 2, width: mb.w - 4, height: mb.h - 4}).
-				setStroke("black");
-			surface.createLine({x1: 2, y1: 2, x2: mb.w - 2, y2: mb.h - 2}).setStroke("black");
-			surface.createLine({x1: 2, y1: mb.h - 2, x2: mb.w - 2, y2: 2}).setStroke("black");
-		}
-	}
-});
-
-}
-
diff --git a/dojox/charting/widget/Legend.js b/dojox/charting/widget/Legend.js
index 60c87bc..0cff803 100644
--- a/dojox/charting/widget/Legend.js
+++ b/dojox/charting/widget/Legend.js
@@ -1,120 +1,169 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.widget.Legend"]){
-dojo._hasResource["dojox.charting.widget.Legend"]=true;
 dojo.provide("dojox.charting.widget.Legend");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
+
 dojo.require("dojox.lang.functional.array");
 dojo.require("dojox.lang.functional.fold");
-dojo.declare("dojox.charting.widget.Legend",[dijit._Widget,dijit._Templated],{chartRef:"",horizontal:true,swatchSize:18,templateString:"<table dojoAttachPoint='legendNode' class='dojoxLegendNode'><tbody dojoAttachPoint='legendBody'></tbody></table>",legendNode:null,legendBody:null,postCreate:function(){
-if(!this.chart){
-if(!this.chartRef){
-return;
-}
-this.chart=dijit.byId(this.chartRef);
-if(!this.chart){
-var _1=dojo.byId(this.chartRef);
-if(_1){
-this.chart=dijit.byNode(_1);
-}else{
-return;
-}
-}
-this.series=this.chart.chart.series;
-}else{
-this.series=this.chart.series;
-}
-this.refresh();
-},refresh:function(){
-var df=dojox.lang.functional;
-if(this._surfaces){
-dojo.forEach(this._surfaces,function(_2){
-_2.destroy();
+
+dojo.declare("dojox.charting.widget.Legend", [dijit._Widget, dijit._Templated], {
+	// summary: A legend for a chart. A legend contains summary labels for 
+	// each series of data contained in the chart.
+	//
+	// Set the horizontal attribute to boolean false to layout legend labels vertically.
+	// Set the horizontal attribute to a number to layout legend labels in horizontal
+	// rows each containing that number of labels (except possibly the last row).
+	//
+	// (Line or Scatter charts (colored lines with shape symbols) )
+	// -o- Series1		-X- Series2		-v- Series3
+	//
+	// (Area/Bar/Pie charts (letters represent colors))
+	// [a] Series1		[b] Series2		[c] Series3
+	
+	chartRef:   "",
+	horizontal: true,
+	swatchSize: 18,
+	
+	templateString: "<table dojoAttachPoint='legendNode' class='dojoxLegendNode'><tbody dojoAttachPoint='legendBody'></tbody></table>",
+	
+	legendNode: null,
+	legendBody: null,
+	
+	postCreate: function(){
+		if(!this.chart){
+			if(!this.chartRef){ return; }
+			this.chart = dijit.byId(this.chartRef);
+			if(!this.chart){
+				var node = dojo.byId(this.chartRef);
+				if(node){
+					this.chart = dijit.byNode(node);
+				}else{
+					console.log("Could not find chart instance with id: " + this.chartRef);
+					return;
+				}
+			}
+			this.series = this.chart.chart.series;
+		}else{
+			this.series = this.chart.series;
+		}
+		
+		this.refresh();
+	},
+	refresh: function(){
+		// summary: regenerates the legend to reflect changes to the chart
+		
+		var df = dojox.lang.functional;
+
+		// cleanup
+		if(this._surfaces){
+			dojo.forEach(this._surfaces, function(surface){
+				surface.destroy();
+			});
+		}
+		this._surfaces = [];
+		while(this.legendBody.lastChild){
+			dojo.destroy(this.legendBody.lastChild);
+		}
+
+		if(this.horizontal){
+			dojo.addClass(this.legendNode, "dojoxLegendHorizontal");
+			// make a container <tr>
+			this._tr = dojo.doc.createElement("tr");
+			this.legendBody.appendChild(this._tr);
+			this._inrow = 0;
+		}
+		
+		var s = this.series;
+		if(s.length == 0){
+			return;
+		}
+		if(s[0].chart.stack[0].declaredClass == "dojox.charting.plot2d.Pie"){
+			var t = s[0].chart.stack[0];
+			if(typeof t.run.data[0] == "number"){
+				var filteredRun = df.map(t.run.data, "Math.max(x, 0)");
+				if(df.every(filteredRun, "<= 0")){
+					return;
+				}
+				var slices = df.map(filteredRun, "/this", df.foldl(filteredRun, "+", 0));
+				dojo.forEach(slices, function(x, i){
+					this._addLabel(t.dyn[i], t._getLabel(x * 100) + "%");
+				}, this);
+			}else{
+				dojo.forEach(t.run.data, function(x, i){
+					this._addLabel(t.dyn[i], x.legend || x.text || x.y);
+				}, this);
+			}
+		}else{
+			dojo.forEach(s, function(x){
+				this._addLabel(x.dyn, x.legend || x.name);
+			}, this);
+		}
+	},
+	_addLabel: function(dyn, label){
+		// create necessary elements
+		var icon = dojo.doc.createElement("td"),
+			text = dojo.doc.createElement("td"),
+			div  = dojo.doc.createElement("div");
+		dojo.addClass(icon, "dojoxLegendIcon");
+		dojo.addClass(text, "dojoxLegendText");
+		div.style.width  = this.swatchSize + "px";
+		div.style.height = this.swatchSize + "px";
+		icon.appendChild(div);
+		
+		// create a skeleton
+		if(this._tr){
+			// horizontal
+			this._tr.appendChild(icon);
+			this._tr.appendChild(text);
+			if(++this._inrow === this.horizontal){
+				// make a fresh container <tr>
+				this._tr = dojo.doc.createElement("tr");
+				this.legendBody.appendChild(this._tr);
+				this._inrow = 0;
+			}
+		}else{
+			// vertical
+			var tr = dojo.doc.createElement("tr");
+			this.legendBody.appendChild(tr);
+			tr.appendChild(icon);
+			tr.appendChild(text);
+		}
+		
+		// populate the skeleton
+		this._makeIcon(div, dyn);
+		text.innerHTML = String(label);
+	},
+	_makeIcon: function(div, dyn){
+		var mb = { h: this.swatchSize, w: this.swatchSize };
+		var surface = dojox.gfx.createSurface(div, mb.w, mb.h);
+		this._surfaces.push(surface);
+		if(dyn.fill){
+			// regions
+			surface.createRect({x: 2, y: 2, width: mb.w - 4, height: mb.h - 4}).
+				setFill(dyn.fill).setStroke(dyn.stroke);
+		}else if(dyn.stroke || dyn.marker){
+			// draw line
+			var line = {x1: 0, y1: mb.h / 2, x2: mb.w, y2: mb.h / 2};
+			if(dyn.stroke){
+				surface.createLine(line).setStroke(dyn.stroke);
+			}
+			if(dyn.marker){
+				// draw marker on top
+				var c = {x: mb.w / 2, y: mb.h / 2};
+				if(dyn.stroke){
+					surface.createPath({path: "M" + c.x + " " + c.y + " " + dyn.marker}).
+						setFill(dyn.stroke.color).setStroke(dyn.stroke);
+				}else{
+					surface.createPath({path: "M" + c.x + " " + c.y + " " + dyn.marker}).
+						setFill(dyn.color).setStroke(dyn.color);
+				}
+			}
+		}else{
+			// nothing
+			surface.createRect({x: 2, y: 2, width: mb.w - 4, height: mb.h - 4}).
+				setStroke("black");
+			surface.createLine({x1: 2, y1: 2, x2: mb.w - 2, y2: mb.h - 2}).setStroke("black");
+			surface.createLine({x1: 2, y1: mb.h - 2, x2: mb.w - 2, y2: 2}).setStroke("black");
+		}
+	}
 });
-}
-this._surfaces=[];
-while(this.legendBody.lastChild){
-dojo.destroy(this.legendBody.lastChild);
-}
-if(this.horizontal){
-dojo.addClass(this.legendNode,"dojoxLegendHorizontal");
-this._tr=dojo.doc.createElement("tr");
-this.legendBody.appendChild(this._tr);
-}
-var s=this.series;
-if(s.length==0){
-return;
-}
-if(s[0].chart.stack[0].declaredClass=="dojox.charting.plot2d.Pie"){
-var t=s[0].chart.stack[0];
-if(typeof t.run.data[0]=="number"){
-var _3=df.map(t.run.data,"Math.max(x, 0)");
-if(df.every(_3,"<= 0")){
-return;
-}
-var _4=df.map(_3,"/this",df.foldl(_3,"+",0));
-dojo.forEach(_4,function(x,i){
-this._addLabel(t.dyn[i],t._getLabel(x*100)+"%");
-},this);
-}else{
-dojo.forEach(t.run.data,function(x,i){
-this._addLabel(t.dyn[i],x.legend||x.text||x.y);
-},this);
-}
-}else{
-dojo.forEach(s,function(x){
-this._addLabel(x.dyn,x.legend||x.name);
-},this);
-}
-},_addLabel:function(_5,_6){
-var _7=dojo.doc.createElement("td"),_8=dojo.doc.createElement("td"),_9=dojo.doc.createElement("div");
-dojo.addClass(_7,"dojoxLegendIcon");
-dojo.addClass(_8,"dojoxLegendText");
-_9.style.width=this.swatchSize+"px";
-_9.style.height=this.swatchSize+"px";
-_7.appendChild(_9);
-if(this._tr){
-this._tr.appendChild(_7);
-this._tr.appendChild(_8);
-}else{
-var tr=dojo.doc.createElement("tr");
-this.legendBody.appendChild(tr);
-tr.appendChild(_7);
-tr.appendChild(_8);
-}
-this._makeIcon(_9,_5);
-_8.innerHTML=String(_6);
-},_makeIcon:function(_a,_b){
-var mb={h:this.swatchSize,w:this.swatchSize};
-var _c=dojox.gfx.createSurface(_a,mb.w,mb.h);
-this._surfaces.push(_c);
-if(_b.fill){
-_c.createRect({x:2,y:2,width:mb.w-4,height:mb.h-4}).setFill(_b.fill).setStroke(_b.stroke);
-}else{
-if(_b.stroke||_b.marker){
-var _d={x1:0,y1:mb.h/2,x2:mb.w,y2:mb.h/2};
-if(_b.stroke){
-_c.createLine(_d).setStroke(_b.stroke);
-}
-if(_b.marker){
-var c={x:mb.w/2,y:mb.h/2};
-if(_b.stroke){
-_c.createPath({path:"M"+c.x+" "+c.y+" "+_b.marker}).setFill(_b.stroke.color).setStroke(_b.stroke);
-}else{
-_c.createPath({path:"M"+c.x+" "+c.y+" "+_b.marker}).setFill(_b.color).setStroke(_b.color);
-}
-}
-}else{
-_c.createRect({x:2,y:2,width:mb.w-4,height:mb.h-4}).setStroke("black");
-_c.createLine({x1:2,y1:2,x2:mb.w-2,y2:mb.h-2}).setStroke("black");
-_c.createLine({x1:2,y1:mb.h-2,x2:mb.w-2,y2:2}).setStroke("black");
-}
-}
-}});
-}
diff --git a/dojox/charting/widget/Sparkline.js b/dojox/charting/widget/Sparkline.js
index ebd9e86..61e5253 100644
--- a/dojox/charting/widget/Sparkline.js
+++ b/dojox/charting/widget/Sparkline.js
@@ -1,33 +1,63 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.charting.widget.Sparkline"]){
-dojo._hasResource["dojox.charting.widget.Sparkline"]=true;
 dojo.provide("dojox.charting.widget.Sparkline");
+
 dojo.require("dojox.charting.widget.Chart2D");
 dojo.require("dojox.charting.themes.ET.greys");
+
 (function(){
-var d=dojo;
-dojo.declare("dojox.charting.widget.Sparkline",dojox.charting.widget.Chart2D,{theme:dojox.charting.themes.ET.greys,margins:{l:0,r:0,t:0,b:0},type:"Lines",valueFn:"Number(x)",store:"",field:"",query:"",queryOptions:"",start:"0",count:"Infinity",sort:"",data:"",name:"default",buildRendering:function(){
-var n=this.srcNodeRef;
-if(!n.childNodes.length||!d.query("> .axis, > .plot, > .action, > .series",n).length){
-var _1=document.createElement("div");
-d.attr(_1,{"class":"plot","name":"default","type":this.type});
-n.appendChild(_1);
-var _2=document.createElement("div");
-d.attr(_2,{"class":"series",plot:"default",name:this.name,start:this.start,count:this.count,valueFn:this.valueFn});
-d.forEach(["store","field","query","queryOptions","sort","data"],function(i){
-if(this[i].length){
-d.attr(_2,i,this[i]);
-}
-},this);
-n.appendChild(_2);
-}
-this.inherited(arguments);
-}});
+
+	var d = dojo;
+
+	dojo.declare("dojox.charting.widget.Sparkline",
+		dojox.charting.widget.Chart2D,
+		{
+			theme: dojox.charting.themes.ET.greys,
+			margins: { l: 0, r: 0, t: 0, b: 0 },
+			type: "Lines",
+			valueFn: "Number(x)",
+			store: "",
+			field: "",
+			query: "",
+			queryOptions: "",
+			start: "0",
+			count: "Infinity",
+			sort: "",
+			data: "",
+			name: "default",
+			buildRendering: function(){
+				var n = this.srcNodeRef;
+				if(	!n.childNodes.length || // shortcut the query
+					!d.query("> .axis, > .plot, > .action, > .series", n).length){
+					var plot = document.createElement("div");
+					d.attr(plot, {
+						"class": "plot",
+						"name": "default",
+						"type": this.type
+					});
+					n.appendChild(plot);
+
+					var series = document.createElement("div");
+					d.attr(series, {
+						"class": "series",
+						plot: "default",
+						name: this.name,
+						start: this.start,
+						count: this.count,
+						valueFn: this.valueFn
+					});
+					d.forEach(
+						["store", "field", "query", "queryOptions", "sort", "data"],
+						function(i){
+							if(this[i].length){
+								d.attr(series, i, this[i]);
+							}
+						},
+						this
+					);
+					n.appendChild(series);
+				}
+				this.inherited(arguments);
+			}
+		}
+	);
+
 })();
-}
diff --git a/dojox/collections.js b/dojox/collections.js
index d0bb1d9..6ff7320 100644
--- a/dojox/collections.js
+++ b/dojox/collections.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.collections"]){
-dojo._hasResource["dojox.collections"]=true;
 dojo.provide("dojox.collections");
 dojo.require("dojox.collections._base");
-}
diff --git a/dojox/collections/ArrayList.js b/dojox/collections/ArrayList.js
index b6fabaf..578ad38 100644
--- a/dojox/collections/ArrayList.js
+++ b/dojox/collections/ArrayList.js
@@ -1,104 +1,129 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.collections.ArrayList"]){
-dojo._hasResource["dojox.collections.ArrayList"]=true;
 dojo.provide("dojox.collections.ArrayList");
 dojo.require("dojox.collections._base");
-dojox.collections.ArrayList=function(_1){
-var _2=[];
-if(_1){
-_2=_2.concat(_1);
-}
-this.count=_2.length;
-this.add=function(_3){
-_2.push(_3);
-this.count=_2.length;
-};
-this.addRange=function(a){
-if(a.getIterator){
-var e=a.getIterator();
-while(!e.atEnd()){
-this.add(e.get());
-}
-this.count=_2.length;
-}else{
-for(var i=0;i<a.length;i++){
-_2.push(a[i]);
-}
-this.count=_2.length;
-}
-};
-this.clear=function(){
-_2.splice(0,_2.length);
-this.count=0;
-};
-this.clone=function(){
-return new dojox.collections.ArrayList(_2);
-};
-this.contains=function(_4){
-for(var i=0;i<_2.length;i++){
-if(_2[i]==_4){
-return true;
-}
-}
-return false;
-};
-this.forEach=function(fn,_5){
-dojo.forEach(_2,fn,_5);
-};
-this.getIterator=function(){
-return new dojox.collections.Iterator(_2);
-};
-this.indexOf=function(_6){
-for(var i=0;i<_2.length;i++){
-if(_2[i]==_6){
-return i;
-}
-}
-return -1;
-};
-this.insert=function(i,_7){
-_2.splice(i,0,_7);
-this.count=_2.length;
-};
-this.item=function(i){
-return _2[i];
-};
-this.remove=function(_8){
-var i=this.indexOf(_8);
-if(i>=0){
-_2.splice(i,1);
-}
-this.count=_2.length;
-};
-this.removeAt=function(i){
-_2.splice(i,1);
-this.count=_2.length;
-};
-this.reverse=function(){
-_2.reverse();
-};
-this.sort=function(fn){
-if(fn){
-_2.sort(fn);
-}else{
-_2.sort();
-}
-};
-this.setByIndex=function(i,_9){
-_2[i]=_9;
-this.count=_2.length;
-};
-this.toArray=function(){
-return [].concat(_2);
-};
-this.toString=function(_a){
-return _2.join((_a||","));
-};
+
+dojox.collections.ArrayList=function(/* array? */arr){
+	//	summary
+	//	Returns a new object of type dojox.collections.ArrayList
+	var items=[];
+	if(arr) items=items.concat(arr);
+	this.count=items.length;
+	this.add=function(/* object */obj){
+		//	summary
+		//	Add an element to the collection.
+		items.push(obj);
+		this.count=items.length;
+	};
+	this.addRange=function(/* array */a){
+		//	summary
+		//	Add a range of objects to the ArrayList
+		if(a.getIterator){
+			var e=a.getIterator();
+			while(!e.atEnd()){
+				this.add(e.get());
+			}
+			this.count=items.length;
+		}else{
+			for(var i=0; i<a.length; i++){
+				items.push(a[i]);
+			}
+			this.count=items.length;
+		}
+	};
+	this.clear=function(){
+		//	summary
+		//	Clear all elements out of the collection, and reset the count.
+		items.splice(0, items.length);
+		this.count=0;
+	};
+	this.clone=function(){
+		//	summary
+		//	Clone the array list
+		return new dojox.collections.ArrayList(items);	//	dojox.collections.ArrayList
+	};
+	this.contains=function(/* object */obj){
+		//	summary
+		//	Check to see if the passed object is a member in the ArrayList
+		for(var i=0; i < items.length; i++){
+			if(items[i] == obj) {
+				return true;	//	bool
+			}
+		}
+		return false;	//	bool
+	};
+	this.forEach=function(/* function */ fn, /* object? */ scope){
+		//	summary
+		//	functional iterator, following the mozilla spec.
+		dojo.forEach(items, fn, scope);
+	};
+	this.getIterator=function(){
+		//	summary
+		//	Get an Iterator for this object
+		return new dojox.collections.Iterator(items);	//	dojox.collections.Iterator
+	};
+	this.indexOf=function(/* object */obj){
+		//	summary
+		//	Return the numeric index of the passed object; will return -1 if not found.
+		for(var i=0; i < items.length; i++){
+			if(items[i] == obj) {
+				return i;	//	int
+			}
+		}
+		return -1;	// int
+	};
+	this.insert=function(/* int */ i, /* object */ obj){
+		//	summary
+		//	Insert the passed object at index i
+		items.splice(i,0,obj);
+		this.count=items.length;
+	};
+	this.item=function(/* int */ i){
+		//	summary
+		//	return the element at index i
+		return items[i];	//	object
+	};
+	this.remove=function(/* object */obj){
+		//	summary
+		//	Look for the passed object, and if found, remove it from the internal array.
+		var i=this.indexOf(obj);
+		if(i >=0) {
+			items.splice(i,1);
+		}
+		this.count=items.length;
+	};
+	this.removeAt=function(/* int */ i){
+		//	summary
+		//	return an array with function applied to all elements
+		items.splice(i,1);
+		this.count=items.length;
+	};
+	this.reverse=function(){
+		//	summary
+		//	Reverse the internal array
+		items.reverse();
+	};
+	this.sort=function(/* function? */ fn){
+		//	summary
+		//	sort the internal array
+		if(fn){
+			items.sort(fn);
+		}else{
+			items.sort();
+		}
+	};
+	this.setByIndex=function(/* int */ i, /* object */ obj){
+		//	summary
+		//	Set an element in the array by the passed index.
+		items[i]=obj;
+		this.count=items.length;
+	};
+	this.toArray=function(){
+		//	summary
+		//	Return a new array with all of the items of the internal array concatenated.
+		return [].concat(items);
+	}
+	this.toString=function(/* string */ delim){
+		//	summary
+		//	implementation of toString, follows [].toString();
+		return items.join((delim||","));
+	};
 };
-}
diff --git a/dojox/collections/BinaryTree.js b/dojox/collections/BinaryTree.js
index 341dd88..57215d2 100644
--- a/dojox/collections/BinaryTree.js
+++ b/dojox/collections/BinaryTree.js
@@ -1,255 +1,207 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.collections.BinaryTree"]){
-dojo._hasResource["dojox.collections.BinaryTree"]=true;
 dojo.provide("dojox.collections.BinaryTree");
 dojo.require("dojox.collections._base");
-dojox.collections.BinaryTree=function(_1){
-function _2(_3,_4,_5){
-this.value=_3||null;
-this.right=_4||null;
-this.left=_5||null;
-this.clone=function(){
-var c=new _2();
-if(this.value.value){
-c.value=this.value.clone();
-}else{
-c.value=this.value;
-}
-if(this.left!=null){
-c.left=this.left.clone();
-}
-if(this.right!=null){
-c.right=this.right.clone();
-}
-return c;
-};
-this.compare=function(n){
-if(this.value>n.value){
-return 1;
-}
-if(this.value<n.value){
-return -1;
-}
-return 0;
-};
-this.compareData=function(d){
-if(this.value>d){
-return 1;
-}
-if(this.value<d){
-return -1;
-}
-return 0;
-};
-};
-function _6(_7,a){
-if(_7){
-_6(_7.left,a);
-a.push(_7.value);
-_6(_7.right,a);
-}
-};
-function _8(_9,_a){
-var s="";
-if(_9){
-s=_9.value.toString()+_a;
-s+=_8(_9.left,_a);
-s+=_8(_9.right,_a);
-}
-return s;
-};
-function _b(_c,_d){
-var s="";
-if(_c){
-s=_b(_c.left,_d);
-s+=_c.value.toString()+_d;
-s+=_b(_c.right,_d);
-}
-return s;
-};
-function _e(_f,sep){
-var s="";
-if(_f){
-s=_e(_f.left,sep);
-s+=_e(_f.right,sep);
-s+=_f.value.toString()+sep;
-}
-return s;
-};
-function _10(_11,_12){
-if(!_11){
-return null;
-}
-var i=_11.compareData(_12);
-if(i==0){
-return _11;
-}
-if(i>0){
-return _10(_11.left,_12);
-}else{
-return _10(_11.right,_12);
-}
-};
-this.add=function(_13){
-var n=new _2(_13);
-var i;
-var _14=_15;
-var _16=null;
-while(_14){
-i=_14.compare(n);
-if(i==0){
-return;
-}
-_16=_14;
-if(i>0){
-_14=_14.left;
-}else{
-_14=_14.right;
-}
-}
-this.count++;
-if(!_16){
-_15=n;
-}else{
-i=_16.compare(n);
-if(i>0){
-_16.left=n;
-}else{
-_16.right=n;
-}
-}
-};
-this.clear=function(){
-_15=null;
-this.count=0;
-};
-this.clone=function(){
-var c=new dojox.collections.BinaryTree();
-var itr=this.getIterator();
-while(!itr.atEnd()){
-c.add(itr.get());
-}
-return c;
-};
-this.contains=function(_17){
-return this.search(_17)!=null;
-};
-this.deleteData=function(_18){
-var _19=_15;
-var _1a=null;
-var i=_19.compareData(_18);
-while(i!=0&&_19!=null){
-if(i>0){
-_1a=_19;
-_19=_19.left;
-}else{
-if(i<0){
-_1a=_19;
-_19=_19.right;
-}
-}
-i=_19.compareData(_18);
-}
-if(!_19){
-return;
-}
-this.count--;
-if(!_19.right){
-if(!_1a){
-_15=_19.left;
-}else{
-i=_1a.compare(_19);
-if(i>0){
-_1a.left=_19.left;
-}else{
-if(i<0){
-_1a.right=_19.left;
-}
-}
-}
-}else{
-if(!_19.right.left){
-if(!_1a){
-_15=_19.right;
-}else{
-i=_1a.compare(_19);
-if(i>0){
-_1a.left=_19.right;
-}else{
-if(i<0){
-_1a.right=_19.right;
-}
-}
-}
-}else{
-var _1b=_19.right.left;
-var _1c=_19.right;
-while(_1b.left!=null){
-_1c=_1b;
-_1b=_1b.left;
-}
-_1c.left=_1b.right;
-_1b.left=_19.left;
-_1b.right=_19.right;
-if(!_1a){
-_15=_1b;
-}else{
-i=_1a.compare(_19);
-if(i>0){
-_1a.left=_1b;
-}else{
-if(i<0){
-_1a.right=_1b;
-}
-}
-}
-}
-}
-};
-this.getIterator=function(){
-var a=[];
-_6(_15,a);
-return new dojox.collections.Iterator(a);
-};
-this.search=function(_1d){
-return _10(_15,_1d);
-};
-this.toString=function(_1e,sep){
-if(!_1e){
-_1e=dojox.collections.BinaryTree.TraversalMethods.Inorder;
-}
-if(!sep){
-sep=",";
-}
-var s="";
-switch(_1e){
-case dojox.collections.BinaryTree.TraversalMethods.Preorder:
-s=_8(_15,sep);
-break;
-case dojox.collections.BinaryTree.TraversalMethods.Inorder:
-s=_b(_15,sep);
-break;
-case dojox.collections.BinaryTree.TraversalMethods.Postorder:
-s=_e(_15,sep);
-break;
-}
-if(s.length==0){
-return "";
-}else{
-return s.substring(0,s.length-sep.length);
-}
-};
-this.count=0;
-var _15=this.root=null;
-if(_1){
-this.add(_1);
+
+dojox.collections.BinaryTree=function(data){
+	function node(data, rnode, lnode){
+		this.value=data||null;
+		this.right=rnode||null;
+		this.left=lnode||null;
+		this.clone=function(){
+			var c=new node();
+			if(this.value.value){
+				c.value=this.value.clone();
+			}else{ 
+				c.value=this.value;
+			}
+			if(this.left!=null){
+				c.left=this.left.clone();
+			}
+			if(this.right!=null){
+				c.right=this.right.clone();
+			}
+			return c;
+		}
+		this.compare=function(n){
+			if(this.value>n.value){ return 1; }
+			if(this.value<n.value){ return -1; }
+			return 0;
+		}
+		this.compareData=function(d){
+			if(this.value>d){ return 1; }
+			if(this.value<d){ return -1; }
+			return 0;
+		}
+	}
+
+	function inorderTraversalBuildup(current, a){
+		if(current){
+			inorderTraversalBuildup(current.left, a);
+			a.push(current.value);
+			inorderTraversalBuildup(current.right, a);
+		}
+	}
+
+	function preorderTraversal(current, sep){
+		var s="";
+		if (current){
+			s=current.value.toString() + sep;
+			s+=preorderTraversal(current.left, sep);
+			s+=preorderTraversal(current.right, sep);
+		}
+		return s;
+	}
+	function inorderTraversal(current, sep){
+		var s="";
+		if (current){
+			s=inorderTraversal(current.left, sep);
+			s+=current.value.toString() + sep;
+			s+=inorderTraversal(current.right, sep);
+		}
+		return s;
+	}
+	function postorderTraversal(current, sep){
+		var s="";
+		if (current){
+			s=postorderTraversal(current.left, sep);
+			s+=postorderTraversal(current.right, sep);
+			s+=current.value.toString() + sep;
+		}
+		return s;
+	}
+	
+	function searchHelper(current, data){
+		if(!current){ return null; }
+		var i=current.compareData(data);
+		if(i==0){ return current; }
+		if(i>0){ return searchHelper(current.left, data); }
+		else{ return searchHelper(current.right, data); }
+	}
+
+	this.add=function(data){
+		var n=new node(data);
+		var i;
+		var current=root;
+		var parent=null;
+		while(current){
+			i=current.compare(n);
+			if(i==0){ return; }
+			parent=current;
+			if(i>0){ current=current.left; }
+			else{ current=current.right; }
+		}
+		this.count++;
+		if(!parent){
+			root=n;
+		}else{
+			i=parent.compare(n);
+			if(i>0){ 
+				parent.left=n;
+			}else{
+				parent.right=n;
+			}
+		}
+	};
+	this.clear=function(){
+		root=null;
+		this.count=0;
+	};
+	this.clone=function(){
+		var c=new dojox.collections.BinaryTree();
+		var itr=this.getIterator();
+		while(!itr.atEnd()){
+			c.add(itr.get());
+		}
+		return c;
+	};
+	this.contains=function(data){
+		return this.search(data) != null;
+	};
+	this.deleteData=function(data){
+		var current=root;
+		var parent=null;
+		var i=current.compareData(data);
+		while(i!=0&&current!=null){
+			if(i>0){
+				parent=current;
+				current=current.left;
+			}else if(i<0){
+				parent=current;
+				current=current.right;
+			}
+			i=current.compareData(data);
+		}
+		if(!current){ return; }
+		this.count--;
+		if(!current.right){
+			if(!parent){ 
+				root=current.left;
+			}else{
+				i=parent.compare(current);
+				if(i>0){ parent.left=current.left; }
+				else if(i<0){ parent.right=current.left; }
+			}
+		} 
+		else if(!current.right.left){
+			if(!parent){
+				root=current.right;
+			}else{
+				i=parent.compare(current);
+				if(i>0){ parent.left=current.right; }
+				else if(i<0){ parent.right=current.right; }
+			}
+		}
+		else{
+			var leftmost=current.right.left;
+			var lmParent=current.right;
+			while(leftmost.left!=null){
+				lmParent=leftmost;
+				leftmost=leftmost.left;
+			}
+			lmParent.left=leftmost.right;
+			leftmost.left=current.left;
+			leftmost.right=current.right;
+			if(!parent){ 
+				root=leftmost;
+			}else{
+				i=parent.compare(current);
+				if(i>0){ parent.left=leftmost; }
+				else if(i<0){ parent.right=leftmost; }
+			}
+		}
+	};
+	this.getIterator=function(){
+		var a=[];
+		inorderTraversalBuildup(root, a);
+		return new dojox.collections.Iterator(a);
+	};
+	this.search=function(data){
+		return searchHelper(root, data);
+	};
+	this.toString=function(order, sep){
+		if(!order){ order=dojox.collections.BinaryTree.TraversalMethods.Inorder; }
+		if(!sep){ sep=","; }
+		var s="";
+		switch(order){
+			case dojox.collections.BinaryTree.TraversalMethods.Preorder:
+				s=preorderTraversal(root, sep);
+				break;
+			case dojox.collections.BinaryTree.TraversalMethods.Inorder:
+				s=inorderTraversal(root, sep);
+				break;
+			case dojox.collections.BinaryTree.TraversalMethods.Postorder:
+				s=postorderTraversal(root, sep);
+				break;
+		};
+		if(s.length==0){ return ""; }
+		else{ return s.substring(0, s.length - sep.length); }
+	};
+
+	this.count=0;
+	var root=this.root=null;
+	if(data){
+		this.add(data);
+	}
 }
+dojox.collections.BinaryTree.TraversalMethods={
+	Preorder: 1, Inorder: 2, Postorder: 3
 };
-dojox.collections.BinaryTree.TraversalMethods={Preorder:1,Inorder:2,Postorder:3};
-}
diff --git a/dojox/collections/Dictionary.js b/dojox/collections/Dictionary.js
index c6f1a18..27deee6 100644
--- a/dojox/collections/Dictionary.js
+++ b/dojox/collections/Dictionary.js
@@ -1,91 +1,112 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.collections.Dictionary"]){
-dojo._hasResource["dojox.collections.Dictionary"]=true;
 dojo.provide("dojox.collections.Dictionary");
 dojo.require("dojox.collections._base");
-dojox.collections.Dictionary=function(_1){
-var _2={};
-this.count=0;
-var _3={};
-this.add=function(k,v){
-var b=(k in _2);
-_2[k]=new dojox.collections.DictionaryEntry(k,v);
-if(!b){
-this.count++;
-}
-};
-this.clear=function(){
-_2={};
-this.count=0;
-};
-this.clone=function(){
-return new dojox.collections.Dictionary(this);
-};
-this.contains=this.containsKey=function(k){
-if(_3[k]){
-return false;
-}
-return (_2[k]!=null);
-};
-this.containsValue=function(v){
-var e=this.getIterator();
-while(e.get()){
-if(e.element.value==v){
-return true;
-}
-}
-return false;
-};
-this.entry=function(k){
-return _2[k];
-};
-this.forEach=function(fn,_4){
-var a=[];
-for(var p in _2){
-if(!_3[p]){
-a.push(_2[p]);
-}
-}
-dojo.forEach(a,fn,_4);
-};
-this.getKeyList=function(){
-return (this.getIterator()).map(function(_5){
-return _5.key;
-});
-};
-this.getValueList=function(){
-return (this.getIterator()).map(function(_6){
-return _6.value;
-});
-};
-this.item=function(k){
-if(k in _2){
-return _2[k].valueOf();
-}
-return undefined;
-};
-this.getIterator=function(){
-return new dojox.collections.DictionaryIterator(_2);
-};
-this.remove=function(k){
-if(k in _2&&!_3[k]){
-delete _2[k];
-this.count--;
-return true;
-}
-return false;
-};
-if(_1){
-var e=_1.getIterator();
-while(e.get()){
-this.add(e.element.key,e.element.value);
-}
-}
+
+dojox.collections.Dictionary=function(/* dojox.collections.Dictionary? */dictionary){
+	//	summary
+	//	Returns an object of type dojox.collections.Dictionary
+	var items={};
+	this.count=0;
+
+	//	comparator for property addition and access.
+	var testObject={};
+
+	this.add=function(/* string */k, /* object */v){
+		//	summary
+		//	Add a new item to the Dictionary.
+		var b=(k in items);
+		items[k]=new dojox.collections.DictionaryEntry(k,v);
+		if(!b){
+			this.count++;
+		}
+	};
+	this.clear=function(){
+		//	summary
+		//	Clears the internal dictionary.
+		items={};
+		this.count=0;
+	};
+	this.clone=function(){
+		//	summary
+		//	Returns a new instance of dojox.collections.Dictionary; note the the dictionary is a clone but items might not be.
+		return new dojox.collections.Dictionary(this);	//	dojox.collections.Dictionary
+	};
+	this.contains=this.containsKey=function(/* string */k){
+		//	summary
+		//	Check to see if the dictionary has an entry at key "k".
+		if(testObject[k]){
+			return false;			// bool
+		}
+		return (items[k]!=null);	//	bool
+	};
+	this.containsValue=function(/* object */v){
+		//	summary
+		//	Check to see if the dictionary has an entry with value "v".
+		var e=this.getIterator();
+		while(e.get()){
+			if(e.element.value==v){
+				return true;	//	bool
+			}
+		}
+		return false;	//	bool
+	};
+	this.entry=function(/* string */k){
+		//	summary
+		//	Accessor method; similar to dojox.collections.Dictionary.item but returns the actual Entry object.
+		return items[k];	//	dojox.collections.DictionaryEntry
+	};
+	this.forEach=function(/* function */ fn, /* object? */ scope){
+		//	summary
+		//	functional iterator, following the mozilla spec.
+		var a=[];	//	Create an indexing array
+		for(var p in items) {
+			if(!testObject[p]){
+				a.push(items[p]);	//	fill it up
+			}
+		}
+		dojo.forEach(a, fn, scope);
+	};
+	this.getKeyList=function(){
+		//	summary
+		//	Returns an array of the keys in the dictionary.
+		return (this.getIterator()).map(function(entry){ 
+			return entry.key; 
+		});	//	array
+	};
+	this.getValueList=function(){
+		//	summary
+		//	Returns an array of the values in the dictionary.
+		return (this.getIterator()).map(function(entry){ 
+			return entry.value; 
+		});	//	array
+	};
+	this.item=function(/* string */k){
+		//	summary
+		//	Accessor method.
+		if(k in items){
+			return items[k].valueOf();	//	object
+		}
+		return undefined;	//	object
+	};
+	this.getIterator=function(){
+		//	summary
+		//	Gets a dojox.collections.DictionaryIterator for iteration purposes.
+		return new dojox.collections.DictionaryIterator(items);	//	dojox.collections.DictionaryIterator
+	};
+	this.remove=function(/* string */k){
+		//	summary
+		//	Removes the item at k from the internal collection.
+		if(k in items && !testObject[k]){
+			delete items[k];
+			this.count--;
+			return true;	//	bool
+		}
+		return false;	//	bool
+	};
+
+	if (dictionary){
+		var e=dictionary.getIterator();
+		while(e.get()) {
+			 this.add(e.element.key, e.element.value);
+		}
+	}
 };
-}
diff --git a/dojox/collections/Queue.js b/dojox/collections/Queue.js
index f689e8a..d8754e3 100644
--- a/dojox/collections/Queue.js
+++ b/dojox/collections/Queue.js
@@ -1,57 +1,70 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.collections.Queue"]){
-dojo._hasResource["dojox.collections.Queue"]=true;
 dojo.provide("dojox.collections.Queue");
 dojo.require("dojox.collections._base");
-dojox.collections.Queue=function(_1){
-var q=[];
-if(_1){
-q=q.concat(_1);
-}
-this.count=q.length;
-this.clear=function(){
-q=[];
-this.count=q.length;
-};
-this.clone=function(){
-return new dojox.collections.Queue(q);
-};
-this.contains=function(o){
-for(var i=0;i<q.length;i++){
-if(q[i]==o){
-return true;
-}
-}
-return false;
-};
-this.copyTo=function(_2,i){
-_2.splice(i,0,q);
-};
-this.dequeue=function(){
-var r=q.shift();
-this.count=q.length;
-return r;
-};
-this.enqueue=function(o){
-this.count=q.push(o);
-};
-this.forEach=function(fn,_3){
-dojo.forEach(q,fn,_3);
-};
-this.getIterator=function(){
-return new dojox.collections.Iterator(q);
-};
-this.peek=function(){
-return q[0];
-};
-this.toArray=function(){
-return [].concat(q);
-};
+
+dojox.collections.Queue=function(/* array? */arr){
+	//	summary
+	//	return an object of type dojox.collections.Queue
+	var q=[];
+	if (arr){
+		q=q.concat(arr);
+	}
+	this.count=q.length;
+	this.clear=function(){
+		//	summary
+		//	clears the internal collection
+		q=[];
+		this.count=q.length;
+	};
+	this.clone=function(){
+		//	summary
+		//	creates a new Queue based on this one
+		return new dojox.collections.Queue(q);	//	dojox.collections.Queue
+	};
+	this.contains=function(/* object */ o){
+		//	summary
+		//	Check to see if the passed object is an element in this queue
+		for(var i=0; i<q.length; i++){
+			if (q[i]==o){
+				return true;	//	bool
+			}
+		}
+		return false;	//	bool
+	};
+	this.copyTo=function(/* array */ arr, /* int */ i){
+		//	summary
+		//	Copy the contents of this queue into the passed array at index i.
+		arr.splice(i,0,q);
+	};
+	this.dequeue=function(){
+		//	summary
+		//	shift the first element off the queue and return it
+		var r=q.shift();
+		this.count=q.length;
+		return r;	//	object
+	};
+	this.enqueue=function(/* object */ o){
+		//	summary
+		//	put the passed object at the end of the queue
+		this.count=q.push(o);
+	};
+	this.forEach=function(/* function */ fn, /* object? */ scope){
+		//	summary
+		//	functional iterator, following the mozilla spec.
+		dojo.forEach(q, fn, scope);
+	};
+	this.getIterator=function(){
+		//	summary
+		//	get an Iterator based on this queue.
+		return new dojox.collections.Iterator(q);	//	dojox.collections.Iterator
+	};
+	this.peek=function(){
+		//	summary
+		//	get the next element in the queue without altering the queue.
+		return q[0];
+	};
+	this.toArray=function(){
+		//	summary
+		//	return an array based on the internal array of the queue.
+		return [].concat(q);
+	};
 };
-}
diff --git a/dojox/collections/Set.js b/dojox/collections/Set.js
index 667214d..1939631 100644
--- a/dojox/collections/Set.js
+++ b/dojox/collections/Set.js
@@ -1,84 +1,85 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.collections.Set"]){
-dojo._hasResource["dojox.collections.Set"]=true;
 dojo.provide("dojox.collections.Set");
 dojo.require("dojox.collections.ArrayList");
+
 (function(){
-var _1=dojox.collections;
-_1.Set=new (function(){
-function _2(_3){
-if(_3.constructor==Array){
-return new dojox.collections.ArrayList(_3);
-}
-return _3;
-};
-this.union=function(_4,_5){
-_4=_2(_4);
-_5=_2(_5);
-var _6=new dojox.collections.ArrayList(_4.toArray());
-var e=_5.getIterator();
-while(!e.atEnd()){
-var _7=e.get();
-if(!_6.contains(_7)){
-_6.add(_7);
-}
-}
-return _6;
-};
-this.intersection=function(_8,_9){
-_8=_2(_8);
-_9=_2(_9);
-var _a=new dojox.collections.ArrayList();
-var e=_9.getIterator();
-while(!e.atEnd()){
-var _b=e.get();
-if(_8.contains(_b)){
-_a.add(_b);
-}
-}
-return _a;
-};
-this.difference=function(_c,_d){
-_c=_2(_c);
-_d=_2(_d);
-var _e=new dojox.collections.ArrayList();
-var e=_c.getIterator();
-while(!e.atEnd()){
-var _f=e.get();
-if(!_d.contains(_f)){
-_e.add(_f);
-}
-}
-return _e;
-};
-this.isSubSet=function(_10,_11){
-_10=_2(_10);
-_11=_2(_11);
-var e=_10.getIterator();
-while(!e.atEnd()){
-if(!_11.contains(e.get())){
-return false;
-}
-}
-return true;
-};
-this.isSuperSet=function(_12,_13){
-_12=_2(_12);
-_13=_2(_13);
-var e=_13.getIterator();
-while(!e.atEnd()){
-if(!_12.contains(e.get())){
-return false;
-}
-}
-return true;
-};
-})();
+	var dxc=dojox.collections;
+	dxc.Set=new (function(){
+		function conv(arr){
+			if(arr.constructor==Array){
+				return new dojox.collections.ArrayList(arr);	//	dojox.collections.ArrayList
+			}
+			return arr;		//	dojox.collections.ArrayList
+		}
+		this.union = function(/* array */setA, /* array */setB){
+			//	summary
+			//	Return the union of the two passed sets.
+			setA=conv(setA);
+			setB=conv(setB);
+			var result = new dojox.collections.ArrayList(setA.toArray());
+			var e = setB.getIterator();
+			while(!e.atEnd()){
+				var item=e.get();
+				if(!result.contains(item)){
+					result.add(item);
+				}
+			}
+			return result;	//	dojox.collections.ArrayList
+		};
+		this.intersection = function(/* array */setA, /* array */setB){
+			//	summary
+			//	Return the intersection of the two passed sets.
+			setA=conv(setA);
+			setB=conv(setB);
+			var result = new dojox.collections.ArrayList();
+			var e = setB.getIterator();
+			while(!e.atEnd()){
+				var item=e.get();
+				if(setA.contains(item)){
+					result.add(item);
+				}
+			}
+			return result;	//	dojox.collections.ArrayList
+		};
+		this.difference = function(/* array */setA, /* array */setB){
+			//	summary
+			//	Returns everything in setA that is not in setB.
+			setA=conv(setA);
+			setB=conv(setB);
+			var result = new dojox.collections.ArrayList();
+			var e=setA.getIterator();
+			while(!e.atEnd()){
+				var item=e.get();
+				if(!setB.contains(item)){
+					result.add(item);
+				}
+			}
+			return result;	//	dojox.collections.ArrayList
+		};
+		this.isSubSet = function(/* array */setA, /* array */setB) {
+			//	summary
+			//	Returns if set B is a subset of set A.
+			setA=conv(setA);
+			setB=conv(setB);
+			var e = setA.getIterator();
+			while(!e.atEnd()){
+				if(!setB.contains(e.get())){
+					return false;	//	boolean
+				}
+			}
+			return true;	//	boolean
+		};
+		this.isSuperSet = function(/* array */setA, /* array */setB){
+			//	summary
+			//	Returns if set B is a superset of set A.
+			setA=conv(setA);
+			setB=conv(setB);
+			var e = setB.getIterator();
+			while(!e.atEnd()){
+				if(!setA.contains(e.get())){
+					return false;	//	boolean
+				}
+			}
+			return true;	//	boolean
+		};
+	})();
 })();
-}
diff --git a/dojox/collections/SortedList.js b/dojox/collections/SortedList.js
index c7e4c56..002eefb 100644
--- a/dojox/collections/SortedList.js
+++ b/dojox/collections/SortedList.js
@@ -1,161 +1,194 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.collections.SortedList"]){
-dojo._hasResource["dojox.collections.SortedList"]=true;
 dojo.provide("dojox.collections.SortedList");
 dojo.require("dojox.collections._base");
-dojox.collections.SortedList=function(_1){
-var _2=this;
-var _3={};
-var q=[];
-var _4=function(a,b){
-if(a.key>b.key){
-return 1;
-}
-if(a.key<b.key){
-return -1;
-}
-return 0;
-};
-var _5=function(){
-q=[];
-var e=_2.getIterator();
-while(!e.atEnd()){
-q.push(e.get());
-}
-q.sort(_4);
-};
-var _6={};
-this.count=q.length;
-this.add=function(k,v){
-if(!_3[k]){
-_3[k]=new dojox.collections.DictionaryEntry(k,v);
-this.count=q.push(_3[k]);
-q.sort(_4);
-}
-};
-this.clear=function(){
-_3={};
-q=[];
-this.count=q.length;
-};
-this.clone=function(){
-return new dojox.collections.SortedList(this);
-};
-this.contains=this.containsKey=function(k){
-if(_6[k]){
-return false;
-}
-return (_3[k]!=null);
-};
-this.containsValue=function(o){
-var e=this.getIterator();
-while(!e.atEnd()){
-var _7=e.get();
-if(_7.value==o){
-return true;
-}
-}
-return false;
-};
-this.copyTo=function(_8,i){
-var e=this.getIterator();
-var _9=i;
-while(!e.atEnd()){
-_8.splice(_9,0,e.get());
-_9++;
-}
-};
-this.entry=function(k){
-return _3[k];
-};
-this.forEach=function(fn,_a){
-dojo.forEach(q,fn,_a);
-};
-this.getByIndex=function(i){
-return q[i].valueOf();
-};
-this.getIterator=function(){
-return new dojox.collections.DictionaryIterator(_3);
-};
-this.getKey=function(i){
-return q[i].key;
-};
-this.getKeyList=function(){
-var _b=[];
-var e=this.getIterator();
-while(!e.atEnd()){
-_b.push(e.get().key);
-}
-return _b;
-};
-this.getValueList=function(){
-var _c=[];
-var e=this.getIterator();
-while(!e.atEnd()){
-_c.push(e.get().value);
-}
-return _c;
-};
-this.indexOfKey=function(k){
-for(var i=0;i<q.length;i++){
-if(q[i].key==k){
-return i;
-}
-}
-return -1;
-};
-this.indexOfValue=function(o){
-for(var i=0;i<q.length;i++){
-if(q[i].value==o){
-return i;
-}
-}
-return -1;
-};
-this.item=function(k){
-if(k in _3&&!_6[k]){
-return _3[k].valueOf();
-}
-return undefined;
-};
-this.remove=function(k){
-delete _3[k];
-_5();
-this.count=q.length;
-};
-this.removeAt=function(i){
-delete _3[q[i].key];
-_5();
-this.count=q.length;
-};
-this.replace=function(k,v){
-if(!_3[k]){
-this.add(k,v);
-return false;
-}else{
-_3[k]=new dojox.collections.DictionaryEntry(k,v);
-_5();
-return true;
-}
-};
-this.setByIndex=function(i,o){
-_3[q[i].key].value=o;
-_5();
-this.count=q.length;
-};
-if(_1){
-var e=_1.getIterator();
-while(!e.atEnd()){
-var _d=e.get();
-q[q.length]=_3[_d.key]=new dojox.collections.DictionaryEntry(_d.key,_d.value);
-}
-q.sort(_4);
-}
-};
+
+dojox.collections.SortedList=function(/* object? */ dictionary){
+	//	summary
+	//	creates a collection that acts like a dictionary but is also internally sorted.
+	//	Note that the act of adding any elements forces an internal resort, making this object potentially slow.
+	var _this=this;
+	var items={};
+	var q=[];
+	var sorter=function(a,b){
+		if (a.key > b.key) return 1;
+		if (a.key < b.key) return -1;
+		return 0;
+	};
+	var build=function(){
+		q=[];
+		var e=_this.getIterator();
+		while (!e.atEnd()){
+			q.push(e.get());
+		}
+		q.sort(sorter);
+	};
+	var testObject={};
+
+	this.count=q.length;
+	this.add=function(/* string */ k,/* object */v){
+		//	summary
+		//	add the passed value to the dictionary at location k
+		if (!items[k]) {
+			items[k]=new dojox.collections.DictionaryEntry(k,v);
+			this.count=q.push(items[k]);
+			q.sort(sorter);
+		}
+	};
+	this.clear=function(){
+		//	summary
+		//	clear the internal collections
+		items={};
+		q=[];
+		this.count=q.length;
+	};
+	this.clone=function(){
+		//	summary
+		//	create a clone of this sorted list
+		return new dojox.collections.SortedList(this);	//	dojox.collections.SortedList
+	};
+	this.contains=this.containsKey=function(/* string */ k){
+		//	summary
+		//	Check to see if the list has a location k
+		if(testObject[k]){
+			return false;			//	bool
+		}
+		return (items[k]!=null);	//	bool
+	};
+	this.containsValue=function(/* object */ o){
+		//	summary
+		//	Check to see if this list contains the passed object
+		var e=this.getIterator();
+		while (!e.atEnd()){
+			var item=e.get();
+			if(item.value==o){ 
+				return true;	//	bool
+			}
+		}
+		return false;	//	bool
+	};
+	this.copyTo=function(/* array */ arr, /* int */ i){
+		//	summary
+		//	copy the contents of the list into array arr at index i
+		var e=this.getIterator();
+		var idx=i;
+		while(!e.atEnd()){
+			arr.splice(idx,0,e.get());
+			idx++;
+		}
+	};
+	this.entry=function(/* string */ k){
+		//	summary
+		//	return the object at location k
+		return items[k];	//	dojox.collections.DictionaryEntry
+	};
+	this.forEach=function(/* function */ fn, /* object? */ scope){
+		//	summary
+		//	functional iterator, following the mozilla spec.
+		dojo.forEach(q, fn, scope);
+	};
+	this.getByIndex=function(/* int */ i){
+		//	summary
+		//	return the item at index i
+		return q[i].valueOf();	//	object
+	};
+	this.getIterator=function(){
+		//	summary
+		//	get an iterator for this object
+		return new dojox.collections.DictionaryIterator(items);	//	dojox.collections.DictionaryIterator
+	};
+	this.getKey=function(/* int */ i){
+		//	summary
+		//	return the key of the item at index i
+		return q[i].key;
+	};
+	this.getKeyList=function(){
+		//	summary
+		//	return an array of the keys set in this list
+		var arr=[];
+		var e=this.getIterator();
+		while (!e.atEnd()){
+			arr.push(e.get().key);
+		}
+		return arr;	//	array
+	};
+	this.getValueList=function(){
+		//	summary
+		//	return an array of values in this list
+		var arr=[];
+		var e=this.getIterator();
+		while (!e.atEnd()){
+			arr.push(e.get().value);
+		}
+		return arr;	//	array
+	};
+	this.indexOfKey=function(/* string */ k){
+		//	summary
+		//	return the index of the passed key.
+		for (var i=0; i<q.length; i++){
+			if (q[i].key==k){
+				return i;	//	int
+			}
+		}
+		return -1;	//	int
+	};
+	this.indexOfValue=function(/* object */ o){
+		//	summary
+		//	return the first index of object o
+		for (var i=0; i<q.length; i++){
+			if (q[i].value==o){
+				return i;	//	int
+			}
+		}
+		return -1;	//	int
+	};
+	this.item=function(/* string */ k){
+		// 	summary
+		//	return the value of the object at location k.
+		if(k in items && !testObject[k]){
+			return items[k].valueOf();	//	object
+		}
+		return undefined;	//	object
+	};
+	this.remove=function(/* string */k){
+		// 	summary
+		//	remove the item at location k and rebuild the internal collections.
+		delete items[k];
+		build();
+		this.count=q.length;
+	};
+	this.removeAt=function(/* int */ i){
+		//	summary
+		//	remove the item at index i, and rebuild the internal collections.
+		delete items[q[i].key];
+		build();
+		this.count=q.length;
+	};
+	this.replace=function(/* string */ k, /* object */ v){
+		//	summary
+		//	Replace an existing item if it's there, and add a new one if not.
+		if (!items[k]){
+			//	we're adding a new object, return false
+			this.add(k,v);
+			return false; // bool
+		}else{
+			//	we're replacing an object, return true
+			items[k]=new dojox.collections.DictionaryEntry(k,v);
+			build();
+			return true; // bool
+		}
+	};
+	this.setByIndex=function(/* int */ i, /* object */ o){
+		//	summary
+		//	set an item by index
+		items[q[i].key].value=o;
+		build();
+		this.count=q.length;
+	};
+	if (dictionary){
+		var e=dictionary.getIterator();
+		while (!e.atEnd()){
+			var item=e.get();
+			q[q.length]=items[item.key]=new dojox.collections.DictionaryEntry(item.key,item.value);
+		}
+		q.sort(sorter);
+	}
 }
diff --git a/dojox/collections/Stack.js b/dojox/collections/Stack.js
index 91f949b..447c394 100644
--- a/dojox/collections/Stack.js
+++ b/dojox/collections/Stack.js
@@ -1,57 +1,68 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.collections.Stack"]){
-dojo._hasResource["dojox.collections.Stack"]=true;
 dojo.provide("dojox.collections.Stack");
 dojo.require("dojox.collections._base");
-dojox.collections.Stack=function(_1){
-var q=[];
-if(_1){
-q=q.concat(_1);
-}
-this.count=q.length;
-this.clear=function(){
-q=[];
-this.count=q.length;
-};
-this.clone=function(){
-return new dojox.collections.Stack(q);
-};
-this.contains=function(o){
-for(var i=0;i<q.length;i++){
-if(q[i]==o){
-return true;
-}
-}
-return false;
-};
-this.copyTo=function(_2,i){
-_2.splice(i,0,q);
-};
-this.forEach=function(fn,_3){
-dojo.forEach(q,fn,_3);
-};
-this.getIterator=function(){
-return new dojox.collections.Iterator(q);
-};
-this.peek=function(){
-return q[(q.length-1)];
-};
-this.pop=function(){
-var r=q.pop();
-this.count=q.length;
-return r;
-};
-this.push=function(o){
-this.count=q.push(o);
-};
-this.toArray=function(){
-return [].concat(q);
-};
-};
+
+dojox.collections.Stack=function(/* array? */arr){
+	//	summary
+	//	returns an object of type dojox.collections.Stack
+	var q=[];
+	if (arr) q=q.concat(arr);
+	this.count=q.length;
+	this.clear=function(){
+		//	summary
+		//	Clear the internal array and reset the count
+		q=[];
+		this.count=q.length;
+	};
+	this.clone=function(){
+		//	summary
+		//	Create and return a clone of this Stack
+		return new dojox.collections.Stack(q);
+	};
+	this.contains=function(/* object */o){
+		//	summary
+		//	check to see if the stack contains object o
+		for (var i=0; i<q.length; i++){
+			if (q[i] == o){
+				return true;	//	bool
+			}
+		}
+		return false;	//	bool
+	};
+	this.copyTo=function(/* array */ arr, /* int */ i){
+		//	summary
+		//	copy the stack into array arr at index i
+		arr.splice(i,0,q);
+	};
+	this.forEach=function(/* function */ fn, /* object? */ scope){
+		//	summary
+		//	functional iterator, following the mozilla spec.
+		dojo.forEach(q, fn, scope);
+	};
+	this.getIterator=function(){
+		//	summary
+		//	get an iterator for this collection
+		return new dojox.collections.Iterator(q);	//	dojox.collections.Iterator
+	};
+	this.peek=function(){
+		//	summary
+		//	Return the next item without altering the stack itself.
+		return q[(q.length-1)];	//	object
+	};
+	this.pop=function(){
+		//	summary
+		//	pop and return the next item on the stack
+		var r=q.pop();
+		this.count=q.length;
+		return r;	//	object
+	};
+	this.push=function(/* object */ o){
+		//	summary
+		//	Push object o onto the stack
+		this.count=q.push(o);
+	};
+	this.toArray=function(){
+		//	summary
+		//	create and return an array based on the internal collection
+		return [].concat(q);	//	array
+	};
 }
diff --git a/dojox/collections/_base.js b/dojox/collections/_base.js
index e2e6405..47e24ec 100644
--- a/dojox/collections/_base.js
+++ b/dojox/collections/_base.js
@@ -1,71 +1,96 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.collections._base"]){
-dojo._hasResource["dojox.collections._base"]=true;
 dojo.provide("dojox.collections._base");
-dojox.collections.DictionaryEntry=function(k,v){
-this.key=k;
-this.value=v;
-this.valueOf=function(){
-return this.value;
-};
-this.toString=function(){
-return String(this.value);
-};
-};
-dojox.collections.Iterator=function(_1){
-var a=_1;
-var _2=0;
-this.element=a[_2]||null;
-this.atEnd=function(){
-return (_2>=a.length);
-};
-this.get=function(){
-if(this.atEnd()){
-return null;
-}
-this.element=a[_2++];
-return this.element;
-};
-this.map=function(fn,_3){
-return dojo.map(a,fn,_3);
-};
-this.reset=function(){
-_2=0;
-this.element=a[_2];
-};
-};
-dojox.collections.DictionaryIterator=function(_4){
-var a=[];
-var _5={};
-for(var p in _4){
-if(!_5[p]){
-a.push(_4[p]);
-}
+
+dojox.collections.DictionaryEntry=function(/* string */k, /* object */v){
+	//	summary
+	//	return an object of type dojox.collections.DictionaryEntry
+	this.key=k;
+	this.value=v;
+	this.valueOf=function(){ 
+		return this.value; 	//	object
+	};
+	this.toString=function(){ 
+		return String(this.value);	//	string 
+	};
 }
-var _6=0;
-this.element=a[_6]||null;
-this.atEnd=function(){
-return (_6>=a.length);
-};
-this.get=function(){
-if(this.atEnd()){
-return null;
+
+/*	Iterators
+ *	The collections.Iterators (Iterator and DictionaryIterator) are built to
+ *	work with the Collections included in this module.  However, they *can*
+ *	be used with arrays and objects, respectively, should one choose to do so.
+ */
+dojox.collections.Iterator=function(/* array */arr){
+	//	summary
+	//	return an object of type dojox.collections.Iterator
+	var a=arr;
+	var position=0;
+	this.element=a[position]||null;
+	this.atEnd=function(){
+		//	summary
+		//	Test to see if the internal cursor has reached the end of the internal collection.
+		return (position>=a.length);	//	bool
+	};
+	this.get=function(){
+		//	summary
+		//	Get the next member in the collection.
+		if(this.atEnd()){
+			return null;		//	object
+		}
+		this.element=a[position++];
+		return this.element;	//	object
+	};
+	this.map=function(/* function */fn, /* object? */scope){
+		//	summary
+		//	Functional iteration with optional scope.
+		return dojo.map(a, fn, scope);
+	};
+	this.reset=function(){
+		//	summary
+		//	reset the internal cursor.
+		position=0;
+		this.element=a[position];
+	};
 }
-this.element=a[_6++];
-return this.element;
-};
-this.map=function(fn,_7){
-return dojo.map(a,fn,_7);
-};
-this.reset=function(){
-_6=0;
-this.element=a[_6];
-};
+
+/*	Notes:
+ *	The DictionaryIterator no longer supports a key and value property;
+ *	the reality is that you can use this to iterate over a JS object
+ *	being used as a hashtable.
+ */
+dojox.collections.DictionaryIterator=function(/* object */obj){
+	//	summary
+	//	return an object of type dojox.collections.DictionaryIterator
+	var a=[];	//	Create an indexing array
+	var testObject={};
+	for(var p in obj){
+		if(!testObject[p]){
+			a.push(obj[p]);	//	fill it up
+		}
+	}
+	var position=0;
+	this.element=a[position]||null;
+	this.atEnd=function(){
+		//	summary
+		//	Test to see if the internal cursor has reached the end of the internal collection.
+		return (position>=a.length);	//	bool
+	};
+	this.get=function(){
+		//	summary
+		//	Get the next member in the collection.
+		if(this.atEnd()){
+			return null;		//	object
+		}
+		this.element=a[position++];
+		return this.element;	//	object
+	};
+	this.map=function(/* function */fn, /* object? */scope){
+		//	summary
+		//	Functional iteration with optional scope.
+		return dojo.map(a, fn, scope);
+	};
+	this.reset=function() { 
+		//	summary
+		//	reset the internal cursor.
+		position=0; 
+		this.element=a[position];
+	};
 };
-}
diff --git a/dojox/collections/tests/ArrayList.js b/dojox/collections/tests/ArrayList.js
new file mode 100644
index 0000000..444e07a
--- /dev/null
+++ b/dojox/collections/tests/ArrayList.js
@@ -0,0 +1,79 @@
+dojo.provide("dojox.collections.tests.ArrayList");
+dojo.require("dojox.collections.ArrayList");
+
+tests.register("dojox.collections.tests.ArrayList", [
+	function testCtor(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		t.assertEqual(4, al.count);
+	},
+	function testAdd(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		al.add("carp");
+		t.assertEqual("foo,bar,test,bull,carp", al.toString());
+		al.addRange(["oof","rab"]);
+		t.assertEqual("foo,bar,test,bull,carp,oof,rab", al.toString());
+	},
+	function testClear(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		al.clear();
+		t.assertEqual(0, al.count);
+	},
+	function testClone(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		var cloned=al.clone();
+		t.assertEqual(al.toString(), cloned.toString());
+	},
+	function testContains(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		t.assertTrue(al.contains("bar"));
+		t.assertFalse(al.contains("faz"));
+	},
+	function testGetIterator(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		var itr=al.getIterator();
+		while(!itr.atEnd()){
+			itr.get();
+		}
+		t.assertEqual("bull", itr.element);
+	},
+	function testIndexOf(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		t.assertEqual(1, al.indexOf("bar"));
+	},
+	function testInsert(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		al.insert(2, "baz");
+		t.assertEqual(2, al.indexOf("baz"));
+	},
+	function testItem(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		t.assertEqual("test", al.item(2));
+	},
+	function testRemove(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		al.remove("bar");
+		t.assertEqual("foo,test,bull", al.toString());
+		t.assertEqual(3, al.count);
+	},
+	function testRemoveAt(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		al.removeAt(3);
+		t.assertEqual("foo,bar,test", al.toString());
+		t.assertEqual(3, al.count);
+	},
+	function testReverse(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		al.reverse();
+		t.assertEqual("bull,test,bar,foo", al.toString());
+	},
+	function testSort(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		al.sort();
+		t.assertEqual("bar,bull,foo,test", al.toString());
+	},
+	function testToArray(t){
+		var al=new dojox.collections.ArrayList(["foo","bar","test","bull"]);
+		var a=al.toArray();
+		t.assertEqual(a.join(","), al.toString());
+	}
+]);
diff --git a/dojox/collections/tests/BinaryTree.js b/dojox/collections/tests/BinaryTree.js
new file mode 100644
index 0000000..eeb2c0d
--- /dev/null
+++ b/dojox/collections/tests/BinaryTree.js
@@ -0,0 +1,79 @@
+dojo.provide("dojox.collections.tests.BinaryTree");
+dojo.require("dojox.collections.BinaryTree");
+
+tests.register("dojox.collections.tests.BinaryTree", [
+	function testCtor(t){
+		var bt=new dojox.collections.BinaryTree("foo");
+		t.assertTrue(bt instanceof dojox.collections.BinaryTree);
+	},
+	function testAdd(t){
+		var bt=new dojox.collections.BinaryTree("foo");
+		bt.add("bar");
+		bt.add("baz");
+		bt.add("buck");
+		bt.add("shot");
+		bt.add("apple");
+		t.assertEqual("apple,bar,baz,buck,foo,shot",bt.toString());
+	},
+	function testClear(t){
+		var bt=new dojox.collections.BinaryTree("foo");
+		bt.add("bar");
+		bt.add("baz");
+		bt.add("buck");
+		bt.add("shot");
+		bt.add("apple");
+		bt.clear();
+		t.assertEqual(bt.count, 0);
+	},
+	function testClone(t){
+		var bt=new dojox.collections.BinaryTree("foo");
+		bt.add("bar");
+		bt.add("baz");
+		bt.add("buck");
+		bt.add("shot");
+		bt.add("apple");
+		var bt2=bt.clone();
+		t.assertEqual(bt2.count, 6);
+		t.assertEqual(bt.toString(), bt2.toString());
+	},
+	function testContains(t){
+		var bt=new dojox.collections.BinaryTree("foo");
+		bt.add("bar");
+		bt.add("baz");
+		bt.add("buck");
+		bt.add("shot");
+		bt.add("apple");
+		t.assertTrue(bt.contains("buck"));
+		t.assertFalse(bt.contains("duck"));
+	},
+	function testDeleteData(t){
+		var bt=new dojox.collections.BinaryTree("foo");
+		bt.add("bar");
+		bt.add("baz");
+		bt.add("buck");
+		bt.add("shot");
+		bt.add("apple");
+		bt.deleteData("buck");
+		t.assertEqual("apple,bar,baz,foo,shot",bt.toString());
+	},
+	function testGetIterator(t){
+		var bt=new dojox.collections.BinaryTree("foo");
+		bt.add("bar");
+		bt.add("baz");
+		bt.add("buck");
+		bt.add("shot");
+		bt.add("apple");
+		var itr=bt.getIterator();
+		while(!itr.atEnd()){ itr.get(); }
+		t.assertEqual("shot", itr.element);
+	},
+	function testSearch(t){
+		var bt=new dojox.collections.BinaryTree("foo");
+		bt.add("bar");
+		bt.add("baz");
+		bt.add("buck");
+		bt.add("shot");
+		bt.add("apple");
+		t.assertEqual("buck", bt.search("buck").value);
+	}
+]);
diff --git a/dojox/collections/tests/Dictionary.js b/dojox/collections/tests/Dictionary.js
new file mode 100644
index 0000000..cc0303b
--- /dev/null
+++ b/dojox/collections/tests/Dictionary.js
@@ -0,0 +1,78 @@
+dojo.provide("dojox.collections.tests.Dictionary");
+dojo.require("dojox.collections.Dictionary");
+
+tests.register("dojox.collections.tests.Dictionary", [
+	function testCtor(t){
+		var d=new dojox.collections.Dictionary();
+		t.assertTrue(d instanceof dojox.collections.Dictionary);
+	},
+	function testAdd(t){
+		var d=new dojox.collections.Dictionary();
+		d.add("foo","bar");
+		t.assertEqual("bar", d.item("foo").valueOf());
+	},
+	function testClear(t){
+		var d=new dojox.collections.Dictionary();
+		d.add("foo","bar");
+		d.clear()
+		t.assertEqual(0, d.count);
+	},
+	function testClone(t){
+		var d=new dojox.collections.Dictionary();
+		d.add("baz","fab");
+		d.add("buck","shot");
+		d.add("apple","orange");
+		var d2 = d.clone();
+		t.assertTrue(d2.contains("baz"));
+	},
+	function testContains(t){
+		var d=new dojox.collections.Dictionary();
+		d.add("foo","bar");
+		d.add("baz","fab");
+		d.add("buck","shot");
+		d.add("apple","orange");
+		t.assertTrue(d.contains("baz"));
+	},
+	function testContainsKey(t){
+		var d=new dojox.collections.Dictionary();
+		d.add("foo","bar");
+		d.add("baz","fab");
+		d.add("buck","shot");
+		d.add("apple","orange");
+		t.assertTrue(d.containsKey("buck"));
+	},
+	function testContainsValue(t){
+		var d=new dojox.collections.Dictionary();
+		d.add("foo","bar");
+		d.add("baz","fab");
+		d.add("buck","shot");
+		d.add("apple","orange");
+		t.assertTrue(d.containsValue("shot"));
+	},
+	function testGetKeyList(t){
+		var d=new dojox.collections.Dictionary();
+		d.add("foo","bar");
+		d.add("baz","fab");
+		d.add("buck","shot");
+		d.add("apple","orange");
+		t.assertEqual("foo,baz,buck,apple", d.getKeyList().join(","));
+	},
+	function testGetValueList(t){
+		var d=new dojox.collections.Dictionary();
+		d.add("foo","bar");
+		d.add("baz","fab");
+		d.add("buck","shot");
+		d.add("apple","orange");
+		t.assertEqual("bar,fab,shot,orange", d.getValueList().join(","));
+	},
+	function testRemove(t){
+		var d=new dojox.collections.Dictionary();
+		d.add("foo","bar");
+		d.add("baz","fab");
+		d.add("buck","shot");
+		d.add("apple","orange");
+		d.remove("baz");
+		t.assertEqual(3, d.count);
+		t.assertEqual(undefined, d.item("baz"));
+	}
+]);
diff --git a/dojox/collections/tests/Queue.js b/dojox/collections/tests/Queue.js
new file mode 100644
index 0000000..2880f8d
--- /dev/null
+++ b/dojox/collections/tests/Queue.js
@@ -0,0 +1,45 @@
+dojo.provide("dojox.collections.tests.Queue");
+dojo.require("dojox.collections.Queue");
+
+tests.register("dojox.collections.tests.Queue", [
+	function testCtor(t){
+		var q=new dojox.collections.Queue(["foo","bar","test","bull"]);
+		t.assertEqual(4, q.count);
+	},
+	function testClear(t){
+		var q=new dojox.collections.Queue(["foo","bar","test","bull"]);
+		q.clear();
+		t.assertEqual(0, q.count);
+	},
+	function testClone(t){
+		var q=new dojox.collections.Queue(["foo","bar","test","bull"]);
+		var cloned=q.clone();
+		t.assertEqual(q.count, cloned.count);
+		t.assertEqual(q.toArray().join(), cloned.toArray().join());
+	},
+	function testContains(t){
+		var q=new dojox.collections.Queue(["foo","bar","test","bull"]);
+		t.assertTrue(q.contains("bar"));
+		t.assertFalse(q.contains("faz"));
+	},
+	function testGetIterator(t){
+		var q=new dojox.collections.Queue(["foo","bar","test","bull"]);
+		var itr=q.getIterator();
+		while(!itr.atEnd()){ itr.get(); }
+		t.assertEqual("bull", itr.element);
+	},
+	function testPeek(t){
+		var q=new dojox.collections.Queue(["foo","bar","test","bull"]);
+		t.assertEqual("foo", q.peek());
+	},
+	function testDequeue(t){
+		var q=new dojox.collections.Queue(["foo","bar","test","bull"]);
+		t.assertEqual("foo", q.dequeue());
+		t.assertEqual("bar,test,bull", q.toArray().join(","));
+	},
+	function testEnqueue(t){
+		var q=new dojox.collections.Queue(["foo","bar","test","bull"]);
+		q.enqueue("bull");
+		t.assertEqual("bull", q.toArray().pop());
+	}
+]);
diff --git a/dojox/collections/tests/Set.js b/dojox/collections/tests/Set.js
new file mode 100644
index 0000000..cbc9ed8
--- /dev/null
+++ b/dojox/collections/tests/Set.js
@@ -0,0 +1,31 @@
+dojo.provide("dojox.collections.tests.Set");
+dojo.require("dojox.collections.Set");
+
+(function(){
+	var dxcs=dojox.collections.Set;
+	var a = ["apple","bear","candy","donut","epiphite","frank"];
+	var b = ["bear","epiphite","google","happy","joy"];
+	tests.register("dojox.collections.tests.Set", [
+		function testUnion(t){
+			var union=dxcs.union(a,b);
+			t.assertEqual("apple,bear,candy,donut,epiphite,frank,google,happy,joy", union.toArray().join(','));
+		},
+		function testIntersection(t){
+			var itsn=dxcs.intersection(a,b);
+			t.assertEqual("bear,epiphite", itsn.toArray().join(","));
+			t.assertEqual("bear", dxcs.intersection(["bear","apple"], ["bear"]));
+		},
+		function testDifference(t){
+			var d=dxcs.difference(a,b);
+			t.assertEqual("apple,candy,donut,frank",d.toArray().join(','));
+		},
+		function testIsSubSet(t){
+			t.assertFalse(dxcs.isSubSet(a,["bear","candy"]));
+			t.assertTrue(dxcs.isSubSet(["bear","candy"],a));
+		},
+		function testIsSuperSet(t){
+			t.assertTrue(dxcs.isSuperSet(a,["bear","candy"]));
+			t.assertFalse(dxcs.isSuperSet(["bear","candy"],a));
+		}
+	]);
+})();
diff --git a/dojox/collections/tests/SortedList.js b/dojox/collections/tests/SortedList.js
new file mode 100644
index 0000000..c5c3865
--- /dev/null
+++ b/dojox/collections/tests/SortedList.js
@@ -0,0 +1,164 @@
+dojo.provide("dojox.collections.tests.SortedList");
+dojo.require("dojox.collections.SortedList");
+
+tests.register("dojox.collections.tests.SortedList", [
+	function testCtor(t){
+		var sl=new dojox.collections.SortedList();
+		t.assertTrue(sl instanceof dojox.collections.SortedList);
+	},
+	function testAdd(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		t.assertEqual("bar", sl.item("foo").valueOf());
+	},
+	function testClear(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.clear();
+		t.assertEqual(0, sl.count);
+	},
+	function testClone(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		var sl2=sl.clone();
+		t.assertTrue(sl2.contains("baz"));
+	},
+	function testContains(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		t.assertTrue(sl.contains("baz"));
+		t.assertFalse(sl.contains("faz"));
+	},
+	function testContainsKey(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		t.assertTrue(sl.containsKey("buck"));
+		t.assertFalse(sl.containsKey("faz"));
+	},
+	function testContainsValue(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		t.assertTrue(sl.containsValue("shot"));
+		t.assertFalse(sl.containsValue("faz"));
+	},
+	function testGetKeyList(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		t.assertEqual("foo,baz,buck,apple",sl.getKeyList().join(','));
+	},
+	function testGetValueList(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		t.assertEqual("bar,fab,shot,orange",sl.getValueList().join(','));
+	},
+	function testCopyTo(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		var arr=["bek"];
+		sl.copyTo(arr,0);
+		t.assertEqual("bar,fab,shot,orange,bek", arr.join(','));
+	},
+	function testGetByIndex(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		t.assertEqual("shot", sl.getByIndex(2));
+	},
+	function testGetKey(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		t.assertEqual("apple", sl.getKey(0));
+	},
+	function testIndexOfKey(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		t.assertEqual(0, sl.indexOfKey("apple"));
+	},
+	function testIndexOfValue(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		t.assertEqual(3, sl.indexOfValue("bar"));
+	},
+	function testRemove(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		sl.remove("baz");
+		t.assertEqual(3, sl.count);
+		t.assertEqual(undefined, sl.item("baz"));
+	},
+	function testRemoveAt(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		sl.removeAt(2);
+		t.assertEqual(undefined, sl.item("buck"));
+	},
+	function testReplace(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		sl.replace("buck","dollar");
+		t.assertEqual(sl.item("buck").valueOf(), "dollar");
+	},
+	function testSetByIndex(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+		sl.setByIndex(0, "bar");
+		t.assertEqual("bar", sl.getByIndex(0));
+	},
+	function testSorting(t){
+		var sl=new dojox.collections.SortedList();
+		sl.add("foo","bar");
+		sl.add("baz","fab");
+		sl.add("buck","shot");
+		sl.add("apple","orange");
+
+		var a=[];
+		sl.forEach(function(item){
+			a.push(item);
+		});
+		t.assertEqual("orange,fab,shot,bar", a.join());
+	}
+]);
diff --git a/dojox/collections/tests/Stack.js b/dojox/collections/tests/Stack.js
new file mode 100644
index 0000000..b600941
--- /dev/null
+++ b/dojox/collections/tests/Stack.js
@@ -0,0 +1,45 @@
+dojo.provide("dojox.collections.tests.Stack");
+dojo.require("dojox.collections.Stack");
+
+tests.register("dojox.collections.tests.Stack", [
+	function testCtor(t){
+		var s=new dojox.collections.Stack(["foo","bar","test","bull"]);
+		t.assertEqual(4, s.count);
+	},
+	function testClear(t){
+		var s=new dojox.collections.Stack(["foo","bar","test","bull"]);
+		s.clear();
+		t.assertEqual(0, s.count);
+	},
+	function testClone(t){
+		var s=new dojox.collections.Stack(["foo","bar","test","bull"]);
+		var cloned=s.clone();
+		t.assertEqual(s.count, cloned.count);
+		t.assertEqual(s.toArray().join(), cloned.toArray().join());
+	},
+	function testContains(t){
+		var s=new dojox.collections.Stack(["foo","bar","test","bull"]);
+		t.assertTrue(s.contains("bar"));
+		t.assertFalse(s.contains("faz"));
+	},
+	function testGetIterator(t){
+		var s=new dojox.collections.Stack(["foo","bar","test","bull"]);
+		var itr=s.getIterator();
+		while(!itr.atEnd()){ itr.get(); }
+		t.assertEqual("bull", itr.element);
+	},
+	function testPeek(t){
+		var s=new dojox.collections.Stack(["foo","bar","test","bull"]);
+		t.assertEqual("bull", s.peek());
+	},
+	function testPop(t){
+		var s=new dojox.collections.Stack(["foo","bar","test","bull"]);
+		t.assertEqual("bull", s.pop());
+		t.assertEqual("test", s.pop());
+	},
+	function testPush(t){
+		var s=new dojox.collections.Stack(["foo","bar","test","bull"]);
+		s.push("bug");
+		t.assertEqual("bug", s.peek());
+	}
+]);
diff --git a/dojox/collections/tests/_base.js b/dojox/collections/tests/_base.js
new file mode 100644
index 0000000..da760c9
--- /dev/null
+++ b/dojox/collections/tests/_base.js
@@ -0,0 +1,80 @@
+dojo.provide("dojox.collections.tests._base");
+dojo.require("dojox.collections");
+
+tests.register("dojox.collections.tests._base", [
+	function testDictionaryEntry(t){
+		var d=new dojox.collections.DictionaryEntry("foo","bar");
+		t.assertEqual("bar", d.valueOf());
+		t.assertEqual("bar", d.toString());
+	},
+
+	function testIterator(t){
+		var itr=new dojox.collections.Iterator(["foo","bar","baz","zoo"]);
+		t.assertEqual("foo", itr.element);	//	test initialization
+		t.assertTrue(!itr.atEnd());
+		t.assertEqual("foo", itr.get());	//	make sure the first get doesn't advance.
+		t.assertEqual("bar", itr.get());
+		t.assertEqual("baz", itr.get());
+		t.assertEqual("zoo", itr.get());
+		t.assertTrue(itr.atEnd());
+		t.assertEqual(null, itr.get());
+
+		itr.reset();
+		t.assertTrue(!itr.atEnd());
+		t.assertEqual("foo", itr.element);
+
+		//	test map
+		var a=itr.map(function(elm){
+			return elm+"-mapped";
+		});
+		itr=new dojox.collections.Iterator(a);
+		t.assertEqual("foo-mapped", itr.element);	//	test initialization
+		t.assertTrue(!itr.atEnd());
+		t.assertEqual("foo-mapped", itr.get());	//	make sure the first get doesn't advance.
+		t.assertEqual("bar-mapped", itr.get());
+		t.assertEqual("baz-mapped", itr.get());
+		t.assertEqual("zoo-mapped", itr.get());
+		t.assertTrue(itr.atEnd());
+		t.assertEqual(null, itr.get());
+	},
+
+	function testDictionaryIterator(t){
+		/*
+			in the context of any of the Dictionary-based collections, the
+			element would normally return a DictionaryEntry.  However, since
+			the DictionaryIterator is really an iterator of pure objects,
+			we will just test with an object here.  This means all property
+			names are lost in the translation, but...that's why there's a
+			DictionaryEntry object :)
+		*/
+		var itr=new dojox.collections.DictionaryIterator({
+			first:"foo", second:"bar", third:"baz", fourth:"zoo"
+		});
+		t.assertEqual("foo", itr.element);	//	test initialization
+		t.assertTrue(!itr.atEnd());
+		t.assertEqual("foo", itr.get());	//	make sure the first get doesn't advance.
+		t.assertEqual("bar", itr.get());
+		t.assertEqual("baz", itr.get());
+		t.assertEqual("zoo", itr.get());
+		t.assertTrue(itr.atEnd());
+		t.assertEqual(null, itr.get());
+
+		itr.reset();
+		t.assertTrue(!itr.atEnd());
+		t.assertEqual("foo", itr.element);
+
+		//	test map
+		var a=itr.map(function(elm){
+			return elm+"-mapped";
+		});
+		itr=new dojox.collections.Iterator(a);
+		t.assertEqual("foo-mapped", itr.element);	//	test initialization
+		t.assertTrue(!itr.atEnd());
+		t.assertEqual("foo-mapped", itr.get());	//	make sure the first get doesn't advance.
+		t.assertEqual("bar-mapped", itr.get());
+		t.assertEqual("baz-mapped", itr.get());
+		t.assertEqual("zoo-mapped", itr.get());
+		t.assertTrue(itr.atEnd());
+		t.assertEqual(null, itr.get());
+	}
+]);
diff --git a/dojox/collections/tests/collections.js b/dojox/collections/tests/collections.js
new file mode 100644
index 0000000..439794e
--- /dev/null
+++ b/dojox/collections/tests/collections.js
@@ -0,0 +1,15 @@
+dojo.provide("dojox.collections.tests.collections");
+dojo.require("dojox.collections");
+
+try{
+	dojo.require("dojox.collections.tests._base");
+	dojo.require("dojox.collections.tests.ArrayList");
+	dojo.require("dojox.collections.tests.BinaryTree");
+	dojo.require("dojox.collections.tests.Dictionary");
+	dojo.require("dojox.collections.tests.Queue");
+	dojo.require("dojox.collections.tests.Set");
+	dojo.require("dojox.collections.tests.SortedList");
+	dojo.require("dojox.collections.tests.Stack");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/collections/tests/runTests.html b/dojox/collections/tests/runTests.html
new file mode 100644
index 0000000..37f26a6
--- /dev/null
+++ b/dojox/collections/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox.wire Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.collections.tests.collections"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/color.js b/dojox/color.js
index 2af5f8c..db080ec 100644
--- a/dojox/color.js
+++ b/dojox/color.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.color"]){
-dojo._hasResource["dojox.color"]=true;
 dojo.provide("dojox.color");
 dojo.require("dojox.color._base");
-}
diff --git a/dojox/color/Colorspace.js b/dojox/color/Colorspace.js
index 931d126..1295013 100644
--- a/dojox/color/Colorspace.js
+++ b/dojox/color/Colorspace.js
@@ -1,472 +1,552 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.color.Colorspace"]){
-dojo._hasResource["dojox.color.Colorspace"]=true;
 dojo.provide("dojox.color.Colorspace");
 dojo.require("dojox.math.matrix");
+
 dojox.color.Colorspace=new (function(){
-var _1=dojox.color;
-var _2=dojox.math.matrix;
-var _3=this;
-var _4={"2":{"E":{x:1/3,y:1/3,t:5400},"D50":{x:0.34567,y:0.3585,t:5000},"D55":{x:0.33242,y:0.34743,t:5500},"D65":{x:0.31271,y:0.32902,t:6500},"D75":{x:0.29902,y:0.31485,t:7500},"A":{x:0.44757,y:0.40745,t:2856},"B":{x:0.34842,y:0.35161,t:4874},"C":{x:0.31006,y:0.31616,t:6774},"9300":{x:0.2848,y:0.2932,t:9300},"F2":{x:0.37207,y:0.37512,t:4200},"F7":{x:0.31285,y:0.32918,t:6500},"F11":{x:0.38054,y:0.37691,t:4000}},"10":{"E":{x:1/3,y:1/3,t:5400},"D50":{x:0.34773,y:0.35952,t:5000},"D55":{x:0.3 [...]
-var _5={"Adobe RGB 98":[2.2,"D65",0.64,0.33,0.297361,0.21,0.71,0.627355,0.15,0.06,0.075285],"Apple RGB":[1.8,"D65",0.625,0.34,0.244634,0.28,0.595,0.672034,0.155,0.07,0.083332],"Best RGB":[2.2,"D50",0.7347,0.2653,0.228457,0.215,0.775,0.737352,0.13,0.035,0.034191],"Beta RGB":[2.2,"D50",0.6888,0.3112,0.303273,0.1986,0.7551,0.663786,0.1265,0.0352,0.032941],"Bruce RGB":[2.2,"D65",0.64,0.33,0.240995,0.28,0.65,0.683554,0.15,0.06,0.075452],"CIE RGB":[2.2,"E",0.735,0.265,0.176204,0.274,0.717,0.81 [...]
-var _6={"XYZ scaling":{ma:[[1,0,0],[0,1,0],[0,0,1]],mai:[[1,0,0],[0,1,0],[0,0,1]]},"Bradford":{ma:[[0.8951,-0.7502,0.0389],[0.2664,1.7135,-0.0685],[-0.1614,0.0367,1.0296]],mai:[[0.986993,0.432305,-0.008529],[-0.147054,0.51836,0.040043],[0.159963,0.049291,0.968487]]},"Von Kries":{ma:[[0.40024,-0.2263,0],[0.7076,1.16532,0],[-0.08081,0.0457,0.91822]],mai:[[1.859936,0.361191,0],[-1.129382,0.638812,0],[0.219897,-0.000006,1.089064]]}};
-var _7={"XYZ":{"xyY":function(_8,_9){
-_9=dojo.mixin({whitepoint:"D65",observer:"10",useApproximation:true},_9||{});
-var wp=_3.whitepoint(_9.whitepoint,_9.observer);
-var _a=_8.X+_8.Y+_8.Z;
-if(_a==0){
-var x=wp.x,y=wp.y;
-}else{
-var x=_8.X/_a,y=_8.Y/_a;
-}
-return {x:x,y:y,Y:_8.Y};
-},"Lab":function(_b,_c){
-_c=dojo.mixin({whitepoint:"D65",observer:"10",useApproximation:true},_c||{});
-var _d=_3.kappa(_c.useApproximation),_e=_3.epsilon(_c.useApproximation);
-var wp=_3.whitepoint(_c.whitepoint,_c.observer);
-var xr=_b.X/wp.x,yr=_b.Y/wp.y,zr=_b.z/wp.z;
-var fx=(xr>_e)?Math.pow(xr,1/3):(_d*xr+16)/116;
-var fy=(yr>_e)?Math.pow(yr,1/3):(_d*yr+16)/116;
-var fz=(zr>_e)?Math.pow(zr,1/3):(_d*zr+16)/116;
-var L=116*fy-16,a=500*(fx-fy),b=200*(fy-fz);
-return {L:L,a:a,b:b};
-},"Luv":function(_f,_10){
-_10=dojo.mixin({whitepoint:"D65",observer:"10",useApproximation:true},_10||{});
-var _11=_3.kappa(_10.useApproximation),_12=_3.epsilon(_10.useApproximation);
-var wp=_3.whitepoint(_10.whitepoint,_10.observer);
-var ud=(4*_f.X)/(_f.X+15*_f.Y+3*_f.Z);
-var vd=(9*_f.Y)/(_f.X+15*_f.Y+3*_f.Z);
-var udr=(4*wp.x)/(wp.x+15*wp.y+3*wp.z);
-var vdr=(9*wp.y)/(wp.x+15*wp.y+3*wp.z);
-var yr=_f.Y/wp.y;
-var L=(yr>_12)?116*Math.pow(yr,1/3)-16:_11*yr;
-var u=13*L*(ud-udr);
-var v=13*L*(vd-vdr);
-return {L:L,u:u,v:v};
-}},"xyY":{"XYZ":function(xyY){
-if(xyY.y==0){
-var X=0,Y=0,Z=0;
-}else{
-var X=(xyY.x*xyY.Y)/xyY.y;
-var Y=xyY.Y;
-var Z=((1-xyY.x-xyY.y)*xyY.Y)/xyY.y;
-}
-return {X:X,Y:Y,Z:Z};
-}},"Lab":{"XYZ":function(lab,_13){
-_13=dojo.mixin({whitepoint:"D65",observer:"10",useApproximation:true},_13||{});
-var b=_13.useApproximation,_14=_3.kappa(b),_15=_3.epsilon(b);
-var wp=_3.whitepoint(_13.whitepoint,_13.observer);
-var yr=(lab.L>(_14*_15))?Math.pow((lab.L+16)/116,3):lab.L/_14;
-var fy=(yr>_15)?(lab.L+16)/116:(_14*yr+16)/116;
-var fx=(lab.a/500)+fy;
-var fz=fy-(lab.b/200);
-var _16=Math.pow(fx,3),_17=Math.pow(fz,3);
-var xr=(_16>_15)?_16:(116*fx-16)/_14;
-var zr=(_17>_15)?_17:(116*fz-16)/_14;
-return {X:xr*wp.x,Y:yr*wp.y,Z:zr*wp.z};
-},"LCHab":function(lab){
-var L=lab.L,C=Math.pow(lab.a*lab.a+lab.b*lab.b,0.5),H=Math.atan(lab.b,lab.a)*(180/Math.PI);
-if(H<0){
-H+=360;
-}
-if(H<360){
-H-=360;
-}
-return {L:L,C:C,H:H};
-}},"LCHab":{"Lab":function(lch){
-var _18=lch.H*(Math.PI/180),L=lch.L,a=lch.C/Math.pow(Math.pow(Math.tan(_18),2)+1,0.5);
-if(90<lchH&&lch.H<270){
-a=-a;
-}
-var b=Math.pow(Math.pow(lch.C,2)-Math.pow(a,2),0.5);
-if(lch.H>180){
-b=-b;
-}
-return {L:L,a:a,b:b};
-}},"Luv":{"XYZ":function(Luv,_19){
-_19=dojo.mixin({whitepoint:"D65",observer:"10",useApproximation:true},_19||{});
-var b=_19.useApproximation,_1a=_3.kappa(b),_1b=_3.epsilon(b);
-var wp=_3.whitepoint(_19.whitepoint,_19.observer);
-var uz=(4*wp.x)/(wp.x+15*wp.y+3*wp.z);
-var vz=(9*wp.y)/(wp.x+15*wp.y+3*wp.z);
-var Y=(Luv.L>_1a*_1b)?Math.pow((Luv.L+16)/116,3):Luv.L/_1a;
-var a=(1/3)*(((52*Luv.L)/(Luv.u+13*Luv.L*uz))-1);
-var b=-5*Y,c=-(1/3),d=Y*(((39*Luv.L)/(Luv.v+13*Luv.L*vz))-5);
-var X=(d-b)/(a-c),Z=X*a+b;
-return {X:X,Y:Y,Z:Z};
-},"LCHuv":function(Luv){
-var L=Luv.L,C=Math.pow(Luv.u*Luv.u+Luv.v*Luv*v,0.5),H=Math.atan(Luv.v,Luv.u)*(180/Math.PI);
-if(H<0){
-H+=360;
-}
-if(H>360){
-H-=360;
-}
-return {L:L,C:C,H:H};
-}},"LCHuv":{"Luv":function(LCH){
-var _1c=LCH.H*(Math.PI/180);
-var L=LCH.L,u=LCH.C/Math.pow(Math.pow(Math.tan(_1c),2)+1,0.5);
-var v=Math.pow(LCH.C*LCH.C-u*u,0.5);
-if(90<LCH.H&&LCH.H>270){
-u*=-1;
-}
-if(LCH.H>180){
-v*=-1;
-}
-return {L:L,u:u,v:v};
-}}};
-var _1d={"CMY":{"CMYK":function(obj,_1e){
-return _1.fromCmy(obj).toCmyk();
-},"HSL":function(obj,_1f){
-return _1.fromCmy(obj).toHsl();
-},"HSV":function(obj,_20){
-return _1.fromCmy(obj).toHsv();
-},"Lab":function(obj,_21){
-return _7["XYZ"]["Lab"](_1.fromCmy(obj).toXYZ(_21));
-},"LCHab":function(obj,_22){
-return _7["Lab"]["LCHab"](_1d["CMY"]["Lab"](obj));
-},"LCHuv":function(obj,_23){
-return _7["LCHuv"]["Luv"](_7["Luv"]["XYZ"](_1.fromCmy(obj).toXYZ(_23)));
-},"Luv":function(obj,_24){
-return _7["Luv"]["XYZ"](_1.fromCmy(obj).toXYZ(_24));
-},"RGB":function(obj,_25){
-return _1.fromCmy(obj);
-},"XYZ":function(obj,_26){
-return _1.fromCmy(obj).toXYZ(_26);
-},"xyY":function(obj,_27){
-return _7["XYZ"]["xyY"](_1.fromCmy(obj).toXYZ(_27));
-}},"CMYK":{"CMY":function(obj,_28){
-return _1.fromCmyk(obj).toCmy();
-},"HSL":function(obj,_29){
-return _1.fromCmyk(obj).toHsl();
-},"HSV":function(obj,_2a){
-return _1.fromCmyk(obj).toHsv();
-},"Lab":function(obj,_2b){
-return _7["XYZ"]["Lab"](_1.fromCmyk(obj).toXYZ(_2b));
-},"LCHab":function(obj,_2c){
-return _7["Lab"]["LCHab"](_1d["CMYK"]["Lab"](obj));
-},"LCHuv":function(obj,_2d){
-return _7["LCHuv"]["Luv"](_7["Luv"]["XYZ"](_1.fromCmyk(obj).toXYZ(_2d)));
-},"Luv":function(obj,_2e){
-return _7["Luv"]["XYZ"](_1.fromCmyk(obj).toXYZ(_2e));
-},"RGB":function(obj,_2f){
-return _1.fromCmyk(obj);
-},"XYZ":function(obj,_30){
-return _1.fromCmyk(obj).toXYZ(_30);
-},"xyY":function(obj,_31){
-return _7["XYZ"]["xyY"](_1.fromCmyk(obj).toXYZ(_31));
-}},"HSL":{"CMY":function(obj,_32){
-return _1.fromHsl(obj).toCmy();
-},"CMYK":function(obj,_33){
-return _1.fromHsl(obj).toCmyk();
-},"HSV":function(obj,_34){
-return _1.fromHsl(obj).toHsv();
-},"Lab":function(obj,_35){
-return _7["XYZ"]["Lab"](_1.fromHsl(obj).toXYZ(_35));
-},"LCHab":function(obj,_36){
-return _7["Lab"]["LCHab"](_1d["CMYK"]["Lab"](obj));
-},"LCHuv":function(obj,_37){
-return _7["LCHuv"]["Luv"](_7["Luv"]["XYZ"](_1.fromHsl(obj).toXYZ(_37)));
-},"Luv":function(obj,_38){
-return _7["Luv"]["XYZ"](_1.fromHsl(obj).toXYZ(_38));
-},"RGB":function(obj,_39){
-return _1.fromHsl(obj);
-},"XYZ":function(obj,_3a){
-return _1.fromHsl(obj).toXYZ(_3a);
-},"xyY":function(obj,_3b){
-return _7["XYZ"]["xyY"](_1.fromHsl(obj).toXYZ(_3b));
-}},"HSV":{"CMY":function(obj,_3c){
-return _1.fromHsv(obj).toCmy();
-},"CMYK":function(obj,_3d){
-return _1.fromHsv(obj).toCmyk();
-},"HSL":function(obj,_3e){
-return _1.fromHsv(obj).toHsl();
-},"Lab":function(obj,_3f){
-return _7["XYZ"]["Lab"](_1.fromHsv(obj).toXYZ(_3f));
-},"LCHab":function(obj,_40){
-return _7["Lab"]["LCHab"](_1d["CMYK"]["Lab"](obj));
-},"LCHuv":function(obj,_41){
-return _7["LCHuv"]["Luv"](_7["Luv"]["XYZ"](_1.fromHsv(obj).toXYZ(_41)));
-},"Luv":function(obj,_42){
-return _7["Luv"]["XYZ"](_1.fromHsv(obj).toXYZ(_42));
-},"RGB":function(obj,_43){
-return _1.fromHsv(obj);
-},"XYZ":function(obj,_44){
-return _1.fromHsv(obj).toXYZ(_44);
-},"xyY":function(obj,_45){
-return _7["XYZ"]["xyY"](_1.fromHsv(obj).toXYZ(_45));
-}},"Lab":{"CMY":function(obj,_46){
-return _1.fromXYZ(_7["Lab"]["XYZ"](obj,_46)).toCmy();
-},"CMYK":function(obj,_47){
-return _1.fromXYZ(_7["Lab"]["XYZ"](obj,_47)).toCmyk();
-},"HSL":function(obj,_48){
-return _1.fromXYZ(_7["Lab"]["XYZ"](obj,_48)).toHsl();
-},"HSV":function(obj,_49){
-return _1.fromXYZ(_7["Lab"]["XYZ"](obj,_49)).toHsv();
-},"LCHab":function(obj,_4a){
-return _7["Lab"]["LCHab"](obj,_4a);
-},"LCHuv":function(obj,_4b){
-return _7["Luv"]["LCHuv"](_7["Lab"]["XYZ"](obj,_4b),_4b);
-},"Luv":function(obj,_4c){
-return _7["XYZ"]["Luv"](_7["Lab"]["XYZ"](obj,_4c),_4c);
-},"RGB":function(obj,_4d){
-return _1.fromXYZ(_7["Lab"]["XYZ"](obj,_4d));
-},"XYZ":function(obj,_4e){
-return _7["Lab"]["XYZ"](obj,_4e);
-},"xyY":function(obj,_4f){
-return _7["XYZ"]["xyY"](_7["Lab"]["XYZ"](obj,_4f),_4f);
-}},"LCHab":{"CMY":function(obj,_50){
-return _1.fromXYZ(_7["Lab"]["XYZ"](_7["LCHab"]["Lab"](obj),_50),_50).toCmy();
-},"CMYK":function(obj,_51){
-return _1.fromXYZ(_7["Lab"]["XYZ"](_7["LCHab"]["Lab"](obj),_51),_51).toCmyk();
-},"HSL":function(obj,_52){
-return _1.fromXYZ(_7["Lab"]["XYZ"](_7["LCHab"]["Lab"](obj),_52),_52).toHsl();
-},"HSV":function(obj,_53){
-return _1.fromXYZ(_7["Lab"]["XYZ"](_7["LCHab"]["Lab"](obj),_53),_53).toHsv();
-},"Lab":function(obj,_54){
-return _7["Lab"]["LCHab"](obj,_54);
-},"LCHuv":function(obj,_55){
-return _7["Luv"]["LCHuv"](_7["XYZ"]["Luv"](_7["Lab"]["XYZ"](_7["LCHab"]["Lab"](obj),_55),_55),_55);
-},"Luv":function(obj,_56){
-return _7["XYZ"]["Luv"](_7["Lab"]["XYZ"](_7["LCHab"]["Lab"](obj),_56),_56);
-},"RGB":function(obj,_57){
-return _1.fromXYZ(_7["Lab"]["XYZ"](_7["LCHab"]["Lab"](obj),_57),_57);
-},"XYZ":function(obj,_58){
-return _7["Lab"]["XYZ"](_7["LCHab"]["Lab"](obj,_58),_58);
-},"xyY":function(obj,_59){
-return _7["XYZ"]["xyY"](_7["Lab"]["XYZ"](_7["LCHab"]["Lab"](obj),_59),_59);
-}},"LCHuv":{"CMY":function(obj,_5a){
-return _1.fromXYZ(_7["Luv"]["XYZ"](_7["LCHuv"]["Luv"](obj),_5a),_5a).toCmy();
-},"CMYK":function(obj,_5b){
-return _1.fromXYZ(_7["Luv"]["XYZ"](_7["LCHuv"]["Luv"](obj),_5b),_5b).toCmyk();
-},"HSL":function(obj,_5c){
-return _1.fromXYZ(_7["Luv"]["XYZ"](_7["LCHuv"]["Luv"](obj),_5c),_5c).toHsl();
-},"HSV":function(obj,_5d){
-return _1.fromXYZ(_7["Luv"]["XYZ"](_7["LCHuv"]["Luv"](obj),_5d),_5d).toHsv();
-},"Lab":function(obj,_5e){
-return _7["XYZ"]["Lab"](_7["Luv"]["XYZ"](_7["LCHuv"]["Luv"](obj),_5e),_5e);
-},"LCHab":function(obj,_5f){
-return _7["Lab"]["LCHab"](_7["XYZ"]["Lab"](_7["Luv"]["XYZ"](_7["LCHuv"]["Luv"](obj),_5f),_5f),_5f);
-},"Luv":function(obj,_60){
-return _7["LCHuv"]["Luv"](obj,_60);
-},"RGB":function(obj,_61){
-return _1.fromXYZ(_7["Luv"]["XYZ"](_7["LCHuv"]["Luv"](obj),_61),_61);
-},"XYZ":function(obj,_62){
-return _7["Luv"]["XYZ"](_7["LCHuv"]["Luv"](obj),_62);
-},"xyY":function(obj,_63){
-return _7["XYZ"]["xyY"](_7["Luv"]["XYZ"](_7["LCHuv"]["Luv"](obj),_63),_63);
-}},"Luv":{"CMY":function(obj,_64){
-return _1.fromXYZ(_7["Luv"]["XYZ"](obj,_64),_64).toCmy();
-},"CMYK":function(obj,_65){
-return _1.fromXYZ(_7["Luv"]["XYZ"](obj,_65),_65).toCmyk();
-},"HSL":function(obj,_66){
-return _1.fromXYZ(_7["Luv"]["XYZ"](obj,_66),_66).toHsl();
-},"HSV":function(obj,_67){
-return _1.fromXYZ(_7["Luv"]["XYZ"](obj,_67),_67).toHsv();
-},"Lab":function(obj,_68){
-return _7["XYZ"]["Lab"](_7["Luv"]["XYZ"](obj,_68),_68);
-},"LCHab":function(obj,_69){
-return _7["Lab"]["LCHab"](_7["XYZ"]["Lab"](_7["Luv"]["XYZ"](obj,_69),_69),_69);
-},"LCHuv":function(obj,_6a){
-return _7["Luv"]["LCHuv"](obj,_6a);
-},"RGB":function(obj,_6b){
-return _1.fromXYZ(_7["Luv"]["XYZ"](obj,_6b),_6b);
-},"XYZ":function(obj,_6c){
-return _7["Luv"]["XYZ"](obj,_6c);
-},"xyY":function(obj,_6d){
-return _7["XYZ"]["xyY"](_7["Luv"]["XYZ"](obj,_6d),_6d);
-}},"RGB":{"CMY":function(obj,_6e){
-return obj.toCmy();
-},"CMYK":function(obj,_6f){
-return obj.toCmyk();
-},"HSL":function(obj,_70){
-return obj.toHsl();
-},"HSV":function(obj,_71){
-return obj.toHsv();
-},"Lab":function(obj,_72){
-return _7["XYZ"]["Lab"](obj.toXYZ(_72),_72);
-},"LCHab":function(obj,_73){
-return _7["LCHab"]["Lab"](_7["XYZ"]["Lab"](obj.toXYZ(_73),_73),_73);
-},"LCHuv":function(obj,_74){
-return _7["LCHuv"]["Luv"](_7["XYZ"]["Luv"](obj.toXYZ(_74),_74),_74);
-},"Luv":function(obj,_75){
-return _7["XYZ"]["Luv"](obj.toXYZ(_75),_75);
-},"XYZ":function(obj,_76){
-return obj.toXYZ(_76);
-},"xyY":function(obj,_77){
-return _7["XYZ"]["xyY"](obj.toXYZ(_77),_77);
-}},"XYZ":{"CMY":function(obj,_78){
-return _1.fromXYZ(obj,_78).toCmy();
-},"CMYK":function(obj,_79){
-return _1.fromXYZ(obj,_79).toCmyk();
-},"HSL":function(obj,_7a){
-return _1.fromXYZ(obj,_7a).toHsl();
-},"HSV":function(obj,_7b){
-return _1.fromXYZ(obj,_7b).toHsv();
-},"Lab":function(obj,_7c){
-return _7["XYZ"]["Lab"](obj,_7c);
-},"LCHab":function(obj,_7d){
-return _7["Lab"]["LCHab"](_7["XYZ"]["Lab"](obj,_7d),_7d);
-},"LCHuv":function(obj,_7e){
-return _7["Luv"]["LCHuv"](_7["XYZ"]["Luv"](obj,_7e),_7e);
-},"Luv":function(obj,_7f){
-return _7["XYZ"]["Luv"](obj,_7f);
-},"RGB":function(obj,_80){
-return _1.fromXYZ(obj,_80);
-},"xyY":function(obj,_81){
-return _7["XYZ"]["xyY"](_1.fromXYZ(obj,_81),_81);
-}},"xyY":{"CMY":function(obj,_82){
-return _1.fromXYZ(_7["xyY"]["XYZ"](obj,_82),_82).toCmy();
-},"CMYK":function(obj,_83){
-return _1.fromXYZ(_7["xyY"]["XYZ"](obj,_83),_83).toCmyk();
-},"HSL":function(obj,_84){
-return _1.fromXYZ(_7["xyY"]["XYZ"](obj,_84),_84).toHsl();
-},"HSV":function(obj,_85){
-return _1.fromXYZ(_7["xyY"]["XYZ"](obj,_85),_85).toHsv();
-},"Lab":function(obj,_86){
-return _7["Lab"]["XYZ"](_7["xyY"]["XYZ"](obj,_86),_86);
-},"LCHab":function(obj,_87){
-return _7["LCHab"]["Lab"](_7["Lab"]["XYZ"](_7["xyY"]["XYZ"](obj,_87),_87),_87);
-},"LCHuv":function(obj,_88){
-return _7["LCHuv"]["Luv"](_7["Luv"]["XYZ"](_7["xyY"]["XYZ"](obj,_88),_88),_88);
-},"Luv":function(obj,_89){
-return _7["Luv"]["XYZ"](_7["xyY"]["XYZ"](obj,_89),_89);
-},"RGB":function(obj,_8a){
-return _1.fromXYZ(_7["xyY"]["XYZ"](obj,_8a),_8a);
-},"XYZ":function(obj,_8b){
-return _7["xyY"]["XYZ"](obj,_8b);
-}}};
-this.whitepoint=function(_8c,_8d){
-_8d=_8d||"10";
-var x=0,y=0,t=0;
-if(_4[_8d]&&_4[_8d][_8c]){
-x=_4[_8d][_8c].x;
-y=_4[_8d][_8c].y;
-t=_4[_8d][_8c].t;
-}else{
-console.warn("dojox.color.Colorspace::whitepoint: either the observer or the whitepoint name was not found. ",_8d,_8c);
-}
-var wp={x:x,y:y,z:(1-x-y),t:t,Y:1};
-return this.convert(wp,"xyY","XYZ");
-};
-this.tempToWhitepoint=function(t){
-if(t<4000){
-console.warn("dojox.color.Colorspace::tempToWhitepoint: can't find a white point for temperatures less than 4000K. (Passed ",t,").");
-return {x:0,y:0};
-}
-if(t>25000){
-console.warn("dojox.color.Colorspace::tempToWhitepoint: can't find a white point for temperatures greater than 25000K. (Passed ",t,").");
-return {x:0,y:0};
-}
-var t1=t,t2=t*t,t3=t2*t;
-var _8e=Math.pow(10,9),_8f=Math.pow(10,6),_90=Math.pow(10,3);
-if(t<=7000){
-var x=(-4.607*_8e/t3)+(2.9678*_8f/t2)+(0.09911*_90/t)+0.2444063;
-}else{
-var x=(-2.0064*_8e/t3)+(1.9018*_8f/t2)+(0.24748*_90/t)+0.23704;
-}
-var y=-3*x*x+2.87*x-0.275;
-return {x:x,y:y};
-};
-this.primaries=function(_91){
-_91=dojo.mixin({profile:"sRGB",whitepoint:"D65",observer:"10",adaptor:"Bradford"},_91||{});
-var m=[];
-if(_5[_91.profile]){
-m=_5[_91.profile].slice(0);
-}else{
-console.warn("dojox.color.Colorspace::primaries: the passed profile was not found.  ","Available profiles include: ",_5,".  The profile passed was ",_91.profile);
-}
-var _92={name:_91.profile,gamma:m[0],whitepoint:m[1],xr:m[2],yr:m[3],Yr:m[4],xg:m[5],yg:m[6],Yg:m[7],xb:m[8],yb:m[9],Yb:m[10]};
-if(_91.whitepoint!=_92.whitepoint){
-var r=this.convert(this.adapt({color:this.convert({x:xr,y:yr,Y:Yr},"xyY","XYZ"),adaptor:_91.adaptor,source:_92.whitepoint,destination:_91.whitepoint}),"XYZ","xyY");
-var g=this.convert(this.adapt({color:this.convert({x:xg,y:yg,Y:Yg},"xyY","XYZ"),adaptor:_91.adaptor,source:_92.whitepoint,destination:_91.whitepoint}),"XYZ","xyY");
-var b=this.convert(this.adapt({color:this.convert({x:xb,y:yb,Y:Yb},"xyY","XYZ"),adaptor:_91.adaptor,source:_92.whitepoint,destination:_91.whitepoint}),"XYZ","xyY");
-_92=dojo.mixin(_92,{xr:r.x,yr:r.y,Yr:r.Y,xg:g.x,yg:g.y,Yg:g.Y,xb:b.x,yb:b.y,Yb:b.Y,whitepoint:_91.whitepoint});
-}
-return dojo.mixin(_92,{zr:1-_92.xr-_92.yr,zg:1-_92.xg-_92.yg,zb:1-_92.xb-_92.yb});
-};
-this.adapt=function(_93){
-if(!_93.color||!_93.source){
-console.error("dojox.color.Colorspace::adapt: color and source arguments are required. ",_93);
-}
-_93=dojo.mixin({adaptor:"Bradford",destination:"D65"},_93);
-var swp=this.whitepoint(_93.source);
-var dwp=this.whitepoint(_93.destination);
-if(_6[_93.adaptor]){
-var ma=_6[_93.adaptor].ma;
-var mai=_6[_93.adaptor].mai;
-}else{
-console.warn("dojox.color.Colorspace::adapt: the passed adaptor '",_93.adaptor,"' was not found.");
-}
-var _94=_2.multiply([[swp.x,swp.y,swp.z]],ma);
-var _95=_2.multiply([[dwp.x,dwp.y,dwp.z]],ma);
-var _96=[[_95[0][0]/_94[0][0],0,0],[0,_95[0][1]/_94[0][1],0],[0,0,_95[0][2]/_94[0][2]]];
-var m=_2.multiply(_2.multiply(ma,_96),mai);
-var r=_2.multiply([[_93.color.X,_93.color.Y,_93.color.Z]],m)[0];
-return {X:r[0],Y:r[1],Z:r[2]};
-};
-this.matrix=function(to,_97){
-var wp=this.whitepoint(_97.whitepoint);
-var Xr=p.xr/p.yr,Yr=1,Zr=(1-p.xr-p.yr)/p.yr;
-var Xg=p.xg/p.yg,Yg=1,Zg=(1-p.xg-p.yg)/p.yg;
-var Xb=p.xb/p.yb,Yb=1,Zr=(1-p.xb-p.yb)/p.yb;
-var m1=[[Xr,Yr,Zr],[Xg,Yg,Zg],[Xb,Yb,Zb]];
-var m2=[[wp.X,wp.Y,wp.Z]];
-var sm=dojox.math.matrix.multiply(m2,dojox.math.matrix.inverse(m1));
-var Sr=sm[0][0],Sg=sm[0][1],Sb=sm[0][2];
-var _98=[[Sr*Xr,Sr*Yr,Sr*Zr],[Sg*Xg,Sg*Yg,Sg*Zg],[Sb*Xb,Sb*Yb,Sb*Zb]];
-if(to=="RGB"){
-return dojox.math.inverse(_98);
-}
-return _98;
-};
-this.epsilon=function(_99){
-return (_99||typeof (_99)=="undefined")?0.008856:216/24289;
-};
-this.kappa=function(_9a){
-return (_9a||typeof (_9a)=="undefined")?903.3:24389/27;
-};
-this.convert=function(_9b,_9c,to,_9d){
-if(_1d[_9c]&&_1d[_9c][to]){
-return _1d[_9c][to](obj,_9d);
-}
-console.warn("dojox.color.Colorspace::convert: Can't convert ",_9b," from ",_9c," to ",to,".");
-};
+	var dxc=dojox.color;
+	var dxm=dojox.math.matrix;
+	var self=this;
+	var wpMap={
+		"2":{
+			"E":	{ x:1/3,     y:1/3,     t:5400 },
+			"D50":	{ x:0.34567, y:0.3585,  t:5000 },
+			"D55":	{ x:0.33242, y:0.34743, t:5500 },
+			"D65":	{ x:0.31271, y:0.32902, t:6500 },
+			"D75":	{ x:0.29902, y:0.31485, t:7500 },
+			"A":	{ x:0.44757, y:0.40745, t:2856 },
+			"B":	{ x:0.34842, y:0.35161, t:4874 },
+			"C":	{ x:0.31006, y:0.31616, t:6774 },
+			"9300":	{ x:0.2848,  y:0.2932,  t:9300 },
+			"F2":	{ x:0.37207, y:0.37512, t:4200 },
+			"F7":	{ x:0.31285, y:0.32918, t:6500 },
+			"F11":	{ x:0.38054, y:0.37691, t:4000 }
+		},
+		"10":{
+			"E":	{ x:1/3,     y:1/3,     t:5400 },
+			"D50":	{ x:0.34773, y:0.35952, t:5000 },
+			"D55":	{ x:0.33411, y:0.34877, t:5500 },
+			"D65":	{ x:0.31382, y:0.331,   t:6500 },
+			"D75":	{ x:0.29968, y:0.3174,  t:7500 },
+			"A":	{ x:0.45117, y:0.40594, t:2856 },
+			"B":	{ x:0.3498,  y:0.3527,  t:4874 },
+			"C":	{ x:0.31039, y:0.31905, t:6774 },
+			"F2":	{ x:0.37928, y:0.36723, t:4200 },
+			"F7":	{ x:0.31565, y:0.32951, t:6500 },
+			"F11":	{ x:0.38543, y:0.3711,  t:4000 }
+		}
+	};
+
+	var profiles={
+		"Adobe RGB 98":[2.2, "D65", 0.64, 0.33, 0.297361, 0.21, 0.71, 0.627355, 0.15, 0.06, 0.075285],
+		"Apple RGB":[1.8, "D65", 0.625, 0.34, 0.244634, 0.28, 0.595, 0.672034, 0.155, 0.07, 0.083332],
+		"Best RGB":[2.2, "D50", 0.7347, 0.2653, 0.228457, 0.215, 0.775, 0.737352, 0.13, 0.035, 0.034191],
+		"Beta RGB":[2.2, "D50", 0.6888, 0.3112, 0.303273, 0.1986, 0.7551, 0.663786, 0.1265, 0.0352, 0.032941],
+		"Bruce RGB":[2.2, "D65", 0.64, 0.33, 0.240995, 0.28, 0.65, 0.683554, 0.15, 0.06, 0.075452],
+		"CIE RGB":[2.2, "E", 0.735, 0.265, 0.176204, 0.274, 0.717, 0.812985, 0.167, 0.009, 0.010811],
+		"ColorMatch RGB":[1.8, "D50", 0.63, 0.34, 0.274884, 0.295, 0.605, 0.658132, 0.15, 0.075, 0.066985],
+		"DON RGB 4":[2.2, "D50", 0.696, 0.3, 0.27835, 0.215, 0.765, 0.68797, 0.13, 0.035, 0.03368],
+		"ECI RGB":[1.8, "D50", 0.67, 0.33, 0.32025, 0.21, 0.71, 0.602071, 0.14, 0.08, 0.077679],
+		"EktaSpace PS5":[2.2, "D50", 0.695, 0.305, 0.260629, 0.26, 0.7, 0.734946, 0.11, 0.005, 0.004425],
+		"NTSC RGB":[2.2, "C", 0.67, 0.33, 0.298839, 0.21, 0.71, 0.586811, 0.14, 0.08, 0.11435],
+		"PAL/SECAM RGB":[2.2, "D65", 0.64, 0.33, 0.222021, 0.29, 0.6, 0.706645, 0.15, 0.06, 0.071334],
+		"Pro Photo RGB":[1.8, "D50", 0.7347, 0.2653, 0.28804, 0.1596, 0.8404, 0.711874, 0.0366, 0.0001, 0.000086],
+		"SMPTE/C RGB":[2.2, "D65", 0.63, 0.34, 0.212395, 0.31, 0.595, 0.701049, 0.155, 0.07, 0.086556],
+		"sRGB":[2.2, "D65", 0.64, 0.33, 0.212656, 0.3, 0.6, 0.715158, 0.15, 0.06, 0.072186],
+		"Wide Gamut RGB":[2.2, "D50", 0.735, 0.265, 0.258187, 0.115, 0.826, 0.724938, 0.157, 0.018, 0.016875]
+	};
+
+	var adaptors={
+		"XYZ scaling":{
+			ma:  [[1,0,0], [0,1,0], [0,0,1]],
+			mai: [[1,0,0], [0,1,0], [0,0,1]]
+		},
+		"Bradford":{
+			ma:  [[0.8951, -0.7502, 0.0389], [0.2664, 1.7135, -0.0685], [-0.1614, 0.0367, 1.0296]],
+			mai: [[0.986993, 0.432305, -0.008529], [-0.147054, 0.51836, 0.040043], [0.159963, 0.049291, 0.968487]]
+		},
+		"Von Kries":{
+			ma:  [[0.40024, -0.2263, 0], [0.7076, 1.16532, 0], [-0.08081, 0.0457, 0.91822]],
+			mai: [[1.859936, 0.361191, 0], [-1.129382, 0.638812, 0], [0.219897, -0.000006, 1.089064]]
+		}
+	};
+
+	var cMaps={
+		"XYZ":{
+			"xyY":function(xyz, kwArgs){
+				kwArgs=dojo.mixin({
+					whitepoint:"D65",
+					observer:"10",
+					useApproximation:true
+				}, kwArgs||{});
+				var wp=self.whitepoint(kwArgs.whitepoint, kwArgs.observer);
+				var sum=xyz.X+xyz.Y+xyz.Z;
+				if(sum==0){ var x=wp.x, y=wp.y; }
+				else{ var x=xyz.X/sum, y=xyz.Y/sum; }
+				return { x:x, y:y, Y:xyz.Y };
+			},
+			"Lab":function(xyz, kwArgs){
+				kwArgs=dojo.mixin({
+					whitepoint:"D65",
+					observer:"10",
+					useApproximation:true
+				}, kwArgs||{});
+
+				var kappa=self.kappa(kwArgs.useApproximation), epsilon=self.epsilon(kwArgs.useApproximation);
+				var wp=self.whitepoint(kwArgs.whitepoint, kwArgs.observer);
+				var xr=xyz.X/wp.x, yr=xyz.Y/wp.y, zr=xyz.z/wp.z;
+				var fx=(xr>epsilon)?Math.pow(xr,1/3):(kappa*xr+16)/116;
+				var fy=(yr>epsilon)?Math.pow(yr,1/3):(kappa*yr+16)/116;
+				var fz=(zr>epsilon)?Math.pow(zr,1/3):(kappa*zr+16)/116;
+				var L=116*fy-16, a=500*(fx-fy), b=200*(fy-fz);
+				return { L:L, a:a, b:b };
+			},
+			"Luv": function(xyz, kwArgs){
+				kwArgs=dojo.mixin({
+					whitepoint:"D65",
+					observer:"10",
+					useApproximation:true
+				}, kwArgs||{});
+
+				var kappa=self.kappa(kwArgs.useApproximation), epsilon=self.epsilon(kwArgs.useApproximation);
+				var wp=self.whitepoint(kwArgs.whitepoint, kwArgs.observer);
+				var ud=(4*xyz.X)/(xyz.X+15*xyz.Y+3*xyz.Z);
+				var vd=(9*xyz.Y)/(xyz.X+15*xyz.Y+3*xyz.Z);
+				var udr=(4*wp.x)/(wp.x+15*wp.y+3*wp.z);
+				var vdr=(9*wp.y)/(wp.x+15*wp.y+3*wp.z);
+				var yr=xyz.Y/wp.y;
+				var L=(yr>epsilon)?116*Math.pow(yr, 1/3)-16:kappa*yr;
+				var u=13*L*(ud-udr);
+				var v=13*L*(vd-vdr);
+				return { L:L, u:u, v:v };
+			}
+		},
+		"xyY":{
+			"XYZ":function(xyY){
+				if(xyY.y==0){ var X=0, Y=0, Z=0; }
+				else{
+					var X=(xyY.x*xyY.Y)/xyY.y;
+					var Y=xyY.Y;
+					var Z=((1-xyY.x-xyY.y)*xyY.Y)/xyY.y;
+				}
+				return { X:X, Y:Y, Z:Z };
+			}
+		},
+		"Lab":{
+			"XYZ": function(lab, kwArgs){
+				kwArgs=dojo.mixin({
+					whitepoint:"D65",
+					observer:"10",
+					useApproximation:true
+				}, kwArgs||{});
+
+				var b=kwArgs.useApproximation, kappa=self.kappa(b), epsilon=self.epsilon(b);
+				var wp=self.whitepoint(kwArgs.whitepoint, kwArgs.observer);
+				var yr=(lab.L>(kappa*epsilon))?Math.pow((lab.L+16)/116, 3):lab.L/kappa;
+				var fy=(yr>epsilon)?(lab.L+16)/116:(kappa*yr+16)/116;
+				var fx=(lab.a/500)+fy;
+				var fz=fy-(lab.b/200);
+				var fxcube=Math.pow(fx, 3), fzcube=Math.pow(fz, 3);
+				var xr=(fxcube>epsilon)?fxcube:(116*fx-16)/kappa;
+				var zr=(fzcube>epsilon)?fzcube:(116*fz-16)/kappa;
+				return { X: xr*wp.x, Y: yr*wp.y, Z: zr*wp.z };
+			},
+			"LCHab": function(lab){
+				var L=lab.L, C=Math.pow(lab.a*lab.a+lab.b*lab.b, 0.5), H=Math.atan(lab.b, lab.a)*(180/Math.PI);
+				if(H<0){ H+=360; }
+				if(H<360){ H-=360; }
+				return { L:L, C:C, H:H };
+			}
+		},
+		"LCHab":{
+			"Lab":function(lch){
+				var hRad=lch.H*(Math.PI/180), L=lch.L, a=lch.C/Math.pow(Math.pow(Math.tan(hRad),2)+1, 0.5);
+				if(90<lchH && lch.H<270){ a = -a; }
+				var b=Math.pow(Math.pow(lch.C,2)-Math.pow(a, 2), 0.5);
+				if(lch.H>180){ b = -b; }
+				return { L: L, a:a, b:b };
+			}
+		},
+		"Luv":{
+			"XYZ": function(Luv, kwArgs){
+				kwArgs=dojo.mixin({
+					whitepoint:"D65",
+					observer:"10",
+					useApproximation:true
+				}, kwArgs||{});
+
+				var b=kwArgs.useApproximation, kappa=self.kappa(b), epsilon=self.epsilon(b);
+				var wp=self.whitepoint(kwArgs.whitepoint, kwArgs.observer);
+				var uz=(4*wp.x)/(wp.x+15*wp.y+3*wp.z);
+				var vz=(9*wp.y)/(wp.x+15*wp.y+3*wp.z);
+				var Y=(Luv.L>kappa*epsilon)?Math.pow((Luv.L+16)/116, 3):Luv.L/kappa;
+				var a=(1/3)*(((52*Luv.L)/(Luv.u+13*Luv.L*uz))-1);
+				var b=-5*Y, c=-(1/3), d=Y*(((39*Luv.L)/(Luv.v+13*Luv.L*vz))-5);
+				var X=(d-b)/(a-c), Z=X*a+b;
+				return { X:X, Y:Y, Z:Z };
+			},
+			"LCHuv": function(Luv){
+				var L=Luv.L, C=Math.pow(Luv.u*Luv.u+Luv.v*Luv*v, 0.5), H=Math.atan(Luv.v, Luv.u)*(180/Math.PI);
+				if(H<0){ H+=360; }
+				if(H>360){ H-=360; }
+				return { L:L, C:C, H:H };
+			}
+		},
+		"LCHuv":{
+			"Luv": function(LCH){
+				var hRad=LCH.H*(Math.PI/180);
+				var L=LCH.L, u=LCH.C/Math.pow(Math.pow(Math.tan(hRad),2)+1, 0.5);
+				var v=Math.pow(LCH.C*LCH.C-u*u, 0.5);
+				if(90<LCH.H && LCH.H>270){ u*=-1; }
+				if(LCH.H>180){ v*=-1; }
+				return { L:L, u:u, v:v };
+			}
+		}
+	};
+	var converters={
+		"CMY":{ 
+			"CMYK":function(obj, kwArgs){ return dxc.fromCmy(obj).toCmyk(); },
+			"HSL":function(obj, kwArgs){ return dxc.fromCmy(obj).toHsl(); },
+			"HSV":function(obj, kwArgs){ return dxc.fromCmy(obj).toHsv(); },
+			"Lab":function(obj, kwArgs){ return cMaps["XYZ"]["Lab"](dxc.fromCmy(obj).toXYZ(kwArgs)); },
+			"LCHab":function(obj, kwArgs){ return cMaps["Lab"]["LCHab"](converters["CMY"]["Lab"](obj)); },
+			"LCHuv":function(obj, kwArgs){ return cMaps["LCHuv"]["Luv"](cMaps["Luv"]["XYZ"](dxc.fromCmy(obj).toXYZ(kwArgs))); },
+			"Luv":function(obj, kwArgs){ return cMaps["Luv"]["XYZ"](dxc.fromCmy(obj).toXYZ(kwArgs)); },
+			"RGB":function(obj, kwArgs){ return dxc.fromCmy(obj); },
+			"XYZ":function(obj, kwArgs){ return dxc.fromCmy(obj).toXYZ(kwArgs); },
+			"xyY":function(obj, kwArgs){ return cMaps["XYZ"]["xyY"](dxc.fromCmy(obj).toXYZ(kwArgs)); }
+		},
+		"CMYK":{ 
+			"CMY":function(obj, kwArgs){ return dxc.fromCmyk(obj).toCmy(); },
+			"HSL":function(obj, kwArgs){ return dxc.fromCmyk(obj).toHsl(); },
+			"HSV":function(obj, kwArgs){ return dxc.fromCmyk(obj).toHsv(); },
+			"Lab":function(obj, kwArgs){ return cMaps["XYZ"]["Lab"](dxc.fromCmyk(obj).toXYZ(kwArgs)); },
+			"LCHab":function(obj, kwArgs){ return cMaps["Lab"]["LCHab"](converters["CMYK"]["Lab"](obj)); },
+			"LCHuv":function(obj, kwArgs){ return cMaps["LCHuv"]["Luv"](cMaps["Luv"]["XYZ"](dxc.fromCmyk(obj).toXYZ(kwArgs))); },
+			"Luv":function(obj, kwArgs){ return cMaps["Luv"]["XYZ"](dxc.fromCmyk(obj).toXYZ(kwArgs)); },
+			"RGB":function(obj, kwArgs){ return dxc.fromCmyk(obj); },
+			"XYZ":function(obj, kwArgs){ return dxc.fromCmyk(obj).toXYZ(kwArgs); },
+			"xyY":function(obj, kwArgs){ return cMaps["XYZ"]["xyY"](dxc.fromCmyk(obj).toXYZ(kwArgs)); }
+		},
+		"HSL":{ 
+			"CMY":function(obj, kwArgs){ return dxc.fromHsl(obj).toCmy(); },
+			"CMYK":function(obj, kwArgs){ return dxc.fromHsl(obj).toCmyk(); },
+			"HSV":function(obj, kwArgs){ return dxc.fromHsl(obj).toHsv(); },
+			"Lab":function(obj, kwArgs){ return cMaps["XYZ"]["Lab"](dxc.fromHsl(obj).toXYZ(kwArgs)); },
+			"LCHab":function(obj, kwArgs){ return cMaps["Lab"]["LCHab"](converters["CMYK"]["Lab"](obj)); },
+			"LCHuv":function(obj, kwArgs){ return cMaps["LCHuv"]["Luv"](cMaps["Luv"]["XYZ"](dxc.fromHsl(obj).toXYZ(kwArgs))); },
+			"Luv":function(obj, kwArgs){ return cMaps["Luv"]["XYZ"](dxc.fromHsl(obj).toXYZ(kwArgs)); },
+			"RGB":function(obj, kwArgs){ return dxc.fromHsl(obj); },
+			"XYZ":function(obj, kwArgs){ return dxc.fromHsl(obj).toXYZ(kwArgs); },
+			"xyY":function(obj, kwArgs){ return cMaps["XYZ"]["xyY"](dxc.fromHsl(obj).toXYZ(kwArgs)); }
+		},
+		"HSV":{ 
+			"CMY":function(obj, kwArgs){ return dxc.fromHsv(obj).toCmy(); },
+			"CMYK":function(obj, kwArgs){ return dxc.fromHsv(obj).toCmyk(); },
+			"HSL":function(obj, kwArgs){ return dxc.fromHsv(obj).toHsl(); },
+			"Lab":function(obj, kwArgs){ return cMaps["XYZ"]["Lab"](dxc.fromHsv(obj).toXYZ(kwArgs)); },
+			"LCHab":function(obj, kwArgs){ return cMaps["Lab"]["LCHab"](converters["CMYK"]["Lab"](obj)); },
+			"LCHuv":function(obj, kwArgs){ return cMaps["LCHuv"]["Luv"](cMaps["Luv"]["XYZ"](dxc.fromHsv(obj).toXYZ(kwArgs))); },
+			"Luv":function(obj, kwArgs){ return cMaps["Luv"]["XYZ"](dxc.fromHsv(obj).toXYZ(kwArgs)); },
+			"RGB":function(obj, kwArgs){ return dxc.fromHsv(obj); },
+			"XYZ":function(obj, kwArgs){ return dxc.fromHsv(obj).toXYZ(kwArgs); },
+			"xyY":function(obj, kwArgs){ return cMaps["XYZ"]["xyY"](dxc.fromHsv(obj).toXYZ(kwArgs)); }
+		},
+		"Lab":{ 
+			"CMY":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Lab"]["XYZ"](obj, kwArgs)).toCmy(); },
+			"CMYK":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Lab"]["XYZ"](obj, kwArgs)).toCmyk(); },
+			"HSL":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Lab"]["XYZ"](obj, kwArgs)).toHsl(); },
+			"HSV":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Lab"]["XYZ"](obj, kwArgs)).toHsv(); },
+			"LCHab":function(obj, kwArgs){ return cMaps["Lab"]["LCHab"](obj, kwArgs); },
+			"LCHuv":function(obj, kwArgs){ return cMaps["Luv"]["LCHuv"](cMaps["Lab"]["XYZ"](obj, kwArgs), kwArgs); },
+			"Luv":function(obj, kwArgs){ return cMaps["XYZ"]["Luv"](cMaps["Lab"]["XYZ"](obj, kwArgs), kwArgs); },
+			"RGB":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Lab"]["XYZ"](obj, kwArgs)); },
+			"XYZ":function(obj, kwArgs){ return cMaps["Lab"]["XYZ"](obj, kwArgs); },
+			"xyY":function(obj, kwArgs){ return cMaps["XYZ"]["xyY"](cMaps["Lab"]["XYZ"](obj, kwArgs), kwArgs); }
+		},
+		"LCHab":{ 
+			"CMY":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Lab"]["XYZ"](cMaps["LCHab"]["Lab"](obj), kwArgs), kwArgs).toCmy(); },
+			"CMYK":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Lab"]["XYZ"](cMaps["LCHab"]["Lab"](obj), kwArgs), kwArgs).toCmyk(); },
+			"HSL":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Lab"]["XYZ"](cMaps["LCHab"]["Lab"](obj), kwArgs), kwArgs).toHsl(); },
+			"HSV":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Lab"]["XYZ"](cMaps["LCHab"]["Lab"](obj), kwArgs), kwArgs).toHsv(); },
+			"Lab":function(obj, kwArgs){ return cMaps["Lab"]["LCHab"](obj, kwArgs); },
+			"LCHuv":function(obj, kwArgs){ return cMaps["Luv"]["LCHuv"](cMaps["XYZ"]["Luv"](cMaps["Lab"]["XYZ"](cMaps["LCHab"]["Lab"](obj), kwArgs), kwArgs), kwArgs);},
+			"Luv":function(obj, kwArgs){ return cMaps["XYZ"]["Luv"](cMaps["Lab"]["XYZ"](cMaps["LCHab"]["Lab"](obj), kwArgs), kwArgs);},
+			"RGB":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Lab"]["XYZ"](cMaps["LCHab"]["Lab"](obj), kwArgs), kwArgs); },
+			"XYZ":function(obj, kwArgs){ return cMaps["Lab"]["XYZ"](cMaps["LCHab"]["Lab"](obj, kwArgs), kwArgs); },
+			"xyY":function(obj, kwArgs){ return cMaps["XYZ"]["xyY"](cMaps["Lab"]["XYZ"](cMaps["LCHab"]["Lab"](obj), kwArgs), kwArgs); }
+		},
+		"LCHuv":{ 
+			"CMY":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Luv"]["XYZ"](cMaps["LCHuv"]["Luv"](obj), kwArgs), kwArgs).toCmy(); },
+			"CMYK":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Luv"]["XYZ"](cMaps["LCHuv"]["Luv"](obj), kwArgs), kwArgs).toCmyk(); },
+			"HSL":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Luv"]["XYZ"](cMaps["LCHuv"]["Luv"](obj), kwArgs), kwArgs).toHsl(); },
+			"HSV":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Luv"]["XYZ"](cMaps["LCHuv"]["Luv"](obj), kwArgs), kwArgs).toHsv(); },
+			"Lab":function(obj, kwArgs){ return cMaps["XYZ"]["Lab"](cMaps["Luv"]["XYZ"](cMaps["LCHuv"]["Luv"](obj), kwArgs), kwArgs); },
+			"LCHab":function(obj, kwArgs){ return cMaps["Lab"]["LCHab"](cMaps["XYZ"]["Lab"](cMaps["Luv"]["XYZ"](cMaps["LCHuv"]["Luv"](obj), kwArgs), kwArgs), kwArgs); },
+			"Luv":function(obj, kwArgs){ return cMaps["LCHuv"]["Luv"](obj, kwArgs); },
+			"RGB":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Luv"]["XYZ"](cMaps["LCHuv"]["Luv"](obj), kwArgs), kwArgs); },
+			"XYZ":function(obj, kwArgs){ return cMaps["Luv"]["XYZ"](cMaps["LCHuv"]["Luv"](obj), kwArgs); },
+			"xyY":function(obj, kwArgs){ return cMaps["XYZ"]["xyY"](cMaps["Luv"]["XYZ"](cMaps["LCHuv"]["Luv"](obj), kwArgs), kwArgs); }
+		},
+		"Luv":{ 
+			"CMY":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Luv"]["XYZ"](obj, kwArgs), kwArgs).toCmy(); },
+			"CMYK":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Luv"]["XYZ"](obj, kwArgs), kwArgs).toCmyk(); },
+			"HSL":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Luv"]["XYZ"](obj, kwArgs), kwArgs).toHsl(); },
+			"HSV":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Luv"]["XYZ"](obj, kwArgs), kwArgs).toHsv(); },
+			"Lab":function(obj, kwArgs){ return cMaps["XYZ"]["Lab"](cMaps["Luv"]["XYZ"](obj, kwArgs), kwArgs); },
+			"LCHab":function(obj, kwArgs){ return cMaps["Lab"]["LCHab"](cMaps["XYZ"]["Lab"](cMaps["Luv"]["XYZ"](obj, kwArgs), kwArgs), kwArgs); },
+			"LCHuv":function(obj, kwArgs){ return cMaps["Luv"]["LCHuv"](obj, kwArgs); },
+			"RGB":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["Luv"]["XYZ"](obj, kwArgs), kwArgs); },
+			"XYZ":function(obj, kwArgs){ return cMaps["Luv"]["XYZ"](obj, kwArgs); },
+			"xyY":function(obj, kwArgs){ return cMaps["XYZ"]["xyY"](cMaps["Luv"]["XYZ"](obj, kwArgs), kwArgs); }
+		},
+		"RGB":{ 
+			"CMY":function(obj, kwArgs){ return obj.toCmy(); },
+			"CMYK":function(obj, kwArgs){ return obj.toCmyk(); },
+			"HSL":function(obj, kwArgs){ return obj.toHsl(); },
+			"HSV":function(obj, kwArgs){ return obj.toHsv(); },
+			"Lab":function(obj, kwArgs){ return cMaps["XYZ"]["Lab"](obj.toXYZ(kwArgs), kwArgs); },
+			"LCHab":function(obj, kwArgs){ return cMaps["LCHab"]["Lab"](cMaps["XYZ"]["Lab"](obj.toXYZ(kwArgs), kwArgs), kwArgs);},
+			"LCHuv":function(obj, kwArgs){ return cMaps["LCHuv"]["Luv"](cMaps["XYZ"]["Luv"](obj.toXYZ(kwArgs), kwArgs), kwArgs);},
+			"Luv":function(obj, kwArgs){ return cMaps["XYZ"]["Luv"](obj.toXYZ(kwArgs), kwArgs); },
+			"XYZ":function(obj, kwArgs){ return obj.toXYZ(kwArgs); },
+			"xyY":function(obj, kwArgs){ return cMaps["XYZ"]["xyY"](obj.toXYZ(kwArgs), kwArgs); }
+		},
+		"XYZ":{ 
+			"CMY":function(obj, kwArgs){ return dxc.fromXYZ(obj, kwArgs).toCmy(); },
+			"CMYK":function(obj, kwArgs){ return dxc.fromXYZ(obj, kwArgs).toCmyk(); },
+			"HSL":function(obj, kwArgs){ return dxc.fromXYZ(obj, kwArgs).toHsl(); },
+			"HSV":function(obj, kwArgs){ return dxc.fromXYZ(obj, kwArgs).toHsv(); },
+			"Lab":function(obj, kwArgs){ return cMaps["XYZ"]["Lab"](obj, kwArgs); },
+			"LCHab":function(obj, kwArgs){ return cMaps["Lab"]["LCHab"](cMaps["XYZ"]["Lab"](obj, kwArgs), kwArgs); },
+			"LCHuv":function(obj, kwArgs){ return cMaps["Luv"]["LCHuv"](cMaps["XYZ"]["Luv"](obj, kwArgs), kwArgs); },
+			"Luv":function(obj, kwArgs){ return cMaps["XYZ"]["Luv"](obj, kwArgs); },
+			"RGB":function(obj, kwArgs){ return dxc.fromXYZ(obj, kwArgs); },
+			"xyY":function(obj, kwArgs){ return cMaps["XYZ"]["xyY"](dxc.fromXYZ(obj, kwArgs), kwArgs); }
+		},
+		// TODO: revisit this. xyY represents a single color, not a spectrum of colors.
+		"xyY":{ 
+			"CMY":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["xyY"]["XYZ"](obj, kwArgs), kwArgs).toCmy(); },
+			"CMYK":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["xyY"]["XYZ"](obj, kwArgs), kwArgs).toCmyk(); },
+			"HSL":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["xyY"]["XYZ"](obj, kwArgs), kwArgs).toHsl(); },
+			"HSV":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["xyY"]["XYZ"](obj, kwArgs), kwArgs).toHsv(); },
+			"Lab":function(obj, kwArgs){ return cMaps["Lab"]["XYZ"](cMaps["xyY"]["XYZ"](obj, kwArgs), kwArgs); },
+			"LCHab":function(obj, kwArgs){ return cMaps["LCHab"]["Lab"](cMaps["Lab"]["XYZ"](cMaps["xyY"]["XYZ"](obj, kwArgs), kwArgs), kwArgs); },
+			"LCHuv":function(obj, kwArgs){ return cMaps["LCHuv"]["Luv"](cMaps["Luv"]["XYZ"](cMaps["xyY"]["XYZ"](obj, kwArgs), kwArgs), kwArgs); },
+			"Luv":function(obj, kwArgs){ return cMaps["Luv"]["XYZ"](cMaps["xyY"]["XYZ"](obj, kwArgs), kwArgs); },
+			"RGB":function(obj, kwArgs){ return dxc.fromXYZ(cMaps["xyY"]["XYZ"](obj, kwArgs), kwArgs); },
+			"XYZ":function(obj, kwArgs){ return cMaps["xyY"]["XYZ"](obj, kwArgs); }
+		}
+	};
+
+	this.whitepoint=function(/* String */wpName, /* String? */observer){
+		observer=observer||"10";
+		var x=0, y=0, t=0;
+		if(wpMap[observer] && wpMap[observer][wpName]){
+			x=wpMap[observer][wpName].x;
+			y=wpMap[observer][wpName].y;
+			t=wpMap[observer][wpName].t;
+		} else {
+			console.warn(
+				"dojox.color.Colorspace::whitepoint: either the observer or the whitepoint name was not found. ", 
+				observer, wpName
+			);
+		}
+		var wp={ x:x, y:y, z:(1-x-y), t:t, Y:1 };
+		return this.convert(wp, "xyY", "XYZ");
+	};
+
+	this.tempToWhitepoint=function(/* Number */t){
+		if(t<4000){
+			console.warn("dojox.color.Colorspace::tempToWhitepoint: can't find a white point for temperatures less than 4000K. (Passed ", t, ").");
+			return { x:0, y:0 };
+		}
+		if(t>25000){
+			console.warn("dojox.color.Colorspace::tempToWhitepoint: can't find a white point for temperatures greater than 25000K. (Passed ", t, ").");
+			return { x:0, y:0 };
+		}
+		var t1=t, t2=t*t, t3=t2*t;
+		var ten9=Math.pow(10, 9), ten6=Math.pow(10, 6), ten3=Math.pow(10,3);
+		if(t<=7000){
+			var x=(-4.607*ten9/t3)+(2.9678*ten6/t2)+(0.09911*ten3/t)+0.2444063;
+		} else {
+			var x=(-2.0064*ten9/t3)+(1.9018*ten6/t2)+(0.24748*ten3/t)+0.23704;
+		}
+		var y=-3*x*x+2.87*x-0.275;
+		return { x:x, y:y };
+	};
+
+	this.primaries=function(/* Object */kwArgs){
+		//	mix in the defaults.
+		kwArgs=dojo.mixin({
+			profile:"sRGB",
+			whitepoint:"D65",
+			observer:"10",
+			adaptor:"Bradford"
+		}, kwArgs||{});
+
+		var m=[];
+		if(profiles[kwArgs.profile]){
+			m=profiles[kwArgs.profile].slice(0);
+		} else {
+			console.warn(
+				"dojox.color.Colorspace::primaries: the passed profile was not found.  ",
+				"Available profiles include: ", profiles, 
+				".  The profile passed was ", kwArgs.profile
+			);
+		}
+		var primary={
+			name:kwArgs.profile,
+			gamma:m[0], whitepoint:m[1], 
+			xr:m[2], yr:m[3], Yr:m[4],
+			xg:m[5], yg:m[6], Yg:m[7],
+			xb:m[8], yb:m[9], Yb:m[10]
+		};
+		
+		//	convert for the whitepoint
+		if(kwArgs.whitepoint!=primary.whitepoint){
+			var r=this.convert(
+				this.adapt({
+					color:this.convert({ x:xr, y:yr, Y:Yr }, "xyY", "XYZ"),
+					adaptor:kwArgs.adaptor, 
+					source:primary.whitepoint, 
+					destination:kwArgs.whitepoint
+				}),
+				"XYZ",
+				"xyY"
+			);
+			var g=this.convert(
+				this.adapt({
+					color:this.convert({ x:xg, y:yg, Y:Yg }, "xyY", "XYZ"),
+					adaptor:kwArgs.adaptor, 
+					source:primary.whitepoint, 
+					destination:kwArgs.whitepoint
+				}),
+				"XYZ",
+				"xyY"
+			);
+			var b=this.convert(
+				this.adapt({
+					color:this.convert({ x:xb, y:yb, Y:Yb }, "xyY", "XYZ"),
+					adaptor:kwArgs.adaptor, 
+					source:primary.whitepoint, 
+					destination:kwArgs.whitepoint
+				}),
+				"XYZ",
+				"xyY"
+			);
+			primary=dojo.mixin(primary, {
+				xr: r.x, yr: r.y, Yr: r.Y,
+				xg: g.x, yg: g.y, Yg: g.Y,
+				xb: b.x, yb: b.y, Yb: b.Y,
+				whitepoint: kwArgs.whitepoint
+			});
+		}
+		return dojo.mixin(primary, {
+			zr: 1-primary.xr-primary.yr,
+			zg: 1-primary.xg-primary.yg,
+			zb: 1-primary.xb-primary.yb
+		});		//	Object
+	};
+
+	this.adapt=function(/* Object */kwArgs){
+		//	color is required in the form of XYZ, source whitepoint name is required.
+		if(!kwArgs.color || !kwArgs.source){
+			console.error("dojox.color.Colorspace::adapt: color and source arguments are required. ", kwArgs);
+		}
+
+		//	defaults
+		kwArgs=dojo.mixin({
+			adaptor:"Bradford",
+			destination:"D65"
+		}, kwArgs);
+
+		//	adapt
+		var swp = this.whitepoint(kwArgs.source);
+		var dwp = this.whitepoint(kwArgs.destination);
+		if(adaptors[kwArgs.adaptor]){
+			var ma=adaptors[kwArgs.adaptor].ma;
+			var mai=adaptors[kwArgs.adaptor].mai;
+		}else{
+			console.warn("dojox.color.Colorspace::adapt: the passed adaptor '", kwArgs.adaptor, "' was not found.");
+		}
+		var dSrc=dxm.multiply([[swp.x, swp.y, swp.z]], ma);
+		var dDest=dxm.multiply([[dwp.x, dwp.y, dwp.z]], ma);
+		var center=[
+			[dDest[0][0]/dSrc[0][0], 0, 0],
+			[0, dDest[0][1]/dSrc[0][1], 0],
+			[0, 0, dDest[0][2]/dSrc[0][2]]
+		];
+		var m=dxm.multiply(dxm.multiply(ma, center), mai);
+		var r=dxm.multiply([[ kwArgs.color.X, kwArgs.color.Y, kwArgs.color.Z ]], m)[0];
+		return { X:r[0], Y:r[1], Z:r[2] };
+	};
+
+	this.matrix=function(/* String */to, /* Object */primary){
+		var wp=this.whitepoint(primary.whitepoint);
+		var Xr = p.xr/p.yr, Yr = 1, Zr = (1-p.xr-p.yr)/p.yr;
+		var Xg = p.xg/p.yg, Yg = 1, Zg = (1-p.xg-p.yg)/p.yg;
+		var Xb = p.xb/p.yb, Yb = 1, Zr = (1-p.xb-p.yb)/p.yb;
+
+		var m1 = [[ Xr, Yr, Zr ], [ Xg, Yg, Zg ], [ Xb, Yb, Zb ]];
+		var m2 = [[ wp.X, wp.Y, wp.Z ]];
+		var sm = dojox.math.matrix.multiply(m2, dojox.math.matrix.inverse(m1));
+		var Sr = sm[0][0], Sg = sm[0][1], Sb = sm[0][2];
+		var result=[
+			[Sr*Xr, Sr*Yr, Sr*Zr],
+			[Sg*Xg, Sg*Yg, Sg*Zg],
+			[Sb*Xb, Sb*Yb, Sb*Zb]
+		];
+		if(to=="RGB"){ return dojox.math.inverse(result); }
+		return result;
+	};
+
+	this.epsilon=function(/* bool? */useApprox){
+		return (useApprox || typeof(useApprox)=="undefined")? 0.008856: 216/24289;
+	};
+	this.kappa=function(/* bool? */useApprox){
+		return (useApprox || typeof(useApprox)=="undefined")? 903.3: 24389/27;
+	};
+
+	this.convert=function(/* Object */color, /* string */from, /* string */to, /* Object? */kwArgs){
+		if(converters[from] && converters[from][to]){
+			return converters[from][to](obj, kwArgs);
+		}
+		console.warn("dojox.color.Colorspace::convert: Can't convert ", color, " from ", from, " to ", to, ".");
+	};
 })();
-dojo.mixin(dojox.color,{fromXYZ:function(xyz,_9e){
-_9e=_9e||{};
-var p=dojox.color.Colorspace.primaries(_9e);
-var m=dojox.color.Colorspace.matrix("RGB",p);
-var rgb=dojox.math.matrix.mutliply([[xyz.X,xyz.Y,xyz.Z]],m);
-var r=rgb[0][0],g=rgb[0][1],b=rgb[0][2];
-if(p.profile=="sRGB"){
-var R=(r>0.0031308)?(1.055*Math.pow(r,1/2.4))-0.055:12.92*r;
-var G=(g>0.0031308)?(1.055*Math.pow(g,1/2.4))-0.055:12.92*g;
-var B=(b>0.0031308)?(1.055*Math.pow(b,1/2.4))-0.055:12.92*b;
-}else{
-var R=Math.pow(r,1/p.gamma),G=Math.pow(g,1/p.gamma),B=Math.pow(b,1/p.gamma);
-}
-return new dojox.color.Color({r:Math.floor(R*255),g:Math.floor(G*255),b:Math.floor(B*255)});
-}});
-dojo.extend(dojox.color.Color,{toXYZ:function(_9f){
-_9f=_9f||{};
-var p=dojox.color.Colorspace.primaries(_9f);
-var m=dojox.color.Colorspace.matrix("XYZ",p);
-var _a0=this.r/255,_a1=this.g/255,_a2=this.b/255;
-if(p.profile=="sRGB"){
-var r=(_a0>0.04045)?Math.pow(((_a0+0.055)/1.055),2.4):_a0/12.92;
-var g=(_a1>0.04045)?Math.pow(((_a1+0.055)/1.055),2.4):_a1/12.92;
-var b=(_a2>0.04045)?Math.pow(((_a2+0.055)/1.055),2.4):_a2/12.92;
-}else{
-var r=Math.pow(_a0,p.gamma),g=Math.pow(_a1,p.gamma),b=Math.pow(_a2,p.gamma);
-}
-var xyz=dojox.math.matrix([[r,g,b]],m);
-return {X:xyz[0][0],Y:xyz[0][1],Z:xyz[0][2]};
-}});
-}
+
+//	More dojox.color and dojox.color.Color extensions
+dojo.mixin(dojox.color, {
+	fromXYZ: function(/* Object */xyz, /* Object?*/kwArgs){
+		kwArgs=kwArgs||{};
+		var p=dojox.color.Colorspace.primaries(kwArgs);
+		var m=dojox.color.Colorspace.matrix("RGB", p);
+		var rgb=dojox.math.matrix.mutliply([[ xyz.X, xyz.Y, xyz.Z ]], m);
+		var r=rgb[0][0], g=rgb[0][1], b=rgb[0][2];
+		if(p.profile=="sRGB"){
+			var R = (r>0.0031308)?(1.055*Math.pow(r, 1/2.4))-0.055: 12.92*r;
+			var G = (g>0.0031308)?(1.055*Math.pow(g, 1/2.4))-0.055: 12.92*g;
+			var B = (b>0.0031308)?(1.055*Math.pow(b, 1/2.4))-0.055: 12.92*b;
+		}else{
+			var R=Math.pow(r, 1/p.gamma), G=Math.pow(g, 1/p.gamma), B=Math.pow(b, 1/p.gamma);
+		}
+		return new dojox.color.Color({ r:Math.floor(R*255), g:Math.floor(G*255), b:Math.floor(B*255) });
+	}
+});
+
+dojo.extend(dojox.color.Color, {
+	toXYZ: function(/* Object */kwArgs){
+		kwArgs=kwArgs||{};
+		var p=dojox.color.Colorspace.primaries(kwArgs);
+		var m=dojox.color.Colorspace.matrix("XYZ", p);
+		var _r=this.r/255, _g=this.g/255, _b=this.b/255;
+		if(p.profile=="sRGB"){
+			var r=(_r>0.04045) ? Math.pow(((_r+0.055)/1.055), 2.4):_r/12.92;
+			var g=(_g>0.04045) ? Math.pow(((_g+0.055)/1.055), 2.4):_g/12.92;
+			var b=(_b>0.04045) ? Math.pow(((_b+0.055)/1.055), 2.4):_b/12.92;
+		} else {
+			var r=Math.pow(_r, p.gamma), g=Math.pow(_g, p.gamma), b=Math.pow(_b, p.gamma);
+		}
+		var xyz=dojox.math.matrix([[ r, g, b ]], m);
+		return { X: xyz[0][0], Y: xyz[0][1], Z: xyz[0][2] };	//	Object
+	}
+});
diff --git a/dojox/color/Palette.js b/dojox/color/Palette.js
index b8f6ea3..6aeb5c0 100644
--- a/dojox/color/Palette.js
+++ b/dojox/color/Palette.js
@@ -1,174 +1,482 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.color.Palette"]){
-dojo._hasResource["dojox.color.Palette"]=true;
 dojo.provide("dojox.color.Palette");
 dojo.require("dojox.color");
+
 (function(){
-var _1=dojox.color;
-_1.Palette=function(_2){
-this.colors=[];
-if(_2 instanceof dojox.color.Palette){
-this.colors=_2.colors.slice(0);
-}else{
-if(_2 instanceof dojox.color.Color){
-this.colors=[null,null,_2,null,null];
-}else{
-if(dojo.isArray(_2)){
-this.colors=dojo.map(_2.slice(0),function(_3){
-if(dojo.isString(_3)){
-return new dojox.color.Color(_3);
-}
-return _3;
-});
-}else{
-if(dojo.isString(_2)){
-this.colors=[null,null,new dojox.color.Color(_2),null,null];
-}
-}
-}
-}
-};
-function _4(p,_5,_6){
-var _7=new dojox.color.Palette();
-_7.colors=[];
-dojo.forEach(p.colors,function(_8){
-var r=(_5=="dr")?_8.r+_6:_8.r,g=(_5=="dg")?_8.g+_6:_8.g,b=(_5=="db")?_8.b+_6:_8.b,a=(_5=="da")?_8.a+_6:_8.a;
-_7.colors.push(new dojox.color.Color({r:Math.min(255,Math.max(0,r)),g:Math.min(255,Math.max(0,g)),b:Math.min(255,Math.max(0,b)),a:Math.min(1,Math.max(0,a))}));
-});
-return _7;
-};
-function _9(p,_a,_b){
-var _c=new dojox.color.Palette();
-_c.colors=[];
-dojo.forEach(p.colors,function(_d){
-var o=_d.toCmy(),c=(_a=="dc")?o.c+_b:o.c,m=(_a=="dm")?o.m+_b:o.m,y=(_a=="dy")?o.y+_b:o.y;
-_c.colors.push(dojox.color.fromCmy(Math.min(100,Math.max(0,c)),Math.min(100,Math.max(0,m)),Math.min(100,Math.max(0,y))));
-});
-return _c;
-};
-function _e(p,_f,val){
-var ret=new dojox.color.Palette();
-ret.colors=[];
-dojo.forEach(p.colors,function(_10){
-var o=_10.toCmyk(),c=(_f=="dc")?o.c+val:o.c,m=(_f=="dm")?o.m+val:o.m,y=(_f=="dy")?o.y+val:o.y,k=(_f=="dk")?o.b+val:o.b;
-ret.colors.push(dojox.color.fromCmyk(Math.min(100,Math.max(0,c)),Math.min(100,Math.max(0,m)),Math.min(100,Math.max(0,y)),Math.min(100,Math.max(0,k))));
-});
-return ret;
-};
-function _11(p,_12,val){
-var ret=new dojox.color.Palette();
-ret.colors=[];
-dojo.forEach(p.colors,function(_13){
-var o=_13.toHsl(),h=(_12=="dh")?o.h+val:o.h,s=(_12=="ds")?o.s+val:o.s,l=(_12=="dl")?o.l+val:o.l;
-ret.colors.push(dojox.color.fromHsl(h%360,Math.min(100,Math.max(0,s)),Math.min(100,Math.max(0,l))));
-});
-return ret;
-};
-function _14(p,_15,val){
-var ret=new dojox.color.Palette();
-ret.colors=[];
-dojo.forEach(p.colors,function(_16){
-var o=_16.toHsv(),h=(_15=="dh")?o.h+val:o.h,s=(_15=="ds")?o.s+val:o.s,v=(_15=="dv")?o.v+val:o.v;
-ret.colors.push(dojox.color.fromHsv(h%360,Math.min(100,Math.max(0,s)),Math.min(100,Math.max(0,v))));
-});
-return ret;
-};
-function _17(val,low,_18){
-return _18-((_18-val)*((_18-low)/_18));
-};
-dojo.extend(_1.Palette,{transform:function(_19){
-var fn=_4;
-if(_19.use){
-var use=_19.use.toLowerCase();
-if(use.indexOf("hs")==0){
-if(use.charAt(2)=="l"){
-fn=_11;
-}else{
-fn=_14;
-}
-}else{
-if(use.indexOf("cmy")==0){
-if(use.charAt(3)=="k"){
-fn=_e;
-}else{
-fn=_9;
-}
-}
-}
-}else{
-if("dc" in _19||"dm" in _19||"dy" in _19){
-if("dk" in _19){
-fn=_e;
-}else{
-fn=_9;
-}
-}else{
-if("dh" in _19||"ds" in _19){
-if("dv" in _19){
-fn=_14;
-}else{
-fn=_11;
-}
-}
-}
-}
-var _1a=this;
-for(var p in _19){
-if(p=="use"){
-continue;
-}
-_1a=fn(_1a,p,_19[p]);
-}
-return _1a;
-},clone:function(){
-return new _1.Palette(this);
-}});
-dojo.mixin(_1.Palette,{generators:{analogous:function(_1b){
-var _1c=_1b.high||60,low=_1b.low||18,_1d=dojo.isString(_1b.base)?new dojox.color.Color(_1b.base):_1b.base,hsv=_1d.toHsv();
-var h=[(hsv.h+low+360)%360,(hsv.h+Math.round(low/2)+360)%360,hsv.h,(hsv.h-Math.round(_1c/2)+360)%360,(hsv.h-_1c+360)%360];
-var s1=Math.max(10,(hsv.s<=95)?hsv.s+5:(100-(hsv.s-95))),s2=(hsv.s>1)?hsv.s-1:21-hsv.s,v1=(hsv.v>=92)?hsv.v-9:Math.max(hsv.v+9,20),v2=(hsv.v<=90)?Math.max(hsv.v+5,20):(95+Math.ceil((hsv.v-90)/2)),s=[s1,s2,hsv.s,s1,s1],v=[v1,v2,hsv.v,v1,v2];
-return new _1.Palette(dojo.map(h,function(hue,i){
-return dojox.color.fromHsv(hue,s[i],v[i]);
-}));
-},monochromatic:function(_1e){
-var _1f=dojo.isString(_1e.base)?new dojox.color.Color(_1e.base):_1e.base,hsv=_1f.toHsv();
-var s1=(hsv.s-30>9)?hsv.s-30:hsv.s+30,s2=hsv.s,v1=_17(hsv.v,20,100),v2=(hsv.v-20>20)?hsv.v-20:hsv.v+60,v3=(hsv.v-50>20)?hsv.v-50:hsv.v+30;
-return new _1.Palette([dojox.color.fromHsv(hsv.h,s1,v1),dojox.color.fromHsv(hsv.h,s2,v3),_1f,dojox.color.fromHsv(hsv.h,s1,v3),dojox.color.fromHsv(hsv.h,s2,v2)]);
-},triadic:function(_20){
-var _21=dojo.isString(_20.base)?new dojox.color.Color(_20.base):_20.base,hsv=_21.toHsv();
-var h1=(hsv.h+57+360)%360,h2=(hsv.h-157+360)%360,s1=(hsv.s>20)?hsv.s-10:hsv.s+10,s2=(hsv.s>90)?hsv.s-10:hsv.s+10,s3=(hsv.s>95)?hsv.s-5:hsv.s+5,v1=(hsv.v-20>20)?hsv.v-20:hsv.v+20,v2=(hsv.v-30>20)?hsv.v-30:hsv.v+30,v3=(hsv.v-30>70)?hsv.v-30:hsv.v+30;
-return new _1.Palette([dojox.color.fromHsv(h1,s1,hsv.v),dojox.color.fromHsv(hsv.h,s2,v2),_21,dojox.color.fromHsv(h2,s2,v1),dojox.color.fromHsv(h2,s3,v3)]);
-},complementary:function(_22){
-var _23=dojo.isString(_22.base)?new dojox.color.Color(_22.base):_22.base,hsv=_23.toHsv();
-var h1=((hsv.h*2)+137<360)?(hsv.h*2)+137:Math.floor(hsv.h/2)-137,s1=Math.max(hsv.s-10,0),s2=_17(hsv.s,10,100),s3=Math.min(100,hsv.s+20),v1=Math.min(100,hsv.v+30),v2=(hsv.v>20)?hsv.v-30:hsv.v+30;
-return new _1.Palette([dojox.color.fromHsv(hsv.h,s1,v1),dojox.color.fromHsv(hsv.h,s2,v2),_23,dojox.color.fromHsv(h1,s3,v2),dojox.color.fromHsv(h1,hsv.s,hsv.v)]);
-},splitComplementary:function(_24){
-var _25=dojo.isString(_24.base)?new dojox.color.Color(_24.base):_24.base,_26=_24.da||30,hsv=_25.toHsv();
-var _27=((hsv.h*2)+137<360)?(hsv.h*2)+137:Math.floor(hsv.h/2)-137,h1=(_27-_26+360)%360,h2=(_27+_26)%360,s1=Math.max(hsv.s-10,0),s2=_17(hsv.s,10,100),s3=Math.min(100,hsv.s+20),v1=Math.min(100,hsv.v+30),v2=(hsv.v>20)?hsv.v-30:hsv.v+30;
-return new _1.Palette([dojox.color.fromHsv(h1,s1,v1),dojox.color.fromHsv(h1,s2,v2),_25,dojox.color.fromHsv(h2,s3,v2),dojox.color.fromHsv(h2,hsv.s,hsv.v)]);
-},compound:function(_28){
-var _29=dojo.isString(_28.base)?new dojox.color.Color(_28.base):_28.base,hsv=_29.toHsv();
-var h1=((hsv.h*2)+18<360)?(hsv.h*2)+18:Math.floor(hsv.h/2)-18,h2=((hsv.h*2)+120<360)?(hsv.h*2)+120:Math.floor(hsv.h/2)-120,h3=((hsv.h*2)+99<360)?(hsv.h*2)+99:Math.floor(hsv.h/2)-99,s1=(hsv.s-40>10)?hsv.s-40:hsv.s+40,s2=(hsv.s-10>80)?hsv.s-10:hsv.s+10,s3=(hsv.s-25>10)?hsv.s-25:hsv.s+25,v1=(hsv.v-40>10)?hsv.v-40:hsv.v+40,v2=(hsv.v-20>80)?hsv.v-20:hsv.v+20,v3=Math.max(hsv.v,20);
-return new _1.Palette([dojox.color.fromHsv(h1,s1,v1),dojox.color.fromHsv(h1,s2,v2),_29,dojox.color.fromHsv(h2,s3,v3),dojox.color.fromHsv(h3,s2,v2)]);
-},shades:function(_2a){
-var _2b=dojo.isString(_2a.base)?new dojox.color.Color(_2a.base):_2a.base,hsv=_2b.toHsv();
-var s=(hsv.s==100&&hsv.v==0)?0:hsv.s,v1=(hsv.v-50>20)?hsv.v-50:hsv.v+30,v2=(hsv.v-25>=20)?hsv.v-25:hsv.v+55,v3=(hsv.v-75>=20)?hsv.v-75:hsv.v+5,v4=Math.max(hsv.v-10,20);
-return new _1.Palette([new dojox.color.fromHsv(hsv.h,s,v1),new dojox.color.fromHsv(hsv.h,s,v2),_2b,new dojox.color.fromHsv(hsv.h,s,v3),new dojox.color.fromHsv(hsv.h,s,v4)]);
-}},generate:function(_2c,_2d){
-if(dojo.isFunction(_2d)){
-return _2d({base:_2c});
-}else{
-if(_1.Palette.generators[_2d]){
-return _1.Palette.generators[_2d]({base:_2c});
-}
+	var dxc = dojox.color;
+	/***************************************************************
+	*	dojox.color.Palette
+	*
+	*	The Palette object is loosely based on the color palettes
+	*	at Kuler (http://kuler.adobe.com).  They are 5 color palettes
+	*	with the base color considered to be the third color in the
+	*	palette (for generation purposes).
+	*
+	*	Palettes can be generated from well-known algorithms or they
+	* 	can be manually created by passing an array to the constructor.
+	*
+	*	Palettes can be transformed, using a set of specific params
+	*	similar to the way shapes can be transformed with dojox.gfx.
+	*	However, unlike with transformations in dojox.gfx, transforming
+	* 	a palette will return you a new Palette object, in effect
+	* 	a clone of the original.
+	***************************************************************/
+
+	//	ctor ----------------------------------------------------------------------------
+	dxc.Palette = function(/* String|Array|dojox.color.Color|dojox.color.Palette */base){
+		//	summary:
+		//		An object that represents a palette of colors.
+		//	description:
+		//		A Palette is a representation of a set of colors.  While the standard
+		//		number of colors contained in a palette is 5, it can really handle any
+		//		number of colors.
+		//
+		//		A palette is useful for the ability to transform all the colors in it
+		//		using a simple object-based approach.  In addition, you can generate
+		//		palettes using dojox.color.Palette.generate; these generated palettes
+		//		are based on the palette generators at http://kuler.adobe.com.
+		//
+		//	colors: dojox.color.Color[]
+		//		The actual color references in this palette.
+		this.colors = [];
+		if(base instanceof dojox.color.Palette){
+			this.colors = base.colors.slice(0);
+		}
+		else if(base instanceof dojox.color.Color){
+			this.colors = [ null, null, base, null, null ];
+		}
+		else if(dojo.isArray(base)){
+			this.colors = dojo.map(base.slice(0), function(item){
+				if(dojo.isString(item)){ return new dojox.color.Color(item); }
+				return item;
+			});
+		}
+		else if (dojo.isString(base)){
+			this.colors = [ null, null, new dojox.color.Color(base), null, null ];
+		}
+	}
+
+	//	private functions ---------------------------------------------------------------
+
+	//	transformations
+	function tRGBA(p, param, val){
+		var ret = new dojox.color.Palette();
+		ret.colors = [];
+		dojo.forEach(p.colors, function(item){
+			var r=(param=="dr")?item.r+val:item.r,
+				g=(param=="dg")?item.g+val:item.g,
+				b=(param=="db")?item.b+val:item.b,
+				a=(param=="da")?item.a+val:item.a
+			ret.colors.push(new dojox.color.Color({
+				r: Math.min(255, Math.max(0, r)),
+				g: Math.min(255, Math.max(0, g)),
+				b: Math.min(255, Math.max(0, b)),
+				a: Math.min(1, Math.max(0, a))
+			}));
+		});
+		return ret;
+	}
+
+	function tCMY(p, param, val){
+		var ret = new dojox.color.Palette();
+		ret.colors = [];
+		dojo.forEach(p.colors, function(item){
+			var o=item.toCmy(), 
+				c=(param=="dc")?o.c+val:o.c,
+				m=(param=="dm")?o.m+val:o.m,
+				y=(param=="dy")?o.y+val:o.y;
+			ret.colors.push(dojox.color.fromCmy(
+				Math.min(100, Math.max(0, c)),
+				Math.min(100, Math.max(0, m)),
+				Math.min(100, Math.max(0, y))
+			));
+		});
+		return ret;
+	}
+
+	function tCMYK(p, param, val){
+		var ret = new dojox.color.Palette();
+		ret.colors = [];
+		dojo.forEach(p.colors, function(item){
+			var o=item.toCmyk(), 
+				c=(param=="dc")?o.c+val:o.c,
+				m=(param=="dm")?o.m+val:o.m,
+				y=(param=="dy")?o.y+val:o.y,
+				k=(param=="dk")?o.b+val:o.b;
+			ret.colors.push(dojox.color.fromCmyk(
+				Math.min(100, Math.max(0, c)),
+				Math.min(100, Math.max(0, m)),
+				Math.min(100, Math.max(0, y)),
+				Math.min(100, Math.max(0, k))
+			));
+		});
+		return ret;
+	}
+
+	function tHSL(p, param, val){
+		var ret = new dojox.color.Palette();
+		ret.colors = [];
+		dojo.forEach(p.colors, function(item){
+			var o=item.toHsl(), 
+				h=(param=="dh")?o.h+val:o.h,
+				s=(param=="ds")?o.s+val:o.s,
+				l=(param=="dl")?o.l+val:o.l;
+			ret.colors.push(dojox.color.fromHsl(h%360, Math.min(100, Math.max(0, s)), Math.min(100, Math.max(0, l))));
+		});
+		return ret;
+	}
+
+	function tHSV(p, param, val){
+		var ret = new dojox.color.Palette();
+		ret.colors = [];
+		dojo.forEach(p.colors, function(item){
+			var o=item.toHsv(), 
+				h=(param=="dh")?o.h+val:o.h,
+				s=(param=="ds")?o.s+val:o.s,
+				v=(param=="dv")?o.v+val:o.v;
+			ret.colors.push(dojox.color.fromHsv(h%360, Math.min(100, Math.max(0, s)), Math.min(100, Math.max(0, v))));
+		});
+		return ret;
+	}
+
+	//	helper functions
+	function rangeDiff(val, low, high){
+		//	given the value in a range from 0 to high, find the equiv
+		//		using the range low to high.
+		return high-((high-val)*((high-low)/high));
+	}
+
+	//	object methods ---------------------------------------------------------------
+	dojo.extend(dxc.Palette, {
+		transform: function(/* dojox.color.Palette.__transformArgs */kwArgs){
+			//	summary:
+			//		Transform the palette using a specific transformation function
+			//		and a set of transformation parameters.
+			//	description:
+			//		{palette}.transform is a simple way to uniformly transform
+			//		all of the colors in a palette using any of 5 formulae:
+			//		RGBA, HSL, HSV, CMYK or CMY.
+			//
+			//		Once the forumula to be used is determined, you can pass any
+			//		number of parameters based on the formula "d"[param]; for instance,
+			//		{ use: "rgba", dr: 20, dg: -50 } will take all of the colors in
+			//		palette, add 20 to the R value and subtract 50 from the G value.
+			//
+			//		Unlike other types of transformations, transform does *not* alter
+			//		the original palette but will instead return a new one.
+			var fn=tRGBA;	//	the default transform function.
+			if(kwArgs.use){
+				//	we are being specific about the algo we want to use.
+				var use=kwArgs.use.toLowerCase();
+				if(use.indexOf("hs")==0){
+					if(use.charAt(2)=="l"){ fn=tHSL; }
+					else { fn=tHSV; }
+				}
+				else if(use.indexOf("cmy")==0){
+					if(use.charAt(3)=="k"){ fn=tCMYK; }
+					else { fn=tCMY; }
+				}
+			}
+			//	try to guess the best choice.
+			else if("dc" in kwArgs || "dm" in kwArgs || "dy" in kwArgs){
+				if("dk" in kwArgs){ fn = tCMYK; }
+				else { fn = tCMY; }
+			}
+			else if("dh" in kwArgs || "ds" in kwArgs){
+				if("dv" in kwArgs){ fn = tHSV; }
+				else { fn = tHSL; }
+			}
+
+			var palette = this;
+			for(var p in kwArgs){
+				//	ignore use
+				if(p=="use"){ continue; }
+				palette = fn(palette, p, kwArgs[p]);
+			}
+			return palette;		//	dojox.color.Palette
+		},
+		clone: function(){
+			//	summary:
+			//		Clones the current palette.
+			return new dxc.Palette(this);	//	dojox.color.Palette
+		}
+	});
+
+/*=====
+dojox.color.Palette.__transformArgs = function(use, dr, dg, db, da, dc, dm, dy, dk, dh, ds, dv, dl){
+	//	summary:
+	//		The keywords argument to be passed to the dojox.color.Palette.transform function.  Note that
+	//		while all arguments are optional, *some* arguments must be passed.  The basic concept is that
+	//		you pass a delta value for a specific aspect of a color model (or multiple aspects of the same
+	//		color model); for instance, if you wish to transform a palette based on the HSV color model,
+	//		you would pass one of "dh", "ds", or "dv" as a value.
+	//
+	//	use: String?
+	//		Specify the color model to use for the transformation.  Can be "rgb", "rgba", "hsv", "hsl", "cmy", "cmyk".
+	//	dr: Number?
+	//		The delta to be applied to the red aspect of the RGB/RGBA color model.
+	//	dg: Number?
+	//		The delta to be applied to the green aspect of the RGB/RGBA color model.
+	//	db: Number?
+	//		The delta to be applied to the blue aspect of the RGB/RGBA color model.
+	//	da: Number?
+	//		The delta to be applied to the alpha aspect of the RGBA color model.
+	//	dc: Number?
+	//		The delta to be applied to the cyan aspect of the CMY/CMYK color model.
+	//	dm: Number?
+	//		The delta to be applied to the magenta aspect of the CMY/CMYK color model.
+	//	dy: Number?
+	//		The delta to be applied to the yellow aspect of the CMY/CMYK color model.
+	//	dk: Number?
+	//		The delta to be applied to the black aspect of the CMYK color model.
+	//	dh: Number?
+	//		The delta to be applied to the hue aspect of the HSL/HSV color model.
+	//	ds: Number?
+	//		The delta to be applied to the saturation aspect of the HSL/HSV color model.
+	//	dl: Number?
+	//		The delta to be applied to the luminosity aspect of the HSL color model.
+	//	dv: Number?
+	//		The delta to be applied to the value aspect of the HSV color model.
+	this.use = use;
+	this.dr = dr;
+	this.dg = dg;
+	this.db = db;
+	this.da = da;
+	this.dc = dc;
+	this.dm = dm;
+	this.dy = dy;
+	this.dk = dk;
+	this.dh = dh;
+	this.ds = ds;
+	this.dl = dl;
+	this.dv = dv;
 }
-throw new Error("dojox.color.Palette.generate: the specified generator ('"+_2d+"') does not exist.");
-}});
+dojox.color.Palette.__generatorArgs = function(base){
+	//	summary:
+	//		The keyword arguments object used to create a palette based on a base color.
+	//
+	//	base: dojo.Color
+	//		The base color to be used to generate the palette.
+	this.base = base;
+} 
+dojox.color.Palette.__analogousArgs = function(base, high, low){
+	//	summary:
+	//		The keyword arguments object that is used to create a 5 color palette based on the
+	//		analogous rules as implemented at http://kuler.adobe.com, using the HSV color model.
+	//
+	//	base: dojo.Color
+	//		The base color to be used to generate the palette.
+	//	high: Number?
+	//		The difference between the hue of the base color and the highest hue.  In degrees, default is 60.
+	//	low: Number?
+	//		The difference between the hue of the base color and the lowest hue.  In degrees, default is 18.
+	this.base = base;
+	this.high = high;
+	this.low = low;
+} 
+dojox.color.Palette.__splitComplementaryArgs = function(base, da){
+	//	summary:
+	//		The keyword arguments object used to create a palette based on the split complementary rules
+	//		as implemented at http://kuler.adobe.com.
+	//
+	//	base: dojo.Color
+	//		The base color to be used to generate the palette.
+	//	da: Number?
+	//		The delta angle to be used to determine where the split for the complementary rules happen.
+	//		In degrees, the default is 30.
+	this.base = base;
+	this.da = da;
+} 
+=====*/
+	dojo.mixin(dxc.Palette, {
+		generators: {
+			analogous:function(/* dojox.color.Palette.__analogousArgs */args){
+				//	summary:
+				//		Create a 5 color palette based on the analogous rules as implemented at
+				//		http://kuler.adobe.com.
+				var high=args.high||60, 	//	delta between base hue and highest hue (subtracted from base)
+					low=args.low||18,		//	delta between base hue and lowest hue (added to base)
+					base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
+					hsv=base.toHsv();
+
+				//	generate our hue angle differences
+				var h=[
+					(hsv.h+low+360)%360,
+					(hsv.h+Math.round(low/2)+360)%360,
+					hsv.h,
+					(hsv.h-Math.round(high/2)+360)%360,
+					(hsv.h-high+360)%360
+				];
+
+				var s1=Math.max(10, (hsv.s<=95)?hsv.s+5:(100-(hsv.s-95))),
+					s2=(hsv.s>1)?hsv.s-1:21-hsv.s,
+					v1=(hsv.v>=92)?hsv.v-9:Math.max(hsv.v+9, 20),
+					v2=(hsv.v<=90)?Math.max(hsv.v+5, 20):(95+Math.ceil((hsv.v-90)/2)),
+					s=[ s1, s2, hsv.s, s1, s1 ],
+					v=[ v1, v2, hsv.v, v1, v2 ]
+
+				return new dxc.Palette(dojo.map(h, function(hue, i){
+					return dojox.color.fromHsv(hue, s[i], v[i]);
+				}));		//	dojox.color.Palette
+			},
+
+			monochromatic: function(/* dojox.color.Palette.__generatorArgs */args){
+				//	summary:
+				//		Create a 5 color palette based on the monochromatic rules as implemented at
+				//		http://kuler.adobe.com.
+				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
+					hsv = base.toHsv();
+				
+				//	figure out the saturation and value
+				var s1 = (hsv.s-30>9)?hsv.s-30:hsv.s+30,
+					s2 = hsv.s,
+					v1 = rangeDiff(hsv.v, 20, 100),
+					v2 = (hsv.v-20>20)?hsv.v-20:hsv.v+60,
+					v3 = (hsv.v-50>20)?hsv.v-50:hsv.v+30;
+
+				return new dxc.Palette([
+					dojox.color.fromHsv(hsv.h, s1, v1),
+					dojox.color.fromHsv(hsv.h, s2, v3),
+					base,
+					dojox.color.fromHsv(hsv.h, s1, v3),
+					dojox.color.fromHsv(hsv.h, s2, v2)
+				]);		//	dojox.color.Palette
+			},
+
+			triadic: function(/* dojox.color.Palette.__generatorArgs */args){
+				//	summary:
+				//		Create a 5 color palette based on the triadic rules as implemented at
+				//		http://kuler.adobe.com.
+				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
+					hsv = base.toHsv();
+
+				var h1 = (hsv.h+57+360)%360,
+					h2 = (hsv.h-157+360)%360,
+					s1 = (hsv.s>20)?hsv.s-10:hsv.s+10,
+					s2 = (hsv.s>90)?hsv.s-10:hsv.s+10,
+					s3 = (hsv.s>95)?hsv.s-5:hsv.s+5,
+					v1 = (hsv.v-20>20)?hsv.v-20:hsv.v+20,
+					v2 = (hsv.v-30>20)?hsv.v-30:hsv.v+30,
+					v3 = (hsv.v-30>70)?hsv.v-30:hsv.v+30;
+
+				return new dxc.Palette([
+					dojox.color.fromHsv(h1, s1, hsv.v),
+					dojox.color.fromHsv(hsv.h, s2, v2),
+					base,
+					dojox.color.fromHsv(h2, s2, v1),
+					dojox.color.fromHsv(h2, s3, v3)
+				]);		//	dojox.color.Palette
+			},
+
+			complementary: function(/* dojox.color.Palette.__generatorArgs */args){
+				//	summary:
+				//		Create a 5 color palette based on the complementary rules as implemented at
+				//		http://kuler.adobe.com.
+				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
+					hsv = base.toHsv();
+
+				var h1 = ((hsv.h*2)+137<360)?(hsv.h*2)+137:Math.floor(hsv.h/2)-137,
+					s1 = Math.max(hsv.s-10, 0),
+					s2 = rangeDiff(hsv.s, 10, 100),
+					s3 = Math.min(100, hsv.s+20),
+					v1 = Math.min(100, hsv.v+30),
+					v2 = (hsv.v>20)?hsv.v-30:hsv.v+30;
+
+				return new dxc.Palette([
+					dojox.color.fromHsv(hsv.h, s1, v1),
+					dojox.color.fromHsv(hsv.h, s2, v2),
+					base,
+					dojox.color.fromHsv(h1, s3, v2),
+					dojox.color.fromHsv(h1, hsv.s, hsv.v)
+				]);		//	dojox.color.Palette
+			},
+
+			splitComplementary: function(/* dojox.color.Palette.__splitComplementaryArgs */args){
+				//	summary:
+				//		Create a 5 color palette based on the split complementary rules as implemented at
+				//		http://kuler.adobe.com.
+				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
+					dangle = args.da || 30,
+					hsv = base.toHsv();
+
+				var baseh = ((hsv.h*2)+137<360)?(hsv.h*2)+137:Math.floor(hsv.h/2)-137,
+					h1 = (baseh-dangle+360)%360,
+					h2 = (baseh+dangle)%360,
+					s1 = Math.max(hsv.s-10, 0),
+					s2 = rangeDiff(hsv.s, 10, 100),
+					s3 = Math.min(100, hsv.s+20),
+					v1 = Math.min(100, hsv.v+30),
+					v2 = (hsv.v>20)?hsv.v-30:hsv.v+30;
+
+				return new dxc.Palette([
+					dojox.color.fromHsv(h1, s1, v1),
+					dojox.color.fromHsv(h1, s2, v2),
+					base,
+					dojox.color.fromHsv(h2, s3, v2),
+					dojox.color.fromHsv(h2, hsv.s, hsv.v)
+				]);		//	dojox.color.Palette
+			},
+
+			compound: function(/* dojox.color.Palette.__generatorArgs */args){
+				//	summary:
+				//		Create a 5 color palette based on the compound rules as implemented at
+				//		http://kuler.adobe.com.
+				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
+					hsv = base.toHsv();
+
+				var h1 = ((hsv.h*2)+18<360)?(hsv.h*2)+18:Math.floor(hsv.h/2)-18,
+					h2 = ((hsv.h*2)+120<360)?(hsv.h*2)+120:Math.floor(hsv.h/2)-120,
+					h3 = ((hsv.h*2)+99<360)?(hsv.h*2)+99:Math.floor(hsv.h/2)-99,
+					s1 = (hsv.s-40>10)?hsv.s-40:hsv.s+40,
+					s2 = (hsv.s-10>80)?hsv.s-10:hsv.s+10,
+					s3 = (hsv.s-25>10)?hsv.s-25:hsv.s+25,
+					v1 = (hsv.v-40>10)?hsv.v-40:hsv.v+40,
+					v2 = (hsv.v-20>80)?hsv.v-20:hsv.v+20,
+					v3 = Math.max(hsv.v, 20);
+
+				return new dxc.Palette([
+					dojox.color.fromHsv(h1, s1, v1),
+					dojox.color.fromHsv(h1, s2, v2),
+					base,
+					dojox.color.fromHsv(h2, s3, v3),
+					dojox.color.fromHsv(h3, s2, v2)
+				]);		//	dojox.color.Palette
+			},
+
+			shades: function(/* dojox.color.Palette.__generatorArgs */args){
+				//	summary:
+				//		Create a 5 color palette based on the shades rules as implemented at
+				//		http://kuler.adobe.com.
+				var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
+					hsv = base.toHsv();
+
+				var s  = (hsv.s==100 && hsv.v==0)?0:hsv.s,
+					v1 = (hsv.v-50>20)?hsv.v-50:hsv.v+30,
+					v2 = (hsv.v-25>=20)?hsv.v-25:hsv.v+55,
+					v3 = (hsv.v-75>=20)?hsv.v-75:hsv.v+5,
+					v4 = Math.max(hsv.v-10, 20);
+
+				return new dxc.Palette([
+					new dojox.color.fromHsv(hsv.h, s, v1),
+					new dojox.color.fromHsv(hsv.h, s, v2),
+					base,
+					new dojox.color.fromHsv(hsv.h, s, v3),
+					new dojox.color.fromHsv(hsv.h, s, v4)
+				]);		//	dojox.color.Palette
+			}
+		},
+		generate: function(/* String|dojox.color.Color */base, /* Function|String */type){
+			//	summary:
+			//		Generate a new Palette using any of the named functions in
+			//		dojox.color.Palette.generators or an optional function definition.  Current
+			//		generators include "analogous", "monochromatic", "triadic", "complementary",
+			//		"splitComplementary", and "shades".
+			if(dojo.isFunction(type)){
+				return type({ base: base });	//	dojox.color.Palette
+			}
+			else if(dxc.Palette.generators[type]){
+				return dxc.Palette.generators[type]({ base: base });	//	dojox.color.Palette
+			}
+			throw new Error("dojox.color.Palette.generate: the specified generator ('" + type + "') does not exist.");
+		}
+	});
 })();
-}
diff --git a/dojox/color/_base.js b/dojox/color/_base.js
index 5ee28c1..c7eea81 100644
--- a/dojox/color/_base.js
+++ b/dojox/color/_base.js
@@ -1,180 +1,193 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.color._base"]){
-dojo._hasResource["dojox.color._base"]=true;
 dojo.provide("dojox.color._base");
 dojo.require("dojo.colors");
+
+//	alias all the dojo.Color mechanisms
 dojox.color.Color=dojo.Color;
 dojox.color.blend=dojo.blendColors;
 dojox.color.fromRgb=dojo.colorFromRgb;
 dojox.color.fromHex=dojo.colorFromHex;
 dojox.color.fromArray=dojo.colorFromArray;
 dojox.color.fromString=dojo.colorFromString;
+
+//	alias the dojo.colors mechanisms
 dojox.color.greyscale=dojo.colors.makeGrey;
-dojo.mixin(dojox.color,{fromCmy:function(_1,_2,_3){
-if(dojo.isArray(_1)){
-_2=_1[1],_3=_1[2],_1=_1[0];
-}else{
-if(dojo.isObject(_1)){
-_2=_1.m,_3=_1.y,_1=_1.c;
-}
-}
-_1/=100,_2/=100,_3/=100;
-var r=1-_1,g=1-_2,b=1-_3;
-return new dojox.color.Color({r:Math.round(r*255),g:Math.round(g*255),b:Math.round(b*255)});
-},fromCmyk:function(_4,_5,_6,_7){
-if(dojo.isArray(_4)){
-_5=_4[1],_6=_4[2],_7=_4[3],_4=_4[0];
-}else{
-if(dojo.isObject(_4)){
-_5=_4.m,_6=_4.y,_7=_4.b,_4=_4.c;
-}
-}
-_4/=100,_5/=100,_6/=100,_7/=100;
-var r,g,b;
-r=1-Math.min(1,_4*(1-_7)+_7);
-g=1-Math.min(1,_5*(1-_7)+_7);
-b=1-Math.min(1,_6*(1-_7)+_7);
-return new dojox.color.Color({r:Math.round(r*255),g:Math.round(g*255),b:Math.round(b*255)});
-},fromHsl:function(_8,_9,_a){
-if(dojo.isArray(_8)){
-_9=_8[1],_a=_8[2],_8=_8[0];
-}else{
-if(dojo.isObject(_8)){
-_9=_8.s,_a=_8.l,_8=_8.h;
-}
-}
-_9/=100;
-_a/=100;
-while(_8<0){
-_8+=360;
-}
-while(_8>=360){
-_8-=360;
-}
-var r,g,b;
-if(_8<120){
-r=(120-_8)/60,g=_8/60,b=0;
-}else{
-if(_8<240){
-r=0,g=(240-_8)/60,b=(_8-120)/60;
-}else{
-r=(_8-240)/60,g=0,b=(360-_8)/60;
-}
-}
-r=2*_9*Math.min(r,1)+(1-_9);
-g=2*_9*Math.min(g,1)+(1-_9);
-b=2*_9*Math.min(b,1)+(1-_9);
-if(_a<0.5){
-r*=_a,g*=_a,b*=_a;
-}else{
-r=(1-_a)*r+2*_a-1;
-g=(1-_a)*g+2*_a-1;
-b=(1-_a)*b+2*_a-1;
-}
-return new dojox.color.Color({r:Math.round(r*255),g:Math.round(g*255),b:Math.round(b*255)});
-},fromHsv:function(_b,_c,_d){
-if(dojo.isArray(_b)){
-_c=_b[1],_d=_b[2],_b=_b[0];
-}else{
-if(dojo.isObject(_b)){
-_c=_b.s,_d=_b.v,_b=_b.h;
-}
-}
-if(_b==360){
-_b=0;
-}
-_c/=100;
-_d/=100;
-var r,g,b;
-if(_c==0){
-r=_d,b=_d,g=_d;
-}else{
-var _e=_b/60,i=Math.floor(_e),f=_e-i;
-var p=_d*(1-_c);
-var q=_d*(1-(_c*f));
-var t=_d*(1-(_c*(1-f)));
-switch(i){
-case 0:
-r=_d,g=t,b=p;
-break;
-case 1:
-r=q,g=_d,b=p;
-break;
-case 2:
-r=p,g=_d,b=t;
-break;
-case 3:
-r=p,g=q,b=_d;
-break;
-case 4:
-r=t,g=p,b=_d;
-break;
-case 5:
-r=_d,g=p,b=q;
-break;
-}
-}
-return new dojox.color.Color({r:Math.round(r*255),g:Math.round(g*255),b:Math.round(b*255)});
-}});
-dojo.extend(dojox.color.Color,{toCmy:function(){
-var _f=1-(this.r/255),_10=1-(this.g/255),_11=1-(this.b/255);
-return {c:Math.round(_f*100),m:Math.round(_10*100),y:Math.round(_11*100)};
-},toCmyk:function(){
-var _12,_13,_14,_15;
-var r=this.r/255,g=this.g/255,b=this.b/255;
-_15=Math.min(1-r,1-g,1-b);
-_12=(1-r-_15)/(1-_15);
-_13=(1-g-_15)/(1-_15);
-_14=(1-b-_15)/(1-_15);
-return {c:Math.round(_12*100),m:Math.round(_13*100),y:Math.round(_14*100),b:Math.round(_15*100)};
-},toHsl:function(){
-var r=this.r/255,g=this.g/255,b=this.b/255;
-var min=Math.min(r,b,g),max=Math.max(r,g,b);
-var _16=max-min;
-var h=0,s=0,l=(min+max)/2;
-if(l>0&&l<1){
-s=_16/((l<0.5)?(2*l):(2-2*l));
-}
-if(_16>0){
-if(max==r&&max!=g){
-h+=(g-b)/_16;
-}
-if(max==g&&max!=b){
-h+=(2+(b-r)/_16);
-}
-if(max==b&&max!=r){
-h+=(4+(r-g)/_16);
-}
-h*=60;
-}
-return {h:h,s:Math.round(s*100),l:Math.round(l*100)};
-},toHsv:function(){
-var r=this.r/255,g=this.g/255,b=this.b/255;
-var min=Math.min(r,b,g),max=Math.max(r,g,b);
-var _17=max-min;
-var h=null,s=(max==0)?0:(_17/max);
-if(s==0){
-h=0;
-}else{
-if(r==max){
-h=60*(g-b)/_17;
-}else{
-if(g==max){
-h=120+60*(b-r)/_17;
-}else{
-h=240+60*(r-g)/_17;
-}
-}
-if(h<0){
-h+=360;
-}
-}
-return {h:h,s:Math.round(s*100),v:Math.round(max*100)};
-}});
-}
+
+//	static methods
+dojo.mixin(dojox.color, {
+	fromCmy: function(/* Object|Array|int */cyan, /*int*/magenta, /*int*/yellow){
+		//	summary
+		//	Create a dojox.color.Color from a CMY defined color.
+		//	All colors should be expressed as 0-100 (percentage)
+
+		if(dojo.isArray(cyan)){
+			magenta=cyan[1], yellow=cyan[2], cyan=cyan[0];
+		} else if(dojo.isObject(cyan)){
+			magenta=cyan.m, yellow=cyan.y, cyan=cyan.c;
+		}
+		cyan/=100, magenta/=100, yellow/=100;
+
+		var r=1-cyan, g=1-magenta, b=1-yellow;
+		return new dojox.color.Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) });	//	dojox.color.Color
+	},
+
+	fromCmyk: function(/* Object|Array|int */cyan, /*int*/magenta, /*int*/yellow, /*int*/black){
+		//	summary
+		//	Create a dojox.color.Color from a CMYK defined color.
+		//	All colors should be expressed as 0-100 (percentage)
+
+		if(dojo.isArray(cyan)){
+			magenta=cyan[1], yellow=cyan[2], black=cyan[3], cyan=cyan[0];
+		} else if(dojo.isObject(cyan)){
+			magenta=cyan.m, yellow=cyan.y, black=cyan.b, cyan=cyan.c;
+		}
+		cyan/=100, magenta/=100, yellow/=100, black/=100;
+		var r,g,b;
+		r = 1-Math.min(1, cyan*(1-black)+black);
+		g = 1-Math.min(1, magenta*(1-black)+black);
+		b = 1-Math.min(1, yellow*(1-black)+black);
+		return new dojox.color.Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) });	//	dojox.color.Color
+	},
+	
+	fromHsl: function(/* Object|Array|int */hue, /* int */saturation, /* int */luminosity){
+		//	summary
+		//	Create a dojox.color.Color from an HSL defined color.
+		//	hue from 0-359 (degrees), saturation and luminosity 0-100.
+
+		if(dojo.isArray(hue)){
+			saturation=hue[1], luminosity=hue[2], hue=hue[0];
+		} else if(dojo.isObject(hue)){
+			saturation=hue.s, luminosity=hue.l, hue=hue.h;
+		}
+		saturation/=100;
+		luminosity/=100;
+
+		while(hue<0){ hue+=360; }
+		while(hue>=360){ hue-=360; }
+		
+		var r, g, b;
+		if(hue<120){
+			r=(120-hue)/60, g=hue/60, b=0;
+		} else if (hue<240){
+			r=0, g=(240-hue)/60, b=(hue-120)/60;
+		} else {
+			r=(hue-240)/60, g=0, b=(360-hue)/60;
+		}
+		
+		r=2*saturation*Math.min(r, 1)+(1-saturation);
+		g=2*saturation*Math.min(g, 1)+(1-saturation);
+		b=2*saturation*Math.min(b, 1)+(1-saturation);
+		if(luminosity<0.5){
+			r*=luminosity, g*=luminosity, b*=luminosity;
+		}else{
+			r=(1-luminosity)*r+2*luminosity-1;
+			g=(1-luminosity)*g+2*luminosity-1;
+			b=(1-luminosity)*b+2*luminosity-1;
+		}
+		return new dojox.color.Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) });	//	dojox.color.Color
+	},
+	
+	fromHsv: function(/* Object|Array|int */hue, /* int */saturation, /* int */value){
+		//	summary
+		//	Create a dojox.color.Color from an HSV defined color.
+		//	hue from 0-359 (degrees), saturation and value 0-100.
+
+		if(dojo.isArray(hue)){
+			saturation=hue[1], value=hue[2], hue=hue[0];
+		} else if (dojo.isObject(hue)){
+			saturation=hue.s, value=hue.v, hue=hue.h;
+		}
+		
+		if(hue==360){ hue=0; }
+		saturation/=100;
+		value/=100;
+		
+		var r, g, b;
+		if(saturation==0){
+			r=value, b=value, g=value;
+		}else{
+			var hTemp=hue/60, i=Math.floor(hTemp), f=hTemp-i;
+			var p=value*(1-saturation);
+			var q=value*(1-(saturation*f));
+			var t=value*(1-(saturation*(1-f)));
+			switch(i){
+				case 0:{ r=value, g=t, b=p; break; }
+				case 1:{ r=q, g=value, b=p; break; }
+				case 2:{ r=p, g=value, b=t; break; }
+				case 3:{ r=p, g=q, b=value; break; }
+				case 4:{ r=t, g=p, b=value; break; }
+				case 5:{ r=value, g=p, b=q; break; }
+			}
+		}
+		return new dojox.color.Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) });	//	dojox.color.Color
+	}
+});
+
+//	Conversions directly on dojox.color.Color
+dojo.extend(dojox.color.Color, {
+	toCmy: function(){
+		//	summary
+		//	Convert this Color to a CMY definition.
+		var cyan=1-(this.r/255), magenta=1-(this.g/255), yellow=1-(this.b/255);
+		return { c:Math.round(cyan*100), m:Math.round(magenta*100), y:Math.round(yellow*100) };		//	Object
+	},
+	
+	toCmyk: function(){
+		//	summary
+		//	Convert this Color to a CMYK definition.
+		var cyan, magenta, yellow, black;
+		var r=this.r/255, g=this.g/255, b=this.b/255;
+		black = Math.min(1-r, 1-g, 1-b);
+		cyan = (1-r-black)/(1-black);
+		magenta = (1-g-black)/(1-black);
+		yellow = (1-b-black)/(1-black);
+		return { c:Math.round(cyan*100), m:Math.round(magenta*100), y:Math.round(yellow*100), b:Math.round(black*100) };	//	Object
+	},
+	
+	toHsl: function(){
+		//	summary
+		//	Convert this Color to an HSL definition.
+		var r=this.r/255, g=this.g/255, b=this.b/255;
+		var min = Math.min(r, b, g), max = Math.max(r, g, b);
+		var delta = max-min;
+		var h=0, s=0, l=(min+max)/2;
+		if(l>0 && l<1){
+			s = delta/((l<0.5)?(2*l):(2-2*l));
+		}
+		if(delta>0){
+			if(max==r && max!=g){
+				h+=(g-b)/delta;
+			}
+			if(max==g && max!=b){
+				h+=(2+(b-r)/delta);
+			}
+			if(max==b && max!=r){
+				h+=(4+(r-g)/delta);
+			}
+			h*=60;
+		}
+		return { h:h, s:Math.round(s*100), l:Math.round(l*100) };	//	Object
+	},
+
+	toHsv: function(){
+		//	summary
+		//	Convert this Color to an HSV definition.
+		var r=this.r/255, g=this.g/255, b=this.b/255;
+		var min = Math.min(r, b, g), max = Math.max(r, g, b);
+		var delta = max-min;
+		var h = null, s = (max==0)?0:(delta/max);
+		if(s==0){
+			h = 0;
+		}else{
+			if(r==max){
+				h = 60*(g-b)/delta;
+			}else if(g==max){
+				h = 120 + 60*(b-r)/delta;
+			}else{
+				h = 240 + 60*(r-g)/delta;
+			}
+
+			if(h<0){ h+=360; }
+		}
+		return { h:h, s:Math.round(s*100), v:Math.round(max*100) };	//	Object
+	}
+});
diff --git a/dojox/color/tests/Generator.js b/dojox/color/tests/Generator.js
new file mode 100644
index 0000000..7cb7253
--- /dev/null
+++ b/dojox/color/tests/Generator.js
@@ -0,0 +1,150 @@
+dojo.provide("dojox.color.tests.Generator");
+dojo.require("dojox.color.Generator");
+
+var __p__, palette=function(){
+	if(__p__) return __p__;
+	__p__=document.createElement("div");
+	var s=__p__.style;
+	s.overflow="auto";
+	s.padding="0 6px";
+	//	drop it in the test thing
+	var body=dojo.query("#testListContainer table tbody")[0];
+	if(body){
+		var tr=document.createElement("tr");
+		var td=document.createElement("td");
+		td.colSpan=4;
+		td.appendChild(__p__);
+		tr.appendChild(td);
+		body.appendChild(tr);
+	}
+	return __p__;
+}
+
+tests.register("dojox.color.tests.Generator", [
+	function testAnalogous(t){
+		//	test the defaults
+		var args={ base: new dojox.color.Color({ r:128, g:0, b:0 }) };
+		var a=dojox.color.Generator.analogous(args);
+		var s='<h3>dojox.color.Generator.analogous</h3><table cellpadding="0" cellspacing="1" border="0"><tr>';
+		var cols=5, c=0;
+		dojo.forEach(a, function(item){
+			if(c++%cols==0){ s+="</tr><tr>"; }
+			s+='<td width="32" bgcolor="'+item.toHex()+'"> </td>';
+		});
+		if(c<cols){
+			for(; c<cols; c++){
+				s+='<td width="32"> </td>';
+			}
+		}
+//		t.debug(s+'</tr></table>');
+		palette().innerHTML += s+'</tr></table>';
+	},
+
+	function testMonochromatic(t){
+		//	test the defaults
+		var a=dojox.color.Generator.monochromatic({ base:new dojox.color.Color({r:128, g:0, b:0}) });
+		var s='<h3>dojox.color.Generator.monochromatic</h3><table cellpadding="0" cellspacing="1" border="0"><tr>';
+		var cols=8, c=0;
+		dojo.forEach(a, function(item){
+			if(c++%cols==0){ s+="</tr><tr>"; }
+			s+='<td width="32" bgcolor="'+item.toHex()+'"> </td>';
+		});
+		if(c<cols){
+			for(; c<cols; c++){
+				s+='<td width="32"> </td>';
+			}
+		}
+	//	t.debug(s+'</tr></table>');
+		palette().innerHTML += s+'</tr></table>';
+	},
+
+	function testTriadic(t){
+		//	test the defaults
+		var a=dojox.color.Generator.triadic({ base:new dojox.color.Color({r:128, g:0, b:0}) });
+		var s='<h3>dojox.color.Generator.triadic</h3><table cellpadding="0" cellspacing="1" border="0"><tr>';
+		var cols=3, c=0;
+		dojo.forEach(a, function(item){
+			if(c++%cols==0){ s+="</tr><tr>"; }
+			s+='<td width="32" bgcolor="'+item.toHex()+'"> </td>';
+		});
+		if(c<cols){
+			for(; c<cols; c++){
+				s+='<td width="32"> </td>';
+			}
+		}
+	//	t.debug(s+'</tr></table>');
+		palette().innerHTML += s+'</tr></table>';
+	},
+
+	function testComplementary(t){
+		//	test the defaults
+		var a=dojox.color.Generator.complementary({ base:new dojox.color.Color({r:128, g:0, b:0}) });
+		var s='<h3>dojox.color.Generator.complementary</h3><table cellpadding="0" cellspacing="1" border="0"><tr>';
+		var cols=2, c=0;
+		dojo.forEach(a, function(item){
+			if(c++%cols==0){ s+="</tr><tr>"; }
+			s+='<td width="32" bgcolor="'+item.toHex()+'"> </td>';
+		});
+		if(c<cols){
+			for(; c<cols; c++){
+				s+='<td width="32"> </td>';
+			}
+		}
+	//	t.debug(s+'</tr></table>');
+		palette().innerHTML += s+'</tr></table>';
+	},
+
+	function testSplitComplementary(t){
+		//	test the defaults
+		var a=dojox.color.Generator.splitComplementary({ base:new dojox.color.Color({r:128, g:0, b:0}) });
+		var s='<h3>dojox.color.Generator.splitComplementary</h3><table cellpadding="0" cellspacing="1" border="0"><tr>';
+		var cols=3, c=0;
+		dojo.forEach(a, function(item){
+			if(c++%cols==0){ s+="</tr><tr>"; }
+			s+='<td width="32" bgcolor="'+item.toHex()+'"> </td>';
+		});
+		if(c<cols){
+			for(; c<cols; c++){
+				s+='<td width="32"> </td>';
+			}
+		}
+	//	t.debug(s+'</tr></table>');
+		palette().innerHTML += s+'</tr></table>';
+	},
+
+	function testCompound(t){
+		//	test the defaults
+		var a=dojox.color.Generator.compound({ base:new dojox.color.Color({r:128, g:0, b:0}) });
+		var s='<h3>dojox.color.Generator.compound</h3><table cellpadding="0" cellspacing="1" border="0"><tr>';
+		var cols=4, c=0;
+		dojo.forEach(a, function(item){
+			if(c++%cols==0){ s+="</tr><tr>"; }
+			s+='<td width="32" bgcolor="'+item.toHex()+'"> </td>';
+		});
+		if(c<cols){
+			for(; c<cols; c++){
+				s+='<td width="32"> </td>';
+			}
+		}
+	//	t.debug(s+'</tr></table>');
+		palette().innerHTML += s+'</tr></table>';
+	},
+
+	function testShades(t){
+		//	test the defaults
+		var a=dojox.color.Generator.shades({ base:new dojox.color.Color({r:128, g:0, b:0}) });
+		var s='<h3>dojox.color.Generator.shades</h3><table cellpadding="0" cellspacing="1" border="0"><tr>';
+		var cols=8, c=0;
+		dojo.forEach(a, function(item){
+			if(c++%cols==0){ s+="</tr><tr>"; }
+			s+='<td width="32" bgcolor="'+item.toHex()+'"> </td>';
+		});
+		if(c<cols){
+			for(; c<cols; c++){
+				s+='<td width="32"> </td>';
+			}
+		}
+		palette().innerHTML += s+'</tr></table>';
+//		t.debug(s+'</tr></table>');
+	}
+]);
diff --git a/dojox/color/tests/Palette.js b/dojox/color/tests/Palette.js
new file mode 100644
index 0000000..b5b0e15
--- /dev/null
+++ b/dojox/color/tests/Palette.js
@@ -0,0 +1,86 @@
+dojo.provide("dojox.color.tests.Palette");
+dojo.require("dojox.color.Palette");
+
+var __p__, palette=function(){
+	if(__p__) return __p__;
+	__p__=document.createElement("div");
+	var s=__p__.style;
+	s.overflow="auto";
+	s.padding="0 6px";
+	//	drop it in the test thing
+	var body=dojo.query("#testListContainer table tbody")[0];
+	if(body){
+		var tr=document.createElement("tr");
+		var td=document.createElement("td");
+		td.colSpan=4;
+		td.appendChild(__p__);
+		tr.appendChild(td);
+		body.appendChild(tr);
+	}
+	return __p__;
+}
+
+var p = new dojox.color.Palette([
+	"#ff0000",
+	"#ffff00",
+	"#ff00ff",
+	"#00ffff",
+	"#0000ff"
+]);
+
+function displayIt(pal, title){
+	var s='<h3>'+title+'</h3><table cellpadding="0" cellspacing="1" border="0"><tr>';
+	var cols=5, c=0;
+	dojo.forEach(pal.colors, function(item){
+		s+='<td width="32" bgcolor="'+item.toHex()+'"> </td>';
+		console.log("item color is ", item.toHex());
+	});
+	palette().innerHTML += s + "</tr></table>";
+}
+
+tests.register("dojox.color.tests.Palette", [
+	function testPalette(t){
+		var p = new dojox.color.Palette([
+			"#000000",
+			"#333333",
+			"#666666",
+			"#999999",
+			"#cccccc"
+		]);
+		displayIt(p, "dojox.color.Palette");
+	},
+
+	function testTransform(t){
+		displayIt(p, "Transform: initial palette");
+		var trans = p.transform({
+			use: "hsv",
+			dh: 120,
+			dv: -40
+		});
+		displayIt(trans, "Transform dh:+120, dv: -40");
+
+		trans = p.transform({
+			use: "cmyk",
+			dc: 30,
+			dk: 30
+		});
+		displayIt(trans, "Transform using CMYK dc:+30, dk: +30");
+
+		trans = p.transform({
+			use: "rgba",
+			db: -100
+		});
+		displayIt(trans, "Transform using RGB db:-100");
+	},
+
+	function testGenerators(t){
+		var base = "#ff0000";
+		displayIt(dojox.color.Palette.generate(base, "analogous"), "Generated analogous palette");
+		displayIt(dojox.color.Palette.generate(base, "monochromatic"), "Generated monochromatic palette");
+		displayIt(dojox.color.Palette.generate(base, "triadic"), "Generated triadic palette");
+		displayIt(dojox.color.Palette.generate(base, "complementary"), "Generated complementary palette");
+		displayIt(dojox.color.Palette.generate(base, "splitComplementary"), "Generated splitComplementary palette");
+		displayIt(dojox.color.Palette.generate(base, "compound"), "Generated compound palette");
+		displayIt(dojox.color.Palette.generate(base, "shades"), "Generated shades palette");
+	}
+]);
diff --git a/dojox/color/tests/_base.js b/dojox/color/tests/_base.js
new file mode 100644
index 0000000..8d5f370
--- /dev/null
+++ b/dojox/color/tests/_base.js
@@ -0,0 +1,78 @@
+dojo.provide("dojox.color.tests._base");
+dojo.require("dojox.color");
+
+/************************************************************
+ *	Note that some color translations are not exact,
+ *	due to the need to round calculations in translation.
+ *
+ *	These tests work with grey, the primary colors and
+ *	one secondary color to ensure that extreme calculation
+ *	is correct.
+ ************************************************************/
+
+tests.register("dojox.color.tests._base", [
+	function testStaticMethods(t){
+		//	fromCmy
+		t.assertEqual(dojox.color.fromCmy({ c:50, m:50, y:50}), new dojo.Color({ r:128, g:128, b:128 }));
+		t.assertEqual(dojox.color.fromCmy({ c:0, m:100, y:100}), new dojo.Color({ r:255, g:0, b:0 }));
+		t.assertEqual(dojox.color.fromCmy({ c:100, m:0, y:100}), new dojo.Color({ r:0, g:255, b:0 }));
+		t.assertEqual(dojox.color.fromCmy({ c:100, m:100, y:0}), new dojo.Color({ r:0, g:0, b:255 }));
+		t.assertEqual(dojox.color.fromCmy({ c:0, m:0, y:100}), new dojo.Color({ r:255, g:255, b:0 }));
+
+		//	fromCmyk
+		t.assertEqual(dojox.color.fromCmyk({ c:0, m:0, y:0, b:50}), new dojo.Color({ r:128, g:128, b:128 }));
+		t.assertEqual(dojox.color.fromCmyk({ c:0, m:100, y:100, b:0}), new dojo.Color({ r:255, g:0, b:0 }));
+		t.assertEqual(dojox.color.fromCmyk({ c:100, m:0, y:100, b:0}), new dojo.Color({ r:0, g:255, b:0 }));
+		t.assertEqual(dojox.color.fromCmyk({ c:100, m:100, y:0, b:0}), new dojo.Color({ r:0, g:0, b:255 }));
+		t.assertEqual(dojox.color.fromCmyk({ c:0, m:0, y:100, b:0}), new dojo.Color({ r:255, g:255, b:0 }));
+
+		//	fromHsl
+		t.assertEqual(dojox.color.fromHsl({ h:0, s:0, l:50}), new dojo.Color({ r:128, g:128, b:128 }));
+		t.assertEqual(dojox.color.fromHsl({ h:0, s:100, l:50}), new dojo.Color({ r:255, g:0, b:0 }));
+		t.assertEqual(dojox.color.fromHsl({ h:120, s:100, l:50}), new dojo.Color({ r:0, g:255, b:0 }));
+		t.assertEqual(dojox.color.fromHsl({ h:240, s:100, l:50}), new dojo.Color({ r:0, g:0, b:255 }));
+		t.assertEqual(dojox.color.fromHsl({ h:60, s:100, l:50}), new dojo.Color({ r:255, g:255, b:0 }));
+
+		//	fromHsv
+		t.assertEqual(dojox.color.fromHsv({ h:0, s:0, v:50}), new dojo.Color({ r:128, g:128, b:128 }));
+		t.assertEqual(dojox.color.fromHsv({ h:0, s:100, v:100}), new dojo.Color({ r:255, g:0, b:0 }));
+		t.assertEqual(dojox.color.fromHsv({ h:120, s:100, v:100}), new dojo.Color({ r:0, g:255, b:0 }));
+		t.assertEqual(dojox.color.fromHsv({ h:240, s:100, v:100}), new dojo.Color({ r:0, g:0, b:255 }));
+		t.assertEqual(dojox.color.fromHsv({ h:60, s:100, v:100}), new dojo.Color({ r:255, g:255, b:0 }));
+	},
+	function testColorExtensions(t){
+		var grey=new dojox.color.Color({ r:128, g:128, b:128 });
+		var red=new dojox.color.Color({ r:255, g:0, b:0 });
+		var green=new dojox.color.Color({ r:0, g:255, b:0 });
+		var blue=new dojox.color.Color({ r:0, g:0, b:255 });
+		var yellow=new dojox.color.Color({ r:255, g:255, b:0 });
+
+		//	toCmy
+		t.assertEqual(grey.toCmy(), { c:50, m:50, y:50 });
+		t.assertEqual(red.toCmy(), { c:0, m:100, y:100 });
+		t.assertEqual(green.toCmy(), { c:100, m:0, y:100 });
+		t.assertEqual(blue.toCmy(), { c:100, m:100, y:0 });
+		t.assertEqual(yellow.toCmy(), { c:0, m:0, y:100 });
+
+		//	toCmyk
+		t.assertEqual(grey.toCmyk(), { c:0, m:0, y:0, b:50 });
+		t.assertEqual(red.toCmyk(), { c:0, m:100, y:100, b:0 });
+		t.assertEqual(green.toCmyk(), { c:100, m:0, y:100, b:0 });
+		t.assertEqual(blue.toCmyk(), { c:100, m:100, y:0, b:0 });
+		t.assertEqual(yellow.toCmyk(), { c:0, m:0, y:100, b:0 });
+
+		//	toHsl
+		t.assertEqual(grey.toHsl(), { h:0, s:0, l:50 });
+		t.assertEqual(red.toHsl(), { h:0, s:100, l:50 });
+		t.assertEqual(green.toHsl(), { h:120, s:100, l:50 });
+		t.assertEqual(blue.toHsl(), { h:240, s:100, l:50 });
+		t.assertEqual(yellow.toHsl(), { h:60, s:100, l:50 });
+
+		//	toHsv
+		t.assertEqual(grey.toHsv(), { h:0, s:0, v:50 });
+		t.assertEqual(red.toHsv(), { h:0, s:100, v:100 });
+		t.assertEqual(green.toHsv(), { h:120, s:100, v:100 });
+		t.assertEqual(blue.toHsv(), { h:240, s:100, v:100 });
+		t.assertEqual(yellow.toHsv(), { h:60, s:100, v:100 });
+	}
+]);
diff --git a/dojox/color/tests/color.js b/dojox/color/tests/color.js
new file mode 100644
index 0000000..843329b
--- /dev/null
+++ b/dojox/color/tests/color.js
@@ -0,0 +1,11 @@
+dojo.provide("dojox.color.tests.color");
+dojo.require("dojox.color");
+
+try{
+	dojo.require("dojox.color.tests._base");
+//	dojo.require("dojox.color.tests.Colorspace");
+	dojo.require("dojox.color.tests.Palette");
+//	dojo.require("dojox.color.tests.Generator");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/color/tests/runTests.html b/dojox/color/tests/runTests.html
new file mode 100644
index 0000000..9376e20
--- /dev/null
+++ b/dojox/color/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox.wire Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.color.tests.color"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/cometd.js b/dojox/cometd.js
index 6744f97..ad541c5 100644
--- a/dojox/cometd.js
+++ b/dojox/cometd.js
@@ -1,14 +1,5 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.cometd"]){
-dojo._hasResource["dojox.cometd"]=true;
+// stub loader for the cometd module since no implementation code is allowed to live in top-level files
 dojo.provide("dojox.cometd");
 dojo.require("dojox.cometd._base");
 dojo.require("dojox.cometd.longPollTransport");
 dojo.require("dojox.cometd.callbackPollTransport");
-}
diff --git a/dojox/cometd/HttpChannels.js b/dojox/cometd/HttpChannels.js
index f690c1c..6724e3c 100644
--- a/dojox/cometd/HttpChannels.js
+++ b/dojox/cometd/HttpChannels.js
@@ -1,14 +1,32 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.cometd.HttpChannels"]){
-dojo._hasResource["dojox.cometd.HttpChannels"]=true;
 dojo.provide("dojox.cometd.HttpChannels");
+ 
 dojo.require("dojox.io.httpParse");
 dojo.require("dojox.cometd.RestChannels");
-dojox.cometd.HttpChannels=dojox.cometd.RestChannels;
-}
+// Note that cometd _base is _not_ required, this can run standalone, but ifyou want 
+// cometd functionality, you must explicitly load/require it elsewhere, and cometd._base
+// MUST be loaded prior to HttpChannels ifyou use it.
+
+// summary:
+// 		HttpChannels - An HTTP Based approach to Comet transport with full HTTP messaging 
+// 		semantics including REST. HttpChannels is exactly the same as RestChannels, loading HttpChannels simply ensures that http parsing
+//		capabilities are present for application/http messages
+
+// description:
+// 		This can be used:
+// 		1. As a cometd transport
+// 		2. As an enhancement for the REST RPC service, to enable "live" data (real-time updates directly alter the data in indexes)
+// 		2a. With the JsonRestStore (which is driven by the REST RPC service), so this dojo.data has real-time data. Updates can be heard through the dojo.data notification API.
+// 		3. As a standalone transport. To use it as a standalone transport looks like this:
+// 	|		dojox.cometd.HttpChannels.open();
+// 	|		dojox.cometd.HttpChannels.get("/myResource",{callback:function(){
+// 	|			// this is called when the resource is first retrieved and any time the 
+// 	|			// resource is changed in the future. This provides a means for retrieving a
+// 	|			// resource and subscribing to it in a single request
+// 	|		});
+// 	|	dojox.cometd.HttpChannels.subscribe("/anotherResource",{callback:function(){
+// 	|		// this is called when the resource is changed in the future
+// 	|	});
+// 		Channels HTTP can be configured to a different delays:
+// 	|	dojox.cometd.HttpChannels.autoReconnectTime = 60000; // reconnect after one minute
+//
+dojox.cometd.HttpChannels = dojox.cometd.RestChannels;  
diff --git a/dojox/cometd/RestChannels.js b/dojox/cometd/RestChannels.js
index 896c376..f82d6a2 100644
--- a/dojox/cometd/RestChannels.js
+++ b/dojox/cometd/RestChannels.js
@@ -1,337 +1,482 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.cometd.RestChannels"]){
-dojo._hasResource["dojox.cometd.RestChannels"]=true;
 dojo.provide("dojox.cometd.RestChannels");
+ 
 dojo.require("dojox.rpc.Client");
-dojo.requireIf(dojox.data&&!!dojox.data.JsonRestStore,"dojox.data.restListener");
+dojo.requireIf(dojox.data && !!dojox.data.JsonRestStore,"dojox.data.restListener");
+
+// Note that cometd _base is _not_ required, this can run standalone, but ifyou want 
+// cometd functionality, you must explicitly load/require it elsewhere, and cometd._base
+// MUST be loaded prior to RestChannels ifyou use it.
+
+// summary:
+// 		REST Channels - An HTTP/REST Based approach to Comet transport with full REST messaging 
+// 		semantics
+// 		REST Channels is a efficient, reliable duplex transport for Comet
+
+// description:
+// 		This can be used:
+// 		1. As a cometd transport
+// 		2. As an enhancement for the REST RPC service, to enable "live" data (real-time updates directly alter the data in indexes)
+// 		2a. With the JsonRestStore (which is driven by the REST RPC service), so this dojo.data has real-time data. Updates can be heard through the dojo.data notification API.
+// 		3. As a standalone transport. To use it as a standalone transport looks like this:
+// 	|		dojox.cometd.RestChannels.open();
+// 	|		dojox.cometd.RestChannels.get("/myResource",{callback:function(){
+// 	|			// this is called when the resource is first retrieved and any time the 
+// 	|			// resource is changed in the future. This provides a means for retrieving a
+// 	|			// resource and subscribing to it in a single request
+// 	|		});
+// 	|	dojox.cometd.RestChannels.subscribe("/anotherResource",{callback:function(){
+// 	|		// this is called when the resource is changed in the future
+// 	|	});
+// 		Channels HTTP can be configured to a different delays:
+// 	|	dojox.cometd.RestChannels.defaultInstance.autoReconnectTime = 60000; // reconnect after one minute
+//
+
 (function(){
-dojo.declare("dojox.cometd.RestChannels",null,{constructor:function(_1){
-dojo.mixin(this,_1);
-if(dojox.rpc.Rest&&this.autoSubscribeRoot){
-var _2=dojox.rpc.Rest._get;
-var _3=this;
-dojox.rpc.Rest._get=function(_4,id){
-var _5=dojo.xhrGet;
-dojo.xhrGet=function(r){
-var _6=_3.autoSubscribeRoot;
-return (_6&&r.url.substring(0,_6.length)==_6)?_3.get(r.url,r):_5(r);
-};
-var _7=_2.apply(this,arguments);
-dojo.xhrGet=_5;
-return _7;
-};
-}
-},absoluteUrl:function(_8,_9){
-return new dojo._Url(_8,_9)+"";
-},acceptType:"application/rest+json,application/http;q=0.9,*/*;q=0.7",subscriptions:{},subCallbacks:{},autoReconnectTime:3000,reloadDataOnReconnect:true,sendAsJson:false,url:"/channels",autoSubscribeRoot:"/",open:function(){
-this.started=true;
-if(!this.connected){
-this.connectionId=dojox.rpc.Client.clientId;
-var _a=this.createdClientId?"Client-Id":"Create-Client-Id";
-this.createdClientId=true;
-var _b={Accept:this.acceptType};
-_b[_a]=this.connectionId;
-var _c=dojo.xhrPost({headers:_b,url:this.url,noStatus:true});
-var _d=this;
-this.lastIndex=0;
-var _e,_f=function(_10){
-if(typeof dojo=="undefined"){
-return null;
-}
-if(xhr&&xhr.status>400){
-return _e(true);
-}
-if(typeof _10=="string"){
-_10=_10.substring(_d.lastIndex);
-}
-var _11=xhr&&(xhr.contentType||xhr.getResponseHeader("Content-Type"))||(typeof _10!="string"&&"already json");
-var _12=_d.onprogress(xhr,_10,_11);
-if(_12){
-if(_e()){
-return new Error(_12);
-}
-}
-if(!xhr||xhr.readyState==4){
-xhr=null;
-if(_d.connected){
-_d.connected=false;
-_d.open();
-}
-}
-return _10;
-};
-_e=function(_13){
-if(xhr&&xhr.status==409){
-_d.disconnected();
-return null;
-}
-_d.createdClientId=false;
-_d.disconnected();
-return _13;
-};
-_c.addCallbacks(_f,_e);
-var xhr=_c.ioArgs.xhr;
-if(xhr){
-xhr.onreadystatechange=function(){
-var _14;
-try{
-if(xhr.readyState==3){
-_d.readyState=3;
-_14=xhr.responseText;
-}
-}
-catch(e){
-}
-if(typeof _14=="string"){
-_f(_14);
-}
-};
-}
-if(window.attachEvent){
-window.attachEvent("onunload",function(){
-_d.connected=false;
-if(xhr){
-xhr.abort();
-}
-});
-}
-this.connected=true;
-}
-},_send:function(_15,_16,_17){
-if(this.sendAsJson){
-_16.postData=dojo.toJson({target:_16.url,method:_15,content:_17,params:_16.content,subscribe:_16.headers["Subscribe"]});
-_16.url=this.url;
-_15="POST";
-}else{
-_16.postData=dojo.toJson(_17);
-}
-return dojo.xhr(_15,_16,_16.postData);
-},subscribe:function(_18,_19){
-_19=_19||{};
-_19.url=this.absoluteUrl(this.url,_18);
-if(_19.headers){
-delete _19.headers.Range;
-}
-var _1a=this.subscriptions[_18];
-var _1b=_19.method||"HEAD";
-var _1c=_19.since;
-var _1d=_19.callback;
-var _1e=_19.headers||(_19.headers={});
-this.subscriptions[_18]=_1c||_1a||0;
-var _1f=this.subCallbacks[_18];
-if(_1d){
-this.subCallbacks[_18]=_1f?function(m){
-_1f(m);
-_1d(m);
-}:_1d;
-}
-if(!this.connected){
-this.open();
-}
-if(_1a===undefined||_1a!=_1c){
-_1e["Cache-Control"]="max-age=0";
-_1c=typeof _1c=="number"?new Date(_1c).toUTCString():_1c;
-if(_1c){
-_1e["Subscribe-Since"]=_1c;
-}
-_1e["Subscribe"]=_19.unsubscribe?"none":"*";
-var dfd=this._send(_1b,_19);
-var _20=this;
-dfd.addBoth(function(_21){
-var xhr=dfd.ioArgs.xhr;
-if(!(_21 instanceof Error)){
-if(_19.confirmation){
-_19.confirmation();
-}
-}
-if(xhr&&xhr.getResponseHeader("Subscribed")=="OK"){
-var _22=xhr.getResponseHeader("Last-Modified");
-if(xhr.responseText){
-_20.subscriptions[_18]=_22||new Date().toUTCString();
-}else{
-return null;
-}
-}else{
-if(xhr&&!(_21 instanceof Error)){
-delete _20.subscriptions[_18];
-}
-}
-if(!(_21 instanceof Error)){
-var _23={responseText:xhr&&xhr.responseText,channel:_18,getResponseHeader:function(_24){
-return xhr.getResponseHeader(_24);
-},getAllResponseHeaders:function(){
-return xhr.getAllResponseHeaders();
-},result:_21};
-if(_20.subCallbacks[_18]){
-_20.subCallbacks[_18](_23);
-}
-}else{
-if(_20.subCallbacks[_18]){
-_20.subCallbacks[_18](xhr);
-}
-}
-return _21;
-});
-return dfd;
-}
-return null;
-},publish:function(_25,_26){
-return this._send("POST",{url:_25,contentType:"application/json"},_26);
-},_processMessage:function(_27){
-_27.event=_27.event||_27.getResponseHeader("Event");
-if(_27.event=="connection-conflict"){
-return "conflict";
-}
-try{
-_27.result=_27.result||dojo.fromJson(_27.responseText);
-}
-catch(e){
-}
-var _28=this;
-var loc=_27.channel=new dojo._Url(this.url,_27.source||_27.getResponseHeader("Content-Location"))+"";
-if(loc in this.subscriptions&&_27.getResponseHeader){
-this.subscriptions[loc]=_27.getResponseHeader("Last-Modified");
-}
-if(this.subCallbacks[loc]){
-setTimeout(function(){
-_28.subCallbacks[loc](_27);
-},0);
-}
-this.receive(_27);
-return null;
-},onprogress:function(xhr,_29,_2a){
-if(!_2a||_2a.match(/application\/rest\+json/)){
-var _2b=_29.length;
-_29=_29.replace(/^\s*[,\[]?/,"[").replace(/[,\]]?\s*$/,"]");
-try{
-var _2c=dojo.fromJson(_29);
-this.lastIndex+=_2b;
-}
-catch(e){
-}
-}else{
-if(dojox.io&&dojox.io.httpParse&&_2a.match(/application\/http/)){
-var _2d="";
-if(xhr&&xhr.getAllResponseHeaders){
-_2d=xhr.getAllResponseHeaders();
-}
-_2c=dojox.io.httpParse(_29,_2d,xhr.readyState!=4);
-}else{
-if(typeof _29=="object"){
-_2c=_29;
-}
-}
-}
-if(_2c){
-for(var i=0;i<_2c.length;i++){
-if(this._processMessage(_2c[i])){
-return "conflict";
-}
-}
-return null;
-}
-if(!xhr){
-return "error";
-}
-if(xhr.readyState!=4){
-return null;
-}
-if(xhr.__proto__){
-xhr={channel:"channel",__proto__:xhr};
-}
-return this._processMessage(xhr);
-},get:function(_2e,_2f){
-(_2f=_2f||{}).method="GET";
-return this.subscribe(_2e,_2f);
-},receive:function(_30){
-if(dojox.data&&dojox.data.restListener){
-dojox.data.restListener(_30);
-}
-},disconnected:function(){
-var _31=this;
-if(this.connected){
-this.connected=false;
-if(this.started){
-setTimeout(function(){
-var _32=_31.subscriptions;
-_31.subscriptions={};
-for(var i in _32){
-if(_31.reloadDataOnReconnect&&dojox.rpc.JsonRest){
-delete dojox.rpc.Rest._index[i];
-dojox.rpc.JsonRest.fetch(i);
-}else{
-_31.subscribe(i,{since:_32[i]});
-}
-}
-_31.open();
-},this.autoReconnectTime);
-}
-}
-},unsubscribe:function(_33,_34){
-_34=_34||{};
-_34.unsubscribe=true;
-this.subscribe(_33,_34);
-},disconnect:function(){
-this.started=false;
-this.xhr.abort();
-}});
-var _35=dojox.cometd.RestChannels.defaultInstance=new dojox.cometd.RestChannels();
-if(dojox.cometd.connectionTypes){
-_35.startup=function(_36){
-_35.open();
-this._cometd._deliver({channel:"/meta/connect",successful:true});
-};
-_35.check=function(_37,_38,_39){
-for(var i=0;i<_37.length;i++){
-if(_37[i]=="rest-channels"){
-return !_39;
-}
-}
-return false;
-};
-_35.deliver=function(_3a){
-};
-dojo.connect(this,"receive",null,function(_3b){
-_3b.data=_3b.result;
-this._cometd._deliver(_3b);
-});
-_35.sendMessages=function(_3c){
-for(var i=0;i<_3c.length;i++){
-var _3d=_3c[i];
-var _3e=_3d.channel;
-var _3f=this._cometd;
-var _40={confirmation:function(){
-_3f._deliver({channel:_3e,successful:true});
-}};
-if(_3e=="/meta/subscribe"){
-this.subscribe(_3d.subscription,_40);
-}else{
-if(_3e=="/meta/unsubscribe"){
-this.unsubscribe(_3d.subscription,_40);
-}else{
-if(_3e=="/meta/connect"){
-_40.confirmation();
-}else{
-if(_3e=="/meta/disconnect"){
-_35.disconnect();
-_40.confirmation();
-}else{
-if(_3e.substring(0,6)!="/meta/"){
-this.publish(_3e,_3d.data);
-}
-}
-}
-}
-}
-}
-};
-dojox.cometd.connectionTypes.register("rest-channels",_35.check,_35,false,true);
-}
+	dojo.declare("dojox.cometd.RestChannels", null, {
+		constructor: function(options){
+			// summary:
+			//		Initiates the REST Channels protocol
+			//	options:
+			//		Keyword arguments:
+			//	The *autoSubscribeRoot* parameter:
+			//		When this is set, all REST service requests that have this
+			// 		prefix will be auto-subscribed. The default is '/' (all REST requests).
+			//  The *url* parameter:
+			//		This is the url to connect to for server-sent messages. The default
+			//		is "/channels".
+			//	The *autoReconnectTime* parameter:
+			// 		This is amount time to wait to reconnect with a connection is broken
+			// The *reloadDataOnReconnect* parameter:
+			// 		This indicates whether RestChannels should re-download data when a connection
+			// 		is restored (value of true), or if it should re-subscribe with retroactive subscriptions
+			// 		(Subscribe-Since header) using HEAD requests (value of false). The 
+			// 		default is true.	
+			dojo.mixin(this,options);
+			// If we have a Rest service available and we are auto subscribing, we will augment the Rest service 
+			if(dojox.rpc.Rest && this.autoSubscribeRoot){
+				// override the default Rest handler so we can add subscription requests
+				var defaultGet = dojox.rpc.Rest._get;
+				var self = this;
+				dojox.rpc.Rest._get = function(service, id){
+					// when there is a REST get, we will intercept and add our own xhr handler
+					var defaultXhrGet = dojo.xhrGet;
+					dojo.xhrGet = function(r){
+						var autoSubscribeRoot = self.autoSubscribeRoot;
+						return (autoSubscribeRoot && r.url.substring(0, autoSubscribeRoot.length) == autoSubscribeRoot) ?
+							self.get(r.url,r) : // auto-subscribe 
+							defaultXhrGet(r); // plain XHR request
+					};
+		
+					var result = defaultGet.apply(this,arguments);
+					dojo.xhrGet = defaultXhrGet;
+					return result;
+				};
+			}
+		},
+		absoluteUrl: function(baseUrl,relativeUrl){
+			return new dojo._Url(baseUrl,relativeUrl)+'';
+		},
+		acceptType: "application/rest+json,application/http;q=0.9,*/*;q=0.7",
+		subscriptions: {},
+		subCallbacks: {},
+		autoReconnectTime: 3000,
+		reloadDataOnReconnect: true,
+		sendAsJson: false,
+		url: '/channels',
+		autoSubscribeRoot: '/',
+		open: function(){
+			// summary:
+			// 		Startup the transport (connect to the "channels" resource to receive updates from the server).
+			//
+			// description:
+			//		Note that if there is no connection open, this is automatically called when you do a subscription,
+			// 		it is often not necessary to call this
+			//
+			this.started = true;
+			if(!this.connected){
+				this.connectionId = dojox.rpc.Client.clientId;
+				var clientIdHeader = this.createdClientId ? 'Client-Id' : 'Create-Client-Id';
+				this.createdClientId = true;
+				var headers = {Accept:this.acceptType};
+				headers[clientIdHeader] = this.connectionId;
+				var dfd = dojo.xhrPost({headers:headers, url: this.url, noStatus: true});
+		  		var self = this;
+		  		this.lastIndex = 0; 
+				var onerror, onprogress = function(data){ // get all the possible event handlers
+					if(typeof dojo == 'undefined'){
+						return null;// this can be called after dojo is unloaded, just do nothing in that case
+					}
+					if(xhr && xhr.status > 400){
+						return onerror(true);
+					}
+					if(typeof data == 'string'){
+						data = data.substring(self.lastIndex);
+					}
+					var contentType = xhr && (xhr.contentType || xhr.getResponseHeader("Content-Type")) || (typeof data != 'string' && "already json");
+					var error = self.onprogress(xhr,data,contentType);
+					if(error){
+						if(onerror()){
+							return new Error(error);
+						}
+					}
+					if(!xhr || xhr.readyState==4){
+						xhr = null;
+						if(self.connected){
+							self.connected = false;
+							self.open();
+						}
+					}
+					return data;
+				};
+				onerror = function(error){
+					if(xhr && xhr.status == 409){
+						// a 409 indicates that there is a multiple connections, and we need to poll
+						console.log("multiple tabs/windows open, polling");
+						self.disconnected();
+						return null;
+					}
+					self.createdClientId = false;
+					self.disconnected();
+					return error;
+			  	};
+			  	dfd.addCallbacks(onprogress,onerror);
+			  	var xhr = dfd.ioArgs.xhr; // this may not exist if we are not using XHR, but an alternate XHR plugin
+			  	if(xhr){
+			  		// if we are doing a monitorable XHR, we want to listen to streaming events
+	  				xhr.onreadystatechange = function(){
+	  					var responseText;
+						try{
+							if(xhr.readyState == 3){// only for progress, the deferred object will handle the finished responses
+								self.readyState = 3;
+								responseText = xhr.responseText;
+							}
+						} catch(e){
+						}
+	  					if(typeof responseText=='string'){
+	  						onprogress(responseText);
+	  					}
+	  				} 
+			  	}
+			  	
+	  			 
+				if(window.attachEvent){// IE needs a little help with cleanup
+					window.attachEvent("onunload",function(){
+						self.connected= false;
+						if(xhr){
+							xhr.abort();
+						}
+					});
+				}
+				
+				this.connected = true;
+			}
+		},
+		_send: function(method,args,data){
+			// fire an XHR with appropriate modification for JSON handling
+			if(this.sendAsJson){
+				// send use JSON Messaging
+				args.postData = dojo.toJson({
+					target:args.url,
+					method:method,
+					content: data,
+					params:args.content,
+					subscribe:args.headers["Subscribe"]
+				});
+				args.url = this.url;
+				method = "POST";
+			}else{
+				args.postData = dojo.toJson(data);
+			}			
+			return dojo.xhr(method,args,args.postData);
+		}, 
+		subscribe: function(/*String*/channel, /*dojo.__XhrArgs?*/args){
+			// summary:
+			// 		Subscribes to a channel/uri, and returns a dojo.Deferred object for the response from 
+			// 		the subscription request
+			//
+			// channel: 
+			// 		the uri for the resource you want to monitor
+			// 
+			// args: 
+			// 		See dojo.xhr
+			// 
+			// headers:
+			// 		These are the headers to be applied to the channel subscription request
+			//
+			// callback:
+			// 		This will be called when a event occurs for the channel
+			// 		The callback will be called with a single argument:
+			// 	|	callback(message)
+			// 		where message is an object that follows the XHR API:
+			// 		status : Http status
+			// 		statusText : Http status text
+			// 		getAllResponseHeaders() : The response headers
+			// 		getResponseHeaders(headerName) : Retrieve a header by name
+			// 		responseText : The response body as text
+			// 			with the following additional Bayeux properties 
+			// 		data : The response body as JSON
+			// 		channel : The channel/url of the response
+			args = args || {};
+			args.url = this.absoluteUrl(this.url, channel);
+			if(args.headers){ 
+				// FIXME: combining Ranges with notifications is very complicated, we will save that for a future version
+				delete args.headers.Range;
+			}
+			var oldSince = this.subscriptions[channel];
+			var method = args.method || "HEAD"; // HEAD is the default for a subscription
+			var since = args.since;
+			var callback = args.callback;
+			var headers = args.headers || (args.headers = {});
+			this.subscriptions[channel] = since || oldSince || 0;
+			var oldCallback = this.subCallbacks[channel];
+			if(callback){
+				this.subCallbacks[channel] = oldCallback ? function(m){
+					oldCallback(m);
+					callback(m);
+				} : callback;
+			} 
+			if(!this.connected){
+				this.open();
+			}
+			if(oldSince === undefined || oldSince != since){
+				headers["Cache-Control"] = "max-age=0";
+				since = typeof since == 'number' ? new Date(since).toUTCString() : since;
+				if(since){
+					headers["Subscribe-Since"] = since;
+				}
+				headers["Subscribe"] = args.unsubscribe ? 'none' : '*';
+				var dfd = this._send(method,args);
+				
+				var self = this;
+				dfd.addBoth(function(result){					
+					var xhr = dfd.ioArgs.xhr;
+					if(!(result instanceof Error)){
+						if(args.confirmation){
+							args.confirmation();
+						}
+					}
+					if(xhr && xhr.getResponseHeader("Subscribed")  == "OK"){
+						var lastMod = xhr.getResponseHeader('Last-Modified');
+						
+						if(xhr.responseText){ 
+							self.subscriptions[channel] = lastMod || new Date().toUTCString();
+						}else{
+							return null; // don't process the response, the response will be received in the main channels response
+						}
+					}else if(xhr && !(result instanceof Error)){ // if the server response was successful and we have access to headers but it does indicate a subcription was successful, that means it is did not accept the subscription
+						delete self.subscriptions[channel];
+					}
+					if(!(result instanceof Error)){
+						var message = {
+							responseText:xhr && xhr.responseText,
+							channel:channel,
+							getResponseHeader:function(name){
+								return xhr.getResponseHeader(name);
+							},
+							getAllResponseHeaders:function(){
+								return xhr.getAllResponseHeaders();
+							},
+							result: result
+						};
+						if(self.subCallbacks[channel]){
+							self.subCallbacks[channel](message); // call with the fake xhr object
+						}
+					}else{
+						if(self.subCallbacks[channel]){
+							self.subCallbacks[channel](xhr); // call with the actual xhr object
+						}
+					}
+					return result;
+				});
+				return dfd;
+			}
+			return null;
+		},
+		publish: function(channel,data){
+			// summary:
+			//		Publish an event.
+			// description:
+			// 		This does a simple POST operation to the provided URL,
+			// 		POST is the semantic equivalent of publishing a message within REST/Channels
+			// channel:
+			// 		Channel/resource path to publish to
+			// data:
+			//		data to publish
+			return this._send("POST",{url:channel,contentType : 'application/json'},data);
+		},
+		_processMessage: function(message){
+			message.event = message.event || message.getResponseHeader('Event');
+			if(message.event=="connection-conflict"){
+				return "conflict"; // indicate an error
+			}
+			try{
+				message.result = message.result || dojo.fromJson(message.responseText);
+			}
+			catch(e){}
+			var self = this;	
+			var loc = message.channel = new dojo._Url(this.url, message.source || message.getResponseHeader('Content-Location'))+'';//for cometd
+			if(loc in this.subscriptions && message.getResponseHeader){
+				this.subscriptions[loc] = message.getResponseHeader('Last-Modified'); 
+			}
+			if(this.subCallbacks[loc]){
+				setTimeout(function(){ //give it it's own stack 
+					self.subCallbacks[loc](message);
+				},0);
+			}
+			this.receive(message);
+			return null;		
+		},
+		onprogress: function(xhr,data,contentType){
+			// internal XHR progress handler
+			if(!contentType || contentType.match(/application\/rest\+json/)){
+				var size = data.length;
+				data = data.replace(/^\s*[,\[]?/,'['). // must start with a opening bracket
+					replace(/[,\]]?\s*$/,']'); // and end with a closing bracket
+				try{
+					// if this fails, it probably means we have an incomplete JSON object
+					var xhrs = dojo.fromJson(data);
+					this.lastIndex += size;
+				}
+				catch(e){
+				}
+			}else if(dojox.io && dojox.io.httpParse && contentType.match(/application\/http/)){
+				// do HTTP tunnel parsing
+				var topHeaders = '';
+				if(xhr && xhr.getAllResponseHeaders){
+					// mixin/inherit headers from the container response
+					topHeaders = xhr.getAllResponseHeaders();
+				}
+				xhrs = dojox.io.httpParse(data,topHeaders,xhr.readyState != 4);
+			}else if(typeof data == "object"){
+				xhrs = data;
+			}
+			if(xhrs){
+				for(var i = 0;i < xhrs.length;i++){
+					if(this._processMessage(xhrs[i])){
+						return "conflict";
+					}
+				}
+				return null;
+			}
+			if(!xhr){
+				//no streaming and we didn't get any message, must be an error
+				return "error";
+			}
+			if(xhr.readyState != 4){ // we only want finished responses here if we are not streaming 
+				return null;
+			}
+			if(xhr.__proto__){// firefox uses this property, so we create an instance to shadow this property
+				xhr = {channel:"channel",__proto__:xhr};
+			}			
+			return this._processMessage(xhr);
+		
+		},
+		
+		get: function(/*String*/channel, /*dojo.__XhrArgs?*/args){
+			// summary:
+			// 		GET the initial value of the resource and subscribe to it  
+			//		See subscribe for parameter values
+			(args = args || {}).method = "GET"; 
+			return this.subscribe(channel,args);
+		},
+		receive: function(message){
+			// summary:
+			//		Called when a message is received from the server
+			//	message:
+			//		A cometd/XHR message
+			if(dojox.data && dojox.data.restListener){
+				dojox.data.restListener(message);
+			}
+		},
+		disconnected: function(){
+			// summary:
+			// 		called when our channel gets disconnected
+			var self = this;
+			if(this.connected){ 
+				this.connected = false;
+				if(this.started){ // if we are started, we shall try to reconnect
+					setTimeout(function(){ // auto reconnect
+						// resubscribe to our current subscriptions
+						var subscriptions = self.subscriptions;
+						self.subscriptions = {};
+						for(var i in subscriptions){
+							if(self.reloadDataOnReconnect && dojox.rpc.JsonRest){
+								// do a reload of the resource
+								delete dojox.rpc.Rest._index[i];
+								dojox.rpc.JsonRest.fetch(i);
+							}else{
+								self.subscribe(i,{since:subscriptions[i]});
+							}
+						}
+						self.open();
+					}, this.autoReconnectTime);
+				}
+			}
+		},
+		unsubscribe: function(/*String*/channel, /*dojo.__XhrArgs?*/args){
+			// summary:
+			// 		unsubscribes from the resource  
+			//		See subscribe for parameter values 
+			
+			args = args || {};
+			args.unsubscribe = true;
+			this.subscribe(channel,args); // change the time frame to after 5000AD 
+		},
+		disconnect: function(){
+			// summary:
+			// 		disconnect from the server  
+			this.started = false;
+			this.xhr.abort();
+		}
+	});
+	var Channels = dojox.cometd.RestChannels.defaultInstance = new dojox.cometd.RestChannels();
+	if(dojox.cometd.connectionTypes){ 
+		// register as a dojox.cometd transport and wire everything for cometd handling
+		// below are the necessary adaptions for cometd
+		Channels.startup = function(data){ // must be able to handle objects or strings
+			Channels.open();
+			this._cometd._deliver({channel:"/meta/connect",successful:true}); // tell cometd we are connected so it can proceed to send subscriptions, even though we aren't yet 
+
+		};
+		Channels.check = function(types, version, xdomain){
+			for(var i = 0; i< types.length; i++){
+				if(types[i] == "rest-channels"){
+					return !xdomain;
+				}
+			}
+			return false;
+		};
+		Channels.deliver = function(message){ 
+			// nothing to do
+		};
+		dojo.connect(this,"receive",null,function(message){
+			message.data = message.result;
+			this._cometd._deliver(message);
+		});
+		Channels.sendMessages = function(messages){
+			for(var i = 0; i < messages.length; i++){
+				var message = messages[i];
+				var channel = message.channel;
+				var cometd = this._cometd;
+				var args = {
+					confirmation: function(){ // send a confirmation back to cometd
+						cometd._deliver({channel:channel,successful:true});
+					}
+				};
+				if(channel == '/meta/subscribe'){
+					this.subscribe(message.subscription,args);
+				}else if(channel == '/meta/unsubscribe'){
+					this.unsubscribe(message.subscription,args);
+				}else if(channel == '/meta/connect'){
+					args.confirmation();
+				}else if(channel == '/meta/disconnect'){
+					Channels.disconnect();
+					args.confirmation();
+				}else if(channel.substring(0,6) != '/meta/'){
+					this.publish(channel,message.data);
+				}
+			}
+		};
+		dojox.cometd.connectionTypes.register("rest-channels", Channels.check, Channels,false,true);
+	}
 })();
-}
diff --git a/dojox/cometd/_base.js b/dojox/cometd/_base.js
index 393395c..0e4f300 100644
--- a/dojox/cometd/_base.js
+++ b/dojox/cometd/_base.js
@@ -1,400 +1,754 @@
+dojo.provide("dojox.cometd._base");
+dojo.require("dojo.AdapterRegistry");
+
+
 /*
-	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 file defines Comet protocol client. Actual message transport is
+ * deferred to one of several connection type implementations. The default is a
+ * long-polling implementation. A single global object named "dojox.cometd" is
+ * used to mediate for these connection types in order to provide a stable
+ * interface.
+ *
+ * extensions modules may be loaded (eg "dojox.cometd.timestamp", that use
+ * the cometd._extendInList and cometd._extendOutList fields to provide functions
+ * that extend and handling incoming and outgoing messages.
+ * 
+ * By default the long-polling and callback-polling transports will be required.
+ * If specific or alternative transports are required, then they can be directly 
+ * loaded. For example dojo.require('dojox.cometd.longPollTransportJsonEncoded')
+ * will load cometd with only the json encoded variant of the long polling transport.
+ */
 
+dojox.cometd = {
+	Connection: function(prefix){ // This constructor is stored as dojox.cometd.Connection
+		// summary
+		// This constructor is used to create new cometd connections. Generally, you should use
+		// one cometd connection for each server you connect to. A default connection instance is 
+		// created at dojox.cometd.
+		// To connect to a new server you can create an instance like:
+		// var cometd = new dojox.cometd.Connection("/otherServer");
+		// cometd.init("http://otherServer.com/cometd");
+		//
+		// prefix is the prefix for all the events that are published in the Dojo pub/sub system.
+		// You must include this prefix, and it should start with a slash like "/myprefix".
+		
+		// cometd states:
+		// unconnected, handshaking, connecting, connected, disconnected
+		dojo.mixin(this, {
+		prefix: prefix,
+			_status: "unconnected",
+			_handshook: false,
+			_initialized: false,
+			_polling: false,
+		
+			expectedNetworkDelay: 10000, // expected max network delay
+			connectTimeout: 0,		 // If set, used as ms to wait for a connect response and sent as the advised timeout
+		
+			version:	"1.0",
+			minimumVersion: "0.9",
+			clientId: null,
+			messageId: 0,
+			batch: 0,
+		
+			_isXD: false,
+			handshakeReturn: null,
+			currentTransport: null,
+			url: null,
+			lastMessage: null,
+			_messageQ: [],
+			handleAs: "json",
+			_advice: {},
+			_backoffInterval: 0,
+			_backoffIncrement: 1000,
+			_backoffMax: 60000,
+			_deferredSubscribes: {},
+			_deferredUnsubscribes: {},
+			_subscriptions: [],
+			_extendInList: [],	// List of functions invoked before delivering messages
+			_extendOutList: []	// List of functions invoked before sending messages
+			
+		});
+	
+		this.state = function() {
+			 return this._status;
+		}
+	
+		this.init = function(	/*String*/	root,
+					/*Object?*/ props,
+					/*Object?*/ bargs){	// return: dojo.Deferred
+			//	summary:
+			//		Initialize the cometd implementation of the Bayeux protocol
+			//	description:
+			//		Initialize the cometd implementation of the Bayeux protocol by
+			//		sending a handshake message. The cometd state will be changed to CONNECTING
+			//		until a handshake response is received and the first successful connect message
+			//		has returned.
+			//		The protocol state changes may be monitored
+			//		by subscribing to the dojo topic "/prefix/meta" (typically "/cometd/meta") where 
+			//		events are published in the form 
+			//		   {cometd:this,action:"handshake",successful:true,state:this.state()}
+			//	root:
+			//		The URL of the cometd server. If the root is absolute, the host
+			//		is examined to determine if xd transport is needed. Otherwise the
+			//		same domain is assumed.
+			//	props:
+			//		An optional object that is used as the basis of the handshake message
+			//	bargs:
+			//		An optional object of bind args mixed in with the send of the handshake
+			//	example:
+			//	|	dojox.cometd.init("/cometd");
+			//	|	dojox.cometd.init("http://xdHost/cometd",{ext:{user:"fred",pwd:"secret"}});
+	
+			// FIXME: if the root isn't from the same host, we should automatically
+			// try to select an XD-capable transport
+			props = props || {};
+			// go ask the short bus server what we can support
+			props.version = this.version;
+			props.minimumVersion = this.minimumVersion;
+			props.channel = "/meta/handshake";
+			props.id = "" + this.messageId++;
+	
+			this.url = root || dojo.config["cometdRoot"];
+			if(!this.url){
+				throw "no cometd root";
+				return null;
+			}
+	
+			// Are we x-domain? borrowed from dojo.uri.Uri in lieu of fixed host and port properties
+			var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
+			var parts = ("" + window.location).match(new RegExp(regexp));
+			if(parts[4]){
+				var tmp = parts[4].split(":");
+				var thisHost = tmp[0];
+				var thisPort = tmp[1]||"80"; // FIXME: match 443
+	
+				parts = this.url.match(new RegExp(regexp));
+				if(parts[4]){
+					tmp = parts[4].split(":");
+					var urlHost = tmp[0];
+					var urlPort = tmp[1]||"80";
+					this._isXD = ((urlHost != thisHost)||(urlPort != thisPort));
+				}
+			}
+	
+			if(!this._isXD){
+				props.supportedConnectionTypes = dojo.map(dojox.cometd.connectionTypes.pairs, "return item[0]");
+			}
+	
+			props = this._extendOut(props);
+	
+			var bindArgs = {
+				url: this.url,
+				handleAs: this.handleAs,
+				content: { "message": dojo.toJson([props]) },
+				load: dojo.hitch(this,function(msg){
+					this._backon();
+					this._finishInit(msg);
+				}),
+				error: dojo.hitch(this,function(e){
+					this._backoff();
+					this._finishInit(e);
+				}),
+				timeout: this.expectedNetworkDelay
+			};
+	
+			if(bargs){
+				dojo.mixin(bindArgs, bargs);
+			}
+			this._props = props;
+			for(var tname in this._subscriptions){
+				for(var sub in this._subscriptions[tname]){
+					if(this._subscriptions[tname][sub].topic){
+						dojo.unsubscribe(this._subscriptions[tname][sub].topic);
+					}
+				}
+			}
+			this._messageQ = [];
+			this._subscriptions = [];
+			this._initialized = true;
+			this._status = "handshaking";
+			this.batch = 0;
+			this.startBatch();
+			
+			var r;
+			// if xdomain, then we assume jsonp for handshake
+			if(this._isXD){
+				bindArgs.callbackParamName = "jsonp";
+				r = dojo.io.script.get(bindArgs);
+			}else{
+				r = dojo.xhrPost(bindArgs);
+			}
+			return r;
+		}
+		
+		this.publish = function(/*String*/ channel, /*Object*/ data, /*Object?*/ props){
+			// summary:
+			//		publishes the passed message to the cometd server for delivery
+			//		on the specified topic
+			// channel:
+			//		the destination channel for the message
+			// data:
+			//		a JSON object containing the message "payload"
+			// properties:
+			//		Optional. Other meta-data to be mixed into the top-level of the
+			//		message
+			var message = {
+				data: data,
+				channel: channel
+			};
+			if(props){
+				dojo.mixin(message, props);
+			}
+			this._sendMessage(message);
+		}
+	
+		
+		this.subscribe = function(	/*String */	channel,
+						/*Object */	objOrFunc,
+						/*String */	funcName,
+						/*Object?*/ props){ // return: dojo.Deferred
+			//	summary:
+			//		inform the server of this client's interest in channel
+			//	description:
+			//		`dojox.cometd.subscribe()` handles all the hard work of telling
+			//		the server that we want to be notified when events are
+			//		published on a particular topic. `subscribe` accepts a function
+			//		to handle messages and returns a `dojo.Deferred` object which
+			//		has an extra property added to it which makes it suitable for
+			//		passing to `dojox.cometd.unsubscribe()` as a "subscription
+			//		handle" (much like the handle object that `dojo.connect()`
+			//		produces and which `dojo.disconnect()` expects).
+			//		
+			//		Note that of a subscription is registered before a connection
+			//		with the server is established, events sent before the
+			//		connection is established will not be delivered to this client.
+			//		The deferred object which `subscribe` returns will callback
+			//		when the server successfuly acknolwedges receipt of our
+			//		"subscribe" request.
+			//	channel:
+			//		name of the cometd channel to subscribe to
+			//	objOrFunc:
+			//		an object scope for funcName or the name or reference to a
+			//		function to be called when messages are delivered to the
+			//		channel
+			//	funcName:
+			//		the second half of the objOrFunc/funcName pair for identifying
+			//		a callback function to notifiy upon channel message delivery
+			//	example:
+			//		Simple subscribe use-case
+			//	|	dojox.cometd.init("http://myserver.com:8080/cometd");
+			//	|	// log out all incoming messages on /foo/bar
+			//	|	dojox.cometd.subscribe("/foo/bar", console, "debug");
+			//	example:
+			//		Subscribe before connection is initialized
+			//	|	dojox.cometd.subscribe("/foo/bar", console, "debug");
+			//	|	dojox.cometd.init("http://myserver.com:8080/cometd");
+			//	example:
+			//		Subscribe an unsubscribe
+			//	|	dojox.cometd.init("http://myserver.com:8080/cometd");
+			//	|	var h = dojox.cometd.subscribe("/foo/bar", console, "debug");
+			//	|	dojox.cometd.unsubscribe(h);
+			//	example:
+			//		Listen for successful subscription:
+			//	|	dojox.cometd.init("http://myserver.com:8080/cometd");
+			//	|	var h = dojox.cometd.subscribe("/foo/bar", console, "debug");
+			//	|	h.addCallback(function(){
+			//	|		console.debug("subscription to /foo/bar established");
+			//	|	});
+	
+			props = props||{};
+			if(objOrFunc){
+				var tname = prefix + channel;
+				var subs = this._subscriptions[tname];
+				if(!subs || subs.length == 0){
+					subs = [];
+					props.channel = "/meta/subscribe";
+					props.subscription = channel;
+					this._sendMessage(props);
+					
+					var _ds = this._deferredSubscribes;
+					if(_ds[channel]){
+						_ds[channel].cancel();
+						delete _ds[channel];
+					}
+					_ds[channel] = new dojo.Deferred();
+				}
+				
+				for(var i in subs){
+					if(subs[i].objOrFunc === objOrFunc && (!subs[i].funcName&&!funcName||subs[i].funcName==funcName) ){
+						return null;
+					}
+				}
+				
+				var topic = dojo.subscribe(tname, objOrFunc, funcName);
+				subs.push({ 
+					topic: topic, 
+					objOrFunc: objOrFunc, 
+					funcName: funcName
+				});
+				this._subscriptions[tname] = subs;
+			}
+			var ret = this._deferredSubscribes[channel] || {};
+			ret.args = dojo._toArray(arguments);
+			return ret; // dojo.Deferred
+		}
+	
+		this.unsubscribe = function(	/*String*/	channel,
+						/*Object?*/ objOrFunc,
+						/*String?*/ funcName,
+						/*Object?*/ props){
+			// summary:
+			//		inform the server of this client's disinterest in channel
+			// channel:
+			//		name of the cometd channel to unsubscribe from
+			// objOrFunc:
+			//		an object scope for funcName or the name or reference to a
+			//		function to be called when messages are delivered to the
+			//		channel. If null then all subscribers to the channel are unsubscribed.
+			// funcName:
+			//		the second half of the objOrFunc/funcName pair for identifying
+			//		a callback function to notifiy upon channel message delivery
+	
+			if(
+				(arguments.length == 1) &&
+				(!dojo.isString(channel)) &&
+				(channel.args)
+			){
+				// it's a subscription handle, unroll
+				return this.unsubscribe.apply(this, channel.args);
+			}
+			
+			var tname = prefix + channel;
+			var subs = this._subscriptions[tname];
+			if(!subs || subs.length==0){
+				return null;
+			}
+	
+			var s=0;
+			for(var i in subs){
+				var sb = subs[i];
+				if((!objOrFunc) ||
+					(
+						sb.objOrFunc===objOrFunc &&
+						(!sb.funcName && !funcName || sb.funcName==funcName)
+					)
+				){
+					dojo.unsubscribe(subs[i].topic);
+					delete subs[i];
+				}else{
+					s++;
+				}
+			}
+			
+			if(s == 0){
+				props = props || {};
+				props.channel = "/meta/unsubscribe";
+				props.subscription = channel;
+				delete this._subscriptions[tname];
+				this._sendMessage(props);
+				this._deferredUnsubscribes[channel] = new dojo.Deferred();
+				if(this._deferredSubscribes[channel]){
+					this._deferredSubscribes[channel].cancel();
+					delete this._deferredSubscribes[channel];
+				}
+			}
+			return this._deferredUnsubscribes[channel]; // dojo.Deferred
+		}
+		
+		
+		this.disconnect = function(){
+			//	summary:
+			//		Disconnect from the server.
+			//	description:
+			//		Disconnect from the server by sending a disconnect message
+			//	example:
+			//	|	dojox.cometd.disconnect();
+	
+			for(var tname in this._subscriptions){
+				for(var sub in this._subscriptions[tname]){
+					if(this._subscriptions[tname][sub].topic){
+						dojo.unsubscribe(this._subscriptions[tname][sub].topic);
+					}
+				}
+			}
+			this._subscriptions = [];
+			this._messageQ = [];
+			if(this._initialized && this.currentTransport){
+				this._initialized=false;
+				this.currentTransport.disconnect();
+			}
+			if(!this._polling) {
+				this._publishMeta("connect",false);
+			}
+			this._initialized=false;
+			this._handshook=false;
+			this._status = "disconnected"; //should be disconnecting, but we ignore the reply to this message
+			this._publishMeta("disconnect",true);
+		}
+	
+		
+		// public extension points
+		
+		this.subscribed = function(	/*String*/channel, /*Object*/message){ }
+	
+		this.unsubscribed = function(/*String*/channel, /*Object*/message){ }
+	
+	
+		// private methods (TODO name all with leading _)
+	
+		this.tunnelInit = function(childLocation, childDomain){
+			// placeholder - replaced by _finishInit
+		}
+		
+		this.tunnelCollapse = function(){
+			// placeholder - replaced by _finishInit
+		}
+		
+		this._backoff = function(){
+			if(!this._advice){
+				this._advice={reconnect:"retry",interval:0};
+			}else if(!this._advice.interval){
+				this._advice.interval = 0;
+			}
+			
+			if(this._backoffInterval < this._backoffMax){
+				this._backoffInterval += this._backoffIncrement;
+			}
+		}
+		
+		this._backon = function(){
+			this._backoffInterval=0;
+		}
+	
+		this._interval = function(){
+			var i = this._backoffInterval + (this._advice ? (this._advice.interval ? this._advice.interval : 0) : 0);
+			if (i>0){
+				console.log("Retry in interval+backoff=" + this._advice.interval + "+" + this._backoffInterval+"="+i+"ms");
+			}
+			return i;
+		}
+		
+		this._publishMeta = function(action,successful,props){
+			try {
+				var meta = {cometd:this,action:action,successful:successful,state:this.state()};
+				if (props){
+					dojo.mixin(meta, props);
+				}
+				dojo.publish(this.prefix + "/meta", [meta]);
+			} catch(e) {
+				console.log(e);
+			}
+		}
+	
+		this._finishInit = function(data){
+			//	summary:
+			//		Handle the handshake return from the server and initialize
+			//		connection if all is OK
 
-if(!dojo._hasResource["dojox.cometd._base"]){
-dojo._hasResource["dojox.cometd._base"]=true;
-dojo.provide("dojox.cometd._base");
-dojo.require("dojo.AdapterRegistry");
-dojox.cometd={Connection:function(_1){
-dojo.mixin(this,{prefix:_1,_status:"unconnected",_handshook:false,_initialized:false,_polling:false,expectedNetworkDelay:10000,connectTimeout:0,version:"1.0",minimumVersion:"0.9",clientId:null,messageId:0,batch:0,_isXD:false,handshakeReturn:null,currentTransport:null,url:null,lastMessage:null,_messageQ:[],handleAs:"json",_advice:{},_backoffInterval:0,_backoffIncrement:1000,_backoffMax:60000,_deferredSubscribes:{},_deferredUnsubscribes:{},_subscriptions:[],_extendInList:[],_extendOutList:[]});
-this.state=function(){
-return this._status;
-};
-this.init=function(_2,_3,_4){
-_3=_3||{};
-_3.version=this.version;
-_3.minimumVersion=this.minimumVersion;
-_3.channel="/meta/handshake";
-_3.id=""+this.messageId++;
-this.url=_2||dojo.config["cometdRoot"];
-if(!this.url){
-throw "no cometd root";
-return null;
-}
-var _5="^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
-var _6=(""+window.location).match(new RegExp(_5));
-if(_6[4]){
-var _7=_6[4].split(":");
-var _8=_7[0];
-var _9=_7[1]||"80";
-_6=this.url.match(new RegExp(_5));
-if(_6[4]){
-_7=_6[4].split(":");
-var _a=_7[0];
-var _b=_7[1]||"80";
-this._isXD=((_a!=_8)||(_b!=_9));
-}
-}
-if(!this._isXD){
-_3.supportedConnectionTypes=dojo.map(dojox.cometd.connectionTypes.pairs,"return item[0]");
-}
-_3=this._extendOut(_3);
-var _c={url:this.url,handleAs:this.handleAs,content:{"message":dojo.toJson([_3])},load:dojo.hitch(this,function(_d){
-this._backon();
-this._finishInit(_d);
-}),error:dojo.hitch(this,function(e){
-this._backoff();
-this._finishInit(e);
-}),timeout:this.expectedNetworkDelay};
-if(_4){
-dojo.mixin(_c,_4);
-}
-this._props=_3;
-for(var _e in this._subscriptions){
-for(var _f in this._subscriptions[_e]){
-if(this._subscriptions[_e][_f].topic){
-dojo.unsubscribe(this._subscriptions[_e][_f].topic);
-}
-}
-}
-this._messageQ=[];
-this._subscriptions=[];
-this._initialized=true;
-this._status="handshaking";
-this.batch=0;
-this.startBatch();
-var r;
-if(this._isXD){
-_c.callbackParamName="jsonp";
-r=dojo.io.script.get(_c);
-}else{
-r=dojo.xhrPost(_c);
-}
-return r;
-};
-this.publish=function(_10,_11,_12){
-var _13={data:_11,channel:_10};
-if(_12){
-dojo.mixin(_13,_12);
-}
-this._sendMessage(_13);
-};
-this.subscribe=function(_14,_15,_16,_17){
-_17=_17||{};
-if(_15){
-var _18=_1+_14;
-var _19=this._subscriptions[_18];
-if(!_19||_19.length==0){
-_19=[];
-_17.channel="/meta/subscribe";
-_17.subscription=_14;
-this._sendMessage(_17);
-var _1a=this._deferredSubscribes;
-if(_1a[_14]){
-_1a[_14].cancel();
-delete _1a[_14];
-}
-_1a[_14]=new dojo.Deferred();
-}
-for(var i in _19){
-if(_19[i].objOrFunc===_15&&(!_19[i].funcName&&!_16||_19[i].funcName==_16)){
-return null;
-}
-}
-var _1b=dojo.subscribe(_18,_15,_16);
-_19.push({topic:_1b,objOrFunc:_15,funcName:_16});
-this._subscriptions[_18]=_19;
-}
-var ret=this._deferredSubscribes[_14]||{};
-ret.args=dojo._toArray(arguments);
-return ret;
-};
-this.unsubscribe=function(_1c,_1d,_1e,_1f){
-if((arguments.length==1)&&(!dojo.isString(_1c))&&(_1c.args)){
-return this.unsubscribe.apply(this,_1c.args);
-}
-var _20=_1+_1c;
-var _21=this._subscriptions[_20];
-if(!_21||_21.length==0){
-return null;
-}
-var s=0;
-for(var i in _21){
-var sb=_21[i];
-if((!_1d)||(sb.objOrFunc===_1d&&(!sb.funcName&&!_1e||sb.funcName==_1e))){
-dojo.unsubscribe(_21[i].topic);
-delete _21[i];
-}else{
-s++;
-}
-}
-if(s==0){
-_1f=_1f||{};
-_1f.channel="/meta/unsubscribe";
-_1f.subscription=_1c;
-delete this._subscriptions[_20];
-this._sendMessage(_1f);
-this._deferredUnsubscribes[_1c]=new dojo.Deferred();
-if(this._deferredSubscribes[_1c]){
-this._deferredSubscribes[_1c].cancel();
-delete this._deferredSubscribes[_1c];
-}
-}
-return this._deferredUnsubscribes[_1c];
-};
-this.disconnect=function(){
-for(var _22 in this._subscriptions){
-for(var sub in this._subscriptions[_22]){
-if(this._subscriptions[_22][sub].topic){
-dojo.unsubscribe(this._subscriptions[_22][sub].topic);
-}
-}
-}
-this._subscriptions=[];
-this._messageQ=[];
-if(this._initialized&&this.currentTransport){
-this._initialized=false;
-this.currentTransport.disconnect();
-}
-if(!this._polling){
-this._publishMeta("connect",false);
-}
-this._initialized=false;
-this._handshook=false;
-this._status="disconnected";
-this._publishMeta("disconnect",true);
-};
-this.subscribed=function(_23,_24){
-};
-this.unsubscribed=function(_25,_26){
-};
-this.tunnelInit=function(_27,_28){
-};
-this.tunnelCollapse=function(){
-};
-this._backoff=function(){
-if(!this._advice){
-this._advice={reconnect:"retry",interval:0};
-}else{
-if(!this._advice.interval){
-this._advice.interval=0;
-}
-}
-if(this._backoffInterval<this._backoffMax){
-this._backoffInterval+=this._backoffIncrement;
-}
-};
-this._backon=function(){
-this._backoffInterval=0;
-};
-this._interval=function(){
-var i=this._backoffInterval+(this._advice?(this._advice.interval?this._advice.interval:0):0);
-if(i>0){
-}
-return i;
-};
-this._publishMeta=function(_29,_2a,_2b){
-try{
-var _2c={cometd:this,action:_29,successful:_2a,state:this.state()};
-if(_2b){
-dojo.mixin(_2c,_2b);
-}
-dojo.publish(this.prefix+"/meta",[_2c]);
-}
-catch(e){
-}
-};
-this._finishInit=function(_2d){
-if(this._status!="handshaking"){
-return;
-}
-var _2e=this._handshook;
-var _2f=false;
-var _30={};
-if(_2d instanceof Error){
-dojo.mixin(_30,{reestablish:false,failure:true,error:_2d,advice:this._advice});
-}else{
-_2d=_2d[0];
-_2d=this._extendIn(_2d);
-this.handshakeReturn=_2d;
-if(_2d["advice"]){
-this._advice=_2d.advice;
-}
-_2f=_2d.successful?_2d.successful:false;
-if(_2d.version<this.minimumVersion){
-if(console.log){
-}
-_2f=false;
-this._advice.reconnect="none";
-}
-dojo.mixin(_30,{reestablish:_2f&&_2e,response:_2d});
-}
-this._publishMeta("handshake",_2f,_30);
-if(this._status!="handshaking"){
-return;
-}
-if(_2f){
-this._status="connecting";
-this._handshook=true;
-this.currentTransport=dojox.cometd.connectionTypes.match(_2d.supportedConnectionTypes,_2d.version,this._isXD);
-var _31=this.currentTransport;
-_31._cometd=this;
-_31.version=_2d.version;
-this.clientId=_2d.clientId;
-this.tunnelInit=_31.tunnelInit&&dojo.hitch(_31,"tunnelInit");
-this.tunnelCollapse=_31.tunnelCollapse&&dojo.hitch(_31,"tunnelCollapse");
-_31.startup(_2d);
-}else{
-if(!this._advice||this._advice["reconnect"]!="none"){
-setTimeout(dojo.hitch(this,"init",this.url,this._props),this._interval());
-}
-}
-};
-this._extendIn=function(_32){
-dojo.forEach(dojox.cometd._extendInList,function(f){
-_32=f(_32)||_32;
-});
-return _32;
-};
-this._extendOut=function(_33){
-dojo.forEach(dojox.cometd._extendOutList,function(f){
-_33=f(_33)||_33;
-});
-return _33;
-};
-this.deliver=function(_34){
-dojo.forEach(_34,this._deliver,this);
-return _34;
-};
-this._deliver=function(_35){
-_35=this._extendIn(_35);
-if(!_35["channel"]){
-if(_35["success"]!==true){
-return;
-}
-}
-this.lastMessage=_35;
-if(_35.advice){
-this._advice=_35.advice;
-}
-var _36=null;
-if((_35["channel"])&&(_35.channel.length>5)&&(_35.channel.substr(0,5)=="/meta")){
-switch(_35.channel){
-case "/meta/connect":
-var _37={response:_35};
-if(_35.successful){
-if(this._status!="connected"){
-this._status="connected";
-this.endBatch();
-}
-}
-if(this._initialized){
-this._publishMeta("connect",_35.successful,_37);
-}
-break;
-case "/meta/subscribe":
-_36=this._deferredSubscribes[_35.subscription];
-try{
-if(!_35.successful){
-if(_36){
-_36.errback(new Error(_35.error));
-}
-this.currentTransport.cancelConnect();
-return;
-}
-if(_36){
-_36.callback(true);
-}
-this.subscribed(_35.subscription,_35);
-}
-catch(e){
-log.warn(e);
-}
-break;
-case "/meta/unsubscribe":
-_36=this._deferredUnsubscribes[_35.subscription];
-try{
-if(!_35.successful){
-if(_36){
-_36.errback(new Error(_35.error));
-}
-this.currentTransport.cancelConnect();
-return;
-}
-if(_36){
-_36.callback(true);
-}
-this.unsubscribed(_35.subscription,_35);
-}
-catch(e){
-log.warn(e);
-}
-break;
-default:
-if(_35.successful&&!_35.successful){
-this.currentTransport.cancelConnect();
-return;
-}
-}
-}
-this.currentTransport.deliver(_35);
-if(_35.data){
-try{
-var _38=[_35];
-var _39=_1+_35.channel;
-var _3a=_35.channel.split("/");
-var _3b=_1;
-for(var i=1;i<_3a.length-1;i++){
-dojo.publish(_3b+"/**",_38);
-_3b+="/"+_3a[i];
-}
-dojo.publish(_3b+"/**",_38);
-dojo.publish(_3b+"/*",_38);
-dojo.publish(_39,_38);
-}
-catch(e){
-}
-}
-};
-this._sendMessage=function(_3c){
-if(this.currentTransport&&!this.batch){
-return this.currentTransport.sendMessages([_3c]);
-}else{
-this._messageQ.push(_3c);
-return null;
-}
-};
-this.startBatch=function(){
-this.batch++;
-};
-this.endBatch=function(){
-if(--this.batch<=0&&this.currentTransport&&this._status=="connected"){
-this.batch=0;
-var _3d=this._messageQ;
-this._messageQ=[];
-if(_3d.length>0){
-this.currentTransport.sendMessages(_3d);
-}
-}
-};
-this._onUnload=function(){
-dojo.addOnUnload(dojox.cometd,"disconnect");
-};
-this._connectTimeout=function(){
-var _3e=0;
-if(this._advice&&this._advice.timeout&&this.expectedNetworkDelay>0){
-_3e=this._advice.timeout+this.expectedNetworkDelay;
-}
-if(this.connectTimeout>0&&this.connectTimeout<_3e){
-return this.connectTimeout;
+			if(this._status!="handshaking") {return;}
+
+
+			var wasHandshook = this._handshook;
+			var successful = false;	
+			var metaMsg = {};
+
+			if (data instanceof Error) {
+				dojo.mixin(metaMsg,{
+					reestablish:false,
+					failure: true,
+					error: data,
+					advice: this._advice
+				});
+			} else {
+				data = data[0];
+				data = this._extendIn(data);
+				this.handshakeReturn = data;
+				// remember any advice
+				if(data["advice"]){
+					this._advice = data.advice;
+				}
+
+				successful = data.successful ? data.successful : false;
+
+				// check version
+				if(data.version < this.minimumVersion){
+					if (console.log)
+						console.log("cometd protocol version mismatch. We wanted", this.minimumVersion, "but got", data.version);
+					successful=false;
+					this._advice.reconnect="none";
+				}
+				dojo.mixin(metaMsg,{reestablish: successful && wasHandshook, response:data});
+			} 
+
+			this._publishMeta("handshake",successful,metaMsg);
+			//in the meta listeners, disconnect() may have been called, so recheck it now to 
+			//prevent resends or continuing with initializing the protocol
+			if(this._status!="handshaking") {return;}
+
+			// If all OK
+			if(successful){
+				this._status = "connecting";
+				this._handshook = true;
+				// pick a transport
+				this.currentTransport = dojox.cometd.connectionTypes.match(
+					data.supportedConnectionTypes,
+					data.version,
+					this._isXD
+				);
+				var transport = this.currentTransport;
+				// initialize the transport
+				transport._cometd = this;
+				transport.version = data.version;
+				this.clientId = data.clientId;
+				this.tunnelInit = transport.tunnelInit && dojo.hitch(transport, "tunnelInit");
+				this.tunnelCollapse = transport.tunnelCollapse && dojo.hitch(transport, "tunnelCollapse");
+				transport.startup(data);
+			}else{
+				// If there is a problem follow advice
+				if(!this._advice || this._advice["reconnect"] != "none"){
+					setTimeout(dojo.hitch(this, "init", this.url, this._props), this._interval());
+				}
+			}
+		}
+	
+		// FIXME: lots of repeated code...why?
+		this._extendIn = function(message){
+			// summary: Handle extensions for inbound messages
+			dojo.forEach(dojox.cometd._extendInList, function(f){
+				message = f(message) || message;
+			});
+			return message;
+		}
+	
+		this._extendOut = function(message){
+			// summary: Handle extensions for inbound messages
+			dojo.forEach(dojox.cometd._extendOutList, function(f){
+				message = f(message) || message;
+			});
+			return message;
+		}
+	
+		this.deliver = function(messages){
+			dojo.forEach(messages, this._deliver, this);
+			return messages;
+		}
+	
+		this._deliver = function(message){
+			// dipatch events along the specified path
+			
+			message = this._extendIn(message);
+	
+			if(!message["channel"]){
+				if(message["success"] !== true){
+					return;
+				}
+			}
+			this.lastMessage = message;
+	
+			if(message.advice){
+				this._advice = message.advice; // TODO maybe merge?
+			}
+	
+			// check to see if we got a /meta channel message that we care about
+			var deferred=null;
+			if(	(message["channel"]) &&
+				(message.channel.length > 5) &&
+				(message.channel.substr(0, 5) == "/meta")){
+				// check for various meta topic actions that we need to respond to
+				switch(message.channel){
+					case "/meta/connect":
+						var metaMsg = {response: message};
+						if(message.successful) {
+							if (this._status != "connected"){
+								this._status = "connected";
+								this.endBatch();
+							}
+						}
+ 
+						if(this._initialized){
+							this._publishMeta("connect",message.successful, metaMsg);
+						}
+						break;
+					case "/meta/subscribe":
+						deferred = this._deferredSubscribes[message.subscription];
+						try
+						{
+							if(!message.successful){
+								if(deferred){
+									deferred.errback(new Error(message.error));
+								}
+								this.currentTransport.cancelConnect();
+								return;
+							}
+							if(deferred){
+								deferred.callback(true);
+							}
+							this.subscribed(message.subscription, message);
+						} catch(e)	{
+							log.warn(e);
+						}
+						break;
+					case "/meta/unsubscribe":
+						deferred = this._deferredUnsubscribes[message.subscription];
+						try
+						{
+							if(!message.successful){
+								if(deferred){
+									deferred.errback(new Error(message.error));
+								}
+								this.currentTransport.cancelConnect();
+								return;
+							}
+							if(deferred){
+								deferred.callback(true);
+							}
+							this.unsubscribed(message.subscription, message);
+						} catch(e)	{
+							log.warn(e);
+						}
+						break;
+					default:
+						if(message.successful && !message.successful){
+							this.currentTransport.cancelConnect();
+							return;
+						}
+				}
+			}
+			
+			// send the message down for processing by the transport
+			this.currentTransport.deliver(message);
+	
+			if(message.data){
+				// dispatch the message to any locally subscribed listeners
+				try{
+					var messages = [message];
+	
+					// Determine target topic
+					var tname = prefix + message.channel;
+	
+					// Deliver to globs that apply to target topic
+					var tnameParts = message.channel.split("/");
+					var tnameGlob = prefix;
+					for (var i = 1; i < tnameParts.length - 1; i++){
+						dojo.publish(tnameGlob + "/**", messages);
+						tnameGlob += "/" + tnameParts[i];
+					}
+					dojo.publish(tnameGlob + "/**", messages);
+					dojo.publish(tnameGlob + "/*", messages);
+		
+					// deliver to target topic
+					dojo.publish(tname,messages);
+				}catch(e){
+					console.log(e);
+				}
+			}
+		}
+	
+		this._sendMessage = function(/* object */ message){
+			if(this.currentTransport && !this.batch){
+				return this.currentTransport.sendMessages([message]);
+			}else{
+				this._messageQ.push(message);
+				return null;
+			}
+		}
+	
+		this.startBatch = function(){
+			this.batch++;
+		}
+	
+		this.endBatch = function(){
+			if(--this.batch <= 0 && this.currentTransport && this._status == "connected"){
+				this.batch = 0;
+				var messages = this._messageQ;
+				this._messageQ = [];
+				if(messages.length > 0){
+					this.currentTransport.sendMessages(messages);
+				}
+			}
+		}
+		
+		this._onUnload = function(){
+			// make this the last of the onUnload method
+			dojo.addOnUnload(dojox.cometd, "disconnect");
+		}
+	
+		this._connectTimeout = function(){
+			// summary: Return the connect timeout in ms, calculated as the minimum of the advised timeout
+			// and the configured timeout. Else 0 to indicate no client side timeout
+			var advised=0;
+			if(this._advice && this._advice.timeout && this.expectedNetworkDelay > 0){
+				advised = this._advice.timeout + this.expectedNetworkDelay;
+			}
+			
+			if(this.connectTimeout > 0 && this.connectTimeout < advised){
+				return this.connectTimeout;
+			}
+			
+			return advised;
+		}
+	},
+	// connectionTypes are shared by all cometd Connection.
+	connectionTypes : new dojo.AdapterRegistry(true)
 }
-return _3e;
-};
-},connectionTypes:new dojo.AdapterRegistry(true)};
-dojox.cometd.Connection.call(dojox.cometd,"/cometd");
-dojo.addOnUnload(dojox.cometd,"_onUnload");
+
+// create the default instance
+dojox.cometd.Connection.call(dojox.cometd,"/cometd"); 
+
+/*
+
+FIXME: TODOC: this info should be part of the relevant functions and/or overview so
+the parser can find it.
+
+transport objects MUST expose the following methods:
+	- check
+	- startup
+	- sendMessages
+	- deliver
+	- disconnect
+optional, standard but transport dependent methods are:
+	- tunnelCollapse
+	- tunnelInit
+
+Transports SHOULD be namespaced under the cometd object and transports MUST
+register themselves with cometd.connectionTypes
+
+here's a stub transport defintion:
+
+cometd.blahTransport = new function(){
+	this._connectionType="my-polling";
+	this._cometd=null;
+	this.lastTimestamp = null;
+
+	this.check = function(types, version, xdomain){
+		// summary:
+		//		determines whether or not this transport is suitable given a
+		//		list of transport types that the server supports
+		return dojo.inArray(types, "blah");
+	}
+
+	this.startup = function(){
+		if(dojox.cometd._polling){ return; }
+		// FIXME: fill in startup routine here
+		dojox.cometd._polling = true;
+	}
+
+	this.sendMessages = function(message){
+		// FIXME: fill in message array sending logic
+	}
+
+	this.deliver = function(message){
+	}
+
+	this.disconnect = function(){
+		// send orderly disconnect message
+	}
+
+	this.cancelConnect = function(){
+		// cancel the current connection
+	}
 }
+cometd.connectionTypes.register("blah", cometd.blahTransport.check, cometd.blahTransport);
+*/
+
+dojo.addOnUnload(dojox.cometd, "_onUnload");
diff --git a/dojox/cometd/ack.js b/dojox/cometd/ack.js
index 461f9dd..8c37156 100644
--- a/dojox/cometd/ack.js
+++ b/dojox/cometd/ack.js
@@ -1,46 +1,50 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.cometd.ack"]){
-dojo._hasResource["dojox.cometd.ack"]=true;
 dojo.provide("dojox.cometd.ack");
 dojo.require("dojox.cometd._base");
-dojox.cometd._ack=new function(){
-var _1=false;
-var _2=-1;
-this._in=function(_3){
-if(_3.channel=="/meta/handshake"){
-_1=_3.ext&&_3.ext.ack;
-}else{
-if(_1&&_3.channel=="/meta/connect"&&_3.ext&&_3.ext.ack&&_3.successful){
-var _4=parseInt(_3.ext.ack);
-_2=_4;
-}
-}
-return _3;
-};
-this._out=function(_5){
-if(_5.channel=="/meta/handshake"){
-if(!_5.ext){
-_5.ext={};
-}
-_5.ext.ack=dojox.cometd.ackEnabled;
-_2=-1;
-}
-if(_1&&_5.channel=="/meta/connect"){
-if(!_5.ext){
-_5.ext={};
-}
-_5.ext.ack=_2;
-}
-return _5;
-};
+
+/*
+ * This file provides the dojox cometd ack extension which
+ * acknowledges the messages received in /meta/connect responses.
+ * Each meta/connect is sent with the id of the last successful meta/connect
+ * received.  The server uses this information to manage a queue of unacknowleged
+ * messages.
+ *
+ * To use, add dojo.require("dojox.cometd.ack"); and if the handshake will be sent
+ * with ext:{ack:true}.  If the server supports the same extension, then the 
+ * mechanism will be initialized.  The dojox.cometd.ackEnabled field may also be
+ * used to optionally enable/disable the extension before init of cometd.
+ *
+ */
+dojox.cometd._ack = new function(){
+	var supportAcks = false;
+	var lastAck = -1;
+	
+	this._in = function(msg){
+		if (msg.channel == "/meta/handshake") {
+			supportAcks = msg.ext && msg.ext.ack;
+		} else if (supportAcks && msg.channel == "/meta/connect" && msg.ext && msg.ext.ack && msg.successful) {
+			var ackId = parseInt(msg.ext.ack);
+			lastAck = ackId;
+		}
+		return msg;
+	}
+	
+	this._out = function(msg){
+	
+		if (msg.channel == "/meta/handshake") {
+			if (!msg.ext) 
+				msg.ext = {};
+			msg.ext.ack = dojox.cometd.ackEnabled;
+			lastAck = -1;
+		}
+		if (supportAcks && msg.channel == "/meta/connect") {
+			if (!msg.ext) 
+				msg.ext = {};
+			msg.ext.ack = lastAck;
+		}
+		return msg;
+	}
 };
-dojox.cometd._extendInList.push(dojo.hitch(dojox.cometd._ack,"_in"));
-dojox.cometd._extendOutList.push(dojo.hitch(dojox.cometd._ack,"_out"));
-dojox.cometd.ackEnabled=true;
-}
+
+dojox.cometd._extendInList.push(dojo.hitch(dojox.cometd._ack, "_in"));
+dojox.cometd._extendOutList.push(dojo.hitch(dojox.cometd._ack, "_out"));
+dojox.cometd.ackEnabled = true;
diff --git a/dojox/cometd/callbackPollTransport.js b/dojox/cometd/callbackPollTransport.js
index 86d816b..2def71f 100644
--- a/dojox/cometd/callbackPollTransport.js
+++ b/dojox/cometd/callbackPollTransport.js
@@ -1,74 +1,102 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.cometd.callbackPollTransport"]){
-dojo._hasResource["dojox.cometd.callbackPollTransport"]=true;
 dojo.provide("dojox.cometd.callbackPollTransport");
 dojo.require("dojox.cometd._base");
 dojo.require("dojox.cometd.longPollTransport");
 dojo.require("dojo.io.script");
-dojox.cometd.callbackPollTransport=new function(){
-this._connectionType="callback-polling";
-this._cometd=null;
-this.check=function(_1,_2,_3){
-return (dojo.indexOf(_1,"callback-polling")>=0);
-};
-this.tunnelInit=function(){
-var _4={channel:"/meta/connect",clientId:this._cometd.clientId,connectionType:this._connectionType,id:""+this._cometd.messageId++};
-_4=this._cometd._extendOut(_4);
-this.openTunnelWith([_4]);
-};
-this.tunnelCollapse=dojox.cometd.longPollTransport.tunnelCollapse;
-this._connect=dojox.cometd.longPollTransport._connect;
-this.deliver=dojox.cometd.longPollTransport.deliver;
-this.openTunnelWith=function(_5,_6){
-this._cometd._polling=true;
-var _7={load:dojo.hitch(this,function(_8){
-this._cometd._polling=false;
-this._cometd.deliver(_8);
-this._cometd._backon();
-this.tunnelCollapse();
-}),error:dojo.hitch(this,function(_9){
-this._cometd._polling=false;
-this._cometd._publishMeta("connect",false);
-this._cometd._backoff();
-this.tunnelCollapse();
-}),url:(_6||this._cometd.url),content:{message:dojo.toJson(_5)},callbackParamName:"jsonp"};
-var _a=this._cometd._connectTimeout();
-if(_a>0){
-_7.timeout=_a;
-}
-dojo.io.script.get(_7);
-};
-this.sendMessages=function(_b){
-for(var i=0;i<_b.length;i++){
-_b[i].clientId=this._cometd.clientId;
-_b[i].id=""+this._cometd.messageId++;
-_b[i]=this._cometd._extendOut(_b[i]);
-}
-var _c={url:this._cometd.url||dojo.config["cometdRoot"],load:dojo.hitch(this._cometd,"deliver"),callbackParamName:"jsonp",content:{message:dojo.toJson(_b)},error:dojo.hitch(this,function(_d){
-this._cometd._publishMeta("publish",false,{messages:_b});
-}),timeout:this._cometd.expectedNetworkDelay};
-return dojo.io.script.get(_c);
-};
-this.startup=function(_e){
-if(this._cometd._connected){
-return;
-}
-this.tunnelInit();
-};
-this.disconnect=dojox.cometd.longPollTransport.disconnect;
-this.disconnect=function(){
-var _f={channel:"/meta/disconnect",clientId:this._cometd.clientId,id:""+this._cometd.messageId++};
-_f=this._cometd._extendOut(_f);
-dojo.io.script.get({url:this._cometd.url||dojo.config["cometdRoot"],callbackParamName:"jsonp",content:{message:dojo.toJson([_f])}});
-};
-this.cancelConnect=function(){
-};
-};
-dojox.cometd.connectionTypes.register("callback-polling",dojox.cometd.callbackPollTransport.check,dojox.cometd.callbackPollTransport);
+
+dojox.cometd.callbackPollTransport = new function(){
+
+	this._connectionType = "callback-polling";
+	this._cometd = null;
+
+	this.check = function(types, version, xdomain){
+		// we handle x-domain!
+		return (dojo.indexOf(types, "callback-polling") >= 0);
+	}
+
+	this.tunnelInit = function(){
+		var message = {
+			channel:	"/meta/connect",
+			clientId:	this._cometd.clientId,
+			connectionType: this._connectionType,
+			id:	"" + this._cometd.messageId++
+		};
+		message = this._cometd._extendOut(message);		
+		this.openTunnelWith([message]);
+	}
+
+	this.tunnelCollapse = dojox.cometd.longPollTransport.tunnelCollapse;
+	this._connect = dojox.cometd.longPollTransport._connect;
+	this.deliver = dojox.cometd.longPollTransport.deliver;
+
+	this.openTunnelWith = function(content, url){
+		this._cometd._polling = true;
+		var script = {
+			load: dojo.hitch(this, function(data){
+				this._cometd._polling=false;
+				this._cometd.deliver(data);
+				this._cometd._backon();
+				this.tunnelCollapse();
+			}),
+			error: dojo.hitch(this, function(err){
+				this._cometd._polling = false;
+				this._cometd._publishMeta("connect",false);
+				this._cometd._backoff();
+				this.tunnelCollapse();
+			}),
+			url: (url || this._cometd.url),
+			content: { message: dojo.toJson(content) },
+			callbackParamName: "jsonp"
+		};
+		var connectTimeout = this._cometd._connectTimeout();
+		if(connectTimeout > 0){
+			script.timeout=connectTimeout;
+		}
+		dojo.io.script.get(script);
+	}
+
+	this.sendMessages = function(/*array*/ messages){
+		for(var i = 0; i < messages.length; i++){
+			messages[i].clientId = this._cometd.clientId;
+			messages[i].id = ""+this._cometd.messageId++;
+			messages[i]=this._cometd._extendOut(messages[i]);
+		}
+
+		var bindArgs = {
+			url: this._cometd.url || dojo.config["cometdRoot"],
+			load: dojo.hitch(this._cometd, "deliver"),
+			callbackParamName: "jsonp",
+			content: { message: dojo.toJson( messages ) },
+			error: dojo.hitch(this, function(err){
+				this._cometd._publishMeta("publish",false,{messages:messages});
+			}),
+			timeout: this._cometd.expectedNetworkDelay
+		};
+		return dojo.io.script.get(bindArgs);
+	}
+
+	this.startup = function(handshakeData){
+		if(this._cometd._connected){ return; }
+		this.tunnelInit();
+	}
+
+	// FIXME: what is this supposed to do? ;)
+	this.disconnect = dojox.cometd.longPollTransport.disconnect;	
+	this.disconnect = function(){
+		var message = {
+			channel: "/meta/disconnect",
+			clientId: this._cometd.clientId,
+			id: "" + this._cometd.messageId++
+		};
+		message = this._cometd._extendOut(message);		
+		dojo.io.script.get({
+			url: this._cometd.url || dojo.config["cometdRoot"],
+			callbackParamName: "jsonp",
+			content: { message: dojo.toJson([message]) }
+		});
+	}
+
+	this.cancelConnect = function(){}
 }
+
+dojox.cometd.connectionTypes.register("callback-polling", dojox.cometd.callbackPollTransport.check, dojox.cometd.callbackPollTransport);
+
diff --git a/dojox/cometd/longPollTransport.js b/dojox/cometd/longPollTransport.js
index 84fae98..d7b3b39 100644
--- a/dojox/cometd/longPollTransport.js
+++ b/dojox/cometd/longPollTransport.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.cometd.longPollTransport"]){
-dojo._hasResource["dojox.cometd.longPollTransport"]=true;
 dojo.provide("dojox.cometd.longPollTransport");
 dojo.require("dojox.cometd.longPollTransportJsonEncoded");
-}
diff --git a/dojox/cometd/longPollTransportFormEncoded.js b/dojox/cometd/longPollTransportFormEncoded.js
index 077e450..14af240 100644
--- a/dojox/cometd/longPollTransportFormEncoded.js
+++ b/dojox/cometd/longPollTransportFormEncoded.js
@@ -1,118 +1,157 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.cometd.longPollTransportFormEncoded"]){
-dojo._hasResource["dojox.cometd.longPollTransportFormEncoded"]=true;
 dojo.provide("dojox.cometd.longPollTransportFormEncoded");
 dojo.require("dojox.cometd._base");
-dojox.cometd.longPollTransportFormEncoded=new function(){
-this._connectionType="long-polling";
-this._cometd=null;
-this.check=function(_1,_2,_3){
-return ((!_3)&&(dojo.indexOf(_1,"long-polling")>=0));
-};
-this.tunnelInit=function(){
-var _4={channel:"/meta/connect",clientId:this._cometd.clientId,connectionType:this._connectionType,id:""+this._cometd.messageId++};
-_4=this._cometd._extendOut(_4);
-this.openTunnelWith({message:dojo.toJson([_4])});
-};
-this.tunnelCollapse=function(){
-if(!this._cometd._initialized){
-return;
-}
-if(this._cometd._advice&&this._cometd._advice["reconnect"]=="none"){
-return;
-}
-var _5=this._cometd._interval();
-if(this._cometd._status=="connected"){
-setTimeout(dojo.hitch(this,"_connect"),_5);
-}else{
-setTimeout(dojo.hitch(this._cometd,function(){
-this.init(this.url,this._props);
-}),_5);
-}
-};
-this._connect=function(){
-if(!this._cometd._initialized){
-return;
-}
-if(this._cometd._polling){
-return;
-}
-if((this._cometd._advice)&&(this._cometd._advice["reconnect"]=="handshake")){
-this._cometd._status="unconnected";
-this._initialized=false;
-this._cometd.init(this._cometd.url,this._cometd._props);
-}else{
-if(this._cometd._status=="connected"){
-var _6={channel:"/meta/connect",connectionType:this._connectionType,clientId:this._cometd.clientId,id:""+this._cometd.messageId++};
-if(this._cometd.connectTimeout>=this._cometd.expectedNetworkDelay){
-_6.advice={timeout:this._cometd.connectTimeout-this._cometd.expectedNetworkDelay};
-}
-_6=this._cometd._extendOut(_6);
-this.openTunnelWith({message:dojo.toJson([_6])});
-}
-}
-};
-this.deliver=function(_7){
-};
-this.openTunnelWith=function(_8,_9){
-this._cometd._polling=true;
-var _a={url:(_9||this._cometd.url),content:_8,handleAs:this._cometd.handleAs,load:dojo.hitch(this,function(_b){
-this._cometd._polling=false;
-this._cometd.deliver(_b);
-this._cometd._backon();
-this.tunnelCollapse();
-}),error:dojo.hitch(this,function(_c){
-var _d={failure:true,error:_c,advice:this._cometd._advice};
-this._cometd._polling=false;
-this._cometd._publishMeta("connect",false,_d);
-this._cometd._backoff();
-this.tunnelCollapse();
-})};
-var _e=this._cometd._connectTimeout();
-if(_e>0){
-_a.timeout=_e;
-}
-this._poll=dojo.xhrPost(_a);
-};
-this.sendMessages=function(_f){
-for(var i=0;i<_f.length;i++){
-_f[i].clientId=this._cometd.clientId;
-_f[i].id=""+this._cometd.messageId++;
-_f[i]=this._cometd._extendOut(_f[i]);
-}
-return dojo.xhrPost({url:this._cometd.url||dojo.config["cometdRoot"],handleAs:this._cometd.handleAs,load:dojo.hitch(this._cometd,"deliver"),content:{message:dojo.toJson(_f)},error:dojo.hitch(this,function(err){
-this._cometd._publishMeta("publish",false,{messages:_f});
-}),timeout:this._cometd.expectedNetworkDelay});
-};
-this.startup=function(_10){
-if(this._cometd._status=="connected"){
-return;
-}
-this.tunnelInit();
-};
-this.disconnect=function(){
-var _11={channel:"/meta/disconnect",clientId:this._cometd.clientId,id:""+this._cometd.messageId++};
-_11=this._cometd._extendOut(_11);
-dojo.xhrPost({url:this._cometd.url||dojo.config["cometdRoot"],handleAs:this._cometd.handleAs,content:{message:dojo.toJson([_11])}});
-};
-this.cancelConnect=function(){
-if(this._poll){
-this._poll.cancel();
-this._cometd._polling=false;
-this._cometd._publishMeta("connect",false,{cancel:true});
-this._cometd._backoff();
-this.disconnect();
-this.tunnelCollapse();
-}
-};
-};
-dojox.cometd.longPollTransport=dojox.cometd.longPollTransportFormEncoded;
-dojox.cometd.connectionTypes.register("long-polling",dojox.cometd.longPollTransport.check,dojox.cometd.longPollTransportFormEncoded);
-dojox.cometd.connectionTypes.register("long-polling-form-encoded",dojox.cometd.longPollTransport.check,dojox.cometd.longPollTransportFormEncoded);
+
+dojox.cometd.longPollTransportFormEncoded = new function(){
+	// This is an alternative implementation to that provided in logPollTransport.js that 
+	// form encodes all messages instead of sending them as text/json
+	
+	this._connectionType = "long-polling";
+	this._cometd = null;
+
+	this.check = function(types, version, xdomain){
+		return ((!xdomain)&&(dojo.indexOf(types, "long-polling") >= 0));
+	}
+
+	this.tunnelInit = function(){
+		var message = {
+			channel: "/meta/connect",
+			clientId: this._cometd.clientId,
+			connectionType: this._connectionType,
+			id:	"" + this._cometd.messageId++
+		};
+		message = this._cometd._extendOut(message);
+		this.openTunnelWith({ message: dojo.toJson([message]) });
+	}
+
+	this.tunnelCollapse = function(){
+		// TODO handle transport specific advice
+		
+		if(!this._cometd._initialized){ return; }
+		if(this._cometd._advice && this._cometd._advice["reconnect"]=="none"){
+			return;
+		}
+		var interval = this._cometd._interval();
+		if (this._cometd._status=="connected") {
+			setTimeout(dojo.hitch(this, "_connect"), interval);
+		}else{
+			setTimeout(dojo.hitch(this._cometd, function(){
+				this.init(this.url, this._props);
+			}), interval);
+		}
+	}
+
+	this._connect = function(){
+		if(!this._cometd._initialized){ return; }
+		if(this._cometd._polling) { return; }
+			
+		if((this._cometd._advice) && (this._cometd._advice["reconnect"]=="handshake")){
+			this._cometd._status="unconnected"; //?
+			this._initialized = false;
+			this._cometd.init(this._cometd.url, this._cometd._props);
+ 		}else if(this._cometd._status=="connected"){
+			var message = {
+				channel: "/meta/connect",
+				connectionType: this._connectionType,
+				clientId: this._cometd.clientId,
+				id:	"" + this._cometd.messageId++
+			};
+			if(this._cometd.connectTimeout>=this._cometd.expectedNetworkDelay){
+				message.advice = { 
+					timeout: this._cometd.connectTimeout - this._cometd.expectedNetworkDelay
+				};
+			}
+			message = this._cometd._extendOut(message);
+			this.openTunnelWith({ message: dojo.toJson([message]) });
+		}
+	}
+
+	this.deliver = function(message){
+		// Nothing to do
+	}
+
+	this.openTunnelWith = function(content, url){
+		this._cometd._polling = true;
+		var post = {
+			url: (url||this._cometd.url),
+			content: content,
+			handleAs: this._cometd.handleAs,
+			load: dojo.hitch(this, function(data){
+				this._cometd._polling=false;
+				this._cometd.deliver(data);
+				this._cometd._backon();
+				this.tunnelCollapse();
+			}),
+			error: dojo.hitch(this, function(err){
+				var metaMsg = {
+					failure: true,
+					error: err,
+					advice: this._cometd._advice
+				};
+				this._cometd._polling=false;
+				this._cometd._publishMeta("connect",false, metaMsg);
+				this._cometd._backoff();
+				this.tunnelCollapse();
+			})
+		};
+
+		var connectTimeout = this._cometd._connectTimeout();
+		if(connectTimeout > 0){
+			post.timeout = connectTimeout;
+		}
+
+		this._poll = dojo.xhrPost(post);
+	}
+
+	this.sendMessages = function(messages){
+		for(var i=0; i < messages.length; i++){
+			messages[i].clientId = this._cometd.clientId;
+			messages[i].id = "" + this._cometd.messageId++;
+			messages[i]= this._cometd._extendOut(messages[i]);
+		}
+		return dojo.xhrPost({
+			url: this._cometd.url||dojo.config["cometdRoot"],
+			handleAs: this._cometd.handleAs,
+			load: dojo.hitch(this._cometd, "deliver"),
+			content: { message: dojo.toJson(messages) },
+			error: dojo.hitch(this, function(err){
+				this._cometd._publishMeta("publish",false,{messages:messages});
+			}),
+			timeout: this._cometd.expectedNetworkDelay
+		});
+	}
+
+	this.startup = function(handshakeData){
+		if(this._cometd._status=="connected"){ return; }
+		this.tunnelInit();
+	}
+
+	this.disconnect = function(){
+		var message = {
+			channel: "/meta/disconnect",
+			clientId: this._cometd.clientId,
+			id: "" + this._cometd.messageId++
+		};
+		message = this._cometd._extendOut(message);
+		dojo.xhrPost({
+			url: this._cometd.url || dojo.config["cometdRoot"],
+			handleAs: this._cometd.handleAs,
+			content: { message: dojo.toJson([message]) }
+		});
+	}
+
+	this.cancelConnect = function(){
+		if(this._poll){
+			this._poll.cancel();
+			this._cometd._polling=false;
+			this._cometd._publishMeta("connect",false,{cancel:true});
+			this._cometd._backoff();
+			this.disconnect();
+			this.tunnelCollapse();
+		}
+	}
 }
+
+dojox.cometd.longPollTransport = dojox.cometd.longPollTransportFormEncoded;
+
+dojox.cometd.connectionTypes.register("long-polling", dojox.cometd.longPollTransport.check, dojox.cometd.longPollTransportFormEncoded);
+dojox.cometd.connectionTypes.register("long-polling-form-encoded", dojox.cometd.longPollTransport.check, dojox.cometd.longPollTransportFormEncoded);
diff --git a/dojox/cometd/longPollTransportJsonEncoded.js b/dojox/cometd/longPollTransportJsonEncoded.js
index 75d1888..6859480 100644
--- a/dojox/cometd/longPollTransportJsonEncoded.js
+++ b/dojox/cometd/longPollTransportJsonEncoded.js
@@ -1,119 +1,159 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.cometd.longPollTransportJsonEncoded"]){
-dojo._hasResource["dojox.cometd.longPollTransportJsonEncoded"]=true;
 dojo.provide("dojox.cometd.longPollTransportJsonEncoded");
 dojo.require("dojox.cometd._base");
-dojox.cometd.longPollTransportJsonEncoded=new function(){
-this._connectionType="long-polling";
-this._cometd=null;
-this.check=function(_1,_2,_3){
-return ((!_3)&&(dojo.indexOf(_1,"long-polling")>=0));
-};
-this.tunnelInit=function(){
-var _4={channel:"/meta/connect",clientId:this._cometd.clientId,connectionType:this._connectionType,id:""+this._cometd.messageId++};
-_4=this._cometd._extendOut(_4);
-this.openTunnelWith([_4]);
-};
-this.tunnelCollapse=function(){
-if(!this._cometd._initialized){
-return;
-}
-if(this._cometd._advice&&this._cometd._advice["reconnect"]=="none"){
-return;
-}
-if(this._cometd._status=="connected"){
-setTimeout(dojo.hitch(this,function(){
-this._connect();
-}),this._cometd._interval());
-}else{
-setTimeout(dojo.hitch(this._cometd,function(){
-this.init(this.url,this._props);
-}),this._cometd._interval());
-}
-};
-this._connect=function(){
-if(!this._cometd._initialized){
-return;
-}
-if(this._cometd._polling){
-return;
-}
-if((this._cometd._advice)&&(this._cometd._advice["reconnect"]=="handshake")){
-this._cometd._status="unconnected";
-this._initialized=false;
-this._cometd.init(this._cometd.url,this._cometd._props);
-}else{
-if(this._cometd._status=="connected"){
-var _5={channel:"/meta/connect",connectionType:this._connectionType,clientId:this._cometd.clientId,id:""+this._cometd.messageId++};
-if(this._cometd.connectTimeout>=this._cometd.expectedNetworkDelay){
-_5.advice={timeout:(this._cometd.connectTimeout-this._cometd.expectedNetworkDelay)};
-}
-_5=this._cometd._extendOut(_5);
-this.openTunnelWith([_5]);
-}
-}
-};
-this.deliver=function(_6){
-};
-this.openTunnelWith=function(_7,_8){
-this._cometd._polling=true;
-var _9={url:(_8||this._cometd.url),postData:dojo.toJson(_7),contentType:"text/json;charset=UTF-8",handleAs:this._cometd.handleAs,load:dojo.hitch(this,function(_a){
-this._cometd._polling=false;
-this._cometd.deliver(_a);
-this._cometd._backon();
-this.tunnelCollapse();
-}),error:dojo.hitch(this,function(_b){
-this._cometd._polling=false;
-var _c={failure:true,error:_b,advice:this._cometd._advice};
-this._cometd._publishMeta("connect",false,_c);
-this._cometd._backoff();
-this.tunnelCollapse();
-})};
-var _d=this._cometd._connectTimeout();
-if(_d>0){
-_9.timeout=_d;
-}
-this._poll=dojo.rawXhrPost(_9);
-};
-this.sendMessages=function(_e){
-for(var i=0;i<_e.length;i++){
-_e[i].clientId=this._cometd.clientId;
-_e[i].id=""+this._cometd.messageId++;
-_e[i]=this._cometd._extendOut(_e[i]);
-}
-return dojo.rawXhrPost({url:this._cometd.url||dojo.config["cometdRoot"],handleAs:this._cometd.handleAs,load:dojo.hitch(this._cometd,"deliver"),postData:dojo.toJson(_e),contentType:"text/json;charset=UTF-8",error:dojo.hitch(this,function(_f){
-this._cometd._publishMeta("publish",false,{messages:_e});
-}),timeout:this._cometd.expectedNetworkDelay});
-};
-this.startup=function(_10){
-if(this._cometd._status=="connected"){
-return;
-}
-this.tunnelInit();
-};
-this.disconnect=function(){
-var _11={channel:"/meta/disconnect",clientId:this._cometd.clientId,id:""+this._cometd.messageId++};
-_11=this._cometd._extendOut(_11);
-dojo.rawXhrPost({url:this._cometd.url||dojo.config["cometdRoot"],handleAs:this._cometd.handleAs,postData:dojo.toJson([_11]),contentType:"text/json;charset=UTF-8"});
-};
-this.cancelConnect=function(){
-if(this._poll){
-this._poll.cancel();
-this._cometd._polling=false;
-this._cometd._publishMeta("connect",false,{cancel:true});
-this._cometd._backoff();
-this.disconnect();
-this.tunnelCollapse();
-}
-};
-};
-dojox.cometd.longPollTransport=dojox.cometd.longPollTransportJsonEncoded;
-dojox.cometd.connectionTypes.register("long-polling",dojox.cometd.longPollTransport.check,dojox.cometd.longPollTransportJsonEncoded);
-dojox.cometd.connectionTypes.register("long-polling-json-encoded",dojox.cometd.longPollTransport.check,dojox.cometd.longPollTransportJsonEncoded);
+
+dojox.cometd.longPollTransportJsonEncoded = new function(){
+	// This is an alternative implementation to that provided in logPollTransportFormEncoded.js 
+	// that sends messages as text/json rather than form encoding them. 
+	
+	this._connectionType="long-polling";
+	this._cometd=null;
+
+	this.check = function(types, version, xdomain){
+		return ((!xdomain)&&(dojo.indexOf(types, "long-polling") >= 0));
+	}
+
+	this.tunnelInit = function(){
+		var message = {
+			channel:	"/meta/connect",
+			clientId:	this._cometd.clientId,
+			connectionType: this._connectionType,
+			id:	""+this._cometd.messageId++
+		};
+		message=this._cometd._extendOut(message);
+		this.openTunnelWith([message]);
+	}
+
+	this.tunnelCollapse = function(){
+		// TODO handle transport specific advice
+		
+		if(!this._cometd._initialized){ return; }
+			
+		if(this._cometd._advice && this._cometd._advice["reconnect"]=="none"){
+			return;
+		}
+		if (this._cometd._status=="connected") {
+			setTimeout(dojo.hitch(this,function(){this._connect();}),this._cometd._interval());
+		}else{
+			setTimeout(dojo.hitch(this._cometd,function(){this.init(this.url,this._props);}),this._cometd._interval());
+		}
+	}
+
+	this._connect = function(){
+		if(!this._cometd._initialized){ return; }
+		if(this._cometd._polling) {
+			return;
+		}
+			
+		if((this._cometd._advice) && (this._cometd._advice["reconnect"]=="handshake")){
+			this._cometd._status="unconnected";
+			this._initialized = false;
+			this._cometd.init(this._cometd.url,this._cometd._props);
+ 		}else if(this._cometd._status=="connected"){
+			var message={
+				channel:	"/meta/connect",
+				connectionType: this._connectionType,
+				clientId:	this._cometd.clientId,
+				id:	""+this._cometd.messageId++
+			};
+			if (this._cometd.connectTimeout>=this._cometd.expectedNetworkDelay){
+				message.advice={timeout:(this._cometd.connectTimeout-this._cometd.expectedNetworkDelay)};
+			}
+			message=this._cometd._extendOut(message);
+			this.openTunnelWith([message]);
+		}
+	}
+
+	this.deliver = function(message){
+		// Nothing to do
+	}
+
+	this.openTunnelWith = function(messages, url){
+		this._cometd._polling = true;
+		var post = {
+			url: (url||this._cometd.url),
+			postData: dojo.toJson(messages),
+			contentType: "text/json;charset=UTF-8",
+			handleAs: this._cometd.handleAs,
+			load: dojo.hitch(this, function(data){
+				this._cometd._polling=false;
+				this._cometd.deliver(data);
+				this._cometd._backon();
+				this.tunnelCollapse();
+			}),
+			error: dojo.hitch(this, function(err){
+				this._cometd._polling=false;
+				var metaMsg = {
+					failure: true,
+					error: err,
+					advice: this._cometd._advice
+				};
+				this._cometd._publishMeta("connect",false, metaMsg);
+				this._cometd._backoff();
+				this.tunnelCollapse();
+			})
+		};
+
+		var connectTimeout=this._cometd._connectTimeout();
+		if (connectTimeout>0) {
+			post.timeout=connectTimeout;
+		}
+
+		this._poll = dojo.rawXhrPost(post);
+	}
+
+	this.sendMessages = function(messages){
+		for(var i=0; i<messages.length; i++){
+			messages[i].clientId = this._cometd.clientId;
+			messages[i].id = ""+this._cometd.messageId++;
+			messages[i]=this._cometd._extendOut(messages[i]);
+		}
+		return dojo.rawXhrPost({
+			url: this._cometd.url||dojo.config["cometdRoot"],
+			handleAs: this._cometd.handleAs,
+			load: dojo.hitch(this._cometd, "deliver"),
+			postData: dojo.toJson(messages),
+			contentType: "text/json;charset=UTF-8",
+			error: dojo.hitch(this, function(err){
+				this._cometd._publishMeta("publish",false,{messages:messages});
+			}),
+			timeout: this._cometd.expectedNetworkDelay
+		});
+	}
+
+	this.startup = function(handshakeData){
+		if(this._cometd._status=="connected"){ return; }
+		this.tunnelInit();
+	}
+
+	this.disconnect = function(){
+		var message = {
+			channel: "/meta/disconnect",
+			clientId: this._cometd.clientId,
+			id:	"" + this._cometd.messageId++
+		};
+		message = this._cometd._extendOut(message);
+		dojo.rawXhrPost({
+			url: this._cometd.url || dojo.config["cometdRoot"],
+			handleAs: this._cometd.handleAs,
+			postData: dojo.toJson([message]),
+			contentType: "text/json;charset=UTF-8"
+		});
+	}
+
+	this.cancelConnect = function(){
+		if(this._poll){
+			this._poll.cancel();
+			this._cometd._polling=false;
+			this._cometd._publishMeta("connect",false,{cancel:true});
+			this._cometd._backoff();
+			this.disconnect();
+			this.tunnelCollapse();
+		}
+	}
 }
+
+dojox.cometd.longPollTransport = dojox.cometd.longPollTransportJsonEncoded;
+
+dojox.cometd.connectionTypes.register("long-polling", dojox.cometd.longPollTransport.check, dojox.cometd.longPollTransportJsonEncoded);
+dojox.cometd.connectionTypes.register("long-polling-json-encoded", dojox.cometd.longPollTransport.check, dojox.cometd.longPollTransportJsonEncoded);
+
diff --git a/dojox/cometd/tests/_base.js b/dojox/cometd/tests/_base.js
new file mode 100644
index 0000000..1d836c7
--- /dev/null
+++ b/dojox/cometd/tests/_base.js
@@ -0,0 +1,31 @@
+dojo.provide("dojox.cometd.tests._base");
+dojo.require("dojox.cometd");
+
+tests.register("dojox.cometd.tests._base", [
+
+	function basicSyntaxCheck(t){
+		// w00t, we made it! (FIXME: how to unit test basic functionality?)
+		// FIXME: gregw? include basicSyntax tests for other transports?
+		t.assertTrue(true);
+	},
+
+	function basicInitCheck(t){
+		var d = dojox.cometd.init("http://www.sitepen.com:9000/cometd");
+		if(d){
+			t.assertTrue(true);
+		}
+	},
+
+	function basicSubscribeCheck(t){
+		dojox.cometd.subscribe("/basic/unit/test", function(e){
+			console.log("message received", e);
+		});
+		t.assertTrue(true);		
+	},
+
+	function basicPublishCheck(t){
+		dojox.cometd.publish("/basic/unit/test", [{ message: "unit test" }]);
+		t.assertTrue(true);
+	}
+
+]);
diff --git a/dojox/cometd/tests/all.js b/dojox/cometd/tests/all.js
new file mode 100644
index 0000000..e681fe5
--- /dev/null
+++ b/dojox/cometd/tests/all.js
@@ -0,0 +1,8 @@
+dojo.provide("dojox.cometd.tests.all");
+dojo.require("dojox.cometd._base");
+
+try{
+	dojo.require("dojox.cometd.tests._base");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/cometd/tests/runTests.html b/dojox/cometd/tests/runTests.html
new file mode 100644
index 0000000..9982545
--- /dev/null
+++ b/dojox/cometd/tests/runTests.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox.wire Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.cometd.tests.all">
+	</head>
+    <body>
+        Redirecting to D.O.H runner.
+    </body>
+</html> 
diff --git a/dojox/cometd/timestamp.js b/dojox/cometd/timestamp.js
index 77b20c5..d0c537e 100644
--- a/dojox/cometd/timestamp.js
+++ b/dojox/cometd/timestamp.js
@@ -1,16 +1,8 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.cometd.timestamp"]){
-dojo._hasResource["dojox.cometd.timestamp"]=true;
 dojo.provide("dojox.cometd.timestamp");
 dojo.require("dojox.cometd._base");
-dojox.cometd._extendOutList.push(function(_1){
-_1.timestamp=new Date().toUTCString();
-return _1;
+
+// A cometd extension that adds a timestamp to every message
+dojox.cometd._extendOutList.push(function(msg){
+	msg.timestamp = new Date().toUTCString();
+	return msg
 });
-}
diff --git a/dojox/cometd/timesync.js b/dojox/cometd/timesync.js
index 9e75172..d7e9b32 100644
--- a/dojox/cometd/timesync.js
+++ b/dojox/cometd/timesync.js
@@ -1,75 +1,141 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.cometd.timesync"]){
-dojo._hasResource["dojox.cometd.timesync"]=true;
 dojo.provide("dojox.cometd.timesync");
 dojo.require("dojox.cometd._base");
-dojox.cometd.timesync=new function(){
-this._window=10;
-this._lags=[];
-this._offsets=[];
-this.lag=0;
-this.offset=0;
-this.samples=0;
-this.getServerTime=function(){
-return new Date().getTime()+this.offset;
-};
-this.getServerDate=function(){
-return new Date(this.getServerTime());
-};
-this.setTimeout=function(_1,_2){
-var ts=(_2 instanceof Date)?_2.getTime():(0+_2);
-var tc=ts-this.offset;
-var _3=tc-new Date().getTime();
-if(_3<=0){
-_3=1;
-}
-return setTimeout(_1,_3);
-};
-this._in=function(_4){
-var _5=_4.channel;
-if(_5&&_5.indexOf("/meta/")==0){
-if(_4.ext&&_4.ext.timesync){
-var _6=_4.ext.timesync;
-var _7=new Date().getTime();
-var l=(_7-_6.tc-_6.p)/2-_6.a;
-var o=_6.ts-_6.tc-l;
-this._lags.push(l);
-this._offsets.push(o);
-if(this._offsets.length>this._window){
-this._offsets.shift();
-this._lags.shift();
-}
-this.samples++;
-l=0;
-o=0;
-for(var i in this._offsets){
-l+=this._lags[i];
-o+=this._offsets[i];
-}
-this.offset=parseInt((o/this._offsets.length).toFixed());
-this.lag=parseInt((l/this._lags.length).toFixed());
-}
-}
-return _4;
-};
-this._out=function(_8){
-var _9=_8.channel;
-if(_9&&_9.indexOf("/meta/")==0){
-var _a=new Date().getTime();
-if(!_8.ext){
-_8.ext={};
-}
-_8.ext.timesync={tc:_a,l:this.lag,o:this.offset};
-}
-return _8;
-};
+
+/**
+ * this file provides the time synchronization extension to cometd.
+ * Timesync allows the client and server to exchange time information on every 
+ * handshake and connect message so that the client may calculate an approximate
+ * offset from it's own clock epoch to that of the server.
+ *
+ * With each handshake or connect, the extension sends timestamps within the 
+ * ext field like: <code>{ext:{timesync:{tc:12345567890,l:23,o:4567},...},...}</code>
+ * where:<ul>
+ *  <li>tc is the client timestamp in ms since 1970 of when the message was sent.
+ *  <li>l is the network lag that the client has calculated.
+ *  <li>o is the clock offset that the client has calculated.
+ * </ul>
+ * The accuracy of the offset and lag may be calculated with tc-now-l-o,
+ * which should be zero if the calculated offset and lag are perfectly
+ * accurate.
+ * <p>
+ * A cometd server that supports timesync, should respond only if the
+ * measured accuracy value is greater than accuracy target. The response
+ * will be an ext field like: <code>{ext:{timesync:{tc:12345567890,ts:1234567900,p:123,a:3},...},...}</code>
+ * where:<ul>
+ *  <li>tc is the client timestamp of when the message was sent,
+ *  <li>ts is the server timestamp of when the message was received
+ *  <li>p is the poll duration in ms - ie the time the server took before sending the response.
+ *  <li>a is the measured accuracy of the calculated offset and lag sent by the client
+ * </ul>
+ * 
+ * On receipt of the response, the client is able to use current time to determine
+ * the total trip time, from which p is subtracted to determine an approximate
+ * two way network traversal time. The measured accuracy is used to adjust the assumption 
+ * that the network is symmetric for traversal time, so: <ul>
+ * <li>lag = (now-tc-p)/2-a
+ * <li>offset = ts-tc-lag
+ * </ul>
+ *
+ * In order to smooth over any transient fluctuations, the extension keeps a sliding
+ * average of the offsets received. By default this is over 10 messages, but this can
+ * be changed with the dojox.cometd.timesync._window element.
+ */
+dojox.cometd.timesync = new function(){
+	this._window = 10;		// The window size for the sliding average of offset samples.
+	this._lags = [];		// The samples used to calculate the average lag.
+	this._offsets = [];		// The samples used to calculate the average offset.
+	this.lag=0;				// The calculated network lag from client to server
+	this.offset = 0;		// The offset in ms between the clients clock and the servers clock. 
+	this.samples = 0; 		// The number of samples used to calculate the offset. If 0, the offset is not valid.
+	
+	this.getServerTime = function(){ // return: long
+		// Summary:
+		//	Calculate the current time on the server
+		// 
+		return new Date().getTime()+this.offset;
+	}
+	
+	this.getServerDate = function(){ // return: Date
+		// Summary:
+		//	Calculate the current time on the server
+		// 
+		return new Date(this.getServerTime());
+	}
+	
+	this.setTimeout = function(/*function*/call, /*long|Date*/atTimeOrDate){
+		// Summary:
+		//	Set a timeout function relative to server time
+		// call:
+		//	the function to call when the timeout occurs
+		// atTimeOrTime: 
+		//	a long timestamp or a Date representing the server time at
+		//	which the timeout should occur.
+		
+		var ts = (atTimeOrDate instanceof Date) ? atTimeOrDate.getTime() : (0 + atTimeOrDate);
+		var tc = ts - this.offset;
+		var interval = tc - new Date().getTime();
+		if(interval <= 0){
+			interval = 1;
+		}
+		return setTimeout(call,interval);
+	}
+
+	this._in = function(/*Object*/msg){
+		// Summary:
+		//	Handle incoming messages for the timesync extension.
+		// description:
+		//	Look for ext:{timesync:{}} field and calculate offset if present.
+		// msg: 
+		//	The incoming bayeux message
+		
+		var channel = msg.channel;
+		if(channel && channel.indexOf('/meta/') == 0){
+			if(msg.ext && msg.ext.timesync){
+				var sync = msg.ext.timesync;
+				var now = new Date().getTime();
+				var l=(now-sync.tc-sync.p)/2-sync.a;
+				var o=sync.ts-sync.tc-l;
+				
+				this._lags.push(l);
+				this._offsets.push(o);
+				if(this._offsets.length > this._window){
+					this._offsets.shift();
+					this._lags.shift();
+				}
+				this.samples++;
+				l=0;
+				o=0;
+				for(var i in this._offsets){
+					l+=this._lags[i];
+					o+=this._offsets[i];
+				}
+				this.offset = parseInt((o / this._offsets.length).toFixed());
+				this.lag = parseInt((l / this._lags.length).toFixed());
+				
+			}
+		}
+		return msg;
+	}
+
+	this._out = function(msg){
+		// Summary:
+		//	Handle outgoing messages for the timesync extension.
+		// description:
+		//	Look for handshake and connect messages and add the ext:{timesync:{}} fields
+		// msg: 
+		//	The outgoing bayeux message
+		
+		var channel = msg.channel;
+		if(channel && channel.indexOf('/meta/') == 0){
+			var now = new Date().getTime();
+			if(!msg.ext){
+				msg.ext = {};
+			}
+			msg.ext.timesync = {tc:now,l:this.lag,o:this.offset};
+		}
+		return msg;
+	}
 };
-dojox.cometd._extendInList.push(dojo.hitch(dojox.cometd.timesync,"_in"));
-dojox.cometd._extendOutList.push(dojo.hitch(dojox.cometd.timesync,"_out"));
-}
+
+dojox.cometd._extendInList.push(dojo.hitch(dojox.cometd.timesync, "_in"));
+dojox.cometd._extendOutList.push(dojo.hitch(dojox.cometd.timesync, "_out"));
diff --git a/dojox/css3/fx.js b/dojox/css3/fx.js
new file mode 100644
index 0000000..e69cfbe
--- /dev/null
+++ b/dojox/css3/fx.js
@@ -0,0 +1,183 @@
+dojo.provide("dojox.css3.fx");
+
+dojo.require("dojo.fx");
+dojo.require("dojox.html.ext-dojo.style");
+dojo.require("dojox.fx.ext-dojo.complex");
+
+dojo.mixin(dojox.css3.fx, {
+	puff: function(args){
+		// summary:
+		//		Returns an animation that will do a "puff" effect on the given node
+		//
+		// description:
+		//		Fades out an element and scales it to args.endScale
+		//
+		return dojo.fx.combine([dojo.fadeOut(args),
+			this.expand({
+				node: args.node,
+				endScale: args.endScale || 2
+			})
+		]);
+	},
+
+	expand: function(args){
+		// summary:
+		//		Returns an animation that expands args.node
+		//
+		// description:
+		//		Scales an element to args.endScale
+		//
+		return dojo.animateProperty({
+			node: args.node,
+			properties: {
+				transform: { start: "scale(1)", end: "scale(" + [args.endScale || 3] + ")" }
+			}
+		});
+	},
+
+	shrink: function(args){
+		// summary:
+		//		Returns an animation that shrinks args.node
+		//
+		// description:
+		//		Shrinks an element, same as expand({ node: node, endScale: .01 });
+		//
+		return this.expand({
+			node: args.node,
+			endScale: .01
+		});
+	},
+
+	rotate: function(args){
+		// summary:
+		//		Returns an animation that rotates an element
+		//
+		// description:
+		//		Rotates an element from args.startAngle to args.endAngle
+		//
+		return dojo.animateProperty({
+			node: args.node,
+			duration: args.duration || 1000,
+			properties: {
+				transform: { start: "rotate(" + (args.startAngle || "0deg") + ")", end: "rotate(" + (args.endAngle || "360deg") + ")" }
+			}
+		});
+	},
+
+	flip: function(args){
+		// summary:
+		//		Returns an animation that flips an element around his y axis
+		//
+		// description:
+		//		Flips an element around his y axis. The default is a 360deg flip
+		//		but it's possible to run a partial flip using args.whichAnims
+		//
+		// example:
+		//	|	// half flip
+		//	|	dojox.css3.fx.flip({
+		//	|		node: domNode,
+		//	|		whichAnim: [0, 1] 
+		//	|	}).play();
+		//
+		var anims = [],
+			whichAnims = args.whichAnims || [0, 1, 2, 3],
+				direction = args.direction || 1,
+			transforms = [
+				{ start: "scale(1, 1) skew(0deg,0deg)", end: "scale(0, 1) skew(0," + (direction * 30) + "deg)" },
+				{ start: "scale(0, 1) skew(0deg," + (direction * 30) + "deg)", end: "scale(-1, 1) skew(0deg,0deg)" },
+				{ start: "scale(-1, 1) skew(0deg,0deg)", end: "scale(0, 1) skew(0deg," + (-direction * 30) + "deg)" },
+				{ start: "scale(0, 1) skew(0deg," + (-direction * 30) + "deg)", end: "scale(1, 1) skew(0deg,0deg)" }
+		];
+		for(var i = 0; i < whichAnims.length; i++){
+			anims.push(dojo.animateProperty(
+				dojo.mixin({
+				node: args.node,
+				duration: args.duration || 600,
+				properties: {
+					transform: transforms[whichAnims[i]]
+				}}, args)
+			));
+		}
+		return dojo.fx.chain(anims);
+	},
+
+	bounce: function(args){
+		// summary:
+		//		Returns an animation that do a "bounce" effect on args.node
+		//
+		// description:
+		//		Vertical bounce animation, the scaleX, scaleY deformation and the
+		//		jump height (args.jumpHeight) can be specified
+		//
+		var anims = [],
+			n = args.node,
+			duration = args.duration || 1000,
+			scaleX = args.scaleX || 1.2,
+			scaleY = args.scaleY || .6,
+			ds = dojo.style,
+			oldPos = ds(n, "position"),
+			newPos = "absolute",
+			oldTop = ds(n, "top"),
+			combinedAnims = [],
+			bTime = 0,
+			round = Math.round,
+			jumpHeight = args.jumpHeight || 70
+		;
+		if(oldPos !== "absolute"){
+			newPos = "relative";
+		}
+		var a1 = dojo.animateProperty({
+			node: n,
+			duration: duration / 6,
+			properties: {
+				transform: { start: "scale(1, 1)", end: "scale(" + scaleX + ", " + scaleY + ")" }
+			}
+		});
+		dojo.connect(a1, "onBegin", function(){
+			ds(n, {
+				transformOrigin: "50% 100%",
+				position: newPos
+			});
+		});
+		anims.push(a1);
+		var a2 = dojo.animateProperty({
+			node: n,
+			duration: duration / 6,
+			properties: {
+				transform: { end: "scale(1, 1)", start: "scale(" + scaleX + ", " + scaleY + ")" }
+			}
+		});
+		combinedAnims.push(a2);
+		combinedAnims.push(new dojo.Animation(dojo.mixin({
+			curve: [],
+			duration: duration / 3,
+			delay: duration / 12,
+			onBegin: function(){
+				bTime = (new Date).getTime();
+			},
+			onAnimate: function(){
+				var cTime = (new Date).getTime();
+				ds(n, {
+					top: parseInt(ds(n, "top")) - round(jumpHeight*((cTime-bTime)/this.duration)) + "px"
+				});
+				bTime = cTime;
+			}
+		}, args)));
+		anims.push(dojo.fx.combine(combinedAnims));
+		anims.push(dojo.animateProperty(dojo.mixin({
+			duration: duration / 3,
+			onEnd: function(){
+				ds(n, {
+					position: oldPos
+				});
+			},
+			properties:{
+				top: oldTop
+			}
+		}, args)));
+		anims.push(a1);
+		anims.push(a2);
+
+		return dojo.fx.chain(anims);
+	}
+});
\ No newline at end of file
diff --git a/dojox/data/AndOrReadStore.js b/dojox/data/AndOrReadStore.js
old mode 100644
new mode 100755
index 0b357db..8dbe397
--- a/dojox/data/AndOrReadStore.js
+++ b/dojox/data/AndOrReadStore.js
@@ -1,671 +1,1043 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.AndOrReadStore"]){
-dojo._hasResource["dojox.data.AndOrReadStore"]=true;
 dojo.provide("dojox.data.AndOrReadStore");
+
 dojo.require("dojo.data.util.filter");
 dojo.require("dojo.data.util.simpleFetch");
 dojo.require("dojo.date.stamp");
-dojo.declare("dojox.data.AndOrReadStore",null,{constructor:function(_1){
-this._arrayOfAllItems=[];
-this._arrayOfTopLevelItems=[];
-this._loadFinished=false;
-this._jsonFileUrl=_1.url;
-this._ccUrl=_1.url;
-this.url=_1.url;
-this._jsonData=_1.data;
-this.data=null;
-this._datatypeMap=_1.typeMap||{};
-if(!this._datatypeMap["Date"]){
-this._datatypeMap["Date"]={type:Date,deserialize:function(_2){
-return dojo.date.stamp.fromISOString(_2);
-}};
-}
-this._features={"dojo.data.api.Read":true,"dojo.data.api.Identity":true};
-this._itemsByIdentity=null;
-this._storeRefPropName="_S";
-this._itemNumPropName="_0";
-this._rootItemPropName="_RI";
-this._reverseRefMap="_RRM";
-this._loadInProgress=false;
-this._queuedFetches=[];
-if(_1.urlPreventCache!==undefined){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-if(_1.hierarchical!==undefined){
-this.hierarchical=_1.hierarchical?true:false;
-}
-if(_1.clearOnClose){
-this.clearOnClose=true;
-}
-},url:"",_ccUrl:"",data:null,typeMap:null,clearOnClose:false,urlPreventCache:false,hierarchical:true,_assertIsItem:function(_3){
-if(!this.isItem(_3)){
-throw new Error("dojox.data.AndOrReadStore: Invalid item argument.");
-}
-},_assertIsAttribute:function(_4){
-if(typeof _4!=="string"){
-throw new Error("dojox.data.AndOrReadStore: Invalid attribute argument.");
-}
-},getValue:function(_5,_6,_7){
-var _8=this.getValues(_5,_6);
-return (_8.length>0)?_8[0]:_7;
-},getValues:function(_9,_a){
-this._assertIsItem(_9);
-this._assertIsAttribute(_a);
-return _9[_a]||[];
-},getAttributes:function(_b){
-this._assertIsItem(_b);
-var _c=[];
-for(var _d in _b){
-if((_d!==this._storeRefPropName)&&(_d!==this._itemNumPropName)&&(_d!==this._rootItemPropName)&&(_d!==this._reverseRefMap)){
-_c.push(_d);
-}
-}
-return _c;
-},hasAttribute:function(_e,_f){
-this._assertIsItem(_e);
-this._assertIsAttribute(_f);
-return (_f in _e);
-},containsValue:function(_10,_11,_12){
-var _13=undefined;
-if(typeof _12==="string"){
-_13=dojo.data.util.filter.patternToRegExp(_12,false);
-}
-return this._containsValue(_10,_11,_12,_13);
-},_containsValue:function(_14,_15,_16,_17){
-return dojo.some(this.getValues(_14,_15),function(_18){
-if(_18!==null&&!dojo.isObject(_18)&&_17){
-if(_18.toString().match(_17)){
-return true;
-}
-}else{
-if(_16===_18){
-return true;
-}
-}
-});
-},isItem:function(_19){
-if(_19&&_19[this._storeRefPropName]===this){
-if(this._arrayOfAllItems[_19[this._itemNumPropName]]===_19){
-return true;
-}
-}
-return false;
-},isItemLoaded:function(_1a){
-return this.isItem(_1a);
-},loadItem:function(_1b){
-this._assertIsItem(_1b.item);
-},getFeatures:function(){
-return this._features;
-},getLabel:function(_1c){
-if(this._labelAttr&&this.isItem(_1c)){
-return this.getValue(_1c,this._labelAttr);
-}
-return undefined;
-},getLabelAttributes:function(_1d){
-if(this._labelAttr){
-return [this._labelAttr];
-}
-return null;
-},_fetchItems:function(_1e,_1f,_20){
-var _21=this;
-var _22=function(_23,_24){
-var _25=[];
-if(_23.query){
-var _26=dojo.fromJson(dojo.toJson(_23.query));
-if(typeof _26=="object"){
-var _27=0;
-var p;
-for(p in _26){
-_27++;
-}
-if(_27>1&&_26.complexQuery){
-var cq=_26.complexQuery;
-var _28=false;
-for(p in _26){
-if(p!=="complexQuery"){
-if(!_28){
-cq="( "+cq+" )";
-_28=true;
-}
-var v=_23.query[p];
-if(dojo.isString(v)){
-v="'"+v+"'";
-}
-cq+=" AND "+p+":"+v;
-delete _26[p];
-}
-}
-_26.complexQuery=cq;
-}
-}
-var _29=_23.queryOptions?_23.queryOptions.ignoreCase:false;
-if(typeof _26!="string"){
-_26=dojo.toJson(_26);
-_26=_26.replace(/\\\\/g,"\\");
-}
-_26=_26.replace(/\\"/g,"\"");
-var _2a=dojo.trim(_26.replace(/{|}/g,""));
-var _2b,i;
-if(_2a.match(/"? *complexQuery *"?:/)){
-_2a=dojo.trim(_2a.replace(/"?\s*complexQuery\s*"?:/,""));
-var _2c=["'","\""];
-var _2d,_2e;
-var _2f=false;
-for(i=0;i<_2c.length;i++){
-_2d=_2a.indexOf(_2c[i]);
-_2b=_2a.indexOf(_2c[i],1);
-_2e=_2a.indexOf(":",1);
-if(_2d===0&&_2b!=-1&&_2e<_2b){
-_2f=true;
-break;
-}
-}
-if(_2f){
-_2a=_2a.replace(/^\"|^\'|\"$|\'$/g,"");
-}
-}
-var _30=_2a;
-var _31=/^,|^NOT |^AND |^OR |^\(|^\)|^!|^&&|^\|\|/i;
-var _32="";
-var op="";
-var val="";
-var pos=-1;
-var err=false;
-var key="";
-var _33="";
-var tok="";
-_2b=-1;
-for(i=0;i<_24.length;++i){
-var _34=true;
-var _35=_24[i];
-if(_35===null){
-_34=false;
-}else{
-_2a=_30;
-_32="";
-while(_2a.length>0&&!err){
-op=_2a.match(_31);
-while(op&&!err){
-_2a=dojo.trim(_2a.replace(op[0],""));
-op=dojo.trim(op[0]).toUpperCase();
-op=op=="NOT"?"!":op=="AND"||op==","?"&&":op=="OR"?"||":op;
-op=" "+op+" ";
-_32+=op;
-op=_2a.match(_31);
-}
-if(_2a.length>0){
-pos=_2a.indexOf(":");
-if(pos==-1){
-err=true;
-break;
-}else{
-key=dojo.trim(_2a.substring(0,pos).replace(/\"|\'/g,""));
-_2a=dojo.trim(_2a.substring(pos+1));
-tok=_2a.match(/^\'|^\"/);
-if(tok){
-tok=tok[0];
-pos=_2a.indexOf(tok);
-_2b=_2a.indexOf(tok,pos+1);
-if(_2b==-1){
-err=true;
-break;
-}
-_33=_2a.substring(pos+1,_2b);
-if(_2b==_2a.length-1){
-_2a="";
-}else{
-_2a=dojo.trim(_2a.substring(_2b+1));
-}
-_32+=_21._containsValue(_35,key,_33,dojo.data.util.filter.patternToRegExp(_33,_29));
-}else{
-tok=_2a.match(/\s|\)|,/);
-if(tok){
-var _36=new Array(tok.length);
-for(var j=0;j<tok.length;j++){
-_36[j]=_2a.indexOf(tok[j]);
-}
-pos=_36[0];
-if(_36.length>1){
-for(var j=1;j<_36.length;j++){
-pos=Math.min(pos,_36[j]);
-}
-}
-_33=dojo.trim(_2a.substring(0,pos));
-_2a=dojo.trim(_2a.substring(pos));
-}else{
-_33=dojo.trim(_2a);
-_2a="";
-}
-_32+=_21._containsValue(_35,key,_33,dojo.data.util.filter.patternToRegExp(_33,_29));
-}
-}
-}
-}
-_34=eval(_32);
-}
-if(_34){
-_25.push(_35);
-}
-}
-if(err){
-_25=[];
-}
-_1f(_25,_23);
-}else{
-for(var i=0;i<_24.length;++i){
-var _37=_24[i];
-if(_37!==null){
-_25.push(_37);
-}
-}
-_1f(_25,_23);
-}
-};
-if(this._loadFinished){
-_22(_1e,this._getItemsArray(_1e.queryOptions));
-}else{
-if(this._jsonFileUrl!==this._ccUrl){
-dojo.deprecated("dojox.data.AndOrReadStore: ","To change the url, set the url property of the store,"+" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
-this._ccUrl=this._jsonFileUrl;
-this.url=this._jsonFileUrl;
-}else{
-if(this.url!==this._ccUrl){
-this._jsonFileUrl=this.url;
-this._ccUrl=this.url;
-}
-}
-if(this.data!=null&&this._jsonData==null){
-this._jsonData=this.data;
-this.data=null;
-}
-if(this._jsonFileUrl){
-if(this._loadInProgress){
-this._queuedFetches.push({args:_1e,filter:_22});
-}else{
-this._loadInProgress=true;
-var _38={url:_21._jsonFileUrl,handleAs:"json-comment-optional",preventCache:this.urlPreventCache};
-var _39=dojo.xhrGet(_38);
-_39.addCallback(function(_3a){
-try{
-_21._getItemsFromLoadedData(_3a);
-_21._loadFinished=true;
-_21._loadInProgress=false;
-_22(_1e,_21._getItemsArray(_1e.queryOptions));
-_21._handleQueuedFetches();
-}
-catch(e){
-_21._loadFinished=true;
-_21._loadInProgress=false;
-_20(e,_1e);
-}
-});
-_39.addErrback(function(_3b){
-_21._loadInProgress=false;
-_20(_3b,_1e);
-});
-var _3c=null;
-if(_1e.abort){
-_3c=_1e.abort;
-}
-_1e.abort=function(){
-var df=_39;
-if(df&&df.fired===-1){
-df.cancel();
-df=null;
-}
-if(_3c){
-_3c.call(_1e);
-}
-};
-}
-}else{
-if(this._jsonData){
-try{
-this._loadFinished=true;
-this._getItemsFromLoadedData(this._jsonData);
-this._jsonData=null;
-_22(_1e,this._getItemsArray(_1e.queryOptions));
-}
-catch(e){
-_20(e,_1e);
-}
-}else{
-_20(new Error("dojox.data.AndOrReadStore: No JSON source data was provided as either URL or a nested Javascript object."),_1e);
-}
-}
-}
-},_handleQueuedFetches:function(){
-if(this._queuedFetches.length>0){
-for(var i=0;i<this._queuedFetches.length;i++){
-var _3d=this._queuedFetches[i];
-var _3e=_3d.args;
-var _3f=_3d.filter;
-if(_3f){
-_3f(_3e,this._getItemsArray(_3e.queryOptions));
-}else{
-this.fetchItemByIdentity(_3e);
-}
-}
-this._queuedFetches=[];
-}
-},_getItemsArray:function(_40){
-if(_40&&_40.deep){
-return this._arrayOfAllItems;
-}
-return this._arrayOfTopLevelItems;
-},close:function(_41){
-if(this.clearOnClose&&this._loadFinished&&!this._loadInProgress){
-if(((this._jsonFileUrl==""||this._jsonFileUrl==null)&&(this.url==""||this.url==null))&&this.data==null){
-}
-this._arrayOfAllItems=[];
-this._arrayOfTopLevelItems=[];
-this._loadFinished=false;
-this._itemsByIdentity=null;
-this._loadInProgress=false;
-this._queuedFetches=[];
-}
-},_getItemsFromLoadedData:function(_42){
-var _43=this;
-function _44(_45){
-var _46=((_45!==null)&&(typeof _45==="object")&&(!dojo.isArray(_45))&&(!dojo.isFunction(_45))&&(_45.constructor==Object)&&(typeof _45._reference==="undefined")&&(typeof _45._type==="undefined")&&(typeof _45._value==="undefined")&&_43.hierarchical);
-return _46;
-};
-function _47(_48){
-_43._arrayOfAllItems.push(_48);
-for(var _49 in _48){
-var _4a=_48[_49];
-if(_4a){
-if(dojo.isArray(_4a)){
-var _4b=_4a;
-for(var k=0;k<_4b.length;++k){
-var _4c=_4b[k];
-if(_44(_4c)){
-_47(_4c);
-}
-}
-}else{
-if(_44(_4a)){
-_47(_4a);
-}
-}
-}
-}
-};
-this._labelAttr=_42.label;
-var i;
-var _4d;
-this._arrayOfAllItems=[];
-this._arrayOfTopLevelItems=_42.items;
-for(i=0;i<this._arrayOfTopLevelItems.length;++i){
-_4d=this._arrayOfTopLevelItems[i];
-_47(_4d);
-_4d[this._rootItemPropName]=true;
-}
-var _4e={};
-var key;
-for(i=0;i<this._arrayOfAllItems.length;++i){
-_4d=this._arrayOfAllItems[i];
-for(key in _4d){
-if(key!==this._rootItemPropName){
-var _4f=_4d[key];
-if(_4f!==null){
-if(!dojo.isArray(_4f)){
-_4d[key]=[_4f];
-}
-}else{
-_4d[key]=[null];
-}
-}
-_4e[key]=key;
-}
-}
-while(_4e[this._storeRefPropName]){
-this._storeRefPropName+="_";
-}
-while(_4e[this._itemNumPropName]){
-this._itemNumPropName+="_";
-}
-while(_4e[this._reverseRefMap]){
-this._reverseRefMap+="_";
-}
-var _50;
-var _51=_42.identifier;
-if(_51){
-this._itemsByIdentity={};
-this._features["dojo.data.api.Identity"]=_51;
-for(i=0;i<this._arrayOfAllItems.length;++i){
-_4d=this._arrayOfAllItems[i];
-_50=_4d[_51];
-var _52=_50[0];
-if(!this._itemsByIdentity[_52]){
-this._itemsByIdentity[_52]=_4d;
-}else{
-if(this._jsonFileUrl){
-throw new Error("dojox.data.AndOrReadStore:  The json data as specified by: ["+this._jsonFileUrl+"] is malformed.  Items within the list have identifier: ["+_51+"].  Value collided: ["+_52+"]");
-}else{
-if(this._jsonData){
-throw new Error("dojox.data.AndOrReadStore:  The json data provided by the creation arguments is malformed.  Items within the list have identifier: ["+_51+"].  Value collided: ["+_52+"]");
-}
-}
-}
-}
-}else{
-this._features["dojo.data.api.Identity"]=Number;
-}
-for(i=0;i<this._arrayOfAllItems.length;++i){
-_4d=this._arrayOfAllItems[i];
-_4d[this._storeRefPropName]=this;
-_4d[this._itemNumPropName]=i;
-}
-for(i=0;i<this._arrayOfAllItems.length;++i){
-_4d=this._arrayOfAllItems[i];
-for(key in _4d){
-_50=_4d[key];
-for(var j=0;j<_50.length;++j){
-_4f=_50[j];
-if(_4f!==null&&typeof _4f=="object"){
-if(("_type" in _4f)&&("_value" in _4f)){
-var _53=_4f._type;
-var _54=this._datatypeMap[_53];
-if(!_54){
-throw new Error("dojox.data.AndOrReadStore: in the typeMap constructor arg, no object class was specified for the datatype '"+_53+"'");
-}else{
-if(dojo.isFunction(_54)){
-_50[j]=new _54(_4f._value);
-}else{
-if(dojo.isFunction(_54.deserialize)){
-_50[j]=_54.deserialize(_4f._value);
-}else{
-throw new Error("dojox.data.AndOrReadStore: Value provided in typeMap was neither a constructor, nor a an object with a deserialize function");
-}
-}
-}
-}
-if(_4f._reference){
-var _55=_4f._reference;
-if(!dojo.isObject(_55)){
-_50[j]=this._itemsByIdentity[_55];
-}else{
-for(var k=0;k<this._arrayOfAllItems.length;++k){
-var _56=this._arrayOfAllItems[k];
-var _57=true;
-for(var _58 in _55){
-if(_56[_58]!=_55[_58]){
-_57=false;
-}
-}
-if(_57){
-_50[j]=_56;
-}
-}
-}
-if(this.referenceIntegrity){
-var _59=_50[j];
-if(this.isItem(_59)){
-this._addReferenceToMap(_59,_4d,key);
-}
-}
-}else{
-if(this.isItem(_4f)){
-if(this.referenceIntegrity){
-this._addReferenceToMap(_4f,_4d,key);
-}
-}
-}
-}
-}
-}
-}
-},_addReferenceToMap:function(_5a,_5b,_5c){
-},getIdentity:function(_5d){
-var _5e=this._features["dojo.data.api.Identity"];
-if(_5e===Number){
-return _5d[this._itemNumPropName];
-}else{
-var _5f=_5d[_5e];
-if(_5f){
-return _5f[0];
-}
-}
-return null;
-},fetchItemByIdentity:function(_60){
-if(!this._loadFinished){
-var _61=this;
-if(this._jsonFileUrl!==this._ccUrl){
-dojo.deprecated("dojox.data.AndOrReadStore: ","To change the url, set the url property of the store,"+" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
-this._ccUrl=this._jsonFileUrl;
-this.url=this._jsonFileUrl;
-}else{
-if(this.url!==this._ccUrl){
-this._jsonFileUrl=this.url;
-this._ccUrl=this.url;
-}
-}
-if(this.data!=null&&this._jsonData==null){
-this._jsonData=this.data;
-this.data=null;
-}
-if(this._jsonFileUrl){
-if(this._loadInProgress){
-this._queuedFetches.push({args:_60});
-}else{
-this._loadInProgress=true;
-var _62={url:_61._jsonFileUrl,handleAs:"json-comment-optional",preventCache:this.urlPreventCache};
-var _63=dojo.xhrGet(_62);
-_63.addCallback(function(_64){
-var _65=_60.scope?_60.scope:dojo.global;
-try{
-_61._getItemsFromLoadedData(_64);
-_61._loadFinished=true;
-_61._loadInProgress=false;
-var _66=_61._getItemByIdentity(_60.identity);
-if(_60.onItem){
-_60.onItem.call(_65,_66);
-}
-_61._handleQueuedFetches();
-}
-catch(error){
-_61._loadInProgress=false;
-if(_60.onError){
-_60.onError.call(_65,error);
-}
-}
-});
-_63.addErrback(function(_67){
-_61._loadInProgress=false;
-if(_60.onError){
-var _68=_60.scope?_60.scope:dojo.global;
-_60.onError.call(_68,_67);
-}
-});
-}
-}else{
-if(this._jsonData){
-_61._getItemsFromLoadedData(_61._jsonData);
-_61._jsonData=null;
-_61._loadFinished=true;
-var _69=_61._getItemByIdentity(_60.identity);
-if(_60.onItem){
-var _6a=_60.scope?_60.scope:dojo.global;
-_60.onItem.call(_6a,_69);
-}
-}
-}
-}else{
-var _69=this._getItemByIdentity(_60.identity);
-if(_60.onItem){
-var _6a=_60.scope?_60.scope:dojo.global;
-_60.onItem.call(_6a,_69);
-}
-}
-},_getItemByIdentity:function(_6b){
-var _6c=null;
-if(this._itemsByIdentity){
-_6c=this._itemsByIdentity[_6b];
-}else{
-_6c=this._arrayOfAllItems[_6b];
-}
-if(_6c===undefined){
-_6c=null;
-}
-return _6c;
-},getIdentityAttributes:function(_6d){
-var _6e=this._features["dojo.data.api.Identity"];
-if(_6e===Number){
-return null;
-}else{
-return [_6e];
-}
-},_forceLoad:function(){
-var _6f=this;
-if(this._jsonFileUrl!==this._ccUrl){
-dojo.deprecated("dojox.data.AndOrReadStore: ","To change the url, set the url property of the store,"+" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
-this._ccUrl=this._jsonFileUrl;
-this.url=this._jsonFileUrl;
-}else{
-if(this.url!==this._ccUrl){
-this._jsonFileUrl=this.url;
-this._ccUrl=this.url;
-}
-}
-if(this.data!=null&&this._jsonData==null){
-this._jsonData=this.data;
-this.data=null;
-}
-if(this._jsonFileUrl){
-var _70={url:_6f._jsonFileUrl,handleAs:"json-comment-optional",preventCache:this.urlPreventCache,sync:true};
-var _71=dojo.xhrGet(_70);
-_71.addCallback(function(_72){
-try{
-if(_6f._loadInProgress!==true&&!_6f._loadFinished){
-_6f._getItemsFromLoadedData(_72);
-_6f._loadFinished=true;
-}else{
-if(_6f._loadInProgress){
-throw new Error("dojox.data.AndOrReadStore:  Unable to perform a synchronous load, an async load is in progress.");
-}
-}
-}
-catch(e){
-throw e;
-}
-});
-_71.addErrback(function(_73){
-throw _73;
+
+dojo.declare("dojox.data.AndOrReadStore", null,{
+	//	summary:
+	//		AndOrReadStore uses ItemFileReadStore as a base, modifying only the query (_fetchItems) section.
+	//		Supports queries of the form: query:"id:1* OR dept:'Sales Department' || (id:2* && NOT dept:S*)"
+	//		Includes legacy/widget support via:  
+	//			query:{complexQuery:"id:1* OR dept:'Sales Department' || (id:2* && NOT dept:S*)"}
+	//		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._ccUrl = keywordParameters.url;
+		this.url = keywordParameters.url;
+		this._jsonData = keywordParameters.data;
+		this.data = null;
+		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.hierarchical !== undefined){
+			this.hierarchical = keywordParameters.hierarchical?true:false;
+		}
+		if(keywordParameters.clearOnClose){
+			this.clearOnClose = true;
+		}
+	},
+	
+	url: "", // use "" rather than undefined for the benefit of the parser (#3539)
+
+	//Internal var, crossCheckUrl.  Used so that setting either url or _jsonFileUrl, can still trigger a reload
+	//when clearOnClose and close is used.
+	_ccUrl: "",
+
+	data: null, //Make this parser settable.
+
+	typeMap: null, //Make this parser settable.
+
+	//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,
+
+	//Parameter to indicate to process data from the url as hierarchical 
+	//(data items can contain other data items in js form).  Default is true 
+	//for backwards compatibility.  False means only root items are processed 
+	//as items, all child objects outside of type-mapped objects and those in 
+	//specific reference format, are left straight JS data objects.
+	hierarchical: true,
+
+	_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("dojox.data.AndOrReadStore: 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("dojox.data.AndOrReadStore: 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);
+		var arr = item[attribute] || [];
+		// Clone it before returning.  refs: #10474
+		return arr.slice(0, arr.length); // 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()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		return (attribute in item);
+	},
+
+	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()
+		//		filter modified to permit complex queries where
+		//			logical operators are case insensitive:  
+		//			, NOT AND OR ( ) ! && ||
+		//			Note:  "," included for quoted/string legacy queries. 
+		var self = this;
+		var filter = function(requestArgs, arrayOfItems){
+			var items = [];
+			if(requestArgs.query){
+				//Complete copy, we may have to mess with it.
+				//Safer than clone, which does a shallow copy, I believe.
+				var query = dojo.fromJson(dojo.toJson(requestArgs.query));
+				//Okay, object form query, we have to check to see if someone mixed query methods (such as using FilteringSelect
+				//with a complexQuery).  In that case, the params need to be anded to the complex query statement.
+				//See defect #7980
+				if(typeof query == "object" ){
+					var count = 0;
+					var p;
+					for(p in query){
+						count++;
+					}
+					if(count > 1 && query.complexQuery){
+						var cq = query.complexQuery;
+						var wrapped = false;
+						for(p in query){
+							if(p !== "complexQuery"){ 
+								//We should wrap this in () as it should and with the entire complex query
+								//Not just part of it.
+								if(!wrapped){
+									cq = "( " + cq + " )";
+									wrapped = true;
+								}
+								//Make sure strings are quoted when going into complexQuery merge.
+								var v = requestArgs.query[p];
+								if(dojo.isString(v)){
+									v = "'" + v + "'";
+								}
+								cq += " AND " + p + ":" + v;
+								delete query[p];
+								
+							}
+						}
+						query.complexQuery = cq;
+					}
+				}
+
+				var ignoreCase = requestArgs.queryOptions ? requestArgs.queryOptions.ignoreCase : false; 
+				//for complex queries only:  pattern = query[:|=]"NOT id:23* AND (type:'test*' OR dept:'bob') && !filed:true"
+				//logical operators are case insensitive:  , NOT AND OR ( ) ! && ||  // "," included for quoted/string legacy queries.
+				if(typeof query != "string"){
+					query = dojo.toJson(query);	
+					query = query.replace(/\\\\/g,"\\"); //counter toJson expansion of backslashes, e.g., foo\\*bar test.
+				}
+				query = query.replace(/\\"/g,"\"");   //ditto, for embedded \" in lieu of " availability.
+				var complexQuery = dojo.trim(query.replace(/{|}/g,"")); //we can handle these, too.
+				var pos2, i;
+				if(complexQuery.match(/"? *complexQuery *"?:/)){ //case where widget required a json object, so use complexQuery:'the real query'
+					complexQuery = dojo.trim(complexQuery.replace(/"?\s*complexQuery\s*"?:/,""));
+					var quotes = ["'",'"'];
+					var pos1,colon;
+					var flag = false;
+					for(i = 0; i<quotes.length; i++){
+						pos1 = complexQuery.indexOf(quotes[i]);
+						pos2 = complexQuery.indexOf(quotes[i],1);
+						colon = complexQuery.indexOf(":",1);
+						if(pos1 === 0 && pos2 != -1 && colon < pos2){
+							flag = true;
+							break;
+						} //first two sets of quotes don't occur before the first colon.	
+					}	
+					if(flag){	//dojo.toJson, and maybe user, adds surrounding quotes, which we need to remove.
+						complexQuery = complexQuery.replace(/^\"|^\'|\"$|\'$/g,"");
+					}
+				} //end query="{complexQuery:'id:1* || dept:Sales'}" parsing (for when widget required json object query).
+				var complexQuerySave = complexQuery;
+				//valid logical operators.
+				var begRegExp = /^,|^NOT |^AND |^OR |^\(|^\)|^!|^&&|^\|\|/i; //trailing space on some tokens on purpose.
+				var sQuery = ""; //will be eval'ed for each i-th candidateItem, based on query components.
+				var op = "";
+				var val = "";
+				var pos = -1;
+				var err = false;
+				var key = "";
+				var value = "";
+				var tok = "";
+				pos2 = -1;
+				for(i = 0; i < arrayOfItems.length; ++i){
+					var match = true;
+					var candidateItem = arrayOfItems[i];
+					if(candidateItem === null){
+						match = false;
+					}else{
+						//process entire string for this i-th candidateItem.
+						complexQuery = complexQuerySave; //restore query for next candidateItem.
+						sQuery = "";
+						//work left to right, finding either key:value pair or logical operator at the beginning of the complexQuery string.
+						//when found, concatenate to sQuery and remove from complexQuery and loop back.
+						while(complexQuery.length > 0 && !err){
+							op = complexQuery.match(begRegExp);
+							
+							//get/process/append one or two leading logical operators.
+							while(op && !err){ //look for leading logical operators.
+								complexQuery = dojo.trim(complexQuery.replace(op[0],""));
+								op = dojo.trim(op[0]).toUpperCase();
+								//convert some logical operators to their javascript equivalents for later eval.
+								op = op == "NOT" ? "!" : op == "AND" || op == "," ? "&&" : op == "OR" ? "||" : op; 
+								op = " " + op + " ";
+								sQuery += op;
+								op = complexQuery.match(begRegExp);
+							}//end op && !err
+							
+							//now get/process/append one key:value pair.
+							if(complexQuery.length > 0){
+								pos = complexQuery.indexOf(":");
+								if(pos == -1){
+									err = true;
+									break;
+								}else{
+									key = dojo.trim(complexQuery.substring(0,pos).replace(/\"|\'/g,""));
+									complexQuery = dojo.trim(complexQuery.substring(pos + 1));
+									tok = complexQuery.match(/^\'|^\"/);	//quoted?
+									if(tok){
+										tok = tok[0];
+										pos = complexQuery.indexOf(tok);
+										pos2 = complexQuery.indexOf(tok,pos + 1);
+										if(pos2 == -1){
+											err = true;
+											break;
+										}	
+										value = complexQuery.substring(pos + 1,pos2);
+										if(pos2 == complexQuery.length - 1){ //quote is last character
+											complexQuery = "";
+										}else{
+											complexQuery = dojo.trim(complexQuery.substring(pos2 + 1));
+										}
+										sQuery += self._containsValue(candidateItem, key, value, dojo.data.util.filter.patternToRegExp(value, ignoreCase));
+									}
+									else{ //not quoted, so a space, comma, or closing parens (or the end) will be the break.
+										tok = complexQuery.match(/\s|\)|,/);
+										if(tok){
+											var pos3 = new Array(tok.length);
+											for(var j = 0;j<tok.length;j++){ 
+												pos3[j] = complexQuery.indexOf(tok[j]);
+											}
+											pos = pos3[0];
+											if(pos3.length > 1){
+												for(var j=1;j<pos3.length;j++){
+													pos = Math.min(pos,pos3[j]);													
+												}
+											}
+											value = dojo.trim(complexQuery.substring(0,pos));
+											complexQuery = dojo.trim(complexQuery.substring(pos));
+										}else{ //not a space, so must be at the end of the complexQuery.
+											value = dojo.trim(complexQuery);
+											complexQuery = "";
+										} //end  inner if(tok) else
+										sQuery += self._containsValue(candidateItem, key, value, dojo.data.util.filter.patternToRegExp(value, ignoreCase));
+									} //end outer if(tok) else
+								} //end found ":"
+							} //end if(complexQuery.length > 0)
+						} //end while complexQuery.length > 0 && !err, so finished the i-th item.
+						match = eval(sQuery);
+					} //end else is non-null candidateItem.
+					if(match){
+						items.push(candidateItem);
+					}
+				} //end for/next of all items.
+				if(err){
+					//soft fail.
+					items = [];
+					console.log("The store's _fetchItems failed, probably due to a syntax error in query.");
+				}
+				findCallback(items, requestArgs);
+			}else{
+				// No query...
+				// 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(var i = 0; i < arrayOfItems.length; ++i){
+					var item = arrayOfItems[i];
+					if(item !== null){
+						items.push(item);
+					}
+				}
+				findCallback(items, requestArgs);
+			} //end if there is a query.
+		}; //end filter function
+
+		if(this._loadFinished){
+			filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));
+		}else{
+			if(this._jsonFileUrl !== this._ccUrl){
+				dojo.deprecated("dojox.data.AndOrReadStore: ", 
+								"To change the url, set the url property of the store," +
+								" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
+				this._ccUrl = this._jsonFileUrl;
+				this.url = this._jsonFileUrl;
+			}else if(this.url !== this._ccUrl){
+				this._jsonFileUrl = this.url;
+				this._ccUrl = this.url;
+			}
+			//See if there was any forced reset of data.
+			if(this.data != null && this._jsonData == null){
+				this._jsonData = this.data;
+				this.data = null;
+			}
+			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("dojox.data.AndOrReadStore: No JSON source data was provided as either URL or a nested Javascript object."), keywordArgs);
+			}
+		} //end deferred fetching.
+	}, //end _fetchItems
+
+	_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._loadFinished &&
+			!this._loadInProgress){
+			 //Reset all internalsback to default state.  This will force a reload
+			 //on next fetch.  This also checks that the data or url param was set 
+			 //so that the store knows it can get data.  Without one of those being set,
+			 //the next fetch will trigger an error.
+
+			 if(((this._jsonFileUrl == "" || this._jsonFileUrl == null) && 
+				 (this.url == "" || this.url == null)
+				) && this.data == null){
+				 console.debug("dojox.data.AndOrReadStore: WARNING!  Data reload " +
+					" information has not been provided." + 
+					"  Please set 'url' or 'data' to the appropriate value before" +
+					" the next fetch");
+			 }
+			 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 self = this;
+		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)) &&
+				(!dojo.isFunction(aValue)) &&
+				(aValue.constructor == Object) &&
+				(typeof aValue._reference === "undefined") && 
+				(typeof aValue._type === "undefined") && 
+				(typeof aValue._value === "undefined") &&
+				self.hierarchical
+			);
+			return isItem;
+		}
+		
+		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];
+			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("dojox.data.AndOrReadStore:  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("dojox.data.AndOrReadStore:  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(("_type" in value) && ("_value" in 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("dojox.data.AndOrReadStore: 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("dojox.data.AndOrReadStore: 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._getItemByIdentity(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.
+		if(!this._loadFinished){
+			var self = this;
+			if(this._jsonFileUrl !== this._ccUrl){
+				dojo.deprecated("dojox.data.AndOrReadStore: ", 
+								"To change the url, set the url property of the store," +
+								" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
+				this._ccUrl = this._jsonFileUrl;
+				this.url = this._jsonFileUrl;
+			}else if(this.url !== this._ccUrl){
+				this._jsonFileUrl = this.url;
+				this._ccUrl = this.url;
+			}
+			//See if there was any forced reset of data.
+			if(this.data != null && this._jsonData == null){
+				this._jsonData = this.data;
+				this.data = null;
+			}
+			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;
+							var 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;
+				var item = self._getItemByIdentity(keywordArgs.identity);
+				if(keywordArgs.onItem){
+					var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+					keywordArgs.onItem.call(scope, item);
+				}
+			} 
+		}else{
+			// Already loaded.  We can just look it up and call back.
+			var item = this._getItemByIdentity(keywordArgs.identity);
+			if(keywordArgs.onItem){
+				var 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 !== this._ccUrl){
+			dojo.deprecated("dojox.data.AndOrReadStore: ", 
+							"To change the url, set the url property of the store," +
+							" not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
+			this._ccUrl = this._jsonFileUrl;
+			this.url = this._jsonFileUrl;
+		}else if(this.url !== this._ccUrl){
+			this._jsonFileUrl = this.url;
+			this._ccUrl = this.url;
+		}
+		//See if there was any forced reset of data.
+		if(this.data != null && this._jsonData == null){
+			this._jsonData = this.data;
+			this.data = null;
+		}
+		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("dojox.data.AndOrReadStore:  Unable to perform a synchronous load, an async load is in progress."); 
+					}
+				}catch(e){
+					console.log(e);
+					throw e;
+				}
+			});
+			getHandler.addErrback(function(error){
+				throw error;
+			});
+		}else if(this._jsonData){
+			self._getItemsFromLoadedData(self._jsonData);
+			self._jsonData = null;
+			self._loadFinished = true;
+		} 
+	}
 });
-}else{
-if(this._jsonData){
-_6f._getItemsFromLoadedData(_6f._jsonData);
-_6f._jsonData=null;
-_6f._loadFinished=true;
-}
-}
-}});
+//Mix in the simple fetch implementation to this class.
 dojo.extend(dojox.data.AndOrReadStore,dojo.data.util.simpleFetch);
-}
+
+
diff --git a/dojox/data/AndOrWriteStore.js b/dojox/data/AndOrWriteStore.js
old mode 100644
new mode 100755
index 3115746..195762d
--- a/dojox/data/AndOrWriteStore.js
+++ b/dojox/data/AndOrWriteStore.js
@@ -1,511 +1,807 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.AndOrWriteStore"]){
-dojo._hasResource["dojox.data.AndOrWriteStore"]=true;
 dojo.provide("dojox.data.AndOrWriteStore");
 dojo.require("dojox.data.AndOrReadStore");
-dojo.declare("dojox.data.AndOrWriteStore",dojox.data.AndOrReadStore,{constructor:function(_1){
-this._features["dojo.data.api.Write"]=true;
-this._features["dojo.data.api.Notification"]=true;
-this._pending={_newItems:{},_modifiedItems:{},_deletedItems:{}};
-if(!this._datatypeMap["Date"].serialize){
-this._datatypeMap["Date"].serialize=function(_2){
-return dojo.date.stamp.toISOString(_2,{zulu:true});
-};
-}
-if(_1&&(_1.referenceIntegrity===false)){
-this.referenceIntegrity=false;
-}
-this._saveInProgress=false;
-},referenceIntegrity:true,_assert:function(_3){
-if(!_3){
-throw new Error("assertion failed in ItemFileWriteStore");
-}
-},_getIdentifierAttribute:function(){
-var _4=this.getFeatures()["dojo.data.api.Identity"];
-return _4;
-},newItem:function(_5,_6){
-this._assert(!this._saveInProgress);
-if(!this._loadFinished){
-this._forceLoad();
-}
-if(typeof _5!="object"&&typeof _5!="undefined"){
-throw new Error("newItem() was passed something other than an object");
-}
-var _7=null;
-var _8=this._getIdentifierAttribute();
-if(_8===Number){
-_7=this._arrayOfAllItems.length;
-}else{
-_7=_5[_8];
-if(typeof _7==="undefined"){
-throw new Error("newItem() was not passed an identity for the new item");
-}
-if(dojo.isArray(_7)){
-throw new Error("newItem() was not passed an single-valued identity");
-}
-}
-if(this._itemsByIdentity){
-this._assert(typeof this._itemsByIdentity[_7]==="undefined");
-}
-this._assert(typeof this._pending._newItems[_7]==="undefined");
-this._assert(typeof this._pending._deletedItems[_7]==="undefined");
-var _9={};
-_9[this._storeRefPropName]=this;
-_9[this._itemNumPropName]=this._arrayOfAllItems.length;
-if(this._itemsByIdentity){
-this._itemsByIdentity[_7]=_9;
-_9[_8]=[_7];
-}
-this._arrayOfAllItems.push(_9);
-var _a=null;
-if(_6&&_6.parent&&_6.attribute){
-_a={item:_6.parent,attribute:_6.attribute,oldValue:undefined};
-var _b=this.getValues(_6.parent,_6.attribute);
-if(_b&&_b.length>0){
-var _c=_b.slice(0,_b.length);
-if(_b.length===1){
-_a.oldValue=_b[0];
-}else{
-_a.oldValue=_b.slice(0,_b.length);
-}
-_c.push(_9);
-this._setValueOrValues(_6.parent,_6.attribute,_c,false);
-_a.newValue=this.getValues(_6.parent,_6.attribute);
-}else{
-this._setValueOrValues(_6.parent,_6.attribute,_9,false);
-_a.newValue=_9;
-}
-}else{
-_9[this._rootItemPropName]=true;
-this._arrayOfTopLevelItems.push(_9);
-}
-this._pending._newItems[_7]=_9;
-for(var _d in _5){
-if(_d===this._storeRefPropName||_d===this._itemNumPropName){
-throw new Error("encountered bug in ItemFileWriteStore.newItem");
-}
-var _e=_5[_d];
-if(!dojo.isArray(_e)){
-_e=[_e];
-}
-_9[_d]=_e;
-if(this.referenceIntegrity){
-for(var i=0;i<_e.length;i++){
-var _f=_e[i];
-if(this.isItem(_f)){
-this._addReferenceToMap(_f,_9,_d);
-}
-}
-}
-}
-this.onNew(_9,_a);
-return _9;
-},_removeArrayElement:function(_10,_11){
-var _12=dojo.indexOf(_10,_11);
-if(_12!=-1){
-_10.splice(_12,1);
-return true;
-}
-return false;
-},deleteItem:function(_13){
-this._assert(!this._saveInProgress);
-this._assertIsItem(_13);
-var _14=_13[this._itemNumPropName];
-var _15=this.getIdentity(_13);
-if(this.referenceIntegrity){
-var _16=this.getAttributes(_13);
-if(_13[this._reverseRefMap]){
-_13["backup_"+this._reverseRefMap]=dojo.clone(_13[this._reverseRefMap]);
-}
-dojo.forEach(_16,function(_17){
-dojo.forEach(this.getValues(_13,_17),function(_18){
-if(this.isItem(_18)){
-if(!_13["backupRefs_"+this._reverseRefMap]){
-_13["backupRefs_"+this._reverseRefMap]=[];
-}
-_13["backupRefs_"+this._reverseRefMap].push({id:this.getIdentity(_18),attr:_17});
-this._removeReferenceFromMap(_18,_13,_17);
-}
-},this);
-},this);
-var _19=_13[this._reverseRefMap];
-if(_19){
-for(var _1a in _19){
-var _1b=null;
-if(this._itemsByIdentity){
-_1b=this._itemsByIdentity[_1a];
-}else{
-_1b=this._arrayOfAllItems[_1a];
-}
-if(_1b){
-for(var _1c in _19[_1a]){
-var _1d=this.getValues(_1b,_1c)||[];
-var _1e=dojo.filter(_1d,function(_1f){
-return !(this.isItem(_1f)&&this.getIdentity(_1f)==_15);
-},this);
-this._removeReferenceFromMap(_13,_1b,_1c);
-if(_1e.length<_1d.length){
-this._setValueOrValues(_1b,_1c,_1e);
-}
-}
-}
-}
-}
-}
-this._arrayOfAllItems[_14]=null;
-_13[this._storeRefPropName]=null;
-if(this._itemsByIdentity){
-delete this._itemsByIdentity[_15];
-}
-this._pending._deletedItems[_15]=_13;
-if(_13[this._rootItemPropName]){
-this._removeArrayElement(this._arrayOfTopLevelItems,_13);
-}
-this.onDelete(_13);
-return true;
-},setValue:function(_20,_21,_22){
-return this._setValueOrValues(_20,_21,_22,true);
-},setValues:function(_23,_24,_25){
-return this._setValueOrValues(_23,_24,_25,true);
-},unsetAttribute:function(_26,_27){
-return this._setValueOrValues(_26,_27,[],true);
-},_setValueOrValues:function(_28,_29,_2a,_2b){
-this._assert(!this._saveInProgress);
-this._assertIsItem(_28);
-this._assert(dojo.isString(_29));
-this._assert(typeof _2a!=="undefined");
-var _2c=this._getIdentifierAttribute();
-if(_29==_2c){
-throw new Error("ItemFileWriteStore does not have support for changing the value of an item's identifier.");
-}
-var _2d=this._getValueOrValues(_28,_29);
-var _2e=this.getIdentity(_28);
-if(!this._pending._modifiedItems[_2e]){
-var _2f={};
-for(var key in _28){
-if((key===this._storeRefPropName)||(key===this._itemNumPropName)||(key===this._rootItemPropName)){
-_2f[key]=_28[key];
-}else{
-if(key===this._reverseRefMap){
-_2f[key]=dojo.clone(_28[key]);
-}else{
-_2f[key]=_28[key].slice(0,_28[key].length);
-}
-}
-}
-this._pending._modifiedItems[_2e]=_2f;
-}
-var _30=false;
-if(dojo.isArray(_2a)&&_2a.length===0){
-_30=delete _28[_29];
-_2a=undefined;
-if(this.referenceIntegrity&&_2d){
-var _31=_2d;
-if(!dojo.isArray(_31)){
-_31=[_31];
-}
-for(var i=0;i<_31.length;i++){
-var _32=_31[i];
-if(this.isItem(_32)){
-this._removeReferenceFromMap(_32,_28,_29);
-}
-}
-}
-}else{
-var _33;
-if(dojo.isArray(_2a)){
-var _34=_2a;
-_33=_2a.slice(0,_2a.length);
-}else{
-_33=[_2a];
-}
-if(this.referenceIntegrity){
-if(_2d){
-var _31=_2d;
-if(!dojo.isArray(_31)){
-_31=[_31];
-}
-var map={};
-dojo.forEach(_31,function(_35){
-if(this.isItem(_35)){
-var id=this.getIdentity(_35);
-map[id.toString()]=true;
-}
-},this);
-dojo.forEach(_33,function(_36){
-if(this.isItem(_36)){
-var id=this.getIdentity(_36);
-if(map[id.toString()]){
-delete map[id.toString()];
-}else{
-this._addReferenceToMap(_36,_28,_29);
-}
-}
-},this);
-for(var rId in map){
-var _37;
-if(this._itemsByIdentity){
-_37=this._itemsByIdentity[rId];
-}else{
-_37=this._arrayOfAllItems[rId];
-}
-this._removeReferenceFromMap(_37,_28,_29);
-}
-}else{
-for(var i=0;i<_33.length;i++){
-var _32=_33[i];
-if(this.isItem(_32)){
-this._addReferenceToMap(_32,_28,_29);
-}
-}
-}
-}
-_28[_29]=_33;
-_30=true;
-}
-if(_2b){
-this.onSet(_28,_29,_2d,_2a);
-}
-return _30;
-},_addReferenceToMap:function(_38,_39,_3a){
-var _3b=this.getIdentity(_39);
-var _3c=_38[this._reverseRefMap];
-if(!_3c){
-_3c=_38[this._reverseRefMap]={};
-}
-var _3d=_3c[_3b];
-if(!_3d){
-_3d=_3c[_3b]={};
-}
-_3d[_3a]=true;
-},_removeReferenceFromMap:function(_3e,_3f,_40){
-var _41=this.getIdentity(_3f);
-var _42=_3e[this._reverseRefMap];
-var _43;
-if(_42){
-for(_43 in _42){
-if(_43==_41){
-delete _42[_43][_40];
-if(this._isEmpty(_42[_43])){
-delete _42[_43];
-}
-}
-}
-if(this._isEmpty(_42)){
-delete _3e[this._reverseRefMap];
-}
-}
-},_dumpReferenceMap:function(){
-var i;
-for(i=0;i<this._arrayOfAllItems.length;i++){
-var _44=this._arrayOfAllItems[i];
-if(_44&&_44[this._reverseRefMap]){
-}
-}
-},_getValueOrValues:function(_45,_46){
-var _47=undefined;
-if(this.hasAttribute(_45,_46)){
-var _48=this.getValues(_45,_46);
-if(_48.length==1){
-_47=_48[0];
-}else{
-_47=_48;
-}
-}
-return _47;
-},_flatten:function(_49){
-if(this.isItem(_49)){
-var _4a=_49;
-var _4b=this.getIdentity(_4a);
-var _4c={_reference:_4b};
-return _4c;
-}else{
-if(typeof _49==="object"){
-for(var _4d in this._datatypeMap){
-var _4e=this._datatypeMap[_4d];
-if(dojo.isObject(_4e)&&!dojo.isFunction(_4e)){
-if(_49 instanceof _4e.type){
-if(!_4e.serialize){
-throw new Error("ItemFileWriteStore:  No serializer defined for type mapping: ["+_4d+"]");
-}
-return {_type:_4d,_value:_4e.serialize(_49)};
-}
-}else{
-if(_49 instanceof _4e){
-return {_type:_4d,_value:_49.toString()};
-}
-}
-}
-}
-return _49;
-}
-},_getNewFileContentString:function(){
-var _4f={};
-var _50=this._getIdentifierAttribute();
-if(_50!==Number){
-_4f.identifier=_50;
-}
-if(this._labelAttr){
-_4f.label=this._labelAttr;
-}
-_4f.items=[];
-for(var i=0;i<this._arrayOfAllItems.length;++i){
-var _51=this._arrayOfAllItems[i];
-if(_51!==null){
-var _52={};
-for(var key in _51){
-if(key!==this._storeRefPropName&&key!==this._itemNumPropName&&key!==this._reverseRefMap&&key!==this._rootItemPropName){
-var _53=key;
-var _54=this.getValues(_51,_53);
-if(_54.length==1){
-_52[_53]=this._flatten(_54[0]);
-}else{
-var _55=[];
-for(var j=0;j<_54.length;++j){
-_55.push(this._flatten(_54[j]));
-_52[_53]=_55;
-}
-}
-}
-}
-_4f.items.push(_52);
-}
-}
-var _56=true;
-return dojo.toJson(_4f,_56);
-},_isEmpty:function(_57){
-var _58=true;
-if(dojo.isObject(_57)){
-var i;
-for(i in _57){
-_58=false;
-break;
-}
-}else{
-if(dojo.isArray(_57)){
-if(_57.length>0){
-_58=false;
-}
-}
-}
-return _58;
-},save:function(_59){
-this._assert(!this._saveInProgress);
-this._saveInProgress=true;
-var _5a=this;
-var _5b=function(){
-_5a._pending={_newItems:{},_modifiedItems:{},_deletedItems:{}};
-_5a._saveInProgress=false;
-if(_59&&_59.onComplete){
-var _5c=_59.scope||dojo.global;
-_59.onComplete.call(_5c);
-}
-};
-var _5d=function(){
-_5a._saveInProgress=false;
-if(_59&&_59.onError){
-var _5e=_59.scope||dojo.global;
-_59.onError.call(_5e);
-}
-};
-if(this._saveEverything){
-var _5f=this._getNewFileContentString();
-this._saveEverything(_5b,_5d,_5f);
-}
-if(this._saveCustom){
-this._saveCustom(_5b,_5d);
-}
-if(!this._saveEverything&&!this._saveCustom){
-_5b();
-}
-},revert:function(){
-this._assert(!this._saveInProgress);
-var _60;
-for(_60 in this._pending._modifiedItems){
-var _61=this._pending._modifiedItems[_60];
-var _62=null;
-if(this._itemsByIdentity){
-_62=this._itemsByIdentity[_60];
-}else{
-_62=this._arrayOfAllItems[_60];
-}
-_61[this._storeRefPropName]=this;
-for(key in _62){
-delete _62[key];
-}
-dojo.mixin(_62,_61);
-}
-var _63;
-for(_60 in this._pending._deletedItems){
-_63=this._pending._deletedItems[_60];
-_63[this._storeRefPropName]=this;
-var _64=_63[this._itemNumPropName];
-if(_63["backup_"+this._reverseRefMap]){
-_63[this._reverseRefMap]=_63["backup_"+this._reverseRefMap];
-delete _63["backup_"+this._reverseRefMap];
-}
-this._arrayOfAllItems[_64]=_63;
-if(this._itemsByIdentity){
-this._itemsByIdentity[_60]=_63;
-}
-if(_63[this._rootItemPropName]){
-this._arrayOfTopLevelItems.push(_63);
-}
-}
-for(_60 in this._pending._deletedItems){
-_63=this._pending._deletedItems[_60];
-if(_63["backupRefs_"+this._reverseRefMap]){
-dojo.forEach(_63["backupRefs_"+this._reverseRefMap],function(_65){
-var _66;
-if(this._itemsByIdentity){
-_66=this._itemsByIdentity[_65.id];
-}else{
-_66=this._arrayOfAllItems[_65.id];
-}
-this._addReferenceToMap(_66,_63,_65.attr);
-},this);
-delete _63["backupRefs_"+this._reverseRefMap];
-}
-}
-for(_60 in this._pending._newItems){
-var _67=this._pending._newItems[_60];
-_67[this._storeRefPropName]=null;
-this._arrayOfAllItems[_67[this._itemNumPropName]]=null;
-if(_67[this._rootItemPropName]){
-this._removeArrayElement(this._arrayOfTopLevelItems,_67);
-}
-if(this._itemsByIdentity){
-delete this._itemsByIdentity[_60];
-}
-}
-this._pending={_newItems:{},_modifiedItems:{},_deletedItems:{}};
-return true;
-},isDirty:function(_68){
-if(_68){
-var _69=this.getIdentity(_68);
-return new Boolean(this._pending._newItems[_69]||this._pending._modifiedItems[_69]||this._pending._deletedItems[_69]).valueOf();
-}else{
-if(!this._isEmpty(this._pending._newItems)||!this._isEmpty(this._pending._modifiedItems)||!this._isEmpty(this._pending._deletedItems)){
-return true;
-}
-return false;
-}
-},onSet:function(_6a,_6b,_6c,_6d){
-},onNew:function(_6e,_6f){
-},onDelete:function(_70){
-},close:function(_71){
-if(this.clearOnClose){
-if(!this.isDirty()){
-this.inherited(arguments);
-}else{
-throw new Error("dojox.data.AndOrWriteStore: There are unsaved changes present in the store.  Please save or revert the changes before invoking close.");
-}
-}
-}});
-}
+
+dojo.declare("dojox.data.AndOrWriteStore", dojox.data.AndOrReadStore, {
+	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.
+		//		}
+
+		// AndOrWriteStore duplicates ItemFileWriteStore, except extends AndOrReadStore, which offers complex queries.
+		// 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);
+							}
+						}
+					}
+				}
+			}
+		}
+
+		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]){
+				console.log("Item: [" + this.getIdentity(item) + "] is referenced by: " + dojo.toJson(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(){
+			self._saveInProgress = false;
+			if(keywordArgs && keywordArgs.onError){
+				var scope = keywordArgs.scope || dojo.global;
+				keywordArgs.onError.call(scope);
+			}
+		};
+		
+		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 copyOfItemState = this._pending._modifiedItems[identity];
+			var modifiedItem = null;
+			if(this._itemsByIdentity){
+				modifiedItem = this._itemsByIdentity[identity];
+			}else{
+				modifiedItem = this._arrayOfAllItems[identity];
+			}
+	
+			// Restore the original item into a full-fledged item again, we want to try to 
+			// keep the same object instance as if we don't it, causes bugs like #9022.
+			copyOfItemState[this._storeRefPropName] = this;
+			for(key in modifiedItem){
+				delete modifiedItem[key];
+			}
+			dojo.mixin(modifiedItem, copyOfItemState);
+		}
+		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{
+				//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("dojox.data.AndOrWriteStore: There are unsaved changes present in the store.  Please save or revert the changes before invoking close.");
+			}
+		}
+	}
+});
diff --git a/dojox/data/AppStore.js b/dojox/data/AppStore.js
index b65a12e..0dfd0e0 100644
--- a/dojox/data/AppStore.js
+++ b/dojox/data/AppStore.js
@@ -1,550 +1,829 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.AppStore"]){
-dojo._hasResource["dojox.data.AppStore"]=true;
 dojo.provide("dojox.data.AppStore");
+
 dojo.require("dojox.atom.io.Connection");
 dojo.require("dojo.data.util.simpleFetch");
 dojo.require("dojo.data.util.filter");
+
 dojo.experimental("dojox.data.AppStore");
-dojo.declare("dojox.data.AppStore",null,{url:"",urlPreventCache:false,xmethod:false,_atomIO:null,_feed:null,_requests:null,_processing:null,_updates:null,_adds:null,_deletes:null,constructor:function(_1){
-if(_1&&_1.url){
-this.url=_1.url;
-}
-if(_1&&_1.urlPreventCache){
-this.urlPreventCache=_1.urlPreventCache;
-}
-if(!this.url){
-throw new Error("A URL is required to instantiate an APP Store object");
-}
-},_setFeed:function(_2,_3){
-this._feed=_2;
-var i;
-for(i=0;i<this._feed.entries.length;i++){
-this._feed.entries[i].store=this;
-}
-if(this._requests){
-for(i=0;i<this._requests.length;i++){
-var _4=this._requests[i];
-if(_4.request&&_4.fh&&_4.eh){
-this._finishFetchItems(_4.request,_4.fh,_4.eh);
-}else{
-if(_4.clear){
-this._feed=null;
-}else{
-if(_4.add){
-this._feed.addEntry(_4.add);
-}else{
-if(_4.remove){
-this._feed.removeEntry(_4.remove);
-}
-}
-}
-}
-}
-}
-this._requests=null;
-},_getAllItems:function(){
-var _5=[];
-for(var i=0;i<this._feed.entries.length;i++){
-_5.push(this._feed.entries[i]);
-}
-return _5;
-},_assertIsItem:function(_6){
-if(!this.isItem(_6)){
-throw new Error("This error message is provided when a function is called in the following form: "+"getAttribute(argument, attributeName).  The argument variable represents the member "+"or owner of the object. The error is created when an item that does not belong "+"to this store is specified as an argument.");
-}
-},_assertIsAttribute:function(_7){
-if(typeof _7!=="string"){
-throw new Error("The attribute argument must be a string. The error is created "+"when a different type of variable is specified such as an array or object.");
-}
-for(var _8 in dojox.atom.io.model._actions){
-if(_8==_7){
-return true;
-}
-}
-return false;
-},_addUpdate:function(_9){
-if(!this._updates){
-this._updates=[_9];
-}else{
-this._updates.push(_9);
-}
-},getValue:function(_a,_b,_c){
-var _d=this.getValues(_a,_b);
-return (_d.length>0)?_d[0]:_c;
-},getValues:function(_e,_f){
-this._assertIsItem(_e);
-var _10=this._assertIsAttribute(_f);
-if(_10){
-if((_f==="author"||_f==="contributor"||_f==="link")&&_e[_f+"s"]){
-return _e[_f+"s"];
-}
-if(_f==="category"&&_e.categories){
-return _e.categories;
-}
-if(_e[_f]){
-_e=_e[_f];
-if(_e.declaredClass=="dojox.atom.io.model.Content"){
-return [_e.value];
-}
-return [_e];
-}
-}
-return [];
-},getAttributes:function(_11){
-this._assertIsItem(_11);
-var _12=[];
-for(var key in dojox.atom.io.model._actions){
-if(this.hasAttribute(_11,key)){
-_12.push(key);
-}
-}
-return _12;
-},hasAttribute:function(_13,_14){
-return this.getValues(_13,_14).length>0;
-},containsValue:function(_15,_16,_17){
-var _18=undefined;
-if(typeof _17==="string"){
-_18=dojo.data.util.filter.patternToRegExp(_17,false);
-}
-return this._containsValue(_15,_16,_17,_18);
-},_containsValue:function(_19,_1a,_1b,_1c,_1d){
-var _1e=this.getValues(_19,_1a);
-for(var i=0;i<_1e.length;++i){
-var _1f=_1e[i];
-if(typeof _1f==="string"&&_1c){
-if(_1d){
-_1f=_1f.replace(new RegExp(/^\s+/),"");
-_1f=_1f.replace(new RegExp(/\s+$/),"");
-}
-_1f=_1f.replace(/\r|\n|\r\n/g,"");
-return (_1f.match(_1c)!==null);
-}else{
-if(_1b===_1f){
-return true;
-}
-}
-}
-return false;
-},isItem:function(_20){
-return _20&&_20.store&&_20.store===this;
-},isItemLoaded:function(_21){
-return this.isItem(_21);
-},loadItem:function(_22){
-this._assertIsItem(_22.item);
-},_fetchItems:function(_23,_24,_25){
-if(this._feed){
-this._finishFetchItems(_23,_24,_25);
-}else{
-var _26=false;
-if(!this._requests){
-this._requests=[];
-_26=true;
-}
-this._requests.push({request:_23,fh:_24,eh:_25});
-if(_26){
-this._atomIO=new dojox.atom.io.Connection(false,this.urlPreventCache);
-this._atomIO.getFeed(this.url,this._setFeed,null,this);
-}
-}
-},_finishFetchItems:function(_27,_28,_29){
-var _2a=null;
-var _2b=this._getAllItems();
-if(_27.query){
-var _2c=_27.queryOptions?_27.queryOptions.ignoreCase:false;
-_2a=[];
-var _2d={};
-var key;
-var _2e;
-for(key in _27.query){
-_2e=_27.query[key]+"";
-if(typeof _2e==="string"){
-_2d[key]=dojo.data.util.filter.patternToRegExp(_2e,_2c);
-}
-}
-for(var i=0;i<_2b.length;++i){
-var _2f=true;
-var _30=_2b[i];
-for(key in _27.query){
-_2e=_27.query[key]+"";
-if(!this._containsValue(_30,key,_2e,_2d[key],_27.trim)){
-_2f=false;
-}
-}
-if(_2f){
-_2a.push(_30);
-}
-}
-}else{
-if(_2b.length>0){
-_2a=_2b.slice(0,_2b.length);
-}
-}
-try{
-_28(_2a,_27);
-}
-catch(e){
-_29(e,_27);
-}
-},getFeatures:function(){
-return {"dojo.data.api.Read":true,"dojo.data.api.Write":true,"dojo.data.api.Identity":true};
-},close:function(_31){
-this._feed=null;
-},getLabel:function(_32){
-if(this.isItem(_32)){
-return this.getValue(_32,"title","No Title");
-}
-return undefined;
-},getLabelAttributes:function(_33){
-return ["title"];
-},getIdentity:function(_34){
-this._assertIsItem(_34);
-return this.getValue(_34,"id");
-},getIdentityAttributes:function(_35){
-return ["id"];
-},fetchItemByIdentity:function(_36){
-this._fetchItems({query:{id:_36.identity},onItem:_36.onItem,scope:_36.scope},function(_37,_38){
-var _39=_38.scope;
-if(!_39){
-_39=dojo.global;
-}
-if(_37.length<1){
-_38.onItem.call(_39,null);
-}else{
-_38.onItem.call(_39,_37[0]);
-}
-},_36.onError);
-},newItem:function(_3a){
-var _3b=new dojox.atom.io.model.Entry();
-var _3c=null;
-var _3d=null;
-var i;
-for(var key in _3a){
-if(this._assertIsAttribute(key)){
-_3c=_3a[key];
-switch(key){
-case "link":
-for(i in _3c){
-_3d=_3c[i];
-_3b.addLink(_3d.href,_3d.rel,_3d.hrefLang,_3d.title,_3d.type);
-}
-break;
-case "author":
-for(i in _3c){
-_3d=_3c[i];
-_3b.addAuthor(_3d.name,_3d.email,_3d.uri);
-}
-break;
-case "contributor":
-for(i in _3c){
-_3d=_3c[i];
-_3b.addContributor(_3d.name,_3d.email,_3d.uri);
-}
-break;
-case "category":
-for(i in _3c){
-_3d=_3c[i];
-_3b.addCategory(_3d.scheme,_3d.term,_3d.label);
-}
-break;
-case "icon":
-case "id":
-case "logo":
-case "xmlBase":
-case "rights":
-_3b[key]=_3c;
-break;
-case "updated":
-case "published":
-case "issued":
-case "modified":
-_3b[key]=dojox.atom.io.model.util.createDate(_3c);
-break;
-case "content":
-case "summary":
-case "title":
-case "subtitle":
-_3b[key]=new dojox.atom.io.model.Content(key);
-_3b[key].value=_3c;
-break;
-default:
-_3b[key]=_3c;
-break;
-}
-}
-}
-_3b.store=this;
-_3b.isDirty=true;
-if(!this._adds){
-this._adds=[_3b];
-}else{
-this._adds.push(_3b);
-}
-if(this._feed){
-this._feed.addEntry(_3b);
-}else{
-if(this._requests){
-this._requests.push({add:_3b});
-}else{
-this._requests=[{add:_3b}];
-this._atomIO=new dojox.atom.io.Connection(false,this.urlPreventCache);
-this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
-}
-}
-return true;
-},deleteItem:function(_3e){
-this._assertIsItem(_3e);
-if(!this._deletes){
-this._deletes=[_3e];
-}else{
-this._deletes.push(_3e);
-}
-if(this._feed){
-this._feed.removeEntry(_3e);
-}else{
-if(this._requests){
-this._requests.push({remove:_3e});
-}else{
-this._requests=[{remove:_3e}];
-this._atomIO=new dojox.atom.io.Connection(false,this.urlPreventCache);
-this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
-}
-}
-_3e=null;
-return true;
-},setValue:function(_3f,_40,_41){
-this._assertIsItem(_3f);
-var _42={item:_3f};
-if(this._assertIsAttribute(_40)){
-switch(_40){
-case "link":
-_42.links=_3f.links;
-this._addUpdate(_42);
-_3f.links=null;
-_3f.addLink(_41.href,_41.rel,_41.hrefLang,_41.title,_41.type);
-_3f.isDirty=true;
-return true;
-case "author":
-_42.authors=_3f.authors;
-this._addUpdate(_42);
-_3f.authors=null;
-_3f.addAuthor(_41.name,_41.email,_41.uri);
-_3f.isDirty=true;
-return true;
-case "contributor":
-_42.contributors=_3f.contributors;
-this._addUpdate(_42);
-_3f.contributors=null;
-_3f.addContributor(_41.name,_41.email,_41.uri);
-_3f.isDirty=true;
-return true;
-case "category":
-_42.categories=_3f.categories;
-this._addUpdate(_42);
-_3f.categories=null;
-_3f.addCategory(_41.scheme,_41.term,_41.label);
-_3f.isDirty=true;
-return true;
-case "icon":
-case "id":
-case "logo":
-case "xmlBase":
-case "rights":
-_42[_40]=_3f[_40];
-this._addUpdate(_42);
-_3f[_40]=_41;
-_3f.isDirty=true;
-return true;
-case "updated":
-case "published":
-case "issued":
-case "modified":
-_42[_40]=_3f[_40];
-this._addUpdate(_42);
-_3f[_40]=dojox.atom.io.model.util.createDate(_41);
-_3f.isDirty=true;
-return true;
-case "content":
-case "summary":
-case "title":
-case "subtitle":
-_42[_40]=_3f[_40];
-this._addUpdate(_42);
-_3f[_40]=new dojox.atom.io.model.Content(_40);
-_3f[_40].value=_41;
-_3f.isDirty=true;
-return true;
-default:
-_42[_40]=_3f[_40];
-this._addUpdate(_42);
-_3f[_40]=_41;
-_3f.isDirty=true;
-return true;
-}
-}
-return false;
-},setValues:function(_43,_44,_45){
-if(_45.length===0){
-return this.unsetAttribute(_43,_44);
-}
-this._assertIsItem(_43);
-var _46={item:_43};
-var _47;
-var i;
-if(this._assertIsAttribute(_44)){
-switch(_44){
-case "link":
-_46.links=_43.links;
-_43.links=null;
-for(i in _45){
-_47=_45[i];
-_43.addLink(_47.href,_47.rel,_47.hrefLang,_47.title,_47.type);
-}
-_43.isDirty=true;
-return true;
-case "author":
-_46.authors=_43.authors;
-_43.authors=null;
-for(i in _45){
-_47=_45[i];
-_43.addAuthor(_47.name,_47.email,_47.uri);
-}
-_43.isDirty=true;
-return true;
-case "contributor":
-_46.contributors=_43.contributors;
-_43.contributors=null;
-for(i in _45){
-_47=_45[i];
-_43.addContributor(_47.name,_47.email,_47.uri);
-}
-_43.isDirty=true;
-return true;
-case "categories":
-_46.categories=_43.categories;
-_43.categories=null;
-for(i in _45){
-_47=_45[i];
-_43.addCategory(_47.scheme,_47.term,_47.label);
-}
-_43.isDirty=true;
-return true;
-case "icon":
-case "id":
-case "logo":
-case "xmlBase":
-case "rights":
-_46[_44]=_43[_44];
-_43[_44]=_45[0];
-_43.isDirty=true;
-return true;
-case "updated":
-case "published":
-case "issued":
-case "modified":
-_46[_44]=_43[_44];
-_43[_44]=dojox.atom.io.model.util.createDate(_45[0]);
-_43.isDirty=true;
-return true;
-case "content":
-case "summary":
-case "title":
-case "subtitle":
-_46[_44]=_43[_44];
-_43[_44]=new dojox.atom.io.model.Content(_44);
-_43[_44].values[0]=_45[0];
-_43.isDirty=true;
-return true;
-default:
-_46[_44]=_43[_44];
-_43[_44]=_45[0];
-_43.isDirty=true;
-return true;
-}
-}
-this._addUpdate(_46);
-return false;
-},unsetAttribute:function(_48,_49){
-this._assertIsItem(_48);
-if(this._assertIsAttribute(_49)){
-if(_48[_49]!==null){
-var _4a={item:_48};
-switch(_49){
-case "author":
-case "contributor":
-case "link":
-_4a[_49+"s"]=_48[_49+"s"];
-break;
-case "category":
-_4a.categories=_48.categories;
-break;
-default:
-_4a[_49]=_48[_49];
-break;
-}
-_48.isDirty=true;
-_48[_49]=null;
-this._addUpdate(_4a);
-return true;
-}
-}
-return false;
-},save:function(_4b){
-var i;
-for(i in this._adds){
-this._atomIO.addEntry(this._adds[i],null,function(){
-},_4b.onError,false,_4b.scope);
-}
-this._adds=null;
-for(i in this._updates){
-this._atomIO.updateEntry(this._updates[i].item,function(){
-},_4b.onError,false,this.xmethod,_4b.scope);
-}
-this._updates=null;
-for(i in this._deletes){
-this._atomIO.removeEntry(this._deletes[i],function(){
-},_4b.onError,this.xmethod,_4b.scope);
-}
-this._deletes=null;
-this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
-if(_4b.onComplete){
-var _4c=_4b.scope||dojo.global;
-_4b.onComplete.call(_4c);
-}
-},revert:function(){
-var i;
-for(i in this._adds){
-this._feed.removeEntry(this._adds[i]);
-}
-this._adds=null;
-var _4d,_4e,key;
-for(i in this._updates){
-_4d=this._updates[i];
-_4e=_4d.item;
-for(key in _4d){
-if(key!=="item"){
-_4e[key]=_4d[key];
-}
-}
-}
-this._updates=null;
-for(i in this._deletes){
-this._feed.addEntry(this._deletes[i]);
-}
-this._deletes=null;
-return true;
-},isDirty:function(_4f){
-if(_4f){
-this._assertIsItem(_4f);
-return _4f.isDirty?true:false;
-}
-return (this._adds!==null||this._updates!==null);
-}});
+
+dojo.declare("dojox.data.AppStore",
+	null,{
+
+	// url: [public] string
+	//		So the parser can instantiate the store via markup.		
+	url: "",
+	
+	// urlPreventCache: [public] boolean
+	//		Whether or not to pass the preventCache parameter to the connection
+	urlPreventCache: false,
+
+	// xmethod: [public] boolean
+	//		Whether to use X-Method-Override for PUT/DELETE.
+	xmethod: false,
+	
+	_atomIO: null,
+	_feed: null,
+	_requests: null,
+	_processing: null,
+	
+	_updates: null,
+	_adds: null,
+	_deletes: null,
+	
+	constructor: function(/*Object*/args){
+		// summary:
+		//		The APP data store.  
+		// description:
+		//		The APP Store is instantiated either in markup or programmatically by supplying a
+		//		url of the Collection to be used.
+		//
+		// args:
+		//		An anonymous object to initialize properties.  It expects the following values:
+		//		url:		The url of the Collection to load.
+		//		urlPreventCache:	Whether or not to append on cache prevention params (as defined by dojo.xhr*)
+		
+		if(args && args.url){
+			this.url = args.url;
+		}
+		if(args && args.urlPreventCache){
+			this.urlPreventCache = args.urlPreventCache;
+		}
+		if(!this.url){
+			throw new Error("A URL is required to instantiate an APP Store object");
+		}
+	},
+	
+	_setFeed: function(feed, data){
+		// summary: 
+		//		Sets the internal feed using a dojox.atom.io.model.Feed object.
+		// description:
+		//		Sets the internal feed using a dojox.atom.io.model.Feed object.  Also adds
+		//		a property to the entries to track that they belong to this store. It 
+		//		also parses stored requests (since we were waiting on a callback) and 
+		//		executes those as well.
+		//
+		// feed: dojox.atom.io.model.Feed object
+		//		The Feed to use for this data store.
+		// data: unused
+		//		Signature for this function is defined by AtomIO.getFeed, since this is a callback.
+		this._feed = feed;
+		var i;
+		for(i=0; i<this._feed.entries.length; i++){
+			this._feed.entries[i].store = this;
+		}
+		if(this._requests){
+			for(i=0; i<this._requests.length; i++){
+				var request = this._requests[i];
+				if(request.request && request.fh && request.eh){
+					this._finishFetchItems(request.request, request.fh, request.eh);
+				}else if(request.clear){
+					this._feed = null;	
+				}else if(request.add){
+					this._feed.addEntry(request.add);
+				}else if(request.remove){
+					this._feed.removeEntry(request.remove);
+				}
+			}
+		}
+		this._requests = null;
+	},
+	
+	_getAllItems: function(){
+		// summary:
+		//		Function to return all entries in the Feed as an array of items.
+		// description:
+		//		Function to return all entries in the Feed as an array of items.
+		//
+		// returns:
+		//		Array of all entries in the feed.
+		var items = [];
+		for(var i=0; i<this._feed.entries.length; i++){
+			items.push(this._feed.entries[i]);
+		}
+		return items; //array
+	},
+	
+	_assertIsItem: function(/* item */ item){
+		// summary:
+		//		This function tests whether the item is an item.
+		// description:
+		//		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("This error message is provided when a function is called in the following form: "
+				+ "getAttribute(argument, attributeName).  The argument variable represents the member "
+				+ "or owner of the object. The error is created when an item that does not belong "
+				+ "to this store is specified as an argument.");
+		}
+	},
+
+	_assertIsAttribute: function(/* String */ attribute){
+		// summary:
+		//		This function tests whether the item is an attribute.
+		// description:
+		//		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.
+		//
+		// returns:
+		//		Returns a boolean indicating whether this is a valid attribute.
+		if(typeof attribute !== "string"){ 
+			throw new Error("The attribute argument must be a string. The error is created "
+			+ "when a different type of variable is specified such as an array or object.");
+		}
+
+		for(var key in dojox.atom.io.model._actions){
+			if(key == attribute){
+				return true;
+			}
+		}
+		return false;
+	},
+	
+	_addUpdate: function(/* Object */ update){
+		// summary:
+		//		Internal function to add an updated entry to our updates array
+		// description:
+		//		Internal function to add an updated entry to our updates array
+		//
+		// update: dojox.atom.io.model.Entry object
+		//		The updated Entry we've changed.
+		if(!this._updates){
+			this._updates = [update];
+		}else{
+			this._updates.push(update);
+		}
+	},
+
+/***************************************
+     dojo.data.api.Read API
+***************************************/
+	
+	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; //Object || int || Boolean
+	},
+
+	getValues: function(/* item */ item, 
+						/* attribute-name-string */ attribute){
+		// summary: 
+		//		See dojo.data.api.Read.getValues()
+
+		this._assertIsItem(item);
+		var flag = this._assertIsAttribute(attribute);
+
+		if(flag){
+			if((attribute === "author" || attribute === "contributor" || attribute === "link") && item[attribute+"s"]){
+				return item[attribute+"s"];
+			}
+			if(attribute === "category" && item.categories){
+				return item.categories;
+			}
+			if(item[attribute]){
+				item = item[attribute];
+				if(item.declaredClass == "dojox.atom.io.model.Content"){
+					return [item.value];			
+				}
+				return [item] ;
+			}
+		}
+		return []; //Array
+	},
+
+	getAttributes: function(/* item */ item){
+		// summary: 
+		//		See dojo.data.api.Read.getAttributes()
+		this._assertIsItem(item);
+		var attributes = [];
+		for(var key in dojox.atom.io.model._actions){
+			if(this.hasAttribute(item, key)){
+				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,
+								/* Boolean?*/ trim){
+		// 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'
+		var values = this.getValues(item, attribute);
+		for(var i = 0; i < values.length; ++i){
+			var possibleValue = values[i];
+			if(typeof possibleValue === "string" && regexp){
+				if(trim){
+					possibleValue = possibleValue.replace(new RegExp(/^\s+/),""); // START
+					possibleValue = possibleValue.replace(new RegExp(/\s+$/),""); // END
+				}
+				possibleValue = possibleValue.replace(/\r|\n|\r\n/g, "");
+				return (possibleValue.match(regexp) !== null);
+			}else{
+				//Non-string matching.
+				if(value === possibleValue){
+					return true; // Boolean
+				}
+			}
+		}
+		return false; // Boolean
+	},
+
+	isItem: function(/* anything */ something){
+		// summary: 
+		//		See dojo.data.api.Read.isItem()
+		return something && something.store && something.store === this; //boolean
+	},
+
+	isItemLoaded: function(/* anything */ something){
+		// summary: 
+		//		See dojo.data.api.Read.isItemLoaded()
+		return this.isItem(something);
+	},
+
+	loadItem: function(/* Object */ keywordArgs){
+		// summary: 
+		//		See dojo.data.api.Read.loadItem()
+		this._assertIsItem(keywordArgs.item);
+	},
+	
+	_fetchItems: function(request, fetchHandler, errorHandler){
+		// summary: 
+		//		Fetch items (Atom entries) that match to a query
+		// description: 
+		//		Fetch items (Atom entries) that match to a query
+		// request:
+		//		A request object
+		// fetchHandler:
+		//		A function to call for fetched items
+		// errorHandler:
+		//		A function to call on error
+		if(this._feed){
+			this._finishFetchItems(request, fetchHandler, errorHandler);
+		}else{
+			var flag = false;
+			if(!this._requests){
+				this._requests = [];
+				flag = true;
+			}
+			this._requests.push({request: request, fh: fetchHandler, eh: errorHandler});
+			if(flag){
+				this._atomIO = new dojox.atom.io.Connection(false, this.urlPreventCache);
+				this._atomIO.getFeed(this.url,this._setFeed, null, this);
+			}
+		}
+	},
+		
+	_finishFetchItems: function(request, fetchHandler, errorHandler){
+		// summary: 
+		//		Internal function for finishing a fetch request.
+		// description: 
+		//		Internal function for finishing a fetch request.  Needed since the feed
+		//		might not have been loaded, so we finish the fetch in a callback.
+		//
+		// request:
+		//		A request object
+		// fetchHandler:
+		//		A function to call for fetched items
+		// errorHandler:
+		//		A function to call on error
+		var items = null;
+		var arrayOfAllItems = this._getAllItems();
+		if(request.query){
+			var ignoreCase = request.queryOptions ? request.queryOptions.ignoreCase : false; 
+			items = [];
+
+			//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 = {};
+			var key;
+			var value;
+			for(key in request.query){
+				value = request.query[key]+'';
+				if(typeof value === "string"){
+					regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
+				}
+			}
+
+			for(var i = 0; i < arrayOfAllItems.length; ++i){
+				var match = true;
+				var candidateItem = arrayOfAllItems[i];
+				for(key in request.query){
+					value = request.query[key]+'';
+					if(!this._containsValue(candidateItem, key, value, regexpList[key], request.trim)){
+						match = false;
+					}
+				}
+				if(match){
+					items.push(candidateItem);
+				}
+			}
+		}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 listsand sort without affecting each other.
+			if(arrayOfAllItems.length> 0){
+				items = arrayOfAllItems.slice(0,arrayOfAllItems.length); 
+			}
+		}
+		try{
+			fetchHandler(items, request);
+		}catch(e){
+			errorHandler(e, request);
+		}
+	},
+
+	getFeatures: function(){
+		// summary: 
+		//		See dojo.data.api.Read.getFeatures()
+		return {
+			'dojo.data.api.Read': true,
+			'dojo.data.api.Write': true,
+			'dojo.data.api.Identity': true
+		};
+	},
+	
+	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+		// summary:
+		//		See dojo.data.api.Read.close()
+		// nothing to do here!
+		this._feed = null;
+	},
+
+	getLabel: function(/* item */ item){
+		// summary: 
+		//		See dojo.data.api.Read.getLabel()
+		if(this.isItem(item)){
+			return this.getValue(item, "title", "No Title");
+		}
+		return undefined;
+	},
+
+	getLabelAttributes: function(/* item */ item){
+		// summary: 
+		//		See dojo.data.api.Read.getLabelAttributes()
+		return ["title"];
+	},
+
+/***************************************
+     dojo.data.api.Identity API
+***************************************/
+
+	getIdentity: function(/* item */ item){
+		// summary: 
+		//		See dojo.data.api.Identity.getIdentity()
+		this._assertIsItem(item);
+		return this.getValue(item, "id");
+	},
+
+	getIdentityAttributes: function(/* item */ item){
+		 //	summary: 
+		 //		See dojo.data.api.Identity.getIdentityAttributes()
+		 return ["id"];
+	},
+
+	fetchItemByIdentity: function(keywordArgs){
+		// summary: 
+		//		See dojo.data.api.Identity.fetchItemByIdentity()
+
+		this._fetchItems({query:{id:keywordArgs.identity}, onItem: keywordArgs.onItem, scope: keywordArgs.scope},
+			function(items, request){
+				var scope = request.scope;
+				if(!scope){
+					scope = dojo.global;
+				}
+				if(items.length < 1){
+					request.onItem.call(scope, null);
+				}else{
+					request.onItem.call(scope, items[0]);
+				}
+		}, keywordArgs.onError);
+	},
+
+/***************************************
+     dojo.data.api.Identity API
+***************************************/
+
+	newItem: function(/* Object? */ keywordArgs){
+		// summary: 
+		//		See dojo.data.api.Write.newItem()
+		var entry = new dojox.atom.io.model.Entry();
+		var value = null;
+		var temp = null;
+		var i;
+		for(var key in keywordArgs){
+			if(this._assertIsAttribute(key)){
+				value = keywordArgs[key];
+				switch(key){
+					case "link":
+						for(i in value){
+							temp = value[i];
+							entry.addLink(temp.href,temp.rel,temp.hrefLang,temp.title,temp.type);
+						}
+						break;
+					case "author":
+						for(i in value){
+							temp = value[i];
+							entry.addAuthor(temp.name, temp.email, temp.uri);
+						}
+						break;
+					case "contributor":
+						for(i in value){
+							temp = value[i];
+							entry.addContributor(temp.name, temp.email, temp.uri);
+						}
+						break;
+					case "category":
+						for(i in value){
+							temp = value[i];
+							entry.addCategory(temp.scheme, temp.term, temp.label);
+						}
+						break;
+					case "icon":
+					case "id":
+					case "logo":
+					case "xmlBase":
+					case "rights":
+						entry[key] = value;
+						break;
+					case "updated":
+					case "published":
+					case "issued":
+					case "modified":
+						entry[key] = dojox.atom.io.model.util.createDate(value);
+						break;
+					case "content":
+					case "summary":
+					case "title":
+					case "subtitle":
+						entry[key] = new dojox.atom.io.model.Content(key);
+						entry[key].value = value;
+						break;
+					default:
+						entry[key] = value;
+						break;
+				}
+			}
+		}
+		entry.store = this;
+		entry.isDirty = true;
+
+		if(!this._adds){
+			this._adds = [entry];
+		}else{
+			this._adds.push(entry);
+		}
+
+		if(this._feed){
+			this._feed.addEntry(entry);
+		}else{
+			if(this._requests){
+				this._requests.push({add:entry});
+			}else{
+				this._requests = [{add:entry}];
+				this._atomIO = new dojox.atom.io.Connection(false, this.urlPreventCache);
+				this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
+			}
+		}
+		return true;
+	},
+
+	deleteItem: function(/* item */ item){
+		// summary: 
+		//		See dojo.data.api.Write.deleteItem()
+		this._assertIsItem(item);
+
+		if(!this._deletes){
+			this._deletes = [item];
+		}else{
+			this._deletes.push(item);
+		}
+
+		if(this._feed){
+			this._feed.removeEntry(item);
+		}else{
+			if(this._requests){
+				this._requests.push({remove:item});
+			}else{
+				this._requests = [{remove:item}];
+				this._atomIO = new dojox.atom.io.Connection(false, this.urlPreventCache);
+				this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
+			}
+		}
+		item = null;
+		return true;
+	},
+
+	setValue: function(	/* item */ item, 
+						/* string */ attribute,
+						/* almost anything */ value){
+		// summary: 
+		//		See dojo.data.api.Write.setValue()
+		this._assertIsItem(item);
+		
+		var update = {item: item};
+		if(this._assertIsAttribute(attribute)){
+			switch(attribute){
+				case "link":
+					update.links = item.links;
+					this._addUpdate(update);
+					item.links = null;
+					item.addLink(value.href,value.rel,value.hrefLang,value.title,value.type);
+					item.isDirty = true;
+					return true;
+				case "author":
+					update.authors = item.authors;
+					this._addUpdate(update);
+					item.authors = null;
+					item.addAuthor(value.name, value.email, value.uri);
+					item.isDirty = true;
+					return true;
+				case "contributor":
+					update.contributors = item.contributors;
+					this._addUpdate(update);
+					item.contributors = null;
+					item.addContributor(value.name, value.email, value.uri);
+					item.isDirty = true;
+					return true;
+				case "category":
+					update.categories = item.categories;
+					this._addUpdate(update);
+					item.categories = null;
+					item.addCategory(value.scheme, value.term, value.label);
+					item.isDirty = true;
+					return true;
+				case "icon":
+				case "id":
+				case "logo":
+				case "xmlBase":
+				case "rights":
+					update[attribute] = item[attribute];
+					this._addUpdate(update);
+					item[attribute] = value;
+					item.isDirty = true;
+					return true;
+				case "updated":
+				case "published":
+				case "issued":
+				case "modified":
+					update[attribute] = item[attribute];
+					this._addUpdate(update);
+					item[attribute] = dojox.atom.io.model.util.createDate(value);
+					item.isDirty = true;
+					return true;
+				case "content":
+				case "summary":
+				case "title":
+				case "subtitle":
+					update[attribute] = item[attribute];
+					this._addUpdate(update);
+					item[attribute] = new dojox.atom.io.model.Content(attribute);
+					item[attribute].value = value;
+					item.isDirty = true;
+					return true;
+				default:
+					update[attribute] = item[attribute];
+					this._addUpdate(update);
+					item[attribute] = value;
+					item.isDirty = true;
+					return true;
+			}
+		}
+		return false;
+	},
+
+	setValues: function(/* item */ item,
+						/* string */ attribute, 
+						/* array */ values){
+		// summary: 
+		//		See dojo.data.api.Write.setValues()
+		if(values.length === 0){
+			return this.unsetAttribute(item, attribute);
+		}
+		this._assertIsItem(item);
+		
+		var update = {item: item};
+		var value;
+		var i;
+		if(this._assertIsAttribute(attribute)){
+			switch(attribute){
+				case "link":
+					update.links = item.links;
+					item.links = null;
+					for(i in values){
+						value = values[i];
+						item.addLink(value.href,value.rel,value.hrefLang,value.title,value.type);
+					}
+					item.isDirty = true;
+					return true;
+				case "author":
+					update.authors = item.authors;
+					item.authors = null;
+					for(i in values){
+						value = values[i];
+						item.addAuthor(value.name, value.email, value.uri);
+					}
+					item.isDirty = true;
+					return true;
+				case "contributor":
+					update.contributors = item.contributors;
+					item.contributors = null;
+					for(i in values){
+						value = values[i];
+						item.addContributor(value.name, value.email, value.uri);
+					}
+					item.isDirty = true;
+					return true;
+				case "categories":
+					update.categories = item.categories;
+					item.categories = null;
+					for(i in values){
+						value = values[i];
+						item.addCategory(value.scheme, value.term, value.label);
+					}
+					item.isDirty = true;
+					return true;
+				case "icon":
+				case "id":
+				case "logo":
+				case "xmlBase":
+				case "rights":
+					update[attribute] = item[attribute];
+					item[attribute] = values[0];
+					item.isDirty = true;
+					return true;
+				case "updated":
+				case "published":
+				case "issued":
+				case "modified":
+					update[attribute] = item[attribute];
+					item[attribute] = dojox.atom.io.model.util.createDate(values[0]);
+					item.isDirty = true;
+					return true;
+				case "content":
+				case "summary":
+				case "title":
+				case "subtitle":
+					update[attribute] = item[attribute];
+					item[attribute] = new dojox.atom.io.model.Content(attribute);
+					item[attribute].values[0] = values[0];
+					item.isDirty = true;
+					return true;
+				default:
+					update[attribute] = item[attribute];
+					item[attribute] = values[0];
+					item.isDirty = true;
+					return true;
+			}
+		}
+		this._addUpdate(update);
+		return false;
+	},
+
+	unsetAttribute: function(	/* item */ item, 
+								/* string */ attribute){
+		// summary: 
+		//		See dojo.data.api.Write.unsetAttribute()
+		this._assertIsItem(item);
+		if(this._assertIsAttribute(attribute)){
+			if(item[attribute] !== null){
+				var update = {item: item};
+				switch(attribute){
+					case "author":
+					case "contributor":
+					case "link":
+						update[attribute+"s"] = item[attribute+"s"];
+						break;
+					case "category":
+						update.categories = item.categories;
+						break;
+					default:
+						update[attribute] = item[attribute];
+						break;
+				}
+				item.isDirty = true;
+				item[attribute] = null;
+				this._addUpdate(update);
+				return true;
+			}
+		}
+		return false; // boolean
+	},
+
+	save: function(/* object */ keywordArgs){
+		// summary: 
+		//		See dojo.data.api.Write.save()
+		// keywordArgs:
+		//		{
+		//			onComplete: function
+		//			onError: function
+		//			scope: object
+		//		}
+		var i;
+		for(i in this._adds){
+			this._atomIO.addEntry(this._adds[i], null, function(){}, keywordArgs.onError, false, keywordArgs.scope);
+		}
+			
+		this._adds = null;
+		
+		for(i in this._updates){
+			this._atomIO.updateEntry(this._updates[i].item, function(){}, keywordArgs.onError, false, this.xmethod, keywordArgs.scope);
+		}
+			
+		this._updates = null;
+		
+		for(i in this._deletes){
+			this._atomIO.removeEntry(this._deletes[i], function(){}, keywordArgs.onError, this.xmethod, keywordArgs.scope);
+		}
+			
+		this._deletes = null;
+		
+		this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
+		
+		if(keywordArgs.onComplete){
+			var scope = keywordArgs.scope || dojo.global;
+			keywordArgs.onComplete.call(scope);
+		}
+	},
+
+	revert: function(){
+		// summary: 
+		//		See dojo.data.api.Write.revert()
+		var i;
+		for(i in this._adds){
+			this._feed.removeEntry(this._adds[i]);
+		}
+			
+		this._adds = null;
+		
+		var update, item, key;
+		for(i in this._updates){
+			update = this._updates[i];
+			item = update.item;
+			for(key in update){
+				if(key !== "item"){
+					item[key] = update[key];
+				}
+			}
+		}
+		this._updates = null;
+		
+		for(i in this._deletes){
+			this._feed.addEntry(this._deletes[i]);
+		}
+		this._deletes = null;
+		return true;
+	},
+
+	isDirty: function(/* item? */ item){
+		// summary: 
+		//		See dojo.data.api.Write.isDirty()
+		if(item){
+			this._assertIsItem(item);
+			return item.isDirty?true:false; //boolean
+		}
+		return (this._adds !== null || this._updates !== null); //boolean
+	}
+});
 dojo.extend(dojox.data.AppStore,dojo.data.util.simpleFetch);
-}
diff --git a/dojox/data/AtomReadStore.js b/dojox/data/AtomReadStore.js
index 10083e5..c6a176d 100644
--- a/dojox/data/AtomReadStore.js
+++ b/dojox/data/AtomReadStore.js
@@ -1,340 +1,552 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.AtomReadStore"]){
-dojo._hasResource["dojox.data.AtomReadStore"]=true;
 dojo.provide("dojox.data.AtomReadStore");
+
 dojo.require("dojo.data.util.simpleFetch");
 dojo.require("dojo.data.util.filter");
 dojo.require("dojo.date.stamp");
+
 dojo.experimental("dojox.data.AtomReadStore");
-dojo.declare("dojox.data.AtomReadStore",null,{constructor:function(_1){
-if(_1){
-this.url=_1.url;
-this.rewriteUrl=_1.rewriteUrl;
-this.label=_1.label||this.label;
-this.sendQuery=(_1.sendQuery||_1.sendquery||this.sendQuery);
-this.unescapeHTML=_1.unescapeHTML;
-if("urlPreventCache" in _1){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-}
-if(!this.url){
-throw new Error("AtomReadStore: a URL must be specified when creating the data store");
-}
-},url:"",label:"title",sendQuery:false,unescapeHTML:false,urlPreventCache:false,getValue:function(_2,_3,_4){
-this._assertIsItem(_2);
-this._assertIsAttribute(_3);
-this._initItem(_2);
-_3=_3.toLowerCase();
-if(!_2._attribs[_3]&&!_2._parsed){
-this._parseItem(_2);
-_2._parsed=true;
-}
-var _5=_2._attribs[_3];
-if(!_5&&_3=="summary"){
-var _6=this.getValue(_2,"content");
-var _7=new RegExp("/(<([^>]+)>)/g","i");
-var _8=_6.text.replace(_7,"");
-_5={text:_8.substring(0,Math.min(400,_8.length)),type:"text"};
-_2._attribs[_3]=_5;
-}
-if(_5&&this.unescapeHTML){
-if((_3=="content"||_3=="summary"||_3=="subtitle")&&!_2["_"+_3+"Escaped"]){
-_5.text=this._unescapeHTML(_5.text);
-_2["_"+_3+"Escaped"]=true;
-}
-}
-return _5?dojo.isArray(_5)?_5[0]:_5:_4;
-},getValues:function(_9,_a){
-this._assertIsItem(_9);
-this._assertIsAttribute(_a);
-this._initItem(_9);
-_a=_a.toLowerCase();
-if(!_9._attribs[_a]){
-this._parseItem(_9);
-}
-var _b=_9._attribs[_a];
-return _b?((_b.length!==undefined&&typeof (_b)!=="string")?_b:[_b]):undefined;
-},getAttributes:function(_c){
-this._assertIsItem(_c);
-if(!_c._attribs){
-this._initItem(_c);
-this._parseItem(_c);
-}
-var _d=[];
-for(var x in _c._attribs){
-_d.push(x);
-}
-return _d;
-},hasAttribute:function(_e,_f){
-return (this.getValue(_e,_f)!==undefined);
-},containsValue:function(_10,_11,_12){
-var _13=this.getValues(_10,_11);
-for(var i=0;i<_13.length;i++){
-if((typeof _12==="string")){
-if(_13[i].toString&&_13[i].toString()===_12){
-return true;
-}
-}else{
-if(_13[i]===_12){
-return true;
-}
-}
-}
-return false;
-},isItem:function(_14){
-if(_14&&_14.element&&_14.store&&_14.store===this){
-return true;
-}
-return false;
-},isItemLoaded:function(_15){
-return this.isItem(_15);
-},loadItem:function(_16){
-},getFeatures:function(){
-var _17={"dojo.data.api.Read":true};
-return _17;
-},getLabel:function(_18){
-if((this.label!=="")&&this.isItem(_18)){
-var _19=this.getValue(_18,this.label);
-if(_19&&_19.text){
-return _19.text;
-}else{
-if(_19){
-return _19.toString();
-}else{
-return undefined;
-}
-}
-}
-return undefined;
-},getLabelAttributes:function(_1a){
-if(this.label!==""){
-return [this.label];
-}
-return null;
-},getFeedValue:function(_1b,_1c){
-var _1d=this.getFeedValues(_1b,_1c);
-if(dojo.isArray(_1d)){
-return _1d[0];
-}
-return _1d;
-},getFeedValues:function(_1e,_1f){
-if(!this.doc){
-return _1f;
-}
-if(!this._feedMetaData){
-this._feedMetaData={element:this.doc.getElementsByTagName("feed")[0],store:this,_attribs:{}};
-this._parseItem(this._feedMetaData);
-}
-return this._feedMetaData._attribs[_1e]||_1f;
-},_initItem:function(_20){
-if(!_20._attribs){
-_20._attribs={};
-}
-},_fetchItems:function(_21,_22,_23){
-var url=this._getFetchUrl(_21);
-if(!url){
-_23(new Error("No URL specified."));
-return;
-}
-var _24=(!this.sendQuery?_21:null);
-var _25=this;
-var _26=function(_27){
-_25.doc=_27;
-var _28=_25._getItems(_27,_24);
-var _29=_21.query;
-if(_29){
-if(_29.id){
-_28=dojo.filter(_28,function(_2a){
-return (_25.getValue(_2a,"id")==_29.id);
-});
-}else{
-if(_29.category){
-_28=dojo.filter(_28,function(_2b){
-var _2c=_25.getValues(_2b,"category");
-if(!_2c){
-return false;
-}
-return dojo.some(_2c,"return item.term=='"+_29.category+"'");
-});
-}
-}
-}
-if(_28&&_28.length>0){
-_22(_28,_21);
-}else{
-_22([],_21);
-}
-};
-if(this.doc){
-_26(this.doc);
-}else{
-var _2d={url:url,handleAs:"xml",preventCache:this.urlPreventCache};
-var _2e=dojo.xhrGet(_2d);
-_2e.addCallback(_26);
-_2e.addErrback(function(_2f){
-_23(_2f,_21);
-});
-}
-},_getFetchUrl:function(_30){
-if(!this.sendQuery){
-return this.url;
-}
-var _31=_30.query;
-if(!_31){
-return this.url;
-}
-if(dojo.isString(_31)){
-return this.url+_31;
-}
-var _32="";
-for(var _33 in _31){
-var _34=_31[_33];
-if(_34){
-if(_32){
-_32+="&";
-}
-_32+=(_33+"="+_34);
-}
-}
-if(!_32){
-return this.url;
-}
-var _35=this.url;
-if(_35.indexOf("?")<0){
-_35+="?";
-}else{
-_35+="&";
-}
-return _35+_32;
-},_getItems:function(_36,_37){
-if(this._items){
-return this._items;
-}
-var _38=[];
-var _39=[];
-if(_36.childNodes.length<1){
-this._items=_38;
-return _38;
-}
-var _3a=dojo.filter(_36.childNodes,"return item.tagName && item.tagName.toLowerCase() == 'feed'");
-var _3b=_37.query;
-if(!_3a||_3a.length!=1){
-return _38;
-}
-_39=dojo.filter(_3a[0].childNodes,"return item.tagName && item.tagName.toLowerCase() == 'entry'");
-if(_37.onBegin){
-_37.onBegin(_39.length,this.sendQuery?_37:{});
-}
-for(var i=0;i<_39.length;i++){
-var _3c=_39[i];
-if(_3c.nodeType!=1){
-continue;
-}
-_38.push(this._getItem(_3c));
-}
-this._items=_38;
-return _38;
-},close:function(_3d){
-},_getItem:function(_3e){
-return {element:_3e,store:this};
-},_parseItem:function(_3f){
-var _40=_3f._attribs;
-var _41=this;
-var _42,_43;
-function _44(_45){
-var txt=_45.textContent||_45.innerHTML||_45.innerXML;
-if(!txt&&_45.childNodes[0]){
-var _46=_45.childNodes[0];
-if(_46&&(_46.nodeType==3||_46.nodeType==4)){
-txt=_45.childNodes[0].nodeValue;
-}
-}
-return txt;
-};
-function _47(_48){
-return {text:_44(_48),type:_48.getAttribute("type")};
-};
-dojo.forEach(_3f.element.childNodes,function(_49){
-var _4a=_49.tagName?_49.tagName.toLowerCase():"";
-switch(_4a){
-case "title":
-_40[_4a]={text:_44(_49),type:_49.getAttribute("type")};
-break;
-case "subtitle":
-case "summary":
-case "content":
-_40[_4a]=_47(_49);
-break;
-case "author":
-var _4b,_4c;
-dojo.forEach(_49.childNodes,function(_4d){
-if(!_4d.tagName){
-return;
-}
-switch(_4d.tagName.toLowerCase()){
-case "name":
-_4b=_4d;
-break;
-case "uri":
-_4c=_4d;
-break;
-}
-});
-var _4e={};
-if(_4b&&_4b.length==1){
-_4e.name=_44(_4b[0]);
-}
-if(_4c&&_4c.length==1){
-_4e.uri=_44(_4c[0]);
-}
-_40[_4a]=_4e;
-break;
-case "id":
-_40[_4a]=_44(_49);
-break;
-case "updated":
-_40[_4a]=dojo.date.stamp.fromISOString(_44(_49));
-break;
-case "published":
-_40[_4a]=dojo.date.stamp.fromISOString(_44(_49));
-break;
-case "category":
-if(!_40[_4a]){
-_40[_4a]=[];
-}
-_40[_4a].push({scheme:_49.getAttribute("scheme"),term:_49.getAttribute("term")});
-break;
-case "link":
-if(!_40[_4a]){
-_40[_4a]=[];
-}
-var _4f={rel:_49.getAttribute("rel"),href:_49.getAttribute("href"),type:_49.getAttribute("type")};
-_40[_4a].push(_4f);
-if(_4f.rel=="alternate"){
-_40["alternate"]=_4f;
-}
-break;
-default:
-break;
-}
+
+dojo.declare("dojox.data.AtomReadStore", null, {
+	//	summary:
+	//		A read only data store for Atom XML based services or documents
+	//	description:
+	//		A data store for Atom XML based services or documents.	This store is still under development
+	//		and doesn't support wildcard filtering yet.	Attribute filtering is limited to category or id.
+
+	constructor: function(/* object */ args){
+		//	summary:
+		//		Constructor for the AtomRead store.
+		//	args:
+		//		An anonymous object to initialize properties.	It expects the following values:
+		//		url:			The url to a service or an XML document that represents the store
+		//		unescapeHTML:	A boolean to specify whether or not to unescape HTML text
+		//		sendQuery:		A boolean indicate to add a query string to the service URL
+
+		if(args){
+			this.url = args.url;
+			this.rewriteUrl = args.rewriteUrl;
+			this.label = args.label || this.label;
+			this.sendQuery = (args.sendQuery || args.sendquery || this.sendQuery);
+			this.unescapeHTML = args.unescapeHTML;
+			if("urlPreventCache" in args){
+				this.urlPreventCache = args.urlPreventCache?true:false;
+						}
+		}
+		if(!this.url){
+			throw new Error("AtomReadStore: a URL must be specified when creating the data store");
+		}
+	},
+
+	//Values that may be set by the parser.
+	//Ergo, have to be instantiated to something
+	//So the parser knows how to set them.
+	url: "",
+
+	label: "title",
+
+	sendQuery: false,
+
+	unescapeHTML: false,
+
+	//Configurable preventCache option for the URL.
+	urlPreventCache: false,
+
+	/* dojo.data.api.Read */
+
+	getValue: function(/* item */ item, /* attribute || attribute-name-string */ attribute, /* value? */ defaultValue){
+		//	summary:
+		//		Return an attribute value
+		//	description:
+		//		'item' must be an instance of an object created by the AtomReadStore instance.
+		//		Accepted attributes are id, subtitle, title, summary, content, author, updated,
+		//		published, category, link and alternate
+		//	item:
+		//		An item returned by a call to the 'fetch' method.
+		//	attribute:
+		//		A attribute of the Atom Entry
+		//	defaultValue:
+		//		A default value
+		//	returns:
+		//		An attribute value found, otherwise 'defaultValue'
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		this._initItem(item);
+		attribute = attribute.toLowerCase();
+		//If the attribute has previously been retrieved, then return it
+		if(!item._attribs[attribute] && !item._parsed){
+			this._parseItem(item);
+			item._parsed = true;
+		}
+		var retVal = item._attribs[attribute];
+
+		if(!retVal && attribute == "summary"){
+			var content = this.getValue(item, "content");
+			var regexp = new RegExp("/(<([^>]+)>)/g", "i");
+			var text = content.text.replace(regexp,"");
+			retVal = {
+				text: text.substring(0, Math.min(400, text.length)),
+				type: "text"
+			};
+			item._attribs[attribute] = retVal;
+		}
+
+		if(retVal && this.unescapeHTML){
+			if((attribute == "content" || attribute == "summary" || attribute == "subtitle") && !item["_"+attribute+"Escaped"]){
+				retVal.text = this._unescapeHTML(retVal.text);
+				item["_"+attribute+"Escaped"] = true;
+			}
+		}
+		return retVal ? dojo.isArray(retVal) ? retVal[0]: retVal : defaultValue;
+	},
+
+	getValues: function(/* item */ item, /* attribute || attribute-name-string */ attribute){
+		//	summary:
+		//		Return an attribute value
+		//	description:
+		//		'item' must be an instance of an object created by the AtomReadStore instance.
+		//		Accepted attributes are id, subtitle, title, summary, content, author, updated,
+		//		published, category, link and alternate
+		//	item:
+		//		An item returned by a call to the 'fetch' method.
+		//	attribute:
+		//		A attribute of the Atom Entry
+		//	returns:
+		//		An array of values for the attribute value found, otherwise 'defaultValue'
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		this._initItem(item);
+		attribute = attribute.toLowerCase();
+		//If the attribute has previously been retrieved, then return it
+		if(!item._attribs[attribute]){
+			this._parseItem(item);
+		}
+		var retVal = item._attribs[attribute];
+		return retVal ? ((retVal.length !== undefined && typeof(retVal) !== "string") ? retVal : [retVal]) : undefined;
+	},
+
+	getAttributes: function(/* item */ item){
+		//	summary:
+		//		Return an array of attribute names
+		// 	description:
+		//		'item' must be have been created by the AtomReadStore instance.
+		//		tag names of child elements and XML attribute names of attributes
+		//		specified to the element are returned along with special attribute
+		//		names applicable to the element including "tagName", "childNodes"
+		//		if the element has child elements, "text()" if the element has
+		//		child text nodes, and attribute names in '_attributeMap' that match
+		//		the tag name of the element.
+		//	item:
+		//		An XML element
+		//	returns:
+		//		An array of attributes found
+		this._assertIsItem(item);
+		if(!item._attribs){
+			this._initItem(item);
+			this._parseItem(item);
+		}
+		var attrNames = [];
+		for(var x in item._attribs){
+			attrNames.push(x);
+		}
+		return attrNames; //array
+	},
+
+	hasAttribute: function(/* item */ item, /* attribute || attribute-name-string */ attribute){
+		//	summary:
+		//		Check whether an element has the attribute
+		//	item:
+		//		'item' must be created by the AtomReadStore instance.
+		//	attribute:
+		//		An attribute of an Atom Entry item.
+		//	returns:
+		//		True if the element has the attribute, otherwise false
+		return (this.getValue(item, attribute) !== undefined); //boolean
+	},
+
+	containsValue: function(/* item */ item, /* attribute || attribute-name-string */ attribute, /* anything */ value){
+		//	summary:
+		//		Check whether the attribute values contain the value
+		//	item:
+		//		'item' must be an instance of a dojox.data.XmlItem from the store instance.
+		//	attribute:
+		//		A tag name of a child element, An XML attribute name or one of
+		//		special names
+		//	returns:
+		//		True if the attribute values contain the value, otherwise false
+		var values = this.getValues(item, attribute);
+		for(var i = 0; i < values.length; i++){
+			if((typeof value === "string")){
+				if(values[i].toString && values[i].toString() === value){
+					return true;
+				}
+			}else if(values[i] === value){
+				return true; //boolean
+			}
+		}
+		return false;//boolean
+	},
+
+	isItem: function(/* anything */ something){
+		//	summary:
+		//		Check whether the object is an item (XML element)
+		//	item:
+		//		An object to check
+		// 	returns:
+		//		True if the object is an XML element, otherwise false
+		if(something && something.element && something.store && something.store === this){
+			return true; //boolean
+		}
+		return false; //boolran
+	},
+
+	isItemLoaded: function(/* anything */ something){
+		//	summary:
+		//		Check whether the object is an item (XML element) and loaded
+		//	item:
+		//		An object to check
+		//	returns:
+		//		True if the object is an XML element, otherwise false
+		return this.isItem(something); //boolean
+	},
+
+	loadItem: function(/* object */ keywordArgs){
+		//	summary:
+		//		Load an item (XML element)
+		//	keywordArgs:
+		//		object containing the args for loadItem.	See dojo.data.api.Read.loadItem()
+	},
+
+	getFeatures: function(){
+		//	summary:
+		//		Return supported data APIs
+		//	returns:
+		//		"dojo.data.api.Read" and "dojo.data.api.Write"
+		var features = {
+			"dojo.data.api.Read": true
+		};
+		return features; //array
+	},
+
+	getLabel: function(/* item */ item){
+		//	summary:
+		//		See dojo.data.api.Read.getLabel()
+		if((this.label !== "") && this.isItem(item)){
+			var label = this.getValue(item,this.label);
+			if(label && label.text){
+				return label.text;
+			}else if(label){
+				return label.toString();
+			}else{
+				return undefined;
+			}
+		}
+		return undefined; //undefined
+	},
+
+	getLabelAttributes: function(/* item */ item){
+		//	summary:
+		//		See dojo.data.api.Read.getLabelAttributes()
+		if(this.label !== ""){
+			return [this.label]; //array
+		}
+		return null; //null
+	},
+
+	getFeedValue: function(attribute, defaultValue){
+		// summary:
+		//		Non-API method for retrieving values regarding the Atom feed,
+		//		rather than the Atom entries.
+		var values = this.getFeedValues(attribute, defaultValue);
+		if(dojo.isArray(values)){
+			return values[0];
+		}
+		return values;
+	},
+
+	getFeedValues: function(attribute, defaultValue){
+		// summary:
+		//		Non-API method for retrieving values regarding the Atom feed,
+		//		rather than the Atom entries.
+		if(!this.doc){
+			return defaultValue;
+		}
+		if(!this._feedMetaData){
+			this._feedMetaData = {
+				element: this.doc.getElementsByTagName("feed")[0],
+				store: this,
+				_attribs: {}
+			};
+			this._parseItem(this._feedMetaData);
+		}
+		return this._feedMetaData._attribs[attribute] || defaultValue;
+	},
+
+	_initItem: function(item){
+		// summary:
+		//		Initializes an item before it can be parsed.
+		if(!item._attribs){
+			item._attribs = {};
+		}
+	},
+
+	_fetchItems: function(request, fetchHandler, errorHandler){
+		// summary:
+		//		Retrieves the items from the Atom XML document.
+		var url = this._getFetchUrl(request);
+		if(!url){
+			errorHandler(new Error("No URL specified."));
+			return;
+		}
+		var localRequest = (!this.sendQuery ? request : null); // use request for _getItems()
+
+		var _this = this;
+		var docHandler = function(data){
+			_this.doc = data;
+			var items = _this._getItems(data, localRequest);
+			var query = request.query;
+			if(query){
+				if(query.id){
+					items = dojo.filter(items, function(item){
+						return (_this.getValue(item, "id") == query.id);
+					});
+				}else if(query.category){
+					items = dojo.filter(items, function(entry){
+						var cats = _this.getValues(entry, "category");
+						if(!cats){
+							return false;
+						}
+						return dojo.some(cats, "return item.term=='"+query.category+"'");
+					});
+				}
+			}
+
+			if(items && items.length > 0){
+				fetchHandler(items, request);
+			}else{
+				fetchHandler([], request);
+			}
+		};
+
+		if(this.doc){
+			docHandler(this.doc);
+		}else{
+			var getArgs = {
+				url: url,
+				handleAs: "xml",
+				preventCache: this.urlPreventCache
+			};
+			var getHandler = dojo.xhrGet(getArgs);
+			getHandler.addCallback(docHandler);
+
+			getHandler.addErrback(function(data){
+				errorHandler(data, request);
+			});
+		}
+	},
+
+	_getFetchUrl: function(request){
+		if(!this.sendQuery){
+			return this.url;
+		}
+		var query = request.query;
+		if(!query){
+			return this.url;
+		}
+		if(dojo.isString(query)){
+			return this.url + query;
+		}
+		var queryString = "";
+		for(var name in query){
+			var value = query[name];
+			if(value){
+				if(queryString){
+					queryString += "&";
+				}
+				queryString += (name + "=" + value);
+			}
+		}
+		if(!queryString){
+			return this.url;
+		}
+		//Check to see if the URL already has query params or not.
+		var fullUrl = this.url;
+		if(fullUrl.indexOf("?") < 0){
+			fullUrl += "?";
+		}else{
+			fullUrl += "&";
+		}
+		return fullUrl + queryString;
+	},
+
+	_getItems: function(document, request){
+		// summary:
+		//		Parses the document in a first pass
+		if(this._items){
+			return this._items;
+		}
+		var items = [];
+		var nodes = [];
+
+		if(document.childNodes.length < 1){
+			this._items = items;
+			console.log("dojox.data.AtomReadStore: Received an invalid Atom document. Check the content type header");
+			return items;
+		}
+
+		var feedNodes = dojo.filter(document.childNodes, "return item.tagName && item.tagName.toLowerCase() == 'feed'");
+
+		var query = request.query;
+
+		if(!feedNodes || feedNodes.length != 1){
+			console.log("dojox.data.AtomReadStore: Received an invalid Atom document, number of feed tags = " + (feedNodes? feedNodes.length : 0));
+			return items;
+		}
+
+		nodes = dojo.filter(feedNodes[0].childNodes, "return item.tagName && item.tagName.toLowerCase() == 'entry'");
+
+		if(request.onBegin){
+			request.onBegin(nodes.length, this.sendQuery ? request : {});
+		}
+
+		for(var i = 0; i < nodes.length; i++){
+			var node = nodes[i];
+			if(node.nodeType != 1 /*ELEMENT_NODE*/){
+				continue;
+			}
+			items.push(this._getItem(node));
+		}
+		this._items = items;
+		return items;
+	},
+
+	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+		 //	summary:
+		 //		See dojo.data.api.Read.close()
+	},
+
+/* internal API */
+
+	_getItem: function(element){
+		return {
+			element: element,
+			store: this
+		};
+	},
+
+	_parseItem: function(item){
+		var attribs = item._attribs;
+		var _this = this;
+		var text, type;
+
+		function getNodeText(node){
+			var txt = node.textContent || node.innerHTML || node.innerXML;
+			if(!txt && node.childNodes[0]){
+				var child = node.childNodes[0];
+				if(child && (child.nodeType == 3 || child.nodeType == 4)){
+					txt = node.childNodes[0].nodeValue;
+				}
+			}
+			return txt;
+		}
+		function parseTextAndType(node){
+			return {text: getNodeText(node),type: node.getAttribute("type")};
+		}
+		dojo.forEach(item.element.childNodes, function(node){
+			var tagName = node.tagName ? node.tagName.toLowerCase() : "";
+			switch(tagName){
+				case "title":
+					attribs[tagName] = {
+						text: getNodeText(node),
+						type: node.getAttribute("type")
+					}; break;
+				case "subtitle":
+				case "summary":
+				case "content":
+					attribs[tagName] = parseTextAndType(node);
+					break;
+				case "author":
+					var nameNode ,uriNode;
+					dojo.forEach(node.childNodes, function(child){
+						if(!child.tagName){
+							return;
+						}
+						switch(child.tagName.toLowerCase()){
+							case "name":
+								nameNode = child;
+								break;
+							case "uri": 
+								uriNode = child; 
+								break;
+						}
+					});
+					var author = {};
+					if(nameNode && nameNode.length == 1){
+						author.name = getNodeText(nameNode[0]);
+					}
+					if(uriNode && uriNode.length == 1){
+						author.uri = getNodeText(uriNode[0]);
+					}
+					attribs[tagName] = author;
+					break;
+				case "id": 
+					attribs[tagName] = getNodeText(node); 
+					break;
+				case "updated": 
+					attribs[tagName] = dojo.date.stamp.fromISOString(getNodeText(node) );
+					break;
+				case "published": 
+					attribs[tagName] = dojo.date.stamp.fromISOString(getNodeText(node));
+					break;
+				case "category":
+					if(!attribs[tagName]){
+						attribs[tagName] = [];
+					}
+					attribs[tagName].push({scheme:node.getAttribute("scheme"), term: node.getAttribute("term")});
+					break;
+				case "link":
+					if(!attribs[tagName]){
+						attribs[tagName] = [];
+					}
+					var link = {
+						rel: node.getAttribute("rel"),
+						href: node.getAttribute("href"),
+						type: node.getAttribute("type")};
+					attribs[tagName].push(link);
+
+					if(link.rel == "alternate"){
+						attribs["alternate"] = link;
+					}
+					break;
+				default:
+					break;
+			}
+		});
+	},
+
+	_unescapeHTML : function(text){
+		//Replace HTML character codes with their unencoded equivalents, e.g. ’ with '
+		text = text.replace(/’/m , "'").replace(/″/m , "\"").replace(/</m,">").replace(/>/m,"<").replace(/&/m,"&");
+		return text;
+	},
+
+	_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("dojox.data.AtomReadStore: 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("dojox.data.AtomReadStore: Invalid attribute argument.");
+		}
+	}
 });
-},_unescapeHTML:function(_50){
-_50=_50.replace(/’/m,"'").replace(/″/m,"\"").replace(/</m,">").replace(/>/m,"<").replace(/&/m,"&");
-return _50;
-},_assertIsItem:function(_51){
-if(!this.isItem(_51)){
-throw new Error("dojox.data.AtomReadStore: Invalid item argument.");
-}
-},_assertIsAttribute:function(_52){
-if(typeof _52!=="string"){
-throw new Error("dojox.data.AtomReadStore: Invalid attribute argument.");
-}
-}});
 dojo.extend(dojox.data.AtomReadStore,dojo.data.util.simpleFetch);
-}
diff --git a/dojox/data/CdfStore.js b/dojox/data/CdfStore.js
old mode 100644
new mode 100755
index b7596f8..20d414d
--- a/dojox/data/CdfStore.js
+++ b/dojox/data/CdfStore.js
@@ -1,318 +1,597 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.CdfStore"]){
-dojo._hasResource["dojox.data.CdfStore"]=true;
 dojo.provide("dojox.data.CdfStore");
 dojo.require("dojo.data.util.sorter");
-dojox.data.ASYNC_MODE=0;
-dojox.data.SYNC_MODE=1;
-dojo.declare("dojox.data.CdfStore",null,{identity:"jsxid",url:"",xmlStr:"",data:null,label:"",mode:dojox.data.ASYNC_MODE,constructor:function(_1){
-if(_1){
-this.url=_1.url;
-this.xmlStr=_1.xmlStr||_1.str;
-if(_1.data){
-this.xmlStr=this._makeXmlString(_1.data);
-}
-this.identity=_1.identity||this.identity;
-this.label=_1.label||this.label;
-this.mode=_1.mode!==undefined?_1.mode:this.mode;
-}
-this._modifiedItems={};
-this.byId=this.fetchItemByIdentity;
-},getValue:function(_2,_3,_4){
-return _2.getAttribute(_3)||_4;
-},getValues:function(_5,_6){
-var v=this.getValue(_5,_6,[]);
-return dojo.isArray(v)?v:[v];
-},getAttributes:function(_7){
-return _7.getAttributeNames();
-},hasAttribute:function(_8,_9){
-return (this.getValue(_8,_9)!==undefined);
-},hasProperty:function(_a,_b){
-return this.hasAttribute(_a,_b);
-},containsValue:function(_c,_d,_e){
-var _f=this.getValues(_c,_d);
-for(var i=0;i<_f.length;i++){
-if(_f[i]===null){
-continue;
-}
-if((typeof _e==="string")){
-if(_f[i].toString&&_f[i].toString()===_e){
-return true;
-}
-}else{
-if(_f[i]===_e){
-return true;
-}
-}
-}
-return false;
-},isItem:function(_10){
-if(_10.getClass&&_10.getClass().equals(jsx3.xml.Entity.jsxclass)){
-return true;
-}
-return false;
-},isItemLoaded:function(_11){
-return this.isItem(_11);
-},loadItem:function(_12){
-},getFeatures:function(){
-return {"dojo.data.api.Read":true,"dojo.data.api.Write":true,"dojo.data.api.Identity":true};
-},getLabel:function(_13){
-if((this.label!=="")&&this.isItem(_13)){
-var _14=this.getValue(_13,this.label);
-if(_14){
-return _14.toString();
-}
-}
-return undefined;
-},getLabelAttributes:function(_15){
-if(this.label!==""){
-return [this.label];
-}
-return null;
-},fetch:function(_16){
-_16=_16||{};
-if(!_16.store){
-_16.store=this;
-}
-if(_16.mode!==undefined){
-this.mode=_16.mode;
-}
-var _17=this;
-var _18=function(_19){
-if(_16.onError){
-var _1a=_16.scope||dojo.global;
-_16.onError.call(_1a,_19,_16);
-}else{
-console.error("cdfStore Error:",_19);
-}
-};
-var _1b=function(_1c,_1d){
-_1d=_1d||_16;
-var _1e=_1d.abort||null;
-var _1f=false;
-var _20=_1d.start?_1d.start:0;
-var _21=(_1d.count&&(_1d.count!==Infinity))?(_20+_1d.count):_1c.length;
-_1d.abort=function(){
-_1f=true;
-if(_1e){
-_1e.call(_1d);
-}
-};
-var _22=_1d.scope||dojo.global;
-if(!_1d.store){
-_1d.store=_17;
-}
-if(_1d.onBegin){
-_1d.onBegin.call(_22,_1c.length,_1d);
-}
-if(_1d.sort){
-_1c.sort(dojo.data.util.sorter.createSortFunction(_1d.sort,_17));
-}
-if(_1d.onItem){
-for(var i=_20;(i<_1c.length)&&(i<_21);++i){
-var _23=_1c[i];
-if(!_1f){
-_1d.onItem.call(_22,_23,_1d);
-}
-}
-}
-if(_1d.onComplete&&!_1f){
-if(!_1d.onItem){
-_1c=_1c.slice(_20,_21);
-if(_1d.byId){
-_1c=_1c[0];
-}
-}
-_1d.onComplete.call(_22,_1c,_1d);
-}else{
-_1c=_1c.slice(_20,_21);
-if(_1d.byId){
-_1c=_1c[0];
-}
-}
-return _1c;
-};
-if(!this.url&&!this.data&&!this.xmlStr){
-_18(new Error("No URL or data specified."));
-return false;
-}
-var _24=_16||"*";
-if(this.mode==dojox.data.SYNC_MODE){
-var res=this._loadCDF();
-if(res instanceof Error){
-if(_16.onError){
-_16.onError.call(_16.scope||dojo.global,res,_16);
-}else{
-console.error("CdfStore Error:",res);
-}
-return res;
-}
-this.cdfDoc=res;
-var _25=this._getItems(this.cdfDoc,_24);
-if(_25&&_25.length>0){
-_25=_1b(_25,_16);
-}else{
-_25=_1b([],_16);
-}
-return _25;
-}else{
-var dfd=this._loadCDF();
-dfd.addCallbacks(dojo.hitch(this,function(_26){
-var _27=this._getItems(this.cdfDoc,_24);
-if(_27&&_27.length>0){
-_1b(_27,_16);
-}else{
-_1b([],_16);
-}
-}),dojo.hitch(this,function(err){
-_18(err,_16);
-}));
-return dfd;
-}
-},_loadCDF:function(){
-var dfd=new dojo.Deferred();
-if(this.cdfDoc){
-if(this.mode==dojox.data.SYNC_MODE){
-return this.cdfDoc;
-}else{
-setTimeout(dojo.hitch(this,function(){
-dfd.callback(this.cdfDoc);
-}),0);
-return dfd;
-}
-}
-this.cdfDoc=jsx3.xml.CDF.Document.newDocument();
-this.cdfDoc.subscribe("response",this,function(evt){
-dfd.callback(this.cdfDoc);
-});
-this.cdfDoc.subscribe("error",this,function(err){
-dfd.errback(err);
+
+dojox.data.ASYNC_MODE = 0;
+dojox.data.SYNC_MODE = 1;
+
+dojo.declare("dojox.data.CdfStore", null, {
+	//	summary:
+	//		IMPORTANT: The CDF Store is designed to work with Tibco GI, and references Tibco's
+	//		JSX3 JavaScript library and will not work without it.
+	//
+	//		The CDF Store implements dojo.data.Read, Write, and Identity api's.  It is a local
+	//		(in memory) store that handles XML documents formatted according to the
+	//		Common Data Format (CDF) spec:
+	//		http://www.tibco.com/devnet/resources/gi/3_1/tips_and_techniques/CommonDataFormatCDF.pdf
+	//
+	//		The purpose of this store is to provide a glue between a jsx3 CDF file and a Dijit.
+	//
+	//		While a CDF document is an XML file, other than the initial input, all data returned
+	//		from and written to this store should be in object format.
+	//		
+	// identity: [const] String
+	//		The unique identifier for each item. Defaults to "jsxid" which is standard for a CDF
+	//		document. Should not be changed.
+	identity: "jsxid",
+	//
+	//	url : String 
+	//		The location from which to fetch the XML (CDF) document.
+	url: "",
+	//
+	//	xmlStr: String
+	//		A string that can be parsed into an XML document and should be formatted according
+	//		to the CDF spec.
+	//	example:
+	//		|	'<data jsxid="jsxroot"><record jsxtext="A"/><record jsxtext="B" jsxid="2" jsxid="2"/></data>'
+	xmlStr:"",
+	//
+	//	data:	Object
+	//		A object that will be converted into the xmlStr property, and then parsed into a CDF.
+	data:null,
+	//
+	//	label:	String
+	//		The property within each item used to define the item.
+	label: "",
+	//
+	//	mode [const]: dojox.data.ASYNC_MODE | dojox.data.SYNC_MODE
+	//		This store supports syncronous fetches if this property is set to dojox.data.SYNC_MODE.
+	mode:dojox.data.ASYNC_MODE,
+	
+	constructor: function(/* Object */ args){
+		// summary:
+		//	Constructor for the CDF store. Instantiate a new CdfStore. 
+		//
+		if(args){
+			this.url = args.url;
+			this.xmlStr = args.xmlStr || args.str;
+			if(args.data){
+				this.xmlStr = this._makeXmlString(args.data);
+			}
+			this.identity = args.identity || this.identity;
+			this.label = args.label || this.label;
+			this.mode = args.mode !== undefined ? args.mode : this.mode;
+		}
+		this._modifiedItems = {};
+		
+		this.byId = this.fetchItemByIdentity;
+	},
+	
+	/* dojo.data.api.Read */
+
+	getValue: function(/* jsx3.xml.Entity */ item, /* String */ property, /* value? */ defaultValue){
+		//	summary:
+		//		Return an property value of an item
+		//
+		return item.getAttribute(property) || defaultValue; // anything
+	},
+
+	getValues: function(/* jsx3.xml.Entity */ item, /* String */ property){
+		//	summary:
+		//		Return an array of values
+		//
+		//	TODO!!! Can't find an example of an array in any CDF files
+		//
+		var v = this.getValue(item, property, []);
+		return dojo.isArray(v) ? v : [v];
+	},
+
+	getAttributes: function(/* jsx3.xml.Entity */ item){
+		//	summary:
+		//		Return an array of property names
+		//
+		return item.getAttributeNames(); // Array
+	},
+
+	hasAttribute: function(/* jsx3.xml.Entity */ item, /* String */ property){
+		//	summary:
+		//		Check whether an item has a property
+		//
+		return (this.getValue(item, property) !== undefined); // Boolean
+	},
+	
+	hasProperty: function(/* jsx3.xml.Entity */ item, /* String */ property){
+		// summary:
+		//	Alias for hasAttribute
+		return this.hasAttribute(item, property);
+	},
+	
+	containsValue: function(/* jsx3.xml.Entity */ item, /* String */ property, /* anything */ value){
+		//	summary:
+		//		Check whether an item contains a value
+		//
+		var values = this.getValues(item, property);
+		for(var i = 0; i < values.length; i++){
+			if(values[i] === null){ continue; }
+			if((typeof value === "string")){
+				if(values[i].toString && values[i].toString() === value){
+					return true;
+				}
+			}else if(values[i] === value){
+				return true; //boolean
+			}
+		}
+		return false;//boolean
+	},
+
+	isItem: function(/* anything */ something){
+		//	summary:
+		//		Check whether the object is an item (jsx3.xml.Entity)
+		//
+		if(something.getClass && something.getClass().equals(jsx3.xml.Entity.jsxclass)){
+			return true; //boolean
+		}
+		return false; //boolran
+	},
+
+	isItemLoaded: function(/* anything */ something){
+		//	summary:
+		//		Check whether the object is a jsx3.xml.Entity object and loaded
+		//
+		return this.isItem(something); // Boolean
+	},
+
+	loadItem: function(/* object */ keywordArgs){
+		//	summary:
+		//		Load an item
+		//	description:
+		//		The store always loads all items, so if it's an item, then it's loaded.
+	},
+
+	getFeatures: function(){
+		//	summary:
+		//		Return supported data APIs
+		//
+		return {
+			"dojo.data.api.Read": true,
+			"dojo.data.api.Write": true,
+			"dojo.data.api.Identity":true
+		}; // Object
+	},
+
+	getLabel: function(/* jsx3.xml.Entity */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabel()
+		//
+		if((this.label !== "") && this.isItem(item)){
+			var label = this.getValue(item,this.label);
+			if(label){
+				return label.toString();
+			}
+		}
+		return undefined; //undefined
+	},
+
+	getLabelAttributes: function(/* jsx3.xml.Entity */ item){
+		//	summary:
+		//		returns an array of what properties of the item that were used
+		//      to generate its label
+		//		See dojo.data.api.Read.getLabelAttributes()
+		//
+		if(this.label !== ""){
+			return [this.label]; //array
+		}
+		return null; //null
+	},
+
+	
+	fetch: function(/* Object? */ request){
+		// summary:
+		//		Returns an Array of items based on the request arguments.
+		// description:
+		//		Returns an Array of items based on the request arguments.
+		//		If the store is in ASYNC mode, the items should be expected in an onComplete
+		//		method passed in the request object. If store is in SYNC mode, the items will
+		//		be return directly as well as within the onComplete method.
+		//	note:
+		//		The mode can be set on store initialization or during a fetch as one of the
+		//		parameters.
+		//
+		//	query: String
+		//		The items in the store are treated as objects, but this is reading an XML
+		//		document. Further, the actual querying of the items takes place in Tibco GI's
+		//		jsx3.xml.Entity. Therefore, we are using their syntax which is xpath.
+		//	Note:
+		//		As conforming to a CDF document, most, if not all nodes are considered "records"
+		//		and their tagNames are as such. The root node is named "data".
+		//
+		//	examples:
+		//		All items:
+		//		|	store.fetch({query:"*"});
+		//		Item with a jsxid attribute equal to "1" (note you could use byId for this)
+		//		|	store.fetch({query:"//record[@jsxid='1']"});
+		//		All items with any jsxid attribute:
+		//		|	"//record[@jsxid='*']"
+		//		The items with a jsxid of '1' or '4':
+		//		|	"//record[@jsxid='4' or @jsxid='1']"
+		//		All children within a "group" node (could be multiple group nodes):
+		//		"//group/record"
+		//		All children within a specific group node:
+		//		"//group[@name='mySecondGroup']/record"
+		//		Any record, anywhere in the document:
+		//		|	"//record"
+		//		Only the records beneath the root (data) node:
+		//		|	"//data/record"
+		//		
+		//	See:
+		//	http://www.tibco.com/devnet/resources/gi/3_7/api/html/jsx3/xml/Entity.html#method:selectNodes
+		//	http://www.w3.org/TR/xpath
+		//	http://msdn.microsoft.com/en-us/library/ms256086.aspx
+		//
+		//	See dojo.data.Read.fetch():
+		//	onBegin
+		//	onComplete
+		//	onItem
+		//	onError
+		//	scope
+		//	start
+		//	count
+		//	sort
+		//
+		request = request || {};
+		if(!request.store){
+			request.store = this;
+		}
+		if(request.mode !== undefined){
+			this.mode = request.mode;
+		}
+		var self = this;
+	
+		var errorHandler = function(errorData){
+			if(request.onError){
+				var scope = request.scope || dojo.global;
+				request.onError.call(scope, errorData, request);
+			}else{
+				console.error("cdfStore Error:", errorData);
+			}
+		};
+	
+		var fetchHandler = function(items, requestObject){
+			requestObject = requestObject || request;
+			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){
+				if(!requestObject.onItem){
+					items = items.slice(startIndex, endIndex);
+					if(requestObject.byId){
+						items = items[0];	
+					}
+				}
+				requestObject.onComplete.call(scope, items, requestObject);
+			}else{
+				items = items.slice(startIndex, endIndex);
+				if(requestObject.byId){
+					items = items[0];	
+				}
+			}
+			return items;
+		};
+		
+		if(!this.url && !this.data && !this.xmlStr){
+			errorHandler(new Error("No URL or data specified."));
+			return false;
+		}
+		var localRequest = request || "*"; // use request for _getItems()
+		
+		if(this.mode == dojox.data.SYNC_MODE){
+			// sync mode. items returned directly	
+			var res = this._loadCDF();
+			if(res instanceof Error){
+				if(request.onError){
+					request.onError.call(request.scope || dojo.global, res, request);
+				}else{
+					console.error("CdfStore Error:", res);
+				}
+				return res;
+			}
+			this.cdfDoc = res;
+			
+			var items = this._getItems(this.cdfDoc, localRequest);
+			if(items && items.length > 0){
+				items = fetchHandler(items, request);
+			}else{
+				items = fetchHandler([], request);
+			}
+			return items;
+		
+		}else{
+			
+			// async mode. Return a Deferred.			
+			var dfd = this._loadCDF();
+			dfd.addCallbacks(dojo.hitch(this, function(cdfDoc){
+				var items = this._getItems(this.cdfDoc, localRequest);
+				if(items && items.length > 0){
+					fetchHandler(items, request);
+				}else{
+					fetchHandler([], request);
+				}
+			}),
+			dojo.hitch(this, function(err){
+				errorHandler(err, request);
+			}));
+			
+			return dfd;	// Object
+		}
+	},
+
+	
+	_loadCDF: function(){
+		//	summary:
+		//		Internal method.
+		//		If a cdfDoc exists, return it. Otherwise, get one from JSX3,
+		//		load the data or url, and return the doc or a deferred.
+		var dfd = new dojo.Deferred();
+		if(this.cdfDoc){
+			if(this.mode == dojox.data.SYNC_MODE){
+				return this.cdfDoc; // jsx3.xml.CDF
+			}else{
+				setTimeout(dojo.hitch(this, function(){
+					dfd.callback(this.cdfDoc);
+				}), 0);
+				return dfd; // dojo.Deferred
+			}
+		}
+		
+		this.cdfDoc = jsx3.xml.CDF.Document.newDocument();
+		this.cdfDoc.subscribe("response", this, function(evt){
+			dfd.callback(this.cdfDoc);
+		});
+		this.cdfDoc.subscribe("error", this, function(err){
+			dfd.errback(err);
+		});
+		
+		this.cdfDoc.setAsync(!this.mode);
+		if(this.url){
+			this.cdfDoc.load(this.url);
+		}else if(this.xmlStr){
+			this.cdfDoc.loadXML(this.xmlStr);
+			if(this.cdfDoc.getError().code){
+				return new Error(this.cdfDoc.getError().description); // Error
+			}
+		}
+		
+		if(this.mode == dojox.data.SYNC_MODE){
+			return this.cdfDoc; // jsx3.xml.CDF
+		}else{
+			return dfd;			// dojo.Deferred
+		}
+	},
+	
+	_getItems: function(/* jsx3.xml.Entity */cdfDoc, /* Object */request){
+		// summary:
+		//		Internal method.
+		//		Requests the items from jsx3.xml.Entity with an xpath query.
+		//
+		var itr = cdfDoc.selectNodes(request.query, false, 1);
+		var items = [];
+		while(itr.hasNext()){
+			items.push(itr.next());
+		}
+		return items;
+	},
+
+	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+		 //	summary: 
+		 //		See dojo.data.api.Read.close()
+	},
+
+/* dojo.data.api.Write */
+
+	newItem: function(/* object? */ keywordArgs, /* object? || String? */parentInfo){
+		//	summary:
+		//		Creates a jsx3.xml.Entity item and inserts it either inside the
+		//		parent or appends it to the root
+		//
+		keywordArgs = (keywordArgs || {});
+		if(keywordArgs.tagName){
+			// record tagName is automatic and this would add it
+			// as a property
+			if(keywordArgs.tagName!="record"){
+				// TODO: How about some sort of group?
+				console.warn("Only record inserts are supported at this time");
+			}
+			delete keywordArgs.tagName;
+		}
+		keywordArgs.jsxid = keywordArgs.jsxid || this.cdfDoc.getKey();
+		if(this.isItem(parentInfo)){
+			parentInfo = this.getIdentity(parentInfo);
+		}
+		var item = this.cdfDoc.insertRecord(keywordArgs, parentInfo);
+
+		this._makeDirty(item);
+		
+		return item; // jsx3.xml.Entity
+	},
+	
+	deleteItem: function(/* jsx3.xml.Entity */ item){
+		//	summary:
+		//		Delete an jsx3.xml.Entity (wrapper to a XML element).
+		//
+		this.cdfDoc.deleteRecord(this.getIdentity(item));
+		this._makeDirty(item);
+		return true; //boolean
+	},
+	
+	setValue: function(/* jsx3.xml.Entity */ item, /* String */ property, /* almost anything */ value){
+		//	summary:
+		//		Set an property value
+		//
+		this._makeDirty(item);
+		item.setAttribute(property, value);
+		return true; // Boolean
+	},
+		
+	setValues: function(/* jsx3.xml.Entity */ item, /* String */ property, /*array*/ values){
+		//	summary:
+		//		Set property values
+		//		TODO: Needs to be fully implemented.
+		//
+		this._makeDirty(item);
+		console.warn("cdfStore.setValues only partially implemented.");
+		return item.setAttribute(property, values);
+		
+	},
+	
+	unsetAttribute: function(/* jsx3.xml.Entity */ item, /* String */ property){
+		//	summary:
+		//		Remove an property
+		//
+		this._makeDirty(item);
+		item.removeAttribute(property);
+		return true; // Boolean
+	},
+	
+	revert: function(){
+		// summary:
+		//		Invalidate changes (new and/or modified elements)
+		//		Resets data by simply deleting the reference to the cdfDoc.
+		//		Subsequent fetches will load the new data.
+		// Note:
+		//		Any items outside the store will no longer be valid and may cause errors.
+		//
+		delete this.cdfDoc;
+		this._modifiedItems = {};
+		return true; //boolean
+	},
+	
+	isDirty: function(/* jsx3.xml.Entity ? */ item){
+		//	summary:
+		//		Check whether an item is new, modified or deleted.
+		//		If no item is passed, checks if anything in the store has changed.
+		//
+		if(item){
+			return !!this._modifiedItems[this.getIdentity(item)]; // Boolean
+		}else{
+			var _dirty = false;
+			for(var nm in this._modifiedItems){ _dirty = true; break; }
+			return _dirty; // Boolean
+		}
+	},
+
+	
+
+/* internal API */
+
+	_makeDirty: function(item){
+		// summary:
+		//		Internal method.
+		//		Marks items as modified, deleted or new.
+		var id = this.getIdentity(item);
+		this._modifiedItems[id] = item;	
+	},
+	
+	
+	_makeXmlString: function(obj){
+		// summary:
+		//		Internal method.
+		//		Converts an object into an XML string.
+		//
+		var parseObj = function(obj, name){
+			var xmlStr = "";
+			var nm;
+			if(dojo.isArray(obj)){
+				for(var i=0;i<obj.length;i++){
+					xmlStr += parseObj(obj[i], name);
+				}
+			}else if(dojo.isObject(obj)){
+				xmlStr += '<'+name+' ';
+				for(nm in obj){
+					if(!dojo.isObject(obj[nm])){
+						xmlStr += nm+'="'+obj[nm]+'" ';
+					}
+				}
+				xmlStr +='>';
+				for(nm in obj){
+					if(dojo.isObject(obj[nm])){
+						xmlStr += parseObj(obj[nm], nm);
+					}
+				}
+				xmlStr += '</'+name+'>';
+			}
+			return xmlStr;
+		};
+		return parseObj(obj, "data");
+	},
+
+	/*************************************
+	 * Dojo.data Identity implementation *
+	 *************************************/
+	getIdentity: function(/* jsx3.xml.Entity */ item){
+		//	summary:
+		//		Returns the identifier for an item.  
+		//
+		return this.getValue(item, this.identity); // String
+	},
+
+	getIdentityAttributes: function(/* jsx3.xml.Entity */ item){
+		//	summary:
+		//		Returns the property used for the identity.
+		//
+		return [this.identity]; // Array
+	},
+
+
+	fetchItemByIdentity: function(/* Object || String */ args){
+		//	summary:
+		//		See dojo.data.api.Identity.fetchItemByIdentity(keywordArgs)
+		//
+		//	Note:
+		//		This method can be synchronous if mode is set.
+		//		Also, there is a more finger friendly alias of this method, byId();
+		if(dojo.isString(args)){
+			var id = args;
+			args = {query:"//record[@jsxid='"+id+"']", mode: dojox.data.SYNC_MODE};
+		}else{
+			if(args){
+				args.query = "//record[@jsxid='"+args.identity+"']";
+			}
+			if(!args.mode){args.mode = this.mode;}
+		}
+		args.byId = true;
+		return this.fetch(args); // dojo.Deferred || Array
+	},
+	byId: function(/* Object || String */ args){
+		// stub. See fetchItemByIdentity
+	}
+	
 });
-this.cdfDoc.setAsync(!this.mode);
-if(this.url){
-this.cdfDoc.load(this.url);
-}else{
-if(this.xmlStr){
-this.cdfDoc.loadXML(this.xmlStr);
-if(this.cdfDoc.getError().code){
-return new Error(this.cdfDoc.getError().description);
-}
-}
-}
-if(this.mode==dojox.data.SYNC_MODE){
-return this.cdfDoc;
-}else{
-return dfd;
-}
-},_getItems:function(_28,_29){
-var itr=_28.selectNodes(_29.query,false,1);
-var _2a=[];
-while(itr.hasNext()){
-_2a.push(itr.next());
-}
-return _2a;
-},close:function(_2b){
-},newItem:function(_2c,_2d){
-_2c=(_2c||{});
-if(_2c.tagName){
-if(_2c.tagName!="record"){
-console.warn("Only record inserts are supported at this time");
-}
-delete _2c.tagName;
-}
-_2c.jsxid=_2c.jsxid||this.cdfDoc.getKey();
-if(this.isItem(_2d)){
-_2d=this.getIdentity(_2d);
-}
-var _2e=this.cdfDoc.insertRecord(_2c,_2d);
-this._makeDirty(_2e);
-return _2e;
-},deleteItem:function(_2f){
-this.cdfDoc.deleteRecord(this.getIdentity(_2f));
-this._makeDirty(_2f);
-return true;
-},setValue:function(_30,_31,_32){
-this._makeDirty(_30);
-_30.setAttribute(_31,_32);
-return true;
-},setValues:function(_33,_34,_35){
-this._makeDirty(_33);
-console.warn("cdfStore.setValues only partially implemented.");
-return _33.setAttribute(_34,_35);
-},unsetAttribute:function(_36,_37){
-this._makeDirty(_36);
-_36.removeAttribute(_37);
-return true;
-},revert:function(){
-delete this.cdfDoc;
-this._modifiedItems={};
-return true;
-},isDirty:function(_38){
-if(_38){
-return !!this._modifiedItems[this.getIdentity(_38)];
-}else{
-var _39=false;
-for(var nm in this._modifiedItems){
-_39=true;
-break;
-}
-return _39;
-}
-},_makeDirty:function(_3a){
-var id=this.getIdentity(_3a);
-this._modifiedItems[id]=_3a;
-},_makeXmlString:function(obj){
-var _3b=function(obj,_3c){
-var _3d="";
-var nm;
-if(dojo.isArray(obj)){
-for(var i=0;i<obj.length;i++){
-_3d+=_3b(obj[i],_3c);
-}
-}else{
-if(dojo.isObject(obj)){
-_3d+="<"+_3c+" ";
-for(nm in obj){
-if(!dojo.isObject(obj[nm])){
-_3d+=nm+"=\""+obj[nm]+"\" ";
-}
-}
-_3d+=">";
-for(nm in obj){
-if(dojo.isObject(obj[nm])){
-_3d+=_3b(obj[nm],nm);
-}
-}
-_3d+="</"+_3c+">";
-}
-}
-return _3d;
-};
-return _3b(obj,"data");
-},getIdentity:function(_3e){
-return this.getValue(_3e,this.identity);
-},getIdentityAttributes:function(_3f){
-return [this.identity];
-},fetchItemByIdentity:function(_40){
-if(dojo.isString(_40)){
-var id=_40;
-_40={query:"//record[@jsxid='"+id+"']",mode:dojox.data.SYNC_MODE};
-}else{
-if(_40){
-_40.query="//record[@jsxid='"+_40.identity+"']";
-}
-if(!_40.mode){
-_40.mode=this.mode;
-}
-}
-_40.byId=true;
-return this.fetch(_40);
-},byId:function(_41){
-}});
-}
+
diff --git a/dojox/data/ClientFilter.js b/dojox/data/ClientFilter.js
index f160a90..0d90248 100644
--- a/dojox/data/ClientFilter.js
+++ b/dojox/data/ClientFilter.js
@@ -1,187 +1,292 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.ClientFilter"]){
-dojo._hasResource["dojox.data.ClientFilter"]=true;
 dojo.provide("dojox.data.ClientFilter");
-dojo.require("dojo.data.util.filter");
+dojo.require("dojo.data.util.filter"); 
+// This is an abstract data store module for adding updateable result set functionality to an existing data store class
 (function(){
-var cf;
-var _1=function(_2,_3,_4){
-return function(_5){
-_2._updates.push({create:_3&&_5,remove:_4&&_5});
-cf.onUpdate();
-};
-};
-cf=dojo.declare("dojox.data.ClientFilter",null,{cacheByDefault:false,constructor:function(){
-this.onSet=_1(this,true,true);
-this.onNew=_1(this,true,false);
-this.onDelete=_1(this,false,true);
-this._updates=[];
-this._fetchCache=[];
-},clearCache:function(){
-this._fetchCache=[];
-},updateResultSet:function(_6,_7){
-if(this.isUpdateable(_7)){
-for(var i=_7._version||0;i<this._updates.length;i++){
-var _8=this._updates[i].create;
-var _9=this._updates[i].remove;
-if(_9){
-for(var j=0;j<_6.length;j++){
-if(_6[j]==_9){
-_6.splice(j--,1);
-var _a=true;
-}
-}
-}
-if(_8&&this.matchesQuery(_8,_7)&&dojo.indexOf(_6,_8)==-1){
-_6.push(_8);
-_a=true;
-}
-}
-if(_7.sort&&_a){
-_6.sort(this.makeComparator(_7.sort.concat()));
-}
-_6._fullLength=_6.length;
-if(_7.count&&_a&&_7.count!==Infinity){
-_6.splice(_7.count,_6.length);
-}
-_7._version=this._updates.length;
-return _a?2:1;
-}
-return 0;
-},querySuperSet:function(_b,_c){
-if(_b.query==_c.query){
-return {};
-}
-if(!(_c.query instanceof Object&&(!_b.query||typeof _b.query=="object"))){
-return false;
-}
-var _d=dojo.mixin({},_c.query);
-for(var i in _b.query){
-if(_d[i]==_b.query[i]){
-delete _d[i];
-}else{
-if(!(typeof _b.query[i]=="string"&&dojo.data.util.filter.patternToRegExp(_b.query[i]).test(_d[i]))){
-return false;
-}
-}
-}
-return _d;
-},serverVersion:0,cachingFetch:function(_e){
-var _f=this;
-for(var i=0;i<this._fetchCache.length;i++){
-var _10=this._fetchCache[i];
-var _11=this.querySuperSet(_10,_e);
-if(_11!==false){
-var _12=_10._loading;
-if(!_12){
-_12=new dojo.Deferred();
-_12.callback(_10.cacheResults);
-}
-_12.addCallback(function(_13){
-_13=_f.clientSideFetch(dojo.mixin(dojo.mixin({},_e),{query:_11}),_13);
-_12.fullLength=_13._fullLength;
-return _13;
-});
-_e._version=_10._version;
-break;
-}
-}
-if(!_12){
-var _14=dojo.mixin({},_e);
-var _15=(_e.queryOptions||0).cache;
-var _16=this._fetchCache;
-if(_15===undefined?this.cacheByDefault:_15){
-if(_e.start||_e.count){
-delete _14.start;
-delete _14.count;
-_e.clientQuery=dojo.mixin(_e.clientQuery||{},{start:_e.start,count:_e.count});
-}
-_e=_14;
-_16.push(_e);
-}
-_12=_e._loading=this._doQuery(_e);
-_12.addErrback(function(){
-_16.splice(dojo.indexOf(_16,_e),1);
-});
-}
-var _17=this.serverVersion;
-_12.addCallback(function(_18){
-delete _e._loading;
-if(_18){
-_e._version=typeof _e._version=="number"?_e._version:_17;
-_f.updateResultSet(_18,_e);
-_e.cacheResults=_18;
-if(!_e.count||_18.length<_e.count){
-_12.fullLength=((_e.start)?_e.start:0)+_18.length;
-}
-}
-return _18;
-});
-return _12;
-},isUpdateable:function(_19){
-return typeof _19.query=="object";
-},clientSideFetch:function(_1a,_1b){
-if(_1a.queryOptions&&_1a.queryOptions.results){
-_1b=_1a.queryOptions.results;
-}
-if(_1a.query){
-var _1c=[];
-for(var i=0;i<_1b.length;i++){
-var _1d=_1b[i];
-if(_1d&&this.matchesQuery(_1d,_1a)){
-_1c.push(_1b[i]);
-}
-}
-}else{
-_1c=_1a.sort?_1b.concat():_1b;
-}
-if(_1a.sort){
-_1c.sort(this.makeComparator(_1a.sort.concat()));
-}
-return this.clientSidePaging(_1a,_1c);
-},clientSidePaging:function(_1e,_1f){
-var _20=_1e.start||0;
-var _21=(_20||_1e.count)?_1f.slice(_20,_20+(_1e.count||_1f.length)):_1f;
-_21._fullLength=_1f.length;
-return _21;
-},matchesQuery:function(_22,_23){
-var _24=_23.query;
-var _25=_23.queryOptions&&_23.queryOptions.ignoreCase;
-for(var i in _24){
-var _26=_24[i];
-var _27=this.getValue(_22,i);
-if((typeof _26=="string"&&(_26.match(/[\*\.]/)||_25))?!dojo.data.util.filter.patternToRegExp(_26,_25).test(_27):_27!=_26){
-return false;
-}
-}
-return true;
-},makeComparator:function(_28){
-var _29=_28.shift();
-if(!_29){
-return function(){
-return 0;
-};
-}
-var _2a=_29.attribute;
-var _2b=!!_29.descending;
-var _2c=this.makeComparator(_28);
-var _2d=this;
-return function(a,b){
-var av=_2d.getValue(a,_2a);
-var bv=_2d.getValue(b,_2a);
-if(av!=bv){
-return av<bv==_2b?1:-1;
-}
-return _2c(a,b);
-};
-}});
-cf.onUpdate=function(){
-};
+	var cf;
+	var addUpdate = function(store,create,remove){
+		// create a handler that adds to the list of notifications
+		return function(item){
+			store._updates.push({
+					create:create && item,
+					remove:remove && item
+				});
+			cf.onUpdate();
+		}
+	};
+	cf = dojo.declare("dojox.data.ClientFilter",
+		null,
+		{
+			cacheByDefault: false,
+			constructor: function(){
+				// summary:
+				//		This is an abstract class that data stores can extend to add updateable result set functionality
+				// 		as well as client side querying capabilities. This enables
+				//		widgets to be aware of how active results change in response to the modifications/notifications.
+				//
+				//	description:
+				//		To a update a result set after a notification (onNew, onSet, and onDelete),
+				// 		widgets can call the updateResultSet method. Widgets can use the updated
+				//		result sets to determine how to react to notifications, and how to update their displayed results
+				//		based on changes.
+				//
+				// 		This module will use the best available information to update result sets, using query attribute
+				// 		objects to determine if items are in a result set, and using the sort arrays to maintain sort
+				// 		information. However, queries can be opaque strings, and this module can not update
+				// 		results by itself in this case. In this situations, data stores can provide a isUpdateable(request) function
+				// 		and matchesQuery(item,request) function. If a data store can handle a query, it can return true from
+				// 		isUpdateable and if an item matches a query, it can return true from matchesQuery. Here is 
+				//		definition of isUpdateable and matchesQuery
+				// 		isUpdateable(request)  - request is the keywords arguments as is passed to the fetch function.
+				// 		matchesQuery(item,request) - item is the item to test, and request is the value arguments object
+				//				for the fetch function.
+				//
+				//		You can define a property on this object instance "cacheByDefault" to a value of true that will 
+				// 		cause all queries to be cached by default unless the cache queryOption is explicitly set to false.
+				// 		This can be defined in the constructor options for ServiceStore/JsonRestStore and subtypes. 
+				//
+				// example:
+				//		to make a updated-result-set data store from an existing data store:
+				//	|	dojo.declare("dojox.data.MyLiveDataStore",
+				//	|		dojox.data.MyDataStore,dojox.data.ClientFilter], // subclass LiveResultSets if available
+				//	|		{}
+				//	|	);
+				this.onSet = addUpdate(this,true,true);
+				this.onNew = addUpdate(this,true,false);
+				this.onDelete = addUpdate(this,false,true);
+				this._updates= [];
+				this._fetchCache = [];				
+			},
+			clearCache: function(){
+				//	summary:
+				//		Clears the cache of client side queries
+				this._fetchCache = [];
+			},
+			updateResultSet: function(/*Array*/ resultSet, /*Object*/ request){
+				//	summary:
+				//		Attempts to update the given result set based on previous notifications
+				//	resultSet:				
+				//		The result set array that should be updated
+				//	request:
+				//		This object follows the same meaning as the keywordArgs passed to a dojo.data.api.Read.fetch.
+				//	description:
+				// 		This will attempt to update the provide result based on previous notification, adding new items 
+				// 		from onNew calls, removing deleted items, and updating modified items, and properly removing
+				//  	and adding items as required by the query and sort parameters. This function will return:
+				//		0: Indicates it could not successfully update the result set
+				//		1: Indicates it could successfully handle all the notifications, but no changes were made to the result set
+				//		2: Indicates it successfully handled all the notifications and result set has been updated.
+				if(this.isUpdateable(request)){
+					// we try to avoid rerunning notification updates more than once on the same object for performance 
+					for(var i = request._version || 0; i < this._updates.length;i++){
+						// for each notification,we will update the result set
+						var create = this._updates[i].create;
+						var remove = this._updates[i].remove;
+						if(remove){
+							for(var j = 0; j < resultSet.length;j++){
+								if(this.getIdentity(resultSet[j]) == this.getIdentity(remove)){
+									resultSet.splice(j--,1);
+									var updated = true;
+								}
+							}
+						}
+						if(create && this.matchesQuery(create,request) && // if there is a new/replacement item and it matches the query 
+								dojo.indexOf(resultSet,create) == -1){ // and it doesn't already exist in query
+							resultSet.push(create); // should this go at the beginning by default instead?
+							updated = true;
+						}
+					}
+					if(request.sort && updated){
+						// do the sort if needed
+						resultSet.sort(this.makeComparator(request.sort.concat()));
+					}
+					resultSet._fullLength = resultSet.length;
+					if(request.count && updated && request.count !== Infinity){
+						// do we really need to do this?
+						// make sure we still find within the defined paging set
+						resultSet.splice(request.count, resultSet.length);
+					}
+					request._version = this._updates.length;
+					return updated ? 2 : 1;
+				}
+				return 0;
+			},
+			querySuperSet: function(argsSuper, argsSub){
+				//	summary:
+				//		Determines whether the provided arguments are super/sub sets of each other
+				// argsSuper:
+				// 		Dojo Data Fetch arguments 
+				// argsSub:
+				// 		Dojo Data Fetch arguments
+				if(argsSuper.query == argsSub.query){
+					return {};
+				}
+				if(!(argsSub.query instanceof Object && // sub query must be an object
+						// super query must be non-existent or an object
+						(!argsSuper.query || typeof argsSuper.query == 'object'))){
+					return false;
+				}
+				var clientQuery = dojo.mixin({},argsSub.query);
+				for(var i in argsSuper.query){
+					if(clientQuery[i] == argsSuper.query[i]){
+						delete clientQuery[i];
+					}else if(!(typeof argsSuper.query[i] == 'string' && 
+							// if it is a pattern, we can test to see if it is a sub-pattern 
+							// FIXME: This is not technically correct, but it will work for the majority of cases
+							dojo.data.util.filter.patternToRegExp(argsSuper.query[i]).test(clientQuery[i]))){
+						return false;
+					}
+				}
+				return clientQuery;
+			},
+			//	This is the point in the version notification history at which it is known that the server is in sync, this should
+			//	be updated to this._updates.length on commit operations.
+			serverVersion: 0,
+			
+			cachingFetch: function(args){
+				var self = this;
+				for(var i = 0; i < this._fetchCache.length;i++){
+					var cachedArgs = this._fetchCache[i];
+					var clientQuery = this.querySuperSet(cachedArgs,args);
+					if(clientQuery !== false){
+						var defResult = cachedArgs._loading;
+						if(!defResult){
+							defResult = new dojo.Deferred();
+							defResult.callback(cachedArgs.cacheResults);
+						}
+						defResult.addCallback(function(results){
+							results = self.clientSideFetch(dojo.mixin(dojo.mixin({}, args),{query:clientQuery}), results);
+							defResult.fullLength = results._fullLength;
+							return results;
+						});
+						args._version = cachedArgs._version;
+						break;
+					}
+				}
+				if(!defResult){
+					var serverArgs = dojo.mixin({}, args);
+					var putInCache = (args.queryOptions || 0).cache;
+					var fetchCache = this._fetchCache;
+					if(putInCache === undefined ? this.cacheByDefault : putInCache){
+						// we are caching this request, so we want to get all the data, and page on the client side
+						if(args.start || args.count){
+							delete serverArgs.start;
+							delete serverArgs.count;
+							args.clientQuery = dojo.mixin(args.clientQuery || {}, {
+								start: args.start,
+								count: args.count
+							});
+						}
+						args = serverArgs;
+						fetchCache.push(args);
+					}
+					defResult= args._loading = this._doQuery(args);
+					 
+					defResult.addErrback(function(){
+						fetchCache.splice(dojo.indexOf(fetchCache, args), 1);
+					});
+				}
+				var version = this.serverVersion;
+				
+				defResult.addCallback(function(results){
+					delete args._loading;
+					// update the result set in case anything changed while we were waiting for the fetch
+					if(results){
+						args._version = typeof args._version == "number" ? args._version : version;
+						self.updateResultSet(results,args);
+						args.cacheResults = results;
+						if(!args.count || results.length < args.count){
+							defResult.fullLength = ((args.start)?args.start:0) + results.length;
+						}
+					}
+					return results;
+				});
+				return defResult;
+			},
+			isUpdateable: function(/*Object*/ request){
+				//	summary:
+				//		Returns whether the provide fetch arguments can be used to update an existing list
+				//	request:
+				//		See dojo.data.api.Read.fetch request
+				
+				return typeof request.query == "object";
+			},
+			clientSideFetch: function(/*Object*/ request,/*Array*/ baseResults){
+				// summary:
+				//		Performs a query on the client side and returns the results as an array
+				//
+				//	request:
+				//		See dojo.data.api.Read.fetch request
+				//		
+				//	baseResults:
+				//		This provides the result set to start with for client side querying
+				if(request.queryOptions && request.queryOptions.results){
+					baseResults = request.queryOptions.results;
+				}
+				if(request.query){
+					// filter by the query
+					var results = [];
+					for(var i = 0; i < baseResults.length; i++){
+						var value = baseResults[i];
+						if(value && this.matchesQuery(value,request)){
+							results.push(baseResults[i]);
+						}
+					}
+				}else{
+					results = request.sort ? baseResults.concat() : baseResults; // we don't want to mutate the baseResults if we are doing a sort
+				}
+				if(request.sort){
+					// do the sort if needed
+					results.sort(this.makeComparator(request.sort.concat()));
+				}
+				return this.clientSidePaging(request, results);
+			},
+			clientSidePaging: function(/*Object*/ request,/*Array*/ baseResults){
+				var start = request.start || 0;
+				var finalResults = (start || request.count) ? baseResults.slice(start,start + (request.count || baseResults.length)) : baseResults;
+				finalResults._fullLength = baseResults.length;
+				return finalResults; 
+			},
+			matchesQuery: function(item,request){
+				var query = request.query; 
+				var ignoreCase = request.queryOptions && request.queryOptions.ignoreCase;
+				for(var i in query){
+					// if anything doesn't match, than this should be in the query
+					var match = query[i];
+					var value = this.getValue(item,i);
+					if((typeof match == 'string' && (match.match(/[\*\.]/) || ignoreCase)) ?
+						!dojo.data.util.filter.patternToRegExp(match, ignoreCase).test(value) :
+						value != match){
+						return false;
+					}
+				}
+				return true;
+			},
+			makeComparator: function(sort){
+				//	summary:
+				// 		returns a comparator function for the given sort order array
+				//	sort:
+				//		See dojox.data.api.Read.fetch
+				var current = sort.shift();
+				if(!current){
+					// sort order for ties and no sort orders
+					return function(){
+						return 0;// keep the order unchanged
+					}; 
+				}
+				var attribute = current.attribute;
+				var descending = !!current.descending;
+				var next = this.makeComparator(sort);
+				var store = this;
+				return function(a,b){
+					var av = store.getValue(a,attribute);
+					var bv = store.getValue(b,attribute);
+					if(av != bv){
+						return av < bv == descending ? 1 : -1;
+					}
+					return next(a,b); 
+				}; 
+			}
+		}
+	);
+	cf.onUpdate = function(){};
 })();
-}
diff --git a/dojox/data/CouchDBRestStore.js b/dojox/data/CouchDBRestStore.js
index 629d91e..bcff5dc 100644
--- a/dojox/data/CouchDBRestStore.js
+++ b/dojox/data/CouchDBRestStore.js
@@ -1,65 +1,79 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.CouchDBRestStore"]){
-dojo._hasResource["dojox.data.CouchDBRestStore"]=true;
 dojo.provide("dojox.data.CouchDBRestStore");
 dojo.require("dojox.data.JsonRestStore");
-dojo.declare("dojox.data.CouchDBRestStore",dojox.data.JsonRestStore,{save:function(_1){
-var _2=this.inherited(arguments);
-var _3=this.service.servicePath;
-for(var i=0;i<_2.length;i++){
-(function(_4,_5){
-_5.addCallback(function(_6){
-if(_6){
-_4.__id=_3+_6.id;
-_4._rev=_6.rev;
-}
-return _6;
-});
-})(_2[i].content,_2[i].deferred);
-}
-},fetch:function(_7){
-_7.query=_7.query||"_all_docs?";
-if(_7.start){
-_7.query=(_7.query?(_7.query+"&"):"")+"startkey="+_7.start;
-delete _7.start;
-}
-if(_7.count){
-_7.query=(_7.query?(_7.query+"&"):"")+"limit="+_7.count;
-delete _7.count;
-}
-return this.inherited(arguments);
-},_processResults:function(_8){
-var _9=_8.rows;
-if(_9){
-var _a=this.service.servicePath;
-var _b=this;
-for(var i=0;i<_9.length;i++){
-var _c=_9[i].value;
-_c.__id=_a+_9[i].id;
-_c._id=_9[i].id;
-_c._loadObject=dojox.rpc.JsonRest._loader;
-_9[i]=_c;
-}
-return {totalCount:_8.total_rows,items:_8.rows};
-}else{
-return {items:_8};
-}
-}});
-dojox.data.CouchDBRestStore.getStores=function(_d){
-var _e=dojo.xhrGet({url:_d+"_all_dbs",handleAs:"json",sync:true});
-var _f={};
-_e.addBoth(function(dbs){
-for(var i=0;i<dbs.length;i++){
-_f[dbs[i]]=new dojox.data.CouchDBRestStore({target:_d+dbs[i],idAttribute:"_id"});
-}
-return _f;
-});
-return _f;
+
+// A CouchDBRestStore is an extension of JsonRestStore to handle CouchDB's idiosyncrasies, special features,
+// and deviations from standard HTTP Rest.
+// NOTE: CouchDB is not designed to be run on a public facing network. There is no access control
+// on database documents, and you should NOT rely on client side control to implement security.
+
+
+dojo.declare("dojox.data.CouchDBRestStore",
+	dojox.data.JsonRestStore,
+	{
+		save: function(kwArgs){
+			var actions = this.inherited(arguments); // do the default save and then update for version numbers
+			var prefix = this.service.servicePath;
+			for(var i = 0; i < actions.length; i++){
+				// need to update the item's version number after it has been committed
+				(function(item,dfd){
+					dfd.addCallback(function(result){
+						if(result){
+							item.__id = prefix + result.id; // update the object with the results of the post
+							item._rev = result.rev;
+						}
+						return result;
+					});
+				})(actions[i].content,actions[i].deferred);
+			}
+		},
+		fetch: function(args){
+			// summary:
+			// 		This only differs from JsonRestStore in that it, will put the query string the query part of the URL and it handles start and count
+			args.query = args.query || '_all_docs?';
+			if(args.start){
+				args.query = (args.query ? (args.query + '&') : '') + 'startkey=' + args.start;
+				delete args.start;
+			}
+			if(args.count){
+				args.query = (args.query ? (args.query + '&') : '') + 'limit=' + args.count;
+				delete args.count;
+			}
+			return this.inherited(arguments);
+		},
+		_processResults: function(results){
+			var rows = results.rows;
+			if(rows){
+				var prefix = this.service.servicePath;
+				var self = this;
+				for(var i = 0; i < rows.length;i++){
+					var realItem = rows[i].value;
+					realItem.__id= prefix + rows[i].id;
+					realItem._id= rows[i].id;
+					realItem._loadObject= dojox.rpc.JsonRest._loader;
+					rows[i] = realItem;
+				}
+				return {totalCount:results.total_rows, items:results.rows};
+			}else{
+				return {items:results};
+			}
+
+		}
+	}
+);
+
+// create a set of stores
+dojox.data.CouchDBRestStore.getStores = function(couchServerUrl){
+	var dfd = dojo.xhrGet({
+		url: couchServerUrl+"_all_dbs",
+		handleAs: "json",
+		sync: true
+	});
+	var stores = {};
+	dfd.addBoth(function(dbs){
+		for(var i = 0; i < dbs.length; i++){
+			stores[dbs[i]] = new dojox.data.CouchDBRestStore({target:couchServerUrl + dbs[i],idAttribute:"_id"});
+		}
+		return stores;
+	});
+	return stores;
 };
-}
diff --git a/dojox/data/CssClassStore.js b/dojox/data/CssClassStore.js
old mode 100644
new mode 100755
index a928f4e..52a0a94
--- a/dojox/data/CssClassStore.js
+++ b/dojox/data/CssClassStore.js
@@ -1,104 +1,158 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.CssClassStore"]){
-dojo._hasResource["dojox.data.CssClassStore"]=true;
 dojo.provide("dojox.data.CssClassStore");
+
 dojo.require("dojox.data.CssRuleStore");
-dojo.declare("dojox.data.CssClassStore",dojox.data.CssRuleStore,{_labelAttribute:"class",_idAttribute:"class",_cName:"dojox.data.CssClassStore",getFeatures:function(){
-return {"dojo.data.api.Read":true,"dojo.data.api.Identity":true};
-},getAttributes:function(_1){
-this._assertIsItem(_1);
-return ["class","classSans"];
-},getValue:function(_2,_3,_4){
-var _5=this.getValues(_2,_3);
-if(_5&&_5.length>0){
-return _5[0];
-}
-return _4;
-},getValues:function(_6,_7){
-this._assertIsItem(_6);
-this._assertIsAttribute(_7);
-var _8=[];
-if(_7==="class"){
-_8=[_6.className];
-}else{
-if(_7==="classSans"){
-_8=[_6.className.replace(/\./g,"")];
-}
-}
-return _8;
-},_handleRule:function(_9,_a,_b){
-var _c={};
-var s=_9["selectorText"].split(" ");
-for(var j=0;j<s.length;j++){
-var _d=s[j];
-var _e=_d.indexOf(".");
-if(_d&&_d.length>0&&_e!==-1){
-var _f=_d.indexOf(",")||_d.indexOf("[");
-_d=_d.substring(_e,((_f!==-1&&_f>_e)?_f:_d.length));
-_c[_d]=true;
-}
-}
-for(var key in _c){
-if(!this._allItems[key]){
-var _10={};
-_10.className=key;
-_10[this._storeRef]=this;
-this._allItems[key]=_10;
-}
-}
-},_handleReturn:function(){
-var _11=[];
-var _12={};
-for(var i in this._allItems){
-_12[i]=this._allItems[i];
-}
-var _13;
-while(this._pending.length){
-_13=this._pending.pop();
-_13.request._items=_12;
-_11.push(_13);
-}
-while(_11.length){
-_13=_11.pop();
-if(_13.fetch){
-this._handleFetchReturn(_13.request);
-}else{
-this._handleFetchByIdentityReturn(_13.request);
-}
-}
-},_handleFetchByIdentityReturn:function(_14){
-var _15=_14._items;
-var _16=_15[(dojo.isWebKit?_14.identity.toLowerCase():_14.identity)];
-if(!this.isItem(_16)){
-_16=null;
-}
-if(_14.onItem){
-var _17=_14.scope||dojo.global;
-_14.onItem.call(_17,_16);
-}
-},getIdentity:function(_18){
-this._assertIsItem(_18);
-return this.getValue(_18,this._idAttribute);
-},getIdentityAttributes:function(_19){
-this._assertIsItem(_19);
-return [this._idAttribute];
-},fetchItemByIdentity:function(_1a){
-_1a=_1a||{};
-if(!_1a.store){
-_1a.store=this;
-}
-if(this._pending&&this._pending.length>0){
-this._pending.push({request:_1a});
-}else{
-this._pending=[{request:_1a}];
-this._fetch(_1a);
-}
-return _1a;
-}});
-}
+
+dojo.declare("dojox.data.CssClassStore", dojox.data.CssRuleStore, {
+	//	summary:
+	//		Basic store to display CSS information.
+	//	description:
+	//		The CssClassStore allows users to get information about active Css classes in the page running the CssClassStore.
+	//		It can also filter out classes from specific stylesheets.  The attributes it exposes on classes are as follows:
+	//			class:		The classname, including the '.'.
+	//			classSans:	The classname without the '.'.
+
+	_labelAttribute: 'class', // text representation of the Item [label and identifier may need to stay due to method names]
+	_idAttribute: 'class',
+	_cName: "dojox.data.CssClassStore",
+
+	getFeatures: function(){
+		//	summary: 
+		//		See dojo.data.api.Read.getFeatures()
+		return { 
+			"dojo.data.api.Read" : true,
+			"dojo.data.api.Identity" : true 
+		};
+	},
+
+	getAttributes: function(item){
+		//	summary: 
+		//		See dojo.data.api.Read.getAttributes()
+		this._assertIsItem(item);
+		return ['class', 'classSans'];
+	},
+
+	getValue: function(item, attribute, defaultValue){
+		//	summary: 
+		//		See dojo.data.api.Read.getValue()
+		var values = this.getValues(item, attribute);
+		if(values && values.length > 0){
+			return values[0];
+		}
+		return defaultValue;
+	},
+
+	getValues: function(item, attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.getValues()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		var value = [];
+		if(attribute === "class"){
+			value = [item.className];
+		}else if(attribute === "classSans"){
+			value = [item.className.replace(/\./g,'')];
+		}
+		return value;
+	},
+
+	_handleRule: function(rule, styleSheet, href){
+		//	summary:
+		//		Handles the creation of an item based on the passed rule.  In this store, this implies
+		//		parsing out all available class names.
+		var obj = {};
+		var s = rule['selectorText'].split(" ");
+		for(var j=0; j<s.length; j++){
+			var tmp = s[j];
+			var first = tmp.indexOf('.');
+			if(tmp && tmp.length > 0 && first !== -1){
+				var last = tmp.indexOf(',') || tmp.indexOf('[');
+				tmp = tmp.substring(first, ((last !== -1 && last > first)?last:tmp.length));
+				obj[tmp] = true;
+			}
+		}
+		for(var key in obj){
+			if(!this._allItems[key]){
+				var item = {};
+				item.className = key;
+				item[this._storeRef] = this;
+				this._allItems[key] = item;
+			}
+		}
+	},
+
+	_handleReturn: function(){
+		//	summary:
+		//		Handles the return from a fetching action.  Delegates requests to act on the resulting
+		//		item set to eitehr the _handleFetchReturn or _handleFetchByIdentityReturn depending on
+		//		where the request originated.  
+		var _inProgress = [];
+		
+		var items = {};
+		for(var i in this._allItems){
+			items[i] = this._allItems[i];
+		}
+		var requestInfo;
+		// One-level deep clone (can't use dojo.clone, since we don't want to clone all those store refs!)
+		while(this._pending.length){
+			requestInfo = this._pending.pop();
+			requestInfo.request._items = items;
+			_inProgress.push(requestInfo);
+		}
+
+		while(_inProgress.length){
+			requestInfo = _inProgress.pop();
+			if(requestInfo.fetch){
+				this._handleFetchReturn(requestInfo.request);
+			}else{
+				this._handleFetchByIdentityReturn(requestInfo.request);
+			}
+		}
+	},
+
+	_handleFetchByIdentityReturn: function(request){
+		//	summary:
+		//		Handles a fetchByIdentity request by finding the correct item.
+		var items = request._items;
+		// Per https://bugs.webkit.org/show_bug.cgi?id=17935 , Safari 3.x always returns the selectorText 
+		// of a rule in full lowercase.
+		var item = items[(dojo.isWebKit?request.identity.toLowerCase():request.identity)];
+		if(!this.isItem(item)){
+			item = null;
+		}
+		if(request.onItem){
+			var scope = request.scope || dojo.global;
+			request.onItem.call(scope, item);
+		}
+	},
+
+	/* Identity API */
+	getIdentity: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Identity.getIdentity()
+		this._assertIsItem(item);
+		return this.getValue(item, this._idAttribute);
+	},
+
+	getIdentityAttributes: function(/* item */ item){
+		 //	summary: 
+		 //		See dojo.data.api.Identity.getIdentityAttributes()
+		this._assertIsItem(item);
+		return [this._idAttribute];
+	},
+
+	fetchItemByIdentity: function(/* request */ request){
+		//	summary: 
+		//		See dojo.data.api.Identity.fetchItemByIdentity()
+		request = request || {};
+		if(!request.store){
+			request.store = this;
+		}
+		if(this._pending && this._pending.length > 0){
+			this._pending.push({request: request});
+		}else{
+			this._pending = [{request: request}];
+			this._fetch(request);
+		}
+		return request;
+	}
+});
diff --git a/dojox/data/CssRuleStore.js b/dojox/data/CssRuleStore.js
old mode 100644
new mode 100755
index b0a1b8d..0239746
--- a/dojox/data/CssRuleStore.js
+++ b/dojox/data/CssRuleStore.js
@@ -1,336 +1,463 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.CssRuleStore"]){
-dojo._hasResource["dojox.data.CssRuleStore"]=true;
 dojo.provide("dojox.data.CssRuleStore");
+
 dojo.require("dojo.data.util.filter");
 dojo.require("dojo.data.util.sorter");
 dojo.require("dojox.data.css");
-dojo.declare("dojox.data.CssRuleStore",null,{_storeRef:"_S",_labelAttribute:"selector",_cache:null,_browserMap:null,_cName:"dojox.data.CssRuleStore",constructor:function(_1){
-if(_1){
-dojo.mixin(this,_1);
-}
-this._cache={};
-this._allItems=null;
-this._waiting=[];
-this.gatherHandle=null;
-var _2=this;
-function _3(){
-try{
-_2.context=dojox.data.css.determineContext(_2.context);
-if(_2.gatherHandle){
-clearInterval(_2.gatherHandle);
-_2.gatherHandle=null;
-}
-while(_2._waiting.length){
-var _4=_2._waiting.pop();
-dojox.data.css.rules.forEach(_4.forFunc,null,_2.context);
-_4.finishFunc();
-}
-}
-catch(e){
-}
-};
-this.gatherHandle=setInterval(_3,250);
-},setContext:function(_5){
-if(_5){
-this.close();
-this.context=dojox.data.css.determineContext(_5);
-}
-},getFeatures:function(){
-return {"dojo.data.api.Read":true};
-},isItem:function(_6){
-if(_6&&_6[this._storeRef]==this){
-return true;
-}
-return false;
-},hasAttribute:function(_7,_8){
-this._assertIsItem(_7);
-this._assertIsAttribute(_8);
-var _9=this.getAttributes(_7);
-if(dojo.indexOf(_9,_8)!=-1){
-return true;
-}
-return false;
-},getAttributes:function(_a){
-this._assertIsItem(_a);
-var _b=["selector","classes","rule","style","cssText","styleSheet","parentStyleSheet","parentStyleSheetHref"];
-var _c=_a.rule.style;
-if(_c){
-var _d;
-for(_d in _c){
-_b.push("style."+_d);
-}
-}
-return _b;
-},getValue:function(_e,_f,_10){
-var _11=this.getValues(_e,_f);
-var _12=_10;
-if(_11&&_11.length>0){
-return _11[0];
-}
-return _10;
-},getValues:function(_13,_14){
-this._assertIsItem(_13);
-this._assertIsAttribute(_14);
-var _15=null;
-if(_14==="selector"){
-_15=_13.rule["selectorText"];
-if(_15&&dojo.isString(_15)){
-_15=_15.split(",");
-}
-}else{
-if(_14==="classes"){
-_15=_13.classes;
-}else{
-if(_14==="rule"){
-_15=_13.rule.rule;
-}else{
-if(_14==="style"){
-_15=_13.rule.style;
-}else{
-if(_14==="cssText"){
-if(dojo.isIE){
-if(_13.rule.style){
-_15=_13.rule.style.cssText;
-if(_15){
-_15="{ "+_15.toLowerCase()+" }";
-}
-}
-}else{
-_15=_13.rule.cssText;
-if(_15){
-_15=_15.substring(_15.indexOf("{"),_15.length);
-}
-}
-}else{
-if(_14==="styleSheet"){
-_15=_13.rule.styleSheet;
-}else{
-if(_14==="parentStyleSheet"){
-_15=_13.rule.parentStyleSheet;
-}else{
-if(_14==="parentStyleSheetHref"){
-if(_13.href){
-_15=_13.href;
-}
-}else{
-if(_14.indexOf("style.")===0){
-var _16=_14.substring(_14.indexOf("."),_14.length);
-_15=_13.rule.style[_16];
-}else{
-_15=[];
-}
-}
-}
-}
-}
-}
-}
-}
-}
-if(_15!==undefined){
-if(!dojo.isArray(_15)){
-_15=[_15];
-}
-}
-return _15;
-},getLabel:function(_17){
-this._assertIsItem(_17);
-return this.getValue(_17,this._labelAttribute);
-},getLabelAttributes:function(_18){
-return [this._labelAttribute];
-},containsValue:function(_19,_1a,_1b){
-var _1c=undefined;
-if(typeof _1b==="string"){
-_1c=dojo.data.util.filter.patternToRegExp(_1b,false);
-}
-return this._containsValue(_19,_1a,_1b,_1c);
-},isItemLoaded:function(_1d){
-return this.isItem(_1d);
-},loadItem:function(_1e){
-this._assertIsItem(_1e.item);
-},fetch:function(_1f){
-_1f=_1f||{};
-if(!_1f.store){
-_1f.store=this;
-}
-var _20=_1f.scope||dojo.global;
-if(this._pending&&this._pending.length>0){
-this._pending.push({request:_1f,fetch:true});
-}else{
-this._pending=[{request:_1f,fetch:true}];
-this._fetch(_1f);
-}
-return _1f;
-},_fetch:function(_21){
-var _22=_21.scope||dojo.global;
-if(this._allItems===null){
-this._allItems={};
-try{
-if(this.gatherHandle){
-this._waiting.push({"forFunc":dojo.hitch(this,this._handleRule),"finishFunc":dojo.hitch(this,this._handleReturn)});
-}else{
-dojox.data.css.rules.forEach(dojo.hitch(this,this._handleRule),null,this.context);
-this._handleReturn();
-}
-}
-catch(e){
-if(_21.onError){
-_21.onError.call(_22,e,_21);
-}
-}
-}else{
-this._handleReturn();
-}
-},_handleRule:function(_23,_24,_25){
-var _26=_23["selectorText"];
-var s=_26.split(" ");
-var _27=[];
-for(var j=0;j<s.length;j++){
-var tmp=s[j];
-var _28=tmp.indexOf(".");
-if(tmp&&tmp.length>0&&_28!==-1){
-var _29=tmp.indexOf(",")||tmp.indexOf("[");
-tmp=tmp.substring(_28,((_29!==-1&&_29>_28)?_29:tmp.length));
-_27.push(tmp);
-}
-}
-var _2a={};
-_2a.rule=_23;
-_2a.styleSheet=_24;
-_2a.href=_25;
-_2a.classes=_27;
-_2a[this._storeRef]=this;
-if(!this._allItems[_26]){
-this._allItems[_26]=[];
-}
-this._allItems[_26].push(_2a);
-},_handleReturn:function(){
-var _2b=[];
-var _2c=[];
-var _2d=null;
-for(var i in this._allItems){
-_2d=this._allItems[i];
-for(var j in _2d){
-_2c.push(_2d[j]);
-}
-}
-var _2e;
-while(this._pending.length){
-_2e=this._pending.pop();
-_2e.request._items=_2c;
-_2b.push(_2e);
-}
-while(_2b.length){
-_2e=_2b.pop();
-this._handleFetchReturn(_2e.request);
-}
-},_handleFetchReturn:function(_2f){
-var _30=_2f.scope||dojo.global;
-var _31=[];
-var _32="all";
-var i;
-if(_2f.query){
-_32=dojo.toJson(_2f.query);
-}
-if(this._cache[_32]){
-_31=this._cache[_32];
-}else{
-if(_2f.query){
-for(i in _2f._items){
-var _33=_2f._items[i];
-var _34=dojo.isWebKit?true:(_2f.queryOptions?_2f.queryOptions.ignoreCase:false);
-var _35={};
-var key;
-var _36;
-for(key in _2f.query){
-_36=_2f.query[key];
-if(typeof _36==="string"){
-_35[key]=dojo.data.util.filter.patternToRegExp(_36,_34);
-}
-}
-var _37=true;
-for(key in _2f.query){
-_36=_2f.query[key];
-if(!this._containsValue(_33,key,_36,_35[key])){
-_37=false;
-}
-}
-if(_37){
-_31.push(_33);
-}
-}
-this._cache[_32]=_31;
-}else{
-for(i in _2f._items){
-_31.push(_2f._items[i]);
-}
-}
-}
-var _38=_31.length;
-if(_2f.sort){
-_31.sort(dojo.data.util.sorter.createSortFunction(_2f.sort,this));
-}
-var _39=0;
-var _3a=_31.length;
-if(_2f.start>0&&_2f.start<_31.length){
-_39=_2f.start;
-}
-if(_2f.count&&_2f.count){
-_3a=_2f.count;
-}
-var _3b=_39+_3a;
-if(_3b>_31.length){
-_3b=_31.length;
-}
-_31=_31.slice(_39,_3b);
-if(_2f.onBegin){
-_2f.onBegin.call(_30,_38,_2f);
-}
-if(_2f.onItem){
-if(dojo.isArray(_31)){
-for(i=0;i<_31.length;i++){
-_2f.onItem.call(_30,_31[i],_2f);
-}
-if(_2f.onComplete){
-_2f.onComplete.call(_30,null,_2f);
-}
-}
-}else{
-if(_2f.onComplete){
-_2f.onComplete.call(_30,_31,_2f);
-}
-}
-return _2f;
-},close:function(){
-this._cache={};
-this._allItems=null;
-},_assertIsItem:function(_3c){
-if(!this.isItem(_3c)){
-throw new Error(this._cName+": Invalid item argument.");
-}
-},_assertIsAttribute:function(_3d){
-if(typeof _3d!=="string"){
-throw new Error(this._cName+": Invalid attribute argument.");
-}
-},_containsValue:function(_3e,_3f,_40,_41){
-return dojo.some(this.getValues(_3e,_3f),function(_42){
-if(_42!==null&&!dojo.isObject(_42)&&_41){
-if(_42.toString().match(_41)){
-return true;
-}
-}else{
-if(_40===_42){
-return true;
-}
-}
-return false;
+
+dojo.declare("dojox.data.CssRuleStore", null, {
+	//	summary:
+	//		Basic store to display CSS information.
+	//	description:
+	//		The CssRuleStore allows users to get information about active CSS rules in the page running the CssRuleStore.
+	//		It can also filter out rules from specific stylesheets.  The attributes it exposes on rules are as follows:
+	//			selector:				The selector text.
+	//			classes:				An array of classes present in this selector.
+	//			rule:					The actual DOM Rule object.
+	//			style:					The actual DOM CSSStyleDeclaration object.
+	//			cssText:				The cssText string provided on the rule object.
+	//			styleSheet:				The originating DOM Stylesheet object.
+	//			parentStyleSheet: 		The parent stylesheet to the sheet this rule originates from.
+	//			parentStyleSheetHref: 	The href of the parent stylesheet.
+	//		AND every style attribute denoted as style.*, such as style.textAlign or style.backgroundColor
+
+	_storeRef: '_S',
+	_labelAttribute: 'selector', // text representation of the Item [label and identifier may need to stay due to method names]
+
+	_cache: null,
+
+	_browserMap: null,
+
+	_cName: "dojox.data.CssRuleStore",
+
+	constructor: function(/* Object */ keywordParameters){
+		// Initializes this store
+		if(keywordParameters){
+			dojo.mixin(this, keywordParameters);
+		}
+		this._cache = {};
+		this._allItems = null;
+		this._waiting = [];
+		this.gatherHandle = null;
+		var self = this;
+		// CSS files may not be finished loading by the time the store is constructed.  We need to 
+		// give them a little time, so setting the stylesheet loading to retry every 250ms.
+		function gatherRules(){
+			try{
+				// Funkiness here is due to css that may still be loading.  This throws an DOM Access 
+				// error if css isnt completely loaded.
+				self.context = dojox.data.css.determineContext(self.context);
+				if(self.gatherHandle){
+					clearInterval(self.gatherHandle);
+					self.gatherHandle = null;
+				}
+				// Handle any fetches that have been queued while we've been waiting on the CSS files 
+				// to finish
+				while(self._waiting.length){
+					var item = self._waiting.pop();
+					dojox.data.css.rules.forEach(item.forFunc, null, self.context);
+					item.finishFunc();
+				}
+			}catch(e){}
+		}
+		this.gatherHandle = setInterval(gatherRules,250);
+	},
+	
+	setContext: function(/* Array */ context){
+		// Sets the context in which queries are executed
+		// context: Array - Array of CSS string paths to execute queries within
+		if(context){
+			this.close();
+			this.context = dojox.data.css.determineContext(context);
+		}
+	},
+
+	getFeatures: function(){
+		//	summary: 
+		//		See dojo.data.api.Read.getFeatures()
+		return { 
+			"dojo.data.api.Read" : true
+		};
+	},
+
+	isItem: function(item){
+		//	summary: 
+		//		See dojo.data.api.Read.isItem()
+		if(item && item[this._storeRef] == this){
+			return true;
+		}
+		return false;
+	},
+
+	hasAttribute: function(item, attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.hasAttribute()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		var attrs = this.getAttributes(item);
+		if(dojo.indexOf(attrs, attribute) != -1){
+			return true;
+		}
+		return false;
+	},
+
+	getAttributes: function(item){
+		//	summary: 
+		//		See dojo.data.api.Read.getAttributes()
+		this._assertIsItem(item);
+		var attrs = ['selector', 'classes', 'rule', 'style', 'cssText', 'styleSheet', 'parentStyleSheet', 'parentStyleSheetHref'];
+		var style = item.rule.style;
+		if(style){
+			var key;
+			for(key in style){
+				attrs.push("style." + key);
+			}
+		}
+		return attrs;
+	},
+
+	getValue: function(item, attribute, defaultValue){
+		//	summary: 
+		//		See dojo.data.api.Read.getValue()
+		var values = this.getValues(item, attribute);
+		var value = defaultValue;
+		if(values && values.length > 0){
+			return values[0];
+		}
+		return defaultValue;
+	},
+
+	getValues: function(item, attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.getValues()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		var value = null;
+		if(attribute === "selector"){
+			value = item.rule["selectorText"];
+			if(value && dojo.isString(value)){
+				value = value.split(",");
+			}
+		}else if(attribute === "classes"){
+			value = item.classes;
+		}else if(attribute === "rule"){
+			value = item.rule.rule;
+		}else if(attribute === "style"){
+			value = item.rule.style;
+		}else if(attribute === "cssText"){
+			if(dojo.isIE){
+				if(item.rule.style){
+					value = item.rule.style.cssText;
+					if(value){
+						value = "{ " + value.toLowerCase() + " }";
+					}
+				}
+			}else{
+				value = item.rule.cssText;
+				if(value){
+					value = value.substring(value.indexOf("{"), value.length);
+				}
+			}
+		}else if(attribute === "styleSheet"){
+			value = item.rule.styleSheet;
+		}else if(attribute === "parentStyleSheet"){
+			value = item.rule.parentStyleSheet;
+		}else if(attribute === "parentStyleSheetHref"){
+			if(item.href){
+				value = item.href;
+			}
+		}else if(attribute.indexOf("style.") === 0){
+			var attr = attribute.substring(attribute.indexOf("."), attribute.length);
+			value = item.rule.style[attr];
+		}else{
+			value = [];
+		}
+		if(value !== undefined){
+			if(!dojo.isArray(value)){
+				value = [value];
+			}
+		}
+		return value;
+	},
+
+	getLabel: function(item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabel()
+		this._assertIsItem(item);
+		return this.getValue(item, this._labelAttribute);
+	},
+
+	getLabelAttributes: function(item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabelAttributes()
+		return [this._labelAttribute];
+	},
+
+	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.
+	},
+
+	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);
+	},
+
+	fetch: function(request){
+		//	summary: 
+		//		See dojo.data.api.Read.fetch()
+		request = request || {};
+		if(!request.store){
+			request.store = this;
+		}
+
+		var scope = request.scope || dojo.global;
+		if(this._pending && this._pending.length > 0){
+			this._pending.push({request: request, fetch: true});
+		}else{
+			this._pending = [{request: request, fetch: true}];
+			this._fetch(request);
+		}
+		return request;
+	},
+
+	_fetch: function(request){
+		//	summary:
+		//		Populates the _allItems object with unique class names
+		var scope = request.scope || dojo.global;
+		if(this._allItems === null){
+			this._allItems = {};
+			try{
+				if(this.gatherHandle){
+					this._waiting.push({'forFunc': dojo.hitch(this, this._handleRule), 'finishFunc': dojo.hitch(this, this._handleReturn)});
+				}else{
+					dojox.data.css.rules.forEach(dojo.hitch(this, this._handleRule), null, this.context);
+					this._handleReturn();
+				}
+			}catch(e){
+				if(request.onError){
+					request.onError.call(scope, e, request);
+				}
+			}
+		}else{
+			this._handleReturn();
+		}
+	},
+
+	_handleRule: function(rule, styleSheet, href){
+		//	summary:
+		//		Handles the creation of an item based on the passed rule.  In this store, this implies
+		//		parsing out all available class names.
+		var selector = rule['selectorText'];
+		var s = selector.split(" ");
+		var classes = [];
+		for(var j=0; j<s.length; j++){
+			var tmp = s[j];
+			var first = tmp.indexOf('.');
+			if(tmp && tmp.length > 0 && first !== -1){
+				var last = tmp.indexOf(',') || tmp.indexOf('[');
+				tmp = tmp.substring(first, ((last !== -1 && last > first)?last:tmp.length));
+				classes.push(tmp);
+			}
+		}
+		var item = {};
+		item.rule = rule;
+		item.styleSheet = styleSheet;
+		item.href = href;
+		item.classes = classes;
+		item[this._storeRef] = this;
+		if(!this._allItems[selector]){
+			this._allItems[selector] = [];
+		}
+		this._allItems[selector].push(item);
+	},
+
+	_handleReturn: function(){
+		//	summary:
+		//		Handles the return from a fetching action.  Delegates requests to act on the resulting
+		//		item set to eitehr the _handleFetchReturn or _handleFetchByIdentityReturn depending on
+		//		where the request originated.  
+		var _inProgress = [];
+		
+		var items = [];
+		var item = null;
+		for(var i in this._allItems){
+			item = this._allItems[i];
+			for(var j in item){
+				items.push(item[j]);
+			}
+		}
+
+		var requestInfo;
+		// One-level deep clone (can't use dojo.clone, since we don't want to clone all those store refs!)
+		while(this._pending.length){
+			requestInfo = this._pending.pop();
+			requestInfo.request._items = items;
+			_inProgress.push(requestInfo);
+		}
+
+		while(_inProgress.length){
+			requestInfo = _inProgress.pop();
+			this._handleFetchReturn(requestInfo.request);
+		}
+	},
+
+	_handleFetchReturn: function(/*Request */ request){
+		//	summary:
+		//		Handles a fetchByIdentity request by finding the correct items.
+		var scope = request.scope || dojo.global;
+		var items = [];
+		//Check to see if we've looked this query up before
+		//If so, just reuse it, much faster.  Only regen if query changes.
+		var cacheKey = "all";
+		var i;
+		if(request.query){
+			cacheKey = dojo.toJson(request.query);
+		}
+		if(this._cache[cacheKey]){
+			items = this._cache[cacheKey];
+		}else if(request.query){
+			for(i in request._items){
+				var item = request._items[i];
+				// Per https://bugs.webkit.org/show_bug.cgi?id=17935 , Safari 3.x always returns the selectorText 
+				// of a rule in full lowercase.
+				var ignoreCase = dojo.isWebKit ? true : (request.queryOptions ? request.queryOptions.ignoreCase : false); 
+				var regexpList = {};
+				var key;
+				var value;
+				for(key in request.query){
+					value = request.query[key];
+					if(typeof value === "string"){
+						regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
+					}
+				}
+				var match = true;
+				for(key in request.query){
+					value = request.query[key];
+					if(!this._containsValue(item, key, value, regexpList[key])){
+						match = false;
+					}
+				}
+				if(match){
+					items.push(item); 
+				}
+			}
+			this._cache[cacheKey] = items;
+		}else{
+			for(i in request._items){
+				items.push(request._items[i]);
+			}
+		}
+		var total = items.length;
+
+		//Sort it if we need to.
+		if(request.sort){
+			items.sort(dojo.data.util.sorter.createSortFunction(request.sort, this));
+		}
+		var start = 0;
+		var count = items.length;
+		if(request.start > 0 && request.start < items.length){
+			start = request.start;	
+		}
+		if(request.count && request.count){
+			count = request.count;
+		}
+		var endIdx = start + count;
+		if(endIdx > items.length){
+			endIdx = items.length;
+		}
+
+		items = items.slice(start, endIdx);
+
+		if(request.onBegin){
+			request.onBegin.call(scope, total, request);
+		}
+		if(request.onItem){
+			if(dojo.isArray(items)){
+				for(i = 0; i < items.length; i++){
+					request.onItem.call(scope, items[i], request); 
+				}
+				if(request.onComplete){
+					request.onComplete.call(scope, null, request);
+				}
+			}
+		}else if(request.onComplete){
+			request.onComplete.call(scope, items, request); 
+		}
+		return request;
+	},
+
+	close: function(){
+		//	summary: 
+		//		See dojo.data.api.Read.close()
+		//		Clears out the cache and allItems objects, meaning all future fetches will requery
+		//		the stylesheets.
+		this._cache = {};
+		this._allItems = null;
+	},
+	
+	_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(this._cName + ": 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(this._cName + ": Invalid attribute argument.");
+		}
+	},
+
+	_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
+			}
+			return false;
+		});
+	}
 });
-}});
-}
diff --git a/dojox/data/CsvStore.js b/dojox/data/CsvStore.js
index 4a5353b..09627f3 100644
--- a/dojox/data/CsvStore.js
+++ b/dojox/data/CsvStore.js
@@ -1,444 +1,725 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.CsvStore"]){
-dojo._hasResource["dojox.data.CsvStore"]=true;
 dojo.provide("dojox.data.CsvStore");
+
 dojo.require("dojo.data.util.filter");
 dojo.require("dojo.data.util.simpleFetch");
-dojo.declare("dojox.data.CsvStore",null,{constructor:function(_1){
-this._attributes=[];
-this._attributeIndexes={};
-this._dataArray=[];
-this._arrayOfAllItems=[];
-this._loadFinished=false;
-if(_1.url){
-this.url=_1.url;
-}
-this._csvData=_1.data;
-if(_1.label){
-this.label=_1.label;
-}else{
-if(this.label===""){
-this.label=undefined;
-}
-}
-this._storeProp="_csvStore";
-this._idProp="_csvId";
-this._features={"dojo.data.api.Read":true,"dojo.data.api.Identity":true};
-this._loadInProgress=false;
-this._queuedFetches=[];
-this.identifier=_1.identifier;
-if(this.identifier===""){
-delete this.identifier;
-}else{
-this._idMap={};
-}
-if("separator" in _1){
-this.separator=_1.separator;
-}
-if("urlPreventCache" in _1){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-},url:"",label:"",identifier:"",separator:",",urlPreventCache:false,_assertIsItem:function(_2){
-if(!this.isItem(_2)){
-throw new Error(this.declaredClass+": a function was passed an item argument that was not an item");
-}
-},_getIndex:function(_3){
-var _4=this.getIdentity(_3);
-if(this.identifier){
-_4=this._idMap[_4];
-}
-return _4;
-},getValue:function(_5,_6,_7){
-this._assertIsItem(_5);
-var _8=_7;
-if(typeof _6==="string"){
-var ai=this._attributeIndexes[_6];
-if(ai!=null){
-var _9=this._dataArray[this._getIndex(_5)];
-_8=_9[ai]||_7;
-}
-}else{
-throw new Error(this.declaredClass+": a function was passed an attribute argument that was not a string");
-}
-return _8;
-},getValues:function(_a,_b){
-var _c=this.getValue(_a,_b);
-return (_c?[_c]:[]);
-},getAttributes:function(_d){
-this._assertIsItem(_d);
-var _e=[];
-var _f=this._dataArray[this._getIndex(_d)];
-for(var i=0;i<_f.length;i++){
-if(_f[i]!==""){
-_e.push(this._attributes[i]);
-}
-}
-return _e;
-},hasAttribute:function(_10,_11){
-this._assertIsItem(_10);
-if(typeof _11==="string"){
-var _12=this._attributeIndexes[_11];
-var _13=this._dataArray[this._getIndex(_10)];
-return (typeof _12!=="undefined"&&_12<_13.length&&_13[_12]!=="");
-}else{
-throw new Error(this.declaredClass+": a function was passed an attribute argument that was not a string");
-}
-},containsValue:function(_14,_15,_16){
-var _17=undefined;
-if(typeof _16==="string"){
-_17=dojo.data.util.filter.patternToRegExp(_16,false);
-}
-return this._containsValue(_14,_15,_16,_17);
-},_containsValue:function(_18,_19,_1a,_1b){
-var _1c=this.getValues(_18,_19);
-for(var i=0;i<_1c.length;++i){
-var _1d=_1c[i];
-if(typeof _1d==="string"&&_1b){
-return (_1d.match(_1b)!==null);
-}else{
-if(_1a===_1d){
-return true;
-}
-}
-}
-return false;
-},isItem:function(_1e){
-if(_1e&&_1e[this._storeProp]===this){
-var _1f=_1e[this._idProp];
-if(this.identifier){
-var _20=this._dataArray[this._idMap[_1f]];
-if(_20){
-return true;
-}
-}else{
-if(_1f>=0&&_1f<this._dataArray.length){
-return true;
-}
-}
-}
-return false;
-},isItemLoaded:function(_21){
-return this.isItem(_21);
-},loadItem:function(_22){
-},getFeatures:function(){
-return this._features;
-},getLabel:function(_23){
-if(this.label&&this.isItem(_23)){
-return this.getValue(_23,this.label);
-}
-return undefined;
-},getLabelAttributes:function(_24){
-if(this.label){
-return [this.label];
-}
-return null;
-},_fetchItems:function(_25,_26,_27){
-var _28=this;
-var _29=function(_2a,_2b){
-var _2c=null;
-if(_2a.query){
-var key,_2d;
-_2c=[];
-var _2e=_2a.queryOptions?_2a.queryOptions.ignoreCase:false;
-var _2f={};
-for(key in _2a.query){
-_2d=_2a.query[key];
-if(typeof _2d==="string"){
-_2f[key]=dojo.data.util.filter.patternToRegExp(_2d,_2e);
-}
-}
-for(var i=0;i<_2b.length;++i){
-var _30=true;
-var _31=_2b[i];
-for(key in _2a.query){
-_2d=_2a.query[key];
-if(!_28._containsValue(_31,key,_2d,_2f[key])){
-_30=false;
-}
-}
-if(_30){
-_2c.push(_31);
-}
-}
-}else{
-_2c=_2b.slice(0,_2b.length);
-}
-_26(_2c,_2a);
-};
-if(this._loadFinished){
-_29(_25,this._arrayOfAllItems);
-}else{
-if(this.url!==""){
-if(this._loadInProgress){
-this._queuedFetches.push({args:_25,filter:_29});
-}else{
-this._loadInProgress=true;
-var _32={url:_28.url,handleAs:"text",preventCache:_28.urlPreventCache};
-var _33=dojo.xhrGet(_32);
-_33.addCallback(function(_34){
-try{
-_28._processData(_34);
-_29(_25,_28._arrayOfAllItems);
-_28._handleQueuedFetches();
-}
-catch(e){
-_27(e,_25);
-}
-});
-_33.addErrback(function(_35){
-_28._loadInProgress=false;
-if(_27){
-_27(_35,_25);
-}else{
-throw _35;
-}
-});
-var _36=null;
-if(_25.abort){
-_36=_25.abort;
-}
-_25.abort=function(){
-var df=_33;
-if(df&&df.fired===-1){
-df.cancel();
-df=null;
-}
-if(_36){
-_36.call(_25);
-}
-};
-}
-}else{
-if(this._csvData){
-try{
-this._processData(this._csvData);
-this._csvData=null;
-_29(_25,this._arrayOfAllItems);
-}
-catch(e){
-_27(e,_25);
-}
-}else{
-var _37=new Error(this.declaredClass+": No CSV source data was provided as either URL or String data input.");
-if(_27){
-_27(_37,_25);
-}else{
-throw _37;
-}
-}
-}
-}
-},close:function(_38){
-},_getArrayOfArraysFromCsvFileContents:function(_39){
-if(dojo.isString(_39)){
-var _3a=new RegExp("^\\s+","g");
-var _3b=new RegExp("\\s+$","g");
-var _3c=new RegExp("\"\"","g");
-var _3d=[];
-var i;
-var _3e=this._splitLines(_39);
-for(i=0;i<_3e.length;++i){
-var _3f=_3e[i];
-if(_3f.length>0){
-var _40=_3f.split(this.separator);
-var j=0;
-while(j<_40.length){
-var _41=_40[j];
-var _42=_41.replace(_3a,"");
-var _43=_42.replace(_3b,"");
-var _44=_43.charAt(0);
-var _45=_43.charAt(_43.length-1);
-var _46=_43.charAt(_43.length-2);
-var _47=_43.charAt(_43.length-3);
-if(_43.length===2&&_43=="\"\""){
-_40[j]="";
-}else{
-if((_44=="\"")&&((_45!="\"")||((_45=="\"")&&(_46=="\"")&&(_47!="\"")))){
-if(j+1===_40.length){
-return;
-}
-var _48=_40[j+1];
-_40[j]=_42+this.separator+_48;
-_40.splice(j+1,1);
-}else{
-if((_44=="\"")&&(_45=="\"")){
-_43=_43.slice(1,(_43.length-1));
-_43=_43.replace(_3c,"\"");
-}
-_40[j]=_43;
-j+=1;
-}
-}
-}
-_3d.push(_40);
-}
-}
-this._attributes=_3d.shift();
-for(i=0;i<this._attributes.length;i++){
-this._attributeIndexes[this._attributes[i]]=i;
-}
-this._dataArray=_3d;
-}
-},_splitLines:function(_49){
-var _4a=[];
-var i;
-var _4b="";
-var _4c=false;
-for(i=0;i<_49.length;i++){
-var c=_49.charAt(i);
-switch(c){
-case "\"":
-_4c=!_4c;
-_4b+=c;
-break;
-case "\r":
-if(_4c){
-_4b+=c;
-}else{
-_4a.push(_4b);
-_4b="";
-if(i<(_49.length-1)&&_49.charAt(i+1)=="\n"){
-i++;
-}
-}
-break;
-case "\n":
-if(_4c){
-_4b+=c;
-}else{
-_4a.push(_4b);
-_4b="";
-}
-break;
-default:
-_4b+=c;
-}
-}
-if(_4b!==""){
-_4a.push(_4b);
-}
-return _4a;
-},_processData:function(_4d){
-this._getArrayOfArraysFromCsvFileContents(_4d);
-this._arrayOfAllItems=[];
-if(this.identifier){
-if(this._attributeIndexes[this.identifier]===undefined){
-throw new Error(this.declaredClass+": Identity specified is not a column header in the data set.");
-}
-}
-for(var i=0;i<this._dataArray.length;i++){
-var id=i;
-if(this.identifier){
-var _4e=this._dataArray[i];
-id=_4e[this._attributeIndexes[this.identifier]];
-this._idMap[id]=i;
-}
-this._arrayOfAllItems.push(this._createItemFromIdentity(id));
-}
-this._loadFinished=true;
-this._loadInProgress=false;
-},_createItemFromIdentity:function(_4f){
-var _50={};
-_50[this._storeProp]=this;
-_50[this._idProp]=_4f;
-return _50;
-},getIdentity:function(_51){
-if(this.isItem(_51)){
-return _51[this._idProp];
-}
-return null;
-},fetchItemByIdentity:function(_52){
-var _53;
-var _54=_52.scope?_52.scope:dojo.global;
-if(!this._loadFinished){
-var _55=this;
-if(this.url!==""){
-if(this._loadInProgress){
-this._queuedFetches.push({args:_52});
-}else{
-this._loadInProgress=true;
-var _56={url:_55.url,handleAs:"text"};
-var _57=dojo.xhrGet(_56);
-_57.addCallback(function(_58){
-try{
-_55._processData(_58);
-var _59=_55._createItemFromIdentity(_52.identity);
-if(!_55.isItem(_59)){
-_59=null;
-}
-if(_52.onItem){
-_52.onItem.call(_54,_59);
-}
-_55._handleQueuedFetches();
-}
-catch(error){
-if(_52.onError){
-_52.onError.call(_54,error);
-}
-}
-});
-_57.addErrback(function(_5a){
-this._loadInProgress=false;
-if(_52.onError){
-_52.onError.call(_54,_5a);
-}
+
+dojo.declare("dojox.data.CsvStore", null, {
+	// summary:
+	//		The CsvStore implements the dojo.data.api.Read API and reads
+	//		data from files in CSV (Comma Separated Values) format.
+	//		All values are simple string values. References to other items
+	//		are not supported as attribute values in this datastore.
+	//
+	//		Example data file:
+	//		name, color, age, tagline
+	//		Kermit, green, 12, "Hi, I'm Kermit the Frog."
+	//		Fozzie Bear, orange, 10, "Wakka Wakka Wakka!"
+	//		Miss Piggy, pink, 11, "Kermie!"
+	//
+	//		Note that values containing a comma must be enclosed with quotes ("")
+	//		Also note that values containing quotes must be escaped with two consecutive quotes (""quoted"")
+	//
+	// examples:
+	//		var csvStore = new dojox.data.CsvStore({url:"movies.csv");
+	//		var csvStore = new dojox.data.CsvStore({url:"http://example.com/movies.csv");
+
+	constructor: function(/* Object */ keywordParameters){
+		// summary: 
+		//		initializer
+		// keywordParameters: {url: String}
+		// keywordParameters: {data: String}
+		// keywordParameters: {label: String} The column label for the column to use for the label returned by getLabel.
+		// keywordParameters: {identifier: String} The column label for the column to use for the identity.  Optional.  If not set, the identity is the row number.
+		
+		this._attributes = [];			// e.g. ["Title", "Year", "Producer"]
+		this._attributeIndexes = {};	// e.g. {Title: 0, Year: 1, Producer: 2}
+ 		this._dataArray = [];			// e.g. [[<Item0>],[<Item1>],[<Item2>]]
+ 		this._arrayOfAllItems = [];		// e.g. [{_csvId:0,_csvStore:store},...]
+		this._loadFinished = false;
+		if(keywordParameters.url){
+			this.url = keywordParameters.url;
+		}
+		this._csvData = keywordParameters.data;
+		if(keywordParameters.label){
+			this.label = keywordParameters.label;
+		}else if(this.label === ""){
+			this.label = undefined;
+		}
+		this._storeProp = "_csvStore";	// Property name for the store reference on every item.
+		this._idProp = "_csvId"; 		// Property name for the Item Id on every item.
+		this._features = {	
+			'dojo.data.api.Read': true,
+			'dojo.data.api.Identity': true 
+		};
+		this._loadInProgress = false;	//Got to track the initial load to prevent duelling loads of the dataset.
+		this._queuedFetches = [];
+		this.identifier = keywordParameters.identifier;
+		if(this.identifier === ""){
+			delete this.identifier;
+		}else{
+			this._idMap = {};
+		}
+		if("separator" in keywordParameters){
+			this.separator = keywordParameters.separator;
+		}
+		if("urlPreventCache" in keywordParameters){
+			this.urlPreventCache = keywordParameters.urlPreventCache?true:false;
+		}
+	},
+
+	// url: [public] string
+	//		Declarative hook for setting Csv source url.		
+	url: "",
+
+	// label: [public] string
+	//		Declarative hook for setting the label attribute. 
+	label: "",
+
+	// identifier: [public] string
+	//		Declarative hook for setting the identifier.
+	identifier: "",
+
+	// separator: [public] string
+	//		Declatative and programmatic hook for defining the separator 
+	//		character used in the Csv style file. 
+	separator: ",",
+
+	// separator: [public] string
+	//		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.
+	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(this.declaredClass + ": a function was passed an item argument that was not an item");
+		}
+	},
+	
+	_getIndex: function(item){
+		// summary:
+		//		Internal function to get the internal index to the item data from the item handle
+		// item:
+		//		The idem handle to get the index for.
+		var idx = this.getIdentity(item);
+		if(this.identifier){
+			idx = this._idMap[idx];
+		}
+		return idx;
+	},
+
+/***************************************
+     dojo.data.api.Read API
+***************************************/
+	getValue: function(	/* item */ item, 
+						/* attribute || attribute-name-string */ attribute, 
+						/* value? */ defaultValue){
+		// summary: 
+		//      See dojo.data.api.Read.getValue()
+		//		Note that for the CsvStore, an empty string value is the same as no value, 
+		// 		so the defaultValue would be returned instead of an empty string.
+		this._assertIsItem(item);
+		var itemValue = defaultValue;
+		if(typeof attribute === "string"){
+			var ai = this._attributeIndexes[attribute];
+			if(ai != null){
+				var itemData = this._dataArray[this._getIndex(item)];
+				itemValue = itemData[ai] || defaultValue;
+			}
+		}else{
+			throw new Error(this.declaredClass + ": a function was passed an attribute argument that was not a string");
+		}
+		return itemValue; //String
+	},
+
+	getValues: function(/* item */ item, 
+						/* attribute || attribute-name-string */ attribute){
+		// summary: 
+		//		See dojo.data.api.Read.getValues()
+		// 		CSV syntax does not support multi-valued attributes, so this is just a
+		// 		wrapper function for getValue().
+		var value = this.getValue(item, attribute);
+		return (value ? [value] : []); //Array
+	},
+
+	getAttributes: function(/* item */ item){
+		// summary: 
+		//		See dojo.data.api.Read.getAttributes()
+		this._assertIsItem(item);
+		var attributes = [];
+		var itemData = this._dataArray[this._getIndex(item)];
+		for(var i=0; i<itemData.length; i++){
+			// Check for empty string values. CsvStore treats empty strings as no value.
+			if(itemData[i] !== ""){
+				attributes.push(this._attributes[i]);
+			}
+		}
+		return attributes; //Array
+	},
+
+	hasAttribute: function(	/* item */ item,
+							/* attribute-name-string */ attribute){
+		// summary: 
+		//		See dojo.data.api.Read.hasAttribute()
+		// 		The hasAttribute test is true if attribute has an index number within the item's array length
+		// 		AND if the item has a value for that attribute. Note that for the CsvStore, an
+		// 		empty string value is the same as no value.
+		this._assertIsItem(item);
+		if(typeof attribute === "string"){
+			var attributeIndex = this._attributeIndexes[attribute];
+			var itemData = this._dataArray[this._getIndex(item)];
+			return (typeof attributeIndex !== "undefined" && attributeIndex < itemData.length && itemData[attributeIndex] !== ""); //Boolean
+		}else{
+			throw new Error(this.declaredClass + ": a function was passed an attribute argument that was not a string");
+		}
+	},
+
+	containsValue: function(/* item */ item, 
+							/* attribute || 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 || 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'
+		// tags:
+		//		private
+		var values = this.getValues(item, attribute);
+		for(var i = 0; i < values.length; ++i){
+			var possibleValue = values[i];
+			if(typeof possibleValue === "string" && regexp){
+				return (possibleValue.match(regexp) !== null);
+			}else{
+				//Non-string matching.
+				if(value === possibleValue){
+					return true; // Boolean
+				}
+			}
+		}
+		return false; // Boolean
+	},
+
+	isItem: function(/* anything */ something){
+		// summary: 
+		//		See dojo.data.api.Read.isItem()
+		if(something && something[this._storeProp] === this){
+			var identity = something[this._idProp];
+			//If an identifier was specified, we have to look it up via that and the mapping,
+			//otherwise, just use row number.
+			if(this.identifier){
+				var data = this._dataArray[this._idMap[identity]];
+				if(data){
+					return true;
+				}
+			}else{
+				if(identity >= 0 && identity < this._dataArray.length){
+					return true; //Boolean
+				}
+			}
+		}
+		return false; //Boolean
+	},
+
+	isItemLoaded: function(/* anything */ something){
+		// summary: 
+		//		See dojo.data.api.Read.isItemLoaded()
+		//		The CsvStore always loads all items, so if it's an item, then it's loaded.
+		return this.isItem(something); //Boolean
+	},
+
+	loadItem: function(/* item */ item){
+		// summary: 
+		//		See dojo.data.api.Read.loadItem()
+		// description:
+		//		The CsvStore always loads all items, so if it's an item, then it's loaded.
+		//		From the dojo.data.api.Read.loadItem docs:
+		//			If a call to isItemLoaded() returns true before loadItem() is even called,
+		//			then loadItem() need not do any work at all and will not even invoke
+		//			the callback handlers.
+	},
+
+	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.label && this.isItem(item)){
+			return this.getValue(item,this.label); //String
+		}
+		return undefined; //undefined
+	},
+
+	getLabelAttributes: function(/* item */ item){
+		// summary: 
+		//		See dojo.data.api.Read.getLabelAttributes()
+		if(this.label){
+			return [this.label]; //array
+		}
+		return null; //null
+	},
+
+
+	// The dojo.data.api.Read.fetch() function is implemented as
+	// a mixin from dojo.data.util.simpleFetch.
+	// That mixin requires us to define _fetchItems().
+	_fetchItems: function(	/* Object */ keywordArgs, 
+							/* Function */ findCallback, 
+							/* Function */ errorCallback){
+		// summary: 
+		//		See dojo.data.util.simpleFetch.fetch()
+		// tags:
+		//		protected
+		var self = this;
+		var filter = function(requestArgs, arrayOfAllItems){
+			var items = null;
+			if(requestArgs.query){
+				var key, value;
+				items = [];
+				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(var i = 0; i < arrayOfAllItems.length; ++i){
+					var match = true;
+					var candidateItem = arrayOfAllItems[i];
+					for(key in requestArgs.query){
+						value = requestArgs.query[key];
+						if(!self._containsValue(candidateItem, key, value, regexpList[key])){
+							match = false;
+						}
+					}
+					if(match){
+						items.push(candidateItem);
+					}
+				}
+			}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.
+				items = arrayOfAllItems.slice(0,arrayOfAllItems.length); 
+				
+			}
+			findCallback(items, requestArgs);
+		};
+
+		if(this._loadFinished){
+			filter(keywordArgs, this._arrayOfAllItems);
+		}else{
+			if(this.url !== ""){
+				//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.url, 
+							handleAs: "text",
+							preventCache: self.urlPreventCache
+						};
+					var getHandler = dojo.xhrGet(getArgs);
+					getHandler.addCallback(function(data){
+						try{
+							self._processData(data);
+							filter(keywordArgs, self._arrayOfAllItems);
+							self._handleQueuedFetches();
+						}catch(e){
+							errorCallback(e, keywordArgs);
+						}
+					});
+					getHandler.addErrback(function(error){
+						self._loadInProgress = false;
+						if(errorCallback){
+							errorCallback(error, keywordArgs);
+						}else{
+							throw error;
+						}
+					});
+					//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._csvData){
+				try{
+					this._processData(this._csvData);
+					this._csvData = null;
+					filter(keywordArgs, this._arrayOfAllItems);
+				}catch(e){
+					errorCallback(e, keywordArgs);
+				}
+			}else{
+				var error = new Error(this.declaredClass + ": No CSV source data was provided as either URL or String data input.");
+				if(errorCallback){
+					errorCallback(error, keywordArgs);
+				}else{
+					throw error;
+				}
+			}
+		}
+	},
+	
+	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+		 //	summary: 
+		 //		See dojo.data.api.Read.close()
+	},
+	
+	
+	// -------------------------------------------------------------------
+	// Private methods
+	_getArrayOfArraysFromCsvFileContents: function(/* string */ csvFileContents){
+		// summary:
+		//		Parses a string of CSV records into a nested array structure.
+		// description:
+		//		Given a string containing CSV records, this method parses
+		//		the string and returns a data structure containing the parsed
+		//		content.  The data structure we return is an array of length
+		//		R, where R is the number of rows (lines) in the CSV data.  The 
+		//		return array contains one sub-array for each CSV line, and each 
+		//		sub-array contains C string values, where C is the number of 
+		//		columns in the CSV data.
+		// example:
+		//		For example, given this CSV string as input:
+		//			"Title, Year, Producer \n Alien, 1979, Ridley Scott \n Blade Runner, 1982, Ridley Scott"
+		//		this._dataArray will be set to:
+		//			[["Alien", "1979", "Ridley Scott"],
+		//			["Blade Runner", "1982", "Ridley Scott"]]
+		//		And this._attributes will be set to:
+		//			["Title", "Year", "Producer"]
+		//		And this._attributeIndexes will be set to:
+		//			{ "Title":0, "Year":1, "Producer":2 }
+		// tags:
+		//		private
+		if(dojo.isString(csvFileContents)){
+			var leadingWhiteSpaceCharacters = new RegExp("^\\s+",'g');
+			var trailingWhiteSpaceCharacters = new RegExp("\\s+$",'g');
+			var doubleQuotes = new RegExp('""','g');
+			var arrayOfOutputRecords = [];
+			var i;
+			
+			var arrayOfInputLines = this._splitLines(csvFileContents);
+			for(i = 0; i < arrayOfInputLines.length; ++i){
+				var singleLine = arrayOfInputLines[i];
+				if(singleLine.length > 0){
+					var listOfFields = singleLine.split(this.separator);
+					var j = 0;
+					while(j < listOfFields.length){
+						var space_field_space = listOfFields[j];
+						var field_space = space_field_space.replace(leadingWhiteSpaceCharacters, ''); // trim leading whitespace
+						var field = field_space.replace(trailingWhiteSpaceCharacters, ''); // trim trailing whitespace
+						var firstChar = field.charAt(0);
+						var lastChar = field.charAt(field.length - 1);
+						var secondToLastChar = field.charAt(field.length - 2);
+						var thirdToLastChar = field.charAt(field.length - 3);
+						if(field.length === 2 && field == "\"\""){
+							listOfFields[j] = ""; //Special case empty string field.
+						}else if((firstChar == '"') && 
+								((lastChar != '"') || 
+								 ((lastChar == '"') && (secondToLastChar == '"') && (thirdToLastChar != '"')))){
+							if(j+1 === listOfFields.length){
+								// alert("The last field in record " + i + " is corrupted:\n" + field);
+								return; //null
+							}
+							var nextField = listOfFields[j+1];
+							listOfFields[j] = field_space + this.separator + nextField;
+							listOfFields.splice(j+1, 1); // delete element [j+1] from the list
+						}else{
+							if((firstChar == '"') && (lastChar == '"')){
+								field = field.slice(1, (field.length - 1)); // trim the " characters off the ends
+								field = field.replace(doubleQuotes, '"'); // replace "" with "
+							}
+							listOfFields[j] = field;
+							j += 1;
+						}
+					}
+					arrayOfOutputRecords.push(listOfFields);
+				}
+			}
+			
+			// The first item of the array must be the header row with attribute names.
+			this._attributes = arrayOfOutputRecords.shift();
+			for(i = 0; i<this._attributes.length; i++){
+				// Store the index of each attribute 
+				this._attributeIndexes[this._attributes[i]] = i;
+			}
+			this._dataArray = arrayOfOutputRecords; //Array
+		}
+	},
+
+	_splitLines: function(csvContent){
+		// summary:
+		//		Function to split the CSV file contents into separate lines.
+		//		Since line breaks can occur inside quotes, a Regexp didn't
+		//		work as well.  A quick passover parse should be just as efficient.
+		// tags:
+		//		private
+		var split = [];
+		var i;
+		var line = "";
+		var inQuotes = false;
+		for(i = 0; i < csvContent.length; i++){
+			var c = csvContent.charAt(i);
+			switch(c){
+				case '\"':
+					inQuotes = !inQuotes;
+					line += c;
+					break;
+				case '\r':
+					if(inQuotes){
+						line += c;
+					}else{
+						split.push(line);
+						line = "";
+						if(i < (csvContent.length - 1) && csvContent.charAt(i + 1) == '\n'){
+							i++; //Skip it, it's CRLF
+						}
+					}
+					break;
+				case '\n':
+					if(inQuotes){
+						line += c;
+					}else{
+						split.push(line);
+						line = "";
+					}
+					break;
+				default:
+					line +=c;
+			}
+		}
+		if(line !== ""){
+			split.push(line);
+		}
+		return split;
+	},
+	
+	_processData: function(/* String */ data){
+		// summary:
+		//		Function for processing the string data from the server.
+		// data: String
+		//		The CSV data.
+		// tags:
+		//		private
+		this._getArrayOfArraysFromCsvFileContents(data);
+		this._arrayOfAllItems = [];
+
+		//Check that the specified Identifier is actually a column title, if provided.
+		if(this.identifier){
+			if(this._attributeIndexes[this.identifier] === undefined){
+				throw new Error(this.declaredClass + ": Identity specified is not a column header in the data set.");
+			}
+		}
+
+		for(var i=0; i<this._dataArray.length; i++){
+			var id = i;
+			//Associate the identifier to a row in this case
+			//for o(1) lookup.
+			if(this.identifier){
+				var iData = this._dataArray[i];
+				id = iData[this._attributeIndexes[this.identifier]];
+				this._idMap[id] = i;
+			}
+			this._arrayOfAllItems.push(this._createItemFromIdentity(id));
+		}
+		this._loadFinished = true;
+		this._loadInProgress = false;
+	},
+	
+	_createItemFromIdentity: function(/* String */ identity){
+		// summary:
+		//		Function for creating a new item from its identifier.
+		// identity: String
+		//		The identity
+		// tags:
+		//		private
+		var item = {};
+		item[this._storeProp] = this;
+		item[this._idProp] = identity;
+		return item; //Object
+	},
+	
+	
+/***************************************
+     dojo.data.api.Identity API
+***************************************/
+	getIdentity: function(/* item */ item){
+		// summary: 
+		//		See dojo.data.api.Identity.getIdentity()
+		// tags:
+		//		public
+		if(this.isItem(item)){
+			return item[this._idProp]; //String
+		}
+		return null; //null
+	},
+
+	fetchItemByIdentity: function(/* Object */ keywordArgs){
+		// summary: 
+		//		See dojo.data.api.Identity.fetchItemByIdentity()
+		// tags:
+		//		public
+		var item;
+		var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+		//Hasn't loaded yet, we have to trigger the load.
+		if(!this._loadFinished){
+			var self = this;
+			if(this.url !== ""){
+				//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});
+				}else{
+					this._loadInProgress = true;
+					var getArgs = {
+							url: self.url, 
+							handleAs: "text"
+						};
+					var getHandler = dojo.xhrGet(getArgs);
+					getHandler.addCallback(function(data){
+						try{
+							self._processData(data);
+							var item = self._createItemFromIdentity(keywordArgs.identity);
+							if(!self.isItem(item)){
+								item = null;
+							}
+							if(keywordArgs.onItem){
+								keywordArgs.onItem.call(scope, item);
+							}
+							self._handleQueuedFetches();
+						}catch(error){
+							if(keywordArgs.onError){
+								keywordArgs.onError.call(scope, error);
+							}
+						}
+					});
+					getHandler.addErrback(function(error){
+						this._loadInProgress = false;
+						if(keywordArgs.onError){
+							keywordArgs.onError.call(scope, error);
+						}
+					});
+				}
+			}else if(this._csvData){
+				try{
+					self._processData(self._csvData);
+					self._csvData = null;
+					item = self._createItemFromIdentity(keywordArgs.identity);
+					if(!self.isItem(item)){
+						item = null;
+					}
+					if(keywordArgs.onItem){
+						keywordArgs.onItem.call(scope, item);
+					}
+				}catch(e){
+					if(keywordArgs.onError){
+						keywordArgs.onError.call(scope, e);
+					}
+				}
+			}
+		}else{
+			//Already loaded.  We can just look it up and call back.
+			item = this._createItemFromIdentity(keywordArgs.identity);
+			if(!this.isItem(item)){
+				item = null;
+			}
+			if(keywordArgs.onItem){
+				keywordArgs.onItem.call(scope, item);
+			}
+		}
+	},
+
+	getIdentityAttributes: function(/* item */ item){
+		// summary: 
+		//		See dojo.data.api.Identity.getIdentifierAttributes()
+		// tags:
+		//		public
+		 
+		//Identity isn't a public attribute in the item, it's the row position index.
+		//So, return null.
+		if(this.identifier){
+			return [this.identifier];
+		}else{
+			return null;
+		}
+	},
+
+	_handleQueuedFetches: function(){
+		// summary: 
+		//		Internal function to execute delayed request in the store.
+		// tags:
+		//		private
+
+		//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 delayedFilter = fData.filter;
+				var delayedQuery = fData.args;
+				if(delayedFilter){
+					delayedFilter(delayedQuery, this._arrayOfAllItems); 
+				}else{
+					this.fetchItemByIdentity(fData.args);
+				}
+			}
+			this._queuedFetches = [];
+		}
+	}
 });
-}
-}else{
-if(this._csvData){
-try{
-_55._processData(_55._csvData);
-_55._csvData=null;
-_53=_55._createItemFromIdentity(_52.identity);
-if(!_55.isItem(_53)){
-_53=null;
-}
-if(_52.onItem){
-_52.onItem.call(_54,_53);
-}
-}
-catch(e){
-if(_52.onError){
-_52.onError.call(_54,e);
-}
-}
-}
-}
-}else{
-_53=this._createItemFromIdentity(_52.identity);
-if(!this.isItem(_53)){
-_53=null;
-}
-if(_52.onItem){
-_52.onItem.call(_54,_53);
-}
-}
-},getIdentityAttributes:function(_5b){
-if(this.identifier){
-return [this.identifier];
-}else{
-return null;
-}
-},_handleQueuedFetches:function(){
-if(this._queuedFetches.length>0){
-for(var i=0;i<this._queuedFetches.length;i++){
-var _5c=this._queuedFetches[i];
-var _5d=_5c.filter;
-var _5e=_5c.args;
-if(_5d){
-_5d(_5e,this._arrayOfAllItems);
-}else{
-this.fetchItemByIdentity(_5c.args);
-}
-}
-this._queuedFetches=[];
-}
-}});
+//Mix in the simple fetch implementation to this class.
 dojo.extend(dojox.data.CsvStore,dojo.data.util.simpleFetch);
-}
diff --git a/dojox/data/FileStore.js b/dojox/data/FileStore.js
old mode 100644
new mode 100755
index dd7b37b..6ff11bc
--- a/dojox/data/FileStore.js
+++ b/dojox/data/FileStore.js
@@ -1,239 +1,429 @@
-/*
-	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
-*/
+dojo.provide("dojox.data.FileStore");
 
+dojo.declare("dojox.data.FileStore", null, {
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		A simple store that provides a datastore interface to a filesystem.
+		//	description:
+		//		A simple store that provides a datastore interface to a filesystem.  It takes a few parameters
+		//		for initialization:
+		//			url:	The URL of the service which provides the file store serverside implementation.
+		//			label:	The attribute of the file to use as the huma-readable text.  Default is 'name'.
+		//		The purpose of this store is to represent a file as a datastore item.  The
+		//		datastore item by default has the following attributes that can be examined on it.
+		//			directory:	Boolean indicating if the file item represents a directory.
+		//			name:	The filename with no path informatiom.
+		//			path:	The file complete file path including name, relative to the location the
+		//					file service scans from
+		//			size:	The size of the file, in bytes.
+		//			parentDir:	The parent directory path.
+		//			children:	Any child files contained by a directory file item.
+		//
+		//		Note that the store's server call pattern is RESTlike.
+		//
+		//		The store also supports the passing of configurable options to the back end service, such as
+		//		expanding all child files (no lazy load), displaying hidden files, displaying only directories, and so on.
+		//		These are defined through a comma-separated list in declarative, or through setting the options array in programmatic.
+		//		example:	options="expand,dirsOnly,showHiddenFiles"
+		if(args && args.label){
+			this.label = args.label;
+		}
+		if(args && args.url){
+			this.url = args.url;
+		}
+		if(args && args.options){
+			if(dojo.isArray(args.options)){
+				this.options = args.options;
+			}else{
+				if(dojo.isString(args.options)){
+					this.options = args.options.split(",");
+				}
+			}
+		}
+		if(args && args.pathAsQueryParam){
+			this.pathAsQueryParam = true;
+		}
+		if(args && "urlPreventCache" in args){
+			this.urlPreventCache = args.urlPreventCache?true:false;
+		}
+	},
 
-if(!dojo._hasResource["dojox.data.FileStore"]){
-dojo._hasResource["dojox.data.FileStore"]=true;
-dojo.provide("dojox.data.FileStore");
-dojo.declare("dojox.data.FileStore",null,{constructor:function(_1){
-if(_1&&_1.label){
-this.label=_1.label;
-}
-if(_1&&_1.url){
-this.url=_1.url;
-}
-if(_1&&_1.options){
-if(dojo.isArray(_1.options)){
-this.options=_1.options;
-}else{
-if(dojo.isString(_1.options)){
-this.options=_1.options.split(",");
-}
-}
-}
-if(_1&&_1.pathAsQueryParam){
-this.pathAsQueryParam=true;
-}
-if(_1&&"urlPreventCache" in _1){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-},url:"",_storeRef:"_S",label:"name",_identifier:"path",_attributes:["children","directory","name","path","modified","size","parentDir"],pathSeparator:"/",options:[],failOk:false,urlPreventCache:true,_assertIsItem:function(_2){
-if(!this.isItem(_2)){
-throw new Error("dojox.data.FileStore: a function was passed an item argument that was not an item");
-}
-},_assertIsAttribute:function(_3){
-if(typeof _3!=="string"){
-throw new Error("dojox.data.FileStore: a function was passed an attribute argument that was not an attribute name string");
-}
-},pathAsQueryParam:false,getFeatures:function(){
-return {"dojo.data.api.Read":true,"dojo.data.api.Identity":true};
-},getValue:function(_4,_5,_6){
-var _7=this.getValues(_4,_5);
-if(_7&&_7.length>0){
-return _7[0];
-}
-return _6;
-},getAttributes:function(_8){
-return this._attributes;
-},hasAttribute:function(_9,_a){
-this._assertIsItem(_9);
-this._assertIsAttribute(_a);
-return (_a in _9);
-},getIdentity:function(_b){
-return this.getValue(_b,this._identifier);
-},getIdentityAttributes:function(_c){
-return [this._identifier];
-},isItemLoaded:function(_d){
-var _e=this.isItem(_d);
-if(_e&&typeof _d._loaded=="boolean"&&!_d._loaded){
-_e=false;
-}
-return _e;
-},loadItem:function(_f){
-var _10=_f.item;
-var _11=this;
-var _12=_f.scope||dojo.global;
-var _13={};
-if(this.options.length>0){
-_13.options=dojo.toJson(this.options);
-}
-if(this.pathAsQueryParam){
-_13.path=_10.parentPath+this.pathSeparator+_10.name;
-}
-var _14={url:this.pathAsQueryParam?this.url:this.url+"/"+_10.parentPath+"/"+_10.name,handleAs:"json-comment-optional",content:_13,preventCache:this.urlPreventCache,failOk:this.failOk};
-var _15=dojo.xhrGet(_14);
-_15.addErrback(function(_16){
-if(_f.onError){
-_f.onError.call(_12,_16);
-}
-});
-_15.addCallback(function(_17){
-delete _10.parentPath;
-delete _10._loaded;
-dojo.mixin(_10,_17);
-_11._processItem(_10);
-if(_f.onItem){
-_f.onItem.call(_12,_10);
-}
-});
-},getLabel:function(_18){
-return this.getValue(_18,this.label);
-},getLabelAttributes:function(_19){
-return [this.label];
-},containsValue:function(_1a,_1b,_1c){
-var _1d=this.getValues(_1a,_1b);
-for(var i=0;i<_1d.length;i++){
-if(_1d[i]==_1c){
-return true;
-}
-}
-return false;
-},getValues:function(_1e,_1f){
-this._assertIsItem(_1e);
-this._assertIsAttribute(_1f);
-var _20=_1e[_1f];
-if(typeof _20!=="undefined"&&!dojo.isArray(_20)){
-_20=[_20];
-}else{
-if(typeof _20==="undefined"){
-_20=[];
-}
-}
-return _20;
-},isItem:function(_21){
-if(_21&&_21[this._storeRef]===this){
-return true;
-}
-return false;
-},close:function(_22){
-},fetch:function(_23){
-_23=_23||{};
-if(!_23.store){
-_23.store=this;
-}
-var _24=this;
-var _25=_23.scope||dojo.global;
-var _26={};
-if(_23.query){
-_26.query=dojo.toJson(_23.query);
-}
-if(_23.sort){
-_26.sort=dojo.toJson(_23.sort);
-}
-if(_23.queryOptions){
-_26.queryOptions=dojo.toJson(_23.queryOptions);
-}
-if(typeof _23.start=="number"){
-_26.start=""+_23.start;
-}
-if(typeof _23.count=="number"){
-_26.count=""+_23.count;
-}
-if(this.options.length>0){
-_26.options=dojo.toJson(this.options);
-}
-var _27={url:this.url,preventCache:this.urlPreventCache,failOk:this.failOk,handleAs:"json-comment-optional",content:_26};
-var _28=dojo.xhrGet(_27);
-_28.addCallback(function(_29){
-_24._processResult(_29,_23);
-});
-_28.addErrback(function(_2a){
-if(_23.onError){
-_23.onError.call(_25,_2a,_23);
-}
-});
-},fetchItemByIdentity:function(_2b){
-var _2c=_2b.identity;
-var _2d=this;
-var _2e=_2b.scope||dojo.global;
-var _2f={};
-if(this.options.length>0){
-_2f.options=dojo.toJson(this.options);
-}
-if(this.pathAsQueryParam){
-_2f.path=_2c;
-}
-var _30={url:this.pathAsQueryParam?this.url:this.url+"/"+_2c,handleAs:"json-comment-optional",content:_2f,preventCache:this.urlPreventCache,failOk:this.failOk};
-var _31=dojo.xhrGet(_30);
-_31.addErrback(function(_32){
-if(_2b.onError){
-_2b.onError.call(_2e,_32);
-}
-});
-_31.addCallback(function(_33){
-var _34=_2d._processItem(_33);
-if(_2b.onItem){
-_2b.onItem.call(_2e,_34);
-}
+	// url: [public] string
+	//		The URL to the file path service.
+	url: "",
+	
+	// _storeRef: [private] string
+	//		Internal variable used to denote an item came from this store instance.
+	_storeRef: "_S",
+
+	// label: [public] string
+	//		Default attribute to use to represent the item as a user-readable 
+	//		string.  Public, so users can change it.
+	label: "name",
+
+	// _identifier: [private] string
+	//		Default attribute to use to represent the item's identifier.  
+	//		Path should always be unique in the store instance.		
+	_identifier: "path",	
+
+	// _attributes: [private] string
+	//		Internal variable of attributes all file items should have.
+	_attributes: ["children", "directory", "name", "path", "modified", "size", "parentDir"], //
+	
+	// pathSeparator: [public] string
+	//		The path separator to use when chaining requests for children
+	//		Can be overriden by the server on initial load
+	pathSeparator: "/",
+
+	// options: [public] array
+	//		Array of options to always send when doing requests.  
+	//		Back end service controls this, like 'dirsOnly', 'showHiddenFiles', 'expandChildren', etc.
+	options: [],
+
+	// failOk: [public] boolean
+	//		Flag to pass on to xhr functions to check if we are OK to fail the call silently
+	failOk: false,
+
+	// urlPreventCache: [public] string
+	//		Flag to dennote if preventCache should be passed to xhrGet.
+	urlPreventCache: true,
+
+	_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("dojox.data.FileStore: a function was passed an item argument that was not an item");
+		}
+	},
+
+	_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("dojox.data.FileStore: a function was passed an attribute argument that was not an attribute name string");
+		}
+	},
+
+	pathAsQueryParam: false, //Function to switch between REST style URL lookups and passing the path to specific items as a query param: 'path'.
+
+	getFeatures: function(){
+		// summary: 
+		//      See dojo.data.api.Read.getFeatures()
+		return {
+			'dojo.data.api.Read': true, 'dojo.data.api.Identity':true
+		};
+	},
+
+	getValue: function(item, attribute, defaultValue){
+		// summary: 
+		//      See dojo.data.api.Read.getValue()
+		var values = this.getValues(item, attribute);
+		if(values && values.length > 0){
+			return values[0];
+		}
+		return defaultValue;
+	},
+
+	getAttributes: function(item){
+		// summary: 
+		//      See dojo.data.api.Read.getAttributes()
+		return this._attributes; 
+	},
+
+	hasAttribute: function(item, attribute){
+		// summary: 
+		//      See dojo.data.api.Read.hasAttribute()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		return (attribute in item);
+	},
+	
+	getIdentity: function(/* item */ item){
+		// summary: 
+		//		See dojo.data.api.Identity.getIdentity()
+		return this.getValue(item, this._identifier); 
+	},
+	
+	getIdentityAttributes: function(item){
+		// summary: 
+		//      See dojo.data.api.Read.getLabelAttributes()
+		return [this._identifier];
+	},
+
+
+	isItemLoaded: function(item){
+		 //	summary: 
+		 //      See dojo.data.api.Read.isItemLoaded()
+		 var loaded = this.isItem(item);
+		 if(loaded && typeof item._loaded == "boolean" && !item._loaded){
+		 	loaded = false; 
+		 }
+		 return loaded;
+	},
+
+	loadItem: function(keywordArgs){
+		// summary: 
+		//      See dojo.data.api.Read.loadItem()
+		var item = keywordArgs.item;
+		var self = this;
+		var scope = keywordArgs.scope || dojo.global;
+
+		var content = {};
+
+		if(this.options.length > 0){
+			content.options = dojo.toJson(this.options);
+		}
+
+		if(this.pathAsQueryParam){
+			content.path = item.parentPath + this.pathSeparator + item.name;
+		}
+		var xhrData = {
+			url: this.pathAsQueryParam? this.url : this.url + "/" + item.parentPath + "/" + item.name,
+			handleAs: "json-comment-optional",
+			content: content,
+			preventCache: this.urlPreventCache,
+			failOk: this.failOk
+		};
+
+		var deferred = dojo.xhrGet(xhrData);
+		deferred.addErrback(function(error){
+				if(keywordArgs.onError){
+					keywordArgs.onError.call(scope, error);
+				}
+		});
+		
+		deferred.addCallback(function(data){
+			delete item.parentPath;
+			delete item._loaded;
+			dojo.mixin(item, data);
+			self._processItem(item);
+			if(keywordArgs.onItem){
+				keywordArgs.onItem.call(scope, item);
+			}
+		});
+	},
+
+	getLabel: function(item){
+		// summary: 
+		//      See dojo.data.api.Read.getLabel()
+		return this.getValue(item,this.label);
+	},
+	
+	getLabelAttributes: function(item){
+		// summary: 
+		//      See dojo.data.api.Read.getLabelAttributes()
+		return [this.label];
+	},
+	
+	containsValue: function(item, attribute, value){
+		// summary: 
+		//      See dojo.data.api.Read.containsValue()
+		var values = this.getValues(item,attribute);
+		for(var i = 0; i < values.length; i++){
+			if(values[i] == value){
+				return true;
+			}
+		}
+		return false;
+	},
+
+	getValues: function(item, attribute){
+		// summary: 
+		//      See dojo.data.api.Read.getValue()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		
+		var value = item[attribute];
+		if(typeof value !== "undefined" && !dojo.isArray(value)){
+			value = [value];
+		}else if(typeof value === "undefined"){	
+			value = [];
+		}
+		return value;
+	},
+
+	isItem: function(item){
+		// summary: 
+		//      See dojo.data.api.Read.isItem()
+		if(item && item[this._storeRef] === this){
+			return true;
+		}
+		return false;
+	},
+	
+	close: function(request){
+		// summary: 
+		//      See dojo.data.api.Read.close()
+	},
+
+	fetch: function(request){
+		// summary:
+		//		Fetch  items that match to a query
+		// request:
+		//		A request object
+
+		request = request || {};
+		if(!request.store){
+			request.store = this;
+		}
+		var self = this;
+		var scope = request.scope || dojo.global;
+
+		//Generate what will be sent over.
+		var reqParams = {};
+		if(request.query){
+			reqParams.query = dojo.toJson(request.query);
+		}
+
+		if(request.sort){
+			reqParams.sort = dojo.toJson(request.sort);
+		}
+
+		if(request.queryOptions){
+			reqParams.queryOptions = dojo.toJson(request.queryOptions);
+		}
+
+		if(typeof request.start == "number"){
+			reqParams.start = "" + request.start;
+		}
+		if(typeof request.count == "number"){
+			reqParams.count = "" + request.count;
+		}
+
+		if(this.options.length > 0){
+			reqParams.options = dojo.toJson(this.options);
+		}
+
+		var getArgs = {
+			url: this.url,
+			preventCache: this.urlPreventCache,
+			failOk: this.failOk,
+			handleAs: "json-comment-optional",
+			content: reqParams
+		};
+
+
+		var deferred = dojo.xhrGet(getArgs);
+
+		deferred.addCallback(function(data){self._processResult(data, request);});
+		deferred.addErrback(function(error){
+			if(request.onError){
+				request.onError.call(scope, error, request);
+			}
+		});
+	},
+
+	fetchItemByIdentity: function(keywordArgs){
+		// summary: 
+		//      See dojo.data.api.Read.loadItem()
+		var path = keywordArgs.identity;
+		var self = this;
+		var scope = keywordArgs.scope || dojo.global;
+
+		var content = {};
+
+		if(this.options.length > 0){
+			content.options = dojo.toJson(this.options);
+		}
+
+		if(this.pathAsQueryParam){
+			content.path = path;
+		}
+		var xhrData = {
+			url: this.pathAsQueryParam? this.url : this.url + "/" + path,
+			handleAs: "json-comment-optional",
+			content: content,
+			preventCache: this.urlPreventCache,
+			failOk: this.failOk
+		};
+
+		var deferred = dojo.xhrGet(xhrData);
+		deferred.addErrback(function(error){
+				if(keywordArgs.onError){
+					keywordArgs.onError.call(scope, error);
+				}
+		});
+		
+		deferred.addCallback(function(data){
+			var item = self._processItem(data);
+			if(keywordArgs.onItem){
+				keywordArgs.onItem.call(scope, item);
+			}
+		});
+	},
+
+	_processResult: function(data, request){
+		 var scope = request.scope || dojo.global;
+		 try{
+			 //If the data contains a path separator, set ours
+			 if(data.pathSeparator){
+				 this.pathSeparator = data.pathSeparator;
+			 }
+			 //Invoke the onBegin handler, if any, to return the
+			 //size of the dataset as indicated by the service.
+			 if(request.onBegin){
+				 request.onBegin.call(scope, data.total, request);
+			 }
+			 //Now process all the returned items thro
+			 var items = this._processItemArray(data.items);
+			 if(request.onItem){
+				var i;
+				for(i = 0; i < items.length; i++){
+					request.onItem.call(scope, items[i], request);
+				}
+				items = null;
+			 }
+			 if(request.onComplete){
+				 request.onComplete.call(scope, items, request);
+			 }
+		 }catch (e){
+			 if(request.onError){
+				 request.onError.call(scope, e, request);
+			 }else{
+				 console.log(e);
+			 }
+		 }
+	},
+	
+	_processItemArray: function(itemArray){
+		 //	summary:
+		 //		Internal function for processing an array of items for return.
+		 var i;
+		 for(i = 0; i < itemArray.length; i++){
+		 	this._processItem(itemArray[i]);
+		 }
+		 return itemArray;
+	},
+	
+	_processItem: function(item){
+		//	summary:
+		//		Internal function for processing an item returned from the store.
+		//		It sets up the store ref as well as sets up the attributes necessary
+		//		to invoke a lazy load on a child, if there are any.
+		if(!item){return null;}
+		item[this._storeRef] = this;
+		if(item.children && item.directory){
+			if(dojo.isArray(item.children)){
+				var children = item.children;
+				var i;
+				for(i = 0; i < children.length; i++ ){
+					var name = children[i];
+					if(dojo.isObject(name)){
+						children[i] = this._processItem(name);
+					}else{
+						children[i] = {name: name, _loaded: false, parentPath: item.path};
+						children[i][this._storeRef] = this;
+					}
+				}
+			}else{
+				delete item.children;
+			}
+		}
+		return item;
+	}
 });
-},_processResult:function(_35,_36){
-var _37=_36.scope||dojo.global;
-try{
-if(_35.pathSeparator){
-this.pathSeparator=_35.pathSeparator;
-}
-if(_36.onBegin){
-_36.onBegin.call(_37,_35.total,_36);
-}
-var _38=this._processItemArray(_35.items);
-if(_36.onItem){
-var i;
-for(i=0;i<_38.length;i++){
-_36.onItem.call(_37,_38[i],_36);
-}
-_38=null;
-}
-if(_36.onComplete){
-_36.onComplete.call(_37,_38,_36);
-}
-}
-catch(e){
-if(_36.onError){
-_36.onError.call(_37,e,_36);
-}else{
-}
-}
-},_processItemArray:function(_39){
-var i;
-for(i=0;i<_39.length;i++){
-this._processItem(_39[i]);
-}
-return _39;
-},_processItem:function(_3a){
-if(!_3a){
-return null;
-}
-_3a[this._storeRef]=this;
-if(_3a.children&&_3a.directory){
-if(dojo.isArray(_3a.children)){
-var _3b=_3a.children;
-var i;
-for(i=0;i<_3b.length;i++){
-var _3c=_3b[i];
-if(dojo.isObject(_3c)){
-_3b[i]=this._processItem(_3c);
-}else{
-_3b[i]={name:_3c,_loaded:false,parentPath:_3a.path};
-_3b[i][this._storeRef]=this;
-}
-}
-}else{
-delete _3a.children;
-}
-}
-return _3a;
-}});
-}
+
diff --git a/dojox/data/FlickrRestStore.js b/dojox/data/FlickrRestStore.js
index 7b52d0f..c6d0cc2 100644
--- a/dojox/data/FlickrRestStore.js
+++ b/dojox/data/FlickrRestStore.js
@@ -1,296 +1,482 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.FlickrRestStore"]){
-dojo._hasResource["dojox.data.FlickrRestStore"]=true;
 dojo.provide("dojox.data.FlickrRestStore");
+
 dojo.require("dojox.data.FlickrStore");
-dojo.declare("dojox.data.FlickrRestStore",dojox.data.FlickrStore,{constructor:function(_1){
-if(_1){
-if(_1.label){
-this.label=_1.label;
-}
-if(_1.apikey){
-this._apikey=_1.apikey;
-}
-}
-this._cache=[];
-this._prevRequests={};
-this._handlers={};
-this._prevRequestRanges=[];
-this._maxPhotosPerUser={};
-this._id=dojox.data.FlickrRestStore.prototype._id++;
-},_id:0,_requestCount:0,_flickrRestUrl:"http://www.flickr.com/services/rest/",_apikey:null,_storeRef:"_S",_cache:null,_prevRequests:null,_handlers:null,_sortAttributes:{"date-posted":true,"date-taken":true,"interestingness":true},_fetchItems:function(_2,_3,_4){
-var _5={};
-if(!_2.query){
-_2.query=_5={};
-}else{
-dojo.mixin(_5,_2.query);
-}
-var _6=[];
-var _7=[];
-var _8={format:"json",method:"flickr.photos.search",api_key:this._apikey,extras:"owner_name,date_upload,date_taken"};
-var _9=false;
-if(_5.userid){
-_9=true;
-_8.user_id=_2.query.userid;
-_6.push("userid"+_2.query.userid);
-}
-if(_5.groupid){
-_9=true;
-_8.group_id=_5.groupid;
-_6.push("groupid"+_5.groupid);
-}
-if(_5.apikey){
-_9=true;
-_8.api_key=_2.query.apikey;
-_7.push("api"+_2.query.apikey);
-}else{
-if(_8.api_key){
-_9=true;
-_2.query.apikey=_8.api_key;
-_7.push("api"+_8.api_key);
-}else{
-throw Error("dojox.data.FlickrRestStore: An API key must be specified.");
-}
-}
-_2._curCount=_2.count;
-if(_5.page){
-_8.page=_2.query.page;
-_7.push("page"+_8.page);
-}else{
-if(("start" in _2)&&_2.start!==null){
-if(!_2.count){
-_2.count=20;
-}
-var _a=_2.start%_2.count;
-var _b=_2.start,_c=_2.count;
-if(_a!==0){
-if(_b<_c/2){
-_c=_b+_c;
-_b=0;
-}else{
-var _d=20,_e=2;
-for(var i=_d;i>0;i--){
-if(_b%i===0&&(_b/i)>=_c){
-_e=i;
-break;
-}
-}
-_c=_b/_e;
-}
-_2._realStart=_2.start;
-_2._realCount=_2.count;
-_2._curStart=_b;
-_2._curCount=_c;
-}else{
-_2._realStart=_2._realCount=null;
-_2._curStart=_2.start;
-_2._curCount=_2.count;
-}
-_8.page=(_b/_c)+1;
-_7.push("page"+_8.page);
-}
-}
-if(_2._curCount){
-_8.per_page=_2._curCount;
-_7.push("count"+_2._curCount);
-}
-if(_5.lang){
-_8.lang=_2.query.lang;
-_6.push("lang"+_2.lang);
-}
-if(_5.setid){
-_8.method="flickr.photosets.getPhotos";
-_8.photoset_id=_2.query.setid;
-_6.push("set"+_2.query.setid);
-}
-if(_5.tags){
-if(_5.tags instanceof Array){
-_8.tags=_5.tags.join(",");
-}else{
-_8.tags=_5.tags;
-}
-_6.push("tags"+_8.tags);
-if(_5["tag_mode"]&&(_5.tag_mode.toLowerCase()==="any"||_5.tag_mode.toLowerCase()==="all")){
-_8.tag_mode=_5.tag_mode;
-}
-}
-if(_5.text){
-_8.text=_5.text;
-_6.push("text:"+_5.text);
-}
-if(_5.sort&&_5.sort.length>0){
-if(!_5.sort[0].attribute){
-_5.sort[0].attribute="date-posted";
-}
-if(this._sortAttributes[_5.sort[0].attribute]){
-if(_5.sort[0].descending){
-_8.sort=_5.sort[0].attribute+"-desc";
-}else{
-_8.sort=_5.sort[0].attribute+"-asc";
-}
-}
-}else{
-_8.sort="date-posted-asc";
-}
-_6.push("sort:"+_8.sort);
-_6=_6.join(".");
-_7=_7.length>0?"."+_7.join("."):"";
-var _f=_6+_7;
-_2={query:_5,count:_2._curCount,start:_2._curStart,_realCount:_2._realCount,_realStart:_2._realStart,onBegin:_2.onBegin,onComplete:_2.onComplete,onItem:_2.onItem};
-var _10={request:_2,fetchHandler:_3,errorHandler:_4};
-if(this._handlers[_f]){
-this._handlers[_f].push(_10);
-return;
-}
-this._handlers[_f]=[_10];
-var _11=null;
-var _12={url:this._flickrRestUrl,preventCache:this.urlPreventCache,content:_8,callbackParamName:"jsoncallback"};
-var _13=dojo.hitch(this,function(_14,_15,_16){
-var _17=_16.request.onBegin;
-_16.request.onBegin=null;
-var _18;
-var req=_16.request;
-if(("_realStart" in req)&&req._realStart!=null){
-req.start=req._realStart;
-req.count=req._realCount;
-req._realStart=req._realCount=null;
-}
-if(_17){
-var _19=null;
-if(_15){
-_19=(_15.photoset?_15.photoset:_15.photos);
-}
-if(_19&&("perpage" in _19)&&("pages" in _19)){
-if(_19.perpage*_19.pages<=_16.request.start+_16.request.count){
-_18=_16.request.start+_19.photo.length;
-}else{
-_18=_19.perpage*_19.pages;
-}
-this._maxPhotosPerUser[_6]=_18;
-_17(_18,_16.request);
-}else{
-if(this._maxPhotosPerUser[_6]){
-_17(this._maxPhotosPerUser[_6],_16.request);
-}
-}
-}
-_16.fetchHandler(_14,_16.request);
-if(_17){
-_16.request.onBegin=_17;
-}
-});
-var _1a=dojo.hitch(this,function(_1b){
-if(_1b.stat!="ok"){
-_4(null,_2);
-}else{
-var _1c=this._handlers[_f];
-if(!_1c){
-return;
-}
-this._handlers[_f]=null;
-this._prevRequests[_f]=_1b;
-var _1d=this._processFlickrData(_1b,_2,_6);
-if(!this._prevRequestRanges[_6]){
-this._prevRequestRanges[_6]=[];
-}
-this._prevRequestRanges[_6].push({start:_2.start,end:_2.start+(_1b.photoset?_1b.photoset.photo.length:_1b.photos.photo.length)});
-dojo.forEach(_1c,function(i){
-_13(_1d,_1b,i);
-});
-}
-});
-var _1e=this._prevRequests[_f];
-if(_1e){
-this._handlers[_f]=null;
-_13(this._cache[_6],_1e,_10);
-return;
-}else{
-if(this._checkPrevRanges(_6,_2.start,_2.count)){
-this._handlers[_f]=null;
-_13(this._cache[_6],null,_10);
-return;
-}
-}
-var _1f=dojo.io.script.get(_12);
-_1f.addCallback(_1a);
-_1f.addErrback(function(_20){
-dojo.disconnect(_11);
-_4(_20,_2);
-});
-},getAttributes:function(_21){
-return ["title","author","imageUrl","imageUrlSmall","imageUrlMedium","imageUrlThumb","link","dateTaken","datePublished"];
-},getValues:function(_22,_23){
-this._assertIsItem(_22);
-this._assertIsAttribute(_23);
-switch(_23){
-case "title":
-return [this._unescapeHtml(_22.title)];
-case "author":
-return [_22.ownername];
-case "imageUrlSmall":
-return [_22.media.s];
-case "imageUrl":
-return [_22.media.l];
-case "imageUrlOriginal":
-return [_22.media.o];
-case "imageUrlLarge":
-return [_22.media.l];
-case "imageUrlMedium":
-return [_22.media.m];
-case "imageUrlThumb":
-return [_22.media.t];
-case "link":
-return ["http://www.flickr.com/photos/"+_22.owner+"/"+_22.id];
-case "dateTaken":
-return [_22.datetaken];
-case "datePublished":
-return [_22.datepublished];
-default:
-return undefined;
-}
-},_processFlickrData:function(_24,_25,_26){
-if(_24.items){
-return dojox.data.FlickrStore.prototype._processFlickrData.apply(this,arguments);
-}
-var _27=["http://farm",null,".static.flickr.com/",null,"/",null,"_",null];
-var _28=[];
-var _29=(_24.photoset?_24.photoset:_24.photos);
-if(_24.stat=="ok"&&_29&&_29.photo){
-_28=_29.photo;
-for(var i=0;i<_28.length;i++){
-var _2a=_28[i];
-_2a[this._storeRef]=this;
-_27[1]=_2a.farm;
-_27[3]=_2a.server;
-_27[5]=_2a.id;
-_27[7]=_2a.secret;
-var _2b=_27.join("");
-_2a.media={s:_2b+"_s.jpg",m:_2b+"_m.jpg",l:_2b+".jpg",t:_2b+"_t.jpg",o:_2b+"_o.jpg"};
-if(!_2a.owner&&_24.photoset){
-_2a.owner=_24.photoset.owner;
-}
-}
-}
-var _2c=_25.start?_25.start:0;
-var arr=this._cache[_26];
-if(!arr){
-this._cache[_26]=arr=[];
-}
-dojo.forEach(_28,function(i,idx){
-arr[idx+_2c]=i;
-});
-return arr;
-},_checkPrevRanges:function(_2d,_2e,_2f){
-var end=_2e+_2f;
-var arr=this._prevRequestRanges[_2d];
-return (!!arr)&&dojo.some(arr,function(_30){
-return ((_2e>=_30.start)&&(end<=_30.end));
+
+dojo.declare("dojox.data.FlickrRestStore",
+	dojox.data.FlickrStore, {
+	constructor: function(/*Object*/args){
+		// summary:
+		//	Initializer for the FlickrRestStore store.
+		// description:
+		//	The FlickrRestStore is a Datastore interface to one of the basic services
+		//	of the Flickr service, the public photo feed.  This does not provide
+		//	access to all the services of Flickr.
+		//	This store cannot do * and ? filtering as the flickr service
+		//	provides no interface for wildcards.
+		if(args){
+			if(args.label){
+				this.label = args.label;
+			}
+			if(args.apikey){
+				this._apikey = args.apikey;
+			}
+		}
+		this._cache = [];
+		this._prevRequests = {};
+		this._handlers = {};
+		this._prevRequestRanges = [];
+		this._maxPhotosPerUser = {};
+		this._id = dojox.data.FlickrRestStore.prototype._id++;
+	},
+
+	// _id: Integer
+	//		A unique identifier for this store.
+	_id: 0,
+
+	// _requestCount: Integer
+	//		A counter for the number of requests made. This is used to define
+	//		the callback function that Flickr will use.
+	_requestCount: 0,
+
+	// _flickrRestUrl: String
+	//		The URL to the Flickr REST services.
+	_flickrRestUrl: "http://www.flickr.com/services/rest/",
+
+	// _apikey: String
+	//		The users API key to be used when accessing Flickr REST services.
+	_apikey: null,
+
+	// _storeRef: String
+	//		A key used to mark an data store item as belonging to this store.
+	_storeRef: "_S",
+
+	// _cache: Array
+	//		An Array of all previously downloaded picture info.
+	_cache: null,
+
+	// _prevRequests: Object
+	//		A HashMap used to record the signature of a request to prevent duplicate
+	//		request being made.
+	_prevRequests: null,
+
+	// _handlers: Object
+	//		A HashMap used to record the handlers registered for a single remote request.  Multiple
+	//		requests may be made for the same information before the first request has finished.
+	//		Each element of this Object is an array of handlers to call back when the request finishes.
+	//		This prevents multiple requests being made for the same information.
+	_handlers: null,
+
+	// _sortAttributes: Object
+	//		A quick lookup of valid attribute names in a sort query.
+	_sortAttributes: {
+		"date-posted": true,
+		"date-taken": true,
+		"interestingness": true
+	},
+
+	_fetchItems: function(	/*Object*/ request,
+							/*Function*/ fetchHandler,
+							/*Function*/ errorHandler){
+		//	summary: Fetch flickr items that match to a query
+		//	request:
+		//		A request object
+		//	fetchHandler:
+		//		A function to call for fetched items
+		//	errorHandler:
+		//		A function to call on error
+		var query = {};
+		if(!request.query){
+			request.query = query = {};
+		} else {
+			dojo.mixin(query, request.query);
+		}
+
+		var primaryKey = [];
+		var secondaryKey = [];
+
+		//Build up the content to send the request for.
+		var content = {
+			format: "json",
+			method: "flickr.photos.search",
+			api_key: this._apikey,
+			extras: "owner_name,date_upload,date_taken"
+		};
+		var isRest = false;
+		if(query.userid){
+			isRest = true;
+			content.user_id = request.query.userid;
+			primaryKey.push("userid"+request.query.userid);
+		}
+
+		if(query.groupid){
+			isRest = true;
+			content.group_id = query.groupid;
+			primaryKey.push("groupid" + query.groupid);
+		}
+
+		if(query.apikey){
+			isRest = true;
+			content.api_key = request.query.apikey;
+			secondaryKey.push("api"+request.query.apikey);
+		}else if(content.api_key){
+			isRest = true;
+			request.query.apikey = content.api_key;
+			secondaryKey.push("api"+content.api_key);
+		}else{
+			throw Error("dojox.data.FlickrRestStore: An API key must be specified.");
+		}
+
+		request._curCount = request.count;
+
+		if(query.page){
+			content.page = request.query.page;
+			secondaryKey.push("page" + content.page);
+		}else if(("start" in request) && request.start !== null){
+			if(!request.count){
+				request.count = 20;
+			}
+			var diff = request.start % request.count;
+			var start = request.start, count = request.count;
+			// If the count does not divide cleanly into the start number,
+			// more work has to be done to figure out the best page to request
+			if(diff !== 0) {
+				if(start < count / 2){
+					// If the first record requested is less than half the
+					// amount requested, then request from 0 to the count record
+					count = start + count;
+					start = 0;
+				}else{
+					var divLimit = 20, div = 2;
+					for(var i = divLimit; i > 0; i--){
+						if(start % i === 0 && (start/i) >= count){
+							div = i;
+							break;
+						}
+					}
+					count = start/div;
+				}
+				request._realStart = request.start;
+				request._realCount = request.count;
+				request._curStart = start;
+				request._curCount = count;
+			}else{
+				request._realStart = request._realCount = null;
+				request._curStart = request.start;
+				request._curCount = request.count;
+			}
+
+			content.page = (start / count) + 1;
+			secondaryKey.push("page" + content.page);
+		}
+
+		if(request._curCount){
+			content.per_page = request._curCount;
+			secondaryKey.push("count" + request._curCount);
+		}
+
+		if(query.lang){
+			content.lang = request.query.lang;
+			primaryKey.push("lang" + request.lang);
+		}
+
+		if(query.setid){
+			content.method = "flickr.photosets.getPhotos";
+			content.photoset_id = request.query.setid;
+			primaryKey.push("set" + request.query.setid);
+		}
+
+		if(query.tags){
+			if(query.tags instanceof Array){
+				content.tags = query.tags.join(",");
+			}else{
+				content.tags = query.tags;
+			}
+			primaryKey.push("tags" + content.tags);
+
+			if(query["tag_mode"] && (query.tag_mode.toLowerCase() === "any" ||
+				query.tag_mode.toLowerCase() === "all")){
+				content.tag_mode = query.tag_mode;
+			}
+		}
+		if(query.text){
+			content.text=query.text;
+			primaryKey.push("text:"+query.text);
+		}
+
+		//The store only supports a single sort attribute, even though the
+		//Read API technically allows multiple sort attributes
+		if(query.sort && query.sort.length > 0){
+			//The default sort attribute is 'date-posted'
+			if(!query.sort[0].attribute){
+				query.sort[0].attribute = "date-posted";
+			}
+
+			//If the sort attribute is valid, check if it is ascending or
+			//descending.
+			if(this._sortAttributes[query.sort[0].attribute]) {
+				if(query.sort[0].descending){
+					content.sort = query.sort[0].attribute + "-desc";
+				}else{
+					content.sort = query.sort[0].attribute + "-asc";
+				}
+			}
+		}else{
+			//The default sort in the Dojo Data API is ascending.
+			content.sort = "date-posted-asc";
+		}
+		primaryKey.push("sort:"+content.sort);
+
+		//Generate a unique key for this request, so the store can
+		//detect duplicate requests.
+		primaryKey = primaryKey.join(".");
+		secondaryKey = secondaryKey.length > 0 ? "." + secondaryKey.join(".") : "";
+		var requestKey = primaryKey + secondaryKey;
+
+		//Make a copy of the request, in case the source object is modified
+		//before the request completes
+		request = {
+			query: query,
+			count: request._curCount,
+			start: request._curStart,
+			_realCount: request._realCount,
+			_realStart: request._realStart,
+			onBegin: request.onBegin,
+			onComplete: request.onComplete,
+			onItem: request.onItem
+		};
+
+		var thisHandler = {
+			request: request,
+			fetchHandler: fetchHandler,
+			errorHandler: errorHandler
+		};
+
+		//If the request has already been made, but not yet completed,
+		//then add the callback handler to the list of handlers
+		//for this request, and finish.
+		if(this._handlers[requestKey]){
+			this._handlers[requestKey].push(thisHandler);
+			return;
+		}
+
+		this._handlers[requestKey] = [thisHandler];
+
+		//Linking this up to Flickr is a PAIN!
+		var handle = null;
+		var getArgs = {
+			url: this._flickrRestUrl,
+			preventCache: this.urlPreventCache,
+			content: content,
+			callbackParamName: "jsoncallback"
+		};
+
+		var doHandle = dojo.hitch(this, function(processedData, data, handler){
+			var onBegin = handler.request.onBegin;
+			handler.request.onBegin = null;
+			var maxPhotos;
+			var req = handler.request;
+
+			if(("_realStart" in req) && req._realStart != null){
+				req.start = req._realStart;
+				req.count = req._realCount;
+				req._realStart = req._realCount = null;
+			}
+
+			//If the request contains an onBegin method, the total number
+			//of photos must be calculated.
+			if(onBegin){
+				var photos = null;
+				if(data){
+					photos = (data.photoset ? data.photoset : data.photos);
+				}
+				if(photos && ("perpage" in photos) && ("pages" in photos)){
+					if(photos.perpage * photos.pages <= handler.request.start + handler.request.count){
+						//If the final page of results has been received, it is possible to
+						//know exactly how many photos there are
+						maxPhotos = handler.request.start + photos.photo.length;
+					}else{
+						//If the final page of results has not yet been received,
+						//it is not possible to tell exactly how many photos exist, so
+						//return the number of pages multiplied by the number of photos per page.
+						maxPhotos = photos.perpage * photos.pages;
+					}
+					this._maxPhotosPerUser[primaryKey] = maxPhotos;
+					onBegin(maxPhotos, handler.request);
+				}else if(this._maxPhotosPerUser[primaryKey]){
+					onBegin(this._maxPhotosPerUser[primaryKey], handler.request);
+				}
+			}
+			//Call whatever functions the caller has defined on the request object, except for onBegin
+			handler.fetchHandler(processedData, handler.request);
+			if(onBegin){
+				//Replace the onBegin function, if it existed.
+				handler.request.onBegin = onBegin;
+			}
+		});
+
+		//Define a callback for the script that iterates through a list of
+		//handlers for this piece of data.  Multiple requests can come into
+		//the store for the same data.
+		var myHandler = dojo.hitch(this, function(data){
+			//The handler should not be called more than once, so disconnect it.
+			//if(handle !== null){ dojo.disconnect(handle); }
+			if(data.stat != "ok"){
+				errorHandler(null, request);
+			}else{ //Process the items...
+				var handlers = this._handlers[requestKey];
+				if(!handlers){
+					console.log("FlickrRestStore: no handlers for data", data);
+					return;
+				}
+
+				this._handlers[requestKey] = null;
+				this._prevRequests[requestKey] = data;
+
+				//Process the data once.
+				var processedData = this._processFlickrData(data, request, primaryKey);
+				if(!this._prevRequestRanges[primaryKey]){
+					this._prevRequestRanges[primaryKey] = [];
+				}
+				this._prevRequestRanges[primaryKey].push({
+					start: request.start,
+					end: request.start + (data.photoset ? data.photoset.photo.length : data.photos.photo.length)
+				});
+
+				//Iterate through the array of handlers, calling each one.
+				dojo.forEach(handlers, function(i){
+					doHandle(processedData, data, i);
+				});
+			}
+		});
+
+		var data = this._prevRequests[requestKey];
+
+		//If the data was previously retrieved, there is no need to fetch it again.
+		if(data){
+			this._handlers[requestKey] = null;
+			doHandle(this._cache[primaryKey], data, thisHandler);
+			return;
+		}else if(this._checkPrevRanges(primaryKey, request.start, request.count)){
+			//If this range of data has already been retrieved, reuse it.
+			this._handlers[requestKey] = null;
+			doHandle(this._cache[primaryKey], null, thisHandler);
+			return;
+		}
+
+		var deferred = dojo.io.script.get(getArgs);
+		deferred.addCallback(myHandler);
+
+		//We only set up the errback, because the callback isn't ever really used because we have
+		//to link to the jsonFlickrFeed function....
+		deferred.addErrback(function(error){
+			dojo.disconnect(handle);
+			errorHandler(error, request);
+		});
+	},
+
+	getAttributes: function(item){
+		//	summary:
+		//      See dojo.data.api.Read.getAttributes()
+		return [
+			"title", "author", "imageUrl", "imageUrlSmall", "imageUrlMedium",
+			"imageUrlThumb", "imageUrlLarge", "imageUrlOriginal", "link", "dateTaken", "datePublished"
+		];
+	},
+
+	getValues: function(item, attribute){
+		//	summary:
+		//      See dojo.data.api.Read.getValue()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+
+		switch(attribute){
+			case "title":
+				return [ this._unescapeHtml(item.title) ]; // String
+			case "author":
+				return [ item.ownername ]; // String
+			case "imageUrlSmall":
+				return [ item.media.s ]; // String
+			case "imageUrl":
+				return [ item.media.l ]; // String
+			case "imageUrlOriginal":
+				return [ item.media.o ]; // String
+			case "imageUrlLarge":
+				return [ item.media.l ]; // String
+			case "imageUrlMedium":
+				return [ item.media.m ]; // String
+			case "imageUrlThumb":
+				return [ item.media.t ]; // String
+			case "link":
+				return [ "http://www.flickr.com/photos/" + item.owner + "/" + item.id ]; // String
+			case "dateTaken":
+				return [ item.datetaken ];
+			case "datePublished":
+				return [ item.datepublished ];
+			default:
+				return undefined;
+		}
+
+	},
+
+	_processFlickrData: function(/* Object */data, /* Object */request, /* String */ cacheKey){
+		// summary: Processes the raw data from Flickr and updates the internal cache.
+		// data:
+		//		Data returned from Flickr
+		// request:
+		//		The original dojo.data.Request object passed in by the user.
+
+		// If the data contains an 'item' object, it has not come from the REST
+		// services, so process it using the FlickrStore.
+		if(data.items){
+			return dojox.data.FlickrStore.prototype._processFlickrData.apply(this,arguments);
+		}
+        var template = ["http://farm", null, ".static.flickr.com/", null, "/", null, "_", null];
+
+		var items = [];
+		var photos = (data.photoset ? data.photoset : data.photos);
+		if(data.stat == "ok" && photos && photos.photo){
+			items = photos.photo;
+
+			//Add on the store ref so that isItem can work.
+			for(var i = 0; i < items.length; i++){
+				var item = items[i];
+				item[this._storeRef] = this;
+                template[1] = item.farm;
+                template[3] = item.server;
+                template[5] = item.id;
+                template[7] = item.secret;
+                
+                var base = template.join("");
+				item.media = {
+                    s: base + "_s.jpg",
+                    m: base + "_m.jpg",
+                    l: base + ".jpg",
+                    t: base + "_t.jpg",
+                    o: base + "_o.jpg"
+				};
+				if(!item.owner && data.photoset){
+					item.owner = data.photoset.owner;
+				}
+			}
+		}
+		var start = request.start ? request.start : 0;
+		var arr = this._cache[cacheKey];
+		if(!arr){
+			this._cache[cacheKey] = arr = [];
+		}
+		dojo.forEach(items, function(i, idx){
+			arr[idx+ start] = i;
+		});
+
+		return arr; // Array
+	},
+
+	_checkPrevRanges: function(primaryKey, start, count){
+		var end = start + count;
+		var arr = this._prevRequestRanges[primaryKey];
+		return (!!arr) && dojo.some(arr, function(item){
+			return ((start >= item.start)&&(end <= item.end));
+		});
+	}
 });
-}});
-}
+
diff --git a/dojox/data/FlickrStore.js b/dojox/data/FlickrStore.js
index a7a49f0..2fabc22 100644
--- a/dojox/data/FlickrStore.js
+++ b/dojox/data/FlickrStore.js
@@ -1,151 +1,289 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.FlickrStore"]){
-dojo._hasResource["dojox.data.FlickrStore"]=true;
 dojo.provide("dojox.data.FlickrStore");
+
 dojo.require("dojo.data.util.simpleFetch");
 dojo.require("dojo.io.script");
 dojo.require("dojo.date.stamp");
 dojo.require("dojo.AdapterRegistry");
+
 (function(){
-var d=dojo;
-dojo.declare("dojox.data.FlickrStore",null,{constructor:function(_1){
-if(_1&&_1.label){
-this.label=_1.label;
-}
-if(_1&&"urlPreventCache" in _1){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-},_storeRef:"_S",label:"title",urlPreventCache:true,_assertIsItem:function(_2){
-if(!this.isItem(_2)){
-throw new Error("dojox.data.FlickrStore: a function was passed an item argument that was not an item");
-}
-},_assertIsAttribute:function(_3){
-if(typeof _3!=="string"){
-throw new Error("dojox.data.FlickrStore: a function was passed an attribute argument that was not an attribute name string");
-}
-},getFeatures:function(){
-return {"dojo.data.api.Read":true};
-},getValue:function(_4,_5,_6){
-var _7=this.getValues(_4,_5);
-if(_7&&_7.length>0){
-return _7[0];
-}
-return _6;
-},getAttributes:function(_8){
-return ["title","description","author","datePublished","dateTaken","imageUrl","imageUrlSmall","imageUrlMedium","tags","link"];
-},hasAttribute:function(_9,_a){
-var v=this.getValue(_9,_a);
-if(v||v===""||v===false){
-return true;
-}
-return false;
-},isItemLoaded:function(_b){
-return this.isItem(_b);
-},loadItem:function(_c){
-},getLabel:function(_d){
-return this.getValue(_d,this.label);
-},getLabelAttributes:function(_e){
-return [this.label];
-},containsValue:function(_f,_10,_11){
-var _12=this.getValues(_f,_10);
-for(var i=0;i<_12.length;i++){
-if(_12[i]===_11){
-return true;
-}
-}
-return false;
-},getValues:function(_13,_14){
-this._assertIsItem(_13);
-this._assertIsAttribute(_14);
-var u=d.hitch(this,"_unescapeHtml");
-var s=d.hitch(d.date.stamp,"fromISOString");
-switch(_14){
-case "title":
-return [u(_13.title)];
-case "author":
-return [u(_13.author)];
-case "datePublished":
-return [s(_13.published)];
-case "dateTaken":
-return [s(_13.date_taken)];
-case "imageUrlSmall":
-return [_13.media.m.replace(/_m\./,"_s.")];
-case "imageUrl":
-return [_13.media.m.replace(/_m\./,".")];
-case "imageUrlMedium":
-return [_13.media.m];
-case "link":
-return [_13.link];
-case "tags":
-return _13.tags.split(" ");
-case "description":
-return [u(_13.description)];
-default:
-return [];
-}
-},isItem:function(_15){
-if(_15&&_15[this._storeRef]===this){
-return true;
-}
-return false;
-},close:function(_16){
-},_fetchItems:function(_17,_18,_19){
-var rq=_17.query=_17.query||{};
-var _1a={format:"json",tagmode:"any"};
-d.forEach(["tags","tagmode","lang","id","ids"],function(i){
-if(rq[i]){
-_1a[i]=rq[i];
-}
-});
-_1a.id=rq.id||rq.userid||rq.groupid;
-if(rq.userids){
-_1a.ids=rq.userids;
-}
-var _1b=null;
-var _1c={url:dojox.data.FlickrStore.urlRegistry.match(_17),preventCache:this.urlPreventCache,content:_1a};
-var _1d=d.hitch(this,function(_1e){
-if(!!_1b){
-d.disconnect(_1b);
-}
-_18(this._processFlickrData(_1e),_17);
-});
-_1b=d.connect("jsonFlickrFeed",_1d);
-var _1f=d.io.script.get(_1c);
-_1f.addErrback(function(_20){
-d.disconnect(_1b);
-_19(_20,_17);
-});
-},_processFlickrData:function(_21){
-var _22=[];
-if(_21.items){
-_22=_21.items;
-for(var i=0;i<_21.items.length;i++){
-var _23=_21.items[i];
-_23[this._storeRef]=this;
-}
-}
-return _22;
-},_unescapeHtml:function(str){
-return str.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,"\"").replace(/'/gm,"'");
-}});
-dojo.extend(dojox.data.FlickrStore,dojo.data.util.simpleFetch);
-var _24="http://api.flickr.com/services/feeds/";
-var reg=dojox.data.FlickrStore.urlRegistry=new d.AdapterRegistry(true);
-reg.register("group pool",function(_25){
-return !!_25.query["groupid"];
-},_24+"groups_pool.gne");
-reg.register("default",function(_26){
-return true;
-},_24+"photos_public.gne");
+	var d = dojo;
+
+	dojo.declare("dojox.data.FlickrStore", null, {
+		constructor: function(/*Object*/args){
+			//	summary:
+			//		Initializer for the FlickrStore store.  
+			//	description:
+			//		The FlickrStore is a Datastore interface to one of the basic services
+			//		of the Flickr service, the public photo feed.  This does not provide
+			//		access to all the services of Flickr.
+			//		This store cannot do * and ? filtering as the flickr service 
+			//		provides no interface for wildcards.
+			if(args && args.label){
+				this.label = args.label;
+			}
+			if(args && "urlPreventCache" in args){
+				this.urlPreventCache = args.urlPreventCache?true:false;
+			}
+		},
+
+		_storeRef: "_S",
+
+		label: "title",
+
+		//Flag to allor control of if cache prevention is enabled or not.
+		urlPreventCache: true,
+
+		_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("dojox.data.FlickrStore: a function was passed an item argument that was not an item");
+			}
+		},
+
+		_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("dojox.data.FlickrStore: a function was passed an attribute argument that was not an attribute name string");
+			}
+		},
+
+		getFeatures: function(){
+			//	summary: 
+			//      See dojo.data.api.Read.getFeatures()
+			return {
+				'dojo.data.api.Read': true
+			};
+		},
+
+		getValue: function(item, attribute, defaultValue){
+			//	summary: 
+			//      See dojo.data.api.Read.getValue()
+			var values = this.getValues(item, attribute);
+			if(values && values.length > 0){
+				return values[0];
+			}
+			return defaultValue;
+		},
+
+		getAttributes: function(item){
+			//	summary: 
+			//      See dojo.data.api.Read.getAttributes()
+			return [
+				"title", "description", "author", "datePublished", "dateTaken", 
+				"imageUrl", "imageUrlSmall", "imageUrlMedium", "tags", "link"
+			]; 
+		},
+
+		hasAttribute: function(item, attribute){
+			//	summary: 
+			//      See dojo.data.api.Read.hasAttributes()
+			var v = this.getValue(item,attribute); 
+			if(v || v === "" || v === false){
+				return true;
+			}
+			return false;
+		},
+
+		isItemLoaded: function(item){
+			 //	summary: 
+			 //      See dojo.data.api.Read.isItemLoaded()
+			 return this.isItem(item);
+		},
+
+		loadItem: function(keywordArgs){
+			//	summary: 
+			//      See dojo.data.api.Read.loadItem()
+		},
+
+		getLabel: function(item){
+			//	summary: 
+			//      See dojo.data.api.Read.getLabel()
+			return this.getValue(item,this.label);
+		},
+		
+		getLabelAttributes: function(item){
+			//	summary: 
+			//      See dojo.data.api.Read.getLabelAttributes()
+			return [this.label];
+		},
+
+		containsValue: function(item, attribute, value){
+			//	summary: 
+			//      See dojo.data.api.Read.containsValue()
+			var values = this.getValues(item,attribute);
+			for(var i = 0; i < values.length; i++){
+				if(values[i] === value){
+					return true;
+				}
+			}
+			return false;
+		},
+
+		getValues: function(item, attribute){
+			//	summary: 
+			//      See dojo.data.api.Read.getValue()
+
+			this._assertIsItem(item);
+			this._assertIsAttribute(attribute);
+			var u = d.hitch(this, "_unescapeHtml");
+			var s = d.hitch(d.date.stamp, "fromISOString");
+			switch(attribute){
+				case "title":
+					return [ u(item.title) ];
+				case "author":
+					return [ u(item.author) ];
+				case "datePublished":
+					return [ s(item.published) ];
+				case "dateTaken":
+					return [ s(item.date_taken) ];
+				case "imageUrlSmall":
+					return [ item.media.m.replace(/_m\./, "_s.") ];
+				case "imageUrl":
+					return [ item.media.m.replace(/_m\./, ".") ];
+				case "imageUrlMedium":
+					return [ item.media.m ];
+				case "link":
+					return [ item.link ];
+				case "tags":
+					return item.tags.split(" ");
+				case "description":
+					return [ u(item.description) ];
+				default:
+					return [];
+			}
+		},
+
+		isItem: function(item){
+			//	summary: 
+			//      See dojo.data.api.Read.isItem()
+			if(item && item[this._storeRef] === this){
+				return true;
+			}
+			return false;
+		},
+		
+		close: function(request){
+			//	summary: 
+			//      See dojo.data.api.Read.close()
+		},
+
+		_fetchItems: function(request, fetchHandler, errorHandler){
+			//	summary:
+			//		Fetch flickr items that match to a query
+			//	request:
+			//		A request object
+			//	fetchHandler:
+			//		A function to call for fetched items
+			//	errorHandler:
+			//		A function to call on error
+
+			var rq = request.query = request.query || {};
+
+			//Build up the content to send the request for.
+			var content = {
+				format: "json",
+				tagmode:"any"
+			};
+
+			d.forEach(
+				[ "tags", "tagmode", "lang", "id", "ids" ],
+				function(i){
+					if(rq[i]){ content[i] = rq[i]; }
+				}
+			);
+
+			content.id = rq.id || rq.userid || rq.groupid;
+
+			if(rq.userids){
+				content.ids = rq.userids;
+			}
+
+			//Linking this up to Flickr is a PAIN!
+			var handle = null;
+			var getArgs = {
+				url: dojox.data.FlickrStore.urlRegistry.match(request),
+				preventCache: this.urlPreventCache,
+				content: content
+			};
+			var myHandler = d.hitch(this, function(data){
+				if(!!handle){
+					d.disconnect(handle);
+				}
+
+				//Process the items...
+				fetchHandler(this._processFlickrData(data), request);
+			});
+			handle = d.connect("jsonFlickrFeed", myHandler);
+			var deferred = d.io.script.get(getArgs);
+			
+			//We only set up the errback, because the callback isn't ever really used because we have
+			//to link to the jsonFlickrFeed function....
+			deferred.addErrback(function(error){
+				d.disconnect(handle);
+				errorHandler(error, request);
+			});
+		},
+
+		_processFlickrData: function(data){
+			 var items = [];
+			 if(data.items){
+				 items = data.items;
+				 //Add on the store ref so that isItem can work.
+				 for(var i = 0; i < data.items.length; i++){
+					 var item = data.items[i];
+					 item[this._storeRef] = this;
+				 }
+			 }
+			 return items;
+		},
+
+		_unescapeHtml: function(/*String*/ str){
+			// summary: 
+			//		Utility function to un-escape XML special characters in an
+			//		HTML string.
+			//	str: String.
+			//		The string to un-escape
+			// returns: 
+			//		HTML String converted back to the normal text (unescaped)
+			//		characters (<,>,&, ", etc,).
+
+			//TODO: 
+			//		Check to see if theres already compatible escape() in
+			//		dojo.string or dojo.html
+			return 	str.replace(/&/gm, "&").
+						replace(/</gm, "<").
+						replace(/>/gm, ">").
+						replace(/"/gm, "\"").
+						replace(/'/gm, "'"); 
+		}
+	});
+
+	dojo.extend(dojox.data.FlickrStore, dojo.data.util.simpleFetch);
+
+	var feedsUrl = "http://api.flickr.com/services/feeds/";
+
+	var reg = dojox.data.FlickrStore.urlRegistry = new d.AdapterRegistry(true);
+
+	reg.register("group pool",
+		function(request){ return !!request.query["groupid"]; },
+		feedsUrl+"groups_pool.gne"
+	);
+
+	reg.register("default", 
+		function(request){ return true; },
+		feedsUrl+"photos_public.gne"
+	);
 })();
+
+
+//We have to define this because of how the Flickr API works.  
+//This somewhat stinks, but what can you do?
 if(!jsonFlickrFeed){
-var jsonFlickrFeed=function(_27){
-};
-}
+	var jsonFlickrFeed = function(data){};
 }
diff --git a/dojox/data/GoogleFeedStore.js b/dojox/data/GoogleFeedStore.js
index 4cd587e..bb55773 100644
--- a/dojox/data/GoogleFeedStore.js
+++ b/dojox/data/GoogleFeedStore.js
@@ -1,39 +1,75 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.GoogleFeedStore"]){
-dojo._hasResource["dojox.data.GoogleFeedStore"]=true;
 dojo.provide("dojox.data.GoogleFeedStore");
 dojo.experimental("dojox.data.GoogleFeedStore");
+
 dojo.require("dojox.data.GoogleSearchStore");
-dojo.declare("dojox.data.GoogleFeedStore",dojox.data.GoogleSearchStore,{_type:"",_googleUrl:"http://ajax.googleapis.com/ajax/services/feed/load",_attributes:["title","link","author","published","content","summary","categories"],_queryAttrs:{"url":"q"},getFeedValue:function(_1,_2){
-var _3=this.getFeedValues(_1,_2);
-if(dojo.isArray(_3)){
-return _3[0];
-}
-return _3;
-},getFeedValues:function(_4,_5){
-if(!this._feedMetaData){
-return _5;
-}
-return this._feedMetaData[_4]||_5;
-},_processItem:function(_6,_7){
-this.inherited(arguments);
-_6["summary"]=_6["contentSnippet"];
-_6["published"]=_6["publishedDate"];
-},_getItems:function(_8){
-if(_8["feed"]){
-this._feedMetaData={title:_8.feed.title,desc:_8.feed.description,url:_8.feed.link,author:_8.feed.author};
-return _8.feed.entries;
-}
-return null;
-},_createContent:function(_9,_a,_b){
-var cb=this.inherited(arguments);
-cb.num=(_b.count||10)+(_b.start||0);
-return cb;
-}});
-}
+
+dojo.declare("dojox.data.GoogleFeedStore", dojox.data.GoogleSearchStore,{
+	// summary:
+	//	A data store for retrieving RSS and Atom feeds from Google. The 
+	//  feeds can come from any source, which is specified in the "url"
+	//  parameter of the query passed to the "fetch" function.
+	//	The following attributes are supported on each item:
+	//		<ul>
+	//			<li>title - The feed entry title.</li>
+	//			<li>link - The URL for the HTML version of the feed entry.</li>
+	//			<li>content - The full content of the blog post, in HTML format</li>
+	//			<li>summary - A snippet of information about the feed entry, in plain text</li>
+	//			<li>published - The string date on which the entry was published.
+	//				You can parse the date with new Date(store.getValue(item, "published")</li>
+	//			<li>categories - An array of string tags for the entry</li>
+	//		</ul>
+	//	The query accepts one parameter: url - The URL of the feed to retrieve
+	_type: "",
+	_googleUrl: "http://ajax.googleapis.com/ajax/services/feed/load",
+	_attributes: ["title", "link", "author", "published",
+			"content", "summary", "categories"],
+	_queryAttrs: {
+		"url":"q"
+	},
+	
+	getFeedValue: function(attribute, defaultValue){
+		// summary:
+		//		Non-API method for retrieving values regarding the Atom feed,
+		//		rather than the Atom entries.
+		var values = this.getFeedValues(attribute, defaultValue);
+		if(dojo.isArray(values)){
+			return values[0];
+		}
+		return values;
+	},
+
+	getFeedValues: function(attribute, defaultValue){
+		// summary:
+		//		Non-API method for retrieving values regarding the Atom feed,
+		//		rather than the Atom entries.
+		if(!this._feedMetaData){
+			return defaultValue;
+		}
+		return this._feedMetaData[attribute] || defaultValue;
+	},
+
+	_processItem: function(item, request) {
+		this.inherited(arguments);
+		item["summary"] = item["contentSnippet"];
+		item["published"] = item["publishedDate"];
+	},
+
+	_getItems: function(data){
+		if(data['feed']){
+			this._feedMetaData = {
+				title: data.feed.title,
+				desc: data.feed.description,
+				url: data.feed.link,
+				author: data.feed.author
+			};
+			return data.feed.entries;
+		}
+		return null;
+	},
+
+	_createContent: function(query, callback, request){
+		var cb = this.inherited(arguments);
+		cb.num = (request.count || 10) + (request.start || 0);
+		return cb;
+	}
+});
diff --git a/dojox/data/GoogleSearchStore.js b/dojox/data/GoogleSearchStore.js
index edc433e..1912070 100644
--- a/dojox/data/GoogleSearchStore.js
+++ b/dojox/data/GoogleSearchStore.js
@@ -1,12 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.GoogleSearchStore"]){
-dojo._hasResource["dojox.data.GoogleSearchStore"]=true;
 dojo.provide("dojox.data.GoogleSearchStore");
 dojo.provide("dojox.data.GoogleWebSearchStore");
 dojo.provide("dojox.data.GoogleBlogSearchStore");
@@ -15,242 +6,646 @@ dojo.provide("dojox.data.GoogleVideoSearchStore");
 dojo.provide("dojox.data.GoogleNewsSearchStore");
 dojo.provide("dojox.data.GoogleBookSearchStore");
 dojo.provide("dojox.data.GoogleImageSearchStore");
+
 dojo.require("dojo.io.script");
+
 dojo.experimental("dojox.data.GoogleSearchStore");
-dojo.declare("dojox.data.GoogleSearchStore",null,{constructor:function(_1){
-if(_1){
-if(_1.label){
-this.label=_1.label;
-}
-if(_1.key){
-this._key=_1.key;
-}
-if(_1.lang){
-this._lang=_1.lang;
-}
-if("urlPreventCache" in _1){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-}
-this._id=dojox.data.GoogleSearchStore.prototype._id++;
-},_id:0,_requestCount:0,_googleUrl:"http://ajax.googleapis.com/ajax/services/search/",_storeRef:"_S",_attributes:["unescapedUrl","url","visibleUrl","cacheUrl","title","titleNoFormatting","content","estimatedResultCount"],_aggregatedAttributes:{estimatedResultCount:"cursor.estimatedResultCount"},label:"titleNoFormatting",_type:"web",urlPreventCache:true,_queryAttrs:{text:"q"},_assertIsItem:function(_2){
-if(!this.isItem(_2)){
-throw new Error("dojox.data.GoogleSearchStore: a function was passed an item argument that was not an item");
-}
-},_assertIsAttribute:function(_3){
-if(typeof _3!=="string"){
-throw new Error("dojox.data.GoogleSearchStore: a function was passed an attribute argument that was not an attribute name string");
-}
-},getFeatures:function(){
-return {"dojo.data.api.Read":true};
-},getValue:function(_4,_5,_6){
-var _7=this.getValues(_4,_5);
-if(_7&&_7.length>0){
-return _7[0];
-}
-return _6;
-},getAttributes:function(_8){
-return this._attributes;
-},hasAttribute:function(_9,_a){
-if(this.getValue(_9,_a)){
-return true;
-}
-return false;
-},isItemLoaded:function(_b){
-return this.isItem(_b);
-},loadItem:function(_c){
-},getLabel:function(_d){
-return this.getValue(_d,this.label);
-},getLabelAttributes:function(_e){
-return [this.label];
-},containsValue:function(_f,_10,_11){
-var _12=this.getValues(_f,_10);
-for(var i=0;i<_12.length;i++){
-if(_12[i]===_11){
-return true;
-}
-}
-return false;
-},getValues:function(_13,_14){
-this._assertIsItem(_13);
-this._assertIsAttribute(_14);
-var val=_13[_14];
-if(dojo.isArray(val)){
-return val;
-}else{
-if(val!==undefined){
-return [val];
-}else{
-return [];
-}
-}
-},isItem:function(_15){
-if(_15&&_15[this._storeRef]===this){
-return true;
-}
-return false;
-},close:function(_16){
-},_format:function(_17,_18){
-return _17;
-},fetch:function(_19){
-_19=_19||{};
-var _1a=_19.scope||dojo.global;
-if(!_19.query){
-if(_19.onError){
-_19.onError.call(_1a,new Error(this.declaredClass+": A query must be specified."));
-return;
-}
-}
-var _1b={};
-for(var _1c in this._queryAttrs){
-_1b[_1c]=_19.query[_1c];
-}
-_19={query:_1b,onComplete:_19.onComplete,onError:_19.onError,onItem:_19.onItem,onBegin:_19.onBegin,start:_19.start,count:_19.count};
-var _1d=8;
-var _1e="GoogleSearchStoreCallback_"+this._id+"_"+(++this._requestCount);
-var _1f=this._createContent(_1b,_1e,_19);
-var _20;
-if(typeof (_19.start)==="undefined"||_19.start===null){
-_19.start=0;
-}
-if(!_19.count){
-_19.count=_1d;
-}
-_20={start:_19.start-_19.start%_1d};
-var _21=this;
-var _22=this._googleUrl+this._type;
-var _23={url:_22,preventCache:this.urlPreventCache,content:_1f};
-var _24=[];
-var _25=0;
-var _26=false;
-var _27=_19.start-1;
-var _28=0;
-var _29=[];
-function _2a(req){
-_28++;
-_23.content.context=_23.content.start=req.start;
-var _2b=dojo.io.script.get(_23);
-_29.push(_2b.ioArgs.id);
-_2b.addErrback(function(_2c){
-if(_19.onError){
-_19.onError.call(_1a,_2c,_19);
-}
+
+dojo.declare("dojox.data.GoogleSearchStore",null,{
+	//	summary:
+	//		A data store for retrieving search results from Google.
+	//		This data store acts as a base class for Google searches,
+	//		and has a number of child data stores that implement different
+	//		searches. This store defaults to searching the web, and is functionally
+	//		identical to the dojox.data.GoogleWebSearchStore object.
+	//		The following attributes are supported on each item:
+	//		<ul>
+	//			<li>url - The URL for the item</li>
+	//			<li>unescapedUrl - The URL for the item, with URL escaping. This is often more readable</li>
+	//			<li>visibleUrl - The URL with no protocol specified.
+	//			<li>cacheUrl - The URL to the copy of the document cached by Google
+	//			<li>title - The page title in HTML format.</li>
+	//			<li>titleNoFormatting - The page title in plain text</li>
+	//			<li>content - A snippet of information about the page</li>
+	//		</ul>
+	//		The query accepts one parameter: text - The string to search for
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		Initializer for the GoogleSearchStore store.
+		//	description:
+		//		The GoogleSearchStore is a Datastore interface to
+		//		the Google search service. The constructor accepts the following arguments:
+		//		<ul>
+		//			<li>label - the label attribute to use. Defaults to titleNoFormatting</li>
+		//			<li>key - The API key to use. This is optional</li>
+		//			<li>lang - The language locale to use. Defaults to the browser locale</li>
+		//		</ul>
+
+		if(args){
+			if(args.label){
+				this.label = args.label;
+			}
+			if(args.key){
+				this._key = args.key;
+			}
+			if(args.lang){
+				this._lang = args.lang;
+			}
+			if("urlPreventCache" in args){
+				this.urlPreventCache = args.urlPreventCache?true:false;
+			}
+		}
+		this._id = dojox.data.GoogleSearchStore.prototype._id++;
+	},
+
+	// _id: Integer
+	// A unique identifier for this store.
+	_id: 0,
+
+	// _requestCount: Integer
+	// A counter for the number of requests made. This is used to define
+	// the callback function that GoogleSearchStore will use.
+	_requestCount: 0,
+
+	// _googleUrl: String
+	// The URL to Googles search web service.
+	_googleUrl: "http://ajax.googleapis.com/ajax/services/search/",
+
+	// _storeRef: String
+	// The internal reference added to each item pointing at the store which owns it.
+	_storeRef: "_S",
+
+	// _attributes: Array
+	// The list of attributes that this store supports
+	_attributes: [	"unescapedUrl", "url", "visibleUrl", "cacheUrl", "title", 
+			"titleNoFormatting", "content", "estimatedResultCount"],
+
+	// _aggregtedAttributes: Hash
+	// Maps per-query aggregated attributes that this store supports to the result keys that they come from.
+	_aggregatedAttributes: {
+		estimatedResultCount: "cursor.estimatedResultCount"
+	},
+
+	// label: String
+	// The default attribute which acts as a label for each item.
+	label: "titleNoFormatting",
+
+	// type: String
+	// The type of search. Valid values are "web", "local", "video", "blogs", "news", "books", "images".
+	// This should not be set directly. Instead use one of the child classes.
+	_type: "web",
+
+	// urlPreventCache: boolean
+	// Sets whether or not to pass preventCache to dojo.io.script.
+	urlPreventCache: true,
+
+
+	// _queryAttrs: Hash
+	// Maps query hash keys to Google query parameters. 
+	_queryAttrs: {
+		text: 'q'
+	},
+
+	_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("dojox.data.GoogleSearchStore: a function was passed an item argument that was not an item");
+		}
+	},
+
+	_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("dojox.data.GoogleSearchStore: a function was passed an attribute argument that was not an attribute name string");
+		}
+	},
+
+	getFeatures: function(){
+		//	summary:
+		//		See dojo.data.api.Read.getFeatures()
+		return {
+			'dojo.data.api.Read': true
+		};
+	},
+
+	getValue: function(item, attribute, defaultValue){
+		//	summary:
+		//		See dojo.data.api.Read.getValue()
+		var values = this.getValues(item, attribute);
+		if(values && values.length > 0){
+			return values[0];
+		}
+		return defaultValue;
+	},
+
+	getAttributes: function(item){
+		//	summary:
+		//		See dojo.data.api.Read.getAttributes()
+		return this._attributes;
+	},
+
+	hasAttribute: function(item, attribute){
+		//	summary:
+		//		See dojo.data.api.Read.hasAttributes()
+		if(this.getValue(item,attribute)){
+			return true;
+		}
+		return false;
+	},
+
+	isItemLoaded: function(item){
+		 //	summary:
+		 //		See dojo.data.api.Read.isItemLoaded()
+		 return this.isItem(item);
+	},
+
+	loadItem: function(keywordArgs){
+		//	summary:
+		//		See dojo.data.api.Read.loadItem()
+	},
+
+	getLabel: function(item){
+		//	summary:
+		//		See dojo.data.api.Read.getLabel()
+		return this.getValue(item,this.label);
+	},
+
+	getLabelAttributes: function(item){
+		//	summary:
+		//		See dojo.data.api.Read.getLabelAttributes()
+		return [this.label];
+	},
+
+	containsValue: function(item, attribute, value){
+		//	summary:
+		//		See dojo.data.api.Read.containsValue()
+		var values = this.getValues(item,attribute);
+		for(var i = 0; i < values.length; i++){
+			if(values[i] === value){
+				return true;
+			}
+		}
+		return false;
+	},
+
+	getValues: function(item, attribute){
+		//	summary:
+		//		See dojo.data.api.Read.getValue()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		var val = item[attribute];
+		if(dojo.isArray(val)) {
+			return val;
+		}else if(val !== undefined){
+			return [val];
+		}else{
+			return [];
+		}
+	},
+
+	isItem: function(item){
+		//	summary:
+		//		See dojo.data.api.Read.isItem()
+		if(item && item[this._storeRef] === this){
+			return true;
+		}
+		return false;
+	},
+
+	close: function(request){
+		//	summary:
+		//		See dojo.data.api.Read.close()
+	},
+
+	_format: function(item, name){
+		return item;//base implementation does not format any items
+	},
+
+	fetch: function(request){
+		//	summary:
+		//		Fetch Google search items that match to a query
+		//	request:
+		//		A request object
+		//	fetchHandler:
+		//		A function to call for fetched items
+		//	errorHandler:
+		//		A function to call on error
+		request = request || {};
+
+		var scope = request.scope || dojo.global;
+
+		if(!request.query){
+			if(request.onError){
+				request.onError.call(scope, new Error(this.declaredClass + 
+					": A query must be specified."));
+				return;
+			}
+		}
+		//Make a copy of the request object, in case it is
+		//modified outside the store in the middle of a request
+		var query = {};
+		for(var attr in this._queryAttrs) {
+			query[attr] = request.query[attr];
+		}		
+		request = {
+			query: query,
+			onComplete: request.onComplete,
+			onError: request.onError,
+			onItem: request.onItem,
+			onBegin: request.onBegin,
+			start: request.start,
+			count: request.count
+		};
+
+		//Google's web api will only return a max of 8 results per page.
+		var pageSize = 8;
+
+		//Generate a unique function to be called back
+		var callbackFn = "GoogleSearchStoreCallback_" + this._id + "_" + (++this._requestCount);
+
+		//Build up the content to send the request for.
+		//rsz is the result size, "large" gives 8 results each time
+		var content = this._createContent(query, callbackFn, request);
+
+		var firstRequest;
+
+		if(typeof(request.start) === "undefined" || request.start === null){
+			request.start = 0;
+		}
+
+		if(!request.count){
+			request.count = pageSize;
+		}
+		firstRequest = {start: request.start - request.start % pageSize};
+
+		var _this = this;
+		var searchUrl = this._googleUrl + this._type;
+
+		var getArgs = {
+			url: searchUrl,
+			preventCache: this.urlPreventCache,
+			content: content
+		};
+
+		var items = [];
+		var successfulReq = 0;
+		var finished = false;
+		var lastOnItem = request.start -1;
+		var numRequests = 0;
+		var scriptIds = [];
+
+		// Performs the remote request.
+		function doRequest(req){
+			//Record how many requests have been made.
+			numRequests ++;
+			getArgs.content.context = getArgs.content.start = req.start;
+
+			var deferred = dojo.io.script.get(getArgs);
+			scriptIds.push(deferred.ioArgs.id);
+
+			//We only set up the errback, because the callback isn't ever really used because we have
+			//to link to the jsonp callback function....
+			deferred.addErrback(function(error){
+				if(request.onError){
+					request.onError.call(scope, error, request);
+				}
+			});
+		}
+
+		// Function to handle returned data.
+		var myHandler = function(start, data){
+			if (scriptIds.length > 0) {
+				// Delete the script node that was created.
+				dojo.query("#" + scriptIds.splice(0,1)).forEach(dojo.destroy);
+			}
+			if(finished){return;}
+
+			var results = _this._getItems(data);
+			var cursor = data ? data['cursor']: null;
+
+			if(results){
+				//Process the results, adding the store reference to them
+				for(var i = 0; i < results.length && i + start < request.count + request.start; i++) {
+					_this._processItem(results[i], data);
+					items[i + start] = results[i];
+				}
+				successfulReq ++;
+				if(successfulReq == 1){
+					// After the first request, we know how many results exist.
+					// So perform any follow up requests to retrieve more data.
+					var pages = cursor ? cursor.pages : null;
+					var firstStart = pages ? Number(pages[pages.length - 1].start) : 0;
+
+					//Call the onBegin method if it exists
+					if (request.onBegin){
+						var est = cursor ? cursor.estimatedResultCount : results.length;
+						var total =  est ? Math.min(est, firstStart + results.length) : firstStart + results.length;
+						request.onBegin.call(scope, total, request);
+					}
+
+					// Request the next pages.
+					var nextPage = (request.start - request.start % pageSize) + pageSize;
+					var page = 1;
+					while(pages){
+						if(!pages[page] || Number(pages[page].start) >= request.start + request.count){
+							break;
+						}
+						if(Number(pages[page].start) >= nextPage) {
+							doRequest({start: pages[page].start});
+						}
+						page++;
+					}
+				}
+
+				// Call the onItem function on all retrieved items.
+				if(request.onItem && items[lastOnItem + 1]){
+					do{
+						lastOnItem++;
+						request.onItem.call(scope, items[lastOnItem], request);
+					}while(items[lastOnItem + 1] && lastOnItem < request.start + request.count);
+				}
+
+				//If this is the last request, call final fetch handler.
+				if(successfulReq == numRequests){
+					//Process the items...
+					finished = true;
+					//Clean up the function, it should never be called again
+					dojo.global[callbackFn] = null;
+					if(request.onItem){
+						request.onComplete.call(scope, null, request);
+					}else{
+						items = items.slice(request.start, request.start + request.count);
+						request.onComplete.call(scope, items, request);
+					}
+
+				}
+			}
+		};
+
+		var callbacks = [];
+		var lastCallback = firstRequest.start - 1;
+
+		// Attach a callback function to the global namespace, where Google can call it.
+		dojo.global[callbackFn] = function(start, data, responseCode, errorMsg){
+			try {
+				if(responseCode != 200){
+					if(request.onError){
+						request.onError.call(scope, new Error("Response from Google was: " + responseCode), request);
+					}
+					dojo.global[callbackFn] = function(){};//an error occurred, do not return anything else.
+					return;
+				}
+	
+				if(start == lastCallback + 1){
+					myHandler(Number(start), data);
+					lastCallback += pageSize;
+	
+					//make sure that the callbacks happen in the correct sequence
+					if(callbacks.length > 0){
+						callbacks.sort(_this._getSort());
+						//In case the requsts do not come back in order, sort the returned results.
+						while(callbacks.length > 0 && callbacks[0].start == lastCallback + 1){
+							myHandler(Number(callbacks[0].start), callbacks[0].data);
+							callbacks.splice(0,1);
+							lastCallback += pageSize;
+						}
+					}
+				}else{
+					callbacks.push({start:start, data: data});
+				}
+			} catch (e) {
+				request.onError.call(scope, e, request);
+			}
+		};
+
+		// Perform the first request. When this has finished
+		// we will have a list of pages, which can then be
+		// gone through
+		doRequest(firstRequest);
+	},
+	
+	_getSort: function() {
+		return function(a,b){
+			if(a.start < b.start){return -1;}
+			if(b.start < a.start){return 1;}
+			return 0;
+		};
+	},
+
+	_processItem: function(item, data) {
+		item[this._storeRef] = this;
+		// Copy aggregated attributes from query results to the item.
+		for(var attribute in this._aggregatedAttributes) {
+			item[attribute] = dojo.getObject(this._aggregatedAttributes[attribute], false, data);
+		}
+	},
+
+	_getItems: function(data){
+		return data['results'] || data;
+	},
+
+	_createContent: function(query, callback, request){
+		var content = {
+			v: "1.0",
+			rsz: "large",
+			callback: callback,
+			key: this._key,
+			hl: this._lang
+		};
+		for(var attr in this._queryAttrs) {
+			content[this._queryAttrs[attr]] = query[attr];
+		}
+		return content;
+	}
+});
+
+dojo.declare("dojox.data.GoogleWebSearchStore", dojox.data.GoogleSearchStore,{
+	//	Summary:
+	//		A data store for retrieving search results from Google.
+	//		The following attributes are supported on each item:
+	//		<ul>
+	//			<li>title - The page title in HTML format.</li>
+	//			<li>titleNoFormatting - The page title in plain text</li>
+	//			<li>content - A snippet of information about the page</li>
+	//			<li>url - The URL for the item</li>
+	//			<li>unescapedUrl - The URL for the item, with URL escaping. This is often more readable</li>
+	//			<li>visibleUrl - The URL with no protocol specified.</li>
+	//			<li>cacheUrl - The URL to the copy of the document cached by Google</li>
+	//			<li>estimatedResultCount - (aggregated per-query) estimated number of results</li>
+	//		</ul>
+	//		The query accepts one parameter: text - The string to search for
+});
+
+dojo.declare("dojox.data.GoogleBlogSearchStore", dojox.data.GoogleSearchStore,{
+	//	Summary:
+	//		A data store for retrieving search results from Google.
+	//		The following attributes are supported on each item:
+	//		<ul>
+	//			<li>title - The blog post title in HTML format.</li>
+	//			<li>titleNoFormatting - The  blog post title in plain text</li>
+	//			<li>content - A snippet of information about the blog post</li>
+	//			<li>blogUrl - The URL for the blog</li>
+	//			<li>postUrl - The URL for the a single blog post</li>
+	//			<li>visibleUrl - The URL with no protocol specified.
+	//			<li>cacheUrl - The URL to the copy of the document cached by Google
+	//			<li>author - The author of the blog post</li>
+	//			<li>publishedDate - The published date, in RFC-822 format</li>
+	//		</ul>
+	//		The query accepts one parameter: text - The string to search for
+	_type: "blogs",
+	_attributes: ["blogUrl", "postUrl", "title", "titleNoFormatting", "content", 
+			"author", "publishedDate"],
+	_aggregatedAttributes: { }
+});
+
+
+dojo.declare("dojox.data.GoogleLocalSearchStore", dojox.data.GoogleSearchStore,{
+	//	summary:
+	//		A data store for retrieving search results from Google.
+	//		The following attributes are supported on each item:
+	//		<ul>
+	//			<li>title - The blog post title in HTML format.</li>
+	//			<li>titleNoFormatting - The  blog post title in plain text</li>
+	//			<li>content - A snippet of information about the blog post</li>
+	//			<li>url - The URL for the item</li>
+	//			<li>lat - The latitude.</li>
+	//			<li>lng - The longtitude.</li>
+	//			<li>streetAddress - The street address</li>
+	//			<li>city - The city</li>
+	//			<li>region - The region</li>
+	//			<li>country - The country</li>
+	//			<li>phoneNumbers - Phone numbers associated with this address. Can be one or more.</li>
+	//			<li>ddUrl - A URL that can be used to provide driving directions from the center of the search results to this search results</li>
+	//			<li>ddUrlToHere - A URL that can be used to provide driving directions from this search result to a user specified location</li>
+	//			<li>staticMapUrl - The published date, in RFC-822 format</li>
+	//			<li>viewport - Recommended viewport for the query results (same for all results in a query)
+	//				<ul>
+	//					<li>center - contains lat, lng properties</li>
+	//					<li>span - lat, lng properties for the viewport span</li>
+	//					<li>ne, sw - lat, lng properties for the viewport corners<li>
+	//				</ul>
+	//			</li>
+	//		</ul>
+	//		The query accepts the following parameters:
+	//		<ul>
+	//			<li>text - The string to search for</li>
+	//			<li>centerLatLong - Comma-separated lat & long for the center of the search (e.g. "48.8565,2.3509")</li>
+	//			<li>searchSpan - Comma-separated lat & long degrees indicating the size of the desired search area (e.g. "0.065165,0.194149")</li>
+	//		</ul>
+	_type: "local",
+	_attributes: ["title", "titleNoFormatting", "url", "lat", "lng", "streetAddress",
+			"city", "region", "country", "phoneNumbers", "ddUrl", "ddUrlToHere",
+			"ddUrlFromHere", "staticMapUrl", "viewport"],
+	_aggregatedAttributes: {
+		viewport: "viewport"
+	},
+	_queryAttrs: {
+		text: 'q',
+		centerLatLong: 'sll',
+		searchSpan: 'sspn'
+	}
+});
+
+dojo.declare("dojox.data.GoogleVideoSearchStore", dojox.data.GoogleSearchStore,{
+	//	summary:
+	//		A data store for retrieving search results from Google.
+	//		The following attributes are supported on each item:
+	//		<ul>
+	//			<li>title - The blog post title in HTML format.</li>
+	//			<li>titleNoFormatting - The  blog post title in plain text</li>
+	//			<li>content - A snippet of information about the blog post</li>
+	//			<li>url - The URL for the item</li>
+	//			<li>published - The published date, in RFC-822 format.</li>
+	//			<li>publisher - The name of the publisher.</li>
+	//			<li>duration - The approximate duration, in seconds, of the video.</li>
+	//			<li>tbWidth - The width in pixels of the video.</li>
+	//			<li>tbHeight - The height in pixels of the video</li>
+	//			<li>tbUrl - The URL to a thumbnail representation of the video.</li>
+	//			<li>playUrl - If present, supplies the url of the flash version of the video that can be played inline on your page. To play this video simply create and <embed> element on your page using this value as the src attribute and using application/x-shockwave-flash as the type attribute. If you want the video to play right away, make sure to append &autoPlay=true to the url..</li>
+	//		</ul>
+	//		The query accepts one parameter: text - The string to search for
+	_type: "video",
+	_attributes: ["title", "titleNoFormatting", "content", "url", "published", "publisher",
+			"duration", "tbWidth", "tbHeight", "tbUrl", "playUrl"],
+	_aggregatedAttributes: { }
+});
+
+dojo.declare("dojox.data.GoogleNewsSearchStore", dojox.data.GoogleSearchStore,{
+	//	summary:
+	//		A data store for retrieving search results from Google.
+	//		The following attributes are supported on each item:
+	//		<ul>
+	//			<li>title - The news story title in HTML format.</li>
+	//			<li>titleNoFormatting - The news story title in plain text</li>
+	//			<li>content - A snippet of information about the news story</li>
+	//			<li>url - The URL for the item</li>
+	//			<li>unescapedUrl - The URL for the item, with URL escaping. This is often more readable</li>
+	//			<li>publisher - The name of the publisher</li>
+	//			<li>clusterUrl - A URL pointing to a page listing related storied.</li>
+	//			<li>location - The location of the news story.</li>
+	//			<li>publishedDate - The date of publication, in RFC-822 format.</li>
+	//			<li>relatedStories - An optional array of objects specifying related stories.
+	//				Each object has the following subset of properties:
+	//				"title", "titleNoFormatting", "url", "unescapedUrl", "publisher", "location", "publishedDate".
+	//			</li>
+	//		</ul>
+	//		The query accepts one parameter: text - The string to search for
+	_type: "news",
+	_attributes: ["title", "titleNoFormatting", "content", "url", "unescapedUrl", "publisher",
+			"clusterUrl", "location", "publishedDate", "relatedStories" ],
+	_aggregatedAttributes: { }
+});
+
+dojo.declare("dojox.data.GoogleBookSearchStore", dojox.data.GoogleSearchStore,{
+	// 	summary:
+	//		A data store for retrieving search results from Google.
+	//		The following attributes are supported on each item:
+	//		<ul>
+	//			<li>title - The book title in HTML format.</li>
+	//			<li>titleNoFormatting - The book title in plain text</li>
+	//			<li>authors - An array of authors</li>
+	//			<li>url - The URL for the item</li>
+	//			<li>unescapedUrl - The URL for the item, with URL escaping. This is often more readable</li>
+	//			<li>bookId - An identifier for the book, usually an ISBN.</li>
+	//			<li>pageCount - The number of pages in the book.</li>
+	//			<li>publishedYear - The year of publication.</li>
+	//		</ul>
+	//		The query accepts one parameter: text - The string to search for
+	_type: "books",
+	_attributes: ["title", "titleNoFormatting", "authors", "url", "unescapedUrl", "bookId",
+			"pageCount", "publishedYear"],
+	_aggregatedAttributes: { }
+});
+
+dojo.declare("dojox.data.GoogleImageSearchStore", dojox.data.GoogleSearchStore,{
+	//	summary:
+	//		A data store for retrieving search results from Google.
+	//		The following attributes are supported on each item:
+	//		<ul>
+	//			<li>title - The image title in HTML format.</li>
+	//			<li>titleNoFormatting - The image title in plain text</li>
+	//			<li>url - The URL for the image</li>
+	//			<li>unescapedUrl - The URL for the image, with URL escaping. This is often more readable</li>
+	//			<li>tbUrl - The URL for the image thumbnail</li>
+	//			<li>visibleUrl - A shortened version of the URL associated with the result, stripped of a protocol and path</li>
+	//			<li>originalContextUrl - The URL of the page containing the image.</li>
+	//			<li>width - The width of the image in pixels.</li>
+	//			<li>height - The height of the image in pixels.</li>
+	//			<li>tbWidth - The width of the image thumbnail in pixels.</li>
+	//			<li>tbHeight - The height of the image thumbnail in pixels.</li>
+	//			<li>content - A snippet of information about the image, in HTML format</li>
+	//			<li>contentNoFormatting - A snippet of information about the image, in plain text</li>
+	//		</ul>
+	//		The query accepts one parameter: text - The string to search for
+	_type: "images",
+	_attributes: ["title", "titleNoFormatting", "visibleUrl", "url", "unescapedUrl", 
+			"originalContextUrl", "width", "height", "tbWidth", "tbHeight", 
+			"tbUrl", "content", "contentNoFormatting"],
+	_aggregatedAttributes: { }
 });
-};
-var _2d=function(_2e,_2f){
-if(_29.length>0){
-dojo.query("#"+_29.splice(0,1)).forEach(dojo.destroy);
-}
-if(_26){
-return;
-}
-var _30=_21._getItems(_2f);
-var _31=_2f?_2f["cursor"]:null;
-if(_30){
-for(var i=0;i<_30.length&&i+_2e<_19.count+_19.start;i++){
-_21._processItem(_30[i],_2f);
-_24[i+_2e]=_30[i];
-}
-_25++;
-if(_25==1){
-var _32=_31?_31.pages:null;
-var _33=_32?Number(_32[_32.length-1].start):0;
-if(_19.onBegin){
-var est=_31?_31.estimatedResultCount:_30.length;
-var _34=est?Math.min(est,_33+_30.length):_33+_30.length;
-_19.onBegin.call(_1a,_34,_19);
-}
-var _35=(_19.start-_19.start%_1d)+_1d;
-var _36=1;
-while(_32){
-if(!_32[_36]||Number(_32[_36].start)>=_19.start+_19.count){
-break;
-}
-if(Number(_32[_36].start)>=_35){
-_2a({start:_32[_36].start});
-}
-_36++;
-}
-}
-if(_19.onItem&&_24[_27+1]){
-do{
-_27++;
-_19.onItem.call(_1a,_24[_27],_19);
-}while(_24[_27+1]&&_27<_19.start+_19.count);
-}
-if(_25==_28){
-_26=true;
-dojo.global[_1e]=null;
-if(_19.onItem){
-_19.onComplete.call(_1a,null,_19);
-}else{
-_24=_24.slice(_19.start,_19.start+_19.count);
-_19.onComplete.call(_1a,_24,_19);
-}
-}
-}
-};
-var _37=[];
-var _38=_20.start-1;
-dojo.global[_1e]=function(_39,_3a,_3b,_3c){
-try{
-if(_3b!=200){
-if(_19.onError){
-_19.onError.call(_1a,new Error("Response from Google was: "+_3b),_19);
-}
-dojo.global[_1e]=function(){
-};
-return;
-}
-if(_39==_38+1){
-_2d(Number(_39),_3a);
-_38+=_1d;
-if(_37.length>0){
-_37.sort(_21._getSort());
-while(_37.length>0&&_37[0].start==_38+1){
-_2d(Number(_37[0].start),_37[0].data);
-_37.splice(0,1);
-_38+=_1d;
-}
-}
-}else{
-_37.push({start:_39,data:_3a});
-}
-}
-catch(e){
-_19.onError.call(_1a,e,_19);
-}
-};
-_2a(_20);
-},_getSort:function(){
-return function(a,b){
-if(a.start<b.start){
-return -1;
-}
-if(b.start<a.start){
-return 1;
-}
-return 0;
-};
-},_processItem:function(_3d,_3e){
-_3d[this._storeRef]=this;
-for(var _3f in this._aggregatedAttributes){
-_3d[_3f]=dojo.getObject(this._aggregatedAttributes[_3f],false,_3e);
-}
-},_getItems:function(_40){
-return _40["results"]||_40;
-},_createContent:function(_41,_42,_43){
-var _44={v:"1.0",rsz:"large",callback:_42,key:this._key,hl:this._lang};
-for(var _45 in this._queryAttrs){
-_44[this._queryAttrs[_45]]=_41[_45];
-}
-return _44;
-}});
-dojo.declare("dojox.data.GoogleWebSearchStore",dojox.data.GoogleSearchStore,{});
-dojo.declare("dojox.data.GoogleBlogSearchStore",dojox.data.GoogleSearchStore,{_type:"blogs",_attributes:["blogUrl","postUrl","title","titleNoFormatting","content","author","publishedDate"],_aggregatedAttributes:{}});
-dojo.declare("dojox.data.GoogleLocalSearchStore",dojox.data.GoogleSearchStore,{_type:"local",_attributes:["title","titleNoFormatting","url","lat","lng","streetAddress","city","region","country","phoneNumbers","ddUrl","ddUrlToHere","ddUrlFromHere","staticMapUrl","viewport"],_aggregatedAttributes:{viewport:"viewport"},_queryAttrs:{text:"q",centerLatLong:"sll",searchSpan:"sspn"}});
-dojo.declare("dojox.data.GoogleVideoSearchStore",dojox.data.GoogleSearchStore,{_type:"video",_attributes:["title","titleNoFormatting","content","url","published","publisher","duration","tbWidth","tbHeight","tbUrl","playUrl"],_aggregatedAttributes:{}});
-dojo.declare("dojox.data.GoogleNewsSearchStore",dojox.data.GoogleSearchStore,{_type:"news",_attributes:["title","titleNoFormatting","content","url","unescapedUrl","publisher","clusterUrl","location","publishedDate","relatedStories"],_aggregatedAttributes:{}});
-dojo.declare("dojox.data.GoogleBookSearchStore",dojox.data.GoogleSearchStore,{_type:"books",_attributes:["title","titleNoFormatting","authors","url","unescapedUrl","bookId","pageCount","publishedYear"],_aggregatedAttributes:{}});
-dojo.declare("dojox.data.GoogleImageSearchStore",dojox.data.GoogleSearchStore,{_type:"images",_attributes:["title","titleNoFormatting","visibleUrl","url","unescapedUrl","originalContextUrl","width","height","tbWidth","tbHeight","tbUrl","content","contentNoFormatting"],_aggregatedAttributes:{}});
-}
diff --git a/dojox/data/HtmlStore.js b/dojox/data/HtmlStore.js
index 079c756..c03e6e3 100644
--- a/dojox/data/HtmlStore.js
+++ b/dojox/data/HtmlStore.js
@@ -1,322 +1,558 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.HtmlStore"]){
-dojo._hasResource["dojox.data.HtmlStore"]=true;
 dojo.provide("dojox.data.HtmlStore");
+
 dojo.require("dojox.xml.parser");
 dojo.require("dojo.data.util.simpleFetch");
 dojo.require("dojo.data.util.filter");
-dojo.declare("dojox.data.HtmlStore",null,{constructor:function(_1){
-if(_1&&"urlPreventCache" in _1){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-if(_1&&"trimWhitespace" in _1){
-this.trimWhitespace=_1.trimWhitespace?true:false;
-}
-if(_1.url){
-if(!_1.dataId){
-throw new Error("dojo.data.HtmlStore: Cannot instantiate using url without an id!");
-}
-this.url=_1.url;
-this.dataId=_1.dataId;
-}else{
-if(_1.dataId){
-this._rootNode=dojo.byId(_1.dataId);
-this.dataId=this._rootNode.id;
-}else{
-this._rootNode=dojo.byId(this.dataId);
-}
-this._indexItems();
-}
-},url:"",dataId:"",trimWhitespace:false,urlPreventCache:false,_indexItems:function(){
-this._getHeadings();
-if(this._rootNode.rows){
-if(this._rootNode.tBodies&&this._rootNode.tBodies.length>0){
-this._rootNode=this._rootNode.tBodies[0];
-}
-var i;
-for(i=0;i<this._rootNode.rows.length;i++){
-this._rootNode.rows[i].store=this;
-this._rootNode.rows[i]._ident=i+1;
-}
-}else{
-var c=1;
-for(i=0;i<this._rootNode.childNodes.length;i++){
-if(this._rootNode.childNodes[i].nodeType===1){
-this._rootNode.childNodes[i].store=this;
-this._rootNode.childNodes[i]._ident=c;
-c++;
-}
-}
-}
-},_getHeadings:function(){
-this._headings=[];
-if(this._rootNode.tHead){
-dojo.forEach(this._rootNode.tHead.rows[0].cells,dojo.hitch(this,function(th){
-var _2=dojox.xml.parser.textContent(th);
-this._headings.push(this.trimWhitespace?dojo.trim(_2):_2);
-}));
-}else{
-this._headings=["name"];
-}
-},_getAllItems:function(){
-var _3=[];
-var i;
-if(this._rootNode.rows){
-for(i=0;i<this._rootNode.rows.length;i++){
-_3.push(this._rootNode.rows[i]);
-}
-}else{
-for(i=0;i<this._rootNode.childNodes.length;i++){
-if(this._rootNode.childNodes[i].nodeType===1){
-_3.push(this._rootNode.childNodes[i]);
-}
-}
-}
-return _3;
-},_assertIsItem:function(_4){
-if(!this.isItem(_4)){
-throw new Error("dojo.data.HtmlStore: a function was passed an item argument that was not an item");
-}
-},_assertIsAttribute:function(_5){
-if(typeof _5!=="string"){
-throw new Error("dojo.data.HtmlStore: a function was passed an attribute argument that was not an attribute name string");
-return -1;
-}
-return dojo.indexOf(this._headings,_5);
-},getValue:function(_6,_7,_8){
-var _9=this.getValues(_6,_7);
-return (_9.length>0)?_9[0]:_8;
-},getValues:function(_a,_b){
-this._assertIsItem(_a);
-var _c=this._assertIsAttribute(_b);
-if(_c>-1){
-var _d;
-if(_a.cells){
-_d=dojox.xml.parser.textContent(_a.cells[_c]);
-}else{
-_d=dojox.xml.parser.textContent(_a);
-}
-return [this.trimWhitespace?dojo.trim(_d):_d];
-}
-return [];
-},getAttributes:function(_e){
-this._assertIsItem(_e);
-var _f=[];
-for(var i=0;i<this._headings.length;i++){
-if(this.hasAttribute(_e,this._headings[i])){
-_f.push(this._headings[i]);
-}
-}
-return _f;
-},hasAttribute:function(_10,_11){
-return this.getValues(_10,_11).length>0;
-},containsValue:function(_12,_13,_14){
-var _15=undefined;
-if(typeof _14==="string"){
-_15=dojo.data.util.filter.patternToRegExp(_14,false);
-}
-return this._containsValue(_12,_13,_14,_15);
-},_containsValue:function(_16,_17,_18,_19){
-var _1a=this.getValues(_16,_17);
-for(var i=0;i<_1a.length;++i){
-var _1b=_1a[i];
-if(typeof _1b==="string"&&_19){
-return (_1b.match(_19)!==null);
-}else{
-if(_18===_1b){
-return true;
-}
-}
-}
-return false;
-},isItem:function(_1c){
-if(_1c&&_1c.store&&_1c.store===this){
-return true;
-}
-return false;
-},isItemLoaded:function(_1d){
-return this.isItem(_1d);
-},loadItem:function(_1e){
-this._assertIsItem(_1e.item);
-},_fetchItems:function(_1f,_20,_21){
-if(this._rootNode){
-this._finishFetchItems(_1f,_20,_21);
-}else{
-if(!this.url){
-this._rootNode=dojo.byId(this.dataId);
-}else{
-var _22={url:this.url,handleAs:"text",preventCache:this.urlPreventCache};
-var _23=this;
-var _24=dojo.xhrGet(_22);
-_24.addCallback(function(_25){
-var _26=function(_27,id){
-if(_27.id==id){
-return _27;
-}
-if(_27.childNodes){
-for(var i=0;i<_27.childNodes.length;i++){
-var _28=_26(_27.childNodes[i],id);
-if(_28){
-return _28;
-}
-}
-}
-return null;
-};
-var d=document.createElement("div");
-d.innerHTML=_25;
-_23._rootNode=_26(d,_23.dataId);
-_23._indexItems();
-_23._finishFetchItems(_1f,_20,_21);
-});
-_24.addErrback(function(_29){
-_21(_29,_1f);
-});
-}
-}
-},_finishFetchItems:function(_2a,_2b,_2c){
-var _2d=null;
-var _2e=this._getAllItems();
-if(_2a.query){
-var _2f=_2a.queryOptions?_2a.queryOptions.ignoreCase:false;
-_2d=[];
-var _30={};
-var key;
-var _31;
-for(key in _2a.query){
-_31=_2a.query[key]+"";
-if(typeof _31==="string"){
-_30[key]=dojo.data.util.filter.patternToRegExp(_31,_2f);
-}
-}
-for(var i=0;i<_2e.length;++i){
-var _32=true;
-var _33=_2e[i];
-for(key in _2a.query){
-_31=_2a.query[key]+"";
-if(!this._containsValue(_33,key,_31,_30[key])){
-_32=false;
-}
-}
-if(_32){
-_2d.push(_33);
-}
-}
-_2b(_2d,_2a);
-}else{
-if(_2e.length>0){
-_2d=_2e.slice(0,_2e.length);
-}
-_2b(_2d,_2a);
-}
-},getFeatures:function(){
-return {"dojo.data.api.Read":true,"dojo.data.api.Identity":true};
-},close:function(_34){
-},getLabel:function(_35){
-if(this.isItem(_35)){
-if(_35.cells){
-return "Item #"+this.getIdentity(_35);
-}else{
-return this.getValue(_35,"name");
-}
-}
-return undefined;
-},getLabelAttributes:function(_36){
-if(_36.cells){
-return null;
-}else{
-return ["name"];
-}
-},getIdentity:function(_37){
-this._assertIsItem(_37);
-if(this.hasAttribute(_37,"name")){
-return this.getValue(_37,"name");
-}else{
-return _37._ident;
-}
-},getIdentityAttributes:function(_38){
-return null;
-},fetchItemByIdentity:function(_39){
-var _3a=_39.identity;
-var _3b=this;
-var _3c=null;
-var _3d=null;
-if(!this._rootNode){
-if(!this.url){
-this._rootNode=dojo.byId(this.dataId);
-this._indexItems();
-if(_3b._rootNode.rows){
-_3c=this._rootNode.rows[_3a+1];
-}else{
-for(var i=0;i<_3b._rootNode.childNodes.length;i++){
-if(_3b._rootNode.childNodes[i].nodeType===1&&_3a===dojox.xml.parser.textContent(_3b._rootNode.childNodes[i])){
-_3c=_3b._rootNode.childNodes[i];
-}
-}
-}
-if(_39.onItem){
-_3d=_39.scope?_39.scope:dojo.global;
-_39.onItem.call(_3d,_3c);
-}
-}else{
-var _3e={url:this.url,handleAs:"text"};
-var _3f=dojo.xhrGet(_3e);
-_3f.addCallback(function(_40){
-var _41=function(_42,id){
-if(_42.id==id){
-return _42;
-}
-if(_42.childNodes){
-for(var i=0;i<_42.childNodes.length;i++){
-var _43=_41(_42.childNodes[i],id);
-if(_43){
-return _43;
-}
-}
-}
-return null;
-};
-var d=document.createElement("div");
-d.innerHTML=_40;
-_3b._rootNode=_41(d,_3b.dataId);
-_3b._indexItems();
-if(_3b._rootNode.rows&&_3a<=_3b._rootNode.rows.length){
-_3c=_3b._rootNode.rows[_3a-1];
-}else{
-for(var i=0;i<_3b._rootNode.childNodes.length;i++){
-if(_3b._rootNode.childNodes[i].nodeType===1&&_3a===dojox.xml.parser.textContent(_3b._rootNode.childNodes[i])){
-_3c=_3b._rootNode.childNodes[i];
-break;
-}
-}
-}
-if(_39.onItem){
-_3d=_39.scope?_39.scope:dojo.global;
-_39.onItem.call(_3d,_3c);
-}
-});
-_3f.addErrback(function(_44){
-if(_39.onError){
-_3d=_39.scope?_39.scope:dojo.global;
-_39.onError.call(_3d,_44);
-}
+
+dojo.declare("dojox.data.HtmlStore", null, {
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		Initializer for the HTML table store.  
+		//	description:
+		//		The HtmlStore can be created in one of two ways: a) by parsing an existing
+		//		table or list DOM node on the current page or b) by referencing an external url and giving
+		//		the id of the table or list in that page.  The remote url will be parsed as an html page.
+		//
+		//		The HTML table or list should be of the following form:
+		//
+		//		|	<table id="myTable">
+		//		|		<thead>
+		//		|			<tr>
+		//		|				<th>Attribute1</th>
+		//		|				<th>Attribute2</th>
+		//		|			</tr>
+		//		|		</thead>
+		//		|		<tbody>
+		//		|			<tr>
+		//		|				<td>Value1.1</td>
+		//		|				<td>Value1.2</td>
+		//		|			</tr>
+		//		|			<tr>
+		//		|				<td>Value2.1</td>
+		//		|				<td>Value2.2</td>
+		//		|			</tr>
+		//		|		</tbody>
+		//		|	</table>
+		//
+		// -or-
+		//
+		//		|	<ul id="myUnorderedList">
+		//		|		<li>Value.1</li>
+		//		|		<li>Value.2</li>
+		//		|	</ul>
+		//
+		// -or-
+		//
+		//		|	<ol id="myOrderedList">
+		//		|		<li>Value.1</li>
+		//		|		<li>Value.2</li>
+		//		|	</ol>
+		//
+		//	args:
+		//		An anonymous object to initialize properties.  It expects the following values:
+		//		dataId:	The id of the HTML table to use.
+		//		OR
+		//		url:	The url of the remote page to load
+		//		dataId:	The id of the table element in the remote page
+		//		and the option:
+		//		trimWhitespace:  Trim off any surrounding whitespace from the headers (attribute
+		//			names) and text content of the items in question.  Default is false for 
+		//			backwards compatibility.
+		if(args && "urlPreventCache" in args){
+			this.urlPreventCache = args.urlPreventCache?true:false;
+		}
+		if(args && "trimWhitespace" in args){
+			this.trimWhitespace = args.trimWhitespace?true:false;
+		}
+		if(args.url){
+			if(!args.dataId)
+				throw new Error("dojo.data.HtmlStore: Cannot instantiate using url without an id!");
+			this.url = args.url;
+			this.dataId = args.dataId;
+		}else{
+			if(args.dataId){
+				this._rootNode = dojo.byId(args.dataId);
+				this.dataId = this._rootNode.id;
+			}else{
+				this._rootNode = dojo.byId(this.dataId);
+			}
+			this._indexItems();
+		}
+	},
+
+	// url: [public] string
+	//		The URL from which to load an HTML document for data loading
+	url: "",
+	
+	// dataId: [public] string
+	//		The id in the document for an element from which to get the data.
+	dataId: "",
+
+	// trimWhitepace: [public] boolean
+	//		Boolean flag to denote if the store should trim whitepace around 
+	//		header and data content of a node.  This matters if reformatters
+	//		alter the white spacing around the tags.  The default is false for
+	//		backwards compat.
+	trimWhitespace: false, 
+
+	// urlPreventCache: [public] boolean
+	//		Flag to denote if peventCache should be used on xhrGet calls.
+	urlPreventCache: false,
+	
+	_indexItems: function(){
+		// summary:
+		//		Function to index items found under the id.
+		// tags:
+		//		private
+		this._getHeadings();
+		if(this._rootNode.rows){//tables
+			if(this._rootNode.tBodies && this._rootNode.tBodies.length > 0){
+				this._rootNode = this._rootNode.tBodies[0];
+			}
+			var i;
+			for(i=0; i<this._rootNode.rows.length; i++){
+				this._rootNode.rows[i].store = this;
+				this._rootNode.rows[i]._ident = i+1;
+			}
+		}else{//lists
+			var c=1;
+			for(i=0; i<this._rootNode.childNodes.length; i++){
+				if(this._rootNode.childNodes[i].nodeType === 1){
+					this._rootNode.childNodes[i].store = this;
+					this._rootNode.childNodes[i]._ident = c;
+					c++;
+				}
+			}
+		}
+	},
+
+	_getHeadings: function(){
+		//	summary:
+		//		Function to load the attribute names from the table header so that the 
+		//		attributes (cells in a row), can have a reasonable name.
+		//      For list items, returns single implicit heading, ["name"]
+		this._headings = [];
+		if(this._rootNode.tHead){
+			dojo.forEach(this._rootNode.tHead.rows[0].cells, dojo.hitch(this, function(th){
+				var text = dojox.xml.parser.textContent(th); 
+				this._headings.push(this.trimWhitespace?dojo.trim(text):text);
+			}));
+		}else{
+			this._headings = ["name"];
+		}
+	},
+	
+	_getAllItems: function(){
+		//	summary:
+		//		Function to return all rows in the table as an array of items.
+		var items = [];
+		var i;
+		if(this._rootNode.rows){//table
+			for(i=0; i<this._rootNode.rows.length; i++){
+				items.push(this._rootNode.rows[i]);
+			}
+		}else{ //list
+			for(i=0; i<this._rootNode.childNodes.length; i++){
+				if(this._rootNode.childNodes[i].nodeType === 1){
+					items.push(this._rootNode.childNodes[i]);
+				}
+			}
+		}
+		return items; //array
+	},
+	
+	_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.HtmlStore: a function was passed an item argument that was not an item");
+		}
+	},
+
+	_assertIsAttribute: function(/* 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.
+		//
+		//	returns:
+		//		Returns the index (column) that the attribute resides in the row.
+		if(typeof attribute !== "string"){ 
+			throw new Error("dojo.data.HtmlStore: a function was passed an attribute argument that was not an attribute name string");
+			return -1;
+		}
+		return dojo.indexOf(this._headings, attribute); //int
+	},
+
+/***************************************
+	 dojo.data.api.Read API
+***************************************/
+	
+	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; //Object || int || Boolean
+	},
+
+	getValues: function(/* item */ item, 
+						/* attribute-name-string */ attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.getValues()
+
+		this._assertIsItem(item);
+		var index = this._assertIsAttribute(attribute);
+		if(index>-1){
+			var text;
+			if(item.cells){
+				text = dojox.xml.parser.textContent(item.cells[index]);
+			}else{//return Value for lists
+				text = dojox.xml.parser.textContent(item);
+			}
+			return [this.trimWhitespace?dojo.trim(text):text];
+		}
+		return []; //Array
+	},
+
+	getAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getAttributes()
+		this._assertIsItem(item);
+		var attributes = [];
+		for(var i=0; i<this._headings.length; i++){
+			if(this.hasAttribute(item, this._headings[i]))
+				attributes.push(this._headings[i]);
+		}
+		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'
+		var values = this.getValues(item, attribute);
+		for(var i = 0; i < values.length; ++i){
+			var possibleValue = values[i];
+			if(typeof possibleValue === "string" && regexp){
+				return (possibleValue.match(regexp) !== null);
+			}else{
+				//Non-string matching.
+				if(value === possibleValue){
+					return true; // Boolean
+				}
+			}
+		}
+		return false; // Boolean
+	},
+
+	isItem: function(/* anything */ something){
+		//	summary: 
+		//		See dojo.data.api.Read.isItem()
+		if(something && something.store && something.store === this){
+			return true; //boolean
+		}
+		return false; //boolean
+	},
+
+	isItemLoaded: function(/* anything */ something){
+		//	summary: 
+		//		See dojo.data.api.Read.isItemLoaded()
+		return this.isItem(something);
+	},
+
+	loadItem: function(/* Object */ keywordArgs){
+		//	summary: 
+		//		See dojo.data.api.Read.loadItem()
+		this._assertIsItem(keywordArgs.item);
+	},
+	
+	_fetchItems: function(request, fetchHandler, errorHandler){
+		//	summary:
+		//		Fetch items (XML elements) that match to a query
+		//	description:
+		//		If '_fetchUrl' is specified, it is used to load an XML document
+		//		with a query string.
+		//		Otherwise and if 'url' is specified, the XML document is
+		//		loaded and list XML elements that match to a query (set of element
+		//		names and their text attribute values that the items to contain).
+		//		A wildcard, "*" can be used to query values to match all
+		//		occurrences.
+		//		If '_rootItem' is specified, it is used to fetch items.
+		//	request:
+		//		A request object
+		//	fetchHandler:
+		//		A function to call for fetched items
+		//	errorHandler:
+		//		A function to call on error
+		
+		if(this._rootNode){
+			this._finishFetchItems(request, fetchHandler, errorHandler);
+		}else{
+			if(!this.url){
+				this._rootNode = dojo.byId(this.dataId);
+			}else{
+				var getArgs = {
+						url: this.url,
+						handleAs: "text",
+						preventCache: this.urlPreventCache
+					};
+				var self = this;
+				var getHandler = dojo.xhrGet(getArgs);
+				getHandler.addCallback(function(data){
+					var findNode = function(node, id){
+						if(node.id == id){
+							return node; //object
+						}
+						if(node.childNodes){
+							for(var i=0; i<node.childNodes.length; i++){
+								var returnNode = findNode(node.childNodes[i], id);
+								if(returnNode){
+									return returnNode; //object
+								}
+							}
+						}
+						return null; //null
+					}
+
+					var d = document.createElement("div");
+					d.innerHTML = data;
+					self._rootNode = findNode(d, self.dataId);
+					self._indexItems();
+					self._finishFetchItems(request, fetchHandler, errorHandler);
+				});
+				getHandler.addErrback(function(error){
+					errorHandler(error, request);
+				});
+			}
+		}
+	},
+	
+	_finishFetchItems: function(request, fetchHandler, errorHandler){
+		//	summary:
+		//		Internal function for processing the passed in request and locating the requested items.
+		var items = [];
+		var arrayOfAllItems = this._getAllItems();
+		if(request.query){
+			var ignoreCase = request.queryOptions ? request.queryOptions.ignoreCase : false; 
+			items = [];
+
+			//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 = {};
+			var key;
+						var value;
+			for(key in request.query){
+				value = request.query[key]+'';
+				if(typeof value === "string"){
+					regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
+				}
+			}
+
+			for(var i = 0; i < arrayOfAllItems.length; ++i){
+				var match = true;
+				var candidateItem = arrayOfAllItems[i];
+				for(key in request.query){
+					value = request.query[key]+'';
+					if(!this._containsValue(candidateItem, key, value, regexpList[key])){
+						match = false;
+					}
+				}
+				if(match){
+					items.push(candidateItem);
+				}
+			}
+			fetchHandler(items, request);
+		}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 listsand sort without affecting each other.
+			if(arrayOfAllItems.length> 0){
+				items = arrayOfAllItems.slice(0,arrayOfAllItems.length); 
+			}
+			fetchHandler(items, request);
+		}
+	},
+
+	getFeatures: function(){
+		//	summary: 
+		//		See dojo.data.api.Read.getFeatures()
+		return {
+			'dojo.data.api.Read': true,
+			'dojo.data.api.Identity': true
+		};
+	},
+	
+	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+		//	summary:
+		//		See dojo.data.api.Read.close()
+		// nothing to do here!
+	},
+
+	getLabel: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabel()
+		if(this.isItem(item)){
+			if(item.cells){
+				return "Item #" + this.getIdentity(item);
+			}else{
+				return this.getValue(item,"name");
+			}
+		}
+		return undefined;
+	},
+
+	getLabelAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabelAttributes()
+		if(item.cells){
+			return null;
+		}else{
+			return ["name"];
+		}
+	},
+
+/***************************************
+	 dojo.data.api.Identity API
+***************************************/
+
+	getIdentity: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Identity.getIdentity()
+		this._assertIsItem(item);
+		if(this.hasAttribute(item, "name")){
+		 	return this.getValue(item,"name");
+		}else{
+			return item._ident;
+		}
+	},
+
+	getIdentityAttributes: function(/* item */ item){
+		 //	summary: 
+		 //		See dojo.data.api.Identity.getIdentityAttributes()
+		 //Identity isn't taken from a public attribute.
+		 return null;
+	},
+
+	fetchItemByIdentity: function(keywordArgs){
+		//	summary: 
+		//		See dojo.data.api.Identity.fetchItemByIdentity()
+		var identity = keywordArgs.identity;
+		var self = this;
+		var item = null;
+		var scope = null;
+		if(!this._rootNode){
+			if(!this.url){
+				this._rootNode = dojo.byId(this.dataId);
+				this._indexItems();
+				if(self._rootNode.rows){ //Table
+					item = this._rootNode.rows[identity + 1];
+				}else{ //Lists
+					for(var i = 0; i < self._rootNode.childNodes.length; i++){
+						if(self._rootNode.childNodes[i].nodeType === 1 && identity === dojox.xml.parser.textContent(self._rootNode.childNodes[i])){
+							item = self._rootNode.childNodes[i];
+						}
+					}
+				}
+				if(keywordArgs.onItem){
+					scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+					keywordArgs.onItem.call(scope, item);
+				}
+
+			}else{
+				var getArgs = {
+						url: this.url,
+						handleAs: "text"
+					};
+				var getHandler = dojo.xhrGet(getArgs);
+				getHandler.addCallback(function(data){
+					var findNode = function(node, id){
+						if(node.id == id){
+							return node; //object
+						}
+						if(node.childNodes){
+							for(var i=0; i<node.childNodes.length; i++){
+								var returnNode = findNode(node.childNodes[i], id);
+								if(returnNode){
+									return returnNode; //object
+								}
+							}
+						}
+						return null; //null
+					}
+					var d = document.createElement("div");
+					d.innerHTML = data;
+					self._rootNode = findNode(d, self.dataId);
+					self._indexItems();
+					if(self._rootNode.rows && identity <= self._rootNode.rows.length){ //Table
+						item = self._rootNode.rows[identity-1];
+					}else{ //List
+						for(var i = 0; i < self._rootNode.childNodes.length; i++){
+							if(self._rootNode.childNodes[i].nodeType === 1 && identity === dojox.xml.parser.textContent(self._rootNode.childNodes[i])){
+									item = self._rootNode.childNodes[i];
+									break;
+							}
+						}
+					}
+					if(keywordArgs.onItem){
+						scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+						keywordArgs.onItem.call(scope, item);
+					}
+				});
+				getHandler.addErrback(function(error){
+					if(keywordArgs.onError){
+						scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+						keywordArgs.onError.call(scope, error);
+
+					}
+				});
+			}
+		}else{
+			if(this._rootNode.rows[identity+1]){
+				item = this._rootNode.rows[identity+1];
+				if(keywordArgs.onItem){
+					scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+					keywordArgs.onItem.call(scope, item);
+				}
+			}
+		}
+	}
 });
-}
-}else{
-if(this._rootNode.rows[_3a+1]){
-_3c=this._rootNode.rows[_3a+1];
-if(_39.onItem){
-_3d=_39.scope?_39.scope:dojo.global;
-_39.onItem.call(_3d,_3c);
-}
-}
-}
-}});
 dojo.extend(dojox.data.HtmlStore,dojo.data.util.simpleFetch);
-}
diff --git a/dojox/data/HtmlTableStore.js b/dojox/data/HtmlTableStore.js
index cab7928..f46e33f 100644
--- a/dojox/data/HtmlTableStore.js
+++ b/dojox/data/HtmlTableStore.js
@@ -1,267 +1,470 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.HtmlTableStore"]){
-dojo._hasResource["dojox.data.HtmlTableStore"]=true;
 dojo.provide("dojox.data.HtmlTableStore");
+
 dojo.require("dojox.xml.parser");
 dojo.require("dojo.data.util.simpleFetch");
 dojo.require("dojo.data.util.filter");
-dojo.declare("dojox.data.HtmlTableStore",null,{constructor:function(_1){
-dojo.deprecated("dojox.data.HtmlTableStore","Please use dojox.data.HtmlStore");
-if(_1.url){
-if(!_1.tableId){
-throw new Error("dojo.data.HtmlTableStore: Cannot instantiate using url without an id!");
-}
-this.url=_1.url;
-this.tableId=_1.tableId;
-}else{
-if(_1.tableId){
-this._rootNode=dojo.byId(_1.tableId);
-this.tableId=this._rootNode.id;
-}else{
-this._rootNode=dojo.byId(this.tableId);
-}
-this._getHeadings();
-for(var i=0;i<this._rootNode.rows.length;i++){
-this._rootNode.rows[i].store=this;
-}
-}
-},url:"",tableId:"",_getHeadings:function(){
-this._headings=[];
-dojo.forEach(this._rootNode.tHead.rows[0].cells,dojo.hitch(this,function(th){
-this._headings.push(dojox.xml.parser.textContent(th));
-}));
-},_getAllItems:function(){
-var _2=[];
-for(var i=1;i<this._rootNode.rows.length;i++){
-_2.push(this._rootNode.rows[i]);
-}
-return _2;
-},_assertIsItem:function(_3){
-if(!this.isItem(_3)){
-throw new Error("dojo.data.HtmlTableStore: a function was passed an item argument that was not an item");
-}
-},_assertIsAttribute:function(_4){
-if(typeof _4!=="string"){
-throw new Error("dojo.data.HtmlTableStore: a function was passed an attribute argument that was not an attribute name string");
-return -1;
-}
-return dojo.indexOf(this._headings,_4);
-},getValue:function(_5,_6,_7){
-var _8=this.getValues(_5,_6);
-return (_8.length>0)?_8[0]:_7;
-},getValues:function(_9,_a){
-this._assertIsItem(_9);
-var _b=this._assertIsAttribute(_a);
-if(_b>-1){
-return [dojox.xml.parser.textContent(_9.cells[_b])];
-}
-return [];
-},getAttributes:function(_c){
-this._assertIsItem(_c);
-var _d=[];
-for(var i=0;i<this._headings.length;i++){
-if(this.hasAttribute(_c,this._headings[i])){
-_d.push(this._headings[i]);
-}
-}
-return _d;
-},hasAttribute:function(_e,_f){
-return this.getValues(_e,_f).length>0;
-},containsValue:function(_10,_11,_12){
-var _13=undefined;
-if(typeof _12==="string"){
-_13=dojo.data.util.filter.patternToRegExp(_12,false);
-}
-return this._containsValue(_10,_11,_12,_13);
-},_containsValue:function(_14,_15,_16,_17){
-var _18=this.getValues(_14,_15);
-for(var i=0;i<_18.length;++i){
-var _19=_18[i];
-if(typeof _19==="string"&&_17){
-return (_19.match(_17)!==null);
-}else{
-if(_16===_19){
-return true;
-}
-}
-}
-return false;
-},isItem:function(_1a){
-if(_1a&&_1a.store&&_1a.store===this){
-return true;
-}
-return false;
-},isItemLoaded:function(_1b){
-return this.isItem(_1b);
-},loadItem:function(_1c){
-this._assertIsItem(_1c.item);
-},_fetchItems:function(_1d,_1e,_1f){
-if(this._rootNode){
-this._finishFetchItems(_1d,_1e,_1f);
-}else{
-if(!this.url){
-this._rootNode=dojo.byId(this.tableId);
-this._getHeadings();
-for(var i=0;i<this._rootNode.rows.length;i++){
-this._rootNode.rows[i].store=this;
-}
-}else{
-var _20={url:this.url,handleAs:"text"};
-var _21=this;
-var _22=dojo.xhrGet(_20);
-_22.addCallback(function(_23){
-var _24=function(_25,id){
-if(_25.id==id){
-return _25;
-}
-if(_25.childNodes){
-for(var i=0;i<_25.childNodes.length;i++){
-var _26=_24(_25.childNodes[i],id);
-if(_26){
-return _26;
-}
-}
-}
-return null;
-};
-var d=document.createElement("div");
-d.innerHTML=_23;
-_21._rootNode=_24(d,_21.tableId);
-_21._getHeadings.call(_21);
-for(var i=0;i<_21._rootNode.rows.length;i++){
-_21._rootNode.rows[i].store=_21;
-}
-_21._finishFetchItems(_1d,_1e,_1f);
-});
-_22.addErrback(function(_27){
-_1f(_27,_1d);
-});
-}
-}
-},_finishFetchItems:function(_28,_29,_2a){
-var _2b=null;
-var _2c=this._getAllItems();
-if(_28.query){
-var _2d=_28.queryOptions?_28.queryOptions.ignoreCase:false;
-_2b=[];
-var _2e={};
-var _2f;
-var key;
-for(key in _28.query){
-_2f=_28.query[key]+"";
-if(typeof _2f==="string"){
-_2e[key]=dojo.data.util.filter.patternToRegExp(_2f,_2d);
-}
-}
-for(var i=0;i<_2c.length;++i){
-var _30=true;
-var _31=_2c[i];
-for(key in _28.query){
-_2f=_28.query[key]+"";
-if(!this._containsValue(_31,key,_2f,_2e[key])){
-_30=false;
-}
-}
-if(_30){
-_2b.push(_31);
-}
-}
-_29(_2b,_28);
-}else{
-if(_2c.length>0){
-_2b=_2c.slice(0,_2c.length);
-}
-_29(_2b,_28);
-}
-},getFeatures:function(){
-return {"dojo.data.api.Read":true,"dojo.data.api.Identity":true};
-},close:function(_32){
-},getLabel:function(_33){
-if(this.isItem(_33)){
-return "Table Row #"+this.getIdentity(_33);
-}
-return undefined;
-},getLabelAttributes:function(_34){
-return null;
-},getIdentity:function(_35){
-this._assertIsItem(_35);
-if(!dojo.isOpera){
-return _35.sectionRowIndex;
-}else{
-return (dojo.indexOf(this._rootNode.rows,_35)-1);
-}
-},getIdentityAttributes:function(_36){
-return null;
-},fetchItemByIdentity:function(_37){
-var _38=_37.identity;
-var _39=this;
-var _3a=null;
-var _3b=null;
-if(!this._rootNode){
-if(!this.url){
-this._rootNode=dojo.byId(this.tableId);
-this._getHeadings();
-for(var i=0;i<this._rootNode.rows.length;i++){
-this._rootNode.rows[i].store=this;
-}
-_3a=this._rootNode.rows[_38+1];
-if(_37.onItem){
-_3b=_37.scope?_37.scope:dojo.global;
-_37.onItem.call(_3b,_3a);
-}
-}else{
-var _3c={url:this.url,handleAs:"text"};
-var _3d=dojo.xhrGet(_3c);
-_3d.addCallback(function(_3e){
-var _3f=function(_40,id){
-if(_40.id==id){
-return _40;
-}
-if(_40.childNodes){
-for(var i=0;i<_40.childNodes.length;i++){
-var _41=_3f(_40.childNodes[i],id);
-if(_41){
-return _41;
-}
-}
-}
-return null;
-};
-var d=document.createElement("div");
-d.innerHTML=_3e;
-_39._rootNode=_3f(d,_39.tableId);
-_39._getHeadings.call(_39);
-for(var i=0;i<_39._rootNode.rows.length;i++){
-_39._rootNode.rows[i].store=_39;
-}
-_3a=_39._rootNode.rows[_38+1];
-if(_37.onItem){
-_3b=_37.scope?_37.scope:dojo.global;
-_37.onItem.call(_3b,_3a);
-}
-});
-_3d.addErrback(function(_42){
-if(_37.onError){
-_3b=_37.scope?_37.scope:dojo.global;
-_37.onError.call(_3b,_42);
-}
+
+dojo.declare("dojox.data.HtmlTableStore", null, {
+	constructor: function(/*Object*/args){
+		dojo.deprecated("dojox.data.HtmlTableStore", "Please use dojox.data.HtmlStore");
+		//	summary:
+		//		Initializer for the HTML table store.  
+		//	description:
+		//		The HtmlTableStore can be created in one of two ways: a) by parsing an existing
+		//		table DOM node on the current page or b) by referencing an external url and giving
+		//		the id of the table in that page.  The remote url will be parsed as an html page.
+		//
+		//		The HTML table should be of the following form:
+		//		<table id="myTable">
+		//			<thead>
+		//				<tr>
+		//					<th>Attribute1</th>
+		//					<th>Attribute2</th>
+		//				</tr>
+		//			</thead>
+		//			<tbody>
+		//				<tr>
+		//					<td>Value1.1</td>
+		//					<td>Value1.2</td>
+		//				</tr>
+		//				<tr>
+		//					<td>Value2.1</td>
+		//					<td>Value2.2</td>
+		//				</tr>
+		//			</tbody>
+		//		</table>
+		//
+		//	args:
+		//		An anonymous object to initialize properties.  It expects the following values:
+		//		tableId:	The id of the HTML table to use.
+		//		OR
+		//		url:		The url of the remote page to load
+		//		tableId:	The id of the table element in the remote page
+		
+		if(args.url){
+			if(!args.tableId)
+				throw new Error("dojo.data.HtmlTableStore: Cannot instantiate using url without an id!");
+			this.url = args.url;
+			this.tableId = args.tableId;
+		}else{
+			if(args.tableId){
+				this._rootNode = dojo.byId(args.tableId);
+				this.tableId = this._rootNode.id;
+			}else{
+				this._rootNode = dojo.byId(this.tableId);
+			}
+			this._getHeadings();
+			for(var i=0; i<this._rootNode.rows.length; i++){
+				this._rootNode.rows[i].store = this;
+			}
+		}
+	},
+
+	// url: [public] string
+	//		The URL from which to load an HTML document for data loading
+	url: "",
+	
+	// tableId: [public] string
+	//		The id of the table to load as store contents.
+	tableId: "",
+
+	_getHeadings: function(){
+		//	summary:
+		//		Function to load the attribute names from the table header so that the 
+		//		attributes (cells in a row), can have a reasonable name.
+		this._headings = [];
+		dojo.forEach(this._rootNode.tHead.rows[0].cells, dojo.hitch(this, function(th){
+			this._headings.push(dojox.xml.parser.textContent(th));
+		}));
+	},
+	
+	_getAllItems: function(){
+		//	summary:
+		//		Function to return all rows in the table as an array of items.
+		var items = [];
+		for(var i=1; i<this._rootNode.rows.length; i++){
+			items.push(this._rootNode.rows[i]);
+		}
+		return items; //array
+	},
+	
+	_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.HtmlTableStore: a function was passed an item argument that was not an item");
+		}
+	},
+
+	_assertIsAttribute: function(/* 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.
+		//
+		//	returns:
+		//		Returns the index (column) that the attribute resides in the row.
+		if(typeof attribute !== "string"){ 
+			throw new Error("dojo.data.HtmlTableStore: a function was passed an attribute argument that was not an attribute name string");
+			return -1;
+		}
+		return dojo.indexOf(this._headings, attribute); //int
+	},
+
+/***************************************
+     dojo.data.api.Read API
+***************************************/
+	
+	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; //Object || int || Boolean
+	},
+
+	getValues: function(/* item */ item, 
+						/* attribute-name-string */ attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.getValues()
+
+		this._assertIsItem(item);
+		var index = this._assertIsAttribute(attribute);
+
+		if(index>-1){
+			return [dojox.xml.parser.textContent(item.cells[index])] ;
+		}
+		return []; //Array
+	},
+
+	getAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getAttributes()
+		this._assertIsItem(item);
+		var attributes = [];
+		for(var i=0; i<this._headings.length; i++){
+			if(this.hasAttribute(item, this._headings[i]))
+				attributes.push(this._headings[i]);
+		}
+		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'
+		var values = this.getValues(item, attribute);
+		for(var i = 0; i < values.length; ++i){
+			var possibleValue = values[i];
+			if(typeof possibleValue === "string" && regexp){
+				return (possibleValue.match(regexp) !== null);
+			}else{
+				//Non-string matching.
+				if(value === possibleValue){
+					return true; // Boolean
+				}
+			}
+		}
+		return false; // Boolean
+	},
+
+	isItem: function(/* anything */ something){
+		//	summary: 
+		//		See dojo.data.api.Read.isItem()
+		if(something && something.store && something.store === this){
+			return true; //boolean
+		}
+		return false; //boolean
+	},
+
+	isItemLoaded: function(/* anything */ something){
+		//	summary: 
+		//		See dojo.data.api.Read.isItemLoaded()
+		return this.isItem(something);
+	},
+
+	loadItem: function(/* Object */ keywordArgs){
+		//	summary: 
+		//		See dojo.data.api.Read.loadItem()
+		this._assertIsItem(keywordArgs.item);
+	},
+	
+	_fetchItems: function(request, fetchHandler, errorHandler){
+		//	summary:
+		//		Fetch items (XML elements) that match to a query
+		//	description:
+		//		If '_fetchUrl' is specified, it is used to load an XML document
+		//		with a query string.
+		//		Otherwise and if 'url' is specified, the XML document is
+		//		loaded and list XML elements that match to a query (set of element
+		//		names and their text attribute values that the items to contain).
+		//		A wildcard, "*" can be used to query values to match all
+		//		occurrences.
+		//		If '_rootItem' is specified, it is used to fetch items.
+		//	request:
+		//		A request object
+		//	fetchHandler:
+		//		A function to call for fetched items
+		//	errorHandler:
+		//		A function to call on error
+		
+		if(this._rootNode){
+			this._finishFetchItems(request, fetchHandler, errorHandler);
+		}else{
+			if(!this.url){
+				this._rootNode = dojo.byId(this.tableId);
+				this._getHeadings();
+				for(var i=0; i<this._rootNode.rows.length; i++){
+					this._rootNode.rows[i].store = this;
+				}
+			}else{
+				var getArgs = {
+						url: this.url,
+						handleAs: "text"
+					};
+				var self = this;
+				var getHandler = dojo.xhrGet(getArgs);
+				getHandler.addCallback(function(data){
+					var findNode = function(node, id){
+						if(node.id == id){
+							return node; //object
+						}
+						if(node.childNodes){
+							for(var i=0; i<node.childNodes.length; i++){
+								var returnNode = findNode(node.childNodes[i], id);
+								if(returnNode){
+									return returnNode; //object
+								}
+							}
+						}
+						return null; //null
+					}
+
+					var d = document.createElement("div");
+					d.innerHTML = data;
+					self._rootNode = findNode(d, self.tableId);
+					self._getHeadings.call(self);
+					for(var i=0; i<self._rootNode.rows.length; i++){
+						self._rootNode.rows[i].store = self;
+					}
+					self._finishFetchItems(request, fetchHandler, errorHandler);
+				});
+				getHandler.addErrback(function(error){
+					errorHandler(error, request);
+				});
+			}
+		}
+	},
+	
+	_finishFetchItems: function(request, fetchHandler, errorHandler){
+		//	summary:
+		//		Internal function for processing the passed in request and locating the requested items.
+		var items = null;
+		var arrayOfAllItems = this._getAllItems();
+		if(request.query){
+			var ignoreCase = request.queryOptions ? request.queryOptions.ignoreCase : false; 
+			items = [];
+
+			//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 = {};
+			var value;
+			var key;
+			for(key in request.query){
+				value = request.query[key]+'';
+				if(typeof value === "string"){
+					regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
+				}
+			}
+
+			for(var i = 0; i < arrayOfAllItems.length; ++i){
+				var match = true;
+				var candidateItem = arrayOfAllItems[i];
+				for(key in request.query){
+					value = request.query[key]+'';
+					if(!this._containsValue(candidateItem, key, value, regexpList[key])){
+						match = false;
+					}
+				}
+				if(match){
+					items.push(candidateItem);
+				}
+			}
+			fetchHandler(items, request);
+		}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 listsand sort without affecting each other.
+			if(arrayOfAllItems.length> 0){
+				items = arrayOfAllItems.slice(0,arrayOfAllItems.length); 
+			}
+			fetchHandler(items, request);
+		}
+	},
+
+	getFeatures: function(){
+		//	summary: 
+		//		See dojo.data.api.Read.getFeatures()
+		return {
+			'dojo.data.api.Read': true,
+			'dojo.data.api.Identity': true
+		};
+	},
+	
+	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+		//	summary:
+		//		See dojo.data.api.Read.close()
+		// nothing to do here!
+	},
+
+	getLabel: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabel()
+		if(this.isItem(item))
+			return "Table Row #" + this.getIdentity(item);
+		return undefined;
+	},
+
+	getLabelAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabelAttributes()
+		return null;
+	},
+
+/***************************************
+     dojo.data.api.Identity API
+***************************************/
+
+	getIdentity: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Identity.getIdentity()
+		this._assertIsItem(item);
+		//Opera doesn't support the sectionRowIndex, 
+		//So, have to call the indexOf to locate it. 
+		//Blah.
+		if(!dojo.isOpera){
+			return item.sectionRowIndex; // int	
+		}else{
+			return (dojo.indexOf(this._rootNode.rows, item) - 1) // int
+		}
+	},
+
+	getIdentityAttributes: function(/* item */ item){
+		 //	summary: 
+		 //		See dojo.data.api.Identity.getIdentityAttributes()
+		 //Identity isn't taken from a public attribute.
+		 return null;
+	},
+
+	fetchItemByIdentity: function(keywordArgs){
+		//	summary: 
+		//		See dojo.data.api.Identity.fetchItemByIdentity()
+		var identity = keywordArgs.identity;
+		var self = this;
+		var item = null;
+		var scope = null;
+
+		if(!this._rootNode){
+			if(!this.url){
+				this._rootNode = dojo.byId(this.tableId);
+				this._getHeadings();
+				for(var i=0; i<this._rootNode.rows.length; i++){
+					this._rootNode.rows[i].store = this;
+				}
+				item = this._rootNode.rows[identity+1];
+				if(keywordArgs.onItem){
+					scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+					keywordArgs.onItem.call(scope, item);
+				}
+
+			}else{
+				var getArgs = {
+						url: this.url,
+						handleAs: "text"
+					};
+				var getHandler = dojo.xhrGet(getArgs);
+				getHandler.addCallback(function(data){
+					var findNode = function(node, id){
+						if(node.id == id){
+							return node; //object
+						}
+						if(node.childNodes){
+							for(var i=0; i<node.childNodes.length; i++){
+								var returnNode = findNode(node.childNodes[i], id);
+								if(returnNode){
+									return returnNode; //object
+								}
+							}
+						}
+						return null; //null
+					}
+					var d = document.createElement("div");
+					d.innerHTML = data;
+					self._rootNode = findNode(d, self.tableId);
+					self._getHeadings.call(self);
+					for(var i=0; i<self._rootNode.rows.length; i++){
+						self._rootNode.rows[i].store = self;
+					}
+					item = self._rootNode.rows[identity+1];
+					if(keywordArgs.onItem){
+						scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+						keywordArgs.onItem.call(scope, item);
+					}
+				});
+				getHandler.addErrback(function(error){
+					if(keywordArgs.onError){
+						scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+						keywordArgs.onError.call(scope, error);
+
+					}
+				});
+			}
+		}else{
+			if(this._rootNode.rows[identity+1]){
+				item = this._rootNode.rows[identity+1];
+				if(keywordArgs.onItem){
+					scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+					keywordArgs.onItem.call(scope, item);
+				}
+			}
+		}
+	}
 });
-}
-}else{
-if(this._rootNode.rows[_38+1]){
-_3a=this._rootNode.rows[_38+1];
-if(_37.onItem){
-_3b=_37.scope?_37.scope:dojo.global;
-_37.onItem.call(_3b,_3a);
-}
-}
-}
-}});
 dojo.extend(dojox.data.HtmlTableStore,dojo.data.util.simpleFetch);
-}
diff --git a/dojox/data/ItemExplorer.js b/dojox/data/ItemExplorer.js
index b4d54d4..667f160 100644
--- a/dojox/data/ItemExplorer.js
+++ b/dojox/data/ItemExplorer.js
@@ -1,12 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.ItemExplorer"]){
-dojo._hasResource["dojox.data.ItemExplorer"]=true;
 dojo.provide("dojox.data.ItemExplorer");
 dojo.require("dijit.Tree");
 dojo.require("dijit.Dialog");
@@ -16,446 +7,620 @@ dojo.require("dijit.form.Textarea");
 dojo.require("dijit.form.Button");
 dojo.require("dijit.form.CheckBox");
 dojo.require("dijit.form.FilteringSelect");
+
 (function(){
-var _1=function(_2,_3,_4){
-var _5=_2.getValues(_3,_4);
-if(_5.length<2){
-_5=_2.getValue(_3,_4);
-}
-return _5;
-};
-dojo.declare("dojox.data.ItemExplorer",dijit.Tree,{useSelect:false,refSelectSearchAttr:null,constructor:function(_6){
-dojo.mixin(this,_6);
-var _7=this;
-var _8={};
-var _9=this.rootModelNode={value:_8,id:"root"};
-this._modelNodeIdMap={};
-this._modelNodePropMap={};
-var _a=1;
-this.model={getRoot:function(_b){
-_b(_9);
-},mayHaveChildren:function(_c){
-return _c.value&&typeof _c.value=="object"&&!(_c.value instanceof Date);
-},getChildren:function(_d,_e,_f){
-var _10,_11,_12=_d.value;
-var _13=[];
-if(_12==_8){
-_e([]);
-return;
-}
-var _14=_7.store&&_7.store.isItem(_12,true);
-if(_14&&!_7.store.isItemLoaded(_12)){
-_7.store.loadItem({item:_12,onItem:function(_15){
-_12=_15;
-_16();
-}});
-}else{
-_16();
-}
-function _16(){
-if(_14){
-_10=_7.store.getAttributes(_12);
-_11=_12;
-}else{
-if(_12&&typeof _12=="object"){
-_11=_d.value;
-_10=[];
-for(var i in _12){
-if(_12.hasOwnProperty(i)&&i!="__id"&&i!="__clientId"){
-_10.push(i);
-}
-}
-}
-}
-if(_10){
-for(var key,k=0;key=_10[k++];){
-_13.push({property:key,value:_14?_1(_7.store,_12,key):_12[key],parent:_11});
-}
-_13.push({addNew:true,parent:_11,parentNode:_d});
-}
-_e(_13);
-};
-},getIdentity:function(_17){
-if(!_17.id){
-if(_17.addNew){
-_17.property="--addNew";
-}
-_17.id=_a++;
-if(_7.store){
-if(_7.store.isItem(_17.value)){
-var _18=_7.store.getIdentity(_17.value);
-(_7._modelNodeIdMap[_18]=_7._modelNodeIdMap[_18]||[]).push(_17);
-}
-if(_17.parent){
-_18=_7.store.getIdentity(_17.parent)+"."+_17.property;
-(_7._modelNodePropMap[_18]=_7._modelNodePropMap[_18]||[]).push(_17);
-}
-}
-}
-return _17.id;
-},getLabel:function(_19){
-return _19===_9?"Object Properties":_19.addNew?(_19.parent instanceof Array?"Add new value":"Add new property"):_19.property+": "+(_19.value instanceof Array?"("+_19.value.length+" elements)":_19.value);
-},onChildrenChange:function(_1a){
-},onChange:function(_1b){
-}};
-},postCreate:function(){
-this.inherited(arguments);
-dojo.connect(this,"onClick",function(_1c,_1d){
-this.lastFocused=_1d;
-if(_1c.addNew){
-this._addProperty();
-}else{
-this._editProperty();
-}
-});
-var _1e=new dijit.Menu({targetNodeIds:[this.rootNode.domNode],id:"contextMenu"});
-dojo.connect(_1e,"_openMyself",this,function(e){
-var _1f=dijit.getEnclosingWidget(e.target);
-if(_1f){
-var _20=_1f.item;
-if(this.store.isItem(_20.value,true)&&!_20.parent){
-_1e.getChildren().forEach(function(_21){
-_21.attr("disabled",(_21.label!="Add"));
-});
-this.lastFocused=_1f;
-}else{
-if(_20.value&&typeof _20.value=="object"&&!(_20.value instanceof Date)){
-_1e.getChildren().forEach(function(_22){
-_22.attr("disabled",(_22.label!="Add")&&(_22.label!="Delete"));
-});
-this.lastFocused=_1f;
-}else{
-if(_20.property&&dojo.indexOf(this.store.getIdentityAttributes(),_20.property)>=0){
-this.focusNode(_1f);
-alert("Cannot modify an Identifier node.");
-}else{
-if(_20.addNew){
-this.focusNode(_1f);
-}else{
-_1e.getChildren().forEach(function(_23){
-_23.attr("disabled",(_23.label!="Edit")&&(_23.label!="Delete"));
-});
-this.lastFocused=_1f;
-}
-}
-}
-}
-}
-});
-_1e.addChild(new dijit.MenuItem({label:"Add",onClick:dojo.hitch(this,"_addProperty")}));
-_1e.addChild(new dijit.MenuItem({label:"Edit",onClick:dojo.hitch(this,"_editProperty")}));
-_1e.addChild(new dijit.MenuItem({label:"Delete",onClick:dojo.hitch(this,"_destroyProperty")}));
-_1e.startup();
-},store:null,setStore:function(_24){
-this.store=_24;
-var _25=this;
-if(this._editDialog){
-this._editDialog.destroyRecursive();
-delete this._editDialog;
-}
-dojo.connect(_24,"onSet",function(_26,_27,_28,_29){
-var _2a,i,_2b=_25.store.getIdentity(_26);
-_2a=_25._modelNodeIdMap[_2b];
-if(_2a&&(_28===undefined||_29===undefined||_28 instanceof Array||_29 instanceof Array||typeof _28=="object"||typeof _29=="object")){
-for(i=0;i<_2a.length;i++){
-(function(_2c){
-_25.model.getChildren(_2c,function(_2d){
-_25.model.onChildrenChange(_2c,_2d);
-});
-})(_2a[i]);
-}
-}
-_2a=_25._modelNodePropMap[_2b+"."+_27];
-if(_2a){
-for(i=0;i<_2a.length;i++){
-_2a[i].value=_29;
-_25.model.onChange(_2a[i]);
-}
-}
-});
-this.rootNode.setChildItems([]);
-},setItem:function(_2e){
-(this._modelNodeIdMap={})[this.store.getIdentity(_2e)]=[this.rootModelNode];
-this._modelNodePropMap={};
-this.rootModelNode.value=_2e;
-var _2f=this;
-this.model.getChildren(this.rootModelNode,function(_30){
-_2f.rootNode.setChildItems(_30);
-});
-},refreshItem:function(){
-this.setItem(this.rootModelNode.value);
-},_createEditDialog:function(){
-this._editDialog=new dijit.Dialog({title:"Edit Property",execute:dojo.hitch(this,"_updateItem"),preload:true});
-this._editDialog.placeAt(dojo.body());
-this._editDialog.startup();
-var _31=dojo.doc.createElement("div");
-var _32=dojo.doc.createElement("label");
-dojo.attr(_32,"for","property");
-dojo.style(_32,"fontWeight","bold");
-dojo.attr(_32,"innerHTML","Property:");
-_31.appendChild(_32);
-var _33=new dijit.form.ValidationTextBox({name:"property",value:"",required:true,disabled:true}).placeAt(_31);
-_31.appendChild(dojo.doc.createElement("br"));
-_31.appendChild(dojo.doc.createElement("br"));
-var _34=new dijit.form.RadioButton({name:"itemType",value:"value",onClick:dojo.hitch(this,function(){
-this._enableFields("value");
-})}).placeAt(_31);
-var _35=dojo.doc.createElement("label");
-dojo.attr(_35,"for","value");
-dojo.attr(_35,"innerHTML","Value (JSON):");
-_31.appendChild(_35);
-var _36=dojo.doc.createElement("div");
-dojo.addClass(_36,"value");
-var _37=new dijit.form.Textarea({name:"jsonVal"}).placeAt(_36);
-_31.appendChild(_36);
-var _38=new dijit.form.RadioButton({name:"itemType",value:"reference",onClick:dojo.hitch(this,function(){
-this._enableFields("reference");
-})}).placeAt(_31);
-var _39=dojo.doc.createElement("label");
-dojo.attr(_39,"for","_reference");
-dojo.attr(_39,"innerHTML","Reference (ID):");
-_31.appendChild(_39);
-_31.appendChild(dojo.doc.createElement("br"));
-var _3a=dojo.doc.createElement("div");
-dojo.addClass(_3a,"reference");
-if(this.useSelect){
-var _3b=new dijit.form.FilteringSelect({name:"_reference",store:this.store,searchAttr:this.refSelectSearchAttr||this.store.getIdentityAttributes()[0],required:false,value:null,pageSize:10}).placeAt(_3a);
-}else{
-var _3c=new dijit.form.ValidationTextBox({name:"_reference",value:"",promptMessage:"Enter the ID of the item to reference",isValid:dojo.hitch(this,function(_3d){
-return true;
-})}).placeAt(_3a);
-}
-_31.appendChild(_3a);
-_31.appendChild(dojo.doc.createElement("br"));
-_31.appendChild(dojo.doc.createElement("br"));
-var _3e=document.createElement("div");
-_3e.setAttribute("dir","rtl");
-var _3f=new dijit.form.Button({type:"reset",label:"Cancel"}).placeAt(_3e);
-_3f.onClick=dojo.hitch(this._editDialog,"onCancel");
-var _40=new dijit.form.Button({type:"submit",label:"OK"}).placeAt(_3e);
-_31.appendChild(_3e);
-this._editDialog.attr("content",_31);
-},_enableFields:function(_41){
-switch(_41){
-case "reference":
-dojo.query(".value [widgetId]",this._editDialog.containerNode).forEach(function(_42){
-dijit.getEnclosingWidget(_42).attr("disabled",true);
-});
-dojo.query(".reference [widgetId]",this._editDialog.containerNode).forEach(function(_43){
-dijit.getEnclosingWidget(_43).attr("disabled",false);
-});
-break;
-case "value":
-dojo.query(".value [widgetId]",this._editDialog.containerNode).forEach(function(_44){
-dijit.getEnclosingWidget(_44).attr("disabled",false);
-});
-dojo.query(".reference [widgetId]",this._editDialog.containerNode).forEach(function(_45){
-dijit.getEnclosingWidget(_45).attr("disabled",true);
-});
-break;
-}
-},_updateItem:function(_46){
-var _47,_48,val,_49,_4a=this._editDialog.attr("title")=="Edit Property";
-var _4b=this._editDialog;
-var _4c=this.store;
-function _4d(){
-try{
-var _4e,_4f=[];
-var _50=_46.property;
-if(_4a){
-while(!_4c.isItem(_48.parent,true)){
-_47=_47.getParent();
-_4f.push(_48.property);
-_48=_47.item;
-}
-if(_4f.length==0){
-_4c.setValue(_48.parent,_48.property,val);
-}else{
-_49=_1(_4c,_48.parent,_48.property);
-if(_49 instanceof Array){
-_49=_49.concat();
-}
-_4e=_49;
-while(_4f.length>1){
-_4e=_4e[_4f.pop()];
-}
-_4e[_4f]=val;
-_4c.setValue(_48.parent,_48.property,_49);
-}
-}else{
-if(_4c.isItem(_51,true)){
-if(!_4c.isItemLoaded(_51)){
-_4c.loadItem({item:_51,onItem:function(_52){
-if(_52 instanceof Array){
-_50=_52.length;
-}
-_4c.setValue(_52,_50,val);
-}});
-}else{
-if(_51 instanceof Array){
-_50=_51.length;
-}
-_4c.setValue(_51,_50,val);
-}
-}else{
-if(_48.value instanceof Array){
-_4f.push(_48.value.length);
-}else{
-_4f.push(_46.property);
-}
-while(!_4c.isItem(_48.parent,true)){
-_47=_47.getParent();
-_4f.push(_48.property);
-_48=_47.item;
-}
-_49=_1(_4c,_48.parent,_48.property);
-_4e=_49;
-while(_4f.length>1){
-_4e=_4e[_4f.pop()];
-}
-_4e[_4f]=val;
-_4c.setValue(_48.parent,_48.property,_49);
-}
-}
-}
-catch(e){
-alert(e);
-}
-};
-if(_4b.validate()){
-_47=this.lastFocused;
-_48=_47.item;
-var _51=_48.value;
-if(_48.addNew){
-_51=_47.item.parent;
-_47=_47.getParent();
-_48=_47.item;
-}
-val=null;
-switch(_46.itemType){
-case "reference":
-this.store.fetchItemByIdentity({identity:_46._reference,onItem:function(_53){
-val=_53;
-_4d();
-},onError:function(){
-alert("The id could not be found");
-}});
-break;
-case "value":
-var _54=_46.jsonVal;
-val=dojo.fromJson(_54);
-if(typeof val=="function"){
-val.toString=function(){
-return _54;
-};
-}
-_4d();
-break;
-}
-}else{
-_4b.show();
-}
-},_editProperty:function(){
-var _55=dojo.mixin({},this.lastFocused.item);
-if(!this._editDialog){
-this._createEditDialog();
-}else{
-this._editDialog.reset();
-}
-if(dojo.indexOf(this.store.getIdentityAttributes(),_55.property)>=0){
-alert("Cannot Edit an Identifier!");
-}else{
-this._editDialog.attr("title","Edit Property");
-dijit.getEnclosingWidget(dojo.query("input",this._editDialog.containerNode)[0]).attr("disabled",true);
-if(this.store.isItem(_55.value,true)){
-if(_55.parent){
-_55.itemType="reference";
-this._enableFields(_55.itemType);
-_55._reference=this.store.getIdentity(_55.value);
-this._editDialog.attr("value",_55);
-this._editDialog.show();
-}
-}else{
-if(_55.value&&typeof _55.value=="object"&&!(_55.value instanceof Date)){
-}else{
-_55.itemType="value";
-this._enableFields(_55.itemType);
-_55.jsonVal=typeof _55.value=="function"?_55.value.toString():_55.value instanceof Date?"new Date(\""+_55.value+"\")":dojo.toJson(_55.value);
-this._editDialog.attr("value",_55);
-this._editDialog.show();
-}
-}
-}
-},_destroyProperty:function(){
-var _56=this.lastFocused;
-var _57=_56.item;
-var _58=[];
-while(!this.store.isItem(_57.parent,true)||_57.parent instanceof Array){
-_56=_56.getParent();
-_58.push(_57.property);
-_57=_56.item;
-}
-if(dojo.indexOf(this.store.getIdentityAttributes(),_57.property)>=0){
-alert("Cannot Delete an Identifier!");
-}else{
-try{
-if(_58.length>0){
-var _59,_5a=_1(this.store,_57.parent,_57.property);
-_59=_5a;
-while(_58.length>1){
-_59=_59[_58.pop()];
-}
-if(dojo.isArray(_59)){
-_59.splice(_58,1);
-}else{
-delete _59[_58];
-}
-this.store.setValue(_57.parent,_57.property,_5a);
-}else{
-this.store.unsetAttribute(_57.parent,_57.property);
-}
-}
-catch(e){
-alert(e);
-}
-}
-},_addProperty:function(){
-var _5b=this.lastFocused.item;
-var _5c=_5b.value;
-var _5d=dojo.hitch(this,function(){
-var _5e=null;
-if(!this._editDialog){
-this._createEditDialog();
-}else{
-this._editDialog.reset();
-}
-if(_5c instanceof Array){
-_5e=_5c.length;
-dijit.getEnclosingWidget(dojo.query("input",this._editDialog.containerNode)[0]).attr("disabled",true);
-}else{
-dijit.getEnclosingWidget(dojo.query("input",this._editDialog.containerNode)[0]).attr("disabled",false);
-}
-this._editDialog.attr("title","Add Property");
-this._enableFields("value");
-this._editDialog.attr("value",{itemType:"value",property:_5e});
-this._editDialog.show();
+	var getValue = function(store, item, prop){
+		var value = store.getValues(item, prop);
+		if(value.length < 2){
+			value = store.getValue(item, prop);
+		}
+		return value;
+	}
+
+dojo.declare("dojox.data.ItemExplorer", dijit.Tree, {
+	useSelect: false,
+	refSelectSearchAttr: null,
+	constructor: function(options){
+		dojo.mixin(this, options);
+		var self = this;
+		var initialRootValue = {};
+		var root = this.rootModelNode = {value:initialRootValue,id:"root"};
+
+		this._modelNodeIdMap = {};
+		this._modelNodePropMap = {};
+		var nextId = 1;
+		this.model = {
+			getRoot: function(onItem){
+				onItem(root);
+			},
+			mayHaveChildren: function(modelNode){
+				return modelNode.value && typeof modelNode.value == 'object' && !(modelNode.value instanceof Date);
+			},
+			getChildren: function(parentModelNode, onComplete, onError){
+				var keys, parent, item = parentModelNode.value;
+				var children = [];
+				if(item == initialRootValue){
+					onComplete([]);
+					return;
+				}
+				var isItem = self.store && self.store.isItem(item, true);
+				if(isItem && !self.store.isItemLoaded(item)){
+					// if it is not loaded, do so now.
+					self.store.loadItem({
+						item:item,
+						onItem:function(loadedItem){
+							item = loadedItem;
+							enumerate();
+						}
+					});
+				}else{
+					enumerate();
+				}
+				function enumerate(){
+					// once loaded, enumerate the keys
+					if(isItem){
+						// get the properties through the dojo data API
+						keys = self.store.getAttributes(item);
+						parent = item;
+					}else if(item && typeof item == 'object'){
+						parent = parentModelNode.value;
+						keys = [];
+						// also we want to be able to drill down into plain JS objects/arrays
+						for(var i in item){
+							if(item.hasOwnProperty(i) && i != '__id' && i != '__clientId'){
+								keys.push(i);
+							}
+						}
+					}
+					if(keys){
+						for(var key, k=0; key = keys[k++];){
+							children.push({
+								property:key,
+								value: isItem ? getValue(self.store, item, key) : item[key],
+								parent:	parent});
+						}
+						children.push({addNew:true, parent: parent, parentNode : parentModelNode});
+					}
+					onComplete(children);
+				}
+			},
+			getIdentity: function(modelNode){
+				if(!modelNode.id){
+					if(modelNode.addNew){
+						modelNode.property = "--addNew";
+					}
+					modelNode.id = nextId++;
+					if(self.store){
+						if(self.store.isItem(modelNode.value)){
+							var identity = self.store.getIdentity(modelNode.value);
+							(self._modelNodeIdMap[identity] = self._modelNodeIdMap[identity] || []).push(modelNode);
+						}
+						if(modelNode.parent){
+							identity = self.store.getIdentity(modelNode.parent) + '.' + modelNode.property;
+							(self._modelNodePropMap[identity] = self._modelNodePropMap[identity] || []).push(modelNode);
+						}
+					}
+				}
+				return modelNode.id;
+			},
+			getLabel: function(modelNode){
+				return modelNode === root ?
+						"Object Properties" :
+							modelNode.addNew ? (modelNode.parent instanceof Array ? "Add new value" : "Add new property") :
+								modelNode.property + ": " +
+									(modelNode.value instanceof Array ? "(" + modelNode.value.length + " elements)" : modelNode.value);
+			},
+			onChildrenChange: function(modelNode){
+			},
+			onChange: function(modelNode){
+			}
+		};
+	},
+	postCreate: function(){
+		this.inherited(arguments);
+		// handle the clicking on the "add new property item"
+		dojo.connect(this, "onClick", function(modelNode, treeNode){
+			this.lastFocused = treeNode;
+			if(modelNode.addNew){
+				//this.focusNode(treeNode.getParent());
+				this._addProperty();
+			}else{
+				this._editProperty();
+			}
+		});
+		var contextMenu = new dijit.Menu({
+			targetNodeIds: [this.rootNode.domNode],
+			id: "contextMenu"
+			});
+		dojo.connect(contextMenu, "_openMyself", this, function(e){
+			var node = dijit.getEnclosingWidget(e.target);
+			if(node){
+				var item = node.item;
+				if(this.store.isItem(item.value, true) && !item.parent){
+					dojo.forEach(contextMenu.getChildren(), function(widget){
+						widget.attr("disabled", (widget.label != "Add"));
+					});
+					this.lastFocused = node;
+					// TODO: Root Node - allow Edit when mutli-value editing is possible
+				}else if(item.value && typeof item.value == 'object' && !(item.value instanceof Date)){
+					// an object that's not a Date - could be a store item
+					dojo.forEach(contextMenu.getChildren(), function(widget){
+						widget.attr("disabled", (widget.label != "Add") && (widget.label != "Delete"));
+					});
+					this.lastFocused = node;
+					// TODO: Object - allow Edit when mutli-value editing is possible
+				}else if(item.property && dojo.indexOf(this.store.getIdentityAttributes(), item.property) >= 0){ // id node
+					this.focusNode(node);
+					alert("Cannot modify an Identifier node.");
+				}else if(item.addNew){
+					this.focusNode(node);
+				}else{
+					dojo.forEach(contextMenu.getChildren(), function(widget){
+						widget.attr("disabled", (widget.label != "Edit") && (widget.label != "Delete"));
+					})
+					// this won't focus the node but gives us a way to reference the node
+					this.lastFocused = node;
+				}
+			}
+		});
+		contextMenu.addChild(new dijit.MenuItem({label: "Add", onClick: dojo.hitch(this, "_addProperty")}));
+		contextMenu.addChild(new dijit.MenuItem({label: "Edit", onClick: dojo.hitch(this, "_editProperty")}));
+		contextMenu.addChild(new dijit.MenuItem({label: "Delete", onClick: dojo.hitch(this, "_destroyProperty")}));
+		contextMenu.startup();
+	},
+	store: null,
+	setStore: function(store){
+		this.store = store;
+		var self = this;
+		if(this._editDialog){
+			this._editDialog.destroyRecursive();
+			delete this._editDialog;
+		}
+		// i think we should just destroy this._editDialog and let _createEditDialog take care of everything
+		// once it gets called again by either _editProperty or _addProperty - it will create everything again
+		// using the new store.	this way we don't need to keep track of what is in the dialog if we change it.
+		/*if(this._editDialog && this.useSelect){
+			dojo.query(".reference [widgetId]", this._editDialog.containerNode).forEach(function(node){
+				dijit.getEnclosingWidget(node).attr("store", store);
+			});
+		}*/
+		dojo.connect(store, "onSet", function(item, attribute, oldValue, newValue){
+			var nodes, i, identity = self.store.getIdentity(item);
+			nodes = self._modelNodeIdMap[identity];
+
+			if(nodes &&
+					(oldValue === undefined || newValue === undefined ||
+					oldValue instanceof Array || newValue instanceof Array || typeof oldValue == 'object' || typeof newValue == 'object')){
+				for(i = 0; i < nodes.length; i++){
+					(function(node){
+						self.model.getChildren(node, function(children){
+							self.model.onChildrenChange(node, children);
+						});
+					})(nodes[i]);
+				}
+			}
+			nodes = self._modelNodePropMap[identity + "." + attribute];
+
+			if(nodes){
+				for(i = 0; i < nodes.length; i++){
+					nodes[i].value = newValue;
+					self.model.onChange(nodes[i]);
+				}
+			}
+		});
+		this.rootNode.setChildItems([]);
+	},
+	setItem: function(item){
+		// this is called to show a different item
+
+		// reset the maps, for the root getIdentity is not called, so we pre-initialize it here
+		(this._modelNodeIdMap = {})[this.store.getIdentity(item)] = [this.rootModelNode];
+		this._modelNodePropMap = {};
+
+		this.rootModelNode.value = item;
+		var self = this;
+		this.model.getChildren(this.rootModelNode, function(children){
+			self.rootNode.setChildItems(children);
+		});
+
+	},
+	refreshItem: function(){
+		this.setItem(this.rootModelNode.value);
+	},
+	_createEditDialog: function(){
+		this._editDialog = new dijit.Dialog({
+			 title: "Edit Property",
+			 execute: dojo.hitch(this, "_updateItem"),
+			 preload: true
+		});
+		this._editDialog.placeAt(dojo.body());
+		this._editDialog.startup();
+
+		// handle for dialog content
+		var pane = dojo.doc.createElement('div');
+
+		// label for property
+		var labelProp = dojo.doc.createElement('label');
+		dojo.attr(labelProp, "for", "property");
+		dojo.style(labelProp, "fontWeight", "bold");
+		dojo.attr(labelProp, "innerHTML", "Property:")
+		pane.appendChild(labelProp);
+
+		// property name field
+		var propName = new dijit.form.ValidationTextBox({
+			name: "property",
+			value: "",
+			required: true,
+			disabled: true
+		}).placeAt(pane);
+
+		pane.appendChild(dojo.doc.createElement("br"));
+		pane.appendChild(dojo.doc.createElement("br"));
+
+		// radio button for "value"
+		var value = new dijit.form.RadioButton({
+			name: "itemType",
+			value: "value",
+			onClick: dojo.hitch(this, function(){this._enableFields("value");})
+		}).placeAt(pane);
+
+		// label for value
+		var labelVal = dojo.doc.createElement('label');
+		dojo.attr(labelVal, "for", "value");
+		dojo.attr(labelVal, "innerHTML", "Value (JSON):")
+		pane.appendChild(labelVal);
+
+		 // container for value fields
+		var valueDiv = dojo.doc.createElement("div");
+		dojo.addClass(valueDiv, "value");
+
+		// textarea
+		var textarea = new dijit.form.Textarea({
+			name: "jsonVal"
+		}).placeAt(valueDiv);
+		pane.appendChild(valueDiv);
+
+		// radio button for "reference"
+		var reference = new dijit.form.RadioButton({
+			name: "itemType",
+			value: "reference",
+			onClick: dojo.hitch(this, function(){this._enableFields("reference");})
+		}).placeAt(pane);
+
+		// label for reference
+		var labelRef = dojo.doc.createElement('label');
+		dojo.attr(labelRef, "for", "_reference");
+		dojo.attr(labelRef, "innerHTML", "Reference (ID):")
+		pane.appendChild(labelRef);
+		pane.appendChild(dojo.doc.createElement("br"));
+
+		// container for reference fields
+		var refDiv = dojo.doc.createElement("div");
+		dojo.addClass(refDiv, "reference");
+
+		if(this.useSelect){
+			// filteringselect
+			// TODO: see if there is a way to sort the items in this list
+			var refSelect = new dijit.form.FilteringSelect({
+				name: "_reference",
+				store: this.store,
+				searchAttr: this.refSelectSearchAttr || this.store.getIdentityAttributes()[0],
+				required: false,
+				value: null,		// need to file a ticket about the fetch that happens when declared with value: null
+				pageSize: 10
+			}).placeAt(refDiv);
+		}else{
+			var refTextbox = new dijit.form.ValidationTextBox({
+				name: "_reference",
+				value: "",
+				promptMessage: "Enter the ID of the item to reference",
+				isValid: dojo.hitch(this, function(isFocused){
+					// don't validate while it's focused
+					return true;//isFocused || this.store.getItemByIdentity(this._editDialog.attr("value")._reference);
+				})
+			}).placeAt(refDiv);
+		}
+		pane.appendChild(refDiv);
+		pane.appendChild(dojo.doc.createElement("br"));
+		pane.appendChild(dojo.doc.createElement("br"));
+
+		// buttons
+		var buttons = document.createElement('div');
+		buttons.setAttribute("dir", "rtl");
+		var cancelButton = new dijit.form.Button({type: "reset", label: "Cancel"}).placeAt(buttons);
+		cancelButton.onClick = dojo.hitch(this._editDialog, "onCancel");
+		var okButton = new dijit.form.Button({type: "submit", label: "OK"}).placeAt(buttons);
+		pane.appendChild(buttons);
+
+		this._editDialog.attr("content", pane);
+	},
+	_enableFields: function(selection){
+		// enables/disables fields based on whether the value in this._editDialog is a reference or a primitive value
+		switch(selection){
+			case "reference":
+				dojo.query(".value [widgetId]", this._editDialog.containerNode).forEach(function(node){
+					dijit.getEnclosingWidget(node).attr("disabled", true);
+				});
+				dojo.query(".reference [widgetId]", this._editDialog.containerNode).forEach(function(node){
+					dijit.getEnclosingWidget(node).attr("disabled", false);
+				});
+				break;
+			case "value":
+				dojo.query(".value [widgetId]", this._editDialog.containerNode).forEach(function(node){
+					dijit.getEnclosingWidget(node).attr("disabled", false);
+				});
+				dojo.query(".reference [widgetId]", this._editDialog.containerNode).forEach(function(node){
+					dijit.getEnclosingWidget(node).attr("disabled", true);
+				});
+				break;
+		}
+	},
+	_updateItem: function(vals){
+		// a single "execute" function that handles adding and editing of values and references.
+		var node, item, val, storeItemVal, editingItem = this._editDialog.attr("title") == "Edit Property";
+		var editDialog = this._editDialog;
+		var store = this.store;
+		function setValue(){
+			try{
+				var itemVal, propPath = [];
+				var prop = vals.property;
+				if(editingItem){
+					while(!store.isItem(item.parent, true)){
+						node = node.getParent();
+						propPath.push(item.property);
+						item = node.item;
+					}
+					if(propPath.length == 0){
+						// working with an item attribute already
+						store.setValue(item.parent, item.property, val);
+					}else{
+						// need to walk back down the item property to the object
+						storeItemVal = getValue(store, item.parent, item.property);
+						if(storeItemVal instanceof Array){
+							// create a copy for modification
+							storeItemVal = storeItemVal.concat();
+						}
+						itemVal = storeItemVal;
+						while(propPath.length > 1){
+							itemVal = itemVal[propPath.pop()];
+						}
+						itemVal[propPath] = val; // this change is reflected in storeItemVal as well
+						store.setValue(item.parent, item.property, storeItemVal);
+					}
+				}else{
+					// adding a property
+					if(store.isItem(value, true)){
+						// adding a top-level property to an item
+						if(!store.isItemLoaded(value)){
+							// fetch the value and see if it is an array
+							store.loadItem({
+								item: value,
+								onItem: function(loadedItem){
+									if(loadedItem instanceof Array){
+										prop = loadedItem.length;
+									}
+									store.setValue(loadedItem, prop, val);
+								}
+							});
+						}else{
+							if(value instanceof Array){
+								prop = value.length;
+							}
+							store.setValue(value, prop, val);
+						}
+					}else{
+						// adding a property to a lower level in an item
+						if(item.value instanceof Array){
+							propPath.push(item.value.length);
+						}else{
+							propPath.push(vals.property);
+						}
+						while(!store.isItem(item.parent, true)){
+							node = node.getParent();
+							propPath.push(item.property);
+							item = node.item;
+						}
+						storeItemVal = getValue(store, item.parent, item.property);
+						itemVal = storeItemVal;
+						while(propPath.length > 1){
+							itemVal = itemVal[propPath.pop()];
+						}
+						itemVal[propPath] = val;
+						store.setValue(item.parent, item.property, storeItemVal);
+					}
+				}
+			}catch(e){
+				alert(e);
+			}
+		}
+
+		if(editDialog.validate()){
+			node = this.lastFocused;
+			item = node.item;
+			var value = item.value;
+			// var property = null;
+			if(item.addNew){
+				// we are adding a property to the parent item
+				// the real value of the parent is in the parent property of the lastFocused item
+				// this.lastFocused.getParent().item.value may be a reference to an item
+				value = node.item.parent;
+				node = node.getParent();
+				item = node.item;
+			}
+			val = null;
+			switch(vals.itemType){
+				case "reference":
+					this.store.fetchItemByIdentity({identity:vals._reference,
+						onItem:function(item){
+							val = item;
+							setValue();
+						},
+						onError:function(){
+							alert("The id could not be found");
+						}
+					});
+					break;
+				case "value":
+					var jsonVal = vals.jsonVal;
+					val = dojo.fromJson(jsonVal);
+					// ifit is a function we want to preserve the source (comments, et al)
+					if(typeof val == 'function'){
+						val.toString = function(){
+							return jsonVal;
+						}
+					}
+					setValue();
+					break;
+			}
+		}else{
+			// the form didn't validate - show it again.
+			editDialog.show();
+		}
+	},
+	_editProperty: function(){
+		// this mixin stops us polluting the tree item with jsonVal etc.
+		// FIXME: if a store identifies items by instanceof checks, this will fail
+		var item = dojo.mixin({}, this.lastFocused.item);
+		// create the dialog or reset it if it already exists
+		if(!this._editDialog){
+			this._createEditDialog();
+		}else{
+			this._editDialog.reset();
+		}
+		// not allowed to edit an item's id - so check for that and stop it.
+		if(dojo.indexOf(this.store.getIdentityAttributes(), item.property) >= 0){
+			alert("Cannot Edit an Identifier!");
+		}else{
+			this._editDialog.attr("title", "Edit Property");
+			// make sure the property input is disabled
+			dijit.getEnclosingWidget(dojo.query("input", this._editDialog.containerNode)[0]).attr("disabled", true);
+			if(this.store.isItem(item.value, true)){
+				// root node || Item reference
+				if(item.parent){
+					// Item reference
+					item.itemType = "reference";
+					this._enableFields(item.itemType);
+					item._reference = this.store.getIdentity(item.value);
+					this._editDialog.attr("value", item);
+					this._editDialog.show();
+				} // else root node
+			}else{
+				if(item.value && typeof item.value == 'object' && !(item.value instanceof Date)){
+					// item.value is an object but it's NOT an item from the store - no-op
+					// only allow editing on a property not on the node that represents the object/array
+				}else{
+					// this is a primitive
+					item.itemType = "value";
+					this._enableFields(item.itemType);
+					item.jsonVal = typeof item.value == 'function' ?
+							// use the plain toString for functions, dojo.toJson doesn't support functions
+							item.value.toString() :
+								item.value instanceof Date ?
+									// A json-ish form of a date:
+									'new Date("' + item.value + '")' :
+									dojo.toJson(item.value);
+					this._editDialog.attr("value", item);
+					this._editDialog.show();
+				}
+			}
+		}
+	},
+	_destroyProperty: function(){
+		var node = this.lastFocused;
+		var item = node.item;
+		var propPath = [];
+		// we have to walk up the tree to the item before we can know if we're working with the identifier
+		while(!this.store.isItem(item.parent, true) || item.parent instanceof Array){
+			node = node.getParent();
+			propPath.push(item.property);
+			item = node.item;
+		}
+		// this will prevent any part of the identifier from being changed
+		if(dojo.indexOf(this.store.getIdentityAttributes(), item.property) >= 0){
+			alert("Cannot Delete an Identifier!");
+		}else{
+			try{
+				if(propPath.length > 0){
+					// not deleting a top-level property of an item so get the top-level store item to change
+					var itemVal, storeItemVal = getValue(this.store, item.parent, item.property);
+					itemVal = storeItemVal;
+					// walk back down the object if needed
+					while(propPath.length > 1){
+						itemVal = itemVal[propPath.pop()];
+					}
+					// delete the property
+					if(dojo.isArray(itemVal)){
+						// the value being deleted represents an array element
+						itemVal.splice(propPath, 1);
+					}else{
+						// object property
+						delete itemVal[propPath];
+					}
+					// save it back to the store
+					this.store.setValue(item.parent, item.property, storeItemVal);
+				}else{
+					// deleting an item property
+					this.store.unsetAttribute(item.parent, item.property);
+				}
+			}catch(e){
+				alert(e);
+			}
+		}
+	},
+	_addProperty: function(){
+		// item is what we are adding a property to
+		var item = this.lastFocused.item;
+		// value is the real value of the item - not a reference to a store item
+		var value = item.value;
+		var showDialog = dojo.hitch(this, function(){
+			var property = null;
+			if(!this._editDialog){
+				this._createEditDialog();
+			}else{
+				this._editDialog.reset();
+			}
+			// are we adding another item to an array?
+			if(value instanceof Array){
+				// preset the property to the next index in the array and disable the property field
+				property = value.length;
+				dijit.getEnclosingWidget(dojo.query("input", this._editDialog.containerNode)[0]).attr("disabled", true);
+			}else{
+				// enable the property TextBox
+				dijit.getEnclosingWidget(dojo.query("input", this._editDialog.containerNode)[0]).attr("disabled", false);
+			}
+			this._editDialog.attr("title", "Add Property");
+			// default to a value type
+			this._enableFields("value");
+			this._editDialog.attr("value", {itemType: "value", property: property});
+			this._editDialog.show();
+		});
+
+		if(item.addNew){
+			// we are adding a property to the parent item
+			item = this.lastFocused.getParent().item;
+			// the real value of the parent is in the parent property of the lastFocused item
+			// this.lastFocused.getParent().item.value may be a reference to an item
+			value = this.lastFocused.item.parent;
+		}
+		if(item.property && dojo.indexOf(this.store.getIdentityAttributes(), item.property) >= 0){
+			alert("Cannot add properties to an ID node!");
+		}else{
+			// ifthe value is an item then we need to get the item's value
+			if(this.store.isItem(value, true) && !this.store.isItemLoaded(value)){
+				// fetch the value and see if it is an array
+				this.store.loadItem({
+					item: value,
+					onItem: function(loadedItem){
+						value = loadedItem;
+						showDialog();
+					}
+				});
+			}else{
+				showDialog();
+			}
+//
+		}
+	}
 });
-if(_5b.addNew){
-_5b=this.lastFocused.getParent().item;
-_5c=this.lastFocused.item.parent;
-}
-if(_5b.property&&dojo.indexOf(this.store.getIdentityAttributes(),_5b.property)>=0){
-alert("Cannot add properties to an ID node!");
-}else{
-if(this.store.isItem(_5c,true)&&!this.store.isItemLoaded(_5c)){
-this.store.loadItem({item:_5c,onItem:function(_5f){
-_5c=_5f;
-_5d();
-}});
-}else{
-_5d();
-}
-}
-}});
 })();
-}
+
diff --git a/dojox/data/JsonQueryRestStore.js b/dojox/data/JsonQueryRestStore.js
index 9a96ef1..799767d 100644
--- a/dojox/data/JsonQueryRestStore.js
+++ b/dojox/data/JsonQueryRestStore.js
@@ -1,17 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.JsonQueryRestStore"]){
-dojo._hasResource["dojox.data.JsonQueryRestStore"]=true;
 dojo.provide("dojox.data.JsonQueryRestStore");
 dojo.require("dojox.data.JsonRestStore");
 dojo.require("dojox.data.util.JsonQuery");
-dojo.requireIf(!!dojox.data.ClientFilter,"dojox.json.query");
-dojo.declare("dojox.data.JsonQueryRestStore",[dojox.data.JsonRestStore,dojox.data.util.JsonQuery],{matchesQuery:function(_1,_2){
-return _1.__id&&(_1.__id.indexOf("#")==-1)&&this.inherited(arguments);
-}});
-}
+
+dojo.requireIf(!!dojox.data.ClientFilter,"dojox.json.query"); // this is so we can perform queries locally 
+
+// this is an extension of JsonRestStore to convert object attribute queries to 
+// JSONQuery/JSONPath syntax to be sent to the server. This also enables
+//	JSONQuery/JSONPath queries to be performed locally if dojox.data.ClientFilter
+//	has been loaded
+dojo.declare("dojox.data.JsonQueryRestStore",[dojox.data.JsonRestStore,dojox.data.util.JsonQuery],{
+	matchesQuery: function(item,request){
+		return item.__id && (item.__id.indexOf("#") == -1) && this.inherited(arguments);
+	}
+});
diff --git a/dojox/data/JsonRestStore.js b/dojox/data/JsonRestStore.js
index c215b10..0f7f921 100644
--- a/dojox/data/JsonRestStore.js
+++ b/dojox/data/JsonRestStore.js
@@ -1,232 +1,482 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.JsonRestStore"]){
-dojo._hasResource["dojox.data.JsonRestStore"]=true;
 dojo.provide("dojox.data.JsonRestStore");
+
 dojo.require("dojox.data.ServiceStore");
 dojo.require("dojox.rpc.JsonRest");
-dojo.declare("dojox.data.JsonRestStore",dojox.data.ServiceStore,{constructor:function(_1){
-dojo.connect(dojox.rpc.Rest._index,"onUpdate",this,function(_2,_3,_4,_5){
-var _6=this.service.servicePath;
-if(!_2.__id){
-}else{
-if(_2.__id.substring(0,_6.length)==_6){
-this.onSet(_2,_3,_4,_5);
-}
-}
-});
-this.idAttribute=this.idAttribute||"id";
-if(typeof _1.target=="string"){
-_1.target=_1.target.match(/\/$/)||this.allowNoTrailingSlash?_1.target:(_1.target+"/");
-if(!this.service){
-this.service=dojox.rpc.JsonRest.services[_1.target]||dojox.rpc.Rest(_1.target,true);
-}
-}
-dojox.rpc.JsonRest.registerService(this.service,_1.target,this.schema);
-this.schema=this.service._schema=this.schema||this.service._schema||{};
-this.service._store=this;
-this.service.idAsRef=this.idAsRef;
-this.schema._idAttr=this.idAttribute;
-var _7=dojox.rpc.JsonRest.getConstructor(this.service);
-var _8=this;
-this._constructor=function(_9){
-_7.call(this,_9);
-_8.onNew(this);
-};
-this._constructor.prototype=_7.prototype;
-this._index=dojox.rpc.Rest._index;
-},loadReferencedSchema:true,idAsRef:false,referenceIntegrity:true,target:"",allowNoTrailingSlash:false,newItem:function(_a,_b){
-_a=new this._constructor(_a);
-if(_b){
-var _c=this.getValue(_b.parent,_b.attribute,[]);
-_c=_c.concat([_a]);
-_a.__parent=_c;
-this.setValue(_b.parent,_b.attribute,_c);
-}
-return _a;
-},deleteItem:function(_d){
-var _e=[];
-var _f=dojox.data._getStoreForItem(_d)||this;
-if(this.referenceIntegrity){
-dojox.rpc.JsonRest._saveNotNeeded=true;
-var _10=dojox.rpc.Rest._index;
-var _11=function(_12){
-var _13;
-_e.push(_12);
-_12.__checked=1;
-for(var i in _12){
-if(i.substring(0,2)!="__"){
-var _14=_12[i];
-if(_14==_d){
-if(_12!=_10){
-if(_12 instanceof Array){
-(_13=_13||[]).push(i);
-}else{
-(dojox.data._getStoreForItem(_12)||_f).unsetAttribute(_12,i);
-}
-}
-}else{
-if((typeof _14=="object")&&_14){
-if(!_14.__checked){
-_11(_14);
-}
-if(typeof _14.__checked=="object"&&_12!=_10){
-(dojox.data._getStoreForItem(_12)||_f).setValue(_12,i,_14.__checked);
-}
-}
-}
-}
-}
-if(_13){
-i=_13.length;
-_12=_12.__checked=_12.concat();
-while(i--){
-_12.splice(_13[i],1);
-}
-return _12;
-}
-return null;
-};
-_11(_10);
-dojox.rpc.JsonRest._saveNotNeeded=false;
-var i=0;
-while(_e[i]){
-delete _e[i++].__checked;
-}
-}
-dojox.rpc.JsonRest.deleteObject(_d);
-_f.onDelete(_d);
-},changing:function(_15,_16){
-dojox.rpc.JsonRest.changing(_15,_16);
-},setValue:function(_17,_18,_19){
-var old=_17[_18];
-var _1a=_17.__id?dojox.data._getStoreForItem(_17):this;
-if(dojox.json.schema&&_1a.schema&&_1a.schema.properties){
-dojox.json.schema.mustBeValid(dojox.json.schema.checkPropertyChange(_19,_1a.schema.properties[_18]));
-}
-if(_18==_1a.idAttribute){
-throw new Error("Can not change the identity attribute for an item");
-}
-_1a.changing(_17);
-_17[_18]=_19;
-if(_19&&!_19.__parent){
-_19.__parent=_17;
-}
-_1a.onSet(_17,_18,old,_19);
-},setValues:function(_1b,_1c,_1d){
-if(!dojo.isArray(_1d)){
-throw new Error("setValues expects to be passed an Array object as its value");
-}
-this.setValue(_1b,_1c,_1d);
-},unsetAttribute:function(_1e,_1f){
-this.changing(_1e);
-var old=_1e[_1f];
-delete _1e[_1f];
-this.onSet(_1e,_1f,old,undefined);
-},save:function(_20){
-if(!(_20&&_20.global)){
-(_20=_20||{}).service=this.service;
-}
-if("syncMode" in _20?_20.syncMode:this.syncMode){
-dojox.rpc._sync=true;
-}
-var _21=dojox.rpc.JsonRest.commit(_20);
-this.serverVersion=this._updates&&this._updates.length;
-return _21;
-},revert:function(_22){
-dojox.rpc.JsonRest.revert(_22&&_22.global&&this.service);
-},isDirty:function(_23){
-return dojox.rpc.JsonRest.isDirty(_23);
-},isItem:function(_24,_25){
-return _24&&_24.__id&&(_25||this.service==dojox.rpc.JsonRest.getServiceAndId(_24.__id).service);
-},_doQuery:function(_26){
-var _27=typeof _26.queryStr=="string"?_26.queryStr:_26.query;
-var _28=dojox.rpc.JsonRest.query(this.service,_27,_26);
-var _29=this;
-if(this.loadReferencedSchema){
-_28.addCallback(function(_2a){
-var _2b=_28.ioArgs&&_28.ioArgs.xhr&&_28.ioArgs.xhr.getResponseHeader("Content-Type");
-var _2c=_2b&&_2b.match(/definedby\s*=\s*([^;]*)/);
-if(_2b&&!_2c){
-_2c=_28.ioArgs.xhr.getResponseHeader("Link");
-_2c=_2c&&_2c.match(/<([^>]*)>;\s*rel="?definedby"?/);
-}
-_2c=_2c&&_2c[1];
-if(_2c){
-var _2d=dojox.rpc.JsonRest.getServiceAndId((_29.target+_2c).replace(/^(.*\/)?(\w+:\/\/)|[^\/\.]+\/\.\.\/|^.*\/(\/)/,"$2$3"));
-var _2e=dojox.rpc.JsonRest.byId(_2d.service,_2d.id);
-_2e.addCallbacks(function(_2f){
-dojo.mixin(_29.schema,_2f);
-return _2a;
-},function(_30){
-console.error(_30);
-return _2a;
-});
-return _2e;
-}
-return undefined;
-});
-}
-return _28;
-},_processResults:function(_31,_32){
-var _33=_31.length;
-return {totalCount:_32.fullLength||(_32.request.count==_33?(_32.request.start||0)+_33*2:_33),items:_31};
-},getConstructor:function(){
-return this._constructor;
-},getIdentity:function(_34){
-var id=_34.__clientId||_34.__id;
-if(!id){
-return id;
-}
-var _35=this.service.servicePath.replace(/[^\/]*$/,"");
-return id.substring(0,_35.length)!=_35?id:id.substring(_35.length);
-},fetchItemByIdentity:function(_36){
-var id=_36.identity;
-var _37=this;
-if(id.toString().match(/^(\w*:)?\//)){
-var _38=dojox.rpc.JsonRest.getServiceAndId(id);
-_37=_38.service._store;
-_36.identity=_38.id;
-}
-_36._prefix=_37.service.servicePath.replace(/[^\/]*$/,"");
-return _37.inherited(arguments);
-},onSet:function(){
-},onNew:function(){
-},onDelete:function(){
-},getFeatures:function(){
-var _39=this.inherited(arguments);
-_39["dojo.data.api.Write"]=true;
-_39["dojo.data.api.Notification"]=true;
-return _39;
-},getParent:function(_3a){
-return _3a&&_3a.__parent;
-}});
-dojox.data.JsonRestStore.getStore=function(_3b,_3c){
-if(typeof _3b.target=="string"){
-_3b.target=_3b.target.match(/\/$/)||_3b.allowNoTrailingSlash?_3b.target:(_3b.target+"/");
-var _3d=(dojox.rpc.JsonRest.services[_3b.target]||{})._store;
-if(_3d){
-return _3d;
-}
-}
-return new (_3c||dojox.data.JsonRestStore)(_3b);
+
+dojo.declare("dojox.data.JsonRestStore",
+	dojox.data.ServiceStore,
+	{
+		constructor: function(options){
+			//summary:
+			//		JsonRestStore is a Dojo Data store interface to JSON HTTP/REST web
+			//		storage services that support read and write through GET, PUT, POST, and DELETE.
+			// options:
+			// 		Keyword arguments
+			//
+			// The *schema* parameter
+			//		This is a schema object for this store. This should be JSON Schema format.
+			//
+			// The *service* parameter
+			// 		This is the service object that is used to retrieve lazy data and save results
+			// 		The function should be directly callable with a single parameter of an object id to be loaded
+			// 		The function should also have the following methods:
+			// 			put(id,value) - puts the value at the given id
+			// 			post(id,value) - posts (appends) the value at the given id
+			// 			delete(id) - deletes the value corresponding to the given id
+			//		Note that it is critical that the service parses responses as JSON.
+			//		If you are using dojox.rpc.Service, the easiest way to make sure this
+			// 		happens is to make the responses have a content type of
+			// 		application/json. If you are creating your own service, make sure you
+			//		use handleAs: "json" with your XHR requests.
+			//
+			// The *target* parameter
+			// 		This is the target URL for this Service store. This may be used in place
+			// 		of a service parameter to connect directly to RESTful URL without
+			// 		using a dojox.rpc.Service object.
+			//
+			// The *idAttribute* parameter
+			//		Defaults to 'id'. The name of the attribute that holds an objects id.
+			//		This can be a preexisting id provided by the server.
+			//		If an ID isn't already provided when an object
+			//		is fetched or added to the store, the autoIdentity system
+			//		will generate an id for it and add it to the index.
+			//
+			// The *syncMode* parameter
+			//		Setting this to true will set the store to using synchronous calls by default.
+			//		Sync calls return their data immediately from the calling function, so
+			//		callbacks are unnecessary
+			//
+			//	description:
+			//		The JsonRestStore will cause all saved modifications to be sent to the server using Rest commands (PUT, POST, or DELETE).
+			// 		When using a Rest store on a public network, it is important to implement proper security measures to
+			//		control access to resources.
+			//		On the server side implementing a REST interface means providing GET, PUT, POST, and DELETE handlers.
+			//		GET - Retrieve an object or array/result set, this can be by id (like /table/1) or with a
+			// 			query (like /table/?name=foo).
+			//		PUT - This should modify a object, the URL will correspond to the id (like /table/1), and the body will
+			// 			provide the modified object
+			//		POST - This should create a new object. The URL will correspond to the target store (like /table/)
+			// 			and the body should be the properties of the new object. The server's response should include a
+			// 			Location header that indicates the id of the newly created object. This id will be used for subsequent
+			// 			PUT and DELETE requests. JsonRestStore also includes a Content-Location header that indicates
+			//			the temporary randomly generated id used by client, and this location is used for subsequent
+			// 			PUT/DELETEs if no Location header is provided by the server or if a modification is sent prior
+			// 			to receiving a response from the server.
+			// 		DELETE - This should delete an object by id.
+			// 		These articles include more detailed information on using the JsonRestStore:
+			//		http://www.sitepen.com/blog/2008/06/13/restful-json-dojo-data/
+			//		http://blog.medryx.org/2008/07/24/jsonreststore-overview/
+			//
+			//	example:
+			// 		A JsonRestStore takes a REST service or a URL and uses it the remote communication for a
+			// 		read/write dojo.data implementation. A JsonRestStore can be created with a simple URL like:
+			// 	|	new JsonRestStore({target:"/MyData/"});
+			//	example:
+			// 		To use a JsonRestStore with a service, you should create a
+			// 		service with a REST transport. This can be configured with an SMD:
+			//	|	{
+			//	|		services: {
+			//	|			jsonRestStore: {
+			//	|				transport: "REST",
+			//	|				envelope: "URL",
+			//	|				target: "store.php",
+			//	|				contentType:"application/json",
+			//	|				parameters: [
+			//	|					{name: "location", type: "string", optional: true}
+			//	|				]
+			//	|			}
+			//	|		}
+			//	|	}
+			// 		The SMD can then be used to create service, and the service can be passed to a JsonRestStore. For example:
+			//	|	var myServices = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.tests.resources", "test.smd"));
+			//	|	var jsonStore = new dojox.data.JsonRestStore({service:myServices.jsonRestStore});
+			//	example:
+			//		The JsonRestStore also supports lazy loading. References can be made to objects that have not been loaded.
+			//		For example if a service returned:
+			//	|	{"name":"Example","lazyLoadedObject":{"$ref":"obj2"}}
+			// 		And this object has accessed using the dojo.data API:
+			//	|	var obj = jsonStore.getValue(myObject,"lazyLoadedObject");
+			//		The object would automatically be requested from the server (with an object id of "obj2").
+			//
+
+			dojo.connect(dojox.rpc.Rest._index,"onUpdate",this,function(obj,attrName,oldValue,newValue){
+				var prefix = this.service.servicePath;
+				if(!obj.__id){
+					console.log("no id on updated object ", obj);
+				}else if(obj.__id.substring(0,prefix.length) == prefix){
+					this.onSet(obj,attrName,oldValue,newValue);
+				}
+			});
+			this.idAttribute = this.idAttribute || 'id';// no options about it, we have to have identity
+
+			if(typeof options.target == 'string'){
+				options.target = options.target.match(/\/$/) || this.allowNoTrailingSlash ? options.target : (options.target + '/');
+				if(!this.service){
+					this.service = dojox.rpc.JsonRest.services[options.target] ||
+							dojox.rpc.Rest(options.target, true);
+					// create a default Rest service
+				}
+			}
+
+			dojox.rpc.JsonRest.registerService(this.service, options.target, this.schema);
+			this.schema = this.service._schema = this.schema || this.service._schema || {};
+			// wrap the service with so it goes through JsonRest manager
+			this.service._store = this;
+			this.service.idAsRef = this.idAsRef;
+			this.schema._idAttr = this.idAttribute;
+			var constructor = dojox.rpc.JsonRest.getConstructor(this.service);
+			var self = this;
+			this._constructor = function(data){
+				constructor.call(this, data);
+				self.onNew(this);
+			}
+			this._constructor.prototype = constructor.prototype;
+			this._index = dojox.rpc.Rest._index;
+		},
+		
+		// summary:
+		//		Will load any schemas referenced content-type header or in Link headers
+		loadReferencedSchema: true,
+		// summary:
+		//		Treat objects in queries as partially loaded objects
+		idAsRef: false,
+		referenceIntegrity: true,
+		target:"",
+		// summary:
+		// 		Allow no trailing slash on target paths. This is generally discouraged since
+		// 		it creates prevents simple scalar values from being used a relative URLs.
+		// 		Disabled by default.
+		allowNoTrailingSlash: false,
+		//Write API Support
+		newItem: function(data, parentInfo){
+			// summary:
+			//		adds a new item to the store at the specified point.
+			//		Takes two parameters, data, and options.
+			//
+			//	data: /* object */
+			//		The data to be added in as an item.
+			data = new this._constructor(data);
+			if(parentInfo){
+				// get the previous value or any empty array
+				var values = this.getValue(parentInfo.parent,parentInfo.attribute,[]);
+				// set the new value
+				values = values.concat([data]);
+				data.__parent = values;
+				this.setValue(parentInfo.parent, parentInfo.attribute, values);
+			}
+			return data;
+		},
+		deleteItem: function(item){
+			// summary:
+			//		deletes item and any references to that item from the store.
+			//
+			//	item:
+			//		item to delete
+			//
+
+			//	If the desire is to delete only one reference, unsetAttribute or
+			//	setValue is the way to go.
+			var checked = [];
+			var store = dojox.data._getStoreForItem(item) || this;
+			if(this.referenceIntegrity){
+				// cleanup all references
+				dojox.rpc.JsonRest._saveNotNeeded = true;
+				var index = dojox.rpc.Rest._index;
+				var fixReferences = function(parent){
+					var toSplice;
+					// keep track of the checked ones
+					checked.push(parent);
+					// mark it checked so we don't run into circular loops when encountering cycles
+					parent.__checked = 1;
+					for(var i in parent){
+						if(i.substring(0,2) != "__"){
+							var value = parent[i];
+							if(value == item){
+								if(parent != index){ // make sure we are just operating on real objects
+									if(parent instanceof Array){
+										// mark it as needing to be spliced, don't do it now or it will mess up the index into the array
+										(toSplice = toSplice || []).push(i);
+									}else{
+										// property, just delete it.
+										(dojox.data._getStoreForItem(parent) || store).unsetAttribute(parent, i);
+									}
+								}
+							}else{
+								if((typeof value == 'object') && value){
+									if(!value.__checked){
+										// recursively search
+										fixReferences(value);
+									}
+									if(typeof value.__checked == 'object' && parent != index){
+										// if it is a modified array, we will replace it
+										(dojox.data._getStoreForItem(parent) || store).setValue(parent, i, value.__checked);
+									}
+								}
+							}
+						}
+					}
+					if(toSplice){
+						// we need to splice the deleted item out of these arrays
+						i = toSplice.length;
+						parent = parent.__checked = parent.concat(); // indicates that the array is modified
+						while(i--){
+							parent.splice(toSplice[i], 1);
+						}
+						return parent;
+					}
+					return null;
+				};
+				// start with the index
+				fixReferences(index);
+				dojox.rpc.JsonRest._saveNotNeeded = false;
+				var i = 0;
+				while(checked[i]){
+					// remove the checked marker
+					delete checked[i++].__checked;
+				}
+			}
+			dojox.rpc.JsonRest.deleteObject(item);
+
+			store.onDelete(item);
+		},
+		changing: function(item,_deleting){
+			// summary:
+			//		adds an item to the list of dirty items.	This item
+			//		contains a reference to the item itself as well as a
+			//		cloned and trimmed version of old item for use with
+			//		revert.
+			dojox.rpc.JsonRest.changing(item,_deleting);
+		},
+
+		setValue: function(item, attribute, value){
+			// summary:
+			//		sets 'attribute' on 'item' to 'value'
+
+			var old = item[attribute];
+			var store = item.__id ? dojox.data._getStoreForItem(item) : this;
+			if(dojox.json.schema && store.schema && store.schema.properties){
+				// if we have a schema and schema validator available we will validate the property change
+				dojox.json.schema.mustBeValid(dojox.json.schema.checkPropertyChange(value,store.schema.properties[attribute]));
+			}
+			if(attribute == store.idAttribute){
+				throw new Error("Can not change the identity attribute for an item");
+			}
+			store.changing(item);
+			item[attribute]=value;
+			if(value && !value.__parent){
+				value.__parent = item;
+			}
+			store.onSet(item,attribute,old,value);
+		},
+		setValues: function(item, attribute, values){
+			// summary:
+			//	sets 'attribute' on 'item' to 'value' value
+			//	must be an array.
+
+
+			if(!dojo.isArray(values)){
+				throw new Error("setValues expects to be passed an Array object as its value");
+			}
+			this.setValue(item,attribute,values);
+		},
+
+		unsetAttribute: function(item, attribute){
+			// summary:
+			//		unsets 'attribute' on 'item'
+
+			this.changing(item);
+			var old = item[attribute];
+			delete item[attribute];
+			this.onSet(item,attribute,old,undefined);
+		},
+		save: function(kwArgs){
+			// summary:
+			//		Saves the dirty data using REST Ajax methods. See dojo.data.api.Write for API.
+			//
+			//	kwArgs.global:
+			//		This will cause the save to commit the dirty data for all
+			// 		JsonRestStores as a single transaction.
+			//
+			//	kwArgs.revertOnError
+			//		This will cause the changes to be reverted if there is an
+			//		error on the save. By default a revert is executed unless
+			//		a value of false is provide for this parameter.
+			//
+			//	kwArgs.incrementalUpdates
+			//		For items that have been updated, if this is enabled, the server will be sent a POST request
+			// 		with a JSON object containing the changed properties. By default this is
+			// 		not enabled, and a PUT is used to deliver an update, and will include a full
+			// 		serialization of all the properties of the item/object.
+			//		If this is true, the POST request body will consist of a JSON object with
+			// 		only the changed properties. The incrementalUpdates parameter may also
+			//		be a function, in which case it will be called with the updated and previous objects
+			//		and an object update representation can be returned.
+			//
+			//	kwArgs.alwaysPostNewItems
+			//		If this is true, new items will always be sent with a POST request. By default
+			//		this is not enabled, and the JsonRestStore will send a POST request if
+			//		the item does not include its identifier (expecting server assigned location/
+			//		identifier), and will send a PUT request if the item does include its identifier
+			//		(the PUT will be sent to the URI corresponding to the provided identifier).
+
+			if(!(kwArgs && kwArgs.global)){
+				(kwArgs = kwArgs || {}).service = this.service;
+			}
+			if("syncMode" in kwArgs ? kwArgs.syncMode : this.syncMode){
+				dojox.rpc._sync = true;
+			}
+
+			var actions = dojox.rpc.JsonRest.commit(kwArgs);
+			this.serverVersion = this._updates && this._updates.length;
+			return actions;
+		},
+
+		revert: function(kwArgs){
+			// summary
+			//		returns any modified data to its original state prior to a save();
+			//
+			//	kwArgs.global:
+			//		This will cause the revert to undo all the changes for all
+			// 		JsonRestStores in a single operation.
+			dojox.rpc.JsonRest.revert(kwArgs && kwArgs.global && this.service);
+		},
+
+		isDirty: function(item){
+			// summary
+			//		returns true if the item is marked as dirty.
+			return dojox.rpc.JsonRest.isDirty(item);
+		},
+		isItem: function(item, anyStore){
+			//	summary:
+			//		Checks to see if a passed 'item'
+			//		really belongs to this JsonRestStore.
+			//
+			//	item: /* object */
+			//		The value to test for being an item
+			//	anyStore: /* boolean*/
+			//		If true, this will return true if the value is an item for any JsonRestStore,
+			//		not just this instance
+			return item && item.__id && (anyStore || this.service == dojox.rpc.JsonRest.getServiceAndId(item.__id).service);
+		},
+		_doQuery: function(args){
+			var query= typeof args.queryStr == 'string' ? args.queryStr : args.query;
+			var deferred = dojox.rpc.JsonRest.query(this.service,query, args);
+			var self = this;
+			if(this.loadReferencedSchema){
+				deferred.addCallback(function(result){
+					var contentType = deferred.ioArgs && deferred.ioArgs.xhr && deferred.ioArgs.xhr.getResponseHeader("Content-Type");
+					var schemaRef = contentType && contentType.match(/definedby\s*=\s*([^;]*)/);
+					if(contentType && !schemaRef){
+						schemaRef = deferred.ioArgs.xhr.getResponseHeader("Link");
+						schemaRef = schemaRef && schemaRef.match(/<([^>]*)>;\s*rel="?definedby"?/);
+					}
+					schemaRef = schemaRef && schemaRef[1];
+					if(schemaRef){
+						var serviceAndId = dojox.rpc.JsonRest.getServiceAndId((self.target + schemaRef).replace(/^(.*\/)?(\w+:\/\/)|[^\/\.]+\/\.\.\/|^.*\/(\/)/,"$2$3"));
+						var schemaDeferred = dojox.rpc.JsonRest.byId(serviceAndId.service, serviceAndId.id);
+						schemaDeferred.addCallbacks(function(newSchema){
+							dojo.mixin(self.schema, newSchema);
+							return result;
+						}, function(error){
+							console.error(error); // log it, but don't let it cause the main request to fail
+							return result;
+						});
+						return schemaDeferred;
+					}
+					return undefined;//don't change anything, and deal with the stupid post-commit lint complaints
+				});
+			}
+			return deferred;
+		},
+		_processResults: function(results, deferred){
+			// index the results
+			var count = results.length;
+			// if we don't know the length, and it is partial result, we will guess that it is twice as big, that will work for most widgets
+			return {totalCount:deferred.fullLength || (deferred.request.count == count ? (deferred.request.start || 0) + count * 2 : count), items: results};
+		},
+
+		getConstructor: function(){
+			// summary:
+			// 		Gets the constructor for objects from this store
+			return this._constructor;
+		},
+		getIdentity: function(item){
+			var id = item.__clientId || item.__id;
+			if(!id){
+				return id;
+			}
+			var prefix = this.service.servicePath.replace(/[^\/]*$/,'');
+			// support for relative or absolute referencing with ids
+			return id.substring(0,prefix.length) != prefix ?	id : id.substring(prefix.length); // String
+		},
+		fetchItemByIdentity: function(args){
+			var id = args.identity;
+			var store = this;
+			// if it is an absolute id, we want to find the right store to query
+			if(id.toString().match(/^(\w*:)?\//)){
+				var serviceAndId = dojox.rpc.JsonRest.getServiceAndId(id);
+				store = serviceAndId.service._store;
+				args.identity = serviceAndId.id;
+			}
+			args._prefix = store.service.servicePath.replace(/[^\/]*$/,'');
+			return store.inherited(arguments);
+		},
+		//Notifcation Support
+
+		onSet: function(){},
+		onNew: function(){},
+		onDelete: 	function(){},
+
+		getFeatures: function(){
+			// summary:
+			// 		return the store feature set
+			var features = this.inherited(arguments);
+			features["dojo.data.api.Write"] = true;
+			features["dojo.data.api.Notification"] = true;
+			return features;
+		},
+
+		getParent: function(item){
+			//	summary:
+			//		Returns the parent item (or query) for the given item
+			//	item:
+			//		The item to find the parent of
+
+			return item && item.__parent;
+		}
+
+
+	}
+);
+dojox.data.JsonRestStore.getStore = function(options, Class){
+	//	summary:
+	//		Will retrieve or create a store using the given options (the same options
+	//		that are passed to JsonRestStore constructor. Returns a JsonRestStore instance
+	//	options:
+	//		See the JsonRestStore constructor
+	//	Class:
+	//		Constructor to use (for creating stores from JsonRestStore subclasses).
+	// 		This is optional and defaults to JsonRestStore.
+	if(typeof options.target == 'string'){
+		options.target = options.target.match(/\/$/) || options.allowNoTrailingSlash ?
+				options.target : (options.target + '/');
+		var store = (dojox.rpc.JsonRest.services[options.target] || {})._store;
+		if(store){
+			return store;
+		}
+	}
+	return new (Class || dojox.data.JsonRestStore)(options);
 };
-dojox.data._getStoreForItem=function(_3e){
-if(_3e.__id){
-var _3f=dojox.rpc.JsonRest.getServiceAndId(_3e.__id);
-if(_3f&&_3f.service._store){
-return _3f.service._store;
-}else{
-var _40=_3e.__id.toString().match(/.*\//)[0];
-return new dojox.data.JsonRestStore({target:_40});
-}
-}
-return null;
+dojox.data._getStoreForItem = function(item){
+	if(item.__id){
+		var serviceAndId = dojox.rpc.JsonRest.getServiceAndId(item.__id);
+		if(serviceAndId && serviceAndId.service._store){
+			return serviceAndId.service._store;
+		}else{
+			var servicePath = item.__id.toString().match(/.*\//)[0];
+			return new dojox.data.JsonRestStore({target:servicePath});
+		}
+	}
+	return null;
 };
-dojox.json.ref._useRefs=true;
-}
+dojox.json.ref._useRefs = true; // Use referencing when identifiable objects are referenced
diff --git a/dojox/data/KeyValueStore.js b/dojox/data/KeyValueStore.js
index b85904a..5484a1e 100644
--- a/dojox/data/KeyValueStore.js
+++ b/dojox/data/KeyValueStore.js
@@ -1,225 +1,391 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.KeyValueStore"]){
-dojo._hasResource["dojox.data.KeyValueStore"]=true;
 dojo.provide("dojox.data.KeyValueStore");
+
 dojo.require("dojo.data.util.filter");
 dojo.require("dojo.data.util.simpleFetch");
-dojo.declare("dojox.data.KeyValueStore",null,{constructor:function(_1){
-if(_1.url){
-this.url=_1.url;
-}
-this._keyValueString=_1.data;
-this._keyValueVar=_1.dataVar;
-this._keyAttribute="key";
-this._valueAttribute="value";
-this._storeProp="_keyValueStore";
-this._features={"dojo.data.api.Read":true,"dojo.data.api.Identity":true};
-this._loadInProgress=false;
-this._queuedFetches=[];
-if(_1&&"urlPreventCache" in _1){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-},url:"",data:"",urlPreventCache:false,_assertIsItem:function(_2){
-if(!this.isItem(_2)){
-throw new Error("dojox.data.KeyValueStore: a function was passed an item argument that was not an item");
-}
-},_assertIsAttribute:function(_3,_4){
-if(!dojo.isString(_4)){
-throw new Error("dojox.data.KeyValueStore: a function was passed an attribute argument that was not an attribute object nor an attribute name string");
-}
-},getValue:function(_5,_6,_7){
-this._assertIsItem(_5);
-this._assertIsAttribute(_5,_6);
-var _8;
-if(_6==this._keyAttribute){
-_8=_5[this._keyAttribute];
-}else{
-_8=_5[this._valueAttribute];
-}
-if(_8===undefined){
-_8=_7;
-}
-return _8;
-},getValues:function(_9,_a){
-var _b=this.getValue(_9,_a);
-return (_b?[_b]:[]);
-},getAttributes:function(_c){
-return [this._keyAttribute,this._valueAttribute,_c[this._keyAttribute]];
-},hasAttribute:function(_d,_e){
-this._assertIsItem(_d);
-this._assertIsAttribute(_d,_e);
-return (_e==this._keyAttribute||_e==this._valueAttribute||_e==_d[this._keyAttribute]);
-},containsValue:function(_f,_10,_11){
-var _12=undefined;
-if(typeof _11==="string"){
-_12=dojo.data.util.filter.patternToRegExp(_11,false);
-}
-return this._containsValue(_f,_10,_11,_12);
-},_containsValue:function(_13,_14,_15,_16){
-var _17=this.getValues(_13,_14);
-for(var i=0;i<_17.length;++i){
-var _18=_17[i];
-if(typeof _18==="string"&&_16){
-return (_18.match(_16)!==null);
-}else{
-if(_15===_18){
-return true;
-}
-}
-}
-return false;
-},isItem:function(_19){
-if(_19&&_19[this._storeProp]===this){
-return true;
-}
-return false;
-},isItemLoaded:function(_1a){
-return this.isItem(_1a);
-},loadItem:function(_1b){
-},getFeatures:function(){
-return this._features;
-},close:function(_1c){
-},getLabel:function(_1d){
-return _1d[this._keyAttribute];
-},getLabelAttributes:function(_1e){
-return [this._keyAttribute];
-},_fetchItems:function(_1f,_20,_21){
-var _22=this;
-var _23=function(_24,_25){
-var _26=null;
-if(_24.query){
-_26=[];
-var _27=_24.queryOptions?_24.queryOptions.ignoreCase:false;
-var _28={};
-for(var key in _24.query){
-var _29=_24.query[key];
-if(typeof _29==="string"){
-_28[key]=dojo.data.util.filter.patternToRegExp(_29,_27);
-}
-}
-for(var i=0;i<_25.length;++i){
-var _2a=true;
-var _2b=_25[i];
-for(var key in _24.query){
-var _29=_24.query[key];
-if(!_22._containsValue(_2b,key,_29,_28[key])){
-_2a=false;
-}
-}
-if(_2a){
-_26.push(_2b);
-}
-}
-}else{
-if(_24.identity){
-_26=[];
-var _2c;
-for(var key in _25){
-_2c=_25[key];
-if(_2c[_22._keyAttribute]==_24.identity){
-_26.push(_2c);
-break;
-}
-}
-}else{
-if(_25.length>0){
-_26=_25.slice(0,_25.length);
-}
-}
-}
-_20(_26,_24);
-};
-if(this._loadFinished){
-_23(_1f,this._arrayOfAllItems);
-}else{
-if(this.url!==""){
-if(this._loadInProgress){
-this._queuedFetches.push({args:_1f,filter:_23});
-}else{
-this._loadInProgress=true;
-var _2d={url:_22.url,handleAs:"json-comment-filtered",preventCache:this.urlPreventCache};
-var _2e=dojo.xhrGet(_2d);
-_2e.addCallback(function(_2f){
-_22._processData(_2f);
-_23(_1f,_22._arrayOfAllItems);
-_22._handleQueuedFetches();
-});
-_2e.addErrback(function(_30){
-_22._loadInProgress=false;
-throw _30;
+
+dojo.declare("dojox.data.KeyValueStore", null, {
+	//	summary:
+	//		This is a dojo.data store implementation.  It can take in either a Javascript
+	//		array, JSON string, or URL as the data source.  Data is expected to be in the 
+	//		following format:
+	//			[
+	//				{ "key1": "value1" },
+	//				{ "key2": "value2" }
+	//			]
+	//		This is to mimic the Java Properties file format.  Each 'item' from this store 
+	//		is a JS object representing a key-value pair.  If an item in the above array has 
+	//		more than one key/value pair, only the first will be used/accessed.
+	constructor: function(/* Object */ keywordParameters){
+		//	summary: constructor
+		//	keywordParameters: {url: String}
+		//	keywordParameters: {data: string}
+		//	keywordParameters: {dataVar: jsonObject}
+		if(keywordParameters.url){
+			this.url = keywordParameters.url;
+		}
+		this._keyValueString = keywordParameters.data;
+		this._keyValueVar = keywordParameters.dataVar;
+		this._keyAttribute = "key";
+		this._valueAttribute = "value";
+		this._storeProp = "_keyValueStore";
+		this._features = {	
+			'dojo.data.api.Read': true,
+			'dojo.data.api.Identity': true 
+		};
+		this._loadInProgress = false;	//Got to track the initial load to prevent duelling loads of the dataset.
+		this._queuedFetches = [];
+		if(keywordParameters && "urlPreventCache" in keywordParameters){
+			this.urlPreventCache = keywordParameters.urlPreventCache?true:false;
+		}
+	},
+	
+	url: "",
+	data: "",
+
+	//urlPreventCache: boolean
+	//Controls if urlPreventCache should be used with underlying xhrGet.
+	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("dojox.data.KeyValueStore: a function was passed an item argument that was not an item");
+		}
+	},
+	
+	_assertIsAttribute: function(/* item */ item, /* 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(!dojo.isString(attribute)){
+			throw new Error("dojox.data.KeyValueStore: a function was passed an attribute argument that was not an attribute object nor an attribute name string");
+		}
+	},
+
+/***************************************
+     dojo.data.api.Read API
+***************************************/
+	getValue: function(	/* item */ item, 
+						/* attribute-name-string */ attribute, 
+						/* value? */ defaultValue){
+		//	summary: 
+		//		See dojo.data.api.Read.getValue()
+		this._assertIsItem(item);
+		this._assertIsAttribute(item, attribute);
+		var value;
+		if(attribute == this._keyAttribute){ // Looking for key
+			value = item[this._keyAttribute];
+		}else{
+			value = item[this._valueAttribute]; // Otherwise, attribute == ('value' || the actual key )
+		}
+		if(value === undefined){
+			value = defaultValue;
+		}
+		return value;
+	},
+
+	getValues: function(/* item */ item,
+						/* attribute-name-string */ attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.getValues()
+		// 		Key/Value syntax does not support multi-valued attributes, so this is just a
+		// 		wrapper function for getValue().
+		var value = this.getValue(item, attribute);
+		return (value ? [value] : []); //Array
+	},
+
+	getAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getAttributes()
+		return [this._keyAttribute, this._valueAttribute, item[this._keyAttribute]];
+	},
+
+	hasAttribute: function(	/* item */ item,
+							/* attribute-name-string */ attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.hasAttribute()
+		this._assertIsItem(item);
+		this._assertIsAttribute(item, attribute);
+		return (attribute == this._keyAttribute || attribute == this._valueAttribute || attribute == item[this._keyAttribute]);
+	},
+
+	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 || 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'
+		var values = this.getValues(item, attribute);
+		for(var i = 0; i < values.length; ++i){
+			var possibleValue = values[i];
+			if(typeof possibleValue === "string" && regexp){
+				return (possibleValue.match(regexp) !== null);
+			}else{
+				//Non-string matching.
+				if(value === possibleValue){
+					return true; // Boolean
+				}
+			}
+		}
+		return false; // Boolean
+	},
+
+	isItem: function(/* anything */ something){
+		//	summary: 
+		//		See dojo.data.api.Read.isItem()
+		if(something && something[this._storeProp] === this){
+			return true; //Boolean
+		}
+		return false; //Boolean
+	},
+
+	isItemLoaded: function(/* anything */ something){
+		//	summary: 
+		//		See dojo.data.api.Read.isItemLoaded()
+		//		The KeyValueStore always loads all items, so if it's an item, then it's loaded.
+		return this.isItem(something); //Boolean
+	},
+
+	loadItem: function(/* object */ keywordArgs){
+		//	summary: 
+		//		See dojo.data.api.Read.loadItem()
+		//	description:
+		//		The KeyValueStore always loads all items, so if it's an item, then it's loaded.
+		//		From the dojo.data.api.Read.loadItem docs:
+		//			If a call to isItemLoaded() returns true before loadItem() is even called,
+		//			then loadItem() need not do any work at all and will not even invoke
+		//			the callback handlers.
+	},
+
+	getFeatures: function(){
+		//	summary: 
+		//		See dojo.data.api.Read.getFeatures()
+		return this._features; //Object
+	},
+
+	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+		//	summary: 
+		//		See dojo.data.api.Read.close()
+	},
+
+	getLabel: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabel()
+		return item[this._keyAttribute];
+	},
+
+	getLabelAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabelAttributes()
+		return [this._keyAttribute];
+	},
+	
+	// The dojo.data.api.Read.fetch() function is implemented as
+	// a mixin from dojo.data.util.simpleFetch.
+	// That mixin requires us to define _fetchItems().
+	_fetchItems: function(	/* Object */ keywordArgs,
+							/* Function */ findCallback,
+							/* Function */ errorCallback){
+		//	summary: 
+		//		See dojo.data.util.simpleFetch.fetch()
+		
+		var self = this;
+
+		var filter = function(requestArgs, arrayOfAllItems){
+			var items = null;
+			if(requestArgs.query){
+				items = [];
+				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(var key in requestArgs.query){
+					var value = requestArgs.query[key];
+					if(typeof value === "string"){
+						regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
+					}
+				}
+
+				for(var i = 0; i < arrayOfAllItems.length; ++i){
+					var match = true;
+					var candidateItem = arrayOfAllItems[i];
+					for(var key in requestArgs.query){
+						var value = requestArgs.query[key];
+						if(!self._containsValue(candidateItem, key, value, regexpList[key])){
+							match = false;
+						}
+					}
+					if(match){
+						items.push(candidateItem);
+					}
+				}
+			}else if(requestArgs.identity){
+				items = [];
+				var item;
+				for(var key in arrayOfAllItems){
+					item = arrayOfAllItems[key];
+					if(item[self._keyAttribute] == requestArgs.identity){
+						items.push(item);
+						break;
+					}
+				}
+			}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.
+				if(arrayOfAllItems.length> 0){
+					items = arrayOfAllItems.slice(0,arrayOfAllItems.length); 
+				}
+			}
+			findCallback(items, requestArgs);
+		};
+
+		if(this._loadFinished){
+			filter(keywordArgs, this._arrayOfAllItems);
+		}else{
+			if(this.url !== ""){
+				//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.url, 
+							handleAs: "json-comment-filtered",
+							preventCache: this.urlPreventCache
+						};
+					var getHandler = dojo.xhrGet(getArgs);
+					getHandler.addCallback(function(data){
+						self._processData(data);
+						filter(keywordArgs, self._arrayOfAllItems);
+						self._handleQueuedFetches();
+					});
+					getHandler.addErrback(function(error){
+						self._loadInProgress = false;
+						throw error;
+					});
+				}
+			}else if(this._keyValueString){
+				this._processData(eval(this._keyValueString));
+				this._keyValueString = null;
+				filter(keywordArgs, this._arrayOfAllItems);
+			}else if(this._keyValueVar){
+				this._processData(this._keyValueVar);
+				this._keyValueVar = null;
+				filter(keywordArgs, this._arrayOfAllItems);
+			}else{
+				throw new Error("dojox.data.KeyValueStore: No source data was provided as either URL, String, or Javascript variable data input.");
+			}
+		}
+		
+	},
+
+	_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 delayedFilter = fData.filter;
+				var delayedQuery = fData.args;
+				if(delayedFilter){
+					delayedFilter(delayedQuery, this._arrayOfAllItems); 
+				}else{
+					this.fetchItemByIdentity(fData.args);
+				}
+			}
+			this._queuedFetches = [];
+		}
+	},
+	
+	_processData: function(/* Array */ data){
+		this._arrayOfAllItems = [];
+		for(var i=0; i<data.length; i++){
+			this._arrayOfAllItems.push(this._createItem(data[i]));
+		}
+		this._loadFinished = true;
+		this._loadInProgress = false;
+	},
+	
+	_createItem: function(/* Object */ something){
+		var item = {};
+		item[this._storeProp] = this;
+		for(var i in something){
+			item[this._keyAttribute] = i;
+			item[this._valueAttribute] = something[i];
+			break;
+		}
+		return item; //Object
+	},
+
+/***************************************
+     dojo.data.api.Identity API
+***************************************/
+	getIdentity: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Identity.getIdentity()
+		if(this.isItem(item)){
+			return item[this._keyAttribute]; //String
+		}
+		return null; //null
+	},
+
+	getIdentityAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Identity.getIdentifierAttributes()
+		return [this._keyAttribute];
+	},
+
+	fetchItemByIdentity: function(/* object */ keywordArgs){
+		//	summary: 
+		//		See dojo.data.api.Identity.fetchItemByIdentity()
+		keywordArgs.oldOnItem = keywordArgs.onItem;
+		keywordArgs.onItem = null;
+		keywordArgs.onComplete = this._finishFetchItemByIdentity ;
+		this.fetch(keywordArgs);
+	},
+	
+	_finishFetchItemByIdentity: function(/* Array */ items, /* object */ request){
+		var scope = request.scope || dojo.global;
+		if(items.length){
+			request.oldOnItem.call(scope, items[0]);
+		}else{
+			request.oldOnItem.call(scope, null);
+		}
+	}
 });
-}
-}else{
-if(this._keyValueString){
-this._processData(eval(this._keyValueString));
-this._keyValueString=null;
-_23(_1f,this._arrayOfAllItems);
-}else{
-if(this._keyValueVar){
-this._processData(this._keyValueVar);
-this._keyValueVar=null;
-_23(_1f,this._arrayOfAllItems);
-}else{
-throw new Error("dojox.data.KeyValueStore: No source data was provided as either URL, String, or Javascript variable data input.");
-}
-}
-}
-}
-},_handleQueuedFetches:function(){
-if(this._queuedFetches.length>0){
-for(var i=0;i<this._queuedFetches.length;i++){
-var _31=this._queuedFetches[i];
-var _32=_31.filter;
-var _33=_31.args;
-if(_32){
-_32(_33,this._arrayOfAllItems);
-}else{
-this.fetchItemByIdentity(_31.args);
-}
-}
-this._queuedFetches=[];
-}
-},_processData:function(_34){
-this._arrayOfAllItems=[];
-for(var i=0;i<_34.length;i++){
-this._arrayOfAllItems.push(this._createItem(_34[i]));
-}
-this._loadFinished=true;
-this._loadInProgress=false;
-},_createItem:function(_35){
-var _36={};
-_36[this._storeProp]=this;
-for(var i in _35){
-_36[this._keyAttribute]=i;
-_36[this._valueAttribute]=_35[i];
-break;
-}
-return _36;
-},getIdentity:function(_37){
-if(this.isItem(_37)){
-return _37[this._keyAttribute];
-}
-return null;
-},getIdentityAttributes:function(_38){
-return [this._keyAttribute];
-},fetchItemByIdentity:function(_39){
-_39.oldOnItem=_39.onItem;
-_39.onItem=null;
-_39.onComplete=this._finishFetchItemByIdentity;
-this.fetch(_39);
-},_finishFetchItemByIdentity:function(_3a,_3b){
-var _3c=_3b.scope||dojo.global;
-if(_3a.length){
-_3b.oldOnItem.call(_3c,_3a[0]);
-}else{
-_3b.oldOnItem.call(_3c,null);
-}
-}});
+//Mix in the simple fetch implementation to this class.
 dojo.extend(dojox.data.KeyValueStore,dojo.data.util.simpleFetch);
-}
diff --git a/dojox/data/OpenSearchStore.js b/dojox/data/OpenSearchStore.js
index 6c0296d..39e2a0b 100644
--- a/dojox/data/OpenSearchStore.js
+++ b/dojox/data/OpenSearchStore.js
@@ -1,219 +1,367 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.OpenSearchStore"]){
-dojo._hasResource["dojox.data.OpenSearchStore"]=true;
 dojo.provide("dojox.data.OpenSearchStore");
+
 dojo.require("dojo.data.util.simpleFetch");
 dojo.require("dojox.xml.DomParser");
 dojo.require("dojox.xml.parser");
+
 dojo.experimental("dojox.data.OpenSearchStore");
-dojo.declare("dojox.data.OpenSearchStore",null,{constructor:function(_1){
-if(_1){
-this.label=_1.label;
-this.url=_1.url;
-this.itemPath=_1.itemPath;
-if("urlPreventCache" in _1){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-}
-var _2=dojo.xhrGet({url:this.url,handleAs:"xml",sync:true,preventCache:this.urlPreventCache});
-_2.addCallback(this,"_processOsdd");
-_2.addErrback(function(){
-throw new Error("Unable to load OpenSearch Description document from ".args.url);
-});
-},url:"",itemPath:"",_storeRef:"_S",urlElement:null,iframeElement:null,urlPreventCache:true,ATOM_CONTENT_TYPE:3,ATOM_CONTENT_TYPE_STRING:"atom",RSS_CONTENT_TYPE:2,RSS_CONTENT_TYPE_STRING:"rss",XML_CONTENT_TYPE:1,XML_CONTENT_TYPE_STRING:"xml",_assertIsItem:function(_3){
-if(!this.isItem(_3)){
-throw new Error("dojox.data.OpenSearchStore: a function was passed an item argument that was not an item");
-}
-},_assertIsAttribute:function(_4){
-if(typeof _4!=="string"){
-throw new Error("dojox.data.OpenSearchStore: a function was passed an attribute argument that was not an attribute name string");
-}
-},getFeatures:function(){
-return {"dojo.data.api.Read":true};
-},getValue:function(_5,_6,_7){
-var _8=this.getValues(_5,_6);
-if(_8){
-return _8[0];
-}
-return _7;
-},getAttributes:function(_9){
-return ["content"];
-},hasAttribute:function(_a,_b){
-if(this.getValue(_a,_b)){
-return true;
-}
-return false;
-},isItemLoaded:function(_c){
-return this.isItem(_c);
-},loadItem:function(_d){
-},getLabel:function(_e){
-return undefined;
-},getLabelAttributes:function(_f){
-return null;
-},containsValue:function(_10,_11,_12){
-var _13=this.getValues(_10,_11);
-for(var i=0;i<_13.length;i++){
-if(_13[i]===_12){
-return true;
-}
-}
-return false;
-},getValues:function(_14,_15){
-this._assertIsItem(_14);
-this._assertIsAttribute(_15);
-var _16=this.processItem(_14,_15);
-if(_16){
-return [_16];
-}
-return undefined;
-},isItem:function(_17){
-if(_17&&_17[this._storeRef]===this){
-return true;
-}
-return false;
-},close:function(_18){
-},process:function(_19){
-return this["_processOSD"+this.contentType](_19);
-},processItem:function(_1a,_1b){
-return this["_processItem"+this.contentType](_1a.node,_1b);
-},_createSearchUrl:function(_1c){
-var _1d=this.urlElement.attributes.getNamedItem("template").nodeValue;
-var _1e=this.urlElement.attributes;
-var _1f=_1d.indexOf("{searchTerms}");
-_1d=_1d.substring(0,_1f)+_1c.query.searchTerms+_1d.substring(_1f+13);
-dojo.forEach([{"name":"count","test":_1c.count,"def":"10"},{"name":"startIndex","test":_1c.start,"def":this.urlElement.attributes.getNamedItem("indexOffset")?this.urlElement.attributes.getNamedItem("indexOffset").nodeValue:0},{"name":"startPage","test":_1c.startPage,"def":this.urlElement.attributes.getNamedItem("pageOffset")?this.urlElement.attributes.getNamedItem("pageOffset").nodeValue:0},{"name":"language","test":_1c.language,"def":"*"},{"name":"inputEncoding","test":_1c.inputEncoding [...]
-_1d=_1d.replace("{"+_20.name+"}",_20.test||_20.def);
-_1d=_1d.replace("{"+_20.name+"?}",_20.test||_20.def);
-});
-return _1d;
-},_fetchItems:function(_21,_22,_23){
-if(!_21.query){
-_21.query={};
-}
-var _24=this;
-var url=this._createSearchUrl(_21);
-var _25={url:url,preventCache:this.urlPreventCache};
-var xhr=dojo.xhrGet(_25);
-xhr.addErrback(function(_26){
-_23(_26,_21);
-});
-xhr.addCallback(function(_27){
-var _28=[];
-if(_27){
-_28=_24.process(_27);
-for(var i=0;i<_28.length;i++){
-_28[i]={node:_28[i]};
-_28[i][_24._storeRef]=_24;
-}
-}
-_22(_28,_21);
+
+dojo.declare("dojox.data.OpenSearchStore", null, {
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		Initializer for the OpenSearchStore store.  
+		//	description:
+		//		The OpenSearchStore is a Datastore interface to any search
+		//		engine that implements the open search specifications.
+		if(args){
+			this.label = args.label;
+			this.url = args.url;
+			this.itemPath = args.itemPath;
+			if("urlPreventCache" in args){
+				this.urlPreventCache = args.urlPreventCache?true:false;
+			}
+		}
+		var def = dojo.xhrGet({
+			url: this.url,
+			handleAs: "xml",
+			sync: true,
+			preventCache: this.urlPreventCache
+		});
+		def.addCallback(this, "_processOsdd");
+		def.addErrback(function(){
+			throw new Error("Unable to load OpenSearch Description document from " . args.url);					
+		});
+	},
+	
+	// URL to the open search description document
+	url: "",
+	itemPath: "",
+	_storeRef: "_S",
+	urlElement: null,
+	iframeElement: null,
+
+	//urlPreventCache: boolean
+	//Flag denoting if xhrGet calls should use the preventCache option.
+	urlPreventCache: true,
+	
+	ATOM_CONTENT_TYPE: 3,
+	ATOM_CONTENT_TYPE_STRING: "atom",
+	RSS_CONTENT_TYPE: 2,
+	RSS_CONTENT_TYPE_STRING: "rss",
+	XML_CONTENT_TYPE: 1,
+	XML_CONTENT_TYPE_STRING: "xml",
+
+	_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("dojox.data.OpenSearchStore: a function was passed an item argument that was not an item");
+		}
+	},
+
+	_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("dojox.data.OpenSearchStore: a function was passed an attribute argument that was not an attribute name string");
+		}
+	},
+
+	getFeatures: function(){
+		//	summary: 
+		//      See dojo.data.api.Read.getFeatures()
+		return {
+			'dojo.data.api.Read': true
+		};
+	},
+
+	getValue: function(item, attribute, defaultValue){
+		//	summary: 
+		//      See dojo.data.api.Read.getValue()
+		var values = this.getValues(item, attribute);
+		if(values){
+			return values[0];
+		}
+		return defaultValue;
+	},
+
+	getAttributes: function(item){
+		//	summary: 
+		//      See dojo.data.api.Read.getAttributes()
+		return ["content"]; 
+	},
+
+	hasAttribute: function(item, attribute){
+		//	summary: 
+		//      See dojo.data.api.Read.hasAttributes()
+		if(this.getValue(item,attribute)){
+			return true;
+		}
+		return false;
+	},
+
+	isItemLoaded: function(item){
+		 //	summary: 
+		 //      See dojo.data.api.Read.isItemLoaded()
+		 return this.isItem(item);
+	},
+
+	loadItem: function(keywordArgs){
+		//	summary: 
+		//      See dojo.data.api.Read.loadItem()
+	},
+
+	getLabel: function(item){
+		//	summary: 
+		//      See dojo.data.api.Read.getLabel()
+		return undefined;
+	},
+	
+	getLabelAttributes: function(item){
+		//	summary: 
+		//      See dojo.data.api.Read.getLabelAttributes()
+		return null;
+	},
+
+	containsValue: function(item, attribute, value){
+		//	summary: 
+		//      See dojo.data.api.Read.containsValue()
+		var values = this.getValues(item,attribute);
+		for(var i = 0; i < values.length; i++){
+			if(values[i] === value){
+				return true;
+			}
+		}
+		return false;
+	},
+
+	getValues: function(item, attribute){
+		//	summary: 
+		//      See dojo.data.api.Read.getValue()
+
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		var value = this.processItem(item, attribute);
+		if(value){
+			return [value];
+		}
+		return undefined;
+	},
+
+	isItem: function(item){
+		//	summary: 
+		//      See dojo.data.api.Read.isItem()
+		if(item && item[this._storeRef] === this){
+			return true;
+		}
+		return false;
+	},
+	
+	close: function(request){
+		//	summary: 
+		//      See dojo.data.api.Read.close()
+	},
+	
+	process: function(data){
+		// This should return an array of items.  This would be the function to override if the 
+		// developer wanted to customize the processing/parsing of the entire batch of search
+		// results.
+		return this["_processOSD"+this.contentType](data);
+	},
+	
+	processItem: function(item, attribute){
+		// This returns the text that represents the item.  If a developer wanted to customize 
+		// how an individual item is rendered/parsed, they'd override this function.
+		return this["_processItem"+this.contentType](item.node, attribute);
+	},
+	
+	_createSearchUrl: function(request){
+		var template = this.urlElement.attributes.getNamedItem("template").nodeValue;
+		var attrs = this.urlElement.attributes;
+		var index = template.indexOf("{searchTerms}");
+		template = template.substring(0, index) + request.query.searchTerms + template.substring(index+13);
+		
+		dojo.forEach([	{'name': 'count', 'test': request.count, 'def': '10'},
+						{'name': 'startIndex', 'test': request.start, 'def': this.urlElement.attributes.getNamedItem("indexOffset")?this.urlElement.attributes.getNamedItem("indexOffset").nodeValue:0},
+						{'name': 'startPage', 'test': request.startPage, 'def': this.urlElement.attributes.getNamedItem("pageOffset")?this.urlElement.attributes.getNamedItem("pageOffset").nodeValue:0},
+						{'name': 'language', 'test': request.language, 'def': "*"},
+						{'name': 'inputEncoding', 'test': request.inputEncoding, 'def': 'UTF-8'},
+						{'name': 'outputEncoding', 'test': request.outputEncoding, 'def': 'UTF-8'}
+					], function(item){
+			template = template.replace('{'+item.name+'}', item.test || item.def);
+			template = template.replace('{'+item.name+'?}', item.test || item.def);
+		});
+		return template;
+	},
+
+	_fetchItems: function(request, fetchHandler, errorHandler){
+		//	summary:
+		//		Fetch OpenSearch items that match to a query
+		//	request:
+		//		A request object
+		//	fetchHandler:
+		//		A function to call for fetched items
+		//	errorHandler:
+		//		A function to call on error
+
+		if(!request.query){
+			request.query={};
+		}
+
+		//Build up the content using information from the request 
+		var self = this;
+		var url = this._createSearchUrl(request);
+		var getArgs = {
+			url: url,
+			preventCache: this.urlPreventCache
+		};
+
+		// Change to fetch the query results.
+		var xhr = dojo.xhrGet(getArgs);
+
+		xhr.addErrback(function(error){
+			errorHandler(error, request);
+		});
+
+		xhr.addCallback(function(data){
+			var items = [];
+			if(data){
+				//Process the items...
+				items = self.process(data);
+				for(var i=0; i < items.length; i++){
+					items[i] = {node: items[i]};
+					items[i][self._storeRef] = self;
+				}
+			}
+			fetchHandler(items, request);
+		});
+	},
+	
+	_processOSDxml: function(data){
+		var div = dojo.doc.createElement("div");
+		div.innerHTML = data;
+		return dojo.query(this.itemPath, div);
+	},
+	
+	_processItemxml: function(item, attribute){
+		if(attribute === "content"){
+			return item.innerHTML;
+		}
+		return undefined;
+	},
+	
+	_processOSDatom: function(data){
+		return this._processOSDfeed(data, "entry");
+	},
+
+	_processItematom: function(item, attribute){
+		return this._processItemfeed(item, attribute, "content");
+	},
+
+	_processOSDrss: function(data){
+		return this._processOSDfeed(data, "item");
+	},
+
+	_processItemrss: function(item, attribute){
+		return this._processItemfeed(item, attribute, "description");
+	},
+
+	_processOSDfeed: function(data, type){
+		data = dojox.xml.parser.parse(data);
+		var items = [];
+		var nodeList = data.getElementsByTagName(type);
+		for(var i=0; i<nodeList.length; i++){
+			items.push(nodeList.item(i));
+		}
+		return items;
+	},
+
+	_processItemfeed: function(item, attribute, type){
+		if(attribute === "content"){
+			var content = item.getElementsByTagName(type).item(0);
+			return this._getNodeXml(content, true);
+		}
+		return undefined;
+	},
+	
+	_getNodeXml: function(node, skipFirst){
+		var i;
+		switch(node.nodeType){
+			case 1:
+				var xml = [];
+				if(!skipFirst){
+					xml.push("<"+node.tagName);
+					var attr;
+					for(i=0; i<node.attributes.length; i++){
+						attr = node.attributes.item(i);
+						xml.push(" "+attr.nodeName+"=\""+attr.nodeValue+"\"");
+					}
+					xml.push(">");
+				}
+				for(i=0; i<node.childNodes.length; i++){
+					xml.push(this._getNodeXml(node.childNodes.item(i)));
+				}
+				if(!skipFirst){
+					xml.push("</"+node.tagName+">\n");
+				}
+				return xml.join("");
+			case 3:
+			case 4:
+				return node.nodeValue;
+		}
+		return undefined;
+	},
+
+	_processOsdd: function(doc){
+		var urlnodes = doc.getElementsByTagName("Url");
+		//TODO: Check all the urlnodes and determine what our best one is...
+		var types = [];
+		var contentType;
+		var i;
+		for(i=0; i<urlnodes.length; i++){
+			contentType = urlnodes[i].attributes.getNamedItem("type").nodeValue;
+			switch(contentType){
+				case "application/rss+xml":
+					types[i] = this.RSS_CONTENT_TYPE;
+					break;
+				case "application/atom+xml":
+					types[i] = this.ATOM_CONTENT_TYPE;
+					break;
+				default:
+					types[i] = this.XML_CONTENT_TYPE;
+					break;
+			}
+		}
+		var index = 0;
+		var currentType = types[0];
+		for(i=1; i<urlnodes.length; i++){
+			if(types[i]>currentType){
+				index = i;
+				currentType = types[i];
+			}
+		}
+
+		// We'll be using urlnodes[index] as it's the best option (ATOM > RSS > XML)
+		var label = urlnodes[index].nodeName.toLowerCase();
+		if(label == 'url'){
+			var urlattrs = urlnodes[index].attributes;
+			this.urlElement = urlnodes[index];
+			switch(types[index]){
+				case this.ATOM_CONTENT_TYPE:
+					this.contentType = this.ATOM_CONTENT_TYPE_STRING;
+					break;
+				case this.RSS_CONTENT_TYPE:
+					this.contentType = this.RSS_CONTENT_TYPE_STRING;
+					break;
+				case this.XML_CONTENT_TYPE:
+					this.contentType = this.XML_CONTENT_TYPE_STRING;
+					break;
+			}
+		} 
+	}
 });
-},_processOSDxml:function(_29){
-var div=dojo.doc.createElement("div");
-div.innerHTML=_29;
-return dojo.query(this.itemPath,div);
-},_processItemxml:function(_2a,_2b){
-if(_2b==="content"){
-return _2a.innerHTML;
-}
-return undefined;
-},_processOSDatom:function(_2c){
-return this._processOSDfeed(_2c,"entry");
-},_processItematom:function(_2d,_2e){
-return this._processItemfeed(_2d,_2e,"content");
-},_processOSDrss:function(_2f){
-return this._processOSDfeed(_2f,"item");
-},_processItemrss:function(_30,_31){
-return this._processItemfeed(_30,_31,"description");
-},_processOSDfeed:function(_32,_33){
-_32=dojox.xml.parser.parse(_32);
-var _34=[];
-var _35=_32.getElementsByTagName(_33);
-for(var i=0;i<_35.length;i++){
-_34.push(_35.item(i));
-}
-return _34;
-},_processItemfeed:function(_36,_37,_38){
-if(_37==="content"){
-var _39=_36.getElementsByTagName(_38).item(0);
-return this._getNodeXml(_39,true);
-}
-return undefined;
-},_getNodeXml:function(_3a,_3b){
-var i;
-switch(_3a.nodeType){
-case 1:
-var xml=[];
-if(!_3b){
-xml.push("<"+_3a.tagName);
-var _3c;
-for(i=0;i<_3a.attributes.length;i++){
-_3c=_3a.attributes.item(i);
-xml.push(" "+_3c.nodeName+"=\""+_3c.nodeValue+"\"");
-}
-xml.push(">");
-}
-for(i=0;i<_3a.childNodes.length;i++){
-xml.push(this._getNodeXml(_3a.childNodes.item(i)));
-}
-if(!_3b){
-xml.push("</"+_3a.tagName+">\n");
-}
-return xml.join("");
-case 3:
-case 4:
-return _3a.nodeValue;
-}
-return undefined;
-},_processOsdd:function(doc){
-var _3d=doc.getElementsByTagName("Url");
-var _3e=[];
-var _3f;
-var i;
-for(i=0;i<_3d.length;i++){
-_3f=_3d[i].attributes.getNamedItem("type").nodeValue;
-switch(_3f){
-case "application/rss+xml":
-_3e[i]=this.RSS_CONTENT_TYPE;
-break;
-case "application/atom+xml":
-_3e[i]=this.ATOM_CONTENT_TYPE;
-break;
-default:
-_3e[i]=this.XML_CONTENT_TYPE;
-break;
-}
-}
-var _40=0;
-var _41=_3e[0];
-for(i=1;i<_3d.length;i++){
-if(_3e[i]>_41){
-_40=i;
-_41=_3e[i];
-}
-}
-var _42=_3d[_40].nodeName.toLowerCase();
-if(_42=="url"){
-var _43=_3d[_40].attributes;
-this.urlElement=_3d[_40];
-switch(_3e[_40]){
-case this.ATOM_CONTENT_TYPE:
-this.contentType=this.ATOM_CONTENT_TYPE_STRING;
-break;
-case this.RSS_CONTENT_TYPE:
-this.contentType=this.RSS_CONTENT_TYPE_STRING;
-break;
-case this.XML_CONTENT_TYPE:
-this.contentType=this.XML_CONTENT_TYPE_STRING;
-break;
-}
-}
-}});
 dojo.extend(dojox.data.OpenSearchStore,dojo.data.util.simpleFetch);
-}
diff --git a/dojox/data/OpmlStore.js b/dojox/data/OpmlStore.js
index 2972b58..280aa2c 100644
--- a/dojox/data/OpmlStore.js
+++ b/dojox/data/OpmlStore.js
@@ -1,329 +1,523 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.OpmlStore"]){
-dojo._hasResource["dojox.data.OpmlStore"]=true;
 dojo.provide("dojox.data.OpmlStore");
+
 dojo.require("dojo.data.util.filter");
 dojo.require("dojo.data.util.simpleFetch");
-dojo.declare("dojox.data.OpmlStore",null,{constructor:function(_1){
-this._xmlData=null;
-this._arrayOfTopLevelItems=[];
-this._arrayOfAllItems=[];
-this._metadataNodes=null;
-this._loadFinished=false;
-this.url=_1.url;
-this._opmlData=_1.data;
-if(_1.label){
-this.label=_1.label;
-}
-this._loadInProgress=false;
-this._queuedFetches=[];
-this._identityMap={};
-this._identCount=0;
-this._idProp="_I";
-if(_1&&"urlPreventCache" in _1){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-},label:"text",url:"",urlPreventCache:false,_assertIsItem:function(_2){
-if(!this.isItem(_2)){
-throw new Error("dojo.data.OpmlStore: a function was passed an item argument that was not an item");
-}
-},_assertIsAttribute:function(_3){
-if(!dojo.isString(_3)){
-throw new Error("dojox.data.OpmlStore: a function was passed an attribute argument that was not an attribute object nor an attribute name string");
-}
-},_removeChildNodesThatAreNotElementNodes:function(_4,_5){
-var _6=_4.childNodes;
-if(_6.length===0){
-return;
-}
-var _7=[];
-var i,_8;
-for(i=0;i<_6.length;++i){
-_8=_6[i];
-if(_8.nodeType!=1){
-_7.push(_8);
-}
-}
-for(i=0;i<_7.length;++i){
-_8=_7[i];
-_4.removeChild(_8);
-}
-if(_5){
-for(i=0;i<_6.length;++i){
-_8=_6[i];
-this._removeChildNodesThatAreNotElementNodes(_8,_5);
-}
-}
-},_processRawXmlTree:function(_9){
-this._loadFinished=true;
-this._xmlData=_9;
-var _a=_9.getElementsByTagName("head");
-var _b=_a[0];
-if(_b){
-this._removeChildNodesThatAreNotElementNodes(_b);
-this._metadataNodes=_b.childNodes;
-}
-var _c=_9.getElementsByTagName("body");
-var _d=_c[0];
-if(_d){
-this._removeChildNodesThatAreNotElementNodes(_d,true);
-var _e=_c[0].childNodes;
-for(var i=0;i<_e.length;++i){
-var _f=_e[i];
-if(_f.tagName=="outline"){
-this._identityMap[this._identCount]=_f;
-this._identCount++;
-this._arrayOfTopLevelItems.push(_f);
-this._arrayOfAllItems.push(_f);
-this._checkChildNodes(_f);
-}
-}
-}
-},_checkChildNodes:function(_10){
-if(_10.firstChild){
-for(var i=0;i<_10.childNodes.length;i++){
-var _11=_10.childNodes[i];
-if(_11.tagName=="outline"){
-this._identityMap[this._identCount]=_11;
-this._identCount++;
-this._arrayOfAllItems.push(_11);
-this._checkChildNodes(_11);
-}
-}
-}
-},_getItemsArray:function(_12){
-if(_12&&_12.deep){
-return this._arrayOfAllItems;
-}
-return this._arrayOfTopLevelItems;
-},getValue:function(_13,_14,_15){
-this._assertIsItem(_13);
-this._assertIsAttribute(_14);
-if(_14=="children"){
-return (_13.firstChild||_15);
-}else{
-var _16=_13.getAttribute(_14);
-return (_16!==undefined)?_16:_15;
-}
-},getValues:function(_17,_18){
-this._assertIsItem(_17);
-this._assertIsAttribute(_18);
-var _19=[];
-if(_18=="children"){
-for(var i=0;i<_17.childNodes.length;++i){
-_19.push(_17.childNodes[i]);
-}
-}else{
-if(_17.getAttribute(_18)!==null){
-_19.push(_17.getAttribute(_18));
-}
-}
-return _19;
-},getAttributes:function(_1a){
-this._assertIsItem(_1a);
-var _1b=[];
-var _1c=_1a;
-var _1d=_1c.attributes;
-for(var i=0;i<_1d.length;++i){
-var _1e=_1d.item(i);
-_1b.push(_1e.nodeName);
-}
-if(_1c.childNodes.length>0){
-_1b.push("children");
-}
-return _1b;
-},hasAttribute:function(_1f,_20){
-return (this.getValues(_1f,_20).length>0);
-},containsValue:function(_21,_22,_23){
-var _24=undefined;
-if(typeof _23==="string"){
-_24=dojo.data.util.filter.patternToRegExp(_23,false);
-}
-return this._containsValue(_21,_22,_23,_24);
-},_containsValue:function(_25,_26,_27,_28){
-var _29=this.getValues(_25,_26);
-for(var i=0;i<_29.length;++i){
-var _2a=_29[i];
-if(typeof _2a==="string"&&_28){
-return (_2a.match(_28)!==null);
-}else{
-if(_27===_2a){
-return true;
-}
-}
-}
-return false;
-},isItem:function(_2b){
-return (_2b&&_2b.nodeType==1&&_2b.tagName=="outline"&&_2b.ownerDocument===this._xmlData);
-},isItemLoaded:function(_2c){
-return this.isItem(_2c);
-},loadItem:function(_2d){
-},getLabel:function(_2e){
-if(this.isItem(_2e)){
-return this.getValue(_2e,this.label);
-}
-return undefined;
-},getLabelAttributes:function(_2f){
-return [this.label];
-},_fetchItems:function(_30,_31,_32){
-var _33=this;
-var _34=function(_35,_36){
-var _37=null;
-if(_35.query){
-_37=[];
-var _38=_35.queryOptions?_35.queryOptions.ignoreCase:false;
-var _39={};
-for(var key in _35.query){
-var _3a=_35.query[key];
-if(typeof _3a==="string"){
-_39[key]=dojo.data.util.filter.patternToRegExp(_3a,_38);
-}
-}
-for(var i=0;i<_36.length;++i){
-var _3b=true;
-var _3c=_36[i];
-for(var key in _35.query){
-var _3a=_35.query[key];
-if(!_33._containsValue(_3c,key,_3a,_39[key])){
-_3b=false;
-}
-}
-if(_3b){
-_37.push(_3c);
-}
-}
-}else{
-if(_36.length>0){
-_37=_36.slice(0,_36.length);
-}
-}
-_31(_37,_35);
-};
-if(this._loadFinished){
-_34(_30,this._getItemsArray(_30.queryOptions));
-}else{
-if(this._loadInProgress){
-this._queuedFetches.push({args:_30,filter:_34});
-}else{
-if(this.url!==""){
-this._loadInProgress=true;
-var _3d={url:_33.url,handleAs:"xml",preventCache:_33.urlPreventCache};
-var _3e=dojo.xhrGet(_3d);
-_3e.addCallback(function(_3f){
-_33._processRawXmlTree(_3f);
-_34(_30,_33._getItemsArray(_30.queryOptions));
-_33._handleQueuedFetches();
-});
-_3e.addErrback(function(_40){
-throw _40;
-});
-}else{
-if(this._opmlData){
-this._processRawXmlTree(this._opmlData);
-this._opmlData=null;
-_34(_30,this._getItemsArray(_30.queryOptions));
-}else{
-throw new Error("dojox.data.OpmlStore: No OPML source data was provided as either URL or XML data input.");
-}
-}
-}
-}
-},getFeatures:function(){
-var _41={"dojo.data.api.Read":true,"dojo.data.api.Identity":true};
-return _41;
-},getIdentity:function(_42){
-if(this.isItem(_42)){
-for(var i in this._identityMap){
-if(this._identityMap[i]===_42){
-return i;
-}
-}
-}
-return null;
-},fetchItemByIdentity:function(_43){
-if(!this._loadFinished){
-var _44=this;
-if(this.url!==""){
-if(this._loadInProgress){
-this._queuedFetches.push({args:_43});
-}else{
-this._loadInProgress=true;
-var _45={url:_44.url,handleAs:"xml"};
-var _46=dojo.xhrGet(_45);
-_46.addCallback(function(_47){
-var _48=_43.scope?_43.scope:dojo.global;
-try{
-_44._processRawXmlTree(_47);
-var _49=_44._identityMap[_43.identity];
-if(!_44.isItem(_49)){
-_49=null;
-}
-if(_43.onItem){
-_43.onItem.call(_48,_49);
-}
-_44._handleQueuedFetches();
-}
-catch(error){
-if(_43.onError){
-_43.onError.call(_48,error);
-}
-}
-});
-_46.addErrback(function(_4a){
-this._loadInProgress=false;
-if(_43.onError){
-var _4b=_43.scope?_43.scope:dojo.global;
-_43.onError.call(_4b,_4a);
-}
+
+dojo.declare("dojox.data.OpmlStore", null, {
+	/* summary:
+	 *   The OpmlStore implements the dojo.data.api.Read API.  
+	 */
+	 
+	/* examples:
+	 *   var opmlStore = new dojo.data.OpmlStore({url:"geography.xml"});
+	 *   var opmlStore = new dojo.data.OpmlStore({url:"http://example.com/geography.xml"});
+	 */
+	constructor: function(/* Object */ keywordParameters){
+		// summary: constructor
+		// keywordParameters: {url: String, label: String}  Where label is optional and configures what should be used as the return from getLabel()
+		this._xmlData = null;
+		this._arrayOfTopLevelItems = [];
+		this._arrayOfAllItems = [];
+		this._metadataNodes = null;
+		this._loadFinished = false;
+		this.url = keywordParameters.url;
+		this._opmlData = keywordParameters.data; // XML DOM Document
+		if(keywordParameters.label){
+			this.label = keywordParameters.label;
+		}
+		this._loadInProgress = false;	//Got to track the initial load to prevent duelling loads of the dataset.
+		this._queuedFetches = [];
+		this._identityMap = {};
+		this._identCount = 0;
+		this._idProp = "_I";
+		if(keywordParameters && "urlPreventCache" in keywordParameters){
+			this.urlPreventCache = keywordParameters.urlPreventCache?true:false;
+		}
+	},
+
+	// label: [public] string
+	//		The attribute of the Opml item to act as a label.
+	label: "text",
+
+	// url: [public] string
+	//		The location from which to fetch the Opml document.
+	url: "",
+
+	// urlPreventCache: [public] boolean
+	//		Flag to denote if the underlying xhrGet call should set preventCache.
+	urlPreventCache: false,
+
+	_assertIsItem: function(/* item */ item){
+		if(!this.isItem(item)){ 
+			throw new Error("dojo.data.OpmlStore: a function was passed an item argument that was not an item");
+		}
+	},
+	
+	_assertIsAttribute: function(/* item || 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(!dojo.isString(attribute)){
+			throw new Error("dojox.data.OpmlStore: a function was passed an attribute argument that was not an attribute object nor an attribute name string");
+		}
+	},
+	
+	_removeChildNodesThatAreNotElementNodes: function(/* node */ node, /* boolean */ recursive){
+		var childNodes = node.childNodes;
+		if(childNodes.length === 0){
+			return;
+		}
+		var nodesToRemove = [];
+		var i, childNode;
+		for(i = 0; i < childNodes.length; ++i){
+			childNode = childNodes[i];
+			if(childNode.nodeType != 1){ 
+				nodesToRemove.push(childNode); 
+			}
+		}
+		for(i = 0; i < nodesToRemove.length; ++i){
+			childNode = nodesToRemove[i];
+			node.removeChild(childNode);
+		}
+		if(recursive){
+			for(i = 0; i < childNodes.length; ++i){
+				childNode = childNodes[i];
+				this._removeChildNodesThatAreNotElementNodes(childNode, recursive);
+			}
+		}
+	},
+	
+	_processRawXmlTree: function(/* xmlDoc */ rawXmlTree){
+		this._loadFinished = true;
+		this._xmlData = rawXmlTree;
+		var headNodes = rawXmlTree.getElementsByTagName('head');
+		var headNode = headNodes[0];
+		if(headNode){
+			this._removeChildNodesThatAreNotElementNodes(headNode);
+			this._metadataNodes = headNode.childNodes;
+		}
+		var bodyNodes = rawXmlTree.getElementsByTagName('body');
+		var bodyNode = bodyNodes[0];
+		if(bodyNode){
+			this._removeChildNodesThatAreNotElementNodes(bodyNode, true);
+			
+			var bodyChildNodes = bodyNodes[0].childNodes;
+			for(var i = 0; i < bodyChildNodes.length; ++i){
+				var node = bodyChildNodes[i];
+				if(node.tagName == 'outline'){
+					this._identityMap[this._identCount] = node;
+					this._identCount++;
+					this._arrayOfTopLevelItems.push(node);
+					this._arrayOfAllItems.push(node);
+					this._checkChildNodes(node);
+				}
+			}
+		}
+	},
+
+	_checkChildNodes: function(node /*Node*/){
+		//	summary:
+		//		Internal function to recurse over all child nodes from the store and add them
+		//		As non-toplevel items
+		//	description:
+		//		Internal function to recurse over all child nodes from the store and add them
+		//		As non-toplevel items
+		//
+		//	node:
+		//		The child node to walk.
+		if(node.firstChild){
+			for(var i = 0; i < node.childNodes.length; i++){
+				var child = node.childNodes[i];
+				if(child.tagName == 'outline'){
+					this._identityMap[this._identCount] = child;
+					this._identCount++;
+					this._arrayOfAllItems.push(child);
+					this._checkChildNodes(child);
+				}
+			}
+		}
+	},
+
+	_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;
+	},
+
+/***************************************
+     dojo.data.api.Read API
+***************************************/
+	getValue: function( /* item */ item,
+						/* attribute || attribute-name-string */ attribute,
+						/* value? */ defaultValue){
+		//	summary: 
+		//      See dojo.data.api.Read.getValue()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		if(attribute == 'children'){
+			return (item.firstChild || defaultValue); //Object
+		}else{
+			var value = item.getAttribute(attribute);
+			return (value !== undefined) ? value : defaultValue; //Object
+		}
+	},
+	
+	getValues: function(/* item */ item,
+						/* attribute || attribute-name-string */ attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.getValues()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		var array = [];
+		if(attribute == 'children'){
+			for(var i = 0; i < item.childNodes.length; ++i){
+				array.push(item.childNodes[i]);
+			}
+		} else if(item.getAttribute(attribute) !== null){
+				array.push(item.getAttribute(attribute));
+		}
+		return array; // Array
+	},
+	
+	getAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getAttributes()
+		this._assertIsItem(item);
+		var attributes = [];
+		var xmlNode = item;
+		var xmlAttributes = xmlNode.attributes;
+		for(var i = 0; i < xmlAttributes.length; ++i){
+			var xmlAttribute = xmlAttributes.item(i);
+			attributes.push(xmlAttribute.nodeName);
+		}
+		if(xmlNode.childNodes.length > 0){
+			attributes.push('children');
+		}
+		return attributes; //Array
+	},
+	
+	hasAttribute: function( /* item */ item,
+							/* attribute || attribute-name-string */ attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.hasAttribute()
+		return (this.getValues(item, attribute).length > 0); //Boolean
+	},
+	
+	containsValue: function(/* item */ item, 
+							/* attribute || 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 || 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'
+		var values = this.getValues(item, attribute);
+		for(var i = 0; i < values.length; ++i){
+			var possibleValue = values[i];
+			if(typeof possibleValue === "string" && regexp){
+				return (possibleValue.match(regexp) !== null);
+			}else{
+				//Non-string matching.
+				if(value === possibleValue){
+					return true; // Boolean
+				}
+			}
+		}
+		return false; // Boolean
+	},
+			
+	isItem: function(/* anything */ something){
+		//	summary: 
+		//		See dojo.data.api.Read.isItem()
+		//	description:
+		//		Four things are verified to ensure that "something" is an item:
+		//		something can not be null, the nodeType must be an XML Element,
+		//		the tagName must be "outline", and the node must be a member of
+		//		XML document for this datastore. 
+		return (something && 
+				something.nodeType == 1 && 
+				something.tagName == 'outline' &&
+				something.ownerDocument === this._xmlData); //Boolean
+	},
+	
+	isItemLoaded: function(/* anything */ something){
+		//	summary: 
+		//		See dojo.data.api.Read.isItemLoaded()
+		// 		OpmlStore loads every item, so if it's an item, then it's loaded.
+		return this.isItem(something); //Boolean
+	},
+	
+	loadItem: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.loadItem()
+		//	description:
+		//		The OpmlStore always loads all items, so if it's an item, then it's loaded.
+		//		From the dojo.data.api.Read.loadItem docs:
+		//			If a call to isItemLoaded() returns true before loadItem() is even called,
+		//			then loadItem() need not do any work at all and will not even invoke the callback handlers.
+	},
+
+	getLabel: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabel()
+		if(this.isItem(item)){
+			return this.getValue(item,this.label); //String
+		}
+		return undefined; //undefined
+	},
+
+	getLabelAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabelAttributes()
+		return [this.label]; //array
+	},
+
+	// The dojo.data.api.Read.fetch() function is implemented as
+	// a mixin from dojo.data.util.simpleFetch.
+	// That mixin requires us to define _fetchItems().
+	_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 = null;
+			if(requestArgs.query){
+				items = [];
+				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(var key in requestArgs.query){
+					var value = requestArgs.query[key];
+					if(typeof value === "string"){
+						regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
+					}
+				}
+
+				for(var i = 0; i < arrayOfItems.length; ++i){
+					var match = true;
+					var candidateItem = arrayOfItems[i];
+					for(var key in requestArgs.query){
+						var value = requestArgs.query[key];
+						if(!self._containsValue(candidateItem, key, value, regexpList[key])){
+							match = false;
+						}
+					}
+					if(match){
+						items.push(candidateItem);
+					}
+				}
+			}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.
+				if(arrayOfItems.length> 0){
+					items = arrayOfItems.slice(0,arrayOfItems.length); 
+				}
+			}
+			findCallback(items, requestArgs);
+		};
+
+		if(this._loadFinished){
+			filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));
+		}else{
+
+			//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{
+				if(this.url !== ""){
+					this._loadInProgress = true;
+					var getArgs = {
+							url: self.url, 
+							handleAs: "xml",
+							preventCache: self.urlPreventCache
+						};
+					var getHandler = dojo.xhrGet(getArgs);
+					getHandler.addCallback(function(data){
+						self._processRawXmlTree(data);
+						filter(keywordArgs, self._getItemsArray(keywordArgs.queryOptions));
+						self._handleQueuedFetches();
+					});
+					getHandler.addErrback(function(error){
+						throw error;
+					});
+				}else if(this._opmlData){
+					this._processRawXmlTree(this._opmlData);
+					this._opmlData = null;
+					filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));
+				}else{
+					throw new Error("dojox.data.OpmlStore: No OPML source data was provided as either URL or XML data input.");
+				}
+			}
+		}
+	},
+	
+	getFeatures: function(){
+		// summary: See dojo.data.api.Read.getFeatures()
+		var features = {
+			'dojo.data.api.Read': true,
+			'dojo.data.api.Identity': true
+		};
+		return features; //Object
+	},
+
+/***************************************
+     dojo.data.api.Identity API
+***************************************/
+	getIdentity: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Identity.getIdentity()
+		if(this.isItem(item)){
+			//No ther way to do this other than O(n) without
+			//complete rework of how the tree stores nodes.
+			for(var i in this._identityMap){
+				if(this._identityMap[i] === item){
+					return i;
+				}
+			}
+		}
+		return null; //null
+	},
+
+	fetchItemByIdentity: function(/* Object */ keywordArgs){
+		//	summary: 
+		//		See dojo.data.api.Identity.fetchItemByIdentity()
+
+		//Hasn't loaded yet, we have to trigger the load.
+		if(!this._loadFinished){
+			var self = this;
+			if(this.url !== ""){
+				//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});
+				}else{
+					this._loadInProgress = true;
+					var getArgs = {
+							url: self.url, 
+							handleAs: "xml"
+						};
+					var getHandler = dojo.xhrGet(getArgs);
+					getHandler.addCallback(function(data){
+						var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+						try{
+							self._processRawXmlTree(data);
+							var item = self._identityMap[keywordArgs.identity];
+							if(!self.isItem(item)){
+								item = null;
+							}
+							if(keywordArgs.onItem){
+								keywordArgs.onItem.call(scope, item);
+							}
+							self._handleQueuedFetches();
+						}catch(error){
+							if(keywordArgs.onError){
+								keywordArgs.onError.call(scope, error);
+							}
+						}
+					});
+					getHandler.addErrback(function(error){
+						this._loadInProgress = false;
+						if(keywordArgs.onError){
+							var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+							keywordArgs.onError.call(scope, error);
+						}
+					});
+				}
+			}else if(this._opmlData){
+				this._processRawXmlTree(this._opmlData);
+				this._opmlData = null;
+				var item = this._identityMap[keywordArgs.identity];
+				if(!self.isItem(item)){
+					item = null;
+				}
+				if(keywordArgs.onItem){
+					var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+					keywordArgs.onItem.call(scope, item);
+				}
+			}
+		}else{
+			//Already loaded.  We can just look it up and call back.
+			var item = this._identityMap[keywordArgs.identity];
+			if(!this.isItem(item)){
+				item = null;
+			}
+			if(keywordArgs.onItem){
+				var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
+				keywordArgs.onItem.call(scope, item);
+			}
+		}
+	},
+
+	getIdentityAttributes: function(/* item */ item){
+		 //	summary: 
+		 //		See dojo.data.api.Identity.getIdentifierAttributes()
+		 
+		 //Identity isn't a public attribute in the item, it's the node count.
+		 //So, return null.
+		 return null;
+	},
+
+	_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 = [];
+		}
+	},
+
+	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+		 //	summary: 
+		 //		See dojo.data.api.Read.close()
+	}
 });
-}
-}else{
-if(this._opmlData){
-this._processRawXmlTree(this._opmlData);
-this._opmlData=null;
-var _4c=this._identityMap[_43.identity];
-if(!_44.isItem(_4c)){
-_4c=null;
-}
-if(_43.onItem){
-var _4d=_43.scope?_43.scope:dojo.global;
-_43.onItem.call(_4d,_4c);
-}
-}
-}
-}else{
-var _4c=this._identityMap[_43.identity];
-if(!this.isItem(_4c)){
-_4c=null;
-}
-if(_43.onItem){
-var _4d=_43.scope?_43.scope:dojo.global;
-_43.onItem.call(_4d,_4c);
-}
-}
-},getIdentityAttributes:function(_4e){
-return null;
-},_handleQueuedFetches:function(){
-if(this._queuedFetches.length>0){
-for(var i=0;i<this._queuedFetches.length;i++){
-var _4f=this._queuedFetches[i];
-var _50=_4f.args;
-var _51=_4f.filter;
-if(_51){
-_51(_50,this._getItemsArray(_50.queryOptions));
-}else{
-this.fetchItemByIdentity(_50);
-}
-}
-this._queuedFetches=[];
-}
-},close:function(_52){
-}});
+//Mix in the simple fetch implementation to this class.
 dojo.extend(dojox.data.OpmlStore,dojo.data.util.simpleFetch);
-}
+	
diff --git a/dojox/data/PersevereStore.js b/dojox/data/PersevereStore.js
index 87f8e9a..fd4d243 100644
--- a/dojox/data/PersevereStore.js
+++ b/dojox/data/PersevereStore.js
@@ -1,78 +1,110 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.PersevereStore"]){
-dojo._hasResource["dojox.data.PersevereStore"]=true;
 dojo.provide("dojox.data.PersevereStore");
 dojo.require("dojox.data.JsonQueryRestStore");
-dojo.require("dojox.rpc.Client");
-dojox.json.ref.serializeFunctions=true;
-dojo.declare("dojox.data.PersevereStore",dojox.data.JsonQueryRestStore,{useFullIdInQueries:true,jsonQueryPagination:false});
-dojox.data.PersevereStore.getStores=function(_1,_2){
-_1=(_1&&(_1.match(/\/$/)?_1:(_1+"/")))||"/";
-if(_1.match(/^\w*:\/\//)){
-dojo.require("dojox.io.xhrScriptPlugin");
-dojox.io.xhrScriptPlugin(_1,"callback",dojox.io.xhrPlugins.fullHttpAdapter);
-}
-var _3=dojo.xhr;
-dojo.xhr=function(_4,_5){
-(_5.headers=_5.headers||{})["Server-Methods"]=false;
-return _3.apply(dojo,arguments);
-};
-var _6=dojox.rpc.Rest(_1,true);
-dojox.rpc._sync=_2;
-var _7=_6("Class/");
-var _8;
-var _9={};
-var _a=0;
-_7.addCallback(function(_b){
-dojox.json.ref.resolveJson(_b,{index:dojox.rpc.Rest._index,idPrefix:"/Class/",assignAbsoluteIds:true});
-function _c(_d){
-if(_d["extends"]&&_d["extends"].prototype){
-if(!_d.prototype||!_d.prototype.isPrototypeOf(_d["extends"].prototype)){
-_c(_d["extends"]);
-dojox.rpc.Rest._index[_d.prototype.__id]=_d.prototype=dojo.mixin(dojo.delegate(_d["extends"].prototype),_d.prototype);
-}
-}
-};
-function _e(_f,_10){
-if(_f&&_10){
-for(var j in _f){
-var _11=_f[j];
-if(_11.runAt!="client"&&!_10[j]){
-_10[j]=(function(_12){
-return function(){
-var _13=dojo.rawXhrPost({url:this.__id,postData:dojo.toJson({method:_12,id:_a++,params:dojo._toArray(arguments)}),handleAs:"json"});
-_13.addCallback(function(_14){
-return _14.error?new Error(_14.error):_14.result;
-});
-return _13;
-};
-})(j);
-}
-}
-}
-};
-for(var i in _b){
-if(typeof _b[i]=="object"){
-var _15=_b[i];
-_c(_15);
-_e(_15.methods,_15.prototype=_15.prototype||{});
-_e(_15.staticMethods,_15);
-_9[_b[i].id]=new dojox.data.PersevereStore({target:new dojo._Url(_1,_b[i].id)+"/",schema:_15});
-}
-}
-return (_8=_9);
+dojo.require("dojox.rpc.Client"); // Persevere supports this and it improves reliability
+
+// PersevereStore is an extension of JsonRestStore to handle Persevere's special features
+
+dojox.json.ref.serializeFunctions = true; // Persevere supports persisted functions
+
+dojo.declare("dojox.data.PersevereStore",dojox.data.JsonQueryRestStore,{
+	useFullIdInQueries: true, // in JSONQuerys use the full id
+	jsonQueryPagination: false // use the Range headers instead	
 });
-dojo.xhr=_3;
-return _2?_8:_7;
+	
+dojox.data.PersevereStore.getStores = function(/*String?*/path,/*Boolean?*/sync){
+	// summary:
+	//		Creates Dojo data stores for all the table/classes on a Persevere server
+	// path:
+	// 		URL of the Persevere server's root, this normally just "/"
+	// 		which is the default value if the target is not provided
+	// sync:
+	// 		Indicates that the operation should happen synchronously.
+	// return:
+	// 		A map/object of datastores will be returned if it is performed asynchronously,
+	// 		otherwise it will return a Deferred object that will provide the map/object.
+	// 		The name of each property is a the name of a store,
+	// 		and the value is the actual data store object.
+	path = (path && (path.match(/\/$/) ? path : (path + '/'))) || '/';
+	if(path.match(/^\w*:\/\//)){
+		// if it is cross-domain, we will use window.name for communication
+		dojo.require("dojox.io.xhrScriptPlugin");
+		dojox.io.xhrScriptPlugin(path, "callback", dojox.io.xhrPlugins.fullHttpAdapter);
+	}
+	var plainXhr = dojo.xhr;
+	dojo.xhr = function(method,args){
+		(args.headers = args.headers || {})['Server-Methods'] = "false";
+		return plainXhr.apply(dojo,arguments);
+	}
+	var rootService= dojox.rpc.Rest(path,true);
+	dojox.rpc._sync = sync;
+	var dfd = rootService("Class/");//dojo.xhrGet({url: target, sync:!callback, handleAs:'json'});
+	var results;
+	var stores = {};
+	var callId = 0;
+	dfd.addCallback(function(schemas){
+		dojox.json.ref.resolveJson(schemas, {
+			index: dojox.rpc.Rest._index,
+			idPrefix: "/Class/",
+			assignAbsoluteIds: true
+		});
+		function setupHierarchy(schema){
+			if(schema['extends'] && schema['extends'].prototype){
+				if(!schema.prototype || !schema.prototype.isPrototypeOf(schema['extends'].prototype)){
+					setupHierarchy(schema['extends']);
+					dojox.rpc.Rest._index[schema.prototype.__id] = schema.prototype = dojo.mixin(dojo.delegate(schema['extends'].prototype), schema.prototype);
+				}
+			}
+		}
+		function setupMethods(methodsDefinitions, methodsTarget){
+			if(methodsDefinitions && methodsTarget){
+				for(var j in methodsDefinitions){
+					var methodDef = methodsDefinitions[j];
+					// if any method definitions indicate that the method should run on the server, than add 
+					// it to the prototype as a JSON-RPC method
+					if(methodDef.runAt != "client" && !methodsTarget[j]){
+						methodsTarget[j] = (function(methodName){
+							return function(){
+								// execute a JSON-RPC call
+								var deferred = dojo.rawXhrPost({
+									url: this.__id,
+									// the JSON-RPC call
+									postData: dojo.toJson({
+										method: methodName,
+										id: callId++,
+										params: dojo._toArray(arguments)
+									}),
+									handleAs: "json"
+								});
+								deferred.addCallback(function(response){
+									// handle the response
+									return response.error ?
+										new Error(response.error) :
+										response.result;
+								});
+								return deferred;
+							}
+						})(j);	
+					}
+				}
+			}
+		}
+		for(var i in schemas){
+			if(typeof schemas[i] == 'object'){
+				var schema = schemas[i];
+				setupHierarchy(schema);
+				setupMethods(schema.methods, schema.prototype = schema.prototype || {});
+				setupMethods(schema.staticMethods, schema);
+				stores[schemas[i].id] = new dojox.data.PersevereStore({target:new dojo._Url(path,schemas[i].id) + '/',schema:schema});
+			}
+		}
+		return (results = stores);
+	});
+	dojo.xhr = plainXhr;
+	return sync ? results : dfd;
 };
-dojox.data.PersevereStore.addProxy=function(){
-dojo.require("dojox.io.xhrPlugins");
-dojox.io.xhrPlugins.addProxy("/proxy/");
+dojox.data.PersevereStore.addProxy = function(){
+	// summary:
+	//		Invokes the XHR proxy plugin. Call this if you will be using x-site data.
+	dojo.require("dojox.io.xhrPlugins"); // also not necessary, but we can register that Persevere supports proxying
+	dojox.io.xhrPlugins.addProxy("/proxy/");
 };
-}
diff --git a/dojox/data/PicasaStore.js b/dojox/data/PicasaStore.js
index 473dbb3..4b5bc1f 100644
--- a/dojox/data/PicasaStore.js
+++ b/dojox/data/PicasaStore.js
@@ -1,172 +1,272 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.PicasaStore"]){
-dojo._hasResource["dojox.data.PicasaStore"]=true;
 dojo.provide("dojox.data.PicasaStore");
+
 dojo.require("dojo.data.util.simpleFetch");
 dojo.require("dojo.io.script");
 dojo.require("dojo.date.stamp");
-dojo.declare("dojox.data.PicasaStore",null,{constructor:function(_1){
-if(_1&&_1.label){
-this.label=_1.label;
-}
-if(_1&&"urlPreventCache" in _1){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-if(_1&&"maxResults" in _1){
-this.maxResults=parseInt(_1.maxResults);
-if(!this.maxResults){
-this.maxResults=20;
-}
-}
-},_picasaUrl:"http://picasaweb.google.com/data/feed/api/all",_storeRef:"_S",label:"title",urlPreventCache:false,maxResults:20,_assertIsItem:function(_2){
-if(!this.isItem(_2)){
-throw new Error("dojox.data.PicasaStore: a function was passed an item argument that was not an item");
-}
-},_assertIsAttribute:function(_3){
-if(typeof _3!=="string"){
-throw new Error("dojox.data.PicasaStore: a function was passed an attribute argument that was not an attribute name string");
-}
-},getFeatures:function(){
-return {"dojo.data.api.Read":true};
-},getValue:function(_4,_5,_6){
-var _7=this.getValues(_4,_5);
-if(_7&&_7.length>0){
-return _7[0];
-}
-return _6;
-},getAttributes:function(_8){
-return ["id","published","updated","category","title$type","title","summary$type","summary","rights$type","rights","link","author","gphoto$id","gphoto$name","location","imageUrlSmall","imageUrlMedium","imageUrl","datePublished","dateTaken","description"];
-},hasAttribute:function(_9,_a){
-if(this.getValue(_9,_a)){
-return true;
-}
-return false;
-},isItemLoaded:function(_b){
-return this.isItem(_b);
-},loadItem:function(_c){
-},getLabel:function(_d){
-return this.getValue(_d,this.label);
-},getLabelAttributes:function(_e){
-return [this.label];
-},containsValue:function(_f,_10,_11){
-var _12=this.getValues(_f,_10);
-for(var i=0;i<_12.length;i++){
-if(_12[i]===_11){
-return true;
-}
-}
-return false;
-},getValues:function(_13,_14){
-this._assertIsItem(_13);
-this._assertIsAttribute(_14);
-if(_14==="title"){
-return [this._unescapeHtml(_13.title)];
-}else{
-if(_14==="author"){
-return [this._unescapeHtml(_13.author[0].name)];
-}else{
-if(_14==="datePublished"){
-return [dojo.date.stamp.fromISOString(_13.published)];
-}else{
-if(_14==="dateTaken"){
-return [dojo.date.stamp.fromISOString(_13.published)];
-}else{
-if(_14==="updated"){
-return [dojo.date.stamp.fromISOString(_13.updated)];
-}else{
-if(_14==="imageUrlSmall"){
-return [_13.media.thumbnail[1].url];
-}else{
-if(_14==="imageUrl"){
-return [_13.content$src];
-}else{
-if(_14==="imageUrlMedium"){
-return [_13.media.thumbnail[2].url];
-}else{
-if(_14==="link"){
-return [_13.link[1]];
-}else{
-if(_14==="tags"){
-return _13.tags.split(" ");
-}else{
-if(_14==="description"){
-return [this._unescapeHtml(_13.summary)];
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-return [];
-},isItem:function(_15){
-if(_15&&_15[this._storeRef]===this){
-return true;
-}
-return false;
-},close:function(_16){
-},_fetchItems:function(_17,_18,_19){
-if(!_17.query){
-_17.query={};
-}
-var _1a={alt:"jsonm",pp:"1",psc:"G"};
-_1a["start-index"]="1";
-if(_17.query.start){
-_1a["start-index"]=_17.query.start;
-}
-if(_17.query.tags){
-_1a.q=_17.query.tags;
-}
-if(_17.query.userid){
-_1a.uname=_17.query.userid;
-}
-if(_17.query.userids){
-_1a.ids=_17.query.userids;
-}
-if(_17.query.lang){
-_1a.hl=_17.query.lang;
-}
-_1a["max-results"]=this.maxResults;
-var _1b=this;
-var _1c=null;
-var _1d=function(_1e){
-if(_1c!==null){
-dojo.disconnect(_1c);
-}
-_18(_1b._processPicasaData(_1e),_17);
-};
-var _1f={url:this._picasaUrl,preventCache:this.urlPreventCache,content:_1a,callbackParamName:"callback",handle:_1d};
-var _20=dojo.io.script.get(_1f);
-_20.addErrback(function(_21){
-dojo.disconnect(_1c);
-_19(_21,_17);
+
+dojo.declare("dojox.data.PicasaStore", null, {
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		Initializer for the PicasaStore store.  
+		//	description:
+		//		The PicasaStore is a Datastore interface to one of the basic services
+		//		of the Picasa service, the public photo feed.  This does not provide
+		//		access to all the services of Picasa.
+		//		This store cannot do * and ? filtering as the picasa service 
+		//		provides no interface for wildcards.
+		if(args && args.label){
+			this.label = args.label;
+		}
+		if(args && "urlPreventCache" in args){
+			this.urlPreventCache = args.urlPreventCache?true:false;
+		}
+		if(args && "maxResults" in args){
+			this.maxResults = parseInt(args.maxResults);
+			if(!this.maxResults){
+				this.maxResults = 20;
+			}
+		}
+	},
+
+	_picasaUrl: "http://picasaweb.google.com/data/feed/api/all",
+
+	_storeRef: "_S",
+
+	//label: string
+	//The attribute to use from the picasa item as its label.
+	label: "title",
+
+	//urlPreventCache: boolean
+	//Flag denoting if preventCache should be passed to dojo.io.script.
+	urlPreventCache: false,
+
+	//maxResults:  Define out how many results to return for a fetch.
+	maxResults: 20,
+
+	_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("dojox.data.PicasaStore: a function was passed an item argument that was not an item");
+		}
+	},
+
+	_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("dojox.data.PicasaStore: a function was passed an attribute argument that was not an attribute name string");
+		}
+	},
+
+	getFeatures: function(){
+		//	summary: 
+		//      See dojo.data.api.Read.getFeatures()
+		return {
+			'dojo.data.api.Read': true
+		};
+	},
+
+	getValue: function(item, attribute, defaultValue){
+		//	summary: 
+		//      See dojo.data.api.Read.getValue()
+		var values = this.getValues(item, attribute);
+		if(values && values.length > 0){
+			return values[0];
+		}
+		return defaultValue;
+	},
+
+	getAttributes: function(item){
+		//	summary: 
+		//      See dojo.data.api.Read.getAttributes()
+		 return ["id", "published", "updated", "category", "title$type", "title", 
+			 "summary$type", "summary", "rights$type", "rights", "link", "author", 
+			 "gphoto$id", "gphoto$name", "location", "imageUrlSmall", "imageUrlMedium",
+			 "imageUrl", "datePublished", "dateTaken","description"]; 
+	},
+
+	hasAttribute: function(item, attribute){
+		//	summary: 
+		//      See dojo.data.api.Read.hasAttributes()
+		if(this.getValue(item,attribute)){
+			return true;
+		}
+		return false;
+	},
+
+	isItemLoaded: function(item){
+		 //	summary: 
+		 //      See dojo.data.api.Read.isItemLoaded()
+		 return this.isItem(item);
+	},
+
+	loadItem: function(keywordArgs){
+		//	summary: 
+		//      See dojo.data.api.Read.loadItem()
+	},
+
+	getLabel: function(item){
+		//	summary: 
+		//      See dojo.data.api.Read.getLabel()
+		return this.getValue(item,this.label);
+	},
+	
+	getLabelAttributes: function(item){
+		//	summary: 
+		//      See dojo.data.api.Read.getLabelAttributes()
+		return [this.label];
+	},
+
+	containsValue: function(item, attribute, value){
+		//	summary: 
+		//      See dojo.data.api.Read.containsValue()
+		var values = this.getValues(item,attribute);
+		for(var i = 0; i < values.length; i++){
+			if(values[i] === value){
+				return true;
+			}
+		}
+		return false;
+	},
+
+	getValues: function(item, attribute){
+		//	summary: 
+		//      See dojo.data.api.Read.getValue()
+
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		if(attribute === "title"){
+			return [this._unescapeHtml(item.title)];
+		}else if(attribute === "author"){
+			return [this._unescapeHtml(item.author[0].name)];
+		}else if(attribute === "datePublished"){
+			return [dojo.date.stamp.fromISOString(item.published)];
+		}else if(attribute === "dateTaken"){
+			return [dojo.date.stamp.fromISOString(item.published)];
+		}else if(attribute === "updated"){
+			return [dojo.date.stamp.fromISOString(item.updated)];
+		}else if(attribute === "imageUrlSmall"){
+			return [item.media.thumbnail[1].url];
+		}else if(attribute === "imageUrl"){
+			return [item.content$src];
+		}else if(attribute === "imageUrlMedium"){
+			return [item.media.thumbnail[2].url];
+		}else if(attribute === "link"){
+			return [item.link[1]];
+		}else if(attribute === "tags"){
+			return item.tags.split(" ");
+		}else if(attribute === "description"){
+			return [this._unescapeHtml(item.summary)];
+		}
+		return [];
+	},
+
+	isItem: function(item){
+		//	summary: 
+		//      See dojo.data.api.Read.isItem()
+		if(item && item[this._storeRef] === this){
+			return true;
+		}
+		return false;
+	},
+	
+	close: function(request){
+		//	summary: 
+		//      See dojo.data.api.Read.close()
+	},
+
+	_fetchItems: function(request, fetchHandler, errorHandler){
+		//	summary:
+		//		Fetch picasa items that match to a query
+		//	request:
+		//		A request object
+		//	fetchHandler:
+		//		A function to call for fetched items
+		//	errorHandler:
+		//		A function to call on error
+
+		if(!request.query){
+			request.query={};
+		}
+
+		//Build up the content to send the request for.
+		var content = {alt: "jsonm", pp: "1", psc: "G"};
+
+		content['start-index'] = "1";
+		if(request.query.start){
+			content['start-index'] = request.query.start;
+		}
+		if(request.query.tags){
+			content.q = request.query.tags;
+		}
+		if(request.query.userid){
+			content.uname = request.query.userid;
+		}
+		if(request.query.userids){
+			content.ids = request.query.userids;
+		}
+		if(request.query.lang){
+			content.hl = request.query.lang;
+		}
+		content['max-results'] = this.maxResults;
+
+		//Linking this up to Picasa is a JOY!
+		var self = this;
+		var handle = null;
+		var myHandler = function(data){
+			if(handle !== null){
+				dojo.disconnect(handle);
+			}
+
+			//Process the items...
+			fetchHandler(self._processPicasaData(data), request);
+		};
+		var getArgs = {
+			url: this._picasaUrl,
+			preventCache: this.urlPreventCache,
+			content: content,
+			callbackParamName: 'callback',
+			handle: myHandler
+		};
+		var deferred = dojo.io.script.get(getArgs);
+		
+		deferred.addErrback(function(error){
+			dojo.disconnect(handle);
+			errorHandler(error, request);
+		});
+	},
+
+	_processPicasaData: function(data){
+		var items = [];
+		if(data.feed){
+			items = data.feed.entry;
+			//Add on the store ref so that isItem can work.
+			for(var i = 0; i < items.length; i++){
+				var item = items[i];
+				item[this._storeRef] = this;
+			}
+		}
+		return items;
+	},
+
+	_unescapeHtml: function(str){
+		// summary: Utility function to un-escape XML special characters in an HTML string.
+		// description: Utility function to un-escape XML special characters in an HTML string.
+		// str: String.
+		//   The string to un-escape
+		// returns: HTML String converted back to the normal text (unescaped) characters (<,>,&, ", etc,).
+		//
+		//TODO: Check to see if theres already compatible escape() in dojo.string or dojo.html
+		if(str){
+			str = str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, "\"");
+			str = str.replace(/'/gm, "'"); 
+		}
+		return str;
+	}
 });
-},_processPicasaData:function(_22){
-var _23=[];
-if(_22.feed){
-_23=_22.feed.entry;
-for(var i=0;i<_23.length;i++){
-var _24=_23[i];
-_24[this._storeRef]=this;
-}
-}
-return _23;
-},_unescapeHtml:function(str){
-if(str){
-str=str.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,"\"");
-str=str.replace(/'/gm,"'");
-}
-return str;
-}});
-dojo.extend(dojox.data.PicasaStore,dojo.data.util.simpleFetch);
-}
+dojo.extend(dojox.data.PicasaStore,dojo.data.util.simpleFetch);										  
diff --git a/dojox/data/QueryReadStore.js b/dojox/data/QueryReadStore.js
index eec2c92..137c7d7 100644
--- a/dojox/data/QueryReadStore.js
+++ b/dojox/data/QueryReadStore.js
@@ -1,254 +1,516 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.QueryReadStore"]){
-dojo._hasResource["dojox.data.QueryReadStore"]=true;
 dojo.provide("dojox.data.QueryReadStore");
+
 dojo.require("dojo.string");
 dojo.require("dojo.data.util.sorter");
-dojo.declare("dojox.data.QueryReadStore",null,{url:"",requestMethod:"get",_className:"dojox.data.QueryReadStore",_items:[],_lastServerQuery:null,_numRows:-1,lastRequestHash:null,doClientPaging:false,doClientSorting:false,_itemsByIdentity:null,_identifier:null,_features:{"dojo.data.api.Read":true,"dojo.data.api.Identity":true},_labelAttr:"label",constructor:function(_1){
-dojo.mixin(this,_1);
-},getValue:function(_2,_3,_4){
-this._assertIsItem(_2);
-if(!dojo.isString(_3)){
-throw new Error(this._className+".getValue(): Invalid attribute, string expected!");
-}
-if(!this.hasAttribute(_2,_3)){
-if(_4){
-return _4;
-}
-}
-return _2.i[_3];
-},getValues:function(_5,_6){
-this._assertIsItem(_5);
-var _7=[];
-if(this.hasAttribute(_5,_6)){
-_7.push(_5.i[_6]);
-}
-return _7;
-},getAttributes:function(_8){
-this._assertIsItem(_8);
-var _9=[];
-for(var i in _8.i){
-_9.push(i);
-}
-return _9;
-},hasAttribute:function(_a,_b){
-return this.isItem(_a)&&typeof _a.i[_b]!="undefined";
-},containsValue:function(_c,_d,_e){
-var _f=this.getValues(_c,_d);
-var len=_f.length;
-for(var i=0;i<len;i++){
-if(_f[i]==_e){
-return true;
-}
-}
-return false;
-},isItem:function(_10){
-if(_10){
-return typeof _10.r!="undefined"&&_10.r==this;
-}
-return false;
-},isItemLoaded:function(_11){
-return this.isItem(_11);
-},loadItem:function(_12){
-if(this.isItemLoaded(_12.item)){
-return;
-}
-},fetch:function(_13){
-_13=_13||{};
-if(!_13.store){
-_13.store=this;
-}
-var _14=this;
-var _15=function(_16,_17){
-if(_17.onError){
-var _18=_17.scope||dojo.global;
-_17.onError.call(_18,_16,_17);
-}
-};
-var _19=function(_1a,_1b,_1c){
-var _1d=_1b.abort||null;
-var _1e=false;
-var _1f=_1b.start?_1b.start:0;
-if(_14.doClientPaging==false){
-_1f=0;
-}
-var _20=_1b.count?(_1f+_1b.count):_1a.length;
-_1b.abort=function(){
-_1e=true;
-if(_1d){
-_1d.call(_1b);
-}
-};
-var _21=_1b.scope||dojo.global;
-if(!_1b.store){
-_1b.store=_14;
-}
-if(_1b.onBegin){
-_1b.onBegin.call(_21,_1c,_1b);
-}
-if(_1b.sort&&_14.doClientSorting){
-_1a.sort(dojo.data.util.sorter.createSortFunction(_1b.sort,_14));
-}
-if(_1b.onItem){
-for(var i=_1f;(i<_1a.length)&&(i<_20);++i){
-var _22=_1a[i];
-if(!_1e){
-_1b.onItem.call(_21,_22,_1b);
-}
-}
-}
-if(_1b.onComplete&&!_1e){
-var _23=null;
-if(!_1b.onItem){
-_23=_1a.slice(_1f,_20);
-}
-_1b.onComplete.call(_21,_23,_1b);
-}
-};
-this._fetchItems(_13,_19,_15);
-return _13;
-},getFeatures:function(){
-return this._features;
-},close:function(_24){
-},getLabel:function(_25){
-if(this._labelAttr&&this.isItem(_25)){
-return this.getValue(_25,this._labelAttr);
-}
-return undefined;
-},getLabelAttributes:function(_26){
-if(this._labelAttr){
-return [this._labelAttr];
-}
-return null;
-},_xhrFetchHandler:function(_27,_28,_29,_2a){
-_27=this._filterResponse(_27);
-if(_27.label){
-this._labelAttr=_27.label;
-}
-var _2b=_27.numRows||-1;
-this._items=[];
-dojo.forEach(_27.items,function(e){
-this._items.push({i:e,r:this});
-},this);
-var _2c=_27.identifier;
-this._itemsByIdentity={};
-if(_2c){
-this._identifier=_2c;
-var i;
-for(i=0;i<this._items.length;++i){
-var _2d=this._items[i].i;
-var _2e=_2d[_2c];
-if(!this._itemsByIdentity[_2e]){
-this._itemsByIdentity[_2e]=_2d;
-}else{
-throw new Error(this._className+":  The json data as specified by: ["+this.url+"] is malformed.  Items within the list have identifier: ["+_2c+"].  Value collided: ["+_2e+"]");
-}
-}
-}else{
-this._identifier=Number;
-for(i=0;i<this._items.length;++i){
-this._items[i].n=i;
-}
-}
-_2b=this._numRows=(_2b===-1)?this._items.length:_2b;
-_29(this._items,_28,_2b);
-this._numRows=_2b;
-},_fetchItems:function(_2f,_30,_31){
-var _32=_2f.serverQuery||_2f.query||{};
-if(!this.doClientPaging){
-_32.start=_2f.start||0;
-if(_2f.count){
-_32.count=_2f.count;
-}
-}
-if(!this.doClientSorting){
-if(_2f.sort){
-var _33=_2f.sort[0];
-if(_33&&_33.attribute){
-var _34=_33.attribute;
-if(_33.descending){
-_34="-"+_34;
-}
-_32.sort=_34;
-}
-}
-}
-if(this.doClientPaging&&this._lastServerQuery!==null&&dojo.toJson(_32)==dojo.toJson(this._lastServerQuery)){
-this._numRows=(this._numRows===-1)?this._items.length:this._numRows;
-_30(this._items,_2f,this._numRows);
-}else{
-var _35=this.requestMethod.toLowerCase()=="post"?dojo.xhrPost:dojo.xhrGet;
-var _36=_35({url:this.url,handleAs:"json-comment-optional",content:_32});
-_36.addCallback(dojo.hitch(this,function(_37){
-this._xhrFetchHandler(_37,_2f,_30,_31);
-}));
-_36.addErrback(function(_38){
-_31(_38,_2f);
-});
-this.lastRequestHash=new Date().getTime()+"-"+String(Math.random()).substring(2);
-this._lastServerQuery=dojo.mixin({},_32);
-}
-},_filterResponse:function(_39){
-return _39;
-},_assertIsItem:function(_3a){
-if(!this.isItem(_3a)){
-throw new Error(this._className+": Invalid item argument.");
-}
-},_assertIsAttribute:function(_3b){
-if(typeof _3b!=="string"){
-throw new Error(this._className+": Invalid attribute argument ('"+_3b+"').");
-}
-},fetchItemByIdentity:function(_3c){
-if(this._itemsByIdentity){
-var _3d=this._itemsByIdentity[_3c.identity];
-if(!(_3d===undefined)){
-if(_3c.onItem){
-var _3e=_3c.scope?_3c.scope:dojo.global;
-_3c.onItem.call(_3e,{i:_3d,r:this});
-}
-return;
-}
-}
-var _3f=function(_40,_41){
-var _42=_3c.scope?_3c.scope:dojo.global;
-if(_3c.onError){
-_3c.onError.call(_42,_40);
-}
-};
-var _43=function(_44,_45){
-var _46=_3c.scope?_3c.scope:dojo.global;
-try{
-var _47=null;
-if(_44&&_44.length==1){
-_47=_44[0];
-}
-if(_3c.onItem){
-_3c.onItem.call(_46,_47);
-}
-}
-catch(error){
-if(_3c.onError){
-_3c.onError.call(_46,error);
-}
-}
-};
-var _48={serverQuery:{id:_3c.identity}};
-this._fetchItems(_48,_43,_3f);
-},getIdentity:function(_49){
-var _4a=null;
-if(this._identifier===Number){
-_4a=_49.n;
-}else{
-_4a=_49.i[this._identifier];
-}
-return _4a;
-},getIdentityAttributes:function(_4b){
-return [this._identifier];
-}});
-}
+
+dojo.declare("dojox.data.QueryReadStore",
+	null,
+	{
+		//	summary:
+		//		This class provides a store that is mainly intended to be used
+		//		for loading data dynamically from the server, used i.e. for
+		//		retreiving chunks of data from huge data stores on the server (by server-side filtering!).
+		//		Upon calling the fetch() method of this store the data are requested from
+		//		the server if they are not yet loaded for paging (or cached).
+		//
+		//		For example used for a combobox which works on lots of data. It
+		//		can be used to retreive the data partially upon entering the
+		//		letters "ac" it returns only items like "action", "acting", etc.
+		//
+		// note:
+		//		The field name "id" in a query is reserved for looking up data
+		//		by id. This is necessary as before the first fetch, the store
+		//		has no way of knowing which field the server will declare as
+		//		identifier.
+		//
+		//	example:
+		// |	// The parameter "query" contains the data that are sent to the server.
+		// |	var store = new dojox.data.QueryReadStore({url:'/search.php'});
+		// |	store.fetch({query:{name:'a'}, queryOptions:{ignoreCase:false}});
+		//
+		// |	// Since "serverQuery" is given, it overrules and those data are
+		// |	// sent to the server.
+		// |	var store = new dojox.data.QueryReadStore({url:'/search.php'});
+		// |	store.fetch({serverQuery:{name:'a'}, queryOptions:{ignoreCase:false}});
+		//
+		// |	<div dojoType="dojox.data.QueryReadStore"
+		// |		jsId="store2"
+		// |		url="../tests/stores/QueryReadStore.php"
+		// |		requestMethod="post"></div>
+		// |	<div dojoType="dojox.grid.data.DojoData"
+		// |		jsId="model2"
+		// |		store="store2"
+		// |		sortFields="[{attribute: 'name', descending: true}]"
+		// |		rowsPerPage="30"></div>
+		// |	<div dojoType="dojox.Grid" id="grid2"
+		// |		model="model2"
+		// |		structure="gridLayout"
+		// |		style="height:300px; width:800px;"></div>
+	
+		//
+		//	todo:
+		//		- there is a bug in the paging, when i set start:2, count:5 after an initial fetch() and doClientPaging:true
+		//		  it returns 6 elemetns, though count=5, try it in QueryReadStore.html
+		//		- add optional caching
+		//		- when the first query searched for "a" and the next for a subset of
+		//		  the first, i.e. "ab" then we actually dont need a server request, if
+		//		  we have client paging, we just need to filter the items we already have
+		//		  that might also be tooo much logic
+		
+		url:"",
+		requestMethod:"get",
+		//useCache:false,
+		
+		// We use the name in the errors, once the name is fixed hardcode it, may be.
+		_className:"dojox.data.QueryReadStore",
+		
+		// This will contain the items we have loaded from the server.
+		// The contents of this array is optimized to satisfy all read-api requirements
+		// and for using lesser storage, so the keys and their content need some explaination:
+		// 		this._items[0].i - the item itself 
+		//		this._items[0].r - a reference to the store, so we can identify the item
+		//			securly. We set this reference right after receiving the item from the
+		//			server.
+		_items:[],
+		
+		// Store the last query that triggered xhr request to the server.
+		// So we can compare if the request changed and if we shall reload 
+		// (this also depends on other factors, such as is caching used, etc).
+		_lastServerQuery:null,
+		
+		// Store how many rows we have so that we can pass it to a clientPaging handler
+		_numRows:-1,
+		
+		// Store a hash of the last server request. Actually I introduced this
+		// for testing, so I can check if no unnecessary requests were issued for
+		// client-side-paging.
+		lastRequestHash:null,
+		
+		// summary:
+		//		By default every request for paging is sent to the server.
+		doClientPaging:false,
+	
+		// summary:
+		//		By default all the sorting is done serverside before the data is returned
+		//		which is the proper place to be doing it for really large datasets.
+		doClientSorting:false,
+	
+		// Items by identify for Identify API
+		_itemsByIdentity:null,
+		
+		// Identifier used
+		_identifier:null,
+	
+		_features: {'dojo.data.api.Read':true, 'dojo.data.api.Identity':true},
+	
+		_labelAttr: "label",
+		
+		constructor: function(/* Object */ params){
+			dojo.mixin(this,params);
+		},
+		
+		getValue: function(/* item */ item, /* attribute-name-string */ attribute, /* value? */ defaultValue){
+			//	According to the Read API comments in getValue() and exception is
+			//	thrown when an item is not an item or the attribute not a string!
+			this._assertIsItem(item);
+			if(!dojo.isString(attribute)){
+				throw new Error(this._className+".getValue(): Invalid attribute, string expected!");
+			}
+			if(!this.hasAttribute(item, attribute)){
+				// read api says: return defaultValue "only if *item* does not have a value for *attribute*." 
+				// Is this the case here? The attribute doesn't exist, but a defaultValue, sounds reasonable.
+				if(defaultValue){
+					return defaultValue;
+				}
+				console.log(this._className+".getValue(): Item does not have the attribute '"+attribute+"'.");
+			}
+			return item.i[attribute];
+		},
+		
+		getValues: function(/* item */ item, /* attribute-name-string */ attribute){
+			this._assertIsItem(item);
+			var ret = [];
+			if(this.hasAttribute(item, attribute)){
+				ret.push(item.i[attribute]);
+			}
+			return ret;
+		},
+		
+		getAttributes: function(/* item */ item){
+			this._assertIsItem(item);
+			var ret = [];
+			for(var i in item.i){
+				ret.push(i);
+			}
+			return ret;
+		},
+	
+		hasAttribute: function(/* item */ item,	/* attribute-name-string */ attribute){
+			//	summary: 
+			//		See dojo.data.api.Read.hasAttribute()
+			return this.isItem(item) && typeof item.i[attribute]!="undefined";
+		},
+		
+		containsValue: function(/* item */ item, /* attribute-name-string */ attribute, /* anything */ value){
+			var values = this.getValues(item, attribute);
+			var len = values.length;
+			for(var i=0; i<len; i++){
+				if(values[i] == value){
+					return true;
+				}
+			}
+			return false;
+		},
+		
+		isItem: function(/* anything */ something){
+			// Some basic tests, that are quick and easy to do here.
+			// >>> var store = new dojox.data.QueryReadStore({});
+			// >>> store.isItem("");
+			// false
+			//
+			// >>> var store = new dojox.data.QueryReadStore({});
+			// >>> store.isItem({});
+			// false
+			//
+			// >>> var store = new dojox.data.QueryReadStore({});
+			// >>> store.isItem(0);
+			// false
+			//
+			// >>> var store = new dojox.data.QueryReadStore({});
+			// >>> store.isItem({name:"me", label:"me too"});
+			// false
+			//
+			if(something){
+				return typeof something.r != "undefined" && something.r == this;
+			}
+			return false;
+		},
+		
+		isItemLoaded: function(/* anything */ something){
+			// Currently we dont have any state that tells if an item is loaded or not
+			// if the item exists its also loaded.
+			// This might change when we start working with refs inside items ...
+			return this.isItem(something);
+		},
+	
+		loadItem: function(/* object */ args){
+			if(this.isItemLoaded(args.item)){
+				return;
+			}
+			// Actually we have nothing to do here, or at least I dont know what to do here ...
+		},
+	
+		fetch:function(/* Object? */ request){
+			//	summary:
+			//		See dojo.data.util.simpleFetch.fetch() this is just a copy and I adjusted
+			//		only the paging, since it happens on the server if doClientPaging is
+			//		false, thx to http://trac.dojotoolkit.org/ticket/4761 reporting this.
+			//		Would be nice to be able to use simpleFetch() to reduce copied code,
+			//		but i dont know how yet. Ideas please!
+			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, numRows){
+				var oldAbortFunction = requestObject.abort || null;
+				var aborted = false;
+				
+				var startIndex = requestObject.start?requestObject.start:0;
+				if(self.doClientPaging == false){
+					// For client paging we dont need no slicing of the result.
+					startIndex = 0;
+				}
+				var endIndex = requestObject.count?(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, numRows, requestObject);
+				}
+				if(requestObject.sort && self.doClientSorting){
+					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
+		},
+	
+		getFeatures: function(){
+			return this._features;
+		},
+	
+		close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+			// I have no idea if this is really needed ... 
+		},
+	
+		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
+		},
+		
+		_xhrFetchHandler: function(data, request, fetchHandler, errorHandler){
+			data = this._filterResponse(data);
+			if(data.label){
+				this._labelAttr = data.label;
+			}
+			var numRows = data.numRows || -1;
+
+			this._items = [];
+			// Store a ref to "this" in each item, so we can simply check if an item
+			// really origins form here (idea is from ItemFileReadStore, I just don't know
+			// how efficient the real storage use, garbage collection effort, etc. is).
+			dojo.forEach(data.items,function(e){ 
+				this._items.push({i:e, r:this}); 
+			},this); 
+			
+			var identifier = data.identifier;
+			this._itemsByIdentity = {};
+			if(identifier){
+				this._identifier = identifier;
+				var i;
+				for(i = 0; i < this._items.length; ++i){
+					var item = this._items[i].i;
+					var identity = item[identifier];
+					if(!this._itemsByIdentity[identity]){
+						this._itemsByIdentity[identity] = item;
+					}else{
+						throw new Error(this._className+":  The json data as specified by: [" + this.url + "] is malformed.  Items within the list have identifier: [" + identifier + "].  Value collided: [" + identity + "]");
+					}
+				}
+			}else{
+				this._identifier = Number;
+				for(i = 0; i < this._items.length; ++i){
+					this._items[i].n = i;
+				}
+			}
+			
+			// TODO actually we should do the same as dojo.data.ItemFileReadStore._getItemsFromLoadedData() to sanitize
+			// (does it really sanititze them) and store the data optimal. should we? for security reasons???
+			numRows = this._numRows = (numRows === -1) ? this._items.length : numRows;
+			fetchHandler(this._items, request, numRows);
+			this._numRows = numRows;		
+		},
+		
+		_fetchItems: function(request, fetchHandler, errorHandler){
+			//	summary:
+			// 		The request contains the data as defined in the Read-API.
+			// 		Additionally there is following keyword "serverQuery".
+			//
+			//	The *serverQuery* parameter, optional.
+			//		This parameter contains the data that will be sent to the server.
+			//		If this parameter is not given the parameter "query"'s
+			//		data are sent to the server. This is done for some reasons:
+			//		- to specify explicitly which data are sent to the server, they
+			//		  might also be a mix of what is contained in "query", "queryOptions"
+			//		  and the paging parameters "start" and "count" or may be even
+			//		  completely different things.
+			//		- don't modify the request.query data, so the interface using this
+			//		  store can rely on unmodified data, as the combobox dijit currently
+			//		  does it, it compares if the query has changed
+			//		- request.query is required by the Read-API
+			//
+			// 		I.e. the following examples might be sent via GET:
+			//		  fetch({query:{name:"abc"}, queryOptions:{ignoreCase:true}})
+			//		  the URL will become:   /url.php?name=abc
+			//
+			//		  fetch({serverQuery:{q:"abc", c:true}, query:{name:"abc"}, queryOptions:{ignoreCase:true}})
+			//		  the URL will become:   /url.php?q=abc&c=true
+			//		  // The serverQuery-parameter has overruled the query-parameter
+			//		  // but the query parameter stays untouched, but is not sent to the server!
+			//		  // The serverQuery contains more data than the query, so they might differ!
+			//
+	
+			var serverQuery = request.serverQuery || request.query || {};
+			//Need to add start and count
+			if(!this.doClientPaging){
+				serverQuery.start = request.start || 0;
+				// Count might not be sent if not given.
+				if(request.count){
+					serverQuery.count = request.count;
+				}
+			}
+			if(!this.doClientSorting && request.sort){
+				var sortInfo = [];
+				dojo.forEach(request.sort, function(sort){
+					if(sort && sort.attribute){
+						sortInfo.push((sort.descending ? "-" : "") + sort.attribute);
+					}
+				});
+				serverQuery.sort = sortInfo.join(',');
+			}
+			// Compare the last query and the current query by simply json-encoding them,
+			// so we dont have to do any deep object compare ... is there some dojo.areObjectsEqual()???
+			if(this.doClientPaging && this._lastServerQuery !== null &&
+				dojo.toJson(serverQuery) == dojo.toJson(this._lastServerQuery)
+				){
+				this._numRows = (this._numRows === -1) ? this._items.length : this._numRows;
+				fetchHandler(this._items, request, this._numRows);
+			}else{
+				var xhrFunc = this.requestMethod.toLowerCase() == "post" ? dojo.xhrPost : dojo.xhrGet;
+				var xhrHandler = xhrFunc({url:this.url, handleAs:"json-comment-optional", content:serverQuery});
+				xhrHandler.addCallback(dojo.hitch(this, function(data){
+					this._xhrFetchHandler(data, request, fetchHandler, errorHandler);
+				}));
+				xhrHandler.addErrback(function(error){
+					errorHandler(error, request);
+				});
+				// Generate the hash using the time in milliseconds and a randon number.
+				// Since Math.randon() returns something like: 0.23453463, we just remove the "0."
+				// probably just for esthetic reasons :-).
+				this.lastRequestHash = new Date().getTime()+"-"+String(Math.random()).substring(2);
+				this._lastServerQuery = dojo.mixin({}, serverQuery);
+			}
+		},
+		
+		_filterResponse: function(data){
+			//	summary:
+			//		If the data from servers needs to be processed before it can be processed by this
+			//		store, then this function should be re-implemented in subclass. This default 
+			//		implementation just return the data unchanged.
+			//	data:
+			//		The data received from server
+			return data;
+		},
+	
+		_assertIsItem: function(/* item */ item){
+			//	summary:
+			//		It throws an error if item is not valid, so you can call it in every method that needs to
+			//		throw an error when item is invalid.
+			//	item: 
+			//		The item to test for being contained by the store.
+			if(!this.isItem(item)){
+				throw new Error(this._className+": 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(this._className+": Invalid attribute argument ('"+attribute+"').");
+			}
+		},
+	
+		fetchItemByIdentity: function(/* Object */ keywordArgs){
+			//	summary: 
+			//		See dojo.data.api.Identity.fetchItemByIdentity()
+	
+			// See if we have already loaded the item with that id
+			// In case there hasn't been a fetch yet, _itemsByIdentity is null
+			// and thus a fetch will be triggered below.
+			if(this._itemsByIdentity){
+				var item = this._itemsByIdentity[keywordArgs.identity];
+				if(!(item === undefined)){
+					if(keywordArgs.onItem){
+						var scope = keywordArgs.scope ? keywordArgs.scope : dojo.global;
+						keywordArgs.onItem.call(scope, {i:item, r:this});
+					}
+					return;
+				}
+			}
+	
+			// Otherwise we need to go remote
+			// Set up error handler
+			var _errorHandler = function(errorData, requestObject){
+				var scope = keywordArgs.scope ? keywordArgs.scope : dojo.global;
+				if(keywordArgs.onError){
+					keywordArgs.onError.call(scope, errorData);
+				}
+			};
+			
+			// Set up fetch handler
+			var _fetchHandler = function(items, requestObject){
+				var scope = keywordArgs.scope ? keywordArgs.scope : dojo.global;
+				try{
+					// There is supposed to be only one result
+					var item = null;
+					if(items && items.length == 1){
+						item = items[0];
+					}
+					
+					// If no item was found, item is still null and we'll
+					// fire the onItem event with the null here
+					if(keywordArgs.onItem){
+						keywordArgs.onItem.call(scope, item);
+					}
+				}catch(error){
+					if(keywordArgs.onError){
+						keywordArgs.onError.call(scope, error);
+					}
+				}
+			};
+			
+			// Construct query
+			var request = {serverQuery:{id:keywordArgs.identity}};
+			
+			// Dispatch query
+			this._fetchItems(request, _fetchHandler, _errorHandler);
+		},
+		
+		getIdentity: function(/* item */ item){
+			//	summary: 
+			//		See dojo.data.api.Identity.getIdentity()
+			var identifier = null;
+			if(this._identifier === Number){
+				identifier = item.n; // Number
+			}else{
+				identifier = item.i[this._identifier];
+			}
+			return identifier;
+		},
+		
+		getIdentityAttributes: function(/* item */ item){
+			//	summary:
+			//		See dojo.data.api.Identity.getIdentityAttributes()
+			return [this._identifier];
+		}
+	}
+);
diff --git a/dojox/data/RailsStore.js b/dojox/data/RailsStore.js
index 27fa4dc..68d00e1 100644
--- a/dojox/data/RailsStore.js
+++ b/dojox/data/RailsStore.js
@@ -1,119 +1,167 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.RailsStore"]){
-dojo._hasResource["dojox.data.RailsStore"]=true;
 dojo.provide("dojox.data.RailsStore");
 dojo.require("dojox.data.JsonRestStore");
-dojo.declare("dojox.data.RailsStore",dojox.data.JsonRestStore,{constructor:function(){
-},preamble:function(_1){
-if(typeof _1.target=="string"&&!_1.service){
-var _2=_1.target.replace(/\/$/g,"");
-var _3=function(id,_4){
-_4=_4||{};
-var _5=_2;
-var _6;
-var _7;
-if(dojo.isObject(id)){
-_7="";
-_6="?"+dojo.objectToQuery(id);
-}else{
-if(_4.queryStr&&_4.queryStr.indexOf("?")!=-1){
-_7=_4.queryStr.replace(/\?.*/,"");
-_6=_4.queryStr.replace(/[^?]*\?/g,"?");
-}else{
-if(dojo.isString(_4.query)&&_4.query.indexOf("?")!=-1){
-_7=_4.query.replace(/\?.*/,"");
-_6=_4.query.replace(/[^?]*\?/g,"?");
-}else{
-_7=id?id.toString():"";
-_6="";
-}
-}
-}
-if(_7.indexOf("=")!=-1){
-_6=_7;
-_7="";
-}
-if(_7){
-_5=_5+"/"+_7+".json"+_6;
-}else{
-_5=_5+".json"+_6;
-}
-var _8=dojox.rpc._sync;
-dojox.rpc._sync=false;
-return {url:_5,handleAs:"json",contentType:"application/json",sync:_8,headers:{Accept:"application/json,application/javascript",Range:_4&&(_4.start>=0||_4.count>=0)?"items="+(_4.start||"0")+"-"+((_4.count&&(_4.count+(_4.start||0)-1))||""):undefined}};
-};
-_1.service=dojox.rpc.Rest(this.target,true,null,_3);
-}
-},fetch:function(_9){
-_9=_9||{};
-function _a(_b){
-function _c(){
-if(_9.queryStr==null){
-_9.queryStr="";
-}
-if(dojo.isObject(_9.query)){
-_9.queryStr="?"+dojo.objectToQuery(_9.query);
-}else{
-if(dojo.isString(_9.query)){
-_9.queryStr=_9.query;
-}
-}
-};
-function _d(){
-if(_9.queryStr.indexOf("?")==-1){
-return "?";
-}else{
-return "&";
-}
-};
-if(_9.queryStr==null){
-_c();
-}
-_9.queryStr=_9.queryStr+_d()+dojo.objectToQuery(_b);
-};
-if(_9.start||_9.count){
-if((_9.start||0)%_9.count){
-throw new Error("The start parameter must be a multiple of the count parameter");
-}
-_a({page:((_9.start||0)/_9.count)+1,per_page:_9.count});
-}
-if(_9.sort){
-var _e={sortBy:[],sortDir:[]};
-dojo.forEach(_9.sort,function(_f){
-_e.sortBy.push(_f.attribute);
-_e.sortDir.push(!!_f.descending?"DESC":"ASC");
+// Contains code donated by Travis Tilley under CLA
+
+
+dojo.declare("dojox.data.RailsStore", dojox.data.JsonRestStore, {
+	constructor: function(){
+		//	summary:
+		//		RailsStore is a data store for interacting with RESTful Rails controllers
+	},
+	preamble: function(options){
+		if(typeof options.target == 'string' && !options.service){
+			var target = options.target.replace(/\/$/g, '');
+
+			// Special getRequest handler for handling content type negotiation via
+			// the Rails format extension, as well as properly setting the ID param
+			// in the URL.
+			var getRequest = function(id, args){
+				args = args || {};
+				var url = target;
+				var query;
+				var ident;
+
+				if(dojo.isObject(id)){
+					ident = '';
+					query = '?' + dojo.objectToQuery(id);
+				}else if(args.queryStr && args.queryStr.indexOf('?') != -1){
+					ident = args.queryStr.replace(/\?.*/, '');
+					query = args.queryStr.replace(/[^?]*\?/g, '?');
+				}else if(dojo.isString(args.query) && args.query.indexOf('?') != -1){
+					ident = args.query.replace(/\?.*/, '');
+					query = args.query.replace(/[^?]*\?/g, '?');
+				}else{
+					ident = id ? id.toString() : '';
+					query = '';
+				}
+
+				if(ident.indexOf('=') != -1){
+					query = ident;
+					ident = '';
+				}
+
+				if(ident){
+					url = url + '/' + ident + '.json' + query;
+				}else{
+					url = url + '.json' + query;
+				}
+
+				var isSync = dojox.rpc._sync;
+				dojox.rpc._sync = false;
+
+				return {
+					url : url,
+					handleAs : 'json',
+					contentType : 'application/json',
+					sync : isSync,
+					headers : {
+						Accept : 'application/json,application/javascript',
+						Range : args && (args.start >= 0 || args.count >= 0)
+								? "items="
+										+ (args.start || '0')
+										+ '-'
+										+ ((args.count && (args.count
+												+ (args.start || 0) - 1)) || '')
+								: undefined
+					}
+				};
+			};
+
+			options.service = dojox.rpc.Rest(this.target, true, null,
+					getRequest);
+		}
+	},
+	fetch: function(args){
+		args = args || {};
+		function addToQueryStr(obj){
+			function buildInitialQueryString(){
+				if(args.queryStr == null){
+					args.queryStr = '';
+				}
+				if(dojo.isObject(args.query)){
+					args.queryStr = '?' + dojo.objectToQuery(args.query);
+				}else if(dojo.isString(args.query)){
+					args.queryStr = args.query;
+				}
+			}
+			function separator(){
+				if(args.queryStr.indexOf('?') == -1){
+					return '?';
+				}else{
+					return '&';
+				}
+			}
+			if(args.queryStr == null){
+				buildInitialQueryString();
+			}
+			args.queryStr = args.queryStr + separator() + dojo.objectToQuery(obj);
+		}
+		if(args.start || args.count){
+			// in addition to the content range headers, also provide query parameters for use
+			// with the will_paginate plugin if so desired.
+			if((args.start || 0) % args.count){
+				throw new Error("The start parameter must be a multiple of the count parameter");
+			}
+			addToQueryStr({
+				page: ((args.start || 0) / args.count) + 1,
+				per_page: args.count
+			});
+		}
+		if(args.sort){
+			// make the sort into query parameters
+			var queryObj = {
+				sortBy : [],
+				sortDir : []
+			};
+
+			dojo.forEach(args.sort, function(item){
+				queryObj.sortBy.push(item.attribute);
+				queryObj.sortDir.push(!!item.descending ? 'DESC' : 'ASC');
+			});
+
+			addToQueryStr(queryObj);
+			delete args.sort;
+		}
+
+		return this.inherited(arguments);
+	},
+	_processResults: function(results, deferred){
+		var items;
+
+		/*
+		 * depending on the ActiveRecord::Base.include_root_in_json setting,
+		 * you might get back an array of attribute objects, or an array of
+		 * objects with the attribute object nested under an attribute having
+		 * the same name as the (remote and unguessable) model class.
+		 *
+		 * 'Example' without root_in_json: [{'id':1, 'text':'first'}]
+		 * 'Example' with root_in_json: [{'example':{'id':1, 'text':'first'}}]
+		 */
+		if((typeof this.rootAttribute == 'undefined') && results[0]){
+			if(results[0][this.idAttribute]){
+				this.rootAttribute = false;
+				console.debug('RailsStore: without root_in_json');
+			}else{
+				for(var attribute in results[0]){
+					if(results[0][attribute][this.idAttribute]){
+						this.rootAttribute = attribute;
+						console.debug('RailsStore: with root_in_json, attribute: ' + attribute);
+					}
+				}
+			}
+		}
+
+		if(this.rootAttribute){
+			items = dojo.map(results, function(item){
+				return item[this.rootAttribute];
+			}, this);
+		}else{
+			items = results;
+		}
+
+		// index the results
+		var count = results.length;
+		// if we don't know the length, and it is partial result, we will guess that it is twice as big, that will work for most widgets
+		return {totalCount:deferred.fullLength || (deferred.request.count == count ? (deferred.request.start || 0) + count * 2 : count), items: items};
+	}
 });
-_a(_e);
-delete _9.sort;
-}
-return this.inherited(arguments);
-},_processResults:function(_10,_11){
-var _12;
-if((typeof this.rootAttribute=="undefined")&&_10[0]){
-if(_10[0][this.idAttribute]){
-this.rootAttribute=false;
-}else{
-for(var _13 in _10[0]){
-if(_10[0][_13][this.idAttribute]){
-this.rootAttribute=_13;
-}
-}
-}
-}
-if(this.rootAttribute){
-_12=dojo.map(_10,function(_14){
-return _14[this.rootAttribute];
-},this);
-}else{
-_12=_10;
-}
-var _15=_10.length;
-return {totalCount:_11.fullLength||(_11.request.count==_15?(_11.request.start||0)+_15*2:_15),items:_12};
-}});
-}
diff --git a/dojox/data/S3Store.js b/dojox/data/S3Store.js
index 0c3ea8f..51923c9 100644
--- a/dojox/data/S3Store.js
+++ b/dojox/data/S3Store.js
@@ -1,29 +1,34 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.S3Store"]){
-dojo._hasResource["dojox.data.S3Store"]=true;
 dojo.provide("dojox.data.S3Store");
 dojo.require("dojox.rpc.ProxiedPath");
 dojo.require("dojox.data.JsonRestStore");
-dojo.declare("dojox.data.S3Store",dojox.data.JsonRestStore,{_processResults:function(_1){
-var _2=_1.getElementsByTagName("Key");
-var _3=[];
-var _4=this;
-for(var i=0;i<_2.length;i++){
-var _5=_2[i];
-var _6={_loadObject:(function(_7,_8){
-return function(_9){
-delete this._loadObject;
-_4.service(_7).addCallback(_9);
-};
-})(_5.firstChild.nodeValue,_6)};
-_3.push(_6);
-}
-return {totalCount:_3.length,items:_3};
-}});
-}
+
+// S3JsonRestStore is an extension of JsonRestStore to handle
+// Amazon's S3 service using JSON data
+
+dojo.declare("dojox.data.S3Store",
+	dojox.data.JsonRestStore,
+	{
+		_processResults : function(results){
+			// unfortunately, S3 returns query results in XML form
+			var keyElements = results.getElementsByTagName("Key");
+			var jsResults = [];
+			var self = this;
+			for(var i=0; i <keyElements.length;i++){
+				var keyElement = keyElements[i];
+				// manually create lazy loaded Deferred items for each item in the result array
+				var val = {
+					_loadObject: (function(key,val){
+						return function(callback){
+							// when a callback is added we will fetch it
+							delete this._loadObject;
+							self.service(key).addCallback(callback);
+						};
+					})(keyElement.firstChild.nodeValue,val)
+				};
+				jsResults.push(val);
+			}
+			
+			return {totalCount:jsResults.length, items: jsResults};
+		}
+	}
+);
diff --git a/dojox/data/ServiceStore.js b/dojox/data/ServiceStore.js
index c48edb6..0bfa09d 100644
--- a/dojox/data/ServiceStore.js
+++ b/dojox/data/ServiceStore.js
@@ -1,154 +1,399 @@
-/*
-	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
-*/
+dojo.provide("dojox.data.ServiceStore");
 
+// note that dojox.rpc.Service is not required, you can create your own services
 
-if(!dojo._hasResource["dojox.data.ServiceStore"]){
-dojo._hasResource["dojox.data.ServiceStore"]=true;
-dojo.provide("dojox.data.ServiceStore");
-dojo.declare("dojox.data.ServiceStore",dojox.data.ClientFilter,{service:null,constructor:function(_1){
-this.byId=this.fetchItemByIdentity;
-this._index={};
-if(_1){
-dojo.mixin(this,_1);
-}
-this.idAttribute=(_1&&_1.idAttribute)||(this.schema&&this.schema._idAttr);
-this.labelAttribute=this.labelAttribute||"label";
-},schema:null,idAttribute:"id",syncMode:false,estimateCountFactor:1,getSchema:function(){
-return this.schema;
-},loadLazyValues:true,getValue:function(_2,_3,_4){
-var _5=_2[_3];
-return _5||(_3 in _2?_5:_2._loadObject?(dojox.rpc._sync=true)&&arguments.callee.call(this,dojox.data.ServiceStore.prototype.loadItem({item:_2})||{},_3,_4):_4);
-},getValues:function(_6,_7){
-var _8=this.getValue(_6,_7);
-return _8 instanceof Array?_8:_8===undefined?[]:[_8];
-},getAttributes:function(_9){
-var _a=[];
-for(var i in _9){
-if(_9.hasOwnProperty(i)&&!(i.charAt(0)=="_"&&i.charAt(1)=="_")){
-_a.push(i);
-}
-}
-return _a;
-},hasAttribute:function(_b,_c){
-return _c in _b;
-},containsValue:function(_d,_e,_f){
-return dojo.indexOf(this.getValues(_d,_e),_f)>-1;
-},isItem:function(_10){
-return (typeof _10=="object")&&_10&&!(_10 instanceof Date);
-},isItemLoaded:function(_11){
-return _11&&!_11._loadObject;
-},loadItem:function(_12){
-var _13;
-if(_12.item._loadObject){
-_12.item._loadObject(function(_14){
-_13=_14;
-delete _13._loadObject;
-var _15=_14 instanceof Error?_12.onError:_12.onItem;
-if(_15){
-_15.call(_12.scope,_14);
-}
-});
-}else{
-if(_12.onItem){
-_12.onItem.call(_12.scope,_12.item);
-}
-}
-return _13;
-},_currentId:0,_processResults:function(_16,_17){
-if(_16&&typeof _16=="object"){
-var id=_16.__id;
-if(!id){
-if(this.idAttribute){
-id=_16[this.idAttribute];
-}else{
-id=this._currentId++;
-}
-if(id!==undefined){
-var _18=this._index[id];
-if(_18){
-for(var j in _18){
-delete _18[j];
-}
-_16=dojo.mixin(_18,_16);
-}
-_16.__id=id;
-this._index[id]=_16;
-}
-}
-for(var i in _16){
-_16[i]=this._processResults(_16[i],_17).items;
-}
-var _19=_16.length;
-}
-return {totalCount:_17.request.count==_19?(_17.request.start||0)+_19*this.estimateCountFactor:_19,items:_16};
-},close:function(_1a){
-return _1a&&_1a.abort&&_1a.abort();
-},fetch:function(_1b){
-_1b=_1b||{};
-if("syncMode" in _1b?_1b.syncMode:this.syncMode){
-dojox.rpc._sync=true;
-}
-var _1c=this;
-var _1d=_1b.scope||_1c;
-var _1e=this.cachingFetch?this.cachingFetch(_1b):this._doQuery(_1b);
-_1e.request=_1b;
-_1e.addCallback(function(_1f){
-if(_1b.clientFetch){
-_1f=_1c.clientSideFetch({query:_1b.clientFetch,sort:_1b.sort,start:_1b.start,count:_1b.count},_1f);
-}
-var _20=_1c._processResults(_1f,_1e);
-_1f=_1b.results=_20.items;
-if(_1b.onBegin){
-_1b.onBegin.call(_1d,_20.totalCount,_1b);
-}
-if(_1b.onItem){
-for(var i=0;i<_1f.length;i++){
-_1b.onItem.call(_1d,_1f[i],_1b);
-}
-}
-if(_1b.onComplete){
-_1b.onComplete.call(_1d,_1b.onItem?null:_1f,_1b);
-}
-return _1f;
-});
-_1e.addErrback(_1b.onError&&function(err){
-return _1b.onError.call(_1d,err,_1b);
-});
-_1b.abort=function(){
-_1e.cancel();
-};
-_1b.store=this;
-return _1b;
-},_doQuery:function(_21){
-var _22=typeof _21.queryStr=="string"?_21.queryStr:_21.query;
-return this.service(_22);
-},getFeatures:function(){
-return {"dojo.data.api.Read":true,"dojo.data.api.Identity":true,"dojo.data.api.Schema":this.schema};
-},getLabel:function(_23){
-return this.getValue(_23,this.labelAttribute);
-},getLabelAttributes:function(_24){
-return [this.labelAttribute];
-},getIdentity:function(_25){
-return _25.__id;
-},getIdentityAttributes:function(_26){
-return [this.idAttribute];
-},fetchItemByIdentity:function(_27){
-var _28=this._index[(_27._prefix||"")+_27.identity];
-if(_28){
-if(_28._loadObject){
-_27.item=_28;
-return this.loadItem(_27);
-}else{
-if(_27.onItem){
-_27.onItem.call(_27.scope,_28);
-}
-}
-}else{
-return this.fetch({query:_27.identity,onComplete:_27.onItem,onError:_27.onError,scope:_27.scope}).results;
-}
-return _28;
-}});
-}
+// A ServiceStore is a readonly data store that provides a data.data interface to an RPC service.
+// var myServices = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.tests.resources", "test.smd"));
+// var serviceStore = new dojox.data.ServiceStore({service:myServices.ServiceStore});
+//
+// The ServiceStore also supports lazy loading. References can be made to objects that have not been loaded.
+//	For example if a service returned:
+// {"name":"Example","lazyLoadedObject":{"$ref":"obj2"}}
+//
+// And this object has accessed using the dojo.data API:
+// var obj = serviceStore.getValue(myObject,"lazyLoadedObject");
+// The object would automatically be requested from the server (with an object id of "obj2").
+//
+
+dojo.declare("dojox.data.ServiceStore",
+	// ClientFilter is intentionally not required, ServiceStore does not need it, and is more
+	// lightweight without it, but if it is provided, the ServiceStore will use it.
+	dojox.data.ClientFilter||null,{
+		service: null,
+		constructor: function(options){
+			//summary:
+			//		ServiceStore constructor, instantiate a new ServiceStore
+			// 		A ServiceStore can be configured from a JSON Schema. Queries are just
+			// 		passed through to the underlying services
+			//
+			// options:
+			// 		Keyword arguments
+			// The *schema* parameter
+			//		This is a schema object for this store. This should be JSON Schema format.
+			//
+			// The *service* parameter
+			// 		This is the service object that is used to retrieve lazy data and save results
+			// 		The function should be directly callable with a single parameter of an object id to be loaded
+			//
+			// The *idAttribute* parameter
+			//		Defaults to 'id'. The name of the attribute that holds an objects id.
+			//		This can be a preexisting id provided by the server.
+			//		If an ID isn't already provided when an object
+			//		is fetched or added to the store, the autoIdentity system
+			//		will generate an id for it and add it to the index.
+			//
+			// The *estimateCountFactor* parameter
+			// 		This parameter is used by the ServiceStore to estimate the total count. When
+			//		paging is indicated in a fetch and the response includes the full number of items
+			//	 	requested by the fetch's count parameter, then the total count will be estimated
+			//		to be estimateCountFactor multiplied by the provided count. If this is 1, then it is assumed that the server
+			//		does not support paging, and the response is the full set of items, where the
+			// 		total count is equal to the numer of items returned. If the server does support
+			//		paging, an estimateCountFactor of 2 is a good value for estimating the total count
+			//		It is also possible to override _processResults if the server can provide an exact
+			// 		total count.
+			//
+			// The *syncMode* parameter
+			//		Setting this to true will set the store to using synchronous calls by default.
+			//		Sync calls return their data immediately from the calling function, so
+			//		callbacks are unnecessary. This will only work with a synchronous capable service.
+			//
+			// description:
+			//		ServiceStore can do client side caching and result set updating if
+			// 		dojox.data.ClientFilter is loaded. Do this add:
+			//	|	dojo.require("dojox.data.ClientFilter")
+			//		prior to loading the ServiceStore (ClientFilter must be loaded before ServiceStore).
+			//		To utilize client side filtering with a subclass, you can break queries into
+			//		client side and server side components by putting client side actions in
+			//		clientFilter property in fetch calls. For example you could override fetch:
+			//	|	fetch: function(args){
+				//	|		// do the sorting and paging on the client side
+	 			//	|		args.clientFilter = {start:args.start, count: args.count, sort: args.sort};
+	 			//	|		// args.query will be passed to the service object for the server side handling
+	 			//	|		return this.inherited(arguments);
+			//	|	}
+			//		When extending this class, if you would like to create lazy objects, you can follow
+			//		the example from dojox.data.tests.stores.ServiceStore:
+			// |	var lazyItem = {
+			// |		_loadObject: function(callback){
+			// |			this.name="loaded";
+			// |			delete this._loadObject;
+			// |			callback(this);
+			// |		}
+			// |	};
+			//setup a byId alias to the api call
+			this.byId=this.fetchItemByIdentity;
+			this._index = {};
+			// if the advanced json parser is enabled, we can pass through object updates as onSet events
+			if(options){
+				dojo.mixin(this,options);
+			}
+			// We supply a default idAttribute for parser driven construction, but if no id attribute
+			//	is supplied, it should be null so that auto identification takes place properly
+			this.idAttribute = (options && options.idAttribute) || (this.schema && this.schema._idAttr);
+		},
+		schema: null,
+		idAttribute: "id",
+		labelAttribute: "label",
+		syncMode: false,
+		estimateCountFactor: 1,
+		getSchema: function(){
+			return this.schema;
+		},
+
+		loadLazyValues:true,
+
+		getValue: function(/*Object*/ item, /*String*/property, /*value?*/defaultValue){
+			// summary:
+			//	Gets the value of an item's 'property'
+			//
+			//	item:
+			//		The item to get the value from
+			//	property:
+			//		property to look up value for
+			//	defaultValue:
+			//		the default value
+
+			var value = item[property];
+			return value || // return the plain value since it was found;
+						(property in item ? // a truthy value was not found, see if we actually have it
+							value : // we do, so we can return it
+							item._loadObject ? // property was not found, maybe because the item is not loaded, we will try to load it synchronously so we can get the property
+								(dojox.rpc._sync = true) && arguments.callee.call(this,dojox.data.ServiceStore.prototype.loadItem({item:item}) || {}, property, defaultValue) : // load the item and run getValue again
+								defaultValue);// not in item -> return default value
+		},
+		getValues: function(item, property){
+			// summary:
+			//		Gets the value of an item's 'property' and returns
+			//		it.	If this value is an array it is just returned,
+			//		if not, the value is added to an array and that is returned.
+			//
+			//	item: /* object */
+			//	property: /* string */
+			//		property to look up value for
+
+			var val = this.getValue(item,property);
+			if(val instanceof Array){
+				return val;
+			}
+			if(!this.isItemLoaded(val)){
+				dojox.rpc._sync = true;
+				val = this.loadItem({item:val});
+			}
+			return val instanceof Array ? val : val === undefined ? [] : [val];
+		},
+
+		getAttributes: function(item){
+			// summary:
+			//	Gets the available attributes of an item's 'property' and returns
+			//	it as an array.
+			//
+			//	item: /* object */
+
+			var res = [];
+			for(var i in item){
+				if(item.hasOwnProperty(i) && !(i.charAt(0) == '_' && i.charAt(1) == '_')){
+					res.push(i);
+				}
+			}
+			return res;
+		},
+
+		hasAttribute: function(item,attribute){
+			// summary:
+			//		Checks to see if item has attribute
+			//
+			//	item: /* object */
+			//	attribute: /* string */
+			return attribute in item;
+		},
+
+		containsValue: function(item, attribute, value){
+			// summary:
+			//		Checks to see if 'item' has 'value' at 'attribute'
+			//
+			//	item: /* object */
+			//	attribute: /* string */
+			//	value: /* anything */
+			return dojo.indexOf(this.getValues(item,attribute),value) > -1;
+		},
+
+
+		isItem: function(item){
+			// summary:
+			//		Checks to see if the argument is an item
+			//
+			//	item: /* object */
+			//	attribute: /* string */
+
+			// we have no way of determining if it belongs, we just have object returned from
+			// 	service queries
+			return (typeof item == 'object') && item && !(item instanceof Date);
+		},
+
+		isItemLoaded: function(item){
+			// summary:
+			//		Checks to see if the item is loaded.
+			//
+			//		item: /* object */
+
+			return item && !item._loadObject;
+		},
+
+		loadItem: function(args){
+			// summary:
+			// 		Loads an item and calls the callback handler. Note, that this will call the callback
+			// 		handler even if the item is loaded. Consequently, you can use loadItem to ensure
+			// 		that an item is loaded is situations when the item may or may not be loaded yet.
+			// 		If you access a value directly through property access, you can use this to load
+			// 		a lazy value as well (doesn't need to be an item).
+			//
+			//	example:
+			//		store.loadItem({
+			//			item: item, // this item may or may not be loaded
+			//			onItem: function(item){
+			// 				// do something with the item
+			//			}
+			//		});
+
+			var item;
+			if(args.item._loadObject){
+				args.item._loadObject(function(result){
+					item = result; // in synchronous mode this can allow loadItem to return the value
+					delete item._loadObject;
+					var func = result instanceof Error ? args.onError : args.onItem;
+					if(func){
+						func.call(args.scope, result);
+					}
+				});
+			}else if(args.onItem){
+				// even if it is already loaded, we will use call the callback, this makes it easier to
+				// use when it is not known if the item is loaded (you can always safely call loadItem).
+				args.onItem.call(args.scope, args.item);
+			}
+			return item;
+		},
+		_currentId : 0,
+		_processResults : function(results, deferred){
+			// this should return an object with the items as an array and the total count of
+			// items (maybe more than currently in the result set).
+			// for example:
+			//	| {totalCount:10, items: [{id:1},{id:2}]}
+
+			// index the results, assigning ids as necessary
+
+			if(results && typeof results == 'object'){
+				var id = results.__id;
+				if(!id){// if it hasn't been assigned yet
+					if(this.idAttribute){
+						// use the defined id if available
+						id = results[this.idAttribute];
+					}else{
+						id = this._currentId++;
+					}
+					if(id !== undefined){
+						var existingObj = this._index[id];
+						if(existingObj){
+							for(var j in existingObj){
+								delete existingObj[j]; // clear it so we can mixin
+							}
+							results = dojo.mixin(existingObj,results);
+						}
+						results.__id = id;
+						this._index[id] = results;
+					}
+				}
+				for(var i in results){
+					results[i] = this._processResults(results[i], deferred).items;
+				}
+				var count = results.length;
+			}
+			return {totalCount: deferred.request.count == count ? (deferred.request.start || 0) + count * this.estimateCountFactor : count, items: results};
+		},
+		close: function(request){
+			return request && request.abort && request.abort();
+		},
+		fetch: function(args){
+			// summary:
+			//		See dojo.data.api.Read.fetch
+			//
+			// The *queryOptions.cache* parameter
+			//		If true, indicates that the query result should be cached for future use. This is only available
+			// 		if dojox.data.ClientFilter has been loaded before the ServiceStore
+			//
+			//	The *syncMode* parameter
+			//		Indicates that the call should be fetch synchronously if possible (this is not always possible)
+			//
+			// The *clientFetch* parameter
+			//		This is a fetch keyword argument for explicitly doing client side filtering, querying, and paging
+
+			args = args || {};
+
+			if("syncMode" in args ? args.syncMode : this.syncMode){
+				dojox.rpc._sync = true;
+			}
+			var self = this;
+
+			var scope = args.scope || self;
+			var defResult = this.cachingFetch ? this.cachingFetch(args) : this._doQuery(args);
+			defResult.request = args;
+			defResult.addCallback(function(results){
+				if(args.clientFetch){
+					results = self.clientSideFetch({query:args.clientFetch,sort:args.sort,start:args.start,count:args.count},results);
+				}
+				var resultSet = self._processResults(results, defResult);
+				results = args.results = resultSet.items;
+				if(args.onBegin){
+					args.onBegin.call(scope, resultSet.totalCount, args);
+				}
+				if(args.onItem){
+					for(var i=0; i<results.length;i++){
+						args.onItem.call(scope, results[i], args);
+					}
+				}
+				if(args.onComplete){
+					args.onComplete.call(scope, args.onItem ? null : results, args);
+				}
+				return results;
+			});
+			defResult.addErrback(args.onError && function(err){
+				return args.onError.call(scope, err, args);
+			});
+			args.abort = function(){
+				// abort the request
+				defResult.cancel();
+			};
+			args.store = this;
+			return args;
+		},
+		_doQuery: function(args){
+			var query= typeof args.queryStr == 'string' ? args.queryStr : args.query;
+			return this.service(query);
+		},
+		getFeatures: function(){
+			// summary:
+			// 		return the store feature set
+
+			return {
+				"dojo.data.api.Read": true,
+				"dojo.data.api.Identity": true,
+				"dojo.data.api.Schema": this.schema
+			};
+		},
+
+		getLabel: function(item){
+			// summary
+			//		returns the label for an item. Just gets the "label" attribute.
+			//
+			return this.getValue(item,this.labelAttribute);
+		},
+
+		getLabelAttributes: function(item){
+			// summary:
+			//		returns an array of attributes that are used to create the label of an item
+			return [this.labelAttribute];
+		},
+
+		//Identity API Support
+
+
+		getIdentity: function(item){
+			return item.__id;
+		},
+
+		getIdentityAttributes: function(item){
+			// summary:
+			//		returns the attributes which are used to make up the
+			//		identity of an item.	Basically returns this.idAttribute
+
+			return [this.idAttribute];
+		},
+
+		fetchItemByIdentity: function(args){
+			// summary:
+			//		fetch an item by its identity, by looking in our index of what we have loaded
+			var item = this._index[(args._prefix || '') + args.identity];
+			if(item){
+				// the item exists in the index
+				if(item._loadObject){
+					// we have a handle on the item, but it isn't loaded yet, so we need to load it
+					args.item = item;
+					return this.loadItem(args);
+				}else if(args.onItem){
+					// it's already loaded, so we can immediately callback
+					args.onItem.call(args.scope, item);
+				}
+			}else{
+				// convert the different spellings
+				return this.fetch({
+						query: args.identity,
+						onComplete: args.onItem,
+						onError: args.onError,
+						scope: args.scope
+					}).results;
+			}
+			return item;
+		}
+
+	}
+);
diff --git a/dojox/data/SnapLogicStore.js b/dojox/data/SnapLogicStore.js
index e85196a..300e21a 100644
--- a/dojox/data/SnapLogicStore.js
+++ b/dojox/data/SnapLogicStore.js
@@ -1,183 +1,328 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.SnapLogicStore"]){
-dojo._hasResource["dojox.data.SnapLogicStore"]=true;
 dojo.provide("dojox.data.SnapLogicStore");
+
 dojo.require("dojo.io.script");
 dojo.require("dojo.data.util.sorter");
-dojo.declare("dojox.data.SnapLogicStore",null,{Parts:{DATA:"data",COUNT:"count"},url:"",constructor:function(_1){
-if(_1.url){
-this.url=_1.url;
-}
-this._parameters=_1.parameters;
-},_assertIsItem:function(_2){
-if(!this.isItem(_2)){
-throw new Error("dojox.data.SnapLogicStore: a function was passed an item argument that was not an item");
-}
-},_assertIsAttribute:function(_3){
-if(typeof _3!=="string"){
-throw new Error("dojox.data.SnapLogicStore: a function was passed an attribute argument that was not an attribute name string");
-}
-},getFeatures:function(){
-return {"dojo.data.api.Read":true};
-},getValue:function(_4,_5,_6){
-this._assertIsItem(_4);
-this._assertIsAttribute(_5);
-var i=dojo.indexOf(_4.attributes,_5);
-if(i!==-1){
-return _4.values[i];
-}
-return _6;
-},getAttributes:function(_7){
-this._assertIsItem(_7);
-return _7.attributes;
-},hasAttribute:function(_8,_9){
-this._assertIsItem(_8);
-this._assertIsAttribute(_9);
-for(var i=0;i<_8.attributes.length;++i){
-if(_9==_8.attributes[i]){
-return true;
-}
-}
-return false;
-},isItemLoaded:function(_a){
-return this.isItem(_a);
-},loadItem:function(_b){
-},getLabel:function(_c){
-return undefined;
-},getLabelAttributes:function(_d){
-return null;
-},containsValue:function(_e,_f,_10){
-return this.getValue(_e,_f)===_10;
-},getValues:function(_11,_12){
-this._assertIsItem(_11);
-this._assertIsAttribute(_12);
-var i=dojo.indexOf(_11.attributes,_12);
-if(i!==-1){
-return [_11.values[i]];
-}
-return [];
-},isItem:function(_13){
-if(_13&&_13._store===this){
-return true;
-}
-return false;
-},close:function(_14){
-},_fetchHandler:function(_15){
-var _16=_15.scope||dojo.global;
-if(_15.onBegin){
-_15.onBegin.call(_16,_15._countResponse[0],_15);
-}
-if(_15.onItem||_15.onComplete){
-var _17=_15._dataResponse;
-if(!_17.length){
-_15.onError.call(_16,new Error("dojox.data.SnapLogicStore: invalid response of length 0"),_15);
-return;
-}else{
-if(_15.query!="record count"){
-var _18=_17.shift();
-var _19=[];
-for(var i=0;i<_17.length;++i){
-if(_15._aborted){
-break;
-}
-_19.push({attributes:_18,values:_17[i],_store:this});
-}
-if(_15.sort&&!_15._aborted){
-_19.sort(dojo.data.util.sorter.createSortFunction(_15.sort,self));
-}
-}else{
-_19=[({attributes:["count"],values:_17,_store:this})];
-}
-}
-if(_15.onItem){
-for(var i=0;i<_19.length;++i){
-if(_15._aborted){
-break;
-}
-_15.onItem.call(_16,_19[i],_15);
-}
-_19=null;
-}
-if(_15.onComplete&&!_15._aborted){
-_15.onComplete.call(_16,_19,_15);
-}
-}
-},_partHandler:function(_1a,_1b,_1c){
-if(_1c instanceof Error){
-if(_1b==this.Parts.DATA){
-_1a._dataHandle=null;
-}else{
-_1a._countHandle=null;
-}
-_1a._aborted=true;
-if(_1a.onError){
-_1a.onError.call(_1a.scope,_1c,_1a);
-}
-}else{
-if(_1a._aborted){
-return;
-}
-if(_1b==this.Parts.DATA){
-_1a._dataResponse=_1c;
-}else{
-_1a._countResponse=_1c;
-}
-if((!_1a._dataHandle||_1a._dataResponse!==null)&&(!_1a._countHandle||_1a._countResponse!==null)){
-this._fetchHandler(_1a);
-}
-}
-},fetch:function(_1d){
-_1d._countResponse=null;
-_1d._dataResponse=null;
-_1d._aborted=false;
-_1d.abort=function(){
-if(!_1d._aborted){
-_1d._aborted=true;
-if(_1d._dataHandle&&_1d._dataHandle.cancel){
-_1d._dataHandle.cancel();
-}
-if(_1d._countHandle&&_1d._countHandle.cancel){
-_1d._countHandle.cancel();
-}
-}
-};
-if(_1d.onItem||_1d.onComplete){
-var _1e=this._parameters||{};
-if(_1d.start){
-if(_1d.start<0){
-throw new Error("dojox.data.SnapLogicStore: request start value must be 0 or greater");
-}
-_1e["sn.start"]=_1d.start+1;
-}
-if(_1d.count){
-if(_1d.count<0){
-throw new Error("dojox.data.SnapLogicStore: request count value 0 or greater");
-}
-_1e["sn.limit"]=_1d.count;
-}
-_1e["sn.content_type"]="application/javascript";
-var _1f=this;
-var _20=function(_21,_22){
-if(_21 instanceof Error){
-_1f._fetchHandler(_21,_1d);
-}
-};
-var _23={url:this.url,content:_1e,timeout:60000,callbackParamName:"sn.stream_header",handle:dojo.hitch(this,"_partHandler",_1d,this.Parts.DATA)};
-_1d._dataHandle=dojo.io.script.get(_23);
-}
-if(_1d.onBegin){
-var _1e={};
-_1e["sn.count"]="records";
-_1e["sn.content_type"]="application/javascript";
-var _23={url:this.url,content:_1e,timeout:60000,callbackParamName:"sn.stream_header",handle:dojo.hitch(this,"_partHandler",_1d,this.Parts.COUNT)};
-_1d._countHandle=dojo.io.script.get(_23);
-}
-return _1d;
-}});
-}
+
+dojo.declare("dojox.data.SnapLogicStore", null, {
+	Parts: {
+		DATA: "data",
+		COUNT: "count"
+	},
+
+	url: "",
+
+	constructor: function(/* Object */args){
+		//	summary:
+		//		Initialize a SnapLogicStore object.
+		//	args:
+		//		An object that contains properties for initializing the new data store object. The
+		//		following properties are understood:
+		//			url:
+		//				A URL to the SnapLogic pipeline's output routed through PipeToHttp. Typically, this
+		//				will look like "http://<server-host>:<port>/pipe/<pipeline-url>/<pipeline-output-view>".
+		//			parameters:
+		//				An object whose properties define parameters to the pipeline. The values of these
+		//				properties will be sent to the pipeline as parameters when it run.
+		//
+		if(args.url){
+			this.url = args.url;
+		}
+		this._parameters = args.parameters;
+	},
+
+	_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("dojox.data.SnapLogicStore: a function was passed an item argument that was not an item");
+		}
+	},
+
+	_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("dojox.data.SnapLogicStore: a function was passed an attribute argument that was not an attribute name string");
+		}
+	},
+
+	getFeatures: function(){
+		//	summary: 
+		//		See dojo.data.api.Read.getFeatures()
+		return {
+			'dojo.data.api.Read': true
+		};
+	},
+
+	getValue: function(item, attribute, defaultValue){
+		//	summary: 
+		//		See dojo.data.api.Read.getValue()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		var i = dojo.indexOf(item.attributes, attribute);
+		if(i !== -1){
+			return item.values[i];
+		}
+		return defaultValue;
+	},
+
+	getAttributes: function(item){
+		//	summary: 
+		//		See dojo.data.api.Read.getAttributes()
+		this._assertIsItem(item);
+		return item.attributes;
+	},
+
+	hasAttribute: function(item, attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.hasAttributes()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		for(var i = 0; i < item.attributes.length; ++i){
+			if(attribute == item.attributes[i]){
+				return true;
+			}
+		}
+		return false;
+	},
+
+	isItemLoaded: function(item){
+		 //	summary: 
+		 //		 See dojo.data.api.Read.isItemLoaded()
+		 return this.isItem(item);		// Boolean
+	},
+
+	loadItem: function(keywordArgs){
+		//	summary: 
+		//		See dojo.data.api.Read.loadItem()
+	},
+
+	getLabel: function(item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabel()
+		return undefined;
+	},
+	
+	getLabelAttributes: function(item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabelAttributes()
+		return null;
+	},
+
+	containsValue: function(item, attribute, value){
+		//	summary: 
+		//		See dojo.data.api.Read.containsValue()
+		return this.getValue(item, attribute) === value;		// Boolean
+	},
+
+	getValues: function(item, attribute){
+		//	summary: 
+		//		See dojo.data.api.Read.getValue()
+		this._assertIsItem(item);
+		this._assertIsAttribute(attribute);
+		var i = dojo.indexOf(item.attributes, attribute);
+		if(i !== -1){
+			return [item.values[i]];	// Array
+		}
+		return [];
+	},
+
+	isItem: function(item){
+		//	summary: 
+		//		See dojo.data.api.Read.isItem()
+		if(item && item._store === this){
+			return true;
+		}
+		return false;
+	},
+	
+	close: function(request){
+		//	summary: 
+		//		See dojo.data.api.Read.close()
+	},
+
+	_fetchHandler: function(/* Object */request){
+		//	summary: 
+		//		Process data retrieved via fetch and send it back to requester.
+		//	response:
+		//		The data returend from the I/O transport. In the normal case, it will be an array of result rows
+		//		from the pipeline. In the special case for record count optimization, response will be an array
+		//		with a single element containing the total pipeline result row count. See fetch() for details
+		//		on this optimization.
+
+		var scope = request.scope || dojo.global;
+
+		if(request.onBegin){
+			// Check for the record count optimization
+			request.onBegin.call(scope, request._countResponse[0], request);
+		}
+		
+		if(request.onItem || request.onComplete){
+			var response = request._dataResponse;
+
+			if(!response.length){
+				request.onError.call(scope, 
+									 new Error("dojox.data.SnapLogicStore: invalid response of length 0"),
+									 request);
+				return;
+			}else if(request.query != 'record count'){
+				//If this was not a record count request, the first element returned will contain
+				//the field names.
+				var field_names = response.shift();
+				
+				var items = [];
+				for(var i = 0; i < response.length; ++i){
+					if(request._aborted){
+						break;
+					}
+
+					items.push({attributes: field_names, values: response[i], _store: this});
+				}
+
+				if(request.sort && !request._aborted){
+					items.sort(dojo.data.util.sorter.createSortFunction(request.sort, self));
+				}
+			}else{
+				//This is a record count request, so manually set the field names.
+				items = [({attributes: ['count'], values: response, _store: this})];
+			}
+
+			if(request.onItem){
+				for(var i = 0; i < items.length; ++i){
+					if(request._aborted){
+						break;
+					}
+					request.onItem.call(scope, items[i], request);
+				}
+				items = null;
+			}
+
+			if(request.onComplete && !request._aborted){
+				request.onComplete.call(scope, items, request);
+			}
+		}
+	},
+		
+	_partHandler: function(/* Object */request, /* String */part, /* Object */response){
+		//	summary: 
+		//		Handle the individual replies for both data and length requests.
+		//	request:
+		//		The request/handle object used with the original fetch() call.
+		//  part:
+		//		A value indicating which request this handler call is for (this.Parts).
+		//	response:
+		//		Response received from the underlying IO transport.
+
+		if(response instanceof Error){
+			if(part == this.Parts.DATA){
+				request._dataHandle = null;
+			}else{
+				request._countHandle = null;
+			}
+			request._aborted = true;
+			if(request.onError){
+				request.onError.call(request.scope, response, request);
+			}
+		}else{
+			if(request._aborted){
+				return;
+			}
+			if(part == this.Parts.DATA){
+				request._dataResponse = response;
+			}else{
+				request._countResponse = response;
+			}
+			if((!request._dataHandle || request._dataResponse !== null) && 
+				(!request._countHandle || request._countResponse !== null)){
+				this._fetchHandler(request);
+			}
+		}
+	},
+
+	fetch: function(/* Object */request){
+		//	summary: 
+		//		See dojo.data.api.Read.close()
+		//	request:
+		//		See dojo.data.api.Read.close() for generic interface.
+		//
+		//		In addition to the standard Read API fetch support, this store supports an optimization for
+		//		for retrieving the total count of records in the Pipeline without retrieving the data. To
+		//		use this optimization, simply provide an onBegin handler without an onItem or onComplete handler.
+
+		request._countResponse = null;
+		request._dataResponse = null;
+		request._aborted = false;
+		request.abort = function(){
+			if(!request._aborted){
+				request._aborted = true;
+				if(request._dataHandle && request._dataHandle.cancel){
+					request._dataHandle.cancel();
+				}
+				if(request._countHandle && request._countHandle.cancel){
+					request._countHandle.cancel();
+				}
+			}
+		};
+
+		// Only make the call for data if onItem or onComplete is used. Otherwise, onBegin will only
+		// require the total row count.
+		if(request.onItem || request.onComplete){
+			var content = this._parameters || {};
+			if(request.start){
+				if(request.start < 0){
+					throw new Error("dojox.data.SnapLogicStore: request start value must be 0 or greater");
+				}
+				content['sn.start'] = request.start + 1;
+			}
+			if(request.count){
+				if(request.count < 0){
+					throw new Error("dojox.data.SnapLogicStore: request count value 0 or greater");
+				}
+				content['sn.limit'] = request.count;
+			}
+			
+			content['sn.content_type'] = 'application/javascript';
+
+			var store = this;
+			var handler = function(response, ioArgs){
+				if(response instanceof Error){
+					store._fetchHandler(response, request);
+				}
+			};
+
+			var getArgs = {
+				url: this.url,
+				content: content,
+				// preventCache: true,
+				timeout: 60000,								//Starting a pipeline can take a long time.
+				callbackParamName: "sn.stream_header",
+				handle: dojo.hitch(this, "_partHandler", request, this.Parts.DATA)
+			};
+
+			request._dataHandle = dojo.io.script.get(getArgs);
+		}
+		
+		if(request.onBegin){
+			var content = {};
+			content['sn.count'] = 'records';
+			content['sn.content_type'] = 'application/javascript';
+
+			var getArgs = {
+				url: this.url,
+				content: content,
+				timeout: 60000,
+				callbackParamName: "sn.stream_header",
+				handle: dojo.hitch(this, "_partHandler", request, this.Parts.COUNT)
+			};
+
+			request._countHandle = dojo.io.script.get(getArgs);
+		}
+			
+		return request;			// Object
+	}
+});
+
diff --git a/dojox/data/StoreExplorer.js b/dojox/data/StoreExplorer.js
index 3eebc33..f0bbce7 100644
--- a/dojox/data/StoreExplorer.js
+++ b/dojox/data/StoreExplorer.js
@@ -1,150 +1,187 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.StoreExplorer"]){
-dojo._hasResource["dojox.data.StoreExplorer"]=true;
 dojo.provide("dojox.data.StoreExplorer");
 dojo.require("dojox.grid.DataGrid");
 dojo.require("dojox.data.ItemExplorer");
 dojo.require("dijit.layout.BorderContainer");
 dojo.require("dijit.layout.ContentPane");
-dojo.declare("dojox.data.StoreExplorer",dijit.layout.BorderContainer,{constructor:function(_1){
-dojo.mixin(this,_1);
-},store:null,stringQueries:false,postCreate:function(){
-var _2=this;
-this.inherited(arguments);
-var _3=new dijit.layout.ContentPane({region:"top"}).placeAt(this);
-function _4(_5,_6){
-var _7=new dijit.form.Button({label:_5});
-_3.containerNode.appendChild(_7.domNode);
-_7.onClick=_6;
-return _7;
-};
-var _8=_3.containerNode.appendChild(document.createElement("span"));
-_8.innerHTML="Enter query:  ";
-_8.id="queryText";
-var _9=_3.containerNode.appendChild(document.createElement("input"));
-_9.type="text";
-_9.id="queryTextBox";
-_4("Query",function(){
-var _a=_9.value;
-_2.setQuery(_2.stringQueries?_a:dojo.fromJson(_a));
-});
-_3.containerNode.appendChild(document.createElement("span")).innerHTML="   ";
-var _b=_4("Create New",dojo.hitch(this,"createNew"));
-var _c=_4("Delete",function(){
-var _d=_e.selection.getSelected();
-for(var i=0;i<_d.length;i++){
-_2.store.deleteItem(_d[i]);
-}
-});
-this.setItemName=function(_f){
-_b.attr("label","<img style='width:12px; height:12px' src='"+dojo.moduleUrl("dijit.themes.tundra.images","dndCopy.png")+"' /> Create New "+_f);
-_c.attr("label","Delete "+_f);
-};
-_4("Save",function(){
-_2.store.save({onError:function(_10){
-alert(_10);
-}});
-_2.tree.refreshItem();
-});
-_4("Revert",function(){
-_2.store.revert();
-});
-_4("Add Column",function(){
-var _11=prompt("Enter column name:","property");
-if(_11){
-_2.gridLayout.push({field:_11,name:_11,formatter:dojo.hitch(_2,"_formatCell"),editable:true});
-_2.grid.attr("structure",_2.gridLayout);
-}
-});
-var _12=new dijit.layout.ContentPane({region:"center"}).placeAt(this);
-var _e=this.grid=new dojox.grid.DataGrid({store:this.store});
-_12.attr("content",_e);
-_e.canEdit=function(_13,_14){
-var _15=this._copyAttr(_14,_13.field);
-return !(_15&&typeof _15=="object")||_15 instanceof Date;
-};
-var _16=new dijit.layout.ContentPane({region:"trailing",splitter:true,style:"width: 300px"}).placeAt(this);
-var _17=this.tree=new dojox.data.ItemExplorer({store:this.store});
-_16.attr("content",_17);
-dojo.connect(_e,"onCellClick",function(){
-var _18=_e.selection.getSelected()[0];
-_17.setItem(_18);
-});
-this.gridOnFetchComplete=_e._onFetchComplete;
-this.setStore(this.store);
-},setQuery:function(_19){
-this.grid.setQuery(_19);
-},_formatCell:function(_1a){
-if(this.store.isItem(_1a)){
-return this.store.getLabel(_1a)||this.store.getIdentity(_1a);
-}
-return _1a;
-},setStore:function(_1b){
-this.store=_1b;
-var _1c=this;
-var _1d=this.grid;
-_1d._pending_requests[0]=false;
-function _1e(_1f){
-return _1c._formatCell(_1f);
-};
-var _20=this.gridOnFetchComplete;
-_1d._onFetchComplete=function(_21,req){
-var _22=_1c.gridLayout=[];
-var _23,key,_24,i,j,k,_25=_1b.getIdentityAttributes();
-for(i=0;i<_25.length;i++){
-key=_25[i];
-_22.push({field:key,name:key,_score:100,formatter:_1e,editable:false});
-}
-for(i=0;_24=_21[i++];){
-var _26=_1b.getAttributes(_24);
-for(k=0;key=_26[k++];){
-var _27=false;
-for(j=0;_23=_22[j++];){
-if(_23.field==key){
-_23._score++;
-_27=true;
-break;
-}
-}
-if(!_27){
-_22.push({field:key,name:key,_score:1,formatter:_1e,styles:"white-space:nowrap; ",editable:true});
-}
-}
-}
-_22=_22.sort(function(a,b){
-return a._score>b._score?-1:1;
+
+dojo.declare("dojox.data.StoreExplorer", dijit.layout.BorderContainer, {
+	constructor: function(options){
+		dojo.mixin(this, options);
+	},
+	store: null,
+	stringQueries: false,
+	postCreate: function(){
+		var self = this;
+		this.inherited(arguments);
+		var contentPane = new dijit.layout.ContentPane({
+			region:'top'
+		}).placeAt(this);
+		function addButton(name, action){
+			var button = new dijit.form.Button({label: name});
+			contentPane.containerNode.appendChild(button.domNode);
+			button.onClick = action;
+			return button;
+		}
+		var queryText = contentPane.containerNode.appendChild(document.createElement("span"));
+		queryText.innerHTML = "Enter query:  ";
+		queryText.id = "queryText";
+		var queryTextBox = contentPane.containerNode.appendChild(document.createElement("input"));
+		queryTextBox.type = "text";
+		queryTextBox.id = "queryTextBox";
+		addButton("Query",function(){
+			var query = queryTextBox.value;
+			self.setQuery(self.stringQueries ? query : dojo.fromJson(query));
+		});
+		contentPane.containerNode.appendChild(document.createElement("span")).innerHTML = "   ";
+		var createNewButton = addButton("Create New", dojo.hitch(this, "createNew"));
+		var deleteButton = addButton("Delete",function(){
+			var items = grid.selection.getSelected();
+			for(var i = 0; i < items.length; i++){
+				self.store.deleteItem(items[i]);
+			}
+		});
+		this.setItemName = function(name){
+			createNewButton.attr('label',"<img style='width:12px; height:12px' src='" + dojo.moduleUrl("dijit.themes.tundra.images","dndCopy.png") + "' /> Create New " + name);
+			deleteButton.attr('label',"Delete " + name);
+		}
+		addButton("Save",function(){
+			self.store.save({onError:function(error){
+				alert(error);
+			}});
+			//refresh the tree
+			self.tree.refreshItem();
+		});
+		addButton("Revert",function(){
+			self.store.revert();
+		});
+		addButton("Add Column", function(){
+			var columnName = prompt("Enter column name:","property");
+			if(columnName){
+				self.gridLayout.push({
+						field: columnName,
+						name: columnName,
+						formatter: dojo.hitch(self,"_formatCell"),
+						editable: true
+					});
+				self.grid.attr("structure",self.gridLayout);
+			}
+		});
+		var centerCP = new dijit.layout.ContentPane({
+			region:'center'
+		}).placeAt(this);
+		var grid = this.grid = new dojox.grid.DataGrid(
+				{store: this.store}
+			);
+		centerCP.attr("content", grid);
+		grid.canEdit = function(inCell, inRowIndex){
+			var value = this._copyAttr(inRowIndex, inCell.field);
+			return !(value && typeof value == 'object') || value instanceof Date;
+		}
+
+		var trailingCP = new dijit.layout.ContentPane({
+			region: 'trailing',
+			splitter: true,
+			style: "width: 300px"
+		}).placeAt(this);
+
+		var tree = this.tree = new dojox.data.ItemExplorer({
+			store: this.store}
+			);
+		trailingCP.attr("content", tree);
+
+		dojo.connect(grid, "onCellClick", function(){
+			var selected = grid.selection.getSelected()[0];
+			tree.setItem(selected);
+		});
+
+		this.gridOnFetchComplete = grid._onFetchComplete;
+		this.setStore(this.store);
+	},
+	setQuery: function(query, options){
+		this.grid.setQuery(query, options);
+	},
+	_formatCell: function(value){
+		if(this.store.isItem(value)){
+			return this.store.getLabel(value) || this.store.getIdentity(value);
+		}
+		return value;
+	},
+	setStore: function(store){
+		this.store = store;
+		var self = this;
+		var grid = this.grid;
+		grid._pending_requests[0] = false;
+		function formatCell(value){
+			return self._formatCell(value);
+		}
+		var defaultOnComplete = this.gridOnFetchComplete;
+		grid._onFetchComplete = function(items, req){
+			var layout = self.gridLayout = [];
+			var column, key, item, i, j, k, idAttributes = store.getIdentityAttributes();
+			for(i = 0; i < idAttributes.length; i++){
+				key = idAttributes[i];
+				layout.push({
+					field: key,
+					name: key,
+					_score: 100,
+					formatter: formatCell,
+					editable: false
+				});
+
+			}
+			for(i=0; item = items[i++];){
+				var keys = store.getAttributes(item);
+				for(k=0; key = keys[k++];){
+					var found = false;
+					for(j=0; column = layout[j++];){
+						if(column.field == key){
+							column._score++;
+							found = true;
+							break;
+						}
+					}
+					if(!found){
+						layout.push({
+							field: key,
+							name: key,
+							_score: 1,
+							formatter: formatCell,
+							styles: "white-space:nowrap; ",
+							editable: true
+						});
+					}
+				}
+			}
+			layout = layout.sort(function(a, b){
+				return a._score > b._score ? -1 : 1;
+			});
+			for(j=0; column = layout[j]; j++){
+				if(column._score < items.length/40 * j){
+					layout.splice(j,layout.length-j);
+					break;
+				}
+			}
+			for(j=0; column = layout[j++];){
+				column.width=Math.round(100/layout.length) + '%';
+			}
+			grid._onFetchComplete = defaultOnComplete;
+			grid.attr("structure",layout);
+			var retValue = defaultOnComplete.apply(this, arguments);
+
+		}
+ 		grid.setStore(store);
+ 		this.queryOptions = {cache:true};
+		this.tree.setStore(store);
+	},
+	createNew: function(){
+		var props = prompt("Enter any properties (in JSON literal form) to put in the new item (passed to the newItem constructor):","{ }");
+		if(props){
+			try{
+				this.store.newItem(dojo.fromJson(props));
+			}catch(e){
+				alert(e);
+			}
+
+		}
+	}
 });
-for(j=0;_23=_22[j];j++){
-if(_23._score<_21.length/40*j){
-_22.splice(j,_22.length-j);
-break;
-}
-}
-for(j=0;_23=_22[j++];){
-_23.width=Math.round(100/_22.length)+"%";
-}
-_1d._onFetchComplete=_20;
-_1d.attr("structure",_22);
-var _28=_20.apply(this,arguments);
-};
-_1d.setStore(_1b);
-this.queryOptions={cache:true};
-this.tree.setStore(_1b);
-},createNew:function(){
-var _29=prompt("Enter any properties (in JSON literal form) to put in the new item (passed to the newItem constructor):","{ }");
-if(_29){
-try{
-this.store.newItem(dojo.fromJson(_29));
-}
-catch(e){
-alert(e);
-}
-}
-}});
-}
diff --git a/dojox/data/WikipediaStore.js b/dojox/data/WikipediaStore.js
index 4d24e29..deb134a 100644
--- a/dojox/data/WikipediaStore.js
+++ b/dojox/data/WikipediaStore.js
@@ -1,63 +1,115 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.WikipediaStore"]){
-dojo._hasResource["dojox.data.WikipediaStore"]=true;
 dojo.provide("dojox.data.WikipediaStore");
+
 dojo.require("dojo.io.script");
 dojo.require("dojox.rpc.Service");
 dojo.require("dojox.data.ServiceStore");
+
 dojo.experimental("dojox.data.WikipediaStore");
-dojo.declare("dojox.data.WikipediaStore",dojox.data.ServiceStore,{constructor:function(_1){
-if(_1&&_1.service){
-this.service=_1.service;
-}else{
-var _2=new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.SMDLibrary","wikipedia.smd"));
-this.service=_2.query;
-}
-this.idAttribute=this.labelAttribute="title";
-},fetch:function(_3){
-var rq=dojo.mixin({},_3.query);
-if(rq&&(!rq.action||rq.action==="parse")){
-rq.action="parse";
-rq.page=rq.title;
-delete rq.title;
-}else{
-if(rq.action==="query"){
-rq.list="search";
-rq.srwhat="text";
-rq.srsearch=rq.text;
-if(_3.start){
-rq.sroffset=_3.start-1;
-}
-if(_3.count){
-rq.srlimit=_3.count>=500?500:_3.count;
-}
-delete rq.text;
-}
-}
-_3.query=rq;
-return this.inherited(arguments);
-},_processResults:function(_4,_5){
-if(_4.parse){
-_4.parse.title=dojo.queryToObject(_5.ioArgs.url.split("?")[1]).page;
-_4=[_4.parse];
-}else{
-if(_4.query&&_4.query.search){
-_4=_4.query.search;
-var _6=this;
-for(var i in _4){
-_4[i]._loadObject=function(_7){
-_6.fetch({query:{action:"parse",title:this.title},onItem:_7});
-delete this._loadObject;
-};
-}
-}
-}
-return this.inherited(arguments);
-}});
-}
+
+dojo.declare("dojox.data.WikipediaStore", dojox.data.ServiceStore,{
+	//	summary:
+	//		Initializer for the Wikipedia data store interface.
+	//	description:
+	//		The WikipediaStore is a data store interface to Wikipedia, using the
+	//		Wikipedia SMD spec from dojox.rpc. It currently is useful only for
+	//		finding articles that contain some particular text or grabbing single
+	//		articles by full name; no wildcards or other filtering are supported.
+	//	example:
+	//		|	var store = new dojox.data.WikipediaStore();
+	//		|	store.fetch({
+	//		|		query: {title:"Dojo Toolkit"},
+	//		|		onItem: function(item){
+	//		|			dojo.byId("somediv").innerHTML = item.text["*"];
+	//		|		}
+	//		|	});
+	constructor: function(options){
+		if(options && options.service){
+			this.service = options.service;
+		}else{
+			var svc = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.SMDLibrary", "wikipedia.smd"));
+			this.service = svc.query;
+		}
+
+		this.idAttribute = this.labelAttribute = "title";
+	},
+
+	fetch: function(/* object */ request){
+		//	summary:
+		//		Fetch a page or some partially-loaded search results from
+		//		Wikipedia. Note that there isn't a way to sort data coming
+		//		in from the API, so we just ignore the *sort* parameter.
+		//	example:
+		//		Loading a page:
+		//		|	store.fetch({
+		//		|		query: {title:"Dojo Toolkit"},
+		//		|		// define your handlers here
+		//		|	});
+		//	example:
+		//		Searching for pages containing "dojo":
+		//		|	store.fetch({
+		//		|		query: {
+		//		|			action: "query",
+		//		|			text: "dojo"
+		//		|		},
+		//		|		// define your handlers here
+		//		|	});
+		//	example:
+		//		Searching for the next 50 pages containing "dojo":
+		//		|	store.fetch({
+		//		|		query: {
+		//		|			action: "query",
+		//		|			text: "dojo",
+		//		|			start: 10,
+		//		|			count: 50 // max 500; will be capped if necessary
+		//		|		},
+		//		|		// define your handlers here
+		//		|	});
+		var rq = dojo.mixin({}, request.query);
+		if(rq && (!rq.action || rq.action === "parse")){
+			// default to a single page fetch
+			rq.action = "parse";
+			rq.page = rq.title;
+			delete rq.title;
+
+		}else if(rq.action === "query"){
+			// perform a full text search on page content
+			rq.list = "search";
+			rq.srwhat = "text";
+			rq.srsearch = rq.text;
+			if(request.start){
+				rq.sroffset = request.start-1;
+			}
+			if(request.count){
+				rq.srlimit = request.count >= 500 ? 500 : request.count;
+			}
+			delete rq.text;
+		}
+		request.query = rq;
+		return this.inherited(arguments);
+	},
+
+	_processResults: function(results, def){
+		if(results.parse){
+			// loading a complete page
+			results.parse.title = dojo.queryToObject(def.ioArgs.url.split("?")[1]).page;
+			results = [results.parse];
+
+		}else if(results.query && results.query.search){
+			// loading some search results; all we have here is page titles,
+			// so we mark our items as incomplete
+			results = results.query.search;
+			var _thisStore = this;
+			for(var i in results){
+				results[i]._loadObject = function(callback){
+					_thisStore.fetch({
+						query: { action:"parse", title:this.title },
+						onItem: callback
+					});
+					delete this._loadObject;
+				}
+			}
+		}
+		return this.inherited(arguments);
+	}
+});
+
diff --git a/dojox/data/XmlStore.js b/dojox/data/XmlStore.js
index ff69b9a..a4a3962 100644
--- a/dojox/data/XmlStore.js
+++ b/dojox/data/XmlStore.js
@@ -1,934 +1,1517 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.XmlStore"]){
-dojo._hasResource["dojox.data.XmlStore"]=true;
 dojo.provide("dojox.data.XmlStore");
 dojo.provide("dojox.data.XmlItem");
+
 dojo.require("dojo.data.util.simpleFetch");
 dojo.require("dojo.data.util.filter");
 dojo.require("dojox.xml.parser");
-dojo.declare("dojox.data.XmlStore",null,{constructor:function(_1){
-if(_1){
-this.url=_1.url;
-this.rootItem=(_1.rootItem||_1.rootitem||this.rootItem);
-this.keyAttribute=(_1.keyAttribute||_1.keyattribute||this.keyAttribute);
-this._attributeMap=(_1.attributeMap||_1.attributemap);
-this.label=_1.label||this.label;
-this.sendQuery=(_1.sendQuery||_1.sendquery||this.sendQuery);
-if("urlPreventCache" in _1){
-this.urlPreventCache=_1.urlPreventCache?true:false;
-}
-}
-this._newItems=[];
-this._deletedItems=[];
-this._modifiedItems=[];
-},url:"",rootItem:"",keyAttribute:"",label:"",sendQuery:false,attributeMap:null,urlPreventCache:true,getValue:function(_2,_3,_4){
-var _5=_2.element;
-var i;
-var _6;
-if(_3==="tagName"){
-return _5.nodeName;
-}else{
-if(_3==="childNodes"){
-for(i=0;i<_5.childNodes.length;i++){
-_6=_5.childNodes[i];
-if(_6.nodeType===1){
-return this._getItem(_6);
-}
-}
-return _4;
-}else{
-if(_3==="text()"){
-for(i=0;i<_5.childNodes.length;i++){
-_6=_5.childNodes[i];
-if(_6.nodeType===3||_6.nodeType===4){
-return _6.nodeValue;
-}
-}
-return _4;
-}else{
-_3=this._getAttribute(_5.nodeName,_3);
-if(_3.charAt(0)==="@"){
-var _7=_3.substring(1);
-var _8=_5.getAttribute(_7);
-return (_8)?_8:_4;
-}else{
-for(i=0;i<_5.childNodes.length;i++){
-_6=_5.childNodes[i];
-if(_6.nodeType===1&&_6.nodeName===_3){
-return this._getItem(_6);
-}
-}
-return _4;
-}
-}
-}
-}
-},getValues:function(_9,_a){
-var _b=_9.element;
-var _c=[];
-var i;
-var _d;
-if(_a==="tagName"){
-return [_b.nodeName];
-}else{
-if(_a==="childNodes"){
-for(i=0;i<_b.childNodes.length;i++){
-_d=_b.childNodes[i];
-if(_d.nodeType===1){
-_c.push(this._getItem(_d));
-}
-}
-return _c;
-}else{
-if(_a==="text()"){
-var ec=_b.childNodes;
-for(i=0;i<ec.length;i++){
-_d=ec[i];
-if(_d.nodeType===3||_d.nodeType===4){
-_c.push(_d.nodeValue);
-}
-}
-return _c;
-}else{
-_a=this._getAttribute(_b.nodeName,_a);
-if(_a.charAt(0)==="@"){
-var _e=_a.substring(1);
-var _f=_b.getAttribute(_e);
-return (_f!==undefined)?[_f]:[];
-}else{
-for(i=0;i<_b.childNodes.length;i++){
-_d=_b.childNodes[i];
-if(_d.nodeType===1&&_d.nodeName===_a){
-_c.push(this._getItem(_d));
-}
-}
-return _c;
-}
-}
-}
-}
-},getAttributes:function(_10){
-var _11=_10.element;
-var _12=[];
-var i;
-_12.push("tagName");
-if(_11.childNodes.length>0){
-var _13={};
-var _14=true;
-var _15=false;
-for(i=0;i<_11.childNodes.length;i++){
-var _16=_11.childNodes[i];
-if(_16.nodeType===1){
-var _17=_16.nodeName;
-if(!_13[_17]){
-_12.push(_17);
-_13[_17]=_17;
-}
-_14=true;
-}else{
-if(_16.nodeType===3){
-_15=true;
-}
-}
-}
-if(_14){
-_12.push("childNodes");
-}
-if(_15){
-_12.push("text()");
-}
-}
-for(i=0;i<_11.attributes.length;i++){
-_12.push("@"+_11.attributes[i].nodeName);
-}
-if(this._attributeMap){
-for(var key in this._attributeMap){
-i=key.indexOf(".");
-if(i>0){
-var _18=key.substring(0,i);
-if(_18===_11.nodeName){
-_12.push(key.substring(i+1));
-}
-}else{
-_12.push(key);
-}
-}
-}
-return _12;
-},hasAttribute:function(_19,_1a){
-return (this.getValue(_19,_1a)!==undefined);
-},containsValue:function(_1b,_1c,_1d){
-var _1e=this.getValues(_1b,_1c);
-for(var i=0;i<_1e.length;i++){
-if((typeof _1d==="string")){
-if(_1e[i].toString&&_1e[i].toString()===_1d){
-return true;
-}
-}else{
-if(_1e[i]===_1d){
-return true;
-}
-}
-}
-return false;
-},isItem:function(_1f){
-if(_1f&&_1f.element&&_1f.store&&_1f.store===this){
-return true;
-}
-return false;
-},isItemLoaded:function(_20){
-return this.isItem(_20);
-},loadItem:function(_21){
-},getFeatures:function(){
-var _22={"dojo.data.api.Read":true,"dojo.data.api.Write":true};
-if(!this.sendQuery||this.keyAttribute!==""){
-_22["dojo.data.api.Identity"]=true;
-}
-return _22;
-},getLabel:function(_23){
-if((this.label!=="")&&this.isItem(_23)){
-var _24=this.getValue(_23,this.label);
-if(_24){
-return _24.toString();
-}
-}
-return undefined;
-},getLabelAttributes:function(_25){
-if(this.label!==""){
-return [this.label];
-}
-return null;
-},_fetchItems:function(_26,_27,_28){
-var url=this._getFetchUrl(_26);
-if(!url){
-_28(new Error("No URL specified."));
-return;
-}
-var _29=(!this.sendQuery?_26:{});
-var _2a=this;
-var _2b={url:url,handleAs:"xml",preventCache:_2a.urlPreventCache};
-var _2c=dojo.xhrGet(_2b);
-_2c.addCallback(function(_2d){
-var _2e=_2a._getItems(_2d,_29);
-if(_2e&&_2e.length>0){
-_27(_2e,_26);
-}else{
-_27([],_26);
-}
-});
-_2c.addErrback(function(_2f){
-_28(_2f,_26);
-});
-},_getFetchUrl:function(_30){
-if(!this.sendQuery){
-return this.url;
-}
-var _31=_30.query;
-if(!_31){
-return this.url;
-}
-if(dojo.isString(_31)){
-return this.url+_31;
-}
-var _32="";
-for(var _33 in _31){
-var _34=_31[_33];
-if(_34){
-if(_32){
-_32+="&";
-}
-_32+=(_33+"="+_34);
-}
-}
-if(!_32){
-return this.url;
-}
-var _35=this.url;
-if(_35.indexOf("?")<0){
-_35+="?";
-}else{
-_35+="&";
-}
-return _35+_32;
-},_getItems:function(_36,_37){
-var _38=null;
-if(_37){
-_38=_37.query;
-}
-var _39=[];
-var _3a=null;
-if(this.rootItem!==""){
-_3a=dojo.query(this.rootItem,_36);
-}else{
-_3a=_36.documentElement.childNodes;
-}
-var _3b=_37.queryOptions?_37.queryOptions.deep:false;
-if(_3b){
-_3a=this._flattenNodes(_3a);
-}
-for(var i=0;i<_3a.length;i++){
-var _3c=_3a[i];
-if(_3c.nodeType!=1){
-continue;
-}
-var _3d=this._getItem(_3c);
-if(_38){
-var _3e=_37.queryOptions?_37.queryOptions.ignoreCase:false;
-var _3f;
-var _40=false;
-var j;
-var _41=true;
-var _42={};
-for(var key in _38){
-_3f=_38[key];
-if(typeof _3f==="string"){
-_42[key]=dojo.data.util.filter.patternToRegExp(_3f,_3e);
-}
-}
-for(var _43 in _38){
-_41=false;
-var _44=this.getValues(_3d,_43);
-for(j=0;j<_44.length;j++){
-_3f=_44[j];
-if(_3f){
-var _45=_38[_43];
-if((typeof _3f)==="string"&&(_42[_43])){
-if((_3f.match(_42[_43]))!==null){
-_40=true;
-}else{
-_40=false;
-}
-}else{
-if((typeof _3f)==="object"){
-if(_3f.toString&&(_42[_43])){
-var _46=_3f.toString();
-if((_46.match(_42[_43]))!==null){
-_40=true;
-}else{
-_40=false;
-}
-}else{
-if(_45==="*"||_45===_3f){
-_40=true;
-}else{
-_40=false;
-}
-}
-}
-}
-}
-if(_40){
-break;
-}
-}
-if(!_40){
-break;
-}
-}
-if(_41||_40){
-_39.push(_3d);
-}
-}else{
-_39.push(_3d);
-}
-}
-dojo.forEach(_39,function(_47){
-if(_47.element.parentNode){
-_47.element.parentNode.removeChild(_47.element);
-}
-},this);
-return _39;
-},_flattenNodes:function(_48){
-var _49=[];
-if(_48){
-var i;
-for(i=0;i<_48.length;i++){
-var _4a=_48[i];
-_49.push(_4a);
-if(_4a.childNodes&&_4a.childNodes.length>0){
-_49=_49.concat(this._flattenNodes(_4a.childNodes));
-}
-}
-}
-return _49;
-},close:function(_4b){
-},newItem:function(_4c,_4d){
-_4c=(_4c||{});
-var _4e=_4c.tagName;
-if(!_4e){
-_4e=this.rootItem;
-if(_4e===""){
-return null;
-}
-}
-var _4f=this._getDocument();
-var _50=_4f.createElement(_4e);
-for(var _51 in _4c){
-var _52;
-if(_51==="tagName"){
-continue;
-}else{
-if(_51==="text()"){
-_52=_4f.createTextNode(_4c[_51]);
-_50.appendChild(_52);
-}else{
-_51=this._getAttribute(_4e,_51);
-if(_51.charAt(0)==="@"){
-var _53=_51.substring(1);
-_50.setAttribute(_53,_4c[_51]);
-}else{
-var _54=_4f.createElement(_51);
-_52=_4f.createTextNode(_4c[_51]);
-_54.appendChild(_52);
-_50.appendChild(_54);
-}
-}
-}
-}
-var _55=this._getItem(_50);
-this._newItems.push(_55);
-var _56=null;
-if(_4d&&_4d.parent&&_4d.attribute){
-_56={item:_4d.parent,attribute:_4d.attribute,oldValue:undefined};
-var _57=this.getValues(_4d.parent,_4d.attribute);
-if(_57&&_57.length>0){
-var _58=_57.slice(0,_57.length);
-if(_57.length===1){
-_56.oldValue=_57[0];
-}else{
-_56.oldValue=_57.slice(0,_57.length);
-}
-_58.push(_55);
-this.setValues(_4d.parent,_4d.attribute,_58);
-_56.newValue=this.getValues(_4d.parent,_4d.attribute);
-}else{
-this.setValues(_4d.parent,_4d.attribute,_55);
-_56.newValue=_55;
-}
-}
-return _55;
-},deleteItem:function(_59){
-var _5a=_59.element;
-if(_5a.parentNode){
-this._backupItem(_59);
-_5a.parentNode.removeChild(_5a);
-return true;
-}
-this._forgetItem(_59);
-this._deletedItems.push(_59);
-return true;
-},setValue:function(_5b,_5c,_5d){
-if(_5c==="tagName"){
-return false;
-}
-this._backupItem(_5b);
-var _5e=_5b.element;
-var _5f;
-var _60;
-if(_5c==="childNodes"){
-_5f=_5d.element;
-_5e.appendChild(_5f);
-}else{
-if(_5c==="text()"){
-while(_5e.firstChild){
-_5e.removeChild(_5e.firstChild);
-}
-_60=this._getDocument(_5e).createTextNode(_5d);
-_5e.appendChild(_60);
-}else{
-_5c=this._getAttribute(_5e.nodeName,_5c);
-if(_5c.charAt(0)==="@"){
-var _61=_5c.substring(1);
-_5e.setAttribute(_61,_5d);
-}else{
-for(var i=0;i<_5e.childNodes.length;i++){
-var _62=_5e.childNodes[i];
-if(_62.nodeType===1&&_62.nodeName===_5c){
-_5f=_62;
-break;
-}
-}
-var _63=this._getDocument(_5e);
-if(_5f){
-while(_5f.firstChild){
-_5f.removeChild(_5f.firstChild);
-}
-}else{
-_5f=_63.createElement(_5c);
-_5e.appendChild(_5f);
-}
-_60=_63.createTextNode(_5d);
-_5f.appendChild(_60);
-}
-}
-}
-return true;
-},setValues:function(_64,_65,_66){
-if(_65==="tagName"){
-return false;
-}
-this._backupItem(_64);
-var _67=_64.element;
-var i;
-var _68;
-var _69;
-if(_65==="childNodes"){
-while(_67.firstChild){
-_67.removeChild(_67.firstChild);
-}
-for(i=0;i<_66.length;i++){
-_68=_66[i].element;
-_67.appendChild(_68);
-}
-}else{
-if(_65==="text()"){
-while(_67.firstChild){
-_67.removeChild(_67.firstChild);
-}
-var _6a="";
-for(i=0;i<_66.length;i++){
-_6a+=_66[i];
-}
-_69=this._getDocument(_67).createTextNode(_6a);
-_67.appendChild(_69);
-}else{
-_65=this._getAttribute(_67.nodeName,_65);
-if(_65.charAt(0)==="@"){
-var _6b=_65.substring(1);
-_67.setAttribute(_6b,_66[0]);
-}else{
-for(i=_67.childNodes.length-1;i>=0;i--){
-var _6c=_67.childNodes[i];
-if(_6c.nodeType===1&&_6c.nodeName===_65){
-_67.removeChild(_6c);
-}
-}
-var _6d=this._getDocument(_67);
-for(i=0;i<_66.length;i++){
-_68=_6d.createElement(_65);
-_69=_6d.createTextNode(_66[i]);
-_68.appendChild(_69);
-_67.appendChild(_68);
-}
-}
-}
-}
-return true;
-},unsetAttribute:function(_6e,_6f){
-if(_6f==="tagName"){
-return false;
-}
-this._backupItem(_6e);
-var _70=_6e.element;
-if(_6f==="childNodes"||_6f==="text()"){
-while(_70.firstChild){
-_70.removeChild(_70.firstChild);
-}
-}else{
-_6f=this._getAttribute(_70.nodeName,_6f);
-if(_6f.charAt(0)==="@"){
-var _71=_6f.substring(1);
-_70.removeAttribute(_71);
-}else{
-for(var i=_70.childNodes.length-1;i>=0;i--){
-var _72=_70.childNodes[i];
-if(_72.nodeType===1&&_72.nodeName===_6f){
-_70.removeChild(_72);
-}
-}
-}
-}
-return true;
-},save:function(_73){
-if(!_73){
-_73={};
-}
-var i;
-for(i=0;i<this._modifiedItems.length;i++){
-this._saveItem(this._modifiedItems[i],_73,"PUT");
-}
-for(i=0;i<this._newItems.length;i++){
-var _74=this._newItems[i];
-if(_74.element.parentNode){
-this._newItems.splice(i,1);
-i--;
-continue;
-}
-this._saveItem(this._newItems[i],_73,"POST");
-}
-for(i=0;i<this._deletedItems.length;i++){
-this._saveItem(this._deletedItems[i],_73,"DELETE");
-}
-},revert:function(){
-this._newItems=[];
-this._restoreItems(this._deletedItems);
-this._deletedItems=[];
-this._restoreItems(this._modifiedItems);
-this._modifiedItems=[];
-return true;
-},isDirty:function(_75){
-if(_75){
-var _76=this._getRootElement(_75.element);
-return (this._getItemIndex(this._newItems,_76)>=0||this._getItemIndex(this._deletedItems,_76)>=0||this._getItemIndex(this._modifiedItems,_76)>=0);
-}else{
-return (this._newItems.length>0||this._deletedItems.length>0||this._modifiedItems.length>0);
-}
-},_saveItem:function(_77,_78,_79){
-var url;
-var _7a;
-if(_79==="PUT"){
-url=this._getPutUrl(_77);
-}else{
-if(_79==="DELETE"){
-url=this._getDeleteUrl(_77);
-}else{
-url=this._getPostUrl(_77);
-}
-}
-if(!url){
-if(_78.onError){
-_7a=_78.scope||dojo.global;
-_78.onError.call(_7a,new Error("No URL for saving content: "+this._getPostContent(_77)));
-}
-return;
-}
-var _7b={url:url,method:(_79||"POST"),contentType:"text/xml",handleAs:"xml"};
-var _7c;
-if(_79==="PUT"){
-_7b.putData=this._getPutContent(_77);
-_7c=dojo.rawXhrPut(_7b);
-}else{
-if(_79==="DELETE"){
-_7c=dojo.xhrDelete(_7b);
-}else{
-_7b.postData=this._getPostContent(_77);
-_7c=dojo.rawXhrPost(_7b);
-}
-}
-_7a=(_78.scope||dojo.global);
-var _7d=this;
-_7c.addCallback(function(_7e){
-_7d._forgetItem(_77);
-if(_78.onComplete){
-_78.onComplete.call(_7a);
-}
-});
-_7c.addErrback(function(_7f){
-if(_78.onError){
-_78.onError.call(_7a,_7f);
-}
-});
-},_getPostUrl:function(_80){
-return this.url;
-},_getPutUrl:function(_81){
-return this.url;
-},_getDeleteUrl:function(_82){
-var url=this.url;
-if(_82&&this.keyAttribute!==""){
-var _83=this.getValue(_82,this.keyAttribute);
-if(_83){
-var key=this.keyAttribute.charAt(0)==="@"?this.keyAttribute.substring(1):this.keyAttribute;
-url+=url.indexOf("?")<0?"?":"&";
-url+=key+"="+_83;
-}
-}
-return url;
-},_getPostContent:function(_84){
-var _85=_84.element;
-var _86="<?xml version=\"1.0\"?>";
-return _86+dojox.xml.parser.innerXML(_85);
-},_getPutContent:function(_87){
-var _88=_87.element;
-var _89="<?xml version=\"1.0\"?>";
-return _89+dojox.xml.parser.innerXML(_88);
-},_getAttribute:function(_8a,_8b){
-if(this._attributeMap){
-var key=_8a+"."+_8b;
-var _8c=this._attributeMap[key];
-if(_8c){
-_8b=_8c;
-}else{
-_8c=this._attributeMap[_8b];
-if(_8c){
-_8b=_8c;
-}
-}
-}
-return _8b;
-},_getItem:function(_8d){
-try{
-var q=null;
-if(this.keyAttribute===""){
-q=this._getXPath(_8d);
-}
-return new dojox.data.XmlItem(_8d,this,q);
-}
-catch(e){
-}
-return null;
-},_getItemIndex:function(_8e,_8f){
-for(var i=0;i<_8e.length;i++){
-if(_8e[i].element===_8f){
-return i;
-}
-}
-return -1;
-},_backupItem:function(_90){
-var _91=this._getRootElement(_90.element);
-if(this._getItemIndex(this._newItems,_91)>=0||this._getItemIndex(this._modifiedItems,_91)>=0){
-return;
-}
-if(_91!=_90.element){
-_90=this._getItem(_91);
-}
-_90._backup=_91.cloneNode(true);
-this._modifiedItems.push(_90);
-},_restoreItems:function(_92){
-dojo.forEach(_92,function(_93){
-if(_93._backup){
-_93.element=_93._backup;
-_93._backup=null;
-}
-},this);
-},_forgetItem:function(_94){
-var _95=_94.element;
-var _96=this._getItemIndex(this._newItems,_95);
-if(_96>=0){
-this._newItems.splice(_96,1);
-}
-_96=this._getItemIndex(this._deletedItems,_95);
-if(_96>=0){
-this._deletedItems.splice(_96,1);
-}
-_96=this._getItemIndex(this._modifiedItems,_95);
-if(_96>=0){
-this._modifiedItems.splice(_96,1);
-}
-},_getDocument:function(_97){
-if(_97){
-return _97.ownerDocument;
-}else{
-if(!this._document){
-return dojox.xml.parser.parse();
-}
-}
-return null;
-},_getRootElement:function(_98){
-while(_98.parentNode){
-_98=_98.parentNode;
-}
-return _98;
-},_getXPath:function(_99){
-var _9a=null;
-if(!this.sendQuery){
-var _9b=_99;
-_9a="";
-while(_9b&&_9b!=_99.ownerDocument){
-var pos=0;
-var _9c=_9b;
-var _9d=_9b.nodeName;
-while(_9c){
-_9c=_9c.previousSibling;
-if(_9c&&_9c.nodeName===_9d){
-pos++;
-}
-}
-var _9e="/"+_9d+"["+pos+"]";
-if(_9a){
-_9a=_9e+_9a;
-}else{
-_9a=_9e;
-}
-_9b=_9b.parentNode;
-}
-}
-return _9a;
-},getIdentity:function(_9f){
-if(!this.isItem(_9f)){
-throw new Error("dojox.data.XmlStore: Object supplied to getIdentity is not an item");
-}else{
-var id=null;
-if(this.sendQuery&&this.keyAttribute!==""){
-id=this.getValue(_9f,this.keyAttribute).toString();
-}else{
-if(!this.serverQuery){
-if(this.keyAttribute!==""){
-id=this.getValue(_9f,this.keyAttribute).toString();
-}else{
-id=_9f.q;
-}
-}
-}
-return id;
-}
-},getIdentityAttributes:function(_a0){
-if(!this.isItem(_a0)){
-throw new Error("dojox.data.XmlStore: Object supplied to getIdentity is not an item");
-}else{
-if(this.keyAttribute!==""){
-return [this.keyAttribute];
-}else{
-return null;
-}
-}
-},fetchItemByIdentity:function(_a1){
-var _a2=null;
-var _a3=null;
-var _a4=this;
-var url=null;
-var _a5=null;
-var _a6=null;
-if(!_a4.sendQuery){
-_a2=function(_a7){
-if(_a7){
-if(_a4.keyAttribute!==""){
-var _a8={};
-_a8.query={};
-_a8.query[_a4.keyAttribute]=_a1.identity;
-_a8.queryOptions={deep:true};
-var _a9=_a4._getItems(_a7,_a8);
-_a3=_a1.scope||dojo.global;
-if(_a9.length===1){
-if(_a1.onItem){
-_a1.onItem.call(_a3,_a9[0]);
-}
-}else{
-if(_a9.length===0){
-if(_a1.onItem){
-_a1.onItem.call(_a3,null);
-}
-}else{
-if(_a1.onError){
-_a1.onError.call(_a3,new Error("Items array size for identity lookup greater than 1, invalid keyAttribute."));
-}
-}
-}
-}else{
-var _aa=_a1.identity.split("/");
-var i;
-var _ab=_a7;
-for(i=0;i<_aa.length;i++){
-if(_aa[i]&&_aa[i]!==""){
-var _ac=_aa[i];
-_ac=_ac.substring(0,_ac.length-1);
-var _ad=_ac.split("[");
-var tag=_ad[0];
-var _ae=parseInt(_ad[1],10);
-var pos=0;
-if(_ab){
-var _af=_ab.childNodes;
-if(_af){
-var j;
-var _b0=null;
-for(j=0;j<_af.length;j++){
-var _b1=_af[j];
-if(_b1.nodeName===tag){
-if(pos<_ae){
-pos++;
-}else{
-_b0=_b1;
-break;
-}
-}
-}
-if(_b0){
-_ab=_b0;
-}else{
-_ab=null;
-}
-}else{
-_ab=null;
-}
-}else{
-break;
-}
-}
-}
-var _b2=null;
-if(_ab){
-_b2=_a4._getItem(_ab);
-if(_b2.element.parentNode){
-_b2.element.parentNode.removeChild(_b2.element);
-}
-}
-if(_a1.onItem){
-_a3=_a1.scope||dojo.global;
-_a1.onItem.call(_a3,_b2);
-}
-}
-}
-};
-url=this._getFetchUrl(null);
-_a5={url:url,handleAs:"xml",preventCache:_a4.urlPreventCache};
-_a6=dojo.xhrGet(_a5);
-_a6.addCallback(_a2);
-if(_a1.onError){
-_a6.addErrback(function(_b3){
-var s=_a1.scope||dojo.global;
-_a1.onError.call(s,_b3);
+
+dojo.declare("dojox.data.XmlStore", null, {
+	//	summary:
+	//		A data store for XML based services or documents
+	//	description:
+	//		A data store for XML based services or documents
+	
+	constructor: function(/* object */ args){
+		//	summary:
+		//		Constructor for the XML store.  
+		//	args:
+		//		An anonymous object to initialize properties.  It expects the following values:
+		//		url:		The url to a service or an XML document that represents the store
+		//		rootItem:	A tag name for root items
+		//		keyAttribute:	An attribute name for a key or an identity (unique identifier)
+		//						Required for serverside fetchByIdentity, etc.  Not required for 
+		//						client side fetchItemBIdentity, as it will use an XPath-like
+		//						structure if keyAttribute was not specified.  Recommended to always
+		//						set this, though, for consistent identity behavior.
+		// 		attributeMap:   An anonymous object contains properties for attribute mapping,
+		//						{"tag_name.item_attribute_name": "@xml_attribute_name", ...}
+		//		sendQuery:		A boolean indicate to add a query string to the service URL.  
+		//						Default is false.
+		//		urlPreventCache: Parameter to indicate whether or not URL calls should apply 
+		//		                 the preventCache option to the xhr request.
+		if(args){
+			this.url = args.url;
+			this.rootItem = (args.rootItem || args.rootitem || this.rootItem);
+			this.keyAttribute = (args.keyAttribute || args.keyattribute || this.keyAttribute);
+			this._attributeMap = (args.attributeMap || args.attributemap);
+			this.label = args.label || this.label;
+			this.sendQuery = (args.sendQuery || args.sendquery || this.sendQuery);
+			if("urlPreventCache" in args){
+				this.urlPreventCache = args.urlPreventCache?true:false;
+			}
+		}
+		this._newItems = [];
+		this._deletedItems = [];
+		this._modifiedItems = [];
+	},
+
+	//Values that may be set by the parser.  
+	//Ergo, have to be instantiated to something
+	//So the parser knows how to set them.
+	url: "",
+
+	//	A tag name for XML tags to be considered root items in the hierarchy
+	rootItem: "",
+
+	//	An attribute name for a key or an identity (unique identifier)
+	//	Required for serverside fetchByIdentity, etc.  Not required for
+	//	client side fetchItemBIdentity, as it will use an XPath-like
+	//	structure if keyAttribute was not specified.  Recommended to always
+	//	set this, though, for consistent identity behavior.
+	keyAttribute: "",
+
+	//	An attribute of the item to use as the label.
+	label: "",
+
+	//	A boolean indicate to add a query string to the service URL.
+	//	Default is false.
+	sendQuery: false,
+
+	//	An anonymous object that contains properties for attribute mapping, 
+	//	for example {"tag_name.item_attribute_name": "@xml_attribute_name", ...}. 
+	//	This is optional. This is done so that attributes which are actual 
+	//	XML tag attributes (and not sub-tags of an XML tag), can be referenced.
+	attributeMap: null,
+
+	//	Parameter to indicate whether or not URL calls should apply the preventCache option to the xhr request.
+	urlPreventCache: true,
+
+	/* dojo.data.api.Read */
+
+	getValue: function(/* item */ item, /* attribute || attribute-name-string */ attribute, /* value? */ defaultValue){
+		//	summary:
+		//		Return an attribute value
+		//	description:
+		//		'item' must be an instance of a dojox.data.XmlItem from the store instance.
+		//		If 'attribute' specifies "tagName", the tag name of the element is
+		//		returned.
+		//		If 'attribute' specifies "childNodes", the first element child is
+		//		returned.
+		//		If 'attribute' specifies "text()", the value of the first text
+		//		child is returned.
+		//		For generic attributes, if '_attributeMap' is specified,
+		//		an actual attribute name is looked up with the tag name of
+		//		the element and 'attribute' (concatenated with '.').
+		//		Then, if 'attribute' starts with "@", the value of the XML
+		//		attribute is returned.
+		//		Otherwise, the first child element of the tag name specified with
+		//		'attribute' is returned.
+		//	item:
+		//		An XML element that holds the attribute
+		//	attribute:
+		//		A tag name of a child element, An XML attribute name or one of
+		// 		special names
+		//	defaultValue:
+		//		A default value
+		//	returns:
+		//		An attribute value found, otherwise 'defaultValue'
+		var element = item.element;
+		var i;
+		var node;
+		if(attribute === "tagName"){
+			return element.nodeName;
+		}else if(attribute === "childNodes"){
+			for(i = 0; i < element.childNodes.length; i++){
+				node = element.childNodes[i];
+				if(node.nodeType === 1 /*ELEMENT_NODE*/){
+					return this._getItem(node); //object
+				}
+			}
+			return defaultValue;
+		}else if(attribute === "text()"){
+			for(i = 0; i < element.childNodes.length; i++){
+				node = element.childNodes[i];
+				if(node.nodeType === 3 /*TEXT_NODE*/ ||
+					node.nodeType === 4 /*CDATA_SECTION_NODE*/){
+					return node.nodeValue; //string
+				}
+			}
+			return defaultValue;
+		}else{
+			attribute = this._getAttribute(element.nodeName, attribute);
+			if(attribute.charAt(0) === '@'){
+				var name = attribute.substring(1);
+				var value = element.getAttribute(name);
+				//Note that getAttribute will return null or empty string for undefined/unset 
+				//attributes, therefore, we should just check the return was valid
+				//non-empty string and not null.
+				return (value) ? value : defaultValue; //object
+			}else{
+				for(i = 0; i < element.childNodes.length; i++){
+					node = element.childNodes[i];
+					if(	node.nodeType === 1 /*ELEMENT_NODE*/ &&
+						node.nodeName === attribute){
+						return this._getItem(node); //object
+					}
+				}
+				return defaultValue; //object
+			}
+		}
+	},
+
+	getValues: function(/* item */ item, /* attribute || attribute-name-string */ attribute){
+		//	summary:
+		//		Return an array of attribute values
+		//	description:
+		//		'item' must be an instance of a dojox.data.XmlItem from the store instance.
+		//		If 'attribute' specifies "tagName", the tag name of the element is
+		//		returned.
+		//		If 'attribute' specifies "childNodes", child elements are returned.
+		//		If 'attribute' specifies "text()", the values of child text nodes
+		//		are returned.
+		//		For generic attributes, if 'attributeMap' is specified,
+		//		an actual attribute name is looked up with the tag name of
+		//		the element and 'attribute' (concatenated with '.').
+		//		Then, if 'attribute' starts with "@", the value of the XML
+		//		attribute is returned.
+		//		Otherwise, child elements of the tag name specified with
+		//		'attribute' are returned.
+		//	item:
+		//		An XML element that holds the attribute
+		//	attribute:
+		//		A tag name of child elements, An XML attribute name or one of
+		//		special names
+		//	returns:
+		//		An array of attribute values found, otherwise an empty array
+		var element = item.element;
+		var values = [];
+		var i;
+		var node;
+		if(attribute === "tagName"){
+			return [element.nodeName];
+		}else if(attribute === "childNodes"){
+			for(i = 0; i < element.childNodes.length; i++){
+				node = element.childNodes[i];
+				if(node.nodeType === 1 /*ELEMENT_NODE*/){
+					values.push(this._getItem(node));
+				}
+			}
+			return values; //array
+		}else if(attribute === "text()"){
+			var ec = element.childNodes;
+			for(i = 0; i < ec.length; i++){
+				node = ec[i];
+				if(node.nodeType === 3 || node.nodeType === 4){
+					values.push(node.nodeValue);
+				}
+			}
+			return values; //array
+		}else{
+			attribute = this._getAttribute(element.nodeName, attribute);
+			if(attribute.charAt(0) === '@'){
+				var name = attribute.substring(1);
+				var value = element.getAttribute(name);
+				return (value !== undefined) ? [value] : []; //array
+			}else{
+				for(i = 0; i < element.childNodes.length; i++){
+					node = element.childNodes[i];
+					if(	node.nodeType === 1 /*ELEMENT_NODE*/ &&
+						node.nodeName === attribute){
+						values.push(this._getItem(node));
+					}
+				}
+				return values; //array
+			}
+		}
+	},
+
+	getAttributes: function(/* item */ item){
+		//	summary:
+		//		Return an array of attribute names
+		// 	description:
+		//		'item' must be an instance of a dojox.data.XmlItem from the store instance.
+		//		tag names of child elements and XML attribute names of attributes
+		//		specified to the element are returned along with special attribute
+		//		names applicable to the element including "tagName", "childNodes"
+		//		if the element has child elements, "text()" if the element has
+		//		child text nodes, and attribute names in '_attributeMap' that match
+		//		the tag name of the element.
+		//	item:
+		//		An XML element
+		//	returns:
+		//		An array of attributes found
+		var element = item.element;
+		var attributes = [];
+		var i;
+		attributes.push("tagName");
+		if(element.childNodes.length > 0){
+			var names = {};
+			var childNodes = true;
+			var text = false;
+			for(i = 0; i < element.childNodes.length; i++){
+				var node = element.childNodes[i];
+				if(node.nodeType === 1 /*ELEMENT_NODE*/){
+					var name = node.nodeName;
+					if(!names[name]){
+						attributes.push(name);
+						names[name] = name;
+					}
+					childNodes = true;
+				}else if(node.nodeType === 3){
+					text = true;
+				}
+			}
+			if(childNodes){
+				attributes.push("childNodes");
+			}
+			if(text){
+				attributes.push("text()");
+			}
+		}
+		for(i = 0; i < element.attributes.length; i++){
+			attributes.push("@" + element.attributes[i].nodeName);
+		}
+		if(this._attributeMap){
+			for(var key in this._attributeMap){
+				i = key.indexOf('.');
+				if(i > 0){
+					var tagName = key.substring(0, i);
+					if(tagName === element.nodeName){
+						attributes.push(key.substring(i + 1));
+					}
+				}else{ // global attribute
+					attributes.push(key);
+				}
+			}
+		}
+		return attributes; //array
+	},
+
+	hasAttribute: function(/* item */ item, /* attribute || attribute-name-string */ attribute){
+		//	summary:
+		//		Check whether an element has the attribute
+		//	item:
+		//		'item' must be an instance of a dojox.data.XmlItem from the store instance.
+		//	attribute:
+		//		A tag name of a child element, An XML attribute name or one of
+		//		special names
+		//	returns:
+		//		True if the element has the attribute, otherwise false
+		return (this.getValue(item, attribute) !== undefined); //boolean
+	},
+
+	containsValue: function(/* item */ item, /* attribute || attribute-name-string */ attribute, /* anything */ value){
+		//	summary:
+		//		Check whether the attribute values contain the value
+		//	item:
+		//		'item' must be an instance of a dojox.data.XmlItem from the store instance.
+		//	attribute:
+		//		A tag name of a child element, An XML attribute name or one of
+		//		special names
+		//	returns:
+		//		True if the attribute values contain the value, otherwise false
+		var values = this.getValues(item, attribute);
+		for(var i = 0; i < values.length; i++){
+			if((typeof value === "string")){
+				if(values[i].toString && values[i].toString() === value){
+					return true;
+				}
+			}else if(values[i] === value){
+				return true; //boolean
+			}
+		}
+		return false;//boolean
+	},
+
+	isItem: function(/* anything */ something){
+		//	summary:
+		//		Check whether the object is an item (XML element)
+		//	item:
+		//		An object to check
+		// 	returns:
+		//		True if the object is an XML element, otherwise false
+		if(something && something.element && something.store && something.store === this){
+			return true; //boolean
+		}
+		return false; //boolran
+	},
+
+	isItemLoaded: function(/* anything */ something){
+		//	summary:
+		//		Check whether the object is an item (XML element) and loaded
+		//	item:
+		//		An object to check
+		//	returns:
+		//		True if the object is an XML element, otherwise false
+		return this.isItem(something); //boolean
+	},
+
+	loadItem: function(/* object */ keywordArgs){
+		//	summary:
+		//		Load an item (XML element)
+		//	keywordArgs:
+		//		object containing the args for loadItem.  See dojo.data.api.Read.loadItem()
+	},
+
+	getFeatures: function(){
+		//	summary:
+		//		Return supported data APIs
+		//	returns:
+		//		"dojo.data.api.Read" and "dojo.data.api.Write"
+		var features = {
+			"dojo.data.api.Read": true,
+			"dojo.data.api.Write": true
+		};
+
+		//Local XML parsing can implement Identity fairly simple via 
+		if(!this.sendQuery || this.keyAttribute !== ""){
+			features["dojo.data.api.Identity"] = true;
+		}
+		return features; //array
+	},
+
+	getLabel: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabel()
+		if((this.label !== "") && this.isItem(item)){
+			var label = this.getValue(item,this.label);
+			if(label){
+				return label.toString();
+			}
+		}
+		return undefined; //undefined
+	},
+
+	getLabelAttributes: function(/* item */ item){
+		//	summary: 
+		//		See dojo.data.api.Read.getLabelAttributes()
+		if(this.label !== ""){
+			return [this.label]; //array
+		}
+		return null; //null
+	},
+
+	_fetchItems: function(request, fetchHandler, errorHandler){
+		//	summary:
+		//		Fetch items (XML elements) that match to a query
+		//	description:
+		//		If 'sendQuery' is true, an XML document is loaded from
+		//		'url' with a query string.
+		//		Otherwise, an XML document is loaded and list XML elements that
+		//		match to a query (set of element names and their text attribute
+		//		values that the items to contain).
+		//		A wildcard, "*" can be used to query values to match all
+		//		occurrences.
+		//		If 'rootItem' is specified, it is used to fetch items.
+		//	request:
+		//		A request object
+		//	fetchHandler:
+		//		A function to call for fetched items
+		//	errorHandler:
+		//		A function to call on error
+		var url = this._getFetchUrl(request);
+		console.log("XmlStore._fetchItems(): url=" + url);
+		if(!url){
+			errorHandler(new Error("No URL specified."));
+			return;
+		}
+		var localRequest = (!this.sendQuery ? request : {}); // use request for _getItems()
+
+		var self = this;
+		var getArgs = {
+				url: url,
+				handleAs: "xml",
+				preventCache: self.urlPreventCache
+			};
+		var getHandler = dojo.xhrGet(getArgs);
+		getHandler.addCallback(function(data){
+			var items = self._getItems(data, localRequest);
+			console.log("XmlStore._fetchItems(): length=" + (items ? items.length : 0));
+			if(items && items.length > 0){
+				fetchHandler(items, request);
+			}else{
+				fetchHandler([], request);
+			}
+		});
+		getHandler.addErrback(function(data){
+			errorHandler(data, request);
+		});
+	},
+
+	_getFetchUrl: function(request){
+		//	summary:
+		//		Generate a URL for fetch
+		//	description:
+		//		This default implementation generates a query string in the form of
+		//		"?name1=value1&name2=value2..." off properties of 'query' object
+		//		specified in 'request' and appends it to 'url', if 'sendQuery'
+		//		is set to false.
+		//		Otherwise, 'url' is returned as is.
+		//		Sub-classes may override this method for the custom URL generation.
+		//	request:
+		//		A request object
+		//	returns:
+		//		A fetch URL
+		if(!this.sendQuery){
+			return this.url;
+		}
+		var query = request.query;
+		if(!query){
+			return this.url;
+		}
+		if(dojo.isString(query)){
+			return this.url + query;
+		}
+		var queryString = "";
+		for(var name in query){
+			var value = query[name];
+			if(value){
+				if(queryString){
+					queryString += "&";
+				}
+				queryString += (name + "=" + value);
+			}
+		}
+		if(!queryString){
+			return this.url;
+		}
+		//Check to see if the URL already has query params or not.
+		var fullUrl = this.url;
+		if(fullUrl.indexOf("?") < 0){
+			fullUrl += "?";
+		}else{
+			fullUrl += "&";
+		}
+		return fullUrl + queryString;
+	},
+
+	_getItems: function(document, request){
+		//	summary:
+		//		Fetch items (XML elements) in an XML document based on a request
+		//	description:
+		//		This default implementation walks through child elements of
+		//		the document element to see if all properties of 'query' object
+		//		match corresponding attributes of the element (item).
+		//		If 'request' is not specified, all child elements are returned.
+		//		Sub-classes may override this method for the custom search in
+		//		an XML document.
+		//	document:
+		//		An XML document
+		//	request:
+		//		A request object
+		//	returns:
+		//		An array of items
+		var query = null;
+		if(request){
+			query = request.query;
+		}
+		var items = [];
+		var nodes = null;
+
+		if(this.rootItem !== ""){
+			nodes = dojo.query(this.rootItem, document);
+		}else{
+			nodes = document.documentElement.childNodes;
+		}
+
+		var deep = request.queryOptions ? request.queryOptions.deep : false; 
+		if(deep){
+			nodes = this._flattenNodes(nodes);
+		}
+		for(var i = 0; i < nodes.length; i++){
+			var node = nodes[i];
+			if(node.nodeType != 1 /*ELEMENT_NODE*/){
+				continue;
+			}
+			var item = this._getItem(node);
+			if(query){
+				var ignoreCase = request.queryOptions ? request.queryOptions.ignoreCase : false; 
+				var value;
+				var match = false;
+				var j;
+				var emptyQuery = true;
+
+				//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(var key in query){
+					value = query[key];
+					if(typeof value === "string"){
+						regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
+					}
+				}
+				for(var attribute in query){
+					emptyQuery = false;
+					var values = this.getValues(item, attribute);
+					for(j = 0; j < values.length; j++){
+						value = values[j];
+						if(value){
+							var queryValue = query[attribute];
+							if((typeof value) === "string" && 
+								(regexpList[attribute])){
+								if((value.match(regexpList[attribute])) !== null){
+									match = true;
+								}else{
+									match = false;
+								}
+							}else if((typeof value) === "object"){
+								if(	value.toString && 
+									(regexpList[attribute])){
+									var stringValue = value.toString();
+									if((stringValue.match(regexpList[attribute])) !== null){
+										match = true;
+									}else{
+										match = false;
+									}
+								}else{
+									if(queryValue === "*" || queryValue === value){
+										match = true;
+									}else{
+										match = false;
+									}
+								}
+							}
+						}
+						//One of the multiValue values matched, 
+						//so quit looking.
+						if(match){
+							break;
+						}
+					}
+					if(!match){
+						break;
+					}
+				}
+				//Either the query was an empty object {}, which is match all, or 
+				//was an actual match.
+				if(emptyQuery || match){
+					items.push(item);
+				}
+			}else{
+				//No query, everything matches.
+				items.push(item);
+			}
+		}
+		dojo.forEach(items,function(item){
+			if(item.element.parentNode){
+				item.element.parentNode.removeChild(item.element); // make it root
+			}
+		},this);
+		return items;
+	},
+
+	_flattenNodes: function(nodes){
+		//	Summary:	
+		//		Function used to flatten a hierarchy of XML nodes into a single list for
+		//		querying over.  Used when deep = true;
+		var flattened = [];
+		if(nodes){
+			var i;
+			for(i = 0; i < nodes.length; i++){
+				var node = nodes[i];
+				flattened.push(node);
+				if(node.childNodes && node.childNodes.length > 0){
+					flattened = flattened.concat(this._flattenNodes(node.childNodes));
+				}
+			}
+		}
+		return flattened;
+	},
+
+	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+		 //	summary: 
+		 //		See dojo.data.api.Read.close()
+	},
+
+/* dojo.data.api.Write */
+
+	newItem: function(/* object? */ keywordArgs, parentInfo){
+		//	summary:
+		//		Return a new dojox.data.XmlItem
+		//	description:
+		//		At least, 'keywordArgs' must contain "tagName" to be used for
+		//		the new	element.
+		//		Other attributes in 'keywordArgs' are set to the new element,
+		//		including "text()", but excluding "childNodes".
+		// 	keywordArgs:
+		//		An object containing initial attributes
+		//	returns:
+		//		An XML element
+		console.log("XmlStore.newItem()");
+		keywordArgs = (keywordArgs || {});
+		var tagName = keywordArgs.tagName;
+		if(!tagName){
+			tagName = this.rootItem;
+			if(tagName === ""){
+				return null;
+			}
+		}
+
+		var document = this._getDocument();
+		var element = document.createElement(tagName);
+		for(var attribute in keywordArgs){
+			var text;
+			if(attribute === "tagName"){
+				continue;
+			}else if(attribute === "text()"){
+				text = document.createTextNode(keywordArgs[attribute]);
+				element.appendChild(text);
+			}else{
+				attribute = this._getAttribute(tagName, attribute);
+				if(attribute.charAt(0) === '@'){
+					var name = attribute.substring(1);
+					element.setAttribute(name, keywordArgs[attribute]);
+				}else{
+					var child = document.createElement(attribute);
+					text = document.createTextNode(keywordArgs[attribute]);
+					child.appendChild(text);
+					element.appendChild(child);
+				}
+			}
+		}
+
+		var item = this._getItem(element);
+		this._newItems.push(item);
+
+		var pInfo = null;
+		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(item);
+				this.setValues(parentInfo.parent, parentInfo.attribute, tempValues);
+				pInfo.newValue = this.getValues(parentInfo.parent, parentInfo.attribute);
+			}else{
+				this.setValues(parentInfo.parent, parentInfo.attribute, item);
+				pInfo.newValue = item;
+			}
+		}
+		return item; //object
+	},
+	
+	deleteItem: function(/* item */ item){
+		//	summary:
+		//		Delete an dojox.data.XmlItem (wrapper to a XML element).
+		//	item:
+		//		An XML element to delete
+		//	returns:
+		//		True
+		console.log("XmlStore.deleteItem()");
+		var element = item.element;
+		if(element.parentNode){
+			this._backupItem(item);
+			element.parentNode.removeChild(element);
+			return true;
+		}
+		this._forgetItem(item);
+		this._deletedItems.push(item);
+		return true; //boolean
+	},
+	
+	setValue: function(/* item */ item, /* attribute || string */ attribute, /* almost anything */ value){
+		//	summary:
+		//		Set an attribute value
+		//	description:
+		//		'item' must be an instance of a dojox.data.XmlItem from the store instance.
+		//		If 'attribute' specifies "tagName", nothing is set and false is
+		//		returned.
+		//		If 'attribute' specifies "childNodes", the value (XML element) is
+		//		added to the element.
+		//		If 'attribute' specifies "text()", a text node is created with
+		//		the value and set it to the element as a child.
+		//		For generic attributes, if '_attributeMap' is specified,
+		//		an actual attribute name is looked up with the tag name of
+		//		the element and 'attribute' (concatenated with '.').
+		//		Then, if 'attribute' starts with "@", the value is set to the XML
+		//		attribute.
+		//		Otherwise, a text node is created with the value and set it to
+		//		the first child element of the tag name specified with 'attribute'.
+		//		If the child element does not exist, it is created.
+		//	item:
+		//		An XML element that holds the attribute
+		//	attribute:
+		//		A tag name of a child element, An XML attribute name or one of
+		//		special names
+		//	value:
+		//		A attribute value to set
+		//	returns:
+		//		False for "tagName", otherwise true
+		if(attribute === "tagName"){
+			return false; //boolean
+		}
+
+		this._backupItem(item);
+
+		var element = item.element;
+		var child;
+		var text;
+		if(attribute === "childNodes"){
+			child = value.element;
+			element.appendChild(child);
+		}else if(attribute === "text()"){
+			while(element.firstChild){
+				element.removeChild(element.firstChild);
+			}
+			text = this._getDocument(element).createTextNode(value);
+			element.appendChild(text);
+		}else{
+			attribute = this._getAttribute(element.nodeName, attribute);
+			if(attribute.charAt(0) === '@'){
+				var name = attribute.substring(1);
+				element.setAttribute(name, value);
+			}else{
+				for(var i = 0; i < element.childNodes.length; i++){
+					var node = element.childNodes[i];
+					if(	node.nodeType === 1 /*ELEMENT_NODE*/ &&
+						node.nodeName === attribute){
+						child = node;
+						break;
+					}
+				}
+				var document = this._getDocument(element);
+				if(child){
+					while(child.firstChild){
+						child.removeChild(child.firstChild);
+					}
+				}else{
+					child = document.createElement(attribute);
+					element.appendChild(child);
+				}
+				text = document.createTextNode(value);
+				child.appendChild(text);
+			}
+		}
+		return true; //boolean
+	},
+		
+	setValues: function(/* item */ item, /* attribute || string */ attribute, /*array*/ values){
+		//	summary:
+		//		Set attribute values
+		//	description:
+		//		'item' must be an instance of a dojox.data.XmlItem from the store instance.
+		//		If 'attribute' specifies "tagName", nothing is set and false is
+		//		returned.
+		//		If 'attribute' specifies "childNodes", the value (array of XML
+		//		elements) is set to the element's childNodes.
+		//		If 'attribute' specifies "text()", a text node is created with
+		//		the values and set it to the element as a child.
+		//		For generic attributes, if '_attributeMap' is specified,
+		//		an actual attribute name is looked up with the tag name of
+		//		the element and 'attribute' (concatenated with '.').
+		//		Then, if 'attribute' starts with "@", the first value is set to
+		//		the XML attribute.
+		//		Otherwise, child elements of the tag name specified with
+		//		'attribute' are replaced with new child elements and their
+		//		child text nodes of values.
+		//	item:
+		//		An XML element that holds the attribute
+		//	attribute:
+		//		A tag name of child elements, an XML attribute name or one of
+		//		special names
+		//	value:
+		//		A attribute value to set
+		//	notify:
+		//		A non-API optional argument, used to indicate if notification API should be called
+		//		or not.
+
+		//	returns:
+		//		False for "tagName", otherwise true
+		if(attribute === "tagName"){
+			return false; //boolean
+		}
+
+		this._backupItem(item);
+
+		var element = item.element;
+		var i;
+		var child;
+		var text;
+		if(attribute === "childNodes"){
+			while(element.firstChild){
+				element.removeChild(element.firstChild);
+			}
+			for(i = 0; i < values.length; i++){
+				child = values[i].element;
+				element.appendChild(child);
+			}
+		}else if(attribute === "text()"){
+			while(element.firstChild){
+				element.removeChild(element.firstChild);
+			}
+			var value = "";
+			for(i = 0; i < values.length; i++){
+				value += values[i];
+			}
+			text = this._getDocument(element).createTextNode(value);
+			element.appendChild(text);
+		}else{
+			attribute = this._getAttribute(element.nodeName, attribute);
+			if(attribute.charAt(0) === '@'){
+				var name = attribute.substring(1);
+				element.setAttribute(name, values[0]);
+			}else{
+				for(i = element.childNodes.length - 1; i >= 0; i--){
+					var node = element.childNodes[i];
+					if(	node.nodeType === 1 /*ELEMENT_NODE*/ &&
+						node.nodeName === attribute){
+						element.removeChild(node);
+					}
+				}
+				var document = this._getDocument(element);
+				for(i = 0; i < values.length; i++){
+					child = document.createElement(attribute);
+					text = document.createTextNode(values[i]);
+					child.appendChild(text);
+					element.appendChild(child);
+				}
+			}
+		}
+		return true; //boolean
+	},
+	
+	unsetAttribute: function(/* item */ item, /* attribute || string */ attribute){
+		//	summary:
+		//		Remove an attribute
+		//	description:
+		//		'item' must be an instance of a dojox.data.XmlItem from the store instance.
+		//		'attribute' can be an XML attribute name of the element or one of
+		//		special names described below.
+		//		If 'attribute' specifies "tagName", nothing is removed and false is
+		//		returned.
+		//		If 'attribute' specifies "childNodes" or "text()", all child nodes
+		//		are removed.
+		//		For generic attributes, if '_attributeMap' is specified,
+		//		an actual attribute name is looked up with the tag name of
+		//		the element and 'attribute' (concatenated with '.').
+		//		Then, if 'attribute' starts with "@", the XML attribute is removed.
+		//		Otherwise, child elements of the tag name specified with
+		//		'attribute' are removed.
+		//	item:
+		//		An XML element that holds the attribute
+		//	attribute:
+		//		A tag name of child elements, an XML attribute name or one of
+		//		special names
+		//	returns:
+		//		False for "tagName", otherwise true
+		if(attribute === "tagName"){
+			return false; //boolean
+		}
+
+		this._backupItem(item);
+
+		var element = item.element;
+		if(attribute === "childNodes" || attribute === "text()"){
+			while(element.firstChild){
+				element.removeChild(element.firstChild);
+			}
+		}else{
+			attribute = this._getAttribute(element.nodeName, attribute);
+			if(attribute.charAt(0) === '@'){
+				var name = attribute.substring(1);
+				element.removeAttribute(name);
+			}else{
+				for(var i = element.childNodes.length - 1; i >= 0; i--){
+					var node = element.childNodes[i];
+					if(	node.nodeType === 1 /*ELEMENT_NODE*/ &&
+						node.nodeName === attribute){
+						element.removeChild(node);
+					}
+				}
+			}
+		}
+		return true; //boolean
+	},
+	
+	save: function(/* object */ keywordArgs){
+		//	summary:
+		//		Save new and/or modified items (XML elements)
+		// 	description:
+		//		'url' is used to save XML documents for new, modified and/or
+		//		deleted XML elements.
+		// 	keywordArgs:
+		//		An object for callbacks
+		if(!keywordArgs){
+			keywordArgs = {};
+		}
+		var i;
+		for(i = 0; i < this._modifiedItems.length; i++){
+			this._saveItem(this._modifiedItems[i], keywordArgs, "PUT");
+		}
+		for(i = 0; i < this._newItems.length; i++){
+			var item = this._newItems[i];
+			if(item.element.parentNode){ // reparented
+				this._newItems.splice(i, 1);
+				i--;
+				continue;
+			}
+			this._saveItem(this._newItems[i], keywordArgs, "POST");
+		}
+		for(i = 0; i < this._deletedItems.length; i++){
+			this._saveItem(this._deletedItems[i], keywordArgs, "DELETE");
+		}
+	},
+
+	revert: function(){
+		// summary:
+		//	Invalidate changes (new and/or modified elements)
+		// returns:
+		//	True
+		console.log("XmlStore.revert() _newItems=" + this._newItems.length);
+		console.log("XmlStore.revert() _deletedItems=" + this._deletedItems.length);
+		console.log("XmlStore.revert() _modifiedItems=" + this._modifiedItems.length);
+		this._newItems = [];
+		this._restoreItems(this._deletedItems);
+		this._deletedItems = [];
+		this._restoreItems(this._modifiedItems);
+		this._modifiedItems = [];
+		return true; //boolean
+	},
+	
+	isDirty: function(/* item? */ item){
+		//	summary:
+		//		Check whether an item is new, modified or deleted
+		//	description:
+		//		If 'item' is specified, true is returned if the item is new,
+		//		modified or deleted.
+		//		Otherwise, true is returned if there are any new, modified
+		//		or deleted items.
+		//	item:
+		//		An item (XML element) to check
+		//	returns:
+		//		True if an item or items are new, modified or deleted, otherwise
+		//		false
+		if(item){
+			var element = this._getRootElement(item.element);
+			return (this._getItemIndex(this._newItems, element) >= 0 ||
+				this._getItemIndex(this._deletedItems, element) >= 0 ||
+				this._getItemIndex(this._modifiedItems, element) >= 0); //boolean
+		}else{
+			return (this._newItems.length > 0 ||
+				this._deletedItems.length > 0 ||
+				this._modifiedItems.length > 0); //boolean
+		}
+	},
+
+	_saveItem: function(item, keywordArgs, method){
+		var url;
+		var scope;
+		if(method === "PUT"){
+			url = this._getPutUrl(item);
+		}else if(method === "DELETE"){
+			url = this._getDeleteUrl(item);
+		}else{ // POST
+			url = this._getPostUrl(item);
+		}
+		if(!url){
+			if(keywordArgs.onError){
+				scope = keywordArgs.scope || dojo.global;
+				keywordArgs.onError.call(scope, new Error("No URL for saving content: " + this._getPostContent(item)));
+			}
+			return;
+		}
+
+		var saveArgs = {
+			url: url,
+			method: (method || "POST"),
+			contentType: "text/xml",
+			handleAs: "xml"
+		};
+		var saveHandler;
+		if(method === "PUT"){
+			saveArgs.putData = this._getPutContent(item);
+			saveHandler = dojo.rawXhrPut(saveArgs);
+		}else if(method === "DELETE"){
+			saveHandler = dojo.xhrDelete(saveArgs);
+		}else{ // POST
+			saveArgs.postData = this._getPostContent(item);
+			saveHandler = dojo.rawXhrPost(saveArgs);
+		}
+		scope = (keywordArgs.scope || dojo.global);
+		var self = this;
+		saveHandler.addCallback(function(data){
+			self._forgetItem(item);
+			if(keywordArgs.onComplete){
+				keywordArgs.onComplete.call(scope);
+			}
+		});
+		saveHandler.addErrback(function(error){
+			if(keywordArgs.onError){
+				keywordArgs.onError.call(scope, error);
+			}
+		});
+	},
+
+	_getPostUrl: function(item){
+		//	summary:
+		//		Generate a URL for post
+		//	description:
+		//		This default implementation just returns 'url'.
+		//		Sub-classes may override this method for the custom URL.
+		//	item:
+		//		An item to save
+		//	returns:
+		//		A post URL
+		return this.url; //string
+	},
+
+	_getPutUrl: function(item){
+		//	summary:
+		//		Generate a URL for put
+		//	description:
+		//		This default implementation just returns 'url'.
+		//		Sub-classes may override this method for the custom URL.
+		//	item:
+		//		An item to save
+		//	returns:
+		//		A put URL
+		return this.url; //string
+	},
+
+	_getDeleteUrl: function(item){
+		//	summary:
+		//		Generate a URL for delete
+		// 	description:
+		//		This default implementation returns 'url' with 'keyAttribute'
+		//		as a query string.
+		//		Sub-classes may override this method for the custom URL based on
+		//		changes (new, deleted, or modified).
+		// 	item:
+		//		An item to delete
+		// 	returns:
+		//		A delete URL
+		var url = this.url;
+		if(item && this.keyAttribute !== ""){
+			var value = this.getValue(item, this.keyAttribute);
+			if(value){
+				var key = this.keyAttribute.charAt(0) ==='@' ? this.keyAttribute.substring(1): this.keyAttribute;
+				url += url.indexOf('?') < 0 ? '?' : '&';
+				url += key + '=' + value;
+			}
+		}
+		return url;	//string
+	},
+
+	_getPostContent: function(item){
+		//	summary:
+		//		Generate a content to post
+		// 	description:
+		//		This default implementation generates an XML document for one
+		//		(the first only) new or modified element.
+		//		Sub-classes may override this method for the custom post content
+		//		generation.
+		//	item:
+		//		An item to save
+		//	returns:
+		//		A post content
+		var element = item.element;
+		var declaration = "<?xml version=\"1.0\"?>"; // FIXME: encoding?
+		return declaration + dojox.xml.parser.innerXML(element); //XML string
+	},
+
+	_getPutContent: function(item){
+		//	summary:
+		//		Generate a content to put
+		// 	description:
+		//		This default implementation generates an XML document for one
+		//		(the first only) new or modified element.
+		//		Sub-classes may override this method for the custom put content
+		//		generation.
+		//	item:
+		//		An item to save
+		//	returns:
+		//		A post content
+		var element = item.element;
+		var declaration = "<?xml version=\"1.0\"?>"; // FIXME: encoding?
+		return declaration + dojox.xml.parser.innerXML(element); //XML string
+	},
+
+/* internal API */
+
+	_getAttribute: function(tagName, attribute){
+		if(this._attributeMap){
+			var key = tagName + "." + attribute;
+			var value = this._attributeMap[key];
+			if(value){
+				attribute = value;
+			}else{ // look for global attribute
+				value = this._attributeMap[attribute];
+				if(value){
+					attribute = value;
+				}
+			}
+		}
+		return attribute; //object
+	},
+
+	_getItem: function(element){
+		try{
+			var q = null;
+			//Avoid function call if possible.
+			if(this.keyAttribute === ""){
+				q = this._getXPath(element); 
+			}
+			return new dojox.data.XmlItem(element, this, q); //object
+		}catch (e){
+			console.log(e);
+		}
+		return null;
+	},
+
+	_getItemIndex: function(items, element){
+		for(var i = 0; i < items.length; i++){
+			if(items[i].element === element){
+				return i; //int
+			}
+		}
+		return -1; //int
+	},
+
+	_backupItem: function(item){
+		var element = this._getRootElement(item.element);
+		if(	this._getItemIndex(this._newItems, element) >= 0 ||
+			this._getItemIndex(this._modifiedItems, element) >= 0){
+			return; // new or already modified
+		}
+		if(element != item.element){
+			item = this._getItem(element);
+		}
+		item._backup = element.cloneNode(true);
+		this._modifiedItems.push(item);
+	},
+
+	_restoreItems: function(items){
+
+		dojo.forEach(items,function(item){ 
+			if(item._backup){
+				item.element = item._backup;
+				item._backup = null;
+			}
+		},this); 
+	},
+
+	_forgetItem: function(item){
+		var element = item.element;
+		var index = this._getItemIndex(this._newItems, element);
+		if(index >= 0){
+			this._newItems.splice(index, 1);
+		}
+		index = this._getItemIndex(this._deletedItems, element);
+		if(index >= 0){
+			this._deletedItems.splice(index, 1);
+		}
+		index = this._getItemIndex(this._modifiedItems, element);
+		if(index >= 0){
+			this._modifiedItems.splice(index, 1);
+		}
+	},
+
+	_getDocument: function(element){
+		if(element){
+			return element.ownerDocument; //DOMDocument
+		}else if(!this._document){
+			return dojox.xml.parser.parse(); // DOMDocument
+		}
+		return null; //null
+	},
+
+	_getRootElement: function(element){
+		while(element.parentNode){
+			element = element.parentNode;
+		}
+		return element; //DOMElement
+	},
+
+	_getXPath: function(element){
+		//	summary:
+		//		A function to compute the xpath of a node in a DOM document.
+		//	description:
+		//		A function to compute the xpath of a node in a DOM document.  Used for
+		//		Client side query handling and identity.
+		var xpath = null;
+		if(!this.sendQuery){
+			//xpath should be null for any server queries, as we don't have the entire
+			//XML dom to figure it out.
+			var node = element;
+			xpath = "";
+			while(node && node != element.ownerDocument){
+				var pos = 0;
+				var sibling = node;
+				var name = node.nodeName;
+				while(sibling){
+					sibling = sibling.previousSibling;
+					if(sibling && sibling.nodeName === name){
+						pos++;
+					}
+				}
+				var temp = "/" + name + "[" + pos + "]";
+				if(xpath){
+					xpath = temp + xpath;
+				}else{
+					xpath = temp;
+				}
+				node = node.parentNode;
+			}
+		}
+		return xpath; //string
+	},
+
+	/*************************************
+	 * Dojo.data Identity implementation *
+	 *************************************/
+	getIdentity: function(/* item */ item){
+		//	summary:
+		//		Returns a unique identifier for an item.  
+		//	item:
+		//		The XML Item from the store from which to obtain its identifier.
+		if(!this.isItem(item)){
+			throw new Error("dojox.data.XmlStore: Object supplied to getIdentity is not an item");
+		}else{
+			var id = null;
+			if(this.sendQuery && this.keyAttribute !== ""){
+				id = this.getValue(item, this.keyAttribute).toString();
+			}else if(!this.serverQuery){
+				if(this.keyAttribute !== ""){
+					id = this.getValue(item,this.keyAttribute).toString();
+				}else{
+					//No specified identity, so return the dojo.query/xpath 
+					//for the node as fallback.
+					id = item.q;
+				}
+			}
+			return id; //String.
+		}
+	},
+
+	getIdentityAttributes: function(/* item */ item){
+		//	summary:
+		//		Returns an array of attribute names that are used to generate the identity.
+		//	description:
+		//		For XmlStore, if sendQuery is false and no keyAttribute was set, then this function 
+		//		returns null, as xpath is used for the identity, which is not a public attribute of 
+		//		the item.  If sendQuery is true and keyAttribute is set, then this function
+		//		returns an array of one attribute name: keyAttribute.   This means the server side 
+		//		implementation must apply a keyAttribute to a returned node that always allows 
+		//		it to be looked up again.
+		//	item:
+		//		The item from the store from which to obtain the array of public attributes that 
+		//		compose the identifier, if any.
+		if(!this.isItem(item)){
+			throw new Error("dojox.data.XmlStore: Object supplied to getIdentity is not an item");
+		}else{
+			if(this.keyAttribute !== ""){
+				return [this.keyAttribute]; //array
+			}else{
+				//Otherwise it's either using xpath (not an attribute), or the remote store 
+				//doesn't support identity.
+				return null; //null
+			}
+		}
+	},
+
+
+	fetchItemByIdentity: function(/* object */ keywordArgs){
+		//	summary:
+		//		See dojo.data.api.Identity.fetchItemByIdentity(keywordArgs)
+		var handleDocument = null;
+		var scope = null;
+		var self = this;
+		var url = null;
+		var getArgs = null;
+		var getHandler = null;
+
+		if(!self.sendQuery){
+			handleDocument = function(data){
+				if(data){
+					if(self.keyAttribute !== ""){
+						//We have a key attribute specified.  So ... we can process the items and locate the item
+						//that contains a matching key attribute.  Its identity, as it were.
+						var request = {};
+						request.query={};
+						request.query[self.keyAttribute] = keywordArgs.identity;
+						request.queryOptions = {deep: true};
+						var items = self._getItems(data,request);
+						scope = keywordArgs.scope || dojo.global;
+						if(items.length === 1){
+							if(keywordArgs.onItem){
+								keywordArgs.onItem.call(scope, items[0]);
+							}
+						}else if(items.length === 0){
+							if(keywordArgs.onItem){
+								keywordArgs.onItem.call(scope, null);
+							}
+						}else{
+							if(keywordArgs.onError){
+								keywordArgs.onError.call(scope, new Error("Items array size for identity lookup greater than 1, invalid keyAttribute."));
+							}
+						}
+					}else{
+						//Since dojo.query doesn't really support the functions needed
+						//to do child node selection on IE well and since xpath support 
+						//is flakey across browsers, it's simpler to implement a 
+						//pseudo-xpath parser here.
+						var qArgs = keywordArgs.identity.split("/");
+						var i;
+						var node = data;
+						for(i = 0; i < qArgs.length; i++){
+							if(qArgs[i] && qArgs[i] !== ""){
+								var section = qArgs[i];
+								section = section.substring(0,section.length - 1);
+								var vals = section.split("[");
+								var tag = vals[0];
+								var index = parseInt(vals[1], 10);
+								var pos = 0;
+								if(node){
+									var cNodes = node.childNodes;
+									if(cNodes){
+										var j;
+										var foundNode = null;
+										for(j = 0; j < cNodes.length; j++){
+											var pNode = cNodes[j];
+											if(pNode.nodeName === tag){
+												if(pos < index){
+													pos++;
+												}else{
+													foundNode = pNode;
+													break;
+												}
+											}
+										}
+										if(foundNode){
+											node = foundNode;
+										}else{
+											node = null;
+										}
+									}else{
+										node = null;
+									}
+								}else{
+									break;
+								}
+							}
+						}
+						//Return what we found, if any.
+						var item = null;
+						if(node){
+							item = self._getItem(node);
+							if(item.element.parentNode){
+								item.element.parentNode.removeChild(item.element);
+							}
+						}
+						if(keywordArgs.onItem){
+							scope = keywordArgs.scope || dojo.global;
+							keywordArgs.onItem.call(scope, item);
+						}
+					}
+				}
+			};
+			url = this._getFetchUrl(null);
+			getArgs = {
+				url: url,
+				handleAs: "xml",
+				preventCache: self.urlPreventCache
+			};
+			getHandler = dojo.xhrGet(getArgs);
+			
+			//Add in the callbacks for completion of data load.
+			getHandler.addCallback(handleDocument);
+			if(keywordArgs.onError){
+				getHandler.addErrback(function(error){
+					var s = keywordArgs.scope || dojo.global;
+					keywordArgs.onError.call(s, error);
+				});
+			}
+		}else{
+			//Server side querying, so need to pass the keyAttribute back to the server and let it return
+			//what it will.  It SHOULD be only one item.  
+			if(self.keyAttribute !== ""){
+				var request = {query:{}};
+				request.query[self.keyAttribute] = keywordArgs.identity;
+				url = this._getFetchUrl(request);
+				handleDocument = function(data){
+					var item = null;
+					if(data){
+						var items = self._getItems(data, {});
+						if(items.length === 1){
+							item = items[0];
+						}else{
+							if(keywordArgs.onError){
+								var scope = keywordArgs.scope || dojo.global;
+								keywordArgs.onError.call(scope, new Error("More than one item was returned from the server for the denoted identity"));
+							}
+						}
+					}
+					if(keywordArgs.onItem){
+						scope = keywordArgs.scope || dojo.global;
+						keywordArgs.onItem.call(scope, item);
+					}
+				};
+
+				getArgs = {
+					url: url,
+					handleAs: "xml",
+					preventCache: self.urlPreventCache
+				};
+				getHandler = dojo.xhrGet(getArgs);
+
+				//Add in the callbacks for completion of data load.
+				getHandler.addCallback(handleDocument);
+				if(keywordArgs.onError){
+					getHandler.addErrback(function(error){
+						var s = keywordArgs.scope || dojo.global;
+						keywordArgs.onError.call(s, error);
+					});
+				}
+			}else{
+				if(keywordArgs.onError){
+					var s = keywordArgs.scope || dojo.global;
+					keywordArgs.onError.call(s, new Error("XmlStore is not told that the server to provides identity support.  No keyAttribute specified."));
+				}
+			}
+		}
+	}
 });
-}
-}else{
-if(_a4.keyAttribute!==""){
-var _b4={query:{}};
-_b4.query[_a4.keyAttribute]=_a1.identity;
-url=this._getFetchUrl(_b4);
-_a2=function(_b5){
-var _b6=null;
-if(_b5){
-var _b7=_a4._getItems(_b7,{});
-if(_b7.length===1){
-_b6=_b7[0];
-}else{
-if(_a1.onError){
-var _b8=_a1.scope||dojo.global;
-_a1.onError.call(_b8,new Error("More than one item was returned from the server for the denoted identity"));
-}
-}
-}
-if(_a1.onItem){
-_b8=_a1.scope||dojo.global;
-_a1.onItem.call(_b8,_b6);
-}
-};
-_a5={url:url,handleAs:"xml",preventCache:_a4.urlPreventCache};
-_a6=dojo.xhrGet(_a5);
-_a6.addCallback(_a2);
-if(_a1.onError){
-_a6.addErrback(function(_b9){
-var s=_a1.scope||dojo.global;
-_a1.onError.call(s,_b9);
+
+dojo.declare("dojox.data.XmlItem", null, {
+	constructor: function(element, store, query){
+		//	summary:
+		//		Initialize with an XML element
+		//	element:
+		//		An XML element
+		//	store:
+		//		The containing store, if any.
+		//	query:
+		//		The query to use to look up a specific element.
+		//		Usually an XPath or dojo.query statement.
+		this.element = element;
+		this.store = store;
+		this.q = query;
+	}, 
+	//	summary:
+	//		A data item of 'XmlStore'
+	//	description:
+	//		This class represents an item of 'XmlStore' holding an XML element.
+	//		'element'
+	//	element:
+	//		An XML element
+	toString: function(){
+		//	summary:
+		//		Return a value of the first text child of the element
+		// 	returns:
+		//		a value of the first text child of the element
+		var str = "";
+		if(this.element){
+			for(var i = 0; i < this.element.childNodes.length; i++){
+				var node = this.element.childNodes[i];
+				if(node.nodeType === 3 || node.nodeType === 4){
+					str += node.nodeValue;
+				}
+			}
+		}
+		return str;	//String
+	}
 });
-}
-}else{
-if(_a1.onError){
-var s=_a1.scope||dojo.global;
-_a1.onError.call(s,new Error("XmlStore is not told that the server to provides identity support.  No keyAttribute specified."));
-}
-}
-}
-}});
-dojo.declare("dojox.data.XmlItem",null,{constructor:function(_ba,_bb,_bc){
-this.element=_ba;
-this.store=_bb;
-this.q=_bc;
-},toString:function(){
-var str="";
-if(this.element){
-for(var i=0;i<this.element.childNodes.length;i++){
-var _bd=this.element.childNodes[i];
-if(_bd.nodeType===3||_bd.nodeType===4){
-str+=_bd.nodeValue;
-}
-}
-}
-return str;
-}});
 dojo.extend(dojox.data.XmlStore,dojo.data.util.simpleFetch);
-}
diff --git a/dojox/data/css.js b/dojox/data/css.js
old mode 100644
new mode 100755
index 6e939fc..d7185c7
--- a/dojox/data/css.js
+++ b/dojox/data/css.js
@@ -1,91 +1,95 @@
-/*
-	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
-*/
+dojo.provide('dojox.data.css');
+dojo.provide('dojox.data.css.rules');
 
-
-if(!dojo._hasResource["dojox.data.css"]){
-dojo._hasResource["dojox.data.css"]=true;
-dojo.provide("dojox.data.css");
-dojo.provide("dojox.data.css.rules");
-dojox.data.css.rules.forEach=function(fn,_1,_2){
-if(_2){
-var _3=function(_4){
-dojo.forEach(_4[_4.cssRules?"cssRules":"rules"],function(_5){
-if(!_5.type||_5.type!==3){
-var _6="";
-if(_4&&_4.href){
-_6=_4.href;
-}
-fn.call(_1?_1:this,_5,_4,_6);
-}
-});
-};
-dojo.forEach(_2,_3);
-}
-};
-dojox.data.css.findStyleSheets=function(_7){
-var _8=[];
-var _9=function(_a){
-var s=dojox.data.css.findStyleSheet(_a);
-if(s){
-dojo.forEach(s,function(_b){
-if(dojo.indexOf(_8,_b)===-1){
-_8.push(_b);
-}
-});
-}
-};
-dojo.forEach(_7,_9);
-return _8;
-};
-dojox.data.css.findStyleSheet=function(_c){
-var _d=[];
-if(_c.charAt(0)==="."){
-_c=_c.substring(1);
-}
-var _e=function(_f){
-if(_f.href&&_f.href.match(_c)){
-_d.push(_f);
-return true;
-}
-if(_f.imports){
-return dojo.some(_f.imports,function(_10){
-return _e(_10);
-});
-}
-return dojo.some(_f[_f.cssRules?"cssRules":"rules"],function(_11){
-if(_11.type&&_11.type===3&&_e(_11.styleSheet)){
-return true;
-}
-return false;
-});
+dojox.data.css.rules.forEach = function(fn,ctx,context){
+	if(context){
+		var _processSS = function(styleSheet){
+			//iterate across rules in the stylesheet
+			dojo.forEach(styleSheet[styleSheet.cssRules?"cssRules":"rules"], function(rule){
+				if(!rule.type || rule.type !== 3){// apply fn to current rule with approp ctx. rule is arg (all browsers)
+					var href = "";
+					if(styleSheet && styleSheet.href){
+						href = styleSheet.href;
+					}
+					fn.call(ctx?ctx:this,rule, styleSheet, href);
+				}
+			});
+			//process any child stylesheets
+		};
+		dojo.forEach(context,_processSS);
+	}
 };
-dojo.some(document.styleSheets,_e);
-return _d;
+dojox.data.css.findStyleSheets = function(sheets){
+	// Takes an array of stylesheet paths and finds the currently loaded StyleSheet objects matching
+	// those names
+	var sheetObjects = [];
+	var _processSS = function(styleSheet){
+		var s = dojox.data.css.findStyleSheet(styleSheet);
+		if(s){
+			dojo.forEach(s, function(sheet){
+				if(dojo.indexOf(sheetObjects, sheet) === -1){
+					sheetObjects.push(sheet);
+				}
+			});
+		}
+	};
+	dojo.forEach(sheets, _processSS);
+	return sheetObjects;
 };
-dojox.data.css.determineContext=function(_12){
-var ret=[];
-if(_12&&_12.length>0){
-_12=dojox.data.css.findStyleSheets(_12);
-}else{
-_12=document.styleSheets;
-}
-var _13=function(_14){
-ret.push(_14);
-if(_14.imports){
-dojo.forEach(_14.imports,function(_15){
-_13(_15);
-});
-}
-dojo.forEach(_14[_14.cssRules?"cssRules":"rules"],function(_16){
-if(_16.type&&_16.type===3){
-_13(_16.styleSheet);
-}
-});
+dojox.data.css.findStyleSheet = function(sheet){
+	// Takes a stylesheet path and finds the currently loaded StyleSheet objects matching
+	// those names (and it's parent(s), if it is imported from another)
+	var sheetObjects = [];
+	if(sheet.charAt(0) === '.'){
+		sheet = sheet.substring(1);
+	}
+	var _processSS = function(styleSheet){
+		if(styleSheet.href && styleSheet.href.match(sheet)){
+			sheetObjects.push(styleSheet);
+			return true;
+		}
+		if(styleSheet.imports){
+			return dojo.some(styleSheet.imports, function(importedSS){ //IE stylesheet has imports[] containing @import'ed rules 
+				//console.debug("Processing IE @import rule",importedSS);
+				return _processSS(importedSS);
+			});
+		}
+		//iterate across rules in the stylesheet
+		return dojo.some(styleSheet[styleSheet.cssRules?"cssRules":"rules"], function(rule){
+			if(rule.type && rule.type === 3 && _processSS(rule.styleSheet)){// CSSImportRule (firefox)
+				//sheetObjects.push(styleSheet);
+				return true;
+			}
+			return false;
+		});
+	};
+	dojo.some(document.styleSheets, _processSS);
+	return sheetObjects;
 };
-dojo.forEach(_12,_13);
-return ret;
+dojox.data.css.determineContext = function(initialStylesheets){
+	// Takes an array of stylesheet paths and returns an array of all stylesheets that fall in the 
+	// given context.  If no paths are given, all stylesheets are returned.
+	var ret = [];
+	if(initialStylesheets && initialStylesheets.length > 0){
+		initialStylesheets = dojox.data.css.findStyleSheets(initialStylesheets);
+	}else{
+		initialStylesheets = document.styleSheets;
+	}
+	var _processSS = function(styleSheet){
+		ret.push(styleSheet);
+		if(styleSheet.imports){
+			dojo.forEach(styleSheet.imports, function(importedSS){ //IE stylesheet has imports[] containing @import'ed rules 
+				//console.debug("Processing IE @import rule",importedSS);
+				_processSS(importedSS);
+			});
+		}
+		//iterate across rules in the stylesheet
+		dojo.forEach(styleSheet[styleSheet.cssRules?"cssRules":"rules"], function(rule){
+			if(rule.type && rule.type === 3){// CSSImportRule (firefox)
+				_processSS(rule.styleSheet);
+			}
+		});
+	};
+	dojo.forEach(initialStylesheets,_processSS);
+	return ret;
 };
-}
diff --git a/dojox/data/demos/GoogleFeedTemplate.html b/dojox/data/demos/GoogleFeedTemplate.html
new file mode 100644
index 0000000..2d18fca
--- /dev/null
+++ b/dojox/data/demos/GoogleFeedTemplate.html
@@ -0,0 +1,26 @@
+{% load dojox.dtl.contrib.data %}
+{% bind_data items to store as google %}
+<ul>
+{% for item in google %}
+<li class="search-result">
+	<div>
+	<a href="{{item.link}}">{{item.title}}</a>
+	<div style="display:none" class="content">
+		<h2>{{item.title}}</h2>
+		{{item.content}}
+	</div>
+	</div>
+	<div class="summary">
+		{{item.summary}}
+	</div>
+	<div class="tags">
+		<!--{% if item.categories %}-->
+			Tags: 
+			<!--{% for cat in item.categories %}-->
+				{{cat}}
+			<!--{% endfor %}-->
+		<!--{% endif %}-->
+	</div>
+</li>
+{% endfor %}
+</ul>
\ No newline at end of file
diff --git a/dojox/data/demos/GoogleTemplate.html b/dojox/data/demos/GoogleTemplate.html
new file mode 100644
index 0000000..a87d107
--- /dev/null
+++ b/dojox/data/demos/GoogleTemplate.html
@@ -0,0 +1,7 @@
+{% load dojox.dtl.contrib.data %}
+{% bind_data items to store as google %}
+{% for item in google %}
+<span class="search-result">
+	<a href="{{item.unescapedUrl}}">{{item.titleNoFormatting}}</a>				
+</span>
+{% endfor %}
diff --git a/dojox/data/demos/GoogleTemplateBlog.html b/dojox/data/demos/GoogleTemplateBlog.html
new file mode 100644
index 0000000..4d67548
--- /dev/null
+++ b/dojox/data/demos/GoogleTemplateBlog.html
@@ -0,0 +1,7 @@
+{% load dojox.dtl.contrib.data %}
+{% bind_data items to store as google %}
+{% for item in google %}
+<span class="search-result">
+	<a href="{{item.postUrl}}">{{item.titleNoFormatting}}</a>				
+</span>
+{% endfor %}
diff --git a/dojox/data/demos/GoogleTemplateImage.html b/dojox/data/demos/GoogleTemplateImage.html
new file mode 100644
index 0000000..37088d8
--- /dev/null
+++ b/dojox/data/demos/GoogleTemplateImage.html
@@ -0,0 +1,7 @@
+{% load dojox.dtl.contrib.data %}
+{% bind_data items to store as google %}
+{% for item in google %}
+<span class="search-result">
+	<a href="{{item.unescapedUrl}}"><img src="{{item.tbUrl}}" alt="{{item.contentNoFormatting}}"></a>				
+</span>
+{% endfor %}
diff --git a/dojox/data/demos/GoogleTemplateLocal.html b/dojox/data/demos/GoogleTemplateLocal.html
new file mode 100644
index 0000000..da37f90
--- /dev/null
+++ b/dojox/data/demos/GoogleTemplateLocal.html
@@ -0,0 +1,7 @@
+{% load dojox.dtl.contrib.data %}
+{% bind_data items to store as google %}
+{% for item in google %}
+<span class="search-result">
+	<a href="{{item.url}}"><img src="{{item.staticMapUrl}}"></a>				
+</span>
+{% endfor %}
diff --git a/dojox/data/demos/GoogleTemplateVideo.html b/dojox/data/demos/GoogleTemplateVideo.html
new file mode 100644
index 0000000..0600db0
--- /dev/null
+++ b/dojox/data/demos/GoogleTemplateVideo.html
@@ -0,0 +1,7 @@
+{% load dojox.dtl.contrib.data %}
+{% bind_data items to store as google %}
+{% for item in google %}
+<span class="search-result">
+	<a href="{{item.url}}"><img src="{{item.tbUrl}}" width="100" height="75"></a>				
+</span>
+{% endfor %}
diff --git a/dojox/data/demos/demo_CssStores_combo_tree_grid.html b/dojox/data/demos/demo_CssStores_combo_tree_grid.html
new file mode 100755
index 0000000..165e5ed
--- /dev/null
+++ b/dojox/data/demos/demo_CssStores_combo_tree_grid.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!--
+	Demo application showing The CssClassStore.
+-->
+<html>
+<head>
+	<title>Demo:  dojox.data.CssClassStore</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+  		@import "../../grid/resources/tundraGrid.css";
+	</style>
+
+	<!--
+		The following script tag instantiates the dojo library and sets some basic properties.  In this case, the application
+		is told that debug mode is off, and to parse all dojoType widgets when it has fully loaded.
+	-->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: false, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../../../dijit/dijit.js"></script>
+	<script>
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dojox.data.CssRuleStore");
+		dojo.require("dojox.data.CssClassStore");
+		dojo.require("dojox.grid.DataGrid");
+
+		var layoutCss = [
+			[
+				{ field: "selector", name: "Selector", width: 20 },
+				{ field: "parentStyleSheetHref", name: "StyleSheet", width: 20 },
+				{ field: "cssText", name: "CSS", width: 'auto' }
+			]
+		];
+
+		function init() {
+			var combo = dijit.byId("classCombo");
+			var grid = dijit.byId("cssGrid");
+			
+			function requery() {
+				var val = combo.getValue();
+				val = "." + val;
+				var query = {
+					selector: "*" + val + "*"
+				}
+				grid.filter(query,true);
+			}
+			dojo.connect(combo, "onChange", requery);
+		}
+		dojo.addOnLoad(init);
+
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>
+		Demo:  Demo of using the Css Stores to browse the loaded CSS classes and associated rules.
+	</h1>
+	<p>This demo demonstrates hooking up the Css*Stores to the various digit widgets to browse the Css loaded for the page.</p>
+	<hr>
+
+	<div dojoType="dojox.data.CssRuleStore" jsId="ruleStore"></div>
+	<div dojoType="dojox.data.CssClassStore" jsId="classStore"></div>
+	
+
+	<div dojoType="dijit.tree.ForestStoreModel" 
+		 jsId="classModel" 
+		 store="classStore" 
+		 query="{}"
+		 rootId="Loaded Classes" 
+		 rootLabel="Loaded Classes" 
+		 childrenAttrs="children">
+	</div>
+
+	<h2>dojox.data.CssClassStore connected to ComboBox and querying on classSans:</h2>
+	<div id="classCombo" dojoType="dijit.form.ComboBox"  store="classStore" searchAttr="classSans"></div> 
+
+	<h2>dojox.data.CssRuleStore:</h2>
+	<i>Displays the list of CSS rules filtered by the class selected in the ComboBox.</i>
+	<div id="cssGrid"
+		 jsId="cssGrid" 
+		 dojoType="dojox.grid.DataGrid" 
+		 query="{}" 
+		 rowsPerPage="20"
+		 store="ruleStore" 
+		 structure="layoutCss"
+		 style="width: 100%; height: 400px;">
+	</div>
+
+	<h2>dojox.data.CssClassStore connected to Tree:</h2>
+	<span id="tree" dojoType="dijit.Tree" model="classModel"> </span>
+	<hr>
+</body>
+</html>
diff --git a/dojox/data/demos/demo_DataDemoTable.html b/dojox/data/demos/demo_DataDemoTable.html
new file mode 100644
index 0000000..5b40e4b
--- /dev/null
+++ b/dojox/data/demos/demo_DataDemoTable.html
@@ -0,0 +1,143 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo Visual Loader Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+
+		.oddRow { background-color: #f2f5f9; }
+		.population { text-align: right; }
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug: false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojo.parser");
+		dojo.require("dijit.Declaration");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dojox.data.FlickrStore");
+	</script>
+</head>
+<body class="tundra">
+	<span dojoType="dojo.data.ItemFileReadStore" 
+		jsId="continentStore"
+		url="../../../dijit/tests/_data/countries.json"></span>
+	<span dojoType="dojox.data.FlickrStore" jsId="flickrStore"></span>
+
+
+	<h1 class="testTitle">Dojox Data Demo Table</h1>
+
+	<table dojoType="dijit.Declaration" 
+		widgetClass="demo.Table" class="dojoTabular" 
+		defaults="{ store: null, query: { query: { name: '*' } }, columns: [ { name: 'Name', attribute: 'name' } ] }">
+		<thead dojoAttachPoint="head">
+			<tr dojoAttachPoint="headRow"></tr>
+		</thead>
+		<tbody dojoAttachPoint="body">
+			<tr dojoAttachPoint="row">
+			</tr>
+		</tbody>
+
+		<script type="dojo/method">
+			dojo.forEach(this.columns, function(item, idx){
+				var icn = item.className||"";
+				// add a header for each column
+				var tth = document.createElement("th");
+				tth.innerHTML = item.name;
+				tth.className = icn;
+				dojo.connect(tth, "onclick", dojo.hitch(this, "onSort", idx));
+				this.headRow.appendChild(tth);
+
+				// and fill in the column cell in the template row
+				this.row.appendChild(document.createElement("td"));
+				this.row.lastChild.className = icn;
+			}, this);
+			this.runQuery();
+		</script>
+		<script type="dojo/method" event="onSort" args="index">
+			var ca = this.columns[index].attribute;
+			var qs = this.query.sort;
+			// clobber an existing sort arrow
+			dojo.query("> th", this.headRow).style("background", "").style("paddingRight", "");
+			if(qs && qs[0].attribute == ca){
+				qs[0].descending = !qs[0].descending;
+			}else{
+				this.query.sort = [{
+					attribute: ca,
+					descending: false
+				}];
+			}
+			var th = dojo.query("> th", this.headRow)[index];
+			th.style.paddingRight = "16px"; // space for the sort arrow
+			th.style.background = "url(\""+dojo.moduleUrl("dijit", "themes/tundra/images/arrow"+(this.query.sort[0].descending ? "Up" : "Down")+((dojo.isIE == 6) ? ".gif" : ".png")) + "\") no-repeat 98% 4px";
+			this.runQuery();
+		</script>
+		<script type="dojo/method" event="runQuery">
+			this.query.onBegin = dojo.hitch(this, function(){ dojo.query("tr", this.body).orphan(); });
+			this.query.onItem = dojo.hitch(this, "onItem");
+			this.query.onComplete = dojo.hitch(this, function(){
+				dojo.query("tr:nth-child(odd)", this.body).addClass("oddRow");
+				dojo.query("tr:nth-child(even)", this.body).removeClass("oddRow");
+			});
+			this.store.fetch(this.query);
+		</script>
+		<script type="dojo/method" event="onItem" args="item">
+			var tr = this.row.cloneNode(true);
+			dojo.query("td", tr).forEach(function(n, i, a){
+				var tc = this.columns[i];
+				var tv = this.store.getValue(item, tc.attribute)||"";
+				if(tc.format){ tv = tc.format(tv, item, this.store); }
+				n.innerHTML = tv;
+			}, this);
+			this.body.appendChild(tr);
+		</script>
+	</table>
+
+	<span dojoType="demo.Table" store="continentStore"
+		query="{ query: { type: 'country' }, sort: [ { attribute: 'name', descending: true } ]  }" 
+		id="foo">
+		<script type="dojo/method" event="preamble">
+			this.columns = [
+				{ name: "Name", attribute: "name" },
+				{	name: 		"Population",
+					attribute:	"population",
+					className:	"population"
+				}
+			];
+		</script>
+	</span>
+	<span dojoType="demo.Table" store="continentStore"
+		query="{ query: { name: 'A*' } }"></span>
+	<span dojoType="demo.Table" store="flickrStore"
+		query="{ query: { groupid: '27475260 at N00' } }">
+		<script type="dojo/method" event="preamble">
+			this.columns = [
+				{	name: "", attribute: "imageUrlSmall", 
+					format: function(value, item, store){
+						return (value.length) ? "<img src='"+value+"'>" : "";
+					}
+				},
+				{ name: "Title", attribute: "title" }
+			];
+		</script>
+	</span>
+	<span dojoType="demo.Table" store="flickrStore"
+		query="{ query: { tags: 'dojotoolkit' } }">
+		<script type="dojo/method" event="preamble">
+			this.columns = [
+				{	name: "", attribute: "imageUrlSmall", 
+					format: function(value, item, store){
+						return (value.length) ? "<img src='"+value+"'>" : "";
+					}
+				},
+				{ name: "Title", attribute: "title" }
+			];
+		</script>
+	</span>
+</body>
+</html>
diff --git a/dojox/data/demos/demo_FileStore_dojotree.html b/dojox/data/demos/demo_FileStore_dojotree.html
new file mode 100755
index 0000000..1d0b457
--- /dev/null
+++ b/dojox/data/demos/demo_FileStore_dojotree.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!--
+	Demo application showing LazyLoading File store.
+-->
+<html>
+<head>
+	<title>Demo:  dojox.data.FileStore</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		.fileView {
+			margin: 5px;
+			width: 100%;
+
+		}
+		.fileView .fileViewTitle{
+			color: white;
+			background-color: black;
+			font-size: larger;
+			font-weight: bold;
+
+		}
+
+		.fileView .fileViewTable {
+			border-width: 2px;
+			border-style: solid;
+			width: 100%;
+		}
+
+		.fileView .fileViewTable tr td {
+			border-width: 1px;
+			border-style: solid;
+			border-color: lightgray;
+			width: 50%;
+			vertical-align: top;
+		}
+
+		.fileView .fileName {
+			background-color: lightgray;
+		}
+
+	</style>
+
+	<!--
+		The following script tag instantiates the dojo library and sets some basic properties.  In this case, the application
+		is told that debug mode is off, and to parse all dojoType widgets when it has fully loaded.
+	-->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: false, parseOnLoad: true, useCommentedJson: true"></script>
+	<script type="text/javascript" src="../../../dijit/dijit.js"></script>
+	<script>
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+		dojo.require("dojox.data.FileStore");
+		dojo.require("dojox.data.demos.widgets.FileView");
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>
+		Demo:  Lazy Loading File Browsing Store
+	</h1>
+	<p>The tree below uses the dojox.data.FileStore and a PHP implementation for the serverside to browse the dojo tree hierarchy in a lazy-load fashion.</p>
+	<p><i><b>This demo must be run from a web-server with PHP support enabled.  Without PHP support, this demo cannot function.</b></i></p>
+	<hr>
+	<i>Clicking on a file in the tree will display the details about that file.</i>
+	<div dojoType="dojox.data.FileStore" url="stores/filestore_dojotree.php" jsId="fileStore" pathAsQueryParam="true"></div>
+	<div dojoType="dijit.tree.ForestStoreModel" jsId="fileModel" 
+		store="fileStore" query="{}"
+		rootId="DojoFiles" rootLabel="Dojo Files" childrenAttrs="children"></div>
+
+	<table style="width: 100%;">
+		<tbody>
+			<tr style="width: 100%;">
+				<td style="width: 50%;  vertical-align: top;">
+					<span id="tree" dojoType="dijit.Tree" model="fileModel" >
+						<script type="dojo/method" event="onClick" args="item">
+							if (fileStore.isItem(item)){
+								var attachPt = dojo.byId("fileInfo");
+								if (attachPt) {
+									while(attachPt.firstChild) {
+										attachPt.removeChild(attachPt.firstChild);
+									}
+									var newArgs = {};
+									newArgs.name = fileStore.getValue(item, "name");
+									newArgs.path = fileStore.getValue(item, "path");
+									newArgs.size = fileStore.getValue(item, "size");
+									newArgs.directory = fileStore.getValue(item, "directory");
+									newArgs.parentDir = fileStore.getValue(item, "parentDir");
+									var children = fileStore.getValues(item, "children");
+									if (children && children.length > 0) {
+										newArgs.children = [];
+										var i;
+										for (i = 0; i < children.length; i++) {
+											//Note here that even though the store is lazy-loading, the unloaded items for children still
+											//have the 'name' attribute, since it is used as part of the info to load the full item.  Generally
+											//you should not access properties of an item that has not been fully inflated yet.  It just works
+											//well in this case for this store.
+											newArgs.children.push(fileStore.getValue(children[i], "name"));
+										}
+									}                                
+									var fInfo = new dojox.data.demos.widgets.FileView(newArgs);
+									attachPt.appendChild(fInfo.domNode);
+									fInfo.startup();
+								}
+							}
+						</script>
+					</span>
+				</td>
+				<td id="fileInfo" STYLE="width: 50%; vertical-align: top;">
+				</td>
+			</tr>
+
+		</tbody>    
+	</table>
+	<hr>
+</body>
+</html>
diff --git a/dojox/data/demos/demo_FileStore_dojoxdata_combo_grid.html b/dojox/data/demos/demo_FileStore_dojoxdata_combo_grid.html
new file mode 100755
index 0000000..9b18c8d
--- /dev/null
+++ b/dojox/data/demos/demo_FileStore_dojoxdata_combo_grid.html
@@ -0,0 +1,157 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!--
+	Demo application showing LazyLoading File store.
+-->
+<html>
+<head>
+	<title>Demo:  dojox.data.FileStore</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dojox/grid/resources/tundraGrid.css";
+
+		.fileView {
+			margin: 5px;
+			width: 100%;
+
+		}
+		.fileView .fileViewTitle{
+			color: white;
+			background-color: black;
+			font-size: larger;
+			font-weight: bold;
+
+		}
+
+		.fileView .fileViewTable {
+			border-width: 2px;
+			border-style: solid;
+			width: 100%;
+		}
+
+		.fileView .fileViewTable tr td {
+			border-width: 1px;
+			border-style: solid;
+			border-color: lightgray;
+			width: 50%;
+			vertical-align: top;
+		}
+
+		.fileView .fileName {
+			background-color: lightgray;
+		}
+
+		.tundra .dojoxGrid-cell {
+				text-indent: 3px;
+		}
+	</style>
+
+	<!--
+		The following script tag instantiates the dojo library and sets some basic properties.  In this case, the application
+		is told that debug mode is off, and to parse all dojoType widgets when it has fully loaded.
+	-->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: false, parseOnLoad: true, useCommentedJson: true"></script>
+	<script type="text/javascript" src="../../../dijit/dijit.js"></script>
+	<script>
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dojox.data.FileStore");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojox.data.demos.widgets.FileView");
+
+		var layoutFiles = [
+			 [
+				{ field: "name", name: "Filename", width: 20 },
+				{ field: "size", name: "File Size (bytes)", width: 10 },
+				{ field: "directory", name: "Is Directory", width: 10 },
+				{ field: "path", name: "Path", width: 'auto' }
+			  ]
+		];
+
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>
+		Demo:  Lazy Loading File Browsing Store connected to multiple widgets
+	</h1>
+	<p>All the widgets used in this demo connect to the same filestore instance.  It is talking to a filestore rooted in the dojox/data/ sub-directory to make it fast handling when querying across all files.</p>
+	<p><i><b>This demo must be run from a web-server with PHP support enabled.  Without PHP support, this demo cannot function.</b></i></p>
+	<hr>
+
+	<div dojoType="dojox.data.FileStore" url="stores/filestore_dojoxdata.php" jsId="fileStore" pathAsQueryParam="true"></div>
+	<div dojoType="dijit.tree.ForestStoreModel" jsId="fileModel" 
+		store="fileStore" query="{}"
+		rootId="./dojox/data" rootLabel="./dojox/data" childrenAttrs="children"></div>
+
+
+	<h2>dojox.data.FileStore connected to ComboBox and querying on path:</h2>
+	<div dojoType="dijit.form.ComboBox"  store="fileStore" searchAttr="path" value="./demos"></div> 
+
+
+	<h2>dojox.data.FileStore connected to Grid and displaying all files:</h2>
+	<div style="width: 100%; height: 300px;">
+	    <div id="grid" 
+			 dojoType="dojox.grid.DataGrid" 
+			 store="fileStore" 
+			 structure="layoutFiles" 
+			 queryOptions="{deep:true}"
+			 query="{}" 
+			 sortFields="[{'attribute':'path', 'descending': false}]"
+			 rowsPerPage="40">
+
+		</div>
+	</div>
+
+
+	<h2>dojox.data.FileStore connected to Tree:</h2>
+	<i>Clicking on a file in the tree will display the details about that file.</i>
+	<table style="width: 100%;">
+		<tbody>
+			<tr style="width: 100%;">
+				<td style="width: 50%;  vertical-align: top;">
+					<span id="tree" dojoType="dijit.Tree" model="fileModel">
+						<script type="dojo/method" event="onClick" args="item">
+							if (fileStore.isItem(item)){
+								var attachPt = dojo.byId("fileInfo");
+								if (attachPt) {
+									while(attachPt.firstChild) {
+										attachPt.removeChild(attachPt.firstChild);
+									}
+									var newArgs = {};
+									newArgs.name = fileStore.getValue(item, "name");
+									newArgs.path = fileStore.getValue(item, "path");
+									newArgs.size = fileStore.getValue(item, "size");
+									newArgs.directory = fileStore.getValue(item, "directory");
+									newArgs.parentDir = fileStore.getValue(item, "parentDir");
+									var children = fileStore.getValues(item, "children");
+									if (children && children.length > 0) {
+										newArgs.children = [];
+										var i;
+										for (i = 0; i < children.length; i++) {
+											//Note here that even though the store is lazy-loading, the unloaded items for children still
+											//have the 'name' attribute, since it is used as part of the info to load the full item.  Generally
+											//you should not access properties of an item that has not been fully inflated yet.  It just works
+											//well in this case for this store.
+											newArgs.children.push(fileStore.getValue(children[i], "name"));
+										}
+									}                                
+									var fInfo = new dojox.data.demos.widgets.FileView(newArgs);
+									attachPt.appendChild(fInfo.domNode);
+									fInfo.startup();
+								}
+							}
+						</script>
+					</span>
+				</td>
+				<td id="fileInfo" STYLE="width: 50%; vertical-align: top;">
+				</td>
+			</tr>
+
+		</tbody>    
+	</table>
+	<hr>
+</body>
+</html>
diff --git a/dojox/data/demos/demo_FlickrRestStore.html b/dojox/data/demos/demo_FlickrRestStore.html
new file mode 100644
index 0000000..5774c76
--- /dev/null
+++ b/dojox/data/demos/demo_FlickrRestStore.html
@@ -0,0 +1,236 @@
+<!--
+  This file is a demo of the FlickrStore, a simple wrapper to the public feed service
+  of Flickr.  This just does very basic queries against Flickr and loads the results
+  into a list viewing widget.
+-->
+<html>
+<head>
+	<title>Demo of FlickrRestStore</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.NumberSpinner");
+		dojo.require("dojox.data.FlickrStore");
+		dojo.require("dojox.data.FlickrRestStore");
+		dojo.require("dojox.data.demos.widgets.FlickrViewList");
+
+		function init(){
+			//Function to invoke the search of the FlickrStore
+			function invokeSearch(){
+				var request = { 
+					query: {
+					  apikey: "8c6803164dbc395fb7131c9d54843627"  
+					}
+				};
+
+				if(idWidget){
+					var userid = idWidget.getValue();
+					if(userid && userid !== ""){
+						request.query.userid = userid;
+					}
+				}
+				if(tagsWidget){
+					request.query.tags = (tagsWidget.getValue()||"").split(" ").join(",");
+				}
+				if(tagmodeWidget){
+					request.query.tagmode = tagmodeWidget.getValue()||"";
+				}
+				
+				if(setIdWidget){
+					var setid = setIdWidget.getValue();
+					if(setid != ""){
+					  request.query.setid = setid;
+					}
+				}
+				
+				if(fullTextWidget){
+					var fullText = fullTextWidget.getValue();
+					if(fullText != ""){
+					  request.query.text = fullText;
+					}
+				}
+				
+				if(sortTypeWidget && sortDirWidget){
+					var sortType = sortTypeWidget.getValue();
+					var sortDirection = sortDirWidget.getValue();
+					
+					if(sortType != "" && sortDirection != ""){
+						request.query.sort = [
+							{
+								attribute: sortType,
+								descending: (sortDirection.toLowerCase() == "descending")
+							}					  
+						];
+					}
+				}
+				
+				if(countWidget){
+					request.count = countWidget.getValue();
+				}
+				if(pageWidget){
+					request.start = request.count * (pageWidget.getValue() -1);
+				}
+
+				if(statusWidget){
+					statusWidget.setValue("PROCESSING REQUEST");
+				}
+
+				// flickrStore.fetch(request);
+				flickrViewsWidget.fetch(request);
+			}
+
+			//Lastly, link up the search event.
+			var button = dijit.byId("searchButton");
+			dojo.connect(button, "onClick", invokeSearch);
+		}
+		dojo.addOnLoad(init);
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>
+		DEMO:  FlickrRestStore Search
+	</h1>
+	<hr>
+	<h3>
+		Description:
+	</h3>
+	<p>
+		This simple demo shows how services, such as Flickr, can be wrapped by the datastore API.
+		In this demo, you can search public Flickr images through a FlickrRestStore by specifying
+		a series of tags (separated by spaces) to search on.  The results will be displayed below the search box.
+	</p>
+	<p>
+		For fun, search on the 3dny tag!
+	</p>
+
+	<blockquote>
+
+	<!--
+		The store instance used by this demo.
+	-->
+	<table>
+		<tbody>
+			<tr>
+				<td>
+					<b>Status:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="status" jsId="statusWidget" disabled="true"></div>
+				</td>
+				<td></td>
+				<td></td>
+			</tr>
+			<tr>
+				<td>
+					<b>User ID:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="userid" jsId="idWidget" value="44153025 at N00"></div>
+				</td>
+				<td>
+					<b>Set ID</b>
+				</td>
+				<td>
+					  <div dojoType="dijit.form.TextBox" size="50" id="setid" jsId="setIdWidget"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>Tags:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="tags" jsId="tagsWidget" value="rollingstones,kinsale"></div>
+				</td>
+				<td>
+					<b>Full Text</b>
+				</td>
+				<td>
+					  <div dojoType="dijit.form.TextBox" size="50" id="fulltext" jsId="fullTextWidget"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>Tagmode:</b>
+				</td>
+				<td>
+					<select id="tagmode"
+							jsId="tagmodeWidget"
+							dojoType="dijit.form.ComboBox"
+							autocomplete="false"
+							value="any"
+					>
+						<option>any</option>
+						<option>all</option>
+					</select>
+				</td>
+				<td>
+					<b>Sort</b>
+				</td>
+				<td>
+					  <select dojoType="dijit.form.ComboBox" size="15" id="sorttype" jsId="sortTypeWidget">
+						<option>date-posted</option>
+						<option>date-taken</option>
+						<option>interestingness</option>
+					  </select>
+					   <select dojoType="dijit.form.ComboBox" size="15" id="sortdirection" jsId="sortDirWidget">
+						<option>ascending</option>
+						<option>descending</option>
+					  </select>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>Number of Pictures:</b>
+				</td>
+				<td>
+					<div   
+						id="count"
+						jsId="countWidget"
+						dojoType="dijit.form.NumberSpinner"
+						value="20"
+						constraints="{min:1,max:20,places:0}" 
+					></div>
+				</td>
+				<td>
+					<b>Page:</b>
+				</td>
+				<td>
+					<div   
+						id="page"
+						jsId="pageWidget"
+						dojoType="dijit.form.NumberSpinner"
+						value="1"
+						constraints="{min:1,max:5,places:0}" 
+					></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+				</td>
+				<td>
+					<div dojoType="dijit.form.Button" label="Search" id="searchButton" jsId="searchButtonWidget"></div>
+				</td>
+			</tr>
+		</tbody>
+	</table>
+	<hr/>
+	</blockquote>
+	<div dojoType="dojox.data.FlickrRestStore" jsId="flickrStore" label="title"></div>
+	<div dojoType="dojox.data.demos.widgets.FlickrViewList" 
+		store="flickrStore"
+		id="flickrViews" 
+		jsId="flickrViewsWidget"></div>
+
+</body>
+</html>
diff --git a/dojox/data/demos/demo_FlickrStore.html b/dojox/data/demos/demo_FlickrStore.html
new file mode 100644
index 0000000..0adf8d2
--- /dev/null
+++ b/dojox/data/demos/demo_FlickrStore.html
@@ -0,0 +1,161 @@
+<html>
+<head>
+	<!--
+		This file is a demo of the FlickrStore, a simple wrapper to the public
+		feed service of Flickr. This just does very basic queries against
+		Flickr and loads the results into a list viewing widget.
+	-->
+	<title>Demo of FlickrStore</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.NumberSpinner");
+		dojo.require("dojox.data.FlickrStore");
+		dojo.require("dojox.data.demos.widgets.FlickrViewList");
+
+		function init(){
+			//Function to invoke the search of the FlickrStore
+			var invokeSearch = function(){
+				var request = { query: {} };
+				
+				if(idWidget){
+					var id = idWidget.getValue() || "";
+					if(id && id.length){
+						request.query.userid = id;
+					}
+				}
+                
+				if(tagsWidget){
+					request.query.tags = (tagsWidget.getValue()||"").split(" ").join(",");
+				}
+
+				
+				if(tagmodeWidget){
+					request.query.tagmode = tagmodeWidget.getValue()||"";
+				}
+
+				if(countWidget){
+					request.count = countWidget.getValue();
+				}
+				flickrViewsWidget.fetch(request);
+			}
+			
+			dojo.connect(flickrViewsWidget, "fetch", function() {
+				statusWidget.setValue("PROCESSING REQUEST");
+			});
+			
+			dojo.connect(flickrViewsWidget, "onComplete", function() {
+                statusWidget.setValue("PROCESSING COMPLETE.");
+			});
+
+			dojo.connect(flickrViewsWidget, "onError", function() {
+                statusWidget.setValue("ERROR!");
+			});
+
+			//Lastly, link up the search event.
+			var button = dijit.byId("searchButton");
+			dojo.connect(button, "onClick", invokeSearch);
+		}
+		dojo.addOnLoad(init);
+		dojo.addOnLoad(function(){ dijit.byId("searchButton").onClick(); });
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>
+		DEMO:  FlickrStore Search
+	</h1>
+	<p>
+		This simple demo shows how services, such as Flickr, can be wrapped by
+		the datastore API. In this demo, you can search public Flickr images
+		through a simple FlickrStore by specifying a series of tags (separated
+		by spaces) to search on.  The results will be displayed below the
+		search box.
+	</p>
+	<table>
+		<tbody>
+			<tr>
+				<td>
+					<b>Status:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="status" jsId="statusWidget" disabled="true"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>ID:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="userid" jsId="idWidget"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>Tags:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="tags" jsId="tagsWidget" value="nature"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>Tagmode:</b>
+				</td>
+				<td>
+					<select id="tagmode"
+							jsId="tagmodeWidget"
+							dojoType="dijit.form.ComboBox"
+							autocomplete="false"
+							value="any"
+					>
+						<option>any</option>
+						<option>all</option>
+					</select>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>Number of Pictures:</b>
+				</td>
+				<td>
+					<div   
+						id="count"
+						jsId="countWidget"
+						dojoType="dijit.form.NumberSpinner"
+						value="20"
+						constraints="{min:1,max:20,places:0}" 
+					></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+				</td>
+				<td>
+					<div dojoType="dijit.form.Button" label="Search" 
+						id="searchButton" jsId="searchButtonWidget"></div>
+				</td>
+			</tr>
+		</tbody>
+	</table>
+	<!--
+		The store instance used by this demo.
+	-->
+	<div dojoType="dojox.data.FlickrStore" jsId="flickrStore" label="title"></div>
+	<div dojoType="dojox.data.demos.widgets.FlickrViewList" 
+		store="flickrStore"
+		id="flickrViews" 
+		jsId="flickrViewsWidget"></div>
+
+</body>
+</html>
diff --git a/dojox/data/demos/demo_GoogleFeedStore.html b/dojox/data/demos/demo_GoogleFeedStore.html
new file mode 100644
index 0000000..86c052c
--- /dev/null
+++ b/dojox/data/demos/demo_GoogleFeedStore.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/tundra/tundra_rtl.css";
+		
+		#output {
+			width: 400px;
+			position: absolute;
+			top: 50px;
+		}
+		#entryContent {
+			margin-left: 450px;
+			position: absolute;
+			top: 50px;
+			background-color: #eee;
+			height: 800px;
+			padding: 2px;
+		}		
+		.search-result {
+			width: 100%;
+			border: 2px dashed;
+			padding: 4px;
+		}
+		#entryContent h2 {
+			text-decoration: underline;
+		}
+		.summary {
+			font-weight: bolder;
+		}
+		.tags {
+			background-color: lightGrey;
+		}
+	</style>
+
+	<title>Google Feed Store</title>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../GoogleSearchStore.js"></script>
+	<script type="text/javascript" src="../GoogleFeedStore.js"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dojox.dtl");
+		dojo.require("dojox.dtl.ext-dojo.NodeList");
+		
+		dojo.addOnLoad(function(){
+			dojo.connect(dojo.byId("output"), "onclick", function(evt) {
+				if(evt.target.tagName != "A"){return true;}
+				dojo.stopEvent(evt);
+				
+				dojo.byId("entryContent").innerHTML = dojo.query(".content", evt.target.parentNode)[0].innerHTML;
+				
+				return false;
+			})
+			
+		});
+
+		function doSearch() {					    
+			var query = {
+				url: dojo.byId("searchText").value
+			};
+			var request = {query:query};
+			
+			var itemBuffer = [];
+			var maxBufSize = 8;
+			var outNode = dojo.byId("output");
+			outNode.innerHTML = "Searching...";	
+			var count = 0;
+			var template = "GoogleFeedTemplate.html";
+			testStore = new dojox.data.GoogleFeedStore();
+			function doAppend(items){
+				var node = document.createElement("div");
+				node.id = "res" + (count++);
+				outNode.appendChild(node);
+				dojo.query("#"+node.id).dtl(template, { items: items , store: testStore});
+			}
+			
+			request.onBegin = function(numItems){
+				outNode.innerHTML += ".. found " + numItems + " results";
+			};
+			
+			request.onComplete = doAppend;
+
+			var count = dojo.byId("count").value;
+			request.count = count ? Number(count) : 8;			
+			
+			testStore.fetch(request);
+		}
+	</script>
+</head>
+<body class="tundra" style="margin:20px;">
+	<form>
+		Text: <select id="searchText" >
+				<option value="http://shaneosullivan.wordpress.com/feed/">http://shaneosullivan.wordpress.com/feed/</option>
+				<option value="http://dojocampus.org/content/category/dojo-cookies/feed/">http://dojocampus.org/content/category/dojo-cookies/feed/</option>
+				<option value="http://www.dojotoolkit.org/aggregator/rss">http://www.dojotoolkit.org/aggregator/rss</option>
+			</select>
+		Count: <input id="count" type="text" value="10" width=20/>
+		<input id="searchButton" type="button" value="store.fetch()" onclick="doSearch()" />
+		
+		<div id="output">
+			
+		</div>
+		<div id="entryContent">
+			
+		</div>
+	</form>
+</body>
+</html>
diff --git a/dojox/data/demos/demo_GoogleSearchStore.html b/dojox/data/demos/demo_GoogleSearchStore.html
new file mode 100644
index 0000000..b82b334
--- /dev/null
+++ b/dojox/data/demos/demo_GoogleSearchStore.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/tundra/tundra_rtl.css";
+		
+		.search-result {
+			float: left;
+			width: 150px;
+			border: 2px dashed;
+			padding: 4px;
+		}
+	</style>
+
+	<title>Google Search store</title>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.data.GoogleSearchStore");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dojox.dtl");
+		dojo.require("dojox.dtl.ext-dojo.NodeList");
+
+		function doSearch() {
+			var queryOptions = {};
+					    
+			var query = {};
+			query.text = dojo.byId("searchText").value;
+			query.type = dojo.byId("typeText").value;
+			var request = {query:query};
+			
+			var itemBuffer = [];
+			var maxBufSize = 8;
+			var outNode = dojo.byId("output");
+			outNode.innerHTML = "Searching...";	
+			var count = 0;
+			var template = "GoogleTemplate.html";
+			switch(query.type) {
+				case "web" :
+					testStore = new dojox.data.GoogleSearchStore();					
+					break;
+				case "blogs":
+					testStore = new dojox.data.GoogleBlogSearchStore();
+					template = "GoogleTemplateBlog.html";
+					break;
+				case "local":
+					testStore = new dojox.data.GoogleLocalSearchStore();
+					template = "GoogleTemplateLocal.html";
+					break;
+				case "video":
+					testStore = new dojox.data.GoogleVideoSearchStore();
+					template = "GoogleTemplateVideo.html";
+					break;
+				case "news":
+					testStore = new dojox.data.GoogleNewsSearchStore();
+					break;
+				case "books":
+					testStore = new dojox.data.GoogleBookSearchStore();
+					break;
+				case "images":
+					testStore = new dojox.data.GoogleImageSearchStore();
+					template = "GoogleTemplateImage.html";
+					break;
+			}
+			
+			function doAppend(){
+				var node = document.createElement("span");
+				node.id = "res" + (count++);
+				outNode.appendChild(node);
+				dojo.query("#"+node.id).dtl(template, { items: itemBuffer , store: testStore});
+			}
+			
+			request.onBegin = function(numItems){
+				outNode.innerHTML += ".. found " + numItems + " results";
+			};
+			
+			request.onItem = function(item){
+				itemBuffer.push(item);
+				if(itemBuffer.length >= maxBufSize){
+					console.log("onItem, buffer length = " + itemBuffer.length + " & maxBufSize = " + maxBufSize);
+					doAppend();
+					itemBuffer = [];
+				} else {
+					console.log("onItem, buffer length = " + itemBuffer.length);
+				}
+			};
+			
+			request.onComplete = function (items) {				
+				if (itemBuffer.length > 0) {
+					doAppend();
+				}
+			};
+
+			var count = dojo.byId("count").value;
+			request.count = count ? Number(count) : 8;			
+			
+			testStore.fetch(request);
+		}
+	</script>
+</head>
+<body class="tundra" style="margin:20px;">
+	<form>
+		Text: <input id="searchText" type="text" value="dojo ajax"/>
+		Count: <input id="count" type="text" value="8" width=20/>
+		<input id="searchButton" type="button" value="store.fetch()" onclick="doSearch()" />
+		Type 
+			<select id="typeText" name="typeText">
+				<option selected value="web">Web</option>
+				<option value="local">Local</option>
+				<option value="video">Video</option>
+				<option value="blogs">Blogs</option>
+				<option value="news">News</option>
+				<option value="books">Books</option>
+				<option value="images">Images</option>			
+			</select> 
+		<div id="output">
+			
+		</div>
+	</form>
+</body>
+</html>
diff --git a/dojox/data/demos/demo_GoogleSearchStore_Grid.html b/dojox/data/demos/demo_GoogleSearchStore_Grid.html
new file mode 100644
index 0000000..e73ba0d
--- /dev/null
+++ b/dojox/data/demos/demo_GoogleSearchStore_Grid.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/tundra/tundra_rtl.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dojox/grid/resources/tundraGrid.css";
+	</style>
+
+	<title>Google Search Store with Grid</title>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../../../dijit/dijit.js"></script>
+	<script type="text/javascript" src="../GoogleSearchStore.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojox.wire.ml.Invocation");
+		dojo.require("dojox.wire.ml.Transfer");
+		dojo.require("dojox.wire.ml.Action");
+		dojo.require("dojox.data.GoogleSearchStore");
+
+		var href = function(value) {
+			return "<a href=\"" + value + "\" target=\"_blank\">" + value + "</a>";  
+		}
+		var layoutResults = [
+				[
+					{ name: "Title", field: "title", width: 10 },
+					{ name: "Summary", field: "content", width: "auto"},
+					{ name: "URL", field: "url", width: 20, formatter: href }
+				]
+		];
+		var newQuery = {text: 'dojo ajax' }; 
+	</script>
+</head>
+<body class="tundra" style="margin:20px;">
+	<h1>dojox.data.GoogleSearchStore:</h1>
+	<i>Displays a list of results from a google query.</i>
+	<div dojoType="dojox.data.GoogleSearchStore" jsId="googleStore"></div>
+	<br>
+	<br>
+	<div dojoType="dijit.form.TextBox" id="searchText" value="dojo ajax"></div> 
+	<button dojoType="dijit.form.Button" id="searchButton">Search</button>
+	<br>
+	<br>
+	<br>
+
+	<div dojoType="dojox.grid.DataGrid" 
+		rowsPerPage="8"
+		store="googleStore" 
+		structure="layoutResults" 
+		query="{ text: 'dojo ajax' }"
+		jsId="grid"
+		style="width: 800px; height: 500px;"
+		>
+	</div>
+	
+	<!-- 
+		Link the button to updating the query, then triggering the refresh of the grid. 
+		Handy use of dojox.wire!
+	-->    
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="searchButton"
+		triggerEvent="onClick">
+		<div dojoType="dojox.wire.ml.Transfer" source="searchText.value" target="newQuery.text"></div>
+		<div dojoType="dojox.wire.ml.Invocation" object="grid" method="setQuery" parameters="newQuery"></div>
+	</div>    
+</body>
+</html>
diff --git a/dojox/data/demos/demo_LazyLoad.html b/dojox/data/demos/demo_LazyLoad.html
new file mode 100644
index 0000000..358ce84
--- /dev/null
+++ b/dojox/data/demos/demo_LazyLoad.html
@@ -0,0 +1,66 @@
+<!--
+  This file is a simple loader for the Lazy Load demo of a Datastore.  In this
+  Example, a simple extension of ItemFileReadStore that can do rudimentary lazy-loading
+  of items into the store is used to showcase how Datastores can hide how data
+  is loaded from the widget.  As long as the widget implements to the Dojo.data API
+  spec, then it should be able to use most datastores as input sources for its
+  values.
+-->
+<html>
+<head>
+	<title>Demo of Lazy Loading Datastore</title>
+	<style type="text/css">
+
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true, usePlainJson: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojox.data.demos.stores.LazyLoadJSIStore");
+		dojo.require("dijit.Tree");
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>
+		DEMO:  Lazy Loading Datastore used by dijit.Tree
+	</h1>
+	<hr>
+	<h3>
+		Description:
+	</h3>
+	<p>
+		This simple demo shows how the dijit.Tree widget can work with a Datastore that does lazy-loading of values into the tree.  
+		In this demo, the Datastore is an extension of ItemFileReadStore that overrides the <i>isItemLoaded()</i> and <i>loadItem()</i> functions of
+		with ones that can detect 'stub' items and use the data in the stub item to load the real data for that item when it
+		is required.  In this demo, the real data is required when one of the tree nodes is expanded.
+	</p>
+	<p>
+		The key thing to note is that all the lazy-loading logic (how to locate the data from the backend and so forth) is encapsulated 
+		into the store functions.  The dijit.Tree widget only knows about and uses the dojo.data.Read API interfaces to call to the store to 
+		get items, test if child items are fully loaded or not, and to invoke the <i>loadItem()</i>  function on items that are not yet fully 
+		loaded but have been requested to be expanded into view.  It has no knowledge of how the store actually goes and gets the data.
+	</p>        
+
+	<blockquote>
+
+	<!--
+		The store instance used by this demo.
+	-->
+	<div dojoType="dojox.data.demos.stores.LazyLoadJSIStore" jsId="continentStore"
+		url="geography/root.json"></div>
+
+	<!-- 
+		Display the toplevel tree with items that have an attribute of 'type',
+		with value of 'contintent'
+	-->
+	<b>Continents</b>
+	<div dojoType="dijit.Tree" id=tree label="Continents" store="continentStore" query="{type:'continent'}"
+		labelAttr="name" typeAttr="type"></div>
+	</blockquote>
+
+</body>
+</html>
diff --git a/dojox/data/demos/demo_MultiStores.html b/dojox/data/demos/demo_MultiStores.html
new file mode 100644
index 0000000..29ede27
--- /dev/null
+++ b/dojox/data/demos/demo_MultiStores.html
@@ -0,0 +1,116 @@
+<!--
+  This file is a demo of multiple dojo.data aware widgets using different datastore implementations for displaying data.
+-->
+<html>
+<head>
+	<title>Demo of Multiple Widgets using different Datastores</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+
+		dojo.require("dojox.data.OpmlStore");
+		dojo.require("dojox.data.XmlStore");
+		dojo.require("dojo.data.ItemFileReadStore");
+
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>
+		DEMO:  Multiple DataStore implementations with dojo.data aware Widgets
+	</h1>
+	<hr>
+	<h3>
+		Description:
+	</h3>
+	<p>
+		This simple demo shows how widgets which know only the dojo.data interfaces can work with data sources of varying formats.  In this case an OpmlStore
+		and a ItemFileReadStore are used to house the same data in different formats.
+	</p>
+
+	<blockquote>
+
+    	<!--
+    		The store instances used by this demo.
+    	-->
+    	<div dojoType="dojo.data.ItemFileReadStore" url="geography.json"               jsId="ifrGeoStore"></div>
+    	<div dojoType="dojox.data.OpmlStore"        url="geography.xml"   label="text" jsId="opmlGeoStore"></div>
+        <div dojoType="dojox.data.XmlStore"         url="geography2.xml"  label="text" attributeMap="{'text': '@text'}" jsId="xmlGeoStore"></div>
+    
+    	<h3>
+    		Widgets using OpmlStore:
+    	</h3>
+    	<blockquote>
+        	<b>ComboBox:</b><br>
+        	<input dojoType="dijit.form.ComboBox" id="combo1" name="combo1" class="medium" store="opmlGeoStore" searchAttr="text" query="{}"></input>
+        	<br>
+        	<br>
+        	<b>Filtering Select:</b><br>
+        	<input dojoType="dijit.form.FilteringSelect" id="fs1" name="fs1" class="medium" store="opmlGeoStore" searchAttr="text" query="{}"></input>
+        	<br>
+        	<br>
+        
+        	<b>Tree:</b><br>
+        	<div dojoType="dijit.tree.ForestStoreModel" jsId="opmlModel" 
+		        store="opmlGeoStore" query="{}"
+		        rootId="Continents" rootLabel="Continents" childrenAttrs="children">
+            </div>
+        	<div dojoType="dijit.Tree" id="tree1" model="opmlModel"></div>
+        </blockquote>
+    
+    	<h3>
+    		Widgets using ItemFileReadStore:
+    	</h3>
+    	<blockquote>
+        	<b>ComboBox:</b><br>
+        	<input dojoType="dijit.form.ComboBox" id="combo2" name="combo2" class="medium" store="ifrGeoStore" searchAttr="name" query="{}"></input>
+        	<br>
+        	<br>
+        
+            <b>Filtering Select:</b><br>
+        	<input dojoType="dijit.form.FilteringSelect" id="fs2" name="fs2" class="medium" store="ifrGeoStore" searchAttr="text" query="{}"></input>
+        	<br>
+        	<br>
+        
+        	<b>Tree:</b><br>
+        	<div dojoType="dijit.tree.ForestStoreModel" jsId="ifrModel" 
+		        store="ifrGeoStore" query="{}"
+		        rootId="Continents" rootLabel="Continents" childrenAttrs="children">
+            </div>
+           	<div dojoType="dijit.Tree" id="tree2" model="ifrModel"></div>
+    	</blockquote>
+    
+    	<h3>
+    		Widgets using XmlStore:
+    	</h3>
+    	<blockquote>
+        	<b>ComboBox:</b><br>
+        	<input dojoType="dijit.form.ComboBox" id="combo3" name="combo3" class="medium" store="xmlGeoStore" searchAttr="text" query="{}"></input>
+        	<br>
+        	<br>
+        	
+            <b>Filtering Select:</b><br>
+        	<input dojoType="dijit.form.FilteringSelect" id="fs3" name="fs3" class="medium" store="xmlGeoStore" searchAttr="text" query="{}"></input>
+        	<br>
+        	<br>
+        
+        	<b>Tree:</b><br>
+        	<div dojoType="dijit.tree.ForestStoreModel" jsId="xmlModel" 
+		        store="xmlGeoStore" query="{}"
+		        rootId="Continents" rootLabel="Continents" childrenAttrs="childNodes">
+            </div>
+           	<div dojoType="dijit.Tree" id="tree3" model="xmlModel"></div>
+    	</blockquote>
+	</blockquote>
+</body>
+</html>
diff --git a/dojox/data/demos/demo_OpenSearchStore.html b/dojox/data/demos/demo_OpenSearchStore.html
new file mode 100644
index 0000000..e8bcc13
--- /dev/null
+++ b/dojox/data/demos/demo_OpenSearchStore.html
@@ -0,0 +1,215 @@
+<!--
+  This file is a demo of the OpenSearchStore, a simple wrapper to any OpenSearch compliant
+  search engine.
+  
+  Note, the simple proxy requires a curl-enabled PHP install
+-->
+<html>
+<head>
+	<title>Demo of OpenSearchStore</title>
+	<style type="text/css">
+
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "./openSearchDemo.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dijit.form.CheckBox");
+		dojo.require("dijit.form.NumberSpinner");
+		dojo.require("dijit.Tree");
+		dojo.require("dojox.data.OpenSearchStore");
+
+		function init(){
+			var fViewWidgets = [];
+
+			//Set up an onComplete handler for OpenSearchData
+			function onComplete(items, request){
+				if(items.length > 0){
+					var ul = dojo.byId("searchResults");
+					var test;
+					var li;
+					for(var i=0; i<items.length; i++){
+						li = dojo.doc.createElement("li");
+						li.innerHTML = openSearchStore.getValue(items[i], "content");
+						ul.appendChild(li);
+					}
+				}
+				statusWidget.attr('value', "PROCESSING COMPLETE.");
+			}
+			//What to do if a search fails...
+			function onError(error, request){
+				statusWidget.attr('value', "PROCESSING ERROR.");
+			}
+
+			//Function to invoke the search of the openSearchStore
+			function invokeSearch(){
+				var tbody = dojo.byId("searchResults");
+				while(tbody.childNodes.length){
+					var node = tbody.childNodes.item(0);
+					node.parentNode.removeChild(node);
+				}
+				var request = {
+					query: {},
+					onComplete: onComplete,
+					onError: onError
+				};
+				if(searchTermsWidget){
+					var searchTerms = searchTermsWidget.attr('value');
+					if(searchTerms && searchTerms !== ""){
+						var searchTermsArray = searchTerms.split(" ");
+						searchTerms = "";
+						for(var i = 0; i < searchTermsArray.length; i++){
+							searchTerms = searchTerms + searchTermsArray[i];
+							if(i < (searchTermsArray.length - 1)){
+								searchTerms += ","
+							}
+						}
+						request.query.searchTerms = searchTerms;
+					}
+				}
+
+				if(countWidget){
+					request.count = countWidget.attr('value');
+				}
+
+				if(statusWidget){
+					statusWidget.attr('value', "PROCESSING REQUEST");
+				}
+
+				openSearchStore.fetch(request);
+			}
+
+			//Lastly, link up the search event.
+			dojo.connect(dijit.byId("searchButton"), 'onClick', invokeSearch);
+			var currentArgs = {url: 'http://intertwingly.net/search/'};
+			var oldProcess = null;
+			function setTransform(state){
+				if(state){
+					oldProcess = openSearchStore.processItem;
+					switch(currentArgs.url){
+						case 'http://intertwingly.net/search/':
+							openSearchStore.processItem = intertwinglyTransform;
+							break;
+						case 'http://www.shutterpoint.com/opensearch.xml':
+							openSearchStore.processItem = shutterpointTransform;
+							break;
+						case 'http://technorati.com/osd.xml':
+							openSearchStore.processItem = technoratiTransform;
+							break;
+					}
+				}else if(oldProcess !== null){
+					openSearchStore.processItem = oldProcess;
+				}
+			}
+			dojo.connect(dijit.byId('transformItem'), 'onChange', function(state){
+				setTransform(state);
+			});
+			dojo.connect(dijit.byId('urlSelector'), 'onChange', function(args){
+				currentArgs = dojo.fromJson(args);
+				currentArgs.url = 'openSearchProxy.php?osd=true&url='+currentArgs.url;
+				openSearchStore.close();
+				openSearchStore = new dojox.data.OpenSearchStore(currentArgs);
+				if(dijit.byId('transformItem').checked){
+					setTransform(true);
+				}
+			});
+
+			var intertwinglyTransform = function(item, attribute){
+				function removeAll(/*NodeList*/list){
+					while(list.length) {
+						var node = list.item(0);
+						node.parentNode.removeChild(node);
+					}
+				}
+				var content = item.node.getElementsByTagName("content").item(0);
+				// Remove all blockquote elements
+				removeAll(content.getElementsByTagName("blockquote"));
+				// Remove all pre-formatted elements
+				removeAll(content.getElementsByTagName("pre"));
+				return openSearchStore._getNodeXml(content, true);
+			};
+
+			var shutterpointTransform = function(item, attribute){
+				var description = item.node.getElementsByTagName("description").item(0);
+				var div = dojo.doc.createElement("div");
+				div.innerHTML = description.childNodes.item(0).nodeValue;
+				//Of the description children, remove the divs (to only leave the images)
+				for(var i=0; i<div.childNodes.length; i++){
+					var node = div.childNodes.item(i);
+					if(node.tagName.toLowerCase() === "div")
+						node.parentNode.removeChild(node);
+				}
+				return openSearchStore._getNodeXml(div, true);
+			};
+
+			var technoratiTransform = function(item, attribute){
+				function removeAll(/*NodeList*/list){
+					while(list.length) {
+						var node = list.item(0);
+						node.parentNode.removeChild(node);
+					}
+				}
+				removeAll(item.node.getElementsByTagName("blockquote"));
+				return item.innerHTML;
+			};
+		}
+		dojo.addOnLoad(init);
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>DEMO:  OpenSearchStore Search</h1>
+	<hr />
+	<h3>Description:</h3>
+	<p>
+		This simple demo shows how services, such as an OpenSearch compliant search service, can be wrapped by the datastore API.  In this demo, you can search public search engines through a simple OpenSearchStore by specifying a series of search terms (separated by spaces) to search on.  The results will be displayed below the search box.
+	</p>
+    <p>
+        <b>NOTE:  This demo makes use of a simple PHP based proxy script.  The proxy script requires cURL support in PHP.  Without cURL support, the demo will throw errors.</b>
+    </p>
+	<label for="urlSelector">URL of OpenSearchDocument:</label>
+	<select dojoType="dijit.form.FilteringSelect"
+			id="urlSelector"
+			name="urlSelector"
+			autoComplete="true">
+		<option value="{url: 'http://intertwingly.net/search/'}">http://intertwingly.net/search/</option>
+		<option value="{url: 'http://www.shutterpoint.com/opensearch.xml'}">http://www.shutterpoint.com/opensearch.xml</option>
+		<option value="{url: 'http://technorati.com/osd.xml', itemPath: '.hentry'}">http://technorati.com/osd.xml</option>
+	</select>
+	<label for="transformItem">Apply transform function?</label>
+	<input dojoType="dijit.form.CheckBox"
+		   type="checkbox"
+		   id="transformItem"
+		   name="transformItem">
+	</input>
+	<hr />
+	<label for="status">Status:</label>
+	<div dojoType="dijit.form.TextBox" maxLength="50" id="status" name="status" jsId="statusWidget" disabled="true"></div>
+	<label for="searchTerms">Search For:</label>
+	<div dojoType="dijit.form.TextBox" maxLength="50" id="searchTerms" name="searchTerms" jsId="searchTermsWidget" value="javascript"></div>
+	<label for="count">Number of Results:</label>
+	<div id="count"
+		 name="count"
+		 jsId="countWidget"
+		 dojoType="dijit.form.NumberSpinner"
+		 value="20"
+		 constraints="{min:1,max:20}">
+	</div>
+	<div dojoType="dijit.form.Button" label="Search" id="searchButton" jsId="searchButtonWidget"></div>
+	<hr/>
+	<div dojoType="dojox.data.OpenSearchStore"
+		 url="openSearchProxy.php?osd=true&url=http://intertwingly.net/search/"
+		 jsId="openSearchStore">
+	</div>
+	<ul id="searchResults"></ul>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/data/demos/demo_PicasaStore.html b/dojox/data/demos/demo_PicasaStore.html
new file mode 100644
index 0000000..47f73a4
--- /dev/null
+++ b/dojox/data/demos/demo_PicasaStore.html
@@ -0,0 +1,190 @@
+<!--
+  This file is a demo of the PicasaStore, a simple wrapper to the public feed service
+  of Picasa.  This just does very basic queries against Picasa and loads the results
+  into a list viewing widget.
+-->
+<html>
+<head>
+	<title>Demo of PicasaStore</title>
+	<style type="text/css">
+
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "./picasaDemo.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.NumberSpinner");
+		dojo.require("dijit.Tree");
+		dojo.require("dojox.data.PicasaStore");
+		dojo.require("dojox.data.demos.widgets.PicasaViewList");
+		dojo.require("dojox.data.demos.widgets.PicasaView");
+		
+		function init(){
+			var fViewWidgets = [];
+
+			//Set up an onComplete handler for picasaData
+			function onComplete(items, request){
+				picasaViewsWidget.clearList();
+				if(items.length > 0){
+					for(var i = 0; i < items.length; i++){
+						var picasaData = {
+							title: picasaStore.getValue(items[i],"title"),
+							author: picasaStore.getValue(items[i],"author"),
+							description: picasaStore.getValue(items[i],"description"),
+							iconUrl: picasaStore.getValue(items[i],"imageUrlSmall"),
+							imageUrl: picasaStore.getValue(items[i],"imageUrl")
+						}
+						picasaViewsWidget.addView(picasaData);
+					}
+				}
+				statusWidget.attr("value", "PROCESSING COMPLETE.");
+
+			}
+			//What to do if a search fails...
+			function onError(error, request){
+                console.debug(error);
+				picasaViewsWidget.clearList();
+				statusWidget.attr("value", "PROCESSING ERROR.");
+			}
+
+			//Function to invoke the search of the PicasaStore
+			function invokeSearch(){
+				var request = {
+					query: {},
+					onComplete: onComplete,
+					onError: onError
+				};
+
+				if(idWidget){
+					var userid = idWidget.attr("value");
+					if(userid && userid !== ""){
+						request.query.userid = userid;
+					}
+				}
+				if(tagsWidget){
+					var tags = tagsWidget.attr("value");
+					if(tags && tags !== ""){
+						var tagsArray = tags.split(" ");
+						tags = "";
+						for(var i = 0; i < tagsArray.length; i++){
+							tags = tags + tagsArray[i];
+							if(i < (tagsArray.length - 1)){
+								tags += ","
+							}
+						}
+						request.query.tags = tags;
+					}
+				}
+				if(countWidget){
+					request.count = countWidget.attr("value");
+				}
+
+				if(startWidget){
+					request.query.start = startWidget.attr("value");
+				}
+
+				if(statusWidget){
+					statusWidget.attr("value","PROCESSING REQUEST");
+				}
+
+				picasaStore.fetch(request);
+			}
+
+			//Lastly, link up the search event.
+			var button = dijit.byId("searchButton");
+			dojo.connect(button, "onClick", invokeSearch);
+		}
+		dojo.addOnLoad(init);
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>
+		DEMO:  PicasaStore Search
+	</h1>
+	<hr>
+	<h3>
+		Description:
+	</h3>
+	<p>
+		This simple demo shows how services, such as Picasa, can be wrapped by the datastore API.  In this demo, you can search public Picasa images through a simple PicasaStore by specifying a series of tags (separated by spaces) to search on.  The results will be displayed below the search box.
+	</p>
+	<p>
+		For fun, search on the 3dny tag!
+	</p>
+
+	<blockquote>
+
+	<!--
+		The store instance used by this demo.
+	-->
+	<table>
+		<tbody>
+			<tr>
+				<td>
+					<b>Status:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="status" jsId="statusWidget" disabled="true"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>ID:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="userid" jsId="idWidget"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>Query:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="tags" jsId="tagsWidget" value="flower"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>Number of Pictures:</b>
+				</td>
+				<td>
+					<div   
+						id="start"
+						jsId="startWidget"
+						dojoType="dijit.form.NumberSpinner"
+						value="1"
+						constraints="{min:1,places:0}" 
+					></div>
+					<div   
+						id="count"
+						jsId="countWidget"
+						dojoType="dijit.form.NumberSpinner"
+						value="20"
+						constraints="{min:1,max:100,places:0}" 
+					></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+				</td>
+				<td>
+					<div dojoType="dijit.form.Button" label="Search" id="searchButton" jsId="searchButtonWidget"></div>
+				</td>
+			</tr>
+		</tbody>
+	</table>
+	<hr/>
+	</blockquote>
+	<div dojoType="dojox.data.PicasaStore" jsId="picasaStore" label="title"></div>
+	<div dojoType="dojox.data.demos.widgets.PicasaViewList" id="picasaViews" jsId="picasaViewsWidget"></div>
+
+</body>
+</html>
diff --git a/dojox/data/demos/demo_QueryReadStore_ComboBox.html b/dojox/data/demos/demo_QueryReadStore_ComboBox.html
new file mode 100644
index 0000000..6be9265
--- /dev/null
+++ b/dojox/data/demos/demo_QueryReadStore_ComboBox.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox QueryReadStore+ComboBox Demo</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">Dojox QueryReadStore + ComboBox demo</h1>
+ 
+	<h2>Everything is created ONLY in markup</h2>
+	<div class="dijitContainer">
+		<div style="float:left;">
+			<div dojoType="dojox.data.QueryReadStore"
+				jsId="store1"
+				url="../tests/stores/QueryReadStore.php"
+				requestMethod="post"></div>
+			<div dojoType="dijit.form.ComboBox" id="cb1" store="store1" pageSize="10" autoComplete="false"></div>
+			<button dojoType="dijit.form.Button" onclick="dijit.byId('cb1').reset()">reset</button>
+		</div>
+		<div style="float:left; margin-left:5em;">
+			var w = dijit.byId("cb1");
+			<br /><input id="value1" type="text" /> = w.value
+			<br /><input id="itemId1" type="text" /> = w.item ? w.store.getValue(w.item, "id") : "-"
+			<br /><input id="displayedValue1" type="text" /> = w.attr("displayedValue")
+			<br /><input id="isValid1" type="text" /> = w.isValid()
+			<br /><button dojoType="dijit.form.Button" onclick="refresh1()">refresh</button>
+		</div>
+	</div>
+
+	<script type="text/javascript">
+		dojo.require("dojox.data.QueryReadStore");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.Button");
+		
+		var w = null;
+		var refresh1 = function() {
+			dojo.byId("value1").value = w.value;
+			dojo.byId("itemId1").value = w.item ? w.store.getValue(w.item, "id") : "-";
+			dojo.byId("displayedValue1").value = w.attr("displayedValue");
+			dojo.byId("isValid1").value = w.isValid();
+		};
+		dojo.addOnLoad(function() {
+			w = dijit.byId("cb1");
+			dojo.connect(w.domNode, "onkeyup", refresh1);
+			dojo.connect(w, "onBlur", refresh1);
+			dojo.connect(w, "onChange", refresh1);
+			refresh1();
+		});
+	</script>
+</body>
+</html>
diff --git a/dojox/data/demos/demo_QueryReadStore_FilteringSelect.html b/dojox/data/demos/demo_QueryReadStore_FilteringSelect.html
new file mode 100644
index 0000000..6f89167
--- /dev/null
+++ b/dojox/data/demos/demo_QueryReadStore_FilteringSelect.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox QueryReadStore+FilteringSelect Demo</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">Dojox QueryReadStore + FilteringSelect demo</h1>
+ 
+	<h2>Everything is created ONLY in markup</h2>
+	<div style="float:left;">
+		<div dojoType="dojox.data.QueryReadStore"
+			jsId="store1"
+			url="../tests/stores/QueryReadStore.php"
+			requestMethod="post"></div>
+		<div dojoType="dijit.form.FilteringSelect" id="fs1" store="store1" pageSize="10" autoComplete="false"></div>
+		<button dojoType="dijit.form.Button" onclick="dijit.byId('fs1').reset()">reset</button>
+	</div>
+	<div style="float:left; margin-left:5em;">
+		var w = dijit.byId("fs1");
+		<br /><input id="value1" type="text" /> = w.value
+		<br /><input id="itemId1" type="text" /> = w.item ? w.store.getValue(w.item, "id") : "-"
+		<br /><input id="displayedValue1" type="text" /> = w.getDisplayedValue()
+		<br /><input id="isValid1" type="text" /> = w.isValid()
+		<br /><button dojoType="dijit.form.Button" onclick="refresh1()">refresh</button>
+	</div>
+
+	<script type="text/javascript">
+		dojo.require("dojox.data.QueryReadStore");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dijit.form.Button");
+		
+		var w = null;
+		var refresh1 = function() {
+			dojo.byId("value1").value = w.value;
+			dojo.byId("itemId1").value = w.item ? w.store.getValue(w.item, "id") : "-";
+			dojo.byId("displayedValue1").value = w.getDisplayedValue();
+			dojo.byId("isValid1").value = w.isValid();
+		};
+		dojo.addOnLoad(function() {
+			w = dijit.byId("fs1");
+			dojo.connect(w.domNode, "onkeyup", refresh1);
+			dojo.connect(w, "onBlur", refresh1);
+			dojo.connect(w, "onChange", refresh1);
+			refresh1();
+		});
+	</script>
+</body>
+</html>
diff --git a/dojox/data/demos/demo_QueryReadStore_grid.html b/dojox/data/demos/demo_QueryReadStore_grid.html
new file mode 100644
index 0000000..7035ebd
--- /dev/null
+++ b/dojox/data/demos/demo_QueryReadStore_grid.html
@@ -0,0 +1,110 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox QueryReadStore+grid Demo</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		/* BE SURE TO NEVER FORGET IMPORTING THE GRID's CSS, or you will wonder why the 
+		   grid looks so strange (or even think that it doesnt work) */
+		@import "../../../dojox/grid/resources/tundraGrid.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true, useCommentedJson: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojox.data.QueryReadStore");
+		dojo.require("dojo.parser"); // scan page for widgets and instantiate them
+		var gridLayout = [
+			new dojox.grid.cells.RowIndex({ name: "row #", width: 5, styles: "text-align: right;" }),
+			{
+				name: "id",
+				field: "id",
+				styles: "text-align:right;",
+				width:5
+			},
+			{
+				name: "Name",
+				field: "name",
+				width:20
+				//formatter: rs.chunk.adminUser.grid.formatUser
+			},
+			{
+				name: "Capital",
+				field: "capital",
+				width:20
+				//formatter: rs.chunk.adminUser.grid.formatUser
+			},
+			{
+				name: "Label",
+				width:20,
+				//styles: "text-align:right;",
+				field: "label"
+				//formatter: phpr.grid.formatDate
+			},
+			{
+				name: "Abbrev.",
+				width:5,
+				//styles: "text-align:right;",
+				field: "abbreviation"
+				//formatter: phpr.grid.formatDate
+			}
+		];
+		// Connect the store AFTER the page is loaded, since we can only access
+		// the widget then, since it will be created just before dojo.addOnLoad() is called.
+		var store = null;
+		dojo.addOnLoad(function() {
+			store = new dojox.data.QueryReadStore({
+				url:"../tests/stores/QueryReadStore.php",
+				requestMethod:"post"
+			});
+			grid1.setStore(store);
+			grid1.setStructure(gridLayout);
+		});
+		
+		var lastSearchValue = "";
+		function doSearch(el) {
+			if (el.value!=lastSearchValue) {
+				lastSearchValue = el.value;
+				grid1.filter({name:el.value});
+				grid2.filter({name:el.value});
+			}
+		}
+	</script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">Dojox QueryReadStore + Grid demo - paging, sortable and filterable all server-side</h1>
+ 
+	<h2>The grid is in HTML, store, etc. are JS, sorting is added by extending the model class</h2>
+	<b>Capabilities:</b> load data from server, show data, paging (30 rows at a time), sort, filter<br />
+	You can see that data are loaded upon demand by scrolling down in the grid below line #30,
+	open FireBug and you see a server request being issued, to retreive another 30 rows/items.<br />
+	<br /><br />
+	<input type="text" onkeyup="doSearch(this)" />
+	<div id="grid1" jsid="grid1" dojoType="dojox.grid.DataGrid" query="{ name: '*' }" rowsPerPage="30" style="height:300px; width:800px;"></div>
+
+	<h2>The store and grid are "generated" and connected in HTML, filtering is done via JS</h2>
+	This store is by default sorted descending by name (not as the one above, which is ascending).
+	<div dojoType="dojox.data.QueryReadStore"
+		jsId="store2"
+		url="../tests/stores/QueryReadStore.php"
+		requestMethod="post"></div>
+	<!--<div dojoType="dojox.grid._data.DojoData"
+		jsId="model2"
+		store="store2"
+		sortFields="[{attribute: 'capital', descending: true}]"
+		rowsPerPage="30"></div>-->
+	<div dojoType="dojox.grid.DataGrid"
+		id="grid2" jsid="grid2"
+		store="store2"
+		query="{ name: '*' }"
+		rowsPerPage="30"
+		structure="gridLayout"
+		style="height:300px; width:800px;"></div>
+
+
+
+</body>
+</html>
diff --git a/dojox/data/demos/demo_WikipediaStore.html b/dojox/data/demos/demo_WikipediaStore.html
new file mode 100644
index 0000000..bc290b0
--- /dev/null
+++ b/dojox/data/demos/demo_WikipediaStore.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Wikipedia Data Store</title>
+<style type="text/css">
+ at import "../../../dojo/resources/dojo.css";
+ at import "../../../dijit/themes/tundra/tundra.css";
+h1 { margin-bottom: 1em; }
+</style>
+<script type="text/javascript">
+//<![CDATA[
+djConfig = { isDebug: true };
+//]]>
+</script>
+<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+<script type="text/javascript">
+//<![CDATA[
+dojo.require("dojox.data.WikipediaStore");
+var store = new dojox.data.WikipediaStore();
+
+function doSearch(){
+	var outNode = dojo.byId("output");
+	outNode.innerHTML = "Searching...";	
+
+	function loadArticle(article){
+		var request = {
+			query: {
+				title: article
+			},
+			onItem: function(item, req){
+				var title = store.getValue(item, "title");
+				var text = store.getValue(item, "text")["*"];
+				outNode.innerHTML = "<h1>" + title + "</h1>" + text;
+			}
+		};
+		console.log("Article request: ", request);
+		store.fetch(request);
+	}
+
+
+	var request = {
+		query: {
+			action: "query",
+			text: dojo.byId("searchText").value
+		},
+		count: dojo.byId("count").value,
+		onBegin: function(count){
+			outNode.innerHTML += " found " + count + " results.<br>Click one to load the article.";
+		},
+		onItem: function(item, req){
+			console.debug(item);
+			var node = document.createElement("a");
+			node.href = "#";
+			node.onclick = function(){
+				console.log("clicked ", this.innerHTML);
+				loadArticle(this.innerHTML);
+			};
+			node.style.padding = "6px";
+			node.style.display = "block";
+			node.innerHTML = store.getValue(item, "title");
+			outNode.appendChild(node);
+		}
+	};
+	console.log("Request: ", request);
+	store.fetch(request);
+}
+//]]>
+</script>
+</head>
+<body class="tundra" style="margin:20px;">
+	<form action="#">
+		<p>
+			Text: <input id="searchText" type="text" value="dojo toolkit">
+			Count: <input id="count" type="text" value="8" size="3">
+			<input id="searchButton" type="button" value="store.fetch()" onclick="doSearch()">
+		</p>
+
+		<div id="output" style="padding:0 20px;">
+		</div>
+	</form>
+</body>
+</html>
diff --git a/dojox/data/demos/geography.json b/dojox/data/demos/geography.json
new file mode 100644
index 0000000..c2f01bb
--- /dev/null
+++ b/dojox/data/demos/geography.json
@@ -0,0 +1,45 @@
+{ identifier: 'name',
+  label: 'name',
+  items: [
+	{ name:'Africa', type:'continent', children:[
+		{ name:'Egypt', type:'country' }, 
+		{ name:'Kenya', type:'country', children:[
+			{ name:'Nairobi', type:'city' },
+			{ name:'Mombasa', type:'city' } ]
+		},
+		{ name:'Sudan', type:'country', children:
+			{ name:'Khartoum', type:'city' } 
+		} ]
+	},
+	{ name:'Asia', type:'continent', children:[
+		{ name:'China', type:'country' },
+		{ name:'India', type:'country' },
+		{ name:'Russia', type:'country' },
+		{ name:'Mongolia', type:'country' } ]
+	},
+	{ name:'Australia', type:'continent', population:'21 million', children:
+		{ name:'Commonwealth of Australia', type:'country', population:'21 million'}
+	},
+	{ name:'Europe', type:'continent', children:[
+		{ name:'Germany', type:'country' },
+		{ name:'France', type:'country' },
+		{ name:'Spain', type:'country' },
+		{ name:'Italy', type:'country' } ]
+	},
+	{ name:'North America', type:'continent', children:[
+		{ name:'Mexico', type:'country',  population:'108 million', area:'1,972,550 sq km', children:[
+			{ name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
+			{ name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' } ]
+		},
+		{ name:'Canada', type:'country',  population:'33 million', area:'9,984,670 sq km', children:[
+			{ name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
+			{ name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' }]
+		},
+		{ name:'United States of America', type:'country' } ]
+	},
+	{ name:'South America', type:'continent', children:[
+		{ name:'Brazil', type:'country', population:'186 million' },
+		{ name:'Argentina', type:'country', population:'40 million' } ]
+	} ]
+}
+
diff --git a/dojox/data/demos/geography.xml b/dojox/data/demos/geography.xml
new file mode 100644
index 0000000..070a8c1
--- /dev/null
+++ b/dojox/data/demos/geography.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<opml version="1.0">
+	<head>
+		<title>geography.opml</title>
+		<dateCreated>2006-11-10</dateCreated>
+		<dateModified>2006-11-13</dateModified>
+		<ownerName>Magellan, Ferdinand</ownerName>
+	</head>
+	<body>
+		<outline text="Africa" type="continent">
+			<outline text="Egypt" type="country"/>
+			<outline text="Kenya" type="country">
+				<outline text="Nairobi" type="city"/>
+				<outline text="Mombasa" type="city"/>
+			</outline>
+			<outline text="Sudan" type="country">
+				<outline text="Khartoum" type="city"/>
+			</outline>
+		</outline>
+		<outline text="Asia" type="continent">
+			<outline text="China" type="country"/>
+			<outline text="India" type="country"/>
+			<outline text="Russia" type="country"/>
+			<outline text="Mongolia" type="country"/>
+		</outline>
+		<outline text="Australia" type="continent" population="21 million">
+			<outline text="Australia" type="country" population="21 million"/>
+		</outline>
+		<outline text="Europe" type="continent">
+			<outline text="Germany" type="country"/>
+			<outline text="France" type="country"/>
+			<outline text="Spain" type="country"/>
+			<outline text="Italy" type="country"/>
+		</outline>
+		<outline text="North America" type="continent">
+			<outline text="Mexico" type="country" population="108 million" area="1,972,550 sq km">
+				<outline text="Mexico City" type="city" population="19 million" timezone="-6 UTC"/>
+				<outline text="Guadalajara" type="city" population="4 million" timezone="-6 UTC"/>
+			</outline>
+			<outline text="Canada" type="country" population="33 million" area="9,984,670 sq km">
+				<outline text="Ottawa" type="city" population="0.9 million" timezone="-5 UTC"/>
+				<outline text="Toronto" type="city" population="2.5 million" timezone="-5 UTC"/>
+			</outline>
+			<outline text="United States of America" type="country"/>
+		</outline>
+		<outline text="South America" type="continent">
+			<outline text="Brazil" type="country" population="186 million"/>
+			<outline text="Argentina" type="country" population="40 million"/>
+		</outline>
+	</body>
+</opml>
diff --git a/dojox/data/demos/geography/Argentina/data.json b/dojox/data/demos/geography/Argentina/data.json
new file mode 100644
index 0000000..17ba291
--- /dev/null
+++ b/dojox/data/demos/geography/Argentina/data.json
@@ -0,0 +1,5 @@
+{ 
+	name:'Argentina', 
+	type:'country', 
+	population:'40 million' 
+}
diff --git a/dojox/data/demos/geography/Brazil/data.json b/dojox/data/demos/geography/Brazil/data.json
new file mode 100644
index 0000000..a326c24
--- /dev/null
+++ b/dojox/data/demos/geography/Brazil/data.json
@@ -0,0 +1,5 @@
+{ 
+	name:'Brazil', 
+	type:'country', 
+	population:'186 million' 
+}
diff --git a/dojox/data/demos/geography/Canada/Ottawa/data.json b/dojox/data/demos/geography/Canada/Ottawa/data.json
new file mode 100644
index 0000000..df3bbc8
--- /dev/null
+++ b/dojox/data/demos/geography/Canada/Ottawa/data.json
@@ -0,0 +1,6 @@
+{ 
+		name:'Ottawa', 
+		type:'city', 
+		population:'0.9 million', 
+		timezone:'-5 UTC'
+}
diff --git a/dojox/data/demos/geography/Canada/Toronto/data.json b/dojox/data/demos/geography/Canada/Toronto/data.json
new file mode 100644
index 0000000..534409b
--- /dev/null
+++ b/dojox/data/demos/geography/Canada/Toronto/data.json
@@ -0,0 +1,6 @@
+{ 
+		name:'Toronto', 
+		type:'city', 
+		population:'2.5 million', 
+		timezone:'-5 UTC' 
+}
diff --git a/dojox/data/demos/geography/Canada/data.json b/dojox/data/demos/geography/Canada/data.json
new file mode 100644
index 0000000..6ef34ed
--- /dev/null
+++ b/dojox/data/demos/geography/Canada/data.json
@@ -0,0 +1,10 @@
+{ 
+	name:'Canada', 
+	type:'country',  
+	population:'33 million', area:'9,984,670 sq km',
+	children:[
+		{stub:'Ottawa'}, 
+		{stub:'Toronto'}
+	] 
+}
+
diff --git a/dojox/data/demos/geography/China/data.json b/dojox/data/demos/geography/China/data.json
new file mode 100644
index 0000000..72c29cc
--- /dev/null
+++ b/dojox/data/demos/geography/China/data.json
@@ -0,0 +1,4 @@
+{ 
+	name:'China', 
+	type:'country' 
+}
diff --git a/dojox/data/demos/geography/Commonwealth of Australia/data.json b/dojox/data/demos/geography/Commonwealth of Australia/data.json
new file mode 100644
index 0000000..e093295
--- /dev/null
+++ b/dojox/data/demos/geography/Commonwealth of Australia/data.json	
@@ -0,0 +1,5 @@
+{ 
+	name:'Commonwealth of Australia', 
+	type:'country', 
+	population:'21 million'
+}
diff --git a/dojox/data/demos/geography/Egypt/data.json b/dojox/data/demos/geography/Egypt/data.json
new file mode 100644
index 0000000..d355537
--- /dev/null
+++ b/dojox/data/demos/geography/Egypt/data.json
@@ -0,0 +1,5 @@
+{
+	name:'Egypt', 
+	type:'country' 
+}
+
diff --git a/dojox/data/demos/geography/France/data.json b/dojox/data/demos/geography/France/data.json
new file mode 100644
index 0000000..5b5f3c3
--- /dev/null
+++ b/dojox/data/demos/geography/France/data.json
@@ -0,0 +1,4 @@
+{ 
+	name:'France', 
+	type:'country' 
+}
diff --git a/dojox/data/demos/geography/Germany/data.json b/dojox/data/demos/geography/Germany/data.json
new file mode 100644
index 0000000..1656257
--- /dev/null
+++ b/dojox/data/demos/geography/Germany/data.json
@@ -0,0 +1,4 @@
+{ 
+	name:'Germany', 
+	type:'country' 
+}
diff --git a/dojox/data/demos/geography/India/data.json b/dojox/data/demos/geography/India/data.json
new file mode 100644
index 0000000..3103f89
--- /dev/null
+++ b/dojox/data/demos/geography/India/data.json
@@ -0,0 +1,4 @@
+{ 
+	name:'India', 
+	type:'country' 
+}
diff --git a/dojox/data/demos/geography/Italy/data.json b/dojox/data/demos/geography/Italy/data.json
new file mode 100644
index 0000000..6e6b076
--- /dev/null
+++ b/dojox/data/demos/geography/Italy/data.json
@@ -0,0 +1,4 @@
+{ 
+	name:'Italy', 
+	type:'country' 
+}
diff --git a/dojox/data/demos/geography/Kenya/Mombasa/data.json b/dojox/data/demos/geography/Kenya/Mombasa/data.json
new file mode 100644
index 0000000..28aa849
--- /dev/null
+++ b/dojox/data/demos/geography/Kenya/Mombasa/data.json
@@ -0,0 +1,5 @@
+{
+	name:'Mombasa', 
+	type:'city',
+	population: "Unknown"
+}
diff --git a/dojox/data/demos/geography/Kenya/Nairobi/data.json b/dojox/data/demos/geography/Kenya/Nairobi/data.json
new file mode 100644
index 0000000..f5658ec
--- /dev/null
+++ b/dojox/data/demos/geography/Kenya/Nairobi/data.json
@@ -0,0 +1,5 @@
+{
+	name:'Nairobi', 
+	type:'city',
+	population: "Unknown"
+}
diff --git a/dojox/data/demos/geography/Kenya/data.json b/dojox/data/demos/geography/Kenya/data.json
new file mode 100644
index 0000000..9253c25
--- /dev/null
+++ b/dojox/data/demos/geography/Kenya/data.json
@@ -0,0 +1,9 @@
+{ 
+	name:'Kenya', 
+	type:'country',
+	children:[
+		{stub:'Nairobi'}, 
+		{stub:'Mombasa'}
+	] 
+}
+
diff --git a/dojox/data/demos/geography/Mexico/Guadalajara/data.json b/dojox/data/demos/geography/Mexico/Guadalajara/data.json
new file mode 100644
index 0000000..059fc82
--- /dev/null
+++ b/dojox/data/demos/geography/Mexico/Guadalajara/data.json
@@ -0,0 +1,7 @@
+{ 
+	name:'Guadalajara', 
+	type:'city', 
+	population:'4 million', 
+	timezone:'-6 UTC' 
+}
+
diff --git a/dojox/data/demos/geography/Mexico/Mexico City/data.json b/dojox/data/demos/geography/Mexico/Mexico City/data.json
new file mode 100644
index 0000000..8c67622
--- /dev/null
+++ b/dojox/data/demos/geography/Mexico/Mexico City/data.json	
@@ -0,0 +1,6 @@
+{ 
+	name:'Mexico City', 
+	type:'city', 
+	population:'19 million', 
+	timezone:'-6 UTC'
+}
diff --git a/dojox/data/demos/geography/Mexico/data.json b/dojox/data/demos/geography/Mexico/data.json
new file mode 100644
index 0000000..aa381e4
--- /dev/null
+++ b/dojox/data/demos/geography/Mexico/data.json
@@ -0,0 +1,10 @@
+{ 
+	name:'Mexico', 
+	type:'country',  
+	population:'108 million', 
+	area:'1,972,550 sq km',
+	children:[
+		{stub:'Mexico City'}, 
+		{stub:'Guadalajara'}
+	] 
+}
diff --git a/dojox/data/demos/geography/Mongolia/data.json b/dojox/data/demos/geography/Mongolia/data.json
new file mode 100644
index 0000000..4c60b22
--- /dev/null
+++ b/dojox/data/demos/geography/Mongolia/data.json
@@ -0,0 +1,4 @@
+{ 
+	name:'Mongolia', 
+	type:'country' 
+}
diff --git a/dojox/data/demos/geography/Russia/data.json b/dojox/data/demos/geography/Russia/data.json
new file mode 100644
index 0000000..5d9a6ba
--- /dev/null
+++ b/dojox/data/demos/geography/Russia/data.json
@@ -0,0 +1,4 @@
+{ 
+	name:'Russia', 
+	type:'country' 
+}
diff --git a/dojox/data/demos/geography/Spain/data.json b/dojox/data/demos/geography/Spain/data.json
new file mode 100644
index 0000000..d9a1210
--- /dev/null
+++ b/dojox/data/demos/geography/Spain/data.json
@@ -0,0 +1,4 @@
+{ 
+	name:'Spain', 
+	type:'country' 
+}
diff --git a/dojox/data/demos/geography/Sudan/Khartoum/data.json b/dojox/data/demos/geography/Sudan/Khartoum/data.json
new file mode 100644
index 0000000..befa3c7
--- /dev/null
+++ b/dojox/data/demos/geography/Sudan/Khartoum/data.json
@@ -0,0 +1,5 @@
+{       
+	name:'Khartoum', 
+	type:'city'
+}
+
diff --git a/dojox/data/demos/geography/Sudan/data.json b/dojox/data/demos/geography/Sudan/data.json
new file mode 100644
index 0000000..fe7585b
--- /dev/null
+++ b/dojox/data/demos/geography/Sudan/data.json
@@ -0,0 +1,6 @@
+{ 
+	name:'Sudan', 
+	type:'country',
+	children:{stub:'Khartoum'} 
+}
+
diff --git a/dojox/data/demos/geography/United States of America/data.json b/dojox/data/demos/geography/United States of America/data.json
new file mode 100644
index 0000000..7dbdd61
--- /dev/null
+++ b/dojox/data/demos/geography/United States of America/data.json	
@@ -0,0 +1,4 @@
+{ 
+	name:'United States of America', 
+	type:'country'
+}
diff --git a/dojox/data/demos/geography/root.json b/dojox/data/demos/geography/root.json
new file mode 100644
index 0000000..dda74f5
--- /dev/null
+++ b/dojox/data/demos/geography/root.json
@@ -0,0 +1,39 @@
+{  
+	identifier: 'name',
+	label: 'name',
+	items: [
+		{ name:'Africa', type:'continent',
+		children:[{_reference:'Egypt'}, {_reference:'Kenya'}, {_reference:'Sudan'}] },
+		{ name:'Egypt', type:'stub', parent: 'geography'},
+	 	{ name:'Kenya', type:'stub', parent: 'geography'},
+	 	{ name:'Sudan', type:'stub', parent: 'geography'},
+
+		{ name:'Asia', type:'continent',
+		children:[{_reference:'China'}, {_reference:'India'}, {_reference:'Russia'}, {_reference:'Mongolia'}] },
+		{ name:'China',    type:'stub', parent: 'geography'},
+	 	{ name:'India',    type:'stub', parent: 'geography'},
+		{ name:'Russia',   type:'stub', parent: 'geography'},
+		{ name:'Mongolia', type:'stub', parent: 'geography'},
+
+		{ name:'Australia', type:'continent', population:'21 million',
+		 children:{_reference:'Commonwealth of Australia'}},
+		{ name:'Commonwealth of Australia', type:'stub', parent:'geography'},
+
+		{ name:'Europe', type:'continent',
+		children:[{_reference:'Germany'}, {_reference:'France'}, {_reference:'Spain'}, {_reference:'Italy'}] },
+		{ name:'Germany', type:'stub', parent: 'geography'},
+		{ name:'France',  type:'stub', parent: 'geography'},
+		{ name:'Spain',   type:'stub', parent: 'geography'},
+		{ name:'Italy',   type:'stub', parent: 'geography'},
+
+		{ name:'North America', type:'continent',
+		children:[{_reference:'Mexico'}, {_reference:'Canada'}, {_reference:'United States of America'}] },
+		{ name:'Mexico',                   type:'stub', parent: 'geography'},
+		{ name:'Canada',                   type:'stub', parent: 'geography'},
+		{ name:'United States of America', type:'stub', parent: 'geography'},
+
+		{ name:'South America', type:'continent',
+		children:[{_reference:'Brazil'}, {_reference:'Argentina'}] },
+		{ name:'Brazil',    type:'stub', parent: 'geography'},
+		{ name:'Argentina', type:'stub', parent: 'geography'}
+]}
diff --git a/dojox/data/demos/geography2.xml b/dojox/data/demos/geography2.xml
new file mode 100755
index 0000000..b82c110
--- /dev/null
+++ b/dojox/data/demos/geography2.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<geography>
+    <outline text="Africa" type="continent">
+        <outline text="Egypt" type="country"/>
+        <outline text="Kenya" type="country">
+            <outline text="Nairobi" type="city"/>
+            <outline text="Mombasa" type="city"/>
+        </outline>
+        <outline text="Sudan" type="country">
+            <outline text="Khartoum" type="city"/>
+        </outline>
+    </outline>
+    <outline text="Asia" type="continent">
+        <outline text="China" type="country"/>
+        <outline text="India" type="country"/>
+        <outline text="Russia" type="country"/>
+        <outline text="Mongolia" type="country"/>
+    </outline>
+    <outline text="Australia" type="continent" population="21 million">
+        <outline text="Australia" type="country" population="21 million"/>
+    </outline>
+    <outline text="Europe" type="continent">
+        <outline text="Germany" type="country"/>
+        <outline text="France" type="country"/>
+        <outline text="Spain" type="country"/>
+        <outline text="Italy" type="country"/>
+    </outline>
+    <outline text="North America" type="continent">
+        <outline text="Mexico" type="country" population="108 million" area="1,972,550 sq km">
+            <outline text="Mexico City" type="city" population="19 million" timezone="-6 UTC"/>
+            <outline text="Guadalajara" type="city" population="4 million" timezone="-6 UTC"/>
+        </outline>
+        <outline text="Canada" type="country" population="33 million" area="9,984,670 sq km">
+            <outline text="Ottawa" type="city" population="0.9 million" timezone="-5 UTC"/>
+            <outline text="Toronto" type="city" population="2.5 million" timezone="-5 UTC"/>
+        </outline>
+        <outline text="United States of America" type="country"/>
+    </outline>
+    <outline text="South America" type="continent">
+        <outline text="Brazil" type="country" population="186 million"/>
+        <outline text="Argentina" type="country" population="40 million"/>
+    </outline>
+</geography>
+
diff --git a/dojox/data/demos/openSearchProxy.php b/dojox/data/demos/openSearchProxy.php
new file mode 100755
index 0000000..4f66307
--- /dev/null
+++ b/dojox/data/demos/openSearchProxy.php
@@ -0,0 +1,33 @@
+<?php
+// A simple proxy for testing the OpenSearchStore
+// Note, this simple proxy requires a curl-enabled PHP install
+if(!$_GET['url']){ return; }
+
+$url = str_replace(array(';;;;', '%%%%'), array('?', '&'), $_GET['url']);
+if(stripos($url, "http://intertwingly.net/") === 0 || 
+	stripos($url, "http://www.intertwingly.net/") === 0 || 
+	stripos($url, "http://www.shutterpoint.com/") === 0 || 
+	stripos($url, "http://technorati.com/") === 0){
+	$ch = curl_init($url);
+	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+	$results = curl_exec($ch);
+	header('HTTP/1.1 ' . curl_getinfo($ch, CURLINFO_HTTP_CODE) . ' OK');
+	if($_GET['osd'] === 'true'){
+		$xml = new SimpleXMLElement($results);
+		if($xml->Url){
+			foreach($xml->Url as $url){
+				$url['template'] = $_SERVER['SCRIPT_NAME'].'?url='.str_replace(array('?', '&'), array(';;;;', '%%%%'), $url['template']);
+			}
+			header('Content-Type: text/xml');
+			print $xml->asXML();
+		}
+	}else{
+		header('Content-Type: '.curl_getinfo($ch, CURLINFO_CONTENT_TYPE));
+		print $results;
+	}
+}else{
+	header("HTTP/1.0 403 Forbidden");
+	header("Status: 403 Forbidden");
+	print "Provided URL not allowed by this demo proxy.";
+}
+
diff --git a/dojox/data/demos/picasaDemo.css b/dojox/data/demos/picasaDemo.css
new file mode 100644
index 0000000..e274f87
--- /dev/null
+++ b/dojox/data/demos/picasaDemo.css
@@ -0,0 +1,44 @@
+.picasaView {
+	padding: 3 3 3 3;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #000000;
+	border-collapse: separate;
+        width: 100%;
+}
+
+.picasaView th {
+	text-align: left;
+} 
+
+.picasaView tr {
+	padding: 3 3 3 3;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #000000;
+}
+
+.picasaView tr td {
+	padding: 3 3 3 3;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #000000;
+}
+
+.picasaView {
+	background-color: #EFEFEF;
+        float: left;
+        width: 250px;
+        height: 250px;
+}
+
+.picasaSummary { 
+       width: 250px;
+       height: 30px;
+       overflow: hidden;
+ }
+
+.picasaTitle {
+	background-color: #CCCCCC;
+}
+
diff --git a/dojox/data/demos/stores/LazyLoadJSIStore.js b/dojox/data/demos/stores/LazyLoadJSIStore.js
new file mode 100644
index 0000000..7a08840
--- /dev/null
+++ b/dojox/data/demos/stores/LazyLoadJSIStore.js
@@ -0,0 +1,138 @@
+dojo.provide("dojox.data.demos.stores.LazyLoadJSIStore");
+dojo.require("dojo.data.ItemFileReadStore");
+
+dojo.declare("dojox.data.demos.stores.LazyLoadJSIStore", dojo.data.ItemFileReadStore, {
+	constructor: function(/* object */ keywordParameters){
+		// LazyLoadJSIStore extends ItemFileReadStore to implement an 
+		// example of lazy-loading/faulting in items on-demand.
+		// Note this is certianly not a perfect implementation, it is 
+		// an example.
+	},
+	
+	isItemLoaded: function(/*object*/ item) {
+		//	summary:
+		//		Overload of the isItemLoaded function to look for items of type 'stub', which indicate
+		//		the data hasn't been loaded in yet.
+		//
+		//	item:
+		//		The item to examine.
+		
+		//For this store, if it has the value of stub for its type attribute, 
+		//then the item basn't been fully loaded yet.  It's just a placeholder.
+		if(this.getValue(item, "type") === "stub"){
+			return false;
+		}
+		return true;
+	},
+		
+	loadItem: function(keywordArgs){
+		//	summary:
+		//		Overload of the loadItem function to fault in items.  This assumes the data for an item is laid out
+		//		in a RESTful sort of pattern name0/name1/data.json and so on and uses that to load the data.
+		//		It will also detect stub items in the newly loaded item and insert the stubs into the ItemFileReadStore
+		//		list so they can also be loaded in on-demand.
+		//
+		//	item:
+		//		The item to examine.
+
+		var item = keywordArgs.item;
+		this._assertIsItem(item);
+
+		//Build the path to the data.json for this item
+		//The path consists of where its parent was loaded from 
+		//plus the item name.
+		var itemName = this.getValue(item, "name");
+		var parent   = this.getValue(item, "parent");
+		var dataUrl  = "";
+		if (parent){
+			dataUrl += (parent + "/");
+		}
+
+		//For this store, all child input data is loaded from a url that ends with data.json
+		dataUrl += itemName + "/data.json";
+
+		//Need a reference to the store to call back to its structures.
+		var self = this;
+
+		// Callback for handling a successful load.
+		var gotData = function(data){
+			//Now we need to modify the existing item a bit to take it out of stub state
+			//Since we extend the store and have knowledge of the internal
+			//structure, this can be done here.  Now, is we extended
+			//a write store, we could call the write APIs to do this too
+			//But for a simple demo the diretc modification in the store function
+			//is sufficient.
+
+			//Clear off the stub indicators.
+			delete item.type;
+			delete item.parent;
+
+			//Set up the loaded values in the format ItemFileReadStore uses for attributes.
+			for (var i in data) {
+				if (dojo.isArray(data[i])) {
+					item[i] = data[i];
+				}else{
+					item[i] = [data[i]];
+				}
+			}
+
+			//Reset the item in the reference.
+			self._arrayOfAllItems[item[self._itemNumPropName]] = item;
+
+			//Scan the new values in the item for extra stub items we need to 
+			//add to the items array of the store so they can be lazy-loaded later...
+			var attributes = self.getAttributes(item);
+			for(i in attributes){
+				var values = item[attributes[i]];
+				for (var j = 0; j < values.length; j++) {
+					var value = values[j];
+					
+					if(typeof value === "object"){
+						if(value["stub"] ){
+							//We have a stub reference here, we need to create the stub item
+							var stub = {
+								type: ["stub"],
+								name: [value["stub"]],	//
+								parent: [itemName]		//The child stub item is parented by this item name...
+							};
+							if (parent) {
+								//Add in any parents to your parent so URL construstruction is accurate.
+								stub.parent[0] = parent + "/" + stub.parent[0]; 
+							}
+							//Finalize the addition of the new stub item into the ItemFileReadStore list.
+							self._arrayOfAllItems.push(stub);
+							stub[self._storeRefPropName] = self;
+							stub[self._itemNumPropName] = (self._arrayOfAllItems.length - 1); //Last one pushed in should be the item
+							values[j] = stub; //Set the stub item back in its place and replace the stub notation.
+						}
+					}
+				}
+			}
+
+			//Done processing!  Call the onItem, if any.
+			if(keywordArgs.onItem){
+				var scope = keywordArgs.scope ? keywordArgs.scope : dojo.global;
+				keywordArgs.onItem.call(scope, item);
+			}
+		};
+
+		//Callback for any errors that occur during load.
+		var gotError = function(error){
+			//Call the onComplete, if any
+			if(keywordArgs.onError){
+				var scope = keywordArgs.scope ? keywordArgs.scope : dojo.global;
+				keywordArgs.onError.call(scope, error);
+			}
+		};
+
+		//Fire the get and pass the proper callbacks to the deferred.
+		var xhrArgs = {
+			url: dataUrl,
+			handleAs: "json-comment-optional"
+		};
+		var d = dojo.xhrGet(xhrArgs);
+		d.addCallback(gotData);
+		d.addErrback(gotError);
+	}
+});
+
diff --git a/dojox/data/demos/stores/filestore_dojotree.php b/dojox/data/demos/stores/filestore_dojotree.php
new file mode 100755
index 0000000..24740a2
--- /dev/null
+++ b/dojox/data/demos/stores/filestore_dojotree.php
@@ -0,0 +1,179 @@
+<?php
+	//Define the root directory to use for this service.
+	//All file lookups are relative to this path.
+	$rootDir = "../../../..";
+
+	require_once("filestore_funcs.php");
+
+	//Extract the query, if any.
+	$query = false;
+	if (array_key_exists("query", $_GET)) {
+		$query = $_GET['query'];
+		$query = str_replace("\\\"", "\"", $query);
+		$query = json_decode($query, true);
+	}
+	//Extract relevant query options.
+	$queryOptions = json_decode("{}");
+	$deep = false;
+	$ignoreCase = false;
+	if (array_key_exists("queryOptions", $_GET)) {
+		$queryOptions = $_GET['queryOptions'];
+		$queryOptions = str_replace("\\\"", "\"", $queryOptions);
+		$queryOptions = json_decode($queryOptions);
+		if (property_exists($queryOptions, "deep")) {
+			$deep = $queryOptions->deep;
+		}
+		if (property_exists($queryOptions, "ignoreCase")) {
+			$ignoreCase = $queryOptions->ignoreCase;
+		}
+	}
+
+	//Extract non-dojo.data spec config options.
+	$expand = false;
+	$dirsOnly = false;
+	$showHiddenFiles = false;
+	$options = array();
+	if (array_key_exists("options", $_GET)) {
+		$options = $_GET['options'];
+		$options = str_replace("\\\"", "\"", $options);
+		$options = json_decode($options);
+		if (array_search("expand", $options) > -1) {
+			$expand = true;
+		}
+		if (array_search("dirsOnly", $options) > -1) {
+			$dirsOnly = true;
+		}
+		if (array_search("showHiddenFiles", $options) > -1) {
+			$showHiddenFiles = true;
+		}
+	}
+
+
+	//See if a specific file was requested, or if it is just a query for files.
+	$path = false;
+	if (array_key_exists("path", $_GET)) {
+		$path = $_GET['path'];
+	}
+
+	if (!is_string($path)) {
+
+		$files = array();
+
+		//Handle query for files.  Must try to generate patterns over the query 
+		//attributes.
+		$patterns = array();
+		if (is_array($query)) {
+			//Generate a series of RegExp patterns as necessary.
+			$keys = array_keys($query);
+			$total = count($keys);
+			if ($total > 0) {
+				for ($i = 0; $i < $total; $i++) {
+					$key = $keys[$i];
+					$pattern = $query[$key];
+					if (is_string($pattern)) {
+						$patterns[$key] = patternToRegExp($pattern);
+					}
+				}
+				$files = matchFiles($query, $patterns, $ignoreCase, ".", $rootDir, $deep, $dirsOnly, $expand, $showHiddenFiles);
+			} else {
+				$files = getAllFiles(".",$rootDir,$deep,$dirsOnly,$expand,$showHiddenFiles);
+			}
+		}else{
+			$files = getAllFiles(".",$rootDir,$deep,$dirsOnly,$expand,$showHiddenFiles);
+		}
+
+		$total = count($files);
+
+		//Handle the sorting and paging.
+		$sortSpec = false;
+		if (array_key_exists("sort", $_GET)) {
+			$sortSpec = $_GET['sort'];
+			$sortSpec = str_replace("\\\"", "\"", $sortSpec);
+			$sortSpec = json_decode($sortSpec);
+		}
+
+		if ($sortSpec != null) {
+			$comparator = createComparator($sortSpec);
+			usort($files,array($comparator, "compare"));
+		}
+
+		//Page, if necessary.
+		if (array_key_exists("start", $_GET)) {
+			$start = $_GET['start'];
+			if (!is_numeric($start)) {
+				$start = 0;
+			}
+			$files = array_slice($files, $start);
+		}
+		if (array_key_exists("count", $_GET)) {
+			$count = $_GET['count'];
+			if (!is_numeric($count)) {
+				$count = $total;
+			}
+			$files = array_slice($files, 0, $count);
+		}
+
+		$result;
+		$result->total = $total;
+		$result->items = $files;
+		header("Content-Type", "text/json");
+		print("/* ".json_encode($result)." */");
+	} else {
+		//Query of a specific file (useful for fetchByIdentity and loadItem)
+
+		//Make sure the path isn't trying to walk out of the rooted directory
+		//As defined by $rootDir in the top of the php script.
+		$rootPath = realPath($rootDir);
+		$fullPath = realPath($rootPath."/".$path);
+
+		if ($fullPath !== false) {
+			if (strpos($fullPath,$rootPath) === 0) {
+				//Root the path into the tree cleaner.
+				if (strlen($fullPath) == strlen($rootPath)) {
+					$path = ".";
+				} else {
+					//Fix the path to relative of root and put back into UNIX style (even if windows).
+					$path = substr($fullPath,(strlen($rootPath) + 1),strlen($fullPath));
+					$path = str_replace("\\", "/", $path);
+				}
+
+				if (file_exists($fullPath)) {
+					$arr = split("/", $path);
+					$size = count($arr);
+
+					if ($size > 0) {
+						$fName = $arr[$size - 1];
+						if ($size == 1) {
+							print("Setting path to: .");
+							$path = ".";
+						} else {
+							$path = $arr[0];
+						}
+						for ($i = 1; $i < ($size - 1); $i++) {
+							$path = $path."/".$arr[$i];
+						}
+						$file = generateFileObj($fName, $path, $rootDir, $expand,$showHiddenFiles);
+						header("Content-Type", "text/json");
+						print("/* ".json_encode($file)." */");
+					} else {
+						header("HTTP/1.0 404 Not Found");
+						header("Status: 404 Not Found");
+						print("<b>Cannot access file: [".htmlentities($path)."]<b>");
+					}
+				} else {
+						header("HTTP/1.0 404 Not Found");
+						header("Status: 404 Not Found");
+						print("<b>Cannot access file: [".htmlentities($path)."]<b>");
+				}
+			} else {
+				header("HTTP/1.0 403 Forbidden");
+				header("Status: 403 Forbidden");
+				print("<b>Cannot access file: [".htmlentities($path)."].  It is outside of the root of the file service.<b>");
+			}
+		} else {
+				header("HTTP/1.0 404 Not Found");
+				header("Status: 404 Not Found");
+				print("<b>Cannot access file: [".htmlentities($path)."]<b>");
+		}
+	}
+?>
diff --git a/dojox/data/demos/stores/filestore_dojoxdata.php b/dojox/data/demos/stores/filestore_dojoxdata.php
new file mode 100755
index 0000000..0360049
--- /dev/null
+++ b/dojox/data/demos/stores/filestore_dojoxdata.php
@@ -0,0 +1,179 @@
+<?php
+	//Define the root directory to use for this service.
+	//All file lookups are relative to this path.
+	$rootDir = "../..";
+
+	require_once("filestore_funcs.php");
+
+	//Extract the query, if any.
+	$query = false;
+	if (array_key_exists("query", $_GET)) {
+		$query = $_GET['query'];
+		$query = str_replace("\\\"", "\"", $query);
+		$query = json_decode($query, true);
+	}
+	//Extract relevant query options.
+	$queryOptions = json_decode("{}");
+	$deep = false;
+	$ignoreCase = false;
+	if (array_key_exists("queryOptions", $_GET)) {
+		$queryOptions = $_GET['queryOptions'];
+		$queryOptions = str_replace("\\\"", "\"", $queryOptions);
+		$queryOptions = json_decode($queryOptions);
+		if (property_exists($queryOptions, "deep")) {
+			$deep = $queryOptions->deep;
+		}
+		if (property_exists($queryOptions, "ignoreCase")) {
+			$ignoreCase = $queryOptions->ignoreCase;
+		}
+	}
+
+	//Extract non-dojo.data spec config options.
+	$expand = false;
+	$dirsOnly = false;
+	$showHiddenFiles = false;
+	$options = array();
+	if (array_key_exists("options", $_GET)) {
+		$options = $_GET['options'];
+		$options = str_replace("\\\"", "\"", $options);
+		$options = json_decode($options);
+		if (array_search("expand", $options) > -1) {
+			$expand = true;
+		}
+		if (array_search("dirsOnly", $options) > -1) {
+			$dirsOnly = true;
+		}
+		if (array_search("showHiddenFiles", $options) > -1) {
+			$showHiddenFiles = true;
+		}
+	}
+
+
+	//See if a specific file was requested, or if it is just a query for files.
+	$path = false;
+	if (array_key_exists("path", $_GET)) {
+		$path = $_GET['path'];
+	}
+
+	if (!is_string($path)) {
+
+		$files = array();
+
+		//Handle query for files.  Must try to generate patterns over the query 
+		//attributes.
+		$patterns = array();
+		if (is_array($query)) {
+			//Generate a series of RegExp patterns as necessary.
+			$keys = array_keys($query);
+			$total = count($keys);
+			if ($total > 0) {
+				for ($i = 0; $i < $total; $i++) {
+					$key = $keys[$i];
+					$pattern = $query[$key];
+					if (is_string($pattern)) {
+						$patterns[$key] = patternToRegExp($pattern);
+					}
+				}
+				$files = matchFiles($query, $patterns, $ignoreCase, ".", $rootDir, $deep, $dirsOnly, $expand, $showHiddenFiles);
+			} else {
+				$files = getAllFiles(".",$rootDir,$deep,$dirsOnly,$expand,$showHiddenFiles);
+			}
+		}else{
+			$files = getAllFiles(".",$rootDir,$deep,$dirsOnly,$expand,$showHiddenFiles);
+		}
+
+		$total = count($files);
+
+		//Handle the sorting and paging.
+		$sortSpec = false;
+		if (array_key_exists("sort", $_GET)) {
+			$sortSpec = $_GET['sort'];
+			$sortSpec = str_replace("\\\"", "\"", $sortSpec);
+			$sortSpec = json_decode($sortSpec);
+		}
+
+		if ($sortSpec != null) {
+			$comparator = createComparator($sortSpec);
+			usort($files,array($comparator, "compare"));
+		}
+
+		//Page, if necessary.
+		if (array_key_exists("start", $_GET)) {
+			$start = $_GET['start'];
+			if (!is_numeric($start)) {
+				$start = 0;
+			}
+			$files = array_slice($files, $start);
+		}
+		if (array_key_exists("count", $_GET)) {
+			$count = $_GET['count'];
+			if (!is_numeric($count)) {
+				$count = $total;
+			}
+			$files = array_slice($files, 0, $count);
+		}
+
+		$result;
+		$result->total = $total;
+		$result->items = $files;
+		header("Content-Type", "text/json");
+		print("/* ".json_encode($result)." */");
+	} else {
+		//Query of a specific file (useful for fetchByIdentity and loadItem)
+
+		//Make sure the path isn't trying to walk out of the rooted directory
+		//As defined by $rootDir in the top of the php script.
+		$rootPath = realPath($rootDir);
+		$fullPath = realPath($rootPath."/".$path);
+
+		if ($fullPath !== false) {
+			if (strpos($fullPath,$rootPath) === 0) {
+				//Root the path into the tree cleaner.
+				if (strlen($fullPath) == strlen($rootPath)) {
+					$path = ".";
+				} else {
+					//Fix the path to relative of root and put back into UNIX style (even if windows).
+					$path = substr($fullPath,(strlen($rootPath) + 1),strlen($fullPath));
+					$path = str_replace("\\", "/", $path);
+				}
+
+				if (file_exists($fullPath)) {
+					$arr = split("/", $path);
+					$size = count($arr);
+
+					if ($size > 0) {
+						$fName = $arr[$size - 1];
+						if ($size == 1) {
+							print("Setting path to: .");
+							$path = ".";
+						} else {
+							$path = $arr[0];
+						}
+						for ($i = 1; $i < ($size - 1); $i++) {
+							$path = $path."/".$arr[$i];
+						}
+						$file = generateFileObj($fName, $path, $rootDir, $expand,$showHiddenFiles);
+						header("Content-Type", "text/json");
+						print("/* ".json_encode($file)." */");
+					} else {
+						header("HTTP/1.0 404 Not Found");
+						header("Status: 404 Not Found");
+						print("<b>Cannot access file: [".htmlentities($path)."]<b>");
+					}
+				} else {
+						header("HTTP/1.0 404 Not Found");
+						header("Status: 404 Not Found");
+						print("<b>Cannot access file: [".htmlentities($path)."]<b>");
+				}
+			} else {
+				header("HTTP/1.0 403 Forbidden");
+				header("Status: 403 Forbidden");
+				print("<b>Cannot access file: [".htmlentities($path)."].  It is outside of the root of the file service.<b>");
+			}
+		} else {
+				header("HTTP/1.0 404 Not Found");
+				header("Status: 404 Not Found");
+				print("<b>Cannot access file: [".htmlentities($path)."]<b>");
+		}
+	}
+?>
diff --git a/dojox/data/demos/stores/filestore_funcs.php b/dojox/data/demos/stores/filestore_funcs.php
new file mode 100755
index 0000000..ff61139
--- /dev/null
+++ b/dojox/data/demos/stores/filestore_funcs.php
@@ -0,0 +1,366 @@
+<?php
+	/**
+	 *  Helper function to convert a simple pattern to a regular expression for matching.
+	 * 
+	 *	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.
+	 *
+	 * @param 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.
+	 */
+	function patternToRegExp(/*String*/$pattern){
+		$rxp = "^";
+		$c = "";
+		$len = strlen($pattern);
+		for ($i = 0; $i < $len; $i++) {
+			$c = $pattern[$i];
+			switch ($c) {
+				case '\\':
+					$rxp = $rxp.$c;
+					$i++;
+					$rxp = $rxp.$pattern[$i];
+					break;
+				case '*':
+					$rxp = $rxp.".*"; break;
+				case '?':
+					$rxp = $rxp."."; break;
+				case '$':
+				case '^':
+				case '/':
+				case '+':
+				case '.':
+				case '|':
+				case '(':
+				case ')':
+				case '{':
+				case '}':
+				case '[':
+				case ']':
+					$rxp = $rxp."\\"; //fallthrough
+				default:
+					$rxp = $rxp.$c;
+			}
+		}
+		return "(".$rxp."$)";
+	}
+
+	/**
+	 * Function to load all file info from a particular directory.
+	 *
+	 * @param $dir The dir to seach from, relative to $rootDir.
+	 * @param $rootDir The directory where the file service is rooted, used as separate var to allow easier checking and prevention of ../ing out of the tree.
+	 * @param $recurse Whether or not to deep scan the dir and return all subfiles, or just return the toplevel files.
+	 * @param $dirsOnly boolean to enote to only return directory names, not filenames.
+	 * @param $expand boolean to indicate whether or not to inflate all children files along a path/file, or leave them as stubs.
+	 * @param $showHiddenFiles boolean to indicate to return hidden files as part of the list.
+	 */
+	function getAllfiles($dir, $rootDir, $recurse, $dirsOnly, $expand, $showHiddenFiles) { 
+		//  summary:
+		//      A function to obtain all the files in a particular directory (file or dir)
+		$files = array();
+		$dirHandle = opendir($rootDir."/".$dir);
+		if ($dirHandle) {
+			while($file = readdir($dirHandle)) {
+				if ($file) {
+					if ($file != ".." && $file != ".") {
+						$path = $dir."/".$file;
+						$fileObj = generateFileObj($file, $dir, $rootDir,$expand,$showHiddenFiles);
+						if (is_dir($rootDir."/".$path)) {
+							if ($recurse) {
+								if ($showHiddenFiles || $fileObj["name"][0] != '.') {
+									$subfiles = getAllfiles($path,$rootDir,$recurse,$dirsOnly,$expand,$showHiddenFiles);
+									$length = count($subfiles);
+									for ($i = 0; $i < $length; $i++) {
+										$files[] = $subfiles[$i];
+									}
+								}
+							}
+						}
+						if (!$dirsOnly || $fileObj["directory"]) {
+							if ($showHiddenFiles || $fileObj["name"][0] !== '.') {
+								$files[] = $fileObj;
+							}
+						}
+					}
+				}
+			}
+		}
+		closedir($dirHandle);
+		return $files;
+	}
+
+	/** 
+	 * Function to generate an associative map of data about a specific file.
+	 * @param $file The name of the file this object represents.
+	 * @param $dir The sub-path that contains the file defined by $file
+	 * @param $rootDir The directory from which to append dir and name to get the full path to the file.
+	 * @param $expand boolean to denote that if the file is a directory, expand all children in the children attribute 
+	 *        to a a full object
+	 * @param $showHiddenFiles boolean to denote if hidden files should be shown in-view or not.
+	 *
+	 * @return Associative Map.   The details about the file:
+	 *  $file["name"] - Returns the shortname of the file.
+	 *  $file["parentDir"] - Returns the relative path from the service root for the parent directory containing file $file["name"]
+	 *  $file["path"] - The relative path to the file.
+	 *  $file["directory"] - Boolean indicator if the file represents a directory.
+	 *  $file["size"] - The size of the file, in bytes.
+	 *  $file["modified] - The modified date of the file in milliseconds since Jan 1st, 1970.
+	 *  $file["children"] - Children files of a directory.  Empty if a standard file.
+	 */
+	function generateFileObj($file, $dir, $rootDir, $expand, $showHiddenFiles) {
+		//  summary:
+		//      Function to generate an object representation of a disk file.
+		$path = $file;
+		if ($dir != "." && $dir != "./") {
+			$path = $dir."/".$file;
+		}
+
+		$fullPath = $rootDir."/".$path;
+
+		$atts = stat($fullPath);
+
+		$rootPath = realPath($rootDir);                                       
+		$resolvedDir = realPath($rootDir."/".$dir);
+		$resolvedFullPath = realPath($fullPath);
+
+		//Try to normalize down the paths so it does a consistent return.
+		if (strcmp($rootPath, $resolvedDir) === 0) {
+			$dir = ".";
+		} else {
+			$dir = substr($resolvedDir, (strlen($rootPath) + 1), strlen($resolvedDir));
+			$dir = "./".str_replace("\\","/",$dir);
+		}
+		if (strcmp($rootPath, $resolvedFullPath) === 0) {
+			$path = ".";
+		} else {
+			$path = substr($resolvedFullPath, (strlen($rootPath) + 1), strlen($resolvedFullPath));
+			$path = "./".str_replace("\\","/",$path);
+		}
+
+		$fObj = array();
+		$fObj["name"] = $file;
+		$fObj["parentDir"] = $dir;
+		$fObj["path"] = $path;
+		$fObj["directory"] = is_dir($fullPath);
+		$fObj["size"] = filesize($fullPath);
+		$fObj["modified"] = $atts[9];
+
+		if (is_dir($fullPath)) {
+			$children = array();
+			$dirHandle = opendir($fullPath);
+			while($cFile = readdir($dirHandle)) {
+				if ($cFile) {
+					if ($cFile != ".." && $cFile != ".") {
+						if ($showHiddenFiles || $cFile[0] != '.') {
+							if (!$expand) {
+								$children[] = $cFile;
+							}else{
+								$children[] = generateFileObj($cFile, $path, $rootDir, $expand, $showHiddenFiles);
+							}
+						}
+					}
+				}
+			}
+			closedir($dirHandle);
+			$fObj["children"] = $children;
+		}
+		return $fObj;
+	}
+
+	/**
+	 * A field comparator class, whose role it is to define which fields on an associaive map to compare on
+	 * and provide the comparison function to do so.
+	 */
+	class FieldComparator {
+		var $field;
+		var $descending = false;
+
+		/**
+		 * Constructor.
+		 * @param $f The field of the item to compare.
+		 * @param $d Parameter denoting whether it should be ascending or descending.  Default is ascending.
+		 */
+		function FieldComparator($f, $d) {
+			$this->field = $f;
+			$this->descending = $d;
+		}
+
+		/**
+		 * Function to compare file objects A and B on the field defined by $this->field.
+		 * @param $fileA The first file to compare.
+		 * @param #fileB The second file to compare.
+		 */
+		function compare($fileA,$fileB){
+			$f = $this->field;
+			$a = $fileA[$f];
+			$b = $fileB[$f];
+
+			$ret = 0;
+			if (is_string($a) && is_string($b)) {
+				$ret = strcmp($a,$b);
+			} else if($a > $b || $a === null){
+				$ret = 1;
+			}else if($a < $b || $b === null){
+				$ret = -1;
+			}
+
+			if (property_exists($this, "descending") && $this->descending == true) {
+				$ret = $ret * -1;
+			}
+
+			if ($ret > 0) {
+				$ret = 1;
+			} else if ($ret < 0) {
+				$ret = -1;
+			}
+			return $ret; //int, {-1,0,1}
+		}
+	}
+
+	/**
+	 * A compound comparator class, whose role it is to sequentially call a set of comparators on two objects and 
+	 * return the combined result of the comparison.
+	 */
+	class CompoundComparator {
+		//Comparator chain.
+		var $comparators = array();
+
+		/**
+		 * Function to compare two objects $a and $b, using the chain of comparators.
+		 * @param $a The first object to compare.  
+		 * @param $b The second object to compare.
+		 * @returns -1, 0, 1.  -1 if a < b, 1 if a > b, and 0 if a = b.
+		 */
+		function compare($a, $b) {
+			$ret = 0;
+			$size = count($this->comparators);
+			for ($i = 0; $i < $size; $i++) {
+				$comp = $this->comparators[$i];
+				$ret = $comp->compare($a, $b);
+				if ($ret != 0) {
+					break;
+				}
+			}
+			return $ret;
+		}
+
+		/**
+		 * Function to add a comparator to the chain.
+		 * @param $comp The comparator to add.
+		 */
+		function addComparator($comp){
+			$this->comparators[] = $comp;
+		}
+	}
+
+	/**
+	 * A function to create a Comparator class with chained comparators based off the sort specification passed into the store.
+	 * @param $sortSpec The Sort specification, which is an array of sort objects containing ( attribute: "someStr": descending: true|fase}
+	 * @returns The constructed comparator.
+	 */
+	function createComparator($sortSpec) {
+		//Function to construct the class that handles chained comparisons.
+		$comparator = new CompoundComparator();
+		$size = count($sortSpec);
+		for ($i = 0; $i < $size; $i++) {
+			$sort = $sortSpec[$i];
+			$desc = false;
+			if(property_exists($sort, "descending")){
+				$desc = $sort->descending;
+			}
+			$fileComp = new FieldComparator($sort->attribute,$desc);
+			$comparator->addComparator($fileComp);
+		}
+		return $comparator;
+	}
+
+	/**
+	 * Function to match a set of queries against a directory and possibly all subfiles.
+	 * @param query The Query send in to process and test against.
+	 * @param patterns The set of regexp patterns generated off the query.
+	 * @param dir the directory to search in.
+	 * @param recurse Whether or not to recurse into subdirs and test files there too.
+	 *
+	 * @return Array.  Returns an array of all matches of the query.
+	 */
+	function matchFiles($query, $patterns, $ignoreCase, $dir, $rootDir, $recurse, $dirsOnly, $expand, $showHiddenFiles) {
+		$files = array();
+		$fullDir = $rootDir."/".$dir;
+
+		if ($fullDir != null && is_dir($fullDir)) {
+
+			$dirHandle = opendir($fullDir);
+			while ($file = readdir($dirHandle)) {
+				if ($file != "." && $file != "..") {
+					$item = generateFileObj($file, $dir, $rootDir, $expand,$showHiddenFiles);
+					$keys = array_keys($patterns);
+					$total = count($keys);
+					for ($i = 0; $i < $total; $i++) {
+						$key = $keys[$i];
+						$pattern = $query[$key];
+						$matched = containsValue($item,$key,$query[$key],$patterns[$key], $ignoreCase);
+						if (!$matched) {
+							break;
+						}
+					}
+					if ($matched) {
+						if (!$dirsOnly || $item["directory"]) {
+							if ($showHiddenFiles || $item["name"][0] != '.') {
+								$files[] = $item;
+							}
+						}
+					}
+
+					if (is_dir($rootDir."/".$item["path"]) && $recurse) {
+						if ($showHiddenFiles || $item["name"][0] != '.') {
+							$files = array_merge($files, matchFiles($query, $patterns, $ignoreCase, $item["path"], $rootDir, $recurse, $dirsOnly, $expand, $showHiddenFiles));
+						}
+					}
+				}
+			}
+			closedir($dirHandle);
+		}
+		return $files;
+	}
+
+	/**
+	 * Function to handle comparing the value of an attribute on a file item.
+	 * @param item  The item to examine.
+	 * @param attr The attribute of the tem to examine.
+	 * @parma value The value to compare it to.
+	 * @param rExp A regular Expression pattern object generated off 'value' if any.
+	 * 
+	 * @returns boolean denoting if the value was matched or not.
+	 */
+	function containsValue($item, $attr, $value, $rExp, $ignoreCase) {
+		$matched = false;
+		$possibleValue = $item[$attr];
+		if ($possibleValue === null && $value === null) {
+			$matched = true;
+		} else {
+			if ($rExp != null && is_string($possibleValue)) {
+				if ($ignoreCase) {
+					$matched = eregi($rExp, $possibleValue);
+				} else {
+					$matched = ereg($rExp, $possibleValue);
+				}
+
+			} else {
+				if ($value != null && $possibleValue != null) {
+					$matched = ($value == $possibleValue);
+				}
+			}
+		}              
+		return $matched;
+	}
+// No closing PHP tag on purpose.  Do not want it to print whitepace and thus not allow setting headers later.
diff --git a/dojox/data/demos/widgets/FileView.js b/dojox/data/demos/widgets/FileView.js
new file mode 100755
index 0000000..a73cb4c
--- /dev/null
+++ b/dojox/data/demos/widgets/FileView.js
@@ -0,0 +1,40 @@
+dojo.provide("dojox.data.demos.widgets.FileView");
+dojo.require("dijit._Templated");
+dojo.require("dijit._Widget");
+
+dojo.declare("dojox.data.demos.widgets.FileView", [dijit._Widget, dijit._Templated], {
+	//Simple demo widget for representing a view of a Flickr Item.
+
+	templateString: dojo.cache("dojox", "data/demos/widgets/templates/FileView.html"),
+
+	//Attach points for reference.
+	titleNode: null, 
+	descriptionNode: null,
+	imageNode: null,
+	authorNode: null,
+
+	name: "",
+	path: "",
+	size: 0,
+	directory: false,
+	parentDir: "",
+	children: [],
+
+	postCreate: function(){
+		this.nameNode.appendChild(document.createTextNode(this.name));
+		this.pathNode.appendChild(document.createTextNode(this.path));
+		this.sizeNode.appendChild(document.createTextNode(this.size));
+		this.directoryNode.appendChild(document.createTextNode(this.directory));
+		this.parentDirNode.appendChild(document.createTextNode(this.parentDir));
+		if (this.children && this.children.length > 0) {
+			var i;
+			for (i = 0; i < this.children.length; i++) {
+				var tNode = document.createTextNode(this.children[i]);
+				this.childrenNode.appendChild(tNode);
+				if (i < (this.children.length - 1)) {
+					this.childrenNode.appendChild(document.createElement("br"));
+				}
+			}
+		}
+	}
+});
diff --git a/dojox/data/demos/widgets/FlickrViewList.js b/dojox/data/demos/widgets/FlickrViewList.js
new file mode 100644
index 0000000..0798235
--- /dev/null
+++ b/dojox/data/demos/widgets/FlickrViewList.js
@@ -0,0 +1,30 @@
+dojo.provide("dojox.data.demos.widgets.FlickrViewList");
+dojo.require("dojox.dtl._Templated");
+dojo.require("dijit._Widget");
+
+dojo.declare("dojox.data.demos.widgets.FlickrViewList", 
+	[ dijit._Widget, dojox.dtl._Templated ],
+	{
+		store: null,
+		items: null,
+
+		templateString: dojo.cache("dojox", "data/demos/widgets/templates/FlickrViewList.html"),
+	
+		fetch: function(request){
+			request.onComplete = dojo.hitch(this, "onComplete");
+			request.onError = dojo.hitch(this, "onError");
+			return this.store.fetch(request);
+		},
+
+		onError: function(){
+			console.trace();
+			this.items = [];
+			this.render();
+		},
+
+		onComplete: function(items, request){
+			this.items = items||[];
+			this.render();
+		}
+	}
+);
diff --git a/dojox/data/demos/widgets/PicasaView.js b/dojox/data/demos/widgets/PicasaView.js
new file mode 100644
index 0000000..039d7a1
--- /dev/null
+++ b/dojox/data/demos/widgets/PicasaView.js
@@ -0,0 +1,33 @@
+dojo.provide("dojox.data.demos.widgets.PicasaView");
+dojo.require("dijit._Templated");
+dojo.require("dijit._Widget");
+
+dojo.declare("dojox.data.demos.widgets.PicasaView", [dijit._Widget, dijit._Templated], {
+	//Simple demo widget for representing a view of a Picasa Item.
+
+	templateString: dojo.cache("dojox", "data/demos/widgets/templates/PicasaView.html"),
+
+	//Attach points for reference.
+	titleNode: null, 
+	descriptionNode: null,
+	imageNode: null,
+	authorNode: null,
+
+	title: "",
+	author: "",
+	imageUrl: "",
+	iconUrl: "",
+
+	postCreate: function(){
+		this.titleNode.appendChild(document.createTextNode(this.title));
+		this.authorNode.appendChild(document.createTextNode(this.author));
+		this.descriptionNode.appendChild(document.createTextNode(this.description));
+		var href = document.createElement("a");
+		href.setAttribute("href", this.imageUrl);
+		href.setAttribute("target", "_blank");
+        var imageTag = document.createElement("img");
+		imageTag.setAttribute("src", this.iconUrl);
+		href.appendChild(imageTag);
+		this.imageNode.appendChild(href);
+	}
+});
diff --git a/dojox/data/demos/widgets/PicasaViewList.js b/dojox/data/demos/widgets/PicasaViewList.js
new file mode 100644
index 0000000..67205a5
--- /dev/null
+++ b/dojox/data/demos/widgets/PicasaViewList.js
@@ -0,0 +1,33 @@
+dojo.provide("dojox.data.demos.widgets.PicasaViewList");
+dojo.require("dijit._Templated");
+dojo.require("dijit._Widget");
+dojo.require("dojox.data.demos.widgets.PicasaView");
+
+dojo.declare("dojox.data.demos.widgets.PicasaViewList", [dijit._Widget, dijit._Templated], {
+	//Simple demo widget that is just a list of PicasaView Widgets.
+
+	templateString: dojo.cache("dojox", "data/demos/widgets/templates/PicasaViewList.html"),
+
+	//Attach points for reference.
+	listNode: null,
+
+	postCreate: function(){
+		this.fViewWidgets = [];
+	},
+
+	clearList: function(){
+		while(this.list.firstChild){
+			this.list.removeChild(this.list.firstChild);
+		}
+		for(var i = 0; i < this.fViewWidgets.length; i++){
+			this.fViewWidgets[i].destroy();
+		}
+		this.fViewWidgets = [];
+	},
+
+	addView: function(viewData){
+		 var newView  = new dojox.data.demos.widgets.PicasaView(viewData);
+		 this.fViewWidgets.push(newView);
+		 this.list.appendChild(newView.domNode);
+	}
+});
diff --git a/dojox/data/demos/widgets/templates/FileView.html b/dojox/data/demos/widgets/templates/FileView.html
new file mode 100755
index 0000000..a83fd28
--- /dev/null
+++ b/dojox/data/demos/widgets/templates/FileView.html
@@ -0,0 +1,62 @@
+<div class="fileView">
+	<div class="fileViewTitle">File Details:</div>
+	<table class="fileViewTable">
+		<tbody>
+			<tr class="fileName">
+				<td>
+					<b>
+						Name:
+					</b>
+				</td>
+				<td dojoAttachPoint="nameNode">
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>
+						Path:
+					</b>
+				</td>
+				<td dojoAttachPoint="pathNode">
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>
+						Size:
+					</b>
+				</td>
+				<td>
+					<span dojoAttachPoint="sizeNode"></span> bytes.
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>
+						Is Directory:
+					</b>
+				</td>
+				<td dojoAttachPoint="directoryNode">
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>
+						Parent Directory:
+					</b>
+				</td>
+				<td dojoAttachPoint="parentDirNode">
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>
+						Children:
+					</b>
+				</td>
+				<td dojoAttachPoint="childrenNode">
+				</td>
+			</tr>
+		</tbody>
+	</table>
+</div>
diff --git a/dojox/data/demos/widgets/templates/FlickrViewList.html b/dojox/data/demos/widgets/templates/FlickrViewList.html
new file mode 100644
index 0000000..e9fe02f
--- /dev/null
+++ b/dojox/data/demos/widgets/templates/FlickrViewList.html
@@ -0,0 +1,20 @@
+{% load dojox.dtl.contrib.data %}
+{% bind_data items to store as flickr %}
+<div dojoAttachPoint="list">
+	{% for item in flickr %}
+	<div style="display: inline-block; align: top;">
+		<h5>{{ item.title }}</h5>
+		<a href="{{ item.link }}" style="border: none;">
+			<img src="{{ item.imageUrlMedium }}">
+		</a>
+		<p>{{ item.author }}</p>
+
+		<!--
+		<img src="{{ item.imageUrl }}">
+		<p>{{ item.imageUrl }}</p>
+		<img src="{{ item.imageUrlSmall }}">
+		-->
+	</div>
+	{% endfor %}
+</div>
+
diff --git a/dojox/data/demos/widgets/templates/PicasaView.html b/dojox/data/demos/widgets/templates/PicasaView.html
new file mode 100644
index 0000000..88dbb31
--- /dev/null
+++ b/dojox/data/demos/widgets/templates/PicasaView.html
@@ -0,0 +1,35 @@
+<table class="picasaView">
+	<tbody>
+		<tr class="picasaTitle">
+			<td>
+				<b>
+					Title:
+				</b>
+			</td>
+			<td dojoAttachPoint="titleNode">
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<b>
+					Author:
+				</b>
+			</td>
+			<td dojoAttachPoint="authorNode">
+			</td>
+		</tr>
+		<tr>
+			<td colspan="2">
+				<b>
+					Summary:
+				</b>
+				<span class="picasaSummary" dojoAttachPoint="descriptionNode"></span>
+			</td>
+		</tr>
+		<tr>
+			<td dojoAttachPoint="imageNode" colspan="2">
+			</td>
+		</tr>
+	</tbody>
+</table>
+
diff --git a/dojox/data/demos/widgets/templates/PicasaViewList.html b/dojox/data/demos/widgets/templates/PicasaViewList.html
new file mode 100644
index 0000000..3a9f565
--- /dev/null
+++ b/dojox/data/demos/widgets/templates/PicasaViewList.html
@@ -0,0 +1,2 @@
+<div dojoAttachPoint="list"></div>
+
diff --git a/dojox/data/dom.js b/dojox/data/dom.js
index 800a338..b320245 100644
--- a/dojox/data/dom.js
+++ b/dojox/data/dom.js
@@ -1,42 +1,95 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.dom"]){
-dojo._hasResource["dojox.data.dom"]=true;
 dojo.provide("dojox.data.dom");
 dojo.require("dojox.xml.parser");
-dojo.deprecated("dojox.data.dom","Use dojox.xml.parser instead.","2.0");
-dojox.data.dom.createDocument=function(_1,_2){
-dojo.deprecated("dojox.data.dom.createDocument()","Use dojox.xml.parser.parse() instead.","2.0");
-try{
-return dojox.xml.parser.parse(_1,_2);
-}
-catch(e){
-return null;
-}
+
+//DOM type to int value for reference.
+//Ints make for more compact code than full constant names.
+//ELEMENT_NODE                  = 1;
+//ATTRIBUTE_NODE                = 2;
+//TEXT_NODE                     = 3;
+//CDATA_SECTION_NODE            = 4;
+//ENTITY_REFERENCE_NODE         = 5;
+//ENTITY_NODE                   = 6;
+//PROCESSING_INSTRUCTION_NODE   = 7;
+//COMMENT_NODE                  = 8;
+//DOCUMENT_NODE                 = 9;
+//DOCUMENT_TYPE_NODE            = 10;
+//DOCUMENT_FRAGMENT_NODE        = 11;
+//NOTATION_NODE                 = 12;
+
+//This file contains internal/helper APIs as holders for people who used them.  They have been migrated to
+//a better project, dojox.xml and experimental has been removed there.  Please update usage to the new package.
+dojo.deprecated("dojox.data.dom", "Use dojox.xml.parser instead.", "2.0");
+
+dojox.data.dom.createDocument = function(/*string?*/ str, /*string?*/ mimetype){
+	//	summary:
+	//		cross-browser implementation of creating an XML document object.
+	//
+	//	str:
+	//		Optional text to create the document from.  If not provided, an empty XML document will be created.  
+	//		If str is empty string "", then a new empty document will be created.
+	//	mimetype:
+	//		Optional mimetype of the text.  Typically, this is text/xml.  Will be defaulted to text/xml if not provided.
+	dojo.deprecated("dojox.data.dom.createDocument()", "Use dojox.xml.parser.parse() instead.", "2.0");
+	try{
+		return dojox.xml.parser.parse(str,mimetype); //DOMDocument.
+	}catch(e){
+		/*Squeltch errors like the old parser did.*/
+		return null;
+	}
 };
-dojox.data.dom.textContent=function(_3,_4){
-dojo.deprecated("dojox.data.dom.textContent()","Use dojox.xml.parser.textContent() instead.","2.0");
-if(arguments.length>1){
-return dojox.xml.parser.textContent(_3,_4);
-}else{
-return dojox.xml.parser.textContent(_3);
-}
+
+dojox.data.dom.textContent = function(/*Node*/node, /*string?*/text){
+	//	summary:
+	//		Implementation of the DOM Level 3 attribute; scan node for text
+	//	description:
+	//		Implementation of the DOM Level 3 attribute; scan node for text
+	//		This function can also update the text of a node by replacing all child 
+	//		content of the node.
+	//	node:
+	//		The node to get the text off of or set the text on.
+	//	text:
+	//		Optional argument of the text to apply to the node.
+	dojo.deprecated("dojox.data.dom.textContent()", "Use dojox.xml.parser.textContent() instead.", "2.0");
+	if(arguments.length> 1){
+		return dojox.xml.parser.textContent(node, text); //string
+	}else{
+		return dojox.xml.parser.textContent(node); //string
+	}
 };
-dojox.data.dom.replaceChildren=function(_5,_6){
-dojo.deprecated("dojox.data.dom.replaceChildren()","Use dojox.xml.parser.replaceChildren() instead.","2.0");
-dojox.xml.parser.replaceChildren(_5,_6);
+
+dojox.data.dom.replaceChildren = function(/*Element*/node, /*Node || array*/ newChildren){
+	//	summary:
+	//		Removes all children of node and appends newChild. All the existing
+	//		children will be destroyed.
+	//	description:
+	//		Removes all children of node and appends newChild. All the existing
+	//		children will be destroyed.
+	// 	node:
+	//		The node to modify the children on
+	//	newChildren:
+	//		The children to add to the node.  It can either be a single Node or an
+	//		array of Nodes.
+	dojo.deprecated("dojox.data.dom.replaceChildren()", "Use dojox.xml.parser.replaceChildren() instead.", "2.0");
+	dojox.xml.parser.replaceChildren(node, newChildren);
 };
-dojox.data.dom.removeChildren=function(_7){
-dojo.deprecated("dojox.data.dom.removeChildren()","Use dojox.xml.parser.removeChildren() instead.","2.0");
-return dojox.xml.parser.removeChildren(_7);
+
+dojox.data.dom.removeChildren = function(/*Element*/node){
+	//	summary:
+	//		removes all children from node and returns the count of children removed.
+	//		The children nodes are not destroyed. Be sure to call dojo._destroyElement on them
+	//		after they are not used anymore.
+	//	node:
+	//		The node to remove all the children from.
+	dojo.deprecated("dojox.data.dom.removeChildren()", "Use dojox.xml.parser.removeChildren() instead.", "2.0");
+	return dojox.xml.parser.removeChildren(node); //int
 };
-dojox.data.dom.innerXML=function(_8){
-dojo.deprecated("dojox.data.dom.innerXML()","Use dojox.xml.parser.innerXML() instead.","2.0");
-return dojox.xml.parser.innerXML(_8);
+
+dojox.data.dom.innerXML = function(/*Node*/node){
+	//	summary:
+	//		Implementation of MS's innerXML function.
+	//	node:
+	//		The node from which to generate the XML text representation.
+	dojo.deprecated("dojox.data.dom.innerXML()", "Use dojox.xml.parser.innerXML() instead.", "2.0");
+	return dojox.xml.parser.innerXML(node); //string||null
 };
-}
+
diff --git a/dojox/data/restListener.js b/dojox/data/restListener.js
index bef6a50..02af85b 100644
--- a/dojox/data/restListener.js
+++ b/dojox/data/restListener.js
@@ -1,36 +1,48 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.restListener"]){
-dojo._hasResource["dojox.data.restListener"]=true;
 dojo.provide("dojox.data.restListener");
-dojox.data.restListener=function(_1){
-var _2=_1.channel;
-var jr=dojox.rpc.JsonRest;
-var _3=jr.getServiceAndId(_2).service;
-var _4=dojox.json.ref.resolveJson(_1.result,{defaultId:_1.event=="put"&&_2,index:dojox.rpc.Rest._index,idPrefix:_3.servicePath.replace(/[^\/]*$/,""),idAttribute:jr.getIdAttribute(_3),schemas:jr.schemas,loader:jr._loader,assignAbsoluteIds:true});
-var _5=dojox.rpc.Rest._index&&dojox.rpc.Rest._index[_2];
-var _6="on"+_1.event.toLowerCase();
-var _7=_3&&_3._store;
-if(_5){
-if(_5[_6]){
-_5[_6](_4);
-return;
-}
-}
-if(_7){
-switch(_6){
-case "onpost":
-_7.onNew(_4);
-break;
-case "ondelete":
-_7.onDelete(_5);
-break;
-}
-}
+
+dojox.data.restListener = function(message){
+	// summary:
+	// 		this function can be used to receive REST notifications, from Comet or from another frame
+	// description:
+	//		Example:
+	// |	dojo.connect(window,"onMessage",null,function(event) {
+	//	|		var data = dojo.fromJson(event.data);
+	// 	|		dojox.restListener(data);
+	//	|	});
+	var channel = message.channel;
+	var jr = dojox.rpc.JsonRest;
+	var service = jr.getServiceAndId(channel).service;
+	var result = dojox.json.ref.resolveJson(message.result, {
+					defaultId: message.event == 'put' && channel,
+					index: dojox.rpc.Rest._index,
+					idPrefix: service.servicePath.replace(/[^\/]*$/,''),
+					idAttribute: jr.getIdAttribute(service),
+					schemas: jr.schemas,
+					loader: jr._loader,
+					assignAbsoluteIds: true
+				});
+	var target = dojox.rpc.Rest._index && dojox.rpc.Rest._index[channel];
+	var onEvent = 'on' + message.event.toLowerCase();
+	var store = service && service._store;
+	if(target){
+		if(target[onEvent]){
+			target[onEvent](result); // call the REST handler if available
+			return;
+		}
+	}
+	// this is how we respond to different events
+	if(store){
+		switch(onEvent){
+			case 'onpost':
+				store.onNew(result); // call onNew for the store;
+				break;
+			case 'ondelete':
+		 		store.onDelete(target);
+		 		break;
+				 	// put is handled by JsonReferencing
+				 	//TODO: we may want to bring the JsonReferencing capability into here...
+				 	// that is really tricky though because JsonReferencing handles sub object,
+				 	// it would be expensive to do full object graph searches from here
+		}
+	}
 };
-}
diff --git a/dojox/data/s3/proxy.example-php b/dojox/data/s3/proxy.example-php
index f33a639..e5b57e1 100644
--- a/dojox/data/s3/proxy.example-php
+++ b/dojox/data/s3/proxy.example-php
@@ -1,74 +1,74 @@
-<?php
-// enter your Amazon S3 secret key and access key here:
-$accessKey = "access key";
-$secretAccessKey = "secret access key";
-
-
-
-$TARGET_WS = "http://s3.amazonaws.com";
-
-ob_start();
-
-require_once 'Crypt/HMAC.php';
-require_once 'HTTP/Request.php';
-
-$method = $_SERVER["REQUEST_METHOD"];
-if ($method == "PUT") {
-	$contentType = $_SERVER['CONTENT_TYPE'];
-}
-else {
-	$contentType ='';
-}
-$resource = str_replace($TARGET_WS, '', $_REQUEST['url']);
-$queryIndex = strpos($resource,'?'); // remove the query string
-if ($queryIndex) {
-	$resource = substr($resource,0,$queryIndex);
-}
-
-if (substr($resource,strlen($resource)-1,strlen($resource)) == '/') {
-	// remove the last slash
-	$resource = substr($resource,0,strlen($resource)-1);
-}
-$content = file_get_contents('php://input');
-
-$httpDate = gmdate("D, d M Y H:i:s T");
-$acl = "private";
-$stringToSign = "$method\n\n$contentType\n$httpDate\nx-amz-acl:$acl\n$resource";
-$hashObj =& new Crypt_HMAC($secretAccessKey, "sha1");
-$signature = hexTob64($hashObj->hash($stringToSign));
-
-$req =& new HTTP_Request($TARGET_WS . $resource);
-$req->setMethod($method);
-$req->addHeader("content-type", $contentType);
-$req->addHeader("Date", $httpDate);
-$req->addHeader("x-amz-acl", $acl);
-$req->addHeader("Authorization", "AWS " . $accessKey . ":" . $signature);
-if ($content != "") {
-	$req->setBody($content);
-}
-
-$req->sendRequest();
-
-$contentType = $req->getResponseHeader("content-type");
-header("content-type: $contentType");
-header('HTTP/1.1 ' . $req->getResponseCode() . ' Ok');
-
-ob_end_flush();
-
-$content = $req->getResponseBody();
-if ($content) {
-	print($content);
-}
-else {
-	print("\"success\"");
-}
-
-function hexTob64($str) {
-    $raw = '';
-    for ($i=0; $i < strlen($str); $i+=2) {
-        $raw .= chr(hexdec(substr($str, $i, 2)));
-    }
-    return base64_encode($raw);
-}
-
+<?php
+// enter your Amazon S3 secret key and access key here:
+$accessKey = "access key";
+$secretAccessKey = "secret access key";
+
+
+
+$TARGET_WS = "http://s3.amazonaws.com";
+
+ob_start();
+
+require_once 'Crypt/HMAC.php';
+require_once 'HTTP/Request.php';
+
+$method = $_SERVER["REQUEST_METHOD"];
+if ($method == "PUT") {
+	$contentType = $_SERVER['CONTENT_TYPE'];
+}
+else {
+	$contentType ='';
+}
+$resource = str_replace($TARGET_WS, '', $_REQUEST['url']);
+$queryIndex = strpos($resource,'?'); // remove the query string
+if ($queryIndex) {
+	$resource = substr($resource,0,$queryIndex);
+}
+
+if (substr($resource,strlen($resource)-1,strlen($resource)) == '/') {
+	// remove the last slash
+	$resource = substr($resource,0,strlen($resource)-1);
+}
+$content = file_get_contents('php://input');
+
+$httpDate = gmdate("D, d M Y H:i:s T");
+$acl = "private";
+$stringToSign = "$method\n\n$contentType\n$httpDate\nx-amz-acl:$acl\n$resource";
+$hashObj =& new Crypt_HMAC($secretAccessKey, "sha1");
+$signature = hexTob64($hashObj->hash($stringToSign));
+
+$req =& new HTTP_Request($TARGET_WS . $resource);
+$req->setMethod($method);
+$req->addHeader("content-type", $contentType);
+$req->addHeader("Date", $httpDate);
+$req->addHeader("x-amz-acl", $acl);
+$req->addHeader("Authorization", "AWS " . $accessKey . ":" . $signature);
+if ($content != "") {
+	$req->setBody($content);
+}
+
+$req->sendRequest();
+
+$contentType = $req->getResponseHeader("content-type");
+header("content-type: $contentType");
+header('HTTP/1.1 ' . $req->getResponseCode() . ' Ok');
+
+ob_end_flush();
+
+$content = $req->getResponseBody();
+if ($content) {
+	print($content);
+}
+else {
+	print("\"success\"");
+}
+
+function hexTob64($str) {
+    $raw = '';
+    for ($i=0; $i < strlen($str); $i+=2) {
+        $raw .= chr(hexdec(substr($str, $i, 2)));
+    }
+    return base64_encode($raw);
+}
+
 ?>
\ No newline at end of file
diff --git a/dojox/data/tests/ClientFilter.js b/dojox/data/tests/ClientFilter.js
new file mode 100644
index 0000000..fa6261e
--- /dev/null
+++ b/dojox/data/tests/ClientFilter.js
@@ -0,0 +1,150 @@
+dojo.provide("dojox.data.tests.ClientFilter");
+dojo.require("dojox.data.ClientFilter");
+dojo.require("dojox.data.JsonRestStore");
+
+
+mockService = function(query){
+	var dfd = new dojo.Deferred();
+	setTimeout(function(){
+		dfd.callback([{firstName:"John",lastName:"Smith",__id:"mock/1"},
+				{firstName:"Jim",lastName:"Smith",__id:"mock/2"},
+				{firstName:"Jill",lastName:"Smith",__id:"mock/3"},
+				{firstName:"Jerry",lastName:"Smith",__id:"mock/4"}]);
+	},10);
+	return dfd;
+};
+mockService.servicePath = "mock/";
+jsonStore = new dojox.data.JsonRestStore({service:mockService});
+
+doh.register("dojox.data.tests.ClientFilter", 
+	[
+		function updateWhileLoading(t) {
+			var d = new doh.Deferred();
+			jsonStore.fetch({query:{lastName:"Smith",firstName:"*"},sort:[{attribute:"firstName",descending:true}], 
+				onComplete: function(items, request){
+					t.is(5, items.length); // make sure it was added
+					t.is(newJack,items[4]); // make sure it is in the right location
+					console.log("updateWhileLoading",items[4],newJack);
+					d.callback(true);					
+				}
+			});
+			newJack = jsonStore.newItem({firstName:"Jack",lastName:"Smith"}); // this should fire while we are waiting for the fetch response
+			return d;
+		},
+		function makeChanges(t) {
+			//	summary: 
+			//		Simple test of a basic fetch on JsonRestStore of a simple query.
+			var d = new doh.Deferred();
+			jsonStore.fetch({queryOptions:{cache:true},query:{lastName:"Smith",firstName:"*"},sort:[{attribute:"firstName",descending:true}], 
+				onComplete: function(items, request){
+					t.is(5, items.length); // make sure it was added
+					t.is(newJack,items[4]); // make sure it is in the right location
+					console.log("items[4]",items[4]);
+					var newJoe = jsonStore.newItem({firstName:"Joe",lastName:"Smith"});
+					t.is(5, items.length); // make sure it was not added yet
+					jsonStore.updateResultSet(items, request);
+					t.is(6, items.length); // make sure it was added
+					t.is(newJoe,items[1]); // make sure it is in the right location
+					var jackJones = jsonStore.newItem({firstName:"Jack",lastName:"Jones"});
+					jsonStore.updateResultSet(items, request);
+					t.is(6, items.length); // make sure it is not added
+					jsonStore.setValue(newJoe,"firstName","Jesse");
+					jsonStore.updateResultSet(items, request);
+					t.is(6, items.length); // make sure it is the same
+					t.is(newJoe,items[3]); // make sure it is in the new right location
+					t.f(newJoe==items[1]); // make sure it is not in the old location
+					jsonStore.deleteItem(newJack);
+					jsonStore.updateResultSet(items, request);
+					t.is(5, items.length); // make sure it is has been removed
+					jsonStore.setValue(newJoe,"lastName","Baker");
+					jsonStore.updateResultSet(items, request);
+					t.is(4, items.length); // make sure it is has been removed
+					jsonStore.setValue(jackJones,"lastName","Smith");
+					jsonStore.updateResultSet(items, request);
+					t.is(5, items.length); // make sure it is has been added
+				}
+			});
+			console.log("sent first");
+			var finished;
+			jsonStore.fetch({query:{lastName:"Smith",firstName:"Jack"},sort:[{attribute:"firstName",descending:true}], 
+				onComplete: function(items, request){
+					console.log("items first",items);
+					finished = true;
+					t.is(1, items.length); // make sure we get the correct number of items
+					d.callback(true);
+				}
+			});
+			console.log("sent seconds");
+			t.f(finished); // this should finish synchronously, because we should have it in the cache
+			return d; //Object
+		},
+		function cachedResults(t) {
+			var d = new doh.Deferred();
+			var finished;
+			jsonStore.fetch({query:{lastName:"Smith",firstName:"Jack"},sort:[{attribute:"firstName",descending:true}], 
+				onComplete: function(items, request){
+					console.log("items",items);
+					finished = true;
+					t.is(1, items.length); // make sure we get the correct number of items
+					d.callback(true);
+				}
+			});
+			t.t(finished); // this should finish synchronously, because we should have it in the cache
+			return d;
+		},
+		function repeatedQueries(t) {
+			var d = new doh.Deferred();
+			var finished;
+			jsonStore.fetch({queryOptions:{cache:true},query:{}, 
+				onComplete: function(items, request){
+					console.log("items",items);
+					t.is(6, items.length); // make sure we get the correct number of items
+					jsonStore.newItem({firstName:"Jack",lastName:"Jones"});
+					jsonStore.fetch({query:{}, 
+						onComplete: function(items, request){
+							t.is(7, items.length); // make sure we get the correct number of items
+						}
+					});
+					jsonStore.serverVersion = jsonStore._updates.length;
+					jsonStore.newItem({firstName:"Jack",lastName:"Jones"});
+					jsonStore.fetch({query:{}, 
+						onComplete: function(items, request){
+							finished = true;
+							t.is(8, items.length); // make sure we get the correct number of items
+							d.callback(true);
+						}
+					});
+				}
+			});
+			return d;
+		},
+		
+		function sorting(t) {
+			var d = new doh.Deferred();
+			var finished;
+			// test sorting. Descending order should be John,Jim,Jill,Jerry,Jack
+			jsonStore.fetch({query:{lastName:"Smith",firstName:"*"},sort:[{attribute:"firstName",descending:true}], 
+				onComplete: function(items, request){
+					var last = jsonStore.getValue(items[0], "firstName");
+					console.log("last name: ",last, items[0]);
+
+					t.is("John", last); // make sure we get the correct number of items
+
+					jsonStore.fetch({query:{lastName:"Smith",firstName:"*"},sort:[{attribute:"firstName"}], 
+						onComplete: function(items, request){
+							var first = jsonStore.getValue(items[0], "firstName");
+							console.log("first name",first, items[0]);
+							finished = true;
+							t.is("Jack", first); // make sure we get the correct number of items
+
+							d.callback(true);
+						}
+					});
+				}
+			});
+			t.t(finished); // this should finish synchronously, because we should have it in the cache
+			return d;
+		}
+		
+	]
+);
diff --git a/dojox/data/tests/QueryReadStore.html b/dojox/data/tests/QueryReadStore.html
new file mode 100644
index 0000000..2a70bff
--- /dev/null
+++ b/dojox/data/tests/QueryReadStore.html
@@ -0,0 +1,221 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/tundra/tundra_rtl.css";
+	</style>
+
+	<title>Query read store</title>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../../../dojo/data/util/simpleFetch.js"></script>
+	<script type="text/javascript" src="../../../dojox/data/QueryReadStore.js"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dojox.data.QueryReadStore");
+
+		dojo.provide("ComboBoxReadStore");
+		dojo.declare("ComboBoxReadStore", dojox.data.QueryReadStore, {
+			fetch:function(request) {
+				// Copy the GET/POST parameters (request.query) we need into
+				// request.serverQuery. We actually want to have
+				// the query added to the URL like so:  /url.php?q=<searchString>
+				// The data in "queryOptions" are useless for our backend,
+				// we ignore them, they are not sent to the server.
+				// The combobox puts this into the request-parameter:
+				//      {
+				//          query: {name:<searchString>},
+				//          queryOptions: {ignoreCase:true, deep:true},
+				//          ...
+				//      }
+				// We generate request.serverQuery to be this, since those values will
+				// be sent to the server.
+				//      {
+				//          q:<searchString>}
+				//      }
+				// This results in a xhr request to the following URL (in case of GET):
+				//      /url.php?q=<searchString>
+				//
+
+				request.serverQuery = {q:request.query.name};
+				// If we wanted to send the queryOptions too, we could simply do:
+				//  request.serverQuery = {
+				//          q:request.query.name,
+				//          ignoreCase:request.queryOptions.ignoreCase,
+				//          deep:request.queryOptions.deep
+				//      };
+				// This would then result in this URL, for ignoreCase and deep
+				// assumed to be true:
+				//      /url.php?q=<searchString>&ignoreCase=true&deep=true
+				return this.inherited("fetch", arguments);
+			}
+		});
+
+		dojo.provide("ServerPagingReadStore");
+		dojo.declare("ServerPagingReadStore", dojox.data.QueryReadStore, {
+			fetch:function(request) {
+				request.serverQuery = {q:request.query.name, start:request.start, count:request.count};
+				return this.inherited("fetch", arguments);
+			}
+		});
+
+		var testStore = new dojox.data.QueryReadStore({url:'stores/QueryReadStore.php'});;
+		function doSearch() {
+			var queryOptions = {};
+			if (dojo.byId("ignoreCaseEnabled").checked) {
+				queryOptions.ignoreCase = dojo.query("#fetchForm")[0].ignoreCase[0].checked;
+			}
+			if (dojo.byId("deepEnabled").checked) {
+				queryOptions.deep = dojo.query("#fetchForm")[0].deep[0].checked;
+			}
+		    
+			var query = {};
+			query.q = dojo.byId("searchText").value;
+			var request = {query:query, queryOptions:queryOptions};
+			request.start = parseInt(dojo.query("#fetchForm")[0].pagingStart.value);
+			request.count = parseInt(dojo.query("#fetchForm")[0].pagingCount.value);
+
+			var requestMethod = "get";
+			var radioButtons = dojo.query("#fetchForm")[0].requestMethod;
+			for (var i=0; i<radioButtons.length; i++){
+				if (radioButtons[i].checked) {
+					requestMethod = radioButtons[i].value;
+				}
+			}
+			
+			testStore.requestMethod = requestMethod;
+			testStore.doClientPaging = dojo.query("#fetchForm")[0].doClientPaging.checked;
+			
+			if (!testStore.doClientPaging) {
+				// We have to fill the serverQuery, since we also want to send the
+				// paging data "start" and "count" along with what is in query.
+				request.serverQuery = {q:request.query.q, start:request.start, count:request.count};
+			}
+			
+			request.onComplete = function (items) {
+				var s = "number of items: "+items.length+"<br /><br />";
+				for (var i=0; i<items.length; i++) {
+					s += i+": name: '"+testStore.getValue(items[i], "name")+"'<br />";
+				}
+				//s += "<pre>"+dojo.toJson(items)+"</pre>";
+				dojo.byId("fetchOutput").innerHTML = s;
+			};
+
+			console.log(dojo.toJson(request));
+			testStore.fetch(request);
+		}
+	</script>
+
+	<style>
+	     fieldset {
+	         border:1px solid black;
+	         display:inline;
+	         padding:10px;
+	     }
+	     div.disabled {
+	         opacity:0.1;
+	     }
+	</style>
+</head>
+<body class="tundra" style="margin:20px;">
+	<div dojoType="ComboBoxReadStore" jsId="store" url="stores/QueryReadStore.php" requestMethod="get"></div>
+	This is a ComboBox: <input id="cb" dojoType="dijit.form.ComboBox" store="store" pageSize="5" />
+	<br /><br /><hr />
+
+	This is a FilteringSelect: <input id="fs" dojoType="dijit.form.FilteringSelect" store="store" pageSize="5" />
+	<br />
+	<form id="filteringSelectForm">
+		<input id="selectById" value="0" size="3" />
+		<input type="button" value="set by id" onclick="dijit.byId('fs').setValue(dojo.byId('selectById').value)" />
+	</form>
+	
+	<br /><br /><hr />
+
+	This ComboBox uses a customized QueryReadStore, it prepares the query-string for the URL that
+	way that the paging parameters "start" and "count" are also send.<br />
+	<div dojoType="ServerPagingReadStore" jsId="serverPagingStore" url="stores/QueryReadStore.php" requestMethod="get"></div>
+	<input dojoType="dijit.form.ComboBox" store="serverPagingStore" pageSize="5" />
+	<br />
+	<a href="javascript://" onclick="var d = dojo.byId('pagingCode'); d.style.display= d.style.display=='none'?'block':'none';">Click here to  see the code!</a>
+<div id="pagingCode" style="display:none;">
+	The HTML might look like this.
+	<pre>
+<div dojoType="ServerPagingReadStore" jsId="serverPagingStore" url="stores/QueryReadStore.php" requestMethod="get"></div>
+<input dojoType="dijit.form.ComboBox" store="serverPagingStore" pageSize="10" />
+	</pre>
+	<pre>
+		dojo.require("dojox.data.QueryReadStore");
+		dojo.provide("ServerPagingReadStore");
+		dojo.declare("ServerPagingReadStore", dojox.data.QueryReadStore, {
+			fetch:function(request) {
+				request.serverQuery = {q:request.query.name, start:request.start, count:request.count};
+				return this.inherited("fetch", arguments);
+			}
+		});
+	</pre>
+</div>
+	<br /><br />
+	
+	<hr />
+	
+	<form id="fetchForm">
+		<fieldset title="requestMethod">
+		    <legend>requestMethod</legend>
+			get <input type="radio" value="get" checked="checked" name="requestMethod" />
+			post <input type="radio" value="post" name="requestMethod" />
+		</fieldset>
+		
+		<fieldset title="queryOptions">
+			<legend>queryOptions</legend>
+
+			<fieldset id="ignoreCaseFieldset">
+				<legend><input type="checkbox" id="ignoreCaseEnabled" /> ignoreCase</legend>
+				<div class="disabled">
+					true <input type="radio" value="0" checked="checked" name="ignoreCase" />
+					false <input type="radio" value="1" name="ignoreCase" />
+				</div>
+			</fieldset>
+			<fieldset id="deepFieldset">
+				<legend><input type="checkbox" id="deepEnabled" /> deep</legend>
+				<div class="disabled">
+					true <input type="radio" value="0" name="deep" />
+					false <input type="radio" value="1" name="deep" checked="checked" />
+				</div>
+			</fieldset>
+		</fieldset>
+		<fieldset title="paging">
+			<legend>paging</legend>
+			start: <input id="pagingStart" value="0" size="3" />
+			count: <input id="pagingCount" value="10" size="3"  />
+			<br /><br />
+			do client paging: <input id="doClientPaging" type="checkbox" checked="checked" />
+		</fieldset>
+		<script>
+		    var fieldsets = ["ignoreCaseFieldset", "deepFieldset"];
+		    for (var i=0; i<fieldsets.length; i++) {
+		        dojo.connect(dojo.byId(fieldsets[i]), "onchange", toggleFieldset);
+		    }
+		    function toggleFieldset(el) {
+		        var divs = dojo.query("div", el.target.parentNode.parentNode);
+		        if (divs.length) {
+					var div = divs[0];
+					if (el.target.checked) {
+						dojo.removeClass(div, "disabled");
+					} else {
+						dojo.addClass(div, "disabled");
+					}
+				}
+		    }
+		</script>
+		
+		<br /><br />
+		<input id="searchText" type="text" value="a">
+		<input id="searchButton" type="button" value="store.fetch()" onclick="doSearch()" />
+	</form>
+	<div id="fetchOutput" style="background-color:#FFDDDD; margin-top:1em; float:left;"></div>
+</body>
+</html>
diff --git a/dojox/data/tests/dom.js b/dojox/data/tests/dom.js
new file mode 100644
index 0000000..3d8759c
--- /dev/null
+++ b/dojox/data/tests/dom.js
@@ -0,0 +1,147 @@
+dojo.provide("dojox.data.tests.dom");
+dojo.require("dojox.data.dom");
+
+tests.register("dojox.data.tests.dom", 
+	[
+		function testCreateDocument(t){
+			var document = dojox.data.dom.createDocument();
+			t.assertTrue(document !== null);
+		},
+		function testCreateDocumentFromText(t){
+			var simpleXml = "<parentNode><childNode><grandchildNode/></childNode><childNode/></parentNode>";
+			var document = dojox.data.dom.createDocument(simpleXml, "text/xml");
+			
+			var parent = document.firstChild;
+			t.assertTrue(parent !== null);
+			t.assertTrue(parent.tagName === "parentNode");
+			t.assertTrue(parent.childNodes.length == 2);
+			
+			var firstChild = parent.firstChild;
+			t.assertTrue(firstChild !== null);
+			t.assertTrue(firstChild.tagName === "childNode");
+			t.assertTrue(firstChild.childNodes.length == 1);
+			
+			var secondChild = firstChild.nextSibling;
+			t.assertTrue(secondChild !== null);
+			t.assertTrue(secondChild.tagName === "childNode");
+
+			var grandChild = firstChild.firstChild;
+			t.assertTrue(grandChild !== null);
+			t.assertTrue(grandChild.tagName === "grandchildNode");
+
+		},
+		function testCreateDocumentEmptyString(t){
+			var simpleXml = "";
+			var document = dojox.data.dom.createDocument(simpleXml, "text/xml");
+			
+			t.assertTrue(typeof document != "undefined");
+
+			var parent = document.firstChild;
+			t.assertTrue(parent === null);
+		},
+		function testCreateDocumentEmpty(t){
+			var simpleXml;
+			var document = dojox.data.dom.createDocument();
+			
+			t.assertTrue(typeof document != "undefined");
+
+			var parent = document.firstChild;
+			t.assertTrue(parent === null);
+		},
+		function testReadTextContent(t){
+			var text = "This is a bunch of child text on the node";
+			var simpleXml = "<parentNode>" + text + "</parentNode>";
+			var document = dojox.data.dom.createDocument(simpleXml, "text/xml");
+            
+			var topNode = document.firstChild;
+			t.assertTrue(topNode !== null);
+			t.assertTrue(topNode.tagName === "parentNode");
+			t.assertTrue(text === dojox.data.dom.textContent(topNode));
+			dojo.destroy(topNode);
+			t.assertTrue(document.firstChild === null);
+		},
+		function testSetTextContent(t){
+			var text = "This is a bunch of child text on the node";
+			var text2 = "This is the new text";
+			var simpleXml = "<parentNode>" + text + "</parentNode>";
+			var document = dojox.data.dom.createDocument(simpleXml, "text/xml");
+            
+			var topNode = document.firstChild;
+			t.assertTrue(topNode !== null);
+			t.assertTrue(topNode.tagName === "parentNode");
+			t.assertTrue(text === dojox.data.dom.textContent(topNode));
+			dojox.data.dom.textContent(topNode, text2);
+			t.assertTrue(text2 === dojox.data.dom.textContent(topNode));
+			dojo.destroy(topNode);
+			t.assertTrue(document.firstChild === null);
+
+		},
+		function testReplaceChildrenArray(t){
+			var simpleXml1 = "<parentNode><child1/><child2/><child3/></parentNode>";
+			var simpleXml2 = "<parentNode><child4/><child5/><child6/><child7/></parentNode>";
+			var doc1 = dojox.data.dom.createDocument(simpleXml1, "text/xml");
+			var doc2 = dojox.data.dom.createDocument(simpleXml2, "text/xml");
+            
+			var topNode1 = doc1.firstChild;
+			var topNode2 = doc2.firstChild;
+			t.assertTrue(topNode1 !== null);
+			t.assertTrue(topNode1.tagName === "parentNode");
+			t.assertTrue(topNode2 !== null);
+			t.assertTrue(topNode2.tagName === "parentNode");
+			dojox.data.dom.removeChildren(topNode1);
+			var newChildren=[];
+			for(var i=0;i<topNode2.childNodes.length;i++){
+				newChildren.push(topNode2.childNodes[i]);
+			}
+			dojox.data.dom.removeChildren(topNode2);
+			dojox.data.dom.replaceChildren(topNode1,newChildren);
+			t.assertTrue(topNode1.childNodes.length === 4);
+			t.assertTrue(topNode1.firstChild.tagName === "child4");
+			t.assertTrue(topNode1.lastChild.tagName === "child7");
+
+		},
+		function testReplaceChildrenSingle(t){
+			var simpleXml1 = "<parentNode><child1/><child2/><child3/></parentNode>";
+			var simpleXml2 = "<parentNode><child4/></parentNode>";
+			var doc1 = dojox.data.dom.createDocument(simpleXml1, "text/xml");
+			var doc2 = dojox.data.dom.createDocument(simpleXml2, "text/xml");
+            
+			var topNode1 = doc1.firstChild;
+			var topNode2 = doc2.firstChild;
+			t.assertTrue(topNode1 !== null);
+			t.assertTrue(topNode1.tagName === "parentNode");
+			t.assertTrue(topNode2 !== null);
+			t.assertTrue(topNode2.tagName === "parentNode");
+			dojox.data.dom.removeChildren(topNode1);
+			
+			var newChildren = topNode2.firstChild;
+			dojox.data.dom.removeChildren(topNode2);
+			dojox.data.dom.replaceChildren(topNode1,newChildren);
+			t.assertTrue(topNode1.childNodes.length === 1);
+			t.assertTrue(topNode1.firstChild.tagName === "child4");
+			t.assertTrue(topNode1.lastChild.tagName === "child4");
+		},
+		function testRemoveChildren(t){
+			var simpleXml1 = "<parentNode><child1/><child2/><child3/></parentNode>";
+			var doc1 = dojox.data.dom.createDocument(simpleXml1, "text/xml");
+            
+			var topNode1 = doc1.firstChild;
+			t.assertTrue(topNode1 !== null);
+			t.assertTrue(topNode1.tagName === "parentNode");
+			dojox.data.dom.removeChildren(topNode1);
+			t.assertTrue(topNode1.childNodes.length === 0);
+			t.assertTrue(topNode1.firstChild === null);
+		},
+		function testInnerXML(t){
+			var simpleXml1 = "<parentNode><child1/><child2/><child3/></parentNode>";
+			var doc1 = dojox.data.dom.createDocument(simpleXml1, "text/xml");
+            
+			var topNode1 = doc1.firstChild;
+			t.assertTrue(topNode1 !== null);
+			t.assertTrue(topNode1.tagName === "parentNode");
+
+			var innerXml = dojox.data.dom.innerXML(topNode1);
+			t.assertTrue(simpleXml1 === innerXml);
+		}
+	]
+);
diff --git a/dojox/data/tests/ml/divList.html b/dojox/data/tests/ml/divList.html
new file mode 100644
index 0000000..3f0da2f
--- /dev/null
+++ b/dojox/data/tests/ml/divList.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+		<title>HTML Div List for HtmlStore</title>
+	</head>
+	<body>
+		<div id="divExample">
+			<div><b>bold</b></div>
+			<div><i>italic</i></div>
+			<div><i>normal</i></div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/data/tests/ml/orderedList.html b/dojox/data/tests/ml/orderedList.html
new file mode 100644
index 0000000..e995377
--- /dev/null
+++ b/dojox/data/tests/ml/orderedList.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+		<title>HTML Ordered List for HtmlStore</title>
+	</head>
+	<body>
+		<ol id="olExample">
+			<li>Every</li>
+			<li>Good</li>
+			<li>Boy</li>
+			<li>Does</li>
+			<li>Fine</li>
+		</ol>
+	</body>
+</html>
diff --git a/dojox/data/tests/ml/table.html b/dojox/data/tests/ml/table.html
new file mode 100644
index 0000000..0c556d0
--- /dev/null
+++ b/dojox/data/tests/ml/table.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+		<title>HTML Ordered List for HtmlStore</title>
+	</head>
+	<body>
+		<!-- The table to link into with the HtmlStore-->
+		<table id="tableExample">
+			<thead>
+				<tr>
+					<th>X</th>
+					<th>Y</th>
+					<th>A</th>
+					<th>B</th>
+				</tr>
+			</thead>
+			<tbody>
+				<tr id="test">
+					<td>2</td>
+					<td>3</td>
+					<td></td>
+					<td>8</td>
+				</tr>
+				<tr>
+					<td>1</td>
+					<td>3</td>
+					<td>5</td>
+					<td>7</td>
+				</tr>
+				<tr>
+					<td>4</td>
+					<td>9</td>
+					<td>22</td>
+					<td>777</td>
+				</tr>
+				<tr>
+					<td>3231</td>
+					<td>3</td>
+					<td>535</td>
+					<td>747</td>
+				</tr>
+			</tbody>
+		</table>
+	</body>
+</html>
diff --git a/dojox/data/tests/ml/test_HtmlStore_declaratively.html b/dojox/data/tests/ml/test_HtmlStore_declaratively.html
new file mode 100644
index 0000000..ea36c8a
--- /dev/null
+++ b/dojox/data/tests/ml/test_HtmlStore_declaratively.html
@@ -0,0 +1,172 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Dojox HtmlDataStore Widget</title>
+<style>
+	@import "../../../../dijit/themes/tundra/tundra.css";
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript">
+	djConfig = {
+		isDebug: true,
+		parseOnLoad: true
+	};
+</script>
+<script type="text/javascript" src="../../../../dojo/dojo.js"></script>
+<!--
+<script language="JavaScript" type="text/javascript">
+	dojo.require("doh.runner");
+	function registerTests() {
+		doh.register("t", 
+			[
+				function testTableLoaded(t){
+					t.assertTrue(tableStore !== null);
+					t.assertTrue(tableStore !== undefined);
+				}
+			]
+		);
+		doh.run();
+	};
+	dojo.addOnLoad(registerTests);
+</script>
+-->
+
+<script language="JavaScript" type="text/javascript">
+	dojo.require("dojo.parser");
+	dojo.require("dojox.data.HtmlStore");
+	dojo.require("dijit.Tree");
+	dojo.require("dijit.form.ComboBox");
+	
+	function init() {
+		var table = tableStore;
+		
+		function testComplete(items, request){
+			console.debug("Completed!");
+
+			var attributes = null;
+			for(var i = 0; i < items.length; i++){
+				attributes = table.getAttributes(items[i]);
+				for(var j=0; j < attributes.length; j++){
+					console.debug("attribute: [" + attributes[j] + "] have value: " + table.getValue(items[i], attributes[j]));
+				}
+			}
+			
+		}
+		table.fetch({query:{X:1}, onComplete: testComplete});
+		table.fetch({query:{X:2}, onComplete: testComplete});
+		table.fetch({query:{X:3}, onComplete: testComplete}); 
+		table.fetch({query:{X:4}, onComplete: testComplete}); 
+		table.fetch({query:{X:5}, onComplete: testComplete}); // Should be empty
+	}
+	dojo.addOnLoad(init);
+</script>
+
+</head>
+<body class="tundra">
+	<h1>Dojox HtmlDataStore Widget</h1>
+	<hr/>
+	<br/>
+	<br/>
+
+	<!-- Instantiate the HtmlStore and bind it to global name tableStore -->
+	<div dojoType="dojox.data.HtmlStore" dataId="tableExample" jsId="tableStore"></div>
+	<div dojoType="dojox.data.HtmlStore" dataId="ulExample" jsId="ulStore"></div>
+	<div dojoType="dojox.data.HtmlStore" dataId="olExample" jsId="olStore"></div>
+	<div dojoType="dojox.data.HtmlStore" dataId="divExample" jsId="divStore"></div>
+
+	<!-- The table to link into with the HtmlStore-->
+	<table id="tableExample">
+		<thead>
+			<tr>
+				<th>X</th>
+				<th>Y</th>
+				<th>A</th>
+				<th>B</th>
+			</tr>
+		</thead>
+		<tbody>
+			<tr id="test">
+				<td>2</td>
+				<td>3</td>
+				<td></td>
+				<td>8</td>
+			</tr>
+			<tr>
+				<td>1</td>
+				<td>3</td>
+				<td>5</td>
+				<td>7</td>
+			</tr>
+			<tr>
+				<td>4</td>
+				<td>9</td>
+				<td>22</td>
+				<td>777</td>
+			</tr>
+			<tr>
+				<td>3231</td>
+				<td>3</td>
+				<td>535</td>
+				<td>747</td>
+			</tr>
+		</tbody>
+	</table>
+
+	<br/>
+	<br/>
+	<blockquote>
+		<b>Table Rows: <br/><i>(Just to show that the tree can determine that the tableStore works like a store).<br/>Should have three branches, where the row had attr Y value of 3.</i></b>
+		<div dojoType="dijit.Tree" id="tree" store="tableStore" query="{Y:3}"></div>
+	</blockquote>
+	
+	<ul id="ulExample">
+		<li>Red</li>
+		<li>Orange</li>
+		<li>Yellow</li>
+		<li>Green</li>
+		<li>Blue</li>
+		<li>Violet</li>
+	</ul>
+	
+	<label for="combo1">Unordered List in ComboBox: </label>
+	<input dojoType="dijit.form.ComboBox" value="Red" class="medium" store="ulStore" searchAttr="name" style="width: 300px;" name="ul.item1" id="combo1"	>
+
+	<blockquote>
+		<b>Unordered List in Tree: <br/></b>
+		<div dojoType="dijit.Tree" id="tree2" labelAttr="name" store="ulStore" query="{name:'*'}"></div>
+	</blockquote>
+
+	<ol id="olExample">
+		<li>Every</li>
+		<li>Good</li>
+		<li>Boy</li>
+		<li>Does</li>
+		<li>Fine</li>
+	</ol>
+
+	<label for="combo2">Ordered List in ComboBox: </label>
+	<input dojoType="dijit.form.ComboBox" value="Every" class="medium" store="olStore" searchAttr="name" style="width: 300px;" name="ol.item1" id="combo2" >
+
+	<blockquote>
+		<b>Ordered List in Tree: <br/></b>
+		<div dojoType="dijit.Tree" id="tree3" labelAttr="name" store="olStore" query="{name:'*'}"></div>
+	</blockquote>
+
+	
+	<div id="divExample">
+		<div><b>bold</b></div>
+		<div><i>italic</i></div>
+		<div><i>normal</i></div>
+	</div>
+	
+	<label for="combo3">Div List in ComboBox: </label>
+	<input dojoType="dijit.form.ComboBox" value="bold" class="medium" store="divStore" searchAttr="name" style="width: 300px;" name="bold" id="combo3" >
+
+	<blockquote>
+		<b>Div list in tree: <br/></b>
+		<div dojoType="dijit.Tree" id="tree4" labelAttr="name" store="divStore" query="{name:'*'}"></div>
+	</blockquote>
+	
+</body>
+</html>
diff --git a/dojox/data/tests/ml/test_HtmlStore_remote.html b/dojox/data/tests/ml/test_HtmlStore_remote.html
new file mode 100644
index 0000000..f9d9eff
--- /dev/null
+++ b/dojox/data/tests/ml/test_HtmlStore_remote.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Dojox HtmlDataStore Widget</title>
+<style>
+	@import "../../../../dijit/themes/tundra/tundra.css";
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript">
+	djConfig = {
+		isDebug: true,
+		parseOnLoad: true
+	};
+</script>
+<script type="text/javascript" src="../../../../dojo/dojo.js"></script>
+<!--
+<script language="JavaScript" type="text/javascript">
+	dojo.require("doh.runner");
+	function registerTests() {
+		doh.register("t", 
+			[
+				function testTableLoaded(t){
+					t.assertTrue(tableStore !== null);
+					t.assertTrue(tableStore !== undefined);
+				}
+			]
+		);
+		doh.run();
+	};
+	dojo.addOnLoad(registerTests);
+</script>
+-->
+
+<script language="JavaScript" type="text/javascript">
+	dojo.require("dojo.parser");
+	dojo.require("dojox.data.HtmlStore");
+	dojo.require("dijit.Tree");
+	dojo.require("dijit.form.ComboBox");
+	
+	function init() {
+		var table = tableStore;
+		
+		function testComplete(items, request){
+			console.debug("Completed!");
+
+			var attributes = null;
+			for(var i = 0; i < items.length; i++){
+				attributes = table.getAttributes(items[i]);
+				for(var j=0; j < attributes.length; j++){
+					console.debug("attribute: [" + attributes[j] + "] have value: " + table.getValue(items[i], attributes[j]));
+				}
+			}
+			
+		}
+		table.fetch({query:{X:1}, onComplete: testComplete});
+		table.fetch({query:{X:2}, onComplete: testComplete});
+		table.fetch({query:{X:3}, onComplete: testComplete}); 
+		table.fetch({query:{X:4}, onComplete: testComplete}); 
+		table.fetch({query:{X:5}, onComplete: testComplete}); // Should be empty
+	}
+	dojo.addOnLoad(init);
+</script>
+
+</head>
+<body class="tundra">
+	<h1>Dojox HtmlDataStore Widget</h1>
+	<hr/>
+	<br/>
+	<br/>
+
+	<!-- Instantiate the HtmlStore and bind it to global name tableStore -->
+	<div dojoType="dojox.data.HtmlStore" url="table.html" dataId="tableExample" jsId="tableStore"></div>
+	<div dojoType="dojox.data.HtmlStore" url="unorderedList.html" dataId="ulExample" jsId="ulStore"></div>
+	<div dojoType="dojox.data.HtmlStore" url="orderedList.html" dataId="olExample" jsId="olStore"></div>
+	<div dojoType="dojox.data.HtmlStore" url="divList.html" dataId="divExample" jsId="divStore"></div>
+
+	<blockquote>
+		<b>Table Rows: <br/><i>(Just to show that the tree can determine that the tableStore works like a store).<br/>Should have three branches, where the row had attr Y value of 3.</i></b>
+		<div dojoType="dijit.Tree" id="tree" store="tableStore" query="{Y:3}"></div>
+	</blockquote>
+	
+	<label for="combo1">Unordered List in ComboBox: </label>
+	<input dojoType="dijit.form.ComboBox" value="Red" class="medium" store="ulStore" searchAttr="name" style="width: 300px;" name="ul.item1" id="combo1"	>
+
+	<blockquote>
+		<b>Unordered List in Tree: <br/></b>
+		<div dojoType="dijit.Tree" id="tree2" labelAttr="name" store="ulStore" query="{name:'*'}"></div>
+	</blockquote>
+
+	<label for="combo2">Ordered List in ComboBox: </label>
+	<input dojoType="dijit.form.ComboBox" value="Every" class="medium" store="olStore" searchAttr="name" style="width: 300px;" name="ol.item1" id="combo2" >
+
+	<blockquote>
+		<b>Ordered List in Tree: <br/></b>
+		<div dojoType="dijit.Tree" id="tree3" labelAttr="name" store="olStore" query="{name:'*'}"></div>
+	</blockquote>
+
+	
+	<div id="divExample">
+		<div><b>bold</b></div>
+		<div><i>italic</i></div>
+		<div><i>normal</i></div>
+	</div>
+	
+	<label for="combo3">Div List in ComboBox: </label>
+	<input dojoType="dijit.form.ComboBox" value="bold" class="medium" store="divStore" searchAttr="name" style="width: 300px;" name="bold" id="combo3" >
+
+	<blockquote>
+		<b>Div list in tree: <br/></b>
+		<div dojoType="dijit.Tree" id="tree4" labelAttr="name" store="divStore" query="{name:'*'}"></div>
+	</blockquote>
+	
+</body>
+</html>
diff --git a/dojox/data/tests/ml/test_HtmlTableStore_declaratively.html b/dojox/data/tests/ml/test_HtmlTableStore_declaratively.html
new file mode 100644
index 0000000..f69ba68
--- /dev/null
+++ b/dojox/data/tests/ml/test_HtmlTableStore_declaratively.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Dojox HtmlDataStore Widget</title>
+<style>
+	@import "../../../../dijit/themes/tundra/tundra.css";
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript">
+	djConfig = {
+		isDebug: true,
+		parseOnLoad: true
+	};
+</script>
+<script type="text/javascript" src="../../../../dojo/dojo.js"></script>
+<!--
+<script language="JavaScript" type="text/javascript">
+	dojo.require("doh.runner");
+	function registerTests() {
+		doh.register("t", 
+			[
+				function testTableLoaded(t){
+					t.assertTrue(tableStore !== null);
+					t.assertTrue(tableStore !== undefined);
+				}
+			]
+		);
+		doh.run();
+	};
+	dojo.addOnLoad(registerTests);
+</script>
+-->
+
+<script language="JavaScript" type="text/javascript">
+	dojo.require("dojo.parser");
+	dojo.require("dojox.data.HtmlTableStore");
+	dojo.require("dijit.Tree");
+	
+	function init() {
+		var table = tableStore;
+		
+		function testComplete(items, request){
+			console.debug("Completed!");
+
+			var attributes = null;
+			for(var i = 0; i < items.length; i++){
+				attributes = table.getAttributes(items[i]);
+				for(var j=0; j < attributes.length; j++){
+					console.debug("attribute: [" + attributes[j] + "] have value: " + table.getValue(items[i], attributes[j]));
+				}
+			}
+			
+		}
+		table.fetch({query:{X:1}, onComplete: testComplete});
+		table.fetch({query:{X:2}, onComplete: testComplete});
+		table.fetch({query:{X:3}, onComplete: testComplete}); 
+		table.fetch({query:{X:4}, onComplete: testComplete}); 
+		table.fetch({query:{X:5}, onComplete: testComplete}); // Should be empty
+	}
+	dojo.addOnLoad(init);
+</script>
+
+</head>
+<body class="tundra">
+	<h1>Dojox HtmlDataStore Widget</h1>
+	<hr/>
+	<br/>
+	<br/>
+
+	<!-- Instantiate the HtmlTableStore and bind it to global name tableStore -->
+	<div dojoType="dojox.data.HtmlTableStore" tableId="tableExample" jsId="tableStore"></div>
+
+	<!-- The table to link into with the HtmlTableStore-->
+	<table id="tableExample">
+		<thead>
+			<tr>
+				<th>X</th>
+				<th>Y</th>
+				<th>A</th>
+				<th>B</th>
+			</tr>
+		</thead>
+		<tbody>
+			<tr id="test">
+				<td>2</td>
+				<td>3</td>
+				<td></td>
+				<td>8</td>
+			</tr>
+			<tr>
+				<td>1</td>
+				<td>3</td>
+				<td>5</td>
+				<td>7</td>
+			</tr>
+			<tr>
+				<td>4</td>
+				<td>9</td>
+				<td>22</td>
+				<td>777</td>
+			</tr>
+			<tr>
+				<td>3231</td>
+				<td>3</td>
+				<td>535</td>
+				<td>747</td>
+			</tr>
+
+		</tbody>
+	</table>
+
+	<br/>
+	<br/>
+	<blockquote>
+		<b>Table Rows: <br/><i>(Just to show that the tree can determine that the tableStore works like a store).<br/>Should have three branches, where the row had attr Y value of 3.</i></b>
+		<div dojoType="dijit.Tree" id="tree" store="tableStore" query="{Y:3}" label="Test tree"></div>
+	</blockquote>
+</body>
+</html>
diff --git a/dojox/data/tests/ml/unorderedList.html b/dojox/data/tests/ml/unorderedList.html
new file mode 100644
index 0000000..a19149a
--- /dev/null
+++ b/dojox/data/tests/ml/unorderedList.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+		<title>HTML Unorderd List for HtmlStore</title>
+	</head>
+	<body>
+		<ul id="ulExample">
+			<li>Red</li>
+			<li>Orange</li>
+			<li>Yellow</li>
+			<li>Green</li>
+			<li>Blue</li>
+			<li>Violet</li>
+		</ul>
+	</body>
+</html>
diff --git a/dojox/data/tests/module.js b/dojox/data/tests/module.js
new file mode 100644
index 0000000..323e7f6
--- /dev/null
+++ b/dojox/data/tests/module.js
@@ -0,0 +1,39 @@
+dojo.provide("dojox.data.tests.module");
+
+try{
+	dojo.require("dojox.data.tests.ClientFilter");
+	dojo.require("dojox.data.tests.stores.CsvStore");
+	dojo.require("dojox.data.tests.stores.KeyValueStore");
+	dojo.require("dojox.data.tests.stores.AndOrReadStore"); 
+	dojo.require("dojox.data.tests.stores.AndOrWriteStore"); 
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.HtmlTableStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.HtmlStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.OpmlStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.XmlStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.FlickrStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.FlickrRestStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.PicasaStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.AtomReadStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.GoogleSearchStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.GoogleFeedStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.WikipediaStore");
+
+	//Load only if in a browser AND if the location is remote (not file.  As it needs a PHP server to work).
+	if(dojo.isBrowser){
+		if(window.location.protocol !== "file:"){
+			dojo.require("dojox.data.tests.stores.QueryReadStore");
+			dojo.require("dojox.data.tests.stores.SnapLogicStore");
+			dojo.require("dojox.data.tests.stores.FileStore");
+		}
+	}
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.CssRuleStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.CssClassStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.AppStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.stores.OpenSearchStore");
+	dojo.requireIf(dojo.isBrowser, "dojox.data.tests.dom");
+}catch(e){
+	doh.debug(e);
+}
+
+
+
diff --git a/dojox/data/tests/performance/CsvStore.js b/dojox/data/tests/performance/CsvStore.js
new file mode 100755
index 0000000..23059f3
--- /dev/null
+++ b/dojox/data/tests/performance/CsvStore.js
@@ -0,0 +1,166 @@
+dojo.provide("dojox.data.tests.performance.CsvStore");
+dojo.require("dojox.data.CsvStore");
+dojo.require("dojo.data.util.sorter");
+
+
+dojox.data.tests.performance.CsvStore.getData = function(size){
+	//	summary:
+	//		This function generates a psuedorandom dataset collected 
+	//		from some templated entries.  
+	//	returns:
+	//		A 2000 'row' CSV dataset.
+
+	var header = "Title, Year, Producer\n";
+	var templateData = [
+		"City of God, 2002, Katia Lund\n",
+		"Rain,, Christine Jeffs\n",
+		"2001: A Space Odyssey, 1968, Stanley Kubrick\n",
+		'"This is a ""fake"" movie title", 1957, Sidney Lumet\n',
+		"Alien, 1979   , Ridley Scott\n",
+		'"The Sequel to ""Dances With Wolves.""", 1982, Ridley Scott\n',
+		'"Caine Mutiny, The", 1954, "Dymtryk ""the King"", Edward"\n'
+	];
+
+	var data = header;
+
+	var i;
+	for(i = 0; i < size; i++){
+		var idx =Math.floor(Math.random()*7);
+		data += templateData[idx];
+	}
+	return data;
+};
+
+
+doh.register("dojox.data.tests.performance.CsvStore",[
+	{
+		name: "Initial Parse and First Fetch",
+		testType: "perf",
+		trialDuration: 100,
+		trialDelay: 50,
+		trialIterations: 50,
+		runTest: function(){
+			store = new dojox.data.CsvStore({
+				data: dojox.data.tests.performance.CsvStore.getData(2000)
+			});
+			var def = new doh.Deferred();
+			var complete = function(items, request){
+				try{
+					doh.assertEqual(2000, items.length);
+					def.callback(true);
+				}catch(e){
+					def.errback(e);
+				}
+			};
+			var err = function(error, request){
+				def.errback(error);
+			};
+			store.fetch({onComplete: complete, onError: err});
+			return def;
+		}
+	},
+	{
+		name: "Fetch All Data",
+		testType: "perf",
+		trialDuration: 100,
+		trialDelay: 50,
+		trialIterations: 50,
+		setUp: function(){
+			dojox.data.tests.performance.CsvStore.store = new dojox.data.CsvStore({
+				data: dojox.data.tests.performance.CsvStore.getData(2000)
+			});
+			//Since the store is fed this way, it prettymuch acts sync
+			//and we can force a fill data load and parse.
+			//This gets the parse time out of the fetch.
+			dojox.data.tests.performance.CsvStore.store.fetch({});
+		},
+		tearDown: function(){
+			delete dojox.data.tests.performance.CsvStore.store;
+		},
+		runTest: function(){
+			var store = dojox.data.tests.performance.CsvStore.store;
+			var def = new doh.Deferred();
+			var complete = function(items, request){
+				try{
+					doh.assertEqual(2000, items.length);
+					def.callback(true);
+				}catch(e){
+					def.errback(e);
+				}
+			};
+			var err = function(error, request){
+				def.errback(error);
+			};
+			store.fetch({onComplete: complete, onError: err});
+			if(!dojo.isSafari){
+				//Well, realistically this is all sync so we don't *have* to 
+				//pass back a deferred.  I think safari is blowing stack again.
+				//Need to look more at DOH once more.
+				return def;
+			}
+			return null;
+		}
+	},
+	{
+		name: "getValue",
+		testType: "perf",
+		trialDuration: 100,
+		trialDelay: 50,
+		trialIterations: 50,
+		setUp: function(){
+			dojox.data.tests.performance.CsvStore.store = new dojox.data.CsvStore({
+				data: dojox.data.tests.performance.CsvStore.getData(2000)
+			});
+			//Since the store is fed this way, it prettymuch acts sync
+			//and we can force a fill data load and parse.
+			//This gets the parse time out of the fetch.
+			dojox.data.tests.performance.CsvStore.store.fetch({});
+		},
+		tearDown: function(){
+			delete dojox.data.tests.performance.CsvStore.store;
+		},
+		runTest: function(){
+			//Yes, this is bad, I'm accessing internal data, but I don't care
+			//about the fetch time, only the getValue processing.  So,
+			//I just gab the first item.
+			var value = dojox.data.tests.performance.CsvStore.store.getValue(
+				dojox.data.tests.performance.CsvStore.store._arrayOfAllItems[0], 
+				"Title");
+		}
+	},
+	{
+		name: "sort (500 rows)",
+		testType: "perf",
+		trialDuration: 100,
+		trialDelay: 50,
+		trialIterations: 50,
+		setUp: function(){
+			dojox.data.tests.performance.CsvStore.store = new dojox.data.CsvStore({
+				data: dojox.data.tests.performance.CsvStore.getData(500)
+			});
+			//Since the store is fed this way, it prettymuch acts sync
+			//and we can force a fill data load and parse.
+			//This gets the parse time out of the fetch.
+			dojox.data.tests.performance.CsvStore.store.fetch();
+		},
+		tearDown: function(){
+			delete dojox.data.tests.performance.CsvStore.store;
+		},
+		runTest: function(){
+			//Yes, this is bad, I'm accessing internal data, but I don't care
+			//about the fetch time, only the getValue processing.  So,
+			//I just gab the first item.
+			var sort = [{attribute: "Title"}];
+
+			//Create a clone array of all the data.  Yes, this accesses internals, but my goal here
+			//is to test the sorter code with respect to the store.
+			var data = dojox.data.tests.performance.CsvStore.store._arrayOfAllItems.slice(0, 
+				dojox.data.tests.performance.CsvStore.store._arrayOfAllItems.length);
+
+			//Sort it using the generic sorter..
+			data.sort(dojo.data.util.sorter.createSortFunction(sort, 
+				dojox.data.tests.performance.CsvStore.store));
+		}
+	}
+]);
+
diff --git a/dojox/data/tests/performance/module.js b/dojox/data/tests/performance/module.js
new file mode 100755
index 0000000..209696d
--- /dev/null
+++ b/dojox/data/tests/performance/module.js
@@ -0,0 +1,4 @@
+dojo.provide("dojox.data.tests.performance.module");
+dojo.require("dojox.data.tests.performance.CsvStore");
+
+
diff --git a/dojox/data/tests/performance/runTests.html b/dojox/data/tests/performance/runTests.html
new file mode 100755
index 0000000..cbe6501
--- /dev/null
+++ b/dojox/data/tests/performance/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../../util/doh/runner.html?testModule=dojox.data.tests.performance.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/data/tests/runTests.html b/dojox/data/tests/runTests.html
new file mode 100644
index 0000000..49f065c
--- /dev/null
+++ b/dojox/data/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.data.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/data/tests/stores/AndOrReadStore.js b/dojox/data/tests/stores/AndOrReadStore.js
new file mode 100755
index 0000000..98a6213
--- /dev/null
+++ b/dojox/data/tests/stores/AndOrReadStore.js
@@ -0,0 +1,3575 @@
+dojo.provide("dojox.data.tests.stores.AndOrReadStore");
+dojo.require("dojox.data.AndOrReadStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+dojo.require("dojo.date");
+dojo.require("dojo.date.stamp");
+
+dojo.declare("dojox.data.tests.Wrapper", null, {
+	//	summary:
+	//		Simple class to use for typeMap in order to	test out 
+	//		'falsy' values for _value.
+	_wrapped: null,
+
+	constructor: function(obj){
+		this._wrapped = obj;
+	},
+
+	getValue: function() {
+		return this._wrapped;
+	},
+
+	setValue: function(obj) {
+		this._wrapped = obj;
+	},
+
+	toString: function(){
+		 return "WRAPPER: [" + this._wrapped + "]";
+	}
+});
+
+
+//The test data-sets and tests are taken from ItemFileReadStore, to show 
+//  backwards compatibility.
+//Additionally, where appropriate (fetch/query), the AndOrReadStore test is immediately
+//  followed by the same query (with ", complex" in the description), but with the query 
+//  being a string rather than a json object. 
+//Below all those tests are new ones that test the use of AND, OR, NOT, ||, &&, (, ), and ","
+//  in queries, as well as a mix of string and json object queries.
+//Since some widgets expect the query to be in json object form, in addition to the 
+//  query="id:1234 || dept:'Sales Department' || (dept:Auto && id:2*)" programmatic syntax,
+//  query="{complexQuery:'id:1234 || dept:\"Sales Department\" || (dept:Auto && id:2*)" is
+//  tested/supported.
+
+//-----------------------------------------------------
+// test data-sets
+dojox.data.tests.stores.AndOrReadStore.getTestData = function(name){
+	var data = null;
+	if(name === "countries"){
+		if(dojo.isBrowser){
+			data = {url: dojo.moduleUrl("dojox", "data/tests/stores/countries.json").toString() };
+		}else{
+			data = {data: { 
+				identifier:'abbr',
+				label:'name',
+				items:[
+					{abbr:'ec', name:'Ecuador', capital:'Quito'},
+					{abbr:'eg', name:'Egypt', capital:'Cairo'},
+					{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+					{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+					{abbr:'er', name:'Eritrea', capital:'Asmara'},
+					{abbr:'ee', name:'Estonia', capital:'Tallinn'},
+					{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+				]
+			} };
+		}
+	}else if(name === "countries_withNull"){
+		data = {data: { 
+			identifier:"abbr",
+			items:[
+				{abbr:"ec", name:null, capital:"Quito"},
+				{abbr:'eg', name:null, capital:'Cairo'},
+				{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+				{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+				{abbr:'er', name:'Eritrea', capital:'Asmara'},
+				{abbr:'ee', name:null, capital:'Tallinn'},
+				{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+			]
+		} };
+	}else if(name === "countries_withoutid"){
+		data = {data: { 
+			label: "name",
+			items:[
+				{abbr:"ec", name:null, capital:"Quito"},
+				{abbr:'eg', name:null, capital:'Cairo'},
+				{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+				{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+				{abbr:'er', name:'Eritrea', capital:'Asmara'},
+				{abbr:'ee', name:null, capital:'Tallinn'},
+				{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+			]
+		} };
+	}else if (name === "countries_withBoolean"){
+		data = {data: { 
+			identifier:"abbr",
+			items:[
+				{abbr:"ec", name:"Ecuador", capital:"Quito", real:true},
+				{abbr:'eg', name:'Egypt', capital:'Cairo', real:true},
+				{abbr:'sv', name:'El Salvador', capital:'San Salvador', real:true},
+				{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo', real:true},
+				{abbr:'er', name:'Eritrea', capital:'Asmara', real:true},
+				{abbr:'ee', name:'Estonia', capital:'Tallinn', real:true},
+				{abbr:'et', name:'Ethiopia', capital:'Addis Ababa', real:true},
+				{abbr:'ut', name:'Utopia', capital:'Paradise', real:false}
+			]
+		} };
+	}else if (name === "countries_withDates"){
+		data = {data: { 
+			identifier:"abbr",
+			items:[
+				{abbr:"ec", name:"Ecuador", capital:"Quito"},
+				{abbr:'eg', name:'Egypt', capital:'Cairo'},
+				{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+				{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+				{abbr:'er', name:'Eritrea', capital:'Asmara', independence:{_type:'Date', _value:"1993-05-24T00:00:00Z"}}, // May 24, 1993,
+				{abbr:'ee', name:'Estonia', capital:'Tallinn', independence:{_type:'Date', _value:"1991-08-20T00:00:00Z"}}, // August 20, 1991
+				{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+			]
+		} };
+	}else if (name === "geography_hierarchy_small"){
+		data = {data: { 
+			items:[
+				{ name:'Africa', countries:[
+					{ name:'Egypt', capital:'Cairo' },
+					{ name:'Kenya', capital:'Nairobi' },
+					{ name:'Sudan', capital:'Khartoum' }]},
+				{ name:'Australia', capital:'Canberra' },
+				{ name:'North America', countries:[
+					{ name:'Canada', population:'33 million', cities:[
+						{ name:'Toronto', population:'2.5 million' },
+						{ name:'Alberta', population:'1 million' }
+						]},
+					{ name: 'United States of America', capital: 'Washington DC', states:[
+						{ name: 'Missouri'},
+						{ name: 'Arkansas'}
+						]}
+					]}
+			]
+		}};
+	}else if (name === "data_multitype"){
+		data = {data: { 
+						"identifier": "count",
+						"label": "count", 
+						items: [
+							{ count: 1,    value: "true" },
+							{ count: 2,    value: true   },
+							{ count: 3,    value: "false"},
+							{ count: 4,    value: false  },
+							{ count: 5,    value: true   },
+							{ count: 6,    value: true   },
+							{ count: 7,    value: "true" },
+							{ count: 8,    value: "true" },
+							{ count: 9,    value: "false"},
+							{ count: 10,   value: false  },
+							{ count: 11,   value: [false, false]},
+							{ count: "12", value: [false, "true"]}
+					   ]
+					} 
+				};
+	}else if (name === "countries_references"){
+		data = {data: { identifier: 'name',
+						label: 'name',
+						items: [
+							{ name:'Africa', type:'continent',
+								children:[{_reference:'Egypt'}, {_reference:'Kenya'}, {_reference:'Sudan'}] },
+							{ name:'Egypt', type:'country' },
+							{ name:'Kenya', type:'country',
+								children:[{_reference:'Nairobi'}, {_reference:'Mombasa'}] },
+							{ name:'Nairobi', type:'city' },
+							{ name:'Mombasa', type:'city' },
+							{ name:'Sudan', type:'country',
+								children:{_reference:'Khartoum'} },
+							{ name:'Khartoum', type:'city' },
+							{ name:'Asia', type:'continent',
+								children:[{_reference:'China'}, {_reference:'India'}, {_reference:'Russia'}, {_reference:'Mongolia'}] },
+							{ name:'China', type:'country' },
+							{ name:'India', type:'country' },
+							{ name:'Russia', type:'country' },
+							{ name:'Mongolia', type:'country' },
+							{ name:'Australia', type:'continent', population:'21 million',
+								children:{_reference:'Commonwealth of Australia'}},
+							{ name:'Commonwealth of Australia', type:'country', population:'21 million'},
+							{ name:'Europe', type:'continent',
+								children:[{_reference:'Germany'}, {_reference:'France'}, {_reference:'Spain'}, {_reference:'Italy'}] },
+							{ name:'Germany', type:'country' },
+							{ name:'France', type:'country' },
+							{ name:'Spain', type:'country' },
+							{ name:'Italy', type:'country' },
+							{ name:'North America', type:'continent',
+								children:[{_reference:'Mexico'}, {_reference:'Canada'}, {_reference:'United States of America'}] },
+							{ name:'Mexico', type:'country',  population:'108 million', area:'1,972,550 sq km',
+								children:[{_reference:'Mexico City'}, {_reference:'Guadalajara'}] },
+							{ name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
+							{ name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' },
+							{ name:'Canada', type:'country',  population:'33 million', area:'9,984,670 sq km',
+								children:[{_reference:'Ottawa'}, {_reference:'Toronto'}] },
+							{ name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
+							{ name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' },
+							{ name:'United States of America', type:'country' },
+							{ name:'South America', type:'continent',
+								children:[{_reference:'Brazil'}, {_reference:'Argentina'}] },
+							{ name:'Brazil', type:'country', population:'186 million' },
+							{ name:'Argentina', type:'country', population:'40 million' }
+						]
+					}
+				};
+	}
+	return data;
+};
+
+//-----------------------------------------------------
+// tests
+dojox.data.tests.stores.AndOrReadStore.getTests = function(){
+	dojox.data.tests.stores.AndOrReadStore.tests = [
+		{
+			name: "Identity API: fetchItemByIdentity()",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the fetchItemByIdentity function of the store.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					if(item !== null){
+						var name = store.getValue(item,"name");
+						t.assertEqual(name, "El Salvador");
+					}
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: fetchItemByIdentity() notFound",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the fetchItemByIdentity function of the store.
+				//	description:
+				//		Simple test of the fetchItemByIdentity function of the store.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item === null);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv_not", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: getIdentityAttributes()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getIdentityAttributes function.
+				//	description:
+				//		Simple test of the getIdentityAttributes function.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var identifiers = store.getIdentityAttributes(item);
+					t.assertTrue(dojo.isArray(identifiers));
+					t.assertEqual(1, identifiers.length);
+					t.assertEqual("abbr", identifiers[0]);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: fetchItemByIdentity() commentFilteredJson",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the fetchItemByIdentity function of the store.
+				//	description:
+				//		Simple test of the fetchItemByIdentity function of the store.
+				//		This tests loading a comment-filtered json file so that people using secure
+				//		data with this store can bypass the JavaSceipt hijack noted in Fortify's
+				//		paper.
+	
+				if(dojo.isBrowser){
+	                var store = new dojox.data.AndOrReadStore({url: dojo.moduleUrl("tests", "data/countries_commentFiltered.json").toString()});
+	
+					var d = new doh.Deferred();
+					var onItem = function(item){
+						t.assertTrue(item !== null);
+						var name = store.getValue(item,"name");
+						t.assertEqual(name, "El Salvador");
+						d.callback(true);
+					};
+					var onError = function(errData){
+						t.assertTrue(false);
+						d.errback(errData);
+					};
+					store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+					return d; // Deferred
+				}
+			}
+		},
+		{
+			name: "Identity API: fetchItemByIdentity() nullValue",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the fetchItemByIdentity function of the store, checling a null value.
+				//	description:
+				//		Simple test of the fetchItemByIdentity function of the store, checking a null value.
+				//		This tests handling attributes in json that were defined as null properly.
+				//		Introduced because of tracker: #3153
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries_withNull"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, null);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "ec", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: fetchItemByIdentity() booleanValue",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the fetchItemByIdentity function of the store, checking a boolean value.
+				//	description:
+				//		Simple test of the fetchItemByIdentity function of the store, checking a boolean value.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries_withBoolean"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, "Utopia");
+					var real = store.getValue(item,"real");
+					t.assertEqual(real, false);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "ut", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: fetchItemByIdentity() withoutSpecifiedIdInData",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of bug #4691, looking up something by assigned id, not one specified in the JSON data.
+				//	description:
+				//		Simple test of bug #4691, looking up something by assigned id, not one specified in the JSON data.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries_withoutid"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, "El Salvador");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "2", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: getIdentity()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getIdentity function of the store.
+				//	description:
+				//		Simple test of the getIdentity function of the store.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.getIdentity(item) === "sv");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: getIdentity() withoutSpecifiedId",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the #4691 bug
+				//	description:
+				//		Simple test of the #4691 bug
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries_withoutid"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item, request){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.getIdentity(item) === 2);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ query:{abbr: "sv"}, onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: getIdentity() withoutSpecifiedId, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the #4691 bug
+				//	description:
+				//		Simple test of the #4691 bug
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries_withoutid"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item, request){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.getIdentity(item) === 2);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ query:'abbr: "sv"', onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: fetch() all",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var completedAll = function(items, request){
+					t.is(7, items.length);
+					d.callback(true);
+				};
+				var error = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+	
+				//Get everything...
+				store.fetch({ onComplete: completedAll, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() abort",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch abort on AndOrReadStore.
+				//	description:
+				//		Simple test of a basic fetch abort on AndOrReadStore.
+				if(dojo.isBrowser){
+					var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+					var d = new doh.Deferred();
+					var abortCalled = false;
+					function completedAll(items, request){
+						t.is(7, items.length);
+						if(abortCalled){
+							console.log("Made it to complete callback and abort was called.  Problem.");
+							d.errback(new Error("Should not be here."));
+						}else{
+							//We beat out calling abort, so this is okay.  Timing.
+							console.log("in onComplete and abort has not been called.  Timing.  This is okay.");
+							d.callback(true);
+						}
+					}
+					function error(errData, request){
+						//An abort should throw a cancel error, so we should
+						//reach this.
+						t.assertTrue(true);
+						d.callback(true);
+					}
+					//Get everything...
+					var req = store.fetch({ onComplete: completedAll, onError: error});
+					abortCalled=true;
+					console.log("Calling abort.");
+					req.abort();
+					return d;
+				}
+			}
+		},
+		{
+			name: "Read API: fetch() one",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {abbr: "ec"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() one, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'abbr: "ec"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() shallow",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of only toplevel items
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of only toplevel items.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 2);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: {name: "A*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() shallow, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of only toplevel items
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of only toplevel items.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 2);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: 'name: "A*"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() Multiple",
+	 		runTest: function(t){
+				//	summary: 
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//	description:
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var done = [false, false];
+	
+				var onCompleteOne = function(items, request){
+					done[0] = true;
+					t.assertEqual(items.length, 2);
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onCompleteTwo = function(items, request){
+					done[1] = true;
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: {name: "A*"}, 
+										onComplete: onCompleteOne, 
+										onError: onError
+									});
+	
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: {name: "N*"}, 
+										onComplete: onCompleteTwo, 
+										onError: onError
+									});
+	
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() Multiple, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//	description:
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var done = [false, false];
+	
+				var onCompleteOne = function(items, request){
+					done[0] = true;
+					t.assertEqual(items.length, 2);
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onCompleteTwo = function(items, request){
+					done[1] = true;
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: 'name: "A*"', 
+										onComplete: onCompleteOne, 
+										onError: onError
+									});
+	
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: 'name: "N*"', 
+										onComplete: onCompleteTwo, 
+										onError: onError
+									});
+	
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() MultipleMixedFetch",
+	 		runTest: function(t){
+				//	summary: 
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//	description:
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//		Tests an item fetch and an identity fetch.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var done = [false, false];
+	
+				var onComplete = function(items, request){
+					done[0] = true;
+					t.assertEqual(items.length, 1);
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onItem = function(item){
+					done[1] = true;
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, "El Salvador");
+					
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: {name: "El*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() MultipleMixedFetch, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//	description:
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//		Tests an item fetch and an identity fetch.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var done = [false, false];
+	
+				var onComplete = function(items, request){
+					done[0] = true;
+					t.assertEqual(items.length, 1);
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onItem = function(item){
+					done[1] = true;
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, "El Salvador");
+					
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: 'name: "El*"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() deep",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of all items (including children (nested))
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of all items (including children (nested))
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 4);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, including child (nested) items.
+				store.fetch({ 	query: {name: "A*"}, 
+										onComplete: onComplete, 
+										onError: onError,
+										queryOptions: {deep:true}
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() deep, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of all items (including children (nested))
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of all items (including children (nested))
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 4);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, including child (nested) items.
+				store.fetch({ 	query: 'name: "A*"', 
+										onComplete: onComplete, 
+										onError: onError,
+										queryOptions: {deep:true}
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() hierarchy off",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of all items with hierarchy disabled
+				//		This should turn off processing child objects as data store items.  It will still process
+				//		references and type maps.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of all items with hierarchy disabled
+				//		This should turn off processing child objects as data store items.  It will still process
+				//		references and type maps.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("geography_hierarchy_small"));
+				
+				//Set this as hierarchy off before fetch to make sure it traps and configs right.
+				store.hierarchical = false;
+				
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					//With hierarchy off, this should only match 2, as only two data store items
+					//will be quertied
+					t.assertEqual(2, items.length);
+					var i;
+					var passed = true;
+					for(i = 0; i < items.length; i++){
+						var countries = store.getValues(items[i], "countries");
+						if(countries){
+							var j;
+							//Make sure none of the child objects were processed into items.
+							for(j = 0; j<countries.length; j++){
+								passed = !store.isItem(countries[j]);
+								if(!passed){
+									break;
+								}
+							}
+						}
+						if(!passed){
+							break;
+						}
+					}
+					if(!passed){
+						d.errback(new Error("Located a child item with hierarchy off and no references in the data.  Error."));
+					}else{
+						d.callback(true);
+					}
+				}
+				function onError(errData, request){
+					d.errback(errData);
+				}
+				//Find all items starting with A, including child (nested) items.
+				store.fetch({ 	query: {name: "A*"}, 
+										onComplete: onComplete, 
+										onError: onError,
+										queryOptions: {deep:true}
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() hierarchy off refs still parse",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of all items with hierarchy disabled
+				//		This should turn off processing child objects as data store items.  It will still process
+				//		references and type maps.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of all items with hierarchy disabled
+				//		This should turn off processing child objects as data store items.  It will still process
+				//		references and type maps.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries_references"));
+				
+				//Set this as hierarchy off before fetch to make sure it traps and configs right.
+				store.hierarchical = false;
+				
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					//With hierarchy off, this should only match 2, as only two data store items
+					//will be quertied
+					t.assertEqual(items.length, 4);
+					var i;
+					var passed = true;
+					for(i = 0; i < items.length; i++){
+						var countries = store.getValues(items[i], "children");
+						if(countries){
+							var j;
+							//Make sure none of the child objects were processed into items.
+							for(j = 0; j<countries.length; j++){
+								passed = store.isItem(countries[j]);
+								if(!passed){
+									break;
+								}
+							}
+						}
+						if(!passed){
+							break;
+						}
+					}
+					if(!passed){
+						d.errback(new Error("Found a non-child item in a reference list in a references based input.  Error."));
+					}else{
+						d.callback(true);
+					}
+				}
+				function onError(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				}
+				//Find all items starting with A, including child (nested) items.
+				store.fetch({ 	query: {name: "A*"}, 
+										onComplete: onComplete, 
+										onError: onError,
+										queryOptions: {deep:true}
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() one_commentFilteredJson",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//		This tests loading a comment-filtered json file so that people using secure
+				//		data with this store can bypass the JavaSceipt hijack noted in Fortify's
+				//		paper.
+				if(dojo.isBrowser){
+	                var store = new dojox.data.AndOrReadStore({url: dojo.moduleUrl("tests", "data/countries_commentFiltered.json").toString()});
+	
+					var d = new doh.Deferred();
+					var onComplete = function(items, request){
+						t.assertEqual(items.length, 1);
+						d.callback(true);
+					};
+					var onError = function(errData, request){
+						t.assertTrue(false);
+						d.errback(errData);
+					};
+					store.fetch({ 	query: {abbr: "ec"}, 
+											onComplete: onComplete, 
+											onError: onError
+										});
+					return d;
+				}
+			}
+		},
+		{
+			name: "Read API: fetch() one_commentFilteredJson, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//		This tests loading a comment-filtered json file so that people using secure
+				//		data with this store can bypass the JavaSceipt hijack noted in Fortify's
+				//		paper.
+				if(dojo.isBrowser){
+	                var store = new dojox.data.AndOrReadStore({url: dojo.moduleUrl("tests", "data/countries_commentFiltered.json").toString()});
+	
+					var d = new doh.Deferred();
+					var onComplete = function(items, request){
+						t.assertEqual(items.length, 1);
+						d.callback(true);
+					};
+					var onError = function(errData, request){
+						t.assertTrue(false);
+						d.errback(errData);
+					};
+					store.fetch({ 	query: 'abbr: "ec"', 
+											onComplete: onComplete, 
+											onError: onError
+										});
+					return d;
+				}
+			}
+		},
+		{
+			name: "Read API: fetch() withNull",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item where some attributes are null.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item where some attributes are null.
+				//		Introduced because of tracker: #3153
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries_withNull"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(4, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {name: "E*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() withNull, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item where some attributes are null.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item where some attributes are null.
+				//		Introduced because of tracker: #3153
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries_withNull"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(4, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'name: "E*"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() all_streaming",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var count = 0;
+	
+				var onBegin = function(size, requestObj){
+					t.assertEqual(size, 7);
+				};
+				var onItem = function(item, requestObj){
+					t.assertTrue(store.isItem(item));
+					count++;
+				};
+				var onComplete = function(items, request){
+					t.assertEqual(count, 7);
+					t.assertTrue(items === null);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+	
+				//Get everything...
+				store.fetch({	onBegin: onBegin,
+										onItem: onItem, 
+										onComplete: onComplete,
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() paging",
+	 		runTest: function(t){
+				//	summary: 
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+				//	description:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+
+				var dumpSixthFetch = function(items, request){
+					t.assertEqual(items.length, 5);
+					d.callback(true);
+				};
+
+				var dumpFifthFetch = function(items, request){
+					t.assertEqual(items.length, 0);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpSixthFetch;
+					store.fetch(request);
+				};
+
+				var dumpFourthFetch = function(items, request){
+					t.assertEqual(items.length, 5);
+					request.start = 9;
+					request.count = 100;
+					request.onComplete = dumpFifthFetch;
+					store.fetch(request);
+				};
+
+				var dumpThirdFetch = function(items, request){
+					t.assertEqual(items.length, 5);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpFourthFetch;
+					store.fetch(request);
+				};
+
+				var dumpSecondFetch = function(items, request){
+					t.assertEqual(items.length, 1);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					store.fetch(request);
+				};
+
+				var dumpFirstFetch = function(items, request){
+					t.assertEqual(items.length, 5);
+					request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					store.fetch(request);
+				};
+	
+				var completed = function(items, request){
+					t.assertEqual(items.length, 7);
+					request.start = 1;
+					request.count = 5;
+					request.onComplete = dumpFirstFetch;
+					store.fetch(request);
+				};
+	
+				var error = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() with MultiType Match",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//	description:
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//		Introduced because of tracker: #4931
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("data_multitype"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(4, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {count: "1*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() with MultiType Match, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//	description:
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//		Introduced because of tracker: #4931
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("data_multitype"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(4, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'count: "1*"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() with MultiType, MultiValue Match",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//	description:
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//		Introduced because of tracker: #4931
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("data_multitype"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(7, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {value: "true"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() with MultiType, MultiValue Match, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//	description:
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//		Introduced because of tracker: #4931
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("data_multitype"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(7, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'value: "true"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: getLabel()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var label = store.getLabel(items[0]);
+					t.assertTrue(label !== null);
+					t.assertEqual("Ecuador", label);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {abbr: "ec"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: getLabel(), complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var label = store.getLabel(items[0]);
+					t.assertTrue(label !== null);
+					t.assertEqual("Ecuador", label);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'abbr: "ec"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: getLabelAttributes()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = store.getLabelAttributes(items[0]);
+					t.assertTrue(dojo.isArray(labelList));
+					t.assertEqual("name", labelList[0]);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {abbr: "ec"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: getLabelAttributes(), complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = store.getLabelAttributes(items[0]);
+					t.assertTrue(dojo.isArray(labelList));
+					t.assertEqual("name", labelList[0]);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'abbr: "ec"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: getValue()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertTrue(name === "El Salvador");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: getValues()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getValues function of the store.
+				//	description:
+				//		Simple test of the getValues function of the store.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var names = store.getValues(item,"name");
+					t.assertTrue(dojo.isArray(names));
+					t.assertEqual(names.length, 1);
+					t.assertEqual(names[0], "El Salvador");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: isItem()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the isItem function of the store
+				//	description:
+				//		Simple test of the isItem function of the store
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.isItem(item));
+					t.assertTrue(!store.isItem({}));
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: isItem() multistore",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the isItem function of the store
+				//		to verify two different store instances do not accept
+				//		items from each other.
+				//	description:
+				//		Simple test of the isItem function of the store
+				//		to verify two different store instances do not accept
+				//		items from each other.
+	
+				// Two different instances, even  if they read from the same URL 
+				// should not accept items between each other!
+				var store1 = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				var store2 = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+
+				var onItem1 = function(item1){
+					t.assertTrue(item1 !== null);
+					
+					var onItem2 = function(item2){
+						t.assertTrue(item1 !== null);
+						t.assertTrue(item2 !== null);
+						t.assertTrue(store1.isItem(item1));
+						t.assertTrue(store2.isItem(item2));
+						t.assertTrue(!store1.isItem(item2));
+						t.assertTrue(!store2.isItem(item1));
+						d.callback(true);
+					};
+					store2.fetchItemByIdentity({identity: "sv", onItem: onItem2, onError: onError});
+	
+				};
+				store1.fetchItemByIdentity({identity: "sv", onItem: onItem1, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: hasAttribute()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the hasAttribute function of the store
+				//	description:
+				//		Simple test of the hasAttribute function of the store
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.hasAttribute(item, "abbr"));
+					t.assertTrue(!store.hasAttribute(item, "abbr_not"));
+	
+					//Test that null attributes throw an exception
+					var passed = false;
+					try{
+						store.hasAttribute(item, null);
+					}catch (e){
+						passed = true;
+					}
+					t.assertTrue(passed);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: containsValue()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the containsValue function of the store
+				//	description:
+				//		Simple test of the containsValue function of the store
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.containsValue(item, "abbr", "sv"));
+					t.assertTrue(!store.containsValue(item, "abbr", "sv1"));
+					t.assertTrue(!store.containsValue(item, "abbr", null));
+	
+					//Test that null attributes throw an exception
+					var passed = false;
+					try{
+						store.containsValue(item, null, "foo");
+					}catch (e){
+						passed = true;
+					}
+					t.assertTrue(passed);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: getAttributes()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getAttributes function of the store
+				//	description:
+				//		Simple test of the getAttributes function of the store
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.isItem(item));
+	
+					var attributes = store.getAttributes(item);
+					t.assertEqual(attributes.length, 3);
+					for(var i = 0; i < attributes.length; i++){
+						t.assertTrue((attributes[i] === "name" || attributes[i] === "abbr" || attributes[i] === "capital"));
+					}
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: getFeatures()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getFeatures function of the store
+				//	description:
+				//		Simple test of the getFeatures function of the store
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var features = store.getFeatures();
+				t.assertTrue(features["dojo.data.api.Read"] !== null);
+				t.assertTrue(features["dojo.data.api.Identity"] !== null);
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch0",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of everything starting with lowercase e
+				//	description:
+				//		Function to test pattern matching of everything starting with lowercase e
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var completed = function(items, request) {
+					t.assertEqual(items.length, 5);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "abbr");
+						if(!(value === "ec" || value === "eg" || value === "er" || value === "ee" || value === "et")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected abbreviation found, match failure."));
+					}
+				};
+				var error = function(error, request) {
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: {abbr: "e*"}, onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch0, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of everything starting with lowercase e
+				//	description:
+				//		Function to test pattern matching of everything starting with lowercase e
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var completed = function(items, request) {
+					t.assertEqual(items.length, 5);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "abbr");
+						if(!(value === "ec" || value === "eg" || value === "er" || value === "ee" || value === "et")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected abbreviation found, match failure."));
+					}
+				};
+				var error = function(error, request) {
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: 'abbr: "e*"', onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch1",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of everything with $ in it.
+				//	description:
+				//		Function to test pattern matching of everything with $ in it.
+	
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"boomBam"},
+													   {uniqueId: 4, value:"bit$Bite"},
+													   {uniqueId: 5, value:"ouagadogou"},
+													   {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 8, value:"seaweed"},
+													   {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 2);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bit$Bite" || value === "jfq4@#!$!@Rf14r14i5u")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: {value: "*$*"}, onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch1, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of everything with $ in it.
+				//	description:
+				//		Function to test pattern matching of everything with $ in it.
+	
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"boomBam"},
+													   {uniqueId: 4, value:"bit$Bite"},
+													   {uniqueId: 5, value:"ouagadogou"},
+													   {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 8, value:"seaweed"},
+													   {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 2);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bit$Bite" || value === "jfq4@#!$!@Rf14r14i5u")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: 'value: "*$*"', onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch2",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test exact pattern match
+				//	description:
+				//		Function to test exact pattern match
+	
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"boomBam"},
+													   {uniqueId: 4, value:"bit$Bite"},
+													   {uniqueId: 5, value:"ouagadogou"},
+													   {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 8, value:"seaweed"},
+													   {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+													 ]
+											}
+									 });
+	
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 1);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected abbreviation found, match failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: {value: "bar\\*foo"}, onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch2, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test exact pattern match
+				//	description:
+				//		Function to test exact pattern match
+	
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"boomBam"},
+													   {uniqueId: 4, value:"bit$Bite"},
+													   {uniqueId: 5, value:"ouagadogou"},
+													   {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 8, value:"seaweed"},
+													   {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+													 ]
+											}
+									 });
+	
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 1);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected abbreviation found, match failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: 'value: "bar\\*foo"', onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch_caseSensitive",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of a pattern case-sensitively
+				//	description:
+				//		Function to test pattern matching of a pattern case-sensitively
+	
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"BAR*foo"},
+													   {uniqueId: 4, value:"BARBananafoo"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(1, items.length);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: {value: "bar\\*foo"}, queryOptions: {ignoreCase: false} , onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch_caseSensitive, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of a pattern case-sensitively
+				//	description:
+				//		Function to test pattern matching of a pattern case-sensitively
+	
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"BAR*foo"},
+													   {uniqueId: 4, value:"BARBananafoo"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(1, items.length);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: 'value: "bar\\*foo"', queryOptions: {ignoreCase: false} , onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch_caseInsensitive",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of a pattern case-insensitively
+				//	description:
+				//		Function to test pattern matching of a pattern case-insensitively
+	
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"BAR*foo"},
+													   {uniqueId: 4, value:"BARBananafoo"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 2);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "BAR*foo" || value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: {value: "bar\\*foo"}, queryOptions: {ignoreCase: true}, onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch_caseInsensitive, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of a pattern case-insensitively
+				//	description:
+				//		Function to test pattern matching of a pattern case-insensitively
+	
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"BAR*foo"},
+													   {uniqueId: 4, value:"BARBananafoo"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 2);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "BAR*foo" || value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: 'value: "bar\\*foo"', queryOptions: {ignoreCase: true}, onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortNumeric",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting numerically.
+				//	description:
+				//		Function to test sorting numerically.
+				
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+													   {uniqueId: 1, value:"ba|r*foo"}, 
+													   {uniqueId: 2, value:"boomBam"},
+													   {uniqueId: 3, value:"bit$Bite"},
+													   {uniqueId: 4, value:"ouagadogou"},
+													   {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+													   {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 9, value:"seaweed"},
+													   {uniqueId: 10, value:"zulu"},
+													   {uniqueId: 8, value:"seaweed"}
+													 ]
+											}
+									 });
+	
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "uniqueId") === i)){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+	
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+	
+				var sortAttributes = [{attribute: "uniqueId"}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortNumericDescending",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting numerically.
+				//	description:
+				//		Function to test sorting numerically.
+	
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+													   {uniqueId: 1, value:"ba|r*foo"}, 
+													   {uniqueId: 2, value:"boomBam"},
+													   {uniqueId: 3, value:"bit$Bite"},
+													   {uniqueId: 4, value:"ouagadogou"},
+													   {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+													   {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 9, value:"seaweed"},
+													   {uniqueId: 10, value:"zulu"},
+													   {uniqueId: 8, value:"seaweed"}
+													 ]
+											}
+									 });
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!((items.length - (store.getValue(items[i], "uniqueId") + 1)) === i)){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+	
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+	
+				var sortAttributes = [{attribute: "uniqueId", descending: true}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortNumericWithCount",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting numerically in descending order, returning only a specified number of them.
+				//	description:
+				//		Function to test sorting numerically in descending order, returning only a specified number of them.
+			
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+													  {uniqueId: 1, value:"ba|r*foo"}, 
+													  {uniqueId: 2, value:"boomBam"},
+													  {uniqueId: 3, value:"bit$Bite"},
+													  {uniqueId: 4, value:"ouagadogou"},
+													  {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+													  {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+													  {uniqueId: 7, value:"squawl"},
+													  {uniqueId: 9, value:"seaweed"},
+													  {uniqueId: 10, value:"zulu"},
+													  {uniqueId: 8, value:"seaweed"}
+													]
+										   }
+									});
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 5);
+					var itemId = 10;
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "uniqueId") === itemId)){
+							passed=false;
+							break;
+						}
+						itemId--; // Decrement the item id.  We are descending sorted, so it should go 10, 9, 8, etc.
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+				 
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "uniqueId", descending: true}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes, count: 5});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortAlphabetic",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting alphabetic ordering.
+				//	description:
+				//		Function to test sorting alphabetic ordering.
+			
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value:"abc"},
+													  {uniqueId: 1, value:"bca"}, 
+													  {uniqueId: 2, value:"abcd"},
+													  {uniqueId: 3, value:"abcdefg"},
+													  {uniqueId: 4, value:"lmnop"},
+													  {uniqueId: 5, value:"foghorn"},
+													  {uniqueId: 6, value:"qberty"},
+													  {uniqueId: 7, value:"qwerty"},
+													  {uniqueId: 8, value:""},
+													  {uniqueId: 9, value:"seaweed"},
+													  {uniqueId: 10, value:"123abc"}
+			
+													]
+										   }
+									});
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					//Output should be in this order...
+					var orderedArray = [ 	"",
+											"123abc",
+											"abc",
+											"abcd",
+											"abcdefg",
+											"bca",
+											"foghorn",
+											"lmnop",
+											"qberty",
+											"qwerty",
+											"seaweed"
+						];
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "value") === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request) {
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "value"}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortAlphabeticDescending",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting alphabetic ordering in descending mode.
+				//	description:
+				//		Function to test sorting alphabetic ordering in descending mode.
+			
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value:"abc"},
+													  {uniqueId: 1, value:"bca"}, 
+													  {uniqueId: 2, value:"abcd"},
+													  {uniqueId: 3, value:"abcdefg"},
+													  {uniqueId: 4, value:"lmnop"},
+													  {uniqueId: 5, value:"foghorn"},
+													  {uniqueId: 6, value:"qberty"},
+													  {uniqueId: 7, value:"qwerty"},
+													  {uniqueId: 8, value:""},
+													  {uniqueId: 9, value:"seaweed"},
+													  {uniqueId: 10, value:"123abc"}
+			
+													]
+										   }
+									});
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					//Output should be in this order...
+					var orderedArray = [ 	"",
+											"123abc",
+											"abc",
+											"abcd",
+											"abcdefg",
+											"bca",
+											"foghorn",
+											"lmnop",
+											"qberty",
+											"qwerty",
+											"seaweed"
+						];
+					orderedArray = orderedArray.reverse();
+					t.assertEqual(items.length, 11);
+	
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "value") === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request) {
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "value", descending: true}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortDate",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting date.
+				//	description:
+				//		Function to test sorting date.
+			
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value: new Date(0)},
+													  {uniqueId: 1, value: new Date(100)}, 
+													  {uniqueId: 2, value:new Date(1000)},
+													  {uniqueId: 3, value:new Date(2000)},
+													  {uniqueId: 4, value:new Date(3000)},
+													  {uniqueId: 5, value:new Date(4000)},
+													  {uniqueId: 6, value:new Date(5000)},
+													  {uniqueId: 7, value:new Date(6000)},
+													  {uniqueId: 8, value:new Date(7000)},
+													  {uniqueId: 9, value:new Date(8000)},
+													  {uniqueId: 10, value:new Date(9000)}
+			
+													]
+										   }
+									});
+				
+				var d = new doh.Deferred();
+				var completed = function(items,request){
+					var orderedArray =	[0,100,1000,2000,3000,4000,5000,6000,7000,8000,9000];
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "value").getTime() === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "value"}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortDateDescending",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting date in descending order.
+				//	description:
+				//		Function to test sorting date in descending order.
+			
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value: new Date(0)},
+													  {uniqueId: 1, value: new Date(100)}, 
+													  {uniqueId: 2, value:new Date(1000)},
+													  {uniqueId: 3, value:new Date(2000)},
+													  {uniqueId: 4, value:new Date(3000)},
+													  {uniqueId: 5, value:new Date(4000)},
+													  {uniqueId: 6, value:new Date(5000)},
+													  {uniqueId: 7, value:new Date(6000)},
+													  {uniqueId: 8, value:new Date(7000)},
+													  {uniqueId: 9, value:new Date(8000)},
+													  {uniqueId: 10, value:new Date(9000)}
+			
+													]
+										   }
+									});
+			
+				var d = new doh.Deferred();
+				var completed = function(items,request){
+					var orderedArray =	[0,100,1000,2000,3000,4000,5000,6000,7000,8000,9000];
+					orderedArray = orderedArray.reverse();
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "value").getTime() === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "value", descending: true}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortMultiple",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting on multiple attributes.
+				//	description:
+				//		Function to test sorting on multiple attributes.
+				
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 1, value:"fo|o*b.ar"},
+													  {uniqueId: 2, value:"ba|r*foo"}, 
+													  {uniqueId: 3, value:"boomBam"},
+													  {uniqueId: 4, value:"bit$Bite"},
+													  {uniqueId: 5, value:"ouagadogou"},
+													  {uniqueId: 6, value:"jfq4@#!$!@|f1.$4r14i5u"},
+													  {uniqueId: 7, value:"BaB{aMa|SaRa***F}oo"},
+													  {uniqueId: 8, value:"squawl"},
+													  {uniqueId: 10, value:"seaweed"},
+													  {uniqueId: 12, value:"seaweed"},
+													  {uniqueId: 11, value:"zulu"},
+													  {uniqueId: 9, value:"seaweed"}
+													]
+										   }
+									});
+			
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					var orderedArray0 = [7,2,4,3,1,6,5,12,10,9,8,11];
+					var orderedArray1 = [	"BaB{aMa|SaRa***F}oo",
+											"ba|r*foo",
+											"bit$Bite",
+											"boomBam",
+											"fo|o*b.ar",
+											"jfq4@#!$!@|f1.$4r14i5u",
+											"ouagadogou",
+											"seaweed",
+											"seaweed",
+											"seaweed",
+											"squawl",
+											"zulu"
+										];
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(	(store.getValue(items[i], "uniqueId") === orderedArray0[i])&&
+								(store.getValue(items[i], "value") === orderedArray1[i]))
+							){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{ attribute: "value"}, { attribute: "uniqueId", descending: true}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortMultipleSpecialComparator",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting on multiple attributes with a custom comparator.
+				//	description:
+				//		Function to test sorting on multiple attributes with a custom comparator.
+	
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 1, status:"CLOSED"},
+													  {uniqueId: 2,  status:"OPEN"}, 
+													  {uniqueId: 3,  status:"PENDING"},
+													  {uniqueId: 4,  status:"BLOCKED"},
+													  {uniqueId: 5,  status:"CLOSED"},
+													  {uniqueId: 6,  status:"OPEN"},
+													  {uniqueId: 7,  status:"PENDING"},
+													  {uniqueId: 8,  status:"PENDING"},
+													  {uniqueId: 10, status:"BLOCKED"},
+													  {uniqueId: 12, status:"BLOCKED"},
+													  {uniqueId: 11, status:"OPEN"},
+													  {uniqueId: 9,  status:"CLOSED"}
+													]
+										   }
+									});
+			
+			
+				store.comparatorMap = {};
+				store.comparatorMap["status"] = function(a,b) { 
+					var ret = 0;
+					// We want to map these by what the priority of these items are, not by alphabetical.
+					// So, custom comparator.
+					var enumMap = { OPEN: 3, BLOCKED: 2, PENDING: 1, CLOSED: 0};
+					if (enumMap[a] > enumMap[b]) {
+						ret = 1;
+					}
+					if (enumMap[a] < enumMap[b]) {
+						ret = -1;
+					}
+					return ret;
+				};
+			
+				var sortAttributes = [{attribute: "status", descending: true}, { attribute: "uniqueId", descending: true}];
+			
+				var d = new doh.Deferred();
+				var completed = function(items, findResult){
+					var orderedArray = [11,6,2,12,10,4,8,7,3,9,5,1];
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "uniqueId") === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortAlphabeticWithUndefined",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting alphabetic ordering.
+				//	description:
+				//		Function to test sorting alphabetic ordering.
+			
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value:"abc"},
+													  {uniqueId: 1, value:"bca"}, 
+													  {uniqueId: 2, value:"abcd"},
+													  {uniqueId: 3, value:"abcdefg"},
+													  {uniqueId: 4, value:"lmnop"},
+													  {uniqueId: 5, value:"foghorn"},
+													  {uniqueId: 6, value:"qberty"},
+													  {uniqueId: 7, value:"qwerty"},
+													  {uniqueId: 8 },  //Deliberate undefined value
+													  {uniqueId: 9, value:"seaweed"},
+													  {uniqueId: 10, value:"123abc"}
+			
+													]
+										   }
+									});
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					//Output should be in this order...
+					var orderedArray = [10,0,2,3,1,5,4,6,7,9,8];
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						if(!(store.getValue(items[i], "uniqueId") === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request) {
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "value"}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: errorCondition_idCollision_inMemory",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the errors thrown when there is an id collision in the data.
+				//		Added because of tracker: #2546
+				//	description:
+				//		Simple test of the errors thrown when there is an id collision in the data.
+				//		Added because of tracker: #2546
+	
+				var store = new dojox.data.AndOrReadStore({	data: { identifier: "uniqueId", 
+																	items: [{uniqueId: 12345, value:"foo"},
+																			{uniqueId: 123456, value:"bar"}, 
+																			{uniqueId: 12345, value:"boom"},
+																			{uniqueId: 123457, value:"bit"}
+																		]
+																	}
+																});
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					//This is bad if this fires, this case should fail and not call onComplete.
+					t.assertTrue(false);
+					d.callback(false);
+				};
+			
+				var reportError = function(errData, request){
+					//This is good if this fires, it is expected.
+					t.assertTrue(true);
+					d.callback(true);
+				};
+				store.fetch({onComplete: onComplete, onError: reportError});
+				return d;
+			}
+		},
+		{
+			name: "Read API: errorCondition_idCollision_xhr",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the errors thrown when there is an id collision in the data.
+				//		Added because of tracker: #2546
+				//	description:
+				//		Simple test of the errors thrown when there is an id collision in the data.
+				//		Added because of tracker: #2546
+	
+				if(dojo.isBrowser){
+					var store = new dojox.data.AndOrReadStore({url: dojo.moduleUrl("tests", "data/countries_idcollision.json").toString() });
+					var d = new doh.Deferred();
+					var onComplete = function(items, request){
+						//This is bad if this fires, this case should fail and not call onComplete.
+						t.assertTrue(false);
+						d.callback(false);
+					};
+	
+					var reportError = function(errData, request){
+						//This is good if this fires, it is expected.
+						t.assertTrue(true);
+						d.callback(true);
+					};
+					store.fetch({onComplete: onComplete, onError: reportError});
+					return d;
+				}
+			}
+		},
+		{
+			name: "Read API: Date_datatype",
+	 		runTest: function(t){
+				//var store = new dojox.data.AndOrReadStore(tests.data.readOnlyItemFileTestTemplates.testFile["countries_withDates"]);
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries_withDates"));
+				
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var independenceDate = store.getValue(item, "independence");
+					t.assertTrue(independenceDate instanceof Date);
+					//Check to see if the value was deserialized properly.  Since the store stores in UTC/GMT, it 
+					//should also be compared in the UTC/GMT mode
+					t.assertTrue(dojo.date.stamp.toISOString(independenceDate, {zulu:true}) === "1993-05-24T00:00:00Z");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity:"er", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: custom_datatype_Color_SimpleMapping",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test using literal values with custom datatypes
+				var dataset = {
+					identifier:'name',
+					items: [
+						{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+						{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+					]
+				};
+				var store = new dojox.data.AndOrReadStore({
+						data:dataset,
+						typeMap:{'Color': dojo.Color}
+				});
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var beaker = item;
+					var hairColor = store.getValue(beaker, "hairColor");
+					t.assertTrue(hairColor instanceof dojo.Color);
+					t.assertTrue(hairColor.toHex() == "#ff0000");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity:"Beaker", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: custom_datatype_Color_GeneralMapping",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test using literal values with custom datatypes
+				var dataset = {
+					identifier:'name',
+					items: [
+						{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+						{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+					]
+				};
+				var store = new dojox.data.AndOrReadStore({
+						data:dataset,
+						typeMap:{'Color': 	{	
+												type: dojo.Color,
+												deserialize: function(value){
+													return new dojo.Color(value);
+												}
+											}
+								}
+				});
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var beaker = item;
+					var hairColor = store.getValue(beaker, "hairColor");
+					t.assertTrue(hairColor instanceof dojo.Color);
+					t.assertTrue(hairColor.toHex() == "#ff0000");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity:"Beaker", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: custom_datatype_CustomObject 0 (False) value",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test type mapping and _values that are false-like
+				var dataset = {
+					identifier:'name',
+					items: [
+						{ name:'Bob', species:'human', age: {_type:'dojox.data.tests.Wrapper', _value:0} },
+						{ name:'Nancy', species:'human', age: {_type:'dojox.data.tests.Wrapper', _value:32} }
+					]
+				};
+				var store = new dojox.data.AndOrReadStore({
+						data:dataset,
+						typeMap:{'dojox.data.tests.Wrapper': 	{	
+												type: dojox.data.tests.Wrapper,
+												deserialize: function(value){
+													return new dojox.data.tests.Wrapper(value);
+												}
+											}
+								}
+				});
+				var d = new doh.Deferred();
+				function onItem(item){
+					console.log(item);
+					t.assertTrue(item !== null);
+					var bob = item;
+					var age = store.getValue(item, "age");
+					t.assertTrue(age instanceof dojox.data.tests.Wrapper);
+					t.assertTrue(age.toString() == "WRAPPER: [0]");
+					d.callback(true);
+				}
+				function onError(errData){
+					d.errback(errData);
+				}
+				store.fetchItemByIdentity({identity:"Bob", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: custom_datatype_CustomObject Boolean False values",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test type mapping and _values that are false-like
+				var dataset = {
+					identifier:'name',
+					items: [
+						{ name:'Bob', isHuman: {_type:'dojox.data.tests.Wrapper', _value:false} },
+						{ name:'Nancy', isHuman: {_type:'dojox.data.tests.Wrapper', _value: true} }
+					]
+				};
+				var store = new dojox.data.AndOrReadStore({
+						data:dataset,
+						typeMap:{'dojox.data.tests.Wrapper': 	{	
+												type: dojox.data.tests.Wrapper,
+												deserialize: function(value){
+													return new dojox.data.tests.Wrapper(value);
+												}
+											}
+								}
+				});
+				var d = new doh.Deferred();
+				function onItem(item){
+					t.assertTrue(item !== null);
+					var bob = item;
+					var isHuman = store.getValue(item, "isHuman");
+					t.assertTrue(isHuman instanceof dojox.data.tests.Wrapper);
+					t.assertTrue(isHuman.toString() == "WRAPPER: [false]");
+					d.callback(true);
+				}
+				function onError(errData){
+					d.errback(errData);
+				}
+				store.fetchItemByIdentity({identity:"Bob", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: custom_datatype_CustomObject Empty String values",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test type mapping and _values that are false-like
+				var dataset = {
+					identifier:'name',
+					items: [
+						{ name:'Bob', lastName: {_type:'dojox.data.tests.Wrapper', _value:""} },
+						{ name:'Nancy', lastName: {_type:'dojox.data.tests.Wrapper', _value: "Doe"} }
+					]
+				};
+				var store = new dojox.data.AndOrReadStore({
+						data:dataset,
+						typeMap:{'dojox.data.tests.Wrapper': 	{	
+												type: dojox.data.tests.Wrapper,
+												deserialize: function(value){
+													return new dojox.data.tests.Wrapper(value);
+												}
+											}
+								}
+				});
+				var d = new doh.Deferred();
+				function onItem(item){
+					t.assertTrue(item !== null);
+					var bob = item;
+					var lastName = store.getValue(item, "lastName");
+					t.assertTrue(lastName instanceof dojox.data.tests.Wrapper);
+					t.assertTrue(lastName.toString() == "WRAPPER: []");
+					d.callback(true);
+				}
+				function onError(errData){
+					d.errback(errData);
+				}
+				store.fetchItemByIdentity({identity:"Bob", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: custom_datatype_CustomObject explicit null values",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test type mapping and _values that are false-like
+				var dataset = {
+					identifier:'name',
+					items: [
+						{ name:'Bob', lastName: {_type:'dojox.data.tests.Wrapper', _value:null} },
+						{ name:'Nancy', lastName: {_type:'dojox.data.tests.Wrapper', _value: "Doe"} }
+					]
+				};
+				var store = new dojox.data.AndOrReadStore({
+						data:dataset,
+						typeMap:{'dojox.data.tests.Wrapper': 	{	
+												type: dojox.data.tests.Wrapper,
+												deserialize: function(value){
+													return new dojox.data.tests.Wrapper(value);
+												}
+											}
+								}
+				});
+				var d = new doh.Deferred();
+				function onItem(item){
+					t.assertTrue(item !== null);
+					var bob = item;
+					var lastName = store.getValue(item, "lastName");
+					t.assertTrue(lastName instanceof dojox.data.tests.Wrapper);
+					t.assertTrue(lastName.toString() == "WRAPPER: [null]");
+					d.callback(true);
+				}
+				function onError(errData){
+					d.errback(errData);
+				}
+				store.fetchItemByIdentity({identity:"Bob", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: custom_datatype_CustomObject explicit undefined value",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test type mapping and _values that are false-like
+				var dataset = {
+					identifier:'name',
+					items: [
+						{ name:'Bob', lastName: {_type:'dojox.data.tests.Wrapper', _value: undefined} },
+						{ name:'Nancy', lastName: {_type:'dojox.data.tests.Wrapper', _value: "Doe"} }
+					]
+				};
+				var store = new dojox.data.AndOrReadStore({
+						data:dataset,
+						typeMap:{'dojox.data.tests.Wrapper': 	{	
+												type: dojox.data.tests.Wrapper,
+												deserialize: function(value){
+													return new dojox.data.tests.Wrapper(value);
+												}
+											}
+								}
+				});
+				var d = new doh.Deferred();
+				function onItem(item){
+					t.assertTrue(item !== null);
+					var bob = item;
+					var lastName = store.getValue(item, "lastName");
+					t.assertTrue(lastName instanceof dojox.data.tests.Wrapper);
+					t.assertTrue(lastName.toString() == "WRAPPER: [undefined]");
+					d.callback(true);
+				}
+				function onError(errData){
+					d.errback(errData);
+				}
+				store.fetchItemByIdentity({identity:"Bob", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		},
+
+		{
+			name: "Read API: hierarchical_data",
+	 		runTest: function(t){
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("geography_hierarchy_small"));
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var northAmerica = items[0];
+					var canada = store.getValue(northAmerica, "countries");
+					var toronto = store.getValue(canada, "cities");
+					t.assertEqual(store.getValue(canada, "name"), "Canada");
+					t.assertEqual(store.getValue(toronto, "name"), "Toronto");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					d.errback(errData);
+				};
+				store.fetch({
+					query: {name: "North America"},
+					onComplete: onComplete,
+					onError: onError
+				});
+				
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: hierarchical_data, complex",
+	 		runTest: function(t){
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("geography_hierarchy_small"));
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var northAmerica = items[0];
+					var canada = store.getValue(northAmerica, "countries");
+					var toronto = store.getValue(canada, "cities");
+					t.assertEqual(store.getValue(canada, "name"), "Canada");
+					t.assertEqual(store.getValue(toronto, "name"), "Toronto");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					d.errback(errData);
+				};
+				store.fetch({
+					query: 'name: "North America"',
+					onComplete: onComplete,
+					onError: onError
+				});
+				
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: close (clearOnClose: true, reset url.)",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+				if (dojo.isBrowser) {
+					var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+					store.clearOnClose = true;
+					store.urlPreventCache = true;
+	
+					var d = new doh.Deferred();
+					function onItem(item){
+						var error = null;
+						try {
+							t.assertTrue(item !== null);
+							var ec = item;
+							var val = store.getValue(ec, "name");
+							t.assertEqual("Ecuador", val);
+	
+							store.close();
+							//Check some internals here.  Do not normally access these!
+							t.assertTrue(store._arrayOfAllItems.length === 0);
+							t.assertTrue(store._loadFinished === false);
+							
+							store.url = dojo.moduleUrl("dojox", "data/tests/stores/countries_withNull.json").toString()
+							function onItem2 (item){
+								var err;
+								try{
+									t.assertTrue(item !== null);
+									var val = store.getValue(item, "name");
+									t.assertEqual(null, val);
+								}catch(e){
+									err = e;
+								}
+								if(err){
+									d.errback(err);
+								}else{
+									d.callback(true);
+								}
+							}
+							store.fetchItemByIdentity({identity:"ec", onItem:onItem2, onError:onError});
+						}catch (e){
+							error = e;
+						}
+						if (error) {
+							d.errback(error);
+						}
+					}
+					function onError(errData){
+						d.errback(errData);
+					}
+					store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+					return d; // Deferred
+				}
+			}
+		},
+		{
+			name: "Read API: fetch, close (clearOnClose: true, reset url.)",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+				if (dojo.isBrowser) {
+					var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+					store.clearOnClose = true;
+					store.urlPreventCache = true;
+	
+					var d = new doh.Deferred();
+					function onItem(item){
+						var error = null;
+						try {
+							t.assertTrue(item !== null);
+							var ec = item;
+							var val = store.getValue(ec, "name");
+							t.assertEqual("Ecuador", val);
+	
+							store.close();
+							//Check some internals here.  Do not normally access these!
+							t.assertTrue(store._arrayOfAllItems.length === 0);
+							t.assertTrue(store._loadFinished === false);
+							
+							store.url = dojo.moduleUrl("dojox", "data/tests/stores/countries_withNull.json").toString()
+							function onComplete (items){
+								var err;
+								try{
+									t.assertEqual(1, items.length);
+									var item = items[0];
+									t.assertTrue(item !== null);
+									var val = store.getValue(item, "name");
+									t.assertEqual(null, val);
+								}catch(e){
+									err = e;
+								}
+								if(err){
+									d.errback(err);
+								}else{
+									d.callback(true);
+								}
+							}
+							store.fetch({query: {abbr:"ec"}, onComplete:onComplete, onError:onError});
+						}catch (e){
+							error = e;
+						}
+						if (error) {
+							d.errback(error);
+						}
+					}
+					function onError(errData){
+						d.errback(errData);
+					}
+					store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+					return d; // Deferred
+				}
+			}
+		},
+		{
+			name: "Read API: close (clearOnClose: true, reset _jsonFileUrl.)",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+				if (dojo.isBrowser) {
+					var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+					store.clearOnClose = true;
+					store.urlPreventCache = true;
+	
+					var d = new doh.Deferred();
+					function onItem(item){
+						var error = null;
+						try {
+							t.assertTrue(item !== null);
+							var ec = item;
+							var val = store.getValue(ec, "name");
+							t.assertEqual("Ecuador", val);
+	
+							store.close();
+							//Check some internals here.  Do not normally access these!
+							t.assertTrue(store._arrayOfAllItems.length === 0);
+							t.assertTrue(store._loadFinished === false);
+							
+							store._jsonFileUrl = dojo.moduleUrl("dojox", "data/tests/stores/countries_withNull.json").toString()
+							function onItem2 (item){
+								var err;
+								try{
+									t.assertTrue(item !== null);
+									var val = store.getValue(item, "name");
+									t.assertEqual(null, val);
+								}catch(e){
+									err = e;
+								}
+								if(err){
+									d.errback(err);
+								}else{
+									d.callback(true);
+								}
+							}
+							store.fetchItemByIdentity({identity:"ec", onItem:onItem2, onError:onError});
+						}catch (e){
+							error = e;
+						}
+						if (error) {
+							d.errback(error);
+						}
+					}
+					function onError(errData){
+						d.errback(errData);
+					}
+					store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+					return d; // Deferred
+				}
+			}
+		},
+		{
+			name: "Read API: close (clearOnClose: true, reset data.)",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test that clear on close and reset of data works.
+				//	description:
+				//		Function to test that clear on close and reset of data works.
+				var store = new dojox.data.AndOrReadStore({data: { identifier: "uniqueId", 
+						items: [ {uniqueId: 1, value:"foo*bar"},
+							{uniqueId: 2, value:"bar*foo"}, 
+							{uniqueId: 3, value:"boomBam"},
+							{uniqueId: 4, value:"bit$Bite"},
+							{uniqueId: 5, value:"ouagadogou"},
+							{uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+							{uniqueId: 7, value:"squawl"},
+							{uniqueId: 8, value:"seaweed"},
+							{uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+						]
+					}
+				});
+	
+				var d = new doh.Deferred();
+				var firstComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var firstItem = items[0];
+	
+					//Set the store clearing options and the new data
+					store.clearOnClose = true;
+					store.data = { identifier: "uniqueId", 
+						items: [ {uniqueId: 1, value:"foo*bar"},
+							{uniqueId: 2, value:"bar*foo"}, 
+							{uniqueId: 3, value:"boomBam"},
+							{uniqueId: 4, value:"bit$Bite"},
+							{uniqueId: 5, value:"ouagadogou"},
+							{uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+							{uniqueId: 7, value:"squawl"},
+							{uniqueId: 8, value:"seaweed"},
+							{uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+						]
+					};
+					store.close();
+	
+					//Do the next fetch and verify that the next item you get is not
+					//a reference to the same item (data cleared and reloaded.
+					var secondComplete = function(items, request){
+						try{
+							t.assertEqual(items.length, 1);
+							var secondItem = items[0];
+							t.assertTrue(firstItem != null);
+							t.assertTrue(secondItem != null);
+							t.assertTrue(firstItem != secondItem);
+							d.callback(true);
+						}catch(e){
+							d.errback(e);
+						}
+					}
+					store.fetch({query: {value: "bar\*foo"}, onComplete: secondComplete, onError: error});
+				}
+				function error(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				}
+				store.fetch({query: {value: "bar\*foo"}, onComplete: firstComplete, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Identity API: no_identifier_specified",
+	 		runTest: function(t){
+				var arrayOfItems = [
+					{name:"Kermit", color:"green"},
+					{name:"Miss Piggy", likes:"Kermit"}, 
+					{name:"Beaker", hairColor:"red"}
+				];
+				var store = new dojox.data.AndOrReadStore({data:{items:arrayOfItems}});
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					var features = store.getFeatures();
+					var hasIdentityFeature = Boolean(features['dojo.data.api.Identity']);
+					t.assertTrue(hasIdentityFeature);
+					for(var i = 0; i < items.length; ++i){
+						var item = items[i];
+						var identifier = store.getIdentityAttributes(item);
+						t.assertTrue(identifier === null);
+						var identity = store.getIdentity(item);
+						t.assertTrue(typeof identity == "number");
+					}
+					d.callback(true);
+				};
+				var reportError = function(errData, request){
+					d.errback(true);
+				};
+				store.fetch({onComplete: onComplete, onError: reportError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: hierarchical_data",
+	 		runTest: function(t){
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("geography_hierarchy_small"));
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					var features = store.getFeatures();
+					var hasIdentityFeature = Boolean(features['dojo.data.api.Identity']);
+					t.assertTrue(hasIdentityFeature);
+					for(var i = 0; i < items.length; ++i){
+						var item = items[i];
+						var identifier = store.getIdentityAttributes(item);
+						t.assertTrue(identifier === null);
+						var identity = store.getIdentity(item);
+						t.assertTrue(typeof identity == "number");
+					}
+					d.callback(true);
+				};
+				var reportError = function(errData, request){
+					d.errback(true);
+				};
+				store.fetch({onComplete: onComplete, onError: reportError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: functionConformance",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+				//	description:
+				//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+				var testStore = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				var readApi = new dojo.data.api.Read();
+				var passed = true;
+	
+				for(var i in readApi){
+					if(i.toString().charAt(0) !== '_')
+					{
+						var member = readApi[i];
+						//Check that all the 'Read' defined functions exist on the test store.
+						if(typeof member === "function"){
+							var testStoreMember = testStore[i];
+							if(!(typeof testStoreMember === "function")){
+								passed = false;
+								break;
+							}
+						}
+					}
+				}
+				t.assertTrue(passed);
+			}
+		},
+		{
+			name: "Identity API: functionConformance",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+				//	description:
+				//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+				var testStore = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				var identityApi = new dojo.data.api.Identity();
+				var passed = true;
+	
+				for(var i in identityApi){
+	
+					if(i.toString().charAt(0) !== '_')
+					{
+						var member = identityApi[i];
+						//Check that all the 'Read' defined functions exist on the test store.
+						if(typeof member === "function"){
+							var testStoreMember = testStore[i];
+							if(!(typeof testStoreMember === "function")){
+								passed = false;
+								break;
+							}
+						}
+					}
+				}
+				t.assertTrue(passed);
+			}
+		},
+		//complex parallels of existing simple queries immediately follow them above.  can search on "complex"
+		//below are complex queries.
+		{
+			name: "Read API: fetch() multiple, OR, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 3);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'abbr: "s*" || capital:"A*"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() multiple, AND(OR, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 3);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'abbr: "e*" AND (capital:"A*" or capital: "Q*")', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() multiple, AND(OR, as json object, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 3);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {complexQuery:'abbr: "e*" AND (capital:"A*" or capital: "Q*")'}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() multiple, AND/OR, as json object, complex, with extra attrs",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {complexQuery:'abbr: "e*" AND (capital:"A*" or capital: "Q*")', name: "Ec*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() multiple, AND/OR, as json object, complex, with extra attrs and spaces",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					t.assertEqual("Equatorial Guinea", store.getValue(items[0], "name"));
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {complexQuery:'abbr: "g*" AND (capital:"A*" or capital: "M*")', name: "Equatorial G*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() multiple, AND/OR, as quoted json object, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrReadStore of a single item.
+				var store = new dojox.data.AndOrReadStore(dojox.data.tests.stores.AndOrReadStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 3);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: "{complexQuery:'abbr: \"e*\" AND (capital:\"A*\" or capital: \"Q*\")'}", 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		}
+	];
+	return dojox.data.tests.stores.AndOrReadStore.tests;
+};
+doh.register("dojox.data.tests.stores.AndOrReadStore", dojox.data.tests.stores.AndOrReadStore.getTests());
diff --git a/dojox/data/tests/stores/AndOrWriteStore.js b/dojox/data/tests/stores/AndOrWriteStore.js
new file mode 100755
index 0000000..35495bb
--- /dev/null
+++ b/dojox/data/tests/stores/AndOrWriteStore.js
@@ -0,0 +1,4965 @@
+dojo.provide("dojox.data.tests.stores.AndOrWriteStore");
+dojo.require("dojox.data.AndOrWriteStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+dojo.require("dojo.date");
+dojo.require("dojo.date.stamp");
+dojo.require("dojo.data.api.Write");
+dojo.require("dojo.data.api.Notification");
+
+
+//The test data-sets and tests are taken from ItemFileReadStore, to show 
+//  backwards compatibility, and from ItemFileWriteStore.  
+//Since no new write capabilities are included in AndOrWriteStore (just those from
+//  ItemFileWriteStore), no new write tests were added.
+//Additionally, where appropriate (fetch/query), the ItemFileReadStore test is immediately
+//  followed by the same query (with ", complex" in the description), but with the query 
+//  being a string rather than a json object. 
+//Below all those tests are new ones that test the use of AND, OR, NOT, ||, &&, (, ), and ","
+//  in queries, as well as a mix of string and json object queries.
+//Since some widgets expect the query to be in json object form, in addition to the 
+//  query="id:1234 || dept:'Sales Department' || (dept:Auto && id:2*)" programmatic syntax,
+//  query="{complexQuery:'id:1234 || dept:\"Sales Department\" || (dept:Auto && id:2*)" is
+//  tested/supported.
+
+//-----------------------------------------------------
+// test data-sets
+dojox.data.tests.stores.AndOrWriteStore.getTestData = function(name){
+	var data = null;
+	if(name === "countries"){
+		if(dojo.isBrowser){
+			data = {url: dojo.moduleUrl("dojox", "data/tests/stores/countries.json").toString() };
+		}else{
+			data = {data: { 
+				identifier:'abbr',
+				label:'name',
+				items:[
+					{abbr:'ec', name:'Ecuador', capital:'Quito'},
+					{abbr:'eg', name:'Egypt', capital:'Cairo'},
+					{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+					{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+					{abbr:'er', name:'Eritrea', capital:'Asmara'},
+					{abbr:'ee', name:'Estonia', capital:'Tallinn'},
+					{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+				]
+			} };
+		}
+	}else if(name === "countries_withNull"){
+		data = {data: { 
+			identifier:"abbr",
+			items:[
+				{abbr:"ec", name:null, capital:"Quito"},
+				{abbr:'eg', name:null, capital:'Cairo'},
+				{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+				{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+				{abbr:'er', name:'Eritrea', capital:'Asmara'},
+				{abbr:'ee', name:null, capital:'Tallinn'},
+				{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+			]
+		} };
+	}else if(name === "countries_withoutid"){
+		data = {data: { 
+			label: "name",
+			items:[
+				{abbr:"ec", name:null, capital:"Quito"},
+				{abbr:'eg', name:null, capital:'Cairo'},
+				{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+				{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+				{abbr:'er', name:'Eritrea', capital:'Asmara'},
+				{abbr:'ee', name:null, capital:'Tallinn'},
+				{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+			]
+		} };
+	}else if (name === "countries_withBoolean"){
+		data = {data: { 
+			identifier:"abbr",
+			items:[
+				{abbr:"ec", name:"Ecuador", capital:"Quito", real:true},
+				{abbr:'eg', name:'Egypt', capital:'Cairo', real:true},
+				{abbr:'sv', name:'El Salvador', capital:'San Salvador', real:true},
+				{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo', real:true},
+				{abbr:'er', name:'Eritrea', capital:'Asmara', real:true},
+				{abbr:'ee', name:'Estonia', capital:'Tallinn', real:true},
+				{abbr:'et', name:'Ethiopia', capital:'Addis Ababa', real:true},
+				{abbr:'ut', name:'Utopia', capital:'Paradise', real:false}
+			]
+		} };
+	}else if (name === "countries_withDates"){
+		data = {data: { 
+			identifier:"abbr",
+			items:[
+				{abbr:"ec", name:"Ecuador", capital:"Quito"},
+				{abbr:'eg', name:'Egypt', capital:'Cairo'},
+				{abbr:'sv', name:'El Salvador', capital:'San Salvador'},
+				{abbr:'gq', name:'Equatorial Guinea', capital:'Malabo'},
+				{abbr:'er', name:'Eritrea', capital:'Asmara', independence:{_type:'Date', _value:"1993-05-24T00:00:00Z"}}, // May 24, 1993,
+				{abbr:'ee', name:'Estonia', capital:'Tallinn', independence:{_type:'Date', _value:"1991-08-20T00:00:00Z"}}, // August 20, 1991
+				{abbr:'et', name:'Ethiopia', capital:'Addis Ababa'}
+			]
+		} };
+	}else if (name === "geography_hierarchy_small"){
+		data = {data: { 
+			items:[
+				{ name:'Africa', countries:[
+					{ name:'Egypt', capital:'Cairo' },
+					{ name:'Kenya', capital:'Nairobi' },
+					{ name:'Sudan', capital:'Khartoum' }]},
+				{ name:'Australia', capital:'Canberra' },
+				{ name:'North America', countries:[
+					{ name:'Canada', population:'33 million', cities:[
+						{ name:'Toronto', population:'2.5 million' },
+						{ name:'Alberta', population:'1 million' }
+						]},
+					{ name: 'United States of America', capital: 'Washington DC', states:[
+						{ name: 'Missouri'},
+						{ name: 'Arkansas'}
+						]}
+					]}
+			]
+		}};
+	}else if (name === "data_multitype"){
+		data = {data: { 
+						"identifier": "count",
+						"label": "count", 
+						items: [
+							{ count: 1,    value: "true" },
+							{ count: 2,    value: true   },
+							{ count: 3,    value: "false"},
+							{ count: 4,    value: false  },
+							{ count: 5,    value: true   },
+							{ count: 6,    value: true   },
+							{ count: 7,    value: "true" },
+							{ count: 8,    value: "true" },
+							{ count: 9,    value: "false"},
+							{ count: 10,   value: false  },
+							{ count: 11,   value: [false, false]},
+							{ count: "12", value: [false, "true"]}
+					   ]
+					} 
+				};
+	}else if (name === "countries_references"){
+		data = {data: { identifier: 'name',
+						label: 'name',
+						items: [
+							{ name:'Africa', type:'continent',
+								children:[{_reference:'Egypt'}, {_reference:'Kenya'}, {_reference:'Sudan'}] },
+							{ name:'Egypt', type:'country' },
+							{ name:'Kenya', type:'country',
+								children:[{_reference:'Nairobi'}, {_reference:'Mombasa'}] },
+							{ name:'Nairobi', type:'city' },
+							{ name:'Mombasa', type:'city' },
+							{ name:'Sudan', type:'country',
+								children:{_reference:'Khartoum'} },
+							{ name:'Khartoum', type:'city' },
+							{ name:'Asia', type:'continent',
+								children:[{_reference:'China'}, {_reference:'India'}, {_reference:'Russia'}, {_reference:'Mongolia'}] },
+							{ name:'China', type:'country' },
+							{ name:'India', type:'country' },
+							{ name:'Russia', type:'country' },
+							{ name:'Mongolia', type:'country' },
+							{ name:'Australia', type:'continent', population:'21 million',
+								children:{_reference:'Commonwealth of Australia'}},
+							{ name:'Commonwealth of Australia', type:'country', population:'21 million'},
+							{ name:'Europe', type:'continent',
+								children:[{_reference:'Germany'}, {_reference:'France'}, {_reference:'Spain'}, {_reference:'Italy'}] },
+							{ name:'Germany', type:'country' },
+							{ name:'France', type:'country' },
+							{ name:'Spain', type:'country' },
+							{ name:'Italy', type:'country' },
+							{ name:'North America', type:'continent',
+								children:[{_reference:'Mexico'}, {_reference:'Canada'}, {_reference:'United States of America'}] },
+							{ name:'Mexico', type:'country',  population:'108 million', area:'1,972,550 sq km',
+								children:[{_reference:'Mexico City'}, {_reference:'Guadalajara'}] },
+							{ name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
+							{ name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' },
+							{ name:'Canada', type:'country',  population:'33 million', area:'9,984,670 sq km',
+								children:[{_reference:'Ottawa'}, {_reference:'Toronto'}] },
+							{ name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
+							{ name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' },
+							{ name:'United States of America', type:'country' },
+							{ name:'South America', type:'continent',
+								children:[{_reference:'Brazil'}, {_reference:'Argentina'}] },
+							{ name:'Brazil', type:'country', population:'186 million' },
+							{ name:'Argentina', type:'country', population:'40 million' }
+						]
+					}
+				};
+	}else if(name === "reference_integrity"){  //write test data.
+		data = 
+			{ data: { 
+				"identifier": "id",
+				"label": "name",
+				"items": [
+					{"id": 1, "name": "Item 1"},
+					{"id": 2, "name": "Item 2"},
+					{"id": 3, "name": "Item 3"},
+					{"id": 4, "name": "Item 4"},
+					{"id": 5, "name": "Item 5"},
+					{"id": 6, "name": "Item 6"},
+					{"id": 7, "name": "Item 7"},
+					{"id": 8, "name": "Item 8"},
+					{"id": 9, "name": "Item 9"},
+					{"id": 10, "name": "Item 10", "friends": [{"_reference": 1},{"_reference": 3},{"_reference": 5}]},
+					{"id": 11, "name": "Item 11", "friends": [{"_reference": 10}], "siblings": [{"_reference": 10}]},
+					{"id": 12, "name": "Item 12", "friends": [{"_reference": 3},{"_reference": 7}], "enemies": [{"_reference": 10}]},
+					{"id": 13, "name": "Item 13", "friends": [{"_reference": 10}]},
+					{"id": 14, "name": "Item 14", "friends": [{"_reference": 11}]},
+					{"id": 15, "name": "item 15", "friends": [{"id": 16, "name": "Item 16"}]}
+				]
+			}
+		};
+	}
+
+	return data;
+};
+
+//-----------------------------------------------------
+// tests
+dojox.data.tests.stores.AndOrWriteStore.getTests = function(){
+	dojox.data.tests.stores.AndOrWriteStore.tests = [
+		{
+			name: "Identity API: fetchItemByIdentity()",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the fetchItemByIdentity function of the store.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					if(item !== null){
+						var name = store.getValue(item,"name");
+						t.assertEqual(name, "El Salvador");
+					}
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: fetchItemByIdentity() notFound",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the fetchItemByIdentity function of the store.
+				//	description:
+				//		Simple test of the fetchItemByIdentity function of the store.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item === null);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv_not", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: getIdentityAttributes()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getIdentityAttributes function.
+				//	description:
+				//		Simple test of the getIdentityAttributes function.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var identifiers = store.getIdentityAttributes(item);
+					t.assertTrue(dojo.isArray(identifiers));
+					t.assertEqual(1, identifiers.length);
+					t.assertEqual("abbr", identifiers[0]);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: fetchItemByIdentity() commentFilteredJson",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the fetchItemByIdentity function of the store.
+				//	description:
+				//		Simple test of the fetchItemByIdentity function of the store.
+				//		This tests loading a comment-filtered json file so that people using secure
+				//		data with this store can bypass the JavaSceipt hijack noted in Fortify's
+				//		paper.
+	
+				if(dojo.isBrowser){
+	                var store = new dojox.data.AndOrWriteStore({url: dojo.moduleUrl("tests", "data/countries_commentFiltered.json").toString()});
+	
+					var d = new doh.Deferred();
+					var onItem = function(item){
+						t.assertTrue(item !== null);
+						var name = store.getValue(item,"name");
+						t.assertEqual(name, "El Salvador");
+						d.callback(true);
+					};
+					var onError = function(errData){
+						t.assertTrue(false);
+						d.errback(errData);
+					};
+					store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+					return d; // Deferred
+				}
+			}
+		},
+		{
+			name: "Identity API: fetchItemByIdentity() nullValue",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the fetchItemByIdentity function of the store, checling a null value.
+				//	description:
+				//		Simple test of the fetchItemByIdentity function of the store, checking a null value.
+				//		This tests handling attributes in json that were defined as null properly.
+				//		Introduced because of tracker: #3153
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries_withNull"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, null);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "ec", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: fetchItemByIdentity() booleanValue",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the fetchItemByIdentity function of the store, checking a boolean value.
+				//	description:
+				//		Simple test of the fetchItemByIdentity function of the store, checking a boolean value.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries_withBoolean"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, "Utopia");
+					var real = store.getValue(item,"real");
+					t.assertEqual(real, false);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "ut", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: fetchItemByIdentity() withoutSpecifiedIdInData",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of bug #4691, looking up something by assigned id, not one specified in the JSON data.
+				//	description:
+				//		Simple test of bug #4691, looking up something by assigned id, not one specified in the JSON data.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries_withoutid"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, "El Salvador");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "2", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: getIdentity()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getIdentity function of the store.
+				//	description:
+				//		Simple test of the getIdentity function of the store.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.getIdentity(item) === "sv");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: getIdentity() withoutSpecifiedId",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the #4691 bug
+				//	description:
+				//		Simple test of the #4691 bug
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries_withoutid"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item, request){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.getIdentity(item) === 2);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ query:{abbr: "sv"}, onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: getIdentity() withoutSpecifiedId, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the #4691 bug
+				//	description:
+				//		Simple test of the #4691 bug
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries_withoutid"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item, request){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.getIdentity(item) === 2);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ query:'abbr: "sv"', onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: fetch() all",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var completedAll = function(items, request){
+					t.is(7, items.length);
+					d.callback(true);
+				};
+				var error = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+	
+				//Get everything...
+				store.fetch({ onComplete: completedAll, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() abort",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch abort on AndOrWriteStore.
+				//	description:
+				//		Simple test of a basic fetch abort on AndOrWriteStore.
+				if(dojo.isBrowser){
+					var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+					var d = new doh.Deferred();
+					var abortCalled = false;
+					function completedAll(items, request){
+						t.is(7, items.length);
+						if(abortCalled){
+							console.log("Made it to complete callback and abort was called.  Problem.");
+							d.errback(new Error("Should not be here."));
+						}else{
+							//We beat out calling abort, so this is okay.  Timing.
+							console.log("in onComplete and abort has not been called.  Timing.  This is okay.");
+							d.callback(true);
+						}
+					}
+					function error(errData, request){
+						//An abort should throw a cancel error, so we should
+						//reach this.
+						t.assertTrue(true);
+						d.callback(true);
+					}
+					//Get everything...
+					var req = store.fetch({ onComplete: completedAll, onError: error});
+					abortCalled=true;
+					console.log("Calling abort.");
+					req.abort();
+					return d;
+				}
+			}
+		},
+		{
+			name: "Read API: fetch() one",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {abbr: "ec"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() one, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'abbr: "ec"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() shallow",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of only toplevel items
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of only toplevel items.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 2);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: {name: "A*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() shallow, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of only toplevel items
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of only toplevel items.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 2);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: 'name: "A*"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() Multiple",
+	 		runTest: function(t){
+				//	summary: 
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//	description:
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var done = [false, false];
+	
+				var onCompleteOne = function(items, request){
+					done[0] = true;
+					t.assertEqual(items.length, 2);
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onCompleteTwo = function(items, request){
+					done[1] = true;
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: {name: "A*"}, 
+										onComplete: onCompleteOne, 
+										onError: onError
+									});
+	
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: {name: "N*"}, 
+										onComplete: onCompleteTwo, 
+										onError: onError
+									});
+	
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() Multiple, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//	description:
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var done = [false, false];
+	
+				var onCompleteOne = function(items, request){
+					done[0] = true;
+					t.assertEqual(items.length, 2);
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onCompleteTwo = function(items, request){
+					done[1] = true;
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: 'name: "A*"', 
+										onComplete: onCompleteOne, 
+										onError: onError
+									});
+	
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: 'name: "N*"', 
+										onComplete: onCompleteTwo, 
+										onError: onError
+									});
+	
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() MultipleMixedFetch",
+	 		runTest: function(t){
+				//	summary: 
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//	description:
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//		Tests an item fetch and an identity fetch.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var done = [false, false];
+	
+				var onComplete = function(items, request){
+					done[0] = true;
+					t.assertEqual(items.length, 1);
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onItem = function(item){
+					done[1] = true;
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, "El Salvador");
+					
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: {name: "El*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() MultipleMixedFetch, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//	description:
+				//		Tests that multiple fetches at the same time queue up properly and do not clobber each other on initial load.
+				//		Tests an item fetch and an identity fetch.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var done = [false, false];
+	
+				var onComplete = function(items, request){
+					done[0] = true;
+					t.assertEqual(items.length, 1);
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onItem = function(item){
+					done[1] = true;
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertEqual(name, "El Salvador");
+					
+					if(done[0] && done[1]){
+						d.callback(true);
+					}
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				
+				//Find all items starting with A, only toplevel (root) items.
+				store.fetch({ 	query: 'name: "El*"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() deep",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of all items (including children (nested))
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of all items (including children (nested))
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 4);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, including child (nested) items.
+				store.fetch({ 	query: {name: "A*"}, 
+										onComplete: onComplete, 
+										onError: onError,
+										queryOptions: {deep:true}
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() deep, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of all items (including children (nested))
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of all items (including children (nested))
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("geography_hierarchy_small"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 4);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				//Find all items starting with A, including child (nested) items.
+				store.fetch({ 	query: 'name: "A*"', 
+										onComplete: onComplete, 
+										onError: onError,
+										queryOptions: {deep:true}
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() hierarchy off",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of all items with hierarchy disabled
+				//		This should turn off processing child objects as data store items.  It will still process
+				//		references and type maps.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of all items with hierarchy disabled
+				//		This should turn off processing child objects as data store items.  It will still process
+				//		references and type maps.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("geography_hierarchy_small"));
+				
+				//Set this as hierarchy off before fetch to make sure it traps and configs right.
+				store.hierarchical = false;
+				
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					//With hierarchy off, this should only match 2, as only two data store items
+					//will be quertied
+					t.assertEqual(2, items.length);
+					var i;
+					var passed = true;
+					for(i = 0; i < items.length; i++){
+						var countries = store.getValues(items[i], "countries");
+						if(countries){
+							var j;
+							//Make sure none of the child objects were processed into items.
+							for(j = 0; j<countries.length; j++){
+								passed = !store.isItem(countries[j]);
+								if(!passed){
+									break;
+								}
+							}
+						}
+						if(!passed){
+							break;
+						}
+					}
+					if(!passed){
+						d.errback(new Error("Located a child item with hierarchy off and no references in the data.  Error."));
+					}else{
+						d.callback(true);
+					}
+				}
+				function onError(errData, request){
+					d.errback(errData);
+				}
+				//Find all items starting with A, including child (nested) items.
+				store.fetch({ 	query: {name: "A*"}, 
+										onComplete: onComplete, 
+										onError: onError,
+										queryOptions: {deep:true}
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() hierarchy off refs still parse",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of all items with hierarchy disabled
+				//		This should turn off processing child objects as data store items.  It will still process
+				//		references and type maps.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of all items with hierarchy disabled
+				//		This should turn off processing child objects as data store items.  It will still process
+				//		references and type maps.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries_references"));
+				
+				//Set this as hierarchy off before fetch to make sure it traps and configs right.
+				store.hierarchical = false;
+				
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					//With hierarchy off, this should only match 2, as only two data store items
+					//will be quertied
+					t.assertEqual(items.length, 4);
+					var i;
+					var passed = true;
+					for(i = 0; i < items.length; i++){
+						var countries = store.getValues(items[i], "children");
+						if(countries){
+							var j;
+							//Make sure none of the child objects were processed into items.
+							for(j = 0; j<countries.length; j++){
+								passed = store.isItem(countries[j]);
+								if(!passed){
+									break;
+								}
+							}
+						}
+						if(!passed){
+							break;
+						}
+					}
+					if(!passed){
+						d.errback(new Error("Found a non-child item in a reference list in a references based input.  Error."));
+					}else{
+						d.callback(true);
+					}
+				}
+				function onError(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				}
+				//Find all items starting with A, including child (nested) items.
+				store.fetch({ 	query: {name: "A*"}, 
+										onComplete: onComplete, 
+										onError: onError,
+										queryOptions: {deep:true}
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() one_commentFilteredJson",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//		This tests loading a comment-filtered json file so that people using secure
+				//		data with this store can bypass the JavaSceipt hijack noted in Fortify's
+				//		paper.
+				if(dojo.isBrowser){
+	                var store = new dojox.data.AndOrWriteStore({url: dojo.moduleUrl("tests", "data/countries_commentFiltered.json").toString()});
+	
+					var d = new doh.Deferred();
+					var onComplete = function(items, request){
+						t.assertEqual(items.length, 1);
+						d.callback(true);
+					};
+					var onError = function(errData, request){
+						t.assertTrue(false);
+						d.errback(errData);
+					};
+					store.fetch({ 	query: {abbr: "ec"}, 
+											onComplete: onComplete, 
+											onError: onError
+										});
+					return d;
+				}
+			}
+		},
+		{
+			name: "Read API: fetch() one_commentFilteredJson, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//		This tests loading a comment-filtered json file so that people using secure
+				//		data with this store can bypass the JavaSceipt hijack noted in Fortify's
+				//		paper.
+				if(dojo.isBrowser){
+	                var store = new dojox.data.AndOrWriteStore({url: dojo.moduleUrl("tests", "data/countries_commentFiltered.json").toString()});
+	
+					var d = new doh.Deferred();
+					var onComplete = function(items, request){
+						t.assertEqual(items.length, 1);
+						d.callback(true);
+					};
+					var onError = function(errData, request){
+						t.assertTrue(false);
+						d.errback(errData);
+					};
+					store.fetch({ 	query: 'abbr: "ec"', 
+											onComplete: onComplete, 
+											onError: onError
+										});
+					return d;
+				}
+			}
+		},
+		{
+			name: "Read API: fetch() withNull",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item where some attributes are null.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item where some attributes are null.
+				//		Introduced because of tracker: #3153
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries_withNull"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(4, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {name: "E*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() withNull, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item where some attributes are null.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item where some attributes are null.
+				//		Introduced because of tracker: #3153
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries_withNull"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(4, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'name: "E*"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() all_streaming",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var count = 0;
+	
+				var onBegin = function(size, requestObj){
+					t.assertEqual(size, 7);
+				};
+				var onItem = function(item, requestObj){
+					t.assertTrue(store.isItem(item));
+					count++;
+				};
+				var onComplete = function(items, request){
+					t.assertEqual(count, 7);
+					t.assertTrue(items === null);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+	
+				//Get everything...
+				store.fetch({	onBegin: onBegin,
+										onItem: onItem, 
+										onComplete: onComplete,
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() paging",
+	 		runTest: function(t){
+				//	summary: 
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+				//	description:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+
+				var dumpSixthFetch = function(items, request){
+					t.assertEqual(items.length, 5);
+					d.callback(true);
+				};
+
+				var dumpFifthFetch = function(items, request){
+					t.assertEqual(items.length, 0);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpSixthFetch;
+					store.fetch(request);
+				};
+
+				var dumpFourthFetch = function(items, request){
+					t.assertEqual(items.length, 5);
+					request.start = 9;
+					request.count = 100;
+					request.onComplete = dumpFifthFetch;
+					store.fetch(request);
+				};
+
+				var dumpThirdFetch = function(items, request){
+					t.assertEqual(items.length, 5);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpFourthFetch;
+					store.fetch(request);
+				};
+
+				var dumpSecondFetch = function(items, request){
+					t.assertEqual(items.length, 1);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					store.fetch(request);
+				};
+
+				var dumpFirstFetch = function(items, request){
+					t.assertEqual(items.length, 5);
+					request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					store.fetch(request);
+				};
+	
+				var completed = function(items, request){
+					t.assertEqual(items.length, 7);
+					request.start = 1;
+					request.count = 5;
+					request.onComplete = dumpFirstFetch;
+					store.fetch(request);
+				};
+	
+				var error = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() with MultiType Match",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//	description:
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//		Introduced because of tracker: #4931
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("data_multitype"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(4, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {count: "1*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() with MultiType Match, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//	description:
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//		Introduced because of tracker: #4931
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("data_multitype"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(4, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'count: "1*"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() with MultiType, MultiValue Match",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//	description:
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//		Introduced because of tracker: #4931
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("data_multitype"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(7, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {value: "true"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() with MultiType, MultiValue Match, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//	description:
+				//		Simple test of a basic fetch againct an attribute that has different types for the value across items
+				//		Introduced because of tracker: #4931
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("data_multitype"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(7, items.length);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'value: "true"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: getLabel()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var label = store.getLabel(items[0]);
+					t.assertTrue(label !== null);
+					t.assertEqual("Ecuador", label);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {abbr: "ec"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: getLabel(), complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var label = store.getLabel(items[0]);
+					t.assertTrue(label !== null);
+					t.assertEqual("Ecuador", label);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'abbr: "ec"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: getLabelAttributes()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = store.getLabelAttributes(items[0]);
+					t.assertTrue(dojo.isArray(labelList));
+					t.assertEqual("name", labelList[0]);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {abbr: "ec"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: getLabelAttributes(), complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = store.getLabelAttributes(items[0]);
+					t.assertTrue(dojo.isArray(labelList));
+					t.assertEqual("name", labelList[0]);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'abbr: "ec"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: getValue()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var name = store.getValue(item,"name");
+					t.assertTrue(name === "El Salvador");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: getValues()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getValues function of the store.
+				//	description:
+				//		Simple test of the getValues function of the store.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var names = store.getValues(item,"name");
+					t.assertTrue(dojo.isArray(names));
+					t.assertEqual(names.length, 1);
+					t.assertEqual(names[0], "El Salvador");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: isItem()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the isItem function of the store
+				//	description:
+				//		Simple test of the isItem function of the store
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.isItem(item));
+					t.assertTrue(!store.isItem({}));
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: isItem() multistore",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the isItem function of the store
+				//		to verify two different store instances do not accept
+				//		items from each other.
+				//	description:
+				//		Simple test of the isItem function of the store
+				//		to verify two different store instances do not accept
+				//		items from each other.
+	
+				// Two different instances, even  if they read from the same URL 
+				// should not accept items between each other!
+				var store1 = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				var store2 = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+
+				var onItem1 = function(item1){
+					t.assertTrue(item1 !== null);
+					
+					var onItem2 = function(item2){
+						t.assertTrue(item1 !== null);
+						t.assertTrue(item2 !== null);
+						t.assertTrue(store1.isItem(item1));
+						t.assertTrue(store2.isItem(item2));
+						t.assertTrue(!store1.isItem(item2));
+						t.assertTrue(!store2.isItem(item1));
+						d.callback(true);
+					};
+					store2.fetchItemByIdentity({identity: "sv", onItem: onItem2, onError: onError});
+	
+				};
+				store1.fetchItemByIdentity({identity: "sv", onItem: onItem1, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: hasAttribute()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the hasAttribute function of the store
+				//	description:
+				//		Simple test of the hasAttribute function of the store
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.hasAttribute(item, "abbr"));
+					t.assertTrue(!store.hasAttribute(item, "abbr_not"));
+	
+					//Test that null attributes throw an exception
+					var passed = false;
+					try{
+						store.hasAttribute(item, null);
+					}catch (e){
+						passed = true;
+					}
+					t.assertTrue(passed);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: containsValue()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the containsValue function of the store
+				//	description:
+				//		Simple test of the containsValue function of the store
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.containsValue(item, "abbr", "sv"));
+					t.assertTrue(!store.containsValue(item, "abbr", "sv1"));
+					t.assertTrue(!store.containsValue(item, "abbr", null));
+	
+					//Test that null attributes throw an exception
+					var passed = false;
+					try{
+						store.containsValue(item, null, "foo");
+					}catch (e){
+						passed = true;
+					}
+					t.assertTrue(passed);
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: getAttributes()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getAttributes function of the store
+				//	description:
+				//		Simple test of the getAttributes function of the store
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					t.assertTrue(store.isItem(item));
+	
+					var attributes = store.getAttributes(item);
+					t.assertEqual(attributes.length, 3);
+					for(var i = 0; i < attributes.length; i++){
+						t.assertTrue((attributes[i] === "name" || attributes[i] === "abbr" || attributes[i] === "capital"));
+					}
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity: "sv", onItem: onItem, onError: onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: getFeatures()",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the getFeatures function of the store
+				//	description:
+				//		Simple test of the getFeatures function of the store
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var features = store.getFeatures();
+				t.assertTrue(features["dojo.data.api.Read"] !== null);
+				t.assertTrue(features["dojo.data.api.Identity"] !== null);
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch0",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of everything starting with lowercase e
+				//	description:
+				//		Function to test pattern matching of everything starting with lowercase e
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var completed = function(items, request) {
+					t.assertEqual(items.length, 5);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "abbr");
+						if(!(value === "ec" || value === "eg" || value === "er" || value === "ee" || value === "et")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected abbreviation found, match failure."));
+					}
+				};
+				var error = function(error, request) {
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: {abbr: "e*"}, onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch0, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of everything starting with lowercase e
+				//	description:
+				//		Function to test pattern matching of everything starting with lowercase e
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var completed = function(items, request) {
+					t.assertEqual(items.length, 5);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "abbr");
+						if(!(value === "ec" || value === "eg" || value === "er" || value === "ee" || value === "et")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected abbreviation found, match failure."));
+					}
+				};
+				var error = function(error, request) {
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: 'abbr: "e*"', onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch1",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of everything with $ in it.
+				//	description:
+				//		Function to test pattern matching of everything with $ in it.
+	
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"boomBam"},
+													   {uniqueId: 4, value:"bit$Bite"},
+													   {uniqueId: 5, value:"ouagadogou"},
+													   {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 8, value:"seaweed"},
+													   {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 2);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bit$Bite" || value === "jfq4@#!$!@Rf14r14i5u")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: {value: "*$*"}, onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch1, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of everything with $ in it.
+				//	description:
+				//		Function to test pattern matching of everything with $ in it.
+	
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"boomBam"},
+													   {uniqueId: 4, value:"bit$Bite"},
+													   {uniqueId: 5, value:"ouagadogou"},
+													   {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 8, value:"seaweed"},
+													   {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 2);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bit$Bite" || value === "jfq4@#!$!@Rf14r14i5u")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: 'value: "*$*"', onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch2",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test exact pattern match
+				//	description:
+				//		Function to test exact pattern match
+	
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"boomBam"},
+													   {uniqueId: 4, value:"bit$Bite"},
+													   {uniqueId: 5, value:"ouagadogou"},
+													   {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 8, value:"seaweed"},
+													   {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+													 ]
+											}
+									 });
+	
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 1);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected abbreviation found, match failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: {value: "bar\\*foo"}, onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch2, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test exact pattern match
+				//	description:
+				//		Function to test exact pattern match
+	
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"boomBam"},
+													   {uniqueId: 4, value:"bit$Bite"},
+													   {uniqueId: 5, value:"ouagadogou"},
+													   {uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 8, value:"seaweed"},
+													   {uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+													 ]
+											}
+									 });
+	
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 1);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected abbreviation found, match failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: 'value: "bar\\*foo"', onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch_caseSensitive",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of a pattern case-sensitively
+				//	description:
+				//		Function to test pattern matching of a pattern case-sensitively
+	
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"BAR*foo"},
+													   {uniqueId: 4, value:"BARBananafoo"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(1, items.length);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: {value: "bar\\*foo"}, queryOptions: {ignoreCase: false} , onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch_caseSensitive, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of a pattern case-sensitively
+				//	description:
+				//		Function to test pattern matching of a pattern case-sensitively
+	
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"BAR*foo"},
+													   {uniqueId: 4, value:"BARBananafoo"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(1, items.length);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: 'value: "bar\\*foo"', queryOptions: {ignoreCase: false} , onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch_caseInsensitive",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of a pattern case-insensitively
+				//	description:
+				//		Function to test pattern matching of a pattern case-insensitively
+	
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"BAR*foo"},
+													   {uniqueId: 4, value:"BARBananafoo"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 2);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "BAR*foo" || value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: {value: "bar\\*foo"}, queryOptions: {ignoreCase: true}, onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() patternMatch_caseInsensitive, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test pattern matching of a pattern case-insensitively
+				//	description:
+				//		Function to test pattern matching of a pattern case-insensitively
+	
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 1, value:"foo*bar"},
+													   {uniqueId: 2, value:"bar*foo"}, 
+													   {uniqueId: 3, value:"BAR*foo"},
+													   {uniqueId: 4, value:"BARBananafoo"}
+													 ]
+											}
+									 });
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 2);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(value === "BAR*foo" || value === "bar*foo")){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected pattern matched.  Filter failure."));
+					}
+				};
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+				store.fetch({query: 'value: "bar\\*foo"', queryOptions: {ignoreCase: true}, onComplete: completed, onError: error});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortNumeric",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting numerically.
+				//	description:
+				//		Function to test sorting numerically.
+				
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+													   {uniqueId: 1, value:"ba|r*foo"}, 
+													   {uniqueId: 2, value:"boomBam"},
+													   {uniqueId: 3, value:"bit$Bite"},
+													   {uniqueId: 4, value:"ouagadogou"},
+													   {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+													   {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 9, value:"seaweed"},
+													   {uniqueId: 10, value:"zulu"},
+													   {uniqueId: 8, value:"seaweed"}
+													 ]
+											}
+									 });
+	
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "uniqueId") === i)){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+	
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+	
+				var sortAttributes = [{attribute: "uniqueId"}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortNumericDescending",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting numerically.
+				//	description:
+				//		Function to test sorting numerically.
+	
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												  items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+													   {uniqueId: 1, value:"ba|r*foo"}, 
+													   {uniqueId: 2, value:"boomBam"},
+													   {uniqueId: 3, value:"bit$Bite"},
+													   {uniqueId: 4, value:"ouagadogou"},
+													   {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+													   {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+													   {uniqueId: 7, value:"squawl"},
+													   {uniqueId: 9, value:"seaweed"},
+													   {uniqueId: 10, value:"zulu"},
+													   {uniqueId: 8, value:"seaweed"}
+													 ]
+											}
+									 });
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!((items.length - (store.getValue(items[i], "uniqueId") + 1)) === i)){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+	
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+	
+				var sortAttributes = [{attribute: "uniqueId", descending: true}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortNumericWithCount",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting numerically in descending order, returning only a specified number of them.
+				//	description:
+				//		Function to test sorting numerically in descending order, returning only a specified number of them.
+			
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value:"fo|o*b.ar"},
+													  {uniqueId: 1, value:"ba|r*foo"}, 
+													  {uniqueId: 2, value:"boomBam"},
+													  {uniqueId: 3, value:"bit$Bite"},
+													  {uniqueId: 4, value:"ouagadogou"},
+													  {uniqueId: 5, value:"jfq4@#!$!@|f1.$4r14i5u"},
+													  {uniqueId: 6, value:"BaB{aMa|SaRa***F}oo"},
+													  {uniqueId: 7, value:"squawl"},
+													  {uniqueId: 9, value:"seaweed"},
+													  {uniqueId: 10, value:"zulu"},
+													  {uniqueId: 8, value:"seaweed"}
+													]
+										   }
+									});
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					t.assertEqual(items.length, 5);
+					var itemId = 10;
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "uniqueId") === itemId)){
+							passed=false;
+							break;
+						}
+						itemId--; // Decrement the item id.  We are descending sorted, so it should go 10, 9, 8, etc.
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+				 
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "uniqueId", descending: true}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes, count: 5});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortAlphabetic",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting alphabetic ordering.
+				//	description:
+				//		Function to test sorting alphabetic ordering.
+			
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value:"abc"},
+													  {uniqueId: 1, value:"bca"}, 
+													  {uniqueId: 2, value:"abcd"},
+													  {uniqueId: 3, value:"abcdefg"},
+													  {uniqueId: 4, value:"lmnop"},
+													  {uniqueId: 5, value:"foghorn"},
+													  {uniqueId: 6, value:"qberty"},
+													  {uniqueId: 7, value:"qwerty"},
+													  {uniqueId: 8, value:""},
+													  {uniqueId: 9, value:"seaweed"},
+													  {uniqueId: 10, value:"123abc"}
+			
+													]
+										   }
+									});
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					//Output should be in this order...
+					var orderedArray = [ 	"",
+											"123abc",
+											"abc",
+											"abcd",
+											"abcdefg",
+											"bca",
+											"foghorn",
+											"lmnop",
+											"qberty",
+											"qwerty",
+											"seaweed"
+						];
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "value") === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request) {
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "value"}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortAlphabeticDescending",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting alphabetic ordering in descending mode.
+				//	description:
+				//		Function to test sorting alphabetic ordering in descending mode.
+			
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value:"abc"},
+													  {uniqueId: 1, value:"bca"}, 
+													  {uniqueId: 2, value:"abcd"},
+													  {uniqueId: 3, value:"abcdefg"},
+													  {uniqueId: 4, value:"lmnop"},
+													  {uniqueId: 5, value:"foghorn"},
+													  {uniqueId: 6, value:"qberty"},
+													  {uniqueId: 7, value:"qwerty"},
+													  {uniqueId: 8, value:""},
+													  {uniqueId: 9, value:"seaweed"},
+													  {uniqueId: 10, value:"123abc"}
+			
+													]
+										   }
+									});
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					//Output should be in this order...
+					var orderedArray = [ 	"",
+											"123abc",
+											"abc",
+											"abcd",
+											"abcdefg",
+											"bca",
+											"foghorn",
+											"lmnop",
+											"qberty",
+											"qwerty",
+											"seaweed"
+						];
+					orderedArray = orderedArray.reverse();
+					t.assertEqual(items.length, 11);
+	
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "value") === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request) {
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "value", descending: true}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortDate",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting date.
+				//	description:
+				//		Function to test sorting date.
+			
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value: new Date(0)},
+													  {uniqueId: 1, value: new Date(100)}, 
+													  {uniqueId: 2, value:new Date(1000)},
+													  {uniqueId: 3, value:new Date(2000)},
+													  {uniqueId: 4, value:new Date(3000)},
+													  {uniqueId: 5, value:new Date(4000)},
+													  {uniqueId: 6, value:new Date(5000)},
+													  {uniqueId: 7, value:new Date(6000)},
+													  {uniqueId: 8, value:new Date(7000)},
+													  {uniqueId: 9, value:new Date(8000)},
+													  {uniqueId: 10, value:new Date(9000)}
+			
+													]
+										   }
+									});
+				
+				var d = new doh.Deferred();
+				var completed = function(items,request){
+					var orderedArray =	[0,100,1000,2000,3000,4000,5000,6000,7000,8000,9000];
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "value").getTime() === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "value"}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortDateDescending",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting date in descending order.
+				//	description:
+				//		Function to test sorting date in descending order.
+			
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value: new Date(0)},
+													  {uniqueId: 1, value: new Date(100)}, 
+													  {uniqueId: 2, value:new Date(1000)},
+													  {uniqueId: 3, value:new Date(2000)},
+													  {uniqueId: 4, value:new Date(3000)},
+													  {uniqueId: 5, value:new Date(4000)},
+													  {uniqueId: 6, value:new Date(5000)},
+													  {uniqueId: 7, value:new Date(6000)},
+													  {uniqueId: 8, value:new Date(7000)},
+													  {uniqueId: 9, value:new Date(8000)},
+													  {uniqueId: 10, value:new Date(9000)}
+			
+													]
+										   }
+									});
+			
+				var d = new doh.Deferred();
+				var completed = function(items,request){
+					var orderedArray =	[0,100,1000,2000,3000,4000,5000,6000,7000,8000,9000];
+					orderedArray = orderedArray.reverse();
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "value").getTime() === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "value", descending: true}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortMultiple",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting on multiple attributes.
+				//	description:
+				//		Function to test sorting on multiple attributes.
+				
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 1, value:"fo|o*b.ar"},
+													  {uniqueId: 2, value:"ba|r*foo"}, 
+													  {uniqueId: 3, value:"boomBam"},
+													  {uniqueId: 4, value:"bit$Bite"},
+													  {uniqueId: 5, value:"ouagadogou"},
+													  {uniqueId: 6, value:"jfq4@#!$!@|f1.$4r14i5u"},
+													  {uniqueId: 7, value:"BaB{aMa|SaRa***F}oo"},
+													  {uniqueId: 8, value:"squawl"},
+													  {uniqueId: 10, value:"seaweed"},
+													  {uniqueId: 12, value:"seaweed"},
+													  {uniqueId: 11, value:"zulu"},
+													  {uniqueId: 9, value:"seaweed"}
+													]
+										   }
+									});
+			
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					var orderedArray0 = [7,2,4,3,1,6,5,12,10,9,8,11];
+					var orderedArray1 = [	"BaB{aMa|SaRa***F}oo",
+											"ba|r*foo",
+											"bit$Bite",
+											"boomBam",
+											"fo|o*b.ar",
+											"jfq4@#!$!@|f1.$4r14i5u",
+											"ouagadogou",
+											"seaweed",
+											"seaweed",
+											"seaweed",
+											"squawl",
+											"zulu"
+										];
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(	(store.getValue(items[i], "uniqueId") === orderedArray0[i])&&
+								(store.getValue(items[i], "value") === orderedArray1[i]))
+							){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{ attribute: "value"}, { attribute: "uniqueId", descending: true}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortMultipleSpecialComparator",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting on multiple attributes with a custom comparator.
+				//	description:
+				//		Function to test sorting on multiple attributes with a custom comparator.
+	
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 1, status:"CLOSED"},
+													  {uniqueId: 2,  status:"OPEN"}, 
+													  {uniqueId: 3,  status:"PENDING"},
+													  {uniqueId: 4,  status:"BLOCKED"},
+													  {uniqueId: 5,  status:"CLOSED"},
+													  {uniqueId: 6,  status:"OPEN"},
+													  {uniqueId: 7,  status:"PENDING"},
+													  {uniqueId: 8,  status:"PENDING"},
+													  {uniqueId: 10, status:"BLOCKED"},
+													  {uniqueId: 12, status:"BLOCKED"},
+													  {uniqueId: 11, status:"OPEN"},
+													  {uniqueId: 9,  status:"CLOSED"}
+													]
+										   }
+									});
+			
+			
+				store.comparatorMap = {};
+				store.comparatorMap["status"] = function(a,b) { 
+					var ret = 0;
+					// We want to map these by what the priority of these items are, not by alphabetical.
+					// So, custom comparator.
+					var enumMap = { OPEN: 3, BLOCKED: 2, PENDING: 1, CLOSED: 0};
+					if (enumMap[a] > enumMap[b]) {
+						ret = 1;
+					}
+					if (enumMap[a] < enumMap[b]) {
+						ret = -1;
+					}
+					return ret;
+				};
+			
+				var sortAttributes = [{attribute: "status", descending: true}, { attribute: "uniqueId", descending: true}];
+			
+				var d = new doh.Deferred();
+				var completed = function(items, findResult){
+					var orderedArray = [11,6,2,12,10,4,8,7,3,9,5,1];
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						var value = store.getValue(items[i], "value");
+						if(!(store.getValue(items[i], "uniqueId") === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() sortAlphabeticWithUndefined",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test sorting alphabetic ordering.
+				//	description:
+				//		Function to test sorting alphabetic ordering.
+			
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+												 items: [ {uniqueId: 0, value:"abc"},
+													  {uniqueId: 1, value:"bca"}, 
+													  {uniqueId: 2, value:"abcd"},
+													  {uniqueId: 3, value:"abcdefg"},
+													  {uniqueId: 4, value:"lmnop"},
+													  {uniqueId: 5, value:"foghorn"},
+													  {uniqueId: 6, value:"qberty"},
+													  {uniqueId: 7, value:"qwerty"},
+													  {uniqueId: 8 },  //Deliberate undefined value
+													  {uniqueId: 9, value:"seaweed"},
+													  {uniqueId: 10, value:"123abc"}
+			
+													]
+										   }
+									});
+				
+				var d = new doh.Deferred();
+				var completed = function(items, request){
+					//Output should be in this order...
+					var orderedArray = [10,0,2,3,1,5,4,6,7,9,8];
+					t.assertEqual(items.length, 11);
+					var passed = true;
+					for(var i = 0; i < items.length; i++){
+						if(!(store.getValue(items[i], "uniqueId") === orderedArray[i])){
+							passed=false;
+							break;
+						}
+					}
+					t.assertTrue(passed);
+					if (passed){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected sorting order found, sort failure."));
+					}
+				};
+			
+				var error = function(error, request) {
+					t.assertTrue(false);
+					d.errback(error);
+				};
+			
+				var sortAttributes = [{attribute: "value"}];
+				store.fetch({onComplete: completed, onError: error, sort: sortAttributes});
+				return d;
+			}
+		},
+		{
+			name: "Read API: errorCondition_idCollision_inMemory",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the errors thrown when there is an id collision in the data.
+				//		Added because of tracker: #2546
+				//	description:
+				//		Simple test of the errors thrown when there is an id collision in the data.
+				//		Added because of tracker: #2546
+	
+				var store = new dojox.data.AndOrWriteStore({	data: { identifier: "uniqueId", 
+																	items: [{uniqueId: 12345, value:"foo"},
+																			{uniqueId: 123456, value:"bar"}, 
+																			{uniqueId: 12345, value:"boom"},
+																			{uniqueId: 123457, value:"bit"}
+																		]
+																	}
+																});
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					//This is bad if this fires, this case should fail and not call onComplete.
+					t.assertTrue(false);
+					d.callback(false);
+				};
+			
+				var reportError = function(errData, request){
+					//This is good if this fires, it is expected.
+					t.assertTrue(true);
+					d.callback(true);
+				};
+				store.fetch({onComplete: onComplete, onError: reportError});
+				return d;
+			}
+		},
+		{
+			name: "Read API: errorCondition_idCollision_xhr",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of the errors thrown when there is an id collision in the data.
+				//		Added because of tracker: #2546
+				//	description:
+				//		Simple test of the errors thrown when there is an id collision in the data.
+				//		Added because of tracker: #2546
+	
+				if(dojo.isBrowser){
+					var store = new dojox.data.AndOrWriteStore({url: dojo.moduleUrl("tests", "data/countries_idcollision.json").toString() });
+					var d = new doh.Deferred();
+					var onComplete = function(items, request){
+						//This is bad if this fires, this case should fail and not call onComplete.
+						t.assertTrue(false);
+						d.callback(false);
+					};
+	
+					var reportError = function(errData, request){
+						//This is good if this fires, it is expected.
+						t.assertTrue(true);
+						d.callback(true);
+					};
+					store.fetch({onComplete: onComplete, onError: reportError});
+					return d;
+				}
+			}
+		},
+		{
+			name: "Read API: Date_datatype",
+	 		runTest: function(t){
+				//var store = new dojox.data.AndOrWriteStore(tests.data.readOnlyItemFileTestTemplates.testFile["countries_withDates"]);
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries_withDates"));
+				
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var independenceDate = store.getValue(item, "independence");
+					t.assertTrue(independenceDate instanceof Date);
+					//Check to see if the value was deserialized properly.  Since the store stores in UTC/GMT, it 
+					//should also be compared in the UTC/GMT mode
+					t.assertTrue(dojo.date.stamp.toISOString(independenceDate, {zulu:true}) === "1993-05-24T00:00:00Z");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity:"er", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: custom_datatype_Color_SimpleMapping",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test using literal values with custom datatypes
+				var dataset = {
+					identifier:'name',
+					items: [
+						{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+						{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+					]
+				};
+				var store = new dojox.data.AndOrWriteStore({
+						data:dataset,
+						typeMap:{'Color': dojo.Color}
+				});
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var beaker = item;
+					var hairColor = store.getValue(beaker, "hairColor");
+					t.assertTrue(hairColor instanceof dojo.Color);
+					t.assertTrue(hairColor.toHex() == "#ff0000");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity:"Beaker", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: custom_datatype_Color_GeneralMapping",
+	 		runTest: function(t){
+				//	summary: 
+				//		Function to test using literal values with custom datatypes
+				var dataset = {
+					identifier:'name',
+					items: [
+						{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+						{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+					]
+				};
+				var store = new dojox.data.AndOrWriteStore({
+						data:dataset,
+						typeMap:{'Color': 	{	
+												type: dojo.Color,
+												deserialize: function(value){
+													return new dojo.Color(value);
+												}
+											}
+								}
+				});
+				var d = new doh.Deferred();
+				var onItem = function(item){
+					t.assertTrue(item !== null);
+					var beaker = item;
+					var hairColor = store.getValue(beaker, "hairColor");
+					t.assertTrue(hairColor instanceof dojo.Color);
+					t.assertTrue(hairColor.toHex() == "#ff0000");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					d.errback(errData);
+				};
+				store.fetchItemByIdentity({identity:"Beaker", onItem:onItem, onError:onError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: hierarchical_data",
+	 		runTest: function(t){
+				//var store = new dojox.data.AndOrWriteStore(tests.data.readOnlyItemFileTestTemplates.testFile["geography_hierarchy_small"]);
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("geography_hierarchy_small"));
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var northAmerica = items[0];
+					var canada = store.getValue(northAmerica, "countries");
+					var toronto = store.getValue(canada, "cities");
+					t.assertEqual(store.getValue(canada, "name"), "Canada");
+					t.assertEqual(store.getValue(toronto, "name"), "Toronto");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					d.errback(errData);
+				};
+				store.fetch({
+					query: {name: "North America"},
+					onComplete: onComplete,
+					onError: onError
+				});
+				
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: hierarchical_data, complex",
+	 		runTest: function(t){
+				//var store = new dojox.data.AndOrWriteStore(tests.data.readOnlyItemFileTestTemplates.testFile["geography_hierarchy_small"]);
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("geography_hierarchy_small"));
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var northAmerica = items[0];
+					var canada = store.getValue(northAmerica, "countries");
+					var toronto = store.getValue(canada, "cities");
+					t.assertEqual(store.getValue(canada, "name"), "Canada");
+					t.assertEqual(store.getValue(toronto, "name"), "Toronto");
+					d.callback(true);
+				};
+				var onError = function(errData){
+					d.errback(errData);
+				};
+				store.fetch({
+					query: 'name: "North America"',
+					onComplete: onComplete,
+					onError: onError
+				});
+				
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: no_identifier_specified",
+	 		runTest: function(t){
+				var arrayOfItems = [
+					{name:"Kermit", color:"green"},
+					{name:"Miss Piggy", likes:"Kermit"}, 
+					{name:"Beaker", hairColor:"red"}
+				];
+				var store = new dojox.data.AndOrWriteStore({data:{items:arrayOfItems}});
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					var features = store.getFeatures();
+					var hasIdentityFeature = Boolean(features['dojo.data.api.Identity']);
+					t.assertTrue(hasIdentityFeature);
+					for(var i = 0; i < items.length; ++i){
+						var item = items[i];
+						var identifier = store.getIdentityAttributes(item);
+						t.assertTrue(identifier === null);
+						var identity = store.getIdentity(item);
+						t.assertTrue(typeof identity == "number");
+					}
+					d.callback(true);
+				};
+				var reportError = function(errData, request){
+					d.errback(true);
+				};
+				store.fetch({onComplete: onComplete, onError: reportError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Identity API: hierarchical_data",
+	 		runTest: function(t){
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("geography_hierarchy_small"));
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					var features = store.getFeatures();
+					var hasIdentityFeature = Boolean(features['dojo.data.api.Identity']);
+					t.assertTrue(hasIdentityFeature);
+					for(var i = 0; i < items.length; ++i){
+						var item = items[i];
+						var identifier = store.getIdentityAttributes(item);
+						t.assertTrue(identifier === null);
+						var identity = store.getIdentity(item);
+						t.assertTrue(typeof identity == "number");
+					}
+					d.callback(true);
+				};
+				var reportError = function(errData, request){
+					d.errback(true);
+				};
+				store.fetch({onComplete: onComplete, onError: reportError});
+				return d; // Deferred
+			}
+		},
+		{
+			name: "Read API: functionConformance",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+				//	description:
+				//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+				var testStore = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				var readApi = new dojo.data.api.Read();
+				var passed = true;
+	
+				for(var i in readApi){
+					if(i.toString().charAt(0) !== '_')
+					{
+						var member = readApi[i];
+						//Check that all the 'Read' defined functions exist on the test store.
+						if(typeof member === "function"){
+							var testStoreMember = testStore[i];
+							if(!(typeof testStoreMember === "function")){
+								passed = false;
+								break;
+							}
+						}
+					}
+				}
+				t.assertTrue(passed);
+			}
+		},
+		{
+			name: "Identity API: functionConformance",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+				//	description:
+				//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+				var testStore = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				var identityApi = new dojo.data.api.Identity();
+				var passed = true;
+	
+				for(var i in identityApi){
+	
+					if(i.toString().charAt(0) !== '_')
+					{
+						var member = identityApi[i];
+						//Check that all the 'Read' defined functions exist on the test store.
+						if(typeof member === "function"){
+							var testStoreMember = testStore[i];
+							if(!(typeof testStoreMember === "function")){
+								passed = false;
+								break;
+							}
+						}
+					}
+				}
+				t.assertTrue(passed);
+			}
+		},
+		//complex parallels of existing simple queries immediately follow them above.  can search on "complex"
+		//below are complex queries.
+		{
+			name: "Read API: fetch() multiple, OR, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 3);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'abbr: "s*" || capital:"A*"', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() multiple, AND(OR, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 3);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: 'abbr: "e*" AND (capital:"A*" or capital: "Q*")', 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() multiple, AND/OR, as json object, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 3);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {complexQuery:'abbr: "e*" AND (capital:"A*" or capital: "Q*")'}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() multiple, AND/OR, as json object, complex, with extra attrs",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {complexQuery:'abbr: "e*" AND (capital:"A*" or capital: "Q*")', name: "Ec*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() multiple, AND/OR, as json object, complex, with extra attrs and spaces",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					try{
+						t.assertEqual(items.length, 1);
+						t.assertEqual("Equatorial Guinea", store.getValue(items[0], "name"));
+						d.callback(true);
+					}catch(e){
+						d.errback(e);
+					}
+				};
+				var onError = function(errData, request){
+					d.errback(errData);
+				};
+				store.fetch({ 	query: {complexQuery:'abbr: "g*" AND (capital:"A*" or capital: "M*")', name: "Equatorial G*"}, 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: fetch() multiple, AND/OR, as quoted json object, complex",
+	 		runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AndOrWriteStore of a single item.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(items.length, 3);
+					d.callback(true);
+				};
+				var onError = function(errData, request){
+					t.assertTrue(false);
+					d.errback(errData);
+				};
+				store.fetch({ 	query: "{complexQuery:'abbr: \"e*\" AND (capital:\"A*\" or capital: \"Q*\")'}", 
+										onComplete: onComplete, 
+										onError: onError
+									});
+				return d;
+			}
+		},
+		{
+			name: "Read API: close (clearOnClose: true, reset url.)",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+				if (dojo.isBrowser) {
+					var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+					store.clearOnClose = true;
+					store.urlPreventCache = true;
+	
+					var d = new doh.Deferred();
+					function onItem(item){
+						var error = null;
+						try {
+							t.assertTrue(item !== null);
+							var ec = item;
+							var val = store.getValue(ec, "name");
+							t.assertEqual("Ecuador", val);
+	
+							store.close();
+							//Check some internals here.  Do not normally access these!
+							t.assertTrue(store._arrayOfAllItems.length === 0);
+							t.assertTrue(store._loadFinished === false);
+							
+							store.url = dojo.moduleUrl("dojox", "data/tests/stores/countries_withNull.json").toString()
+							function onItem2 (item){
+								var err;
+								try{
+									t.assertTrue(item !== null);
+									var val = store.getValue(item, "name");
+									t.assertEqual(null, val);
+								}catch(e){
+									err = e;
+								}
+								if(err){
+									d.errback(err);
+								}else{
+									d.callback(true);
+								}
+							}
+							store.fetchItemByIdentity({identity:"ec", onItem:onItem2, onError:onError});
+						}catch (e){
+							error = e;
+						}
+						if (error) {
+							d.errback(error);
+						}
+					}
+					function onError(errData){
+						d.errback(errData);
+					}
+					store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+					return d; // Deferred
+				}
+			}
+		},
+		{
+			name: "Read API: fetch, close (clearOnClose: true, reset url.)",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+				if (dojo.isBrowser) {
+					var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+					store.clearOnClose = true;
+					store.urlPreventCache = true;
+	
+					var d = new doh.Deferred();
+					function onItem(item){
+						var error = null;
+						try {
+							t.assertTrue(item !== null);
+							var ec = item;
+							var val = store.getValue(ec, "name");
+							t.assertEqual("Ecuador", val);
+	
+							store.close();
+							//Check some internals here.  Do not normally access these!
+							t.assertTrue(store._arrayOfAllItems.length === 0);
+							t.assertTrue(store._loadFinished === false);
+							
+							store.url = dojo.moduleUrl("dojox", "data/tests/stores/countries_withNull.json").toString()
+							function onComplete (items){
+								var err;
+								try{
+									t.assertEqual(1, items.length);
+									var item = items[0];
+									t.assertTrue(item !== null);
+									var val = store.getValue(item, "name");
+									t.assertEqual(null, val);
+								}catch(e){
+									err = e;
+								}
+								if(err){
+									d.errback(err);
+								}else{
+									d.callback(true);
+								}
+							}
+							store.fetch({query: {abbr:"ec"}, onComplete:onComplete, onError:onError});
+						}catch (e){
+							error = e;
+						}
+						if (error) {
+							d.errback(error);
+						}
+					}
+					function onError(errData){
+						d.errback(errData);
+					}
+					store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+					return d; // Deferred
+				}
+			}
+		},
+		{
+			name: "Read API: close (clearOnClose: true, reset _jsonFileUrl.)",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test the close api properly clears the store for reload when clearOnClose is set.
+				if (dojo.isBrowser) {
+					var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+					store.clearOnClose = true;
+					store.urlPreventCache = true;
+	
+					var d = new doh.Deferred();
+					function onItem(item){
+						var error = null;
+						try {
+							t.assertTrue(item !== null);
+							var ec = item;
+							var val = store.getValue(ec, "name");
+							t.assertEqual("Ecuador", val);
+	
+							store.close();
+							//Check some internals here.  Do not normally access these!
+							t.assertTrue(store._arrayOfAllItems.length === 0);
+							t.assertTrue(store._loadFinished === false);
+							
+							store._jsonFileUrl = dojo.moduleUrl("dojox", "data/tests/stores/countries_withNull.json").toString()
+							function onItem2 (item){
+								var err;
+								try{
+									t.assertTrue(item !== null);
+									var val = store.getValue(item, "name");
+									t.assertEqual(null, val);
+								}catch(e){
+									err = e;
+								}
+								if(err){
+									d.errback(err);
+								}else{
+									d.callback(true);
+								}
+							}
+							store.fetchItemByIdentity({identity:"ec", onItem:onItem2, onError:onError});
+						}catch (e){
+							error = e;
+						}
+						if (error) {
+							d.errback(error);
+						}
+					}
+					function onError(errData){
+						d.errback(errData);
+					}
+					store.fetchItemByIdentity({identity:"ec", onItem:onItem, onError:onError});
+					return d; // Deferred
+				}
+			}
+		},
+		{
+			name: "Read API: close (clearOnClose: true, reset data.)",
+			runTest: function(t){
+				//	summary: 
+				//		Function to test that clear on close and reset of data works.
+				//	description:
+				//		Function to test that clear on close and reset of data works.
+				var store = new dojox.data.AndOrWriteStore({data: { identifier: "uniqueId", 
+						items: [ {uniqueId: 1, value:"foo*bar"},
+							{uniqueId: 2, value:"bar*foo"}, 
+							{uniqueId: 3, value:"boomBam"},
+							{uniqueId: 4, value:"bit$Bite"},
+							{uniqueId: 5, value:"ouagadogou"},
+							{uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+							{uniqueId: 7, value:"squawl"},
+							{uniqueId: 8, value:"seaweed"},
+							{uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+						]
+					}
+				});
+	
+				var d = new doh.Deferred();
+				var firstComplete = function(items, request){
+					t.assertEqual(items.length, 1);
+					var firstItem = items[0];
+	
+					//Set the store clearing options and the new data
+					store.clearOnClose = true;
+					store.data = { identifier: "uniqueId", 
+						items: [ {uniqueId: 1, value:"foo*bar"},
+							{uniqueId: 2, value:"bar*foo"}, 
+							{uniqueId: 3, value:"boomBam"},
+							{uniqueId: 4, value:"bit$Bite"},
+							{uniqueId: 5, value:"ouagadogou"},
+							{uniqueId: 6, value:"BaBaMaSaRa***Foo"},
+							{uniqueId: 7, value:"squawl"},
+							{uniqueId: 8, value:"seaweed"},
+							{uniqueId: 9, value:"jfq4@#!$!@Rf14r14i5u"}
+						]
+					};
+					store.close();
+	
+					//Do the next fetch and verify that the next item you get is not
+					//a reference to the same item (data cleared and reloaded.
+					var secondComplete = function(items, request){
+						try{
+							t.assertEqual(items.length, 1);
+							var secondItem = items[0];
+							t.assertTrue(firstItem != null);
+							t.assertTrue(secondItem != null);
+							t.assertTrue(firstItem != secondItem);
+							d.callback(true);
+						}catch(e){
+							d.errback(e);
+						}
+					}
+					store.fetch({query: {value: "bar\*foo"}, onComplete: secondComplete, onError: error});
+				}
+				function error(error, request){
+					t.assertTrue(false);
+					d.errback(error);
+				}
+				store.fetch({query: {value: "bar\*foo"}, onComplete: firstComplete, onError: error});
+				return d;
+			}
+		},
+		
+		//write tests follow.
+		{
+			name: "Write API:  getFeatures",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getFeatures function of the store
+				//	description:
+				//		Simple test of the getFeatures function of the store
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var features = store.getFeatures(); 
+	
+				// make sure we have the expected features:
+				t.assertTrue(features["dojo.data.api.Read"] !== null);
+				t.assertTrue(features["dojo.data.api.Identity"] !== null);
+				t.assertTrue(features["dojo.data.api.Write"] !== null);
+				t.assertTrue(features["dojo.data.api.Notification"] !== null);
+				t.assertFalse(features["iggy"]);
+				
+				// and only the expected features:
+				var count = 0;
+				for(var i in features){
+					t.assertTrue((i === "dojo.data.api.Read" || 
+						i === "dojo.data.api.Identity" || 
+						i === "dojo.data.api.Write" || 
+						i === "dojo.data.api.Notification"));
+					count++;
+				}
+				t.assertEqual(count, 4);
+			}
+		},
+		{
+			name: "Write API:  setValue",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the setValue API
+				//	description:
+				//		Simple test of the setValue API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item, "capital", "Cairo"));
+					
+					// FIXME:  
+					//    Okay, so this seems very odd.  Maybe I'm just being dense.
+					//    These tests works:
+					t.assertEqual(store.isDirty(item), false);
+					t.assertTrue(store.isDirty(item) === false);
+					//    But these seemingly equivalent tests will not work:
+					// t.assertFalse(store.isDirty(item));
+					// t.assertTrue(!(store.isDirty(item)));
+					//   
+					//    All of which seems especially weird, given that this *does* work:
+					t.assertFalse(store.isDirty());
+					
+					
+					t.assertTrue(store.isDirty(item) === false);
+					t.assertTrue(!store.isDirty());
+					store.setValue(item, "capital", "New Cairo");
+					t.assertTrue(store.isDirty(item));
+					t.assertTrue(store.isDirty());
+					t.assertEqual(store.getValue(item, "capital").toString(), "New Cairo");
+					d.callback(true);
+				};
+				var onError = function(error, request){
+					d.errback(error);
+				};
+				store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: setValues",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the setValues API
+				//	description:
+				//		Simple test of the setValues API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onComplete = function(items, request){
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item, "name", "Egypt"));
+					t.assertTrue(store.isDirty(item) === false);
+					t.assertTrue(!store.isDirty());
+					store.setValues(item, "name", ["Egypt 1", "Egypt 2"]);
+					t.assertTrue(store.isDirty(item));
+					t.assertTrue(store.isDirty());
+					var values = store.getValues(item, "name");
+					t.assertTrue(values[0] == "Egypt 1");
+					t.assertTrue(values[1] == "Egypt 2");
+					d.callback(true);
+				};
+				var onError = function(error, request){
+					d.errback(error);
+				};
+				store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: unsetAttribute",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the unsetAttribute API
+				//	description:
+				//		Simple test of the unsetAttribute API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onComplete = function(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item, "name", "Egypt"));
+					t.assertTrue(store.isDirty(item) === false);
+					t.assertTrue(!store.isDirty());
+					store.unsetAttribute(item, "name");
+					t.assertTrue(store.isDirty(item));
+					t.assertTrue(store.isDirty());
+					t.assertTrue(!store.hasAttribute(item, "name"));
+					d.callback(true);
+				};
+				var onError = function(error, request) {
+					d.errback(error);
+				};
+				store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: newItem",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the newItem API
+				//	description:
+				//		Simple test of the newItem API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				t.assertTrue(!store.isDirty());
+	
+				var onNewInvoked = false;
+				store.onNew = function(newItem, parentInfo){
+	
+					t.assertTrue(newItem !== null);
+					t.assertTrue(parentInfo === null);
+					t.assertTrue(store.isItem(newItem));
+					onNewInvoked = true;
+				};
+				var canada = store.newItem({name: "Canada", abbr:"ca", capital:"Ottawa"});
+				t.assertTrue(onNewInvoked);
+				
+				t.assertTrue(store.isDirty(canada));
+				t.assertTrue(store.isDirty());
+				t.assertTrue(store.getValues(canada, "name") == "Canada");
+				var onComplete = function(items, request){
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item, "name", "Canada"));
+					d.callback(true);
+				};
+				var onError = function(error, request){
+					d.errback(error);
+				};
+				store.fetch({query:{name:"Canada"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: newItem with a parent assignment",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the newItem API with a parent assignment
+				//	description:
+				//		Simple test of the newItem API with a parent assignment
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				t.assertTrue(!store.isDirty());
+
+				var onError = function(error, request){
+					d.errback(error);
+				};
+
+				var onComplete = function(items, request){
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item, "name", "Egypt"));
+	
+					//Attach an onNew to validate we get expected values.
+					var onNewInvoked = false;
+					store.onNew = function(newItem, parentInfo){
+						t.assertEqual(item, parentInfo.item);
+						t.assertEqual("cities", parentInfo.attribute);
+						t.assertTrue(parentInfo.oldValue === undefined);
+						t.assertTrue(parentInfo.newValue === newItem);
+						onNewInvoked = true;
+					};
+	
+					//Attach an onSet and verify onSet is NOT called in this case.
+					store.onSet = function(item, attribute, oldValue, newValue){
+						t.assertTrue(false);
+					};
+	
+					//See if we can add in a new item representing the city of Cairo.
+					//This should also call the onNew set above....
+					var newItem = store.newItem({name: "Cairo", abbr: "Cairo"}, {parent: item, attribute: "cities"});
+					t.assertTrue(onNewInvoked);
+	
+					var onCompleteNewItemShallow = function(items, request){
+						t.assertEqual(0, items.length);
+						var onCompleteNewItemDeep = function(items, request){
+							t.assertEqual(1, items.length);
+							var item = items[0];
+							t.assertEqual("Cairo", store.getValue(item, "name"));
+							d.callback(true);
+						};
+						//Do a deep search now, should find the new item of the city with name attribute Cairo.
+						store.fetch({query:{name:"Cairo"}, onComplete: onCompleteNewItemDeep, onError: onError, queryOptions: {deep:true}});
+					};
+					//Do a shallow search first, should find nothing.
+					store.fetch({query:{name:"Cairo"}, onComplete: onCompleteNewItemShallow, onError: onError});
+				};
+				store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: newItem with a parent assignment multiple times",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the newItem API with a parent assignment multiple times.
+				//	description:
+				//		Simple test of the newItem API with a parent assignment multiple times.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				
+				t.assertTrue(!store.isDirty());
+				
+				var onComplete = function(items, request){
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item, "name", "Egypt"));
+	
+					//Attach an onNew to validate we get expected values.
+					store.onNew = function(newItem, parentInfo){
+						t.assertEqual(item, parentInfo.item);
+						t.assertEqual("cities", parentInfo.attribute);
+						
+						t.assertTrue(parentInfo.oldValue === undefined);
+						
+						t.assertTrue(parentInfo.newValue === newItem);
+					};
+	
+					//See if we can add in a new item representing the city of Cairo.
+					//This should also call the onNew set above....
+					var newItem1 = store.newItem({name: "Cairo", abbr: "Cairo"}, {parent: item, attribute: "cities"});
+					
+					//Attach a new onNew to validate we get expected values.
+					store.onNew = function(newItem, parentInfo){
+						t.assertEqual(item, parentInfo.item);
+						t.assertEqual("cities", parentInfo.attribute);
+						
+						console.log(parentInfo.oldValue);
+						t.assertTrue(parentInfo.oldValue == newItem1);
+						
+						t.assertTrue(parentInfo.newValue[0] == newItem1);
+						t.assertTrue(parentInfo.newValue[1] == newItem);
+					};
+					var newItem2 = store.newItem({name: "Banha", abbr: "Banha"}, {parent: item, attribute: "cities"});
+					
+					//Attach a new onNew to validate we get expected values.
+					store.onNew = function(newItem, parentInfo){
+						t.assertEqual(item, parentInfo.item);
+						t.assertEqual("cities", parentInfo.attribute);
+						
+						t.assertTrue(parentInfo.oldValue[0] == newItem1);
+						t.assertTrue(parentInfo.oldValue[1] == newItem2);
+						
+						t.assertTrue(parentInfo.newValue[0] == newItem1);
+						t.assertTrue(parentInfo.newValue[1] == newItem2);
+						t.assertTrue(parentInfo.newValue[2] == newItem);
+					};
+					var newItem3 = store.newItem({name: "Damanhur", abbr: "Damanhur"}, {parent: item, attribute: "cities"});
+					d.callback(true);
+				};
+				var onError = function(error, request){
+					d.errback(error);
+				};
+				store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: deleteItem",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the deleteItem API
+				//	description:
+				//		Simple test of the deleteItem API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+
+				var onError = function(error, request){
+					d.errback(error);
+				};
+
+				var onComplete = function(items, request){
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item, "name", "Egypt"));
+					t.assertTrue(store.isDirty(item) === false);
+					t.assertTrue(!store.isDirty());
+					store.deleteItem(item);
+					t.assertTrue(store.isDirty(item));
+					t.assertTrue(store.isDirty());
+					var onCompleteToo = function(itemsToo, requestToo) {
+						t.assertEqual(0, itemsToo.length);
+						d.callback(true);
+					};
+					store.fetch({query:{name:"Egypt"}, onComplete: onCompleteToo, onError: onError});
+				};
+				store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: isDirty",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the isDirty API
+				//	description:
+				//		Simple test of the isDirty API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onComplete = function(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item, "name", "Egypt"));
+					store.setValue(item, "name", "Egypt 2");
+					t.assertTrue(store.getValue(item, "name") == "Egypt 2");
+					t.assertTrue(store.isDirty(item));
+					d.callback(true);
+				};
+				var onError = function(error, request) {
+					d.errback(error);
+				};
+				store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: revert",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the revert API
+				//	description:
+				//		Simple test of the revert API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+
+				var onError = function(error, request){
+					d.errback(error);
+				};
+
+				var onComplete = function(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item, "name", "Egypt"));
+					t.assertTrue(store.isDirty(item) === false);
+					t.assertTrue(!store.isDirty());
+					store.setValue(item, "name", "Egypt 2");
+					t.assertTrue(store.getValue(item, "name") == "Egypt 2");
+					t.assertTrue(store.isDirty(item));
+					t.assertTrue(store.isDirty());
+					store.revert();
+					
+					//Fetch again to see if it reset the state.
+					var onCompleteToo = function(itemsToo, requestToo){
+						t.assertEqual(1, itemsToo.length);
+						var itemToo = itemsToo[0];
+						t.assertTrue(store.containsValue(itemToo, "name", "Egypt"));
+						d.callback(true);
+					};
+					store.fetch({query:{name:"Egypt"}, onComplete: onCompleteToo, onError: onError});
+				};
+				store.fetch({query:{name:"Egypt"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: save",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the save API
+				//	description:
+				//		Simple test of the save API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onError = function(error){
+					d.errback(error);
+				};
+				var onItem = function(item){
+					store.setValue(item, "capital", "New Cairo");
+					var onComplete = function() {
+						d.callback(true);
+					} ;
+					store.save({onComplete:onComplete, onError:onError});
+				};
+				store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: save, verify state",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the save API
+				//	description:
+				//		Simple test of the save API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onError = function(error){
+					d.errback(error);
+				};
+				var onItem = function(item){
+					store.setValue(item, "capital", "New Cairo");
+					var onComplete = function() {
+						//Check internal state.  Note:  Users should NOT do this, this is a UT verification
+						//of internals in this case.  Ref tracker: #4394
+						t.assertTrue(!store._saveInProgress);
+						d.callback(true);
+					};
+					store.save({onComplete:onComplete, onError:onError});
+				};
+				store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: saveEverything",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the save API
+				//	description:
+				//		Simple test of the save API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				var egypt;
+
+				var d = new doh.Deferred();
+				var onError = function(error){
+					d.errback(error);
+				};
+
+				store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+					var struct = dojo.fromJson(newFileContentString);
+					t.assertEqual(struct.identifier, store.getIdentityAttributes(egypt)[0]);
+					t.assertEqual(struct.label, store.getLabelAttributes(egypt)[0]);
+					t.assertEqual(struct.items.length, 7);
+					
+					var cloneStore = new dojox.data.AndOrWriteStore({data:struct});
+					var onItemClone = function(itemClone){
+						var egyptClone = itemClone;
+						t.assertEqual(store.getIdentityAttributes(egypt)[0], cloneStore.getIdentityAttributes(egyptClone)[0]);
+						t.assertEqual(store.getLabelAttributes(egypt)[0], cloneStore.getLabelAttributes(egyptClone)[0]);
+						t.assertEqual(store.getValue(egypt, "name"), cloneStore.getValue(egyptClone, "name"));
+					};
+					cloneStore.fetchItemByIdentity({identity:"eg", onItem:onItemClone, onError:onError});
+					
+					saveCompleteCallback();
+				};
+	
+				var onItem = function(item){
+					egypt = item;
+					var onComplete = function() {
+						d.callback(true);
+					};
+					store.setValue(egypt, "capital", "New Cairo");
+					store.save({onComplete:onComplete, onError:onError});
+				};
+				store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: saveEverything with Date type",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the save API	with a non-atomic type (Date) that has a type mapping.
+				//	description:
+				//		Simple test of the save API	with a non-atomic type (Date) that has a type mapping.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+
+				var d = new doh.Deferred();
+
+				store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+	
+					//Now load the new data into a datastore and validate that it stored the date right.
+					var dataset = dojo.fromJson(newFileContentString);
+					var newStore = new dojox.data.AndOrWriteStore({data: dataset});
+	
+					var gotItem = function(item){
+						var independenceDate = newStore.getValue(item,"independence"); 
+						t.assertTrue(independenceDate instanceof Date);
+						t.assertTrue(dojo.date.compare(new Date(1993,4,24), independenceDate, "date") === 0);
+						saveCompleteCallback();
+					};
+					var failed = function(error, request){
+						d.errback(error);
+						saveFailedCallback();
+					};
+					newStore.fetchItemByIdentity({identity:"eg", onItem:gotItem, onError:failed});
+				};
+	
+				var onError = function(error){
+					d.errback(error);
+				};
+				var onItem = function(item){
+					var onComplete = function() {
+						d.callback(true);
+					};
+					store.setValue(item, "independence", new Date(1993,4,24));
+					store.save({onComplete:onComplete, onError:onError});
+				};
+				store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: saveEverything, with custom color simple type",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
+				//	description:
+				//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
+	
+				//Set up the store basics:  What data it has, and what to do when save is called for saveEverything
+				//And how to map the 'Color' type in and out of the format.
+				//(Test of saving all to a some location...)
+				var dataset = {
+					identifier:'name',
+					items: [
+						{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+						{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+					]
+				};
+	
+				var customTypeMap = {'Color': dojo.Color };
+	
+				var store = new dojox.data.AndOrWriteStore({
+						data:dataset,
+						typeMap: customTypeMap
+				});
+				
+				var d = new doh.Deferred();
+				store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+					//Now load the new data into a datastore and validate that it stored the Color right.
+					var dataset = dojo.fromJson(newFileContentString);
+					var newStore = new dojox.data.AndOrWriteStore({data: dataset, typeMap: customTypeMap});
+	
+					var gotItem = function(item){
+						var hairColor = newStore.getValue(item,"hairColor"); 
+						t.assertTrue(hairColor instanceof dojo.Color);
+						t.assertEqual("rgba(255, 255, 0, 1)", hairColor.toString());
+						saveCompleteCallback();
+					};
+					var failed = function(error, request){
+						d.errback(error);
+						saveFailedCallback();
+					};
+					newStore.fetchItemByIdentity({identity:"Animal", onItem:gotItem, onError:failed});
+				};
+	
+				//Add a new item with a color type, then save it.
+				var onError = function(error){
+					d.errback(error);
+				};
+				var onComplete = function() {
+					d.callback(true);
+				};
+	
+				var animal = store.newItem({name: "Animal", hairColor: new dojo.Color("yellow")});
+				store.save({onComplete:onComplete, onError:onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: saveEverything, with custom color type general",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
+				//	description:
+				//		Simple test of the save API	with a non-atomic type (dojo.Color) that has a type mapping.
+	
+				//Set up the store basics:  What data it has, and what to do when save is called for saveEverything
+				//And how to map the 'Color' type in and out of the format.
+				//(Test of saving all to a some location...)
+				var dataset = {
+					identifier:'name',
+					items: [
+						{ name:'Kermit', species:'frog', color:{_type:'Color', _value:'green'} },
+						{ name:'Beaker', hairColor:{_type:'Color', _value:'red'} }
+					]
+				};
+	
+				var customTypeMap = {'Color': 	{	
+													type: dojo.Color,
+													deserialize: function(value){
+														return new dojo.Color(value);
+													},
+													serialize: function(obj){
+														return obj.toString();
+													}
+												}
+									};
+				var store = new dojox.data.AndOrWriteStore({
+						data:dataset,
+						typeMap: customTypeMap
+				});
+				
+				var d = new doh.Deferred();
+				store._saveEverything = function(saveCompleteCallback, saveFailedCallback, newFileContentString){
+					//Now load the new data into a datastore and validate that it stored the Color right.
+					var dataset = dojo.fromJson(newFileContentString);
+					var newStore = new dojox.data.AndOrWriteStore({data: dataset, typeMap: customTypeMap});
+	
+					var gotItem = function(item){
+						var hairColor = newStore.getValue(item,"hairColor"); 
+						t.assertTrue(hairColor instanceof dojo.Color);
+						t.assertEqual("rgba(255, 255, 0, 1)", hairColor.toString());
+						saveCompleteCallback();
+					};
+					var failed = function(error, request){
+						d.errback(error);
+						saveFailedCallback();
+					};
+					newStore.fetchItemByIdentity({identity:"Animal", onItem:gotItem, onError:failed});
+				};
+	
+				//Add a new item with a color type, then save it.
+				var onError = function(error){
+					d.errback(error);
+				};
+				var onComplete = function() {
+					d.callback(true);
+				};
+	
+				var animal = store.newItem({name: "Animal", hairColor: new dojo.Color("yellow")});
+				store.save({onComplete:onComplete, onError:onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "Write API: newItem, revert",
+			runTest: function(t){
+				//	summary: 
+				//		Test for bug #5357.  Ensure that the revert properly nulls the identity position
+				//      for a new item after revert.
+				var args = {data: {
+					label:"name",
+					items:[
+						{name:'Ecuador', capital:'Quito'},
+						{name:'Egypt', capital:'Cairo'},
+						{name:'El Salvador', capital:'San Salvador'},
+						{name:'Equatorial Guinea', capital:'Malabo'},
+						{name:'Eritrea', capital:'Asmara'},
+						{name:'Estonia', capital:'Tallinn'},
+						{name:'Ethiopia', capital:'Addis Ababa'}
+					]
+				} }; 
+				var store = new dojox.data.AndOrWriteStore(args);
+	
+				var newCountry = store.newItem({name: "Utopia", capitol: "Perfect"});
+	
+				//DO NOT ACCESS THIS WAY.  THESE ARE INTERNAL VARIABLES.  DOING THIS FOR TEST PURPOSES.
+				var itemEntryNum = newCountry[store._itemNumPropName];
+				t.assertTrue(store._arrayOfAllItems[itemEntryNum] === newCountry);
+				store.revert();
+				t.assertTrue(store._arrayOfAllItems[itemEntryNum] === null);
+			}
+		},
+		{
+			name: "Write API: newItem, modify revert",
+			runTest: function(){
+				//	summary: 
+				//		Test of a new item, modify it, then revert, to ensure the state remains consistent.  Added due to #9022.
+				//	description:
+				//		Test of a new item, modify it, then revert, to ensure the state remains consistent.  Added due to #9022.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+
+				var deferred = new doh.Deferred();
+				doh.assertTrue(!store.isDirty());
+
+				var onError = function(error, request){
+					deferred.errback(error);
+				};
+
+				var intialFetch = function(items, request){
+					var initialCount = items.length;
+					var canada = store.newItem({name: "Canada", abbr:"ca", capital:"Ottawa"});
+					store.setValue(canada, "someattribute", "modified a new item!");
+					var afterNewFetch = function(items, request){
+						var afterNewCount = items.length;
+						doh.assertEqual(afterNewCount, (initialCount + 1));
+						store.revert();
+						var afterRevertFetch = function(items, request){
+							var afterRevertCount = items.length;
+							doh.assertEqual(afterRevertCount, initialCount);
+							deferred.callback(true);
+						};
+						store.fetch({onComplete: afterRevertFetch, onError: onError});
+					};
+						  store.fetch({onComplete: afterNewFetch, onError: onError});
+				};
+				store.fetch({onComplete: intialFetch, onError: onError});
+				return deferred; //Object
+			}
+		},
+		{
+			name: "Write API: newItem, modify, delete, revert",
+			runTest: function(){
+				//	summary: 
+				//		Test of a new item, modify it, delete it, then revert, to ensure the state remains consistent.  Added due to #9022.
+				//	description:
+				//		Test of a new item, modify it, delete it, then revert, to ensure the state remains consistent.  Added due to #9022.
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				var i;
+				var found = false;
+	
+				var deferred = new doh.Deferred();
+				doh.assertTrue(!store.isDirty());
+	
+				var onError = function(error, request){
+					deferred.errback(error);
+				};
+	
+				var intialFetch = function(items, request){
+					var initialCount = items.length;
+					var canada = store.newItem({name: "Canada", abbr:"ca", capital:"Ottawa"});
+					store.setValue(canada, "someattribute", "modified a new item!");
+					
+					// check that after new and modify, the total items count goes up by one.
+					var afterNewFetch = function(items, request){
+						var afterNewCount = items.length;
+						doh.assertEqual(afterNewCount, (initialCount + 1));
+						store.deleteItem(canada);
+						
+						//Check that after delete, the total items count goes back to initial count.  
+						//Also verify the item with abbr of ca is gone.
+						var afterDeleteFetch = function(items, request){
+							var afterDeleteCount = items.length;
+							doh.assertEqual(initialCount, afterDeleteCount);
+	
+							for(i=0; i < items.length; i++){
+								found = (store.getIdentity(items[i]) === "ca");
+								if(found){ 
+									break;
+								}
+							}
+							if(found){
+								deferred.errback(new Error("Error: Found the supposedly deleted item!"));
+							}else{
+								store.revert();
+								//Check that after revert, we still have the same item count as the 
+								//original fetch.  Also verify the item with abbr of ca is gone.
+								var afterRevertFetch = function(items, request){
+									var afterRevertCount = items.length;
+									doh.assertEqual(afterRevertCount, initialCount);
+									for(i=0; i < items.length; i++){
+										found = (store.getIdentity(items[i]) === "ca");
+										if(found){ 
+											break;
+										}
+									}
+									if(found){
+										deferred.errback(new Error("Error: Found the 'new' item after revert!"));
+									}else{
+										deferred.callback(true);
+									}
+								};
+								store.fetch({onComplete: afterRevertFetch, onError: onError});
+							}
+						};
+						store.fetch({onComplete: afterDeleteFetch, onError: onError});
+					};
+					store.fetch({onComplete: afterNewFetch, onError: onError});
+				};
+				store.fetch({onComplete: intialFetch, onError: onError});
+				return deferred; //Object
+			}
+		},
+
+		{
+			name: "Write API: onSet notification",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the onSet API
+				//	description:
+				//		Simple test of the onSet API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onError = function(error){
+					d.errback(error);
+				};
+				var onItem = function(fetchedItem){
+					var egypt = fetchedItem;
+					var connectHandle = null;
+					var setValueHandler = function(item, attribute, oldValue, newValue){
+						t.assertTrue(store.isItem(item));
+						t.assertTrue(item == egypt);
+						t.assertTrue(attribute == "capital");
+						t.assertTrue(oldValue == "Cairo");
+						t.assertTrue(newValue == "New Cairo");
+						d.callback(true);
+						dojo.disconnect(connectHandle);
+					};
+					connectHandle = dojo.connect(store, "onSet", setValueHandler);
+					store.setValue(egypt, "capital", "New Cairo");
+				};
+				store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+			}
+		},
+		{
+			name: "Write API: onNew notification",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the onNew API
+				//	description:
+				//		Simple test of the onNew API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var connectHandle = null;
+				var newItemHandler = function(item){
+					t.assertTrue(store.isItem(item));
+					t.assertTrue(store.getValue(item, "name") == "Canada");
+					d.callback(true);
+					dojo.disconnect(connectHandle);
+				};
+				connectHandle = dojo.connect(store, "onNew", newItemHandler);
+				var canada = store.newItem({name:"Canada", abbr:"ca", capital:"Ottawa"});
+			}
+		},
+		{
+			name: "Write API: onDelete notification",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the onDelete API
+				//	description:
+				//		Simple test of the onDelete API
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+	
+				var d = new doh.Deferred();
+				var onError = function(error){
+					d.errback(error);
+				};
+				var onItem = function(fetchedItem){
+					var egypt = fetchedItem;
+					var connectHandle = null;
+					var deleteItemHandler = function(item){
+						t.assertTrue(store.isItem(item) === false);
+						t.assertTrue(item == egypt);
+						d.callback(true);
+						dojo.disconnect(connectHandle);
+					};
+					connectHandle = dojo.connect(store, "onDelete", deleteItemHandler);
+					store.deleteItem(egypt);
+				};
+				store.fetchItemByIdentity({identity:"eg", onItem:onItem, onError:onError});
+			}
+		},
+		{
+			name: "Write API: Read API conformance",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+				//	description:
+				//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+				var testStore = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				var readApi = new dojo.data.api.Read();
+				var passed = true;
+	
+				for(var functionName in readApi){
+					var member = readApi[functionName];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[functionName];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+				t.assertTrue(passed);
+			}
+		},
+		{
+			name: "Write API: Write API conformance",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
+				//	description:
+				//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
+				var testStore = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				var writeApi = new dojo.data.api.Write();
+				var passed = true;
+	
+				for(var functionName in writeApi){
+					var member = writeApi[functionName];
+					//Check that all the 'Write' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[functionName];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+				t.assertTrue(passed);
+			}
+		},
+		{
+			name: "Write API: Notification API conformance",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test Notification API conformance.  Checks to see all declared functions are actual functions on the instances.
+				//	description:
+				//		Simple test Notification API conformance.  Checks to see all declared functions are actual functions on the instances.
+				var testStore = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries"));
+				var api = new dojo.data.api.Notification();
+				var passed = true;
+	
+				for(var functionName in api){
+					var member = api[functionName];
+					//Check that all the 'Write' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[functionName];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+				t.assertTrue(passed);
+			}
+		},
+		{
+			name: "Write API: Identity, auto-creation when missing",
+			runTest: function(t){
+				//	summary: 
+				//		Test for bug #3873. Given a datafile that does not specify an
+				//		identifier, make sure AndOrWriteStore auto-creates identities 
+				//		that are unique even after calls to deleteItem() and newItem()
+				var args = {data: {
+					label:"name",
+					items:[
+						{name:'Ecuador', capital:'Quito'},
+						{name:'Egypt', capital:'Cairo'},
+						{name:'El Salvador', capital:'San Salvador'},
+						{name:'Equatorial Guinea', capital:'Malabo'},
+						{name:'Eritrea', capital:'Asmara'},
+						{name:'Estonia', capital:'Tallinn'},
+						{name:'Ethiopia', capital:'Addis Ababa'}
+					]
+				} }; 
+				var store = new dojox.data.AndOrWriteStore(args);
+				var d = new doh.Deferred();
+				
+				var onError = function(error, request){
+					d.errback(error);
+				};
+				var onComplete = function(items, request){
+					t.assertEqual(7, items.length);
+					
+					var lastItem = items[(items.length - 1)];
+					var idOfLastItem = store.getIdentity(lastItem);
+					store.deleteItem(lastItem);
+					store.newItem({name:'Canada', capital:'Ottawa'});
+					
+					var onCompleteAgain = function(itemsAgain, requestAgain){
+						t.assertEqual(7, itemsAgain.length);
+						var identitiesInUse = {};
+						for(var i = 0; i < itemsAgain.length; ++i){
+							var item = itemsAgain[i];
+							var id = store.getIdentity(item);
+							if(identitiesInUse.hasOwnProperty(id)){
+								// there should not already be an entry for this id
+								t.assertTrue(false);
+							}else{
+								// we want to add the entry now
+								identitiesInUse[id] = item;
+							}
+						}
+						d.callback(true);
+					};
+					store.fetch({onComplete:onCompleteAgain, onError:onError});
+				};
+				
+				store.fetch({onComplete:onComplete, onError:onError});
+				return d;
+			}
+		},
+		{
+			name: "Write API: Identity, auto-creation when missing, revert",
+			runTest: function(t){
+				//	summary: 
+				//		Test for bug #4691  Given a datafile that does not specify an
+				//		identifier, make sure AndOrWriteStore auto-creates identities 
+				//		that are unique even after calls to deleteItem() and newItem()
+				var args = {data: {
+					label:"name",
+					items:[
+						{name:'Ecuador', capital:'Quito'},
+						{name:'Egypt', capital:'Cairo'},
+						{name:'El Salvador', capital:'San Salvador'},
+						{name:'Equatorial Guinea', capital:'Malabo'},
+						{name:'Eritrea', capital:'Asmara'},
+						{name:'Estonia', capital:'Tallinn'},
+						{name:'Ethiopia', capital:'Addis Ababa'}
+					]
+				} }; 
+				var store = new dojox.data.AndOrWriteStore(args);
+				var d = new doh.Deferred();
+				
+				var onError = function(error, request){
+					d.errback(error);
+				};
+				var onComplete = function(items, request){
+					t.assertEqual(7, items.length);
+					
+					var lastItem = items[(items.length - 1)];
+					var idOfLastItem = store.getIdentity(lastItem);
+					store.deleteItem(lastItem);
+					store.newItem({name:'Canada', capital:'Ottawa'});
+					
+					var onCompleteAgain = function(itemsAgain, requestAgain){
+						t.assertEqual(7, itemsAgain.length);
+						var identitiesInUse = {};
+						for(var i = 0; i < itemsAgain.length; ++i){
+							var item = itemsAgain[i];
+							var id = store.getIdentity(item);
+							if(identitiesInUse.hasOwnProperty(id)){
+								// there should not already be an entry for this id
+								t.assertTrue(false);
+							}else{
+								// we want to add the entry now
+								identitiesInUse[id] = item;
+							}
+						}
+						//Last test, revert everything and check item sizes.
+						store.revert();
+	
+						//Now call fetch again and verify store state.
+						var revertComplete = function(itemsReverted, request){
+							t.assertEqual(7, itemsReverted.length);
+							d.callback(true);
+						};
+						store.fetch({onComplete:revertComplete, onError:onError});
+					};
+					store.fetch({onComplete:onCompleteAgain, onError:onError});
+				};
+				store.fetch({onComplete:onComplete, onError:onError});
+				return d;
+			}
+		},
+		{
+			name: "Write API: reference integrity, check references",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test to verify the references were properly resolved.
+				//	description:
+				//		Simple test to verify the references were properly resolved.
+			
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("reference_integrity"));
+	
+				var d = new doh.Deferred();
+				var onError = function(error, request){
+					d.errback(error);
+				};
+				var onComplete = function(items, request){
+	
+					var item10 = null;
+					var item1  = null;
+					var item3  = null;
+					var item5  = null;
+	
+					var i;
+					for (i = 0; i < items.length; i++) {
+						var ident = store.getIdentity(items[i]);
+						if (ident === 10) {
+							item10 = items[i];
+						}else if (ident === 1) {
+							item1 = items[i];
+						}else if (ident === 3) {
+							item3 = items[i];
+						}else if (ident === 5) {
+							item5 = items[i];
+						}
+					}
+					var friends = store.getValues(item10, "friends");
+					t.assertTrue(friends !== null);
+					t.assertTrue(friends !== undefined);
+	
+					t.assertTrue(store.isItem(item10));
+					t.assertTrue(store.isItem(item1));
+					t.assertTrue(store.isItem(item3));
+					t.assertTrue(store.isItem(item5));
+					var found = 0;
+					try{
+						for (i = 0; i < friends.length; i++) {
+							if (i === 0) {
+								t.assertTrue(store.isItem(friends[i]));
+								t.assertEqual(friends[i], item1);
+								t.assertEqual(store.getIdentity(friends[i]), 1);
+								found++;
+							}else if (i === 1) {
+								t.assertTrue(store.isItem(friends[i]));
+								t.assertEqual(friends[i], item3);
+								t.assertEqual(store.getIdentity(friends[i]), 3);
+								found++;
+							}else if (i === 2) {
+								t.assertTrue(store.isItem(friends[i]));
+								t.assertEqual(friends[i], item5);
+								t.assertEqual(store.getIdentity(friends[i]), 5);
+								found++;
+							}
+						}
+					}catch(e){
+						doh.errback(e);
+					}
+					t.assertEqual(3, found);
+					d.callback(true);
+				};
+				store.fetch({onError: onError, onComplete: onComplete});
+				return d;
+			}
+		},
+		{
+			name: "Write API: reference integrity, delete referenced item",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test to verify the references were properly deleted.
+				//	description:
+				//		Simple test to verify the references were properly deleted.
+			
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("reference_integrity"));
+	
+				var d = new doh.Deferred();
+				var passed = true;
+				var onError = function(error, request){
+					d.errback(error);
+				};
+				var onItem = function(item, request){
+					try{
+						console.log("Before delete map state is: " + dojo.toJson(item[store._reverseRefMap]));
+						store.deleteItem(item);
+						console.log("After delete map state is: " + dojo.toJson(item[store._reverseRefMap]));
+						function verifyRefDelete(items, request){
+							var passed = true;
+							for(var i = 0; i < items.length; i++){
+								var curItem = items[i];
+								var attributes = store.getAttributes(curItem);
+								for(var j = 0; j < attributes.length; j++){
+									var values = store.getValues(curItem, attributes[j]);
+									var badRef = false;
+									for(var k = 0; k < values.length; k++){
+										var value = values[k];
+										try{
+											var id = store.getIdentity(value);
+											if(id == 10){
+												badRef = true;
+												break;
+											}
+										}catch(e){/*Not an item, even a dead one, just eat it.*/}
+									}
+									if(badRef){
+										d.errback(new Error("Found a reference remaining to a deleted item.  Failure."));
+										passed = false;
+										break;
+									}
+								}
+							}
+							if(passed){
+								d.callback(true);
+							}
+						}
+						store.fetch({onComplete: verifyRefDelete, onError: onError});
+					}catch(error){
+						d.errback(error);
+					}
+				};
+				store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+				return d;
+			}
+		},
+		{
+			name: "Write API: reference integrity, delete referenced item, then revert",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test to verify the references were properly deleted.
+				//	description:
+				//		Simple test to verify the references were properly deleted.
+			
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("reference_integrity"));
+	
+				var d = new doh.Deferred();
+				var passed = true;
+				var onError = function(error, request){
+					d.errback(error);
+				};
+				var onItem = function(item, request){
+					try{
+						//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+						//THIS IS FOR TESTING INTERNAL STATE!
+						console.log("Map before delete:");
+						store._dumpReferenceMap();
+						var beforeDelete = dojo.toJson(item[store._reverseRefMap]);
+						store.deleteItem(item);
+						console.log("Map after delete:");
+						store._dumpReferenceMap();
+						var afterDelete = dojo.toJson(item[store._reverseRefMap]);
+						store.revert();
+						console.log("Map after revert:");
+						store._dumpReferenceMap();
+						var afterRevert = dojo.toJson(item[store._reverseRefMap]);
+						t.assertTrue(afterRevert === beforeDelete);
+					}catch(e){
+						d.errback(e);
+						passed = false;
+					}
+					if(passed){
+						d.callback(true);
+					}
+				};
+				store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+				return d;
+			}
+		},
+		{
+			name: "Write API: reference integrity, delete multiple items with references and revert",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test to verify that a flow of deleting items with references and reverting does not damage the internal structure.
+				//		Created for tracker bug: #5743
+				//	description:
+				//		Simple test to verify that a flow of deleting items with references and reverting does not damage the internal structure.
+				//		Created for tracker bug: #5743
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("countries_references"));
+	
+				var d = new doh.Deferred();
+				var passed = true;
+				var onError = function(error, request){
+					d.errback(error);
+					t.assertTrue(false);
+				};
+				var onItem = function(item, request){
+					//Save off the located item, then locate another one (peer to Egypt)
+					t.assertTrue(store.isItem(item));
+					var egypt = item;
+					var onItem2 = function(item, request){
+						t.assertTrue(store.isItem(item));
+						var nairobi = item;
+	
+						//Delete them
+						store.deleteItem(egypt);
+						store.deleteItem(nairobi);
+						try{
+							//Revert, then do a fetch.  If the internals have been damaged, this will generally
+							//cause onError to fire instead of onComplete.
+							store.revert();
+							var onComplete = function(items, request){
+								d.callback(true);
+							};
+							store.fetch({query: {name: "*"}, start: 0, count: 20, onComplete: onComplete, onError: onError});
+						}catch(e){
+							d.errback(e);
+						}
+					};
+					store.fetchItemByIdentity({identity: "Nairobi", onError: onError, onItem: onItem2});
+				};
+				store.fetchItemByIdentity({identity: "Egypt", onError: onError, onItem: onItem});
+				return d;
+			}
+		},
+		{
+			name: "Write API: reference integrity, remove reference from attribute",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test to verify the reference removal updates the internal map.
+				//	description:
+				//		Simple test to verify the reference removal updates the internal map.
+			
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("reference_integrity"));
+	
+				var d = new doh.Deferred();
+				var passed = true;
+				var onError = function(error, request){
+					d.errback(error);
+					t.assertTrue(false);
+				};
+				var onItem = function(item, request){
+					try{
+						store.setValues(item, "friends", [null]);
+	
+						var onItem2 = function(item10, request){
+							//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+							//THIS IS FOR TESTING INTERNAL STATE!
+							var refMap = item10[store._reverseRefMap];
+							store._dumpReferenceMap();
+	
+							console.log("MAP for Item 10 is: " + dojo.toJson(refMap));
+	
+							//Assert there is no reference to item 10 in item 11's attribute 'friends'.
+							t.assertTrue(!refMap["11"]["friends"]);
+							store.setValues(item, "siblings", [0, 1, 2]);
+							//Assert there are no more references to 10 in 11.  Ergo, "11"  should be a 'undefined' attribute for the map of items referencing '10'..
+							t.assertTrue(!refMap["11"]);
+							d.callback(true);
+						};
+						store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem2});
+	
+					}catch(e){
+						console.debug(e);
+						d.errback(e);
+						t.assertTrue(false);
+					}
+				};
+				store.fetchItemByIdentity({identity: 11, onError: onError, onItem: onItem});
+				return d;
+			}
+		},
+		{
+			name: "Write API: reference integrity, delete referenced item non-parent",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test to verify the references to a non-parent item was properly deleted.
+				//	description:
+				//		Simple test to verify the references to a non-parent item was properly deleted.
+			
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("reference_integrity"));
+	
+				var d = new doh.Deferred();
+				var passed = true;
+				var onError = function(error, request){
+					d.errback(error);
+				};
+				var onItem = function(item, request){
+					try{
+						console.log("Reference state for item 16 is: " + dojo.toJson(item[store._reverseRefMap]));
+						store.deleteItem(item);
+						function verifyRefDelete(items, request){
+							var passed = true;
+							for(var i = 0; i < items.length; i++){
+								var curItem = items[i];
+								var attributes = store.getAttributes(curItem);
+								for(var j = 0; j < attributes.length; j++){
+									var values = store.getValues(curItem, attributes[j]);
+									var badRef = false;
+									for(var k = 0; k < values.length; k++){
+										var value = values[k];
+										try{
+											var id = store.getIdentity(value);
+											if(id == 16){
+												badRef = true;
+												break;
+											}
+										}catch(e){/*Not an item, even a dead one, just eat it.*/}
+									}
+									if(badRef){
+										d.errback(new Error("Found a reference remaining to a deleted item.  Failure."));
+										passed = false;
+										break;
+									}
+								}
+							}
+							if(passed){
+								d.callback(true);
+							}
+						}
+						store.fetch({onComplete: verifyRefDelete, onError: onError});
+					}catch(error){
+						d.errback(error);
+					}
+				};
+				store.fetchItemByIdentity({identity: 16, onError: onError, onItem: onItem});
+				return d;
+			}
+		},
+		{
+			name: "Write API: reference integrity, add reference to attribute",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test to verify the reference additions can happen.
+				//	description:
+				//		Simple test to verify the reference additions can happen.
+			
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("reference_integrity"));
+	
+				var d = new doh.Deferred();
+				var passed = true;
+				var onError = function(error, request){
+					d.errback(error);
+					t.assertTrue(false);
+				};
+				var onComplete = function(items, request){
+	
+					t.assertTrue(items.length > 2);
+	
+					var item1 = items[0];
+					var item2 = items[1];
+	
+					//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+					//THIS IS FOR TESTING INTERNAL STATE!
+					console.log("Map state for Item 1 is: " + dojo.toJson(item1[store._reverseRefMap]));
+					console.log("Map state for Item 2 is: " + dojo.toJson(item2[store._reverseRefMap]));
+	
+					store.setValue(item1, "siblings", item2);
+	
+					//Emit the current map state for inspection.
+					console.log("Map state for Item 1 is: " + dojo.toJson(item1[store._reverseRefMap]));
+					console.log("Map state for Item 2 is: " + dojo.toJson(item2[store._reverseRefMap]));
+	
+					t.assertTrue(item2[store._reverseRefMap] !== null);
+	
+					//Assert there is a recorded reference to item 2 in item 1's attribute 'sibling'.
+					t.assertTrue(item2[store._reverseRefMap][store.getIdentity(item1)]["siblings"]);
+	
+					d.callback(true);
+				};
+				store.fetch({onError: onError, onComplete: onComplete});
+				return d;
+			}
+		},
+		{
+			name: "Write API: reference integrity, new item with parent reference",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test to verify that newItems with a parent properly record the parent's reference in the map.
+				//	description:
+				//		Simple test to verify that newItems with a parent properly record the parent's reference in the map.
+			
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("reference_integrity"));
+	
+				var d = new doh.Deferred();
+				var passed = true;
+				var onError = function(error, request){
+					d.errback(error);
+					t.assertTrue(false);
+				};
+				var onItem = function(item, request){
+					try{
+						//Create a new item and set its parent to item 10's uncle attribute.
+						var newItem = store.newItem({id: 17, name: "Item 17"}, {parent: item, attribute: "uncles"}); 
+						
+						//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+						//THIS IS FOR TESTING INTERNAL STATE!
+						//Look up the references to 17, as item 10 has one now on attribute 'uncles'
+						var refs = newItem[store._reverseRefMap];
+	
+						//Assert there is a reference from 10 to item 17, on attribute uncle
+						t.assertTrue(refs["10"]["uncles"]);
+	
+						console.log("State of map of item 17 after newItem: " + dojo.toJson(refs));
+					}catch(e){
+						console.debug(e);
+						d.errback(e);
+						t.assertTrue(false);
+						passed = false;
+					}
+					if(passed){
+						d.callback(true);
+					}
+				};
+				store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+				return d;
+			}
+		},
+		{
+			name: "Write API: reference integrity, new item with reference to existing item",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test to verify that a new item with references to existing items properly record the references in the map.
+				//	description:
+				//		Simple test to verify that a new item with references to existing items properly record the references in the map.
+			
+				var store = new dojox.data.AndOrWriteStore(dojox.data.tests.stores.AndOrWriteStore.getTestData("reference_integrity"));
+	
+				var d = new doh.Deferred();
+				var passed = true;
+				var onError = function(error, request){
+					d.errback(error);
+					t.assertTrue(false);
+				};
+				var onItem = function(item, request){
+					try{
+						//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+						//THIS IS FOR TESTING INTERNAL STATE!
+						console.log("State of reference map to item 10 before newItem: " + dojo.toJson(item[store._reverseRefMap]));
+						
+						//Create a new item and set its parent to item 10's uncle attribute.
+						var newItem = store.newItem({id: 17, name: "Item 17", friends: [item]});
+						
+						//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+						//THIS IS FOR TESTING INTERNAL STATE!
+						//Look up the references to 10, as item 17 has one on friends now.
+						var refs = item[store._reverseRefMap];
+						
+						//Assert there is a reference from 15 to item 10, on attribute friends
+						t.assertTrue(refs["17"]["friends"]);
+	
+						console.log("State of reference map to item 10 after newItem: " + dojo.toJson(refs));
+					}catch(e){
+						console.debug(e);
+						d.errback(e);
+						t.assertTrue(false);
+						passed = false;
+					}
+					if(passed){
+						d.callback(true);
+					}
+				};
+				store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+				return d;
+			}
+		},
+		{
+			name: "Write API: reference integrity, disable reference integrity",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test to verify reference integrity can be disabled.
+				//	description:
+				//		Simple test to verify reference integrity can be disabled.
+			
+				var params = dojox.data.tests.stores.AndOrWriteStore.getTestData("reference_integrity");
+				params.referenceIntegrity = false;
+				var store = new dojox.data.AndOrWriteStore(params);
+	
+				var d = new doh.Deferred();
+				var onError = function(error, request){
+					d.errback(error);
+					t.assertTrue(false);
+				};
+				var onItem = function(item, request){
+					//DO NOT EVER ACCESS THESE VARIABLES LIKE THIS!  
+					//THIS IS FOR TESTING INTERNAL STATE!
+					if(item[store._reverseRefMap] === undefined){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Disabling of reference integrity failed."));
+					}
+				};
+				store.fetchItemByIdentity({identity: 10, onError: onError, onItem: onItem});
+				return d;
+			}
+		}
+		
+	];
+	return dojox.data.tests.stores.AndOrWriteStore.tests;
+};
+doh.register("dojox.data.tests.stores.AndOrWriteStore", dojox.data.tests.stores.AndOrWriteStore.getTests());
+
+
diff --git a/dojox/data/tests/stores/AppStore.js b/dojox/data/tests/stores/AppStore.js
new file mode 100644
index 0000000..ca6d763
--- /dev/null
+++ b/dojox/data/tests/stores/AppStore.js
@@ -0,0 +1,898 @@
+dojo.provide("dojox.data.tests.stores.AppStore");
+dojo.require("dojox.data.AppStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Write");
+dojo.require("dojo.data.api.Identity");
+
+dojox.data.tests.stores.AppStore.getStore = function(preventCache){
+	preventCache = preventCache?true:false;
+	return new dojox.data.AppStore({url: dojo.moduleUrl('dojox.atom.tests.widget', 'samplefeedEdit.xml').toString(), urlPreventCache: preventCache});
+};
+
+doh.register("dojox.data.tests.stores.AppStore", 
+	[
+		function testReadAPI_fetch_all(t){
+			//	summary: 
+			//		Simple test of fetching all items 
+			//	description:
+			//		Simple test of fetching all items 
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(8, items.length);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_preventCache(t){
+			//	summary: 
+			//		Simple test of fetching all items 
+			//	description:
+			//		Simple test of fetching all items 
+			var store = dojox.data.tests.stores.AppStore.getStore(true);
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(8, items.length);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one(t){
+			//	summary: 
+			//		Simple test of fetching one item
+			//	description:
+			//		Simple test of fetching one item
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_paging(t){
+			//	summary: 
+			//		Simple test of paging
+			//	description:
+			//		Simple test of paging
+			var store = dojox.data.tests.stores.AppStore.getStore();
+			
+			var d = new doh.Deferred();
+
+			function dumpFifthFetch(items, request){
+				t.assertEqual(0, items.length);
+				d.callback(true);
+			}
+			
+			function dumpFourthFetch(items, request){
+				t.assertEqual(6, items.length);
+				request.start = 9;
+				request.count = 100;
+				request.onComplete = dumpFifthFetch;
+				store.fetch(request);
+			}
+
+			function dumpThirdFetch(items, request){
+				t.assertEqual(5, items.length);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpFourthFetch;
+				store.fetch(request);
+			}
+			
+			function dumpSecondFetch(items, request){
+				t.assertEqual(1, items.length);
+				request.start = 0;
+				request.count = 5;
+				request.onComplete = dumpThirdFetch;
+				store.fetch(request);
+			}
+
+			function dumpFirstFetch(items, request){
+				t.assertEqual(5, items.length);
+				request.start = 3;
+				request.count = 1;
+				request.onComplete = dumpSecondFetch;
+				store.fetch(request);
+			}
+
+			function completed(items, request){
+				t.assertEqual(8, items.length);
+				request.start = 1;
+				request.count = 5;
+				request.onComplete = dumpFirstFetch;
+				store.fetch(request);
+			}
+
+			function error(errData, request){
+				d.errback(errData);
+			}
+
+			store.fetch({onComplete: completed, onError: error});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern0(t){
+			//	summary: 
+			//		Simple test of fetching one item with ? pattern match
+			//	description:
+			//		Simple test of fetching one item with ? pattern match
+			var store = dojox.data.tests.stores.AppStore.getStore();
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"?est Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern1(t){
+			//	summary: 
+			//		Simple test of fetching one item with * pattern match
+			//	description:
+			//		Simple test of fetching one item with * pattern match
+			var store = dojox.data.tests.stores.AppStore.getStore();
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(8, items.length);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"*Test*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern_caseInsensitive(t){
+			//	summary: 
+			//		Simple test of fetching one item with * pattern match case insensitive
+			//	description:
+			//		Simple test of fetching one item with * pattern match case insensitive
+			var store = dojox.data.tests.stores.AppStore.getStore();
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request){
+				t.assertEqual(8, items.length);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"*test*"}, queryOptions: {ignoreCase: true}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testReadAPI_getLabel(t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+
+			var store = dojox.data.tests.stores.AppStore.getStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = store.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				t.assertEqual("Test Editable Entry #1", label);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d;
+		},
+		function testReadAPI_getLabelAttributes(t){
+			//	summary: 
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+			var store = dojox.data.tests.stores.AppStore.getStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var labelList = store.getLabelAttributes(items[0]);
+				t.assertTrue(dojo.isArray(labelList));
+				t.assertEqual("title", labelList[0]);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d;
+		},
+
+		function testReadAPI_getValue(t){
+			 //	summary: 
+			 //		Simple test of the getValue API
+			 //	description:
+			 //		Simple test of the getValue API
+			 var store = dojox.data.tests.stores.AppStore.getStore();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request){
+				 t.assertEqual(1, items.length);
+				 var item = items[0];
+				 t.assertTrue(store.hasAttribute(item,"id"));
+				 t.assertEqual(store.getValue(item,"id"), "http://example.com/samplefeedEdit.xml/entry/10");
+				 d.callback(true);
+			 }
+			 function onError(error, request){
+				 d.errback(error);
+			 }
+			 store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+		function testReadAPI_getValues(t){
+			 //	summary: 
+			 //		Simple test of the getValues API
+			 //	description:
+			 //		Simple test of the getValues API
+			 var store = dojox.data.tests.stores.AppStore.getStore();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request){
+				 t.assertEqual(1, items.length);
+				 var item = items[0];
+				 t.assertTrue(store.hasAttribute(item,"id"));
+				 var values = store.getValues(item,"id");
+				 t.assertEqual(1,values.length);
+				 t.assertEqual(values[0], "http://example.com/samplefeedEdit.xml/entry/10");
+				 d.callback(true);
+			 }
+			 function onError(error, request){
+				 d.errback(error);
+			 }
+			 store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+		function testReadAPI_isItem(t){
+			 //	summary: 
+			 //		Simple test of the isItem API
+			 //	description:
+			 //		Simple test of the isItem API
+			 var store = dojox.data.tests.stores.AppStore.getStore();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.isItem(item));
+				t.assertTrue(!store.isItem({}));
+				t.assertTrue(!store.isItem("Foo"));
+				t.assertTrue(!store.isItem(1));
+				d.callback(true);
+			 }
+			 function onError(error, request){
+				 d.errback(error);
+			 }
+			 store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+		function testReadAPI_isItem_multistore(t){
+			//	summary: 
+			//		Simple test of the isItem API across multiple store instances.
+			//	description:
+			//		Simple test of the isItem API across multiple store instances.
+			var store1 = dojox.data.tests.stores.AppStore.getStore();
+			var store2 = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+
+			function onError(error, request){
+				d.errback(error);
+			}
+
+			function onComplete1(items, request){
+				t.assertEqual(1, items.length);
+				var item1 = items[0];
+				t.assertTrue(store1.isItem(item1));
+
+				function onComplete2(items, request){
+					t.assertEqual(1, items.length);
+					var item2 = items[0];
+					t.assertTrue(store2.isItem(item2));
+					t.assertTrue(!store1.isItem(item2));
+					t.assertTrue(!store2.isItem(item1));
+					d.callback(true);
+				}
+				store2.fetch({query:{title:"Test Entry #1"}, onComplete: onComplete2, onError: onError});
+			}
+			store1.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete1, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_hasAttribute(t){
+			//	summary: 
+			//		Simple test of the hasAttribute API
+			//	description:
+			//		Simple test of the hasAttribute API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+
+			function onError(error, request){
+				d.errback(error);
+			}
+
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.hasAttribute(item,"title"));
+				t.assertTrue(store.hasAttribute(item,"summary"));
+				t.assertTrue(!store.hasAttribute(item,"bob"));
+				d.callback(true);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_containsValue(t){
+			//	summary: 
+			//		Simple test of the containsValue API
+			//	description:
+			//		Simple test of the containsValue API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"title", "Test Editable Entry #1"));
+				t.assertTrue(!store.containsValue(item,"title", "bob"));
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortDescending(t){
+			//	summary: 
+			//		Simple test of the sorting API in descending order.
+			//	description:
+			//		Simple test of the sorting API in descending order.
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			//Comparison is done as a string type (toString comparison), so the order won't be numeric
+			//So have to compare in 'alphabetic' order.
+			var order = [	"Test Entry #6",
+							"Test Entry #5",
+							"Test Entry #4",
+							"Test Entry #3",
+							"Test Entry #2",
+							"Test Entry #1",
+							"Test Editable Entry #2",
+							"Test Editable Entry #1"];
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(8, items.length);
+
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(order[i], store.getValue(items[i],"title"));
+				}
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "title", descending: true}];
+			store.fetch({query:{title:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortAscending(t){
+			//	summary: 
+			//		Simple test of the sorting API in ascending order.
+			//	description:
+			//		Simple test of the sorting API in ascending order.
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			//Comparison is done as a string type (toString comparison), so the order won't be numeric
+			//So have to compare in 'alphabetic' order.
+			var order = [	"Test Editable Entry #1",
+							"Test Editable Entry #2",
+							"Test Entry #1",
+							"Test Entry #2",
+							"Test Entry #3",
+							"Test Entry #4",
+							"Test Entry #5",
+							"Test Entry #6"];
+						
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(8, items.length);
+				var itemId = 1;
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(order[i], store.getValue(items[i],"title"));
+				}
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "title"}];
+			store.fetch({query:{title:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_isItemLoaded(t){
+			//	summary: 
+			//		Simple test of the isItemLoaded API
+			//	description:
+			//		Simple test of the isItemLoaded API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.isItemLoaded(item));
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var store = dojox.data.tests.stores.AppStore.getStore();
+			var features = store.getFeatures(); 
+			var count = 0;
+			for(var i in features){
+				t.assertTrue(( i === "dojo.data.api.Read" || i === "dojo.data.api.Write" || i === "dojo.data.api.Identity"));
+				count++;
+			}
+			t.assertEqual(3, count);
+		},
+		function testReadAPI_getAttributes(t){
+			//	summary: 
+			//		Simple test of the getAttributes API
+			//	description:
+			//		Simple test of the getAttributes API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				var attributes = store.getAttributes(item);
+				t.assertEqual(6,attributes.length);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_newItem(t){
+			//	summary: 
+			//		Simple test of the newItem API
+			//	description:
+			//		Simple test of the newItem API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			store.newItem({title: "New entry", id: "12345", content: "This is test content", author: {name:"Bob"}});
+
+			var d = new doh.Deferred();        
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"title", "New entry"));
+				t.assertTrue(store.containsValue(item, "content", "This is test content"));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{title:"New entry"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_newItemInCallback(t){
+			//	summary: 
+			//		Simple test of the newItem API
+			//	description:
+			//		Simple test of the newItem API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			store.newItem({title: "New entry", id: "12345", content: "This is test content", author: {name:"Bob"}});
+
+			var d = new doh.Deferred();
+
+			function onError(error, request){
+				d.errback(error);
+			}
+
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"title", "New entry"));
+				t.assertTrue(store.containsValue(item, "content", "This is test content"));
+
+				store.newItem({title: "New entry2", id: "12346", content: "This is test content", author: [{name:"Bob"}]});
+				
+				function onComplete1(items, request){
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item, "title", "New entry2"));
+					d.callback(true);
+				}
+				
+				store.fetch({query:{title:"New entry2"}, onComplete: onComplete1, onError: onError});
+			}
+			store.fetch({query:{title:"New entry"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_deleteItem(t){
+			//	summary: 
+			//		Simple test of the deleteItem API
+			//	description:
+			//		Simple test of the deleteItem API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+
+			function onError(error, request){
+				d.errback(error);
+			}
+
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"title", "Test Editable Entry #1"));
+				store.deleteItem(item);
+				
+				function onComplete1(items, request){
+					t.assertEqual(0, items.length);
+					d.callback(true);
+				}
+				store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete1, onError: onError});
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_setValue(t){
+			//	summary: 
+			//		Simple test of the setValue API
+			//	description:
+			//		Simple test of the setValue API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"title", "Test Editable Entry #1"));
+				store.setValue(item, "title", "Edited title");
+				t.assertEqual(store.getValue(item,"title"), "Edited title");
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_setValues(t){
+			//	summary: 
+			//		Simple test of the setValues API
+			//	description:
+			//		Simple test of the setValues API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"title", "Test Editable Entry #1"));
+				store.setValues(item, "author", [{name: "John"}, {name: "Bill", email:"bill at example.com", uri:"http://example.com/bill"}]);
+				var values = store.getValues(item,"author");
+				t.assertEqual(values[0].name, "John");
+				t.assertEqual(values[1].name, "Bill");
+				t.assertEqual(values[1].email, "bill at example.com");
+				t.assertEqual(values[1].uri, "http://example.com/bill");
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_unsetAttribute(t){
+			//	summary: 
+			//		Simple test of the unsetAttribute API
+			//	description:
+			//		Simple test of the unsetAttribute API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"title", "Test Editable Entry #1"));
+				store.unsetAttribute(item,"title");
+				t.assertTrue(!store.hasAttribute(item,"title"));
+				t.assertTrue(store.isDirty(item));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_isDirty(t){
+			//	summary: 
+			//		Simple test of the isDirty API
+			//	description:
+			//		Simple test of the isDirty API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"title", "Test Editable Entry #1"));
+				store.setValue(item, "title", "Edited title");
+				t.assertEqual(store.getValue(item,"title"), "Edited title");
+				t.assertTrue(store.isDirty(item));
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_revert(t){
+			//	summary: 
+			//		Simple test of the isDirty API
+			//	description:
+			//		Simple test of the isDirty API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onError(error, request){
+				d.errback(error);
+			}
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"title", "Test Editable Entry #1"));
+				t.assertTrue(!store.isDirty(item));
+				store.setValue(item, "title", "Edited title");
+				t.assertEqual(store.getValue(item,"title"), "Edited title");
+				t.assertTrue(store.isDirty(item));
+				store.revert();
+				
+				//Fetch again to see if it reset the state.
+				function onComplete1(items, request){
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item,"title", "Test Editable Entry #1"));
+					d.callback(true);
+				}
+				store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete1, onError: onError});
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_revert2(t){
+			//	summary: 
+			//		Simple test of the revert API
+			//	description:
+			//		Simple test of the revert API
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onError(error, request){
+				d.errback(error);
+			}
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"title", "Test Editable Entry #1"));
+				store.deleteItem(item);
+				
+				function onComplete1(items, request){
+					t.assertEqual(7, items.length);
+					store.newItem({title: "New entry", id: "12345", content: "This is test content", author: {name:"Bob"}});
+					
+					function onComplete2(items, request){
+						t.assertEqual(1, items.length);
+						store.revert();
+						
+						function onComplete3(items, request){
+							t.assertEqual(0, items.length);
+							d.callback(true);
+						}
+						store.fetch({query:{title:"New entry"}, onComplete: onComplete3, onError: onError});
+					}
+					store.fetch({query:{title:"New entry"}, onComplete: onComplete2, onError: onError});
+				}
+				store.fetch({query:{title:"*"}, onComplete: onComplete1, onError: onError});
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testReadAPI_getIdentity(t){
+			//	summary: 
+			//		Simple test of fetching the identity of an item.
+			//	description:
+			//		Simple test of fetching the identity of an item.
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var id = store.getIdentity(items[0]);
+				t.assertEqual("http://example.com/samplefeedEdit.xml/entry/10",id);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testReadAPI_getIdentityAttributes(t){
+			//	summary: 
+			//		Simple test of fetching the identity attributes off an item,
+			//	description:
+			//		Simple test of fetching the identity attributes off an item,
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				var idAttrs = store.getIdentityAttributes(items[0]);
+				t.assertEqual(1, idAttrs.length);
+				t.assertEqual("id", idAttrs[0]);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetch({query:{title:"Test Editable Entry #1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testReadAPI_fetchItemByIdentity(t){
+			//	summary: 
+			//		Simple test of fetching one atom item through its identity
+			//	description:
+			//		Simple test of fetching one atom item through its identity
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onItem(item, request) {
+				var id = store.getIdentity(item);
+				t.assertEqual("http://example.com/samplefeedEdit.xml/entry/10",id);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetchItemByIdentity({identity: "http://example.com/samplefeedEdit.xml/entry/10", onItem: onItem, onError: onError});
+			return d; //Object
+		},
+
+		function testReadAPI_fetchItemByIdentity_fails(t){
+			//	summary: 
+			//		Simple test of fetching one atom item through its identity fails correctly on no id match
+			//	description:
+			//		Simple test of fetching one atom item through its identity fails correctly on no id match
+			var store = dojox.data.tests.stores.AppStore.getStore();
+
+			var d = new doh.Deferred();
+			function onItem(item, request){
+				t.assertTrue(item === null);
+				d.callback(true);
+			}
+			function onError(error, request){
+				d.errback(error);
+			}
+			store.fetchItemByIdentity({identity: "http://example.com/samplefeedEdit.xml/entry/10/none", onItem: onItem, onError: onError});
+			return d; //Object
+		},
+
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			var testStore = dojox.data.tests.stores.AppStore.getStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(var i in readApi){
+				var member = readApi[i];
+				//Check that all the 'Read' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						console.log("Problem with function: [" + i + "]");
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		},
+		function testWriteAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
+			var testStore = dojox.data.tests.stores.AppStore.getStore();
+			var writeApi = new dojo.data.api.Write();
+			var passed = true;
+
+			for(var i in writeApi){
+				var member = writeApi[i];
+				//Check that all the 'Write' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		},
+		function testIdentityAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+			var testStore = dojox.data.tests.stores.AppStore.getStore();
+			var identityApi = new dojo.data.api.Identity();
+			var passed = true;
+
+			for(var i in identityApi){
+				var member = identityApi[i];
+				//Check that all the 'Write' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
diff --git a/dojox/data/tests/stores/AtomReadStore.js b/dojox/data/tests/stores/AtomReadStore.js
new file mode 100644
index 0000000..6c89ea1
--- /dev/null
+++ b/dojox/data/tests/stores/AtomReadStore.js
@@ -0,0 +1,637 @@
+dojo.provide("dojox.data.tests.stores.AtomReadStore");
+dojo.require("dojox.data.AtomReadStore");
+dojo.require("dojo.data.api.Read");
+
+dojox.data.tests.stores.AtomReadStore.getBlog1Store = function(){
+	return new dojox.data.AtomReadStore({url: dojo.moduleUrl("dojox.data.tests", "stores/atom1.xml").toString()});
+	//return new dojox.data.AtomReadStore({url: "/sos/feeds/blog.php"});
+};
+/*
+dojox.data.tests.stores.AtomReadStore.getBlog2Store = function(){
+	return new dojox.data.AtomReadStore({url: dojo.moduleUrl("dojox.data.tests", "stores/atom2.xml").toString()});
+};
+*/
+dojox.data.tests.stores.AtomReadStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	//console.log("In here.");
+	//console.trace();
+	d.errback(errData);
+}
+
+doh.register("dojox.data.tests.stores.AtomReadStore",
+	[
+		{
+			name: "ReadAPI:  Fetch_One",
+			timeout:	5000, //1 second
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of a basic fetch on AtomReadStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on AtomReadStore of a single item.
+
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.is(1, items.length);
+					d.callback(true);
+				}
+				atomStore.fetch({
+					query: {
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_5_Streaming",
+			timeout:	5000, //1 second.
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of a basic fetch on AtomReadStore.
+				//	description:
+				//		Simple test of a basic fetch on AtomReadStore.
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				var count = 0;
+
+				function onItem(item, requestObj){
+				  t.assertTrue(atomStore.isItem(item));
+				  count++;
+				}
+				function onComplete(items, request){
+					t.is(5, count);
+
+					t.is(null, items);
+					d.callback(true);
+				}
+				//Get everything...
+				atomStore.fetch({
+					query: {
+					},
+					onBegin: null,
+					count: 5,
+					onItem: onItem,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_Paging",
+			timeout:	5000, //1 second.
+			runTest: function(t) {
+				//	summary:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+				//	description:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+				var d = new doh.Deferred();
+				
+				function dumpFirstFetch(items, request){
+					t.is(5, items.length);
+					request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					atomStore.fetch(request);
+				}
+
+				function dumpSecondFetch(items, request){
+					console.log("dumpSecondFetch: got "+items.length);
+					t.is(1, items.length);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					atomStore.fetch(request);
+				}
+
+				function dumpThirdFetch(items, request){
+					console.log("dumpThirdFetch: got "+items.length);
+					t.is(5, items.length);
+					request.start = 2;
+					request.count = 18;
+					request.onComplete = dumpFourthFetch;
+					atomStore.fetch(request);
+				}
+
+				function dumpFourthFetch(items, request){
+					console.log("dumpFourthFetch: got "+items.length);
+					t.is(18, items.length);
+					request.start = 5;
+					request.count = 11;
+					request.onComplete = dumpFifthFetch;
+					atomStore.fetch(request);
+				}
+
+				function dumpFifthFetch(items, request){
+					console.log("dumpFifthFetch: got "+items.length);
+					t.is(11, items.length);
+					request.start = 4;
+					request.count = 16;
+					request.onComplete = dumpSixthFetch;
+					atomStore.fetch(request);
+				}
+
+				function dumpSixthFetch(items, request){
+					console.log("dumpSixthFetch: got "+items.length);
+					t.is(16, items.length);
+					d.callback(true);
+				}
+
+				function completed(items, request){
+					t.is(7, items.length);
+					request.start = 1;
+					request.count = 5;
+					request.onComplete = dumpFirstFetch;
+					atomStore.fetch(request);
+				}
+				atomStore.fetch({
+					query: {
+					},
+					count: 7,
+					onComplete: completed,
+					onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getLabel",
+			timeout:	5000, //1 second.
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var label = atomStore.getLabel(items[0]);
+					t.assertTrue(label !== null);
+					d.callback(true);
+				}
+				atomStore.fetch({
+					query: {
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)
+				});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getLabelAttributes",
+			timeout:	5000, //1 second
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = atomStore.getLabelAttributes(items[0]);
+					t.assertTrue(dojo.isArray(labelList));
+					t.assertEqual("title", labelList[0]);
+					d.callback(true);
+				}
+				atomStore.fetch({
+					query: {
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)
+				});
+				return d;
+							
+			}
+		},
+		{
+			name: "ReadAPI:  getValue",
+			timeout:	5000, //1 second
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					t.assertTrue(atomStore.getValue(items[0], "summary") !== null);
+					t.assertTrue(atomStore.getValue(items[0], "content") !== null);
+					t.assertTrue(atomStore.getValue(items[0], "published") !== null);
+					t.assertTrue(atomStore.getValue(items[0], "updated") !== null);
+					console.log("typeof updated = "+typeof(atomStore.getValue(items[0], "updated")));
+					t.assertTrue(atomStore.getValue(items[0], "updated").getFullYear);
+					d.callback(true);
+				}
+
+				//Get one item and look at it.
+				atomStore.fetch({
+					query: {
+					},
+					count: 1,
+					onComplete: completedAll,
+					onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getValue_Failure",
+			timeout:	5000, //1 second
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+				var passed = false;
+				try{
+					var value = store.getValue("NotAnItem", "foo");
+				}catch(e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+			}
+		},
+		{
+			name: "ReadAPI:  getValues",
+			timeout:	5000, //1 second
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					var summary = atomStore.getValues(items[0], "summary");
+					t.assertTrue(dojo.isArray(summary));
+
+					var content = atomStore.getValues(items[0], "content");
+					t.assertTrue(dojo.isArray(content));
+
+					var published = atomStore.getValues(items[0], "published");
+					t.assertTrue(dojo.isArray(published));
+
+					var updated = atomStore.getValues(items[0], "updated");
+					t.assertTrue(dojo.isArray(updated));
+					d.callback(true);
+				}
+				//Get one item and look at it.
+				atomStore.fetch({
+					query: {
+					},
+					count: 1,
+					onComplete: completedAll,
+					onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error,
+					t,
+					d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getValues_Failure",
+			timeout:	5000, //1 second
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+				var passed = false;
+				try{
+					var value = store.getValues("NotAnItem", "foo");
+				}catch(e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+			}
+		},
+		{
+			name: "ReadAPI:  isItem",
+			timeout:	5000, //1 second
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the isItem function of the store
+				//	description:
+				//		Simple test of the isItem function of the store
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(5, items.length);
+					for(var i=0; i < items.length; i++){
+						t.assertTrue(atomStore.isItem(items[i]));
+					}
+					d.callback(true);
+				}
+
+				//Get everything...
+				atomStore.fetch({
+						query: {
+						},
+						count: 5,
+						onComplete: completedAll,
+						onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)
+					});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  hasAttribute",
+			timeout:	5000, //1 second
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the hasAttribute function of the store
+				//	description:
+				//		Simple test of the hasAttribute function of the store
+
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(items[0] !== null);
+					var count = 0;
+					console.log("hasAttribute");
+					t.assertTrue(atomStore.hasAttribute(items[0], "author"));
+					t.assertTrue(atomStore.hasAttribute(items[0], "published"));
+					t.assertTrue(atomStore.hasAttribute(items[0], "updated"));
+					t.assertTrue(atomStore.hasAttribute(items[0], "category"));
+					t.assertTrue(atomStore.hasAttribute(items[0], "id"));
+					t.assertTrue(!atomStore.hasAttribute(items[0], "foo"));
+					t.assertTrue(!atomStore.hasAttribute(items[0], "bar"));
+					
+					
+					t.assertTrue(atomStore.hasAttribute(items[0], "summary"));
+					t.assertTrue(atomStore.hasAttribute(items[0], "content"));
+					t.assertTrue(atomStore.hasAttribute(items[0], "title"));
+					
+					
+					var summary = atomStore.getValue(items[0], "summary");
+					var content = atomStore.getValue(items[0], "content");
+					var title = atomStore.getValue(items[0], "title");
+										
+					t.assertTrue(summary && summary.text && summary.type == "html");
+					t.assertTrue(content && content.text && content.type == "html");
+					t.assertTrue(title && title.text && title.type == "html");
+
+					//Test that null attributes throw an exception
+					try{
+						atomStore.hasAttribute(items[0], null);
+						t.assertTrue(false);
+					}catch (e){
+						
+					}
+					d.callback(true);
+				}
+
+				//Get one item...
+				atomStore.fetch({
+					query: {
+					},
+					count: 1,
+						onComplete: onComplete,
+						onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  containsValue",
+			timeout:	5000, //1 second
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the containsValue function of the store
+				//	description:
+				//		Simple test of the containsValue function of the store
+
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+
+					t.assertTrue(atomStore.containsValue(items[0], "id","http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/"));
+
+					d.callback(true);
+				}
+
+				//Get one item...
+				atomStore.fetch({
+					query: {
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getAttributes",
+			timeout:	5000, //1 second
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getAttributes function of the store
+				//	description:
+				//		Simple test of the getAttributes function of the store
+
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(atomStore.isItem(items[0]));
+
+					var attributes = atomStore.getAttributes(items[0]);
+					console.log("getAttributes 4: "+attributes.length);
+					t.is(10, attributes.length);
+					d.callback(true);
+				}
+
+				//Get everything...
+				atomStore.fetch({
+						query: {
+						},
+						count: 1,
+						onComplete: onComplete,
+						onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)
+					});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  fetch_Category",
+			timeout:	5000, //1 second.
+			runTest: function(t) {
+				//	summary:
+				//		Retrieve items from the store by category
+				//	description:
+				//		Simple test of the getAttributes function of the store
+
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(2, items.length);
+					t.assertTrue(atomStore.isItem(items[0]));
+					t.assertTrue(atomStore.isItem(items[1]));
+
+					var categories = atomStore.getValues(items[0], "category");
+					t.assertTrue(dojo.some(categories, function(category){
+						return category.term == "aol";
+					}));
+					categories = atomStore.getValues(items[1], "category");
+					t.assertTrue(dojo.some(categories, function(category){
+						return category.term == "aol";
+					}));
+
+					d.callback(true);
+				}
+
+				//Get everything...
+				atomStore.fetch({
+					query: {
+						category: "aol"
+					},
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  fetch_byID",
+			timeout:	5000, //1 second.
+			runTest: function(t) {
+				//	summary:
+				//		Retrieve items from the store by category
+				//	description:
+				//		Simple test of the getAttributes function of the store
+
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					console.log("getById: items.length="+items.length)
+					t.is(1, items.length);
+					t.assertTrue(atomStore.isItem(items[0]));
+
+					var title = atomStore.getValue(items[0], "title");
+					console.log("getById: title.text="+title.text)
+					t.assertTrue(title.text == "Dojo Grid has landed");
+
+					d.callback(true);
+				}
+
+				//Get everything...
+				atomStore.fetch({
+					query: {
+						id: "http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/"
+					},
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  fetch_alternate",
+			timeout:	5000, //1 second.
+			runTest: function(t) {
+				//	summary:
+				//		Retrieve items from the store by category
+				//	description:
+				//		Simple test of the getAttributes function of the store
+
+				var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(atomStore.isItem(items[0]));
+
+					var alternate = atomStore.getValue(items[0], "alternate");
+					t.assertEqual(alternate.href, "http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/");
+
+					d.callback(true);
+				}
+
+				//Get everything...
+				atomStore.fetch({
+					query: {
+						id: "http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/"
+					},
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.AtomReadStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary:
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var atomStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+
+			var features = atomStore.getFeatures();
+			var count = 0;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read"));
+				count++;
+			}
+			t.assertTrue(count === 1);
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.AtomReadStore.getBlog1Store();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						console.log("Looking at function: [" + i + "]");
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							console.log("Problem with function: [" + i + "].   Got value: " + testStoreMember);
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
diff --git a/dojox/data/tests/stores/CssClassStore.js b/dojox/data/tests/stores/CssClassStore.js
new file mode 100755
index 0000000..8d657b6
--- /dev/null
+++ b/dojox/data/tests/stores/CssClassStore.js
@@ -0,0 +1,964 @@
+dojo.provide("dojox.data.tests.stores.CssClassStore");
+dojo.require("dojox.data.CssClassStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+
+dojox.data.tests.stores.CssClassStore.createStore = function(context){
+	//  summary:
+	//		A simple helper function for getting the sample data used in each of the tests.
+	//  description:
+	//		A simple helper function for getting the sample data used in each of the tests.
+	var store = null;
+	if(dojo.isBrowser){
+		if(!dojox.data.tests.stores.CssClassStore._loaded){
+			var head = dojo.doc.getElementsByTagName('head')[0];
+			var link = document.createElement('link');
+			link.href = dojo.moduleUrl('dojox.data.tests.stores', 'test1.css').toString();
+			link.rel = "stylesheet";
+			link.type = "text/css";
+			head.appendChild(link);
+			var style;
+			var text;
+			if(dojo.isIE){
+				style = document.createStyleSheet();
+				style.cssText = '@import "'+dojo.moduleUrl('dojox.data.tests.stores', 'test2.css').toString()+'";';
+			}else{
+				style = document.createElement('style');
+				text = document.createTextNode('@import "'+dojo.moduleUrl('dojox.data.tests.stores', 'test2.css').toString()+'";');
+				style.appendChild(text);
+				head.appendChild(style);
+			}
+			if(dojo.isIE){
+				style = document.createStyleSheet();
+				style.cssText = '.embeddedTestClass { text-align: center; }';
+			}else{
+				style = document.createElement('style');
+				text = document.createTextNode('.embeddedTestClass { text-align: center; }');
+				style.appendChild(text);
+				head.appendChild(style);
+			}
+			dojox.data.tests.stores.CssClassStore._loaded = true;
+		}
+		store = new dojox.data.CssClassStore({context: context});
+	}else{
+		// When running tests in Rhino, xhrGet is not available,
+		// so we have the file data in the code below.
+		
+		// TODO: What are the stipulations re: DOM ? Can I do the same as above?
+	}
+	return store;
+};
+
+dojox.data.tests.stores.CssClassStore.verifyItems = function(cssClassStore, items, attribute, compareArray){
+	//  summary:
+	//		A helper function for validating that the items array is ordered
+	//		the same as the compareArray
+	if(items.length != compareArray.length){ return false; }
+	for(var i = 0; i < items.length; i++){
+		// Safari is dumb, see comment in CssClassStore about bug in selectorText
+		if(!(cssClassStore.getValue(items[i], attribute) === (dojo.isWebKit?compareArray[i].toLowerCase():compareArray[i]))){
+			return false; //Boolean
+		}
+	}
+	return true; //Boolean
+};
+
+dojox.data.tests.stores.CssClassStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	for (var i in errData) {
+		console.log(errData[i]);
+	}
+	d.errback(errData);	
+};
+
+doh.register("dojox.data.tests.stores.CssClassStore", 
+	[
+		{
+			name: "testReadAPI_fetch",
+			timeout:	10000, //10 seconds.  
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on CssClassStore.
+				//	description:
+				//		Simple test of a basic fetch on CssClassStore.
+				var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.assertTrue(items.length === 3);
+					d.callback(true);
+				}
+
+				//Get everything...
+				cssClassStore.fetch({
+					query: {'class': '*TestClass'},
+					onComplete: completedAll,
+					onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		function testReadAPI_fetch_all(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CssClassStore.
+			//	description:
+			//		Simple test of a basic fetch on CssClassStore.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore(['dojox/data/tests/stores/test1.css', 'dojox/data/tests/stores/test2.css']);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue(items.length === 3);
+				d.callback(true);
+			}
+			
+			//Get everything...
+			cssClassStore.fetch({
+				onComplete: completedAll,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_withinContext(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CssClassStore.
+			//	description:
+			//		Simple test of a basic fetch on CssClassStore.
+			//dojox.data.tests.stores.CssClassStore.loadStylesheets();
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore(['dojox/data/tests/stores/test1.css']);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue(items.length === 1);
+				d.callback(true);
+			}
+			
+			//Get everything...
+			cssClassStore.fetch({
+				query: {'class': '*TestClass'},
+				onComplete: completedAll,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_withinMultipleSheetContext(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CssClassStore.
+			//	description:
+			//		Simple test of a basic fetch on CssClassStore.
+			//dojox.data.tests.stores.CssClassStore.loadStylesheets();
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore(['dojox/data/tests/stores/test1.css', 'dojox/data/tests/stores/test2.css']);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue(items.length === 2);
+				d.callback(true);
+			}
+			
+			//Get everything...
+			cssClassStore.fetch({
+				query: {'class': '*TestClass'},
+				onComplete: completedAll,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_switchContext(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CssClassStore.
+			//	description:
+			//		Simple test of a basic fetch on CssClassStore.
+			//dojox.data.tests.stores.CssClassStore.loadStylesheets();
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore(['dojox/data/tests/stores/test1.css', 'dojox/data/tests/stores/test2.css']);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue(items.length === 2);
+
+				function completedAllTwo(items){
+					t.assertTrue(items.length === 1);
+					d.callback(true);
+				}
+
+				cssClassStore.setContext(['dojox/data/tests/stores/test1.css']);
+				cssClassStore.fetch({
+					query: {'class': '*TestClass'},
+					onComplete: completedAllTwo,
+					onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+				});
+			}
+			
+			//Get everything...
+			cssClassStore.fetch({
+				query: {'class': '*TestClass'},
+				onComplete: completedAll,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.is(1, items.length);
+				d.callback(true);
+			}
+			cssClassStore.fetch({
+				query: {'class': '.linkTestClass'}, 
+				onComplete: onComplete, 
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one_sans(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.is(1, items.length);
+				d.callback(true);
+			}
+			cssClassStore.fetch({
+				query: {'classSans': 'linkTestClass'}, 
+				onComplete: onComplete, 
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_Multiple(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			
+			var d = new doh.Deferred();
+			var done = [false, false];
+
+			function onCompleteOne(items, request){
+				done[0] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+
+			function onCompleteTwo(items, request){
+				done[1] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			
+			try{
+				cssClassStore.fetch({ 
+					query: {'class': '.embeddedTestClass'}, 
+					onComplete: onCompleteOne, 
+					onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+				});
+				cssClassStore.fetch({ 
+					query: {'class': '.linkTestClass'}, 
+					onComplete: onCompleteTwo, 
+					onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+				});
+			}catch(e){
+				for(var i in e){
+					console.log(e[i]);
+				}
+			}
+
+			return d; //Object
+		},
+		function testReadAPI_fetch_MultipleMixed(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			
+			var d = new doh.Deferred();
+
+			var done = [false, false];
+			function onComplete(items, request){
+				done[0] = true;
+				t.is(1, items.length);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssClassStore about bug in selectorText
+					t.is('.linktestclass', cssClassStore.getValue(items[0], 'class'));
+				}else{
+					t.is('.linkTestClass', cssClassStore.getValue(items[0], 'class'));
+				}
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			
+			function onItem(item){
+				done[1] = true;
+				t.assertTrue(item !== null);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssClassStore about bug in selectorText
+					t.is('.embeddedtestclass', cssClassStore.getValue(item, 'class'));
+				}else{
+					t.is('.embeddedTestClass', cssClassStore.getValue(item, 'class'));
+				}
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+
+			cssClassStore.fetch({ 
+				query: {'class': '.linkTestClass'}, 
+				onComplete: onComplete, 
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			
+			cssClassStore.fetch({
+				query: {'classSans': 'embeddedTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_streaming(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+
+			var d = new doh.Deferred();
+			var count = 0;
+
+			function onBegin(size, requestObj){
+				t.assertTrue(size === 3);
+			}
+			function onItem(item, requestObj){
+				t.assertTrue(cssClassStore.isItem(item));
+				count++;
+			}
+			function onComplete(items, request){
+				t.is(3, count);
+				t.is(null, items);
+			    d.callback(true);
+			}
+
+			//Get everything...
+			cssClassStore.fetch({
+				query: {'class': '*TestClass'},
+				onBegin: onBegin,
+				onItem: onItem, 
+				onComplete: onComplete,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_paging(t){
+			 //	summary: 
+			 //		Test of multiple fetches on a single result.  Paging, if you will.
+			 //	description:
+			 //		Test of multiple fetches on a single result.  Paging, if you will.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			
+			var d = new doh.Deferred();
+
+			function dumpThirdFetch(items, request){
+				t.is(2, items.length);
+			    d.callback(true);
+			}
+
+			function dumpSecondFetch(items, request){
+				t.is(1, items.length);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssClassStore about bug in selectorText
+					t.is('.embeddedtestclass', cssClassStore.getValue(items[0], 'class'));
+				}else{
+					t.is('.embeddedTestClass', cssClassStore.getValue(items[0], 'class'));
+				}
+				request.start = 0;
+				request.count = 2;
+				request.onComplete = dumpThirdFetch;
+				cssClassStore.fetch(request);
+			}
+
+			function dumpFirstFetch(items, request){
+				t.is(3, items.length);
+				request.start = 2;
+				request.count = 1;
+				request.onComplete = dumpSecondFetch;
+				cssClassStore.fetch(request);
+			}
+
+			cssClassStore.fetch({
+				query: {'class': '*TestClass'},
+				onComplete: dumpFirstFetch,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+
+		},
+		
+		function testReadAPI_getLabel(t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = cssClassStore.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssClassStore about bug in selectorText
+					t.assertEqual(".linktestclass", label);
+				}else{
+					t.assertEqual(".linkTestClass", label);
+				}
+				d.callback(true);
+			}
+			cssClassStore.fetch({
+				query: {'classSans': 'linkTestClass'}, 
+				onComplete: onComplete, 
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getLabelAttributes(t){
+			//	summary: 
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var labelList = cssClassStore.getLabelAttributes(items[0]);
+				t.assertTrue(dojo.isArray(labelList));
+				t.assertEqual("class", labelList[0]);
+				d.callback(true);
+			}
+			cssClassStore.fetch({ 
+				query: {'classSans': 'linkTestClass'}, 
+				onComplete: onComplete, 
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getValue(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssClassStore about bug in selectorText
+					t.is('.linktestclass', cssClassStore.getValue(item,'class'));
+					t.is('linktestclass', cssClassStore.getValue(item,'classSans'));
+				}else{
+					t.is('.linkTestClass', cssClassStore.getValue(item,'class'));
+					t.is('linkTestClass', cssClassStore.getValue(item,'classSans'));
+				}
+				d.callback(true);	
+			}
+			cssClassStore.fetch({
+				query: {'classSans': 'linkTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getValue_2(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssClassStore about bug in selectorText
+					t.is('.importtestclass', cssClassStore.getValue(item,'class'));
+					t.is('importtestclass', cssClassStore.getValue(item,'classSans'));
+				}else{
+					t.is('.importTestClass', cssClassStore.getValue(item,'class'));
+					t.is('importTestClass', cssClassStore.getValue(item,'classSans'));
+				}
+				d.callback(true);	
+			}
+			cssClassStore.fetch({
+				query: {'classSans': 'importTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getValues(t){
+			//	summary: 
+			//		Simple test of the getValues function of the store.
+			//	description:
+			//		Simple test of the getValues function of the store.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var values = cssClassStore.getValues(item,'class');
+				t.assertTrue(dojo.isArray(values));
+				t.is(1, values.length);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssClassStore about bug in selectorText
+					t.is('.embeddedtestclass', values[0]);
+				}else{
+					t.is('.embeddedTestClass', values[0]);
+				}
+				d.callback(true);	
+			}
+			cssClassStore.fetch({
+				query: {'classSans': 'embeddedTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_isItem(t){
+			//	summary: 
+			//		Simple test of the isItem function of the store
+			//	description:
+			//		Simple test of the isItem function of the store
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(cssClassStore.isItem(item));
+				t.assertTrue(!cssClassStore.isItem({}));
+				t.assertTrue(!cssClassStore.isItem({ item: "not an item" }));
+				t.assertTrue(!cssClassStore.isItem("not an item"));
+				t.assertTrue(!cssClassStore.isItem(["not an item"]));
+				d.callback(true);	
+			}
+			cssClassStore.fetch({
+				query: {'classSans': 'embeddedTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_hasAttribute(t){
+			//	summary: 
+			//		Simple test of the hasAttribute function of the store
+			//	description:
+			//		Simple test of the hasAttribute function of the store
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(cssClassStore.hasAttribute(item, 'class'));
+				t.assertTrue(cssClassStore.hasAttribute(item, 'classSans'));
+				t.assertTrue(!cssClassStore.hasAttribute(item, "Year"));
+				t.assertTrue(!cssClassStore.hasAttribute(item, "Nothing"));
+				t.assertTrue(!cssClassStore.hasAttribute(item, "title"));
+
+				//Test that null attributes throw an exception
+				var passed = false;
+				try{
+					cssClassStore.hasAttribute(item, null);
+				}catch (e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+				d.callback(true);	
+			}
+			cssClassStore.fetch({
+				query: {'classSans': 'embeddedTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_containsValue(t){
+			//	summary: 
+			//		Simple test of the containsValue function of the store
+			//	description:
+			//		Simple test of the containsValue function of the store
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+ 			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssClassStore about bug in selectorText
+					t.assertTrue(cssClassStore.containsValue(item, 'class', '.embeddedtestclass'));
+					t.assertTrue(cssClassStore.containsValue(item, 'classSans', 'embeddedtestclass'));
+				}else{
+					t.assertTrue(cssClassStore.containsValue(item, 'class', '.embeddedTestClass'));
+					t.assertTrue(cssClassStore.containsValue(item, 'classSans', 'embeddedTestClass'));
+				}
+				t.assertTrue(!cssClassStore.containsValue(item, 'class', '.embeddedTestClass2'));
+				t.assertTrue(!cssClassStore.containsValue(item, 'classSans', 'embeddedTestClass	'));
+				t.assertTrue(!cssClassStore.containsValue(item, 'class', null));
+
+				//Test that null attributes throw an exception
+				var passed = false;
+				try{
+					cssClassStore.containsValue(item, null, "foo");
+				}catch (e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+				d.callback(true);	
+			}
+			cssClassStore.fetch({
+				query: {'classSans': 'embeddedTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getAttributes(t){
+			//	summary: 
+			//		Simple test of the getAttributes function of the store
+			//	description:
+			//		Simple test of the getAttributes function of the store
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(cssClassStore.isItem(item));
+
+				var attributes = cssClassStore.getAttributes(item);
+				t.is(2, attributes.length);
+				for(var i = 0; i < attributes.length; i++){
+					t.assertTrue((attributes[i] === 'class' || attributes[i] === 'classSans'));
+				}
+				d.callback(true);	
+			}
+			cssClassStore.fetch({
+				query: {'classSans': 'embeddedTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+
+			var features = cssClassStore.getFeatures(); 
+			var count = 0;
+			for(var i in features){
+				t.assertTrue(i === "dojo.data.api.Read" || i === "dojo.data.api.Identity");
+				count++;
+			}
+			t.assertTrue(count === 2);
+		},
+		function testReadAPI_fetch_patternMatch0(t){
+			//	summary: 
+			//		Function to test pattern matching of everything swith Cla in it
+			//	description:
+			//		Function to test pattern matching of everything with Cla in it
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(3, items.length);
+				var valueArray = ['linkTestClass', 'importTestClass', 'embeddedTestClass'];
+				t.assertTrue(dojox.data.tests.stores.CssClassStore.verifyItems(cssClassStore, items, 'classSans', valueArray));
+				d.callback(true);
+			}
+			
+			cssClassStore.fetch({
+				query: {'class': '*TestCla**'},
+				onComplete: completed,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch_caseInsensitive(t){
+			//	summary: 
+			//		Function to test exact pattern match with case insensitivity set.
+			//	description:
+			//		Function to test exact pattern match with case insensitivity set.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(1, items.length);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssClassStore about bug in selectorText
+					t.assertTrue(cssClassStore.getValue(items[0], 'class') === '.linktestclass');
+				}else{
+					t.assertTrue(cssClassStore.getValue(items[0], 'class') === '.linkTestClass');
+				}
+				d.callback(true);
+			}
+
+			cssClassStore.fetch({
+				query: {'class': '.LINKtEsTclass'},
+				queryOptions: {ignoreCase: true},
+				onComplete: completed,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch_caseSensitive(t){
+			//	summary: 
+			//		Function to test exact pattern match with case insensitivity set.
+			//	description:
+			//		Function to test exact pattern match with case insensitivity set.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			var d = new doh.Deferred();
+			function completed(items, request){
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssClassStore about bug in selectorText
+					t.is(1, items.length);
+				}else{
+					t.is(0, items.length);
+				}
+				d.callback(true);
+			}
+
+			cssClassStore.fetch({
+				query: {'class': '.LINKtEsTclass'},
+				queryOptions: {ignoreCase: false},
+				onComplete: completed,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortAlphabetic(t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering.
+			//	description:
+			//		Function to test sorting alphabetic ordering.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ 	'.embeddedTestClass',
+										'.importTestClass',
+										'.linkTestClass'
+				];
+				t.is(3, items.length);
+				t.assertTrue(dojox.data.tests.stores.CssClassStore.verifyItems(cssClassStore, items, 'class', orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: 'class'}];
+			cssClassStore.fetch({
+				query: {'class': '*TestClass'},
+				sort: sortAttributes,
+				onComplete: completed,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortAlphabeticDescending(t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering in descending mode.
+			//	description:
+			//		Function to test sorting alphabetic ordering in descending mode.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			var d = new doh.Deferred();
+
+
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ 	'linkTestClass',
+										'importTestClass',
+										'embeddedTestClass'
+					];
+
+				console.debug(items);
+
+				t.is(3, items.length);
+				t.assertTrue(dojox.data.tests.stores.CssClassStore.verifyItems(cssClassStore, items, 'classSans', orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: "classSans", descending: true}];
+			cssClassStore.fetch({
+				query: {'class': '*TestClass'},
+				sort: sortAttributes,
+				onComplete: completed,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			var testStore = dojox.data.tests.stores.CssClassStore.createStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(var i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						console.log("Looking at function: [" + i + "]");
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							console.log("Problem with function: [" + i + "].   Got value: " + testStoreMember);
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		},
+		function testIdentityAPI_fetchItemByIdentity(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				d.callback(true);
+			}
+			cssClassStore.fetchItemByIdentity({
+				identity: ".linkTestClass",
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testIdentityAPI_fetchItemByIdentity_bad1(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+			cssClassStore.fetchItemByIdentity({
+				identity: ".bsClass",
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testIdentityAPI_fetchItemByIdentity_bad2(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+			cssClassStore.fetchItemByIdentity({
+				identity: 'linkTestClass', // missing the '.'!
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testIdentityAPI_fetchItemByIdentity_bad3(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+			cssClassStore.fetchItemByIdentity({
+				identity: '9999999',
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d;
+		},
+		function testIdentityAPI_getIdentity(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(3, items.length);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssClassStore about bug in selectorText
+					t.assertTrue(cssClassStore.getIdentity(items[0]) === '.embeddedtestclass');
+					t.assertTrue(cssClassStore.getIdentity(items[1]) === '.importtestclass');
+					t.assertTrue(cssClassStore.getIdentity(items[2]) === '.linktestclass');
+				}else{
+					t.assertTrue(cssClassStore.getIdentity(items[0]) === '.embeddedTestClass');
+					t.assertTrue(cssClassStore.getIdentity(items[1]) === '.importTestClass');
+					t.assertTrue(cssClassStore.getIdentity(items[2]) === '.linkTestClass');
+				}
+				d.callback(true);
+			}
+			//Get everything...
+			cssClassStore.fetch({
+				query: {'class': '*TestClass'},
+				sort: [{attribute: 'class'}],
+				onComplete: completed,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testIdentityAPI_getIdentityAttributes(t){
+			//	summary: 
+			//		Simple test of the getIdentityAttributes
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			var cssClassStore = dojox.data.tests.stores.CssClassStore.createStore();
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(cssClassStore.isItem(item));
+				var attrs = cssClassStore.getIdentityAttributes(item);
+				t.assertTrue(dojo.isArray(attrs));
+				t.is(1, attrs.length);
+				t.assertEqual(attrs[0], 'class'); 
+				d.callback(true);	
+			}
+			cssClassStore.fetchItemByIdentity({
+				identity: ".linkTestClass",
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssClassStore.error, t, d)
+			});
+		   	return d;
+		}
+	]
+);
+
diff --git a/dojox/data/tests/stores/CssRuleStore.js b/dojox/data/tests/stores/CssRuleStore.js
new file mode 100755
index 0000000..86c333e
--- /dev/null
+++ b/dojox/data/tests/stores/CssRuleStore.js
@@ -0,0 +1,838 @@
+dojo.provide("dojox.data.tests.stores.CssRuleStore");
+dojo.require("dojox.data.CssRuleStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+
+dojox.data.tests.stores.CssRuleStore.createStore = function(context){
+	//  summary:
+	//		A simple helper function for getting the sample data used in each of the tests.
+	//  description:
+	//		A simple helper function for getting the sample data used in each of the tests.
+	var store = null;
+	if(dojo.isBrowser){
+		if(!dojox.data.tests.stores.CssRuleStore._loaded){
+			var head = dojo.doc.getElementsByTagName('head')[0];
+			var link = document.createElement('link');
+			link.href = dojo.moduleUrl('dojox.data.tests.stores', 'test1.css').toString();
+			link.rel = "stylesheet";
+			link.type = "text/css";
+			head.appendChild(link);
+			var style;
+			var text;
+			if(dojo.isIE){
+				style = document.createStyleSheet();
+				style.cssText = '@import "'+dojo.moduleUrl('dojox.data.tests.stores', 'test2.css').toString()+'";';
+			}else{
+				style = document.createElement('style');
+				text = document.createTextNode('@import "'+dojo.moduleUrl('dojox.data.tests.stores', 'test2.css').toString()+'";');
+				style.appendChild(text);
+				head.appendChild(style);
+			}
+			if(dojo.isIE){
+				style = document.createStyleSheet();
+				style.cssText = '.embeddedTestClass { text-align: center; }';
+			}else{
+				style = document.createElement('style');
+				text = document.createTextNode('.embeddedTestClass { text-align: center; }');
+				style.appendChild(text);
+				head.appendChild(style);
+			}
+			dojox.data.tests.stores.CssRuleStore._loaded = true;
+		}
+		store = new dojox.data.CssRuleStore({context: context});
+	}else{
+		// When running tests in Rhino, xhrGet is not available,
+		// so we have the file data in the code below.
+		
+		// TODO: What are the stipulations re: DOM ? Can I do the same as above?
+	}
+	return store;
+} ;
+
+dojox.data.tests.stores.CssRuleStore.verifyItems = function(cssRuleStore, items, attribute, compareArray){
+	//  summary:
+	//		A helper function for validating that the items array is ordered
+	//		the same as the compareArray
+	if(items.length != compareArray.length){ return false; }
+	for(var i = 0; i < items.length; i++){
+		if(!(cssRuleStore.getValue(items[i], attribute) === (dojo.isWebKit?compareArray[i].toLowerCase():compareArray[i]))){
+			return false; //Boolean
+		}
+	}
+	return true; //Boolean
+};
+
+dojox.data.tests.stores.CssRuleStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	for (var i in errData) {
+		console.log(errData[i]);
+	}
+	d.errback(errData);	
+};
+
+doh.register("dojox.data.tests.stores.CssRuleStore", 
+	[
+		{
+			name: "testReadAPI_fetch",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on CssRuleStorem longer timeout because initial load can sometimes take a bit..
+				//	description:
+				//		Simple test of a basic fetch on CssRuleStorem longer timeout because initial load can sometimes take a bit.
+				var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.assertTrue(items.length === 3);
+					d.callback(true);
+				}
+
+				//Get everything...
+				cssRuleStore.fetch({
+					query: {'selector': '*TestClass'},
+					onComplete: completedAll,
+					onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		function testReadAPI_fetch_all(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CssRuleStore.
+			//	description:
+			//		Simple test of a basic fetch on CssClassStore.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore(['dojox/data/tests/stores/test1.css', 'dojox/data/tests/stores/test2.css']);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue(items.length === 3);
+				d.callback(true);
+			}
+			
+			//Get everything...
+			cssRuleStore.fetch({
+				onComplete: completedAll,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_withinContext(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CssRuleStore.
+			//	description:
+			//		Simple test of a basic fetch on CssRuleStore.
+			//dojox.data.tests.stores.CssRuleStore.loadStylesheets();
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore(['dojox/data/tests/stores/test1.css']);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue(items.length === 1);
+				d.callback(true);
+			}
+			
+			//Get everything...
+			cssRuleStore.fetch({
+				query: {'selector': '*TestClass'},
+				onComplete: completedAll,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_withinMultipleSheetContext(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CssRuleStore.
+			//	description:
+			//		Simple test of a basic fetch on CssRuleStore.
+			//dojox.data.tests.stores.CssRuleStore.loadStylesheets();
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore(['dojox/data/tests/stores/test1.css', 'dojox/data/tests/stores/test2.css']);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue(items.length === 2);
+				d.callback(true);
+			}
+			
+			//Get everything...
+			cssRuleStore.fetch({
+				query: {'selector': '*TestClass'},
+				onComplete: completedAll,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_switchContext(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CssRuleStore.
+			//	description:
+			//		Simple test of a basic fetch on CssRuleStore.
+			//dojox.data.tests.stores.CssRuleStore.loadStylesheets();
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore(['dojox/data/tests/stores/test1.css', 'dojox/data/tests/stores/test2.css']);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue(items.length === 2);
+
+				function completedAllTwo(items){
+					t.assertTrue(items.length === 1);
+					d.callback(true);
+				}
+
+				cssRuleStore.setContext(['dojox/data/tests/stores/test1.css']);
+				cssRuleStore.fetch({
+					query: {'selector': '*TestClass'},
+					onComplete: completedAllTwo,
+					onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+				});
+			}
+			
+			//Get everything...
+			cssRuleStore.fetch({
+				query: {'selector': '*TestClass'},
+				onComplete: completedAll,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.is(1, items.length);
+				d.callback(true);
+			}
+			cssRuleStore.fetch({
+				query: {'selector': '.linkTestClass'}, 
+				onComplete: onComplete, 
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one_longer(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.is(1, items.length);
+				d.callback(true);
+			}
+			cssRuleStore.fetch({
+				query: {'selector': '.linkTestClass .test'}, 
+				onComplete: onComplete, 
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_Multiple(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			
+			var d = new doh.Deferred();
+			var done = [false, false];
+
+			function onCompleteOne(items, request){
+				done[0] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+
+			function onCompleteTwo(items, request){
+				done[1] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			
+			try{
+				cssRuleStore.fetch({ 
+					query: {'selector': '.embeddedTestClass'}, 
+					onComplete: onCompleteOne, 
+					onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+				});
+				cssRuleStore.fetch({ 
+					query: {'selector': '.linkTestClass'}, 
+					onComplete: onCompleteTwo, 
+					onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+				});
+			}catch(e){
+				for(var i in e){
+					console.log(e[i]);
+				}
+			}
+
+			return d; //Object
+		},
+		function testReadAPI_fetch_MultipleMixed(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			
+			var d = new doh.Deferred();
+
+			var done = [false, false];
+			function onComplete(items, request){
+				done[0] = true;
+				t.is(1, items.length);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssRuleStore about bug in selectorText
+					t.is('.embeddedtestclass', cssRuleStore.getValue(items[0], 'selector'));
+				}else{
+					t.is('.embeddedTestClass', cssRuleStore.getValue(items[0], 'selector'));
+				}
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			
+			function onItem(item){
+				done[1] = true;
+				t.assertTrue(item !== null);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssRuleStore about bug in selectorText
+					t.is('.linktestclass .test', cssRuleStore.getValue(item, 'selector'));
+				}else{
+					t.is('.linkTestClass .test', cssRuleStore.getValue(item, 'selector'));
+				}
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+
+			cssRuleStore.fetch({ 
+				query: {'selector': '.embeddedTestClass'}, 
+				onComplete: onComplete, 
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			
+			cssRuleStore.fetch({
+				query: {'selector': '.linkTestClass .test'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_streaming(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+
+			var d = new doh.Deferred();
+			var count = 0;
+
+			function onBegin(size, requestObj){
+				t.assertTrue(size === 3);
+			}
+			function onItem(item, requestObj){
+				t.assertTrue(cssRuleStore.isItem(item));
+				count++;
+			}
+			function onComplete(items, request){
+				t.is(3, count);
+				t.is(null, items);
+			    d.callback(true);
+			}
+
+			//Get everything...
+			cssRuleStore.fetch({
+				query: {'selector': '*TestClass'},
+				onBegin: onBegin,
+				onItem: onItem, 
+				onComplete: onComplete,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_paging(t){
+			 //	summary: 
+			 //		Test of multiple fetches on a single result.  Paging, if you will.
+			 //	description:
+			 //		Test of multiple fetches on a single result.  Paging, if you will.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			
+			var d = new doh.Deferred();
+
+			function dumpThirdFetch(items, request){
+				t.is(2, items.length);
+			    d.callback(true);
+			}
+			
+			function dumpSecondFetch(items, request){
+				t.is(1, items.length);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssRuleStore about bug in selectorText
+					t.is('.embeddedtestclass', cssRuleStore.getValue(items[0], 'selector'));
+				}else{
+					t.is('.embeddedTestClass', cssRuleStore.getValue(items[0], 'selector'));
+				}
+				request.start = 0;
+				request.count = 2;
+				request.onComplete = dumpThirdFetch;
+				cssRuleStore.fetch(request);
+			}
+
+			function dumpFirstFetch(items, request){
+				t.is(3, items.length);
+				request.start = 2;
+				request.count = 1;
+				request.onComplete = dumpSecondFetch;
+				cssRuleStore.fetch(request);
+			}
+
+
+			cssRuleStore.fetch({
+				query: {'selector': '*TestClass'},
+				onComplete: dumpFirstFetch,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+
+		},
+		
+		function testReadAPI_getLabel(t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = cssRuleStore.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssRuleStore about bug in selectorText
+					t.assertEqual(".linktestclass", label);
+				}else{
+					t.assertEqual(".linkTestClass", label);
+				}
+				d.callback(true);
+			}
+			cssRuleStore.fetch({
+				query: {'selector': '.linkTestClass'}, 
+				onComplete: onComplete, 
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getLabelAttributes(t){
+			//	summary: 
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var labelList = cssRuleStore.getLabelAttributes(items[0]);
+				t.assertTrue(dojo.isArray(labelList));
+				t.assertEqual('selector', labelList[0]);
+				d.callback(true);
+			}
+			cssRuleStore.fetch({ 
+				query: {'selector': '.linkTestClass'}, 
+				onComplete: onComplete, 
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getValue(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssRuleStore about bug in selectorText
+					t.is('.linktestclass', cssRuleStore.getValue(item,'selector'));
+				}else{
+					t.is('.linkTestClass', cssRuleStore.getValue(item,'selector'));
+				}
+				t.assertTrue(cssRuleStore.getValue(item, 'parentStyleSheetHref').match('dojox/data/tests/stores/test1.css'));
+				d.callback(true);	
+			}
+			cssRuleStore.fetch({
+				query: {'selector': '.linkTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getValue_2(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssRuleStore about bug in selectorText
+					t.is('.importtestclass', cssRuleStore.getValue(item,'selector'));
+				}else{
+					t.is('.importTestClass', cssRuleStore.getValue(item,'selector'));
+				}
+				t.assertTrue(cssRuleStore.getValue(item, 'parentStyleSheetHref').match('dojox/data/tests/stores/test2.css'));
+				d.callback(true);	
+			}
+			cssRuleStore.fetch({
+				query: {'selector': '.importTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getValues(t){
+			//	summary: 
+			//		Simple test of the getValues function of the store.
+			//	description:
+			//		Simple test of the getValues function of the store.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var values = cssRuleStore.getValues(item,'selector');
+				t.assertTrue(dojo.isArray(values));
+				t.is(1, values.length);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssRuleStore about bug in selectorText
+					t.is('.embeddedtestclass', values[0]);
+				}else{
+					t.is('.embeddedTestClass', values[0]);
+				}
+				d.callback(true);	
+			}
+			cssRuleStore.fetch({
+				query: {'selector': '.embeddedTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_isItem(t){
+			//	summary: 
+			//		Simple test of the isItem function of the store
+			//	description:
+			//		Simple test of the isItem function of the store
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(cssRuleStore.isItem(item));
+				t.assertTrue(!cssRuleStore.isItem({}));
+				t.assertTrue(!cssRuleStore.isItem({ item: "not an item" }));
+				t.assertTrue(!cssRuleStore.isItem("not an item"));
+				t.assertTrue(!cssRuleStore.isItem(["not an item"]));
+				d.callback(true);	
+			}
+			cssRuleStore.fetch({
+				query: {'selector': '.embeddedTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_hasAttribute(t){
+			//	summary: 
+			//		Simple test of the hasAttribute function of the store
+			//	description:
+			//		Simple test of the hasAttribute function of the store
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(cssRuleStore.hasAttribute(item, 'selector'));
+				t.assertTrue(cssRuleStore.hasAttribute(item, 'classes'));
+				t.assertTrue(!cssRuleStore.hasAttribute(item, 'Year'));
+				t.assertTrue(!cssRuleStore.hasAttribute(item, 'Nothing'));
+				t.assertTrue(!cssRuleStore.hasAttribute(item, 'title'));
+
+				//Test that null attributes throw an exception
+				var passed = false;
+				try{
+					cssRuleStore.hasAttribute(item, null);
+				}catch (e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+				d.callback(true);	
+			}
+			cssRuleStore.fetch({
+				query: {'selector': '.embeddedTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_containsValue(t){
+			//	summary: 
+			//		Simple test of the containsValue function of the store
+			//	description:
+			//		Simple test of the containsValue function of the store
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+ 			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssRuleStore about bug in selectorText
+					t.assertTrue(cssRuleStore.containsValue(item, 'selector', '.embeddedtestclass'));
+					t.assertTrue(cssRuleStore.containsValue(item, 'classes', '.embeddedtestclass'));
+				}else{
+					t.assertTrue(cssRuleStore.containsValue(item, 'selector', '.embeddedTestClass'));
+					t.assertTrue(cssRuleStore.containsValue(item, 'classes', '.embeddedTestClass'));
+				}
+				t.assertTrue(!cssRuleStore.containsValue(item, 'selector', '.embeddedTestClass2'));
+				t.assertTrue(!cssRuleStore.containsValue(item, 'classes', 'embeddedTestClass	'));
+				t.assertTrue(!cssRuleStore.containsValue(item, 'selector', null));
+
+				//Test that null attributes throw an exception
+				var passed = false;
+				try{
+					cssRuleStore.containsValue(item, null, "foo");
+				}catch (e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+				d.callback(true);	
+			}
+			cssRuleStore.fetch({
+				query: {'selector': '.embeddedTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getAttributes(t){
+			//	summary: 
+			//		Simple test of the getAttributes function of the store
+			//	description:
+			//		Simple test of the getAttributes function of the store
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(cssRuleStore.isItem(item));
+
+				var attributes = cssRuleStore.getAttributes(item);
+				t.assertTrue(attributes.length > 8);
+				for(var i = 0; i < 8; i++){
+					var a = attributes[i];
+					t.assertTrue((	a === 'selector' 			|| a === 'classes'
+								||	a === 'rule' 				|| a === 'style'
+								||	a === 'cssText' 			|| a === 'styleSheet'
+								||	a === 'parentStyleSheet' 	|| a === 'parentStyleSheetHref'));
+				}
+				d.callback(true);	
+			}
+			cssRuleStore.fetch({
+				query: {'selector': '.embeddedTestClass'},
+				onItem: onItem,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d;
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+
+			var features = cssRuleStore.getFeatures(); 
+			var count = 0;
+			for(var i in features){
+				t.assertTrue(i === "dojo.data.api.Read");
+				count++;
+			}
+			t.assertTrue(count === 1);
+		},
+		function testReadAPI_fetch_patternMatch(t){
+			//	summary: 
+			//		Function to test pattern matching of everything swith Cla in it
+			//	description:
+			//		Function to test pattern matching of everything with Cla in it
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(4, items.length);
+				var valueArray = ['.linkTestClass', '.linkTestClass .test', '.importTestClass', '.embeddedTestClass'];
+				t.assertTrue(dojox.data.tests.stores.CssRuleStore.verifyItems(cssRuleStore, items, 'selector', valueArray));
+				d.callback(true);
+			}
+			
+			cssRuleStore.fetch({
+				query: {'selector': '*TestCla*'},
+				onComplete: completed,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch_caseInsensitive(t){
+			//	summary: 
+			//		Function to test exact pattern match with case insensitivity set.
+			//	description:
+			//		Function to test exact pattern match with case insensitivity set.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(1, items.length);
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssRuleStore about bug in selectorText
+					t.assertTrue(cssRuleStore.getValue(items[0], 'selector') === '.linktestclass');
+				}else{
+					t.assertTrue(cssRuleStore.getValue(items[0], 'selector') === '.linkTestClass');
+				}
+				d.callback(true);
+			}
+
+			cssRuleStore.fetch({
+				query: {'selector': '.LINKtEsTclass'},
+				queryOptions: {ignoreCase: true},
+				onComplete: completed,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch_caseSensitive(t){
+			//	summary: 
+			//		Function to test exact pattern match with case insensitivity set.
+			//	description:
+			//		Function to test exact pattern match with case insensitivity set.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			var d = new doh.Deferred();
+			function completed(items, request){
+				if(dojo.isWebKit){
+					// Safari is dumb, see comment in CssRuleStore about bug in selectorText
+					t.is(1, items.length);
+				}else{
+					t.is(0, items.length);
+				}
+				d.callback(true);
+			}
+
+			cssRuleStore.fetch({
+				query: {'selector': '.LINKtEsTclass'},
+				queryOptions: {ignoreCase: false},
+				onComplete: completed,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortAlphabetic(t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering.
+			//	description:
+			//		Function to test sorting alphabetic ordering.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ 	'.embeddedTestClass',
+										'.importTestClass',
+										'.linkTestClass'
+				];
+				t.is(3, items.length);
+				t.assertTrue(dojox.data.tests.stores.CssRuleStore.verifyItems(cssRuleStore, items, 'selector', orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: 'selector'}];
+			cssRuleStore.fetch({
+				query: {'selector': '*TestClass'},
+				sort: sortAttributes,
+				onComplete: completed,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortAlphabeticDescending(t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering in descending mode.
+			//	description:
+			//		Function to test sorting alphabetic ordering in descending mode.
+			var cssRuleStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			var d = new doh.Deferred();
+
+
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ 	'.linkTestClass',
+										'.importTestClass',
+										'.embeddedTestClass'
+					];
+
+				t.is(3, items.length);
+				t.assertTrue(dojox.data.tests.stores.CssRuleStore.verifyItems(cssRuleStore, items, 'selector', orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: "selector", descending: true}];
+			cssRuleStore.fetch({
+				query: {'selector': '*TestClass'},
+				sort: sortAttributes,
+				onComplete: completed,
+				onError: dojo.partial(dojox.data.tests.stores.CssRuleStore.error, t, d)
+			});
+			return d; //Object
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			var testStore = dojox.data.tests.stores.CssRuleStore.createStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(var i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						console.log("Looking at function: [" + i + "]");
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							console.log("Problem with function: [" + i + "].   Got value: " + testStoreMember);
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
+
diff --git a/dojox/data/tests/stores/CsvStore.js b/dojox/data/tests/stores/CsvStore.js
new file mode 100644
index 0000000..0afc0c5
--- /dev/null
+++ b/dojox/data/tests/stores/CsvStore.js
@@ -0,0 +1,1411 @@
+dojo.provide("dojox.data.tests.stores.CsvStore");
+dojo.require("dojox.data.CsvStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+
+dojox.data.tests.stores.CsvStore.getDatasource = function(filepath){
+	//  summary:
+	//		A simple helper function for getting the sample data used in each of the tests.
+	//  description:
+	//		A simple helper function for getting the sample data used in each of the tests.
+
+	var dataSource = {};
+	if(dojo.isBrowser){
+		dataSource.url = dojo.moduleUrl("dojox.data.tests", filepath).toString();            
+	}else{
+		// When running tests in Rhino, xhrGet is not available,
+		// so we have the file data in the code below.
+		var csvData;
+		switch(filepath){
+			case "stores/movies.csv":
+				csvData += "Title, Year, Producer\n";
+				csvData += "City of God, 2002, Katia Lund\n";
+				csvData += "Rain,, Christine Jeffs\n";
+				csvData += "2001: A Space Odyssey, 1968, Stanley Kubrick\n";
+				csvData += '"This is a ""fake"" movie title", 1957, Sidney Lumet\n';
+				csvData += "Alien, 1979   , Ridley Scott\n";
+				csvData += '"The Sequel to ""Dances With Wolves.""", 1982, Ridley Scott\n';
+				csvData += '"Caine Mutiny, The", 1954, "Dymtryk ""the King"", Edward"\n';
+				break;
+			case "stores/movies2.csv":
+				csvData += "Title, Year, Producer\n";
+				csvData += "City of God, 2002, Katia Lund\n";
+				csvData += "Rain,\"\", Christine Jeffs\n";
+				csvData += "2001: A Space Odyssey, 1968, Stanley Kubrick\n";
+				csvData += '"This is a ""fake"" movie title", 1957, Sidney Lumet\n';
+				csvData += "Alien, 1979   , Ridley Scott\n";
+				csvData += '"The Sequel to ""Dances With Wolves.""", 1982, Ridley Scott\n';
+				csvData += '"Caine Mutiny, The", 1954, "Dymtryk ""the King"", Edward"\n';
+				break;
+			case "stores/empty.csv":
+				csvData += "Title, Year, Producer\n";
+				break;
+			case "stores/movies3.csv":
+				csvData += "Title, Year, Producer\n";
+				csvData += "\"City\n of God\", 2002, Katia Lund\n";
+				csvData += "Rain,\"\", Christine Jeffs\n";
+				csvData += "2001: A Space Odyssey, 1968, Stanley Kubrick\n";
+				csvData += '"This is a ""fake"" movie title", 1957, Sidney Lumet\n';
+				csvData += "Alien, 1979   , Ridley Scott\n";
+				csvData += '"The Sequel to ""Dances With\n Wolves.""", 1982, Ridley Scott\n';
+				csvData += '"Caine Mutiny, The", 1954, "Dymtryk ""the King"", Edward"\n';
+				break;
+			case "stores/books.csv":
+				csvData += "Title, Author\n";
+				csvData += "The Transparent Society, David Brin\n";
+				csvData += "The First Measured Century, Theodore Caplow\n";
+				csvData += "Maps in a Mirror, Orson Scott Card\n";
+				csvData += "Princess Smartypants, Babette Cole\n";
+				csvData += "Carfree Cities, Crawford J.H.\n";
+				csvData += "Down and Out in the Magic Kingdom, Cory Doctorow\n";
+				csvData += "Tax Shift, Alan Thein Durning\n";
+				csvData += "The Sneetches and other stories, Dr. Seuss\n";
+				csvData += "News from Tartary, Peter Fleming\n";
+				break;
+			case "stores/patterns.csv":
+				csvData += "uniqueId, value\n";
+				csvData += "9, jfq4@#!$!@Rf14r14i5u\n";
+				csvData += "6, BaBaMaSaRa***Foo\n";
+				csvData += "2, bar*foo\n";
+				csvData += "8, 123abc\n";
+				csvData += "4, bit$Bite\n";
+				csvData += "3, 123abc\n";
+				csvData += "10, 123abcdefg\n";
+				csvData += "1, foo*bar\n";
+				csvData += "7, \n";
+				csvData += "5, 123abc\n";
+				break;
+			case "stores/semicolonSeparator.csv":
+				csvData += "article;price\n";
+				csvData += "1008;4,59\n";
+				csvData += "1010;10,09\n";
+				csvData += "1011;5,13\n";
+				csvData += "1016;16,68\n";
+				csvData += "1019;15,5\n";
+				csvData += "1022;10,36\n";
+				break;
+			case "stores/pipeSeparator.csv":
+				csvData += "article|price\n";
+				csvData += "1008|4,59\n";
+				csvData += "1010|10,09\n";
+				csvData += "1011|5,13\n";
+				csvData += "1016|16,68\n";
+				csvData += "1019|15,5\n";
+				csvData += "1022|10,36\n";
+				break;
+			case "stores/pipeSeparatorInData.csv":
+				csvData += "article|price\n";
+				csvData += "1008|\"4,59|4,54\"\n";
+				csvData += "1010|10,09\n";
+				csvData += "1011|5,13\n";
+				csvData += "1016|16,68\n";
+				csvData += "1019|15,5\n";
+				csvData += "1022|10,36\n";
+				break;
+		}
+		dataSource.data = csvData;
+	}
+	return dataSource; //Object
+};
+
+dojox.data.tests.stores.CsvStore.verifyItems = function(csvStore, items, attribute, compareArray){
+	//  summary:
+	//		A helper function for validating that the items array is ordered
+	//		the same as the compareArray
+	if(items.length != compareArray.length){ return false; }
+	for(var i = 0; i < items.length; i++){
+		if(!(csvStore.getValue(items[i], attribute) === compareArray[i])){
+			return false; //Boolean
+		}
+	}
+	return true; //Boolean
+};
+
+dojox.data.tests.stores.CsvStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	for (var i in errData) {
+		console.log(errData[i]);
+	}
+	d.errback(errData);	
+};
+
+doh.register("dojox.data.tests.stores.CsvStore", 
+	[
+		function testReadAPI_fetch_all(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue((items.length === 7));
+				d.callback(true);
+			}
+
+			//Get everything...
+			csvStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_empty(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore that's empty.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore that's empty.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/empty.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue((items.length === 0));
+				d.callback(true);
+			}
+
+			//Get everything...
+			csvStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_semicolon(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore with separator defined as |.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore with separator defined as |.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/semicolonSeparator.csv");
+			args.separator = ";";
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertEqual(6, items.length);
+				d.callback(true);
+			}
+
+			//Get everything...
+			csvStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_pipe(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore with separator defined as |.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore with separator defined as |
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/pipeSeparator.csv");
+			args.separator = "|";
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertEqual(6, items.length);
+				d.callback(true);
+			}
+
+			//Get everything...
+			csvStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_pipe_indata(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore with separator defined as |.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore with separator defined as |
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/pipeSeparatorInData.csv");
+			args.separator = "|";
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertEqual(6, items.length);
+				d.callback(true);
+			}
+
+			//Get everything...
+			csvStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_withnewlinedCsv(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore loading a CSV file with quoted newlines.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore loading a CSV file with quoted newlines.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies3.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue((items.length === 7));
+				d.callback(true);
+			}
+
+			//Get everything...
+			csvStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_withEmptyStringField(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies2.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue((items.length === 7));
+				d.callback(true);
+			}
+
+			//Get everything...
+			csvStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.is(1, items.length);
+				d.callback(true);
+			}
+			csvStore.fetch({ 	query: {Title: "*Sequel*"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)
+							});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one_preventcache(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			args.urlPreventCache = true;
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.is(1, items.length);
+				d.callback(true);
+			}
+			csvStore.fetch({ 	query: {Title: "*Sequel*"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)
+							});
+			return d; //Object
+		},
+		function testReadAPI_fetch_Multiple(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+
+			var done = [false, false];
+
+			function onCompleteOne(items, request){
+				done[0] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			
+			function onCompleteTwo(items, request){
+				done[1] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			
+			try
+			{
+				csvStore.fetch({ 	query: {Title: "*Sequel*"}, 
+									onComplete: onCompleteOne, 
+									onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)
+								});
+				csvStore.fetch({ 	query: {Title: "2001:*"}, 
+									onComplete: onCompleteTwo, 
+									onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)
+								});
+			}
+			catch(e)
+			{
+				for (var i in e) {
+					console.log(e[i]);
+				}
+			}
+
+			return d; //Object
+		},
+		function testReadAPI_fetch_MultipleMixed(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore of a single item.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+
+			var done = [false, false];
+			function onComplete(items, request){
+				done[0] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			
+			function onItem(item){
+				done[1] = true;
+				t.assertTrue(item !== null);
+				t.is('Dymtryk "the King", Edward', csvStore.getValue(item,"Producer"));
+				t.is('Caine Mutiny, The', csvStore.getValue(item,"Title"));
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+
+			csvStore.fetch({ 	query: {Title: "*Sequel*"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)
+							});
+			
+			csvStore.fetchItemByIdentity({identity: "6", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_streaming(t){
+			//	summary: 
+			//		Simple test of a basic fetch on CsvStore.
+			//	description:
+			//		Simple test of a basic fetch on CsvStore.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			var count = 0;
+
+			function onBegin(size, requestObj){
+				t.assertTrue(size === 7);
+			}
+			function onItem(item, requestObj){
+				t.assertTrue(csvStore.isItem(item));
+				count++;
+			}
+			function onComplete(items, request){
+				t.is(7, count);
+				t.is(null, items);
+			    d.callback(true);
+			}
+
+			//Get everything...
+			csvStore.fetch({	onBegin: onBegin,
+								onItem: onItem, 
+								onComplete: onComplete,
+								onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)
+							});
+			return d; //Object
+		},
+		function testReadAPI_fetch_paging(t){
+			 //	summary: 
+			 //		Test of multiple fetches on a single result.  Paging, if you will.
+			 //	description:
+			 //		Test of multiple fetches on a single result.  Paging, if you will.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+
+			function dumpSixthFetch(items, request){
+				t.is(5, items.length);
+			    d.callback(true);
+			}
+
+			function dumpFifthFetch(items, request){
+				t.is(0, items.length);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpSixthFetch;
+				csvStore.fetch(request);
+			}
+
+			function dumpFourthFetch(items, request){
+				t.is(5, items.length);
+				request.start = 9;
+				request.count = 100;
+				request.onComplete = dumpFifthFetch;
+				csvStore.fetch(request);
+			}
+
+			function dumpThirdFetch(items, request){
+				t.is(5, items.length);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpFourthFetch;
+				csvStore.fetch(request);
+			}
+
+			function dumpSecondFetch(items, request){
+				t.is(1, items.length);
+				request.start = 0;
+				request.count = 5;
+				request.onComplete = dumpThirdFetch;
+				csvStore.fetch(request);
+			}
+
+			function dumpFirstFetch(items, request){
+				t.is(5, items.length);
+				request.start = 3;
+				request.count = 1;
+				request.onComplete = dumpSecondFetch;
+				csvStore.fetch(request);
+			}
+
+			function completed(items, request){
+				t.is(7, items.length);
+				request.start = 1;
+				request.count = 5;
+				request.onComplete = dumpFirstFetch;
+				csvStore.fetch(request);
+			}
+
+			csvStore.fetch({onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		
+		function testReadAPI_getLabel(t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			args.label = "Title";
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = csvStore.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				t.assertEqual("The Sequel to \"Dances With Wolves.\"", label);
+				d.callback(true);
+			}
+			csvStore.fetch({ 	query: {Title: "*Sequel*"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)
+							});
+			return d;
+		},
+		function testReadAPI_getLabelAttributes(t){
+			//	summary: 
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+			 var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			 args.label = "Title";
+			 var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var labelList = csvStore.getLabelAttributes(items[0]);
+				t.assertTrue(dojo.isArray(labelList));
+				t.assertEqual("Title", labelList[0]);
+				d.callback(true);
+			}
+			csvStore.fetch({ 	query: {Title: "*Sequel*"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)
+							});
+			return d;
+		},
+		function testReadAPI_getValue(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.is('Dymtryk "the King", Edward', csvStore.getValue(item,"Producer"));
+				t.is('Caine Mutiny, The', csvStore.getValue(item,"Title"));
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "6", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d;
+		},	
+		function testReadAPI_getValue_2(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.is("City of God", csvStore.getValue(item,"Title"));
+				t.is("2002", csvStore.getValue(item,"Year"));
+				d.callback(true);	
+			}
+            csvStore.fetchItemByIdentity({identity: "0", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d;
+		},	
+		function testReadAPI_getValue_3(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.is("1979", csvStore.getValue(item,"Year"));
+				t.is("Alien", csvStore.getValue(item,"Title"));
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "4", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d;
+		},	
+		function testReadAPI_getValue_4(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.is("2001: A Space Odyssey", csvStore.getValue(item,"Title"));
+				t.is("Stanley Kubrick", csvStore.getValue(item,"Producer"));
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "2", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d;
+		},	
+
+		function testReadAPI_getValues(t){
+			//	summary: 
+			//		Simple test of the getValues function of the store.
+			//	description:
+			//		Simple test of the getValues function of the store.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var names = csvStore.getValues(item,"Title");
+				t.assertTrue(dojo.isArray(names));
+				t.is(1, names.length);
+				t.is("Rain", names[0]);
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "1", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d;
+		},
+		function testIdentityAPI_fetchItemByIdentity(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "1", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d;
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_withDefinedIdentifier(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			args.identifier = "Title";
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "City of God", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d;
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_withDefinedIdentifier_bad1(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			args.identifier = "Title";
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "No Such Title", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d;
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_bad1(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "7", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d;
+		},
+		function testIdentityAPI_fetchItemByIdentity_bad2(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "-1", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d;
+		},
+		function testIdentityAPI_fetchItemByIdentity_bad3(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "999999", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d;
+		},
+		function testIdentityAPI_getIdentity(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(7, items.length);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					if(!(csvStore.getIdentity(items[i]) === i)){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				d.callback(true);
+			}
+			
+			//Get everything...
+			csvStore.fetch({ onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+
+		function testIdentityAPI_getIdentity_withDefinedIdentifier(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			args.identifier = "Title";
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(7, items.length);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					if(!csvStore.getIdentity(items[i])){
+                        passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				d.callback(true);
+			}
+			
+			//Get everything...
+			csvStore.fetch({ onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+
+		function testIdentityAPI_getIdentity_withBadDefinedIdentifier(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			args.identifier = "Not Column";
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				d.errback(new Error("Unexpected callback of success in failure case."));
+			}
+			function error(err){
+				d.callback(true);
+			}
+			
+			//Get everything...
+			csvStore.fetch({onComplete: completed, onError: error});
+			return d; //Object
+		},
+
+		function testIdentityAPI_getIdentityAttributes(t){
+			//	summary: 
+			//		Simple test of the getIdentityAttributes
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(csvStore.isItem(item));
+				t.assertEqual(null, csvStore.getIdentityAttributes(item)); 
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "1", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+		   	return d;
+		},
+		function testReadAPI_isItem(t){
+			//	summary: 
+			//		Simple test of the isItem function of the store
+			//	description:
+			//		Simple test of the isItem function of the store
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(csvStore.isItem(item));
+				t.assertTrue(!csvStore.isItem({}));
+				t.assertTrue(!csvStore.isItem({ item: "not an item" }));
+				t.assertTrue(!csvStore.isItem("not an item"));
+				t.assertTrue(!csvStore.isItem(["not an item"]));
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "1", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+		   	return d;
+		},
+		function testReadAPI_hasAttribute(t){
+			//	summary: 
+			//		Simple test of the hasAttribute function of the store
+			//	description:
+			//		Simple test of the hasAttribute function of the store
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(csvStore.hasAttribute(item, "Title"));
+				t.assertTrue(csvStore.hasAttribute(item, "Producer"));
+				t.assertTrue(!csvStore.hasAttribute(item, "Year"));
+				t.assertTrue(!csvStore.hasAttribute(item, "Nothing"));
+				t.assertTrue(!csvStore.hasAttribute(item, "title"));
+
+				//Test that null attributes throw an exception
+				var passed = false;
+				try{
+					csvStore.hasAttribute(item, null);
+				}catch (e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "1", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+		   	return d;
+		},
+		function testReadAPI_containsValue(t){
+			//	summary: 
+			//		Simple test of the containsValue function of the store
+			//	description:
+			//		Simple test of the containsValue function of the store
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+ 			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(csvStore.containsValue(item, "Title", "Alien"));
+				t.assertTrue(csvStore.containsValue(item, "Year", "1979"));
+				t.assertTrue(csvStore.containsValue(item, "Producer", "Ridley Scott"));
+				t.assertTrue(!csvStore.containsValue(item, "Title", "Alien2"));
+				t.assertTrue(!csvStore.containsValue(item, "Year", "1979   "));
+				t.assertTrue(!csvStore.containsValue(item, "Title", null));
+
+				//Test that null attributes throw an exception
+				var passed = false;
+				try{
+					csvStore.containsValue(item, null, "foo");
+				}catch (e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "4", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+		   	return d;
+		},
+		function testReadAPI_getAttributes(t){
+			//	summary: 
+			//		Simple test of the getAttributes function of the store
+			//	description:
+			//		Simple test of the getAttributes function of the store
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(csvStore.isItem(item));
+
+				var attributes = csvStore.getAttributes(item);
+				t.is(3, attributes.length);
+				for(var i = 0; i < attributes.length; i++){
+					t.assertTrue((attributes[i] === "Title" || attributes[i] === "Year" || attributes[i] === "Producer"));
+				}
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "4", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+		   	return d;
+		},
+
+		function testReadAPI_getAttributes_onlyTwo(t){
+			//	summary: 
+			//		Simple test of the getAttributes function of the store
+			//	description:
+			//		Simple test of the getAttributes function of the store
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				// Test an item that does not have all of the attributes
+				t.assertTrue(item !== null);
+				t.assertTrue(csvStore.isItem(item));
+
+				var attributes = csvStore.getAttributes(item);
+				t.assertTrue(attributes.length === 2);
+				t.assertTrue(attributes[0] === "Title");
+				t.assertTrue(attributes[1] === "Producer");
+				d.callback(true);	
+			}
+			csvStore.fetchItemByIdentity({identity: "1", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+		   	return d;
+		},
+
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var features = csvStore.getFeatures(); 
+			var count = 0;
+			for(var i in features){
+				t.assertTrue((i === "dojo.data.api.Read" || i === "dojo.data.api.Identity"));
+				count++;
+			}
+			t.assertTrue(count === 2);
+		},
+		function testReadAPI_fetch_patternMatch0(t){
+			//	summary: 
+			//		Function to test pattern matching of everything starting with lowercase e
+			//	description:
+			//		Function to test pattern matching of everything starting with lowercase e
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(2, items.length);
+				var valueArray = [ "Alien", "The Sequel to \"Dances With Wolves.\""];
+				t.assertTrue(dojox.data.tests.stores.CsvStore.verifyItems(csvStore, items, "Title", valueArray));
+				d.callback(true);
+			}
+			
+			csvStore.fetch({query: {Producer: "* Scott"}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch1(t){
+			//	summary: 
+			//		Function to test pattern matching of everything with $ in it.
+			//	description:
+			//		Function to test pattern matching of everything with $ in it.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/patterns.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.assertTrue(items.length === 2);
+				var valueArray = [ "jfq4@#!$!@Rf14r14i5u", "bit$Bite"];
+				t.assertTrue(dojox.data.tests.stores.CsvStore.verifyItems(csvStore, items, "value", valueArray));
+				d.callback(true);
+			}
+			
+			csvStore.fetch({query: {value: "*$*"}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch2(t){
+			//	summary: 
+			//		Function to test exact pattern match
+			//	description:
+			//		Function to test exact pattern match
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/patterns.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(1, items.length);
+				t.assertTrue(csvStore.getValue(items[0], "value") === "bar*foo");
+				d.callback(true);
+			}
+			
+			csvStore.fetch({query: {value: "bar\\*foo"}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch_caseInsensitive(t){
+			//	summary: 
+			//		Function to test exact pattern match with case insensitivity set.
+			//	description:
+			//		Function to test exact pattern match with case insensitivity set.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/patterns.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(1, items.length);
+				t.assertTrue(csvStore.getValue(items[0], "value") === "bar*foo");
+				d.callback(true);
+			}
+			
+			csvStore.fetch({query: {value: "BAR\\*foo"}, queryOptions: {ignoreCase: true}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch_caseSensitive(t){
+			//	summary: 
+			//		Function to test exact pattern match with case insensitivity set.
+			//	description:
+			//		Function to test exact pattern match with case insensitivity set.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/patterns.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(0, items.length);
+				d.callback(true);
+			}
+			
+			csvStore.fetch({query: {value: "BAR\\*foo"}, queryOptions: {ignoreCase: false}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortNumeric(t){
+			//	summary: 
+			//		Function to test sorting numerically.
+			//	description:
+			//		Function to test sorting numerically.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/patterns.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.assertTrue(items.length === 10);
+				// TODO: CsvStore treats everything like a string, so these numbers will be sorted lexicographically.
+				var orderedArray = [ "1", "10", "2", "3", "4", "5", "6", "7", "8", "9" ];
+				t.assertTrue(dojox.data.tests.stores.CsvStore.verifyItems(csvStore, items, "uniqueId", orderedArray));
+				d.callback(true);
+			}
+
+			var sortAttributes = [{attribute: "uniqueId"}];
+			csvStore.fetch({onComplete: completed, 
+							onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d),
+							sort: sortAttributes});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortNumericDescending(t){
+			//	summary: 
+			//		Function to test sorting numerically.
+			//	description:
+			//		Function to test sorting numerically.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/patterns.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(10, items.length);
+				// TODO: CsvStore treats everything like a string, so these numbers will be sorted lexicographically.
+				var orderedArray = [ "9", "8", "7", "6", "5", "4", "3", "2", "10", "1" ];
+				t.assertTrue(dojox.data.tests.stores.CsvStore.verifyItems(csvStore, items, "uniqueId", orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: "uniqueId", descending: true}];
+			csvStore.fetch({ sort: sortAttributes, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortNumericWithCount(t){
+			//	summary: 
+			//		Function to test sorting numerically in descending order, returning only a specified number of them.
+			//	description:
+			//		Function to test sorting numerically in descending order, returning only a specified number of them.
+		
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/patterns.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(5, items.length);
+				// TODO: CsvStore treats everything like a string, so these numbers will be sorted lexicographically.
+				var orderedArray = [ "9", "8", "7", "6", "5" ];
+				t.assertTrue(dojox.data.tests.stores.CsvStore.verifyItems(csvStore, items, "uniqueId", orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: "uniqueId", descending: true}];
+			csvStore.fetch({sort: sortAttributes, 
+							count: 5,
+							onComplete: completed,
+							onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortAlphabetic(t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering.
+			//	description:
+			//		Function to test sorting alphabetic ordering.
+		
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/patterns.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ 	"123abc",
+										"123abc",
+										"123abc",
+										"123abcdefg",
+										"BaBaMaSaRa***Foo",
+										"bar*foo",
+										"bit$Bite",
+										"foo*bar",
+										"jfq4@#!$!@Rf14r14i5u",
+										undefined
+					];
+				t.is(10, items.length);
+				t.assertTrue(dojox.data.tests.stores.CsvStore.verifyItems(csvStore, items, "value", orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: "value"}];
+			csvStore.fetch({sort: sortAttributes, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortAlphabeticDescending(t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering in descending mode.
+			//	description:
+			//		Function to test sorting alphabetic ordering in descending mode.
+		
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/patterns.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ 	undefined,
+										"jfq4@#!$!@Rf14r14i5u",
+										"foo*bar",
+										"bit$Bite",
+										"bar*foo",
+										"BaBaMaSaRa***Foo",
+										"123abcdefg",
+										"123abc",
+										"123abc",
+										"123abc"
+					];
+				t.is(10, items.length);
+				t.assertTrue(dojox.data.tests.stores.CsvStore.verifyItems(csvStore, items, "value", orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: "value", descending: true}];
+			csvStore.fetch({sort: sortAttributes, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortMultiple(t){
+			//	summary: 
+			//		Function to test sorting on multiple attributes.
+			//	description:
+			//		Function to test sorting on multiple attributes.
+			
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/patterns.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+		
+			var d = new doh.Deferred();
+			function completed(items, request){
+				var orderedArray0 = [ "8", "5", "3", "10", "6", "2", "4", "1", "9", "7" ];
+				var orderedArray1 = [	"123abc",
+										"123abc",
+										"123abc",
+										"123abcdefg",
+										"BaBaMaSaRa***Foo",
+										"bar*foo",
+										"bit$Bite",
+										"foo*bar",
+										"jfq4@#!$!@Rf14r14i5u",
+										undefined
+									];
+				t.is(10, items.length);
+				t.assertTrue(dojox.data.tests.stores.CsvStore.verifyItems(csvStore, items, "uniqueId", orderedArray0));
+				t.assertTrue(dojox.data.tests.stores.CsvStore.verifyItems(csvStore, items, "value", orderedArray1));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{ attribute: "value"}, { attribute: "uniqueId", descending: true}];
+			csvStore.fetch({sort: sortAttributes, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortMultipleSpecialComparator(t){
+			//	summary: 
+			//		Function to test sorting on multiple attributes with a custom comparator.
+			//	description:
+			//		Function to test sorting on multiple attributes with a custom comparator.
+
+			var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+			var csvStore = new dojox.data.CsvStore(args);
+			
+			csvStore.comparatorMap = {};
+			csvStore.comparatorMap["Producer"] = function(a,b){ 
+				var ret = 0;
+				// We want to sort authors alphabetical by their last name
+				function lastName(name){
+					if(typeof name === "undefined"){ return undefined; }
+					
+					var matches = name.match(/\s*(\S+)$/); // Grab the last word in the string.
+					return matches ? matches[1] : name; // Strings with only whitespace will not match.
+				}
+				var lastNameA = lastName(a);
+				var lastNameB = lastName(b);
+				if(lastNameA > lastNameB || typeof lastNameA === "undefined"){
+					ret = 1;
+				}else if(lastNameA < lastNameB || typeof lastNameB === "undefined"){
+					ret = -1;
+				}
+				return ret;
+			};
+		
+			var sortAttributes = [{attribute: "Producer", descending: true}, { attribute: "Title", descending: true}];
+		
+			var d = new doh.Deferred();
+			function completed(items, findResult){
+				var orderedArray = [5,4,0,3,2,1,6];
+				t.assertTrue(items.length === 7);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					if(!(csvStore.getIdentity(items[i]) === orderedArray[i])){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				d.callback(true);
+			}
+			
+			csvStore.fetch({sort: sortAttributes, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.CsvStore.error, t, d)});
+			return d; //Object
+		},
+
+		{
+			name: "testReadAPI_fetch_abort",
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of a basic fetch abort on CsvStore.
+				//	description:
+				//		Simple test of a basic fetch abort on CsvStore.
+				//Can only async abort in a browser, so disable this test from rhino
+				if(dojo.isBrowser){                                            
+					var args = dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv");
+					var store = new dojox.data.CsvStore(args);
+				
+					var d = new doh.Deferred();
+					var abortCalled = false;
+					var completedAll = function(items, request){
+						t.is(7, items.length);
+						if(abortCalled){
+							console.log("Made it to complete callback and abort was called.  Problem.");
+							d.errback(new Error("Should not be here."));
+						}else{
+							//We beat out calling abort, so this is okay.  Timing.
+							console.log("in onComplete and abort has not been called.  Timing.  This is okay.");
+							d.callback(true);
+						}
+					};
+					var error = function(errData, request){
+						//An abort should throw a cancel error, so we should
+						//reach this.
+						t.assertTrue(true);
+						d.callback(true);
+					};
+	
+					//Get everything...
+					var req = store.fetch({ onComplete: completedAll, onError: error});
+					abortCalled=true;
+					console.log("Calling abort.");
+					req.abort();
+					return d;
+				}
+			}
+		},
+
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = new dojox.data.CsvStore(dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv"));
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(var i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						console.log("Looking at function: [" + i + "]");
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							console.log("Problem with function: [" + i + "].   Got value: " + testStoreMember);
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		},
+		function testIdentityAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = new dojox.data.CsvStore(dojox.data.tests.stores.CsvStore.getDatasource("stores/movies.csv"));
+			var identityApi = new dojo.data.api.Identity();
+			var passed = true;
+
+			for(var i in identityApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = identityApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						console.log("Looking at function: [" + i + "]");
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
+
diff --git a/dojox/data/tests/stores/FileStore.js b/dojox/data/tests/stores/FileStore.js
new file mode 100755
index 0000000..79dc59a
--- /dev/null
+++ b/dojox/data/tests/stores/FileStore.js
@@ -0,0 +1,697 @@
+dojo.provide("dojox.data.tests.stores.FileStore");
+dojo.require("dojox.data.FileStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+
+
+dojox.data.tests.stores.FileStore.getGeoStore = function(){
+	return new dojox.data.FileStore({url: dojo.moduleUrl("dojox.data.tests.stores", "filestore_dojoxdatageo.php").toString(), pathAsQueryParam: true});
+};
+
+
+doh.register("dojox.data.tests.stores.FileStore", 
+	[
+/***************************************
+	 dojo.data.api.Read API
+***************************************/
+		{
+			name: "testReadAPI_fetch_all",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of fetching all xml items through an XML element called isbn
+				//	description:
+				//		Simple test of fetching all xml items through an XML element called isbn
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(49, items.length);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"*"}, queryOptions: {deep: true}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_fetch_one",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of fetching one xml items through an XML element called isbn
+				//	description:
+				//		Simple test of fetching one xml items through an XML element called isbn
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"Commonwealth of Australia"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_fetch_paging",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of fetching a series of pages
+				//	description:
+				//		Simple test of fetching a series of pages
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+
+				function dumpSixthFetch(items, request){
+					t.assertEqual(20, items.length);
+					d.callback(true);
+				}
+
+				function dumpFifthFetch(items, request){
+					t.assertEqual(40, items.length);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpSixthFetch;
+					store.fetch(request);
+				}
+
+				function dumpFourthFetch(items, request){
+					t.assertEqual(20, items.length);
+					request.start = 9;
+					request.count = 100;
+					request.onComplete = dumpFifthFetch;
+					store.fetch(request);
+				}
+
+				function dumpThirdFetch(items, request){
+					t.assertEqual(5, items.length);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpFourthFetch;
+					store.fetch(request);
+				}
+
+				function dumpSecondFetch(items, request){
+					t.assertEqual(1, items.length);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					store.fetch(request);
+				}
+
+				function dumpFirstFetch(items, request){
+					t.assertEqual(5, items.length);
+					request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					store.fetch(request);
+				}
+
+				function completed(items, request){
+					t.assertEqual(49, items.length);
+					request.start = 1;
+					request.count = 5;
+					request.onComplete = dumpFirstFetch;
+					store.fetch(request);
+				}
+
+				function error(errData, request){
+					d.errback(errData);
+				}
+
+				store.fetch({queryOptions: {deep:true}, onComplete: completed, onError: error});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_fetch_pattern0",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of fetching a few files based on wildcarded name
+				//	description:
+				//		Simple test of fetching a few files based on wildcarded name
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+				var d = new doh.Deferred();                                                             
+				function onComplete(items, request) {
+					t.assertEqual(3, items.length);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"C*"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_fetch_pattern1",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of fetching a one files based on wildcarded name
+				//	description:
+				//		Simple test of fetching a one file based on wildcarded name
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"?ussia"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_fetch_pattern_caseInsensitive",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of fetching one file item case insensitively
+				//	description:
+				//		Simple test of fetching one file item case insensitively
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+				var d = new doh.Deferred();                                                             
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"germany"}, queryOptions: {ignoreCase: true}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_fetch_pattern_caseSensitive",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of fetching one file item case sensitively
+				//	description:
+				//		Simple test of fetching one file item case sensitively
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+				var d = new doh.Deferred();                                                             
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"Germany"}, queryOptions: {ignoreCase: false}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_getLabel",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getLabel function against a store
+				//	description:
+				//		Simple test of the getLabel function against a store
+
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var label = store.getLabel(items[0]);
+					t.assertTrue(label !== null);
+					t.assertEqual("China", label);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"China"}, onComplete: onComplete, onError: onError});
+				return d;
+			}
+		},
+		{
+			name: "testReadAPI_getLabelAttributes",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = store.getLabelAttributes(items[0]);
+					t.assertTrue(labelList !== null);
+					t.assertEqual("name", labelList[0]);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"China"}, onComplete: onComplete, onError: onError});
+				return d;
+			}
+		},
+		{
+			name: "testReadAPI_getValue",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getValue API
+				//	description:
+				//		Simple test of the getValue API
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.hasAttribute(item,"name"));
+					t.assertEqual(store.getValue(item,"name"), "Guadalajara");
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"Guadalajara"}, queryOptions: {deep: true}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_getValues",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getValues API
+				//	description:
+				//		Simple test of the getValues API
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.hasAttribute(item,"name"));
+					var values = store.getValues(item,"name");
+					t.assertEqual(1,values.length);
+					t.assertEqual("Guadalajara", values[0]);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"Guadalajara"}, queryOptions: {deep: true}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_isItem",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the isItem API
+				//	description:
+				//		Simple test of the isItem API
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+				   t.assertEqual(1, items.length);
+				   var item = items[0];
+				   t.assertTrue(store.isItem(item));
+				   t.assertTrue(!store.isItem({}));
+				   t.assertTrue(!store.isItem("Foo"));
+				   t.assertTrue(!store.isItem(1));
+				   d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"Guadalajara"}, queryOptions: {deep: true}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_isItem_multistore",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the isItem API across multiple store instances.
+				//	description:
+				//		Simple test of the isItem API across multiple store instances.
+				var store1 = dojox.data.tests.stores.FileStore.getGeoStore();
+				var store2 = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+
+				function onError(error, request) {
+					d.errback(error);
+				}
+
+				function onComplete1(items, request) {
+					t.assertEqual(1, items.length);
+					var item1 = items[0];
+					t.assertTrue(store1.isItem(item1));
+
+					function onComplete2(items, request) {
+						t.assertEqual(1, items.length);
+						var item2 = items[0];
+						t.assertTrue(store2.isItem(item2));
+						t.assertTrue(!store1.isItem(item2));
+						t.assertTrue(!store2.isItem(item1));
+						d.callback(true);
+					}
+					store2.fetch({query:{name:"Guadalajara"}, queryOptions: {deep: true}, onComplete: onComplete2, onError: onError});
+				}
+				store1.fetch({query:{name:"China"}, onComplete: onComplete1, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_hasAttribute",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the hasAttribute API
+				//	description:
+				//		Simple test of the hasAttribute API
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.hasAttribute(item,"name"));
+					t.assertTrue(!store.hasAttribute(item,"bob"));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"China"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_containsValue",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the containsValue API
+				//	description:
+				//		Simple test of the containsValue API
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item,"name", "China"));
+					t.assertTrue(!store.containsValue(item,"name", "bob"));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"China"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_sortDescending",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the sorting API in descending order.
+				//	description:
+				//		Simple test of the sorting API in descending order.
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				//Comparison is done as a string type (toString comparison), so the order won't be numeric
+				//So have to compare in 'alphabetic' order.
+				var order = ["root.json","United States of America","Sudan","Spain","Russia","Mongolia","Mexico","Kenya","Italy","India","Germany","France","Egypt","Commonwealth of Australia","China","Canada","Brazil","Argentina"];
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(18, items.length);
+					for(var i = 0; i < items.length; i++){
+						t.assertEqual(order[i], store.getValue(items[i],"name").toString());
+					}
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+
+				var sortAttributes = [{attribute: "name", descending: true}];
+				store.fetch({query:{name:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_sortAscending",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the sorting API in ascending order.
+				//	description:
+				//		Simple test of the sorting API in ascending order.
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				//Comparison is done as a string type (toString comparison), so the order won't be numeric
+				//So have to compare in 'alphabetic' order.
+
+				var order = ["root.json","United States of America","Sudan","Spain","Russia","Mongolia","Mexico","Kenya","Italy","India","Germany","France","Egypt","Commonwealth of Australia","China","Canada","Brazil","Argentina"].reverse();			
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(18, items.length);
+					for(var i = 0; i < items.length; i++){
+						t.assertEqual(order[i], store.getValue(items[i],"name").toString());
+					}
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+
+				var sortAttributes = [{attribute: "name"}];
+				store.fetch({query:{name:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testReadAPI_isItemLoaded",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the isItemLoaded API
+				//	description:
+				//		Simple test of the isItemLoaded API
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.isItemLoaded(item));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"China"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var store = dojox.data.tests.stores.FileStore.getGeoStore();
+			var features = store.getFeatures(); 
+			var count = 0;
+			var i;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read" || i === "dojo.data.api.Identity"));
+				count++;
+			}
+			t.assertEqual(2, count);
+		},
+		{
+			name: "testReadAPI_getAttributes",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getAttributes API
+				//	description:
+				//		Simple test of the getAttributes API
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					var attributes = store.getAttributes(item);
+					t.assertEqual(7,attributes.length);
+					for(var i=0; i<attributes.length; i++){
+						t.assertTrue((attributes[i] === "children" || attributes[i] === "directory" || attributes[i] === "name" || attributes[i] === "path" || attributes[i] === "modified" || attributes[i] === "size" || attributes[i] === "parentDir"));
+					}
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"China"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.FileStore.getGeoStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			var i;
+			for(i in readApi){
+				var member = readApi[i];
+				//Check that all the 'Read' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						console.log("Problem with function: [" + i + "]");
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		},
+
+/***************************************
+ dojo.data.api.Identity API
+***************************************/
+		{
+			name: "testIdentityAPI_getIdentity",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getAttributes API
+				//	description:
+				//		Simple test of the getAttributes API
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertEqual("./Argentina",store.getIdentity(item));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"Argentina"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testIdentityAPI_getIdentityAttributes",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getAttributes API
+				//	description:
+				//		Simple test of the getAttributes API
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					//Should have none, as it's not a public attribute.
+					var attributes = store.getIdentityAttributes(item);
+					t.assertEqual(1, attributes.length);
+					t.assertEqual("path", attributes[0]);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({query:{name:"Argentina"}, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: "testIdentityAPI_fetchItemByIdentity",
+			timeout:	10000, //10 seconds.  Lots of server calls, expect network delay
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the fetchItemByIdentity API
+				//	description:
+				//		Simple test of the fetchItemByIdentity API
+				var store = dojox.data.tests.stores.FileStore.getGeoStore();
+
+				var d = new doh.Deferred();
+				function onItem(item, request) {
+					t.assertTrue(item !== null);
+					t.assertTrue(store.isItem(item));
+					t.assertEqual("Argentina", store.getValue(item, "name"));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetchItemByIdentity({identity: "./Argentina", onItem: onItem, onError: onError});
+				return d; //Object
+			}
+		},
+		function testIdentityAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.FileStore.getGeoStore();
+			var identityApi = new dojo.data.api.Identity();
+			var passed = true;
+
+			var i;
+			for(i in identityApi){
+				var member = identityApi[i];
+				//Check that all the 'Read' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						console.log("Problem with function: [" + i + "]");
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
+
diff --git a/dojox/data/tests/stores/FlickrRestStore.js b/dojox/data/tests/stores/FlickrRestStore.js
new file mode 100644
index 0000000..6cbb60b
--- /dev/null
+++ b/dojox/data/tests/stores/FlickrRestStore.js
@@ -0,0 +1,472 @@
+dojo.provide("dojox.data.tests.stores.FlickrRestStore");
+dojo.require("dojox.data.FlickrRestStore");
+dojo.require("dojo.data.api.Read");
+
+
+dojox.data.tests.stores.FlickrRestStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	d.errback(errData);	
+}
+
+doh.register("dojox.data.tests.stores.FlickrRestStore", 
+	[
+		{
+			name: "ReadAPI:  Fetch_One",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on FlickrRestStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on FlickrRestStore of a single item.
+
+				var flickrStore = new dojox.data.FlickrRestStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.is(1, items.length);
+					d.callback(true);
+				}
+				flickrStore.fetch({ 	
+					query: {
+						userid: "44153025 at N00",
+						apikey: "8c6803164dbc395fb7131c9d54843627"
+					},
+					count: 1,
+					onComplete: onComplete, 
+					onError: dojo.partial(dojox.data.tests.stores.FlickrRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_20_Streaming",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on FlickrRestStore.
+				//	description:
+				//		Simple test of a basic fetch on FlickrRestStore.
+				var flickrStore = new dojox.data.FlickrRestStore();
+
+				var d = new doh.Deferred();
+				var count = 0;
+
+				function onItem(item, requestObj){
+				  t.assertTrue(flickrStore.isItem(item));
+				  count++;
+				}
+				function onComplete(items, request){
+					t.is(5, count);
+					
+					t.is(null, items);
+					d.callback(true);
+				}
+				//Get everything...
+				flickrStore.fetch({	
+					query: {
+						userid: "44153025 at N00",
+						apikey: "8c6803164dbc395fb7131c9d54843627"
+					},
+					onBegin: null,
+					count: 5,
+					onItem: onItem,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.FlickrRestStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_Paging",
+			timeout:	30000, //30 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+				//	description:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+
+				var flickrStore = new dojox.data.FlickrRestStore();
+
+				var d = new doh.Deferred();
+				function dumpFirstFetch(items, request){
+					t.is(5, items.length);
+					request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpSecondFetch(items, request){
+					t.is(1, items.length);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpThirdFetch(items, request){
+					t.is(5, items.length);
+					request.start = 2;
+					request.count = 18;
+					request.onComplete = dumpFourthFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpFourthFetch(items, request){
+					t.is(18, items.length);
+					request.start = 9;
+					request.count = 11;
+					request.onComplete = dumpFifthFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpFifthFetch(items, request){
+					t.is(11, items.length);
+					request.start = 4;
+					request.count = 16;
+					request.onComplete = dumpSixthFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpSixthFetch(items, request){
+					t.is(16, items.length);
+					d.callback(true);
+				}
+
+				function completed(items, request){
+					t.is(7, items.length);
+					request.start = 1;
+					request.count = 5;
+					request.onComplete = dumpFirstFetch;
+					flickrStore.fetch(request);
+				}
+				flickrStore.fetch({
+					query: {
+						userid: "44153025 at N00",
+						apikey: "8c6803164dbc395fb7131c9d54843627"
+					},
+					count: 7, 
+					onComplete: completed, 
+					onError: dojo.partial(dojox.data.tests.stores.FlickrRestStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getLabel",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+
+				var flickrStore = new dojox.data.FlickrRestStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var label = flickrStore.getLabel(items[0]);
+					t.assertTrue(label !== null);
+					d.callback(true);
+				}
+				flickrStore.fetch({ 	
+					query: {
+						userid: "44153025 at N00",
+						apikey: "8c6803164dbc395fb7131c9d54843627"
+					}, 
+					count: 1,
+					onComplete: onComplete, 
+					onError: dojo.partial(dojox.data.tests.stores.FlickrRestStore.error, t, d)
+				});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getLabelAttributes",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+				var flickrStore = new dojox.data.FlickrRestStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = flickrStore.getLabelAttributes(items[0]);
+					t.assertTrue(dojo.isArray(labelList));
+					t.assertEqual("title", labelList[0]);
+					d.callback(true);
+				}
+				flickrStore.fetch({ 	
+									query: {
+										userid: "44153025 at N00",
+										apikey: "8c6803164dbc395fb7131c9d54843627"
+									},
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.FlickrRestStore.error, t, d)
+								});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getValue",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var flickrStore = new dojox.data.FlickrRestStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					t.assertTrue(flickrStore.getValue(items[0], "title") !== null);
+					t.assertTrue(flickrStore.getValue(items[0], "imageUrl") !== null);
+					t.assertTrue(flickrStore.getValue(items[0], "imageUrlSmall") !== null);
+					t.assertTrue(flickrStore.getValue(items[0], "imageUrlMedium") !== null);
+					d.callback(true);
+				}
+
+				//Get one item and look at it.
+				flickrStore.fetch({
+								query: {
+									userid: "44153025 at N00",
+									apikey: "8c6803164dbc395fb7131c9d54843627"
+								},
+								count: 1, 
+								onComplete: completedAll, 
+								onError: dojo.partial(dojox.data.tests.stores.FlickrRestStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getValues",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var flickrStore = new dojox.data.FlickrRestStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					var title = flickrStore.getValues(items[0], "title");
+					t.assertTrue(title instanceof Array);
+					
+					var imgUrl = flickrStore.getValues(items[0], "imageUrl");
+					t.assertTrue(imgUrl instanceof Array);
+					
+					var imgUrlSmall = flickrStore.getValues(items[0], "imageUrlSmall");
+					t.assertTrue(imgUrlSmall instanceof Array);
+					
+					var imgUrlMedium = flickrStore.getValues(items[0], "imageUrlMedium");
+					t.assertTrue(imgUrlMedium instanceof Array);
+					d.callback(true);
+				}
+				//Get one item and look at it.
+				flickrStore.fetch({
+							query: {
+								userid: "44153025 at N00",
+								apikey: "8c6803164dbc395fb7131c9d54843627"
+							},
+							count: 1, 
+							onComplete: completedAll, 
+							onError: dojo.partial(dojox.data.tests.stores.FlickrRestStore.error, 
+							t, 
+							d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  isItem",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the isItem function of the store
+				//	description:
+				//		Simple test of the isItem function of the store
+				var flickrStore = new dojox.data.FlickrRestStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(5, items.length);
+					for(var i=0; i < items.length; i++){
+						t.assertTrue(flickrStore.isItem(items[i]));
+					}
+					d.callback(true);
+				}
+
+				//Get everything...
+				flickrStore.fetch({
+						query: {
+							userid: "44153025 at N00",
+							apikey: "8c6803164dbc395fb7131c9d54843627"
+						},						
+						count: 5, 
+						onComplete: completedAll, 
+						onError: dojo.partial(dojox.data.tests.stores.FlickrRestStore.error, t, d)
+					});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  hasAttribute",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the hasAttribute function of the store
+				//	description:
+				//		Simple test of the hasAttribute function of the store
+
+				var flickrStore = new dojox.data.FlickrRestStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(items[0] !== null);
+					t.assertTrue(flickrStore.hasAttribute(items[0], "title"));
+					t.assertTrue(flickrStore.hasAttribute(items[0], "author"));
+					t.assertTrue(!flickrStore.hasAttribute(items[0], "Nothing"));
+					t.assertTrue(!flickrStore.hasAttribute(items[0], "Text"));
+
+					//Test that null attributes throw an exception
+					var passed = false;
+					try{
+						flickrStore.hasAttribute(items[0], null);
+					}catch (e){
+						passed = true;
+					}
+					t.assertTrue(passed);
+					d.callback(true);
+				}
+
+				//Get one item...
+				flickrStore.fetch({ 	
+					query: {
+						userid: "44153025 at N00",
+						apikey: "8c6803164dbc395fb7131c9d54843627"
+					},
+					count: 1,
+						onComplete: onComplete, 
+						onError: dojo.partial(dojox.data.tests.stores.FlickrRestStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  containsValue",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the containsValue function of the store
+				//	description:
+				//		Simple test of the containsValue function of the store
+
+				var flickrStore = new dojox.data.FlickrRestStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					d.callback(true);
+				}
+
+				//Get one item...
+				flickrStore.fetch({ 	
+									query: {
+										userid: "44153025 at N00",
+										apikey: "8c6803164dbc395fb7131c9d54843627"
+									},
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.FlickrRestStore.error, t, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getAttributes",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getAttributes function of the store
+				//	description:
+				//		Simple test of the getAttributes function of the store
+
+				var flickrStore = new dojox.data.FlickrRestStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(flickrStore.isItem(items[0]));
+
+					var attributes = flickrStore.getAttributes(items[0]);
+					t.is(11, attributes.length);
+					d.callback(true);
+				}
+
+				//Get everything...
+				flickrStore.fetch({ 
+						query: {
+							userid: "44153025 at N00",
+							apikey: "8c6803164dbc395fb7131c9d54843627"
+						},						
+						count: 1, 
+						onComplete: onComplete, 
+						onError: dojo.partial(dojox.data.tests.stores.FlickrRestStore.error, t, d)
+					});
+				return d; //Object
+			}
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var flickrStore = new dojox.data.FlickrRestStore();
+
+			var features = flickrStore.getFeatures(); 
+			var count = 0;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read"));
+				count++;
+			}
+			t.assertTrue(count === 1);
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = new dojox.data.FlickrRestStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+		}
+	]
+);
+
diff --git a/dojox/data/tests/stores/FlickrStore.js b/dojox/data/tests/stores/FlickrStore.js
new file mode 100644
index 0000000..e81368f
--- /dev/null
+++ b/dojox/data/tests/stores/FlickrStore.js
@@ -0,0 +1,406 @@
+dojo.provide("dojox.data.tests.stores.FlickrStore");
+dojo.require("dojox.data.FlickrStore");
+dojo.require("dojo.data.api.Read");
+
+
+dojox.data.tests.stores.FlickrStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	d.errback(errData);	
+}
+
+doh.register("dojox.data.tests.stores.FlickrStore", 
+	[
+		{
+			name: "ReadAPI:  Fetch_One",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on FlickrStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on FlickrStore of a single item.
+
+				var flickrStore = new dojox.data.FlickrStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.is(1, items.length);
+					d.callback(true);
+				}
+				flickrStore.fetch({ 	query: {tags: "animals"},
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.FlickrStore.error, doh, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_20_Streaming",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on FlickrStore.
+				//	description:
+				//		Simple test of a basic fetch on FlickrStore.
+				var flickrStore = new dojox.data.FlickrStore();
+
+				var d = new doh.Deferred();
+				count = 0;
+
+				function onBegin(size, requestObj){
+					t.is(20, size);
+				}
+				function onItem(item, requestObj){
+					t.assertTrue(flickrStore.isItem(item));
+					count++;
+				}
+				function onComplete(items, request){
+					t.is(20, count);
+					t.is(null, items);
+					d.callback(true);
+				}
+
+				//Get everything...
+				flickrStore.fetch({	onBegin: onBegin,
+									count: 20,
+									onItem: onItem,
+									onComplete: onComplete,
+									onError: dojo.partial(dojox.data.tests.stores.FlickrStore.error, t, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_Paging",
+			timeout:	30000, //30 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+				//	description:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+
+				var flickrStore = new dojox.data.FlickrStore();
+
+				var d = new doh.Deferred();
+				function dumpFirstFetch(items, request){
+					t.is(5, items.length);
+                    request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpSecondFetch(items, request){
+					t.is(1, items.length);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpThirdFetch(items, request){
+					t.is(5, items.length);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpFourthFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpFourthFetch(items, request){
+					t.is(18, items.length);
+					request.start = 9;
+					request.count = 100;
+					request.onComplete = dumpFifthFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpFifthFetch(items, request){
+					t.is(11, items.length);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpSixthFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpSixthFetch(items, request){
+					t.is(18, items.length);
+					d.callback(true);
+				}
+
+				function completed(items, request){
+					t.is(7, items.length);
+					request.start = 1;
+					request.count = 5;
+					request.onComplete = dumpFirstFetch;
+					flickrStore.fetch(request);
+				}
+				flickrStore.fetch({count: 7, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.FlickrStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getLabel",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+
+				var flickrStore = new dojox.data.FlickrStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var label = flickrStore.getLabel(items[0]);
+					t.assertTrue(label !== null);
+					d.callback(true);
+				}
+				flickrStore.fetch({ 	query: {tags: "animals"}, 
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.FlickrStore.error, t, d)
+								});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getLabelAttributes",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+				var flickrStore = new dojox.data.FlickrStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = flickrStore.getLabelAttributes(items[0]);
+					t.assertTrue(dojo.isArray(labelList));
+					t.assertEqual("title", labelList[0]);
+					d.callback(true);
+				}
+				flickrStore.fetch({ 	query: {tags: "animals"},
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.FlickrStore.error, t, d)
+								});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getValue",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var flickrStore = new dojox.data.FlickrStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					t.assertTrue(flickrStore.getValue(items[0], "title") !== null);
+					t.assertTrue(flickrStore.getValue(items[0], "imageUrl") !== null);
+					t.assertTrue(flickrStore.getValue(items[0], "imageUrlSmall") !== null);
+					t.assertTrue(flickrStore.getValue(items[0], "imageUrlMedium") !== null);
+					d.callback(true);
+				}
+
+				//Get one item and look at it.
+				flickrStore.fetch({ count: 1, onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.FlickrStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getValues",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var flickrStore = new dojox.data.FlickrStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					t.assertTrue(flickrStore.getValues(items[0], "title") instanceof Array);
+					t.assertTrue(flickrStore.getValues(items[0], "description") instanceof Array);
+					t.assertTrue(flickrStore.getValues(items[0], "imageUrl") instanceof Array);
+					t.assertTrue(flickrStore.getValues(items[0], "imageUrlSmall") instanceof Array);
+					t.assertTrue(flickrStore.getValues(items[0], "imageUrlMedium") instanceof Array);
+					d.callback(true);
+				}
+				//Get one item and look at it.
+				flickrStore.fetch({ count: 1, onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.FlickrStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  isItem",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the isItem function of the store
+				//	description:
+				//		Simple test of the isItem function of the store
+				var flickrStore = new dojox.data.FlickrStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(5, items.length);
+					for(var i=0; i < items.length; i++){
+						t.assertTrue(flickrStore.isItem(items[i]));
+					}
+					d.callback(true);
+				}
+
+				//Get everything...
+				flickrStore.fetch({ count: 5, onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.FlickrStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  hasAttribute",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the hasAttribute function of the store
+				//	description:
+				//		Simple test of the hasAttribute function of the store
+
+				var flickrStore = new dojox.data.FlickrStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(items[0] !== null);
+					t.assertTrue(flickrStore.hasAttribute(items[0], "title"));
+					t.assertTrue(flickrStore.hasAttribute(items[0], "description"));
+					t.assertTrue(flickrStore.hasAttribute(items[0], "author"));
+					t.assertTrue(!flickrStore.hasAttribute(items[0], "Nothing"));
+					t.assertTrue(!flickrStore.hasAttribute(items[0], "Text"));
+
+					//Test that null attributes throw an exception
+					var passed = false;
+					try{
+						flickrStore.hasAttribute(items[0], null);
+					}catch (e){
+						passed = true;
+					}
+					t.assertTrue(passed);
+					d.callback(true);
+				}
+
+				//Get one item...
+				flickrStore.fetch({ 	query: {tags: "animals"}, 
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.FlickrStore.error, t, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  containsValue",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the containsValue function of the store
+				//	description:
+				//		Simple test of the containsValue function of the store
+
+				var flickrStore = new dojox.data.FlickrStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					d.callback(true);
+				}
+
+				//Get one item...
+				flickrStore.fetch({ 	query: {tags: "animals"}, 
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.FlickrStore.error, t, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getAttributes",
+			timeout:	10000, //10 seconds.  Flickr can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getAttributes function of the store
+				//	description:
+				//		Simple test of the getAttributes function of the store
+
+				var flickrStore = new dojox.data.FlickrStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(flickrStore.isItem(items[0]));
+
+					var attributes = flickrStore.getAttributes(items[0]);
+					t.is(10, attributes.length);
+					d.callback(true);
+				}
+
+				//Get everything...
+				flickrStore.fetch({ count: 1, onComplete: onComplete, onError: dojo.partial(dojox.data.tests.stores.FlickrStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var flickrStore = new dojox.data.FlickrStore();
+
+			var features = flickrStore.getFeatures(); 
+			var count = 0;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read"));
+				count++;
+			}
+			t.assertTrue(count === 1);
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = new dojox.data.FlickrStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
+
diff --git a/dojox/data/tests/stores/GoogleFeedStore.js b/dojox/data/tests/stores/GoogleFeedStore.js
new file mode 100644
index 0000000..4a7f315
--- /dev/null
+++ b/dojox/data/tests/stores/GoogleFeedStore.js
@@ -0,0 +1,570 @@
+dojo.provide("dojox.data.tests.stores.GoogleFeedStore");
+dojo.require("dojox.data.GoogleFeedStore");
+dojo.require("dojo.data.api.Read");
+
+dojox.data.tests.stores.GoogleFeedStore.getStore = function(){
+	return new dojox.data.GoogleFeedStore();
+};
+
+dojox.data.tests.stores.GoogleFeedStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	//console.trace();
+	d.errback(errData);
+};
+
+doh.register("dojox.data.tests.stores.GoogleFeedStore",
+	[
+		{
+			name: "ReadAPI:  Fetch_One",
+			timeout:	10000, // 10 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of a basic fetch on GoogleFeedStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on GoogleFeedStore of a single item.
+
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.is(1, items.length);
+					d.callback(true);
+				}
+				googleStore.fetch({
+					query: {
+						url: "http://shaneosullivan.wordpress.com/feed"
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleFeedStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  test_Invalid_Query",
+			timeout:	10000, // 10 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of a basic fetch on GoogleFeedStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on GoogleFeedStore of a single item.
+
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+				var d = new doh.Deferred();
+				function doNotCall1(items, request){
+					t.assertTrue(false);
+					d.callback(true);
+				}
+				function doNotCall2(items, request){
+					t.assertTrue(false);
+					d.callback(true);
+				}
+				function doNotCall3(items, request){
+					t.assertTrue(false);
+					d.callback(true);
+				}
+				try {
+					googleStore.fetch({
+						query: {
+						},
+						count: 1,
+						onItem:doNotCall2,
+						onBegin: doNotCall1,
+						onComplete: doNotCall3,
+						onError: function(){
+							//Swallow this as it is expected
+							d.callback(true);
+						}
+					});
+				} catch (e) {
+					console.log("exception thrown", e);
+					t.assertTrue(false);
+					d.callback(true);
+				}
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_20_Streaming",
+			timeout:	10000, //20 seconds.
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of a basic fetch on GoogleFeedStore.
+				//	description:
+				//		Simple test of a basic fetch on GoogleFeedStore.
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+				var d = new doh.Deferred();
+				var count = 0;
+
+				function onItem(item, requestObj){
+					t.assertTrue(googleStore.isItem(item));
+					count++;
+				}
+				function onComplete(items, request){
+					t.is(20, count);
+
+					t.is(null, items);
+					d.callback(true);
+				}
+				//Get everything...
+				googleStore.fetch({
+					query: {
+						url: "http://shaneosullivan.wordpress.com/feed"
+					},
+					onBegin: null,
+					count: 20,
+					onItem: onItem,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleFeedStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_Paging",
+			timeout:	10000, // 10 seconds.
+			runTest: function(t) {
+				//	summary:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+				//	description:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+				var d = new doh.Deferred();
+
+				function dumpSixthFetch(items, request){
+					t.is(16, items.length);
+					d.callback(true);
+				}
+
+				function dumpFifthFetch(items, request){
+					t.is(11, items.length);
+					request.start = 4;
+					request.count = 16;
+					request.onComplete = dumpSixthFetch;
+					googleStore.fetch(request);
+				}
+
+				function dumpFourthFetch(items, request){
+					t.is(18, items.length);
+					request.start = 5;
+					request.count = 11;
+					request.onComplete = dumpFifthFetch;
+					googleStore.fetch(request);
+				}
+
+				function dumpThirdFetch(items, request){
+					t.is(5, items.length);
+					request.start = 2;
+					request.count = 18;
+					request.onComplete = dumpFourthFetch;
+					googleStore.fetch(request);
+				}
+
+				function dumpSecondFetch(items, request){
+					t.is(1, items.length);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					googleStore.fetch(request);
+				}
+				
+				function dumpFirstFetch(items, request){
+					t.is(5, items.length);
+					request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					googleStore.fetch(request);
+				}
+
+				function completed(items, request){
+					t.is(7, items.length);
+					d.callback(true);
+				}
+				googleStore.fetch({
+					query: {
+						url: "http://shaneosullivan.wordpress.com/feed"
+					},
+					count: 7,
+					onComplete: completed,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleFeedStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getLabel",
+			timeout:	10000, // 10 seconds.
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var label = googleStore.getLabel(items[0]);
+					t.assertTrue(label !== null);
+					d.callback(true);
+				}
+				googleStore.fetch({
+					query: {
+						url: "http://shaneosullivan.wordpress.com/feed"
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleFeedStore.error, t, d)
+				});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getLabelAttributes",
+			timeout:	10000, // 10 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = googleStore.getLabelAttributes(items[0]);
+					t.assertTrue(dojo.isArray(labelList));
+					t.assertEqual("titleNoFormatting", labelList[0]);
+					d.callback(true);
+				}
+				googleStore.fetch({
+					query: {
+						url: "http://shaneosullivan.wordpress.com/feed"
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleFeedStore.error, t, d)
+				});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getValue",
+			timeout:	10000, // 10 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					t.assertTrue(googleStore.getValue(items[0], "unescapedUrl") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "url") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "visibleUrl") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "cacheUrl") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "title") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "titleNoFormatting") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "content") !== null);
+					d.callback(true);
+				}
+
+				//Get one item and look at it.
+				googleStore.fetch({
+					query: {
+						url: "http://shaneosullivan.wordpress.com/feed"
+					},
+					count: 1,
+					onComplete: completedAll,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleFeedStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getValue_Failure",
+			timeout:	10000, // 10 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+				var passed = false;
+				try{
+					var value = googleStore.getValue("NotAnItem", "foo");
+				}catch(e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+			}
+		},
+		{
+			name: "ReadAPI:  getValues",
+			timeout:	10000, // 10 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+                var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					var summary = googleStore.getValues(items[0], "unescapedUrl");
+					t.assertTrue(dojo.isArray(summary));
+
+					var url = googleStore.getValues(items[0], "url");
+					t.assertTrue(dojo.isArray(url));
+
+					var published = googleStore.getValues(items[0], "visibleUrl");
+					t.assertTrue(dojo.isArray(published));
+
+					var updated = googleStore.getValues(items[0], "cacheUrl");
+					t.assertTrue(dojo.isArray(updated));
+
+					var title = googleStore.getValues(items[0], "title");
+					t.assertTrue(dojo.isArray(title));
+
+					var titleNoFormatting = googleStore.getValues(items[0], "titleNoFormatting");
+					t.assertTrue(dojo.isArray(titleNoFormatting));
+
+					var content = googleStore.getValues(items[0], "content");
+					t.assertTrue(dojo.isArray(content));
+
+					d.callback(true);
+				}
+				//Get one item and look at it.
+				googleStore.fetch({
+					query: {
+						url: "http://shaneosullivan.wordpress.com/feed"
+					},
+					count: 1,
+					onComplete: completedAll,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleFeedStore.error,
+					t,
+					d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getValues_Failure",
+			timeout:	10000, // 10 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+				var passed = false;
+				try{
+					var value = googleStore.getValues("NotAnItem", "foo");
+				}catch(e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+			}
+		},
+		{
+			name: "ReadAPI:  isItem",
+			timeout:	10000, // 10 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the isItem function of the store
+				//	description:
+				//		Simple test of the isItem function of the store
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(5, items.length);
+					for(var i=0; i < items.length; i++){
+						t.assertTrue(googleStore.isItem(items[i]));
+					}
+					d.callback(true);
+				}
+
+				//Get everything...
+				googleStore.fetch({
+						query: {
+							url: "http://shaneosullivan.wordpress.com/feed"
+						},
+						count: 5,
+						onComplete: completedAll,
+						onError: dojo.partial(dojox.data.tests.stores.GoogleFeedStore.error, t, d)
+					});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  hasAttribute",
+			timeout:	10000, // 10 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the hasAttribute function of the store
+				//	description:
+				//		Simple test of the hasAttribute function of the store
+
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(items[0] !== null);
+					var count = 0;
+					t.assertTrue(googleStore.hasAttribute(items[0], "title"));
+					t.assertTrue(googleStore.hasAttribute(items[0], "link"));
+					t.assertTrue(googleStore.hasAttribute(items[0], "content"));
+					t.assertTrue(googleStore.hasAttribute(items[0], "author"));
+					t.assertTrue(googleStore.hasAttribute(items[0], "published"));
+					t.assertTrue(googleStore.hasAttribute(items[0], "categories"));
+					t.assertTrue(!googleStore.hasAttribute(items[0], "I dont exist"));
+
+					//Test that null attributes throw an exception
+					try{
+						googleStore.hasAttribute(items[0], null);
+						t.assertTrue(false);
+					}catch (e){
+
+					}
+					d.callback(true);
+				}
+
+				//Get one item...
+				googleStore.fetch({
+					query: {
+						url: "http://shaneosullivan.wordpress.com/feed"
+					},
+					count: 1,
+						onComplete: onComplete,
+						onError: dojo.partial(dojox.data.tests.stores.GoogleFeedStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  containsValue",
+			timeout:	10000, // 10 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the containsValue function of the store
+				//	description:
+				//		Simple test of the containsValue function of the store
+
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+
+					// This is the only way to test the results, as we cannot depend on the search
+					// result with a hard coded value.
+					t.assertTrue(googleStore.containsValue(items[0], "link", items[0].link));
+
+					d.callback(true);
+				}
+
+				//Get one item...
+				googleStore.fetch({
+					query: {
+						url: "http://shaneosullivan.wordpress.com/feed"
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleFeedStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getAttributes",
+			timeout:	10000, // 10 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getAttributes function of the store
+				//	description:
+				//		Simple test of the getAttributes function of the store
+
+				var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					console.log("items.length = " + items.length);
+					t.is(1, items.length);
+					t.assertTrue(googleStore.isItem(items[0]));
+
+					var attributes = googleStore.getAttributes(items[0]);
+
+					console.log("attributes.length = " + attributes.length, attributes);
+					t.is(7, attributes.length);
+					d.callback(true);
+				}
+
+				//Get everything...
+				googleStore.fetch({
+						query: {
+							url: "http://shaneosullivan.wordpress.com/feed"
+						},
+						count: 1,
+						onComplete: onComplete,
+						onError: dojo.partial(dojox.data.tests.stores.GoogleFeedStore.error, t, d)
+					});
+				return d; //Object
+			}
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary:
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var googleStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+
+			var features = googleStore.getFeatures();
+			var count = 0;
+			var i;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read"));
+				count++;
+			}
+			t.assertTrue(count === 1);
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.GoogleFeedStore.getStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+			var i;
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							console.log("Problem with function: [" + i + "].   Got value: " + testStoreMember);
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
diff --git a/dojox/data/tests/stores/GoogleSearchStore.js b/dojox/data/tests/stores/GoogleSearchStore.js
new file mode 100644
index 0000000..8d1597f
--- /dev/null
+++ b/dojox/data/tests/stores/GoogleSearchStore.js
@@ -0,0 +1,603 @@
+dojo.provide("dojox.data.tests.stores.GoogleSearchStore");
+dojo.require("dojox.data.GoogleSearchStore");
+dojo.require("dojo.data.api.Read");
+
+dojox.data.tests.stores.GoogleSearchStore.getStore = function(){
+	return new dojox.data.GoogleSearchStore();
+};
+
+dojox.data.tests.stores.GoogleSearchStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	//console.trace();
+	d.errback(errData);
+};
+
+doh.register("dojox.data.tests.stores.GoogleSearchStore",
+	[
+		{
+			name: "ReadAPI:  Fetch_One",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of a basic fetch on GoogleSearchStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on GoogleSearchStore of a single item.
+
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.is(1, items.length);
+					d.callback(true);
+				}
+				googleStore.fetch({
+					query: {
+						text: "kinsale"
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  test_Invalid_Query",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of a basic fetch on GoogleSearchStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on GoogleSearchStore of a single item.
+
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+				var d = new doh.Deferred();
+				function doNotCall1(items, request){
+					t.assertTrue(false);
+					d.callback(true);
+				}
+				function doNotCall2(items, request){
+					t.assertTrue(false);
+					d.callback(true);
+				}
+				function doNotCall3(items, request){
+					t.assertTrue(false);
+					d.callback(true);
+				}
+				try {
+					googleStore.fetch({
+						query: {
+
+						},
+						count: 1,
+						onItem:doNotCall2,
+						onBegin: doNotCall1,
+						onComplete: doNotCall3,
+						onError: function(){
+							//Swallow this as it is expected
+							d.callback(true);
+						}
+					});
+				} catch (e) {
+					console.log("exception thrown", e);
+					t.assertTrue(false);
+					d.callback(true);
+				}
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_25_Streaming",
+			timeout:	30000, //20 seconds.
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of a basic fetch on GoogleSearchStore.
+				//	description:
+				//		Simple test of a basic fetch on GoogleSearchStore.
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+				var d = new doh.Deferred();
+				var count = 0;
+
+				function onItem(item, requestObj){
+					t.assertTrue(googleStore.isItem(item));
+					count++;
+				}
+				function onComplete(items, request){
+					t.is(25, count);
+
+					t.is(null, items);
+					d.callback(true);
+				}
+				//Get everything...
+				googleStore.fetch({
+					query: {
+						text: "kinsale"
+					},
+					onBegin: null,
+					count: 25,
+					onItem: onItem,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_Paging",
+			timeout:	30000, // 30 seconds.
+			runTest: function(t) {
+				//	summary:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+				//	description:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+				var d = new doh.Deferred();
+
+				function dumpSixthFetch(items, request){
+					t.is(16, items.length);
+					d.callback(true);
+				}
+
+				function dumpFifthFetch(items, request){
+					t.is(11, items.length);
+					request.start = 4;
+					request.count = 16;
+					request.onComplete = dumpSixthFetch;
+					googleStore.fetch(request);
+				}
+
+				function dumpFourthFetch(items, request){
+					t.is(18, items.length);
+					request.start = 5;
+					request.count = 11;
+					request.onComplete = dumpFifthFetch;
+					googleStore.fetch(request);
+				}
+
+				function dumpThirdFetch(items, request){
+					t.is(5, items.length);
+					request.start = 2;
+					request.count = 18;
+					request.onComplete = dumpFourthFetch;
+					googleStore.fetch(request);
+				}
+
+				function dumpSecondFetch(items, request){
+					t.is(1, items.length);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					googleStore.fetch(request);
+				}
+				
+				function dumpFirstFetch(items, request){
+					t.is(5, items.length);
+					request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					googleStore.fetch(request);
+				}
+
+				function completed(items, request){
+					t.is(7, items.length);
+					d.callback(true);
+				}
+				googleStore.fetch({
+					query: {
+						text: "kinsale"
+					},
+					count: 7,
+					onComplete: completed,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getLabel",
+			timeout:	30000, // 30 seconds.
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var label = googleStore.getLabel(items[0]);
+					t.assertTrue(label !== null);
+					d.callback(true);
+				}
+				googleStore.fetch({
+					query: {
+						text: "kinsale"
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error, t, d)
+				});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getLabelAttributes",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = googleStore.getLabelAttributes(items[0]);
+					t.assertTrue(dojo.isArray(labelList));
+					t.assertEqual("titleNoFormatting", labelList[0]);
+					d.callback(true);
+				}
+				googleStore.fetch({
+					query: {
+						text: "kinsale"
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error, t, d)
+				});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getValue",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					t.assertTrue(googleStore.getValue(items[0], "unescapedUrl") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "url") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "visibleUrl") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "cacheUrl") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "title") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "titleNoFormatting") !== null);
+					t.assertTrue(googleStore.getValue(items[0], "content") !== null);
+					d.callback(true);
+				}
+
+				//Get one item and look at it.
+				googleStore.fetch({
+					query: {
+						text: "kinsale"
+					},
+					count: 1,
+					onComplete: completedAll,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getValue_Failure",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+				var passed = false;
+				try{
+					var value = googleStore.getValue("NotAnItem", "foo");
+				}catch(e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+			}
+		},
+		{
+			name: "ReadAPI:  getValues",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+                		var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					var summary = googleStore.getValues(items[0], "unescapedUrl");
+					t.assertTrue(dojo.isArray(summary));
+
+					var url = googleStore.getValues(items[0], "url");
+					t.assertTrue(dojo.isArray(url));
+
+					var published = googleStore.getValues(items[0], "visibleUrl");
+					t.assertTrue(dojo.isArray(published));
+
+					var updated = googleStore.getValues(items[0], "cacheUrl");
+					t.assertTrue(dojo.isArray(updated));
+
+					var title = googleStore.getValues(items[0], "title");
+					t.assertTrue(dojo.isArray(title));
+
+					var titleNoFormatting = googleStore.getValues(items[0], "titleNoFormatting");
+					t.assertTrue(dojo.isArray(titleNoFormatting));
+
+					var content = googleStore.getValues(items[0], "content");
+					t.assertTrue(dojo.isArray(content));
+
+					d.callback(true);
+				}
+				//Get one item and look at it.
+				googleStore.fetch({
+					query: {
+						text: "kinsale"
+					},
+					count: 1,
+					onComplete: completedAll,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error,
+					t,
+					d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getValues_Failure",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+				var passed = false;
+				try{
+					var value = googleStore.getValues("NotAnItem", "foo");
+				}catch(e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+			}
+		},
+		{
+			name: "ReadAPI:  isItem",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the isItem function of the store
+				//	description:
+				//		Simple test of the isItem function of the store
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(5, items.length);
+					for(var i=0; i < items.length; i++){
+						t.assertTrue(googleStore.isItem(items[i]));
+					}
+					d.callback(true);
+				}
+
+				//Get everything...
+				googleStore.fetch({
+						query: {
+							text: "kinsale"
+						},
+						count: 5,
+						onComplete: completedAll,
+						onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error, t, d)
+					});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  hasAttribute",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the hasAttribute function of the store
+				//	description:
+				//		Simple test of the hasAttribute function of the store
+
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(items[0] !== null);
+					var count = 0;
+					t.assertTrue(googleStore.hasAttribute(items[0], "unescapedUrl"));
+					t.assertTrue(googleStore.hasAttribute(items[0], "url"));
+					t.assertTrue(googleStore.hasAttribute(items[0], "visibleUrl"));
+					t.assertTrue(googleStore.hasAttribute(items[0], "cacheUrl"));
+					t.assertTrue(googleStore.hasAttribute(items[0], "title"));
+					t.assertTrue(googleStore.hasAttribute(items[0], "titleNoFormatting"));
+					t.assertTrue(googleStore.hasAttribute(items[0], "content"));
+					t.assertTrue(!googleStore.hasAttribute(items[0], "I dont exist"));
+
+					//Test that null attributes throw an exception
+					try{
+						googleStore.hasAttribute(items[0], null);
+						t.assertTrue(false);
+					}catch (e){
+
+					}
+					d.callback(true);
+				}
+
+				//Get one item...
+				googleStore.fetch({
+					query: {
+						text: "kinsale"
+					},
+					count: 1,
+						onComplete: onComplete,
+						onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  containsValue",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the containsValue function of the store
+				//	description:
+				//		Simple test of the containsValue function of the store
+
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+
+					// This is the only way to test the results, as we cannot depend on the search
+					// result with a hard coded value.
+					t.assertTrue(googleStore.containsValue(items[0], "url", items[0].url));
+
+					d.callback(true);
+				}
+
+				//Get one item...
+				googleStore.fetch({
+					query: {
+						text: "kinsale"
+					},
+					count: 1,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getAttributes",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getAttributes function of the store
+				//	description:
+				//		Simple test of the getAttributes function of the store
+
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(googleStore.isItem(items[0]));
+
+					var attributes = googleStore.getAttributes(items[0]);
+
+					t.is(8, attributes.length);
+					d.callback(true);
+				}
+
+				//Get everything...
+				googleStore.fetch({
+						query: {
+							text: "kinsale"
+						},
+						count: 1,
+						onComplete: onComplete,
+						onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error, t, d)
+					});
+				return d; //Object
+			}
+		},
+		{
+			name: "GoogleSearchStore:  DOM Cleanup",
+			timeout:	30000, // 30 seconds
+			runTest: function(t) {
+				//	summary:
+				//		Simple test of the getAttributes function of the store
+				//	description:
+				//		Simple test of the getAttributes function of the store
+
+				var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+				var d = new doh.Deferred();
+				
+				var preScriptCount = dojo.query("head script").length;
+				
+				function onComplete(items){
+					var postScriptCount = dojo.query("head script").length;					
+					t.is(preScriptCount, postScriptCount);
+					d.callback(true);
+				}
+
+				//Get everything...
+				googleStore.fetch({
+						query: {
+							text: "kinsale"
+						},
+						count: 50,
+						onComplete: onComplete,
+						onError: dojo.partial(dojox.data.tests.stores.GoogleSearchStore.error, t, d)
+					});
+				return d; //Object
+			}
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary:
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var googleStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+
+			var features = googleStore.getFeatures();
+			var count = 0;
+			var i;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read"));
+				count++;
+			}
+			t.assertTrue(count === 1);
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.GoogleSearchStore.getStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+			var i;
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							console.log("Problem with function: [" + i + "].   Got value: " + testStoreMember);
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
diff --git a/dojox/data/tests/stores/HtmlStore.js b/dojox/data/tests/stores/HtmlStore.js
new file mode 100644
index 0000000..7684ad8
--- /dev/null
+++ b/dojox/data/tests/stores/HtmlStore.js
@@ -0,0 +1,861 @@
+dojo.provide("dojox.data.tests.stores.HtmlStore");
+dojo.require("dojox.data.HtmlStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+
+
+dojox.data.tests.stores.HtmlStore.getBooks3Store = function(){
+	return new dojox.data.HtmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books3.html").toString(), dataId: "books3"});
+};
+
+dojox.data.tests.stores.HtmlStore.getBooks2Store = function(){
+	return new dojox.data.HtmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books2.html").toString(), dataId: "books2"});
+};
+
+dojox.data.tests.stores.HtmlStore.getBooksStore = function(){
+	return new dojox.data.HtmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books.html").toString(), dataId: "books"});
+};
+
+dojox.data.tests.stores.HtmlStore.getBooksStoreWhitespace = function(){
+	return new dojox.data.HtmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/booksWhitespace.html").toString(), dataId: "books", trimWhitespace: true});
+};
+
+dojox.data.tests.stores.HtmlStore.getBooks3StoreWhitespace = function(){
+	return new dojox.data.HtmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books3Whitespace.html").toString(), dataId: "books3", trimWhitespace: true});
+};
+
+doh.register("dojox.data.tests.stores.HtmlStore", 
+	[
+/***************************************
+     dojo.data.api.Read API
+***************************************/
+		function testReadAPI_fetch_all_table(t){
+			//	summary: 
+			//		Simple test of fetching all xml items through an XML element called isbn
+			//	description:
+			//		Simple test of fetching all xml items through an XML element called isbn
+			var store = dojox.data.tests.stores.HtmlStore.getBooksStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_table_Whitespace(t){
+			//	summary: 
+			//		Simple test of fetching all table row items through an header called isbn
+			//	description:
+			//		Simple test of fetching all table row items through an header called isbn
+			var store = dojox.data.tests.stores.HtmlStore.getBooksStoreWhitespace();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_list(t){
+			//	summary: 
+			//		Simple test of fetching all xml items through an XML element called isbn
+			//	description:
+			//		Simple test of fetching all xml items through an XML element called isbn
+			var store = dojox.data.tests.stores.HtmlStore.getBooks3Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(5, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{name:"*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one_table(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one_table_Whitespace(t){
+			//	summary: 
+			//		Simple test of fetching one item through an element called isbn
+			//	description:
+			//		Simple test of fetching one item through an element called isbn
+			var store = dojox.data.tests.stores.HtmlStore.getBooksStoreWhitespace();
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"19"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one_list(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn
+			var store = dojox.data.tests.stores.HtmlStore.getBooks3Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{name:"A9B57C - Title of 1 - Author of 1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one_list_Whitespace(t){
+			//	summary: 
+			//		Simple test of fetching one item through an attribute called name
+			//	description:
+			//		Simple test of fetching one item through an attribute called name
+			var store = dojox.data.tests.stores.HtmlStore.getBooks3StoreWhitespace();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{name:"A9B57C - Title of 1 - Author of 1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_paging(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn
+			var store = dojox.data.tests.stores.HtmlStore.getBooksStore();
+			
+			var d = new doh.Deferred();
+			function dumpFirstFetch(items, request){
+				t.assertEqual(5, items.length);
+				request.start = 3;
+				request.count = 1;
+				request.onComplete = dumpSecondFetch;
+				store.fetch(request);
+			}
+
+			function dumpSecondFetch(items, request){
+				t.assertEqual(1, items.length);
+				request.start = 0;
+				request.count = 5;
+				request.onComplete = dumpThirdFetch;
+				store.fetch(request);
+			}
+
+			function dumpThirdFetch(items, request){
+				t.assertEqual(5, items.length);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpFourthFetch;
+				store.fetch(request);
+			}
+
+			function dumpFourthFetch(items, request){
+				t.assertEqual(18, items.length);
+				request.start = 9;
+				request.count = 100;
+				request.onComplete = dumpFifthFetch;
+				store.fetch(request);
+			}
+
+			function dumpFifthFetch(items, request){
+				t.assertEqual(11, items.length);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpSixthFetch;
+				store.fetch(request);
+			}
+
+			function dumpSixthFetch(items, request){
+				t.assertEqual(18, items.length);
+				d.callback(true);
+			}
+
+			function completed(items, request){
+				t.assertEqual(20, items.length);
+				request.start = 1;
+				request.count = 5;
+				request.onComplete = dumpFirstFetch;
+				store.fetch(request);
+			}
+
+			function error(errData, request){
+				d.errback(errData);
+			}
+
+			store.fetch({onComplete: completed, onError: error});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern0(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"?9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern1(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(4, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B57?"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern2(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with * pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with * pattern match
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(5, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern_caseInsensitive(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case insensitive mode.
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case insensitive mode.
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"?9b574"}, queryOptions: {ignoreCase: true}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern_caseSensitive(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case sensitive mode.
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case sensitive mode.
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"?9B574"}, queryOptions: {ignoreCase: false}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_getLabel_table(t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = store.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				t.assertEqual("Item #4", label);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d;
+		},
+		function testReadAPI_getLabel_list(t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+
+			var store = dojox.data.tests.stores.HtmlStore.getBooks3Store();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = store.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				t.assertEqual("A9B57C - Title of 1 - Author of 1", label);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{name:"A9B57C - Title of 1 - Author of 1"}, onComplete: onComplete, onError: onError});
+			return d;
+		},
+		function testReadAPI_getLabelAttributes(t){
+			//	summary: 
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var labelList = store.getLabelAttributes(items[0]);
+				t.assertTrue(labelList === null);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d;
+		},
+
+		function testReadAPI_getValue(t){
+			 //	summary: 
+			 //		Simple test of the getValue API
+			 //	description:
+			 //		Simple test of the getValue API
+			 var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request) {
+				 t.assertEqual(1, items.length);
+				 var item = items[0];
+				 t.assertTrue(store.hasAttribute(item,"isbn"));
+				 t.assertEqual(store.getValue(item,"isbn"), "A9B574");
+				 d.callback(true);
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+		function testReadAPI_getValues(t){
+			 //	summary: 
+			 //		Simple test of the getValues API
+			 //	description:
+			 //		Simple test of the getValues API
+			 var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request) {
+				 t.assertEqual(1, items.length);
+				 var item = items[0];
+				 t.assertTrue(store.hasAttribute(item,"isbn"));
+				 var values = store.getValues(item,"isbn");
+				 t.assertEqual(1,values.length);
+				 t.assertEqual("A9B574", values[0]);
+				 d.callback(true);
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+		function testReadAPI_isItem(t){
+			 //	summary: 
+			 //		Simple test of the isItem API
+			 //	description:
+			 //		Simple test of the isItem API
+			 var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.isItem(item));
+				t.assertTrue(!store.isItem({}));
+				t.assertTrue(!store.isItem("Foo"));
+				t.assertTrue(!store.isItem(1));
+				d.callback(true);
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+		function testReadAPI_isItem_multistore(t){
+			//	summary: 
+			//		Simple test of the isItem API across multiple store instances.
+			//	description:
+			//		Simple test of the isItem API across multiple store instances.
+			var store1 = dojox.data.tests.stores.HtmlStore.getBooksStore();
+			var store2 = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete1(items, request) {
+				t.assertEqual(1, items.length);
+				var item1 = items[0];
+				t.assertTrue(store1.isItem(item1));
+
+				function onComplete2(items, request) {
+					t.assertEqual(1, items.length);
+					var item2 = items[0];
+					t.assertTrue(store2.isItem(item2));
+					t.assertTrue(!store1.isItem(item2));
+					t.assertTrue(!store2.isItem(item1));
+					d.callback(true);
+				}
+				store2.fetch({query:{isbn:"A9B574"}, onComplete: onComplete2, onError: onError});
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store1.fetch({query:{isbn:"1"}, onComplete: onComplete1, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_hasAttribute(t){
+			//	summary: 
+			//		Simple test of the hasAttribute API
+			//	description:
+			//		Simple test of the hasAttribute API
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.hasAttribute(item,"isbn"));
+				t.assertTrue(!store.hasAttribute(item,"bob"));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_containsValue(t){
+			//	summary: 
+			//		Simple test of the containsValue API
+			//	description:
+			//		Simple test of the containsValue API
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"isbn", "A9B574"));
+				t.assertTrue(!store.containsValue(item,"isbn", "bob"));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortDescending(t){
+			//	summary: 
+			//		Simple test of the sorting API in descending order.
+			//	description:
+			//		Simple test of the sorting API in descending order.
+			var store = dojox.data.tests.stores.HtmlStore.getBooksStore();
+
+			//Comparison is done as a string type (toString comparison), so the order won't be numeric
+			//So have to compare in 'alphabetic' order.
+			var order = [9,8,7,6,5,4,3,20,2,19,18,17,16,15,14,13,12,11,10,1];
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(order[i], store.getValue(items[i],"isbn").toString());
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn", descending: true}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortAscending(t){
+			//	summary: 
+			//		Simple test of the sorting API in ascending order.
+			//	description:
+			//		Simple test of the sorting API in ascending order.
+			var store = dojox.data.tests.stores.HtmlStore.getBooksStore();
+
+			//Comparison is done as a string type (toString comparison), so the order won't be numeric
+			//So have to compare in 'alphabetic' order.
+			var order = [1,10,11,12,13,14,15,16,17,18,19,2,20,3,4,5,6,7,8,9];
+						
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+				var itemId = 1;
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(order[i], store.getValue(items[i],"isbn").toString());
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn"}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortDescendingNumeric(t){
+			//	summary: 
+			//		Simple test of the sorting API in descending order using a numeric comparator.
+			//	description:
+			//		Simple test of the sorting API in descending order using a numeric comparator.
+			var store = dojox.data.tests.stores.HtmlStore.getBooksStore();
+
+			//isbn should be treated as a numeric, not as a string comparison
+			store.comparatorMap = {};
+			store.comparatorMap["isbn"] = function(a, b){
+				var ret = 0;
+				if(parseInt(a.toString()) > parseInt(b.toString())){
+					ret = 1;
+				}else if(parseInt(a.toString()) < parseInt(b.toString())){
+					ret = -1;
+				}
+				return ret; //int, {-1,0,1}
+			};
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+                		t.assertEqual(20, items.length);
+                		var itemId = 20;
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(itemId, store.getValue(items[i],"isbn").toString());
+					itemId--;
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn", descending: true}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortAscendingNumeric(t){
+			//	summary: 
+			//		Simple test of the sorting API in ascending order using a numeric comparator.
+			//	description:
+			//		Simple test of the sorting API in ascending order using a numeric comparator.
+			var store = dojox.data.tests.stores.HtmlStore.getBooksStore();
+
+			//isbn should be treated as a numeric, not as a string comparison
+			store.comparatorMap = {};
+			store.comparatorMap["isbn"] = function(a, b){
+				var ret = 0;
+				if(parseInt(a.toString()) > parseInt(b.toString())){
+					ret = 1;
+				}else if(parseInt(a.toString()) < parseInt(b.toString())){
+					ret = -1;
+				}
+				return ret; //int, {-1,0,1}
+			};
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+				var itemId = 1;
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(itemId, store.getValue(items[i],"isbn").toString());
+					itemId++;
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn"}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_isItemLoaded(t){
+			//	summary: 
+			//		Simple test of the isItemLoaded API
+			//	description:
+			//		Simple test of the isItemLoaded API
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.isItemLoaded(item));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+			var features = store.getFeatures(); 
+			var count = 0;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read" || i === "dojo.data.api.Identity"));
+				count++;
+			}
+			t.assertEqual(2, count);
+		},
+		function testReadAPI_getAttributes(t){
+			//	summary: 
+			//		Simple test of the getAttributes API
+			//	description:
+			//		Simple test of the getAttributes API
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				var attributes = store.getAttributes(item);
+				t.assertEqual(3,attributes.length);
+				for(var i=0; i<attributes.length; i++){
+					t.assertTrue((attributes[i] === "isbn" || attributes[i] === "title" || attributes[i] === "author"));
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.HtmlStore.getBooksStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				var member = readApi[i];
+				//Check that all the 'Read' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						console.log("Problem with function: [" + i + "]");
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		},
+/***************************************
+     dojo.data.api.Identity API
+***************************************/
+		function testIdentityAPI_getIdentity_table(t){
+			//	summary: 
+			//		Simple test of the getAttributes API
+			//	description:
+			//		Simple test of the getAttributes API
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertEqual(4,store.getIdentity(item));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testIdentityAPI_getIdentity_list(t){
+			//	summary: 
+			//		Simple test of the getAttributes API
+			//	description:
+			//		Simple test of the getAttributes API
+			var store = dojox.data.tests.stores.HtmlStore.getBooks3Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertEqual("A9B57C - Title of 1 - Author of 1",store.getIdentity(item));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{name:"A9B57C - Title of 1 - Author of 1"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testIdentityAPI_getIdentityAttributes(t){
+			//	summary: 
+			//		Simple test of the getAttributes API
+			//	description:
+			//		Simple test of the getAttributes API
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				//Should have none, as it's not a public attribute.
+				var attributes = store.getIdentityAttributes(item);
+				t.assertEqual(null, attributes);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testIdentityAPI_fetchItemByIdentity_table(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity API
+			//	description:
+			//		Simple test of the fetchItemByIdentity API
+			var store = dojox.data.tests.stores.HtmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onItem(item, request) {
+				t.assertTrue(item !== null);
+				t.assertTrue(store.isItem(item));
+				t.assertEqual("A9B574", store.getValue(item, "isbn"));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetchItemByIdentity({identity: 4, onItem: onItem, onError: onError});
+			return d; //Object
+		},
+		function testIdentityAPI_fetchItemByIdentity_list(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity API
+			//	description:
+			//		Simple test of the fetchItemByIdentity API
+			var store = dojox.data.tests.stores.HtmlStore.getBooks3Store();
+
+			var d = new doh.Deferred();
+			function onItem(item, request) {
+				t.assertTrue(item !== null);
+				t.assertTrue(store.isItem(item));
+				t.assertEqual("A9B57C - Title of 1 - Author of 1", store.getValue(item, "name"));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetchItemByIdentity({identity: "A9B57C - Title of 1 - Author of 1", onItem: onItem, onError: onError});
+			return d; //Object
+		},
+		function testIdentityAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.HtmlStore.getBooksStore();
+			var identityApi = new dojo.data.api.Identity();
+			var passed = true;
+
+			for(i in identityApi){
+				var member = identityApi[i];
+				//Check that all the 'Read' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						console.log("Problem with function: [" + i + "]");
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
+
+//Register the remote tests ... when they work.
+//doh.registerUrl("dojox.data.tests.stores.HtmlStore.remote", dojo.moduleUrl("dojox.data.tests", "ml/test_HtmlStore_declaratively.html"));
\ No newline at end of file
diff --git a/dojox/data/tests/stores/HtmlTableStore.js b/dojox/data/tests/stores/HtmlTableStore.js
new file mode 100644
index 0000000..b7daf1c
--- /dev/null
+++ b/dojox/data/tests/stores/HtmlTableStore.js
@@ -0,0 +1,698 @@
+dojo.provide("dojox.data.tests.stores.HtmlTableStore");
+dojo.require("dojox.data.HtmlTableStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+
+
+dojox.data.tests.stores.HtmlTableStore.getBooks2Store = function(){
+	return new dojox.data.HtmlTableStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books2.html").toString(), tableId: "books2"});
+};
+
+dojox.data.tests.stores.HtmlTableStore.getBooksStore = function(){
+	return new dojox.data.HtmlTableStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books.html").toString(), tableId: "books"});
+};
+
+doh.register("dojox.data.tests.stores.HtmlTableStore", 
+	[
+/***************************************
+     dojo.data.api.Read API
+***************************************/
+		function testReadAPI_fetch_all(t){
+			//	summary: 
+			//		Simple test of fetching all xml items through an XML element called isbn
+			//	description:
+			//		Simple test of fetching all xml items through an XML element called isbn
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooksStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_paging(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooksStore();
+			
+			var d = new doh.Deferred();
+			function dumpFirstFetch(items, request){
+				t.assertEqual(5, items.length);
+				request.start = 3;
+				request.count = 1;
+				request.onComplete = dumpSecondFetch;
+				store.fetch(request);
+			}
+
+			function dumpSecondFetch(items, request){
+				t.assertEqual(1, items.length);
+				request.start = 0;
+				request.count = 5;
+				request.onComplete = dumpThirdFetch;
+				store.fetch(request);
+			}
+
+			function dumpThirdFetch(items, request){
+				t.assertEqual(5, items.length);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpFourthFetch;
+				store.fetch(request);
+			}
+
+			function dumpFourthFetch(items, request){
+				t.assertEqual(18, items.length);
+				request.start = 9;
+				request.count = 100;
+				request.onComplete = dumpFifthFetch;
+				store.fetch(request);
+			}
+
+			function dumpFifthFetch(items, request){
+				t.assertEqual(11, items.length);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpSixthFetch;
+				store.fetch(request);
+			}
+
+			function dumpSixthFetch(items, request){
+				t.assertEqual(18, items.length);
+				d.callback(true);
+			}
+
+			function completed(items, request){
+				t.assertEqual(20, items.length);
+				request.start = 1;
+				request.count = 5;
+				request.onComplete = dumpFirstFetch;
+				store.fetch(request);
+			}
+
+			function error(errData, request){
+				d.errback(errData);
+			}
+
+			store.fetch({onComplete: completed, onError: error});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern0(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"?9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern1(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(4, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B57?"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern2(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with * pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with * pattern match
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(5, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern_caseInsensitive(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case insensitive mode.
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case insensitive mode.
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"?9b574"}, queryOptions: {ignoreCase: true}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern_caseSensitive(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case sensitive mode.
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case sensitive mode.
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"?9B574"}, queryOptions: {ignoreCase: false}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_getLabel(t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = store.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				t.assertEqual("Table Row #3", label);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d;
+		},
+		function testReadAPI_getLabelAttributes(t){
+			//	summary: 
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var labelList = store.getLabelAttributes(items[0]);
+				t.assertTrue(labelList === null);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d;
+		},
+
+		function testReadAPI_getValue(t){
+			 //	summary: 
+			 //		Simple test of the getValue API
+			 //	description:
+			 //		Simple test of the getValue API
+			 var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request) {
+				 t.assertEqual(1, items.length);
+				 var item = items[0];
+				 t.assertTrue(store.hasAttribute(item,"isbn"));
+				 t.assertEqual(store.getValue(item,"isbn"), "A9B574");
+				 d.callback(true);
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+		function testReadAPI_getValues(t){
+			 //	summary: 
+			 //		Simple test of the getValues API
+			 //	description:
+			 //		Simple test of the getValues API
+			 var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request) {
+				 t.assertEqual(1, items.length);
+				 var item = items[0];
+				 t.assertTrue(store.hasAttribute(item,"isbn"));
+				 var values = store.getValues(item,"isbn");
+				 t.assertEqual(1,values.length);
+				 t.assertEqual("A9B574", values[0]);
+				 d.callback(true);
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+		function testReadAPI_isItem(t){
+			 //	summary: 
+			 //		Simple test of the isItem API
+			 //	description:
+			 //		Simple test of the isItem API
+			 var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.isItem(item));
+				t.assertTrue(!store.isItem({}));
+				t.assertTrue(!store.isItem("Foo"));
+				t.assertTrue(!store.isItem(1));
+				d.callback(true);
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+		function testReadAPI_isItem_multistore(t){
+			//	summary: 
+			//		Simple test of the isItem API across multiple store instances.
+			//	description:
+			//		Simple test of the isItem API across multiple store instances.
+			var store1 = dojox.data.tests.stores.HtmlTableStore.getBooksStore();
+			var store2 = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete1(items, request) {
+				t.assertEqual(1, items.length);
+				var item1 = items[0];
+				t.assertTrue(store1.isItem(item1));
+
+				function onComplete2(items, request) {
+					t.assertEqual(1, items.length);
+					var item2 = items[0];
+					t.assertTrue(store2.isItem(item2));
+					t.assertTrue(!store1.isItem(item2));
+					t.assertTrue(!store2.isItem(item1));
+					d.callback(true);
+				}
+				store2.fetch({query:{isbn:"A9B574"}, onComplete: onComplete2, onError: onError});
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store1.fetch({query:{isbn:"1"}, onComplete: onComplete1, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_hasAttribute(t){
+			//	summary: 
+			//		Simple test of the hasAttribute API
+			//	description:
+			//		Simple test of the hasAttribute API
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.hasAttribute(item,"isbn"));
+				t.assertTrue(!store.hasAttribute(item,"bob"));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_containsValue(t){
+			//	summary: 
+			//		Simple test of the containsValue API
+			//	description:
+			//		Simple test of the containsValue API
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"isbn", "A9B574"));
+				t.assertTrue(!store.containsValue(item,"isbn", "bob"));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortDescending(t){
+			//	summary: 
+			//		Simple test of the sorting API in descending order.
+			//	description:
+			//		Simple test of the sorting API in descending order.
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooksStore();
+
+			//Comparison is done as a string type (toString comparison), so the order won't be numeric
+			//So have to compare in 'alphabetic' order.
+			var order = [9,8,7,6,5,4,3,20,2,19,18,17,16,15,14,13,12,11,10,1];
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(order[i], store.getValue(items[i],"isbn").toString());
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn", descending: true}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortAscending(t){
+			//	summary: 
+			//		Simple test of the sorting API in ascending order.
+			//	description:
+			//		Simple test of the sorting API in ascending order.
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooksStore();
+
+			//Comparison is done as a string type (toString comparison), so the order won't be numeric
+			//So have to compare in 'alphabetic' order.
+			var order = [1,10,11,12,13,14,15,16,17,18,19,2,20,3,4,5,6,7,8,9];
+						
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+				var itemId = 1;
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(order[i], store.getValue(items[i],"isbn").toString());
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn"}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortDescendingNumeric(t){
+			//	summary: 
+			//		Simple test of the sorting API in descending order using a numeric comparator.
+			//	description:
+			//		Simple test of the sorting API in descending order using a numeric comparator.
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooksStore();
+
+			//isbn should be treated as a numeric, not as a string comparison
+			store.comparatorMap = {};
+			store.comparatorMap["isbn"] = function(a, b){
+				var ret = 0;
+				if(parseInt(a.toString()) > parseInt(b.toString())){
+					ret = 1;
+				}else if(parseInt(a.toString()) < parseInt(b.toString())){
+					ret = -1;
+				}
+				return ret; //int, {-1,0,1}
+			};
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+                		t.assertEqual(20, items.length);
+                		var itemId = 20;
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(itemId, store.getValue(items[i],"isbn").toString());
+					itemId--;
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn", descending: true}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortAscendingNumeric(t){
+			//	summary: 
+			//		Simple test of the sorting API in ascending order using a numeric comparator.
+			//	description:
+			//		Simple test of the sorting API in ascending order using a numeric comparator.
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooksStore();
+
+			//isbn should be treated as a numeric, not as a string comparison
+			store.comparatorMap = {};
+			store.comparatorMap["isbn"] = function(a, b){
+				var ret = 0;
+				if(parseInt(a.toString()) > parseInt(b.toString())){
+					ret = 1;
+				}else if(parseInt(a.toString()) < parseInt(b.toString())){
+					ret = -1;
+				}
+				return ret; //int, {-1,0,1}
+			};
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+				var itemId = 1;
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(itemId, store.getValue(items[i],"isbn").toString());
+					itemId++;
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn"}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_isItemLoaded(t){
+			//	summary: 
+			//		Simple test of the isItemLoaded API
+			//	description:
+			//		Simple test of the isItemLoaded API
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.isItemLoaded(item));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+			var features = store.getFeatures(); 
+			var count = 0;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read" || i === "dojo.data.api.Identity"));
+				count++;
+			}
+			t.assertEqual(2, count);
+		},
+		function testReadAPI_getAttributes(t){
+			//	summary: 
+			//		Simple test of the getAttributes API
+			//	description:
+			//		Simple test of the getAttributes API
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				var attributes = store.getAttributes(item);
+				t.assertEqual(3,attributes.length);
+				for(var i=0; i<attributes.length; i++){
+					t.assertTrue((attributes[i] === "isbn" || attributes[i] === "title" || attributes[i] === "author"));
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.HtmlTableStore.getBooksStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				var member = readApi[i];
+				//Check that all the 'Read' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						console.log("Problem with function: [" + i + "]");
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		},
+/***************************************
+     dojo.data.api.Identity API
+***************************************/
+		function testIdentityAPI_getIdentity(t){
+			//	summary: 
+			//		Simple test of the getAttributes API
+			//	description:
+			//		Simple test of the getAttributes API
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertEqual(3,store.getIdentity(item));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testIdentityAPI_getIdentityAttributes(t){
+			//	summary: 
+			//		Simple test of the getAttributes API
+			//	description:
+			//		Simple test of the getAttributes API
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				//Should have none, as it's not a public attribute.
+				var attributes = store.getIdentityAttributes(item);
+				t.assertEqual(null, attributes);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testIdentityAPI_fetchItemByIdentity(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity API
+			//	description:
+			//		Simple test of the fetchItemByIdentity API
+			var store = dojox.data.tests.stores.HtmlTableStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onItem(item, request) {
+				t.assertTrue(item !== null);
+				t.assertTrue(store.isItem(item));
+				t.assertEqual("A9B574", store.getValue(item, "isbn"));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetchItemByIdentity({identity: 3, onItem: onItem, onError: onError});
+			return d; //Object
+		},
+		function testIdentityAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.HtmlTableStore.getBooksStore();
+			var identityApi = new dojo.data.api.Identity();
+			var passed = true;
+
+			for(i in identityApi){
+				var member = identityApi[i];
+				//Check that all the 'Read' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						console.log("Problem with function: [" + i + "]");
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
+
+//Register the remote tests ... when they work.
+//doh.registerUrl("dojox.data.tests.stores.HtmlTableStore.remote", dojo.moduleUrl("dojox.data.tests", "ml/test_HtmlTableStore_declaratively.html"));
\ No newline at end of file
diff --git a/dojox/data/tests/stores/JsonQueryRestStore.js b/dojox/data/tests/stores/JsonQueryRestStore.js
new file mode 100644
index 0000000..11f0f99
--- /dev/null
+++ b/dojox/data/tests/stores/JsonQueryRestStore.js
@@ -0,0 +1,205 @@
+dojo.provide("dojox.data.tests.stores.JsonQueryRestStore");
+dojo.require("dojox.data.ClientFilter");
+dojo.require("dojox.data.JsonQueryRestStore");
+
+dojox.data.tests.stores.JsonQueryRestStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	d.errback(errData);	
+}
+testService = function(query){
+	lastQuery = query;
+	var deferred = new dojo.Deferred(); 
+	deferred.callback([
+		{id:1, name:"Ball", price: 5},
+		{id:2, name:"Car", price: 15},
+		{id:3, name:"Truck", price: 25},
+		{id:4, name:"Hula Hoop", price: 55}
+	]);
+	return deferred;
+	
+};
+testService.servicePath = "/testing";
+jsonStore = new dojox.data.JsonQueryRestStore({service:testService});
+
+doh.register("dojox.data.tests.stores.JsonQueryRestStore", 
+	[
+		{
+			name: "Fetch using a query object",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonQueryRestStore of a simple query.
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:{name:"Car"}, 
+					onComplete: function(items, request){
+						t.is(lastQuery,"[?(@.name='Car')]");
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonQueryRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Fetch+Sorting using a query object",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonQueryRestStore of a simple query.
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:{name:"Car"},
+					sort:[{attribute:"price"}], 
+					onComplete: function(items, request){
+						t.is(lastQuery,"[?(@.name='Car')][/@['price']]");
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonQueryRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Fetch all items (and cache for the next tests)",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonQueryRestStore of a simple query.
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"", 
+					onComplete: function(items, request){
+						testItems = items;
+						console.log(items.length, items);
+						t.is(4, items.length);
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonQueryRestStore.error, doh, d),
+					queryOptions:{cache:true}
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Fetch using a query object",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonQueryRestStore of a simple query.
+				var d = new doh.Deferred();
+				lastQuery = null;
+				jsonStore.fetch({query:{name:"Car"}, 
+					onComplete: function(items, request){
+						t.is(1, items.length);
+						t.is(lastQuery, null); // should not be sent to the service
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonQueryRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Fetch using a JSONQuery",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonQueryRestStore of a simple query.
+				var d = new doh.Deferred();
+				lastQuery = null;
+				jsonStore.fetch({query:"?name='Car'", 
+					onComplete: function(items, request){
+						t.is(1, items.length);
+						t.is(lastQuery, null); // should not be sent to the service
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonQueryRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Fetch using a JSONQuery with operator",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonQueryRestStore of a simple query.
+				var d = new doh.Deferred();
+				lastQuery = null;
+				jsonStore.fetch({query:"[?price<20]", 
+					onComplete: function(items, request){
+						t.is(2, items.length);
+						t.is(lastQuery, null); // should not be sent to the service
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonQueryRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Fetch using a JSONQuery with operator and paging",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonQueryRestStore of a simple query.
+				var d = new doh.Deferred();
+				lastQuery = null;
+				jsonStore.fetch({query:"?price<20",start:1, count:1, 
+					onComplete: function(items, request){
+						t.is(1, items.length);
+						t.is(lastQuery, null); // should not be sent to the service
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonQueryRestStore.error, doh, d),
+					queryOptions:{cache:true}
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Sorting",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonQueryRestStore of a simple query.
+				var d = new doh.Deferred();
+				lastQuery = null;
+				jsonStore.fetch({sort:[{attribute:"name", descending: true}], 
+					onComplete: function(items, request){
+						t.is("Truck", items[0].name);
+						t.is("Ball", items[3].name);
+						t.is(lastQuery, null); // should not be sent to the service
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonQueryRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Sorting + Paging",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonQueryRestStore of a simple query.
+				jsonStore.jsonQueryPagination = true;
+				var d = new doh.Deferred();
+				lastQuery = null;
+				jsonStore.fetch({sort:[{attribute:"name", descending: true}],start:1, count:2,
+					onBegin: function(count){
+						t.is(count,4);
+					},
+					onComplete: function(items, request){
+						t.is("Hula Hoop", items[0].name);
+						t.is("Car", items[1].name);
+						t.is(items.length, 2);
+						t.is(lastQuery, null); // should not be sent to the service
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonQueryRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		}
+	]
+);
diff --git a/dojox/data/tests/stores/JsonRestStore.js b/dojox/data/tests/stores/JsonRestStore.js
new file mode 100644
index 0000000..f6ead37
--- /dev/null
+++ b/dojox/data/tests/stores/JsonRestStore.js
@@ -0,0 +1,345 @@
+dojo.provide("dojox.data.tests.stores.JsonRestStore");
+dojo.require("dojox.rpc.Service");
+//dojo.require("dojox.data.ClientFilter");
+dojo.require("dojox.data.JsonRestStore");
+dojo.require("dojox.json.schema");
+dojo.require("dojo.data.api.Read");
+
+dojox.data.tests.stores.JsonRestStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	d.errback(errData);	
+}
+testServices = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.tests.resources", "test.smd"));
+testServices.jsonRestStore.servicePath = "/jsonRest.Store/"; // this makes the regex more challenging
+jsonStore = new dojox.data.JsonRestStore({service:testServices.jsonRestStore});
+
+doh.register("dojox.data.tests.stores.JsonRestStore", 
+	[
+		{
+			name: "Fetch some items",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonRestStore of a simple query.
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"query", 
+					onComplete: function(items, request){
+						t.is(4, items.length);
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "fetch by id",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonRestStore of a single item.
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"obj1", 
+					onComplete: function(item, request){
+						t.is("Object 1", item.name);
+						t.t(jsonStore.hasAttribute(item,"name"));
+						t.is(jsonStore.getValues(item,"name").length,1);
+						t.t(jsonStore.isItem(item));
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Modify,save, check by id",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Fetch an item from a query, modify and save it, and check to see if it was modified correctly
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"query", 
+					onComplete: function(items, request){
+						var now = new Date().getTime();
+						jsonStore.setValue(items[0],"updated",now);
+						jsonStore.setValue(items[0],"obj",{foo:'bar'});
+						jsonStore.setValue(items[0],"obj dup",items[0].obj);
+						jsonStore.setValue(items[0],"testArray",[1,2,3,4]);
+						jsonStore.save({onComplete:function(){
+							jsonStore.fetchItemByIdentity({identity:"obj1",
+								onItem: function(item, request){
+									t.is("Object 1", item.name);
+									t.is(now, item.updated);
+									t.is("bar", item.obj.foo);
+									t.is(item.obj, item['obj dup']);
+									d.callback(true);
+								},
+								onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)
+							});
+						}});
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Revert",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		append/post an item, delete it, sort the lists, resort the list, saving each time.
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"obj1", 
+					onComplete: function(item, request){
+						jsonStore.setValue(item,"name","new name");
+						jsonStore.setValue(item,"newProp","new value");
+						jsonStore.unsetAttribute(item,"updated");
+						t.is(jsonStore.getValue(item,"name"),"new name");
+						t.is(jsonStore.getValue(item,"newProp"),"new value");
+						t.is(jsonStore.getValue(item,"updated"),undefined);
+						jsonStore.revert();
+						t.is(jsonStore.getValue(item,"name"),"Object 1");
+						t.is(jsonStore.getValue(item,"newProp"),undefined);
+						t.t(typeof jsonStore.getValue(item,"updated") == 'number');
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Delete",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		append/post an item, delete it, sort the lists, resort the list, saving each time.
+				var d = new doh.Deferred();
+				jsonStore.fetchItemByIdentity({identity:"obj1", 
+					onItem: function(item, request){
+						var newItem = jsonStore.newItem({directRef: item, name:"Foo"});
+						jsonStore.setValue(newItem, "arrayRef", [1,{subobject:item},item]);
+						jsonStore.deleteItem(item);
+						t.is(jsonStore.getValue(newItem, "directRef"), undefined);
+						t.is(jsonStore.getValue(newItem, "arrayRef").length, 2);
+						t.is(jsonStore.getValue(newItem, "arrayRef")[1].subobject, undefined);
+						jsonStore.revert();
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Lazy loading",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		test lazy loading
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"query", 
+					onComplete: function(items, request){
+						var item = items[2];
+						t.f(jsonStore.isItemLoaded(item));
+						jsonStore.getValue(item,"name"); // this should trigger the load
+						t.is(items[2],item);
+						t.is(item.name,'Object 3');
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "Lazy loading 2",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		test lazy loading
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"query", 
+					onComplete: function(items, request){
+						t.f(jsonStore.isItemLoaded(items[3]));
+						jsonStore.loadItem({item:items[3],onItem:function(item){
+							t.t(jsonStore.isItemLoaded(items[3]));
+							t.is(item,items[3]);
+							t.is(item.name,'Object 4');
+							d.callback(true);
+						}});
+						
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		/*{
+			name: "Load Lazy Value",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on ServiceStore of a single item.
+				var d = new doh.Deferred();
+				jsonStore.fetchItemByIdentity({identity:"obj1", 
+					onItem: function(item, request){
+						t.is("Object 1", item.name);
+						t.f(jsonStore.isItemLoaded(item.lazyValue));
+						var lazyValue = jsonStore.getValue(item,"lazyValue");
+						t.is("Finally loaded",lazyValue);
+						lazyValue = jsonStore.getValue(item,"lazyValue");
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},*/
+		
+		{
+			name: "IdentityAPI: fetchItemByIdentity and getIdentity",
+			timeout: 30000,
+			runTest: function(t) {
+				//	summary:
+				//		Verify the fetchItemByIdentity method works
+				var d = new doh.Deferred();
+		
+				jsonStore.fetchItemByIdentity({identity:"obj3", 
+					onItem: function(item, request){
+						t.t(jsonStore.isItemLoaded(item));
+						t.is(jsonStore.getIdentity(item),"obj3");
+					}
+				});
+			}
+		},
+
+		
+		{
+			name: "ReadAPI:  Fetch_20_Streaming",
+			timeout:	10000, //10 seconds.  Json can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		fetching with paging
+
+				var d = new doh.Deferred();
+				var count = 0;
+
+				function onItem(item, requestObj){
+				  t.assertTrue(typeof item == 'number');
+				  count++;
+				}
+				function onComplete(items, request){
+					t.is(20, count);
+					
+					d.callback(true);
+				}
+				//Get everything...
+				jsonStore.fetch({	
+					query: "bigQuery",
+					onBegin: null,
+					count: 20,
+					onItem: onItem,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		function testSchema(t){
+			var d = new doh.Deferred();
+			jsonStore.fetchItemByIdentity({identity:"obj3", 
+				onItem: function(item, request){
+					var set = false;
+					try{
+						jsonStore.setValue(item,"name",333); // should only take a string, so it should throw an exception
+						set = true;
+					}catch(e){
+						console.log("Correctly blocked invalid property change by schema:",e);
+					}
+					try{
+						jsonStore.setValue(item,"name","a"); // should be at least three character, so it should throw an execption
+						set = true;
+					}catch(e){
+						console.log("Correctly blocked invalid property change by schema:",e);
+					}
+					t.f(set);
+					d.callback(true);
+				}
+			});
+			
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = jsonStore	[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+		},
+		function tryToLoadSameTarget(t){
+			t.is(
+				dojox.data.JsonRestStore.getStore({target:"/something/"},dojox.data.JsonRestStore),
+				dojox.data.JsonRestStore.getStore({target:"/something/"}));
+			
+		}
+	]
+);
+performanceTest = function (){
+	dojo.require("dojo.data.ItemFileReadStore");
+	jsonStore.fetch({query:"obj1", 
+		onComplete: function(item){
+			var now = new Date().getTime();
+			var result;
+			for(var i=0;i<100000;i++){
+			}
+			console.log("Just Loop",new Date().getTime()-now, result);
+			now = new Date().getTime();
+			for(i=0;i<100000;i++){
+				result = item.name;
+			}
+			console.log("Direct Access",new Date().getTime()-now, result);
+			
+			now = new Date().getTime();
+			for(i=0;i<100000;i++){
+				result = jsonStore.getValue(item,"name");
+			}
+			console.log("getValue",new Date().getTime()-now);
+			
+			var ifrs = new dojo.data.ItemFileReadStore({data:{ identifier:'id',items: [
+				{ id:'1',name:'Fozzie Bear', wears:['hat', 'tie']},
+				{ id:'2',name:'Miss Piggy', pets:'Foo-Foo'}
+			]}});
+			ifrs.fetchItemByIdentity({identity:'1',onItem:function(result){
+				item = result;
+			}});
+			
+			now = new Date().getTime();
+			for(i=0;i<100000;i++){
+				result = ifrs.getValue(item,"name");
+			}
+			console.log("ifrs.getValue",new Date().getTime()-now,result);
+			
+		}
+	});	
+
+}
diff --git a/dojox/data/tests/stores/KeyValueStore.js b/dojox/data/tests/stores/KeyValueStore.js
new file mode 100644
index 0000000..76740ed
--- /dev/null
+++ b/dojox/data/tests/stores/KeyValueStore.js
@@ -0,0 +1,998 @@
+dojo.provide("dojox.data.tests.stores.KeyValueStore");
+dojo.require("dojox.data.KeyValueStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+
+dojox.data.tests.stores.KeyValueStore.getDatasource = function(type){
+	//  summary:
+	//		A simple helper function for getting the sample data used in each of the tests.
+	//  description:
+	//		A simple helper function for getting the sample data used in each of the tests.
+
+	var dataSource = {};
+	var filepath = "stores/properties.js";
+	if(dojo.isBrowser){
+		dataSource.url = dojo.moduleUrl("dojox.data.tests", filepath).toString();            
+	}else{
+		// When running tests in Rhino, xhrGet is not available,
+		// so we have the file data in the code below.
+		var keyData = "/*[";
+		// Properties of December 1, 2007 
+		keyData += '{ "year": "2007" },';
+		keyData += '{ "nmonth": "12" },';
+		keyData += '{ "month": "December" },';
+		keyData += '{ "nday": "1" },';
+		keyData += '{ "day": "Saturday" },';
+		keyData += '{ "dayOfYear": "335" },';
+		keyData += '{ "weekOfYear": "48" }';
+		keyData += ']*/';
+		dataSource.data = keyData;
+	}
+	return dataSource; //Object
+}
+
+dojox.data.tests.stores.KeyValueStore.verifyItems = function(keyStore, items, attribute, compareArray){
+	//  summary:
+	//		A helper function for validating that the items array is ordered
+	//		the same as the compareArray
+	if(items.length != compareArray.length){ return false; }
+	for(var i = 0; i < items.length; i++){
+		if(!(keyStore.getValue(items[i], attribute) === compareArray[i])){
+			return false; //Boolean
+		}
+	}
+	return true; //Boolean
+}
+
+dojox.data.tests.stores.KeyValueStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	for (i in errData) {
+		console.log(errData[i]);
+	}
+	d.errback(errData);	
+}
+
+doh.register("dojox.data.tests.stores.KeyValueStore", 
+	[
+		function testReadAPI_fetch_all(t){
+			//	summary: 
+			//		Simple test of a basic fetch on KeyValueStore.
+			//	description:
+			//		Simple test of a basic fetch on KeyValueStore.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/properties.js");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue((items.length === 7));
+				d.callback(true);
+			}
+
+			//Get everything...
+			keyStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_withEmptyStringField(t){
+			//	summary: 
+			//		Simple test of a basic fetch on KeyValueStore.
+			//	description:
+			//		Simple test of a basic fetch on KeyValueStore.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource();
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.assertTrue((items.length === 7));
+				d.callback(true);
+			}
+
+			//Get everything...
+			keyStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one(t){
+			//	summary: 
+			//		Simple test of a basic fetch on KeyValueStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on KeyValueStore of a single item.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource();
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.is(1, items.length);
+				d.callback(true);
+			}
+			keyStore.fetch({ 	query: {key: "year"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)
+							});
+			return d; //Object
+		},
+		function testReadAPI_fetch_Multiple(t){
+			//	summary: 
+			//		Simple test of a basic fetch on KeyValueStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on KeyValueStore of a single item.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource();
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+
+			var done = [false, false];
+
+			function onCompleteOne(items, request){
+				done[0] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			
+			function onCompleteTwo(items, request){
+				done[1] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			
+			try
+			{
+				keyStore.fetch({ 	query: {key: "year"}, 
+									onComplete: onCompleteOne, 
+									onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)
+								});
+				keyStore.fetch({ 	query: {key: "month"}, 
+									onComplete: onCompleteTwo, 
+									onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)
+								});
+			}
+			catch(e)
+			{
+				for (i in e) {
+					console.log(e[i]);
+				}
+			}
+
+			return d; //Object
+		},
+		function testReadAPI_fetch_MultipleMixed(t){
+			//	summary: 
+			//		Simple test of a basic fetch on KeyValueStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on KeyValueStore of a single item.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource();
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+
+			var done = [false, false];
+			function onComplete(items, request){
+				done[0] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			
+			function onItem(item){
+				done[1] = true;
+				t.assertTrue(item !== null);
+				t.is('year', keyStore.getValue(item,"key"));
+				t.is(2007, keyStore.getValue(item,"value"));
+				t.is(2007, keyStore.getValue(item,"year"));
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+
+			keyStore.fetch({ 	query: {key: "day"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)
+							});
+			
+			keyStore.fetchItemByIdentity({identity: "year", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_streaming(t){
+			//	summary: 
+			//		Simple test of a basic fetch on KeyValueStore.
+			//	description:
+			//		Simple test of a basic fetch on KeyValueStore.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource();
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			count = 0;
+
+			function onBegin(size, requestObj){
+				t.assertTrue(size === 7);
+			}
+			function onItem(item, requestObj){
+				t.assertTrue(keyStore.isItem(item));
+				count++;
+			}
+			function onComplete(items, request){
+				t.is(7, count);
+				t.is(null, items);
+			    d.callback(true);
+			}
+
+			//Get everything...
+			keyStore.fetch({	onBegin: onBegin,
+								onItem: onItem, 
+								onComplete: onComplete,
+								onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)
+							});
+			return d; //Object
+		},
+		function testReadAPI_fetch_paging(t){
+			 //	summary: 
+			 //		Test of multiple fetches on a single result.  Paging, if you will.
+			 //	description:
+			 //		Test of multiple fetches on a single result.  Paging, if you will.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource();
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function dumpFirstFetch(items, request){
+				t.is(5, items.length);
+				request.start = 3;
+				request.count = 1;
+				request.onComplete = dumpSecondFetch;
+				keyStore.fetch(request);
+			}
+
+			function dumpSecondFetch(items, request){
+				t.is(1, items.length);
+				request.start = 0;
+				request.count = 5;
+				request.onComplete = dumpThirdFetch;
+				keyStore.fetch(request);
+			}
+
+			function dumpThirdFetch(items, request){
+				t.is(5, items.length);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpFourthFetch;
+				keyStore.fetch(request);
+			}
+
+			function dumpFourthFetch(items, request){
+				t.is(5, items.length);
+				request.start = 9;
+				request.count = 100;
+				request.onComplete = dumpFifthFetch;
+				keyStore.fetch(request);
+			}
+
+			function dumpFifthFetch(items, request){
+				t.is(0, items.length);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpSixthFetch;
+				keyStore.fetch(request);
+			}
+
+			function dumpSixthFetch(items, request){
+				t.is(5, items.length);
+			    d.callback(true);
+			}
+
+			function completed(items, request){
+				t.is(7, items.length);
+				request.start = 1;
+				request.count = 5;
+				request.onComplete = dumpFirstFetch;
+				keyStore.fetch(request);
+			}
+
+			keyStore.fetch({onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		
+		function testReadAPI_getLabel(t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource();
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = keyStore.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				t.assertEqual("year", label);
+				d.callback(true);
+			}
+			keyStore.fetch({ 	query: {key: "year"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)
+							});
+			return d;
+		},
+		function testReadAPI_getLabelAttributes(t){
+			//	summary: 
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+			 var args = dojox.data.tests.stores.KeyValueStore.getDatasource();
+			 var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var labelList = keyStore.getLabelAttributes(items[0]);
+				t.assertTrue(dojo.isArray(labelList));
+				t.assertEqual("key", labelList[0]);
+				d.callback(true);
+			}
+			keyStore.fetch({ 	query: {key: "year"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)
+							});
+			return d;
+		},
+		function testReadAPI_getValue(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.is("nday", keyStore.getValue(item,"key"));
+				t.is(1, keyStore.getValue(item,"value"));
+				t.is(1, keyStore.getValue(item,"nday"));
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "nday", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d;
+		},	
+		function testReadAPI_getValue_2(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.is("day", keyStore.getValue(item,"key"));
+				t.is("Saturday", keyStore.getValue(item,"value"));
+				t.is("Saturday", keyStore.getValue(item,"day"));
+				d.callback(true);	
+			}
+            keyStore.fetchItemByIdentity({identity: "day", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d;
+		},	
+		function testReadAPI_getValue_3(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.is("dayOfYear", keyStore.getValue(item,"key"));
+				t.is(335, keyStore.getValue(item,"value"));
+				t.is(335, keyStore.getValue(item,"dayOfYear"));
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "dayOfYear", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d;
+		},	
+		function testReadAPI_getValue_4(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.is("weekOfYear", keyStore.getValue(item,"key"));
+				t.is(48, keyStore.getValue(item,"value"));
+				t.is(48, keyStore.getValue(item,"weekOfYear"));
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "weekOfYear", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d;
+		},
+		function testReadAPI_getValues(t){
+			//	summary: 
+			//		Simple test of the getValues function of the store.
+			//	description:
+			//		Simple test of the getValues function of the store.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				var names = keyStore.getValues(item,"year");
+				t.assertTrue(dojo.isArray(names));
+				t.is(1, names.length);
+				t.is(2007, names[0]);
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "year", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d;
+		},
+		function testIdentityAPI_fetchItemByIdentity(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "year", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d;
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_bad1(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "y3ar", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d;
+		},
+		function testIdentityAPI_fetchItemByIdentity_bad2(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "-1", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d;
+		},
+		function testIdentityAPI_fetchItemByIdentity_bad3(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "999999", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d;
+		},
+		function testIdentityAPI_getIdentity(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(7, items.length);
+				t.is(keyStore.getIdentity(items[0]), 'year');
+				t.is(keyStore.getIdentity(items[1]), 'nmonth');
+				t.is(keyStore.getIdentity(items[2]), 'month');
+				t.is(keyStore.getIdentity(items[3]), 'nday');
+				t.is(keyStore.getIdentity(items[4]), 'day');
+				t.is(keyStore.getIdentity(items[5]), 'dayOfYear');
+				t.is(keyStore.getIdentity(items[6]), 'weekOfYear');
+				d.callback(true);
+			}
+			
+			//Get everything...
+			keyStore.fetch({ onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testIdentityAPI_getIdentityAttributes(t){
+			//	summary: 
+			//		Simple test of the getIdentityAttributes
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(keyStore.isItem(item));
+				t.assertEqual("key", keyStore.getIdentityAttributes(item)); 
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "year", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+		   	return d;
+		},
+		function testReadAPI_isItem(t){
+			//	summary: 
+			//		Simple test of the isItem function of the store
+			//	description:
+			//		Simple test of the isItem function of the store
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(keyStore.isItem(item));
+				t.assertTrue(!keyStore.isItem({}));
+				t.assertTrue(!keyStore.isItem({ item: "not an item" }));
+				t.assertTrue(!keyStore.isItem("not an item"));
+				t.assertTrue(!keyStore.isItem(["not an item"]));
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "year", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+		   	return d;
+		},
+		function testReadAPI_hasAttribute(t){
+			//	summary: 
+			//		Simple test of the hasAttribute function of the store
+			//	description:
+			//		Simple test of the hasAttribute function of the store
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(keyStore.hasAttribute(item, "key"));
+				t.assertTrue(keyStore.hasAttribute(item, "value"));
+				t.assertTrue(keyStore.hasAttribute(item, "year"));
+				t.assertTrue(!keyStore.hasAttribute(item, "Year"));
+				t.assertTrue(!keyStore.hasAttribute(item, "Nothing"));
+				t.assertTrue(!keyStore.hasAttribute(item, "Title"));
+
+				//Test that null attributes throw an exception
+				var passed = false;
+				try{
+					keyStore.hasAttribute(item, null);
+				}catch (e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "year", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+		   	return d;
+		},
+		function testReadAPI_containsValue(t){
+			//	summary:  
+			//		Simple test of the containsValue function of the store
+			//	description:
+			//		Simple test of the containsValue function of the store
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+ 			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(keyStore.containsValue(item, "year", "2007"));
+				t.assertTrue(keyStore.containsValue(item, "value", "2007"));
+				t.assertTrue(keyStore.containsValue(item, "key", "year"));
+				t.assertTrue(!keyStore.containsValue(item, "Title", "Alien2"));
+				t.assertTrue(!keyStore.containsValue(item, "Year", "1979   "));
+				t.assertTrue(!keyStore.containsValue(item, "Title", null));
+
+				//Test that null attributes throw an exception
+				var passed = false;
+				try{
+					keyStore.containsValue(item, null, "foo");
+				}catch (e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "year", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+		   	return d;
+		},
+		function testReadAPI_getAttributes(t){
+			//	summary: 
+			//		Simple test of the getAttributes function of the store
+			//	description:
+			//		Simple test of the getAttributes function of the store
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				t.assertTrue(keyStore.isItem(item));
+
+				var attributes = keyStore.getAttributes(item);
+				t.is(3, attributes.length);
+				for(var i = 0; i < attributes.length; i++){
+					t.assertTrue((attributes[i] === "year" || attributes[i] === "value" || attributes[i] === "key"));
+				}
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "year", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+		   	return d;
+		},
+
+		function testReadAPI_getAttributes_onlyTwo(t){
+			//	summary: 
+			//		Simple test of the getAttributes function of the store
+			//	description:
+			//		Simple test of the getAttributes function of the store
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			function onItem(item){
+				// Test an item that does not have all of the attributes
+				t.assertTrue(item !== null);
+				t.assertTrue(keyStore.isItem(item));
+
+				var attributes = keyStore.getAttributes(item);
+				t.assertTrue(attributes.length === 3);
+				t.assertTrue(attributes[0] === "key");
+				t.assertTrue(attributes[1] === "value");
+				t.assertTrue(attributes[2] === "nmonth");
+				d.callback(true);	
+			}
+			keyStore.fetchItemByIdentity({identity: "nmonth", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+		   	return d;
+		},
+
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var features = keyStore.getFeatures(); 
+			var count = 0;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read" || i === "dojo.data.api.Identity"));
+				count++;
+			}
+			t.assertTrue(count === 2);
+		},
+		function testReadAPI_fetch_patternMatch0(t){
+			//	summary: 
+			//		Function to test pattern matching of everything starting with lowercase e
+			//	description:
+			//		Function to test pattern matching of everything starting with lowercase e
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(2, items.length);
+				var valueArray = [ "nmonth", "month"];
+				t.assertTrue(dojox.data.tests.stores.KeyValueStore.verifyItems(keyStore, items, "key", valueArray));
+				d.callback(true);
+			}
+			
+			keyStore.fetch({query: {key: "*month"}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch1(t){
+			//	summary: 
+			//		Function to test pattern matching of everything with $ in it.
+			//	description:
+			//		Function to test pattern matching of everything with $ in it.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/patterns.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.assertTrue(items.length === 2);
+				var valueArray = [ "1", "Saturday"];
+				t.assertTrue(dojox.data.tests.stores.KeyValueStore.verifyItems(keyStore, items, "value", valueArray));
+				d.callback(true);
+			}
+			
+			keyStore.fetch({query: {key: "*day"}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch2(t){
+			//	summary: 
+			//		Function to test exact pattern match
+			//	description:
+			//		Function to test exact pattern match
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/patterns.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(2, items.length);
+				t.assertTrue(keyStore.getValue(items[0], "value") === "12");
+				t.assertTrue(keyStore.getValue(items[0], "key") === "nmonth");
+				t.assertTrue(keyStore.getValue(items[1], "value") === "1");
+				t.assertTrue(keyStore.getValue(items[1], "key") === "nday");
+				d.callback(true);
+			}
+			
+			keyStore.fetch({query: {value: "1*"}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch_caseInsensitive(t){
+			//	summary: 
+			//		Function to test exact pattern match with case insensitivity set.
+			//	description:
+			//		Function to test exact pattern match with case insensitivity set.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/patterns.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(1, items.length);
+				t.assertTrue(keyStore.getValue(items[0], "value") === "December");
+				d.callback(true);
+			}
+			
+			keyStore.fetch({query: {key: "MONth"}, queryOptions: {ignoreCase: true}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch_caseSensitive(t){
+			//	summary: 
+			//		Function to test exact pattern match with case insensitivity set.
+			//	description:
+			//		Function to test exact pattern match with case insensitivity set.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/patterns.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(0, items.length);
+				d.callback(true);
+			}
+			
+			keyStore.fetch({query: {value: "DECEMberO"}, queryOptions: {ignoreCase: false}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortAlphabetic(t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering.
+			//	description:
+			//		Function to test sorting alphabetic ordering.
+		
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/patterns.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ "day", "dayOfYear", "month", "nday", "nmonth", "weekOfYear", "year" ];
+				t.is(7, items.length);
+				t.assertTrue(dojox.data.tests.stores.KeyValueStore.verifyItems(keyStore, items, "key", orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: "key"}];
+			keyStore.fetch({sort: sortAttributes, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortAlphabeticDescending(t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering in descending mode.
+			//	description:
+			//		Function to test sorting alphabetic ordering in descending mode.
+		
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/patterns.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ "year", "weekOfYear", "nmonth", "nday", "month", "dayOfYear", "day" ];
+				t.is(7, items.length);
+				t.assertTrue(dojox.data.tests.stores.KeyValueStore.verifyItems(keyStore, items, "key", orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: "key", descending: true}];
+			keyStore.fetch({sort: sortAttributes, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortMultiple(t){
+			//	summary: 
+			//		Function to test sorting on multiple attributes.
+			//	description:
+			//		Function to test sorting on multiple attributes.
+			
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/patterns.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+		
+			var d = new doh.Deferred();
+			function completed(items, request){
+				var orderedArray1 = [	"123abc",
+										"123abc",
+										"123abc",
+										"123abcdefg",
+										"BaBaMaSaRa***Foo",
+										"bar*foo",
+										"bit$Bite",
+										"foo*bar",
+										"jfq4@#!$!@Rf14r14i5u",
+										undefined
+									];
+				var orderedArray0 = [ "day", "dayOfYear", "month", "nday", "nmonth", "weekOfYear", "year" ];
+				var orderedArray1 = [ "Saturday", "335", "December", "1", "12", "48", "2007" ];
+				t.is(7, items.length);
+				t.assertTrue(dojox.data.tests.stores.KeyValueStore.verifyItems(keyStore, items, "key", orderedArray0));
+				t.assertTrue(dojox.data.tests.stores.KeyValueStore.verifyItems(keyStore, items, "value", orderedArray1));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{ attribute: "key"}, { attribute: "value", descending: true}];
+			keyStore.fetch({sort: sortAttributes, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortMultipleSpecialComparator(t){
+			//	summary: 
+			//		Function to test sorting on multiple attributes with a custom comparator.
+			//	description:
+			//		Function to test sorting on multiple attributes with a custom comparator.
+
+			var args = dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv");
+			var keyStore = new dojox.data.KeyValueStore(args);
+			
+			keyStore.comparatorMap = {};
+			keyStore.comparatorMap["key"] = function(a,b){ 
+				var ret = 0;
+				// We want to sort keys alphabetical by the last character in the string
+				function lastChar(name){
+					if(typeof name === "undefined"){ return undefined; }
+					
+					return name.slice(name.length-1); // Grab the last character in the string.
+				}
+				var lastCharA = lastChar(a);
+				var lastCharB = lastChar(b);
+				if(lastCharA > lastCharB || typeof lastCharA === "undefined"){
+					ret = 1;
+				}else if(lastCharA < lastCharB || typeof lastCharB === "undefined"){
+					ret = -1;
+				}
+				return ret;
+			};
+		
+			var sortAttributes = [{attribute: "key", descending: true}, { attribute: "value", descending: true}];
+		
+			var d = new doh.Deferred();
+			function completed(items, findResult){
+				var orderedArray = [5,4,0,3,2,1,6];
+				var orderedArray = [ "day", "nday", "weekOfYear", "dayOfYear", "year", "month", "nmonth" ];
+				t.assertTrue(items.length === 7);
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					if(!(keyStore.getIdentity(items[i]) === orderedArray[i])){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				d.callback(true);
+			}
+			
+			keyStore.fetch({sort: sortAttributes, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.KeyValueStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = new dojox.data.KeyValueStore(dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv"));
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						console.log("Looking at function: [" + i + "]");
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							console.log("Problem with function: [" + i + "].   Got value: " + testStoreMember);
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		},
+		function testIdentityAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = new dojox.data.KeyValueStore(dojox.data.tests.stores.KeyValueStore.getDatasource("stores/movies.csv"));
+			var identityApi = new dojo.data.api.Identity();
+			var passed = true;
+
+			for(i in identityApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = identityApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						console.log("Looking at function: [" + i + "]");
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
+
diff --git a/dojox/data/tests/stores/OpenSearchStore.js b/dojox/data/tests/stores/OpenSearchStore.js
new file mode 100644
index 0000000..7282c97
--- /dev/null
+++ b/dojox/data/tests/stores/OpenSearchStore.js
@@ -0,0 +1,1306 @@
+dojo.provide("dojox.data.tests.stores.OpenSearchStore");
+dojo.require("dojox.data.OpenSearchStore");
+dojo.require("dojo.data.api.Read");
+
+
+dojox.data.tests.stores.OpenSearchStore.getAtomStore = function(){
+	var store = new dojox.data.OpenSearchStore({url: dojo.moduleUrl('dojox.data.tests.stores', 'opensearch_atom.xml').toString()});
+	store._createSearchUrl = function(request){
+		return dojo.moduleUrl('dojox.data.tests.stores', 'atom1.xml').toString();
+	};
+	return store;
+};
+dojox.data.tests.stores.OpenSearchStore.getRSSStore = function(){
+	var store = new dojox.data.OpenSearchStore({url: dojo.moduleUrl('dojox.data.tests.stores', 'opensearch_rss.xml').toString()});
+	store._createSearchUrl = function(request){
+		return dojo.moduleUrl('dojox.data.tests.stores', 'rss1.xml').toString();
+	};
+	return store;
+};
+dojox.data.tests.stores.OpenSearchStore.getHTMLStore = function(){
+	var store = new dojox.data.OpenSearchStore({url: dojo.moduleUrl('dojox.data.tests.stores', 'opensearch_html.xml').toString(), itemPath: "table tbody tr"});
+	store._createSearchUrl = function(request){
+		return dojo.moduleUrl('dojox.data.tests.stores', 'books.html').toString();
+	};
+	return store;
+};
+
+doh.register("dojox.data.tests.stores.OpenSearchStore", 
+	[
+		{
+			name: 'testReadAPI_fetch_all_atom',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of fetching all atom entries
+				//	description:
+				//		Simple test of fetching all atom entries
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_fetch_all_rss',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of fetching all atom entries
+				//	description:
+				//		Simple test of fetching all atom entries
+				var store = dojox.data.tests.stores.OpenSearchStore.getRSSStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_fetch_all_html',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of fetching all atom entries
+				//	description:
+				//		Simple test of fetching all atom entries
+				var store = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_fetch_paging_atom',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of fetching one xml items through an XML element called isbn
+				//	description:
+				//		Simple test of fetching one xml items through an XML element called isbn
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+
+				var d = new doh.Deferred();
+
+                function dumpFifthFetch(items, request){
+					t.assertEqual(0, items.length);
+					d.callback(true);
+				}
+				
+				function dumpFourthFetch(items, request){
+					t.assertEqual(18, items.length);
+					request.start = 20;
+					request.count = 100;
+					request.onComplete = dumpFifthFetch;
+					store.fetch(request);
+				}
+				
+				function dumpThirdFetch(items, request){
+					t.assertEqual(5, items.length);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpFourthFetch;
+					store.fetch(request);
+				}
+
+				function dumpSecondFetch(items, request){
+					t.assertEqual(1, items.length);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					store.fetch(request);
+				}
+				
+				function dumpFirstFetch(items, request){
+					t.assertEqual(5, items.length);
+					request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					store.fetch(request);
+				}
+
+				function completed(items, request){
+					t.assertEqual(20, items.length);
+					request.start = 1;
+					request.count = 5;
+					request.onComplete = dumpFirstFetch;
+					store.fetch(request);
+				}
+
+				function error(errData, request){
+					d.errback(errData);
+				}
+
+				store.fetch({onComplete: completed, onError: error});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_fetch_paging_rss',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of fetching one xml items through an XML element called isbn
+				//	description:
+				//		Simple test of fetching one xml items through an XML element called isbn
+				var store = dojox.data.tests.stores.OpenSearchStore.getRSSStore();
+
+				var d = new doh.Deferred();
+
+				function dumpFifthFetch(items, request){
+					t.assertEqual(0, items.length);
+					d.callback(true);
+				}
+
+				function dumpFourthFetch(items, request){
+					t.assertEqual(18, items.length);
+					request.start = 20;
+					request.count = 100;
+					request.onComplete = dumpFifthFetch;
+					store.fetch(request);
+				}
+				
+				function dumpThirdFetch(items, request){
+					t.assertEqual(5, items.length);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpFourthFetch;
+					store.fetch(request);
+				}
+				
+				function dumpSecondFetch(items, request){
+					t.assertEqual(1, items.length);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					store.fetch(request);
+				}
+				
+				function dumpFirstFetch(items, request){
+					t.assertEqual(5, items.length);
+					request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					store.fetch(request);
+				}
+				
+				function completed(items, request){
+					t.assertEqual(20, items.length);
+					request.start = 1;
+					request.count = 5;
+					request.onComplete = dumpFirstFetch;
+					store.fetch(request);
+				}
+
+				function error(errData, request){
+					d.errback(errData);
+				}
+
+				store.fetch({onComplete: completed, onError: error});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_fetch_paging_html',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of fetching one xml items through an XML element called isbn
+				//	description:
+				//		Simple test of fetching one xml items through an XML element called isbn
+				var store = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+
+				var d = new doh.Deferred();
+
+				function dumpFifthFetch(items, request){
+					t.assertEqual(10, items.length);
+					d.callback(true);
+				}
+				
+				function dumpFourthFetch(items, request){
+					t.assertEqual(18, items.length);
+					request.start = 10;
+					request.count = 100;
+					request.onComplete = dumpFifthFetch;
+					store.fetch(request);
+				}
+
+				function dumpThirdFetch(items, request){
+					t.assertEqual(5, items.length);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpFourthFetch;
+					store.fetch(request);
+				}
+				
+				function dumpSecondFetch(items, request){
+					t.assertEqual(1, items.length);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					store.fetch(request);
+				}
+
+				function dumpFirstFetch(items, request){
+					t.assertEqual(5, items.length);
+					request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					store.fetch(request);
+				}
+				
+				function completed(items, request){
+					t.assertEqual(20, items.length);
+					request.start = 1;
+					request.count = 5;
+					request.onComplete = dumpFirstFetch;
+					store.fetch(request);
+				}
+
+				function error(errData, request){
+					d.errback(errData);
+				}
+
+				store.fetch({onComplete: completed, onError: error});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_getLabel',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//		This test will be the same for all three types, so not bothering.
+	
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 20);
+					var label = store.getLabel(items[0]);
+					t.assertTrue(label === undefined);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d;
+			}
+		},
+		{
+			name: 'testReadAPI_getLabelAttributes',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//		This test will be the same for all three types, so not bothering.
+	
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 20);
+					var labelList = store.getLabelAttributes(items[0]);
+					t.assertTrue(!dojo.isArray(labelList));
+					t.assertTrue(labelList === null);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d;
+			}
+		},
+		{
+			name: 'testReadAPI_getValue_atom',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getValue API
+				//	description:
+				//		Simple test of the getValue API
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertEqual(item.node.nodeName, 'entry');
+					var id = item.node.getElementsByTagName('id');
+					t.assertEqual(id.length, 1);
+					t.assertEqual(dojox.xml.parser.textContent(id[0]), 'http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/');
+					t.assertTrue(store.hasAttribute(item, 'content'));
+					t.assertEqual(store.getValue(item, 'content').length, 6624);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_getValue_rss',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getValue API
+				//	description:
+				//		Simple test of the getValue API
+				var store = dojox.data.tests.stores.OpenSearchStore.getRSSStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertEqual(item.node.nodeName, 'item');
+					var link = item.node.getElementsByTagName('link');
+					t.assertEqual(link.length, 3);
+					t.assertEqual(dojox.xml.parser.textContent(link[0]), 'http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/');
+					t.assertTrue(store.hasAttribute(item, 'content'));
+					t.assertEqual(store.getValue(item, 'content').length, 315);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_getValue_html',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getValue API
+				//	description:
+				//		Simple test of the getValue API
+				var store = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertEqual(item.node.nodeName, 'TR');
+					var td = item.node.getElementsByTagName('td');
+					t.assertEqual(td.length, 3);
+					t.assertEqual(dojox.xml.parser.textContent(td[0]), '1');
+					t.assertEqual(dojox.xml.parser.textContent(td[1]), 'Title of 1');
+					t.assertEqual(dojox.xml.parser.textContent(td[2]), 'Author of 1');
+					t.assertTrue(store.hasAttribute(item, 'content'));
+					t.assertEqual(store.getValue(item, 'content').length, dojo.isIE?53:64);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_getValues_atom',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getValues API
+				//	description:
+				//		Simple test of the getValues API
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertEqual(item.node.nodeName, 'entry');
+					t.assertTrue(store.hasAttribute(item, 'content'));
+					var values = store.getValues(item,'content');
+					t.assertEqual(1,values.length);
+					t.assertEqual(store.getValue(item, 'content').length, 6624);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_getValues_rss',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getValues API
+				//	description:
+				//		Simple test of the getValues API
+				var store = dojox.data.tests.stores.OpenSearchStore.getRSSStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertEqual(item.node.nodeName, 'item');
+					t.assertTrue(store.hasAttribute(item, 'content'));
+					var values = store.getValues(item,'content');
+					t.assertEqual(1,values.length);
+					t.assertEqual(store.getValue(item, 'content').length, 315);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_getValues_html',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getValues API
+				//	description:
+				//		Simple test of the getValues API
+				var store = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertEqual(item.node.nodeName, 'TR');
+					t.assertTrue(store.hasAttribute(item, 'content'));
+					var values = store.getValues(item,'content');
+					t.assertEqual(1,values.length);
+					t.assertEqual(store.getValue(item, 'content').length, dojo.isIE?53:64);
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_isItem_atom',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the isItem API
+				//	description:
+				//		Simple test of the isItem API
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertTrue(store.isItem(item));
+					t.assertTrue(!store.isItem({}));
+					t.assertTrue(!store.isItem("Foo"));
+					t.assertTrue(!store.isItem(1));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_isItem_rss',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the isItem API
+				//	description:
+				//		Simple test of the isItem API
+				var store = dojox.data.tests.stores.OpenSearchStore.getRSSStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertTrue(store.isItem(item));
+					t.assertTrue(!store.isItem({}));
+					t.assertTrue(!store.isItem("Foo"));
+					t.assertTrue(!store.isItem(1));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_isItem_html',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the isItem API
+				//	description:
+				//		Simple test of the isItem API
+				var store = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertTrue(store.isItem(item));
+					t.assertTrue(!store.isItem({}));
+					t.assertTrue(!store.isItem("Foo"));
+					t.assertTrue(!store.isItem(1));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_isItem_multistore',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the isItem API across multiple store instances.
+				//	description:
+				//		Simple test of the isItem API across multiple store instances.
+				var store1 = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+				var store2 = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+	
+				var d = new doh.Deferred();
+				function onError(error, request) {
+					d.errback(error);
+				}
+				function onComplete1(items, request) {
+					t.assertEqual(20, items.length);
+					var item1 = items[0];
+					t.assertTrue(store1.isItem(item1));
+	
+					function onComplete2(items, request) {
+						t.assertEqual(20, items.length);
+						var item2 = items[0];
+						t.assertTrue(store2.isItem(item2));
+						t.assertTrue(!store1.isItem(item2));
+						t.assertTrue(!store2.isItem(item1));
+						d.callback(true);
+					}
+					store2.fetch({onComplete: onComplete2, onError: onError});
+				}
+				store1.fetch({onComplete: onComplete1, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_hasAttribute_atom',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the hasAttribute API
+				//	description:
+				//		Simple test of the hasAttribute API
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertTrue(store.hasAttribute(item,"content"));
+					t.assertTrue(!store.hasAttribute(item,"summary"));
+					t.assertTrue(!store.hasAttribute(item,"bob"));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_hasAttribute_rss',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the hasAttribute API
+				//	description:
+				//		Simple test of the hasAttribute API
+				var store = dojox.data.tests.stores.OpenSearchStore.getRSSStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertTrue(store.hasAttribute(item,"content"));
+					t.assertTrue(!store.hasAttribute(item,"summary"));
+					t.assertTrue(!store.hasAttribute(item,"bob"));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_hasAttribute_html',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the hasAttribute API
+				//	description:
+				//		Simple test of the hasAttribute API
+				var store = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertTrue(store.hasAttribute(item,"content"));
+					t.assertTrue(!store.hasAttribute(item,"summary"));
+					t.assertTrue(!store.hasAttribute(item,"bob"));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_containsValue_atom',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the containsValue API
+				//	description:
+				//		Simple test of the containsValue API
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[19];
+					t.assertTrue(store.containsValue(item,"content", '<div class=\'snap_preview\'><br /><p><a href="http://billhiggins.us/weblog/about/" target="_blank">Bill Higgins</a> of IBM has written a very well thought out article of why web applications should look and act like web applications, and not the desktop variety.  Well worth a read - <a href="http://billhiggins.us/weblog/2007/05/17/the-uncanny-valley-of-user-interface-design" target="_blank">http://billhiggins.us/weblog/2007/05/17/the [...]
+					t.assertTrue(!store.containsValue(item,"content", "bob"));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_containsValue_rss',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the containsValue API
+				//	description:
+				//		Simple test of the containsValue API
+				var store = dojox.data.tests.stores.OpenSearchStore.getRSSStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[19];
+					t.assertTrue(store.containsValue(item,"content", 'Bill Higgins of IBM has written a very well thought out article of why web applications should look and act like web applications, and not the desktop variety.  Well worth a read - http://billhiggins.us/weblog/2007/05/17/the-uncanny-valley-of-user-interface-design\n        (...)'));
+					t.assertTrue(!store.containsValue(item,"content", "bob"));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_containsValue_html',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the containsValue API
+				//	description:
+				//		Simple test of the containsValue API
+				var store = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[19];
+					var val = store.getValue(item, 'content').replace(/20/g, '19');
+					item = items[18];
+					// IE Strips the tabs out, so it has a different value.
+					t.assertTrue(store.containsValue(item,"content", val));
+					t.assertTrue(!store.containsValue(item,"content", "bob"));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_sortDescending_atom',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the sorting API in descending order.
+				//	description:
+				//		Simple test of the sorting API in descending order.
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+	
+				//Comparison is done as a string type (toString comparison), so the order won't be numeric
+				//So have to compare in 'alphabetic' order.
+				var order = [	'http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/',
+							 	'http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/',
+							 	'http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/',
+							 	'http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/',
+							 	'http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/',
+							 	'http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/',
+							 	'http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/',
+							 	'http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/',
+							 	'http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/',
+							 	'http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/',
+							 	'http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/',
+							 	'http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/',
+							 	'http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/',
+							 	'http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/',
+							 	'http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/',
+							 	'http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/',
+							 	'http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/',
+							 	'http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/',
+							 	'http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/',
+							 	'http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/'];
+				
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+	
+					for(var i = 0; i < items.length; i++){
+						var id = items[i].node.getElementsByTagName('id');
+						t.assertEqual(id.length, 1);
+						//console.debug(dojox.xml.parser.textContent(id[0]));
+						t.assertEqual(order[i], dojox.xml.parser.textContent(id[0]));
+					}
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+	
+				var sortAttributes = [{attribute: 'content', descending: true}];
+				store.fetch({sort: sortAttributes, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_sortDescending_rss',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the sorting API in descending order.
+				//	description:
+				//		Simple test of the sorting API in descending order.
+				var store = dojox.data.tests.stores.OpenSearchStore.getRSSStore();
+	
+				//Comparison is done as a string type (toString comparison), so the order won't be numeric
+				//So have to compare in 'alphabetic' order.
+				var order = [	'http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/',
+							 	'http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/',
+							 	'http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/',
+							 	'http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/',
+							 	'http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/',
+							 	'http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/',
+							 	'http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/',
+							 	'http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/',
+							 	'http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/',
+							 	'http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/',
+							 	'http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/',
+							 	'http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/',
+							 	'http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/',
+							 	'http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/',
+							 	'http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/',
+							 	'http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/',
+							 	'http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/',
+							 	'http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/',
+							 	'http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/',
+							 	'http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/'];
+				
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+	
+					for(var i = 0; i < items.length; i++){
+						var link = items[i].node.getElementsByTagName('link');
+						t.assertEqual(link.length, 3);
+						//console.debug(dojox.xml.parser.textContent(link[0]));
+						t.assertEqual(order[i], dojox.xml.parser.textContent(link[0]));
+					}
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+	
+				var sortAttributes = [{attribute: 'content', descending: true}];
+				store.fetch({sort: sortAttributes, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_sortDescending_html',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the sorting API in descending order.
+				//	description:
+				//		Simple test of the sorting API in descending order.
+				var store = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+	
+				//Comparison is done as a string type (toString comparison), so the order won't be numeric
+				//So have to compare in 'alphabetic' order.
+				var order = [	'Author of 9',
+							 	'Author of 8',
+							 	'Author of 7',
+							 	'Author of 6',
+							 	'Author of 5',
+							 	'Author of 4',
+							 	'Author of 3',
+							 	'Author of 2',
+							 	'Author of 20',
+							 	'Author of 1',
+							 	'Author of 19',
+							 	'Author of 18',
+							 	'Author of 17',
+							 	'Author of 16',
+							 	'Author of 15',
+							 	'Author of 14',
+							 	'Author of 13',
+							 	'Author of 12',
+							 	'Author of 11',
+							 	'Author of 10'];
+				
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+	
+					for(var i = 0; i < items.length; i++){
+						var td = items[i].node.getElementsByTagName('TD');
+						t.assertEqual(td.length, 3);
+						t.assertEqual(order[i], dojox.xml.parser.textContent(td[2]));
+					}
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+	
+				var sortAttributes = [{attribute: 'content', descending: true}];
+				store.fetch({sort: sortAttributes, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_sortAscending_atom',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the sorting API in descending order.
+				//	description:
+				//		Simple test of the sorting API in descending order.
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+	
+				//Comparison is done as a string type (toString comparison), so the order won't be numeric
+				//So have to compare in 'alphabetic' order.
+				var order = [	'http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/',
+								'http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/',
+								'http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/',
+								'http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/',
+								'http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/',
+								'http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/',
+								'http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/',
+								'http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/',
+								'http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/',
+								'http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/',
+								'http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/',
+								'http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/',
+								'http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/',
+								'http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/',
+								'http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/',
+								'http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/',
+								'http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/',
+								'http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/',
+								'http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/',
+								'http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/'];
+				
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+	
+					for(var i = 0; i < items.length; i++){
+						var id = items[i].node.getElementsByTagName('id');
+						t.assertEqual(id.length, 1);
+						t.assertEqual(order[i], dojox.xml.parser.textContent(id[0]));
+					}
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+	
+				var sortAttributes = [{attribute: 'content'}];
+				store.fetch({sort: sortAttributes, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_sortAscending_rss',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the sorting API in descending order.
+				//	description:
+				//		Simple test of the sorting API in descending order.
+				var store = dojox.data.tests.stores.OpenSearchStore.getRSSStore();
+	
+				//Comparison is done as a string type (toString comparison), so the order won't be numeric
+				//So have to compare in 'alphabetic' order.
+				var order = [	'http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/',
+								'http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/',
+								'http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/',
+								'http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/',
+								'http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/',
+								'http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/',
+								'http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/',
+								'http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/',
+								'http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/',
+								'http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/',
+								'http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/',
+								'http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/',
+								'http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/',
+								'http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/',
+								'http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/',
+								'http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/',
+								'http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/',
+								'http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/',
+								'http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/',
+								'http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/'];
+				
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+	
+					for(var i = 0; i < items.length; i++){
+						var link = items[i].node.getElementsByTagName('link');
+						t.assertEqual(link.length, 3);
+						t.assertEqual(order[i], dojox.xml.parser.textContent(link[0]));
+					}
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+	
+				var sortAttributes = [{attribute: 'content'}];
+				store.fetch({sort: sortAttributes, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_sortAscending_html',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the sorting API in descending order.
+				//	description:
+				//		Simple test of the sorting API in descending order.
+				var store = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+	
+				//Comparison is done as a string type (toString comparison), so the order won't be numeric
+				//So have to compare in 'alphabetic' order.
+				var order = [	'Author of 10',
+							 	'Author of 11',
+							 	'Author of 12',
+							 	'Author of 13',
+							 	'Author of 14',
+							 	'Author of 15',
+							 	'Author of 16',
+							 	'Author of 17',
+							 	'Author of 18',
+							 	'Author of 19',
+							 	'Author of 1',
+							 	'Author of 20',
+							 	'Author of 2',
+							 	'Author of 3',
+							 	'Author of 4',
+							 	'Author of 5',
+							 	'Author of 6',
+							 	'Author of 7',
+							 	'Author of 8',
+							 	'Author of 9'];
+				
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+	
+					for(var i = 0; i < items.length; i++){
+						var td = items[i].node.getElementsByTagName('TD');
+						t.assertEqual(td.length, 3);
+						t.assertEqual(order[i], dojox.xml.parser.textContent(td[2]));
+					}
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+	
+				var sortAttributes = [{attribute: 'content'}];
+				store.fetch({sort: sortAttributes, onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_isItemLoaded_atom',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the isItemLoaded API
+				//	description:
+				//		Simple test of the isItemLoaded API
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertTrue(store.isItemLoaded(item));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_isItemLoaded_rss',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the isItemLoaded API
+				//	description:
+				//		Simple test of the isItemLoaded API
+				var store = dojox.data.tests.stores.OpenSearchStore.getRSSStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertTrue(store.isItemLoaded(item));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_isItemLoaded_html',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the isItemLoaded API
+				//	description:
+				//		Simple test of the isItemLoaded API
+				var store = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+	
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					t.assertTrue(store.isItemLoaded(item));
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_getFeatures',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getFeatures function of the store
+				//	description:
+				//		Simple test of the getFeatures function of the store
+	
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+				var features = store.getFeatures();
+				t.assertTrue(dojo.isObject(features));
+				t.assertTrue(features["dojo.data.api.Read"]);
+				t.assertFalse(features["dojo.data.api.Identity"]);
+				t.assertFalse(features["dojo.data.api.Write"]);
+				t.assertFalse(features["dojo.data.api.Notification"]);
+			}
+		},
+		{
+			name: 'testReadAPI_getAttributes_atom',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getAttributes API
+				//	description:
+				//		Simple test of the getAttributes API
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					var attributes = store.getAttributes(item);
+					t.assertTrue(dojo.isArray(attributes));
+					t.assertEqual(1,attributes.length);
+					t.assertTrue(attributes[0] === 'content');
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_getAttributes_rss',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getAttributes API
+				//	description:
+				//		Simple test of the getAttributes API
+				var store = dojox.data.tests.stores.OpenSearchStore.getRSSStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					var attributes = store.getAttributes(item);
+					t.assertTrue(dojo.isArray(attributes));
+					t.assertEqual(1,attributes.length);
+					t.assertTrue(attributes[0] === 'content');
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_getAttributes_html',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of the getAttributes API
+				//	description:
+				//		Simple test of the getAttributes API
+				var store = dojox.data.tests.stores.OpenSearchStore.getHTMLStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request) {
+					t.assertEqual(20, items.length);
+					var item = items[0];
+					var attributes = store.getAttributes(item);
+					t.assertTrue(dojo.isArray(attributes));
+					t.assertEqual(1,attributes.length);
+					t.assertTrue(attributes[0] === 'content');
+					d.callback(true);
+				}
+				function onError(error, request) {
+					d.errback(error);
+				}
+				store.fetch({onComplete: onComplete, onError: onError});
+				return d; //Object
+			}
+		},
+		{
+			name: 'testReadAPI_functionConformance',
+			timeout: 20000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+				//	description:
+				//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+	
+				var store = dojox.data.tests.stores.OpenSearchStore.getAtomStore();
+				var readApi = new dojo.data.api.Read();
+				var passed = true;
+	
+				for(var i in readApi){
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = store[i];
+						if(!(typeof testStoreMember === "function")){
+							console.log("Problem with function: [" + i + "]");
+							passed = false;
+							break;
+						}
+					}
+				}
+				t.assertTrue(passed);
+			}
+		}
+	]
+);
diff --git a/dojox/data/tests/stores/OpmlStore.js b/dojox/data/tests/stores/OpmlStore.js
new file mode 100644
index 0000000..135d70f
--- /dev/null
+++ b/dojox/data/tests/stores/OpmlStore.js
@@ -0,0 +1,1072 @@
+dojo.provide("dojox.data.tests.stores.OpmlStore");
+dojo.require("dojox.data.OpmlStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+
+dojox.data.tests.stores.OpmlStore.getDatasource = function(filepath){
+	//  summary:
+	//		A simple helper function for getting the sample data used in each of the tests.
+	//  description:
+	//		A simple helper function for getting the sample data used in each of the tests.
+	
+	var dataSource = {};
+	if(dojo.isBrowser){
+		dataSource.url = dojo.moduleUrl("dojox.data.tests", filepath).toString();            
+	}else{
+		// When running tests in Rhino, xhrGet is not available,
+		// so we have the file data in the code below.
+		switch(filepath){
+			case "stores/geography.xml":
+				var opmlData = "";
+				opmlData += '<?xml version="1.0" encoding="ISO-8859-1"?>\n';
+				opmlData += '	<opml version="1.0">\n';
+				opmlData += '		<head>\n';
+				opmlData += '			<title>geography.opml</title>\n';
+				opmlData += '			<dateCreated>2006-11-10</dateCreated>\n';
+				opmlData += '			<dateModified>2006-11-13</dateModified>\n';
+				opmlData += '			<ownerName>Magellan, Ferdinand</ownerName>\n';
+				opmlData += '		</head>\n';
+				opmlData += '		<body>\n';
+				opmlData += '			<outline text="Africa" type="continent">\n';
+				opmlData += '				<outline text="Egypt" type="country"/>\n';
+				opmlData += '				<outline text="Kenya" type="country">\n';
+				opmlData += '					<outline text="Nairobi" type="city"/>\n';
+				opmlData += '					<outline text="Mombasa" type="city"/>\n';
+				opmlData += '				</outline>\n';
+				opmlData += '				<outline text="Sudan" type="country">\n';
+				opmlData += '					<outline text="Khartoum" type="city"/>\n';
+				opmlData += '				</outline>\n';
+				opmlData += '			</outline>\n';
+				opmlData += '			<outline text="Asia" type="continent">\n';
+				opmlData += '				<outline text="China" type="country"/>\n';
+				opmlData += '				<outline text="India" type="country"/>\n';
+				opmlData += '				<outline text="Russia" type="country"/>\n';
+				opmlData += '				<outline text="Mongolia" type="country"/>\n';
+				opmlData += '			</outline>\n';
+				opmlData += '			<outline text="Australia" type="continent" population="21 million">\n';
+				opmlData += '				<outline text="Australia" type="country" population="21 million"/>\n';
+				opmlData += '			</outline>\n';
+				opmlData += '			<outline text="Europe" type="continent">\n';
+				opmlData += '				<outline text="Germany" type="country"/>\n';
+				opmlData += '				<outline text="France" type="country"/>\n';
+				opmlData += '				<outline text="Spain" type="country"/>\n';
+				opmlData += '				<outline text="Italy" type="country"/>\n';
+				opmlData += '			</outline>\n';
+				opmlData += '			<outline text="North America" type="continent">\n';
+				opmlData += '				<outline text="Mexico" type="country" population="108 million" area="1,972,550 sq km">\n';
+				opmlData += '					<outline text="Mexico City" type="city" population="19 million" timezone="-6 UTC"/>\n';
+				opmlData += '					<outline text="Guadalajara" type="city" population="4 million" timezone="-6 UTC"/>\n';
+				opmlData += '				</outline>\n';
+				opmlData += '				<outline text="Canada" type="country" population="33 million" area="9,984,670 sq km">\n';
+				opmlData += '					<outline text="Ottawa" type="city" population="0.9 million" timezone="-5 UTC"/>\n';
+				opmlData += '					<outline text="Toronto" type="city" population="2.5 million" timezone="-5 UTC"/>\n';
+				opmlData += '				</outline>\n';
+				opmlData += '				<outline text="United States of America" type="country"/>\n';
+				opmlData += '			</outline>\n';
+				opmlData += '			<outline text="South America" type="continent">\n';
+				opmlData += '				<outline text="Brazil" type="country" population="186 million"/>\n';
+				opmlData += '				<outline text="Argentina" type="country" population="40 million"/>\n';
+				opmlData += '			</outline>\n';
+				opmlData += '		</body>\n';
+				opmlData += '	</opml>\n';
+				break;
+			case "stores/geography_withspeciallabel.xml":
+				var opmlData = "";
+				opmlData += '<?xml version="1.0" encoding="ISO-8859-1"?>\n';
+				opmlData += '<opml version="1.0">\n';
+				opmlData += '	<head>\n';
+				opmlData += '		<title>geography.opml</title>\n';
+				opmlData += '		<dateCreated>2006-11-10</dateCreated>\n';
+				opmlData += '		<dateModified>2006-11-13</dateModified>\n';
+				opmlData += '		<ownerName>Magellan, Ferdinand</ownerName>\n';
+				opmlData += '	</head>\n';
+				opmlData += '	<body>\n';
+				opmlData += '		<outline text="Africa" type="continent" label="Continent/Africa">\n';
+				opmlData += '			<outline text="Egypt" type="country" label="Country/Egypt"/>\n';
+				opmlData += '			<outline text="Kenya" type="country" label="Country/Kenya">\n';
+				opmlData += '				<outline text="Nairobi" type="city" label="City/Nairobi"/>\n';
+				opmlData += '				<outline text="Mombasa" type="city" label="City/Mombasa"/>\n';
+				opmlData += '			</outline>\n';
+				opmlData += '			<outline text="Sudan" type="country" label="Country/Sudan">\n';
+				opmlData += '				<outline text="Khartoum" type="city" label="City/Khartoum"/>\n';
+				opmlData += '			</outline>\n';
+				opmlData += '		</outline>\n';
+				opmlData += '		<outline text="Asia" type="continent" label="Continent/Asia">\n';
+				opmlData += '			<outline text="China" type="country" label="Country/China"/>\n';
+				opmlData += '			<outline text="India" type="country" label="Country/India"/>\n';
+				opmlData += '			<outline text="Russia" type="country" label="Country/Russia"/>\n';
+				opmlData += '			<outline text="Mongolia" type="country" label="Country/Mongolia"/>\n';
+				opmlData += '		</outline>\n';
+				opmlData += '		<outline text="Australia" type="continent" population="21 million" label="Continent/Australia">\n';
+				opmlData += '			<outline text="Australia" type="country" population="21 million" label="Country/Australia"/>\n';
+				opmlData += '		</outline>\n';
+				opmlData += '		<outline text="Europe" type="continent" label="Contintent/Europe">\n';
+				opmlData += '			<outline text="Germany" type="country" label="Country/Germany"/>\n';
+				opmlData += '			<outline text="France" type="country"  label="Country/France"/>\n';
+				opmlData += '			<outline text="Spain" type="country"   label="Country/Spain"/>\n';
+				opmlData += '			<outline text="Italy" type="country"   label="Country/Italy"/>\n';
+				opmlData += '		</outline>\n';
+				opmlData += '		<outline text="North America" type="continent" label="Continent/North America">\n';
+				opmlData += '			<outline text="Mexico" type="country" population="108 million" area="1,972,550 sq km" label="Country/Mexico">\n';
+				opmlData += '				<outline text="Mexico City" type="city" population="19 million" timezone="-6 UTC" label="City/Mexico City"/>\n';
+				opmlData += '				<outline text="Guadalajara" type="city" population="4 million" timezone="-6 UTC"  label="City/Guadalajara"/>\n';
+				opmlData += '			</outline>\n';
+				opmlData += '			<outline text="Canada" type="country" population="33 million" area="9,984,670 sq km" label="Country/Canada">\n';
+				opmlData += '				<outline text="Ottawa" type="city" population="0.9 million" timezone="-5 UTC"    label="City/Ottawa"/>\n';
+				opmlData += '				<outline text="Toronto" type="city" population="2.5 million" timezone="-5 UTC"   label="City/Toronto"/>\n';
+				opmlData += '			</outline>\n';
+				opmlData += '			<outline text="United States of America" type="country" label="Country/United States of America"/>\n';
+				opmlData += '		</outline>\n';
+				opmlData += '		<outline text="South America" type="continent" label="Continent/South America">\n';
+				opmlData += '			<outline text="Brazil" type="country" population="186 million" label="Country/Brazil"/>\n';
+				opmlData += '			<outline text="Argentina" type="country" population="40 million" label="Country/Argentina"/>\n';
+				opmlData += '		</outline>\n';
+				opmlData += '	</body>\n';
+				opmlData += '</opml>\n';
+				break;
+		}
+		dataSource.data = opmlData;
+	}
+	return dataSource; //Object
+}
+
+dojox.data.tests.stores.OpmlStore.verifyItems = function(opmlStore, items, attribute, compareArray){
+	//  summary:
+	//		A helper function for validating that the items array is ordered
+	//		the same as the compareArray
+	if(items.length != compareArray.length){ return false; }
+	for(var i = 0; i < items.length; i++){
+		if(!(opmlStore.getValue(items[i], attribute) === compareArray[i])){
+			return false; //Boolean
+		}
+	}
+	return true; //Boolean
+}
+
+dojox.data.tests.stores.OpmlStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	d.errback(errData);	
+}
+
+doh.register("dojox.data.tests.stores.OpmlStore", 
+	[
+		function testReadAPI_fetch_all(t){
+			//	summary: 
+			//		Simple test of a basic fetch on OpmlStore.
+			//	description:
+			//		Simple test of a basic fetch on OpmlStore.
+			
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.is(6, items.length);
+				d.callback(true);
+			}
+
+			//Get everything...
+			opmlStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one(t){
+			//	summary: 
+			//		Simple test of a basic fetch on OpmlStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on OpmlStore of a single item.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.is(1, items.length);
+				d.callback(true);
+			}
+			opmlStore.fetch({ 	query: {text: "Asia"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+							});
+			return d; //Object
+		},
+
+		function testReadAPI_fetch_one_Multiple(t){
+			//	summary: 
+			//		Simple test of a basic fetch on OpmlStore of a single item.
+			//	description:
+			//		Simple test of a basic fetch on OpmlStore of a single item.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			var done = [false,false];
+			function onCompleteOne(items, request){
+				done[0] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			function onCompleteTwo(items, request){
+				done[1] = true;
+				t.is(1, items.length);
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+
+			opmlStore.fetch({ 	query: {text: "Asia"}, 
+								onComplete: onCompleteOne, 
+								onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+							});
+
+			opmlStore.fetch({ 	query: {text: "North America"}, 
+								onComplete: onCompleteTwo, 
+								onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+							});
+
+			return d; //Object
+		},
+
+		function testReadAPI_fetch_one_MultipleMixed(t){
+			//	summary: 
+			//		Simple test of a basic fetch on OpmlStore of a single item mixing two fetch types.
+			//	description:
+			//		Simple test of a basic fetch on Cpmltore of a single item mixing two fetch types.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+
+			var done = [false, false];
+			function onComplete(items, request){
+				done[0] = true;
+				t.is(1, items.length);
+				console.log("Found item: " + opmlStore.getValue(items[0],"text") + " with identity: " + opmlStore.getIdentity(items[0]));
+				t.is(0, opmlStore.getIdentity(items[0]));
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+			
+			function onItem(item){
+				done[1] = true;
+				t.assertTrue(item !== null);
+				console.log("Found item: " + opmlStore.getValue(item,"text"));
+				t.is('Egypt', opmlStore.getValue(item,"text")); //Should be the second node parsed, ergo id 1, first node is id 0.
+				t.is(1, opmlStore.getIdentity(item)); 
+				if(done[0] && done[1]){
+					d.callback(true);
+				}
+			}
+
+			opmlStore.fetch({ 	query: {text: "Africa"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+							});
+			
+            opmlStore.fetchItemByIdentity({identity: "1", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+
+			return d; //Object
+		},
+
+		function testReadAPI_fetch_one_deep(t){
+			//	summary: 
+			//		Simple test of a basic fetch on OpmlStore of a single item that's nested down as a child item.
+			//	description:
+			//		Simple test of a basic fetch on OpmlStore of a single item that's nested down as a child item.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.is(1, items.length);
+				d.callback(true);
+			}
+			opmlStore.fetch({ 	query: {text: "Mexico City"}, 
+								queryOptions: {deep:true},
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+							});
+			return d; //Object
+		},
+
+		function testReadAPI_fetch_one_deep_off(t){
+			//	summary: 
+			//		Simple test of a basic fetch on OpmlStore of a single item that's nested down as a child item.
+			//	description:
+			//		Simple test of a basic fetch on OpmlStore of a single item that's nested down as a child item.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				//Nothing should be found.
+				t.is(0, items.length);
+				d.callback(true);
+			}
+			opmlStore.fetch({ 	query: {text: "Mexico City"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+							});
+			return d; //Object
+		},
+
+		function testReadAPI_fetch_all_streaming(t){
+			//	summary: 
+			//		Simple test of a basic fetch on OpmlStore.
+			//	description:
+			//		Simple test of a basic fetch on OpmlStore.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+
+			var d = new doh.Deferred();
+			count = 0;
+
+			function onBegin(size, requestObj){
+				t.is(6, size);
+			}
+			function onItem(item, requestObj){
+				t.assertTrue(opmlStore.isItem(item));
+				count++;
+			}
+			function onComplete(items, request){
+				t.is(6, count);
+				t.is(null, items);
+				d.callback(true);
+			}
+
+			//Get everything...
+			opmlStore.fetch({	onBegin: onBegin,
+								onItem: onItem, 
+								onComplete: onComplete,
+								onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+							});
+			return d; //Object
+		},
+		function testReadAPI_fetch_paging(t){
+			 //	summary: 
+			 //		Test of multiple fetches on a single result.  Paging, if you will.
+			 //	description:
+			 //		Test of multiple fetches on a single result.  Paging, if you will.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function dumpFirstFetch(items, request){
+				t.is(5, items.length);
+				request.start = 3;
+				request.count = 1;
+				request.onComplete = dumpSecondFetch;
+				opmlStore.fetch(request);
+			}
+
+			function dumpSecondFetch(items, request){
+				t.is(1, items.length);
+				request.start = 0;
+				request.count = 5;
+				request.onComplete = dumpThirdFetch;
+				opmlStore.fetch(request);
+			}
+
+			function dumpThirdFetch(items, request){
+				t.is(5, items.length);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpFourthFetch;
+				opmlStore.fetch(request);
+			}
+
+			function dumpFourthFetch(items, request){
+				t.is(4, items.length);
+				request.start = 9;
+				request.count = 100;
+				request.onComplete = dumpFifthFetch;
+				opmlStore.fetch(request);
+			}
+
+			function dumpFifthFetch(items, request){
+				t.is(0, items.length);
+				request.start = 2;
+				request.count = 20;
+				request.onComplete = dumpSixthFetch;
+				opmlStore.fetch(request);
+			}
+
+			function dumpSixthFetch(items, request){
+				t.is(4, items.length);
+			    d.callback(true);
+			}
+
+			function completed(items, request){
+				t.is(6, items.length);
+				request.start = 1;
+				request.count = 5;
+				request.onComplete = dumpFirstFetch;
+				opmlStore.fetch(request);
+			}
+
+			opmlStore.fetch({onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+
+		},
+		function testReadAPI_getLabel(t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = opmlStore.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				t.assertEqual("Asia", label);
+				d.callback(true);
+			}
+			opmlStore.fetch({ 	query: {text: "Asia"}, 
+						   		onComplete: onComplete, 
+						   		onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+						   	});
+			return d;
+		},
+		function testReadAPI_getLabelAttributes(t){
+			//	summary: 
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var labelList = opmlStore.getLabelAttributes(items[0]);
+				t.assertTrue(dojo.isArray(labelList));
+				t.assertEqual("text", labelList[0]);
+				d.callback(true);
+			}
+			opmlStore.fetch({ 	query: {text: "Asia"}, 
+							   	onComplete: onComplete, 
+							   	onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+							});
+			return d;
+		},
+
+		function testReadAPI_getLabel_nondefault(t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography_withspeciallabel.xml");
+			args.label="label";
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = opmlStore.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				t.assertEqual("Continent/Asia", label);
+				d.callback(true);
+			}
+			opmlStore.fetch({ 	query: {text: "Asia"}, 
+						   		onComplete: onComplete, 
+						   		onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+						   	});
+			return d;
+		},
+		function testReadAPI_getLabelAttributes_nondefault(t){
+			//	summary: 
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography_withspeciallabel.xml");
+			args.label="label";
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var labelList = opmlStore.getLabelAttributes(items[0]);
+				t.assertTrue(dojo.isArray(labelList));
+				t.assertEqual("label", labelList[0]);
+				d.callback(true);
+			}
+			opmlStore.fetch({ 	query: {text: "Asia"}, 
+							   	onComplete: onComplete, 
+							   	onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+							});
+			return d;
+		},
+
+		function testReadAPI_getValue(t){
+			//	summary: 
+			//		Simple test of the getValue function of the store.
+			//	description:
+			//		Simple test of the getValue function of the store.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.is(6, items.length);
+				
+				t.is("Africa", 		opmlStore.getValue(items[0],"text"));
+				t.is("Asia", 		opmlStore.getValue(items[1],"text"));
+				t.is("Australia", 	opmlStore.getValue(items[2],"text"));
+				t.is("Europe", 		opmlStore.getValue(items[3],"text"));
+				t.is("North America", 	opmlStore.getValue(items[4],"text"));
+				t.is("South America",	opmlStore.getValue(items[5],"text"));
+	
+				t.is("continent", 	opmlStore.getValue(items[1],"type"));
+				t.is("21 million", 	opmlStore.getValue(items[2],"population"));
+				
+				var firstChild = opmlStore.getValue(items[4],"children");
+				t.assertTrue(opmlStore.isItem(firstChild));
+				t.is("Mexico", 		opmlStore.getValue(firstChild,"text"));
+				t.is("country", 	opmlStore.getValue(firstChild,"type"));
+				t.is("108 million", 	opmlStore.getValue(firstChild,"population"));
+				t.is("1,972,550 sq km", opmlStore.getValue(firstChild,"area"));
+				
+				firstChild = opmlStore.getValue(firstChild,"children");
+				t.assertTrue(opmlStore.isItem(firstChild));
+				t.is("Mexico City", 	opmlStore.getValue(firstChild,"text"));
+				t.is("city", 		opmlStore.getValue(firstChild,"type"));
+				t.is("19 million", 	opmlStore.getValue(firstChild,"population"));
+				t.is("-6 UTC", 		opmlStore.getValue(firstChild,"timezone"));
+				
+				d.callback(true);
+			}
+
+			//Get everything...
+			opmlStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},	
+		function testReadAPI_getValues(t){
+			//	summary: 
+			//		Simple test of the getValues function of the store.
+			//	description:
+			//		Simple test of the getValues function of the store.
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+
+			var d = new doh.Deferred();
+			function completed(items){
+				t.is(1, items.length);
+				
+				var children = opmlStore.getValues(items[0],"children");
+				t.is(3, children.length);
+				for(var i=0; i<children.length; i++){
+					t.assertTrue(opmlStore.isItem(children[i]));
+				}
+				
+				t.is("Mexico", 		opmlStore.getValues(children[0],"text")[0]);
+				t.is("country", 	opmlStore.getValues(children[0],"type")[0]);
+				t.is("108 million", 	opmlStore.getValues(children[0],"population")[0]);
+				t.is("1,972,550 sq km", opmlStore.getValues(children[0],"area")[0]);
+				
+				t.is("Canada", 		opmlStore.getValues(children[1],"text")[0]);
+				t.is("country", 	opmlStore.getValues(children[1],"type")[0]);
+				
+				children = opmlStore.getValues(children[1],"children");
+				t.is(2, children.length);
+				for(var i=0; i<children.length; i++){
+					t.assertTrue(opmlStore.isItem(children[i]));
+				}
+				t.is("Ottawa", 	opmlStore.getValues(children[0],"text")[0]);
+				t.is("Toronto", opmlStore.getValues(children[1],"text")[0]);
+								
+				d.callback(true);
+			}
+
+			//Get one item...
+			opmlStore.fetch({	query: {text: "North America"},
+								onComplete: completed, 
+								onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_isItem(t){
+			//	summary: 
+			//		Simple test of the isItem function of the store
+			//	description:
+			//		Simple test of the isItem function of the store
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+
+			var d = new doh.Deferred();
+			function completedAll(items){
+				t.is(6, items.length);
+				for(var i=0; i<6; i++){
+					t.assertTrue(opmlStore.isItem(items[i]));
+				}
+				t.assertTrue(!opmlStore.isItem({}));
+				t.assertTrue(!opmlStore.isItem({ item: "not an item" }));
+				t.assertTrue(!opmlStore.isItem("not an item"));
+				t.assertTrue(!opmlStore.isItem(["not an item"]));
+				
+				d.callback(true);
+			}
+
+			//Get everything...
+			opmlStore.fetch({ onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_hasAttribute(t){
+			//	summary: 
+			//		Simple test of the hasAttribute function of the store
+			//	description:
+			//		Simple test of the hasAttribute function of the store
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+
+			var d = new doh.Deferred();
+			function onComplete(items){
+				t.is(1, items.length);
+				t.assertTrue(items[0] !== null);
+				t.assertTrue(opmlStore.hasAttribute(items[0], "text"));
+				t.assertTrue(opmlStore.hasAttribute(items[0], "type"));
+				t.assertTrue(!opmlStore.hasAttribute(items[0], "population"));
+				t.assertTrue(!opmlStore.hasAttribute(items[0], "Nothing"));
+				t.assertTrue(!opmlStore.hasAttribute(items[0], "Text"));
+				
+				//Test that null attributes throw an exception
+				var passed = false;
+				try{
+					opmlStore.hasAttribute(items[0], null);
+				}catch (e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+				
+				d.callback(true);
+			}
+
+			//Get one item...
+			opmlStore.fetch({ 	query: {text: "Asia"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+							});
+			return d; //Object
+		},
+		function testReadAPI_containsValue(t){
+			//	summary: 
+			//		Simple test of the containsValue function of the store
+			//	description:
+			//		Simple test of the containsValue function of the store
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+ 			
+			var d = new doh.Deferred();
+			function onComplete(items){
+				t.is(1, items.length);
+				t.assertTrue(items[0] !== null);
+				t.assertTrue(opmlStore.containsValue(items[0], "text", "North America"));
+				t.assertTrue(opmlStore.containsValue(items[0], "type", "continent"));
+				t.assertTrue(!opmlStore.containsValue(items[0], "text", "America"));
+				t.assertTrue(!opmlStore.containsValue(items[0], "Type", "continent"));
+				t.assertTrue(!opmlStore.containsValue(items[0], "text", null));
+								
+				var children = opmlStore.getValues(items[0], "children");
+				t.assertTrue(opmlStore.containsValue(items[0], "children", children[0]));
+				t.assertTrue(opmlStore.containsValue(items[0], "children", children[1]));
+				t.assertTrue(opmlStore.containsValue(items[0], "children", children[2]));
+	
+				//Test that null attributes throw an exception
+				var passed = false;
+				try{
+					opmlStore.containsValue(items[0], null, "foo");
+				}catch (e){
+					passed = true;
+				}
+				t.assertTrue(passed);
+				
+				d.callback(true);
+			}
+
+			//Get one item...
+			opmlStore.fetch({ 	query: {text: "North America"}, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)
+							});
+			return d; //Object
+		},
+		function testReadAPI_getAttributes(t){
+			//	summary: 
+			//		Simple test of the getAttributes function of the store
+			//	description:
+			//		Simple test of the getAttributes function of the store
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+
+			var d = new doh.Deferred();
+			function onComplete(items){
+				t.is(6, items.length);
+				t.assertTrue(opmlStore.isItem(items[0]));
+	
+				var attributes = opmlStore.getAttributes(items[0]);
+				t.is(3, attributes.length);
+				for(var i = 0; i < attributes.length; i++){
+					t.assertTrue((attributes[i] === "text" || attributes[i] === "type" || attributes[i] === "children"));
+				}
+				
+				d.callback(true);
+			}
+
+			//Get everything...
+			opmlStore.fetch({ onComplete: onComplete, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+
+			var features = opmlStore.getFeatures(); 
+			var count = 0;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read") || (i === "dojo.data.api.Identity"));
+				count++;
+			}
+			t.assertTrue(count === 2);
+		},
+		function testReadAPI_fetch_patternMatch0(t){
+			//	summary: 
+			//		Function to test pattern matching of everything starting with Capital A
+			//	description:
+			//		Function to test pattern matching of everything starting with Capital A
+
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(3, items.length);
+				var valueArray = [ "Africa", "Asia", "Australia"];
+				t.assertTrue(dojox.data.tests.stores.OpmlStore.verifyItems(opmlStore, items, "text", valueArray));
+				d.callback(true);
+			}
+			
+			opmlStore.fetch({query: {text: "A*"}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch1(t){
+			//	summary: 
+			//		Function to test pattern matching of everything with America in it.
+			//	description:
+			//		Function to test pattern matching of everything with America in it.
+			
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.assertTrue(items.length === 2);
+				var valueArray = [ "North America", "South America"];
+				t.assertTrue(dojox.data.tests.stores.OpmlStore.verifyItems(opmlStore, items, "text", valueArray));
+				d.callback(true);
+			}
+			
+			opmlStore.fetch({query: {text: "*America*"}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch2(t){
+			//	summary: 
+			//		Function to test exact pattern match
+			//	description:
+			//		Function to test exact pattern match
+			
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(1, items.length);
+				t.assertTrue(opmlStore.getValue(items[0], "text") === "Europe");
+				d.callback(true);
+			}
+			
+			opmlStore.fetch({query: {text: "Europe"}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch_caseInsensitive(t){
+			//	summary: 
+			//		Function to test exact pattern match with case insensitivity set.
+			//	description:
+			//		Function to test exact pattern match with case insensitivity set.
+			
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(1, items.length);
+				t.assertTrue(opmlStore.getValue(items[0], "text") === "Asia");
+				d.callback(true);
+			}
+			
+			opmlStore.fetch({query: {text: "asia"}, queryOptions: {ignoreCase: true}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_patternMatch_caseSensitive(t){
+			//	summary: 
+			//		Function to test exact pattern match with case sensitivity set.
+			//	description:
+			//		Function to test exact pattern match with case sensitivity set.
+			
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				t.is(0, items.length);
+				d.callback(true);
+			}
+			
+			opmlStore.fetch({query: {text: "ASIA"}, queryOptions: {ignoreCase: false}, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortAlphabetic(t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering.
+			//	description:
+			//		Function to test sorting alphabetic ordering.
+		
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ "Africa", "Asia", "Australia", "Europe", "North America", "South America"];
+				t.is(6, items.length);
+				t.assertTrue(dojox.data.tests.stores.OpmlStore.verifyItems(opmlStore, items, "text", orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: "text"}];
+			opmlStore.fetch({sort: sortAttributes, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortAlphabeticDescending(t){
+			//	summary: 
+			//		Function to test sorting alphabetic ordering in descending mode.
+			//	description:
+			//		Function to test sorting alphabetic ordering in descending mode.
+		
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ "South America", "North America", "Europe", "Australia", "Asia", "Africa"
+					];
+				t.is(6, items.length);
+				t.assertTrue(dojox.data.tests.stores.OpmlStore.verifyItems(opmlStore, items, "text", orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: "text", descending: true}];
+			opmlStore.fetch({sort: sortAttributes, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_fetch_sortAlphabeticWithCount(t){
+			//	summary: 
+			//		Function to test sorting numerically in descending order, returning only a specified number of them.
+			//	description:
+			//		Function to test sorting numerically in descending order, returning only a specified number of them.
+		
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				//Output should be in this order...
+				var orderedArray = [ "South America", "North America", "Europe", "Australia"
+					];
+				t.is(4, items.length);
+				t.assertTrue(dojox.data.tests.stores.OpmlStore.verifyItems(opmlStore, items, "text", orderedArray));
+				d.callback(true);
+			}
+			
+			var sortAttributes = [{attribute: "text", descending: true}];
+			opmlStore.fetch({sort: sortAttributes, 
+							count: 4,
+							onComplete: completed,
+							onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d; //Object
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = new dojox.data.OpmlStore(dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml"));
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		},
+		function testIdentityAPI_fetchItemByIdentity(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item !== null);
+				d.callback(true);	
+			}
+            opmlStore.fetchItemByIdentity({identity: "1", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d;
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_bad1(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+            opmlStore.fetchItemByIdentity({identity: "200", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d;
+		},
+		function testIdentityAPI_fetchItemByIdentity_bad2(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+            opmlStore.fetchItemByIdentity({identity: "-1", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d;
+		},
+		function testIdentityAPI_fetchItemByIdentity_bad3(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			var d = new doh.Deferred();
+			function onItem(item){
+				t.assertTrue(item === null);
+				d.callback(true);	
+			}
+            opmlStore.fetchItemByIdentity({identity: "999999", onItem: onItem, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d)});
+			return d;
+		},
+		function testIdentityAPI_getIdentity(t){
+			//	summary: 
+			//		Simple test of the fetchItemByIdentity function of the store.
+			//	description:
+			//		Simple test of the fetchItemByIdentity function of the store.
+			
+			var args = dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml");
+			var opmlStore = new dojox.data.OpmlStore(args);
+			
+			var d = new doh.Deferred();
+			function completed(items, request){
+				var passed = true;
+				for(var i = 0; i < items.length; i++){
+					console.log("Identity is: " + opmlStore.getIdentity(items[i]) + " count is : "+ i);
+					if(!(opmlStore.getIdentity(items[i]) == i)){
+						passed=false;
+						break;
+					}
+				}
+				t.assertTrue(passed);
+				d.callback(true);
+			}
+			
+			//Get everything...
+			opmlStore.fetch({ onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.OpmlStore.error, t, d), queryOptions: {deep: true}});
+			return d; //Object
+		},
+		function testIdentityAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test identity API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = new dojox.data.OpmlStore(dojox.data.tests.stores.OpmlStore.getDatasource("stores/geography.xml"));
+			var identityApi = new dojo.data.api.Identity();
+			var passed = true;
+
+			for(i in identityApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = identityApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						console.log("Looking at function: [" + i + "]");
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
+
diff --git a/dojox/data/tests/stores/PicasaStore.js b/dojox/data/tests/stores/PicasaStore.js
new file mode 100755
index 0000000..a899328
--- /dev/null
+++ b/dojox/data/tests/stores/PicasaStore.js
@@ -0,0 +1,407 @@
+dojo.provide("dojox.data.tests.stores.PicasaStore");
+dojo.require("dojox.data.PicasaStore");
+dojo.require("dojo.data.api.Read");
+
+
+dojox.data.tests.stores.PicasaStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	d.errback(errData);	
+};
+
+doh.register("dojox.data.tests.stores.PicasaStore", 
+	[
+		{
+			name: "ReadAPI:  Fetch_One",
+			timeout:	10000, //10 seconds.  Picasa can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on PicasaStore of a single item.
+				//	description:
+				//		Simple test of a basic fetch on PicasaStore of a single item.
+
+				var flickrStore = new dojox.data.PicasaStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.is(1, items.length);
+					d.callback(true);
+				}
+				flickrStore.fetch({ 	query: {tags: "animals"},
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.PicasaStore.error, doh, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_20_Streaming",
+			timeout:	10000, //10 seconds.  Picasa can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on PicasaStore.
+				//	description:
+				//		Simple test of a basic fetch on PicasaStore.
+				var flickrStore = new dojox.data.PicasaStore();
+
+				var d = new doh.Deferred();
+				var count = 0;
+
+				function onBegin(size, requestObj){
+					t.is(20, size);
+				}
+				function onItem(item, requestObj){
+					t.assertTrue(flickrStore.isItem(item));
+					count++;
+				}
+				function onComplete(items, request){
+					t.is(20, count);
+					t.is(null, items);
+					d.callback(true);
+				}
+
+				//Get everything...
+				flickrStore.fetch({	onBegin: onBegin,
+									count: 20,
+									onItem: onItem,
+									onComplete: onComplete,
+									onError: dojo.partial(dojox.data.tests.stores.PicasaStore.error, t, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_Paging",
+			timeout:	30000, //30 seconds.  Picasa can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+				//	description:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+
+				var flickrStore = new dojox.data.PicasaStore();
+
+				var d = new doh.Deferred();
+
+				function dumpSixthFetch(items, request){
+					t.is(18, items.length);
+					d.callback(true);
+				}
+
+				function dumpFifthFetch(items, request){
+					t.is(11, items.length);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpSixthFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpFourthFetch(items, request){
+					t.is(18, items.length);
+					request.start = 9;
+					request.count = 100;
+					request.onComplete = dumpFifthFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpThirdFetch(items, request){
+					t.is(5, items.length);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpFourthFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpSecondFetch(items, request){
+					t.is(1, items.length);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					flickrStore.fetch(request);
+				}
+
+				function dumpFirstFetch(items, request){
+					t.is(5, items.length);
+                    request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					flickrStore.fetch(request);
+				}
+
+				function completed(items, request){
+					t.is(7, items.length);
+					request.start = 1;
+					request.count = 5;
+					request.onComplete = dumpFirstFetch;
+					flickrStore.fetch(request);
+				}
+				flickrStore.fetch({count: 7, onComplete: completed, onError: dojo.partial(dojox.data.tests.stores.PicasaStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getLabel",
+			timeout:	10000, //10 seconds.  Picasa can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getLabel function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabel function against a store set that has a label defined.
+
+				var flickrStore = new dojox.data.PicasaStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var label = flickrStore.getLabel(items[0]);
+					t.assertTrue(label !== null);
+					d.callback(true);
+				}
+				flickrStore.fetch({ 	query: {tags: "animals"}, 
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.PicasaStore.error, t, d)
+								});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getLabelAttributes",
+			timeout:	10000, //10 seconds.  Picasa can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+				//	description:
+				//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+				var flickrStore = new dojox.data.PicasaStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = flickrStore.getLabelAttributes(items[0]);
+					t.assertTrue(dojo.isArray(labelList));
+					t.assertEqual("title", labelList[0]);
+					d.callback(true);
+				}
+				flickrStore.fetch({ 	query: {tags: "animals"},
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.PicasaStore.error, t, d)
+								});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getValue",
+			timeout:	10000, //10 seconds.  Picasa can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var flickrStore = new dojox.data.PicasaStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					t.assertTrue(flickrStore.getValue(items[0], "title") !== null);
+					t.assertTrue(flickrStore.getValue(items[0], "imageUrl") !== null);
+					t.assertTrue(flickrStore.getValue(items[0], "imageUrlSmall") !== null);
+					t.assertTrue(flickrStore.getValue(items[0], "imageUrlMedium") !== null);
+					d.callback(true);
+				}
+
+				//Get one item and look at it.
+				flickrStore.fetch({ count: 1, onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.PicasaStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getValues",
+			timeout:	10000, //10 seconds.  Picasa can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var flickrStore = new dojox.data.PicasaStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(1, items.length);
+					t.assertTrue(flickrStore.getValues(items[0], "title") instanceof Array);
+					t.assertTrue(flickrStore.getValues(items[0], "description") instanceof Array);
+					t.assertTrue(flickrStore.getValues(items[0], "imageUrl") instanceof Array);
+					t.assertTrue(flickrStore.getValues(items[0], "imageUrlSmall") instanceof Array);
+					t.assertTrue(flickrStore.getValues(items[0], "imageUrlMedium") instanceof Array);
+					d.callback(true);
+				}
+				//Get one item and look at it.
+				flickrStore.fetch({ count: 1, onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.PicasaStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  isItem",
+			timeout:	10000, //10 seconds.  Picasa can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the isItem function of the store
+				//	description:
+				//		Simple test of the isItem function of the store
+				var flickrStore = new dojox.data.PicasaStore();
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.is(5, items.length);
+					for(var i=0; i < items.length; i++){
+						t.assertTrue(flickrStore.isItem(items[i]));
+					}
+					d.callback(true);
+				}
+
+				//Get everything...
+				flickrStore.fetch({ count: 5, onComplete: completedAll, onError: dojo.partial(dojox.data.tests.stores.PicasaStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  hasAttribute",
+			timeout:	10000, //10 seconds.  Picasa can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the hasAttribute function of the store
+				//	description:
+				//		Simple test of the hasAttribute function of the store
+
+				var flickrStore = new dojox.data.PicasaStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(items[0] !== null);
+					t.assertTrue(flickrStore.hasAttribute(items[0], "title"));
+					t.assertTrue(flickrStore.hasAttribute(items[0], "author"));
+					t.assertTrue(!flickrStore.hasAttribute(items[0], "Nothing"));
+					t.assertTrue(!flickrStore.hasAttribute(items[0], "Text"));
+
+					//Test that null attributes throw an exception
+					var passed = false;
+					try{
+						flickrStore.hasAttribute(items[0], null);
+					}catch (e){
+						passed = true;
+					}
+					t.assertTrue(passed);
+					d.callback(true);
+				}
+
+				//Get one item...
+				flickrStore.fetch({ 	query: {tags: "animals"}, 
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.PicasaStore.error, t, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  containsValue",
+			timeout:	10000, //10 seconds.  Picasa can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the containsValue function of the store
+				//	description:
+				//		Simple test of the containsValue function of the store
+
+				var flickrStore = new dojox.data.PicasaStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					d.callback(true);
+				}
+
+				//Get one item...
+				flickrStore.fetch({ 	query: {tags: "animals"}, 
+									count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.PicasaStore.error, t, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getAttributes",
+			timeout:	10000, //10 seconds.  Picasa can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getAttributes function of the store
+				//	description:
+				//		Simple test of the getAttributes function of the store
+
+				var flickrStore = new dojox.data.PicasaStore();
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.is(1, items.length);
+					t.assertTrue(flickrStore.isItem(items[0]));
+
+					var attributes = flickrStore.getAttributes(items[0]);
+					t.is(21, attributes.length);
+					d.callback(true);
+				}
+
+				//Get everything...
+				flickrStore.fetch({ count: 1, onComplete: onComplete, onError: dojo.partial(dojox.data.tests.stores.PicasaStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var flickrStore = new dojox.data.PicasaStore();
+
+			var features = flickrStore.getFeatures(); 
+			var count = 0;
+			var i;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read"));
+				count++;
+			}
+			t.assertTrue(count === 1);
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = new dojox.data.PicasaStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+			var i;
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
+
diff --git a/dojox/data/tests/stores/QueryReadStore.js b/dojox/data/tests/stores/QueryReadStore.js
new file mode 100644
index 0000000..cb82efd
--- /dev/null
+++ b/dojox/data/tests/stores/QueryReadStore.js
@@ -0,0 +1,438 @@
+dojo.provide("dojox.data.tests.stores.QueryReadStore");
+dojo.require("dojox.data.QueryReadStore");
+dojo.require("dojo.data.api.Read");
+
+//dojo.require("dojox.testing.DocTest");
+
+dojox.data.tests.stores.QueryReadStore.getStore = function(){
+	return new dojox.data.QueryReadStore({
+			url: dojo.moduleUrl("dojox.data.tests", "stores/QueryReadStore.php").toString()
+		});
+};
+
+
+tests.register("dojox.data.tests.stores.QueryReadStore", 
+	[
+		/*
+		function testDocTests(t) {
+			//	summary:
+			// 		Run all the doc comments.
+			var doctest = new dojox.testing.DocTest();
+			doctest.run("dojox.data.QueryReadStore");
+			t.assertTrue(doctest.errors.length==0);
+		},
+		*/
+		
+		function testReadApi_getValue(t){
+			//	summary: 
+			//	description:
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				var item = items[0];
+				// The good cases.
+				t.assertEqual("Alabama", store.getValue(item, "name"));
+				t.assertEqual("<img src='images/Alabama.jpg'/>Alabama", store.getValue(item, "label"));
+				t.assertEqual("AL", store.getValue(item, "abbreviation"));
+				// Test the defaultValue cases (the third paramter).
+				t.assertEqual("default value", store.getValue(item, "NAME", "default value"));
+				// TODO Test for null somehow ...
+				// Read api says: Returns null if and only if null was explicitly set as the attribute value.
+				
+				// According to Read-API getValue() an exception is thrown when
+				// the item is not an item or when the attribute is not a string.
+				t.assertError(Error, store, "getValue", ["not an item", "NOT THERE"]);
+				t.assertError(Error, store, "getValue", [item, {}]);
+				
+				d.callback(true);
+			}
+			store.fetch({query:{q:"Alabama"}, onComplete: onComplete});
+			return d; //Object
+		},
+
+		function testReadApi_getValues(t){
+			//	summary: 
+			//	description:
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				var item = items[0];
+				// The good cases.
+				t.assertEqual(["Alabama"], store.getValues(item, "name"));
+				t.assertEqual(["<img src='images/Alabama.jpg'/>Alabama"], store.getValues(item, "label"));
+				t.assertEqual(["AL"], store.getValues(item, "abbreviation"));
+				// TODO Test for null somehow ...
+				// Read api says: Returns null if and only if null was explicitly set as the attribute value.
+
+				// Test for not-existing attributes without defaultValues and invalid items.
+				// TODO
+				t.assertEqual([], store.getValues(item, "NOT THERE"));
+				var errThrown = false;
+				try{
+					//Should throw an exception.
+					var values = store.getValues("not an item", "NOT THERE");
+				}catch (e){
+					errThrown = true;
+				}
+				t.assertTrue(errThrown);
+				d.callback(true);
+			}
+			store.fetch({query:{q:"Alabama"}, onComplete: onComplete});
+			return d; //Object
+		},
+		
+		function testReadApi_getAttributes(t){
+			//	summary: 
+			//	description:
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				var item = items[0];
+				// The good case(s).
+				t.assertEqual(['id', 'name', 'label', 'abbreviation', 'capital'], store.getAttributes(item));
+				t.assertError(Error, store, "getAttributes", [{}]);
+				
+				d.callback(true);
+			}
+			store.fetch({query:{q:"Alabama"}, onComplete: onComplete});
+			return d; //Object
+		},
+
+		function testReadApi_getLabel(t){
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				var item = items[0];
+				// The good cases.
+				t.assertEqual(["<img src='images/Alabama.jpg'/>Alabama"], store.getLabel(item));
+				d.callback(true);
+			}
+			store.fetch({query:{q:"Alabama"}, onComplete: onComplete});
+			return d; //Object
+		},
+
+		function testReadApi_hasAttribute(t){
+			//	summary: 
+			//	description:
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				var item = items[0];
+				// The positive cases.
+				t.assertEqual(true, store.hasAttribute(item, "name"));
+				t.assertEqual(true, store.hasAttribute(item, "label"));
+				t.assertEqual(true, store.hasAttribute(item, "abbreviation"));
+				// Make sure attribute case doesnt matter.
+				t.assertEqual(false, store.hasAttribute(item, "NAME"));
+				t.assertEqual(false, store.hasAttribute(item, "Name"));
+				t.assertEqual(false, store.hasAttribute(item, "Label"));
+				// Pass in an invalid item.
+				t.assertEqual(false, store.hasAttribute({}, "abbreviation"));
+				// pass in something that looks like the item with the attribute.
+				t.assertEqual(false, store.hasAttribute({name:"yo"}, "name"));
+				
+				d.callback(true);
+			}
+			store.fetch({query:{q:"Alaska"}, onComplete: onComplete});
+			return d; //Object
+		},
+
+		function testReadApi_containsValue(t){
+			//	summary: 
+			//	description:
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				var item = items[0];
+				t.assertTrue(store.containsValue(item, "name", "Alaska"));
+				d.callback(true);
+			}
+			store.fetch({query:{q:"Alaska"}, onComplete: onComplete});
+			return d; //Object
+		},
+
+		function testReadApi_isItem(t){
+			//	summary: 
+			//	description:
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				// The good case.
+				t.assertEqual(true, store.isItem(items[0]));
+				// Try a pure object.
+				t.assertEqual(false, store.isItem({}));
+				// Try to look like an item.
+				t.assertEqual(false, store.isItem({name:"Alaska", label:"Alaska", abbreviation:"AK"}));
+				d.callback(true);
+			}
+			store.fetch({query:{q:"Alaska"}, onComplete: onComplete});
+			return d; //Object
+		},
+
+		function testReadApi_isItemLoaded(t){
+			//	summary: 
+			//	description:
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				var item = items[0];
+				// The good case(s).
+				t.assertTrue(store.isItemLoaded(item));
+				
+				d.callback(true);
+			}
+			store.fetch({query:{q:"Alabama"}, onComplete: onComplete});
+			return d; //Object
+		},
+
+		//function testReadApi_loadItem(t){
+		//	//	summary: 
+		//	//	description:
+		//	t.assertTrue(false);
+		//},
+
+		function testReadApi_fetch_all(t){
+			//	summary: 
+			//		Simple test of fetching all items.
+			//	description:
+			//		Simple test of fetching all items.
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(12, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{q:"m"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		
+		function testReadApi_fetch_onBegin(t){
+			//	summary: 
+			//		Simple test of fetching items, checking that onBegin size is all items matched, and page is just the items asked for.
+			//	description:
+			//		Simple test of fetching items, checking that onBegin size is all items matched, and page is just the items asked for.
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+
+			var d = new doh.Deferred();
+			var passed = false;
+			function onBegin(size, request){
+				t.assertEqual(12, size);
+				passed = true;
+			}
+			function onComplete(items, request) {
+				t.assertEqual(5, items.length);
+				if(passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Store did not return proper number of rows, regardless of page size"));
+				}
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{q:"m"}, start: 0, count: 5, onBegin: onBegin, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testReadApi_fetch_onBegin_ServersidePaging(t){
+			//	summary: 
+			//		Simple test of fetching items, checking that onBegin size is all items matched, and page is just the items asked for.
+			//	description:
+			//		Simple test of fetching items, checking that onBegin size is all items matched, and page is just the items asked for.
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+
+			var d = new doh.Deferred();
+			var passed = false;
+			function onBegin(size, request){
+				t.assertEqual(12, size);
+				passed = true;
+			}
+			function onComplete(items, request) {
+				t.assertEqual(5, items.length);
+				if(passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Store did not return proper number of rows, regardless of page size"));
+				}
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{q:"m"}, start: 5, count: 5, onBegin: onBegin, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testReadApi_fetch_onBegin_ClientsidePaging(t){
+			//	summary: 
+			//		Simple test of fetching items, checking that onBegin size is all items matched, and page is just the items asked for.
+			//	description:
+			//		Simple test of fetching items, checking that onBegin size is all items matched, and page is just the items asked for.
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+			store.doClientPaging = true;
+
+			var d = new doh.Deferred();
+			var passed = false;
+			function onBegin(size, request){
+				t.assertEqual(12, size);
+				passed = true;
+			}
+			function onComplete(items, request) {
+				t.assertEqual(5, items.length);
+				if(passed){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Store did not return proper number of rows, regardless of page size"));
+				}
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{q:"m"}, start: 0, count: 5, onBegin: onBegin, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testReadApi_fetch_one(t){
+			//	summary: 
+			//	description:
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{q:"Alaska"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testReadApi_fetch_client_paging(t){
+			//	summary:
+			//		Lets test that paging on the same request does not trigger
+			//		server requests.
+			//	description:
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+			store.doClientPaging = true;
+
+			var lastRequestHash = null;
+			var firstItems = [];
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(5, items.length);
+				lastRequestHash = store.lastRequestHash;
+				firstItems = items;
+				
+				// Do the next request AFTER the previous one, so we are sure its sequential.
+				// We need to be sure so we can compare to the data from the first request.
+				function onComplete1(items, request) {
+					t.assertEqual(5, items.length);
+					t.assertEqual(lastRequestHash, store.lastRequestHash);
+					t.assertEqual(firstItems[1], items[0]);
+					d.callback(true);
+				}
+				req.start = 1;
+				req.onComplete = onComplete1;
+				store.fetch(req);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			var req = {query:{q:"m"}, start:0, count:5,
+						onComplete: onComplete, onError: onError};
+			store.fetch(req);
+			return d; //Object
+		},
+		
+		function testReadApi_fetch_server_paging(t) {
+			// Verify that the paging on the server side does work.
+			// This is the test for http://trac.dojotoolkit.org/ticket/4761
+			//
+			// How? We request 10 items from the server, start=0, count=10.
+			// The second request requests 5 items: start=5, count=5 and those
+			// 5 items should have the same values as the last 5 of the first
+			// request.
+			// This tests if the server side paging does work.
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+
+			var lastRequestHash = null;
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(10, items.length);
+				lastRequestHash = store.lastRequestHash;
+				firstItems = items;
+				
+				// Do the next request AFTER the previous one, so we are sure its sequential.
+				// We need to be sure so we can compare to the data from the first request.
+				function onComplete1(items, request) {
+					t.assertEqual(5, items.length);
+					// Compare the hash of the last request, they must be different,
+					// since another server request was issued.
+					t.assertTrue(lastRequestHash!=store.lastRequestHash);
+					t.assertEqual(store.getValue(firstItems[5], "name"), store.getValue(items[0], "name"));
+					t.assertEqual(store.getValue(firstItems[6], "name"), store.getValue(items[1], "name"));
+					t.assertEqual(store.getValue(firstItems[7], "name"), store.getValue(items[2], "name"));
+					t.assertEqual(store.getValue(firstItems[8], "name"), store.getValue(items[3], "name"));
+					t.assertEqual(store.getValue(firstItems[9], "name"), store.getValue(items[4], "name"));
+					d.callback(true);
+				}
+				// Init a new store, or it will use the old data, since the query has not changed.
+				store.doClientPaging = false;
+				store.fetch({start:5, count:5, onComplete: onComplete1, onError: onError});
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{}, start:0, count:10, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		
+		function testReadApi_getFeatures(t) {
+			var store = dojox.data.tests.stores.QueryReadStore.getStore();
+			var features = store.getFeatures();
+			t.assertTrue(features["dojo.data.api.Read"]);
+			t.assertTrue(features["dojo.data.api.Identity"]);
+			var count = 0;
+			for (i in features){
+				count++;
+			}
+			t.assertEqual(2, count);
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.QueryReadStore.getStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				var member = readApi[i];
+				//Check that all the 'Read' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						console.log("Problem with function: [" + i + "]");
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
diff --git a/dojox/data/tests/stores/QueryReadStore.php b/dojox/data/tests/stores/QueryReadStore.php
new file mode 100644
index 0000000..956ecaa
--- /dev/null
+++ b/dojox/data/tests/stores/QueryReadStore.php
@@ -0,0 +1,139 @@
+<?php
+
+header("Content-Type", "text/json");
+
+$allItems = array(
+	array('id'=>0, 'name'=>"Alabama", 'label'=>"<img src='images/Alabama.jpg'/>Alabama", 'abbreviation'=>"AL", 'capital'=>'Montgomery'),
+	array('id'=>1, 'name'=>"Alaska", 'label'=>"Alaska", 'abbreviation'=>"AK", 'capital'=>'Juneau'),
+	array('id'=>2, 'name'=>"American Samoa", 'label'=>"American Samoa", 'abbreviation'=>"AS", 'capital'=>'Pago Pago'),
+	array('id'=>3, 'name'=>"Arizona", 'label'=>"Arizona", 'abbreviation'=>"AZ", 'capital'=>'Phoenix'),
+	array('id'=>4, 'name'=>"Arkansas", 'label'=>"Arkansas", 'abbreviation'=>"AR", 'capital'=>'Little Rock'),
+	array('id'=>5, 'name'=>"Armed Forces Europe", 'label'=>"Armed Forces Europe", 'abbreviation'=>"AE", 'capital'=>'??? (Europe)'),
+	array('id'=>6, 'name'=>"Armed Forces Pacific", 'label'=>"Armed Forces Pacific", 'abbreviation'=>"AP", 'capital'=>'??? (Pacific)'),
+	array('id'=>7, 'name'=>"Armed Forces the Americas", 'label'=>"Armed Forces the Americas", 'abbreviation'=>"AA", 'capital'=>'??? (America)'),
+	array('id'=>8, 'name'=>"California", 'label'=>"California", 'abbreviation'=>"CA", 'capital'=>'Sacramento'),
+	array('id'=>9, 'name'=>"Colorado", 'label'=>"Colorado", 'abbreviation'=>"CO", 'capital'=>'Denver'),
+	array('id'=>10, 'name'=>"Connecticut", 'label'=>"Connecticut", 'abbreviation'=>"CT", 'capital'=>'Hartford'),
+	array('id'=>11, 'name'=>"Delaware", 'label'=>"Delaware", 'abbreviation'=>"DE", 'capital'=>'Dover'),
+	array('id'=>12, 'name'=>"District of Columbia", 'label'=>"District of Columbia", 'abbreviation'=>"DC", 'capital'=>'Washington'),
+	array('id'=>13, 'name'=>"Federated States of Micronesia", 'label'=>"Federated States of Micronesia", 'abbreviation'=>"FM", 'capital'=>'Palikir'),
+	array('id'=>14, 'name'=>"Florida", 'label'=>"Florida", 'abbreviation'=>"FL", 'capital'=>'Tallahassee'),
+	array('id'=>15, 'name'=>"Georgia", 'label'=>"Georgia", 'abbreviation'=>"GA", 'capital'=>'Atlanta'),
+	array('id'=>16, 'name'=>"Guam", 'label'=>"Guam", 'abbreviation'=>"GU", 'capital'=>'Hagatna'),
+	array('id'=>17, 'name'=>"Hawaii", 'label'=>"Hawaii", 'abbreviation'=>"HI", 'capital'=>'Honolulu'),
+	array('id'=>18, 'name'=>"Idaho", 'label'=>"Idaho", 'abbreviation'=>"ID", 'capital'=>'Boise'),
+	array('id'=>19, 'name'=>"Illinois", 'label'=>"Illinois", 'abbreviation'=>"IL", 'capital'=>'Springfield'),
+	array('id'=>20, 'name'=>"Indiana", 'label'=>"Indiana", 'abbreviation'=>"IN", 'capital'=>'Indianapolis'),
+	array('id'=>21, 'name'=>"Iowa", 'label'=>"Iowa", 'abbreviation'=>"IA", 'capital'=>'Des Moines'),
+	array('id'=>22, 'name'=>"Kansas", 'label'=>"Kansas", 'abbreviation'=>"KS", 'capital'=>'Topeka'),
+	array('id'=>23, 'name'=>"Kentucky", 'label'=>"Kentucky", 'abbreviation'=>"KY", 'capital'=>'Frankfort'),
+	array('id'=>24, 'name'=>"Louisiana", 'label'=>"Louisiana", 'abbreviation'=>"LA", 'capital'=>'Baton Rouge'),
+	array('id'=>25, 'name'=>"Maine", 'label'=>"Maine", 'abbreviation'=>"ME", 'capital'=>'Augusta'),
+	array('id'=>26, 'name'=>"Marshall Islands", 'label'=>"Marshall Islands", 'abbreviation'=>"MH", 'capital'=>'Answer Majuro'),
+	array('id'=>27, 'name'=>"Maryland", 'label'=>"Maryland", 'abbreviation'=>"MD", 'capital'=>'Annapolis'),
+	array('id'=>28, 'name'=>"Massachusetts", 'label'=>"Massachusetts", 'abbreviation'=>"MA", 'capital'=>'Boston'),
+	array('id'=>29, 'name'=>"Michigan", 'label'=>"Michigan", 'abbreviation'=>"MI", 'capital'=>'Lansing'),
+	array('id'=>30, 'name'=>"Minnesota", 'label'=>"Minnesota", 'abbreviation'=>"MN", 'capital'=>'Saint Paul'),
+	array('id'=>31, 'name'=>"Mississippi", 'label'=>"Mississippi", 'abbreviation'=>"MS", 'capital'=>'Jackson'),
+	array('id'=>32, 'name'=>"Missouri", 'label'=>"Missouri", 'abbreviation'=>"MO", 'capital'=>'Jefferson City'),
+	array('id'=>33, 'name'=>"Montana", 'label'=>"Montana", 'abbreviation'=>"MT", 'capital'=>'Helena'),
+	array('id'=>34, 'name'=>"Nebraska", 'label'=>"Nebraska", 'abbreviation'=>"NE", 'capital'=>'Lincoln'),
+	array('id'=>35, 'name'=>"Nevada", 'label'=>"Nevada", 'abbreviation'=>"NV", 'capital'=>'Carson City'),
+	array('id'=>36, 'name'=>"New Hampshire", 'label'=>"New Hampshire", 'abbreviation'=>"NH", 'capital'=>'Concord'),
+	array('id'=>37, 'name'=>"New Jersey", 'label'=>"New Jersey", 'abbreviation'=>"NJ", 'capital'=>'Trenton'),
+	array('id'=>38, 'name'=>"New Mexico", 'label'=>"New Mexico", 'abbreviation'=>"NM", 'capital'=>'Santa Fe'),
+	array('id'=>39, 'name'=>"New York", 'label'=>"New York", 'abbreviation'=>"NY", 'capital'=>'Albany'),
+	array('id'=>40, 'name'=>"North Carolina", 'label'=>"North Carolina", 'abbreviation'=>"NC", 'capital'=>'Raleigh'),
+	array('id'=>41, 'name'=>"North Dakota", 'label'=>"North Dakota", 'abbreviation'=>"ND", 'capital'=>'Bismarck'),
+	array('id'=>42, 'name'=>"Northern Mariana Islands", 'label'=>"Northern Mariana Islands", 'abbreviation'=>"MP", 'capital'=>'Saipan'),
+	array('id'=>43, 'name'=>"Ohio", 'label'=>"Ohio", 'abbreviation'=>"OH", 'capital'=>'Columbus'),
+	array('id'=>44, 'name'=>"Oklahoma", 'label'=>"Oklahoma", 'abbreviation'=>"OK", 'capital'=>'Oklahoma City'),
+	array('id'=>45, 'name'=>"Oregon", 'label'=>"Oregon", 'abbreviation'=>"OR", 'capital'=>'Salem'),
+	array('id'=>46, 'name'=>"Pennsylvania", 'label'=>"Pennsylvania", 'abbreviation'=>"PA", 'capital'=>'Harrisburg'),
+	array('id'=>47, 'name'=>"Puerto Rico", 'label'=>"Puerto Rico", 'abbreviation'=>"PR", 'capital'=>'San Juan'),
+	array('id'=>48, 'name'=>"Rhode Island", 'label'=>"Rhode Island", 'abbreviation'=>"RI", 'capital'=>'Providence'),
+	array('id'=>49, 'name'=>"South Carolina", 'label'=>"South Carolina", 'abbreviation'=>"SC", 'capital'=>'Columbia'),
+	array('id'=>50, 'name'=>"South Dakota", 'label'=>"South Dakota", 'abbreviation'=>"SD", 'capital'=>'Pierre'),
+	array('id'=>51, 'name'=>"Tennessee", 'label'=>"Tennessee", 'abbreviation'=>"TN", 'capital'=>'Nashville'),
+	array('id'=>52, 'name'=>"Texas", 'label'=>"Texas", 'abbreviation'=>"TX", 'capital'=>'Austin'),
+	array('id'=>53, 'name'=>"Utah", 'label'=>"Utah", 'abbreviation'=>"UT", 'capital'=>'Salt Lake City'),
+	array('id'=>54, 'name'=>"Vermont", 'label'=>"Vermont", 'abbreviation'=>"VT", 'capital'=>'Montpelier'),
+	array('id'=>55, 'name'=> "Virgin Islands, U.S.", 'label'=>"Virgin Islands, U.S.", 'abbreviation'=>"VI", 'capital'=>'Charlotte Amalie'),
+	array('id'=>56, 'name'=>"Virginia", 'label'=>"Virginia", 'abbreviation'=>"VA", 'capital'=>'Richmond'),
+	array('id'=>57, 'name'=>"Washington", 'label'=>"Washington", 'abbreviation'=>"WA", 'capital'=>'Olympia'),
+	array('id'=>58, 'name'=>"West Virginia", 'label'=>"West Virginia", 'abbreviation'=>"WV", 'capital'=>'Charleston'),
+	array('id'=>59, 'name'=>"Wisconsin", 'label'=>"Wisconsin", 'abbreviation'=>"WI", 'capital'=>'Madison'),
+	array('id'=>60, 'name'=>"Wyoming", 'label'=>"Wyoming", 'abbreviation'=>"WY", 'capital'=>'Cheyenne'),
+	array('id'=>61, 'name'=>"Special chars !\"$%&/()=? <a >#'+*-_.:,; <", 'label'=>"Special chars !\"$%&/()=? <a >#'+*-_.:,;<", 'abbreviation'=>":-)", 'capital'=>'/dev/null'),
+);
+
+$q = "";
+if (array_key_exists("q", $_REQUEST)) {
+	$q = $_REQUEST['q'];
+}else if (array_key_exists("name", $_REQUEST)) {
+	$q = $_REQUEST['name'];
+}
+
+if (strlen($q) && $q[strlen($q)-1]=="*") {
+	$q = substr($q, 0, strlen($q)-1);
+}
+$ret = array();
+foreach ($allItems as $item) {
+	$foundPos = -1;
+	$foundWord = false;
+	if ($q) {
+		$foundPos = strpos(strtolower($item['name']), strtolower($q));
+		$foundWord = $foundPos===0;
+		if (!$foundWord) {
+			$foundPos = strpos(strtolower($item['name']), ' '.strtolower($q));
+			if ($foundPos!==false) {
+				$foundPos += 1; // It was found, so subtract the offset the space occupied.
+				$foundWord = true;
+			}
+		}
+	}
+	if (!$q || $foundWord) {
+		// Put a span around the searched characters to highlight them.
+		$resultItem = $item;
+		// Currently we dont need custom highlighting, its implemented in the client too.
+		//if ($foundWord) {
+		//	$resultItem['highlightedLabel'] = substr($item['name'], 0, $foundPos) .
+		//		'<span class="searchResult">' .
+		//		substr($item['name'], $foundPos, strlen($q)) . '</span>' .
+		//		substr($item['name'], $foundPos+strlen($q));
+		//} else {
+		//	$resultItem['highlightedLabel'] = $item['name'];
+		//}
+		$ret[] = $resultItem;
+	}
+}
+
+// Handle sorting
+if (array_key_exists("sort", $_REQUEST)) {
+	$sort = $_REQUEST['sort'];
+	// Check if $sort starts with "-" then we have a DESC sort.
+	$desc = strpos($sort, '-')===0 ? true : false;
+	$sort = strpos($sort, '-')===0 ? substr($sort, 1) : $sort;
+	if (in_array($sort, array_keys($ret[0]))) {
+		$toSort = array();
+		foreach ($ret as $i) $toSort[$i[$sort]] = $i;
+		if ($desc) krsort($toSort); else ksort($toSort);
+		$newRet = array();
+		foreach ($toSort as $i) $newRet[] = $i;
+		$ret = $newRet;
+	}
+}
+
+
+// Handle total number of matches as a return, regardless of page size, but taking the filtering into account (if taken place).
+$numRows = count($ret);
+
+// Handle paging, if given.
+if (array_key_exists("start", $_REQUEST)) {
+	$ret = array_slice($ret, $_REQUEST['start']);
+}
+if (array_key_exists("count", $_REQUEST)) {
+	$ret = array_slice($ret, 0, $_REQUEST['count']);
+}
+
+print '/*'.json_encode(array('numRows'=>$numRows, 'items'=>$ret, 'identity'=>'id')).'*/';
diff --git a/dojox/data/tests/stores/ServiceStore.js b/dojox/data/tests/stores/ServiceStore.js
new file mode 100644
index 0000000..a99431b
--- /dev/null
+++ b/dojox/data/tests/stores/ServiceStore.js
@@ -0,0 +1,161 @@
+dojo.provide("dojox.data.tests.stores.ServiceStore");
+dojo.require("dojox.rpc.Service");
+dojo.require("dojox.rpc.Rest");
+//dojo.require("dojox.data.ClientFilter");
+dojo.require("dojox.data.ServiceStore");
+dojo.require("dojo.data.api.Read");
+dojox.data.tests.stores.ServiceStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	d.errback(errData);	
+}
+var testServices = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.tests.resources", "test.smd"));
+var jsonStore = new dojox.data.ServiceStore({service:testServices.jsonRestStore});
+
+doh.register("dojox.data.tests.stores.ServiceStore", 
+	[
+		{
+			name: "Fetch some items",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on ServiceStore of a simple query.
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"query", 
+					onComplete: function(items, request){
+						t.is(4, items.length);
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.ServiceStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "fetchItemByIdentity, getValue, getValues, hasAttribute,containsValue, getAttributes, getIdentity",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on ServiceStore of a single item.
+				var d = new doh.Deferred();
+				jsonStore.fetchItemByIdentity({identity:1, 
+					onItem: function(item, request){
+						t.is("Object 1", item.name);
+						t.is("Object 1",jsonStore.getValue(item,"name"));
+						t.t(jsonStore.hasAttribute(item,"name"));
+						t.is(jsonStore.getValues(item,"name").length,1);
+						t.t(jsonStore.isItem(item));
+						t.t(jsonStore.isItemLoaded(item));
+						t.t(jsonStore.containsValue(item,"name","Object 1"));
+						t.f(jsonStore.containsValue(item,"name","Something Else"));
+						t.is(jsonStore.getIdentity(item),1);
+						t.t(dojo.indexOf(jsonStore.getAttributes(item),"name")>-1);
+						t.is("default",jsonStore.getValue(item,"nothing","default"));
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.ServiceStore.error, doh, d)
+				});
+				return d; //Object
+			}
+		},
+		{
+			name: "createLazyItem",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on ServiceStore of a single item.
+				var d = new doh.Deferred();
+				var lazyItem = {
+					_loadObject: function(callback){
+						this.name="loaded";
+						delete this._loadObject;
+						callback(this);
+					}
+				};
+				t.f(jsonStore.isItemLoaded(lazyItem));
+				jsonStore.loadItem({item:lazyItem,onItem:function(){
+					t.t(jsonStore.isItemLoaded(lazyItem));
+					t.is(lazyItem.name,"loaded");
+					d.callback(true);
+				}});
+				return d; //Object
+			}
+		},
+		{
+			name: "lazyItem With Fetch",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				var d = new doh.Deferred();
+				jsonStore.idAttribute = "id";
+				jsonStore.syncMode = true;
+				jsonStore.fetch({query:"query", 
+					onComplete: function(items, request){
+						items[0]._loadObject = function(callback){							
+							jsonStore.fetch({query:this.id,onComplete:callback});
+						}
+						t.t(jsonStore.getValue(items[0],"testArray").length);
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.ServiceStore.error, doh, d)
+				});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_20_Streaming",
+			timeout:	10000, //10 seconds.  Json can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		fetching with paging
+
+				var d = new doh.Deferred();
+				var count = 0;
+
+				function onItem(item, requestObj){
+				  t.assertTrue(typeof item == 'number');
+				  count++;
+				}
+				function onComplete(items, request){
+					t.is(20, count);
+					
+					d.callback(true);
+				}
+				//Get everything...
+				jsonStore.fetch({	
+					query: "bigQuery",
+					onBegin: null,
+					count: 20,
+					onItem: onItem,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.ServiceStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = jsonStore	[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+		}
+	]
+);
+
diff --git a/dojox/data/tests/stores/SnapLogicStore.js b/dojox/data/tests/stores/SnapLogicStore.js
new file mode 100644
index 0000000..557cef0
--- /dev/null
+++ b/dojox/data/tests/stores/SnapLogicStore.js
@@ -0,0 +1,434 @@
+dojo.provide("dojox.data.tests.stores.SnapLogicStore");
+dojo.require("dojox.data.SnapLogicStore");
+dojo.require("dojo.data.api.Read");
+
+dojox.data.tests.stores.SnapLogicStore.pipelineUrl = dojo.moduleUrl("dojox.data.tests", "stores/snap_pipeline.php").toString();
+dojox.data.tests.stores.SnapLogicStore.pipelineSize = 14;
+dojox.data.tests.stores.SnapLogicStore.attributes = ["empno", "ename", "job", "hiredate", "sal", "comm", "deptno"];
+
+dojox.data.tests.stores.SnapLogicStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	d.errback(errData);	
+}
+
+doh.register("dojox.data.tests.stores.SnapLogicStore", 
+	[
+	    {
+			name: "ReadAPI:  Fetch One",
+			timeout:	3000, //3 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch from a SnapLogic pipeline
+				//	description:
+				//		Simple test of a basic fetch from a SnapLogic pipeline
+
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(1, items.length);
+					d.callback(true);
+				}
+				store.fetch({	count: 1,
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, doh, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_10_Streaming",
+			timeout:	3000, //3 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on SnapLogic pipeline.
+				//	description:
+				//		Simple test of a basic fetch on SnapLogic pipeline.
+
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				count = 0;
+
+				function onBegin(size, requestObj){
+					t.assertEqual(dojox.data.tests.stores.SnapLogicStore.pipelineSize, size);
+				}
+				function onItem(item, requestObj){
+					t.assertTrue(store.isItem(item));
+					count++;
+				}
+				function onComplete(items, request){
+					t.assertEqual(10, count);
+					t.assertTrue(items === null);
+					d.callback(true);
+				}
+
+				//Get everything...
+				store.fetch({		onBegin: onBegin,
+									count: 10,
+									onItem: onItem,
+									onComplete: onComplete,
+									onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, t, d)
+								});
+				return d; //Object
+			}
+		},
+	    {
+			name: "ReadAPI:  Fetch Zero",
+			timeout:	3000, //3 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Try fetching 0 records. A count of the items in the pipeline should be returned.
+				//	description:
+				//		Try fetching 0 records. A count of the items in the pipeline should be returned.
+
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				function onBegin(count, request){
+					t.assertEqual(dojox.data.tests.stores.SnapLogicStore.pipelineSize, count);
+					d.callback(true);
+				}
+				store.fetch({	count: 0,
+								onBegin: onBegin, 
+								onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, doh, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  Fetch_Paging",
+			timeout:	3000, //3 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+				//	description:
+				//		Test of multiple fetches on a single result.  Paging, if you will.
+
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				function dumpFirstFetch(items, request){
+					t.assertEqual(request.count, items.length);
+					request.start = dojox.data.tests.stores.SnapLogicStore.pipelineSize / 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					store.fetch(request);
+				}
+
+				function dumpSecondFetch(items, request){
+					t.assertEqual(1, items.length);
+					request.start = 0;
+					request.count = dojox.data.tests.stores.SnapLogicStore.pipelineSize / 2;
+					request.onComplete = dumpThirdFetch;
+					store.fetch(request);
+				}
+
+				function dumpThirdFetch(items, request){
+					t.assertEqual(request.count, items.length);
+					request.count = dojox.data.tests.stores.SnapLogicStore.pipelineSize * 2;
+					request.onComplete = dumpFourthFetch;
+					store.fetch(request);
+				}
+
+				function dumpFourthFetch(items, request){
+					t.assertEqual(dojox.data.tests.stores.SnapLogicStore.pipelineSize, items.length);
+					request.start = Math.floor(3 * dojox.data.tests.stores.SnapLogicStore.pipelineSize / 4);
+					request.count = dojox.data.tests.stores.SnapLogicStore.pipelineSize;
+					request.onComplete = dumpFifthFetch;
+					store.fetch(request);
+				}
+
+				function dumpFifthFetch(items, request){
+					t.assertEqual(dojox.data.tests.stores.SnapLogicStore.pipelineSize - request.start, items.length);
+					request.start = 2;
+					request.count = dojox.data.tests.stores.SnapLogicStore.pipelineSize * 10;
+					request.onComplete = dumpSixthFetch;
+					store.fetch(request);
+				}
+
+				function dumpSixthFetch(items, request){
+					t.assertEqual(dojox.data.tests.stores.SnapLogicStore.pipelineSize - request.start, items.length);
+					d.callback(true);
+				}
+
+				store.fetch({	count: 5, 
+								onComplete: dumpFirstFetch, 
+								onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getLabel",
+			timeout:	3000, //3 seconds
+			runTest: function(t) {
+				//	summary: 
+				//		Test that the label function returns undefined since it's not supported.
+				//	description:
+				//		Test that the label function returns undefined since it's not supported.
+
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var label = store.getLabel(items[0]);
+					t.assertTrue(label === undefined);
+					d.callback(true);
+				}
+				store.fetch({		count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, t, d)
+								});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getLabelAttributes",
+			timeout:	3000, //3 seconds.  
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getLabelAttributes returns null since it's not supported.
+				//	description:
+				//		Simple test of the getLabelAttributes returns null since it's not supported.
+
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				function onComplete(items, request){
+					t.assertEqual(items.length, 1);
+					var labelList = store.getLabelAttributes(items[0]);
+					t.assertTrue(labelList === null);
+					d.callback(true);
+				}
+				store.fetch({		count: 1,
+									onComplete: onComplete, 
+									onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, t, d)
+								});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getValue",
+			timeout:	3000, //3 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.assertEqual(1, items.length);
+					console.debug(items[0]);
+					t.assertTrue(store.getValue(items[0], "empno") === 7369);
+					t.assertTrue(store.getValue(items[0], "ename") === "SMITH,CLERK");
+					console.debug(store.getValue(items[0], "sal"));
+					t.assertTrue(store.getValue(items[0], "sal") == 800.00);
+					console.debug(1);
+					t.assertTrue(store.getValue(items[0], "deptno") === 20);
+					d.callback(true);
+				}
+
+				store.fetch({	count: 1, 
+								onComplete: completedAll, 
+								onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, t, d)});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  getValues",
+			timeout:	3000, //3 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getValue function of the store.
+				//	description:
+				//		Simple test of the getValue function of the store.
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.assertEqual(1, items.length);
+					for(var i = 0; i < dojox.data.tests.stores.SnapLogicStore.attributes.length; ++i){
+						var values = store.getValues(items[0], dojox.data.tests.stores.SnapLogicStore.attributes[i]);
+						t.assertTrue(dojo.isArray(values));
+						t.assertTrue(values[0] === store.getValue(items[0], dojox.data.tests.stores.SnapLogicStore.attributes[i]));
+					}
+					d.callback(true);
+				}
+
+				store.fetch({	count: 1, 
+								onComplete: completedAll, 
+								onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, t, d)});
+				return d;
+			}
+		},
+		{
+			name: "ReadAPI:  isItem",
+			timeout:	3000, //3 seconds. 
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the isItem function of the store
+				//	description:
+				//		Simple test of the isItem function of the store
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				function completedAll(items){
+					t.assertEqual(5, items.length);
+					for(var i=0; i < items.length; i++){
+						t.assertTrue(store.isItem(items[i]));
+					}
+					d.callback(true);
+				}
+
+				//Get everything...
+				store.fetch({	count: 5, 
+								onComplete: completedAll, 
+								onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  hasAttribute",
+			timeout:	3000, //3 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the hasAttribute function of the store
+				//	description:
+				//		Simple test of the hasAttribute function of the store
+
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.assertEqual(1, items.length);
+					t.assertTrue(items[0] !== null);
+					for(var i = 0; i < dojox.data.tests.stores.SnapLogicStore.attributes.length; ++i){
+						t.assertTrue(store.hasAttribute(items[0], dojox.data.tests.stores.SnapLogicStore.attributes[i]));
+					}
+					t.assertTrue(!store.hasAttribute(items[0], "Nothing"));
+					t.assertTrue(!store.hasAttribute(items[0], "Text"));
+
+					//Test that null attributes throw an exception
+					var passed = false;
+					try{
+						store.hasAttribute(items[0], null);
+					}catch (e){
+						passed = true;
+					}
+					t.assertTrue(passed);
+					d.callback(true);
+				}
+
+				//Get one item...
+				store.fetch({	count: 1,
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, t, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  containsValue",
+			timeout:	3000, //3 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the containsValue function of the store
+				//	description:
+				//		Simple test of the containsValue function of the store
+
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.assertEqual(1, items.length);
+					var value = store.getValue(items[0], "LastName");
+					t.assertTrue(store.containsValue(items[0], "LastName", value));
+					d.callback(true);
+				}
+
+				//Get one item...
+				store.fetch({	count: 1,
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, t, d)
+								});
+				return d; //Object
+			}
+		},
+		{
+			name: "ReadAPI:  getAttributes",
+			timeout:	3000, //3 seconds. 
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of the getAttributes function of the store
+				//	description:
+				//		Simple test of the getAttributes function of the store
+
+				var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+				var d = new doh.Deferred();
+				function onComplete(items){
+					t.assertEqual(1, items.length);
+
+					var itemAttributes = store.getAttributes(items[0]);
+					t.assertEqual(dojox.data.tests.stores.SnapLogicStore.attributes.length, itemAttributes.length);
+					for(var i = 0; i < dojox.data.tests.stores.SnapLogicStore.attributes.length; ++i){
+						t.assertTrue(dojo.indexOf(itemAttributes, dojox.data.tests.stores.SnapLogicStore.attributes[i]) !== -1);
+					}
+					d.callback(true);
+				}
+
+				//Get everything...
+				store.fetch({	count: 1, 
+								onComplete: onComplete, 
+								onError: dojo.partial(dojox.data.tests.stores.SnapLogicStore.error, t, d)});
+				return d; //Object
+			}
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var store = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+
+			var features = store.getFeatures(); 
+			var count = 0;
+			for(var i in features){
+				t.assertEqual(i, "dojo.data.api.Read");
+				count++;
+			}
+
+			t.assertEqual(count, 1);
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = new dojox.data.SnapLogicStore({url: dojox.data.tests.stores.SnapLogicStore.pipelineUrl});
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(var i in readApi){
+				if(i.toString().charAt(0) !== '_'){
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = testStore[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);		
diff --git a/dojox/data/tests/stores/WikipediaStore.js b/dojox/data/tests/stores/WikipediaStore.js
new file mode 100644
index 0000000..4d30af4
--- /dev/null
+++ b/dojox/data/tests/stores/WikipediaStore.js
@@ -0,0 +1,449 @@
+dojo.provide("dojox.data.tests.stores.WikipediaStore");
+
+dojo.require("dojox.data.WikipediaStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Identity");
+
+dojox.data.tests.stores.WikipediaStore.getStore = function(){
+	return new dojox.data.WikipediaStore();
+};
+
+dojox.data.tests.stores.WikipediaStore.error = function(t, d, errData){
+	//	summary:
+	//		Our shared error callback
+	d.errback(errData);
+};
+
+doh.register("dojox.data.tests.stores.WikipediaStore",[
+	{
+		name: "ReadAPI: containsValue",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Verify the containsValue method functions correctly.
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			// hopefully Wikipedia doesn't rename the Main Page!
+			ws.fetch({
+				query: { title: "Main Page" },
+				onComplete: function(items, length){
+					t.is(1, items.length);
+					t.t(ws.containsValue(items[0], "title", "Main Page"));
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: fetch (one)",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Test a single page fetch from Wikipedia
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { title: "Main Page" },
+				onItem: function(item, request){
+					t.t(item.title && item.title.length && item.title.length > 0);
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, doh, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: fetch (query 30)",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Test a full text search from Wikipedia
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { action: "query", text: "dojo" },
+				count: 30,
+				onComplete: function(items, request){
+					t.is(30, items.length);
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: fetch (paged)",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Test multiple fetches on a single full text search.
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+			var count = 0;
+
+			ws.fetch({
+				query: { action: "query", text: "dojo" },
+				count: 15,
+				onComplete: function(items, request){
+					t.is(15, items.length);
+					count = items.length;
+					ws.fetch({
+						query: { action: "query", text: "dojo" },
+						start: count+1,
+						count: 15,
+						onComplete: function(items, request){
+							t.is(30, count + items.length);
+							d.callback(true);
+						}
+					});
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: getAttributes",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Verify the getAttributes method functions correctly
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { title: "Main Page" },
+				onComplete: function(items, request){
+					t.is(1, items.length);
+					t.t(ws.isItem(items[0]));
+					t.t(ws.getAttributes(items[0]).length > 0);
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: getLabel",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Test that the store correctly sets a label.
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { action: "query", text: "dojo" },
+				count: 1,
+				onComplete: function(items, request){
+					t.is(1, items.length);
+					t.t(ws.getLabel(items[0]) !== null);
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: getLabelAttributes",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Test that the store correctly enumerates the label attributes.
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { action: "query", text: "dojo" },
+				count: 1,
+				onComplete: function(items, request){
+					t.is(1, items.length);
+					var labels = ws.getLabelAttributes(items[0]);
+					t.t(dojo.isArray(labels));
+					t.is("title", labels[0]);
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: getValue",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Verify that getValue does what it should.
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { title: "Main Page" },
+				onComplete: function(items, request){
+					t.is(1, items.length);
+					var i = items[0];
+					t.t(ws.getValue(i, "text") !== null);
+					t.t(ws.getValue(i, "links") !== null);
+					t.t(ws.getValue(i, "categories") !== null);
+					t.t(ws.getValue(i, "images") !== null);
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: getValues",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Verify that getValues does what it should
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { title: "Main Page" },
+				onComplete: function(items, request){
+					t.is(1, items.length);
+					var i = items[0];
+					t.t(dojo.isArray(ws.getValues(i, "text")));
+					t.t(dojo.isArray(ws.getValues(i, "links")));
+					t.t(dojo.isArray(ws.getValues(i, "categories")));
+					t.t(dojo.isArray(ws.getValues(i, "images")));
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: hasAttribute",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Verify the hasAttribute method
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { title: "Main Page" },
+				onComplete: function(items, request){
+					t.is(1, items.length);
+					var i = items[0];
+					t.t(i !== null);
+					t.t(ws.hasAttribute(i, "title"));
+					t.t(ws.hasAttribute(i, "text"));
+					t.t(ws.hasAttribute(i, "links"));
+					t.t(ws.hasAttribute(i, "categories"));
+					t.t(ws.hasAttribute(i, "images"));
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: isItem",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Verify the isItem method
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { action: "query", text: "dojo" },
+				count: 10,
+				onComplete: function(items, request){
+					t.is(10, items.length);
+					for(var i=0; i<items.length; i++){
+						t.t(ws.isItem(items[i]));
+					}
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: isItemLoaded",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Verify the isItemLoaded method
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { action: "query", text: "dojo" },
+				count: 5,
+				onComplete: function(items, request){
+					t.is(5, items.length);
+					ws.loadItem({
+						item: items[0],
+						onItem: function(loadedItem, loadedRequest){
+							t.t(ws.isItemLoaded(loadedItem));
+							t.f(ws.isItemLoaded(items[1])); // test an invalid item
+							d.callback(true);
+						}
+					});
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "IdentityAPI: getIdentity",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Verify the getIdentity method returns the correct value
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { title: "Main Page" },
+				onComplete: function(items, request){
+					t.is(1, items.length);
+					t.t(ws.isItem(items[0]));
+					t.t(ws.getIdentity(items[0]) === "Main Page");
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "ReadAPI: loadItem",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Verify the loadItem method
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { action: "query", text: "dojo" },
+				count: 5,
+				onComplete: function(items, request){
+					t.is(5, items.length);
+					t.t(ws.isItem(items[0]));
+					t.t(ws.getIdentityAttributes(items[0]).length > 0);
+					ws.loadItem({
+						item: items[0],
+						onItem: function(item, request){
+							t.t(ws.isItem(item));
+							t.t(ws.isItemLoaded(item));
+							d.callback(true);
+						}
+					});
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "IdentityAPI: getIdentityAttributes",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Verify the getIdentityAttributes method functions correctly
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { title: "Main Page" },
+				onComplete: function(items, request){
+					t.is(1, items.length);
+					t.t(ws.isItem(items[0]));
+					t.t(ws.getIdentityAttributes(items[0]).length > 0);
+					d.callback(true);
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	{
+		name: "IdentityAPI: fetchItemByIdentity",
+		timeout: 30000,
+		runTest: function(t) {
+			//	summary:
+			//		Verify the fetchItemByIdentity method works
+			var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+			var d = new doh.Deferred();
+
+			ws.fetch({
+				query: { title: "Main Page" },
+				onComplete: function(items, request){
+					var firstItem = items[0];
+					t.is(1, items.length);
+					t.t(ws.isItem(firstItem));
+					ws.fetchItemByIdentity({
+						identity: "Main Page",
+						onItem: function(item, request){
+							t.t(ws.isItem(item));
+							t.t(ws.getValue(firstItem, "title") === ws.getValue(item, "title"));
+							d.callback(true);
+						}
+					});
+				},
+				onError: dojo.partial(dojox.data.tests.stores.WikipediaStore.error, t, d)
+			});
+			return d;
+		}
+	},
+	
+
+	function testIdentityAPI_getFeatures(t){
+		//	summary:
+		//		Test that the store correctly advertises its capabilities
+		var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+
+		var features = ws.getFeatures();
+		var count = 0;
+		for(var i in features){
+			if(i === "dojo.data.api.Read") count++;
+			if(i === "dojo.data.api.Identity") count++;
+		}
+		t.assertTrue(count === 2);
+	},
+
+	function testIdentityAPI_functionConformance(t){
+		//	summary:
+		//		Tests for Identity API conformance by checking to see that all declared functions are actual functions on the instances.
+		var ws = dojox.data.tests.stores.WikipediaStore.getStore();
+		var identityApi = new dojo.data.api.Identity();
+		var passed = true;
+		for(var i in identityApi){
+			if(i.toString().charAt(0) === '_'){
+				continue;
+			}
+			// check that every function defined in the Identity API is defined on the store
+			if(typeof identityApi[i] === "function"){
+				if(!(typeof ws[i] === "function")){
+					console.log("Error:" + i + " should be a function but is: " + typeof ws[i]);
+					passed = false;
+					break;
+				}
+			}
+		}
+		t.assertTrue(passed);
+	}
+]);
diff --git a/dojox/data/tests/stores/XmlStore.js b/dojox/data/tests/stores/XmlStore.js
new file mode 100644
index 0000000..3f68bca
--- /dev/null
+++ b/dojox/data/tests/stores/XmlStore.js
@@ -0,0 +1,1397 @@
+dojo.provide("dojox.data.tests.stores.XmlStore");
+dojo.require("dojox.data.XmlStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojo.data.api.Write");
+dojo.require("dojo.data.api.Identity");
+
+
+dojox.data.tests.stores.XmlStore.getBooks3Store = function(){
+	return new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books2.xml").toString(), label: "title", keyAttribute: "isbn"});
+};
+
+dojox.data.tests.stores.XmlStore.getBooks2Store = function(){
+	return new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books2.xml").toString(), label: "title"});
+};
+
+dojox.data.tests.stores.XmlStore.getBooks2StorePC = function(){
+	return new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books2.xml").toString(), label: "title", urlPreventCache: false});
+};
+
+dojox.data.tests.stores.XmlStore.getBooksStore = function(){
+	return new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books.xml").toString(), label: "title"});
+};
+
+dojox.data.tests.stores.XmlStore.getCDataTestStore = function(){
+	return new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/cdata_test.xml").toString(), label: "title"});
+};
+
+dojox.data.tests.stores.XmlStore.getGeographyStore = function(){
+	return new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/geography2.xml").toString(), label: "text", keyAttribute: "text", attributeMap: {text: '@text'}, rootItem: "geography"});
+};
+
+doh.register("dojox.data.tests.stores.XmlStore", 
+	[
+		function testReadAPI_fetch_all(t){
+			//	summary: 
+			//		Simple test of fetching all xml items through an XML element called isbn
+			//	description:
+			//		Simple test of fetching all xml items through an XML element called isbn
+			var store = dojox.data.tests.stores.XmlStore.getBooksStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_one(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		{
+			name: "testReadAPI_fetch_paging",
+			timeout: 10000,
+			runTest: function(t){
+				//	summary: 
+				//		Simple test of fetching one xml items through an XML element called isbn
+				//	description:
+				//		Simple test of fetching one xml items through an XML element called isbn
+				var store = dojox.data.tests.stores.XmlStore.getBooksStore();
+				var d = new doh.Deferred();
+	
+				var dumpSixthFetch = function(items, request){
+					t.assertEqual(18, items.length);
+					d.callback(true);
+				};
+
+				var dumpFifthFetch = function(items, request){
+					t.assertEqual(11, items.length);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpSixthFetch;
+					store.fetch(request);
+				};
+
+				var dumpFourthFetch = function(items, request){
+					t.assertEqual(18, items.length);
+					request.start = 9;
+					request.count = 100;
+					request.onComplete = dumpFifthFetch;
+					store.fetch(request);
+				};
+
+				var dumpThirdFetch = function (items, request){
+					t.assertEqual(5, items.length);
+					request.start = 2;
+					request.count = 20;
+					request.onComplete = dumpFourthFetch;
+					store.fetch(request);
+				};
+
+				var dumpSecondFetch = function(items, request){
+					t.assertEqual(1, items.length);
+					request.start = 0;
+					request.count = 5;
+					request.onComplete = dumpThirdFetch;
+					store.fetch(request);
+				};
+
+				var dumpFirstFetch = function(items, request){
+					t.assertEqual(5, items.length);
+					request.start = 3;
+					request.count = 1;
+					request.onComplete = dumpSecondFetch;
+					store.fetch(request);
+				};
+
+				var completed = function(items, request){
+					t.assertEqual(20, items.length);
+					request.start = 1;
+					request.count = 5;
+					request.onComplete = dumpFirstFetch;
+					store.fetch(request);
+				};
+	
+
+				function error(errData, request){
+					 d.errback(errData);
+				}
+
+				store.fetch({onComplete: completed, onError: error});
+				return d; //Object
+			}
+		},
+		function testReadAPI_fetch_pattern0(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"?9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern1(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(4, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B57?"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern1_preventCacheOff(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			//		with preventCache off to test that it doesn't pass it when told not to.
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			//		with preventCache off to test that it doesn't pass it when told not to.
+			var store = dojox.data.tests.stores.XmlStore.getBooks2StorePC();
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(4, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B57?"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern2(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with * pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with * pattern match
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(5, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern_multi(t){
+			//	summary: 
+			//		Simple test of fetching one xml items with a pattern of multiple attrs.
+			//	description:
+			//		Simple test of fetching one xml items with a pattern of multiple attrs.
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B57?", title: "?itle of 3"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern_multiValuedValue(t){
+			//	summary: 
+			//		Simple test of fetching one xml items with a pattern of multiple attrs.
+			//	description:
+			//		Simple test of fetching one xml items with a pattern of multiple attrs.
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{author:"Third Author of 5"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern_caseInsensitive(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case insensitive mode.
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case insensitive mode.
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"?9b574"}, queryOptions: {ignoreCase: true}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_pattern_caseSensitive(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case sensitive mode.
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match and in case sensitive mode.
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"?9B574"}, queryOptions: {ignoreCase: false}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_all_rootItem(t){
+			//	summary: 
+			//		Simple test of fetching all xml items through an XML element called isbn
+			//	description:
+			//		Simple test of fetching all xml items through an XML element called isbn
+			var store = new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books3.xml").toString(), 
+				rootItem:"book"});
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(5, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_withAttrMap_all(t){
+			var store = new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books_isbnAttr.xml").toString(),
+				attributeMap: {"book.isbn": "@isbn"}});
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(5, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				console.debug(error);
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_withAttrMap_one(t){
+			var store = new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books_isbnAttr.xml").toString(),
+				attributeMap: {"book.isbn": "@isbn"}});
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				console.debug(error);
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"2"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_withAttrMap_pattern0(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			var store = new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books_isbnAttr2.xml").toString(), 
+				attributeMap: {"book.isbn": "@isbn"}});
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(3, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"ABC?"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_withAttrMap_pattern1(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			var store = new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books_isbnAttr2.xml").toString(),
+				attributeMap: {"book.isbn": "@isbn"}});
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(5, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_fetch_withAttrMap_pattern2(t){
+			//	summary: 
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			//	description:
+			//		Simple test of fetching one xml items through an XML element called isbn with ? pattern match
+			var store = new dojox.data.XmlStore({url: dojo.moduleUrl("dojox.data.tests", "stores/books_isbnAttr2.xml").toString(), 
+				attributeMap: {"book.isbn": "@isbn"}});
+			var d = new doh.Deferred();                                                             
+			function onComplete(items, request) {
+				t.assertEqual(2, items.length);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"?C*"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testReadAPI_getLabel(t){
+			//	summary: 
+			//		Simple test of the getLabel function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabel function against a store set that has a label defined.
+
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var label = store.getLabel(items[0]);
+				t.assertTrue(label !== null);
+				t.assertEqual("Title of 4", label);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d;
+		},
+		function testReadAPI_getLabelAttributes(t){
+			//	summary: 
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+			//	description:
+			//		Simple test of the getLabelAttributes function against a store set that has a label defined.
+
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request){
+				t.assertEqual(items.length, 1);
+				var labelList = store.getLabelAttributes(items[0]);
+				t.assertTrue(dojo.isArray(labelList));
+				t.assertEqual("title", labelList[0]);
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d;
+		},
+
+		function testReadAPI_getValue(t){
+			//	summary: 
+			//		Simple test of the getValue API
+			//	description:
+			//		Simple test of the getValue API
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.hasAttribute(item,"isbn"));
+				t.assertEqual(store.getValue(item,"isbn"), "A9B574");
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_getValue_cdata(t) {
+			//	summary:
+			//		Simple test of the getValue text() special attribute.
+			//	description:
+			//      Simple test of the getValue text() special attribute.
+			var store = dojox.data.tests.stores.XmlStore.getCDataTestStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				try{
+					t.assertTrue(store.hasAttribute(item,"ids"));
+					t.assertEqual(store.getValue(item,"ids"), "{68d3c190-4b83-11dd-c204-000000000001}17");
+					var title = store.getValue(item, "title");
+					t.assertTrue(store.isItem(title));
+					var titleValue = store.getValue(title, "text()");
+					t.assertEqual("<b>First</b> 3", dojo.trim(titleValue));
+					d.callback(true);
+				} catch (e) {
+					d.errback(e);
+				}
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{ids:"{68d3c190-4b83-11dd-c204-000000000001}17"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testReadAPI_getValues_cdata(t) {
+			//	summary:
+			//		Simple test of the getValues text() special attribute.
+			//	description:
+			//      Simple test of the getValues text() special attribute.
+			var store = dojox.data.tests.stores.XmlStore.getCDataTestStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				try{
+					t.assertTrue(store.hasAttribute(item,"ids"));
+					t.assertEqual(store.getValue(item,"ids"), "{68d3c190-4b83-11dd-c204-000000000001}17");
+					var title = store.getValue(item, "title");
+					t.assertTrue(store.isItem(title));
+					var titleValue = store.getValues(title, "text()");
+					t.assertEqual("<b>First</b> 3", dojo.trim(titleValue[0]));
+					d.callback(true);
+				} catch (e) {
+					d.errback(e);
+				}
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{ids:"{68d3c190-4b83-11dd-c204-000000000001}17"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_getValue_cdata_toString(t) {
+			//	summary:
+			//		Simple test of the getValue and toString of the resulting 'XmlItem' API
+			//	description:
+			//      Simple test of the getValue and toString of the resulting 'XmlItem' API
+			var store = dojox.data.tests.stores.XmlStore.getCDataTestStore();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				try{
+					t.assertTrue(store.hasAttribute(item,"ids"));
+					t.assertEqual(store.getValue(item,"ids"), "{68d3c190-4b83-11dd-c204-000000000001}17");
+					var title = store.getValue(item, "title");
+					t.assertTrue(store.isItem(title));
+					var firstText = title.toString();
+					t.assertEqual("<b>First</b> 3", dojo.trim(firstText));
+					d.callback(true);
+				} catch (e) {
+					d.errback(e);
+				}
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{ids:"{68d3c190-4b83-11dd-c204-000000000001}17"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testReadAPI_getValues(t){
+			 //	summary: 
+			 //		Simple test of the getValues API
+			 //	description:
+			 //		Simple test of the getValues API
+			 var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request) {
+				 t.assertEqual(1, items.length);
+				 var item = items[0];
+				 t.assertTrue(store.hasAttribute(item,"isbn"));
+				 var values = store.getValues(item,"isbn");
+				 t.assertEqual(1,values.length);
+				 t.assertEqual("A9B574", values[0]);
+				 d.callback(true);
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+		function testReadAPI_isItem(t){
+			 //	summary: 
+			 //		Simple test of the isItem API
+			 //	description:
+			 //		Simple test of the isItem API
+			 var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.isItem(item));
+				t.assertTrue(!store.isItem({}));
+				t.assertTrue(!store.isItem("Foo"));
+				t.assertTrue(!store.isItem(1));
+				d.callback(true);
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+		function testReadAPI_isItem_multistore(t){
+			//	summary: 
+			//		Simple test of the isItem API across multiple store instances.
+			//	description:
+			//		Simple test of the isItem API across multiple store instances.
+			var store1 = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			var store2 = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			var d = new doh.Deferred();
+
+			var onError = function(error, request) {
+				d.errback(error);
+			};
+
+			var onComplete1 = function(items, request) {
+				t.assertEqual(1, items.length);
+				var item1 = items[0];
+				t.assertTrue(store1.isItem(item1));
+
+				var onComplete2 = function(items, request) {
+					t.assertEqual(1, items.length);
+					var item2 = items[0];
+					t.assertTrue(store2.isItem(item2));
+					t.assertTrue(!store1.isItem(item2));
+					t.assertTrue(!store2.isItem(item1));
+					d.callback(true);
+				};
+				store2.fetch({query:{isbn:"A9B574"}, onComplete: onComplete2, onError: onError});
+			};
+			store1.fetch({query:{isbn:"A9B574"}, onComplete: onComplete1, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_hasAttribute(t){
+			//	summary: 
+			//		Simple test of the hasAttribute API
+			//	description:
+			//		Simple test of the hasAttribute API
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.hasAttribute(item,"isbn"));
+				t.assertTrue(!store.hasAttribute(item,"bob"));
+				//Verify that XML attributes return false in this case.
+				t.assertTrue(store.hasAttribute(item,"@xmlAttribute"));
+				t.assertFalse(store.hasAttribute(item,"@bogus"));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_containsValue(t){
+			//	summary: 
+			//		Simple test of the containsValue API
+			//	description:
+			//		Simple test of the containsValue API
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"isbn", "A9B574"));
+				t.assertTrue(!store.containsValue(item,"isbn", "bob"));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortDescending(t){
+			//	summary: 
+			//		Simple test of the sorting API in descending order.
+			//	description:
+			//		Simple test of the sorting API in descending order.
+			var store = dojox.data.tests.stores.XmlStore.getBooksStore();
+
+			//Comparison is done as a string type (toString comparison), so the order won't be numeric
+			//So have to compare in 'alphabetic' order.
+			var order = [9,8,7,6,5,4,3,20,2,19,18,17,16,15,14,13,12,11,10,1];
+			
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				console.log("Number of items: " + items.length);
+				t.assertEqual(20, items.length);
+
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(order[i], store.getValue(items[i],"isbn").toString());
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn", descending: true}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortAscending(t){
+			//	summary: 
+			//		Simple test of the sorting API in ascending order.
+			//	description:
+			//		Simple test of the sorting API in ascending order.
+			var store = dojox.data.tests.stores.XmlStore.getBooksStore();
+
+			//Comparison is done as a string type (toString comparison), so the order won't be numeric
+			//So have to compare in 'alphabetic' order.
+			var order = [1,10,11,12,13,14,15,16,17,18,19,2,20,3,4,5,6,7,8,9];
+						
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+				var itemId = 1;
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(order[i], store.getValue(items[i],"isbn").toString());
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn"}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortDescendingNumeric(t){
+			//	summary: 
+			//		Simple test of the sorting API in descending order using a numeric comparator.
+			//	description:
+			//		Simple test of the sorting API in descending order using a numeric comparator.
+			var store = dojox.data.tests.stores.XmlStore.getBooksStore();
+
+			//isbn should be treated as a numeric, not as a string comparison
+			store.comparatorMap = {};
+			store.comparatorMap["isbn"] = function(a, b){
+				var ret = 0;
+				if(parseInt(a.toString(), 10) > parseInt(b.toString(), 10)){
+					ret = 1;
+				}else if(parseInt(a.toString(), 10) < parseInt(b.toString(), 10)){
+					ret = -1;
+				}
+				return ret; //int, {-1,0,1}
+			};
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+                		t.assertEqual(20, items.length);
+                		var itemId = 20;
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(itemId, store.getValue(items[i],"isbn").toString());
+					itemId--;
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn", descending: true}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_sortAscendingNumeric(t){
+			//	summary: 
+			//		Simple test of the sorting API in ascending order using a numeric comparator.
+			//	description:
+			//		Simple test of the sorting API in ascending order using a numeric comparator.
+			var store = dojox.data.tests.stores.XmlStore.getBooksStore();
+
+			//isbn should be treated as a numeric, not as a string comparison
+			store.comparatorMap = {};
+			store.comparatorMap["isbn"] = function(a, b){
+				var ret = 0;
+				if(parseInt(a.toString(), 10) > parseInt(b.toString(), 10)){
+					ret = 1;
+				}else if(parseInt(a.toString(), 10) < parseInt(b.toString(), 10)){
+					ret = -1;
+				}
+				return ret; //int, {-1,0,1}
+			};
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(20, items.length);
+				var itemId = 1;
+				for(var i = 0; i < items.length; i++){
+					t.assertEqual(itemId, store.getValue(items[i],"isbn").toString());
+					itemId++;
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+
+			var sortAttributes = [{attribute: "isbn"}];
+			store.fetch({query:{isbn:"*"}, sort: sortAttributes, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_isItemLoaded(t){
+			//	summary: 
+			//		Simple test of the isItemLoaded API
+			//	description:
+			//		Simple test of the isItemLoaded API
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.isItemLoaded(item));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testReadAPI_getFeatures(t){
+			//	summary: 
+			//		Simple test of the getFeatures function of the store
+			//	description:
+			//		Simple test of the getFeatures function of the store
+
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+			var features = store.getFeatures(); 
+			var count = 0;
+			var i;
+			for(i in features){
+				t.assertTrue((i === "dojo.data.api.Read" || i === "dojo.data.api.Write" || "dojo.data.api.Identity"));
+				count++;
+			}
+			t.assertEqual(3, count);
+		},
+		function testReadAPI_getAttributes(t){
+			//	summary: 
+			//		Simple test of the getAttributes API
+			//	description:
+			//		Simple test of the getAttributes API
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				var attributes = store.getAttributes(item);
+
+				//Should be six, as all items should have tagName, childNodes, and text() special attributes 
+				//in addition to any doc defined ones, which in this case are author, title, and isbn
+				//FIXME:  Figure out why IE returns 5!  Need to get firebug lite working in IE for that.
+				//Suspect it's childNodes, may not be defined if there are no child nodes.
+				for(var i = 0; i < attributes.length; i++){
+					console.log("attribute found: " + attributes[i]);
+				}
+				if(dojo.isIE){
+					t.assertEqual(5,attributes.length);
+				}else{
+					t.assertEqual(6,attributes.length);
+				}
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B577"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_setValue(t){
+			//	summary: 
+			//		Simple test of the setValue API
+			//	description:
+			//		Simple test of the setValue API
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"isbn", "A9B574"));
+				store.setValue(item, "isbn", "A9B574-new");
+				t.assertEqual(store.getValue(item,"isbn").toString(), "A9B574-new");
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_setValues(t){
+			//	summary: 
+			//		Simple test of the setValues API
+			//	description:
+			//		Simple test of the setValues API
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"isbn", "A9B574"));
+				store.setValues(item, "isbn", ["A9B574-new1", "A9B574-new2"]);
+				var values = store.getValues(item,"isbn");
+				t.assertEqual(values[0].toString(), "A9B574-new1");
+				t.assertEqual(values[1].toString(), "A9B574-new2");
+				store.setValues(values[0], "text()", ["A9B574", "-new3"]);
+				t.assertEqual(store.getValue(values[0],"text()").toString(), "A9B574-new3");
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_unsetAttribute(t){
+			//	summary: 
+			//		Simple test of the unsetAttribute API
+			//	description:
+			//		Simple test of the unsetAttribute API
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"isbn", "A9B574"));
+				store.unsetAttribute(item,"isbn");
+				t.assertTrue(!store.hasAttribute(item,"isbn"));
+				t.assertTrue(store.isDirty(item));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_isDirty(t){
+			//	summary: 
+			//		Simple test of the isDirty API
+			//	description:
+			//		Simple test of the isDirty API
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			function onComplete(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"isbn", "A9B574"));
+				store.setValue(item, "isbn", "A9B574-new");
+				t.assertEqual(store.getValue(item,"isbn").toString(), "A9B574-new");
+				t.assertTrue(store.isDirty(item));
+				d.callback(true);
+			}
+			function onError(error, request) {
+				d.errback(error);
+			}
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+		function testWriteAPI_revert(t){
+			//	summary: 
+			//		Simple test of the write revert API
+			//	description:
+			//		Simple test of the write revert API
+			var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			var d = new doh.Deferred();
+			var onError = function(error, request) {
+				d.errback(error);
+			};
+			var onComplete = function(items, request) {
+				t.assertEqual(1, items.length);
+				var item = items[0];
+				t.assertTrue(store.containsValue(item,"isbn", "A9B574"));
+				t.assertTrue(!store.isDirty(item));
+				store.setValue(item, "isbn", "A9B574-new");
+				t.assertEqual(store.getValue(item,"isbn").toString(), "A9B574-new");
+				t.assertTrue(store.isDirty(item));
+				store.revert();
+				
+				//Fetch again to see if it reset the state.
+				var onComplete1 = function(items, request) {
+					t.assertEqual(1, items.length);
+					var item = items[0];
+					t.assertTrue(store.containsValue(item,"isbn", "A9B574"));
+					d.callback(true);
+				};
+				store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete1, onError: onError});
+			};
+			store.fetch({query:{isbn:"A9B574"}, onComplete: onComplete, onError: onError});
+			return d; //Object
+		},
+
+		function testIdentityAPI_getIdentity(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API
+			 //	description:
+			 //		Simple test of the Identity getIdentity API
+			 var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onComplete(items, request) {
+				 t.assertEqual(1, items.length);
+				 var item = items[0];
+				 try {
+					 t.assertTrue(store.containsValue(item,"isbn", "A9B5CC"));
+					 t.assertTrue(store.getIdentity(item) !== null);
+					 d.callback(true);
+				 } catch (e) {
+					 d.errback(e);
+				 }
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetch({query:{isbn:"A9B5CC"}, onComplete: onComplete, onError: onError});
+			 return d; //Object
+		},
+
+		function testIdentityAPI_getIdentityAttributes(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentityAttributes API where it defaults to internal xpath (no keyAttribute)
+			 //	description:
+			 //		Simple test of the Identity getIdentityAttributes API where it defaults to internal xpath (no keyAttribute)
+			 var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				try{
+					t.assertTrue(item !== null);
+					var idAttrs = store.getIdentityAttributes(item);
+					t.assertTrue(idAttrs === null);
+					t.assertEqual("/books[0]/book[4]", store.getIdentity(item));
+					d.callback(true);
+				}catch(e){
+					d.errback(e);
+				}
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetchItemByIdentity({identity: "/books[0]/book[4]", onItem: onItem, onError: onError});
+			 return d; //Object
+		},
+
+		function testIdentityAPI_getIdentityAttributes_usingKeyAttributeIdentity(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentityAttributes API where identity is specified by the keyAttribute param
+			 //	description:
+			 //		Simple test of the Identity getIdentityAttributes API where identity is specified by the keyAttribute param
+			 var store = dojox.data.tests.stores.XmlStore.getBooks3Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				try{
+					t.assertTrue(item !== null);
+					var idAttrs = store.getIdentityAttributes(item);
+					t.assertTrue(idAttrs !== null);
+					t.assertTrue(idAttrs.length === 1);
+					t.assertTrue(idAttrs[0] === "isbn");
+					d.callback(true);
+				}catch(e){
+					d.errback(e);
+				}
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetchItemByIdentity({identity: "A9B574", onItem: onItem, onError: onError});
+			 return d; //Object
+		},
+
+		function testIdentityAPI_fetchItemByIdentity(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API where the store defaults the identity to a xpathlike lookup.
+			 //	description:
+			 //		Simple test of the Identity getIdentity API where the store defaults the identity to a xpathlike lookup.
+			 var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				try{
+					t.assertTrue(item !== null);
+					t.assertEqual("/books[0]/book[4]", store.getIdentity(item));
+					d.callback(true);
+				}catch(e){
+					d.errback(e);
+				}
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetchItemByIdentity({identity: "/books[0]/book[4]", onItem: onItem, onError: onError});
+			 return d; //Object
+		
+		},
+
+		function testIdentityAPI_fetchItemByIdentity2(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API where the store defaults the identity to a xpathlike lookup.
+			 //	description:
+			 //		Simple test of the Identity getIdentity API where the store defaults the identity to a xpathlike lookup.
+			 var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				try{
+					t.assertTrue(item !== null);
+					t.assertEqual("/books[0]/book[0]", store.getIdentity(item));
+					d.callback(true);
+				}catch(e){
+					d.errback(e);
+				}
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetchItemByIdentity({identity: "/books[0]/book[0]", onItem: onItem, onError: onError});
+			 return d; //Object
+		
+		},
+
+		function testIdentityAPI_fetchItemByIdentity3(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API where the store defaults the identity to a xpathlike lookup.
+			 //	description:
+			 //		Simple test of the Identity getIdentity API where the store defaults the identity to a xpathlike lookup.
+			 var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				try{
+					t.assertTrue(item !== null);
+					t.assertEqual("/books[0]/book[2]", store.getIdentity(item));
+					d.callback(true);
+				}catch(e){
+					d.errback(e);
+				}
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetchItemByIdentity({identity: "/books[0]/book[2]", onItem: onItem, onError: onError});
+			 return d; //Object
+		
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_usingKeyAttributeIdentity(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API where identity is specified by the keyAttribute param
+			 //	description:
+			 //		Simple test of the Identity getIdentity API where identity is specified by the keyAttribute param
+			 var store = dojox.data.tests.stores.XmlStore.getBooks3Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				try{
+					t.assertTrue(item !== null);
+					t.assertEqual("A9B574", store.getIdentity(item));
+					d.callback(true);
+				}catch(e){
+					d.errback(e);
+				}
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetchItemByIdentity({identity: "A9B574", onItem: onItem, onError: onError});
+			 return d; //Object
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_usingKeyAttributeIdentity2(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API where identity is specified by the keyAttribute param
+			 //	description:
+			 //		Simple test of the Identity getIdentity API where identity is specified by the keyAttribute param
+			 var store = dojox.data.tests.stores.XmlStore.getBooks3Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				try{
+					t.assertTrue(item !== null);
+					t.assertEqual("A9B57C", store.getIdentity(item));
+					d.callback(true);
+				}catch(e){
+					d.errback(e);
+				}
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetchItemByIdentity({identity: "A9B57C", onItem: onItem, onError: onError});
+			 return d; //Object
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_usingKeyAttributeIdentity3(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API where identity is specified by the keyAttribute param
+			 //	description:
+			 //		Simple test of the Identity getIdentity API where identity is specified by the keyAttribute param
+			 var store = dojox.data.tests.stores.XmlStore.getBooks3Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				try{
+					t.assertTrue(item !== null);
+					t.assertEqual("A9B5CC", store.getIdentity(item));
+					d.callback(true);
+				}catch(e){
+					d.errback(e);
+				}
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetchItemByIdentity({identity: "A9B5CC", onItem: onItem, onError: onError});
+			 return d; //Object
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_usingKeyAttributeIdentity4(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API where identity is specified by the keyAttribute param
+			 //	description:
+			 //		Simple test of the Identity getIdentity API where identity is specified by the keyAttribute param
+			 var store = dojox.data.tests.stores.XmlStore.getGeographyStore();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				try{
+					t.assertTrue(item !== null);
+					t.assertEqual("Mexico City", store.getIdentity(item));
+					d.callback(true);
+				}catch(e){
+					d.errback(e);
+				}
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetchItemByIdentity({identity: "Mexico City", onItem: onItem, onError: onError});
+			 return d; //Object
+		},
+
+
+		function testIdentityAPI_fetchItemByIdentity_fails(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API
+			 //	description:
+			 //		Simple test of the Identity getIdentity API
+			 var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				 t.assertTrue(item === null);
+				 d.callback(true);
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 //In memory stores use dojo query syntax for the identifier.
+			 store.fetchItemByIdentity({identity: "/books[0]/book[200]", onItem: onItem, onError: onError});
+			 return d; //Object
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_fails2(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API
+			 //	description:
+			 //		Simple test of the Identity getIdentity API
+			 var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				 t.assertTrue(item === null);
+				 d.callback(true);
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 //In memory stores use dojo query syntax for the identifier.
+			 store.fetchItemByIdentity({identity: "/books[1]/book[4]", onItem: onItem, onError: onError});
+			 return d; //Object
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_fails3(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API
+			 //	description:
+			 //		Simple test of the Identity getIdentity API
+			 var store = dojox.data.tests.stores.XmlStore.getBooks2Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				 t.assertTrue(item === null);
+				 d.callback(true);
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 //In memory stores use dojo query syntax for the identifier.
+			 store.fetchItemByIdentity({identity: "/books[1]/book[200]", onItem: onItem, onError: onError});
+			 return d; //Object
+		},
+
+		function testIdentityAPI_fetchItemByIdentity_usingKeyAttributeIdentity_fails(t) {
+			 //	summary: 
+			 //		Simple test of the Identity getIdentity API where identity is specified by the keyAttribute param
+			 //	description:
+			 //		Simple test of the Identity getIdentity API where identity is specified by the keyAttribute param
+			 var store = dojox.data.tests.stores.XmlStore.getBooks3Store();
+
+			 var d = new doh.Deferred();
+			 function onItem(item, request) {
+				try{
+					t.assertTrue(item === null);
+					d.callback(true);
+				}catch(e){
+					d.errback(e);
+				}
+			 }
+			 function onError(error, request) {
+				 d.errback(error);
+			 }
+			 store.fetchItemByIdentity({identity: "A9B574_NONEXISTANT", onItem: onItem, onError: onError});
+			 return d; //Object
+		},
+
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.XmlStore.getBooksStore();
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+			var i;
+			for(i in readApi){
+				var member = readApi[i];
+				//Check that all the 'Read' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						console.log("Problem with function: [" + i + "]");
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		},
+		function testWriteAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.XmlStore.getBooksStore();
+			var writeApi = new dojo.data.api.Write();
+			var passed = true;
+			var i;
+			for(i in writeApi){
+				var member = writeApi[i];
+				//Check that all the 'Write' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		},
+		function testIdentityAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test write API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var testStore = dojox.data.tests.stores.XmlStore.getBooksStore();
+			var identityApi = new dojo.data.api.Identity();
+			var passed = true;
+			var i;
+			for(i in identityApi){
+				var member = identityApi[i];
+				//Check that all the 'Write' defined functions exist on the test store.
+				if(typeof member === "function"){
+					var testStoreMember = testStore[i];
+					if(!(typeof testStoreMember === "function")){
+						passed = false;
+						break;
+					}
+				}
+			}
+			t.assertTrue(passed);
+		}
+	]
+);
diff --git a/dojox/data/tests/stores/atom1.xml b/dojox/data/tests/stores/atom1.xml
new file mode 100644
index 0000000..faff9aa
--- /dev/null
+++ b/dojox/data/tests/stores/atom1.xml
@@ -0,0 +1,848 @@
+<?xml version="1.0" encoding="UTF-8"?><feed
+  xmlns="http://www.w3.org/2005/Atom"
+  xmlns:thr="http://purl.org/syndication/thread/1.0"
+  xml:lang="en"
+  xml:base="http://shaneosullivan.wordpress.com/wp-atom.php"
+   >
+	<title type="text">SOS</title>
+	<subtitle type="text">..where the wave finally broke, and rolled back.. Shane O'Sullivan's technical blog</subtitle>
+
+	<updated>2008-01-22T14:32:09Z</updated>
+	<generator uri="http://wordpress.org/" version="MU">WordPress</generator>
+
+	<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com" />
+	<id>http://shaneosullivan.wordpress.com/feed/atom/</id>
+	<link rel="self" type="application/atom+xml" href="http://shaneosullivan.wordpress.com/feed/atom/" />
+
+			<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Using AOL hosted Dojo with your custom code]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/" />
+		<id>http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/</id>
+		<updated>2008-01-22T14:32:09Z</updated>
+		<published>2008-01-22T14:32:09Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="Dojo" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="Javascript" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="Technical" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="aol" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="cross domain" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="open source" />		
+		<summary type="html"><![CDATA[The Dojo Ajax Toolkit is kindly hosted by AOL for the consumption of anyone at all.  This has the advantage of
+
+Reducing the load on your own server
+Speeding up the delivery, as a Content Delivery Network (CDN) is used to ensure that the server is as close as possible to the client, and
+The more people [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/"><![CDATA[<div class='snap_preview'><br /><p>The <a href="http://www.dojotoolkit.org" target="_blank">Dojo Ajax Toolkit</a> is kindly <a href="http://dev.aol.com/dojo" target="_blank">hosted</a> by AOL for the consumption of anyone at all.  This has the advantage of</p>
+
+<ul>
+<li>Reducing the load on your own server</li>
+<li>Speeding up the delivery, as a Content Delivery Network (CDN) is used to ensure that the server is as close as possible to the client, and</li>
+<li>The more people who use this the better, as the same Dojo files will be cached when users move from site to site, as they’ll all be downloading the AOL hosted files.</li>
+<li>Gzip compression as standard, so the files are as small as possible</li>
+</ul>
+<p>Additionally, since release 0.9 onwards, the main Dojo JavaScript file, <i>dojo.js</i>, is always exactly the same, whereas in previous released it changed for every developer who built it.</p>
+<p>However, the problem comes in where you want to use your own custom code with the hosted Dojo code.  This is because the hosted code uses <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/functions-used-everywhere/dojo-require" target="_blank">Dojo’s loading system</a> to  dynamically load the resources needed on the page, and this will read the files from AOL, not your server (as you would expect - it knows nothing about your server).  If you [...]
+
+<p>So, the solution I generally tend to use is to put the AOL <i>dojo.js</i> on every page, and tell Dojo to load any other required files from my own server. To do this, set the <i>baseUrl </i>parameter on the djConfig attribute for the JavaScript file to the folder where Dojo is stored on your server. E.g.</p>
+<p><b><script type=”text/javascript” src=”http://o.aolcdn.com/dojo/1.0.2/dojo/dojo.js” djConfig=”{baseUrl:’/js/dojo/’}”></script></b></p>
+
+<p>Notice here that the file I load is <i>dojo.js</i>, the normal version, not <i>dojo.xd.js</i>, which is the cross domain version capable of loading files from AOL.</p>
+<p>After doing this, you can then include whatever custom built layers you like onto an particular page.  For example, if you have a layer built for the <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-5-dojox/dojox-image/gallery" target="_blank">dojox.image.Gallery</a> widget called  <i>/js/dojo/dojox/image/Gallery-layer.js</i>, you can load it either dynamically:</p>
+<p><b><script type=”text/javascript”>dojo.require(”dojox.image.Gallery-layer.js”);</script></b></p>
+
+<p>or include it via a script tag:</p>
+<p><b><script type=”text/javascript” src=”js/dojo/dojox/image/Gallery-layer.js”></script></b></p>
+<p>and it should work just as if you were using Dojo from your own server. Only of course you are not - AOL is serving up that file, and in many cases users will already have cached that file, speeding up your site quite nicely.</p>
+<p>Another approach is to create a custom namespace, register it with Dojo, and put all your layers in there…. but that’s for another post <img src='http://shaneosullivan.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
+
+<b>Share this post:</b><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2008/1/22/using-aol-hosted-dojo-with-your-custom-code&phase=2" target="_blank" title="Post 'Using AOL hosted Dojo with your custom code">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2008/1/22/using-aol-hosted-dojo-with-your-custom-code&title=Using+AOL+hosted+Dojo+with+your+custom+code" target="_blank" title="Post 'Using AOL hosted D [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/88/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/88/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/88/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/88/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/#comments" thr:count="1"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/feed/atom/" thr:count="1"/>
+		<thr:total>1</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Dojo Demo Engine Update]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/" />
+		<id>http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/</id>
+		<updated>2008-01-12T13:22:38Z</updated>
+		<published>2008-01-07T01:02:43Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Demo Engine" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="demo" /><category scheme="http://shaneosullivan.wordpress.com" term="dijit" /><category scheme="http://shaneosullivan.wordpress.com" term="d [...]
+Features
+Since that post, quite a lot of work has gone into both the features and the content of the demo engine, and the development [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/"><![CDATA[<div class='snap_preview'><br /><p>A short while ago I posted about the demo engine I’m writing for the Dojo Ajax Toolkit. <a href="http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/" target="_blank">Click here</a> to read that post or go to <a href="http://www.skynet.ie/~sos/js/demo/dojo/dojoc/demos/featureexplorer.html" target="_blank">http:// [...]
+
+<p><b>Features</b></p>
+<p><b></b>Since that post, quite a lot of work has gone into both the features and the content of the demo engine, and the development process has solidified nicely.  Some of the features include:</p>
+<ul>
+<li><b>Tree navigation</b>. A <i>dijit.Tree</i> widget, reading from a remote JSON data store is used to navigate the various demos.</li>
+<li><b>Search feature</b>. A <i>dijit.form.ComboBox</i> widget, reading from the same JSON data store as the tree, can be used to dynamically search for demos by matching any part of their name.</li>
+
+<li><b>Theme switcher</b>. A <i>dijit.form.ComboBox</i> widget is used to switch between the CSS styles that Dojo provides.</li>
+<li><b>URL addressability</b>. Using a hash identifier (e.g. <i>#Dojo_Query_By%20Class</i>) in the URL of the demo engine causes it to open that demo when it has finished loading.  For example, if you click <a href="http://www.skynet.ie/~sos/js/demo/dojo/dijit/demos/featureexplorer.html#Dojo_Query_By%20Class" target="_blank">this link</a>, it will open the <i>dojo.query</i> demo showing you how to select nodes by class name. Opening any demo changes the URL in the browser to the URL for  [...]
+
+<li><b>Integrated build process</b>. A simple build script is integrated with the Dojo build process. It builds a JSON data file listing all the existing demos and their respective files. It also builds files with URL links for each demo.</li>
+</ul>
+<p><b>Content</b></p>
+<p>To date, a lot of content has been added.  Many, many widgets in <a href="http://www.skynet.ie/~sos/js/demo/dojo/dijit/demos/featureexplorer.html#Dijit" target="_blank">Dijit</a> and <a href="http://www.skynet.ie/~sos/js/demo/dojo/dijit/demos/featureexplorer.html#Dojox" target="_blank">DojoX<br />
+</a> have have been added, including the majority of the <a href="http://www.skynet.ie/~sos/js/demo/dojo/dijit/demos/featureexplorer.html#Dijit_Form%20Controls" target="_blank">Form Controls</a>.</p>
+
+<p>The latest, pretty cool additions have been the <a href="http://www.skynet.ie/~sos/js/demo/dojo/dijit/demos/featureexplorer.html#Dojo_IO" target="_blank">IO</a> and <a href="http://www.skynet.ie/~sos/js/demo/dojo/dijit/demos/featureexplorer.html#Dojo_Query" target="_blank">dojo.query</a> demos.  These cover things such as:</p>
+<ul>
+<li>Performing a XMLHttpRequest request</li>
+<li>Using an iFrame transport</li>
+<li>Submitting a form asynchronously</li>
+<li>Loading remote JavaScript files from another domain</li>
+<li>Selecting nodes using <a href="http://www.w3.org/TR/REC-CSS2/selector.html" target="_blank">CSS selectors</a> with <a href="http://ajaxian.com/archives/dojoquery-a-css-query-engine" target="_blank">dojo.query</a></li>
+
+<li>Performing operations on the NodeList returned from dojo.query</li>
+<li>Attaching events to the <a href="http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-536297177" target="_blank">NodeList</a> returned from dojo.query</li>
+</ul>
+<p><b>File Naming Scheme</b><br />
+A simple file naming scheme is used to add content to the demo framework. Each folder beneath the root folder represents a demo. Each file in a folder must be named the same as the folder, with five possible extensions. For example, given a folder with the name ‘<b>Button</b>‘, the possible files are:</p>
+<ul>
+
+<li><b>Button.html</b> -  this contains the demo to be displayed. Any JavaScript code inside <script> tags is executed, and any <link type=”text/css”> and <style> tags have their CSS loaded. The executed code is shown in the <i>View</i> tab, and and the source code is shown in the <i>XML</i> tab. The <i><html></i>, <i><head></i> and <i><body></i> tags are not required.</li>
+
+<li><b>Button.js</b> - this contains pure JavaScript code that performs the same operations as Button.html, if applicable. It is not executed however. It is shown in the <i>JS</i> tab.</li>
+<li><b>Button.txt</b> - this contains the text description of the demo. It is loaded above the tabs.</li>
+<li><b>Button.links</b> - this contains a JSON array of URL links.  The build script transforms these links into HTML, and the result is loaded into the <i>Links</i> tab. One neat feature of this is that all links from sub folders are integrated with the parent folder and displayed in a nested structure. Do, for example, clicking on <i>Dijit</i> will show all the links for all widgets in the Dijit project.</li>
+
+<li><b>Button.full.html</b> - this is standalone demo, that is designed to run outside the demo engine. The <i>View</i> tab provides a link to the external file.</li>
+<li><b>sort.txt</b> - this contains a comma separated list of the child folders contained in this folder. It specifies the order in which to display the child demos in the tree. If this file is not specified, then an alphabetical ordering is used.</li>
+</ul>
+<p>All of these files are optional. If a file in a folder does not match this naming scheme, it is assumed to be some kind of resource that the demo needs, such as an image or a JSON data file. In this case, the file can be named whatever you like.</p>
+<p>The tree structure in the demo engine mirrors the folder layout.</p>
+
+<p><b>Still To Do</b></p>
+<p>There remains quite a lot of work ahead.  There are a few bugs remaining, some more cross browser testing is needed, and of course more content is required, particularly the base Dojo package.</p>
+<p>In the relatively near future this should be opened up to the public for development. The Dojo folks are setting up a source control server for community additions, and this demo engine should be part of that. Once that is done, people can start adding all sorts of cool stuff!<br />
+<b>Share this post:</b><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update&phase=2" target="_blank" title="Post 'Dojo Demo Engine Update">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update&title=Dojo+Demo+Engine+Update" target="_blank" title="Post 'Dojo Demo Engine Update">kick it</a>|<a href="mailto:?body=Thought%20you%20might%20like%20this:% [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/87/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/87/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/#comments" thr:count="3"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/feed/atom/" thr:count="3"/>
+		<thr:total>3</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Navigating in an IE Modal Dialog]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/" />
+		<id>http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/</id>
+		<updated>2007-12-31T16:36:21Z</updated>
+		<published>2007-12-31T16:36:21Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Internet Explorer" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" term="modal" />		<summary type="html"><![CDATA[Internet Explorer has a nice feature where a new window can be opened modally using the  [...]
+However, the main limitation of IE Modal Dialogs (other than being non-standard), is that [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/"><![CDATA[<div class='snap_preview'><br /><p>Internet Explorer has a nice feature where a new window can be opened modally using the <a href="http://msdn2.microsoft.com/en-us/library/ms536759.aspx"><i>window.showModalDialog</i></a> function, meaning that the page that opened it cannot be accessed until the new window is closed.  This can be useful in many situations.</p>
+
+<p>However, the main limitation of IE Modal Dialogs (other than being non-standard), is that any hyperlink clicked in a modal dialog causes another, non modal, dialog to be opened, rather than opening the page linked to in the same window, as would happen in a normal pop up window.</p>
+<p>The key to solving this problem is to note that a modal dialog only opens another window when a <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_Methods" target="_blank">GET</a> request is made, not when a <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_Methods" target="_blank">POST</a> request is made.  However, an anchor tag automatically causes a GET request, so the solution is to:</p>
+<ol>
+<li> Catch the click on each anchor tag, cancel it,</li>
+<li>Submit a dynamically created FORM element, with it’s <i>method</i> set to ‘<i>POST’ </i>and it’s <i>action</i> set to the URL of the link clicked.</li>
+
+</ol>
+<p>While it is possible to put a listener on each anchor tag to achieve this, such an approach will not scale well.  Instead, place a listener on the <b>body </b>tag. The example below is done using methods from the <a href="http://www.dojotoolkit.org" target="_blank">Dojo Ajax Toolkit</a>, since that the toolkit I use the most, but you can of course use whatever methods you like to achieve the same result:</p>
+<blockquote><p> <code><script type="text/javascript"><br />
+dojo.addOnLoad(function(){<br />
+dojo.connect(dojo.body(), “onclick”, function(evt) {<br />
+if(evt.target.tagName != “A”) {return true;}<br />
+dojo.stopEvent(evt);<br />
+var form = document.createElement(”form”);<br />
+form.setAttribute(”target”, window.name ? window.name : “SrPopUp”);<br />
+form.setAttribute(”action”, url);<br />
+form.setAttribute(”method”,”POST”);<br />
+document.appendChild(form);<br />
+form.submit();<br />
+return false;<br />
+});<br />
+});<br />
+
+</script></code></p></blockquote>
+<p>This method assumes that you have control over the content of the page being shown in the modal dialog.  It would also make sense to add a similar listener to the body tag for key events, as a user can trigger an anchor tag by tabbing to it and hitting enter.</p>
+<p>Thanks to <a href="http://www.dannyg.com/support/modalFix.html" target="_blank">Danny Goodman</a> and <a href="http://www.dannyg.com/support/SOCmodalWindow.js" target="_blank">Steiner Overbeck Cook</a> for coming up with this solution.<br />
+<b>Share this post:</b><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog&phase=2" target="_blank" title="Post 'Navigating in an IE Modal Dialog">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog&title=Navigating+in+an+IE+Modal+Dialog" target="_blank" title="Post 'Navigating in an IE Modal Dialog">kick it</a>|<a href="mailt [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/86/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/86/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/86/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/86/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/#comments" thr:count="1"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/feed/atom/" thr:count="1"/>
+		<thr:total>1</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[A new Demo engine for Dojo]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/" />
+		<id>http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/</id>
+		<updated>2008-01-12T13:23:15Z</updated>
+		<published>2007-12-04T09:29:16Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="demo" /><category scheme="http://shaneosullivan.wordpress.com" term="dijit" /><category scheme="http://shaneosullivan.wordpress.com" term="documentation" /><category scheme="http://shaneosullivan.wordpress.com" term= [...]
+So, I think to myself, this is exactly what the [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/"><![CDATA[<div class='snap_preview'><br /><p>A couple of weeks ago I saw a cool <a href="http://www.smartclient.com/#_Welcome" target="_blank">demo framework</a> for an Ajax toolkit just released as open source.  It’s a very slick implementation, with a tree listing all the various demos, and a tabbed area showing the implementation, and the widget in practice.</p>
+
+<p>So, I think to myself, this is exactly what the <a href="http://www.dojotoolkit.org/" target="_blank">Dojo Ajax Toolkit</a> is missing!  Cut to today, and I’ve put the first rough cut at the demo framework on the web for people’s perusal.  Check it out at <a href="http://www.skynet.ie/~sos/js/demo/dojo/dojoc/demos/featureexplorer.html" target="_blank">http://www.skynet.ie/~sos/js/demo/dojo/dojoc/demos/featureexplorer.html</a> .</p>
+<p><b>Note: I have written a follow up post <a href="http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/" target="_blank">here</a>.</b></p>
+<p>Some of the features include:</p>
+<ul>
+
+<li>Tree navigation for the demos.  Demos can be nested as deep as required.</li>
+<li>View tab.  This shows the widgets in action.</li>
+<li>HTML tab. This shows how to instantiate the widget using HTML markup.</li>
+<li>JS tab. This shows how to instantiate the widget using JavaScript code.</li>
+<li>Links tab. This shows various hyperlinks to alternate content for that demo, e.g. the <a href="http://dojotoolkit.org/book/dojo-book-0-9-0" target="_blank">Dojo Book</a>.</li>
+<li>Demo description. Gives a text description of the demo.</li>
+<li>Theme selector.  This allows you to change from one CSS theme to another</li>
+<li>Ability to link to standalone demos that open in a new page. This is useful for large demos that show the integration of many widgets together, and may not fit well within the demo framework itself.  See the Dijit/Mail demo for an example of this.</li>
+
+<li>A build system that takes a very simple naming scheme for the demos, and creates a JSON data store that the framework runs off of.  So, whenever a user adds a new demo, they simply have to re-run the build step, and that’s it!  No need for a server side script, so you can run this right off your hard drive.</li>
+</ul>
+<p>This is still very much beta code, and there are a couple of errors floating around, but those will of course be hunted down.  There are also some Internet Explorer issues that I’ll get to soon, so try this in Firefox for now (<b>update Dec 05 2007 - most of these have been solved, with one or two small bugs remaining)</b>.  I’m in discussions to get this into the Dojo toolkit, so that the community at large can start adding in demos.  I’ve put in quite a few already [...]
+<p>If you have any suggestions, please let me know.</p>
+<p><a href="http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/demo-framework/" target="_blank" rel="attachment wp-att-85" title="Demo Framework"><img src="http://shaneosullivan.files.wordpress.com/2007/12/demo_framework.jpg" alt="Demo Framework" /></a><br />
+
+<b>Share this post:</b><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/12/4/a-new-demo-engine-for-dojo&phase=2" target="_blank" title="Post 'A new Demo engine for Dojo">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/12/4/a-new-demo-engine-for-dojo&title=A+new+Demo+engine+for+Dojo" target="_blank" title="Post 'A new Demo engine for Dojo">kick it</a>|<a href="mailto:?body=Thought%20you%20might%20 [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/84/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/84/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/84/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/84/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/#comments" thr:count="3"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/feed/atom/" thr:count="3"/>
+		<thr:total>3</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Upgrading Ubuntu Feisty Fawn (7.04) to Gutsy Gibbon (7.10)]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/" />
+		<id>http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/</id>
+		<updated>2008-01-12T10:26:42Z</updated>
+		<published>2007-10-18T16:11:37Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Gutsy Gibbon" /><category scheme="http://shaneosullivan.wordpress.com" term="Ubuntu" /><category scheme="http://shaneosullivan.wordpress.com" term="open source" />		<summary type="html"><![CDATA[Today I’ve begun the process of upgrading my Ubuntu installation of version 7.04 to version 7.10.  To see my previous tutorial of getting Ubuntu installed on my IBM Thinkpad X41, see http://shaneosullivan.wordpress.com/2007/02/1 [...]
+This post lists whatever issues I found when upgrading, and my solutions to them.  For the official instructions, see https://help.ubuntu.com/community/GutsyUpgrades.
+Third Party software [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/"><![CDATA[<div class='snap_preview'><br /><p>Today I’ve begun the process of upgrading my Ubuntu installation of version 7.04 to version 7.10.  To see my previous tutorial of getting Ubuntu installed on my IBM Thinkpad X41, see <a href="http://shaneosullivan.wordpress.com/2007/02/16/installing-ubuntu-edgy-on-a-thinkpad-x41-tablet/" target="_blank">ht [...]
+
+<p>This post lists whatever issues I found when upgrading, and my solutions to them.  For the official instructions, see <a href="https://help.ubuntu.com/community/GutsyUpgrades" target="_blank">https://help.ubuntu.com/community/GutsyUpgrades</a>.</p>
+<p><b>Third Party software sources cause problems</b></p>
+<p>My first problem was caused by having links to third party software distribution sites.  When running the “<i>update-manager -d</i>” command, I received an error, saying the dbus couldn’t run.</p>
+<p>This was caused by having third party software sources enabled that no longer existed, for whatever reason.</p>
+
+<p>To fix this:</p>
+<ol>
+<li>click <i>“System/Administration/Software Sources”</i></li>
+<li>Click the “<i>Third-Party Software</i>” tab</li>
+<li>Deselect any non-Ubuntu software sources.  You can always reselect them after the upgrade</li>
+
+</ol>
+<p><b>Modifying the software channels gets stuck</b></p>
+<p>When the second step in the “Distribution Upgrade” application is running, that is, the “Modifying the software channels” step, it got stuck downloading files.  It would say</p>
+<p>Downloading file 36 of 97</p>
+<p>and stay at that number for a long time.  This was not a bandwidth issue, it simply stopped.  To fix this</p>
+<ol>
+<li>Click the “<i>Cancel</i>” button.</li>
+
+<li>Run the “<i>update-manager -d</i>” command again.</li>
+<li>Repeat this each time it gets stuck downloading files.  I had to do this four times for it to work completely.</li>
+</ol>
+<p><b>Dual monitors didn’t work correctly</b></p>
+<p>When booted up with an external monitor plugged in, the desktop was fixed at 640 * 480 pixels resolution.  I found someone else with a similar issue at <a href="http://ubuntuforums.org/showthread.php?t=566947" target="_blank">http://ubuntuforums.org/showthread.php?t=566947</a> , but their solution didn’t work for me.  I solved this by:</p>
+
+<ol>
+<li>Unplugging the monitor.</li>
+<li>Restart the machine, and log in.</li>
+<li>Click “<i>System/Administration/Screens and Graphics</i>“</li>
+<li>Click the “<i>Graphics Card</i>” tab.</li>
+
+<li>Click the “<i>Driver</i>” button</li>
+<li>From the “<i>Driver</i>” dropdown list, choose “<i>i810 - Intel Integrated Graphics Chipsets</i>“</li>
+<li>Restart the machine.</li>
+
+</ol>
+<p><b>Compiz has problems with dual monitors</b></p>
+<p>Compiz (the 3D graphics stuff) causes problems and refuses to work at all if I am using dual monitors.  Still working on this one.</p>
+<p><b>Some Eclipse plug-ins no longer work</b></p>
+<p>As a Java developer, I often use the <a href="http://www.eclipse.org" target="_blank">Eclipse</a> development platform.   I include some non-standard plugins in the application, like plugins for Subversion support.  However, when Ubuntu is upgraded to 7.10, the base Eclipse platform in upgraded, but not the non-standard plugins, which stops some of them from working.</p>
+<p><i>Update: actually, this didn’t fix my Eclipse problems, please ignore <img src='http://shaneosullivan.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </i></p>
+
+<p>The solution is to upgrade the plugins in the usual Eclipse manner:</p>
+<ol>
+<li>Open Eclipse</li>
+<li>Click <i>Help/Software Updates/Find and Install</i></li>
+<li>Click <i>Finish</i></li>
+<li>Wait a while…</li>
+</ol>
+
+<p><b>Running low on disk space after upgrade</b></p>
+<p>My laptop was running out of disk space after the install, as it downloaded quite a few packages.  I found a very good blog post on how to clean up your Ubuntu install at <a href="http://www.ubuntugeek.com/cleaning-up-all-unnecessary-junk-files-in-ubuntu.html" target="_blank">http://www.ubuntugeek.com/cleaning-up-all-unnecessary-junk-files-in-ubuntu.html</a>.</p>
+<p>Make sure to read comment #7 also, that alone saved me 1GB.</p>
+<p><span style="font-weight:bold;">Some Thinkpad features no longer work</span></p>
+<p>I found that some things didn’t work that did work before, for example the stylus pen and the middle ’scroller’ button of the mouse.  If this happens, just reapply the settings I describe <a href="http://shaneosullivan.wordpress.com/2007/02/16/ubuntu-on-thinkpad-x41-enabling-thinkpad-specific-components/" target="_blank">here</a>, as the upgrade removed them. This solved the problems for me.</p>
+
+<p><b>Share this post:</b><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-%28704%29-to-gutsy-gibbon-%287.10%29&phase=2" target="_blank" title="Post 'Upgrading Ubuntu Feisty Fawn (704) to Gutsy Gibbon (7.10)">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-%28704%29-to-gutsy-gibbon-%287.10%29&title=Upgrading+Ubuntu+Feisty+Fawn+ [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/82/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/82/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/82/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/82/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/#comments" thr:count="25"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/feed/atom/" thr:count="25"/>
+		<thr:total>25</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Introducing the new Dojo Image Widgets]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/" />
+		<id>http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/</id>
+		<updated>2008-01-08T11:23:13Z</updated>
+		<published>2007-10-13T11:09:13Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="Dojo" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="Flickr" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="Image Gallery" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="Javascript" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="Technical" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="aol" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="cross domain" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="dijit" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="dojo.data" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="dojox" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="dojox.data" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="dojox.image" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="json" />
+		<category scheme="http://shaneosullivan.wordpress.com" term="open source" />
+				<summary type="html"><![CDATA[In previous posts (here for the Dojo 0.4.3 version, here and here), I wrote how I wrote an image gallery for version 0.4.3 of the Dojo Ajax Toolkit, and how I was translating it for the latest version of the toolkit, version 1.0.
+Well, that work is now, finally, complete, and I have to say, I’m [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/"><![CDATA[<div class='snap_preview'><br /><p>In previous posts (<a href="http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/" target="_blank">here for the Dojo 0.4.3 version</a>, <a href="http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/" target="_blank">here</a> and <a href="http://shane [...]
+
+<p>Well, that work is now, finally, complete, and I have to say, I’m pretty damn happy with the results.  The code is now part of the <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-5-dojox/dojox-image" target="_blank">dojox.image</a> project (dojox is the Dojo extensions project, for cool new code that may in the future make it into the core code base if enough people like/want it).</p>
+<p>If you’d like to just see the gallery in action, have a look at the <a href="http://www.skynet.ie/~sos/photos.php" target="_blank">Photos page on my personal website</a>, or see the links at the bottom of the post, otherwise, read on!</p>
+<p><b>Update: changes have been made to the widgets since this post was written, resulting in some badly aligned images. This will be fixed in the next few days. (Oct 25th 2007)</b></p>
+<p><b>Update: issue above has been fixed (Oct 29th 2007)</b></p>
+
+<h2>All For One….</h2>
+<p>The gallery is composed of three widgets:</p>
+<ul>
+<li>dojox.image.<a href="http://dojotoolkit.org/book/dojo-book-0-9/part-5-dojox/dojox-image/thumbnailpicker" target="_blank">ThumbnailPicker</a> - a widget to list many small images in either a horizontal or vertical orientation, scroll through them, and attach click events that other widgets can listen to</li>
+<li>dojox.image.<a href="http://dojotoolkit.org/book/dojo-book-0-9/part-5-dojox/dojox-image/slideshow" target="_blank">SlideShow</a> - a widget that displays one image at a time, and can run a slideshow, changing the images every ‘x’ seconds.</li>
+<li>dojox.image.<a href="http://dojotoolkit.org/book/dojo-book-0-9/part-5-dojox/dojox-image/gallery" target="_blank">Gallery</a> - A wrapper around the ThumbnailPicker, and SlideShow widgets.</li>
+
+</ul>
+<p>Both the ThumbnailPicker and Slideshow widgets can also be used on their own, and have no dependencies on each other.<br />
+<img src="http://dojotoolkit.org/files/gallery_0.jpg" height="515" width="524" /></p>
+<h2>Dojo Data Is Too Cool for School</h2>
+<p>One of the coolest features of all of these widgets is that they all feed off image data provided by the<a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/data-retrieval-dojo-data-0" target="_blank"> dojo.data</a> API.  What this basically means is that each widget can display images from any source, with no modification whatsoever.  You simply pass it a Dojo data store, and is shows the pictures.  Some of the data stores currently in the Dojo toolki [...]
+<ul>
+<li>dojo.data.<a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/what-dojo-data/available-stores/dojo-data-item" target="_blank">ItemFileReadStore</a> - pull in simple JSON data in an array.  You could use this if you simply have a directory of images on your own web server you would like to display</li>
+<li>dojox.data.<a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/using-dojo-data/available-stores/flickr-rest-s" target="_blank">FlickrRestStore</a> (<a href="http://archive.dojotoolkit.org/nightly/checkout/dojox/data/demos/demo_FlickrRestStore.html" target="_blank">demo</a>) - query the Flickr photo sharing website for images.  This is all done on the browser, with no need for any server-side redirects. This is <a href="http://shaneosullivan.wordpress [...]
+
+<li>dojox.data.PicasaStore (<a href="http://archive.dojotoolkit.org/nightly/checkout/dojox/data/demos/demo_PicasaStore.html" target="_blank">demo</a>) - query Google’s Picasa image sharing website for images.  As with the Flickr data store, this is done on the browser, with no need for server side support.</li>
+</ul>
+<p>and many more…..   You can also write your own data store if you so desire, but the ones included in the toolkit should cover almost everything you might need.</p>
+<h2>Gimme, Gimme, Gimme!</h2>
+<p>So, how can I get this, you ask!  Well, you can:</p>
+<ul>
+<li>Have a look at the test pages for the widgets:
+
+<ul>
+<li><a href="http://archive.dojotoolkit.org/nightly/checkout/dojox/image/tests/test_Gallery.html" target="_blank">Test page for ThumbnailPicker</a></li>
+<li><a href="http://archive.dojotoolkit.org/nightly/checkout/dojox/image/tests/test_SlideShow.html">Test page for SlideShow</a></li>
+<li><a href="http://archive.dojotoolkit.org/nightly/checkout/dojox/image/tests/test_Gallery.html" target="_blank">Test page for Gallery</a></li>
+<li><a href="http://archive.dojotoolkit.org/nightly/checkout/dojox/data/demos/demo_FlickrRestStore.html" target="_blank">Demo page for dojox.data.FlickrRestStore</a></li>
+
+<li><a href="http://www.skynet.ie/~sos/photos.php" target="_blank">The Gallery on my personal website</a> - example of using the widget hosted on your own server</li>
+<li><a href="http://kadca.com/site/index.php?/photos" target="_blank">The Gallery on another website</a> - example of using the widget hosted on <a href="http://dev.aol.com/dojo" target="_blank">AOL’s cross domain</a> <a href="http://en.wikipedia.org/wiki/Content_Delivery_Network" target="_blank">CDN</a> network.</li>
+<li><a href="http://www.skynet.ie/~sos/js/demo/dojo/dijit/demos/featureexplorer.html#Dojox_Image" target="_blank">Demo page for all DojoX Image widgets</a></li>
+
+</ul>
+</li>
+<li>Read the documentation (I know!!  Documentation… in Dojo!!)
+<ul>
+<li><a href="http://dojotoolkit.org/book/dojo-book-0-9/part-5-dojox/dojox-image/thumbnailpicker" target="_blank">Doc page for ThumbnailPicker</a></li>
+<li><a href="http://dojotoolkit.org/book/dojo-book-0-9/part-5-dojox/dojox-image/slideshow" target="_blank">Doc page for SlideShow</a></li>
+<li><a href="http://dojotoolkit.org/book/dojo-book-0-9/part-5-dojox/dojox-image/gallery" target="_blank">Doc page for Gallery</a></li>
+
+<li><a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/using-dojo-data/available-stores/dojox-data-fl" target="_blank">Doc page for dojox.data.FlickrRestStore</a></li>
+</ul>
+</li>
+<li>Download the <a href="http://archive.dojotoolkit.org/nightly/" target="_blank">latest nightly archive</a> from Dojo.</li>
+<li><a href="http://dojotoolkit.org/book/dojo-book-0-9/part-4-meta-dojo/get-code-subversion" target="_blank">Check out the code</a> from the Subversion repository.</li>
+<li>Wait for Dojo 1.0 to come out (end of Oct 2007) and download the full release from the main<a href="http://www.dojotoolkit.org" target="_blank"> Dojo website</a>.</li>
+
+</ul>
+<p><b>Update: Dojo 1.0 is now released.  Get it at <a href="http://www.dojotoolkit.org/downloads" target="_blank">http://www.dojotoolkit.org/downloads</a></b><br />
+As always, any and all feedback is welcome.  Also, a big thanks to <a href="http://higginsforpresident.net/" target="_blank">Peter Higgins</a>, owner of the dojox.image project, and <a href="http://www.ibm.com/developerworks/blogs/page/webtwooh?tag=Jared_Jurkiewicz" target="_blank">Jared Jurkiewicz</a>, owner of the dojo.data project, for all their helpful ideas, and for reviewing/committing my code to the Dojo project.<br />
+<b>Share this post:</b><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets&phase=2" target="_blank" title="Post 'Introducing the new Dojo Image Widgets">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets&title=Introducing+the+new+Dojo+Image+Widgets" target="_blank" title="Post 'Introducing the new Dojo Image Widge [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/81/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/81/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/81/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/#comments" thr:count="46"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/feed/atom/" thr:count="46"/>
+		<thr:total>46</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Dojo Grid has landed]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/" />
+		<id>http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/</id>
+		<updated>2007-10-14T21:46:03Z</updated>
+		<published>2007-10-05T13:23:17Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="grid" /><category scheme="http://shaneosullivan.wordpress.com" term="open source" />		<summary type="html"><![CDATA[The previously  announced Dojo Grid has landed in source control, and is in the nightly builds.  It has all sorts of fancy functionality, like support for lazy loading huge da [...]
+Check it out at http://archive.dojotoolkit.org/nightly/checkout/dojox/grid/tests/
+Very cool stuff!
+Update: The Sitepen guys have recently blogged about [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/"><![CDATA[<div class='snap_preview'><br /><p>The <a href="http://ajaxian.com/archives/plugging-in-to-the-dojo-grid" target="_blank">previously </a> <a href="http://sitepen.com/pressReleases.php?item=20070917">announced</a> Dojo Grid has landed in source control, and is in the nightly builds.  It has all sorts of fancy functionality, like support for lazy loading huge data sets, individua [...]
+
+<p>Check it out at <a href="http://archive.dojotoolkit.org/nightly/checkout/dojox/grid/tests/" target="_blank">http://archive.dojotoolkit.org/nightly/checkout/dojox/grid/tests/</a></p>
+<p>Very cool stuff!</p>
+<p><strong>Update: </strong>The Sitepen guys have recently blogged about the grid at <a href="http://www.sitepen.com/blog/2007/10/13/dojo-grid-update/" target="_blank">http://www.sitepen.com/blog/2007/10/13/dojo-grid-update/</a></p>
+<p><strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed&phase=2" target="_blank" title="Post 'Dojo Grid has landed">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed&title=Dojo+Grid+has+landed" target="_blank" title="Post 'Dojo Grid has landed">kick it</a>|<a href="mailto:?body=Thought%20you%20might%20like%20this:%20 [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/80/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/80/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/80/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/#comments" thr:count="0"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/feed/atom/" thr:count="0"/>
+		<thr:total>0</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[A TortoiseSVN replacement for Ubuntu]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/" />
+		<id>http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/</id>
+		<updated>2007-10-04T15:50:50Z</updated>
+		<published>2007-10-04T15:50:50Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Linux" /><category scheme="http://shaneosullivan.wordpress.com" term="Nautilus" /><category scheme="http://shaneosullivan.wordpress.com" term="Subversion" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" term="TortoiseSVN" /><category scheme="http://shaneosullivan.wordpress.com" term="Ubuntu" /><category scheme="http://shaneosullivan.wordpress.c [...]
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/"><![CDATA[<div class='snap_preview'><br /><p>I work on a number of open source projects, and many of them use the <a href="http://subversion.tigris.org/" target="_blank">Subversion</a> version control system to manage their code.  Before <a href="http://shaneosullivan.wordpress.com/2007/02/16/installing-ubuntu-edgy-on-a-thinkpad-x41-tablet/" target="_blank">my switch</a>  [...]
+
+<p>TortoiseSVN is simple to use, very intuitive, and does everything I need from it.  You simply right click on a folder you want to store your checked out files in, give it the URL of the Subversion server, and it checks out the code, updates it, checks it back in (if you have permission), performs file diffs ….. basically everything you need to do is integrated right in with your file browser.</p>
+<p>So, I miss this in Ubuntu, as TortoiseSVN is Windows only.  However, I recently found a replacement, which integrates nicely with Nautilus, the Ubuntu file browser.  While it is not as slick as TortoiseSVN, it works in a very similar way.  You right click on a folder, and have a selection of SVN operations you can perform.</p>
+<p>See <a href="http://marius.scurtescu.com/2005/08/24/nautilus_scripts_for_subversion" target="_blank">http://marius.scurtescu.com/2005/08/24/nautilus_scripts_for_subversion</a> for details.</p>
+<p><img src="http://shaneosullivan.files.wordpress.com/2007/10/nautilussubversionscripts.png?w=615&h=264" alt="Nautilus Subversion Menu" height="264" width="615" /></p>
+<p><img src="http://shaneosullivan.files.wordpress.com/2007/10/nautilussubversionscripts-add.png" alt="Nautilus Subversion Dialog" /></p>
+<p>One thing that is missing from this is the display of icons in the file browser (Nautilus) to inform you of the state of a file - checked out, modified, not added to source control etc.  Another person has developed a solution to this, which unfortunately I have not, yet, been able to get working, but perhaps you will have more luck.</p>
+
+<p>See <a href="http://www.kryogenix.org/days/2006/09/12/extremely-noddy-tortoisesvn-for-the-gnome-desktop" target="_blank">http://www.kryogenix.org/days/2006/09/12/extremely-noddy-tortoisesvn-for-the-gnome-desktop</a> for details on this.<br />
+<strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu&phase=2" target="_blank" title="Post 'A TortoiseSVN replacement for Ubuntu">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu&title=A+TortoiseSVN+replacement+for+Ubuntu" target="_blank" title="Post 'A TortoiseSVN replacement for Ubun [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/77/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/77/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/77/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/#comments" thr:count="3"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/feed/atom/" thr:count="3"/>
+		<thr:total>3</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Querying Flickr with Dojo!]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/" />
+		<id>http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/</id>
+		<updated>2007-09-22T18:26:51Z</updated>
+		<published>2007-09-22T16:10:05Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Flickr" /><category scheme="http://shaneosullivan.wordpress.com" term="Image Gallery" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" [...]
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/"><![CDATA[<div class='snap_preview'><br /><p>I’ve recently submitted a new data store for the <a href="http://www.dojotoolkit.org" target="_blank">Dojo Ajax Toolkit</a> that makes it very simple to query <a href="http://www.flickr.com">Flickr</a> for your and other peoples images.  For those not familiar with Flickr, it is a photo sharing website, one of the most popular on th [...]
+
+<p>While these APIs are extremely useful, however, they are also very complex, with a steep learning curve before you can even get started.  In steps Dojo and their new <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/using-dojo-data" target="_blank">Data API</a> specification, whose stated aim is to have a single unified interface to all data sources, so that users of a data store won’t have to care if they’re reading from a database, fro [...]
+<p>So, long story short, I’ve written an implementation of the Dojo Data APIs to query data from Flickr.  It is part of the <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-5-dojox-extensions-dojo-0" target="_blank">DojoX</a> project, and is called <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/using-dojo-data/available-stores/flickr-rest-s" target="_blank">dojox.data.FlickrRestStore</a>.  It provides quite a few methods of querying for [...]
+<ul>
+<li>By one or more tags, matchine any or all of them</li>
+<li>By user id</li>
+
+<li>By set id</li>
+<li>Full text search</li>
+<li>Sorting on date taken, date published or ‘interestingness’</li>
+</ul>
+<p>FlickrRestStore also performs caching of image data, so if you request the data twice it won’t make a second remote request.</p>
+<p>The store is also designed to be accessed by multiple clients simultaneously.  If two clients request the same data, only one request is made, with both clients being notified of the identical results.</p>
+<p><strong>Examples</strong></p>
+
+<p>I’ve put a fairly comprehensive set of examples in the Dojo book at <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/using-dojo-data/available-stores/flickr-rest-s#examples" target="_blank">http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo<br />
+/using-dojo-data/available-stores/flickr-rest-s#examples  </a>.</p>
+<p>You can see a <a href="http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/data/demos/demo_FlickrRestStore.html" target="_blank">Demo</a> of it running at <a href="http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/data/demos/demo_FlickrRestStore.html" target="_blank">http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/data/demos/demo_FlickrRestStore.html</a> .</p>
+<p>The unit tests cover quite a few cases also, and you can see them at <a href="http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/data/tests/stores/FlickrRestStore.js" target="_blank">http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/data/tests/stores/FlickrRestStore.js</a></p>
+<p>To get the code, you can:</p>
+
+<ul>
+<li>Check out the latest copy of the Dojo toolkit, see the instructions <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-4-meta-dojo/get-code-subversion" target="_blank">here</a>.</li>
+<li>Grab the entire nightly build from <a href="http://archive.dojotoolkit.org/nightly/" target="_blank">http://archive.dojotoolkit.org/nightly/</a></li>
+<li>Wait for release 1.0!</li>
+</ul>
+<p><strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo&phase=2" target="_blank" title="Post 'Querying Flickr with Dojo!">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo&title=Querying+Flickr+with+Dojo%21" target="_blank" title="Post 'Querying Flickr with Dojo!">kick it</a>|<a href="mailto:?body=Thought%2 [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/76/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/76/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/#comments" thr:count="3"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/feed/atom/" thr:count="3"/>
+		<thr:total>3</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Specifying the callback function with the Flickr JSON APIs]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/" />
+		<id>http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/</id>
+		<updated>2007-09-13T09:54:53Z</updated>
+		<published>2007-09-13T09:31:30Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Flickr" /><category scheme="http://shaneosullivan.wordpress.com" term="Image Gallery" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" [...]
+Quite a while ago I [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/"><![CDATA[<div class='snap_preview'><br /><p>Flickr is a photo sharing website that has a very flexible set of <a href="http://en.wikipedia.org/wiki/Api" target="_blank">API</a>s that other applications and websites can use to access the photos it stores. This post shows you how to specify a callback function that Flickr can call to pass your web app [...]
+
+<p>Quite a while ago I looked into the <a href="http://www.flickr.com" target="_blank">Flickr</a> APIs for a website I was writing.  Looking at the service that returns photo data in <a href="http://en.wikipedia.org/wiki/Json" target="_blank">JSON</a> (Javascript Object Notation), I noticed that it did so by calling a predefined function, <em>jsonFlickrApi, </em>passing in the data to that function.  This seemed to be an obvious weak spot, since if more than one widget on a page were acc [...]
+<p>Cut to today.  I’ve been working on a JavaScript data store that operates against the Flickr <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer" target="_blank">REST</a> services for the <a href="http://www.dojotoolkit.org" target="_blank">Dojo Ajax Toolkit</a>, and had another look at the Flickr APIs.  Now, whether I missed it before (doubtful, as I looked specifically for it), or the fine Flickr folk have listened to complaints (very likely), but there is no [...]
+<p>All you have to do is pass a parameter <em>jsoncallback</em> to Flickr, with the name of the function you want to be called with the data, and thats it.</p>
+
+<p>E.g. if I had a function:</p>
+<p>function myCallbackFunction(data) {</p>
+<p>alert(”I received ” + data.photos.photo.length +” photos”);</p>
+<p>}</p>
+<p>I could then specify a <script> element in my HTML page to retrieve the data in a cross site manner (since you can’t make cross site <a href="http://en.wikipedia.org/wiki/XmlHttpRequest" target="_blank">XmlHttpRequest </a>calls), like so:</p>
+
+<p><SCRIPT type=”text/javascript” src=”http://www.flickr.com/services/rest/?format=json&<font color="#ff0000">jsoncallback=myCallbackFunction</font><br />
+&method=flickr.people.getPublicPhotos<br />
+&api_key=8c6803164dbc395fb7131c9d54843627<br />
+&user_id=44153025%40N00&per_page=1″></p>
+
+<p></SCRIPT></p>
+<p>Note the jsoncallback parameter in the <em>src</em> attribute.  This results in JavaScript similar to:</p>
+<p><em>myCallbackFunction<span class="sourceRowText">({”photos”:{”page”:1, “pages”:489, “perpage”:1, “total”:”489″, “photo”:[{”id”:”1352049918″, “owner”:”44153025 at N00″, “secret”:”5636009306″, “server”:”1111″, “farm”:2, “title”:”The Liffey Panorama”, “ispublic”:1,  [...]
+
+<p>being called.</p>
+<p>Thanks Flickr! Nice to see them listening, and continually improving.  This will make web applications built on Flickr much more robust, without the need of ridiculous hackery to get around unnecessarily difficult APIs. See <a href="http://www.flickr.com/services/api/response.json.html" target="_blank">http://www.flickr.com/services/api/response.json.html</a> for the offical info on JSON responses.</p>
+<p>Keep an eye out for my dojox.data.FlickrRestStore being release some day soon!!<br />
+<strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis&phase=2" target="_blank" title="Post 'Specifying the callback function with the Flickr JSON APIs">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis&title=Specifying+the+callback+function+wi [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/75/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/75/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/#comments" thr:count="0"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/feed/atom/" thr:count="0"/>
+		<thr:total>0</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Image Gallery, Slideshow, and Flickr data source for Dojo 0.9]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/" />
+		<id>http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/</id>
+		<updated>2007-09-05T08:32:22Z</updated>
+		<published>2007-09-04T23:32:51Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Image Gallery" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" term="dijit" /><category scheme="http://shaneosullivan.wordpress.com"  [...]
+They were very receptive to the idea, [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/"><![CDATA[<div class='snap_preview'><br /><p>In a previous post (see <a href="http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/" target="_blank">here</a>)  I spoke about how I’d written an Image Gallery widget that worked with <a href="http://www.dojotoolkit.org" target="_blank">Dojo Ajax Toolkit</a> version 0.4.2 an [...]
+
+<p>They were very receptive to the idea, with a few suggestions.  Firstly, rather than having its own method of storing information, it should run off the <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/data-retrieval-dojo-data-0" target="_blank">dojo.data </a>API, and secondly, it should go into the newly created dojox.image project.</p>
+<p>Both of these suggestions were perfectly reasonable, so, cut to a few weeks later and I’ve finished my first pass at converting over the code from 0.4.3 to 0.9.  As the Dojo APIs have changed drastically recently, this was no simple matter, but thats the subject of another blog post.</p>
+<p>The code is not finished (or even checked in) yet, but you can see some examples of it running from test pages.  There are two separate widgets:</p>
+<ul>
+<li>dojox.image.SlideShow - a simple widget that runs a slide show of images, with urls loaded from a dojo.data store.</li>
+<li>dojox.image.ImageGallery - this wraps the SlideShow widget, adding thumbnail views. This is also loaded from a dojo.data store.</li>
+</ul>
+<p>Finally, I’ve implemented a dojo.data store that reads from the <a href="http://www.flickr.com/photos/shaneosullivan" target="_blank">Flickr</a> REST APIs, to pull down lists of photos.  This store is more complex than the existing Flickr store, as it does caching of results, as well as going against a much more flexible  API, meaning that expanding its capabilities later is possible.</p>
+
+<p>Whether or not this goes into dojox or not is still undecided. However, you can see the widgets running using this data store.</p>
+<p>See the test files at <a href="http://www.skynet.ie/~sos/js2/dojox/image/tests/" target="_blank">http://www.skynet.ie/~sos/js2/dojox/image/tests</a>  for examples of this working.</p>
+<p>Note that this is NOT the final code.  It may still be buggy, may look different in the future (it’s pretty basic now), and the code will be cleaned up.  However, if you have any suggestions, please feel free to leave comments on this post.</p>
+<p><strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09&phase=2" target="_blank" title="Post 'Image Gallery, Slideshow, and Flickr data source for Dojo 09">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09&title=Image+Gallery,+Slideshow,+and+ [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/74/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/74/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/74/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/74/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/#comments" thr:count="1"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/feed/atom/" thr:count="1"/>
+		<thr:total>1</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Dojo event performance tip]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/" />
+		<id>http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/</id>
+		<updated>2007-08-23T12:38:36Z</updated>
+		<published>2007-08-23T12:29:08Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" term="dojo.event" /><category scheme="http://shaneosullivan.wordpress.com" term="open source" /><category scheme="http://shaneosullivan.wordpress.co [...]
+
+Listen for an event (or function call) to be triggered on  an object, and when it is to run a custom function, e.g.
+    var alertFn = function() [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/"><![CDATA[<div class='snap_preview'><br /><p>When working with the <a href="http://www.dojotoolkit.org" target="_blank">Dojo Ajax Toolkit</a> and using it’s <em>dojo.event</em> package to listen to DOM and custom events, the two most common approaches are:</p>
+
+<ol>
+<li>Listen for an event (or function call) to be triggered on  an object, and when it is to run a custom function, e.g.<br />
+<strong>    var alertFn = function() {alert(”widget is showing”);};<br />
+dojo.event.connect(myWidget, “onShow”, <font color="#ff0000">alertFn</font>);</strong></li>
+<p>This basically says that when the “onShow” function is called on some widget, called myWidget,  run a function that does a simple alert.  Of course you can do whatever you like inside this function.</p>
+
+<li>Listen for an event (or function call) to be triggered on  an object, and when it is to run a custom function defined in the scope of an object, e.g.<br />
+<strong>    var myObj = {<br />
+alertFn: function() {alert(”widget is showing”);}<br />
+};<br />
+dojo.event.connect(myWidget, “onShow”,<font color="#ff0000">myObj,  “alertFn”</font>);</strong></p>
+<p>This is saying that I have an object called “<font color="#ff0000">myObj</font>“, which has  a function called “<font color="#ff0000">alertFn</font>“, and when the “<font color="#ff0000">onShow</font>” method on “<font color="#ff0000">myWidget</font>” is called, call the “<font color="#ff0000">alertFn</font>” function on “<font color="#ff0000">myObj</font>“.</li>
+
+</ol>
+<p>I’ve found that when working with Dojo version 0.4.2 and 0.4.3, <strong>using the second approach is far far quicker</strong>.  It turns out that internally, if you simply pass an anonymous function to Dojo, it will add that function to an internal structure and do a brute force search on that internal structure to make sure that this function is unique.  This can result in a very significant performance hit - I’ve seen it take up over 50% of the startup time of a page on  [...]
+<p>So, the conclusion is that if you are <em>dojo.event.connect</em>, which is one of the most useful functions in the toolkit, make sure to use four arguments to the function (approach #2 above), rather than just three (approach #1 above).  If necessary, place a simple wrapper around the function as I have shown.<br />
+<strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip&phase=2" target="_blank" title="Post 'Dojo event performance tip">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip&title=Dojo+event+performance+tip" target="_blank" title="Post 'Dojo event performance tip">kick it</a>|<a href="mailto:?body=Thought%20yo [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/73/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/73/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/73/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/73/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/#comments" thr:count="0"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/feed/atom/" thr:count="0"/>
+		<thr:total>0</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Dojo 0.9 released]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/" />
+		<id>http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/</id>
+		<updated>2007-09-04T15:23:50Z</updated>
+		<published>2007-08-22T10:24:51Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" term="dijit" /><category scheme="http://shaneosullivan.wordpress.com" term="open source" />		<summary type="html"><![CDATA[The latest  version of th [...]
+Another big change is the the main [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/"><![CDATA[<div class='snap_preview'><br /><p>The latest  version of the <a href="http://www.dojotoolkit.org" target="_blank">Dojo Ajax Toolkit</a> has just been released into the wild.  Version 0.9 is a very streamlined progression of the toolkit, with many of the less essential features pushed out to another project, DojoX, and the Dojo widgets given their own project, Dijit.</p>
+
+<p>Another big change is the the main JavaScript file in Dojo, dojo.js, is no longer customisable.  It now contains the most common features required by most web developers, and nothing more.  As a result, it is far smaller than previous incarnations, down to ~24k when gzipped.</p>
+<p>Some resources:</p>
+<p>James Burke has written up a very informative post about what exactly is baked into the default build of dojo.js, which you can find at <a href="http://dojotoolkit.org/2007/08/22/dissecting-0-9s-dojo-js" target="_blank">http://dojotoolkit.org/2007/08/22/dissecting-0-9s-dojo-js</a> .  Well worth a read.</p>
+<p>Bill Keese wrote up a guided tour of 0.9 at <a href="http://dojotoolkit.org/2007/08/20/dijit-0-9-guided-tour" target="_blank">http://dojotoolkit.org/2007/08/20/dijit-0-9-guided-tour</a>.</p>
+<p>The Dojo book for version 0.9 can be found at <a href="http://dojotoolkit.org/book/dojo-book-0-9-0" target="_blank">http://dojotoolkit.org/book/dojo-book-0-9-0</a>. It’s almost finished (almost!) as of today, Aug 22 2007.</p>
+
+<p>The Ajaxian post on Dojo 0.9 can be read at <a href="http://ajaxian.com/archives/dojo-09-final-version-released" target="_blank">http://ajaxian.com/archives/dojo-09-final-version-released</a>.</p>
+<p>Download  the toolkit from <a href="http://build.dojotoolkit.org/0.9.0/" target="_blank">http://build.dojotoolkit.org/0.9.0</a>.  This page gives some information on how you can use Dojo from AOL’s hosting servers, so you never have to download it at all.<br />
+<strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released&phase=2" target="_blank" title="Post 'Dojo 0.9 released">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released&title=Dojo+0.9+released" target="_blank" title="Post 'Dojo 0.9 released">kick it</a>|<a href="mailto:?body=Thought%20you%20might%20like%20this:%20http://shaneosulliva [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/72/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/72/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/72/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/72/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/#comments" thr:count="2"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/feed/atom/" thr:count="2"/>
+		<thr:total>2</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Dojo theme browser shows off Dijit widgets]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/" />
+		<id>http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/</id>
+		<updated>2007-11-05T13:45:45Z</updated>
+		<published>2007-08-17T12:18:57Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Rich Text" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" term="dijit" /><category scheme="http://shaneosullivan.wordpress.com" term [...]
+Firstly, it showcases the excellent work the Dijit developers have put into new themeing skins.  There are four [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/"><![CDATA[<div class='snap_preview'><br /><p>The <a href="http://www.dojotoolkit.org" target="_blank">Dojo</a>/<a href="http://dojotoolkit.org/developer/dijit" target="_blank">Dijit</a> (Dojo’s widget project) toolkit has <a href="http://dojotoolkit.org/~bill/0.9/dijit/themes/themeTester.html?theme=tundra" target="_blank">created a page</a> where you can view  [...]
+
+<p>Firstly, it showcases the excellent work the Dijit developers have put into new themeing skins.  There are four themes completed so far, and changing the look of Dojo is now as simple as including a different CSS file on your web page.  All Dijit widgets now run off a single CSS file, rather than each having their own CSS file.</p>
+<p>Secondly, it shows the usage of many of Dijit’s widgets (say that five times in a row! <img src='http://shaneosullivan.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> ).  Many of the demos from the 0.4.* days are gone now, and this is about as comprehensive a demo of Dojo’s widgets as you’re likely to see for a while.  And yes, they are very nice indeed.</p>
+<p>Go to <a href="http://archive.dojotoolkit.org/nightly/dojotoolkit/dijit/themes/themeTester.html" target="_blank">http://archive.dojotoolkit.org/nightly/dojotoolkit/dijit/themes/themeTester.html</a> to see the default theme (<em>tundra</em>) in use.  Click on the “Alternate Themes” tab at the bottom of the page to switch themes to one of the alternate themes.</p>
+
+<p>Enjoy!</p>
+<p><strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets&phase=2" target="_blank" title="Post 'Dojo theme browser shows off Dijit widgets">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets&title=Dojo+theme+browser+shows+off+Dijit+widgets" target="_blank" title="Post 'Dojo th [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/71/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/71/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/71/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/71/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/#comments" thr:count="2"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/feed/atom/" thr:count="2"/>
+		<thr:total>2</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Why is my web page slow? YSlow for Firebug can tell you.]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/" />
+		<id>http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/</id>
+		<updated>2007-07-26T08:28:03Z</updated>
+		<published>2007-07-25T15:08:30Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Firebug" /><category scheme="http://shaneosullivan.wordpress.com" term="Firefox" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" term="tools" />		<summary type="html"><![CDATA[Yahoo have released a very [...]
+However, in addition to the bare numbers, [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/"><![CDATA[<div class='snap_preview'><br /><p>Yahoo have released a <a href="http://developer.yahoo.com/yslow/" target="_blank">very useful extension</a> for <a href="http://www.getfirebug.com" target="_blank">Firebug</a>, which is itself an extension for <a href="http://www.getfirefox.com" target="_blank">Firefox</a>, which can be used to analyze a web p [...]
+
+<p>However, in addition to the bare numbers, it also gives your page a ranking, from zero to a hundred, and offers tips in plain English on you can improve the performance of your page.</p>
+<p>All in all, a very handy little addition to a web developer’s toolkit.</p>
+<p>One caveat is that it is of course not perfect -  I tried to use it on Gmail, and it gave the site a 98% mark (practically impossible to achieve in reality), as the initial page of the Gmail application simply loads a single JavaScript page and not much else.  Therefore, YSlow seems to only analyze content sent down the wire to browser upon page load, and ignores generated content.  However, this does not take away from the fact that it is perfectly suitable for the vast majority of w [...]
+<p>More information available <a href="http://developer.yahoo.com/yslow/" target="_blank">here</a>, or read Ajaxian’s post <a href="http://ajaxian.com/archives/yahoo-announces-yslow-firebug-based-performance-tool" target="_blank">here</a>.<br />
+<strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you&phase=2" target="_blank" title="Post 'Why is my web page slow YSlow for Firebug can tell you.">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you&title=Why+is+my+web+page+slow+YSlow+for+Firebug+can+ [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/68/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/68/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/#comments" thr:count="1"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/feed/atom/" thr:count="1"/>
+		<thr:total>1</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Flickr and Dojo Image Gallery]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/" />
+		<id>http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/</id>
+		<updated>2007-07-19T10:44:19Z</updated>
+		<published>2007-07-03T15:53:33Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Flickr" /><category scheme="http://shaneosullivan.wordpress.com" term="Image Gallery" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" [...]
+For more information, including the code and examples, see http://www.skynet.ie/~sos/ajax/imagegallery.php.
+Some [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/"><![CDATA[<div class='snap_preview'><br /><p>I have created an Image Gallery widget built on <a href="http://www.dojotoolkit.org" target="_blank">Dojo</a> 0.4.3 that integrates nicely with <a href="http://www.flickr.com" target="_blank">Flickr</a>.  The widget it written entirely using JavaScript and CSS as a standalone Dojo widget, and is released under the same open source lic [...]
+
+<p>For more information, including the code and examples, see <a href="http://www.skynet.ie/~sos/ajax/imagegallery.php" target="_blank">http://www.skynet.ie/~sos/ajax/imagegallery.php</a>.</p>
+<p>Some of the features of the widget include:</p>
+<ul>
+<li> 			Pages of thumbnails.</li>
+<li> 			Intelligent pre-loading of images so the images you are looking 			at are loaded first.</li>
+<li> 			Fade effects for transitioning of images</li>
+<li> 			Populated using JSON data - any JSON data, not just Flickr.</li>
+<li> 			Flickr integration - remotely load your Flickr images.</li>
+
+<li> 			Paging through a Flickr collection.</li>
+<li> 			Slideshow</li>
+</ul>
+<p>The widget can be instantiated from both HTML markup and programmatically in JavaScript.</p>
+<p>To view your own Flickr pictures on the widget, without installing it on your own site, go to <a href="http://www.skynet.ie/~sos/ajax/yourpics.php" target="_blank">http://www.skynet.ie/~sos/ajax/yourpics.php</a> .</p>
+<p>There is a discussion thread in the Flickr API group at <a href="http://www.flickr.com/groups/api/discuss/72157600624623643/" target="_blank">http://www.flickr.com/groups/api/discuss/72157600624623643</a>.</p>
+<p>So, why create this widget?  Well, firstly I wanted a JavaScript image gallery that would list thumbnails and allow me to page through Flickr photos.  Also, a slide show would have been nice.  I was surprised to discover that I couldn’t find one that I liked in the twenty or so minutes I spent looking for one.  I found a handy Flash based one, but I wanted a HTML and JavaScript only widget.  So I grabbed Dojo 0.4.3 (my JavaScript library of choice right now) and wrote one.</p>
+
+<p>Here is a screen shot:</p>
+<p><a href="http://www.skynet.ie/~sos/ajax/imagegallery.php" target="_blank"><br />
+<img src="http://farm2.static.flickr.com/1359/704747548_d3062f896a.jpg?v=0" alt="Screenshot" border="0" height="458" width="500" /></a></p>
+<p>The widget has all the features that I personally require at the moment, but will probably evolve as I think of new things to add.  If you have  any suggestions/bug reports, please comment on this post.</p>
+<p><strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery&phase=2" target="_blank" title="Post 'Flickr and Dojo Image Gallery">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery&title=Flickr+and+Dojo+Image+Gallery" target="_blank" title="Post 'Flickr and Dojo Image Gallery">kick it</a>|<a href="mailto: [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/66/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/66/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/66/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/66/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/#comments" thr:count="7"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/feed/atom/" thr:count="7"/>
+		<thr:total>7</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Is Dojo being ignored by developers?]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/" />
+		<id>http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/</id>
+		<updated>2007-06-26T10:18:09Z</updated>
+		<published>2007-06-19T10:36:49Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" term="open source" />		<summary type="html"><![CDATA[The two main areas of interest for me over the last year or two, blog-wise that is, have been t [...]
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/"><![CDATA[<div class='snap_preview'><br /><p>The two main areas of interest for me over the last year or two, blog-wise that is, have been the <a href="http://www.dojotoolkit.org" target="_blank">Dojo</a> <a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29" target="_blank">Ajax</a> toolkit, one of the more popular open source <a href="http://en.wikipedia.org/wiki/ [...]
+
+<p>Due to the fact that my blog is hosted on Wordpress.com, I am provided with very detailed statistics on which blog posts are more popular, what days they are accessed on etc.  Looking at these, a very definite trend has become apparent</p>
+<blockquote><p><strong>While the number of hits received by the Ubuntu blogs remains more or less steady, hits on Dojo blog posts falls dramatically on the weekend.</strong></p></blockquote>
+<p>While this is not an exact measurement by any means, it points to a worrying possibility.  People are obviously working with Ubuntu on their spare time, <a href="http://shaneosullivan.wordpress.com/2007/02/16/ubuntu-on-thinkpad-x41-basic-installation-instructions/" target="_blank">installing it</a>, <a href="http://shaneosullivan.wordpress.com/2007/04/30/ubuntu-on-thinkpad-x41-upgrading-to-feisty-fawn-704/" target="_blank">upgrading</a>, <a href="http://shaneosullivan.wordpress.com/20 [...]
+
+<p>This does not seem to be the case for Dojo.</p>
+<p>Dojo has the backing of many large and small companies, including two I have worked for, my previous employer <a href="http://www.ibm.com" target="_blank">IBM</a>, and my current employer <a href="http://www.curamsoftware.com" target="_blank">Curam</a>. Both of these are attracted to Dojo for a number of reasons, chief among them being it’s good design and wide range of features.  The very large size of the toolkit is not a problem for them (and corporations in general) because  [...]
+<p>However, for hobbyists, this is not the case.  A person might only visit a single page on their website, and a ~200KB overhead for perhaps something simple like a collapsible menu and some fading effects is simply not feasible.  I’ve experienced this recently when writing a <a href="http://www.skynet.ie/~sos" target="_blank">simple website for myself </a>- all I wanted was some fading/sliding effects, but the huge overhead just wasn’t worth it.  And I am a very big support [...]
+
+<p>The Dojo team are working hard on the 0.9 release, which is addressing many of these issues, bringing the base size down to a more manageable  size (at time of writing <a href="http://archive.dojotoolkit.org/nightly/dojotoolkit/dojo/dojo.js" target="_blank">dojo.js</a> is down to 68KB).  I look forward to the day when my site statistics change, when Dojo can stand on the shoulders of many thousands of enthusiastic hackers rather than being held up by a few big corporations.  I really do.</p>
+<p>However, this does not seem to be the case today.  Version 0.9 has a lot of work to do.<br />
+<strong>Share this post: </strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/6/19/is-dojo-being-ignored-by-developers&phase=2" target="_blank" title="Post 'Is Dojo being ignored by developers?">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/6/19/is-dojo-being-ignored-by-developers&title=Is+Dojo+being+ignored+by+developers" target="_blank" title="Post 'Is Dojo being ignored by developers?"> [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/64/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/64/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/64/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/64/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/#comments" thr:count="5"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/feed/atom/" thr:count="5"/>
+		<thr:total>5</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Dojo Charting example to show website statistics]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/" />
+		<id>http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/</id>
+		<updated>2007-06-15T12:38:24Z</updated>
+		<published>2007-06-15T12:35:35Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Dojo" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Technical" /><category scheme="http://shaneosullivan.wordpress.com" term="chart" /><category scheme="http://shaneosullivan.wordpress.com" term="charting" /><category scheme="http://shaneosullivan.wordpress.com" term= [...]
+It’s a modified version of the unit test available with the Dojo toolkit, but used in a specific scenario - in this case, to graph the page impressions for my personal [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/"><![CDATA[<div class='snap_preview'><br /><p>I’ve created an example usage of the <a href="http://www.dojotoolkit.org" target="_blank">Dojo</a> <a href="http://ajaxian.com/archives/dojo-charting-engine-released" target="_blank">Charting</a> engine, which you can find at <a href="http://www.skynet.ie/~sos/pageStats.php" target="_blank">http://www.skynet [...]
+It’s a modified version of the unit test available with the Dojo toolkit, but used in a specific scenario - in this case, to graph the page impressions for my <a href="http://www.skynet.ie/~sos">personal website</a> .  The <a href="http://en.wikipedia.org/wiki/Json" target="_blank">JSON</a> data on the page is dynamically generated by PHP, however all other processing is done in JavaScript.</p>
+
+<p>You can filter the data to show info on any combination of pages, and also use a number of different chart types.</p>
+<p>The code is well documented, so should be easy to follow.<br />
+Some other good examples of using the Dojo Charting engine can be found <a href="http://www.ridgway.co.za/archive/2007/04/13/A-Simple-Dojo-Charting-Example.aspx" target="_blank">here</a> and <a href="http://labs.mackirdy.com/chart/chart4.html" target="_blank">here</a>.<br />
+<strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/6/15/dojo-charting-example-to-show-website-statistics-2&phase=2" target="_blank" title="Post 'Dojo Charting example to show website statistics">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/6/15/dojo-charting-example-to-show-website-statistics-2&title=Dojo+Charting+example+to+show+website+statistics" target="_blan [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/63/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/63/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/63/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/63/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/#comments" thr:count="4"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/feed/atom/" thr:count="4"/>
+		<thr:total>4</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[GreaseMonkey script to add Digg-like links to posts]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/" />
+		<id>http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/</id>
+		<updated>2007-05-23T14:56:07Z</updated>
+		<published>2007-05-22T16:57:02Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Firefox" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="greasemonkey" />		<summary type="html"><![CDATA[I decided today that I wanted to put links at the bottom of each of my blog posts that would allow people to  perform actions on the post, e.g:
+
+Digg it
+Kick it
+Mail it
+Bookmark it on del.icio.us
+Bookmark it on reddit.com
+Bookmark it on live.com
+
+My blog is on Wordpress.com which doesn’t seem to have a plugin that will [...]]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/"><![CDATA[<div class='snap_preview'><br /><p>I decided today that I wanted to put links at the bottom of each of my blog posts that would allow people to  perform actions on the post, e.g:</p>
+
+<ul>
+<li><a href="http://digg.com" target="_blank">Digg </a>it</li>
+<li><a href="http://www.dotnetkicks.com" target="_blank">Kick</a> it</li>
+<li>Mail it</li>
+<li>Bookmark it on <a href="http://del.icio.us" target="_blank">del.icio.us</a></li>
+<li>Bookmark it on <a href="http://reddit.com" target="_blank">reddit.com</a></li>
+
+<li>Bookmark it on <a href="http://favorites.live.com" target="_blank">live.com</a></li>
+</ul>
+<p>My blog is on <a href="http://shaneosullivan.wordpress.com" target="_blank">Wordpress.com</a> which doesn’t seem to have a plugin that will allow me to do this.  So, I got off my ass and wrote a <a href="http://greasemonkey.mozdev.org/" target="_blank">GreaseMonkey</a> Firefox script that’ll do it for me.  You can download this script <a href="http://www.skynet.ie/~sos/misc/wordpresslinker.user.js" target="_blank"></a>by going to <a href="http://userscripts.org/scripts/sho [...]
+
+<p>The links that are inserted are at the bottom of this post.  The script is open source (GPL license), so  take it, play with it, whatever.  If you find any bugs, please let me know by commenting on this post.<br />
+<strong>Share this post:</strong><a href="http://www.digg.com/submit?url=http://shaneosullivan.wordpress.com/2007/5/22/greasemonkey-script-to-add-digg-like-links-to-posts&phase=2" target="_blank" title="Post 'GreaseMonkey script to add Digg-like links to posts">digg it</a>|<a href="http://www.dotnetkicks.com/submit/?url=http://shaneosullivan.wordpress.com/2007/5/22/greasemonkey-script-to-add-digg-like-links-to-posts&title=GreaseMonkey+script+to+add+Digg-like+links+to+posts" targe [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/61/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/61/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/61/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/61/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/#comments" thr:count="8"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/feed/atom/" thr:count="8"/>
+		<thr:total>8</thr:total>
+	</entry>
+		<entry>
+		<author>
+			<name>Shane O'Sullivan</name>
+						<uri>http://shaneosullivan.wordpress.com/</uri>
+					</author>
+		<title type="html"><![CDATA[Article on the square pegs and round holes of desktop and web applications]]></title>
+		<link rel="alternate" type="text/html" href="http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/" />
+		<id>http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/</id>
+		<updated>2007-05-22T08:57:59Z</updated>
+		<published>2007-05-22T08:49:00Z</published>
+		<category scheme="http://shaneosullivan.wordpress.com" term="Ajax" /><category scheme="http://shaneosullivan.wordpress.com" term="Javascript" /><category scheme="http://shaneosullivan.wordpress.com" term="Zimbra" />		<summary type="html"><![CDATA[Bill Higgins of IBM has written a very well thought out article of why web applications should look and act like web applications, and not the desktop variety.  Well worth a read - http://billhiggins.us/weblog/2007/05/17/the-uncanny-valley-of- [...]
+       ]]></summary>
+		<content type="html" xml:base="http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/"><![CDATA[<div class='snap_preview'><br /><p><a href="http://billhiggins.us/weblog/about/" target="_blank">Bill Higgins</a> of IBM has written a very well thought out article of why web applications should look and act like web applications, and not the desktop variety.  Well worth a read - <a href="http://billhiggins.us/weblog/2007/0 [...]
+
+<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/shaneosullivan.wordpress.com/56/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/shaneosullivan.wordpress.com/56/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/shaneosullivan.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/shaneosullivan.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/shaneosu [...]
+		<link rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/#comments" thr:count="0"/>
+		<link rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/feed/atom/" thr:count="0"/>
+		<thr:total>0</thr:total>
+	</entry>
+	</feed>
+
diff --git a/dojox/data/tests/stores/books.html b/dojox/data/tests/stores/books.html
new file mode 100644
index 0000000..8535cec
--- /dev/null
+++ b/dojox/data/tests/stores/books.html
@@ -0,0 +1,118 @@
+<html>
+<head>
+	<title>Books.html</title>
+</head>
+<body>
+<table id="books">
+	<thead>
+		<tr>
+			<th>isbn</th>
+			<th>title</th>
+			<th>author</th>
+		</tr>
+	</thead>
+	<tbody>
+		<tr>
+			<td>1</td>
+			<td>Title of 1</td>
+			<td>Author of 1</td>
+		</tr>
+		<tr>
+			<td>2</td>
+			<td>Title of 2</td>
+			<td>Author of 2</td>
+		</tr>
+		<tr>
+			<td>3</td>
+			<td>Title of 3</td>
+			<td>Author of 3</td>
+		</tr>
+		<tr>
+			<td>4</td>
+			<td>Title of 4</td>
+			<td>Author of 4</td>
+		</tr>
+		<tr>
+			<td>5</td>
+			<td>Title of 5</td>
+			<td>Author of 5</td>
+		</tr>
+		<tr>
+			<td>6</td>
+			<td>Title of 6</td>
+			<td>Author of 6</td>
+		</tr>
+		<tr>
+			<td>7</td>
+			<td>Title of 7</td>
+			<td>Author of 7</td>
+		</tr>
+		<tr>
+			<td>8</td>
+			<td>Title of 8</td>
+			<td>Author of 8</td>
+		</tr>
+		<tr>
+			<td>9</td>
+			<td>Title of 9</td>
+			<td>Author of 9</td>
+		</tr>
+		<tr>
+			<td>10</td>
+			<td>Title of 10</td>
+			<td>Author of 10</td>
+		</tr>
+		<tr>
+			<td>11</td>
+			<td>Title of 11</td>
+			<td>Author of 11</td>
+		</tr>
+		<tr>
+			<td>12</td>
+			<td>Title of 12</td>
+			<td>Author of 12</td>
+		</tr>
+		<tr>
+			<td>13</td>
+			<td>Title of 13</td>
+			<td>Author of 13</td>
+		</tr>
+		<tr>
+			<td>14</td>
+			<td>Title of 14</td>
+			<td>Author of 14</td>
+		</tr>
+		<tr>
+			<td>15</td>
+			<td>Title of 15</td>
+			<td>Author of 15</td>
+		</tr>
+		<tr>
+			<td>16</td>
+			<td>Title of 16</td>
+			<td>Author of 16</td>
+		</tr>
+		<tr>
+			<td>17</td>
+			<td>Title of 17</td>
+			<td>Author of 17</td>
+		</tr>
+		<tr>
+			<td>18</td>
+			<td>Title of 18</td>
+			<td>Author of 18</td>
+		</tr>
+		<tr>
+			<td>19</td>
+			<td>Title of 19</td>
+			<td>Author of 19</td>
+		</tr>
+		<tr>
+			<td>20</td>
+			<td>Title of 20</td>
+			<td>Author of 20</td>
+		</tr>
+	</tbody>
+</table>
+</body>
+</html>
diff --git a/dojox/data/tests/stores/books.xml b/dojox/data/tests/stores/books.xml
new file mode 100644
index 0000000..4c330e6
--- /dev/null
+++ b/dojox/data/tests/stores/books.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<books>
+	<book>
+		<isbn>1</isbn>
+		<title>Title of 1</title>
+		<author>Author of 1</author>
+	</book>
+	<book>
+		<isbn>2</isbn>
+		<title>Title of 2</title>
+		<author>Author of 2</author>
+	</book>
+	<book>
+		<isbn>3</isbn>
+		<title>Title of 3</title>
+		<author>Author of 3</author>
+	</book>
+	<book>
+		<isbn>4</isbn>
+		<title>Title of 4</title>
+		<author>Author of 4</author>
+	</book>
+	<book>
+		<isbn>5</isbn>
+		<title>Title of 5</title>
+		<author>Author of 5</author>
+	</book>
+	<book>
+		<isbn>6</isbn>
+		<title>Title of 6</title>
+		<author>Author of 6</author>
+	</book>
+	<book>
+		<isbn>7</isbn>
+		<title>Title of 7</title>
+		<author>Author of 7</author>
+	</book>
+	<book>
+		<isbn>8</isbn>
+		<title>Title of 8</title>
+		<author>Author of 8</author>
+	</book>
+	<book>
+		<isbn>9</isbn>
+		<title>Title of 9</title>
+		<author>Author of 9</author>
+	</book>
+	<book>
+		<isbn>10</isbn>
+		<title>Title of 10</title>
+		<author>Author of 10</author>
+	</book>
+	<book>
+		<isbn>11</isbn>
+		<title>Title of 11</title>
+		<author>Author of 11</author>
+	</book>
+	<book>
+		<isbn>12</isbn>
+		<title>Title of 12</title>
+		<author>Author of 12</author>
+	</book>
+	<book>
+		<isbn>13</isbn>
+		<title>Title of 13</title>
+		<author>Author of 13</author>
+	</book>
+	<book>
+		<isbn>14</isbn>
+		<title>Title of 14</title>
+		<author>Author of 14</author>
+	</book>
+	<book>
+		<isbn>15</isbn>
+		<title>Title of 15</title>
+		<author>Author of 15</author>
+	</book>
+	<book>
+		<isbn>16</isbn>
+		<title>Title of 16</title>
+		<author>Author of 16</author>
+	</book>
+	<book>
+		<isbn>17</isbn>
+		<title>Title of 17</title>
+		<author>Author of 17</author>
+	</book>
+	<book>
+		<isbn>18</isbn>
+		<title>Title of 18</title>
+		<author>Author of 18</author>
+	</book>
+	<book>
+		<isbn>19</isbn>
+		<title>Title of 19</title>
+		<author>Author of 19</author>
+	</book>
+	<book>
+		<isbn>20</isbn>
+		<title>Title of 20</title>
+		<author>Author of 20</author>
+	</book>
+</books>
diff --git a/dojox/data/tests/stores/books2.html b/dojox/data/tests/stores/books2.html
new file mode 100644
index 0000000..c0b3550
--- /dev/null
+++ b/dojox/data/tests/stores/books2.html
@@ -0,0 +1,43 @@
+<html>
+<head>
+	<title>Books2.html</title>
+</head>
+<body>
+<table id="books2">
+	<thead>
+		<tr>
+			<th>isbn</th>
+			<th>title</th>
+			<th>author</th>
+		</tr>
+	</thead>
+	<tbody>
+		<tr>
+			<td>A9B57C</td>
+			<td>Title of 1</td>
+			<td>Author of 1</td>
+		</tr>
+		<tr>
+			<td>A9B57F</td>
+			<td>Title of 2</td>
+			<td>Author of 2</td>
+		</tr>
+		<tr>
+			<td>A9B577</td>
+			<td>Title of 3</td>
+			<td>Author of 3</td>
+		</tr>
+		<tr>
+			<td>A9B574</td>
+			<td>Title of 4</td>
+			<td>Author of 4</td>
+		</tr>
+		<tr>
+			<td>A9B5CC</td>
+			<td>Title of 5</td>
+			<td>Author of 5</td>
+		</tr>
+	</tbody>
+</table>
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/data/tests/stores/books2.xml b/dojox/data/tests/stores/books2.xml
new file mode 100644
index 0000000..ca0f6ac
--- /dev/null
+++ b/dojox/data/tests/stores/books2.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<books>
+	<book>
+		<isbn>A9B57C</isbn>
+		<title>Title of 1</title>
+		<author>Author of 1</author>
+	</book>
+	<book>
+		<isbn>A9B57F</isbn>
+		<title>Title of 2</title>
+		<author>Author of 2</author>
+	</book>
+	<book>
+		<isbn>A9B577</isbn>
+		<title>Title of 3</title>
+		<author>Author of 3</author>
+	</book>
+	<book xmlAttribute="xmlValue">
+		<isbn>A9B574</isbn>
+		<title>Title of 4</title>
+		<author>Author of 4</author>
+	</book>
+	<book>
+		<isbn>A9B5CC</isbn>
+		<title>Title of 5</title>
+		<author>Author of 5</author>
+		<author>Second Author of 5</author>
+		<author>Third Author of 5</author>
+		<author>Fourth Author of 5</author>
+		<author>Fifth Author of 5</author>
+	</book>
+</books>                                           
diff --git a/dojox/data/tests/stores/books3.html b/dojox/data/tests/stores/books3.html
new file mode 100644
index 0000000..d28f6cc
--- /dev/null
+++ b/dojox/data/tests/stores/books3.html
@@ -0,0 +1,14 @@
+<html>
+<head>
+	<title>Books3.html</title>
+</head>
+<body>
+<ul id="books3">
+	<li>A9B57C - Title of 1 - Author of 1</li>
+	<li>A9B57F - Title of 2 - Author of 2</li>
+	<li>A9B577 - Title of 3 - Author of 3</li>
+	<li>A9B574 - Title of 4 - Author of 4</li>
+	<li>A9B5CC - Title of 5 - Author of 5</li>
+</ul>
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/data/tests/stores/books3.xml b/dojox/data/tests/stores/books3.xml
new file mode 100644
index 0000000..c44b4c3
--- /dev/null
+++ b/dojox/data/tests/stores/books3.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<books>
+	<category>
+		<name>Category 1</name>
+		<book>
+			<isbn>1</isbn>
+			<title>Title of 1</title>
+			<author>Author of 1</author>
+		</book>
+		<book>
+			<isbn>2</isbn>
+			<title>Title of 2</title>
+			<author>Author of 2</author>
+		</book>
+		<book>
+			<isbn>3</isbn>
+			<title>Title of 3</title>
+			<author>Author of 3</author>
+		</book>
+		<book>
+			<isbn>4</isbn>
+			<title>Title of 4</title>
+			<author>Author of 4</author>
+		</book>
+		<book>
+			<isbn>5</isbn>
+			<title>Title of 5</title>
+			<author>Author of 5</author>
+		</book>
+	</category>
+</books>
diff --git a/dojox/data/tests/stores/books3Whitespace.html b/dojox/data/tests/stores/books3Whitespace.html
new file mode 100755
index 0000000..4a42df9
--- /dev/null
+++ b/dojox/data/tests/stores/books3Whitespace.html
@@ -0,0 +1,27 @@
+<html>
+	<head>
+		<title>
+			Books3.html
+		</title>
+	</head>
+	<body>
+		<ul id="books3">
+			<li>
+				A9B57C - Title of 1 - Author of 1
+			</li>
+			<li>
+				A9B57F - Title of 2 - Author of 2
+			</li>
+			<li>
+				A9B577 - Title of 3 - Author of 3
+			</li>
+			<li>
+				A9B574 - Title of 4 - Author of 4
+			</li>
+			<li>
+				A9B5CC - Title of 5 - Author of 5
+			</li>
+		</ul>
+	</body>
+</html>
+
diff --git a/dojox/data/tests/stores/booksWhitespace.html b/dojox/data/tests/stores/booksWhitespace.html
new file mode 100755
index 0000000..25b3ac3
--- /dev/null
+++ b/dojox/data/tests/stores/booksWhitespace.html
@@ -0,0 +1,241 @@
+<title>
+	Books.html
+</title>
+<table id="books">
+	<thead>
+		<tr>
+			<th>
+				isbn
+			</th>
+			<th>
+				title
+			</th>
+			<th>
+				author
+			</th>
+		</tr>
+	</thead>
+	<tbody>
+		<tr>
+			<td>
+				1
+			</td>
+			<td>
+				Title of 1
+			</td>
+			<td>
+				Author of 1
+			</td>
+		</tr>
+		<tr>
+			<td>
+				2
+			</td>
+			<td>
+				Title of 2
+			</td>
+			<td>
+				Author of 2
+			</td>
+		</tr>
+		<tr>
+			<td>
+				3
+			</td>
+			<td>
+				Title of 3
+			</td>
+			<td>
+				Author of 3
+			</td>
+		</tr>
+		<tr>
+			<td>
+				4
+			</td>
+			<td>
+				Title of 4
+			</td>
+			<td>
+				Author of 4
+			</td>
+		</tr>
+		<tr>
+			<td>
+				5
+			</td>
+			<td>
+				Title of 5
+			</td>
+			<td>
+				Author of 5
+			</td>
+		</tr>
+		<tr>
+			<td>
+				6
+			</td>
+			<td>
+				Title of 6
+			</td>
+			<td>
+				Author of 6
+			</td>
+		</tr>
+		<tr>
+			<td>
+				7
+			</td>
+			<td>
+				Title of 7
+			</td>
+			<td>
+				Author of 7
+			</td>
+		</tr>
+		<tr>
+			<td>
+				8
+			</td>
+			<td>
+				Title of 8
+			</td>
+			<td>
+				Author of 8
+			</td>
+		</tr>
+		<tr>
+			<td>
+				9
+			</td>
+			<td>
+				Title of 9
+			</td>
+			<td>
+				Author of 9
+			</td>
+		</tr>
+		<tr>
+			<td>
+				10
+			</td>
+			<td>
+				Title of 10
+			</td>
+			<td>
+				Author of 10
+			</td>
+		</tr>
+		<tr>
+			<td>
+				11
+			</td>
+			<td>
+				Title of 11
+			</td>
+			<td>
+				Author of 11
+			</td>
+		</tr>
+		<tr>
+			<td>
+				12
+			</td>
+			<td>
+				Title of 12
+			</td>
+			<td>
+				Author of 12
+			</td>
+		</tr>
+		<tr>
+			<td>
+				13
+			</td>
+			<td>
+				Title of 13
+			</td>
+			<td>
+				Author of 13
+			</td>
+		</tr>
+		<tr>
+			<td>
+				14
+			</td>
+			<td>
+				Title of 14
+			</td>
+			<td>
+				Author of 14
+			</td>
+		</tr>
+		<tr>
+			<td>
+				15
+			</td>
+			<td>
+				Title of 15
+			</td>
+			<td>
+				Author of 15
+			</td>
+		</tr>
+		<tr>
+			<td>
+				16
+			</td>
+			<td>
+				Title of 16
+			</td>
+			<td>
+				Author of 16
+			</td>
+		</tr>
+		<tr>
+			<td>
+				17
+			</td>
+			<td>
+				Title of 17
+			</td>
+			<td>
+				Author of 17
+			</td>
+		</tr>
+		<tr>
+			<td>
+				18
+			</td>
+			<td>
+				Title of 18
+			</td>
+			<td>
+				Author of 18
+			</td>
+		</tr>
+		<tr>
+			<td>
+				19
+			</td>
+			<td>
+				Title of 19
+			</td>
+			<td>
+				Author of 19
+			</td>
+		</tr>
+		<tr>
+			<td>
+				20
+			</td>
+			<td>
+				Title of 20
+			</td>
+			<td>
+				Author of 20
+			</td>
+		</tr>
+	</tbody>
+</table>
+
diff --git a/dojox/data/tests/stores/books_isbnAttr.xml b/dojox/data/tests/stores/books_isbnAttr.xml
new file mode 100644
index 0000000..b9f3d27
--- /dev/null
+++ b/dojox/data/tests/stores/books_isbnAttr.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<books>
+	<book isbn="1">
+		<title>Title of 1</title>
+		<author>Author of 1</author>
+	</book>
+	<book isbn="2">
+		<title>Title of 2</title>
+		<author>Author of 2</author>
+	</book>
+	<book isbn="3">
+		<title>Title of 3</title>
+		<author>Author of 3</author>
+	</book>
+	<book isbn="4">
+		<title>Title of 4</title>
+		<author>Author of 4</author>
+	</book>
+	<book isbn="5">
+		<title>Title of 5</title>
+		<author>Author of 5</author>
+	</book>
+</books>
diff --git a/dojox/data/tests/stores/books_isbnAttr2.xml b/dojox/data/tests/stores/books_isbnAttr2.xml
new file mode 100644
index 0000000..a6ce005
--- /dev/null
+++ b/dojox/data/tests/stores/books_isbnAttr2.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<books>
+	<book isbn="ABC1">
+		<title>Title of 1</title>
+		<author>Author of 1</author>
+	</book>
+	<book isbn="ABC2">
+		<title>Title of 2</title>
+		<author>Author of 2</author>
+	</book>
+	<book isbn="ABC3">
+		<title>Title of 3</title>
+		<author>Author of 3</author>
+	</book>
+	<book isbn="ACB4">
+		<title>Title of 4</title>
+		<author>Author of 4</author>
+	</book>
+	<book isbn="ACF5">
+		<title>Title of 5</title>
+		<author>Author of 5</author>
+	</book>
+</books>
diff --git a/dojox/data/tests/stores/cdata_test.xml b/dojox/data/tests/stores/cdata_test.xml
new file mode 100755
index 0000000..a9cba1f
--- /dev/null
+++ b/dojox/data/tests/stores/cdata_test.xml
@@ -0,0 +1,12 @@
+<problems>
+	<problem>
+		<ids>{68d3c190-4b83-11dd-c204-000000000001}17</ids>
+		<title><![CDATA[ <b>First</b> 3]]></title>
+		<referencename>Problem</referencename>
+	</problem>
+	<problem>
+		<ids>{78d3c190-4b83-11dd-c204-000000000000}17</ids>
+		<title><![CDATA[ <b>Second</b> 3]]></title>
+		<referencename>Problem</referencename>
+	</problem>
+</problems>
diff --git a/dojox/data/tests/stores/cdf1.xml b/dojox/data/tests/stores/cdf1.xml
new file mode 100755
index 0000000..7fa6e36
--- /dev/null
+++ b/dojox/data/tests/stores/cdf1.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data jsxassignids="1" jsxid="jsxroot">
+  <record name="myA" jsxtext="A" jsxid="1" a1="v1" a2="v2" a3="v3"/>
+  <record name="myB" jsxtext="B" jsxid="2"/>
+  <record name="myC" jsxtext="C"/>
+  <record name="myD" jsxtext="D" jsxid="4" a1="{prop1}" a2="{prop2}" jsxtip="{prop3}" a4="{prop4"/>
+  <record name="myE" jsxtext="E"/>
+  <group  name="myGroup" jsxid="group">
+	  <record name="myGE" jsxtext="GE" jsxid="5"/>
+	  <record name="myGF" jsxtext="GF" jsxid="6"/>
+  </group>
+  <group  name="mySecondGroup" jsxid="group2">
+	  <record name="myGG" jsxtext="GG" jsxid="7"/>
+	  <record name="myGH" jsxtext="GH" jsxid="8"/>
+  </group>
+</data>
diff --git a/dojox/data/tests/stores/countries.json b/dojox/data/tests/stores/countries.json
new file mode 100755
index 0000000..9946d25
--- /dev/null
+++ b/dojox/data/tests/stores/countries.json
@@ -0,0 +1,12 @@
+{} && { "identifier": "abbr",
+  "label": "name", 
+  "items": [
+	{ "abbr":"ec", "name":"Ecuador",           "capital":"Quito" },
+	{ "abbr":"eg", "name":"Egypt",             "capital":"Cairo" },
+	{ "abbr":"sv", "name":"El Salvador",       "capital":"San Salvador" },
+	{ "abbr":"gq", "name":"Equatorial Guinea", "capital":"Malabo" },
+	{ "abbr":"er", "name":"Eritrea",           "capital":"Asmara" },
+	{ "abbr":"ee", "name":"Estonia",           "capital":"Tallinn" },
+	{ "abbr":"et", "name":"Ethiopia",          "capital":"Addis Ababa" }
+]}
+
diff --git a/dojox/data/tests/stores/countries_withNull.json b/dojox/data/tests/stores/countries_withNull.json
new file mode 100755
index 0000000..a0a7a3f
--- /dev/null
+++ b/dojox/data/tests/stores/countries_withNull.json
@@ -0,0 +1,10 @@
+{ identifier: 'abbr', 
+  items: [
+	{ abbr:'ec', name:null,                capital:'Quito' },
+	{ abbr:'eg', name:null,                capital:'Cairo' },
+	{ abbr:'sv', name:'El Salvador',       capital:'San Salvador' },
+	{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo' },
+	{ abbr:'er', name:'Eritrea',           capital:'Asmara' },
+	{ abbr:'ee', name:null,                capital:'Tallinn' },
+	{ abbr:'et', name:'Ethiopia',          capital:'Addis Ababa' }
+]}
diff --git a/dojox/data/tests/stores/empty.csv b/dojox/data/tests/stores/empty.csv
new file mode 100644
index 0000000..8dcdaee
--- /dev/null
+++ b/dojox/data/tests/stores/empty.csv
@@ -0,0 +1 @@
+Title, Year, Producer
diff --git a/dojox/data/tests/stores/explore_ItemFileWriteStore.html b/dojox/data/tests/stores/explore_ItemFileWriteStore.html
new file mode 100644
index 0000000..35c61f7
--- /dev/null
+++ b/dojox/data/tests/stores/explore_ItemFileWriteStore.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Store Explorer</title>
+    	<style type="text/css">
+		@import "../../../grid/resources/Grid.css";
+		@import "../../../grid/resources/tundraGrid.css";
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/themes/tundra/tundra.css";
+		@import "../../../../dijit/themes/tundra/tundra_rtl.css";
+		@import "../../../../dijit/tests/css/dijitTests.css";
+		#controls button {
+			margin-left: 10px;
+		}
+		#grid {
+			width: 850px;
+			height: 350px;
+			border: 1px solid silver;
+		}
+		</style>
+    
+    <script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+    <script type="text/javascript">
+    	dojo.require("dojo.data.ItemFileWriteStore");
+    	dojo.require("dojox.data.StoreExplorer");
+    	dojo.require("dojo.parser");		gridLayout = [{
+			defaultCell: { width: 8, editable: true, type: dojox.grid.cells._Widget, styles: 'text-align: right;'  },
+			rows: [
+				{ name: 'Id', field: 'id'}
+			]
+		}];
+    	store = new dojo.data.ItemFileWriteStore({data:
+{ identifier: 'name',
+  label: 'name',
+  items: [
+     { name:'Africa', type:'continent', population:'900 million', area: '30,221,532 sq km',
+        timezone: '-1 UTC to +4 UTC',
+         children:[{_reference:'Egypt'}, {_reference:'Kenya'}, {_reference:'Sudan'}] },
+     { name:'Egypt', type:'country' },
+     { name:'Kenya', type:'country',
+         children:[{_reference:'Nairobi'}, {_reference:'Mombasa'}] },
+     { name:'Nairobi', type:'city' },
+     { name:'Mombasa', type:'city' },
+     { name:'Sudan', type:'country',
+         children:{_reference:'Khartoum'} },
+     { name:'Khartoum', type:'city' },
+     { name:'Asia', type:'continent',
+         children:[{_reference:'China'}, {_reference:'India'}, {_reference:'Russia'}, {_reference:'Mongolia'}] },
+     { name:'China', type:'country' },
+     { name:'India', type:'country' },
+     { name:'Russia', type:'country' },
+     { name:'Mongolia', type:'country' },
+     { name:'Australia', type:'continent', population:'21 million',
+         children:{_reference:'Commonwealth of Australia'}},
+     { name:'Commonwealth of Australia', type:'country', population:'21 million'},
+     { name:'Europe', type:'continent',
+         children:[{_reference:'Germany'}, {_reference:'France'}, {_reference:'Spain'}, {_reference:'Italy'}] },
+     { name:'Germany', type:'country' },
+     { name:'France', type:'country' },
+     { name:'Spain', type:'country' },
+     { name:'Italy', type:'country' },
+     { name:'North America', type:'continent',
+         children:[{_reference:'Mexico'}, {_reference:'Canada'}, {_reference:'United States of America'}] },
+     { name:'Mexico', type:'country',  population:'108 million', area:'1,972,550 sq km',
+         children:[{_reference:'Mexico City'}, {_reference:'Guadalajara'}] },
+     { name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
+     { name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' },
+     { name:'Canada', type:'country',  population:'33 million', area:'9,984,670 sq km',
+         children:[{_reference:'Ottawa'}, {_reference:'Toronto'}] },
+     { name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
+     { name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' },
+     { name:'United States of America', type:'country' },
+     { name:'South America', type:'continent',
+         children:[{_reference:'Brazil'}, {_reference:'Argentina'}] },
+     { name:'Brazil', type:'country', population:'186 million' },
+     { name:'Argentina', type:'country', population:'40 million' }
+]}});
+    </script>
+    <body class="tundra">
+    	<h2>ItemFileWriteStore Explorer</h2>
+		<div dojoType="dojox.data.StoreExplorer" store="store" style="height:500px;width:100%;border:1px solid black" structure="gridLayout"/>
+    </body>
+</html> 
diff --git a/dojox/data/tests/stores/filestore_dojoxdatageo.php b/dojox/data/tests/stores/filestore_dojoxdatageo.php
new file mode 100755
index 0000000..ad10449
--- /dev/null
+++ b/dojox/data/tests/stores/filestore_dojoxdatageo.php
@@ -0,0 +1,178 @@
+<?php
+	//Define the root directory to use for this service.
+	//All file lookups are relative to this path.
+	$rootDir = "../../demos/geography";
+
+	require_once("filestore_funcs.php");
+
+	//Extract the query, if any.
+	$query = false;
+	if (array_key_exists("query", $_GET)) {
+		$query = $_GET['query'];
+		$query = str_replace("\\\"", "\"", $query);
+		$query = json_decode($query, true);
+	}
+	//Extract relevant query options.
+	$queryOptions = json_decode("{}");
+	$deep = false;
+	$ignoreCase = false;
+	if (array_key_exists("queryOptions", $_GET)) {
+		$queryOptions = $_GET['queryOptions'];
+		$queryOptions = str_replace("\\\"", "\"", $queryOptions);
+		$queryOptions = json_decode($queryOptions);
+		if (property_exists($queryOptions, "deep")) {
+			$deep = $queryOptions->deep;
+		}
+		if (property_exists($queryOptions, "ignoreCase")) {
+			$ignoreCase = $queryOptions->ignoreCase;
+		}
+	}
+
+	//Extract non-dojo.data spec config options.
+	$expand = false;
+	$dirsOnly = false;
+	$showHiddenFiles = false;
+	$options = array();
+	if (array_key_exists("options", $_GET)) {
+		$options = $_GET['options'];
+		$options = str_replace("\\\"", "\"", $options);
+		$options = json_decode($options);
+		if (array_search("expand", $options) > -1) {
+			$expand = true;
+		}
+		if (array_search("dirsOnly", $options) > -1) {
+			$dirsOnly = true;
+		}
+		if (array_search("showHiddenFiles", $options) > -1) {
+			$showHiddenFiles = true;
+		}
+	}
+
+	//See if a specific file was requested, or if it is just a query for files.
+	$path = false;
+	if (array_key_exists("path", $_GET)) {
+		$path = $_GET['path'];
+	}
+
+	if (!is_string($path)) {
+
+		$files = array();
+
+		//Handle query for files.  Must try to generate patterns over the query 
+		//attributes.
+		$patterns = array();
+		if (is_array($query)) {
+			//Generate a series of RegExp patterns as necessary.
+			$keys = array_keys($query);
+			$total = count($keys);
+			if ($total > 0) {
+				for ($i = 0; $i < $total; $i++) {
+					$key = $keys[$i];
+					$pattern = $query[$key];
+					if (is_string($pattern)) {
+						$patterns[$key] = patternToRegExp($pattern);
+					}
+				}
+				$files = matchFiles($query, $patterns, $ignoreCase, ".", $rootDir, $deep, $dirsOnly, $expand, $showHiddenFiles);
+			} else {
+				$files = getAllFiles(".",$rootDir,$deep,$dirsOnly,$expand,$showHiddenFiles);
+			}
+		}else{
+			$files = getAllFiles(".",$rootDir,$deep,$dirsOnly,$expand,$showHiddenFiles);
+		}
+
+		$total = count($files);
+
+		//Handle the sorting and paging.
+		$sortSpec = false;
+		if (array_key_exists("sort", $_GET)) {
+			$sortSpec = $_GET['sort'];
+			$sortSpec = str_replace("\\\"", "\"", $sortSpec);
+			$sortSpec = json_decode($sortSpec);
+		}
+
+		if ($sortSpec != null) {
+			$comparator = createComparator($sortSpec);
+			usort($files,array($comparator, "compare"));
+		}
+
+		//Page, if necessary.
+		if (array_key_exists("start", $_GET)) {
+			$start = $_GET['start'];
+			if (!is_numeric($start)) {
+				$start = 0;
+			}
+			$files = array_slice($files, $start);
+		}
+		if (array_key_exists("count", $_GET)) {
+			$count = $_GET['count'];
+			if (!is_numeric($count)) {
+				$count = $total;
+			}
+			$files = array_slice($files, 0, $count);
+		}
+
+		$result;
+		$result->total = $total;
+		$result->items = $files;
+		header("Content-Type", "text/json");
+		print("/* ".json_encode($result)." */");
+	} else {
+		//Query of a specific file (useful for fetchByIdentity and loadItem)
+
+		//Make sure the path isn't trying to walk out of the rooted directory
+		//As defined by $rootDir in the top of the php script.
+		$rootPath = realPath($rootDir);
+		$fullPath = realPath($rootPath."/".$path);
+
+		if ($fullPath !== false) {
+			if (strpos($fullPath,$rootPath) === 0) {
+				//Root the path into the tree cleaner.
+				if (strlen($fullPath) == strlen($rootPath)) {
+					$path = ".";
+				} else {
+					//Fix the path to relative of root and put back into UNIX style (even if windows).
+					$path = substr($fullPath,(strlen($rootPath) + 1),strlen($fullPath));
+					$path = str_replace("\\", "/", $path);
+				}
+
+				if (file_exists($fullPath)) {
+					$arr = split("/", $path);
+					$size = count($arr);
+
+					if ($size > 0) {
+						$fName = $arr[$size - 1];
+						if ($size == 1) {
+							print("Setting path to: .");
+							$path = ".";
+						} else {
+							$path = $arr[0];
+						}
+						for ($i = 1; $i < ($size - 1); $i++) {
+							$path = $path."/".$arr[$i];
+						}
+						$file = generateFileObj($fName, $path, $rootDir, $expand,$showHiddenFiles);
+						header("Content-Type", "text/json");
+						print("/* ".json_encode($file)." */");
+					} else {
+						header("HTTP/1.0 404 Not Found");
+						header("Status: 404 Not Found");
+						print("<b>Cannot access file: [".htmlentities($path)."]<b>");
+					}
+				} else {
+						header("HTTP/1.0 404 Not Found");
+						header("Status: 404 Not Found");
+						print("<b>Cannot access file: [".htmlentities($path)."]<b>");
+				}
+			} else {
+				header("HTTP/1.0 403 Forbidden");
+				header("Status: 403 Forbidden");
+				print("<b>Cannot access file: [".htmlentities($path)."].  It is outside of the root of the file service.<b>");
+			}
+		} else {
+				header("HTTP/1.0 404 Not Found");
+				header("Status: 404 Not Found");
+				print("<b>Cannot access file: [".htmlentities($path)."]<b>");
+		}
+	}
+?>
diff --git a/dojox/data/tests/stores/filestore_funcs.php b/dojox/data/tests/stores/filestore_funcs.php
new file mode 100755
index 0000000..ff61139
--- /dev/null
+++ b/dojox/data/tests/stores/filestore_funcs.php
@@ -0,0 +1,366 @@
+<?php
+	/**
+	 *  Helper function to convert a simple pattern to a regular expression for matching.
+	 * 
+	 *	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.
+	 *
+	 * @param 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.
+	 */
+	function patternToRegExp(/*String*/$pattern){
+		$rxp = "^";
+		$c = "";
+		$len = strlen($pattern);
+		for ($i = 0; $i < $len; $i++) {
+			$c = $pattern[$i];
+			switch ($c) {
+				case '\\':
+					$rxp = $rxp.$c;
+					$i++;
+					$rxp = $rxp.$pattern[$i];
+					break;
+				case '*':
+					$rxp = $rxp.".*"; break;
+				case '?':
+					$rxp = $rxp."."; break;
+				case '$':
+				case '^':
+				case '/':
+				case '+':
+				case '.':
+				case '|':
+				case '(':
+				case ')':
+				case '{':
+				case '}':
+				case '[':
+				case ']':
+					$rxp = $rxp."\\"; //fallthrough
+				default:
+					$rxp = $rxp.$c;
+			}
+		}
+		return "(".$rxp."$)";
+	}
+
+	/**
+	 * Function to load all file info from a particular directory.
+	 *
+	 * @param $dir The dir to seach from, relative to $rootDir.
+	 * @param $rootDir The directory where the file service is rooted, used as separate var to allow easier checking and prevention of ../ing out of the tree.
+	 * @param $recurse Whether or not to deep scan the dir and return all subfiles, or just return the toplevel files.
+	 * @param $dirsOnly boolean to enote to only return directory names, not filenames.
+	 * @param $expand boolean to indicate whether or not to inflate all children files along a path/file, or leave them as stubs.
+	 * @param $showHiddenFiles boolean to indicate to return hidden files as part of the list.
+	 */
+	function getAllfiles($dir, $rootDir, $recurse, $dirsOnly, $expand, $showHiddenFiles) { 
+		//  summary:
+		//      A function to obtain all the files in a particular directory (file or dir)
+		$files = array();
+		$dirHandle = opendir($rootDir."/".$dir);
+		if ($dirHandle) {
+			while($file = readdir($dirHandle)) {
+				if ($file) {
+					if ($file != ".." && $file != ".") {
+						$path = $dir."/".$file;
+						$fileObj = generateFileObj($file, $dir, $rootDir,$expand,$showHiddenFiles);
+						if (is_dir($rootDir."/".$path)) {
+							if ($recurse) {
+								if ($showHiddenFiles || $fileObj["name"][0] != '.') {
+									$subfiles = getAllfiles($path,$rootDir,$recurse,$dirsOnly,$expand,$showHiddenFiles);
+									$length = count($subfiles);
+									for ($i = 0; $i < $length; $i++) {
+										$files[] = $subfiles[$i];
+									}
+								}
+							}
+						}
+						if (!$dirsOnly || $fileObj["directory"]) {
+							if ($showHiddenFiles || $fileObj["name"][0] !== '.') {
+								$files[] = $fileObj;
+							}
+						}
+					}
+				}
+			}
+		}
+		closedir($dirHandle);
+		return $files;
+	}
+
+	/** 
+	 * Function to generate an associative map of data about a specific file.
+	 * @param $file The name of the file this object represents.
+	 * @param $dir The sub-path that contains the file defined by $file
+	 * @param $rootDir The directory from which to append dir and name to get the full path to the file.
+	 * @param $expand boolean to denote that if the file is a directory, expand all children in the children attribute 
+	 *        to a a full object
+	 * @param $showHiddenFiles boolean to denote if hidden files should be shown in-view or not.
+	 *
+	 * @return Associative Map.   The details about the file:
+	 *  $file["name"] - Returns the shortname of the file.
+	 *  $file["parentDir"] - Returns the relative path from the service root for the parent directory containing file $file["name"]
+	 *  $file["path"] - The relative path to the file.
+	 *  $file["directory"] - Boolean indicator if the file represents a directory.
+	 *  $file["size"] - The size of the file, in bytes.
+	 *  $file["modified] - The modified date of the file in milliseconds since Jan 1st, 1970.
+	 *  $file["children"] - Children files of a directory.  Empty if a standard file.
+	 */
+	function generateFileObj($file, $dir, $rootDir, $expand, $showHiddenFiles) {
+		//  summary:
+		//      Function to generate an object representation of a disk file.
+		$path = $file;
+		if ($dir != "." && $dir != "./") {
+			$path = $dir."/".$file;
+		}
+
+		$fullPath = $rootDir."/".$path;
+
+		$atts = stat($fullPath);
+
+		$rootPath = realPath($rootDir);                                       
+		$resolvedDir = realPath($rootDir."/".$dir);
+		$resolvedFullPath = realPath($fullPath);
+
+		//Try to normalize down the paths so it does a consistent return.
+		if (strcmp($rootPath, $resolvedDir) === 0) {
+			$dir = ".";
+		} else {
+			$dir = substr($resolvedDir, (strlen($rootPath) + 1), strlen($resolvedDir));
+			$dir = "./".str_replace("\\","/",$dir);
+		}
+		if (strcmp($rootPath, $resolvedFullPath) === 0) {
+			$path = ".";
+		} else {
+			$path = substr($resolvedFullPath, (strlen($rootPath) + 1), strlen($resolvedFullPath));
+			$path = "./".str_replace("\\","/",$path);
+		}
+
+		$fObj = array();
+		$fObj["name"] = $file;
+		$fObj["parentDir"] = $dir;
+		$fObj["path"] = $path;
+		$fObj["directory"] = is_dir($fullPath);
+		$fObj["size"] = filesize($fullPath);
+		$fObj["modified"] = $atts[9];
+
+		if (is_dir($fullPath)) {
+			$children = array();
+			$dirHandle = opendir($fullPath);
+			while($cFile = readdir($dirHandle)) {
+				if ($cFile) {
+					if ($cFile != ".." && $cFile != ".") {
+						if ($showHiddenFiles || $cFile[0] != '.') {
+							if (!$expand) {
+								$children[] = $cFile;
+							}else{
+								$children[] = generateFileObj($cFile, $path, $rootDir, $expand, $showHiddenFiles);
+							}
+						}
+					}
+				}
+			}
+			closedir($dirHandle);
+			$fObj["children"] = $children;
+		}
+		return $fObj;
+	}
+
+	/**
+	 * A field comparator class, whose role it is to define which fields on an associaive map to compare on
+	 * and provide the comparison function to do so.
+	 */
+	class FieldComparator {
+		var $field;
+		var $descending = false;
+
+		/**
+		 * Constructor.
+		 * @param $f The field of the item to compare.
+		 * @param $d Parameter denoting whether it should be ascending or descending.  Default is ascending.
+		 */
+		function FieldComparator($f, $d) {
+			$this->field = $f;
+			$this->descending = $d;
+		}
+
+		/**
+		 * Function to compare file objects A and B on the field defined by $this->field.
+		 * @param $fileA The first file to compare.
+		 * @param #fileB The second file to compare.
+		 */
+		function compare($fileA,$fileB){
+			$f = $this->field;
+			$a = $fileA[$f];
+			$b = $fileB[$f];
+
+			$ret = 0;
+			if (is_string($a) && is_string($b)) {
+				$ret = strcmp($a,$b);
+			} else if($a > $b || $a === null){
+				$ret = 1;
+			}else if($a < $b || $b === null){
+				$ret = -1;
+			}
+
+			if (property_exists($this, "descending") && $this->descending == true) {
+				$ret = $ret * -1;
+			}
+
+			if ($ret > 0) {
+				$ret = 1;
+			} else if ($ret < 0) {
+				$ret = -1;
+			}
+			return $ret; //int, {-1,0,1}
+		}
+	}
+
+	/**
+	 * A compound comparator class, whose role it is to sequentially call a set of comparators on two objects and 
+	 * return the combined result of the comparison.
+	 */
+	class CompoundComparator {
+		//Comparator chain.
+		var $comparators = array();
+
+		/**
+		 * Function to compare two objects $a and $b, using the chain of comparators.
+		 * @param $a The first object to compare.  
+		 * @param $b The second object to compare.
+		 * @returns -1, 0, 1.  -1 if a < b, 1 if a > b, and 0 if a = b.
+		 */
+		function compare($a, $b) {
+			$ret = 0;
+			$size = count($this->comparators);
+			for ($i = 0; $i < $size; $i++) {
+				$comp = $this->comparators[$i];
+				$ret = $comp->compare($a, $b);
+				if ($ret != 0) {
+					break;
+				}
+			}
+			return $ret;
+		}
+
+		/**
+		 * Function to add a comparator to the chain.
+		 * @param $comp The comparator to add.
+		 */
+		function addComparator($comp){
+			$this->comparators[] = $comp;
+		}
+	}
+
+	/**
+	 * A function to create a Comparator class with chained comparators based off the sort specification passed into the store.
+	 * @param $sortSpec The Sort specification, which is an array of sort objects containing ( attribute: "someStr": descending: true|fase}
+	 * @returns The constructed comparator.
+	 */
+	function createComparator($sortSpec) {
+		//Function to construct the class that handles chained comparisons.
+		$comparator = new CompoundComparator();
+		$size = count($sortSpec);
+		for ($i = 0; $i < $size; $i++) {
+			$sort = $sortSpec[$i];
+			$desc = false;
+			if(property_exists($sort, "descending")){
+				$desc = $sort->descending;
+			}
+			$fileComp = new FieldComparator($sort->attribute,$desc);
+			$comparator->addComparator($fileComp);
+		}
+		return $comparator;
+	}
+
+	/**
+	 * Function to match a set of queries against a directory and possibly all subfiles.
+	 * @param query The Query send in to process and test against.
+	 * @param patterns The set of regexp patterns generated off the query.
+	 * @param dir the directory to search in.
+	 * @param recurse Whether or not to recurse into subdirs and test files there too.
+	 *
+	 * @return Array.  Returns an array of all matches of the query.
+	 */
+	function matchFiles($query, $patterns, $ignoreCase, $dir, $rootDir, $recurse, $dirsOnly, $expand, $showHiddenFiles) {
+		$files = array();
+		$fullDir = $rootDir."/".$dir;
+
+		if ($fullDir != null && is_dir($fullDir)) {
+
+			$dirHandle = opendir($fullDir);
+			while ($file = readdir($dirHandle)) {
+				if ($file != "." && $file != "..") {
+					$item = generateFileObj($file, $dir, $rootDir, $expand,$showHiddenFiles);
+					$keys = array_keys($patterns);
+					$total = count($keys);
+					for ($i = 0; $i < $total; $i++) {
+						$key = $keys[$i];
+						$pattern = $query[$key];
+						$matched = containsValue($item,$key,$query[$key],$patterns[$key], $ignoreCase);
+						if (!$matched) {
+							break;
+						}
+					}
+					if ($matched) {
+						if (!$dirsOnly || $item["directory"]) {
+							if ($showHiddenFiles || $item["name"][0] != '.') {
+								$files[] = $item;
+							}
+						}
+					}
+
+					if (is_dir($rootDir."/".$item["path"]) && $recurse) {
+						if ($showHiddenFiles || $item["name"][0] != '.') {
+							$files = array_merge($files, matchFiles($query, $patterns, $ignoreCase, $item["path"], $rootDir, $recurse, $dirsOnly, $expand, $showHiddenFiles));
+						}
+					}
+				}
+			}
+			closedir($dirHandle);
+		}
+		return $files;
+	}
+
+	/**
+	 * Function to handle comparing the value of an attribute on a file item.
+	 * @param item  The item to examine.
+	 * @param attr The attribute of the tem to examine.
+	 * @parma value The value to compare it to.
+	 * @param rExp A regular Expression pattern object generated off 'value' if any.
+	 * 
+	 * @returns boolean denoting if the value was matched or not.
+	 */
+	function containsValue($item, $attr, $value, $rExp, $ignoreCase) {
+		$matched = false;
+		$possibleValue = $item[$attr];
+		if ($possibleValue === null && $value === null) {
+			$matched = true;
+		} else {
+			if ($rExp != null && is_string($possibleValue)) {
+				if ($ignoreCase) {
+					$matched = eregi($rExp, $possibleValue);
+				} else {
+					$matched = ereg($rExp, $possibleValue);
+				}
+
+			} else {
+				if ($value != null && $possibleValue != null) {
+					$matched = ($value == $possibleValue);
+				}
+			}
+		}              
+		return $matched;
+	}
+// No closing PHP tag on purpose.  Do not want it to print whitepace and thus not allow setting headers later.
diff --git a/dojox/data/tests/stores/geography.xml b/dojox/data/tests/stores/geography.xml
new file mode 100644
index 0000000..070a8c1
--- /dev/null
+++ b/dojox/data/tests/stores/geography.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<opml version="1.0">
+	<head>
+		<title>geography.opml</title>
+		<dateCreated>2006-11-10</dateCreated>
+		<dateModified>2006-11-13</dateModified>
+		<ownerName>Magellan, Ferdinand</ownerName>
+	</head>
+	<body>
+		<outline text="Africa" type="continent">
+			<outline text="Egypt" type="country"/>
+			<outline text="Kenya" type="country">
+				<outline text="Nairobi" type="city"/>
+				<outline text="Mombasa" type="city"/>
+			</outline>
+			<outline text="Sudan" type="country">
+				<outline text="Khartoum" type="city"/>
+			</outline>
+		</outline>
+		<outline text="Asia" type="continent">
+			<outline text="China" type="country"/>
+			<outline text="India" type="country"/>
+			<outline text="Russia" type="country"/>
+			<outline text="Mongolia" type="country"/>
+		</outline>
+		<outline text="Australia" type="continent" population="21 million">
+			<outline text="Australia" type="country" population="21 million"/>
+		</outline>
+		<outline text="Europe" type="continent">
+			<outline text="Germany" type="country"/>
+			<outline text="France" type="country"/>
+			<outline text="Spain" type="country"/>
+			<outline text="Italy" type="country"/>
+		</outline>
+		<outline text="North America" type="continent">
+			<outline text="Mexico" type="country" population="108 million" area="1,972,550 sq km">
+				<outline text="Mexico City" type="city" population="19 million" timezone="-6 UTC"/>
+				<outline text="Guadalajara" type="city" population="4 million" timezone="-6 UTC"/>
+			</outline>
+			<outline text="Canada" type="country" population="33 million" area="9,984,670 sq km">
+				<outline text="Ottawa" type="city" population="0.9 million" timezone="-5 UTC"/>
+				<outline text="Toronto" type="city" population="2.5 million" timezone="-5 UTC"/>
+			</outline>
+			<outline text="United States of America" type="country"/>
+		</outline>
+		<outline text="South America" type="continent">
+			<outline text="Brazil" type="country" population="186 million"/>
+			<outline text="Argentina" type="country" population="40 million"/>
+		</outline>
+	</body>
+</opml>
diff --git a/dojox/data/tests/stores/geography2.xml b/dojox/data/tests/stores/geography2.xml
new file mode 100644
index 0000000..b82c110
--- /dev/null
+++ b/dojox/data/tests/stores/geography2.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<geography>
+    <outline text="Africa" type="continent">
+        <outline text="Egypt" type="country"/>
+        <outline text="Kenya" type="country">
+            <outline text="Nairobi" type="city"/>
+            <outline text="Mombasa" type="city"/>
+        </outline>
+        <outline text="Sudan" type="country">
+            <outline text="Khartoum" type="city"/>
+        </outline>
+    </outline>
+    <outline text="Asia" type="continent">
+        <outline text="China" type="country"/>
+        <outline text="India" type="country"/>
+        <outline text="Russia" type="country"/>
+        <outline text="Mongolia" type="country"/>
+    </outline>
+    <outline text="Australia" type="continent" population="21 million">
+        <outline text="Australia" type="country" population="21 million"/>
+    </outline>
+    <outline text="Europe" type="continent">
+        <outline text="Germany" type="country"/>
+        <outline text="France" type="country"/>
+        <outline text="Spain" type="country"/>
+        <outline text="Italy" type="country"/>
+    </outline>
+    <outline text="North America" type="continent">
+        <outline text="Mexico" type="country" population="108 million" area="1,972,550 sq km">
+            <outline text="Mexico City" type="city" population="19 million" timezone="-6 UTC"/>
+            <outline text="Guadalajara" type="city" population="4 million" timezone="-6 UTC"/>
+        </outline>
+        <outline text="Canada" type="country" population="33 million" area="9,984,670 sq km">
+            <outline text="Ottawa" type="city" population="0.9 million" timezone="-5 UTC"/>
+            <outline text="Toronto" type="city" population="2.5 million" timezone="-5 UTC"/>
+        </outline>
+        <outline text="United States of America" type="country"/>
+    </outline>
+    <outline text="South America" type="continent">
+        <outline text="Brazil" type="country" population="186 million"/>
+        <outline text="Argentina" type="country" population="40 million"/>
+    </outline>
+</geography>
+
diff --git a/dojox/data/tests/stores/geography_withspeciallabel.xml b/dojox/data/tests/stores/geography_withspeciallabel.xml
new file mode 100644
index 0000000..597c164
--- /dev/null
+++ b/dojox/data/tests/stores/geography_withspeciallabel.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<opml version="1.0">
+	<head>
+		<title>geography.opml</title>
+		<dateCreated>2006-11-10</dateCreated>
+		<dateModified>2006-11-13</dateModified>
+		<ownerName>Magellan, Ferdinand</ownerName>
+	</head>
+	<body>
+		<outline text="Africa" type="continent" label="Continent/Africa">
+			<outline text="Egypt" type="country" label="Country/Egypt"/>
+			<outline text="Kenya" type="country" label="Country/Kenya">
+				<outline text="Nairobi" type="city" label="City/Nairobi"/>
+				<outline text="Mombasa" type="city" label="City/Mombasa"/>
+			</outline>
+			<outline text="Sudan" type="country" label="Country/Sudan">
+				<outline text="Khartoum" type="city" label="City/Khartoum"/>
+			</outline>
+		</outline>
+		<outline text="Asia" type="continent" label="Continent/Asia">
+			<outline text="China" type="country" label="Country/China"/>
+			<outline text="India" type="country" label="Country/India"/>
+			<outline text="Russia" type="country" label="Country/Russia"/>
+			<outline text="Mongolia" type="country" label="Country/Mongolia"/>
+		</outline>
+		<outline text="Australia" type="continent" population="21 million" label="Continent/Australia">
+			<outline text="Australia" type="country" population="21 million" label="Country/Australia"/>
+		</outline>
+		<outline text="Europe" type="continent" label="Contintent/Europe">
+			<outline text="Germany" type="country" label="Country/Germany"/>
+			<outline text="France" type="country"  label="Country/France"/>
+			<outline text="Spain" type="country"   label="Country/Spain"/>
+			<outline text="Italy" type="country"   label="Country/Italy"/>
+		</outline>
+		<outline text="North America" type="continent" label="Continent/North America">
+			<outline text="Mexico" type="country" population="108 million" area="1,972,550 sq km" label="Country/Mexico">
+				<outline text="Mexico City" type="city" population="19 million" timezone="-6 UTC" label="City/Mexico City"/>
+				<outline text="Guadalajara" type="city" population="4 million" timezone="-6 UTC"  label="City/Guadalajara"/>
+			</outline>
+			<outline text="Canada" type="country" population="33 million" area="9,984,670 sq km" label="Country/Canada">
+				<outline text="Ottawa" type="city" population="0.9 million" timezone="-5 UTC"    label="City/Ottawa"/>
+				<outline text="Toronto" type="city" population="2.5 million" timezone="-5 UTC"   label="City/Toronto"/>
+			</outline>
+			<outline text="United States of America" type="country" label="Country/United States of America"/>
+		</outline>
+		<outline text="South America" type="continent" label="Continent/South America">
+			<outline text="Brazil" type="country" population="186 million" label="Country/Brazil"/>
+			<outline text="Argentina" type="country" population="40 million" label="Country/Argentina"/>
+		</outline>
+	</body>
+</opml>
diff --git a/dojox/data/tests/stores/movies.csv b/dojox/data/tests/stores/movies.csv
new file mode 100644
index 0000000..baf71eb
--- /dev/null
+++ b/dojox/data/tests/stores/movies.csv
@@ -0,0 +1,9 @@
+Title, Year, Producer
+City of God, 2002, Katia Lund
+Rain,, Christine Jeffs
+2001: A Space Odyssey, , Stanley Kubrick
+"This is a ""fake"" movie title", 1957, Sidney Lumet
+Alien, 1979   , Ridley Scott
+"The Sequel to ""Dances With Wolves.""", 1982, Ridley Scott
+"Caine Mutiny, The", 1954, "Dymtryk ""the King"", Edward"
+
diff --git a/dojox/data/tests/stores/movies2.csv b/dojox/data/tests/stores/movies2.csv
new file mode 100644
index 0000000..401bcfc
--- /dev/null
+++ b/dojox/data/tests/stores/movies2.csv
@@ -0,0 +1,9 @@
+Title, Year, Producer
+City of God, 2002, Katia Lund
+Rain,"", Christine Jeffs
+2001: A Space Odyssey, , Stanley Kubrick
+"This is a ""fake"" movie title", 1957, Sidney Lumet
+Alien, 1979   , Ridley Scott
+"The Sequel to ""Dances With Wolves.""", 1982, Ridley Scott
+"Caine Mutiny, The", 1954, "Dymtryk ""the King"", Edward"
+
diff --git a/dojox/data/tests/stores/movies3.csv b/dojox/data/tests/stores/movies3.csv
new file mode 100755
index 0000000..a7ad288
--- /dev/null
+++ b/dojox/data/tests/stores/movies3.csv
@@ -0,0 +1,11 @@
+Title, Year, Producer
+"City 
+of God", 2002, Katia Lund
+Rain,, Christine Jeffs
+2001: A Space Odyssey, , Stanley Kubrick
+"This is a ""fake"" movie title", 1957, Sidney Lumet
+Alien, 1979   , Ridley Scott
+"The Sequel to ""Dances With
+ Wolves.""", 1982, Ridley Scott
+"Caine Mutiny, The", 1954, "Dymtryk ""the King"", Edward"
+
diff --git a/dojox/data/tests/stores/node1.1 b/dojox/data/tests/stores/node1.1
new file mode 100644
index 0000000..21d1923
--- /dev/null
+++ b/dojox/data/tests/stores/node1.1
@@ -0,0 +1,4 @@
+{ id: 'node1.1',name:'node1.1', someProperty:'somePropertyA1', children: [
+			{ $ref: 'node1.1.1', name: 'node1.1.1'},
+			{ $ref: 'node1.1.2', name: 'node1.1.2'}
+]}
diff --git a/dojox/data/tests/stores/node1.2 b/dojox/data/tests/stores/node1.2
new file mode 100644
index 0000000..b221fab
--- /dev/null
+++ b/dojox/data/tests/stores/node1.2
@@ -0,0 +1 @@
+{ id: 'node1.2',name:'node1.2', someProperty:'somePropertyA2'}
diff --git a/dojox/data/tests/stores/opensearch_atom.xml b/dojox/data/tests/stores/opensearch_atom.xml
new file mode 100644
index 0000000..d6733a6
--- /dev/null
+++ b/dojox/data/tests/stores/opensearch_atom.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  This is an invalid OpenSearch Description Document, but it's simply used for testing.  -->
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <Url type="application/atom+xml" template="atom1.xml?q={searchTerms}"/>
+</OpenSearchDescription>
\ No newline at end of file
diff --git a/dojox/data/tests/stores/opensearch_html.xml b/dojox/data/tests/stores/opensearch_html.xml
new file mode 100644
index 0000000..4793685
--- /dev/null
+++ b/dojox/data/tests/stores/opensearch_html.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  This is an invalid OpenSearch Description Document, but it's simply used for testing.  -->
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <Url type="text/html" template="books.html?q={searchTerms}"/>
+</OpenSearchDescription>
\ No newline at end of file
diff --git a/dojox/data/tests/stores/opensearch_rss.xml b/dojox/data/tests/stores/opensearch_rss.xml
new file mode 100644
index 0000000..a1a9b46
--- /dev/null
+++ b/dojox/data/tests/stores/opensearch_rss.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  This is an invalid OpenSearch Description Document, but it's simply used for testing.  -->
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <Url type="application/rss+xml" template="rss1.xml?q={searchTerms}"/>
+</OpenSearchDescription>
\ No newline at end of file
diff --git a/dojox/data/tests/stores/patterns.csv b/dojox/data/tests/stores/patterns.csv
new file mode 100644
index 0000000..a9bee64
--- /dev/null
+++ b/dojox/data/tests/stores/patterns.csv
@@ -0,0 +1,11 @@
+uniqueId, value
+9, jfq4@#!$!@Rf14r14i5u
+6, BaBaMaSaRa***Foo
+2, bar*foo
+8, 123abc
+4, bit$Bite
+3, 123abc
+10, 123abcdefg
+1, foo*bar
+7, 
+5, 123abc
diff --git a/dojox/data/tests/stores/pipeSeparator.csv b/dojox/data/tests/stores/pipeSeparator.csv
new file mode 100755
index 0000000..5f3d8cb
--- /dev/null
+++ b/dojox/data/tests/stores/pipeSeparator.csv
@@ -0,0 +1,7 @@
+article|price
+1008|4,59
+1010|10,09
+1011|5,13
+1016|16,68
+1019|15,5
+1022|10,36
diff --git a/dojox/data/tests/stores/pipeSeparatorInData.csv b/dojox/data/tests/stores/pipeSeparatorInData.csv
new file mode 100755
index 0000000..d3998b1
--- /dev/null
+++ b/dojox/data/tests/stores/pipeSeparatorInData.csv
@@ -0,0 +1,7 @@
+article|price
+1008|"4,59|5,54"
+1010|10,09
+1011|5,13
+1016|16,68
+1019|15,5
+1022|10,36
diff --git a/dojox/data/tests/stores/properties.js b/dojox/data/tests/stores/properties.js
new file mode 100644
index 0000000..bbdd38d
--- /dev/null
+++ b/dojox/data/tests/stores/properties.js
@@ -0,0 +1,10 @@
+/*[
+	// Properties of December 1, 2007 
+	{ "year": "2007" },
+	{ "nmonth": "12" },
+	{ "month": "December" },
+	{ "nday": "1" },
+	{ "day": "Saturday" },
+	{ "dayOfYear": "335" },
+	{ "weekOfYear": "48" }
+]*/
diff --git a/dojox/data/tests/stores/rss1.xml b/dojox/data/tests/stores/rss1.xml
new file mode 100644
index 0000000..e0ecec1
--- /dev/null
+++ b/dojox/data/tests/stores/rss1.xml
@@ -0,0 +1,436 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:date="http://exslt.org/dates-and-times" version="2.0">
+  <channel><language>en</language><description><![CDATA[..where the wave finally broke, and rolled back.. Shane O'Sullivan's technical blog]]></description>
+	<title><![CDATA[SOS]]></title>
+	
+
+	<pubDate>Tue, 22 Jan 2008 14:32:09 GMT
+</pubDate>
+	
+
+	<link>http://shaneosullivan.wordpress.com</link>
+	
+	<!-- source: http://shaneosullivan.wordpress.com/feed/atom/ -->
+
+			<item><description>The Dojo Ajax Toolkit is kindly hosted by AOL for the consumption of anyone at all.  This has the advantage of
+
+Reducing the load on your own server
+Speeding up the delivery, as a Content Delivery Network (CDN) is used to ensure that the server is as close as possible to the client, and
+The more people [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+		<title>Using AOL hosted Dojo with your custom code</title>
+		<link>http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/</link>
+		<guid>http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/</guid>
+
+		
+		<pubDate>Tue, 22 Jan 2008 14:32:09 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category>
+		<category domain="http://shaneosullivan.wordpress.com">Dojo</category>
+		<category domain="http://shaneosullivan.wordpress.com">Javascript</category>
+		<category domain="http://shaneosullivan.wordpress.com">Technical</category>
+		<category domain="http://shaneosullivan.wordpress.com">aol</category>
+
+		<category domain="http://shaneosullivan.wordpress.com">cross domain</category>
+		<category domain="http://shaneosullivan.wordpress.com">open source</category>		
+		
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/#comments" thr:count="1"/>
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2008/01/22/using-aol-hosted-dojo-with-your-custom-code/feed/atom/" thr:count="1"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>A short while ago I posted about the demo engine I&#8217;m writing for the Dojo Ajax Toolkit. Click here to read that post or go to http://www.skynet.ie/~sos/js/demo/dojo/dojoc/demos/featureexplorer.html to see it in action.
+Features
+Since that post, quite a lot of work has gone into both the features and the content of the demo engine, and the development [...] (...)</description>
+
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+		<title>Dojo Demo Engine Update</title>
+		<link>http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/</link>
+		<guid>http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/</guid>
+		
+		<pubDate>Mon, 07 Jan 2008 01:02:43 GMT
+</pubDate>
+
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Demo Engine</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">demo</category><category domain="http://shaneosullivan.wordpress.com">dijit</category><category domain="http://shaneosullivan.wordpress.com">d [...]
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/#comments" thr:count="3"/>
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2008/01/07/dojo-demo-engine-update/feed/atom/" thr:count="3"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total>
+
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>Internet Explorer has a nice feature where a new window can be opened modally using the window.showModalDialog function, meaning that the page that opened it cannot be accessed until the new window is closed.  This can be useful in many situations.
+However, the main limitation of IE Modal Dialogs (other than being non-standard), is that [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+		<title>Navigating in an IE Modal Dialog</title>
+		<link>http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/</link>
+
+		<guid>http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/</guid>
+		
+		<pubDate>Mon, 31 Dec 2007 16:36:21 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Internet Explorer</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpress.com">modal</category>		
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/#comments" thr:count="1"/>
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/12/31/navigating-in-an-ie-modal-dialog/feed/atom/" thr:count="1"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total>
+
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>A couple of weeks ago I saw a cool demo framework for an Ajax toolkit just released as open source.  It&#8217;s a very slick implementation, with a tree listing all the various demos, and a tabbed area showing the implementation, and the widget in practice.
+So, I think to myself, this is exactly what the [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+		<title>A new Demo engine for Dojo</title>
+		<link>http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/</link>
+
+		<guid>http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/</guid>
+		
+		<pubDate>Tue, 04 Dec 2007 09:29:16 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">demo</category><category domain="http://shaneosullivan.wordpress.com">dijit</category><category domain="http://shaneosullivan.wordpress.com">documentation</category><category domain="http://shaneosullivan.wordpress.com" [...]
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/#comments" thr:count="3"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/12/04/a-new-demo-engine-for-dojo/feed/atom/" thr:count="3"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>Today I&#8217;ve begun the process of upgrading my Ubuntu installation of version 7.04 to version 7.10.  To see my previous tutorial of getting Ubuntu installed on my IBM Thinkpad X41, see http://shaneosullivan.wordpress.com/2007/02/16/installing-ubuntu-edgy-on-a-thinkpad-x41-tablet/.
+This post lists whatever issues I found when upgrading, and my solutions to them.  For the official instructions, see https://help.ubuntu.com/community/GutsyUpgrades.
+Third Party software [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+
+		<title>Upgrading Ubuntu Feisty Fawn (7.04) to Gutsy Gibbon (7.10)</title>
+		<link>http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/</guid>
+		
+		<pubDate>Thu, 18 Oct 2007 16:11:37 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Gutsy Gibbon</category><category domain="http://shaneosullivan.wordpress.com">Ubuntu</category><category domain="http://shaneosullivan.wordpress.com">open source</category>		
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/#comments" thr:count="25"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/10/18/upgrading-ubuntu-feisty-fawn-704-to-gutsy-gibbon-710/feed/atom/" thr:count="25"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">25</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>In previous posts (here for the Dojo 0.4.3 version, here and here), I wrote how I wrote an image gallery for version 0.4.3 of the Dojo Ajax Toolkit, and how I was translating it for the latest version of the toolkit, version 1.0.
+Well, that work is now, finally, complete, and I have to say, I&#8217;m [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+
+		<title>Introducing the new Dojo Image Widgets</title>
+		<link>http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/</guid>
+		
+		<pubDate>Sat, 13 Oct 2007 11:09:13 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category>
+		<category domain="http://shaneosullivan.wordpress.com">Dojo</category>
+
+		<category domain="http://shaneosullivan.wordpress.com">Flickr</category>
+		<category domain="http://shaneosullivan.wordpress.com">Image Gallery</category>
+		<category domain="http://shaneosullivan.wordpress.com">Javascript</category>
+		<category domain="http://shaneosullivan.wordpress.com">Technical</category>
+		<category domain="http://shaneosullivan.wordpress.com">aol</category>
+		<category domain="http://shaneosullivan.wordpress.com">cross domain</category>
+
+		<category domain="http://shaneosullivan.wordpress.com">dijit</category>
+		<category domain="http://shaneosullivan.wordpress.com">dojo.data</category>
+		<category domain="http://shaneosullivan.wordpress.com">dojox</category>
+		<category domain="http://shaneosullivan.wordpress.com">dojox.data</category>
+		<category domain="http://shaneosullivan.wordpress.com">dojox.image</category>
+		<category domain="http://shaneosullivan.wordpress.com">json</category>
+
+		<category domain="http://shaneosullivan.wordpress.com">open source</category>
+				
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/#comments" thr:count="46"/>
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/10/13/introducing-the-new-dojo-image-widgets/feed/atom/" thr:count="46"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">46</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>The previously  announced Dojo Grid has landed in source control, and is in the nightly builds.  It has all sorts of fancy functionality, like support for lazy loading huge data sets, individual styling of rows and columns, inline editing etc.
+Check it out at http://archive.dojotoolkit.org/nightly/checkout/dojox/grid/tests/
+Very cool stuff!
+Update: The Sitepen guys have recently blogged about [...] (...)</description>
+		<managingEditor>
+
+	 (Shane O'Sullivan)
+</managingEditor>
+		<title>Dojo Grid has landed</title>
+		<link>http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/</guid>
+		
+		<pubDate>Fri, 05 Oct 2007 13:23:17 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">grid</category><category domain="http://shaneosullivan.wordpress.com">open source</category>		
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/#comments" thr:count="0"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/10/05/dojo-grid-has-landed/feed/atom/" thr:count="0"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>I work on a number of open source projects, and many of them use the Subversion version control system to manage their code.  Before my switch from Windows XP to Ubuntu Linux (which I am still ecstatically happy with btw), I became a big fan of TortoiseSVN, an extremely useful Subversion client that integrates itself [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+		<title>A TortoiseSVN replacement for Ubuntu</title>
+
+		<link>http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/</guid>
+		
+		<pubDate>Thu, 04 Oct 2007 15:50:50 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Linux</category><category domain="http://shaneosullivan.wordpress.com">Nautilus</category><category domain="http://shaneosullivan.wordpress.com">Subversion</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpress.com">TortoiseSVN</category><category domain="http://shaneosullivan.wordpress.com">Ubuntu</category><category domain="http://shaneosullivan.wordp [...]
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/#comments" thr:count="3"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/10/04/a-tortoisesvn-replacement-for-ubuntu/feed/atom/" thr:count="3"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>I&#8217;ve recently submitted a new data store for the Dojo Ajax Toolkit that makes it very simple to query Flickr for your and other peoples images.  For those not familiar with Flickr, it is a photo sharing website, one of the most popular on the net.  However, what makes it quite special is [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+
+		<title>Querying Flickr with Dojo!</title>
+		<link>http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/</guid>
+		
+		<pubDate>Sat, 22 Sep 2007 16:10:05 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Flickr</category><category domain="http://shaneosullivan.wordpress.com">Image Gallery</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpres [...]
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/#comments" thr:count="3"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/09/22/querying-flickr-with-dojo/feed/atom/" thr:count="3"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>Flickr is a photo sharing website that has a very flexible set of APIs that other applications and websites can use to access the photos it stores. This post shows you how to specify a callback function that Flickr can call to pass your web application information on photos it stores.
+Quite a while ago I [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+		<title>Specifying the callback function with the Flickr JSON APIs</title>
+
+		<link>http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/</guid>
+		
+		<pubDate>Thu, 13 Sep 2007 09:31:30 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Flickr</category><category domain="http://shaneosullivan.wordpress.com">Image Gallery</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpres [...]
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/#comments" thr:count="0"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/09/13/specifying-the-callback-function-with-the-flickr-json-apis/feed/atom/" thr:count="0"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>In a previous post (see here)  I spoke about how I&#8217;d written an Image Gallery widget that worked with Dojo Ajax Toolkit version 0.4.2 and 0.4.3.  I contacted the good folks at Dojo about updating it for the latest release, 0.9, and adding it to the toolkit.
+They were very receptive to the idea, [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+
+		<title>Image Gallery, Slideshow, and Flickr data source for Dojo 0.9</title>
+		<link>http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/</guid>
+		
+		<pubDate>Tue, 04 Sep 2007 23:32:51 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Image Gallery</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpress.com">dijit</category><category domain="http://shaneosullivan.wordpress [...]
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/#comments" thr:count="1"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/09/04/image-gallery-slideshow-and-flickr-data-source-for-dojo-09/feed/atom/" thr:count="1"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>When working with the Dojo Ajax Toolkit and using it&#8217;s dojo.event package to listen to DOM and custom events, the two most common approaches are:
+
+Listen for an event (or function call) to be triggered on  an object, and when it is to run a custom function, e.g.
+    var alertFn = function() [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+
+		<title>Dojo event performance tip</title>
+		<link>http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/</guid>
+		
+		<pubDate>Thu, 23 Aug 2007 12:29:08 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpress.com">dojo.event</category><category domain="http://shaneosullivan.wordpress.com">open source</category><category domain="http://shaneosullivan.wordpr [...]
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/#comments" thr:count="0"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/08/23/dojo-event-performance-tip/feed/atom/" thr:count="0"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>The latest  version of the Dojo Ajax Toolkit has just been released into the wild.  Version 0.9 is a very streamlined progression of the toolkit, with many of the less essential features pushed out to another project, DojoX, and the Dojo widgets given their own project, Dijit.
+Another big change is the the main [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+		<title>Dojo 0.9 released</title>
+
+		<link>http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/</guid>
+		
+		<pubDate>Wed, 22 Aug 2007 10:24:51 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpress.com">dijit</category><category domain="http://shaneosullivan.wordpress.com">open source</category>		
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/#comments" thr:count="2"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/08/22/dojo-09-released/feed/atom/" thr:count="2"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>The Dojo/Dijit (Dojo&#8217;s widget project) toolkit has created a page where you can view many of their widgets using the four CSS themes written so far for Dojo.  This is cool for a couple of reasons.
+Firstly, it showcases the excellent work the Dijit developers have put into new themeing skins.  There are four [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+
+		<title>Dojo theme browser shows off Dijit widgets</title>
+		<link>http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/</guid>
+		
+		<pubDate>Fri, 17 Aug 2007 12:18:57 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Rich Text</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpress.com">dijit</category><category domain="http://shaneosullivan.wordpress.com [...]
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/#comments" thr:count="2"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/08/17/dojo-theme-browser-shows-off-dijit-widgets/feed/atom/" thr:count="2"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>Yahoo have released a very useful extension for Firebug, which is itself an extension for Firefox, which can be used to analyze a web page&#8217;s performance.  The extension, called YSlow, appears as a separate pane in Firebug, and gives you a whole load of statistics about your page.
+However, in addition to the bare numbers, [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+
+		<title>Why is my web page slow? YSlow for Firebug can tell you.</title>
+		<link>http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/</guid>
+		
+		<pubDate>Wed, 25 Jul 2007 15:08:30 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Firebug</category><category domain="http://shaneosullivan.wordpress.com">Firefox</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpress.com">tools</category>		
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/#comments" thr:count="1"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/07/25/why-is-my-web-page-slow-yslow-for-firebug-can-tell-you/feed/atom/" thr:count="1"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>I have created an Image Gallery widget built on Dojo 0.4.3 that integrates nicely with Flickr.  The widget it written entirely using JavaScript and CSS as a standalone Dojo widget, and is released under the same open source license as Dojo, the Academic Free License.
+For more information, including the code and examples, see http://www.skynet.ie/~sos/ajax/imagegallery.php.
+Some [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+		<title>Flickr and Dojo Image Gallery</title>
+
+		<link>http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/</guid>
+		
+		<pubDate>Tue, 03 Jul 2007 15:53:33 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Flickr</category><category domain="http://shaneosullivan.wordpress.com">Image Gallery</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpres [...]
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/#comments" thr:count="7"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/07/03/flickr-and-dojo-image-gallery/feed/atom/" thr:count="7"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>The two main areas of interest for me over the last year or two, blog-wise that is, have been the Dojo Ajax toolkit, one of the more popular open source JavaScript toolkits, and Ubuntu Linux, the very popular operating system that is seen by many as the best chance Linux has of succeeding on the [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+		<title>Is Dojo being ignored by developers?</title>
+
+		<link>http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/</guid>
+		
+		<pubDate>Tue, 19 Jun 2007 10:36:49 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpress.com">open source</category>		
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/#comments" thr:count="5"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/06/19/is-dojo-being-ignored-by-developers/feed/atom/" thr:count="5"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>I&#8217;ve created an example usage of the Dojo Charting engine, which you can find at http://www.skynet.ie/~sos/pageStats.php.  View the source to see how it works.
+It&#8217;s a modified version of the unit test available with the Dojo toolkit, but used in a specific scenario - in this case, to graph the page impressions for my personal [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+
+</managingEditor>
+		<title>Dojo Charting example to show website statistics</title>
+		<link>http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/</guid>
+		
+		<pubDate>Fri, 15 Jun 2007 12:35:35 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Dojo</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Technical</category><category domain="http://shaneosullivan.wordpress.com">chart</category><category domain="http://shaneosullivan.wordpress.com">charting</category><category domain="http://shaneosullivan.wordpress.com" [...]
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/#comments" thr:count="4"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/06/15/dojo-charting-example-to-show-website-statistics-2/feed/atom/" thr:count="4"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>I decided today that I wanted to put links at the bottom of each of my blog posts that would allow people to  perform actions on the post, e.g:
+
+Digg it
+Kick it
+Mail it
+Bookmark it on del.icio.us
+Bookmark it on reddit.com
+Bookmark it on live.com
+
+My blog is on Wordpress.com which doesn&#8217;t seem to have a plugin that will [...] (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+
+		<title>GreaseMonkey script to add Digg-like links to posts</title>
+		<link>http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/</guid>
+		
+		<pubDate>Tue, 22 May 2007 16:57:02 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Firefox</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">greasemonkey</category>		
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/#comments" thr:count="8"/>
+
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/05/22/greasemonkey-script-to-add-digg-like-links-to-posts/feed/atom/" thr:count="8"/>
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">8</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+		<item><description>Bill Higgins of IBM has written a very well thought out article of why web applications should look and act like web applications, and not the desktop variety.  Well worth a read - http://billhiggins.us/weblog/2007/05/17/the-uncanny-valley-of-user-interface-design
+        (...)</description>
+		<managingEditor>
+	 (Shane O'Sullivan)
+</managingEditor>
+		<title>Article on the square pegs and round holes of desktop and web applications</title>
+
+		<link>http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/</link>
+		<guid>http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/</guid>
+		
+		<pubDate>Tue, 22 May 2007 08:49:00 GMT
+</pubDate>
+		<category domain="http://shaneosullivan.wordpress.com">Ajax</category><category domain="http://shaneosullivan.wordpress.com">Javascript</category><category domain="http://shaneosullivan.wordpress.com">Zimbra</category>		
+		
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="text/html" href="http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/#comments" thr:count="0"/>
+		<!--Unknown element link--><link xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" rel="replies" type="appication/atom+xml" href="http://shaneosullivan.wordpress.com/2007/05/22/article-on-the-square-pegs-and-round-holes-of-desktop-and-web-applications/feed/atom/" thr:count="0"/>
+
+		<!--Unknown element total--><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total>
+	<source url="http://shaneosullivan.wordpress.com/feed/atom/">SOS</source></item>
+	<generator>WordPress vMU (http://wordpress.org/) + Atom 1.0 XSLT Transform v1 (http://atom.geekhood.net/)</generator></channel>
+</rss>
\ No newline at end of file
diff --git a/dojox/data/tests/stores/semicolonSeparator.csv b/dojox/data/tests/stores/semicolonSeparator.csv
new file mode 100755
index 0000000..7cf1008
--- /dev/null
+++ b/dojox/data/tests/stores/semicolonSeparator.csv
@@ -0,0 +1,7 @@
+article;price
+1008;4,59
+1010;10,09
+1011;5,13
+1016;16,68
+1019;15,5
+1022;10,36
diff --git a/dojox/data/tests/stores/snap_pipeline.php b/dojox/data/tests/stores/snap_pipeline.php
new file mode 100644
index 0000000..59e72cb
--- /dev/null
+++ b/dojox/data/tests/stores/snap_pipeline.php
@@ -0,0 +1,72 @@
+<?php
+
+$field_names = array('"empno"', '"ename"', '"job"', '"hiredate"', '"sal"', '"comm"', '"deptno"');
+
+$rows = array(array("7369", '"SMITH,CLERK"', "7902", '"1993-06-13"', "800.00", "0.00", "20"),
+              array("7499", '"ALLEN,SALESMAN"', "7698", '"1998-08-15"', "1600.00", "300.00", "30"),
+              array("7521", '"WARD,SALESMAN"', "7698", '"1996-03-26"', "1250.00", "500.00", "30"),
+              array("7566", '"JONES,MANAGER"', "7839", '"1995-10-31"', "2975.00", '""', "20"),
+              array("7698", '"BLAKE,MANAGER"', "7839", '"1992-06-11"', "2850.00", '""', "30"),
+              array("7782", '"CLARK,MANAGER"', "7839", '"1993-05-14"', "2450.00", '""', "10"),
+              array("7788", '"SCOTT,ANALYST"', "7566", '"1996-03-05"', "3000.00", '""', "20"),
+              array("7839", '"KING,PRESIDENT"', '"1990-06-09"', "5000", "1100.0", '""', "0.00", "10"),
+              array("7844", '"TURNER,SALESMAN"', "7698", '"1995-06-04"', "1500.00", '""', "0.00", "30"),
+              array("7876", '"ADAMS,CLERK"', "7788", '"1999-06-04"', "1100.00", '""', "20"),
+              array("7900", '"JAMES,CLERK"', "7698", '"2000-06-23"', "950.00", '""', "30"),
+              array("7934", '"MILLER,CLERK"', "7782", '"2000-01-21"', "1300.00", '""', "10"),
+              array("7902", '"FORD,ANALYST"', "7566", '"1997-12-05"', "3000.00", '""', "20"),
+              array("7654", '"MARTIN,SALESMAN"', "7698", '"1998-12-05"', "1250.00", "1400.00", "30"));
+
+$prefix = htmlentities($_GET["sn_stream_header"]);
+
+if($_GET["sn_count"]) {
+    if($_GET["sn_count"] == "records"){
+        echo $prefix . "([[" . count($rows) . "]])";
+    } else {
+        header("HTTP/1.1 400 Bad Request");
+        echo "sn.count parameter, if present, must be set to 'records'.";
+        exit(0);
+    }
+} else {
+    if($_GET["sn_start"]) {
+        $start = $_GET["sn_start"];
+    } else {
+        $start = 1;
+    }
+
+    if($_GET["sn_limit"]) {
+        $limit = $_GET["sn_limit"];
+    } else {
+        $limit = count($rows);
+    }
+
+    if(!is_numeric($start) || !is_numeric($limit)) {
+        header("HTTP/1.1 400 Bad Request");
+        echo "sn.start or sn.limit specified a non-integer value";
+        exit(0);
+    }
+
+    $start -= 1;
+
+    if($start < 0 || $start >= count($rows) || $limit < 0) {
+        header("HTTP/1.1 400 Bad Request");
+        echo "sn.start and/or sn.limit out of range";
+        exit(0);
+    }
+
+    $slice = array_slice($rows, $start, $limit);
+
+    header("Content-type: application/javascript");
+    echo $prefix . "([";
+
+    $out_rows = array("[" . join(", ", $field_names) . "]");
+    foreach($slice as $r) {
+        $out_rows[] = "[" . join(", ", $r) . "]";
+    }
+    
+    echo join(", ", $out_rows);
+    echo "])";
+ }
+
+?>
+
diff --git a/dojox/data/tests/stores/test1.css b/dojox/data/tests/stores/test1.css
new file mode 100755
index 0000000..ff0ac3a
--- /dev/null
+++ b/dojox/data/tests/stores/test1.css
@@ -0,0 +1,2 @@
+.linkTestClass { text-align: center; }
+.linkTestClass .test { background-color: blue; }
diff --git a/dojox/data/tests/stores/test2.css b/dojox/data/tests/stores/test2.css
new file mode 100755
index 0000000..cc21e7d
--- /dev/null
+++ b/dojox/data/tests/stores/test2.css
@@ -0,0 +1 @@
+.importTestClass { text-align: center; }
diff --git a/dojox/data/tests/stores/test_Tree_on_JsonRestStore.html b/dojox/data/tests/stores/test_Tree_on_JsonRestStore.html
new file mode 100644
index 0000000..f7ce121
--- /dev/null
+++ b/dojox/data/tests/stores/test_Tree_on_JsonRestStore.html
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dijit Tree Test</title>
+
+	<style someProperty="text/css">
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../../dijit/themes/tundra/tundra.css">
+
+	<!-- required: dojo.js -->
+	<script someProperty="text/javascript" src="../../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<!-- do not use: only for testing alternate themes -->
+	<script someProperty="text/javascript" src="../../../../dijit/tests/_testCommon.js"></script>
+
+	<script language="JavaScript" someProperty="text/javascript">
+		dojo.require("dojox.data.JsonRestStore");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.Menu");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+		treeTestStore = new dojox.data.JsonRestStore({target:"./", labelAttribute:"name"});
+		treeTestModel = new dijit.tree.ForestStoreModel({
+			store: treeTestStore,
+			deferItemLoadingUntilExpand: true,
+			query: "treeTestRoot",
+			childrenAttrs: ["children"]
+		});
+		function deleteItem(){
+			var store = dijit.byId("myTree").store;
+			store.deleteItem(selectedItem);
+			resetForms();
+		}
+
+		function addItem(){
+			var store = dijit.byId("myTree").store;
+			var pInfo = selectedItem ? {parent: selectedItem, attribute:"children"} : null;
+			console.debug(pInfo);
+			store.newItem({id: dojo.byId('newId').value,name:dojo.byId("label").value,someProperty:dojo.byId("someProperty").value},pInfo);
+			resetForms();
+		}
+
+		function resetForms() {
+			dojo.byId('selected').innerHTML="Tree Root"
+			selectedItem=null;
+			dojo.byId("uLabel").value = "";
+			dojo.byId("uSomeProperty").value = "";
+		}
+
+		function updateItem(){
+			console.log("Updating Item");
+			var store = dijit.byId("myTree").store;
+
+			if (selectedItem!=null){
+				if (dojo.byId("uLabel").value != store.getValue(selectedItem, "name")){
+					store.setValue(selectedItem, "name", dojo.byId("uLabel").value);
+				}
+
+				if (dojo.byId("uSomeProperty").value != store.getValue(selectedItem, "someProperty")){
+					store.setValue(selectedItem, "someProperty", dojo.byId("uSomeProperty").value);
+				}
+
+			}else{
+				console.error("Can't update the tree root");
+			}
+		}
+
+		dojo.addOnLoad(function(){
+			resetForms();
+		});
+
+		function onClick(item){
+			selectedItem = item;
+			dojo.byId('selected').innerHTML= item ? treeTestStore.getLabel(item) : "";
+			dojo.byId('uLabel').value = item ? treeTestStore.getLabel(item) : "";
+			dojo.byId('uSomeProperty').value = item ? treeTestStore.getValue(item,"someProperty") : "";
+		}
+	</script>
+
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">Dijit Tree Test - dojo.data.Notification API support</h1>
+
+
+	<div dojoType="dijit.Tree" id="myTree" label="root" deferItemLoadingUntilExpand="true" model="treeTestModel" onClick="onClick" labelAttr="name" somePropertyAttr="someProperty"></div>
+
+	<br />
+	<h2>Current Selection: <span id='selected'>Tree Root</span></h2>
+
+	<h2>Selected Item:</h2>
+	Name:		<input id="uLabel" width="50" value="Enter Node Label" /><br />
+	Description: <input id="uSomeProperty" width="50" value="Some Test Property" /><br /><br />
+	<div dojoType="dijit.form.Button" iconClass="noteIcon" onClick="updateItem();">Update Item</div>
+
+	<h2>New Item</h2>
+	<p>Enter an Id, Name, and optionally a description to be added as a new item to the store.  Upon successful addition, the tree will recieve notification of this event and respond accordingly.  If you select a node the item will be added to that node, otherwise the item will be added to the tree root. "Id" is the identifer here and as such must be unique for all items in the store.</p>
+	Id:		<input id="newId" width="50" value="Enter Item Id" /><br />
+	Name:		<input id="label" width="50" value="Enter Item Name" /><br />
+	Description: <input id="someProperty" width="50" value="Enter Some Property Value" /><br /><br />
+
+	<div dojoType="dijit.form.Button" iconClass="noteIcon" onClick="addItem();">Add Item to Store</div>
+	<br />
+	<button dojoType="dijit.form.Button" iconClass="noteIcon" onClick="deleteItem()">Delete Node (and children)</button>
+
+
+	</body>
+</html>
diff --git a/dojox/data/tests/stores/treeTestRoot b/dojox/data/tests/stores/treeTestRoot
new file mode 100644
index 0000000..4a9adf1
--- /dev/null
+++ b/dojox/data/tests/stores/treeTestRoot
@@ -0,0 +1,10 @@
+[ 
+	{ id: 'node1', name:'node1', someProperty:'somePropertyA', children:[
+			{ $ref: 'node1.1', name: 'node1.1', children: true},
+			{ $ref: 'node1.2', name: 'node1.2'}
+	]},
+	{ id: 'node2', name:'node2', someProperty:'somePropertyB'},
+	{ id: 'node3', name:'node3', someProperty:'somePropertyC'},
+	{ id: 'node4', name:'node4', someProperty:'somePropertyA'},
+	{ id: 'node5', name:'node5', someProperty:'somePropertyB'}
+]
diff --git a/dojox/data/tests/treeTest.json b/dojox/data/tests/treeTest.json
new file mode 100644
index 0000000..70cc7d8
--- /dev/null
+++ b/dojox/data/tests/treeTest.json
@@ -0,0 +1,10 @@
+{ 
+	node1: { id: 'node1', name:'node1', someProperty:'somePropertyA', children:[
+			{ id: 'node1.1',name:'node1.1', someProperty:'somePropertyA1'},
+			{ id: 'node1.2',name:'node1.2', someProperty:'somePropertyA2'}
+	]},
+	node2:{ id: 'node2', name:'node2', someProperty:'somePropertyB'},
+	node3:{ id: 'node3', name:'node3', someProperty:'somePropertyC'},
+	node4:{ id: 'node4', name:'node4', someProperty:'somePropertyA'},
+	node5:{ id: 'node5', name:'node5', someProperty:'somePropertyB'}
+}
diff --git a/dojox/data/util/JsonQuery.js b/dojox/data/util/JsonQuery.js
index 49f6bcf..34a17df 100644
--- a/dojox/data/util/JsonQuery.js
+++ b/dojox/data/util/JsonQuery.js
@@ -1,89 +1,93 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.data.util.JsonQuery"]){
-dojo._hasResource["dojox.data.util.JsonQuery"]=true;
 dojo.provide("dojox.data.util.JsonQuery");
-dojo.declare("dojox.data.util.JsonQuery",null,{useFullIdInQueries:false,_toJsonQuery:function(_1,_2){
-var _3=true;
-var _4=this;
-function _5(_6,_7){
-var _8=_7.__id;
-if(_8){
-var _9={};
-_9[_4.idAttribute]=_4.useFullIdInQueries?_7.__id:_7[_4.idAttribute];
-_7=_9;
-}
-for(var i in _7){
-var _a=_7[i];
-var _b=_6+(/^[a-zA-Z_][\w_]*$/.test(i)?"."+i:"["+dojo._escapeString(i)+"]");
-if(_a&&typeof _a=="object"){
-_5(_b,_a);
-}else{
-if(_a!="*"){
-_c+=(_3?"":"&")+_b+((!_8&&typeof _a=="string"&&_1.queryOptions&&_1.queryOptions.ignoreCase)?"~":"=")+(_4.simplifiedQuery?encodeURIComponent(_a):dojo.toJson(_a));
-_3=false;
-}
-}
-}
-};
-if(_1.query&&typeof _1.query=="object"){
-var _c="[?(";
-_5("@",_1.query);
-if(!_3){
-_c+=")]";
-}else{
-_c="";
-}
-_1.queryStr=_c.replace(/\\"|"/g,function(t){
-return t=="\""?"'":t;
+// this is a mixin to convert object attribute queries to 
+// JSONQuery/JSONPath syntax to be sent to the server.
+dojo.declare("dojox.data.util.JsonQuery", null, {
+	useFullIdInQueries: false,
+	_toJsonQuery: function(args, jsonQueryPagination){
+		var first = true;
+		var self = this;
+		function buildQuery(path, query){
+			var isDataItem = query.__id; 
+			if(isDataItem){
+				// it is a reference to a persisted object, need to make it a query by id
+				var newQuery = {};
+				newQuery[self.idAttribute] = self.useFullIdInQueries ? query.__id : query[self.idAttribute];
+				query = newQuery;
+			}
+			for(var i in query){
+				// iterate through each property, adding them to the overall query
+				var value = query[i];
+				var newPath = path + (/^[a-zA-Z_][\w_]*$/.test(i) ? '.' + i : '[' + dojo._escapeString(i) + ']');
+				if(value && typeof value == "object"){
+					buildQuery(newPath, value);
+				}else if(value!="*"){ // full wildcards can be ommitted
+					jsonQuery += (first ? "" : "&") + newPath +
+						((!isDataItem && typeof value == "string" && args.queryOptions && args.queryOptions.ignoreCase) ? "~" : "=") +
+						 (self.simplifiedQuery ? encodeURIComponent(value) : dojo.toJson(value));
+					first = false;
+				}
+			}			
+		}
+		// performs conversion of Dojo Data query objects and sort arrays to JSONQuery strings
+		if(args.query && typeof args.query == "object"){
+			// convert Dojo Data query objects to JSONQuery
+			var jsonQuery = "[?(";
+			buildQuery("@", args.query);
+			if(!first){
+				// use ' instead of " for quoting in JSONQuery, and end with ]
+				jsonQuery += ")]"; 
+			}else{
+				jsonQuery = "";
+			}
+			args.queryStr = jsonQuery.replace(/\\"|"/g,function(t){return t == '"' ? "'" : t;});
+		}else if(!args.query || args.query == '*'){
+			args.query = "";
+		}
+		
+		var sort = args.sort;
+		if(sort){
+			// if we have a sort order, add that to the JSONQuery expression
+			args.queryStr = args.queryStr || (typeof args.query == 'string' ? args.query : ""); 
+			first = true;
+			for(i = 0; i < sort.length; i++){
+				args.queryStr += (first ? '[' : ',') + (sort[i].descending ? '\\' : '/') + "@[" + dojo._escapeString(sort[i].attribute) + "]";
+				first = false; 
+			}
+		}
+		// this is optional because with client side paging JSONQuery doesn't yield the total count
+		if(jsonQueryPagination && (args.start || args.count)){
+			// pagination
+			args.queryStr = (args.queryStr || (typeof args.query == 'string' ? args.query : "")) +
+				'[' + (args.start || '') + ':' + (args.count ? (args.start || 0) + args.count : '') + ']'; 
+		}
+		if(typeof args.queryStr == 'string'){
+			args.queryStr = args.queryStr.replace(/\\"|"/g,function(t){return t == '"' ? "'" : t;});
+			return args.queryStr;
+		}
+		return args.query;
+	},
+	jsonQueryPagination: true,
+	fetch: function(args){
+		this._toJsonQuery(args, this.jsonQueryPagination);
+		return this.inherited(arguments);
+	},
+	isUpdateable: function(){
+		return true;
+	},
+	matchesQuery: function(item,request){
+		request._jsonQuery = request._jsonQuery || dojox.json.query(this._toJsonQuery(request)); 
+		return request._jsonQuery([item]).length;
+	},
+	clientSideFetch: function(/*Object*/ request,/*Array*/ baseResults){
+		request._jsonQuery = request._jsonQuery || dojox.json.query(this._toJsonQuery(request));
+		// we use client side paging function here instead of JSON Query because we must also determine the total count
+		return this.clientSidePaging(request, request._jsonQuery(baseResults));
+	},
+	querySuperSet: function(argsSuper,argsSub){
+		if(!argsSuper.query){
+			return argsSub.query;
+		}
+		return this.inherited(arguments);
+	}
+	
 });
-}else{
-if(!_1.query||_1.query=="*"){
-_1.query="";
-}
-}
-var _d=_1.sort;
-if(_d){
-_1.queryStr=_1.queryStr||(typeof _1.query=="string"?_1.query:"");
-_3=true;
-for(i=0;i<_d.length;i++){
-_1.queryStr+=(_3?"[":",")+(_d[i].descending?"\\":"/")+"@["+dojo._escapeString(_d[i].attribute)+"]";
-_3=false;
-}
-if(!_3){
-_1.queryStr+="]";
-}
-}
-if(_2&&(_1.start||_1.count)){
-_1.queryStr=(_1.queryStr||(typeof _1.query=="string"?_1.query:""))+"["+(_1.start||"")+":"+(_1.count?(_1.start||0)+_1.count:"")+"]";
-}
-if(typeof _1.queryStr=="string"){
-_1.queryStr=_1.queryStr.replace(/\\"|"/g,function(t){
-return t=="\""?"'":t;
-});
-return _1.queryStr;
-}
-return _1.query;
-},jsonQueryPagination:true,fetch:function(_e){
-this._toJsonQuery(_e,this.jsonQueryPagination);
-return this.inherited(arguments);
-},isUpdateable:function(){
-return true;
-},matchesQuery:function(_f,_10){
-_10._jsonQuery=_10._jsonQuery||dojox.json.query(this._toJsonQuery(_10));
-return _10._jsonQuery([_f]).length;
-},clientSideFetch:function(_11,_12){
-_11._jsonQuery=_11._jsonQuery||dojox.json.query(this._toJsonQuery(_11));
-return this.clientSidePaging(_11,_11._jsonQuery(_12));
-},querySuperSet:function(_13,_14){
-if(!_13.query){
-return _14.query;
-}
-return this.inherited(arguments);
-}});
-}
diff --git a/dojox/date/README b/dojox/date/README
index 605baab..401e6c1 100644
--- a/dojox/date/README
+++ b/dojox/date/README
@@ -5,7 +5,12 @@ Version 0.9
 Release date: 5/17/2007
 -------------------------------------------------------------------------------
 Project state:
-experimental
+varies
+
+Buddhist, Hebrew, Islamic calendars: stable
+posix, php: beta
+timezone: experimental
+
 -------------------------------------------------------------------------------
 Credits
 	Paul Sowden (dojox.date.posix)
@@ -18,6 +23,7 @@ Project description
 
 Placeholder for any kind of date operations, including formatters that are
 common to other languages (posix and php).
+
 -------------------------------------------------------------------------------
 Dependencies:
 
diff --git a/dojox/date/buddhist.js b/dojox/date/buddhist.js
index 4846759..376b919 100644
--- a/dojox/date/buddhist.js
+++ b/dojox/date/buddhist.js
@@ -1,182 +1,240 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.buddhist"]){
-dojo._hasResource["dojox.date.buddhist"]=true;
 dojo.provide("dojox.date.buddhist");
 dojo.experimental("dojox.date.buddhist");
+
 dojo.require("dojox.date.buddhist.Date");
-dojo.require("dojo.date");
-dojox.date.buddhist.getDaysInMonth=function(_1){
-return dojo.date.getDaysInMonth(_1.toGregorian());
-};
-dojox.date.buddhist.isLeapYear=function(_2){
-return dojo.date.isLeapYear(_2.toGregorian());
-};
-dojox.date.buddhist.compare=function(_3,_4,_5){
-return dojo.date.compare(_3,_4,_5);
+dojo.require("dojo.date"); // for compare
+	
+// Utility methods to do arithmetic calculations with buddhist.Dates
+
+dojox.date.buddhist.getDaysInMonth = function(/*buddhist.Date*/dateObject){
+	return dojo.date.getDaysInMonth(dateObject.toGregorian());
 };
-dojox.date.buddhist.add=function(_6,_7,_8){
-var _9=new dojox.date.buddhist.Date(_6);
-switch(_7){
-case "day":
-_9.setDate(_6.getDate(true)+_8);
-break;
-case "weekday":
-var _a,_b;
-var _c=_8%5;
-if(!_c){
-_a=(_8>0)?5:-5;
-_b=(_8>0)?((_8-5)/5):((_8+5)/5);
-}else{
-_a=_c;
-_b=parseInt(_8/5);
-}
-var _d=_6.getDay();
-var _e=0;
-if(_d==6&&_8>0){
-_e=1;
-}else{
-if(_d==0&&_8<0){
-_e=-1;
-}
-}
-var _f=_d+_a;
-if(_f==0||_f==6){
-_e=(_8>0)?2:-2;
-}
-_8=(7*_b)+_a+_e;
-_9.setDate(_6.getDate(true)+_8);
-break;
-case "year":
-_9.setFullYear(_6.getFullYear()+_8);
-break;
-case "week":
-_8*=7;
-_9.setDate(_6.getDate(true)+_8);
-break;
-case "month":
-_9.setMonth(_6.getMonth()+_8);
-break;
-case "hour":
-_9.setHours(_6.getHours()+_8);
-break;
-case "minute":
-_9.setMinutes(_6.getMinutes()+_8);
-break;
-case "second":
-_9.setSeconds(_6.getSeconds()+_8);
-break;
-case "millisecond":
-_9.setMilliseconds(_6.getMilliseconds()+_8);
-break;
-}
-return _9;
+
+dojox.date.buddhist.isLeapYear = function(/*buddhist.Date*/dateObject){
+	return dojo.date.isLeapYear(dateObject.toGregorian());
 };
-dojox.date.buddhist.difference=function(_10,_11,_12){
-_11=_11||new dojox.date.buddhist.Date();
-_12=_12||"day";
-var _13=_10.getFullYear()-_11.getFullYear();
-var _14=1;
-switch(_12){
-case "weekday":
-var _15=Math.round(dojox.date.buddhist.difference(_10,_11,"day"));
-var _16=parseInt(dojox.date.buddhist.difference(_10,_11,"week"));
-var mod=_15%7;
-if(mod==0){
-_15=_16*5;
-}else{
-var adj=0;
-var _17=_11.getDay();
-var _18=_10.getDay();
-_16=parseInt(_15/7);
-mod=_15%7;
-var _19=new dojox.date.buddhist.Date(_10);
-_19.setDate(_19.getDate(true)+(_16*7));
-var _1a=_19.getDay();
-if(_15>0){
-switch(true){
-case _17==5:
-adj=-1;
-break;
-case _17==6:
-adj=0;
-break;
-case _18==5:
-adj=-1;
-break;
-case _18==6:
-adj=-2;
-break;
-case (_1a+mod)>5:
-adj=-2;
-}
-}else{
-if(_15<0){
-switch(true){
-case _17==5:
-adj=0;
-break;
-case _17==6:
-adj=1;
-break;
-case _18==5:
-adj=2;
-break;
-case _18==6:
-adj=1;
-break;
-case (_1a+mod)<0:
-adj=2;
-}
-}
-}
-_15+=adj;
-_15-=(_16*2);
-}
-_14=_15;
-break;
-case "year":
-_14=_13;
-break;
-case "month":
-var _1b=(_10.toGregorian()>_11.toGregorian())?_10:_11;
-var _1c=(_10.toGregorian()>_11.toGregorian())?_11:_10;
-var _1d=_1b.getMonth();
-var _1e=_1c.getMonth();
-if(_13==0){
-_14=_1b.getMonth()-_1c.getMonth();
-}else{
-_14=12-_1e;
-_14+=_1d;
-var i=_1c.getFullYear()+1;
-var e=_1b.getFullYear();
-for(i;i<e;i++){
-_14+=12;
-}
-}
-if(_10.toGregorian()<_11.toGregorian()){
-_14=-_14;
-}
-break;
-case "week":
-_14=parseInt(dojox.date.buddhist.difference(_10,_11,"day")/7);
-break;
-case "day":
-_14/=24;
-case "hour":
-_14/=60;
-case "minute":
-_14/=60;
-case "second":
-_14/=1000;
-case "millisecond":
-_14*=_10.toGregorian().getTime()-_11.toGregorian().getTime();
-}
-return Math.round(_14);
+
+//FIXME: reduce compare, add, diff also
+dojox.date.buddhist.compare = function(/*buddhist.Date*/date1, /*buddhist.Date*/date2, /*String?*/portion){
+//	summary:
+	//		Compare two buddhist date objects by date, time, or both.
+	return dojo.date.compare(date1,date2, portion); //FIXME
 };
-}
+
+
+dojox.date.buddhist.add = function(/*dojox.date.buddhist.Date*/date, /*String*/interval, /*int*/amount){
+	//	based on and similar to dojo.date.add
+	//	summary:
+	//		Add to a Date in intervals of different size, from milliseconds to years
+	//	date: buddhist.Date
+	//		Date object to start with
+	//	interval:
+	//		A string representing the interval.  One of the following:
+	//			"year", "month", "day", "hour", "minute", "second",
+	//			"millisecond", "week", "weekday"
+	//	amount:
+	//		How much to add to the date.
+
+	var newBuddDate = new dojox.date.buddhist.Date(date);
+
+	switch(interval){
+		case "day":
+			newBuddDate.setDate(date.getDate(true) + amount);
+			break;
+		case "weekday":
+			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;
+			newBuddDate.setDate(date.getDate(true) + amount);
+			break;
+		case "year":
+			newBuddDate.setFullYear(date.getFullYear() + amount );
+			break;
+		case "week":
+			amount *= 7;
+			newBuddDate.setDate(date.getDate(true) + amount);
+			break;
+		case "month":
+			newBuddDate.setMonth(date.getMonth() + amount);
+			break;
+		case "hour":
+			newBuddDate.setHours(date.getHours() + amount );
+			break;	
+		case "minute":
+			newBuddDate.setMinutes(date.getMinutes() + amount );
+			break;	
+		case "second":
+			newBuddDate.setSeconds(date.getSeconds() + amount );
+			break;	
+		case "millisecond":
+			newBuddDate.setMilliseconds(date.getMilliseconds() + amount );
+			break;
+	}
+	return newBuddDate; // dojox.date.buddhist.Date
+}; 
+
+dojox.date.buddhist.difference = function(/*dojox.date.buddhist.Date*/date1, /*dojox.date.buddhist.Date?*/date2, /*String?*/interval){
+	//	based on and similar to dojo.date.difference
+	//	summary:
+	//        date1 - date2
+	//	 date2 is hebrew.Date object.  If not specified, the current hebrew.Date is used.
+	//	interval:
+	//		A string representing the interval.  One of the following:
+	//			"year", "month", "day", "hour", "minute", "second",
+	//			"millisecond",  "week", "weekday"
+	//		Defaults to "day".
+	
+	date2 = date2 || new dojox.date.buddhist.Date();
+	interval = interval || "day";
+	var yearDiff = date1.getFullYear() - date2.getFullYear();
+	var delta = 1; // Integer return value
+	switch(interval){
+		case "weekday":
+			var days = Math.round(dojox.date.buddhist.difference(date1, date2, "day"));
+			var weeks = parseInt(dojox.date.buddhist.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 = date2.getDay();
+				var bDay = date1.getDay();
+	
+				weeks = parseInt(days/7);
+				mod = days % 7;
+				// Mark the date advanced by the number of
+				// round weeks (may be zero)
+				var dtMark = new dojox.date.buddhist.Date(date1);
+				dtMark.setDate(dtMark.getDate(true)+(weeks*7));
+				var dayMark = dtMark.getDay();
+	
+				// Spare change days -- 6 or less
+				if(days > 0){
+					switch(true){
+						// Range starts on Fri
+						case aDay == 5:
+							adj = -1;
+							break;
+						// Range starts on Sat
+						case aDay == 6:
+							adj = 0;
+							break;
+						// Range ends on Fri
+						case bDay == 5:
+							adj = -1;
+							break;
+						// Range ends on Sat
+						case bDay == 6:
+							adj = -2;
+							break;
+						// Range contains weekend
+						case (dayMark + mod) > 5:
+							adj = -2;
+					}
+				}else if(days < 0){
+					switch(true){
+						// Range starts on Fri
+						case aDay == 5:
+							adj = 0;
+							break;
+						// Range starts on Sat
+						case aDay == 6:
+							adj = 1;
+							break;
+						// Range ends on Fri
+						case bDay == 5:
+							adj = 2;
+							break;
+						// Range ends on Sat
+						case bDay == 6:
+							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":
+			var startdate =  (date1.toGregorian() > date2.toGregorian()) ? date1 : date2; // more
+			var enddate = (date1.toGregorian() > date2.toGregorian()) ? date2 : date1;
+			
+			var month1 = startdate.getMonth();
+			var month2 = enddate.getMonth();
+			
+			if (yearDiff == 0){
+				delta = startdate.getMonth() - enddate.getMonth() ;
+			}else{
+				delta = 12-month2;
+				delta +=  month1;
+				var i = enddate.getFullYear()+1;
+				var e = startdate.getFullYear();
+				for (i;   i < e;  i++){
+					delta += 12; 
+				}
+			}
+			if (date1.toGregorian() < date2.toGregorian()){
+				delta = -delta;
+			}
+			break;
+		case "week":
+			// Truncate instead of rounding
+			// Don't use Math.floor -- value may be negative
+			delta = parseInt(dojox.date.buddhist.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 *= date1.toGregorian().getTime()- date2.toGregorian().getTime();
+	}
+	
+	// Round for fractional values and DST leaps
+	return Math.round(delta); // Number (integer) 
+};
\ No newline at end of file
diff --git a/dojox/date/buddhist/Date.js b/dojox/date/buddhist/Date.js
index 7bcf889..9511fb8 100644
--- a/dojox/date/buddhist/Date.js
+++ b/dojox/date/buddhist/Date.js
@@ -1,223 +1,310 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.buddhist.Date"]){
-dojo._hasResource["dojox.date.buddhist.Date"]=true;
 dojo.provide("dojox.date.buddhist.Date");
 dojo.experimental("dojox.date.buddhist.Date");
-dojo.declare("dojox.date.buddhist.Date",null,{_date:0,_month:0,_year:0,_hours:0,_minutes:0,_seconds:0,_milliseconds:0,_day:0,constructor:function(){
-var _1=arguments.length;
-if(!_1){
-this.fromGregorian(new Date());
-}else{
-if(_1==1){
-var _2=arguments[0];
-if(typeof _2=="number"){
-_2=new Date(_2);
-}
-if(_2 instanceof Date){
-this.fromGregorian(_2);
-}else{
-if(_2==""){
-this._date=new Date("");
-}else{
-this._year=_2._year;
-this._month=_2._month;
-this._date=_2._date;
-this._hours=_2._hours;
-this._minutes=_2._minutes;
-this._seconds=_2._seconds;
-this._milliseconds=_2._milliseconds;
-}
-}
-}else{
-if(_1>=3){
-this._year+=arguments[0];
-this._month+=arguments[1];
-this._date+=arguments[2];
-if(this._month>11){
-console.warn("the month is incorrect , set 0");
-this._month=0;
-}
-this._hours+=arguments[3]||0;
-this._minutes+=arguments[4]||0;
-this._seconds+=arguments[5]||0;
-this._milliseconds+=arguments[6]||0;
-}
-}
-}
-},getDate:function(_3){
-return parseInt(this._date);
-},getMonth:function(){
-return parseInt(this._month);
-},getFullYear:function(){
-return parseInt(this._year);
-},getHours:function(){
-return this._hours;
-},getMinutes:function(){
-return this._minutes;
-},getSeconds:function(){
-return this._seconds;
-},getMilliseconds:function(){
-return this._milliseconds;
-},setDate:function(_4){
-_4=parseInt(_4);
-if(_4>0&&_4<=this._getDaysInMonth(this._month,this._year)){
-this._date=_4;
-}else{
-var _5;
-if(_4>0){
-for(_5=this._getDaysInMonth(this._month,this._year);_4>_5;_4-=_5,_5=this._getDaysInMonth(this._month,this._year)){
-this._month++;
-if(this._month>=12){
-this._year++;
-this._month-=12;
-}
-}
-this._date=_4;
-}else{
-for(_5=this._getDaysInMonth((this._month-1)>=0?(this._month-1):11,((this._month-1)>=0)?this._year:this._year-1);_4<=0;_5=this._getDaysInMonth((this._month-1)>=0?(this._month-1):11,((this._month-1)>=0)?this._year:this._year-1)){
-this._month--;
-if(this._month<0){
-this._year--;
-this._month+=12;
-}
-_4+=_5;
-}
-this._date=_4;
-}
-}
-return this;
-},setFullYear:function(_6,_7,_8){
-this._year=parseInt(_6);
-},setMonth:function(_9){
-this._year+=Math.floor(_9/12);
-this._month=Math.floor(_9%12);
-for(;this._month<0;this._month=this._month+12){
-}
-},setHours:function(){
-var _a=arguments.length;
-var _b=0;
-if(_a>=1){
-_b=parseInt(arguments[0]);
-}
-if(_a>=2){
-this._minutes=parseInt(arguments[1]);
-}
-if(_a>=3){
-this._seconds=parseInt(arguments[2]);
-}
-if(_a==4){
-this._milliseconds=parseInt(arguments[3]);
-}
-while(_b>=24){
-this._date++;
-var _c=this._getDaysInMonth(this._month,this._year);
-if(this._date>_c){
-this._month++;
-if(this._month>=12){
-this._year++;
-this._month-=12;
-}
-this._date-=_c;
-}
-_b-=24;
-}
-this._hours=_b;
-},setMinutes:function(_d){
-while(_d>=60){
-this._hours++;
-if(this._hours>=24){
-this._date++;
-this._hours-=24;
-var _e=this._getDaysInMonth(this._month,this._year);
-if(this._date>_e){
-this._month++;
-if(this._month>=12){
-this._year++;
-this._month-=12;
-}
-this._date-=_e;
-}
-}
-_d-=60;
-}
-this._minutes=_d;
-},setSeconds:function(_f){
-while(_f>=60){
-this._minutes++;
-if(this._minutes>=60){
-this._hours++;
-this._minutes-=60;
-if(this._hours>=24){
-this._date++;
-this._hours-=24;
-var _10=this._getDaysInMonth(this._month,this._year);
-if(this._date>_10){
-this._month++;
-if(this._month>=12){
-this._year++;
-this._month-=12;
-}
-this._date-=_10;
-}
-}
-}
-_f-=60;
-}
-this._seconds=_f;
-},setMilliseconds:function(_11){
-while(_11>=1000){
-this.setSeconds++;
-if(this.setSeconds>=60){
-this._minutes++;
-this.setSeconds-=60;
-if(this._minutes>=60){
-this._hours++;
-this._minutes-=60;
-if(this._hours>=24){
-this._date++;
-this._hours-=24;
-var _12=this._getDaysInMonth(this._month,this._year);
-if(this._date>_12){
-this._month++;
-if(this._month>=12){
-this._year++;
-this._month-=12;
-}
-this._date-=_12;
-}
-}
-}
-}
-_11-=1000;
-}
-this._milliseconds=_11;
-},toString:function(){
-return this._date+", "+this._month+", "+this._year+"  "+this._hours+":"+this._minutes+":"+this._seconds;
-},_getDaysInMonth:function(_13,_14){
-return dojo.date.getDaysInMonth(new Date(_14-543,_13));
-},fromGregorian:function(_15){
-var _16=new Date(_15);
-this._date=_16.getDate();
-this._month=_16.getMonth();
-this._year=_16.getFullYear()+543;
-this._hours=_16.getHours();
-this._minutes=_16.getMinutes();
-this._seconds=_16.getSeconds();
-this._milliseconds=_16.getMilliseconds();
-this._day=_16.getDay();
-return this;
-},toGregorian:function(){
-return new Date(this._year-543,this._month,this._date,this._hours,this._minutes,this._seconds,this._milliseconds);
-},getDay:function(){
-return this.toGregorian().getDay();
-}});
-dojox.date.buddhist.Date.prototype.valueOf=function(){
-return this.toGregorian().valueOf();
+
+dojo.declare("dojox.date.buddhist.Date", null, {
+
+    _date: 0,
+	_month: 0,
+	_year: 0,
+	_hours: 0,
+	_minutes: 0,
+	_seconds: 0,
+	_milliseconds: 0,
+	_day: 0,
+
+ 	constructor: function(){
+		// summary: This is the constructor
+		// description:
+		//	This fucntion initialize the date object values
+		//
+		// example:
+		// |		var date1 = new dojox.date.buddhist.Date();
+		// |		
+		// |		var date2 = new dojox.date.buddhist.Date(date1);
+		// |
+		// |		var date3 = new dojox.date.buddhist.Date(2552,2,12);
+		var len = arguments.length;
+		if(!len){// use the current date value, added "" to the similarity to date
+			this.fromGregorian(new Date());
+		}else if(len == 1){
+			var arg0 = arguments[0];
+			if(typeof arg0 == "number"){ // this is time "valueof"
+				arg0 = new Date(arg0);
+			}
+
+			if(arg0 instanceof Date){
+				this.fromGregorian(arg0);
+			}else if(arg0 == ""){
+				this._date = new Date("");
+			}else{
+				this._year = arg0._year;
+				this._month =  arg0._month;  
+				this._date = arg0._date;
+				this._hours = arg0._hours;
+				this._minutes = arg0._minutes;
+				this._seconds = arg0._seconds;
+				this._milliseconds = arg0._milliseconds; 
+			}	
+		}else if(len >=3){
+			this._year += arguments[0];
+			this._month += arguments[1];
+			this._date += arguments[2];
+			
+			if(this._month >11){
+				console.warn("the month is incorrect , set 0");
+				this._month = 0;			
+			}
+			this._hours += arguments[3] || 0;
+			this._minutes += arguments[4] || 0;
+			this._seconds += arguments[5] || 0;
+			this._milliseconds += arguments[6] || 0;
+		}
+	},
+	
+	getDate: function(/*boolean?*/isNumber){
+		// summary: This function returns the date value (0 - 30)
+		//
+		// example:
+		// |		var date1 = new dojox.date.buddhist.Date();
+		// |
+		// |		console.log(date1.getDate());
+		return parseInt(this._date);
+	},
+
+	getMonth: function(){
+		// summary: This function return the month value ( 0 - 11 )
+		//
+		// example:
+		// |		var date1 = new dojox.date.buddhist.Date();
+		// |
+		// |		console.log(date1.getMonth()+1);
+		return parseInt(this._month);
+	},
+
+
+	getFullYear: function(){
+		// summary: This function return the Year value 
+		//
+		// example:
+		// |		var date1 = new dojox.date.buddhist.Date();
+		// |
+		// |		console.log(date1.getFullYear());
+		return parseInt(this._year);
+	},
+			
+	getHours: function(){
+		//summary: returns the Hour value
+		return this._hours;
+	},
+		
+	getMinutes: function(){
+		//summary: returns the Minuites value
+		return this._minutes;
+	},
+
+	getSeconds: function(){
+		//summary: returns the seconde value
+		return this._seconds;
+	},
+
+	getMilliseconds: function(){
+		//summary: returns the Milliseconds value
+		return this._milliseconds;
+	},
+
+	setDate: function(/*number*/date){	
+		// summary: This function sets the Date
+		// example:
+		// |		var date1 = new dojox.date.buddhist.Date();
+		// |		date1.setDate(2);
+		date = parseInt(date);
+
+		if(date > 0 && date <= this._getDaysInMonth(this._month, this._year)){
+			this._date = date;
+		}else{
+			var mdays;
+			if(date>0){
+				for(mdays = this._getDaysInMonth(this._month, this._year);	
+					date > mdays; 
+						date -= mdays,mdays = this._getDaysInMonth(this._month, this._year)){
+					this._month++;
+					if(this._month >= 12){this._year++; this._month -= 12;}
+				}
+
+				this._date = date;
+			}else{
+				for(mdays = this._getDaysInMonth((this._month-1)>=0 ?(this._month-1) :11 ,((this._month-1)>=0)? this._year: this._year-1);	
+						date <= 0; 
+							mdays = this._getDaysInMonth((this._month-1)>=0 ? (this._month-1) :11,((this._month-1)>=0)? this._year: this._year-1)){
+					this._month--;
+					if(this._month < 0){this._year--; this._month += 12;}
+
+					date+=mdays;
+				}
+				this._date = date;
+			}
+		}
+		return this;
+	},
+	
+	setFullYear: function(/*number*/year, /*number?*/month, /*number?*/ date){
+		// summary: This function set Year 
+		//
+		// example:
+		// |		var date1 = new dojox.date.buddhist.Date();
+		// |		date1.setFullYear(2552);
+		// |		date1.setFullYear(2552, 1, 1);
+		this._year = parseInt(year);
+	},
+			
+	setMonth: function(/*number*/month){
+		// summary: This function set Month
+		//
+		// example:
+		// |		var date1 = new dojox.date.buddhist.Date();
+		// |		date1.setMonth(0); //first month
+		this._year += Math.floor(month / 12);
+		this._month = Math.floor(month % 12);
+		for(; this._month < 0; this._month = this._month+12);
+	},
+			
+	setHours: function(){
+		//summary: set the Hours  0-23
+		var hours_arg_no = arguments.length;
+		var hours = 0;
+		if(hours_arg_no >= 1){
+			hours = parseInt(arguments[0]);
+		}
+			
+		if(hours_arg_no >= 2){
+			this._minutes = parseInt(arguments[1]);
+		}
+			
+		if(hours_arg_no >= 3){
+			this._seconds = parseInt(arguments[2]);
+		}
+			
+		if(hours_arg_no == 4){
+			this._milliseconds = parseInt(arguments[3]);
+		}
+						
+		while(hours >= 24){
+			this._date++;
+			var mdays = this._getDaysInMonth(this._month, this._year);
+			if(this._date > mdays){
+					this._month ++;
+					if(this._month >= 12){this._year++; this._month -= 12;}
+					this._date -= mdays;
+			}
+			hours -= 24;
+		}
+		this._hours = hours;
+	},
+
+	setMinutes: function(/*number*/minutes){
+		//summary: set the Minutes  frm 0-59
+		while(minutes >= 60){
+			this._hours++;
+			if(this._hours >= 24){		 
+				this._date++;
+				this._hours -= 24;
+				var mdays = this._getDaysInMonth(this._month, this._year);
+				if(this._date > mdays){
+						this._month ++;
+						if(this._month >= 12){this._year++; this._month -= 12;}
+						this._date -= mdays;
+				}
+			}
+			minutes -= 60;
+		}
+		this._minutes = minutes;
+	},
+
+	setSeconds: function(/*number*/seconds){
+		//summary: set the Seconds  from 0-59
+		while(seconds >= 60){
+			this._minutes++;
+			if(this._minutes >= 60){
+				this._hours++;
+				this._minutes -= 60;
+				if(this._hours >= 24){		 
+					this._date++;
+					this._hours -= 24;
+					var mdays = this._getDaysInMonth(this._month, this._year);
+					if(this._date > mdays){
+						this._month ++;
+						if(this._month >= 12){this._year++; this._month -= 12;}
+						this._date -= mdays;
+					}
+				}
+			}
+			seconds -= 60;
+		}
+		this._seconds = seconds;
+	},
+
+	setMilliseconds: function(/*number*/milliseconds){
+		//summary: set the milliseconds
+		while(milliseconds >= 1000){
+			this.setSeconds++;
+			if(this.setSeconds >= 60){
+				this._minutes++;
+				this.setSeconds -= 60;
+				if(this._minutes >= 60){
+					this._hours++;
+					this._minutes -= 60;
+					if(this._hours >= 24){		 
+						this._date++;
+						this._hours -= 24;
+						var mdays = this._getDaysInMonth(this._month, this._year);
+				if(this._date > mdays){
+					this._month ++;
+					if(this._month >= 12){this._year++; this._month -= 12;}
+					this._date -= mdays;
+					}
+				}
+			}
+		}
+			milliseconds -= 1000;
+		}
+		this._milliseconds = milliseconds;
+	},
+
+	toString: function(){ 
+		// summary: This returns a string representation of the date in "dd, MM, YYYY HH:MM:SS" format
+		return this._date + ", " + this._month + ", " + this._year + "  " + this._hours + ":" + this._minutes + ":" + this._seconds; // String
+	},
+
+//FIXME: remove this and replace usage with dojox.date.buddhist.getDaysInMonth?
+	_getDaysInMonth: function(/*number*/month, /*number*/ year){
+		return dojo.date.getDaysInMonth(new Date(year-543, month));
+	},
+
+	fromGregorian: function(/*Date*/gdate){
+		// summary: This function sets this Date to the Hebrew Date corresponding to the Gregorian Date
+		var date = new Date(gdate);
+		this._date = date.getDate();
+		this._month = date.getMonth();
+		this._year = date.getFullYear()+543;
+		this._hours = date.getHours();
+		this._minutes = date.getMinutes();
+		this._seconds = date.getSeconds();
+		this._milliseconds = date.getMilliseconds();
+		this._day = date.getDay();
+		return this;
+	},
+
+	toGregorian: function(){
+		// summary: This returns the equivalent Gregorian date value as a Date object
+		return new Date(this._year-543, this._month, this._date, this._hours, this._minutes, this._seconds, this._milliseconds); // Date
+	},
+	
+	getDay: function(){
+		// summary: This function return Week Day value ( 0 - 6 )
+		return this.toGregorian().getDay(); // int
+	}
+});
+
+dojox.date.buddhist.Date.prototype.valueOf = function(){
+	return this.toGregorian().valueOf();
 };
-}
diff --git a/dojox/date/buddhist/locale.js b/dojox/date/buddhist/locale.js
index f9bafeb..cc6dfab 100644
--- a/dojox/date/buddhist/locale.js
+++ b/dojox/date/buddhist/locale.js
@@ -1,372 +1,399 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.buddhist.locale"]){
-dojo._hasResource["dojox.date.buddhist.locale"]=true;
 dojo.provide("dojox.date.buddhist.locale");
 dojo.experimental("dojox.date.buddhist.locale");
+
 dojo.require("dojox.date.buddhist.Date");
 dojo.require("dojo.regexp");
 dojo.require("dojo.string");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojo.cldr","buddhist",null,"th");
+
+dojo.requireLocalization("dojo.cldr", "buddhist");
+
 (function(){
-function _1(_2,_3,_4,_5,_6){
-return _6.replace(/([a-z])\1*/ig,function(_7){
-var s,_8;
-var c=_7.charAt(0);
-var l=_7.length;
-var _9=["abbr","wide","narrow"];
-switch(c){
-case "G":
-s=_3["eraAbbr"][0];
-break;
-case "y":
-s=String(_2.getFullYear());
-break;
-case "M":
-var m=_2.getMonth();
-if(l<3){
-s=m+1;
-_8=true;
-}else{
-var _a=["months","format",_9[l-3]].join("-");
-s=_3[_a][m];
-}
-break;
-case "d":
-s=_2.getDate(true);
-_8=true;
-break;
-case "E":
-var d=_2.getDay();
-if(l<3){
-s=d+1;
-_8=true;
-}else{
-var _b=["days","format",_9[l-3]].join("-");
-s=_3[_b][d];
-}
-break;
-case "a":
-var _c=(_2.getHours()<12)?"am":"pm";
-s=_3[_c];
-break;
-case "h":
-case "H":
-case "K":
-case "k":
-var h=_2.getHours();
-switch(c){
-case "h":
-s=(h%12)||12;
-break;
-case "H":
-s=h;
-break;
-case "K":
-s=(h%12);
-break;
-case "k":
-s=h||24;
-break;
-}
-_8=true;
-break;
-case "m":
-s=_2.getMinutes();
-_8=true;
-break;
-case "s":
-s=_2.getSeconds();
-_8=true;
-break;
-case "S":
-s=Math.round(_2.getMilliseconds()*Math.pow(10,l-3));
-_8=true;
-break;
-default:
-throw new Error("dojox.date.buddhist.locale.formatPattern: invalid pattern char: "+_6);
-}
-if(_8){
-s=dojo.string.pad(s,l);
-}
-return s;
-});
-};
-dojox.date.buddhist.locale.format=function(_d,_e){
-_e=_e||{};
-var _f=dojo.i18n.normalizeLocale(_e.locale);
-var _10=_e.formatLength||"short";
-var _11=dojox.date.buddhist.locale._getBuddhistBundle(_f);
-var str=[];
-var _12=dojo.hitch(this,_1,_d,_11,_f,_e.fullYear);
-if(_e.selector=="year"){
-var _13=_d.getFullYear();
-return _13;
-}
-if(_e.selector!="time"){
-var _14=_e.datePattern||_11["dateFormat-"+_10];
-if(_14){
-str.push(_15(_14,_12));
-}
-}
-if(_e.selector!="date"){
-var _16=_e.timePattern||_11["timeFormat-"+_10];
-if(_16){
-str.push(_15(_16,_12));
-}
-}
-var _17=str.join(" ");
-return _17;
-};
-dojox.date.buddhist.locale.regexp=function(_18){
-return dojox.date.buddhist.locale._parseInfo(_18).regexp;
-};
-dojox.date.buddhist.locale._parseInfo=function(_19){
-_19=_19||{};
-var _1a=dojo.i18n.normalizeLocale(_19.locale);
-var _1b=dojox.date.buddhist.locale._getBuddhistBundle(_1a);
-var _1c=_19.formatLength||"short";
-var _1d=_19.datePattern||_1b["dateFormat-"+_1c];
-var _1e=_19.timePattern||_1b["timeFormat-"+_1c];
-var _1f;
-if(_19.selector=="date"){
-_1f=_1d;
-}else{
-if(_19.selector=="time"){
-_1f=_1e;
-}else{
-_1f=(typeof (_1e)=="undefined")?_1d:_1d+" "+_1e;
-}
-}
-var _20=[];
-var re=_15(_1f,dojo.hitch(this,_21,_20,_1b,_19));
-return {regexp:re,tokens:_20,bundle:_1b};
-};
-dojox.date.buddhist.locale.parse=function(_22,_23){
-_22=_22.replace(/[\u200E\u200F\u202A-\u202E]/g,"");
-if(!_23){
-_23={};
-}
-var _24=dojox.date.buddhist.locale._parseInfo(_23);
-var _25=_24.tokens,_26=_24.bundle;
-var re=new RegExp("^"+_24.regexp+"$");
-var _27=re.exec(_22);
-var _28=dojo.i18n.normalizeLocale(_23.locale);
-if(!_27){
-return null;
-}
-var _29,_2a;
-var _2b=[2513,0,1,0,0,0,0];
-var _2c="";
-var _2d=0;
-var _2e=["abbr","wide","narrow"];
-var _2f=dojo.every(_27,function(v,i){
-if(!i){
-return true;
-}
-var _30=_25[i-1];
-var l=_30.length;
-switch(_30.charAt(0)){
-case "y":
-_2b[0]=Number(v);
-break;
-case "M":
-if(l>2){
-var _31=_26["months-format-"+_2e[l-3]].concat();
-if(!_23.strict){
-v=v.replace(".","").toLowerCase();
-_31=dojo.map(_31,function(s){
-return s?s.replace(".","").toLowerCase():s;
-});
-}
-v=dojo.indexOf(_31,v);
-if(v==-1){
-return false;
-}
-_2d=l;
-}else{
-v--;
-}
-_2b[1]=Number(v);
-break;
-case "D":
-_2b[1]=0;
-case "d":
-_2b[2]=Number(v);
-break;
-case "a":
-var am=_23.am||_26.am;
-var pm=_23.pm||_26.pm;
-if(!_23.strict){
-var _32=/\./g;
-v=v.replace(_32,"").toLowerCase();
-am=am.replace(_32,"").toLowerCase();
-pm=pm.replace(_32,"").toLowerCase();
-}
-if(_23.strict&&v!=am&&v!=pm){
-return false;
-}
-_2c=(v==pm)?"p":(v==am)?"a":"";
-break;
-case "K":
-if(v==24){
-v=0;
-}
-case "h":
-case "H":
-case "k":
-_2b[3]=Number(v);
-break;
-case "m":
-_2b[4]=Number(v);
-break;
-case "s":
-_2b[5]=Number(v);
-break;
-case "S":
-_2b[6]=Number(v);
-}
-return true;
-});
-var _33=+_2b[3];
-if(_2c==="p"&&_33<12){
-_2b[3]=_33+12;
-}else{
-if(_2c==="a"&&_33==12){
-_2b[3]=0;
-}
-}
-var _34=new dojox.date.buddhist.Date(_2b[0],_2b[1],_2b[2],_2b[3],_2b[4],_2b[5],_2b[6]);
-return _34;
+	// Format a pattern without literals
+	function formatPattern(dateObject, bundle, locale, 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["eraAbbr"][0];
+					break;
+				case 'y':
+					s = String(dateObject.getFullYear());
+					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 'd':
+					s = dateObject.getDate(true); 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['dayPeriods-format-wide-' + timePeriod];
+					break;
+				case 'h':
+				case 'H':
+				case 'K':
+				case 'k':
+					var h = dateObject.getHours();
+					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;
+				default:
+					throw new Error("dojox.date.buddhist.locale.formatPattern: invalid pattern char: "+pattern);
+			}
+			if(pad){ s = dojo.string.pad(s, l); }
+			return s;
+		});
+	}	
+	
+dojox.date.buddhist.locale.format = function(/*buddhist.Date*/dateObject, /*object?*/options){
+	// based on and similar to dojo.date.locale.format
+	//summary:
+	//		Format a Date object as a String, using  settings.
+	options = options || {};
+
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	var formatLength = options.formatLength || 'short';
+	var bundle = dojox.date.buddhist.locale._getBuddhistBundle(locale);
+	var str = [];
+
+	var sauce = dojo.hitch(this, formatPattern, dateObject, bundle, locale, options.fullYear);
+	if(options.selector == "year"){
+		var year = dateObject.getFullYear();
+		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
+};	
+
+dojox.date.buddhist.locale.regexp = function(/*object?*/options){
+	//	based on and similar to dojo.date.locale.regexp	
+	// summary:
+	//		Builds the regular needed to parse a buddhist.Date
+	return dojox.date.buddhist.locale._parseInfo(options).regexp; // String
 };
-function _15(_35,_36,_37,_38){
-var _39=function(x){
-return x;
+
+dojox.date.buddhist.locale._parseInfo = function(/*oblect?*/options){
+/* based on and similar to dojo.date.locale._parseInfo */
+
+	options = options || {};
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	var bundle = dojox.date.buddhist.locale._getBuddhistBundle(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 = (typeof (timePattern) == "undefined") ? datePattern : datePattern + ' ' + timePattern;
+	}
+
+	var tokens = [];
+	
+	var re = _processPattern(pattern, dojo.hitch(this, _buildDateTimeRE, tokens, bundle, options));
+	return {regexp: re, tokens: tokens, bundle: bundle};
 };
-_36=_36||_39;
-_37=_37||_39;
-_38=_38||_39;
-var _3a=_35.match(/(''|[^'])+/g);
-var _3b=_35.charAt(0)=="'";
-dojo.forEach(_3a,function(_3c,i){
-if(!_3c){
-_3a[i]="";
-}else{
-_3a[i]=(_3b?_37:_36)(_3c);
-_3b=!_3b;
-}
-});
-return _38(_3a.join(""));
+
+
+
+
+dojox.date.buddhist.locale.parse= function(/*String*/value, /*object?*/options){
+	// based on and similar to dojo.date.locale.parse
+	// summary: This function parse string date value according to options	
+	value =  value.replace(/[\u200E\u200F\u202A-\u202E]/g, ""); //remove special chars
+	
+	if(!options){options={};}
+	var info = dojox.date.buddhist.locale._parseInfo(options);
+	
+	var tokens = info.tokens, bundle = info.bundle;
+	var re = new RegExp("^" + info.regexp + "$");
+	
+	var match = re.exec(value);
+
+	var locale = dojo.i18n.normalizeLocale(options.locale); 
+
+	if(!match){ 
+		console.debug("dojox.date.buddhist.locale.parse: value  "+value+" doesn't match pattern   " + re);
+		return null;
+	} // null
+	
+	var date, date1;
+	
+	var result = [2513,0,1,0,0,0,0];  // buddhist date for [1970,0,1,0,0,0,0] used in gregorian locale
+	var amPm = "";
+	var mLength = 0;
+	var widthList = ["abbr", "wide", "narrow"];
+	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':
+				result[0] = Number(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 ? s.replace(".","").toLowerCase() : s; } );
+					}
+					v = dojo.indexOf(months, v);
+					if(v == -1){
+						return false;
+					}
+					mLength = l;
+				}else{
+					v--;				
+				}
+				result[1] = Number(v);
+				break;
+			case 'D':
+				result[1] = 0;
+				// fallthrough...
+			case 'd':
+					result[2] =  Number(v);
+				break;
+			case 'a': //am/pm
+				var am = options.am || bundle['dayPeriods-format-wide-am'],
+					pm = options.pm || bundle['dayPeriods-format-wide-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)
+				//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] = Number(v);
+				break;
+			case 'm': //minutes
+				result[4] = Number(v);
+				break;
+			case 's': //seconds
+				result[5] = Number(v);
+				break; 
+			case 'S': //milliseconds
+				result[6] = Number(v);
+		}
+		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
+	}
+	var dateObject = new dojox.date.buddhist.Date(result[0], result[1], result[2], result[3], result[4], result[5], result[6]);
+	return dateObject;
 };
-function _21(_3d,_3e,_3f,_40){
-_40=dojo.regexp.escapeString(_40);
-var _41=dojo.i18n.normalizeLocale(_3f.locale);
-return _40.replace(/([a-z])\1*/ig,function(_42){
-var s;
-var c=_42.charAt(0);
-var l=_42.length;
-var p2="",p3="";
-if(_3f.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+";
-break;
-case "M":
-s=(l>2)?"\\S+":p2+"[1-9]|1[0-2]";
-break;
-case "d":
-s="[12]\\d|"+p2+"[1-9]|3[01]";
-break;
-case "E":
-s="\\S+";
-break;
-case "h":
-s=p2+"[1-9]|1[0-2]";
-break;
-case "k":
-s=p2+"\\d|1[01]";
-break;
-case "H":
-s=p2+"\\d|1\\d|2[0-3]";
-break;
-case "K":
-s=p2+"[1-9]|1\\d|2[0-4]";
-break;
-case "m":
-case "s":
-s=p2+"\\d|[0-5]\\d";
-break;
-case "S":
-s="\\d{"+l+"}";
-break;
-case "a":
-var am=_3f.am||_3e.am||"AM";
-var pm=_3f.pm||_3e.pm||"PM";
-if(_3f.strict){
-s=am+"|"+pm;
-}else{
-s=am+"|"+pm;
-if(am!=am.toLowerCase()){
-s+="|"+am.toLowerCase();
-}
-if(pm!=pm.toLowerCase()){
-s+="|"+pm.toLowerCase();
-}
-}
-break;
-default:
-s=".*";
+
+
+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(''));
 }
-if(_3d){
-_3d.push(_42);
+
+function _buildDateTimeRE  (tokens, bundle, options, pattern){
+		// based on and similar to dojo.date.locale._buildDateTimeRE 
+		//
+	
+	pattern = dojo.regexp.escapeString(pattern); 
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	
+	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+';
+					break;
+				case 'M':
+					s = (l>2) ?  '\\S+' : p2+'[1-9]|1[0-2]';
+					break;
+				case 'd':
+					s = '[12]\\d|'+p2+'[1-9]|3[01]';
+					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 = p2+'\\d|[0-5]\\d';
+					break;
+				case 'S':
+					s = '\\d{'+l+'}';
+					break;
+				case 'a':
+					var am = options.am || bundle['dayPeriods-format-wide-am'],
+						pm = options.pm || bundle['dayPeriods-format-wide-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(); }
+					}
+					break;
+				default:
+					s = ".*";
+			}	 
+			if(tokens){ tokens.push(match); }
+			return "(" + s + ")"; // add capture
+		}).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace.  Need explicit handling of \xa0 for IE. */
 }
-return "("+s+")";
-}).replace(/[\xa0 ]/g,"[\\s\\xa0]");
-};
 })();
+
+
+
 (function(){
-var _43=[];
-dojox.date.buddhist.locale.addCustomFormats=function(_44,_45){
-_43.push({pkg:_44,name:_45});
+var _customFormats = [];
+dojox.date.buddhist.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.
+	_customFormats.push({pkg:packageName,name:bundleName});
 };
-dojox.date.buddhist.locale._getBuddhistBundle=function(_46){
-var _47={};
-dojo.forEach(_43,function(_48){
-var _49=dojo.i18n.getLocalization(_48.pkg,_48.name,_46);
-_47=dojo.mixin(_47,_49);
-},this);
-return _47;
+
+dojox.date.buddhist.locale._getBuddhistBundle = function(/*String*/locale){
+	var buddhist = {};
+	dojo.forEach(_customFormats, function(desc){
+		var bundle = dojo.i18n.getLocalization(desc.pkg, desc.name, locale);
+		buddhist = dojo.mixin(buddhist, bundle);
+	}, this);
+	return buddhist; /*Object*/
 };
 })();
+
 dojox.date.buddhist.locale.addCustomFormats("dojo.cldr","buddhist");
-dojox.date.buddhist.locale.getNames=function(_4a,_4b,_4c,_4d,_4e){
-var _4f;
-var _50=dojox.date.buddhist.locale._getBuddhistBundle;
-var _51=[_4a,_4c,_4b];
-if(_4c=="standAlone"){
-var key=_51.join("-");
-_4f=_50(_4d)[key];
-if(_4f===_50("ROOT")[key]){
-_4f=undefined;
-}
-}
-_51[1]="format";
-return (_4f||_50(_4d)[_51.join("-")]).concat();
+
+dojox.date.buddhist.locale.getNames = function(/*String*/item, /*String*/type, /*String?*/context, /*String?*/locale, /*buddhist Date Object?*/date){
+	// summary:
+	//		Used to get localized strings from dojo.cldr for day or month names.
+	var label;
+	var lookup = dojox.date.buddhist.locale._getBuddhistBundle;
+	var props = [item, context, type];
+	if(context == 'standAlone'){
+		var key = props.join('-');
+		label = lookup(locale)[key];
+		// Fall back to 'format' flavor of name
+		if(label === lookup("ROOT")[key]){ label = undefined; } // a bit of a 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(locale)[props.join('-')]).concat(); /*Array*/
 };
-}
diff --git a/dojox/date/hebrew.js b/dojox/date/hebrew.js
index 270700e..3f555c4c 100644
--- a/dojox/date/hebrew.js
+++ b/dojox/date/hebrew.js
@@ -1,191 +1,247 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.hebrew"]){
-dojo._hasResource["dojox.date.hebrew"]=true;
 dojo.provide("dojox.date.hebrew");
+
 dojo.require("dojox.date.hebrew.Date");
-dojo.require("dojo.date");
-dojox.date.hebrew.getDaysInMonth=function(_1){
-return _1.getDaysInHebrewMonth(_1.getMonth(),_1.getFullYear());
-};
-dojox.date.hebrew.compare=function(_2,_3,_4){
-if(_2 instanceof dojox.date.hebrew.Date){
-_2=_2.toGregorian();
-}
-if(_3 instanceof dojox.date.hebrew.Date){
-_3=_3.toGregorian();
-}
-return dojo.date.compare.apply(null,arguments);
+dojo.require("dojo.date"); // for compare
+	
+// Utility methods to do arithmetic calculations with hebrew.Dates
+
+	// added for compat to date
+dojox.date.hebrew.getDaysInMonth = function(/*hebrew.Date*/month){
+	return month.getDaysInHebrewMonth(month.getMonth(), month.getFullYear());
 };
-dojox.date.hebrew.add=function(_5,_6,_7){
-var _8=new dojox.date.hebrew.Date(_5);
-switch(_6){
-case "day":
-_8.setDate(_5.getDate()+_7);
-break;
-case "weekday":
-var _9=_5.getDay();
-var _a=0;
-if(_7<0&&_9==6){
-_9=5;
-_a=-1;
-}
-if((_9+_7)<5&&(_9+_7)>=0){
-_8.setDate(_5.getDate()+_7+_a);
-}else{
-var _b=(_7>0)?5:-1;
-var _c=(_7>0)?2:-2;
-if(_7>0&&(_9==5||_9==6)){
-_a=4-_9;
-_9=4;
-}
-var _d=_9+_7-_b;
-var _e=parseInt(_d/5);
-var _f=_d%5;
-_8.setDate(_5.getDate()-_9+_c+_e*7+_a+_f+_b);
-}
-break;
-case "year":
-_8.setFullYear(_5.getFullYear()+_7);
-break;
-case "week":
-_7*=7;
-_8.setDate(_5.getDate()+_7);
-break;
-case "month":
-var _10=_5.getMonth();
-var _b=_10+_7;
-if(!_5.isLeapYear(_5.getFullYear())){
-if(_10<5&&_b>=5){
-_b++;
-}else{
-if(_10>5&&_b<=5){
-_b--;
-}
-}
-}
-_8.setMonth(_b);
-break;
-case "hour":
-_8.setHours(_5.getHours()+_7);
-break;
-case "minute":
-_8.setMinutes(_5.getMinutes()+_7);
-break;
-case "second":
-_8.setSeconds(_5.getSeconds()+_7);
-break;
-case "millisecond":
-_8.setMilliseconds(_5.getMilliseconds()+_7);
-break;
-}
-return _8;
+
+//TODO: define hebrew.isLeapYear?  Or should it be invalid, since it has different meaning?
+
+dojox.date.hebrew.compare = function(/*hebrew.Date*/dateheb1, /*hebrew.Date*/dateheb2, /*String?*/portion){
+	//	summary:
+	//		Compare two hebrew date objects by date, time, or both.
+	//	description:
+	//  	Returns 0 if equal, positive if a > b, else negative.
+	//	date1:
+	//		hebrew.Date object
+	//	date2:
+	//		hebrew.Date object.  If not specified, the current hebrew.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"
+
+	if(dateheb1 instanceof dojox.date.hebrew.Date){
+		dateheb1 = dateheb1.toGregorian();
+	}
+	if(dateheb2 instanceof dojox.date.hebrew.Date){
+		dateheb2 = dateheb2.toGregorian();
+	}
+	
+	return dojo.date.compare.apply(null, arguments);
 };
-dojox.date.hebrew.difference=function(_11,_12,_13){
-_12=_12||new dojox.date.hebrew.Date();
-_13=_13||"day";
-var _14=_11.getFullYear()-_12.getFullYear();
-var _15=1;
-switch(_13){
-case "weekday":
-var _16=Math.round(dojox.date.hebrew.difference(_11,_12,"day"));
-var _17=parseInt(dojox.date.hebrew.difference(_11,_12,"week"));
-var mod=_16%7;
-if(mod==0){
-_16=_17*5;
-}else{
-var adj=0;
-var _18=_12.getDay();
-var _19=_11.getDay();
-_17=parseInt(_16/7);
-mod=_16%7;
-var _1a=new dojox.date.hebrew.Date(_12);
-_1a.setDate(_1a.getDate()+(_17*7));
-var _1b=_1a.getDay();
-if(_16>0){
-switch(true){
-case _18==5:
-adj=-1;
-break;
-case _18==6:
-adj=0;
-break;
-case _19==5:
-adj=-1;
-break;
-case _19==6:
-adj=-2;
-break;
-case (_1b+mod)>5:
-adj=-2;
-}
-}else{
-if(_16<0){
-switch(true){
-case _18==5:
-adj=0;
-break;
-case _18==6:
-adj=1;
-break;
-case _19==5:
-adj=2;
-break;
-case _19==6:
-adj=1;
-break;
-case (_1b+mod)<0:
-adj=2;
-}
-}
-}
-_16+=adj;
-_16-=(_17*2);
-}
-_15=_16;
-break;
-case "year":
-_15=_14;
-break;
-case "month":
-var _1c=(_11.toGregorian()>_12.toGregorian())?_11:_12;
-var _1d=(_11.toGregorian()>_12.toGregorian())?_12:_11;
-var _1e=_1c.getMonth();
-var _1f=_1d.getMonth();
-if(_14==0){
-_15=(!_11.isLeapYear(_11.getFullYear())&&_1c.getMonth()>5&&_1d.getMonth()<=5)?(_1c.getMonth()-_1d.getMonth()-1):(_1c.getMonth()-_1d.getMonth());
-}else{
-_15=(!_1d.isLeapYear(_1d.getFullYear())&&_1f<6)?(13-_1f-1):(13-_1f);
-_15+=(!_1c.isLeapYear(_1c.getFullYear())&&_1e>5)?(_1e-1):_1e;
-var i=_1d.getFullYear()+1;
-var e=_1c.getFullYear();
-for(i;i<e;i++){
-_15+=_1d.isLeapYear(i)?13:12;
-}
-}
-if(_11.toGregorian()<_12.toGregorian()){
-_15=-_15;
-}
-break;
-case "week":
-_15=parseInt(dojox.date.hebrew.difference(_11,_12,"day")/7);
-break;
-case "day":
-_15/=24;
-case "hour":
-_15/=60;
-case "minute":
-_15/=60;
-case "second":
-_15/=1000;
-case "millisecond":
-_15*=_11.toGregorian().getTime()-_12.toGregorian().getTime();
-}
-return Math.round(_15);
+
+
+dojox.date.hebrew.add = function(/*dojox.date.hebrew.Date*/date, /*String*/interval, /*int*/amount){
+	//	based on and similar to dojo.date.add
+	//	summary:
+	//		Add to a Date in intervals of different size, from milliseconds to years
+	//	date: hebrew.Date
+	//		Date object to start with
+	//	interval:
+	//		A string representing the interval.  One of the following:
+	//			"year", "month", "day", "hour", "minute", "second",
+	//			"millisecond", "week", "weekday"
+	//	amount:
+	//		How much to add to the date.
+
+	var newHebrDate = new dojox.date.hebrew.Date(date);
+
+	switch(interval){
+		case "day":
+			newHebrDate.setDate(date.getDate() + amount);
+			break;
+		case "weekday":
+			var day = date.getDay();
+			var remdays = 0;
+			if(amount < 0 && day == 6){ day = 5; remdays = -1; }
+			
+			if((day + amount) < 5 && (day + amount) >= 0){ //in the same week
+				 newHebrDate.setDate(date.getDate() + amount + remdays);
+			}else{
+				var add = (amount > 0) ? 5 : -1;
+				var adddays = (amount > 0) ? 2 : -2 ; /*first weekend */
+				if  (amount > 0 && (day == 5 || day == 6)) { remdays =  4 - day; day = 4;}
+				var newamount  =  day + amount - add;
+				var weeks = parseInt(newamount / 5);
+				var newday = newamount%5;
+				newHebrDate.setDate(date.getDate() - day+ adddays + weeks * 7 + remdays + newday + add);
+			}
+			break;
+		case "year":
+			newHebrDate.setFullYear(date.getFullYear() + amount);
+			break;
+		case "week":
+			amount *= 7;
+			newHebrDate.setDate(date.getDate() + amount);
+			break;
+		case "month":
+			var month = date.getMonth(); 
+			var add = month + amount;
+			if(!date.isLeapYear(date.getFullYear())){
+				if(month < 5 && add >= 5){ add++;}
+				else if (month > 5 && add <= 5){ add--;}	
+			}
+			newHebrDate.setMonth(add);
+			break;
+		case "hour":
+			newHebrDate.setHours(date.getHours() + amount);
+			break;	
+		case "minute":
+			newHebrDate.setMinutes(date.getMinutes() + amount);
+			break;	
+		case "second":
+			newHebrDate.setSeconds(date.getSeconds() + amount);
+			break;	
+		case "millisecond":
+			newHebrDate.setMilliseconds(date.getMilliseconds() + amount);
+			break;
+	}
+
+	return newHebrDate; // dojox.date.hebrew.Date
+}; 
+
+dojox.date.hebrew.difference = function(/*dojox.date.hebrew.Date*/date1, /*dojox.date.hebrew.Date?*/date2, /*String?*/interval){
+	//	based on and similar to dojo.date.difference
+	//	summary:
+	//        date1 - date2
+	//	 date2 is hebrew.Date object.  If not specified, the current hebrew.Date is used.
+	//	interval:
+	//		A string representing the interval.  One of the following:
+	//			"year", "month", "day", "hour", "minute", "second",
+	//			"millisecond",  "week", "weekday"
+	//		Defaults to "day".
+
+	date2 = date2 || new dojox.date.hebrew.Date();
+	interval = interval || "day";
+	var yearDiff = date1.getFullYear() - date2.getFullYear();
+	var delta = 1; // Integer return value
+	switch(interval){
+		case "weekday":
+			var days = Math.round(dojox.date.hebrew.difference(date1, date2, "day"));
+			var weeks = parseInt(dojox.date.hebrew.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 = date2.getDay();
+				var bDay = date1.getDay();
+	
+				weeks = parseInt(days/7);
+				mod = days % 7;
+				// Mark the date advanced by the number of
+				// round weeks (may be zero)
+				var dtMark = new dojox.date.hebrew.Date(date2);
+				dtMark.setDate(dtMark.getDate()+(weeks*7));
+				var dayMark = dtMark.getDay();
+	
+				// Spare change days -- 6 or less
+				if(days > 0){
+					switch(true){
+						// Range starts on Fri
+						case aDay == 5:
+							adj = -1;
+							break;
+						// Range starts on Sat
+						case aDay == 6:
+							adj = 0;
+							break;
+						// Range ends on Fri
+						case bDay == 5:
+							adj = -1;
+							break;
+						// Range ends on Sat
+						case bDay == 6:
+							adj = -2;
+							break;
+						// Range contains weekend
+						case (dayMark + mod) > 5:
+							adj = -2;
+					}
+				}else if(days < 0){
+					switch(true){
+						// Range starts on Fri
+						case aDay == 5:
+							adj = 0;
+							break;
+						// Range starts on Sat
+						case aDay == 6:
+							adj = 1;
+							break;
+						// Range ends on Fri
+						case bDay == 5:
+							adj = 2;
+							break;
+						// Range ends on Sat
+						case bDay == 6:
+							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":
+			var startdate =  (date1.toGregorian() > date2.toGregorian()) ? date1 : date2; // more
+			var enddate = (date1.toGregorian() > date2.toGregorian()) ? date2 : date1;
+			
+			var month1 = startdate.getMonth();
+			var month2 = enddate.getMonth();
+			
+			if(yearDiff == 0){
+				delta = ( !date1.isLeapYear(date1.getFullYear())  && startdate.getMonth() > 5 && enddate.getMonth() <=5) ? (startdate.getMonth() - enddate.getMonth() - 1) :
+						(startdate.getMonth() - enddate.getMonth() );
+			}else{
+				delta = (!enddate.isLeapYear(enddate.getFullYear()) &&  month2 < 6) ? (13-month2-1) : (13-month2);
+				delta +=  (!startdate.isLeapYear(startdate.getFullYear()) &&  month1 > 5) ? (month1 -1): month1;
+				var i = enddate.getFullYear()  + 1;
+				var e = startdate.getFullYear();
+				for (i;   i < e;  i++){
+					delta += enddate.isLeapYear(i) ? 13 : 12; 
+				}
+			}
+			if(date1.toGregorian() < date2.toGregorian()){
+				delta = -delta;
+			}
+			break;
+		case "week":
+			// Truncate instead of rounding
+			// Don't use Math.floor -- value may be negative
+			delta = parseInt(dojox.date.hebrew.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 *= date1.toGregorian().getTime()- date2.toGregorian().getTime();
+	}
+
+	// Round for fractional values and DST leaps
+	return Math.round(delta); // Number (integer) 
 };
-}
diff --git a/dojox/date/hebrew/Date.js b/dojox/date/hebrew/Date.js
index b8b02f6..15356c2 100644
--- a/dojox/date/hebrew/Date.js
+++ b/dojox/date/hebrew/Date.js
@@ -1,306 +1,702 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.hebrew.Date"]){
-dojo._hasResource["dojox.date.hebrew.Date"]=true;
 dojo.provide("dojox.date.hebrew.Date");
+
 dojo.require("dojox.date.hebrew.numerals");
-dojo.declare("dojox.date.hebrew.Date",null,{_MONTH_LENGTH:[[30,30,30],[29,29,30],[29,30,30],[29,29,29],[30,30,30],[30,30,30],[29,29,29],[30,30,30],[29,29,29],[30,30,30],[29,29,29],[30,30,30],[29,29,29]],_MONTH_START:[[0,0,0],[30,30,30],[59,59,60],[88,89,90],[117,118,119],[147,148,149],[147,148,149],[176,177,178],[206,207,208],[235,236,237],[265,266,267],[294,295,296],[324,325,326],[353,354,355]],_LEAP_MONTH_START:[[0,0,0],[30,30,30],[59,59,60],[88,89,90],[117,118,119],[147,148,149],[177, [...]
-var _1=arguments.length;
-if(!_1){
-this.fromGregorian(new Date());
-}else{
-if(_1==1){
-var _2=arguments[0];
-if(typeof _2=="number"){
-_2=new Date(_2);
-}
-if(_2 instanceof Date){
-this.fromGregorian(_2);
-}else{
-if(_2==""){
-this._date=new Date("");
-}else{
-this._year=_2._year;
-this._month=_2._month;
-this._date=_2._date;
-this._hours=_2._hours;
-this._minutes=_2._minutes;
-this._seconds=_2._seconds;
-this._milliseconds=_2._milliseconds;
-}
-}
-}else{
-if(_1>=3){
-this._year+=arguments[0];
-this._month+=arguments[1];
-this._date+=arguments[2];
-if(this._month>12){
-console.warn("the month is incorrect , set 0  "+this._month+"   "+this._year);
-this._month=0;
-}
-this._hours+=arguments[3]||0;
-this._minutes+=arguments[4]||0;
-this._seconds+=arguments[5]||0;
-this._milliseconds+=arguments[6]||0;
-}
-}
-}
-this._setDay();
-},getDate:function(){
-return this._date;
-},getDateLocalized:function(_3){
-return (_3||dojo.locale).match(/^he(?:-.+)?$/)?dojox.date.hebrew.numerals.getDayHebrewLetters(this._date):this.getDate();
-},getMonth:function(){
-return this._month;
-},getFullYear:function(){
-return this._year;
-},getHours:function(){
-return this._hours;
-},getMinutes:function(){
-return this._minutes;
-},getSeconds:function(){
-return this._seconds;
-},getMilliseconds:function(){
-return this._milliseconds;
-},setDate:function(_4){
-_4=+_4;
-var _5;
-if(_4>0){
-while(_4>(_5=this.getDaysInHebrewMonth(this._month,this._year))){
-_4-=_5;
-this._month++;
-if(this._month>=13){
-this._year++;
-this._month-=13;
-}
-}
-}else{
-while(_4<=0){
-_5=this.getDaysInHebrewMonth((this._month-1)>=0?(this._month-1):12,((this._month-1)>=0)?this._year:this._year-1);
-this._month--;
-if(this._month<0){
-this._year--;
-this._month+=13;
-}
-_4+=_5;
-}
-}
-this._date=_4;
-this._setDay();
-return this;
-},setFullYear:function(_6,_7,_8){
-this._year=_6=+_6;
-if(!this.isLeapYear(_6)&&this._month==5){
-this._month++;
-}
-if(_7!==undefined){
-this.setMonth(_7);
-}
-if(_8!==undefined){
-this.setDate(_8);
-}
-var _9=this.getDaysInHebrewMonth(this._month,this._year);
-if(_9<this._date){
-this._date=_9;
-}
-this._setDay();
-return this;
-},setMonth:function(_a){
-_a=+_a;
-if(!this.isLeapYear(this._year)&&_a==5){
-_a++;
-}
-if(_a>=0){
-while(_a>12){
-this._year++;
-_a-=13;
-if(!this.isLeapYear(this._year)&&_a>=5){
-_a++;
-}
-}
-}else{
-while(_a<0){
-this._year--;
-_a+=(!this.isLeapYear(this._year)&&_a<-7)?12:13;
-}
-}
-this._month=_a;
-var _b=this.getDaysInHebrewMonth(this._month,this._year);
-if(_b<this._date){
-this._date=_b;
-}
-this._setDay();
-return this;
-},setHours:function(){
-var _c=arguments.length;
-var _d=0;
-if(_c>=1){
-_d+=+arguments[0];
-}
-if(_c>=2){
-this._minutes+=+arguments[1];
-}
-if(_c>=3){
-this._seconds+=+arguments[2];
-}
-if(_c==4){
-this._milliseconds+=+arguments[3];
-}
-while(_d>=24){
-this._date++;
-var _e=this.getDaysInHebrewMonth(this._month,this._year);
-if(this._date>_e){
-this._month++;
-if(!this.isLeapYear(this._year)&&this._month==5){
-this._month++;
-}
-if(this._month>=13){
-this._year++;
-this._month-=13;
-}
-this._date-=_e;
-}
-_d-=24;
-}
-this._hours=_d;
-this._setDay();
-return this;
-},setMinutes:function(_f){
-_f=+_f;
-this._minutes=_f%60;
-this.setHours(parseInt(_f/60));
-this._setDay();
-return this;
-},setSeconds:function(_10){
-_10=+_10;
-this._seconds=_10%60;
-this.setMinutes(parseInt(_10/60));
-this._setDay();
-return this;
-},setMilliseconds:function(_11){
-_11=+_11;
-this._milliseconds=_11%1000;
-this.setSeconds(parseInt(_11/1000));
-this._setDay();
-return this;
-},_setDay:function(){
-var day=this._startOfYear(this._year);
-if(this._month!=0){
-day+=(this.isLeapYear(this._year)?this._LEAP_MONTH_START:this._MONTH_START)[this._month][this._yearType(this._year)];
-}
-day+=this._date-1;
-this._day=(day+1)%7;
-},toString:function(){
-return this._date+", "+this._month+", "+this._year+"  "+this._hours+":"+this._minutes+":"+this._seconds;
-},getDaysInHebrewMonth:function(_12,_13){
-var _14=(_12==1||_12==2)?this._yearType(_13):0;
-return (!this.isLeapYear(this._year)&&_12==5)?0:this._MONTH_LENGTH[_12][_14];
-},_yearType:function(_15){
-var _16=this._handleGetYearLength(Number(_15));
-if(_16>380){
-_16-=30;
-}
-var _17=_16-353;
-if(_17<0||_17>2){
-throw new Error("Illegal year length "+_16+" in year "+_15);
-}
-return _17;
-},_handleGetYearLength:function(_18){
-return this._startOfYear(_18+1)-this._startOfYear(_18);
-},_startOfYear:function(_19){
-var _1a=Math.floor((235*_19-234)/19),_1b=_1a*(12*1080+793)+11*1080+204,day=_1a*29+Math.floor(_1b/(24*1080));
-_1b%=24*1080;
-var wd=day%7;
-if(wd==2||wd==4||wd==6){
-day+=1;
-wd=day%7;
-}
-if(wd==1&&_1b>15*1080+204&&!this.isLeapYear(_19)){
-day+=2;
-}else{
-if(wd==0&&_1b>21*1080+589&&this.isLeapYear(_19-1)){
-day+=1;
-}
-}
-return day;
-},isLeapYear:function(_1c){
-var x=(_1c*12+17)%19;
-return x>=((x<0)?-7:12);
-},fromGregorian:function(_1d){
-var _1e=this._computeHebrewFields(_1d);
-this._year=_1e[0];
-this._month=_1e[1];
-this._date=_1e[2];
-this._hours=_1d.getHours();
-this._milliseconds=_1d.getMilliseconds();
-this._minutes=_1d.getMinutes();
-this._seconds=_1d.getSeconds();
-this._setDay();
-return this;
-},_computeHebrewFields:function(_1f){
-var _20=this._getJulianDayFromGregorianDate(_1f),d=_20-347997,m=Math.floor((d*24*1080)/(29*24*1080+12*1080+793)),_21=Math.floor((19*m+234)/235)+1,ys=this._startOfYear(_21),_22=(d-ys);
-while(_22<1){
-_21--;
-ys=this._startOfYear(_21);
-_22=d-ys;
-}
-var _23=this._yearType(_21),_24=this.isLeapYear(_21)?this._LEAP_MONTH_START:this._MONTH_START,_25=0;
-while(_22>_24[_25][_23]){
-_25++;
-}
-_25--;
-var _26=_22-_24[_25][_23];
-return [_21,_25,_26];
-},toGregorian:function(){
-var _27=this._year,_28=this._month,_29=this._date,day=this._startOfYear(_27);
-if(_28!=0){
-day+=(this.isLeapYear(_27)?this._LEAP_MONTH_START:this._MONTH_START)[_28][this._yearType(_27)];
-}
-var _2a=(_29+day+347997),_2b=_2a-1721426;
-var rem=[];
-var _2c=this._floorDivide(_2b,146097,rem),_2d=this._floorDivide(rem[0],36524,rem),n4=this._floorDivide(rem[0],1461,rem),n1=this._floorDivide(rem[0],365,rem),_2e=400*_2c+100*_2d+4*n4+n1,_2f=rem[0];
-if(_2d==4||n1==4){
-_2f=365;
-}else{
-++_2e;
-}
-var _30=!(_2e%4)&&(_2e%100||!(_2e%400)),_31=0,_32=_30?60:59;
-if(_2f>=_32){
-_31=_30?1:2;
-}
-var _33=Math.floor((12*(_2f+_31)+6)/367);
-var _34=_2f-this._GREGORIAN_MONTH_COUNT[_33][_30?3:2]+1;
-return new Date(_2e,_33,_34,this._hours,this._minutes,this._seconds,this._milliseconds);
-},_floorDivide:function(_35,_36,_37){
-if(_35>=0){
-_37[0]=(_35%_36);
-return Math.floor(_35/_36);
-}
-var _38=Math.floor(_35/_36);
-_37[0]=_35-(_38*_36);
-return _38;
-},getDay:function(){
-var _39=this._year,_3a=this._month,_3b=this._date,day=this._startOfYear(_39);
-if(_3a!=0){
-day+=(this.isLeapYear(_39)?this._LEAP_MONTH_START:this._MONTH_START)[_3a][this._yearType(_39)];
-}
-day+=_3b-1;
-return (day+1)%7;
-},_getJulianDayFromGregorianDate:function(_3c){
-var _3d=_3c.getFullYear(),_3e=_3c.getMonth(),d=_3c.getDate(),_3f=!(_3d%4)&&(_3d%100||!(_3d%400)),y=_3d-1;
-var _40=365*y+Math.floor(y/4)-Math.floor(y/100)+Math.floor(y/400)+1721426-1;
-if(_3e!=0){
-_40+=this._GREGORIAN_MONTH_COUNT[_3e][_3f?3:2];
-}
-_40+=d;
-return _40;
-}});
-dojox.date.hebrew.Date.prototype.valueOf=function(){
-return this.toGregorian().valueOf();
+
+dojo.declare("dojox.date.hebrew.Date", null, {
+	// summary: A Date-like object which implements the Hebrew calendar
+	//
+	// description:
+	//	A Date-like object which implements the Hebrew Calendar.  Because this object
+	//	implements many of the same methods as the native JavaScript Date object, which
+	//	implements the Gregorian calendar, it can often be used its place.  Note that
+	//	this object does not extend Date or use its prototype.
+	//
+	// example:
+	// |	dojo.require("dojox.date.hebrew.Date");
+	// |		
+	// |	var date = new dojox.date.hebrew.Date();
+	// |	console.log(date.getFullYear()+'\'+date.getMonth()+'\'+date.getDate());
+
+	// Hebrew date calculations are performed in terms of days, hours, and
+	// "parts" (or halakim), which are 1/1080 of an hour, or 3 1/3 seconds.
+	//_HOUR_PARTS: 1080,
+	//_DAY_PARTS: 24*1080,
+   
+	// An approximate value for the length of a lunar month.
+	// It is used to calculate the approximate year and month of a given
+	// absolute date.
+	//_MONTH_FRACT: 12*1080 + 793,
+	//_MONTH_PARTS: 29*24*1080 + 12*1080 + 793,
+	    
+	// The time of the new moon (in parts) on 1 Tishri, year 1 (the epoch)
+	// counting from noon on the day before.  BAHARAD is an abbreviation of
+	// Bet (Monday), Hey (5 hours from sunset), Resh-Daled (204).
+	//_BAHARAD: 11*1080 + 204,
+
+	// The Julian day of the Gregorian epoch, that is, January 1, 1 on the
+	// Gregorian calendar.
+	//_JAN_1_1_JULIAN_DAY: 1721426,
+
+	/**
+	* The lengths of the Hebrew months.  This is complicated, because there
+	* are three different types of years, or six if you count leap years.
+	* Due to the rules for postponing the start of the year to avoid having
+	* certain holidays fall on the sabbath, the year can end up being three
+	* different lengths, called "deficient", "normal", and "complete".
+	*/
+	
+	//"Absolute" indexes of  months:  Tishri -  0, Heshvan - 1, Kislev - 2, Tevet - 3, Shevat -  4, Adar I (leap years only) - 5, Adar - 6, Nisan - 7, Iyar - 8, Sivan - 9,   Tammuz-10, Av - 11, Elul - 12.
+
+	_MONTH_LENGTH:  [
+		// Deficient  Normal     Complete
+		[   30,	    30,	    30	],		 //Tishri    0
+		[   29,	    29,	    30	],		 //Heshvan   1
+		[   29,	    30,	    30	],		 //Kislev   2
+		[   29,	    29,	    29	],		 //Tevet  3
+		[   30,	    30,	    30	],		 //Shevat  4
+		[   30,	    30,	    30	],		 //Adar I (leap years only)  5
+		[   29,	    29,	    29	],		 //Adar  6
+		[   30,	    30,	    30	],		 //Nisan  7
+		[   29,	    29,	    29	],		 //Iyar  8
+		[   30,	    30,	    30	],		 //Sivan  9
+		[   29,	    29,	    29	],		 //Tammuz  10
+		[   30,	    30,	    30	],		 //Av  11
+		[   29,	    29,	    29	]		 //Elul  12
+	],
+
+	/**
+	* The cumulative # of days to the end of each month in a non-leap year
+	* Although this can be calculated from the MONTH_LENGTH table,
+	* keeping it around separately makes some calculations a lot faster
+	*/
+	_MONTH_START:  [
+		// Deficient  Normal	Complete
+		[    0,		0,		0  ],		// (placeholder)
+		[   30,	    30,	    30  ],		// Tishri
+		[   59,	    59,	    60  ],		// Heshvan
+		[   88,	    89,	    90  ],		// Kislev
+		[  117,	   118,	   119  ],		// Tevet
+		[  147,	   148,	   149  ],		// Shevat
+		[  147,	   148,	   149  ],		// (Adar I placeholder)
+		[  176,	   177,	   178  ],		// Adar
+		[  206,	   207,	   208  ],		// Nisan
+		[  235,	   236,	   237  ],		// Iyar
+		[  265,	   266,	   267  ],		// Sivan
+		[  294,	   295,	   296  ],		// Tammuz
+		[  324,	   325,	   326  ],		// Av
+		[  353,	   354,	   355  ]		// Elul
+	],
+
+	/**
+	* The cumulative # of days to the end of each month in a leap year
+	*/
+	_LEAP_MONTH_START:  [
+		// Deficient  Normal	Complete
+		[    0,		0,		0  ],		// (placeholder)
+		[   30,	    30,	    30  ],		// Tishri
+		[   59,	    59,	    60  ],		// Heshvan
+		[   88,	    89,	    90  ],		// Kislev
+		[  117,	   118,	   119  ],		// Tevet
+		[  147,	   148,	   149  ],		// Shevat
+		[  177,	   178,	   179  ],		// Adar I
+		[  206,	   207,	   208  ],		// Adar II
+		[  236,	   237,	   238  ],		// Nisan
+		[  265,	   266,	   267  ],		// Iyar
+		[  295,	   296,	   297  ],		// Sivan
+		[  324,	   325,	   326  ],		// Tammuz
+		[  354,	   355,	   356  ],		// Av
+		[  383,	   384,	   385  ]		// Elul
+	],
+	
+	_GREGORIAN_MONTH_COUNT:  [
+		//len len2   st  st2
+		[  31,  31,   0,   0 ], // Jan
+		[  28,  29,  31,  31 ], // Feb
+		[  31,  31,  59,  60 ], // Mar
+		[  30,  30,  90,  91 ], // Apr
+		[  31,  31, 120, 121 ], // May
+		[  30,  30, 151, 152 ], // Jun
+		[  31,  31, 181, 182 ], // Jul
+		[  31,  31, 212, 213 ], // Aug
+		[  30,  30, 243, 244 ], // Sep
+		[  31,  31, 273, 274 ], // Oct
+		[  30,  30, 304, 305 ], // Nov
+		[  31,  31, 334, 335 ] // Dec
+		// len  length of month
+		// len2 length of month in a leap year
+		// st   days in year before start of month
+		// st2  days in year before month in leap year
+	],
+
+    _date: 0,
+	_month: 0,
+	_year: 0,
+	_hours: 0,
+	_minutes: 0,
+	_seconds: 0,
+	_milliseconds: 0,
+	_day: 0,
+
+ 	constructor: function(){
+		// summary: initialize the date object value
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date();
+		// |		
+		// |		var date2 = new dojox.date.hebrew.Date(date1);
+		// |
+		// |		var date3 = new dojox.date.hebrew.Date(5768,2,12);
+
+		var len = arguments.length;
+		if(!len){// use the current date value, added "" to the similarity to date
+			this.fromGregorian(new Date());
+		}else if(len == 1){
+			var arg0 = arguments[0];
+			if(typeof arg0 == "number"){ // this is time "valueof"
+				arg0 = new Date(arg0);
+			}
+
+			if(arg0 instanceof Date){
+				this.fromGregorian(arg0);
+			}else if(arg0 == ""){
+				// date should be invalid.  Dijit relies on this behavior.
+				this._date = new Date(""); //TODO: should this be NaN?  _date is not a Date object
+			}else{  // this is hebrew.Date object
+				this._year = arg0._year;
+				this._month =  arg0._month;  
+				this._date = arg0._date;
+				this._hours = arg0._hours;
+				this._minutes = arg0._minutes;
+				this._seconds = arg0._seconds;
+				this._milliseconds = arg0._milliseconds; 
+			}	
+		}else if(len >= 3){
+			// YYYY, MM, DD arguments passed, month is from 0-12,  "absolute" index of month 
+			this._year += arguments[0];
+			this._month += arguments[1];
+			this._date += arguments[2];
+			
+			if(this._month > 12){
+				console.warn("the month is incorrect , set 0  " + this._month + "   " + this._year );
+				this._month = 0;
+			}
+			this._hours += arguments[3] || 0;
+			this._minutes += arguments[4] || 0;
+			this._seconds += arguments[5] || 0;
+			this._milliseconds += arguments[6] || 0;
+		}
+  
+		this._setDay();	
+	},
+	
+	getDate: function(){
+		// summary: returns the date value (1 - 30)
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date();
+		// |
+		// |		console.log(date1.getDate());
+
+		return this._date; // int
+	},
+
+	getDateLocalized: function(/*String?*/locale){
+		// summary: returns the date value as hebrew numerals for the Hebrew locale,
+		//		a number for all others.
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date();
+		// |
+		// |		console.log(date1.getDate());
+
+		return (locale || dojo.locale).match(/^he(?:-.+)?$/) ?
+			dojox.date.hebrew.numerals.getDayHebrewLetters(this._date) : this.getDate();
+	},
+
+	getMonth: function(){
+		// summary: returns the month value (0 - 12)
+		//
+		// description: the result is the index in the month array:
+		//	0. Tishri
+		//	1. Heshvan
+		//	2. Kislev
+		//	3. Tevet
+		//	4. Shevat
+		//	5. Adar I (leap years only)
+		//	6. Adar
+		//	7. Nisan
+		//	8. Iyar
+		//	9. Sivan
+		//	10. Tammuz
+		//	11.	Av
+		//	12. Elul - 12
+		// For non leap years, for months after Shevat, the actual position of
+		// the month in the year (used for short format) is less than
+		// the "absolute" index by 1.
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
+		// |
+		// |		console.log(date1.getMonth()+1);
+		// |		>> 7
+
+		return this._month;
+	},
+
+	getFullYear: function(){
+		// summary: returns the Year value 
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
+		// |
+		// |		console.log(date1.getFullYear());
+		// |		>> 5769
+		return this._year;
+	},
+			
+	getHours: function(){
+ 		//summary: returns the hour value
+		return this._hours;
+	},
+		
+	getMinutes: function(){
+		//summary: returns the minutes value
+
+		return this._minutes;
+	},
+
+	getSeconds: function(){
+		//summary: returns the seconds value
+		return this._seconds;
+	},
+
+	getMilliseconds: function(){
+		//summary: returns the milliseconds value
+
+		return this._milliseconds;
+	},
+
+	setDate: function(/*number*/date){	
+		// summary: sets the date number for a given month
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
+		// |		date1.setDate(2);
+
+		date = +date;
+		var mdays;
+		if(date>0){
+			while (date > (mdays = this.getDaysInHebrewMonth(this._month, this._year))){
+				date -= mdays;
+				this._month++;
+				if(this._month >= 13){this._year++; this._month -= 13;}
+			}
+		}else{
+			while(date<=0){
+				mdays = this.getDaysInHebrewMonth((this._month-1)>=0 ? (this._month-1) : 12, ((this._month-1)>=0)? this._year : this._year-1);
+				this._month--;
+				if(this._month < 0){this._year--; this._month += 13;}
+				date += mdays;
+			}
+		}
+		this._date = date;
+		this._setDay();		
+		return this;
+	},
+	
+
+	setFullYear: function(/*number*/year, /*number?*/month, /*number?*/ date){
+		// summary: set the year 
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date();
+		// |		date1.setFullYear(5768);
+		// |		date1.setFullYear(5768, 1, 1);
+		
+		this._year = year = +year;
+		if(!this.isLeapYear(year) && this._month==5){  //incorrect month number for non leap year
+			this._month++; 
+		} 
+		
+		if(month !== undefined){this.setMonth(month);}
+		if(date !== undefined){this.setDate(date);}
+		
+		var dnum = this.getDaysInHebrewMonth(this._month, this._year);
+		if(dnum < this._date){
+			this._date = dnum;
+		} // if the date in this month more than number of the days in this month
+		
+		this._setDay();
+		return this;
+	},
+
+	setMonth: function(/*number*/month){
+		// summary: sets the month.  You should use "absolute" index in the month array:
+		//	0. Tishri
+		//	1. Heshvan
+		//	2. Kislev
+		//	3. Tevet
+		//	4. Shevat
+		//	5. Adar I (leap years only)
+		//	6. Adar
+		//	7. Nisan
+		//	8. Iyar
+		//	9. Sivan
+		//	10. Tammuz
+		//	11.	Av
+		//	12. Elul - 12
+		//  For non leap years, for months after Shevat, the actual position of
+		//	the month in the year (used for short format) is less than
+		//	the "absolute" index by 1. 
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date();
+		// |		date1.setMonth(0); //first month
+
+		month = +month; // coerce to a Number					
+		if(!this.isLeapYear(this._year) && month == 5){month++;}
+	
+		if(month>=0){
+			while(month >12){
+				this._year++;
+				month -= 13;
+				if (!this.isLeapYear(this._year) && month >= 5){month++;}	
+			}
+		}else{
+			while(month<0){
+				this._year--;
+				month += (!this.isLeapYear(this._year)  &&  month < -7) ? 12 : 13; 
+			}		
+		}
+		
+		this._month = month;
+
+		var dnum = this.getDaysInHebrewMonth(this._month, this._year);
+		if(dnum < this._date){
+			this._date = dnum;
+		} // if the date in this month more than number of the days in this month
+		
+		this._setDay();
+		return this;
+	},
+
+	setHours: function(){
+		//	summary: sets the hour
+		//
+		//	description: Sets the hour and optionally minutes, seconds, milliseconds also.
+		//		
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date();
+		// |		date1.setHours(12, 30, 0, 0); 
+
+		var hours_arg_no = arguments.length;
+		var hours = 0;
+		if(hours_arg_no >= 1){
+			hours += +arguments[0];
+		}
+
+		if(hours_arg_no >= 2){
+			this._minutes += +arguments[1];
+		}
+
+		if(hours_arg_no >= 3){
+			this._seconds += +arguments[2];
+		}
+
+		if(hours_arg_no == 4){
+			this._milliseconds += +arguments[3];
+		}
+
+		while(hours >= 24){
+			this._date++;
+			var mdays = this.getDaysInHebrewMonth(this._month, this._year);
+			if(this._date > mdays)
+			{
+				this._month++;
+				if(!this.isLeapYear(this._year) && this._month==5){ this._month++; }
+				if(this._month >= 13){this._year++; this._month -= 13;}
+				this._date -= mdays;
+			}
+			hours -= 24;
+		}
+		this._hours = hours;
+		this._setDay();
+		return this;
+	},
+
+	setMinutes: function(/*Number*/minutes){
+		//summary: sets the minutes (0-59)
+		minutes = +minutes;
+		this._minutes = minutes % 60;
+		this.setHours(parseInt(minutes / 60));		
+		this._setDay();
+		return this;
+	},
+
+	setSeconds: function(/*Number*/seconds){
+		//summary: sets the seconds (0-59)
+
+		seconds = +seconds;
+		this._seconds = seconds % 60;
+		this.setMinutes(parseInt(seconds / 60));
+		this._setDay();
+		return this;
+	},
+
+	setMilliseconds: function(/*Number*/milliseconds){
+		//summary: sets the milliseconds
+
+		milliseconds = +milliseconds;
+		this._milliseconds = milliseconds % 1000;
+		this.setSeconds(parseInt(milliseconds / 1000));
+		this._setDay();
+		return this;
+	},
+
+	_setDay: function(){ 
+		var day = this._startOfYear(this._year);
+		if(this._month != 0){
+			day += (this.isLeapYear(this._year) ? this._LEAP_MONTH_START : this._MONTH_START)[this._month][this._yearType(this._year)];
+		}
+		day += this._date - 1;
+		this._day = (day+1) % 7;	
+	},
+
+	toString: function(){ 
+		// summary: returns a string representation of the date in "dd, MM, yyyy HH:mm:ss" format
+		//
+		// description: returns a string representation of the date in "dd, MM, yyyy HH:mm:ss" format (all numeric)
+		//	For user presentation, use dojox.date.hebrew.locale.format which will present in the appropriate language
+		//  and format.  toString() language- and culturally-specific conventions to keep this module free of
+		//	dependencies on dojox.date.locale and dojo.cldr.
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date(5769, 6, 1);
+		// |		console.log(date1.toString());
+		// |		>>> "1, 6, 5769 0:0:0"
+		return this._date + ", " + this._month + ", " + this._year + "  " + this._hours + ":" + this._minutes + ":" + this._seconds; // String
+	},
+
+	// ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
+	getDaysInHebrewMonth: function(/*Number*/month, /*Number*/ year){
+		// summary: returns the number of days in the given month and year
+
+		// Aside from the leap month, these two months can vary: 1=HESHVAN, 2=KISLEV
+		// The rest are a fixed length
+		var yearType = (month == 1 || month == 2) ? this._yearType(year) : 0;
+		return (!this.isLeapYear(this._year) && month == 5) ? 0 : this._MONTH_LENGTH[month][yearType];
+	},
+
+	// ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
+	_yearType: function(/*Number*/year){
+		var yearLength = this._handleGetYearLength(Number(year));
+		if(yearLength > 380){
+			yearLength -= 30;        // Subtract length of leap month.
+		}
+
+		var yearType = yearLength - 353;
+		if (yearType < 0 || yearType > 2){
+			throw new Error("Illegal year length " + yearLength + " in year " + year);
+		}
+		return yearType;
+	},
+
+	// ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
+	_handleGetYearLength: function(/*number*/eyear){
+		return this._startOfYear(eyear+1) - this._startOfYear(eyear);
+	},
+
+	// ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
+	_startOfYear: function(/*number*/year){
+		var months = Math.floor((235 * year - 234) / 19),	// # of months before year
+			frac = months * (12*1080 + 793) + 11*1080 + 204/*BAHARAD*/,	// Fractional part of day #
+			day  = months * 29 + Math.floor(frac / (24*1080));	// Whole # part of calculation
+		frac %= 24*1080;	// Time of day
+
+		var wd = day % 7;	// Day of week (0 == Monday)
+
+		if(wd == 2 || wd == 4 || wd == 6){
+			// If the 1st is on Sun, Wed, or Fri, postpone to the next day
+			day += 1;
+			wd = day % 7;
+		}
+		if(wd == 1 && frac > 15 * 1080 + 204 && !this.isLeapYear(year)){
+			// If the new moon falls after 3:11:20am (15h204p from the previous noon)
+			// on a Tuesday and it is not a leap year, postpone by 2 days.
+			// This prevents 356-day years.
+			day += 2;
+		}else if(wd == 0 && frac > 21 * 1080 + 589 && this.isLeapYear(year-1)){
+			// If the new moon falls after 9:32:43 1/3am (21h589p from yesterday noon)
+			// on a Monday and *last* year was a leap year, postpone by 1 day.
+			// Prevents 382-day years.
+			day += 1;
+		}
+
+		return day;
+	},
+
+	// ported from the Java class com.ibm.icu.util.HebrewCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
+	isLeapYear: function(/*Number*/year){	
+	//	summary:
+	//		Determines if the year (argument) is a leap year
+	//	description: The Leap year contains additional month adar sheni
+	//	
+		//return (year * 12 + 17) % 19 >= 12;
+		var x = (year*12 + 17) % 19;
+		return x >= ((x < 0) ? -7 : 12);
+	},
+
+	
+	fromGregorian: function(/*Date*/gdate){
+		// summary: This function sets this Date to the Hebrew Date corresponding to the Gregorian Date
+		// example:
+		// |		var dateHebrew = new dojox.date.hebrew.Date();
+		// |		var dateGregorian = new Date(2008,10,12);
+		// |		dateHebrew.fromGregorian(dateGregorian);
+		var result = this._computeHebrewFields(gdate);
+		this._year = result[0];
+		this._month = result[1];
+		this._date = result[2];
+		this._hours = gdate.getHours();
+		this._milliseconds = gdate.getMilliseconds();
+		this._minutes = gdate.getMinutes();
+		this._seconds = gdate.getSeconds();
+		this._setDay();
+		return this;
+	},
+
+	// ported from the Java class com.ibm.icu.util.HebrewCalendar.handleComputeFields from ICU4J v3.6.1 at http://www.icu-project.org/
+	_computeHebrewFields: function(/*Date*/gdate){
+		var julianDay = this._getJulianDayFromGregorianDate(gdate),
+			d = julianDay - 347997,
+			m = Math.floor((d * 24*1080) / (29*24*1080 + 12*1080 + 793)),       // Months (approx)
+			year = Math.floor((19 * m + 234) / 235) + 1,  // Years (approx)
+			ys  = this._startOfYear(year),                 // 1st day of year
+			dayOfYear = (d - ys);
+		// Because of the postponement rules, it's possible to guess wrong.  Fix it.
+		while(dayOfYear < 1){
+			year--;
+			ys  = this._startOfYear(year);
+			dayOfYear = d - ys;
+		}
+
+		// Now figure out which month we're in, and the date within that month
+
+		var typeofYear = this._yearType(year),
+			monthStart = this.isLeapYear(year) ? this._LEAP_MONTH_START : this._MONTH_START,
+			month = 0;
+
+		while(dayOfYear > monthStart[month][typeofYear]){
+			month++;
+		}
+		month--;
+		var dayOfMonth = dayOfYear - monthStart[month][typeofYear];
+		return [year, month, dayOfMonth];
+	},
+
+	// ported from the Java class com.ibm.icu.util.Calendar.computeGregorianFields from ICU4J v3.6.1 at http://www.icu-project.org/
+	toGregorian: function(){
+		// summary: returns the equivalent Grogorian date value as a native Date object
+		// example:
+		// |		var dateHebrew = new dojox.date.hebrew.Date(5768,11,20);
+		// |		var dateGregorian = dateHebrew.toGregorian();
+		var hYear = this._year,
+			hMonth = this._month,
+			hDate = this._date,
+			day = this._startOfYear(hYear);
+
+		if(hMonth != 0){
+			day += (this.isLeapYear(hYear) ? this._LEAP_MONTH_START : this._MONTH_START)[hMonth][this._yearType(hYear)];
+		}
+
+		var julianDay =  (hDate + day + 347997),
+		// The Gregorian epoch day is zero for Monday January 1, year 1.
+			gregorianEpochDay = julianDay - 1721426;
+
+		// Here we convert from the day number to the multiple radix
+		// representation.  We use 400-year, 100-year, and 4-year cycles.
+		// For example, the 4-year cycle has 4 years + 1 leap day; giving
+		// 1461 == 365*4 + 1 days.
+		var rem = [];
+		var n400 = this._floorDivide(gregorianEpochDay , 146097, rem), // 400-year cycle length
+			n100 = this._floorDivide(rem[0] , 36524, rem), // 100-year cycle length
+			n4 = this._floorDivide(rem[0] , 1461, rem), // 4-year cycle length
+			n1 = this._floorDivide(rem[0] , 365, rem),
+			year = 400*n400 + 100*n100 + 4*n4 + n1,
+			dayOfYear = rem[0]; // zero-based day of year
+
+		if(n100 == 4 || n1 == 4){
+			dayOfYear = 365; // Dec 31 at end of 4- or 400-yr cycle
+		}else{
+			++year;
+		}
+
+		var isLeap = !(year%4) && // equiv. to (year%4 == 0)
+				(year%100 || !(year%400)),
+			correction = 0,
+			march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
+		if(dayOfYear >= march1){ correction = isLeap ? 1 : 2; }
+		var month = Math.floor((12 * (dayOfYear + correction) + 6) / 367); // zero-based month
+		var dayOfMonth = dayOfYear -
+				this._GREGORIAN_MONTH_COUNT[month][isLeap ? 3 : 2] + 1; // one-based DOM
+
+		return new Date(year, month, dayOfMonth, this._hours, this._minutes, this._seconds, this._milliseconds); // Date
+	},
+	_floorDivide: function(numerator, denominator, remainder){
+		if(numerator >= 0){
+			remainder[0] = (numerator % denominator);
+			return Math.floor(numerator / denominator);
+		}
+		var quotient = Math.floor(numerator / denominator);
+		remainder[0] = numerator - (quotient * denominator);
+		return quotient;
+	},
+
+	getDay: function(){
+		// summary: returns weekday value (0 - 6)
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date();
+		// |
+		// |		console.log(date1.getDay());
+
+		var hYear = this._year,
+			hMonth = this._month,
+			hDate = this._date,
+			day = this._startOfYear(hYear);
+
+		if(hMonth != 0){
+			day += (this.isLeapYear(hYear) ? this._LEAP_MONTH_START : this._MONTH_START)[hMonth][this._yearType(hYear)];
+		}
+
+		day += hDate - 1;
+		return (day+1) % 7;
+	},
+
+	// ported from the Java class com.ibm.icu.util.Calendar.computeGregorianMonthStart from ICU4J v3.6.1 at http://www.icu-project.org/
+	_getJulianDayFromGregorianDate: function(gdate){
+		//summary: returns the Julian day of a Gregorian date
+
+		var year = gdate.getFullYear(),
+			month = gdate.getMonth(),
+			d = gdate.getDate(),
+			isLeap = !(year%4) && (year%100 || !(year%400)), //TODO: dup
+			y = year - 1;
+		// This computation is actually ... + (_JAN_1_1_JULIAN_DAY - 3) + 2.
+		// Add 2 because Gregorian calendar starts 2 days after Julian
+		// calendar.
+		var julianDay = 365*y + Math.floor(y/4) - Math.floor(y/100) +
+			Math.floor(y/400) + 1721426 - 1;
+		// At this point julianDay indicates the day BEFORE the first day
+		// of January 1, <eyear> of the Gregorian calendar.
+		if(month != 0){
+			julianDay += this._GREGORIAN_MONTH_COUNT[month][isLeap ? 3 : 2];
+		}
+		
+		julianDay += d;
+		return julianDay;
+	}
+});
+
+dojox.date.hebrew.Date.prototype.valueOf = function(){
+	return this.toGregorian().valueOf();
 };
-}
diff --git a/dojox/date/hebrew/locale.js b/dojox/date/hebrew/locale.js
index f96b1fa..938e125 100644
--- a/dojox/date/hebrew/locale.js
+++ b/dojox/date/hebrew/locale.js
@@ -1,414 +1,520 @@
-/*
-	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
-*/
+dojo.provide("dojox.date.hebrew.locale");
 
 
-if(!dojo._hasResource["dojox.date.hebrew.locale"]){
-dojo._hasResource["dojox.date.hebrew.locale"]=true;
-dojo.provide("dojox.date.hebrew.locale");
 dojo.require("dojox.date.hebrew.Date");
 dojo.require("dojox.date.hebrew.numerals");
 dojo.require("dojo.regexp");
 dojo.require("dojo.string");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojo.cldr","hebrew",null,"ROOT,ar,he");
+
+
+//Load the bundles containing localization information for
+// names and formats 
+dojo.requireLocalization("dojo.cldr", "hebrew");
+
 (function(){
-function _1(_2,_3,_4,_5,_6){
-return _6.replace(/([a-z])\1*/ig,function(_7){
-var s,_8;
-var c=_7.charAt(0);
-var l=_7.length;
-var _9=["abbr","wide","narrow"];
-switch(c){
-case "y":
-if(_4.match(/^he(?:-.+)?$/)){
-s=dojox.date.hebrew.numerals.getYearHebrewLetters(_2.getFullYear());
-}else{
-s=String(_2.getFullYear());
-}
-break;
-case "M":
-var m=_2.getMonth();
-if(l<3){
-if(!_2.isLeapYear(_2.getFullYear())&&m>5){
-m--;
-}
-if(_4.match(/^he(?:-.+)?$/)){
-s=dojox.date.hebrew.numerals.getMonthHebrewLetters(m);
-}else{
-s=m+1;
-_8=true;
-}
-}else{
-var _a=["months","format",_9[l-3]].join("-");
-s=_3[_a][m];
-}
-break;
-case "d":
-if(_4.match(/^he(?:-.+)?$/)){
-s=_2.getDateLocalized(_4);
-}else{
-s=_2.getDate();
-_8=true;
-}
-break;
-case "E":
-var d=_2.getDay();
-if(l<3){
-s=d+1;
-_8=true;
-}else{
-var _b=["days","format",_9[l-3]].join("-");
-s=_3[_b][d];
-}
-break;
-case "a":
-var _c=(_2.getHours()<12)?"am":"pm";
-s=_3[_c];
-break;
-case "h":
-case "H":
-case "K":
-case "k":
-var h=_2.getHours();
-switch(c){
-case "h":
-s=(h%12)||12;
-break;
-case "H":
-s=h;
-break;
-case "K":
-s=(h%12);
-break;
-case "k":
-s=h||24;
-break;
-}
-_8=true;
-break;
-case "m":
-s=_2.getMinutes();
-_8=true;
-break;
-case "s":
-s=_2.getSeconds();
-_8=true;
-break;
-case "S":
-s=Math.round(_2.getMilliseconds()*Math.pow(10,l-3));
-_8=true;
-break;
-case "z":
-s="";
-break;
-default:
-throw new Error("dojox.date.hebrew.locale.formatPattern: invalid pattern char: "+_6);
-}
-if(_8){
-s=dojo.string.pad(s,l);
-}
-return s;
-});
-};
-dojox.date.hebrew.locale.format=function(_d,_e){
-_e=_e||{};
-var _f=dojo.i18n.normalizeLocale(_e.locale);
-var _10=_e.formatLength||"short";
-var _11=dojox.date.hebrew.locale._getHebrewBundle(_f);
-var str=[];
-var _12=dojo.hitch(this,_1,_d,_11,_f,_e.fullYear);
-if(_e.selector=="year"){
-var _13=_d.getFullYear();
-return _f.match(/^he(?:-.+)?$/)?dojox.date.hebrew.numerals.getYearHebrewLetters(_13):_13;
-}
-if(_e.selector!="time"){
-var _14=_e.datePattern||_11["dateFormat-"+_10];
-if(_14){
-str.push(_15(_14,_12));
-}
-}
-if(_e.selector!="date"){
-var _16=_e.timePattern||_11["timeFormat-"+_10];
-if(_16){
-str.push(_15(_16,_12));
-}
-}
-var _17=str.join(" ");
-return _17;
-};
-dojox.date.hebrew.locale.regexp=function(_18){
-return dojox.date.hebrew.locale._parseInfo(_18).regexp;
-};
-dojox.date.hebrew.locale._parseInfo=function(_19){
-_19=_19||{};
-var _1a=dojo.i18n.normalizeLocale(_19.locale);
-var _1b=dojox.date.hebrew.locale._getHebrewBundle(_1a);
-var _1c=_19.formatLength||"short";
-var _1d=_19.datePattern||_1b["dateFormat-"+_1c];
-var _1e=_19.timePattern||_1b["timeFormat-"+_1c];
-var _1f;
-if(_19.selector=="date"){
-_1f=_1d;
-}else{
-if(_19.selector=="time"){
-_1f=_1e;
-}else{
-_1f=(_1e===undefined)?_1d:_1d+" "+_1e;
-}
-}
-var _20=[];
-var re=_15(_1f,dojo.hitch(this,_21,_20,_1b,_19));
-return {regexp:re,tokens:_20,bundle:_1b};
-};
-dojox.date.hebrew.locale.parse=function(_22,_23){
-_22=_22.replace(/[\u200E\u200F\u202A-\u202E]/g,"");
-if(!_23){
-_23={};
-}
-var _24=dojox.date.hebrew.locale._parseInfo(_23);
-var _25=_24.tokens,_26=_24.bundle;
-var re=new RegExp("^"+_24.regexp+"$");
-var _27=re.exec(_22);
-var _28=dojo.i18n.normalizeLocale(_23.locale);
-if(!_27){
-return null;
-}
-var _29,_2a;
-var _2b=[5730,3,23,0,0,0,0];
-var _2c="";
-var _2d=0;
-var _2e=["abbr","wide","narrow"];
-var _2f=dojo.every(_27,function(v,i){
-if(!i){
-return true;
-}
-var _30=_25[i-1];
-var l=_30.length;
-switch(_30.charAt(0)){
-case "y":
-if(_28.match(/^he(?:-.+)?$/)){
-_2b[0]=dojox.date.hebrew.numerals.parseYearHebrewLetters(v);
-}else{
-_2b[0]=Number(v);
-}
-break;
-case "M":
-if(l>2){
-var _31=_26["months-format-"+_2e[l-3]].concat();
-if(!_23.strict){
-v=v.replace(".","").toLowerCase();
-_31=dojo.map(_31,function(s){
-return s?s.replace(".","").toLowerCase():s;
-});
-}
-v=dojo.indexOf(_31,v);
-if(v==-1){
-return false;
-}
-_2d=l;
-}else{
-if(_28.match(/^he(?:-.+)?$/)){
-v=dojox.date.hebrew.numerals.parseMonthHebrewLetters(v);
-}else{
-v--;
-}
-}
-_2b[1]=Number(v);
-break;
-case "D":
-_2b[1]=0;
-case "d":
-if(_28.match(/^he(?:-.+)?$/)){
-_2b[2]=dojox.date.hebrew.numerals.parseDayHebrewLetters(v);
-}else{
-_2b[2]=Number(v);
-}
-break;
-case "a":
-var am=_23.am||_26.am;
-var pm=_23.pm||_26.pm;
-if(!_23.strict){
-var _32=/\./g;
-v=v.replace(_32,"").toLowerCase();
-am=am.replace(_32,"").toLowerCase();
-pm=pm.replace(_32,"").toLowerCase();
-}
-if(_23.strict&&v!=am&&v!=pm){
-return false;
-}
-_2c=(v==pm)?"p":(v==am)?"a":"";
-break;
-case "K":
-if(v==24){
-v=0;
-}
-case "h":
-case "H":
-case "k":
-_2b[3]=Number(v);
-break;
-case "m":
-_2b[4]=Number(v);
-break;
-case "s":
-_2b[5]=Number(v);
-break;
-case "S":
-_2b[6]=Number(v);
-}
-return true;
-});
-var _33=+_2b[3];
-if(_2c==="p"&&_33<12){
-_2b[3]=_33+12;
-}else{
-if(_2c==="a"&&_33==12){
-_2b[3]=0;
-}
-}
-var _34=new dojox.date.hebrew.Date(_2b[0],_2b[1],_2b[2],_2b[3],_2b[4],_2b[5],_2b[6]);
-if(_2d<3&&_2b[1]>=5&&!_34.isLeapYear(_34.getFullYear())){
-_34.setMonth(_2b[1]+1);
-}
-return _34;
+	// Format a pattern without literals
+	function formatPattern(dateObject, bundle, locale, 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 'y':
+					if(locale.match(/^he(?:-.+)?$/)){
+						s = dojox.date.hebrew.numerals.getYearHebrewLetters(dateObject.getFullYear());
+					}else{
+						s = String(dateObject.getFullYear());
+					}	
+					break;
+				case 'M':
+					var m = dateObject.getMonth();
+					if(l<3){
+						if(!dateObject.isLeapYear(dateObject.getFullYear()) && m>5){m--;}
+						if(locale.match(/^he(?:-.+)?$/)){
+							s = dojox.date.hebrew.numerals.getMonthHebrewLetters(m);
+						}else{
+							s = m+1; pad = true;
+						}	
+					}else{
+						var monthNames = dojox.date.hebrew.locale.getNames('months',widthList[l-3], 'format', locale, dateObject);
+						s = monthNames[m];
+					}
+					break;
+				case 'd':
+					if(locale.match(/^he(?:-.+)?$/)){
+						s =  dateObject.getDateLocalized(locale);
+					}else{
+						s = dateObject.getDate(); 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['dayPeriods-format-wide-' + 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 'z': 
+					s = "";
+					break;
+				default:
+					throw new Error("dojox.date.hebrew.locale.formatPattern: invalid pattern char: "+pattern);
+			}
+			if(pad){ s = dojo.string.pad(s, l); }
+			return s;
+		});
+	}	
+	
+dojox.date.hebrew.locale.format = function(/*hebrew.Date*/dateObject, /*object?*/options){
+	// based on and similar to dojo.date.locale.format
+	//summary:
+	//		Format a Date object as a String, using  settings.
+	//
+	// description:
+	//		Create a string from a hebrew.Date object using a known pattern.
+	//		By default, this method formats both date and time from dateObject.
+	//		Default formatting lengths is 'short'
+	//		
+	// 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 = dojox.date.hebrew.locale._getHebrewBundle(locale);
+	var str = [];
+
+	var sauce = dojo.hitch(this, formatPattern, dateObject, bundle, locale, options.fullYear);
+	if(options.selector == "year"){
+		var year = dateObject.getFullYear();
+		return locale.match(/^he(?:-.+)?$/) ?
+			dojox.date.hebrew.numerals.getYearHebrewLetters(year) : 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
+};	
+
+dojox.date.hebrew.locale.regexp = function(/*object?*/options){
+	//	based on and similar to dojo.date.locale.regexp	
+	// summary:
+	//		Builds the regular needed to parse a hebrew.Date
+
+	return dojox.date.hebrew.locale._parseInfo(options).regexp; // String
 };
-function _15(_35,_36,_37,_38){
-var _39=function(x){
-return x;
+
+dojox.date.hebrew.locale._parseInfo = function(/*oblect?*/options){
+/* based on and similar to dojo.date.locale._parseInfo */
+
+	options = options || {};
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	var bundle = dojox.date.hebrew.locale._getHebrewBundle(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 = (timePattern === undefined) ? datePattern : datePattern + ' ' + timePattern; //hebrew resource file does not contain time patterns - a bug?
+	}
+
+	var tokens = [];
+	
+	var re = _processPattern(pattern, dojo.hitch(this, _buildDateTimeRE, tokens, bundle, options));
+	return {regexp: re, tokens: tokens, bundle: bundle};
 };
-_36=_36||_39;
-_37=_37||_39;
-_38=_38||_39;
-var _3a=_35.match(/(''|[^'])+/g);
-var _3b=_35.charAt(0)=="'";
-dojo.forEach(_3a,function(_3c,i){
-if(!_3c){
-_3a[i]="";
-}else{
-_3a[i]=(_3b?_37:_36)(_3c);
-_3b=!_3b;
-}
-});
-return _38(_3a.join(""));
+
+
+
+
+dojox.date.hebrew.locale.parse= function(/*String*/value, /*object?*/options){
+		// based on and similar to dojo.date.locale.parse
+		// summary: This function parse string date value according to options
+		// example:
+		// |		var dateHebrew = dojox.date.hebrew.locale.parse('11/10/5740', {datePattern:'dd/MM/yy', selector:'date'});
+		// |		in Hebrew locale string for parsing contains Hebrew Numerals     
+		// |
+		// |  options = {datePattern:'dd MMMM yy', selector:'date'};
+		// |  
+		// |   y - year  
+		// |   M, MM  - short month 
+		// |  MMM, MMMM - long month 
+		// |  d - date 
+		// |  a - am, pm 	
+		// |   E, EE, EEE, EEEE  - week day 
+		// |  	
+		// |    h, H, k, K, m, s, S,  -  time format  
+		
+	value =  value.replace(/[\u200E\u200F\u202A-\u202E]/g, ""); //remove special chars
+
+	if(!options){options={};}
+	var info = dojox.date.hebrew.locale._parseInfo(options);
+	
+	var tokens = info.tokens, bundle = info.bundle;
+	var re = new RegExp("^" + info.regexp + "$");
+	
+	var match = re.exec(value);
+
+	var locale = dojo.i18n.normalizeLocale(options.locale); 
+
+	if(!match){ 
+		console.debug("dojox.date.hebrew.locale.parse: value  "+value+" doesn't match pattern   " + re);
+		return null;
+	} // null
+	
+	var date, date1;
+	
+	//var result = [1970,0,1,0,0,0,0]; // 
+	var result = [5730,3,23,0,0,0,0];  // hebrew date for [1970,0,1,0,0,0,0] used in gregorian locale
+	var amPm = "";
+	var mLength = 0;
+	var widthList = ["abbr", "wide", "narrow"];
+	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(locale.match(/^he(?:-.+)?$/)){
+					result[0] = dojox.date.hebrew.numerals.parseYearHebrewLetters(v);
+				}else{
+					result[0] = Number(v);
+				}	
+				break;
+			case 'M':
+				//if  it is short format, month is one letter or two letter with "geresh"
+				if(l>2){
+					//we do not know here if the year is leap or not
+					var months = dojox.date.hebrew.locale.getNames('months', widthList[l-3], 'format', locale, new dojox.date.hebrew.Date(5769, 1, 1)),
+						leapmonths = dojox.date.hebrew.locale.getNames('months', widthList[l-3], 'format', locale, new dojox.date.hebrew.Date(5768, 1, 1));
+					if(!options.strict){
+						//Tolerate abbreviating period in month part
+						//Case-insensitive comparison
+						v = v.replace(".","").toLowerCase();
+						months = dojo.map(months, function(s){ return s ? s.replace(".","").toLowerCase() : s; } );
+						leapmonths = dojo.map(leapmonths, function(s){ return s ? s.replace(".","").toLowerCase() : s; } );
+					}
+					var monthName = v; 
+					v = dojo.indexOf(months, monthName);
+					if(v == -1){
+						v = dojo.indexOf(leapmonths, monthName);
+						if(v == -1){
+							//console.debug("dojox.date.hebrew.locale.parse: Could not parse month name:  second   " + v +"'.");
+							return false;
+						}
+					}
+					mLength = l;
+				}else{
+					if(locale.match(/^he(?:-.+)?$/)){
+						v = dojox.date.hebrew.numerals.parseMonthHebrewLetters(v); 
+					}else{
+						v--;
+					}						
+				}
+				result[1] = Number(v);
+				break;
+			case 'D':
+				result[1] = 0;
+				// fallthrough...
+			case 'd':
+				if(locale.match(/^he(?:-.+)?$/)){
+					result[2] = dojox.date.hebrew.numerals.parseDayHebrewLetters(v);
+				}else{
+					result[2] = Number(v);
+				}
+				break;
+			case 'a': //am/pm
+				var am = options.am || bundle['dayPeriods-format-wide-am'],
+					pm = options.pm || bundle['dayPeriods-format-wide-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)
+				//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] = Number(v);
+				break;
+			case 'm': //minutes
+				result[4] = Number(v);
+				break;
+			case 's': //seconds
+				result[5] = Number(v);
+				break; 
+			case 'S': //milliseconds
+				result[6] = Number(v);
+		}
+		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
+	}
+	var dateObject = new dojox.date.hebrew.Date(result[0], result[1], result[2], result[3], result[4], result[5], result[6]); // hebrew.Date
+	//for non leap year, the index of the short month start from adar should be increased by 1
+	if(mLength < 3 && result[1] >= 5 && !dateObject.isLeapYear(dateObject.getFullYear())){
+		dateObject.setMonth(result[1]+1);
+	}
+	return dateObject; // hebrew.Date 
 };
-function _21(_3d,_3e,_3f,_40){
-_40=dojo.regexp.escapeString(_40);
-var _41=dojo.i18n.normalizeLocale(_3f.locale);
-return _40.replace(/([a-z])\1*/ig,function(_42){
-var s;
-var c=_42.charAt(0);
-var l=_42.length;
-var p2="",p3="";
-if(_3f.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="\\S+";
-break;
-case "M":
-if(_41.match("^he(?:-.+)?$")){
-s=(l>2)?"\\S+ ?\\S+":"\\S{1,4}";
-}else{
-s=(l>2)?"\\S+ ?\\S+":p2+"[1-9]|1[0-2]";
-}
-break;
-case "d":
-if(_41.match("^he(?:-.+)?$")){
-s="\\S['\"'׳]{1,2}\\S?";
-}else{
-s="[12]\\d|"+p2+"[1-9]|30";
-}
-break;
-case "E":
-if(_41.match("^he(?:-.+)?$")){
-s=(l>3)?"\\S+ ?\\S+":"\\S";
-}else{
-s="\\S+";
-}
-break;
-case "h":
-s=p2+"[1-9]|1[0-2]";
-break;
-case "k":
-s=p2+"\\d|1[01]";
-break;
-case "H":
-s=p2+"\\d|1\\d|2[0-3]";
-break;
-case "K":
-s=p2+"[1-9]|1\\d|2[0-4]";
-break;
-case "m":
-case "s":
-s=p2+"\\d|[0-5]\\d";
-break;
-case "S":
-s="\\d{"+l+"}";
-break;
-case "a":
-var am=_3f.am||_3e.am||"AM";
-var pm=_3f.pm||_3e.pm||"PM";
-if(_3f.strict){
-s=am+"|"+pm;
-}else{
-s=am+"|"+pm;
-if(am!=am.toLowerCase()){
-s+="|"+am.toLowerCase();
-}
-if(pm!=pm.toLowerCase()){
-s+="|"+pm.toLowerCase();
-}
-}
-break;
-default:
-s=".*";
+
+
+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(''));
 }
-if(_3d){
-_3d.push(_42);
+
+function _buildDateTimeRE  (tokens, bundle, options, pattern){
+		// based on and similar to dojo.date.locale._buildDateTimeRE 
+		//
+	
+	pattern = dojo.regexp.escapeString(pattern); 
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	
+	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 = '\\S+';
+					break;
+				case 'M':
+					if(locale.match('^he(?:-.+)?$')){
+						s = (l>2) ? '\\S+ ?\\S+' : '\\S{1,4}';
+					}else{
+						s = (l>2) ?  '\\S+ ?\\S+' : p2+'[1-9]|1[0-2]';
+					}	
+					break;
+				case 'd':
+					if(locale.match('^he(?:-.+)?$')){
+						s = '\\S[\'\"\'\u05F3]{1,2}\\S?';
+					}else{
+						s = '[12]\\d|'+p2+'[1-9]|30';
+					}
+					break;
+				case 'E':
+					if(locale.match('^he(?:-.+)?$')){
+						s = (l>3) ? '\\S+ ?\\S+' : '\\S';
+					}else{
+						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 = p2+'\\d|[0-5]\\d';
+					break;
+				case 'S':
+					s = '\\d{'+l+'}';
+					break;
+				case 'a':
+					var am = options.am || bundle['dayPeriods-format-wide-am'],
+						pm = options.pm || bundle['dayPeriods-format-wide-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(); }
+					}
+					break;
+				default:
+					s = ".*";
+			}	 
+			if(tokens){ tokens.push(match); }
+			return "(" + s + ")"; // add capture
+		}).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace.  Need explicit handling of \xa0 for IE. */
 }
-return "("+s+")";
-}).replace(/[\xa0 ]/g,"[\\s\\xa0]");
-};
 })();
+
+
+
 (function(){
-var _43=[];
-dojox.date.hebrew.locale.addCustomFormats=function(_44,_45){
-_43.push({pkg:_44,name:_45});
+var _customFormats = [];
+dojox.date.hebrew.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});
 };
-dojox.date.hebrew.locale._getHebrewBundle=function(_46){
-var _47={};
-dojo.forEach(_43,function(_48){
-var _49=dojo.i18n.getLocalization(_48.pkg,_48.name,_46);
-_47=dojo.mixin(_47,_49);
-},this);
-return _47;
+
+dojox.date.hebrew.locale._getHebrewBundle = function(/*String*/locale){
+	var hebrew = {};
+	dojo.forEach(_customFormats, function(desc){
+		var bundle = dojo.i18n.getLocalization(desc.pkg, desc.name, locale);
+		hebrew = dojo.mixin(hebrew, bundle);
+	}, this);
+	return hebrew; /*Object*/
 };
 })();
+
 dojox.date.hebrew.locale.addCustomFormats("dojo.cldr","hebrew");
-dojox.date.hebrew.locale.getNames=function(_4a,_4b,_4c,_4d,_4e){
-var _4f;
-var _50=dojox.date.hebrew.locale._getHebrewBundle;
-var _51=[_4a,_4c,_4b];
-if(_4c=="standAlone"){
-var key=_51.join("-");
-_4f=_50(_4d)[key];
-if(_4f===_50("ROOT")[key]){
-_4f=undefined;
-}
-}
-_51[1]="format";
-return (_4f||_50(_4d)[_51.join("-")]).concat();
+
+dojox.date.hebrew.locale.getNames = function(/*String*/item, /*String*/type, /*String?*/context, /*String?*/locale, /*dojox.date.hebrew.Date?*/date){
+	// 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)
+	// use:
+	//	'standAlone' || 'format' (default)
+	// locale:
+	//	override locale used to find the names
+	// date:
+	//	required for item=months to determine leap month name
+	//
+	// using  var monthNames = dojox.date.hebrew.locale.getNames('months', 'wide', 'format', 'he', new dojox.date.hebrew.Date(5768, 2, 12));
+
+	var label,
+		lookup = dojox.date.hebrew.locale._getHebrewBundle,
+		props = [item, context, type];
+	if(context == 'standAlone'){
+		var key = props.join('-');
+		label = lookup(locale)[key];
+		// Fall back to 'format' flavor of name
+		if(label === lookup("ROOT")[key]){ label = undefined; } // a bit of a kludge, in the absence 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
+	var result = (label || lookup(locale)[props.join('-')]).concat();
+
+	if(item == "months"){
+		if(date.isLeapYear(date.getFullYear())){
+			// Adar I (6th position in the array) will be used.
+			// Substitute the leap month Adar II for the regular Adar (7th position)
+			props.push("leap");
+			result[6] = lookup(locale)[props.join('-')];
+		}else{
+			// Remove Adar I but leave an empty position in the array
+			delete result[5];
+		}
+	}
+
+	return result; /*Array*/
 };
-}
diff --git a/dojox/date/hebrew/numerals.js b/dojox/date/hebrew/numerals.js
index a4c0805..c7d68be 100644
--- a/dojox/date/hebrew/numerals.js
+++ b/dojox/date/hebrew/numerals.js
@@ -1,103 +1,139 @@
-/*
-	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
-*/
+dojo.provide("dojox.date.hebrew.numerals");
 
+//Conversion from "Hindi" numerals to Hebrew numerals and vice versa
 
-if(!dojo._hasResource["dojox.date.hebrew.numerals"]){
-dojo._hasResource["dojox.date.hebrew.numerals"]=true;
-dojo.provide("dojox.date.hebrew.numerals");
 (function(){
-var _1="אבגדהוזחט";
-var _2="יכלמנסעפצ";
-var _3="קרשת";
-var _4=function(_5,_6){
-_5=_5.replace("יה","טו").replace("יו","טז");
-if(!_6){
-var _7=_5.length;
-if(_7>1){
-_5=_5.substr(0,_7-1)+"\""+_5.charAt(_7-1);
-}else{
-_5+="׳";
-}
-}
-return _5;
-};
-var _8=function(_9){
-var _a=0;
-dojo.forEach(_9,function(ch){
-var i;
-if((i=_1.indexOf(ch))!=-1){
-_a+=++i;
-}else{
-if((i=_2.indexOf(ch))!=-1){
-_a+=10*++i;
-}else{
-if((i=_3.indexOf(ch))!=-1){
-_a+=100*++i;
-}
-}
-}
-});
-return _a;
-};
-var _b=function(_c){
-var _d="",n=4,j=9;
-while(_c){
-if(_c>=n*100){
-_d+=_3.charAt(n-1);
-_c-=n*100;
-continue;
-}else{
-if(n>1){
-n--;
-continue;
-}else{
-if(_c>=j*10){
-_d+=_2.charAt(j-1);
-_c-=j*10;
-}else{
-if(j>1){
-j--;
-continue;
-}else{
-if(_c>0){
-_d+=_1.charAt(_c-1);
-_c=0;
-}
-}
-}
-}
-}
-}
-return _d;
-};
-dojox.date.hebrew.numerals.getYearHebrewLetters=function(_e){
-var y=_e%1000;
-if(!y){
-throw new Error("Hebrew year "+_e+" is not in range 5001-5999");
-}
-return _4(_b(y));
-};
-dojox.date.hebrew.numerals.parseYearHebrewLetters=function(_f){
-return _8(_f)+5000;
-};
-dojox.date.hebrew.numerals.getDayHebrewLetters=function(day,_10){
-return _4(_b(day),_10);
-};
-dojox.date.hebrew.numerals.parseDayHebrewLetters=function(day){
-return _8(day);
-};
-dojox.date.hebrew.numerals.getMonthHebrewLetters=function(_11){
-return _4(_b(_11+1));
-};
-dojox.date.hebrew.numerals.parseMonthHebrewLetters=function(_12){
-var _13=dojox.date.hebrew.numerals.parseDayHebrewLetters(_12)-1;
-if(_13==-1||_13>12){
-throw new Error("The month name is incorrect , month = "+_13);
-}
-return _13;
-};
+
+	var DIG="אבגדהוזחט";
+	var	TEN="יכלמנסעפצ";
+	var	HUN="קרשת";
+
+	var transformChars = function(str, nogrsh){
+		str = str.replace("יה", "טו").replace("יו", "טז");
+
+		if(!nogrsh){
+			var len = str.length;
+			if(len > 1){
+				str = str.substr(0, len - 1) + '"' + str.charAt(len - 1);
+			}else{
+				str += "\u05F3"; // 05F3:geresh
+			}
+		}
+		return str; // String
+	};
+	 
+	var parseStrToNumber = function(str){
+		var num = 0;
+		dojo.forEach(str, function(ch){
+			var i;
+			if((i = DIG.indexOf(ch)) != -1){
+				num += ++i;
+			}else if((i = TEN.indexOf(ch)) != -1){
+				num += 10 * ++i;
+			}else if((i = HUN.indexOf(ch)) != -1){
+				num += 100 * ++i;
+			}
+		});
+		return num; //Number
+	};
+	 
+	var convertNumberToStr = function(num){
+		var str  = "", n = 4, j = 9;
+  		while(num){ 
+			if(num >= n*100){
+				str += HUN.charAt(n-1);
+				num -= n*100;
+				continue;
+			}else if(n > 1){
+				n--;
+				continue;
+			}else if(num >= j*10){
+				str += TEN.charAt(j-1);
+				num -= j*10;
+			}else if(j > 1){
+				j--;
+				continue;
+			}else if(num > 0){
+				str += DIG.charAt(num-1);
+				num = 0;
+			}		
+		}
+		return str; //String	
+	};
+
+	dojox.date.hebrew.numerals.getYearHebrewLetters = function(/*Number */ year){
+		// summary: converts the year from an integer to Hebrew numerals.
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date();
+		// |
+		// |		document.writeln(dojox.date.hebrew.numerals.getYearHebrewLetters(date1.getFullYear());	
+		
+		var rem = year % 1000;
+		//FIXME: tests include dates outside this range and seem to pass.
+		//	    	if((year - rem) / 1000 != 5){ throw new Error("Hebrew year "+year+" is not in range 5001-5999");}
+		return transformChars(convertNumberToStr(rem)); // String
+	};
+	
+	dojox.date.hebrew.numerals.parseYearHebrewLetters  = function(/*String hebrew year*/ year){
+		// summary: converts the year written in Hebrew numerals to an integer
+		//                   
+		// example:
+		// |		var date = new dojox.date.hebrew.Date();
+		// |        	date.setFullYear(dojox.date.hebrew.numerals.parseYearHebrewLetters('\u05ea\u05e9\u05e1\u05f4\u05d7'));
+
+		return parseStrToNumber(year) + 5000; // int
+	};
+	
+	dojox.date.hebrew.numerals.getDayHebrewLetters =  function(day, /*boolean?*/ nogrsh){
+		// summary: converts an integer to a String representing the number in Hebrew numerals.   Can be formatted with or without geresh &#x05f3;
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date();
+		// |
+		// |		document.writeln(dojox.date.hebrew.numerals.getDayHebrewLetters(date1.getDay());
+
+		return transformChars(convertNumberToStr(day), nogrsh); // String
+	};
+	
+	dojox.date.hebrew.numerals.parseDayHebrewLetters =  function(/*String hebrew*/ day){
+		// summary: converts the string containing a Hebrew numeral to an integer
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date();
+		// |
+		// |		date1.setDate(dojox.date.hebrew.numerals.parseDayHebrewLetters('\u05d0')); // ALEPH
+		return parseStrToNumber(day); // int
+	};
+
+	dojox.date.hebrew.numerals.getMonthHebrewLetters =  function(/*int*/month){
+		// summary: converts an integer representing a  month to a String written in Hebrew numerals
+		//
+		// example:
+		// |		var date1 = new dojox.date.hebrew.Date();
+		// |
+		// |		document.writeln(dojox.date.hebrew.numerals.getMonthHebrewLetters(date1.getMonth());
+
+		return transformChars(convertNumberToStr(month+1)); // String
+	};	
+
+	dojox.date.hebrew.numerals.parseMonthHebrewLetters = function(/*String*/monthStr){
+		// summary: converts a Hebrew numeral string representing
+		//	a month to an integer.  The returned value
+		//	is indexed in the month name array.  To use it for
+		//	setMonth, do correction for leap year
+		//
+		// example:
+		// |		var date = new dojox.date.hebrew.Date();
+		// |            var number = dojox.date.hebrew.numerals.parseMonthHebrewLetters("\u05ea\u05de\u05d5\u05d6"); // Tammuz
+		// |		date.setMonth(number);
+			
+		//month number from 0 to 12
+		var monnum = dojox.date.hebrew.numerals.parseDayHebrewLetters(monthStr) - 1;
+
+		if(monnum == -1 || monnum > 12){
+			throw new Error("The month name is incorrect , month = " + monnum); 
+		}
+		return monnum;
+	};
 })();
-}
diff --git a/dojox/date/islamic.js b/dojox/date/islamic.js
index 6f211c5..0bd51d9 100644
--- a/dojox/date/islamic.js
+++ b/dojox/date/islamic.js
@@ -1,185 +1,247 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.islamic"]){
-dojo._hasResource["dojox.date.islamic"]=true;
 dojo.provide("dojox.date.islamic");
-dojo.experimental("dojox.date.islamic");
+
 dojo.require("dojox.date.islamic.Date");
-dojo.require("dojo.date");
-dojox.date.islamic.getDaysInMonth=function(_1){
-return _1.getDaysInIslamicMonth(_1.getMonth(),_1.getFullYear());
-};
-dojox.date.islamic.compare=function(_2,_3,_4){
-if(_2 instanceof dojox.date.islamic.Date){
-_2=_2.toGregorian();
-}
-if(_3 instanceof dojox.date.islamic.Date){
-_3=_3.toGregorian();
-}
-return dojo.date.compare.apply(null,arguments);
+dojo.require("dojo.date"); // for compare
+	
+// Utility methods to do arithmetic calculations with islamic.Dates
+
+	// added for compat to date
+dojox.date.islamic.getDaysInMonth = function(/*islamic.Date*/month){
+	return month.getDaysInIslamicMonth(month.getMonth(), month.getFullYear());
 };
-dojox.date.islamic.add=function(_5,_6,_7){
-var _8=new dojox.date.islamic.Date(_5);
-switch(_6){
-case "day":
-_8.setDate(_5.getDate()+_7);
-break;
-case "weekday":
-var _9=_5.getDay();
-if(((_9+_7)<5)&&((_9+_7)>0)){
-_8.setDate(_5.getDate()+_7);
-}else{
-var _a=0,_b=0;
-if(_9==5){
-_9=4;
-_b=(_7>0)?-1:1;
-}else{
-if(_9==6){
-_9=4;
-_b=(_7>0)?-2:2;
-}
-}
-var _c=(_7>0)?(5-_9-1):-_9;
-var _d=_7-_c;
-var _e=parseInt(_d/5);
-if(_d%5!=0){
-_a=(_7>0)?2:-2;
-}
-_a=_a+_e*7+_d%5+_c;
-_8.setDate(_5.getDate()+_a+_b);
-}
-break;
-case "year":
-_8.setFullYear(_5.getFullYear()+_7);
-break;
-case "week":
-_7*=7;
-_8.setDate(_5.getDate()+_7);
-break;
-case "month":
-var _f=_5.getMonth();
-_8.setMonth(_f+_7);
-break;
-case "hour":
-_8.setHours(_5.getHours()+_7);
-break;
-case "minute":
-_8.setMinutes(_5.getMinutes()+_7);
-break;
-case "second":
-_8.setSeconds(_5.getSeconds()+_7);
-break;
-case "millisecond":
-_8.setMilliseconds(_5.getMilliseconds()+_7);
-break;
-}
-return _8;
+
+//TODO: define islamic.isLeapYear?  Or should it be invalid, since it has different meaning?
+
+dojox.date.islamic.compare = function(/*islamic.Date*/date1, /*islamic.Date*/date2, /*String?*/portion){
+	//	summary:
+	//		Compare two islamic date objects by date, time, or both.
+	//	description:
+	//  	Returns 0 if equal, positive if a > b, else negative.
+	//	date1:
+	//		islamic.Date object
+	//	date2:
+	//		islamic.Date object.  If not specified, the current islamic.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"
+
+	if(date1 instanceof dojox.date.islamic.Date){
+		date1 = date1.toGregorian();
+	}
+	if(date2 instanceof dojox.date.islamic.Date){
+		date2 = date2.toGregorian();
+	}
+	
+	return dojo.date.compare.apply(null, arguments);
 };
-dojox.date.islamic.difference=function(_10,_11,_12){
-_11=_11||new dojox.date.islamic.Date();
-_12=_12||"day";
-var _13=_10.getFullYear()-_11.getFullYear();
-var _14=1;
-switch(_12){
-case "weekday":
-var _15=Math.round(dojox.date.islamic.difference(_10,_11,"day"));
-var _16=parseInt(dojox.date.islamic.difference(_10,_11,"week"));
-var mod=_15%7;
-if(mod==0){
-_15=_16*5;
-}else{
-var adj=0;
-var _17=_11.getDay();
-var _18=_10.getDay();
-_16=parseInt(_15/7);
-mod=_15%7;
-var _19=new dojox.date.islamic.Date(_11);
-_19.setDate(_19.getDate()+(_16*7));
-var _1a=_19.getDay();
-if(_15>0){
-switch(true){
-case _17==5:
-adj=-1;
-break;
-case _17==6:
-adj=0;
-break;
-case _18==5:
-adj=-1;
-break;
-case _18==6:
-adj=-2;
-break;
-case (_1a+mod)>5:
-adj=-2;
-}
-}else{
-if(_15<0){
-switch(true){
-case _17==5:
-adj=0;
-break;
-case _17==6:
-adj=1;
-break;
-case _18==5:
-adj=2;
-break;
-case _18==6:
-adj=1;
-break;
-case (_1a+mod)<0:
-adj=2;
-}
-}
-}
-_15+=adj;
-_15-=(_16*2);
-}
-_14=_15;
-break;
-case "year":
-_14=_13;
-break;
-case "month":
-var _1b=(_10.toGregorian()>_11.toGregorian())?_10:_11;
-var _1c=(_10.toGregorian()>_11.toGregorian())?_11:_10;
-var _1d=_1b.getMonth();
-var _1e=_1c.getMonth();
-if(_13==0){
-_14=_1b.getMonth()-_1c.getMonth();
-}else{
-_14=12-_1e;
-_14+=_1d;
-var i=_1c.getFullYear()+1;
-var e=_1b.getFullYear();
-for(i;i<e;i++){
-_14+=12;
-}
-}
-if(_10.toGregorian()<_11.toGregorian()){
-_14=-_14;
-}
-break;
-case "week":
-_14=parseInt(dojox.date.islamic.difference(_10,_11,"day")/7);
-break;
-case "day":
-_14/=24;
-case "hour":
-_14/=60;
-case "minute":
-_14/=60;
-case "second":
-_14/=1000;
-case "millisecond":
-_14*=_10.toGregorian().getTime()-_11.toGregorian().getTime();
-}
-return Math.round(_14);
+
+dojox.date.islamic.add = function(/*dojox.date.islamic.Date*/date, /*String*/interval, /*int*/amount){
+	//	based on and similar to dojo.date.add
+	//	summary:
+	//		Add to a Date in intervals of different size, from milliseconds to years
+	//	date: islamic.Date
+	//		Date object to start with
+	//	interval:
+	//		A string representing the interval.  One of the following:
+	//			"year", "month", "day", "hour", "minute", "second",
+	//			"millisecond", "week", "weekday"
+	//	amount:
+	//		How much to add to the date.
+
+	var newIslamDate = new dojox.date.islamic.Date(date);
+
+	switch(interval){
+		case "day":
+			newIslamDate.setDate(date.getDate() + amount);
+			break;
+		case "weekday":
+			var day = date.getDay();
+			if(((day + amount) < 5) && ((day + amount) > 0)){
+				 newIslamDate.setDate(date.getDate() + amount);
+			}else{
+				var adddays = 0, /*weekend */
+					remdays = 0;
+				if(day == 5){//friday
+					day = 4;
+					remdays = (amount > 0) ?  -1 : 1;
+				}else if(day == 6){ //shabat
+					day = 4;
+					remdays = (amount > 0) ? -2 : 2;		
+				}
+				var add = (amount > 0) ? (5 - day - 1) : -day 
+				var amountdif = amount - add;
+				var div = parseInt(amountdif / 5);
+				if(amountdif % 5 != 0){
+					adddays = (amount > 0)  ? 2 : -2;
+				}
+				adddays = adddays + div * 7 + amountdif % 5 + add;
+				newIslamDate.setDate(date.getDate() + adddays +  remdays);
+			}
+			break;
+		case "year":
+			newIslamDate.setFullYear(date.getFullYear() + amount);
+			break;
+		case "week":
+			amount *= 7;
+			newIslamDate.setDate(date.getDate() + amount);
+			break;
+		case "month":
+			var month = date.getMonth(); 
+			newIslamDate.setMonth(month + amount);
+			break;
+		case "hour":
+			newIslamDate.setHours(date.getHours() + amount);
+			break;	
+		case "minute":
+			newIslamDate.setMinutes(date.getMinutes() + amount);
+			break;	
+		case "second":
+			newIslamDate.setSeconds(date.getSeconds() + amount);
+			break;	
+		case "millisecond":
+			newIslamDate.setMilliseconds(date.getMilliseconds() + amount);
+			break;
+	}
+
+	return newIslamDate; // dojox.date.islamic.Date
+}; 
+
+dojox.date.islamic.difference = function(/*dojox.date.islamic.Date*/date1, /*dojox.date.islamic.Date?*/date2, /*String?*/interval){
+	//	based on and similar to dojo.date.difference
+	//	summary:
+	//        date1 - date2
+	//	 date2 is islamic.Date object.  If not specified, the current islamic.Date is used.
+	//	interval:
+	//		A string representing the interval.  One of the following:
+	//			"year", "month", "day", "hour", "minute", "second",
+	//			"millisecond",  "week", "weekday"
+	//		Defaults to "day".
+
+	date2 = date2 || new dojox.date.islamic.Date();
+	interval = interval || "day";
+	var yearDiff = date1.getFullYear() - date2.getFullYear();
+	var delta = 1; // Integer return value
+	switch(interval){
+		case "weekday":
+			var days = Math.round(dojox.date.islamic.difference(date1, date2, "day"));
+			var weeks = parseInt(dojox.date.islamic.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 = date2.getDay();
+				var bDay = date1.getDay();
+	
+				weeks = parseInt(days/7);
+				mod = days % 7;
+				// Mark the date advanced by the number of
+				// round weeks (may be zero)
+				var dtMark = new dojox.date.islamic.Date(date2);
+				dtMark.setDate(dtMark.getDate()+(weeks*7));
+				var dayMark = dtMark.getDay();
+	
+				// Spare change days -- 6 or less
+				if(days > 0){
+					switch(true){
+						// Range starts on Fri
+						case aDay == 5:
+							adj = -1;
+							break;
+						// Range starts on Sat
+						case aDay == 6:
+							adj = 0;
+							break;
+						// Range ends on Fri
+						case bDay == 5:
+							adj = -1;
+							break;
+						// Range ends on Sat
+						case bDay == 6:
+							adj = -2;
+							break;
+						// Range contains weekend
+						case (dayMark + mod) > 5:
+							adj = -2;
+					}
+				}else if(days < 0){
+					switch(true){
+						// Range starts on Fri
+						case aDay == 5:
+							adj = 0;
+							break;
+						// Range starts on Sat
+						case aDay == 6:
+							adj = 1;
+							break;
+						// Range ends on Fri
+						case bDay == 5:
+							adj = 2;
+							break;
+						// Range ends on Sat
+						case bDay == 6:
+							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":
+			var startdate =  (date1.toGregorian() > date2.toGregorian()) ? date1 : date2; // more
+			var enddate = (date1.toGregorian() > date2.toGregorian()) ? date2 : date1;
+			
+			var month1 = startdate.getMonth();
+			var month2 = enddate.getMonth();
+			
+			if (yearDiff == 0){
+				delta = startdate.getMonth() - enddate.getMonth() ;
+			}else{
+				delta = 12-month2;
+				delta +=  month1;
+				var i = enddate.getFullYear()+1;
+				var e = startdate.getFullYear();
+				for (i;   i < e;  i++){
+					delta += 12; 
+				}
+			}
+			if (date1.toGregorian() < date2.toGregorian()){
+				delta = -delta;
+			}
+			break;
+		case "week":
+			// Truncate instead of rounding
+			// Don't use Math.floor -- value may be negative
+			delta = parseInt(dojox.date.islamic.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 *= date1.toGregorian().getTime()- date2.toGregorian().getTime();
+	}
+
+	// Round for fractional values and DST leaps
+	return Math.round(delta); // Number (integer) 
 };
-}
diff --git a/dojox/date/islamic/Date.js b/dojox/date/islamic/Date.js
index e058e59..58bdd5f 100644
--- a/dojox/date/islamic/Date.js
+++ b/dojox/date/islamic/Date.js
@@ -1,267 +1,457 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.islamic.Date"]){
-dojo._hasResource["dojox.date.islamic.Date"]=true;
 dojo.provide("dojox.date.islamic.Date");
-dojo.experimental("dojox.date.islamic.Date");
+
 dojo.require("dojo.date");
-dojo.requireLocalization("dojo.cldr","islamic",null,"ROOT,ar,he");
-dojo.declare("dojox.date.islamic.Date",null,{_date:0,_month:0,_year:0,_hours:0,_minutes:0,_seconds:0,_milliseconds:0,_day:0,_GREGORIAN_EPOCH:1721425.5,_ISLAMIC_EPOCH:1948439.5,constructor:function(){
-var _1=arguments.length;
-if(!_1){
-this.fromGregorian(new Date());
-}else{
-if(_1==1){
-var _2=arguments[0];
-if(typeof _2=="number"){
-_2=new Date(_2);
-}
-if(_2 instanceof Date){
-this.fromGregorian(_2);
-}else{
-if(_2==""){
-this._date=new Date("");
-}else{
-this._year=_2._year;
-this._month=_2._month;
-this._date=_2._date;
-this._hours=_2._hours;
-this._minutes=_2._minutes;
-this._seconds=_2._seconds;
-this._milliseconds=_2._milliseconds;
-}
-}
-}else{
-if(_1>=3){
-this._year+=arguments[0];
-this._month+=arguments[1];
-this._date+=arguments[2];
-this._hours+=arguments[3]||0;
-this._minutes+=arguments[4]||0;
-this._seconds+=arguments[5]||0;
-this._milliseconds+=arguments[6]||0;
-}
-}
-}
-},getDate:function(){
-return this._date;
-},getMonth:function(){
-return this._month;
-},getFullYear:function(){
-return this._year;
-},getDay:function(){
-return this.toGregorian().getDay();
-},getHours:function(){
-return this._hours;
-},getMinutes:function(){
-return this._minutes;
-},getSeconds:function(){
-return this._seconds;
-},getMilliseconds:function(){
-return this._milliseconds;
-},setDate:function(_3){
-_3=parseInt(_3);
-if(_3>0&&_3<=this.getDaysInIslamicMonth(this._month,this._year)){
-this._date=_3;
-}else{
-var _4;
-if(_3>0){
-for(_4=this.getDaysInIslamicMonth(this._month,this._year);_3>_4;_3-=_4,_4=this.getDaysInIslamicMonth(this._month,this._year)){
-this._month++;
-if(this._month>=12){
-this._year++;
-this._month-=12;
-}
-}
-this._date=_3;
-}else{
-for(_4=this.getDaysInIslamicMonth((this._month-1)>=0?(this._month-1):11,((this._month-1)>=0)?this._year:this._year-1);_3<=0;_4=this.getDaysInIslamicMonth((this._month-1)>=0?(this._month-1):11,((this._month-1)>=0)?this._year:this._year-1)){
-this._month--;
-if(this._month<0){
-this._year--;
-this._month+=12;
-}
-_3+=_4;
-}
-this._date=_3;
-}
-}
-return this;
-},setFullYear:function(_5){
-this._year=+_5;
-},setMonth:function(_6){
-this._year+=Math.floor(_6/12);
-this._month=Math.floor(_6%12);
-},setHours:function(){
-var _7=arguments.length;
-var _8=0;
-if(_7>=1){
-_8=parseInt(arguments[0]);
-}
-if(_7>=2){
-this._minutes=parseInt(arguments[1]);
-}
-if(_7>=3){
-this._seconds=parseInt(arguments[2]);
-}
-if(_7==4){
-this._milliseconds=parseInt(arguments[3]);
-}
-while(_8>=24){
-this._date++;
-var _9=this.getDaysInIslamicMonth(this._month,this._year);
-if(this._date>_9){
-this._month++;
-if(this._month>=12){
-this._year++;
-this._month-=12;
-}
-this._date-=_9;
-}
-_8-=24;
-}
-this._hours=_8;
-},setMinutes:function(_a){
-while(_a>=60){
-this._hours++;
-if(this._hours>=24){
-this._date++;
-this._hours-=24;
-var _b=this.getDaysInIslamicMonth(this._month,this._year);
-if(this._date>_b){
-this._month++;
-if(this._month>=12){
-this._year++;
-this._month-=12;
-}
-this._date-=_b;
-}
-}
-_a-=60;
-}
-this._minutes=_a;
-},setSeconds:function(_c){
-while(_c>=60){
-this._minutes++;
-if(this._minutes>=60){
-this._hours++;
-this._minutes-=60;
-if(this._hours>=24){
-this._date++;
-this._hours-=24;
-var _d=this.getDaysInIslamicMonth(this._month,this._year);
-if(this._date>_d){
-this._month++;
-if(this._month>=12){
-this._year++;
-this._month-=12;
-}
-this._date-=_d;
-}
-}
-}
-_c-=60;
-}
-this._seconds=_c;
-},setMilliseconds:function(_e){
-while(_e>=1000){
-this.setSeconds++;
-if(this.setSeconds>=60){
-this._minutes++;
-this.setSeconds-=60;
-if(this._minutes>=60){
-this._hours++;
-this._minutes-=60;
-if(this._hours>=24){
-this._date++;
-this._hours-=24;
-var _f=this.getDaysInIslamicMonth(this._month,this._year);
-if(this._date>_f){
-this._month++;
-if(this._month>=12){
-this._year++;
-this._month-=12;
-}
-this._date-=_f;
-}
-}
-}
-}
-_e-=1000;
-}
-this._milliseconds=_e;
-},toString:function(){
-var x=new Date();
-x.setHours(this._hours);
-x.setMinutes(this._minutes);
-x.setSeconds(this._seconds);
-x.setMilliseconds(this._milliseconds);
-return (this._month+" "+this._date+" "+this._year+" "+x.toTimeString());
-},toGregorian:function(){
-var _10=this._year;
-var _11=this._month;
-var _12=this._date;
-var _13=_12+Math.ceil(29.5*_11)+(_10-1)*354+Math.floor((3+(11*_10))/30)+this._ISLAMIC_EPOCH-1;
-var wjd=Math.floor(_13-0.5)+0.5,_14=wjd-this._GREGORIAN_EPOCH,_15=Math.floor(_14/146097),dqc=this._mod(_14,146097),_16=Math.floor(dqc/36524),_17=this._mod(dqc,36524),_18=Math.floor(_17/1461),_19=this._mod(_17,1461),_1a=Math.floor(_19/365),_1b=(_15*400)+(_16*100)+(_18*4)+_1a;
-if(!(_16==4||_1a==4)){
-_1b++;
-}
-var _1c=this._GREGORIAN_EPOCH+(365*(_1b-1))+Math.floor((_1b-1)/4)-(Math.floor((_1b-1)/100))+Math.floor((_1b-1)/400);
-var _1d=wjd-_1c;
-var tjd=(this._GREGORIAN_EPOCH-1)+(365*(_1b-1))+Math.floor((_1b-1)/4)-(Math.floor((_1b-1)/100))+Math.floor((_1b-1)/400)+Math.floor((739/12)+((dojo.date.isLeapYear(new Date(_1b,3,1))?-1:-2))+1);
-var _1e=((wjd<tjd)?0:(dojo.date.isLeapYear(new Date(_1b,3,1))?1:2));
-var _1f=Math.floor((((_1d+_1e)*12)+373)/367);
-var _20=(this._GREGORIAN_EPOCH-1)+(365*(_1b-1))+Math.floor((_1b-1)/4)-(Math.floor((_1b-1)/100))+Math.floor((_1b-1)/400)+Math.floor((((367*_1f)-362)/12)+((_1f<=2)?0:(dojo.date.isLeapYear(new Date(_1b,_1f,1))?-1:-2))+1);
-var day=(wjd-_20);
-var _21=new Date(_1b,_1f-1,day);
-_21.setHours(this._hours);
-_21.setMilliseconds(this._milliseconds);
-_21.setMinutes(this._minutes);
-_21.setSeconds(this._seconds);
-return _21;
-},fromGregorian:function(_22){
-var _23=new Date(_22);
-var _24=_23.getFullYear(),_25=_23.getMonth(),_26=_23.getDate();
-var _27=(this._GREGORIAN_EPOCH-1)+(365*(_24-1))+Math.floor((_24-1)/4)+(-Math.floor((_24-1)/100))+Math.floor((_24-1)/400)+Math.floor((((367*(_25+1))-362)/12)+(((_25+1)<=2)?0:(dojo.date.isLeapYear(_23)?-1:-2))+_26)+(Math.floor(_23.getSeconds()+60*(_23.getMinutes()+60*_23.getHours())+0.5)/86400);
-_27=Math.floor(_27)+0.5;
-var _28=_27-1948440;
-var _29=Math.floor((30*_28+10646)/10631);
-var _2a=Math.ceil((_28-29-this._yearStart(_29))/29.5);
-_2a=Math.min(_2a,11);
-var _2b=Math.ceil(_28-this._monthStart(_29,_2a))+1;
-this._date=_2b;
-this._month=_2a;
-this._year=_29;
-this._hours=_23.getHours();
-this._minutes=_23.getMinutes();
-this._seconds=_23.getSeconds();
-this._milliseconds=_23.getMilliseconds();
-this._day=_23.getDay();
-return this;
-},valueOf:function(){
-return this.toGregorian().valueOf();
-},_yearStart:function(_2c){
-return (_2c-1)*354+Math.floor((3+11*_2c)/30);
-},_monthStart:function(_2d,_2e){
-return Math.ceil(29.5*_2e)+(_2d-1)*354+Math.floor((3+11*_2d)/30);
-},_civilLeapYear:function(_2f){
-return (14+11*_2f)%30<11;
-},getDaysInIslamicMonth:function(_30,_31){
-var _32=0;
-_32=29+((_30+1)%2);
-if(_30==11&&this._civilLeapYear(_31)){
-_32++;
-}
-return _32;
-},_mod:function(a,b){
-return a-(b*Math.floor(a/b));
-}});
-dojox.date.islamic.Date.getDaysInIslamicMonth=function(_33){
-return new dojox.date.islamic.Date().getDaysInIslamicMonth(_33.getMonth(),_33.getFullYear());
+dojo.requireLocalization("dojo.cldr", "islamic");
+
+dojo.declare("dojox.date.islamic.Date", null, {
+	// summary: The component defines the Islamic (Hijri) Calendar Object
+	//
+	// description:
+	//	This module is similar to the Date() object provided by JavaScript
+	//
+	// example:
+	// |	dojo.require("dojox.date.islamic.Date"); 
+	// |		
+	// |	var date = new dojox.date.islamic.Date();
+	// |	document.writeln(date.getFullYear()+'\'+date.getMonth()+'\'+date.getDate());
+
+
+	_date: 0,
+	_month: 0,
+	_year: 0,
+	_hours: 0,
+	_minutes: 0,
+	_seconds: 0,
+	_milliseconds: 0,
+	_day: 0,
+	_GREGORIAN_EPOCH : 1721425.5,
+	_ISLAMIC_EPOCH : 1948439.5,
+
+	constructor: function(){
+		// summary: This is the constructor
+		// description:
+		//	This function initialize the date object values
+		//
+		// example:
+		// |		var date1 = new dojox.date.islamic.Date();
+		// |
+		// |		var date2 = new dojox.date.islamic.Date("12\2\1429");
+		// |
+		// |		var date3 = new dojox.date.islamic.Date(date2);
+		// |
+		// |		var date4 = new dojox.date.islamic.Date(1429,2,12);
+
+		var len = arguments.length;
+		if(!len){// use the current date value, added "" to the similarity to date
+			this.fromGregorian(new Date());
+		}else if(len == 1){
+			var arg0 = arguments[0];
+			if(typeof arg0 == "number"){ // this is time "valueof"
+				arg0 = new Date(arg0);
+			}
+
+			if(arg0 instanceof Date){
+				this.fromGregorian(arg0);
+			}else if(arg0 == ""){
+				// date should be invalid.  Dijit relies on this behavior.
+				this._date = new Date(""); //TODO: should this be NaN?  _date is not a Date object
+			}else{  // this is Islamic.Date object
+				this._year = arg0._year;
+				this._month =  arg0._month;  
+				this._date = arg0._date;
+				this._hours = arg0._hours;
+				this._minutes = arg0._minutes;
+				this._seconds = arg0._seconds;
+				this._milliseconds = arg0._milliseconds; 
+			}	
+		}else if(len >=3){
+			// YYYY MM DD arguments passed, month is from 0-12
+			this._year += arguments[0];
+			this._month += arguments[1];
+			this._date += arguments[2];
+			this._hours += arguments[3] || 0;
+			this._minutes += arguments[4] || 0;
+			this._seconds += arguments[5] || 0;
+			this._milliseconds += arguments[6] || 0;
+		}
+	},
+
+	getDate:function(){
+		// summary: This function returns the date value (1 - 30)
+		//
+		// example:
+		// |		var date1 = new dojox.date.islamic.Date();
+		// |
+		// |		document.writeln(date1.getDate);		
+		return this._date;
+	},
+	
+	getMonth:function(){
+		// summary: This function return the month value ( 0 - 11 )
+		//
+		// example:
+		// |		var date1 = new dojox.date.islamic.Date();
+		// |
+		// |		document.writeln(date1.getMonth()+1);
+
+		return this._month;
+	},
+
+	getFullYear:function(){
+		// summary: This function return the Year value 
+		//
+		// example:
+		// |		var date1 = new dojox.date.islamic.Date();
+		// |
+		// |		document.writeln(date1.getFullYear());
+
+		return this._year;
+	},
+		
+	getDay:function(){
+		// summary: This function return Week Day value ( 0 - 6 )
+		//
+		// example:
+		// |		var date1 = new dojox.date.islamic.Date();
+		// |
+		// |		document.writeln(date1.getDay());
+
+		return this.toGregorian().getDay();
+	},
+		
+	getHours:function(){
+		//summary: returns the Hour value
+		return this._hours;
+	},
+	
+	getMinutes:function(){
+		//summary: returns the Minuites value
+		return this._minutes;
+	},
+
+	getSeconds:function(){
+		//summary: returns the seconde value
+		return this._seconds;
+	},
+
+	getMilliseconds:function(){
+		//summary: returns the Milliseconds value
+		return this._milliseconds;
+	},
+
+	setDate: function(/*number*/date){	
+		// summary: This function sets the Date
+		// example:
+		// |		var date1 = new dojox.date.islamic.Date();
+		// |		date1.setDate(2);
+
+		date = parseInt(date);
+
+		if(date > 0 && date <= this.getDaysInIslamicMonth(this._month, this._year)){
+			this._date = date;
+		}else{
+			var mdays;
+			if(date>0){
+				for(mdays = this.getDaysInIslamicMonth(this._month, this._year);	
+					date > mdays; 
+						date -= mdays,mdays =this.getDaysInIslamicMonth(this._month, this._year)){
+					this._month++;
+					if(this._month >= 12){this._year++; this._month -= 12;}
+				}
+
+				this._date = date;
+			}else{
+				for(mdays = this.getDaysInIslamicMonth((this._month-1)>=0 ?(this._month-1) :11 ,((this._month-1)>=0)? this._year: this._year-1);	
+						date <= 0; 
+							mdays = this.getDaysInIslamicMonth((this._month-1)>=0 ? (this._month-1) :11,((this._month-1)>=0)? this._year: this._year-1)){
+					this._month--;
+					if(this._month < 0){this._year--; this._month += 12;}
+
+					date+=mdays;
+				}
+				this._date = date;
+			}
+		}
+		return this;
+	},
+
+	setFullYear:function(/*number*/year){
+		// summary: This function set Year
+		//
+		// example:
+		// |		var date1 = new dojox.date.islamic.Date();
+		// |		date1.setYear(1429);
+
+		this._year = +year;
+	},
+
+	setMonth: function(/*number*/month) {
+		// summary: This function set Month
+		//
+		// example:
+		// |		var date1 = new dojox.date.islamic.Date();
+		// |		date1.setMonth(2);
+
+		this._year += Math.floor(month / 12);
+		if(month > 0){
+			this._month = Math.floor(month % 12);
+		}else{
+			this._month = Math.floor(((month % 12) + 12) % 12);
+		}
+	},
+
+	setHours:function(){
+		//summary: set the Hours
+		var hours_arg_no = arguments.length;
+		var hours = 0;
+		if(hours_arg_no >= 1){
+			hours = parseInt(arguments[0]);
+		}
+
+		if(hours_arg_no >= 2){
+			this._minutes = parseInt(arguments[1]);
+		}
+
+		if(hours_arg_no >= 3){
+			this._seconds = parseInt(arguments[2]);
+		}
+
+		if(hours_arg_no == 4){
+			this._milliseconds = parseInt(arguments[3]);
+		}
+
+		while(hours >= 24){
+			this._date++;
+			var mdays = this.getDaysInIslamicMonth(this._month, this._year);
+			if(this._date > mdays){
+					this._month ++;
+					if(this._month >= 12){this._year++; this._month -= 12;}
+					this._date -= mdays;
+			}
+			hours -= 24;
+		}
+		this._hours = hours;
+	},
+
+	setMinutes:function(/*number*/minutes){
+		//summary: set the Minutes
+
+		while(minutes >= 60){
+			this._hours++;
+			if(this._hours >= 24){		 
+				this._date++;
+				this._hours -= 24;
+				var mdays = this.getDaysInIslamicMonth(this._month, this._year);
+				if(this._date > mdays){
+						this._month ++;
+						if(this._month >= 12){this._year++; this._month -= 12;}
+						this._date -= mdays;
+				}
+			}
+			minutes -= 60;
+		}
+		this._minutes = minutes;
+	},
+		
+		
+	setSeconds:function(/*number*/seconds){
+		//summary: set Seconds
+		while(seconds >= 60){
+			this._minutes++;
+			if(this._minutes >= 60){
+				this._hours++;
+				this._minutes -= 60;
+				if(this._hours >= 24){		 
+					this._date++;
+					this._hours -= 24;
+					var mdays = this.getDaysInIslamicMonth(this._month, this._year);
+					if(this._date > mdays){
+						this._month ++;
+						if(this._month >= 12){this._year++; this._month -= 12;}
+						this._date -= mdays;
+					}
+				}
+			}
+			seconds -= 60;
+		}
+		this._seconds = seconds;
+	},
+		
+	setMilliseconds:function(/*number*/milliseconds){
+		//summary: set the Millisconds
+		while(milliseconds >= 1000){
+			this.setSeconds++;
+			if(this.setSeconds >= 60){
+				this._minutes++;
+				this.setSeconds -= 60;
+				if(this._minutes >= 60){
+					this._hours++;
+					this._minutes -= 60;
+					if(this._hours >= 24){		 
+						this._date++;
+						this._hours -= 24;
+						var mdays = this.getDaysInIslamicMonth(this._month, this._year);
+				if(this._date > mdays){
+					this._month ++;
+					if(this._month >= 12){this._year++; this._month -= 12;}
+					this._date -= mdays;
+					}
+				}
+			}
+		}
+			milliseconds -= 1000;
+		}
+		this._milliseconds = milliseconds;
+	},
+		
+		
+	toString:function(){ 
+		// summary: This returns a string representation of the date in "DDDD MMMM DD YYYY HH:MM:SS" format
+		// example:
+		// |		var date1 = new dojox.date.islamic.Date();
+		// |		document.writeln(date1.toString());
+
+		//FIXME: TZ/DST issues?
+		var x = new Date();
+		x.setHours(this._hours);
+		x.setMinutes(this._minutes);
+		x.setSeconds(this._seconds);
+		x.setMilliseconds(this._milliseconds);
+		return this._month+" "+ this._date + " " + this._year + " " + x.toTimeString();
+	},
+		
+		
+	toGregorian:function(){
+		// summary: This returns the equevalent Grogorian date value in Date object
+		// example:
+		// |		var dateIslamic = new dojox.date.islamic.Date(1429,11,20);
+		// |		var dateGregorian = dateIslamic.toGregorian();
+
+		var hYear = this._year;
+		var hMonth = this._month;
+		var hDate = this._date;
+		var julianDay = hDate + Math.ceil(29.5 * hMonth) + (hYear - 1) * 354 
+						+ Math.floor((3 + (11 * hYear)) / 30) + this._ISLAMIC_EPOCH - 1;
+
+		var wjd = Math.floor(julianDay - 0.5) + 0.5,
+			depoch = wjd - this._GREGORIAN_EPOCH,
+			quadricent = Math.floor(depoch / 146097),
+			dqc = this._mod(depoch, 146097),
+			cent = Math.floor(dqc / 36524),
+			dcent = this._mod(dqc, 36524),
+			quad = Math.floor(dcent / 1461),
+			dquad = this._mod(dcent, 1461),
+			yindex = Math.floor(dquad / 365),
+			year = (quadricent * 400) + (cent * 100) + (quad * 4) + yindex;
+		if(!(cent == 4 || yindex == 4)){
+			year++;
+		}
+		
+		var gYearStart = this._GREGORIAN_EPOCH + (365 * (year - 1)) + Math.floor((year - 1) / 4) 
+						- ( Math.floor((year - 1) / 100)) + Math.floor((year - 1) / 400);
+						
+		var yearday = wjd - gYearStart;
+		
+		var tjd = (this._GREGORIAN_EPOCH - 1) + (365 * (year - 1)) + Math.floor((year - 1) / 4) 
+				-( Math.floor((year - 1) / 100)) + Math.floor((year - 1) / 400) + Math.floor( (739 / 12) 
+				+ ( (dojo.date.isLeapYear(new Date(year,3,1)) ? -1 : -2)) + 1);
+			
+		var leapadj = ((wjd < tjd ) ? 0 : (dojo.date.isLeapYear(new Date(year,3,1)) ? 1 : 2));
+					
+		var month = Math.floor((((yearday + leapadj) * 12) + 373) / 367);
+		var tjd2 = (this._GREGORIAN_EPOCH - 1) + (365 * (year - 1)) 
+					+ Math.floor((year - 1) / 4) - (Math.floor((year - 1) / 100)) 
+					+ Math.floor((year - 1) / 400) + Math.floor((((367 * month) - 362) / 12) 
+					+ ((month <= 2) ? 0 : (dojo.date.isLeapYear(new Date(year,month,1)) ? -1 : -2)) + 1);
+					
+		var day = (wjd - tjd2) + 1;
+
+		var gdate = new Date(year, (month - 1), day, this._hours, this._minutes, this._seconds, this._milliseconds);
+
+		return gdate;
+	},
+
+	//TODO: would it make more sense to make this a constructor option? or a static?
+	// ported from the Java class com.ibm.icu.util.IslamicCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
+	fromGregorian:function(/*Date*/gdate){
+		// summary: This function returns the equivalent Islamic Date value for the Gregorian Date
+		// example:
+		// |		var dateIslamic = new dojox.date.islamic.Date();
+		// |		var dateGregorian = new Date(2008,10,12);
+		// |		dateIslamic.fromGregorian(dateGregorian);
+
+		var date = new Date(gdate);
+		var gYear = date.getFullYear(),
+			gMonth = date.getMonth(),
+			gDay = date.getDate();
+		
+		var julianDay = (this._GREGORIAN_EPOCH - 1) + (365 * (gYear - 1)) + Math.floor((gYear - 1) / 4)
+					+ (-Math.floor((gYear - 1) / 100)) + Math.floor((gYear - 1) / 400)
+					+ Math.floor((((367 * (gMonth+1)) - 362) / 12)
+					+ (((gMonth+1) <= 2) ? 0 : (dojo.date.isLeapYear(date) ? -1 : -2)) + gDay) 
+					+(Math.floor(date.getSeconds() + 60 * (date.getMinutes() + 60 * date.getHours()) + 0.5) / 86400.0);
+		julianDay = Math.floor(julianDay) + 0.5;
+
+		var days = julianDay - this._ISLAMIC_EPOCH;
+		var hYear  = Math.floor( (30 * days + 10646) / 10631.0 );
+		var hMonth = Math.ceil((days - 29 - this._yearStart(hYear)) / 29.5 );
+		hMonth = Math.min(hMonth, 11);
+		var hDay = Math.ceil(days - this._monthStart(hYear, hMonth)) + 1;
+
+		this._date = hDay;
+		this._month = hMonth;
+		this._year = hYear;
+		this._hours = date.getHours();
+		this._minutes = date.getMinutes();
+		this._seconds = date.getSeconds();
+		this._milliseconds = date.getMilliseconds();
+		this._day = date.getDay();
+		return this;
+	},
+	
+	valueOf:function(){
+		// summary: This function returns The stored time value in milliseconds 
+		// since midnight, January 1, 1970 UTC
+
+		return this.toGregorian().valueOf();
+	},
+
+	// ported from the Java class com.ibm.icu.util.IslamicCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
+	_yearStart:function(/*Number*/year){
+		//summary: return start of Islamic year
+		return (year-1)*354 + Math.floor((3+11*year)/30.0);
+	},
+
+	// ported from the Java class com.ibm.icu.util.IslamicCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
+	_monthStart:function(/*Number*/year, /*Number*/month){
+		//summary: return the start of Islamic Month
+		return Math.ceil(29.5*month) +
+			(year-1)*354 + Math.floor((3+11*year)/30.0);
+	},
+
+	// ported from the Java class com.ibm.icu.util.IslamicCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
+	_civilLeapYear:function(/*Number*/year){
+		//summary: return Boolean value if Islamic leap year
+		return (14 + 11 * year) % 30 < 11;
+	},
+
+	// ported from the Java class com.ibm.icu.util.IslamicCalendar from ICU4J v3.6.1 at http://www.icu-project.org/
+	getDaysInIslamicMonth:function(/*Number*/month, /*Number*/ year){
+		//summary: returns the number of days in the given Islamic Month
+		var length = 0;
+		length = 29 + ((month+1) % 2);
+		if(month == 11 && this._civilLeapYear(year)){
+			length++;
+		}
+		return length;
+	},
+
+	_mod:function(a, b){
+		return a - (b * Math.floor(a / b));
+	}
+});
+
+//TODOC
+dojox.date.islamic.Date.getDaysInIslamicMonth = function(/*dojox.date.islamic.Date*/month){
+	return new dojox.date.islamic.Date().getDaysInIslamicMonth(month.getMonth(),month.getFullYear()); // dojox.date.islamic.Date
 };
-}
diff --git a/dojox/date/islamic/locale.js b/dojox/date/islamic/locale.js
index 7b17742..7d2e578 100644
--- a/dojox/date/islamic/locale.js
+++ b/dojox/date/islamic/locale.js
@@ -1,374 +1,425 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.islamic.locale"]){
-dojo._hasResource["dojox.date.islamic.locale"]=true;
 dojo.provide("dojox.date.islamic.locale");
-dojo.experimental("dojox.date.islamic.locale");
+
 dojo.require("dojox.date.islamic.Date");
 dojo.require("dojo.regexp");
 dojo.require("dojo.string");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojo.cldr","islamic",null,"ROOT,ar,he");
+dojo.require("dojo.date");
+
+dojo.requireLocalization("dojo.cldr", "islamic");
+
 (function(){
-function _1(_2,_3,_4,_5,_6){
-return _6.replace(/([a-z])\1*/ig,function(_7){
-var s,_8;
-var c=_7.charAt(0);
-var l=_7.length;
-var _9=["abbr","wide","narrow"];
-switch(c){
-case "G":
-s=_3["eraAbbr"][0];
-break;
-case "y":
-s=String(_2.getFullYear());
-break;
-case "M":
-var m=_2.getMonth();
-if(l<3){
-s=m+1;
-_8=true;
-}else{
-var _a=["months","format",_9[l-3]].join("-");
-s=_3[_a][m];
-}
-break;
-case "d":
-s=_2.getDate(true);
-_8=true;
-break;
-case "E":
-var d=_2.getDay();
-if(l<3){
-s=d+1;
-_8=true;
-}else{
-var _b=["days","format",_9[l-3]].join("-");
-s=_3[_b][d];
-}
-break;
-case "a":
-var _c=(_2.getHours()<12)?"am":"pm";
-s=_3[_c];
-break;
-case "h":
-case "H":
-case "K":
-case "k":
-var h=_2.getHours();
-switch(c){
-case "h":
-s=(h%12)||12;
-break;
-case "H":
-s=h;
-break;
-case "K":
-s=(h%12);
-break;
-case "k":
-s=h||24;
-break;
-}
-_8=true;
-break;
-case "m":
-s=_2.getMinutes();
-_8=true;
-break;
-case "s":
-s=_2.getSeconds();
-_8=true;
-break;
-case "S":
-s=Math.round(_2.getMilliseconds()*Math.pow(10,l-3));
-_8=true;
-break;
-default:
-throw new Error("dojox.date.islamic.locale.formatPattern: invalid pattern char: "+_6);
-}
-if(_8){
-s=dojo.string.pad(s,l);
-}
-return s;
-});
-};
-dojox.date.islamic.locale.format=function(_d,_e){
-_e=_e||{};
-var _f=dojo.i18n.normalizeLocale(_e.locale);
-var _10=_e.formatLength||"short";
-var _11=dojox.date.islamic.locale._getIslamicBundle(_f);
-var str=[];
-var _12=dojo.hitch(this,_1,_d,_11,_f,_e.fullYear);
-if(_e.selector=="year"){
-var _13=_d.getFullYear();
-return _13;
-}
-if(_e.selector!="time"){
-var _14=_e.datePattern||_11["dateFormat-"+_10];
-if(_14){
-str.push(_15(_14,_12));
-}
-}
-if(_e.selector!="date"){
-var _16=_e.timePattern||_11["timeFormat-"+_10];
-if(_16){
-str.push(_15(_16,_12));
-}
-}
-var _17=str.join(" ");
-return _17;
-};
-dojox.date.islamic.locale.regexp=function(_18){
-return dojox.date.islamic.locale._parseInfo(_18).regexp;
-};
-dojox.date.islamic.locale._parseInfo=function(_19){
-_19=_19||{};
-var _1a=dojo.i18n.normalizeLocale(_19.locale);
-var _1b=dojox.date.islamic.locale._getIslamicBundle(_1a);
-var _1c=_19.formatLength||"short";
-var _1d=_19.datePattern||_1b["dateFormat-"+_1c];
-var _1e=_19.timePattern||_1b["timeFormat-"+_1c];
-var _1f;
-if(_19.selector=="date"){
-_1f=_1d;
-}else{
-if(_19.selector=="time"){
-_1f=_1e;
-}else{
-_1f=(typeof (_1e)=="undefined")?_1d:_1d+" "+_1e;
-}
-}
-var _20=[];
-var re=_15(_1f,dojo.hitch(this,_21,_20,_1b,_19));
-return {regexp:re,tokens:_20,bundle:_1b};
-};
-dojox.date.islamic.locale.parse=function(_22,_23){
-_22=_22.replace(/[\u200E\u200F\u202A-\u202E]/g,"");
-if(!_23){
-_23={};
-}
-var _24=dojox.date.islamic.locale._parseInfo(_23);
-var _25=_24.tokens,_26=_24.bundle;
-var re=new RegExp("^"+_24.regexp+"$");
-var _27=re.exec(_22);
-var _28=dojo.i18n.normalizeLocale(_23.locale);
-if(!_27){
-return null;
-}
-var _29,_2a;
-var _2b=[1389,0,1,0,0,0,0];
-var _2c="";
-var _2d=0;
-var _2e=["abbr","wide","narrow"];
-var _2f=dojo.every(_27,function(v,i){
-if(!i){
-return true;
-}
-var _30=_25[i-1];
-var l=_30.length;
-switch(_30.charAt(0)){
-case "y":
-_2b[0]=Number(v);
-break;
-case "M":
-if(l>2){
-var _31=_26["months-format-"+_2e[l-3]].concat();
-if(!_23.strict){
-v=v.replace(".","").toLowerCase();
-_31=dojo.map(_31,function(s){
-return s?s.replace(".","").toLowerCase():s;
-});
-}
-v=dojo.indexOf(_31,v);
-if(v==-1){
-return false;
-}
-_2d=l;
-}else{
-v--;
-}
-_2b[1]=Number(v);
-break;
-case "D":
-_2b[1]=0;
-case "d":
-_2b[2]=Number(v);
-break;
-case "a":
-var am=_23.am||_26.am;
-var pm=_23.pm||_26.pm;
-if(!_23.strict){
-var _32=/\./g;
-v=v.replace(_32,"").toLowerCase();
-am=am.replace(_32,"").toLowerCase();
-pm=pm.replace(_32,"").toLowerCase();
-}
-if(_23.strict&&v!=am&&v!=pm){
-return false;
-}
-_2c=(v==pm)?"p":(v==am)?"a":"";
-break;
-case "K":
-if(v==24){
-v=0;
-}
-case "h":
-case "H":
-case "k":
-_2b[3]=Number(v);
-break;
-case "m":
-_2b[4]=Number(v);
-break;
-case "s":
-_2b[5]=Number(v);
-break;
-case "S":
-_2b[6]=Number(v);
-}
-return true;
-});
-var _33=+_2b[3];
-if(_2c==="p"&&_33<12){
-_2b[3]=_33+12;
-}else{
-if(_2c==="a"&&_33==12){
-_2b[3]=0;
-}
-}
-var _34=new dojox.date.islamic.Date(_2b[0],_2b[1],_2b[2],_2b[3],_2b[4],_2b[5],_2b[6]);
-return _34;
+	// Format a pattern without literals
+	function formatPattern(dateObject, bundle, locale, 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["eraAbbr"][0];
+					break;
+				case 'y':
+					s = String(dateObject.getFullYear());
+					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 'd':
+					s = dateObject.getDate(true); 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['dayPeriods-format-wide-' + timePeriod];
+					break;
+				case 'h':
+				case 'H':
+				case 'K':
+				case 'k':
+					var h = dateObject.getHours();
+					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 'z':
+					// We only have one timezone to offer; the one from the browser
+					s = dojo.date.getTimezoneName(dateObject.toGregorian());
+					if(s){ break; }
+					l = 4;
+					// fallthrough... use GMT if tz not available
+				case 'Z':
+					var offset = dateObject.toGregorian().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;
+				default:
+					throw new Error("dojox.date.islamic.locale.formatPattern: invalid pattern char: "+pattern);
+			}
+			if(pad){ s = dojo.string.pad(s, l); }
+			return s;
+		});
+	}	
+	
+// based on and similar to dojo.date.locale.format
+dojox.date.islamic.locale.format = function(/*islamic.Date*/dateObject, /*Object?*/options){
+	// summary:
+	//		Format a Date object as a String, using  settings.
+	options = options || {};
+
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	var formatLength = options.formatLength || 'short';
+	var bundle = dojox.date.islamic.locale._getIslamicBundle(locale);
+	var str = [];
+
+	var sauce = dojo.hitch(this, formatPattern, dateObject, bundle, locale, options.fullYear);
+	if(options.selector == "year"){
+		var year = dateObject.getFullYear();
+		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
+};	
+
+dojox.date.islamic.locale.regexp = function(/*object?*/options){
+	//	based on and similar to dojo.date.locale.regexp	
+	// summary:
+	//		Builds the regular needed to parse a islamic.Date
+	return dojox.date.islamic.locale._parseInfo(options).regexp; // String
 };
-function _15(_35,_36,_37,_38){
-var _39=function(x){
-return x;
+
+dojox.date.islamic.locale._parseInfo = function(/*oblect?*/options){
+/* based on and similar to dojo.date.locale._parseInfo */
+
+	options = options || {};
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	var bundle = dojox.date.islamic.locale._getIslamicBundle(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 = (typeof (timePattern) == "undefined") ? datePattern : datePattern + ' ' + timePattern;
+	}
+
+	var tokens = [];
+	
+	var re = _processPattern(pattern, dojo.hitch(this, _buildDateTimeRE, tokens, bundle, options));
+	return {regexp: re, tokens: tokens, bundle: bundle};
 };
-_36=_36||_39;
-_37=_37||_39;
-_38=_38||_39;
-var _3a=_35.match(/(''|[^'])+/g);
-var _3b=_35.charAt(0)=="'";
-dojo.forEach(_3a,function(_3c,i){
-if(!_3c){
-_3a[i]="";
-}else{
-_3a[i]=(_3b?_37:_36)(_3c);
-_3b=!_3b;
-}
-});
-return _38(_3a.join(""));
+
+
+
+
+dojox.date.islamic.locale.parse= function(/*String*/value, /*Object?*/options){
+	// based on and similar to dojo.date.locale.parse
+	// summary: This function parse string date value according to options	
+	
+	value =  value.replace(/[\u200E\u200F\u202A\u202E]/g, ""); //remove bidi non-printing chars
+
+	if(!options){ options={}; }
+	var info = dojox.date.islamic.locale._parseInfo(options);
+
+	var tokens = info.tokens, bundle = info.bundle;
+	var regexp = info.regexp.replace(/[\u200E\u200F\u202A\u202E]/g, ""); //remove bidi non-printing chars from the pattern
+	var re = new RegExp("^" + regexp + "$");
+
+	var match = re.exec(value);
+
+	var locale = dojo.i18n.normalizeLocale(options.locale); 
+
+	if(!match){ 
+		console.debug("dojox.date.islamic.locale.parse: value  "+value+" doesn't match pattern   " + re);
+		return null;
+	} // null
+	
+	var date, date1;
+	
+	var result = [1389,0,1,0,0,0,0];  //FIXME: islamic date for [1970,0,1,0,0,0,0] used in gregorian locale
+	var amPm = "";
+	var mLength = 0;
+	var widthList = ["abbr", "wide", "narrow"];
+	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':
+				result[0] = Number(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 ? s.replace(".","").toLowerCase() : s; } );
+					}
+					v = dojo.indexOf(months, v);
+					if(v == -1){
+						return false;
+					}
+					mLength = l;
+				}else{
+					v--;				
+				}
+				result[1] = Number(v);
+				break;
+			case 'D':
+				result[1] = 0;
+				// fallthrough...
+			case 'd':
+					result[2] =  Number(v);
+				break;
+			case 'a': //am/pm
+				var am = options.am || bundle['dayPeriods-format-wide-am'],
+					pm = options.pm || bundle['dayPeriods-format-wide-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)
+				//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] = Number(v);
+				break;
+			case 'm': //minutes
+				result[4] = Number(v);
+				break;
+			case 's': //seconds
+				result[5] = Number(v);
+				break; 
+			case 'S': //milliseconds
+				result[6] = Number(v);
+		}
+		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
+	}
+	var dateObject = new dojox.date.islamic.Date(result[0], result[1], result[2], result[3], result[4], result[5], result[6]);
+	return dateObject;
 };
-function _21(_3d,_3e,_3f,_40){
-_40=dojo.regexp.escapeString(_40);
-var _41=dojo.i18n.normalizeLocale(_3f.locale);
-return _40.replace(/([a-z])\1*/ig,function(_42){
-var s;
-var c=_42.charAt(0);
-var l=_42.length;
-var p2="",p3="";
-if(_3f.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+";
-break;
-case "M":
-s=(l>2)?"\\S+":p2+"[1-9]|1[0-2]";
-break;
-case "d":
-s="[12]\\d|"+p2+"[1-9]|3[01]";
-break;
-case "E":
-s="\\S+";
-break;
-case "h":
-s=p2+"[1-9]|1[0-2]";
-break;
-case "k":
-s=p2+"\\d|1[01]";
-break;
-case "H":
-s=p2+"\\d|1\\d|2[0-3]";
-break;
-case "K":
-s=p2+"[1-9]|1\\d|2[0-4]";
-break;
-case "m":
-case "s":
-s=p2+"\\d|[0-5]\\d";
-break;
-case "S":
-s="\\d{"+l+"}";
-break;
-case "a":
-var am=_3f.am||_3e.am||"AM";
-var pm=_3f.pm||_3e.pm||"PM";
-if(_3f.strict){
-s=am+"|"+pm;
-}else{
-s=am+"|"+pm;
-if(am!=am.toLowerCase()){
-s+="|"+am.toLowerCase();
-}
-if(pm!=pm.toLowerCase()){
-s+="|"+pm.toLowerCase();
-}
-}
-break;
-default:
-s=".*";
+
+
+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(''));
 }
-if(_3d){
-_3d.push(_42);
+
+function _buildDateTimeRE  (tokens, bundle, options, pattern){
+		// based on and similar to dojo.date.locale._buildDateTimeRE 
+		//
+	
+	pattern = dojo.regexp.escapeString(pattern); 
+	var locale = dojo.i18n.normalizeLocale(options.locale);
+	
+	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+';
+					break;
+				case 'M':
+					s = (l>2) ?  '\\S+ ?\\S+' : p2+'[1-9]|1[0-2]';
+					break;
+				case 'd':
+					s = '[12]\\d|'+p2+'[1-9]|3[01]';
+					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 = p2+'\\d|[0-5]\\d';
+					break;
+				case 'S':
+					s = '\\d{'+l+'}';
+					break;
+				case 'a':
+					var am = options.am || bundle['dayPeriods-format-wide-am'],
+						pm = options.pm || bundle['dayPeriods-format-wide-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(); }
+					}
+					break;
+				default:
+					s = ".*";
+			}	 
+			if(tokens){ tokens.push(match); }
+			return "(" + s + ")"; // add capture
+		}).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace.  Need explicit handling of \xa0 for IE. */
 }
-return "("+s+")";
-}).replace(/[\xa0 ]/g,"[\\s\\xa0]");
-};
 })();
+
+
+
 (function(){
-var _43=[];
-dojox.date.islamic.locale.addCustomFormats=function(_44,_45){
-_43.push({pkg:_44,name:_45});
+var _customFormats = [];
+dojox.date.islamic.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.
+	_customFormats.push({pkg:packageName,name:bundleName});
 };
-dojox.date.islamic.locale._getIslamicBundle=function(_46){
-var _47={};
-dojo.forEach(_43,function(_48){
-var _49=dojo.i18n.getLocalization(_48.pkg,_48.name,_46);
-_47=dojo.mixin(_47,_49);
-},this);
-return _47;
+
+dojox.date.islamic.locale._getIslamicBundle = function(/*String*/locale){
+	var islamic = {};
+	dojo.forEach(_customFormats, function(desc){
+		var bundle = dojo.i18n.getLocalization(desc.pkg, desc.name, locale);
+		islamic = dojo.mixin(islamic, bundle);
+	}, this);
+	return islamic; /*Object*/
 };
 })();
+
 dojox.date.islamic.locale.addCustomFormats("dojo.cldr","islamic");
-dojox.date.islamic.locale.getNames=function(_4a,_4b,_4c,_4d,_4e){
-var _4f;
-var _50=dojox.date.islamic.locale._getIslamicBundle;
-var _51=[_4a,_4c,_4b];
-if(_4c=="standAlone"){
-var key=_51.join("-");
-_4f=_50(_4d)[key];
-if(_4f===_50("ROOT")[key]){
-_4f=undefined;
-}
-}
-_51[1]="format";
-return (_4f||_50(_4d)[_51.join("-")]).concat();
+
+dojox.date.islamic.locale.getNames = function(/*String*/item, /*String*/type, /*String?*/context, /*String?*/locale, /*islamic Date Object?*/date){
+	// summary:
+	//		Used to get localized strings from dojo.cldr for day or month names.
+	var label;
+	var lookup = dojox.date.islamic.locale._getIslamicBundle;
+	var props = [item, context, type];
+	if(context == 'standAlone'){
+		var key = props.join('-');
+		label = lookup(locale)[key];
+		// Fall back to 'format' flavor of name
+		if(label === lookup("ROOT")[key]){ label = undefined; } // a bit of a 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(locale)[props.join('-')]).concat(); /*Array*/
 };
-dojox.date.islamic.locale.weekDays=dojox.date.islamic.locale.getNames("days","wide","format");
-dojox.date.islamic.locale.months=dojox.date.islamic.locale.getNames("months","wide","format");
-}
+
+
+dojox.date.islamic.locale.weekDays = dojox.date.islamic.locale.getNames('days', 'wide', 'format');
+
+dojox.date.islamic.locale.months = dojox.date.islamic.locale.getNames('months', 'wide', 'format');
diff --git a/dojox/date/php.js b/dojox/date/php.js
index 6b305cb..6f0090f 100644
--- a/dojox/date/php.js
+++ b/dojox/date/php.js
@@ -1,185 +1,308 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.php"]){
-dojo._hasResource["dojox.date.php"]=true;
 dojo.provide("dojox.date.php");
 dojo.require("dojo.date");
 dojo.require("dojox.string.tokenize");
-dojox.date.php.format=function(_1,_2){
-var df=new dojox.date.php.DateFormat(_2);
-return df.format(_1);
-};
-dojox.date.php.DateFormat=function(_3){
-if(!this.regex){
-var _4=[];
-for(var _5 in this.constructor.prototype){
-if(dojo.isString(_5)&&_5.length==1&&dojo.isFunction(this[_5])){
-_4.push(_5);
-}
-}
-this.constructor.prototype.regex=new RegExp("(?:(\\\\.)|(["+_4.join("")+"]))","g");
-}
-var _6=[];
-this.tokens=dojox.string.tokenize(_3,this.regex,function(_7,_8,i){
-if(_8){
-_6.push([i,_8]);
-return _8;
-}
-if(_7){
-return _7.charAt(1);
-}
-});
-this.replacements=_6;
-};
-dojo.extend(dojox.date.php.DateFormat,{weekdays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],weekdays_3:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],months_3:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],monthdays:[31,28,31,30,31,30,31,31,30,31,30,31],format:function(_9){
-this.date=_9;
-for(var i=0,_a;_a=this.replacements[i];i++){
-this.tokens[_a[0]]=this[_a[1]]();
-}
-return this.tokens.join("");
-},d:function(){
-var j=this.j();
-return (j.length==1)?"0"+j:j;
-},D:function(){
-return this.weekdays_3[this.date.getDay()];
-},j:function(){
-return this.date.getDate()+"";
-},l:function(){
-return this.weekdays[this.date.getDay()];
-},N:function(){
-var w=this.w();
-return (!w)?7:w;
-},S:function(){
-switch(this.date.getDate()){
-case 11:
-case 12:
-case 13:
-return "th";
-case 1:
-case 21:
-case 31:
-return "st";
-case 2:
-case 22:
-return "nd";
-case 3:
-case 23:
-return "rd";
-default:
-return "th";
-}
-},w:function(){
-return this.date.getDay()+"";
-},z:function(){
-var _b=this.date.getTime()-new Date(this.date.getFullYear(),0,1).getTime();
-return Math.floor(_b/86400000)+"";
-},W:function(){
-var _c;
-var _d=new Date(this.date.getFullYear(),0,1).getDay()+1;
-var w=this.date.getDay()+1;
-var z=parseInt(this.z());
-if(z<=(8-_d)&&_d>4){
-var _e=new Date(this.date.getFullYear()-1,this.date.getMonth(),this.date.getDate());
-if(_d==5||(_d==6&&dojo.date.isLeapYear(_e))){
-_c=53;
-}else{
-_c=52;
-}
-}else{
-var i;
-if(Boolean(this.L())){
-i=366;
-}else{
-i=365;
-}
-if((i-z)<(4-w)){
-_c=1;
-}else{
-var j=z+(7-w)+(_d-1);
-_c=Math.ceil(j/7);
-if(_d>4){
---_c;
-}
-}
-}
-return _c;
-},F:function(){
-return this.months[this.date.getMonth()];
-},m:function(){
-var n=this.n();
-return (n.length==1)?"0"+n:n;
-},M:function(){
-return this.months_3[this.date.getMonth()];
-},n:function(){
-return this.date.getMonth()+1+"";
-},t:function(){
-return (Boolean(this.L())&&this.date.getMonth()==1)?29:this.monthdays[this.getMonth()];
-},L:function(){
-return (dojo.date.isLeapYear(this.date))?"1":"0";
-},o:function(){
-},Y:function(){
-return this.date.getFullYear()+"";
-},y:function(){
-return this.Y().slice(-2);
-},a:function(){
-return this.date.getHours()>=12?"pm":"am";
-},b:function(){
-return this.a().toUpperCase();
-},B:function(){
-var _f=this.date.getTimezoneOffset()+60;
-var _10=(this.date.getHours()*3600)+(this.date.getMinutes()*60)+this.getSeconds()+(_f*60);
-var _11=Math.abs(Math.floor(_10/86.4)%1000)+"";
-while(_11.length<2){
-_11="0"+_11;
-}
-return _11;
-},g:function(){
-return (this.date.getHours()>12)?this.date.getHours()-12+"":this.date.getHours()+"";
-},G:function(){
-return this.date.getHours()+"";
-},h:function(){
-var g=this.g();
-return (g.length==1)?"0"+g:g;
-},H:function(){
-var G=this.G();
-return (G.length==1)?"0"+G:G;
-},i:function(){
-var _12=this.date.getMinutes()+"";
-return (_12.length==1)?"0"+_12:_12;
-},s:function(){
-var _13=this.date.getSeconds()+"";
-return (_13.length==1)?"0"+_13:_13;
-},e:function(){
-return dojo.date.getTimezoneName(this.date);
-},I:function(){
-},O:function(){
-var off=Math.abs(this.date.getTimezoneOffset());
-var _14=Math.floor(off/60)+"";
-var _15=(off%60)+"";
-if(_14.length==1){
-_14="0"+_14;
-}
-if(_15.length==1){
-_14="0"+_15;
+
+dojox.date.php.format = function(/*Date*/ date, /*String*/ format){
+	// summary: Get a formatted string for a given date object
+	var df = new dojox.date.php.DateFormat(format);
+	return df.format(date);	
 }
-return ((this.date.getTimezoneOffset()<0)?"+":"-")+_14+_15;
-},P:function(){
-var O=this.O();
-return O.substring(0,2)+":"+O.substring(2,4);
-},T:function(){
-return this.e().substring(0,3);
-},Z:function(){
-return this.date.getTimezoneOffset()*-60;
-},c:function(){
-return this.Y()+"-"+this.m()+"-"+this.d()+"T"+this.h()+":"+this.i()+":"+this.s()+this.P();
-},r:function(){
-return this.D()+", "+this.d()+" "+this.M()+" "+this.Y()+" "+this.H()+":"+this.i()+":"+this.s()+" "+this.O();
-},U:function(){
-return Math.floor(this.date.getTime()/1000);
-}});
+
+dojox.date.php.DateFormat = function(/*String*/ format){
+	// summary: Format the internal date object
+	if(!this.regex){
+		var keys = [];
+		for(var key in this.constructor.prototype){
+			if(dojo.isString(key) && key.length == 1 && dojo.isFunction(this[key])){
+				keys.push(key);
+			}
+		}
+		this.constructor.prototype.regex = new RegExp("(?:(\\\\.)|([" + keys.join("") + "]))", "g");
+	}
+
+	var replacements = [];
+
+	this.tokens = dojox.string.tokenize(format, this.regex, function(escape, token, i){
+		if(token){
+			replacements.push([i, token]);
+			return token;
+		}
+		if(escape){
+			return escape.charAt(1);
+		}
+	});
+
+	this.replacements = replacements;
 }
+dojo.extend(dojox.date.php.DateFormat, {
+	weekdays: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+	weekdays_3: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+	months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+	months_3: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+	monthdays: [31,28,31,30,31,30,31,31,30,31,30,31],
+
+	format: function(/*Date*/ date){
+		this.date = date;
+		for(var i = 0, replacement; replacement = this.replacements[i]; i++){
+			this.tokens[replacement[0]] = this[replacement[1]]();
+		}
+		return this.tokens.join("");
+	},
+
+	// Day
+
+	d: function(){
+		// summary: Day of the month, 2 digits with leading zeros
+		var j = this.j();
+		return (j.length == 1) ? "0" + j : j;
+	},
+
+	D: function(){
+		// summary: A textual representation of a day, three letters
+		return this.weekdays_3[this.date.getDay()];
+	},
+
+	j: function(){
+		// summary: Day of the month without leading zeros
+		return this.date.getDate() + "";
+	},
+
+	l: function(){
+		// summary: A full textual representation of the day of the week
+		return this.weekdays[this.date.getDay()];
+	},
+	
+	N: function(){
+		// summary: ISO-8601 numeric representation of the day of the week (added in PHP 5.1.0)
+		var w = this.w();
+		return (!w) ? 7 : w;
+	},
+
+	S: function(){
+		// summary: English ordinal suffix for the day of the month, 2 characters
+		switch(this.date.getDate()){
+			case 11: case 12: case 13: return "th";
+			case 1: case 21: case 31: return "st";
+			case 2: case 22: return "nd";
+			case 3: case 23: return "rd";
+			default: return "th";
+		}
+	},
+
+	w: function(){
+		// summary: Numeric representation of the day of the week
+		return this.date.getDay() + "";
+	},
+
+	z: function(){
+		// summary: The day of the year (starting from 0)
+		var millis = this.date.getTime() - new Date(this.date.getFullYear(), 0, 1).getTime();
+		return Math.floor(millis/86400000) + "";
+	},
+
+	// Week
+
+	W: function(){
+		// summary: ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0)
+		var week;
+		var jan1_w = new Date(this.date.getFullYear(), 0, 1).getDay() + 1;
+		var w = this.date.getDay() + 1;
+		var z = parseInt(this.z());
+
+		if(z <= (8 - jan1_w) && jan1_w > 4){
+			var last_year = new Date(this.date.getFullYear() - 1, this.date.getMonth(), this.date.getDate());
+			if(jan1_w == 5 || (jan1_w == 6 && dojo.date.isLeapYear(last_year))){
+				week = 53;
+			}else{
+				week = 52;
+			}
+		}else{
+			var i;
+			if(Boolean(this.L())){
+				i = 366;
+			}else{
+				i = 365;
+			}
+			if((i - z) < (4 - w)){
+				week = 1;
+			}else{
+				var j = z + (7 - w) + (jan1_w - 1);
+				week = Math.ceil(j / 7);
+				if(jan1_w > 4){
+					--week;
+				}
+			}
+		}
+		
+		return week;
+	},
+
+	// Month
+
+	F: function(){
+		// summary: A full textual representation of a month, such as January or March
+		return this.months[this.date.getMonth()];
+	},
+
+	m: function(){
+		// summary: Numeric representation of a month, with leading zeros
+		var n = this.n();
+		return (n.length == 1) ? "0" + n : n;
+	},
+
+	M: function(){
+		// summary: A short textual representation of a month, three letters
+		return this.months_3[this.date.getMonth()];
+	},
+
+	n: function(){
+		// summary: Numeric representation of a month, without leading zeros
+		return this.date.getMonth() + 1 + "";
+	},
+
+	t: function(){
+		// summary: Number of days in the given month
+		return (Boolean(this.L()) && this.date.getMonth() == 1) ? 29 : this.monthdays[this.getMonth()];
+	},
+
+	// Year
+
+	L: function(){
+		// summary: Whether it's a leap year
+		return (dojo.date.isLeapYear(this.date)) ? "1" : "0";
+	},
+
+	o: function(){
+		// summary:
+		//		ISO-8601 year number. This has the same value as Y, except that if
+		//		the ISO week number (W) belongs to the previous or next year, that year is used instead. (added in PHP 5.1.0)
+		// TODO: Figure out what this means
+	},
+
+	Y: function(){
+		// summary: A full numeric representation of a year, 4 digits
+		return this.date.getFullYear() + "";
+	},
+
+	y: function(){
+		// summary: A two digit representation of a year
+		return this.Y().slice(-2);
+	},
+
+	// Time
+
+	a: function(){
+		// summary: Lowercase Ante meridiem and Post meridiem
+		return this.date.getHours() >= 12 ? "pm" : "am";
+	},
+
+	b: function(){
+		// summary: Uppercase Ante meridiem and Post meridiem
+		return this.a().toUpperCase();
+	},
+
+	B: function(){
+		// summary:
+		//	Swatch Internet time
+		//	A day is 1,000 beats. All time is measured from GMT + 1
+		var off = this.date.getTimezoneOffset() + 60;
+		var secs = (this.date.getHours() * 3600) + (this.date.getMinutes() * 60) + this.getSeconds() + (off * 60);
+		var beat = Math.abs(Math.floor(secs / 86.4) % 1000) + "";
+		while(beat.length <  2) beat = "0" + beat;
+		return beat;
+	},
+
+	g: function(){
+		// summary: 12-hour format of an hour without leading zeros
+		return (this.date.getHours() > 12) ? this.date.getHours() - 12 + "" : this.date.getHours() + "";
+	},
+
+	G: function(){
+		// summary: 24-hour format of an hour without leading zeros
+		return this.date.getHours() + "";
+	},
+
+	h: function(){
+		// summary: 12-hour format of an hour with leading zeros
+		var g = this.g();
+		return (g.length == 1) ? "0" + g : g;
+	},
+
+	H: function(){
+		// summary: 24-hour format of an hour with leading zeros
+		var G = this.G();
+		return (G.length == 1) ? "0" + G : G;
+	},
+
+	i: function(){
+		// summary: Minutes with leading zeros
+		var mins = this.date.getMinutes() + "";
+		return (mins.length == 1) ? "0" + mins : mins;
+	},
+
+	s: function(){
+		// summary: Seconds, with leading zeros
+		var secs = this.date.getSeconds() + "";
+		return (secs.length == 1) ? "0" + secs : secs;
+	},
+
+	// Timezone
+
+	e: function(){
+		// summary: Timezone identifier (added in PHP 5.1.0)
+		return dojo.date.getTimezoneName(this.date);
+	},
+
+	I: function(){
+		// summary: Whether or not the date is in daylight saving time
+		// TODO: Can dojo.date do this?
+	},
+
+	O: function(){
+		// summary: Difference to Greenwich time (GMT) in hours
+		var off = Math.abs(this.date.getTimezoneOffset());
+		var hours = Math.floor(off / 60) + "";
+		var mins = (off % 60) + "";
+		if(hours.length == 1) hours = "0" + hours;
+		if(mins.length == 1) hours = "0" + mins;
+		return ((this.date.getTimezoneOffset() < 0) ? "+" : "-") + hours + mins;
+	},
+
+	P: function(){
+		// summary: Difference to Greenwich time (GMT) with colon between hours and minutes (added in PHP 5.1.3)
+		var O = this.O();
+		return O.substring(0, 2) + ":" + O.substring(2, 4);
+	},
+
+	T: function(){
+		// summary: Timezone abbreviation
+
+		// Guess...
+		return this.e().substring(0, 3);
+	},
+
+	Z: function(){
+		// summary:
+		//		Timezone offset in seconds. The offset for timezones west of UTC is always negative,
+		//		and for those east of UTC is always positive.
+		return this.date.getTimezoneOffset() * -60;
+	},
+
+	// Full Date/Time
+
+	c: function(){
+		// summary: ISO 8601 date (added in PHP 5)
+		return this.Y() + "-" + this.m() + "-" + this.d() + "T" + this.h() + ":" + this.i() + ":" + this.s() + this.P();
+	},
+
+	r: function(){
+		// summary: RFC 2822 formatted date
+		return this.D() + ", " + this.d() + " " + this.M() + " " + this.Y() + " " + this.H() + ":" + this.i() + ":" + this.s() + " " + this.O();
+	},
+
+	U: function(){
+		// summary: Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
+		return Math.floor(this.date.getTime() / 1000);
+	}
+
+});
\ No newline at end of file
diff --git a/dojox/date/posix.js b/dojox/date/posix.js
index 246234c..17c9dbf 100644
--- a/dojox/date/posix.js
+++ b/dojox/date/posix.js
@@ -1,218 +1,289 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.posix"]){
-dojo._hasResource["dojox.date.posix"]=true;
 dojo.provide("dojox.date.posix");
+
 dojo.require("dojo.date");
 dojo.require("dojo.date.locale");
 dojo.require("dojo.string");
-dojox.date.posix.strftime=function(_1,_2,_3){
-var _4=null;
-var _5=function(s,n){
-return dojo.string.pad(s,n||2,_4||"0");
-};
-var _6=dojo.date.locale._getGregorianBundle(_3);
-var $=function(_7){
-switch(_7){
-case "a":
-return dojo.date.locale.getNames("days","abbr","format",_3)[_1.getDay()];
-case "A":
-return dojo.date.locale.getNames("days","wide","format",_3)[_1.getDay()];
-case "b":
-case "h":
-return dojo.date.locale.getNames("months","abbr","format",_3)[_1.getMonth()];
-case "B":
-return dojo.date.locale.getNames("months","wide","format",_3)[_1.getMonth()];
-case "c":
-return dojo.date.locale.format(_1,{formatLength:"full",locale:_3});
-case "C":
-return _5(Math.floor(_1.getFullYear()/100));
-case "d":
-return _5(_1.getDate());
-case "D":
-return $("m")+"/"+$("d")+"/"+$("y");
-case "e":
-if(_4==null){
-_4=" ";
-}
-return _5(_1.getDate());
-case "f":
-if(_4==null){
-_4=" ";
-}
-return _5(_1.getMonth()+1);
-case "g":
-break;
-case "G":
-dojo.unimplemented("unimplemented modifier 'G'");
-break;
-case "F":
-return $("Y")+"-"+$("m")+"-"+$("d");
-case "H":
-return _5(_1.getHours());
-case "I":
-return _5(_1.getHours()%12||12);
-case "j":
-return _5(dojo.date.locale._getDayOfYear(_1),3);
-case "k":
-if(_4==null){
-_4=" ";
-}
-return _5(_1.getHours());
-case "l":
-if(_4==null){
-_4=" ";
-}
-return _5(_1.getHours()%12||12);
-case "m":
-return _5(_1.getMonth()+1);
-case "M":
-return _5(_1.getMinutes());
-case "n":
-return "\n";
-case "p":
-return _6[_1.getHours()<12?"am":"pm"];
-case "r":
-return $("I")+":"+$("M")+":"+$("S")+" "+$("p");
-case "R":
-return $("H")+":"+$("M");
-case "S":
-return _5(_1.getSeconds());
-case "t":
-return "\t";
-case "T":
-return $("H")+":"+$("M")+":"+$("S");
-case "u":
-return String(_1.getDay()||7);
-case "U":
-return _5(dojo.date.locale._getWeekOfYear(_1));
-case "V":
-return _5(dojox.date.posix.getIsoWeekOfYear(_1));
-case "W":
-return _5(dojo.date.locale._getWeekOfYear(_1,1));
-case "w":
-return String(_1.getDay());
-case "x":
-return dojo.date.locale.format(_1,{selector:"date",formatLength:"full",locale:_3});
-case "X":
-return dojo.date.locale.format(_1,{selector:"time",formatLength:"full",locale:_3});
-case "y":
-return _5(_1.getFullYear()%100);
-case "Y":
-return String(_1.getFullYear());
-case "z":
-var _8=_1.getTimezoneOffset();
-return (_8>0?"-":"+")+_5(Math.floor(Math.abs(_8)/60))+":"+_5(Math.abs(_8)%60);
-case "Z":
-return dojo.date.getTimezoneName(_1);
-case "%":
-return "%";
-}
-};
-var _9="";
-var i=0;
-var _a=0;
-var _b=null;
-while((_a=_2.indexOf("%",i))!=-1){
-_9+=_2.substring(i,_a++);
-switch(_2.charAt(_a++)){
-case "_":
-_4=" ";
-break;
-case "-":
-_4="";
-break;
-case "0":
-_4="0";
-break;
-case "^":
-_b="upper";
-break;
-case "*":
-_b="lower";
-break;
-case "#":
-_b="swap";
-break;
-default:
-_4=null;
-_a--;
-break;
-}
-var _c=$(_2.charAt(_a++));
-switch(_b){
-case "upper":
-_c=_c.toUpperCase();
-break;
-case "lower":
-_c=_c.toLowerCase();
-break;
-case "swap":
-var _d=_c.toLowerCase();
-var _e="";
-var ch="";
-for(var j=0;j<_c.length;j++){
-ch=_c.charAt(j);
-_e+=(ch==_d.charAt(j))?ch.toUpperCase():ch.toLowerCase();
-}
-_c=_e;
-break;
-default:
-break;
-}
-_b=null;
-_9+=_c;
-i=_a;
-}
-_9+=_2.substring(i);
-return _9;
-};
-dojox.date.posix.getStartOfWeek=function(_f,_10){
-if(isNaN(_10)){
-_10=dojo.cldr.supplemental.getFirstDayOfWeek?dojo.cldr.supplemental.getFirstDayOfWeek():0;
-}
-var _11=_10;
-if(_f.getDay()>=_10){
-_11-=_f.getDay();
-}else{
-_11-=(7-_f.getDay());
-}
-var _12=new Date(_f);
-_12.setHours(0,0,0,0);
-return dojo.date.add(_12,"day",_11);
+
+dojox.date.posix.strftime = function(/*Date*/dateObject, /*String*/format, /*String?*/locale){
+//
+// summary:
+//		Formats the date object using the specifications of the POSIX strftime function
+//
+// description:
+//		see http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html
+
+	// zero pad
+	var padChar = null;
+	var _ = function(s, n){
+		return dojo.string.pad(s, n || 2, padChar || "0");
+	};
+
+	var bundle = dojo.date.locale._getGregorianBundle(locale);
+
+	var $ = function(property){
+		switch(property){
+			case "a": // abbreviated weekday name according to the current locale
+				return dojo.date.locale.getNames('days', 'abbr', 'format', locale)[dateObject.getDay()];
+
+			case "A": // full weekday name according to the current locale
+				return dojo.date.locale.getNames('days', 'wide', 'format', locale)[dateObject.getDay()];
+
+			case "b":
+			case "h": // abbreviated month name according to the current locale
+				return dojo.date.locale.getNames('months', 'abbr', 'format', locale)[dateObject.getMonth()];
+				
+			case "B": // full month name according to the current locale
+				return dojo.date.locale.getNames('months', 'wide', 'format', locale)[dateObject.getMonth()];
+				
+			case "c": // preferred date and time representation for the current
+				      // locale
+				return dojo.date.locale.format(dateObject, {formatLength: 'full', locale: locale});
+
+			case "C": // century number (the year divided by 100 and truncated
+				      // to an integer, range 00 to 99)
+				return _(Math.floor(dateObject.getFullYear()/100));
+				
+			case "d": // day of the month as a decimal number (range 01 to 31)
+				return _(dateObject.getDate());
+				
+			case "D": // same as %m/%d/%y
+				return $("m") + "/" + $("d") + "/" + $("y");
+					
+			case "e": // day of the month as a decimal number, a single digit is
+				      // preceded by a space (range ' 1' to '31')
+				if(padChar == null){ padChar = " "; }
+				return _(dateObject.getDate());
+			
+			case "f": // month as a decimal number, a single digit is
+							// preceded by a space (range ' 1' to '12')
+				if(padChar == null){ padChar = " "; }
+				return _(dateObject.getMonth()+1);				
+			
+			case "g": // like %G, but without the century.
+				break;
+			
+			case "G": // The 4-digit year corresponding to the ISO week number
+				      // (see %V).  This has the same format and value as %Y,
+				      // except that if the ISO week number belongs to the
+				      // previous or next year, that year is used instead.
+				dojo.unimplemented("unimplemented modifier 'G'");
+				break;
+			
+			case "F": // same as %Y-%m-%d
+				return $("Y") + "-" + $("m") + "-" + $("d");
+				
+			case "H": // hour as a decimal number using a 24-hour clock (range
+				      // 00 to 23)
+				return _(dateObject.getHours());
+				
+			case "I": // hour as a decimal number using a 12-hour clock (range
+				      // 01 to 12)
+				return _(dateObject.getHours() % 12 || 12);
+
+			case "j": // day of the year as a decimal number (range 001 to 366)
+				return _(dojo.date.locale._getDayOfYear(dateObject), 3);
+
+			case "k": // Hour as a decimal number using a 24-hour clock (range
+					  // 0 to 23 (space-padded))
+				if(padChar == null){ padChar = " "; }
+				return _(dateObject.getHours());
+
+			case "l": // Hour as a decimal number using a 12-hour clock (range
+					  // 1 to 12 (space-padded))
+				if(padChar == null){ padChar = " "; }
+				return _(dateObject.getHours() % 12 || 12);
+
+			case "m": // month as a decimal number (range 01 to 12)
+				return _(dateObject.getMonth() + 1);
+
+			case "M": // minute as a decimal number
+				return _(dateObject.getMinutes());
+
+			case "n":
+				return "\n";
+
+			case "p": // either `am' or `pm' according to the given time value,
+				      // or the corresponding strings for the current locale
+				return bundle['dayPeriods-format-wide-' + (dateObject.getHours() < 12 ? "am" : "pm")];
+				
+			case "r": // time in a.m. and p.m. notation
+				return $("I") + ":" + $("M") + ":" + $("S") + " " + $("p");
+				
+			case "R": // time in 24 hour notation
+				return $("H") + ":" + $("M");
+				
+			case "S": // second as a decimal number
+				return _(dateObject.getSeconds());
+
+			case "t":
+				return "\t";
+
+			case "T": // current time, equal to %H:%M:%S
+				return $("H") + ":" + $("M") + ":" + $("S");
+				
+			case "u": // weekday as a decimal number [1,7], with 1 representing
+				      // Monday
+				return String(dateObject.getDay() || 7);
+				
+			case "U": // week number of the current year as a decimal number,
+				      // starting with the first Sunday as the first day of the
+				      // first week
+				return _(dojo.date.locale._getWeekOfYear(dateObject));
+
+			case "V": // week number of the year (Monday as the first day of the
+				      // week) as a decimal number [01,53]. If the week containing
+				      // 1 January has four or more days in the new year, then it 
+				      // is considered week 1. Otherwise, it is the last week of 
+				      // the previous year, and the next week is week 1.
+				return _(dojox.date.posix.getIsoWeekOfYear(dateObject));
+				
+			case "W": // week number of the current year as a decimal number,
+				      // starting with the first Monday as the first day of the
+				      // first week
+				return _(dojo.date.locale._getWeekOfYear(dateObject, 1));
+				
+			case "w": // day of the week as a decimal, Sunday being 0
+				return String(dateObject.getDay());
+
+			case "x": // preferred date representation for the current locale
+				      // without the time
+				return dojo.date.locale.format(dateObject, {selector:'date', formatLength: 'full', locale:locale});
+
+			case "X": // preferred time representation for the current locale
+				      // without the date
+				return dojo.date.locale.format(dateObject, {selector:'time', formatLength: 'full', locale:locale});
+
+			case "y": // year as a decimal number without a century (range 00 to
+				      // 99)
+				return _(dateObject.getFullYear()%100);
+				
+			case "Y": // year as a decimal number including the century
+				return String(dateObject.getFullYear());
+			
+			case "z": // time zone or name or abbreviation
+				var timezoneOffset = dateObject.getTimezoneOffset();
+				return (timezoneOffset > 0 ? "-" : "+") + 
+					_(Math.floor(Math.abs(timezoneOffset)/60)) + ":" +
+					_(Math.abs(timezoneOffset)%60);
+
+			case "Z": // time zone or name or abbreviation
+				return dojo.date.getTimezoneName(dateObject);
+			
+			case "%":
+				return "%";
+		}
+	};
+
+	// parse the formatting string and construct the resulting string
+	var string = "";
+	var i = 0;
+	var index = 0;
+	var switchCase = null;
+	while ((index = format.indexOf("%", i)) != -1){
+		string += format.substring(i, index++);
+		
+		// inspect modifier flag
+		switch (format.charAt(index++)) {
+			case "_": // Pad a numeric result string with spaces.
+				padChar = " "; break;
+			case "-": // Do not pad a numeric result string.
+				padChar = ""; break;
+			case "0": // Pad a numeric result string with zeros.
+				padChar = "0"; break;
+			case "^": // Convert characters in result string to uppercase.
+				switchCase = "upper"; break;
+			case "*": // Convert characters in result string to lowercase
+				switchCase = "lower"; break;
+			case "#": // Swap the case of the result string.
+				switchCase = "swap"; break;
+			default: // no modifier flag so decrement the index
+				padChar = null; index--; break;
+		}
+
+		// toggle case if a flag is set
+		var property = $(format.charAt(index++));
+		switch (switchCase){
+			case "upper":
+				property = property.toUpperCase();
+				break;
+			case "lower":
+				property = property.toLowerCase();
+				break;
+			case "swap": // Upper to lower, and versey-vicea
+				var compareString = property.toLowerCase();
+				var swapString = '';
+				var ch = '';
+				for (var j = 0; j < property.length; j++){
+					ch = property.charAt(j);
+					swapString += (ch == compareString.charAt(j)) ?
+						ch.toUpperCase() : ch.toLowerCase();
+				}
+				property = swapString;
+				break;
+			default:
+				break;
+		}
+		switchCase = null;
+		
+		string += property;
+		i = index;
+	}
+	string += format.substring(i);
+	
+	return string; // String
 };
-dojox.date.posix.setIsoWeekOfYear=function(_13,_14){
-if(!_14){
-return _13;
+
+dojox.date.posix.getStartOfWeek = function(/*Date*/dateObject, /*Number*/firstDay){
+	// summary: Return a date object representing the first day of the given
+	//   date's week.
+	if(isNaN(firstDay)){
+		firstDay = dojo.cldr.supplemental.getFirstDayOfWeek ? dojo.cldr.supplemental.getFirstDayOfWeek() : 0;
+	}
+	var offset = firstDay;
+	if(dateObject.getDay() >= firstDay){
+		offset -= dateObject.getDay();
+	}else{
+		offset -= (7 - dateObject.getDay());
+	}
+	var date = new Date(dateObject);
+	date.setHours(0, 0, 0, 0);
+	return dojo.date.add(date, "day", offset); // Date
 }
-var _15=dojox.date.posix.getIsoWeekOfYear(_13);
-var _16=_14-_15;
-if(_14<0){
-var _17=dojox.date.posix.getIsoWeeksInYear(_13);
-_16=(_17+_14+1)-_15;
+
+dojox.date.posix.setIsoWeekOfYear = function(/*Date*/dateObject, /*Number*/week){
+	// summary: Set the ISO8601 week number of the given date.
+	//   The week containing January 4th is the first week of the year.
+	// week:
+	//   can be positive or negative: -1 is the year's last week.
+	if(!week){ return dateObject; }
+	var currentWeek = dojox.date.posix.getIsoWeekOfYear(dateObject);
+	var offset = week - currentWeek;
+	if(week < 0){
+		var weeks = dojox.date.posix.getIsoWeeksInYear(dateObject);
+		offset = (weeks + week + 1) - currentWeek;
+	}
+	return dojo.date.add(dateObject, "week", offset); // Date
 }
-return dojo.date.add(_13,"week",_16);
-};
-dojox.date.posix.getIsoWeekOfYear=function(_18){
-var _19=dojox.date.posix.getStartOfWeek(_18,1);
-var _1a=new Date(_18.getFullYear(),0,4);
-_1a=dojox.date.posix.getStartOfWeek(_1a,1);
-var _1b=_19.getTime()-_1a.getTime();
-if(_1b<0){
-return dojox.date.posix.getIsoWeeksInYear(_19);
+
+dojox.date.posix.getIsoWeekOfYear = function(/*Date*/dateObject){
+	// summary: Get the ISO8601 week number of the given date.
+	//   The week containing January 4th is the first week of the year.
+	//   See http://en.wikipedia.org/wiki/ISO_week_date
+	var weekStart = dojox.date.posix.getStartOfWeek(dateObject, 1);
+	var yearStart = new Date(dateObject.getFullYear(), 0, 4); // January 4th
+	yearStart = dojox.date.posix.getStartOfWeek(yearStart, 1);
+	var diff = weekStart.getTime() - yearStart.getTime();
+	if(diff < 0){ return dojox.date.posix.getIsoWeeksInYear(weekStart); } // Integer
+	return Math.ceil(diff / 604800000) + 1; // Integer
 }
-return Math.ceil(_1b/604800000)+1;
-};
-dojox.date.posix.getIsoWeeksInYear=function(_1c){
-function p(y){
-return y+Math.floor(y/4)-Math.floor(y/100)+Math.floor(y/400);
-};
-var y=_1c.getFullYear();
-return (p(y)%7==4||p(y-1)%7==3)?53:52;
-};
+
+dojox.date.posix.getIsoWeeksInYear = function(/*Date*/dateObject) {
+	// summary: Determine the number of ISO8601 weeks in the year of the given 
+	//   date. Most years have 52 but some have 53.
+	//   See http://www.phys.uu.nl/~vgent/calendar/isocalendar_text3.htm	
+	function p(y) {
+		return y + Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400);
+	}
+	var y = dateObject.getFullYear();
+	return ( p(y) % 7 == 4 || p(y-1) % 7 == 3 ) ? 53 : 52;	//	Integer
 }
diff --git a/dojox/date/relative.js b/dojox/date/relative.js
index dc9e254..1e3942b 100644
--- a/dojox/date/relative.js
+++ b/dojox/date/relative.js
@@ -1,49 +1,97 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.relative"]){
-dojo._hasResource["dojox.date.relative"]=true;
 dojo.provide("dojox.date.relative");
+
 dojo.require("dojo.date");
 dojo.require("dojo.date.locale");
+
 (function(d){
-var _1=1000*60*60*24;
-var _2=6*_1;
-var _3=d.delegate;
-var _4=d.date.locale;
-var _5=_4._getGregorianBundle;
-var _6=_4.format;
-function _7(_8){
-_8=dojo.clone(_8);
-_8.setHours(0);
-_8.setMinutes(0);
-_8.setSeconds(0);
-_8.setMilliseconds(0);
-return _8;
-};
-dojox.date.relative.format=function(_9,_a){
-_a=_a||{};
-var _b=_7(_a.relativeDate||new Date());
-var _c=_b.getTime()-_7(_9).getTime();
-var _d={locale:_a.locale};
-if(_c===0){
-return _6(_9,_3(_d,{selector:"time"}));
-}else{
-if(_c<=_2&&_c>0&&_a.weekCheck!==false){
-return _6(_9,_3(_d,{selector:"date",datePattern:"EEE"}))+" "+_6(_9,_3(_d,{selector:"time",formatLength:"short"}));
-}else{
-if(_9.getFullYear()==_b.getFullYear()){
-var _e=_5(dojo.i18n.normalizeLocale(_a.locale));
-return _6(_9,_3(_d,{selector:"date",datePattern:_e["dateFormatItem-MMMd"]}));
-}else{
-return _6(_9,_3(_d,{selector:"date",formatLength:"medium",locale:_a.locale}));
-}
-}
+/*=====
+	dojox.date.relative.__FormatOptions = function(){
+	//	locale: String
+	//		override the locale used to determine formatting rules
+	//	relativeDate: Date
+	//		Date to calculate relation to (defaults to new Date())
+	//	weekCheck: boolean
+	//		Whether or not to display the day of week (defaults true)
+		this.locale = locale;
+		this.relativeDate = relativeDate;
+		this.weekCheck = weekCheck;
+	}
+=====*/
+
+var DAY = 1000*60*60*24;
+var SIX_DAYS = 6 * DAY;
+var del = d.delegate;
+var ddl = d.date.locale;
+var ggb = ddl._getGregorianBundle;
+var fmt = ddl.format;
+
+function _clearTime(date){
+	date = dojo.clone(date);
+	date.setHours(0);
+	date.setMinutes(0);
+	date.setSeconds(0);
+	date.setMilliseconds(0);
+	return date;
 }
+
+dojox.date.relative.format = function(/*Date*/dateObject, /*dojox.date.relative.__FormatOptions?*/options){
+	// summary:
+	//		Format a Date object as a String, using locale-specific settings,
+	//		relative to the current date or some other date.
+	//
+	// description:
+	//		Create a string from a Date object using the most significant information
+	//		and a known localized pattern.  This method formats both the date and
+	//		time from dateObject.  Formatting patterns are chosen appropriate to
+	//		the locale.
+	//
+	//		If the day portion of the date falls within the current date (or the
+	//		relativeDate option, if present), then the time will be all that
+	//		is displayed
+	//
+	//		If the day portion of the date falls within the past week (or the
+	//		week preceeding relativeDate, if present), then the display will show
+	//		day of week and time.  This functionality can be turned off by setting
+	//		weekCheck to false.
+	//
+	//		If the year portion of the date falls within the current year (or the
+	//		year portion of relativeDate, if present), then the display will show
+	//		month and day.
+	//
+	//		Otherwise, this function is equivalent to calling dojo.date.format with
+	//		formatLength of "medium"
+	//
+	// dateObject:
+	//		the date and time to be formatted.
+	
+	options = options || {};
+	
+	var today = _clearTime(options.relativeDate || new Date());
+	var diff = today.getTime() - _clearTime(dateObject).getTime();
+	var fmtOpts = {locale: options.locale};
+	
+	if(diff === 0){
+		// today: 9:32 AM
+		return fmt(dateObject, del(fmtOpts, {selector: "time"}));
+	}else if(diff <= SIX_DAYS && diff > 0 && options.weekCheck !== false){
+		// within the last week: Mon 9:32 am
+		return fmt(dateObject, del(fmtOpts, {selector: "date", datePattern: "EEE"})) + 
+				" " +
+				fmt(dateObject, del(fmtOpts, {selector: "time", formatLength: "short"}));
+	}else if(dateObject.getFullYear() == today.getFullYear()){
+		// this year: Nov 1
+		var bundle = ggb(dojo.i18n.normalizeLocale(options.locale));
+		return fmt(dateObject, del(fmtOpts, {
+			selector: "date",
+			datePattern: bundle["dateFormatItem-MMMd"]
+		}));
+	}else{
+		// default: Jun 1, 2010
+		return fmt(dateObject, del(fmtOpts, {
+			selector: "date",
+			formatLength: "medium",
+			locale: options.locale
+		}));
+	}
 };
 })(dojo);
-}
diff --git a/dojox/date/tests/HebrewDateTest1.html b/dojox/date/tests/HebrewDateTest1.html
new file mode 100644
index 0000000..d6fcb7b
--- /dev/null
+++ b/dojox/date/tests/HebrewDateTest1.html
@@ -0,0 +1,175 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+	<head>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="locale: 'he', parseOnLoad: true, isDebug: true, extraLocale: ['he', 'ru']"></script>
+		<script language="javascript" type="text/javascript">
+			dojo.require("dojox.date.hebrew");
+			dojo.require("dojox.date.hebrew.Date");
+			dojo.require("dojox.date.hebrew.locale");
+			dojo.require("dijit.form.Button");
+		</script>
+	</head>
+	<body>
+		Date in Hebrew calendar:
+		   
+		<br>
+		<br>
+		<label for="list_input">Date input Hebrew calendar</label>
+		<input type="text" id="list_input" NAME="list_input" style="width: 400px;">
+			<script type="text/javascript">
+				var date = new dojox.date.hebrew.Date();
+				var year = date.getFullYear();
+				function onButtonClick(){ //from gregorian to hebrew, use pattern
+					var date = new dojox.date.hebrew.Date();
+					var grdate = new Date();
+					var pat = dojo.trim(document.getElementById('Text5').value);
+					var options = {datePattern:pat, selector:'date'};
+					document.getElementById('Text4').value = dojox.date.hebrew.locale.format(date.fromGregorian(grdate), options);
+				}
+				function onButtonClickH(){ //from hebrew, use pattern
+					var str = dojo.trim(document.getElementById('list_input').value);
+					var pattstr = dojo.trim(document.getElementById('Text2').value);
+					// timePattern:'hh:mm:ss'
+					var options = {datePattern:pattstr, selector:'date'};
+					var dateH = dojox.date.hebrew.locale.parse (str,  options);
+					document.getElementById('Text3').value = dateH.toGregorian();
+				}	
+				function ListChange(){
+						var dropdownIndex = document.getElementById('setvaluetest').selectedIndex;
+						var dropdownValue = document.getElementById('setvaluetest')[dropdownIndex].value;
+						document.getElementById('Text2').value = dropdownValue;
+				}			
+			</script>
+		</input>
+		<label for="Text2">Type Pattern for input</label> 
+		<input ID="Text2" NAME="Text2"  ></input>
+		<label for="setvaluetest">Select Pattern for input</label> 
+		<select	id="setvaluetest"
+				name="state1"
+				onChange="ListChange()"
+				>
+			<option VALUE = "d MMMM yyyy" selected >d MMMM yyyy</option>
+			<option VALUE = "EEEE d MMMM yyyy" >EEEE d MMMM yyyy</option>
+			<option VALUE = "dd/MM/yy" >dd/MM/yy</option>
+			<option VALUE = "d MM yy" >d MM yy</option>
+		</select> 
+		<br>
+		<br>
+		<BR>
+		<label for="Text3">Output Gregorian calendar</label> 
+		<input  type="text" ID="Text3" NAME="Text3" style="width: 400px;"></input>
+		<button onclick="onButtonClickH()" type="button" ID="Button3"> Convert from input to Greg</button>
+		<br>
+		///////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+		<br>
+		<br>
+		<label for="Text5">Type Pattern for Hebrew output</label> 
+		<input  type="text" ID="Text5" NAME="Text5"></input>
+		<label for="Select1">Select Pattern for Hebrew output</label> 
+		<select	id="Select1"
+				name="state1"
+				onChange="Change()"
+				>
+			<option VALUE = "d MMMM yyyy" selected>d MMMM yyyy</option>
+			<option VALUE = "EEEE d MMMM yyyy" >EEEE d MMMM yyyy</option>
+			<option VALUE = "dd/MM/yy" >dd/MM/yy</option>
+			<option VALUE = "d MM yy">d MM yy</option>
+				<script type="text/javascript">
+					function Change(){
+						document.getElementById('Text5').value = Select1.options[Select1.selectedIndex].value;
+					}
+				</script>
+		</select> 		
+		<br>
+		<br>
+		<label for="Text4">Output Hebrew calendar</label> 
+		<input  type="text" ID="Text4" NAME="Text4"  style="width: 400px;"></input>
+		<button onclick="onButtonClick()" type="button" ID="Button1"> Convert today from  Gregorian to Hebrew</button>
+		<br>
+		<br>
+		<BR>
+		///////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+		<br>
+		Test add function
+		<br>
+		<br>
+		<br>
+		<label for="Text6">Type amount number</label> 
+		<input  type="text" ID="Text6" NAME="Text5" style="width: 100px;"></input>	 	
+		<label for="Select2">Select  interval</label> 
+		<select	id="Select2"
+				name="state2"
+				>
+			<option VALUE = "day" selected>day</option>
+			<option VALUE = "week" >week</option>
+			<option VALUE = "weekday" >weekday</option>
+			<option VALUE = "month">month</option>
+			<option VALUE = "year">year</option>
+			<option VALUE = "hour">hour</option>
+			<option VALUE = "minute">minute</option>	
+			<option VALUE = "second">second</option>									
+	
+		</select>
+		<button onclick="onButtonClickAdd()" type="button" ID="Button2"> Add</button>
+				
+		<script type="text/javascript">
+			function onButtonClickAdd(){
+				var dateHebrew= new dojox.date.hebrew.Date();
+				var num = parseInt(document.getElementById('Text6').value);
+				var sel = document.getElementById('Select2');
+				var dateHebrewAdd= dojox.date.hebrew.add(dateHebrew, sel.options[sel.selectedIndex].value, num);
+				var options = {datePattern:'EEEE dd MMMM yyyy HH:mm:ss', selector:'date'};
+				document.getElementById('Text7').value	= dojox.date.hebrew.locale.format(dateHebrewAdd,options);
+			}	
+		</script>				
+		<br>		
+		<br>
+		<br>
+		<label for="Text7">Result: added to today</label> 
+		<input  type="text" ID="Text7" NAME="Text7" style="width: 400px;"></input>	
+		<br>
+		<BR>
+		///////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+		<br>
+		Test difference function	
+		<br>
+		<br>
+		<label for="Text8">Type date in format dd MMMM yyyy HH:mm:ss</label> 
+		<input  type="text" ID="Text8" NAME="Text8" style="width: 200px;"></input>	
+		<label for="Text9">Type date in format dd MMMM yyyy HH:mm:ss</label> 
+		<input  type="text" ID="Text9" NAME="Text9" style="width: 200px;"></input>
+		<br>	
+		<label for="Select3">Select  interval</label> 
+		<select	id="Select3"
+				name="state3"
+				>
+			<option VALUE = "day" selected>day</option>
+			<option VALUE = "week" >week</option>
+			<option VALUE = "weekday" >weekday</option>
+			<option VALUE = "month">month</option>
+			<option VALUE = "year">year</option>
+			<option VALUE = "hour">hour</option>
+			<option VALUE = "minute">minute</option>	
+			<option VALUE = "second">second</option>									
+		</select>		
+		<button onclick="onButtonClickDiff()" type="button" ID="Button4"> Diff</button>
+				
+		<script type="text/javascript">
+			function onButtonClickDiff(){
+				var dateHebrew1 = dojox.date.hebrew.locale.parse(dojo.trim(document.getElementById('Text8').value), {datePattern:'dd MMMM yyyy HH:mm:ss', selector:'date'});
+				var dateHebrew2= dojox.date.hebrew.locale.parse(dojo.trim(document.getElementById('Text9').value),  {datePattern:'dd MMMM yyyy HH:mm:ss', selector:'date'});
+				var sel = document.getElementById('Select3');
+				var dif= dojox.date.hebrew.difference(dateHebrew1, dateHebrew2, sel.options[sel.selectedIndex].value);
+				document.getElementById('Text10').value= dif;
+			}	
+		</script>				
+		<br>		
+		<br>
+		<br>
+		<label for="Text10">Result: difference</label> 
+		<input  type="text" ID="Text10" NAME="Text10" style="width: 40px;"></input>	
+		<br>				
+		<br>		 			
+		<P></P>
+	</body>
+</html>
diff --git a/dojox/date/tests/buddhist/Date.js b/dojox/date/tests/buddhist/Date.js
new file mode 100644
index 0000000..ac5a50f
--- /dev/null
+++ b/dojox/date/tests/buddhist/Date.js
@@ -0,0 +1,174 @@
+dojo.provide("dojox.date.tests.buddhist.Date");
+dojo.require("dojox.date.buddhist");
+dojo.require("dojox.date.buddhist.Date");
+dojo.require("dojox.date.buddhist.locale");
+
+dojo.requireLocalization("dojo.cldr", "greg"); 
+dojo.requireLocalization("dojo.cldr", "buddhist");
+
+tests.register("dojox.date.tests.buddhist.Date", 
+	[
+		{
+			// see tests for dojo.date.locale for setup info
+
+			name: "dojox.date.tests.posix",
+			setUp: function(){
+				var partLocaleList = ["th"];
+
+				dojo.forEach(partLocaleList, function(locale){
+					dojo.requireLocalization("dojo.cldr", "greg", locale);
+					dojo.requireLocalization("dojo.cldr", "buddhist", locale);
+				});
+			},
+			runTest: function(t){
+			},
+			tearDown: function(){
+				//Clean up bundles that should not exist if
+				//the test is re-run.
+				delete dojo.cldr.nls.greg;
+				delete dojo.cldr.nls.buddhist;
+			}
+		},	
+		{
+			name: "toGregorian",
+			runTest: function(t){
+				var dateBuddhist = new dojox.date.buddhist.Date(2551, 11, 19); //Buddhist.Date month 0-12
+				var dateGregorian = dateBuddhist.toGregorian();
+				t.is(0, dojo.date.compare(new Date(2008, 11, 19), dateGregorian, "date"));//Date month 0-11
+				
+				dateBuddhist = new dojox.date.buddhist.Date(2548, 3, 18); 
+				dateGregorian = dateBuddhist.toGregorian();
+				t.is(0, dojo.date.compare(new Date(2005, 3, 18), dateGregorian, "date"));
+				
+				dateBuddhist = new dojox.date.buddhist.Date(2550, 7, 10); 
+				dateGregorian = dateBuddhist.toGregorian();
+				t.is(0, dojo.date.compare(new Date(2007, 7, 10), dateGregorian, "date"));
+				
+				dateBuddhist = new dojox.date.buddhist.Date(2552, 4, 20); 
+				dateGregorian = dateBuddhist.toGregorian();
+				t.is(0, dojo.date.compare(new Date(2009, 4, 20), dateGregorian, "date"));
+				
+				dateBuddhist = new dojox.date.buddhist.Date(2553, 6, 31); 
+				dateGregorian = dateBuddhist.toGregorian();
+				t.is(0, dojo.date.compare(new Date(2010, 6, 31), dateGregorian, "date"));
+				
+				dateBuddhist = new dojox.date.buddhist.Date(2554, 9, 1); 
+				dateGregorian = dateBuddhist.toGregorian();
+				t.is(0, dojo.date.compare(new Date(2011, 9, 1), dateGregorian, "date"));				
+			}
+		},
+		{
+			name: "fromGregorian",
+			runTest: function(t){
+				var dateGregorian = new Date(2009, 3, 12);
+				var dateBuddhistFromGreg = new dojox.date.buddhist.Date(dateGregorian);
+				t.is(0, dojo.date.compare( dateBuddhistFromGreg.toGregorian(), dateGregorian, "date"));
+				t.is(0, dojo.date.compare( dateBuddhistFromGreg.toGregorian(), dateGregorian));
+				
+				dateGregorian = new Date(2008, 11, 18);  //Date month 0-11
+				dateBuddhistFromGreg = new dojox.date.buddhist.Date(dateGregorian);
+				t.is(0, dojox.date.buddhist.compare(new dojox.date.buddhist.Date(2551, 11, 18), dateBuddhistFromGreg, "date")); //Buddhist.Date month 0-12
+	
+				dateGregorian = new Date(2005, 3, 18);
+				dateBuddhistFromGreg = new dojox.date.buddhist.Date(dateGregorian);
+				t.is(0, dojox.date.buddhist.compare(new dojox.date.buddhist.Date(2548, 3, 18), dateBuddhistFromGreg, "date"));
+				
+				dateGregorian = new Date(2007, 7, 10);
+				dateBuddhistFromGreg = new dojox.date.buddhist.Date(dateGregorian);
+				t.is(0, dojox.date.buddhist.compare(new dojox.date.buddhist.Date(2550, 7, 10), dateBuddhistFromGreg, "date"));					
+				
+				dateGregorian = new Date(2009, 4, 20);
+				dateBuddhistFromGreg = new dojox.date.buddhist.Date(dateGregorian);
+				t.is(0, dojox.date.buddhist.compare(new dojox.date.buddhist.Date(2552, 4, 20), dateBuddhistFromGreg, "date"));				
+				
+				dateGregorian = new Date(2010, 6, 31);
+				dateBuddhistFromGreg = new dojox.date.buddhist.Date(dateGregorian);
+				t.is(0, dojox.date.buddhist.compare(new dojox.date.buddhist.Date(2553, 6, 31), dateBuddhistFromGreg, "date"));	
+				
+				dateGregorian = new Date(2011, 9, 1);
+				dateBuddhistFromGreg = new dojox.date.buddhist.Date(dateGregorian);
+				t.is(0, dojox.date.buddhist.compare(new dojox.date.buddhist.Date(2554, 9, 1), dateBuddhistFromGreg, "date"));					
+			}
+		},
+		{
+			name: "compare",
+			runTest: function(t){
+				var dateBuddhist = new dojox.date.buddhist.Date(2552, 5, 16);
+				var dateBuddhist1 = new dojox.date.buddhist.Date(2550,  10,  25);
+				t.is(1, dojo.date.compare(dateBuddhist.toGregorian(), dateBuddhist1.toGregorian()));
+				t.is(-1, dojo.date.compare(dateBuddhist1.toGregorian(), dateBuddhist.toGregorian()));
+			}	
+		},		
+		{
+			name: "add_and_difference",
+			runTest: function(t){
+				var dateBuddhist = new dojox.date.buddhist.Date(2552, 5, 16);
+				var dateBuddhistLeap = new dojox.date.buddhist.Date(2551, 5, 16);
+				
+				var dateBuddhistAdd = dojox.date.buddhist.add(dateBuddhist, "month",  18);
+				var dateBuddhistAddLeap = dojox.date.buddhist.add(dateBuddhistLeap, "month",  18);
+				t.is(0, 18 - dojox.date.buddhist.difference(dateBuddhistAdd, dateBuddhist, "month"));
+				t.is(0, 18 - dojox.date.buddhist.difference(dateBuddhistAddLeap, dateBuddhistLeap, "month"));
+				
+				var dateBuddhistAdd1= dojox.date.buddhist.add(dateBuddhist, "year", 2);
+				t.is(0,  2 - dojox.date.buddhist.difference(dateBuddhistAdd1, dateBuddhist, "year"));
+				t.is(0,  2 - dojox.date.buddhist.difference(dojox.date.buddhist.add(dateBuddhistLeap, "year", 2), dateBuddhistLeap, "year"));
+				
+				var dateBuddhistAdd2= dojox.date.buddhist.add(dateBuddhist, "week",  12);
+				t.is(0, 12 - dojox.date.buddhist.difference(dateBuddhistAdd2, dateBuddhist, "week"));
+				t.is(0,  12 - dojox.date.buddhist.difference(dojox.date.buddhist.add(dateBuddhistLeap, "week", 12), dateBuddhistLeap,"week"));
+								
+				var dateBuddhistAdd3= dojox.date.buddhist.add(dateBuddhist, "weekday", 20);
+				t.is(0, 20 - dojox.date.buddhist.difference(dateBuddhistAdd3, dateBuddhist, "weekday")); 
+				t.is(0,  20 - dojox.date.buddhist.difference(dojox.date.buddhist.add(dateBuddhistLeap, "weekday", 20), dateBuddhistLeap,"weekday"));
+				
+				var dateBuddhistAdd4= dojox.date.buddhist.add(dateBuddhist, "day", -50)
+				t.is(0, -50 - dojox.date.buddhist.difference(dateBuddhistAdd4, dateBuddhist, "day")); 
+				t.is(0, -50 - dojox.date.buddhist.difference(dojox.date.buddhist.add(dateBuddhistLeap, "day", -50), dateBuddhistLeap,"day"));
+											
+				var dateBuddhistAdd5= dojox.date.buddhist.add(dateBuddhist, "hour", 200);
+				t.is(0, 200 - dojox.date.buddhist.difference(dateBuddhistAdd5, dateBuddhist, "hour"));  
+				t.is(0, 200 - dojox.date.buddhist.difference(dojox.date.buddhist.add(dateBuddhistLeap, "hour", 200), dateBuddhistLeap,"hour"));
+				
+				var dateBuddhistAdd6= dojox.date.buddhist.add(dateBuddhist, "minute", -200);
+				t.is(0, -200 - dojox.date.buddhist.difference(dateBuddhistAdd6, dateBuddhist, "minute")); 
+				t.is(0, -200 - dojox.date.buddhist.difference(dojox.date.buddhist.add(dateBuddhistLeap, "minute", -200), dateBuddhistLeap,"minute")); 
+				
+				var dateBuddhistDiff = new dojox.date.buddhist.Date(2552, 5, 17);
+				t.is(1, dojox.date.buddhist.difference(dateBuddhistDiff, dateBuddhist)); 
+			}
+		},
+		{
+			name: "parse_and_format",
+			runTest: function(t){
+				var dateBuddhist = new dojox.date.buddhist.Date(2552, 5, 16);
+					
+				var options = {formatLength:'short'};
+				str= dojox.date.buddhist.locale.format(dateBuddhist, options);
+				dateBuddhist1 = dojox.date.buddhist.locale.parse(str, options);
+				t.is(0, dojo.date.compare(dateBuddhist.toGregorian(), dateBuddhist1.toGregorian(), 'date'));
+				
+				var pat = 'dd/MM/yy h:m:s';
+				 options = {datePattern:pat, selector:'date'};
+				 str= dojox.date.buddhist.locale.format(dateBuddhist, options);
+				 dateBuddhist1 = dojox.date.buddhist.locale.parse(str, options);
+				 t.is(0, dojo.date.compare(dateBuddhist.toGregorian(), dateBuddhist1.toGregorian(), 'date'));
+				 
+				pat = 'dd#MM#yy HH$mm$ss';
+				 options = {datePattern:pat, selector:'date'};
+				 str= dojox.date.buddhist.locale.format(dateBuddhist, options);
+				 dateBuddhist1 = dojox.date.buddhist.locale.parse(str, options);
+				  t.is(0, dojo.date.compare(dateBuddhist.toGregorian(), dateBuddhist1.toGregorian(), 'date'));
+				
+				
+				 pat = 'HH$mm$ss';
+				 options = {timePattern:pat, selector:'time'};
+				 str= dojox.date.buddhist.locale.format(dateBuddhist, options);
+				 dateBuddhist1 = dojox.date.buddhist.locale.parse(str, options);
+				gregDate = dojo.date.locale.parse(str, options);
+				t.is(0, dojo.date.compare(gregDate, dateBuddhist1.toGregorian(), 'time'));	
+								 	
+			}		
+		}	
+	]
+);
diff --git a/dojox/date/tests/hebrew/Date.js b/dojox/date/tests/hebrew/Date.js
new file mode 100644
index 0000000..8551e2e
--- /dev/null
+++ b/dojox/date/tests/hebrew/Date.js
@@ -0,0 +1,406 @@
+dojo.provide("dojox.date.tests.hebrew.Date");
+dojo.require("dojox.date.hebrew");
+dojo.require("dojox.date.hebrew.Date");
+dojo.require("dojox.date.hebrew.locale");
+
+dojo.requireLocalization("dojo.cldr", "gregorian"); 
+dojo.requireLocalization("dojo.cldr", "hebrew");
+
+tests.register("dojox.date.tests.hebrew.Date", 
+	[
+		{
+			// see tests for dojo.date.locale for setup info
+
+			name: "dojox.date.tests.posix",
+			setUp: function(){
+				var partLocaleList = ["he", "en"];
+
+				dojo.forEach(partLocaleList, function(locale){
+					dojo.requireLocalization("dojo.cldr", "gregorian", locale);
+					dojo.requireLocalization("dojo.cldr", "hebrew", locale);
+				});
+			},
+			runTest: function(t){
+			},
+			tearDown: function(){
+				//Clean up bundles that should not exist if
+				//the test is re-run.
+				delete dojo.cldr.nls.gregorian;
+				delete dojo.cldr.nls.hebrew;
+			}
+		},
+		{
+			name: "compare",
+			runTest: function(t){
+				var dateHebrew = new dojox.date.hebrew.Date(5769, 5, 16);
+				var dateHebrew1 = new dojox.date.hebrew.Date(5758,  10,  25);
+				t.is(1, dojo.date.compare(dateHebrew.toGregorian(), dateHebrew1.toGregorian()));
+				t.is(-1, dojo.date.compare(dateHebrew1.toGregorian(), dateHebrew.toGregorian()));
+			}	
+		},	
+		{
+			name: "toGregorian_fromGregorian",
+			runTest: function(t){
+			
+			//Hebrew month names
+			var TISHRI = 0 , HESHVAN = 1, KISLEV = 2, TEVET = 3, SHVAT = 4 , ADARI = 5, ADAR = 6, NISAN= 7 , IYAR= 8 , SIVAN= 9 , TAMMUZ = 10, AV = 11 , ELUL = 12;   	
+				//hebrew.Date month names
+				//Gregorian Date month 1-12 -  for readability
+				var dateTable = [
+					[1239, 9, 8,   5000,TISHRI,1],
+					[1240, 9, 25,  5001,TISHRI,1],
+					[1298, 4, 17, 5058, NISAN,  27],
+					[1391, 7, 11, 5151, AV, 1],
+					[1492, 5, 9, 5252, IYAR, 3],
+					[1560, 4, 4, 5320,  ADAR, 27],
+					[1648, 7, 10, 5408, TAMMUZ, 20],
+					[1903, 5, 19, 5663, IYAR, 22],
+					[1929, 9, 24, 5689, ELUL, 19],
+					[1941, 10, 29, 5702, HESHVAN, 8],
+					[1943, 5, 19, 5703, IYAR, 14],
+					[1943, 11, 6, 5704, HESHVAN, 8],
+					[1992, 4, 15, 5752, NISAN, 12],
+					[1996, 3, 25, 5756, NISAN, 5],					
+					[2005, 4, 18, 5765, NISAN, 9],
+					[2007, 7, 12, 5767, TAMMUZ, 26],					
+					[2007, 10, 13, 5768, HESHVAN, 1],
+					[2007, 11, 11, 5768, KISLEV, 1],
+					[2007, 12, 10, 5768, TEVET, 1],
+					[2008, 1, 8, 5768, SHVAT, 1],
+					[2008, 2, 7, 5768, ADARI, 1], 
+					[2008, 3, 8, 5768, ADAR, 1],
+					[2008, 4, 6, 5768, NISAN, 1],
+					[2008, 5, 6, 5768, IYAR, 1],
+					[2008, 6, 4, 5768, SIVAN, 1],
+					[2008, 7, 4, 5768, TAMMUZ, 1],
+					[2008, 8, 2, 5768, AV, 1],
+					[2008, 8, 4, 5768, AV, 3],
+					[2008, 9, 5, 5768, ELUL, 5],
+					[2008, 8, 5, 5768, AV, 4],
+					[2008, 9, 11, 5768, ELUL, 11],
+					[2008, 12, 19,  5769, KISLEV, 22],							
+					[2009, 1, 26, 5769, SHVAT, 1],
+					[2009, 2, 25, 5769, ADARI, 1], //incorrect, not leap year , the month is set to ADAR
+					[2009, 2, 25, 5769, ADAR, 1],
+					[2009, 3, 26, 5769, NISAN, 1],
+					[2009, 5, 24, 5769, SIVAN, 1],
+					[2009, 7, 22, 5769, AV, 1],
+					[2009, 8, 21, 5769, ELUL, 1],
+					[2010, 7, 2, 5770,  TAMMUZ, 20],
+					[2011, 10, 1, 5772, TISHRI, 3],	
+					[2038, 12, 9, 5799, KISLEV, 12],
+					[2094, 8, 17, 5854, ELUL, 5]													
+				];
+
+					
+
+				var dateHebrew, dateGregorian; 
+				//toGregorian
+				dojo.forEach(dateTable, function(d, i){	
+					dateHebrew = new dojox.date.hebrew.Date(d[3], d[4], d[5]); 
+					dateGregorian = dateHebrew.toGregorian();
+					t.is(0, dojo.date.compare(new Date(d[0], d[1]-1, d[2]), dateGregorian, "date"));
+				});
+				
+				//fromGregorian
+				dojo.forEach(dateTable, function(d, i){	
+					dateGregorian = new  Date(d[0], d[1]-1, d[2]);
+					dateHebrew = new dojox.date.hebrew.Date(dateGregorian);
+					testHebrew = new dojox.date.hebrew.Date(d[3], d[4], d[5]);
+					t.is(0, dojo.date.compare(testHebrew.toGregorian() , dateHebrew.toGregorian(),  "date"));
+				});
+			}
+		},
+		{
+			name: "getDay",
+			runTest: function(t){
+				 var dateTable = [
+					[5769, 0, 11, 5], 
+					[5769, 1, 3, 6],
+					[5769, 2, 10, 0],
+					[5769, 3, 23, 1], 
+					[5769, 6, 21, 2], 
+					[5769, 6, 22, 3],
+					[5769, 7, 15, 4]
+				];
+					dojo.forEach(dateTable, function(d, i){	
+					var date = new  dojox.date.hebrew.Date(d[0], d[1], d[2]);
+					t.is(d[3], 	date.getDay());
+				});
+				
+			}
+		},
+		{
+			name: "getDaysInHebrewMonth",
+			runTest: function(t){
+					
+				 var dateTable = [
+					[5768, 1, 29], //HESHVAN
+					[5770, 1, 30], //HESHVAN
+					[5768, 5, 30], //ADARI
+					[5769, 5, 0], //ADARI
+					[5768, 2, 29], //KISLEV,
+					[5769, 2, 30] //KISLEV,
+				];
+				
+				dojo.forEach(dateTable, function(d, i){	
+					var date = new  dojox.date.hebrew.Date(d[0], d[1], 1);
+					t.is(d[2], 	dojox.date.hebrew.getDaysInMonth(date));
+				});
+			}	
+		},
+		{	
+			name: "add_difference",
+			runTest: function(t){
+		//	5766, 5767, 5769, 5770, 5772, 5772, 5773, 5775 - non leap
+		//      5765, 5768, 5771, 5774 - leap
+		
+		//Hebrew month names
+				var TISHRI = 0 , HESHVAN = 1, KISLEV = 2, TEVET = 3, SHVAT = 4 , ADARI = 5, ADAR = 6, NISAN= 7 , IYAR= 8 , SIVAN= 9 , TAMMUZ = 10, AV = 11 , ELUL = 12;   	
+				var start = [
+						[5767, TAMMUZ, 5769, SIVAN],
+						[5767, TAMMUZ, 5772, IYAR],
+						[5767, 0, 5768, TISHRI],
+						[5775, KISLEV, 5773, TEVET],
+						[5767,  TISHRI , 5765, HESHVAN],
+						[5768, TEVET, 5768, ADARI],
+						[5768, IYAR, 5768, ADAR],
+						[5769, TEVET, 5769, ADAR],
+						[5769, IYAR, 5769, SHVAT],
+						[5769, ELUL, 5770, TISHRI],
+						[5769, ELUL, 5769, AV]
+					];
+					var add =[24, 60, 12, -24,-24, 2, -2, 2, -3, 1, -1];
+						
+					var dateHebStart, dateHebEnd, res, dateHebRes;
+					dojo.forEach(start, function(s, i){
+						dateHebStart = new dojox.date.hebrew.Date( s[0], s[1], 1);
+						dateHebRes = dojox.date.hebrew.add(dateHebStart, "month", add[i]);
+
+						t.is(0, dateHebRes.getMonth() - s[3]);
+						t.is(0, dateHebRes.getFullYear() - s[2]);
+					});
+					
+					//month difference
+					dojo.forEach(start, function(s, i){
+						dateHebRes = new dojox.date.hebrew.Date( s[2], s[3], 1);
+						dateHebStart =  new dojox.date.hebrew.Date( s[0], s[1], 1);
+						t.is(add[i], dojox.date.hebrew.difference(dateHebRes,  dateHebStart , "month"));
+					});	
+					
+					//different fields
+					var fields =  [
+								[   5757, TISHRI,    1,     "year",    10,     5767, TISHRI,    1 ],
+								[   5758, KISLEV,   30,      "year",   -1,     5757, KISLEV,   29 ],
+								[   5769, NISAN,   30,      "year",   -1,     5768, NISAN,  30 ],
+								[   5768, ADARI,  30,      "year",   1,     5769, ADAR,  29 ],
+								[   5757, TISHRI,   30,     "month",   1,     5757, HESHVAN,  29 ],								
+								[   5762, AV,       30,      "day",    1,     5762, ELUL,  1 ],   
+								[   5762, ELUL,      1,     "day",   -1,     5762, AV, 30 ],  
+								[   5769,  TAMMUZ,  27,  "day",  10,  5769, AV, 8],
+								[   5757, KISLEV,    1,    "day",   30,     5757, TEVET,    2 ],   // 29-day month
+								[   5758, KISLEV,    1,     "day",   31,     5758, TEVET,    2 ],   // 30-day month								
+								[   5769,  AV,   27,  "day",  10,  5769, ELUL, 7],
+								[   5769,  ELUL,   27,  "day",  10,  5770, TISHRI, 8],
+							        [   5769,  TAMMUZ,  27,  "day",  -30, 5769, SIVAN, 27],
+								[   5769,  AV,   1,  "day",  -60,  5769,	IYAR, 29],	
+								[   5769,  SHVAT, 	30, "day", 1, 	5769, ADAR, 1],															
+								[   5769,  TAMMUZ,  27,  "weekday", 10,  5769, AV, 12],
+								[   5769,  KISLEV,   1,  "weekday", 1, 5769, KISLEV, 3],
+								[   5769,  NISAN,  1,  "weekday",  -5,  5769, ADAR, 23],
+								[   5769,  AV,   7,  "weekday", -10, 5769, TAMMUZ, 22],
+								[   5769,  AV,   12,  "weekday", -6, 5769, AV, 2],
+								[   5769,  AV,   11,  "weekday", -6, 5769, AV, 2],
+								[   5769,  AV,   10,  "weekday", -6, 5769,AV, 2],
+								[   5769,  AV,   11,  "weekday", 6, 5769, AV, 19],
+								[   5769,  AV,   10,  "weekday", 6, 5769, AV, 19],
+								[   5769,  AV,   11,  "weekday", 12, 5769, AV, 27],
+								[   5769,  AV,   10,  "weekday", 12, 5769, AV, 27],	
+								[   5769,  AV,  9,  "weekday", 12, 5769, AV, 27],								
+								[   5769,  NISAN, 	29, "week", 1, 5769, IYAR, 6],	
+								[   5771,  NISAN, 	1, "week", -4, 5771, ADAR, 2],	
+								[   5771,  NISAN, 	1, "week", -8, 5771, ADARI, 4],	
+								[   5769,  AV, 	17, "week", 2, 5769, ELUL, 1],	
+								[   5769,  AV, 	18, "week", -1, 5769, AV, 11]						];
+						
+					//test add	
+					dojo.forEach( fields, function(f, i){
+						dateHebStart =  new dojox.date.hebrew.Date( f[0], f[1], f[2]);
+						dateHebEnd = dojox.date.hebrew.add(dateHebStart, f[3], f[4]);
+						dateHebRes = new dojox.date.hebrew.Date( f[5], f[6], f[7]);
+						t.is(0, dojo.date.compare (dateHebRes.toGregorian(), dateHebEnd.toGregorian()));
+						if(f[3] == "week"){
+							t.is(dateHebStart.getDay(), dateHebEnd.getDay());
+						}
+					});
+					
+					//test difference
+					dojo.forEach( fields, function(f, i){
+						dateHebStart =  new dojox.date.hebrew.Date( f[0], f[1], f[2]);
+						dateHebRes = new dojox.date.hebrew.Date( f[5], f[6], f[7]);
+						res = dojox.date.hebrew.difference(dateHebRes,  dateHebStart , f[3]);
+						t.is(f[4], res);
+					});
+					
+					// check that setMonth (getMonth + d) is not the same as add month (d), due to adar
+					dateHebStart = new dojox.date.hebrew.Date( 5769, KISLEV, 1);
+					var dateHebAdd =  dojox.date.hebrew.add(dateHebStart, "month", 4);
+					dateHebStart.setMonth(dateHebStart.getMonth() +4);
+					t.assertFalse(dateHebStart.getMonth() == dateHebAdd.getMonth());
+				
+				}
+		},	
+		{
+			name: "consistency_of_add_and_difference",
+			runTest: function(t){
+				var dateHebrew = new dojox.date.hebrew.Date(5769, 4, 16);
+				var dateHebrewLeap = new dojox.date.hebrew.Date(5768, 5, 16);
+				
+			//	var m =  ["TISHRI " , "HESHVAN", "KISLEV", "TEVET", "SHVAT" , "ADARI", "ADAR", "NISAN" , "IYAR" , "SIVAN" , "TAMMUZ", "AV" , "ELUL"];   	
+				
+				var amouts = [2, 5, 6, 7, 8,12, 18,20, 24, 50, -3, -4,  -5, -6, -7, -8, -9, -10, -50, 200, -200];
+				var dateHebrewAdd, dateHebrewAddLeap;
+				
+				dojo.forEach( amouts, function(amount, i){
+					dateHebrewAdd = dojox.date.hebrew.add(dateHebrew, "month",  amount);
+					dateHebrewAddLeap = dojox.date.hebrew.add(dateHebrewLeap, "month",  amount);
+					t.is(dojox.date.hebrew.difference(dateHebrewAdd, dateHebrew, "month"), amount);
+					t.is(amount, dojox.date.hebrew.difference(dateHebrewAddLeap, dateHebrewLeap, "month"));
+												
+					dateHebrewAdd= dojox.date.hebrew.add(dateHebrew, "year", amount);
+					t.is(amount, dojox.date.hebrew.difference(dateHebrewAdd, dateHebrew, "year"));
+					t.is(amount, dojox.date.hebrew.difference(dojox.date.hebrew.add(dateHebrewLeap, "year", amount), dateHebrewLeap, "year"));
+					
+					dateHebrewAdd= dojox.date.hebrew.add(dateHebrew, "week",  amount);
+					t.is(amount,  dojox.date.hebrew.difference(dateHebrewAdd, dateHebrew, "week"));
+					t.is(amount,  dojox.date.hebrew.difference(dojox.date.hebrew.add(dateHebrewLeap, "week", amount), dateHebrewLeap,"week"));
+									
+					dateHebrewAdd= dojox.date.hebrew.add(dateHebrew, "weekday", amount);
+					t.is(amount,  dojox.date.hebrew.difference(dateHebrewAdd, dateHebrew, "weekday")); 
+					dateHebrewAddLeap = dojox.date.hebrew.add(dateHebrewLeap, "weekday", amount);
+					t.is(amount,  dojox.date.hebrew.difference(dojox.date.hebrew.add(dateHebrewLeap, "weekday", amount), dateHebrewLeap,"weekday"));
+					
+					dateHebrewAdd= dojox.date.hebrew.add(dateHebrew, "day", amount)
+					t.is(amount,  dojox.date.hebrew.difference(dateHebrewAdd, dateHebrew, "day")); 
+					t.is(amount, dojox.date.hebrew.difference(dojox.date.hebrew.add(dateHebrewLeap, "day", amount), dateHebrewLeap,"day"));
+												
+					dateHebrewAdd= dojox.date.hebrew.add(dateHebrew, "hour", amount);
+					t.is(amount,  dojox.date.hebrew.difference(dateHebrewAdd, dateHebrew, "hour"));  
+					t.is(amount,  dojox.date.hebrew.difference(dojox.date.hebrew.add(dateHebrewLeap, "hour", amount), dateHebrewLeap,"hour"));
+					
+					dateHebrewAdd= dojox.date.hebrew.add(dateHebrew, "minute", amount);
+					t.is(amount,  dojox.date.hebrew.difference(dateHebrewAdd, dateHebrew, "minute")); 
+					t.is(amount,  dojox.date.hebrew.difference(dojox.date.hebrew.add(dateHebrewLeap, "minute", amount), dateHebrewLeap,"minute"));
+					
+					dateHebrewAdd= dojox.date.hebrew.add(dateHebrew, "second", amount);
+					t.is(amount,  dojox.date.hebrew.difference(dateHebrewAdd, dateHebrew, "second")); 
+					t.is(amount,  dojox.date.hebrew.difference(dojox.date.hebrew.add(dateHebrewLeap, "second", amount), dateHebrewLeap,"second"));
+					
+					dateHebrewAdd= dojox.date.hebrew.add(dateHebrew, "millisecond", amount);
+					t.is(amount,  dojox.date.hebrew.difference(dateHebrewAdd, dateHebrew, "millisecond")); 
+					t.is(amount,  dojox.date.hebrew.difference(dojox.date.hebrew.add(dateHebrewLeap, "millisecond", amount), dateHebrewLeap,"millisecond"));
+				 });
+				 
+				var dateHebrewDiff = new dojox.date.hebrew.Date(5769, 4, 17);
+				t.is(1, dojox.date.hebrew.difference(dateHebrewDiff, dateHebrew));
+			}
+		},
+		{
+			name: "getMonth_setMonth",
+			runTest: function(t){
+			var nonLeap = "5766, 5767, 5769, 5770, 5772, 5772, 5773, 5775";
+		        var leap = "5765, 5768, 5771, 5774";	
+		// ELUL - 12,  ADAR -6, ADARI -5
+				var dateHebrew = new dojox.date.hebrew.Date(5765, 1, 1);
+				for (var year = 5766; year < 5866; year++){
+					dateHebrew.setFullYear(year);
+					t.is(year,dateHebrew.getFullYear());
+					dateHebrew.setMonth(12);
+					t.is(12,dateHebrew.getMonth());
+					dateHebrew.setMonth(6);
+					t.is(6,dateHebrew.getMonth());
+					if (leap.match(year)){
+						dateHebrew.setMonth(5);
+						t.is(5,dateHebrew.getMonth());						
+					}
+					if (nonLeap.match(year)){
+						dateHebrew.setMonth(5); // non leap year does not have  ADARI, set month to ADAR
+						t.is(6,dateHebrew.getMonth());						
+					}
+				} 
+			}	
+		},
+		{
+			name: "hebrew_numerals",
+			runTest: function(t){
+				var i, hebrNum;
+				for ( i = 1 ; i <= 30; i++){
+					//test day hebrew numerals
+					t.is(dojox.date.hebrew.numerals.parseDayHebrewLetters(dojox.date.hebrew.numerals.getDayHebrewLetters(i)), i);
+					t.is(dojox.date.hebrew.numerals.parseDayHebrewLetters(dojox.date.hebrew.numerals.getDayHebrewLetters(i, true)), i); //with geresh
+					//test month hebrew numerals
+					if ( i <= 13){
+						t.is(dojox.date.hebrew.numerals.parseMonthHebrewLetters(dojox.date.hebrew.numerals.getMonthHebrewLetters(i-1)), i-1);
+					}
+				}
+				//test year hebrew numerals
+				for ( i = 5001; i < 6000; i+=27){
+					t.is(dojox.date.hebrew.numerals.parseYearHebrewLetters(dojox.date.hebrew.numerals.getYearHebrewLetters(i)), i);
+				}
+				//hebrew numerals are not relevant for year < 5001 or > 5999
+				t.assertFalse (dojox.date.hebrew.numerals.parseYearHebrewLetters(dojox.date.hebrew.numerals.getYearHebrewLetters(2345)) == 2345);
+				t.assertFalse (dojox.date.hebrew.numerals.parseYearHebrewLetters(dojox.date.hebrew.numerals.getYearHebrewLetters(6789)) == 6789);
+			}
+		},		
+		{
+			name: "parse_and_format",
+			runTest: function(t){
+	
+				//test Hebrew and English locale
+												
+				var dates = [	
+							[5768, 5, 1],
+							[5768, 1, 29],
+							[5769, 6, 16], // "absolute" index of month, non-leap year
+							[5769, 11, 2],
+							[5770, 0, 2]
+						];
+						
+				var dateHebrew, dateHebrew1;		
+				dojo.forEach(dates, function(date, i){
+					dateHebrew = new dojox.date.hebrew.Date(date[0], date[1], date[2]);
+					
+					var options = [{formatLength:'full', locale:'he'},{formatLength:'long', locale:'he'},{formatLength:'medium', locale:'he'},{formatLength:'short', locale:'he'},
+						{formatLength:'full', locale:'en'},{formatLength:'long', locale:'en'},{formatLength:'medium', locale:'en'},{formatLength:'short', locale:'en'}];					
+					dojo.forEach(options, function(opt, i){
+						str= dojox.date.hebrew.locale.format(dateHebrew, opt);
+						var option = "{" +opt+", locale:'he'}";
+						dateHebrew1 = dojox.date.hebrew.locale.parse(str, opt);
+						t.is(0, dojo.date.compare(dateHebrew.toGregorian(), dateHebrew1.toGregorian(), 'date'));
+					}); 
+					
+					var pattern = ['d M yy', 'dd/MM/yy h:m:s',  'dd#MM#yy HH$mm$ss', 'dd MMMM yyyy'];
+					dojo.forEach( pattern, function(pat, i){
+						options = {datePattern:pat, selector:'date', locale:'he'};
+						str= dojox.date.hebrew.locale.format(dateHebrew, options);
+						dateHebrew1 = dojox.date.hebrew.locale.parse(str, options);
+						t.is(0, dojo.date.compare(dateHebrew.toGregorian(), dateHebrew1.toGregorian(), 'date'));
+					});
+				}); 
+						
+				dateHebrew = new dojox.date.hebrew.Date(5769, 6, 3, 15, 3, 59);
+				pattern = 'HH$mm$ss';
+				options = {timePattern:pattern, selector:'time'};
+				str= dojox.date.hebrew.locale.format(dateHebrew, options);
+				dateHebrew1 = dojox.date.hebrew.locale.parse(str, options);
+				var gregDate = dojo.date.locale.parse(str, options);
+				t.is(0, dojo.date.compare(gregDate, dateHebrew1.toGregorian(), 'time'));	 
+				
+				pattern = "h:m:s";
+				options = {timePattern:pattern, selector:'time'};
+				str= dojox.date.hebrew.locale.format(dateHebrew, options);
+				t.is(str, "3:3:59");	 				
+			}		
+		}	
+	]
+);
diff --git a/dojox/date/tests/islamic/Date.js b/dojox/date/tests/islamic/Date.js
new file mode 100644
index 0000000..a3eab8b
--- /dev/null
+++ b/dojox/date/tests/islamic/Date.js
@@ -0,0 +1,231 @@
+dojo.provide("dojox.date.tests.islamic.Date");
+dojo.require("dojox.date.islamic.Date");
+dojo.require("dojox.date.islamic.locale");
+dojo.require("dojox.date.islamic");
+dojo.require("dojo.date");
+
+dojo.requireLocalization("dojo.cldr", "gregorian");
+dojo.requireLocalization("dojo.cldr", "islamic");
+
+tests.register("dojox.date.tests.islamic.Date",
+	[
+		{
+			// Test formatting and parsing of dates in various locales pre-built in dojo.cldr
+			// NOTE: we can't set djConfig.extraLocale before bootstrapping unit tests, so directly
+			// load resources here for specific locales:
+
+			name: "date.locale",
+			setUp: function() {
+				var partLocaleList = ["ar","en"];
+
+				dojo.forEach(partLocaleList, function(locale) {
+					dojo.requireLocalization("dojo.cldr", "islamic", locale);
+				});
+			},
+			runTest: function(t) {
+			},
+			tearDown: function() {
+				//Clean up bundles that should not exist if
+				//the test is re-run.
+				delete dojo.cldr.nls.islamic;
+			}
+		},
+		{
+			name: "toGregorian",
+			runTest: function(t) {
+				var dateIslamic = new dojox.date.islamic.Date(1431, 3, 6); // March 22 2010
+				var dateGregorian = dateIslamic.toGregorian();
+				t.is(0, dojo.date.compare(new Date(2010, 2, 22), dateGregorian, "date"));
+			}
+		},
+		{
+			name: "fromGregorian",
+			runTest: function(t) {
+				var dateIslamic = new dojox.date.islamic.Date();
+				var dateGregorian = new Date(2010, 2, 22);
+				dateIslamic.fromGregorian(dateGregorian);
+				t.is(0, dojox.date.islamic.compare(new dojox.date.islamic.Date(1431, 3, 6), dateIslamic, "date"));
+			}
+		},
+		{
+			name: "getDay",
+			runTest: function(t) {
+				var dateTable = [
+					[1431, 0, 11, 1],
+					[1431, 1, 3, 2],
+					[1431, 2, 10, 3],
+					[1431, 3, 23, 4],
+					[1431, 6, 21, 6],
+					[1431, 6, 22, 0],
+					[1431, 7, 15, 2]
+				];
+				dojo.forEach(dateTable, function(d, i) {
+					var date = new dojox.date.islamic.Date(d[0], d[1], d[2]);
+					t.is(d[3], date.getDay());
+				});
+
+			}
+		},
+		{
+			name: "getDaysInIslamicMonth",
+			runTest: function(t) {
+
+				var dateTable = [
+					[1430, 1, 29], 
+					[1420, 1, 29], 
+					[1422, 5, 29], 
+					[1431, 5, 29], 
+					[1430, 2, 30],
+					[1431, 2, 30]
+				];
+
+				dojo.forEach(dateTable, function(d, i) {
+					var date = new dojox.date.islamic.Date(d[0], d[1], 1);
+					t.is(d[2], dojox.date.islamic.getDaysInMonth(date));
+				});
+			}
+		},
+		{
+			name: "add_difference",
+			runTest: function(t) {
+				var start = [
+						[1420, 1, 1422, 1],
+						[1430, 2, 1435, 2],
+						[1433, 0, 1434, 0],
+						[1422, 2, 1420, 2],
+						[1429, 3, 1427, 3],
+						[1431, 4, 1431, 6],
+						[1429, 7, 1429, 5],
+						[1431, 3, 1431, 5],
+						[1431, 3, 1431, 0],
+						[1431, 1, 1431, 2],
+						[1431, 9, 1431, 8]
+					];
+				var add = [24, 60, 12, -24, -24, 2, -2, 2, -3, 1, -1];
+
+				var dateHijriStart, dateHijriEnd, res, dateHijriRes;
+				dojo.forEach(start, function(s, i) {
+					dateHijriStart = new dojox.date.islamic.Date(s[0], s[1], 1);
+					dateHijriRes = dojox.date.islamic.add(dateHijriStart, "month", add[i]);
+
+					t.is(0, dateHijriRes.getMonth() - s[3]);
+					t.is(0, dateHijriRes.getFullYear() - s[2]);
+				});
+
+				//month difference
+				dojo.forEach(start, function(s, i) {
+					dateHijriRes = new dojox.date.islamic.Date(s[2], s[3], 1);
+					dateHijriStart = new dojox.date.islamic.Date(s[0], s[1], 1);
+					t.is(add[i], dojox.date.islamic.difference(dateHijriRes, dateHijriStart, "month"));
+				});
+			}
+		},
+		{
+			name: "consistency_of_add_and_difference",
+			runTest: function(t) {
+				var dateIslamic = new dojox.date.islamic.Date(1431, 4, 6);
+
+
+				var amouts = [2, 5, 6, 7, 8, 12, 18, 20, 24, 50, -3, -4, -5, -6, -7, -8, -9, -10, -50, 200, -200];
+				var dateIslamicAdd;
+
+				dojo.forEach(amouts, function(amount, i) {
+					dateIslamicAdd = dojox.date.islamic.add(dateIslamic, "month", amount);
+					t.is(dojox.date.islamic.difference(dateIslamicAdd, dateIslamic, "month"), amount);
+
+					dateIslamicAdd = dojox.date.islamic.add(dateIslamic, "year", amount);
+					t.is(amount, dojox.date.islamic.difference(dateIslamicAdd, dateIslamic, "year"));
+
+					dateIslamicAdd = dojox.date.islamic.add(dateIslamic, "week", amount);
+					t.is(amount, dojox.date.islamic.difference(dateIslamicAdd, dateIslamic, "week"));
+
+					dateIslamicAdd = dojox.date.islamic.add(dateIslamic, "weekday", amount);
+					t.is(amount, dojox.date.islamic.difference(dateIslamicAdd, dateIslamic, "weekday"));
+
+					dateIslamicAdd = dojox.date.islamic.add(dateIslamic, "day", amount)
+					t.is(amount, dojox.date.islamic.difference(dateIslamicAdd, dateIslamic, "day"));
+
+					dateIslamicAdd = dojox.date.islamic.add(dateIslamic, "hour", amount);
+					t.is(amount, dojox.date.islamic.difference(dateIslamicAdd, dateIslamic, "hour"));
+
+					dateIslamicAdd = dojox.date.islamic.add(dateIslamic, "minute", amount);
+					t.is(amount, dojox.date.islamic.difference(dateIslamicAdd, dateIslamic, "minute"));
+
+					dateIslamicAdd = dojox.date.islamic.add(dateIslamic, "second", amount);
+					t.is(amount, dojox.date.islamic.difference(dateIslamicAdd, dateIslamic, "second"));
+
+					dateIslamicAdd = dojox.date.islamic.add(dateIslamic, "millisecond", amount);
+					t.is(amount, dojox.date.islamic.difference(dateIslamicAdd, dateIslamic, "millisecond"));
+				});
+
+				var dateIslamicDiff = new dojox.date.islamic.Date(1431, 4, 7);
+				t.is(1, dojox.date.islamic.difference(dateIslamicDiff, dateIslamic));
+			}
+		},
+		{
+			name: "getMonth_setMonth",
+			runTest: function(t) {
+				var dateIslamic = new dojox.date.islamic.Date(1420, 1, 1);
+				for (var year = 1420; year < 1430; year++) {
+					dateIslamic.setFullYear(year);
+					t.is(year, dateIslamic.getFullYear());
+					dateIslamic.setMonth(11);
+					t.is(11, dateIslamic.getMonth());
+					dateIslamic.setMonth(6);
+					t.is(6, dateIslamic.getMonth());
+
+				}
+			}
+		},
+		{
+			name: "parse_and_format",
+			runTest: function(t) {
+
+				//test Islamic and English locale
+
+				var dates = [
+							[1430, 5, 1],
+							[1428, 1, 28],
+							[1431, 5, 16],
+							[1431, 11, 2],
+							[1433, 0, 2]
+						];
+
+				var dateIslamic, dateIslamic1;
+				dojo.forEach(dates, function(date, i) {
+					dateIslamic = new dojox.date.islamic.Date(date[0], date[1], date[2]);
+
+					var options = [{ formatLength: 'full', locale: 'ar' }, { formatLength: 'long', locale: 'ar' }, { formatLength: 'medium', locale: 'ar' }, { formatLength: 'short', locale: 'ar' },
+						{ formatLength: 'full', locale: 'en' }, { formatLength: 'long', locale: 'en' }, { formatLength: 'medium', locale: 'en' }, { formatLength: 'short', locale: 'en'}];
+					dojo.forEach(options, function(opt, i) {
+						str = dojox.date.islamic.locale.format(dateIslamic, opt);
+						var option = "{" + opt + ", locale:'ar'}";
+						dateIslamic1 = dojox.date.islamic.locale.parse(str, opt);
+						t.is(0, dojo.date.compare(dateIslamic.toGregorian(), dateIslamic1.toGregorian(), 'date'));
+					});
+
+					var pattern = ['d M yy', 'dd/MM/yy h:m:s', 'dd#MM#yy HH$mm$ss', 'dd MMMM yyyy'];
+					dojo.forEach(pattern, function(pat, i) {
+						options = { datePattern: pat, selector: 'date', locale: 'ar' };
+						str = dojox.date.islamic.locale.format(dateIslamic, options);
+						dateIslamic1 = dojox.date.islamic.locale.parse(str, options);
+						t.is(0, dojo.date.compare(dateIslamic.toGregorian(), dateIslamic1.toGregorian(), 'date'));
+					});
+				});
+
+				dateIslamic = new dojox.date.islamic.Date(1431, 6, 3, 15, 3, 59);
+				pattern = 'HH$mm$ss';
+				options = { timePattern: pattern, selector: 'time' };
+				str = dojox.date.islamic.locale.format(dateIslamic, options);
+				dateIslamic1 = dojox.date.islamic.locale.parse(str, options);
+				var gregDate = dojo.date.locale.parse(str, options);
+				t.is(0, dojo.date.compare(gregDate, dateIslamic1.toGregorian(), 'time'));
+
+				pattern = "h:m:s";
+				options = { timePattern: pattern, selector: 'time' };
+				str = dojox.date.islamic.locale.format(dateIslamic, options);
+				t.is(str, "3:3:59");
+			}
+		}	
+	]
+);
diff --git a/dojox/date/tests/module.js b/dojox/date/tests/module.js
new file mode 100644
index 0000000..438c89c
--- /dev/null
+++ b/dojox/date/tests/module.js
@@ -0,0 +1,12 @@
+dojo.provide("dojox.date.tests.module");
+
+try{
+	dojo.require("dojox.date.tests.relative");
+	dojo.require("dojox.date.tests.hebrew.Date");
+	dojo.require("dojox.date.tests.islamic.Date");
+	dojo.require("dojox.date.tests.buddhist.Date");
+	dojo.require("dojox.date.tests.posix");
+}catch(e){
+	doh.debug(e);
+}
+
diff --git a/dojox/date/tests/posix.js b/dojox/date/tests/posix.js
new file mode 100644
index 0000000..754db36
--- /dev/null
+++ b/dojox/date/tests/posix.js
@@ -0,0 +1,261 @@
+dojo.provide("dojox.date.tests.posix");
+dojo.require("dojox.date.posix");
+
+tests.register("dojox.date.tests.posix", 
+	[
+		{
+			// see tests for dojo.date.locale for setup info
+
+			name: "dojox.date.tests.posix",
+			setUp: function(){
+				var partLocaleList = ["en"];
+
+				dojo.forEach(partLocaleList, function(locale){
+					dojo.requireLocalization("dojo.cldr", "gregorian", locale);
+				});
+			},
+			runTest: function(t){
+			},
+			tearDown: function(){
+				//Clean up bundles that should not exist if
+				//the test is re-run.
+				delete dojo.cldr.nls.gregorian;
+			}
+		},
+		{
+			name: "strftime",
+			runTest: function(t){
+				var date = new Date(2006, 7, 11, 0, 55, 12, 3456);
+				t.is("06/08/11", dojox.date.posix.strftime(date, "%y/%m/%d"));
+			
+				var dt = null; // Date to test
+				var fmt = ''; // Format to test
+				var res = ''; // Expected result
+				
+				dt = new Date(2006, 0, 1, 18, 23);
+				fmt = '%a';
+				res = 'Sun';
+				t.is(res, dojox.date.posix.strftime(dt, fmt, 'en'));
+				
+				fmt = '%A';
+				res = 'Sunday';
+				t.is(res, dojox.date.posix.strftime(dt, fmt, 'en'));
+				
+				fmt = '%b';
+				res = 'Jan';
+				t.is(res, dojox.date.posix.strftime(dt, fmt, 'en'));
+				
+				fmt = '%B';
+				res = 'January';
+				t.is(res, dojox.date.posix.strftime(dt, fmt, 'en'));
+			
+				fmt = '%c';
+				res = 'Sunday, January 1, 2006 6:23:00 PM';
+				t.is(res, dojox.date.posix.strftime(dt, fmt).substring(0, res.length));
+				
+				fmt = '%C';
+				res = '20';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%d';
+				res = '01';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%D';
+				res = '01/01/06';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%e';
+				res = ' 1';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%h';
+				res = 'Jan';
+				t.is(res, dojox.date.posix.strftime(dt, fmt, 'en'));
+				
+				fmt = '%H';
+				res = '18';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%I';
+				res = '06';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%j';
+				res = '001';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%k';
+				res = '18';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%l';
+				res = ' 6';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%m';
+				res = '01';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%M';
+				res = '23';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%p';
+				res = 'PM';
+				t.is(res, dojox.date.posix.strftime(dt, fmt, 'en'));
+				
+				fmt = '%r';
+				res = '06:23:00 PM';
+				t.is(res, dojox.date.posix.strftime(dt, fmt, 'en'));
+				
+				fmt = '%R';
+				res = '18:23';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%S';
+				res = '00';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%T';
+				res = '18:23:00';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%u';
+				res = '7';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%w';
+				res = '0';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+			
+				fmt = '%x';
+				res = 'Sunday, January 1, 2006';
+				t.is(res, dojox.date.posix.strftime(dt, fmt, 'en'));
+			
+				fmt = '%X';
+				res = '6:23:00 PM';
+				t.is(res, dojox.date.posix.strftime(dt, fmt, 'en').substring(0,res.length));
+				
+				fmt = '%y';
+				res = '06';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%Y';
+				res = '2006';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+				
+				fmt = '%%';
+				res = '%';
+				t.is(res, dojox.date.posix.strftime(dt, fmt));
+			}
+		},
+		{
+			name: "getStartOfWeek",
+			runTest: function(t){
+				var weekStart;
+				
+				// Monday
+				var date = new Date(2007, 0, 1);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 1), 1);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 2), 1);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 3), 1);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 4), 1);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 5), 1);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 6), 1);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 7), 1);
+				t.is(date, weekStart);
+			
+				// Sunday
+				date = new Date(2007, 0, 7);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 7), 0);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 8), 0);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 9), 0);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 10), 0);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 11), 0);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 12), 0);
+				t.is(date, weekStart);
+				weekStart = dojox.date.posix.getStartOfWeek(new Date(2007, 0, 13), 0);
+				t.is(date, weekStart);
+			}
+		},
+		{
+			name: "setIsoWeekOfYear",
+			runTest: function(t){
+				var date = new Date(2006,10,10);
+				var result = dojox.date.posix.setIsoWeekOfYear(date, 1);
+				t.is(new Date(2006,0,6), result);
+				result = dojox.date.posix.setIsoWeekOfYear(date, 10);
+				result = dojox.date.posix.setIsoWeekOfYear(date, 2);
+				t.is(new Date(2006,0,13), result);
+				result = dojox.date.posix.setIsoWeekOfYear(date, 10);
+				t.is(new Date(2006,2,10), result);
+				result = dojox.date.posix.setIsoWeekOfYear(date, 52);
+				t.is(new Date(2006,11,29), result);
+				var result = dojox.date.posix.setIsoWeekOfYear(date, -1);
+				t.is(new Date(2006,11,29), result);
+				var result = dojox.date.posix.setIsoWeekOfYear(date, -2);
+				t.is(new Date(2006,11,22), result);
+				var result = dojox.date.posix.setIsoWeekOfYear(date, -10);
+				t.is(new Date(2006,9,27), result);
+				
+				date = new Date(2004,10,10);
+				result = dojox.date.posix.setIsoWeekOfYear(date, 1);
+				t.is(new Date(2003,11,31), result);
+				result = dojox.date.posix.setIsoWeekOfYear(date, 2);
+				t.is(new Date(2004,0,7), result);
+				result = dojox.date.posix.setIsoWeekOfYear(date, -1);
+				t.is(new Date(2004,11,29), result);
+			}
+		},
+		{
+			name: "getIsoWeekOfYear",
+			runTest: function(t){
+				var week = dojox.date.posix.getIsoWeekOfYear(new Date(2006,0,1));
+				t.is(52, week);
+				week = dojox.date.posix.getIsoWeekOfYear(new Date(2006,0,4));
+				t.is(1, week);
+				week = dojox.date.posix.getIsoWeekOfYear(new Date(2006,11,31));
+				t.is(52, week);
+				week = dojox.date.posix.getIsoWeekOfYear(new Date(2007,0,1));
+				t.is(1, week);
+				week = dojox.date.posix.getIsoWeekOfYear(new Date(2007,11,31));
+				t.is(53, week);
+				week = dojox.date.posix.getIsoWeekOfYear(new Date(2008,0,1));
+				t.is(1, week);
+				week = dojox.date.posix.getIsoWeekOfYear(new Date(2007,11,31));
+				t.is(53, week);
+			}
+		},
+		{
+			name: "getIsoWeeksInYear",
+			runTest: function(t){
+				// 44 long years in a 400 year cycle.
+				var longYears = [4, 9, 15, 20, 26, 32, 37, 43, 48, 54, 60, 65, 71, 76, 82, 
+					88,	93, 99, 105, 111, 116, 122, 128, 133, 139, 144, 150, 156, 161, 167,
+					172, 178, 184, 189, 195, 201, 207, 212, 218, 224, 229, 235, 240, 246, 
+					252, 257, 263, 268, 274, 280, 285, 291, 296, 303, 308, 314, 320, 325,
+					331, 336, 342, 348, 353, 359, 364, 370, 376, 381, 387, 392, 398];
+			
+				var i, j, weeks, result;
+				for(i=0; i < 400; i++) {
+					weeks = 52;
+					if(i == longYears[0]) { weeks = 53; longYears.shift(); }
+					result = dojox.date.posix.getIsoWeeksInYear(new Date(2000 + i, 0, 1));
+					t.is(/*weeks +" weeks in "+ (2000+i), */weeks, result);
+				}
+			}
+		}
+	]
+);
diff --git a/dojox/date/tests/relative.js b/dojox/date/tests/relative.js
new file mode 100644
index 0000000..6096147
--- /dev/null
+++ b/dojox/date/tests/relative.js
@@ -0,0 +1,58 @@
+dojo.provide("dojox.date.tests.relative");
+dojo.require("dojox.date.relative");
+dojo.require("dojo.date");
+
+dojo.requireLocalization("dojo.cldr", "gregorian"); 
+
+tests.register("dojox.date.tests.relative", 
+	[
+		{
+			// Test formatting and parsing of dates in various locales pre-built in dojo.cldr
+			// NOTE: we can't set djConfig.extraLocale before bootstrapping unit tests, so directly
+			// load resources here for specific locales:
+
+			name: "date.locale",
+			setUp: function(){
+				var partLocaleList = ["en-us", "zh-cn"];
+
+				dojo.forEach(partLocaleList, function(locale){
+					dojo.requireLocalization("dojo.cldr", "gregorian", locale);
+				});
+			},
+			runTest: function(t){
+			},
+			tearDown: function(){
+			}
+		},
+		{
+			name: "format_dates",
+			runTest: function(t){
+				//relative to "today", default locale
+				var d = new Date();
+				t.is(dojo.date.locale.format(d, {selector: "time"}), dojox.date.relative.format(d));
+				
+				//en-us: test the various relativities
+				var opts = {locale: "en-us", relativeDate: new Date(2009, 1, 1, 5, 27, 34)};
+				t.is("3:32 AM", dojox.date.relative.format(new Date(2009, 1, 1, 3, 32, 26), opts));
+				t.is("Sat 8:32 PM", dojox.date.relative.format(new Date(2009, 0, 31, 20, 32, 26), opts));
+				t.is("Jan 1", dojox.date.relative.format(new Date(2009, 0, 1, 20, 32, 26), opts));
+				t.is("Jan 1, 2008", dojox.date.relative.format(new Date(2008, 0, 1, 0), opts));				
+				
+				//en-us: test various options as well as future dates and edge cases
+				t.is("8:32 PM", dojox.date.relative.format(new Date(2009, 1, 1, 20, 32, 26), opts));
+				t.is("12:00 AM", dojox.date.relative.format(new Date(2009, 1, 1, 0), opts));
+				t.is("Jan 31", dojox.date.relative.format(new Date(2009, 0, 31, 20, 32, 26), dojo.delegate(opts, {weekCheck: false})));
+				t.is("Jan 1", dojox.date.relative.format(new Date(2009, 0, 1, 20, 32, 26), opts));
+				t.is("Feb 2", dojox.date.relative.format(new Date(2009, 1, 2, 20, 32, 26), opts));
+				t.is("Jan 1, 2010", dojox.date.relative.format(new Date(2010, 0, 1, 0), opts));
+
+				//zh-tw: test the various relativities
+				opts.locale = "zh-cn";
+				t.is("\u4e0a\u53483:32", dojox.date.relative.format(new Date(2009, 1, 1, 3, 32, 26), opts));
+				t.is("\u5468\u516d \u4e0b\u53488:32", dojox.date.relative.format(new Date(2009, 0, 31, 20, 32, 26), opts));
+				t.is("1\u67081\u65e5", dojox.date.relative.format(new Date(2009, 0, 1, 20, 32, 26), opts));
+				t.is("2008-1-1", dojox.date.relative.format(new Date(2008, 0, 1, 0), opts));				
+			}
+		}
+	]
+);
diff --git a/dojox/date/tests/runTests.html b/dojox/date/tests/runTests.html
new file mode 100644
index 0000000..57f6ba1
--- /dev/null
+++ b/dojox/date/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.date.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/date/tests/test_DateTextBoxBuddhist.html b/dojox/date/tests/test_DateTextBoxBuddhist.html
new file mode 100644
index 0000000..ce2fe11
--- /dev/null
+++ b/dojox/date/tests/test_DateTextBoxBuddhist.html
@@ -0,0 +1,148 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Test DateTextBoxNew Buddhist Widget</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			.noticeMessage {
+				color:#093669;
+				font-size:0.95em;
+				margin-left:0.5em;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig=" isDebug: true, parseOnLoad: true, extraLocale: ['en-us', 'th']"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.Form");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojox.date.buddhist"); // TODO: think about changing this packaging so we don't have to include .locale module also
+			dojo.require("dojox.date.buddhist.locale");
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+			function eventHandler(e){
+				// use this.domNode.getAttribute('widgetId') to show "this" is the widget
+				// mouseleave/enter map to mouseout/over in all browsers except IE
+				console.log(this.domNode.getAttribute('widgetId') + ' ' + arguments[0].type);
+			}
+		</script>
+	</head>
+
+	<body class="tundra">
+		
+		<h1 class="testTitle">Test DateTextBoxNew Buddhist Widget</h1>
+		<!--	to test form submission, you'll need to create an action handler similar to
+			http://www.utexas.edu/teamweb/cgi-bin/generic.cgi -->
+		<form id="form1" dojoType='dijit.form.Form' action="" name="example" method="">
+			<div class="dojoTitlePaneLabel">
+				<label for="q1"> Buddhist  Calendar </label>
+				<span class="noticeMessage">DateTextBox class, datePackage = "dojox.date.buddhist"</span>
+			</div>
+			<div class="testExample">
+				<input id="q1" name="noDOMvalue" value="2009-03-10" type="text" dojoType="dijit.form.DateTextBox" datePackage = "dojox.date.buddhist"
+					lang="th"
+					constraints="{datePattern:'dd MMMM G yyyy'}"
+					onMouseEnter="eventHandler"
+					onMouseLeave="eventHandler"
+					onKeyDown="eventHandler"
+					onChange="dojo.byId('oc1').value=''+arguments[0]"
+				>
+				onChange:<input id="oc1" size="34" disabled value="not fired yet!" autocomplete="off">
+				<nobr>
+				<button type=button onclick="dijit.byId('q1').attr('value', null);">set value to null</button>
+				<button type=button onclick="dojo.byId('gv1').value=''+dijit.byId('q1').attr('value');">get value</button>
+				<input id="gv1" size="34" disabled value="not called yet!" autocomplete="off">
+				</nobr>
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<label for="q1"> Gregorian Date</label>
+				<span class="noticeMessage">DateTextBox class, Gregorian Calendar with min max  </span>
+			</div>
+			<div class="testExample">
+				<input id="Text1" name="noDOMvalue" value="2009-01-20" type="text" dojoType="dijit.form.DateTextBox" 
+					lang="en"
+					constraints="{min:'2009-01-01',max:'2009-02-01', datePattern:'dd MMMM yyyy'}"
+					onMouseEnter="eventHandler"
+					onMouseLeave="eventHandler"
+					onKeyDown="eventHandler"
+					onChange="dojo.byId('oc2').value=''+arguments[0]"
+				>
+				onChange:<input id="oc2" size="34" disabled value="not fired yet!" autocomplete="off">
+				<nobr>
+				<button type=button onclick="dijit.byId('Text1').attr('value', null);" ID="Button1">set value to null</button>
+				<button type=button onclick="dojo.byId('Text3').value=''+dijit.byId('Text1').attr('value');" ID="Button2">get value</button>
+				<input id="Text3" size="34" disabled value="not called yet!" autocomplete="off" NAME="Text3">
+				</nobr>
+			</div>
+				<div class="dojoTitlePaneLabel">
+				<label for="q1"> Gregorian Date </label>
+				<span class="noticeMessage">DateTextBox class,  Gregorian Calendar</span>
+			</div>
+			<div class="testExample">
+				<input id="Text4" name="noDOMvalue" value="2009-01-20" type="text" dojoType="dijit.form.DateTextBox" 
+					lang="en"
+					constraints="{datePattern:'dd MMMM yyyy'}"
+					onMouseEnter="eventHandler"
+					onMouseLeave="eventHandler"
+					onKeyDown="eventHandler"
+					onChange="dojo.byId('oc3').value=''+arguments[0]"
+				>
+				onChange:<input id="oc3" size="34" disabled value="not fired yet!" autocomplete="off">
+
+			<script>
+			// See if we can make a widget in script and attach it to the DOM ourselves.
+			dojo.addOnLoad(function(){
+		//		dojo.connect(dijit.byId('q5'), "onMouseEnter", eventHandler);
+		//		dojo.connect(dijit.byId('q5'), "onMouseLeave", eventHandler);
+		//		dojo.connect(dijit.byId('q5'), "onKeyDown", eventHandler);
+
+			});
+			</script>
+
+			<script>
+				function displayData() {
+					var f = document.getElementById("form1");
+					var s = "";
+					for (var i = 0; i < f.elements.length; i++) {
+						var elem = f.elements[i];
+						if (elem.name == "button")  { continue; }
+						s += elem.name + ": " + elem.value + "\n";
+					}
+					alert(s);
+				}
+			</script>
+
+			
+			<div>
+				<button name="button" onclick="displayData(); return false;">view data</button>
+				<input type="submit" name="submit" />
+				<input type="reset" name="reset" />
+			</div>
+		</form>
+	</body>
+</html>
diff --git a/dojox/date/tests/test_DateTextBoxIslamic.html b/dojox/date/tests/test_DateTextBoxIslamic.html
new file mode 100644
index 0000000..12ac0e6
--- /dev/null
+++ b/dojox/date/tests/test_DateTextBoxIslamic.html
@@ -0,0 +1,146 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Test DateTextBoxNew Islamic Widget</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			.noticeMessage {
+				color:#093669;
+				font-size:0.95em;
+				margin-left:0.5em;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig=" isDebug: true, parseOnLoad: true, extraLocale: ['en-us', 'ar']"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.Form");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojox.date.islamic"); // TODO: think about changing this packaging so we don't have to include .locale module also
+			dojo.require("dojox.date.islamic.locale");
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+			function eventHandler(e){
+				// use this.domNode.getAttribute('widgetId') to show "this" is the widget
+				// mouseleave/enter map to mouseout/over in all browsers except IE
+				console.log(this.domNode.getAttribute('widgetId') + ' ' + arguments[0].type);
+			}
+		</script>
+	</head>
+
+	<body class="tundra">
+		
+		<h1 class="testTitle">Test DateTextBoxNew Islamic Widget</h1>
+		<!--	to test form submission, you'll need to create an action handler similar to
+			http://www.utexas.edu/teamweb/cgi-bin/generic.cgi -->
+		<form id="form1" dojoType='dijit.form.Form' action="" name="example" method="">
+			<div class="dojoTitlePaneLabel">
+				<label for="q1"> Islamic  Calendar </label>
+				<span class="noticeMessage">DateTextBox class, datePackage="dojox.date.islamic"</span>
+			</div>
+			<div class="testExample">
+				<input id="q1" name="noDOMvalue" value="2009-03-10" type="text" dojoType="dijit.form.DateTextBox" datePackage="dojox.date.islamic"
+					lang="ar"
+					onMouseEnter="eventHandler"
+					onMouseLeave="eventHandler"
+					onKeyDown="eventHandler"
+					onChange="dojo.byId('oc1').value=''+arguments[0]"
+				>
+				onChange:<input id="oc1" size="34" disabled value="not fired yet!" autocomplete="off">
+				<nobr>
+				<button type=button onclick="dijit.byId('q1').attr('value', null);">set value to null</button>
+				<button type=button onclick="dojo.byId('gv1').value=''+dijit.byId('q1').attr('value');">get value</button>
+				<input id="gv1" size="34" disabled value="not called yet!" autocomplete="off">
+				</nobr>
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<label for="q1"> Gregorian Date</label>
+				<span class="noticeMessage">DateTextBox class, Gregorian Calendar with min max  </span>
+			</div>
+			<div class="testExample">
+				<input id="Text1" name="noDOMvalue" value="2009-01-20" type="text" dojoType="dijit.form.DateTextBox" 
+					lang="en"
+					constraints="{min:'2009-01-01',max:'2009-02-01', datePattern:'dd MMMM yyyy'}"
+					onMouseEnter="eventHandler"
+					onMouseLeave="eventHandler"
+					onKeyDown="eventHandler"
+					onChange="dojo.byId('oc2').value=''+arguments[0]"
+				>
+				onChange:<input id="oc2" size="34" disabled value="not fired yet!" autocomplete="off">
+				<nobr>
+				<button type=button onclick="dijit.byId('Text1').attr('value', null);" ID="Button1">set value to null</button>
+				<button type=button onclick="dojo.byId('Text3').value=''+dijit.byId('Text1').attr('value');" ID="Button2">get value</button>
+				<input id="Text3" size="34" disabled value="not called yet!" autocomplete="off" NAME="Text3">
+				</nobr>
+			</div>
+				<div class="dojoTitlePaneLabel">
+				<label for="q1"> Gregorian Date </label>
+				<span class="noticeMessage">DateTextBox class,  Gregorian Calendar</span>
+			</div>
+			<div class="testExample">
+				<input id="Text4" name="noDOMvalue" value="2009-01-20" type="text" dojoType="dijit.form.DateTextBox" 
+					lang="en"
+					onMouseEnter="eventHandler"
+					onMouseLeave="eventHandler"
+					onKeyDown="eventHandler"
+					onChange="dojo.byId('oc3').value=''+arguments[0]"
+				>
+				onChange:<input id="oc3" size="34" disabled value="not fired yet!" autocomplete="off">
+
+			<script>
+			// See if we can make a widget in script and attach it to the DOM ourselves.
+			dojo.addOnLoad(function(){
+		//		dojo.connect(dijit.byId('q5'), "onMouseEnter", eventHandler);
+		//		dojo.connect(dijit.byId('q5'), "onMouseLeave", eventHandler);
+		//		dojo.connect(dijit.byId('q5'), "onKeyDown", eventHandler);
+
+			});
+			</script>
+
+			<script>
+				function displayData() {
+					var f = document.getElementById("form1");
+					var s = "";
+					for (var i = 0; i < f.elements.length; i++) {
+						var elem = f.elements[i];
+						if (elem.name == "button")  { continue; }
+						s += elem.name + ": " + elem.value + "\n";
+					}
+					alert(s);
+				}
+			</script>
+
+			
+			<div>
+				<button name="button" onclick="displayData(); return false;">view data</button>
+				<input type="submit" name="submit" />
+				<input type="reset" name="reset" />
+			</div>
+		</form>
+	</body>
+</html>
diff --git a/dojox/date/tests/test_DateTextBoxNewHebrewGreg.html b/dojox/date/tests/test_DateTextBoxNewHebrewGreg.html
new file mode 100644
index 0000000..9f84ddf
--- /dev/null
+++ b/dojox/date/tests/test_DateTextBoxNewHebrewGreg.html
@@ -0,0 +1,148 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Test DateTextBoxNew Hebrew Gregorian Widget</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			.noticeMessage {
+				color:#093669;
+				font-size:0.95em;
+				margin-left:0.5em;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+		</style>
+
+		<!-- required: the default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig=" isDebug: true, parseOnLoad: true, extraLocale: ['en-us', 'he-il']"></script>
+
+		<!-- only needed for alternate theme testing: -->
+		<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.form.Form");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojox.date.hebrew"); // TODO: think about changing this packaging so we don't have to include .locale module also
+			dojo.require("dojox.date.hebrew.locale");
+			dojo.require("dijit.form.DateTextBox");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+			function eventHandler(e){
+				// use this.domNode.getAttribute('widgetId') to show "this" is the widget
+				// mouseleave/enter map to mouseout/over in all browsers except IE
+				console.log(this.domNode.getAttribute('widgetId') + ' ' + arguments[0].type);
+			}
+		</script>
+	</head>
+
+	<body class="tundra">
+		
+		<h1 class="testTitle">Test DateTextBoxNew Hebrew and Gregorian Widget</h1>
+		<!--	to test form submission, you'll need to create an action handler similar to
+			http://www.utexas.edu/teamweb/cgi-bin/generic.cgi -->
+		<form id="form1" dojoType='dijit.form.Form' action="" name="example" method="">
+			<div class="dojoTitlePaneLabel">
+				<label for="q1"> Hebrew  Calendar </label>
+				<span class="noticeMessage">DateTextBox class, datePackage = "dojox.date.hebrew"</span>
+			</div>
+			<div class="testExample">
+				<input id="q1" name="noDOMvalue" value="2009-03-10" type="text" dojoType="dijit.form.DateTextBox" datePackage = "dojox.date.hebrew"
+					lang="he"
+					constraints="{min:'2008-03-01',max:'2009-04-01',datePattern:'dd MMMM yyyy'}"
+					onMouseEnter="eventHandler"
+					onMouseLeave="eventHandler"
+					onKeyDown="eventHandler"
+					onChange="dojo.byId('oc1').value=''+arguments[0]"
+				>
+				onChange:<input id="oc1" size="34" disabled value="not fired yet!" autocomplete="off">
+				<nobr>
+				<button type=button onclick="dijit.byId('q1').attr('value', null);">set value to null</button>
+				<button type=button onclick="dojo.byId('gv1').value=''+dijit.byId('q1').attr('value');">get value</button>
+				<input id="gv1" size="34" disabled value="not called yet!" autocomplete="off">
+				</nobr>
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<label for="q1"> Gregorian Date</label>
+				<span class="noticeMessage">DateTextBox class, Gregorian Calendar with min max  </span>
+			</div>
+			<div class="testExample">
+				<input id="Text1" name="noDOMvalue" value="2009-01-20" type="text" dojoType="dijit.form.DateTextBox" 
+					lang="en"
+					constraints="{min:'2009-01-01',max:'2009-02-01', datePattern:'dd MMMM yyyy'}"
+					onMouseEnter="eventHandler"
+					onMouseLeave="eventHandler"
+					onKeyDown="eventHandler"
+					onChange="dojo.byId('oc2').value=''+arguments[0]"
+				>
+				onChange:<input id="oc2" size="34" disabled value="not fired yet!" autocomplete="off">
+				<nobr>
+				<button type=button onclick="dijit.byId('Text1').attr('value', null);" ID="Button1">set value to null</button>
+				<button type=button onclick="dojo.byId('Text3').value=''+dijit.byId('Text1').attr('value');" ID="Button2">get value</button>
+				<input id="Text3" size="34" disabled value="not called yet!" autocomplete="off" NAME="Text3">
+				</nobr>
+			</div>
+				<div class="dojoTitlePaneLabel">
+				<label for="q1"> Gregorian Date </label>
+				<span class="noticeMessage">DateTextBox class,  Gregorian Calendar</span>
+			</div>
+			<div class="testExample">
+				<input id="Text4" name="noDOMvalue" value="2009-01-20" type="text" dojoType="dijit.form.DateTextBox" 
+					lang="en"
+					constraints="{datePattern:'dd MMMM yyyy'}"
+					onMouseEnter="eventHandler"
+					onMouseLeave="eventHandler"
+					onKeyDown="eventHandler"
+					onChange="dojo.byId('oc3').value=''+arguments[0]"
+				>
+				onChange:<input id="oc3" size="34" disabled value="not fired yet!" autocomplete="off">
+
+			<script>
+			// See if we can make a widget in script and attach it to the DOM ourselves.
+			dojo.addOnLoad(function(){
+		//		dojo.connect(dijit.byId('q5'), "onMouseEnter", eventHandler);
+		//		dojo.connect(dijit.byId('q5'), "onMouseLeave", eventHandler);
+		//		dojo.connect(dijit.byId('q5'), "onKeyDown", eventHandler);
+
+			});
+			</script>
+
+			<script>
+				function displayData() {
+					var f = document.getElementById("form1");
+					var s = "";
+					for (var i = 0; i < f.elements.length; i++) {
+						var elem = f.elements[i];
+						if (elem.name == "button")  { continue; }
+						s += elem.name + ": " + elem.value + "\n";
+					}
+					alert(s);
+				}
+			</script>
+
+			
+			<div>
+				<button name="button" onclick="displayData(); return false;">view data</button>
+				<input type="submit" name="submit" />
+				<input type="reset" name="reset" />
+			</div>
+		</form>
+	</body>
+</html>
diff --git a/dojox/date/tests/timezone.js b/dojox/date/tests/timezone.js
new file mode 100644
index 0000000..12986f1
--- /dev/null
+++ b/dojox/date/tests/timezone.js
@@ -0,0 +1,421 @@
+dojo.provide("dojox.date.tests.timezone");
+dojo.require("dojox.date.timezone");
+dojo.require("dojo.date");
+
+doh.checkDate = function(x, u, z, e){
+	var d = new Date(u);
+	var t = dojox.date.timezone.getTzInfo(d, z);
+	// Account for rounding differences between perl and js
+	x.tzOffset = Math.round(x.tzOffset * 1000) / 1000;
+	t.tzOffset = Math.round(t.tzOffset * 1000) / 1000;
+
+	// Check our expected offset and abbreviation
+	doh.assertEqual(x, t);
+	// Check that we didn't change the date internally
+	doh.assertEqual(u, d.getTime());
+}
+
+var testsToRun = [
+	"Africa-Abidjan",
+	"Africa-Accra",
+	"Africa-Addis_Ababa",
+	"Africa-Algiers",
+	"Africa-Asmara",
+	"Africa-Bamako",
+	"Africa-Bangui",
+	"Africa-Banjul",
+	"Africa-Bissau",
+	"Africa-Blantyre",
+	"Africa-Brazzaville",
+	"Africa-Bujumbura",
+	"Africa-Cairo",
+	"Africa-Casablanca",
+	"Africa-Ceuta",
+	"Africa-Conakry",
+	"Africa-Dakar",
+	"Africa-Dar_es_Salaam",
+	"Africa-Djibouti",
+	"Africa-Douala",
+	"Africa-El_Aaiun",
+	"Africa-Freetown",
+	"Africa-Gaborone",
+	"Africa-Harare",
+	"Africa-Johannesburg",
+	"Africa-Kampala",
+	"Africa-Khartoum",
+	"Africa-Kigali",
+	"Africa-Kinshasa",
+	"Africa-Lagos",
+	"Africa-Libreville",
+	"Africa-Lome",
+	"Africa-Luanda",
+	"Africa-Lubumbashi",
+	"Africa-Lusaka",
+	"Africa-Malabo",
+	"Africa-Maputo",
+	"Africa-Maseru",
+	"Africa-Mbabane",
+	"Africa-Mogadishu",
+	"Africa-Monrovia",
+	"Africa-Nairobi",
+	"Africa-Ndjamena",
+	"Africa-Niamey",
+	"Africa-Nouakchott",
+	"Africa-Ouagadougou",
+	"Africa-Porto-Novo",
+	"Africa-Sao_Tome",
+	"Africa-Tripoli",
+	"Africa-Tunis",
+	"Africa-Windhoek",
+	"America-Adak",
+	"America-Anchorage",
+	"America-Anguilla",
+	"America-Antigua",
+	"America-Araguaina",
+	"America-Argentina-Buenos_Aires",
+	"America-Argentina-Catamarca",
+	"America-Argentina-Cordoba",
+	"America-Argentina-Jujuy",
+	"America-Argentina-La_Rioja",
+	"America-Argentina-Mendoza",
+	"America-Argentina-Rio_Gallegos",
+	"America-Argentina-Salta",
+	"America-Argentina-San_Juan",
+	"America-Argentina-San_Luis",
+	"America-Argentina-Tucuman",
+	"America-Argentina-Ushuaia",
+	"America-Aruba",
+	"America-Asuncion",
+	"America-Atikokan",
+	"America-Bahia",
+	"America-Barbados",
+	"America-Belem",
+	"America-Belize",
+	"America-Blanc-Sablon",
+	"America-Boa_Vista",
+	"America-Bogota",
+	"America-Boise",
+	"America-Cambridge_Bay",
+	"America-Campo_Grande",
+	"America-Cancun",
+	"America-Caracas",
+	"America-Cayenne",
+	"America-Cayman",
+	"America-Chicago",
+	"America-Chihuahua",
+	"America-Costa_Rica",
+	"America-Cuiaba",
+	"America-Curacao",
+	"America-Danmarkshavn",
+	"America-Dawson",
+	"America-Dawson_Creek",
+	"America-Denver",
+	"America-Detroit",
+	"America-Dominica",
+	"America-Edmonton",
+	"America-Eirunepe",
+	"America-El_Salvador",
+	"America-Fortaleza",
+	"America-Glace_Bay",
+	"America-Godthab",
+	"America-Goose_Bay",
+	"America-Grand_Turk",
+	"America-Grenada",
+	"America-Guadeloupe",
+	"America-Guatemala",
+	"America-Guayaquil",
+	"America-Guyana",
+	"America-Halifax",
+	"America-Havana",
+	"America-Hermosillo",
+	"America-Indiana-Indianapolis",
+	"America-Indiana-Knox",
+	"America-Indiana-Marengo",
+	"America-Indiana-Petersburg",
+	"America-Indiana-Tell_City",
+	"America-Indiana-Vevay",
+	"America-Indiana-Vincennes",
+	"America-Indiana-Winamac",
+	"America-Inuvik",
+	"America-Iqaluit",
+	"America-Jamaica",
+	"America-Juneau",
+	"America-Kentucky-Louisville",
+	"America-Kentucky-Monticello",
+	"America-La_Paz",
+	"America-Lima",
+	"America-Los_Angeles",
+	"America-Maceio",
+	"America-Managua",
+	"America-Manaus",
+	"America-Martinique",
+	"America-Mazatlan",
+	"America-Menominee",
+	"America-Merida",
+	"America-Mexico_City",
+	"America-Miquelon",
+	"America-Moncton",
+	"America-Monterrey",
+	"America-Montevideo",
+	"America-Montreal",
+	"America-Montserrat",
+	"America-Nassau",
+	"America-New_York",
+	"America-Nipigon",
+	"America-Nome",
+	"America-Noronha",
+	"America-North_Dakota-Center",
+	"America-North_Dakota-New_Salem",
+	"America-Panama",
+	"America-Pangnirtung",
+	"America-Paramaribo",
+	"America-Phoenix",
+	"America-Port-au-Prince",
+	"America-Port_of_Spain",
+	"America-Porto_Velho",
+	"America-Puerto_Rico",
+	"America-Rainy_River",
+	"America-Rankin_Inlet",
+	"America-Recife",
+	"America-Regina",
+	"America-Resolute",
+	"America-Rio_Branco",
+	"America-Santarem",
+	"America-Santiago",
+	"America-Santo_Domingo",
+	"America-Sao_Paulo",
+	"America-Scoresbysund",
+	"America-St_Johns",
+	"America-St_Kitts",
+	"America-St_Lucia",
+	"America-St_Thomas",
+	"America-St_Vincent",
+	"America-Swift_Current",
+	"America-Tegucigalpa",
+	"America-Thule",
+	"America-Thunder_Bay",
+	"America-Tijuana",
+	"America-Toronto",
+	"America-Tortola",
+	"America-Vancouver",
+	"America-Whitehorse",
+	"America-Winnipeg",
+	"America-Yakutat",
+	"America-Yellowknife",
+	"Antarctica-Casey",
+	"Antarctica-Davis",
+	"Antarctica-DumontDUrville",
+	"Antarctica-Mawson",
+	"Antarctica-McMurdo",
+	"Antarctica-Palmer",
+	"Antarctica-Rothera",
+	"Antarctica-Syowa",
+	"Antarctica-Vostok",
+	"Asia-Aden",
+	"Asia-Almaty",
+	"Asia-Amman",
+	"Asia-Anadyr",
+	"Asia-Aqtau",
+	"Asia-Aqtobe",
+	"Asia-Ashgabat",
+	"Asia-Baghdad",
+	"Asia-Bahrain",
+	"Asia-Baku",
+	"Asia-Bangkok",
+	"Asia-Beirut",
+	"Asia-Bishkek",
+	"Asia-Brunei",
+	"Asia-Choibalsan",
+	"Asia-Chongqing",
+	"Asia-Colombo",
+	"Asia-Damascus",
+	"Asia-Dhaka",
+	"Asia-Dili",
+	"Asia-Dubai",
+	"Asia-Dushanbe",
+	"Asia-Gaza",
+	"Asia-Harbin",
+	"Asia-Ho_Chi_Minh",
+	"Asia-Hong_Kong",
+	"Asia-Hovd",
+	"Asia-Irkutsk",
+	"Asia-Jakarta",
+	"Asia-Jayapura",
+	"Asia-Jerusalem",
+	"Asia-Kabul",
+	"Asia-Kamchatka",
+	"Asia-Karachi",
+	"Asia-Kashgar",
+	"Asia-Kathmandu",
+	"Asia-Kolkata",
+	"Asia-Krasnoyarsk",
+	"Asia-Kuala_Lumpur",
+	"Asia-Kuching",
+	"Asia-Kuwait",
+	"Asia-Macau",
+	"Asia-Magadan",
+	"Asia-Makassar",
+	"Asia-Manila",
+	"Asia-Muscat",
+	"Asia-Nicosia",
+	"Asia-Novosibirsk",
+	"Asia-Omsk",
+	"Asia-Oral",
+	"Asia-Phnom_Penh",
+	"Asia-Pontianak",
+	"Asia-Pyongyang",
+	"Asia-Qatar",
+	"Asia-Qyzylorda",
+	"Asia-Rangoon",
+	"Asia-Riyadh",
+	"Asia-Sakhalin",
+	"Asia-Samarkand",
+	"Asia-Seoul",
+	"Asia-Shanghai",
+	"Asia-Singapore",
+	"Asia-Taipei",
+	"Asia-Tashkent",
+	"Asia-Tbilisi",
+	"Asia-Tehran",
+	"Asia-Thimphu",
+	"Asia-Tokyo",
+	"Asia-Ulaanbaatar",
+	"Asia-Urumqi",
+	"Asia-Vientiane",
+	"Asia-Vladivostok",
+	"Asia-Yakutsk",
+	"Asia-Yekaterinburg",
+	"Asia-Yerevan",
+	"Atlantic-Azores",
+	"Atlantic-Bermuda",
+	"Atlantic-Canary",
+	"Atlantic-Cape_Verde",
+	"Atlantic-Faroe",
+	"Atlantic-Madeira",
+	"Atlantic-Reykjavik",
+	"Atlantic-South_Georgia",
+	"Atlantic-St_Helena",
+	"Atlantic-Stanley",
+	"Australia-Adelaide",
+	"Australia-Brisbane",
+	"Australia-Broken_Hill",
+	"Australia-Currie",
+	"Australia-Darwin",
+	"Australia-Eucla",
+	"Australia-Hobart",
+	"Australia-Lindeman",
+	"Australia-Lord_Howe",
+	"Australia-Melbourne",
+	"Australia-Perth",
+	"Australia-Sydney",
+	"CET",
+	"CST6CDT",
+	"EET",
+	"EST5EDT",
+	"Europe-Amsterdam",
+	"Europe-Andorra",
+	"Europe-Athens",
+	"Europe-Belgrade",
+	"Europe-Berlin",
+	"Europe-Brussels",
+	"Europe-Bucharest",
+	"Europe-Budapest",
+	"Europe-Chisinau",
+	"Europe-Copenhagen",
+	"Europe-Dublin",
+	"Europe-Gibraltar",
+	"Europe-Helsinki",
+	"Europe-Istanbul",
+	"Europe-Kaliningrad",
+	"Europe-Kiev",
+	"Europe-Lisbon",
+	"Europe-London",
+	"Europe-Luxembourg",
+	"Europe-Madrid",
+	"Europe-Malta",
+	"Europe-Minsk",
+	"Europe-Monaco",
+	"Europe-Moscow",
+	"Europe-Oslo",
+	"Europe-Paris",
+	"Europe-Prague",
+	"Europe-Riga",
+	"Europe-Rome",
+	"Europe-Samara",
+	"Europe-Simferopol",
+	"Europe-Sofia",
+	"Europe-Stockholm",
+	"Europe-Tallinn",
+	"Europe-Tirane",
+	"Europe-Uzhgorod",
+	"Europe-Vaduz",
+	"Europe-Vienna",
+	"Europe-Vilnius",
+	"Europe-Volgograd",
+	"Europe-Warsaw",
+	"Europe-Zaporozhye",
+	"Europe-Zurich",
+	"HST",
+	"Indian-Antananarivo",
+	"Indian-Chagos",
+	"Indian-Christmas",
+	"Indian-Cocos",
+	"Indian-Comoro",
+	"Indian-Kerguelen",
+	"Indian-Mahe",
+	"Indian-Maldives",
+	"Indian-Mauritius",
+	"Indian-Mayotte",
+	"Indian-Reunion",
+	"MET",
+	"MST7MDT",
+	"PST8PDT",
+	"Pacific-Apia",
+	"Pacific-Auckland",
+	"Pacific-Chatham",
+	"Pacific-Easter",
+	"Pacific-Efate",
+	"Pacific-Enderbury",
+	"Pacific-Fakaofo",
+	"Pacific-Fiji",
+	"Pacific-Funafuti",
+	"Pacific-Galapagos",
+	"Pacific-Gambier",
+	"Pacific-Guadalcanal",
+	"Pacific-Guam",
+	"Pacific-Honolulu",
+	"Pacific-Johnston",
+	"Pacific-Kiritimati",
+	"Pacific-Kosrae",
+	"Pacific-Kwajalein",
+	"Pacific-Majuro",
+	"Pacific-Marquesas",
+	"Pacific-Midway",
+	"Pacific-Nauru",
+	"Pacific-Niue",
+	"Pacific-Norfolk",
+	"Pacific-Noumea",
+	"Pacific-Pago_Pago",
+	"Pacific-Palau",
+	"Pacific-Pitcairn",
+	"Pacific-Ponape",
+	"Pacific-Port_Moresby",
+	"Pacific-Rarotonga",
+	"Pacific-Saipan",
+	"Pacific-Tahiti",
+	"Pacific-Tarawa",
+	"Pacific-Tongatapu",
+	"Pacific-Truk",
+	"Pacific-Wake",
+	"Pacific-Wallis",
+	"WET"
+];
+
+dojo.forEach(testsToRun, function(tRun){
+	dojo.xhrGet({
+		url: dojo.moduleUrl("dojox.date.tests", "tztests/tz_" + tRun + ".json"),
+		handleAs: "json",
+		load: function(d){
+			tests.register("dojox.date.tests.timezone", [ d ]);
+		}});
+});
\ No newline at end of file
diff --git a/dojox/date/tests/timezoneFormatting.js b/dojox/date/tests/timezoneFormatting.js
new file mode 100644
index 0000000..2ce1037
--- /dev/null
+++ b/dojox/date/tests/timezoneFormatting.js
@@ -0,0 +1,83 @@
+dojo.provide("dojox.date.tests.timezoneFormatting");
+dojo.require("dojox.date.timezone");
+dojo.require("dojo.date");
+
+tests.register("dojox.date.tests.timezoneFormatting",
+	[
+		{
+			name: "timezone format",
+			setUp: function(){
+				var partLocaleList = ["en-us", "fr-fr", "es", "de-at", "ja-jp", "zh-cn"];
+
+				dojo.forEach(partLocaleList, function(locale){
+					dojo.requireLocalization("dojo.cldr", "gregorian", locale);
+				});			
+			},
+			runTest: function(t){
+				var date = new Date(1155257712345);
+					// This translates to:
+					//   GMT		Friday, August 11, 2006 at 00:55:12 GMT
+					//   Denver		Thursday, August 10, 2006 at 6:55:12 PM MDT
+					//   Anchorage	Thursday, August 10, 2006 at 4:55:12 PM AKDT
+					//   Jerusalem	Friday, August 11, 2006 at 3:55:12 AM IDT
+					//   Sydney		Friday, August 11, 2006 at 10:55:12 AM EST
+					//   Tokyo		Friday, August 11, 2006 at 9:55:12 AM JST
+					//   Shanghai	Friday, August 11, 2006 at 8:55:12 AM CST
+					//   Paris		Friday, August 11, 2006 at 2:55:12 AM CEST
+					//   Vienna		Friday, August 11, 2006 at 2:55:12 AM CEST
+					//   Madrid		Friday, August 11, 2006 at 2:55:12 AM CEST
+					
+				//////////////////////
+				//  Custom Selector:
+				var selectorOpts = {datePattern: "EEEE, MMMM d, y 'at'", timePattern: "HH:mm:ss z", locale: "en-us"};
+				doh.is("Friday, August 11, 2006 at 00:55:12 GMT", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone: 'GMT'})));
+				doh.is("Thursday, August 10, 2006 at 18:55:12 MDT", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone: 'America/Denver'})));
+				doh.is("Thursday, August 10, 2006 at 16:55:12 AKDT", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone: 'America/Anchorage'})));
+				doh.is("Friday, August 11, 2006 at 03:55:12 IDT", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone: 'Asia/Jerusalem'})));
+				doh.is("Friday, August 11, 2006 at 10:55:12 EST", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone: 'Australia/Sydney'})));
+				doh.is("Friday, August 11, 2006 at 09:55:12 JST", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone: 'Asia/Tokyo'})));
+				doh.is("Friday, August 11, 2006 at 08:55:12 CST", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone: 'Asia/Shanghai'})));
+				doh.is("Friday, August 11, 2006 at 02:55:12 CEST", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone: 'Europe/Madrid'})));
+				
+												
+				//////////////////////
+				//  Full Selectors:
+				// New York (in en-us)
+				doh.is("Thursday, August 10, 2006 8:55:12 PM EDT", dojo.date.locale.format(date, {formatLength:'full',locale:'en-us',timezone:'America/New_York'}));
+				// Tokyo (in ja-jp)
+				doh.is("2006\u5e748\u670811\u65e5\u91d1\u66dc\u65e59\u664255\u520612\u79d2 JST", dojo.date.locale.format(date, {formatLength:'full',locale:'ja-jp',timezone:'Asia/Tokyo'}));
+				// Shanghai (in zh-cn)
+				doh.is("2006\u5e748\u670811\u65e5\u661f\u671f\u4e94\u4e0a\u534808\u65f655\u520612\u79d2 CST", dojo.date.locale.format(date, {formatLength:'full',locale:'zh-cn',timezone:'Asia/Shanghai'}));
+				// Paris (in fr-fr)
+				doh.is("vendredi 11 août 2006 02:55:12 CEST", dojo.date.locale.format(date, {formatLength:'full',locale:'fr-fr',timezone:'Europe/Paris'}));
+				// Vienna (in de-at)
+				doh.is("Freitag, 11. August 2006 02:55:12 CEST", dojo.date.locale.format(date, {formatLength:'full',locale:'de-at',timezone:'Europe/Vienna'}));
+				// Madrid (in es)
+				doh.is("viernes 11 de agosto de 2006 02:55:12 CEST", dojo.date.locale.format(date, {formatLength:'full',locale:'es',timezone:'Europe/Madrid'}));
+				
+				//////////////////////
+				//  Tricky Dates:
+				date = new Date(1225605599000); // 1 second before New York goes off DST - NY and LA are 3 hours apart
+				selectorOpts = {formatLength: "full", locale: "en-us"};
+				doh.is("Sunday, November 2, 2008 1:59:59 AM EDT", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone:'America/New_York'})));
+				doh.is("Saturday, November 1, 2008 10:59:59 PM PDT", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone:'America/Los_Angeles'})));
+				
+				date = new Date(1225605600000); // New York goes off DST - NY and LA are 2 hours apart
+				doh.is("Sunday, November 2, 2008 1:00:00 AM EST", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone:'America/New_York'})));
+				doh.is("Saturday, November 1, 2008 11:00:00 PM PDT", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone:'America/Los_Angeles'})));
+				
+				date = new Date(1225616400000); // LA goes off DST - NY and LA are 3 hours apart again
+				doh.is("Sunday, November 2, 2008 4:00:00 AM EST", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone:'America/New_York'})));
+				doh.is("Sunday, November 2, 2008 1:00:00 AM PST", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone:'America/Los_Angeles'})));
+				
+				date = new Date(1257062399000); // Denver on DST - Denver is 1 hr ahead of Phoenix
+				doh.is("Sunday, November 1, 2009 1:59:59 AM MDT", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone:'America/Denver'})));
+				doh.is("Sunday, November 1, 2009 12:59:59 AM MST", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone:'America/Phoenix'})));
+				
+				date = new Date(1257062400000); // Denver off DST - Denver is same time as Phoenix
+				doh.is("Sunday, November 1, 2009 1:00:00 AM MST", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone:'America/Denver'})));
+				doh.is("Sunday, November 1, 2009 1:00:00 AM MST", dojo.date.locale.format(date, dojo.delegate(selectorOpts, {timezone:'America/Phoenix'})));
+			}
+		}
+	]
+);
\ No newline at end of file
diff --git a/dojox/date/tests/tztests/tz_Africa-Abidjan.json b/dojox/date/tests/tztests/tz_Africa-Abidjan.json
new file mode 100644
index 0000000..2ec548e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Abidjan.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Abidjan",
+	runTest: function(t){
+		var tz = "Africa/Abidjan";
+		doh.checkDate({tzOffset: 16.1333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 16.1333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 16.1333333333333, tzAbbr: "LMT"}, -1830383033000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1830383032000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Accra.json b/dojox/date/tests/tztests/tz_Africa-Accra.json
new file mode 100644
index 0000000..484ea15
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Accra.json
@@ -0,0 +1,42 @@
+({
+	name: "date.timezone.Africa-Accra",
+	runTest: function(t){
+		var tz = "Africa/Accra";
+		doh.checkDate({tzOffset: 0.866666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0.866666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0.866666666666667, tzAbbr: "LMT"}, -1640995149000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1640995148000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1051920001000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -1051920000000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -1041466801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1041466800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1020384001000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -1020384000000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -1009930801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1009930800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -988848001000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -988848000000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -978394801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -978394800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -957312001000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -957312000000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -946858801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -946858800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -925689601000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -925689600000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -915236401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -915236400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -894153601000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -894153600000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -883700401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -883700400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -862617601000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -862617600000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "GHST"}, -852164401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -852164400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Addis_Ababa.json b/dojox/date/tests/tztests/tz_Africa-Addis_Ababa.json
new file mode 100644
index 0000000..915a03c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Addis_Ababa.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Addis_Ababa",
+	runTest: function(t){
+		var tz = "Africa/Addis_Ababa";
+		doh.checkDate({tzOffset: -155.333333333333, tzAbbr: "ADMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -155.333333333333, tzAbbr: "ADMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -155.333333333333, tzAbbr: "ADMT"}, -1062210921000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1062210920000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Algiers.json b/dojox/date/tests/tztests/tz_Africa-Algiers.json
new file mode 100644
index 0000000..8dc4897
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Algiers.json
@@ -0,0 +1,78 @@
+({
+	name: "date.timezone.Africa-Algiers",
+	runTest: function(t){
+		var tz = "Africa/Algiers";
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -1855958962000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1855958961000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1689814801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1689814800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1680397201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1680397200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1665363601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1665363600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1648342801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1648342800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1635123601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1635123600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1616893201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1616893200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1604278801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1604278800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1585443601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1585443600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1574038801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1574038800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1552266001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1552266000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1539997201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1539997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1531443601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1531443600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -956365201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -956365200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -950486401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -950486400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -942012001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -942012000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796262401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796262400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -766630801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -766630800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733280401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -733280400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -439430401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -439430400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -212029201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -212029200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 41468399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 41468400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 54773999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 54774000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 231724799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 231724800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 246236399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 246236400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 259545599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 259545600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 275273999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 275274000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 309740399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 309740400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 325468799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 325468800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 341801999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 341802000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 357523199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 357523200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Asmara.json b/dojox/date/tests/tztests/tz_Africa-Asmara.json
new file mode 100644
index 0000000..96fa05b
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Asmara.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Asmara",
+	runTest: function(t){
+		var tz = "Africa/Asmara";
+		doh.checkDate({tzOffset: -155.333333333333, tzAbbr: "ADMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -155.333333333333, tzAbbr: "ADMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -155.333333333333, tzAbbr: "ADMT"}, -1062210921000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1062210920000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Bamako.json b/dojox/date/tests/tztests/tz_Africa-Bamako.json
new file mode 100644
index 0000000..7843da6
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Bamako.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Africa-Bamako",
+	runTest: function(t){
+		var tz = "Africa/Bamako";
+		doh.checkDate({tzOffset: 32, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 32, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 32, tzAbbr: "LMT"}, -1830382081000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1830382080000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1131235201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1131235200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -300841201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -300841200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Bangui.json b/dojox/date/tests/tztests/tz_Africa-Bangui.json
new file mode 100644
index 0000000..88f9fe4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Bangui.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Bangui",
+	runTest: function(t){
+		var tz = "Africa/Bangui";
+		doh.checkDate({tzOffset: -74.3333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -74.3333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -74.3333333333333, tzAbbr: "LMT"}, -1830388461000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -1830388460000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Banjul.json b/dojox/date/tests/tztests/tz_Africa-Banjul.json
new file mode 100644
index 0000000..a9b9c46
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Banjul.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Africa-Banjul",
+	runTest: function(t){
+		var tz = "Africa/Banjul";
+		doh.checkDate({tzOffset: 66.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 66.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 66.6, tzAbbr: "LMT"}, -1830380005000, tz, 1);
+		doh.checkDate({tzOffset: 66.6, tzAbbr: "BMT"}, -1830380004000, tz, 1);
+		doh.checkDate({tzOffset: 66.6, tzAbbr: "BMT"}, -1104533605000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1104533604000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -189385201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -189385200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Bissau.json b/dojox/date/tests/tztests/tz_Africa-Bissau.json
new file mode 100644
index 0000000..a7e8039
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Bissau.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Africa-Bissau",
+	runTest: function(t){
+		var tz = "Africa/Bissau";
+		doh.checkDate({tzOffset: 62.3333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 62.3333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 62.3333333333333, tzAbbr: "LMT"}, -1849388261000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1849388260000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, 157769999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 157770000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Blantyre.json b/dojox/date/tests/tztests/tz_Africa-Blantyre.json
new file mode 100644
index 0000000..d00ccea
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Blantyre.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Blantyre",
+	runTest: function(t){
+		var tz = "Africa/Blantyre";
+		doh.checkDate({tzOffset: -140, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -140, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -140, tzAbbr: "LMT"}, -2109291601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -2109291600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Brazzaville.json b/dojox/date/tests/tztests/tz_Africa-Brazzaville.json
new file mode 100644
index 0000000..a9d6328
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Brazzaville.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Brazzaville",
+	runTest: function(t){
+		var tz = "Africa/Brazzaville";
+		doh.checkDate({tzOffset: -61.1333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -61.1333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -61.1333333333333, tzAbbr: "LMT"}, -1830387669000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -1830387668000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Bujumbura.json b/dojox/date/tests/tztests/tz_Africa-Bujumbura.json
new file mode 100644
index 0000000..0c79470
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Bujumbura.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Africa-Bujumbura",
+	runTest: function(t){
+		var tz = "Africa/Bujumbura";
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Cairo.json b/dojox/date/tests/tztests/tz_Africa-Cairo.json
new file mode 100644
index 0000000..40c4a16
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Cairo.json
@@ -0,0 +1,360 @@
+({
+	name: "date.timezone.Africa-Cairo",
+	runTest: function(t){
+		var tz = "Africa/Cairo";
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -929844001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -929844000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -923108401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -923108400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -906170401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -906170400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -892868401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -892868400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -875844001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -875844000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -857790001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -857790000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -844308001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -844308000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -825822001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -825822000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -812685601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -812685600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -794199601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -794199600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -779853601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -779853600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -762663601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -762663600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -399088801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -399088800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -386650801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -386650800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -368330401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -368330400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -355114801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -355114800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -336790801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -336790800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -323654401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -323654400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -305168401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -305168400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -292032001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -292032000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -273632401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -273632400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -260496001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -260496000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -242096401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -242096400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -228960001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -228960000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -210560401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -210560400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -197424001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -197424000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -178938001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -178938000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -165801601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -165801600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -147402001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -147402000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -134265601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -134265600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -115866001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -115866000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -102643201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -102643200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -84330001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -84330000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -71107201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -71107200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -52707601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -52707600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -39484801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -39484800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -21171601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -21171600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -7948801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -7948800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 10364399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 10364400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 23587199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 23587200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 41900399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 41900400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 55123199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 55123200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 73522799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 73522800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 86745599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 86745600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 105058799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 105058800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 118281599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 118281600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 136594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 136594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 149817599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 149817600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 168130799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 168130800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 181353599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 181353600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 199753199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 199753200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 212975999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 212976000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 231289199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 231289200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 244511999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 244512000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 262825199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 262825200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 276047999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 276048000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 294361199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 294361200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 307583999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 307584000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 325983599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 325983600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 339206399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 339206400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 357519599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 357519600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 370742399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 370742400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 396399599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 396399600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 402278399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 402278400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 426812399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 426812400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 433814399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 433814400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 452213999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 452214000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 465436799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 465436800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 483749999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 483750000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 496972799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 496972800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 515285999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 515286000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 528508799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 528508800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 546821999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 546822000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 560044799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 560044800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 578444399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 578444400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 591667199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 591667200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 610412399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 610412400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 623203199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 623203200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 641516399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 641516400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 654739199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 654739200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 673052399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 673052400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686275199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686275200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 704674799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 704674800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717897599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717897600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 736210799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 736210800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 749433599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 749433600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 767746799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 767746800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780969599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780969600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 799019999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 799020000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 812321999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 812322000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 830469599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 830469600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 843771599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 843771600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 861919199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 861919200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 875221199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 875221200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 893368799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 893368800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 906670799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 906670800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 925423199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 925423200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 938725199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 938725200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 956872799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 956872800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 970174799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 970174800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 988322399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 988322400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1001624399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1001624400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1019771999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1019772000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1033073999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1033074000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1051221599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1051221600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1064523599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1064523600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1083275999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1083276000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1096577999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1096578000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1114725599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1114725600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1128027599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1128027600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1146175199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1146175200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1158872399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1158872400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1177624799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1177624800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1189112399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1189112400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1209074399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1209074400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1219957199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1219957200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1240523999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1240524000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1253825999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1253826000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1272578399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1272578400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1285880399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1285880400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1304027999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1304028000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1317329999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1317330000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1335477599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1335477600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1348779599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1348779600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1366927199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1366927200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1380229199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1380229200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1398376799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1398376800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1411678799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1411678800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1429826399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1429826400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1443128399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1443128400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1461880799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1461880800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1475182799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1475182800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1493330399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1493330400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1506632399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1506632400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1524779999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1524780000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1538081999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1538082000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1556229599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1556229600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1569531599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1569531600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1587679199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1587679200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1600981199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1600981200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1619733599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1619733600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1633035599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1633035600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1651183199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1651183200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1664485199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1664485200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1682632799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1682632800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1695934799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1695934800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1714082399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1714082400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1727384399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1727384400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1745531999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1745532000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1758833999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1758834000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1776981599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1776981600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1790283599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1790283600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1809035999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1809036000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1822337999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1822338000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1840485599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1840485600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1853787599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1853787600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1871935199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1871935200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1885237199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1885237200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1903384799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1903384800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1916686799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1916686800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1934834399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1934834400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1948136399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1948136400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1966888799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1966888800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1980190799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1980190800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1998338399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1998338400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2011640399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2011640400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2029787999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2029788000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2043089999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2043090000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2061237599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2061237600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2074539599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2074539600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2092687199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2092687200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2105989199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2105989200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2124136799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2124136800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2137438799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2137438800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Casablanca.json b/dojox/date/tests/tztests/tz_Africa-Casablanca.json
new file mode 100644
index 0000000..eacb9fa
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Casablanca.json
@@ -0,0 +1,58 @@
+({
+	name: "date.timezone.Africa-Casablanca",
+	runTest: function(t){
+		var tz = "Africa/Casablanca";
+		doh.checkDate({tzOffset: 30.3333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 30.3333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 30.3333333333333, tzAbbr: "LMT"}, -1773012581000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1773012580000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -956361601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -956361600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -950490001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -950490000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -942019201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -942019200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -761187601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -761187600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -617241601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -617241600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -605149201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -605149200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -81432001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -81432000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -71110801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -71110800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 141263999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 141264000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 147221999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 147222000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 199756799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 199756800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 207701999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 207702000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 231292799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 231292800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 244249199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 244249200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 265507199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 265507200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 271033199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 271033200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 448243199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 448243200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 504917999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 504918000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1212278399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1212278400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1220223599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1220223600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1243814399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1243814400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1250809199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1250809200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Ceuta.json b/dojox/date/tests/tztests/tz_Africa-Ceuta.json
new file mode 100644
index 0000000..d90b8aa
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Ceuta.json
@@ -0,0 +1,262 @@
+({
+	name: "date.timezone.Africa-Ceuta",
+	runTest: function(t){
+		var tz = "Africa/Ceuta";
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1630112401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1630112400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1616810401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1616810400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1442451601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1442451600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1427677201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1427677200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1379293201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1379293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1364778001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1364778000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1348448401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1348448400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1333328401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1333328400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1316394001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1316394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1301274001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1301274000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -81432001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -81432000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -71110801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -71110800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 141263999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 141264000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 147221999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 147222000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 199756799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 199756800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 207701999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 207702000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 231292799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 231292800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 244249199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 244249200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 265507199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 265507200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 271033199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 271033200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 448243199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 448243200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Conakry.json b/dojox/date/tests/tztests/tz_Africa-Conakry.json
new file mode 100644
index 0000000..d1e8865
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Conakry.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Africa-Conakry",
+	runTest: function(t){
+		var tz = "Africa/Conakry";
+		doh.checkDate({tzOffset: 54.8666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 54.8666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 54.8666666666667, tzAbbr: "LMT"}, -1830380709000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1830380708000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1131235201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1131235200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -315615601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -315615600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Dakar.json b/dojox/date/tests/tztests/tz_Africa-Dakar.json
new file mode 100644
index 0000000..032b727
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Dakar.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Africa-Dakar",
+	runTest: function(t){
+		var tz = "Africa/Dakar";
+		doh.checkDate({tzOffset: 69.7333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 69.7333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 69.7333333333333, tzAbbr: "LMT"}, -1830379817000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1830379816000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -902098801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -902098800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Dar_es_Salaam.json b/dojox/date/tests/tztests/tz_Africa-Dar_es_Salaam.json
new file mode 100644
index 0000000..45815fd
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Dar_es_Salaam.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Africa-Dar_es_Salaam",
+	runTest: function(t){
+		var tz = "Africa/Dar_es_Salaam";
+		doh.checkDate({tzOffset: -157.133333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -157.133333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -157.133333333333, tzAbbr: "LMT"}, -1230777429000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1230777428000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -694321201000, tz, 1);
+		doh.checkDate({tzOffset: -164.75, tzAbbr: "BEAUT"}, -694321200000, tz, 1);
+		doh.checkDate({tzOffset: -164.75, tzAbbr: "BEAUT"}, -284006686000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -284006685000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Djibouti.json b/dojox/date/tests/tztests/tz_Africa-Djibouti.json
new file mode 100644
index 0000000..d6eb734
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Djibouti.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Djibouti",
+	runTest: function(t){
+		var tz = "Africa/Djibouti";
+		doh.checkDate({tzOffset: -172.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -172.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -172.6, tzAbbr: "LMT"}, -1846291957000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1846291956000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Douala.json b/dojox/date/tests/tztests/tz_Africa-Douala.json
new file mode 100644
index 0000000..0b65ea4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Douala.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Douala",
+	runTest: function(t){
+		var tz = "Africa/Douala";
+		doh.checkDate({tzOffset: -38.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -38.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -38.8, tzAbbr: "LMT"}, -1830386329000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -1830386328000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-El_Aaiun.json b/dojox/date/tests/tztests/tz_Africa-El_Aaiun.json
new file mode 100644
index 0000000..fcd1257
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-El_Aaiun.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Africa-El_Aaiun",
+	runTest: function(t){
+		var tz = "Africa/El_Aaiun";
+		doh.checkDate({tzOffset: 52.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 52.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 52.8, tzAbbr: "LMT"}, -1136070433000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1136070432000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, 198291599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 198291600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Freetown.json b/dojox/date/tests/tztests/tz_Africa-Freetown.json
new file mode 100644
index 0000000..fcb05ef
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Freetown.json
@@ -0,0 +1,72 @@
+({
+	name: "date.timezone.Africa-Freetown",
+	runTest: function(t){
+		var tz = "Africa/Freetown";
+		doh.checkDate({tzOffset: 53, tzAbbr: "FMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 53, tzAbbr: "FMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 53, tzAbbr: "FMT"}, -1785712021000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1785712020000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1091487601000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -1091487600000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -1080949201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1080949200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1059865201000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -1059865200000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -1049326801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1049326800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1028329201000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -1028329200000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -1017790801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1017790800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -996793201000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -996793200000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -986254801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -986254800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -965257201000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -965257200000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -954718801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -954718800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -933634801000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -933634800000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -923096401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -923096400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -902098801000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -902098800000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -891560401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -891560400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -870562801000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -870562800000, tz, 1);
+		doh.checkDate({tzOffset: 20, tzAbbr: "SLST"}, -860024401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -860024400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -410223601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WAT"}, -410223600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WAT"}, -397180801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -397180800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -389235601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -389235600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -365644801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -365644800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -357699601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -357699600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -334108801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -334108800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -326163601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -326163600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -302486401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -302486400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -294541201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -294541200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -270950401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -270950400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -263005201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -263005200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -239414401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -239414400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "SLST"}, -231469201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -231469200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Gaborone.json b/dojox/date/tests/tztests/tz_Africa-Gaborone.json
new file mode 100644
index 0000000..95bc027
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Gaborone.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Africa-Gaborone",
+	runTest: function(t){
+		var tz = "Africa/Gaborone";
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -829526401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, -829526400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, -813805201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -813805200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Harare.json b/dojox/date/tests/tztests/tz_Africa-Harare.json
new file mode 100644
index 0000000..f6d1629
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Harare.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Harare",
+	runTest: function(t){
+		var tz = "Africa/Harare";
+		doh.checkDate({tzOffset: -124.2, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -124.2, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -124.2, tzAbbr: "LMT"}, -2109290653000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -2109290652000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Johannesburg.json b/dojox/date/tests/tztests/tz_Africa-Johannesburg.json
new file mode 100644
index 0000000..613a317
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Johannesburg.json
@@ -0,0 +1,22 @@
+({
+	name: "date.timezone.Africa-Johannesburg",
+	runTest: function(t){
+		var tz = "Africa/Johannesburg";
+		doh.checkDate({tzOffset: -90, tzAbbr: "SAST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -90, tzAbbr: "SAST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -90, tzAbbr: "SAST"}, -2109288601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -2109288600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -860976001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SAST"}, -860976000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SAST"}, -845254801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -845254800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -829526401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SAST"}, -829526400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SAST"}, -813805201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -813805200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Kampala.json b/dojox/date/tests/tztests/tz_Africa-Kampala.json
new file mode 100644
index 0000000..211945e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Kampala.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.Africa-Kampala",
+	runTest: function(t){
+		var tz = "Africa/Kampala";
+		doh.checkDate({tzOffset: -129.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -129.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -129.666666666667, tzAbbr: "LMT"}, -1309745381000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1309745380000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1262314801000, tz, 1);
+		doh.checkDate({tzOffset: -150, tzAbbr: "BEAT"}, -1262314800000, tz, 1);
+		doh.checkDate({tzOffset: -150, tzAbbr: "BEAT"}, -694319401000, tz, 1);
+		doh.checkDate({tzOffset: -164.75, tzAbbr: "BEAUT"}, -694319400000, tz, 1);
+		doh.checkDate({tzOffset: -164.75, tzAbbr: "BEAUT"}, -410237086000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -410237085000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Khartoum.json b/dojox/date/tests/tztests/tz_Africa-Khartoum.json
new file mode 100644
index 0000000..1300ef6
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Khartoum.json
@@ -0,0 +1,80 @@
+({
+	name: "date.timezone.Africa-Khartoum",
+	runTest: function(t){
+		var tz = "Africa/Khartoum";
+		doh.checkDate({tzOffset: -130.133333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -130.133333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -130.133333333333, tzAbbr: "LMT"}, -1230775809000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -1230775808000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 10360799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 10360800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 24785999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 24786000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 41810399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 41810400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 56321999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 56322000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 73432799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 73432800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 87944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 87944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 104882399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 104882400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 119480399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 119480400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 136331999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 136332000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 151016399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 151016400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 167781599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 167781600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 182552399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 182552400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 199231199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 199231200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 214174799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 214174800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 230680799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 230680800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 245710799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 245710800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 262735199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 262735200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 277246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 277246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 294184799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 294184800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 308782799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 308782800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 325634399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 325634400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 340405199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 340405200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 357083999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 357084000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 371941199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 371941200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 388533599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 388533600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 403477199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 403477200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 419983199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 419983200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 435013199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 435013200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 452037599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 452037600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 466635599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 466635600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 483487199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 483487200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CAST"}, 498171599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 498171600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 947930399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 947930400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Kigali.json b/dojox/date/tests/tztests/tz_Africa-Kigali.json
new file mode 100644
index 0000000..b6feb15
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Kigali.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Kigali",
+	runTest: function(t){
+		var tz = "Africa/Kigali";
+		doh.checkDate({tzOffset: -120.266666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -120.266666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -120.266666666667, tzAbbr: "LMT"}, -1091498417000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -1091498416000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Kinshasa.json b/dojox/date/tests/tztests/tz_Africa-Kinshasa.json
new file mode 100644
index 0000000..202a59f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Kinshasa.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Africa-Kinshasa",
+	runTest: function(t){
+		var tz = "Africa/Kinshasa";
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Lagos.json b/dojox/date/tests/tztests/tz_Africa-Lagos.json
new file mode 100644
index 0000000..116e1ff
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Lagos.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Lagos",
+	runTest: function(t){
+		var tz = "Africa/Lagos";
+		doh.checkDate({tzOffset: -13.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -13.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -13.6, tzAbbr: "LMT"}, -1588464817000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -1588464816000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Libreville.json b/dojox/date/tests/tztests/tz_Africa-Libreville.json
new file mode 100644
index 0000000..dd94083
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Libreville.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Libreville",
+	runTest: function(t){
+		var tz = "Africa/Libreville";
+		doh.checkDate({tzOffset: -37.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -37.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -37.8, tzAbbr: "LMT"}, -1830386269000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -1830386268000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Lome.json b/dojox/date/tests/tztests/tz_Africa-Lome.json
new file mode 100644
index 0000000..1c4a499
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Lome.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Africa-Lome",
+	runTest: function(t){
+		var tz = "Africa/Lome";
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Luanda.json b/dojox/date/tests/tztests/tz_Africa-Luanda.json
new file mode 100644
index 0000000..532c51a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Luanda.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Luanda",
+	runTest: function(t){
+		var tz = "Africa/Luanda";
+		doh.checkDate({tzOffset: -52.0666666666667, tzAbbr: "AOT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -52.0666666666667, tzAbbr: "AOT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -52.0666666666667, tzAbbr: "AOT"}, -1849395125000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -1849395124000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Lubumbashi.json b/dojox/date/tests/tztests/tz_Africa-Lubumbashi.json
new file mode 100644
index 0000000..23b8eb7
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Lubumbashi.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Africa-Lubumbashi",
+	runTest: function(t){
+		var tz = "Africa/Lubumbashi";
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Lusaka.json b/dojox/date/tests/tztests/tz_Africa-Lusaka.json
new file mode 100644
index 0000000..157caa8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Lusaka.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Lusaka",
+	runTest: function(t){
+		var tz = "Africa/Lusaka";
+		doh.checkDate({tzOffset: -113.133333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -113.133333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -113.133333333333, tzAbbr: "LMT"}, -2109289989000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -2109289988000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Malabo.json b/dojox/date/tests/tztests/tz_Africa-Malabo.json
new file mode 100644
index 0000000..e1a587d
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Malabo.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Africa-Malabo",
+	runTest: function(t){
+		var tz = "Africa/Malabo";
+		doh.checkDate({tzOffset: -35.1333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -35.1333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -35.1333333333333, tzAbbr: "LMT"}, -1830386109000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1830386108000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -190857601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -190857600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Maputo.json b/dojox/date/tests/tztests/tz_Africa-Maputo.json
new file mode 100644
index 0000000..422c611
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Maputo.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Maputo",
+	runTest: function(t){
+		var tz = "Africa/Maputo";
+		doh.checkDate({tzOffset: -130.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -130.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -130.333333333333, tzAbbr: "LMT"}, -2109291021000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, -2109291020000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Maseru.json b/dojox/date/tests/tztests/tz_Africa-Maseru.json
new file mode 100644
index 0000000..b0471eb
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Maseru.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Africa-Maseru",
+	runTest: function(t){
+		var tz = "Africa/Maseru";
+		doh.checkDate({tzOffset: -110, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -110, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -110, tzAbbr: "LMT"}, -2109289801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -2109289800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -829526401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SAST"}, -829526400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SAST"}, -813805201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -813805200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Mbabane.json b/dojox/date/tests/tztests/tz_Africa-Mbabane.json
new file mode 100644
index 0000000..a32973a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Mbabane.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Mbabane",
+	runTest: function(t){
+		var tz = "Africa/Mbabane";
+		doh.checkDate({tzOffset: -124.4, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -124.4, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -124.4, tzAbbr: "LMT"}, -2109290665000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -2109290664000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Mogadishu.json b/dojox/date/tests/tztests/tz_Africa-Mogadishu.json
new file mode 100644
index 0000000..b56dfa1
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Mogadishu.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Africa-Mogadishu",
+	runTest: function(t){
+		var tz = "Africa/Mogadishu";
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1230778801000, tz, 1);
+		doh.checkDate({tzOffset: -150, tzAbbr: "BEAT"}, -1230778800000, tz, 1);
+		doh.checkDate({tzOffset: -150, tzAbbr: "BEAT"}, -410236201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -410236200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Monrovia.json b/dojox/date/tests/tztests/tz_Africa-Monrovia.json
new file mode 100644
index 0000000..61f240f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Monrovia.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Africa-Monrovia",
+	runTest: function(t){
+		var tz = "Africa/Monrovia";
+		doh.checkDate({tzOffset: 43.1333333333333, tzAbbr: "MMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 43.1333333333333, tzAbbr: "MMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 43.1333333333333, tzAbbr: "MMT"}, -1604359013000, tz, 1);
+		doh.checkDate({tzOffset: 44.5, tzAbbr: "LRT"}, -1604359012000, tz, 1);
+		doh.checkDate({tzOffset: 44.5, tzAbbr: "LRT"}, 73529069000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 73529070000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Nairobi.json b/dojox/date/tests/tztests/tz_Africa-Nairobi.json
new file mode 100644
index 0000000..167d08e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Nairobi.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.Africa-Nairobi",
+	runTest: function(t){
+		var tz = "Africa/Nairobi";
+		doh.checkDate({tzOffset: -147.266666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -147.266666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -147.266666666667, tzAbbr: "LMT"}, -1309746437000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1309746436000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1262314801000, tz, 1);
+		doh.checkDate({tzOffset: -150, tzAbbr: "BEAT"}, -1262314800000, tz, 1);
+		doh.checkDate({tzOffset: -150, tzAbbr: "BEAT"}, -946780201000, tz, 1);
+		doh.checkDate({tzOffset: -164.75, tzAbbr: "BEAUT"}, -946780200000, tz, 1);
+		doh.checkDate({tzOffset: -164.75, tzAbbr: "BEAUT"}, -315629086000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -315629085000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Ndjamena.json b/dojox/date/tests/tztests/tz_Africa-Ndjamena.json
new file mode 100644
index 0000000..c973813
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Ndjamena.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Africa-Ndjamena",
+	runTest: function(t){
+		var tz = "Africa/Ndjamena";
+		doh.checkDate({tzOffset: -60.2, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60.2, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60.2, tzAbbr: "LMT"}, -1830387613000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -1830387612000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 308703599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 308703600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 321314399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 321314400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Niamey.json b/dojox/date/tests/tztests/tz_Africa-Niamey.json
new file mode 100644
index 0000000..f0bfc42
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Niamey.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Africa-Niamey",
+	runTest: function(t){
+		var tz = "Africa/Niamey";
+		doh.checkDate({tzOffset: -8.46666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -8.46666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -8.46666666666667, tzAbbr: "LMT"}, -1830384509000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1830384508000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1131231601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1131231600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -315619201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -315619200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Nouakchott.json b/dojox/date/tests/tztests/tz_Africa-Nouakchott.json
new file mode 100644
index 0000000..c49fa31
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Nouakchott.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Africa-Nouakchott",
+	runTest: function(t){
+		var tz = "Africa/Nouakchott";
+		doh.checkDate({tzOffset: 63.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 63.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 63.8, tzAbbr: "LMT"}, -1830380173000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1830380172000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1131235201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -1131235200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "WAT"}, -286930801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -286930800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Ouagadougou.json b/dojox/date/tests/tztests/tz_Africa-Ouagadougou.json
new file mode 100644
index 0000000..9ee15e8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Ouagadougou.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Ouagadougou",
+	runTest: function(t){
+		var tz = "Africa/Ouagadougou";
+		doh.checkDate({tzOffset: 6.06666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 6.06666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 6.06666666666667, tzAbbr: "LMT"}, -1830383637000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1830383636000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Porto-Novo.json b/dojox/date/tests/tztests/tz_Africa-Porto-Novo.json
new file mode 100644
index 0000000..3d3d378
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Porto-Novo.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Africa-Porto-Novo",
+	runTest: function(t){
+		var tz = "Africa/Porto-Novo";
+		doh.checkDate({tzOffset: -10.4666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -10.4666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -10.4666666666667, tzAbbr: "LMT"}, -1830384629000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1830384628000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1131235201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, -1131235200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Sao_Tome.json b/dojox/date/tests/tztests/tz_Africa-Sao_Tome.json
new file mode 100644
index 0000000..142a48a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Sao_Tome.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Africa-Sao_Tome",
+	runTest: function(t){
+		var tz = "Africa/Sao_Tome";
+		doh.checkDate({tzOffset: 36.5333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 36.5333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 36.5333333333333, tzAbbr: "LMT"}, -1830381809000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1830381808000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Tripoli.json b/dojox/date/tests/tztests/tz_Africa-Tripoli.json
new file mode 100644
index 0000000..e77b844
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Tripoli.json
@@ -0,0 +1,70 @@
+({
+	name: "date.timezone.Africa-Tripoli",
+	runTest: function(t){
+		var tz = "Africa/Tripoli";
+		doh.checkDate({tzOffset: -52.7333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -52.7333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -52.7333333333333, tzAbbr: "LMT"}, -1577926365000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1577926364000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -574902001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -574902000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -568087201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -568087200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -512175601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -512175600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -504928801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -504928800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -449888401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -449888400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -441856801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -441856800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -347158801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -347158800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 378683999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 378684000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386463599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386463600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 402271199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 402271200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417999599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417999600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433807199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433807200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449621999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449622000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465429599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465429600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481589999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481590000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496965599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496965600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512953199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512953200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528674399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528674400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 544229999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 544230000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 560037599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 560037600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575852399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575852400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591659999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591660000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 607388399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 607388400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 623195999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 623196000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 641775599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 641775600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 844034399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 844034400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 860108399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 860108400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 875915999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 875916000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Tunis.json b/dojox/date/tests/tztests/tz_Africa-Tunis.json
new file mode 100644
index 0000000..5933a0a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Tunis.json
@@ -0,0 +1,190 @@
+({
+	name: "date.timezone.Africa-Tunis",
+	runTest: function(t){
+		var tz = "Africa/Tunis";
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -1855958962000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1855958961000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -969242401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -969242400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -950493601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -950493600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -941940001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -941940000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -891136801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -891136800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -877827601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -842918401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -842918400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -842223601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -842223600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828230401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828230400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796269601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796269600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -766634401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -766634400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 231202799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 231202800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 243903599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 243903600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 262825199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 262825200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 276044399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 276044400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 581122799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 581122800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 641516399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 641516400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654649199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654649200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1114901999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1114902000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1128038399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1128038400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Africa-Windhoek.json b/dojox/date/tests/tztests/tz_Africa-Windhoek.json
new file mode 100644
index 0000000..abb809f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Africa-Windhoek.json
@@ -0,0 +1,196 @@
+({
+	name: "date.timezone.Africa-Windhoek",
+	runTest: function(t){
+		var tz = "Africa/Windhoek";
+		doh.checkDate({tzOffset: -90, tzAbbr: "SWAT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -90, tzAbbr: "SWAT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -90, tzAbbr: "SWAT"}, -2109288601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -2109288600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -860976001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SAST"}, -860976000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SAST"}, -845254801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, -845254800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "SAST"}, 637970399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 637970400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CAT"}, 765323999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 765324000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 778640399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 778640400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 796780799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 796780800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 810089999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 810090000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 828835199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 828835200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 841539599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 841539600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 860284799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 860284800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 873593999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 873594000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 891734399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 891734400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 905043599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 905043600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 923183999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 923184000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 936493199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 936493200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 954633599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 954633600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 967942799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 967942800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 986083199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 986083200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 999392399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 999392400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1018137599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1018137600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1030841999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1030842000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1049587199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1049587200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1062896399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1062896400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1081036799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1081036800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1094345999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1094346000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1112486399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1112486400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1125795599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1125795600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1143935999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1143936000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1157245199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1157245200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1175385599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1175385600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1188694799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1188694800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1207439999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1207440000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1220749199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1220749200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1238889599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1238889600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1252198799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1252198800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1270339199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1270339200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1283648399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1283648400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1301788799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1301788800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1315097999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1315098000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1333238399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1333238400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1346547599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1346547600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1365292799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1365292800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1377997199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1377997200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1396742399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1396742400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1410051599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1410051600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1428191999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1428192000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1441501199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1441501200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1459641599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1459641600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1472950799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1472950800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1491091199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1491091200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1504400399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1504400400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1522540799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1522540800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1535849999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1535850000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1554595199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1554595200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1567299599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1567299600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1586044799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1586044800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1599353999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1599354000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1617494399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1617494400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1630803599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1630803600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1648943999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1648944000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1662253199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1662253200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1680393599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1680393600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1693702799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1693702800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1712447999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1712448000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1725152399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1725152400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1743897599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1743897600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1757206799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1757206800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1775347199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1775347200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1788656399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1788656400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1806796799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1806796800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1820105999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1820106000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1838246399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1838246400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1851555599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1851555600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1869695999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1869696000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1883005199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1883005200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1901750399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1901750400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1914454799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1914454800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1933199999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1933200000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1946509199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1946509200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1964649599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1964649600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1977958799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1977958800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1996099199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1996099200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2009408399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 2009408400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 2027548799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2027548800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2040857999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 2040858000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 2058998399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2058998400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2072307599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 2072307600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 2091052799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2091052800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2104361999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 2104362000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 2122502399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2122502400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 2135811599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 2135811600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WAST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Adak.json b/dojox/date/tests/tztests/tz_America-Adak.json
new file mode 100644
index 0000000..be20f1e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Adak.json
@@ -0,0 +1,298 @@
+({
+	name: "date.timezone.America-Adak",
+	runTest: function(t){
+		var tz = "America/Adak";
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -880196401000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "NWT"}, -880196400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "NWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "NPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "NPT"}, -765374401000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -765374400000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -86878801000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, -86878800000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, -21466801000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, -21466800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, -5745601000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, -5745600000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 9982799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 9982800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 25703999000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 25704000000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 41432399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 41432400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 57758399000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 57758400000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 73486799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 73486800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 89207999000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 89208000000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 104936399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 104936400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 120657599000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 120657600000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 126709199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 126709200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 152107199000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 152107200000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 162392399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 162392400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 183556799000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 183556800000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 199285199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 199285200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 215611199000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 215611200000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 230734799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 230734800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 247060799000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 247060800000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 262789199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 262789200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 278510399000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 278510400000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 294238799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 294238800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 309959999000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 309960000000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 325688399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 325688400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 341409599000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 341409600000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 357137999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 357138000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 372859199000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 372859200000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 388587599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 388587600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 404913599000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 404913600000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 420037199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 420037200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 436363199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 436363200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 439034399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 439034400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 452087999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 452088000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 467809199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 467809200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 483537599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 483537600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 499258799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 499258800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 514987199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 514987200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 530708399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 530708400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 544622399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 544622400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 562157999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 562158000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 576071999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 576072000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 594212399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 594212400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 607521599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 607521600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 625661999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 625662000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 638971199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 638971200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 657111599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 657111600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 671025599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 671025600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 688561199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 688561200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 702475199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 702475200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 720010799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 720010800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 733924799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 733924800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 752065199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 752065200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 765374399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 765374400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 783514799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 783514800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 796823999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 796824000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 814964399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 814964400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 828878399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 828878400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 846413999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 846414000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 860327999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 860328000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 877863599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 877863600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 891777599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 891777600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 909313199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 909313200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 923227199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 923227200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 941367599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 941367600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 954676799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 954676800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 972817199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 972817200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 986126399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 986126400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1004266799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1004266800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1018180799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1018180800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1035716399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1035716400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1049630399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1049630400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1067165999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1067166000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1081079999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1081080000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1099220399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1099220400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1112529599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1112529600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1130669999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1130670000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1143979199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1143979200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1162119599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1162119600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1173614399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1173614400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1194173999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1194174000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1205063999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1205064000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1225623599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1225623600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1236513599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1236513600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1257073199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1257073200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1268567999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1268568000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1289127599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1289127600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1300017599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1300017600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1320577199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1320577200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1331467199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1331467200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1352026799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1352026800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1362916799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1362916800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1383476399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1383476400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1394366399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1394366400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1414925999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1414926000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1425815999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1425816000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1446375599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1446375600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1457870399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1457870400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1478429999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1478430000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1489319999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1489320000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1509879599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1509879600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1520769599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1520769600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1541329199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1541329200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1552219199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1552219200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1572778799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1572778800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1583668799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1583668800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1604228399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1604228400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1615723199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1615723200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1636282799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1636282800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1647172799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1647172800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1667732399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1667732400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1678622399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1678622400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1699181999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1699182000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1710071999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1710072000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1730631599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1730631600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1741521599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1741521600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1762081199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1762081200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1772971199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1772971200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1793530799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1793530800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1805025599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1805025600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1825585199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1825585200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1836475199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1836475200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1857034799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1857034800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1867924799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1867924800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1888484399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1888484400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1899374399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1899374400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1919933999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1919934000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1930823999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1930824000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1951383599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1951383600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1962878399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1962878400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1983437999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1983438000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1994327999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1994328000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 2014887599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 2014887600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 2025777599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 2025777600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 2046337199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 2046337200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 2057227199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 2057227200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 2077786799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 2077786800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 2088676799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 2088676800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 2109236399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 2109236400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 2120126399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 2120126400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 2140685999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 2140686000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HAST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 540, tzAbbr: "HADT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Anchorage.json b/dojox/date/tests/tztests/tz_America-Anchorage.json
new file mode 100644
index 0000000..9503ce4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Anchorage.json
@@ -0,0 +1,298 @@
+({
+	name: "date.timezone.America-Anchorage",
+	runTest: function(t){
+		var tz = "America/Anchorage";
+		doh.checkDate({tzOffset: 600, tzAbbr: "CAT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CAT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CAT"}, -880200001000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "CAWT"}, -880200000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "CAWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "CAPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "CAPT"}, -765378001000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CAT"}, -765378000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CAT"}, -86882401000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, -86882400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, -21470401000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, -21470400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, -5749201000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, -5749200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 9979199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 9979200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 25700399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 25700400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 41428799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 41428800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 57754799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 57754800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 73483199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 73483200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 89204399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 89204400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 104932799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 104932800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 120653999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 120654000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 126705599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 126705600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 152103599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 152103600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 162388799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 162388800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 183553199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 183553200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 199281599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 199281600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 215607599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 215607600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 230731199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 230731200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 247057199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 247057200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 262785599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 262785600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 278506799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 278506800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 294235199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 294235200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 309956399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 309956400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 325684799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 325684800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 341405999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 341406000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 357134399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 357134400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 372855599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 372855600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 388583999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 388584000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 404909999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 404910000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "AHST"}, 420033599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 420033600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AHDT"}, 436359599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 436359600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 439030799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 439030800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 452084399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 452084400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 467805599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 467805600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 483533999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 483534000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 499255199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 499255200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 514983599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 514983600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 530704799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 530704800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 544618799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 544618800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 562154399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 562154400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 576068399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 576068400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 594208799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 594208800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 607517999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 607518000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 625658399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 625658400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 638967599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 638967600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 657107999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 657108000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 671021999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 671022000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 688557599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 688557600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 702471599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 702471600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 720007199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 720007200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 733921199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 733921200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 752061599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 752061600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 765370799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 765370800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 783511199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 783511200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 796820399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 796820400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 814960799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 814960800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 828874799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 828874800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 846410399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 846410400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 860324399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 860324400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 877859999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 877860000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 891773999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 891774000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 909309599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 909309600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 923223599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 923223600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 941363999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 941364000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 954673199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 954673200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 972813599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 972813600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 986122799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 986122800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1004263199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1004263200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1018177199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1018177200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1035712799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1035712800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1049626799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1049626800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1067162399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1067162400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1081076399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1081076400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1099216799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1099216800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1112525999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1112526000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1130666399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1130666400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1143975599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1143975600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1162115999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1162116000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1173610799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1173610800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1194170399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1194170400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1205060399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1205060400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1225619999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1225620000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1236509999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1236510000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1257069599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1257069600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1268564399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1268564400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1289123999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1289124000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1300013999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1300014000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1320573599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1320573600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1331463599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1331463600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1352023199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1352023200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1362913199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1362913200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1383472799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1383472800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1394362799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1394362800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1414922399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1414922400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1425812399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1425812400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1446371999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1446372000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1457866799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1457866800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1478426399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1478426400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1489316399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1489316400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1509875999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1509876000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1520765999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1520766000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1541325599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1541325600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1552215599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1552215600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1572775199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1572775200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1583665199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1583665200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1604224799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1604224800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1615719599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1615719600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1636279199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1636279200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1647169199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1647169200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1667728799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1667728800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1678618799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1678618800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1699178399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1699178400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1710068399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1710068400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1730627999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1730628000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1741517999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1741518000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1762077599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1762077600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1772967599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1772967600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1793527199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1793527200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1805021999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1805022000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1825581599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1825581600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1836471599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1836471600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1857031199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1857031200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1867921199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1867921200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1888480799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1888480800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1899370799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1899370800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1919930399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1919930400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1930820399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1930820400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1951379999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1951380000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1962874799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1962874800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1983434399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1983434400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1994324399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1994324400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2014883999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2014884000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2025773999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2025774000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2046333599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2046333600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2057223599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2057223600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2077783199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2077783200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2088673199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2088673200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2109232799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2109232800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2120122799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2120122800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2140682399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2140682400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Anguilla.json b/dojox/date/tests/tztests/tz_America-Anguilla.json
new file mode 100644
index 0000000..4302b51
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Anguilla.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-Anguilla",
+	runTest: function(t){
+		var tz = "America/Anguilla";
+		doh.checkDate({tzOffset: 252.266666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 252.266666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 252.266666666667, tzAbbr: "LMT"}, -1825098465000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1825098464000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Antigua.json b/dojox/date/tests/tztests/tz_America-Antigua.json
new file mode 100644
index 0000000..ca40ee2
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Antigua.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.America-Antigua",
+	runTest: function(t){
+		var tz = "America/Antigua";
+		doh.checkDate({tzOffset: 247.2, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 247.2, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 247.2, tzAbbr: "LMT"}, -1825098769000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1825098768000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -599598001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -599598000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Araguaina.json b/dojox/date/tests/tztests/tz_America-Araguaina.json
new file mode 100644
index 0000000..5a9ec81
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Araguaina.json
@@ -0,0 +1,110 @@
+({
+	name: "date.timezone.America-Araguaina",
+	runTest: function(t){
+		var tz = "America/Araguaina";
+		doh.checkDate({tzOffset: 192.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 192.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 192.8, tzAbbr: "LMT"}, -1767214033000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1767214032000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1206957601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1206957600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1191362401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1191362400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1175374801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1175374800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1159826401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1159826400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -633819601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -633819600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -622069201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -622069200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -602283601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -602283600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -591832801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -591832800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -570747601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -570747600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -560210401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -560210400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -539125201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -539125200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -531352801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -531352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -191365201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -191365200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -184197601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -184197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -155163601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -155163600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -150069601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -150069600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -128898001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -128898000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -121125601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -121125600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -99954001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -99954000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -89589601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -89589600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -68418001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -68418000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -57967201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -57967200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 499748399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 499748400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 511235999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 511236000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 530593199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 530593200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 540266399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 540266400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 562129199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 562129200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 571197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 571197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 592973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 592974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 602042399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 602042400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 634701599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 634701600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 813725999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 813726000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 824003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 824004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 844570799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 844570800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 856058399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 856058400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 876106799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 876106800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 888717599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 888717600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 908074799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 908074800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 919562399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 919562400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 951616799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 951616800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 970973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 970974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 982461599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 982461600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1003028399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1003028400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1013911199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1013911200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1036292399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1036292400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1045360799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1045360800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-Buenos_Aires.json b/dojox/date/tests/tztests/tz_America-Argentina-Buenos_Aires.json
new file mode 100644
index 0000000..05f82ed
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-Buenos_Aires.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.America-Argentina-Buenos_Aires",
+	runTest: function(t){
+		var tz = "America/Argentina/Buenos_Aires";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 667965599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 667965600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 687927599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 687927600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 699415199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 699415200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 719377199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 719377200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 731469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 731469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1205632799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1205632800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1224385199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1224385200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1237082399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1237082400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1255834799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1255834800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1269136799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1269136800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1287284399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1287284400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1300586399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1300586400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1318733999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1318734000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1332035999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1332036000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1350788399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1350788400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1363485599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1363485600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1382237999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1382238000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1394935199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1394935200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1413687599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1413687600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1426384799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1426384800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1445137199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1445137200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1458439199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1458439200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1476586799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1476586800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1489888799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1489888800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1508036399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1508036400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1521338399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1521338400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1540090799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1540090800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1552787999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1552788000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1571540399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1571540400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1584237599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1584237600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1602989999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1602990000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1616291999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1616292000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1634439599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1634439600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1647741599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1647741600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1665889199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1665889200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1679191199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1679191200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1697338799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1697338800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1710640799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1710640800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1729393199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1729393200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1742090399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1742090400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1760842799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1760842800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1773539999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1773540000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1792292399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1792292400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1805594399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1805594400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1823741999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1823742000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1837043999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1837044000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1855191599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1855191600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1868493599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1868493600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1887245999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1887246000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1899943199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1899943200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1918695599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1918695600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1931392799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1931392800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1950145199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1950145200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1963447199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1963447200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1981594799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1981594800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1994896799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1994896800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2013044399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2013044400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2026346399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2026346400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2044493999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2044494000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2057795999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2057796000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2076548399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2076548400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2089245599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2089245600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2107997999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2107998000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2120695199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2120695200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2139447599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2139447600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-Catamarca.json b/dojox/date/tests/tztests/tz_America-Argentina-Catamarca.json
new file mode 100644
index 0000000..0d66ff6
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-Catamarca.json
@@ -0,0 +1,132 @@
+({
+	name: "date.timezone.America-Argentina-Catamarca",
+	runTest: function(t){
+		var tz = "America/Argentina/Catamarca";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 667965599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 667965600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 687931199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 687931200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 699415199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 699415200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 719377199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 719377200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 731469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 731469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1086058799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1086058800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1087703999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1087704000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1205632799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1205632800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-Cordoba.json b/dojox/date/tests/tztests/tz_America-Argentina-Cordoba.json
new file mode 100644
index 0000000..e6fb563
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-Cordoba.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.America-Argentina-Cordoba",
+	runTest: function(t){
+		var tz = "America/Argentina/Cordoba";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 667965599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 667965600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 687931199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 687931200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 699415199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 699415200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 719377199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 719377200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 731469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 731469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1205632799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1205632800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1224385199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1224385200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1237082399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1237082400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1255834799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1255834800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1269136799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1269136800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1287284399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1287284400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1300586399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1300586400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1318733999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1318734000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1332035999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1332036000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1350788399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1350788400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1363485599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1363485600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1382237999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1382238000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1394935199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1394935200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1413687599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1413687600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1426384799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1426384800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1445137199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1445137200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1458439199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1458439200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1476586799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1476586800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1489888799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1489888800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1508036399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1508036400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1521338399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1521338400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1540090799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1540090800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1552787999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1552788000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1571540399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1571540400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1584237599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1584237600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1602989999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1602990000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1616291999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1616292000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1634439599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1634439600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1647741599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1647741600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1665889199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1665889200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1679191199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1679191200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1697338799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1697338800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1710640799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1710640800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1729393199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1729393200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1742090399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1742090400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1760842799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1760842800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1773539999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1773540000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1792292399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1792292400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1805594399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1805594400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1823741999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1823742000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1837043999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1837044000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1855191599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1855191600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1868493599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1868493600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1887245999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1887246000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1899943199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1899943200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1918695599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1918695600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1931392799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1931392800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1950145199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1950145200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1963447199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1963447200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1981594799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1981594800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1994896799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1994896800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2013044399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2013044400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2026346399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2026346400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2044493999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2044494000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2057795999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2057796000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2076548399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2076548400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2089245599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2089245600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2107997999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2107998000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2120695199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2120695200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2139447599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2139447600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-Jujuy.json b/dojox/date/tests/tztests/tz_America-Argentina-Jujuy.json
new file mode 100644
index 0000000..b980fda
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-Jujuy.json
@@ -0,0 +1,128 @@
+({
+	name: "date.timezone.America-Argentina-Jujuy",
+	runTest: function(t){
+		var tz = "America/Argentina/Jujuy";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 657086399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 657086400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 669178799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 669178800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 686721599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 686721600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 699415199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 699415200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 719377199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 719377200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 731469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 731469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1205632799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1205632800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-La_Rioja.json b/dojox/date/tests/tztests/tz_America-Argentina-La_Rioja.json
new file mode 100644
index 0000000..23efd3c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-La_Rioja.json
@@ -0,0 +1,134 @@
+({
+	name: "date.timezone.America-Argentina-La_Rioja",
+	runTest: function(t){
+		var tz = "America/Argentina/La_Rioja";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 667792799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 667792800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 673588799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 673588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 687927599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 687927600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 699415199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 699415200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 719377199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 719377200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 731469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 731469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1086058799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1086058800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1087703999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1087704000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1205632799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1205632800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-Mendoza.json b/dojox/date/tests/tztests/tz_America-Argentina-Mendoza.json
new file mode 100644
index 0000000..9fa3f27
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-Mendoza.json
@@ -0,0 +1,132 @@
+({
+	name: "date.timezone.America-Argentina-Mendoza",
+	runTest: function(t){
+		var tz = "America/Argentina/Mendoza";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 655963199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 655963200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 667796399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 667796400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 687499199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 687499200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 699418799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 699418800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 719380799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 719380800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 731469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 731469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1085281199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1085281200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1096171199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1096171200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1205632799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1205632800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-Rio_Gallegos.json b/dojox/date/tests/tztests/tz_America-Argentina-Rio_Gallegos.json
new file mode 100644
index 0000000..2d4064c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-Rio_Gallegos.json
@@ -0,0 +1,132 @@
+({
+	name: "date.timezone.America-Argentina-Rio_Gallegos",
+	runTest: function(t){
+		var tz = "America/Argentina/Rio_Gallegos";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 667965599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 667965600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 687927599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 687927600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 699415199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 699415200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 719377199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 719377200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 731469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 731469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1086058799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1086058800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1087703999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1087704000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1205632799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1205632800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-Salta.json b/dojox/date/tests/tztests/tz_America-Argentina-Salta.json
new file mode 100644
index 0000000..9c3b569
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-Salta.json
@@ -0,0 +1,128 @@
+({
+	name: "date.timezone.America-Argentina-Salta",
+	runTest: function(t){
+		var tz = "America/Argentina/Salta";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 667965599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 667965600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 687931199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 687931200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 699415199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 699415200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 719377199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 719377200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 731469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 731469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1205632799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1205632800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-San_Juan.json b/dojox/date/tests/tztests/tz_America-Argentina-San_Juan.json
new file mode 100644
index 0000000..e68c883
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-San_Juan.json
@@ -0,0 +1,134 @@
+({
+	name: "date.timezone.America-Argentina-San_Juan",
+	runTest: function(t){
+		var tz = "America/Argentina/San_Juan";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 667792799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 667792800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 673588799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 673588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 687927599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 687927600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 699415199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 699415200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 719377199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 719377200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 731469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 731469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1085972399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1085972400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1090727999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1090728000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1205632799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1205632800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-San_Luis.json b/dojox/date/tests/tztests/tz_America-Argentina-San_Luis.json
new file mode 100644
index 0000000..9df0edb
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-San_Luis.json
@@ -0,0 +1,242 @@
+({
+	name: "date.timezone.America-Argentina-San_Luis",
+	runTest: function(t){
+		var tz = "America/Argentina/San_Luis";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 637379999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 637380000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 655963199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 655963200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 667796399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 667796400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 675748799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 675748800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1085972399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1085972400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1090727999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1090728000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1200880799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1200880800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1237085999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1237086000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1255838399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1255838400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1269140399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1269140400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1287287999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1287288000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1300589999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1300590000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1318737599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1318737600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1332039599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1332039600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1350791999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1350792000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1363489199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1363489200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1382241599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1382241600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1394938799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1394938800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1413691199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1413691200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1426388399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1426388400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1445140799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1445140800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1458442799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1458442800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1476590399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1476590400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1489892399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1489892400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1508039999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1508040000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1521341999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1521342000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1540094399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1540094400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1552791599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1552791600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1571543999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1571544000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1584241199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1584241200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1602993599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1602993600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1616295599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1616295600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1634443199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1634443200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1647745199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1647745200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1665892799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1665892800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1679194799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1679194800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1697342399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1697342400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1710644399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1710644400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1729396799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1729396800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1742093999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1742094000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1760846399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1760846400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1773543599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1773543600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1792295999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1792296000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1805597999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1805598000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1823745599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1823745600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1837047599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1837047600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1855195199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1855195200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1868497199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1868497200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1887249599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1887249600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1899946799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1899946800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1918699199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1918699200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1931396399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1931396400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1950148799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1950148800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1963450799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1963450800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1981598399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1981598400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 1994900399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1994900400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 2013047999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 2013048000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 2026349999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 2026350000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 2044497599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 2044497600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 2057799599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 2057799600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 2076551999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 2076552000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 2089249199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 2089249200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 2108001599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 2108001600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 2120698799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 2120698800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 2139451199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 2139451200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WARST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-Tucuman.json b/dojox/date/tests/tztests/tz_America-Argentina-Tucuman.json
new file mode 100644
index 0000000..1cfa119
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-Tucuman.json
@@ -0,0 +1,250 @@
+({
+	name: "date.timezone.America-Argentina-Tucuman",
+	runTest: function(t){
+		var tz = "America/Argentina/Tucuman";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 667965599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 667965600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 687931199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 687931200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 699415199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 699415200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 719377199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 719377200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 731469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 731469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1086058799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1086058800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1087099199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1087099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1205632799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1205632800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1224385199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1224385200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1237082399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1237082400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1255834799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1255834800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1269136799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1269136800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1287284399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1287284400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1300586399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1300586400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1318733999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1318734000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1332035999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1332036000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1350788399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1350788400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1363485599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1363485600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1382237999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1382238000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1394935199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1394935200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1413687599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1413687600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1426384799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1426384800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1445137199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1445137200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1458439199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1458439200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1476586799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1476586800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1489888799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1489888800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1508036399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1508036400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1521338399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1521338400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1540090799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1540090800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1552787999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1552788000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1571540399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1571540400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1584237599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1584237600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1602989999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1602990000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1616291999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1616292000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1634439599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1634439600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1647741599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1647741600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1665889199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1665889200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1679191199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1679191200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1697338799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1697338800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1710640799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1710640800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1729393199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1729393200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1742090399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1742090400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1760842799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1760842800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1773539999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1773540000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1792292399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1792292400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1805594399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1805594400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1823741999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1823742000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1837043999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1837044000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1855191599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1855191600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1868493599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1868493600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1887245999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1887246000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1899943199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1899943200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1918695599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1918695600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1931392799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1931392800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1950145199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1950145200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1963447199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1963447200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1981594799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1981594800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1994896799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1994896800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2013044399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2013044400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2026346399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2026346400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2044493999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2044494000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2057795999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2057796000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2076548399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2076548400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2089245599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2089245600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2107997999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2107998000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2120695199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2120695200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2139447599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2139447600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Argentina-Ushuaia.json b/dojox/date/tests/tztests/tz_America-Argentina-Ushuaia.json
new file mode 100644
index 0000000..baa1c51
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Argentina-Ushuaia.json
@@ -0,0 +1,132 @@
+({
+	name: "date.timezone.America-Argentina-Ushuaia",
+	runTest: function(t){
+		var tz = "America/Argentina/Ushuaia";
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 256.8, tzAbbr: "CMT"}, -1567453393000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1567453392000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1233432001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1233432000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1222981201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1222981200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1205956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1205956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1194037201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1194037200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1172865601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1172865600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1162501201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1162501200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1141329601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1141329600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1130965201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1130965200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1109793601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1109793600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1099429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1099429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1078257601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1078257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1067806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1067806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1046635201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1046635200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1036270801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1036270800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1015099201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1015099200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -1004734801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -1004734800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -983563201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -983563200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -973198801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -973198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -952027201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -952027200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -941576401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -941576400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -931032001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -931032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -900882001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -900882000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -890337601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -890337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -833749201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -833749200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -827265601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -827265600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -752274001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -752274000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -733780801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -733780800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -197326801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -197326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -190843201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -190843200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -164491201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -164491200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 596948399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 596948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 605066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 605066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 667965599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 667965600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 687927599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 687927600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 699415199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 699415200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 719377199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 719377200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 731469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 731469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, 952052399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 952052400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1085885999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1085886000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "WART"}, 1087703999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1087704000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1198983599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1198983600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 1205632799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1205632800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Aruba.json b/dojox/date/tests/tztests/tz_America-Aruba.json
new file mode 100644
index 0000000..8f2c798
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Aruba.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.America-Aruba",
+	runTest: function(t){
+		var tz = "America/Aruba";
+		doh.checkDate({tzOffset: 280.4, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 280.4, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 280.4, tzAbbr: "LMT"}, -1826738377000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "ANT"}, -1826738376000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "ANT"}, -157750201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -157750200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Asuncion.json b/dojox/date/tests/tztests/tz_America-Asuncion.json
new file mode 100644
index 0000000..5d74c55
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Asuncion.json
@@ -0,0 +1,268 @@
+({
+	name: "date.timezone.America-Asuncion",
+	runTest: function(t){
+		var tz = "America/Asuncion";
+		doh.checkDate({tzOffset: 230.666666666667, tzAbbr: "AMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 230.666666666667, tzAbbr: "AMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 230.666666666667, tzAbbr: "AMT"}, -1206389361000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, -1206389360000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 86759999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYT"}, 86760000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYT"}, 134017199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 134017200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 181367999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 181368000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 194497199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 194497200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 212990399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 212990400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 226033199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 226033200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 244526399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 244526400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 257569199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 257569200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 276062399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 276062400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 291783599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 291783600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 307598399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 307598400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 323405999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 323406000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 339220799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 339220800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 354941999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 354942000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 370756799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 370756800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 386477999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 386478000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 402292799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 402292800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 418013999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 418014000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 433828799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 433828800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 449636399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 449636400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 465451199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 465451200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 481172399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 481172400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 496987199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 496987200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 512708399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 512708400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 528523199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 528523200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 544244399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 544244400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 560059199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 560059200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 575866799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 575866800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 591681599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 591681600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 607402799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 607402800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 625031999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 625032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 638938799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 638938800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 654753599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 654753600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 670474799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 670474800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 686721599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 686721600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 699418799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 699418800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 718257599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 718257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 733546799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 733546800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 749447999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 749448000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 762317999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 762318000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 780983999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 780984000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 793767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 793767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 812519999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 812520000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 825649199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 825649200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 844574399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 844574400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 856666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 856666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 876023999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 876024000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 888721199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 888721200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 907473599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 907473600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 920775599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 920775600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 938923199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 938923200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 952225199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 952225200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 970372799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 970372800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 983674799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 983674800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1002427199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1002427200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1018148399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1018148400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1030852799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1030852800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1049597999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1049598000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1062907199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1062907200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1081047599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1081047600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1097985599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1097985600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1110682799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1110682800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1129435199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1129435200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1142132399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1142132400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1160884799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1160884800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1173581999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1173582000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1192939199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1192939200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1205031599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1205031600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1224388799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1224388800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1236481199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1236481200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1255838399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1255838400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1268535599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1268535600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1287287999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1287288000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1299985199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1299985200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1318737599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1318737600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1331434799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1331434800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1350791999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1350792000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1362884399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1362884400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1382241599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1382241600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1394333999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1394334000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1413691199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1413691200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1425783599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1425783600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1445140799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1445140800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1457837999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1457838000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1476590399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1476590400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1489287599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1489287600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1508039999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1508040000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1520737199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1520737200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1540094399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1540094400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1552186799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1552186800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1571543999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1571544000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1583636399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1583636400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1602993599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1602993600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1615690799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1615690800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1634443199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1634443200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1647140399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1647140400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1665892799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1665892800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1678589999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1678590000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1697342399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1697342400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1710039599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1710039600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1729396799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1729396800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1741489199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1741489200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1760846399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1760846400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1772938799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1772938800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1792295999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1792296000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1804993199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1804993200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1823745599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1823745600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1836442799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1836442800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1855195199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1855195200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1867892399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1867892400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1887249599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1887249600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1899341999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1899342000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1918699199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1918699200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1930791599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1930791600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1950148799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1950148800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1962845999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1962846000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1981598399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1981598400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1994295599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1994295600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 2013047999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 2013048000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 2025745199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 2025745200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 2044497599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 2044497600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 2057194799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 2057194800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 2076551999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 2076552000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 2088644399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 2088644400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 2108001599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 2108001600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 2120093999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 2120094000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 2139451199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 2139451200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PYST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PYT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Atikokan.json b/dojox/date/tests/tztests/tz_America-Atikokan.json
new file mode 100644
index 0000000..aaa4b54
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Atikokan.json
@@ -0,0 +1,24 @@
+({
+	name: "date.timezone.America-Atikokan",
+	runTest: function(t){
+		var tz = "America/Atikokan";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1632067201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1632067200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1614790801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1614790800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -923248801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -923248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Bahia.json b/dojox/date/tests/tztests/tz_America-Bahia.json
new file mode 100644
index 0000000..861af12
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Bahia.json
@@ -0,0 +1,130 @@
+({
+	name: "date.timezone.America-Bahia",
+	runTest: function(t){
+		var tz = "America/Bahia";
+		doh.checkDate({tzOffset: 154.066666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 154.066666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 154.066666666667, tzAbbr: "LMT"}, -1767216357000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1767216356000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1206957601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1206957600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1191362401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1191362400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1175374801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1175374800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1159826401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1159826400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -633819601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -633819600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -622069201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -622069200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -602283601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -602283600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -591832801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -591832800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -570747601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -570747600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -560210401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -560210400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -539125201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -539125200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -531352801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -531352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -191365201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -191365200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -184197601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -184197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -155163601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -155163600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -150069601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -150069600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -128898001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -128898000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -121125601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -121125600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -99954001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -99954000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -89589601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -89589600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -68418001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -68418000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -57967201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -57967200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 499748399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 499748400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 511235999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 511236000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 530593199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 530593200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 540266399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 540266400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 562129199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 562129200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 571197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 571197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 592973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 592974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 602042399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 602042400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 634701599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 634701600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 666755999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 666756000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 687927599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 687927600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 697600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 697600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 719981999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 719982000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 728445599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 728445600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 750826799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 750826800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 761709599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 761709600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 782276399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 782276400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 793159199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 793159200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 813725999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 813726000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 824003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 824004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 844570799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 844570800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 856058399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 856058400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 876106799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 876106800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 888717599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 888717600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 908074799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 908074800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 919562399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 919562400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 951616799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 951616800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 970973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 970974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 982461599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 982461600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1003028399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1003028400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1013911199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1013911200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1036292399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1036292400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1045360799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1045360800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Barbados.json b/dojox/date/tests/tztests/tz_America-Barbados.json
new file mode 100644
index 0000000..ca2e204
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Barbados.json
@@ -0,0 +1,32 @@
+({
+	name: "date.timezone.America-Barbados",
+	runTest: function(t){
+		var tz = "America/Barbados";
+		doh.checkDate({tzOffset: 238.466666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 238.466666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 238.466666666667, tzAbbr: "LMT"}, -1451678493000, tz, 1);
+		doh.checkDate({tzOffset: 238.466666666667, tzAbbr: "BMT"}, -1451678492000, tz, 1);
+		doh.checkDate({tzOffset: 238.466666666667, tzAbbr: "BMT"}, -1199217693000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1199217692000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 234943199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 234943200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 244616399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 244616400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 261554399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 261554400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 276065999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 276066000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 293003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 293004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 307515599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 307515600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 325058399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 325058400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 338705999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 338706000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Belem.json b/dojox/date/tests/tztests/tz_America-Belem.json
new file mode 100644
index 0000000..32ffea2
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Belem.json
@@ -0,0 +1,70 @@
+({
+	name: "date.timezone.America-Belem",
+	runTest: function(t){
+		var tz = "America/Belem";
+		doh.checkDate({tzOffset: 193.933333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 193.933333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 193.933333333333, tzAbbr: "LMT"}, -1767213965000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1767213964000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1206957601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1206957600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1191362401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1191362400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1175374801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1175374800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1159826401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1159826400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -633819601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -633819600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -622069201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -622069200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -602283601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -602283600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -591832801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -591832800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -570747601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -570747600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -560210401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -560210400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -539125201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -539125200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -531352801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -531352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -191365201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -191365200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -184197601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -184197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -155163601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -155163600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -150069601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -150069600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -128898001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -128898000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -121125601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -121125600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -99954001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -99954000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -89589601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -89589600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -68418001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -68418000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -57967201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -57967200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 499748399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 499748400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 511235999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 511236000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 530593199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 530593200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 540266399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 540266400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 562129199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 562129200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 571197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 571197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Belize.json b/dojox/date/tests/tztests/tz_America-Belize.json
new file mode 100644
index 0000000..2375e1c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Belize.json
@@ -0,0 +1,122 @@
+({
+	name: "date.timezone.America-Belize",
+	runTest: function(t){
+		var tz = "America/Belize";
+		doh.checkDate({tzOffset: 352.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 352.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 352.8, tzAbbr: "LMT"}, -1822500433000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1822500432000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1616954401000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1616954400000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1606069801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1606069800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1585504801000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1585504800000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1574015401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1574015400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1554055201000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1554055200000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1542565801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1542565800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1522605601000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1522605600000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1511116201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1511116200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1490551201000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1490551200000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1479666601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1479666600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1459101601000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1459101600000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1448217001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1448217000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1427652001000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1427652000000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1416162601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1416162600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1396202401000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1396202400000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1384713001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1384713000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1364752801000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1364752800000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1353263401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1353263400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1333303201000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1333303200000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1321813801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1321813800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1301248801000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1301248800000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1290364201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1290364200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1269799201000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1269799200000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1258914601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1258914600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1238349601000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1238349600000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1226860201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1226860200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1206900001000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1206900000000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1195410601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1195410600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1175450401000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1175450400000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1163961001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1163961000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1143396001000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1143396000000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1132511401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1132511400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1111946401000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1111946400000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1101061801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1101061800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1080496801000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1080496800000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1069612201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1069612200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1049047201000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1049047200000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1037557801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1037557800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1017597601000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1017597600000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -1006108201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1006108200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -986148001000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -986148000000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -974658601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -974658600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -954093601000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -954093600000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -943209001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -943209000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -922644001000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -922644000000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -911759401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -911759400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -891194401000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -891194400000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -879705001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -879705000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -859744801000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -859744800000, tz, 1);
+		doh.checkDate({tzOffset: 330, tzAbbr: "CHDT"}, -848255401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -848255400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 123919199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 123919200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 129617999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 129618000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 409039199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 409039200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 413873999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 413874000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Blanc-Sablon.json b/dojox/date/tests/tztests/tz_America-Blanc-Sablon.json
new file mode 100644
index 0000000..9f2e0a3
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Blanc-Sablon.json
@@ -0,0 +1,22 @@
+({
+	name: "date.timezone.America-Blanc-Sablon",
+	runTest: function(t){
+		var tz = "America/Blanc-Sablon";
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1632074401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1632074400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1614798001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1614798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -880221601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -880221600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -765399601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -765399600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Boa_Vista.json b/dojox/date/tests/tztests/tz_America-Boa_Vista.json
new file mode 100644
index 0000000..bb04c85
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Boa_Vista.json
@@ -0,0 +1,78 @@
+({
+	name: "date.timezone.America-Boa_Vista",
+	runTest: function(t){
+		var tz = "America/Boa_Vista";
+		doh.checkDate({tzOffset: 242.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 242.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 242.666666666667, tzAbbr: "LMT"}, -1767211041000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1767211040000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1206954001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1206954000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1191358801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1191358800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1175371201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1175371200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1159822801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1159822800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -633816001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -633816000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -622065601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -622065600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -602280001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -602280000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -591829201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -591829200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -570744001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -570744000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -560206801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -560206800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -539121601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -539121600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -531349201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -531349200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -191361601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -191361600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -155160001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -155160000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -150066001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -150066000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -128894401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -128894400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -99950401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -99950400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -89586001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -89586000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -68414401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -68414400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -57963601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -57963600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 499751999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 499752000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 511239599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 511239600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 530596799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 530596800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 540269999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 540270000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 562132799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 562132800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 571201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 571201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 938923199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 938923200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 951620399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 951620400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 970977599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 970977600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 971578799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 971578800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Bogota.json b/dojox/date/tests/tztests/tz_America-Bogota.json
new file mode 100644
index 0000000..c2b51be
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Bogota.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.America-Bogota",
+	runTest: function(t){
+		var tz = "America/Bogota";
+		doh.checkDate({tzOffset: 296.333333333333, tzAbbr: "BMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 296.333333333333, tzAbbr: "BMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 296.333333333333, tzAbbr: "BMT"}, -1739041421000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "COT"}, -1739041420000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "COT"}, 704869199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "COST"}, 704869200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "COST"}, 733895999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "COT"}, 733896000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "COT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "COT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "COT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "COT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Boise.json b/dojox/date/tests/tztests/tz_America-Boise.json
new file mode 100644
index 0000000..ceb8736
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Boise.json
@@ -0,0 +1,312 @@
+({
+	name: "date.timezone.America-Boise",
+	runTest: function(t){
+		var tz = "America/Boise";
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1633269601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1633269600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1615129201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1615129200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1601820001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1601820000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1583679601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1583679600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1471788001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1471788000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -880210801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -880210800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -765388801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -765388800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -84380401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -84380400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -68659201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -68659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -52930801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -52930800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -37209601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -37209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -21481201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -21481200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -5760001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -5760000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 9968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 9968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 25689599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 25689600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 41417999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 41418000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 57743999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 57744000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 73472399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 73472400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 89193599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 89193600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 104921999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 104922000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 120643199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 120643200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 129113999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 129114000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 152092799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 152092800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 162377999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 162378000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 183542399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 183542400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 199270799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 199270800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 215596799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 215596800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 230720399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 230720400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 247046399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 247046400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 262774799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 262774800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 278495999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 278496000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 294224399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 294224400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 309945599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 309945600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 325673999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 325674000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 341395199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 341395200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 357123599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 357123600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 372844799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 372844800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 388573199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 388573200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 404899199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 404899200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 420022799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 420022800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 436348799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 436348800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 452077199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 452077200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 467798399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 467798400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 483526799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 483526800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 499247999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 499248000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 514976399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 514976400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 530697599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 530697600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 544611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 544611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 562147199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 562147200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 576061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 576061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 594201599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 594201600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 607510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 607510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 625651199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 625651200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 638960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 638960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 657100799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 657100800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 671014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 671014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 688550399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 688550400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 702464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 702464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 719999999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 720000000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 733913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 733914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 752054399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 752054400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 765363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 765363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 783503999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 783504000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 796813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 796813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 814953599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 814953600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 828867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 828867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 846403199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 846403200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 860317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 860317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 877852799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 877852800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 891766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 891766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 923216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 923216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 941356799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 941356800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 954665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 954666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 972806399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 972806400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 986115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 986115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1004255999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1004256000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1018169999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1018170000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1035705599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1035705600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1049619599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1049619600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1067155199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1067155200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1081069199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1081069200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1099209599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1099209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1112518799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1112518800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1130659199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1130659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1143968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1143968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1162108799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1162108800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1173603599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1173603600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1194163199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1194163200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1205053199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1205053200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1225612799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1225612800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1236502799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1236502800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1257062399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1257062400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1268557199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1268557200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1289116799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1289116800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1300006799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1300006800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1320566399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1320566400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1331456399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1331456400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1352015999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1352016000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1362905999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1362906000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1383465599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1383465600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1394355599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1394355600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1414915199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1414915200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1425805199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1425805200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1446364799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1446364800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1457859599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1457859600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1478419199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1478419200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1489309199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1489309200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1509868799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1509868800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1520758799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1520758800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1541318399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1541318400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1552208399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1552208400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1572767999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1572768000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1583657999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1583658000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1604217599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1604217600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1615712399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1615712400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1636271999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1636272000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1647161999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1647162000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1667721599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1667721600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1678611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1678611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1699171199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1699171200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1710061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1710061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1730620799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1730620800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1741510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1741510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1762070399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1762070400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1772960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1772960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1793519999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1793520000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1805014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1805014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1825574399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1825574400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1836464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1836464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1857023999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1857024000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1867913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1867914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1888473599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1888473600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1899363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1899363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1919923199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1919923200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1930813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1930813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1951372799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1951372800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1962867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1962867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1983427199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1983427200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1994317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1994317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2014876799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2014876800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2025766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2025766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2046326399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2046326400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2057216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2057216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2077775999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2077776000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2088665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2088666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2109225599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2109225600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2120115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2120115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2140675199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2140675200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Cambridge_Bay.json b/dojox/date/tests/tztests/tz_America-Cambridge_Bay.json
new file mode 100644
index 0000000..071ed43
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Cambridge_Bay.json
@@ -0,0 +1,258 @@
+({
+	name: "date.timezone.America-Cambridge_Bay",
+	runTest: function(t){
+		var tz = "America/Cambridge_Bay";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -1577923201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1577923200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -880210801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -880210800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -765388801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -765388800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -147891601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "MDDT"}, -147891600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "MDDT"}, -131562001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -131562000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 325673999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 325674000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 341395199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 341395200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 357123599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 357123600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 372844799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 372844800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 388573199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 388573200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 404899199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 404899200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 420022799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 420022800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 436348799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 436348800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 452077199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 452077200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 467798399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 467798400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 483526799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 483526800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 499247999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 499248000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 514976399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 514976400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 530697599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 530697600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 544611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 544611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 562147199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 562147200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 576061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 576061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 594201599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 594201600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 607510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 607510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 625651199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 625651200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 638960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 638960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 657100799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 657100800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 671014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 671014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 688550399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 688550400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 702464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 702464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 719999999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 720000000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 733913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 733914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 752054399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 752054400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 765363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 765363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 783503999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 783504000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 796813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 796813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 814953599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 814953600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 828867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 828867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 846403199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 846403200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 860317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 860317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 877852799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 877852800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 891766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 891766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 923216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 923216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 941356799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941356800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 973400399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 973400400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 986115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 986115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1004255999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1004256000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1018169999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1018170000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1035705599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1035705600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1049619599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1049619600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1067155199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1067155200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1081069199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1081069200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1099209599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1099209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1112518799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1112518800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1130659199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1130659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1143968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1143968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1162108799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1162108800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1173603599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1173603600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1194163199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1194163200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1205053199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1205053200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1225612799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1225612800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1236502799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1236502800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1257062399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1257062400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1268557199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1268557200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1289116799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1289116800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1300006799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1300006800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1320566399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1320566400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1331456399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1331456400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1352015999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1352016000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1362905999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1362906000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1383465599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1383465600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1394355599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1394355600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1414915199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1414915200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1425805199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1425805200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1446364799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1446364800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1457859599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1457859600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1478419199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1478419200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1489309199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1489309200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1509868799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1509868800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1520758799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1520758800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1541318399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1541318400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1552208399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1552208400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1572767999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1572768000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1583657999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1583658000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1604217599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1604217600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1615712399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1615712400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1636271999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1636272000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1647161999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1647162000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1667721599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1667721600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1678611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1678611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1699171199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1699171200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1710061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1710061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1730620799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1730620800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1741510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1741510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1762070399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1762070400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1772960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1772960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1793519999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1793520000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1805014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1805014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1825574399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1825574400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1836464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1836464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1857023999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1857024000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1867913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1867914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1888473599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1888473600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1899363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1899363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1919923199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1919923200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1930813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1930813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1951372799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1951372800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1962867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1962867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1983427199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1983427200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1994317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1994317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2014876799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2014876800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2025766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2025766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2046326399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2046326400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2057216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2057216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2077775999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2077776000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2088665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2088666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2109225599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2109225600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2120115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2120115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2140675199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2140675200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Campo_Grande.json b/dojox/date/tests/tztests/tz_America-Campo_Grande.json
new file mode 100644
index 0000000..0fd4252
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Campo_Grande.json
@@ -0,0 +1,268 @@
+({
+	name: "date.timezone.America-Campo_Grande",
+	runTest: function(t){
+		var tz = "America/Campo_Grande";
+		doh.checkDate({tzOffset: 218.466666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 218.466666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 218.466666666667, tzAbbr: "LMT"}, -1767212493000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1767212492000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1206954001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1206954000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1191358801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1191358800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1175371201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1175371200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1159822801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1159822800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -633816001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -633816000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -622065601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -622065600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -602280001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -602280000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -591829201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -591829200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -570744001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -570744000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -560206801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -560206800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -539121601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -539121600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -531349201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -531349200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -191361601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -191361600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -155160001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -155160000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -150066001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -150066000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -128894401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -128894400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -99950401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -99950400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -89586001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -89586000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -68414401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -68414400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -57963601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -57963600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 499751999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 499752000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 511239599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 511239600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 530596799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 530596800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 540269999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 540270000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 562132799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 562132800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 571201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 571201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 592977599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 592977600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 602045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 602046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 624427199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 624427200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 634705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 634705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 656481599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 656481600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 666759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 666759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 687931199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 687931200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 697604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 697604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 719985599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 719985600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 728449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 728449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 750830399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 750830400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 761713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 761713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 782279999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 782280000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 793162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 793162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 813729599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 813729600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 824007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 824007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 844574399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 844574400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 856061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 856062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 876110399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 876110400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 888721199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 888721200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 908078399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 908078400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 919565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 919566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 938923199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 938923200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 951620399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 951620400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 970977599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 970977600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 982465199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 982465200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1003031999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1003032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1013914799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1013914800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1036295999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1036296000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1045364399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1045364400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1066535999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1066536000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1076813999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1076814000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1099367999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1099368000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1108868399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1108868400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1129435199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1129435200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1140317999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1140318000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1162699199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1162699200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1172372399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1172372400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1192334399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1192334400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1203217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1203217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1224388799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1224388800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1234666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1234666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1255838399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1255838400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1266721199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1266721200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1287287999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1287288000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1298170799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1298170800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1318737599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1318737600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1330225199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1330225200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1350791999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1350792000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1361069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1361070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1382241599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1382241600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1392519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1392519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1413691199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1413691200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1424573999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1424574000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1445140799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1445140800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1456023599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1456023600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1476590399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1476590400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1487473199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1487473200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1508039999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1508040000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1518922799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1518922800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1540094399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1540094400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1550372399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1550372400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1571543999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1571544000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1581821999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1581822000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1602993599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1602993600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1613876399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1613876400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1634443199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1634443200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1645325999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1645326000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1665892799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1665892800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1677380399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1677380400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1697342399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1697342400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1708225199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1708225200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1729396799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1729396800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1739674799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1739674800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1760846399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1760846400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1771729199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1771729200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1792295999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1792296000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1803178799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1803178800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1823745599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1823745600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1834628399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1834628400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1855195199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1855195200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1866077999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1866078000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1887249599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1887249600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1897527599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1897527600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1918699199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1918699200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1928977199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1928977200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1950148799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1950148800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1960426799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1960426800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1981598399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1981598400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1992481199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1992481200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2013047999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2013048000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2024535599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2024535600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2044497599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2044497600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2055380399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2055380400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2076551999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2076552000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2086829999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2086830000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2108001599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2108001600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2118884399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2118884400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2139451199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2139451200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Cancun.json b/dojox/date/tests/tztests/tz_America-Cancun.json
new file mode 100644
index 0000000..f479860
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Cancun.json
@@ -0,0 +1,186 @@
+({
+	name: "date.timezone.America-Cancun",
+	runTest: function(t){
+		var tz = "America/Cancun";
+		doh.checkDate({tzOffset: 347.066666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 347.066666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 347.066666666667, tzAbbr: "LMT"}, -1514743201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1514743200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 377935199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 377935200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 902037599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 902037600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 989135999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 989136000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1001833199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1001833200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035701999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035702000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067151599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067151600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1175414399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1175414400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1193554799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1193554800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1207468799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1207468800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225004399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225004400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1238918399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1238918400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1256453999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1256454000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1270367999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1270368000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1288508399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1288508400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1301817599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1301817600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1319957999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1319958000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1333267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1333267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1351407599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1351407600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1365321599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1365321600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1382857199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1382857200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1396771199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1396771200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414306799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414306800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1428220799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1428220800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1445756399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1445756400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1459670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1459670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1477810799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1477810800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1491119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1491120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509260399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509260400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1522569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1522569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1540709999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1540710000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1554623999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1554624000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1586073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1586073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1603609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1603609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1617523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1617523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1635663599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1635663600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1648972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1648972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1680422399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1680422400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1698562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1698562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1712476799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1712476800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1743926399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1743926400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1761461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1761462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1775375999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1775376000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1792911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1792911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1806825599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1806825600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1824965999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1824966000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1838275199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1838275200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1856415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1856415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1869724799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1869724800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1887865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1887865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1901779199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1901779200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1933228799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1933228800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1950764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1950764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1964678399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1964678400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1982818799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1982818800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1996127999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1996128000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2027577599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2027577600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2045717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2045718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2059027199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2059027200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2091081599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2091081600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2108617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2108617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2122531199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2122531200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Caracas.json b/dojox/date/tests/tztests/tz_America-Caracas.json
new file mode 100644
index 0000000..b8a2f26
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Caracas.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.America-Caracas",
+	runTest: function(t){
+		var tz = "America/Caracas";
+		doh.checkDate({tzOffset: 267.666666666667, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 267.666666666667, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 267.666666666667, tzAbbr: "CMT"}, -1826739141000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "VET"}, -1826739140000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "VET"}, -157750201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "VET"}, -157750200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "VET"}, 1197183599000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "VET"}, 1197183600000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "VET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "VET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "VET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 270, tzAbbr: "VET"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Cayenne.json b/dojox/date/tests/tztests/tz_America-Cayenne.json
new file mode 100644
index 0000000..b432987
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Cayenne.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.America-Cayenne",
+	runTest: function(t){
+		var tz = "America/Cayenne";
+		doh.checkDate({tzOffset: 209.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 209.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 209.333333333333, tzAbbr: "LMT"}, -1846269041000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "GFT"}, -1846269040000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "GFT"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "GFT"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "GFT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "GFT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "GFT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "GFT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Cayman.json b/dojox/date/tests/tztests/tz_America-Cayman.json
new file mode 100644
index 0000000..9bfa33e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Cayman.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-Cayman",
+	runTest: function(t){
+		var tz = "America/Cayman";
+		doh.checkDate({tzOffset: 307.2, tzAbbr: "KMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 307.2, tzAbbr: "KMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 307.2, tzAbbr: "KMT"}, -1827687169000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1827687168000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Chicago.json b/dojox/date/tests/tztests/tz_America-Chicago.json
new file mode 100644
index 0000000..2414a6f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Chicago.json
@@ -0,0 +1,482 @@
+({
+	name: "date.timezone.America-Chicago",
+	runTest: function(t){
+		var tz = "America/Chicago";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1563724801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1563724800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1551632401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1551632400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1538928001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1538928000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1520182801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1520182800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1504454401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1504454400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1491757201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1491757200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1473004801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1473004800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1459702801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1459702800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1441555201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1441555200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1428253201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1428253200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1410105601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1410105600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1396803601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1396803600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1378656001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1378656000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1365354001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1365354000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1347206401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1347206400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1333904401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1333904400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1315152001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1315152000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1301850001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1301850000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1283702401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1283702400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1270400401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1270400400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1252252801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1252252800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1238950801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1238950800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1220803201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1220803200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1207501201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1207501200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1189353601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1189353600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1176051601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1176051600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1157299201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1157299200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1144602001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1144602000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1125849601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1125849600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1112547601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1112547600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1094400001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1094400000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1081098001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1081098000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1067788801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1067788800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1045414801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1045414800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1031500801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1031500800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1018198801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1018198800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1000051201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1000051200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -986749201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -986749200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -967996801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -967996800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -955299601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -955299600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -936547201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -936547200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -923245201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -923245200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -905097601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -905097600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -891795601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -891795600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -747244801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -747244800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -733942801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -733942800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -715795201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -715795200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -702493201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -702493200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -684345601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -684345600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -671043601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -671043600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -652896001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -652896000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -639594001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -639594000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -620841601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -620841600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -608144401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -608144400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -589392001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -589392000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -576090001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -576090000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -557942401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -557942400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -544640401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -544640400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -526492801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -526492800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -513190801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -513190800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -495043201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -495043200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -481741201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -481741200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -463593601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -463593600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -447267601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -447267600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -431539201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -431539200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -415818001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -415818000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -400089601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -400089600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -384368401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -384368400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -368640001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -368640000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -352918801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -352918800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -337190401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -337190400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -321469201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -321469200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -305740801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -305740800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -289414801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -289414800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -273686401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -273686400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -257965201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -257965200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -242236801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -242236800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -226515601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -226515600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -210787201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -210787200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -195066001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -195066000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -179337601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -179337600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -163616401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -163616400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -147888001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -147888000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -131562001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -131562000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -116438401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -116438400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -100112401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -100112400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -84384001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -84384000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -68662801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -68662800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -52934401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -52934400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -37213201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -37213200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -21484801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -21484800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -5763601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -5763600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 9964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 9964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 25685999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 25686000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 41414399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 41414400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 57740399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 57740400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 73468799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 73468800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 89189999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 89190000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 104918399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 104918400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 120639599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 120639600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 126691199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 126691200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 152089199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 152089200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 162374399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 162374400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 183538799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 183538800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 199267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 199267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 215593199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 215593200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 230716799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 230716800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 247042799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 247042800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 262771199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 262771200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 278492399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 278492400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 294220799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 294220800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 309941999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 309942000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 325670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 325670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 341391599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 341391600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 357119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 357120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 372841199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 372841200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 388569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 388569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 404895599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 404895600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 420019199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 420019200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 436345199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 436345200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 452073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 452073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 467794799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 467794800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 483523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 483523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 499244399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 499244400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 514972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 514972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 530693999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 530694000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 544607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 544608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 562143599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 562143600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 576057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 576057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 594197999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 594198000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 607507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 607507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 625647599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 625647600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 638956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 638956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 657097199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 657097200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 671011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 671011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 688546799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 688546800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 702460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 702460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 719996399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 719996400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 733910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 733910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 752050799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 752050800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 765359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 765360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 783500399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 783500400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 796809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 796809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 814949999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 814950000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 986111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 986112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1004252399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1004252400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035701999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035702000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067151599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067151600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1205049599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1205049600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1236499199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1236499200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1257058799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1257058800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1268553599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1268553600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1289113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1289113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1300003199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1300003200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1320562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1320562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1331452799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1331452800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1352012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1352012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1362902399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1362902400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1383461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1383462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1394351999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1394352000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1425801599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1425801600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1446361199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1446361200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1457855999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1457856000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1478415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1478415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1489305599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1489305600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1520755199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1520755200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1541314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1541314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1552204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1552204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1583654399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1583654400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1604213999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1604214000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1615708799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1615708800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1636268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1636268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1647158399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1647158400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1678607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1678608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1699167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1699167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1710057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1710057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1741507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1741507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1762066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1762066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1772956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1772956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1793516399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1793516400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1805011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1805011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1825570799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1825570800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1836460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1836460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1857020399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1857020400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1867910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1867910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1888469999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1888470000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1899359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1899360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919919599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919919600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1930809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1930809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1951369199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1951369200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1962863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1962864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1983423599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1983423600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1994313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1994313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014873199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014873200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2025763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2025763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2046322799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2046322800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2057212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2057212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077772399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077772400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2088662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2088662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2109221999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2109222000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2120111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2120112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140671599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140671600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Chihuahua.json b/dojox/date/tests/tztests/tz_America-Chihuahua.json
new file mode 100644
index 0000000..9cf500d
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Chihuahua.json
@@ -0,0 +1,192 @@
+({
+	name: "date.timezone.America-Chihuahua",
+	runTest: function(t){
+		var tz = "America/Chihuahua";
+		doh.checkDate({tzOffset: 424.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 424.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 424.333333333333, tzAbbr: "LMT"}, -1514739601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1514739600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1343066401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1343066400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1234807201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1234807200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1220292001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1220292000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1207159201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1207159200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1191344401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1191344400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 891766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 923216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 923216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 941356799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 941356800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 954665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 954666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 972806399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 972806400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 989139599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 989139600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1001836799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1001836800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1018169999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1018170000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1035705599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1035705600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1049619599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1049619600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1067155199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1067155200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1081069199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1081069200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1099209599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1099209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1112518799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1112518800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1130659199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1130659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1143968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1143968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1162108799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1162108800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1175417999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1175418000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1193558399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1193558400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1207472399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1207472400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1225007999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1225008000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1238921999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1238922000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1256457599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1256457600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1270371599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1270371600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1288511999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1288512000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1301821199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1301821200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1319961599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1319961600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1333270799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1333270800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1351411199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1351411200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1365325199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1365325200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1382860799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1382860800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1396774799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1396774800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1414310399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1414310400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1428224399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1428224400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1445759999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1445760000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1459673999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1459674000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1477814399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1477814400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1491123599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1491123600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1509263999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1509264000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1522573199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1522573200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1540713599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1540713600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1554627599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1554627600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1572163199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1572163200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1586077199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1586077200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1603612799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1603612800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1617526799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1617526800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1635667199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1635667200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1648976399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1648976400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1667116799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1667116800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1680425999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1680426000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1698566399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1698566400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1712480399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1712480400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1730015999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1730016000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1743929999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1743930000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1761465599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1761465600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1775379599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1775379600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1792915199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1792915200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1806829199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1806829200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1824969599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1824969600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1838278799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1838278800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1856419199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1856419200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1869728399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1869728400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1887868799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1887868800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1901782799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1901782800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1919318399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1919318400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1933232399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1933232400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1950767999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1950768000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1964681999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1964682000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1982822399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1982822400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1996131599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1996131600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2014271999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2014272000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2027581199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2027581200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2045721599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2045721600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2059030799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2059030800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2077171199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2077171200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2091085199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2091085200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2108620799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2108620800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2122534799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2122534800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2140070399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2140070400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Costa_Rica.json b/dojox/date/tests/tztests/tz_America-Costa_Rica.json
new file mode 100644
index 0000000..3c17270
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Costa_Rica.json
@@ -0,0 +1,30 @@
+({
+	name: "date.timezone.America-Costa_Rica",
+	runTest: function(t){
+		var tz = "America/Costa_Rica";
+		doh.checkDate({tzOffset: 336.333333333333, tzAbbr: "SJMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 336.333333333333, tzAbbr: "SJMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 336.333333333333, tzAbbr: "SJMT"}, -1545071021000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1545071020000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 288770399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 288770400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 297233999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 297234000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 320219999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 320220000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 328683599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 328683600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 664264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 664264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 678344399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 678344400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 695714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 695714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 700635599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 700635600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Cuiaba.json b/dojox/date/tests/tztests/tz_America-Cuiaba.json
new file mode 100644
index 0000000..ef81035
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Cuiaba.json
@@ -0,0 +1,264 @@
+({
+	name: "date.timezone.America-Cuiaba",
+	runTest: function(t){
+		var tz = "America/Cuiaba";
+		doh.checkDate({tzOffset: 224.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 224.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 224.333333333333, tzAbbr: "LMT"}, -1767212141000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1767212140000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1206954001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1206954000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1191358801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1191358800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1175371201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1175371200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1159822801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1159822800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -633816001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -633816000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -622065601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -622065600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -602280001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -602280000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -591829201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -591829200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -570744001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -570744000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -560206801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -560206800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -539121601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -539121600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -531349201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -531349200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -191361601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -191361600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -155160001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -155160000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -150066001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -150066000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -128894401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -128894400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -99950401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -99950400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -89586001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -89586000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -68414401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -68414400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -57963601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -57963600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 499751999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 499752000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 511239599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 511239600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 530596799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 530596800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 540269999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 540270000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 562132799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 562132800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 571201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 571201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 592977599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 592977600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 602045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 602046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 624427199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 624427200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 634705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 634705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 656481599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 656481600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 666759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 666759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 687931199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 687931200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 697604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 697604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 719985599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 719985600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 728449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 728449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 750830399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 750830400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 761713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 761713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 782279999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 782280000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 793162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 793162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 813729599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 813729600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 824007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 824007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 844574399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 844574400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 856061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 856062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 876110399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 876110400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 888721199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 888721200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 908078399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 908078400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 919565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 919566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 938923199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 938923200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 951620399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 951620400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 970977599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 970977600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 982465199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 982465200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1003031999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1003032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1013914799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1013914800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1036295999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1036296000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1045364399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1045364400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1099367999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1099368000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1108868399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1108868400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1129435199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1129435200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1140317999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1140318000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1162699199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1162699200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1172372399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1172372400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1192334399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1192334400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1203217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1203217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1224388799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1224388800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1234666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1234666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1255838399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1255838400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1266721199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1266721200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1287287999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1287288000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1298170799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1298170800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1318737599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1318737600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1330225199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1330225200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1350791999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1350792000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1361069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1361070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1382241599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1382241600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1392519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1392519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1413691199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1413691200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1424573999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1424574000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1445140799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1445140800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1456023599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1456023600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1476590399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1476590400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1487473199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1487473200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1508039999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1508040000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1518922799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1518922800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1540094399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1540094400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1550372399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1550372400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1571543999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1571544000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1581821999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1581822000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1602993599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1602993600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1613876399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1613876400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1634443199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1634443200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1645325999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1645326000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1665892799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1665892800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1677380399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1677380400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1697342399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1697342400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1708225199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1708225200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1729396799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1729396800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1739674799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1739674800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1760846399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1760846400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1771729199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1771729200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1792295999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1792296000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1803178799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1803178800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1823745599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1823745600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1834628399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1834628400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1855195199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1855195200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1866077999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1866078000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1887249599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1887249600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1897527599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1897527600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1918699199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1918699200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1928977199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1928977200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1950148799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1950148800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1960426799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1960426800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1981598399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1981598400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1992481199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1992481200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2013047999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2013048000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2024535599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2024535600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2044497599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2044497600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2055380399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2055380400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2076551999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2076552000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2086829999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2086830000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2108001599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2108001600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2118884399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2118884400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2139451199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2139451200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Curacao.json b/dojox/date/tests/tztests/tz_America-Curacao.json
new file mode 100644
index 0000000..496784e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Curacao.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.America-Curacao",
+	runTest: function(t){
+		var tz = "America/Curacao";
+		doh.checkDate({tzOffset: 275.733333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 275.733333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 275.733333333333, tzAbbr: "LMT"}, -1826738657000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "ANT"}, -1826738656000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "ANT"}, -157750201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -157750200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Danmarkshavn.json b/dojox/date/tests/tztests/tz_America-Danmarkshavn.json
new file mode 100644
index 0000000..acdeab0
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Danmarkshavn.json
@@ -0,0 +1,80 @@
+({
+	name: "date.timezone.America-Danmarkshavn",
+	runTest: function(t){
+		var tz = "America/Danmarkshavn";
+		doh.checkDate({tzOffset: 74.6666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 74.6666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 74.6666666666667, tzAbbr: "LMT"}, -1686091521000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, -1686091520000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 323845199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 323845200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 820465199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 820465200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Dawson.json b/dojox/date/tests/tztests/tz_America-Dawson.json
new file mode 100644
index 0000000..8e8515b
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Dawson.json
@@ -0,0 +1,264 @@
+({
+	name: "date.timezone.America-Dawson",
+	runTest: function(t){
+		var tz = "America/Dawson";
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -1632056401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, -1632056400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, -1615125601000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -1615125600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -1596978001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, -1596978000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, -1583164801000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -1583164800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -880203601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YWT"}, -880203600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YPT"}, -765381601000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -765381600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -147884401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "YDDT"}, -147884400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "YDDT"}, -131554801000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -131554800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 120646799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 120646800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 325677599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 325677600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 341398799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 341398800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 357127199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 357127200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 372848399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 372848400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 388576799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 388576800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 404902799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 404902800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 420026399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 420026400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 436352399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 436352400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 452080799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 452080800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 467801999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 467802000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 483530399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 483530400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 499251599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 499251600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 514979999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 514980000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 530701199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 530701200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 544615199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 544615200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 562150799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 562150800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 576064799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 576064800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 594205199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 594205200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 607514399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 607514400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 625654799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 625654800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 638963999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 638964000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 657104399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 657104400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 671018399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 671018400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 688553999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 688554000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 702467999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 702468000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 720003599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 720003600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 733917599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 733917600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 752057999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 752058000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 765367199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 765367200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 783507599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 783507600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 796816799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 796816800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 814957199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 814957200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 828871199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 828871200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 846406799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 846406800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 860320799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 860320800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 877856399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 877856400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 891770399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 891770400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 909305999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 909306000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 923219999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 923220000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 941360399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 941360400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 954669599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 954669600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 972809999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 972810000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 986119199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 986119200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1004259599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1004259600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1018173599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1018173600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1035709199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1035709200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1049623199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1049623200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1067158799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1067158800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1081072799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1081072800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1099213199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1099213200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1112522399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1112522400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1130662799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1130662800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1143971999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1143972000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1162112399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1162112400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1173607199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1173607200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1194166799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1194166800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1205056799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1205056800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1225616399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1225616400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1236506399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1236506400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1257065999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1257066000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1268560799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1268560800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1289120399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1289120400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1300010399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1300010400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1320569999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1320570000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1331459999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1331460000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1352019599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1352019600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1362909599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1362909600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1383469199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1383469200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1394359199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1394359200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1414918799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1414918800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1425808799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1425808800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1446368399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1446368400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1457863199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1457863200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1478422799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1478422800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1489312799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1489312800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1509872399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1509872400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1520762399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1520762400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1541321999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1541322000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1552211999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1552212000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1572771599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1572771600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1583661599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1583661600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1604221199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1604221200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1615715999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1615716000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1636275599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1636275600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1647165599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1647165600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1667725199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1667725200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1678615199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1678615200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1699174799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1699174800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1710064799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1710064800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1730624399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1730624400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1741514399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1741514400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1762073999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1762074000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1772963999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1772964000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1793523599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1793523600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1805018399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1805018400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1825577999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1825578000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1836467999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1836468000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1857027599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1857027600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1867917599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1867917600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1888477199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1888477200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1899367199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1899367200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1919926799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1919926800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1930816799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1930816800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1951376399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1951376400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1962871199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1962871200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1983430799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1983430800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1994320799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1994320800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2014880399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2014880400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2025770399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2025770400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2046329999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2046330000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2057219999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2057220000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2077779599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2077779600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2088669599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2088669600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2109229199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2109229200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2120119199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2120119200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2140678799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2140678800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Dawson_Creek.json b/dojox/date/tests/tztests/tz_America-Dawson_Creek.json
new file mode 100644
index 0000000..7401aa4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Dawson_Creek.json
@@ -0,0 +1,126 @@
+({
+	name: "date.timezone.America-Dawson_Creek",
+	runTest: function(t){
+		var tz = "America/Dawson_Creek";
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1632060001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1632060000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1614783601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1614783600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -880207201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -880207200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -765385201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -765385200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -715788001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -715788000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -702486001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -702486000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -684338401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -684338400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -671036401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -671036400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -652888801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -652888800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -639586801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -639586800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -620834401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -620834400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -608137201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -608137200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -589384801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -589384800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -576082801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -576082800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -557935201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -557935200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -544633201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -544633200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -526485601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -526485600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -513183601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -513183600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -495036001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -495036000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -481734001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -481734000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -463586401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -463586400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -450284401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -450284400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -431532001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -431532000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -418230001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -418230000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -400082401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -400082400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -386780401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -386780400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -368632801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -368632800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -355330801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -355330800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -337183201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -337183200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -323881201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -323881200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -305733601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -305733600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -292431601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -292431600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -273679201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -273679200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -260982001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -260982000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -242229601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -242229600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -226508401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -226508400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -210780001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -210780000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -195058801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -195058800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -179330401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -179330400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -163609201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -163609200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -147880801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -147880800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -131554801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -131554800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -116431201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -116431200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -100105201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -100105200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -84376801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -84376800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -68655601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -68655600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -52927201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -52927200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -37206001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -37206000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -21477601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -21477600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -5756401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -5756400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 9971999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 9972000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 25693199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 25693200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 41421599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 41421600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 57747599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 57747600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 73475999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 73476000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 84013199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 84013200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Denver.json b/dojox/date/tests/tztests/tz_America-Denver.json
new file mode 100644
index 0000000..d4b5618
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Denver.json
@@ -0,0 +1,326 @@
+({
+	name: "date.timezone.America-Denver",
+	runTest: function(t){
+		var tz = "America/Denver";
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1633273201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1633273200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1615132801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1615132800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1601823601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1601823600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1583683201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1583683200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1570374001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1570374000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1551628801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1551628800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1538924401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1538924400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1534089601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1534089600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -880210801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -880210800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -765388801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -765388800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -147884401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -147884400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -131558401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -131558400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -116434801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -116434800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -100108801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -100108800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -84380401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -84380400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -68659201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -68659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -52930801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -52930800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -37209601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -37209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -21481201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -21481200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -5760001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -5760000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 9968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 9968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 25689599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 25689600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 41417999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 41418000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 57743999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 57744000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 73472399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 73472400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 89193599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 89193600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 104921999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 104922000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 120643199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 120643200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 126694799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 126694800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 152092799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 152092800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 162377999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 162378000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 183542399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 183542400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 199270799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 199270800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 215596799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 215596800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 230720399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 230720400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 247046399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 247046400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 262774799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 262774800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 278495999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 278496000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 294224399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 294224400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 309945599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 309945600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 325673999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 325674000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 341395199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 341395200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 357123599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 357123600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 372844799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 372844800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 388573199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 388573200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 404899199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 404899200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 420022799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 420022800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 436348799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 436348800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 452077199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 452077200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 467798399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 467798400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 483526799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 483526800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 499247999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 499248000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 514976399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 514976400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 530697599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 530697600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 544611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 544611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 562147199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 562147200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 576061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 576061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 594201599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 594201600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 607510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 607510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 625651199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 625651200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 638960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 638960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 657100799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 657100800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 671014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 671014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 688550399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 688550400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 702464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 702464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 719999999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 720000000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 733913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 733914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 752054399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 752054400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 765363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 765363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 783503999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 783504000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 796813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 796813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 814953599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 814953600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 828867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 828867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 846403199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 846403200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 860317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 860317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 877852799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 877852800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 891766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 891766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 923216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 923216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 941356799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 941356800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 954665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 954666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 972806399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 972806400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 986115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 986115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1004255999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1004256000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1018169999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1018170000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1035705599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1035705600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1049619599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1049619600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1067155199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1067155200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1081069199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1081069200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1099209599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1099209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1112518799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1112518800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1130659199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1130659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1143968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1143968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1162108799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1162108800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1173603599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1173603600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1194163199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1194163200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1205053199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1205053200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1225612799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1225612800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1236502799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1236502800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1257062399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1257062400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1268557199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1268557200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1289116799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1289116800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1300006799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1300006800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1320566399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1320566400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1331456399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1331456400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1352015999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1352016000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1362905999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1362906000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1383465599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1383465600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1394355599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1394355600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1414915199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1414915200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1425805199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1425805200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1446364799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1446364800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1457859599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1457859600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1478419199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1478419200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1489309199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1489309200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1509868799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1509868800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1520758799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1520758800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1541318399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1541318400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1552208399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1552208400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1572767999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1572768000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1583657999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1583658000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1604217599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1604217600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1615712399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1615712400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1636271999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1636272000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1647161999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1647162000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1667721599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1667721600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1678611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1678611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1699171199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1699171200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1710061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1710061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1730620799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1730620800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1741510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1741510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1762070399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1762070400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1772960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1772960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1793519999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1793520000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1805014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1805014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1825574399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1825574400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1836464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1836464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1857023999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1857024000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1867913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1867914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1888473599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1888473600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1899363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1899363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1919923199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1919923200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1930813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1930813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1951372799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1951372800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1962867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1962867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1983427199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1983427200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1994317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1994317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2014876799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2014876800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2025766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2025766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2046326399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2046326400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2057216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2057216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2077775999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2077776000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2088665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2088666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2109225599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2109225600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2120115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2120115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2140675199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2140675200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Detroit.json b/dojox/date/tests/tztests/tz_America-Detroit.json
new file mode 100644
index 0000000..1315ab5
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Detroit.json
@@ -0,0 +1,290 @@
+({
+	name: "date.timezone.America-Detroit",
+	runTest: function(t){
+		var tz = "America/Detroit";
+		doh.checkDate({tzOffset: 332.183333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 332.183333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 332.183333333333, tzAbbr: "LMT"}, -2051202470000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2051202469000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1724083201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1724083200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -880218001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -880218000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -765396001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -765396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -684349201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -684349200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -671047201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -671047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -80499601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -80499600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -68666401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -68666400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 104914799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 104914800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 120635999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 120636000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 126687599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 126687600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 152085599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152085600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 167813999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 167814000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 183535199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 183535200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 199263599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 199263600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 215589599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 215589600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 230713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 230713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 247039199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 247039200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 262767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 262767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 278488799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 278488800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 294217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 294217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 309938399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 309938400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467791199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467791200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499240799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530690399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 544604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 544604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562139999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 954658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 954658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 972799199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Dominica.json b/dojox/date/tests/tztests/tz_America-Dominica.json
new file mode 100644
index 0000000..54abc09
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Dominica.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-Dominica",
+	runTest: function(t){
+		var tz = "America/Dominica";
+		doh.checkDate({tzOffset: 245.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 245.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 245.6, tzAbbr: "LMT"}, -1846266805000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1846266804000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Edmonton.json b/dojox/date/tests/tztests/tz_America-Edmonton.json
new file mode 100644
index 0000000..49469e4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Edmonton.json
@@ -0,0 +1,320 @@
+({
+	name: "date.timezone.America-Edmonton",
+	runTest: function(t){
+		var tz = "America/Edmonton";
+		doh.checkDate({tzOffset: 453.866666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 453.866666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 453.866666666667, tzAbbr: "LMT"}, -1998663969000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1998663968000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1632063601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1632063600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1614787201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1614787200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1600614001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1600614000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1596816001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1596816000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1567954801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1567954800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1551628801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1551628800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1536505201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1536505200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1523203201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1523203200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1504450801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1504450800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1491753601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1491753600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1473001201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1473001200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1459699201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1459699200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -880210801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -880210800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -765388801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -765388800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -715791601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -715791600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -702489601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -702489600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -84380401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -84380400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -68659201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -68659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -21481201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -21481200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -5760001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -5760000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 73472399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 73472400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 89193599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 89193600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 104921999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 104922000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 120643199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 120643200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 136371599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 136371600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 152092799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 152092800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 167821199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 167821200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 183542399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 183542400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 199270799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 199270800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 215596799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 215596800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 230720399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 230720400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 247046399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 247046400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 262774799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 262774800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 278495999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 278496000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 294224399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 294224400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 309945599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 309945600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 325673999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 325674000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 341395199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 341395200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 357123599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 357123600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 372844799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 372844800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 388573199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 388573200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 404899199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 404899200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 420022799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 420022800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 436348799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 436348800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 452077199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 452077200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 467798399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 467798400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 483526799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 483526800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 499247999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 499248000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 514976399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 514976400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 530697599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 530697600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 544611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 544611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 562147199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 562147200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 576061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 576061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 594201599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 594201600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 607510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 607510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 625651199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 625651200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 638960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 638960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 657100799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 657100800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 671014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 671014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 688550399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 688550400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 702464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 702464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 719999999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 720000000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 733913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 733914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 752054399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 752054400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 765363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 765363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 783503999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 783504000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 796813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 796813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 814953599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 814953600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 828867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 828867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 846403199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 846403200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 860317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 860317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 877852799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 877852800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 891766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 891766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 923216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 923216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 941356799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 941356800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 954665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 954666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 972806399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 972806400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 986115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 986115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1004255999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1004256000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1018169999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1018170000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1035705599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1035705600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1049619599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1049619600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1067155199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1067155200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1081069199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1081069200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1099209599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1099209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1112518799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1112518800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1130659199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1130659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1143968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1143968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1162108799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1162108800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1173603599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1173603600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1194163199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1194163200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1205053199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1205053200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1225612799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1225612800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1236502799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1236502800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1257062399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1257062400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1268557199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1268557200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1289116799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1289116800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1300006799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1300006800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1320566399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1320566400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1331456399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1331456400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1352015999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1352016000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1362905999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1362906000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1383465599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1383465600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1394355599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1394355600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1414915199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1414915200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1425805199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1425805200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1446364799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1446364800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1457859599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1457859600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1478419199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1478419200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1489309199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1489309200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1509868799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1509868800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1520758799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1520758800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1541318399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1541318400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1552208399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1552208400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1572767999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1572768000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1583657999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1583658000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1604217599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1604217600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1615712399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1615712400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1636271999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1636272000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1647161999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1647162000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1667721599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1667721600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1678611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1678611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1699171199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1699171200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1710061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1710061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1730620799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1730620800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1741510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1741510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1762070399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1762070400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1772960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1772960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1793519999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1793520000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1805014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1805014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1825574399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1825574400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1836464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1836464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1857023999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1857024000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1867913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1867914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1888473599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1888473600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1899363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1899363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1919923199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1919923200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1930813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1930813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1951372799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1951372800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1962867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1962867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1983427199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1983427200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1994317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1994317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2014876799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2014876800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2025766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2025766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2046326399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2046326400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2057216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2057216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2077775999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2077776000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2088665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2088666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2109225599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2109225600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2120115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2120115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2140675199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2140675200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Eirunepe.json b/dojox/date/tests/tztests/tz_America-Eirunepe.json
new file mode 100644
index 0000000..40f36e4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Eirunepe.json
@@ -0,0 +1,76 @@
+({
+	name: "date.timezone.America-Eirunepe",
+	runTest: function(t){
+		var tz = "America/Eirunepe";
+		doh.checkDate({tzOffset: 279.466666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 279.466666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 279.466666666667, tzAbbr: "LMT"}, -1767208833000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -1767208832000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -1206950401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -1206950400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -1191355201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -1191355200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -1175367601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -1175367600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -1159819201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -1159819200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -633812401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -633812400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -622062001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -622062000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -602276401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -602276400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -591825601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -591825600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -570740401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -570740400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -560203201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -560203200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -539118001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -539118000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -531345601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -531345600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -191358001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -191358000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -184190401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -184190400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -155156401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -155156400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -150062401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -150062400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -128890801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -128890800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -121118401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -121118400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -99946801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -99946800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -89582401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -89582400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -68410801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -68410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -57960001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -57960000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 499755599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 499755600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 511243199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 511243200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 530600399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 530600400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 540273599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 540273600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 562136399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 562136400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 571204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 571204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 750833999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 750834000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 761716799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 761716800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 1214283599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1214283600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-El_Salvador.json b/dojox/date/tests/tztests/tz_America-El_Salvador.json
new file mode 100644
index 0000000..a0ff44c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-El_Salvador.json
@@ -0,0 +1,22 @@
+({
+	name: "date.timezone.America-El_Salvador",
+	runTest: function(t){
+		var tz = "America/El_Salvador";
+		doh.checkDate({tzOffset: 356.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 356.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 356.8, tzAbbr: "LMT"}, -1546279393000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1546279392000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 547019999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 547020000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 559717199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 559717200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 578469599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 578469600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 591166799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 591166800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Fortaleza.json b/dojox/date/tests/tztests/tz_America-Fortaleza.json
new file mode 100644
index 0000000..479f3ed
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Fortaleza.json
@@ -0,0 +1,90 @@
+({
+	name: "date.timezone.America-Fortaleza",
+	runTest: function(t){
+		var tz = "America/Fortaleza";
+		doh.checkDate({tzOffset: 154, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 154, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 154, tzAbbr: "LMT"}, -1767216361000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1767216360000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1206957601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1206957600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1191362401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1191362400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1175374801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1175374800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1159826401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1159826400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -633819601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -633819600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -622069201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -622069200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -602283601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -602283600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -591832801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -591832800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -570747601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -570747600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -560210401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -560210400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -539125201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -539125200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -531352801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -531352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -191365201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -191365200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -184197601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -184197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -155163601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -155163600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -150069601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -150069600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -128898001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -128898000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -121125601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -121125600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -99954001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -99954000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -89589601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -89589600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -68418001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -68418000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -57967201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -57967200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 499748399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 499748400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 511235999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 511236000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 530593199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 530593200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 540266399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 540266400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 562129199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 562129200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 571197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 571197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 592973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 592974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 602042399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 602042400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 634701599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 634701600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 951616799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 951616800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 970973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 970974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 972179999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 972180000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1003028399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1003028400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1013911199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1013911200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Glace_Bay.json b/dojox/date/tests/tztests/tz_America-Glace_Bay.json
new file mode 100644
index 0000000..06fa374
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Glace_Bay.json
@@ -0,0 +1,292 @@
+({
+	name: "date.timezone.America-Glace_Bay",
+	runTest: function(t){
+		var tz = "America/Glace_Bay";
+		doh.checkDate({tzOffset: 239.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 239.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 239.8, tzAbbr: "LMT"}, -2131646413000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -2131646412000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1632074401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1632074400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1614798001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1614798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -880221601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -880221600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -765399601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -765399600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -526500001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -526500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -513198001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -513198000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 73461599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 73461600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 89182799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 89182800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 104911199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 104911200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 120632399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 120632400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 136360799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 136360800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 152081999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 152082000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 167810399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 167810400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 183531599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 183531600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 199259999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 199260000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 215585999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 215586000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 230709599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 230709600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 247035599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 247035600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 262763999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 262764000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 278485199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 278485200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 294213599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 294213600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 309934799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 309934800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 325663199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 325663200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 341384399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 341384400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 357112799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 357112800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 372833999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 372834000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 388562399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 388562400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 404888399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 404888400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 420011999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 420012000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 436337999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 436338000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 452066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 452066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 467787599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 467787600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 483515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 483516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 499237199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 499237200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 514965599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 514965600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 530686799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 530686800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 544600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 544600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 562136399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 562136400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 576050399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 576050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 594190799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 594190800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 607499999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 607500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 625640399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 625640400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 638949599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 638949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 657089999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 657090000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 671003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 671004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 688539599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 688539600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 702453599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 702453600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 719989199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 719989200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 733903199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 733903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 752043599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 752043600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 765352799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 765352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 783493199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 783493200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 796802399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 796802400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 814942799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 814942800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 828856799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 828856800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 846392399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 846392400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 860306399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 860306400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 877841999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 877842000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 891755999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 891756000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 909291599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 909291600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 923205599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 923205600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 941345999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 941346000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 954655199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 954655200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 972795599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 972795600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 986104799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 986104800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1004245199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1004245200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1018159199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1018159200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1035694799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1035694800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1049608799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1049608800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1067144399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1067144400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1081058399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1081058400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1099198799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1099198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1112507999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1112508000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1130648399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1130648400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1143957599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1143957600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1162097999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1162098000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1173592799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1173592800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1194152399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1194152400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1205042399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1205042400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1225601999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1225602000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1236491999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1236492000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1257051599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1257051600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1268546399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1268546400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1289105999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1289106000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1299995999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1299996000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1320555599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1320555600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1331445599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1331445600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1352005199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1352005200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1362895199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1362895200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1383454799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1383454800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1394344799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1394344800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1414904399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1414904400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1425794399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1425794400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1446353999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1446354000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1457848799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1457848800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1478408399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1478408400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1489298399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1489298400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1509857999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1509858000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1520747999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1520748000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1541307599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1541307600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1552197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1552197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1572757199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1572757200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1583647199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1583647200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1604206799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1604206800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1615701599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1615701600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1636261199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1636261200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1647151199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1647151200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1667710799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1667710800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1678600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1678600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1699160399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1699160400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1710050399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1710050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1730609999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1730610000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1741499999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1741500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1762059599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1762059600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1772949599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1772949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1793509199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1793509200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1805003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1805004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1825563599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1825563600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1836453599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1836453600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1857013199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1857013200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1867903199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1867903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1888462799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1888462800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1899352799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1899352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1919912399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1919912400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1930802399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1930802400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1951361999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1951362000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1962856799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1962856800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1983416399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1983416400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1994306399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1994306400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2014865999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2014866000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2025755999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2025756000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2046315599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2046315600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2057205599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2057205600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2077765199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2077765200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2088655199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2088655200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2109214799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2109214800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2120104799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2120104800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2140664399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2140664400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Godthab.json b/dojox/date/tests/tztests/tz_America-Godthab.json
new file mode 100644
index 0000000..ac07460
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Godthab.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.America-Godthab",
+	runTest: function(t){
+		var tz = "America/Godthab";
+		doh.checkDate({tzOffset: 206.933333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 206.933333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 206.933333333333, tzAbbr: "LMT"}, -1686083585000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, -1686083584000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 323845199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 323845200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "WGT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 120, tzAbbr: "WGST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Goose_Bay.json b/dojox/date/tests/tztests/tz_America-Goose_Bay.json
new file mode 100644
index 0000000..bb10689
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Goose_Bay.json
@@ -0,0 +1,418 @@
+({
+	name: "date.timezone.America-Goose_Bay",
+	runTest: function(t){
+		var tz = "America/Goose_Bay";
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1632076149000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1632076148000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1614799749000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1614799748000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1096921749000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1096921748000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1061670601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -1061670600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -1048973401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1048973400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1030221001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -1030221000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -1017523801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1017523800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -998771401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -998771400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -986074201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -986074200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -966717001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -966717000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -954624601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -954624600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -935267401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -935267400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -922570201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -922570200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -903817801000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -903817800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -891120601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -891120600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -872368201000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NWT"}, -872368200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NPT"}, -765401401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -765401400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -746044201000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -746044200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -733347001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -733347000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -714594601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -714594600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -701897401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -701897400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -683145001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -683145000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -670447801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -670447800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -651695401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -651695400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -638998201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -638998200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -619641001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -619641000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -606943801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -606943800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -589401001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -589401000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -576099001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -576099000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -557951401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -557951400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -544649401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -544649400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -526501801000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -526501800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -513199801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -513199800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -495052201000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -495052200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -481750201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -481750200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -463602601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -463602600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -450300601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -450300600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -431548201000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -431548200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -418246201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -418246200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -400098601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -400098600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -386796601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -386796600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -368649001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -368649000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -355347001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -355347000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -337199401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -337199400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -323897401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -323897400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -305749801000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -305749800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -289423801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -289423800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -273695401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -273695400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -257974201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -257974200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -242245801000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -242245800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -226524601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -226524600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -210796201000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -210796200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -195075001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -195075000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -179346601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -179346600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -163625401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -163625400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -147897001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -147897000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -131571001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -131571000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -119903401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -119903400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -116445601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -116445600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -100119601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -100119600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -84391201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -84391200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -68670001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -68670000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -52941601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -52941600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -37220401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -37220400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -21492001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -21492000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -5770801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -5770800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 9957599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 9957600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 25678799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 25678800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 41407199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 41407200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 57733199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 57733200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 73461599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 73461600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 89182799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 89182800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 104911199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 104911200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 120632399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 120632400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 136360799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 136360800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 152081999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 152082000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 167810399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 167810400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 183531599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 183531600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 199259999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 199260000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 215585999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 215586000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 230709599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 230709600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 247035599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 247035600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 262763999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 262764000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 278485199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 278485200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 294213599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 294213600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 309934799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 309934800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 325663199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 325663200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 341384399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 341384400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 357112799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 357112800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 372833999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 372834000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 388562399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 388562400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 404888399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 404888400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 420011999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 420012000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 436337999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 436338000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 452066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 452066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 467787599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 467787600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 483515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 483516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 499237199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 499237200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 514965599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 514965600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 530686799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 530686800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 544593659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 544593660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 562129259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 562129260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 576043259000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ADDT"}, 576043260000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ADDT"}, 594180059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 594180060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 607492859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 607492860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 625633259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 625633260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 638942459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 638942460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 657082859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 657082860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 670996859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 670996860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 688532459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 688532460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 702446459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 702446460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 719982059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 719982060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 733896059000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 733896060000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 752036459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 752036460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 765345659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 765345660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 783486059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 783486060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 796795259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 796795260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 814935659000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 814935660000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 828849659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 828849660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 846385259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 846385260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 860299259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 860299260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 877834859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 877834860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 891748859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 891748860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 909284459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 909284460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 923198459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 923198460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 941338859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 941338860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 954648059000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 954648060000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 972788459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 972788460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 986097659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 986097660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1004238059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1004238060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1018152059000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1018152060000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1035687659000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1035687660000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1049601659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1049601660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1067137259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1067137260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1081051259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1081051260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1099191659000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1099191660000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1112500859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1112500860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1130641259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1130641260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1143950459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1143950460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1162090859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1162090860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1173585659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1173585660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1194145259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1194145260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1205035259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1205035260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1225594859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1225594860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1236484859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1236484860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1257044459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1257044460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1268539259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1268539260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1289098859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1289098860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1299988859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1299988860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1320548459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1320548460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1331438459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1331438460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1351998059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1351998060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1362888059000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1362888060000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1383447659000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1383447660000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1394337659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1394337660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1414897259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1414897260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1425787259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1425787260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1446346859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1446346860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1457841659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1457841660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1478401259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1478401260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1489291259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1489291260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1509850859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1509850860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1520740859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1520740860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1541300459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1541300460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1552190459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1552190460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1572750059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1572750060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1583640059000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1583640060000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1604199659000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1604199660000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1615694459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1615694460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1636254059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1636254060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1647144059000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1647144060000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1667703659000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1667703660000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1678593659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1678593660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1699153259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1699153260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1710043259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1710043260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1730602859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1730602860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1741492859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1741492860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1762052459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1762052460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1772942459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1772942460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1793502059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1793502060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1804996859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1804996860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1825556459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1825556460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1836446459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1836446460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1857006059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1857006060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1867896059000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1867896060000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1888455659000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1888455660000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1899345659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1899345660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1919905259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1919905260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1930795259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1930795260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1951354859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1951354860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1962849659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1962849660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1983409259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1983409260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1994299259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1994299260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2014858859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2014858860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2025748859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2025748860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2046308459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2046308460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2057198459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2057198460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2077758059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2077758060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2088648059000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2088648060000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2109207659000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2109207660000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2120097659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2120097660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2140657259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2140657260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Grand_Turk.json b/dojox/date/tests/tztests/tz_America-Grand_Turk.json
new file mode 100644
index 0000000..72ae180
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Grand_Turk.json
@@ -0,0 +1,250 @@
+({
+	name: "date.timezone.America-Grand_Turk",
+	runTest: function(t){
+		var tz = "America/Grand_Turk";
+		doh.checkDate({tzOffset: 307.2, tzAbbr: "KMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 307.2, tzAbbr: "KMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 307.2, tzAbbr: "KMT"}, -1827687169000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1827687168000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 294217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 294217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 309938399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 309938400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467791199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467791200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499240799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530690399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 544604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 544604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562139999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 954658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 954658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 972799199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Grenada.json b/dojox/date/tests/tztests/tz_America-Grenada.json
new file mode 100644
index 0000000..bd1246a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Grenada.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-Grenada",
+	runTest: function(t){
+		var tz = "America/Grenada";
+		doh.checkDate({tzOffset: 247, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 247, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 247, tzAbbr: "LMT"}, -1846266781000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1846266780000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Guadeloupe.json b/dojox/date/tests/tztests/tz_America-Guadeloupe.json
new file mode 100644
index 0000000..5f70ad7
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Guadeloupe.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-Guadeloupe",
+	runTest: function(t){
+		var tz = "America/Guadeloupe";
+		doh.checkDate({tzOffset: 246.133333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 246.133333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 246.133333333333, tzAbbr: "LMT"}, -1848254033000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1848254032000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Guatemala.json b/dojox/date/tests/tztests/tz_America-Guatemala.json
new file mode 100644
index 0000000..e7a5f79
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Guatemala.json
@@ -0,0 +1,30 @@
+({
+	name: "date.timezone.America-Guatemala",
+	runTest: function(t){
+		var tz = "America/Guatemala";
+		doh.checkDate({tzOffset: 362.066666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 362.066666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 362.066666666667, tzAbbr: "LMT"}, -1617040677000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1617040676000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 123055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 123055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 130913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 130914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 422344799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 422344800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 433054799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 433054800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 669707999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 669708000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 684219599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 684219600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1146376799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1146376800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1159678799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1159678800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Guayaquil.json b/dojox/date/tests/tztests/tz_America-Guayaquil.json
new file mode 100644
index 0000000..d3b5b1b
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Guayaquil.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-Guayaquil",
+	runTest: function(t){
+		var tz = "America/Guayaquil";
+		doh.checkDate({tzOffset: 314, tzAbbr: "QMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 314, tzAbbr: "QMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 314, tzAbbr: "QMT"}, -1230749161000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ECT"}, -1230749160000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ECT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ECT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ECT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ECT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Guyana.json b/dojox/date/tests/tztests/tz_America-Guyana.json
new file mode 100644
index 0000000..3457149
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Guyana.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.America-Guyana",
+	runTest: function(t){
+		var tz = "America/Guyana";
+		doh.checkDate({tzOffset: 232.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 232.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 232.666666666667, tzAbbr: "LMT"}, -1730578041000, tz, 1);
+		doh.checkDate({tzOffset: 225, tzAbbr: "GBGT"}, -1730578040000, tz, 1);
+		doh.checkDate({tzOffset: 225, tzAbbr: "GBGT"}, -113688901000, tz, 1);
+		doh.checkDate({tzOffset: 225, tzAbbr: "GYT"}, -113688900000, tz, 1);
+		doh.checkDate({tzOffset: 225, tzAbbr: "GYT"}, 176010299000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "GYT"}, 176010300000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "GYT"}, 662698799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "GYT"}, 662698800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "GYT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "GYT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "GYT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "GYT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Halifax.json b/dojox/date/tests/tztests/tz_America-Halifax.json
new file mode 100644
index 0000000..a2294a1
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Halifax.json
@@ -0,0 +1,468 @@
+({
+	name: "date.timezone.America-Halifax",
+	runTest: function(t){
+		var tz = "America/Halifax";
+		doh.checkDate({tzOffset: 254.4, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 254.4, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 254.4, tzAbbr: "LMT"}, -2131645537000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -2131645536000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1696276801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1696276800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1680469201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1680469200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1632074401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1632074400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1614798001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1614798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1566763201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1566763200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1557090001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1557090000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1535486401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1535486400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1524949201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1524949200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1504468801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1504468800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1493413201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1493413200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1472414401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1472414400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1461963601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1461963600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1440964801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1440964800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1429390801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1429390800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1409515201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1409515200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1396731601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1396731600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1376856001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1376856000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1366491601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1366491600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1346616001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1346616000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1333832401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1333832400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1313956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1313956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1303678801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1303678800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1282507201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1282507200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1272661201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1272661200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1251057601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1251057600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1240088401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1240088400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1219608001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1219608000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1207429201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1207429200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1188763201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1188763200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1175979601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1175979600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1157313601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1157313600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1143925201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1143925200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1124049601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1124049600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1113771601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1113771600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1091390401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1091390400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1081026001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1081026000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1059854401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1059854400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1050786001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1050786000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1030910401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1030910400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1018126801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1018126800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -999460801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -999460800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -986677201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -986677200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -965592001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -965592000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -955227601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -955227600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -935956801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -935956800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -923173201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -923173200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -904507201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -904507200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -891723601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -891723600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -880221601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -880221600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -765399601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -765399600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -747252001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -747252000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -733950001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -733950000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -715802401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -715802400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -702500401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -702500400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -684352801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -684352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -671050801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -671050800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -652903201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -652903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -639601201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -639601200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -589399201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -589399200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -576097201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -576097200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -557949601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -557949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -544647601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -544647600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -526500001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -526500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -513198001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -513198000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -495050401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -495050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -481748401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -481748400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -431546401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -431546400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -418244401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -418244400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -400096801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -400096800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -386794801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -386794800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -368647201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -368647200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -355345201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -355345200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -337197601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -337197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -323895601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -323895600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -242244001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -242244000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -226522801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -226522800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -210794401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -210794400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -195073201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -195073200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -179344801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -179344800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -163623601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -163623600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -147895201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -147895200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -131569201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -131569200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -116445601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -116445600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -100119601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -100119600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -84391201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -84391200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -68670001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -68670000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -52941601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -52941600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -37220401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -37220400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -21492001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -21492000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -5770801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -5770800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 9957599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 9957600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 25678799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 25678800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 41407199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 41407200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 57733199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 57733200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 73461599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 73461600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 89182799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 89182800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 104911199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 104911200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 120632399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 120632400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 136360799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 136360800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 152081999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 152082000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 167810399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 167810400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 183531599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 183531600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 199259999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 199260000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 215585999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 215586000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 230709599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 230709600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 247035599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 247035600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 262763999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 262764000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 278485199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 278485200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 294213599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 294213600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 309934799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 309934800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 325663199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 325663200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 341384399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 341384400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 357112799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 357112800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 372833999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 372834000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 388562399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 388562400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 404888399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 404888400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 420011999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 420012000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 436337999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 436338000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 452066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 452066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 467787599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 467787600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 483515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 483516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 499237199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 499237200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 514965599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 514965600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 530686799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 530686800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 544600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 544600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 562136399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 562136400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 576050399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 576050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 594190799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 594190800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 607499999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 607500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 625640399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 625640400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 638949599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 638949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 657089999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 657090000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 671003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 671004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 688539599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 688539600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 702453599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 702453600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 719989199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 719989200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 733903199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 733903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 752043599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 752043600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 765352799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 765352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 783493199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 783493200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 796802399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 796802400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 814942799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 814942800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 828856799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 828856800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 846392399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 846392400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 860306399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 860306400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 877841999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 877842000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 891755999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 891756000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 909291599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 909291600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 923205599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 923205600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 941345999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 941346000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 954655199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 954655200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 972795599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 972795600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 986104799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 986104800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1004245199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1004245200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1018159199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1018159200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1035694799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1035694800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1049608799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1049608800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1067144399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1067144400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1081058399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1081058400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1099198799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1099198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1112507999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1112508000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1130648399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1130648400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1143957599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1143957600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1162097999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1162098000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1173592799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1173592800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1194152399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1194152400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1205042399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1205042400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1225601999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1225602000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1236491999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1236492000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1257051599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1257051600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1268546399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1268546400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1289105999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1289106000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1299995999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1299996000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1320555599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1320555600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1331445599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1331445600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1352005199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1352005200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1362895199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1362895200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1383454799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1383454800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1394344799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1394344800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1414904399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1414904400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1425794399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1425794400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1446353999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1446354000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1457848799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1457848800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1478408399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1478408400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1489298399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1489298400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1509857999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1509858000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1520747999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1520748000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1541307599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1541307600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1552197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1552197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1572757199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1572757200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1583647199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1583647200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1604206799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1604206800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1615701599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1615701600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1636261199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1636261200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1647151199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1647151200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1667710799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1667710800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1678600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1678600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1699160399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1699160400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1710050399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1710050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1730609999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1730610000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1741499999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1741500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1762059599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1762059600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1772949599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1772949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1793509199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1793509200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1805003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1805004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1825563599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1825563600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1836453599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1836453600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1857013199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1857013200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1867903199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1867903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1888462799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1888462800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1899352799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1899352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1919912399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1919912400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1930802399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1930802400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1951361999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1951362000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1962856799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1962856800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1983416399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1983416400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1994306399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1994306400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2014865999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2014866000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2025755999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2025756000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2046315599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2046315600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2057205599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2057205600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2077765199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2077765200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2088655199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2088655200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2109214799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2109214800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2120104799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2120104800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2140664399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2140664400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Havana.json b/dojox/date/tests/tztests/tz_America-Havana.json
new file mode 100644
index 0000000..3bba88a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Havana.json
@@ -0,0 +1,322 @@
+({
+	name: "date.timezone.America-Havana",
+	runTest: function(t){
+		var tz = "America/Havana";
+		doh.checkDate({tzOffset: 329.6, tzAbbr: "HMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 329.6, tzAbbr: "HMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 329.6, tzAbbr: "HMT"}, -1402813825000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -1402813824000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -1311534001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -1311534000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -1300996801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -1300996800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -933534001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -933534000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -925675201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -925675200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -902084401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -902084400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -893620801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -893620800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -870030001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -870030000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -862171201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -862171200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -775681201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -775681200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -767822401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -767822400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -744231601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -744231600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -736372801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -736372800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -144702001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -144702000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -134251201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -134251200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -113425201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -113425200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -102542401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -102542400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -86295601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -86295600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -72907201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -72907200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -54154801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -54154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -41457601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -41457600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -21495601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -21495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, -5774401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, -5774400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 9953999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 9954000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 25675199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 25675200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 41403599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 41403600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 57729599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 57729600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 73457999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 73458000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 87364799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 87364800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 104907599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 104907600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 118900799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 118900800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 136357199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 136357200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 150436799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 150436800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 167806799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 167806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 183527999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 183528000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 199256399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 199256400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 215582399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 215582400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 230705999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 230706000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 247031999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 247032000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 263365199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 263365200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 276667199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 276667200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 290581199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 290581200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 308721599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 308721600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 322030799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 322030800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 340171199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 340171200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 358318799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 358318800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 371620799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 371620800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 389768399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 389768400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 403070399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 403070400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 421217999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 421218000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 434519999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 434520000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 452667599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 452667600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 466574399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 466574400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 484117199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 484117200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 498023999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 498024000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 511333199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 511333200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 529473599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 529473600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 542782799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 542782800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 560923199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 560923200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 574837199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 574837200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 592372799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 592372800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 606286799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 606286800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 623822399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 623822400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 638945999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 638946000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 655876799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 655876800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 671000399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 671000400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 687329999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 687330000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 702449999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 702450000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 718779599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 718779600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 733899599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 733899600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 750229199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 750229200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 765349199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 765349200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 781678799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 781678800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 796798799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 796798800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 813128399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 813128400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 828853199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 828853200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 844577999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 844578000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 860302799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 860302800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 876632399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 876632400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 891147599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 891147600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 909291599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 909291600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 922597199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 922597200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 941345999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 941346000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 954651599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 954651600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 972795599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 972795600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 986101199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 986101200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1004245199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1004245200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1018155599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1018155600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1035694799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1035694800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1049605199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1049605200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1067144399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1067144400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1081054799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1081054800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1162097999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1162098000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1173589199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1173589200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1193547599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1193547600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1205643599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1205643600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1224997199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1224997200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1236488399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1236488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1256446799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1256446800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1268542799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1268542800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1288501199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1288501200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1299992399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1299992400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1319950799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1319950800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1331441999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1331442000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1351400399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1351400400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1362891599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1362891600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1382849999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1382850000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1394341199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1394341200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1414299599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1414299600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1425790799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1425790800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1445749199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1445749200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1457845199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1457845200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1477803599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1477803600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1489294799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1489294800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1509253199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1509253200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1520744399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1520744400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1540702799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1540702800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1552193999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1552194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1572152399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1572152400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1583643599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1583643600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1603601999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1603602000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1615697999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1615698000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1635656399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1635656400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1647147599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1647147600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1667105999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1667106000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1678597199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1678597200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1698555599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1698555600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1710046799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1710046800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1730005199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1730005200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1741496399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1741496400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1761454799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1761454800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1772945999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1772946000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1792904399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1792904400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1805000399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1805000400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1824958799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1824958800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1836449999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1836450000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1856408399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1856408400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1867899599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1867899600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1887857999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1887858000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1899349199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1899349200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1919307599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1919307600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1930798799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1930798800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1950757199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1950757200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1962853199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1962853200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1982811599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1982811600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1994302799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1994302800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 2014261199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 2014261200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 2025752399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 2025752400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 2045710799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 2045710800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 2057201999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 2057202000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 2077160399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 2077160400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 2088651599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 2088651600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 2108609999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 2108610000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 2120101199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 2120101200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 2140059599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 2140059600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Hermosillo.json b/dojox/date/tests/tztests/tz_America-Hermosillo.json
new file mode 100644
index 0000000..5638a81
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Hermosillo.json
@@ -0,0 +1,42 @@
+({
+	name: "date.timezone.America-Hermosillo",
+	runTest: function(t){
+		var tz = "America/Hermosillo";
+		doh.checkDate({tzOffset: 443.866666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 443.866666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 443.866666666667, tzAbbr: "LMT"}, -1514739601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1514739600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1343066401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1343066400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1234807201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1234807200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1220292001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1220292000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1207159201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1207159200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1191344401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1191344400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -873828001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -873828000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -661539601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -661539600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 28799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 28800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 828867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 828867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 846403199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 846403200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 860317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 860317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 877852799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 877852800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 891766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 891766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Indiana-Indianapolis.json b/dojox/date/tests/tztests/tz_America-Indiana-Indianapolis.json
new file mode 100644
index 0000000..ef89387
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Indiana-Indianapolis.json
@@ -0,0 +1,208 @@
+({
+	name: "date.timezone.America-Indiana-Indianapolis",
+	runTest: function(t){
+		var tz = "America/Indiana/Indianapolis";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -900259201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -900259200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -891795601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -891795600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -747244801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -747244800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -733942801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -733942800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -715795201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -715795200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -702493201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -702493200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -684345601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -684345600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -671043601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -671043600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -652896001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -652896000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -639594001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -639594000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -620841601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -620841600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -608144401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -608144400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -589392001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -589392000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -576090001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -576090000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -557942401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -557942400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -544640401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -544640400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -526492801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -526492800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -513190801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -513190800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -495043201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -495043200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -481741201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -481741200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -463593601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -463593600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -386787601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -386787600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -368640001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -368640000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Indiana-Knox.json b/dojox/date/tests/tztests/tz_America-Indiana-Knox.json
new file mode 100644
index 0000000..2c893a4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Indiana-Knox.json
@@ -0,0 +1,318 @@
+({
+	name: "date.timezone.America-Indiana-Knox",
+	runTest: function(t){
+		var tz = "America/Indiana/Knox";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -715795201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -715795200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -702493201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -702493200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -684345601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -684345600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -671043601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -671043600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -652896001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -652896000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -639594001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -639594000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -620841601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -620841600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -608144401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -608144400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -589392001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -589392000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -576090001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -576090000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -557942401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -557942400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -544640401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -544640400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -526492801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -526492800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -513190801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -513190800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -495043201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -495043200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -481741201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -481741200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -463593601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -463593600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -447267601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -447267600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -431539201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -431539200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -415818001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -415818000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -400089601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -400089600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -386787601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -386787600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -368640001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -368640000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -355338001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -355338000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -337190401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -337190400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -321469201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -321469200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -305740801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -305740800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -289414801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -289414800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -273686401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -273686400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -257965201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -257965200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -242236801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -242236800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -195066001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -195066000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -84384001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -84384000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -68662801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -68662800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -52934401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -52934400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -37213201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -37213200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -21484801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -21484800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -5763601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -5763600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 9964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 9964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 25685999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 25686000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 41414399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 41414400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 57740399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 57740400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 73468799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 73468800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 89189999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 89190000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 104918399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 104918400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 120639599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 120639600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 126691199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 126691200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 152089199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 152089200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 162374399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 162374400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 183538799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 183538800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 199267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 199267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 215593199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 215593200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 230716799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 230716800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 247042799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 247042800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 262771199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 262771200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 278492399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 278492400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 294220799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 294220800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 309941999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 309942000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 325670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 325670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 341391599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 341391600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 357119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 357120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 372841199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 372841200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 388569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 388569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 404895599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 404895600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 420019199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 420019200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 436345199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 436345200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 452073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 452073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 467794799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 467794800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 483523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 483523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 499244399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 499244400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 514972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 514972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 530693999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 530694000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 544607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 544608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 562143599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 562143600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 576057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 576057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 594197999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 594198000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 607507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 607507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 625647599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 625647600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 638956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 638956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 657097199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 657097200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 671011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 671011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 688546799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688546800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1205049599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1205049600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1236499199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1236499200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1257058799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1257058800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1268553599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1268553600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1289113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1289113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1300003199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1300003200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1320562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1320562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1331452799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1331452800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1352012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1352012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1362902399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1362902400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1383461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1383462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1394351999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1394352000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1425801599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1425801600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1446361199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1446361200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1457855999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1457856000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1478415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1478415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1489305599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1489305600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1520755199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1520755200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1541314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1541314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1552204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1552204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1583654399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1583654400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1604213999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1604214000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1615708799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1615708800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1636268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1636268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1647158399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1647158400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1678607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1678608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1699167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1699167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1710057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1710057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1741507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1741507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1762066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1762066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1772956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1772956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1793516399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1793516400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1805011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1805011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1825570799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1825570800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1836460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1836460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1857020399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1857020400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1867910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1867910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1888469999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1888470000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1899359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1899360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919919599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919919600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1930809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1930809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1951369199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1951369200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1962863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1962864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1983423599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1983423600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1994313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1994313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014873199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014873200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2025763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2025763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2046322799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2046322800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2057212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2057212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077772399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077772400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2088662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2088662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2109221999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2109222000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2120111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2120112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140671599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140671600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Indiana-Marengo.json b/dojox/date/tests/tztests/tz_America-Indiana-Marengo.json
new file mode 100644
index 0000000..84665f8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Indiana-Marengo.json
@@ -0,0 +1,216 @@
+({
+	name: "date.timezone.America-Indiana-Marengo",
+	runTest: function(t){
+		var tz = "America/Indiana/Marengo";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -589392001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -589392000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -576090001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -576090000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -495043201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -495043200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -481741201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -481741200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -463593601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -463593600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -450291601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -450291600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -431539201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -431539200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -418237201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -418237200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -400089601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -400089600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -386787601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -386787600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -368640001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -368640000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -355338001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -355338000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -337190401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -337190400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -323888401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -323888400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -305740801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -305740800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -292438801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -292438800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -273686401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -273686400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 41410799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 41410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 57736799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 57736800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 73465199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 73465200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 89186399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 89186400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 104914799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 104914800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 120635999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 120636000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 126687599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 126687600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 152089199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152089200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 162370799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 162370800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 183535199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 183535200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Indiana-Petersburg.json b/dojox/date/tests/tztests/tz_America-Indiana-Petersburg.json
new file mode 100644
index 0000000..14e0fe8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Indiana-Petersburg.json
@@ -0,0 +1,242 @@
+({
+	name: "date.timezone.America-Indiana-Petersburg",
+	runTest: function(t){
+		var tz = "America/Indiana/Petersburg";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -462996001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -462996000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -450291601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -450291600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -431539201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -431539200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -418237201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -418237200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -400089601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -400089600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -386787601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -386787600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -368640001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -368640000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -355338001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -355338000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -337190401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -337190400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -323888401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -323888400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -305740801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -305740800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -292438801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -292438800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -273686401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -273686400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -257965201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -257965200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -242236801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -242236800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -226515601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -226515600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -210787201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -210787200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -195066001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -195066000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -179337601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -179337600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -163616401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -163616400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -147888001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -147888000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -100112401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -100112400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -84384001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -84384000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -68662801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -68662800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -52934401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -52934400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -37213201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -37213200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -21484801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -21484800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -5763601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -5763600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 9964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 9964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 25685999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 25686000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 41414399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 41414400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 57740399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 57740400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 73468799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 73468800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 89189999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 89190000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 104918399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 104918400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 120639599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 120639600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 126691199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 126691200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 152089199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 152089200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 162374399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 162374400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 183538799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 183538800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 199267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 199267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 215593199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 215593200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 230716799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 230716800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 247042799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 247042800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Indiana-Tell_City.json b/dojox/date/tests/tztests/tz_America-Indiana-Tell_City.json
new file mode 100644
index 0000000..edfb7a3
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Indiana-Tell_City.json
@@ -0,0 +1,212 @@
+({
+	name: "date.timezone.America-Indiana-Tell_City",
+	runTest: function(t){
+		var tz = "America/Indiana/Tell_City";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -747244801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -747244800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -733942801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -733942800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -526492801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -526492800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -513190801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -513190800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -495043201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -495043200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -481741201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -481741200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -462996001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -462996000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -450291601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -450291600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -431539201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -431539200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -418237201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -418237200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -400089601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -400089600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -386787601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -386787600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -368640001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -368640000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -355338001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -355338000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -337190401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -337190400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -323888401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -323888400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -305740801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -305740800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -289414801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -289414800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -273686401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -273686400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -260989201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -260989200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -242236801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -242236800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -226515601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -226515600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -210787201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -210787200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -195066001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -195066000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -179337601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -179337600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1205049599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1205049600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1236499199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1236499200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1257058799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1257058800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1268553599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1268553600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1289113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1289113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1300003199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1300003200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1320562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1320562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1331452799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1331452800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1352012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1352012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1362902399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1362902400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1383461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1383462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1394351999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1394352000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1425801599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1425801600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1446361199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1446361200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1457855999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1457856000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1478415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1478415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1489305599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1489305600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1520755199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1520755200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1541314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1541314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1552204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1552204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1583654399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1583654400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1604213999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1604214000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1615708799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1615708800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1636268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1636268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1647158399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1647158400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1678607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1678608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1699167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1699167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1710057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1710057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1741507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1741507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1762066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1762066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1772956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1772956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1793516399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1793516400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1805011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1805011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1825570799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1825570800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1836460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1836460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1857020399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1857020400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1867910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1867910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1888469999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1888470000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1899359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1899360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919919599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919919600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1930809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1930809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1951369199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1951369200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1962863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1962864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1983423599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1983423600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1994313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1994313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014873199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014873200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2025763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2025763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2046322799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2046322800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2057212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2057212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077772399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077772400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2088662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2088662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2109221999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2109222000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2120111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2120112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140671599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140671600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Indiana-Vevay.json b/dojox/date/tests/tztests/tz_America-Indiana-Vevay.json
new file mode 100644
index 0000000..511e6b8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Indiana-Vevay.json
@@ -0,0 +1,172 @@
+({
+	name: "date.timezone.America-Indiana-Vevay",
+	runTest: function(t){
+		var tz = "America/Indiana/Vevay";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -495043201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -495043200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 41410799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 41410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 57736799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 57736800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 73465199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 73465200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 89186399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 89186400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Indiana-Vincennes.json b/dojox/date/tests/tztests/tz_America-Indiana-Vincennes.json
new file mode 100644
index 0000000..1d63cb9
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Indiana-Vincennes.json
@@ -0,0 +1,212 @@
+({
+	name: "date.timezone.America-Indiana-Vincennes",
+	runTest: function(t){
+		var tz = "America/Indiana/Vincennes";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -747244801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -747244800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -733942801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -733942800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -526492801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -526492800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -513190801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -513190800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -495043201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -495043200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -481741201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -481741200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -462996001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -462996000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -450291601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -450291600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -431539201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -431539200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -418237201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -418237200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -400089601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -400089600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -386787601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -386787600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -368640001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -368640000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -355338001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -355338000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -337190401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -337190400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -323888401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -323888400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -305740801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -305740800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -289414801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -289414800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -273686401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -273686400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -260989201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -260989200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -242236801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -242236800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -226515601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -226515600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -210787201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -210787200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -195066001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -195066000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -179337601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -179337600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Indiana-Winamac.json b/dojox/date/tests/tztests/tz_America-Indiana-Winamac.json
new file mode 100644
index 0000000..af4cfce
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Indiana-Winamac.json
@@ -0,0 +1,224 @@
+({
+	name: "date.timezone.America-Indiana-Winamac",
+	runTest: function(t){
+		var tz = "America/Indiana/Winamac";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -747244801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -747244800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -733942801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -733942800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -715795201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -715795200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -702493201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -702493200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -684345601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -684345600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -671043601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -671043600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -652896001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -652896000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -639594001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -639594000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -620841601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -620841600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -608144401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -608144400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -589392001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -589392000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -576090001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -576090000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -557942401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -557942400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -544640401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -544640400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -526492801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -526492800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -513190801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -513190800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -495043201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -495043200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -481741201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -481741200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -463593601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -463593600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -447267601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -447267600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -431539201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -431539200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -415818001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -415818000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -400089601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -400089600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -386787601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -386787600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -368640001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -368640000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -355338001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -355338000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -337190401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -337190400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -323888401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -323888400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -305740801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -305740800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -292438801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -292438800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -273686401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -273686400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Inuvik.json b/dojox/date/tests/tztests/tz_America-Inuvik.json
new file mode 100644
index 0000000..ea7ab5c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Inuvik.json
@@ -0,0 +1,252 @@
+({
+	name: "date.timezone.America-Inuvik",
+	runTest: function(t){
+		var tz = "America/Inuvik";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -536457601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -536457600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -147888001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "PDDT"}, -147888000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "PDDT"}, -131558401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -131558400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 294227999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 294228000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 325673999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 325674000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 341395199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 341395200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 357123599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 357123600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 372844799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 372844800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 388573199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 388573200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 404899199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 404899200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 420022799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 420022800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 436348799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 436348800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 452077199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 452077200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 467798399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 467798400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 483526799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 483526800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 499247999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 499248000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 514976399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 514976400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 530697599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 530697600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 544611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 544611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 562147199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 562147200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 576061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 576061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 594201599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 594201600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 607510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 607510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 625651199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 625651200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 638960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 638960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 657100799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 657100800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 671014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 671014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 688550399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 688550400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 702464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 702464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 719999999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 720000000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 733913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 733914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 752054399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 752054400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 765363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 765363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 783503999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 783504000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 796813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 796813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 814953599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 814953600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 828867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 828867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 846403199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 846403200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 860317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 860317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 877852799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 877852800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 891766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 891766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 923216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 923216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 941356799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 941356800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 954665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 954666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 972806399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 972806400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 986115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 986115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1004255999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1004256000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1018169999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1018170000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1035705599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1035705600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1049619599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1049619600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1067155199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1067155200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1081069199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1081069200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1099209599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1099209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1112518799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1112518800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1130659199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1130659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1143968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1143968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1162108799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1162108800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1173603599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1173603600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1194163199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1194163200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1205053199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1205053200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1225612799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1225612800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1236502799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1236502800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1257062399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1257062400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1268557199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1268557200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1289116799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1289116800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1300006799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1300006800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1320566399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1320566400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1331456399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1331456400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1352015999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1352016000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1362905999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1362906000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1383465599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1383465600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1394355599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1394355600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1414915199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1414915200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1425805199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1425805200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1446364799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1446364800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1457859599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1457859600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1478419199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1478419200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1489309199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1489309200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1509868799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1509868800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1520758799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1520758800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1541318399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1541318400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1552208399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1552208400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1572767999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1572768000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1583657999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1583658000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1604217599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1604217600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1615712399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1615712400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1636271999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1636272000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1647161999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1647162000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1667721599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1667721600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1678611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1678611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1699171199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1699171200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1710061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1710061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1730620799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1730620800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1741510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1741510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1762070399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1762070400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1772960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1772960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1793519999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1793520000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1805014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1805014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1825574399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1825574400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1836464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1836464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1857023999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1857024000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1867913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1867914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1888473599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1888473600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1899363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1899363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1919923199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1919923200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1930813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1930813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1951372799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1951372800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1962867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1962867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1983427199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1983427200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1994317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1994317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2014876799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2014876800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2025766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2025766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2046326399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2046326400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2057216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2057216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2077775999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2077776000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2088665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2088666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2109225599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2109225600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2120115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2120115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2140675199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2140675200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Iqaluit.json b/dojox/date/tests/tztests/tz_America-Iqaluit.json
new file mode 100644
index 0000000..7fa497f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Iqaluit.json
@@ -0,0 +1,254 @@
+({
+	name: "date.timezone.America-Iqaluit",
+	runTest: function(t){
+		var tz = "America/Iqaluit";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -865296001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -865296000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -765396001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -765396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -147898801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "EDDT"}, -147898800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "EDDT"}, -131569201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -131569200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467791199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467791200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499240799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530690399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 544604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 544604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562139999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Jamaica.json b/dojox/date/tests/tztests/tz_America-Jamaica.json
new file mode 100644
index 0000000..93e2bb8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Jamaica.json
@@ -0,0 +1,54 @@
+({
+	name: "date.timezone.America-Jamaica",
+	runTest: function(t){
+		var tz = "America/Jamaica";
+		doh.checkDate({tzOffset: 307.2, tzAbbr: "KMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 307.2, tzAbbr: "KMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 307.2, tzAbbr: "KMT"}, -1827687169000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1827687168000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 136364399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 136364400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 152085599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152085600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 162370799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 162370800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 183535199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 183535200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 199263599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 199263600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 215589599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 215589600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 230713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 230713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 247039199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 247039200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 262767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 262767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 278488799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 278488800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 294217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 294217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 309938399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 309938400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Juneau.json b/dojox/date/tests/tztests/tz_America-Juneau.json
new file mode 100644
index 0000000..a7fe096
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Juneau.json
@@ -0,0 +1,296 @@
+({
+	name: "date.timezone.America-Juneau",
+	runTest: function(t){
+		var tz = "America/Juneau";
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -880207201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -880207200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -765385201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -765385200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -21477601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -21477600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -5756401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -5756400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 9971999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 9972000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 25693199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 25693200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 41421599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 41421600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 57747599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 57747600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 73475999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 73476000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 89197199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 89197200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 104925599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 104925600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 120646799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 120646800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 126698399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 126698400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 152096399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 152096400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 162381599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 162381600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 183545999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 183546000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 199274399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 199274400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 215600399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 215600400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 230723999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 230724000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 247049999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 247050000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 262778399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 262778400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 278499599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 278499600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 294227999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 294228000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 309949199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 309949200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 325677599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 325677600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 341398799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 341398800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 357127199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 357127200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 372848399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 372848400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 388576799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 388576800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 404902799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 404902800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 420026399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 420026400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 436352399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 436352400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 439030799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 439030800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 452084399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 452084400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 467805599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 467805600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 483533999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 483534000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 499255199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 499255200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 514983599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 514983600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 530704799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 530704800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 544618799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 544618800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 562154399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 562154400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 576068399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 576068400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 594208799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 594208800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 607517999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 607518000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 625658399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 625658400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 638967599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 638967600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 657107999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 657108000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 671021999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 671022000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 688557599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 688557600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 702471599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 702471600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 720007199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 720007200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 733921199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 733921200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 752061599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 752061600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 765370799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 765370800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 783511199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 783511200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 796820399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 796820400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 814960799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 814960800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 828874799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 828874800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 846410399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 846410400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 860324399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 860324400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 877859999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 877860000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 891773999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 891774000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 909309599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 909309600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 923223599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 923223600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 941363999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 941364000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 954673199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 954673200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 972813599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 972813600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 986122799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 986122800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1004263199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1004263200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1018177199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1018177200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1035712799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1035712800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1049626799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1049626800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1067162399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1067162400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1081076399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1081076400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1099216799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1099216800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1112525999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1112526000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1130666399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1130666400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1143975599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1143975600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1162115999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1162116000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1173610799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1173610800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1194170399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1194170400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1205060399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1205060400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1225619999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1225620000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1236509999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1236510000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1257069599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1257069600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1268564399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1268564400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1289123999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1289124000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1300013999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1300014000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1320573599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1320573600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1331463599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1331463600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1352023199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1352023200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1362913199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1362913200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1383472799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1383472800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1394362799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1394362800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1414922399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1414922400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1425812399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1425812400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1446371999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1446372000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1457866799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1457866800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1478426399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1478426400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1489316399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1489316400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1509875999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1509876000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1520765999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1520766000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1541325599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1541325600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1552215599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1552215600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1572775199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1572775200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1583665199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1583665200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1604224799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1604224800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1615719599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1615719600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1636279199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1636279200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1647169199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1647169200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1667728799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1667728800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1678618799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1678618800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1699178399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1699178400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1710068399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1710068400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1730627999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1730628000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1741517999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1741518000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1762077599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1762077600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1772967599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1772967600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1793527199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1793527200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1805021999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1805022000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1825581599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1825581600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1836471599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1836471600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1857031199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1857031200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1867921199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1867921200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1888480799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1888480800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1899370799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1899370800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1919930399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1919930400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1930820399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1930820400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1951379999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1951380000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1962874799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1962874800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1983434399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1983434400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1994324399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1994324400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2014883999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2014884000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2025773999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2025774000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2046333599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2046333600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2057223599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2057223600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2077783199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2077783200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2088673199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2088673200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2109232799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2109232800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2120122799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2120122800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2140682399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2140682400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Kentucky-Louisville.json b/dojox/date/tests/tztests/tz_America-Kentucky-Louisville.json
new file mode 100644
index 0000000..1d999d6
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Kentucky-Louisville.json
@@ -0,0 +1,366 @@
+({
+	name: "date.timezone.America-Kentucky-Louisville",
+	runTest: function(t){
+		var tz = "America/Kentucky/Louisville";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1535904001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1535904000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1525280401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1525280400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -905097601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -905097600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -891795601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -891795600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -757360801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -757360800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -744224401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -744224400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -715795201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -715795200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -608144401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -608144400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -589392001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -589392000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -576090001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -576090000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -557942401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -557942400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -544640401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -544640400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -526492801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -526492800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -513190801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -513190800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -495043201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -495043200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -481741201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -481741200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -463593601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -463593600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -450291601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -450291600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -431539201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -431539200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -415818001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -415818000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -400089601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -400089600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -384368401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -384368400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -368640001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -368640000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -352918801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -352918800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -337190401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -337190400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -321469201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -321469200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -305740801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -305740800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -289414801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -289414800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -273686401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -273686400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -266432401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -266432400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -52938001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -52938000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -37216801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -37216800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 41410799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 41410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 57736799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 57736800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 73465199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 73465200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 89186399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 89186400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 104914799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 104914800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 120635999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 120636000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 126687599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 126687600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 152089199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152089200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 162370799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 162370800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 183535199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 183535200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 199263599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 199263600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 215589599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 215589600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 230713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 230713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 247039199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 247039200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 262767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 262767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 278488799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 278488800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 294217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 294217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 309938399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 309938400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467791199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467791200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499240799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530690399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 544604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 544604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562139999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 954658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 954658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 972799199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Kentucky-Monticello.json b/dojox/date/tests/tztests/tz_America-Kentucky-Monticello.json
new file mode 100644
index 0000000..fa211c2
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Kentucky-Monticello.json
@@ -0,0 +1,306 @@
+({
+	name: "date.timezone.America-Kentucky-Monticello",
+	runTest: function(t){
+		var tz = "America/Kentucky/Monticello";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -52934401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -52934400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -37213201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -37213200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -21484801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -21484800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -5763601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -5763600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 9964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 9964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 25685999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 25686000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 41414399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 41414400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 57740399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 57740400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 73468799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 73468800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 89189999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 89190000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 104918399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 104918400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 120639599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 120639600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 126691199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 126691200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 152089199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 152089200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 162374399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 162374400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 183538799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 183538800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 199267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 199267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 215593199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 215593200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 230716799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 230716800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 247042799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 247042800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 262771199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 262771200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 278492399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 278492400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 294220799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 294220800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 309941999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 309942000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 325670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 325670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 341391599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 341391600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 357119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 357120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 372841199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 372841200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 388569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 388569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 404895599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 404895600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 420019199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 420019200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 436345199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 436345200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 452073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 452073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 467794799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 467794800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 483523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 483523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 499244399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 499244400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 514972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 514972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 530693999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 530694000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 544607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 544608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 562143599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 562143600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 576057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 576057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 594197999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 594198000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 607507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 607507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 625647599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 625647600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 638956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 638956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 657097199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 657097200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 671011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 671011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 688546799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 688546800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 702460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 702460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 719996399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 719996400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 733910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 733910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 752050799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 752050800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 765359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 765360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 783500399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 783500400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 796809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 796809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 814949999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 814950000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-La_Paz.json b/dojox/date/tests/tztests/tz_America-La_Paz.json
new file mode 100644
index 0000000..735dfdb
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-La_Paz.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.America-La_Paz",
+	runTest: function(t){
+		var tz = "America/La_Paz";
+		doh.checkDate({tzOffset: 272.6, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 272.6, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 272.6, tzAbbr: "CMT"}, -1205954845000, tz, 1);
+		doh.checkDate({tzOffset: 212.6, tzAbbr: "BOST"}, -1205954844000, tz, 1);
+		doh.checkDate({tzOffset: 212.6, tzAbbr: "BOST"}, -1192307245000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "BOT"}, -1192307244000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "BOT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "BOT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "BOT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "BOT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Lima.json b/dojox/date/tests/tztests/tz_America-Lima.json
new file mode 100644
index 0000000..53ba324
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Lima.json
@@ -0,0 +1,42 @@
+({
+	name: "date.timezone.America-Lima",
+	runTest: function(t){
+		var tz = "America/Lima";
+		doh.checkDate({tzOffset: 308.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 308.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 308.6, tzAbbr: "LMT"}, -1938538285000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, -1938538284000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, -1009825201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, -1009825200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, -1002052801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, -1002052800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, -986756401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, -986756400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, -971035201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, -971035200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, -955306801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, -955306800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, -939585601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, -939585600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 504939599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, 504939600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, 512711999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 512712000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 536475599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, 536475600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, 544247999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 544248000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 631169999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, 631170000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, 638942399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 638942400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 757400399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, 757400400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "PEST"}, 765172799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 765172800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "PET"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Los_Angeles.json b/dojox/date/tests/tztests/tz_America-Los_Angeles.json
new file mode 100644
index 0000000..f2ee7f7
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Los_Angeles.json
@@ -0,0 +1,382 @@
+({
+	name: "date.timezone.America-Los_Angeles",
+	runTest: function(t){
+		var tz = "America/Los_Angeles";
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1633269601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1633269600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1615129201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1615129200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1601820001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1601820000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1583679601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1583679600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -880207201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -880207200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -765385201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -765385200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -687967201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -687967200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -662655601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -662655600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -620834401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -620834400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -608137201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -608137200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -589384801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -589384800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -576082801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -576082800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -557935201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -557935200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -544633201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -544633200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -526485601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -526485600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -513183601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -513183600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -495036001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -495036000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -481734001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -481734000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -463586401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -463586400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -450284401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -450284400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -431532001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -431532000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -418230001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -418230000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -400082401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -400082400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -386780401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -386780400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -368632801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -368632800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -355330801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -355330800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -337183201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -337183200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -323881201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -323881200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -305733601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -305733600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -292431601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -292431600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -273679201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -273679200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -260982001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -260982000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -242229601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -242229600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -226508401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -226508400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -210780001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -210780000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -195058801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -195058800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -179330401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -179330400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -163609201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -163609200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -147880801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -147880800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -131554801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -131554800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -116431201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -116431200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -100105201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -100105200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -84376801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -84376800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -68655601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -68655600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -52927201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -52927200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -37206001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -37206000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -21477601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -21477600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -5756401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -5756400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 9971999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 9972000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 25693199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 25693200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 41421599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 41421600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 57747599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 57747600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 73475999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 73476000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 89197199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 89197200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 104925599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 104925600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 120646799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 120646800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 126698399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 126698400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 152096399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 152096400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 162381599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 162381600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 183545999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 183546000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 199274399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 199274400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 215600399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 215600400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 230723999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 230724000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 247049999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 247050000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 262778399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 262778400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 278499599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 278499600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 294227999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 294228000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 309949199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 309949200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 325677599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 325677600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 341398799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 341398800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 357127199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 357127200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 372848399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 372848400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 388576799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 388576800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 404902799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 404902800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 420026399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 420026400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 436352399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 436352400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 452080799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 452080800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 467801999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 467802000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 483530399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 483530400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 499251599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 499251600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 514979999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 514980000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 530701199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 530701200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 544615199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 544615200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 562150799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 562150800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 576064799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 576064800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 594205199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 594205200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 607514399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 607514400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 625654799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 625654800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 638963999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 638964000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 657104399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 657104400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 671018399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 671018400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 688553999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 688554000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 702467999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 702468000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 720003599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 720003600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 733917599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 733917600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 752057999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 752058000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 765367199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 765367200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 783507599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 783507600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 796816799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 796816800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 814957199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 814957200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 828871199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 828871200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 846406799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 846406800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 860320799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 860320800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 877856399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 877856400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 891770399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 891770400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 909305999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 909306000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 923219999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 923220000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 941360399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 941360400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 954669599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 954669600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 972809999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 972810000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 986119199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 986119200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1004259599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1004259600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1018173599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1018173600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1035709199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1035709200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1049623199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1049623200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1067158799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1067158800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1081072799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1081072800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1099213199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1099213200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1112522399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1112522400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1130662799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1130662800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1143971999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1143972000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1162112399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1162112400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1173607199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1173607200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1194166799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1194166800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1205056799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1205056800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1225616399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1225616400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1236506399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1236506400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1257065999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1257066000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1268560799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1268560800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1289120399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1289120400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1300010399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1300010400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1320569999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1320570000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1331459999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1331460000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1352019599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1352019600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1362909599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1362909600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1383469199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1383469200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1394359199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1394359200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1414918799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1414918800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1425808799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1425808800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1446368399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1446368400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1457863199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1457863200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1478422799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1478422800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1489312799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1489312800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1509872399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1509872400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1520762399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1520762400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1541321999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1541322000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1552211999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1552212000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1572771599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1572771600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1583661599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1583661600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1604221199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1604221200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1615715999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1615716000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1636275599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1636275600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1647165599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1647165600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1667725199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1667725200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1678615199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1678615200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1699174799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1699174800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1710064799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1710064800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1730624399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1730624400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1741514399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1741514400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1762073999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1762074000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1772963999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1772964000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1793523599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1793523600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1805018399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1805018400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1825577999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1825578000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1836467999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1836468000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1857027599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1857027600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1867917599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1867917600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1888477199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1888477200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1899367199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1899367200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1919926799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1919926800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1930816799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1930816800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1951376399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1951376400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1962871199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1962871200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1983430799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1983430800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1994320799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1994320800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2014880399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2014880400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2025770399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2025770400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2046329999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2046330000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2057219999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2057220000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2077779599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2077779600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2088669599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2088669600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2109229199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2109229200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2120119199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2120119200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2140678799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2140678800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Maceio.json b/dojox/date/tests/tztests/tz_America-Maceio.json
new file mode 100644
index 0000000..a05dfd8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Maceio.json
@@ -0,0 +1,94 @@
+({
+	name: "date.timezone.America-Maceio",
+	runTest: function(t){
+		var tz = "America/Maceio";
+		doh.checkDate({tzOffset: 142.866666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 142.866666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 142.866666666667, tzAbbr: "LMT"}, -1767217029000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1767217028000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1206957601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1206957600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1191362401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1191362400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1175374801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1175374800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1159826401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1159826400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -633819601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -633819600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -622069201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -622069200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -602283601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -602283600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -591832801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -591832800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -570747601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -570747600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -560210401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -560210400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -539125201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -539125200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -531352801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -531352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -191365201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -191365200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -184197601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -184197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -155163601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -155163600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -150069601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -150069600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -128898001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -128898000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -121125601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -121125600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -99954001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -99954000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -89589601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -89589600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -68418001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -68418000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -57967201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -57967200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 499748399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 499748400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 511235999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 511236000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 530593199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 530593200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 540266399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 540266400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 562129199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 562129200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 571197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 571197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 592973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 592974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 602042399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 602042400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 634701599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 634701600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 813725999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 813726000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 824003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 824004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 951616799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 951616800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 970973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 970974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 972179999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 972180000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1003028399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1003028400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1013911199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1013911200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Managua.json b/dojox/date/tests/tztests/tz_America-Managua.json
new file mode 100644
index 0000000..8c8fb7a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Managua.json
@@ -0,0 +1,42 @@
+({
+	name: "date.timezone.America-Managua",
+	runTest: function(t){
+		var tz = "America/Managua";
+		doh.checkDate({tzOffset: 345.2, tzAbbr: "MMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 345.2, tzAbbr: "MMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 345.2, tzAbbr: "MMT"}, -1121105689000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1121105688000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 105083999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 105084000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 161758799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 161758800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 290584799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 290584800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 299134799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 299134800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 322034399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 322034400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 330584399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 330584400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 694259999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 694260000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 717310799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 717310800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 725867999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 725868000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 852094799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 852094800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1113112799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1113112800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1128229199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1128229200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1146383999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1146384000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1159682399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1159682400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Manaus.json b/dojox/date/tests/tztests/tz_America-Manaus.json
new file mode 100644
index 0000000..9352da8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Manaus.json
@@ -0,0 +1,74 @@
+({
+	name: "date.timezone.America-Manaus",
+	runTest: function(t){
+		var tz = "America/Manaus";
+		doh.checkDate({tzOffset: 240.066666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 240.066666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 240.066666666667, tzAbbr: "LMT"}, -1767211197000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1767211196000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1206954001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1206954000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1191358801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1191358800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1175371201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1175371200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1159822801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1159822800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -633816001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -633816000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -622065601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -622065600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -602280001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -602280000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -591829201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -591829200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -570744001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -570744000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -560206801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -560206800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -539121601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -539121600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -531349201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -531349200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -191361601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -191361600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -155160001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -155160000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -150066001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -150066000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -128894401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -128894400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -99950401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -99950400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -89586001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -89586000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -68414401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -68414400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -57963601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -57963600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 499751999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 499752000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 511239599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 511239600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 530596799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 530596800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 540269999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 540270000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 562132799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 562132800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 571201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 571201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 750830399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 750830400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 761713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 761713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Martinique.json b/dojox/date/tests/tztests/tz_America-Martinique.json
new file mode 100644
index 0000000..abd498a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Martinique.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.America-Martinique",
+	runTest: function(t){
+		var tz = "America/Martinique";
+		doh.checkDate({tzOffset: 244.333333333333, tzAbbr: "FFMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 244.333333333333, tzAbbr: "FFMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 244.333333333333, tzAbbr: "FFMT"}, -1851537341000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1851537340000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 323841599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 323841600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 338957999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 338958000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Mazatlan.json b/dojox/date/tests/tztests/tz_America-Mazatlan.json
new file mode 100644
index 0000000..a3706f4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Mazatlan.json
@@ -0,0 +1,198 @@
+({
+	name: "date.timezone.America-Mazatlan",
+	runTest: function(t){
+		var tz = "America/Mazatlan";
+		doh.checkDate({tzOffset: 425.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 425.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 425.666666666667, tzAbbr: "LMT"}, -1514739601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1514739600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1343066401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1343066400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1234807201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1234807200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1220292001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1220292000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1207159201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1207159200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1191344401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1191344400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -873828001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -873828000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -661539601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -661539600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 28799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 28800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 828867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 828867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 846403199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 846403200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 860317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 860317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 877852799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 877852800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 891766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 891766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 923216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 923216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 941356799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 941356800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 954665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 954666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 972806399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 972806400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 989139599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 989139600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1001836799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1001836800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1018169999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1018170000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1035705599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1035705600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1049619599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1049619600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1067155199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1067155200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1081069199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1081069200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1099209599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1099209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1112518799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1112518800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1130659199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1130659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1143968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1143968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1162108799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1162108800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1175417999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1175418000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1193558399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1193558400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1207472399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1207472400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1225007999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1225008000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1238921999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1238922000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1256457599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1256457600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1270371599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1270371600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1288511999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1288512000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1301821199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1301821200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1319961599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1319961600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1333270799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1333270800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1351411199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1351411200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1365325199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1365325200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1382860799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1382860800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1396774799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1396774800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1414310399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1414310400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1428224399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1428224400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1445759999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1445760000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1459673999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1459674000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1477814399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1477814400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1491123599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1491123600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1509263999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1509264000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1522573199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1522573200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1540713599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1540713600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1554627599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1554627600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1572163199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1572163200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1586077199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1586077200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1603612799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1603612800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1617526799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1617526800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1635667199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1635667200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1648976399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1648976400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1667116799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1667116800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1680425999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1680426000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1698566399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1698566400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1712480399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1712480400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1730015999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1730016000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1743929999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1743930000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1761465599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1761465600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1775379599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1775379600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1792915199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1792915200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1806829199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1806829200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1824969599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1824969600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1838278799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1838278800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1856419199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1856419200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1869728399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1869728400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1887868799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1887868800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1901782799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1901782800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1919318399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1919318400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1933232399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1933232400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1950767999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1950768000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1964681999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1964682000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1982822399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1982822400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1996131599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1996131600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2014271999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2014272000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2027581199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2027581200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2045721599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2045721600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2059030799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2059030800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2077171199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2077171200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2091085199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2091085200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2108620799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2108620800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2122534799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2122534800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2140070399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2140070400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Menominee.json b/dojox/date/tests/tztests/tz_America-Menominee.json
new file mode 100644
index 0000000..45d8d64
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Menominee.json
@@ -0,0 +1,296 @@
+({
+	name: "date.timezone.America-Menominee",
+	runTest: function(t){
+		var tz = "America/Menominee";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -747244801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -747244800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -733942801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -733942800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -116438401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -116438400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -100112401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -100112400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -21484801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21484800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 104914799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 104914800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 120639599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 120639600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 126691199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 126691200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 152089199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 152089200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 162374399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 162374400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 183538799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 183538800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 199267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 199267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 215593199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 215593200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 230716799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 230716800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 247042799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 247042800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 262771199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 262771200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 278492399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 278492400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 294220799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 294220800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 309941999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 309942000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 325670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 325670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 341391599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 341391600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 357119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 357120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 372841199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 372841200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 388569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 388569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 404895599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 404895600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 420019199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 420019200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 436345199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 436345200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 452073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 452073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 467794799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 467794800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 483523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 483523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 499244399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 499244400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 514972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 514972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 530693999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 530694000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 544607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 544608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 562143599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 562143600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 576057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 576057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 594197999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 594198000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 607507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 607507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 625647599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 625647600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 638956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 638956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 657097199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 657097200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 671011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 671011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 688546799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 688546800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 702460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 702460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 719996399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 719996400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 733910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 733910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 752050799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 752050800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 765359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 765360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 783500399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 783500400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 796809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 796809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 814949999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 814950000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 986111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 986112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1004252399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1004252400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035701999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035702000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067151599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067151600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1205049599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1205049600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1236499199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1236499200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1257058799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1257058800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1268553599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1268553600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1289113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1289113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1300003199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1300003200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1320562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1320562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1331452799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1331452800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1352012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1352012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1362902399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1362902400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1383461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1383462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1394351999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1394352000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1425801599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1425801600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1446361199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1446361200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1457855999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1457856000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1478415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1478415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1489305599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1489305600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1520755199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1520755200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1541314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1541314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1552204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1552204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1583654399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1583654400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1604213999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1604214000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1615708799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1615708800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1636268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1636268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1647158399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1647158400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1678607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1678608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1699167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1699167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1710057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1710057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1741507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1741507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1762066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1762066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1772956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1772956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1793516399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1793516400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1805011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1805011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1825570799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1825570800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1836460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1836460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1857020399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1857020400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1867910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1867910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1888469999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1888470000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1899359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1899360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919919599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919919600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1930809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1930809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1951369199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1951369200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1962863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1962864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1983423599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1983423600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1994313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1994313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014873199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014873200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2025763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2025763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2046322799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2046322800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2057212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2057212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077772399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077772400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2088662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2088662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2109221999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2109222000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2120111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2120112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140671599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140671600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Merida.json b/dojox/date/tests/tztests/tz_America-Merida.json
new file mode 100644
index 0000000..2ec5bd3
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Merida.json
@@ -0,0 +1,186 @@
+({
+	name: "date.timezone.America-Merida",
+	runTest: function(t){
+		var tz = "America/Merida";
+		doh.checkDate({tzOffset: 358.466666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 358.466666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 358.466666666667, tzAbbr: "LMT"}, -1514743201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1514743200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 377935199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 377935200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 407653199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 407653200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 989135999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 989136000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1001833199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1001833200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035701999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035702000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067151599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067151600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1175414399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1175414400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1193554799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1193554800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1207468799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1207468800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225004399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225004400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1238918399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1238918400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1256453999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1256454000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1270367999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1270368000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1288508399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1288508400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1301817599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1301817600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1319957999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1319958000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1333267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1333267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1351407599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1351407600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1365321599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1365321600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1382857199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1382857200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1396771199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1396771200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414306799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414306800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1428220799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1428220800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1445756399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1445756400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1459670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1459670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1477810799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1477810800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1491119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1491120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509260399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509260400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1522569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1522569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1540709999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1540710000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1554623999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1554624000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1586073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1586073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1603609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1603609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1617523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1617523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1635663599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1635663600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1648972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1648972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1680422399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1680422400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1698562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1698562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1712476799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1712476800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1743926399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1743926400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1761461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1761462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1775375999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1775376000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1792911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1792911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1806825599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1806825600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1824965999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1824966000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1838275199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1838275200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1856415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1856415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1869724799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1869724800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1887865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1887865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1901779199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1901779200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1933228799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1933228800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1950764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1950764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1964678399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1964678400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1982818799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1982818800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1996127999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1996128000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2027577599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2027577600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2045717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2045718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2059027199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2059027200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2091081599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2091081600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2108617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2108617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2122531199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2122531200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Mexico_City.json b/dojox/date/tests/tztests/tz_America-Mexico_City.json
new file mode 100644
index 0000000..a5693ac
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Mexico_City.json
@@ -0,0 +1,208 @@
+({
+	name: "date.timezone.America-Mexico_City",
+	runTest: function(t){
+		var tz = "America/Mexico_City";
+		doh.checkDate({tzOffset: 396.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 396.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 396.6, tzAbbr: "LMT"}, -1514739601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1514739600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1343066401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1343066400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1234807201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1234807200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1220292001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1220292000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1207159201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1207159200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1191344401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1191344400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -975261601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -975261600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -963169201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -963169200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -917114401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -917114400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -907354801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -907354800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -821901601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -821901600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -810068401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -810068400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -627501601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -627501600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -612990001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -612990000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 989135999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 989136000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1001833199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1001833200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035701999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035702000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067151599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067151600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1175414399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1175414400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1193554799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1193554800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1207468799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1207468800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225004399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225004400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1238918399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1238918400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1256453999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1256454000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1270367999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1270368000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1288508399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1288508400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1301817599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1301817600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1319957999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1319958000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1333267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1333267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1351407599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1351407600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1365321599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1365321600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1382857199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1382857200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1396771199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1396771200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414306799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414306800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1428220799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1428220800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1445756399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1445756400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1459670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1459670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1477810799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1477810800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1491119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1491120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509260399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509260400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1522569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1522569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1540709999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1540710000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1554623999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1554624000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1586073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1586073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1603609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1603609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1617523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1617523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1635663599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1635663600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1648972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1648972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1680422399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1680422400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1698562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1698562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1712476799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1712476800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1743926399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1743926400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1761461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1761462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1775375999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1775376000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1792911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1792911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1806825599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1806825600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1824965999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1824966000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1838275199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1838275200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1856415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1856415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1869724799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1869724800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1887865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1887865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1901779199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1901779200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1933228799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1933228800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1950764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1950764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1964678399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1964678400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1982818799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1982818800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1996127999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1996128000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2027577599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2027577600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2045717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2045718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2059027199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2059027200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2091081599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2091081600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2108617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2108617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2122531199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2122531200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Miquelon.json b/dojox/date/tests/tztests/tz_America-Miquelon.json
new file mode 100644
index 0000000..5ccf80f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Miquelon.json
@@ -0,0 +1,220 @@
+({
+	name: "date.timezone.America-Miquelon",
+	runTest: function(t){
+		var tz = "America/Miquelon";
+		doh.checkDate({tzOffset: 224.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 224.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 224.666666666667, tzAbbr: "LMT"}, -1850328921000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1850328920000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 326001599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 326001600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 544597199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 544597200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 562132799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 562132800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 576046799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 576046800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 594187199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 594187200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 607496399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 607496400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 625636799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 625636800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 638945999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 638946000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 657086399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 657086400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 671000399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 671000400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 688535999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 688536000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 702449999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 702450000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 719985599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 719985600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 733899599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 733899600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 752039999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 752040000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 765349199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 765349200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 783489599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 783489600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 796798799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 796798800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 814939199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 814939200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 828853199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 828853200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 846388799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 846388800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 860302799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 860302800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 877838399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 877838400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 891752399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 891752400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 909287999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 909288000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 923201999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 923202000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 941342399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 941342400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 954651599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 954651600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 972791999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 972792000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 986101199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 986101200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1004241599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1004241600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1018155599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1018155600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1035691199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1035691200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1049605199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1049605200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1067140799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1067140800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1081054799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1081054800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1099195199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1099195200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1112504399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1112504400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1130644799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1130644800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1143953999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1143954000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1162094399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1162094400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1173589199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1173589200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1194148799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1194148800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1205038799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1205038800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1225598399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1225598400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1236488399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1236488400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1257047999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1257048000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1268542799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1268542800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1289102399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1289102400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1299992399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1299992400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1320551999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1320552000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1331441999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1331442000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1352001599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1352001600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1362891599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1362891600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1383451199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1383451200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1394341199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1394341200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1414900799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1414900800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1425790799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1425790800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1446350399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1446350400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1457845199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1457845200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1478404799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1478404800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1489294799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1489294800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1509854399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1509854400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1520744399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1520744400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1541303999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1541304000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1552193999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1552194000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1572753599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1572753600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1583643599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1583643600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1604203199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1604203200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1615697999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1615698000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1636257599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1636257600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1647147599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1647147600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1667707199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1667707200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1678597199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1678597200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1699156799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1699156800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1710046799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1710046800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1730606399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1730606400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1741496399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1741496400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1762055999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1762056000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1772945999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1772946000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1793505599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1793505600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1805000399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1805000400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1825559999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1825560000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1836449999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1836450000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1857009599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1857009600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1867899599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1867899600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1888459199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1888459200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1899349199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1899349200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1919908799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1919908800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1930798799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1930798800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1951358399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1951358400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1962853199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1962853200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1983412799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1983412800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1994302799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1994302800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 2014862399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 2014862400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 2025752399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 2025752400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 2046311999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 2046312000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 2057201999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 2057202000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 2077761599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 2077761600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 2088651599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 2088651600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 2109211199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 2109211200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 2120101199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 2120101200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 2140660799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 2140660800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "PMST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 120, tzAbbr: "PMDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Moncton.json b/dojox/date/tests/tztests/tz_America-Moncton.json
new file mode 100644
index 0000000..1171eb5
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Moncton.json
@@ -0,0 +1,424 @@
+({
+	name: "date.timezone.America-Moncton",
+	runTest: function(t){
+		var tz = "America/Moncton";
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2131642801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -2131642800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1632074401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1632074400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1614798001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1614798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1153681201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1153681200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1145822401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1145822400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1122231601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1122231600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1114372801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1114372800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1090782001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1090782000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1082923201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1082923200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1059332401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1059332400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1051473601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1051473600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1027882801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1027882800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -1020024001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1020024000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -996433201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -996433200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -988574401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -988574400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -965674801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -965674800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -955396801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -955396800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -934743601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -934743600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -923947201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -923947200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -904503601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -904503600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -891892801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -891892800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -880221601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -880221600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -765399601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -765399600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -747252001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -747252000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -733950001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -733950000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -715802401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -715802400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -702500401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -702500400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -684352801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -684352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -671050801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -671050800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -652903201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -652903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -639601201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -639601200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -620848801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -620848800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -608151601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -608151600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -589399201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -589399200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -576097201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -576097200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -557949601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -557949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -544647601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -544647600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -526500001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -526500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -513198001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -513198000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -495050401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -495050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -481748401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -481748400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -463600801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -463600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -450298801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -450298800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -431546401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -431546400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -418244401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -418244400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -400096801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -400096800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -384375601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -384375600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -368647201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -368647200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -352926001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -352926000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -337197601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -337197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -321476401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -321476400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -305748001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -305748000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -289422001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -289422000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -273693601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -273693600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -257972401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -257972400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -242244001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -242244000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -226522801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -226522800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -210794401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -210794400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -195073201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -195073200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -179344801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -179344800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -163623601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -163623600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -147895201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -147895200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -131569201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -131569200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -116445601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -116445600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -100119601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -100119600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -84391201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -84391200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -68670001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -68670000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -52941601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -52941600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -37220401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -37220400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -21492001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -21492000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, -5770801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -5770800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 9957599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 9957600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 25678799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 25678800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 41407199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 41407200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 57733199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 57733200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 73461599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 73461600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 89182799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 89182800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 136360799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 136360800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 152081999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 152082000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 167810399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 167810400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 183531599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 183531600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 199259999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 199260000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 215585999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 215586000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 230709599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 230709600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 247035599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 247035600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 262763999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 262764000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 278485199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 278485200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 294213599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 294213600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 309934799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 309934800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 325663199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 325663200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 341384399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 341384400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 357112799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 357112800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 372833999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 372834000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 388562399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 388562400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 404888399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 404888400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 420011999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 420012000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 436337999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 436338000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 452066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 452066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 467787599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 467787600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 483515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 483516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 499237199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 499237200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 514965599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 514965600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 530686799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 530686800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 544600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 544600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 562136399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 562136400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 576050399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 576050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 594190799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 594190800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 607499999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 607500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 625640399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 625640400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 638949599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 638949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 657089999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 657090000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 671003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 671004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 688539599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 688539600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 702453599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 702453600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 719989199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 719989200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 733896059000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 733896060000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 752036459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 752036460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 765345659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 765345660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 783486059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 783486060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 796795259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 796795260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 814935659000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 814935660000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 828849659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 828849660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 846385259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 846385260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 860299259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 860299260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 877834859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 877834860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 891748859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 891748860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 909284459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 909284460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 923198459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 923198460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 941338859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 941338860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 954648059000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 954648060000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 972788459000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 972788460000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 986097659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 986097660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1004238059000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1004238060000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1018152059000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1018152060000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1035687659000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1035687660000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1049601659000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1049601660000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1067137259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1067137260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1081051259000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1081051260000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1099191659000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1099191660000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1112500859000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1112500860000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1130641259000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1130641260000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1143950459000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1143950460000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1162090859000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1162090860000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1173592799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1173592800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1194152399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1194152400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1205042399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1205042400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1225601999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1225602000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1236491999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1236492000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1257051599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1257051600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1268546399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1268546400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1289105999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1289106000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1299995999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1299996000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1320555599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1320555600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1331445599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1331445600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1352005199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1352005200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1362895199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1362895200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1383454799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1383454800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1394344799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1394344800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1414904399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1414904400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1425794399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1425794400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1446353999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1446354000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1457848799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1457848800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1478408399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1478408400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1489298399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1489298400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1509857999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1509858000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1520747999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1520748000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1541307599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1541307600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1552197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1552197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1572757199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1572757200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1583647199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1583647200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1604206799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1604206800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1615701599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1615701600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1636261199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1636261200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1647151199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1647151200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1667710799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1667710800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1678600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1678600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1699160399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1699160400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1710050399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1710050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1730609999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1730610000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1741499999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1741500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1762059599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1762059600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1772949599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1772949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1793509199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1793509200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1805003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1805004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1825563599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1825563600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1836453599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1836453600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1857013199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1857013200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1867903199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1867903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1888462799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1888462800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1899352799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1899352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1919912399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1919912400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1930802399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1930802400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1951361999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1951362000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1962856799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1962856800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1983416399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1983416400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1994306399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1994306400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2014865999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2014866000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2025755999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2025756000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2046315599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2046315600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2057205599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2057205600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2077765199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2077765200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2088655199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2088655200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2109214799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2109214800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2120104799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2120104800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2140664399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2140664400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Monterrey.json b/dojox/date/tests/tztests/tz_America-Monterrey.json
new file mode 100644
index 0000000..ac7e981
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Monterrey.json
@@ -0,0 +1,186 @@
+({
+	name: "date.timezone.America-Monterrey",
+	runTest: function(t){
+		var tz = "America/Monterrey";
+		doh.checkDate({tzOffset: 401.266666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 401.266666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 401.266666666667, tzAbbr: "LMT"}, -1514743201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1514743200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 576057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 576057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 594197999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 594198000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 989135999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 989136000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1001833199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1001833200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035701999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035702000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067151599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067151600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1175414399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1175414400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1193554799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1193554800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1207468799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1207468800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225004399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225004400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1238918399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1238918400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1256453999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1256454000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1270367999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1270368000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1288508399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1288508400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1301817599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1301817600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1319957999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1319958000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1333267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1333267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1351407599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1351407600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1365321599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1365321600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1382857199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1382857200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1396771199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1396771200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414306799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414306800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1428220799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1428220800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1445756399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1445756400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1459670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1459670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1477810799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1477810800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1491119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1491120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509260399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509260400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1522569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1522569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1540709999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1540710000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1554623999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1554624000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1586073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1586073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1603609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1603609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1617523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1617523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1635663599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1635663600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1648972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1648972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1680422399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1680422400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1698562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1698562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1712476799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1712476800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1743926399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1743926400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1761461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1761462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1775375999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1775376000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1792911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1792911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1806825599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1806825600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1824965999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1824966000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1838275199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1838275200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1856415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1856415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1869724799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1869724800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1887865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1887865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1901779199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1901779200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1933228799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1933228800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1950764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1950764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1964678399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1964678400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1982818799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1982818800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1996127999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1996128000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2027577599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2027577600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2045717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2045718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2059027199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2059027200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2091081599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2091081600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2108617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2108617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2122531199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2122531200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Montevideo.json b/dojox/date/tests/tztests/tz_America-Montevideo.json
new file mode 100644
index 0000000..c933d28
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Montevideo.json
@@ -0,0 +1,274 @@
+({
+	name: "date.timezone.America-Montevideo",
+	runTest: function(t){
+		var tz = "America/Montevideo";
+		doh.checkDate({tzOffset: 224.733333333333, tzAbbr: "MMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 224.733333333333, tzAbbr: "MMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 224.733333333333, tzAbbr: "MMT"}, -1567455317000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1567455316000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1459542601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1459542600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1443819601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1443819600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1428006601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1428006600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1412283601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1412283600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1396470601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1396470600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1380747601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1380747600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1141590601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1141590600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1128286801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1128286800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1110141001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1110141000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1096837201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1096837200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1078691401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1078691400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1065387601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1065387600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1046637001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1046637000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1033938001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1033938000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1015187401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1015187400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -1002488401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -1002488400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -983737801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -983737800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -971038801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -971038800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -952288201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -952288200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -938984401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -938984400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -920838601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -920838600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -907534801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -907534800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -896819401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -896819400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYHST"}, -883602001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -883602000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "UYT"}, -853619401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -853619400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -845848801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -845848800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -334789201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -334789200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -319672801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -319672800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -314226001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -314226000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -309996001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -309996000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -149720401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -149720400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -134604001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -134604000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -118270801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -118270800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -100044001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -100044000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, -68508001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -68508000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -50446801000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "UYHST"}, -50446800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "UYHST"}, -34119001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -34119000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -18910801000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "UYHST"}, -18910800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "UYHST"}, -2583001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, -2583000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 12625199000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "UYHST"}, 12625200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "UYHST"}, 28952999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 28953000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 72932399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 72932400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 82691999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 82692000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 132116399000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "UYHST"}, 132116400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "UYHST"}, 156911399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 156911400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 212983199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 212983200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 250052399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 250052400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 260243999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 260244000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 307594799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 307594800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 325994399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 325994400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 566449199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 566449200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 574307999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 574308000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 597812399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 597812400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 605671199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 605671200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 625633199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 625633200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 636515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 636516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 667965599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 667965600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 688532399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 688532400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 699415199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 699415200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 719377199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 719377200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 730864799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 730864800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1095562799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1095562800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1111895999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1111896000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1128833999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1128834000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1142135999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1142136000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1159678799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1159678800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1173585599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1173585600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1191733199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1191733200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1205035199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1205035200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1223182799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1223182800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1236484799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1236484800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1254632399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1254632400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1268539199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1268539200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1286081999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1286082000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1299988799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1299988800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1317531599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1317531600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1331438399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1331438400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1349585999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1349586000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1362887999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1362888000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1381035599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1381035600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1394337599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1394337600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1412485199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1412485200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1425787199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1425787200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1443934799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1443934800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1457841599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1457841600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1475384399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1475384400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1489291199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1489291200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1506833999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1506834000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1520740799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1520740800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1538888399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1538888400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1552190399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1552190400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1570337999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1570338000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1583639999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1583640000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1601787599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1601787600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1615694399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1615694400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1633237199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1633237200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1647143999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1647144000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1664686799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1664686800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1678593599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1678593600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1696136399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1696136400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1710043199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1710043200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1728190799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1728190800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1741492799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1741492800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1759640399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1759640400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1772942399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1772942400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1791089999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1791090000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1804996799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1804996800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1822539599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1822539600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1836446399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1836446400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1853989199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1853989200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1867895999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1867896000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1886043599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1886043600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1899345599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1899345600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1917493199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1917493200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1930795199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1930795200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1948942799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1948942800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1962849599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1962849600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1980392399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1980392400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1994299199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1994299200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 2011841999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 2011842000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 2025748799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 2025748800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 2043291599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 2043291600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 2057198399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 2057198400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 2075345999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 2075346000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 2088647999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 2088648000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 2106795599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 2106795600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 2120097599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 2120097600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 2138245199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 2138245200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "UYST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "UYT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Montreal.json b/dojox/date/tests/tztests/tz_America-Montreal.json
new file mode 100644
index 0000000..d1b4cb5
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Montreal.json
@@ -0,0 +1,476 @@
+({
+	name: "date.timezone.America-Montreal",
+	runTest: function(t){
+		var tz = "America/Montreal";
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1665334801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1665334800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1662753601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1662753600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1632070801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1632070800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1614794401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1614794400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1601742601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1601742600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1583775001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1583775000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1567355401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1567355400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1554053401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1554053400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1535907601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1535907600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1522603801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1522603800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1504458001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1504458000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1491154201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1491154200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1439830801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1439830800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1428255001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1428255000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1409504401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1409504400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1396805401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1396805400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1378054801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1378054800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1365355801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1365355800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1346612401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1346612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1333915201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1333915200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1315162801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1315162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1301860801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1301860800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1283713201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1283713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1270411201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1270411200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1252263601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1252263600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1238961601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1238961600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1220814001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1220814000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1207512001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1207512000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1188759601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1188759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1176062401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1176062400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1157310001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1157310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1144008001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1144008000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1125860401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1125860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1112558401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1112558400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1094410801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1094410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1081108801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1081108800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1062961201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1062961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1049659201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1049659200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1031511601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1031511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1018209601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1018209600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1000062001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1000062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -986760001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -986760000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -968007601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -968007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -955310401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -955310400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -936558001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -936558000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -880218001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -880218000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -765396001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -765396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -747248401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -747248400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -733946401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -733946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -715798801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -715798800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -702496801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -702496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -684349201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -684349200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -671047201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -671047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -652899601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -652899600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -636573601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -636573600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -620845201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -620845200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -605124001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -605124000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -589395601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -589395600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -576093601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -576093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -557946001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -557946000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -544644001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -544644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -526496401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -526496400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -513194401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -513194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -495046801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -495046800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -481744801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -481744800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -463597201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -463597200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -450295201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -450295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -431542801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -431542800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -418240801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -418240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -400093201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -400093200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -384372001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -384372000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -368643601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -368643600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -352922401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -352922400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -337194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -337194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -321472801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -321472800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -305744401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -305744400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -289418401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -289418400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -273690001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -273690000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -257968801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -257968800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -242240401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -242240400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -226519201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -226519200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -210790801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -210790800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -195069601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -195069600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -179341201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -179341200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -163620001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -163620000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -147891601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -147891600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -131565601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -131565600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -116442001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -116442000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -100116001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -100116000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -84387601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -84387600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -68666401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -68666400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -52938001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -52938000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -37216801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -37216800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 41410799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 41410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 57736799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 57736800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 73465199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 73465200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 89186399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 89186400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 104914799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 104914800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 120635999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 120636000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 136364399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 136364400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 152085599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152085600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 167813999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 167814000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 183535199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 183535200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 199263599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 199263600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 215589599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 215589600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 230713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 230713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 247039199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 247039200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 262767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 262767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 278488799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 278488800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 294217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 294217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 309938399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 309938400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467791199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467791200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499240799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530690399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 544604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 544604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562139999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 954658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 954658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 972799199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Montserrat.json b/dojox/date/tests/tztests/tz_America-Montserrat.json
new file mode 100644
index 0000000..06d35e7
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Montserrat.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-Montserrat",
+	runTest: function(t){
+		var tz = "America/Montserrat";
+		doh.checkDate({tzOffset: 248.866666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 248.866666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 248.866666666667, tzAbbr: "LMT"}, -1846266609000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1846266608000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Nassau.json b/dojox/date/tests/tztests/tz_America-Nassau.json
new file mode 100644
index 0000000..a9fbc38
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Nassau.json
@@ -0,0 +1,310 @@
+({
+	name: "date.timezone.America-Nassau",
+	runTest: function(t){
+		var tz = "America/Nassau";
+		doh.checkDate({tzOffset: 309.4, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 309.4, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 309.4, tzAbbr: "LMT"}, -1825095037000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1825095036000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -179341201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -179341200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -163620001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -163620000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -147891601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -147891600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -131565601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -131565600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -116442001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -116442000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -100116001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -100116000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -84387601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -84387600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -68666401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -68666400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -52938001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -52938000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -37216801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -37216800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 41410799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 41410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 57736799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 57736800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 73465199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 73465200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 89186399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 89186400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 104914799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 104914800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 120635999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 120636000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 136364399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 136364400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 152085599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152085600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 167813999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 167814000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 183535199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 183535200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 199263599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 199263600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 215589599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 215589600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 230713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 230713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 247039199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 247039200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 262767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 262767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 278488799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 278488800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 294217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 294217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 309938399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 309938400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467791199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467791200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499240799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530690399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 544604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 544604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562139999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 954658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 954658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 972799199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-New_York.json b/dojox/date/tests/tztests/tz_America-New_York.json
new file mode 100644
index 0000000..75bd42b
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-New_York.json
@@ -0,0 +1,482 @@
+({
+	name: "date.timezone.America-New_York",
+	runTest: function(t){
+		var tz = "America/New_York";
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1633280401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1633280400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1615140001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1615140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1601830801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1601830800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1583690401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1583690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1570381201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1570381200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1551636001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1551636000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1536512401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1536512400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1523210401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1523210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1504458001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1504458000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1491760801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1491760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1473008401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1473008400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1459706401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1459706400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1441558801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1441558800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1428256801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1428256800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1410109201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1410109200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1396807201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1396807200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1378659601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1378659600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1365357601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1365357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1347210001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1347210000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1333908001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1333908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1315155601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1315155600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1301853601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1301853600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1283706001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1283706000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1270404001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1270404000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1252256401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1252256400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1238954401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1238954400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1220806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1220806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1207504801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1207504800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1189357201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1189357200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1176055201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1176055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1157302801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1157302800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1144605601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1144605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1125853201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1125853200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1112551201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1112551200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1094403601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1094403600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1081101601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1081101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1062954001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1062954000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1049652001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1049652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1031504401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1031504400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1018202401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1018202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1000054801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1000054800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -986752801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -986752800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -968000401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -968000400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -955303201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -955303200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -936550801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -936550800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -923248801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -923248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -905101201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -905101200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -891799201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -891799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -880218001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -880218000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -765396001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -765396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -747248401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -747248400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -733946401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -733946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -715798801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -715798800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -702496801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -702496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -684349201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -684349200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -671047201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -671047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -652899601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -652899600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -639597601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -639597600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -620845201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -620845200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -608148001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -608148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -589395601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -589395600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -576093601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -576093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -557946001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -557946000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -544644001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -544644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -526496401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -526496400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -513194401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -513194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -495046801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -495046800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -481744801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -481744800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -463597201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -463597200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -447271201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -447271200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -431542801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -431542800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -415821601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -415821600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -400093201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -400093200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -384372001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -384372000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -368643601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -368643600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -352922401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -352922400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -337194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -337194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -321472801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -321472800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -305744401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -305744400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -289418401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -289418400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -273690001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -273690000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -257968801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -257968800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -242240401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -242240400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -226519201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -226519200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -210790801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -210790800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -195069601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -195069600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -179341201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -179341200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -163620001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -163620000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -147891601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -147891600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -131565601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -131565600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -116442001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -116442000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -100116001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -100116000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -84387601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -84387600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -68666401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -68666400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -52938001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -52938000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -37216801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -37216800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 41410799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 41410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 57736799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 57736800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 73465199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 73465200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 89186399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 89186400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 104914799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 104914800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 120635999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 120636000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 126687599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 126687600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 152085599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152085600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 162370799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 162370800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 183535199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 183535200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 199263599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 199263600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 215589599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 215589600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 230713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 230713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 247039199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 247039200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 262767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 262767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 278488799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 278488800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 294217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 294217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 309938399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 309938400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467791199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467791200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499240799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530690399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 544604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 544604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562139999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 954658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 954658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 972799199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Nipigon.json b/dojox/date/tests/tztests/tz_America-Nipigon.json
new file mode 100644
index 0000000..2a62963
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Nipigon.json
@@ -0,0 +1,280 @@
+({
+	name: "date.timezone.America-Nipigon",
+	runTest: function(t){
+		var tz = "America/Nipigon";
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1632070801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1632070800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1614794401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1614794400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -923252401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -923252400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -880218001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -880218000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -765396001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -765396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 136364399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 136364400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 152085599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152085600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 167813999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 167814000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 183535199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 183535200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 199263599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 199263600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 215589599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 215589600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 230713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 230713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 247039199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 247039200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 262767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 262767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 278488799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 278488800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 294217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 294217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 309938399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 309938400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467791199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467791200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499240799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530690399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 544604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 544604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562139999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 954658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 954658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 972799199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Nome.json b/dojox/date/tests/tztests/tz_America-Nome.json
new file mode 100644
index 0000000..5c82470
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Nome.json
@@ -0,0 +1,298 @@
+({
+	name: "date.timezone.America-Nome",
+	runTest: function(t){
+		var tz = "America/Nome";
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -880196401000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "NWT"}, -880196400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "NWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "NPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "NPT"}, -765374401000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -765374400000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -86878801000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, -86878800000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, -21466801000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, -21466800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, -5745601000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, -5745600000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 9982799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 9982800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 25703999000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 25704000000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 41432399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 41432400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 57758399000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 57758400000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 73486799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 73486800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 89207999000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 89208000000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 104936399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 104936400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 120657599000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 120657600000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 126709199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 126709200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 152107199000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 152107200000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 162392399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 162392400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 183556799000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 183556800000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 199285199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 199285200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 215611199000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 215611200000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 230734799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 230734800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 247060799000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 247060800000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 262789199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 262789200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 278510399000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 278510400000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 294238799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 294238800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 309959999000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 309960000000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 325688399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 325688400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 341409599000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 341409600000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 357137999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 357138000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 372859199000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 372859200000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 388587599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 388587600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 404913599000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 404913600000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 420037199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 420037200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "BDT"}, 436363199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 436363200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 439030799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 439030800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 452084399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 452084400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 467805599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 467805600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 483533999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 483534000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 499255199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 499255200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 514983599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 514983600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 530704799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 530704800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 544618799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 544618800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 562154399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 562154400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 576068399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 576068400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 594208799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 594208800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 607517999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 607518000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 625658399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 625658400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 638967599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 638967600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 657107999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 657108000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 671021999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 671022000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 688557599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 688557600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 702471599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 702471600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 720007199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 720007200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 733921199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 733921200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 752061599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 752061600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 765370799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 765370800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 783511199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 783511200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 796820399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 796820400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 814960799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 814960800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 828874799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 828874800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 846410399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 846410400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 860324399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 860324400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 877859999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 877860000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 891773999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 891774000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 909309599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 909309600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 923223599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 923223600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 941363999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 941364000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 954673199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 954673200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 972813599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 972813600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 986122799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 986122800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1004263199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1004263200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1018177199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1018177200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1035712799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1035712800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1049626799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1049626800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1067162399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1067162400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1081076399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1081076400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1099216799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1099216800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1112525999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1112526000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1130666399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1130666400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1143975599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1143975600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1162115999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1162116000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1173610799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1173610800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1194170399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1194170400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1205060399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1205060400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1225619999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1225620000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1236509999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1236510000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1257069599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1257069600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1268564399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1268564400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1289123999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1289124000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1300013999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1300014000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1320573599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1320573600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1331463599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1331463600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1352023199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1352023200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1362913199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1362913200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1383472799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1383472800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1394362799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1394362800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1414922399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1414922400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1425812399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1425812400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1446371999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1446372000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1457866799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1457866800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1478426399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1478426400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1489316399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1489316400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1509875999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1509876000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1520765999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1520766000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1541325599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1541325600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1552215599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1552215600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1572775199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1572775200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1583665199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1583665200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1604224799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1604224800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1615719599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1615719600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1636279199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1636279200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1647169199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1647169200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1667728799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1667728800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1678618799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1678618800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1699178399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1699178400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1710068399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1710068400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1730627999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1730628000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1741517999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1741518000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1762077599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1762077600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1772967599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1772967600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1793527199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1793527200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1805021999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1805022000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1825581599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1825581600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1836471599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1836471600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1857031199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1857031200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1867921199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1867921200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1888480799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1888480800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1899370799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1899370800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1919930399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1919930400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1930820399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1930820400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1951379999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1951380000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1962874799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1962874800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1983434399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1983434400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1994324399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1994324400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2014883999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2014884000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2025773999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2025774000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2046333599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2046333600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2057223599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2057223600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2077783199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2077783200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2088673199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2088673200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2109232799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2109232800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2120122799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2120122800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2140682399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2140682400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Noronha.json b/dojox/date/tests/tztests/tz_America-Noronha.json
new file mode 100644
index 0000000..ce4c3c9
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Noronha.json
@@ -0,0 +1,90 @@
+({
+	name: "date.timezone.America-Noronha",
+	runTest: function(t){
+		var tz = "America/Noronha";
+		doh.checkDate({tzOffset: 129.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 129.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 129.666666666667, tzAbbr: "LMT"}, -1767217821000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -1767217820000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -1206961201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -1206961200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -1191366001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -1191366000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -1175378401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -1175378400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -1159830001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -1159830000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -633823201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -633823200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -622072801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -622072800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -602287201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -602287200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -591836401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -591836400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -570751201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -570751200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -560214001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -560214000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -539128801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -539128800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -531356401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -531356400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -191368801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -191368800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -184201201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -184201200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -155167201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -155167200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -150073201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -150073200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -128901601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -128901600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -121129201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -121129200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -99957601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -99957600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -89593201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -89593200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -68421601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -68421600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, -57970801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, -57970800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 499744799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 499744800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 511232399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 511232400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 530589599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 530589600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 540262799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 540262800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 562125599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 562125600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 571193999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 571194000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 592970399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 592970400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 602038799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 602038800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 624419999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 624420000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 634697999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 634698000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 938915999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 938916000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 951613199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 951613200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 970970399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 970970400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 971571599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 971571600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 1003024799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 1003024800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "FNST"}, 1013907599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 1013907600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FNT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-North_Dakota-Center.json b/dojox/date/tests/tztests/tz_America-North_Dakota-Center.json
new file mode 100644
index 0000000..95a7868
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-North_Dakota-Center.json
@@ -0,0 +1,310 @@
+({
+	name: "date.timezone.America-North_Dakota-Center",
+	runTest: function(t){
+		var tz = "America/North_Dakota/Center";
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1633273201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1633273200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1615132801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1615132800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1601823601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1601823600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1583683201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1583683200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -880210801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -880210800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -765388801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -765388800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -84380401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -84380400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -68659201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -68659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -52930801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -52930800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -37209601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -37209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -21481201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -21481200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -5760001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -5760000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 9968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 9968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 25689599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 25689600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 41417999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 41418000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 57743999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 57744000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 73472399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 73472400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 89193599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 89193600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 104921999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 104922000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 120643199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 120643200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 126694799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 126694800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 152092799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 152092800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 162377999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 162378000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 183542399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 183542400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 199270799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 199270800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 215596799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 215596800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 230720399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 230720400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 247046399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 247046400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 262774799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 262774800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 278495999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 278496000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 294224399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 294224400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 309945599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 309945600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 325673999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 325674000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 341395199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 341395200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 357123599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 357123600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 372844799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 372844800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 388573199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 388573200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 404899199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 404899200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 420022799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 420022800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 436348799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 436348800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 452077199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 452077200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 467798399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 467798400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 483526799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 483526800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 499247999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 499248000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 514976399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 514976400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 530697599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 530697600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 544611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 544611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 562147199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 562147200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 576061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 576061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 594201599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 594201600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 607510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 607510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 625651199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 625651200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 638960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 638960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 657100799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 657100800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 671014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 671014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 688550399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 688550400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 702464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 702464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 719999999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 720000000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 733910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 733910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 752050799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 752050800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 765359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 765360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 783500399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 783500400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 796809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 796809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 814949999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 814950000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 986111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 986112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1004252399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1004252400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035701999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035702000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067151599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067151600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1205049599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1205049600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1236499199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1236499200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1257058799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1257058800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1268553599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1268553600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1289113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1289113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1300003199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1300003200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1320562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1320562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1331452799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1331452800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1352012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1352012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1362902399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1362902400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1383461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1383462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1394351999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1394352000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1425801599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1425801600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1446361199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1446361200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1457855999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1457856000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1478415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1478415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1489305599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1489305600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1520755199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1520755200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1541314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1541314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1552204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1552204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1583654399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1583654400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1604213999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1604214000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1615708799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1615708800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1636268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1636268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1647158399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1647158400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1678607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1678608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1699167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1699167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1710057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1710057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1741507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1741507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1762066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1762066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1772956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1772956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1793516399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1793516400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1805011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1805011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1825570799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1825570800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1836460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1836460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1857020399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1857020400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1867910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1867910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1888469999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1888470000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1899359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1899360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919919599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919919600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1930809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1930809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1951369199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1951369200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1962863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1962864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1983423599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1983423600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1994313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1994313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014873199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014873200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2025763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2025763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2046322799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2046322800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2057212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2057212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077772399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077772400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2088662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2088662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2109221999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2109222000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2120111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2120112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140671599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140671600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-North_Dakota-New_Salem.json b/dojox/date/tests/tztests/tz_America-North_Dakota-New_Salem.json
new file mode 100644
index 0000000..a0d0c45
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-North_Dakota-New_Salem.json
@@ -0,0 +1,310 @@
+({
+	name: "date.timezone.America-North_Dakota-New_Salem",
+	runTest: function(t){
+		var tz = "America/North_Dakota/New_Salem";
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1633273201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1633273200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1615132801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1615132800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1601823601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1601823600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1583683201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1583683200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -880210801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -880210800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -765388801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -765388800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -84380401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -84380400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -68659201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -68659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -52930801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -52930800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -37209601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -37209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -21481201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -21481200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -5760001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -5760000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 9968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 9968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 25689599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 25689600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 41417999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 41418000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 57743999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 57744000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 73472399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 73472400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 89193599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 89193600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 104921999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 104922000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 120643199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 120643200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 126694799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 126694800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 152092799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 152092800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 162377999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 162378000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 183542399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 183542400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 199270799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 199270800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 215596799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 215596800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 230720399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 230720400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 247046399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 247046400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 262774799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 262774800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 278495999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 278496000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 294224399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 294224400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 309945599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 309945600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 325673999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 325674000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 341395199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 341395200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 357123599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 357123600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 372844799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 372844800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 388573199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 388573200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 404899199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 404899200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 420022799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 420022800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 436348799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 436348800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 452077199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 452077200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 467798399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 467798400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 483526799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 483526800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 499247999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 499248000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 514976399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 514976400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 530697599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 530697600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 544611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 544611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 562147199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 562147200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 576061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 576061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 594201599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 594201600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 607510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 607510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 625651199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 625651200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 638960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 638960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 657100799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 657100800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 671014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 671014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 688550399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 688550400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 702464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 702464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 719999999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 720000000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 733913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 733914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 752054399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 752054400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 765363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 765363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 783503999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 783504000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 796813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 796813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 814953599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 814953600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 828867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 828867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 846403199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 846403200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 860317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 860317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 877852799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 877852800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 891766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 891766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 923216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 923216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 941356799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 941356800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 954665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 954666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 972806399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 972806400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 986115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 986115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1004255999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1004256000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1018169999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1018170000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1035705599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1035705600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1049619599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1049619600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1067155199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067155200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1205049599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1205049600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1236499199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1236499200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1257058799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1257058800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1268553599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1268553600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1289113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1289113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1300003199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1300003200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1320562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1320562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1331452799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1331452800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1352012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1352012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1362902399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1362902400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1383461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1383462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1394351999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1394352000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1425801599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1425801600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1446361199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1446361200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1457855999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1457856000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1478415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1478415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1489305599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1489305600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1520755199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1520755200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1541314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1541314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1552204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1552204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1583654399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1583654400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1604213999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1604214000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1615708799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1615708800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1636268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1636268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1647158399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1647158400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1678607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1678608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1699167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1699167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1710057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1710057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1741507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1741507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1762066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1762066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1772956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1772956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1793516399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1793516400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1805011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1805011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1825570799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1825570800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1836460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1836460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1857020399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1857020400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1867910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1867910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1888469999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1888470000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1899359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1899360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919919599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919919600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1930809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1930809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1951369199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1951369200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1962863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1962864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1983423599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1983423600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1994313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1994313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014873199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014873200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2025763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2025763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2046322799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2046322800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2057212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2057212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077772399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077772400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2088662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2088662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2109221999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2109222000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2120111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2120112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140671599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140671600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Panama.json b/dojox/date/tests/tztests/tz_America-Panama.json
new file mode 100644
index 0000000..8012835
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Panama.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-Panama",
+	runTest: function(t){
+		var tz = "America/Panama";
+		doh.checkDate({tzOffset: 319.6, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 319.6, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 319.6, tzAbbr: "CMT"}, -1946918425000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1946918424000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Pangnirtung.json b/dojox/date/tests/tztests/tz_America-Pangnirtung.json
new file mode 100644
index 0000000..ef5eb06
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Pangnirtung.json
@@ -0,0 +1,256 @@
+({
+	name: "date.timezone.America-Pangnirtung",
+	runTest: function(t){
+		var tz = "America/Pangnirtung";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -1546300801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1546300800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -880221601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -880221600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -765399601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -765399600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -147902401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ADDT"}, -147902400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ADDT"}, -131572801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -131572800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 325663199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 325663200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 341384399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 341384400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 357112799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 357112800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 372833999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 372834000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 388562399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 388562400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 404888399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 404888400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 420011999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 420012000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 436337999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 436338000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 452066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 452066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 467787599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 467787600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 483515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 483516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 499237199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 499237200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 514965599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 514965600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 530686799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 530686800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 544600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 544600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 562136399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 562136400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 576050399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 576050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 594190799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 594190800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 607499999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 607500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 625640399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 625640400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 638949599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 638949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 657089999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 657090000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 671003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 671004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 688539599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 688539600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 702453599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 702453600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 719989199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 719989200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 733903199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 733903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 752043599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 752043600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 765352799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 765352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 783493199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 783493200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 796802399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796802400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Paramaribo.json b/dojox/date/tests/tztests/tz_America-Paramaribo.json
new file mode 100644
index 0000000..253980d
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Paramaribo.json
@@ -0,0 +1,22 @@
+({
+	name: "date.timezone.America-Paramaribo",
+	runTest: function(t){
+		var tz = "America/Paramaribo";
+		doh.checkDate({tzOffset: 220.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 220.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 220.666666666667, tzAbbr: "LMT"}, -1861906761000, tz, 1);
+		doh.checkDate({tzOffset: 220.866666666667, tzAbbr: "PMT"}, -1861906760000, tz, 1);
+		doh.checkDate({tzOffset: 220.866666666667, tzAbbr: "PMT"}, -1104524349000, tz, 1);
+		doh.checkDate({tzOffset: 220.6, tzAbbr: "PMT"}, -1104524348000, tz, 1);
+		doh.checkDate({tzOffset: 220.6, tzAbbr: "PMT"}, -765317965000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NEGT"}, -765317964000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NEGT"}, 185686199000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "SRT"}, 185686200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "SRT"}, 465449399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "SRT"}, 465449400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "SRT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "SRT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "SRT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "SRT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Phoenix.json b/dojox/date/tests/tztests/tz_America-Phoenix.json
new file mode 100644
index 0000000..7711be9
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Phoenix.json
@@ -0,0 +1,32 @@
+({
+	name: "date.timezone.America-Phoenix",
+	runTest: function(t){
+		var tz = "America/Phoenix";
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1633273201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1633273200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1615132801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1615132800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1601823601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1601823600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1583683201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1583683200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -880210801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -880210800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -820519141000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -820519140000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -812653141000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -812653140000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -796845541000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -796845540000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -84380401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -84380400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -68659201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -68659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Port-au-Prince.json b/dojox/date/tests/tztests/tz_America-Port-au-Prince.json
new file mode 100644
index 0000000..7c86ad2
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Port-au-Prince.json
@@ -0,0 +1,82 @@
+({
+	name: "date.timezone.America-Port-au-Prince",
+	runTest: function(t){
+		var tz = "America/Port-au-Prince";
+		doh.checkDate({tzOffset: 289, tzAbbr: "PPMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 289, tzAbbr: "PPMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 289, tzAbbr: "PPMT"}, -1670483461000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1670483460000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 421217999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 421218000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436334399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436334400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452062799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452062800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467783999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467784000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483512399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483512400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499233599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499233600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514961999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514962000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530683199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530683200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 546411599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 546411600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562132799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562132800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576050399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576050400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607499999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607500000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638949599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638949600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671003999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671004000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702453599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702453600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733903199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733903200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765352799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765352800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796802399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796802400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828856799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828856800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860306399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860306400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112504399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112504400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130644799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130644800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143953999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143954000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162094399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162094400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Port_of_Spain.json b/dojox/date/tests/tztests/tz_America-Port_of_Spain.json
new file mode 100644
index 0000000..d22b365
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Port_of_Spain.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-Port_of_Spain",
+	runTest: function(t){
+		var tz = "America/Port_of_Spain";
+		doh.checkDate({tzOffset: 246.066666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 246.066666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 246.066666666667, tzAbbr: "LMT"}, -1825098837000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1825098836000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Porto_Velho.json b/dojox/date/tests/tztests/tz_America-Porto_Velho.json
new file mode 100644
index 0000000..e73aabf
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Porto_Velho.json
@@ -0,0 +1,70 @@
+({
+	name: "date.timezone.America-Porto_Velho",
+	runTest: function(t){
+		var tz = "America/Porto_Velho";
+		doh.checkDate({tzOffset: 255.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 255.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 255.6, tzAbbr: "LMT"}, -1767210265000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1767210264000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1206954001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1206954000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1191358801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1191358800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1175371201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1175371200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1159822801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1159822800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -633816001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -633816000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -622065601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -622065600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -602280001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -602280000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -591829201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -591829200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -570744001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -570744000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -560206801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -560206800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -539121601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -539121600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -531349201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -531349200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -191361601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -191361600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -155160001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -155160000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -150066001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -150066000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -128894401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -128894400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -99950401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -99950400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -89586001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -89586000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -68414401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -68414400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -57963601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -57963600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 499751999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 499752000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 511239599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 511239600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 530596799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 530596800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 540269999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 540270000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 562132799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 562132800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 571201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 571201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Puerto_Rico.json b/dojox/date/tests/tztests/tz_America-Puerto_Rico.json
new file mode 100644
index 0000000..3c8d08f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Puerto_Rico.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.America-Puerto_Rico",
+	runTest: function(t){
+		var tz = "America/Puerto_Rico";
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -873057601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -873057600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "APT"}, -765399601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -765399600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Rainy_River.json b/dojox/date/tests/tztests/tz_America-Rainy_River.json
new file mode 100644
index 0000000..8a9820a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Rainy_River.json
@@ -0,0 +1,280 @@
+({
+	name: "date.timezone.America-Rainy_River",
+	runTest: function(t){
+		var tz = "America/Rainy_River";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1632067201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1632067200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1614790801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1614790800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -923248801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -923248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 136367999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 136368000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 152089199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 152089200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 167817599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 167817600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 183538799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 183538800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 199267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 199267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 215593199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 215593200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 230716799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 230716800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 247042799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 247042800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 262771199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 262771200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 278492399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 278492400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 294220799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 294220800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 309941999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 309942000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 325670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 325670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 341391599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 341391600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 357119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 357120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 372841199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 372841200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 388569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 388569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 404895599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 404895600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 420019199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 420019200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 436345199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 436345200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 452073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 452073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 467794799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 467794800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 483523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 483523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 499244399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 499244400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 514972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 514972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 530693999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 530694000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 544607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 544608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 562143599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 562143600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 576057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 576057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 594197999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 594198000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 607507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 607507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 625647599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 625647600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 638956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 638956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 657097199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 657097200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 671011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 671011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 688546799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 688546800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 702460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 702460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 719996399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 719996400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 733910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 733910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 752050799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 752050800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 765359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 765360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 783500399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 783500400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 796809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 796809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 814949999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 814950000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 986111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 986112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1004252399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1004252400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035701999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035702000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067151599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067151600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1205049599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1205049600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1236499199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1236499200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1257058799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1257058800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1268553599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1268553600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1289113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1289113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1300003199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1300003200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1320562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1320562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1331452799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1331452800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1352012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1352012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1362902399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1362902400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1383461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1383462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1394351999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1394352000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1425801599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1425801600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1446361199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1446361200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1457855999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1457856000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1478415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1478415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1489305599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1489305600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1520755199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1520755200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1541314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1541314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1552204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1552204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1583654399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1583654400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1604213999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1604214000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1615708799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1615708800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1636268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1636268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1647158399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1647158400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1678607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1678608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1699167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1699167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1710057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1710057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1741507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1741507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1762066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1762066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1772956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1772956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1793516399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1793516400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1805011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1805011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1825570799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1825570800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1836460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1836460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1857020399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1857020400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1867910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1867910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1888469999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1888470000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1899359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1899360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919919599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919919600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1930809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1930809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1951369199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1951369200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1962863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1962864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1983423599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1983423600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1994313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1994313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014873199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014873200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2025763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2025763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2046322799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2046322800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2057212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2057212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077772399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077772400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2088662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2088662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2109221999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2109222000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2120111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2120112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140671599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140671600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Rankin_Inlet.json b/dojox/date/tests/tztests/tz_America-Rankin_Inlet.json
new file mode 100644
index 0000000..d1b840c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Rankin_Inlet.json
@@ -0,0 +1,250 @@
+({
+	name: "date.timezone.America-Rankin_Inlet",
+	runTest: function(t){
+		var tz = "America/Rankin_Inlet";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -410227201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -410227200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -147895201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDDT"}, -147895200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDDT"}, -131565601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -131565600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 325670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 325670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 341391599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 341391600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 357119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 357120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 372841199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 372841200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 388569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 388569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 404895599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 404895600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 420019199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 420019200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 436345199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 436345200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 452073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 452073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 467794799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 467794800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 483523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 483523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 499244399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 499244400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 514972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 514972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 530693999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 530694000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 544607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 544608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 562143599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 562143600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 576057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 576057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 594197999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 594198000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 607507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 607507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 625647599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 625647600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 638956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 638956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 657097199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 657097200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 671011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 671011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 688546799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 688546800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 702460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 702460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 719996399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 719996400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 733910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 733910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 752050799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 752050800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 765359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 765360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 783500399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 783500400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 796809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 796809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 814949999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 814950000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 986112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1004252399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1004252400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035701999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035702000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067151599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067151600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1205049599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1205049600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1236499199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1236499200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1257058799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1257058800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1268553599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1268553600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1289113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1289113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1300003199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1300003200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1320562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1320562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1331452799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1331452800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1352012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1352012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1362902399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1362902400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1383461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1383462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1394351999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1394352000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1425801599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1425801600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1446361199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1446361200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1457855999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1457856000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1478415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1478415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1489305599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1489305600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1520755199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1520755200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1541314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1541314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1552204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1552204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1583654399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1583654400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1604213999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1604214000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1615708799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1615708800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1636268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1636268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1647158399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1647158400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1678607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1678608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1699167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1699167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1710057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1710057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1741507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1741507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1762066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1762066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1772956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1772956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1793516399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1793516400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1805011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1805011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1825570799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1825570800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1836460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1836460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1857020399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1857020400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1867910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1867910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1888469999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1888470000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1899359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1899360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919919599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919919600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1930809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1930809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1951369199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1951369200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1962863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1962864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1983423599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1983423600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1994313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1994313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014873199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014873200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2025763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2025763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2046322799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2046322800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2057212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2057212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077772399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077772400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2088662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2088662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2109221999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2109222000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2120111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2120112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140671599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140671600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Recife.json b/dojox/date/tests/tztests/tz_America-Recife.json
new file mode 100644
index 0000000..49d3204
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Recife.json
@@ -0,0 +1,90 @@
+({
+	name: "date.timezone.America-Recife",
+	runTest: function(t){
+		var tz = "America/Recife";
+		doh.checkDate({tzOffset: 139.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 139.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 139.6, tzAbbr: "LMT"}, -1767217225000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1767217224000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1206957601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1206957600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1191362401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1191362400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1175374801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1175374800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1159826401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1159826400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -633819601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -633819600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -622069201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -622069200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -602283601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -602283600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -591832801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -591832800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -570747601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -570747600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -560210401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -560210400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -539125201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -539125200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -531352801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -531352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -191365201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -191365200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -184197601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -184197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -155163601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -155163600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -150069601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -150069600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -128898001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -128898000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -121125601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -121125600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -99954001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -99954000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -89589601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -89589600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -68418001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -68418000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -57967201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -57967200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 499748399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 499748400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 511235999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 511236000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 530593199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 530593200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 540266399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 540266400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 562129199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 562129200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 571197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 571197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 592973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 592974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 602042399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 602042400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 634701599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 634701600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 951616799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 951616800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 970973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 970974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 971575199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 971575200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1003028399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1003028400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1013911199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1013911200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Regina.json b/dojox/date/tests/tztests/tz_America-Regina.json
new file mode 100644
index 0000000..05ae97e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Regina.json
@@ -0,0 +1,118 @@
+({
+	name: "date.timezone.America-Regina",
+	runTest: function(t){
+		var tz = "America/Regina";
+		doh.checkDate({tzOffset: 418.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 418.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 418.6, tzAbbr: "LMT"}, -2030202085000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2030202084000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1632063601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1632063600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1614787201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1614787200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1251651601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1251651600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1238349601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1238349600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1220202001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1220202000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1206900001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1206900000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1188752401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1188752400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1175450401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1175450400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1156698001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1156698000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1144000801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1144000800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1125248401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1125248400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1111946401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1111946400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1032714001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1032714000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1016992801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1016992800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1001264401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1001264400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -986148001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -986148000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -969814801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -969814800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -954093601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -954093600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -937760401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -937760400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -922039201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -922039200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -906310801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -906310800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -890589601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -890589600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -880210801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -880210800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -765388801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -765388800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -748450801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -748450800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -732729601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -732729600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -715791601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -715791600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -702489601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -702489600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -684342001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -684342000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -671040001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -671040000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -652892401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -652892400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -639590401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -639590400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -620838001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -620838000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -608140801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -608140800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -589388401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -589388400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -576086401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -576086400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -557938801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -557938800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -544636801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -544636800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -526489201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -526489200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -513187201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -513187200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -495039601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -495039600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -481737601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -481737600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -463590001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -463590000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -450288001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -450288000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -431535601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -431535600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -418233601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -418233600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -400086001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -400086000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -386784001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -386784000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -337186801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -337186800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -321465601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -321465600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -305737201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -305737200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Resolute.json b/dojox/date/tests/tztests/tz_America-Resolute.json
new file mode 100644
index 0000000..e402249
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Resolute.json
@@ -0,0 +1,250 @@
+({
+	name: "date.timezone.America-Resolute",
+	runTest: function(t){
+		var tz = "America/Resolute";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -704937601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -704937600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -147895201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDDT"}, -147895200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CDDT"}, -131565601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -131565600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 325670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 325670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 341391599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 341391600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 357119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 357120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 372841199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 372841200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 388569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 388569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 404895599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 404895600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 420019199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 420019200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 436345199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 436345200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 452073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 452073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 467794799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 467794800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 483523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 483523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 499244399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 499244400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 514972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 514972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 530693999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 530694000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 544607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 544608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 562143599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 562143600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 576057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 576057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 594197999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 594198000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 607507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 607507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 625647599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 625647600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 638956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 638956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 657097199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 657097200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 671011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 671011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 688546799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 688546800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 702460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 702460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 719996399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 719996400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 733910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 733910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 752050799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 752050800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 765359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 765360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 783500399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 783500400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 796809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 796809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 814949999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 814950000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 986112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1004252399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1004252400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035701999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035702000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067151599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067151600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225609199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225609200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1257058799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257058800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1289113199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289113200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1320562799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320562800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1352012399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352012400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1383461999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383462000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414911599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414911600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1446361199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446361200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1478415599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478415600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509865199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509865200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1541314799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541314800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572764399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572764400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1604213999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604214000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1636268399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636268400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667717999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667718000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1699167599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699167600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730617199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730617200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1762066799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762066800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1793516399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793516400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1825570799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825570800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1857020399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857020400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1888469999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888470000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919919599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919919600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1951369199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951369200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1983423599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983423600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014873199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014873200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2046322799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046322800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077772399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077772400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2109221999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109222000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140671599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140671600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Rio_Branco.json b/dojox/date/tests/tztests/tz_America-Rio_Branco.json
new file mode 100644
index 0000000..21efaf7
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Rio_Branco.json
@@ -0,0 +1,72 @@
+({
+	name: "date.timezone.America-Rio_Branco",
+	runTest: function(t){
+		var tz = "America/Rio_Branco";
+		doh.checkDate({tzOffset: 271.2, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 271.2, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 271.2, tzAbbr: "LMT"}, -1767209329000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -1767209328000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -1206950401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -1206950400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -1191355201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -1191355200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -1175367601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -1175367600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -1159819201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -1159819200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -633812401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -633812400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -622062001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -622062000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -602276401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -602276400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -591825601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -591825600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -570740401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -570740400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -560203201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -560203200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -539118001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -539118000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -531345601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -531345600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -191358001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -191358000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -184190401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -184190400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -155156401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -155156400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -150062401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -150062400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -128890801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -128890800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -121118401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -121118400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -99946801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -99946800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -89582401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -89582400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -68410801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -68410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, -57960001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, -57960000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 499755599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 499755600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 511243199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 511243200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 530600399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 530600400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 540273599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 540273600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 562136399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 562136400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ACST"}, 571204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 571204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ACT"}, 1214283599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1214283600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Santarem.json b/dojox/date/tests/tztests/tz_America-Santarem.json
new file mode 100644
index 0000000..7cdf912
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Santarem.json
@@ -0,0 +1,72 @@
+({
+	name: "date.timezone.America-Santarem",
+	runTest: function(t){
+		var tz = "America/Santarem";
+		doh.checkDate({tzOffset: 218.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 218.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 218.8, tzAbbr: "LMT"}, -1767212473000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1767212472000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1206954001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1206954000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1191358801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1191358800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1175371201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1175371200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -1159822801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -1159822800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -633816001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -633816000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -622065601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -622065600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -602280001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -602280000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -591829201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -591829200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -570744001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -570744000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -560206801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -560206800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -539121601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -539121600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -531349201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -531349200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -191361601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -191361600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -184194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -184194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -155160001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -155160000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -150066001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -150066000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -128894401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -128894400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -99950401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -99950400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -89586001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -89586000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -68414401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -68414400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, -57963601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, -57963600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 499751999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 499752000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 511239599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 511239600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 530596799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 530596800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 540269999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 540270000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 562132799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 562132800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "AMST"}, 571201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 571201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AMT"}, 1214279999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1214280000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Santiago.json b/dojox/date/tests/tztests/tz_America-Santiago.json
new file mode 100644
index 0000000..7b3557d
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Santiago.json
@@ -0,0 +1,328 @@
+({
+	name: "date.timezone.America-Santiago",
+	runTest: function(t){
+		var tz = "America/Santiago";
+		doh.checkDate({tzOffset: 282.766666666667, tzAbbr: "SMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 282.766666666667, tzAbbr: "SMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 282.766666666667, tzAbbr: "SMT"}, -1893439035000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1893439034000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1688410801000, tz, 1);
+		doh.checkDate({tzOffset: 282.766666666667, tzAbbr: "SMT"}, -1688410800000, tz, 1);
+		doh.checkDate({tzOffset: 282.766666666667, tzAbbr: "SMT"}, -1619983035000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, -1619983034000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, -1593806401000, tz, 1);
+		doh.checkDate({tzOffset: 282.766666666667, tzAbbr: "SMT"}, -1593806400000, tz, 1);
+		doh.checkDate({tzOffset: 282.766666666667, tzAbbr: "SMT"}, -1335986235000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -1335986234000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -1317585601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1317585600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1304362801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -1304362800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -1286049601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1286049600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1272826801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -1272826800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -1254513601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1254513600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1241290801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -1241290800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -1222977601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1222977600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1209754801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -1209754800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -1191355201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1191355200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -1178132401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -1178132400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -870552001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -870552000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -865278001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -865278000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLST"}, -736376401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -736376400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CLT"}, -713646001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, -713646000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, -36619201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, -36619200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, -23922001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, -23922000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, -3355201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, -3355200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 7527599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 7527600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 24465599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 24465600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 37767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 37767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 55915199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 55915200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 69217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 69217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 87969599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 87969600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 100666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 100666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 118209599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 118209600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 132116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 132116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 150868799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 150868800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 163565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 163566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 182318399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 182318400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 195620399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 195620400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 213767999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 213768000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 227069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 227070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 245217599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 245217600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 258519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 258519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 277271999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 277272000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 289969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 289969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 308721599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 308721600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 321418799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 321418800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 340171199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 340171200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 353473199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 353473200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 371620799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 371620800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 384922799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 384922800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 403070399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 403070400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 416372399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 416372400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 434519999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 434520000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 447821999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 447822000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 466574399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 466574400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 479271599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 479271600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 498023999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 498024000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 510721199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 510721200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 529473599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 529473600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 545194799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 545194800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 560923199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 560923200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 574225199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 574225200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 591767999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 591768000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 605674799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 605674800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 624427199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 624427200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 637729199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 637729200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 653457599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 653457600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 668573999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 668574000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 687326399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 687326400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 700628399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 700628400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 718775999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 718776000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 732077999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 732078000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 750225599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 750225600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 763527599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 763527600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 781675199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 781675200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 794977199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 794977200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 813729599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 813729600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 826426799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 826426800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 845179199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 845179200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 859690799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 859690800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 876628799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 876628800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 889930799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 889930800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 906868799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 906868800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 923194799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 923194800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 939527999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 939528000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 952829999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 952830000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 971582399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 971582400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 984279599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 984279600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1003031999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1003032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1015729199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1015729200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1034481599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1034481600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1047178799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1047178800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1065931199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1065931200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1079233199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1079233200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1097380799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1097380800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1110682799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1110682800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1128830399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1128830400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1142132399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1142132400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1160884799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1160884800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1173581999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1173582000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1192334399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1192334400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1206845999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1206846000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1223783999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1223784000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1237085999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1237086000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1255233599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1255233600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1268535599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1268535600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1286683199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1286683200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1299985199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1299985200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1318132799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1318132800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1331434799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1331434800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1350187199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1350187200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1362884399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1362884400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1381636799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1381636800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1394333999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1394334000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1413086399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1413086400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1426388399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1426388400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1444535999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1444536000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1457837999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1457838000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1475985599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1475985600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1489287599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1489287600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1508039999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1508040000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1520737199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1520737200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1539489599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1539489600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1552186799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1552186800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1570939199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1570939200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1584241199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1584241200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1602388799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1602388800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1615690799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1615690800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1633838399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1633838400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1647140399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1647140400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1665287999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1665288000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1678589999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1678590000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1697342399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1697342400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1710039599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1710039600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1728791999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1728792000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1741489199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1741489200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1760241599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1760241600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1773543599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1773543600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1791691199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1791691200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1804993199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1804993200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1823140799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1823140800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1836442799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1836442800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1855195199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1855195200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1867892399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1867892400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1886644799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1886644800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1899341999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1899342000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1918094399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1918094400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1930791599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1930791600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1949543999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1949544000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1962845999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1962846000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1980993599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1980993600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1994295599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1994295600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2012443199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2012443200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2025745199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2025745200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2044497599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2044497600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2057194799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2057194800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2075947199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2075947200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2088644399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2088644400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2107396799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2107396800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2120698799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2120698800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2138846399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2138846400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Santo_Domingo.json b/dojox/date/tests/tztests/tz_America-Santo_Domingo.json
new file mode 100644
index 0000000..8f6164b
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Santo_Domingo.json
@@ -0,0 +1,44 @@
+({
+	name: "date.timezone.America-Santo_Domingo",
+	runTest: function(t){
+		var tz = "America/Santo_Domingo";
+		doh.checkDate({tzOffset: 280, tzAbbr: "SDMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 280, tzAbbr: "SDMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 280, tzAbbr: "SDMT"}, -1159773601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1159773600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -100119601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -100119600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -89668801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -89668800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5770801000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "EHDT"}, -5770800000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "EHDT"}, 4422599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 4422600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25678799000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "EHDT"}, 25678800000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "EHDT"}, 33193799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 33193800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 57733199000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "EHDT"}, 57733200000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "EHDT"}, 64816199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 64816200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 89182799000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "EHDT"}, 89182800000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "EHDT"}, 96438599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 96438600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 120632399000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "EHDT"}, 120632400000, tz, 1);
+		doh.checkDate({tzOffset: 270, tzAbbr: "EHDT"}, 127974599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 127974600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152081999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 152082000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 972799199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 975823199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 975823200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Sao_Paulo.json b/dojox/date/tests/tztests/tz_America-Sao_Paulo.json
new file mode 100644
index 0000000..82a5a68
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Sao_Paulo.json
@@ -0,0 +1,268 @@
+({
+	name: "date.timezone.America-Sao_Paulo",
+	runTest: function(t){
+		var tz = "America/Sao_Paulo";
+		doh.checkDate({tzOffset: 186.466666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 186.466666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 186.466666666667, tzAbbr: "LMT"}, -1767214413000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1767214412000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1206957601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1206957600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1191362401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1191362400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1175374801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1175374800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -1159826401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -1159826400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -633819601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -633819600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -622069201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -622069200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -602283601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -602283600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -591832801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -591832800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -570747601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -570747600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -560210401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -560210400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -539125201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -539125200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -531352801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -531352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -195426001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -195426000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -184197601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -184197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -155163601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -155163600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -150069601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -150069600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -128898001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -128898000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -121125601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -121125600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -99954001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -99954000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -89589601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -89589600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -68418001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -68418000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, -57967201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, -57967200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 499748399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 499748400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 511235999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 511236000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 530593199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 530593200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 540266399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 540266400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 562129199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 562129200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 571197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 571197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 592973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 592974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 602042399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 602042400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 624423599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 624423600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 634701599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 634701600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 656477999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 656478000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 666755999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 666756000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 687927599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 687927600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 697600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 697600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 719981999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 719982000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 728445599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 728445600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 750826799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 750826800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 761709599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 761709600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 782276399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 782276400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 793159199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 793159200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 813725999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 813726000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 824003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 824004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 844570799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 844570800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 856058399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 856058400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 876106799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 876106800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 888717599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 888717600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 908074799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 908074800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 919562399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 919562400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 938919599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 938919600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 951616799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 951616800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 970973999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 970974000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 982461599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 982461600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1003028399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1003028400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1013911199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1013911200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1036292399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1036292400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1045360799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1045360800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1066532399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1066532400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1076810399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1076810400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1099364399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1099364400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1108864799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1108864800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1129431599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1129431600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1140314399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1140314400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1162695599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1162695600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1172368799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1172368800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1192330799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1192330800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1203213599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1203213600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1224385199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1224385200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1234663199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1234663200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1255834799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1255834800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1266717599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1266717600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1287284399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1287284400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1298167199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1298167200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1318733999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1318734000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1330221599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1330221600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1350788399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1350788400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1361066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1361066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1382237999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1382238000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1392515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1392516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1413687599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1413687600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1424570399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1424570400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1445137199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1445137200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1456019999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1456020000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1476586799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1476586800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1487469599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1487469600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1508036399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1508036400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1518919199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1518919200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1540090799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1540090800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1550368799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1550368800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1571540399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1571540400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1581818399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1581818400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1602989999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1602990000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1613872799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1613872800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1634439599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1634439600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1645322399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1645322400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1665889199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1665889200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1677376799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1677376800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1697338799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1697338800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1708221599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1708221600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1729393199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1729393200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1739671199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1739671200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1760842799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1760842800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1771725599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1771725600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1792292399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1792292400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1803175199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1803175200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1823741999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1823742000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1834624799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1834624800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1855191599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1855191600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1866074399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1866074400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1887245999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1887246000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1897523999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1897524000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1918695599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1918695600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1928973599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1928973600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1950145199000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1950145200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1960423199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1960423200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1981594799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1981594800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1992477599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1992477600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2013044399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 2013044400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 2024531999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2024532000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2044493999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 2044494000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 2055376799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2055376800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2076548399000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 2076548400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 2086826399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2086826400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2107997999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 2107998000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 2118880799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2118880800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 2139447599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 2139447600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "BRST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "BRT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Scoresbysund.json b/dojox/date/tests/tztests/tz_America-Scoresbysund.json
new file mode 100644
index 0000000..95841a7
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Scoresbysund.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.America-Scoresbysund",
+	runTest: function(t){
+		var tz = "America/Scoresbysund";
+		doh.checkDate({tzOffset: 87.8666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 87.8666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 87.8666666666667, tzAbbr: "LMT"}, -1686090729000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "CGT"}, -1686090728000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "CGT"}, 323841599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "CGST"}, 323841600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "CGST"}, 338961599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "CGT"}, 338961600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "CGT"}, 354679199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 354679200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "EGT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "EGST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-St_Johns.json b/dojox/date/tests/tztests/tz_America-St_Johns.json
new file mode 100644
index 0000000..eea742d
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-St_Johns.json
@@ -0,0 +1,488 @@
+({
+	name: "date.timezone.America-St_Johns",
+	runTest: function(t){
+		var tz = "America/St_Johns";
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1664130549000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1664130548000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1650137349000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1650137348000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1632076149000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1632076148000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1614799749000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1614799748000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1598650149000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1598650148000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1590100149000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1590100148000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1567286949000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1567286948000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1551565749000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1551565748000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1535837349000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1535837348000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1520116149000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1520116148000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1503782949000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1503782948000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1488666549000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1488666548000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1472333349000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1472333348000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1457216949000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1457216948000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1440883749000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1440883748000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1425767349000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1425767348000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1409434149000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1409434148000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1394317749000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1394317748000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1377984549000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1377984548000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1362263349000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1362263348000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1346534949000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1346534948000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1330813749000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1330813748000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1314480549000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1314480548000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1299364149000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1299364148000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1283030949000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1283030948000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1267914549000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1267914548000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1251581349000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1251581348000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1236464949000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1236464948000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1220131749000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1220131748000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1205015349000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1205015348000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1188682149000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1188682148000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1172960949000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1172960948000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1156627749000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1156627748000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1141511349000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1141511348000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1125178149000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1125178148000, tz, 1);
+		doh.checkDate({tzOffset: 150.866666666667, tzAbbr: "NDT"}, -1110061749000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1110061748000, tz, 1);
+		doh.checkDate({tzOffset: 210.866666666667, tzAbbr: "NST"}, -1096921749000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1096921748000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1093728601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -1093728600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -1078612201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1078612200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1061670601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -1061670600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -1048973401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1048973400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1030221001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -1030221000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -1017523801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -1017523800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -998771401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -998771400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -986074201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -986074200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -966717001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -966717000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -954624601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -954624600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -935267401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -935267400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -922570201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -922570200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -903817801000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -903817800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -891120601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -891120600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -872368201000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NWT"}, -872368200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NPT"}, -765401401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -765401400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -746044201000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -746044200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -733347001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -733347000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -714594601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -714594600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -701897401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -701897400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -683145001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -683145000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -670447801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -670447800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -651695401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -651695400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -638998201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -638998200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -619641001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -619641000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -606943801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -606943800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -589401001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -589401000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -576099001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -576099000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -557951401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -557951400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -544649401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -544649400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -526501801000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -526501800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -513199801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -513199800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -495052201000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -495052200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -481750201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -481750200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -463602601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -463602600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -450300601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -450300600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -431548201000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -431548200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -418246201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -418246200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -400098601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -400098600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -386796601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -386796600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -368649001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -368649000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -355347001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -355347000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -337199401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -337199400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -323897401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -323897400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -305749801000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -305749800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -289423801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -289423800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -273695401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -273695400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -257974201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -257974200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -242245801000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -242245800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -226524601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -226524600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -210796201000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -210796200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -195075001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -195075000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -179346601000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -179346600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -163625401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -163625400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -147897001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -147897000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -131571001000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -131571000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -116447401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -116447400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -100121401000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -100121400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -84393001000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -84393000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -68671801000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -68671800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -52943401000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -52943400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -37222201000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -37222200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -21493801000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -21493800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, -5772601000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, -5772600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 9955799000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 9955800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 25676999000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 25677000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 41405399000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 41405400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 57731399000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 57731400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 73459799000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 73459800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 89180999000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 89181000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 104909399000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 104909400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 120630599000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 120630600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 136358999000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 136359000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 152080199000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 152080200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 167808599000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 167808600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 183529799000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 183529800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 199258199000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 199258200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 215584199000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 215584200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 230707799000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 230707800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 247033799000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 247033800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 262762199000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 262762200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 278483399000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 278483400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 294211799000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 294211800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 309932999000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 309933000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 325661399000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 325661400000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 341382599000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 341382600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 357110999000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 357111000000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 372832199000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 372832200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 388560599000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 388560600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 404886599000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 404886600000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 420010199000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 420010200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 436336199000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 436336200000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 452064599000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 452064600000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 467785799000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 467785800000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 483514199000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 483514200000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 499235399000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 499235400000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 514963799000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 514963800000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 530684999000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 530685000000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 544591859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 544591860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 562127459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 562127460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 576041459000, tz, 1);
+		doh.checkDate({tzOffset: 90, tzAbbr: "NDDT"}, 576041460000, tz, 1);
+		doh.checkDate({tzOffset: 90, tzAbbr: "NDDT"}, 594178259000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 594178260000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 607491059000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 607491060000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 625631459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 625631460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 638940659000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 638940660000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 657081059000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 657081060000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 670995059000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 670995060000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 688530659000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 688530660000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 702444659000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 702444660000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 719980259000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 719980260000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 733894259000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 733894260000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 752034659000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 752034660000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 765343859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 765343860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 783484259000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 783484260000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 796793459000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 796793460000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 814933859000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 814933860000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 828847859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 828847860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 846383459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 846383460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 860297459000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 860297460000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 877833059000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 877833060000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 891747059000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 891747060000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 909282659000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 909282660000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 923196659000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 923196660000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 941337059000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 941337060000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 954646259000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 954646260000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 972786659000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 972786660000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 986095859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 986095860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1004236259000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1004236260000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1018150259000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1018150260000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1035685859000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1035685860000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1049599859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1049599860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1067135459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1067135460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1081049459000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1081049460000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1099189859000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1099189860000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1112499059000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1112499060000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1130639459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1130639460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1143948659000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1143948660000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1162089059000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1162089060000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1173583859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1173583860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1194143459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1194143460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1205033459000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1205033460000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1225593059000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1225593060000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1236483059000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1236483060000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1257042659000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1257042660000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1268537459000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1268537460000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1289097059000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1289097060000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1299987059000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1299987060000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1320546659000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1320546660000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1331436659000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1331436660000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1351996259000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1351996260000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1362886259000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1362886260000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1383445859000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1383445860000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1394335859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1394335860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1414895459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1414895460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1425785459000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1425785460000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1446345059000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1446345060000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1457839859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1457839860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1478399459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1478399460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1489289459000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1489289460000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1509849059000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1509849060000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1520739059000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1520739060000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1541298659000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1541298660000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1552188659000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1552188660000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1572748259000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1572748260000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1583638259000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1583638260000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1604197859000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1604197860000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1615692659000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1615692660000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1636252259000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1636252260000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1647142259000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1647142260000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1667701859000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1667701860000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1678591859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1678591860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1699151459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1699151460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1710041459000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1710041460000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1730601059000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1730601060000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1741491059000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1741491060000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1762050659000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1762050660000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1772940659000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1772940660000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1793500259000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1793500260000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1804995059000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1804995060000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1825554659000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1825554660000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1836444659000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1836444660000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1857004259000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1857004260000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1867894259000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1867894260000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1888453859000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1888453860000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1899343859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1899343860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1919903459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1919903460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1930793459000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1930793460000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1951353059000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1951353060000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1962847859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1962847860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1983407459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1983407460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1994297459000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1994297460000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 2014857059000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 2014857060000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 2025747059000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 2025747060000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 2046306659000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 2046306660000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 2057196659000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 2057196660000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 2077756259000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 2077756260000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 2088646259000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 2088646260000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 2109205859000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 2109205860000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 2120095859000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 2120095860000, tz, 1);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 2140655459000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 2140655460000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 210, tzAbbr: "NST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 150, tzAbbr: "NDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-St_Kitts.json b/dojox/date/tests/tztests/tz_America-St_Kitts.json
new file mode 100644
index 0000000..b0c5208
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-St_Kitts.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-St_Kitts",
+	runTest: function(t){
+		var tz = "America/St_Kitts";
+		doh.checkDate({tzOffset: 250.866666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 250.866666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 250.866666666667, tzAbbr: "LMT"}, -1825098549000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1825098548000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-St_Lucia.json b/dojox/date/tests/tztests/tz_America-St_Lucia.json
new file mode 100644
index 0000000..0f3e54c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-St_Lucia.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-St_Lucia",
+	runTest: function(t){
+		var tz = "America/St_Lucia";
+		doh.checkDate({tzOffset: 244, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 244, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 244, tzAbbr: "CMT"}, -1830369361000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1830369360000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-St_Thomas.json b/dojox/date/tests/tztests/tz_America-St_Thomas.json
new file mode 100644
index 0000000..9cceb0f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-St_Thomas.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-St_Thomas",
+	runTest: function(t){
+		var tz = "America/St_Thomas";
+		doh.checkDate({tzOffset: 259.733333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 259.733333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 259.733333333333, tzAbbr: "LMT"}, -1846266017000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1846266016000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-St_Vincent.json b/dojox/date/tests/tztests/tz_America-St_Vincent.json
new file mode 100644
index 0000000..daff3c4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-St_Vincent.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-St_Vincent",
+	runTest: function(t){
+		var tz = "America/St_Vincent";
+		doh.checkDate({tzOffset: 244.933333333333, tzAbbr: "KMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 244.933333333333, tzAbbr: "KMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 244.933333333333, tzAbbr: "KMT"}, -1830369305000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1830369304000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Swift_Current.json b/dojox/date/tests/tztests/tz_America-Swift_Current.json
new file mode 100644
index 0000000..b0e7c1f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Swift_Current.json
@@ -0,0 +1,58 @@
+({
+	name: "date.timezone.America-Swift_Current",
+	runTest: function(t){
+		var tz = "America/Swift_Current";
+		doh.checkDate({tzOffset: 431.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 431.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 431.333333333333, tzAbbr: "LMT"}, -2030201321000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2030201320000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1632063601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1632063600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1614787201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1614787200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -880210801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -880210800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -765388801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -765388800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -747241201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -747241200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -732729601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -732729600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -715791601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -715791600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -702489601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -702489600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -684342001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -684342000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -671040001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -671040000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -652892401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -652892400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -639590401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -639590400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -400086001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -400086000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -384364801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -384364800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -337186801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -337186800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -321465601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -321465600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -305737201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -305737200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -292435201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -292435200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -273682801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -273682800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -260985601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -260985600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 73472399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 73472400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Tegucigalpa.json b/dojox/date/tests/tztests/tz_America-Tegucigalpa.json
new file mode 100644
index 0000000..f175a98
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Tegucigalpa.json
@@ -0,0 +1,26 @@
+({
+	name: "date.timezone.America-Tegucigalpa",
+	runTest: function(t){
+		var tz = "America/Tegucigalpa";
+		doh.checkDate({tzOffset: 348.866666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 348.866666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 348.866666666667, tzAbbr: "LMT"}, -1538503869000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1538503868000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 547019999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 547020000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 559717199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 559717200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 578469599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 578469600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 591166799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 591166800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1146981599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1146981600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1154926799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1154926800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Thule.json b/dojox/date/tests/tztests/tz_America-Thule.json
new file mode 100644
index 0000000..05867fa
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Thule.json
@@ -0,0 +1,202 @@
+({
+	name: "date.timezone.America-Thule",
+	runTest: function(t){
+		var tz = "America/Thule";
+		doh.checkDate({tzOffset: 275.133333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 275.133333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 275.133333333333, tzAbbr: "LMT"}, -1686079493000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1686079492000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 670399199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 670399200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 686120399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 686120400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 701848799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 701848800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 717569999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 717570000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 733903199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 733903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 752043599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 752043600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 765352799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 765352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 783493199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 783493200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 796802399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 796802400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 814942799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 814942800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 828856799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 828856800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 846392399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 846392400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 860306399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 860306400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 877841999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 877842000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 891755999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 891756000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 909291599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 909291600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 923205599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 923205600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 941345999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 941346000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 954655199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 954655200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 972795599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 972795600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 986104799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 986104800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1004245199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1004245200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1018159199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1018159200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1035694799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1035694800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1049608799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1049608800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1067144399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1067144400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1081058399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1081058400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1099198799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1099198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1112507999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1112508000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1130648399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1130648400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1143957599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1143957600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1162097999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1162098000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1173592799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1173592800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1194152399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1194152400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1205042399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1205042400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1225601999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1225602000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1236491999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1236492000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1257051599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1257051600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1268546399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1268546400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1289105999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1289106000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1299995999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1299996000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1320555599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1320555600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1331445599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1331445600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1352005199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1352005200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1362895199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1362895200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1383454799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1383454800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1394344799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1394344800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1414904399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1414904400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1425794399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1425794400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1446353999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1446354000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1457848799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1457848800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1478408399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1478408400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1489298399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1489298400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1509857999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1509858000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1520747999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1520748000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1541307599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1541307600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1552197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1552197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1572757199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1572757200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1583647199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1583647200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1604206799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1604206800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1615701599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1615701600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1636261199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1636261200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1647151199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1647151200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1667710799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1667710800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1678600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1678600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1699160399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1699160400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1710050399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1710050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1730609999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1730610000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1741499999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1741500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1762059599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1762059600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1772949599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1772949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1793509199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1793509200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1805003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1805004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1825563599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1825563600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1836453599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1836453600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1857013199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1857013200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1867903199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1867903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1888462799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1888462800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1899352799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1899352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1919912399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1919912400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1930802399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1930802400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1951361999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1951362000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1962856799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1962856800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1983416399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1983416400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1994306399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1994306400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2014865999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2014866000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2025755999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2025756000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2046315599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2046315600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2057205599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2057205600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2077765199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2077765200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2088655199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2088655200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2109214799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2109214800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2120104799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2120104800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2140664399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2140664400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Thunder_Bay.json b/dojox/date/tests/tztests/tz_America-Thunder_Bay.json
new file mode 100644
index 0000000..032a3a8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Thunder_Bay.json
@@ -0,0 +1,288 @@
+({
+	name: "date.timezone.America-Thunder_Bay",
+	runTest: function(t){
+		var tz = "America/Thunder_Bay";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1893434401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1893434400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -880218001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -880218000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -765396001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -765396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 41410799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 41410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 57736799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 57736800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 73465199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 73465200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 89186399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 89186400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 136364399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 136364400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 152085599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152085600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 167813999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 167814000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 183535199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 183535200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 199263599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 199263600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 215589599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 215589600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 230713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 230713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 247039199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 247039200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 262767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 262767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 278488799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 278488800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 294217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 294217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 309938399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 309938400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467791199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467791200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499240799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530690399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 544604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 544604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562139999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 954658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 954658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 972799199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Tijuana.json b/dojox/date/tests/tztests/tz_America-Tijuana.json
new file mode 100644
index 0000000..eb46518
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Tijuana.json
@@ -0,0 +1,310 @@
+({
+	name: "date.timezone.America-Tijuana",
+	runTest: function(t){
+		var tz = "America/Tijuana";
+		doh.checkDate({tzOffset: 468.066666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 468.066666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 468.066666666667, tzAbbr: "LMT"}, -1514736001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1514736000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1451667601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1451667600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1343062801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1343062800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1234803601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1234803600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1222963201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1222963200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1207242001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1207242000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -873820801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -873820800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -761677201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -761677200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -686073601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -686073600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -661539601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -661539600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -495036001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -495036000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -481734001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -481734000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -463586401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -463586400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -450284401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -450284400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -431532001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -431532000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -418230001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -418230000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -400082401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -400082400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -386780401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -386780400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -368632801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -368632800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -355330801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -355330800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -337183201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -337183200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -323881201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -323881200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -305733601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -305733600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -292431601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -292431600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 199274399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 199274400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 215600399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 215600400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 230723999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 230724000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 247049999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 247050000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 262778399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 262778400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 278499599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 278499600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 294227999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 294228000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 309949199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 309949200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 325677599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 325677600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 341398799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 341398800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 357127199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 357127200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 372848399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 372848400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 388576799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 388576800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 404902799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 404902800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 420026399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 420026400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 436352399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 436352400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 452080799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 452080800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 467801999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 467802000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 483530399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 483530400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 499251599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 499251600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 514979999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 514980000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 530701199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 530701200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 544615199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 544615200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 562150799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 562150800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 576064799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 576064800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 594205199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 594205200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 607514399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 607514400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 625654799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 625654800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 638963999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 638964000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 657104399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 657104400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 671018399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 671018400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 688553999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 688554000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 702467999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 702468000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 720003599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 720003600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 733917599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 733917600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 752057999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 752058000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 765367199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 765367200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 783507599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 783507600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 796816799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 796816800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 814957199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 814957200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 828871199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 828871200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 846406799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 846406800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 860320799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 860320800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 877856399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 877856400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 891770399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 891770400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 909305999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 909306000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 923219999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 923220000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 941360399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 941360400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 954669599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 954669600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 972809999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 972810000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 986119199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 986119200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1004259599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1004259600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1018173599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1018173600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1035709199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1035709200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1049623199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1049623200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1067158799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1067158800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1081072799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1081072800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1099213199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1099213200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1112522399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1112522400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1130662799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1130662800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1143971999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1143972000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1162112399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1162112400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1175421599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1175421600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1193561999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1193562000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1207475999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1207476000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1225011599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1225011600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1238925599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1238925600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1256461199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1256461200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1270375199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1270375200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1288515599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1288515600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1301824799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1301824800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1319965199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1319965200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1333274399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1333274400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1351414799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1351414800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1365328799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1365328800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1382864399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1382864400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1396778399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1396778400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1414313999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1414314000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1428227999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1428228000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1445763599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1445763600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1459677599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1459677600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1477817999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1477818000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1491127199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1491127200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1509267599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1509267600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1522576799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1522576800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1540717199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1540717200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1554631199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1554631200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1572166799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1572166800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1586080799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1586080800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1603616399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1603616400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1617530399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1617530400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1635670799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1635670800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1648979999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1648980000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1667120399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1667120400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1680429599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1680429600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1698569999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1698570000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1712483999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1712484000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1730019599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1730019600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1743933599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1743933600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1761469199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1761469200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1775383199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1775383200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1792918799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1792918800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1806832799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1806832800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1824973199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1824973200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1838282399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1838282400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1856422799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1856422800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1869731999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1869732000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1887872399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1887872400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1901786399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1901786400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1919321999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1919322000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1933235999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1933236000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1950771599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1950771600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1964685599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1964685600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1982825999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1982826000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1996135199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1996135200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2014275599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2014275600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2027584799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2027584800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2045725199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2045725200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2059034399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2059034400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2077174799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2077174800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2091088799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2091088800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2108624399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2108624400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2122538399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2122538400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2140073999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2140074000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Toronto.json b/dojox/date/tests/tztests/tz_America-Toronto.json
new file mode 100644
index 0000000..b1b56b1
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Toronto.json
@@ -0,0 +1,476 @@
+({
+	name: "date.timezone.America-Toronto",
+	runTest: function(t){
+		var tz = "America/Toronto";
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1632070801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1632070800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1614794401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1614794400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1601753401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1601753400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1583697601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1583697600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1567357201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1567357200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1554667201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1554667200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1534698001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1534698000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1524074401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1524074400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1503248401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1503248400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1492365601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1492365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1471798801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1471798800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1460916001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1460916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1440954001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1440954000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1428861601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1428861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1409504401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1409504400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1397412001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1397412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1378054801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1378054800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1365962401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1365962400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1346605201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1346605200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1333908001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1333908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1315155601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1315155600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1301853601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1301853600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1283706001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1283706000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1270404001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1270404000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1252256401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1252256400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1238954401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1238954400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1220806801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1220806800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1207504801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1207504800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1188752401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1188752400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1176055201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1176055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1157302801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1157302800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1144000801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1144000800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1125853201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1125853200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1112551201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1112551200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1094403601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1094403600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1081101601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1081101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1062954001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1062954000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1049652001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1049652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1031504401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1031504400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1018202401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1018202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1000054801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1000054800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -986752801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -986752800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -968000401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -968000400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -955303201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -955303200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -936550801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -936550800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -880218001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -880218000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -765396001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -765396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -747248401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -747248400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -733946401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -733946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -715806001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -715806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -702504001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -702504000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -684356401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -684356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -671054401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -671054400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -652906801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -652906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -634161601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -634161600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -620845201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -620845200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -602704801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -602704800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -589395601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -589395600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -576093601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -576093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -557946001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -557946000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -544644001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -544644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -526496401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -526496400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -513194401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -513194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -495046801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -495046800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -481744801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -481744800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -463597201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -463597200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -450295201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -450295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -431542801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -431542800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -418240801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -418240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -400093201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -400093200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -384372001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -384372000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -368643601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -368643600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -352922401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -352922400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -337194001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -337194000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -321472801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -321472800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -305744401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -305744400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -289418401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -289418400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -273690001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -273690000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -257968801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -257968800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -242240401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -242240400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -226519201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -226519200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -210790801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -210790800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -195069601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -195069600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -179341201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -179341200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -163620001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -163620000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -147891601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -147891600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -131565601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -131565600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -116442001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -116442000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -100116001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -100116000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -84387601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -84387600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -68666401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -68666400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -52938001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -52938000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -37216801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -37216800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 41410799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 41410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 57736799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 57736800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 73465199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 73465200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 89186399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 89186400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 104914799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 104914800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 120635999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 120636000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 136364399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 136364400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 152085599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152085600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 167813999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 167814000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 183535199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 183535200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 199263599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 199263600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 215589599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 215589600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 230713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 230713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 247039199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 247039200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 262767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 262767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 278488799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 278488800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 294217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 294217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 309938399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 309938400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467791199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467791200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499240799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530690399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 544604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 544604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562139999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 954658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 954658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 972799199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Tortola.json b/dojox/date/tests/tztests/tz_America-Tortola.json
new file mode 100644
index 0000000..6cdec8f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Tortola.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.America-Tortola",
+	runTest: function(t){
+		var tz = "America/Tortola";
+		doh.checkDate({tzOffset: 258.466666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 258.466666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 258.466666666667, tzAbbr: "LMT"}, -1846266093000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1846266092000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Vancouver.json b/dojox/date/tests/tztests/tz_America-Vancouver.json
new file mode 100644
index 0000000..2a28172
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Vancouver.json
@@ -0,0 +1,390 @@
+({
+	name: "date.timezone.America-Vancouver",
+	runTest: function(t){
+		var tz = "America/Vancouver";
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1632060001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1632060000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1614783601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1614783600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -880207201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -880207200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -765385201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -765385200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -747237601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -747237600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -732726001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -732726000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -715788001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -715788000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -702486001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -702486000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -684338401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -684338400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -671036401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -671036400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -652888801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -652888800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -639586801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -639586800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -620834401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -620834400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -608137201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -608137200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -589384801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -589384800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -576082801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -576082800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -557935201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -557935200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -544633201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -544633200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -526485601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -526485600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -513183601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -513183600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -495036001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -495036000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -481734001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -481734000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -463586401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -463586400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -450284401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -450284400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -431532001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -431532000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -418230001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -418230000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -400082401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -400082400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -386780401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -386780400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -368632801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -368632800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -355330801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -355330800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -337183201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -337183200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -323881201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -323881200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -305733601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -305733600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -292431601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -292431600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -273679201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -273679200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -260982001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -260982000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -242229601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -242229600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -226508401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -226508400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -210780001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -210780000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -195058801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -195058800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -179330401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -179330400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -163609201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -163609200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -147880801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -147880800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -131554801000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -131554800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -116431201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -116431200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -100105201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -100105200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -84376801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -84376800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -68655601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -68655600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -52927201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -52927200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -37206001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -37206000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -21477601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -21477600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -5756401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -5756400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 9971999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 9972000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 25693199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 25693200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 41421599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 41421600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 57747599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 57747600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 73475999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 73476000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 89197199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 89197200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 104925599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 104925600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 120646799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 120646800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 136375199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 136375200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 152096399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 152096400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 167824799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 167824800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 183545999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 183546000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 199274399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 199274400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 215600399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 215600400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 230723999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 230724000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 247049999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 247050000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 262778399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 262778400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 278499599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 278499600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 294227999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 294228000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 309949199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 309949200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 325677599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 325677600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 341398799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 341398800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 357127199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 357127200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 372848399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 372848400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 388576799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 388576800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 404902799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 404902800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 420026399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 420026400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 436352399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 436352400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 452080799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 452080800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 467801999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 467802000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 483530399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 483530400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 499251599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 499251600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 514979999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 514980000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 530701199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 530701200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 544615199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 544615200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 562150799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 562150800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 576064799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 576064800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 594205199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 594205200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 607514399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 607514400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 625654799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 625654800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 638963999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 638964000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 657104399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 657104400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 671018399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 671018400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 688553999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 688554000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 702467999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 702468000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 720003599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 720003600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 733917599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 733917600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 752057999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 752058000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 765367199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 765367200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 783507599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 783507600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 796816799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 796816800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 814957199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 814957200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 828871199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 828871200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 846406799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 846406800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 860320799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 860320800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 877856399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 877856400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 891770399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 891770400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 909305999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 909306000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 923219999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 923220000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 941360399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 941360400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 954669599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 954669600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 972809999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 972810000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 986119199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 986119200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1004259599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1004259600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1018173599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1018173600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1035709199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1035709200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1049623199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1049623200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1067158799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1067158800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1081072799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1081072800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1099213199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1099213200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1112522399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1112522400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1130662799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1130662800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1143971999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1143972000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1162112399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1162112400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1173607199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1173607200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1194166799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1194166800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1205056799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1205056800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1225616399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1225616400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1236506399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1236506400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1257065999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1257066000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1268560799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1268560800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1289120399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1289120400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1300010399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1300010400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1320569999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1320570000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1331459999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1331460000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1352019599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1352019600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1362909599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1362909600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1383469199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1383469200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1394359199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1394359200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1414918799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1414918800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1425808799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1425808800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1446368399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1446368400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1457863199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1457863200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1478422799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1478422800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1489312799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1489312800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1509872399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1509872400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1520762399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1520762400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1541321999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1541322000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1552211999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1552212000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1572771599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1572771600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1583661599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1583661600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1604221199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1604221200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1615715999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1615716000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1636275599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1636275600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1647165599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1647165600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1667725199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1667725200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1678615199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1678615200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1699174799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1699174800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1710064799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1710064800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1730624399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1730624400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1741514399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1741514400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1762073999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1762074000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1772963999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1772964000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1793523599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1793523600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1805018399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1805018400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1825577999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1825578000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1836467999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1836468000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1857027599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1857027600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1867917599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1867917600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1888477199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1888477200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1899367199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1899367200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1919926799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1919926800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1930816799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1930816800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1951376399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1951376400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1962871199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1962871200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1983430799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1983430800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1994320799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1994320800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2014880399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2014880400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2025770399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2025770400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2046329999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2046330000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2057219999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2057220000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2077779599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2077779600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2088669599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2088669600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2109229199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2109229200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2120119199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2120119200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2140678799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2140678800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Whitehorse.json b/dojox/date/tests/tztests/tz_America-Whitehorse.json
new file mode 100644
index 0000000..3da89ac
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Whitehorse.json
@@ -0,0 +1,264 @@
+({
+	name: "date.timezone.America-Whitehorse",
+	runTest: function(t){
+		var tz = "America/Whitehorse";
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -1632056401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, -1632056400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, -1615125601000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -1615125600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -1596978001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, -1596978000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, -1583164801000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -1583164800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -880203601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YWT"}, -880203600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YPT"}, -765381601000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -765381600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -147884401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "YDDT"}, -147884400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "YDDT"}, -131554801000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -131554800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -110552401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -110552400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 325677599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 325677600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 341398799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 341398800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 357127199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 357127200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 372848399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 372848400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 388576799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 388576800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 404902799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 404902800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 420026399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 420026400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 436352399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 436352400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 452080799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 452080800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 467801999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 467802000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 483530399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 483530400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 499251599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 499251600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 514979999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 514980000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 530701199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 530701200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 544615199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 544615200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 562150799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 562150800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 576064799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 576064800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 594205199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 594205200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 607514399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 607514400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 625654799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 625654800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 638963999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 638964000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 657104399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 657104400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 671018399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 671018400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 688553999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 688554000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 702467999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 702468000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 720003599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 720003600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 733917599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 733917600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 752057999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 752058000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 765367199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 765367200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 783507599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 783507600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 796816799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 796816800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 814957199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 814957200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 828871199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 828871200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 846406799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 846406800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 860320799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 860320800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 877856399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 877856400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 891770399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 891770400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 909305999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 909306000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 923219999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 923220000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 941360399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 941360400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 954669599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 954669600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 972809999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 972810000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 986119199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 986119200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1004259599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1004259600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1018173599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1018173600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1035709199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1035709200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1049623199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1049623200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1067158799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1067158800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1081072799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1081072800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1099213199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1099213200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1112522399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1112522400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1130662799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1130662800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1143971999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1143972000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1162112399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1162112400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1173607199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1173607200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1194166799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1194166800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1205056799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1205056800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1225616399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1225616400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1236506399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1236506400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1257065999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1257066000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1268560799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1268560800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1289120399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1289120400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1300010399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1300010400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1320569999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1320570000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1331459999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1331460000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1352019599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1352019600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1362909599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1362909600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1383469199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1383469200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1394359199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1394359200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1414918799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1414918800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1425808799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1425808800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1446368399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1446368400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1457863199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1457863200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1478422799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1478422800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1489312799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1489312800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1509872399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1509872400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1520762399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1520762400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1541321999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1541322000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1552211999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1552212000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1572771599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1572771600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1583661599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1583661600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1604221199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1604221200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1615715999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1615716000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1636275599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1636275600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1647165599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1647165600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1667725199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1667725200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1678615199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1678615200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1699174799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1699174800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1710064799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1710064800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1730624399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1730624400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1741514399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1741514400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1762073999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1762074000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1772963999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1772964000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1793523599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1793523600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1805018399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1805018400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1825577999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1825578000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1836467999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1836468000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1857027599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1857027600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1867917599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1867917600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1888477199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1888477200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1899367199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1899367200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1919926799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1919926800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1930816799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1930816800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1951376399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1951376400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1962871199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1962871200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1983430799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1983430800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1994320799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1994320800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2014880399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2014880400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2025770399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2025770400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2046329999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2046330000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2057219999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2057220000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2077779599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2077779600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2088669599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2088669600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2109229199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2109229200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2120119199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2120119200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2140678799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2140678800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Winnipeg.json b/dojox/date/tests/tztests/tz_America-Winnipeg.json
new file mode 100644
index 0000000..e77ab66
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Winnipeg.json
@@ -0,0 +1,382 @@
+({
+	name: "date.timezone.America-Winnipeg",
+	runTest: function(t){
+		var tz = "America/Winnipeg";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1694368801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1694368800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1681671601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1681671600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1632067201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1632067200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1614790801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1614790800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1029686401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1029686400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1018198801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1018198800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -746035201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -746035200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -732733201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -732733200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -715795201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -715795200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -702493201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -702493200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -684345601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -684345600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -671043601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -671043600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -652896001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -652896000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -639594001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -639594000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -620755201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -620755200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -607626001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -607626000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -589392001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -589392000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -576090001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -576090000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -557942401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -557942400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -544640401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -544640400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -526492801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -526492800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -513190801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -513190800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -495043201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -495043200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -481741201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -481741200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -463593601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -463593600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -450291601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -450291600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -431539201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -431539200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -418237201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -418237200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -400089601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -400089600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -386787601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -386787600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -368640001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -368640000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -355338001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -355338000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -337190401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -337190400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -321469201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -321469200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -305740801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -305740800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -292438801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -292438800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -210787201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -210787200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -198090001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -198090000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -116438401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -116438400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -100108801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -100108800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -84384001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -84384000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -68659201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -68659200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -52934401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -52934400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -37209601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -37209600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -21484801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -21484800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -5760001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -5760000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 9964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 9964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 25689599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 25689600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 41414399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 41414400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 57743999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 57744000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 73468799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 73468800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 89193599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 89193600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 104918399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 104918400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 120643199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 120643200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 136367999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 136368000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 152092799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 152092800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 167817599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 167817600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 183542399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 183542400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 199267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 199267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 215596799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 215596800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 230716799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 230716800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 247046399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 247046400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 262771199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 262771200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 278495999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 278496000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 294220799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 294220800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 309945599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 309945600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 325670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 325670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 341395199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 341395200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 357119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 357120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 372844799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 372844800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 388569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 388569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 404899199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 404899200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 420019199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 420019200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 436348799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 436348800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 452073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 452073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 467798399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 467798400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 483523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 483523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 499247999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 499248000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 514972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 514972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 530697599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 530697600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 544607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 544608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 562147199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 562147200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 576057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 576057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 594201599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 594201600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 607507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 607507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 625651199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 625651200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 638956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 638956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 657100799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 657100800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 671011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 671011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 688550399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 688550400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 702460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 702460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 719999999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 720000000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 733910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 733910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 752054399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 752054400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 765359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 765360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 783503999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 783504000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 796809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 796809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 814953599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 814953600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846403199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846403200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877852799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877852800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941356799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941356800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972806399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 972806400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 986111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 986112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1004255999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1004256000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035705599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035705600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067155199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067155200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099209599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099209600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130659199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130659200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1205049599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1205049600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1236499199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1236499200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1257058799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1257058800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1268553599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1268553600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1289113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1289113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1300003199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1300003200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1320562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1320562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1331452799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1331452800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1352012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1352012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1362902399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1362902400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1383461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1383462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1394351999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1394352000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1425801599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1425801600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1446361199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1446361200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1457855999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1457856000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1478415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1478415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1489305599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1489305600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1520755199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1520755200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1541314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1541314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1552204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1552204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1583654399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1583654400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1604213999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1604214000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1615708799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1615708800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1636268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1636268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1647158399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1647158400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1678607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1678608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1699167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1699167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1710057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1710057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1741507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1741507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1762066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1762066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1772956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1772956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1793516399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1793516400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1805011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1805011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1825570799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1825570800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1836460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1836460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1857020399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1857020400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1867910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1867910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1888469999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1888470000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1899359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1899360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919919599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919919600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1930809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1930809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1951369199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1951369200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1962863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1962864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1983423599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1983423600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1994313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1994313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014873199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014873200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2025763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2025763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2046322799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2046322800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2057212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2057212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077772399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077772400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2088662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2088662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2109221999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2109222000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2120111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2120112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140671599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140671600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Yakutat.json b/dojox/date/tests/tztests/tz_America-Yakutat.json
new file mode 100644
index 0000000..c9995ad
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Yakutat.json
@@ -0,0 +1,296 @@
+({
+	name: "date.timezone.America-Yakutat",
+	runTest: function(t){
+		var tz = "America/Yakutat";
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -880203601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YWT"}, -880203600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YPT"}, -765381601000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -765381600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -21474001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, -21474000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, -5752801000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, -5752800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 9975599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 9975600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 25696799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 25696800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 41425199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 41425200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 57751199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 57751200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 73479599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 73479600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 89200799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 89200800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 104929199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 104929200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 120650399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 120650400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 126701999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 126702000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 152099999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 152100000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 162385199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 162385200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 183549599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 183549600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 199277999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 199278000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 215603999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 215604000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 230727599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 230727600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 247053599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 247053600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 262781999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 262782000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 278503199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 278503200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 294231599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 294231600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 309952799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 309952800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 325681199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 325681200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 341402399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 341402400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 357130799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 357130800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 372851999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 372852000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 388580399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 388580400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 404906399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 404906400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 420029999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 420030000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "YDT"}, 436355999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 436356000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "YST"}, 439030799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 439030800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 452084399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 452084400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 467805599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 467805600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 483533999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 483534000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 499255199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 499255200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 514983599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 514983600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 530704799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 530704800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 544618799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 544618800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 562154399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 562154400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 576068399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 576068400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 594208799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 594208800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 607517999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 607518000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 625658399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 625658400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 638967599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 638967600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 657107999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 657108000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 671021999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 671022000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 688557599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 688557600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 702471599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 702471600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 720007199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 720007200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 733921199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 733921200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 752061599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 752061600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 765370799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 765370800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 783511199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 783511200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 796820399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 796820400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 814960799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 814960800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 828874799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 828874800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 846410399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 846410400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 860324399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 860324400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 877859999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 877860000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 891773999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 891774000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 909309599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 909309600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 923223599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 923223600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 941363999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 941364000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 954673199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 954673200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 972813599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 972813600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 986122799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 986122800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1004263199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1004263200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1018177199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1018177200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1035712799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1035712800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1049626799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1049626800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1067162399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1067162400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1081076399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1081076400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1099216799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1099216800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1112525999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1112526000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1130666399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1130666400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1143975599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1143975600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1162115999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1162116000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1173610799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1173610800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1194170399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1194170400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1205060399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1205060400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1225619999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1225620000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1236509999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1236510000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1257069599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1257069600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1268564399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1268564400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1289123999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1289124000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1300013999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1300014000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1320573599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1320573600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1331463599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1331463600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1352023199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1352023200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1362913199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1362913200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1383472799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1383472800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1394362799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1394362800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1414922399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1414922400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1425812399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1425812400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1446371999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1446372000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1457866799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1457866800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1478426399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1478426400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1489316399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1489316400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1509875999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1509876000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1520765999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1520766000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1541325599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1541325600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1552215599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1552215600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1572775199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1572775200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1583665199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1583665200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1604224799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1604224800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1615719599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1615719600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1636279199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1636279200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1647169199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1647169200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1667728799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1667728800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1678618799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1678618800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1699178399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1699178400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1710068399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1710068400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1730627999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1730628000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1741517999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1741518000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1762077599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1762077600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1772967599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1772967600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1793527199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1793527200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1805021999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1805022000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1825581599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1825581600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1836471599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1836471600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1857031199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1857031200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1867921199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1867921200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1888480799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1888480800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1899370799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1899370800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1919930399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1919930400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1930820399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1930820400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1951379999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1951380000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1962874799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1962874800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1983434399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1983434400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1994324399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1994324400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2014883999000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2014884000000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2025773999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2025774000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2046333599000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2046333600000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2057223599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2057223600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2077783199000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2077783200000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2088673199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2088673200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2109232799000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2109232800000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2120122799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2120122800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 2140682399000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2140682400000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "AKST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 480, tzAbbr: "AKDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_America-Yellowknife.json b/dojox/date/tests/tztests/tz_America-Yellowknife.json
new file mode 100644
index 0000000..09a668c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_America-Yellowknife.json
@@ -0,0 +1,256 @@
+({
+	name: "date.timezone.America-Yellowknife",
+	runTest: function(t){
+		var tz = "America/Yellowknife";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -1104537601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1104537600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -880210801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -880210800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -765388801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -765388800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -147891601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "MDDT"}, -147891600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "MDDT"}, -131562001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -131562000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 325673999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 325674000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 341395199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 341395200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 357123599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 357123600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 372844799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 372844800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 388573199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 388573200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 404899199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 404899200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 420022799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 420022800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 436348799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 436348800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 452077199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 452077200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 467798399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 467798400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 483526799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 483526800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 499247999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 499248000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 514976399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 514976400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 530697599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 530697600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 544611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 544611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 562147199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 562147200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 576061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 576061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 594201599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 594201600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 607510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 607510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 625651199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 625651200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 638960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 638960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 657100799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 657100800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 671014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 671014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 688550399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 688550400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 702464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 702464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 719999999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 720000000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 733913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 733914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 752054399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 752054400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 765363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 765363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 783503999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 783504000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 796813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 796813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 814953599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 814953600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 828867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 828867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 846403199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 846403200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 860317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 860317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 877852799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 877852800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 891766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 891766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 923216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 923216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 941356799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 941356800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 954665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 954666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 972806399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 972806400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 986115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 986115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1004255999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1004256000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1018169999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1018170000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1035705599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1035705600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1049619599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1049619600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1067155199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1067155200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1081069199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1081069200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1099209599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1099209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1112518799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1112518800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1130659199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1130659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1143968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1143968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1162108799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1162108800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1173603599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1173603600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1194163199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1194163200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1205053199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1205053200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1225612799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1225612800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1236502799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1236502800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1257062399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1257062400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1268557199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1268557200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1289116799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1289116800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1300006799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1300006800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1320566399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1320566400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1331456399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1331456400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1352015999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1352016000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1362905999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1362906000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1383465599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1383465600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1394355599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1394355600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1414915199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1414915200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1425805199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1425805200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1446364799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1446364800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1457859599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1457859600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1478419199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1478419200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1489309199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1489309200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1509868799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1509868800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1520758799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1520758800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1541318399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1541318400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1552208399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1552208400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1572767999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1572768000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1583657999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1583658000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1604217599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1604217600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1615712399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1615712400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1636271999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1636272000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1647161999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1647162000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1667721599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1667721600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1678611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1678611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1699171199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1699171200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1710061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1710061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1730620799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1730620800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1741510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1741510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1762070399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1762070400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1772960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1772960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1793519999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1793520000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1805014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1805014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1825574399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1825574400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1836464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1836464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1857023999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1857024000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1867913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1867914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1888473599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1888473600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1899363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1899363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1919923199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1919923200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1930813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1930813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1951372799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1951372800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1962867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1962867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1983427199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1983427200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1994317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1994317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2014876799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2014876800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2025766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2025766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2046326399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2046326400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2057216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2057216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2077775999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2077776000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2088665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2088666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2109225599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2109225600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2120115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2120115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2140675199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2140675200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Antarctica-Casey.json b/dojox/date/tests/tztests/tz_Antarctica-Casey.json
new file mode 100644
index 0000000..d066c73
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Antarctica-Casey.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Antarctica-Casey",
+	runTest: function(t){
+		var tz = "Antarctica/Casey";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -31536001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, -31536000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Antarctica-Davis.json b/dojox/date/tests/tztests/tz_Antarctica-Davis.json
new file mode 100644
index 0000000..6ee51c1
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Antarctica-Davis.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Antarctica-Davis",
+	runTest: function(t){
+		var tz = "Antarctica/Davis";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -409190401000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DAVT"}, -409190400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DAVT"}, -163062001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -163062000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -28857601000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DAVT"}, -28857600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DAVT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DAVT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DAVT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DAVT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Antarctica-DumontDUrville.json b/dojox/date/tests/tztests/tz_Antarctica-DumontDUrville.json
new file mode 100644
index 0000000..7be9e65
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Antarctica-DumontDUrville.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Antarctica-DumontDUrville",
+	runTest: function(t){
+		var tz = "Antarctica/DumontDUrville";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -725846401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "PMT"}, -725846400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "PMT"}, -566992801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -566992800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -415497601000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "DDUT"}, -415497600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "DDUT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "DDUT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "DDUT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "DDUT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Antarctica-Mawson.json b/dojox/date/tests/tztests/tz_Antarctica-Mawson.json
new file mode 100644
index 0000000..4ce3987
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Antarctica-Mawson.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Antarctica-Mawson",
+	runTest: function(t){
+		var tz = "Antarctica/Mawson";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -501206401000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "MAWT"}, -501206400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "MAWT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "MAWT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "MAWT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -360, tzAbbr: "MAWT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Antarctica-McMurdo.json b/dojox/date/tests/tztests/tz_Antarctica-McMurdo.json
new file mode 100644
index 0000000..89ce929
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Antarctica-McMurdo.json
@@ -0,0 +1,268 @@
+({
+	name: "date.timezone.Antarctica-McMurdo",
+	runTest: function(t){
+		var tz = "Antarctica/McMurdo";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -441849601000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -441849600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 152632799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 152632800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 162309599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 162309600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 183477599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 183477600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 194968799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 194968800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 215531999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 215532000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 226418399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 226418400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 246981599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 246981600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 257867999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 257868000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 278431199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 278431200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 289317599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 289317600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 309880799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 309880800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 320767199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 320767200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 341330399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 341330400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 352216799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 352216800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 372779999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 372780000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 384271199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 384271200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 404834399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 404834400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 415720799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 415720800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 436283999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 436284000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 447170399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 447170400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 467733599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 467733600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 478619999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 478620000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 499183199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 499183200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 510069599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 510069600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 530632799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 530632800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 541519199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 541519200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 562082399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 562082400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 573573599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 573573600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 594136799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 594136800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 605023199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 605023200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 623771999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 623772000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 637682399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 637682400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 655221599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 655221600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 669131999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 669132000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 686671199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 686671200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 700581599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 700581600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 718120799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 718120800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 732635999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 732636000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 749570399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 749570400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 764085599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 764085600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 781019999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 781020000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 795535199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 795535200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 812469599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 812469600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 826984799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 826984800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 844523999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 844524000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 858434399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 858434400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 875973599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 875973600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 889883999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 889884000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 907423199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 907423200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 921938399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 921938400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 938872799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 938872800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 953387999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 953388000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 970322399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 970322400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 984837599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 984837600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1002376799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1002376800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1016287199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1016287200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1033826399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1033826400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1047736799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1047736800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1065275999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1065276000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1079791199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1079791200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1096725599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1096725600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1111240799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1111240800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1128175199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1128175200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1142690399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1142690400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1159624799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1159624800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1174139999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1174140000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1191074399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1191074400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1207403999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1207404000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1222523999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1222524000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1238853599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1238853600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1253973599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1253973600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1270303199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1270303200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1285423199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1285423200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1301752799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1301752800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1316872799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1316872800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1333202399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1333202400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1348927199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1348927200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1365256799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1365256800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1380376799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1380376800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1396706399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1396706400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1411826399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1411826400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1428155999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1428156000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1443275999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1443276000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1459605599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1459605600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1474725599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1474725600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1491055199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1491055200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1506175199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1506175200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1522504799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1522504800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1538229599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1538229600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1554559199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1554559200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1569679199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1569679200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1586008799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1586008800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1601128799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1601128800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1617458399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1617458400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1632578399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1632578400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1648907999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1648908000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1664027999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1664028000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1680357599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1680357600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1695477599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1695477600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1712411999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1712412000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1727531999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1727532000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1743861599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1743861600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1758981599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1758981600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1775311199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1775311200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1790431199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1790431200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1806760799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1806760800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1821880799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1821880800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1838210399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1838210400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1853330399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1853330400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1869659999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1869660000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1885384799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1885384800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1901714399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1901714400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1916834399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1916834400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1933163999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1933164000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1948283999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1948284000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1964613599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1964613600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1979733599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1979733600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1996063199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1996063200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2011183199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2011183200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2027512799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2027512800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2042632799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2042632800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2058962399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2058962400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2074687199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2074687200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2091016799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2091016800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2106136799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2106136800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2122466399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2122466400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2137586399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2137586400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Antarctica-Palmer.json b/dojox/date/tests/tztests/tz_Antarctica-Palmer.json
new file mode 100644
index 0000000..08984f4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Antarctica-Palmer.json
@@ -0,0 +1,262 @@
+({
+	name: "date.timezone.Antarctica-Palmer",
+	runTest: function(t){
+		var tz = "Antarctica/Palmer";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -157766401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -157766400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -152658001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -152658000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -132955201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -132955200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -121122001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -121122000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -101419201000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -101419200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -86821201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -86821200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -71092801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -71092800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -54766801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -54766800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -39038401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -39038400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ARST"}, -23317201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -23317200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "ART"}, -7588801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, -7588800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 128141999000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 128142000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "ARST"}, 136605599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 136605600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ART"}, 389069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 389070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 403070399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 403070400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 416372399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 416372400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 434519999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 434520000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 447821999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 447822000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 466574399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 466574400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 479271599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 479271600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 498023999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 498024000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 510721199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 510721200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 529473599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 529473600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 545194799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 545194800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 560923199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 560923200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 574225199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 574225200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 591767999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 591768000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 605674799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 605674800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 624427199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 624427200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 637729199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 637729200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 653457599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 653457600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 668573999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 668574000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 687326399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 687326400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 700628399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 700628400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 718775999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 718776000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 732077999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 732078000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 750225599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 750225600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 763527599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 763527600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 781675199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 781675200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 794977199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 794977200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 813729599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 813729600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 826426799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 826426800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 845179199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 845179200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 859690799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 859690800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 876628799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 876628800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 889930799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 889930800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 906868799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 906868800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 923194799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 923194800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 939527999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 939528000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 952829999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 952830000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 971582399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 971582400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 984279599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 984279600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1003031999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1003032000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1015729199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1015729200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1034481599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1034481600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1047178799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1047178800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1065931199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1065931200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1079233199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1079233200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1097380799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1097380800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1110682799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1110682800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1128830399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1128830400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1142132399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1142132400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1160884799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1160884800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1173581999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1173582000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1192334399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1192334400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1205031599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1205031600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1223783999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1223784000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1237085999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1237086000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1255233599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1255233600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1268535599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1268535600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1286683199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1286683200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1299985199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1299985200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1318132799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1318132800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1331434799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1331434800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1350187199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1350187200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1362884399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1362884400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1381636799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1381636800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1394333999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1394334000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1413086399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1413086400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1426388399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1426388400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1444535999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1444536000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1457837999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1457838000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1475985599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1475985600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1489287599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1489287600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1508039999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1508040000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1520737199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1520737200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1539489599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1539489600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1552186799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1552186800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1570939199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1570939200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1584241199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1584241200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1602388799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1602388800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1615690799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1615690800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1633838399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1633838400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1647140399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1647140400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1665287999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1665288000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1678589999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1678590000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1697342399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1697342400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1710039599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1710039600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1728791999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1728792000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1741489199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1741489200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1760241599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1760241600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1773543599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1773543600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1791691199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1791691200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1804993199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1804993200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1823140799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1823140800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1836442799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1836442800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1855195199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1855195200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1867892399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1867892400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1886644799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1886644800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1899341999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1899342000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1918094399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1918094400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1930791599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1930791600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1949543999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1949544000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1962845999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1962846000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1980993599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1980993600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1994295599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1994295600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2012443199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2012443200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2025745199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2025745200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2044497599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2044497600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2057194799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2057194800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2075947199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2075947200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2088644399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2088644400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2107396799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2107396800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2120698799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2120698800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 2138846399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2138846400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "CLST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "CLT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Antarctica-Rothera.json b/dojox/date/tests/tztests/tz_Antarctica-Rothera.json
new file mode 100644
index 0000000..0ecee9a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Antarctica-Rothera.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Antarctica-Rothera",
+	runTest: function(t){
+		var tz = "Antarctica/Rothera";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, 218246399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ROTT"}, 218246400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ROTT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ROTT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ROTT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ROTT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Antarctica-Syowa.json b/dojox/date/tests/tztests/tz_Antarctica-Syowa.json
new file mode 100644
index 0000000..6115d57
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Antarctica-Syowa.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Antarctica-Syowa",
+	runTest: function(t){
+		var tz = "Antarctica/Syowa";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -407808001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SYOT"}, -407808000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SYOT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SYOT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SYOT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SYOT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Antarctica-Vostok.json b/dojox/date/tests/tztests/tz_Antarctica-Vostok.json
new file mode 100644
index 0000000..bf94dfc
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Antarctica-Vostok.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Antarctica-Vostok",
+	runTest: function(t){
+		var tz = "Antarctica/Vostok";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -380073601000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "VOST"}, -380073600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "VOST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "VOST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "VOST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -360, tzAbbr: "VOST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Aden.json b/dojox/date/tests/tztests/tz_Asia-Aden.json
new file mode 100644
index 0000000..c13bb89
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Aden.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Asia-Aden",
+	runTest: function(t){
+		var tz = "Asia/Aden";
+		doh.checkDate({tzOffset: -180.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -180.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -180.8, tzAbbr: "LMT"}, -631162849000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, -631162848000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Almaty.json b/dojox/date/tests/tztests/tz_Asia-Almaty.json
new file mode 100644
index 0000000..4c023d4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Almaty.json
@@ -0,0 +1,108 @@
+({
+	name: "date.timezone.Asia-Almaty",
+	runTest: function(t){
+		var tz = "Asia/Almaty";
+		doh.checkDate({tzOffset: -307.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -307.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -307.8, tzAbbr: "LMT"}, -1441170469000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ALMT"}, -1441170468000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ALMT"}, -1247547601000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, -1247547600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 354909599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 354909600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 370717199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 370717200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 386445599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 386445600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 402253199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 402253200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 417981599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 417981600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 433789199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 433789200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 449603999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 449604000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 465335999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 465336000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 481060799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 481060800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 496785599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 496785600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 512510399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 512510400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 528235199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 528235200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 543959999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 543960000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 559684799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 559684800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 575409599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 575409600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 591134399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 591134400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 606859199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 606859200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 622583999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 622584000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 638308799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 638308800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 654638399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 654638400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 701801999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 701802000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 717523199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 717523200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 733262399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 733262400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 748987199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 748987200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 764711999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 764712000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 780436799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 780436800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 796161599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 796161600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 811886399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 811886400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 828215999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 828216000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 846359999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 846360000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 859665599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 859665600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 877809599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 877809600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 891115199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 891115200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 909259199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 909259200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 922564799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 922564800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 941313599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 941313600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 954014399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 954014400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 972763199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 972763200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 985463999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 985464000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 1004212799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 1004212800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 1017518399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 1017518400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 1035662399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 1035662400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 1048967999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 1048968000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 1067111999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 1067112000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 1080417599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 1080417600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ALMST"}, 1099166399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 1099166400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ALMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Amman.json b/dojox/date/tests/tztests/tz_Asia-Amman.json
new file mode 100644
index 0000000..0d7dd4b
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Amman.json
@@ -0,0 +1,250 @@
+({
+	name: "date.timezone.Asia-Amman",
+	runTest: function(t){
+		var tz = "Asia/Amman";
+		doh.checkDate({tzOffset: -143.733333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -143.733333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -143.733333333333, tzAbbr: "LMT"}, -1230776625000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1230776624000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 108165599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 108165600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 118270799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 118270800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 136591199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 136591200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 149806799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 149806800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 168127199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 168127200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 181342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 181342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 199749599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 199749600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 215643599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 215643600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 231285599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 231285600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 244501199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 244501200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 262735199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 262735200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 275950799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 275950800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 481154399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 481154400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 496961999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 496962000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 512949599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 512949600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 528670799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 528670800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 544399199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 544399200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 560120399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 560120400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 575848799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 575848800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 592174799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 592174800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 610581599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 610581600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 623624399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 623624400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 641167199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 641167200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 655073999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 655074000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 671839199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 671839200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 685918799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 685918800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 702856799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 702856800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717973199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717973200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733701599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733701600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 749422799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 749422800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 765151199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 765151200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 779662799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 779662800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 797205599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 797205600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811115999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811116000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828655199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828655200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 843170399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 843170400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 860104799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 860104800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 874619999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 874620000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891554399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891554400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 906069599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 906069600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 930779999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 930780000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 938123999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 938124000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954367199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954367200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 970178399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 970178400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985816799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985816800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1001627999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1001628000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017352799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017352800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1033077599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1033077600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048802399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048802400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1066946399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1066946400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080251999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080252000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1097791199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1097791200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1112306399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1112306400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1128031199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1128031200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143755999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143756000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1161899999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1161900000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1175205599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1175205600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193349599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193349600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206655199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206655200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1225403999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1225404000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238104799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238104800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256853599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256853600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269554399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269554400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288303199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288303200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301608799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301608800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319752799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319752800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1333058399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1333058400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351202399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351202400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364507999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364508000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382651999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382652000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1395957599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1395957600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414706399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414706400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427407199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427407200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1446155999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1446156000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459461599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459461600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477605599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477605600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490911199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490911200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509055199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509055200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1522360799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1522360800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540504799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540504800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553810399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553810400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1571954399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1571954400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585259999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585260000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1604008799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1604008800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616709599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616709600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635458399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635458400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648763999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648764000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1666907999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1666908000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1680213599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1680213600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698357599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698357600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711663199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711663200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729807199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729807200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743112799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743112800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761861599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761861600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774562399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774562400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1793311199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1793311200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806011999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806012000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824760799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824760800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1838066399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1838066400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856210399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856210400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869515999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869516000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887659999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887660000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1900965599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1900965600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919109599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919109600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932415199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932415200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1951163999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1951164000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1963864799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1963864800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982613599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982613600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995919199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995919200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014063199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014063200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2027368799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2027368800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045512799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045512800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058818399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058818400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2076962399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2076962400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090267999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090268000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2109016799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2109016800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121717599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121717600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140466399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140466400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Anadyr.json b/dojox/date/tests/tztests/tz_Asia-Anadyr.json
new file mode 100644
index 0000000..6a6da39
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Anadyr.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.Asia-Anadyr",
+	runTest: function(t){
+		var tz = "Asia/Anadyr";
+		doh.checkDate({tzOffset: -709.933333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -709.933333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -709.933333333333, tzAbbr: "LMT"}, -1441194597000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, -1441194596000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, -1247572801000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAT"}, -1247572800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAT"}, 354884399000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "ANAST"}, 354884400000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "ANAST"}, 370691999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAT"}, 370692000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAT"}, 386420399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 386420400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 402231599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 402231600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 417959999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 417960000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 433767599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 433767600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 449582399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 449582400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 465314399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 465314400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 481039199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 481039200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 496763999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 496764000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 512488799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 512488800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 528213599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 528213600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 543938399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 543938400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 559663199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 559663200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 575387999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 575388000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 591112799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 591112800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 606837599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 606837600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 622562399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 622562400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 638287199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 638287200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 654616799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 654616800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 670341599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAST"}, 670341600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAST"}, 686069999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "ANAT"}, 686070000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "ANAT"}, 695746799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 695746800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 701780399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 701780400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 717501599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 717501600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 733240799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 733240800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 748965599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 748965600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 764690399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 764690400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 780415199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 780415200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 796139999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 796140000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 811864799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 811864800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 828194399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 828194400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 846338399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 846338400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 859643999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 859644000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 877787999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 877788000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 891093599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 891093600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 909237599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 909237600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 922543199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 922543200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 941291999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 941292000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 953992799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 953992800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 972741599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 972741600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 985442399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 985442400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1004191199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1004191200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1017496799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1017496800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1035640799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1035640800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1048946399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1048946400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1067090399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1067090400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1080395999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1080396000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1099144799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1099144800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1111845599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1111845600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1130594399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1130594400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1143295199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1143295200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1162043999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1162044000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1174744799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1174744800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1193493599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1193493600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1206799199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1206799200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1224943199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1224943200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1238248799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1238248800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1256392799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1256392800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1269698399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1269698400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1288447199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1288447200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1301147999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1301148000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1319896799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1319896800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1332597599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1332597600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1351346399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1351346400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1364651999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1364652000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1382795999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1382796000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1396101599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1396101600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1414245599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1414245600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1427551199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1427551200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1445695199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1445695200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1459000799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1459000800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1477749599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1477749600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1490450399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1490450400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1509199199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1509199200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1521899999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1521900000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1540648799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1540648800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1553954399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1553954400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1572098399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1572098400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1585403999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1585404000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1603547999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1603548000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1616853599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1616853600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1635602399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1635602400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1648303199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1648303200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1667051999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1667052000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1679752799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1679752800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1698501599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1698501600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1711807199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1711807200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1729951199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1729951200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1743256799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1743256800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1761400799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1761400800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1774706399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1774706400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1792850399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1792850400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1806155999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1806156000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1824904799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1824904800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1837605599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1837605600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1856354399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1856354400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1869055199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1869055200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1887803999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1887804000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1901109599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1901109600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1919253599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1919253600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1932559199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1932559200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1950703199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1950703200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1964008799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1964008800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1982757599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1982757600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1995458399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1995458400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 2014207199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 2014207200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 2026907999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 2026908000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 2045656799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 2045656800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 2058357599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 2058357600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 2077106399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 2077106400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 2090411999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 2090412000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 2108555999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 2108556000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 2121861599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 2121861600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 2140005599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 2140005600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "ANAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -780, tzAbbr: "ANAST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Aqtau.json b/dojox/date/tests/tztests/tz_Asia-Aqtau.json
new file mode 100644
index 0000000..7ab8ed6
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Aqtau.json
@@ -0,0 +1,112 @@
+({
+	name: "date.timezone.Asia-Aqtau",
+	runTest: function(t){
+		var tz = "Asia/Aqtau";
+		doh.checkDate({tzOffset: -201.066666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -201.066666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -201.066666666667, tzAbbr: "LMT"}, -1441164065000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "FORT"}, -1441164064000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "FORT"}, -1247544001000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "FORT"}, -1247544000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "FORT"}, -220942801000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, -220942800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 370724399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHET"}, 370724400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHET"}, 386445599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 386445600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 402256799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 402256800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 417985199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 417985200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 433792799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 433792800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 449607599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 449607600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 465339599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 465339600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 481064399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 481064400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 496789199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 496789200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 512513999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 512514000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 528238799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 528238800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 543963599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 543963600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 559688399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 559688400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 575413199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 575413200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 591137999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 591138000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 606862799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 606862800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 622587599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 622587600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 638312399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 638312400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SHEST"}, 654641999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 654642000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SHET"}, 692823599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 692823600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 701805599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 701805600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 717526799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 717526800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 733265999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 733266000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 748990799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 748990800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 764715599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 764715600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 780440399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 780440400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 796165199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 796165200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 811893599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 811893600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 828223199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 828223200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 846367199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 846367200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 859672799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 859672800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 877816799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 877816800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 891122399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 891122400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 909266399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 909266400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 922571999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 922572000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 941320799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 941320800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 954021599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 954021600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 972770399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 972770400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 985471199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 985471200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 1004219999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 1004220000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 1017525599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 1017525600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 1035669599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 1035669600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 1048975199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 1048975200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 1067119199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 1067119200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 1080424799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 1080424800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTST"}, 1099173599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 1099173600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AQTT"}, 1110830399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1110830400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Aqtobe.json b/dojox/date/tests/tztests/tz_Asia-Aqtobe.json
new file mode 100644
index 0000000..e175991
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Aqtobe.json
@@ -0,0 +1,110 @@
+({
+	name: "date.timezone.Asia-Aqtobe",
+	runTest: function(t){
+		var tz = "Asia/Aqtobe";
+		doh.checkDate({tzOffset: -228.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -228.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -228.666666666667, tzAbbr: "LMT"}, -1441165721000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AKTT"}, -1441165720000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AKTT"}, -1247544001000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, -1247544000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 354913199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 354913200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 370720799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTT"}, 370720800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTT"}, 386445599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 386445600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 402256799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 402256800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 417985199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 417985200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 433792799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 433792800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 449607599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 449607600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 465339599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 465339600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 481064399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 481064400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 496789199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 496789200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 512513999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 512514000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 528238799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 528238800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 543963599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 543963600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 559688399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 559688400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 575413199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 575413200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 591137999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 591138000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 606862799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 606862800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 622587599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 622587600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 638312399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 638312400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AKTST"}, 654641999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 654642000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AKTT"}, 692823599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 692823600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 701805599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 701805600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 717526799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 717526800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 733265999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 733266000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 748990799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 748990800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 764715599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 764715600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 780440399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 780440400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 796165199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 796165200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 811889999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 811890000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 828219599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 828219600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 846363599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 846363600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 859669199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 859669200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 877813199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 877813200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 891118799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 891118800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 909262799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 909262800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 922568399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 922568400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 941317199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 941317200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 954017999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 954018000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 972766799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 972766800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 985467599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 985467600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 1004216399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1004216400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1017521999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 1017522000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 1035665999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1035666000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1048971599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 1048971600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 1067115599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1067115600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1080421199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 1080421200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "AQTST"}, 1099169999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1099170000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AQTT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Ashgabat.json b/dojox/date/tests/tztests/tz_Asia-Ashgabat.json
new file mode 100644
index 0000000..f7a340e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Ashgabat.json
@@ -0,0 +1,64 @@
+({
+	name: "date.timezone.Asia-Ashgabat",
+	runTest: function(t){
+		var tz = "Asia/Ashgabat";
+		doh.checkDate({tzOffset: -233.533333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -233.533333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -233.533333333333, tzAbbr: "LMT"}, -1441166013000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ASHT"}, -1441166012000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ASHT"}, -1247544001000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, -1247544000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 354913199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 354913200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 370720799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 370720800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 386449199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 386449200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 402256799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 402256800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 417985199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 417985200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 433792799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 433792800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 449607599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 449607600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 465339599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 465339600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 481064399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 481064400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 496789199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 496789200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 512513999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 512514000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 528238799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 528238800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 543963599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 543963600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 559688399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 559688400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 575413199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 575413200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 591137999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 591138000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 606862799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 606862800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 622587599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 622587600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 638312399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 638312400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "ASHST"}, 654641999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 654642000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHT"}, 670366799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHST"}, 670366800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ASHST"}, 686095199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ASHT"}, 686095200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ASHT"}, 688507199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TMT"}, 688507200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TMT"}, 695771999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TMT"}, 695772000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Baghdad.json b/dojox/date/tests/tztests/tz_Asia-Baghdad.json
new file mode 100644
index 0000000..71864e9
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Baghdad.json
@@ -0,0 +1,118 @@
+({
+	name: "date.timezone.Asia-Baghdad",
+	runTest: function(t){
+		var tz = "Asia/Baghdad";
+		doh.checkDate({tzOffset: -177.6, tzAbbr: "BMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -177.6, tzAbbr: "BMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -177.6, tzAbbr: "BMT"}, -1641005857000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, -1641005856000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 389048399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 389048400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 417905999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 417906000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 465422399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 465422400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 481150799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 481150800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 496792799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 496792800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 512517599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 512517600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 528242399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 528242400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 543967199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 543967200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 559691999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 559692000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 575416799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 575416800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 591141599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 591141600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 606866399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 606866400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 622591199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 622591200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 638315999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 638316000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 654645599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 654645600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 670463999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 670464000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 686275199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 686275200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 702086399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 702086400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 717897599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 717897600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 733622399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 733622400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 749433599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 749433600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 765158399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 765158400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 780969599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 780969600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 796694399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 796694400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 812505599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 812505600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 828316799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 828316800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 844127999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 844128000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 859852799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 859852800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 875663999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 875664000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 891388799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 891388800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 907199999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 907200000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 922924799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 922924800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 938735999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 938736000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 954547199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 954547200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 970358399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 970358400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 986083199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 986083200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1001894399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1001894400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1017619199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1017619200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1033430399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1033430400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1049155199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1049155200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1064966399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1064966400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1080777599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1080777600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1096588799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1096588800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1112313599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1112313600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1128124799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1128124800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1143849599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1143849600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1159660799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1159660800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1175385599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1175385600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ADT"}, 1191196799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1191196800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Bahrain.json b/dojox/date/tests/tztests/tz_Asia-Bahrain.json
new file mode 100644
index 0000000..2dc92e2
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Bahrain.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Asia-Bahrain",
+	runTest: function(t){
+		var tz = "Asia/Bahrain";
+		doh.checkDate({tzOffset: -202.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -202.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -202.333333333333, tzAbbr: "LMT"}, -1577935341000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, -1577935340000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, 76190399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 76190400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Baku.json b/dojox/date/tests/tztests/tz_Asia-Baku.json
new file mode 100644
index 0000000..edb1679
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Baku.json
@@ -0,0 +1,234 @@
+({
+	name: "date.timezone.Asia-Baku",
+	runTest: function(t){
+		var tz = "Asia/Baku";
+		doh.checkDate({tzOffset: -199.4, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -199.4, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -199.4, tzAbbr: "LMT"}, -1441163965000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "BAKT"}, -1441163964000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "BAKT"}, -405140401000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, -405140400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 354916799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 354916800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 370724399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 370724400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 386452799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 386452800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 402260399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 402260400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 417988799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 417988800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 433796399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 433796400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 449611199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 449611200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 465343199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 465343200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 481067999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 481068000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 496792799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 496792800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 512517599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 512517600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 528242399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 528242400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 543967199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 543967200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 559691999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 559692000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 575416799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 575416800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 591141599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 591141600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 606866399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 606866400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 622591199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 622591200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 638315999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 638316000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "BAKST"}, 654645599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 654645600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKT"}, 670370399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKST"}, 670370400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "BAKST"}, 683495999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZST"}, 683496000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZST"}, 686098799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AZT"}, 686098800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AZT"}, 701812799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZST"}, 701812800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZST"}, 717533999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 717534000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 859679999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 859680000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 877823999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 877824000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 891129599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 891129600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 909273599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 909273600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 922579199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 922579200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 941327999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 941328000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 954028799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 954028800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 972777599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 972777600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 985478399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 985478400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1004227199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1004227200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1017532799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1017532800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1035676799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1035676800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1048982399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1048982400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1067126399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1067126400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1080431999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1080432000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1099180799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1099180800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1111881599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1111881600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1130630399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1130630400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1143331199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1143331200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1162079999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1162080000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1174780799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1174780800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1193529599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1193529600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1206835199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1206835200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1224979199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1224979200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1238284799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1238284800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1256428799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1256428800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1269734399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1269734400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1288483199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1288483200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1301183999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1301184000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1319932799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1319932800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1332633599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1332633600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1351382399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1351382400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1364687999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1364688000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1382831999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1382832000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1396137599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1396137600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1414281599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1414281600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1427587199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1427587200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1445731199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1445731200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1459036799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1459036800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1477785599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1477785600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1490486399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1490486400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1509235199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1509235200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1521935999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1521936000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1540684799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1540684800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1553990399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1553990400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1572134399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1572134400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1585439999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1585440000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1603583999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1603584000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1616889599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1616889600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1635638399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1635638400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1648339199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1648339200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1667087999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1667088000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1679788799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1679788800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1698537599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1698537600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1711843199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1711843200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1729987199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1729987200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1743292799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1743292800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1761436799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1761436800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1774742399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1774742400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1792886399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1792886400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1806191999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1806192000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1824940799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1824940800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1837641599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1837641600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1856390399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1856390400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1869091199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1869091200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1887839999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1887840000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1901145599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1901145600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1919289599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1919289600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1932595199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1932595200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1950739199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1950739200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1964044799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1964044800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1982793599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1982793600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1995494399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1995494400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 2014243199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 2014243200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 2026943999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 2026944000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 2045692799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 2045692800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 2058393599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 2058393600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 2077142399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 2077142400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 2090447999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 2090448000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 2108591999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 2108592000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 2121897599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 2121897600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 2140041599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 2140041600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AZT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AZST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Bangkok.json b/dojox/date/tests/tztests/tz_Asia-Bangkok.json
new file mode 100644
index 0000000..6130271
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Bangkok.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Asia-Bangkok",
+	runTest: function(t){
+		var tz = "Asia/Bangkok";
+		doh.checkDate({tzOffset: -402.066666666667, tzAbbr: "BMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -402.066666666667, tzAbbr: "BMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -402.066666666667, tzAbbr: "BMT"}, -1570084925000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, -1570084924000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Beirut.json b/dojox/date/tests/tztests/tz_Asia-Beirut.json
new file mode 100644
index 0000000..7b98a6e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Beirut.json
@@ -0,0 +1,292 @@
+({
+	name: "date.timezone.Asia-Beirut",
+	runTest: function(t){
+		var tz = "Asia/Beirut";
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1570413601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1570413600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1552186801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1552186800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1538359201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1538359200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1522551601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1522551600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1507514401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1507514400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1490583601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1490583600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1473645601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1473645600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1460948401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1460948400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -399866401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -399866400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -386650801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -386650800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -368330401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -368330400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -355114801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -355114800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -336794401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -336794400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -323578801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -323578800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -305172001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -305172000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -291956401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -291956400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -273636001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -273636000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -260420401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -260420400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 78011999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 78012000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 86734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 86734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 105055199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 105055200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 118270799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 118270800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 136591199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 136591200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 149806799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 149806800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 168127199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 168127200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 181342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 181342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 199749599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 199749600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 212965199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 212965200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 231285599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 231285600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 244501199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 244501200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 262735199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 262735200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 275950799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 275950800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 452210399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 452210400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 466721999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 466722000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 483746399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 483746400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 498257999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 498258000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 515282399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 515282400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 529793999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 529794000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 546818399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 546818400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 561329999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 561330000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 581119199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 581119200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 592952399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 592952400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 610754399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 610754400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 624488399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 624488400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 641512799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 641512800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 656024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 656024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 673048799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 673048800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 687560399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 687560400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 704671199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 704671200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 718145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 718146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733269599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733269600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 748990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 748990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764719199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764719200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796168799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796168800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828223199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828223200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 843944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 843944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859672799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859672800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 875393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 875394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891122399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891122400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 906843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 906843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922571999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922572000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941317199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941317200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954021599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954021600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972766799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972766800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985471199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985471200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004216399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004216400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017525599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017525600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035665999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035666000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048975199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048975200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067115599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067115600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080424799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080424800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099169999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099170000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111874399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111874400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130619599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130619600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143323999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143324000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162069199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162069200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174773599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174773600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193518799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193518800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206827999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206828000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224968399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224968400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238277599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238277600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256417999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256418000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269727199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269727200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288472399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288472400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301176799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301176800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319921999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319922000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332626399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332626400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351371599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351371600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364680799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364680800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382821199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382821200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396130399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396130400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414270799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414270800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427579999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427580000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445720399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445720400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459029599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459029600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477774799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477774800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490479199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490479200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509224399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509224400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521928799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521928800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540673999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540674000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553983199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553983200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572123599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572123600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585432799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585432800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603573199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603573200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616882399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616882400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635627599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635627600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648331999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648332000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667077199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667077200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679781599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679781600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698526799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698526800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711835999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711836000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729976399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729976400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743285599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743285600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761425999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761426000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774735199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774735200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792875599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792875600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806184799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806184800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824929999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824930000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837634399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837634400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856379599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856379600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869083999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869084000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887829199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887829200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901138399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901138400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919278799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919278800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932587999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932588000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950728399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950728400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964037599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964037600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982782799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982782800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995487199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995487200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014232399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014232400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026936799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026936800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045681999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045682000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058386399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058386400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077131599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077131600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090440799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090440800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108581199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108581200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121890399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121890400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140030799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140030800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Bishkek.json b/dojox/date/tests/tztests/tz_Asia-Bishkek.json
new file mode 100644
index 0000000..4f3ff1d
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Bishkek.json
@@ -0,0 +1,116 @@
+({
+	name: "date.timezone.Asia-Bishkek",
+	runTest: function(t){
+		var tz = "Asia/Bishkek";
+		doh.checkDate({tzOffset: -298.4, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -298.4, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -298.4, tzAbbr: "LMT"}, -1441169905000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "FRUT"}, -1441169904000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "FRUT"}, -1247547601000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, -1247547600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 354909599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 354909600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 370717199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 370717200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 386445599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 386445600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 402253199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 402253200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 417981599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 417981600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 433789199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 433789200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 449603999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 449604000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 465335999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 465336000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 481060799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 481060800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 496785599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 496785600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 512510399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 512510400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 528235199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 528235200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 543959999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 543960000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 559684799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 559684800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 575409599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 575409600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 591134399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 591134400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 606859199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 606859200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 622583999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 622584000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 638308799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 638308800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "FRUST"}, 654638399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 654638400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUT"}, 670363199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUST"}, 670363200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "FRUST"}, 683582399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 683582400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 703018799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 703018800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 717530399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 717530400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 734468399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 734468400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 748979999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 748980000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 765917999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 765918000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 780429599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 780429600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 797367599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 797367600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 811879199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 811879200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 828817199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 828817200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 843933599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 843933600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 859670999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 859671000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 877811399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 877811400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 891120599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 891120600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 909260999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 909261000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 922570199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 922570200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 941315399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 941315400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 954019799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 954019800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 972764999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 972765000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 985469399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 985469400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 1004214599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 1004214600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 1017523799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 1017523800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 1035664199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 1035664200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 1048973399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 1048973400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 1067113799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 1067113800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 1080422999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 1080423000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 1099168199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 1099168200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KGT"}, 1111872599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 1111872600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGST"}, 1123783199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGT"}, 1123783200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KGT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Brunei.json b/dojox/date/tests/tztests/tz_Asia-Brunei.json
new file mode 100644
index 0000000..6b7b558
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Brunei.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Asia-Brunei",
+	runTest: function(t){
+		var tz = "Asia/Brunei";
+		doh.checkDate({tzOffset: -459.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -459.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -459.666666666667, tzAbbr: "LMT"}, -1383464381000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "BNT"}, -1383464380000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "BNT"}, -1167636601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BNT"}, -1167636600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BNT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BNT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BNT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BNT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Choibalsan.json b/dojox/date/tests/tztests/tz_Asia-Choibalsan.json
new file mode 100644
index 0000000..da2f24d
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Choibalsan.json
@@ -0,0 +1,106 @@
+({
+	name: "date.timezone.Asia-Choibalsan",
+	runTest: function(t){
+		var tz = "Asia/Choibalsan";
+		doh.checkDate({tzOffset: -458, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -458, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -458, tzAbbr: "LMT"}, -2032933081000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ULAT"}, -2032933080000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ULAT"}, 252435599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 252435600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 417974399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 417974400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 433778399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 433778400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 449593199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 449593200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 465314399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 465314400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 481042799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 481042800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 496763999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 496764000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 512492399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 512492400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 528213599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 528213600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 543941999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 543942000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 559663199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 559663200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 575391599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 575391600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 591112799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 591112800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 606841199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 606841200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 622562399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 622562400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 638290799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 638290800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 654616799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 654616800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 670345199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 670345200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 686066399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 686066400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 701794799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 701794800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 717515999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 717516000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 733244399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 733244400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 748965599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 748965600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 764693999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 764694000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 780415199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 780415200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 796143599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 796143600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 811864799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 811864800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 828197999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 828198000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 843919199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 843919200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 859647599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 859647600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 875368799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 875368800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 891097199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 891097200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 906818399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 906818400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 988390799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 988390800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 1001692799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1001692800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1017421199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 1017421200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 1033142399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1033142400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1048870799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 1048870800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 1064591999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1064592000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1080320399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 1080320400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 1096041599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1096041600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1111769999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 1111770000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 1127491199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1127491200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1143219599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 1143219600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "CHOST"}, 1159545599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1159545600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHOT"}, 1206889199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CHOT"}, 1206889200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CHOT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CHOT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CHOT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CHOT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Chongqing.json b/dojox/date/tests/tztests/tz_Asia-Chongqing.json
new file mode 100644
index 0000000..bb51ded
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Chongqing.json
@@ -0,0 +1,40 @@
+({
+	name: "date.timezone.Asia-Chongqing",
+	runTest: function(t){
+		var tz = "Asia/Chongqing";
+		doh.checkDate({tzOffset: -426.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -426.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -426.333333333333, tzAbbr: "LMT"}, -1325487981000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "LONT"}, -1325487980000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "LONT"}, 325961999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 325962000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 515519999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 515520000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 527007599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 527007600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 545155199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 545155200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 558457199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 558457200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 576604799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 576604800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 589906799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 589906800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 608659199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 608659200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 621961199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 621961200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 640108799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 640108800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 653410799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 653410800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 671558399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 671558400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 684860399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 684860400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Colombo.json b/dojox/date/tests/tztests/tz_Asia-Colombo.json
new file mode 100644
index 0000000..661a9d5
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Colombo.json
@@ -0,0 +1,26 @@
+({
+	name: "date.timezone.Asia-Colombo",
+	runTest: function(t){
+		var tz = "Asia/Colombo";
+		doh.checkDate({tzOffset: -319.533333333333, tzAbbr: "MMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -319.533333333333, tzAbbr: "MMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -319.533333333333, tzAbbr: "MMT"}, -2019705573000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -2019705572000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -883287001000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "IHST"}, -883287000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "IHST"}, -862639201000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "IST"}, -862639200000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "IST"}, -764051401000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -764051400000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 832962599000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "LKT"}, 832962600000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "LKT"}, 846266399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "LKT"}, 846266400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "LKT"}, 1145039399000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 1145039400000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Damascus.json b/dojox/date/tests/tztests/tz_Asia-Damascus.json
new file mode 100644
index 0000000..0b0f1f9
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Damascus.json
@@ -0,0 +1,314 @@
+({
+	name: "date.timezone.Asia-Damascus",
+	runTest: function(t){
+		var tz = "Asia/Damascus";
+		doh.checkDate({tzOffset: -145.2, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -145.2, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -145.2, tzAbbr: "LMT"}, -1577931913000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1577931912000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1568592001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1568592000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1554080401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1554080400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1537142401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1537142400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1522630801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1522630800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1505692801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1505692800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1491181201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1491181200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1474243201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1474243200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1459126801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1459126800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -242265601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -242265600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -228877201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -228877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -210556801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -210556800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -197427601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -197427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -178934401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -178934400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -165718801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -165718800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -147398401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -147398400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -134269201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -134269200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -116467201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -116467200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -102646801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -102646800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -84326401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -84326400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -71110801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -71110800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -52704001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -52704000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -39488401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -39488400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -21168001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -21168000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -7952401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -7952400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 10367999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 10368000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 23583599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 23583600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 41903999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 41904000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 55119599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 55119600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 73526399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 73526400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 86741999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 86742000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 105062399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 105062400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 118277999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 118278000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 136598399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 136598400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 149813999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 149814000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 168134399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 168134400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 181349999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 181350000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 199756799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 199756800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 212972399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 212972400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 231292799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 231292800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 241916399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 241916400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 262828799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 262828800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 273452399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 273452400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 418694399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 418694400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 433810799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 433810800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 450316799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 450316800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 465433199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 465433200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 508895999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 508896000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 529196399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 529196400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 541555199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 541555200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 562633199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 562633200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 574387199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 574387200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 594255599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 594255600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 607305599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 607305600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 623199599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 623199600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 638927999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 638928000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 654649199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 654649200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670456799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670456800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686264399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686264400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 702683999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 702684000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717886799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717886800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733096799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733096800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 748904399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 748904400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 765151199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 765151200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780958799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780958800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796687199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796687200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 812494799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 812494800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828309599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828309600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 844117199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 844117200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859759199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859759200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 875653199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 875653200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891208799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891208800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 907189199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 907189200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922917599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922917600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 938725199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 938725200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954539999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954540000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 970347599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 970347600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 986075999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 986076000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1001883599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1001883600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017611999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017612000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1033419599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1033419600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1049147999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1049148000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1064955599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1064955600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080770399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080770400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1096577999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1096578000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1112306399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1112306400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1128113999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1128114000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143842399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143842400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1158872399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1158872400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1175205599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1175205600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193950799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193950800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1207259999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1207260000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1225486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1225486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238104799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238104800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1257022799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1257022800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269554399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269554400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288558799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288558800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301003999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301004000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1320094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1320094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1333058399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1333058400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351717199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351717200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364507999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364508000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1383253199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1383253200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1395957599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1395957600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427407199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427407200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1446325199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1446325200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1458856799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1458856800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490911199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490911200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509483599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509483600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1522360799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1522360800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1541019599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1541019600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553810399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553810400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572555599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572555600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585259999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585260000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1604177999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1604178000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616709599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616709600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635713999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635714000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648159199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648159200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667249999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667250000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1680213599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1680213600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698785999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698786000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711663199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711663200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1730408399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1730408400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743112799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743112800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774562399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774562400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1793480399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1793480400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806011999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806012000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1825016399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1825016400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1838066399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1838066400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856638799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856638800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869515999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869516000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1888174799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1888174800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1900965599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1900965600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919710799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919710800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932415199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932415200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1951246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1951246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1963864799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1963864800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982869199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982869200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995314399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995314400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014405199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014405200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2027368799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2027368800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045941199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045941200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058818399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058818400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077477199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077477200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090267999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090268000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2109099599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2109099600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121717599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121717600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140635599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140635600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Dhaka.json b/dojox/date/tests/tztests/tz_Asia-Dhaka.json
new file mode 100644
index 0000000..888dccc
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Dhaka.json
@@ -0,0 +1,24 @@
+({
+	name: "date.timezone.Asia-Dhaka",
+	runTest: function(t){
+		var tz = "Asia/Dhaka";
+		doh.checkDate({tzOffset: -353.333333333333, tzAbbr: "HMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -353.333333333333, tzAbbr: "HMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -353.333333333333, tzAbbr: "HMT"}, -891582801000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "BURT"}, -891582800000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "BURT"}, -872058601000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -872058600000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -862637401000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "BURT"}, -862637400000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "BURT"}, -576138601000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DACT"}, -576138600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DACT"}, 38771999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "BDT"}, 38772000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "BDT"}, 1245430799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "BDST"}, 1245430800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "BDST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "BDST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "BDT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "BDST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Dili.json b/dojox/date/tests/tztests/tz_Asia-Dili.json
new file mode 100644
index 0000000..06f172f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Dili.json
@@ -0,0 +1,22 @@
+({
+	name: "date.timezone.Asia-Dili",
+	runTest: function(t){
+		var tz = "Asia/Dili";
+		doh.checkDate({tzOffset: -502.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -502.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -502.333333333333, tzAbbr: "LMT"}, -1830414141000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "TLT"}, -1830414140000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "TLT"}, -879152401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -879152400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -766054801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "TLT"}, -766054800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "TLT"}, 199897199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CIT"}, 199897200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CIT"}, 969119999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "TLT"}, 969120000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "TLT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "TLT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "TLT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -540, tzAbbr: "TLT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Dubai.json b/dojox/date/tests/tztests/tz_Asia-Dubai.json
new file mode 100644
index 0000000..d9bafd4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Dubai.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Asia-Dubai",
+	runTest: function(t){
+		var tz = "Asia/Dubai";
+		doh.checkDate({tzOffset: -221.2, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -221.2, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -221.2, tzAbbr: "LMT"}, -1577936473000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, -1577936472000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Dushanbe.json b/dojox/date/tests/tztests/tz_Asia-Dushanbe.json
new file mode 100644
index 0000000..ca39c25
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Dushanbe.json
@@ -0,0 +1,60 @@
+({
+	name: "date.timezone.Asia-Dushanbe",
+	runTest: function(t){
+		var tz = "Asia/Dushanbe";
+		doh.checkDate({tzOffset: -275.2, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -275.2, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -275.2, tzAbbr: "LMT"}, -1441168513000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "DUST"}, -1441168512000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "DUST"}, -1247547601000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, -1247547600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 354909599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 354909600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 370717199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 370717200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 386445599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 386445600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 402253199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 402253200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 417981599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 417981600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 433789199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 433789200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 449603999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 449604000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 465335999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 465336000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 481060799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 481060800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 496785599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 496785600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 512510399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 512510400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 528235199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 528235200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 543959999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 543960000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 559684799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 559684800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 575409599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 575409600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 591134399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 591134400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 606859199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 606859200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 622583999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 622584000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 638308799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 638308800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "DUSST"}, 654638399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 654638400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUST"}, 670363199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUSST"}, 670363200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "DUSST"}, 684363599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TJT"}, 684363600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TJT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TJT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TJT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TJT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Gaza.json b/dojox/date/tests/tztests/tz_Asia-Gaza.json
new file mode 100644
index 0000000..592cada
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Gaza.json
@@ -0,0 +1,298 @@
+({
+	name: "date.timezone.Asia-Gaza",
+	runTest: function(t){
+		var tz = "Asia/Gaza";
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -933645601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EET"}, -933645600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EET"}, -857358001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -857358000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -844300801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EET"}, -844300800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EET"}, -825822001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -825822000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -812685601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EET"}, -812685600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EET"}, -794199601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -794199600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -779853601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EET"}, -779853600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EET"}, -762656401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -762656400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -748310401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EET"}, -748310400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EET"}, -731127601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -731127600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -399088801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -399088800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -386650801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -386650800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -368330401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -368330400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -355114801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -355114800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -336790801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -336790800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -323654401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -323654400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -305168401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -305168400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -292032001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -292032000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -273632401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -273632400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -260496001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -260496000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -242096401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -242096400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -228960001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -228960000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -210560401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -210560400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -197424001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -197424000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -178938001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -178938000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -165801601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -165801600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -147402001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -147402000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -134265601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -134265600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -115866001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -115866000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -102643201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -102643200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -84330001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -84330000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -81313201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -81313200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 142379999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 142380000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 150843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 150843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 167176799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 167176800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 178664399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 178664400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 482277599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 482277600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 495579599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 495579600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 516751199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 516751200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 526424399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 526424400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 545435999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 545436000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 558478799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 558478800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 576539999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 576540000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 589237199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 589237200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 609890399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 609890400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 620773199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 620773200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 638315999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 638316000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 651617999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 651618000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 669765599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 669765600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 683672399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 683672400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 715726799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 715726800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 733701599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 733701600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 747176399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 747176400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 765151199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 765151200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 778021199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 778021200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 796600799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 796600800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 810075599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 810075600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 820447199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 820447200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828655199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828655200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 843170399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 843170400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 860104799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 860104800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 874619999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 874620000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891554399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891554400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 906069599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 906069600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 924213599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 924213600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 939934799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 939934800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 956267999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 956268000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 971989199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 971989200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 987717599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 987717600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1003438799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1003438800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1019167199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1019167200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1034888399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1034888400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1050616799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1050616800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1066337999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1066338000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1082066399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1082066400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1096581599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1096581600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1113515999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1113516000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1128380399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1128380400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143842399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143842400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1158872399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1158872400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1175378399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1175378400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1189637999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1189638000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1207000799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1207000800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1219964399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1219964400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238104799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238104800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1254092399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1254092400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269554399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269554400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1285541999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1285542000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301003999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301004000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1316991599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1316991600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1333058399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1333058400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1348441199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1348441200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364507999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364508000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1380495599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1380495600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1395957599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1395957600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1411945199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1411945200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427407199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427407200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1443394799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1443394800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1458856799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1458856800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1474844399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1474844400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490911199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490911200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1506293999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1506294000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1522360799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1522360800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1537743599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1537743600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553810399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553810400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1569797999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1569798000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585259999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585260000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1601247599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1601247600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616709599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616709600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1632697199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1632697200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648159199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648159200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1664146799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1664146800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1680213599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1680213600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1695596399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1695596400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711663199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711663200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1727650799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1727650800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743112799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743112800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1759100399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1759100400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774562399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774562400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1790549999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1790550000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806011999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806012000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1821999599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1821999600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1838066399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1838066400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1853449199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1853449200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869515999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869516000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1884898799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1884898800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1900965599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1900965600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1916953199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1916953200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932415199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932415200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1948402799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1948402800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1963864799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1963864800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1979852399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1979852400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995314399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995314400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2011301999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2011302000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2027368799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2027368800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2042751599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2042751600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058818399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058818400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2074201199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2074201200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090267999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090268000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2106255599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2106255600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121717599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121717600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2137705199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2137705200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Harbin.json b/dojox/date/tests/tztests/tz_Asia-Harbin.json
new file mode 100644
index 0000000..7b3a9d7
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Harbin.json
@@ -0,0 +1,46 @@
+({
+	name: "date.timezone.Asia-Harbin",
+	runTest: function(t){
+		var tz = "Asia/Harbin";
+		doh.checkDate({tzOffset: -506.733333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -506.733333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -506.733333333333, tzAbbr: "LMT"}, -1325492805000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "CHAT"}, -1325492804000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "CHAT"}, -1194078601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -1194078600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -946800001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHAT"}, -946800000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CHAT"}, -115894801000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "CHAT"}, -115894800000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "CHAT"}, 325956599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 325956600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 515519999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 515520000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 527007599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 527007600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 545155199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 545155200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 558457199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 558457200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 576604799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 576604800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 589906799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 589906800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 608659199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 608659200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 621961199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 621961200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 640108799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 640108800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 653410799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 653410800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 671558399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 671558400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 684860399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 684860400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Ho_Chi_Minh.json b/dojox/date/tests/tztests/tz_Asia-Ho_Chi_Minh.json
new file mode 100644
index 0000000..cc42e55
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Ho_Chi_Minh.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.Asia-Ho_Chi_Minh",
+	runTest: function(t){
+		var tz = "Asia/Ho_Chi_Minh";
+		doh.checkDate({tzOffset: -426.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -426.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -426.666666666667, tzAbbr: "LMT"}, -2005974401000, tz, 1);
+		doh.checkDate({tzOffset: -426.333333333333, tzAbbr: "SMT"}, -2005974400000, tz, 1);
+		doh.checkDate({tzOffset: -426.333333333333, tzAbbr: "SMT"}, -1855983921000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, -1855983920000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, -1819954801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ICT"}, -1819954800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ICT"}, -1220428801000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, -1220428800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Hong_Kong.json b/dojox/date/tests/tztests/tz_Asia-Hong_Kong.json
new file mode 100644
index 0000000..0ce8721
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Hong_Kong.json
@@ -0,0 +1,150 @@
+({
+	name: "date.timezone.Asia-Hong_Kong",
+	runTest: function(t){
+		var tz = "Asia/Hong_Kong";
+		doh.checkDate({tzOffset: -456.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -456.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -456.6, tzAbbr: "LMT"}, -2056692997000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -2056692996000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -747981001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -747981000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -728544601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -728544600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -717049801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -717049800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -694503001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -694503000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -683785801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -683785800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -668064601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -668064600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -654755401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -654755400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -636615001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -636615000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -623305801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -623305800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -605165401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -605165400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -591856201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -591856200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -573715801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -573715800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -559801801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -559801800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -542266201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -542266200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -528352201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -528352200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -510211801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -510211800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -498112201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -498112200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -478762201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -478762200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -466662601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -466662600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -446707801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -446707800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -435213001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -435213000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -415258201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -415258200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -403158601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -403158600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -383808601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -383808600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -371709001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -371709000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -352359001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -352359000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -340259401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -340259400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -320909401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -320909400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -308809801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -308809800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -288855001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -288855000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -277360201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -277360200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -257405401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -257405400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -245910601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -245910600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -225955801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -225955800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -213856201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -213856200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -194506201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -194506200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -182406601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -182406600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -163056601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -163056600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -148537801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -148537800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -132816601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -132816600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -117088201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -117088200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -101367001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -101367000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -85638601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -85638600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -69312601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -69312600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -53584201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -53584200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -37863001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -37863000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -22134601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -22134600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, -6413401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, -6413400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 9314999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 9315000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 25036199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 25036200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 40764599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 40764600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 56485799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 56485800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 72214199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 72214200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 88540199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 88540200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 104268599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 104268600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 119989799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 119989800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 135718199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 135718200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 151439399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 151439400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 167167799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 167167800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 182888999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 182889000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 198617399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 198617400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 214338599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 214338600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 230066999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 230067000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 245788199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 245788200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 295385399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 295385400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 309292199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 309292200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 326834999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 326835000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "HKST"}, 340741799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 340741800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HKT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Hovd.json b/dojox/date/tests/tztests/tz_Asia-Hovd.json
new file mode 100644
index 0000000..2ac3805
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Hovd.json
@@ -0,0 +1,104 @@
+({
+	name: "date.timezone.Asia-Hovd",
+	runTest: function(t){
+		var tz = "Asia/Hovd";
+		doh.checkDate({tzOffset: -366.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -366.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -366.6, tzAbbr: "LMT"}, -2032927597000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "HOVT"}, -2032927596000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "HOVT"}, 252439199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 252439200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 417977999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 417978000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 433785599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 433785600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 449600399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 449600400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 465321599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 465321600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 481049999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 481050000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 496771199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 496771200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 512499599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 512499600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 528220799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 528220800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 543949199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 543949200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 559670399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 559670400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 575398799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 575398800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 591119999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 591120000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 606848399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 606848400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 622569599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 622569600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 638297999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 638298000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 654623999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 654624000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 670352399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 670352400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 686073599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 686073600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 701801999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 701802000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 717523199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 717523200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 733251599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 733251600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 748972799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 748972800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 764701199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 764701200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 780422399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 780422400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 796150799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 796150800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 811871999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 811872000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 828205199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 828205200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 843926399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 843926400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 859654799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 859654800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 875375999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 875376000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 891104399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 891104400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 906825599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 906825600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 988397999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 988398000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 1001699999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1001700000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1017428399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 1017428400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 1033149599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1033149600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1048877999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 1048878000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 1064599199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1064599200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1080327599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 1080327600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 1096048799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1096048800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1111777199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 1111777200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 1127498399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1127498400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1143226799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 1143226800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "HOVST"}, 1159552799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1159552800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "HOVT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Irkutsk.json b/dojox/date/tests/tztests/tz_Asia-Irkutsk.json
new file mode 100644
index 0000000..75855b3
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Irkutsk.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.Asia-Irkutsk",
+	runTest: function(t){
+		var tz = "Asia/Irkutsk";
+		doh.checkDate({tzOffset: -417.333333333333, tzAbbr: "IMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -417.333333333333, tzAbbr: "IMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -417.333333333333, tzAbbr: "IMT"}, -1575874641000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "IRKT"}, -1575874640000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "IRKT"}, -1247554801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, -1247554800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 354902399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 354902400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 370709999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 370710000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 386438399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 386438400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 402245999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 402246000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 417974399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 417974400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 433781999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 433782000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 449596799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 449596800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 465328799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 465328800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 481053599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 481053600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 496778399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 496778400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 512503199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 512503200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 528227999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 528228000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 543952799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 543952800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 559677599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 559677600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 575402399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 575402400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 591127199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 591127200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 606851999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 606852000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 622576799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 622576800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 638301599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 638301600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 654631199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 654631200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 670355999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKST"}, 670356000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKST"}, 686084399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "IRKT"}, 686084400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "IRKT"}, 695761199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 695761200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 701794799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 701794800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 717515999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 717516000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 733255199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 733255200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 748979999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 748980000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 764704799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 764704800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 780429599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 780429600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 796154399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 796154400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 811879199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 811879200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 828208799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 828208800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 846352799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 846352800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 859658399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 859658400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 877802399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 877802400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 891107999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 891108000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 909251999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 909252000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 922557599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 922557600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 941306399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 941306400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 954007199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 954007200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 972755999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 972756000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 985456799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 985456800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1004205599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1004205600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1017511199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1017511200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1035655199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1035655200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1048960799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1048960800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1067104799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1067104800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1080410399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1080410400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1099159199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1099159200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1111859999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1111860000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1130608799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1130608800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1143309599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1143309600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1162058399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1162058400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1174759199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1174759200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1193507999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1193508000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1206813599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1206813600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1224957599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1224957600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1238263199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1238263200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1256407199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1256407200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1269712799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1269712800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1288461599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1288461600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1301162399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1301162400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1319911199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1319911200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1332611999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1332612000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1351360799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1351360800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1364666399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1364666400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1382810399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1382810400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1396115999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1396116000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1414259999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1414260000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1427565599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1427565600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1445709599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1445709600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1459015199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1459015200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1477763999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1477764000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1490464799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1490464800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1509213599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1509213600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1521914399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1521914400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1540663199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1540663200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1553968799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1553968800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1572112799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1572112800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1585418399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1585418400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1603562399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1603562400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1616867999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1616868000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1635616799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1635616800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1648317599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1648317600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1667066399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1667066400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1679767199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1679767200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1698515999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1698516000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1711821599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1711821600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1729965599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1729965600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1743271199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1743271200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1761415199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1761415200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1774720799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1774720800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1792864799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1792864800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1806170399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1806170400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1824919199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1824919200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1837619999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1837620000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1856368799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1856368800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1869069599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1869069600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1887818399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1887818400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1901123999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1901124000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1919267999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1919268000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1932573599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1932573600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1950717599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1950717600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1964023199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1964023200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1982771999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1982772000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1995472799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1995472800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 2014221599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 2014221600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 2026922399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 2026922400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 2045671199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 2045671200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 2058371999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 2058372000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 2077120799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 2077120800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 2090426399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 2090426400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 2108570399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 2108570400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 2121875999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 2121876000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 2140019999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 2140020000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "IRKT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -540, tzAbbr: "IRKST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Jakarta.json b/dojox/date/tests/tztests/tz_Asia-Jakarta.json
new file mode 100644
index 0000000..5f4c8cc
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Jakarta.json
@@ -0,0 +1,26 @@
+({
+	name: "date.timezone.Asia-Jakarta",
+	runTest: function(t){
+		var tz = "Asia/Jakarta";
+		doh.checkDate({tzOffset: -427.2, tzAbbr: "JMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -427.2, tzAbbr: "JMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -427.2, tzAbbr: "JMT"}, -1451719201000, tz, 1);
+		doh.checkDate({tzOffset: -440, tzAbbr: "JAVT"}, -1451719200000, tz, 1);
+		doh.checkDate({tzOffset: -440, tzAbbr: "JAVT"}, -1172906401000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -1172906400000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -876641401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -876641400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -766054801000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -766054800000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -683883001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WIT"}, -683883000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WIT"}, -620812801000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -620812800000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -189415801000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "WIT"}, -189415800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "WIT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "WIT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "WIT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "WIT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Jayapura.json b/dojox/date/tests/tztests/tz_Asia-Jayapura.json
new file mode 100644
index 0000000..191a752
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Jayapura.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Asia-Jayapura",
+	runTest: function(t){
+		var tz = "Asia/Jayapura";
+		doh.checkDate({tzOffset: -562.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -562.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -562.8, tzAbbr: "LMT"}, -1172913769000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "EIT"}, -1172913768000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "EIT"}, -799491601000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -799491600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -189423001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "EIT"}, -189423000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "EIT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "EIT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "EIT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -540, tzAbbr: "EIT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Jerusalem.json b/dojox/date/tests/tztests/tz_Asia-Jerusalem.json
new file mode 100644
index 0000000..46160c7
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Jerusalem.json
@@ -0,0 +1,296 @@
+({
+	name: "date.timezone.Asia-Jerusalem",
+	runTest: function(t){
+		var tz = "Asia/Jerusalem";
+		doh.checkDate({tzOffset: -140.666666666667, tzAbbr: "JMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -140.666666666667, tzAbbr: "JMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -140.666666666667, tzAbbr: "JMT"}, -1641003641000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -1641003640000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -933645601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -933645600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -857358001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -857358000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -844300801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -844300800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -825822001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -825822000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -812685601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -812685600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -794199601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -794199600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -779853601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -779853600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -762656401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -762656400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -748310401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -748310400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -731127601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -731127600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -681962401000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "IDDT"}, -681962400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "IDDT"}, -673243201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -673243200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -667962001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -667962000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -652327201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -652327200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -636426001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -636426000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -622087201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -622087200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -608947201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -608947200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -591847201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -591847200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -572486401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -572486400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -558576001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -558576000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -542851201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -542851200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -527731201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -527731200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -514425601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -514425600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -490845601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -490845600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -482986801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -482986800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -459475201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -459475200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -451537201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -451537200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -428551201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -428551200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -418262401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -418262400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -400032001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -400032000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, -387428401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, -387428400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 142379999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 142380000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 150843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 150843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 167176799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 167176800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 178664399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 178664400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 482277599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 482277600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 495579599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 495579600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 516751199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 516751200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 526424399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 526424400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 545435999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 545436000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 558478799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 558478800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 576539999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 576540000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 589237199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 589237200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 609890399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 609890400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 620773199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 620773200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 638315999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 638316000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 651617999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 651618000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 669765599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 669765600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 683672399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 683672400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 715726799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 715726800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 733701599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 733701600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 747176399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 747176400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 765151199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 765151200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 778021199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 778021200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 796600799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 796600800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 810075599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 810075600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 826840799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 826840800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 842821199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 842821200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 858895199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 858895200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 874184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 874184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 890344799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 890344800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 905029199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 905029200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 923011199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 923011200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 936313199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 936313200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 955670399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 955670400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 970783199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 970783200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 986770799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 986770800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1001282399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1001282400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1017356399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1017356400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1033941599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1033941600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1048805999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1048806000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1065131999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1065132000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1081292399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1081292400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1095803999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1095804000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1112313599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1112313600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1128812399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1128812400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1143763199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1143763200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1159657199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1159657200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1175212799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1175212800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1189897199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1189897200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1206662399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1206662400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1223161199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1223161200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1238111999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1238112000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1254005999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1254006000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1269561599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1269561600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1284245999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1284246000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1301615999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1301616000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1317509999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1317510000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1333065599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1333065600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1348354799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1348354800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1364515199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1364515200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1378594799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1378594800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1395964799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1395964800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1411858799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1411858800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1427414399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1427414400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1442703599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1442703600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1459468799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1459468800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1475967599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1475967600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1490918399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1490918400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1506207599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1506207600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1522367999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1522368000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1537052399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1537052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1553817599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1553817600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1570316399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1570316400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1585267199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1585267200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1601161199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1601161200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1616716799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1616716800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1631401199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1631401200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1648771199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1648771200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1664665199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1664665200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1680220799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1680220800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1695509999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1695510000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1711670399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1711670400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1728169199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1728169200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1743119999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1743120000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1759013999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1759014000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1774569599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1774569600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1789858799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1789858800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1806019199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1806019200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1823122799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1823122800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1838073599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1838073600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1853362799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1853362800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1869523199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1869523200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1884207599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1884207600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1900972799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1900972800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1917471599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1917471600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1932422399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1932422400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1947711599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1947711600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1963871999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1963872000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1978556399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1978556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1995926399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1995926400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 2011820399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 2011820400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 2027375999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 2027376000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 2042060399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 2042060400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 2058825599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 2058825600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 2075324399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 2075324400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 2090275199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 2090275200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 2106169199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 2106169200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 2121724799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 2121724800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 2136409199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 2136409200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "IST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "IDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Kabul.json b/dojox/date/tests/tztests/tz_Asia-Kabul.json
new file mode 100644
index 0000000..015db30
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Kabul.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Asia-Kabul",
+	runTest: function(t){
+		var tz = "Asia/Kabul";
+		doh.checkDate({tzOffset: -240, tzAbbr: "AFT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AFT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AFT"}, -788932801000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "AFT"}, -788932800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "AFT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "AFT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "AFT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -270, tzAbbr: "AFT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Kamchatka.json b/dojox/date/tests/tztests/tz_Asia-Kamchatka.json
new file mode 100644
index 0000000..c69b861
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Kamchatka.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.Asia-Kamchatka",
+	runTest: function(t){
+		var tz = "Asia/Kamchatka";
+		doh.checkDate({tzOffset: -634.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -634.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -634.6, tzAbbr: "LMT"}, -1487759677000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "PETT"}, -1487759676000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "PETT"}, -1247569201000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, -1247569200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 354887999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 354888000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 370695599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 370695600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 386423999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 386424000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 402231599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 402231600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 417959999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 417960000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 433767599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 433767600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 449582399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 449582400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 465314399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 465314400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 481039199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 481039200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 496763999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 496764000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 512488799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 512488800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 528213599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 528213600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 543938399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 543938400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 559663199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 559663200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 575387999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 575388000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 591112799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 591112800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 606837599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 606837600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 622562399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 622562400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 638287199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 638287200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 654616799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 654616800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 670341599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETST"}, 670341600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETST"}, 686069999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "PETT"}, 686070000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "PETT"}, 695746799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 695746800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 701780399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 701780400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 717501599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 717501600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 733240799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 733240800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 748965599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 748965600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 764690399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 764690400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 780415199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 780415200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 796139999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 796140000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 811864799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 811864800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 828194399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 828194400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 846338399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 846338400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 859643999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 859644000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 877787999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 877788000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 891093599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 891093600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 909237599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 909237600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 922543199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 922543200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 941291999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 941292000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 953992799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 953992800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 972741599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 972741600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 985442399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 985442400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1004191199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1004191200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1017496799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1017496800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1035640799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1035640800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1048946399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1048946400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1067090399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1067090400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1080395999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1080396000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1099144799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1099144800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1111845599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1111845600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1130594399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1130594400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1143295199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1143295200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1162043999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1162044000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1174744799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1174744800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1193493599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1193493600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1206799199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1206799200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1224943199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1224943200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1238248799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1238248800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1256392799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1256392800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1269698399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1269698400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1288447199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1288447200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1301147999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1301148000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1319896799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1319896800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1332597599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1332597600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1351346399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1351346400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1364651999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1364652000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1382795999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1382796000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1396101599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1396101600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1414245599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1414245600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1427551199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1427551200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1445695199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1445695200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1459000799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1459000800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1477749599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1477749600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1490450399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1490450400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1509199199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1509199200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1521899999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1521900000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1540648799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1540648800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1553954399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1553954400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1572098399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1572098400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1585403999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1585404000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1603547999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1603548000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1616853599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1616853600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1635602399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1635602400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1648303199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1648303200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1667051999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1667052000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1679752799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1679752800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1698501599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1698501600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1711807199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1711807200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1729951199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1729951200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1743256799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1743256800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1761400799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1761400800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1774706399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1774706400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1792850399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1792850400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1806155999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1806156000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1824904799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1824904800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1837605599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1837605600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1856354399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1856354400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1869055199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1869055200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1887803999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1887804000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1901109599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1901109600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1919253599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1919253600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1932559199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1932559200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1950703199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1950703200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1964008799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1964008800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1982757599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1982757600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1995458399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1995458400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 2014207199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 2014207200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 2026907999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 2026908000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 2045656799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 2045656800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 2058357599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 2058357600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 2077106399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 2077106400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 2090411999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 2090412000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 2108555999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 2108556000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 2121861599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 2121861600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 2140005599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 2140005600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "PETT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PETST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Karachi.json b/dojox/date/tests/tztests/tz_Asia-Karachi.json
new file mode 100644
index 0000000..7bc28d0
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Karachi.json
@@ -0,0 +1,34 @@
+({
+	name: "date.timezone.Asia-Karachi",
+	runTest: function(t){
+		var tz = "Asia/Karachi";
+		doh.checkDate({tzOffset: -268.2, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -268.2, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -268.2, tzAbbr: "LMT"}, -1988166493000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -1988166492000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -862637401000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "IST"}, -862637400000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "IST"}, -764145001000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -764145000000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -576135001000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KART"}, -576135000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KART"}, 38775599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "PKT"}, 38775600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "PKT"}, 1018119659000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "PKST"}, 1018119660000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "PKST"}, 1033840859000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "PKT"}, 1033840860000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "PKT"}, 1212260399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "PKST"}, 1212260400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "PKST"}, 1225475999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "PKT"}, 1225476000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "PKT"}, 1239735599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "PKST"}, 1239735600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "PKST"}, 1257011999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "PKT"}, 1257012000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "PKT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "PKT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "PKT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -360, tzAbbr: "PKST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Kashgar.json b/dojox/date/tests/tztests/tz_Asia-Kashgar.json
new file mode 100644
index 0000000..06c0010
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Kashgar.json
@@ -0,0 +1,42 @@
+({
+	name: "date.timezone.Asia-Kashgar",
+	runTest: function(t){
+		var tz = "Asia/Kashgar";
+		doh.checkDate({tzOffset: -303.933333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -303.933333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -303.933333333333, tzAbbr: "LMT"}, -1325480637000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "KAST"}, -1325480636000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "KAST"}, -946791001000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KAST"}, -946791000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KAST"}, 325969199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 325969200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 515519999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 515520000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 527007599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 527007600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 545155199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 545155200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 558457199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 558457200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 576604799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 576604800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 589906799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 589906800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 608659199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 608659200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 621961199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 621961200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 640108799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 640108800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 653410799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 653410800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 671558399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 671558400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 684860399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 684860400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Kathmandu.json b/dojox/date/tests/tztests/tz_Asia-Kathmandu.json
new file mode 100644
index 0000000..868b276
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Kathmandu.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Asia-Kathmandu",
+	runTest: function(t){
+		var tz = "Asia/Kathmandu";
+		doh.checkDate({tzOffset: -341.266666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -341.266666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -341.266666666667, tzAbbr: "LMT"}, -1577943677000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -1577943676000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 504901799000, tz, 1);
+		doh.checkDate({tzOffset: -345, tzAbbr: "NPT"}, 504901800000, tz, 1);
+		doh.checkDate({tzOffset: -345, tzAbbr: "NPT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -345, tzAbbr: "NPT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -345, tzAbbr: "NPT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -345, tzAbbr: "NPT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Kolkata.json b/dojox/date/tests/tztests/tz_Asia-Kolkata.json
new file mode 100644
index 0000000..faff00a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Kolkata.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.Asia-Kolkata",
+	runTest: function(t){
+		var tz = "Asia/Kolkata";
+		doh.checkDate({tzOffset: -353.333333333333, tzAbbr: "HMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -353.333333333333, tzAbbr: "HMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -353.333333333333, tzAbbr: "HMT"}, -891582801000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "BURT"}, -891582800000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "BURT"}, -872058601000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -872058600000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -862637401000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "IST"}, -862637400000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "IST"}, -764145001000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -764145000000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Krasnoyarsk.json b/dojox/date/tests/tztests/tz_Asia-Krasnoyarsk.json
new file mode 100644
index 0000000..06d08d7
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Krasnoyarsk.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.Asia-Krasnoyarsk",
+	runTest: function(t){
+		var tz = "Asia/Krasnoyarsk";
+		doh.checkDate({tzOffset: -371.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -371.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -371.333333333333, tzAbbr: "LMT"}, -1577513481000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KRAT"}, -1577513480000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KRAT"}, -1247551201000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, -1247551200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 354905999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 354906000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 370713599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 370713600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 386441999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 386442000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 402249599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 402249600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 417977999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 417978000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 433785599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 433785600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 449600399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 449600400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 465332399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 465332400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 481057199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 481057200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 496781999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 496782000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 512506799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 512506800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 528231599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 528231600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 543956399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 543956400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 559681199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 559681200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 575405999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 575406000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 591130799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 591130800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 606855599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 606855600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 622580399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 622580400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 638305199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 638305200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 654634799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 654634800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 670359599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAST"}, 670359600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAST"}, 686087999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KRAT"}, 686088000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KRAT"}, 695764799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 695764800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 701798399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 701798400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 717519599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 717519600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 733258799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 733258800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 748983599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 748983600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 764708399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 764708400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 780433199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 780433200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 796157999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 796158000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 811882799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 811882800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 828212399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 828212400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 846356399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 846356400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 859661999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 859662000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 877805999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 877806000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 891111599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 891111600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 909255599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 909255600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 922561199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 922561200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 941309999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 941310000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 954010799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 954010800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 972759599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 972759600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 985460399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 985460400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1004209199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1004209200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1017514799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1017514800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1035658799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1035658800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1048964399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1048964400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1067108399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1067108400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1080413999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1080414000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1099162799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1099162800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1111863599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1111863600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1130612399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1130612400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1143313199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1143313200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1162061999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1162062000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1174762799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1174762800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1193511599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1193511600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1206817199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1206817200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1224961199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1224961200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1238266799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1238266800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1256410799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1256410800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1269716399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1269716400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1288465199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1288465200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1301165999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1301166000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1319914799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1319914800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1332615599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1332615600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1351364399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1351364400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1364669999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1364670000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1382813999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1382814000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1396119599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1396119600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1414263599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1414263600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1427569199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1427569200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1445713199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1445713200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1459018799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1459018800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1477767599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1477767600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1490468399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1490468400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1509217199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1509217200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1521917999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1521918000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1540666799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1540666800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1553972399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1553972400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1572116399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1572116400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1585421999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1585422000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1603565999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1603566000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1616871599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1616871600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1635620399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1635620400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1648321199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1648321200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1667069999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1667070000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1679770799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1679770800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1698519599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1698519600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1711825199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1711825200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1729969199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1729969200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1743274799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1743274800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1761418799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1761418800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1774724399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1774724400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1792868399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1792868400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1806173999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1806174000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1824922799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1824922800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1837623599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1837623600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1856372399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1856372400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1869073199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1869073200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1887821999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1887822000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1901127599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1901127600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1919271599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1919271600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1932577199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1932577200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1950721199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1950721200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1964026799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1964026800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1982775599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1982775600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1995476399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1995476400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 2014225199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 2014225200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 2026925999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 2026926000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 2045674799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 2045674800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 2058375599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 2058375600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 2077124399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 2077124400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 2090429999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 2090430000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 2108573999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 2108574000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 2121879599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 2121879600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 2140023599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 2140023600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "KRAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KRAST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Kuala_Lumpur.json b/dojox/date/tests/tztests/tz_Asia-Kuala_Lumpur.json
new file mode 100644
index 0000000..2e9f1ac
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Kuala_Lumpur.json
@@ -0,0 +1,26 @@
+({
+	name: "date.timezone.Asia-Kuala_Lumpur",
+	runTest: function(t){
+		var tz = "Asia/Kuala_Lumpur";
+		doh.checkDate({tzOffset: -415.416666666667, tzAbbr: "SMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -415.416666666667, tzAbbr: "SMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -415.416666666667, tzAbbr: "SMT"}, -2038200926000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "MALT"}, -2038200925000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "MALT"}, -1167634801000, tz, 1);
+		doh.checkDate({tzOffset: -440, tzAbbr: "MALST"}, -1167634800000, tz, 1);
+		doh.checkDate({tzOffset: -440, tzAbbr: "MALST"}, -1073028001000, tz, 1);
+		doh.checkDate({tzOffset: -440, tzAbbr: "MALT"}, -1073028000000, tz, 1);
+		doh.checkDate({tzOffset: -440, tzAbbr: "MALT"}, -894180001000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "MALT"}, -894180000000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "MALT"}, -879665401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -879665400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -767005201000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "MALT"}, -767005200000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "MALT"}, 378664199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MYT"}, 378664200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MYT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MYT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MYT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MYT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Kuching.json b/dojox/date/tests/tztests/tz_Asia-Kuching.json
new file mode 100644
index 0000000..a1ad3a4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Kuching.json
@@ -0,0 +1,50 @@
+({
+	name: "date.timezone.Asia-Kuching",
+	runTest: function(t){
+		var tz = "Asia/Kuching";
+		doh.checkDate({tzOffset: -441.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -441.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -441.333333333333, tzAbbr: "LMT"}, -1383463281000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "BORT"}, -1383463280000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "BORT"}, -1167636601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -1167636600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -1082448001000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -1082448000000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -1074586801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -1074586800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -1050825601000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -1050825600000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -1042964401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -1042964400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -1019289601000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -1019289600000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -1011428401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -1011428400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -987753601000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -987753600000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -979892401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -979892400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -956217601000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -956217600000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -948356401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -948356400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -924595201000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -924595200000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -916734001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -916734000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -893059201000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -893059200000, tz, 1);
+		doh.checkDate({tzOffset: -500, tzAbbr: "BORTST"}, -885198001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -885198000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -879667201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -879667200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -767005201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, -767005200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "BORT"}, 378662399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MYT"}, 378662400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MYT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MYT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MYT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MYT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Kuwait.json b/dojox/date/tests/tztests/tz_Asia-Kuwait.json
new file mode 100644
index 0000000..7a00292
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Kuwait.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Asia-Kuwait",
+	runTest: function(t){
+		var tz = "Asia/Kuwait";
+		doh.checkDate({tzOffset: -191.933333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -191.933333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -191.933333333333, tzAbbr: "LMT"}, -631163517000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, -631163516000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Macau.json b/dojox/date/tests/tztests/tz_Asia-Macau.json
new file mode 100644
index 0000000..7b07360
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Macau.json
@@ -0,0 +1,96 @@
+({
+	name: "date.timezone.Asia-Macau",
+	runTest: function(t){
+		var tz = "Asia/Macau";
+		doh.checkDate({tzOffset: -454.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -454.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -454.333333333333, tzAbbr: "LMT"}, -1830411261000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -1830411260000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -277360201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -277360200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -257405401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -257405400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -245910601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -245910600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -225955801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -225955800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -214473601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -214473600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -194506201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -194506200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -182406601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -182406600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -163056601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -163056600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -150969601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -150969600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -131619601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -131619600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -117088201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -117088200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -101367001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -101367000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -85638601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -85638600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -69312601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -69312600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -53584201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -53584200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -37863001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -37863000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -22134601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -22134600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, -6413401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, -6413400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 9314999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 9315000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 25036199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 25036200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 40764599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 40764600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 56485799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 56485800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 72201599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 72201600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 87922799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 87922800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 103651199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 103651200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 119977199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 119977200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 135705599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 135705600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 151439399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 151439400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 167167799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 167167800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 182888999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 182889000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 198617399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 198617400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 214338599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 214338600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 230066999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 230067000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 245788199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 245788200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 261503999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 261504000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 277225199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 277225200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 292953599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 292953600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 309279599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 309279600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 325007999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 325008000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MOST"}, 340729199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 340729200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "MOT"}, 945619199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 945619200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Magadan.json b/dojox/date/tests/tztests/tz_Asia-Magadan.json
new file mode 100644
index 0000000..e45fb77
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Magadan.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.Asia-Magadan",
+	runTest: function(t){
+		var tz = "Asia/Magadan";
+		doh.checkDate({tzOffset: -603.2, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -603.2, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -603.2, tzAbbr: "LMT"}, -1441188193000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "MAGT"}, -1441188192000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "MAGT"}, -1247565601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, -1247565600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 354891599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 354891600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 370699199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 370699200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 386427599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 386427600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 402235199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 402235200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 417963599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 417963600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 433771199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 433771200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 449585999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 449586000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 465317999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 465318000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 481042799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 481042800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 496767599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 496767600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 512492399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 512492400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 528217199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 528217200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 543941999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 543942000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 559666799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 559666800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 575391599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 575391600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 591116399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 591116400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 606841199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 606841200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 622565999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 622566000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 638290799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 638290800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 654620399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 654620400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 670345199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGST"}, 670345200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGST"}, 686073599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "MAGT"}, 686073600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "MAGT"}, 695750399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 695750400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 701783999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 701784000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 717505199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 717505200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 733244399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 733244400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 748969199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 748969200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 764693999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 764694000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 780418799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 780418800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 796143599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 796143600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 811868399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 811868400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 828197999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 828198000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 846341999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 846342000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 859647599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 859647600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 877791599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 877791600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 891097199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 891097200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 909241199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 909241200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 922546799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 922546800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 941295599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 941295600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 953996399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 953996400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 972745199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 972745200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 985445999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 985446000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1004194799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1004194800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1017500399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1017500400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1035644399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1035644400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1048949999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1048950000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1067093999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1067094000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1080399599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1080399600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1099148399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1099148400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1111849199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1111849200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1130597999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1130598000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1143298799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1143298800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1162047599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1162047600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1174748399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1174748400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1193497199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1193497200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1206802799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1206802800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1224946799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1224946800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1238252399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1238252400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1256396399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1256396400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1269701999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1269702000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1288450799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1288450800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1301151599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1301151600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1319900399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1319900400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1332601199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1332601200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1351349999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1351350000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1364655599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1364655600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1382799599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1382799600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1396105199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1396105200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1414249199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1414249200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1427554799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1427554800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1445698799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1445698800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1459004399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1459004400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1477753199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1477753200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1490453999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1490454000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1509202799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1509202800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1521903599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1521903600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1540652399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1540652400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1553957999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1553958000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1572101999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1572102000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1585407599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1585407600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1603551599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1603551600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1616857199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1616857200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1635605999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1635606000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1648306799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1648306800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1667055599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1667055600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1679756399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1679756400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1698505199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1698505200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1711810799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1711810800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1729954799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1729954800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1743260399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1743260400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1761404399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1761404400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1774709999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1774710000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1792853999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1792854000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1806159599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1806159600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1824908399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1824908400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1837609199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1837609200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1856357999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1856358000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1869058799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1869058800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1887807599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1887807600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1901113199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1901113200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1919257199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1919257200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1932562799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1932562800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1950706799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1950706800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1964012399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1964012400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1982761199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1982761200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1995461999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1995462000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 2014210799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 2014210800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 2026911599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 2026911600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 2045660399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 2045660400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 2058361199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 2058361200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 2077109999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 2077110000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 2090415599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 2090415600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 2108559599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 2108559600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 2121865199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 2121865200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 2140009199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 2140009200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MAGT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MAGST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Makassar.json b/dojox/date/tests/tztests/tz_Asia-Makassar.json
new file mode 100644
index 0000000..0887892
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Makassar.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.Asia-Makassar",
+	runTest: function(t){
+		var tz = "Asia/Makassar";
+		doh.checkDate({tzOffset: -477.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -477.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -477.6, tzAbbr: "LMT"}, -1577951857000, tz, 1);
+		doh.checkDate({tzOffset: -477.6, tzAbbr: "MMT"}, -1577951856000, tz, 1);
+		doh.checkDate({tzOffset: -477.6, tzAbbr: "MMT"}, -1172908657000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CIT"}, -1172908656000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CIT"}, -880272001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -880272000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -766054801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CIT"}, -766054800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CIT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CIT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CIT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CIT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Manila.json b/dojox/date/tests/tztests/tz_Asia-Manila.json
new file mode 100644
index 0000000..745fd55
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Manila.json
@@ -0,0 +1,28 @@
+({
+	name: "date.timezone.Asia-Manila",
+	runTest: function(t){
+		var tz = "Asia/Manila";
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, -1046678401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "PHST"}, -1046678400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "PHST"}, -1038733201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, -1038733200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, -873273601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -873273600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -794221201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, -794221200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, -496224001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "PHST"}, -496224000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "PHST"}, -489315601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, -489315600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, 259343999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "PHST"}, 259344000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "PHST"}, 275151599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, 275151600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "PHT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Muscat.json b/dojox/date/tests/tztests/tz_Asia-Muscat.json
new file mode 100644
index 0000000..72b62bd
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Muscat.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Asia-Muscat",
+	runTest: function(t){
+		var tz = "Asia/Muscat";
+		doh.checkDate({tzOffset: -234.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -234.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -234.333333333333, tzAbbr: "LMT"}, -1577937261000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, -1577937260000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Nicosia.json b/dojox/date/tests/tztests/tz_Asia-Nicosia.json
new file mode 100644
index 0000000..44a0489
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Nicosia.json
@@ -0,0 +1,266 @@
+({
+	name: "date.timezone.Asia-Nicosia",
+	runTest: function(t){
+		var tz = "Asia/Nicosia";
+		doh.checkDate({tzOffset: -133.466666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -133.466666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -133.466666666667, tzAbbr: "LMT"}, -1518920009000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1518920008000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 166571999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 166572000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 182293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 182293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 200959199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 200959200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 213829199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 213829200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 228866399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 228866400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 243982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 243982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 260315999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 260316000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 276123599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 276123600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 291765599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 291765600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 307486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 307486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 323819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 323820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 338936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 338936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 354664799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 354664800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 370385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 370386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 386114399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 386114400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 401835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 401835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 417563999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 417564000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 433285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 433285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 449013599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 449013600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 465339599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 465339600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 481067999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 481068000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 496789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 496789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 512517599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 512517600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 528238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 528238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 543967199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 543967200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 559688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 559688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 575416799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 575416800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 591137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 591138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 606866399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 606866400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 622587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 622587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 638315999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 638316000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 654641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 654642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670370399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670370400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733269599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733269600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 748990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 748990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764719199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764719200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796168799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796168800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828223199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828223200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 843944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 843944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859672799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859672800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 875393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 875394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891122399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891122400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Novosibirsk.json b/dojox/date/tests/tztests/tz_Asia-Novosibirsk.json
new file mode 100644
index 0000000..779b176
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Novosibirsk.json
@@ -0,0 +1,248 @@
+({
+	name: "date.timezone.Asia-Novosibirsk",
+	runTest: function(t){
+		var tz = "Asia/Novosibirsk";
+		doh.checkDate({tzOffset: -331.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -331.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -331.666666666667, tzAbbr: "LMT"}, -1579476701000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, -1579476700000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, -1247551201000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, -1247551200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 354905999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 354906000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 370713599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 370713600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 386441999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 386442000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 402249599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 402249600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 417977999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 417978000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 433785599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 433785600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 449600399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 449600400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 465332399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 465332400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 481057199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 481057200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 496781999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 496782000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 512506799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 512506800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 528231599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 528231600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 543956399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 543956400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 559681199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 559681200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 575405999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 575406000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 591130799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 591130800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 606855599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 606855600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 622580399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 622580400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 638305199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 638305200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 654634799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 654634800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 670359599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 670359600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 686087999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 686088000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 695764799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 695764800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 701798399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 701798400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 717519599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 717519600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVT"}, 733258799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 733258800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "NOVST"}, 738086399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 738086400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 748987199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 748987200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 764711999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 764712000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 780436799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 780436800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 796161599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 796161600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 811886399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 811886400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 828215999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 828216000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 846359999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 846360000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 859665599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 859665600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 877809599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 877809600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 891115199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 891115200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 909259199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 909259200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 922564799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 922564800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 941313599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 941313600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 954014399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 954014400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 972763199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 972763200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 985463999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 985464000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1004212799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1004212800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1017518399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1017518400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1035662399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1035662400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1048967999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1048968000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1067111999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1067112000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1080417599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1080417600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1099166399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1099166400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1111867199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1111867200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1130615999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1130616000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1143316799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1143316800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1162065599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1162065600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1174766399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1174766400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1193515199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1193515200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1206820799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1206820800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1224964799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1224964800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1238270399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1238270400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1256414399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1256414400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1269719999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1269720000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1288468799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1288468800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1301169599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1301169600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1319918399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1319918400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1332619199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1332619200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1351367999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1351368000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1364673599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1364673600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1382817599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1382817600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1396123199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1396123200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1414267199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1414267200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1427572799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1427572800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1445716799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1445716800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1459022399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1459022400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1477771199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1477771200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1490471999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1490472000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1509220799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1509220800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1521921599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1521921600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1540670399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1540670400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1553975999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1553976000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1572119999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1572120000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1585425599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1585425600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1603569599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1603569600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1616875199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1616875200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1635623999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1635624000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1648324799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1648324800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1667073599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1667073600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1679774399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1679774400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1698523199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1698523200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1711828799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1711828800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1729972799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1729972800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1743278399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1743278400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1761422399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1761422400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1774727999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1774728000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1792871999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1792872000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1806177599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1806177600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1824926399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1824926400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1837627199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1837627200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1856375999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1856376000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1869076799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1869076800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1887825599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1887825600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1901131199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1901131200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1919275199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1919275200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1932580799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1932580800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1950724799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1950724800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1964030399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1964030400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1982779199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1982779200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1995479999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1995480000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 2014228799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 2014228800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 2026929599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 2026929600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 2045678399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 2045678400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 2058379199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 2058379200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 2077127999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 2077128000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 2090433599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 2090433600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 2108577599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 2108577600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 2121883199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 2121883200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 2140027199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 2140027200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "NOVT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "NOVST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Omsk.json b/dojox/date/tests/tztests/tz_Asia-Omsk.json
new file mode 100644
index 0000000..b46d34d
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Omsk.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.Asia-Omsk",
+	runTest: function(t){
+		var tz = "Asia/Omsk";
+		doh.checkDate({tzOffset: -293.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -293.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -293.6, tzAbbr: "LMT"}, -1582088017000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "OMST"}, -1582088016000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "OMST"}, -1247547601000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, -1247547600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 354909599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 354909600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 370717199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 370717200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 386445599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 386445600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 402253199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 402253200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 417981599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 417981600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 433789199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 433789200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 449603999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 449604000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 465335999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 465336000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 481060799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 481060800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 496785599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 496785600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 512510399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 512510400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 528235199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 528235200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 543959999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 543960000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 559684799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 559684800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 575409599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 575409600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 591134399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 591134400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 606859199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 606859200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 622583999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 622584000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 638308799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 638308800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 654638399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 654638400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 670363199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMSST"}, 670363200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMSST"}, 686091599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "OMST"}, 686091600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "OMST"}, 695768399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 695768400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 701801999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 701802000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 717523199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 717523200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 733262399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 733262400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 748987199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 748987200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 764711999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 764712000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 780436799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 780436800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 796161599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 796161600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 811886399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 811886400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 828215999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 828216000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 846359999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 846360000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 859665599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 859665600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 877809599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 877809600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 891115199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 891115200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 909259199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 909259200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 922564799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 922564800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 941313599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 941313600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 954014399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 954014400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 972763199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 972763200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 985463999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 985464000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1004212799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1004212800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1017518399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1017518400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1035662399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1035662400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1048967999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1048968000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1067111999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1067112000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1080417599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1080417600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1099166399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1099166400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1111867199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1111867200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1130615999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1130616000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1143316799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1143316800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1162065599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1162065600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1174766399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1174766400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1193515199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1193515200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1206820799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1206820800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1224964799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1224964800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1238270399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1238270400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1256414399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1256414400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1269719999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1269720000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1288468799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1288468800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1301169599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1301169600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1319918399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1319918400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1332619199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1332619200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1351367999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1351368000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1364673599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1364673600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1382817599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1382817600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1396123199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1396123200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1414267199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1414267200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1427572799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1427572800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1445716799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1445716800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1459022399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1459022400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1477771199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1477771200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1490471999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1490472000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1509220799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1509220800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1521921599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1521921600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1540670399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1540670400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1553975999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1553976000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1572119999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1572120000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1585425599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1585425600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1603569599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1603569600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1616875199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1616875200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1635623999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1635624000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1648324799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1648324800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1667073599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1667073600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1679774399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1679774400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1698523199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1698523200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1711828799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1711828800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1729972799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1729972800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1743278399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1743278400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1761422399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1761422400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1774727999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1774728000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1792871999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1792872000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1806177599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1806177600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1824926399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1824926400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1837627199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1837627200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1856375999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1856376000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1869076799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1869076800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1887825599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1887825600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1901131199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1901131200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1919275199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1919275200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1932580799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1932580800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1950724799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1950724800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1964030399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1964030400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1982779199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1982779200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1995479999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1995480000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 2014228799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 2014228800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 2026929599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 2026929600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 2045678399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 2045678400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 2058379199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 2058379200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 2077127999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 2077128000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 2090433599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 2090433600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 2108577599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 2108577600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 2121883199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 2121883200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 2140027199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 2140027200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "OMST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "OMSST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Oral.json b/dojox/date/tests/tztests/tz_Asia-Oral.json
new file mode 100644
index 0000000..ea232fa
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Oral.json
@@ -0,0 +1,112 @@
+({
+	name: "date.timezone.Asia-Oral",
+	runTest: function(t){
+		var tz = "Asia/Oral";
+		doh.checkDate({tzOffset: -205.4, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -205.4, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -205.4, tzAbbr: "LMT"}, -1441164325000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "URAT"}, -1441164324000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "URAT"}, -1247544001000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, -1247544000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 354913199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 354913200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 370720799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAT"}, 370720800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAT"}, 386445599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 386445600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 402256799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 402256800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 417985199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 417985200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 433792799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 433792800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 449607599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 449607600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 465339599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 465339600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 481064399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 481064400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 496789199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 496789200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 512513999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 512514000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 528238799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 528238800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 543963599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 543963600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 559688399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 559688400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 575413199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 575413200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URAST"}, 591137999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 591138000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAT"}, 606862799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAST"}, 606862800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAST"}, 622591199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "URAT"}, 622591200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "URAT"}, 638315999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAST"}, 638316000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "URAST"}, 654645599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "URAT"}, 654645600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "URAT"}, 692827199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 692827200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 701809199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 701809200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 717530399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 717530400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 733269599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 733269600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 748994399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 748994400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 764719199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 764719200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 780443999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 780444000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 796168799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 796168800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 811893599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 811893600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 828223199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 828223200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 846367199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 846367200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 859672799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 859672800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 877816799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 877816800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 891122399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 891122400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 909266399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 909266400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 922571999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 922572000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 941320799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 941320800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 954021599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 954021600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 972770399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 972770400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 985471199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 985471200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 1004219999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 1004220000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 1017525599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 1017525600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 1035669599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 1035669600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 1048975199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 1048975200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 1067119199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 1067119200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 1080424799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 1080424800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAST"}, 1099173599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 1099173600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "ORAT"}, 1110830399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAT"}, 1110830400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "ORAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Phnom_Penh.json b/dojox/date/tests/tztests/tz_Asia-Phnom_Penh.json
new file mode 100644
index 0000000..9cb0e16
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Phnom_Penh.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.Asia-Phnom_Penh",
+	runTest: function(t){
+		var tz = "Asia/Phnom_Penh";
+		doh.checkDate({tzOffset: -419.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -419.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -419.666666666667, tzAbbr: "LMT"}, -2005973981000, tz, 1);
+		doh.checkDate({tzOffset: -426.333333333333, tzAbbr: "SMT"}, -2005973980000, tz, 1);
+		doh.checkDate({tzOffset: -426.333333333333, tzAbbr: "SMT"}, -1855983921000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, -1855983920000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, -1819954801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ICT"}, -1819954800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ICT"}, -1220428801000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, -1220428800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Pontianak.json b/dojox/date/tests/tztests/tz_Asia-Pontianak.json
new file mode 100644
index 0000000..88906cb
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Pontianak.json
@@ -0,0 +1,28 @@
+({
+	name: "date.timezone.Asia-Pontianak",
+	runTest: function(t){
+		var tz = "Asia/Pontianak";
+		doh.checkDate({tzOffset: -437.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -437.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -437.333333333333, tzAbbr: "LMT"}, -1946186241000, tz, 1);
+		doh.checkDate({tzOffset: -437.333333333333, tzAbbr: "PMT"}, -1946186240000, tz, 1);
+		doh.checkDate({tzOffset: -437.333333333333, tzAbbr: "PMT"}, -1172906241000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -1172906240000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -881220601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -881220600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -766054801000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -766054800000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -683883001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WIT"}, -683883000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WIT"}, -620812801000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -620812800000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "WIT"}, -189415801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CIT"}, -189415800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CIT"}, 567964799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "WIT"}, 567964800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "WIT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "WIT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "WIT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "WIT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Pyongyang.json b/dojox/date/tests/tztests/tz_Asia-Pyongyang.json
new file mode 100644
index 0000000..e014498
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Pyongyang.json
@@ -0,0 +1,22 @@
+({
+	name: "date.timezone.Asia-Pyongyang",
+	runTest: function(t){
+		var tz = "Asia/Pyongyang";
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -2053931401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, -2053931400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, -1325494801000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -1325494800000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -1199262601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, -1199262600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, -498128401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KST"}, -498128400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KST"}, -264931201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, -264931200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Qatar.json b/dojox/date/tests/tztests/tz_Asia-Qatar.json
new file mode 100644
index 0000000..7b2e217
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Qatar.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Asia-Qatar",
+	runTest: function(t){
+		var tz = "Asia/Qatar";
+		doh.checkDate({tzOffset: -206.133333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -206.133333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -206.133333333333, tzAbbr: "LMT"}, -1577935569000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, -1577935568000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GST"}, 76190399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 76190400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Qyzylorda.json b/dojox/date/tests/tztests/tz_Asia-Qyzylorda.json
new file mode 100644
index 0000000..b825f07
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Qyzylorda.json
@@ -0,0 +1,112 @@
+({
+	name: "date.timezone.Asia-Qyzylorda",
+	runTest: function(t){
+		var tz = "Asia/Qyzylorda";
+		doh.checkDate({tzOffset: -261.866666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -261.866666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -261.866666666667, tzAbbr: "LMT"}, -1441167713000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KIZT"}, -1441167712000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KIZT"}, -1247544001000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, -1247544000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 354913199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 354913200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 370720799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZT"}, 370720800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZT"}, 386445599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 386445600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 402256799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 402256800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 417985199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 417985200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 433792799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 433792800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 449607599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 449607600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 465339599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 465339600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 481064399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 481064400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 496789199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 496789200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 512513999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 512514000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 528238799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 528238800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 543963599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 543963600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 559688399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 559688400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 575413199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 575413200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 591137999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 591138000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 606862799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 606862800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 622587599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 622587600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 638312399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 638312400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "KIZST"}, 654641999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 654642000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KIZT"}, 692823599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "QYZT"}, 692823600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "QYZT"}, 695768399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 695768400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 701801999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 701802000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 717523199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 717523200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 733262399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 733262400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 748987199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 748987200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 764711999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 764712000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 780436799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 780436800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 796161599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 796161600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 811886399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 811886400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 828215999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 828216000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 846359999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 846360000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 859665599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 859665600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 877809599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 877809600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 891115199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 891115200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 909259199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 909259200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 922564799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 922564800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 941313599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 941313600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 954014399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 954014400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 972763199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 972763200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 985463999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 985464000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 1004212799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 1004212800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 1017518399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 1017518400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 1035662399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 1035662400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 1048967999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 1048968000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 1067111999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 1067112000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 1080417599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 1080417600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "QYZST"}, 1099166399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 1099166400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -360, tzAbbr: "QYZT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Rangoon.json b/dojox/date/tests/tztests/tz_Asia-Rangoon.json
new file mode 100644
index 0000000..12fb842
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Rangoon.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Asia-Rangoon",
+	runTest: function(t){
+		var tz = "Asia/Rangoon";
+		doh.checkDate({tzOffset: -384.6, tzAbbr: "RMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -384.6, tzAbbr: "RMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -384.6, tzAbbr: "RMT"}, -1577946277000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "BURT"}, -1577946276000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "BURT"}, -873268201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -873268200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -778410001000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "MMT"}, -778410000000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "MMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "MMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "MMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -390, tzAbbr: "MMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Riyadh.json b/dojox/date/tests/tztests/tz_Asia-Riyadh.json
new file mode 100644
index 0000000..6c9f38e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Riyadh.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Asia-Riyadh",
+	runTest: function(t){
+		var tz = "Asia/Riyadh";
+		doh.checkDate({tzOffset: -186.866666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -186.866666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -186.866666666667, tzAbbr: "LMT"}, -631163213000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, -631163212000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Sakhalin.json b/dojox/date/tests/tztests/tz_Asia-Sakhalin.json
new file mode 100644
index 0000000..51668e1
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Sakhalin.json
@@ -0,0 +1,248 @@
+({
+	name: "date.timezone.Asia-Sakhalin",
+	runTest: function(t){
+		var tz = "Asia/Sakhalin";
+		doh.checkDate({tzOffset: -570.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -570.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -570.8, tzAbbr: "LMT"}, -2031039049000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CJT"}, -2031039048000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CJT"}, -1009875601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -1009875600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -768560401000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, -768560400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 354891599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 354891600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 370699199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 370699200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 386427599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 386427600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 402235199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 402235200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 417963599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 417963600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 433771199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 433771200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 449585999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 449586000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 465317999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 465318000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 481042799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 481042800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 496767599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 496767600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 512492399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 512492400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 528217199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 528217200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 543941999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 543942000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 559666799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 559666800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 575391599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 575391600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 591116399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 591116400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 606841199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 606841200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 622565999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 622566000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 638290799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 638290800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 654620399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 654620400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 670345199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 670345200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 686073599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 686073600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 695750399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 695750400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 701783999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 701784000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 717505199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 717505200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 733244399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 733244400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 748969199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 748969200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 764693999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 764694000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 780418799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 780418800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 796143599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 796143600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 811868399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 811868400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 828197999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 828198000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "SAKST"}, 846341999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 846342000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKT"}, 859647599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 859647600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 877795199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 877795200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 891100799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 891100800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 909244799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 909244800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 922550399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 922550400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 941299199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 941299200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 953999999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 954000000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 972748799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 972748800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 985449599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 985449600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1004198399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1004198400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1017503999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1017504000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1035647999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1035648000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1048953599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1048953600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1067097599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1067097600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1080403199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1080403200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1099151999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1099152000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1111852799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1111852800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1130601599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1130601600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1143302399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1143302400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1162051199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1162051200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1174751999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1174752000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1193500799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1193500800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1206806399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1206806400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1224950399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1224950400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1238255999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1238256000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1256399999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1256400000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1269705599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1269705600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1288454399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1288454400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1301155199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1301155200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1319903999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1319904000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1332604799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1332604800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1351353599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1351353600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1364659199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1364659200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1382803199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1382803200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1396108799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1396108800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1414252799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1414252800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1427558399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1427558400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1445702399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1445702400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1459007999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1459008000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1477756799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1477756800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1490457599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1490457600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1509206399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1509206400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1521907199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1521907200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1540655999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1540656000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1553961599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1553961600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1572105599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1572105600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1585411199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1585411200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1603555199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1603555200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1616860799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1616860800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1635609599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1635609600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1648310399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1648310400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1667059199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1667059200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1679759999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1679760000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1698508799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1698508800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1711814399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1711814400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1729958399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1729958400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1743263999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1743264000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1761407999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1761408000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1774713599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1774713600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1792857599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1792857600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1806163199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1806163200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1824911999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1824912000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1837612799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1837612800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1856361599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1856361600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1869062399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1869062400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1887811199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1887811200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1901116799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1901116800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1919260799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1919260800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1932566399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1932566400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1950710399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1950710400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1964015999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1964016000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1982764799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1982764800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1995465599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1995465600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 2014214399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 2014214400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 2026915199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 2026915200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 2045663999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 2045664000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 2058364799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 2058364800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 2077113599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 2077113600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 2090419199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 2090419200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 2108563199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 2108563200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 2121868799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 2121868800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 2140012799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 2140012800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "SAKT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SAKST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Samarkand.json b/dojox/date/tests/tztests/tz_Asia-Samarkand.json
new file mode 100644
index 0000000..5e74000
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Samarkand.json
@@ -0,0 +1,62 @@
+({
+	name: "date.timezone.Asia-Samarkand",
+	runTest: function(t){
+		var tz = "Asia/Samarkand";
+		doh.checkDate({tzOffset: -267.2, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -267.2, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -267.2, tzAbbr: "LMT"}, -1441168033000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, -1441168032000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, -1247544001000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, -1247544000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 354913199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 354913200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 370720799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 370720800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 386445599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 386445600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 402256799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 402256800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 417985199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 417985200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 433792799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 433792800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 449607599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 449607600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 465339599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 465339600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 481064399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 481064400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 496789199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 496789200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 512513999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 512514000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 528238799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 528238800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 543963599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 543963600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 559688399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 559688400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 575413199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 575413200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 591137999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 591138000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 606862799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 606862800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 622587599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 622587600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 638312399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 638312400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 654641999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 654642000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMT"}, 670366799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 670366800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SAMST"}, 683661599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "UZST"}, 683661600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "UZST"}, 686091599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "UZT"}, 686091600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "UZT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "UZT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "UZT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "UZT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Seoul.json b/dojox/date/tests/tztests/tz_Asia-Seoul.json
new file mode 100644
index 0000000..d95be34
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Seoul.json
@@ -0,0 +1,36 @@
+({
+	name: "date.timezone.Asia-Seoul",
+	runTest: function(t){
+		var tz = "Asia/Seoul";
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -2053931401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, -2053931400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, -1325494801000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -1325494800000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -1199262601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, -1199262600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, -498128401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KST"}, -498128400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KST"}, -303984001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KDT"}, -303984000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KDT"}, -293533201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KST"}, -293533200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "KST"}, -264931201000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -264931200000, tz, 1);
+		doh.checkDate({tzOffset: -510, tzAbbr: "KST"}, -39515401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, -39515400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 547570799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "KDT"}, 547570800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "KDT"}, 560872799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 560872800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 579020399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "KDT"}, 579020400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "KDT"}, 592322399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 592322400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -540, tzAbbr: "KST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Shanghai.json b/dojox/date/tests/tztests/tz_Asia-Shanghai.json
new file mode 100644
index 0000000..7c40aa8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Shanghai.json
@@ -0,0 +1,46 @@
+({
+	name: "date.timezone.Asia-Shanghai",
+	runTest: function(t){
+		var tz = "Asia/Shanghai";
+		doh.checkDate({tzOffset: -485.866666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -485.866666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -485.866666666667, tzAbbr: "LMT"}, -1325491553000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -1325491552000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -933494401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -933494400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -923130001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -923130000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -908784001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -908784000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -891594001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -891594000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 515519999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 515520000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 527007599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 527007600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 545155199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 545155200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 558457199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 558457200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 576604799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 576604800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 589906799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 589906800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 608659199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 608659200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 621961199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 621961200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 640108799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 640108800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 653410799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 653410800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 671558399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 671558400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 684860399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 684860400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Singapore.json b/dojox/date/tests/tztests/tz_Asia-Singapore.json
new file mode 100644
index 0000000..3247527
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Singapore.json
@@ -0,0 +1,28 @@
+({
+	name: "date.timezone.Asia-Singapore",
+	runTest: function(t){
+		var tz = "Asia/Singapore";
+		doh.checkDate({tzOffset: -415.416666666667, tzAbbr: "SMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -415.416666666667, tzAbbr: "SMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -415.416666666667, tzAbbr: "SMT"}, -2038200926000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "MALT"}, -2038200925000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "MALT"}, -1167634801000, tz, 1);
+		doh.checkDate({tzOffset: -440, tzAbbr: "MALST"}, -1167634800000, tz, 1);
+		doh.checkDate({tzOffset: -440, tzAbbr: "MALST"}, -1073028001000, tz, 1);
+		doh.checkDate({tzOffset: -440, tzAbbr: "MALT"}, -1073028000000, tz, 1);
+		doh.checkDate({tzOffset: -440, tzAbbr: "MALT"}, -894180001000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "MALT"}, -894180000000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "MALT"}, -879665401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -879665400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -767005201000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "MALT"}, -767005200000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "MALT"}, -138785401000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "SGT"}, -138785400000, tz, 1);
+		doh.checkDate({tzOffset: -450, tzAbbr: "SGT"}, 378664199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "SGT"}, 378664200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "SGT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "SGT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "SGT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "SGT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Taipei.json b/dojox/date/tests/tztests/tz_Asia-Taipei.json
new file mode 100644
index 0000000..752c57c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Taipei.json
@@ -0,0 +1,92 @@
+({
+	name: "date.timezone.Asia-Taipei",
+	runTest: function(t){
+		var tz = "Asia/Taipei";
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -778579201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -778579200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -765363601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -765363600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -747043201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -747043200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -733827601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -733827600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -715507201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -715507200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -702291601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -702291600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -683884801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -683884800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -670669201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -670669200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -652348801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -652348800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -639133201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -639133200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -620812801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -620812800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -607597201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -607597200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -589276801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -589276800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -576061201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -576061200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -562924801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -562924800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -541760401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -541760400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -528710401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -528710400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -510224401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -510224400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -497174401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -497174400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -478688401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -478688400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -465638401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -465638400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -449830801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -449830800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -434016001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -434016000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -418208401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -418208400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -402480001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -402480000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -386672401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -386672400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -370944001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -370944000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -355136401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -355136400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -339408001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -339408000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -323600401000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -323600400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -302515201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -302515200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -291978001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -291978000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -270979201000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -270979200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, -260442001000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, -260442000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 133977599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 133977600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 149785199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 149785200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 165513599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 165513600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 181321199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 181321200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 331142399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 331142400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 339087599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 339087600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Tashkent.json b/dojox/date/tests/tztests/tz_Asia-Tashkent.json
new file mode 100644
index 0000000..01951ef
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Tashkent.json
@@ -0,0 +1,62 @@
+({
+	name: "date.timezone.Asia-Tashkent",
+	runTest: function(t){
+		var tz = "Asia/Tashkent";
+		doh.checkDate({tzOffset: -277.2, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -277.2, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -277.2, tzAbbr: "LMT"}, -1441168633000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TAST"}, -1441168632000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TAST"}, -1247547601000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, -1247547600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 354909599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 354909600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 370717199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 370717200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 386445599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 386445600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 402253199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 402253200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 417981599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 417981600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 433789199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 433789200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 449603999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 449604000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 465335999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 465336000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 481060799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 481060800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 496785599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 496785600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 512510399000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 512510400000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 528235199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 528235200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 543959999000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 543960000000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 559684799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 559684800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 575409599000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 575409600000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 591134399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 591134400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 606859199000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 606859200000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 622583999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 622584000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 638308799000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 638308800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "TASST"}, 654638399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 654638400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TAST"}, 670363199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TASST"}, 670363200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "TASST"}, 683661599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "UZST"}, 683661600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "UZST"}, 686091599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "UZT"}, 686091600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "UZT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "UZT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "UZT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "UZT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Tbilisi.json b/dojox/date/tests/tztests/tz_Asia-Tbilisi.json
new file mode 100644
index 0000000..94c1ba8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Tbilisi.json
@@ -0,0 +1,114 @@
+({
+	name: "date.timezone.Asia-Tbilisi",
+	runTest: function(t){
+		var tz = "Asia/Tbilisi";
+		doh.checkDate({tzOffset: -179.266666666667, tzAbbr: "TBMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -179.266666666667, tzAbbr: "TBMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -179.266666666667, tzAbbr: "TBMT"}, -1441162757000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TBIT"}, -1441162756000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TBIT"}, -405140401000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, -405140400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 354916799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 354916800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 370724399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 370724400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 386452799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 386452800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 402260399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 402260400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 417988799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 417988800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 433796399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 433796400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 449611199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 449611200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 465343199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 465343200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 481067999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 481068000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 496792799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 496792800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 512517599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 512517600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 528242399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 528242400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 543967199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 543967200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 559691999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 559692000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 575416799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 575416800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 591141599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 591141600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 606866399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 606866400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 622591199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 622591200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 638315999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 638316000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TBIST"}, 654645599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 654645600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIT"}, 670370399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIST"}, 670370400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TBIST"}, 671140799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GEST"}, 671140800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GEST"}, 686098799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "GET"}, 686098800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "GET"}, 701816399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GEST"}, 701816400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GEST"}, 717537599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "GET"}, 717537600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "GET"}, 733265999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GEST"}, 733266000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GEST"}, 748987199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "GET"}, 748987200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "GET"}, 764715599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GEST"}, 764715600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GEST"}, 780436799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 780436800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 796161599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 796161600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 811882799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 811882800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 828215999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 828216000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 877805999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 877806000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 891115199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 891115200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 909255599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 909255600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 922564799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 922564800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 941309999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 941310000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 954014399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 954014400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 972759599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 972759600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 985463999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 985464000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 1004209199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 1004209200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 1017518399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 1017518400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 1035658799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 1035658800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 1048967999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 1048968000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 1067108399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 1067108400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 1080417599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 1080417600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "GEST"}, 1088276399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GEST"}, 1088276400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GEST"}, 1099177199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "GET"}, 1099177200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "GET"}, 1111877999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 1111878000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -240, tzAbbr: "GET"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Tehran.json b/dojox/date/tests/tztests/tz_Asia-Tehran.json
new file mode 100644
index 0000000..20dd4db
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Tehran.json
@@ -0,0 +1,212 @@
+({
+	name: "date.timezone.Asia-Tehran",
+	runTest: function(t){
+		var tz = "Asia/Tehran";
+		doh.checkDate({tzOffset: -205.733333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -205.733333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -205.733333333333, tzAbbr: "LMT"}, -1704165945000, tz, 1);
+		doh.checkDate({tzOffset: -205.733333333333, tzAbbr: "TMT"}, -1704165944000, tz, 1);
+		doh.checkDate({tzOffset: -205.733333333333, tzAbbr: "TMT"}, -757394745000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, -757394744000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 247177799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "IRST"}, 247177800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "IRST"}, 259271999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "IRDT"}, 259272000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "IRDT"}, 277757999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "IRST"}, 277758000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "IRST"}, 283982399000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 283982400000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 290809799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 290809800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 306530999000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 306531000000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 322432199000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 322432200000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 338498999000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 338499000000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 673216199000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 673216200000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 685481399000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 685481400000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 701209799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 701209800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 717103799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 717103800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 732745799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 732745800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 748639799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 748639800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 764281799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 764281800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 780175799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 780175800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 795817799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 795817800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 811711799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 811711800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 827353799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 827353800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 843247799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 843247800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 858976199000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 858976200000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 874870199000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 874870200000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 890512199000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 890512200000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 906406199000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 906406200000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 922048199000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 922048200000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 937942199000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 937942200000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 953584199000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 953584200000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 969478199000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 969478200000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 985206599000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 985206600000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1001100599000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1001100600000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1016742599000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1016742600000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1032636599000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1032636600000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1048278599000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1048278600000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1064172599000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1064172600000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1079814599000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1079814600000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1095708599000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1095708600000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1111436999000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1111437000000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1127330999000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1127331000000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1206044999000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1206045000000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1221938999000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1221939000000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1237667399000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1237667400000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1253561399000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1253561400000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1269203399000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1269203400000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1285097399000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1285097400000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1300739399000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1300739400000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1316633399000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1316633400000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1332275399000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1332275400000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1348169399000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1348169400000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1363897799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1363897800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1379791799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1379791800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1395433799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1395433800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1411327799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1411327800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1426969799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1426969800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1442863799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1442863800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1458505799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1458505800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1474399799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1474399800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1490128199000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1490128200000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1506022199000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1506022200000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1521664199000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1521664200000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1537558199000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1537558200000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1553200199000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1553200200000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1569094199000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1569094200000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1584736199000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1584736200000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1600630199000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1600630200000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1616358599000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1616358600000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1632252599000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1632252600000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1647894599000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1647894600000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1663788599000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1663788600000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1679430599000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1679430600000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1695324599000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1695324600000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1710966599000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1710966600000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1726860599000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1726860600000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1742588999000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1742589000000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1758482999000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1758483000000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1774124999000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1774125000000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1790018999000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1790019000000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1805660999000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1805661000000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1821554999000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1821555000000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1837196999000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1837197000000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1853090999000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1853091000000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1868732999000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1868733000000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1884626999000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1884627000000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1900355399000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1900355400000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1916249399000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1916249400000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1931891399000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1931891400000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1947785399000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1947785400000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1963427399000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1963427400000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1979321399000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1979321400000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1994963399000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1994963400000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 2010857399000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 2010857400000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 2026585799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 2026585800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 2042479799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 2042479800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 2058121799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 2058121800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 2074015799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 2074015800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 2089657799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 2089657800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 2105551799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 2105551800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 2121193799000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 2121193800000, tz, 1);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 2137087799000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 2137087800000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -210, tzAbbr: "IRST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -270, tzAbbr: "IRDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Thimphu.json b/dojox/date/tests/tztests/tz_Asia-Thimphu.json
new file mode 100644
index 0000000..4089553
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Thimphu.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Asia-Thimphu",
+	runTest: function(t){
+		var tz = "Asia/Thimphu";
+		doh.checkDate({tzOffset: -358.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -358.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -358.6, tzAbbr: "LMT"}, -706341517000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, -706341516000, tz, 1);
+		doh.checkDate({tzOffset: -330, tzAbbr: "IST"}, 560024999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "BTT"}, 560025000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "BTT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "BTT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "BTT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -360, tzAbbr: "BTT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Tokyo.json b/dojox/date/tests/tztests/tz_Asia-Tokyo.json
new file mode 100644
index 0000000..29ee51e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Tokyo.json
@@ -0,0 +1,30 @@
+({
+	name: "date.timezone.Asia-Tokyo",
+	runTest: function(t){
+		var tz = "Asia/Tokyo";
+		doh.checkDate({tzOffset: -540, tzAbbr: "CJT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CJT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CJT"}, -1009875601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -1009875600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -683794801000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "JDT"}, -683794800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "JDT"}, -672393601000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -672393600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -654764401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "JDT"}, -654764400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "JDT"}, -640944001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -640944000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -620290801000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "JDT"}, -620290800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "JDT"}, -609494401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -609494400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -588841201000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "JDT"}, -588841200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "JDT"}, -578044801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -578044800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Ulaanbaatar.json b/dojox/date/tests/tztests/tz_Asia-Ulaanbaatar.json
new file mode 100644
index 0000000..07eadb2
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Ulaanbaatar.json
@@ -0,0 +1,104 @@
+({
+	name: "date.timezone.Asia-Ulaanbaatar",
+	runTest: function(t){
+		var tz = "Asia/Ulaanbaatar";
+		doh.checkDate({tzOffset: -427.533333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -427.533333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -427.533333333333, tzAbbr: "LMT"}, -2032931253000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ULAT"}, -2032931252000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ULAT"}, 252435599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 252435600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 417974399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 417974400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 433781999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 433782000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 449596799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 449596800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 465317999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 465318000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 481046399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 481046400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 496767599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 496767600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 512495999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 512496000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 528217199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 528217200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 543945599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 543945600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 559666799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 559666800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 575395199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 575395200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 591116399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 591116400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 606844799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 606844800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 622565999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 622566000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 638294399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 638294400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 654620399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 654620400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 670348799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 670348800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 686069999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 686070000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 701798399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 701798400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 717519599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 717519600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 733247999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 733248000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 748969199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 748969200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 764697599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 764697600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 780418799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 780418800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 796147199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 796147200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 811868399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 811868400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 828201599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 828201600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 843922799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 843922800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 859651199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 859651200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 875372399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 875372400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 891100799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 891100800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 906821999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 906822000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 988394399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 988394400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 1001696399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1001696400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1017424799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 1017424800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 1033145999000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1033146000000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1048874399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 1048874400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 1064595599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1064595600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1080323999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 1080324000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 1096045199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1096045200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1111773599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 1111773600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 1127494799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1127494800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1143223199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 1143223200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "ULAST"}, 1159549199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1159549200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ULAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Urumqi.json b/dojox/date/tests/tztests/tz_Asia-Urumqi.json
new file mode 100644
index 0000000..1a955cb
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Urumqi.json
@@ -0,0 +1,40 @@
+({
+	name: "date.timezone.Asia-Urumqi",
+	runTest: function(t){
+		var tz = "Asia/Urumqi";
+		doh.checkDate({tzOffset: -350.333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -350.333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -350.333333333333, tzAbbr: "LMT"}, -1325483421000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URUT"}, -1325483420000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "URUT"}, 325965599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 325965600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 515519999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 515520000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 527007599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 527007600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 545155199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 545155200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 558457199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 558457200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 576604799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 576604800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 589906799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 589906800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 608659199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 608659200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 621961199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 621961200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 640108799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 640108800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 653410799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 653410800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 671558399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 671558400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "CDT"}, 684860399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 684860400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Vientiane.json b/dojox/date/tests/tztests/tz_Asia-Vientiane.json
new file mode 100644
index 0000000..db0b772
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Vientiane.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.Asia-Vientiane",
+	runTest: function(t){
+		var tz = "Asia/Vientiane";
+		doh.checkDate({tzOffset: -410.4, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -410.4, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -410.4, tzAbbr: "LMT"}, -2005973425000, tz, 1);
+		doh.checkDate({tzOffset: -426.333333333333, tzAbbr: "SMT"}, -2005973424000, tz, 1);
+		doh.checkDate({tzOffset: -426.333333333333, tzAbbr: "SMT"}, -1855983921000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, -1855983920000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, -1819954801000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ICT"}, -1819954800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "ICT"}, -1220428801000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, -1220428800000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "ICT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Vladivostok.json b/dojox/date/tests/tztests/tz_Asia-Vladivostok.json
new file mode 100644
index 0000000..e9bb852
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Vladivostok.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.Asia-Vladivostok",
+	runTest: function(t){
+		var tz = "Asia/Vladivostok";
+		doh.checkDate({tzOffset: -527.733333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -527.733333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -527.733333333333, tzAbbr: "LMT"}, -1487321265000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "VLAT"}, -1487321264000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "VLAT"}, -1247562001000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, -1247562000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 354895199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 354895200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 370702799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 370702800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 386431199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 386431200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 402238799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 402238800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 417967199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 417967200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 433774799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 433774800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 449589599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 449589600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 465321599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 465321600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 481046399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 481046400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 496771199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 496771200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 512495999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 512496000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 528220799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 528220800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 543945599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 543945600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 559670399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 559670400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 575395199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 575395200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 591119999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 591120000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 606844799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 606844800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 622569599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 622569600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 638294399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 638294400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 654623999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 654624000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 670348799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLASST"}, 670348800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLASST"}, 686077199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "VLAST"}, 686077200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "VLAST"}, 695753999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 695754000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 701787599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 701787600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 717508799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 717508800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 733247999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 733248000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 748972799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 748972800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 764697599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 764697600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 780422399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 780422400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 796147199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 796147200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 811871999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 811872000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 828201599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 828201600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 846345599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 846345600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 859651199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 859651200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 877795199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 877795200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 891100799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 891100800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 909244799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 909244800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 922550399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 922550400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 941299199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 941299200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 953999999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 954000000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 972748799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 972748800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 985449599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 985449600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1004198399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1004198400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1017503999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1017504000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1035647999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1035648000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1048953599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1048953600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1067097599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1067097600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1080403199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1080403200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1099151999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1099152000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1111852799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1111852800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1130601599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1130601600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1143302399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1143302400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1162051199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1162051200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1174751999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1174752000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1193500799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1193500800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1206806399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1206806400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1224950399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1224950400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1238255999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1238256000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1256399999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1256400000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1269705599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1269705600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1288454399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1288454400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1301155199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1301155200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1319903999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1319904000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1332604799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1332604800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1351353599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1351353600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1364659199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1364659200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1382803199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1382803200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1396108799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1396108800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1414252799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1414252800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1427558399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1427558400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1445702399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1445702400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1459007999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1459008000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1477756799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1477756800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1490457599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1490457600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1509206399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1509206400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1521907199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1521907200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1540655999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1540656000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1553961599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1553961600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1572105599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1572105600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1585411199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1585411200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1603555199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1603555200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1616860799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1616860800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1635609599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1635609600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1648310399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1648310400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1667059199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1667059200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1679759999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1679760000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1698508799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1698508800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1711814399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1711814400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1729958399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1729958400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1743263999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1743264000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1761407999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1761408000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1774713599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1774713600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1792857599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1792857600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1806163199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1806163200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1824911999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1824912000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1837612799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1837612800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1856361599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1856361600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1869062399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1869062400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1887811199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1887811200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1901116799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1901116800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1919260799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1919260800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1932566399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1932566400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1950710399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1950710400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1964015999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1964016000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1982764799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1982764800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1995465599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1995465600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 2014214399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 2014214400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 2026915199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 2026915200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 2045663999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 2045664000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 2058364799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 2058364800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 2077113599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 2077113600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 2090419199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 2090419200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 2108563199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 2108563200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 2121868799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 2121868800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 2140012799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 2140012800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "VLAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VLAST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Yakutsk.json b/dojox/date/tests/tztests/tz_Asia-Yakutsk.json
new file mode 100644
index 0000000..e8215ca
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Yakutsk.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.Asia-Yakutsk",
+	runTest: function(t){
+		var tz = "Asia/Yakutsk";
+		doh.checkDate({tzOffset: -518.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -518.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -518.666666666667, tzAbbr: "LMT"}, -1579423121000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "YAKT"}, -1579423120000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "YAKT"}, -1247558401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, -1247558400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 354898799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 354898800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 370706399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 370706400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 386434799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 386434800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 402242399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 402242400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 417970799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 417970800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 433778399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 433778400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 449593199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 449593200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 465325199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 465325200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 481049999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 481050000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 496774799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 496774800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 512499599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 512499600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 528224399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 528224400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 543949199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 543949200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 559673999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 559674000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 575398799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 575398800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 591123599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 591123600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 606848399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 606848400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 622573199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 622573200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 638297999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 638298000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 654627599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 654627600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 670352399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKST"}, 670352400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKST"}, 686080799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "YAKT"}, 686080800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "YAKT"}, 695757599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 695757600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 701791199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 701791200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 717512399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 717512400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 733251599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 733251600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 748976399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 748976400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 764701199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 764701200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 780425999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 780426000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 796150799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 796150800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 811875599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 811875600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 828205199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 828205200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 846349199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 846349200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 859654799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 859654800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 877798799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 877798800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 891104399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 891104400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 909248399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 909248400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 922553999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 922554000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 941302799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 941302800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 954003599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 954003600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 972752399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 972752400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 985453199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 985453200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1004201999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1004202000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1017507599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1017507600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1035651599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1035651600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1048957199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1048957200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1067101199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1067101200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1080406799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1080406800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1099155599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1099155600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1111856399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1111856400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1130605199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1130605200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1143305999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1143306000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1162054799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1162054800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1174755599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1174755600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1193504399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1193504400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1206809999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1206810000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1224953999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1224954000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1238259599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1238259600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1256403599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1256403600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1269709199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1269709200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1288457999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1288458000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1301158799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1301158800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1319907599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1319907600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1332608399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1332608400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1351357199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1351357200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1364662799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1364662800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1382806799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1382806800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1396112399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1396112400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1414256399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1414256400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1427561999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1427562000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1445705999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1445706000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1459011599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1459011600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1477760399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1477760400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1490461199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1490461200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1509209999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1509210000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1521910799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1521910800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1540659599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1540659600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1553965199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1553965200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1572109199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1572109200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1585414799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1585414800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1603558799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1603558800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1616864399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1616864400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1635613199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1635613200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1648313999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1648314000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1667062799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1667062800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1679763599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1679763600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1698512399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1698512400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1711817999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1711818000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1729961999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1729962000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1743267599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1743267600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1761411599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1761411600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1774717199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1774717200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1792861199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1792861200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1806166799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1806166800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1824915599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1824915600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1837616399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1837616400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1856365199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1856365200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1869065999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1869066000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1887814799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1887814800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1901120399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1901120400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1919264399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1919264400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1932569999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1932570000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1950713999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1950714000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1964019599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1964019600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1982768399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1982768400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1995469199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1995469200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 2014217999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 2014218000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 2026918799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 2026918800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 2045667599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 2045667600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 2058368399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 2058368400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 2077117199000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 2077117200000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 2090422799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 2090422800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 2108566799000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 2108566800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 2121872399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 2121872400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 2140016399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 2140016400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "YAKT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "YAKST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Yekaterinburg.json b/dojox/date/tests/tztests/tz_Asia-Yekaterinburg.json
new file mode 100644
index 0000000..416ef16
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Yekaterinburg.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.Asia-Yekaterinburg",
+	runTest: function(t){
+		var tz = "Asia/Yekaterinburg";
+		doh.checkDate({tzOffset: -242.4, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -242.4, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -242.4, tzAbbr: "LMT"}, -1592611345000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SVET"}, -1592611344000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SVET"}, -1247544001000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, -1247544000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 354913199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 354913200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 370720799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 370720800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 386449199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 386449200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 402256799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 402256800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 417985199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 417985200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 433792799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 433792800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 449607599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 449607600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 465339599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 465339600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 481064399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 481064400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 496789199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 496789200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 512513999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 512514000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 528238799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 528238800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 543963599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 543963600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 559688399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 559688400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 575413199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 575413200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 591137999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 591138000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 606862799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 606862800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 622587599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 622587600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 638312399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 638312400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "SVEST"}, 654641999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 654642000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVET"}, 670366799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVEST"}, 670366800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SVEST"}, 686095199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SVET"}, 686095200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SVET"}, 695771999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 695772000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 701805599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 701805600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 717526799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 717526800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 733265999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 733266000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 748990799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 748990800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 764715599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 764715600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 780440399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 780440400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 796165199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 796165200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 811889999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 811890000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 828219599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 828219600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 846363599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 846363600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 859669199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 859669200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 877813199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 877813200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 891118799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 891118800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 909262799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 909262800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 922568399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 922568400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 941317199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 941317200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 954017999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 954018000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 972766799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 972766800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 985467599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 985467600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1004216399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1004216400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1017521999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1017522000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1035665999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1035666000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1048971599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1048971600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1067115599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1067115600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1080421199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1080421200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1099169999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1099170000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1111870799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1111870800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1130619599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1130619600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1143320399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1143320400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1162069199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1162069200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1174769999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1174770000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1193518799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1193518800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1206824399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1206824400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1224968399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1224968400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1238273999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1238274000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1256417999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1256418000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1269723599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1269723600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1288472399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1288472400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1301173199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1301173200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1319921999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1319922000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1332622799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1332622800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1351371599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1351371600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1364677199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1364677200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1382821199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1382821200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1396126799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1396126800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1414270799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1414270800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1427576399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1427576400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1445720399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1445720400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1459025999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1459026000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1477774799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1477774800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1490475599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1490475600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1509224399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1509224400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1521925199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1521925200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1540673999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1540674000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1553979599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1553979600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1572123599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1572123600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1585429199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1585429200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1603573199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1603573200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1616878799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1616878800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1635627599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1635627600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1648328399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1648328400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1667077199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1667077200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1679777999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1679778000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1698526799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1698526800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1711832399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1711832400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1729976399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1729976400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1743281999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1743282000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1761425999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1761426000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1774731599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1774731600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1792875599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1792875600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1806181199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1806181200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1824929999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1824930000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1837630799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1837630800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1856379599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1856379600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1869080399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1869080400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1887829199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1887829200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1901134799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1901134800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1919278799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1919278800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1932584399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1932584400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1950728399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1950728400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1964033999000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1964034000000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1982782799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1982782800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1995483599000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1995483600000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 2014232399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 2014232400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 2026933199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 2026933200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 2045681999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 2045682000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 2058382799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 2058382800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 2077131599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 2077131600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 2090437199000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 2090437200000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 2108581199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 2108581200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 2121886799000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 2121886800000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 2140030799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 2140030800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YEKT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -360, tzAbbr: "YEKST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Asia-Yerevan.json b/dojox/date/tests/tztests/tz_Asia-Yerevan.json
new file mode 100644
index 0000000..0862c60
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Asia-Yerevan.json
@@ -0,0 +1,242 @@
+({
+	name: "date.timezone.Asia-Yerevan",
+	runTest: function(t){
+		var tz = "Asia/Yerevan";
+		doh.checkDate({tzOffset: -178, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -178, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -178, tzAbbr: "LMT"}, -1441162681000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "YERT"}, -1441162680000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "YERT"}, -405140401000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, -405140400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 354916799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 354916800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 370724399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 370724400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 386452799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 386452800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 402260399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 402260400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 417988799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 417988800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 433796399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 433796400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 449611199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 449611200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 465343199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 465343200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 481067999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 481068000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 496792799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 496792800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 512517599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 512517600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 528242399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 528242400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 543967199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 543967200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 559691999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 559692000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 575416799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 575416800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 591141599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 591141600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 606866399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 606866400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 622591199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 622591200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 638315999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 638316000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "YERST"}, 654645599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 654645600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERT"}, 670370399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERST"}, 670370400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "YERST"}, 685569599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMST"}, 685569600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMST"}, 686098799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AMT"}, 686098800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AMT"}, 701812799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMST"}, 701812800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMST"}, 717533999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AMT"}, 717534000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AMT"}, 733273199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMST"}, 733273200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMST"}, 748997999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AMT"}, 748998000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AMT"}, 764722799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMST"}, 764722800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMST"}, 780447599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AMT"}, 780447600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "AMT"}, 796172399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMST"}, 796172400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMST"}, 811897199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 811897200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 859672799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 859672800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 877816799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 877816800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 891122399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 891122400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 909266399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 909266400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 922571999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 922572000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 941320799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 941320800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 954021599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 954021600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 972770399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 972770400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 985471199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 985471200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1004219999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1004220000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1017525599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1017525600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1035669599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1035669600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1048975199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1048975200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1067119199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1067119200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1080424799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1080424800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1099173599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1099173600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1111874399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1111874400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1130623199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1130623200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1143323999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1143324000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1162072799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1162072800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1174773599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1174773600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1193522399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1193522400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1206827999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1206828000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1224971999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1224972000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1238277599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1238277600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1256421599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1256421600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1269727199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1269727200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1288475999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1288476000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1301176799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1301176800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1319925599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1319925600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1332626399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1332626400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1351375199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1351375200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1364680799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1364680800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1382824799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1382824800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1396130399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1396130400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1414274399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1414274400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1427579999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1427580000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1445723999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1445724000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1459029599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1459029600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1477778399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1477778400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1490479199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1490479200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1509227999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1509228000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1521928799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1521928800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1540677599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1540677600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1553983199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1553983200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1572127199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1572127200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1585432799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1585432800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1603576799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1603576800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1616882399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1616882400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1635631199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1635631200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1648331999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1648332000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1667080799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1667080800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1679781599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1679781600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1698530399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1698530400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1711835999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1711836000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1729979999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1729980000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1743285599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1743285600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1761429599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1761429600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1774735199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1774735200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1792879199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1792879200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1806184799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1806184800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1824933599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1824933600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1837634399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1837634400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1856383199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1856383200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1869083999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1869084000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1887832799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1887832800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1901138399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1901138400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1919282399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1919282400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1932587999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1932588000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1950731999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1950732000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1964037599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1964037600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1982786399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1982786400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1995487199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1995487200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 2014235999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 2014236000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 2026936799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 2026936800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 2045685599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 2045685600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 2058386399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 2058386400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 2077135199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 2077135200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 2090440799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 2090440800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 2108584799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 2108584800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 2121890399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 2121890400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 2140034399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 2140034400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "AMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "AMST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Atlantic-Azores.json b/dojox/date/tests/tztests/tz_Atlantic-Azores.json
new file mode 100644
index 0000000..0dda93a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Atlantic-Azores.json
@@ -0,0 +1,452 @@
+({
+	name: "date.timezone.Atlantic-Azores",
+	runTest: function(t){
+		var tz = "Atlantic/Azores";
+		doh.checkDate({tzOffset: 114.533333333333, tzAbbr: "HMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 114.533333333333, tzAbbr: "HMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 114.533333333333, tzAbbr: "HMT"}, -1849557929000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1849557928000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1689548401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1689548400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1677794401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1677794400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1667430001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1667430000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1647730801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1647730800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1635807601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1635807600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1616194801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1616194800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1604358001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1604358000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1584658801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1584658800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1572735601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1572735600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1553036401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1553036400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1541199601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1541199600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1521500401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1521500400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1442444401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1442444400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1426806001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1426806000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1379286001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1379286000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1364770801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1364770800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1348441201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1348441200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1333321201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1333321200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1316386801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1316386800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1301266801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1301266800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1284332401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1284332400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1269817201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1269817200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1221433201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1221433200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1206918001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1206918000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1191193201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1191193200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1175468401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1175468400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1127689201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1127689200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1111964401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1111964400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1096844401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1096844400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1080514801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1080514800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1063580401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1063580400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1049065201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1049065200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1033340401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1033340400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1017615601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1017615600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -1002495601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -1002495600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -986166001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -986166000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -969231601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -969231600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -950482801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -950482800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -942015601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -942015600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -922662001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -922662000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -906937201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -906937200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -891126001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -891126000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -877302001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -877302000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -873676801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOMT"}, -873676800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOMT"}, -864000001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -864000000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -857948401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -857948400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -845852401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -845852400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -842832001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOMT"}, -842832000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOMT"}, -831340801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -831340800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -825894001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -825894000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -814402801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -814402800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -810777601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOMT"}, -810777600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOMT"}, -799891201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -799891200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -794444401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -794444400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -782953201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -782953200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -779328001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOMT"}, -779328000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOMT"}, -768441601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -768441600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -762994801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -762994800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -749084401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -749084400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -733359601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -733359600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -717624001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -717624000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -701899201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -701899200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -686174401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -686174400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -670449601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -670449600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -654724801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -654724800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -639000001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -639000000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -591825601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -591825600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -575496001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -575496000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -559771201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -559771200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -544046401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -544046400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -528321601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -528321600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -512596801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -512596800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -496872001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -496872000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -481147201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -481147200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -465422401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -465422400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -449697601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -449697600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -433972801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -433972800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -417643201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -417643200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -401918401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -401918400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -386193601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -386193600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -370468801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -370468800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -354744001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -354744000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -339019201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -339019200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -323294401000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -323294400000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -307569601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -307569600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -291844801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -291844800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -276120001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -276120000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -260395201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -260395200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -244670401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -244670400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -228340801000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -228340800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -212616001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -212616000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -196891201000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -196891200000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -181166401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -181166400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -165441601000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -165441600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -149716801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -149716800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOST"}, -133992001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -133992000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "AZOT"}, -118267201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, -118267200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 228272399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 228272400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 243997199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 243997200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 260326799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 260326800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 276051599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 276051600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 307504799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 307504800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 323225999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 323226000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 338954399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 338954400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 354679199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 354679200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 370403999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 370404000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 386128799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 386128800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 401853599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 401853600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 417581999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 417582000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 433303199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 433303200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 449027999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 449028000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 465357599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 465357600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 481082399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 481082400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 496807199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 496807200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 512531999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 512532000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 528256799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 528256800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 543981599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 543981600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 559706399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 559706400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 575431199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 575431200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 591155999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 591156000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 606880799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 606880800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 622605599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 622605600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 638330399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 638330400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 654659999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 654660000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 670384799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 670384800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 686109599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 686109600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 701834399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 701834400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 717559199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 717559200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "AZOT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "AZOST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Atlantic-Bermuda.json b/dojox/date/tests/tztests/tz_Atlantic-Bermuda.json
new file mode 100644
index 0000000..913006b
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Atlantic-Bermuda.json
@@ -0,0 +1,270 @@
+({
+	name: "date.timezone.Atlantic-Bermuda",
+	runTest: function(t){
+		var tz = "Atlantic/Bermuda";
+		doh.checkDate({tzOffset: 259.066666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 259.066666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 259.066666666667, tzAbbr: "LMT"}, -1262281257000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, -1262281256000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 136360799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 136360800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 152081999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 152082000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 167810399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 167810400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 183531599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 183531600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 199259999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 199260000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 215585999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 215586000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 230709599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 230709600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 247035599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 247035600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 262763999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 262764000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 278485199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 278485200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 294213599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 294213600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 309934799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 309934800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 325663199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 325663200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 341384399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 341384400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 357112799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 357112800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 372833999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 372834000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 388562399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 388562400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 404888399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 404888400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 420011999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 420012000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 436337999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 436338000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 452066399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 452066400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 467787599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 467787600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 483515999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 483516000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 499237199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 499237200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 514965599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 514965600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 530686799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 530686800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 544600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 544600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 562136399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 562136400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 576050399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 576050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 594190799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 594190800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 607499999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 607500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 625640399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 625640400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 638949599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 638949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 657089999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 657090000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 671003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 671004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 688539599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 688539600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 702453599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 702453600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 719989199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 719989200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 733903199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 733903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 752043599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 752043600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 765352799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 765352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 783493199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 783493200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 796802399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 796802400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 814942799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 814942800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 828856799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 828856800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 846392399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 846392400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 860306399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 860306400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 877841999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 877842000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 891755999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 891756000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 909291599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 909291600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 923205599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 923205600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 941345999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 941346000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 954655199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 954655200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 972795599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 972795600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 986104799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 986104800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1004245199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1004245200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1018159199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1018159200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1035694799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1035694800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1049608799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1049608800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1067144399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1067144400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1081058399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1081058400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1099198799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1099198800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1112507999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1112508000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1130648399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1130648400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1143957599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1143957600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1162097999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1162098000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1173592799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1173592800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1194152399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1194152400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1205042399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1205042400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1225601999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1225602000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1236491999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1236492000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1257051599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1257051600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1268546399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1268546400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1289105999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1289106000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1299995999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1299996000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1320555599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1320555600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1331445599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1331445600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1352005199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1352005200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1362895199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1362895200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1383454799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1383454800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1394344799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1394344800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1414904399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1414904400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1425794399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1425794400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1446353999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1446354000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1457848799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1457848800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1478408399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1478408400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1489298399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1489298400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1509857999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1509858000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1520747999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1520748000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1541307599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1541307600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1552197599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1552197600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1572757199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1572757200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1583647199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1583647200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1604206799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1604206800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1615701599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1615701600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1636261199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1636261200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1647151199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1647151200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1667710799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1667710800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1678600799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1678600800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1699160399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1699160400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1710050399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1710050400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1730609999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1730610000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1741499999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1741500000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1762059599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1762059600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1772949599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1772949600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1793509199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1793509200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1805003999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1805004000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1825563599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1825563600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1836453599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1836453600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1857013199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1857013200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1867903199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1867903200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1888462799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1888462800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1899352799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1899352800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1919912399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1919912400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1930802399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1930802400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1951361999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1951362000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1962856799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1962856800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1983416399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1983416400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1994306399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1994306400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2014865999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2014866000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2025755999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2025756000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2046315599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2046315600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2057205599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2057205600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2077765199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2077765200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2088655199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2088655200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2109214799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2109214800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2120104799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2120104800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 2140664399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2140664400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "AST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 180, tzAbbr: "ADT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Atlantic-Canary.json b/dojox/date/tests/tztests/tz_Atlantic-Canary.json
new file mode 100644
index 0000000..9864c82
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Atlantic-Canary.json
@@ -0,0 +1,248 @@
+({
+	name: "date.timezone.Atlantic-Canary",
+	runTest: function(t){
+		var tz = "Atlantic/Canary";
+		doh.checkDate({tzOffset: 61.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 61.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 61.6, tzAbbr: "LMT"}, -1509663505000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "CANT"}, -1509663504000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "CANT"}, -733874401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -733874400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 323827199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 323827200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Atlantic-Cape_Verde.json b/dojox/date/tests/tztests/tz_Atlantic-Cape_Verde.json
new file mode 100644
index 0000000..5725c9d
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Atlantic-Cape_Verde.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.Atlantic-Cape_Verde",
+	runTest: function(t){
+		var tz = "Atlantic/Cape_Verde";
+		doh.checkDate({tzOffset: 94.0666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 94.0666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 94.0666666666667, tzAbbr: "LMT"}, -1988144757000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "CVT"}, -1988144756000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "CVT"}, -862610401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "CVST"}, -862610400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "CVST"}, -764118001000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "CVT"}, -764118000000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "CVT"}, 186119999000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "CVT"}, 186120000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "CVT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "CVT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "CVT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 60, tzAbbr: "CVT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Atlantic-Faroe.json b/dojox/date/tests/tztests/tz_Atlantic-Faroe.json
new file mode 100644
index 0000000..47fdaa0
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Atlantic-Faroe.json
@@ -0,0 +1,242 @@
+({
+	name: "date.timezone.Atlantic-Faroe",
+	runTest: function(t){
+		var tz = "Atlantic/Faroe";
+		doh.checkDate({tzOffset: 27.0666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 27.0666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 27.0666666666667, tzAbbr: "LMT"}, -1955748777000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1955748776000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Atlantic-Madeira.json b/dojox/date/tests/tztests/tz_Atlantic-Madeira.json
new file mode 100644
index 0000000..4da1c45
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Atlantic-Madeira.json
@@ -0,0 +1,452 @@
+({
+	name: "date.timezone.Atlantic-Madeira",
+	runTest: function(t){
+		var tz = "Atlantic/Madeira";
+		doh.checkDate({tzOffset: 67.6, tzAbbr: "FMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 67.6, tzAbbr: "FMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 67.6, tzAbbr: "FMT"}, -1849560745000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1849560744000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1689552001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1689552000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1677798001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1677798000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1667433601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1667433600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1647734401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1647734400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1635811201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1635811200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1616198401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1616198400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1604361601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1604361600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1584662401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1584662400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1572739201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1572739200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1553040001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1553040000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1541203201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1541203200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1521504001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1521504000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1442448001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1442448000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1426809601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1426809600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1379289601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1379289600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1364774401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1364774400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1348444801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1348444800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1333324801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1333324800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1316390401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1316390400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1301270401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1301270400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1284336001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1284336000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1269820801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1269820800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1221436801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1221436800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1206921601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1206921600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1191196801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1191196800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1175472001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1175472000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1127692801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1127692800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1111968001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1111968000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1096848001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1096848000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1080518401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1080518400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1063584001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1063584000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1049068801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1049068800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1033344001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1033344000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1017619201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1017619200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -1002499201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -1002499200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -986169601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -986169600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -969235201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -969235200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -950486401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -950486400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -942019201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -942019200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -922665601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -922665600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -906940801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -906940800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -891129601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -891129600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -877305601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -877305600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -873680401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MADMT"}, -873680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MADMT"}, -864003601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -864003600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -857952001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -857952000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -845856001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -845856000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -842835601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MADMT"}, -842835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MADMT"}, -831344401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -831344400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -825897601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -825897600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -814406401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -814406400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -810781201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MADMT"}, -810781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MADMT"}, -799894801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -799894800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -794448001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -794448000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -782956801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -782956800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -779331601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MADMT"}, -779331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MADMT"}, -768445201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -768445200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -762998401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -762998400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -749088001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -749088000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -733363201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -733363200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -717627601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -717627600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -701902801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -701902800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -686178001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -686178000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -670453201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -670453200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -654728401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -654728400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -639003601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -639003600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -591829201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -591829200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -575499601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -575499600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -559774801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -559774800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -544050001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -544050000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -528325201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -528325200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -512600401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -512600400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -496875601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -496875600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -481150801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -481150800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -465426001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -465426000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -449701201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -449701200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -433976401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -433976400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -417646801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -417646800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -401922001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -401922000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -386197201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -386197200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -370472401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -370472400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -354747601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -354747600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -339022801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -339022800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -323298001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -323298000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -307573201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -307573200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -291848401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -291848400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -276123601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -276123600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -260398801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -260398800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -244674001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -244674000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -228344401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -228344400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -212619601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -212619600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -196894801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -196894800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -181170001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -181170000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -165445201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -165445200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -149720401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -149720400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "MADST"}, -133995601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -133995600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "MADT"}, -118270801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -118270800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 228268799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 228268800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 243993599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 243993600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 260323199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 260323200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 276047999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 276048000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 291772799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 291772800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 323222399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 323222400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 417578399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 417578400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Atlantic-Reykjavik.json b/dojox/date/tests/tztests/tz_Atlantic-Reykjavik.json
new file mode 100644
index 0000000..ab3d5a6
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Atlantic-Reykjavik.json
@@ -0,0 +1,140 @@
+({
+	name: "date.timezone.Atlantic-Reykjavik",
+	runTest: function(t){
+		var tz = "Atlantic/Reykjavik";
+		doh.checkDate({tzOffset: 87.8, tzAbbr: "RMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 87.8, tzAbbr: "RMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 87.8, tzAbbr: "RMT"}, -1956609133000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -1956609132000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -1668211201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -1668211200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -1647212401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -1647212400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -1636675201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -1636675200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -1613430001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -1613430000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -968025601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -968025600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -949615201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -949615200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -942008401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -942008400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -920239201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -920239200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -909957601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -909957600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -888789601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -888789600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -877903201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -877903200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -857944801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -857944800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -846453601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -846453600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -826495201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -826495200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -815004001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -815004000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -795045601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -795045600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -783554401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -783554400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -762991201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -762991200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -752104801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -752104800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -731541601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -731541600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -717631201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -717631200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -700092001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -700092000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -686181601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -686181600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -668642401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -668642400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -654732001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -654732000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -636588001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -636588000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -623282401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -623282400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -605743201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -605743200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -591832801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -591832800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -573688801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -573688800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -559778401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -559778400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -542239201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -542239200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -528328801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -528328800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -510789601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -510789600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -496879201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -496879200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -479340001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -479340000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -465429601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -465429600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -447890401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -447890400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -433980001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -433980000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -415836001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -415836000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -401925601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -401925600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -384386401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -384386400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -370476001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -370476000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -352936801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -352936800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -339026401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -339026400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -321487201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -321487200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -307576801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -307576800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -290037601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -290037600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -276127201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -276127200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -258588001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -258588000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -244677601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -244677600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -226533601000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -226533600000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -212623201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -212623200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -195084001000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -195084000000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -181173601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -181173600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -163634401000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -163634400000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -149724001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -149724000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -132184801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -132184800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -118274401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -118274400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -100735201000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -100735200000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -86824801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -86824800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "ISST"}, -68680801000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -68680800000, tz, 1);
+		doh.checkDate({tzOffset: 60, tzAbbr: "IST"}, -54770401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -54770400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Atlantic-South_Georgia.json b/dojox/date/tests/tztests/tz_Atlantic-South_Georgia.json
new file mode 100644
index 0000000..a84a167
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Atlantic-South_Georgia.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Atlantic-South_Georgia",
+	runTest: function(t){
+		var tz = "Atlantic/South_Georgia";
+		doh.checkDate({tzOffset: 120, tzAbbr: "GST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "GST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "GST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "GST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "GST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 120, tzAbbr: "GST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Atlantic-St_Helena.json b/dojox/date/tests/tztests/tz_Atlantic-St_Helena.json
new file mode 100644
index 0000000..b32e460
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Atlantic-St_Helena.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Atlantic-St_Helena",
+	runTest: function(t){
+		var tz = "Atlantic/St_Helena";
+		doh.checkDate({tzOffset: 22.8, tzAbbr: "JMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 22.8, tzAbbr: "JMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 22.8, tzAbbr: "JMT"}, -599614633000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -599614632000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Atlantic-Stanley.json b/dojox/date/tests/tztests/tz_Atlantic-Stanley.json
new file mode 100644
index 0000000..610184b
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Atlantic-Stanley.json
@@ -0,0 +1,258 @@
+({
+	name: "date.timezone.Atlantic-Stanley",
+	runTest: function(t){
+		var tz = "Atlantic/Stanley";
+		doh.checkDate({tzOffset: 231.4, tzAbbr: "SMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 231.4, tzAbbr: "SMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 231.4, tzAbbr: "SMT"}, -1824235717000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -1824235716000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -1018209601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -1018209600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -1003093201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -1003093200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -986760001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -986760000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -971643601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -971643600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -954705601000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -954705600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -939589201000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -939589200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -923256001000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -923256000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -908139601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -908139600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -891806401000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -891806400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -876690001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -876690000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -860356801000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -860356800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, -852066001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, -852066000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 420609599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKT"}, 420609600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKT"}, 433306799000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FKST"}, 433306800000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FKST"}, 452051999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKT"}, 452052000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKT"}, 464151599000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FKST"}, 464151600000, tz, 1);
+		doh.checkDate({tzOffset: 120, tzAbbr: "FKST"}, 483501599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKT"}, 483501600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKT"}, 495601199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 495601200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 514349999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 514350000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 527054399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 527054400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 545799599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 545799600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 558503999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 558504000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 577249199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 577249200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 589953599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 589953600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 608698799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 608698800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 621403199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 621403200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 640753199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 640753200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 652852799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 652852800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 672202799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 672202800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 684907199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 684907200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 703652399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 703652400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 716356799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 716356800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 735101999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 735102000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 747806399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 747806400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 766551599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 766551600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 779255999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 779256000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 798001199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 798001200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 810705599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 810705600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 830055599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 830055600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 842759999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 842760000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 861505199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 861505200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 874209599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 874209600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 892954799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 892954800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 905659199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 905659200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 924404399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 924404400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 937108799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 937108800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 955853999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 955854000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 968558399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 968558400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 987310799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 987310800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 999410399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 999410400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1019365199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1019365200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1030859999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1030860000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1050814799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1050814800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1062914399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1062914400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1082264399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1082264400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1094363999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1094364000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1113713999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1113714000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1125813599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1125813600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1145163599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1145163600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1157263199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1157263200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1176613199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1176613200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1188712799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1188712800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1208667599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1208667600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1220767199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1220767200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1240117199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1240117200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1252216799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1252216800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1271566799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1271566800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1283666399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1283666400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1303016399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1303016400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1315115999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1315116000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1334465999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1334466000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1346565599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1346565600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1366520399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1366520400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1378015199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1378015200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1397969999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1397970000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1410069599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1410069600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1429419599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1429419600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1441519199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1441519200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1460869199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1460869200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1472968799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1472968800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1492318799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1492318800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1504418399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1504418400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1523768399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1523768400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1535867999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1535868000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1555822799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1555822800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1567317599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1567317600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1587272399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1587272400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1599371999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1599372000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1618721999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1618722000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1630821599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1630821600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1650171599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1650171600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1662271199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1662271200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1681621199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1681621200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1693720799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1693720800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1713675599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1713675600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1725170399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1725170400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1745125199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1745125200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1757224799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1757224800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1776574799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1776574800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1788674399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1788674400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1808024399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1808024400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1820123999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1820124000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1839473999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1839474000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1851573599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1851573600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1870923599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1870923600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1883023199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1883023200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1902977999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1902978000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1914472799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1914472800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1934427599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1934427600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1946527199000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1946527200000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1965877199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1965877200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1977976799000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1977976800000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1997326799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1997326800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 2009426399000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 2009426400000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 2028776399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 2028776400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 2040875999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 2040876000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 2060225999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 2060226000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 2072325599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 2072325600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 2092280399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 2092280400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 2104379999000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 2104380000000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 2123729999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 2123730000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 2135829599000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 2135829600000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 180, tzAbbr: "FKST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "FKT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Adelaide.json b/dojox/date/tests/tztests/tz_Australia-Adelaide.json
new file mode 100644
index 0000000..93fb65a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Adelaide.json
@@ -0,0 +1,294 @@
+({
+	name: "date.timezone.Australia-Adelaide",
+	runTest: function(t){
+		var tz = "Australia/Adelaide";
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -1672565341000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -1672565340000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -1665390601000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -1665390600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -883639801000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -883639800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -876126601000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -876126600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -860398201000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -860398200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -844677001000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -844677000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -828343801000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -828343800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -813227401000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -813227400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 57688199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 57688200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 67969799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 67969800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 89137799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 89137800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 100024199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 100024200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 120587399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 120587400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 131473799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 131473800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 152036999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 152037000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 162923399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 162923400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 183486599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 183486600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 194977799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 194977800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 215540999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 215541000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 226427399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 226427400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 246990599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 246990600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 257876999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 257877000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 278440199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 278440200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 289326599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 289326600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 309889799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 309889800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 320776199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 320776200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 341339399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 341339400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 352225799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 352225800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 372788999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 372789000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 384280199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 384280200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 404843399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 404843400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 415729799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 415729800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 436292999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 436293000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 447179399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 447179400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 467742599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 467742600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 478628999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 478629000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 499192199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 499192200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 511288199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 511288200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 530036999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 530037000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 542737799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 542737800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 562091399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 562091400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 574792199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 574792200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 594145799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 594145800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 606241799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 606241800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 625595399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 625595400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 637691399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 637691400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 657044999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 657045000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 667931399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 667931400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 688494599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 688494600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 701195399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 701195400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 719944199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 719944200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 731435399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 731435400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 751998599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 751998600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 764094599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 764094600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 783448199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 783448200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 796148999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 796149000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 814897799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 814897800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 828203399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 828203400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 846347399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 846347400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 859652999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 859653000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 877796999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 877797000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 891102599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 891102600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 909246599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 909246600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 922552199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 922552200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 941300999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 941301000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 954001799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 954001800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 972750599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 972750600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 985451399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 985451400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1004200199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1004200200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1017505799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1017505800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1035649799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1035649800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1048955399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1048955400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1067099399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1067099400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1080404999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1080405000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1099153799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1099153800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1111854599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1111854600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1130603399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1130603400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1143908999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1143909000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1162052999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1162053000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1174753799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1174753800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1193502599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1193502600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1207412999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1207413000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1223137799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1223137800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1238862599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1238862600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1254587399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1254587400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1270312199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1270312200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1286036999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1286037000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1301761799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1301761800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1317486599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1317486600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1333211399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1333211400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1349540999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1349541000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1365265799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1365265800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1380990599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1380990600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1396715399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1396715400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1412440199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1412440200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1428164999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1428165000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1443889799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1443889800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1459614599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1459614600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1475339399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1475339400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1491064199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1491064200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1506788999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1506789000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1522513799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1522513800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1538843399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1538843400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1554568199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1554568200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1570292999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1570293000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1586017799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1586017800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1601742599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1601742600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1617467399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1617467400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1633192199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1633192200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1648916999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1648917000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1664641799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1664641800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1680366599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1680366600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1696091399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1696091400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1712420999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1712421000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1728145799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1728145800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1743870599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1743870600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1759595399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1759595400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1775320199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1775320200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1791044999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1791045000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1806769799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1806769800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1822494599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1822494600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1838219399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1838219400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1853944199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1853944200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1869668999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1869669000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1885998599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1885998600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1901723399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1901723400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1917448199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1917448200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1933172999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1933173000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1948897799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1948897800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1964622599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1964622600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1980347399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1980347400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1996072199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1996072200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2011796999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2011797000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2027521799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2027521800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2043246599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2043246600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2058971399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2058971400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2075300999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2075301000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2091025799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2091025800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2106750599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2106750600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2122475399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2122475400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2138200199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2138200200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Brisbane.json b/dojox/date/tests/tztests/tz_Australia-Brisbane.json
new file mode 100644
index 0000000..31de6fd
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Brisbane.json
@@ -0,0 +1,44 @@
+({
+	name: "date.timezone.Australia-Brisbane",
+	runTest: function(t){
+		var tz = "Australia/Brisbane";
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1672567141000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1672567140000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1665392401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1665392400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -883641601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -883641600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -876128401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -876128400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -860400001000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -860400000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -844678801000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -844678800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -828345601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -828345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -813229201000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -813229200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 57686399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 57686400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 67967999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 67968000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 625593599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 625593600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 636479999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 636480000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 657043199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 657043200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 667929599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 667929600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 688492799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 688492800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 699379199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 699379200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Broken_Hill.json b/dojox/date/tests/tztests/tz_Australia-Broken_Hill.json
new file mode 100644
index 0000000..61fb5d8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Broken_Hill.json
@@ -0,0 +1,294 @@
+({
+	name: "date.timezone.Australia-Broken_Hill",
+	runTest: function(t){
+		var tz = "Australia/Broken_Hill";
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -1672565341000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -1672565340000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -1665390601000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -1665390600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -883639801000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -883639800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -876126601000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -876126600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -860398201000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -860398200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -844677001000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -844677000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -828343801000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -828343800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -813227401000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -813227400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 57688199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 57688200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 67969799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 67969800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 89137799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 89137800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 100024199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 100024200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 120587399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 120587400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 131473799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 131473800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 152036999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 152037000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 162923399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 162923400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 183486599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 183486600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 194977799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 194977800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 215540999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 215541000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 226427399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 226427400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 246990599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 246990600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 257876999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 257877000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 278440199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 278440200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 289326599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 289326600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 309889799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 309889800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 320776199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 320776200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 341339399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 341339400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 352225799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 352225800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 372788999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 372789000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 386699399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 386699400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 404843399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 404843400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 415729799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 415729800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 436292999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 436293000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 447179399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 447179400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 467742599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 467742600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 478628999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 478629000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 499192199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 499192200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 511288199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 511288200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 530036999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 530037000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 542737799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 542737800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 562091399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 562091400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 574792199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 574792200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 594145799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 594145800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 606241799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 606241800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 625595399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 625595400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 636481799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 636481800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 657044999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 657045000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 667931399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 667931400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 688494599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 688494600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 699380999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 699381000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 719944199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 719944200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 731435399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 731435400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 751998599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 751998600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 762884999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 762885000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 783448199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 783448200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 794334599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 794334600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 814897799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 814897800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 828203399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 828203400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 846347399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 846347400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 859652999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 859653000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 877796999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 877797000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 891102599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 891102600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 909246599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 909246600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 922552199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 922552200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 941300999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 941301000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 954001799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 954001800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 972750599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 972750600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 985451399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 985451400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1004200199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1004200200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1017505799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1017505800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1035649799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1035649800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1048955399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1048955400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1067099399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1067099400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1080404999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1080405000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1099153799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1099153800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1111854599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1111854600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1130603399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1130603400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1143908999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1143909000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1162052999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1162053000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1174753799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1174753800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1193502599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1193502600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1207412999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1207413000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1223137799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1223137800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1238862599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1238862600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1254587399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1254587400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1270312199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1270312200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1286036999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1286037000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1301761799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1301761800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1317486599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1317486600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1333211399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1333211400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1349540999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1349541000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1365265799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1365265800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1380990599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1380990600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1396715399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1396715400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1412440199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1412440200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1428164999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1428165000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1443889799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1443889800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1459614599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1459614600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1475339399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1475339400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1491064199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1491064200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1506788999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1506789000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1522513799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1522513800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1538843399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1538843400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1554568199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1554568200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1570292999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1570293000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1586017799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1586017800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1601742599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1601742600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1617467399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1617467400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1633192199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1633192200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1648916999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1648917000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1664641799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1664641800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1680366599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1680366600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1696091399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1696091400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1712420999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1712421000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1728145799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1728145800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1743870599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1743870600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1759595399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1759595400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1775320199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1775320200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1791044999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1791045000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1806769799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1806769800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1822494599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1822494600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1838219399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1838219400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1853944199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1853944200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1869668999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1869669000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1885998599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1885998600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1901723399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1901723400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1917448199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1917448200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1933172999000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1933173000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1948897799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1948897800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1964622599000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1964622600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1980347399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1980347400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1996072199000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1996072200000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2011796999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2011797000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2027521799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2027521800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2043246599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2043246600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2058971399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2058971400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2075300999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2075301000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2091025799000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2091025800000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2106750599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2106750600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2122475399000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2122475400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2138200199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2138200200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Currie.json b/dojox/date/tests/tztests/tz_Australia-Currie.json
new file mode 100644
index 0000000..8974bf2
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Currie.json
@@ -0,0 +1,294 @@
+({
+	name: "date.timezone.Australia-Currie",
+	runTest: function(t){
+		var tz = "Australia/Currie";
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1680508801000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1680508800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1665392401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1665392400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -883641601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -883641600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -876128401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -876128400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -860400001000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -860400000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -844678801000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -844678800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -828345601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -828345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -813229201000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -813229200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 57686399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 57686400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 67967999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 67968000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 89135999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 89136000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 100022399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 100022400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 120585599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 120585600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 131471999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 131472000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 152035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 152035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 162921599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 162921600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 183484799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 183484800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 194975999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 194976000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 215539199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 215539200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 226425599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 226425600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 246988799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 246988800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 257875199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 257875200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 278438399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 278438400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 289324799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 289324800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 309887999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 309888000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 320774399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 320774400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 341337599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 341337600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 352223999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 352224000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 372787199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 372787200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 386092799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 386092800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 404841599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 404841600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 417542399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 417542400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 436291199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 436291200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 447177599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 447177600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 467740799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 467740800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 478627199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 478627200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 499190399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 499190400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 510076799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 510076800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 530035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 530035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 542735999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 542736000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 562089599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 562089600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 574790399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 574790400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 594143999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 594144000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 606239999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 606240000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 625593599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 625593600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 637689599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 637689600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 657043199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 657043200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 670348799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 670348800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 686678399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 686678400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 701798399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 701798400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 718127999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 718128000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 733247999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 733248000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 749577599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 749577600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 764697599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 764697600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 781027199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 781027200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 796147199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 796147200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 812476799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 812476800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 828201599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 828201600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 844531199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 844531200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 859651199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 859651200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 875980799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 875980800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 891100799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 891100800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 907430399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 907430400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 922550399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 922550400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 938879999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 938880000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 953999999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 954000000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 967305599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 967305600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 985449599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 985449600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1002383999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1002384000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1017503999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1017504000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1033833599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1033833600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1048953599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1048953600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1065283199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1065283200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1080403199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1080403200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1096732799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1096732800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1111852799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1111852800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1128182399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1128182400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1143907199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1143907200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1159631999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1159632000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1174751999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1174752000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1191686399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1191686400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1207411199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1207411200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1223135999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1223136000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1238860799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1238860800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1254585599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1254585600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1270310399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1270310400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1286035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1286035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1301759999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1301760000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1317484799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1317484800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1333209599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1333209600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1349539199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1349539200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1365263999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1365264000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1380988799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1380988800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1396713599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1396713600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1412438399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1412438400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1428163199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1428163200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1443887999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1443888000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1459612799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1459612800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1475337599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1475337600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1491062399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1491062400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1506787199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1506787200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1522511999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1522512000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1538841599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1538841600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1554566399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1554566400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1570291199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1570291200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1586015999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1586016000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1601740799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1601740800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1617465599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1617465600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1633190399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1633190400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1648915199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1648915200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1664639999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1664640000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1680364799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1680364800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1696089599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1696089600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1712419199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1712419200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1728143999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1728144000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1743868799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1743868800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1759593599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1759593600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1775318399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1775318400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1791043199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1791043200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1806767999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1806768000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1822492799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1822492800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1838217599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1838217600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1853942399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1853942400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1869667199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1869667200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1885996799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1885996800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1901721599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1901721600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1917446399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1917446400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1933171199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1933171200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1948895999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1948896000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1964620799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1964620800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1980345599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1980345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1996070399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1996070400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2011795199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2011795200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2027519999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2027520000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2043244799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2043244800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2058969599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2058969600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2075299199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2075299200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2091023999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2091024000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2106748799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2106748800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2122473599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2122473600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2138198399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2138198400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Darwin.json b/dojox/date/tests/tztests/tz_Australia-Darwin.json
new file mode 100644
index 0000000..23470fd
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Darwin.json
@@ -0,0 +1,28 @@
+({
+	name: "date.timezone.Australia-Darwin",
+	runTest: function(t){
+		var tz = "Australia/Darwin";
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -1672565341000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -1672565340000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -1665390601000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -1665390600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -883639801000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -883639800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -876126601000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -876126600000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -860398201000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -860398200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -844677001000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -844677000000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -828343801000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -828343800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "CST"}, -813227401000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, -813227400000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -570, tzAbbr: "CST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Eucla.json b/dojox/date/tests/tztests/tz_Australia-Eucla.json
new file mode 100644
index 0000000..fac8fe9
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Eucla.json
@@ -0,0 +1,48 @@
+({
+	name: "date.timezone.Australia-Eucla",
+	runTest: function(t){
+		var tz = "Australia/Eucla";
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, -1672562641000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, -1672562640000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, -1665387901000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, -1665387900000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, -883637101000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, -883637100000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, -876123901000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, -876123900000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, -860395501000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, -860395500000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, -844674301000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, -844674300000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 152039699000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 152039700000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 162926099000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 162926100000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 436295699000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 436295700000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 447182099000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 447182100000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 690311699000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 690311700000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 699383699000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 699383700000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 1165079699000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 1165079700000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 1174756499000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 1174756500000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 1193505299000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 1193505300000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 1206810899000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 1206810900000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 1224954899000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 1224954900000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 1238260499000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 1238260500000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -585, tzAbbr: "CWST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -525, tzAbbr: "CWST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Hobart.json b/dojox/date/tests/tztests/tz_Australia-Hobart.json
new file mode 100644
index 0000000..578ca54
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Hobart.json
@@ -0,0 +1,310 @@
+({
+	name: "date.timezone.Australia-Hobart",
+	runTest: function(t){
+		var tz = "Australia/Hobart";
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1680508801000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1680508800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1665392401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1665392400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -883641601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -883641600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -876128401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -876128400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -860400001000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -860400000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -844678801000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -844678800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -828345601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -828345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -813229201000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -813229200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -71136001000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -71136000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -55411201000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -55411200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -37267201000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -37267200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -25776001000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -25776000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -5817601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -5817600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 5673599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 5673600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 25631999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 25632000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 37727999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 37728000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 57686399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 57686400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 67967999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 67968000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 89135999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 89136000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 100022399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 100022400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 120585599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 120585600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 131471999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 131472000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 152035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 152035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 162921599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 162921600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 183484799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 183484800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 194975999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 194976000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 215539199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 215539200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 226425599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 226425600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 246988799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 246988800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 257875199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 257875200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 278438399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 278438400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 289324799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 289324800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 309887999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 309888000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 320774399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 320774400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 341337599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 341337600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 352223999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 352224000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 372787199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 372787200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 386092799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 386092800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 404841599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 404841600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 417542399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 417542400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 436291199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 436291200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 447177599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 447177600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 467740799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 467740800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 478627199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 478627200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 499190399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 499190400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 510076799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 510076800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 530035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 530035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 542735999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 542736000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 562089599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 562089600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 574790399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 574790400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 594143999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 594144000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 606239999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 606240000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 625593599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 625593600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 637689599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 637689600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 657043199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 657043200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 670348799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 670348800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 686678399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 686678400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 701798399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 701798400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 718127999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 718128000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 733247999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 733248000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 749577599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 749577600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 764697599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 764697600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 781027199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 781027200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 796147199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 796147200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 812476799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 812476800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 828201599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 828201600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 844531199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 844531200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 859651199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 859651200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 875980799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 875980800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 891100799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 891100800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 907430399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 907430400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 922550399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 922550400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 938879999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 938880000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 953999999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 954000000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 967305599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 967305600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 985449599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 985449600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1002383999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1002384000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1017503999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1017504000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1033833599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1033833600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1048953599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1048953600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1065283199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1065283200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1080403199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1080403200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1096732799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1096732800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1111852799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1111852800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1128182399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1128182400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1143907199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1143907200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1159631999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1159632000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1174751999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1174752000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1191686399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1191686400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1207411199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1207411200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1223135999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1223136000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1238860799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1238860800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1254585599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1254585600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1270310399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1270310400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1286035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1286035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1301759999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1301760000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1317484799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1317484800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1333209599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1333209600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1349539199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1349539200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1365263999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1365264000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1380988799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1380988800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1396713599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1396713600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1412438399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1412438400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1428163199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1428163200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1443887999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1443888000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1459612799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1459612800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1475337599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1475337600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1491062399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1491062400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1506787199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1506787200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1522511999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1522512000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1538841599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1538841600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1554566399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1554566400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1570291199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1570291200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1586015999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1586016000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1601740799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1601740800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1617465599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1617465600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1633190399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1633190400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1648915199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1648915200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1664639999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1664640000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1680364799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1680364800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1696089599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1696089600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1712419199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1712419200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1728143999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1728144000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1743868799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1743868800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1759593599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1759593600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1775318399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1775318400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1791043199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1791043200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1806767999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1806768000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1822492799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1822492800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1838217599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1838217600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1853942399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1853942400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1869667199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1869667200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1885996799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1885996800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1901721599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1901721600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1917446399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1917446400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1933171199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1933171200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1948895999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1948896000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1964620799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1964620800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1980345599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1980345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1996070399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1996070400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2011795199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2011795200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2027519999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2027520000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2043244799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2043244800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2058969599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2058969600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2075299199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2075299200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2091023999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2091024000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2106748799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2106748800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2122473599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2122473600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2138198399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2138198400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Lindeman.json b/dojox/date/tests/tztests/tz_Australia-Lindeman.json
new file mode 100644
index 0000000..3fd835e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Lindeman.json
@@ -0,0 +1,52 @@
+({
+	name: "date.timezone.Australia-Lindeman",
+	runTest: function(t){
+		var tz = "Australia/Lindeman";
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1672567141000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1672567140000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1665392401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1665392400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -883641601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -883641600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -876128401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -876128400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -860400001000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -860400000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -844678801000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -844678800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -828345601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -828345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -813229201000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -813229200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 57686399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 57686400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 67967999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 67968000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 625593599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 625593600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 636479999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 636480000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 657043199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 657043200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 667929599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 667929600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 688492799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 688492800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 699379199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 699379200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 719942399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 719942400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 731433599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 731433600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 751996799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 751996800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 762883199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 762883200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Lord_Howe.json b/dojox/date/tests/tztests/tz_Australia-Lord_Howe.json
new file mode 100644
index 0000000..df40f26
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Lord_Howe.json
@@ -0,0 +1,240 @@
+({
+	name: "date.timezone.Australia-Lord_Howe",
+	runTest: function(t){
+		var tz = "Australia/Lord_Howe";
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 352216799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 352216800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 372785399000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "LHST"}, 372785400000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "LHST"}, 384272999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 384273000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 404839799000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "LHST"}, 404839800000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "LHST"}, 415722599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 415722600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 436289399000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "LHST"}, 436289400000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "LHST"}, 447172199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 447172200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 467738999000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "LHST"}, 467739000000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "LHST"}, 478621799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 478621800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 499188599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 499188600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 511282799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 511282800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 530033399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 530033400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 542732399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 542732400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 562087799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 562087800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 574786799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 574786800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 594142199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 594142200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 606236399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 606236400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 625591799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 625591800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 636476399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 636476400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 657041399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 657041400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 667925999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 667926000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 688490999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 688491000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 699375599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 699375600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 719940599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 719940600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 731429999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 731430000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 751994999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 751995000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 762879599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 762879600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 783444599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 783444600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 794329199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 794329200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 814894199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 814894200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 828197999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 828198000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 846343799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 846343800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 859647599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 859647600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 877793399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 877793400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 891097199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 891097200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 909242999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 909243000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 922546799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 922546800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 941297399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 941297400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 953996399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 953996400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 967303799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 967303800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 985445999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 985446000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1004196599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1004196600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1017500399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1017500400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1035646199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1035646200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1048949999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1048950000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1067095799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1067095800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1080399599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1080399600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1099150199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1099150200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1111849199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1111849200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1130599799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1130599800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1143903599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1143903600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1162049399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1162049400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1174748399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1174748400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1193498999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1193499000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1207407599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1207407600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1223134199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1223134200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1238857199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1238857200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1254583799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1254583800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1270306799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1270306800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1286033399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1286033400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1301756399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1301756400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1317482999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1317483000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1333205999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1333206000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1349537399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1349537400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1365260399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1365260400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1380986999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1380987000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1396709999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1396710000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1412436599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1412436600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1428159599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1428159600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1443886199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1443886200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1459609199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1459609200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1475335799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1475335800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1491058799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1491058800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1506785399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1506785400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1522508399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1522508400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1538839799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1538839800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1554562799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1554562800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1570289399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1570289400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1586012399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1586012400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1601738999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1601739000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1617461999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1617462000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1633188599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1633188600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1648911599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1648911600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1664638199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1664638200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1680361199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1680361200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1696087799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1696087800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1712415599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1712415600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1728142199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1728142200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1743865199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1743865200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1759591799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1759591800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1775314799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1775314800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1791041399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1791041400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1806764399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1806764400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1822490999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1822491000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1838213999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1838214000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1853940599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1853940600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1869663599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1869663600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1885994999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1885995000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1901717999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1901718000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1917444599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1917444600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1933167599000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1933167600000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1948894199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1948894200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1964617199000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1964617200000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1980343799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1980343800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1996066799000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1996066800000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 2011793399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 2011793400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 2027516399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 2027516400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 2043242999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 2043243000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 2058965999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 2058966000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 2075297399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 2075297400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 2091020399000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 2091020400000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 2106746999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 2106747000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 2122469999000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 2122470000000, tz, 1);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 2138196599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 2138196600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "LHST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -630, tzAbbr: "LHST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Melbourne.json b/dojox/date/tests/tztests/tz_Australia-Melbourne.json
new file mode 100644
index 0000000..e84ecd8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Melbourne.json
@@ -0,0 +1,294 @@
+({
+	name: "date.timezone.Australia-Melbourne",
+	runTest: function(t){
+		var tz = "Australia/Melbourne";
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1672567141000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1672567140000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1665392401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1665392400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -883641601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -883641600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -876128401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -876128400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -860400001000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -860400000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -844678801000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -844678800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -828345601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -828345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -813229201000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -813229200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 57686399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 57686400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 67967999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 67968000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 89135999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 89136000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 100022399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 100022400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 120585599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 120585600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 131471999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 131472000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 152035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 152035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 162921599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 162921600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 183484799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 183484800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 194975999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 194976000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 215539199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 215539200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 226425599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 226425600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 246988799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 246988800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 257875199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 257875200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 278438399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 278438400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 289324799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 289324800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 309887999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 309888000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 320774399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 320774400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 341337599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 341337600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 352223999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 352224000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 372787199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 372787200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 384278399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 384278400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 404841599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 404841600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 415727999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 415728000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 436291199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 436291200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 447177599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 447177600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 467740799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 467740800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 478627199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 478627200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 499190399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 499190400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 511286399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 511286400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 530035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 530035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 542735999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 542736000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 561484799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 561484800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 574790399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 574790400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 594143999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 594144000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 606239999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 606240000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 625593599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 625593600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 637689599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 637689600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 657043199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 657043200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 667929599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 667929600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 688492799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 688492800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 699379199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 699379200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 719942399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 719942400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 731433599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 731433600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 751996799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 751996800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 762883199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 762883200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 783446399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 783446400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 796147199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 796147200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 814895999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 814896000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 828201599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 828201600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 846345599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 846345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 859651199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 859651200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 877795199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 877795200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 891100799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 891100800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 909244799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 909244800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 922550399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 922550400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 941299199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 941299200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 953999999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 954000000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 967305599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 967305600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 985449599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 985449600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1004198399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1004198400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1017503999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1017504000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1035647999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1035648000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1048953599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1048953600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1067097599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1067097600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1080403199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1080403200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1099151999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1099152000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1111852799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1111852800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1130601599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1130601600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1143907199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1143907200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1162051199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1162051200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1174751999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1174752000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1193500799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1193500800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1207411199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1207411200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1223135999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1223136000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1238860799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1238860800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1254585599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1254585600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1270310399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1270310400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1286035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1286035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1301759999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1301760000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1317484799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1317484800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1333209599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1333209600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1349539199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1349539200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1365263999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1365264000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1380988799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1380988800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1396713599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1396713600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1412438399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1412438400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1428163199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1428163200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1443887999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1443888000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1459612799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1459612800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1475337599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1475337600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1491062399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1491062400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1506787199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1506787200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1522511999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1522512000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1538841599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1538841600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1554566399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1554566400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1570291199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1570291200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1586015999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1586016000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1601740799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1601740800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1617465599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1617465600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1633190399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1633190400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1648915199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1648915200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1664639999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1664640000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1680364799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1680364800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1696089599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1696089600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1712419199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1712419200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1728143999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1728144000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1743868799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1743868800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1759593599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1759593600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1775318399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1775318400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1791043199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1791043200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1806767999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1806768000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1822492799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1822492800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1838217599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1838217600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1853942399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1853942400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1869667199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1869667200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1885996799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1885996800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1901721599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1901721600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1917446399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1917446400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1933171199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1933171200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1948895999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1948896000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1964620799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1964620800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1980345599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1980345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1996070399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1996070400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2011795199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2011795200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2027519999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2027520000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2043244799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2043244800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2058969599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2058969600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2075299199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2075299200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2091023999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2091024000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2106748799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2106748800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2122473599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2122473600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2138198399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2138198400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Perth.json b/dojox/date/tests/tztests/tz_Australia-Perth.json
new file mode 100644
index 0000000..dc9d7ea
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Perth.json
@@ -0,0 +1,48 @@
+({
+	name: "date.timezone.Australia-Perth",
+	runTest: function(t){
+		var tz = "Australia/Perth";
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, -1672559941000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, -1672559940000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, -1665385201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, -1665385200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, -883634401000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, -883634400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, -876121201000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, -876121200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, -860392801000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, -860392800000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, -844671601000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, -844671600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 152042399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 152042400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 162928799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 162928800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 436298399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 436298400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 447184799000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 447184800000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 690314399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 690314400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 699386399000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 699386400000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 1165082399000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 1165082400000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 1174759199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 1174759200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 1193507999000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 1193508000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 1206813599000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 1206813600000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 1224957599000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 1224957600000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 1238263199000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 1238263200000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "WST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -480, tzAbbr: "WST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Australia-Sydney.json b/dojox/date/tests/tztests/tz_Australia-Sydney.json
new file mode 100644
index 0000000..c844c65
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Australia-Sydney.json
@@ -0,0 +1,294 @@
+({
+	name: "date.timezone.Australia-Sydney",
+	runTest: function(t){
+		var tz = "Australia/Sydney";
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1672567141000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1672567140000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -1665392401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -1665392400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -883641601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -883641600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -876128401000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -876128400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -860400001000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -860400000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -844678801000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -844678800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -828345601000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -828345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, -813229201000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, -813229200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 57686399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 57686400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 67967999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 67968000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 89135999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 89136000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 100022399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 100022400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 120585599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 120585600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 131471999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 131472000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 152035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 152035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 162921599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 162921600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 183484799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 183484800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 194975999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 194976000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 215539199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 215539200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 226425599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 226425600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 246988799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 246988800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 257875199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 257875200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 278438399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 278438400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 289324799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 289324800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 309887999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 309888000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 320774399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 320774400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 341337599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 341337600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 352223999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 352224000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 372787199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 372787200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 386697599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 386697600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 404841599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 404841600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 415727999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 415728000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 436291199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 436291200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 447177599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 447177600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 467740799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 467740800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 478627199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 478627200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 499190399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 499190400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 511286399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 511286400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 530035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 530035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 542735999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 542736000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 562089599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 562089600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 574790399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 574790400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 594143999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 594144000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 606239999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 606240000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 625593599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 625593600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 636479999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 636480000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 657043199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 657043200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 667929599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 667929600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 688492799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 688492800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 699379199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 699379200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 719942399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 719942400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 731433599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 731433600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 751996799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 751996800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 762883199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 762883200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 783446399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 783446400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 794332799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 794332800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 814895999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 814896000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 828201599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 828201600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 846345599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 846345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 859651199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 859651200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 877795199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 877795200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 891100799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 891100800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 909244799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 909244800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 922550399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 922550400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 941299199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 941299200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 953999999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 954000000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 967305599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 967305600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 985449599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 985449600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1004198399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1004198400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1017503999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1017504000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1035647999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1035648000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1048953599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1048953600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1067097599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1067097600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1080403199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1080403200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1099151999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1099152000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1111852799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1111852800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1130601599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1130601600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1143907199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1143907200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1162051199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1162051200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1174751999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1174752000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1193500799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1193500800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1207411199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1207411200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1223135999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1223136000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1238860799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1238860800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1254585599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1254585600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1270310399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1270310400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1286035199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1286035200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1301759999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1301760000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1317484799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1317484800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1333209599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1333209600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1349539199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1349539200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1365263999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1365264000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1380988799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1380988800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1396713599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1396713600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1412438399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1412438400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1428163199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1428163200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1443887999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1443888000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1459612799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1459612800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1475337599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1475337600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1491062399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1491062400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1506787199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1506787200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1522511999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1522512000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1538841599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1538841600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1554566399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1554566400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1570291199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1570291200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1586015999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1586016000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1601740799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1601740800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1617465599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1617465600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1633190399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1633190400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1648915199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1648915200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1664639999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1664640000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1680364799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1680364800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1696089599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1696089600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1712419199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1712419200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1728143999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1728144000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1743868799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1743868800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1759593599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1759593600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1775318399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1775318400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1791043199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1791043200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1806767999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1806768000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1822492799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1822492800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1838217599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1838217600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1853942399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1853942400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1869667199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1869667200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1885996799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1885996800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1901721599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1901721600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1917446399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1917446400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1933171199000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1933171200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1948895999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1948896000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1964620799000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1964620800000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1980345599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1980345600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1996070399000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1996070400000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2011795199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2011795200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2027519999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2027520000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2043244799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2043244800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2058969599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2058969600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2075299199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2075299200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2091023999000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2091024000000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2106748799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2106748800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2122473599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2122473600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 2138198399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2138198400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_CET.json b/dojox/date/tests/tztests/tz_CET.json
new file mode 100644
index 0000000..7e6b0ba
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_CET.json
@@ -0,0 +1,284 @@
+({
+	name: "date.timezone.CET",
+	runTest: function(t){
+		var tz = "CET";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1693706401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1693706400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1663455601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1663455600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1650150001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1650150000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1632006001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1632006000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1618700401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1618700400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -938905201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -938905200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -766623601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -766623600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 228877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 228877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 243997199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 243997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 260326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 260326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 276051599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 276051600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_CST6CDT.json b/dojox/date/tests/tztests/tz_CST6CDT.json
new file mode 100644
index 0000000..251ae56
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_CST6CDT.json
@@ -0,0 +1,310 @@
+({
+	name: "date.timezone.CST6CDT",
+	runTest: function(t){
+		var tz = "CST6CDT";
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1633276801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1633276800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1615136401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1615136400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1601827201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1601827200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -1583686801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -1583686800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -880214401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -880214400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CPT"}, -765392401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -765392400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -84384001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -84384000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -68662801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -68662800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -52934401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -52934400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -37213201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -37213200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -21484801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -21484800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, -5763601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, -5763600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 9964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 9964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 25685999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 25686000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 41414399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 41414400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 57740399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 57740400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 73468799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 73468800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 89189999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 89190000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 104918399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 104918400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 120639599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 120639600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 126691199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 126691200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 152089199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 152089200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 162374399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 162374400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 183538799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 183538800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 199267199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 199267200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 215593199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 215593200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 230716799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 230716800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 247042799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 247042800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 262771199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 262771200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 278492399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 278492400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 294220799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 294220800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 309941999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 309942000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 325670399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 325670400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 341391599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 341391600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 357119999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 357120000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 372841199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 372841200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 388569599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 388569600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 404895599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 404895600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 420019199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 420019200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 436345199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 436345200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 452073599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 452073600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 467794799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 467794800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 483523199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 483523200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 499244399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 499244400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 514972799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 514972800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 530693999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 530694000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 544607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 544608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 562143599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 562143600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 576057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 576057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 594197999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 594198000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 607507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 607507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 625647599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 625647600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 638956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 638956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 657097199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 657097200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 671011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 671011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 688546799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 688546800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 702460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 702460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 719996399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 719996400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 733910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 733910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 752050799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 752050800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 765359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 765360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 783500399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 783500400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 796809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 796809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 814949999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 814950000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 828863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 828864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 846399599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 846399600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 860313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 860313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 877849199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 877849200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 891763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 891763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 909298799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 909298800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 923212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 923212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 941353199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 941353200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 954662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 954662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 972802799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 972802800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 986111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 986112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1004252399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1004252400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1018166399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1018166400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1035701999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1035702000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1049615999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1049616000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1067151599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1067151600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1081065599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1081065600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1099205999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1099206000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1112515199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1112515200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1130655599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1130655600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1143964799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1143964800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1162105199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1162105200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1173599999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1173600000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1194159599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1194159600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1205049599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1205049600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1225609199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1225609200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1236499199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1236499200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1257058799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1257058800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1268553599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1268553600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1289113199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1289113200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1300003199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1300003200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1320562799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1320562800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1331452799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1331452800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1352012399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1352012400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1362902399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1362902400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1383461999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1383462000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1394351999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1394352000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1414911599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1414911600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1425801599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1425801600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1446361199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1446361200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1457855999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1457856000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1478415599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1478415600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1489305599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1489305600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1509865199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1509865200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1520755199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1520755200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1541314799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1541314800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1552204799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1552204800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1572764399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1572764400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1583654399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1583654400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1604213999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1604214000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1615708799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1615708800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1636268399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1636268400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1647158399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1647158400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1667717999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1667718000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1678607999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1678608000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1699167599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1699167600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1710057599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1710057600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1730617199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1730617200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1741507199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1741507200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1762066799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1762066800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1772956799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1772956800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1793516399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1793516400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1805011199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1805011200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1825570799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1825570800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1836460799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1836460800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1857020399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1857020400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1867910399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1867910400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1888469999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1888470000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1899359999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1899360000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1919919599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1919919600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1930809599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1930809600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1951369199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1951369200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1962863999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1962864000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1983423599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1983423600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1994313599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1994313600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2014873199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2014873200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2025763199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2025763200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2046322799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2046322800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2057212799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2057212800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2077772399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2077772400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2088662399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2088662400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2109221999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2109222000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2120111999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2120112000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 2140671599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2140671600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "CST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "CDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_EET.json b/dojox/date/tests/tztests/tz_EET.json
new file mode 100644
index 0000000..f961eef
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_EET.json
@@ -0,0 +1,256 @@
+({
+	name: "date.timezone.EET",
+	runTest: function(t){
+		var tz = "EET";
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 228877199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 228877200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 243997199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 243997200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 260326799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 260326800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 276051599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 276051600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_EST.json b/dojox/date/tests/tztests/tz_EST.json
new file mode 100644
index 0000000..2d415e2
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_EST.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.EST",
+	runTest: function(t){
+		var tz = "EST";
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_EST5EDT.json b/dojox/date/tests/tztests/tz_EST5EDT.json
new file mode 100644
index 0000000..6a5552e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_EST5EDT.json
@@ -0,0 +1,310 @@
+({
+	name: "date.timezone.EST5EDT",
+	runTest: function(t){
+		var tz = "EST5EDT";
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1633280401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1633280400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1615140001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1615140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1601830801000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1601830800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -1583690401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -1583690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -880218001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -880218000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EPT"}, -765396001000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -765396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -84387601000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -84387600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -68666401000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -68666400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -52938001000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -52938000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -37216801000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -37216800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -21488401000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -21488400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, -5767201000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, -5767200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 9961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 9961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 25682399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 25682400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 41410799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 41410800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 57736799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 57736800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 73465199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 73465200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 89186399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 89186400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 104914799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 104914800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 120635999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 120636000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 126687599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 126687600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 152085599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 152085600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 162370799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 162370800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 183535199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 183535200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 199263599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 199263600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 215589599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 215589600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 230713199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 230713200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 247039199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 247039200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 262767599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 262767600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 278488799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 278488800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 294217199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 294217200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 309938399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 309938400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 325666799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 325666800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 341387999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 341388000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 357116399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 357116400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 372837599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 372837600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 388565999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 388566000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 404891999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 404892000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 420015599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 420015600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 436341599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 436341600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 452069999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 452070000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 467791199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 467791200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 483519599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 483519600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 499240799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 499240800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 514969199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 514969200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 530690399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 530690400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 544604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 544604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 562139999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 562140000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 576053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 576054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 594194399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 594194400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 607503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 607503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 625643999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 625644000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 638953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 638953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 657093599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 657093600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 671007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 671007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 688543199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 688543200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 702457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 702457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 719992799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 719992800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 733906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 733906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 752047199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 752047200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 765356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 765356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 783496799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 783496800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 796805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 796806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 814946399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 814946400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 828860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 828860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 846395999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 846396000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 860309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 860310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 877845599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 877845600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 891759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 891759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 909295199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 909295200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 923209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 923209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 941349599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 941349600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 954658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 954658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 972799199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 972799200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 986108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 986108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1004248799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1004248800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1018162799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1018162800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1035698399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1035698400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1049612399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1049612400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1067147999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1067148000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1081061999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1081062000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1099202399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1099202400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1112511599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1112511600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1130651999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1130652000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1143961199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1143961200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1162101599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1162101600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1173596399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1173596400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1194155999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1194156000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1205045999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1205046000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1225605599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1225605600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1236495599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1236495600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1257055199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1257055200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1268549999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1268550000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1289109599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1289109600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1299999599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1299999600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1320559199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1320559200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1331449199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1331449200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1352008799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1352008800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1362898799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1362898800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1383458399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1383458400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1394348399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1394348400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1414907999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1414908000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1425797999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1425798000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1446357599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1446357600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1457852399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1457852400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1478411999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1478412000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1489301999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1489302000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1509861599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1509861600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1520751599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1520751600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1541311199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1541311200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1552201199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1552201200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1572760799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1572760800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1583650799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1583650800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1604210399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1604210400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1615705199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1615705200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1636264799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1636264800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1647154799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1647154800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1667714399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1667714400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1678604399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1678604400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1699163999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1699164000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1710053999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1710054000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1730613599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1730613600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1741503599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1741503600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1762063199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1762063200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1772953199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1772953200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1793512799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1793512800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1805007599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1805007600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1825567199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1825567200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1836457199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1836457200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1857016799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1857016800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1867906799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1867906800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1888466399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1888466400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1899356399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1899356400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1919915999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1919916000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1930805999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1930806000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1951365599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1951365600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1962860399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1962860400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1983419999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1983420000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1994309999000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1994310000000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2014869599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2014869600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2025759599000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2025759600000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2046319199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2046319200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2057209199000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2057209200000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2077768799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2077768800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2088658799000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2088658800000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2109218399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2109218400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2120108399000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2120108400000, tz, 1);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 2140667999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2140668000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 240, tzAbbr: "EDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Amsterdam.json b/dojox/date/tests/tztests/tz_Europe-Amsterdam.json
new file mode 100644
index 0000000..eca7f21
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Amsterdam.json
@@ -0,0 +1,370 @@
+({
+	name: "date.timezone.Europe-Amsterdam",
+	runTest: function(t){
+		var tz = "Europe/Amsterdam";
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1693700373000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1693700372000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1680484773000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1680484772000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1663453173000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1663453172000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1650147573000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1650147572000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1633213173000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1633213172000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1617488373000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1617488372000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1601158773000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1601158772000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1586038773000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1586038772000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1569709173000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1569709172000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1554589173000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1554589172000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1538259573000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1538259572000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1523139573000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1523139572000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1507501173000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1507501172000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1490566773000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1490566772000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1470176373000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1470176372000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1459117173000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1459117172000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1443997173000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1443997172000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1427667573000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1427667572000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1406672373000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1406672372000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1396217973000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1396217972000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1376950773000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1376950772000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1364768373000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1364768372000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1345414773000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1345414772000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1333318773000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1333318772000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1313792373000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1313792372000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1301264373000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1301264372000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1282256373000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1282256372000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1269814773000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1269814772000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1250720373000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1250720372000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1238365173000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1238365172000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1219184373000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1219184372000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1206915573000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1206915572000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1186957173000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1186957172000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1175465973000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1175465972000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1156025973000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1156025972000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1143411573000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1143411572000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1124489973000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1124489972000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1111961973000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1111961972000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1092953973000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1092953972000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1080512373000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1080512372000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1061331573000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1061331572000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1049062773000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1049062772000, tz, 1);
+		doh.checkDate({tzOffset: -19.5333333333333, tzAbbr: "AMT"}, -1029190773000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1029190772000, tz, 1);
+		doh.checkDate({tzOffset: -79.5333333333333, tzAbbr: "NST"}, -1025745573000, tz, 1);
+		doh.checkDate({tzOffset: -80, tzAbbr: "NEST"}, -1025745572000, tz, 1);
+		doh.checkDate({tzOffset: -80, tzAbbr: "NEST"}, -1017613201000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "NET"}, -1017613200000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "NET"}, -998259601000, tz, 1);
+		doh.checkDate({tzOffset: -80, tzAbbr: "NEST"}, -998259600000, tz, 1);
+		doh.checkDate({tzOffset: -80, tzAbbr: "NEST"}, -986163601000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "NET"}, -986163600000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "NET"}, -966723601000, tz, 1);
+		doh.checkDate({tzOffset: -80, tzAbbr: "NEST"}, -966723600000, tz, 1);
+		doh.checkDate({tzOffset: -80, tzAbbr: "NEST"}, -954109201000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "NET"}, -954109200000, tz, 1);
+		doh.checkDate({tzOffset: -20, tzAbbr: "NET"}, -935022001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -935022000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -766623601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -766623600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 228877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 228877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 243997199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 243997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 260326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 260326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 276051599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 276051600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Andorra.json b/dojox/date/tests/tztests/tz_Europe-Andorra.json
new file mode 100644
index 0000000..74780b2
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Andorra.json
@@ -0,0 +1,226 @@
+({
+	name: "date.timezone.Europe-Andorra",
+	runTest: function(t){
+		var tz = "Europe/Andorra";
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -733881601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733881600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Athens.json b/dojox/date/tests/tztests/tz_Europe-Athens.json
new file mode 100644
index 0000000..7b48a5b
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Athens.json
@@ -0,0 +1,286 @@
+({
+	name: "date.timezone.Europe-Athens",
+	runTest: function(t){
+		var tz = "Europe/Athens";
+		doh.checkDate({tzOffset: -94.8666666666667, tzAbbr: "AMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -94.8666666666667, tzAbbr: "AMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -94.8666666666667, tzAbbr: "AMT"}, -1686101633000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1686101632000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1182996001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1182996000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1178161201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1178161200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -906861601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -906861600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -904878001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -904878000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844477201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844477200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828237601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828237600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812422801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -812422800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -552362401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -552362400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -541652401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -541652400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 166485599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 166485600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 186184799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 186184800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 198028799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 198028800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 213753599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 213753600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 228873599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 228873600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 244079999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 244080000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 260323199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 260323200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 275446799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 275446800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 291797999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 291798000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 307407599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 307407600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 323387999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 323388000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 338936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 338936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Belgrade.json b/dojox/date/tests/tztests/tz_Europe-Belgrade.json
new file mode 100644
index 0000000..09a183e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Belgrade.json
@@ -0,0 +1,248 @@
+({
+	name: "date.timezone.Europe-Belgrade",
+	runTest: function(t){
+		var tz = "Europe/Belgrade";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -905824801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -905824800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -777942001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -777942000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -766623601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -766623600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Berlin.json b/dojox/date/tests/tztests/tz_Europe-Berlin.json
new file mode 100644
index 0000000..6b8a245
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Berlin.json
@@ -0,0 +1,296 @@
+({
+	name: "date.timezone.Europe-Berlin",
+	runTest: function(t){
+		var tz = "Europe/Berlin";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1693706401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1693706400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1663455601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1663455600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1650150001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1650150000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1632006001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1632006000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1618700401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1618700400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -938905201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -938905200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -776563201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CEMT"}, -776563200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CEMT"}, -765936001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -765936000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -761180401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -761180400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -748479601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -748479600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -733273201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733273200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -717631201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -717631200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -714610801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CEMT"}, -714610800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CEMT"}, -710380801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -710380800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -701910001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -701910000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -684975601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -684975600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -670460401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -670460400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -654130801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -654130800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -639010801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -639010800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Brussels.json b/dojox/date/tests/tztests/tz_Europe-Brussels.json
new file mode 100644
index 0000000..7e65581
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Brussels.json
@@ -0,0 +1,378 @@
+({
+	name: "date.timezone.Europe-Brussels",
+	runTest: function(t){
+		var tz = "Europe/Brussels";
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1740355201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1740355200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1693702801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1693702800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1663455601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1663455600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1650150001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1650150000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1632006001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1632006000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1618700401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1618700400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1613826001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1613826000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1604278801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1604278800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1585530001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1585530000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1574038801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1574038800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1552266001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1552266000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1539997201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1539997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1520557201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1520557200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1507510801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1507510800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1490576401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1490576400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1473642001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1473642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1459126801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1459126800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1444006801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1444006800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1427677201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1427677200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1411952401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1411952400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1396227601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1396227600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1379293201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1379293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1364778001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1364778000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1348448401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1348448400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1333328401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1333328400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1316394001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1316394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1301263201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1301263200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1284328801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1284328800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1269813601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1269813600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1253484001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1253484000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1238364001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1238364000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1221429601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1221429600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1206914401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1206914400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1191189601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1191189600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1175464801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1175464800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1160344801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1160344800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1143410401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1143410400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1127685601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1127685600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1111960801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1111960800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1096840801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1096840800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1080511201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1080511200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1063576801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1063576800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1049061601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1049061600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1033336801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1033336800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1017612001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1017612000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1002492001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1002492000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -986162401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -986162400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -969228001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -969228000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -950479201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -950479200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -942012001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -942012000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -934668001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -934668000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -798073201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -798073200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -766623601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -766623600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -745455601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -745455600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -733273201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733273200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 228877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 228877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 243997199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 243997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 260326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 260326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 276051599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 276051600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Bucharest.json b/dojox/date/tests/tztests/tz_Europe-Bucharest.json
new file mode 100644
index 0000000..7f207b5
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Bucharest.json
@@ -0,0 +1,282 @@
+({
+	name: "date.timezone.Europe-Bucharest",
+	runTest: function(t){
+		var tz = "Europe/Bucharest";
+		doh.checkDate({tzOffset: -104.4, tzAbbr: "BMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -104.4, tzAbbr: "BMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -104.4, tzAbbr: "BMT"}, -1213148665000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1213148664000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1187056801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1187056800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1175479201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1175479200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1159754401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1159754400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1144029601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1144029600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1127700001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1127700000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1111975201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1111975200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1096250401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1096250400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1080525601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1080525600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1064800801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1064800800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1049076001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1049076000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1033351201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1033351200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1017626401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1017626400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1001901601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1001901600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -986176801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -986176800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -970452001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -970452000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -954727201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -954727200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 296603999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 296604000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 307486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 307486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 323816399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 323816400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 338939999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 338940000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 354671999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 354672000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 370396799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 370396800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 386121599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 386121600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 401846399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 401846400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 417571199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 417571200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 433295999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 433296000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 449020799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 449020800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 465350399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 465350400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 481075199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 481075200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 496799999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 496800000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 512524799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 512524800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 528249599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 528249600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 543974399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 543974400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 559699199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 559699200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 575423999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 575424000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 591148799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 591148800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 606873599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 606873600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 622598399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 622598400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 638323199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 638323200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 654652799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 654652800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670370399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670370400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686095199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686095200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717544799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717544800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733269599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733269600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 748994399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 748994400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764719199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764719200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796168799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796168800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828223199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828223200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846363599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846363600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Budapest.json b/dojox/date/tests/tztests/tz_Europe-Budapest.json
new file mode 100644
index 0000000..5c4e0b6
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Budapest.json
@@ -0,0 +1,316 @@
+({
+	name: "date.timezone.Europe-Budapest",
+	runTest: function(t){
+		var tz = "Europe/Budapest";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1693706401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1693706400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1663455601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1663455600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1650150001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1650150000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1633212001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1633212000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1617577201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1617577200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1600466401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1600466400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1587250801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1587250800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1569708001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1569708000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1554332401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1554332400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -906937201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -906937200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -778471201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -778471200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -762487201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -762487200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -749689201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -749689200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -733359601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733359600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -717634801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -717634800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -701910001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -701910000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -686185201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -686185200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -670460401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -670460400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -654130801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -654130800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -639010801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -639010800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -621990001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -621990000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -605660401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -605660400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -492656401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -492656400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -481168801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -481168800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -461120401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -461120400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -449632801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -449632800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -428547601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -428547600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -418269601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -418269600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -397094401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -397094400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -386809201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -386809200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323827199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323827200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Chisinau.json b/dojox/date/tests/tztests/tz_Europe-Chisinau.json
new file mode 100644
index 0000000..c8916a6
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Chisinau.json
@@ -0,0 +1,288 @@
+({
+	name: "date.timezone.Europe-Chisinau",
+	runTest: function(t){
+		var tz = "Europe/Chisinau";
+		doh.checkDate({tzOffset: -115, tzAbbr: "CMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -115, tzAbbr: "CMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -115, tzAbbr: "CMT"}, -1637114101000, tz, 1);
+		doh.checkDate({tzOffset: -104.4, tzAbbr: "BMT"}, -1637114100000, tz, 1);
+		doh.checkDate({tzOffset: -104.4, tzAbbr: "BMT"}, -1213148665000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1213148664000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1187056801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1187056800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1175479201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1175479200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1159754401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1159754400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1144029601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1144029600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1127700001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1127700000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1111975201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1111975200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1096250401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1096250400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1080525601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1080525600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1064800801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1064800800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1049076001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1049076000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1033351201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1033351200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1017626401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1017626400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1001901601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1001901600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -986176801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -986176800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -970452001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -970452000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -954727201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -954727200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -927165601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -927165600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -898138801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -898138800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -800157601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -800157600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 354920399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 354920400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 370727999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 370728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 386456399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 386456400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 417992399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 417992400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 465346799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 465346800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 481071599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 481071600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 496796399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 496796400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 512521199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 512521200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 528245999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 528246000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 543970799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 543970800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 559695599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 559695600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 575420399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 575420400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 641941199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 641941200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670377599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670377600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686102399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686102400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733269599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733269600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 748990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 748990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764719199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764719200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796168799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796168800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828223199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828223200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846363599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846363600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Copenhagen.json b/dojox/date/tests/tztests/tz_Europe-Copenhagen.json
new file mode 100644
index 0000000..4812c49
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Copenhagen.json
@@ -0,0 +1,276 @@
+({
+	name: "date.timezone.Europe-Copenhagen",
+	runTest: function(t){
+		var tz = "Europe/Copenhagen";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1692496801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1692496800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680490801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680490800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -935110801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -935110800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -769388401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -769388400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -747010801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -747010800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -736383601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -736383600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -715215601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -715215600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -706748401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -706748400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -683161201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -683161200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -675298801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -675298800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Dublin.json b/dojox/date/tests/tztests/tz_Europe-Dublin.json
new file mode 100644
index 0000000..c9f556a
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Dublin.json
@@ -0,0 +1,466 @@
+({
+	name: "date.timezone.Europe-Dublin",
+	runTest: function(t){
+		var tz = "Europe/Dublin";
+		doh.checkDate({tzOffset: 25.35, tzAbbr: "DMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 25.35, tzAbbr: "DMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 25.35, tzAbbr: "DMT"}, -1691962480000, tz, 1);
+		doh.checkDate({tzOffset: -34.65, tzAbbr: "IST"}, -1691962479000, tz, 1);
+		doh.checkDate({tzOffset: -34.65, tzAbbr: "IST"}, -1680471280000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1680471279000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1664143201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1664143200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1650146401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1650146400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1633903201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1633903200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1617487201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1617487200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1601848801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1601848800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1586037601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1586037600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1570399201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1570399200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1552168801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1552168800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1538344801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1538344800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1522533601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1522533600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1507500001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1507500000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1490565601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1490565600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1473631201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1473631200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1460930401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1460930400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1442786401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1442786400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1428876001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1428876000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1410732001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1410732000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1396216801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1396216800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1379282401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1379282400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1364767201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1364767200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1348437601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1348437600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1333317601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1333317600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1315778401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1315778400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1301263201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1301263200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1284328801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1284328800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1269813601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1269813600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1253484001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1253484000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1238364001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1238364000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1221429601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1221429600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1206914401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1206914400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1189980001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1189980000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1175464801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1175464800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1159135201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1159135200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1143410401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1143410400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1126476001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1126476000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1111960801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1111960800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1095631201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1095631200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1080511201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1080511200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1063576801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1063576800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1049061601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1049061600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1032127201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1032127200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1017612001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1017612000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1001282401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -1001282400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -986162401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -986162400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -969228001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -969228000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -950479201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -950479200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -942012001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -942012000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -733359601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -733359600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -719445601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -719445600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -699490801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -699490800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -684972001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -684972000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -668037601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -668037600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -654732001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -654732000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -636588001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -636588000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -622072801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -622072800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -605743201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -605743200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -590623201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -590623200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -574293601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -574293600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -558568801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -558568800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -542239201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -542239200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -527119201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -527119200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -512604001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -512604000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -496274401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -496274400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -481154401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -481154400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -464220001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -464220000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -449704801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -449704800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -432165601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -432165600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -417650401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -417650400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -401320801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -401320800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -386200801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -386200800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -369266401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -369266400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -354751201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -354751200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -337816801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -337816800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -323301601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -323301600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -306972001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -306972000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -291852001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -291852000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -276732001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -276732000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -257983201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -257983200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -245282401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -245282400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -226533601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -226533600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -213228001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -213228000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -195084001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -195084000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -182383201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -182383200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -163634401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -163634400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -150933601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -150933600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -132184801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -132184800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -119484001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -119484000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -100735201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -100735200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -88034401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -88034400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -68680801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -68680800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -59004001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -59004000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -37242001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, -37242000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 57722399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 57722400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 69818399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 69818400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 89171999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 89172000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 101267999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 101268000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 120621599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 120621600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 132717599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 132717600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 152071199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 152071200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 164167199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 164167200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 183520799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 183520800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 196221599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 196221600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 214970399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 214970400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 227671199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 227671200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 246419999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 246420000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 259120799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 259120800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 278474399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 278474400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 290570399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 290570400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 309923999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 309924000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 322019999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 322020000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 341373599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 341373600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 372819599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 372819600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 404269199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 404269200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 435718799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 435718800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 467773199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 467773200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 499222799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 499222800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 530672399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 530672400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 562121999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 562122000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 593571599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 593571600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 625625999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 625626000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 657075599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 657075600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 688525199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 688525200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 719974799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 719974800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 751424399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 751424400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 782873999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 782874000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 814323599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 814323600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "IST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Gibraltar.json b/dojox/date/tests/tztests/tz_Europe-Gibraltar.json
new file mode 100644
index 0000000..fb78a2c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Gibraltar.json
@@ -0,0 +1,406 @@
+({
+	name: "date.timezone.Europe-Gibraltar",
+	runTest: function(t){
+		var tz = "Europe/Gibraltar";
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1691964001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1691964000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1680472801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1680472800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1664143201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1664143200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1650146401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1650146400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1633903201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1633903200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1617487201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1617487200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1601848801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1601848800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1586037601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1586037600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1570399201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1570399200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1552168801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1552168800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1538344801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1538344800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1522533601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1522533600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1507500001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1507500000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1490565601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1490565600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1473631201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1473631200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1460930401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1460930400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1442786401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1442786400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1428876001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1428876000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1410732001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1410732000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1396216801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1396216800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1379282401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1379282400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1364767201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1364767200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1348437601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1348437600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1333317601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1333317600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1315778401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1315778400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1301263201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1301263200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1284328801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1284328800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1269813601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1269813600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1253484001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1253484000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1238364001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1238364000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1221429601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1221429600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1206914401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1206914400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1189980001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1189980000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1175464801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1175464800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1159135201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1159135200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1143410401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1143410400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1126476001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1126476000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1111960801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1111960800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1095631201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1095631200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1080511201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1080511200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1063576801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1063576800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1049061601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1049061600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1032127201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1032127200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1017612001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1017612000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1001282401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1001282400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -986162401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -986162400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -969228001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -969228000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -950479201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -950479200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -942012001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -942012000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -904518001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -904518000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -896050801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -896050800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -875487601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -875487600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -864601201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -864601200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -844038001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -844038000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -832546801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -832546800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -812588401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -812588400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -798073201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -798073200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -772066801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -772066800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -764805601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -764805600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -748476001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -748476000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -733356001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -733356000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -719445601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -719445600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -717030001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -717030000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -706748401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -706748400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -699487201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -699487200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -687996001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -687996000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -668037601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -668037600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -654732001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -654732000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -636588001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -636588000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -622072801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -622072800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -605743201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -605743200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -590623201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -590623200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -574293601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -574293600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -558568801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -558568800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -542239201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -542239200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -527119201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -527119200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -512604001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -512604000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -496274401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -496274400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -481154401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -481154400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -464220001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -464220000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -449704801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -449704800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -432165601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -432165600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -417650401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -417650400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -401320801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -401320800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Helsinki.json b/dojox/date/tests/tztests/tz_Europe-Helsinki.json
new file mode 100644
index 0000000..6ac34c5
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Helsinki.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.Europe-Helsinki",
+	runTest: function(t){
+		var tz = "Europe/Helsinki";
+		doh.checkDate({tzOffset: -99.8666666666667, tzAbbr: "HMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -99.8666666666667, tzAbbr: "HMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -99.8666666666667, tzAbbr: "HMT"}, -1535938793000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1535938792000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -875671201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -875671200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -859863601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -859863600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Istanbul.json b/dojox/date/tests/tztests/tz_Europe-Istanbul.json
new file mode 100644
index 0000000..ca718cd
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Istanbul.json
@@ -0,0 +1,352 @@
+({
+	name: "date.timezone.Europe-Istanbul",
+	runTest: function(t){
+		var tz = "Europe/Istanbul";
+		doh.checkDate({tzOffset: -116.933333333333, tzAbbr: "IMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -116.933333333333, tzAbbr: "IMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -116.933333333333, tzAbbr: "IMT"}, -1869875817000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1869875816000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1693706401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1693706400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1680490801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1680490800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1570413601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1570413600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1552186801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1552186800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1538359201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1538359200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1522551601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1522551600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1507514401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1507514400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1490583601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1490583600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1440208801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1440208800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1428030001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1428030000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1409709601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1409709600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1396494001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1396494000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -931140001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -931140000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -922762801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -922762800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -917834401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -917834400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -892436401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -892436400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -875844001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -875844000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -857358001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -857358000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -781063201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -781063200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -764737201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -764737200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -744343201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -744343200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -733806001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -733806000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -716436001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -716436000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -701924401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -701924400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -684986401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -684986400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -670474801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -670474800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -654141601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -654141600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -639025201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -639025200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -621828001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -621828000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -606970801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -606970800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -590032801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -590032800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -575434801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -575434800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -235620001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -235620000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -228279601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -228279600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -177732001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -177732000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -165726001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -165726000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 10533599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 10533600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 23835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 23835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 41983199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 41983200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 55285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 55285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 74037599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 74037600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 87339599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 87339600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 107909999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 107910000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 121219199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 121219200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 133919999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 133920000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 152675999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 152676000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 165362399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 165362400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 183502799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 183502800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 202427999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 202428000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 215557199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 215557200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 228866399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 228866400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 245797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 245797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 260315999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 260316000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 277246799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TRST"}, 277246800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TRST"}, 308779199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TRT"}, 308779200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TRT"}, 323827199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TRST"}, 323827200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TRST"}, 340228799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TRT"}, 340228800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TRT"}, 354671999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TRST"}, 354672000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TRST"}, 371678399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TRT"}, 371678400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TRT"}, 386121599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TRST"}, 386121600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TRST"}, 403127999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TRT"}, 403128000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TRT"}, 428446799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TRST"}, 428446800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "TRST"}, 433886399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TRT"}, 433886400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TRT"}, 482792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 482792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 496702799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 496702800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 512524799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 512524800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 528249599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 528249600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 543974399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 543974400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 559699199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 559699200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 575423999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 575424000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 591148799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 591148800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 606873599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 606873600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 622598399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 622598400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 638323199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 638323200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 654652799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 654652800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670373999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670374000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686098799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686098800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701823599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701823600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717548399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717548400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733273199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733273200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 748997999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 748998000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764722799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764722800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780447599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780447600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796172399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796172400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811897199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811897200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828226799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828226800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846370799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846370800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859676399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859676400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877820399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877820400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891125999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891126000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909269999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909270000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922575599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922575600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941324399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941324400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954025199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954025200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972773999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972774000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985474799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985474800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004223599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004223600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017529199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017529200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035673199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035673200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048978799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048978800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067122799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067122800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080428399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080428400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099177199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099177200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111877999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111878000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130626799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130626800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143327599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143327600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162076399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162076400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Kaliningrad.json b/dojox/date/tests/tztests/tz_Europe-Kaliningrad.json
new file mode 100644
index 0000000..c96c934
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Kaliningrad.json
@@ -0,0 +1,272 @@
+({
+	name: "date.timezone.Europe-Kaliningrad",
+	runTest: function(t){
+		var tz = "Europe/Kaliningrad";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1693706401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1693706400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1663455601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1663455600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1650150001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1650150000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1632006001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1632006000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1618700401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1618700400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -938905201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -938905200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -788922001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CET"}, -788922000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CET"}, -778730401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CEST"}, -778730400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "CEST"}, -762663601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CET"}, -762663600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CET"}, -757389601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -757389600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 354920399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 354920400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 370727999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 370728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 386456399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 386456400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 417992399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 417992400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 465346799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 465346800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 481071599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 481071600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 496796399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 496796400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 512521199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 512521200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 528245999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 528246000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 543970799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 543970800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 559695599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 559695600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 575420399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 575420400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 638319599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 638319600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 654649199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 654649200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 670373999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670374000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686102399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686102400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701816399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701816400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717537599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717537600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733276799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733276800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 749001599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 749001600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764726399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764726400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780451199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780451200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796175999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796176000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811900799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811900800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828230399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828230400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846374399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846374400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859679999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859680000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877823999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877824000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891129599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891129600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909273599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909273600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922579199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922579200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941327999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941328000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954028799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954028800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972777599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972777600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985478399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985478400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004227199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004227200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017532799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017532800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035676799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035676800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048982399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048982400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067126399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067126400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080431999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080432000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099180799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099180800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111881599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111881600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130630399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130630400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143331199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143331200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162079999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162080000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174780799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174780800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193529599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193529600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206835199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206835200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224979199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224979200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238284799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238284800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256428799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256428800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269734399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269734400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288483199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288483200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301183999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301184000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319932799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319932800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332633599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332633600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351382399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351382400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364687999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364688000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382831999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382832000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396137599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396137600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414281599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414281600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427587199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427587200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445731199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445731200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459036799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459036800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477785599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477785600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490486399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490486400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509235199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509235200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521935999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521936000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540684799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540684800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553990399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553990400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572134399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572134400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585439999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585440000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603583999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603584000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616889599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616889600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635638399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635638400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648339199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648339200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667087999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667088000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679788799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679788800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698537599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698537600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711843199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711843200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729987199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729987200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743292799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743292800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761436799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761436800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774742399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774742400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792886399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792886400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806191999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806192000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824940799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824940800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837641599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837641600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856390399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856390400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869091199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869091200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887839999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887840000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901145599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901145600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919289599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919289600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932595199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932595200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950739199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950739200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964044799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964044800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982793599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982793600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995494399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995494400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014243199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014243200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026943999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026944000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045692799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045692800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058393599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058393600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077142399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077142400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090447999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090448000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108591999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108592000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121897599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121897600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140041599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140041600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Kiev.json b/dojox/date/tests/tztests/tz_Europe-Kiev.json
new file mode 100644
index 0000000..3160b42
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Kiev.json
@@ -0,0 +1,248 @@
+({
+	name: "date.timezone.Europe-Kiev",
+	runTest: function(t){
+		var tz = "Europe/Kiev";
+		doh.checkDate({tzOffset: -122.066666666667, tzAbbr: "KMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -122.066666666667, tzAbbr: "KMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -122.066666666667, tzAbbr: "KMT"}, -1441159325000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1441159324000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1247536801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -1247536800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -892522801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -892522800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -825382801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -825382800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 354920399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 354920400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 370727999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 370728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 386456399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 386456400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 417992399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 417992400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 465346799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 465346800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 481071599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 481071600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 496796399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 496796400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 512521199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 512521200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 528245999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 528246000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 543970799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 543970800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 559695599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 559695600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 575420399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 575420400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 646786799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 646786800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733269599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733269600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 748990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 748990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764719199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764719200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Lisbon.json b/dojox/date/tests/tztests/tz_Europe-Lisbon.json
new file mode 100644
index 0000000..ddb6aca
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Lisbon.json
@@ -0,0 +1,454 @@
+({
+	name: "date.timezone.Europe-Lisbon",
+	runTest: function(t){
+		var tz = "Europe/Lisbon";
+		doh.checkDate({tzOffset: 36.5333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 36.5333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 36.5333333333333, tzAbbr: "LMT"}, -1830381809000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1830381808000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1689555601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1689555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1677801601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1677801600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1667437201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1667437200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1647738001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1647738000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1635814801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1635814800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1616202001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1616202000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1604365201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1604365200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1584666001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1584666000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1572742801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1572742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1553043601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1553043600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1541206801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1541206800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1521507601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1521507600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1442451601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1442451600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1426813201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1426813200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1379293201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1379293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1364778001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1364778000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1348448401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1348448400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1333328401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1333328400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1316394001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1316394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1301274001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1301274000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1284339601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1284339600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1269824401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1269824400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1221440401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1221440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1206925201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1206925200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1191200401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1191200400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1175475601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1175475600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1127696401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1127696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1111971601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1111971600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1096851601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1096851600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1080522001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1080522000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1063587601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1063587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1049072401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1049072400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1033347601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1033347600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1017622801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1017622800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1002502801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1002502800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -986173201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -986173200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -969238801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -969238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -950490001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -950490000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -942022801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -942022800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -922669201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -922669200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -906944401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -906944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -891133201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -891133200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -877309201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -877309200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -873684001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -873684000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -864007201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -864007200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -857955601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -857955600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -845859601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -845859600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -842839201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -842839200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -831348001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -831348000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -825901201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -825901200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -814410001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -814410000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -810784801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -810784800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -799898401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -799898400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -794451601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -794451600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -782960401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -782960400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -779335201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -779335200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -768448801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -768448800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -763002001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -763002000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -749091601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -749091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -733366801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -733366800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -717631201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -717631200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -701906401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -701906400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -686181601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -686181600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -670456801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -670456800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -654732001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -654732000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -639007201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -639007200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -591832801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -591832800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -575503201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -575503200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -559778401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -559778400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -544053601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -544053600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -528328801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -528328800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -512604001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -512604000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -496879201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -496879200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -481154401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -481154400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -465429601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -465429600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -449704801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -449704800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -433980001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -433980000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -417650401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -417650400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -401925601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -401925600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -386200801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -386200800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -370476001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -370476000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -354751201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -354751200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -339026401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -339026400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -323301601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -323301600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -307576801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -307576800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -291852001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -291852000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -276127201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -276127200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -260402401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -260402400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -244677601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -244677600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -228348001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -228348000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -212623201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -212623200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -196898401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -196898400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -181173601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -181173600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -165448801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -165448800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -149724001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -149724000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -133999201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -133999200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -118274401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -118274400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 212543999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 212544000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 228268799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 228268800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 243993599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 243993600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 260323199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 260323200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 276047999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 276048000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 291772799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 291772800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 323222399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 323222400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 417578399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 417578400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-London.json b/dojox/date/tests/tztests/tz_Europe-London.json
new file mode 100644
index 0000000..e3a050c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-London.json
@@ -0,0 +1,494 @@
+({
+	name: "date.timezone.Europe-London",
+	runTest: function(t){
+		var tz = "Europe/London";
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1691964001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1691964000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1680472801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1680472800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1664143201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1664143200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1650146401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1650146400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1633903201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1633903200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1617487201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1617487200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1601848801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1601848800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1586037601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1586037600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1570399201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1570399200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1552168801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1552168800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1538344801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1538344800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1522533601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1522533600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1507500001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1507500000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1490565601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1490565600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1473631201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1473631200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1460930401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1460930400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1442786401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1442786400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1428876001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1428876000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1410732001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1410732000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1396216801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1396216800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1379282401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1379282400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1364767201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1364767200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1348437601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1348437600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1333317601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1333317600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1315778401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1315778400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1301263201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1301263200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1284328801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1284328800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1269813601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1269813600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1253484001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1253484000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1238364001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1238364000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1221429601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1221429600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1206914401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1206914400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1189980001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1189980000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1175464801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1175464800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1159135201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1159135200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1143410401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1143410400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1126476001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1126476000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1111960801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1111960800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1095631201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1095631200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1080511201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1080511200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1063576801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1063576800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1049061601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1049061600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1032127201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1032127200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1017612001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1017612000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -1001282401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -1001282400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -986162401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -986162400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -969228001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -969228000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -950479201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -950479200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -942012001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -942012000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -904518001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -904518000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -896050801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -896050800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -875487601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -875487600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -864601201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -864601200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -844038001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -844038000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -832546801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -832546800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -812588401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -812588400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -798073201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -798073200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -772066801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -772066800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -764805601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -764805600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -748476001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -748476000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -733356001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -733356000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -719445601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -719445600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -717030001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -717030000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "BDST"}, -706748401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -706748400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -699487201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -699487200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -687996001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -687996000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -668037601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -668037600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -654732001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -654732000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -636588001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -636588000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -622072801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -622072800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -605743201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -605743200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -590623201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -590623200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -574293601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -574293600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -558568801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -558568800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -542239201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -542239200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -527119201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -527119200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -512604001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -512604000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -496274401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -496274400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -481154401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -481154400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -464220001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -464220000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -449704801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -449704800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -432165601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -432165600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -417650401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -417650400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -401320801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -401320800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -386200801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -386200800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -369266401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -369266400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -354751201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -354751200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -337816801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -337816800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -323301601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -323301600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -306972001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -306972000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -291852001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -291852000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -276732001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -276732000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -257983201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -257983200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -245282401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -245282400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -226533601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -226533600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -213228001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -213228000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -195084001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -195084000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -182383201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -182383200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -163634401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -163634400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -150933601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -150933600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -132184801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -132184800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -119484001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -119484000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -100735201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -100735200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -88034401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -88034400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -68680801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -68680800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, -59004001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -59004000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -37242001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, -37242000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 57722399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 57722400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 69818399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 69818400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 89171999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 89172000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 101267999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 101268000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 120621599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 120621600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 132717599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 132717600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 152071199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 152071200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 164167199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 164167200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 183520799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 183520800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 196221599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 196221600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 214970399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 214970400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 227671199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 227671200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 246419999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 246420000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 259120799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 259120800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 278474399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 278474400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 290570399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 290570400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 309923999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 309924000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 322019999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 322020000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 341373599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 341373600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 372819599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 372819600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 404269199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 404269200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 435718799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 435718800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 467773199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 467773200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 499222799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 499222800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 530672399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 530672400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 562121999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 562122000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 593571599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 593571600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 625625999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 625626000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 657075599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 657075600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 688525199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 688525200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 719974799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 719974800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 751424399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 751424400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 782873999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 782874000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 814323599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 814323600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "GMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "BST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Luxembourg.json b/dojox/date/tests/tztests/tz_Europe-Luxembourg.json
new file mode 100644
index 0000000..32f9428
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Luxembourg.json
@@ -0,0 +1,378 @@
+({
+	name: "date.timezone.Europe-Luxembourg",
+	runTest: function(t){
+		var tz = "Europe/Luxembourg";
+		doh.checkDate({tzOffset: -24.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -24.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -24.6, tzAbbr: "LMT"}, -2069713477000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2069713476000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1692496801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1692496800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1662343201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1662343200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1650157201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1650157200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1632006001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1632006000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1618700401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1618700400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1612659601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1612659600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1604278801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1604278800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1585519201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1585519200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1574038801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1574038800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1552258801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1552258800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1539997201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1539997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1520550001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1520550000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1507510801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1507510800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1490572801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1490572800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1473642001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1473642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1459119601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1459119600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1444006801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1444006800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1427673601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1427673600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1411866001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1411866000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1396224001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1396224000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1379293201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1379293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1364774401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1364774400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1348448401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1348448400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1333324801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1333324800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1316394001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1316394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1301270401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1301270400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1284339601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1284339600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1269813601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1269813600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1253484001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1253484000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1238364001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1238364000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1221429601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1221429600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1206914401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1206914400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1191189601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1191189600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1175464801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1175464800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1160344801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1160344800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1143410401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1143410400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1127685601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1127685600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1111960801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1111960800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1096840801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1096840800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1080511201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1080511200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1063576801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1063576800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1049061601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1049061600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1033336801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1033336800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1017612001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1017612000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1002492001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1002492000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -986162401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -986162400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -969228001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -969228000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -950479201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -950479200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -942012001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -942012000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -935186401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEST"}, -935186400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEST"}, -797986801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -797986800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -766623601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -766623600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -745455601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -745455600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -733273201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733273200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 228877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 228877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 243997199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 243997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 260326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 260326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 276051599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 276051600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Madrid.json b/dojox/date/tests/tztests/tz_Europe-Madrid.json
new file mode 100644
index 0000000..62ac03f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Madrid.json
@@ -0,0 +1,338 @@
+({
+	name: "date.timezone.Europe-Madrid",
+	runTest: function(t){
+		var tz = "Europe/Madrid";
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1661734801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1661734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1648429201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1648429200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1631926801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1631926800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1616893201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1616893200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1601254801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1601254800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1585357201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1585357200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1442451601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1442451600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1427677201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1427677200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1379293201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1379293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1364778001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1364778000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1348448401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1348448400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1333328401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1333328400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1316394001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1316394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1301274001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1301274000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1284339601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1284339600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1269824401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1269824400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1029114001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1029114000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1017622801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1017622800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1002848401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1002848400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -986173201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -986173200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -969238801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -969238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -954118801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -954118800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -940208401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -940208400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -873079201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -873079200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -862538401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -862538400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -842839201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -842839200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -828237601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -828237600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -811389601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -811389600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -796010401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -796010400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -779940001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -779940000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -765421201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -765421200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -748490401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -748490400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -733888801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733888800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -652327201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -652327200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -639190801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -639190800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 135122399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 135122400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 150245999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 150246000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 167176799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 167176800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 181695599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 181695600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 196811999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 196812000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 212540399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 212540400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 228866399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 228866400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 243989999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 243990000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 260402399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 260402400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 276044399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 276044400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Malta.json b/dojox/date/tests/tztests/tz_Europe-Malta.json
new file mode 100644
index 0000000..a26263f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Malta.json
@@ -0,0 +1,348 @@
+({
+	name: "date.timezone.Europe-Malta",
+	runTest: function(t){
+		var tz = "Europe/Malta";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1690851601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1690851600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1664758801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1664758800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1649034001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1649034000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1635123601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1635123600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1616979601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1616979600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1604278801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1604278800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1585530001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1585530000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1571014801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1571014800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1555290001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1555290000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -932432401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -932432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -766717201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -766717200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -750898801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -750898800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -733359601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733359600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -719456401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -719456400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -701917201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -701917200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -689209201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -689209200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -670460401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -670460400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -114051601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -114051600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -103168801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -103168800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -81997201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -81997200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -71719201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -71719200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -50547601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -50547600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -40269601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -40269600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -18493201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -18493200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -8215201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -8215200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 12956399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 12956400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 23234399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 23234400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 43801199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 43801200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 54687599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 54687600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 75855599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 75855600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 86738399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 86738400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 102380399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 102380400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 118105199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 118105200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 135730799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 135730800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 148517999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 148518000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 167187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 167187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 180489599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 180489600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 198637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 198637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 211939199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 211939200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 230086799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 230086800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 243388799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 243388800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 261536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 261536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 274838399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 274838400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 292985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 292986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 306287999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 306288000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323312399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323312400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338342399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338342400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Minsk.json b/dojox/date/tests/tztests/tz_Europe-Minsk.json
new file mode 100644
index 0000000..b844f56
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Minsk.json
@@ -0,0 +1,252 @@
+({
+	name: "date.timezone.Europe-Minsk",
+	runTest: function(t){
+		var tz = "Europe/Minsk";
+		doh.checkDate({tzOffset: -110, tzAbbr: "MMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -110, tzAbbr: "MMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -110, tzAbbr: "MMT"}, -1441158601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1441158600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1247536801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -1247536800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -899780401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -899780400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -804650401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -804650400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 354920399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 354920400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 370727999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 370728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 386456399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 386456400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 417992399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 417992400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 465346799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 465346800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 481071599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 481071600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 496796399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 496796400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 512521199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 512521200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 528245999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 528246000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 543970799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 543970800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 559695599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 559695600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 575420399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 575420400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 670373999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670374000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686102399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686102400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717544799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717544800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733276799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733276800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 749001599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 749001600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764726399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764726400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780451199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780451200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796175999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796176000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811900799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811900800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828230399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828230400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846374399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846374400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859679999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859680000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877823999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877824000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891129599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891129600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909273599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909273600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922579199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922579200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941327999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941328000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954028799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954028800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972777599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972777600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985478399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985478400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004227199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004227200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017532799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017532800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035676799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035676800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048982399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048982400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067126399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067126400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080431999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080432000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099180799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099180800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111881599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111881600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130630399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130630400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143331199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143331200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162079999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162080000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174780799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174780800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193529599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193529600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206835199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206835200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224979199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224979200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238284799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238284800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256428799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256428800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269734399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269734400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288483199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288483200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301183999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301184000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319932799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319932800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332633599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332633600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351382399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351382400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364687999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364688000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382831999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382832000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396137599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396137600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414281599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414281600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427587199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427587200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445731199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445731200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459036799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459036800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477785599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477785600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490486399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490486400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509235199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509235200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521935999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521936000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540684799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540684800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553990399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553990400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572134399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572134400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585439999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585440000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603583999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603584000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616889599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616889600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635638399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635638400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648339199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648339200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667087999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667088000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679788799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679788800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698537599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698537600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711843199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711843200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729987199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729987200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743292799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743292800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761436799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761436800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774742399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774742400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792886399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792886400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806191999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806192000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824940799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824940800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837641599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837641600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856390399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856390400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869091199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869091200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887839999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887840000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901145599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901145600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919289599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919289600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932595199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932595200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950739199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950739200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964044799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964044800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982793599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982793600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995494399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995494400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014243199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014243200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026943999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026944000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045692799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045692800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058393599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058393600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077142399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077142400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090447999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090448000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108591999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108592000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121897599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121897600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140041599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140041600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Monaco.json b/dojox/date/tests/tztests/tz_Europe-Monaco.json
new file mode 100644
index 0000000..fcc0726
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Monaco.json
@@ -0,0 +1,380 @@
+({
+	name: "date.timezone.Europe-Monaco",
+	runTest: function(t){
+		var tz = "Europe/Monaco";
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -1855958962000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1855958961000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1689814801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1689814800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1680397201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1680397200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1665363601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1665363600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1648342801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1648342800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1635123601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1635123600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1616893201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1616893200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1604278801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1604278800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1585443601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1585443600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1574038801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1574038800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1552266001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1552266000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1539997201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1539997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1520557201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1520557200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1507510801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1507510800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1490576401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1490576400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1470618001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1470618000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1459126801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1459126800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1444006801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1444006800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1427677201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1427677200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1411952401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1411952400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1396227601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1396227600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1379293201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1379293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1364778001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1364778000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1348448401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1348448400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1333328401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1333328400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1316394001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1316394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1301274001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1301274000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1284339601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1284339600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1269824401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1269824400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1253494801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1253494800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1238374801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1238374800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1221440401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1221440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1206925201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1206925200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1191200401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1191200400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1175475601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1175475600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1160355601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1160355600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1143421201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1143421200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1127696401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1127696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1111971601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1111971600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1096851601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1096851600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1080522001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1080522000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1063587601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1063587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1049072401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1049072400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1033347601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1033347600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1017622801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1017622800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1002502801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1002502800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -986173201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -986173200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -969238801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -969238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -950490001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -950490000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -942012001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -942012000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -904438801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -904438800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -891136801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -891136800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -877827601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -796266001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -796266000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -766623601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -766623600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 196819199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 196819200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 212540399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 212540400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 228877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 228877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 243997199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 243997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 260326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 260326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 276051599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 276051600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Moscow.json b/dojox/date/tests/tztests/tz_Europe-Moscow.json
new file mode 100644
index 0000000..13215e9
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Moscow.json
@@ -0,0 +1,270 @@
+({
+	name: "date.timezone.Europe-Moscow",
+	runTest: function(t){
+		var tz = "Europe/Moscow";
+		doh.checkDate({tzOffset: -150, tzAbbr: "MMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -150, tzAbbr: "MMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -150, tzAbbr: "MMT"}, -1688265001000, tz, 1);
+		doh.checkDate({tzOffset: -150.8, tzAbbr: "MMT"}, -1688265000000, tz, 1);
+		doh.checkDate({tzOffset: -150.8, tzAbbr: "MMT"}, -1656819049000, tz, 1);
+		doh.checkDate({tzOffset: -210.8, tzAbbr: "MST"}, -1656819048000, tz, 1);
+		doh.checkDate({tzOffset: -210.8, tzAbbr: "MST"}, -1641353449000, tz, 1);
+		doh.checkDate({tzOffset: -150.8, tzAbbr: "MMT"}, -1641353448000, tz, 1);
+		doh.checkDate({tzOffset: -150.8, tzAbbr: "MMT"}, -1627965049000, tz, 1);
+		doh.checkDate({tzOffset: -270.8, tzAbbr: "MDST"}, -1627965048000, tz, 1);
+		doh.checkDate({tzOffset: -270.8, tzAbbr: "MDST"}, -1618716649000, tz, 1);
+		doh.checkDate({tzOffset: -210.8, tzAbbr: "MST"}, -1618716648000, tz, 1);
+		doh.checkDate({tzOffset: -210.8, tzAbbr: "MST"}, -1596429049000, tz, 1);
+		doh.checkDate({tzOffset: -270.8, tzAbbr: "MDST"}, -1596429048000, tz, 1);
+		doh.checkDate({tzOffset: -270.8, tzAbbr: "MDST"}, -1593829849000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, -1593829848000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, -1589860801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -1589860800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -1542427201000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, -1542427200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, -1539493201000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "MSD"}, -1539493200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "MSD"}, -1525323601000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, -1525323600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, -1522728001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -1522728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -1491188401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1491188400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1247536801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -1247536800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 354920399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 354920400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 370727999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 370728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 386456399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 386456400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 417992399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 417992400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 465346799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 465346800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 481071599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 481071600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 496796399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 496796400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 512521199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 512521200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 528245999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 528246000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 543970799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 543970800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 559695599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 559695600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 575420399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 575420400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 638319599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 638319600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 654649199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 654649200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 670373999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670374000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686102399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686102400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 695779199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 695779200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 701812799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 701812800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 717533999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 717534000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 733273199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 733273200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 748997999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 748998000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 764722799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 764722800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 780447599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 780447600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 796172399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 796172400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 811897199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 811897200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 828226799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 828226800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 846370799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 846370800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 859676399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 859676400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 877820399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 877820400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 891125999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 891126000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 909269999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 909270000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 922575599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 922575600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 941324399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 941324400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 954025199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 954025200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 972773999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 972774000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 985474799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 985474800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1004223599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1004223600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1017529199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1017529200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1035673199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1035673200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1048978799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1048978800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1067122799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1067122800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1080428399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1080428400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1099177199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1099177200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1111877999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1111878000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1130626799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1130626800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1143327599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1143327600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1162076399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1162076400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1174777199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1174777200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1193525999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1193526000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1206831599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1206831600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1224975599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1224975600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1238281199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1238281200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1256425199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1256425200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1269730799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1269730800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1288479599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1288479600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1301180399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1301180400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1319929199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1319929200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1332629999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1332630000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1351378799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1351378800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1364684399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1364684400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1382828399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1382828400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1396133999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1396134000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1414277999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1414278000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1427583599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1427583600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1445727599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1445727600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1459033199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1459033200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1477781999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1477782000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1490482799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1490482800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1509231599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1509231600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1521932399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1521932400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1540681199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1540681200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1553986799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1553986800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1572130799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1572130800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1585436399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1585436400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1603580399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1603580400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1616885999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1616886000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1635634799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1635634800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1648335599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1648335600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1667084399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1667084400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1679785199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1679785200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1698533999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1698534000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1711839599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1711839600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1729983599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1729983600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1743289199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1743289200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1761433199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1761433200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1774738799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1774738800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1792882799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1792882800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1806188399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1806188400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1824937199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1824937200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1837637999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1837638000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1856386799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1856386800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1869087599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1869087600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1887836399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1887836400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1901141999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1901142000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1919285999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1919286000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1932591599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1932591600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1950735599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1950735600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1964041199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1964041200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1982789999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1982790000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1995490799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1995490800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 2014239599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 2014239600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 2026940399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 2026940400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 2045689199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 2045689200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 2058389999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 2058390000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 2077138799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 2077138800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 2090444399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 2090444400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 2108588399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 2108588400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 2121893999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 2121894000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 2140037999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 2140038000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Oslo.json b/dojox/date/tests/tztests/tz_Europe-Oslo.json
new file mode 100644
index 0000000..552de2d
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Oslo.json
@@ -0,0 +1,292 @@
+({
+	name: "date.timezone.Europe-Oslo",
+	runTest: function(t){
+		var tz = "Europe/Oslo";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1691884801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1691884800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680573601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680573600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -927511201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -927511200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -765327601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -765327600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -340844401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -340844400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -324514801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -324514800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -308790001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -308790000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -293065201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -293065200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -277340401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -277340400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -261615601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -261615600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -245890801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -245890800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -230166001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -230166000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -214441201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -214441200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -198716401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -198716400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -182991601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -182991600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -166662001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -166662000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -147913201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -147913200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -135212401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -135212400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Paris.json b/dojox/date/tests/tztests/tz_Europe-Paris.json
new file mode 100644
index 0000000..a09e6c5
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Paris.json
@@ -0,0 +1,378 @@
+({
+	name: "date.timezone.Europe-Paris",
+	runTest: function(t){
+		var tz = "Europe/Paris";
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -9.35, tzAbbr: "PMT"}, -1855958902000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1855958901000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1689814801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1689814800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1680397201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1680397200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1665363601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1665363600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1648342801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1648342800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1635123601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1635123600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1616893201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1616893200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1604278801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1604278800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1585443601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1585443600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1574038801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1574038800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1552266001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1552266000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1539997201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1539997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1520557201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1520557200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1507510801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1507510800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1490576401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1490576400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1470618001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1470618000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1459126801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1459126800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1444006801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1444006800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1427677201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1427677200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1411952401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1411952400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1396227601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1396227600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1379293201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1379293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1364778001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1364778000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1348448401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1348448400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1333328401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1333328400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1316394001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1316394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1301274001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1301274000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1284339601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1284339600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1269824401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1269824400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1253494801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1253494800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1238374801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1238374800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1221440401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1221440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1206925201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1206925200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1191200401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1191200400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1175475601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1175475600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1160355601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1160355600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1143421201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1143421200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1127696401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1127696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1111971601000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1111971600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1096851601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1096851600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1080522001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1080522000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1063587601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1063587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1049072401000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1049072400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1033347601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1033347600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1017622801000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1017622800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -1002502801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -1002502800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -986173201000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -986173200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -969238801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -969238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -950490001000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -950490000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -942012001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -942012000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -932436001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -932436000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -800071201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -800071200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -796266001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -796266000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "WEMT"}, -766623601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -766623600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 196819199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 196819200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 212540399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 212540400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 228877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 228877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 243997199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 243997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 260326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 260326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 276051599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 276051600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Prague.json b/dojox/date/tests/tztests/tz_Europe-Prague.json
new file mode 100644
index 0000000..bdba42f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Prague.json
@@ -0,0 +1,292 @@
+({
+	name: "date.timezone.Europe-Prague",
+	runTest: function(t){
+		var tz = "Europe/Prague";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1693706401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1693706400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1663455601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1663455600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1650150001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1650150000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1632006001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1632006000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1618700401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1618700400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -938905201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -938905200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -798073201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -798073200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -780534001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -780534000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -761180401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -761180400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -746578801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -746578800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -733359601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733359600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -716425201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -716425200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -701910001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -701910000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -684975601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -684975600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -670460401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -670460400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -654217201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -654217200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -639010801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -639010800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Riga.json b/dojox/date/tests/tztests/tz_Europe-Riga.json
new file mode 100644
index 0000000..1c581fe
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Riga.json
@@ -0,0 +1,262 @@
+({
+	name: "date.timezone.Europe-Riga",
+	runTest: function(t){
+		var tz = "Europe/Riga";
+		doh.checkDate({tzOffset: -96.4, tzAbbr: "RMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -96.4, tzAbbr: "RMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -96.4, tzAbbr: "RMT"}, -1632008185000, tz, 1);
+		doh.checkDate({tzOffset: -156.4, tzAbbr: "LST"}, -1632008184000, tz, 1);
+		doh.checkDate({tzOffset: -156.4, tzAbbr: "LST"}, -1618702585000, tz, 1);
+		doh.checkDate({tzOffset: -96.4, tzAbbr: "RMT"}, -1618702584000, tz, 1);
+		doh.checkDate({tzOffset: -96.4, tzAbbr: "RMT"}, -1601681785000, tz, 1);
+		doh.checkDate({tzOffset: -156.4, tzAbbr: "LST"}, -1601681784000, tz, 1);
+		doh.checkDate({tzOffset: -156.4, tzAbbr: "LST"}, -1597275385000, tz, 1);
+		doh.checkDate({tzOffset: -96.4, tzAbbr: "RMT"}, -1597275384000, tz, 1);
+		doh.checkDate({tzOffset: -96.4, tzAbbr: "RMT"}, -1377308185000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1377308184000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -928029601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -928029600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -899521201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -899521200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -795834001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -795834000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 354920399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 354920400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 370727999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 370728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 386456399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 386456400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 417992399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 417992400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 465346799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 465346800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 481071599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 481071600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 496796399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 496796400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 512521199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 512521200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 528245999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 528246000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 543970799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 543970800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 559695599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 559695600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 575420399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 575420400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 622598399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 622598400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 638323199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 638323200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 654652799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 654652800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670377599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670377600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686102399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686102400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701827199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701827200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717551999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717552000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733276799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733276800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 749001599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 749001600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764726399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764726400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780451199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780451200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796175999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796176000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811900799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811900800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828230399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828230400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 843955199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 843955200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Rome.json b/dojox/date/tests/tztests/tz_Europe-Rome.json
new file mode 100644
index 0000000..b17c070
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Rome.json
@@ -0,0 +1,348 @@
+({
+	name: "date.timezone.Europe-Rome",
+	runTest: function(t){
+		var tz = "Europe/Rome";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1690851601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1690851600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1664758801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1664758800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1649034001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1649034000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1635123601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1635123600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1616979601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1616979600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1604278801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1604278800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1585530001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1585530000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1571014801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1571014800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1555290001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1555290000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -932432401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -932432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -798080401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -798080400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -766717201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -766717200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -750898801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -750898800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -733359601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733359600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -719456401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -719456400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -701917201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -701917200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -689209201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -689209200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -670460401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -670460400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -114051601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -114051600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -103168801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -103168800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -81997201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -81997200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -71719201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -71719200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -50547601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -50547600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -40269601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -40269600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -18493201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -18493200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -8215201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -8215200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 12956399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 12956400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 23234399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 23234400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 43801199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 43801200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 54687599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 54687600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 75855599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 75855600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 86738399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 86738400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 107909999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 107910000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 118187999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 118188000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 138754799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 138754800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 149637599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 149637600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 170809199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 170809200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 181090799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 181090800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 202258799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 202258800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 212540399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 212540400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 233103599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 233103600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 243989999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 243990000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 265157999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 265158000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 276044399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 276044400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 296607599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 296607600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 307493999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 307494000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Samara.json b/dojox/date/tests/tztests/tz_Europe-Samara.json
new file mode 100644
index 0000000..b7c9cca
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Samara.json
@@ -0,0 +1,248 @@
+({
+	name: "date.timezone.Europe-Samara",
+	runTest: function(t){
+		var tz = "Europe/Samara";
+		doh.checkDate({tzOffset: -200.6, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -200.6, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -200.6, tzAbbr: "LMT"}, -1593825637000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SAMT"}, -1593825636000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "SAMT"}, -1247540401000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, -1247540400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, -1102305601000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, -1102305600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 354916799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 354916800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 370724399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 370724400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 386452799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 386452800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 402260399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 402260400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 417988799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 417988800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 433796399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 433796400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 449611199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 449611200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 465343199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 465343200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 481067999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 481068000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 496792799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 496792800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 512517599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 512517600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 528242399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 528242400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 543967199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 543967200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 559691999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 559692000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 575416799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 575416800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "KUYST"}, 591141599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 591141600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYT"}, 606866399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYST"}, 606866400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYST"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "KUYT"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "KUYT"}, 638319599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYST"}, 638319600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "KUYST"}, 654649199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "KUYT"}, 654649200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "KUYT"}, 670373999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "KUYST"}, 670374000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "KUYST"}, 686102399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "KUYT"}, 686102400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "KUYT"}, 687916799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 687916800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 701809199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 701809200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 717530399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 717530400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 733269599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 733269600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 748994399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 748994400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 764719199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 764719200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 780443999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 780444000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 796168799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 796168800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 811893599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 811893600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 828223199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 828223200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 846367199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 846367200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 859672799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 859672800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 877816799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 877816800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 891122399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 891122400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 909266399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 909266400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 922571999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 922572000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 941320799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 941320800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 954021599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 954021600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 972770399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 972770400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 985471199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 985471200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1004219999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1004220000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1017525599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1017525600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1035669599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1035669600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1048975199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1048975200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1067119199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1067119200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1080424799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1080424800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1099173599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1099173600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1111874399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1111874400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1130623199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1130623200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1143323999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1143324000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1162072799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1162072800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1174773599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1174773600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1193522399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1193522400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1206827999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1206828000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1224971999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1224972000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1238277599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1238277600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1256421599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1256421600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1269727199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1269727200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1288475999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1288476000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1301176799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1301176800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1319925599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1319925600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1332626399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1332626400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1351375199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1351375200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1364680799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1364680800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1382824799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1382824800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1396130399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1396130400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1414274399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1414274400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1427579999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1427580000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1445723999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1445724000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1459029599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1459029600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1477778399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1477778400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1490479199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1490479200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1509227999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1509228000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1521928799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1521928800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1540677599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1540677600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1553983199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1553983200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1572127199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1572127200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1585432799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1585432800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1603576799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1603576800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1616882399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1616882400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1635631199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1635631200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1648331999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1648332000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1667080799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1667080800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1679781599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1679781600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1698530399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1698530400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1711835999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1711836000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1729979999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1729980000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1743285599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1743285600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1761429599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1761429600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1774735199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1774735200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1792879199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1792879200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1806184799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1806184800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1824933599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1824933600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1837634399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1837634400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1856383199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1856383200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1869083999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1869084000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1887832799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1887832800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1901138399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1901138400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1919282399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1919282400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1932587999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1932588000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1950731999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1950732000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1964037599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1964037600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1982786399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1982786400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1995487199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1995487200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 2014235999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 2014236000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 2026936799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 2026936800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 2045685599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 2045685600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 2058386399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 2058386400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 2077135199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 2077135200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 2090440799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 2090440800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 2108584799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 2108584800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 2121890399000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 2121890400000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 2140034399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 2140034400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SAMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "SAMST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Simferopol.json b/dojox/date/tests/tztests/tz_Europe-Simferopol.json
new file mode 100644
index 0000000..5118747
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Simferopol.json
@@ -0,0 +1,252 @@
+({
+	name: "date.timezone.Europe-Simferopol",
+	runTest: function(t){
+		var tz = "Europe/Simferopol";
+		doh.checkDate({tzOffset: -136, tzAbbr: "SMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -136, tzAbbr: "SMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -136, tzAbbr: "SMT"}, -1441160161000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1441160160000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1247536801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -1247536800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -888894001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -888894000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -811648801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -811648800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 354920399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 354920400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 370727999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 370728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 386456399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 386456400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 417992399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 417992400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 465346799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 465346800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 481071599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 481071600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 496796399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 496796400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 512521199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 512521200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 528245999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 528246000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 543970799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 543970800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 559695599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 559695600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 575420399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 575420400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 646786799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 646786800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733269599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733269600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 748990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 748990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764719199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764719200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 767739599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 767739600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 780436799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 780436800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 796165199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 796165200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 811886399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 811886400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 828219599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 828219600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 846374399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 846374400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Sofia.json b/dojox/date/tests/tztests/tz_Europe-Sofia.json
new file mode 100644
index 0000000..3132107
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Sofia.json
@@ -0,0 +1,260 @@
+({
+	name: "date.timezone.Europe-Sofia",
+	runTest: function(t){
+		var tz = "Europe/Sofia";
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781048801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -781048800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 291761999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 291762000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 307576799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 307576800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 323816399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 323816400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 339026399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 339026400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 355265999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 355266000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 370393199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 370393200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 386715599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 386715600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 401846399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 401846400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 417571199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 417571200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 433295999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 433296000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 449020799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 449020800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 465350399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 465350400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 481075199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 481075200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 496799999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 496800000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 512524799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 512524800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 528249599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 528249600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 543974399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 543974400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 559699199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 559699200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 575423999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 575424000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 591148799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 591148800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 606873599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 606873600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 622598399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 622598400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 638323199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 638323200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 654652799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 654652800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670370399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670370400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733269599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733269600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 748990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 748990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764719199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764719200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796168799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796168800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828223199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828223200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846363599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846363600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Stockholm.json b/dojox/date/tests/tztests/tz_Europe-Stockholm.json
new file mode 100644
index 0000000..6f36a7c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Stockholm.json
@@ -0,0 +1,248 @@
+({
+	name: "date.timezone.Europe-Stockholm",
+	runTest: function(t){
+		var tz = "Europe/Stockholm";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1692496801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1692496800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Tallinn.json b/dojox/date/tests/tztests/tz_Europe-Tallinn.json
new file mode 100644
index 0000000..6e71150
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Tallinn.json
@@ -0,0 +1,256 @@
+({
+	name: "date.timezone.Europe-Tallinn",
+	runTest: function(t){
+		var tz = "Europe/Tallinn";
+		doh.checkDate({tzOffset: -99, tzAbbr: "TMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -99, tzAbbr: "TMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -99, tzAbbr: "TMT"}, -1638322741000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1638322740000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1632006001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1632006000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1618700401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1618700400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1593824401000, tz, 1);
+		doh.checkDate({tzOffset: -99, tzAbbr: "TMT"}, -1593824400000, tz, 1);
+		doh.checkDate({tzOffset: -99, tzAbbr: "TMT"}, -1535938741000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1535938740000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -927943201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -927943200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -892954801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -892954800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -797652001000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -797652000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 354920399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 354920400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 370727999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 370728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 386456399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 386456400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 417992399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 417992400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 465346799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 465346800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 481071599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 481071600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 496796399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 496796400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 512521199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 512521200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 528245999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 528246000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 543970799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 543970800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 559695599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 559695600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 575420399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 575420400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 622598399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 622598400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 638323199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 638323200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 654652799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 654652800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670377599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670377600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686102399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686102400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701827199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701827200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717551999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717552000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733276799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733276800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 749001599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 749001600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764726399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764726400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780451199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780451200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796175999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796176000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811900799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811900800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828230399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828230400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846374399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846374400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859679999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859680000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877823999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877824000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891129599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891129600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Tirane.json b/dojox/date/tests/tztests/tz_Europe-Tirane.json
new file mode 100644
index 0000000..3dd7fde
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Tirane.json
@@ -0,0 +1,278 @@
+({
+	name: "date.timezone.Europe-Tirane",
+	runTest: function(t){
+		var tz = "Europe/Tirane";
+		doh.checkDate({tzOffset: -79.3333333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -79.3333333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -79.3333333333333, tzAbbr: "LMT"}, -1767230361000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1767230360000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -932346001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -932346000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -843519601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -843519600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 136853999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 136854000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 149896799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 149896800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 168130799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 168130800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 181432799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 181432800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 199839599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 199839600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 213141599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 213141600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 231893999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 231894000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 244591199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 244591200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 263257199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 263257200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 276040799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 276040800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 294706799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 294706800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 307490399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 307490400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 326156399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 326156400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 339458399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 339458400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 357087599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 357087600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370389599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370389600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 389141999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 389142000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 402443999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 402444000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 419468399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 419468400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433807199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433807200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449621999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449622000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Uzhgorod.json b/dojox/date/tests/tztests/tz_Europe-Uzhgorod.json
new file mode 100644
index 0000000..670b835
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Uzhgorod.json
@@ -0,0 +1,250 @@
+({
+	name: "date.timezone.Europe-Uzhgorod",
+	runTest: function(t){
+		var tz = "Europe/Uzhgorod";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -938905201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -938905200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -794714401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -794714400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -773456401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -773456400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 354920399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 354920400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 370727999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 370728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 386456399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 386456400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 417992399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 417992400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 465346799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 465346800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 481071599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 481071600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 496796399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 496796400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 512521199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 512521200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 528245999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 528246000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 543970799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 543970800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 559695599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 559695600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 575420399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 575420400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 646786799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 646786800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670384799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 670384800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733269599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733269600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 748990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 748990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764719199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764719200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Vaduz.json b/dojox/date/tests/tztests/tz_Europe-Vaduz.json
new file mode 100644
index 0000000..9176352
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Vaduz.json
@@ -0,0 +1,240 @@
+({
+	name: "date.timezone.Europe-Vaduz",
+	runTest: function(t){
+		var tz = "Europe/Vaduz";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Vienna.json b/dojox/date/tests/tztests/tz_Europe-Vienna.json
new file mode 100644
index 0000000..c0bbbd2
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Vienna.json
@@ -0,0 +1,288 @@
+({
+	name: "date.timezone.Europe-Vienna",
+	runTest: function(t){
+		var tz = "Europe/Vienna";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1693706401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1693706400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1663455601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1663455600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1650150001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1650150000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1632006001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1632006000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1618700401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1618700400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1569711601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1569711600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1555801201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1555801200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -938905201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -938905200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -780188401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -780188400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -748479601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -748479600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -733359601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733359600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -717634801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -717634800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -701910001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -701910000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -684975601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -684975600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -670460401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -670460400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323823599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323823600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338939999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338940000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Vilnius.json b/dojox/date/tests/tztests/tz_Europe-Vilnius.json
new file mode 100644
index 0000000..f39ec98
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Vilnius.json
@@ -0,0 +1,250 @@
+({
+	name: "date.timezone.Europe-Vilnius",
+	runTest: function(t){
+		var tz = "Europe/Vilnius";
+		doh.checkDate({tzOffset: -84, tzAbbr: "WMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -84, tzAbbr: "WMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -84, tzAbbr: "WMT"}, -1672536241000, tz, 1);
+		doh.checkDate({tzOffset: -95.6, tzAbbr: "KMT"}, -1672536240000, tz, 1);
+		doh.checkDate({tzOffset: -95.6, tzAbbr: "KMT"}, -1585100137000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1585100136000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1561251601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1561251600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1553565601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1553565600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -928198801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -928198800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -900126001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -900126000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -802144801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -802144800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 354920399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 354920400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 370727999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 370728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 386456399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 386456400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 417992399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 417992400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 465346799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 465346800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 481071599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 481071600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 496796399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 496796400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 512521199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 512521200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 528245999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 528246000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 543970799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 543970800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 559695599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 559695600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 575420399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 575420400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 638319599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 638319600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 654649199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 654649200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 670373999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670374000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686102399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686102400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701827199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701827200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717551999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717552000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733276799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733276800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 749001599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 749001600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764726399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764726400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780451199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780451200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796175999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796176000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811900799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811900800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828230399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828230400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846374399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846374400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859679999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859680000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877823999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877824000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Volgograd.json b/dojox/date/tests/tztests/tz_Europe-Volgograd.json
new file mode 100644
index 0000000..3b6a5e9
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Volgograd.json
@@ -0,0 +1,246 @@
+({
+	name: "date.timezone.Europe-Volgograd",
+	runTest: function(t){
+		var tz = "Europe/Volgograd";
+		doh.checkDate({tzOffset: -177.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -177.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -177.666666666667, tzAbbr: "LMT"}, -1577761061000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TSAT"}, -1577761060000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "TSAT"}, -1411873201000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "STAT"}, -1411873200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "STAT"}, -1247540401000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "STAT"}, -1247540400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "STAT"}, -256881601000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, -256881600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 354916799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 354916800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 370724399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 370724400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 386452799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 386452800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 402260399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 402260400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 417988799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 417988800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 433796399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 433796400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 449611199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 449611200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 465343199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 465343200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 481067999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 481068000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 496792799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 496792800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 512517599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 512517600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 528242399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 528242400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 543967199000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 543967200000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 559691999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 559692000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 575416799000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 575416800000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "VOLST"}, 591141599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 591141600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 606866399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 606866400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 638319599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 638319600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 654649199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 654649200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 670373999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 670374000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLT"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 717533999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 717534000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 733273199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 733273200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 748997999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 748998000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 764722799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 764722800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 780447599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 780447600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 796172399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 796172400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 811897199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 811897200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 828226799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 828226800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 846370799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 846370800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 859676399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 859676400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 877820399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 877820400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 891125999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 891126000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 909269999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 909270000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 922575599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 922575600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 941324399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 941324400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 954025199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 954025200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 972773999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 972774000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 985474799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 985474800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1004223599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1004223600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1017529199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1017529200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1035673199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1035673200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1048978799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1048978800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1067122799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1067122800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1080428399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1080428400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1099177199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1099177200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1111877999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1111878000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1130626799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1130626800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1143327599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1143327600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1162076399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1162076400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1174777199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1174777200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1193525999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1193526000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1206831599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1206831600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1224975599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1224975600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1238281199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1238281200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1256425199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1256425200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1269730799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1269730800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1288479599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1288479600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1301180399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1301180400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1319929199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1319929200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1332629999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1332630000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1351378799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1351378800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1364684399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1364684400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1382828399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1382828400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1396133999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1396134000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1414277999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1414278000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1427583599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1427583600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1445727599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1445727600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1459033199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1459033200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1477781999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1477782000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1490482799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1490482800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1509231599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1509231600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1521932399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1521932400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1540681199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1540681200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1553986799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1553986800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1572130799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1572130800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1585436399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1585436400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1603580399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1603580400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1616885999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1616886000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1635634799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1635634800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1648335599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1648335600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1667084399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1667084400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1679785199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1679785200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1698533999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1698534000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1711839599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1711839600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1729983599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1729983600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1743289199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1743289200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1761433199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1761433200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1774738799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1774738800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1792882799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1792882800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1806188399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1806188400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1824937199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1824937200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1837637999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1837638000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1856386799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1856386800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1869087599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1869087600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1887836399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1887836400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1901141999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1901142000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1919285999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1919286000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1932591599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1932591600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1950735599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1950735600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1964041199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1964041200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1982789999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1982790000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1995490799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1995490800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 2014239599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 2014239600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 2026940399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 2026940400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 2045689199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 2045689200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 2058389999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 2058390000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 2077138799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 2077138800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 2090444399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 2090444400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 2108588399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 2108588400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 2121893999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 2121894000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 2140037999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 2140038000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "VOLT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -240, tzAbbr: "VOLST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Warsaw.json b/dojox/date/tests/tztests/tz_Europe-Warsaw.json
new file mode 100644
index 0000000..5bc5845
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Warsaw.json
@@ -0,0 +1,340 @@
+({
+	name: "date.timezone.Europe-Warsaw",
+	runTest: function(t){
+		var tz = "Europe/Warsaw";
+		doh.checkDate({tzOffset: -84, tzAbbr: "WMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -84, tzAbbr: "WMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -84, tzAbbr: "WMT"}, -1717032241000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1717032240000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1693706401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1693706400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1663455601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1663455600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1650150001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1650150000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1632006001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1632006000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -1618700401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1618700400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1600473601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1600473600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, -1587168001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1587168000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1501725601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -1501725600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -931734001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -931734000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -796608001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -796608000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -778726801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -778726800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -762660001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -762660000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -748486801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -748486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -733273201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -733273200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -715215601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -715215600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -701910001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -701910000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -684975601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -684975600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -670460401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -670460400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -654130801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -654130800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -639010801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -639010800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -397094401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -397094400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -386812801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -386812800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -371088001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -371088000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -355363201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -355363200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -334195201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -334195200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -323308801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -323308800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -307584001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -307584000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -291859201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -291859200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -271296001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -271296000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -260409601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -260409600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -239846401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -239846400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -228960001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -228960000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -208396801000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -208396800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -197510401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -197510400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -176342401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -176342400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -166060801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -166060800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 228873599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 228873600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 243993599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 243993600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 260323199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 260323200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 276047999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 276048000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 291772799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 291772800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 307497599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 307497600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 323827199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 323827200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 338947199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 338947200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354671999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354672000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370396799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370396800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386121599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386121600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401846399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401846400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417571199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417571200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433295999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433296000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449020799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449020800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465350399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465350400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481075199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481075200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496799999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496800000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512524799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512524800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528249599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528249600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543974399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543974400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559699199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559699200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Zaporozhye.json b/dojox/date/tests/tztests/tz_Europe-Zaporozhye.json
new file mode 100644
index 0000000..a96bc23
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Zaporozhye.json
@@ -0,0 +1,254 @@
+({
+	name: "date.timezone.Europe-Zaporozhye",
+	runTest: function(t){
+		var tz = "Europe/Zaporozhye";
+		doh.checkDate({tzOffset: -140, tzAbbr: "CUT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -140, tzAbbr: "CUT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -140, tzAbbr: "CUT"}, -1441160401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1441160400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, -1247536801000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -1247536800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -894769201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -894769200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -826419601000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, -826419600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 354920399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 354920400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 370727999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 370728000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 386456399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 386456400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 402263999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 402264000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 417992399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 417992400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 433799999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 433800000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 449614799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 449614800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 465346799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 465346800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 481071599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 481071600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 496796399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 496796400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 512521199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 512521200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 528245999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 528246000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 543970799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 543970800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 559695599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 559695600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 575420399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 575420400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 591145199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 591145200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 606869999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 606870000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 622594799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 622594800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 638319599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 638319600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MSD"}, 654649199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 654649200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "MSK"}, 670373999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 670374000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 686091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 686091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 701819999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 701820000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 717541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 717541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 733269599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 733269600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 748990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 748990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 764719199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 764719200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 780440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 780440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "EET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Europe-Zurich.json b/dojox/date/tests/tztests/tz_Europe-Zurich.json
new file mode 100644
index 0000000..e173c29
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Europe-Zurich.json
@@ -0,0 +1,248 @@
+({
+	name: "date.timezone.Europe-Zurich",
+	runTest: function(t){
+		var tz = "Europe/Zurich";
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -904435201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -904435200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -891129601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -891129600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -872985601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -872985600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, -859680001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, -859680000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "CET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "CEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_HST.json b/dojox/date/tests/tztests/tz_HST.json
new file mode 100644
index 0000000..28873aa
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_HST.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.HST",
+	runTest: function(t){
+		var tz = "HST";
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Indian-Antananarivo.json b/dojox/date/tests/tztests/tz_Indian-Antananarivo.json
new file mode 100644
index 0000000..54e46e8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Indian-Antananarivo.json
@@ -0,0 +1,18 @@
+({
+	name: "date.timezone.Indian-Antananarivo",
+	runTest: function(t){
+		var tz = "Indian/Antananarivo";
+		doh.checkDate({tzOffset: -190.066666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -190.066666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -190.066666666667, tzAbbr: "LMT"}, -1846293005000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1846293004000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -499924801000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "EAST"}, -499924800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "EAST"}, -492062401000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -492062400000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Indian-Chagos.json b/dojox/date/tests/tztests/tz_Indian-Chagos.json
new file mode 100644
index 0000000..46036e3
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Indian-Chagos.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Indian-Chagos",
+	runTest: function(t){
+		var tz = "Indian/Chagos";
+		doh.checkDate({tzOffset: -289.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -289.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -289.666666666667, tzAbbr: "LMT"}, -1988167781000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "IOT"}, -1988167780000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "IOT"}, 820436399000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "IOT"}, 820436400000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "IOT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "IOT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -360, tzAbbr: "IOT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -360, tzAbbr: "IOT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Indian-Christmas.json b/dojox/date/tests/tztests/tz_Indian-Christmas.json
new file mode 100644
index 0000000..71a16e0
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Indian-Christmas.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Indian-Christmas",
+	runTest: function(t){
+		var tz = "Indian/Christmas";
+		doh.checkDate({tzOffset: -420, tzAbbr: "CXT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "CXT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "CXT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "CXT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -420, tzAbbr: "CXT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -420, tzAbbr: "CXT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Indian-Cocos.json b/dojox/date/tests/tztests/tz_Indian-Cocos.json
new file mode 100644
index 0000000..efe56ce
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Indian-Cocos.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Indian-Cocos",
+	runTest: function(t){
+		var tz = "Indian/Cocos";
+		doh.checkDate({tzOffset: -390, tzAbbr: "CCT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "CCT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "CCT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "CCT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -390, tzAbbr: "CCT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -390, tzAbbr: "CCT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Indian-Comoro.json b/dojox/date/tests/tztests/tz_Indian-Comoro.json
new file mode 100644
index 0000000..b2db7e9
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Indian-Comoro.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Indian-Comoro",
+	runTest: function(t){
+		var tz = "Indian/Comoro";
+		doh.checkDate({tzOffset: -173.066666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -173.066666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -173.066666666667, tzAbbr: "LMT"}, -1846291985000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1846291984000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Indian-Kerguelen.json b/dojox/date/tests/tztests/tz_Indian-Kerguelen.json
new file mode 100644
index 0000000..4df789e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Indian-Kerguelen.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Indian-Kerguelen",
+	runTest: function(t){
+		var tz = "Indian/Kerguelen";
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "zzz"}, -631152001000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TFT"}, -631152000000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TFT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TFT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TFT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "TFT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Indian-Mahe.json b/dojox/date/tests/tztests/tz_Indian-Mahe.json
new file mode 100644
index 0000000..4f35eed
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Indian-Mahe.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Indian-Mahe",
+	runTest: function(t){
+		var tz = "Indian/Mahe";
+		doh.checkDate({tzOffset: -221.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -221.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -221.8, tzAbbr: "LMT"}, -2006653309000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SCT"}, -2006653308000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SCT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SCT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SCT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -240, tzAbbr: "SCT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Indian-Maldives.json b/dojox/date/tests/tztests/tz_Indian-Maldives.json
new file mode 100644
index 0000000..c22f37f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Indian-Maldives.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Indian-Maldives",
+	runTest: function(t){
+		var tz = "Indian/Maldives";
+		doh.checkDate({tzOffset: -294, tzAbbr: "MMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -294, tzAbbr: "MMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -294, tzAbbr: "MMT"}, -315636841000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "MVT"}, -315636840000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "MVT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "MVT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "MVT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -300, tzAbbr: "MVT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Indian-Mauritius.json b/dojox/date/tests/tztests/tz_Indian-Mauritius.json
new file mode 100644
index 0000000..3f1367c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Indian-Mauritius.json
@@ -0,0 +1,136 @@
+({
+	name: "date.timezone.Indian-Mauritius",
+	runTest: function(t){
+		var tz = "Indian/Mauritius";
+		doh.checkDate({tzOffset: -230, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -230, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -230, tzAbbr: "LMT"}, -1988164201000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, -1988164200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 403041599000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "MUST"}, 403041600000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "MUST"}, 417034799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 417034800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1224971999000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "MUST"}, 1224972000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1238277599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1238277600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1256421599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1256421600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1269727199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1269727200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1288475999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1288476000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1301176799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1301176800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1319925599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1319925600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1332626399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1332626400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1351375199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1351375200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1364680799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1364680800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1382824799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1382824800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1396130399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1396130400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1414274399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1414274400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1427579999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1427580000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1445723999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1445724000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1459029599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1459029600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1477778399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1477778400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1490479199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1490479200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1509227999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1509228000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1521928799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1521928800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1540677599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1540677600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1553983199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1553983200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1572127199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1572127200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1585432799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1585432800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1603576799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1603576800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1616882399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1616882400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1635631199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1635631200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1648331999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1648332000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1667080799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1667080800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1679781599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1679781600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1698530399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1698530400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1711835999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1711836000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1729979999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1729980000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1743285599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1743285600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1761429599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1761429600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1774735199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1774735200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1792879199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1792879200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1806184799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1806184800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1824933599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1824933600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1837634399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1837634400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1856383199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1856383200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1869083999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1869084000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1887832799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1887832800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1901138399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1901138400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1919282399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1919282400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1932587999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1932588000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1950731999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1950732000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1964037599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1964037600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1982786399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1982786400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 1995487199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1995487200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 2014235999000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 2014236000000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 2026936799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 2026936800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 2045685599000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 2045685600000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 2058386399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 2058386400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 2077135199000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 2077135200000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 2090440799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 2090440800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 2108584799000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 2108584800000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 2121890399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 2121890400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 2140034399000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 2140034400000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -300, tzAbbr: "MUST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -240, tzAbbr: "MUT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Indian-Mayotte.json b/dojox/date/tests/tztests/tz_Indian-Mayotte.json
new file mode 100644
index 0000000..16866ac
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Indian-Mayotte.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Indian-Mayotte",
+	runTest: function(t){
+		var tz = "Indian/Mayotte";
+		doh.checkDate({tzOffset: -180.933333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -180.933333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -180.933333333333, tzAbbr: "LMT"}, -1846292457000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, -1846292456000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -180, tzAbbr: "EAT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Indian-Reunion.json b/dojox/date/tests/tztests/tz_Indian-Reunion.json
new file mode 100644
index 0000000..7280f8f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Indian-Reunion.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Indian-Reunion",
+	runTest: function(t){
+		var tz = "Indian/Reunion";
+		doh.checkDate({tzOffset: -221.866666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -221.866666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -221.866666666667, tzAbbr: "LMT"}, -1848886913000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "RET"}, -1848886912000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "RET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "RET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -240, tzAbbr: "RET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -240, tzAbbr: "RET"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_MET.json b/dojox/date/tests/tztests/tz_MET.json
new file mode 100644
index 0000000..f4e5bcd
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_MET.json
@@ -0,0 +1,284 @@
+({
+	name: "date.timezone.MET",
+	runTest: function(t){
+		var tz = "MET";
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -1693706401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -1693706400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -1680483601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -1680483600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -1663455601000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -1663455600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -1650150001000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -1650150000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -1632006001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -1632006000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -1618700401000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -1618700400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -938905201000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -938905200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -857257201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -857257200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -844556401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -844556400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -828226801000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -828226800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -812502001000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -812502000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -796777201000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -796777200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -781052401000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -781052400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, -766623601000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, -766623600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 228877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 228877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 243997199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 243997200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 260326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 260326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 276051599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 276051600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "MET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -120, tzAbbr: "MEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_MST.json b/dojox/date/tests/tztests/tz_MST.json
new file mode 100644
index 0000000..6eb748c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_MST.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.MST",
+	runTest: function(t){
+		var tz = "MST";
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_MST7MDT.json b/dojox/date/tests/tztests/tz_MST7MDT.json
new file mode 100644
index 0000000..a63f70f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_MST7MDT.json
@@ -0,0 +1,310 @@
+({
+	name: "date.timezone.MST7MDT",
+	runTest: function(t){
+		var tz = "MST7MDT";
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1633273201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1633273200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1615132801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1615132800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1601823601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1601823600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -1583683201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -1583683200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -880210801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -880210800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MPT"}, -765388801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -765388800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -84380401000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -84380400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -68659201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -68659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -52930801000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -52930800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -37209601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -37209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -21481201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -21481200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, -5760001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, -5760000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 9968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 9968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 25689599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 25689600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 41417999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 41418000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 57743999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 57744000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 73472399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 73472400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 89193599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 89193600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 104921999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 104922000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 120643199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 120643200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 126694799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 126694800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 152092799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 152092800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 162377999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 162378000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 183542399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 183542400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 199270799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 199270800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 215596799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 215596800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 230720399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 230720400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 247046399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 247046400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 262774799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 262774800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 278495999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 278496000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 294224399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 294224400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 309945599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 309945600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 325673999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 325674000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 341395199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 341395200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 357123599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 357123600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 372844799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 372844800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 388573199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 388573200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 404899199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 404899200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 420022799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 420022800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 436348799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 436348800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 452077199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 452077200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 467798399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 467798400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 483526799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 483526800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 499247999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 499248000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 514976399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 514976400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 530697599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 530697600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 544611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 544611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 562147199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 562147200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 576061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 576061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 594201599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 594201600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 607510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 607510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 625651199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 625651200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 638960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 638960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 657100799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 657100800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 671014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 671014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 688550399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 688550400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 702464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 702464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 719999999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 720000000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 733913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 733914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 752054399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 752054400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 765363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 765363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 783503999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 783504000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 796813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 796813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 814953599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 814953600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 828867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 828867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 846403199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 846403200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 860317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 860317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 877852799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 877852800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 891766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 891766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 909302399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 909302400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 923216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 923216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 941356799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 941356800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 954665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 954666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 972806399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 972806400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 986115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 986115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1004255999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1004256000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1018169999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1018170000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1035705599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1035705600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1049619599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1049619600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1067155199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1067155200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1081069199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1081069200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1099209599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1099209600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1112518799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1112518800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1130659199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1130659200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1143968399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1143968400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1162108799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1162108800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1173603599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1173603600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1194163199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1194163200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1205053199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1205053200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1225612799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1225612800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1236502799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1236502800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1257062399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1257062400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1268557199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1268557200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1289116799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1289116800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1300006799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1300006800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1320566399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1320566400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1331456399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1331456400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1352015999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1352016000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1362905999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1362906000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1383465599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1383465600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1394355599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1394355600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1414915199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1414915200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1425805199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1425805200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1446364799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1446364800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1457859599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1457859600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1478419199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1478419200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1489309199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1489309200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1509868799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1509868800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1520758799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1520758800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1541318399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1541318400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1552208399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1552208400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1572767999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1572768000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1583657999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1583658000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1604217599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1604217600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1615712399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1615712400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1636271999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1636272000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1647161999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1647162000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1667721599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1667721600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1678611599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1678611600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1699171199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1699171200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1710061199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1710061200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1730620799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1730620800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1741510799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1741510800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1762070399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1762070400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1772960399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1772960400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1793519999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1793520000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1805014799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1805014800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1825574399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1825574400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1836464399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1836464400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1857023999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1857024000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1867913999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1867914000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1888473599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1888473600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1899363599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1899363600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1919923199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1919923200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1930813199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1930813200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1951372799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1951372800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1962867599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1962867600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1983427199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1983427200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1994317199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1994317200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2014876799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2014876800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2025766799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2025766800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2046326399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2046326400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2057216399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2057216400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2077775999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2077776000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2088665999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2088666000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2109225599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2109225600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2120115599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2120115600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 2140675199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2140675200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "MST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "MDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_PST8PDT.json b/dojox/date/tests/tztests/tz_PST8PDT.json
new file mode 100644
index 0000000..1db49c3
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_PST8PDT.json
@@ -0,0 +1,310 @@
+({
+	name: "date.timezone.PST8PDT",
+	runTest: function(t){
+		var tz = "PST8PDT";
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1633269601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1633269600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1615129201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1615129200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1601820001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1601820000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -1583679601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -1583679600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -880207201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -880207200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PPT"}, -765385201000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -765385200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -84376801000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -84376800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -68655601000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -68655600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -52927201000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -52927200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -37206001000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -37206000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -21477601000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -21477600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, -5756401000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, -5756400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 9971999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 9972000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 25693199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 25693200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 41421599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 41421600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 57747599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 57747600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 73475999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 73476000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 89197199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 89197200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 104925599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 104925600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 120646799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 120646800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 126698399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 126698400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 152096399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 152096400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 162381599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 162381600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 183545999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 183546000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 199274399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 199274400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 215600399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 215600400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 230723999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 230724000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 247049999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 247050000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 262778399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 262778400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 278499599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 278499600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 294227999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 294228000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 309949199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 309949200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 325677599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 325677600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 341398799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 341398800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 357127199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 357127200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 372848399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 372848400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 388576799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 388576800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 404902799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 404902800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 420026399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 420026400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 436352399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 436352400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 452080799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 452080800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 467801999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 467802000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 483530399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 483530400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 499251599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 499251600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 514979999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 514980000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 530701199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 530701200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 544615199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 544615200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 562150799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 562150800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 576064799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 576064800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 594205199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 594205200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 607514399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 607514400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 625654799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 625654800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 638963999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 638964000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 657104399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 657104400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 671018399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 671018400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 688553999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 688554000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 702467999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 702468000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 720003599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 720003600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 733917599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 733917600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 752057999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 752058000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 765367199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 765367200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 783507599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 783507600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 796816799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 796816800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 814957199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 814957200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 828871199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 828871200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 846406799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 846406800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 860320799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 860320800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 877856399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 877856400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 891770399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 891770400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 909305999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 909306000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 923219999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 923220000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 941360399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 941360400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 954669599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 954669600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 972809999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 972810000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 986119199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 986119200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1004259599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1004259600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1018173599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1018173600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1035709199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1035709200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1049623199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1049623200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1067158799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1067158800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1081072799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1081072800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1099213199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1099213200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1112522399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1112522400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1130662799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1130662800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1143971999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1143972000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1162112399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1162112400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1173607199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1173607200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1194166799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1194166800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1205056799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1205056800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1225616399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1225616400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1236506399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1236506400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1257065999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1257066000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1268560799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1268560800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1289120399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1289120400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1300010399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1300010400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1320569999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1320570000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1331459999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1331460000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1352019599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1352019600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1362909599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1362909600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1383469199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1383469200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1394359199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1394359200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1414918799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1414918800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1425808799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1425808800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1446368399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1446368400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1457863199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1457863200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1478422799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1478422800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1489312799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1489312800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1509872399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1509872400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1520762399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1520762400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1541321999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1541322000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1552211999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1552212000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1572771599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1572771600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1583661599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1583661600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1604221199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1604221200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1615715999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1615716000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1636275599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1636275600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1647165599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1647165600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1667725199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1667725200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1678615199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1678615200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1699174799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1699174800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1710064799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1710064800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1730624399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1730624400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1741514399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1741514400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1762073999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1762074000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1772963999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1772964000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1793523599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1793523600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1805018399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1805018400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1825577999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1825578000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1836467999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1836468000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1857027599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1857027600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1867917599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1867917600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1888477199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1888477200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1899367199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1899367200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1919926799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1919926800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1930816799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1930816800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1951376399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1951376400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1962871199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1962871200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1983430799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1983430800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1994320799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1994320800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2014880399000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2014880400000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2025770399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2025770400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2046329999000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2046330000000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2057219999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2057220000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2077779599000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2077779600000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2088669599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2088669600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2109229199000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2109229200000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2120119199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2120119200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 2140678799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2140678800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 420, tzAbbr: "PDT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Apia.json b/dojox/date/tests/tztests/tz_Pacific-Apia.json
new file mode 100644
index 0000000..88099f8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Apia.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Pacific-Apia",
+	runTest: function(t){
+		var tz = "Pacific/Apia";
+		doh.checkDate({tzOffset: 686.933333333333, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 686.933333333333, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 686.933333333333, tzAbbr: "LMT"}, -1861878785000, tz, 1);
+		doh.checkDate({tzOffset: 690, tzAbbr: "SAMT"}, -1861878784000, tz, 1);
+		doh.checkDate({tzOffset: 690, tzAbbr: "SAMT"}, -631110601000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "WST"}, -631110600000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "WST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "WST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "WST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 660, tzAbbr: "WST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Auckland.json b/dojox/date/tests/tztests/tz_Pacific-Auckland.json
new file mode 100644
index 0000000..17daded
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Auckland.json
@@ -0,0 +1,322 @@
+({
+	name: "date.timezone.Pacific-Auckland",
+	runTest: function(t){
+		var tz = "Pacific/Auckland";
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1330335001000, tz, 1);
+		doh.checkDate({tzOffset: -750, tzAbbr: "NZST"}, -1330335000000, tz, 1);
+		doh.checkDate({tzOffset: -750, tzAbbr: "NZST"}, -1320057001000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1320057000000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1300699801000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1300699800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1287396001000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1287396000000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1269250201000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1269250200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1255946401000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1255946400000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1237800601000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1237800600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1224496801000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1224496800000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1206351001000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1206351000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1192442401000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1192442400000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1174901401000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1174901400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1160992801000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1160992800000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1143451801000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1143451800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1125914401000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1125914400000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1112607001000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1112607000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1094464801000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1094464800000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1081157401000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1081157400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1063015201000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1063015200000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1049707801000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1049707800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1031565601000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1031565600000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1018258201000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1018258200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -1000116001000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -1000116000000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -986808601000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -986808600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -968061601000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -968061600000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -955359001000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -955359000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -936612001000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -936612000000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NZMT"}, -923304601000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -923304600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -757425601000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, -757425600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 152632799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 152632800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 162309599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 162309600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 183477599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 183477600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 194968799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 194968800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 215531999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 215532000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 226418399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 226418400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 246981599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 246981600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 257867999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 257868000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 278431199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 278431200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 289317599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 289317600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 309880799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 309880800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 320767199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 320767200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 341330399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 341330400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 352216799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 352216800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 372779999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 372780000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 384271199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 384271200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 404834399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 404834400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 415720799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 415720800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 436283999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 436284000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 447170399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 447170400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 467733599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 467733600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 478619999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 478620000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 499183199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 499183200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 510069599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 510069600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 530632799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 530632800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 541519199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 541519200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 562082399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 562082400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 573573599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 573573600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 594136799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 594136800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 605023199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 605023200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 623771999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 623772000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 637682399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 637682400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 655221599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 655221600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 669131999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 669132000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 686671199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 686671200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 700581599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 700581600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 718120799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 718120800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 732635999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 732636000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 749570399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 749570400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 764085599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 764085600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 781019999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 781020000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 795535199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 795535200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 812469599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 812469600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 826984799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 826984800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 844523999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 844524000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 858434399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 858434400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 875973599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 875973600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 889883999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 889884000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 907423199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 907423200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 921938399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 921938400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 938872799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 938872800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 953387999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 953388000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 970322399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 970322400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 984837599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 984837600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1002376799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1002376800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1016287199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1016287200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1033826399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1033826400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1047736799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1047736800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1065275999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1065276000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1079791199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1079791200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1096725599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1096725600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1111240799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1111240800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1128175199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1128175200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1142690399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1142690400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1159624799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1159624800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1174139999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1174140000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1191074399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1191074400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1207403999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1207404000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1222523999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1222524000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1238853599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1238853600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1253973599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1253973600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1270303199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1270303200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1285423199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1285423200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1301752799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1301752800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1316872799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1316872800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1333202399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1333202400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1348927199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1348927200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1365256799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1365256800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1380376799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1380376800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1396706399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1396706400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1411826399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1411826400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1428155999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1428156000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1443275999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1443276000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1459605599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1459605600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1474725599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1474725600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1491055199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1491055200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1506175199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1506175200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1522504799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1522504800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1538229599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1538229600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1554559199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1554559200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1569679199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1569679200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1586008799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1586008800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1601128799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1601128800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1617458399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1617458400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1632578399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1632578400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1648907999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1648908000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1664027999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1664028000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1680357599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1680357600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1695477599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1695477600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1712411999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1712412000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1727531999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1727532000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1743861599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1743861600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1758981599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1758981600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1775311199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1775311200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1790431199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1790431200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1806760799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1806760800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1821880799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1821880800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1838210399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1838210400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1853330399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1853330400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1869659999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1869660000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1885384799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1885384800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1901714399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1901714400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1916834399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1916834400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1933163999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1933164000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1948283999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1948284000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1964613599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1964613600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1979733599000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1979733600000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1996063199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1996063200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2011183199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2011183200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2027512799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2027512800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2042632799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2042632800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2058962399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2058962400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2074687199000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2074687200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2091016799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2091016800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2106136799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2106136800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2122466399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2122466400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 2137586399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2137586400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "NZDT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NZST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Chatham.json b/dojox/date/tests/tztests/tz_Pacific-Chatham.json
new file mode 100644
index 0000000..9db6871
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Chatham.json
@@ -0,0 +1,268 @@
+({
+	name: "date.timezone.Pacific-Chatham",
+	runTest: function(t){
+		var tz = "Pacific/Chatham";
+		doh.checkDate({tzOffset: -733.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -733.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -733.8, tzAbbr: "LMT"}, -410271229000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, -410271228000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 152632799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 152632800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 162309599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 162309600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 183477599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 183477600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 194968799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 194968800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 215531999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 215532000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 226418399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 226418400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 246981599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 246981600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 257867999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 257868000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 278431199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 278431200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 289317599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 289317600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 309880799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 309880800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 320767199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 320767200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 341330399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 341330400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 352216799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 352216800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 372779999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 372780000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 384271199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 384271200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 404834399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 404834400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 415720799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 415720800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 436283999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 436284000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 447170399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 447170400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 467733599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 467733600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 478619999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 478620000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 499183199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 499183200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 510069599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 510069600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 530632799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 530632800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 541519199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 541519200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 562082399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 562082400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 573573599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 573573600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 594136799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 594136800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 605023199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 605023200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 623771999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 623772000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 637682399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 637682400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 655221599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 655221600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 669131999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 669132000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 686671199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 686671200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 700581599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 700581600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 718120799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 718120800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 732635999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 732636000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 749570399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 749570400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 764085599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 764085600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 781019999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 781020000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 795535199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 795535200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 812469599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 812469600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 826984799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 826984800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 844523999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 844524000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 858434399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 858434400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 875973599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 875973600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 889883999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 889884000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 907423199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 907423200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 921938399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 921938400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 938872799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 938872800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 953387999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 953388000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 970322399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 970322400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 984837599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 984837600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1002376799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1002376800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1016287199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1016287200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1033826399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1033826400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1047736799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1047736800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1065275999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1065276000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1079791199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1079791200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1096725599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1096725600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1111240799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1111240800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1128175199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1128175200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1142690399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1142690400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1159624799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1159624800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1174139999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1174140000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1191074399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1191074400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1207403999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1207404000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1222523999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1222524000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1238853599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1238853600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1253973599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1253973600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1270303199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1270303200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1285423199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1285423200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1301752799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1301752800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1316872799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1316872800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1333202399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1333202400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1348927199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1348927200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1365256799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1365256800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1380376799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1380376800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1396706399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1396706400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1411826399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1411826400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1428155999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1428156000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1443275999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1443276000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1459605599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1459605600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1474725599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1474725600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1491055199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1491055200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1506175199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1506175200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1522504799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1522504800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1538229599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1538229600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1554559199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1554559200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1569679199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1569679200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1586008799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1586008800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1601128799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1601128800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1617458399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1617458400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1632578399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1632578400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1648907999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1648908000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1664027999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1664028000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1680357599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1680357600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1695477599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1695477600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1712411999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1712412000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1727531999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1727532000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1743861599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1743861600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1758981599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1758981600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1775311199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1775311200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1790431199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1790431200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1806760799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1806760800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1821880799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1821880800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1838210399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1838210400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1853330399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1853330400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1869659999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1869660000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1885384799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1885384800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1901714399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1901714400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1916834399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1916834400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1933163999000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1933164000000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1948283999000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1948284000000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1964613599000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1964613600000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1979733599000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1979733600000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1996063199000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1996063200000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 2011183199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 2011183200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 2027512799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 2027512800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 2042632799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 2042632800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 2058962399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 2058962400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 2074687199000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 2074687200000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 2091016799000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 2091016800000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 2106136799000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 2106136800000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 2122466399000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 2122466400000, tz, 1);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 2137586399000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 2137586400000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -825, tzAbbr: "CHADT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -765, tzAbbr: "CHAST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Easter.json b/dojox/date/tests/tztests/tz_Pacific-Easter.json
new file mode 100644
index 0000000..fb27162
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Easter.json
@@ -0,0 +1,298 @@
+({
+	name: "date.timezone.Pacific-Easter",
+	runTest: function(t){
+		var tz = "Pacific/Easter";
+		doh.checkDate({tzOffset: 437.466666666667, tzAbbr: "EMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 437.466666666667, tzAbbr: "EMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 437.466666666667, tzAbbr: "EMT"}, -1178124153000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, -1178124152000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, -870552001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, -870552000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, -865278001000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, -865278000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, -736376401000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, -736376400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, -36619201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, -36619200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, -23922001000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, -23922000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, -3355201000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, -3355200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 7527599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 7527600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 24465599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 24465600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 37767599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 37767600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 55915199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 55915200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 69217199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 69217200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 87969599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 87969600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 100666799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 100666800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 118209599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 118209600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 132116399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 132116400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 150868799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 150868800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 163565999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 163566000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 182318399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 182318400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 195620399000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 195620400000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 213767999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 213768000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 227069999000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 227070000000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 245217599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 245217600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 258519599000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 258519600000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 277271999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 277272000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 289969199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 289969200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 308721599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 308721600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 321418799000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 321418800000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 340171199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 340171200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 353473199000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 353473200000, tz, 1);
+		doh.checkDate({tzOffset: 420, tzAbbr: "EAST"}, 371620799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 371620800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EASST"}, 384922799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 384922800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 403070399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 403070400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 416372399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 416372400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 434519999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 434520000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 447821999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 447822000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 466574399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 466574400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 479271599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 479271600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 498023999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 498024000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 510721199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 510721200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 529473599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 529473600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 545194799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 545194800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 560923199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 560923200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 574225199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 574225200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 591767999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 591768000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 605674799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 605674800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 624427199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 624427200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 637729199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 637729200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 653457599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 653457600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 668573999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 668574000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 687326399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 687326400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 700628399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 700628400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 718775999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 718776000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 732077999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 732078000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 750225599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 750225600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 763527599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 763527600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 781675199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 781675200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 794977199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 794977200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 813729599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 813729600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 826426799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 826426800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 845179199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 845179200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 859690799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 859690800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 876628799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 876628800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 889930799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 889930800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 906868799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 906868800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 923194799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 923194800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 939527999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 939528000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 952829999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 952830000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 971582399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 971582400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 984279599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 984279600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1003031999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1003032000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1015729199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1015729200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1034481599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1034481600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1047178799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1047178800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1065931199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1065931200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1079233199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1079233200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1097380799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1097380800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1110682799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1110682800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1128830399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1128830400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1142132399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1142132400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1160884799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1160884800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1173581999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1173582000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1192334399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1192334400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1206845999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1206846000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1223783999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1223784000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1237085999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1237086000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1255233599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1255233600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1268535599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1268535600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1286683199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1286683200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1299985199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1299985200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1318132799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1318132800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1331434799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1331434800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1350187199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1350187200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1362884399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1362884400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1381636799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1381636800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1394333999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1394334000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1413086399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1413086400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1426388399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1426388400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1444535999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1444536000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1457837999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1457838000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1475985599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1475985600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1489287599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1489287600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1508039999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1508040000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1520737199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1520737200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1539489599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1539489600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1552186799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1552186800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1570939199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1570939200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1584241199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1584241200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1602388799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1602388800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1615690799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1615690800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1633838399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1633838400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1647140399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1647140400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1665287999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1665288000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1678589999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1678590000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1697342399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1697342400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1710039599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1710039600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1728791999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1728792000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1741489199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1741489200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1760241599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1760241600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1773543599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1773543600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1791691199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1791691200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1804993199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1804993200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1823140799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1823140800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1836442799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1836442800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1855195199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1855195200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1867892399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1867892400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1886644799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1886644800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1899341999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1899342000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1918094399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1918094400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1930791599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1930791600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1949543999000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1949544000000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1962845999000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1962846000000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1980993599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1980993600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1994295599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1994295600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 2012443199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 2012443200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 2025745199000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 2025745200000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 2044497599000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 2044497600000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 2057194799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 2057194800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 2075947199000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 2075947200000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 2088644399000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 2088644400000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 2107396799000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 2107396800000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 2120698799000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 2120698800000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 2138846399000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 2138846400000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "EASST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "EAST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Efate.json b/dojox/date/tests/tztests/tz_Pacific-Efate.json
new file mode 100644
index 0000000..ec59079
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Efate.json
@@ -0,0 +1,54 @@
+({
+	name: "date.timezone.Pacific-Efate",
+	runTest: function(t){
+		var tz = "Pacific/Efate";
+		doh.checkDate({tzOffset: -673.266666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -673.266666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -673.266666666667, tzAbbr: "LMT"}, -1829387597000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, -1829387596000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 433256399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 433256400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 448977599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 448977600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 467297999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 467298000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 480427199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 480427200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 496760399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 496760400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 511876799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 511876800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 528209999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 528210000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 543931199000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 543931200000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 559659599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 559659600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 575380799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 575380800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 591109199000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 591109200000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 606830399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 606830400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 622558799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 622558800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 638279999000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 638280000000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 654008399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 654008400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 669729599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 669729600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 686062799000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 686062800000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 696340799000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 696340800000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 719931599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 719931600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "VUST"}, 727790399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 727790400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -660, tzAbbr: "VUT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Enderbury.json b/dojox/date/tests/tztests/tz_Pacific-Enderbury.json
new file mode 100644
index 0000000..d2054d8
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Enderbury.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Pacific-Enderbury",
+	runTest: function(t){
+		var tz = "Pacific/Enderbury";
+		doh.checkDate({tzOffset: 720, tzAbbr: "PHOT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 720, tzAbbr: "PHOT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 720, tzAbbr: "PHOT"}, 307627199000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "PHOT"}, 307627200000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "PHOT"}, 788957999000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PHOT"}, 788958000000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PHOT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PHOT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PHOT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -780, tzAbbr: "PHOT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Fakaofo.json b/dojox/date/tests/tztests/tz_Pacific-Fakaofo.json
new file mode 100644
index 0000000..0985d74
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Fakaofo.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Pacific-Fakaofo",
+	runTest: function(t){
+		var tz = "Pacific/Fakaofo";
+		doh.checkDate({tzOffset: 600, tzAbbr: "TKT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "TKT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "TKT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "TKT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "TKT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 600, tzAbbr: "TKT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Fiji.json b/dojox/date/tests/tztests/tz_Pacific-Fiji.json
new file mode 100644
index 0000000..d43d153
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Fiji.json
@@ -0,0 +1,22 @@
+({
+	name: "date.timezone.Pacific-Fiji",
+	runTest: function(t){
+		var tz = "Pacific/Fiji";
+		doh.checkDate({tzOffset: -713.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -713.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -713.666666666667, tzAbbr: "LMT"}, -1709985221000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "FJT"}, -1709985220000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "FJT"}, 909842399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "FJST"}, 909842400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "FJST"}, 920123999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "FJT"}, 920124000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "FJT"}, 941896799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "FJST"}, 941896800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "FJST"}, 951573599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "FJT"}, 951573600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "FJT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "FJT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "FJT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -720, tzAbbr: "FJT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Funafuti.json b/dojox/date/tests/tztests/tz_Pacific-Funafuti.json
new file mode 100644
index 0000000..9e71c12
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Funafuti.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Pacific-Funafuti",
+	runTest: function(t){
+		var tz = "Pacific/Funafuti";
+		doh.checkDate({tzOffset: -720, tzAbbr: "TVT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "TVT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "TVT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "TVT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "TVT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -720, tzAbbr: "TVT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Galapagos.json b/dojox/date/tests/tztests/tz_Pacific-Galapagos.json
new file mode 100644
index 0000000..3d86251
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Galapagos.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Pacific-Galapagos",
+	runTest: function(t){
+		var tz = "Pacific/Galapagos";
+		doh.checkDate({tzOffset: 358.4, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 358.4, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 358.4, tzAbbr: "LMT"}, -1230746497000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ECT"}, -1230746496000, tz, 1);
+		doh.checkDate({tzOffset: 300, tzAbbr: "ECT"}, 504939599000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "GALT"}, 504939600000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "GALT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "GALT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 360, tzAbbr: "GALT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 360, tzAbbr: "GALT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Gambier.json b/dojox/date/tests/tztests/tz_Pacific-Gambier.json
new file mode 100644
index 0000000..2d59976
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Gambier.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Pacific-Gambier",
+	runTest: function(t){
+		var tz = "Pacific/Gambier";
+		doh.checkDate({tzOffset: 539.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 539.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 539.8, tzAbbr: "LMT"}, -1806678013000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "GAMT"}, -1806678012000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "GAMT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "GAMT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 540, tzAbbr: "GAMT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 540, tzAbbr: "GAMT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Guadalcanal.json b/dojox/date/tests/tztests/tz_Pacific-Guadalcanal.json
new file mode 100644
index 0000000..468fd70
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Guadalcanal.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Pacific-Guadalcanal",
+	runTest: function(t){
+		var tz = "Pacific/Guadalcanal";
+		doh.checkDate({tzOffset: -639.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -639.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -639.8, tzAbbr: "LMT"}, -1806748789000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SBT"}, -1806748788000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SBT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SBT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SBT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -660, tzAbbr: "SBT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Guam.json b/dojox/date/tests/tztests/tz_Pacific-Guam.json
new file mode 100644
index 0000000..abcfd63
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Guam.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Pacific-Guam",
+	runTest: function(t){
+		var tz = "Pacific/Guam";
+		doh.checkDate({tzOffset: -600, tzAbbr: "GST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "GST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "GST"}, 977493599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "ChST"}, 977493600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "ChST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "ChST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "ChST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "ChST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Honolulu.json b/dojox/date/tests/tztests/tz_Pacific-Honolulu.json
new file mode 100644
index 0000000..e9c18f3
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Honolulu.json
@@ -0,0 +1,24 @@
+({
+	name: "date.timezone.Pacific-Honolulu",
+	runTest: function(t){
+		var tz = "Pacific/Honolulu";
+		doh.checkDate({tzOffset: 630, tzAbbr: "HST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 630, tzAbbr: "HST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 630, tzAbbr: "HST"}, -1157283001000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "HDT"}, -1157283000000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "HDT"}, -1155472201000, tz, 1);
+		doh.checkDate({tzOffset: 630, tzAbbr: "HST"}, -1155472200000, tz, 1);
+		doh.checkDate({tzOffset: 630, tzAbbr: "HST"}, -880198201000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "HWT"}, -880198200000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "HWT"}, -769395601000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "HPT"}, -769395600000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "HPT"}, -765376201000, tz, 1);
+		doh.checkDate({tzOffset: 630, tzAbbr: "HST"}, -765376200000, tz, 1);
+		doh.checkDate({tzOffset: 630, tzAbbr: "HST"}, -712150201000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, -712150200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Johnston.json b/dojox/date/tests/tztests/tz_Pacific-Johnston.json
new file mode 100644
index 0000000..04e4422
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Johnston.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Pacific-Johnston",
+	runTest: function(t){
+		var tz = "Pacific/Johnston";
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 600, tzAbbr: "HST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Kiritimati.json b/dojox/date/tests/tztests/tz_Pacific-Kiritimati.json
new file mode 100644
index 0000000..cae0196
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Kiritimati.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Pacific-Kiritimati",
+	runTest: function(t){
+		var tz = "Pacific/Kiritimati";
+		doh.checkDate({tzOffset: 640, tzAbbr: "LINT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 640, tzAbbr: "LINT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 640, tzAbbr: "LINT"}, 307622399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "LINT"}, 307622400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "LINT"}, 788954399000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "LINT"}, 788954400000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "LINT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "LINT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "LINT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -840, tzAbbr: "LINT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Kosrae.json b/dojox/date/tests/tztests/tz_Pacific-Kosrae.json
new file mode 100644
index 0000000..0a59d29
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Kosrae.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Pacific-Kosrae",
+	runTest: function(t){
+		var tz = "Pacific/Kosrae";
+		doh.checkDate({tzOffset: -660, tzAbbr: "KOST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "KOST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "KOST"}, -7988401000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "KOST"}, -7988400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "KOST"}, 915105599000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "KOST"}, 915105600000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "KOST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "KOST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "KOST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -660, tzAbbr: "KOST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Kwajalein.json b/dojox/date/tests/tztests/tz_Pacific-Kwajalein.json
new file mode 100644
index 0000000..70a472d
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Kwajalein.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Pacific-Kwajalein",
+	runTest: function(t){
+		var tz = "Pacific/Kwajalein";
+		doh.checkDate({tzOffset: -660, tzAbbr: "MHT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MHT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MHT"}, -7988401000, tz, 1);
+		doh.checkDate({tzOffset: 720, tzAbbr: "KWAT"}, -7988400000, tz, 1);
+		doh.checkDate({tzOffset: 720, tzAbbr: "KWAT"}, 745847999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MHT"}, 745848000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MHT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MHT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MHT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MHT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Majuro.json b/dojox/date/tests/tztests/tz_Pacific-Majuro.json
new file mode 100644
index 0000000..ef5697b
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Majuro.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Pacific-Majuro",
+	runTest: function(t){
+		var tz = "Pacific/Majuro";
+		doh.checkDate({tzOffset: -660, tzAbbr: "MHT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MHT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "MHT"}, -7988401000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MHT"}, -7988400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MHT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MHT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MHT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -720, tzAbbr: "MHT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Marquesas.json b/dojox/date/tests/tztests/tz_Pacific-Marquesas.json
new file mode 100644
index 0000000..a3c3aff
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Marquesas.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Pacific-Marquesas",
+	runTest: function(t){
+		var tz = "Pacific/Marquesas";
+		doh.checkDate({tzOffset: 558, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 558, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 558, tzAbbr: "LMT"}, -1806676921000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "MART"}, -1806676920000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "MART"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "MART"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "MART"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 570, tzAbbr: "MART"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Midway.json b/dojox/date/tests/tztests/tz_Pacific-Midway.json
new file mode 100644
index 0000000..337e493
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Midway.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.Pacific-Midway",
+	runTest: function(t){
+		var tz = "Pacific/Midway";
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -428504401000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "NDT"}, -428504400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "NDT"}, -420645601000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -420645600000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -86878801000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, -86878800000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 439037999000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "SST"}, 439038000000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "SST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "SST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "SST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 660, tzAbbr: "SST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Nauru.json b/dojox/date/tests/tztests/tz_Pacific-Nauru.json
new file mode 100644
index 0000000..4fb8ed3
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Nauru.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.Pacific-Nauru",
+	runTest: function(t){
+		var tz = "Pacific/Nauru";
+		doh.checkDate({tzOffset: -667.666666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -667.666666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -667.666666666667, tzAbbr: "LMT"}, -1545131261000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NRT"}, -1545131260000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NRT"}, -877347001000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -877347000000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "JST"}, -800960401000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NRT"}, -800960400000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NRT"}, 294323399000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NRT"}, 294323400000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NRT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NRT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NRT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NRT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Niue.json b/dojox/date/tests/tztests/tz_Pacific-Niue.json
new file mode 100644
index 0000000..120deae
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Niue.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Pacific-Niue",
+	runTest: function(t){
+		var tz = "Pacific/Niue";
+		doh.checkDate({tzOffset: 680, tzAbbr: "NUT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 680, tzAbbr: "NUT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 680, tzAbbr: "NUT"}, -599575201000, tz, 1);
+		doh.checkDate({tzOffset: 690, tzAbbr: "NUT"}, -599575200000, tz, 1);
+		doh.checkDate({tzOffset: 690, tzAbbr: "NUT"}, 276089399000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NUT"}, 276089400000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NUT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NUT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NUT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NUT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Norfolk.json b/dojox/date/tests/tztests/tz_Pacific-Norfolk.json
new file mode 100644
index 0000000..b1e1e37
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Norfolk.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Pacific-Norfolk",
+	runTest: function(t){
+		var tz = "Pacific/Norfolk";
+		doh.checkDate({tzOffset: -672, tzAbbr: "NMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -672, tzAbbr: "NMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -672, tzAbbr: "NMT"}, -599656321000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NFT"}, -599656320000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NFT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NFT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NFT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -690, tzAbbr: "NFT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Noumea.json b/dojox/date/tests/tztests/tz_Pacific-Noumea.json
new file mode 100644
index 0000000..8d3026f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Noumea.json
@@ -0,0 +1,26 @@
+({
+	name: "date.timezone.Pacific-Noumea",
+	runTest: function(t){
+		var tz = "Pacific/Noumea";
+		doh.checkDate({tzOffset: -665.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -665.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -665.8, tzAbbr: "LMT"}, -1829387149000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "NCT"}, -1829387148000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "NCT"}, 250001999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NCST"}, 250002000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NCST"}, 257342399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "NCT"}, 257342400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "NCT"}, 281451599000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NCST"}, 281451600000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NCST"}, 288878399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "NCT"}, 288878400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "NCT"}, 849365999000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NCST"}, 849366000000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "NCST"}, 857228399000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "NCT"}, 857228400000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "NCT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "NCT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "NCT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -660, tzAbbr: "NCT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Pago_Pago.json b/dojox/date/tests/tztests/tz_Pacific-Pago_Pago.json
new file mode 100644
index 0000000..a83338f
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Pago_Pago.json
@@ -0,0 +1,20 @@
+({
+	name: "date.timezone.Pacific-Pago_Pago",
+	runTest: function(t){
+		var tz = "Pacific/Pago_Pago";
+		doh.checkDate({tzOffset: 682.8, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 682.8, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 682.8, tzAbbr: "LMT"}, -1861879033000, tz, 1);
+		doh.checkDate({tzOffset: 690, tzAbbr: "SAMT"}, -1861879032000, tz, 1);
+		doh.checkDate({tzOffset: 690, tzAbbr: "SAMT"}, -631110601000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -631110600000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "NST"}, -86878801000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, -86878800000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "BST"}, 439037999000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "SST"}, 439038000000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "SST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "SST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 660, tzAbbr: "SST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 660, tzAbbr: "SST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Palau.json b/dojox/date/tests/tztests/tz_Pacific-Palau.json
new file mode 100644
index 0000000..e4b6b8e
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Palau.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Pacific-Palau",
+	runTest: function(t){
+		var tz = "Pacific/Palau";
+		doh.checkDate({tzOffset: -540, tzAbbr: "PWT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "PWT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "PWT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "PWT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "PWT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -540, tzAbbr: "PWT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Pitcairn.json b/dojox/date/tests/tztests/tz_Pacific-Pitcairn.json
new file mode 100644
index 0000000..23c2c53
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Pitcairn.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Pacific-Pitcairn",
+	runTest: function(t){
+		var tz = "Pacific/Pitcairn";
+		doh.checkDate({tzOffset: 510, tzAbbr: "PNT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 510, tzAbbr: "PNT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 510, tzAbbr: "PNT"}, 893665799000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 893665800000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 480, tzAbbr: "PST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Ponape.json b/dojox/date/tests/tztests/tz_Pacific-Ponape.json
new file mode 100644
index 0000000..3ba1acc
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Ponape.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Pacific-Ponape",
+	runTest: function(t){
+		var tz = "Pacific/Ponape";
+		doh.checkDate({tzOffset: -660, tzAbbr: "PONT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "PONT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "PONT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "PONT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -660, tzAbbr: "PONT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -660, tzAbbr: "PONT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Port_Moresby.json b/dojox/date/tests/tztests/tz_Pacific-Port_Moresby.json
new file mode 100644
index 0000000..00f42f6
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Port_Moresby.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Pacific-Port_Moresby",
+	runTest: function(t){
+		var tz = "Pacific/Port_Moresby";
+		doh.checkDate({tzOffset: -600, tzAbbr: "PGT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "PGT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "PGT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "PGT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "PGT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "PGT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Rarotonga.json b/dojox/date/tests/tztests/tz_Pacific-Rarotonga.json
new file mode 100644
index 0000000..ca72231
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Rarotonga.json
@@ -0,0 +1,64 @@
+({
+	name: "date.timezone.Pacific-Rarotonga",
+	runTest: function(t){
+		var tz = "Pacific/Rarotonga";
+		doh.checkDate({tzOffset: 630, tzAbbr: "CKT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 630, tzAbbr: "CKT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 630, tzAbbr: "CKT"}, 279714599000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 279714600000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 289387799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 289387800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 309952799000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 309952800000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 320837399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 320837400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 341402399000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 341402400000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 352286999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 352287000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 372851999000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 372852000000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 384341399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 384341400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 404906399000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 404906400000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 415790999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 415791000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 436355999000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 436356000000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 447240599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 447240600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 467805599000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 467805600000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 478690199000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 478690200000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 499255199000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 499255200000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 510139799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 510139800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 530704799000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 530704800000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 541589399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 541589400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 562154399000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 562154400000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 573643799000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 573643800000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 594208799000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 594208800000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 605093399000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 605093400000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 625658399000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 625658400000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 636542999000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 636543000000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 657107999000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 657108000000, tz, 1);
+		doh.checkDate({tzOffset: 570, tzAbbr: "CKHST"}, 667992599000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 667992600000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 600, tzAbbr: "CKT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Saipan.json b/dojox/date/tests/tztests/tz_Pacific-Saipan.json
new file mode 100644
index 0000000..79a2959
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Saipan.json
@@ -0,0 +1,16 @@
+({
+	name: "date.timezone.Pacific-Saipan",
+	runTest: function(t){
+		var tz = "Pacific/Saipan";
+		doh.checkDate({tzOffset: -540, tzAbbr: "MPT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MPT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -540, tzAbbr: "MPT"}, -7981201000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "MPT"}, -7981200000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "MPT"}, 977493599000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "ChST"}, 977493600000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "ChST"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "ChST"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "ChST"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "ChST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Tahiti.json b/dojox/date/tests/tztests/tz_Pacific-Tahiti.json
new file mode 100644
index 0000000..f65e953
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Tahiti.json
@@ -0,0 +1,14 @@
+({
+	name: "date.timezone.Pacific-Tahiti",
+	runTest: function(t){
+		var tz = "Pacific/Tahiti";
+		doh.checkDate({tzOffset: 598.266666666667, tzAbbr: "LMT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 598.266666666667, tzAbbr: "LMT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 598.266666666667, tzAbbr: "LMT"}, -1806674505000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "TAHT"}, -1806674504000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "TAHT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "TAHT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 600, tzAbbr: "TAHT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: 600, tzAbbr: "TAHT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Tarawa.json b/dojox/date/tests/tztests/tz_Pacific-Tarawa.json
new file mode 100644
index 0000000..d998341
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Tarawa.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Pacific-Tarawa",
+	runTest: function(t){
+		var tz = "Pacific/Tarawa";
+		doh.checkDate({tzOffset: -720, tzAbbr: "GILT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "GILT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "GILT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "GILT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "GILT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -720, tzAbbr: "GILT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Tongatapu.json b/dojox/date/tests/tztests/tz_Pacific-Tongatapu.json
new file mode 100644
index 0000000..227dd9c
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Tongatapu.json
@@ -0,0 +1,26 @@
+({
+	name: "date.timezone.Pacific-Tongatapu",
+	runTest: function(t){
+		var tz = "Pacific/Tongatapu";
+		doh.checkDate({tzOffset: -740, tzAbbr: "TOT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -740, tzAbbr: "TOT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -740, tzAbbr: "TOT"}, -915193201000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "TOT"}, -915193200000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "TOT"}, 939214799000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "TOST"}, 939214800000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "TOST"}, 953384399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "TOT"}, 953384400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "TOT"}, 973342799000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "TOST"}, 973342800000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "TOST"}, 980596799000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "TOT"}, 980596800000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "TOT"}, 1004792399000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "TOST"}, 1004792400000, tz, 1);
+		doh.checkDate({tzOffset: -840, tzAbbr: "TOST"}, 1012046399000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "TOT"}, 1012046400000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "TOT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "TOT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -780, tzAbbr: "TOT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -780, tzAbbr: "TOT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Truk.json b/dojox/date/tests/tztests/tz_Pacific-Truk.json
new file mode 100644
index 0000000..5b7c26b
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Truk.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Pacific-Truk",
+	runTest: function(t){
+		var tz = "Pacific/Truk";
+		doh.checkDate({tzOffset: -600, tzAbbr: "TRUT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "TRUT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "TRUT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "TRUT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -600, tzAbbr: "TRUT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -600, tzAbbr: "TRUT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Wake.json b/dojox/date/tests/tztests/tz_Pacific-Wake.json
new file mode 100644
index 0000000..71c03f4
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Wake.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Pacific-Wake",
+	runTest: function(t){
+		var tz = "Pacific/Wake";
+		doh.checkDate({tzOffset: -720, tzAbbr: "WAKT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "WAKT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "WAKT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "WAKT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "WAKT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -720, tzAbbr: "WAKT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_Pacific-Wallis.json b/dojox/date/tests/tztests/tz_Pacific-Wallis.json
new file mode 100644
index 0000000..341e1cd
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_Pacific-Wallis.json
@@ -0,0 +1,12 @@
+({
+	name: "date.timezone.Pacific-Wallis",
+	runTest: function(t){
+		var tz = "Pacific/Wallis";
+		doh.checkDate({tzOffset: -720, tzAbbr: "WFT"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "WFT"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "WFT"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "WFT"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: -720, tzAbbr: "WFT"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -720, tzAbbr: "WFT"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests/tz_WET.json b/dojox/date/tests/tztests/tz_WET.json
new file mode 100644
index 0000000..5edaf49
--- /dev/null
+++ b/dojox/date/tests/tztests/tz_WET.json
@@ -0,0 +1,256 @@
+({
+	name: "date.timezone.WET",
+	runTest: function(t){
+		var tz = "WET";
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -2147483648000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, -2147397248000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 228877199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 228877200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 243997199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 243997200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 260326799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 260326800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 276051599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 276051600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 291776399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 291776400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 307501199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 307501200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 323830799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 323830800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 338950799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 338950800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 354675599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 354675600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 370400399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 370400400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 386125199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 386125200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 401849999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 401850000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 417574799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 417574800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 433299599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 433299600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 449024399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 449024400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 465353999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 465354000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 481078799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 481078800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 496803599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 496803600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 512528399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 512528400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 528253199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 528253200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 543977999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 543978000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 559702799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 559702800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 575427599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 575427600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 591152399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 591152400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 606877199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 606877200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 622601999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 622602000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 638326799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 638326800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 654656399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 654656400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 670381199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 670381200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 686105999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 686106000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 701830799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 701830800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 717555599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 717555600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 733280399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 733280400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 749005199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 749005200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 764729999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 764730000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 780454799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 780454800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 796179599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 796179600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 811904399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 811904400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 828233999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 828234000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 846377999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 846378000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 859683599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 859683600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 877827599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 877827600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 891133199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 891133200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 909277199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 909277200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 922582799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 922582800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 941331599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 941331600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 954032399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 954032400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 972781199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 972781200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 985481999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 985482000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1004230799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1004230800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1017536399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1017536400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1035680399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1035680400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1048985999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1048986000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1067129999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1067130000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1080435599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1080435600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1099184399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1099184400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1111885199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1111885200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1130633999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1130634000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1143334799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1143334800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1162083599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1162083600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1174784399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1174784400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1193533199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1193533200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1206838799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1206838800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1224982799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1224982800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1238288399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1238288400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1256432399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1256432400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1269737999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1269738000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1288486799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1288486800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1301187599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1301187600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1319936399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1319936400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1332637199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1332637200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1351385999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1351386000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1364691599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1364691600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1382835599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1382835600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1396141199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1396141200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1414285199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1414285200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1427590799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1427590800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1445734799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1445734800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1459040399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1459040400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1477789199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1477789200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1490489999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1490490000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1509238799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1509238800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1521939599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1521939600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1540688399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1540688400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1553993999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1553994000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1572137999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1572138000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1585443599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1585443600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1603587599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1603587600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1616893199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1616893200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1635641999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1635642000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1648342799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1648342800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1667091599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1667091600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1679792399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1679792400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1698541199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1698541200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1711846799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1711846800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1729990799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1729990800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1743296399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1743296400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1761440399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1761440400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1774745999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1774746000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1792889999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1792890000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1806195599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1806195600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1824944399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1824944400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1837645199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1837645200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1856393999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1856394000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1869094799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1869094800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1887843599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1887843600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1901149199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1901149200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1919293199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1919293200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1932598799000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1932598800000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1950742799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1950742800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1964048399000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1964048400000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1982797199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1982797200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1995497999000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1995498000000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2014246799000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2014246800000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2026947599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2026947600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2045696399000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2045696400000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2058397199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2058397200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2077145999000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2077146000000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2090451599000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2090451600000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2108595599000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2108595600000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2121901199000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2121901200000, tz, 1);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 2140045199000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2140045200000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147397247000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 2147483647000, tz, 1);
+		doh.checkDate({tzOffset: 0, tzAbbr: "WET"}, 1231151400000, tz, 0);
+		doh.checkDate({tzOffset: -60, tzAbbr: "WEST"}, 1246789800000, tz, 0);
+	}
+})
diff --git a/dojox/date/tests/tztests_from_zdump.pl b/dojox/date/tests/tztests_from_zdump.pl
new file mode 100644
index 0000000..19d46f1
--- /dev/null
+++ b/dojox/date/tests/tztests_from_zdump.pl
@@ -0,0 +1,227 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+use lib './lib';
+
+use DateTime::TimeZone;
+use File::Spec;
+use Getopt::Long;
+use DateTime;
+
+my %opts;
+GetOptions( 'name:s'     => \@{ $opts{name} },
+            'zoneinfo:s' => \$opts{zoneinfo},
+            'zdump:s'    => \$opts{zdump},
+            'verbose'    => \$opts{verbose},
+            'help'       => \$opts{help},
+          );
+
+if ( $opts{help} )
+{
+    print <<'EOF';
+
+This script uses the zdump utility to generate comprehensive tests for
+time zones.
+
+Tests are generated as files in the tztests/ directory starting with "tz_".
+
+By default, it generates tests for all time zones.
+
+For each time zone name, it checks to see that the zoneinfo directory
+has a corresponding file.  This is done because zdump will happily
+generate garbage output if given a non-existent time zone name.
+
+Note, if your version of the zoneinfo data is different from that used
+to generate the Perl time zone modules then you will almost certainly
+end up generating some tests that fail.
+
+It takes the following arguments:
+
+  --name      Only create tests for this zone.
+              May be given multiple times.
+
+  --zoneinfo  The location of your zoneinfo directory.
+              Defaults to /usr/share/zoneinfo.
+
+  --zdump     Path to zdump binary.  Default is just 'zdump'.
+
+  --verbose   Blab about what it's doing as it does it.
+
+  --help      What you are reading
+
+EOF
+
+    exit;
+}
+
+$opts{zoneinfo} ||= '/usr/share/zoneinfo';
+
+die "No zoneinfo directory at $opts{zoneinfo}!\n" unless -d $opts{zoneinfo};
+
+$opts{zdump} ||= 'zdump';
+
+my $x = 1;
+my %months = map { $_ => $x++ }
+             qw( Jan Feb Mar Apr May Jun
+	         Jul Aug Sep Oct Nov Dec);
+
+my @pieces = qw( year month day hour minute second );
+
+my @names = @{ $opts{name} } ? @{ $opts{name} } : DateTime::TimeZone::all_names();
+foreach my $tz_name (@names)
+{
+    unless ( -e File::Spec->catfile( $opts{zoneinfo}, split /\//, $tz_name ) )
+    {
+        print "\nNo zoneinfo file for $tz_name - skipping\n" if $opts{verbose};
+        next;
+    }
+
+    print "\nGetting change data for $tz_name\n" if $opts{verbose};
+
+    my @tests;
+    my $command = "$opts{zdump} -v $tz_name";
+    my @lines = `$command`;
+
+    die qq|Nothing returning from calling "$command".  Did you specify a valid zdump binary?\n|
+        unless @lines;
+
+    foreach my $line (@lines)
+    {
+        # This seems to happen on 64-bit systems.
+        next if $line =~ /= NULL$/;
+
+        my ( $utc_mon_name, $utc_day, $utc_hour, $utc_min, $utc_sec, $utc_year,
+             $loc_mon_name, $loc_day, $loc_hour, $loc_min, $loc_sec, $loc_year,
+             $short_name, $is_dst ) =
+                 $line =~
+                     m/ ^
+                        \w+(?:\/[\w\/-]+)? # zone name
+                        \s+
+                        \w\w\w        # UTC day name
+                        \s+
+                        (\w\w\w)      # UTC month name
+                        \s+
+                        (\d+)         # UTC day of month
+                        \s+
+                        (\d\d):(\d\d):(\d\d)  # UTC time
+                        \s+
+                        (\d\d\d\d)    # UTC year
+                        \s+
+                        (?:UTC|GMT)   # some systems say one, some the other
+                        \s+
+                        =
+                        \s+
+                        \w\w\w        # local day name
+                        \s+
+                        (\w\w\w)      # local month name
+                        \s+
+                        (\d+)         # local day of month
+                        \s+
+                        (\d\d):(\d\d):(\d\d)  # local time
+                        \s+
+                        (\d\d\d\d)    # local year
+                        \s+
+                        (\w+)         # local short name
+                        \s+
+                        isdst=(1|0)
+                      /x;
+
+        unless ($1)
+        {
+            warn "Can't parse zump output:\n$line\n";
+            next;
+        }
+
+        my $utc_month = $months{$utc_mon_name};
+        my $loc_month = $months{$loc_mon_name};
+
+		my $dt = DateTime->new( year => 1 * $utc_year,
+								month => (1 * $utc_month),
+								day => 1 * $utc_day,
+								hour => 1 * $utc_hour,
+								minute => 1 * $utc_min,
+								second => 1 * $utc_sec,
+								time_zone => 'UTC', );
+		$dt->set_time_zone($tz_name);
+        # use '1 * ' to make sure everything is treated as numbers,
+        push @tests, { time_zone => $tz_name,
+                       short_name => $short_name,
+					   epoch	  => $dt->epoch,
+                       offset     => (($dt->offset * -1) / 60),
+                       edge       => 1,
+                     }
+    }
+
+	# Just some fairly-current tests - non-edgecase
+	my $currDt = DateTime->new( year => 2009,
+                                month => 1,
+                                day => 5,
+                                hour => 10,
+                                minute => 30,
+                                second => 0,
+                                time_zone => 'UTC', );
+	$currDt->set_time_zone($tz_name);
+	push @tests, { time_zone => $tz_name,
+                       short_name => $currDt->time_zone_short_name,
+					   epoch	  => $currDt->epoch,
+                       offset     => (($currDt->offset * -1) / 60),
+                       edge       => 0,
+                     };
+	$currDt = DateTime->new( year => 2009,
+                                month => 7,
+                                day => 5,
+                                hour => 10,
+                                minute => 30,
+                                second => 0,
+                                time_zone => 'UTC', );
+	$currDt->set_time_zone($tz_name);
+	push @tests, { time_zone => $tz_name,
+                       short_name => $currDt->time_zone_short_name,
+					   epoch	  => $currDt->epoch,
+                       offset     => (($currDt->offset * -1) / 60),
+                       edge       => 0,
+                     };
+					
+
+    unless (@tests)
+    {
+        print "No change data in time_t range for $tz_name - can't create tests\n" if $opts{verbose};
+        next;
+    }
+
+    local *T;
+
+    (my $test_file_name = $tz_name) =~ s,/,-,g;
+    my $file = File::Spec->catfile( 'tztests', "tz_$test_file_name.json" );
+    open T, ">$file"
+        or die "Cannot write to $file: $!";
+
+    print "Creating tests for $tz_name in $file\n" if $opts{verbose};
+
+    my $test_count = scalar @tests * 9;
+
+	my $started = 0;
+
+    foreach my $t (@tests)
+    {
+		if (!$started){
+			print T <<"EOF";
+({
+	name: "date.timezone.$test_file_name",
+	runTest: function(t){
+		var tz = "$tz_name";
+EOF
+			$started = 1;
+		}
+		print T <<"EOF";
+		doh.checkDate({tzOffset: $t->{offset}, tzAbbr: "$t->{short_name}"}, $t->{epoch}000, tz, $t->{edge});
+EOF
+	}
+	if($started){
+    	print T <<"EOF";
+	}
+})
+EOF
+	}
+}
diff --git a/dojox/date/timezone.js b/dojox/date/timezone.js
index 7483065..452ec20 100644
--- a/dojox/date/timezone.js
+++ b/dojox/date/timezone.js
@@ -1,445 +1,710 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.date.timezone"]){
-dojo._hasResource["dojox.date.timezone"]=true;
+/******************************************************************************
+ * Dojo port of fleegix date plugin from
+ *
+ *   http://js.fleegix.org/plugins/date/date
+ *
+ * contributed to Dojo under CLA, with thanks to Matthew Eernisse (mde at fleegix.org)
+ * and Open Source Applications Foundation
+ *
+ * Credits: Ideas included from incomplete JS implementation of Olson
+ * parser, "XMLDate" by Philippe Goetz (philippe.goetz at wanadoo.fr)
+ *****************************************************************************/
 dojo.experimental("dojox.date.timezone");
 dojo.provide("dojox.date.timezone");
+
 dojo.require("dojo.date.locale");
-(function(_1){
-var _2=_1.config;
-var _3=["africa","antarctica","asia","australasia","backward","etcetera","europe","northamerica","pacificnew","southamerica"];
-var _4=1835;
-var _5=2038;
-var _6={};
-var _7={};
-var _8={};
-var _9={};
-var _a=_2.timezoneFileBasePath||_1.moduleUrl("dojox.date","zoneinfo");
-var _b=_2.timezoneLoadingScheme||"preloadAll";
-var _c=_2.defaultZoneFile||((_b=="preloadAll")?_3:"northamerica");
-_1._contentHandlers["olson-zoneinfo"]=function(_d){
-var _e=_1._contentHandlers["text"](_d);
-var s="";
-var _f=_e.split("\n");
-var arr=[];
-var _10="";
-var _11=null;
-var _12=null;
-var ret={zones:{},rules:{}};
-for(var i=0;i<_f.length;i++){
-var l=_f[i];
-if(l.match(/^\s/)){
-l="Zone "+_11+l;
-}
-l=l.split("#")[0];
-if(l.length>3){
-arr=l.split(/\s+/);
-_10=arr.shift();
-switch(_10){
-case "Zone":
-_11=arr.shift();
-if(arr[0]){
-if(!ret.zones[_11]){
-ret.zones[_11]=[];
-}
-ret.zones[_11].push(arr);
-}
-break;
-case "Rule":
-_12=arr.shift();
-if(!ret.rules[_12]){
-ret.rules[_12]=[];
-}
-ret.rules[_12].push(arr);
-break;
-case "Link":
-if(ret.zones[arr[1]]){
-throw new Error("Error with Link "+arr[1]);
-}
-ret.zones[arr[1]]=arr[0];
-break;
-case "Leap":
-break;
-default:
-break;
-}
-}
-}
-return ret;
-};
-function _13(_14){
-_14=_14||{};
-_7=_1.mixin(_7,_14.zones||{});
-_9=_1.mixin(_9,_14.rules||{});
-};
-function _15(e){
-console.error("Error loading zone file:",e);
-throw e;
-};
-function _16(_17){
-_6[_17]=true;
-_1.xhrGet({url:_a+"/"+_17,sync:true,handleAs:"olson-zoneinfo",load:_13,error:_15});
-};
-var _18={"jan":0,"feb":1,"mar":2,"apr":3,"may":4,"jun":5,"jul":6,"aug":7,"sep":8,"oct":9,"nov":10,"dec":11};
-var _19={"sun":0,"mon":1,"tue":2,"wed":3,"thu":4,"fri":5,"sat":6};
-var _1a={"EST":"northamerica","MST":"northamerica","HST":"northamerica","EST5EDT":"northamerica","CST6CDT":"northamerica","MST7MDT":"northamerica","PST8PDT":"northamerica","America":"northamerica","Pacific":"australasia","Atlantic":"europe","Africa":"africa","Indian":"africa","Antarctica":"antarctica","Asia":"asia","Australia":"australasia","Europe":"europe","WET":"europe","CET":"europe","MET":"europe","EET":"europe"};
-var _1b={"Pacific/Honolulu":"northamerica","Atlantic/Bermuda":"northamerica","Atlantic/Cape_Verde":"africa","Atlantic/St_Helena":"africa","Indian/Kerguelen":"antarctica","Indian/Chagos":"asia","Indian/Maldives":"asia","Indian/Christmas":"australasia","Indian/Cocos":"australasia","America/Danmarkshavn":"europe","America/Scoresbysund":"europe","America/Godthab":"europe","America/Thule":"europe","Asia/Yekaterinburg":"europe","Asia/Omsk":"europe","Asia/Novosibirsk":"europe","Asia/Krasnoyarsk [...]
-var _1c={"US":"S","Chatham":"S","NZ":"S","NT_YK":"S","Edm":"S","Salv":"S","Canada":"S","StJohns":"S","TC":"S","Guat":"S","Mexico":"S","Haiti":"S","Barb":"S","Belize":"S","CR":"S","Moncton":"S","Swift":"S","Hond":"S","Thule":"S","NZAQ":"S","Zion":"S","ROK":"S","PRC":"S","Taiwan":"S","Ghana":"GMT","SL":"WAT","Chicago":"S","Detroit":"S","Vanc":"S","Denver":"S","Halifax":"S","Cuba":"S","Indianapolis":"S","Starke":"S","Marengo":"S","Pike":"S","Perry":"S","Vincennes":"S","Pulaski":"S","Louisvi [...]
-function _1d(t){
-throw new Error("Timezone \""+t+"\" is either incorrect, or not loaded in the timezone registry.");
-};
-function _1e(tz){
-var ret=_1b[tz];
-if(!ret){
-var reg=tz.split("/")[0];
-ret=_1a[reg];
-if(!ret){
-var _1f=_7[tz];
-if(typeof _1f=="string"){
-return _1e(_1f);
-}else{
-if(!_6.backward){
-_16("backward");
-return _1e(tz);
-}else{
-_1d(tz);
-}
-}
-}
-}
-return ret;
-};
-function _20(str){
-var pat=/(\d+)(?::0*(\d*))?(?::0*(\d*))?([su])?$/;
-var hms=str.match(pat);
-if(!hms){
-return null;
-}
-hms[1]=parseInt(hms[1],10);
-hms[2]=hms[2]?parseInt(hms[2],10):0;
-hms[3]=hms[3]?parseInt(hms[3],10):0;
-return hms;
-};
-function _21(y,m,d,h,mn,s,off){
-return Date.UTC(y,m,d,h,mn,s)+((off||0)*60*1000);
-};
-function _22(m){
-return _18[m.substr(0,3).toLowerCase()];
-};
-function _23(str){
-var off=_20(str);
-if(off===null){
-return 0;
-}
-var adj=str.indexOf("-")===0?-1:1;
-off=adj*(((off[1]*60+off[2])*60+off[3])*1000);
-return -off/60/1000;
-};
-function _24(_25,_26,off){
-var _27=_22(_25[3]),day=_25[4],_28=_20(_25[5]);
-if(_28[4]=="u"){
-off=0;
-}
-var d,_29,_2a;
-if(isNaN(day)){
-if(day.substr(0,4)=="last"){
-day=_19[day.substr(4,3).toLowerCase()];
-d=new Date(_21(_26,_27+1,1,_28[1]-24,_28[2],_28[3],off));
-_29=_1.date.add(d,"minute",-off).getUTCDay();
-_2a=(day>_29)?(day-_29-7):(day-_29);
-if(_2a!==0){
-d=_1.date.add(d,"hour",_2a*24);
-}
-return d;
-}else{
-day=_19[day.substr(0,3).toLowerCase()];
-if(day!="undefined"){
-if(_25[4].substr(3,2)==">="){
-d=new Date(_21(_26,_27,parseInt(_25[4].substr(5),10),_28[1],_28[2],_28[3],off));
-_29=_1.date.add(d,"minute",-off).getUTCDay();
-_2a=(day<_29)?(day-_29+7):(day-_29);
-if(_2a!==0){
-d=_1.date.add(d,"hour",_2a*24);
-}
-return d;
-}else{
-if(day.substr(3,2)=="<="){
-d=new Date(_21(_26,_27,parseInt(_25[4].substr(5),10),_28[1],_28[2],_28[3],off));
-_29=_1.date.add(d,"minute",-off).getUTCDay();
-_2a=(day>_29)?(day-_29-7):(day-_29);
-if(_2a!==0){
-d=_1.date.add(d,"hour",_2a*24);
-}
-return d;
-}
-}
-}
-}
-}else{
-d=new Date(_21(_26,_27,parseInt(day,10),_28[1],_28[2],_28[3],off));
-return d;
-}
-return null;
-};
-function _2b(_2c,_2d){
-var _2e=[];
-_1.forEach(_9[_2c[1]]||[],function(r){
-for(var i=0;i<2;i++){
-switch(r[i]){
-case "min":
-r[i]=_4;
-break;
-case "max":
-r[i]=_5;
-break;
-case "only":
-break;
-default:
-r[i]=parseInt(r[i],10);
-if(isNaN(r[i])){
-throw new Error("Invalid year found on rule");
-}
-break;
-}
-}
-if(typeof r[6]=="string"){
-r[6]=_23(r[6]);
-}
-if((r[0]<=_2d&&r[1]>=_2d)||(r[0]==_2d&&r[1]=="only")){
-_2e.push({r:r,d:_24(r,_2d,_2c[0])});
-}
-});
-return _2e;
-};
-function _2f(tz,_30){
-var zr=_8[tz]=[];
-for(var i=0;i<_30.length;i++){
-var z=_30[i];
-var r=zr[i]=[];
-var _31=null;
-var _32=null;
-var _33=[];
-if(typeof z[0]=="string"){
-z[0]=_23(z[0]);
-}
-if(i===0){
-r[0]=Date.UTC(_4,0,1,0,0,0,0);
-}else{
-r[0]=zr[i-1][1];
-_31=_30[i-1];
-_32=zr[i-1];
-_33=_32[2];
-}
-var _34=new Date(r[0]).getUTCFullYear();
-var _35=z[3]?parseInt(z[3],10):_5;
-var rlz=[];
-var j;
-for(j=_34;j<=_35;j++){
-rlz=rlz.concat(_2b(z,j));
-}
-rlz.sort(function(a,b){
-return _1.date.compare(a.d,b.d);
-});
-var rl;
-for(j=0,rl;(rl=rlz[j]);j++){
-var _36=j>0?rlz[j-1]:null;
-if(rl.r[5].indexOf("u")<0&&rl.r[5].indexOf("s")<0){
-if(j===0&&i>0){
-if(_33.length){
-rl.d=_1.date.add(rl.d,"minute",_33[_33.length-1].r[6]);
-}else{
-if(_1.date.compare(new Date(_32[1]),rl.d,"date")===0){
-rl.d=new Date(_32[1]);
-}else{
-rl.d=_1.date.add(rl.d,"minute",_23(_31[1]));
-}
-}
-}else{
-if(j>0){
-rl.d=_1.date.add(rl.d,"minute",_36.r[6]);
-}
-}
-}
-}
-r[2]=rlz;
-if(!z[3]){
-r[1]=Date.UTC(_5,11,31,23,59,59,999);
-}else{
-var _37=parseInt(z[3],10),_38=_22(z[4]||"Jan"),day=parseInt(z[5]||"1",10),_39=_20(z[6]||"0");
-var _3a=r[1]=_21(_37,_38,day,_39[1],_39[2],_39[3],((_39[4]=="u")?0:z[0]));
-if(isNaN(_3a)){
-_3a=r[1]=_24([0,0,0,z[4],z[5],z[6]||"0"],_37,((_39[4]=="u")?0:z[0])).getTime();
-}
-var _3b=_1.filter(rlz,function(rl,idx){
-var o=idx>0?rlz[idx-1].r[6]*60*1000:0;
-return (rl.d.getTime()<_3a+o);
-});
-if(_39[4]!="u"&&_39[4]!="s"){
-if(_3b.length){
-r[1]+=_3b[_3b.length-1].r[6]*60*1000;
-}else{
-r[1]+=_23(z[1])*60*1000;
-}
-}
-}
-}
-};
-function _3c(dt,tz){
-var t=tz;
-var _3d=_7[t];
-while(typeof _3d=="string"){
-t=_3d;
-_3d=_7[t];
-}
-if(!_3d){
-if(!_6.backward){
-var _3e=_16("backward",true);
-return _3c(dt,tz);
-}
-_1d(t);
-}
-if(!_8[tz]){
-_2f(tz,_3d);
-}
-var _3f=_8[tz];
-var tm=dt.getTime();
-for(var i=0,r;(r=_3f[i]);i++){
-if(tm>=r[0]&&tm<r[1]){
-return {zone:_3d[i],range:_3f[i],idx:i};
-}
-}
-throw new Error("No Zone found for \""+tz+"\" on "+dt);
-};
-function _40(dt,_41){
-var _42=-1;
-var _43=_41.range[2]||[];
-var tsp=dt.getTime();
-var zr=_41.range;
-for(var i=0,r;(r=_43[i]);i++){
-if(tsp>=r.d.getTime()){
-_42=i;
-}
-}
-if(_42>=0){
-return _43[_42].r;
-}
-return null;
-};
-function _44(tz,_45,_46){
-var res;
-var _47=_45.zone;
-var _48=_47[2];
-if(_48.indexOf("%s")>-1){
-var _49;
-if(_46){
-_49=_46[7];
-if(_49=="-"){
-_49="";
-}
-}else{
-if(_47[1] in _1c){
-_49=_1c[_47[1]];
-}else{
-if(_45.idx>0){
-var pz=_7[tz][_45.idx-1];
-var pb=pz[2];
-if(pb.indexOf("%s")<0){
-if(_48.replace("%s","S")==pb){
-_49="S";
-}else{
-_49="";
-}
-}else{
-_49="";
-}
-}else{
-_49="";
-}
-}
-}
-res=_48.replace("%s",_49);
-}else{
-if(_48.indexOf("/")>-1){
-var bs=_48.split("/");
-if(_46){
-res=bs[_46[6]===0?0:1];
-}else{
-res=bs[0];
-}
-}else{
-res=_48;
-}
-}
-return res;
+
+(function(_d){
+	var cfg = _d.config;
+	var _zoneFiles = [ "africa", "antarctica", "asia", "australasia", "backward", 
+					"etcetera", "europe", "northamerica", "pacificnew", 
+					"southamerica" ];
+					
+	// Our mins an maxes for years that we care about
+	var _minYear = 1835,
+		_maxYear = 2038;
+	
+	var _loadedZones = {},
+		_zones = {},
+		_loadedRanges = {},
+		_rules = {};
+	
+	// timezoneFileBasePath: String
+	//		A different location to pull zone files from
+	var timezoneFileBasePath = cfg.timezoneFileBasePath || 
+								_d.moduleUrl("dojox.date", "zoneinfo");
+	
+	// loadingScheme: String
+	//		One of "preloadAll", "lazyLoad" (Defaults "lazyLoad")
+	var loadingScheme = cfg.timezoneLoadingScheme || "preloadAll";
+		
+	// defaultZoneFile: String or String[]
+	//		The default file (or files) to load on startup - other files will
+	//		be lazily-loaded on-demand
+	var defaultZoneFile = cfg.defaultZoneFile || 
+					((loadingScheme == "preloadAll") ? _zoneFiles : "northamerica");
+
+	// Set our olson-zoneinfo content handler
+	_d._contentHandlers["olson-zoneinfo"] = function(xhr){
+		var str = _d._contentHandlers["text"](xhr);
+		var s = "";
+		var lines = str.split("\n");
+		var arr = [];
+		var chunk = "";
+		var zone = null;
+		var rule = null;
+		var ret = {zones: {}, rules: {}};
+		for(var i = 0; i < lines.length; i++){
+			var l = lines[i];
+			if(l.match(/^\s/)){
+				l = "Zone " + zone + l;
+			}
+			l = l.split("#")[0];
+			if(l.length > 3){
+				arr = l.split(/\s+/);
+				chunk = arr.shift();
+				switch(chunk){
+					case 'Zone':
+						zone = arr.shift();
+						if(arr[0]){
+							// Handle extra commas in the middle of a zone
+							if(!ret.zones[zone]){ ret.zones[zone] = []; }
+							ret.zones[zone].push(arr);
+						}
+						break;
+					case 'Rule':
+						rule = arr.shift();
+						if(!ret.rules[rule]){ ret.rules[rule] = []; }
+						ret.rules[rule].push(arr);
+						break;
+					case 'Link':
+						// No zones for these should already exist
+						if(ret.zones[arr[1]]){
+						  throw new Error('Error with Link ' + arr[1]);
+						}
+						// Create the link
+						ret.zones[arr[1]] = arr[0];
+						break;
+					case 'Leap':
+						break;
+					default:
+						// Fail silently
+						break;
+				}
+			}
+		}
+		return ret; // Object
+	};
+	
+	function loadZoneObj(/* Object */ data){
+		// summary:
+		//		Loads the given data object into the zone database
+		//
+		// data: Object
+		//		The data to load - contains "zones" and "rules" parameters
+		data = data || {};
+		_zones = _d.mixin(_zones, data.zones||{});
+		_rules = _d.mixin(_rules, data.rules||{});
+	}
+	
+	function errorLoadingZoneFile(e){
+		console.error("Error loading zone file:", e);
+		throw e;
+	}
+	
+	function loadZoneFile(/* String */ fileName){
+		// summary:
+		//		Loads the given URL of the Olson zone information into the
+		//		zone database
+		//
+		// fileName: String
+		//		The zoneinfo file name to load
+		
+		// TODO: Maybe behave similar to requireLocalization - rather than
+		//		Using dojo.xhrGet?
+		_loadedZones[fileName] = true;
+		_d.xhrGet({
+			url: timezoneFileBasePath + "/" + fileName,
+			sync: true, // Needs to be synchronous so we can return values
+			handleAs: "olson-zoneinfo",
+			load: loadZoneObj,
+			error: errorLoadingZoneFile
+		});
+	}
+	
+	var monthMap = { 'jan': 0, 'feb': 1, 'mar': 2, 'apr': 3,'may': 4, 'jun': 5,
+				'jul': 6, 'aug': 7, 'sep': 8, 'oct': 9, 'nov': 10, 'dec': 11 },
+		dayMap = {'sun': 0, 'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4, 
+				'fri': 5, 'sat': 6 },
+		regionMap = {'EST': "northamerica", 'MST': "northamerica",
+					'HST': "northamerica", 'EST5EDT': "northamerica",
+					'CST6CDT': "northamerica", 'MST7MDT': "northamerica",
+					'PST8PDT': "northamerica", 'America': "northamerica",
+					'Pacific': "australasia", 'Atlantic': "europe",
+					'Africa': "africa", 'Indian': "africa",
+					'Antarctica': "antarctica", 'Asia': "asia", 
+					'Australia': "australasia", 'Europe': "europe",
+					'WET': "europe", 'CET': "europe", 'MET': "europe",
+					'EET': "europe"},
+		regionExceptions = {'Pacific/Honolulu':"northamerica",
+							'Atlantic/Bermuda':"northamerica",
+							'Atlantic/Cape_Verde':"africa",
+							'Atlantic/St_Helena':"africa",
+							'Indian/Kerguelen':"antarctica",
+							'Indian/Chagos':"asia",
+							'Indian/Maldives':"asia",
+							'Indian/Christmas':"australasia",
+							'Indian/Cocos':"australasia",
+							'America/Danmarkshavn':"europe",
+							'America/Scoresbysund':"europe",
+							'America/Godthab':"europe",
+							'America/Thule':"europe",
+							'Asia/Yekaterinburg':"europe",
+							'Asia/Omsk':"europe",
+							'Asia/Novosibirsk':"europe",
+							'Asia/Krasnoyarsk':"europe",
+							'Asia/Irkutsk':"europe",
+							'Asia/Yakutsk':"europe",
+							'Asia/Vladivostok':"europe",
+							'Asia/Sakhalin':"europe",
+							'Asia/Magadan':"europe",
+							'Asia/Kamchatka':"europe",
+							'Asia/Anadyr':"europe",
+							'Africa/Ceuta':"europe",
+							'America/Argentina/Buenos_Aires':"southamerica",
+							'America/Argentina/Cordoba':"southamerica",
+							'America/Argentina/Tucuman':"southamerica",
+							'America/Argentina/La_Rioja':"southamerica",
+							'America/Argentina/San_Juan':"southamerica",
+							'America/Argentina/Jujuy':"southamerica",
+							'America/Argentina/Catamarca':"southamerica",
+							'America/Argentina/Mendoza':"southamerica",
+							'America/Argentina/Rio_Gallegos':"southamerica",
+							'America/Argentina/Ushuaia':"southamerica",
+							'America/Aruba':"southamerica",
+							'America/La_Paz':"southamerica",
+							'America/Noronha':"southamerica",
+							'America/Belem':"southamerica",
+							'America/Fortaleza':"southamerica",
+							'America/Recife':"southamerica",
+							'America/Araguaina':"southamerica",
+							'America/Maceio':"southamerica",
+							'America/Bahia':"southamerica",
+							'America/Sao_Paulo':"southamerica",
+							'America/Campo_Grande':"southamerica",
+							'America/Cuiaba':"southamerica",
+							'America/Porto_Velho':"southamerica",
+							'America/Boa_Vista':"southamerica",
+							'America/Manaus':"southamerica",
+							'America/Eirunepe':"southamerica",
+							'America/Rio_Branco':"southamerica",
+							'America/Santiago':"southamerica",
+							'Pacific/Easter':"southamerica",
+							'America/Bogota':"southamerica",
+							'America/Curacao':"southamerica",
+							'America/Guayaquil':"southamerica",
+							'Pacific/Galapagos':"southamerica",
+							'Atlantic/Stanley':"southamerica",
+							'America/Cayenne':"southamerica",
+							'America/Guyana':"southamerica",
+							'America/Asuncion':"southamerica",
+							'America/Lima':"southamerica",
+							'Atlantic/South_Georgia':"southamerica",
+							'America/Paramaribo':"southamerica",
+							'America/Port_of_Spain':"southamerica",
+							'America/Montevideo':"southamerica",
+							'America/Caracas':"southamerica"},
+		abbrExceptions = { 'US': "S", 'Chatham': "S", 'NZ': "S", 'NT_YK': "S", 
+							'Edm': "S", 'Salv': "S", 'Canada': "S", 'StJohns': "S",
+							'TC': "S", 'Guat': "S", 'Mexico': "S", 'Haiti': "S",
+							'Barb': "S", 'Belize': "S", 'CR': "S", 'Moncton': "S",
+							'Swift': "S", 'Hond': "S", 'Thule': "S", 'NZAQ': "S",
+							'Zion': "S", 'ROK': "S", 'PRC': "S", 'Taiwan': "S",
+							'Ghana': "GMT", 'SL': "WAT", 'Chicago': "S", 
+							'Detroit': "S", 'Vanc': "S", 'Denver': "S", 
+							'Halifax': "S", 'Cuba': "S", 'Indianapolis': "S",
+							'Starke': "S", 'Marengo': "S", 'Pike': "S",
+							'Perry': "S", 'Vincennes': "S", 'Pulaski': "S",
+							'Louisville': "S", 'CA': "S", 'Nic': "S",
+							'Menominee': "S", 'Mont': "S", 'Bahamas': "S",
+							'NYC': "S", 'Regina': "S", 'Resolute': "ES",
+							'DR': "S", 'Toronto': "S", 'Winn': "S" };
+	
+	function invalidTZError(t) {
+		throw new Error('Timezone "' + t + 
+				'" is either incorrect, or not loaded in the timezone registry.');
+	}
+	
+	function getRegionForTimezone(/* String */ tz) {
+		// summary:
+		//		Returns the Olson region for the given timezone
+		var ret = regionExceptions[tz];
+		if(!ret){
+			var reg = tz.split('/')[0];
+			ret = regionMap[reg];
+			// If there's nothing listed in the main regions for
+			// this TZ, check the 'backward' links
+			if(!ret){
+				var link = _zones[tz];
+				if(typeof link == 'string'){
+					return getRegionForTimezone(link); // String
+				}else{
+					// Backward-compat file hasn't loaded yet, try looking in there
+					if (!_loadedZones.backward) {
+						// This is for obvious legacy zones (e.g., Iceland) that
+						// don't even have a prefix like "America/" that look like
+						// normal zones
+						loadZoneFile("backward");
+						return getRegionForTimezone(tz); // String
+					}else{
+						invalidTZError(tz);
+					}
+				}
+			}
+		}
+		return ret; // String
+	}
+	
+	function parseTimeString(/* String */ str) {
+		// summary:
+		//		Parses the given time string and returns it as an integer array
+		var pat = /(\d+)(?::0*(\d*))?(?::0*(\d*))?([su])?$/;
+		var hms = str.match(pat);
+		if(!hms){
+			return null;
+		}
+		hms[1] = parseInt(hms[1], 10);
+		hms[2] = hms[2] ? parseInt(hms[2], 10) : 0;
+		hms[3] = hms[3] ? parseInt(hms[3], 10) : 0;
+		return hms; // int[]
+	}
+	
+	function getUTCStamp(/* int */ y, /* int */ m, /* int */ d, /* int */ h, 
+						/* int */ mn, /* int */ s, /* int? */ off){
+		// summary:
+		//		Returns the UTC timestamp, adjusted by the given (optional) offset
+		return Date.UTC(y, m, d, h, mn, s) + ((off||0) * 60 * 1000);
+	}
+	
+	function getMonthNumber(/* String */ m){
+		// summary:
+		//		Returns the javascript month number for the given string
+		return monthMap[m.substr(0, 3).toLowerCase()];
+	}
+	
+	function getOffsetInMins(/* String */ str){
+		// summary:
+		//		Returns the offset value represented by the string, in minutes
+		var off = parseTimeString(str);
+		if(off === null){ return 0; }
+		var adj = str.indexOf('-') === 0 ? -1 : 1;
+		off = adj * (((off[1] * 60 + off[2]) *60 + off[3]) * 1000);
+		return -off/60/1000;
+	}
+
+	function _getRuleStart(/* Rule */ rule, /* int */ year, /* int */ off){
+		// summary:
+		//		Returns a date that the rule begins matching in the given year.
+		var month = getMonthNumber(rule[3]),
+			day = rule[4],
+			time = parseTimeString(rule[5]);
+		if(time[4] == "u"){
+			// We are UTC - so there is no offset to use
+			off = 0;
+		}
+		
+		var d, dtDay, incr;
+		if(isNaN(day)){
+			if(day.substr(0, 4) == "last"){
+				// Last day of the month at the desired time of day
+				day = dayMap[day.substr(4,3).toLowerCase()];
+				d = new Date(getUTCStamp(year, month + 1, 1,
+										time[1] - 24, time[2], time[3], 
+										off));
+				dtDay = _d.date.add(d, "minute", -off).getUTCDay();
+				// Set it to the final day of the correct weekday that month
+				incr = (day > dtDay) ? (day - dtDay - 7) : (day - dtDay);
+				if(incr !== 0){
+					d = _d.date.add(d, "hour", incr * 24);
+				}
+				return d;
+			}else{
+				day = dayMap[day.substr(0, 3).toLowerCase()];
+				if(day != "undefined"){
+					if(rule[4].substr(3, 2) == '>='){
+						// The stated date of the month
+						d = new Date(getUTCStamp(year, month, parseInt(rule[4].substr(5), 10), 
+									time[1], time[2], time[3], off));
+						dtDay = _d.date.add(d, "minute", -off).getUTCDay();
+						// Set to the first correct weekday after the stated date
+						incr = (day < dtDay) ? (day - dtDay + 7) : (day - dtDay);
+						if(incr !== 0){
+							d = _d.date.add(d, "hour", incr * 24);
+						}
+						return d;
+					}else if(day.substr(3, 2) == '<='){
+						// The stated date of the month
+						d = new Date(getUTCStamp(year, month, parseInt(rule[4].substr(5), 10), 
+									time[1], time[2], time[3], off));
+						dtDay = _d.date.add(d, "minute", -off).getUTCDay();
+						// Set to first correct weekday before the stated date
+						incr = (day > dtDay) ? (day - dtDay - 7) : (day - dtDay);
+						if(incr !== 0){
+							d = _d.date.add(d, "hour", incr * 24);
+						}
+						return d;
+					}
+				}
+			}
+		}else{
+			// Numeric date
+			d = new Date(getUTCStamp(year, month, parseInt(day, 10), 
+						time[1], time[2], time[3], off));
+			return d;
+		}
+		return null;
+	}
+
+	function _getRulesForYear(/* Zone */ zone, /* int */ year){
+		var rules = [];
+		_d.forEach(_rules[zone[1]]||[], function(r){
+			// Clean up rules as needed
+			for(var i = 0; i < 2; i++){
+				switch(r[i]){
+					case "min":
+						r[i] = _minYear;
+						break;
+					case "max":
+						r[i] = _maxYear;
+						break;
+					case "only":
+						break;
+					default:
+						r[i] = parseInt(r[i], 10);
+						if(isNaN(r[i])){
+							throw new Error('Invalid year found on rule');
+						}
+						break;
+				}
+			}
+			if(typeof r[6] == "string"){
+				// Change our offset to be an integer
+				r[6] = getOffsetInMins(r[6]);
+			}
+			
+			// Quick-filter to grab all rules that match my year
+			if((r[0] <= year && r[1] >= year) || // Matches my y
+				(r[0] == year && r[1] == "only")){ // Matches my only
+				rules.push({r: r, d: _getRuleStart(r, year, zone[0])});
+			}
+		});
+		return rules;
+	}
+
+
+	function _loadZoneRanges(/* String */ tz, /* Object[] */ zoneList) {
+		// summary:
+		//		Loads the zone ranges for the given timezone
+		
+		var zr = _loadedRanges[tz] = [];
+		for(var i = 0; i < zoneList.length; i++){
+			var z = zoneList[i];
+			var r = zr[i] = [];
+			var prevZone = null;
+			var prevRange = null;
+			var prevRules = [];
+			
+			// Set up our zone offset to not be a string anymore
+			if(typeof z[0] == "string"){
+				z[0] = getOffsetInMins(z[0]);
+			}
+			
+			if(i === 0){
+				// The beginning of zoneinfo time - let's not worry about 
+				// to-the-hour accuracy before Jan 1, 1835
+				r[0] = Date.UTC(_minYear,0,1,0,0,0,0);
+			}else{
+				r[0] = zr[i - 1][1];
+				prevZone = zoneList[i - 1];
+				prevRange = zr[i - 1];
+				prevRules = prevRange[2];
+			}
+
+			// Load the rules that will be going in to our zone
+			var startYear = new Date(r[0]).getUTCFullYear();
+			var endYear = z[3] ? parseInt(z[3], 10) : _maxYear;
+			var rlz = [];
+			var j;
+			for(j = startYear; j <= endYear; j++){
+				rlz = rlz.concat(_getRulesForYear(z, j));
+			}
+			rlz.sort(function(a, b){
+				return _d.date.compare(a.d, b.d);
+			});
+			var rl;
+			for(j = 0, rl; (rl = rlz[j]); j++){
+				var prevRule = j > 0 ? rlz[j - 1] : null;
+				if(rl.r[5].indexOf("u") < 0 && rl.r[5].indexOf("s") < 0){
+					if(j === 0 && i > 0){
+						if(prevRules.length){
+							// We have a previous rule - so use it
+							rl.d = _d.date.add(rl.d, "minute", prevRules[prevRules.length - 1].r[6]);
+						}else if(_d.date.compare(new Date(prevRange[1]), rl.d, "date") === 0){
+							// No previous rules - but our date is the same as the
+							// previous zone ended on - so use that.
+							rl.d = new Date(prevRange[1]);
+						}else{
+							rl.d = _d.date.add(rl.d, "minute", getOffsetInMins(prevZone[1]));
+						}
+					}else if(j > 0){
+						rl.d = _d.date.add(rl.d, "minute", prevRule.r[6]);
+					}
+				}
+			}
+			r[2] = rlz;
+
+			if(!z[3]){
+				// The end of zoneinfo time - we'll cross this bridge when we
+				// get close to Dec 31, 2038
+				r[1] = Date.UTC(_maxYear,11,31,23,59,59,999);
+			}else{
+				var year = parseInt(z[3], 10), 
+					month = getMonthNumber(z[4]||"Jan"), 
+					day = parseInt(z[5]||"1", 10), 
+					time = parseTimeString(z[6]||"0");
+				var utcStmp = r[1] = getUTCStamp(year, month, day, 
+									time[1], time[2], time[3],
+									((time[4] == "u") ? 0 : z[0]));
+				if(isNaN(utcStmp)){
+					utcStmp = r[1] = _getRuleStart([0,0,0,z[4],z[5],z[6]||"0"], 
+											year, ((time[4] == "u") ? 0 : z[0])).getTime();
+				}
+				var matches = _d.filter(rlz, function(rl, idx){
+					var o = idx > 0 ? rlz[idx - 1].r[6] * 60 * 1000 : 0;
+					return (rl.d.getTime() < utcStmp + o);
+				});
+				if(time[4] != "u" && time[4] != "s"){
+					if(matches.length){
+						r[1] += matches[matches.length - 1].r[6] * 60 * 1000;
+					}else{
+						r[1] += getOffsetInMins(z[1]) * 60 * 1000;
+					}
+				}
+			}
+		}
+	}
+	
+	function getZoneInfo(/* String */ dt, /* String */ tz) {
+		// summary:
+		//		Returns the zone entry from the zoneinfo database for the given date
+		//		and timezone
+		var t = tz;
+		var zoneList = _zones[t];
+
+		// Follow links to get to an actual zone
+		while(typeof zoneList == "string"){
+			t = zoneList;
+			zoneList = _zones[t];
+		}
+		if(!zoneList){
+			// Backward-compat file hasn't loaded yet, try looking in there
+			if(!_loadedZones.backward){
+				// This is for backward entries like "America/Fort_Wayne" that
+				// getRegionForTimezone *thinks* it has a region file and zone
+				// for (e.g., America => 'northamerica'), but in reality it's a
+				// legacy zone we need the backward file for
+				var parsed = loadZoneFile("backward", true);
+				return getZoneInfo(dt, tz); //Object
+			}
+			invalidTZError(t);
+		}
+		
+		if(!_loadedRanges[tz]){
+			_loadZoneRanges(tz, zoneList);
+		}
+		var ranges = _loadedRanges[tz];
+		var tm = dt.getTime();
+		for(var i = 0, r; (r = ranges[i]); i++){
+			if(tm >= r[0] && tm < r[1]){
+				return {zone: zoneList[i], range: ranges[i], idx: i};
+			}
+		}
+		throw new Error('No Zone found for "' + tz + '" on ' + dt);
+	}
+	
+	function getRule(/* Date */ dt, /* ZoneInfo */ zoneInfo) {
+ 		// summary:
+		//		Returns the latest-matching rule entry from the zoneinfo
+		//		database for the given date and zone
+		
+		var lastMatch = -1;
+		var rules = zoneInfo.range[2]||[];
+		var tsp = dt.getTime();
+		var zr = zoneInfo.range;
+		for(var i = 0, r; (r = rules[i]); i++){
+			if(tsp >= r.d.getTime()){
+				lastMatch = i;
+			}
+		}
+		if(lastMatch >= 0){
+			return rules[lastMatch].r;
+		}
+		return null;
+	}
+  
+	function getAbbreviation(/* String */ tz, /* Object */ zoneInfo, /* Object */ rule) {
+		// summary:
+		//		Returns the abbreviation for the given zone and rule
+		var res;
+		var zone = zoneInfo.zone;
+		var base = zone[2];
+		if(base.indexOf('%s') > -1){
+			var repl;
+			if(rule){
+				repl = rule[7];
+				if(repl == "-"){ repl = ""; }
+			}else if(zone[1] in abbrExceptions){
+				repl = abbrExceptions[zone[1]];
+			}else{
+				if(zoneInfo.idx > 0){
+					// Check if our previous zone's base is the same as our 
+					// current in "S" (standard) mode.  If so, then use "S"
+					// for our replacement
+					var pz = _zones[tz][zoneInfo.idx - 1];
+					var pb = pz[2];
+					if(pb.indexOf('%s') < 0){
+						if(base.replace('%s', "S") == pb){
+							repl = "S";
+						}else{
+							repl = "";
+						}
+					}else{
+						repl = "";
+					}
+				}else{
+					repl = "";
+				}
+			}
+			res = base.replace('%s', repl);
+		}else if(base.indexOf("/") > -1){
+			var bs = base.split("/");
+			if(rule){
+				res = bs[rule[6] === 0 ? 0 : 1];
+			}else{
+				res = bs[0];
+			}
+		}else{
+			res = base;
+		}
+		return res; // String
+	}
+	
+/*=====
+dojox.date.timezone = function(){
+	// summary:
+	//	mix-in to dojo.date to provide timezones based on
+	//	the Olson timezone data
+	//
+	// description:
+	//	mix-in to dojo.date to provide timezones based on
+	//	the Olson timezone data.
+	//	If you pass "timezone" as a parameter to your format options,
+	//	then you get the date formatted (and offset) for that timezone
+
+//TODOC
 };
-_1.setObject("dojox.date.timezone",{getTzInfo:function(dt,tz){
-if(_b=="lazyLoad"){
-var _4a=_1e(tz);
-if(!_4a){
-throw new Error("Not a valid timezone ID.");
-}else{
-if(!_6[_4a]){
-_16(_4a);
-}
-}
-}
-var _4b=_3c(dt,tz);
-var off=_4b.zone[0];
-var _4c=_40(dt,_4b);
-if(_4c){
-off+=_4c[6];
-}else{
-if(_9[_4b.zone[1]]&&_4b.idx>0){
-off+=_23(_7[tz][_4b.idx-1][1]);
-}else{
-off+=_23(_4b.zone[1]);
-}
-}
-var _4d=_44(tz,_4b,_4c);
-return {tzOffset:off,tzAbbr:_4d};
-},getAllZones:function(){
-var arr=[];
-for(var z in _7){
-arr.push(z);
-}
-arr.sort();
-return arr;
-}});
-if(typeof _c=="string"&&_c){
-_c=[_c];
-}
-if(_1.isArray(_c)){
-_1.forEach(_c,function(f){
-_16(f);
-});
-}
-var _4e=_1.date.locale.format;
-var _4f=_1.date.locale._getZone;
-_1.date.locale.format=function(_50,_51){
-_51=_51||{};
-if(_51.timezone&&!_51._tzInfo){
-_51._tzInfo=dojox.date.timezone.getTzInfo(_50,_51.timezone);
-}
-if(_51._tzInfo){
-var _52=_50.getTimezoneOffset()-_51._tzInfo.tzOffset;
-_50=new Date(_50.getTime()+(_52*60*1000));
-}
-return _4e.call(this,_50,_51);
+
+dojox.date.timezone.getTzInfo = function(dt, tz){
+	// summary:
+	//	Returns the timezone information for the given date and
+	//	timezone string
+	//
+	// dt: Date
+	//	The Date - a "proxyDate"
+	//
+	// tz: String
+	//	String representation of the timezone you want to get info
+	//	for date
 };
-_1.date.locale._getZone=function(_53,_54,_55){
-if(_55._tzInfo){
-if(_54){
-return _55._tzInfo.tzAbbr;
-}else{
-return _55._tzInfo.tzOffset;
-}
-}
-return _4f.call(this,_53,_54,_55);
+
+dojox.date.timezone.getAllZones = function(){
+	// summary:
+	//	Returns an array of zones that have been loaded
 };
+=====*/
+	_d.setObject("dojox.date.timezone", {
+		getTzInfo: function(/* Date */ dt, /* String */ tz){
+			// Lazy-load any zones not yet loaded
+			if(loadingScheme == "lazyLoad"){
+				// Get the correct region for the zone
+				var zoneFile = getRegionForTimezone(tz);
+				if(!zoneFile){
+					throw new Error("Not a valid timezone ID.");
+				}else{
+					if(!_loadedZones[zoneFile]){
+						// Get the file and parse it -- use synchronous XHR
+						loadZoneFile(zoneFile);
+					}
+				}
+			}
+			var zoneInfo = getZoneInfo(dt, tz);
+			var off = zoneInfo.zone[0];
+			// See if the offset needs adjustment
+			var rule = getRule(dt, zoneInfo);
+			if(rule){
+				off += rule[6];
+			}else{
+				if(_rules[zoneInfo.zone[1]] && zoneInfo.idx > 0){
+					off += getOffsetInMins(_zones[tz][zoneInfo.idx - 1][1]);
+				}else{
+					off += getOffsetInMins(zoneInfo.zone[1]);
+				}
+			}
+
+			var abbr = getAbbreviation(tz, zoneInfo, rule);
+			return { tzOffset: off, tzAbbr: abbr }; // Object
+		},
+		getAllZones: function(){
+			var arr = [];
+			for(var z in _zones){ arr.push(z); }
+			arr.sort();
+			return arr; // String[]
+		}
+	});
+	
+	// Now - initialize the stuff that we should have pre-loaded
+	if(typeof defaultZoneFile == "string" && defaultZoneFile){
+		defaultZoneFile = [defaultZoneFile];
+	}
+	if(_d.isArray(defaultZoneFile)){
+		_d.forEach(defaultZoneFile, function(f){
+			loadZoneFile(f);
+		});
+	}
+	
+	// And enhance the default formatting functions
+	// If you pass "timezone" as a parameter to your format options,
+	// then you get the date formatted (and offset) for that timezone
+	var oLocaleFmt = _d.date.locale.format,
+		oGetZone = _d.date.locale._getZone;
+	_d.date.locale.format = function(dateObject, options){
+		options = options||{};
+		if(options.timezone && !options._tzInfo){
+			// Store it in our options so we can use it later
+			options._tzInfo = dojox.date.timezone.getTzInfo(dateObject, options.timezone);
+		}
+		if(options._tzInfo){
+			// Roll our date to display the correct time according to the 
+			// desired offset
+			var offset = dateObject.getTimezoneOffset() - options._tzInfo.tzOffset;
+			dateObject = new Date(dateObject.getTime() + (offset * 60 * 1000));
+		}
+		return oLocaleFmt.call(this, dateObject, options);
+	};
+	_d.date.locale._getZone = function(dateObject, getName, options){
+		if(options._tzInfo){
+			return getName ? options._tzInfo.tzAbbr : options._tzInfo.tzOffset;
+		}
+		return oGetZone.call(this, dateObject, getName, options);
+	};
 })(dojo);
-}
diff --git a/dojox/dnd/BoundingBoxController.js b/dojox/dnd/BoundingBoxController.js
new file mode 100644
index 0000000..e51fc11
--- /dev/null
+++ b/dojox/dnd/BoundingBoxController.js
@@ -0,0 +1,130 @@
+dojo.provide("dojox.dnd.BoundingBoxController");
+
+dojo.declare(
+	"dojox.dnd.BoundingBoxController",
+	null,
+	{
+		// summary: Allows the user draw bounding boxes around nodes on the page.
+		// Publishes to the "/dojox/dnd/bounding" topic to tell the selector to check
+		// to see whether any dnd items fall within the coordinates of the bounding box 
+		
+		// x,y start and end coordinates for the bounding box
+		_startX: null,
+		_startY: null,
+		_endX: null,
+		_endY: null,
+
+		constructor: function(sources, domNode){
+			//	summary:
+			//		Sets mouse handlers for the document to capture when a user
+			//		is trying to draw a bounding box.
+			//	sources: Array:
+			//		an array of dojox.dnd.Selectors which need to be aware of
+			//		the positioning of the bounding box.
+			//	domNode: String|DomNode:
+			//		the DOM node or id which represents the bounding box on the page.
+			this.events = [
+				dojo.connect(dojo.doc, "onmousedown", this, "_onMouseDown"),
+				dojo.connect(dojo.doc, "onmouseup",   this, "_onMouseUp"),
+				// cancel text selection and text dragging
+				//dojo.connect(dojo.doc, "ondragstart",   dojo.stopEvent),
+				//dojo.connect(dojo.doc, "onselectstart", dojo.stopEvent),
+				// when a user is scrolling using a scrollbar, don't draw the bounding box.
+				dojo.connect(dojo.doc, "onscroll", this, "_finishSelecting")
+			];
+			// set up a subscription so the client can easily cancel a user drawing a bounding box.
+			this.subscriptions = [
+				dojo.subscribe("/dojox/bounding/cancel", this, "_finishSelecting")
+			];
+			dojo.forEach(sources, function(item){
+				// listen for "/dojox/dnd/bounding" events eminating from the bounding box.
+				// for each of the dojox.dnd.selectors passed in args.
+				if(item.selectByBBox){
+					this.subscriptions.push(dojo.subscribe("/dojox/dnd/bounding", item, "selectByBBox"));
+				}
+			}, this)
+			this.domNode = dojo.byId(domNode);
+			dojo.style(this.domNode, {
+				position: "absolute",
+				display:  "none"
+			});
+		},
+		
+		destroy: function(){
+			// summary:
+			//		prepares this object to be garbage-collected
+			dojo.forEach(this.events, dojo.disconnect);
+			dojo.forEach(this.subscriptions, dojo.unsubscribe);
+			this.domNode = null;
+		},
+		
+		boundingBoxIsViable: function(){
+			// summary: Override-able by the client as an extra check to ensure that a bounding
+			// box is viable. In some instances, it might not make sense that
+			// a mouse down -> mouse move -> mouse up interaction represents a bounding box.
+			// For example, if a dialog is open the client might want to suppress a bounding
+			// box. This function could be used by the client to ensure that a bounding box is only
+			// drawn on the document when certain conditions are met.
+			return true;
+		},
+		
+		_onMouseDown: function(evt){
+			// summary: Executed when the user mouses down on the document. Resets the
+			// this._startX and this._startY member variables.
+			// evt: Object: the mouse event which caused this callback to fire.
+			if(dojo.mouseButtons.isLeft(evt)){
+				if(this._startX === null){
+					this._startX = evt.clientX;
+					this._startY = evt.clientY;
+				}
+				this.events.push(
+					dojo.connect(dojo.doc, "onmousemove", this, "_onMouseMove")
+				);
+			}
+		},
+		
+		_onMouseMove: function(evt){
+			// summary: Executed when the user moves the mouse over the document. Delegates to
+			// this._drawBoundingBox if the user is trying to draw a bounding box.
+		 	// whether the user was drawing a bounding box and publishes to the
+		 	// "/dojox/dnd/bounding" topic if the user is finished drawing their bounding box.
+			// evt: Object: the mouse event which caused this callback to fire.
+			this._endX = evt.clientX;
+			this._endY = evt.clientY;
+			this._drawBoundingBox();
+		},
+
+		_onMouseUp: function(evt){
+			// summary: Executed when the users mouses up on the document. Checks to see
+		 	// whether the user was drawing a bounding box and publishes to the
+		 	// "/dojox/dnd/bounding" topic if the user is finished drawing their bounding box.
+			// evt: Object: the mouse event which caused this callback to fire.
+			if(this._endX !== null && this.boundingBoxIsViable()){
+				// the user has moused up ... tell the selector to check to see whether
+				// any nodes within the bounding box need to be selected.
+				dojo.publish("/dojox/dnd/bounding", [this._startX, this._startY, this._endX, this._endY]);
+			}
+			this._finishSelecting();
+		},
+		
+		_finishSelecting: function(){
+			// summary: hide the bounding box and reset for the next time around
+			if(this._startX !== null){
+				dojo.disconnect(this.events.pop());
+				dojo.style(this.domNode, "display", "none");
+				this._startX = this._endX = null;
+			}
+		},
+		
+		_drawBoundingBox: function(){
+			// summary: draws the bounding box over the document.
+			dojo.style(this.domNode, {
+				left:     Math.min(this._startX, this._endX) + "px",
+				top:      Math.min(this._startY, this._endY) + "px",
+				width:    Math.abs(this._startX - this._endX) + "px",
+				height:   Math.abs(this._startY - this._endY) + "px",
+				display:  ""
+			});
+		}
+	}
+);
diff --git a/dojox/dnd/README b/dojox/dnd/README
new file mode 100644
index 0000000..3e19a0f
--- /dev/null
+++ b/dojox/dnd/README
@@ -0,0 +1,22 @@
+-------------------------------------------------------------------------------
+dojox.dnd Simple extensions to dojo.dnd.
+-------------------------------------------------------------------------------
+Version 1.0
+Release date: 2/1/2010
+-------------------------------------------------------------------------------
+Project state: beta
+-------------------------------------------------------------------------------
+Credits
+
+Sean O' Shea
+Arech
+Eugene Lazutkin
+-------------------------------------------------------------------------------
+Project description
+
+Extending and augmenting dojo.dnd, a clearing house for future dojo.dnd
+additions.
+-------------------------------------------------------------------------------
+Dependencies
+
+	require Dojo Core
diff --git a/dojox/dnd/Selector.js b/dojox/dnd/Selector.js
new file mode 100644
index 0000000..041c261
--- /dev/null
+++ b/dojox/dnd/Selector.js
@@ -0,0 +1,159 @@
+dojo.provide("dojox.dnd.Selector");
+
+dojo.require("dojo.dnd.Selector");
+
+dojo.declare(
+	"dojox.dnd.Selector",
+	dojo.dnd.Selector,
+	{
+		isSelected: function(node){
+			//	summary:
+			//		checks if node is selected
+			//	node: String|DomNode:
+			//		Node to check (id or DOM Node)
+			var id = dojo.isString(node) ? node : node.id,
+				item = this.getItem(id);
+			return item && this.selected[id];	// Boolean
+		},
+		
+		selectNode: function(node, add){
+			//	summary:
+			//		selects a node
+			//	node: String|DomNode:
+			//		Node to select (id or DOM Node)
+			//	add: Boolean?:
+			//		If true, node is added to selection, otherwise current
+			//		selection is removed, and node will be the only selection.
+			if(!add){
+				this.selectNone();
+			}
+			var id = dojo.isString(node) ? node : node.id,
+				item = this.getItem(id);
+			if(item){
+				this._removeAnchor();
+				this.anchor = dojo.byId(node);
+				this._addItemClass(this.anchor, "Anchor");
+				this.selection[id] = 1;
+				this._addItemClass(this.anchor, "Selected");
+			}
+			return this;	// self
+		},
+		
+		deselectNode: function(node){
+			//	summary:
+			//		deselects a node
+			//	node: String|DomNode:
+			//		Node to deselect (id or DOM Node)
+			var id = dojo.isString(node) ? node : node.id,
+				item = this.getItem(id);
+			if(item && this.selection[id]){
+				if(this.anchor === dojo.byId(node)){
+					this._removeAnchor();
+				}
+				delete this.selection[id];
+				this._removeItemClass(this.anchor, "Selected");
+			}
+			return this;	// self
+		},
+		
+		selectByBBox: function(left, top, right, bottom, add) {
+			//	summary:
+			//		selects nodes by bounding box
+			//	left: Number:
+			//		Left coordinate of the bounding box
+			//	top: Number:
+			//		Top coordinate of the bounding box
+			//	right: Number:
+			//		Right coordinate of the bounding box
+			//	bottom: Number:
+			//		Bottom coordinate of the bounding box
+			//	add: Boolean?:
+			//		If true, node is added to selection, otherwise current
+			//		selection is removed, and node will be the only selection.
+
+			// user has drawn a bounding box ... time to see whether any dom nodes
+			// in this container satisfy the bounding box range.
+			if(!add){
+				this.selectNone();
+			}
+			this.forInItems(function(data, id){
+				var node = dojo.byId(id);
+				if(node && this._isBoundedByBox(node, left, top, right, bottom)){
+					this.selectNode(id, true);
+				}
+			}, this);
+			return this;	// self
+		},
+		
+		_isBoundedByBox: function(node, left, top, right, bottom) {
+			//	summary:
+			//		figures out whether certain coodinates bound a particular
+			//		dom node.
+			//	node: String|DomNode:
+			//		Node to check (id or DOM Node)
+			//	left: Number:
+			//		Left coordinate of the bounding box
+			//	top: Number:
+			//		Top coordinate of the bounding box
+			//	right: Number:
+			//		Right coordinate of the bounding box
+			//	bottom: Number:
+			//		Bottom coordinate of the bounding box
+			var c = dojo.coords(node), t;
+			// normalize input
+			if(left > right){
+				t = left;
+				left = right;
+				right = t;
+			}
+			if(top > bottom){
+				t = top;
+				top = bottom;
+				bottom = t;
+			}
+			return c.x >= left && c.x + c.w <= right && c.y >= top && c.y + c.h <= bottom;	// Boolean
+		},
+		
+		shift: function(toNext, add) {
+			//	summary:
+			//		shifts the currently selected dnd item forwards and backwards.
+			//		One possible use would be to allow a user select different
+			//		dnd items using the right and left keys.
+			//	toNext: Boolean:
+			//		If true, we select the next node, otherwise the previous one.
+			//	add: Boolean?:
+			//		If true, add to selection, otherwise current selection is
+			//		removed before adding any nodes.
+			var selectedNodes = this.getSelectedNodes();
+			if(selectedNodes && selectedNodes.length) {
+				// only delegate to selectNode if at least one node is selected.
+				// If multiple nodes are selected assume that we go with
+				// the last selected node.
+				this.selectNode(this._getNodeId(selectedNodes[selectedNodes.length - 1].id, toNext), add);
+			}
+		},
+
+		_getNodeId: function(nodeId, toNext) {
+			//	summary:
+			//		finds a next/previous node in relation to nodeId
+			//	nodeId: String:
+			//		the id of the node to use as the base node
+			//	toNext: Boolean:
+			//		If true, we select the next node, otherwise the previous one.
+			var allNodes = this.getAllNodes(), newId = nodeId;
+			for(var i = 0, l = allNodes.length; i < l; ++i) {
+				if(allNodes[i].id == nodeId) {
+					// have a match ... make sure we don't go outside
+					var j = Math.min(l - 1, Math.max(0, i + (toNext ? 1 : -1)));
+					if(i != j){
+						// we should be fine to go with the id the user has requested.
+						newId = allNodes[j].id;
+					}
+					break;
+				}
+			}
+			// if we don't get a match, the newId defaults to the currently selected node
+			return newId;
+		}
+	}
+);
diff --git a/dojox/dnd/tests/robot/test_selector.html b/dojox/dnd/tests/robot/test_selector.html
new file mode 100644
index 0000000..7b4fbc6
--- /dev/null
+++ b/dojox/dnd/tests/robot/test_selector.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot dojox DnD Test</title>
+	
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.robotx");
+			
+			dojo.addOnLoad(function() {
+	
+				doh.robot.initRobot('../test_selector.html');
+	
+				doh.register('dojox.robot.DndSelectorTest', [
+					{
+						name: 'dojox dnd shift down test',
+						timeout: 10000,
+						runTest: function() {
+							var d = new doh.Deferred();
+							doh.robot.mouseMoveAt('blonde', 1000);
+							doh.robot.mouseClick({left:true, middle:false, right:false}, 100);
+							doh.robot.mouseClick({left:true, middle:false, right:false}, 100);
+							doh.robot.mouseMoveAt('header', 250);
+							doh.robot.mouseClick({left:true, middle:false, right:false}, 100);
+							doh.robot.typeKeys("d", 100);
+							doh.robot.sequence(function() {
+								dojo.query("> div", dojo.byId('albums')).forEach(function(item, index, array) {
+									if(index == 1) {
+										if(dojo.hasClass(item, "dojoDndItemSelected") && item.id == "highway") {
+											d.callback(true);		
+										} else {
+											d.errback(new Error("Second item in the album list was not selected"));		
+										}
+									} else {
+										doh.assertFalse(dojo.hasClass(item, "dojoDndItemSelected"));
+									}
+								});
+							}, 3000);
+							return d;
+						}
+					},
+					{
+						name: 'dojox dnd shift up test',
+						timeout: 10000,
+						runTest: function() {
+							var d = new doh.Deferred();
+							doh.robot.typeKeys("u", 100);
+							doh.robot.sequence(function() {
+								dojo.query("> div", dojo.byId('albums')).forEach(function(item, index, array) {
+									if(index == 0) {
+										if(dojo.hasClass(item, "dojoDndItemSelected") && item.id == "blonde") {
+											d.callback(true);		
+										} else {
+											d.errback(new Error("First item in the album list was not selected"));		
+										}
+									}
+								});
+							}, 1000);
+							return d;
+						}
+					}
+				]);
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
\ No newline at end of file
diff --git a/dojox/dnd/tests/test_selector.html b/dojox/dnd/tests/test_selector.html
new file mode 100644
index 0000000..6396004
--- /dev/null
+++ b/dojox/dnd/tests/test_selector.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Dojox DnD selector test</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dojo/tests/dnd/dndDefault.css";
+			body { padding: 20px; }
+		</style>
+		<style title="text/css">
+			#boundingBox {
+				background: #999;
+				border: 1px solid #2B2B2B;
+				opacity: 0.5;
+				filter: alpha(opacity = 60); /* for IE */
+				position: absolute;
+				z-index: 19999;
+			}
+			#albums {
+				position: relative;
+				width: 200px;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.dnd.Selector");
+			dojo.require("dojox.dnd.BoundingBoxController");
+			var albums, bb;
+			var init = function() {
+				albums = new dojox.dnd.Selector(dojo.byId("albums"));
+				dojo.connect(dojo.doc, "onkeydown", dojo.hitch(this, function(evt) {
+					// would usually use dojo.keys.UP_ARROW/dojo.keys.DOWN_ARROW
+					// but can't seem to get that working with doh. Instead, I'm using
+					// 'u' as an indicator for up and 'd' as an indicator for down.
+					if(evt.keyCode == dojo.keys.UP_ARROW) {
+						albums.shift(false, evt.shiftKey);
+					}
+					if(evt.keyCode == dojo.keys.DOWN_ARROW) {
+						albums.shift(true, evt.shiftKey);
+					}
+				}));
+				bb = new dojox.dnd.BoundingBoxController([albums], "boundingBox");
+			};
+			dojo.addOnLoad(init);
+		</script>
+	</head>
+	<body>
+		<h1 id="header">Dojox DnD selector test</h1>
+		<p>Use the up/down arrows to iterate through the list after selecting one.</p>
+		<div id="albums" class="container">
+			<div id="blonde"  class="dojoDndItem">Blonde on Blonde</div>
+			<div id="highway" class="dojoDndItem">Highway 61 Revisited</div>
+			<div id="tracks"  class="dojoDndItem">Blood on the Tracks</div>
+		</div>
+		<div id="boundingBox" style="display:none;"></div>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/drawing.js b/dojox/drawing.js
index ff263cf..af74383 100644
--- a/dojox/drawing.js
+++ b/dojox/drawing.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing"]){
-dojo._hasResource["dojox.drawing"]=true;
 dojo.provide("dojox.drawing");
-dojo.require("dojox.drawing._base");
-}
+dojo.require("dojox.drawing._base");
\ No newline at end of file
diff --git a/dojox/drawing/Drawing.js b/dojox/drawing/Drawing.js
old mode 100644
new mode 100755
index 1ac172e..c97da63
--- a/dojox/drawing/Drawing.js
+++ b/dojox/drawing/Drawing.js
@@ -1,231 +1,544 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.Drawing"]){
-dojo._hasResource["dojox.drawing.Drawing"]=true;
 dojo.provide("dojox.drawing.Drawing");
+
 (function(){
-var _1=false;
-dojo.declare("dojox.drawing.Drawing",[],{ready:false,mode:"",width:0,height:0,constructor:function(_2,_3){
-var _4=dojo.attr(_3,"defaults");
-if(_4){
-dojox.drawing.defaults=dojo.getObject(_4);
-}
-this.defaults=dojox.drawing.defaults;
-this.id=_3.id;
-dojox.drawing.register(this,"drawing");
-this.mode=(_2.mode||dojo.attr(_3,"mode")||"").toLowerCase();
-var _5=dojo.contentBox(_3);
-this.width=_5.w;
-this.height=_5.h;
-this.util=dojox.drawing.util.common;
-this.util.register(this);
-this.keys=dojox.drawing.manager.keys;
-this.mouse=new dojox.drawing.manager.Mouse({util:this.util,keys:this.keys,id:this.mode=="ui"?"MUI":"mse"});
-this.mouse.setEventMode(this.mode);
-this.tools={};
-this.stencilTypes={};
-this.stencilTypeMap={};
-this.srcRefNode=_3;
-this.domNode=_3;
-var _6=dojo.attr(_3,"plugins");
-if(_6){
-this.plugins=eval(_6);
-}else{
-this.plugins=[];
-}
-this.widgetId=this.id;
-dojo.attr(this.domNode,"widgetId",this.widgetId);
-if(dijit&&dijit.registry){
-dijit.registry.add(this);
-}else{
-dijit.registry={objs:{},add:function(_7){
-this.objs[_7.id]=_7;
-}};
-dijit.byId=function(id){
-return dijit.registry.objs[id];
-};
-dijit.registry.add(this);
-}
-var _8=dojox.drawing.getRegistered("stencil");
-for(var nm in _8){
-this.registerTool(_8[nm].name);
-}
-var _9=dojox.drawing.getRegistered("tool");
-for(var nm in _9){
-this.registerTool(_9[nm].name);
-}
-var _a=dojox.drawing.getRegistered("plugin");
-for(var nm in _a){
-this.registerTool(_a[nm].name);
-}
-this._createCanvas();
-},_createCanvas:function(){
-this.canvas=new dojox.drawing.manager.Canvas({srcRefNode:this.domNode,util:this.util,mouse:this.mouse,callback:dojo.hitch(this,"onSurfaceReady")});
-this.initPlugins();
-},resize:function(_b){
-dojo.style(this.domNode,{width:_b.w+"px",height:_b.h+"px"});
-if(!this.canvas){
-this._createCanvas();
-}else{
-this.canvas.resize(_b.w,_b.h);
-}
-},startup:function(){
-},getShapeProps:function(_c,_d){
-return dojo.mixin({container:this.mode=="ui"||_d=="ui"?this.canvas.overlay.createGroup():this.canvas.surface.createGroup(),util:this.util,keys:this.keys,mouse:this.mouse,drawing:this,drawingType:this.mode=="ui"||_d=="ui"?"ui":"stencil",style:this.defaults.copy()},_c||{});
-},addPlugin:function(_e){
-this.plugins.push(_e);
-if(this.canvas.surfaceReady){
-this.initPlugins();
-}
-},initPlugins:function(){
-if(!this.canvas||!this.canvas.surfaceReady){
-var c=dojo.connect(this,"onSurfaceReady",this,function(){
-dojo.disconnect(c);
-this.initPlugins();
-});
-return;
-}
-dojo.forEach(this.plugins,function(p,i){
-var _f=dojo.mixin({util:this.util,keys:this.keys,mouse:this.mouse,drawing:this,stencils:this.stencils,anchors:this.anchors,canvas:this.canvas},p.options||{});
-this.registerTool(p.name,dojo.getObject(p.name));
-try{
-this.plugins[i]=new this.tools[p.name](_f);
-}
-catch(e){
-console.error("Failed to initilaize plugin:\t"+p.name+". Did you require it?");
-}
-},this);
-this.plugins=[];
-_1=true;
-this.mouse.setCanvas();
-},onSurfaceReady:function(){
-this.ready=true;
-this.mouse.init(this.canvas.domNode);
-this.undo=new dojox.drawing.manager.Undo({keys:this.keys});
-this.anchors=new dojox.drawing.manager.Anchors({drawing:this,mouse:this.mouse,undo:this.undo,util:this.util});
-if(this.mode=="ui"){
-this.uiStencils=new dojox.drawing.manager.StencilUI({canvas:this.canvas,surface:this.canvas.surface,mouse:this.mouse,keys:this.keys});
-}else{
-this.stencils=new dojox.drawing.manager.Stencil({canvas:this.canvas,surface:this.canvas.surface,mouse:this.mouse,undo:this.undo,keys:this.keys,anchors:this.anchors});
-this.uiStencils=new dojox.drawing.manager.StencilUI({canvas:this.canvas,surface:this.canvas.surface,mouse:this.mouse,keys:this.keys});
-}
-if(dojox.gfx.renderer=="silverlight"){
-try{
-new dojox.drawing.plugins.drawing.Silverlight({util:this.util,mouse:this.mouse,stencils:this.stencils,anchors:this.anchors,canvas:this.canvas});
-}
-catch(e){
-throw new Error("Attempted to install the Silverlight plugin, but it was not found.");
-}
-}
-dojo.forEach(this.plugins,function(p){
-p.onSurfaceReady&&p.onSurfaceReady();
-});
-},addUI:function(_10,_11){
-if(!this.ready){
-var c=dojo.connect(this,"onSurfaceReady",this,function(){
-dojo.disconnect(c);
-this.addUI(_10,_11);
-});
-return false;
-}
-if(_11&&!_11.data&&!_11.points){
-_11={data:_11};
-}
-if(!this.stencilTypes[_10]){
-if(_10!="tooltip"){
-console.warn("Not registered:",_10);
-}
-return null;
-}
-var s=this.uiStencils.register(new this.stencilTypes[_10](this.getShapeProps(_11,"ui")));
-return s;
-},addStencil:function(_12,_13){
-if(!this.ready){
-var c=dojo.connect(this,"onSurfaceReady",this,function(){
-dojo.disconnect(c);
-this.addStencil(_12,_13);
-});
-return false;
-}
-if(_13&&!_13.data&&!_13.points){
-_13={data:_13};
-}
-var s=this.stencils.register(new this.stencilTypes[_12](this.getShapeProps(_13)));
-this.currentStencil&&this.currentStencil.moveToFront();
-return s;
-},removeStencil:function(_14){
-this.stencils.unregister(_14);
-_14.destroy();
-},removeAll:function(){
-this.stencils.removeAll();
-},selectAll:function(){
-this.stencils.selectAll();
-},toSelected:function(_15){
-this.stencils.toSelected.apply(this.stencils,arguments);
-},exporter:function(){
-return this.stencils.exporter();
-},importer:function(_16){
-dojo.forEach(_16,function(m){
-this.addStencil(m.type,m);
-},this);
-},changeDefaults:function(_17){
-for(var nm in _17){
-for(var n in _17[nm]){
-this.defaults[nm][n]=_17[nm][n];
-}
-}
-this.unSetTool();
-this.setTool(this.currentType);
-},onRenderStencil:function(_18){
-this.stencils.register(_18);
-this.unSetTool();
-this.setTool(this.currentType);
-},onDeleteStencil:function(_19){
-this.stencils.unregister(_19);
-},registerTool:function(_1a){
-if(this.tools[_1a]){
-return;
-}
-var _1b=dojo.getObject(_1a);
-this.tools[_1a]=_1b;
-var _1c=this.util.abbr(_1a);
-this.stencilTypes[_1c]=_1b;
-this.stencilTypeMap[_1c]=_1a;
-},getConstructor:function(_1d){
-return this.stencilTypes[_1d];
-},setTool:function(_1e){
-if(this.mode=="ui"){
-return;
-}
-if(!this.canvas||!this.canvas.surface){
-var c=dojo.connect(this,"onSurfaceReady",this,function(){
-dojo.disconnect(c);
-this.setTool(_1e);
-});
-return;
-}
-if(this.currentStencil){
-this.unSetTool();
-}
-this.currentType=this.tools[_1e]?_1e:this.stencilTypeMap[_1e];
-try{
-this.currentStencil=new this.tools[this.currentType]({container:this.canvas.surface.createGroup(),util:this.util,mouse:this.mouse,keys:this.keys});
-this.currentStencil.connect(this.currentStencil,"onRender",this,"onRenderStencil");
-this.currentStencil.connect(this.currentStencil,"destroy",this,"onDeleteStencil");
-}
-catch(e){
-console.error("dojox.drawing.setTool Error:",e);
-console.error(this.currentType+" is not a constructor: ",this.tools[this.currentType]);
-}
-},unSetTool:function(){
-if(!this.currentStencil.created){
-this.currentStencil.destroy();
-}
-}});
-})();
-}
+	
+	var _plugsInitialized = false;
+	
+	dojo.declare("dojox.drawing.Drawing", [], {
+		// summary:
+		//		Drawing is a project that sits on top of DojoX GFX and uses SVG and
+		//		VML vector graphics to draw and display.
+		// description:
+		//		Drawing is similar to DojoX Sketch, but is designed to be more versatile
+		//		extendable and customizable.
+		//		Drawing currently only initiates from HTML although it's technically not
+		//		a Dijit to keep the file size light. But if Dijit is available, Drawing
+		//		will register itself with it and can be accessed dijit.byId('myDrawing')
+		//
+		//	NOTES:
+		//		Although not Drawing and Toolbar, all other objects are created with a custom
+		//		declare. See dojox.drawing.util.oo
+		//
+		//The files are laid out as such:
+		//		- Drawing
+		//			The master class. More than one instance of a Drawing can be placed
+		//			on a page at one time (although this has not yet been tested). Plugins
+		//			can be added in markup.
+		// 	- Toolbar
+		//			Like Drawing, Toolbar is a psudeo Dijit that does not need Dijit. It is
+		//			optional. It can be oriented horizontal or vertical by placing one of
+		//			those params in the class (at least one is required).  Plugins
+		//			can be added in markup. A drawingId is required to point toolbar to 
+		//			the drawing.
+		//		- defaults
+		//			Contains the default styles and dimensions for Stencils. An individual
+		//			Stencil can be changed by calling stencil.att({color obj}); To change
+		//			all styles, a custom defaults file should be used.
+		//		-Stencils
+		//			Drawing uses a concept of 'Stencils' to avoid confusion between a
+		//			Dojox Shape and a Drawing Shape. The classes in the 'stencils' package
+		//			are display only, they are not used for actually drawing (see 'tools').
+		//			This package contains _Base from which stencils inherit most of their
+		//			methods.(Path and Image are display only and not found in Tools)
+		//		- Tools
+		//			The Tools package contains Stencils that are attached to mouse events
+		//			and can be used for drawing. Items in this package can also be selected
+		//			and modified.
+		//		- Tools / Custom
+		//			Holds tools that do not directly extend Stencil base classes and often
+		//			have very custom code.
+		//		- Library (not implemented)
+		//			The Library package, which is not yet implemented, will be the place to
+		//			hold stencils that have very specific data points that result in a picture.
+		//			Flag-like-banners, fancy borders, or other complex shapes would go here.
+		//		- Annotations
+		//			Annotations 'decorate' and attach to other Stencils, such as a 'Label'
+		//			that can show text on a stencil, or an 'Angle' that shows while dragging
+		//			or modifying a Vector, or an Arrow head that is attached to the beginning
+		//			or end of a line.
+		//		- Manager
+		//			Contains classes that control functionality of a Drawing.
+		//		- Plugins
+		//			Contains optional classes that are 'plugged into' a Drawing. There are two
+		//			types: 'drawing' plugins that modify the canvas, and 'tools' which would
+		//			show in the toolbar.
+		//		- Util
+		//			A collection of common tasks.
+		//
+		// example:
+		//		|	<div dojoType="dojox.drawing.Drawing" id="drawing" defaults="myCustom.defaults"
+		//		|		plugins="[{'name':'dojox.drawing.plugins.drawing.Grid', 'options':{gap:100}}]">   
+		//		|   </div>
+		//
+		//	example:
+		//		|	<div dojoType="dojox.drawing.Toolbar" drawingId="drawing" class="drawingToolbar vertical">
+		//		|		<div tool="dojox.drawing.tools.Line" selected="false">Line</div>
+		//		|		<div tool="dojox.drawing.tools.Rect" selected="false">Rect</div>
+		//		|		<div tool="dojox.drawing.tools.Ellipse" selected="false">Ellipse</div>
+		//		|		<div tool="dojox.drawing.tools.TextBlock" selected="false">Statement</div>
+		//		|		<div tool="dojox.drawing.tools.custom.Equation" selected="false">Equation</div>
+		//		|		<div plugin="dojox.drawing.plugins.tools.Pan" options="{}">Pan</div>
+		//		|		<div plugin="dojox.drawing.plugins.tools.Zoom" options="{zoomInc:.1,minZoom:.5,maxZoom:2}">Zoom</div>
+		//		|	</div>
+		//
+		//
+		// ready: Boolean
+		//	Whether or not the canvas has been created and Stencils can be added
+		ready:false,
+		// mode: [optional] String
+		//		Changes the functionality of the drawing
+		mode: "",
+		// width: Number
+		//		Width of the canvas
+		width:0,
+		//
+		// height: Number
+		//		Height of the canvas
+		height:0,
+		//
+		// defaults : Object
+		//		Optional replacements for native defaults.
+		// plugins: Object
+		//		Key values of plugins that apply to canvas.
+		//
+		constructor: function(/* Object */props, /* HTMLNode */node){
+			// summary:
+			//		Drawing is not a Dijit. This is the master method.
+			//		NOTE:
+			// 			props is always null since this is not a real widget
+			//			Will change when Drawing can be created programmatically.
+			//
+			var def = dojo.attr(node, "defaults");
+			if(def){
+				dojox.drawing.defaults =  dojo.getObject(def);
+			}
+			this.defaults =  dojox.drawing.defaults;
+			
+			this.id = node.id;
+			dojox.drawing.register(this, "drawing");
+			this.mode = (props.mode || dojo.attr(node, "mode") || "").toLowerCase();
+			var box = dojo.contentBox(node);
+			this.width = box.w;
+			this.height = box.h;
+			this.util = dojox.drawing.util.common;
+			this.util.register(this); // So Toolbar can find this Drawing DEPRECATED
+			this.keys = dojox.drawing.manager.keys;
+			this.mouse = new dojox.drawing.manager.Mouse({util:this.util, keys:this.keys, id:this.mode=="ui"?"MUI":"mse"});
+			this.mouse.setEventMode(this.mode);
+			
+			this.tools = {};
+			this.stencilTypes = {};
+			this.stencilTypeMap = {};
+			this.srcRefNode = node; // need this?
+			this.domNode = node;
+			var str = dojo.attr(node, "plugins"); // FIXME: get this from props if available
+			if(str){
+				this.plugins = eval(str);
+			}else{
+				this.plugins = [];
+			}
+			
+			this.widgetId = this.id;
+			dojo.attr(this.domNode, "widgetId", this.widgetId);
+			// If Dijit is available in the page, register with it
+			if(dijit && dijit.registry){
+				dijit.registry.add(this);
+				console.log("using dijit")
+			}else{
+				// else fake dijit.byId
+				// FIXME: This seems pretty hacky.
+				// Maybe should just encourage jsId
+				dijit.registry = {
+					objs:{},
+					add:function(obj){
+						this.objs[obj.id] = obj;
+					}
+				};
+				dijit.byId = function(id){
+					return dijit.registry.objs[id];
+				};
+				dijit.registry.add(this);
+			}
+			
+			var stencils = dojox.drawing.getRegistered("stencil");
+			for(var nm in stencils){
+				this.registerTool(stencils[nm].name);
+			}
+			var tools = dojox.drawing.getRegistered("tool");
+			for(nm in tools){
+				this.registerTool(tools[nm].name);
+			}
+			var plugs = dojox.drawing.getRegistered("plugin");
+			for(nm in plugs){
+				this.registerTool(plugs[nm].name);
+			}
+			this._createCanvas();
+			
+		},
+		
+		_createCanvas: function(){
+			console.info("drawing create canvas...");
+			this.canvas = new dojox.drawing.manager.Canvas({
+				srcRefNode:this.domNode,
+				util:this.util,
+				mouse:this.mouse,
+				callback: dojo.hitch(this, "onSurfaceReady")
+			});
+			this.initPlugins();
+		},
+		
+		resize: function(/* Object */box){
+			// summary:
+			//		Resizes the canvas.
+			//		If within a ContentPane this will get called automatically.
+			//		Can also be called directly.
+			//
+			box && dojo.style(this.domNode, {
+				width:box.w+"px",
+				height:box.h+"px"
+			});
+			if(!this.canvas){
+				this._createCanvas();		
+			}else if(box){
+				this.canvas.resize(box.w, box.h);
+			}
+		},
+		
+		startup: function(){
+			//console.info("drawing startup")
+		},
+		
+		getShapeProps: function(/* Object */data, mode){
+			// summary:
+			// 		The common objects that are mixed into
+			//		a new Stencil. Mostly internal, but could be used.
+			//
+			var surface = data.stencilType;
+			var ui = this.mode=="ui" || mode=="ui"; 
+			return dojo.mixin({
+				container: ui && !surface ? this.canvas.overlay.createGroup() : this.canvas.surface.createGroup(),
+				util:this.util,
+				keys:this.keys,
+				mouse:this.mouse,
+				drawing:this,
+				drawingType: ui && !surface ? "ui" : "stencil",
+				style:this.defaults.copy()
+			}, data || {});
+		},
+		
+		addPlugin: function(/* Object */plugin){
+			// summary:
+			//		Add a toolbar plugin object to plugins array
+			//		to be parsed
+			this.plugins.push(plugin);
+			if(this.canvas.surfaceReady){
+				this.initPlugins();		
+			}
+		},
+		
+		initPlugins: function(){
+			// summary:
+			// 		Called from Toolbar after a plugin has been loaded
+			// 		The call to this coming from toobar is a bit funky as the timing
+			//		of IE for canvas load is different than other browsers
+			if(!this.canvas || !this.canvas.surfaceReady){
+				var c = dojo.connect(this, "onSurfaceReady", this, function(){
+					dojo.disconnect(c);
+					this.initPlugins();
+				});
+				return;
+			}
+			
+			dojo.forEach(this.plugins, function(p, i){
+				var props = dojo.mixin({
+					util:this.util,
+					keys:this.keys,
+					mouse:this.mouse,
+					drawing:this,
+					stencils:this.stencils,
+					anchors:this.anchors,
+					canvas:this.canvas
+				}, p.options || {});
+				//console.log('drawing.plugin:::', p.name, props)
+				this.registerTool(p.name, dojo.getObject(p.name));
+				try{
+					this.plugins[i] = new this.tools[p.name](props);
+				}catch(e){
+					console.error("Failed to initilaize plugin:	" +p.name + ". Did you require it?");
+				}
+			}, this);
+			this.plugins = [];
+			_plugsInitialized = true;
+			// In IE, because the timing is different we have to get the
+			// canvas position after everything has drawn. *sigh*
+			this.mouse.setCanvas();
+		},
+		
+		onSurfaceReady: function(){
+			// summary:
+			//		Event that to which can be connected.
+			//		Fired when the canvas is ready and can be drawn to.
+			//
+			this.ready = true;
+			//console.info("Surface ready")
+			this.mouse.init(this.canvas.domNode);
+			this.undo = new dojox.drawing.manager.Undo({keys:this.keys});
+			this.anchors = new dojox.drawing.manager.Anchors({drawing:this, mouse:this.mouse, undo:this.undo, util:this.util});
+			if(this.mode == "ui"){
+				this.uiStencils = new dojox.drawing.manager.StencilUI({canvas:this.canvas, surface:this.canvas.surface, mouse:this.mouse, keys:this.keys});
+			}else{
+				this.stencils = new dojox.drawing.manager.Stencil({canvas:this.canvas, surface:this.canvas.surface, mouse:this.mouse, undo:this.undo, keys:this.keys, anchors:this.anchors});
+				this.uiStencils = new dojox.drawing.manager.StencilUI({canvas:this.canvas, surface:this.canvas.surface, mouse:this.mouse, keys:this.keys});
+			}
+			if(dojox.gfx.renderer=="silverlight"){
+				try{
+				new dojox.drawing.plugins.drawing.Silverlight({util:this.util, mouse:this.mouse, stencils:this.stencils, anchors:this.anchors, canvas:this.canvas});
+				}catch(e){
+					throw new Error("Attempted to install the Silverlight plugin, but it was not found.");
+				}
+			}
+			dojo.forEach(this.plugins, function(p){
+				p.onSurfaceReady && p.onSurfaceReady();	
+			});
+		
+		},
+		
+		addUI: function(/* String */type, /* Object */options){
+			// summary:
+			//		Use this method to programmatically add Stencils that display on
+			//		the canvas.
+			//		FIXME: Currently only supports Stencils that have been registered,
+			//			which is items in the toolbar, and the additional Stencils at the
+			//			end of onSurfaceReady. This covers all Stencils, but you can't
+			//			use 'display only' Stencils for Line, Rect, and Ellipse.
+			//		arguments:
+			//			type: String
+			//				The final name of the tool, lower case: 'image', 'line', 'textBlock'
+			//		options:
+			//			type: Object
+			//				The parameters used to draw the object. See stencil._Base and each
+			//				tool for specific parameters of teh data or points objects.
+			//
+			if(!this.ready){
+				var c = dojo.connect(this, "onSurfaceReady", this, function(){
+					dojo.disconnect(c);
+					this.addUI(type, options);
+				});
+				return false;
+			}
+			if(options && !options.data && !options.points){
+				options = {data:options}
+			}
+			if(!this.stencilTypes[type]){
+				if(type != "tooltip"){
+					console.warn("Not registered:", type);
+				}
+				return null;
+			}
+			var s = this.uiStencils.register( new this.stencilTypes[type](this.getShapeProps(options, "ui")));
+			return s;
+		},
+		
+		
+		addStencil: function(/* String */type, /* Object */options){
+			// summary:
+			//		Use this method to programmatically add Stencils that display on
+			//		the canvas.
+			//		FIXME: Currently only supports Stencils that have been registered,
+			//			which is items in the toolbar, and the additional Stencils at the
+			//			end of onSurfaceReady. This covers all Stencils, but you can't
+			//			use 'display only' Stencils for Line, Rect, and Ellipse.
+			//		arguments:
+			//			type: String
+			//				The final name of the tool, lower case: 'image', 'line', 'textBlock'
+			//		options:
+			//			type: Object
+			//				The parameters used to draw the object. See stencil._Base and each
+			//				tool for specific parameters of teh data or points objects.
+			//
+			if(!this.ready){
+				var c = dojo.connect(this, "onSurfaceReady", this, function(){
+					dojo.disconnect(c);
+					this.addStencil(type, options);
+				});
+				return false;
+			}
+			if(options && !options.data && !options.points){
+				options = {data:options}
+			}
+			var s = this.stencils.register( new this.stencilTypes[type](this.getShapeProps(options)));
+			// need this or not?
+			//s.connect(s, "destroy", this, "onDeleteStencil");
+			this.currentStencil && this.currentStencil.moveToFront();
+			return s;
+		},
+		
+		removeStencil: function(/* Object */stencil){
+			// summary:
+			//		Use this method to programmatically remove Stencils from the canvas.
+			// 	arguments:
+			//		Stencil: Object
+			//			The Stencil to be removed
+			//
+			this.stencils.unregister(stencil);
+			stencil.destroy();
+		},
+		
+		removeAll: function(){
+			// summary:
+			//		Deletes all Stencils on the canvas.
+			this.stencils.removeAll();
+		},
+		
+		selectAll: function(){
+			// summary:
+			//		Selects all stencils
+			this.stencils.selectAll();
+		},
+		
+		toSelected: function(/*String*/func /*[args, ...]*/){
+			// summary:
+			//		Call a function within all selected Stencils
+			//		like attr()
+			// example:
+			//		|	myDrawing.toSelected('attr', {x:10})
+			//
+			this.stencils.toSelected.apply(this.stencils, arguments);
+		},
+		
+		exporter: function(){
+			// summary:
+			//		Collects all Stencil data and returns an
+			//		Array of objects.
+			console.log("this.stencils", this.stencils);
+			return this.stencils.exporter();  //Array
+		},
+		
+		importer: function(/* Array */objects){
+			// summary:
+			//		Handles an Array of stencil data and imports the objects
+			//		to the drawing.
+			dojo.forEach(objects, function(m){
+				this.addStencil(m.type, m);
+			}, this);	
+		},
+		
+		changeDefaults: function(/*Object*/newStyle){
+			// summary:
+			//		Change the defaults so that all Stencils from this
+			// 		point on will use the newly changed style.
+			// arguments:
+			//		newStyle: Object
+			//			An object that represents one of the objects in
+			//			drawing.style that will be mixed in. Not all
+			//			properties are necessary. Only one object may
+			//			be changed at a time. Non-objects like angleSnap
+			//			cannot be changed in this manner.
+			// example:
+			//		|	myDrawing.changeDefaults({
+			//		|		norm:{
+			//		|			fill:"#0000ff",
+			//		|			width:5,
+			//		|			color:"#ffff00"
+			//		|		}
+			//		|	});
+			//
+			for(var nm in newStyle){
+				for(var n in newStyle[nm]){
+					console.log("  copy", nm, n, " to: ", newStyle[nm][n]);
+					this.defaults[nm][n] = newStyle[nm][n];
+				}
+			}
+			this.unSetTool();
+			this.setTool(this.currentType);
+		},
+		
+		onRenderStencil: function(/* Object */stencil){
+			// summary:
+			//		Event that fires when a stencil is drawn. Does not fire from
+			//		'addStencil'.
+			//
+			//console.info("--------------------------------------dojox.drawing.onRenderStencil:", stencil.id);
+			
+			this.stencils.register(stencil);
+			this.unSetTool();
+			if(!this.defaults.clickMode){ 
+				this.setTool(this.currentType);
+			}else{
+				if(this.defaults.clickMode){ this.defaults.clickable = true; }
+			}
+		},
+		
+		onDeleteStencil: function(/* Object */stencil){
+			// summary:
+			//		Event fired from a stencil that has destroyed itself
+			//	 	will also be called when it is removed by "removeStencil"
+			//	 	or stencils.onDelete. 
+			//
+			this.stencils.unregister(stencil);
+		},
+		
+		registerTool: function(/* String */type){
+			// summary:
+			//		 Registers a tool that can be accessed. Internal.
+			if(this.tools[type]){ return; }
+			var constr = dojo.getObject(type);
+			//console.log("constr:", type)
+			this.tools[type] = constr;
+			var abbr = this.util.abbr(type);
+			this.stencilTypes[abbr] = constr;
+			this.stencilTypeMap[abbr] = type;
+		},
+		
+		getConstructor: function(/*String*/abbr){
+			// summary:
+			//		Returns a Stencil constructor base on
+			//		abbreviation
+			return this.stencilTypes[abbr];
+		},
+		
+		setTool: function(/* String */type){
+			// summary:
+			//		Sets up a new class to be used to draw. Called from Toolbar,
+			//		and this class... after a tool is used a new one of the same
+			//		type is initialized. Could be called externally.
+			//
+			if(this.mode=="ui"){ return; }
+			if(!this.canvas || !this.canvas.surface){
+				var c = dojo.connect(this, "onSurfaceReady", this, function(){
+					dojo.disconnect(c);
+					this.setTool(type);
+				});
+				return;
+			}
+			if(this.currentStencil){
+				this.unSetTool();
+			}
+			
+			this.currentType = this.tools[type] ? type : this.stencilTypeMap[type];
+			//console.log("new tool arg:", type, "curr:", this.currentType, "mode:", this.mode, "tools:", this.tools)
+			
+			try{
+				this.currentStencil = new this.tools[this.currentType]({container:this.canvas.surface.createGroup(), util:this.util, mouse:this.mouse, keys:this.keys});
+				console.log("new tool is:", this.currentStencil.id, this.currentStencil);
+				if(this.defaults.clickMode){ this.defaults.clickable = false; }
+				this.currentStencil.connect(this.currentStencil, "onRender", this, "onRenderStencil");
+				this.currentStencil.connect(this.currentStencil, "destroy", this, "onDeleteStencil");
+			}catch(e){
+				console.error("dojox.drawing.setTool Error:", e);
+				console.error(this.currentType + " is not a constructor: ", this.tools[this.currentType]);
+				//console.trace();
+			}
+		},
+		
+		unSetTool: function(){
+			// summary:
+			//		Destroys current tool
+			if(!this.currentStencil.created){
+				this.currentStencil.destroy();	
+			}
+			
+		}
+	});
+	
+})();
\ No newline at end of file
diff --git a/dojox/drawing/_base.js b/dojox/drawing/_base.js
index eadb557..10a1263 100644
--- a/dojox/drawing/_base.js
+++ b/dojox/drawing/_base.js
@@ -1,14 +1,6 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing._base"]){
-dojo._hasResource["dojox.drawing._base"]=true;
 dojo.provide("dojox.drawing._base");
 dojo.experimental("dojox.drawing");
+
 dojo.require("dojox.drawing.manager._registry");
 dojo.require("dojox.gfx");
 dojo.require("dojox.drawing.Drawing");
@@ -16,12 +8,16 @@ dojo.require("dojox.drawing.util.oo");
 dojo.require("dojox.drawing.util.common");
 dojo.require("dojox.drawing.defaults");
 dojo.require("dojox.drawing.manager.Canvas");
+
+// interactive managers
 dojo.require("dojox.drawing.manager.Undo");
 dojo.require("dojox.drawing.manager.keys");
 dojo.require("dojox.drawing.manager.Mouse");
 dojo.require("dojox.drawing.manager.Stencil");
-dojo.require("dojox.drawing.manager.StencilUI");
+dojo.require("dojox.drawing.manager.StencilUI"); // plugin? or as a require? good here? in toolbar?
 dojo.require("dojox.drawing.manager.Anchors");
+
+// standard stencils
 dojo.require("dojox.drawing.stencil._Base");
 dojo.require("dojox.drawing.stencil.Line");
 dojo.require("dojox.drawing.stencil.Rect");
@@ -29,8 +25,11 @@ dojo.require("dojox.drawing.stencil.Ellipse");
 dojo.require("dojox.drawing.stencil.Path");
 dojo.require("dojox.drawing.stencil.Text");
 dojo.require("dojox.drawing.stencil.Image");
+
+// annotations are built within stencil/_Base.js
+// would like to optionally include them, but for
+// now it's mandatory.
 dojo.require("dojox.drawing.annotations.Label");
 dojo.require("dojox.drawing.annotations.Angle");
 dojo.require("dojox.drawing.annotations.Arrow");
-dojo.require("dojox.drawing.annotations.BoxShadow");
-}
+dojo.require("dojox.drawing.annotations.BoxShadow");
\ No newline at end of file
diff --git a/dojox/drawing/annotations/Angle.js b/dojox/drawing/annotations/Angle.js
old mode 100644
new mode 100755
index d0ddb56..7e89231
--- a/dojox/drawing/annotations/Angle.js
+++ b/dojox/drawing/annotations/Angle.js
@@ -1,52 +1,104 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.annotations.Angle");
 
+dojox.drawing.annotations.Angle = dojox.drawing.util.oo.declare(
+	// summary:
+	//	When initiated, an HTML box will hover near the Stencil,
+	//	displaying it's angle while drawn or modified. Currently
+	//	only works with Vector, Line, Arrow, and Axes.
+	// description:
+	//	Annotation is positioned with dojox.drawing.util.positioning.angle
+	//	That method should be overwritten for custom placement.
+	//	Called internally. To initiaize:
+	//	TODO: currently always on
+	//
+	function(/*Object*/options){
+		// arguments:
+		//	options: Object
+		//		One key value: the stencil that called this.
+		//
+		this.stencil = options.stencil;
+		this.util = options.stencil.util;
+		this.mouse = options.stencil.mouse;
 
-if(!dojo._hasResource["dojox.drawing.annotations.Angle"]){
-dojo._hasResource["dojox.drawing.annotations.Angle"]=true;
-dojo.provide("dojox.drawing.annotations.Angle");
-dojox.drawing.annotations.Angle=dojox.drawing.util.oo.declare(function(_1){
-this.stencil=_1.stencil;
-this.util=_1.stencil.util;
-this.mouse=_1.stencil.mouse;
-this.stencil.connectMult([["onDrag",this,"showAngle"],["onUp",this,"hideAngle"],["onTransformBegin",this,"showAngle"],["onTransform",this,"showAngle"],["onTransformEnd",this,"hideAngle"]]);
-},{type:"dojox.drawing.tools.custom",angle:0,showAngle:function(){
-if(!this.stencil.selected&&this.stencil.created){
-return;
-}
-if(this.stencil.getRadius()<this.stencil.minimumSize){
-this.hideAngle();
-return;
-}
-var _2=this.getAngleNode();
-var d=this.stencil.pointsToData();
-var pt=dojox.drawing.util.positioning.angle({x:d.x1,y:d.y1},{x:d.x2,y:d.y2});
-var sc=this.mouse.scrollOffset();
-var mx=this.stencil.getTransform();
-var dx=mx.dx/this.mouse.zoom;
-var dy=mx.dy/this.mouse.zoom;
-pt.x/=this.mouse.zoom;
-pt.y/=this.mouse.zoom;
-var x=this.stencil._offX+pt.x-sc.left+dx;
-var y=this.stencil._offY+pt.y-sc.top+dy;
-dojo.style(_2,{left:x+"px",top:y+"px",align:pt.align});
-_2.innerHTML=Math.ceil(this.stencil.getAngle());
-},getAngleNode:function(){
-if(!this._angleNode){
-this._angleNode=dojo.create("span",null,dojo.body());
-dojo.addClass(this._angleNode,"textAnnotation");
-dojo.style(this._angleNode,"opacity",1);
-}
-return this._angleNode;
-},hideAngle:function(){
-if(this._angleNode&&dojo.style(this._angleNode,"opacity")>0.9){
-dojo.fadeOut({node:this._angleNode,duration:500,onEnd:function(_3){
-dojo.destroy(_3);
-}}).play();
-this._angleNode=null;
-}
-}});
-}
+		this.stencil.connectMult([
+			["onDrag", this, "showAngle"],
+			["onUp", this, "hideAngle"],
+			["onTransformBegin", this, "showAngle"],
+			["onTransform", this, "showAngle"],
+			["onTransformEnd", this, "hideAngle"]
+		]);
+	},
+	{
+		type:"dojox.drawing.tools.custom",
+		angle:0,
+
+		showAngle: function(){
+			//	summary:
+			//		Called to display angle
+			//
+			if(!this.stencil.selected && this.stencil.created){ return; }
+			if(this.stencil.getRadius() < this.stencil.minimumSize){
+				this.hideAngle();
+				return;
+			}
+			var node = this.getAngleNode();
+			var d = this.stencil.pointsToData();
+			var pt = dojox.drawing.util.positioning.angle({x:d.x1,y:d.y1},{x:d.x2,y:d.y2});
+			var sc = this.mouse.scrollOffset();
+			var mx = this.stencil.getTransform();
+			var dx = mx.dx / this.mouse.zoom;
+			var dy = mx.dy / this.mouse.zoom;
+			pt.x /= this.mouse.zoom;
+			pt.y /= this.mouse.zoom;
+
+			// adding _offX & _offY since this is HTML
+			// and we are from the page corner, not
+			// the canvas corner
+			var x = this.stencil._offX + pt.x - sc.left + dx;
+			var y = this.stencil._offY + pt.y - sc.top + dy;
+			dojo.style(node, {
+				left:  	x + "px",
+				top: 	y + "px",
+				align:pt.align
+			});
+
+			var angle=this.stencil.getAngle();
+			if(this.stencil.style.zAxis && this.stencil.shortType=="vector"){
+			  node.innerHTML = this.stencil.data.cosphi > 0 ? "out of" : "into";
+			}else if(this.stencil.shortType=="line"){
+			  node.innerHTML = this.stencil.style.zAxis?"out of":Math.ceil(angle%180);
+			}else{
+			  node.innerHTML = Math.ceil(angle);
+			}
+		},
+
+		getAngleNode: function(){
+			//	summary:
+			//		Gets or creates HTMLNode used for display
+			if(!this._angleNode){
+				this._angleNode = dojo.create("span", null, dojo.body());
+				dojo.addClass(this._angleNode, "textAnnotation");
+				dojo.style(this._angleNode, "opacity", 1);
+			}
+			return this._angleNode; //HTMLNode
+		},
+
+		hideAngle: function(){
+			//	summary:
+			//		Turns display off.
+			//
+			if(this._angleNode && dojo.style(this._angleNode, "opacity")>0.9){
+
+				dojo.fadeOut({node:this._angleNode,
+					duration:500,
+					onEnd: function(node){
+						dojo.destroy(node);
+					}
+				}).play();
+				this._angleNode = null;
+			}
+
+		}
+	}
+
+)
\ No newline at end of file
diff --git a/dojox/drawing/annotations/Arrow.js b/dojox/drawing/annotations/Arrow.js
old mode 100644
new mode 100755
index 45f9a3a..5350caf
--- a/dojox/drawing/annotations/Arrow.js
+++ b/dojox/drawing/annotations/Arrow.js
@@ -1,36 +1,71 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.annotations.Arrow"]){
-dojo._hasResource["dojox.drawing.annotations.Arrow"]=true;
 dojo.provide("dojox.drawing.annotations.Arrow");
 dojo.require("dojox.drawing.stencil.Path");
-dojox.drawing.annotations.Arrow=dojox.drawing.util.oo.declare(dojox.drawing.stencil.Path,function(_1){
-this.stencil.connectMult([[this.stencil,"select",this,"select"],[this.stencil,"deselect",this,"deselect"],[this.stencil,"render",this,"render"],[this.stencil,"onDelete",this,"destroy"]]);
-this.connect("onBeforeRender",this,function(){
-var o=this.stencil.points[this.idx1];
-var c=this.stencil.points[this.idx2];
-if(this.stencil.getRadius()>=this.minimumSize){
-this.points=this.arrowHead(c.x,c.y,o.x,o.y,this.style);
-}else{
-this.points=[];
-}
-});
-},{idx1:0,idx2:1,subShape:true,minimumSize:30,arrowHead:function(x1,y1,x2,y2,_2){
-var _3={start:{x:x1,y:y1},x:x2,y:y2};
-var _4=this.util.angle(_3);
-var _5=this.util.length(_3);
-var al=_2.arrows.length;
-var aw=_2.arrows.width/2;
-if(_5<al){
-al=_5/2;
-}
-var p1=this.util.pointOnCircle(x2,y2,-al,_4-aw);
-var p2=this.util.pointOnCircle(x2,y2,-al,_4+aw);
-return [{x:x2,y:y2},p1,p2];
-}});
-}
+
+dojox.drawing.annotations.Arrow = dojox.drawing.util.oo.declare(
+	// summary:
+	//	An annotation called internally to put an arrowhead
+	//	on ether end of a Line. Initiated in Arrow (and Vector)
+	//	with the optional params: arrowStart and arrowEnd. Both
+	//	default true for Axes.
+	//
+	dojox.drawing.stencil.Path,
+	function(/* dojox.__stencilArgs */options){
+		// arguments: See stencil._Base
+		this.stencil.connectMult([
+			[this.stencil, "select", this, "select"],
+			[this.stencil, "deselect", this, "deselect"],
+			[this.stencil, "render", this, "render"],
+			[this.stencil, "onDelete", this, "destroy"]
+		]);
+		
+		this.connect("onBeforeRender", this, function(){
+			var o = this.stencil.points[this.idx1];
+			var c = this.stencil.points[this.idx2];
+			if(this.stencil.getRadius() >= this.minimumSize){
+				this.points = this.arrowHead(c.x, c.y, o.x, o.y, this.style);
+			}else{
+				this.points = [];
+			}
+		});
+		
+	},
+	{
+		idx1:0,
+		idx2:1,
+		
+		subShape:true,
+		minimumSize:30,
+		//annotation:true, NOT!
+		
+		arrowHead: function(x1, y1, x2, y2, style){
+			// summary:
+			//	Creates data used to draw arrow head.
+			//
+			var obj = {
+				start:{
+					x:x1,
+					y:y1
+				},
+				x:x2,
+				y:y2
+			}
+			var angle = this.util.angle(obj);
+			
+			var lineLength = this.util.length(obj); 
+			var al = style.arrows.length;
+			var aw = style.arrows.width/2;
+			if(lineLength<al){
+				al = lineLength/2;
+			}
+			var p1 = this.util.pointOnCircle(x2, y2, -al, angle-aw);
+			var p2 = this.util.pointOnCircle(x2, y2, -al, angle+aw);
+			
+			return [
+				{x:x2, y:y2},
+				p1,
+				p2
+			];
+		}
+		
+	}
+);
\ No newline at end of file
diff --git a/dojox/drawing/annotations/BoxShadow.js b/dojox/drawing/annotations/BoxShadow.js
index e9efc21..2201cc1 100644
--- a/dojox/drawing/annotations/BoxShadow.js
+++ b/dojox/drawing/annotations/BoxShadow.js
@@ -1,122 +1,307 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.annotations.BoxShadow");
 
+dojox.drawing.annotations.BoxShadow = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Creates a box shadow under solid objects. Can change the
+	//		shadow direction, color, size, and intensity. Can center
+	//		the shadow and make it a Glow.
+	// description:
+	//		This is a psuedo shadow, created by duplicating the
+	//		original stencil and increasing the line weight while
+	//		reducing the opacity. Therefore it will not work with
+	//		text. Also won't look very good if the Stencil has no
+	//		fill or is transparent. Can't do knockouts or inner
+	//		shadows. Currently can't do paths - while doable, it
+	//		will most likely choke IE into certain death.
+	//
+	function(/*Object*/options){
+		this.stencil = options.stencil;
+		this.util = options.stencil.util;
+		this.mouse = options.stencil.mouse;
+		this.style = options.stencil.style;
+		
+		var shadowDefaults = {
+			// summary:
+			//		When passing a shadow object into a stencil, that shadow
+			//		object will be mixed in with these defaults.
+			//
+			// size: Number, mult: Number
+			//		These two props work together. Both affect the size and quality
+			//		of the shadow. size affects the actual size and mult affects the
+			//		lineWidths that overlap to make the shadow. Generally you want a
+			//		bigger 'size' than 'mult'. The defaults are good for a shadow, but
+			//		you will want to increase them when making a glow.
+			//	TODO: Make this more clear or use other properties.
+			size:6,
+			mult:4,
+			// alpha: Float
+			//		Affects the alpha of the shadow. Because this is multiple shapes
+			//		overlapped, you want much less than you may think. .1 is pretty
+			//		dark and . is black. Higher numbers also give a sharper edge.
+			alpha:.05,
+			//	place: String
+			//		Tells the position of the shadow:
+			//			B: bottom
+			//			T: top
+			//			L: left
+			//			R: right
+			//			C: center, or a glow
+			//		Can be used in combinations such as BR, BL, L, T, etc. 'C' should
+			//		be used by itself.
+			place:"BR",
+			//	color: String
+			//		The color of the shadow or glow.
+			color:"#646464"
+		}
+		
+		delete options.stencil;
+		this.options = dojo.mixin(shadowDefaults, options);
+		this.options.color = new dojo.Color(this.options.color)
+		this.options.color.a = this.options.alpha;
+		switch(this.stencil.shortType){
+			case "image":
+			case "rect":
+				this.method = "createForRect"; break;
+			case "ellipse":
+				this.method = "createForEllipse"; break;
+			case "line":
+				this.method = "createForLine"; break;
+			case "path":
+				this.method = "createForPath"; break;
+				// 	path is a bit of a hassle. Plus I think in IE it would be
+				//slower than the political process. Maybe TODO.
+			case "vector":
+				this.method = "createForZArrow"; break;
+			default:
+				console.warn("A shadow cannot be made for Stencil type ", this.stencil.type);
+		}
+		
+		if(this.method){
+			this.render();
+			this.stencil.connectMult([
+				[this.stencil, "onTransform", this, "onTransform"],
+				this.method=="createForZArrow"?[this.stencil, "render", this, "render"]:[this.stencil, "render", this, "onRender"],
+				[this.stencil, "onDelete", this, "destroy"]
+			]);
+		}
+	},
+	{
+		showing:true,
+		render: function(){
+			if(this.container){
+				this.container.removeShape();
+			}
+			this.container = this.stencil.container.createGroup();
+			this.container.moveToBack();
+			
+			var o = this.options,
+				size = o.size,
+				mult = o.mult,
+				d = this.method == "createForPath"
+					? this.stencil.points
+					: this.stencil.data,
+				r = d.r || 1,
+				p = o.place,
+				c = o.color;
+				
+			this[this.method](o, size, mult, d, r, p, c);	
+		},
+		
+		hide: function(){
+			if(this.showing){
+				this.showing = false;
+				this.container.removeShape();
+			}
+		},
+		
+		show: function(){
+			if(!this.showing){
+				this.showing = true;
+				this.stencil.container.add(this.container);
+			}
+		},
+		
+		createForPath: function(o, size, mult, pts, r, p, c){
+			var sh = size * mult / 4,
+				shy = /B/.test(p) ? sh : /T/.test(p) ? sh*-1 : 0,
+				shx = /R/.test(p) ? sh : /L/.test(p) ? sh*-1 : 0;
+			
+			var closePath = true;
+			
+			for(var i=1;i<=size;i++){
+				var lineWidth = i * mult;
+				//var rect = this.container.createLine({x1:d.x1+shx, y1:d.y1+shy, x2:d.x2+shx, y2:d.y2+shy})
+				//	.setStroke({width:lineWidth, color:c, cap:"round"})		
+			
+				if(dojox.gfx.renderer=="svg"){
+					var strAr = [];
+					dojo.forEach(pts, function(o, i){
+						if(i==0){
+							strAr.push("M " + (o.x+shx) +" "+ (o.y+shy));
+						}else{
+							var cmd = o.t || "L ";
+							strAr.push(cmd + (o.x+shx) +" "+ (o.y+shy)); // Z + undefined works here
+						}
+					}, this);
+					if(closePath){
+						strAr.push("Z");
+					}
+					this.container.createPath(strAr.join(", ")).setStroke({width:lineWidth, color:c, cap:"round"})	
+					
+				}else{
+					// Leaving this code for VML. It seems slightly faster but times vary.
+					var pth = this.container.createPath({}).setStroke({width:lineWidth, color:c, cap:"round"})	
+					
+					dojo.forEach(this.points, function(o, i){
+						if(i==0 || o.t=="M"){
+							pth.moveTo(o.x+shx, o.y+shy);
+						}else if(o.t=="Z"){
+							closePath && pth.closePath();
+						}else{
+							pth.lineTo(o.x+shx, o.y+shy);
+						}
+					}, this);
+					
+					closePath && pth.closePath();
+				}
+			
+			
+			}
+		},
+		
+		createForLine: function(o, size, mult, d, r, p, c){
+			
+			var sh = size * mult / 4,
+				shy = /B/.test(p) ? sh : /T/.test(p) ? sh*-1 : 0,
+				shx = /R/.test(p) ? sh : /L/.test(p) ? sh*-1 : 0;
+			for(var i=1;i<=size;i++){
+				var lineWidth = i * mult;
+				this.container.createLine({x1:d.x1+shx, y1:d.y1+shy, x2:d.x2+shx, y2:d.y2+shy})
+					.setStroke({width:lineWidth, color:c, cap:"round"})		
+			}
+		},
+		createForEllipse: function(o, size, mult, d, r, p, c){
+		
+			var sh = size * mult / 8,
+				shy = /B/.test(p) ? sh : /T/.test(p) ? sh*-1 : 0,
+				shx = /R/.test(p) ? sh*.8 : /L/.test(p) ? sh*-.8 : 0;
+			
+			for(var i=1;i<=size;i++){
+				var lineWidth = i * mult;
+				this.container.createEllipse({cx:d.cx+shx, cy:d.cy+shy, rx:d.rx-sh, ry:d.ry-sh, r:r})
+					.setStroke({width:lineWidth, color:c})		
+			}
+		},
+		
+		createForRect: function(o, size, mult, d, r, p, c){
+			
+			var sh = size * mult / 2,
+				shy = /B/.test(p) ? sh : /T/.test(p) ? 0 : sh /2,
+				shx = /R/.test(p) ? sh : /L/.test(p) ? 0 : sh /2;
+			
+			for(var i=1;i<=size;i++){
+				var lineWidth = i * mult;
+				this.container.createRect({x:d.x+shx, y:d.y+shy, width:d.width-sh, height:d.height-sh, r:r})
+					.setStroke({width:lineWidth, color:c})		
+			}
+		},
+		
+		arrowPoints: function(){
+			// summary:
+			//	Creates data used to draw arrow head.
+			//
+			var d = this.stencil.data;
+			var radius = this.stencil.getRadius();
+			var angle = this.style.zAngle + 30;
 
-if(!dojo._hasResource["dojox.drawing.annotations.BoxShadow"]){
-dojo._hasResource["dojox.drawing.annotations.BoxShadow"]=true;
-dojo.provide("dojox.drawing.annotations.BoxShadow");
-dojox.drawing.annotations.BoxShadow=dojox.drawing.util.oo.declare(function(_1){
-this.stencil=_1.stencil;
-this.util=_1.stencil.util;
-this.mouse=_1.stencil.mouse;
-this.style=_1.stencil.style;
-var _2={size:6,mult:4,alpha:0.05,place:"BR",color:"#646464"};
-delete _1.stencil;
-this.options=dojo.mixin(_2,_1);
-this.options.color=new dojo.Color(this.options.color);
-this.options.color.a=this.options.alpha;
-switch(this.stencil.shortType){
-case "image":
-case "rect":
-this.method="createForRect";
-break;
-case "ellipse":
-this.method="createForEllipse";
-break;
-case "line":
-this.method="createForLine";
-break;
-case "path":
-this.method="createForPath";
-break;
-default:
-console.warn("A shadow cannot be made for Stencil type ",this.stencil.type);
-}
-if(this.method){
-this.render();
-this.stencil.connectMult([[this.stencil,"onTransform",this,"onTransform"],[this.stencil,"render",this,"onRender"],[this.stencil,"onDelete",this,"destroy"]]);
-}
-},{showing:true,render:function(){
-if(this.container){
-this.container.removeShape();
-}
-this.container=this.stencil.container.createGroup();
-this.container.moveToBack();
-var o=this.options,_3=o.size,_4=o.mult,d=this.method=="createForPath"?this.stencil.points:this.stencil.data,r=d.r||1,p=o.place,c=o.color;
-this[this.method](o,_3,_4,d,r,p,c);
-},hide:function(){
-if(this.showing){
-this.showing=false;
-this.container.removeShape();
-}
-},show:function(){
-if(!this.showing){
-this.showing=true;
-this.stencil.container.add(this.container);
-}
-},createForPath:function(o,_5,_6,_7,r,p,c){
-var sh=_5*_6/4,_8=/B/.test(p)?sh:/T/.test(p)?sh*-1:0,_9=/R/.test(p)?sh:/L/.test(p)?sh*-1:0;
-var _a=true;
-for(var i=1;i<=_5;i++){
-var _b=i*_6;
-if(dojox.gfx.renderer=="svg"){
-var _c=[];
-dojo.forEach(_7,function(o,i){
-if(i==0){
-_c.push("M "+(o.x+_9)+" "+(o.y+_8));
-}else{
-var _d=o.t||"L ";
-_c.push(_d+(o.x+_9)+" "+(o.y+_8));
-}
-},this);
-if(_a){
-_c.push("Z");
-}
-this.container.createPath(_c.join(", ")).setStroke({width:_b,color:c,cap:"round"});
-}else{
-var _e=this.container.createPath({}).setStroke({width:_b,color:c,cap:"round"});
-dojo.forEach(this.points,function(o,i){
-if(i==0||o.t=="M"){
-_e.moveTo(o.x+_9,o.y+_8);
-}else{
-if(o.t=="Z"){
-_a&&_e.closePath();
-}else{
-_e.lineTo(o.x+_9,o.y+_8);
-}
-}
-},this);
-_a&&_e.closePath();
-}
-}
-},createForLine:function(o,_f,_10,d,r,p,c){
-var sh=_f*_10/4,shy=/B/.test(p)?sh:/T/.test(p)?sh*-1:0,shx=/R/.test(p)?sh:/L/.test(p)?sh*-1:0;
-for(var i=1;i<=_f;i++){
-var _11=i*_10;
-this.container.createLine({x1:d.x1+shx,y1:d.y1+shy,x2:d.x2+shx,y2:d.y2+shy}).setStroke({width:_11,color:c,cap:"round"});
-}
-},createForEllipse:function(o,_12,_13,d,r,p,c){
-var sh=_12*_13/8,shy=/B/.test(p)?sh:/T/.test(p)?sh*-1:0,shx=/R/.test(p)?sh*0.8:/L/.test(p)?sh*-0.8:0;
-for(var i=1;i<=_12;i++){
-var _14=i*_13;
-this.container.createEllipse({cx:d.cx+shx,cy:d.cy+shy,rx:d.rx-sh,ry:d.ry-sh,r:r}).setStroke({width:_14,color:c});
-}
-},createForRect:function(o,_15,_16,d,r,p,c){
-var sh=_15*_16/2,shy=/B/.test(p)?sh:/T/.test(p)?0:sh/2,shx=/R/.test(p)?sh:/L/.test(p)?0:sh/2;
-for(var i=1;i<=_15;i++){
-var _17=i*_16;
-this.container.createRect({x:d.x+shx,y:d.y+shy,width:d.width-sh,height:d.height-sh,r:r}).setStroke({width:_17,color:c});
-}
-},onTransform:function(){
-this.render();
-},onRender:function(){
-this.container.moveToBack();
-},destroy:function(){
-if(this.container){
-this.container.removeShape();
-}
-}});
-}
+			var pt = this.util.pointOnCircle(d.x1, d.y1, radius*.75, angle);
+			
+			var obj = {
+				start:{
+					x:d.x1,
+					y:d.y1
+				},
+				x:pt.x,
+				y:pt.y
+			}
+			var angle = this.util.angle(obj);
+			var lineLength = this.util.length(obj); 
+			var al = this.style.arrows.length;
+			var aw = this.style.arrows.width/3;
+			if(lineLength<al){
+				al = lineLength/2;
+			}
+
+			var p1 = this.util.pointOnCircle(obj.x, obj.y, -al, angle-aw);
+			var p2 = this.util.pointOnCircle(obj.x, obj.y, -al, angle+aw);
+			return [
+				{x:obj.x, y:obj.y},
+				p1,
+				p2
+			];
+		},
+		
+		createForZArrow: function(o, size, mult, pts, r, p, c){
+			if(this.stencil.data.cosphi<1 || !this.stencil.points[0]){ return; }
+			var sh = size * mult / 4,
+				shy = /B/.test(p) ? sh : /T/.test(p) ? sh*-1 : 0,
+				shx = /R/.test(p) ? sh : /L/.test(p) ? sh*-1 : 0;
+			var closePath = true;
+			for(var i=1;i<=size;i++){
+				var lineWidth = i * mult;
+				pts = this.arrowPoints();
+				if(!pts){ return; }
+				if(dojox.gfx.renderer=="svg"){
+					
+					var strAr = [];
+					dojo.forEach(pts, function(o, i){
+						if(i==0){
+							strAr.push("M " + (o.x+shx) +" "+ (o.y+shy));
+						}else{
+							var cmd = o.t || "L ";
+							strAr.push(cmd + (o.x+shx) +" "+ (o.y+shy)); // Z + undefined works here
+						}
+					}, this);
+					if(closePath){
+						strAr.push("Z");
+					}
+
+					this.container.createPath(strAr.join(", ")).setStroke({width:lineWidth, color:c, cap:"round"}).setFill(c);
+					
+				}else{
+					// Leaving this code for VML. It seems slightly faster but times vary.
+					var pth = this.container.createPath({}).setStroke({width:lineWidth, color:c, cap:"round"})	
+					
+					dojo.forEach(pts, function(o, i){
+						if(i==0 || o.t=="M"){
+							pth.moveTo(o.x+shx, o.y+shy);
+						}else if(o.t=="Z"){
+							closePath && pth.closePath();
+						}else{
+							pth.lineTo(o.x+shx, o.y+shy);
+						}
+					}, this);
+					
+					closePath && pth.closePath();
+				}
+				var sp = this.stencil.points;
+				this.container.createLine({x1:sp[0].x, y1:sp[0].y, x2:pts[0].x, y2:pts[0].y})
+					.setStroke({width:lineWidth, color:c, cap:"round"});
+			
+			}
+		},
+		
+		
+		onTransform: function(){
+			this.render();
+		},
+		onRender: function(){
+			this.container.moveToBack();
+		},
+		destroy: function(){
+			if(this.container){
+				this.container.removeShape();
+			}
+		}
+	}
+);
\ No newline at end of file
diff --git a/dojox/drawing/annotations/Label.js b/dojox/drawing/annotations/Label.js
old mode 100644
new mode 100755
index f2a9fea..3fbe535
--- a/dojox/drawing/annotations/Label.js
+++ b/dojox/drawing/annotations/Label.js
@@ -1,65 +1,111 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.annotations.Label"]){
-dojo._hasResource["dojox.drawing.annotations.Label"]=true;
 dojo.provide("dojox.drawing.annotations.Label");
 dojo.require("dojox.drawing.stencil.Text");
-dojox.drawing.annotations.Label=dojox.drawing.util.oo.declare(dojox.drawing.stencil.Text,function(_1){
-this.master=_1.stencil;
-this.labelPosition=_1.labelPosition||"BR";
-if(dojo.isFunction(this.labelPosition)){
-this.setLabel=this.setLabelCustom;
-}
-this.setLabel(_1.text||"");
-this.connect(this.master,"onTransform",this,"setLabel");
-this.connect(this.master,"destroy",this,"destroy");
-if(this.style.labelSameColor){
-this.connect(this.master,"attr",this,"beforeAttr");
-}
-},{_align:"start",setLabelCustom:function(_2){
-var d=dojo.hitch(this.master,this.labelPosition)();
-this.setData({x:d.x,y:d.y,width:d.w||this.style.text.minWidth,height:d.h||this._lineHeight});
-if(_2&&!_2.split){
-_2=null;
-}
-this.render(_2);
-},setLabel:function(_3){
-var x,y,_4=this.master.getBounds();
-if(/B/.test(this.labelPosition)){
-y=_4.y2-this._lineHeight;
-}else{
-y=_4.y1;
-}
-if(/R/.test(this.labelPosition)){
-x=_4.x2;
-}else{
-y=_4.y1;
-this._align="end";
-}
-if(!this.labelWidth||(_3&&_3.split&&_3!=this._text)){
-this.setData({x:x,y:y,height:this._lineHeight,width:this.style.text.minWidth});
-this.labelWidth=this.style.text.minWidth;
-this.render(_3);
-}else{
-this.setData({x:x,y:y,height:this.data.height,width:this.data.width});
-this.render();
-}
-},beforeAttr:function(_5,_6){
-if(_6!==undefined){
-var k=_5;
-_5={};
-_5[k]=_6;
-}
-delete _5.x;
-delete _5.y;
-delete _5.width;
-delete _5.height;
-this.attr(_5);
-!this.created&&this.render();
-}});
-}
+
+dojox.drawing.annotations.Label = dojox.drawing.util.oo.declare(
+	// summary:
+	// 	An annotation called internally to label an Stencil.
+	// description:
+	//	Annotation is positioned with dojox.drawing.util.positioning.label
+	//	That method should be overwritten for custom placement. Or,
+	//	add a 'setLabelCustom' method to the Stencil and it will be used.
+	//
+	dojox.drawing.stencil.Text,
+	function(/*Object*/options){
+		// arguments:
+		//	options: Object
+		//		One key value: the stencil that called this.
+		//
+		this.master = options.stencil;
+		this.labelPosition = options.labelPosition || "BR"; // TL, TR, BR, BL, or function
+		if(dojo.isFunction(this.labelPosition)){
+			this.setLabel = this.setLabelCustom;	
+		}
+		this.setLabel(options.text || "");
+		this.connect(this.master, "onTransform", this, "setLabel");
+		this.connect(this.master, "destroy", this, "destroy");
+		
+		if(this.style.labelSameColor){
+			this.connect(this.master, "attr", this, "beforeAttr");		
+		}
+	},{
+		_align:"start",
+		
+		setLabelCustom: function(/* ? String */text){
+			// summary:
+			//	Attaches to custom positioning within a Stencil
+			//
+			var d = dojo.hitch(this.master, this.labelPosition)();
+			this.setData({
+				x:d.x,
+				y:d.y,
+				width:d.w || this.style.text.minWidth,
+				height:d.h || this._lineHeight
+			});
+			
+			// is an event, not text:
+			if(text && !text.split){ text = null; }
+			
+			this.render(this.typesetter(text));
+		},
+		
+		setLabel: function(/* String */text){
+			// summary:
+			//	Sets the text of the label. Not called directly. Should
+			//	be called within Stencil. See stencil._Base
+			//
+			// onTransform will pass an object here
+			var x, y, box = this.master.getBounds();
+			
+			if(/B/.test(this.labelPosition)){
+				y = box.y2 - this._lineHeight;
+			}else{
+				y = box.y1;
+			}
+			
+			if(/R/.test(this.labelPosition)){
+				x = box.x2;
+			}else{
+				y = box.y1;
+				this._align = "end";
+			}
+			
+			if(!this.labelWidth || (text && text.split && text != this.getText())){ //????????????????????????????????????
+				this.setData({
+					x:x,
+					y:y,
+					height:this._lineHeight,
+					width:this.style.text.minWidth
+				});
+				
+				this.labelWidth = this.style.text.minWidth;
+				this.render(this.typesetter(text));
+				
+			}else{
+				
+				this.setData({
+					x:x,
+					y:y,
+					height:this.data.height,
+					width:this.data.width
+				});
+				
+				this.render();
+			}
+			
+		},
+		beforeAttr: function(key, value){
+			if(value!==undefined){
+				// make it an object
+				var k = key; key = {}; key[k] = value;	
+			}
+			delete key.x;
+			delete key.y;
+			delete key.width;
+			delete key.height;
+			this.attr(key);
+			 // FIXME: this.created should already be set, shouldn't it?
+			!this.created && this.render();
+		}
+	}
+
+);
\ No newline at end of file
diff --git a/dojox/drawing/defaults.js b/dojox/drawing/defaults.js
old mode 100644
new mode 100755
index 63ed972..e0f34d4
--- a/dojox/drawing/defaults.js
+++ b/dojox/drawing/defaults.js
@@ -1,42 +1,288 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.defaults");
 
+dojox.drawing.defaults = {
+	// summary:
+	//		Styles and defaults used for Drawing stencils and text.
+	// description:
+	//		This object contains defaults for objects used in Drawing.
+	//		To change one item's style, use item.attr();
+	//		To change all these styles, create a copy of this file
+	//		and point to it in the Drawing properties:
+	//		|	<div dojoType="dojox.drawing.Drawing" id="drawing" defaults="MyCustom.defaults"></div>
+	// See:
+	//		Drawing.changeDefaults
+	//
+	//  Determines whether in draw or edit mode (whether stencils
+	//  are clickable.  If clickMode is false, the original
+	//  functionality of silently switching between select modes
+	//  is enabled.  If clickMode is true, it allows powerpoint-
+	//  like functionality.  Clickable is used by powerpoint to
+	//  distinguish when things can be selected and when they can't
+	clickMode:true,
+	clickable:true,
+
+	// current: Object
+	// 	 current will point to either null or selected
+	current:null,
+	// currentHit: Object
+	//		currentHit will point to either hitNorm or hitSelected
+	currentHit:null,
+
+	// angleSnap: Number
+	// 		Line, arrows, vector and axes will all snap to this angle on mouse up
+	// 		shown angle also reflects the snap
+	// 		currently cannot accept less than 1 degree
+	angleSnap:1,
+
+	// zAxis:  Boolean
+    // 		If true, draw current object in z-direction.
+	// zAxisEnabled: Boolean
+    // 		If true, render axes with Z-axis included, allow objects drawn in z-direction.
+	//		If false the z-axis button will not show up.
+	zAxis: false,
+	zAxisEnabled: true,
+	zAngle: 225,
+	
+	// renderHitLines: Boolean
+	//		If true, renders a second, larger layer for lines to make
+	// 		them more easily clickable.
+	renderHitLines: true,
+	//
+	// renderHitLayer:
+	// 		If true, renders a second layer for each Stencil, one
+	// 		acting as a 'hit' object for a wider mouse-click area.
+	// 		It also doubles as a hilight. If true, overrides
+	//		renderHitLines setting.
+	renderHitLayer:true,
+
+	// labelSameColor:
+	//		If true, the label text color will be the same as the
+	//		Stencil's line color.
+	labelSameColor:false,
+
+	//
+	useSelectedStyle: true,
+
+	norm:{
+		// summary:
+		// 		Normal style of all shapes
+		// 		will get overridden by
+		// 		above andes styles
+		width:1,
+		color:"#000000",
+		style:"Solid",
+		cap:"round", // square, butt, round
+		fill:"#CCCCCC"
+	},
+
+	selected:{
+		// summary:
+		// 		Selected style of all shapes
+		// 		styles not shown will used from
+		//	norm
+		width:6,
+		color:"#00FF00"
+	},
+
+	highlighted:{
+		// summary:
+		// 		Highlighted style of all shapes
+		// 		NOT CURRENTLY BEING USED
+		width:6,
+		color:"#FF00FF",
+		style:"Solid",
+		cap:"round",
+		fill:"#E11EBB"
+	},
+
+	disabled:{
+		// summary:
+		// 		Disabled or "locked" or "fade" style of all shapes
+		width:1,
+		color:"#666666",
+		style:"solid",
+		cap:"round",
+		fill:"#cccccc"
+	},
+
+	// "hit" refers to the hidden object below the shape
+	// that is usually larger than the object to give a
+	// larger 'target' to click upon. These hit objects
+	// double as highlights.
+	//
+	hitNorm:{
+		// summary:
+		//		Normal style of a hit area
+		width:6,
+		color:{r:0, g:255, b:255, a:0},
+		style:"Solid",
+		cap:"round",
+		fill:{r:255, g:255, b:255, a:0}
+	},
+	hitSelected:{
+		// summary:
+		//		Selected style of a hit area
+		width:6,
+		color:"#FF9900",
+		style:"Solid",
+		cap:"round",
+		fill:{r:255, g:255, b:255, a:0}
+	},
+	hitHighlighted:{
+		// summary:
+		//		Highlighted style of a hit area
+		width:6,
+		color:"#FFFF00",
+		style:"Solid",
+		cap:"round",
+		fill:{r:255, g:255, b:255, a:0}
+	},
+
+
+	anchors:{
+		// summary:
+		// 		Style for the anchor resize-points
+		size:10,
+		width:2,
+		color:"#999",
+		style:"solid",
+		fill:"#fff",
+		cap:"square",
+		minSize:10,
+		marginZero:5 // not really an anchor prop
+	},
+	arrows:{
+		// summary:
+		// 		Size of arrows on vectors.
+		// 		length is in pixels
+		// 		width is actually an angle
+		// 		but is close to pixels in size
+		length:30,
+		width:16
+	},
+	text:{
+		// summary:
+		// 		Style of text
+		minWidth:100,
+		deleteEmptyCreate:true,
+		deleteEmptyModify:true,
+		pad:3,
+		size:"18px",
+		family:"sans-serif",
+		weight:"normal",
+		color:"#000000"
+	},
+	textDisabled:{
+		// summary:
+		// 		Style of disabled text
+		size:"18px",
+		family:"sans-serif",
+		weight:"normal",
+		color:"#cccccc"
+	},
+
+	textMode:{
+		// summary:
+		// 		These styles apply to the containing
+		//		text box (edit mode), and not the text itself
+		create:{
+			width:2,
+			style:"dotted",
+			color:"#666666",
+			fill:null
+		},
+		edit:{
+			width:1,
+			style:"dashed",
+			color:"#666",
+			fill:null
+		}
+
+	},
+
+	button:{
+		norm:{
+			"color": "#cccccc",
+			"fill": {
+				type:"linear",
+				x1:0, x2:0, y1:0, y2:100,
+				colors:[
+					{offset:.5, color:"#ffffff"},
+					{offset:1, color:"#e5e5e5"}
+				]
+			}
+		},
+		over:{
+			"fill": {
+				type:"linear",
+				x1:0, x2:0, y1:0, y2:100,
+				colors:[{offset:.5, color:"#ffffff"}, {offset:1, color:"#e1eaf5"}]
+			},
+			"color": "#92a0b3"
+		},
+		down:{
+			"fill": {
+				type:"linear",
+				x1:0, x2:0, y1:0, y2:100,
+				colors:[{offset:0, color:"#e1eaf5"}, {offset:1, color:"#ffffff"}]
+			},
+			"color": "#92a0b3"
+		},
+		selected:{
+			"fill": {
+				type:"linear",
+				x1:0, x2:0, y1:0, y2:100,
+				colors:[{offset:0, color:"#97b4bf"}, {offset:1, color:"#c8dae1"}]
+			},
+			"color": "#92a0b3"
+		},
+		icon:{
+			norm:{
+				fill:null,
+				color:"#92a0b3"
+			},
+			selected:{
+				fill:"#ffffff",
+				color:"#92a0b3"
+			}
+		}
+	},
+
+	copy: function(){
+		// summary
+		//		Each shape gets its own copy
+		//		of these styles so that instances
+		// 		do not change each other's styles
+		//
+		var cpy = function(obj){
+				if(typeof(obj)!="object" || obj===null || obj===undefined){
+					return obj;
+				}
+				var o;
+				if(obj.push){
+					o = [];
+					for(var i=0; i<obj.length;i++){
+						o.push(cpy(obj[i]))
+					}
+					return o;
+				}
+			o = {};
+			for(var nm in obj){
+				if(nm!="copy"){
+					if(typeof(obj[nm])=="object"){
+						o[nm] = cpy(obj[nm]);
+					}else{
+						o[nm] = obj[nm]
+					}
+				}
+			}
+			return o;
+		}
+		var o = cpy(this);
+		o.current = o.norm;
+		o.currentHit = o.hitNorm;
+		o.currentText = o.text;
+		return o;
+	}
 
-if(!dojo._hasResource["dojox.drawing.defaults"]){
-dojo._hasResource["dojox.drawing.defaults"]=true;
-dojo.provide("dojox.drawing.defaults");
-dojox.drawing.defaults={current:null,currentHit:null,angleSnap:1,renderHitLines:true,renderHitLayer:true,labelSameColor:false,useSelectedStyle:true,norm:{width:1,color:"#000000",style:"Solid",cap:"round",fill:"#CCCCCC"},selected:{width:6,color:"#00FF00"},highlighted:{width:6,color:"#FF00FF",style:"Solid",cap:"round",fill:"#E11EBB"},disabled:{width:1,color:"#666666",style:"solid",cap:"round",fill:"#cccccc"},hitNorm:{width:6,color:{r:0,g:255,b:255,a:0},style:"Solid",cap:"round",fill:{r:255 [...]
-var _1=function(_2){
-if(typeof (_2)!="object"||_2===null||_2===undefined){
-return _2;
-}
-var o;
-if(_2.push){
-o=[];
-for(var i=0;i<_2.length;i++){
-o.push(_1(_2[i]));
-}
-return o;
-}
-o={};
-for(var nm in _2){
-if(nm!="copy"){
-if(typeof (_2[nm])=="object"){
-o[nm]=_1(_2[nm]);
-}else{
-o[nm]=_2[nm];
-}
-}
-}
-return o;
 };
-var o=_1(this);
-o.current=o.norm;
-o.currentHit=o.hitNorm;
-o.currentText=o.text;
-return o;
-}};
-}
diff --git a/dojox/drawing/library/icons.js b/dojox/drawing/library/icons.js
index 3015808..ea73d08 100644
--- a/dojox/drawing/library/icons.js
+++ b/dojox/drawing/library/icons.js
@@ -1,12 +1,161 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.library.icons"]){
-dojo._hasResource["dojox.drawing.library.icons"]=true;
 dojo.provide("dojox.drawing.library.icons");
-dojox.drawing.library.icons={line:{type:"line",borderWidth:1,x1:20,y1:20,x2:80,y2:80},ellipse:{type:"ellipse",borderWidth:1,cx:50,cy:50,rx:35,ry:20},rect:{type:"rect",borderWidth:1,x:10,y:30,width:80,height:40},triangle:{type:"path",borderWidth:1,closePath:true,points:[{x:50,y:10},{x:10,y:90},{x:90,y:90}]},path:{type:"path",borderWidth:0,closePath:true,points:[{x:20,y:80},{x:26,y:20},{x:80,y:32},{x:32,y:50},{x:56,y:62}]},arrow:{type:"path",borderWidth:1,closePath:false,points:[{x:20,y:20 [...]
-}
+
+dojox.drawing.library.icons = {
+	// summary:
+	//		A collection of icon Stencils for use with the buttons in the ui/Toolbar.
+	// description:
+	//		Each icon name coresponds to a Stencil or a Plugin. One can be inserted
+	//		into a button by adding the property: 'icon', which points to one of
+	//		these Stencil objects.
+	line:{
+		type:"line",
+		borderWidth:1,
+		x1:20,
+		y1:20,
+		x2:80,
+		y2:80
+	},
+	ellipse:{
+		type:"ellipse",
+		borderWidth:1,
+		cx:50,
+		cy:50,
+		rx:35,
+		ry:20
+	},
+	rect:{
+		type:"rect",
+		borderWidth:1,
+		x:10,
+		y:30,
+		width:80,
+		height:40
+	},
+	triangle:{
+		type:"path",
+		borderWidth:1,
+		closePath:true,
+		points:[{x:50, y:10}, {x:10, y:90}, {x:90, y:90}]
+	},
+	path:{
+		type:"path",
+		borderWidth:0,
+		closePath:true,
+		points:[ { x:20, y:80 }, { x:26, y:20 }, { x:80, y:32 }, { x:32, y:50 }, { x:56, y:62 } ]
+	},
+	arrow:{
+		type:"path",
+		borderWidth:1,
+		closePath:false,
+		points:[ { x:20, y:20 }, { x:80, y:80 }, { t:'M', x:74, y:56 }, { x:80, y:80 }, { x:56, y:74 } ]
+	},
+	textBlock:{
+		type:"path",
+		borderWidth:0,
+		closePath:true,
+		points:[ { x:20, y:20 }, { x:80, y:20 }, { x:80, y:38 }, { x:80, y:38 }, { x:74, y:32 }, { x:68, y:26 }, { x:56, y:20 }, { x:56, y:68 }, { x:56, y:74 }, { x:62, y:80 }, { x:68, y:80 }, { x:68, y:80 }, { x:32, y:80 }, { x:32, y:80 }, { x:38, y:80 }, { x:44, y:74 }, { x:44, y:68 }, { x:44, y:20 }, { x:32, y:26 }, { x:26, y:32 }, { x:20, y:38 }, { x:20, y:38 } ]
+	},
+	
+	equation:{
+		type:"path",
+		borderWidth:2,
+		closePath:false,
+		points:[ {x:20, y:60 }, { x:80, y:60 }, {t:'M', x:20, y:40 }, { x:80, y:40 } ]
+	},
+	
+	axes:{
+		type:"path",
+		borderWidth:1,
+		closePath:false,
+		points:[ { x:20, y:32 }, { x:26, y:20 }, { x:32, y:32 }, { t:'M', x:26, y:20 }, { x:26, y:74 }, { x:80, y:74 }, { t:'M', x:68, y:68 }, { x:80, y:74 }, { x:68, y:80 } ]
+	},
+	vector:{
+		type:"path",
+		borderWidth:1,
+		closePath:false,
+		points:[ { x:20, y:80 }, { x:80, y:20 }, { t:'M', x:62, y:26 }, { x:80, y:20 }, { x:73, y:40 }, { t:'M', x:56, y:56 }, { x:62, y:68 }, { x:62, y:74 } ]
+	},
+	pan:{
+		type:"path",
+		borderWidth:1,
+		closePath:true,
+		points:[ { x:38, y:80 }, { x:26, y:68 }, { x:20, y:50 }, { x:26, y:44 }, { x:26, y:44 }, { x:38, y:56 }, { x:32, y:32 }, { x:32, y:26 }, { x:38, y:26 }, { x:44, y:44 }, { x:44, y:20 }, { x:50, y:20 }, { x:56, y:20 }, { x:56, y:44 }, { x:56, y:26 }, { x:62, y:26 }, { x:68, y:26 }, { x:68, y:50 }, { x:68, y:32 }, { x:74, y:32 }, { x:80, y:38 }, { x:80, y:50 }, { x:74, y:68 }, { x:68, y:80 } ]
+	},
+	
+	plus:{
+		type:"path",
+		borderWidth:3,
+		closePath:false,
+		points:[ { x:50, y:20 }, { x:50, y:80 }, { t:"M", x:20, y:50 }, { x:80, y:50 } ]
+	},
+	zoomIn:{
+		type:"path",
+		borderWidth:3,
+		closePath:false,
+		points:[ { x:50, y:20 }, { x:50, y:80 }, { t:"M", x:20, y:50 }, { x:80, y:50 } ]
+	},
+	zoomOut:{
+		type:"path",
+		borderWidth:3,
+		closePath:false,
+		points:[ {x:20, y:50 }, { x:80, y:50 } ]
+	},
+	zoom100:{
+		type:"text",
+		text:"100%"
+	},
+	iconize:{
+		type:"path",
+		borderWidth:0,
+		closePath:true,
+		points:
+		
+[
+{	x:20,		y:38	},
+{	x:32,		y:26	},
+{	x:44,		y:26	},
+{	x:56,		y:38	},
+{	x:56,		y:50	},
+{	x:44,		y:62	},
+{	x:32,		y:62	},
+{	x:20,		y:56	},
+{	t:'Z'	},
+{	t:'M', x:38,		y:44	},
+{	x:68,		y:44	},
+{	x:68,		y:80	},
+{	x:38,		y:80	},
+{	t:'Z'	},
+{	t:'M', x:56,		y:62	},
+{	x:68,		y:20	},
+{	x:80,		y:62	}
+]
+		
+	},
+	pencil:{
+		type:"path",
+		borderWidth:0,
+		closePath:true,
+		points:
+		
+[
+{	x:20,		y:80	},
+{	x:26,		y:68	},
+{	x:68,		y:20	},
+{	x:80,		y:20	},
+{	x:80,		y:32	},
+{	x:38,		y:74	},
+{	t:'Z'	},
+{	t:'M', x:62,		y:32	},
+{	x:68,		y:26	},
+{	x:74,		y:26	},
+{	x:74,		y:32	},
+{	x:68,		y:38	},
+{	x:68,		y:32	},
+{	t:'Z'	},
+{	t:'M', x:56,		y:38	},
+{	x:62,		y:38	},
+{	x:32,		y:68	},
+{	x:32,		y:68	}
+]
+	}
+};
\ No newline at end of file
diff --git a/dojox/drawing/manager/Anchors.js b/dojox/drawing/manager/Anchors.js
old mode 100644
new mode 100755
index 6563c53..2719a3d
--- a/dojox/drawing/manager/Anchors.js
+++ b/dojox/drawing/manager/Anchors.js
@@ -1,236 +1,464 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.manager.Anchors");
 
+dojox.drawing.manager.Anchors = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Creates and manages the anchor points that are attached to
+	//		(usually) the corners of a Stencil.
+	// description:
+	//		Used internally, but there are some things that should be known:
+	//		Anchors attach to a Stencil's 'points' (See stencil.points)
+	//		To not display an anchor on a certain point, add noAnchor:true
+	//		to the point.
+	
+	function(/* dojox.__stencilArgs */options){
+		// arguments: See stencil._Base
+		this.mouse = options.mouse;
+		this.undo = options.undo;
+		this.util = options.util;
+		this.drawing = options.drawing;
+		this.items = {};
+	},
+	{
+		onAddAnchor: function(/*Anchor*/anchor){
+			// summary:
+			//		Event fires when anchor is created
+		},
+		
+		
+		onReset: function(/*Stencil*/stencil){
+			// summary:
+			//		Event fires when an anchor's reset method is called
+			//
+			// a desperate hack in order to get the anchor point to reset.
+			// FIXME: Is this still used? I think its item.deselect();item.select();
+			var st = this.util.byId("drawing").stencils;
+			st.onDeselect(stencil);
+			st.onSelect(stencil);
+		},
+		
+		onRenderStencil: function(){
+			// summary:
+			//		Event fires when an anchor calls a Stencil's render method
+			//
+			for(var nm in this.items){
+				dojo.forEach(this.items[nm].anchors, function(a){
+					a.shape.moveToFront();
+				});
+			}
+		},
+		
+		onTransformPoint: function(/*Anchor*/anchor){
+			// summary:
+			//		Event fired on anchor drag
+			//
+			//		If anchors are a "group", it's corresponding anchor
+			//		is set. All anchors then moved to front.
+			var anchors = this.items[anchor.stencil.id].anchors;
+			var item = this.items[anchor.stencil.id].item;
+			var pts = [];
+			dojo.forEach(anchors, function(a, i){
+				
+				
+				if(anchor.id == a.id || anchor.stencil.anchorType!="group"){
+					// nothing 
+				}else{
+					if(anchor.org.y == a.org.y){
+						a.setPoint({
+							dx: 0,
+							dy: anchor.shape.getTransform().dy - a.shape.getTransform().dy
+						});
+					}else if(anchor.org.x == a.org.x){
+						a.setPoint({
+							dx: anchor.shape.getTransform().dx - a.shape.getTransform().dx,
+							dy: 0
+						});
+					}
+					a.shape.moveToFront();
+				}
+				
+				var mx = a.shape.getTransform();
+				pts.push({x:mx.dx + a.org.x, y:mx.dy+ a.org.y});
+				
+				if(a.point.t){
+					pts[pts.length-1].t = a.point.t;
+				}
+				
+			}, this);
+			item.setPoints(pts);
+			item.onTransform(anchor);
+			this.onRenderStencil();
+		},
+		
+		onAnchorUp: function(/*Anchor*/anchor){
+			// summary:
+			//		Event fired on anchor mouseup
+		},
+		
+		onAnchorDown: function(/*Anchor*/anchor){
+			// summary:
+			//		Event fired on anchor mousedown
+		},
+		
+		onAnchorDrag: function(/*Anchor*/anchor){
+			// summary:
+			//		Event fired when anchor is moved
+		},
+		
+		onChangeStyle: function(/*Object*/stencil){
+			// summary:
+			// 		if the Stencil changes color while were's selected
+			// 		this moves the anchors to the back. Fix it.
+			
+			for(var nm in this.items){
+				dojo.forEach(this.items[nm].anchors, function(a){
+					a.shape.moveToFront();
+				});
+			}
+		},
+		
+		add: function(/*Stencil*/item){
+			// summary:
+			//		Creates anchor points on a Stencil, based on the
+			//		Stencil's points.
+			//	
+			this.items[item.id] = {
+				item:item,
+				anchors:[]
+			};
+			if(item.anchorType=="none"){ return; }
+			var pts = item.points;
+			dojo.forEach(pts, function(p, i){
+				if(p.noAnchor){ return; }
+				if(i==0 || i == item.points.length-1){
+					console.log("ITEM TYPE:", item.type, item.shortType);
+				}
+				var a = new dojox.drawing.manager.Anchor({stencil:item, point:p, pointIdx:i, mouse:this.mouse, util:this.util});
+				this.items[item.id]._cons = [
+					dojo.connect(a, "onRenderStencil", this, "onRenderStencil"),
+					dojo.connect(a, "reset", this, "onReset"),
+					dojo.connect(a, "onAnchorUp", this, "onAnchorUp"),
+					dojo.connect(a, "onAnchorDown", this, "onAnchorDown"),
+					dojo.connect(a, "onAnchorDrag", this, "onAnchorDrag"),
+					dojo.connect(a, "onTransformPoint", this, "onTransformPoint"),
+					// FIXME: this will fire for each anchor. yech.
+					dojo.connect(item, "onChangeStyle", this, "onChangeStyle")
+				];
+				
+				this.items[item.id].anchors.push(a);
+				this.onAddAnchor(a);
+			}, this);
+			
+			if(item.shortType=="path"){
+				// check if we have a double-point of a closed-curve-path
+				var f = pts[0], l = pts[pts.length-1], a = this.items[item.id].anchors;
+				if(f.x ==l.x && f.y==l.y){
+					console.warn("LINK ANVHROS", a[0], a[a.length-1]);
+					a[0].linkedAnchor = a[a.length-1];
+					a[a.length-1].linkedAnchor = a[0];
+				}
+			}
+			
+			if(item.anchorType=="group"){
+				dojo.forEach(this.items[item.id].anchors, function(anchor){
+					dojo.forEach(this.items[item.id].anchors, function(a){
+						if(anchor.id != a.id){
+							if(anchor.org.y == a.org.y){
+								anchor.x_anchor = a;
+							}else if(anchor.org.x == a.org.x){
+								anchor.y_anchor = a;
+							}
+						}
+					},this);	
+				},this);
+				
+			}
+		},
+		
+		remove: function(/*Stencil*/item){
+			// summary:
+			//		Destroys the anchor points for a Stencil.
+			//
+			if(!this.items[item.id]){
+				return;
+			}
+			dojo.forEach(this.items[item.id].anchors, function(a){
+				a.destroy();
+			});
+			dojo.forEach(this.items[item.id]._cons, dojo.disconnect, dojo);
+			this.items[item.id].anchors = null;
+			delete this.items[item.id];
+		}
+	}
+);
 
-if(!dojo._hasResource["dojox.drawing.manager.Anchors"]){
-dojo._hasResource["dojox.drawing.manager.Anchors"]=true;
-dojo.provide("dojox.drawing.manager.Anchors");
-dojox.drawing.manager.Anchors=dojox.drawing.util.oo.declare(function(_1){
-this.mouse=_1.mouse;
-this.undo=_1.undo;
-this.util=_1.util;
-this.drawing=_1.drawing;
-this.items={};
-},{onAddAnchor:function(_2){
-},onReset:function(_3){
-var st=this.util.byId("drawing").stencils;
-st.onDeselect(_3);
-st.onSelect(_3);
-},onRenderStencil:function(){
-for(var nm in this.items){
-dojo.forEach(this.items[nm].anchors,function(a){
-a.shape.moveToFront();
-});
-}
-},onTransformPoint:function(_4){
-var _5=this.items[_4.stencil.id].anchors;
-var _6=this.items[_4.stencil.id].item;
-var _7=[];
-dojo.forEach(_5,function(a,i){
-if(_4.id==a.id||_4.stencil.anchorType!="group"){
-}else{
-if(_4.org.y==a.org.y){
-a.setPoint({dx:0,dy:_4.shape.getTransform().dy-a.shape.getTransform().dy});
-}else{
-if(_4.org.x==a.org.x){
-a.setPoint({dx:_4.shape.getTransform().dx-a.shape.getTransform().dx,dy:0});
-}
-}
-a.shape.moveToFront();
-}
-var mx=a.shape.getTransform();
-_7.push({x:mx.dx+a.org.x,y:mx.dy+a.org.y});
-if(a.point.t){
-_7[_7.length-1].t=a.point.t;
-}
-},this);
-_6.setPoints(_7);
-_6.onTransform(_4);
-this.onRenderStencil();
-},onAnchorUp:function(_8){
-},onAnchorDown:function(_9){
-},onAnchorDrag:function(_a){
-},onChangeStyle:function(_b){
-for(var nm in this.items){
-dojo.forEach(this.items[nm].anchors,function(a){
-a.shape.moveToFront();
-});
-}
-},add:function(_c){
-this.items[_c.id]={item:_c,anchors:[]};
-if(_c.anchorType=="none"){
-return;
-}
-var _d=_c.points;
-dojo.forEach(_d,function(p,i){
-if(p.noAnchor){
-return;
-}
-if(i==0||i==_c.points.length-1){
-if(i==0){
-}else{
-}
-}
-var a=new dojox.drawing.manager.Anchor({stencil:_c,point:p,pointIdx:i,mouse:this.mouse,util:this.util});
-this.items[_c.id]._cons=[dojo.connect(a,"onRenderStencil",this,"onRenderStencil"),dojo.connect(a,"reset",this,"onReset"),dojo.connect(a,"onAnchorUp",this,"onAnchorUp"),dojo.connect(a,"onAnchorDown",this,"onAnchorDown"),dojo.connect(a,"onAnchorDrag",this,"onAnchorDrag"),dojo.connect(a,"onTransformPoint",this,"onTransformPoint"),dojo.connect(_c,"onChangeStyle",this,"onChangeStyle")];
-this.items[_c.id].anchors.push(a);
-this.onAddAnchor(a);
-},this);
-if(_c.shortType=="path"){
-var f=_d[0],l=_d[_d.length-1],a=this.items[_c.id].anchors;
-if(f.x==l.x&&f.y==l.y){
-console.warn("LINK ANVHROS",a[0],a[a.length-1]);
-a[0].linkedAnchor=a[a.length-1];
-a[a.length-1].linkedAnchor=a[0];
-}
-}
-if(_c.anchorType=="group"){
-dojo.forEach(this.items[_c.id].anchors,function(_e){
-dojo.forEach(this.items[_c.id].anchors,function(a){
-if(_e.id!=a.id){
-if(_e.org.y==a.org.y){
-_e.x_anchor=a;
-}else{
-if(_e.org.x==a.org.x){
-_e.y_anchor=a;
-}
-}
-}
-},this);
-},this);
-}
-},remove:function(_f){
-if(!this.items[_f.id]){
-return;
-}
-dojo.forEach(this.items[_f.id].anchors,function(a){
-a.destroy();
-});
-dojo.forEach(this.items[_f.id]._cons,dojo.disconnect,dojo);
-this.items[_f.id].anchors=null;
-delete this.items[_f.id];
-}});
-dojox.drawing.manager.Anchor=dojox.drawing.util.oo.declare(function(_10){
-this.defaults=dojox.drawing.defaults.copy();
-this.mouse=_10.mouse;
-this.point=_10.point;
-this.pointIdx=_10.pointIdx;
-this.util=_10.util;
-this.id=_10.id||this.util.uid("anchor");
-this.org=dojo.mixin({},this.point);
-this.stencil=_10.stencil;
-if(this.stencil.anchorPositionCheck){
-this.anchorPositionCheck=dojo.hitch(this.stencil,this.stencil.anchorPositionCheck);
-}
-this._zCon=dojo.connect(this.mouse,"setZoom",this,"render");
-this.render();
-this.connectMouse();
-},{y_anchor:null,x_anchor:null,render:function(){
-this.shape&&this.shape.removeShape();
-var d=this.defaults.anchors,z=this.mouse.zoom,b=d.width*z,s=d.size*z,p=s/2,_11={width:b,style:d.style,color:d.color,cap:d.cap};
-var _12={x:this.point.x-p,y:this.point.y-p,width:s,height:s};
-this.shape=this.stencil.container.createRect(_12).setStroke(_11).setFill(d.fill);
-this.shape.setTransform({dx:0,dy:0});
-this.util.attr(this,"drawingType","anchor");
-this.util.attr(this,"id",this.id);
-},onRenderStencil:function(_13){
-},onTransformPoint:function(_14){
-},onAnchorDown:function(obj){
-this.selected=obj.id==this.id;
-},onAnchorUp:function(obj){
-this.selected=false;
-this.stencil.onTransformEnd(this);
-},onAnchorDrag:function(obj){
-if(this.selected){
-var mx=this.shape.getTransform();
-var pmx=this.shape.getParent().getParent().getTransform();
-var _15=this.defaults.anchors.marginZero;
-var _16=pmx.dx+this.org.x,_17=pmx.dy+this.org.y,x=obj.x-_16;
-y=obj.y-_17;
-s=this.defaults.anchors.minSize;
-var _18,_19,_1a,_1b;
-var chk=this.anchorPositionCheck(x,y,this);
-if(chk.x<0){
-console.warn("X<0 Shift");
-while(this.anchorPositionCheck(x,y,this).x<0){
-this.shape.getParent().getParent().applyTransform({dx:2,dy:0});
-}
-}
-if(chk.y<0){
-console.warn("Y<0 Shift");
-while(this.anchorPositionCheck(x,y,this).y<0){
-this.shape.getParent().getParent().applyTransform({dx:0,dy:2});
-}
-}
-if(this.y_anchor){
-if(this.org.y>this.y_anchor.org.y){
-_1a=this.y_anchor.point.y+s-this.org.y;
-_1b=Infinity;
-if(y<_1a){
-y=_1a;
-}
-}else{
-_1a=-_17+_15;
-_1b=this.y_anchor.point.y-s-this.org.y;
-if(y<_1a){
-y=_1a;
-}else{
-if(y>_1b){
-y=_1b;
-}
-}
-}
-}else{
-_1a=-_17+_15;
-if(y<_1a){
-y=_1a;
-}
-}
-if(this.x_anchor){
-if(this.org.x>this.x_anchor.org.x){
-_18=this.x_anchor.point.x+s-this.org.x;
-_19=Infinity;
-if(x<_18){
-x=_18;
-}
-}else{
-_18=-_16+_15;
-_19=this.x_anchor.point.x-s-this.org.x;
-if(x<_18){
-x=_18;
-}else{
-if(x>_19){
-x=_19;
-}
-}
-}
-}else{
-_18=-_16+_15;
-if(x<_18){
-x=_18;
-}
-}
-this.shape.setTransform({dx:x,dy:y});
-if(this.linkedAnchor){
-this.linkedAnchor.shape.setTransform({dx:x,dy:y});
-}
-this.onTransformPoint(this);
-}
-},anchorPositionCheck:function(x,y,_1c){
-return {x:1,y:1};
-},setPoint:function(mx){
-this.shape.applyTransform(mx);
-},connectMouse:function(){
-this._mouseHandle=this.mouse.register(this);
-},disconnectMouse:function(){
-this.mouse.unregister(this._mouseHandle);
-},reset:function(_1d){
-},destroy:function(){
-dojo.disconnect(this._zCon);
-this.disconnectMouse();
-this.shape.removeShape();
-}});
-}
+dojox.drawing.manager.Anchor = dojox.drawing.util.oo.declare(
+	// summary:
+	//		An anchor point that is attached to (usually) one of the
+	//		corners of a Stencil.
+	//		Used internally.
+	function(/* Object */options){
+		// summary:
+		//		constructor.
+		//		arguments:
+		//			dojox.__stencilArgs plus some additional
+		//			data, like which point this is (pointIdx)
+		//		
+		this.defaults = dojox.drawing.defaults.copy();
+		this.mouse = options.mouse;
+		this.point = options.point;
+		this.pointIdx = options.pointIdx;
+		this.util = options.util;
+		this.id = options.id || this.util.uid("anchor");
+		this.org = dojo.mixin({}, this.point);
+		this.stencil = options.stencil;
+		if(this.stencil.anchorPositionCheck){
+			this.anchorPositionCheck = dojo.hitch(this.stencil, this.stencil.anchorPositionCheck);
+		}
+		if(this.stencil.anchorConstrain){
+			this.anchorConstrain = dojo.hitch(this.stencil, this.stencil.anchorConstrain);
+		}
+		this._zCon = dojo.connect(this.mouse, "setZoom", this, "render");
+		this.render();
+		this.connectMouse();
+	},
+	{
+		y_anchor:null,
+		x_anchor:null,
+		render: function(){
+			// summary:
+			//		Creates the anchor point. Unlike most render methods
+			//		in Drawing, this is only called once.
+			//
+			this.shape && this.shape.removeShape();
+			var d = this.defaults.anchors,
+				z = this.mouse.zoom,
+				b = d.width * z,
+				s = d.size * z,
+				p = s/2,
+				line = {
+					width:b,
+					style:d.style,
+					color:d.color,
+					cap:d.cap
+				};
+			
+	
+			var _r = {
+				x: this.point.x-p,
+				y: this.point.y-p,
+				width: s,
+				height: s
+			};
+			this.shape = this.stencil.container.createRect(_r)
+				.setStroke(line)
+				.setFill(d.fill);
+			
+			this.shape.setTransform({dx:0, dy:0});
+			this.util.attr(this, "drawingType", "anchor");
+			this.util.attr(this, "id", this.id);
+		},
+		onRenderStencil: function(/*Anchor*/anchor){
+			// summary:
+			//		Event fires when an anchor calls a Stencil's render method
+		},
+		onTransformPoint: function(/*Anchor*/anchor){
+			// summary:
+			//		Event fires when an anchor changes the points of a Stencil
+		},
+		onAnchorDown: function(/*Mouse.EventObject*/obj){
+			// summary:
+			//		Event fires for mousedown on anchor 
+			this.selected = obj.id == this.id;
+		},
+		onAnchorUp: function(/*Mouse.EventObject*/obj){
+			// summary:
+			//		Event fires for mouseup on anchor
+			this.selected = false;
+			this.stencil.onTransformEnd(this);
+		},
+		
+		onAnchorDrag: function(/*Mouse.EventObject*/obj){
+			// summary:
+			//		Event fires for on dragging of an anchor
+			if(this.selected){
+				// mx is the original transform from when the anchor
+				// was created. It does not change
+				var mx = this.shape.getTransform();
+				
+				var pmx = this.shape.getParent().getParent().getTransform();
+				
+				var marginZero = this.defaults.anchors.marginZero;
+				
+				var orgx = pmx.dx + this.org.x,
+					orgy = pmx.dy + this.org.y,
+					x = obj.x - orgx,
+					y = obj.y - orgy,
+					s = this.defaults.anchors.minSize;
+				
+				var conL, conR, conT, conB;
+				
+				var chk = this.anchorPositionCheck(x, y, this);
+				if(chk.x<0){
+					console.warn("X<0 Shift");
+					while(this.anchorPositionCheck(x, y, this).x<0){
+						this.shape.getParent().getParent().applyTransform({dx:2, dy:0});
+					}
+				}
+				if(chk.y<0){
+					console.warn("Y<0 Shift");
+					while(this.anchorPositionCheck(x, y, this).y<0){
+						this.shape.getParent().getParent().applyTransform({dx:0, dy:2});
+					}
+				}
+				
+				if(this.y_anchor){
+					// prevent y overlap of opposite anchor
+					if(this.org.y > this.y_anchor.org.y){
+						// bottom anchor
+						
+						conT = this.y_anchor.point.y + s - this.org.y;
+						conB = Infinity;
+						
+						if(y < conT){
+							// overlapping other anchor
+							y = conT;
+						}
+						
+						
+					}else{
+						// top anchor
+						
+						conT = -orgy + marginZero;
+						conB = this.y_anchor.point.y - s - this.org.y;
+						
+						if(y < conT){
+							// less than zero
+							y = conT;
+						}else if(y > conB){
+							// overlapping other anchor
+							y = conB; 
+						}
+					}
+				}else{
+					// Lines - check for zero
+					conT = -orgy + marginZero;
+					if(y < conT){
+						// less than zero
+						y = conT;
+					}
+				}
+				
+				
+				
+				
+				if(this.x_anchor){
+					// prevent x overlap of opposite anchor
+					
+					if(this.org.x>this.x_anchor.org.x){
+						// right anchor
+						
+						conL = this.x_anchor.point.x + s - this.org.x;
+						conR = Infinity;
+						
+						if(x < conL){
+							// overlapping other anchor
+							x = conL;
+						}							
+						
+					}else{
+						// left anchor
+						
+						conL = -orgx + marginZero;
+						conR = this.x_anchor.point.x - s - this.org.x;
+						
+						if(x < conL){
+							x = conL;
+						}else if(x > conR){
+							// overlapping other anchor
+							x = conR; 
+						}
+					}
+				}else{
+					// Lines check for zero
+					conL = -orgx + marginZero;
+					if(x < conL){
+						x = conL;
+					}
+				}
+				//Constrains anchor point, returns null if not overwritten by stencil
+				var constrained = this.anchorConstrain(x, y);
+				if(constrained != null){ 
+					x=constrained.x;
+					y=constrained.y; 
+				}
+				
+				this.shape.setTransform({
+					dx:x,
+					dy:y
+				});
+				if(this.linkedAnchor){
+					// first and last points of a closed-curve-path
+					this.linkedAnchor.shape.setTransform({
+						dx:x,
+						dy:y
+					});
+				}
+				this.onTransformPoint(this);
+			}
+		},
+		
+		anchorConstrain: function(/* Number */x,/* Number */ y){
+			// summary:
+			//		To be over written by tool!
+			//		Add an anchorConstrain method to the tool
+			//		and it will automatically overwrite this stub.
+			//		Should return a constrained x & y value.
+			return null;
+		},
+		
+		anchorPositionCheck: function(/* Number */x,/* Number */ y, /* Anchor */anchor){
+			// summary:
+			//		To be over written by tool!
+			//		Add a anchorPositionCheck method to the tool
+			//		and it will automatically overwrite this stub.
+			//		Should return x and y coords. Success is both
+			//		being greater than zero, fail is if one or both
+			//		are less than zero. 
+			return {x:1, y:1};
+		},
+		
+		setPoint: function(mx){
+			// summary:
+			//		Internal. Sets the Stencil's point
+			this.shape.applyTransform(mx);
+		},
+		
+		connectMouse: function(){
+			// summary:
+			//		Internal. Connects anchor to manager.mouse
+			this._mouseHandle = this.mouse.register(this);
+		},
+		
+		disconnectMouse: function(){
+			// summary:
+			//		Internal. Disconnects anchor to manager.mouse
+			this.mouse.unregister(this._mouseHandle);
+		},
+		
+		reset: function(stencil){
+			// summary:
+			//		Called (usually) from a Stencil when that Stencil
+			//		needed to make modifications to the position of the
+			//		point. Basically used when teh anchor causes a
+			//		less than zero condition.
+		},
+		
+		destroy: function(){
+			// summary:
+			//		Destroys anchor.
+			dojo.disconnect(this._zCon);
+			this.disconnectMouse();
+			this.shape.removeShape();
+		}
+	}
+);
diff --git a/dojox/drawing/manager/Canvas.js b/dojox/drawing/manager/Canvas.js
old mode 100644
new mode 100755
index f97469c..55a0658
--- a/dojox/drawing/manager/Canvas.js
+++ b/dojox/drawing/manager/Canvas.js
@@ -1,87 +1,161 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.manager.Canvas"]){
-dojo._hasResource["dojox.drawing.manager.Canvas"]=true;
 dojo.provide("dojox.drawing.manager.Canvas");
+
 (function(){
-dojox.drawing.manager.Canvas=dojox.drawing.util.oo.declare(function(_1){
-dojo.mixin(this,_1);
-var _2=dojo.contentBox(this.srcRefNode);
-this.height=this.parentHeight=_2.h;
-this.width=this.parentWidth=_2.w;
-this.domNode=dojo.create("div",{id:"canvasNode"},this.srcRefNode);
-dojo.style(this.domNode,{width:this.width,height:"auto"});
-dojo.setSelectable(this.domNode,false);
-this.id=this.id||this.util.uid("surface");
-this.gfxSurface=dojox.gfx.createSurface(this.domNode,this.width,this.height);
-this.gfxSurface.whenLoaded(this,function(){
-setTimeout(dojo.hitch(this,function(){
-this.surfaceReady=true;
-if(dojo.isIE){
-}else{
-if(dojox.gfx.renderer=="silverlight"){
-this.id=this.domNode.firstChild.id;
-}else{
-}
-}
-this.underlay=this.gfxSurface.createGroup();
-this.surface=this.gfxSurface.createGroup();
-this.overlay=this.gfxSurface.createGroup();
-this.surface.setTransform({dx:0,dy:0,xx:1,yy:1});
-this.gfxSurface.getDimensions=dojo.hitch(this.gfxSurface,"getDimensions");
-if(_1.callback){
-_1.callback(this.domNode);
-}
-}),500);
-});
-this._mouseHandle=this.mouse.register(this);
-},{zoom:1,useScrollbars:true,baseClass:"drawingCanvas",resize:function(_3,_4){
-this.parentWidth=_3;
-this.parentHeight=_4;
-this.setDimensions(_3,_4);
-},setDimensions:function(_5,_6,_7,_8){
-var sw=this.getScrollWidth();
-this.width=Math.max(_5,this.parentWidth);
-this.height=Math.max(_6,this.parentHeight);
-if(this.height>this.parentHeight){
-this.width-=sw;
-}
-if(this.width>this.parentWidth){
-this.height-=sw;
-}
-this.gfxSurface.setDimensions(this.width,this.height);
-this.domNode.parentNode.scrollTop=_8||0;
-this.domNode.parentNode.scrollLeft=_7||0;
-if(this.useScrollbars){
-dojo.style(this.domNode.parentNode,{overflowY:this.height>this.parentHeight?"scroll":"hidden",overflowX:this.width>this.parentWidth?"scroll":"hidden"});
-}else{
-dojo.style(this.domNode.parentNode,{overflowY:"hidden",overflowX:"hidden"});
-}
-},setZoom:function(_9){
-this.zoom=_9;
-this.surface.setTransform({xx:_9,yy:_9});
-this.setDimensions(this.width*_9,this.height*_9);
-},onScroll:function(){
-},getScrollOffset:function(){
-return {top:this.domNode.parentNode.scrollTop,left:this.domNode.parentNode.scrollLeft};
-},getScrollWidth:function(){
-var p=dojo.create("div");
-p.innerHTML="<div style=\"width:50px;height:50px;overflow:hidden;position:absolute;top:0px;left:-1000px;\"><div style=\"height:100px;\"></div>";
-var _a=p.firstChild;
-dojo.body().appendChild(_a);
-var _b=dojo.contentBox(_a).h;
-dojo.style(_a,"overflow","scroll");
-var _c=_b-dojo.contentBox(_a).h;
-dojo.destroy(_a);
-this.getScrollWidth=function(){
-return _c;
-};
-return _c;
-}});
-})();
-}
+	
+	dojox.drawing.manager.Canvas = dojox.drawing.util.oo.declare(
+		// summary:
+		//		Creates a dojox.gfx.surface to be used for Drawing. Note that
+		//		The 'surface' that Drawing uses is actually a dojox.gfx.group.
+		//		This allows for more versatility.
+		//
+		//		Called internally from a dojox.Drawing.
+		//	
+		//		Note: Surface creation is asynchrous. Connect to
+		//  		onSurfaceReady in Drawing.
+		//
+		function(/*Object*/options){
+			dojo.mixin(this, options);
+			
+			var dim = dojo.contentBox(this.srcRefNode);
+			this.height = this.parentHeight = dim.h;
+			this.width = this.parentWidth = dim.w;
+			this.domNode = dojo.create("div", {id:"canvasNode"}, this.srcRefNode);
+			dojo.style(this.domNode, {
+				width:this.width,
+				height:"auto"
+			});
+			
+			dojo.setSelectable(this.domNode, false);
+			
+			this.id = this.id || this.util.uid("surface");
+			
+			console.info("create canvas");
+			this.gfxSurface = dojox.gfx.createSurface(this.domNode, this.width, this.height);
+			this.gfxSurface.whenLoaded(this, function(){
+				setTimeout(dojo.hitch(this, function(){
+					this.surfaceReady = true;
+					if(dojo.isIE){
+						//this.gfxSurface.rawNode.parentNode.id = this.id;
+					}else if(dojox.gfx.renderer == "silverlight"){
+						this.id = this.domNode.firstChild.id
+					}else{
+						//this.gfxSurface.rawNode.id = this.id;
+					}
+					
+					this.underlay = this.gfxSurface.createGroup();
+					this.surface = this.gfxSurface.createGroup();
+					this.overlay = this.gfxSurface.createGroup();
+					this.surface.setTransform({dx:0, dy:0,xx:1,yy:1});
+					
+					this.gfxSurface.getDimensions = dojo.hitch(this.gfxSurface, "getDimensions");
+					if(options.callback){
+						options.callback(this.domNode);
+					}
+				}),500);
+			});
+			this._mouseHandle = this.mouse.register(this);
+		},
+		{
+			// zoom: [readonly] Number
+			//	The amount the canvas is zoomed
+			zoom:1,
+						
+			useScrollbars: true,
+			baseClass:"drawingCanvas",
+			
+			resize: function(width, height){
+				// summary:
+				//		Method used to change size of canvas. Potentially
+				//		called from a container like ContentPane. May be
+				//		called directly.
+				//	
+				this.parentWidth = width;
+				this.parentHeight = height;
+				this.setDimensions(width, height);
+			},
+			
+			setDimensions: function(width, height, scrollx, scrolly){
+				// summary:
+				//		Internal. Changes canvas size and sets scroll position.
+				//		Do not call this, use resize().
+				//
+				// changing the size of the surface and setting scroll
+				// if items are off screen
+				var sw = this.getScrollWidth(); //+ 10;
+				this.width = Math.max(width, this.parentWidth);
+				this.height = Math.max(height, this.parentHeight);
+				
+				if(this.height>this.parentHeight){
+					this.width -= sw;
+				}
+				if(this.width>this.parentWidth){
+					this.height -= sw;
+				}
+				
+				this.mouse.resize(this.width,this.height);
+				this.gfxSurface.setDimensions(this.width, this.height);
+
+			
+				this.domNode.parentNode.scrollTop = scrolly || 0;
+				this.domNode.parentNode.scrollLeft = scrollx || 0;
+				
+				
+				if(this.useScrollbars){
+					//console.info("Set Canvas Scroll", (this.height > this.parentHeight), this.height, this.parentHeight)
+					dojo.style(this.domNode.parentNode, {
+						overflowY: this.height > this.parentHeight ? "scroll" : "hidden",
+						overflowX: this.width > this.parentWidth ? "scroll" : "hidden"
+					});
+				}else{
+					dojo.style(this.domNode.parentNode, {
+						overflowY: "hidden",
+						overflowX: "hidden"
+					});
+				}
+			},
+			
+			
+			setZoom: function(zoom){
+				// summary:
+				//		Internal. Zooms canvas in and out.
+				this.zoom = zoom;
+				this.surface.setTransform({xx:zoom, yy:zoom});
+				this.setDimensions(this.width*zoom, this.height*zoom)
+			},
+			
+			onScroll: function(){
+				// summary:
+				//		Event fires on scroll.NOT IMPLEMENTED
+			},
+			
+			getScrollOffset: function(){
+				// summary:
+				//		Get the scroll position of the canvas
+				return {
+					top:this.domNode.parentNode.scrollTop,
+					left:this.domNode.parentNode.scrollLeft		
+				}; // Object
+			},
+			
+			getScrollWidth: function(){
+				// summary:
+				//		Special method used to detect the width (and height)
+				// 		of the browser scrollbars. Becomes memoized.
+				//
+				var p = dojo.create('div');
+				p.innerHTML = '<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:0;left:-1000px;"><div style="height:100px;"></div>';
+				var div = p.firstChild;
+				dojo.body().appendChild(div);
+				var noscroll = dojo.contentBox(div).h;
+				dojo.style(div, "overflow", "scroll");
+				var scrollWidth = noscroll - dojo.contentBox(div).h;
+				dojo.destroy(div);
+				this.getScrollWidth = function(){
+					return scrollWidth;
+				};
+				return scrollWidth; // Object
+			}
+		}
+	);
+	
+})();
\ No newline at end of file
diff --git a/dojox/drawing/manager/Mouse.js b/dojox/drawing/manager/Mouse.js
old mode 100644
new mode 100755
index cc56123..98a63fc
--- a/dojox/drawing/manager/Mouse.js
+++ b/dojox/drawing/manager/Mouse.js
@@ -1,195 +1,507 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.manager.Mouse");
 
+dojox.drawing.manager.Mouse = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Master object (instance) that tracks mouse
+	//		events. A new instance is created for each
+	//		Drawing object.
+	// description:
+	//		You could connect to any method or event in this
+	//		class, but it is designed to have the object
+	//		'registered'. All objects with the current event
+	//		will be called directly.
+	//
+	//		Custom events are used often. In addition to
+	//		standard events onDown, onUp, onDrag, etc, if
+	//		a certain object is clicked upon (or dragged, etc),
+	//		that object's drawingType will create the custom event,
+	//		such as onAnchorDown, or onStencilDown.
+	//
+	function(/* Object */options){
+		this.util = options.util;
+		this.keys = options.keys;
+		this.id = options.id || this.util.uid("mouse");
+		this.currentNodeId = "";
+		this.registered = {};
+	},
+	
+	{
+		// doublClickSpeed: Number
+		//		Milliseconds between clicks to
+		//		register as for onDoubleClick
+		doublClickSpeed:400,
+		
+		// private properties
+		
+		_lastx:0,
+		_lasty:0,
+		__reg:0,
+		_downOnCanvas:false,
+		
+/*=====
+CustomEventMethod: function(){
+	// summary:
+	//		The custom event method that an Object that has
+	//		registered with manager.Mouse can receive.
+	//		Can contain any or all of the following methods
+	//		and they will be called as mouse events. All events
+	//		will be sent a EventObject event object.
+	//	NOTE:
+	//		Events happen anywhere in the document unless
+	//		otherwise noted.
+	//
+	//	onMove
+	//		Fires on mousemove when mouse is up
+	//	onDown
+	//		Fires on mousedown *on the canvas*
+	//	onDrag
+	//		Fires on mousemove when mouse is down
+	//	onUp
+	//		Fires on mouseup, anywhere in the document
+	//	onStencilDown
+	//		Fired on mousedown on a Stencil
+	//	onStencilDrag
+	//		Fired when mouse moves and mose is down on a Stencil
+	//	onStencilUp
+	//		Fired on mouseup off of a Stencil
+	//	on[Custom]Up|Down|Move
+	//		Custom events can bet set and fired by setting a
+	//		different drawingType on a Stencil, or by calling
+	//		setEventMode(customEventName)
+},
+EventObject: function(){
+	// summary:
+	//		The custom event object that is sent to registered objects
+	//		and their respective methods.
+	//	NOTE: Most event objects are the same with the exception
+	//		of the onDown events, which have fewer.
+	//
+	// All event properties included onDown:
+	//
+	//	id: String
+	//		Id of the focused object
+	//	pageX: Number
+	//		The X coordinate of the mouse from the left side of
+	//		the document.
+	//	pageY: Number
+	//		The Y coordinate of the mouse from the top of
+	//		the document.
+	//	x:	Number
+	//		The X coordinate of the mouse from the left side
+	//		of the canvas
+	//	y:	Number
+	//		The Y coordinate of the mouse from the top
+	//		of the canvas
+	//
+	// These event properties are *not* in onDown:
+	//
+	//	last:	Object
+	//		The x and y coordinates of the last mousemove
+	//		relative to the canvas
+	//	move: Object
+	//		The x and y amounts the mouse moved since the last event
+	//	orgX:	Number
+	//		The left side of the canvas from the side of the document
+	//	orgY:	Number
+	//		The top of the canvas from the top of the document
+	//	scroll: Object
+	//		The 'top' and 'left' scroll amounts of the canvas.
+	//	start:	Object
+	//		The x and y coordinates of the mousedown event
+	//	withinCanvas: Boolean
+	//		Whether the event happened within the Canvas or not
+	
+},
+=====*/
+			
+		init: function(/* HTMLNode*/node){
+			//	summary:
+			//		Internal. Initializes mouse.
+			//
+			this.container = node;
+			this.setCanvas();
+			var c;
+			var _isDown = false;
+			dojo.connect(this.container, "rightclick", this, function(evt){
+				console.warn("RIGHTCLICK")
+			});
+			
+			dojo.connect(document.body, "mousedown", this, function(evt){
+				//evt.preventDefault();
+				//dojo.stopEvent(evt);
+			});
+			
+			dojo.connect(this.container, "mousedown", this, function(evt){
+				this.down(evt);
+				_isDown = true;
+				c = dojo.connect(document, "mousemove", this, "drag");
+			});
+			dojo.connect(document, "mouseup", this, function(evt){
+				dojo.disconnect(c);
+				_isDown = false;
+				this.up(evt);
+			});
+			dojo.connect(document, "mousemove", this, function(evt){
+				if(!_isDown){
+					this.move(evt);
+				}
+			});
+			dojo.connect(this.keys, "onEsc", this, function(evt){
+				this._dragged = false;	
+			});
+		},
+		
+		setCanvas: function(){
+			// summary:
+			//		Internal. Sets canvas position
+			var pos = dojo.coords(this.container.parentNode);
+			this.origin = dojo.clone(pos);
+		},
+		
+		scrollOffset: function(){
+			// summary:
+			// 	Gets scroll offset of canvas
+			return {
+				top:this.container.parentNode.scrollTop,
+				left:this.container.parentNode.scrollLeft		
+			}; // Object
+		},
 
-if(!dojo._hasResource["dojox.drawing.manager.Mouse"]){
-dojo._hasResource["dojox.drawing.manager.Mouse"]=true;
-dojo.provide("dojox.drawing.manager.Mouse");
-dojox.drawing.manager.Mouse=dojox.drawing.util.oo.declare(function(_1){
-this.util=_1.util;
-this.keys=_1.keys;
-this.id=_1.id||this.util.uid("mouse");
-this.currentNodeId="";
-this.registered={};
-},{doublClickSpeed:400,_lastx:0,_lasty:0,__reg:0,_downOnCanvas:false,init:function(_2){
-this.container=_2;
-this.setCanvas();
-var c;
-var _3=false;
-dojo.connect(this.container,"rightclick",this,function(_4){
-console.warn("RIGHTCLICK");
-});
-dojo.connect(document.body,"mousedown",this,function(_5){
-});
-dojo.connect(this.container,"mousedown",this,function(_6){
-this.down(_6);
-_3=true;
-c=dojo.connect(document,"mousemove",this,"drag");
-});
-dojo.connect(document,"mouseup",this,function(_7){
-dojo.disconnect(c);
-_3=false;
-this.up(_7);
-});
-dojo.connect(document,"mousemove",this,function(_8){
-if(!_3){
-this.move(_8);
-}
-});
-dojo.connect(this.keys,"onEsc",this,function(_9){
-this._dragged=false;
-});
-},setCanvas:function(){
-var _a=dojo.coords(this.container.parentNode);
-this.origin=dojo.clone(_a);
-},scrollOffset:function(){
-return {top:this.container.parentNode.scrollTop,left:this.container.parentNode.scrollLeft};
-},register:function(_b){
-var _c=_b.id||"reg_"+(this.__reg++);
-if(!this.registered[_c]){
-this.registered[_c]=_b;
-}
-return _c;
-},unregister:function(_d){
-if(!this.registered[_d]){
-return;
-}
-delete this.registered[_d];
-},_broadcastEvent:function(_e,_f){
-for(var nm in this.registered){
-if(this.registered[nm][_e]){
-this.registered[nm][_e](_f);
-}
-}
-},onDown:function(obj){
-this._broadcastEvent(this.eventName("down"),obj);
-},onDrag:function(obj){
-var nm=this.eventName("drag");
-if(this._selected&&nm=="onDrag"){
-nm="onStencilDrag";
-}
-this._broadcastEvent(nm,obj);
-},onMove:function(obj){
-this._broadcastEvent("onMove",obj);
-},onOver:function(obj){
-this._broadcastEvent("onOver",obj);
-},onOut:function(obj){
-this._broadcastEvent("onOut",obj);
-},onUp:function(obj){
-var nm=this.eventName("up");
-if(nm=="onStencilUp"){
-this._selected=true;
-}else{
-if(this._selected&&nm=="onUp"){
-nm="onStencilUp";
-this._selected=false;
-}
-}
-this._broadcastEvent(nm,obj);
-if(dojox.gfx.renderer=="silverlight"){
-return;
-}
-this._clickTime=new Date().getTime();
-if(this._lastClickTime){
-if(this._clickTime-this._lastClickTime<this.doublClickSpeed){
-var dnm=this.eventName("doubleClick");
-console.warn("DOUBLE CLICK",dnm,obj);
-this._broadcastEvent(dnm,obj);
-}else{
-}
-}
-this._lastClickTime=this._clickTime;
-},zoom:1,setZoom:function(_10){
-this.zoom=1/_10;
-},setEventMode:function(_11){
-this.mode=_11?"on"+_11.charAt(0).toUpperCase()+_11.substring(1):"";
-},eventName:function(_12){
-_12=_12.charAt(0).toUpperCase()+_12.substring(1);
-if(this.mode){
-if(this.mode=="onPathEdit"){
-return "on"+_12;
-}
-if(this.mode=="onUI"){
-}
-return this.mode+_12;
-}else{
-var dt=!this.drawingType||this.drawingType=="surface"||this.drawingType=="canvas"?"":this.drawingType;
-var t=!dt?"":dt.charAt(0).toUpperCase()+dt.substring(1);
-return "on"+t+_12;
-}
-},up:function(evt){
-this.onUp(this.create(evt));
-},down:function(evt){
-evt.preventDefault();
-dojo.stopEvent(evt);
-this._downOnCanvas=true;
-var sc=this.scrollOffset();
-var dim=this._getXY(evt);
-this._lastpagex=dim.x;
-this._lastpagey=dim.y;
-var o=this.origin;
-var x=dim.x-o.x;
-var y=dim.y-o.y;
-x*=this.zoom;
-y*=this.zoom;
-x+=sc.left*this.zoom;
-y+=sc.top*this.zoom;
-var _13=x>=0&&y>=0&&x<=o.w&&y<=o.h;
-o.startx=x;
-o.starty=y;
-this._lastx=x;
-this._lasty=y;
-this.drawingType=this.util.attr(evt,"drawingType")||"";
-var id=this._getId(evt);
-this.onDown({mid:this.id,x:x,y:y,pageX:dim.x,pageY:dim.y,withinCanvas:_13,id:id});
-},over:function(obj){
-this.onOver(obj);
-},out:function(obj){
-this.onOut(obj);
-},move:function(evt){
-var obj=this.create(evt);
-if(this.id=="MUI"){
-}
-if(obj.id!=this.currentNodeId){
-var _14={};
-for(var nm in obj){
-_14[nm]=obj[nm];
-}
-_14.id=this.currentNodeId;
-this.currentNodeId&&this.out(_14);
-obj.id&&this.over(obj);
-this.currentNodeId=obj.id;
-}
-this.onMove(obj);
-},drag:function(evt){
-this.onDrag(this.create(evt,true));
-},create:function(evt,_15){
-var sc=this.scrollOffset();
-var dim=this._getXY(evt);
-var _16=dim.x;
-var _17=dim.y;
-var x=dim.x-this.origin.x;
-var y=dim.y-this.origin.y;
-var o=this.origin;
-x+=sc.left;
-y+=sc.top;
-x*=this.zoom;
-y*=this.zoom;
-var _18=x>=0&&y>=0&&x<=o.w&&y<=o.h;
-var id=_18?this._getId(evt,_15):"";
-var ret={mid:this.id,x:x,y:y,pageX:dim.x,pageY:dim.y,page:{x:dim.x,y:dim.y},orgX:o.x,orgY:o.y,last:{x:this._lastx,y:this._lasty},start:{x:this.origin.startx,y:this.origin.starty},move:{x:_16-this._lastpagex,y:_17-this._lastpagey},scroll:sc,id:id,withinCanvas:_18};
-this._lastx=x;
-this._lasty=y;
-this._lastpagex=_16;
-this._lastpagey=_17;
-dojo.stopEvent(evt);
-return ret;
-},_getId:function(evt,_19){
-return this.util.attr(evt,"id",null,_19);
-},_getXY:function(evt){
-return {x:evt.pageX,y:evt.pageY};
-}});
-}
+		resize: function(width,height){
+			if(this.origin){
+				this.origin.w=width;
+				this.origin.h=height;
+			}
+		},
+
+		register: function(/* Object*/scope){
+			// summary:
+			//		All objects (Stencils) should register here if they
+			//		use mouse events. When registering, the object will
+			//		be called if it has that method.
+			//	argument:
+			//		The object to be called
+			//	Returns: handle
+			//		Keep the handle to be used for disconnection.
+			// See: CustomEventMethod and EventObject
+			//
+			var handle = scope.id || "reg_"+(this.__reg++);
+			if(!this.registered[handle]){ this.registered[handle] = scope; }
+			return handle; // String
+		},
+		unregister: function(handle){
+			// summary:
+			// 		Disconnects object. Mouse events are no longer
+			//		called for it.
+			if(!this.registered[handle]){ return; }
+			delete this.registered[handle];
+		},
+		
+		_broadcastEvent:function(strEvt, obj){
+			// summary:
+			//		Fire events to all registered objects.
+			//
+			//console.log("mouse.broadcast:", strEvt, obj)
+			for(var nm in this.registered){
+				if(this.registered[nm][strEvt]) this.registered[nm][strEvt](obj);
+			}
+		},
+		
+		onDown: function(obj){
+			// summary:
+			// 		Create on[xx]Down event and send to broadcaster.
+			//		Could be connected to.
+			//console.info("onDown:", this.eventName("down"))
+			this._broadcastEvent(this.eventName("down"), obj);			
+		},
+		
+		onDrag: function(obj){
+			// summary:
+			// 		Create on[xx]Drag event and send to broadcaster.
+			//		Could be connected to.
+			//
+			var nm = this.eventName("drag");
+			if(this._selected && nm == "onDrag"){
+				nm = "onStencilDrag"
+			}
+			this._broadcastEvent(nm, obj);
+		},
+		
+		onMove: function(obj){
+			// summary:
+			// 		Create onMove event and send to broadcaster.
+			//		Could be connected to.
+			//		Note: onMove never uses a custom event
+			//		Note: onMove is currently not enabled in the app.
+			//
+			this._broadcastEvent("onMove", obj);
+		},
+		
+		overName: function(obj,evt){
+			var nm = obj.id.split(".");
+			evt = evt.charAt(0).toUpperCase() + evt.substring(1);
+			if(nm[0] == "dojox" && (dojox.drawing.defaults.clickable || !dojox.drawing.defaults.clickMode)){
+				return "onStencil"+evt;	
+			}else{
+				return "on"+evt;	
+			}
+			
+		},
+		
+		onOver: function(obj){
+			// summary:
+			//
+			this._broadcastEvent(this.overName(obj,"over"), obj);
+		},
+		
+		onOut: function(obj){
+			// summary:
+			//
+			this._broadcastEvent(this.overName(obj,"out"), obj);
+		},
+		
+		onUp: function(obj){
+			// summary:
+			// 		Create on[xx]Up event and send to broadcaster.
+			//		Could be connected to.
+			//
+			// 	blocking first click-off (deselect), largely for TextBlock
+			// 	TODO: should have param to make this optional?
+			var nm = this.eventName("up");
+			
+			if(nm == "onStencilUp"){
+				this._selected  = true;
+			}else if(this._selected && nm == "onUp"){ //////////////////////////////////////////
+				nm = "onStencilUp";
+				this._selected = false;
+			}
+			
+			console.info("Up Event:", this.id, nm, "id:", obj.id);
+			this._broadcastEvent(nm, obj);
+			
+			// Silverlight double-click handled in Silverlight class
+			if(dojox.gfx.renderer == "silverlight"){ return; }
+			
+			// Check Double Click
+			// If a double click is detected, the onDoubleClick event fires,
+			// but does not replace the normal event. They both fire.
+			this._clickTime = new Date().getTime();
+			if(this._lastClickTime){
+				if(this._clickTime-this._lastClickTime<this.doublClickSpeed){
+					var dnm = this.eventName("doubleClick");
+					console.warn("DOUBLE CLICK", dnm, obj);
+					this._broadcastEvent(dnm, obj);
+				}else{
+					//console.log("    slow:", this._clickTime-this._lastClickTime)
+				}
+			}
+			this._lastClickTime = this._clickTime;
+			
+		},
+		
+		zoom: 1,
+		setZoom: function(zoom){
+			// summary:
+			// 		Internal. Sets the mouse zoom percentage to
+			//		that of the canvas
+			this.zoom = 1/zoom;
+		},
+		
+		setEventMode: function(mode){
+			// summary:
+			//		Sets the mouse mode s that custom events can be called.
+			//		Also can 'disable' events by using a bogus mode:
+			// 		|	mouse.setEventMode("DISABLED")
+			//		(unless any object subscribes to this event,
+			//		it is effectively disabled)
+			//
+			this.mode = mode ? "on" + mode.charAt(0).toUpperCase() + mode.substring(1) :  "";
+		},
+		
+		eventName: function(name){
+			// summary:
+			//		Internal. Determine the event name
+			//
+			name = name.charAt(0).toUpperCase() + name.substring(1);
+			if(this.mode){
+				if(this.mode == "onPathEdit"){
+					return "on"+name;
+				}
+				if(this.mode == "onUI"){
+					//return "on"+name;
+				}
+				return this.mode + name;
+			}else{
+				//Allow a mode where stencils aren't clickable
+				if(!dojox.drawing.defaults.clickable && dojox.drawing.defaults.clickMode){return "on"+name;}
+				var dt = !this.drawingType || this.drawingType=="surface" || this.drawingType=="canvas" ? "" : this.drawingType;
+				var t = !dt ? "" : dt.charAt(0).toUpperCase() + dt.substring(1);
+				return "on"+t+name;
+			}
+		},
+		
+		up: function(evt){
+			// summary:
+			//		Internal. Create onUp event
+			//
+			this.onUp(this.create(evt));
+		},
+		
+		down: function(evt){
+			// summary:
+			//		Internal. Create onDown event
+			//
+			evt.preventDefault();
+			dojo.stopEvent(evt);
+			
+			this._downOnCanvas = true;
+			var sc = this.scrollOffset();
+			var dim = this._getXY(evt);
+			this._lastpagex = dim.x;
+			this._lastpagey = dim.y;
+			var o = this.origin;
+			var x = dim.x - o.x + sc.left;
+			var y = dim.y - o.y + sc.top;
+			
+			var withinCanvas = x>=0 && y>=0 && x<=o.w && y<=o.h;
+			x*= this.zoom;
+			y*= this.zoom;
+			
+			o.startx = x;
+			o.starty = y;
+			this._lastx = x;
+			this._lasty = y;
+			
+			this.drawingType = this.util.attr(evt, "drawingType") || "";
+			var id = this._getId(evt);
+			//console.log("DOWN:", this.id, id, withinCanvas);
+			//console.log("this.drawingType:", this.drawingType);
+			this.onDown({
+				mid:this.id,
+				x:x,
+				y:y,
+				pageX:dim.x,
+				pageY:dim.y,
+				withinCanvas:withinCanvas,
+				id:id
+			});
+			
+		},
+		over: function(obj){
+			// summary:
+			//		Internal.
+			//
+			this.onOver(obj);
+		},
+		out: function(obj){
+			// summary:
+			//		Internal.
+			//
+			this.onOut(obj);
+		},
+		move: function(evt){
+			// summary:
+			//		Internal.
+			//
+			var obj = this.create(evt);
+			if(this.id=="MUI"){
+				//console.log("obj.id:", obj.id, "was:", this.currentNodeId)
+			}
+			if(obj.id != this.currentNodeId){
+				// TODO: I wonder if an ID is good enough
+				//	that would avoid the mixin
+				var outObj = {};
+				for(var nm in obj){
+					outObj[nm] = obj[nm];
+				}
+				outObj.id = this.currentNodeId;
+				this.currentNodeId && this.out(outObj);
+				obj.id && this.over(obj);
+				this.currentNodeId = obj.id;
+			}
+			this.onMove(obj);
+		},
+		drag: function(evt){
+			// summary:
+			//		Internal. Create onDrag event
+			this.onDrag(this.create(evt, true));
+		},
+		create: function(evt, squelchErrors){
+			// summary:
+			//		Internal. Create EventObject
+			//
+			var sc = this.scrollOffset();
+			var dim = this._getXY(evt);
+			
+			var pagex = dim.x;
+			var pagey = dim.y;
+			
+			var o = this.origin;
+			var x = dim.x - o.x + sc.left;
+			var y = dim.y - o.y + sc.top;
+
+			var withinCanvas = x>=0 && y>=0 && x<=o.w && y<=o.h;
+			x*= this.zoom;
+			y*= this.zoom;
+			
+			var id = withinCanvas ? this._getId(evt, squelchErrors) : "";
+			var ret = {
+				mid:this.id,
+				x:x,
+				y:y,
+				pageX:dim.x,
+				pageY:dim.y,
+				page:{
+					x:dim.x,
+					y:dim.y
+				},
+				orgX:o.x,
+				orgY:o.y,
+				last:{
+					x: this._lastx,
+					y: this._lasty
+				},
+				start:{
+					x: this.origin.startx, //+ sc.left,
+					y: this.origin.starty //+ sc.top
+				},
+				move:{
+					x:pagex - this._lastpagex,
+					y:pagey - this._lastpagey
+				},
+				scroll:sc,
+				id:id,
+				withinCanvas:withinCanvas
+			};
+			
+			//console.warn("MSE LAST:", x-this._lastx, y-this._lasty)
+			this._lastx = x;
+			this._lasty = y;
+			this._lastpagex = pagex;
+			this._lastpagey = pagey;
+			dojo.stopEvent(evt);
+			return ret; //Object
+		},
+		_getId: function(evt, squelchErrors){
+			// summary:
+			//		Internal. Gets ID of focused node.
+			return this.util.attr(evt, "id", null, squelchErrors); // String
+		},
+		_getXY: function(evt){
+			// summary:
+			//		Internal. Gets mouse coords to page.
+			return {x:evt.pageX, y:evt.pageY}; // Object
+		},
+		
+		setCursor: function(cursor,/* HTMLNode*/node){
+			// summary:
+			//		Sets the cursor for  a given node.  If no
+			//		node is specified the containing node is used.
+			if(!node){ 
+				dojo.style(this.container, "cursor", cursor); 
+			}else{
+				dojo.style(node, "cursor", cursor);
+			}
+		}
+	}
+);
diff --git a/dojox/drawing/manager/Stencil.js b/dojox/drawing/manager/Stencil.js
old mode 100644
new mode 100755
index 3495677..76a9b5c
--- a/dojox/drawing/manager/Stencil.js
+++ b/dojox/drawing/manager/Stencil.js
@@ -1,312 +1,597 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.manager.Stencil"]){
-dojo._hasResource["dojox.drawing.manager.Stencil"]=true;
 dojo.provide("dojox.drawing.manager.Stencil");
+
 (function(){
-var _1,_2;
-dojox.drawing.manager.Stencil=dojox.drawing.util.oo.declare(function(_3){
-_1=_3.surface;
-this.canvas=_3.canvas;
-this.defaults=dojox.drawing.defaults.copy();
-this.undo=_3.undo;
-this.mouse=_3.mouse;
-this.keys=_3.keys;
-this.anchors=_3.anchors;
-this.stencils={};
-this.selectedStencils={};
-this._mouseHandle=this.mouse.register(this);
-dojo.connect(this.keys,"onArrow",this,"onArrow");
-dojo.connect(this.keys,"onEsc",this,"deselect");
-dojo.connect(this.keys,"onDelete",this,"onDelete");
-},{_dragBegun:false,_wasDragged:false,_secondClick:false,_isBusy:false,register:function(_4){
-if(_4.isText&&!_4.editMode&&_4.deleteEmptyCreate&&!_4.getText()){
-console.warn("EMPTY CREATE DELETE",_4);
-_4.destroy();
-return false;
-}
-this.stencils[_4.id]=_4;
-if(_4.execText){
-if(_4._text&&!_4.editMode){
-this.selectItem(_4);
-}
-_4.connect("execText",this,function(){
-if(_4.isText&&_4.deleteEmptyModify&&!_4.getText()){
-console.warn("EMPTY MOD DELETE",_4);
-this.deleteItem(_4);
-}else{
-if(_4.selectOnExec){
-this.selectItem(_4);
-}
-}
-});
-}
-_4.connect("deselect",this,function(){
-if(!this._isBusy&&this.isSelected(_4)){
-this.deselectItem(_4);
-}
-});
-_4.connect("select",this,function(){
-if(!this._isBusy&&!this.isSelected(_4)){
-this.selectItem(_4);
-}
-});
-return _4;
-},unregister:function(_5){
-if(_5){
-_5.selected&&this.onDeselect(_5);
-delete this.stencils[_5.id];
-}
-},onArrow:function(_6){
-if(this.hasSelected()){
-this.saveThrottledState();
-this.group.applyTransform({dx:_6.x,dy:_6.y});
-}
-},_throttleVrl:null,_throttle:false,throttleTime:400,_lastmxx:-1,_lastmxy:-1,saveMoveState:function(){
-var mx=this.group.getTransform();
-if(mx.dx==this._lastmxx&&mx.dy==this._lastmxy){
-return;
-}
-this._lastmxx=mx.dx;
-this._lastmxy=mx.dy;
-this.undo.add({before:dojo.hitch(this.group,"setTransform",mx)});
-},saveThrottledState:function(){
-clearTimeout(this._throttleVrl);
-clearInterval(this._throttleVrl);
-this._throttleVrl=setTimeout(dojo.hitch(this,function(){
-this._throttle=false;
-this.saveMoveState();
-}),this.throttleTime);
-if(this._throttle){
-return;
-}
-this._throttle=true;
-this.saveMoveState();
-},unDelete:function(_7){
-for(var s in _7){
-_7[s].render();
-this.onSelect(_7[s]);
-}
-},onDelete:function(_8){
-if(_8!==true){
-this.undo.add({before:dojo.hitch(this,"unDelete",this.selectedStencils),after:dojo.hitch(this,"onDelete",true)});
-}
-this.withSelected(function(m){
-this.anchors.remove(m);
-var id=m.id;
-m.destroy();
-delete this.stencils[id];
-});
-this.selectedStencils={};
-},deleteItem:function(_9){
-if(this.hasSelected()){
-var _a=[];
-for(var m in this.selectedStencils){
-if(this.selectedStencils.id==_9.id){
-if(this.hasSelected()==1){
-this.onDelete();
-return;
-}
-}else{
-_a.push(this.selectedStencils.id);
-}
-}
-this.deselect();
-this.selectItem(_9);
-this.onDelete();
-dojo.forEach(_a,function(id){
-this.selectItem(id);
-},this);
-}else{
-this.selectItem(_9);
-this.onDelete();
-}
-},removeAll:function(){
-this.selectAll();
-this._isBusy=true;
-this.onDelete();
-this.stencils={};
-this._isBusy=false;
-},setSelectionGroup:function(){
-this.withSelected(function(m){
-this.onDeselect(m,true);
-});
-if(this.group){
-_1.remove(this.group);
-this.group.removeShape();
-}
-this.group=_1.createGroup();
-this.group.setTransform({dx:0,dy:0});
-this.withSelected(function(m){
-this.group.add(m.container);
-m.select();
-});
-},setConstraint:function(){
-var t=Infinity;
-l=Infinity;
-this.withSelected(function(m){
-var o=m.getBounds();
-t=Math.min(o.y1,t);
-l=Math.min(o.x1,l);
-});
-this.constrain={l:-l,t:-t};
-},onDeselect:function(_b,_c){
-if(!_c){
-delete this.selectedStencils[_b.id];
-}
-this.anchors.remove(_b);
-_1.add(_b.container);
-_b.selected&&_b.deselect();
-_b.applyTransform(this.group.getTransform());
-},deselectItem:function(_d){
-this.onDeselect(_d);
-},deselect:function(){
-this.withSelected(function(m){
-this.onDeselect(m);
-});
-this._dragBegun=false;
-this._wasDragged=false;
-},onSelect:function(_e){
-if(!_e){
-console.error("null stencil is not selected:",this.stencils);
-}
-if(this.selectedStencils[_e.id]){
-return;
-}
-this.selectedStencils[_e.id]=_e;
-this.group.add(_e.container);
-_e.select();
-if(this.hasSelected()==1){
-this.anchors.add(_e,this.group);
-}
-},selectAll:function(){
-this._isBusy=true;
-for(var m in this.stencils){
-this.selectItem(m);
-}
-this._isBusy=false;
-},selectItem:function(_f){
-var id=typeof (_f)=="string"?_f:_f.id;
-var _10=this.stencils[id];
-this.setSelectionGroup();
-this.onSelect(_10);
-this.group.moveToFront();
-this.setConstraint();
-},onStencilDoubleClick:function(obj){
-if(this.selectedStencils[obj.id]){
-if(this.selectedStencils[obj.id].edit){
-var m=this.selectedStencils[obj.id];
-m.editMode=true;
-this.deselect();
-m.edit();
-}
-}
-},onAnchorUp:function(){
-this.setConstraint();
-},onStencilDown:function(obj,evt){
-if(!this.stencils[obj.id]){
-return;
-}
-this._isBusy=true;
-if(this.selectedStencils[obj.id]&&this.keys.meta){
-if(dojo.isMac&&this.keys.cmmd){
-}
-this.onDeselect(this.selectedStencils[obj.id]);
-if(this.hasSelected()==1){
-this.withSelected(function(m){
-this.anchors.add(m,this.group);
-});
-}
-this.group.moveToFront();
-this.setConstraint();
-return;
-}else{
-if(this.selectedStencils[obj.id]){
-var mx=this.group.getTransform();
-this._offx=obj.x-mx.dx;
-this._offy=obj.y-mx.dy;
-return;
-}else{
-if(!this.keys.meta){
-this.deselect();
-}else{
-}
-}
-}
-this.selectItem(obj.id);
-var mx=this.group.getTransform();
-this._offx=obj.x-mx.dx;
-this._offy=obj.y-mx.dx;
-this.orgx=obj.x;
-this.orgy=obj.y;
-this._isBusy=false;
-this.undo.add({before:function(){
-},after:function(){
-}});
-},onStencilUp:function(obj){
-},onStencilDrag:function(obj){
-if(!this._dragBegun){
-this.onBeginDrag(obj);
-this._dragBegun=true;
-}else{
-this.saveThrottledState();
-var x=obj.x-obj.last.x,y=obj.y-obj.last.y,mx=this.group.getTransform(),c=this.constrain,mz=this.defaults.anchors.marginZero;
-x=obj.x-this._offx;
-y=obj.y-this._offy;
-if(x<c.l+mz){
-x=c.l+mz;
-}
-if(y<c.t+mz){
-y=c.t+mz;
-}
-this.group.setTransform({dx:x,dy:y});
-}
-},onDragEnd:function(obj){
-this._dragBegun=false;
-},onBeginDrag:function(obj){
-this._wasDragged=true;
-},onDown:function(obj){
-this.deselect();
-},exporter:function(){
-var _11=[];
-for(var m in this.stencils){
-this.stencils[m].enabled&&_11.push(this.stencils[m].exporter());
-}
-return _11;
-},toSelected:function(_12){
-var _13=Array.prototype.slice.call(arguments).splice(1);
-for(var m in this.selectedStencils){
-var _14=this.selectedStencils[m];
-_14[_12].apply(_14,_13);
-}
-},withSelected:function(_15){
-var f=dojo.hitch(this,_15);
-for(var m in this.selectedStencils){
-f(this.selectedStencils[m]);
-}
-},withUnselected:function(_16){
-var f=dojo.hitch(this,_16);
-for(var m in this.stencils){
-!this.stencils[m].selected&&f(this.stencils[m]);
-}
-},withStencils:function(_17){
-var f=dojo.hitch(this,_17);
-for(var m in this.stencils){
-f(this.stencils[m]);
-}
-},hasSelected:function(){
-var ln=0;
-for(var m in this.selectedStencils){
-ln++;
-}
-return ln;
-},isSelected:function(_18){
-return !!this.selectedStencils[_18.id];
-}});
+	var surface, surfaceNode;
+	dojox.drawing.manager.Stencil = dojox.drawing.util.oo.declare(
+		// summary:
+		//		The main class for tracking Stencils that are cretaed, added,
+		//		selected, or deleted. Also handles selections, multiple
+		//		selections, adding and removing from selections, and dragging
+		//		selections. It's this class that triggers the anchors to
+		//		appear on a Stencil and whther there are anchor on a multiple
+		//		select or not (currently not)
+		//
+		function(options){
+			//
+			// TODO: mixin props
+			//
+			surface = options.surface;
+			this.canvas = options.canvas;
+			
+			this.defaults = dojox.drawing.defaults.copy();
+			this.undo = options.undo;
+			this.mouse = options.mouse;
+			this.keys = options.keys;
+			this.anchors = options.anchors;
+			this.stencils = {};
+			this.selectedStencils = {};
+			this._mouseHandle = this.mouse.register(this);
+			
+			dojo.connect(this.keys, "onArrow", this, "onArrow");
+			dojo.connect(this.keys, "onEsc", this, "deselect");
+			dojo.connect(this.keys, "onDelete", this, "onDelete");
+			
+		},
+		{
+			_dragBegun: false,
+			_wasDragged:false,
+			_secondClick:false,
+			_isBusy:false,
+			
+			register: function(/*Object*/stencil){
+				// summary:
+				//		Key method for adding Stencils. Stencils
+				//		can be added to the canvas without adding
+				//		them to this, but they won't have selection
+				//		or drag ability.
+				//
+				console.log("Selection.register ::::::", stencil.id);
+				if(stencil.isText && !stencil.editMode && stencil.deleteEmptyCreate && !stencil.getText()){
+					// created empty text field
+					// defaults say to delete
+					console.warn("EMPTY CREATE DELETE", stencil);
+					stencil.destroy();
+					return false;
+				}
+				
+				this.stencils[stencil.id] = stencil;
+				
+				if(stencil.execText){
+					if(stencil._text && !stencil.editMode){
+						console.log("select text");
+						this.selectItem(stencil);
+					}
+					stencil.connect("execText", this, function(){
+						if(stencil.isText && stencil.deleteEmptyModify && !stencil.getText()){
+							console.warn("EMPTY MOD DELETE", stencil);
+							// text deleted
+							// defaults say to delete
+							this.deleteItem(stencil);
+						}else if(stencil.selectOnExec){
+							this.selectItem(stencil);
+						}
+					});
+				}
+				
+				stencil.connect("deselect", this, function(){
+					if(!this._isBusy && this.isSelected(stencil)){
+						// called from within stencil. do action.
+						this.deselectItem(stencil);
+					}
+				});
+				
+				stencil.connect("select", this, function(){
+					if(!this._isBusy && !this.isSelected(stencil)){
+						// called from within stencil. do action.
+						this.selectItem(stencil);
+					}
+				});
+				
+				return stencil;
+			},
+			unregister: function(/*Object*/stencil){
+				// summary:
+				//		Method for removing Stencils from the manager.
+				//		This doesn't delete them, only removes them from
+				// 		the list.
+				//
+				console.log("Selection.unregister ::::::", stencil.id, "sel:", stencil.selected);
+				if(stencil){
+					stencil.selected && this.onDeselect(stencil);
+					delete this.stencils[stencil.id];
+				}
+			},
+			
+			onArrow: function(/*Key Event*/evt){
+				// summary:
+				// 		Moves selection based on keyboard arrow keys
+				//
+				// FIXME: Check constraints
+				if(this.hasSelected()){
+					this.saveThrottledState();
+					this.group.applyTransform({dx:evt.x, dy: evt.y});
+				}
+			},
+			
+			_throttleVrl:null,
+			_throttle: false,
+			throttleTime:400,
+			_lastmxx:-1,
+			_lastmxy:-1,
+			saveMoveState: function(){
+				// summary:
+				//		Internal. Used for the prototype undo stack.
+				// 		Saves selection position.
+				//
+				var mx = this.group.getTransform();
+				if(mx.dx == this._lastmxx && mx.dy == this._lastmxy){ return; }
+				this._lastmxx = mx.dx;
+				this._lastmxy = mx.dy;
+				//console.warn("SAVE MOVE!", mx.dx, mx.dy);
+				this.undo.add({
+					before:dojo.hitch(this.group, "setTransform", mx)
+				});
+			},
+			
+			saveThrottledState: function(){
+				// summary:
+				//		Internal. Used for the prototype undo stack.
+				//		Prevents an undo point on every mouse move.
+				//		Only does a point when the mouse hesitates.
+				//
+				clearTimeout(this._throttleVrl);
+				clearInterval(this._throttleVrl);
+				this._throttleVrl = setTimeout(dojo.hitch(this, function(){
+					this._throttle = false;
+					this.saveMoveState();
+				}), this.throttleTime);
+				if(this._throttle){ return; }
+				this._throttle = true;
+				
+				this.saveMoveState();					
+				
+			},
+			unDelete: function(/*Array*/stencils){
+				// summary:
+				//		Undeletes a stencil. Used in undo stack.
+				//
+				console.log("unDelete:", stencils);
+				for(var s in stencils){
+					stencils[s].render();
+					this.onSelect(stencils[s]);
+				}
+			},
+			onDelete: function(/*Boolean*/noundo){
+				// summary:
+				//		Event fired on deletion of a stencil
+				//
+				console.log("onDelete", noundo);
+				if(noundo!==true){
+					this.undo.add({
+						before:dojo.hitch(this, "unDelete", this.selectedStencils),
+						after:dojo.hitch(this, "onDelete", true)
+					});
+				}
+				this.withSelected(function(m){
+					this.anchors.remove(m);
+					var id = m.id;
+					console.log("delete:", m);
+					m.destroy();
+					delete this.stencils[id];
+				});
+				this.selectedStencils = {};
+			},
+			
+			deleteItem: function(/*Object*/stencil){
+				// summary:
+				//		Deletes a stencil.
+				//		NOTE: supports limited undo.
+				//
+				// manipulating the selection to fire onDelete properly
+				if(this.hasSelected()){
+					// there is a selection
+					var sids = [];
+					for(var m in this.selectedStencils){
+						if(this.selectedStencils.id == stencil.id){
+							if(this.hasSelected()==1){
+								// the deleting stencil is the only one selected
+								this.onDelete();
+								return;
+							}
+						}else{
+							sids.push(this.selectedStencils.id);
+						}
+					}
+					// remove selection, delete, restore selection
+					this.deselect();
+					this.selectItem(stencil);
+					this.onDelete();
+					dojo.forEach(sids, function(id){
+						this.selectItem(id);
+					}, this);
+				}else{
+					// there is not a selection. select it, delete it
+					this.selectItem(stencil);
+					// now delete selection
+					this.onDelete();
+				}
+			},
+			
+			removeAll: function(){
+				// summary:
+				//		Deletes all Stencils on the canvas.
+				
+				this.selectAll();
+				this._isBusy = true;
+				this.onDelete();
+				this.stencils = {};
+				this._isBusy = false;
+			},
+			
+			setSelectionGroup: function(){
+				// summary:
+				//		Internal. Creates a new selection group
+				//		used to hold selected stencils.
+				//
+				this.withSelected(function(m){
+					this.onDeselect(m, true);
+				});
+				
+				if(this.group){
+					surface.remove(this.group);
+					this.group.removeShape();
+				}
+				this.group = surface.createGroup();
+				this.group.setTransform({dx:0, dy: 0});
+				
+				this.withSelected(function(m){
+					this.group.add(m.container);
+					m.select();
+				});
+			},
+			
+			setConstraint: function(){
+				// summary:
+				//		Internal. Gets all selected stencils' coordinates
+				//		and determines how far left and up the selection
+				//		can go without going below zero
+				//
+				var t = Infinity, l = Infinity;
+				this.withSelected(function(m){
+					var o = m.getBounds();
+					t = Math.min(o.y1, t);
+					l = Math.min(o.x1, l);
+				});
+				this.constrain = {l:-l, t:-t};
+			},
+			
+			
+			
+			onDeselect: function(stencil, keepObject){
+				// summary:
+				//		Event fired on deselection of a stencil
+				//
+				if(!keepObject){
+					delete this.selectedStencils[stencil.id];
+				}
+				//console.log('onDeselect, keep:', keepObject, "stencil:", stencil.type)
+				
+				this.anchors.remove(stencil);
+				
+				surface.add(stencil.container);
+				stencil.selected && stencil.deselect();
+				stencil.applyTransform(this.group.getTransform());
+			},
+			
+			deselectItem: function(/*Object*/stencil){
+				// summary:
+				//		Deselect passed stencil
+				//
+				// note: just keeping with standardized methods
+				this.onDeselect(stencil);
+			},
+			
+			deselect: function(){ // all stencils
+				// summary:
+				//		Deselect all stencils
+				//
+				this.withSelected(function(m){
+					this.onDeselect(m);
+				});
+				this._dragBegun = false;
+				this._wasDragged = false;
+			},
+			
+			onSelect: function(/*Object*/stencil){
+				// summary:
+				//		Event fired on selection of a stencil
+				//
+				//console.log("stencil.onSelect", stencil);
+				if(!stencil){
+					console.error("null stencil is not selected:", this.stencils)
+				}
+				if(this.selectedStencils[stencil.id]){ return; }
+				this.selectedStencils[stencil.id] = stencil;
+				this.group.add(stencil.container);
+				stencil.select();
+				if(this.hasSelected()==1){
+					this.anchors.add(stencil, this.group);
+				}
+			},
+			
+			selectAll: function(){
+				// summary:
+				//		Selects all items
+				this._isBusy = true;
+				for(var m in this.stencils){
+					//if(!this.stencils[m].selected){
+						this.selectItem(m);
+					//}
+				}
+				this._isBusy = false;
+			},
+			
+			selectItem: function(/*String|Object*/ idOrItem){
+				// summary:
+				//		Method used to select a stencil.
+				//
+				var id = typeof(idOrItem)=="string" ? idOrItem : idOrItem.id;
+				var stencil = this.stencils[id];
+				this.setSelectionGroup();
+				this.onSelect(stencil);
+				this.group.moveToFront();
+				this.setConstraint();
+			},
+			
+			onStencilDoubleClick: function(/*EventObject*/obj){
+				// summary:
+				//		Event fired on the double-click of a stencil
+				//
+				console.info("mgr.onStencilDoubleClick:", obj);
+				if(this.selectedStencils[obj.id]){
+					if(this.selectedStencils[obj.id].edit){
+						console.info("Mgr Stencil Edit -> ", this.selectedStencils[obj.id]);
+						var m = this.selectedStencils[obj.id];
+						// deselect must happen first to set the transform
+						// then edit knows where to set the text box
+						m.editMode = true;
+						this.deselect();
+						m.edit();
+					}
+				}
+				
+			},
+			
+			onAnchorUp: function(){
+				// summary:
+				//		Event fire on mouseup off of an anchor point
+				this.setConstraint();
+			},
+			
+			onStencilDown: function(/*EventObject*/obj, evt){
+				// summary:
+				//		Event fired on mousedown on a stencil
+				//
+				console.info(" >>> onStencilDown:", obj.id, this.keys.meta);
+				if(!this.stencils[obj.id]){ return; }
+				this._isBusy = true;
+				
+				
+				if(this.selectedStencils[obj.id] && this.keys.meta){
+					if(dojo.isMac && this.keys.cmmd){
+						// block context menu
+						
+					}
+					console.log("    shift remove");
+					this.onDeselect(this.selectedStencils[obj.id]);
+					if(this.hasSelected()==1){
+						this.withSelected(function(m){
+							this.anchors.add(m, this.group);
+						});
+					}
+					this.group.moveToFront();
+					this.setConstraint();
+					return;
+				
+				}else if(this.selectedStencils[obj.id]){
+					console.log("    clicked on selected");
+					// clicking on same selected item(s)
+					// RESET OFFSETS
+					var mx = this.group.getTransform();
+					this._offx = obj.x - mx.dx; 
+					this._offy = obj.y - mx.dy;
+					return;
+				
+				}else if(!this.keys.meta){
+					
+					console.log("    deselect all");
+					this.deselect();
+				
+				}else{
+					// meta-key add
+					//console.log("reset sel and add stencil")
+				}
+				console.log("    add stencil to selection");
+				// add a stencil
+				this.selectItem(obj.id);
+				
+				mx = this.group.getTransform();
+				this._offx = obj.x - mx.dx; 
+				this._offy = obj.y - mx.dx;
+				
+				this.orgx = obj.x;
+				this.orgy = obj.y;
+				
+				this._isBusy = false;
+				
+				// TODO:
+				//  dojo.style(surfaceNode, "cursor", "pointer");
+				
+				// TODO:
+				this.undo.add({
+					before:function(){
+						
+					},
+					after: function(){
+						
+					}
+				});
+			},
+			
+			onStencilUp: function(/*EventObject*/obj){
+				// summary:
+				//		Event fired on mouseup off of a stencil
+				//
+			},
+			
+			onStencilDrag: function(/*EventObject*/obj){
+				// summary:
+				//		Event fired on every mousemove of a stencil drag
+				//	
+				if(!this._dragBegun){
+					// bug, in FF anyway - first mouse move shows x=0
+					// the 'else' fixes it
+					this.onBeginDrag(obj);
+					this._dragBegun = true;
+				}else{
+					this.saveThrottledState();
+					
+					var x = obj.x - obj.last.x,
+						y = obj.y - obj.last.y,
+						c = this.constrain,
+						mz = this.defaults.anchors.marginZero;
+					
+					
+					x = obj.x - this._offx;
+					y = obj.y - this._offy;
+					
+					if(x < c.l + mz){
+						x = c.l + mz;
+					}
+					if(y < c.t + mz){
+						y = c.t + mz;
+					}
+					
+					this.group.setTransform({
+						dx: x,
+						dy: y
+					});
+					
+					
+				}
+			},
+			
+			onDragEnd: function(/*EventObject*/obj){
+				// summary:
+				//		Event fired at the end of a stencil drag
+				//
+				this._dragBegun = false;
+			},
+			onBeginDrag: function(/*EventObject*/obj){
+				// summary:
+				//		Event fired at the beginning of a stencil drag
+				//
+				this._wasDragged = true;
+			},
+			
+			onDown: function(/*EventObject*/obj){
+				// summary:
+				//		Event fired on mousedown on the canvas
+				//
+				this.deselect();
+			},
+						
+			
+			onStencilOver: function(obj){
+				// summary:
+				//		This changes the cursor when hovering over
+				//		a selectable stencil.
+				//console.log("OVER")
+				dojo.style(obj.id, "cursor", "move");
+			},
+
+			onStencilOut: function(obj){
+				// summary:
+				//		This restores the cursor.
+				//console.log("OUT")
+				dojo.style(obj.id, "cursor", "crosshair");
+			},
+			
+			exporter: function(){
+				// summary:
+				//		Collects all Stencil data and returns an
+				//		Array of objects.
+				var items = [];
+				for(var m in this.stencils){
+					this.stencils[m].enabled && items.push(this.stencils[m].exporter());
+				}
+				return items; // Array
+			},
+			
+			listStencils: function(){
+				return this.stencils;
+			},
+			
+			toSelected: function(/*String*/func){
+				// summary:
+				//		Convenience function calls function *within*
+				//		all selected stencils
+				var args = Array.prototype.slice.call(arguments).splice(1);
+				for(var m in this.selectedStencils){
+					var item = this.selectedStencils[m];
+					item[func].apply(item, args);
+				}
+			},
+			
+			withSelected: function(/*Function*/func){
+				// summary:
+				//		Convenience function calls function on
+				//		all selected stencils
+				var f = dojo.hitch(this, func);
+				for(var m in this.selectedStencils){
+					f(this.selectedStencils[m]);
+				}
+			},
+			
+			withUnselected: function(/*Function*/func){
+				// summary:
+				//		Convenience function calls function on
+				//		all stencils that are not selected
+				var f = dojo.hitch(this, func);
+				for(var m in this.stencils){
+					!this.stencils[m].selected && f(this.stencils[m]);
+				}
+			},
+			
+			withStencils: function(/*Function*/func){
+				// summary:
+				//		Convenience function calls function on
+				//		all stencils
+				var f = dojo.hitch(this, func);
+				for(var m in this.stencils){
+					f(this.stencils[m]);
+				}
+			},
+			
+			hasSelected: function(){
+				// summary:
+				// 		Returns number of selected (generally used
+				//		as truthy or falsey)
+				//
+				// FIXME: should be areSelected?
+				var ln = 0;
+				for(var m in this.selectedStencils){ ln++; }
+				return ln; // Number
+			},
+			
+			isSelected: function(/*Object*/stencil){
+				// summary:
+				//		Returns if passed stencil is selected or not
+				//		based on internal collection, not on stencil
+				//		boolean
+				return !!this.selectedStencils[stencil.id]; // Boolean
+			}
+		}
+		
+	);
 })();
-}
diff --git a/dojox/drawing/manager/StencilUI.js b/dojox/drawing/manager/StencilUI.js
index c7a7baf..b4af29d 100644
--- a/dojox/drawing/manager/StencilUI.js
+++ b/dojox/drawing/manager/StencilUI.js
@@ -1,48 +1,65 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.manager.StencilUI"]){
-dojo._hasResource["dojox.drawing.manager.StencilUI"]=true;
 dojo.provide("dojox.drawing.manager.StencilUI");
+
 (function(){
-var _1,_2;
-dojox.drawing.manager.StencilUI=dojox.drawing.util.oo.declare(function(_3){
-_1=_3.surface;
-this.canvas=_3.canvas;
-this.defaults=dojox.drawing.defaults.copy();
-this.mouse=_3.mouse;
-this.keys=_3.keys;
-this._mouseHandle=this.mouse.register(this);
-this.stencils={};
-},{register:function(_4){
-this.stencils[_4.id]=_4;
-return _4;
-},onUiDown:function(_5){
-if(!this._isStencil(_5)){
-return;
-}
-this.stencils[_5.id].onDown(_5);
-},onUiUp:function(_6){
-if(!this._isStencil(_6)){
-return;
-}
-this.stencils[_6.id].onUp(_6);
-},onOver:function(_7){
-if(!this._isStencil(_7)){
-return;
-}
-this.stencils[_7.id].onOver(_7);
-},onOut:function(_8){
-if(!this._isStencil(_8)){
-return;
-}
-this.stencils[_8.id].onOut(_8);
-},_isStencil:function(_9){
-return !!_9.id&&!!this.stencils[_9.id]&&this.stencils[_9.id].type=="drawing.library.UI.Button";
-}});
-})();
-}
+	var surface, surfaceNode;
+	dojox.drawing.manager.StencilUI = dojox.drawing.util.oo.declare(
+		// summary:
+		//		Used for handling Stencils as UI components.
+		// description:
+		//		Replaces manager.Stencil. Handles basic UI mouse
+		//		events like onmouseover. Does not handle selections
+		//		or support delete, etc.
+		//
+		function(options){
+			//
+			// TODO: mixin props
+			//
+			surface = options.surface;
+			this.canvas = options.canvas;
+			
+			this.defaults = dojox.drawing.defaults.copy();
+			this.mouse = options.mouse;
+			this.keys = options.keys;
+			this._mouseHandle = this.mouse.register(this);
+			this.stencils = {};
+		},
+		{
+			register: function(/*Object*/stencil){
+				this.stencils[stencil.id] = stencil;	
+				return stencil;
+			},
+			onUiDown: function(/*EventObject*/obj){
+				// summary:
+				//		Event fired on mousedown on a stencil
+				//
+				if(!this._isStencil(obj)){ return; }
+				this.stencils[obj.id].onDown(obj);
+			},
+			onUiUp: function(/*EventObject*/obj){
+				// summary:
+				//		Event fired on mousedown on a stencil
+				//
+				if(!this._isStencil(obj)){ return; }
+				this.stencils[obj.id].onUp(obj);
+			},
+			onOver: function(/*EventObject*/obj){
+				// summary:
+				//		Event fired on mousedown on a stencil
+				//
+				if(!this._isStencil(obj)){ return; }
+				this.stencils[obj.id].onOver(obj);
+			},
+			onOut: function(/*EventObject*/obj){
+				// summary:
+				//		Event fired on mousedown on a stencil
+				//
+				if(!this._isStencil(obj)){ return; }
+				this.stencils[obj.id].onOut(obj);
+			},
+			_isStencil: function(/*EventObject*/obj){
+				return !!obj.id && !!this.stencils[obj.id] && this.stencils[obj.id].type == "drawing.library.UI.Button";
+			}
+		}
+	);
+	
+})();
\ No newline at end of file
diff --git a/dojox/drawing/manager/Undo.js b/dojox/drawing/manager/Undo.js
old mode 100644
new mode 100755
index b2b6caa..e5feb16
--- a/dojox/drawing/manager/Undo.js
+++ b/dojox/drawing/manager/Undo.js
@@ -1,51 +1,57 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.manager.Undo"]){
-dojo._hasResource["dojox.drawing.manager.Undo"]=true;
 dojo.provide("dojox.drawing.manager.Undo");
-dojox.drawing.manager.Undo=dojox.drawing.util.oo.declare(function(_1){
-this.keys=_1.keys;
-this.undostack=[];
-this.redostack=[];
-dojo.connect(this.keys,"onKeyDown",this,"onKeyDown");
-},{onKeyDown:function(_2){
-if(!_2.cmmd){
-return;
-}
-if(_2.keyCode==90&&!_2.shift){
-this.undo();
-}else{
-if((_2.keyCode==90&&_2.shift)||_2.keyCode==89){
-this.redo();
-}
-}
-},add:function(_3){
-_3.args=dojo.mixin({},_3.args);
-this.undostack.push(_3);
-},apply:function(_4,_5,_6){
-dojo.hitch(_4,_5)(_6);
-},undo:function(){
-var o=this.undostack.pop();
-if(!o){
-return;
-}
-o.before();
-this.redostack.push(o);
-},redo:function(){
-var o=this.redostack.pop();
-if(!o){
-return;
-}
-if(o.after){
-o.after();
-}else{
-o.before();
-}
-this.undostack.push(o);
-}});
-}
+
+dojox.drawing.manager.Undo = dojox.drawing.util.oo.declare(
+	// summary
+	//	Handles the Undo in drawing.
+	//	NOTE: Only partially implemented!!! There is very
+	//		little actual undo functionality!
+	//
+	function(options){
+		this.keys = options.keys;
+		this.undostack = [];
+		this.redostack = [];
+		dojo.connect(this.keys, "onKeyDown", this, "onKeyDown");
+	},
+	{
+		onKeyDown: function(evt){
+			if(!evt.cmmd){ return; }
+			
+			if(evt.keyCode==90 && !evt.shift){
+				this.undo();
+			}else if((evt.keyCode == 90 && evt.shift) || evt.keyCode==89){
+				this.redo();
+			}
+			
+		},
+		add: function(stack){
+			//console.log("undo add", stack)
+			stack.args = dojo.mixin({}, stack.args);
+			this.undostack.push(stack);	
+		},
+		apply: function(scope, method, args){
+			dojo.hitch(scope, method)(args);
+		},
+		undo: function(){
+			
+			var o = this.undostack.pop();
+			console.log("undo!", o);	
+			if(!o){ return; }
+			
+			o.before();
+			
+			this.redostack.push(o);
+		},
+		redo: function(){
+			console.log("redo!");
+			var o = this.redostack.pop();
+			if(!o){ return; }
+			if(o.after){
+				o.after();
+			}else{
+				o.before(); ///??????
+			}
+			
+			this.undostack.push(o);
+		}
+	}
+);
\ No newline at end of file
diff --git a/dojox/drawing/manager/_registry.js b/dojox/drawing/manager/_registry.js
index 3de4d94..bce0dbf 100644
--- a/dojox/drawing/manager/_registry.js
+++ b/dojox/drawing/manager/_registry.js
@@ -1,34 +1,31 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.manager._registry"]){
-dojo._hasResource["dojox.drawing.manager._registry"]=true;
 dojo.provide("dojox.drawing.manager._registry");
+
 (function(){
-var _1={tool:{},stencil:{},drawing:{},plugin:{}};
-dojox.drawing.register=function(_2,_3){
-if(_3=="drawing"){
-_1.drawing[_2.id]=_2;
-}else{
-if(_3=="tool"){
-_1.tool[_2.name]=_2;
-}else{
-if(_3=="stencil"){
-_1.stencil[_2.name]=_2;
-}else{
-if(_3=="plugin"){
-_1.plugin[_2.name]=_2;
-}
-}
-}
-}
-};
-dojox.drawing.getRegistered=function(_4,id){
-return id?_1[_4][id]:_1[_4];
-};
-})();
-}
+	
+	var _registered = {
+		tool:{},
+		stencil:{},
+		drawing:{},
+		plugin:{},
+		button:{}
+	};
+	
+	dojox.drawing.register = function(item, type){
+		if(type=="drawing"){
+			_registered.drawing[item.id] = item;
+		}else if(type=="tool"){
+			_registered.tool[item.name] = item;	
+		}else if(type=="stencil"){
+			_registered.stencil[item.name] = item;	
+		}else if(type=="plugin"){
+			_registered.plugin[item.name] = item;	
+		}else if(type=="button"){
+			_registered.button[item.toolType] = item;
+		}
+	};
+	
+	dojox.drawing.getRegistered = function(type, id){
+		return id ? _registered[type][id] : _registered[type];
+	}
+	
+})();
\ No newline at end of file
diff --git a/dojox/drawing/manager/keys.js b/dojox/drawing/manager/keys.js
old mode 100644
new mode 100755
index 4a8bd1d..7ce0179
--- a/dojox/drawing/manager/keys.js
+++ b/dojox/drawing/manager/keys.js
@@ -1,154 +1,264 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.manager.keys"]){
-dojo._hasResource["dojox.drawing.manager.keys"]=true;
 dojo.provide("dojox.drawing.manager.keys");
+
 (function(){
-var _1=false;
-var _2=true;
-var _3="abcdefghijklmnopqrstuvwxyz";
-dojox.drawing.manager.keys={arrowIncrement:1,arrowShiftIncrement:10,shift:false,ctrl:false,alt:false,cmmd:false,meta:false,onDelete:function(_4){
-},onEsc:function(_5){
-},onEnter:function(_6){
-},onArrow:function(_7){
-},onKeyDown:function(_8){
-},onKeyUp:function(_9){
-},listeners:[],register:function(_a){
-var _b=dojox.drawing.util.uid("listener");
-this.listeners.push({handle:_b,scope:_a.scope||window,callback:_a.callback,keyCode:_a.keyCode});
-},_getLetter:function(_c){
-if(!_c.meta&&_c.keyCode>=65&&_c.keyCode<=90){
-return _3.charAt(_c.keyCode-65);
-}
-return null;
-},_mixin:function(_d){
-_d.meta=this.meta;
-_d.shift=this.shift;
-_d.alt=this.alt;
-_d.cmmd=this.cmmd;
-_d.letter=this._getLetter(_d);
-return _d;
-},editMode:function(_e){
-_1=_e;
-},enable:function(_f){
-_2=_f;
-},scanForFields:function(){
-if(this._fieldCons){
-dojo.forEach(this._fieldCons,dojo.disconnect,dojo);
-}
-this._fieldCons=[];
-dojo.query("input").forEach(function(n){
-var a=dojo.connect(n,"focus",this,function(evt){
-this.enable(false);
-});
-var b=dojo.connect(n,"blur",this,function(evt){
-this.enable(true);
-});
-this._fieldCons.push(a);
-this._fieldCons.push(b);
-},this);
-},init:function(){
-setTimeout(dojo.hitch(this,"scanForFields"),500);
-dojo.connect(document,"blur",this,function(evt){
-this.meta=this.shift=this.ctrl=this.cmmd=this.alt=false;
-});
-dojo.connect(document,"keydown",this,function(evt){
-if(!_2){
-return;
-}
-if(evt.keyCode==16){
-this.shift=true;
-}
-if(evt.keyCode==17){
-this.ctrl=true;
-}
-if(evt.keyCode==18){
-this.alt=true;
-}
-if(evt.keyCode==224){
-this.cmmd=true;
-}
-this.meta=this.shift||this.ctrl||this.cmmd||this.alt;
-if(!_1){
-this.onKeyDown(this._mixin(evt));
-if(evt.keyCode==8||evt.keyCode==46){
-dojo.stopEvent(evt);
-}
-}
-});
-dojo.connect(document,"keyup",this,function(evt){
-if(!_2){
-return;
-}
-var _10=false;
-if(evt.keyCode==16){
-this.shift=false;
-}
-if(evt.keyCode==17){
-this.ctrl=false;
-}
-if(evt.keyCode==18){
-this.alt=false;
-}
-if(evt.keyCode==224){
-this.cmmd=false;
-}
-this.meta=this.shift||this.ctrl||this.cmmd||this.alt;
-!_1&&this.onKeyUp(this._mixin(evt));
-if(evt.keyCode==13){
-console.warn("KEY ENTER");
-this.onEnter(evt);
-_10=true;
-}
-if(evt.keyCode==27){
-this.onEsc(evt);
-_10=true;
-}
-if(evt.keyCode==8||evt.keyCode==46){
-this.onDelete(evt);
-_10=true;
-}
-if(_10&&!_1){
-dojo.stopEvent(evt);
-}
-});
-dojo.connect(document,"keypress",this,function(evt){
-if(!_2){
-return;
-}
-var inc=this.shift?this.arrowIncrement*this.arrowShiftIncrement:this.arrowIncrement;
-var x=0,y=0;
-if(evt.keyCode==32&&!_1){
-dojo.stopEvent(evt);
-}
-if(evt.keyCode==37){
-x=-inc;
-}
-if(evt.keyCode==38){
-y=-inc;
-}
-if(evt.keyCode==39){
-x=inc;
-}
-if(evt.keyCode==40){
-y=inc;
-}
-if(x||y){
-evt.x=x;
-evt.y=y;
-evt.shift=this.shift;
-this.onArrow(evt);
-if(!_1){
-dojo.stopEvent(evt);
-}
-}
-});
-}};
-dojo.addOnLoad(dojox.drawing.manager.keys,"init");
+	
+	// Ref: isEdit allows events to happen in Drawing, like TextBlocks
+	var isEdit = false;
+	
+	// Ref: enabled = false allows inputs outside of drawing to function
+	var enabled = true;
+	
+	var alphabet = "abcdefghijklmnopqrstuvwxyz";
+	
+	dojox.drawing.manager.keys = {
+		// summary:
+		//		A singleton, master object that detects
+		//		keyboard keys and events
+		// 		Connect to it like:
+		//		dojo.connect(this.keys, "onEnter", ....);
+		//
+		// arrowIncrement:Number
+		//		The amount, in pixels, a selected Stencil will
+		//		move on an arrow key event
+		arrowIncrement:1,
+		//
+		//	arrowShiftIncrement: Number
+		//		The amount, in pixels, a selected Stencil will
+		//		move on an arrow key + SHIFT event
+		arrowShiftIncrement:10,
+		//
+		// shift: [readonly] Boolean
+		//		Indicates whether the Shift key is currently pressed
+		shift:false,
+		//
+		// ctrl: [readonly] Boolean
+		//		Indicates whether the Control key is currently pressed
+		ctrl:false,
+		//
+		// alt: [readonly] Boolean
+		//		Indicates whether the Alt or Option key is currently pressed
+		alt:false,
+		//
+		// cmmd: [readonly] Boolean
+		//		Indicates whether the Apple Command key is currently pressed
+		cmmd:false, // apple key
+		//
+		// meta: [readonly] Boolean
+		//		Indicates whether any 'meta' key is currently pressed:
+		//			shift || ctrl || cmmd || alt
+		meta:false, // any meta key
+		
+		onDelete: function(/* Event */evt){
+			// summary:
+			//		Event fires when Delete key is released
+		},
+		onEsc: function(/* Event */evt){
+			// summary:
+			//		Event fires when ESC key is released
+		},
+		onEnter: function(/* Event */evt){
+			// summary:
+			//		Event fires when Enter key is released
+		},
+		onArrow: function(/* Event */evt){
+			// summary:
+			//		Event fires when an Arrow key is released
+			//		You will have to further check if evt.keyCode
+			//		is 37,38,39, or 40
+		},
+		onKeyDown: function(/* Event */evt){
+			// summary:
+			//		Event fires when any key is pressed
+		},
+		onKeyUp: function(/* Event */evt){
+			// summary:
+			//		Event fires when any key is released
+		},
+		
+		listeners:[],
+		register: function(options){
+			// summary:
+			//		Register an object and callback to be notified
+			//		of events.
+			//		NOTE: Not really used in code, but should work.
+			//		See manager.mouse for similar usage
+			//
+			var _handle = dojox.drawing.util.uid("listener");
+			this.listeners.push({
+				handle:_handle,
+				scope: options.scope || window,
+				callback:options.callback,
+				keyCode:options.keyCode
+			});	
+		},
+		
+		_getLetter: function(evt){
+			if(!evt.meta && evt.keyCode>=65 && evt.keyCode<=90){
+				return alphabet.charAt(evt.keyCode-65);	
+			}
+			return null;
+		},
+		
+		_mixin: function(evt){
+			// summary:
+			//		Internal. Mixes in key events.
+			evt.meta = this.meta;
+			evt.shift = this.shift;
+			evt.alt = this.alt;
+			evt.cmmd = this.cmmd;
+			evt.letter = this._getLetter(evt);
+			return evt;
+		},
+		
+		editMode: function(_isedit){
+			// summary:
+			//		Relinquishes control of events to another portion
+			// 		of Drawing; namely the TextBlock.
+			isEdit = _isedit;
+		},
+		
+		enable: function(_enabled){
+			// summary:
+			//		Enables or disables key events, to relinquish
+			//		control to something outside of Drawing; input
+			//		fields for example.
+			//		You may need to call this directly if you are
+			//		using textareas or contenteditables.
+			//		NOTE: See scanForFields
+			enabled = _enabled;
+		},
+		
+		scanForFields: function(){
+			// summary:
+			//		Scans the document for inputs
+			//		and calls this automatically. However you may need
+			//		to call this if you create inputs after the fact.
+			//
+			if(this._fieldCons){
+				dojo.forEach(this._fieldCons, dojo.disconnect, dojo);
+			}
+			this._fieldCons = [];
+			dojo.query("input").forEach(function(n){
+				var a = dojo.connect(n, "focus", this, function(evt){
+					this.enable(false);	
+				});
+				var b = dojo.connect(n, "blur", this, function(evt){
+					this.enable(true);	
+				});
+				this._fieldCons.push(a);
+				this._fieldCons.push(b);
+			}, this);
+		
+		},
+		
+		init: function(){
+			// summary:
+			//		Initialize the keys object
+			//
+			// a little extra time is needed in some browsers
+			setTimeout(dojo.hitch(this, "scanForFields"), 500);
+			
+			dojo.connect(document, "blur", this, function(evt){
+				// when command tabbing to another application, the key "sticks"
+				// this clears any key used for such activity
+				this.meta = this.shift = this.ctrl = this.cmmd = this.alt = false;
+			});
+			
+			dojo.connect(document, "keydown", this, function(evt){
+				if(!enabled){ return; }
+				if(evt.keyCode==16){
+					this.shift = true;
+				}
+				if(evt.keyCode==17){
+					this.ctrl = true;
+				}
+				if(evt.keyCode==18){
+					this.alt = true;
+				}
+				if(evt.keyCode==224){
+					this.cmmd = true;
+				}
+				
+				this.meta = this.shift || this.ctrl || this.cmmd || this.alt;
+				
+				if(!isEdit){
+					this.onKeyDown(this._mixin(evt));
+					if(evt.keyCode==8 || evt.keyCode==46){
+						dojo.stopEvent(evt);
+					}
+				}
+			});
+			dojo.connect(document, "keyup", this, function(evt){
+				if(!enabled){ return; }
+				//console.log("KEY UP:", evt.keyCode);
+				var _stop = false;
+				if(evt.keyCode==16){
+					this.shift = false;
+				}
+				if(evt.keyCode==17){
+					this.ctrl = false;
+				}
+				if(evt.keyCode==18){
+					this.alt = false;
+				}
+				if(evt.keyCode==224){
+					this.cmmd = false;
+				}
+				
+				this.meta = this.shift || this.ctrl || this.cmmd || this.alt;
+				
+				!isEdit && this.onKeyUp(this._mixin(evt));
+				
+				if(evt.keyCode==13){
+					console.warn("KEY ENTER");
+					this.onEnter(evt);
+					_stop = true;
+				}
+				if(evt.keyCode==27){
+					this.onEsc(evt);
+					_stop = true;
+				}
+				if(evt.keyCode==8 || evt.keyCode==46){
+					this.onDelete(evt);
+					_stop = true;
+				}
+				
+				if(_stop && !isEdit){
+					dojo.stopEvent(evt);	
+				}
+			});
+			
+			dojo.connect(document, "keypress", this, function(evt){
+				if(!enabled){ return; }
+				var inc = this.shift ? this.arrowIncrement*this.arrowShiftIncrement : this.arrowIncrement;
+				
+				var x =0, y =0;
+				if(evt.keyCode==32 && !isEdit){ //space
+					dojo.stopEvent(evt);
+				}
+				if(evt.keyCode==37){ //left
+					x = -inc;
+				}
+				if(evt.keyCode==38){ //up
+					y = -inc;
+				}
+				if(evt.keyCode==39){ //right
+					x = inc;
+				}
+				if(evt.keyCode==40){ //down
+					y = inc;
+				}
+				if(x || y){
+					evt.x = x;
+					evt.y = y;
+					evt.shift = this.shift;
+					this.onArrow(evt);
+					if(!isEdit){
+						dojo.stopEvent(evt);	
+					}
+				}
+			});
+		}
+	};
+	dojo.addOnLoad(dojox.drawing.manager.keys, "init");
 })();
-}
diff --git a/dojox/drawing/plugins/_Plugin.js b/dojox/drawing/plugins/_Plugin.js
old mode 100644
new mode 100755
index 919cdbe..f13ec8e
--- a/dojox/drawing/plugins/_Plugin.js
+++ b/dojox/drawing/plugins/_Plugin.js
@@ -1,28 +1,39 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.plugins._Plugin"]){
-dojo._hasResource["dojox.drawing.plugins._Plugin"]=true;
 dojo.provide("dojox.drawing.plugins._Plugin");
-dojox.drawing.plugins._Plugin=dojox.drawing.util.oo.declare(function(_1){
-this._cons=[];
-dojo.mixin(this,_1);
-if(this.button&&this.onClick){
-this.connect(this.button,"onClick",this,"onClick");
-}
-},{util:null,keys:null,mouse:null,drawing:null,stencils:null,anchors:null,canvas:null,node:null,button:null,type:"dojox.drawing.plugins._Plugin",connect:function(){
-this._cons.push(dojo.connect.apply(dojo,arguments));
-},disconnect:function(_2){
-if(!_2){
-return;
-}
-if(!dojo.isArray(_2)){
-_2=[_2];
-}
-dojo.forEach(_2,dojo.disconnect,dojo);
-}});
-}
+
+dojox.drawing.plugins._Plugin = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Base class for plugins.
+	// description:
+	//		When creating a plugin, use this class as the
+	//		base to ensure full functionality.
+	function(options){
+		this._cons = [];
+		dojo.mixin(this, options);
+		if(this.button && this.onClick){
+			this.connect(this.button, "onClick", this, "onClick")
+		}
+	},
+	{
+		util:null,
+		keys:null,
+		mouse:null,
+		drawing:null,
+		stencils:null,
+		anchors:null,
+		canvas:null,
+		node:null,
+		button:null,//gfx button
+		type:"dojox.drawing.plugins._Plugin",
+		connect: function(){
+			this._cons.push(dojo.connect.apply(dojo, arguments));	
+		},
+		disconnect: function(/*handle | Array*/handles){
+			// summary:
+			//		Removes connections based on passed
+			//		handles arguments
+			if(!handles){ return };
+			if(!dojo.isArray(handles)){ handles=[handles]; }
+			dojo.forEach(handles, dojo.disconnect, dojo);
+		}
+	}
+);
\ No newline at end of file
diff --git a/dojox/drawing/plugins/drawing/Grid.js b/dojox/drawing/plugins/drawing/Grid.js
old mode 100644
new mode 100755
index b727d14..a54aa35
--- a/dojox/drawing/plugins/drawing/Grid.js
+++ b/dojox/drawing/plugins/drawing/Grid.js
@@ -1,52 +1,98 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.plugins.drawing.Grid"]){
-dojo._hasResource["dojox.drawing.plugins.drawing.Grid"]=true;
 dojo.provide("dojox.drawing.plugins.drawing.Grid");
 dojo.require("dojox.drawing.plugins._Plugin");
-dojox.drawing.plugins.drawing.Grid=dojox.drawing.util.oo.declare(dojox.drawing.plugins._Plugin,function(_1){
-if(_1.gap){
-this.major=_1.gap;
-}
-this.setGrid();
-dojo.connect(this.canvas,"setZoom",this,"setZoom");
-},{type:"dojox.drawing.plugins.drawing.Grid",gap:100,major:100,minor:0,zoom:1,setZoom:function(_2){
-this.zoom=_2;
-this.setGrid();
-},setGrid:function(_3){
-var _4=Math.floor(this.major*this.zoom);
-var _5=this.minor?Math.floor(this.minor*this.zoom):_4;
-this.grid&&this.grid.removeShape();
-var x1,x2,y1,y2,i,_6;
-var s=this.canvas.underlay.createGroup();
-var w=2000;
-var h=1000;
-var b=1;
-var mj="#00ffff";
-var mn="#d7ffff";
-var _7=function(x1,y1,x2,y2,c){
-s.createLine({x1:x1,y1:y1,x2:x2,y2:y2}).setStroke({style:"Solid",width:b,cap:"round",color:c});
-};
-for(i=1,len=h/_5;i<len;i++){
-x1=0,x2=w;
-y1=_5*i,y2=y1;
-_6=y1%_4?mn:mj;
-_7(x1,y1,x2,y2,_6);
-}
-for(i=1,len=w/_5;i<len;i++){
-y1=0,y2=h;
-x1=_5*i,x2=x1;
-_6=x1%_4?mn:mj;
-_7(x1,y1,x2,y2,_6);
-}
-s.moveToBack();
-this.grid=s;
-this.util.attr(s,"id","grid");
-return s;
-}});
-}
+
+dojox.drawing.plugins.drawing.Grid = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Plugin that displays a grid on the Drawing canvas.
+	// example:
+	//		|	<div dojoType="dojox.drawing.Drawing" id="drawingNode"
+	//		|		plugins="[{'name':'dojox.drawing.plugins.drawing.Grid', 'options':{gap:50}}]">
+	//		|	</div>
+	//
+	dojox.drawing.plugins._Plugin,
+	function(options){
+		if(options.gap){
+			this.major = options.gap;
+		}
+		this.majorColor = options.majorColor || this.majorColor;
+		this.minorColor = options.minorColor || this.minorColor;
+
+		this.setGrid();
+		dojo.connect(this.canvas, "setZoom", this, "setZoom");
+	},
+	{
+		type:"dojox.drawing.plugins.drawing.Grid",
+		//
+		// gap: Number
+		//		How far apart to set the grid lines
+		gap:100,
+		major:100,
+		minor:0,
+		//
+		// majorColor: String
+		//		Major lines color
+		majorColor: "#00ffff",
+		//
+		// minorColor: String
+		//		Minor lines color
+		minorColor: "#d7ffff",
+		//
+		// zoom: [readonly] Number
+		//		The current zoom of the grid
+		zoom:1,
+		
+		setZoom: function(zoom){
+			// summary:
+			//		Set's the zoom of the canvas
+			this.zoom = zoom;
+			this.setGrid();
+		},
+		setGrid: function(options){
+			// summary:
+			//		Renders grid
+			//
+			// TODO: major minor lines
+			//	minors dont show on zoom out
+			//	draw minors first
+			//
+			var mjr = Math.floor(this.major * this.zoom);
+			var mnr = this.minor ? Math.floor(this.minor * this.zoom) : mjr;
+			
+			this.grid && this.grid.removeShape();
+			
+			var x1,x2,y1,y2,i,clr,len;
+			var s = this.canvas.underlay.createGroup();
+			var w = 2000;//this.canvas.width;
+			var h = 1000;//this.canvas.height;
+			var b = 1;
+			var mj = this.majorColor;
+			var mn = this.minorColor;
+			
+			var createGridLine = function(x1,y1,x2,y2, c){
+				s.createLine({x1: x1, y1: y1, x2: x2, y2: y2}).setStroke({style: "Solid", width: b, cap: "round", color:c});
+			};
+			
+			// horz
+			for(i=1,len = h/mnr; i<len; i++){
+				x1 = 0, x2 = w;
+				y1 = mnr*i, y2 = y1;
+				
+				
+				clr = y1%mjr ? mn : mj;
+				createGridLine(x1,y1,x2,y2, clr);
+			}
+			// vert
+			for(i=1,len = w/mnr; i<len; i++){
+				y1 = 0, y2 = h;
+				x1 = mnr*i, x2 = x1;
+				clr = x1%mjr ? mn : mj;
+				createGridLine(x1,y1,x2,y2, clr);
+			}	
+		
+			s.moveToBack();
+			this.grid = s;
+			this.util.attr(s, "id", "grid");
+			return s;
+		}
+	}
+);
\ No newline at end of file
diff --git a/dojox/drawing/plugins/drawing/Silverlight.js b/dojox/drawing/plugins/drawing/Silverlight.js
old mode 100644
new mode 100755
index c450036..596c9b7
--- a/dojox/drawing/plugins/drawing/Silverlight.js
+++ b/dojox/drawing/plugins/drawing/Silverlight.js
@@ -1,138 +1,193 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.plugins.drawing.Silverlight"]){
-dojo._hasResource["dojox.drawing.plugins.drawing.Silverlight"]=true;
 dojo.provide("dojox.drawing.plugins.drawing.Silverlight");
-dojox.drawing.plugins.drawing.Silverlight=dojox.drawing.util.oo.declare(function(_1){
-if(dojox.gfx.renderer!="silverlight"){
-return;
-}
-this.mouse=_1.mouse;
-this.stencils=_1.stencils;
-this.anchors=_1.anchors;
-this.canvas=_1.canvas;
-this.util=_1.util;
-dojo.connect(this.stencils,"register",this,function(_2){
-var c1,c2,c3,c4,c5,_3=this;
-var _4=function(){
-c1=_2.container.connect("onmousedown",function(_5){
-_5.superTarget=_2;
-_3.mouse.down(_5);
-});
-};
-_4();
-c2=dojo.connect(_2,"setTransform",this,function(){
-});
-c3=dojo.connect(_2,"onBeforeRender",function(){
-});
-c4=dojo.connect(_2,"onRender",this,function(){
-});
-c5=dojo.connect(_2,"destroy",this,function(){
-dojo.forEach([c1,c2,c3,c4,c5],dojo.disconnect,dojo);
-});
-});
-dojo.connect(this.anchors,"onAddAnchor",this,function(_6){
-var c1=_6.shape.connect("onmousedown",this.mouse,function(_7){
-_7.superTarget=_6;
-this.down(_7);
-});
-var c2=dojo.connect(_6,"disconnectMouse",this,function(){
-dojo.disconnect(c1);
-dojo.disconnect(c2);
-});
-});
-this.mouse._down=function(_8){
-var _9=this._getXY(_8);
-var x=_9.x-this.origin.x;
-var y=_9.y-this.origin.y;
-x*=this.zoom;
-y*=this.zoom;
-this.origin.startx=x;
-this.origin.starty=y;
-this._lastx=x;
-this._lasty=y;
-this.drawingType=this.util.attr(_8,"drawingType")||"";
-var id=this._getId(_8);
-var _a={x:x,y:y,id:id};
-this.onDown(_a);
-this._clickTime=new Date().getTime();
-if(this._lastClickTime){
-if(this._clickTime-this._lastClickTime<this.doublClickSpeed){
-var _b=this.eventName("doubleClick");
-console.warn("DOUBLE CLICK",_b,_a);
-this._broadcastEvent(_b,_a);
-}else{
-}
-}
-this._lastClickTime=this._clickTime;
-};
-this.mouse.down=function(_c){
-clearTimeout(this.__downInv);
-if(this.util.attr(_c,"drawingType")=="surface"){
-this.__downInv=setTimeout(dojo.hitch(this,function(){
-this._down(_c);
-}),500);
-return;
-}
-this._down(_c);
-};
-this.mouse._getXY=function(_d){
-if(_d.pageX){
-return {x:_d.pageX,y:_d.pageY,cancelBubble:true};
-}
-for(var nm in _d){
-}
-if(_d.x!==undefined){
-return {x:_d.x+this.origin.x,y:_d.y+this.origin.y};
-}else{
-return {x:_d.pageX,y:_d.pageY};
-}
-};
-this.mouse._getId=function(_e){
-return this.util.attr(_e,"id");
-};
-this.util.attr=function(_f,_10,_11,_12){
-if(!_f){
-return false;
-}
-try{
-var t;
-if(_f.superTarget){
-t=_f.superTarget;
-}else{
-if(_f.superClass){
-t=_f.superClass;
-}else{
-if(_f.target){
-t=_f.target;
-}else{
-t=_f;
-}
-}
-}
-if(_11!==undefined){
-_f[_10]=_11;
-return _11;
-}
-if(t.tagName){
-if(_10=="drawingType"&&t.tagName.toLowerCase()=="object"){
-return "surface";
-}
-var r=dojo.attr(t,_10);
-}
-var r=t[_10];
-return r;
-}
-catch(e){
-if(!_12){
-}
-return false;
-}
-};
-},{});
-}
+
+dojox.drawing.plugins.drawing.Silverlight = dojox.drawing.util.oo.declare(
+	// summary:
+	// 	"Plugin" to allow the Silverlight plugin to work
+	//	with DojoX Drawing.
+	//
+	//	WARNING: This is not completely implemented. For the most
+	//	part, DojoX Drawing does not support Silverlight. This class
+	//	was created in an attempt for support, but there were too many
+	//	obstacles and not enough time. The basic functionality is here
+	//	and there's a good head start if anyone elase wishes to pick up
+	//	where I left off.
+	//
+	function(options){
+		// summary:
+		//	The constructor is the only method in this class.
+		//	What is happening here is other methods in other
+		//	classes are being overridden to adapt to Silverlight.
+		//
+ 		
+		if(dojox.gfx.renderer != "silverlight"){ return; }
+		this.mouse = options.mouse;
+		this.stencils = options.stencils;
+		this.anchors = options.anchors;
+		this.canvas = options.canvas;
+		this.util = options.util;
+	
+		
+		dojo.connect(this.stencils, "register", this, function(item){
+			var c1, c2, c3, c4, c5, self = this;
+			var conMouse = function(){
+				//console.info("------connect shape", item.id)
+				
+				// Connect to PARENT (SL Canvas) , not SHAPE 
+				c1 = item.container.connect("onmousedown", function(evt){
+					//console.info("----------------------------------SHAPE DOWN", item.container)
+					evt.superTarget = item;
+					self.mouse.down(evt);
+				});
+			}
+			conMouse();
+			
+			c2 = dojo.connect(item, "setTransform", this, function(){
+				//dojo.disconnect(c1);
+			});
+			
+			c3 = dojo.connect(item, "onBeforeRender", function(){
+				//dojo.disconnect(c1);
+			});
+			
+			
+			c4 = dojo.connect(item, "onRender", this, function(){
+				//conMouse();
+			});
+			
+			c5 = dojo.connect(item, "destroy", this, function(){
+				dojo.forEach([c1,c2,c3,c4,c5], dojo.disconnect, dojo);
+			});
+		});
+		
+		dojo.connect(this.anchors, "onAddAnchor", this, function(anchor){
+			var c1 = anchor.shape.connect("onmousedown", this.mouse, function(evt){
+				evt.superTarget = anchor;
+				this.down(evt)
+			});
+			var c2 = dojo.connect(anchor, "disconnectMouse", this, function(){
+				dojo.disconnect(c1);
+				dojo.disconnect(c2);
+			});
+			
+		});
+		
+		
+		this.mouse._down = function(evt){
+			var dim = this._getXY(evt);
+			var x = dim.x - this.origin.x;
+			var y = dim.y - this.origin.y;
+			
+			x*= this.zoom;
+			y*= this.zoom;
+			
+			this.origin.startx = x;
+			this.origin.starty = y;
+			this._lastx = x;
+			this._lasty = y;
+			
+			this.drawingType = this.util.attr(evt, "drawingType") || "";
+			var id = this._getId(evt);
+			var obj = {x:x,y:y, id:id};
+			console.log(" > > > id:", id, "drawingType:", this.drawingType, "evt:", evt)
+		
+			this.onDown(obj);
+			
+			this._clickTime = new Date().getTime();
+			if(this._lastClickTime){
+				if(this._clickTime-this._lastClickTime<this.doublClickSpeed){
+					var dnm = this.eventName("doubleClick");
+					console.warn("DOUBLE CLICK", dnm, obj);
+					this._broadcastEvent(dnm, obj);
+				}else{
+					//console.log("    slow:", this._clickTime-this._lastClickTime)
+				}
+			}
+			this._lastClickTime = this._clickTime;
+			
+			// throws errors in IE silverlight. Oddness.
+			//dojo.stopEvent(evt);
+		}
+		
+		this.mouse.down = function(evt){
+			clearTimeout(this.__downInv);
+			if(this.util.attr(evt, "drawingType")=="surface"){
+				this.__downInv = setTimeout(dojo.hitch(this, function(){
+					this._down(evt);		
+				}),500);
+				return;
+			}
+			this._down(evt);
+			
+			
+		}
+		
+		this.mouse._getXY =  function(evt){
+			
+			if(evt.pageX){
+				return {x:evt.pageX, y:evt.pageY, cancelBubble:true};
+			}
+			console.log("EVT", evt)
+			//console.log("EVT", evt.pageX)
+			for(var nm in evt){
+				//console.log("..."+nm+"="+evt[nm]);
+			}
+			console.log("EVTX", evt.x)
+			if(evt.x !== undefined){
+				return {
+					x:evt.x + this.origin.x,
+					y:evt.y + this.origin.y
+				};
+			}else{
+				return {x:evt.pageX, y:evt.pageY};
+			}
+		}
+		
+		this.mouse._getId = function(evt){
+			return this.util.attr(evt, "id");
+		}
+		
+		this.util.attr = function(/* Object */ elem, /* property */ prop, /* ? value */ value, squelchErrors){
+			if(!elem){ return false; }
+			try{
+				
+				var t;
+				if(elem.superTarget){
+					t = elem.superTarget;
+				}else if(elem.superClass){
+					t = elem.superClass; 
+				}else if(elem.target){
+					t = elem.target;
+				}else{
+					t = elem;
+				}
+				
+				if(value!==undefined){
+					elem[prop] = value;
+					return value;
+				}
+				
+				if(t.tagName){
+					if(prop=="drawingType" && t.tagName.toLowerCase()=="object"){
+						return "surface";
+					}
+					var r =  dojo.attr(t, prop);
+				}
+				var r = t[prop];
+				return r
+			
+				
+			}catch(e){
+				if(!squelchErrors){
+					// For debugging only. These errors actually cause more errors in IE's console
+					//console.error("BAD ATTR: prop:", prop, "el:", elem)
+					//console.error(e)
+					//console.trace();
+				}
+				return false;
+			}
+		}
+	},
+	{
+		
+	}
+);
\ No newline at end of file
diff --git a/dojox/drawing/plugins/tools/Iconize.js b/dojox/drawing/plugins/tools/Iconize.js
index fe556de..e0957e5 100644
--- a/dojox/drawing/plugins/tools/Iconize.js
+++ b/dojox/drawing/plugins/tools/Iconize.js
@@ -1,78 +1,100 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.plugins.tools.Iconize"]){
-dojo._hasResource["dojox.drawing.plugins.tools.Iconize"]=true;
 dojo.provide("dojox.drawing.plugins.tools.Iconize");
 dojo.require("dojox.drawing.plugins._Plugin");
-dojox.drawing.plugins.tools.Iconize=dojox.drawing.util.oo.declare(dojox.drawing.plugins._Plugin,function(_1){
-},{onClick:function(){
-var _2;
-for(var nm in this.stencils.stencils){
-if(this.stencils.stencils[nm].shortType=="path"){
-_2=this.stencils.stencils[nm];
-break;
-}
-}
-if(_2){
-this.makeIcon(_2.points);
-}
-},makeIcon:function(p){
-var _3=function(n){
-return Number(n.toFixed(1));
+
+dojox.drawing.plugins.tools.Iconize = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Somewhat of internal use...
+	//		Outputs a path to be used as an icon. Will end up being a
+	//		sub-icon under Export options
+	
+	dojox.drawing.plugins._Plugin,
+	function(options){
+	
+	},
+	{
+		onClick: function(){
+			var item;
+			for(var nm in this.stencils.stencils){
+				console.log(" stanceil item:", this.stencils.stencils[nm].id, this.stencils.stencils[nm])
+				if(this.stencils.stencils[nm].shortType=="path"){
+					item = this.stencils.stencils[nm];
+					break;
+				}
+			}
+			if(item){
+				console.log("click Iconize plugin", item.points);
+				this.makeIcon(item.points);
+			}
+		},
+		makeIcon: function(/*Array*/p){
+			var rnd = function(n){
+				return Number(n.toFixed(1));
+			}
+			
+			var x = 10000;
+			var y = 10000;
+			p.forEach(function(pt){
+				if(pt.x!==undefined && !isNaN(pt.x)){
+					x = Math.min(x, pt.x);
+					y = Math.min(y, pt.y);
+				}
+			});
+			
+			var xmax = 0;
+			var ymax = 0;
+			p.forEach(function(pt){
+				if(pt.x!==undefined && !isNaN(pt.x)){
+					pt.x = rnd(pt.x - x);
+					//console.log("Y:", pt.y, y, pt.y - y)
+					pt.y = rnd(pt.y - y);
+					xmax = Math.max(xmax, pt.x);
+					ymax = Math.max(ymax, pt.y);
+				}
+			});
+			
+			console.log("xmax:", xmax, "ymax:", ymax)
+			
+			var s = 60
+			var m = 20
+			
+			p.forEach(function(pt){
+				pt.x = rnd(pt.x / xmax) * s + m;
+				pt.y = rnd(pt.y / ymax) * s + m;
+			});
+			
+			var txt = "[\n";
+			dojo.forEach(p, function(pt, i){
+				txt += "{\t"
+				if(pt.t){
+					txt += "t:'"+pt.t+"'"
+				}
+				if(pt.x!==undefined && !isNaN(pt.x)){
+					if(pt.t){
+						txt += ", ";
+					}
+					txt += "x:"+pt.x+",\t\ty:"+pt.y;
+				}
+				txt += "\t}";
+				if(i!=p.length-1){
+					txt += ","
+				}
+				txt += "\n"
+			});
+			txt+="]"
+			
+			console.log(txt)
+			var n = dojo.byId("data");
+			if(n){
+				n.value = txt;
+			}
+		}
+	}
+);
+
+dojox.drawing.plugins.tools.Iconize.setup = {
+	name:"dojox.drawing.plugins.tools.Iconize",
+	tooltip:"Iconize Tool",
+	iconClass:"iconPan"
 };
-var x=10000;
-var y=10000;
-p.forEach(function(pt){
-if(pt.x!==undefined&&!isNaN(pt.x)){
-x=Math.min(x,pt.x);
-y=Math.min(y,pt.y);
-}
-});
-var _4=0;
-var _5=0;
-p.forEach(function(pt){
-if(pt.x!==undefined&&!isNaN(pt.x)){
-pt.x=_3(pt.x-x);
-pt.y=_3(pt.y-y);
-_4=Math.max(_4,pt.x);
-_5=Math.max(_5,pt.y);
-}
-});
-var s=60;
-var m=20;
-p.forEach(function(pt){
-pt.x=_3(pt.x/_4)*s+m;
-pt.y=_3(pt.y/_5)*s+m;
-});
-var _6="[\n";
-dojo.forEach(p,function(pt,i){
-_6+="{\t";
-if(pt.t){
-_6+="t:'"+pt.t+"'";
-}
-if(pt.x!==undefined&&!isNaN(pt.x)){
-if(pt.t){
-_6+=", ";
-}
-_6+="x:"+pt.x+",\t\ty:"+pt.y;
-}
-_6+="\t}";
-if(i!=p.length-1){
-_6+=",";
-}
-_6+="\n";
-});
-_6+="]";
-var n=dojo.byId("data");
-if(n){
-n.value=_6;
-}
-}});
-dojox.drawing.plugins.tools.Iconize.setup={name:"dojox.drawing.plugins.tools.Iconize",tooltip:"Iconize Tool",iconClass:"iconPan"};
-dojox.drawing.register(dojox.drawing.plugins.tools.Iconize.setup,"plugin");
-}
+
+dojox.drawing.register(dojox.drawing.plugins.tools.Iconize.setup, "plugin");
\ No newline at end of file
diff --git a/dojox/drawing/plugins/tools/Pan.js b/dojox/drawing/plugins/tools/Pan.js
old mode 100644
new mode 100755
index 9267dac..465c9d2
--- a/dojox/drawing/plugins/tools/Pan.js
+++ b/dojox/drawing/plugins/tools/Pan.js
@@ -1,126 +1,242 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.plugins.tools.Pan"]){
-dojo._hasResource["dojox.drawing.plugins.tools.Pan"]=true;
 dojo.provide("dojox.drawing.plugins.tools.Pan");
 dojo.require("dojox.drawing.plugins._Plugin");
-dojox.drawing.plugins.tools.Pan=dojox.drawing.util.oo.declare(dojox.drawing.plugins._Plugin,function(_1){
-this.domNode=_1.node;
-var _2;
-this.toolbar=_1.scope;
-this.connect(this.toolbar,"onToolClick",this,function(){
-this.onSetPan(false);
-});
-this.connect(this.button,"onClick",this,"onSetPan");
-this.connect(this.keys,"onKeyUp",this,"onKeyUp");
-this.connect(this.keys,"onKeyDown",this,"onKeyDown");
-this.connect(this.anchors,"onAnchorUp",this,"checkBounds");
-this.connect(this.stencils,"register",this,"checkBounds");
-this.connect(this.canvas,"resize",this,"checkBounds");
-this.connect(this.canvas,"setZoom",this,"checkBounds");
-this.connect(this.canvas,"onScroll",this,function(){
-if(this._blockScroll){
-this._blockScroll=false;
-return;
-}
-_2&&clearTimeout(_2);
-_2=setTimeout(dojo.hitch(this,"checkBounds"),200);
-});
-this._mouseHandle=this.mouse.register(this);
-},{selected:false,type:"dojox.drawing.plugins.tools.Pan",onPanUp:function(_3){
-if(_3.id==this.button.id){
-this.onSetPan(false);
-}
-},onKeyUp:function(_4){
-if(_4.keyCode==32){
-this.onSetPan(false);
-}
-},onKeyDown:function(_5){
-if(_5.keyCode==32){
-this.onSetPan(true);
-}
-},onSetPan:function(_6){
-if(_6===true||_6===false){
-this.selected=!_6;
-}
-if(this.selected){
-this.selected=false;
-this.button.deselect();
-}else{
-this.selected=true;
-this.button.select();
-}
-this.mouse.setEventMode(this.selected?"pan":"");
-},onPanDrag:function(_7){
-var x=_7.x-_7.last.x;
-var y=_7.y-_7.last.y;
-this.canvas.domNode.parentNode.scrollTop-=_7.move.y;
-this.canvas.domNode.parentNode.scrollLeft-=_7.move.x;
-this.canvas.onScroll();
-},onStencilUp:function(_8){
-this.checkBounds();
-},onStencilDrag:function(_9){
-},checkBounds:function(){
-var _a=function(){
-};
-var _b=function(){
+
+dojox.drawing.plugins.tools.Pan = dojox.drawing.util.oo.declare(
+	// summary:
+	//		A plugin that allows for a scrolling canvas. An action
+	//		tool is added to the toolbar that allows for panning. Holding
+	//		the space bar is a shortcut to that action. The canvas will
+	//		only pan and scroll if there are objects out of the viewable
+	//		area.
+	// example:
+	//		|	<div dojoType="dojox.drawing.Toolbar" drawingId="drawingNode" class="drawingToolbar vertical">
+	//		|		<div tool="dojox.drawing.tools.Line" selected="true">Line</div>
+	//		|		<div plugin="dojox.drawing.plugins.tools.Pan" options="{}">Pan</div>
+	//		|	</div>
+	//
+	dojox.drawing.plugins._Plugin,
+	function(options){
+		this.domNode = options.node;
+		var _scrollTimeout;
+		this.toolbar = options.scope;
+		this.connect(this.toolbar, "onToolClick", this, function(){
+			this.onSetPan(false)
+		});
+		this.connect(this.keys, "onKeyUp", this, "onKeyUp");
+		this.connect(this.keys, "onKeyDown", this, "onKeyDown");
+		this.connect(this.keys, "onArrow", this, "onArrow");
+		this.connect(this.anchors, "onAnchorUp", this, "checkBounds");
+		this.connect(this.stencils, "register", this, "checkBounds");
+		this.connect(this.canvas, "resize", this, "checkBounds");
+		this.connect(this.canvas, "setZoom", this, "checkBounds");
+		this.connect(this.canvas, "onScroll", this, function(){
+			if(this._blockScroll){
+				this._blockScroll = false;
+				return;
+			}
+			_scrollTimeout && clearTimeout(_scrollTimeout);
+			_scrollTimeout = setTimeout(dojo.hitch(this, "checkBounds"), 200);
+		});
+		this._mouseHandle = this.mouse.register(this);
+		// This HAS to be called after setting initial objects or things get screwy.
+		//this.checkBounds();
+		
+	},{
+		selected:false,
+		keyScroll:false,
+		type:"dojox.drawing.plugins.tools.Pan",
+		
+		onPanUp: function(obj){
+			if(obj.id == this.button.id){
+				this.onSetPan(false);
+			}
+		},
+		
+		onKeyUp: function(evt){
+			switch(evt.keyCode){
+				case 32:
+					this.onSetPan(false);
+					break;
+				case 39: case 37: case 38: case 40:
+					clearInterval(this._timer);
+					break;
+			}
+		},
+		
+		onKeyDown: function(evt){
+			if(evt.keyCode == 32){
+				this.onSetPan(true);
+			}
+		},
+		
+		interval: 20,
+		
+		onArrow: function(evt){
+			if(this._timer){ clearInterval(this._timer); }
+			this._timer = setInterval(dojo.hitch(this,function(evt){
+				this.canvas.domNode.parentNode.scrollLeft += evt.x*10;
+				this.canvas.domNode.parentNode.scrollTop += evt.y*10;
+			},evt), this.interval);
+		},
+		
+		onSetPan: function(/*Boolean | Event*/ bool){
+			if(bool === true || bool === false){
+				this.selected = !bool;
+			}
+			console.log('ON SET PAN:', this.selected)
+			if(this.selected){
+				this.selected = false;
+				this.button.deselect();
+			}else{
+				this.selected = true;
+				this.button.select();
+			}
+			this.mouse.setEventMode(this.selected ? "pan" : "");
+		},
+		
+		onPanDrag: function(obj){
+			var x = obj.x - obj.last.x;
+			var y = obj.y - obj.last.y;
+			this.canvas.domNode.parentNode.scrollTop -= obj.move.y;
+			this.canvas.domNode.parentNode.scrollLeft -= obj.move.x;
+			this.canvas.onScroll();
+		},
+		
+		onUp: function(obj){
+			if(obj.withinCanvas){
+				this.keyScroll = true;
+			}else{
+				this.keyScroll = false;
+			}
+		},
+		
+		onStencilUp: function(obj){
+			// this gets called even on click-off because of the
+			// issues with TextBlock deselection
+			this.checkBounds();
+		},
+		onStencilDrag: function(obj){
+			// this gets called even on click-off because of the
+			// issues with TextBlock deselection
+			//this.checkBounds();
+		},
+		
+		checkBounds: function(){
+			
+			//watch("CHECK BOUNDS DISABLED", true); return;
+			
+			
+			// summary:
+			//		Scans all items on the canvas and checks if they are out of
+			// 		bounds. If so, a scroll bar (in Canvas) is shown. If the position
+			// 		is left or top, the canvas is scrolled all items are relocated
+			// 		the distance of the scroll. Ideally, it should look as if the
+			// 		items do not move.
+			
+			// logging stuff here so it can be turned on and off. This method is
+			// very high maintenance.
+			var log = function(){
+				//console.log.apply(console, arguments);
+			}
+			var warn = function(){
+				//console.warn.apply(console, arguments);
+			}
+			//console.clear();
+			//console.time("check bounds");
+			
+			// initialize a shot-tin of vars
+			var t=Infinity, r=-Infinity, b=-10000, l=10000,
+				sx=0, sy=0, dy=0, dx=0,
+				mx = this.stencils.group ? this.stencils.group.getTransform() : {dx:0, dy:0},
+				sc = this.mouse.scrollOffset(),
+				// scY, scX: the scrollbar creates the need for extra dimension
+				scY = sc.left ? 10 : 0, 
+				scX = sc.top ? 10 : 0,
+				// ch, cw: the current size of the canvas
+				ch = this.canvas.height,
+				cw = this.canvas.width,
+				z = this.canvas.zoom,
+				// pch, pcw: the normal size of the canvas (not scrolled)
+				// these could change if the container resizes.
+				pch = this.canvas.parentHeight,
+				pcw = this.canvas.parentWidth;
+			
+			
+			this.stencils.withSelected(function(m){
+				var o = m.getBounds();
+				warn("SEL BOUNDS:", o);
+				t = Math.min(o.y1 + mx.dy, t);
+				r = Math.max(o.x2 + mx.dx, r);
+				b = Math.max(o.y2 + mx.dy, b);
+				l = Math.min(o.x1 + mx.dx, l);
+			});
+			
+			this.stencils.withUnselected(function(m){
+				var o = m.getBounds();
+				warn("UN BOUNDS:", o);
+				t = Math.min(o.y1, t);
+				r = Math.max(o.x2, r);
+				b = Math.max(o.y2, b);
+				l = Math.min(o.x1, l);
+				log("----------- B:", b, o.y2)
+			});
+			
+			b *= z;
+			var xscroll = 0, yscroll = 0;
+			log("Bottom test", "b:", b, "z:", z, "ch:", ch, "pch:", pch, "top:", sc.top, "sy:", sy, "mx.dy:", mx.dy);
+			if(b > pch || sc.top ){ 
+				log("*bottom scroll*");
+				// item off bottom
+				ch = Math.max(b, pch + sc.top);
+				sy = sc.top;
+				xscroll += this.canvas.getScrollWidth();
+			}else if(!sy && ch>pch){
+				log("*bottom remove*");
+				// item moved from bottom
+				ch = pch;
+			}
+			
+			r *= z;
+			if(r > pcw || sc.left){
+				//log("*right scroll*");
+				// item off right
+				cw = Math.max(r, pcw + sc.left);
+				sx = sc.left;
+				yscroll += this.canvas.getScrollWidth();
+			}else if(!sx && cw>pcw){
+				//log("*right remove*");
+				// item moved from right
+				cw = pcw;
+			}
+			
+			// add extra space for scrollbars
+			// double it to give some breathing room
+			cw += xscroll*2;
+			ch += yscroll*2;
+			
+			this._blockScroll = true;
+			
+			// selected items are not transformed. The selection itself is
+			// and the items are on de-select
+			this.stencils.group && this.stencils.group.applyTransform({dx:dx, dy:dy});
+			
+			// non-selected items are transformed
+			this.stencils.withUnselected(function(m){
+				m.transformPoints({dx:dx, dy:dy});
+			});
+			
+			this.canvas.setDimensions(cw, ch, sx, sy);
+			
+			//console.timeEnd("check bounds");
+		}
+	}
+);
+
+dojox.drawing.plugins.tools.Pan.setup = {
+	name:"dojox.drawing.plugins.tools.Pan",
+	tooltip:"Pan Tool",
+	iconClass:"iconPan",
+	button:false
 };
-var t=Infinity,r=-Infinity,b=-10000,l=10000,sx=0,sy=0,dy=0,dx=0,mx=this.stencils.group?this.stencils.group.getTransform():{dx:0,dy:0},sc=this.mouse.scrollOffset(),_c=sc.left?10:0,_d=sc.top?10:0,ch=this.canvas.height,cw=this.canvas.width,z=this.canvas.zoom,_e=this.canvas.parentHeight,_f=this.canvas.parentWidth;
-this.stencils.withSelected(function(m){
-var o=m.getBounds();
-_b("SEL BOUNDS:",o);
-t=Math.min(o.y1+mx.dy,t);
-r=Math.max(o.x2+mx.dx,r);
-b=Math.max(o.y2+mx.dy,b);
-l=Math.min(o.x1+mx.dx,l);
-});
-this.stencils.withUnselected(function(m){
-var o=m.getBounds();
-_b("UN BOUNDS:",o);
-t=Math.min(o.y1,t);
-r=Math.max(o.x2,r);
-b=Math.max(o.y2,b);
-l=Math.min(o.x1,l);
-_a("----------- B:",b,o.y2);
-});
-b*=z;
-var _10=0,_11=0;
-_a("Bottom test","b:",b,"z:",z,"ch:",ch,"pch:",_e,"top:",sc.top,"sy:",sy,"mx.dy:",mx.dy);
-if(b>_e||sc.top){
-_a("*bottom scroll*");
-ch=Math.max(b,_e+sc.top);
-sy=sc.top;
-_10+=this.canvas.getScrollWidth();
-}else{
-if(!sy&&ch>_e){
-_a("*bottom remove*");
-ch=_e;
-}
-}
-r*=z;
-if(r>_f||sc.left){
-cw=Math.max(r,_f+sc.left);
-sx=sc.left;
-_11+=this.canvas.getScrollWidth();
-}else{
-if(!sx&&cw>_f){
-cw=_f;
-}
-}
-cw+=_10*2;
-ch+=_11*2;
-this._blockScroll=true;
-this.stencils.group&&this.stencils.group.applyTransform({dx:dx,dy:dy});
-this.stencils.withUnselected(function(m){
-m.transformPoints({dx:dx,dy:dy});
-});
-this.canvas.setDimensions(cw,ch,sx,sy);
-}});
-dojox.drawing.plugins.tools.Pan.setup={name:"dojox.drawing.plugins.tools.Pan",tooltip:"Pan Tool",iconClass:"iconPan"};
-dojox.drawing.register(dojox.drawing.plugins.tools.Pan.setup,"plugin");
-}
+
+dojox.drawing.register(dojox.drawing.plugins.tools.Pan.setup, "plugin");
\ No newline at end of file
diff --git a/dojox/drawing/plugins/tools/Zoom.js b/dojox/drawing/plugins/tools/Zoom.js
old mode 100644
new mode 100755
index 804bf8e..de85f9b
--- a/dojox/drawing/plugins/tools/Zoom.js
+++ b/dojox/drawing/plugins/tools/Zoom.js
@@ -1,49 +1,125 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.plugins.tools.Zoom"]){
-dojo._hasResource["dojox.drawing.plugins.tools.Zoom"]=true;
 dojo.provide("dojox.drawing.plugins.tools.Zoom");
 dojo.require("dojox.drawing.plugins._Plugin");
+
 (function(){
-var _1=0.1,_2=10,_3=0.1,_4=1,dt=dojox.drawing.plugins.tools;
-dt.ZoomIn=dojox.drawing.util.oo.declare(function(_5){
-},{});
-dt.ZoomIn=dojox.drawing.util.oo.declare(dojox.drawing.plugins._Plugin,function(_6){
-},{type:"dojox.drawing.plugins.tools.ZoomIn",onZoomIn:function(){
-_4+=_1;
-_4=Math.min(_4,_2);
-this.canvas.setZoom(_4);
-this.mouse.setZoom(_4);
-},onClick:function(){
-this.onZoomIn();
-}});
-dt.Zoom100=dojox.drawing.util.oo.declare(dojox.drawing.plugins._Plugin,function(_7){
-},{type:"dojox.drawing.plugins.tools.Zoom100",onZoom100:function(){
-_4=1;
-this.canvas.setZoom(_4);
-this.mouse.setZoom(_4);
-},onClick:function(){
-this.onZoom100();
-}});
-dt.ZoomOut=dojox.drawing.util.oo.declare(dojox.drawing.plugins._Plugin,function(_8){
-},{type:"dojox.drawing.plugins.tools.ZoomOut",onZoomOut:function(){
-_4-=_1;
-_4=Math.max(_4,_3);
-this.canvas.setZoom(_4);
-this.mouse.setZoom(_4);
-},onClick:function(){
-this.onZoomOut();
-}});
-dt.ZoomIn.setup={name:"dojox.drawing.plugins.tools.ZoomIn",tooltip:"Zoom In"};
-dojox.drawing.register(dt.ZoomIn.setup,"plugin");
-dt.Zoom100.setup={name:"dojox.drawing.plugins.tools.Zoom100",tooltip:"Zoom to 100%"};
-dojox.drawing.register(dt.Zoom100.setup,"plugin");
-dt.ZoomOut.setup={name:"dojox.drawing.plugins.tools.ZoomOut",tooltip:"Zoom In"};
-dojox.drawing.register(dt.ZoomOut.setup,"plugin");
-})();
-}
+	//
+	// 	zoomInc: Float
+	//		The amount of zoom that will occur upon each click.
+	var zoomInc = Math.pow(2.0,0.25),
+	//
+	//	maxZoom: Number
+	//		The maximum the canvas can be zoomed in. 10 = 1000%
+	maxZoom = 10,
+	//
+	//	minZoom: Float
+	//		The most the canvas can be zoomed out. .1 = 10%
+	minZoom = 0.1,
+	//
+	//	zoomFactor: [readonly] Float
+	//		The current zoom amount
+	zoomFactor = 1,
+	
+	dt = dojox.drawing.plugins.tools;
+	
+	dt.ZoomIn = dojox.drawing.util.oo.declare(
+		// summary:
+		//		A plugin that allows for zooming the canvas in and out. An
+		//		action-tool is added to the toolbar with plus, minus and 100%
+		//		buttons.
+		//
+		function(options){
+			// mix in private vars
+			
+		},
+		{}
+	);
+	
+	
+	dt.ZoomIn = dojox.drawing.util.oo.declare(
+		// summary:
+		dojox.drawing.plugins._Plugin,
+		function(options){
+			
+		},
+		{
+			type:"dojox.drawing.plugins.tools.ZoomIn",
+			onZoomIn: function(){
+				// summary:
+				//		Handles zoom in.
+				//
+				zoomFactor *= zoomInc;
+				zoomFactor = Math.min(zoomFactor, maxZoom);
+				this.canvas.setZoom(zoomFactor);
+				this.mouse.setZoom(zoomFactor);
+			},
+			onClick: function(){
+				this.onZoomIn();
+			}
+		}
+	);
+	
+	dt.Zoom100 = dojox.drawing.util.oo.declare(
+		// summary:
+		dojox.drawing.plugins._Plugin,
+		function(options){
+			
+		},
+		{
+			type:"dojox.drawing.plugins.tools.Zoom100",
+			onZoom100: function(){
+				// summary:
+				//		Zooms to 100%
+				//
+				zoomFactor = 1;
+				this.canvas.setZoom(zoomFactor);
+				this.mouse.setZoom(zoomFactor);
+			},
+			onClick: function(){
+				this.onZoom100();
+			}
+		}
+	);
+	
+	dt.ZoomOut = dojox.drawing.util.oo.declare(
+		// summary:
+		dojox.drawing.plugins._Plugin,
+		function(options){
+			
+		},
+		{
+			type:"dojox.drawing.plugins.tools.ZoomOut",
+			onZoomOut: function(){
+				// summary:
+				//		Handles zoom out.
+				//
+				zoomFactor /= zoomInc;
+				zoomFactor = Math.max(zoomFactor, minZoom);
+				this.canvas.setZoom(zoomFactor);
+				this.mouse.setZoom(zoomFactor);
+			},
+			onClick: function(){
+				this.onZoomOut();
+			}
+		}
+	);
+
+	
+	dt.ZoomIn.setup = {
+		name:"dojox.drawing.plugins.tools.ZoomIn",
+		tooltip:"Zoom In"
+	};
+	dojox.drawing.register(dt.ZoomIn.setup, "plugin");
+	
+	dt.Zoom100.setup = {
+		name:"dojox.drawing.plugins.tools.Zoom100",
+		tooltip:"Zoom to 100%"
+	};
+	dojox.drawing.register(dt.Zoom100.setup, "plugin");
+	
+	dt.ZoomOut.setup = {
+		name:"dojox.drawing.plugins.tools.ZoomOut",
+		tooltip:"Zoom In"
+	};
+	dojox.drawing.register(dt.ZoomOut.setup, "plugin");
+
+})();
\ No newline at end of file
diff --git a/dojox/drawing/resources/drawing.css b/dojox/drawing/resources/drawing.css
old mode 100644
new mode 100755
index 29055a3..9df91b4
--- a/dojox/drawing/resources/drawing.css
+++ b/dojox/drawing/resources/drawing.css
@@ -3,6 +3,7 @@ html, body{
 	height:100%;
 	font-family:sans-serif;
 }
+
 .textAnnotation{
 	position:absolute;
 	border:1px solid #ccc;
@@ -14,12 +15,16 @@ html, body{
 	margin-top:-10px;
 	z-index:501;
 }
+
 #conEdit{
 	border:0;
-	
+	/*background:#ccc;
+	border:1px solid #ff0000;
+	outline:none;*/
 	padding:3px;
 	margin:0;
 }
+
 .drawingTooltip{
 	font-family:sans-serif;
 	font-family:sans-serif;
@@ -33,4 +38,4 @@ html, body{
 .drawingTipDesc{
 	font-size:11px;
 	padding-left:10px;
-}
+}
\ No newline at end of file
diff --git a/dojox/drawing/resources/images/tool_icons.png b/dojox/drawing/resources/images/tool_icons.png
old mode 100644
new mode 100755
diff --git a/dojox/drawing/resources/toolbar.css b/dojox/drawing/resources/toolbar.css
old mode 100644
new mode 100755
index e964938..c33a790
--- a/dojox/drawing/resources/toolbar.css
+++ b/dojox/drawing/resources/toolbar.css
@@ -1,4 +1,8 @@
-
+/*
+ FIXME:
+ IE refuses to honor the class targeting here, combining vertical and horizontal
+ currently vertical has precidence, horizontal will screw up
+*/
 .horizontal.drawingToolbar{
 	position:relative;
 	width:auto;
@@ -14,6 +18,7 @@
 	margin-top:5px;
 	background:#fff;
 }
+
 .drawingToolbar .drawingButton{
 	position:relative;
 	padding:0;
@@ -24,17 +29,21 @@
 	border:0;
 	cursor:pointer;
 }
+
 .horizontal.drawingToolbar .drawingButton{
 	float:left;
 	margin-right:5px;
 }
+
 .dj_ie6 .drawingToolbar .drawingButton {
+
 	filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale src='images/tool_sprites.png');	
 }
 .vertical.drawingToolbar .drawingButton{
 	margin-bottom:5px;
 	margin-right:0px;
 }
+
 .drawingToolbar .drawingButton.hover{
 	background-position:-32px 0px;
 }
@@ -45,7 +54,11 @@
 	background-position:-96px 0px;
 }
 .drawingToolbar .drawingButton.selected:hover{}
+
 .drawingToolbar.vertical{}
+
+
+
 .drawingToolbar .drawingButton .icon{
 	background-image:url("images/tool_icons.png");
 	width:32px;
@@ -57,11 +70,19 @@
 	padding:0;
 	clip: rect(0px 32px 32px 0px);
 }
+
+
 .drawingToolbar .drawingButton.selected .icon{
-	
+	/*
+	background-position-y is not supported in Firefox
+	The workaround is to shift the icon with 'top'
+	and hide a portion of it with 'clip'
+	*/
 	top:-32px;
 	clip: rect(32px 32px 64px 0px);
 }
+
+
 .drawingToolbar .drawingButton .icon.iconLine{
 	background-position:-64px 0px;
 }
@@ -89,10 +110,17 @@
 .drawingToolbar .drawingButton .icon.iconEq{
 	background-position:-351px 0px;
 }
+
 .dj_ie6 .drawingToolbar .drawingButton .icon {
 	
 	filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale src='images/tool_icons.png');
 }
+
+
+
+/* Combo button - a button that is connected (beg middle end)  */
+
+/* Vertical*/
 .drawingToolbar.vertical .toolCombo .drawingButton.toolComboTop{
 	background-position:-128px 0px;
 	margin:0;
@@ -105,6 +133,8 @@
 .drawingToolbar.vertical .toolCombo .drawingButton.toolComboTop.active{
 	background-position:-192px 0px;
 }
+
+
 .drawingToolbar.vertical .toolCombo .drawingButton.toolComboMid{
 	background-position:-384px 0px;
 	border-style:solid;
@@ -122,6 +152,8 @@
 .drawingToolbar.horizontal .toolCombo .drawingButton.toolComboMid.active{
 	background-position:-448px 0px;
 }
+
+
 .drawingToolbar.vertical .toolCombo .drawingButton.toolComboBot{
 	background-position:-256px 0px;
 	border-top:1px solid #fff;
@@ -133,12 +165,18 @@
 .drawingToolbar.vertical .toolCombo .drawingButton.toolComboBot.active{
 	background-position:-320px 0px;
 }
+
+
+/* Horizontal
+FIXME: Horizontal alignment needs tweaking 
+*/
 .drawingToolbar.horizontal .toolCombo .drawingButton.toolComboTop{
 	background-position:-512px 0px;
 	margin:0;
 	margin-left:10px;
 	border:0px;
 	border-right:1px solid #d6d6d6;
+
 }
 .drawingToolbar.horizontal .toolCombo .drawingButton.toolComboTop.hover{
 	background-position:-544px 0px;
@@ -146,6 +184,8 @@
 .drawingToolbar.horizontal .toolCombo .drawingButton.toolComboTop.active{
 	background-position:-576px 0px;
 }
+
+
 .drawingToolbar.horizontal .toolCombo .drawingButton.toolComboMid{
 	background-position:-384px 0px;
 	border-style:solid;
@@ -155,6 +195,7 @@
 	width:31px;
 	margin:0;
 }
+
 .drawingToolbar.horizontal .toolCombo .drawingButton.toolComboBot{
 	background-position:-640px 0px;
 	border-left:1px solid #fff;
@@ -168,6 +209,8 @@
 .drawingToolbar.horizontal .toolCombo .drawingButton.toolComboBot.active{
 	background-position:-704px 0px;
 }
+
+
 .drawingToolbar .drawingButton .icon.iconZoomIn{
 	background-position:-256px 0px;
 }
@@ -177,3 +220,6 @@
 .drawingToolbar .drawingButton .icon.iconZoomOut{
 	background-position:-288px 0px;
 }
+
+
+
diff --git a/dojox/drawing/stencil/Ellipse.js b/dojox/drawing/stencil/Ellipse.js
old mode 100644
new mode 100755
index 90873f2..c84977e
--- a/dojox/drawing/stencil/Ellipse.js
+++ b/dojox/drawing/stencil/Ellipse.js
@@ -1,33 +1,100 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.stencil.Ellipse");
 
+/*=====
+__StencilData = {
+	// summary:
+	//		the data used to create the dojox.gfx Shape
+	//
 
-if(!dojo._hasResource["dojox.drawing.stencil.Ellipse"]){
-dojo._hasResource["dojox.drawing.stencil.Ellipse"]=true;
-dojo.provide("dojox.drawing.stencil.Ellipse");
-dojox.drawing.stencil.Ellipse=dojox.drawing.util.oo.declare(dojox.drawing.stencil._Base,function(_1){
-},{type:"dojox.drawing.stencil.Ellipse",anchorType:"group",baseRender:true,dataToPoints:function(o){
-o=o||this.data;
-var x=o.cx-o.rx,y=o.cy-o.ry,w=o.rx*2,h=o.ry*2;
-this.points=[{x:x,y:y},{x:x+w,y:y},{x:x+w,y:y+h},{x:x,y:y+h}];
-return this.points;
-},pointsToData:function(p){
-p=p||this.points;
-var s=p[0];
-var e=p[2];
-this.data={cx:s.x+(e.x-s.x)/2,cy:s.y+(e.y-s.y)/2,rx:(e.x-s.x)*0.5,ry:(e.y-s.y)*0.5};
-return this.data;
-},_create:function(_2,d,_3){
-this.remove(this[_2]);
-this[_2]=this.container.createEllipse(d).setStroke(_3).setFill(_3.fill);
-this.util.attr(this[_2],"drawingType","stencil");
-},render:function(){
-this.onBeforeRender(this);
-this.renderHit&&this._create("hit",this.data,this.style.currentHit);
-this._create("shape",this.data,this.style.current);
-}});
-dojox.drawing.register({name:"dojox.drawing.stencil.Ellipse"},"stencil");
+	// 	cx: Number
+	//		Center point x
+	cx:0,
+	// 	cy: Number
+	//		Center point y
+	cy:0,
+	// 	rx: Number
+	//		Horizontal radius
+	rx:0,
+	// 	ry: Number
+	//		Vertical radius
+	ry:0
 }
+=====*/
+
+dojox.drawing.stencil.Ellipse = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Creates a dojox.gfx Ellipse based on data or points provided.
+	//
+	dojox.drawing.stencil._Base,
+	function(options){
+		// summary:
+		//		constructor
+	},
+	{
+		
+		type:"dojox.drawing.stencil.Ellipse",
+		anchorType: "group",
+		baseRender:true,
+		dataToPoints: function(/*Object*/o){
+			//summary:
+			//		Converts data to points.
+			o = o || this.data;
+			var x = o.cx - o.rx,
+				y = o.cy - o.ry,
+				w = o.rx*2,
+				h = o.ry*2
+			this.points = [
+				{x:x, y:y}, 	// TL
+				{x:x+w, y:y},	// TR
+				{x:x+w, y:y+h},	// BR
+				{x:x, y:y+h}	// BL
+			];
+			return this.points; //Array
+		},
+		
+		pointsToData: function(/*Array*/p){
+			// summary:
+			//		Converts points to data
+			p = p || this.points;
+			var s = p[0];
+			var e = p[2];
+			this.data = {
+				cx: s.x + (e.x - s.x)/2,
+				cy: s.y + (e.y - s.y)/2,
+				rx: (e.x - s.x)*.5,
+				ry: (e.y - s.y)*.5
+			};
+			return this.data; //Object
+		
+		},
+		
+		_create: function(/*String*/shp, /*__StencilData*/d, /*Object*/sty){
+			// summary:
+			//		Creates a dojox.gfx.shape based on passed arguments.
+			//		Can be called many times by implementation to create
+			//		multiple shapes in one stencil.
+			//
+			this.remove(this[shp]);
+			this[shp] = this.container.createEllipse(d)
+				.setStroke(sty)
+				.setFill(sty.fill);
+			this._setNodeAtts(this[shp]);
+		},
+		
+		render: function(){
+			// summary:
+			//		Renders the 'hit' object (the shape used for an expanded
+			//		hit area and for highlighting) and the'shape' (the actual
+			//		display object).
+			//
+			this.onBeforeRender(this);
+			this.renderHit && this._create("hit", this.data, this.style.currentHit);
+			this._create("shape", this.data, this.style.current);
+		}
+		
+	}
+);
+
+dojox.drawing.register({
+	name:"dojox.drawing.stencil.Ellipse"	
+}, "stencil");
\ No newline at end of file
diff --git a/dojox/drawing/stencil/Image.js b/dojox/drawing/stencil/Image.js
old mode 100644
new mode 100755
index d9cf690..d81a39a
--- a/dojox/drawing/stencil/Image.js
+++ b/dojox/drawing/stencil/Image.js
@@ -1,62 +1,155 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.stencil.Image");
 
 
-if(!dojo._hasResource["dojox.drawing.stencil.Image"]){
-dojo._hasResource["dojox.drawing.stencil.Image"]=true;
-dojo.provide("dojox.drawing.stencil.Image");
-dojox.drawing.stencil.Image=dojox.drawing.util.oo.declare(dojox.drawing.stencil._Base,function(_1){
-},{type:"dojox.drawing.stencil.Image",anchorType:"group",baseRender:true,dataToPoints:function(o){
-o=o||this.data;
-this.points=[{x:o.x,y:o.y},{x:o.x+o.width,y:o.y},{x:o.x+o.width,y:o.y+o.height},{x:o.x,y:o.y+o.height}];
-return this.points;
-},pointsToData:function(p){
-p=p||this.points;
-var s=p[0];
-var e=p[2];
-this.data={x:s.x,y:s.y,width:e.x-s.x,height:e.y-s.y,src:this.src||this.data.src};
-return this.data;
-},_createHilite:function(){
-this.remove(this.hit);
-this.hit=this.container.createRect(this.data).setStroke(this.style.current).setFill(this.style.current.fill);
-this._setNodeAtts(this.hit);
-},_create:function(_2,d,_3){
-this.remove(this[_2]);
-var s=this.container.getParent();
-this[_2]=s.createImage(d);
-this.container.add(this[_2]);
-this._setNodeAtts(this[_2]);
-},render:function(_4){
-if(this.data.width=="auto"||isNaN(this.data.width)){
-this.getImageSize(true);
-console.warn("Image size not provided. Acquiring...");
-return;
-}
-this.onBeforeRender(this);
-this.renderHit&&this._createHilite();
-this._create("shape",this.data,this.style.current);
-},getImageSize:function(_5){
-if(this._gettingSize){
-return;
-}
-this._gettingSize=true;
-var _6=dojo.create("img",{src:this.data.src},dojo.body());
-var _7=dojo.connect(_6,"error",this,function(){
-dojo.disconnect(c);
-dojo.disconnect(_7);
-console.error("Error loading image:",this.data.src);
-console.warn("Error image:",this.data);
-});
-var c=dojo.connect(_6,"load",this,function(){
-var _8=dojo.marginBox(_6);
-this.setData({x:this.data.x,y:this.data.y,src:this.data.src,width:_8.w,height:_8.h});
-dojo.disconnect(c);
-dojo.destroy(_6);
-_5&&this.render(true);
-});
-}});
-dojox.drawing.register({name:"dojox.drawing.stencil.Image"},"stencil");
-}
+dojox.drawing.stencil.Image = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Creates an dojox.gfx Image based on the data
+	//		provided.
+	//
+	dojox.drawing.stencil._Base,
+	function(options){
+		// summary:
+		//		constructor
+	},
+	{
+		type:"dojox.drawing.stencil.Image",
+		anchorType: "group",
+		baseRender:true,
+		
+/*=====
+StencilData: {
+	// summary:
+	//		The data used to create the dojox.gfx Shape
+	// 	x: Number
+	//		Left point x
+	// 	y: Number
+	//		Top point y
+	// 	width: ? Number
+	//		Optional width of Image. If not provided, it is obtained
+	// 	height: ? Number
+	//		Optional height of Image. If not provided, it is obtained
+	// 	src: String
+	//		The location of the source image
+},
+
+StencilPoints: [
+	// summary:
+	//		An Array of dojox.__StencilPoint objects that describe the Stencil
+	// 	0: Object
+	//		Top left point
+	// 	1: Object
+	//		Top right point
+	// 	2: Object
+	//		Bottom right point
+	// 	3: Object
+	//		Bottom left point
+],
+=====*/
+		
+		dataToPoints: function(/*Object*/o){
+			//summary:
+			//		Converts data to points.
+			o = o || this.data;
+			this.points = [
+				{x:o.x, y:o.y}, 						// TL
+				{x:o.x + o.width, y:o.y},				// TR
+				{x:o.x + o.width, y:o.y + o.height},	// BR
+				{x:o.x, y:o.y + o.height}				// BL
+			];
+			return this.points;
+		},
+		
+		pointsToData: function(/*Array*/p){
+			// summary:
+			//		Converts points to data
+			p = p || this.points;
+			var s = p[0];
+			var e = p[2];
+			this.data = {
+				x: s.x,
+				y: s.y,
+				width: e.x-s.x,
+				height: e.y-s.y,
+				src: this.src || this.data.src
+			};
+			return this.data;
+			
+		},
+		
+		_createHilite: function(){
+			// summary:
+			//		Create the hit and highlight area
+			//		for the Image.
+			this.remove(this.hit);
+			this.hit = this.container.createRect(this.data)
+				.setStroke(this.style.current)
+				.setFill(this.style.current.fill);
+			this._setNodeAtts(this.hit);
+		},
+		_create: function(/*String*/shp, /*StencilData*/d, /*Object*/sty){
+			// summary:
+			//		Creates a dojox.gfx.shape based on passed arguments.
+			//		Can be called many times by implementation to create
+			//		multiple shapes in one stencil.
+			//
+			this.remove(this[shp]);
+			var s = this.container.getParent();
+			this[shp] = s.createImage(d)
+			this.container.add(this[shp]);
+			this._setNodeAtts(this[shp]);
+		},
+		
+		render: function(dbg){
+			// summary:
+			//		Renders the 'hit' object (the shape used for an expanded
+			//		hit area and for highlighting) and the'shape' (the actual
+			//		display object). Image is slightly different than other
+			//		implementations. Instead of calling render twice, it calls
+			//		_createHilite for the 'hit'
+			//
+			if(this.data.width == "auto" || isNaN(this.data.width)){
+				this.getImageSize(true);
+				console.warn("Image size not provided. Acquiring...")
+				return;
+			}
+			this.onBeforeRender(this);
+			this.renderHit && this._createHilite();
+			this._create("shape", this.data, this.style.current);
+		},
+		getImageSize: function(render){
+			// summary:
+			//		Internal. If no image size is passed in with the data
+			//		create a dom node, insert and image, gets its dimensions
+			//		record them - then destroy everything.
+			//
+			if(this._gettingSize){ return; } // IE gets it twice (will need to mod if src changes)
+			this._gettingSize = true;
+			var img = dojo.create("img", {src:this.data.src}, dojo.body());
+			var err = dojo.connect(img, "error", this, function(){
+				dojo.disconnect(c);
+				dojo.disconnect(err);
+				console.error("Error loading image:", this.data.src)
+				console.warn("Error image:", this.data)
+				
+			});
+			var c = dojo.connect(img, "load", this, function(){
+				var dim = dojo.marginBox(img);
+				this.setData({
+					x:this.data.x,
+					y:this.data.y,
+					src:this.data.src,
+					width:dim.w,
+					height:dim.h
+				});
+				dojo.disconnect(c);
+				dojo.destroy(img);
+				render && this.render(true);
+			});
+		}
+	}
+);
+
+
+dojox.drawing.register({
+	name:"dojox.drawing.stencil.Image"	
+}, "stencil");
\ No newline at end of file
diff --git a/dojox/drawing/stencil/Line.js b/dojox/drawing/stencil/Line.js
old mode 100644
new mode 100755
index 1068175..b24c3ab
--- a/dojox/drawing/stencil/Line.js
+++ b/dojox/drawing/stencil/Line.js
@@ -1,36 +1,118 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.stencil.Line");
 
+dojox.drawing.stencil.Line = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Creates a dojox.gfx Line based on data or points provided.
+	//
+	dojox.drawing.stencil._Base,
+	function(options){
+		// summary:
+		//		constructor
+	},
+	{
+		type:"dojox.drawing.stencil.Line",
+		anchorType: "single",
+		baseRender:true,
+		
+/*=====
+StencilData: {
+	// summary:
+	//		The data used to create the dojox.gfx Shape
+	// 	x1: Number
+	//		First point x
+	// 	y1: Number
+	//		First point y
+	// 	x2: Number
+	//		Second point x
+	// 	y2: Number
+	//		Second point y
+	
+	// ALTERNATIVE:
+	
+	// 	x: Number
+	//		First point x
+	// 	y: Number
+	//		First point y
+	// 	angle: Number
+	//		angle of line
+	// 	radius: Number
+	//		length of line
+},
 
-if(!dojo._hasResource["dojox.drawing.stencil.Line"]){
-dojo._hasResource["dojox.drawing.stencil.Line"]=true;
-dojo.provide("dojox.drawing.stencil.Line");
-dojox.drawing.stencil.Line=dojox.drawing.util.oo.declare(dojox.drawing.stencil._Base,function(_1){
-},{type:"dojox.drawing.stencil.Line",anchorType:"single",baseRender:true,dataToPoints:function(o){
-o=o||this.data;
-if(o.radius||o.angle){
-var _2=o.angle;
-o.angle=(180-o.angle)<0?180-o.angle+360:180-o.angle;
-var pt=this.util.pointOnCircle(o.x,o.y,o.radius,o.angle);
-this.data=o={x1:o.x,y1:o.y,x2:pt.x,y2:pt.y};
-}
-this.points=[{x:o.x1,y:o.y1},{x:o.x2,y:o.y2}];
-return this.points;
-},pointsToData:function(p){
-p=p||this.points;
-this.data={x1:p[0].x,y1:p[0].y,x2:p[1].x,y2:p[1].y};
-return this.data;
-},_create:function(_3,d,_4){
-this.remove(this[_3]);
-this[_3]=this.container.createLine(d).setStroke(_4);
-this._setNodeAtts(this[_3]);
-},render:function(){
-this.onBeforeRender(this);
-this.renderHit&&this._create("hit",this.data,this.style.currentHit);
-this._create("shape",this.data,this.style.current);
-}});
-dojox.drawing.register({name:"dojox.drawing.stencil.Line"},"stencil");
-}
+StencilPoints: [
+	// summary:
+	//		An Array of dojox.__StencilPoint objects that describe the Stencil
+	// 	0: Object
+	//		First point
+	// 	1: Object
+	//		Second point
+],
+=====*/
+		
+		dataToPoints: function(o){
+			//summary:
+			//		Converts data to points.
+			o = o || this.data;
+			if(o.radius || o.angle){
+				// instead of using x1,x2,y1,y1,
+				// it's been set as x,y,angle,radius
+				
+				var pt = this.util.pointOnCircle(o.x,o.y,o.radius,o.angle);
+				//console.log(" ---- pts:", pt.x, pt.y);
+				this.data = o = {
+					x1:o.x,
+					y1:o.y,
+					x2:pt.x,
+					y2:pt.y
+				}
+				
+			}
+			this.points = [
+				{x:o.x1, y:o.y1},
+				{x:o.x2, y:o.y2}
+			];
+			return this.points;
+		},
+		pointsToData: function(p){
+			// summary:
+			//		Converts points to data
+			p = p || this.points;
+			this.data = {
+				x1: p[0].x,
+				y1: p[0].y,
+				x2: p[1].x,
+				y2: p[1].y
+			};
+			return this.data;
+		},
+		
+		_create: function(/*String*/shp, /*StencilData*/d, /*Object*/sty){
+			// summary:
+			//		Creates a dojox.gfx.shape based on passed arguments.
+			//		Can be called many times by implementation to create
+			//		multiple shapes in one stencil.
+			//
+			this.remove(this[shp]);
+			this[shp] = this.container.createLine(d)
+				.setStroke(sty);
+			this._setNodeAtts(this[shp]);
+		},
+		
+		render: function(){
+			// summary:
+			//		Renders the 'hit' object (the shape used for an expanded
+			//		hit area and for highlighting) and the'shape' (the actual
+			//		display object).
+			//
+			this.onBeforeRender(this);
+			this.renderHit && this._create("hit", this.data, this.style.currentHit);
+			this._create("shape", this.data, this.style.current);
+			
+		}		
+		
+	}
+);
+
+dojox.drawing.register({
+	name:"dojox.drawing.stencil.Line"	
+}, "stencil");
\ No newline at end of file
diff --git a/dojox/drawing/stencil/Path.js b/dojox/drawing/stencil/Path.js
old mode 100644
new mode 100755
index 6a266eb..80e201d
--- a/dojox/drawing/stencil/Path.js
+++ b/dojox/drawing/stencil/Path.js
@@ -1,86 +1,169 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.stencil.Path");
 
 
-if(!dojo._hasResource["dojox.drawing.stencil.Path"]){
-dojo._hasResource["dojox.drawing.stencil.Path"]=true;
-dojo.provide("dojox.drawing.stencil.Path");
-dojox.drawing.stencil.Path=dojox.drawing.util.oo.declare(dojox.drawing.stencil._Base,function(_1){
-dojo.disconnect(this._postRenderCon);
-},{type:"dojox.drawing.stencil.Path",closePath:true,baseRender:true,closeRadius:10,closeColor:{r:255,g:255,b:0,a:0.5},_create:function(_2,_3){
-this.remove(this[_2]);
-if(!this.points.length){
-return;
-}
-if(dojox.gfx.renderer=="svg"){
-var _4=[];
-dojo.forEach(this.points,function(o,i){
-if(i==0){
-_4.push("M "+o.x+" "+o.y);
-}else{
-var _5=(o.t||"")+" ";
-if(o.x===undefined){
-_4.push(_5);
-}else{
-_4.push(_5+o.x+" "+o.y);
-}
-}
-},this);
-if(this.closePath){
-_4.push("Z");
-}
-this.stringPath=_4.join(" ");
-this[_2]=this.container.createPath(_4.join(" ")).setStroke(_3);
-this.closePath&&this[_2].setFill(_3.fill);
-}else{
-this[_2]=this.container.createPath({}).setStroke(_3);
-this.closePath&&this[_2].setFill(_3.fill);
-dojo.forEach(this.points,function(o,i){
-if(i==0||o.t=="M"){
-this[_2].moveTo(o.x,o.y);
-}else{
-if(o.t=="Z"){
-this.closePath&&this[_2].closePath();
-}else{
-this[_2].lineTo(o.x,o.y);
-}
-}
-},this);
-this.closePath&&this[_2].closePath();
-}
-this._setNodeAtts(this[_2]);
-},render:function(){
-this.onBeforeRender(this);
-this.renderHit&&this._create("hit",this.style.currentHit);
-this._create("shape",this.style.current);
-},getBounds:function(_6){
-var _7=10000,_8=10000,_9=0,_a=0;
-dojo.forEach(this.points,function(p){
-if(p.x!==undefined&&!isNaN(p.x)){
-_7=Math.min(_7,p.x);
-_8=Math.min(_8,p.y);
-_9=Math.max(_9,p.x);
-_a=Math.max(_a,p.y);
-}
-});
-return {x1:_7,y1:_8,x2:_9,y2:_a,x:_7,y:_8,w:_9-_7,h:_a-_8};
-},checkClosePoint:function(_b,_c,_d){
-var _e=this.util.distance(_b.x,_b.y,_c.x,_c.y);
-if(this.points.length>1){
-if(_e<this.closeRadius&&!this.closeGuide&&!_d){
-var c={cx:_b.x,cy:_b.y,rx:this.closeRadius,ry:this.closeRadius};
-this.closeGuide=this.container.createEllipse(c).setFill(this.closeColor);
-}else{
-if(_d||_e>this.closeRadius&&this.closeGuide){
-this.remove(this.closeGuide);
-this.closeGuide=null;
-}
-}
-}
-return _e<this.closeRadius;
-}});
-dojox.drawing.register({name:"dojox.drawing.stencil.Path"},"stencil");
-}
+dojox.drawing.stencil.Path = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Creates a dojox.gfx Path based on points provided.
+	//
+	dojox.drawing.stencil._Base,
+	function(options){
+		dojo.disconnect(this._postRenderCon);
+	},
+	{
+		type:"dojox.drawing.stencil.Path",
+		closePath: true,
+		baseRender:true,
+		closeRadius:10,
+		closeColor:{r:255,g:255,b:0,a:.5},
+		
+/*=====
+StencilData: {
+	// NOT SUPPORTED FOR PATH
+},
+
+StencilPoints: [
+	// summary:
+	//		An Array of StencilPoint objects that describe the Stencil
+	// 	0: Object
+	//		First point
+	// 	[1, 2, 3...] more points
+],
+=====*/
+		
+		_create: function(/*String*/shp, /*Object*/sty){
+			// summary:
+			//		Creates a dojox.gfx.shape based on passed arguments.
+			//		Can be called many times by implementation to create
+			//		multiple shapes in one stencil.
+			//
+			this.remove(this[shp]);
+			if(!this.points.length){ return; }
+	
+			if(dojox.gfx.renderer=="svg"){
+				// NOTE:
+				// In order to avoid the Safari d="" errors,
+				// we'll need to build a string and set that.
+				var strAr = [];
+				dojo.forEach(this.points, function(o, i){
+					if(!o.skip){
+						if(i==0){
+							strAr.push("M " + o.x +" "+ o.y);
+						}else{
+							var cmd = (o.t || "") + " ";
+							if(o.x===undefined){// Z + undefined works here, but checking anyway
+								strAr.push(cmd);
+							}else{
+								strAr.push(cmd + o.x +" "+ o.y); 
+							}
+						}
+					}
+				}, this);
+				if(this.closePath){
+					strAr.push("Z");
+				}
+				
+				this.stringPath = strAr.join(" ");
+				
+				this[shp] = this.container.createPath(strAr.join(" ")).setStroke(sty);
+				this.closePath && this[shp].setFill(sty.fill);
+				
+			}else{
+				// Leaving this code for VML. It seems slightly faster but times vary.
+				this[shp] = this.container.createPath({}).setStroke(sty);
+				
+				this.closePath && this[shp].setFill(sty.fill);
+				
+				dojo.forEach(this.points, function(o, i){
+					if(!o.skip){
+						if(i==0 || o.t=="M"){
+							this[shp].moveTo(o.x, o.y);
+						}else if(o.t=="Z"){
+							this.closePath && this[shp].closePath();
+						}else{
+							this[shp].lineTo(o.x, o.y);
+						}
+					}
+				}, this);
+				
+				this.closePath && this[shp].closePath();
+			}
+			
+			this._setNodeAtts(this[shp]);
+		},
+		
+		render: function(){
+			// summary:
+			//		Renders the 'hit' object (the shape used for an expanded
+			//		hit area and for highlighting) and the'shape' (the actual
+			//		display object).
+			//
+			this.onBeforeRender(this);
+			this.renderHit && this._create("hit", this.style.currentHit);
+			this._create("shape", this.style.current);
+			//console.log("path render")
+			
+			
+		//console.log("---------------------rend hit", this.renderHit, this.id)
+		},
+		getBounds: function(/* ? Boolean*/absolute){
+			// summary:
+			//	Overwriting _Base.getBounds. Not sure how absolute should
+			//	work for a path.
+			var minx = 10000, miny = 10000, maxx = 0, maxy = 0;
+			dojo.forEach(this.points, function(p){
+				if(p.x!==undefined && !isNaN(p.x)){
+					minx = Math.min(minx, p.x);
+					miny = Math.min(miny, p.y);
+					maxx = Math.max(maxx, p.x);
+					maxy = Math.max(maxy, p.y);
+				}
+			});
+			
+			return {
+				x1:minx,
+				y1:miny,
+				x2:maxx,
+				y2:maxy,
+				x:minx,
+				y:miny,
+				w:maxx-minx,
+				h:maxy-miny
+			};
+		},
+		
+		checkClosePoint: function(/*Object*/firstPt, /*Object*/currPt, /*Boolean*/remove){
+			// summary:
+			//		Checks if points are close enough to indicate that
+			//		path should be close. Provides a visual cue.
+			// description:
+			//		Not actually used in stencil.path - this is used for
+			//		drawable tools that extend it. Note that those tools
+			//		need to remove the shape created: this.closeGuide, or
+			//		add arg: remove
+			//
+			var dist = this.util.distance(firstPt.x, firstPt.y, currPt.x, currPt.y);
+			if(this.points.length>1){
+				if(dist<this.closeRadius && !this.closeGuide && !remove){
+					var c = {
+						cx:firstPt.x,
+						cy:firstPt.y,
+						rx:this.closeRadius,
+						ry:this.closeRadius
+					}
+					this.closeGuide = this.container.createEllipse(c)
+						.setFill(this.closeColor);
+						
+				}else if(remove || dist > this.closeRadius && this.closeGuide){
+					this.remove(this.closeGuide);
+					this.closeGuide = null;
+				}
+			}
+			// return if we are within close distance
+			return dist < this.closeRadius; // Boolean
+		}
+	}
+);
+
+dojox.drawing.register({
+	name:"dojox.drawing.stencil.Path"	
+}, "stencil");
\ No newline at end of file
diff --git a/dojox/drawing/stencil/Rect.js b/dojox/drawing/stencil/Rect.js
old mode 100644
new mode 100755
index 0bbc711..c369a16
--- a/dojox/drawing/stencil/Rect.js
+++ b/dojox/drawing/stencil/Rect.js
@@ -1,34 +1,82 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.stencil.Rect");
 
 
-if(!dojo._hasResource["dojox.drawing.stencil.Rect"]){
-dojo._hasResource["dojox.drawing.stencil.Rect"]=true;
-dojo.provide("dojox.drawing.stencil.Rect");
-dojox.drawing.stencil.Rect=dojox.drawing.util.oo.declare(dojox.drawing.stencil._Base,function(_1){
-if(this.points.length){
-}
-},{type:"dojox.drawing.stencil.Rect",anchorType:"group",baseRender:true,dataToPoints:function(d){
-d=d||this.data;
-this.points=[{x:d.x,y:d.y},{x:d.x+d.width,y:d.y},{x:d.x+d.width,y:d.y+d.height},{x:d.x,y:d.y+d.height}];
-return this.points;
-},pointsToData:function(p){
-p=p||this.points;
-var s=p[0];
-var e=p[2];
-this.data={x:s.x,y:s.y,width:e.x-s.x,height:e.y-s.y,r:this.data.r||0};
-return this.data;
-},_create:function(_2,d,_3){
-this.remove(this[_2]);
-this[_2]=this.container.createRect(d).setStroke(_3).setFill(_3.fill);
-this._setNodeAtts(this[_2]);
-},render:function(){
-this.onBeforeRender(this);
-this.renderHit&&this._create("hit",this.data,this.style.currentHit);
-this._create("shape",this.data,this.style.current);
-}});
-dojox.drawing.register({name:"dojox.drawing.stencil.Rect"},"stencil");
-}
+dojox.drawing.stencil.Rect = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Creates a dojox.gfx rectangle based on data or points provided.
+	//
+	dojox.drawing.stencil._Base,
+	function(options){
+		// summary:
+		//		constructor
+		if(this.points.length){
+			//this.render();
+		}
+	},
+	{
+		type:"dojox.drawing.stencil.Rect",
+		anchorType: "group",
+		baseRender:true,
+		
+		dataToPoints: function(/*Object*/d){
+			//summary:
+			//		Converts data to points.
+			d = d || this.data;
+			this.points = [
+				{x:d.x, y:d.y}, 						// TL
+				{x:d.x + d.width, y:d.y},				// TR
+				{x:d.x + d.width, y:d.y + d.height},	// BR
+				{x:d.x, y:d.y + d.height}				// BL
+			];
+			return this.points;
+		},
+		
+		pointsToData: function(/*Array*/p){
+			// summary:
+			//		Converts points to data
+			p = p || this.points;
+			var s = p[0];
+			var e = p[2];
+			this.data = {
+				x: s.x,
+				y: s.y,
+				width: e.x-s.x,
+				height: e.y-s.y,
+				r:this.data.r || 0
+			};
+			return this.data;
+			
+		},
+		
+		_create: function(/*String*/shp, /*StencilData*/d, /*Object*/sty){
+			// summary:
+			//		Creates a dojox.gfx.shape based on passed arguments.
+			//		Can be called many times by implementation to create
+			//		multiple shapes in one stencil.
+			//
+			//console.log("render rect", d)
+			//console.log("rect sty:", sty)
+			this.remove(this[shp]);
+			this[shp] = this.container.createRect(d)
+				.setStroke(sty)
+				.setFill(sty.fill);
+			
+			this._setNodeAtts(this[shp]);
+		},
+		
+		render: function(){
+			// summary:
+			//		Renders the 'hit' object (the shape used for an expanded
+			//		hit area and for highlighting) and the'shape' (the actual
+			//		display object).
+			//
+			this.onBeforeRender(this);
+			this.renderHit && this._create("hit", this.data, this.style.currentHit);
+			this._create("shape", this.data, this.style.current);
+		}
+	}
+);
+
+dojox.drawing.register({
+	name:"dojox.drawing.stencil.Rect"	
+}, "stencil");
\ No newline at end of file
diff --git a/dojox/drawing/stencil/Text.js b/dojox/drawing/stencil/Text.js
old mode 100644
new mode 100755
index b220b27..841509e
--- a/dojox/drawing/stencil/Text.js
+++ b/dojox/drawing/stencil/Text.js
@@ -1,91 +1,228 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.stencil.Text");
 
+dojox.drawing.stencil.Text = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Creates a dojox.gfx Text (SVG or VML) based on data provided.
+	// description:
+	//		There are two text classes. TextBlock extends this one and
+	//		adds editable functionality, discovers text width etc.
+	//		This class displays text only. There is no line wrapping.
+	//		Multiple lines can be acheived by inserting \n linebreaks
+	//		in the text.
+	//
+	dojox.drawing.stencil._Base,
+	function(options){
+		// summary:
+		//		constructor.
+	},
+	{
+		type:"dojox.drawing.stencil.Text",
+		anchorType:"none",
+		baseRender:true,
+		
+		// align: String
+		//	Text horizontal alignment.
+		//		Options: start, middle, end
+		align:"start",
+		//
+		// valign:String
+		//	Text vertical alignment
+		//		Options: top, middle, bottom (FIXME: bottom not supported)
+		valign:"top",
+		//
+		// _lineHeight: [readonly] Number
+		// 	The height of each line of text. Based on style information
+		//	and font size.
+		_lineHeight:1,
+		
+/*=====
+StencilData: {
+	// summary:
+	//		The data used to create the dojox.gfx Text
+	// 	x: Number
+	//		Left point x
+	// 	y: Number
+	//		Top point y
+	// 	width: ? Number
+	//		Optional width of Text. Not required but reccommended.
+	//		for auto-sizing, use TextBlock
+	// 	height: ? Number
+	//		Optional height of Text. If not provided, _lineHeight is used.
+	// 	text: String
+	//		The string content. If not provided, may auto-delete depending on defaults.
+},
 
-if(!dojo._hasResource["dojox.drawing.stencil.Text"]){
-dojo._hasResource["dojox.drawing.stencil.Text"]=true;
-dojo.provide("dojox.drawing.stencil.Text");
-dojox.drawing.stencil.Text=dojox.drawing.util.oo.declare(dojox.drawing.stencil._Base,function(_1){
-},{type:"dojox.drawing.stencil.Text",anchorType:"none",baseRender:true,align:"start",valign:"top",_lineHeight:1,setText:function(_2){
-this._text=_2;
-this._textArray=[];
-this.created&&this.render(_2);
-},getText:function(){
-return this._text;
-},dataToPoints:function(o){
-o=o||this.data;
-var w=o.width=="auto"?1:o.width;
-var h=o.height||this._lineHeight;
-this.points=[{x:o.x,y:o.y},{x:o.x+w,y:o.y},{x:o.x+w,y:o.y+h},{x:o.x,y:o.y+h}];
-return this.points;
-},pointsToData:function(p){
-p=p||this.points;
-var s=p[0];
-var e=p[2];
-this.data={x:s.x,y:s.y,width:e.x-s.x,height:e.y-s.y};
-return this.data;
-},render:function(_3){
-this.remove(this.shape,this.hit);
-!this.annotation&&this.renderHit&&this._renderOutline();
-if(_3){
-this._text=_3;
-this._textArray=this._text.split("\n");
-}
-var d=this.pointsToData();
-var w=d.width;
-var h=this._lineHeight;
-var x=d.x+this.style.text.pad*2;
-var y=d.y+this._lineHeight-(this.textSize*0.4);
-if(this.valign=="middle"){
-y-=h/2;
-}
-this.shape=this.container.createGroup();
-dojo.forEach(this._textArray,function(_4,i){
-var tb=this.shape.createText({x:x,y:y+(h*i),text:unescape(_4),align:this.align}).setFont(this.style.currentText).setFill(this.style.currentText.color);
-this._setNodeAtts(tb);
-},this);
-this._setNodeAtts(this.shape);
-},_renderOutline:function(){
-if(this.annotation){
-return;
-}
-var d=this.pointsToData();
-if(this.align=="middle"){
-d.x-=d.width/2-this.style.text.pad*2;
-}else{
-if(this.align=="start"){
-d.x+=this.style.text.pad;
-}else{
-if(this.align=="end"){
-d.x-=d.width-this.style.text.pad*3;
-}
-}
-}
-if(this.valign=="middle"){
-d.y-=(this._lineHeight)/2-this.style.text.pad;
-}
-this.hit=this.container.createRect(d).setStroke(this.style.currentHit).setFill(this.style.currentHit.fill);
-this._setNodeAtts(this.hit);
-this.hit.moveToBack();
-},makeFit:function(_5,w){
-var _6=dojo.create("span",{innerHTML:_5,id:"foo"},document.body);
-var sz=1;
-dojo.style(_6,"fontSize",sz+"px");
-var _7=30;
-while(dojo.marginBox(_6).w<w){
-sz++;
-dojo.style(_6,"fontSize",sz+"px");
-if(_7--<=0){
-break;
-}
-}
-sz--;
-var _8=dojo.marginBox(_6);
-dojo.destroy(_6);
-return {size:sz,box:_8};
-}});
-dojox.drawing.register({name:"dojox.drawing.stencil.Text"},"stencil");
-}
+StencilPoints: [
+	// summary:
+	//		An Array of dojox.__StencilPoint objects that describe the Stencil
+	// 	0: Object
+	//		Top left point
+	// 	1: Object
+	//		Top right point
+	// 	2: Object
+	//		Bottom right point
+	// 	3: Object
+	//		Bottom left point
+],
+=====*/
+
+		typesetter: function(text){
+			// summary:
+			//		Register raw text, returning typeset form.
+			//		Uses function dojox.drawing.stencil.Text.typeset
+			//		for typesetting, if it exists.
+			//
+			if(dojox.drawing.stencil.Text.typeset){
+				this._rawText = text;
+				return dojox.drawing.stencil.Text.typeset(text);
+			}
+			return text;
+		},
+
+		setText: function(text){
+			// summary:
+			//		Setter for text.
+			//
+			// Only apply typesetting to objects that the user can modify.
+			// Else, it is assumed that typesetting is done elsewhere.
+			if(this.enabled){
+				text = this.typesetter(text);
+			}
+			// This only has an effect if text is null or this.created is false.
+			this._text = text;
+
+			this._textArray = [];
+			this.created && this.render(text);
+		},
+		
+		getText: function(){
+			// summary:
+			//		Getter for text.
+			//
+			return this._rawText || this._text;	
+		},
+		
+		dataToPoints: function(/*Object*/o){
+			//summary:
+			//		Converts data to points.
+			o = o || this.data;
+			var w = o.width =="auto" ? 1 : o.width;
+			var h = o.height || this._lineHeight;
+			this.points = [
+				{x:o.x, y:o.y}, 				// TL
+				{x:o.x + w, y:o.y},				// TR
+				{x:o.x + w, y:o.y + h},			// BR
+				{x:o.x, y:o.y + h}				// BL
+			];
+			return this.points;
+		},
+		pointsToData: function(/*Array*/p){
+			// summary:
+			//		Converts points to data
+			p = p || this.points;
+			var s = p[0];
+			var e = p[2];
+			this.data = {
+				x: s.x,
+				y: s.y,
+				width: e.x-s.x,
+				height: e.y-s.y
+			};
+			return this.data;
+		},
+		
+		render: function(/* String*/text){
+			// summary:
+			//		Renders the 'hit' object (the shape used for an expanded
+			//		hit area and for highlighting) and the'shape' (the actual
+			//		display object). Text is slightly different than other
+			//		implementations. Instead of calling render twice, it calls
+			//		_createHilite for the 'hit'
+			// arguments:
+			//		text String
+			//			Changes text if sent. Be sure to use the setText and
+			//			not to call this directly.
+			//
+			this.remove(this.shape, this.hit);
+			//console.log("text render, outline:", !this.annotation, this.renderHit, (!this.annotation && this.renderHit))
+			!this.annotation && this.renderHit && this._renderOutline();
+			if(text){
+				this._text = text;
+				this._textArray = this._text.split("\n");	
+			}
+			
+			var d = this.pointsToData();
+			var h = this._lineHeight;
+			var x = d.x + this.style.text.pad*2;
+			var y = d.y + this._lineHeight - (this.textSize*.4);
+			if(this.valign=="middle"){
+				y -= h/2;
+			}
+			this.shape = this.container.createGroup();
+			
+			/*console.log("    render ", this.type, this.id)
+			console.log("    render Y:", d.y, "textSize:", this.textSize, "LH:", this._lineHeight)
+			console.log("    render text:", y, " ... ", this._text, "enabled:", this.enabled);
+			console.log("    render text:", this.style.currentText);
+			*/
+			dojo.forEach(this._textArray, function(txt, i){
+				var tb = this.shape.createText({x: x, y: y+(h*i), text: unescape(txt), align: this.align})
+					.setFont(this.style.currentText)
+					.setFill(this.style.currentText.color);
+				
+				this._setNodeAtts(tb);
+			
+			}, this);
+			
+			this._setNodeAtts(this.shape);
+			
+		},
+		_renderOutline: function(){
+			// summary:
+			//		Create the hit and highlight area
+			//		for the Text.
+			//
+			if(this.annotation){ return; }
+			var d = this.pointsToData();
+			
+			if(this.align=="middle"){
+				d.x -= d.width/2 - this.style.text.pad * 2;
+			}else if(this.align=="start"){
+				d.x += this.style.text.pad;
+			}else if(this.align=="end"){
+				d.x -= d.width - this.style.text.pad * 3;
+			}
+			
+			if(this.valign=="middle"){
+				d.y -= (this._lineHeight )/2 - this.style.text.pad;
+			}
+			
+			this.hit = this.container.createRect(d)
+				.setStroke(this.style.currentHit)
+				.setFill(this.style.currentHit.fill);
+				//.setFill("#ffff00");
+			
+			this._setNodeAtts(this.hit);
+			this.hit.moveToBack();
+		},
+		makeFit: function(text, w){
+			var span = dojo.create('span', {innerHTML:text, id:"foo"}, document.body);
+			var sz = 1;
+			dojo.style(span, "fontSize", sz+"px");
+			var cnt = 30;
+			while(dojo.marginBox(span).w<w){
+				sz++;
+				dojo.style(span, "fontSize", sz+"px");
+				if(cnt--<=0) break;
+			}
+			sz--;
+			var box = dojo.marginBox(span);
+			dojo.destroy(span);
+			
+			return {size:sz, box:box};
+		}
+	}
+);
+dojox.drawing.register({
+	name:"dojox.drawing.stencil.Text"	
+}, "stencil");
\ No newline at end of file
diff --git a/dojox/drawing/stencil/_Base.js b/dojox/drawing/stencil/_Base.js
old mode 100644
new mode 100755
index 1c6d723..307d756
--- a/dojox/drawing/stencil/_Base.js
+++ b/dojox/drawing/stencil/_Base.js
@@ -1,569 +1,1208 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.stencil._Base"]){
-dojo._hasResource["dojox.drawing.stencil._Base"]=true;
 dojo.provide("dojox.drawing.stencil._Base");
 dojo.require("dojo.fx.easing");
-dojox.drawing.stencil._Base=dojox.drawing.util.oo.declare(function(_1){
-dojo.mixin(this,_1);
-this.style=_1.style||dojox.drawing.defaults.copy();
-if(_1.stencil){
-this.stencil=_1.stencil;
-this.util=_1.stencil.util;
-this.mouse=_1.stencil.mouse;
-this.container=_1.stencil.container;
-this.style=_1.stencil.style;
-}
-var _2=/Line|Vector|Axes|Arrow/;
-var _3=/Text/;
-this.shortType=this.util.abbr(this.type);
-this.isText=_3.test(this.type);
-this.isLine=_2.test(this.type);
-this.renderHit=this.style.renderHitLayer;
-if(!this.renderHit&&this.style.renderHitLines&&this.isLine){
-this.renderHit=true;
-}
-if(!this.renderHit&&this.style.useSelectedStyle){
-this.useSelectedStyle=true;
-this.selCopy=dojo.clone(this.style.selected);
-for(var nm in this.style.norm){
-if(this.style.selected[nm]===undefined){
-this.style.selected[nm]=this.style.norm[nm];
-}
-}
-this.textSelected=dojo.clone(this.style.text);
-this.textSelected.color=this.style.selected.fill;
-}
-this.angleSnap=this.style.angleSnap||1;
-this.marginZero=_1.marginZero||this.style.anchors.marginZero;
-this.id=_1.id||this.util.uid(this.type);
-this._cons=[];
-if(!this.annotation&&!this.subShape){
-this.util.attr(this.container,"id",this.id);
-}
-this.connect(this,"onBeforeRender","preventNegativePos");
-this._offX=this.mouse.origin.x;
-this._offY=this.mouse.origin.y;
-if(this.isText){
-this.align=_1.align||this.align;
-this.valign=_1.valign||this.valign;
-if(_1.data&&_1.data.makeFit){
-var _4=this.makeFit(_1.data.text,_1.data.width);
-this.textSize=this.style.text.size=_4.size;
-this._lineHeight=_4.box.h;
-}else{
-this.textSize=parseInt(this.style.text.size,10);
-this._lineHeight=this.textSize*1.4;
-}
-this.deleteEmptyCreate=_1.deleteEmptyCreate!==undefined?_1.deleteEmptyCreate:this.style.text.deleteEmptyCreate;
-this.deleteEmptyModify=_1.deleteEmptyModify!==undefined?_1.deleteEmptyModify:this.style.text.deleteEmptyModify;
-}
-this.attr(_1.data);
-if(this.noBaseRender){
-return;
-}
-if(_1.points){
-if(_1.data&&_1.data.closePath===false){
-this.closePath=false;
-}
-this.setPoints(_1.points);
-this.connect(this,"render",this,"onRender",true);
-this.baseRender&&this.enabled&&this.render();
-_1.label&&this.setLabel(_1.label);
-_1.shadow&&this.addShadow(_1.shadow);
-}else{
-if(_1.data){
-_1.data.width=_1.data.width?_1.data.width:this.style.text.minWidth;
-_1.data.height=_1.data.height?_1.data.height:this._lineHeight;
-this.setData(_1.data);
-this.connect(this,"render",this,"onRender",true);
-this.baseRender&&this.enabled&&this.render(_1.data.text);
-_1.label&&this.setLabel(_1.label);
-_1.shadow&&this.addShadow(_1.shadow);
-}else{
-if(this.draws){
-this.points=[];
-this.data={};
-this.connectMouse();
-this._postRenderCon=dojo.connect(this,"render",this,"_onPostRender");
-}
-}
-}
-if(this.showAngle){
-this.angleLabel=new dojox.drawing.annotations.Angle({stencil:this});
-}
-if(!this.enabled){
-this.disable();
-this.moveToBack();
-this.render(_1.data.text);
-}
-},{type:"dojox.drawing.stencil",minimumSize:10,enabled:true,drawingType:"stencil",setData:function(_5){
-this.data=_5;
-this.points=this.dataToPoints();
-},setPoints:function(_6){
-this.points=_6;
-if(this.pointsToData){
-this.data=this.pointsToData();
-}
-},onDelete:function(_7){
-},onBeforeRender:function(_8){
-},onModify:function(_9){
-},onChangeData:function(_a){
-},onChangeText:function(_b){
-},onRender:function(_c){
-this._postRenderCon=dojo.connect(this,"render",this,"_onPostRender");
-this.created=true;
-this.disconnectMouse();
-if(this.shape){
-this.shape.superClass=this;
-}else{
-this.container.superClass=this;
-}
-this._setNodeAtts(this);
-},onChangeStyle:function(_d){
-this._isBeingModified=true;
-if(!this.enabled){
-this.style.current=this.style.disabled;
-this.style.currentText=this.style.textDisabled;
-this.style.currentHit=this.style.hitNorm;
-}else{
-this.style.current=this.style.norm;
-this.style.currentHit=this.style.hitNorm;
-this.style.currentText=this.style.text;
-}
-if(this.selected){
-if(this.useSelectedStyle){
-this.style.current=this.style.selected;
-this.style.currentText=this.textSelected;
-}
-this.style.currentHit=this.style.hitSelected;
-}else{
-if(this.highlighted){
-this.style.currentHit=this.style.hitHighlighted;
-}
-}
-this.render();
-},animate:function(_e,_f){
-console.warn("ANIMATE..........................");
-var d=_e.d||_e.duration||1000;
-var ms=_e.ms||20;
-var _10=_e.ease||dojo.fx.easing.linear;
-var _11=_e.steps;
-var ts=new Date().getTime();
-var w=100;
-var cnt=0;
-var _12=true;
-var sp,ep;
-if(dojo.isArray(_e.start)){
-sp=_e.start;
-ep=_e.end;
-}else{
-if(dojo.isObject(_e.start)){
-sp=_e.start;
-ep=_e.end;
-_12=false;
-}else{
-console.warn("No data provided to animate");
-}
-}
-var v=setInterval(dojo.hitch(this,function(){
-var t=new Date().getTime()-ts;
-var p=_10(1-t/d);
-if(t>d||cnt++>100){
-clearInterval(v);
-return;
-}
-if(_12){
-var _13=[];
-dojo.forEach(sp,function(pt,i){
-var o={x:(ep[i].x-sp[i].x)*p+sp[i].x,y:(ep[i].y-sp[i].y)*p+sp[i].y};
-_13.push(o);
-});
-this.setPoints(_13);
-this.render();
-}else{
-var o={};
-for(var nm in sp){
-o[nm]=(ep[nm]-sp[nm])*p+sp[nm];
-}
-this.attr(o);
-}
-}),ms);
-},attr:function(key,_14){
-var n=this.style.norm,t=this.style.text,ts=this.textSelected||{},o,nm,_15,_16=dojo.toJson(n),_17=dojo.toJson(t);
-var _18={x:true,y:true,r:true,height:true,width:true,r:true,radius:true,angle:true};
-var _19=false;
-if(typeof (key)!="object"){
-o={};
-o[key]=_14;
-}else{
-o=dojo.clone(key);
-}
-if(o.width){
-_15=o.width;
-delete o.width;
-}
-for(nm in o){
-if(nm in n){
-n[nm]=o[nm];
-}
-if(nm in t){
-t[nm]=o[nm];
-}
-if(nm in ts){
-ts[nm]=o[nm];
-}
-if(nm in _18){
-_18[nm]=o[nm];
-_19=true;
-if(nm=="radius"&&o.angle===undefined){
-o.angle=_18.angle=this.getAngle();
-}else{
-if(nm=="angle"&&o.radius===undefined){
-o.radius=_18.radius=this.getRadius();
-}
-}
-}
-if(nm=="text"){
-this.setText(o.text);
-}
-if(nm=="label"){
-this.setLabel(o.label);
-}
-}
-if(o.borderWidth!==undefined){
-n.width=o.borderWidth;
-}
-if(this.useSelectedStyle){
-for(nm in this.style.norm){
-if(this.selCopy[nm]===undefined){
-this.style.selected[nm]=this.style.norm[nm];
-}
-}
-this.textSelected.color=this.style.selected.color;
-}
-if(!this.created){
-return;
-}
-if(o.x!==undefined||o.y!==undefined){
-var box=this.getBounds(true);
-var mx={dx:0,dy:0};
-for(nm in o){
-if(nm=="x"||nm=="y"||nm=="r"){
-mx["d"+nm]=o[nm]-box[nm];
-}
-}
-this.transformPoints(mx);
-}
-var p=this.points;
-if(o.angle!==undefined){
-this.dataToPoints({x:this.data.x1,y:this.data.y1,angle:o.angle,radius:o.radius});
-}else{
-if(_15!==undefined){
-p[1].x=p[2].x=p[0].x+_15;
-this.pointsToData(p);
-}
-}
-if(o.height!==undefined&&o.angle===undefined){
-p[2].y=p[3].y=p[0].y+o.height;
-this.pointsToData(p);
-}
-if(o.r!==undefined){
-this.data.r=Math.max(0,o.r);
-}
-if(_19||_17!=dojo.toJson(t)||_16!=dojo.toJson(n)){
-this.onChangeStyle(this);
-}
-o.width=_15;
-},exporter:function(){
-var _1a=this.type.substring(this.type.lastIndexOf(".")+1).charAt(0).toLowerCase()+this.type.substring(this.type.lastIndexOf(".")+2);
-var o=dojo.clone(this.style.norm);
-o.borderWidth=o.width;
-delete o.width;
-if(_1a=="path"){
-o.points=this.points;
-}else{
-o=dojo.mixin(o,this.data);
-}
-o.type=_1a;
-if(this.isText){
-o.text=this.getText();
-o=dojo.mixin(o,this.style.text);
-delete o.minWidth;
-delete o.deleteEmptyCreate;
-delete o.deleteEmptyModify;
-}
-var lbl=this.getLabel();
-if(lbl){
-o.label=lbl;
-}
-return o;
-},disable:function(){
-this.enabled=false;
-this.renderHit=false;
-this.onChangeStyle(this);
-},enable:function(){
-this.enabled=true;
-this.renderHit=true;
-this.onChangeStyle(this);
-},select:function(){
-this.selected=true;
-this.onChangeStyle(this);
-},deselect:function(_1b){
-if(_1b){
-setTimeout(dojo.hitch(this,function(){
-this.selected=false;
-this.onChangeStyle(this);
-}),200);
-}else{
-this.selected=false;
-this.onChangeStyle(this);
-}
-},_toggleSelected:function(){
-if(!this.selected){
-return;
-}
-this.deselect();
-setTimeout(dojo.hitch(this,"select"),0);
-},highlight:function(){
-this.highlighted=true;
-this.onChangeStyle(this);
-},unhighlight:function(){
-this.highlighted=false;
-this.onChangeStyle(this);
-},moveToFront:function(){
-this.container&&this.container.moveToFront();
-},moveToBack:function(){
-this.container&&this.container.moveToBack();
-},onTransformBegin:function(_1c){
-this._isBeingModified=true;
-},onTransformEnd:function(_1d){
-this._isBeingModified=false;
-this.onModify(this);
-},onTransform:function(_1e){
-if(!this._isBeingModified){
-this.onTransformBegin();
-}
-this.setPoints(this.points);
-this.render();
-},transformPoints:function(mx){
-if(!mx.dx&&!mx.dy){
-return;
-}
-var _1f=dojo.clone(this.points),_20=false;
-dojo.forEach(this.points,function(o){
-o.x+=mx.dx;
-o.y+=mx.dy;
-if(o.x<this.marginZero||o.y<this.marginZero){
-_20=true;
-}
-});
-if(_20){
-this.points=_1f;
-console.error("Attempt to set object '"+this.id+"' to less than zero.");
-return;
-}
-this.onTransform();
-this.onTransformEnd();
-},applyTransform:function(mx){
-this.transformPoints(mx);
-},setTransform:function(mx){
-this.attr({x:mx.dx,y:mx.dy});
-},getTransform:function(){
-return this.selected?this.container.getParent().getTransform():{dx:0,dy:0};
-},addShadow:function(_21){
-_21=_21===true?{}:_21;
-_21.stencil=this;
-this.shadow=new dojox.drawing.annotations.BoxShadow(_21);
-},removeShadow:function(){
-this.shadow.destroy();
-},setLabel:function(_22){
-if(!this._label){
-this._label=new dojox.drawing.annotations.Label({text:_22,util:this.util,mouse:this.mouse,stencil:this,annotation:true,container:this.container,labelPosition:this.labelPosition});
-}else{
-if(_22){
-this._label.setLabel(_22);
-}
-}
-},getLabel:function(){
-if(this._label){
-return this._label.getText();
-}
-return null;
-},getAngle:function(){
-var d=this.pointsToData();
-var obj={start:{x:d.x1,y:d.y1},x:d.x2,y:d.y2};
-var _23=this.util.angle(obj,this.angleSnap);
-_23=180-_23;
-_23=_23==360?0:_23;
-return _23;
-},getRadius:function(){
-var box=this.getBounds(true);
-var _24={start:{x:box.x1,y:box.y1},x:box.x2,y:box.y2};
-return this.util.length(_24);
-},getBounds:function(_25){
-var p=this.points,x1,y1,x2,y2;
-if(p.length==2){
-if(_25){
-x1=p[0].x;
-y1=p[0].y;
-x2=p[1].x;
-y2=p[1].y;
-}else{
-x1=p[0].x<p[1].x?p[0].x:p[1].x;
-y1=p[0].y<p[1].y?p[0].y:p[1].y;
-x2=p[0].x<p[1].x?p[1].x:p[0].x;
-y2=p[0].y<p[1].y?p[1].y:p[0].y;
-}
-return {x1:x1,y1:y1,x2:x2,y2:y2,x:x1,y:y1,w:x2-x1,h:y2-y1};
-}else{
-return {x1:p[0].x,y1:p[0].y,x2:p[2].x,y2:p[2].y,x:p[0].x,y:p[0].y,w:p[2].x-p[0].x,h:p[2].y-p[0].y};
-}
-},preventNegativePos:function(){
-if(this._isBeingModified){
-return;
-}
-if(!this.points||!this.points.length){
-return;
-}
-if(this.type=="dojox.drawing.tools.custom.Axes"){
-var _26=this.marginZero,_27=this.marginZero;
-dojo.forEach(this.points,function(p){
-_26=Math.min(p.y,_26);
-});
-dojo.forEach(this.points,function(p){
-_27=Math.min(p.x,_27);
-});
-if(_26<this.marginZero){
-dojo.forEach(this.points,function(p,i){
-p.y=p.y+(this.marginZero-_26);
-},this);
-}
-if(_27<this.marginZero){
-dojo.forEach(this.points,function(p){
-p.x+=(this.marginZero-_27);
-},this);
-}
-}else{
-dojo.forEach(this.points,function(p){
-p.x=p.x<0?this.marginZero:p.x;
-p.y=p.y<0?this.marginZero:p.y;
-});
-}
-this.setPoints(this.points);
-},_onPostRender:function(_28){
-if(this._isBeingModified){
-this.onModify(this);
-this._isBeingModified=false;
-}else{
-if(!this.created){
-}
-}
-if(!this.editMode&&!this.selected&&this._prevData&&dojo.toJson(this._prevData)!=dojo.toJson(this.data)){
-this.onChangeData(this);
-this._prevData=dojo.clone(this.data);
-}else{
-if(!this._prevData&&(!this.isText||this.getText())){
-this._prevData=dojo.clone(this.data);
-}
-}
-},_setNodeAtts:function(_29){
-var att=this.enabled&&!this.annotation?this.drawingType:"";
-this.util.attr(_29,"drawingType",att);
-},destroy:function(){
-if(this.destroyed){
-return;
-}
-if(this.data||this.points&&this.points.length){
-this.onDelete(this);
-}
-this.disconnectMouse();
-this.disconnect(this._cons);
-dojo.disconnect(this._postRenderCon);
-this.remove(this.shape,this.hit);
-this.destroyed=true;
-},remove:function(){
-var a=arguments;
-if(!a.length){
-if(!this.shape){
-return;
-}
-a=[this.shape];
-}
-for(var i=0;i<a.length;i++){
-if(a[i]){
-a[i].removeShape();
-}
-}
-},connectMult:function(){
-if(arguments.length>1){
-this._cons.push(this.connect.apply(this,arguments));
-}else{
-if(dojo.isArray(arguments[0][0])){
-dojo.forEach(arguments[0],function(ar){
-this._cons.push(this.connect.apply(this,ar));
-},this);
-}else{
-this._cons.push(this.connect.apply(this,arguments[0]));
-}
-}
-},connect:function(o,e,s,m,_2a){
-var c;
-if(typeof (o)!="object"){
-if(s){
-m=s;
-s=e;
-e=o;
-o=this;
-}else{
-m=e;
-e=o;
-o=s=this;
-}
-}else{
-if(!m){
-m=s;
-s=this;
-}else{
-if(_2a){
-c=dojo.connect(o,e,function(evt){
-dojo.hitch(s,m)(evt);
-dojo.disconnect(c);
-});
-this._cons.push(c);
-return c;
-}else{
-}
-}
-}
-c=dojo.connect(o,e,s,m);
-this._cons.push(c);
-return c;
-},disconnect:function(_2b){
-if(!_2b){
-return;
-}
-if(!dojo.isArray(_2b)){
-_2b=[_2b];
+
+/*=====
+StencilArgs = {
+//	container: [readonly] dojo.gfx.group
+//		The parent shape that contains all
+//		shapes used in a Stencil
+container:null,
+//
+//	anchorType: String
+//		Optionally blank or 'group'. 'group' tells
+//		an anchor point that it must constrain
+//		itself to other anchor points.
+anchorType:"",
+//
+// 	isText: Boolean
+//		Whether this is a text object or not
+//		(either stencil.text or tools.TextBlock)
+isText:false,
+//
+// 	shortType: String
+//		The type of stencil that corresponds with the types and
+//		constructors used in Drawing.registerTool
+shortType:"",
+//
+//	annotation: Boolean
+//		A Stencil used within a Stencil. An annotation
+//		is not selectable or clickable. A Label would
+//		be one example.
+annotation:false,
+//
+//	subShape: Boolean
+//		A Stencil used within a Stencil. A subShape
+//		is clickable. An arrow head would be an example.
+subShape:false,
+//
+//	style: Object
+//		An instance of the styles and defaults used within
+//		the Stencil.
+style:null,
+//
+//	util: Object
+//		Pointer to util.common
+util:null,
+//
+//	mouse: Object
+//		Pointer to the mouse instance
+mouse:null,
+//
+//	keys: Object
+//		Pointer to the keys class
+keys:null,
+//
+//	points: StencilPoints
+//		Points is an array of objects that make up the
+//		description of a Stencil. The points to a Rect
+//		that is 100x100 and at x:10 and y:10 would look like:
+//		[{x:10,y:10}, {x:110, y:10}, {x:110, y:110}, {x:10, y:110}]
+//		Points go clockwise from the top left. In the case of Paths,
+//		they would go in the order that the Stencil would be drawn.
+//		Always when the points Array is set, a data Object is created
+//		as well. So never set points directly, always use setPoints().
+//	See:
+//		setPoints()
+points:[],
+//
+//	data: StencilData
+//		A data object typically (but not always) resembles the data
+//		that is used to create the dojox.gfx Shape. The same Rect
+//		example shown in points above would look like:
+//		{x:10, y:10, width:100, height:100}
+//		And an Ellipse with the same coordinates:
+//		{cx:55, cy:55, rx:50, ry:50}
+//		The only Stencil that does not support data (at this time)
+//		is the Path. While x1,x2,x3... culd be used in a data object
+//		it doesn't provide much benefit.
+//		Always when a data object is set, a set of points is created
+//		as well. So never set data directly, always use setData().
+//	See:
+//		setData()
+data:null,
+//
+// 	marginZero [readonly] Number
+// 		How closely shape can get to y:0 or x:0. Less than zero has
+//		bugs in VML. This is set with defaults, and should be equal
+//		to half the size of an anchor point (5 px)
+marginZero:0,
+//
+//	created [readonly] Boolean
+//		Whether the Stencil has been rendered for the first time or
+//		not.
+created: false,
+//
+//	highlighted [readonly] Boolean
+//		Whether the Stencil is highlighted or not.
+highlighted:false,
+//
+//	selected [readonly] Boolean
+//		Whether the Stencil is selected or not.
+selected:false,
+//
+//	draws [readonly] Boolean
+//		Whether the Stencil can draw with a mouse drag or can just
+//		be created programmtically. If the Stencil comes from the
+//		stencil package, it should be draw:false. If it comes from
+//		the tools package it should be draw:true.
+draws:false
 }
-dojo.forEach(_2b,dojo.disconnect,dojo);
-},connectMouse:function(){
-this._mouseHandle=this.mouse.register(this);
-},disconnectMouse:function(){
-this.mouse.unregister(this._mouseHandle);
-},render:function(){
-},dataToPoints:function(_2c){
-},pointsToData:function(_2d){
-},onDown:function(obj){
-dojo.disconnect(this._postRenderCon);
-this._postRenderCon=null;
-},onMove:function(obj){
-},onDrag:function(obj){
-},onUp:function(obj){
-}});
+
+StencilPoint = {
+// summary:
+//	One point Object in the points Array
+//	x: Number
+//		x position of point
+//	y: Number
+//		y position of point
 }
+
+ToolsSetup = {
+// summary:
+//	An object attached to a Tool's constructor
+//	used to inform the toolbar of its information
+//	and properties.
+// description:
+//	This object is inserted into the *function* of
+//	a tool (not a stencil). Like: function.ToolsSetup
+//	It must be attached after constructr creation, so
+//	this object is found at the botton of the file.
+//
+//	name:String
+//		Fully qualified name of constructor
+//	tooltip: Stirng
+//		Text to display on toolbar button hover
+//	iconClass: String
+//		CSS class with icon information to attach
+//		to toolbar button.
+}
+=====*/
+
+dojox.drawing.stencil._Base = dojox.drawing.util.oo.declare(
+	// summary:
+	//		The base class used for all Stencils.
+	// description:
+	//		All stencils extend this base class.
+	//		Most methods and events can be found here.
+	//
+	function(options){
+		//console.log("______Base", this.type, options)
+		// clone style so changes are reflected in future shapes
+		dojo.mixin(this, options);
+		this.style = options.style || dojox.drawing.defaults.copy();
+		if(options.stencil){
+			this.stencil = options.stencil;
+			this.util = options.stencil.util;
+			this.mouse = options.stencil.mouse;
+			this.container = options.stencil.container;
+			this.style = options.stencil.style;
+		}
+
+		// don't use the 'g' on these, it affects
+		// the global RegExp
+		var lineTypes = /Line|Vector|Axes|Arrow/;
+		var textTypes = /Text/;
+
+		this.shortType = this.util.abbr(this.type);
+		this.isText = textTypes.test(this.type);
+		this.isLine = lineTypes.test(this.type);
+
+		this.renderHit = this.style.renderHitLayer;
+		if(!this.renderHit && this.style.renderHitLines && this.isLine){
+			this.renderHit = true;
+		}
+		if(!this.renderHit && this.style.useSelectedStyle){
+			this.useSelectedStyle = true;
+			this.selCopy = dojo.clone(this.style.selected);
+			for(var nm in this.style.norm){
+				if(this.style.selected[nm]===undefined){
+					this.style.selected[nm] = this.style.norm[nm];
+				}
+			}
+			this.textSelected = dojo.clone(this.style.text);
+			this.textSelected.color = this.style.selected.fill;
+
+		}
+
+
+		this.angleSnap = this.style.angleSnap || 1;
+
+		this.marginZero = options.marginZero || this.style.anchors.marginZero;
+		this.id = options.id || this.util.uid(this.type);
+		this._cons = [];
+
+		if(!this.annotation && !this.subShape){
+			this.util.attr(this.container, "id", this.id);
+		}
+
+		this.connect(this, "onBeforeRender", "preventNegativePos");
+
+		this._offX = this.mouse.origin.x;
+		this._offY = this.mouse.origin.y;
+
+		if(this.isText){
+			this.align = options.align || this.align;
+			this.valign = options.valign || this.valign;
+			if(options.data && options.data.makeFit){
+				var textObj = this.makeFit(options.data.text, options.data.width);
+				this.textSize = this.style.text.size = textObj.size;
+				this._lineHeight = textObj.box.h;
+			}else{
+				this.textSize = parseInt(this.style.text.size, 10);
+				this._lineHeight = this.textSize * 1.4;
+			}
+
+
+			// TODO: thinner text selection
+			//this.style.hitSelected.width *= 0.5;
+			//
+			// ouch. how verbose. My mixin is weak....
+			this.deleteEmptyCreate = options.deleteEmptyCreate!==undefined ? options.deleteEmptyCreate : this.style.text.deleteEmptyCreate;
+			this.deleteEmptyModify = options.deleteEmptyModify!==undefined ? options.deleteEmptyModify : this.style.text.deleteEmptyModify;
+		}
+
+		//this.drawingType
+
+		this.attr(options.data);
+
+		// make truthy
+		// add to renders below
+		// this.baseRender && render()
+		//if(this.type == "dojox.drawing.tools.TextBlock"){
+		if(this.noBaseRender){
+			// TextBlock will handle rendering itself
+			return;
+		}
+
+		//console.log("BASE OPTS:", options)
+		if(options.points){
+			//console.log("__________Base.constr >>>> ", this.type, "points", options.points)
+			if(options.data && options.data.closePath===false){
+				this.closePath = false;
+			}
+			this.setPoints(options.points);
+			this.connect(this, "render", this, "onRender", true);
+			this.baseRender && this.enabled && this.render();
+			options.label && this.setLabel(options.label);
+			options.shadow && this.addShadow(options.shadow);
+
+		}else if(options.data){
+			//console.log("___________Base.constr", this.type, "options data", options.data)
+			options.data.width = options.data.width ? options.data.width : this.style.text.minWidth;
+			options.data.height = options.data.height ? options.data.height : this._lineHeight;
+			this.setData(options.data);
+			this.connect(this, "render", this, "onRender", true);
+			this.baseRender && this.enabled && this.render(options.data.text);
+			this.baseRender && options.label && this.setLabel(options.label);
+			this.baseRender && options.shadow && this.addShadow(options.shadow);
+
+		}else if(this.draws){
+			//console.log("_____________Base.constr", this.type, "draws")
+			this.points = [];
+			this.data = {};
+			this.connectMouse();
+			this._postRenderCon = dojo.connect(this, "render", this, "_onPostRender");
+		}
+		if(this.showAngle){
+			this.angleLabel = new dojox.drawing.annotations.Angle({stencil:this});
+		}
+
+		if(!this.enabled){
+			this.disable();
+			this.moveToBack();
+			// some things render some don't...
+			this.render(options.data.text);
+		}
+
+	},
+	{
+
+		// type: String
+		//		The type of Stencil this is. Should be overridden
+		//		by extending classes.
+		//	FIXME: should this be declaredClass?
+		type:"dojox.drawing.stencil",
+		//
+		//	minimumSize: Number
+		//		The minimum size allowed for a render. If the size
+		//		is less, the shape is destroyed.
+		minimumSize:10,
+		//
+		//	enabled [readonly] Boolean
+		//		Whether the Stencil is enabled or not.
+		enabled:true,
+
+
+		drawingType:"stencil",
+
+		//points:[],
+
+		setData: function(/*StencilData*/data){
+			// summary:
+			//		Setter for Stencil data; also converts
+			//		data to points. See individual Stencils
+			//		for specific data properties.
+			this.data = data;
+			this.points = this.dataToPoints();
+		},
+
+		setPoints: function(/*StencilPoints*/points){
+			// summary:
+			//		Setter for Stencil points; also converts
+			//		points to data. See individual Stencils
+			//		for specific points properties.
+			this.points = points;
+			// Path doesn't do data
+			if(this.pointsToData){
+				this.data = this.pointsToData();
+			}
+		},
+
+		onDelete: function(/* Stencil */ stencil){
+			// summary:
+			//		Stub - fires before this is destroyed
+			console.info("onDelete", this.id);
+		},
+
+		onBeforeRender: function(/*Object*/ stencil){
+			// summary:
+			//		Stub - Fires before render occurs.
+		},
+
+		onModify: function(/*Object*/stencil){
+			// summary:
+			//		Stub - fires on change of any property,
+			// including style properties
+
+		},
+
+		onChangeData: function(/*Object*/ stencil){
+			// summary:
+			//		Stub - fires on change of dimensional
+			//	properties or a text change
+		},
+
+		onChangeText: function(value){ // value or 'this' ?
+			// summary:
+			//		Stub - fires on change of text in a
+			//	TextBlock tool only
+		},
+
+		onRender: function(/*Object*/ stencil){
+			// summary:
+			//		Stub - Fires on creation.
+			// 		Drawing connects to this (once!) to be
+			// 		notified of drag completion. But only if it
+			//		was registered as a Tool. Creating Stencil in and of
+			// 		itself does not register it.
+			//
+			// 		This should fire
+			// 		at the *end* of creation (not during drag)
+			//
+			//	FIXME:
+			//		This should probably be onCreate. It should
+			//		only fire once. But the mechanism for determining
+			//		this is more complicated than it sounds.
+			//
+			//if(!this._postRenderCon){
+				this._postRenderCon = dojo.connect(this, "render", this, "_onPostRender");
+			//}
+			this.created = true;
+			this.disconnectMouse();
+
+			// for Silverlight
+			if(this.shape){
+				this.shape.superClass = this;
+			}else{
+				this.container.superClass = this;
+			}
+			this._setNodeAtts(this);
+			//console.warn("ONRENDER", this.id, this)
+		},
+
+		onChangeStyle: function(/*Object*/stencil){
+			// summary:
+			//		Fires when styles of shape has changed
+			//
+			this._isBeingModified = true; // need this to prevent onRender
+			if(!this.enabled){
+				this.style.current = this.style.disabled;
+				this.style.currentText = this.style.textDisabled;
+				this.style.currentHit = this.style.hitNorm;
+
+			}else{
+				this.style.current = this.style.norm;
+				this.style.currentHit = this.style.hitNorm;
+				this.style.currentText = this.style.text;
+			}
+
+			if(this.selected){
+				if(this.useSelectedStyle){
+					this.style.current = this.style.selected;
+					this.style.currentText = this.textSelected;
+				}
+				this.style.currentHit = this.style.hitSelected;
+
+			}else if(this.highlighted){
+				//this.style.current = this.style.highlighted;
+				this.style.currentHit = this.style.hitHighlighted;
+				//this.style.currentText = this.style.textHighlighted;
+			}
+
+			// NOTE: Can't just change props like setStroke
+			//	because Silverlight throws error
+			this.render();
+		},
+
+		animate: function(options, create){
+			console.warn("ANIMATE..........................")
+			var d = 	options.d || options.duration || 1000;
+			var ms = 	options.ms || 20;
+			var ease = 	options.ease || dojo.fx.easing.linear;
+			var steps = options.steps;
+			var ts = 	new Date().getTime();
+			var w = 	100;
+			var cnt = 	0;
+			var isArray = true;
+			var sp, ep;
+
+			if(dojo.isArray(options.start)){
+				sp =	options.start;
+				ep = 	options.end;
+
+			}else if(dojo.isObject(options.start)){
+				sp =	options.start;
+				ep = 	options.end;
+				isArray = 	false;
+			}else{
+
+				console.warn("No data provided to animate")
+			}
+
+			var v = setInterval(dojo.hitch(this, function(){
+				var t = new Date().getTime() - ts;
+				var p = ease(1-t/d);
+				if(t > d || cnt++ > 100){
+					clearInterval(v);
+					return;
+				}
+
+				if(isArray){
+					var pnts = [];
+					dojo.forEach(sp, function(pt, i){
+
+						var o = {
+							x: (ep[i].x-sp[i].x)*p + sp[i].x,
+							y: (ep[i].y-sp[i].y)*p + sp[i].y
+						};
+						pnts.push(o);
+					});
+					this.setPoints(pnts);
+					this.render();
+
+				}else{
+
+					var o = {};
+					for(var nm in sp){
+						o[nm] = (ep[nm] - sp[nm]) * p + sp[nm];
+					}
+
+					this.attr(o);
+
+				}
+				//console.dir(pnts)
+
+
+				//this.attr("height", w);
+				////console.log("W:", w)
+				//w += 5;
+
+			}), ms);
+		},
+
+		attr: function(/*String | Object*/key, /* ? String | Number */value){
+			// summary
+			//		Changes properties in the style or disabled styles,
+			//		depending on whether the object is enabled.
+			//		Also can be used to change most position and size props.
+
+			// NOTE: JUST A SETTTER!! TODO!
+
+			// WARNING:
+			//	Not doing any Stencil-type checking here. Setting a height
+			//	on a line or an angle on a rectangle will just not render.
+
+			// FIXME
+			// 'width' attr is used for line width. How to change the width of a stencil?
+			var n = this.enabled?this.style.norm:this.style.disabled;
+			var t = this.enabled?this.style.text:this.style.textDisabled;
+			var ts = this.textSelected || {},
+				o,
+				nm,
+				width,
+				styleWas = dojo.toJson(n),
+				textWas = dojo.toJson(t);
+
+			var coords = {
+				x:true,
+				y:true,
+				r:true,
+				height:true,
+				width:true,
+				radius:true,
+				angle:true
+			};
+			var propChange = false;
+			if(typeof(key)!="object"){
+				o = {};
+				o[key] = value;
+			}else{
+				// prevent changing actual data
+				o = dojo.clone(key);
+			}
+
+			if(o.width){
+				// using width for size,
+				// borderWidth should be used
+				// for line thickness
+				width = o.width;
+				delete o.width;
+			}
+
+			for(nm in o){
+				if(nm in n){ n[nm] = o[nm]; }
+				if(nm in t){ t[nm] = o[nm]; }
+				if(nm in ts){ ts[nm] = o[nm]; }
+
+				if(nm in coords){
+					coords[nm] = o[nm];
+					propChange = true;
+					if(nm == "radius" && o.angle===undefined){
+						o.angle = coords.angle = this.getAngle();
+					}else if(nm == "angle" && o.radius===undefined){
+						o.radius = coords.radius = this.getRadius();
+					}
+
+				}
+				if(nm == "text"){
+					this.setText(o.text);
+				}
+				if(nm == "label"){
+					this.setLabel(o.label);
+				}
+			}
+			if(o.borderWidth!==undefined){
+				n.width = o.borderWidth;
+			}
+			
+			if(this.useSelectedStyle){
+				// using the orginal selected style copy as
+				// a reference map of what props to copy
+				for(nm in this.style.norm){
+					if(this.selCopy[nm]===undefined){
+						this.style.selected[nm] = this.style.norm[nm];
+					}
+				}
+				this.textSelected.color = this.style.selected.color;
+
+			}
+
+			if(!this.created){
+				return;
+			}
+
+			// basic transform
+			if(o.x!==undefined || o.y!==undefined){
+				var box = this.getBounds(true);
+				var mx = { dx:0, dy:0 };
+				for(nm in o){
+					if(nm=="x" || nm =="y" || nm =="r"){
+						mx["d"+nm] = o[nm] - box[nm];
+					}
+				}
+				this.transformPoints(mx);
+			}
+
+
+			var p = this.points;
+			if(o.angle!==undefined){
+				this.dataToPoints({
+					x:this.data.x1,
+					y:this.data.y1,
+					angle:o.angle,
+					radius:o.radius
+				});
+
+			} else if(width!==undefined){
+				p[1].x = p[2].x = p[0].x + width;
+				this.pointsToData(p);
+			}
+
+			if(o.height!==undefined && o.angle===undefined){
+			console.log("Doing P2D-2");
+				p[2].y = p[3].y = p[0].y + o.height;
+				this.pointsToData(p);
+			}
+
+			if(o.r!==undefined){
+				this.data.r = Math.max(0, o.r);
+			}
+
+			//console.dir(this.data);
+			if(propChange || textWas!=dojo.toJson(t) || styleWas != dojo.toJson(n)){
+				// to trigger the render
+				// other events will be called post render
+				this.onChangeStyle(this);
+			}
+			o.width = width;
+			
+			if(o.cosphi!=undefined){
+				!this.data? this.data = {cosphi:o.cosphi} : this.data.cosphi = o.cosphi;
+				this.style.zAxis = o.cosphi!=0 ? true : false;
+			}
+		},
+
+		exporter: function(){
+			// summary:
+			//		Exports Stencil data
+			//
+			var type = this.type.substring(this.type.lastIndexOf(".")+1).charAt(0).toLowerCase()
+				+ this.type.substring(this.type.lastIndexOf(".")+2);
+			var o = dojo.clone(this.style.norm);
+			o.borderWidth = o.width;
+			delete o.width;
+			if(type=="path"){
+				o.points = this.points;
+			}else{
+				o = dojo.mixin(o, this.data);
+			}
+			o.type = type;
+			if(this.isText){
+				o.text = this.getText();
+				o = dojo.mixin(o, this.style.text);
+				delete o.minWidth;
+				delete o.deleteEmptyCreate;
+				delete o.deleteEmptyModify;
+			}
+			var lbl = this.getLabel();
+			if(lbl){
+				o.label = lbl;
+			}
+			return o;
+		},
+
+
+		//	TODO:
+		// 		Makes these all called by att()
+		//		Should points and data be?
+		//
+		disable: function(){
+			// summary:
+			//		Disables Stencil so it is not selectable.
+			//		Changes the color to the disabled style.
+			this.enabled = false;
+			this.renderHit = false;
+			this.onChangeStyle(this);
+		},
+
+		enable: function(){
+			// summary:
+			//		Enables Stencil so it is not selectable (if
+			//		it was selectable to begin with). Changes the
+			//		color to the current style.
+			this.enabled = true;
+			this.renderHit = true;
+			this.onChangeStyle(this);
+		},
+
+		select: function(){
+			// summary:
+			//		Called when the Stencil is selected.
+			//		NOTE: Calling this will not select the Stencil
+			//		calling this just sets the style to the 'selected'
+			//		theme. 'manager.Stencil' should be used for selecting
+			//		Stencils.
+			//
+			this.selected = true;
+			this.onChangeStyle(this);
+		},
+
+		deselect: function(/*Boolean*/useDelay){
+			// summary:
+			//		Called when the Stencil is deselected.
+			//		NOTE: Calling this will not deselect the Stencil
+			//		calling this just sets the style to the current
+			//		theme. 'manager.Stencil' should be used for selecting
+			//		and deselecting Stencils.
+			//
+			//	arguments:
+			//		useDelay: Boolean
+			//			Adds  slight delay before the style is set.
+			//
+			// should not have to render here because the deselection
+			// re-renders after the transform
+			// but... oh well.
+			if(useDelay){
+				setTimeout(dojo.hitch(this, function(){
+					this.selected = false;
+					this.onChangeStyle(this);
+				}),200);
+			}else{
+				this.selected = false;
+				this.onChangeStyle(this);
+			}
+		},
+		_toggleSelected: function(){
+			if(!this.selected){ return; }
+			this.deselect();
+			setTimeout(dojo.hitch(this, "select"), 0);
+		},
+
+		highlight: function(){
+			// summary:
+			//		Changes style to the highlight theme.
+			this.highlighted = true;
+			this.onChangeStyle(this);
+		},
+
+		unhighlight: function(){
+			// summary:
+			//		Changes style to the current theme.
+			this.highlighted = false;
+			this.onChangeStyle(this);
+		},
+
+		moveToFront: function(){
+			// summary:
+			//		Moves Stencil to the front of all other items
+			//		on the canvas.
+			this.container && this.container.moveToFront();
+		},
+
+		moveToBack: function(){
+			// summary:
+			//		Moves Stencil to the back of all other items
+			//		on the canvas.
+			this.container && this.container.moveToBack();
+		},
+
+		onTransformBegin: function(/* ? manager.Anchor */anchor){
+			// summary:
+			//		Fired at the start of a transform. This would be
+			//		an anchor drag or a selection.
+			//
+			this._isBeingModified = true;
+		},
+
+		onTransformEnd: function(/* manager.Anchor */anchor){
+			// summary:
+			// 		Called from anchor point up mouse up
+			this._isBeingModified = false;
+			this.onModify(this);
+		},
+
+		onTransform: function(/* ? manager.Anchor */anchor){
+			// summary:
+			// 		Called from anchor point mouse drag
+			// 		also called from plugins.Pan.checkBounds
+			if(!this._isBeingModified){
+				this.onTransformBegin();
+			}
+			// this is not needed for anchor moves, but it
+			// is for stencil move:
+			this.setPoints(this.points);
+			this.render();
+		},
+
+		transformPoints: function(mx){
+			// summary:
+			//		Moves object to a new X Y location
+			//		mx is additive. So mx.dx=1 will move the stencil
+			//		1 pixel to the right from wherever it was.
+			//
+			// An attempt is made to prevent < 0 errors, but
+			// this won't work on all shapes (like Axes)
+			//
+			if(!mx.dx && !mx.dy){
+				// no change
+				return;
+			}
+			var backup = dojo.clone(this.points), abort = false;
+			dojo.forEach(this.points, function(o){
+				o.x += mx.dx;
+				o.y += mx.dy;
+				if(o.x<this.marginZero || o.y<this.marginZero){
+					abort = true;
+				}
+			});
+			if(abort){
+				this.points = backup;
+				console.error("Attempt to set object '"+this.id+"' to less than zero.");
+				return;
+			}
+			this.onTransform();
+			this.onTransformEnd();
+		},
+
+		applyTransform: function(mx){
+			// summary:
+			//		Applies the transform to the stencil
+			//		NOTE: PARTIALLY IMPLEMENTED
+			//			Only applies x y coords
+			this.transformPoints(mx);
+		},
+
+		setTransform: function(/*Object*/mx){
+			// summary:
+			//		Sets the transform to the stencil
+			//		NOTE: PARTIALLY IMPLEMENTED
+			//			Only applies x y coords
+			this.attr({
+				x:mx.dx,
+				y:mx.dy
+			});
+		},
+
+		getTransform: function(){
+			// summary:
+			//		Returns the current transform (position) of the Stencil's
+			//		container
+			return this.selected ? this.container.getParent().getTransform() : {dx:0, dy:0}; // Object
+		},
+
+		addShadow: function(/*Object*/args){
+			args = args===true ? {} : args;
+			args.stencil = this;
+			this.shadow = new dojox.drawing.annotations.BoxShadow(args);
+		},
+
+		removeShadow: function(){
+			this.shadow.destroy();
+		},
+
+		setLabel: function(/*String*/text){
+			// summary:
+			//		Creates and sets a label annotation for the Stencil.
+			//		If Stencil contains a labelPosition method, that will
+			//		be used for positioning. Otherwise
+			//		dojox.drawing.util.positioning.label is used.
+			// arguments:
+			//		text: String
+			//			The text to set as the label.
+			//
+			if(!this._label){
+				this._label = new dojox.drawing.annotations.Label({
+					text:text,
+					util:this.util,
+					mouse:this.mouse,
+					stencil:this,
+					annotation:true,
+					container:this.container,
+					labelPosition:this.labelPosition
+				});
+			}else if(text){
+				this._label.setLabel(text);
+			}
+		},
+
+		getLabel: function(){
+			// summary:
+			//		Get the text of the label.
+			//
+			if(this._label){
+				return this._label.getText(); // String
+			}
+			return null; //null
+		},
+
+		getAngle: function(){
+			// summary:
+			//		Gets angle of Stencil
+			// NOTE: Only works for Lines, Arrows, Vectors and Axes
+			//		(works on points, not transforms)
+			var d = this.pointsToData();
+			var obj = {
+				start:{
+					x:d.x1,
+					y:d.y1
+				},
+				x:d.x2,
+				y:d.y2
+			};
+			var angle = this.util.angle(obj, this.angleSnap);
+			// converting the angle for display: -180 -> 180, -90 -> 270
+			angle<0 ? angle = 360 + angle : angle;
+			return angle;
+		},
+		getRadius: function(){
+			// summary:
+			//		Gets radius (length) of Stencil
+			// NOTE: Only works for Lines, Arrows and Vectors
+			//	(not for Ellipse, Axes has its own version)
+			//
+			var box = this.getBounds(true);
+			var line = {start:{x:box.x1, y:box.y1}, x:box.x2, y:box.y2};
+			return this.util.length(line);
+		},
+		getBounds: function(/* ? Boolean*/absolute){
+			// summary:
+			//		Returns the coordinates of the Stencil. This is often
+			//		different than the data or the points.
+			//		arguments:
+			//			absolute: Boolean
+			//				Keeps lines from flipping (see note).
+			//
+			// NOTE: Won't work for paths or annotations (labels, Axes, arrow tips)
+			//		They should overwrite.
+			// NOTE: Primarily used for checking for if shape is off
+			//		canvas. Therefore Lines could get flipped. Use absolute
+			//		to prevent this.
+			//
+			var p = this.points, x1, y1, x2, y2;
+			if(p.length==2){
+				if(absolute){
+					x1 = p[0].x;
+					y1 = p[0].y;
+					x2 = p[1].x;
+					y2 = p[1].y
+				}else{
+					x1 = p[0].x < p[1].x ? p[0].x : p[1].x;
+					y1 = p[0].y < p[1].y ? p[0].y : p[1].y;
+					x2 = p[0].x < p[1].x ? p[1].x : p[0].x;
+					y2 = p[0].y < p[1].y ? p[1].y : p[0].y;
+				}
+				return {
+					x1:x1,
+					y1:y1,
+					x2:x2,
+					y2:y2,
+					x:x1,
+					y:y1,
+					w:x2-x1,
+					h:y2-y1
+				}; // Object
+			}else{
+				return {
+					x1:p[0].x,
+					y1:p[0].y,
+					x2:p[2].x,
+					y2:p[2].y,
+					x:p[0].x,
+					y:p[0].y,
+					w:p[2].x - p[0].x,
+					h:p[2].y - p[0].y
+				}; // Object
+			}
+		},
+
+
+		preventNegativePos: function(){
+			// summary:
+			//		Internal. Prevent item from being drawn/rendered less
+			//		than zero on the X or Y.
+			//
+			// if being modified anchors will prevent less than zero.
+			if(this._isBeingModified){ return; }
+			// FIXME: why is this sometimes empty?
+			if(!this.points || !this.points.length){ return; }
+
+			if(this.type=="dojox.drawing.tools.custom.Axes"){
+				// this scenario moves all points if < 0
+				var minY = this.marginZero, minX = this.marginZero;
+				dojo.forEach(this.points, function(p){ minY = Math.min(p.y, minY); });
+				dojo.forEach(this.points, function(p){ minX = Math.min(p.x, minX); });
+
+				if(minY<this.marginZero){
+					dojo.forEach(this.points, function(p, i){
+						p.y = p.y + (this.marginZero-minY)
+					}, this);
+				}
+				if(minX<this.marginZero){
+					dojo.forEach(this.points, function(p){
+						p.x += (this.marginZero-minX)
+					}, this);
+				}
+
+			}else{
+				// this scenario moves just the one point that is < 0
+				dojo.forEach(this.points, function(p){
+					p.x = p.x < 0 ? this.marginZero : p.x;
+					p.y = p.y < 0 ? this.marginZero : p.y;
+				});
+			}
+			this.setPoints(this.points);
+		},
+
+		_onPostRender: function(/*Object*/data){
+			// summary:
+			//		Drag-create or programmatic create calls onRender
+			//		and afterwards, _onPostRender is called and
+			//		manages further events.
+			//
+			// TODO: can this be onModify? Is that more clear?
+			//
+			//console.info("...........post render.....");
+
+			if(this._isBeingModified){
+				this.onModify(this);
+				this._isBeingModified = false;
+			}else if(!this.created){
+				//this.onCreate(this);
+				//this.onRender(this);
+			}
+
+			if(!this.editMode && !this.selected && this._prevData && dojo.toJson(this._prevData) != dojo.toJson(this.data)){
+				//console.info("_Base data changed ----> : this.editMode:", this.editMode)
+				this.onChangeData(this);
+				this._prevData = dojo.clone(this.data);
+
+			}else if(!this._prevData && (!this.isText || this.getText())){
+				//console.info("_Base no prevData..........................");
+				this._prevData = dojo.clone(this.data);
+
+			}
+
+		},
+
+		_setNodeAtts: function(shape){
+			// summary:
+			//		Internal. Sets the rawNode attribute. (Or in Silverlight
+			//		an "object attribute". "stencil" is
+			// 		used by the application to determine if
+			//		something is selectable or not. This also
+			//		sets the mouse custom events like:
+			//		"onStencilUp". To disable the selectability,
+			//		make the att "", which causes a standard
+			//		mouse event.
+			var att = this.enabled && !this.annotation ? this.drawingType : "";
+			this.util.attr(shape, "drawingType", att);
+		},
+
+
+		destroy: function(){
+			// summary:
+			//		Destroys this Stencil
+			// Note:
+			//		Can connect to this, but it's better to
+			//		connect to onDelete
+			//
+			// prevent loops:
+			if(this.destroyed){ return; }
+			if(this.data || this.points && this.points.length){
+				this.onDelete(this);
+			}
+
+			this.disconnectMouse();
+			this.disconnect(this._cons);
+			dojo.disconnect(this._postRenderCon);
+			this.remove(this.shape, this.hit);
+			this.destroyed = true;
+		},
+
+		remove: function(/*Shape...*/){
+			// summary:
+			//		Removes shape(s), typically before a re-render
+			// 		No args defaults to this.shape
+			//		Pass in multiple args to remove multiple shapes
+			//
+			// FIXME: Use an Array of all shapes
+			//
+			var a = arguments;
+			if(!a.length){
+				if(!this.shape){ return; }
+				a = [this.shape];
+			}
+			for(var i=0;i<a.length;i++){
+				if(a[i]){
+					a[i].removeShape();
+				}
+			}
+		},
+
+		connectMult: function(/*dojo.connect args */){
+			// summary:
+			//		Convenience method for batches of quick connects
+			// 		Handles are not returned and therefore cannot be
+			//		disconnected until Shape destroy time
+			//
+			if(arguments.length>1){
+				// arguments are the connect params
+				this._cons.push(this.connect.apply(this, arguments));
+			}else if(dojo.isArray(arguments[0][0])){
+				// an array of arrays of params
+				dojo.forEach(arguments[0], function(ar){
+					this._cons.push(this.connect.apply(this, ar));
+				}, this);
+			}else{
+				//one array of params
+				this._cons.push(this.connect.apply(this, arguments[0]));
+			}
+
+		},
+
+		// TODO: connect to a Shape event from outside class
+		connect: function(o, e, s, m, /* Boolean*/once){
+			// summary:
+			//		Convenience method for quick connects
+			//		See comments below for possiblities
+			//		functions can be strings
+			// once:
+			//		If true, the connection happens only
+			//		once then disconnects. Five args are required
+			//		for this functionality.
+			//
+			var c;
+			if(typeof(o)!="object"){
+				if(s){
+					// ** function object function **
+					m = s; s = e; e=o; o = this;
+				}else{
+					// ** function function **
+					m = e; e = o; o = s = this;
+				}
+			}else if(!m){
+				// ** object function function **
+				m = s; s = this;
+			}else if(once){
+				// ** object function object function Boolean **
+				c = dojo.connect(o, e, function(evt){
+					dojo.hitch(s, m)(evt);
+					dojo.disconnect(c);
+				});
+				this._cons.push(c);
+				return c;
+			}else{
+				// ** object function object function **
+			}
+			c = dojo.connect(o, e, s, m);
+			this._cons.push(c);
+			return c;
+		},
+
+		disconnect: function(/*handle | Array*/handles){
+			// summary:
+			//		Removes connections based on passed
+			//		handles arguments
+			if(!handles){ return }
+			if(!dojo.isArray(handles)){ handles=[handles]; }
+			dojo.forEach(handles, dojo.disconnect, dojo);
+		},
+
+		connectMouse: function(){
+			// summary:
+			//		Internal. Registers this Stencil to receive
+			//		mouse events.
+			this._mouseHandle = this.mouse.register(this);
+		},
+		disconnectMouse: function(){
+			// summary:
+			//		Internal. Unregisters this Stencil from receiving
+			//		mouse events.
+			this.mouse.unregister(this._mouseHandle);
+		},
+
+		// Should be overwritten by sub class:
+		render: function(){
+			// summary:
+			// 	This Stencil's render description. Often
+			//	calls 'sub render' methods.
+		},
+		//renderOutline: function(){},
+		dataToPoints: function(/*Object*/data){
+			// summary:
+			//		Converts data to points.
+		},
+		pointsToData: function(/*Array*/points){
+			// summary:
+			//		Converts points to data
+		},
+		onDown: function(/*EventObject*/obj){
+			// summary:
+			//		Mouse event, fired on mousedown on canvas
+			//
+			// by default, object is ready to accept data
+			// turn this off for dragging or onRender will
+			// keep firing and register the shape
+			// NOTE: Not needed for all stencils. Axes needs it.
+			this._downOnCanvas = true;
+			dojo.disconnect(this._postRenderCon);
+			this._postRenderCon = null;
+		},
+		onMove: function(/*EventObject*/obj){
+			// summary:
+			//		Mouse event, fired on mousemove while mouse
+			//		is not down.
+			//		NOTE: Not currently implemented
+		},
+		onDrag: function(/*EventObject*/obj){
+			// summary:
+			//		Mouse event, fired on mousemove while mouse
+			// 		is down on canvas
+		},
+		onUp: function(/*EventObject*/obj){
+			// summary:
+			//		Mouse event, fired on mouseup
+		}
+	}
+);
+
diff --git a/dojox/drawing/tests/drawing.html b/dojox/drawing/tests/drawing.html
new file mode 100755
index 0000000..a59f76d
--- /dev/null
+++ b/dojox/drawing/tests/drawing.html
@@ -0,0 +1,183 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+    <title>Drawing Test</title>
+	<link href="../resources/drawing.css" rel="stylesheet" />
+	<link href="../resources/toolbar.css" rel="stylesheet" />
+
+	<style>
+		href, body{
+		}
+		.drawing{
+			margin-left:52px;
+			width:800px;
+			height:500px;
+			border:1px solid #ccc;
+			cursor:crosshair;
+		}
+		#data{
+			display:block;
+			height:100px;
+			width:855px;
+			margin-top:5px;
+		}
+		button{
+			border:2px solid #ccc;
+			border-color:#D9E1F9 #B5BCD0 #878E9D #C6CEE4;
+			background-color:#CDDCF3;
+			cursor:pointer;
+		}
+	</style>
+
+	<script>
+		djConfig = {
+			isDebug:false,
+			parseOnLoad:true
+		};
+	</script>
+	<script src="../../../dojo/dojo.js"></script>
+	<script>
+		dojo.require("dojo.parser");
+		dojo.require("dojox.drawing");
+		// custom Tools and Plugins need to be required
+		dojo.require("dojox.drawing.ui.dom.Toolbar");
+		dojo.require("dojox.drawing.tools.TextBlock");
+		dojo.require("dojox.drawing.tools.Rect");
+		dojo.require("dojox.drawing.tools.Ellipse");
+		dojo.require("dojox.drawing.tools.Line");
+		dojo.require("dojox.drawing.tools.Path");
+
+		dojo.require("dojox.drawing.annotations.Label");
+		dojo.require("dojox.drawing.annotations.Angle");
+		dojo.require("dojox.drawing.annotations.Arrow");
+		dojo.require("dojox.drawing.annotations.BoxShadow");
+
+		dojo.require("dojox.drawing.tools.custom.Vector");
+		dojo.require("dojox.drawing.tools.custom.Axes");
+		dojo.require("dojox.drawing.tools.Arrow");
+		dojo.require("dojox.drawing.ui.dom.Pan");
+		dojo.require("dojox.drawing.ui.dom.Zoom");
+		dojo.require("dojox.drawing.plugins.drawing.Grid");
+
+
+		var doExport = function(){
+			var o = myDrawing.exporter();
+			console.log("EXPORT:")
+			console.dir(o)
+			console.log(dojo.toJson(o));
+			dojo.byId("data").value = dojo.toJson(o, true);
+		}
+
+		var doImport = function(){
+			myDrawing.importer(dojo.fromJson(dojo.byId("data").value));
+		}
+
+		var doClear = function(){
+			myDrawing.removeAll();
+		}
+
+		dojo.addOnLoad(function(){
+
+
+			// myDrawing referenced by jsId
+			dojo.connect(myDrawing, "onSurfaceReady", function(){
+
+				var rect = myDrawing.addStencil("rect", {data:{x:50, y:275, width:100, height:100}});
+
+
+				var json = '[{"color":"#0000FF","style":"Solid","cap":"round","fill":{"r":256,"g":0,"b":0,"a":0.5},"borderWidth":1,"x":413,"y":366,"width":100,"height":32,"type":"textBlock","text":"DojoX Drawing is Mike","pad":3,"size":"12px","family":"sans-serif","weight":"normal"},{"color":"#0000FF","style":"Solid","cap":"round","fill":{"r":256,"g":0,"b":0,"a":0.5},"borderWidth":1,"cx":732.5,"cy":197.54166412353516,"rx":54.5,"ry":187.54166412353516,"type":"ellipse"},{"color":"#000000","style":"Sol [...]
+				dojo.byId("data").value = json;
+
+
+				var textBlock = myDrawing.addStencil("textBlock", {data:{x:20, y:30, width:200, text:"DojoX Drawing Rocks"}});
+				textBlock.attr({fill:{r:256,g:0,b:0,a:.5}, width:10, color:"#0000FF", size:"24px", weight:"bold"});
+
+
+				var ellipse = myDrawing.addStencil("ellipse", {data:{cx:200, cy:200, rx:100, ry:50}});
+				ellipse.attr({fill:{r:256,g:0,b:0,a:.5}, width:500, height:200, color:"#0000FF"});
+
+
+				var arrow = myDrawing.addStencil("arrow", {data:{x1:400, y1:200, x2:500, y2:300}, arrowStart:true});
+				arrow.attr({angle:210, radius:200, borderWidth:3, label:"My Arrow"})
+
+				var text = myDrawing.addStencil("text", {data:{x:300, y:260, width:200, text:"This is just text"}});
+
+				myDrawing.addStencil("path", {points:[{x:700, y:20},{x:650, y:150},{x:750,y:150}, {t:"Z", x:700, y:20}, {t:"M", x:700, y:40},{x:680, y:120},{x:720,y:120} ], shadow:{place:"C", size:4, mult:4, color:"#00ff00"}});//
+
+			});
+
+			dojo.connect(dojo.byId("import"), "click", doImport);
+			dojo.connect(dojo.byId("export"), "click", doExport);
+			dojo.connect(dojo.byId("clear"), "click", doClear);
+			dojo.connect(dojo.byId("selectall"), "click", function(){
+				myDrawing.selectAll();
+			});
+
+			dojo.connect(dojo.byId("red"), "click", function(){
+				myDrawing.changeDefaults({
+					norm:{
+						fill:"#ff0000",
+						width:5,
+						color:"#ff00ff"
+					}
+				});
+			});
+			dojo.connect(dojo.byId("blue"), "click", function(){
+				myDrawing.changeDefaults({
+					norm:{
+						fill:"#0000ff",
+						width:5,
+						color:"#ffff00"
+					}
+				});
+			});
+			dojo.connect(dojo.byId("yellow"), "click", function(){
+				myDrawing.toSelected("attr", {
+					fill:"#ffff00"
+				});
+			});
+		});
+
+
+	</script>
+
+</head>
+<body>
+    <h2>Drawing Test</h2>
+	<div id="conEdit" contenteditable="true"></div>
+	<div id="wrapper">
+		<div dojoType="dojox.drawing.ui.dom.Toolbar" drawingId="drawingNode" class="drawingToolbar vertical">
+			<div tool="dojox.drawing.tools.Line" selected="false">Line</div>
+			<div tool="dojox.drawing.tools.Rect" selected="false">Rect</div>
+			<div tool="dojox.drawing.tools.Ellipse" selected="false">Ellipse</div>
+			<div tool="dojox.drawing.tools.Path" selected="true">Path</div>
+			<div tool="dojox.drawing.tools.TextBlock" selected="false">Text</div>
+			<div tool="dojox.drawing.tools.Arrow" selected="false">Arrow</div>
+			<div tool="dojox.drawing.tools.custom.Vector" selected="false">Vector</div>
+			<div tool="dojox.drawing.tools.custom.Axes" selected="false">Axes</div>
+			<div plugin="dojox.drawing.ui.dom.Pan" options="{}">Pan</div>
+			<div plugin="dojox.drawing.ui.dom.Zoom" options="{zoomInc:.1,minZoom:.5,maxZoom:2}">Zoom</div>
+
+		</div>
+
+		<div dojoType="dojox.drawing.Drawing" id="drawingNode" jsId="myDrawing" drawingType="canvas" class="drawing"
+			 plugins="[{'name':'dojox.drawing.plugins.drawing.Grid', 'options':{gap:100}}]">
+
+		</div>
+	</div>
+
+	<br/>
+	<br/>
+	<button id="import">Import</button>
+	<button id="export">Export</button>
+	<button id="selectall">Select All</button>
+	<button id="clear">Clear Drawing</button>
+	   
+	<button id="blue">Change defaults to Blue</button>
+	<button id="red">Change defaults to Red</button>
+	<button id="yellow">Change selected to Yellow</button>
+	<br/>
+	<br/>
+
+	<textarea id="data"></textarea>
+</body>
+</html>
diff --git a/dojox/drawing/tests/test_drawing.html b/dojox/drawing/tests/test_drawing.html
new file mode 100644
index 0000000..06d76f4
--- /dev/null
+++ b/dojox/drawing/tests/test_drawing.html
@@ -0,0 +1,158 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+    <title>Drawing GFX Toolbar Test</title>
+	<link href="../resources/drawing.css" rel="stylesheet" />
+	<link href="../resources/toolbar.css" rel="stylesheet" />
+
+	<style>
+		href, body{
+		}
+		.drawing{
+			width:800px;
+			height:500px;
+			border:1px solid #ccc;
+			cursor:crosshair;
+		}
+		#data{
+			display:block;
+			height:100px;
+			width:800px;
+			margin-top:5px;
+		}
+		button{
+			border:2px solid #ccc;
+			border-color:#D9E1F9 #B5BCD0 #878E9D #C6CEE4;
+			background-color:#CDDCF3;
+			cursor:pointer;
+		}
+		.gfxToolbar{
+			width:800px;
+			height:50px;
+			margin-bottom:10px;
+			border:1px solid #ccc;
+		}
+	</style>
+
+	<script>
+		djConfig = {
+			isDebug:false,
+			parseOnLoad:true
+		};
+	</script>
+	<script src="../../../dojo/dojo.js"></script>
+	<script>
+		dojo.require("dojo.parser");
+		dojo.require("dojox.drawing");
+
+
+		// custom Tools and Plugins need to be required
+		dojo.require("dojox.drawing.tools.TextBlock");
+		dojo.require("dojox.drawing.tools.Rect");
+		dojo.require("dojox.drawing.tools.Ellipse");
+		dojo.require("dojox.drawing.tools.Line");
+		dojo.require("dojox.drawing.tools.Path");
+		dojo.require("dojox.drawing.tools.Pencil");
+
+		dojo.require("dojox.drawing.tools.custom.Vector");
+		dojo.require("dojox.drawing.tools.custom.Axes");
+		dojo.require("dojox.drawing.tools.Arrow");
+
+		dojo.require("dojox.drawing.plugins.tools.Pan");
+		dojo.require("dojox.drawing.plugins.tools.Zoom");
+		dojo.require("dojox.drawing.plugins.tools.Iconize");
+
+		dojo.require("dojox.drawing.plugins.drawing.Grid");
+
+		dojo.require("dojox.drawing.ui.Toolbar");
+		dojo.require("dojox.drawing.ui.Button");
+		//dojo.require("dojox.drawing.ui.Tooltip");
+
+		var doExport = function(){
+			var o = myDrawing.exporter();
+			console.log("EXPORT:")
+			console.dir(o)
+			console.log(dojo.toJson(o));
+			dojo.byId("data").value = dojo.toJson(o, true);
+		}
+
+		var doImport = function(){
+			myDrawing.importer(dojo.fromJson(dojo.byId("data").value));
+		}
+
+		var doClear = function(){
+			myDrawing.removeAll();
+		}
+
+		dojo.addOnLoad(function(){
+			dojo.connect(myDrawing, "onSurfaceReady", function(){
+				new dojox.drawing.ui.Toolbar({
+					drawing:myDrawing,
+					tools:"all",
+					plugs:"all",
+					selected:"ellipse",
+					size:30,
+					radius:2,
+					margin:5
+				});
+
+			});
+
+			dojo.connect(dojo.byId("import"), "click", doImport);
+			dojo.connect(dojo.byId("export"), "click", doExport);
+			dojo.connect(dojo.byId("clear"), "click", doClear);
+			dojo.connect(dojo.byId("selectall"), "click", function(){
+				myDrawing.selectAll();
+			});
+
+			dojo.connect(dojo.byId("red"), "click", function(){
+				myDrawing.changeDefaults({
+					norm:{
+						fill:"#ff0000",
+						width:5,
+						color:"#ff00ff"
+					}
+				});
+			});
+			dojo.connect(dojo.byId("blue"), "click", function(){
+				myDrawing.changeDefaults({
+					norm:{
+						fill:"#0000ff",
+						width:5,
+						color:"#ffff00"
+					}
+				});
+			});
+			dojo.connect(dojo.byId("yellow"), "click", function(){
+				myDrawing.toSelected("attr", {
+					fill:"#ffff00"
+				});
+			});
+		})
+	</script>
+
+</head>
+<body>
+    <h2>Drawing Test</h2>
+	<div id="conEdit" contenteditable="true"></div>
+	<div id="wrapper">
+		<div dojoType="dojox.drawing.Drawing" id="drawingNode" jsId="myDrawing" class="drawing"
+			 plugins="[{'name':'dojox.drawing.plugins.drawing.Grid', 'options':{minor:20, major:100}}]">
+		</div>
+	</div>
+
+	<br/>
+	<button id="import">Import</button>
+	<button id="export">Export</button>
+	<button id="selectall">Select All</button>
+	<button id="clear">Clear Drawing</button>
+	   
+	<button id="blue">Change defaults to Blue</button>
+	<button id="red">Change defaults to Red</button>
+	<button id="yellow">Change selected to Yellow</button>
+	<br/>
+	<br/>
+
+	<textarea id="data"></textarea>
+
+</body>
+</html>
diff --git a/dojox/drawing/tests/test_drawing_toolbar.html b/dojox/drawing/tests/test_drawing_toolbar.html
new file mode 100644
index 0000000..70ed70b
--- /dev/null
+++ b/dojox/drawing/tests/test_drawing_toolbar.html
@@ -0,0 +1,101 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+    <title>Drawing Test</title>
+	<link href="../resources/drawing.css" rel="stylesheet" />
+	<link href="../resources/toolbar.css" rel="stylesheet" />
+
+	<style>
+		href, body{
+			overflow:hidden;
+		}
+		.drawing{
+			margin-left:52px;
+			width:800px;
+			height:400px;
+			border:1px solid #ccc;
+			cursor:crosshair;
+			position:absolute;
+			left:52px;
+			top:100px;
+		}
+		#data{
+			display:block;
+			height:100px;
+			width:855px;
+			margin-top:5px;
+		}
+		button{
+			border:2px solid #ccc;
+			border-color:#D9E1F9 #B5BCD0 #878E9D #C6CEE4;
+			background-color:#CDDCF3;
+			cursor:pointer;
+		}
+		.gfxToolbar{
+			width:800px;
+			height:50px;
+			margin-bottom:10px;
+			margin-left:52px;
+			border:1px solid #ccc;
+		}
+		.gfxToolbar{
+			width:50px;
+			height:800px;
+			margin-top:50px;
+			margin-left:2px;
+			border:1px solid #ccc;
+		}
+	</style>
+	
+	<script>
+		djConfig = {
+			isDebug:false,
+			parseOnLoad:true
+		};
+	</script>
+	<script src="../../../dojo/dojo.js"></script>
+	<script>
+		dojo.require("dojo.parser");
+		dojo.require("dojox.drawing");
+		
+		
+		// custom Tools and Plugins need to be required
+		dojo.require("dojox.drawing.tools.TextBlock");
+		dojo.require("dojox.drawing.tools.Rect");
+		dojo.require("dojox.drawing.tools.Ellipse");
+		dojo.require("dojox.drawing.tools.Line");
+		dojo.require("dojox.drawing.tools.Path");
+		
+		dojo.require("dojox.drawing.annotations.Label");
+		dojo.require("dojox.drawing.annotations.Angle");
+		dojo.require("dojox.drawing.annotations.Arrow");
+		dojo.require("dojox.drawing.annotations.BoxShadow");
+
+		dojo.require("dojox.drawing.tools.custom.Vector");
+		dojo.require("dojox.drawing.tools.custom.Axes");				
+		dojo.require("dojox.drawing.tools.Arrow");
+		dojo.require("dojox.drawing.plugins.tools.Pan");
+		dojo.require("dojox.drawing.plugins.tools.Zoom");
+		dojo.require("dojox.drawing.plugins.drawing.Grid");
+		
+		dojo.require("dojox.drawing.ui.Toolbar");
+		dojo.require("dojox.drawing.ui.Button");
+		dojo.require("dojox.drawing.library.icons");
+
+		
+	</script>
+
+</head>
+<body>
+    <h2>Drawing Test</h2>
+	<div id="conEdit" contenteditable="true"></div>
+	<div id="wrapper">
+		
+		<div dojoType="dojox.drawing.ui.Toolbar" id="gfxToolbarNode" drawingId="drawingNode" class="gfxToolbar" tools="all" plugs="all" selected="ellipse"></div>
+		
+		<div dojoType="dojox.drawing.Drawing" id="drawingNode" jsId="myDrawing" class="drawing"
+			 plugins="[{'name':'dojox.drawing.plugins.drawing.Grid', 'options':{gap:100}}]">
+		</div>
+	</div>
+	
+</body>
+</html>
diff --git a/dojox/drawing/tests/test_paths.html b/dojox/drawing/tests/test_paths.html
new file mode 100644
index 0000000..49306cd
--- /dev/null
+++ b/dojox/drawing/tests/test_paths.html
@@ -0,0 +1,116 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+    <title>Drawing Paths Test</title>
+	<link href="../resources/drawing.css" rel="stylesheet" />
+	<link href="../resources/toolbar.css" rel="stylesheet" />
+
+	<style>
+		href, body{
+			overflow:hidden;
+		}
+		.drawing{
+			width:800px;
+			height:400px;
+			border:1px solid #ccc;
+			cursor:crosshair;
+		}
+		#data{
+			display:block;
+			height:100px;
+			width:855px;
+			margin-top:5px;
+		}
+		button{
+			border:2px solid #ccc;
+			border-color:#D9E1F9 #B5BCD0 #878E9D #C6CEE4;
+			background-color:#CDDCF3;
+			cursor:pointer;
+		}
+		.gfxToolbar{
+			width:800px;
+			height:50px;
+			margin-bottom:10px;
+			border:1px solid #ccc;
+		}
+	</style>
+	
+	<script>
+		djConfig = {
+			isDebug:false,
+			parseOnLoad:true
+		};
+	</script>
+	<script src="../../../dojo/dojo.js"></script>
+	<script>
+		dojo.require("dojo.parser");
+		dojo.require("dojox.drawing");
+		
+		
+		// custom Tools and Plugins need to be required
+		dojo.require("dojox.drawing.tools.TextBlock");
+		dojo.require("dojox.drawing.tools.Rect");
+		dojo.require("dojox.drawing.tools.Ellipse");
+		dojo.require("dojox.drawing.tools.Line");
+		dojo.require("dojox.drawing.tools.Path");
+		dojo.require("dojox.drawing.tools.Pencil");
+		
+		dojo.require("dojox.drawing.plugins.drawing.Grid");
+		
+		dojo.require("dojox.drawing.ui.Toolbar");
+		dojo.require("dojox.drawing.ui.Button");
+		
+
+		dojo.addOnLoad(function(){
+			dojo.connect(myDrawing, "onSurfaceReady", function(){
+				
+				var path = function(pts, dontClosePath){
+					var closePath = !dontClosePath;
+					myDrawing.addStencil("path", {points:pts, closePath:closePath});
+					
+				}
+				
+				// Test Q curve
+				path([{x:210, y:210},{t:"Q", x:300, y:400},{x:400,y:210} ])
+				
+				// Test closing path on a Q curve (have to use a double-point)
+				path([{t:"Q", x:300, y:390},{x:500, y:390},{t:"Q", x:400,y:300}, {x:300,y:390} ])
+				
+				// test double donut
+				path([
+					  {x:10, y:390},{x:10, y:200},{x:100,y:200},{x:100,y:390}, {t:"Z"},
+					  {t:"M", x:20, y:210}, {x:90,y:210}, {x:90, y:290}, {x:20, y:290}, {t:"Z"},
+					  {t:"M", x:20, y:310}, {x:90,y:310}, {x:90, y:380}, {x:20, y:380} , {t:"Z"}
+				]);
+				
+				//  test unclosed paths
+				path([{x:300, y:10},{x:400, y:50}, {x:320, y:100}], true);
+				path([{x:400, y:10},{x:500, y:50}, {x:420, y:100}], true);
+				
+				// approximate a circle
+				path([
+					  {x:600, y:150},{t:"Q", x:600, y:100},{x:650,y:100}, {x:700, y:100},
+					  {x:700,y:150},{x:700,y:200},{x:650,y:200},{x:600,y:200},{x:600,y:150}
+					  ]);
+				
+				// pencil icon
+				path([ { x:68, y:20 }, { x:80, y:32 }, { x:32, y:74 }, { x:20, y:80 }, { x:62, y:74 }, { x:80, y:80 }, { x:20, y:80 }, { x:26, y:68 }, { t:'Z' }, { t:'M', x:26, y:74 }, { x:26, y:68 }, { x:62, y:32 }, { x:68, y:38 }, { x:62, y:38 }, { x:32, y:68 } ])
+			});	
+		})
+	</script>
+
+</head>
+<body>
+    <h2>Drawing Paths Test</h2>
+	<div id="conEdit" contenteditable="true"></div>
+	<div id="wrapper">
+		
+		
+		<div dojoType="dojox.drawing.ui.Toolbar" id="gfxToolbarNode" drawingId="drawingNode" class="gfxToolbar" tools="all" plugs="all" selected="pencil"></div>
+		
+		<div dojoType="dojox.drawing.Drawing" id="drawingNode" jsId="myDrawing" class="drawing"
+			 plugins="[{'name':'dojox.drawing.plugins.drawing.Grid', 'options':{minor:20, major:100}}]">
+		</div>
+	</div>
+	
+</body>
+</html>
diff --git a/dojox/drawing/tests/test_shadows.html b/dojox/drawing/tests/test_shadows.html
new file mode 100644
index 0000000..a9b8e9c
--- /dev/null
+++ b/dojox/drawing/tests/test_shadows.html
@@ -0,0 +1,99 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+    <title>Drawing GFX Toolbar Test</title>
+	<link href="../resources/drawing.css" rel="stylesheet" />
+	<link href="../resources/toolbar.css" rel="stylesheet" />
+
+	<style>
+		href, body{
+			overflow:hidden;
+		}
+		.drawing{
+			width:800px;
+			height:400px;
+			border:1px solid #ccc;
+			cursor:crosshair;
+		}
+		#data{
+			display:block;
+			height:100px;
+			width:855px;
+			margin-top:5px;
+		}
+		button{
+			border:2px solid #ccc;
+			border-color:#D9E1F9 #B5BCD0 #878E9D #C6CEE4;
+			background-color:#CDDCF3;
+			cursor:pointer;
+		}
+		.gfxToolbar{
+			width:800px;
+			height:50px;
+			margin-bottom:10px;
+			border:1px solid #ccc;
+		}
+	</style>
+
+	<script>
+		djConfig = {
+			isDebug:false,
+			parseOnLoad:true
+		};
+	</script>
+	<script src="../../../dojo/dojo.js"></script>
+	<script>
+		dojo.require("dojo.parser");
+		dojo.require("dojox.drawing");
+
+
+		// custom Tools and Plugins need to be required
+		dojo.require("dojox.drawing.tools.TextBlock");
+		dojo.require("dojox.drawing.tools.Rect");
+		dojo.require("dojox.drawing.tools.Ellipse");
+		dojo.require("dojox.drawing.tools.Line");
+		dojo.require("dojox.drawing.tools.Path");
+
+		dojo.require("dojox.drawing.plugins.drawing.Grid");
+
+		dojo.require("dojox.drawing.ui.Toolbar");
+		dojo.require("dojox.drawing.ui.Button");
+
+
+		dojo.addOnLoad(function(){
+			dojo.connect(myDrawing, "onSurfaceReady", function(){
+
+				var image = myDrawing.addStencil("image", {data:{x:450, y:125, width:320, height:240, src:"../resources/CrazyTruck.jpg"}, shadow:{place:"BR", size:8, mult:6}});
+
+				myDrawing.addStencil("rect", {data:{x:50, y:25, width:100, height:50}, shadow:{color:"#0000ff", place:"TL"}});
+				myDrawing.addStencil("rect", {data:{x:50, y:100, width:100, height:50, r:10}, shadow:{place:"C", color:"#ff0000", size:8, mult:6}});
+				myDrawing.addStencil("rect", {data:{x:50, y:175, width:100, height:50, r:10}, shadow:{place:"BR"}});
+
+				myDrawing.addStencil("ellipse", {data:{cx:300, cy:60, rx:100, ry:50, fill:{r:200,g:200,b:0,a:1}}, shadow:{place:"TL"}});
+				myDrawing.addStencil("ellipse", {data:{cx:300, cy:175, rx:100, ry:50, fill:{r:200,g:200,b:0,a:1}}, shadow:{place:"C", size:6, mult:4, color:"#ffff00"}});
+				myDrawing.addStencil("ellipse", {data:{cx:300, cy:290, rx:100, ry:50, fill:{r:200,g:200,b:0,a:1}}, shadow:{place:"BR"}});
+
+				myDrawing.addStencil("line", {data:{x1:500, y1:70, x2:700, y2:10}, shadow:{place:"BR", size:4, mult:2}});
+				myDrawing.addStencil("line", {data:{x1:500, y1:100, x2:700, y2:100}, shadow:{place:"C", size:4, mult:4, color:"#00ff00"}});
+
+				myDrawing.addStencil("path", {points:[{x:10, y:390},{x:50, y:250},{x:175,y:330}, {x:100,y:300} ], shadow:{place:"C", size:4, mult:4, color:"#00ff00"}});//
+
+			});
+		})
+	</script>
+
+</head>
+<body>
+    <h2>Drawing Test</h2>
+	<div id="conEdit" contenteditable="true"></div>
+	<div id="wrapper">
+
+
+		<!--<div dojoType="dojox.drawing.ui.Toolbar" id="gfxToolbarNode" drawingId="drawingNode" class="gfxToolbar" tools="all" plugs="all" selected="ellipse"></div>-->
+
+		<div dojoType="dojox.drawing.Drawing" id="drawingNode" jsId="myDrawing" class="drawing"
+			 plugins="[{'name':'dojox.drawing.plugins.drawing.Grid', 'options':{minor:20, major:100}}]">
+		</div>
+	</div>
+
+</body>
+</html>
diff --git a/dojox/drawing/tools/Arrow.js b/dojox/drawing/tools/Arrow.js
old mode 100644
new mode 100755
index 718bb7b..da84a1c
--- a/dojox/drawing/tools/Arrow.js
+++ b/dojox/drawing/tools/Arrow.js
@@ -1,38 +1,68 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.tools.Arrow");
 
+dojox.drawing.tools.Arrow = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Extends stencil.Line and adds an arrow head
+	//		to the end and or start.
+	//
+	dojox.drawing.tools.Line,
+	function(options){
+		// summary: constructor
+		if(this.arrowStart){
+			this.begArrow = new dojox.drawing.annotations.Arrow({stencil:this, idx1:0, idx2:1});
+		}
+		if(this.arrowEnd){
+			this.endArrow = new dojox.drawing.annotations.Arrow({stencil:this, idx1:1, idx2:0});
+		}
+		if(this.points.length){
+			this.render();
+		}
+	},
+	{
+		draws:true,
+		type:"dojox.drawing.tools.Arrow",
+		baseRender:false,
+		
+		// arrowStart: Boolean
+		//		Whether or not to place an arrow on start.
+		arrowStart:false,
+		//
+		// arrowEnd: Boolean
+		//		Whether or not to place an arrow on end.
+		arrowEnd:true,
+		
+		
+		onUp: function(/*EventObject*/obj){
+			// summary: See stencil._Base.onUp
+			//
+			if(this.created || !this.shape){ return; }
+			
+			// if too small, need to reset
+			var p = this.points;
+			var len = this.util.distance(p[0].x,p[0].y,p[1].x,p[1].y);
+			if(len<this.minimumSize){
+				this.remove(this.shape, this.hit);
+				return;
+			}
+			
+			var pt = this.util.snapAngle(obj, this.angleSnap/180);
+			this.setPoints([
+				{x:p[0].x, y:p[0].y},
+				{x:pt.x, y:pt.y}
+			]);
+			
+			this.renderedOnce = true;
+			this.onRender(this);
+		}
+	}
+);
 
-if(!dojo._hasResource["dojox.drawing.tools.Arrow"]){
-dojo._hasResource["dojox.drawing.tools.Arrow"]=true;
-dojo.provide("dojox.drawing.tools.Arrow");
-dojox.drawing.tools.Arrow=dojox.drawing.util.oo.declare(dojox.drawing.tools.Line,function(_1){
-if(this.arrowStart){
-this.begArrow=new dojox.drawing.annotations.Arrow({stencil:this,idx1:0,idx2:1});
-}
-if(this.arrowEnd){
-this.endArrow=new dojox.drawing.annotations.Arrow({stencil:this,idx1:1,idx2:0});
-}
-if(this.points.length){
-this.render();
-}
-},{draws:true,type:"dojox.drawing.tools.Arrow",baseRender:false,arrowStart:false,arrowEnd:true,onUp:function(_2){
-if(this.created||!this.shape){
-return;
-}
-var p=this.points;
-var _3=this.util.distance(p[0].x,p[0].y,p[1].x,p[1].y);
-if(_3<this.minimumSize){
-this.remove(this.shape,this.hit);
-return;
-}
-var pt=this.util.snapAngle(_2,this.angleSnap/180);
-this.setPoints([{x:p[0].x,y:p[0].y},{x:pt.x,y:pt.y}]);
-this.renderedOnce=true;
-this.onRender(this);
-}});
-dojox.drawing.tools.Arrow.setup={name:"dojox.drawing.tools.Arrow",tooltip:"Arrow Tool",iconClass:"iconArrow"};
-dojox.drawing.register(dojox.drawing.tools.Arrow.setup,"tool");
-}
+dojox.drawing.tools.Arrow.setup = {
+	// summary: See stencil._Base ToolsSetup
+	//
+	name:"dojox.drawing.tools.Arrow",
+	tooltip:"Arrow Tool",
+	iconClass:"iconArrow"
+};
+
+dojox.drawing.register(dojox.drawing.tools.Arrow.setup, "tool");
\ No newline at end of file
diff --git a/dojox/drawing/tools/Ellipse.js b/dojox/drawing/tools/Ellipse.js
old mode 100644
new mode 100755
index 90f2bdf..e7cb627
--- a/dojox/drawing/tools/Ellipse.js
+++ b/dojox/drawing/tools/Ellipse.js
@@ -1,46 +1,79 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.tools.Ellipse");
 
+dojox.drawing.tools.Ellipse = dojox.drawing.util.oo.declare(
+	// summary:
+	//		A drawable Ellipse.
+	//
+	dojox.drawing.stencil.Ellipse,
+	function(){
+		// summary: constructor
+	},
+	{
+		draws:true,
+		onDrag: function(/*EventObject*/obj){
+			// summary: See stencil._Base.onDrag
+			//
+			var s = obj.start, e = obj;
+			var	x = s.x < e.x ? s.x : e.x,
+				y = s.y < e.y ? s.y : e.y,
+				w = s.x < e.x ? e.x-s.x : s.x-e.x,
+				h = s.y < e.y ? e.y-s.y : s.y-e.y;
+			
+			if(this.keys.shift){ w = h = Math.max(w,h); }
+			if(!this.keys.alt){ // ellipse is normally on center
+				x+=w/2; y+=h/2; w/=2; h/=2;
+			} else{
+				if(y - h < 0){ h = y; }
+				if(x - w < 0){ w = x; }
+			}
+			
+			this.points = [
+				{x:x-w, y:y-h}, 	// TL
+				{x:x+w, y:y-h},		// TR
+				{x:x+w, y:y+h},		// BR
+				{x:x-w, y:y+h}		// BL
+			];
+			this.render();
+		},
+		
+		onUp: function(/*EventObject*/obj){
+			// summary: See stencil._Base.onUp
+			//
+			if(this.created || !this._downOnCanvas){ return; }
+			this._downOnCanvas = false;
+			//Default shape on single click
+			if(!this.shape){
+				var s = obj.start, e = this.minimumSize*2;
+				this.data = {
+					cx: s.x+e,
+					cy: s.y+e,
+					rx: e,
+					ry: e
+				};
+				this.dataToPoints();
+				this.render();
+			}else{
+			// if too small, need to reset
+				var o = this.pointsToData();
+				console.log("Create a default shape here, pt to data: ",o);
+				if(o.rx*2<this.minimumSize && o.ry*2 < this.minimumSize){
+					this.remove(this.shape, this.hit);
+					return;
+				}
+			}
+			
+			this.onRender(this);
+			
+		}
+	}
+);
 
-if(!dojo._hasResource["dojox.drawing.tools.Ellipse"]){
-dojo._hasResource["dojox.drawing.tools.Ellipse"]=true;
-dojo.provide("dojox.drawing.tools.Ellipse");
-dojox.drawing.tools.Ellipse=dojox.drawing.util.oo.declare(dojox.drawing.stencil.Ellipse,function(){
-},{draws:true,onDrag:function(_1){
-var s=_1.start,e=_1;
-var x=s.x<e.x?s.x:e.x,y=s.y<e.y?s.y:e.y,w=s.x<e.x?e.x-s.x:s.x-e.x,h=s.y<e.y?e.y-s.y:s.y-e.y;
-if(this.keys.shift){
-w=h=Math.max(w,h);
-}
-if(!this.keys.alt){
-x+=w/2;
-y+=h/2;
-w/=2;
-h/=2;
-}else{
-if(y-h<0){
-h=y;
-}
-if(x-w<0){
-w=x;
-}
-}
-this.points=[{x:x-w,y:y-h},{x:x+w,y:y-h},{x:x+w,y:y+h},{x:x-w,y:y+h}];
-this.render();
-},onUp:function(_2){
-if(this.created||!this.shape){
-return;
-}
-var o=this.pointsToData();
-if(o.rx*2<this.minimumSize&&o.ry*2<this.minimumSize){
-this.remove(this.shape,this.hit);
-return;
-}
-this.onRender(this);
-}});
-dojox.drawing.tools.Ellipse.setup={name:"dojox.drawing.tools.Ellipse",tooltip:"Ellipse Tool",iconClass:"iconEllipse"};
-dojox.drawing.register(dojox.drawing.tools.Ellipse.setup,"tool");
-}
+dojox.drawing.tools.Ellipse.setup = {
+	// summary: See stencil._Base ToolsSetup
+	//	
+	name:"dojox.drawing.tools.Ellipse",
+	tooltip:"Ellipse Tool",
+	iconClass:"iconEllipse"
+};
+
+dojox.drawing.register(dojox.drawing.tools.Ellipse.setup, "tool");
\ No newline at end of file
diff --git a/dojox/drawing/tools/Line.js b/dojox/drawing/tools/Line.js
old mode 100644
new mode 100755
index c5516ad..45138f3
--- a/dojox/drawing/tools/Line.js
+++ b/dojox/drawing/tools/Line.js
@@ -1,61 +1,118 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.tools.Line");
 
+dojox.drawing.tools.Line = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Class for a drawable Line
+	dojox.drawing.stencil.Line,
+	function(){
+		// summary: constructor
+	},
+	{
+		draws:true,
+		showAngle:true,
+		onTransformEnd: function(/*manager.Anchor*/anchor){
+			// summary:
+			//	Overwrites _Base.onTransformEnd
+			//
+			this._toggleSelected();
+			if(this.getRadius()<this.minimumSize){ 
+				var p = this.points; 
+				this.setPoints([ 
+					{x:p[0].x, y:p[0].y}, 
+					{x:p[0].x, y:p[0].y} 
+				]); 
+			}else{
+				var d = this.data;
+				var obj = {start:{x:d.x1,y:d.y1},x:d.x2,y:d.y2};
+				var pt = this.util.snapAngle(obj, this.angleSnap/180);
+				this.setPoints([
+					{x:d.x1, y:d.y1},
+					{x:pt.x, y:pt.y}
+				]);
+				
+				this._isBeingModified = false;
+				this.onModify(this);
+			}
+		},
+		
+		onDrag: function(/*EventObject*/obj){
+			// summary: See stencil._Base.onDrag
+			//
+			if(this.created){ return; }
+			var x1 = obj.start.x,
+				y1 = obj.start.y,
+				x2 = obj.x,
+				y2 = obj.y;
+			
+			if(this.keys.shift){
+				var pt = this.util.snapAngle(obj, 45/180);
+				x2 = pt.x;
+				y2 = pt.y;
+			}
+			
+			if(this.keys.alt){
+				// FIXME:
+				//	should double the length of the line
+				// FIXME:
+				//	if alt dragging past ZERO it seems to work
+				//	but select/deselect shows bugs
+				var dx = x2>x1 ? ((x2-x1)/2) : ((x1-x2)/-2);
+				var dy = y2>y1 ? ((y2-y1)/2) : ((y1-y2)/-2);
+				x1 -= dx;
+				x2 -= dx;
+				y1 -= dy;
+				y2 -= dy;
+			}
+			
+			this.setPoints([
+				{x:x1, y:y1},
+				{x:x2, y:y2}
+			]);
+			this.render();
+		},
+		
+		onUp: function(/*EventObject*/obj){
+			// summary: See stencil._Base.onUp
+			//
+			if(this.created || !this._downOnCanvas){ return; }
+			this._downOnCanvas = false;
+			//Default shape on single click
+			if(!this.shape){
+				var s = obj.start, e = this.minimumSize*4;
+				this.setPoints([
+					{x:s.x, y:s.y+e},
+					{x:s.x, y:s.y}
+				]);
+				this.render();
+				
+			}else{
+				// if too small, need to reset
+				
+				if(this.getRadius()<this.minimumSize){
+					this.remove(this.shape, this.hit);
+					return;
+				}
+			}
+			
+			var pt = this.util.snapAngle(obj, this.angleSnap/180);
+			var p = this.points;
+			this.setPoints([
+				{x:p[0].x, y:p[0].y},
+				{x:pt.x, y:pt.y}
+			]);
+			
+			this.renderedOnce = true;
+			this.onRender(this);
+		}
+	}
+);
 
-if(!dojo._hasResource["dojox.drawing.tools.Line"]){
-dojo._hasResource["dojox.drawing.tools.Line"]=true;
-dojo.provide("dojox.drawing.tools.Line");
-dojox.drawing.tools.Line=dojox.drawing.util.oo.declare(dojox.drawing.stencil.Line,function(){
-},{draws:true,showAngle:true,onTransformEnd:function(_1){
-this._toggleSelected();
-if(this.getRadius()<this.minimumSize){
-var p=this.points;
-this.setPoints([{x:p[0].x,y:p[0].y},{x:p[0].x,y:p[0].y}]);
-}else{
-var d=this.data;
-var _2={start:{x:d.x1,y:d.y1},x:d.x2,y:d.y2};
-var pt=this.util.snapAngle(_2,this.angleSnap/180);
-this.setPoints([{x:d.x1,y:d.y1},{x:pt.x,y:pt.y}]);
-this._isBeingModified=false;
-this.onModify(this);
-}
-},onDrag:function(_3){
-if(this.created){
-return;
-}
-var x1=_3.start.x,y1=_3.start.y,x2=_3.x,y2=_3.y;
-if(this.keys.shift){
-var pt=this.util.snapAngle(_3,45/180);
-x2=pt.x;
-y2=pt.y;
-}
-if(this.keys.alt){
-var dx=x2>x1?((x2-x1)/2):((x1-x2)/-2);
-var dy=y2>y1?((y2-y1)/2):((y1-y2)/-2);
-x1-=dx;
-x2-=dx;
-y1-=dy;
-y2-=dy;
-}
-this.setPoints([{x:x1,y:y1},{x:x2,y:y2}]);
-this.render();
-},onUp:function(_4){
-if(this.created||!this.shape){
-return;
-}
-if(this.getRadius()<this.minimumSize){
-this.remove(this.shape,this.hit);
-return;
-}
-var pt=this.util.snapAngle(_4,this.angleSnap/180);
-var p=this.points;
-this.setPoints([{x:p[0].x,y:p[0].y},{x:pt.x,y:pt.y}]);
-this.renderedOnce=true;
-this.onRender(this);
-}});
-dojox.drawing.tools.Line.setup={name:"dojox.drawing.tools.Line",tooltip:"Line Tool",iconClass:"iconLine"};
-dojox.drawing.register(dojox.drawing.tools.Line.setup,"tool");
-}
+dojox.drawing.tools.Line.setup = {
+	// summary: See stencil._Base ToolsSetup
+	//
+	name:"dojox.drawing.tools.Line",
+	tooltip:"Line Tool",
+	iconClass:"iconLine"
+};
+
+dojox.drawing.register(dojox.drawing.tools.Line.setup, "tool");
\ No newline at end of file
diff --git a/dojox/drawing/tools/Path.js b/dojox/drawing/tools/Path.js
index 857531a..e3202e1 100644
--- a/dojox/drawing/tools/Path.js
+++ b/dojox/drawing/tools/Path.js
@@ -1,152 +1,203 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.tools.Path");
 
+dojox.drawing.tools.Path = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Class for a drawable Path
+	//
+	dojox.drawing.stencil.Path,
+	function(){
+		// summary: constructor
+		
+		this.pathMode = "";
+		this.currentPathMode = "";
+		this._started = false;
+		this.oddEvenClicks = 0;
+		
+	},
+	{
+		draws:true,
+		onDown: function(obj){
+			if(!this._started){ 
+				this.onStartPath(obj);
+			}
+			
+		},
+		
+		makeSubPath: function(_closePath){
+			if(_closePath){
+				if(this.currentPathMode=="Q"){
+					this.points.push({
+						x:this.points[0].x,
+						y:this.points[0].y
+					});
+				}
+				this.points.push({t:"Z"});
+				this.render();
+			}
+			this.currentPathMode = "";
+			this.pathMode = "M";
+		},
+		
+		onStartPath: function(obj){
+			this._started = true;
+			this.revertRenderHit = this.renderHit;
+			this.renderHit = false;
+			this.closePath = false;
+			
+			
+			this.mouse.setEventMode("PathEdit");
+			
+			this.closePoint = {x:obj.x, y:obj.y};
+			
+			this._kc1 = this.connect(this.keys, "onEsc", this, function(){
+				this.onCompletePath(false);
+			});
+			
+			this._kc2 = this.connect(this.keys, "onKeyUp", this, function(evt){
+				
+				switch(evt.letter){
+					case "c":
+						this.onCompletePath(true); break;		
+					case "l": this.pathMode = "L"; break;
+					case "m": this.makeSubPath(false); break;		
+					case "q": this.pathMode = "Q"; break;		
+					case "s": this.pathMode = "S"; break;
+					case "z": this.makeSubPath(true); break;
+				}
+				 
+				//console.log("KEY:", evt.letter);	
+			});
+		},
+		
+		onCompletePath:function(_closePath){
+			this.remove(this.closeGuide, this.guide);
+			var box = this.getBounds();
+			if(box.w<this.minimumSize && box.h<this.minimumSize){
+				this.remove(this.hit, this.shape, this.closeGuide);
+				this._started = false;
+				this.mouse.setEventMode("");
+				this.setPoints([]);
+				return;
+			}
+			
+			
+			if(_closePath){
+				if(this.currentPathMode=="Q"){
+					this.points.push({
+						x:this.points[0].x,
+						y:this.points[0].y
+					});
+				}
+				this.closePath = true;
+			}
+			
+			
+			this.renderHit = this.revertRenderHit;
+			this.renderedOnce = true;
+			this.onRender(this);
+			this.disconnect([this._kc1, this._kc2]);
+			this.mouse.setEventMode("");
+			this.render();
+			//console.log(this.stringPath);
+		},
+		
+		onUp: function(/*EventObject*/obj){
+			//console.log("   Path UP", obj.mid, "within:", obj.withinCanvas)
+					
+				
+			if(!this._started || !obj.withinCanvas){ return; }
+			
+		
+			if(this.points.length>2 && this.closeRadius>this.util.distance(obj.x, obj.y, this.closePoint.x, this.closePoint.y)){
+				this.onCompletePath(true);
+				
+			}else {
+				var p = {
+					x:obj.x,
+					y:obj.y
+				};
+				this.oddEvenClicks++;
+				if(this.currentPathMode != this.pathMode){
+					if(this.pathMode=="Q"){
+						p.t = "Q";
+						this.oddEvenClicks = 0;
+					}else if(this.pathMode=="L"){
+						p.t = "L";
+					}else if(this.pathMode=="M"){
+						p.t = "M";
+						this.closePoint = {x:obj.x, y:obj.y};
+					}
+					this.currentPathMode = this.pathMode;
+				}
+				
+				
+				this.points.push(p);
+				if(this.points.length>1){
+					this.remove(this.guide);
+					this.render();
+				}
+				
+			}
+			
+			//console.log(this.stringPath);
+		},
+		createGuide: function(obj){
+			if(!this.points.length){ return; }
+			var realPoints = [].concat(this.points);
+			
+			var pt = {
+				x:obj.x,
+				y:obj.y
+			};
+			if(this.currentPathMode=="Q" && this.oddEvenClicks % 2){
+				// On a Q curve, every other click needs to be a
+				// straight line - the inbetween Q coords don't render
+				pt.t = "L"; // this is not permanent
+			}
+			
+			this.points.push(pt);
+			
+			this.render();
+			this.points = realPoints;
+			
+			
+			var dist = this.util.distance(obj.x, obj.y, this.closePoint.x, this.closePoint.y);
+			if(this.points.length>1){
+				if(dist<this.closeRadius && !this.closeGuide){
+					var c = {
+						cx:this.closePoint.x,
+						cy:this.closePoint.y,
+						rx:this.closeRadius,
+						ry:this.closeRadius
+					}
+					this.closeGuide = this.container.createEllipse(c)
+						.setFill(this.closeColor);
+						
+				}else if(dist>this.closeRadius && this.closeGuide){
+					this.remove(this.closeGuide);
+					this.closeGuide = null;
+				}
+			}
+			
+		},
+		
+		onMove: function(obj){
+			if(!this._started){ return; }
+			this.createGuide(obj);
+		},
+		onDrag: function(obj){
+			if(!this._started){ return; }
+			this.createGuide(obj);
+		}
+	}
+);
 
-if(!dojo._hasResource["dojox.drawing.tools.Path"]){
-dojo._hasResource["dojox.drawing.tools.Path"]=true;
-dojo.provide("dojox.drawing.tools.Path");
-dojox.drawing.tools.Path=dojox.drawing.util.oo.declare(dojox.drawing.stencil.Path,function(){
-this.pathMode="";
-this.currentPathMode="";
-this._started=false;
-this.oddEvenClicks=0;
-},{draws:true,onDown:function(_1){
-if(!this._started){
-this.onStartPath(_1);
-}
-},makeSubPath:function(_2){
-if(_2){
-if(this.currentPathMode=="Q"){
-this.points.push({x:this.points[0].x,y:this.points[0].y});
-}
-this.points.push({t:"Z"});
-this.render();
-}
-this.currentPathMode="";
-this.pathMode="M";
-},onStartPath:function(_3){
-this._started=true;
-this.revertRenderHit=this.renderHit;
-this.renderHit=false;
-this.closePath=false;
-this.mouse.setEventMode("PathEdit");
-this.closePoint={x:_3.x,y:_3.y};
-this._kc1=this.connect(this.keys,"onEsc",this,function(){
-this.onCompletePath(false);
-});
-this._kc2=this.connect(this.keys,"onKeyUp",this,function(_4){
-switch(_4.letter){
-case "c":
-this.onCompletePath(true);
-break;
-case "l":
-this.pathMode="L";
-break;
-case "m":
-this.makeSubPath(false);
-break;
-case "q":
-this.pathMode="Q";
-break;
-case "s":
-this.pathMode="S";
-break;
-case "z":
-this.makeSubPath(true);
-break;
-}
-});
-},onCompletePath:function(_5){
-this.remove(this.closeGuide,this.guide);
-var _6=this.getBounds();
-if(_6.w<this.minimumSize&&_6.h<this.minimumSize){
-this.remove(this.hit,this.shape,this.closeGuide);
-this._started=false;
-this.mouse.setEventMode("");
-this.setPoints([]);
-return;
-}
-if(_5){
-if(this.currentPathMode=="Q"){
-this.points.push({x:this.points[0].x,y:this.points[0].y});
-}
-this.closePath=true;
-}
-this.renderHit=this.revertRenderHit;
-this.renderedOnce=true;
-this.onRender(this);
-this.disconnect([this._kc1,this._kc2]);
-this.mouse.setEventMode("");
-this.render();
-},onUp:function(_7){
-if(!this._started||!_7.withinCanvas){
-return;
-}
-if(this.points.length>2&&this.closeRadius>this.util.distance(_7.x,_7.y,this.closePoint.x,this.closePoint.y)){
-this.onCompletePath(true);
-}else{
-var p={x:_7.x,y:_7.y};
-this.oddEvenClicks++;
-if(this.currentPathMode!=this.pathMode){
-if(this.pathMode=="Q"){
-p.t="Q";
-this.oddEvenClicks=0;
-}else{
-if(this.pathMode=="L"){
-p.t="L";
-}else{
-if(this.pathMode=="M"){
-p.t="M";
-this.closePoint={x:_7.x,y:_7.y};
-}
-}
-}
-this.currentPathMode=this.pathMode;
-}
-this.points.push(p);
-if(this.points.length>1){
-this.remove(this.guide);
-this.render();
-}
-}
-},createGuide:function(_8){
-if(!this.points.length){
-return;
-}
-var _9=[].concat(this.points);
-var pt={x:_8.x,y:_8.y};
-if(this.currentPathMode=="Q"&&this.oddEvenClicks%2){
-pt.t="L";
-}
-this.points.push(pt);
-this.render();
-this.points=_9;
-var _a=this.util.distance(_8.x,_8.y,this.closePoint.x,this.closePoint.y);
-if(this.points.length>1){
-if(_a<this.closeRadius&&!this.closeGuide){
-var c={cx:this.closePoint.x,cy:this.closePoint.y,rx:this.closeRadius,ry:this.closeRadius};
-this.closeGuide=this.container.createEllipse(c).setFill(this.closeColor);
-}else{
-if(_a>this.closeRadius&&this.closeGuide){
-this.remove(this.closeGuide);
-this.closeGuide=null;
-}
-}
-}
-},onMove:function(_b){
-if(!this._started){
-return;
-}
-this.createGuide(_b);
-},onDrag:function(_c){
-if(!this._started){
-return;
-}
-this.createGuide(_c);
-}});
-dojox.drawing.tools.Path.setup={name:"dojox.drawing.tools.Path",tooltip:"Path Tool",iconClass:"iconLine"};
-dojox.drawing.register(dojox.drawing.tools.Path.setup,"tool");
-}
+dojox.drawing.tools.Path.setup = {
+	// summary: See Base ToolsSetup
+	//
+	name:"dojox.drawing.tools.Path",
+	tooltip:"Path Tool",
+	iconClass:"iconLine"
+};
+
+dojox.drawing.register(dojox.drawing.tools.Path.setup, "tool");
\ No newline at end of file
diff --git a/dojox/drawing/tools/Pencil.js b/dojox/drawing/tools/Pencil.js
index 59d95a8..ba1efae 100644
--- a/dojox/drawing/tools/Pencil.js
+++ b/dojox/drawing/tools/Pencil.js
@@ -1,56 +1,83 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.tools.Pencil");
 
+dojox.drawing.tools.Pencil = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Class for a drawable, continous Path
+	//
+	dojox.drawing.stencil.Path,
+	function(){
+		// summary: constructor
+		this._started = false;
+	},
+	{
+		draws:true,
+		// minDist: Number
+		//		The distance the mouse must travel before rendering
+		//		a path segment. Lower number is a higher definition
+		//		path but more points.
+		minDist: 15, // how to make this more dynamic? Settable?
+		
+		onDown: function(obj){
+			this._started = true;
+			var p = {
+				x:obj.x,
+				y:obj.y
+			};
+			this.points = [p];
+			this.lastPoint = p;
+			this.revertRenderHit = this.renderHit;
+			this.renderHit = false;
+			this.closePath = false;
+		},
+		
+		onDrag: function(obj){
+			if(
+			   !this._started
+			   || this.minDist > this.util.distance(obj.x, obj.y, this.lastPoint.x, this.lastPoint.y)
+			){ return; }
+			
+			var p = {
+				x:obj.x,
+				y:obj.y
+			};
+			this.points.push(p);
+			this.render();
+			this.checkClosePoint(this.points[0], obj);
+			this.lastPoint = p;
+		},
+		
+		onUp: function(obj){
+			if(!this._started){ return; }
+			if(!this.points || this.points.length<2){
+				this._started = false;
+				this.points = [];
+				return;
+			}
+			var box = this.getBounds();
+			if(box.w<this.minimumSize && box.h<this.minimumSize){
+				this.remove(this.hit, this.shape, this.closeGuide);
+				this._started = false;
+				this.setPoints([]);
+				return;
+			}
+			if(this.checkClosePoint(this.points[0], obj, true)){
+				this.closePath = true;
+			}
+			this.renderHit = this.revertRenderHit;
+			this.renderedOnce = true;
+			this.render();
+			this.onRender(this);
+			
+		}
+	}
+);
 
-if(!dojo._hasResource["dojox.drawing.tools.Pencil"]){
-dojo._hasResource["dojox.drawing.tools.Pencil"]=true;
-dojo.provide("dojox.drawing.tools.Pencil");
-dojox.drawing.tools.Pencil=dojox.drawing.util.oo.declare(dojox.drawing.stencil.Path,function(){
-this._started=false;
-},{draws:true,minDist:15,onDown:function(_1){
-this._started=true;
-var p={x:_1.x,y:_1.y};
-this.points=[p];
-this.lastPoint=p;
-this.revertRenderHit=this.renderHit;
-this.renderHit=false;
-this.closePath=false;
-},onDrag:function(_2){
-if(!this._started||this.minDist>this.util.distance(_2.x,_2.y,this.lastPoint.x,this.lastPoint.y)){
-return;
-}
-var p={x:_2.x,y:_2.y};
-this.points.push(p);
-this.render();
-this.checkClosePoint(this.points[0],_2);
-this.lastPoint=p;
-},onUp:function(_3){
-if(!this._started){
-return;
-}
-if(!this.points||this.points.length<2){
-this._started=false;
-this.points=[];
-return;
-}
-var _4=this.getBounds();
-if(_4.w<this.minimumSize&&_4.h<this.minimumSize){
-this.remove(this.hit,this.shape,this.closeGuide);
-this._started=false;
-this.setPoints([]);
-return;
-}
-if(this.checkClosePoint(this.points[0],_3,true)){
-this.closePath=true;
-}
-this.renderHit=this.revertRenderHit;
-this.renderedOnce=true;
-this.render();
-this.onRender(this);
-}});
-dojox.drawing.tools.Pencil.setup={name:"dojox.drawing.tools.Pencil",tooltip:"Pencil Tool",iconClass:"iconLine"};
-dojox.drawing.register(dojox.drawing.tools.Pencil.setup,"tool");
-}
+dojox.drawing.tools.Pencil.setup = {
+	// summary: See Base ToolsSetup
+	//
+	name:"dojox.drawing.tools.Pencil",
+	tooltip:"Pencil Tool",
+	iconClass:"iconLine"
+};
+
+dojox.drawing.register(dojox.drawing.tools.Pencil.setup, "tool");
\ No newline at end of file
diff --git a/dojox/drawing/tools/Rect.js b/dojox/drawing/tools/Rect.js
old mode 100644
new mode 100755
index 77920a1..66db50f
--- a/dojox/drawing/tools/Rect.js
+++ b/dojox/drawing/tools/Rect.js
@@ -1,41 +1,79 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.tools.Rect");
 
+dojox.drawing.tools.Rect = dojox.drawing.util.oo.declare(
+	// summary:
+	// 		Class for a drawable rectangle
+	//
+	dojox.drawing.stencil.Rect,
+	function(){
+		// summary: constructor
+	},
+	{
+		draws:true,
+		
+		onDrag: function(/*EventObject*/obj){
+			// summary: See stencil._Base.onDrag
+			//
+			var s = obj.start, e = obj;
+			var	x = s.x < e.x ? s.x : e.x,
+				y = s.y < e.y ? s.y : e.y,
+				w = s.x < e.x ? e.x-s.x : s.x-e.x,
+				h = s.y < e.y ? e.y-s.y : s.y-e.y;
+			
+			if(this.keys.shift){ w = h = Math.max(w,h); }
+			
+			if(this.keys.alt){
+				x-=w; y-=h; w*=2; h*=2;
+				x = Math.max(x, 0);
+				y = Math.max(y, 0);
+			}
+			this.setPoints ([
+				{x:x, y:y}, 	// TL
+				{x:x+w, y:y},	// TR
+				{x:x+w, y:y+h},	// BR
+				{x:x, y:y+h}	// BL
+			]);
+			this.render();
+		},
+		
+		onUp: function(/*EventObject*/obj){
+			// summary: See stencil._Base.onUp
+			//
+			if(this.created || !this._downOnCanvas){ return; }
+			this._downOnCanvas = false;
+			
+			//Default shape on single click
+			if(!this.shape){
+				var s = obj.start;
+				var e = this.minimumSize*4;
+				this.setPoints([
+					{x:s.x, y:s.y},
+					{x:s.x+e, y:s.y},
+					{x:s.x+e, y:s.y+e},
+					{x:s.x, y:s.y+e}
+				]);
+				this.render();
+			}else{
+			
+				// if too small, need to reset
+				var o = this.data;
+				if(o.width<this.minimumSize && o.height < this.minimumSize){
+					this.remove(this.shape, this.hit);
+					return;
+				}
+			}
+			this.onRender(this);
+			
+		}
+	}
+);
 
-if(!dojo._hasResource["dojox.drawing.tools.Rect"]){
-dojo._hasResource["dojox.drawing.tools.Rect"]=true;
-dojo.provide("dojox.drawing.tools.Rect");
-dojox.drawing.tools.Rect=dojox.drawing.util.oo.declare(dojox.drawing.stencil.Rect,function(){
-},{draws:true,onDrag:function(_1){
-var s=_1.start,e=_1;
-var x=s.x<e.x?s.x:e.x,y=s.y<e.y?s.y:e.y,w=s.x<e.x?e.x-s.x:s.x-e.x,h=s.y<e.y?e.y-s.y:s.y-e.y;
-if(this.keys.shift){
-w=h=Math.max(w,h);
-}
-if(this.keys.alt){
-x-=w;
-y-=h;
-w*=2;
-h*=2;
-x=Math.max(x,0);
-y=Math.max(y,0);
-}
-this.setPoints([{x:x,y:y},{x:x+w,y:y},{x:x+w,y:y+h},{x:x,y:y+h}]);
-this.render();
-},onUp:function(_2){
-if(this.created||!this.shape){
-return;
-}
-var o=this.data;
-if(o.width<this.minimumSize&&o.height<this.minimumSize){
-this.remove(this.shape,this.hit);
-return;
-}
-this.onRender(this);
-}});
-dojox.drawing.tools.Rect.setup={name:"dojox.drawing.tools.Rect",tooltip:"<span class=\"drawingTipTitle\">Rectangle Tool</span><br/>"+"<span class=\"drawingTipDesc\">SHIFT - constrain to square</span>",iconClass:"iconRect"};
-dojox.drawing.register(dojox.drawing.tools.Rect.setup,"tool");
-}
+dojox.drawing.tools.Rect.setup = {
+	// summary: See stencil._Base ToolsSetup
+	//
+	name:"dojox.drawing.tools.Rect",
+	tooltip:'<span class="drawingTipTitle">Rectangle Tool</span><br/>'
+		+ '<span class="drawingTipDesc">SHIFT - constrain to square</span>',
+	iconClass:"iconRect"
+};
+dojox.drawing.register(dojox.drawing.tools.Rect.setup, "tool");
\ No newline at end of file
diff --git a/dojox/drawing/tools/TextBlock.js b/dojox/drawing/tools/TextBlock.js
old mode 100644
new mode 100755
index 1492756..af8b1e6
--- a/dojox/drawing/tools/TextBlock.js
+++ b/dojox/drawing/tools/TextBlock.js
@@ -1,385 +1,657 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.tools.TextBlock"]){
-dojo._hasResource["dojox.drawing.tools.TextBlock"]=true;
 dojo.provide("dojox.drawing.tools.TextBlock");
 dojo.require("dojox.drawing.stencil.Text");
+
 (function(){
-var _1;
-dojo.addOnLoad(function(){
-_1=dojo.byId("conEdit");
-if(!_1){
-console.error("A contenteditable div is missing from the main document. See 'dojox.drawing.tools.TextBlock'");
-}else{
-_1.parentNode.removeChild(_1);
-}
-});
-dojox.drawing.tools.TextBlock=dojox.drawing.util.oo.declare(dojox.drawing.stencil.Text,function(_2){
-if(_2.data){
-var d=_2.data;
-var w=!d.width?this.style.text.minWidth:d.width=="auto"?"auto":Math.max(d.width,this.style.text.minWidth);
-var h=this._lineHeight;
-if(d.text&&w=="auto"){
-var o=this.measureText(this.cleanText(d.text,false),w);
-w=o.w;
-h=o.h;
-}else{
-this._text="";
-}
-this.points=[{x:d.x,y:d.y},{x:d.x+w,y:d.y},{x:d.x+w,y:d.y+h},{x:d.x,y:d.y+h}];
-if(d.showEmpty||d.text){
-this.editMode=true;
-dojo.disconnect(this._postRenderCon);
-this._postRenderCon=null;
-this.connect(this,"render",this,"onRender",true);
-if(d.showEmpty){
-this._text=d.text||"";
-this.edit();
-}else{
-if(d.text&&d.editMode){
-this._text="";
-this.edit();
-}else{
-if(d.text){
-this.render(d.text);
-}
-}
-}
-setTimeout(dojo.hitch(this,function(){
-this.editMode=false;
-}),100);
-}
-}else{
-this.connectMouse();
-this._postRenderCon=dojo.connect(this,"render",this,"_onPostRender");
-}
-},{draws:true,baseRender:false,type:"dojox.drawing.tools.TextBlock",selectOnExec:true,showEmpty:false,onDrag:function(_3){
-if(!this.parentNode){
-this.showParent(_3);
-}
-var s=this._startdrag,e=_3.page;
-this._box.left=(s.x<e.x?s.x:e.x);
-this._box.top=s.y;
-this._box.width=(s.x<e.x?e.x-s.x:s.x-e.x)+this.style.text.pad;
-dojo.style(this.parentNode,this._box.toPx());
-},onUp:function(_4){
-if(!this._downOnCanvas){
-return;
-}
-this._downOnCanvas=false;
-var c=dojo.connect(this,"render",this,function(){
-dojo.disconnect(c);
-this.onRender(this);
-});
-this.editMode=true;
-this.showParent(_4);
-this.created=true;
-this.createTextField();
-this.connectTextField();
-},showParent:function(_5){
-if(this.parentNode){
-return;
-}
-var x=_5.pageX||10;
-var y=_5.pageY||10;
-this.parentNode=dojo.doc.createElement("div");
-this.parentNode.id=this.id;
-var d=this.style.textMode.create;
-this._box={left:x,top:y,width:_5.width||1,height:_5.height&&_5.height>8?_5.height:this._lineHeight,border:d.width+"px "+d.style+" "+d.color,position:"absolute",zIndex:500,toPx:function(){
-var o={};
-for(var nm in this){
-o[nm]=typeof (this[nm])=="number"&&nm!="zIndex"?this[nm]+"px":this[nm];
-}
-return o;
-}};
-dojo.style(this.parentNode,this._box);
-document.body.appendChild(this.parentNode);
-},createTextField:function(_6){
-var d=this.style.textMode.edit;
-this._box.border=d.width+"px "+d.style+" "+d.color;
-this._box.height="auto";
-this._box.width=Math.max(this._box.width,this.style.text.minWidth*this.mouse.zoom);
-dojo.style(this.parentNode,this._box.toPx());
-this.parentNode.appendChild(_1);
-dojo.style(_1,{height:_6?"auto":this._lineHeight+"px",fontSize:(this.textSize/this.mouse.zoom)+"px",fontFamily:this.style.text.family});
-_1.innerHTML=_6||"";
-return _1;
-},connectTextField:function(){
-if(this._textConnected){
-return;
-}
-this._textConnected=true;
-this.mouse.setEventMode("TEXT");
-this.keys.editMode(true);
-var _7,_8,_9,_a,_b=this,_c=false,_d=function(){
-dojo.forEach([_7,_8,_9,_a],function(c){
-dojo.disconnect(c);
-});
-_b._textConnected=false;
-_b.keys.editMode(false);
-_b.mouse.setEventMode();
-_b.execText();
-};
-_7=dojo.connect(_1,"keyup",this,function(_e){
-if(dojo.trim(_1.innerHTML)&&!_c){
-dojo.style(_1,"height","auto");
-_c=true;
-}else{
-if(dojo.trim(_1.innerHTML).length<2&&_c){
-dojo.style(_1,"height",this._lineHeight+"px");
-_c=false;
-}
-}
-if(_e.keyCode==13||_e.keyCode==27){
-dojo.stopEvent(_e);
-_d();
-}
-});
-_8=dojo.connect(_1,"keydown",this,function(_f){
-if(_f.keyCode==13||_f.keyCode==27){
-dojo.stopEvent(_f);
-}
-});
-_9=dojo.connect(document,"mouseup",this,function(evt){
-if(!this._onAnchor&&evt.target.id!="conEdit"){
-dojo.stopEvent(evt);
-_d();
-}else{
-_1.blur();
-setTimeout(function(){
-_1.focus();
-},200);
-}
-});
-this.createAnchors();
-_a=dojo.connect(this.mouse,"setZoom",this,function(evt){
-_d();
-});
-_1.focus();
-this.onDown=function(){
-};
-this.onDrag=function(){
-};
-var _b=this;
-setTimeout(dojo.hitch(this,function(){
-_1.focus();
-this.onUp=function(){
-if(!_b._onAnchor&&this.parentNode){
-_b.disconnectMouse();
-_d();
-_b.onUp=function(){
-};
-}
-};
-}),500);
-},execText:function(){
-var d=dojo.marginBox(this.parentNode);
-var w=Math.max(d.w,this.style.text.minWidth);
-var txt=this.cleanText(_1.innerHTML,true);
-_1.innerHTML="";
-_1.blur();
-this.destroyAnchors();
-var o=this.measureText(txt,w);
-var sc=this.mouse.scrollOffset();
-var org=this.mouse.origin;
-var x=this._box.left+sc.left-org.x;
-var y=this._box.top+sc.top-org.y;
-x*=this.mouse.zoom;
-y*=this.mouse.zoom;
-w*=this.mouse.zoom;
-o.h*=this.mouse.zoom;
-this.points=[{x:x,y:y},{x:x+w,y:y},{x:x+w,y:y+o.h},{x:x,y:y+o.h}];
-this.editMode=false;
-if(!o.text){
-this._text="";
-this._textArray=[];
-}
-this.render(o.text);
-this.onChangeText(txt);
-},edit:function(){
-this.editMode=true;
-if(this.parentNode||!this.points){
-return;
-}
-var d=this.pointsToData();
-var sc=this.mouse.scrollOffset();
-var org=this.mouse.origin;
-var obj={pageX:(d.x)/this.mouse.zoom-sc.left+org.x,pageY:(d.y)/this.mouse.zoom-sc.top+org.y,width:d.width/this.mouse.zoom,height:d.height/this.mouse.zoom};
-this.remove(this.shape,this.hit);
-this.showParent(obj);
-this.createTextField(this._text.replace("/n"," "));
-this.connectTextField();
-if(this._text){
-this.setSelection(_1,"end");
-}
-},cleanText:function(txt,_10){
-var _11=function(str){
-var _12={"<":"<",">":">","&":"&"};
-for(var nm in _12){
-str=str.replace(new RegExp(nm,"gi"),_12[nm]);
-}
-return str;
-};
-if(_10){
-dojo.forEach(["<br>","<br/>","<br />","\\n","\\r"],function(br){
-txt=txt.replace(new RegExp(br,"gi")," ");
-});
-}
-txt=txt.replace(/ /g," ");
-txt=_11(txt);
-txt=dojo.trim(txt);
-txt=txt.replace(/\s{2,}/g," ");
-return txt;
-},measureText:function(str,_13){
-var r="(<br\\s*/*>)|(\\n)|(\\r)";
-this.showParent({width:_13||"auto",height:"auto"});
-this.createTextField(str);
-var txt="";
-var el=_1;
-el.innerHTML="X";
-var h=dojo.marginBox(el).h;
-el.innerHTML=str;
-if(!_13||new RegExp(r,"gi").test(str)){
-txt=str.replace(new RegExp(r,"gi"),"\n");
-el.innerHTML=str.replace(new RegExp(r,"gi"),"<br/>");
-}else{
-if(dojo.marginBox(el).h==h){
-txt=str;
-}else{
-var ar=str.split(" ");
-var _14=[[]];
-var _15=0;
-el.innerHTML="";
-while(ar.length){
-var _16=ar.shift();
-el.innerHTML+=_16+" ";
-if(dojo.marginBox(el).h>h){
-_15++;
-_14[_15]=[];
-el.innerHTML=_16+" ";
-}
-_14[_15].push(_16);
-}
-dojo.forEach(_14,function(ar,i){
-_14[i]=ar.join(" ");
-});
-txt=_14.join("\n");
-el.innerHTML=txt.replace("\n","<br/>");
-}
-}
-var dim=dojo.marginBox(el);
-_1.parentNode.removeChild(_1);
-dojo.destroy(this.parentNode);
-this.parentNode=null;
-return {h:dim.h,w:dim.w,text:txt};
-},_downOnCanvas:false,onDown:function(obj){
-this._startdrag={x:obj.pageX,y:obj.pageY};
-dojo.disconnect(this._postRenderCon);
-this._postRenderCon=null;
-this._downOnCanvas=true;
-},createAnchors:function(){
-this._anchors={};
-var _17=this;
-var d=this.style.anchors,b=d.width,w=d.size-b*2,h=d.size-b*2,p=(d.size)/2*-1+"px";
-var s={position:"absolute",width:w+"px",height:h+"px",backgroundColor:d.fill,border:b+"px "+d.style+" "+d.color};
-if(dojo.isIE){
-s.paddingLeft=w+"px";
-s.fontSize=w+"px";
-}
-var ss=[{top:p,left:p},{top:p,right:p},{bottom:p,right:p},{bottom:p,left:p}];
-for(var i=0;i<4;i++){
-var _18=(i==0)||(i==3);
-var id=this.util.uid(_18?"left_anchor":"right_anchor");
-var a=dojo.create("div",{id:id},this.parentNode);
-dojo.style(a,dojo.mixin(dojo.clone(s),ss[i]));
-var md,mm,mu;
-var md=dojo.connect(a,"mousedown",this,function(evt){
-_18=evt.target.id.indexOf("left")>-1;
-_17._onAnchor=true;
-var _19=evt.pageX;
-var _1a=this._box.width;
-dojo.stopEvent(evt);
-mm=dojo.connect(document,"mousemove",this,function(evt){
-var x=evt.pageX;
-if(_18){
-this._box.left=x;
-this._box.width=_1a+_19-x;
-}else{
-this._box.width=x+_1a-_19;
-}
-dojo.style(this.parentNode,this._box.toPx());
-});
-mu=dojo.connect(document,"mouseup",this,function(evt){
-_19=this._box.left;
-_1a=this._box.width;
-dojo.disconnect(mm);
-dojo.disconnect(mu);
-_17._onAnchor=false;
-_1.focus();
-dojo.stopEvent(evt);
-});
-});
-this._anchors[id]={a:a,cons:[md]};
-}
-},destroyAnchors:function(){
-for(var n in this._anchors){
-dojo.forEach(this._anchors[n].con,dojo.disconnect,dojo);
-dojo.destroy(this._anchors[n].a);
-}
-},setSelection:function(_1b,_1c){
-console.warn("setSelection:");
-if(dojo.doc.selection){
-var r=dojo.body().createTextRange();
-r.moveToElementText(_1b);
-r.collapse(false);
-r.select();
-}else{
-var _1d=function(_1e,_1f){
-_1f=_1f||[];
-for(var i=0;i<_1e.childNodes.length;i++){
-var n=_1e.childNodes[i];
-if(n.nodeType==3){
-_1f.push(n);
-}else{
-if(n.tagName&&n.tagName.toLowerCase()=="img"){
-_1f.push(n);
-}
-}
-if(n.childNodes&&n.childNodes.length){
-_1d(n,_1f);
-}
-}
-return _1f;
-};
-_1b.focus();
-var _20=dojo.global.getSelection();
-_20.removeAllRanges();
-var r=dojo.doc.createRange();
-r.selectNodeContents(_1b);
-var _21=_1d(_1b);
-if(_1c=="end"){
-r.setStart(_21[_21.length-1],_21[_21.length-1].textContent.length);
-r.setEnd(_21[_21.length-1],_21[_21.length-1].textContent.length);
-}else{
-if(_1c=="beg"||_1c=="start"){
-r.setStart(_21[0],0);
-r.setEnd(_21[0],0);
-}else{
-if(_1c=="all"){
-r.setStart(_21[0],0);
-r.setEnd(_21[_21.length-1],_21[_21.length-1].textContent.length);
-}
-}
-}
-_20.addRange(r);
-}
-}});
-dojox.drawing.tools.TextBlock.setup={name:"dojox.drawing.tools.TextBlock",tooltip:"Text Tool",iconClass:"iconText"};
-dojox.drawing.register(dojox.drawing.tools.TextBlock.setup,"tool");
-})();
-}
+	
+	var conEdit;
+	dojo.addOnLoad(function(){
+		//		In order to use VML in IE, it's necessary to remove the
+		//		DOCTYPE. But this has the side effect that causes a bug
+		//		where contenteditable divs cannot be made dynamically.
+		//		The solution is to include one in the main document
+		//		that can be appended and removed as necessary:
+		//		<div id="conEdit" contenteditable="true"></div>
+		//
+		conEdit = dojo.byId("conEdit");
+		if(!conEdit){
+			console.error("A contenteditable div is missing from the main document. See 'dojox.drawing.tools.TextBlock'")
+		}else{
+			conEdit.parentNode.removeChild(conEdit);
+		}
+	});
+	
+	dojox.drawing.tools.TextBlock = dojox.drawing.util.oo.declare(
+		// summary:
+		//		A tool to create text fields on a canvas.
+		// description:
+		//		Extends stencil.Text by adding an HTML layer that
+		//		can be dragged out to a certain size, and accept
+		//		a text entry. Will wrap text to the width of the
+		//		html field.
+		//		When created programmtically, use 'auto' to shrink
+		//		the width to the size of the text. Use line breaks
+		//		( \n ) to create new lines.
+		//
+		// TODO - disable zoom while showing?
+		//
+		// FIXME:
+		//		Handles width: auto, align:middle, etc. but for
+		//		display only, edit is out of whack
+		//
+		dojox.drawing.stencil.Text,
+		function(options){
+			// summary: constructor
+			//
+			if(options.data){
+				var d = options.data;
+				var text = d.text;
+				var w = !d.width ? this.style.text.minWidth : d.width=="auto" ? "auto" : Math.max(d.width, this.style.text.minWidth)
+				var h = this._lineHeight;
+				
+				// need to typeset before measuring width
+				text = this.typesetter(text);
+				
+				if(text && w=="auto"){
+					var o = this.measureText(this.cleanText(text, false), w);
+					w = o.w;
+					h = o.h;
+				}else{
+					//	w = this.style.text.minWidth;
+					this._text = "";
+				}
+				
+				this.points = [
+					{x:d.x, y:d.y},
+					{x:d.x+w, y:d.y},
+					{x:d.x+w, y:d.y+h},
+					{x:d.x, y:d.y+h}
+				];
+				
+				if(d.showEmpty || text){
+					this.editMode = true;
+					
+				
+					dojo.disconnect(this._postRenderCon);
+					this._postRenderCon = null;
+					this.connect(this, "render", this, "onRender", true);
+					
+					if(d.showEmpty){
+						this._text = text || "";
+						this.edit();
+					}else if(text && d.editMode){
+						this._text = "";
+						this.edit();
+					}else if(text){
+						this.render(text);
+					}
+					setTimeout(dojo.hitch(this, function(){
+						this.editMode = false;	
+					}),100)
+					
+				}
+				
+			}else{
+				this.connectMouse();
+				this._postRenderCon = dojo.connect(this, "render", this, "_onPostRender");
+			}
+			//console.log("TextBlock:", this.id)
+		},
+		{
+			draws:true,
+			baseRender:false,
+			type:"dojox.drawing.tools.TextBlock",
+			
+/*=====
+StencilData: {
+	// summary:
+	//		The data used to create the dojox.gfx Text
+	// 	x: Number
+	//		Left point x
+	// 	y: Number
+	//		Top point y
+	// 	width: ? Number|String
+	//		Optional width of Text. Not required but reccommended.
+	//		for auto-sizing, use 'auto'
+	// 	height: ? Number
+	//		Optional height of Text. If not provided, _lineHeight is used.
+	// 	text: String
+	//		The string content. If not provided, may auto-delete depending on defaults.
+},
+=====*/
+			
+			// selectOnExec: Boolean
+			//		Whether the Stencil is selected when the text field
+			//		is executed or not	
+			selectOnExec:true,
+			//
+			// showEmpty: Boolean
+			//		If true and there is no text in the data, the TextBlock
+			//		Is displayed and focused and awaits input.
+			showEmpty: false,
+			
+			onDrag: function(/*EventObject*/obj){
+				// summary: See stencil._Base.onDrag
+				//
+				if(!this.parentNode){
+					this.showParent(obj);
+				}
+				var s = this._startdrag, e = obj.page;
+				this._box.left = (s.x < e.x ? s.x : e.x);
+				this._box.top = s.y;
+				this._box.width = (s.x < e.x ? e.x-s.x : s.x-e.x) + this.style.text.pad;
+				
+				dojo.style(this.parentNode, this._box.toPx());
+			},
+			
+			onUp: function(/*EventObject*/obj){
+				// summary: See stencil._Base.onUp
+				//
+
+				if(!this._downOnCanvas){ return; }
+				this._downOnCanvas = false;
+				
+				var c = dojo.connect(this, "render", this, function(){
+					dojo.disconnect(c);
+					this.onRender(this);	
+					
+				});
+				this.editMode = true;
+				this.showParent(obj);
+				this.created = true;
+				this.createTextField();
+				this.connectTextField();
+			},
+			
+			showParent: function(/*EventObject*/obj){
+				// summary:
+				//		Internal. Builds the parent node for the
+				//		contenteditable HTML node.
+				//
+				if(this.parentNode){ return; }
+				var x = obj.pageX || 10;
+				var y = obj.pageY || 10;
+				this.parentNode = dojo.doc.createElement("div");
+				this.parentNode.id = this.id;
+				var d = this.style.textMode.create;
+				this._box = {
+					left:x,
+					top:y,
+					width:obj.width || 1,
+					height:obj.height && obj.height>8 ? obj.height : this._lineHeight,
+					border:d.width+"px "+d.style+" "+d.color,
+					position:"absolute",
+					zIndex:500,
+					toPx: function(){
+						var o = {};
+						for(var nm in this){
+							o[nm] = typeof(this[nm])=="number" && nm!="zIndex" ? this[nm] + "px" : this[nm];
+						}
+						return o;
+					}
+				};
+				
+				dojo.style(this.parentNode, this._box);
+				
+				document.body.appendChild(this.parentNode);
+			},
+			createTextField: function(/*String*/txt){
+				// summary:
+				//		Internal. Inserts the contenteditable HTML node
+				//		into its parent node, and styles it.
+				//
+				// style parent
+				var d = this.style.textMode.edit;
+				this._box.border = d.width+"px "+d.style+" "+d.color;
+				this._box.height = "auto";
+				this._box.width = Math.max(this._box.width, this.style.text.minWidth*this.mouse.zoom);
+				dojo.style(this.parentNode, this._box.toPx());
+				// style input
+				this.parentNode.appendChild(conEdit);
+				dojo.style(conEdit, {
+					height: txt ? "auto" : this._lineHeight+"px",
+					fontSize:(this.textSize/this.mouse.zoom)+"px",
+					fontFamily:this.style.text.family
+				});
+				// FIXME:
+				// In Safari, if the txt ends with '&' it gets stripped
+				conEdit.innerHTML = txt || "";
+				
+				return conEdit; //HTMLNade
+			},
+			connectTextField: function(){
+				// summary:
+				//		Internal. Creates the connections to the
+				//		contenteditable HTML node.
+				//
+				if(this._textConnected){ return; } // good ol' IE and its double events
+				this._textConnected = true;
+				this.mouse.setEventMode("TEXT");
+				this.keys.editMode(true);
+				var kc1, kc2, kc3, kc4, self = this, _autoSet = false,
+					exec = function(){
+						dojo.forEach([kc1,kc2,kc3,kc4], function(c){
+							dojo.disconnect(c)
+						});
+						self._textConnected = false;
+						self.keys.editMode(false);
+						self.mouse.setEventMode();
+						self.execText();
+					};
+					
+				kc1 = dojo.connect(conEdit, "keyup", this, function(evt){
+					// 	if text is empty, we need a height so the field's height
+					//	doesn't collapse
+					if(dojo.trim(conEdit.innerHTML) && !_autoSet){
+						dojo.style(conEdit, "height", "auto"); _autoSet = true;
+					}else if(dojo.trim(conEdit.innerHTML).length<2 && _autoSet){
+						dojo.style(conEdit, "height", this._lineHeight+"px"); _autoSet = false;
+					}
+					
+					
+					if(evt.keyCode==13 || evt.keyCode==27){
+						dojo.stopEvent(evt);
+						exec();
+					}
+				});
+				kc2 = dojo.connect(conEdit, "keydown", this, function(evt){
+					if(evt.keyCode==13 || evt.keyCode==27){ // TODO: make escape an option
+						dojo.stopEvent(evt);
+					}
+				});
+				
+				kc3 = dojo.connect(document, "mouseup", this, function(evt){
+					// note: _onAnchor means an anchor has been clicked upon
+					
+					if(!this._onAnchor && evt.target.id != "conEdit"){
+						dojo.stopEvent(evt);
+						exec();
+					}else{
+						// wonky stuff happens when you click on the 
+						// field when its empty.
+						conEdit.blur();
+						setTimeout(function(){
+							conEdit.focus();
+						},200)
+					}
+				});
+				
+				this.createAnchors();
+				
+				kc4 = dojo.connect(this.mouse, "setZoom", this, function(evt){
+					exec();
+				});
+				
+				
+				conEdit.focus();
+				
+				this.onDown = function(){};
+				this.onDrag = function(){};
+				
+				setTimeout(dojo.hitch(this, function(){
+					// once again for Silverlight:
+					conEdit.focus();
+					
+					// this is a pretty odd chunk of code here.
+					// specifcally need to overwrite old onUp
+					// however, this still gets called. its
+					// not disconnecting.
+					this.onUp = function(){
+						if(!self._onAnchor && this.parentNode){
+							self.disconnectMouse();
+							exec();
+							self.onUp = function(){}
+						}
+					}	
+				}), 500);
+			},
+			
+			execText: function(){
+				// summary:
+				//		Internal. Method fired when text is executed,
+				//		via mouse-click-off, ESC key or Enter key.
+				//
+				var d = dojo.marginBox(this.parentNode);
+				var w = Math.max(d.w, this.style.text.minWidth);
+				
+				var txt = this.cleanText(conEdit.innerHTML, true);
+				conEdit.innerHTML = "";
+				conEdit.blur();
+				this.destroyAnchors();
+
+				// need to convert characters before measuring width.
+				txt = this.typesetter(txt);
+				
+				var o = this.measureText(txt, w);
+				var sc = this.mouse.scrollOffset();
+				var org = this.mouse.origin;
+				
+				var x = this._box.left + sc.left - org.x;
+				var y = this._box.top + sc.top - org.y;
+				
+				x *= this.mouse.zoom;
+				y *= this.mouse.zoom;
+				w *= this.mouse.zoom;
+				o.h *= this.mouse.zoom;
+				
+				
+				this.points = [
+					{x:x, y:y},
+					{x:x+w, y:y},
+					{x:x+w, y:y+o.h},
+					{x:x, y:y+o.h}
+				];
+				this.editMode = false;
+				
+				
+				console.log("EXEC TEXT::::", this._postRenderCon);
+				
+				if(!o.text){
+					this._text = "";
+					this._textArray = [];
+				}
+				this.render(o.text);
+				// Only for Combo objects (vectors, rectangle, or ellipse).
+				this.onChangeText(this.getText());
+			},
+			
+			edit: function(){
+				// summary:
+				//		Internal?
+				//		Method used to instantiate the contenteditable HTML node.
+				//
+				this.editMode = true;
+				var text = this.getText() || "";
+				console.log("EDIT TEXT:",text, " ",text.replace("/n", " "));
+				// NOTE: no mouse obj
+				if(this.parentNode || !this.points){ return; }
+				var d = this.pointsToData();
+				
+				var sc = this.mouse.scrollOffset();
+				var org = this.mouse.origin;
+				
+				var obj = {
+					pageX: (d.x  ) / this.mouse.zoom - sc.left + org.x,
+					pageY: (d.y  ) / this.mouse.zoom- sc.top + org.y,
+					width:d.width / this.mouse.zoom,
+					height:d.height / this.mouse.zoom
+				};
+				
+				this.remove(this.shape, this.hit);
+				this.showParent(obj);
+				this.createTextField(text.replace("/n", " "));
+				this.connectTextField();
+				if(text){
+					//setTimeout(dojo.hitch(this, function(){
+					this.setSelection(conEdit, "end");
+					//}), 500)
+				}
+			},
+			cleanText: function(/*String*/txt, /*Boolean*/removeBreaks){
+				// summary:
+				//		Cleans text. Strings HTML chars and double spaces
+				//  	and optionally removes line breaks.
+				var replaceHtmlCodes = function(str){
+					var chars = {
+						"<":"<",
+						">":">",
+						"&":"&"
+					};
+					for(var nm in chars){
+						str = str.replace(new RegExp(nm, "gi"), chars[nm])
+					}
+					return str
+				};
+
+				if(removeBreaks){
+					dojo.forEach(['<br>', '<br/>', '<br />', '\\n', '\\r'], function(br){
+						txt = txt.replace(new RegExp(br, 'gi'), " ");
+					});
+				}
+				txt = txt.replace(/ /g, " ");
+				txt = replaceHtmlCodes(txt);
+				txt = dojo.trim(txt);
+				// remove double spaces, since SVG doesn't show them anyway
+				txt = txt.replace(/\s{2,}/g, " ");
+				return txt; //String
+			},
+			
+			measureText: function(/* String */ str, /* ? Number */width){
+				// summary:
+				//		Mechanism for measuring text.
+				//		SVG nor VML have a way of determining the width or
+				//		height of a block of text. This method creates an
+				//		HTML text block and those measurements are used for
+				//		displaying the SVG/VML text.
+				// arguments:
+				//		str: String
+				//			The text to display and measure.
+				//		width: [optional] Number 
+				//			If the width is not provided, it will be assumed
+				//			that the text is one line and the width will be
+				//			measured and the _lineHeight used for th height.
+				//			If width is provided, word-wrap is assumed, and
+				//			line breaks will be inserted into the text at each
+				//			point where a word wraps in the HTML. The height is
+				//			then measured.
+				//
+				var r = "(<br\\s*/*>)|(\\n)|(\\r)";
+				this.showParent({width:width || "auto", height:"auto"});
+				this.createTextField(str);
+				var txt = "";
+				var el = conEdit;
+				el.innerHTML = "X";
+				var h = dojo.marginBox(el).h;
+				
+				el.innerHTML = str;
+				
+				if(!width || new RegExp(r, "gi").test(str)){
+					// has line breaks in text
+					txt = str.replace(new RegExp(r, "gi"), "\n");
+					el.innerHTML = str.replace(new RegExp(r, "gi"), "<br/>");
+				
+				}else if(dojo.marginBox(el).h == h){
+					// one line
+					txt = str;
+					
+				}else{
+					// text wraps
+					var ar = str.split(" ");
+					var strAr = [[]];
+					var line = 0;
+					el.innerHTML = "";
+					while(ar.length){
+						var word = ar.shift();
+						el.innerHTML += word+" "; //urk, always an extra space
+						if(dojo.marginBox(el).h > h){
+							line++;
+							strAr[line] = [];
+							el.innerHTML = word+" ";
+						}
+						strAr[line].push(word)
+					}
+					
+					dojo.forEach(strAr, function(ar, i){
+						strAr[i] = ar.join(" ");
+					});	
+					txt = strAr.join("\n");
+					
+					// get the resultant height
+					el.innerHTML = txt.replace("\n", "<br/>");
+					
+				}
+				
+				var dim = dojo.marginBox(el);
+				
+				conEdit.parentNode.removeChild(conEdit);
+				dojo.destroy(this.parentNode);
+				this.parentNode = null;
+				
+				return {h:dim.h, w:dim.w, text:txt}; //Object
+			},
+			
+			_downOnCanvas:false,
+			onDown: function(/*EventObject*/obj){
+				// summary: See stencil._Base.onDown
+				//
+				this._startdrag = {
+					x: obj.pageX,
+					y: obj.pageY
+				};
+				dojo.disconnect(this._postRenderCon);
+				this._postRenderCon = null;
+				this._downOnCanvas = true;
+			},
+			
+			createAnchors: function(){
+				// summary:
+				//		Internal. Creates HTML nodes at each corner
+				//		of the contenteditable div. These nodes are
+				//		draggable and will resize the div horizontally.
+				//
+				this._anchors = {};
+				var self = this;
+				var d = this.style.anchors,
+					b = d.width,
+					w = d.size-b*2,
+					h = d.size-b*2,
+					p = (d.size)/2*-1 + "px";
+				
+				var s = {
+					position:"absolute",
+					width:w+"px",
+					height:h+"px",
+					backgroundColor:d.fill,
+					border:b+"px " + d.style + " "+d.color
+				};
+				if(dojo.isIE){
+					s.paddingLeft = w + "px";
+					s.fontSize = w + "px"
+				}
+				var ss = [
+					{top: p, left:p},
+					{top:p, right:p},
+					{bottom:p, right:p},
+					{bottom:p,left:p}
+				];
+				for(var i=0;i<4;i++){
+					var isLeft = (i==0) || (i==3);
+					var id = this.util.uid(isLeft ? "left_anchor" : "right_anchor");
+					
+					var a = dojo.create("div", {id:id}, this.parentNode);
+					dojo.style(a, dojo.mixin(dojo.clone(s), ss[i]));
+					
+					var md, mm, mu;
+					var md = dojo.connect(a, "mousedown", this, function(evt){
+						isLeft = evt.target.id.indexOf("left")>-1;
+						self._onAnchor = true;
+						var orgX = evt.pageX;
+						var orgW = this._box.width;
+						dojo.stopEvent(evt);
+						
+							
+						mm = dojo.connect(document, "mousemove", this, function(evt){
+							var x = evt.pageX;
+							if(isLeft){
+								this._box.left = x;
+								this._box.width = orgW + orgX - x;
+							}else{
+								this._box.width = x + orgW - orgX;
+							}
+							dojo.style(this.parentNode, this._box.toPx());
+						});
+						
+						mu = dojo.connect(document, "mouseup", this, function(evt){
+							orgX = this._box.left;
+							orgW = this._box.width;
+							dojo.disconnect(mm);
+							dojo.disconnect(mu);
+							self._onAnchor = false;
+							conEdit.focus();
+							dojo.stopEvent(evt);
+						});
+					});
+					
+					this._anchors[id] = {
+						a:a,
+						cons:[md]
+					}
+				}
+			},
+			
+			destroyAnchors: function(){
+				// summary:
+				//		Internal. Destroys HTML anchors.
+				for(var n in this._anchors){
+					dojo.forEach(this._anchors[n].con, dojo.disconnect, dojo);
+					dojo.destroy(this._anchors[n].a);
+				}
+			},
+			setSelection: function(node, what){
+				// summary:
+				//		Used for placing the cursor at the end of the
+				//		text on edit.
+				//
+				console.warn("setSelection:");
+				if(dojo.doc.selection){ // IE
+					var r = dojo.body().createTextRange();
+					r.moveToElementText(node);
+					r.collapse(false);
+					r.select();
+					
+				}else{
+					var getAllChildren = function(node, children){
+						children = children || [];
+						for(var i=0;i<node.childNodes.length; i++){
+							var n = node.childNodes[i];
+							if(n.nodeType==3){
+								children.push(n);
+							}else if(n.tagName && n.tagName.toLowerCase()=="img"){
+								children.push(n);
+							}
+							
+							if(n.childNodes && n.childNodes.length){
+								getAllChildren(n, children);
+							}
+						}
+						return children;
+					};
+					console.log("ff node:", node)
+					node.focus();
+					var selection = dojo.global.getSelection();
+					selection.removeAllRanges();
+					console.log(1);
+					r = dojo.doc.createRange();
+					r.selectNodeContents(node);
+					console.log(2);
+					var nodes = getAllChildren(node);
+					console.log(3);
+					if(what == "end"){
+						console.log("len:", nodes[nodes.length - 1].textContent.length);
+						r.setStart(nodes[nodes.length - 1], nodes[nodes.length - 1].textContent.length);
+						r.setEnd(nodes[nodes.length - 1], nodes[nodes.length - 1].textContent.length);
+					}else if(what=="beg" || what == "start"){
+						r.setStart(nodes[0], 0);
+						r.setEnd(nodes[0], 0);
+					}else if(what=="all"){
+						r.setStart(nodes[0], 0);
+						r.setEnd(nodes[nodes.length - 1], nodes[nodes.length - 1].textContent.length);
+					}
+					
+					selection.addRange(r);
+					
+					console.log("sel ", what, " on ", node)
+				}
+			}
+		}
+	);
+	
+	dojox.drawing.tools.TextBlock.setup = {
+		// summary: See stencil._Base ToolsSetup
+		//
+		name:"dojox.drawing.tools.TextBlock",
+		tooltip:"Text Tool",
+		iconClass:"iconText"
+	};
+	dojox.drawing.register(dojox.drawing.tools.TextBlock.setup, "tool");
+	
+})();
\ No newline at end of file
diff --git a/dojox/drawing/tools/custom/Axes.js b/dojox/drawing/tools/custom/Axes.js
old mode 100644
new mode 100755
index 9b58912..4e8875e
--- a/dojox/drawing/tools/custom/Axes.js
+++ b/dojox/drawing/tools/custom/Axes.js
@@ -1,204 +1,573 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.tools.custom.Axes"]){
-dojo._hasResource["dojox.drawing.tools.custom.Axes"]=true;
 dojo.provide("dojox.drawing.tools.custom.Axes");
 dojo.require("dojox.drawing.stencil.Path");
-dojox.drawing.tools.custom.Axes=dojox.drawing.util.oo.declare(dojox.drawing.stencil.Path,function(_1){
-this.closePath=false;
-this.xArrow=new dojox.drawing.annotations.Arrow({stencil:this,idx1:0,idx2:1});
-this.yArrow=new dojox.drawing.annotations.Arrow({stencil:this,idx1:2,idx2:1});
-if(this.points&&this.points.length){
-this.setPoints=this._postSetPoints;
-this.render();
-this.onRender();
-}
-},{draws:true,type:"dojox.drawing.tools.custom.Axes",minimumSize:30,showAngle:true,closePath:false,baseRender:false,createLabels:function(){
-var _2={align:"middle",valign:"middle",util:this.util,annotation:true,container:this.container,mouse:this.mouse,stencil:this};
-this.labelX=new dojox.drawing.annotations.Label(dojo.mixin(_2,{labelPosition:this.setLabelX}));
-this.labelY=new dojox.drawing.annotations.Label(dojo.mixin(_2,{labelPosition:this.setLabelY}));
-},setLabelX:function(){
-var ax=this.points[0];
-var c=this.points[1];
-var ay=this.points[2];
-var _3=40;
-var _4=20;
-var pt,px,py,_5;
-pt=this.util.lineSub(c.x,c.y,ax.x,ax.y,_3);
-px=pt.x+(pt.y-ax.y);
-py=pt.y+(ax.x-pt.x);
-_5=this.util.lineSub(pt.x,pt.y,px,py,(_3-_4));
-return {x:_5.x,y:_5.y,width:20};
-},setLabelY:function(){
-var ax=this.points[0];
-var c=this.points[1];
-var ay=this.points[2];
-var _6=40;
-var _7=20;
-var pt,px,py,_8;
-pt=this.util.lineSub(c.x,c.y,ay.x,ay.y,_6);
-px=pt.x+(ay.y-pt.y);
-py=pt.y+(pt.x-ay.x);
-_8=this.util.lineSub(pt.x,pt.y,px,py,(_6-_7));
-_8=this.util.lineSub(pt.x,pt.y,px,py,(_6-_7));
-return {x:_8.x,y:_8.y,width:20};
-},setLabel:function(_9){
-if(this._labelsCreated){
-return;
-}
-!this.labelX&&this.createLabels();
-var x="x";
-var y="y";
-if(_9){
-_9.replace(/^\s+/,"");
-_9.replace(/\s+$/,"");
-var _a=_9.match(/(.*?)(and|&)(.*)/i);
-if(_a.length>2){
-x=_a[1].replace(/\s+$/,"");
-y=_a[3].replace(/^\s+/,"");
-}
-}
-this.labelX.setLabel(x);
-this.labelY.setLabel(y);
-this._labelsCreated=true;
-},getLabel:function(){
-if(!this.labelX){
-return {};
-}
-return {x:this.labelX._text,y:this.labelY._text};
-},anchorPositionCheck:function(x,y,_b){
-var pm=this.container.getParent().getTransform();
-var am=_b.shape.getTransform();
-var p=this.points;
-var o={x:am.dx+_b.org.x+pm.dx,y:am.dy+_b.org.y+pm.dy};
-var c={x:p[1].x+pm.dx,y:p[1].y+pm.dy};
-var ox=c.x-(c.y-o.y);
-var oy=c.y-(o.x-c.x);
-return {x:ox,y:oy};
-},onTransformBegin:function(_c){
-this._isBeingModified=true;
-},onTransformEnd:function(_d){
-if(!_d){
-return;
-}
-this._isBeingModified=false;
-this._toggleSelected();
-var o=this.points[0];
-var c=this.points[1];
-var pt=this.util.constrainAngle({start:{x:c.x,y:c.y},x:o.x,y:o.y},91,180);
-if(pt.x==o.x&&pt.y==o.y){
-var _e={start:{x:c.x,y:c.y},x:o.x,y:o.y};
-pt=this.util.snapAngle(_e,this.angleSnap/180);
-_e.x=pt.x;
-_e.y=pt.y;
-var ox=_e.start.x-(_e.start.y-_e.y);
-var oy=_e.start.y-(_e.x-_e.start.x);
-if(ox<0||oy<0){
-console.warn("AXES ERROR LESS THAN ZERO - ABORT");
-return;
-}
-this.points=[{x:_e.x,y:_e.y},{x:_e.start.x,y:_e.start.y,noAnchor:true}];
-this.points.push({x:ox,y:oy,noAnchor:true});
-this.setPoints(this.points);
-this.onModify(this);
-return;
-}
-this.points[0].x=pt.x;
-this.points[0].y=pt.y;
-o=this.points[0];
-var ox=c.x-(c.y-o.y);
-var oy=c.y-(o.x-c.x);
-this.points[2]={x:ox,y:oy,noAnchor:true};
-this.setPoints(this.points);
-this.labelX.setLabel();
-this.labelY.setLabel();
-this.onModify(this);
-},getBounds:function(_f){
-var px=this.points[0],pc=this.points[1],py=this.points[2];
-if(_f){
-return {x:pc.x,y:pc.y,x1:pc.x,y1:pc.y,x2:px.x,y2:px.y,x3:py.x,y3:py.y};
-}
-var x1=py.x,y1=py.y<px.y?py.y:px.y,x2=px.x,y2=pc.y;
-return {x1:x1,y1:y1,x2:x2,y2:y2,x:x1,y:y1,w:x2-x1,h:y2-y1};
-},_postSetPoints:function(pts){
-this.points[0]=pts[0];
-if(this.pointsToData){
-this.data=this.pointsToData();
-}
-},onTransform:function(_10){
-var o=this.points[0];
-var c=this.points[1];
-var ox=c.x-(c.y-o.y);
-var oy=c.y-(o.x-c.x);
-this.points[2]={x:ox,y:oy,noAnchor:true};
-this.setPoints(this.points);
-if(!this._isBeingModified){
-this.onTransformBegin();
-}
-this.render();
-},pointsToData:function(){
-var p=this.points;
-return {x1:p[1].x,y1:p[1].y,x2:p[0].x,y2:p[0].y,x3:p[2].x,y3:p[2].y};
-},dataToPoints:function(o){
-o=o||this.data;
-if(o.radius||o.angle){
-o.angle=(180-o.angle)<0?180-o.angle+360:180-o.angle;
-var pt=this.util.pointOnCircle(o.x,o.y,o.radius,o.angle);
-var ox=o.x-(o.y-pt.y);
-var oy=o.y-(pt.x-o.x);
-this.data=o={x2:o.x,y2:o.y,x1:pt.x,y1:pt.y,x3:ox,y3:oy};
-}
-this.points=[{x:o.x1,y:o.y1},{x:o.x2,y:o.y2,noAnchor:true},{x:o.x3,y:o.y3,noAnchor:true}];
-return this.points;
-},onDrag:function(obj){
-var pt=this.util.constrainAngle(obj,91,180);
-obj.x=pt.x;
-obj.y=pt.y;
-var ox=obj.start.x-(obj.start.y-obj.y);
-var oy=obj.start.y-(obj.x-obj.start.x);
-if(ox<0||oy<0){
-return;
-}
-this.points=[{x:obj.x,y:obj.y},{x:obj.start.x,y:obj.start.y,noAnchor:true}];
-this.points.push({x:ox,y:oy,noAnchor:true});
-this.render();
-},onUp:function(obj){
-var p=this.points;
-if(!p.length){
-return;
-}
-var len=this.util.distance(p[1].x,p[1].y,p[0].x,p[0].y);
-if(!p||!p.length){
-return;
-}else{
-if(len<this.minimumSize){
-this.remove(this.shape,this.hit);
-this.xArrow.remove(this.xArrow.shape,this.xArrow.hit);
-this.yArrow.remove(this.yArrow.shape,this.yArrow.hit);
-return;
-}
-}
-var o=p[0];
-var c=p[1];
-obj={start:{x:c.x,y:c.y},x:o.x,y:o.y};
-var pt=this.util.snapAngle(obj,this.angleSnap/180);
-obj.x=pt.x;
-obj.y=pt.y;
-var ox=obj.start.x-(obj.start.y-obj.y);
-var oy=obj.start.y-(obj.x-obj.start.x);
-if(ox<0||oy<0){
-return;
-}
-this.points=[{x:obj.x,y:obj.y},{x:obj.start.x,y:obj.start.y,noAnchor:true}];
-this.points.push({x:ox,y:oy,noAnchor:true});
-this.onRender(this);
-this.setPoints=this._postSetPoints;
-}});
-dojox.drawing.tools.custom.Axes.setup={name:"dojox.drawing.tools.custom.Axes",tooltip:"Axes Tool",iconClass:"iconAxes"};
-dojox.drawing.register(dojox.drawing.tools.custom.Axes.setup,"tool");
-}
+
+
+dojox.drawing.tools.custom.Axes = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Draws a right-angle Axes (shaped like an L, not a +)
+	// description:
+	//		This Stencil is created with a Path so that the L shape
+	//		is one continuous piece. Arrow heads are placed at the end
+	// 		of each axis. The Axes can be rotated. There are custom
+	// 		label methods.
+	//
+	dojox.drawing.stencil.Path,
+	function(options){
+		this.closePath = false;
+
+		this.xArrow = new dojox.drawing.annotations.Arrow({stencil:this, idx1:0, idx2:1});
+		this.yArrow = new dojox.drawing.annotations.Arrow({stencil:this, idx1:2, idx2:1});
+		if(options.data){
+			//Allows import of z-axis in non-enabled canvas and xy-axis in
+			//enabled canvas
+			this.style.zAxisEnabled = options.data.cosphi == 1 ? true : false;
+			this.setData(options.data);
+		}
+		if(this.style.zAxisEnabled){
+			// If the z-axis is enabled, all axes will be created with a z-axis on the canvas.
+			// there is no switching back and forth for the axis, only for vectors.
+			this.data.cosphi = 1;
+			var ops = {};
+			dojo.mixin(ops,options);
+			dojo.mixin(ops,{
+				container:this.container.createGroup(),
+				style: this.style,
+				showAngle: false,
+				label: null
+			});
+			if(options.data && (!ops.data.radius || !ops.data.angle)){
+				ops.data.x2 = ops.data.x4;
+				ops.data.y2 = ops.data.y4;
+			}
+			ops.style.zAxis = true;
+			this.zAxis = new dojox.drawing.tools.custom.Vector(ops);
+			this.zAxis.minimumSize = 5;
+			//console.log("-----constructing axes: ",this.zAxis);
+			this.connectMult([
+				[this, "onChangeStyle", this.zAxis, "onChangeStyle"],
+				[this, "select", this.zAxis, "select"],
+				[this, "deselect", this.zAxis, "deselect"],
+				[this, "onDelete", this.zAxis, "destroy"],
+				[this, "onDrag", this, "zSet"],
+				[this, "onTransform", this, "zSet"],
+				[this.zAxis, "onBeforeRender", this, "zSet"],
+				[this, "_onPostRender", this.zAxis, "render"]
+			]);
+			
+		}
+
+		if(this.points && this.points.length){
+			this.setPoints = this._postSetPoints;
+			// render isn't called yet because baseRender is false
+			// instead it is called here
+			this.render();
+			options.label && this.setLabel(options.label);
+			options.shadow && this.addShadow(options.shadow);
+		}
+	},
+	{
+		draws:true,
+		type:"dojox.drawing.tools.custom.Axes",
+		minimumSize:30,
+		showAngle:true,
+		closePath:false,
+		baseRender:false,
+		zScale:.5,
+		
+		zPoint: function(obj){
+			// summary:
+			//		Finds the point for the z axis.
+			obj.radius = this.util.length(obj);
+			var pt = this.util.pointOnCircle(obj.start.x, obj.start.y, obj.radius*this.zScale, this.style.zAngle);
+			return {x:pt.x, y:pt.y, skip:true, noAnchor:true};
+		},
+		
+		zSet: function(){
+			if(!this.zAxis){ return; };
+			var c = this.points[1];
+			var z = this.points[3];
+			var p = [
+				{x:c.x, y:c.y},
+				{x:z.x, y:z.y}
+			];
+			var len = this.util.length({start:{x:c.x, y:c.y}, x:z.x, y:z.y});
+			len > this.zAxis.minimumSize ? this.zAxis.setPoints(p) : false; 
+			this.zAxis.cosphi = 1; 
+		},
+		
+		createLabels: function(){
+			// summary:
+			//		Creates the label for each axis.
+			//
+			// NOTE: Not passing style into text because it's changing it
+			var props = {align:"middle", valign:"middle", util:this.util, annotation:true, container:this.container, mouse:this.mouse, stencil:this};
+			this.labelX = new dojox.drawing.annotations.Label(dojo.mixin(props,{
+				labelPosition:this.setLabelX
+			}));
+			this.labelY = new dojox.drawing.annotations.Label(dojo.mixin(props,{
+				labelPosition:this.setLabelY
+			}));
+			if(this.style.zAxisEnabled){
+				this.labelZ = new dojox.drawing.annotations.Label(dojo.mixin(props,{
+					labelPosition:this.setLabelZ
+				}));
+			}
+
+		},
+
+		setLabelX: function(){
+			// summary:
+			//		Custom placement for x-axis label
+			//
+			var ax = this.points[0];
+			var c =  this.points[1];
+
+			var dist = 40;
+			var offdist = 20;
+			var pt, px, py, pt2;
+
+			pt = this.util.lineSub(c.x, c.y, ax.x, ax.y, dist);
+			px = pt.x + (pt.y -ax.y);
+			py = pt.y + (ax.x - pt.x);
+			pt2 = this.util.lineSub(pt.x, pt.y, px, py, (dist-offdist));
+
+			return {
+				x:  pt2.x,
+				y:  pt2.y,
+				width:20
+			};
+		},
+		setLabelY: function(){
+			// summary:
+			//		Custom placement for y-axis label
+			//
+			var c =  this.points[1];
+			var ay = this.points[2];
+
+			var dist = 40;
+			var offdist = 20;
+			var pt, px, py, pt2;
+			pt = this.util.lineSub(c.x, c.y, ay.x, ay.y, dist);
+			px = pt.x + (ay.y - pt.y);
+			py = pt.y + (pt.x - ay.x);
+			pt2 = this.util.lineSub(pt.x, pt.y, px, py, (dist-offdist));
+			return {
+				x:  pt2.x,
+				y:  pt2.y,
+				width:20
+			};
+		},
+		setLabelZ: function(){
+			// summary:
+			//		Custom placement for z-axis label
+			//
+			var c = this.points[1];
+			var z = this.points[3];
+			
+			var dist = 40;
+			var offdist = 20;
+			var pt, px, py, pt2;
+			pt = this.util.lineSub(c.x, c.y, z.x, z.y, dist);
+			px = pt.x + (pt.y - z.y);
+			py = pt.y + (z.x - pt.x);
+			pt2 = this.util.lineSub(pt.x, pt.y, px, py, (dist-offdist));
+			
+			return {
+				x:pt2.x,
+				y:pt2.y,
+				width:20
+			}
+		},
+		setLabel: function(/* ? String*/value){
+			// summary:
+			//		Set the text of the labels. The text would be
+			//		broken up into the two labels.
+			// arguments:
+			//		value: [optional] String
+			//			If no argument is passed, defaults to two labels
+			//			'x' and 'y'. If an argument is passed, that
+			//			text will be split on the word 'and' to determine
+			//			the two labels.
+			//
+			if(this._labelsCreated){ return; }
+			!this.labelX && this.createLabels();
+			var x = "x";
+			var y = "y";
+			var z = "z";
+			if(value){
+				// match first "and" or "&" and trim whitespace.
+				// Non-greedy matches are not supported in older
+				// browsers such as Netscape Navigator 4 or
+				// Microsoft Internet Explorer 5.0.
+				if(this.labelZ){
+					var lbls = value.match(/(.*?)(and|&)(.*?)(and|&)(.*)/i);
+					if(lbls.length>4){
+						x = lbls[1].replace(/^\s+/,"").replace(/\s+$/,"");
+						y = lbls[3].replace(/^\s+/,"").replace(/\s+$/,"");
+						z = lbls[5].replace(/^\s+/,"").replace(/\s+$/,"");
+					}
+				}else{
+					var lbls = value.match(/(.*?)(and|&)(.*)/i);
+					if(lbls.length>2){
+						x = lbls[1].replace(/^\s+/,"").replace(/\s+$/,"");
+						y = lbls[3].replace(/^\s+/,"").replace(/\s+$/,"");
+					}
+				}
+			}
+			this.labelX.setLabel(x);
+			this.labelY.setLabel(y);
+			if(this.labelZ){
+				this.labelZ.setLabel(z);
+			}
+			this._labelsCreated = true;
+		},
+		getLabel: function(){
+			// summary:
+			//		Getter for the labels. returns an object.
+			//
+			if(!this.labelX){ return null; }
+			return {
+				x:this.labelX.getText(),
+				y:this.labelY.getText(),
+				z:this.labelZ?this.labelZ.getText():null
+			}; // Object
+		},
+
+		anchorPositionCheck: function(/*Number*/x, /*Number*/y, /*manager.Anchor*/anchor){
+			// summary:
+			//		Gets called from anchor to check if its current
+			//		position is ok. If not, its x or y transform will
+			// 		be changed until this passes.
+			//
+			var pm = this.container.getParent().getTransform();
+			var am = anchor.shape.getTransform();
+
+			// the xaxis point has changed and is not yet set as a point
+			//	- but the center should be good (except for the transform).
+			// Now check the yaxis point.
+
+			var p = this.points;
+			var o = {x:am.dx+anchor.org.x+pm.dx, y:am.dy+anchor.org.y+pm.dy};
+			var c = {x:p[1].x+pm.dx, y:p[1].y+pm.dy};
+			var ox = c.x - (c.y - o.y);
+			var oy = c.y - (o.x - c.x);
+
+			return {x:ox, y:oy};
+
+		},
+
+		onTransformBegin: function(/*manager.Anchor*/anchor){
+			// summary:
+			//		Overwrites _Base.onTransformBegin
+			//
+			// called from anchor point up mouse down
+			this._isBeingModified = true;
+		},
+
+		onTransformEnd: function(/*manager.Anchor*/anchor){
+			// summary:
+			//		Overwrites _Base.onTransformEnd
+			//
+			// Gets called on anchor mouseup
+			//	also gets called by checkBounds - we don't want that.
+			if(!anchor){ return; }
+
+			//	tell anchor to go to prev point if wrong
+			// called from anchor point up mouse up
+
+			this._isBeingModified = false;
+			//this.deselect();
+			this._toggleSelected();
+			console.log("before:", Math.ceil(this.points[1].x), " x ", Math.ceil(this.points[1].y))
+
+			var o = this.points[0];
+			var c = this.points[1];
+			var obj = {start:{x:c.x,y:c.y},x:o.x, y:o.y};
+			var pt = this.util.constrainAngle(obj, 0, 89);
+			var zpt = this.style.zAxisEnabled ? this.zPoint(obj) : null;
+
+			if(pt.x==o.x && pt.y == o.y){
+				// we're within the constraint, so now we snap
+				pt = this.util.snapAngle(obj, this.angleSnap/180);
+
+				obj.x = pt.x;
+				obj.y = pt.y;
+				var ox = obj.start.x - (obj.start.y - obj.y);
+				var oy = obj.start.y - (obj.x - obj.start.x);
+
+				if(ox<0 || oy<0){
+					console.warn("AXES ERROR LESS THAN ZERO - ABORT");
+					return;
+				}
+				this.points = [{x:obj.x, y:obj.y}, {x:obj.start.x, y:obj.start.y, noAnchor:true}];
+				this.points.push({x:ox, y:oy, noAnchor:true});
+				if(zpt){ this.points.push(zpt);}
+				this.setPoints(this.points);
+
+				//this.select();
+				this.onModify(this);
+				return;
+			}
+
+			// we're outside of the constraint. Set to the low or high.
+			this.points[0].x = pt.x
+			this.points[0].y = pt.y;
+			o = this.points[0];
+
+			var ox = c.x - (c.y - o.y);
+			var oy = c.y - (o.x - c.x);
+
+			this.points[2] = {x:ox, y:oy, noAnchor:true};
+			if(zpt){ this.points.push(zpt); }
+			this.setPoints(this.points);
+
+			// reset handles render
+			//anchor.reset(this);
+
+			this.labelX.setLabel();
+			this.labelY.setLabel();
+			if(this.labelZ){
+				this.labelZ.setLabel();
+			}
+
+			//this.select();
+			this.onModify(this);
+
+		},
+
+		getBounds: function(/*Boolean*/absolute){
+			// summary:
+			//		Custom getBounds overwrites _Base.getBounds
+			//
+			var px = this.points[0],
+			    pc = this.points[1],
+			    py = this.points[2];
+			if(this.style.zAxisEnabled){ var pz = this.points[3]; }
+
+			if(absolute){
+				var bounds = {
+					x:pc.x,
+					y:pc.y,
+					x1:pc.x,
+					y1:pc.y,
+					x2:px.x,
+					y2:px.y,
+					x3:py.x,
+					y3:py.y
+				};
+				if(this.style.zAxisEnabled){
+					bounds.x4 = pz.x;
+					bounds.y4 = pz.y;
+				}
+				return bounds;
+			}
+
+			var x1 = this.style.zAxisEnabled ? (py.x < pz.x ? py.x : pz.x) : py.x;
+			    y1 = py.y < px.y ? py.y : px.y,
+			    x2 = px.x,
+			    y2 = this.style.zAxisEnabled ? pz.y : pc.y;
+
+			return {
+				x1:x1,
+				y1:y1,
+				x2:x2,
+				y2:y2,
+				x:x1,
+				y:y1,
+				w:x2-x1,
+				h:y2-y1
+			};
+		},
+
+		_postSetPoints: function(/*Array*/pts){
+			// summary:
+			// 		Because Axes only has one anchor,
+			// 		we substitute a special setPoints method
+			//
+			this.points[0] = pts[0];
+			if(this.pointsToData){
+				this.data = this.pointsToData();
+			}
+		},
+
+		onTransform: function(/*Number*/anchor){
+			// summary:
+			//		Overwrites _Base.onTransform
+			//
+			// the xaxis point has changed - the center will not.
+			// need to find the yaxis point.
+			var o = this.points[0];
+			var c = this.points[1];
+			var ox = c.x - (c.y - o.y);
+			var oy = c.y - (o.x - c.x);
+
+			// 'noAnchor' on a point indicates an anchor should
+			// not be rendered. This is the Y point being set.
+			this.points[2] = {x:ox, y:oy, noAnchor:true};
+			if(this.style.zAxisEnabled){
+				this.points[3] = this.zPoint({start:{x:c.x, y:c.y}, x:o.x, y:o.y});
+			}
+			this.setPoints(this.points);
+			if(!this._isBeingModified){
+				this.onTransformBegin();
+			}
+			this.render();
+		},
+
+		pointsToData: function(){
+			//summary:
+			//		Converts points to data.
+			var p = this.points;
+			var d = {
+				x1:p[1].x,
+				y1:p[1].y,
+				x2:p[0].x,
+				y2:p[0].y,
+				x3:p[2].x,
+				y3:p[2].y
+			}
+			if(this.style.zAxisEnabled){
+				d.x4 = p[3].x;
+				d.y4 = p[3].y;
+				d.cosphi = 1;
+			}
+			return d;
+			
+		},
+		
+		getRadius: function(){
+			//summary:
+			//		Possibility of z-axis makes bounds unreliable.
+			//		Use these points instead.
+			var p = this.points;
+			var line = {start:{x:p[1].x, y:p[1].y}, x:p[0].x, y:p[0].y};
+			return this.util.length(line);
+		},
+
+		dataToPoints: function(/* ? Object*/o){
+			//summary:
+			//		Converts data to points.
+			o = o || this.data;
+			if(o.radius || o.angle){
+				// instead of using x1,x2,y1,y1,
+				// it's been set as x,y,angle,radius
+				var pt = this.util.pointOnCircle(o.x,o.y,o.radius,o.angle), zpt;
+				var ox = o.x - (o.y - pt.y);
+				var oy = o.y - (pt.x - o.x);
+				if((o.cosphi && o.cosphi==1) || this.style.zAxisEnabled){
+					this.style.zAxisEnabled = true;
+					zpt = this.util.pointOnCircle(o.x, o.y, o.radius*this.zScale, this.style.zAngle);
+				}
+				this.data = o = {
+					x1:o.x,
+					y1:o.y,
+					x2:pt.x,
+					y2:pt.y,
+					x3:ox,
+					y3:oy
+				}
+				if(this.style.zAxisEnabled){
+					this.data.x4 = o.x4 = zpt.x;
+					this.data.y4 = o.y4 = zpt.y;
+					this.data.cosphi = 1;
+				}
+
+			}
+			this.points = [
+				{x:o.x2, y:o.y2},
+				{x:o.x1, y:o.y1, noAnchor:true},
+				{x:o.x3, y:o.y3, noAnchor:true}
+			];
+			if(this.style.zAxisEnabled){ this.points.push({x:o.x4, y:o.y4, skip:true, noAnchor:true}); }
+			return this.points;
+		},
+
+		onDrag: function(/*EventObject*/obj){
+			// summary: See stencil._Base.onDrag
+			//
+			var pt = this.util.constrainAngle(obj, 0, 89);
+			obj.x = pt.x;
+			obj.y = pt.y;
+			var ox = obj.start.x - (obj.start.y - obj.y);
+			var oy = obj.start.y - (obj.x - obj.start.x);
+
+			if(ox<0 || oy<0){
+				return;
+			}
+			this.points = [{x:obj.x, y:obj.y}, {x:obj.start.x, y:obj.start.y, noAnchor:true}];
+
+			this.points.push({x:ox, y:oy, noAnchor:true});
+			if(this.style.zAxisEnabled){
+				var zpt = this.zPoint(obj);
+				this.points.push(zpt);
+			}
+			this.render();
+		},
+
+		onUp: function(/*EventObject*/obj){
+			// summary: See stencil._Base.onUp
+			//
+			if(!this._downOnCanvas){ return; }
+			this._downOnCanvas = false;
+			var p = this.points;
+			if(!p.length){
+				var s = obj.start, d = 100;
+				this.points = [
+					{x:s.x+d, y:s.y+d},
+					{x:s.x, y:s.y+d, noAnchor:true},
+					{x:s.x, y:s.y, noAnchor:true}
+				];
+				if(this.style.zAxisEnabled){
+					var zpt = this.zPoint({start:{x:s.x, y:s.y+d}, x:s.x+d, y:s.y+d});
+					this.points.push(zpt);
+				}
+				this.setPoints = this._postSetPoints;
+				this.pointsToData();
+				this.render();
+				this.onRender(this);
+				return;
+			}
+
+			var len = this.util.distance(p[1].x ,p[1].y ,p[0].x ,p[0].y );
+			if(!p || !p.length){
+				return;
+			}else if(len < this.minimumSize){
+				this.remove(this.shape, this.hit);
+				this.xArrow.remove(this.xArrow.shape, this.xArrow.hit);
+				this.yArrow.remove(this.yArrow.shape, this.yArrow.hit);
+				if(this.zArrow){
+				  this.zArrow.remove(this.zArrow.shape, this.zArrow.hit);
+				}
+				return;
+			}
+
+			var o = p[0];
+			var c = p[1];
+			obj = {start:{x:c.x,y:c.y},x:o.x,y:o.y};
+			var pt = this.util.snapAngle(obj, this.angleSnap/180);
+			obj.x = pt.x;
+			obj.y = pt.y;
+			var ox = obj.start.x - (obj.start.y - obj.y);
+			var oy = obj.start.y - (obj.x - obj.start.x);
+
+			if(ox<0 || oy<0){
+				return;
+			}
+			this.points = [{x:obj.x, y:obj.y}, {x:obj.start.x, y:obj.start.y, noAnchor:true}];
+
+			this.points.push({x:ox, y:oy, noAnchor:true});
+			if(this.style.zAxisEnabled){ this.points.push(this.zPoint(obj)); }
+			this.onRender(this);
+			this.setPoints = this._postSetPoints;
+		}
+	}
+);
+
+dojox.drawing.tools.custom.Axes.setup = {
+	// summary: See stencil._Base ToolsSetup
+	//
+	name:"dojox.drawing.tools.custom.Axes",
+	tooltip:"Axes Tool",
+	iconClass:"iconAxes"
+};
+dojox.drawing.register(dojox.drawing.tools.custom.Axes.setup, "tool");
\ No newline at end of file
diff --git a/dojox/drawing/tools/custom/Equation.js b/dojox/drawing/tools/custom/Equation.js
index 6e0dac5..5cd3a20 100644
--- a/dojox/drawing/tools/custom/Equation.js
+++ b/dojox/drawing/tools/custom/Equation.js
@@ -1,16 +1,26 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.tools.custom.Equation"]){
-dojo._hasResource["dojox.drawing.tools.custom.Equation"]=true;
 dojo.provide("dojox.drawing.tools.custom.Equation");
 dojo.require("dojox.drawing.tools.TextBlock");
-dojox.drawing.tools.custom.Equation=dojox.drawing.util.oo.declare(dojox.drawing.tools.TextBlock,function(_1){
-},{customType:"equation"});
-dojox.drawing.tools.custom.Equation.setup={name:"dojox.drawing.tools.custom.Equation",tooltip:"Equation Tool",iconClass:"iconEq"};
-dojox.drawing.register(dojox.drawing.tools.custom.Equation.setup,"tool");
-}
+
+dojox.drawing.tools.custom.Equation = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Essentially the same as the TextBlock tool, but
+	//		allows for a different icon and tooltip title.
+	//
+	dojox.drawing.tools.TextBlock,
+	function(options){
+	
+	},
+	{
+		customType:"equation"
+	}
+	
+);
+
+dojox.drawing.tools.custom.Equation.setup = {
+	// summary: See stencil._Base ToolsSetup
+	//
+	name:"dojox.drawing.tools.custom.Equation",
+	tooltip:"Equation Tool",
+	iconClass:"iconEq"
+};
+dojox.drawing.register(dojox.drawing.tools.custom.Equation.setup, "tool");
\ No newline at end of file
diff --git a/dojox/drawing/tools/custom/Vector.js b/dojox/drawing/tools/custom/Vector.js
old mode 100644
new mode 100755
index 6b47205..4f2bd40
--- a/dojox/drawing/tools/custom/Vector.js
+++ b/dojox/drawing/tools/custom/Vector.js
@@ -1,52 +1,402 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.tools.custom.Vector"]){
-dojo._hasResource["dojox.drawing.tools.custom.Vector"]=true;
 dojo.provide("dojox.drawing.tools.custom.Vector");
 dojo.require("dojox.drawing.tools.Arrow");
 dojo.require("dojox.drawing.util.positioning");
-dojox.drawing.tools.custom.Vector=dojox.drawing.util.oo.declare(dojox.drawing.tools.Arrow,function(_1){
-this.minimumSize=this.style.arrows.length;
-},{draws:true,type:"dojox.drawing.tools.custom.Vector",minimumSize:30,showAngle:true,labelPosition:function(){
-var d=this.data;
-var pt=dojox.drawing.util.positioning.label({x:d.x1,y:d.y1},{x:d.x2,y:d.y2});
-return {x:pt.x,y:pt.y};
-},_createZeroVector:function(_2,d,_3){
-var s=_2=="hit"?this.minimumSize:this.minimumSize/2;
-var f=_2=="hit"?_3.fill:null;
-d={cx:this.data.x1,cy:this.data.y1,rx:s,ry:s};
-this.remove(this[_2]);
-this[_2]=this.container.createEllipse(d).setStroke(_3).setFill(f);
-this.util.attr(this[_2],"drawingType","stencil");
-},render:function(){
-this.onBeforeRender(this);
-if(this.getRadius()>=this.minimumSize){
-this._create("hit",this.data,this.style.currentHit);
-this._create("shape",this.data,this.style.current);
-}else{
-this._createZeroVector("hit",this.data,this.style.currentHit);
-this._createZeroVector("shape",this.data,this.style.current);
-}
-},onUp:function(_4){
-if(this.created||!this.shape){
-return;
-}
-if(this.getRadius()<this.minimumSize){
-var p=this.points;
-this.setPoints([{x:p[0].x,y:p[0].y},{x:p[0].x,y:p[0].y}]);
-}else{
-var pt=this.util.snapAngle(_4,this.angleSnap/180);
-var p=this.points;
-this.setPoints([{x:p[0].x,y:p[0].y},{x:pt.x,y:pt.y}]);
-}
-this.renderedOnce=true;
-this.onRender(this);
-}});
-dojox.drawing.tools.custom.Vector.setup={name:"dojox.drawing.tools.custom.Vector",tooltip:"Vector Tool",iconClass:"iconVector"};
-dojox.drawing.register(dojox.drawing.tools.custom.Vector.setup,"tool");
+
+dojox.drawing.tools.custom.Vector = dojox.drawing.util.oo.declare(
+	// summary:
+	//		Creates a Vector Stencil.
+	// description:
+	//		Generally the same as an arrow, except that the arrow
+	//		head is only at the end. There is additionaly functionality
+	//		to allow for a 'zero vector' - one with no length.
+	//
+	// 	TODO: Zero Vectors are less than the minimumSize. But if
+	//	you get the radius, it will report a length.
+	//
+	dojox.drawing.tools.Arrow,
+	function(options){
+		this.minimumSize = this.style.arrows.length;
+		this.addShadow({size:3, mult:2});
+	},
+	{
+		draws:true,
+		type:"dojox.drawing.tools.custom.Vector",
+		minimumSize:30,
+		showAngle:true,
+		
+		labelPosition: function(){
+			// summary:
+			//		The custom position used for the label
+			//
+			var d = this.data;
+			var pt = dojox.drawing.util.positioning.label({x:d.x1,y:d.y1},{x:d.x2,y:d.y2});
+			return {
+				x:pt.x,
+				y:pt.y
+			}
+		},
+		
+		changeAxis: function(cosphi){
+			//	summary:
+			//		Converts a vector to and from the z axis.
+			//		If passed a cosphi value that is used to set
+			//		the axis, otherwise it is the opp of what it is.
+			cosphi = cosphi!==undefined?cosphi:this.style.zAxis? 0 : 1;
+			if(cosphi == 0){
+				this.style.zAxis = false;
+				this.data.cosphi = 0;
+			}else{
+				this.style.zAxis = true;
+				var p = this.points;
+				var pt = this.zPoint();
+				this.setPoints([
+					{x:p[0].x, y:p[0].y},
+					{x:pt.x, y:pt.y}
+				]);
+			}
+			this.render();
+		},
+		
+		_createZeroVector: function(shp, d, sty){
+			// summary:
+			//		Special creation function for the zero-vector shape
+			//
+			var s = shp=="hit" ? this.minimumSize : this.minimumSize/6;
+			var f = shp=="hit" ? sty.fill : null;
+			d = {
+				cx:this.data.x1,
+				cy:this.data.y1,
+				rx:s,
+				ry:s
+			};
+			
+			this.remove(this[shp]);
+			this[shp] = this.container.createEllipse(d)
+				.setStroke(sty)
+				.setFill(f);
+			this.util.attr(this[shp], "drawingType", "stencil");
+		},
+		
+		_create: function(/*String*/shp, /*StencilData*/d, /*Object*/sty){
+			// summary:
+			//		Creates a dojox.gfx.shape based on passed arguments.
+			//		Can be called many times by implementation to create
+			//		multiple shapes in one stencil.
+			//
+			this.remove(this[shp]);
+			this[shp] = this.container.createLine(d)
+				.setStroke(sty);
+			this._setNodeAtts(this[shp]);
+		},
+		
+		onDrag: function(/*EventObject*/obj){
+			// summary: See stencil._Base.onDrag
+			//
+			if(this.created){ return; }
+			
+			var x1 = obj.start.x,
+				y1 = obj.start.y,
+				x2 = obj.x,
+				y2 = obj.y;
+			
+			if(this.keys.shift && !this.style.zAxis){
+				var pt = this.util.snapAngle(obj, 45/180);
+				x2 = pt.x;
+				y2 = pt.y;
+			}
+			
+			if(this.keys.alt){
+				// FIXME:
+				//	should double the length of the line
+				// FIXME:
+				//	if alt dragging past ZERO it seems to work
+				//	but select/deselect shows bugs
+				var dx = x2>x1 ? ((x2-x1)/2) : ((x1-x2)/-2);
+				var dy = y2>y1 ? ((y2-y1)/2) : ((y1-y2)/-2);
+				x1 -= dx;
+				x2 -= dx;
+				y1 -= dy;
+				y2 -= dy;
+			}
+			
+			if(this.style.zAxis){
+				var pts = this.zPoint(obj);
+				x2 = pts.x;
+				y2 = pts.y;
+			}
+			
+			this.setPoints([
+				{x:x1, y:y1},
+				{x:x2, y:y2}
+			]);
+			this.render();
+		},
+		
+		onTransform: function(/* ? manager.Anchor */anchor){
+			// summary:
+			// 		Called from anchor point mouse drag
+			// 		also called from plugins.Pan.checkBounds
+			if(!this._isBeingModified){
+				this.onTransformBegin();
+			}
+			// this is not needed for anchor moves, but it
+			// is for stencil move:
+			
+			this.setPoints(this.points);
+			this.render();			
+		},
+		
+		anchorConstrain: function(x, y){
+			//	summary:
+			//		Called from anchor point mouse drag
+			if(!this.style.zAxis){ return null; }
+			var radians = this.style.zAngle*Math.PI/180;
+			//Constrain to angle
+			var test = x<0 ? x>-y : x<-y;
+			var dx = test ? x : -y/Math.tan(radians); 
+			var dy = !test ? y : -Math.tan(radians)*x;
+			return {x:dx, y:dy}
+		},
+		
+		zPoint: function(obj){
+			//	summary:
+			//		Takes any point and converts it to
+			//		be on the z-axis.
+			if(obj===undefined){
+				if(!this.points[0]){ return null; };
+				var d = this.pointsToData();
+				obj = {
+					start:{
+						x:d.x1,
+						y:d.y1
+					},
+					x:d.x2,
+					y:d.y2
+				};
+			}
+			var radius = this.util.length(obj);
+			var angle = this.util.angle(obj);
+			angle<0 ? angle = 360 + angle : angle;
+			
+			angle = angle > 135 && angle < 315 ? this.style.zAngle : this.util.oppAngle(this.style.zAngle);
+			
+			return this.util.pointOnCircle(obj.start.x, obj.start.y, radius, angle);
+		},
+		
+		pointsToData: function(p){
+			// summary:
+			//		Converts points to data
+			p = p || this.points;
+			var cosphi = 0;
+			var obj = {start:{x:p[0].x, y:p[0].y}, x:p[1].x, y:p[1].y};
+			if(this.style.zAxis && (this.util.length(obj)>this.minimumSize)){
+				
+				var angle = this.util.angle(obj);
+				angle<0 ? angle = 360 + angle : angle;
+				cosphi = angle > 135 && angle < 315 ? 1 : -1;
+			}
+			this.data = {
+				x1: p[0].x,
+				y1: p[0].y,
+				x2: p[1].x,
+				y2: p[1].y,
+				cosphi: cosphi
+			};
+			return this.data;
+		},
+		
+		dataToPoints: function(o){
+			//summary:
+			//		Converts data to points.
+			o = o || this.data;
+			if(o.radius || o.angle){
+				// instead of using x1,x2,y1,y1,
+				// it's been set as x,y,angle,radius
+				var cosphi = 0;
+				var pt = this.util.pointOnCircle(o.x,o.y,o.radius,o.angle);
+				if(this.style.zAxis || (o.cosphi && o.cosphi!=0)){
+					this.style.zAxis = true;
+					cosphi = o.angle > 135 && o.angle < 315 ? 1 : -1;
+				}
+				//console.log(" ---- pts:", pt.x, pt.y);
+				this.data = o = {
+					x1:o.x,
+					y1:o.y,
+					x2:pt.x,
+					y2:pt.y,
+					cosphi:cosphi
+				}
+				
+			}
+			this.points = [
+				{x:o.x1, y:o.y1},
+				{x:o.x2, y:o.y2}
+			];
+			return this.points;
+		},
+		
+		render: function(){
+			// summary:
+			//		Renders the 'hit' object (the shape used for an expanded
+			//		hit area and for highlighting) and the'shape' (the actual
+			//		display object). Additionally checks if Vector should be
+			//		drawn as an arrow or a circle (zero-length)
+			//
+			this.onBeforeRender(this);
+			if(this.getRadius() >= this.minimumSize){
+				this._create("hit", this.data, this.style.currentHit);
+				this._create("shape", this.data, this.style.current);
+			
+			}else{
+				this.data.cosphi = 0;
+				this._createZeroVector("hit", this.data, this.style.currentHit);
+				this._createZeroVector("shape", this.data, this.style.current);
+			}
+		},
+		onUp: function(/*EventObject*/obj){
+			// summary: See stencil._Base.onUp
+			//
+			if(this.created || !this._downOnCanvas){ return; }
+			this._downOnCanvas = false;
+			//Default vector for single click
+			if(!this.shape){
+				var d = 100;
+				obj.start.x = this.style.zAxis ? obj.start.x + d : obj.start.x;
+				obj.y = obj.y+d;
+				this.setPoints([
+					{x:obj.start.x, y:obj.start.y},
+					{x:obj.x, y:obj.y}
+				]);
+				this.render();
+			}
+			
+			// if too small, need to reset
+			// 		This sets the zero length vector to zero within the minimum size 
+			
+			if(this.getRadius()<this.minimumSize){
+				var p = this.points; 
+				this.setPoints([ 
+					{x:p[0].x, y:p[0].y}, 
+					{x:p[0].x, y:p[0].y} 
+				]); 
+			}else{ 			
+				//needed as else to avoid zero length problem in snapAngle 
+				var p = this.points;
+				var pt = this.style.zAxis ? this.zPoint(obj) : this.util.snapAngle(obj, this.angleSnap/180);
+				this.setPoints([
+					{x:p[0].x, y:p[0].y},
+					{x:pt.x, y:pt.y}
+				]);
+			}
+			this.renderedOnce = true;
+			this.onRender(this);
+		}
+	}
+	
+);
+
+dojox.drawing.tools.custom.Vector.setup = {
+	// summary: See stencil._Base ToolsSetup
+	//
+	name:"dojox.drawing.tools.custom.Vector",
+	tooltip:"Vector Tool",
+	iconClass:"iconVector"
+};
+
+if(dojox.drawing.defaults.zAxisEnabled){
+	dojox.drawing.tools.custom.Vector.setup.secondary = {
+		// summary:
+		//		Creates a secondary tool for the Vector Stencil.
+		// description:
+		//		See Toolbar.js makeButtons function.  The toolbar 
+		//		checks Vector.setup for a secondary tool and requires
+		//		name, label, and funct.  Currently it doesn't accept icon
+		//		and only uses text from label for the button.  Funct is the
+		//		function that fires when the button is clicked.
+		//
+		//		Setup and postSetup are optional
+		//		and allow tool specific functions to be added to the
+		//		Toolbar object as if they were written there.
+		name: "vectorSecondary",
+		label: "z-axis",
+		funct: function(button){
+			button.selected ? this.zDeselect(button) : this.zSelect(button);
+			
+			var stencils = this.drawing.stencils.selectedStencils;
+			for(var nm in stencils){
+				if(stencils[nm].shortType == "vector" && (stencils[nm].style.zAxis != dojox.drawing.defaults.zAxis)){
+					var s = stencils[nm];
+					s.changeAxis();
+					//Reset anchors
+					if(s.style.zAxis){ s.deselect(); s.select(); }
+				}
+			}
+			
+		},
+		setup: function(){
+			// summary:
+			//		All functions, variables and connections defined here
+			//		are treated as if they were added directly to toolbar.
+			//		They are included with the tool because secondary buttons
+			//		are tool specific.
+			var zAxis = dojox.drawing.defaults.zAxis;
+			this.zSelect = function(button){
+				if(!button.enabled){ return; }
+				zAxis = true;
+				dojox.drawing.defaults.zAxis = true;
+				button.select();
+				this.vectorTest();
+				this.zSelected = button;
+			};
+			this.zDeselect = function(button){
+				if(!button.enabled){ return; }
+				zAxis = false;
+				dojox.drawing.defaults.zAxis = false;
+				button.deselect();
+				this.vectorTest();
+				this.zSelected = null;
+			};
+			this.vectorTest = function(){
+				dojo.forEach(this.buttons, function(b){
+					if(b.toolType=="vector" && b.selected){
+						this.drawing.currentStencil.style.zAxis = zAxis;
+					} 
+				},this);
+			};
+			dojo.connect(this, "onRenderStencil", this, function(){ if(this.zSelected){ this.zDeselect(this.zSelected)}});
+			var c = dojo.connect(this.drawing, "onSurfaceReady", this, function(){
+				dojo.disconnect(c);
+				dojo.connect(this.drawing.stencils, "onSelect", this, function(stencil){
+					if(stencil.shortType == "vector"){
+						if(stencil.style.zAxis){
+							//If stencil is on the z-axis, update button to reflect that
+							dojo.forEach(this.buttons, function(b){
+								if(b.toolType=="vectorSecondary"){
+									this.zSelect(b);
+								}
+							},this);
+							
+						}else{
+							//Update button to not be z-axis
+							dojo.forEach(this.buttons, function(b){
+								if(b.toolType=="vectorSecondary"){
+									this.zDeselect(b);
+								}
+							},this);
+						}
+					};
+				});
+			});
+		},
+		postSetup: function(btn){
+			// summary:
+			//		Depending on the secondary tool, it may need
+			//		extra functionality for some of the basic functions.
+			//		Post is passed the button so those connections can
+			//		be made.
+			dojo.connect(btn, "enable", function(){ dojox.drawing.defaults.zAxisEnabled = true; });
+			dojo.connect(btn, "disable", function(){ dojox.drawing.defaults.zAxisEnabled = false; });
+		}
+	};
 }
+dojox.drawing.register(dojox.drawing.tools.custom.Vector.setup, "tool");
\ No newline at end of file
diff --git a/dojox/drawing/ui/Button.js b/dojox/drawing/ui/Button.js
index 487741d..7c34225 100644
--- a/dojox/drawing/ui/Button.js
+++ b/dojox/drawing/ui/Button.js
@@ -1,140 +1,226 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.ui.Button");
 
+dojox.drawing.ui.Button =  dojox.drawing.util.oo.declare(
+	// summary:
+	//		Creates a clickable button in "UI" mode of the drawing.
+	// description:
+	//		Creates a 4-state button: normal, hover, active, selected.
+	//		Optionally may include button text or an icon.
+	function(options){
+		options.subShape = true;
+		dojo.mixin(this, options);
+		//console.log("  button:", this);
+		this.width = options.data.width || options.data.rx*2;
+		this.height = options.data.height || options.data.ry*2;
+		this.y = options.data.y || options.data.cy - options.data.ry;
+		//
+		this.id = this.id || this.util.uid(this.type);
+		this.util.attr(this.container, "id", this.id);
+		if(this.callback){
+			this.hitched = dojo.hitch(this.scope || window, this.callback, this);
+		}
+		
+		// Rectangle itself must be "ui" for radio buttons to work.
+		// This is a work-around for messy code associated with drawingType;
+		// see http://www.andestutor.org/bugzilla/show_bug.cgi?id=1745
+		options.drawingType="ui";
+		// Choose between rectangle and ellipse based on options
+		if(options.data.width && options.data.height){
+			this.shape = new dojox.drawing.stencil.Rect(options);
+		}else{
+			this.shape = new dojox.drawing.stencil.Ellipse(options);
+		}
+		
+		var setGrad = function(s, p, v){
+			dojo.forEach(["norm", "over", "down", "selected"], function(nm){
+				s[nm].fill[p] = v;
+			});
+		};
+		// for button backs, not for icons
+		setGrad(this.style.button, "y2", this.height + this.y);
+		setGrad(this.style.button, "y1", this.y);
+		
+		if(options.icon && !options.icon.text){
+			var constr = this.drawing.getConstructor(options.icon.type);
+			var o = this.makeOptions(options.icon);
+			o.data = dojo.mixin(o.data, this.style.button.icon.norm);
+			
+			if(o.data && o.data.borderWidth===0){
+				o.data.fill = this.style.button.icon.norm.fill = o.data.color;
+			}else if(options.icon.type=="line" || (options.icon.type=="path" && !options.icon.closePath)){
+				this.style.button.icon.selected.color = this.style.button.icon.selected.fill;
+			}else{
+				//o.data.fill = this.style.button.icon.norm.fill = o.data.color;
+			}
+			this.icon = new constr(o);
+			//console.log("  button:", this.toolType, this.style.button.icon)
+		}else if(options.text || (options.icon && options.icon.text)){
+			//console.warn("button text:", options.text || options.icon.text)
+			o = this.makeOptions(options.text || options.icon.text);
+			o.data.color = this.style.button.icon.norm.color; //= o.data.fill;
+			this.style.button.icon.selected.color = this.style.button.icon.selected.fill;
+			this.icon = new dojox.drawing.stencil.Text(o);
+			this.icon.attr({
+				height:	this.icon._lineHeight,
+				y:((this.height-this.icon._lineHeight)/2)+this.y
+			});
+		}
+		
+		var c = this.drawing.getConstructor(this.toolType);
+		if(c){
+			this.drawing.addUI("tooltip", {data:{text:c.setup.tooltip}, button:this});
+		}
+		
+		this.onOut();
+		
+	},{
+		
+		callback:null,
+		scope:null,
+		hitched:null,
+		toolType:"",
+		
+		onClick: function(/*Object*/button){
+			// summary:
+			//		Stub to connect. Event is 'this'
+			//		Alternatively can pass in a scope and a callback
+			//		on creation.
+		},
+		
+		makeOptions: function(/*Object*/d, /*Float*/s){
+			
+			s = s || 1;
+			d = dojo.clone(d);
+			var o = {
+				util: this.util,
+				mouse: this.mouse,
+				container: this.container,
+				subShape:true
+			};
+			
+			if(typeof(d)=="string"){
+				
+				o.data = {
+					x:this.data.x - 5,
+					y: this.data.y + 2,
+					width:this.data.width,
+					height:this.data.height,
+					text:d,
+					makeFit:true
+				};
+			
+			}else if(d.points){
+				//console.warn("points")
+				dojo.forEach(d.points, function(pt){
+					pt.x = pt.x * this.data.width * .01 * s + this.data.x;
+					pt.y = pt.y * this.data.height * .01 * s + this.data.y;
+				}, this);
+				o.data = {};
+				for(var n in d){
+					if(n!="points"){
+						o.data[n] = d[n];
+					}
+				}
+				o.points = d.points;
+				
+			}else{
+				//console.warn("data")
+				for(n in d){
+					if(/x|width/.test(n)){
+						d[n] = d[n] * this.data.width * .01 * s;
+					}else if(/y|height/.test(n)){
+						d[n] = d[n] * this.data.height * .01 * s;
+					}
+					if(/x/.test(n) && !/r/.test(n)){
+						d[n] += this.data.x;
+					}else if(/y/.test(n) && !/r/.test(n)){
+						d[n] += this.data.y;
+					}
+				}
+				delete d.type;
+				o.data = d;
+				
+			}
+			o.drawingType = "ui";
+			return o;
+		
+			// do style
+			if(d.borderWidth!==undefined){
+				//console.log(" -------- bw data:", o.data)
+				o.data.borderWidth = d.borderWidth;
+			}
+			
+			return o;
+		},
+		
+		enabled:true,
+		selected:false,
+		type:"drawing.library.UI.Button",
+		
+		// note:
+		//	need to move the Stencil's shape to front, not
+		// its container. Therefore we can't use the Stencil's
+		// moveTo.. methods.
+		select: function(){
+			this.selected = true;
+			if(this.icon){this.icon.attr(this.style.button.icon.selected);}
+			this._change(this.style.button.selected);
+			this.shape.shadow && this.shape.shadow.hide();
+		},
+		deselect: function(){
+			this.selected = false;
+			if(this.icon){this.icon.attr(this.style.button.icon.norm);}
+			this.shape.shadow && this.shape.shadow.show();
+			this._change(this.style.button.norm);
+			
+		},
+		disable: function(){
+			if(!this.enabled){ return; }
+			this.enabled = false;
+			this._change(this.style.button.disabled);
+			this.icon.attr({color:this.style.button.norm.color});
+		},
+		enable: function(){
+			if(this.enabled){ return; }
+			this.enabled = true;
+			this._change(this.style.button.norm);
+			this.icon.attr({color:this.style.button.icon.norm.color});
+		},
+		
+		_change: function(/*Object*/sty){
+			this.shape.attr(sty);
+			this.shape.shadow && this.shape.shadow.container.moveToBack();	
+			if(this.icon){this.icon.shape.moveToFront();};
+		},
+		onOver: function(){
+			//console.log("BUTTON OVER")
+			if(this.selected || !this.enabled){ return; }
+			this._change(this.style.button.over);
+		},
+		onOut: function(){
+			if(this.selected){ return; }
+			this._change(this.style.button.norm);
+		},
+		onDown: function(){
+			if(this.selected || !this.enabled){ return; }
+			this._change(this.style.button.selected);
+		},
+		onUp: function(){
+			//console.log("BUTTON UP")
+			if(!this.enabled){ return; }
+			this._change(this.style.button.over);
+			if(this.hitched){
+				this.hitched();
+			}
+			this.onClick(this);
+		},
+		attr: function(options){
+			if(this.icon){this.icon.attr(options);}
+		}
+	}	
+	
+);
 
-if(!dojo._hasResource["dojox.drawing.ui.Button"]){
-dojo._hasResource["dojox.drawing.ui.Button"]=true;
-dojo.provide("dojox.drawing.ui.Button");
-dojox.drawing.ui.Button=dojox.drawing.util.oo.declare(function(_1){
-_1.subShape=true;
-dojo.mixin(this,_1);
-this.width=_1.data.width;
-this.height=_1.data.height;
-this.id=this.id||this.util.uid(this.type);
-this.util.attr(this.container,"id",this.id);
-if(this.callback){
-this.hitched=dojo.hitch(this.scope||window,this.callback,this);
-}
-this.shape=new dojox.drawing.stencil.Rect(_1);
-var _2=function(s,p,v){
-dojo.forEach(["norm","over","down","selected"],function(nm){
-s[nm].fill[p]=v;
-});
-};
-_2(this.style.button,"y2",this.data.height+this.data.y);
-_2(this.style.button,"y1",this.data.y);
-if(_1.icon&&!_1.icon.text){
-var _3=this.drawing.getConstructor(_1.icon.type);
-var o=this.makeOptions(_1.icon);
-o.data=dojo.mixin(o.data,this.style.button.icon.norm);
-if(o.data&&o.data.borderWidth===0){
-o.data.fill=this.style.button.icon.norm.fill=o.data.color;
-}else{
-if(_1.icon.type=="line"||(_1.icon.type=="path"&&!_1.icon.closePath)){
-this.style.button.icon.selected.color=this.style.button.icon.selected.fill;
-}else{
-}
-}
-this.icon=new _3(o);
-}else{
-if(_1.text||_1.icon.text){
-var o=this.makeOptions(_1.text||_1.icon.text);
-o.data.color=this.style.button.icon.norm.color;
-this.style.button.icon.selected.color=this.style.button.icon.selected.fill;
-this.icon=new dojox.drawing.stencil.Text(o);
-this.icon.attr({height:this.icon._lineHeight,y:((this.data.height-this.icon._lineHeight)/2)+this.data.y});
-}
-}
-var c=this.drawing.getConstructor(this.toolType);
-if(c){
-this.drawing.addUI("tooltip",{data:{text:c.setup.tooltip},button:this});
-}
-this.onOut();
-},{callback:null,scope:null,hitched:null,toolType:"",onClick:function(_4){
-},makeOptions:function(d,s){
-s=s||1;
-d=dojo.clone(d);
-var o={util:this.util,mouse:this.mouse,container:this.container,subShape:true};
-if(typeof (d)=="string"){
-o.data={x:this.data.x-5,y:this.data.y+2,width:this.data.width,height:this.data.height,text:d,makeFit:true};
-}else{
-if(d.points){
-dojo.forEach(d.points,function(pt){
-pt.x=pt.x*this.data.width*0.01*s+this.data.x;
-pt.y=pt.y*this.data.height*0.01*s+this.data.y;
-},this);
-o.data={};
-for(var n in d){
-if(n!="points"){
-o.data[n]=d[n];
-}
-}
-o.points=d.points;
-}else{
-for(var n in d){
-if(/x|width/.test(n)){
-d[n]=d[n]*this.data.width*0.01*s;
-}else{
-if(/y|height/.test(n)){
-d[n]=d[n]*this.data.height*0.01*s;
-}
-}
-if(/x/.test(n)&&!/r/.test(n)){
-d[n]+=this.data.x;
-}else{
-if(/y/.test(n)&&!/r/.test(n)){
-d[n]+=this.data.y;
-}
-}
-}
-delete d.type;
-o.data=d;
-}
-}
-o.drawingType="ui";
-return o;
-if(d.borderWidth!==undefined){
-o.data.borderWidth=d.borderWidth;
-}
-return o;
-},enabled:true,selected:false,type:"drawing.library.UI.Button",select:function(){
-this.selected=true;
-this.icon.attr(this.style.button.icon.selected);
-this._change(this.style.button.selected);
-this.shape.shadow&&this.shape.shadow.hide();
-},deselect:function(){
-this.selected=false;
-this.icon.attr(this.style.button.icon.norm);
-this.shape.shadow&&this.shape.shadow.show();
-this._change(this.style.button.norm);
-},_change:function(_5){
-this.shape.attr(_5);
-this.shape.shadow&&this.shape.shadow.container.moveToBack();
-this.icon.shape.moveToFront();
-},onOver:function(){
-if(this.selected){
-return;
-}
-this._change(this.style.button.over);
-},onOut:function(){
-if(this.selected){
-return;
-}
-this._change(this.style.button.norm);
-},onDown:function(){
-if(this.selected){
-return;
-}
-this._change(this.style.button.selected);
-},onUp:function(){
-this._change(this.style.button.over);
-if(this.hitched){
-this.hitched();
-}
-this.onClick(this);
-}});
-dojox.drawing.register({name:"dojox.drawing.ui.Button"},"stencil");
-}
+dojox.drawing.register({
+	name:"dojox.drawing.ui.Button"	
+}, "stencil");
\ No newline at end of file
diff --git a/dojox/drawing/ui/Toolbar.js b/dojox/drawing/ui/Toolbar.js
index 5b65af8..b2dc25e 100644
--- a/dojox/drawing/ui/Toolbar.js
+++ b/dojox/drawing/ui/Toolbar.js
@@ -1,123 +1,279 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.ui.Toolbar"]){
-dojo._hasResource["dojox.drawing.ui.Toolbar"]=true;
 dojo.provide("dojox.drawing.ui.Toolbar");
 dojo.require("dojox.drawing.library.icons");
-dojo.declare("dojox.drawing.ui.Toolbar",[],{constructor:function(_1,_2){
-this.util=dojox.drawing.util.common;
-if(_1.drawing){
-this.toolDrawing=_1.drawing;
-this.drawing=this.toolDrawing;
-this.width=this.toolDrawing.width;
-this.height=this.toolDrawing.height;
-this.strSelected=_1.selected;
-this.strTools=_1.tools;
-this.strPlugs=_1.plugs;
-this._mixprops(["padding","margin","size","radius"],_1);
-this.addBack();
-}else{
-var _3=dojo.marginBox(_2);
-this.width=_3.w;
-this.height=_3.h;
-this.strSelected=dojo.attr(_2,"selected");
-this.strTools=dojo.attr(_2,"tools");
-this.strPlugs=dojo.attr(_2,"plugs");
-this._mixprops(["padding","margin","size","radius"],_2);
-this.toolDrawing=new dojox.drawing.Drawing({mode:"ui"},_2);
-}
-this.horizontal=this.width>this.height;
-if(this.toolDrawing.ready){
-this.makeButtons();
-}else{
-var c=dojo.connect(this.toolDrawing,"onSurfaceReady",this,function(){
-dojo.disconnect(c);
-this.drawing=dojox.drawing.getRegistered("drawing",dojo.attr(_2,"drawingId"));
-this.makeButtons();
-});
-}
-},padding:10,margin:5,size:30,radius:3,toolPlugGap:20,strSlelected:"",strTools:"",strPlugs:"",makeButtons:function(){
-this.buttons=[];
-this.plugins=[];
-var x=this.padding,y=this.padding,w=this.size,h=this.size,r=this.radius,g=this.margin,_4=dojox.drawing.library.icons,s={place:"BR",size:2,mult:4};
-if(this.strTools){
-var _5=[];
-if(this.strTools=="all"){
-for(var nm in dojox.drawing.getRegistered("tool")){
-_5.push(this.util.abbr(nm));
-}
-}else{
-_5=this.strTools.split(",");
-dojo.map(_5,function(t){
-return dojo.trim(t);
-});
-}
-dojo.forEach(_5,function(t){
-t=dojo.trim(t);
-var _6=this.toolDrawing.addUI("button",{data:{x:x,y:y,width:w,height:h,r:r},toolType:t,icon:_4[t],shadow:s,scope:this,callback:"onToolClick"});
-this.buttons.push(_6);
-if(this.strSelected==t){
-_6.select();
-this.drawing.setTool(_6.toolType);
-}
-if(this.horizontal){
-y+=h+g;
-}else{
-y+=h+g;
-}
-},this);
-}
-if(this.horizontal){
-y+=this.toolPlugGap;
-}else{
-y+=this.toolPlugGap;
-}
-if(this.strPlugs){
-var _7=[];
-if(this.strPlugs=="all"){
-for(var nm in dojox.drawing.getRegistered("plugin")){
-_7.push(this.util.abbr(nm));
-}
-}else{
-_7=this.strPlugs.split(",");
-dojo.map(_7,function(p){
-return dojo.trim(p);
-});
-}
-dojo.forEach(_7,function(p){
-t=dojo.trim(p);
-var _8=this.toolDrawing.addUI("button",{data:{x:x,y:y,width:w,height:h,r:r},toolType:t,icon:_4[t],shadow:s,scope:this,callback:"onPlugClick"});
-this.plugins.push(_8);
-if(this.horizontal){
-y+=h+g;
-}else{
-y+=h+g;
-}
-this.drawing.addPlugin({name:this.drawing.stencilTypeMap[p],options:{button:_8}});
-},this);
-}
-},addTool:function(){
-},addPlugin:function(){
-},addBack:function(){
-this.toolDrawing.addUI("rect",{data:{x:0,y:0,width:this.width,height:this.size+(this.padding*2),fill:"#ffffff",borderWidth:0}});
-},onToolClick:function(_9){
-dojo.forEach(this.buttons,function(b){
-if(b.id==_9.id){
-b.select();
-this.drawing.setTool(_9.toolType);
-}else{
-b.deselect();
-}
-},this);
-},onPlugClick:function(_a){
-},_mixprops:function(_b,_c){
-dojo.forEach(_b,function(p){
-this[p]=_c.tagName?dojo.attr(_c,p)===null?this[p]:dojo.attr(_c,p):_c[p]===undefined?this[p]:_c[p];
-},this);
-}});
-}
+
+dojo.declare("dojox.drawing.ui.Toolbar", [], {
+	// summary:
+	//		A Toolbar used for holding buttons; typically representing the Stencils
+	//		used for a DojoX Drawing.
+	// description:
+	//		Creates a GFX-based toobar that holds GFX-based buttons. Can be either created
+	//		within the actual drawing or within a seperate DOM element. When within the
+	//		drawing, the toolbar will cover a portion of the drawing; hence the option.
+	//
+	//		A Toolbar can be created programmtically or in markup. Currently markup is as
+	//		a separate DOM element and programmtic is within the drawing.
+	// examples:
+	//		|	dojo.connect(myDrawing, "onSurfaceReady", function(){
+	//		|		new dojox.drawing.ui.Toolbar({
+	//		|			drawing:myDrawing,
+	//		|			tools:"all",
+	//		|			plugs:"all",
+	//		|			selected:"ellipse"
+	//		|		});
+	//		|	});
+	//
+	//		| <div dojoType="dojox.drawing.ui.Toolbar" id="gfxToolbarNode" drawingId="drawingNode"
+	//		|		class="gfxToolbar" tools="all" plugs="all" selected="ellipse"></div>
+	//
+	//
+	constructor: function(props, node){
+		//console.warn("GFX Toolbar:", props, node)
+		this.util = dojox.drawing.util.common;
+		
+		// no mixin. painful.
+		if(props.drawing){
+			// programmatic
+			this.toolDrawing = props.drawing;
+			this.drawing = this.toolDrawing;
+			this.width = this.toolDrawing.width;
+			this.height = this.toolDrawing.height;
+			this.strSelected = props.selected;
+			this.strTools = props.tools;
+			this.strPlugs = props.plugs;
+			this._mixprops(["padding", "margin", "size", "radius"], props);
+			this.addBack()
+		}else{
+			// markup
+			var box = dojo.marginBox(node);
+			this.width = box.w;
+			this.height = box.h;
+			this.strSelected = dojo.attr(node, "selected");
+			this.strTools = dojo.attr(node, "tools");
+			this.strPlugs = dojo.attr(node, "plugs");
+			this._mixprops(["padding", "margin", "size", "radius"], node);
+			this.toolDrawing = new dojox.drawing.Drawing({mode:"ui"}, node);
+		}
+		
+		this.horizontal = this.width > this.height;
+		
+		if(this.toolDrawing.ready){
+			this.makeButtons();
+			if(!this.strSelected && this.drawing.defaults.clickMode){ this.drawing.mouse.setCursor('default'); };
+		}else{
+			var c = dojo.connect(this.toolDrawing, "onSurfaceReady", this, function(){
+				//console.log("TB built")
+				dojo.disconnect(c);
+				this.drawing = dojox.drawing.getRegistered("drawing", dojo.attr(node, "drawingId")); // 
+				this.makeButtons();
+				if(!this.strSelected && this.drawing.defaults.clickMode){ 
+					var c = dojo.connect(this.drawing, "onSurfaceReady", this, function(){
+					dojo.disconnect(c);
+					this.drawing.mouse.setCursor('default'); 
+					});
+				}
+			});
+		}
+		
+	},
+	
+	// padding:Number
+	//		The amount of spce between the top and left of the toolbar and the buttons.
+	padding:10,
+	// margin: Number
+	//		The space between each button.
+	margin:5,
+	// size: Number
+	//		The width and height of the button
+	size:30,
+	// radius: Number
+	//		The size of the button's rounded corner
+	radius:3,
+	//
+	// toolPlugGap: number
+	//		The distnce between the tool buttons and plug buttons
+	toolPlugGap:20,
+	
+	//	strSlelected | selected: String
+	//		The button that should be selected at startup.
+	strSelected:"",
+	//	strTools | tools: String
+	//		A comma delineated list of the Stencil-tools to include in the Toolbar.
+	//		If "all" is used, all registered tools are included.
+	strTools:"",
+	//	strPlugs | plugs: String
+	//		A comma delineated list of the plugins to include in the Toolbar.
+	//		If "all" is used, all registered plugins are included.
+	strPlugs:"",
+	
+	makeButtons: function(){
+		// summary:
+		//		Internal. create buttons.
+		this.buttons = [];
+		this.plugins = [];
+	
+		var x = this.padding, y = this.padding, w = this.size, h = this.size, r = this.radius, g = this.margin,
+				 sym = dojox.drawing.library.icons,
+				 s = {place:"BR", size:2, mult:4};
+				 
+		if(this.strTools){
+			var toolAr = [];
+			var tools = dojox.drawing.getRegistered("tool");
+			var toolMap = {};
+			for(var nm in tools){
+				var tool = this.util.abbr(nm);
+				toolMap[tool] = tools[nm];
+				if(this.strTools=="all"){
+					toolAr.push(tool);
+					var details = dojox.drawing.getRegistered("tool",nm);
+					if(details.secondary){
+						toolAr.push(details.secondary.name);
+					}
+				}
+			}
+			if(this.strTools!="all"){
+				var toolTmp = this.strTools.split(",");
+				dojo.forEach(toolTmp, function(tool){
+					tool = dojo.trim(tool);
+					toolAr.push(tool);
+					var details = dojox.drawing.getRegistered("tool",toolMap[tool].name);
+					if(details.secondary){
+						toolAr.push(details.secondary.name);
+					}
+				}, this);
+				//dojo.map(toolAr, function(t){ return dojo.trim(t); });
+			}
+			
+			dojo.forEach(toolAr, function(t){
+				t = dojo.trim(t);
+				var secondary = false;
+				if(t.indexOf("Secondary")>-1){
+					var prim = t.substring(0,t.indexOf("Secondary"));
+					var sec = dojox.drawing.getRegistered("tool",toolMap[prim].name).secondary;
+					var label = sec.label;
+					this[t] = sec.funct;
+					if(sec.setup){ dojo.hitch(this, sec.setup)(); };
+					var btn = this.toolDrawing.addUI("button", {data:{x:x, y:y, width:w, height:h/2, r:r}, toolType:t, secondary:true, text:label, shadow:s, scope:this, callback:this[t]});
+					if(sec.postSetup){ dojo.hitch(this, sec.postSetup, btn)(); };
+					secondary = true;
+				} else {
+					var btn = this.toolDrawing.addUI("button", {data:{x:x, y:y, width:w, height:h, r:r}, toolType:t, icon:sym[t], shadow:s, scope:this, callback:"onToolClick"});
+				}
+				dojox.drawing.register(btn, "button");
+				this.buttons.push(btn);
+				if(this.strSelected==t){
+					btn.select();
+					this.selected = btn;
+					this.drawing.setTool(btn.toolType);
+				}
+				if(this.horizontal){
+					var space = secondary ? h/2 + g : h + g;
+					y += space;
+				}else{
+					var space = secondary ? h/2 + g : h + g;
+					y += space;
+				}
+			}, this);
+		}
+		
+		if(this.horizontal){
+			y += this.toolPlugGap;
+		}else{
+			y += this.toolPlugGap;
+		}
+		
+		if(this.strPlugs){
+			var plugAr = [];
+			var plugs = dojox.drawing.getRegistered("plugin");
+			var plugMap = {};
+			for(var nm in plugs){
+				var abbr = this.util.abbr(nm);
+				plugMap[abbr] = plugs[nm];
+				if(this.strPlugs=="all"){ plugAr.push(abbr); }
+			}
+			if(this.strPlugs!="all"){
+				plugAr = this.strPlugs.split(",");
+				dojo.map(plugAr, function(p){ return dojo.trim(p); });
+			}
+			
+			dojo.forEach(plugAr, function(p){
+				var t = dojo.trim(p);
+				//console.log("   plugin:", p);
+				if(plugMap[p].button != false){  
+					var btn = this.toolDrawing.addUI("button", {data:{x:x, y:y, width:w, height:h, r:r}, toolType:t, icon:sym[t], shadow:s, scope:this, callback:"onPlugClick"});
+					dojox.drawing.register(btn, "button");
+					this.plugins.push(btn);
+					
+					if(this.horizontal){
+						y += h + g;
+					}else{
+						y += h + g;
+					}
+				}
+				
+				var addPlug = {}
+				plugMap[p].button == false ? addPlug = {name:this.drawing.stencilTypeMap[p]} : addPlug = {name:this.drawing.stencilTypeMap[p], options:{button:btn}};
+				this.drawing.addPlugin(addPlug); 
+			}, this);
+		}
+		
+		dojo.connect(this.drawing, "onRenderStencil", this, "onRenderStencil");
+	},
+	
+	onRenderStencil: function(/* Object */stencil){
+		// summary:
+		//		Stencil render event.
+		if(this.drawing.defaults.clickMode){
+			this.drawing.mouse.setCursor("default");
+			this.selected && this.selected.deselect();
+			this.selected = null;
+		}
+
+	},
+	
+	addTool: function(){
+		// TODO: add button here
+	},
+	
+	addPlugin: function(){
+		// TODO: add button here
+	},
+	
+	addBack: function(){
+		// summary:
+		//		Internal. Adds the back, behind the toolbar.
+		this.toolDrawing.addUI("rect", {data:{x:0, y:0, width:this.width, height:this.size + (this.padding*2), fill:"#ffffff", borderWidth:0}});
+	},
+	
+	onToolClick: function(/*Object*/button){
+		// summary:
+		//		Tool click event. May be connected to.
+		//
+		if(this.drawing.defaults.clickMode){ this.drawing.mouse.setCursor("crosshair"); }
+		dojo.forEach(this.buttons, function(b){
+			if(b.id==button.id){
+				b.select();
+				this.selected = b;
+				this.drawing.setTool(button.toolType)
+			}else{
+				if(!b.secondary){ b.deselect(); }
+			}
+		},this)
+	},
+	
+	onPlugClick: function(/*Object*/button){
+		// summary:
+		//		Plugin click event. May be connected to.
+	},
+	
+	_mixprops: function(/*Array*/props, /*Object | Node*/objNode){
+		// summary:
+		//		Internally used for mixing in props from an object or
+		//		from a dom node.
+		dojo.forEach(props, function(p){
+			this[p] = objNode.tagName
+				? dojo.attr(objNode, p)===null ? this[p] : dojo.attr(objNode, p)
+				: objNode[p]===undefined ? this[p] : objNode[p];
+		}, this);
+	}
+	
+});
\ No newline at end of file
diff --git a/dojox/drawing/ui/Tooltip.js b/dojox/drawing/ui/Tooltip.js
index d5b1242..9336d48 100644
--- a/dojox/drawing/ui/Tooltip.js
+++ b/dojox/drawing/ui/Tooltip.js
@@ -1,64 +1,115 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.ui.Tooltip"]){
-dojo._hasResource["dojox.drawing.ui.Tooltip"]=true;
 dojo.provide("dojox.drawing.ui.Tooltip");
 dojo.require("dojox.drawing.plugins._Plugin");
+
+
 (function(){
-var _1=null;
-var _2=dojox.drawing.util.oo.declare(dojox.drawing.plugins._Plugin,function(_3){
-this.createDom();
-},{show:function(_4,_5){
-this.domNode.innerHTML=_5;
-var dx=30,dy=30;
-var px=_4.data.x+_4.data.width;
-var py=_4.data.y+_4.data.height;
-var x=px+this.mouse.origin.x+dx;
-var y=py+this.mouse.origin.y+dx;
-dojo.style(this.domNode,{display:"inline",left:x+"px",top:y+"px"});
-var _6=dojo.marginBox(this.domNode);
-this.createShape(x-this.mouse.origin.x,y-this.mouse.origin.y,_6.w,_6.h);
-},createShape:function(x,y,w,h){
-this.balloon&&this.balloon.destroy();
-var r=5,x2=x+w,y2=y+h,_7=[];
-var _8=function(){
-for(var i=0;i<arguments.length;i++){
-_7.push(arguments[i]);
-}
-};
-_8({x:x,y:y+5},{t:"Q",x:x,y:y},{x:x+r,y:y});
-_8({t:"L",x:x2-r,y:y});
-_8({t:"Q",x:x2,y:y},{x:x2,y:y+r});
-_8({t:"L",x:x2,y:y2-r});
-_8({t:"Q",x:x2,y:y2},{x:x2-r,y:y2});
-_8({t:"L",x:x+r,y:y2});
-_8({t:"Q",x:x,y:y2},{x:x,y:y2-r});
-_8({t:"L",x:x,y:y+r});
-this.balloon=this.drawing.addUI("path",{points:_7});
-},createDom:function(){
-this.domNode=dojo.create("span",{"class":"drawingTooltip"},document.body);
-dojo.style(this.domNode,{display:"none",position:"absolute"});
-}});
-dojox.drawing.ui.Tooltip=dojox.drawing.util.oo.declare(dojox.drawing.plugins._Plugin,function(_9){
-if(!_1){
-_1=new _2(_9);
-}
-if(_9.stencil){
-}else{
-if(this.button){
-this.connect(this.button,"onOver",this,"onOver");
-this.connect(this.button,"onOut",this,"onOut");
-}
-}
-},{width:300,height:200,onOver:function(){
-_1.show(this.button,this.data.text);
-},onOut:function(){
-}});
-dojox.drawing.register({name:"dojox.drawing.ui.Tooltip"},"stencil");
-})();
-}
+	
+	//	summary:
+	//		Used for UI tooltips. Buttons in the toolbar.
+	// 		This file is not complete.
+	//
+	var master = null;
+	var MasterC = dojox.drawing.util.oo.declare(
+		
+		dojox.drawing.plugins._Plugin,
+		function(options){
+			this.createDom();
+		},
+		{
+			show: function(button, text){
+				this.domNode.innerHTML = text;
+				
+				var dx = 30;
+				var px = button.data.x + button.data.width; 
+				var py = button.data.y + button.data.height;
+				var x =  px + this.mouse.origin.x + dx;
+				var y = py + this.mouse.origin.y + dx;
+				
+				dojo.style(this.domNode, {
+					display: "inline",
+					left:x +"px",
+					top:y+"px"
+				});
+				
+				var box = dojo.marginBox(this.domNode);
+				
+				this.createShape(x-this.mouse.origin.x, y-this.mouse.origin.y, box.w, box.h);
+			},
+			
+			
+			createShape: function(x,y,w,h){
+				this.balloon && this.balloon.destroy();
+				var r = 5, x2 = x+w, y2 = y+h, points = [];
+				var add = function(){
+					for(var i=0;i<arguments.length;i++){
+						points.push(arguments[i]);
+					}
+				};
+				
+				add({x:x,y:y+5},
+					{t:"Q", x:x,y:y},
+					{x:x+r,y:y});
+				
+				add({t:"L", x:x2-r,y:y});
+				
+				add({t:"Q", x:x2,y:y},
+					{x:x2,y:y+r});
+					
+				add({t:"L", x:x2,y:y2-r});
+					
+				add({t:"Q", x:x2,y:y2},
+					{x:x2-r,y:y2});
+				
+				add({t:"L", x:x+r,y:y2});
+				
+				add({t:"Q", x:x,y:y2},
+					{x:x,y:y2-r});
+					
+				add({t:"L", x:x,y:y+r});
+				
+				this.balloon = this.drawing.addUI("path", {points:points});
+			},
+			
+			createDom: function(){
+				this.domNode = dojo.create('span', {"class":"drawingTooltip"}, document.body);
+				dojo.style(this.domNode, {
+					display: "none",
+					position:"absolute"
+				});
+			}
+		}
+	);
+	
+	dojox.drawing.ui.Tooltip =  dojox.drawing.util.oo.declare(
+		
+		dojox.drawing.plugins._Plugin,
+		function(options){
+			if(!master){
+				master = new MasterC(options);
+			}
+			if(options.stencil){
+				//todo
+			}else if(this.button){
+				this.connect(this.button, "onOver", this, "onOver");
+				this.connect(this.button, "onOut", this, "onOut");
+			}
+			
+		},
+		{
+			width:300,
+			height:200,
+			onOver: function(){
+				//console.log("   tooltip over", this.data.text)
+				master.show(this.button, this.data.text);
+			},
+			
+			onOut: function(){
+				//console.log("   tooltip out")
+			}
+		}
+	);
+	
+	dojox.drawing.register({
+		name:"dojox.drawing.ui.Tooltip"	
+	}, "stencil");
+})();
\ No newline at end of file
diff --git a/dojox/drawing/ui/dom/Pan.js b/dojox/drawing/ui/dom/Pan.js
index b9d26bc..810fde0 100644
--- a/dojox/drawing/ui/dom/Pan.js
+++ b/dojox/drawing/ui/dom/Pan.js
@@ -1,118 +1,209 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.ui.dom.Pan"]){
-dojo._hasResource["dojox.drawing.ui.dom.Pan"]=true;
 dojo.provide("dojox.drawing.ui.dom.Pan");
 dojo.require("dojox.drawing.plugins._Plugin");
-dojo.deprecated("dojox.drawing.ui.dom.Pan","It may not even make it to the 1.4 release.",1.4);
-dojox.drawing.ui.dom.Pan=dojox.drawing.util.oo.declare(dojox.drawing.plugins._Plugin,function(_1){
-this.domNode=_1.node;
-var _2;
-dojo.connect(this.domNode,"click",this,"onSetPan");
-dojo.connect(this.keys,"onKeyUp",this,"onKeyUp");
-dojo.connect(this.keys,"onKeyDown",this,"onKeyDown");
-dojo.connect(this.anchors,"onAnchorUp",this,"checkBounds");
-dojo.connect(this.stencils,"register",this,"checkBounds");
-dojo.connect(this.canvas,"resize",this,"checkBounds");
-dojo.connect(this.canvas,"setZoom",this,"checkBounds");
-dojo.connect(this.canvas,"onScroll",this,function(){
-if(this._blockScroll){
-this._blockScroll=false;
-return;
-}
-_2&&clearTimeout(_2);
-_2=setTimeout(dojo.hitch(this,"checkBounds"),200);
-});
-this._mouseHandle=this.mouse.register(this);
-},{selected:false,type:"dojox.drawing.ui.dom.Pan",onKeyUp:function(_3){
-if(_3.keyCode==32){
-this.onSetPan(false);
-}
-},onKeyDown:function(_4){
-if(_4.keyCode==32){
-this.onSetPan(true);
-}
-},onSetPan:function(_5){
-if(_5===true||_5===false){
-this.selected=!_5;
-}
-if(this.selected){
-this.selected=false;
-dojo.removeClass(this.domNode,"selected");
-}else{
-this.selected=true;
-dojo.addClass(this.domNode,"selected");
-}
-this.mouse.setEventMode(this.selected?"pan":"");
-},onPanDrag:function(_6){
-var x=_6.x-_6.last.x;
-var y=_6.y-_6.last.y;
-this.canvas.domNode.parentNode.scrollTop-=_6.move.y;
-this.canvas.domNode.parentNode.scrollLeft-=_6.move.x;
-this.canvas.onScroll();
-},onStencilUp:function(_7){
-this.checkBounds();
-},onStencilDrag:function(_8){
-},checkBounds:function(){
-var _9=function(){
-};
-var _a=function(){
+dojo.deprecated("dojox.drawing.ui.dom.Pan", "It may not even make it to the 1.4 release.", 1.4);
+
+dojox.drawing.ui.dom.Pan = dojox.drawing.util.oo.declare(
+	// NOTE:
+	//			dojox.drawing.ui.dom.Pan is DEPRECATED.
+	//			This was a temporary DOM solution. Use the non-dom
+	//			tools for Toobar and Plugins.
+	//
+	// summary:
+	//		A plugin that allows for a scrolling canvas. An action
+	//		tool is added to the toolbar that allows for panning. Holding
+	//		the space bar is a shortcut to that action. The canvas will
+	//		only pan and scroll if there are objects out of the viewable
+	//		area.
+	// example:
+	//		|	<div dojoType="dojox.drawing.Toolbar" drawingId="drawingNode" class="drawingToolbar vertical">
+	//		|		<div tool="dojox.drawing.tools.Line" selected="true">Line</div>
+	//		|		<div plugin="dojox.drawing.ui.dom.Pan" options="{}">Pan</div>
+	//		|	</div>
+	//
+	dojox.drawing.plugins._Plugin,
+	function(options){
+		
+		this.domNode = options.node;
+		var _scrollTimeout;
+		dojo.connect(this.domNode, "click", this, "onSetPan");
+		dojo.connect(this.keys, "onKeyUp", this, "onKeyUp");
+		dojo.connect(this.keys, "onKeyDown", this, "onKeyDown");
+		dojo.connect(this.anchors, "onAnchorUp", this, "checkBounds");
+		dojo.connect(this.stencils, "register", this, "checkBounds");
+		dojo.connect(this.canvas, "resize", this, "checkBounds");
+		dojo.connect(this.canvas, "setZoom", this, "checkBounds");
+		dojo.connect(this.canvas, "onScroll", this, function(){
+			if(this._blockScroll){
+				this._blockScroll = false;
+				return;
+			}
+			_scrollTimeout && clearTimeout(_scrollTimeout);
+			_scrollTimeout = setTimeout(dojo.hitch(this, "checkBounds"), 200);
+		});
+		this._mouseHandle = this.mouse.register(this);
+		// This HAS to be called after setting initial objects or things get screwy.
+		//this.checkBounds();
+	},{
+		selected:false,
+		type:"dojox.drawing.ui.dom.Pan",
+		
+		onKeyUp: function(evt){
+			if(evt.keyCode == 32){
+				this.onSetPan(false);
+			}
+		},
+		
+		onKeyDown: function(evt){
+			if(evt.keyCode == 32){
+				this.onSetPan(true);
+			}
+		},
+		
+		onSetPan: function(/*Boolean | Event*/ bool){
+			if(bool === true || bool === false){
+				this.selected = !bool;
+			}
+			if(this.selected){
+				this.selected = false;
+				dojo.removeClass(this.domNode, "selected");
+			}else{
+				this.selected = true;
+				dojo.addClass(this.domNode, "selected");
+			}
+			this.mouse.setEventMode(this.selected ? "pan" : "");
+		},
+		
+		onPanDrag: function(obj){
+			var x = obj.x - obj.last.x;
+			var y = obj.y - obj.last.y;
+			this.canvas.domNode.parentNode.scrollTop -= obj.move.y;
+			this.canvas.domNode.parentNode.scrollLeft -= obj.move.x;
+			this.canvas.onScroll();
+		},
+		
+		onStencilUp: function(obj){
+			// this gets called even on click-off because of the
+			// issues with TextBlock deselection
+			this.checkBounds();
+		},
+		onStencilDrag: function(obj){
+			// this gets called even on click-off because of the
+			// issues with TextBlock deselection
+			//this.checkBounds();
+		},
+		
+		checkBounds: function(){
+			
+			//watch("CHECK BOUNDS DISABLED", true); return;
+			
+			
+			// summary:
+			//		Scans all items on the canvas and checks if they are out of
+			// 		bounds. If so, a scroll bar (in Canvas) is shown. If the position
+			// 		is left or top, the canvas is scrolled all items are relocated
+			// 		the distance of the scroll. Ideally, it should look as if the
+			// 		items do not move.
+			
+			// logging stuff here so it can be turned on and off. This method is
+			// very high maintenance.
+			var log = function(){
+				///console.log.apply(console, arguments);
+			};
+			var warn = function(){
+				//console.warn.apply(console, arguments);
+			};
+			//console.clear();
+			//console.time("check bounds");
+			var t=Infinity, r=-Infinity, b=-Infinity, l=Infinity,
+				sx=0, sy=0, dy=0, dx=0,
+				mx = this.stencils.group ? this.stencils.group.getTransform() : {dx:0, dy:0},
+				sc = this.mouse.scrollOffset(),
+				// scY, scX: the scrollbar creates the need for extra dimension
+				scY = sc.left ? 10 : 0, 
+				scX = sc.top ? 10 : 0,
+				// ch, cw: the current size of the canvas
+				ch = this.canvas.height,
+				cw = this.canvas.width,
+				z = this.canvas.zoom,
+				// pch, pcw: the normal size of the canvas (not scrolled)
+				// these could change if the container resizes.
+				pch = this.canvas.parentHeight,
+				pcw = this.canvas.parentWidth;
+			
+			
+			this.stencils.withSelected(function(m){
+				var o = m.getBounds();
+				warn("SEL BOUNDS:", o);
+				t = Math.min(o.y1 + mx.dy, t);
+				r = Math.max(o.x2 + mx.dx, r);
+				b = Math.max(o.y2 + mx.dy, b);
+				l = Math.min(o.x1 + mx.dx, l);
+			});
+			
+			this.stencils.withUnselected(function(m){
+				var o = m.getBounds();
+				warn("UN BOUNDS:", o);
+				t = Math.min(o.y1, t);
+				r = Math.max(o.x2, r);
+				b = Math.max(o.y2, b);
+				l = Math.min(o.x1, l);
+			});
+			
+			b *= z;
+			var xscroll = 0, yscroll = 0;
+			log("Bottom test", "b:", b, "z:", z, "ch:", ch, "pch:", pch, "top:", sc.top, "sy:", sy);
+			if(b > pch || sc.top ){ 
+				log("*bottom scroll*");
+				// item off bottom
+				ch = Math.max(b, pch + sc.top);
+				sy = sc.top;
+				xscroll += this.canvas.getScrollWidth();
+			}else if(!sy && ch>pch){
+				log("*bottom remove*");
+				// item moved from bottom
+				ch = pch;
+			}
+			
+			r *= z;
+			if(r > pcw || sc.left){
+				//log("*right scroll*");
+				// item off right
+				cw = Math.max(r, pcw + sc.left);
+				sx = sc.left;
+				yscroll += this.canvas.getScrollWidth();
+			}else if(!sx && cw>pcw){
+				//log("*right remove*");
+				// item moved from right
+				cw = pcw;
+			}
+			
+			// add extra space for scrollbars
+			// double it to give some breathing room
+			cw += xscroll*2;
+			ch += yscroll*2;
+			
+			this._blockScroll = true;
+			
+			// selected items are not transformed. The selection itself is
+			// and the items are on de-select
+			this.stencils.group && this.stencils.group.applyTransform({dx:dx, dy:dy});
+			
+			// non-selected items are transformed
+			this.stencils.withUnselected(function(m){
+				m.transformPoints({dx:dx, dy:dy});
+			});
+			
+			this.canvas.setDimensions(cw, ch, sx, sy);
+			
+			//console.timeEnd("check bounds");
+		}
+	}
+);
+
+dojox.drawing.ui.dom.Pan.setup = {
+	name:"dojox.drawing.ui.dom.Pan",
+	tooltip:"Pan Tool",
+	iconClass:"iconPan"
 };
-var t=Infinity,r=-Infinity,b=-Infinity,l=Infinity,sx=0,sy=0,dy=0,dx=0,mx=this.stencils.group?this.stencils.group.getTransform():{dx:0,dy:0},sc=this.mouse.scrollOffset(),_b=sc.left?10:0,_c=sc.top?10:0,ch=this.canvas.height,cw=this.canvas.width,z=this.canvas.zoom,_d=this.canvas.parentHeight,_e=this.canvas.parentWidth;
-this.stencils.withSelected(function(m){
-var o=m.getBounds();
-_a("SEL BOUNDS:",o);
-t=Math.min(o.y1+mx.dy,t);
-r=Math.max(o.x2+mx.dx,r);
-b=Math.max(o.y2+mx.dy,b);
-l=Math.min(o.x1+mx.dx,l);
-});
-this.stencils.withUnselected(function(m){
-var o=m.getBounds();
-_a("UN BOUNDS:",o);
-t=Math.min(o.y1,t);
-r=Math.max(o.x2,r);
-b=Math.max(o.y2,b);
-l=Math.min(o.x1,l);
-});
-b*=z;
-var _f=0,_10=0;
-_9("Bottom test","b:",b,"z:",z,"ch:",ch,"pch:",_d,"top:",sc.top,"sy:",sy);
-if(b>_d||sc.top){
-_9("*bottom scroll*");
-ch=Math.max(b,_d+sc.top);
-sy=sc.top;
-_f+=this.canvas.getScrollWidth();
-}else{
-if(!sy&&ch>_d){
-_9("*bottom remove*");
-ch=_d;
-}
-}
-r*=z;
-if(r>_e||sc.left){
-cw=Math.max(r,_e+sc.left);
-sx=sc.left;
-_10+=this.canvas.getScrollWidth();
-}else{
-if(!sx&&cw>_e){
-cw=_e;
-}
-}
-cw+=_f*2;
-ch+=_10*2;
-this._blockScroll=true;
-this.stencils.group&&this.stencils.group.applyTransform({dx:dx,dy:dy});
-this.stencils.withUnselected(function(m){
-m.transformPoints({dx:dx,dy:dy});
-});
-this.canvas.setDimensions(cw,ch,sx,sy);
-}});
-dojox.drawing.ui.dom.Pan.setup={name:"dojox.drawing.ui.dom.Pan",tooltip:"Pan Tool",iconClass:"iconPan"};
-dojox.drawing.register(dojox.drawing.ui.dom.Pan.setup,"plugin");
-}
+
+dojox.drawing.register(dojox.drawing.ui.dom.Pan.setup, "plugin");
\ No newline at end of file
diff --git a/dojox/drawing/ui/dom/Toolbar.js b/dojox/drawing/ui/dom/Toolbar.js
index 211f0fe..7501c51 100644
--- a/dojox/drawing/ui/dom/Toolbar.js
+++ b/dojox/drawing/ui/dom/Toolbar.js
@@ -1,114 +1,207 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.ui.dom.Toolbar"]){
-dojo._hasResource["dojox.drawing.ui.dom.Toolbar"]=true;
 dojo.provide("dojox.drawing.ui.dom.Toolbar");
-dojo.deprecated("dojox.drawing.ui.dom.Toolbar","It may not even make it to the 1.4 release.",1.4);
+dojo.deprecated("dojox.drawing.ui.dom.Toolbar", "It may not even make it to the 1.4 release.", 1.4);
+
 (function(){
-dojo.declare("dojox.drawing.ui.dom.Toolbar",[],{baseClass:"drawingToolbar",buttonClass:"drawingButton",iconClass:"icon",constructor:function(_1,_2){
-dojo.addOnLoad(this,function(){
-this.domNode=dojo.byId(_2);
-dojo.addClass(this.domNode,this.baseClass);
-this.parse();
-});
-},createIcon:function(_3,_4){
-var _5=_4&&_4.setup?_4.setup:{};
-if(_5.iconClass){
-var _6=_5.iconClass?_5.iconClass:"iconNone";
-var _7=_5.tooltip?_5.tooltip:"Tool";
-var _8=dojo.create("div",{title:_7},_3);
-dojo.addClass(_8,this.iconClass);
-dojo.addClass(_8,_6);
-dojo.connect(_3,"mouseup",function(_9){
-dojo.stopEvent(_9);
-dojo.removeClass(_3,"active");
-});
-dojo.connect(_3,"mouseover",function(_a){
-dojo.stopEvent(_a);
-dojo.addClass(_3,"hover");
-});
-dojo.connect(_3,"mousedown",this,function(_b){
-dojo.stopEvent(_b);
-dojo.addClass(_3,"active");
-});
-dojo.connect(_3,"mouseout",this,function(_c){
-dojo.stopEvent(_c);
-dojo.removeClass(_3,"hover");
-});
-}
-},createTool:function(_d){
-_d.innerHTML="";
-var _e=dojo.attr(_d,"tool");
-this.toolNodes[_e]=_d;
-dojo.attr(_d,"tabIndex",1);
-var _f=dojo.getObject(_e);
-this.createIcon(_d,_f);
-this.drawing.registerTool(_e,_f);
-dojo.connect(_d,"mouseup",this,function(evt){
-dojo.stopEvent(evt);
-dojo.removeClass(_d,"active");
-this.onClick(_e);
-});
-dojo.connect(_d,"mouseover",function(evt){
-dojo.stopEvent(evt);
-dojo.addClass(_d,"hover");
-});
-dojo.connect(_d,"mousedown",this,function(evt){
-dojo.stopEvent(evt);
-dojo.addClass(_d,"active");
-});
-dojo.connect(_d,"mouseout",this,function(evt){
-dojo.stopEvent(evt);
-dojo.removeClass(_d,"hover");
-});
-},parse:function(){
-var _10=dojo.attr(this.domNode,"drawingId");
-this.drawing=dojox.drawing.util.common.byId(_10);
-!this.drawing&&console.error("Drawing not found based on 'drawingId' in Toolbar. ");
-this.toolNodes={};
-var _11;
-dojo.query(">",this.domNode).forEach(function(_12,i){
-_12.className=this.buttonClass;
-var _13=dojo.attr(_12,"tool");
-var _14=dojo.attr(_12,"action");
-var _15=dojo.attr(_12,"plugin");
-if(_13){
-if(i==0||dojo.attr(_12,"selected")=="true"){
-_11=_13;
-}
-this.createTool(_12);
-}else{
-if(_15){
-var p={name:_15,options:{}},opt=dojo.attr(_12,"options");
-if(opt){
-p.options=eval("("+opt+")");
-}
-p.options.node=_12;
-_12.innerHTML="";
-this.drawing.addPlugin(p);
-this.createIcon(_12,dojo.getObject(dojo.attr(_12,"plugin")));
-}
-}
-},this);
-this.drawing.initPlugins();
-dojo.connect(this.drawing,"setTool",this,"onSetTool");
-this.drawing.setTool(_11);
-},onClick:function(_16){
-this.drawing.setTool(_16);
-},onSetTool:function(_17){
-for(var n in this.toolNodes){
-if(n==_17){
-dojo.addClass(this.toolNodes[_17],"selected");
-this.toolNodes[_17].blur();
-}else{
-dojo.removeClass(this.toolNodes[n],"selected");
-}
-}
-}});
-})();
-}
+	
+	dojo.declare("dojox.drawing.ui.dom.Toolbar", [], {
+		// NOTE:
+		//			dojox.drawing.Toolbar is DEPRECATED.
+		//			The intention never was to use HTML as buttons for a Drawing.
+		//			This was implemented in order to finish the project for which
+		//			Drawing was developed.
+		//			Instead use: drawing/ui/Toolbar.js
+		//
+		// summary:
+		//	Creates a Toolbar to be used with a DojoX Drawing.
+		// description:
+		//	Currently works in markup only. A class is required with
+		//	either horizontal or vertical as a class (IE prevented using
+		//	either as a default). Assign an attribute of 'drawingId' with
+		//	the id of the DojoX Drawing to which this is assigned.
+		//	The node children will be assigned as the Tools in the toolbar.
+		//	Plugins can also be assigned.
+		//	The Toolbar is largely self contained and has no real public
+		//	methods or events. the Drawing object should be used.
+		//
+		// example:
+		//	|	<div dojoType="dojox.drawing.Toolbar" drawingId="drawing" class="drawingToolbar vertical">
+		//	|		<div tool="dojox.drawing.tools.Line" 				selected="false">	Line</div>
+		//	|		<div tool="dojox.drawing.tools.Rect" 				selected="true">	Rect</div>
+		//	|		<div plugin="dojox.drawing.plugins.tools.Zoom" options="{zoomInc:.1,minZoom:.5,maxZoom:2}">Zoom</div>
+		//	|	</div>
+		//
+		// TODO: Toolbar works in markup only. Need programmatic.
+		// NOTE: There are plans to make the toolbar out of dojox.gfx vectors.
+		//		 This may change the APIs in the future.
+		//
+		//	baseClass:String
+		//		The CSS style to apply to the toolbar node
+		baseClass:"drawingToolbar",
+		//	buttonClass:String
+		//		The CSS style to apply to each button node
+		buttonClass:"drawingButton",
+		//	iconClass:String
+		//		The CSS style to apply to each button icon node
+		iconClass:"icon",
+		//
+		constructor: function(props, node){
+			// props is null from markup
+			dojo.addOnLoad(this, function(){
+				this.domNode = dojo.byId(node);
+				dojo.addClass(this.domNode, this.baseClass);
+				this.parse();
+			});
+		},
+		
+		createIcon: function(/*HTMLNode*/node, /* ? Function*/constr){
+			// summary:
+			//	Internal. Creates an icon node for each button.
+			// arguments:
+			//	node: HTMLNode
+			//		The button node.
+			//	constr: [optional] Function
+			//		Optional. If not supplied, an icon is not created.
+			//		Information for each icon is derived from
+			//		the ToolsSetup object defined at the end
+			//		of each tool. See: stencil._Base
+			//
+			var setup = constr && constr.setup ? constr.setup : {};
+			if(setup.iconClass){
+				var icon = setup.iconClass ? setup.iconClass : "iconNone";
+				var tip = setup.tooltip ? setup.tooltip : "Tool";
+				
+				var iNode = dojo.create("div", {title:tip}, node);
+				dojo.addClass(iNode, this.iconClass);
+				dojo.addClass(iNode, icon);
+			
+				dojo.connect(node, "mouseup", function(evt){
+					dojo.stopEvent(evt);
+					dojo.removeClass(node, "active");
+				});
+				dojo.connect(node, "mouseover", function(evt){
+					dojo.stopEvent(evt);
+					dojo.addClass(node, "hover");
+				});
+				dojo.connect(node, "mousedown", this, function(evt){
+					dojo.stopEvent(evt);
+					dojo.addClass(node, "active");
+				});
+				
+				dojo.connect(node, "mouseout", this, function(evt){
+					dojo.stopEvent(evt);
+					dojo.removeClass(node, "hover");
+				});
+			}
+		},
+		
+		createTool: function(/*HTMLNode*/node){
+			// summary:
+			//	Creates a button on the Toolbar that is
+			//  a Tool, not a Plugin. Tools draw Stencils,
+			//	Plugins do actions.
+			// arguments:
+			//	node: HTMLNode
+			//		The button node.
+			//
+			node.innerHTML = "";
+			var type = dojo.attr(node, "tool");
+			this.toolNodes[type] = node;
+			dojo.attr(node, "tabIndex", 1);
+			var constr = dojo.getObject(type);
+			
+			this.createIcon(node, constr);	
+			
+			this.drawing.registerTool(type, constr);
+			dojo.connect(node, "mouseup", this, function(evt){
+				dojo.stopEvent(evt);
+				dojo.removeClass(node, "active");
+				this.onClick(type);
+			});
+			dojo.connect(node, "mouseover", function(evt){
+				dojo.stopEvent(evt);
+				dojo.addClass(node, "hover");
+			});
+			dojo.connect(node, "mousedown", this, function(evt){
+				dojo.stopEvent(evt);
+				dojo.addClass(node, "active");
+			});
+			
+			dojo.connect(node, "mouseout", this, function(evt){
+				dojo.stopEvent(evt);
+				dojo.removeClass(node, "hover");
+			});
+		},
+		
+		parse: function(){
+			// summary:
+			//	Initializing method that reads the dom node and its
+			//	children for tools and plugins.
+			//
+			var drawingId = dojo.attr(this.domNode, "drawingId");
+			this.drawing = dojox.drawing.util.common.byId(drawingId);
+			!this.drawing && console.error("Drawing not found based on 'drawingId' in Toolbar. ");
+			this.toolNodes = {};
+			var _sel;
+			dojo.query(">", this.domNode).forEach(function(node, i){
+				node.className = this.buttonClass;
+				var tool = dojo.attr(node, "tool");
+				var action = dojo.attr(node, "action");
+				var plugin = dojo.attr(node, "plugin");
+				if(tool){
+					if(i==0 || dojo.attr(node, "selected")=="true"){
+						_sel = tool;
+					}
+					this.createTool(node);
+					
+				}else if(plugin){
+					
+					
+					
+					
+					var p = {name:plugin, options:{}},
+						opt = dojo.attr(node, "options");
+					if(opt){
+						p.options = eval("("+opt+")");
+					}
+					p.options.node = node;
+					node.innerHTML = "";
+			this.drawing.addPlugin(p);
+					
+					
+					
+					
+					
+					this.createIcon(node, dojo.getObject(dojo.attr(node, "plugin")));
+				}
+				
+			}, this);
+			this.drawing.initPlugins();
+			dojo.connect(this.drawing, "setTool", this, "onSetTool");	
+			this.drawing.setTool(_sel);
+		},
+		onClick: function(/*String*/type){
+			// summary:
+			//	Event fired from clicking a Tool, not a PLugin.
+			//	Plugin clicks are handled within the plugin's class.
+			// arguments:
+			//	type: Fully qualified name of class. ex:
+			//			dojox.drawing.tools.Ellipse
+			//
+			this.drawing.setTool(type);
+		},
+		onSetTool: function(/*String*/type){
+			// summary:
+			// handles buttons clicks and selects or deselects
+			for(var n in this.toolNodes){
+				if(n == type){
+					dojo.addClass(this.toolNodes[type], "selected");
+					this.toolNodes[type].blur();
+				}else{
+					dojo.removeClass(this.toolNodes[n], "selected");
+				}
+				
+			}
+		}
+	});
+	
+})();
\ No newline at end of file
diff --git a/dojox/drawing/ui/dom/Zoom.js b/dojox/drawing/ui/dom/Zoom.js
index ac84345..1a64272 100644
--- a/dojox/drawing/ui/dom/Zoom.js
+++ b/dojox/drawing/ui/dom/Zoom.js
@@ -1,57 +1,129 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.ui.dom.Zoom"]){
-dojo._hasResource["dojox.drawing.ui.dom.Zoom"]=true;
 dojo.provide("dojox.drawing.ui.dom.Zoom");
 dojo.require("dojox.drawing.plugins._Plugin");
-dojox.drawing.ui.dom.Zoom=dojox.drawing.util.oo.declare(dojox.drawing.plugins._Plugin,function(_1){
-var _2=_1.node.className;
-var _3=_1.node.innerHTML;
-this.domNode=dojo.create("div",{id:"btnZoom","class":"toolCombo"},_1.node,"replace");
-this.makeButton("ZoomIn",this.topClass);
-this.makeButton("Zoom100",this.midClass);
-this.makeButton("ZoomOut",this.botClass);
-},{type:"dojox.drawing.ui.dom.Zoom",zoomInc:0.1,maxZoom:10,minZoom:0.1,zoomFactor:1,baseClass:"drawingButton",topClass:"toolComboTop",midClass:"toolComboMid",botClass:"toolComboBot",makeButton:function(_4,_5){
-var _6=dojo.create("div",{id:"btn"+_4,"class":this.baseClass+" "+_5,innerHTML:"<div title=\"Zoom In\" class=\"icon icon"+_4+"\"></div>"},this.domNode);
-dojo.connect(document,"mouseup",function(_7){
-dojo.stopEvent(_7);
-dojo.removeClass(_6,"active");
-});
-dojo.connect(_6,"mouseup",this,function(_8){
-dojo.stopEvent(_8);
-dojo.removeClass(_6,"active");
-this["on"+_4]();
-});
-dojo.connect(_6,"mouseover",function(_9){
-dojo.stopEvent(_9);
-dojo.addClass(_6,"hover");
-});
-dojo.connect(_6,"mousedown",this,function(_a){
-dojo.stopEvent(_a);
-dojo.addClass(_6,"active");
-});
-dojo.connect(_6,"mouseout",this,function(_b){
-dojo.stopEvent(_b);
-dojo.removeClass(_6,"hover");
-});
-},onZoomIn:function(_c){
-this.zoomFactor+=this.zoomInc;
-this.zoomFactor=Math.min(this.zoomFactor,this.maxZoom);
-this.canvas.setZoom(this.zoomFactor);
-this.mouse.setZoom(this.zoomFactor);
-},onZoom100:function(_d){
-this.zoomFactor=1;
-this.canvas.setZoom(this.zoomFactor);
-this.mouse.setZoom(this.zoomFactor);
-},onZoomOut:function(_e){
-this.zoomFactor-=this.zoomInc;
-this.zoomFactor=Math.max(this.zoomFactor,this.minZoom);
-this.canvas.setZoom(this.zoomFactor);
-this.mouse.setZoom(this.zoomFactor);
-}});
-}
+
+dojox.drawing.ui.dom.Zoom = dojox.drawing.util.oo.declare(
+	// NOTE:
+	//			dojox.drawing.ui.dom.Zoom is DEPRECATED.
+	//			This was a temporary DOM solution. Use the non-dom
+	//			tools for Toobar and Plugins.
+	//
+	// summary:
+	//		A plugin that allows for zooming the canvas in and out. An
+	//		action-tool is added to the toolbar with plus, minus and 100%
+	//		buttons.
+	// example:
+	//		|	<div dojoType="dojox.drawing.Toolbar" drawingId="drawingNode" class="drawingToolbar vertical">
+	//		|		<div tool="dojox.drawing.tools.Line" selected="true">Line</div>
+	//		|		<div plugin="dojox.drawing.ui.dom.Zoom" options="{zoomInc:.1,minZoom:.5,maxZoom:2}">Zoom</div>
+	//		|	</div>
+	//
+	dojox.drawing.plugins._Plugin,
+	function(options){
+		var cls = options.node.className;
+		var txt = options.node.innerHTML;
+		this.domNode = dojo.create("div", {id:"btnZoom", "class":"toolCombo"}, options.node, "replace");
+		
+		this.makeButton("ZoomIn", this.topClass);
+		this.makeButton("Zoom100", this.midClass);
+		this.makeButton("ZoomOut", this.botClass);
+		
+	},
+	{
+		type:"dojox.drawing.ui.dom.Zoom",
+		//
+		// 	zoomInc: Float
+		//		The amount of zoom that will occur upon each click.
+		zoomInc:.1,
+		//
+		//	maxZoom: Number
+		//		The maximum the canvas can be zoomed in. 10 = 1000%
+		maxZoom:10,
+		//
+		//	minZoom: Float
+		//		The most the canvas can be zoomed out. .1 = 10%
+		minZoom:.1,
+		//
+		//	zoomFactor: [readonly] Float
+		//		The current zoom amount
+		zoomFactor:1,
+		//
+		//	baseClass: String
+		//		The CSS class added to the Toolbar buttons
+		baseClass:"drawingButton",
+		//
+		//	topClass: String
+		//		The CSS class added to the top (or left) Toolbar button
+		topClass:"toolComboTop",
+		//
+		//	midClass: String
+		//		The CSS class added to the middle Toolbar button
+		midClass:"toolComboMid",
+		//
+		//	botClass: String
+		//		The CSS class added to the bottom (or right) Toolbar button
+		botClass:"toolComboBot",
+		//
+		makeButton: function(name, cls){
+			// summary:
+			//		Internal. Creates one of the buttons in the zoom-button set.
+			//
+			var node = dojo.create("div", {id:"btn"+name, "class":this.baseClass+" "+cls,
+				innerHTML:'<div title="Zoom In" class="icon icon'+name+'"></div>'}, this.domNode);
+			
+			dojo.connect(document, "mouseup", function(evt){
+				dojo.stopEvent(evt);
+				dojo.removeClass(node, "active");
+			});
+			dojo.connect(node, "mouseup", this, function(evt){
+				dojo.stopEvent(evt);
+				dojo.removeClass(node, "active");
+				this["on"+name](); // this is what calls the methods below
+			});
+			dojo.connect(node, "mouseover", function(evt){
+				dojo.stopEvent(evt);
+				dojo.addClass(node, "hover");
+			});
+			dojo.connect(node, "mousedown", this, function(evt){
+				dojo.stopEvent(evt);
+				dojo.addClass(node, "active");
+			});
+			
+			dojo.connect(node, "mouseout", this, function(evt){
+				dojo.stopEvent(evt);
+				dojo.removeClass(node, "hover");
+			});
+		
+		},
+		
+		onZoomIn: function(/*Mouse Event*/evt){
+			// summary:
+			//		Handles zoom in.
+			//
+			this.zoomFactor += this.zoomInc;
+			this.zoomFactor = Math.min(this.zoomFactor, this.maxZoom);
+			this.canvas.setZoom(this.zoomFactor);
+			this.mouse.setZoom(this.zoomFactor);
+		},
+		onZoom100: function(/*Mouse Event*/evt){
+			// summary:
+			//		Zooms to 100%
+			//
+			this.zoomFactor = 1;
+			this.canvas.setZoom(this.zoomFactor);
+			this.mouse.setZoom(this.zoomFactor);
+		},
+		onZoomOut: function(/*Mouse Event*/evt){
+			// summary:
+			//		Handles zoom out.
+			//
+			this.zoomFactor -= this.zoomInc;
+			this.zoomFactor = Math.max(this.zoomFactor, this.minZoom);
+			this.canvas.setZoom(this.zoomFactor);
+			this.mouse.setZoom(this.zoomFactor);
+		}
+	}
+);
+
+
+//dojox.drawing.register(dojox.drawing.plugins.tools.Pan, "plugin");
+
diff --git a/dojox/drawing/util/common.js b/dojox/drawing/util/common.js
old mode 100644
new mode 100755
index 7ad18f7..ff47ae5
--- a/dojox/drawing/util/common.js
+++ b/dojox/drawing/util/common.js
@@ -1,108 +1,280 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.drawing.util.common"]){
-dojo._hasResource["dojox.drawing.util.common"]=true;
 dojo.provide("dojox.drawing.util.common");
 dojo.require("dojox.math.round");
+
 (function(){
-var _1={};
-dojox.drawing.util.common={radToDeg:function(n){
-return (n*180)/Math.PI;
-},degToRad:function(n){
-return (n*Math.PI)/180;
-},angle:function(_2,_3){
-if(_3){
-_3=_3/180;
-var _4=this.radians(_2),_5=this.length(_2),_6=Math.PI*_3,_7=dojox.math.round(_4/_6),_8=_7*_6;
-return dojox.math.round(this.radToDeg(_8));
-}else{
-return this.radToDeg(this.radians(_2));
-}
-},radians:function(o){
-return Math.atan2(o.start.y-o.y,o.start.x-o.x);
-},length:function(o){
-return Math.sqrt(Math.pow(o.start.x-o.x,2)+Math.pow(o.start.y-o.y,2));
-},lineSub:function(x1,y1,x2,y2,_9){
-var _a=this.distance(this.argsToObj.apply(this,arguments));
-_a=_a<_9?_9:_a;
-var pc=(_a-_9)/_a;
-var x=x1-(x1-x2)*pc;
-var y=y1-(y1-y2)*pc;
-return {x:x,y:y};
-},argsToObj:function(){
-var a=arguments;
-if(a.length<4){
-return a[0];
-}
-return {start:{x:a[0],y:a[1]},x:a[2],y:a[3]};
-},distance:function(){
-var o=this.argsToObj.apply(this,arguments);
-return Math.abs(Math.sqrt(Math.pow(o.start.x-o.x,2)+Math.pow(o.start.y-o.y,2)));
-},slope:function(p1,p2){
-if(!(p1.x-p2.x)){
-return 0;
-}
-return ((p1.y-p2.y)/(p1.x-p2.x));
-},pointOnCircle:function(cx,cy,_b,_c){
-radians=_c*Math.PI/180;
-var x=_b*Math.cos(radians)*-1;
-var y=_b*Math.sin(radians)*-1;
-return {x:cx+x,y:cy+y};
-},constrainAngle:function(_d,_e,_f){
-var _10=this.angle(_d);
-if(_10>=_e&&_10<=_f){
-return _d;
-}
-var _11=this.length(_d);
-var _12=_e-((360-(_f-_e))/2);
-var _13=_10>_f?_f:_e-_10<100?_e:_f;
-return this.pointOnCircle(_d.start.x,_d.start.y,_11,_13);
-},snapAngle:function(obj,ca){
-var _14=this.radians(obj),_15=this.angle(obj),_16=this.length(obj),seg=Math.PI*ca,rnd=Math.round(_14/seg),_17=rnd*seg,_18=this.radToDeg(_17),pt=this.pointOnCircle(obj.start.x,obj.start.y,_16,_18);
-return pt;
-},uid:function(str){
-str=str||"shape";
-_1[str]=_1[str]===undefined?0:_1[str]+1;
-return str+_1[str];
-},abbr:function(_19){
-return _19.substring(_19.lastIndexOf(".")+1).charAt(0).toLowerCase()+_19.substring(_19.lastIndexOf(".")+2);
-},mixin:function(o1,o2){
-},objects:{},register:function(obj){
-this.objects[obj.id]=obj;
-},byId:function(id){
-return this.objects[id];
-},attr:function(_1a,_1b,_1c,_1d){
-if(!_1a){
-return false;
-}
-try{
-if(_1a.shape&&_1a.util){
-_1a=_1a.shape;
-}
-if(!_1c&&_1b=="id"&&_1a.target){
-var n=_1a.target;
-while(!dojo.attr(n,"id")){
-n=n.parentNode;
-}
-return dojo.attr(n,"id");
-}
-if(_1a.rawNode||_1a.target){
-var _1e=Array.prototype.slice.call(arguments);
-_1e[0]=_1a.rawNode||_1a.target;
-return dojo.attr.apply(dojo,_1e);
-}
-return dojo.attr(_1a,"id");
-}
-catch(e){
-if(!_1d){
-}
-return false;
-}
-}};
-})();
-}
+	
+	var uidMap = {};
+	var start = 0;
+	dojox.drawing.util.common	= {
+		// summary:
+		//		A collection of common methods used for DojoX Drawing.
+		//		This singleton is accessible in most Drawing classes
+		//		as this.util
+		//
+		// NOTE:
+		//		A lot of functions use a EventObject
+		//		as an argument. An attempt was made to accept
+		//		either that object or a list of numbers. That wasn't
+		//		finished (it didn't work well in all cases) but is
+		//		likely to happen in the future.
+		//		In cases where you are not sending a Mouse object,
+		//		form your argument like so:
+		//		var obj = {
+		//			start:{
+		//					x:Number,  	// start x
+		//					y:Number	// start y
+		//				},
+		//				x: Number,		// end x
+		//				y:Number		// end y
+		//			}
+		//
+		//
+		radToDeg: function(/*Numer*/n){
+			// summary:
+			//		Convert the passed number to degrees.
+			return (n*180)/Math.PI;	//	Number
+		},
+		
+		degToRad: function(/*Numer*/n){
+			// summary:
+			//		Convert the passed number to radians.
+			return (n*Math.PI)/180;	// Number
+		},
+		
+		angle: function(/*EventObject*/obj, /* ? Float */snap){
+			// summary:
+			//		Return angle based on mouse object
+			// arguments:
+			//		obj: EventObject
+			//			Manager.Mouse event.
+			// 		snap: Float 
+			//			Returns nearest angle within snap limits
+			//
+			//obj = this.argsToObj.apply(this, arguments);
+			if(snap){
+				snap = snap/180;
+				var radians = this.radians(obj),
+					seg = Math.PI * snap,
+					rnd = dojox.math.round(radians/seg),
+					new_radian = rnd*seg;
+				return dojox.math.round(this.radToDeg(new_radian)); // Whole Number
+			
+			}else{
+				return this.radToDeg(this.radians(obj)); // Float
+			}
+		},
+		
+		oppAngle: function(/*Angle*/ang){
+			(ang+=180) > 360 ? ang = ang - 360 : ang;
+			return ang;
+		},
+		
+		radians: function(/*EventObject*/o){
+			// summary:
+			//		Return the radians derived from the coordinates
+			//		in the Mouse object.
+			//
+			//var o = this.argsToObj.apply(this, arguments);
+			return Math.atan2(o.start.y-o.y,o.x-o.start.x);
+		},
+		
+		length: function(/*EventObject*/o){
+			// summary:
+			//		Return the length derived from the coordinates
+			//		in the Mouse object.
+			//
+			return Math.sqrt(Math.pow(o.start.x-o.x, 2)+Math.pow(o.start.y-o.y, 2));
+		},
+		
+		lineSub: function(/*Number*/x1, /*Number*/y1, /*Number*/x2, /*Number*/y2, /*Number*/amt){
+			// summary:
+			//		Subtract an amount from a line
+			// description:
+			//		x1,y1,x2,y2 represents the Line. 'amt' represents the amount
+			//		to subtract from it.
+			//
+			var len = this.distance(this.argsToObj.apply(this, arguments));
+			len = len < amt ? amt : len;
+			var pc = (len-amt)/len;
+			var x = x1 - (x1-x2) * pc;
+			var y = y1 - (y1-y2) * pc;
+			return {x:x, y:y}; // Object
+		},
+		
+		argsToObj: function(){
+			// summary:
+			//		Attempts to determine in a Mouse Object
+			//		was passed or indiviual numbers. Returns
+			//		an object.
+			//
+			var a = arguments;
+			if(a.length < 4){ return a[0]; }
+			return {
+				start:{
+					x:a[0],
+					y:a[1]
+				},
+				x:a[2],
+				y:a[3]//,
+				//snap:a[4]
+			}; // Object
+		},
+		
+		distance: function(/*EventObject or x1,y1,x2,y2*/){
+			// summary:
+			//		Return the length derived from the coordinates
+			//		in the Mouse object. Different from util.length
+			//		in that this always returns an absolute value.
+			//
+			var o = this.argsToObj.apply(this, arguments);
+			return Math.abs(Math.sqrt(Math.pow(o.start.x-o.x, 2)+Math.pow(o.start.y-o.y, 2))); // Number
+		},
+		
+		slope:function(/*Object*/p1, /*Object*/p2){
+			// summary:
+			//		Given two poits of a line, returns the slope.
+			if(!(p1.x-p2.x)){ return 0; }
+			return ((p1.y-p2.y)/(p1.x-p2.x)); // Number
+		},
+		
+		pointOnCircle: function(/*Number*/cx, /*Number*/cy, /*Number*/radius, /*Number*/angle){
+			// summary:
+			//		A *very* helpful method. If you know the center
+			//		(or starting) point, length and angle, find the
+			//		x,y point at the end of that line.
+			//
+			var radians =  angle * Math.PI / 180.0;
+			var x = radius * Math.cos(radians);
+			var y = radius * Math.sin(radians);
+			return {
+				x:cx+x,
+				y:cy-y
+			}; // Object
+		},
+		
+		constrainAngle: function(/*EventObject*/obj, /*Number*/min, /*Number*/max){
+			// summary:
+			//		Ensures the angle in the Mouse Object is within the
+			//		min and max limits. If not one of those limits is used.
+			//		Returns an x,y point for the angle used.
+			//
+			var angle = this.angle(obj);
+			if(angle >= min && angle <= max){
+				return obj;	 // Object
+			}
+			var radius = this.length(obj);
+			var new_angle = angle > max ? max : min - angle < 100 ? min : max;
+			return this.pointOnCircle(obj.start.x,obj.start.y,radius, new_angle); // Object
+		},
+		
+		snapAngle: function(/*EventObject*/obj, /*Float*/ca){
+			// summary:
+			//		Snaps a line to the nearest angle
+			//			obj: Mouse object (see dojox.drawing.Mouse)
+			//			ca: Fractional amount to snap to
+			//				A decimal number fraction of a half circle
+			//				.5 would snap to 90 degrees
+			//				.25  would snap to 45 degrees
+			//				.125 would snap to 22.5 degrees, etc.
+			//
+			var radians = this.radians(obj),
+				radius = this.length(obj),
+				seg = Math.PI * ca,
+				rnd = Math.round(radians/seg),
+				new_radian = rnd*seg,
+				new_angle = this.radToDeg(new_radian),
+				pt = this.pointOnCircle(obj.start.x,obj.start.y,radius,new_angle);
+			return pt;  // Object
+		},
+		
+		// helpers
+		idSetStart: function(num){
+			start=num;
+		},
+		
+		uid: function(/* ? String */str){
+			// summary:
+			//		Creates a unique ID.
+			// arguments:
+			//		str: String
+			//			If provided, kept in a map, incremented
+			//			and used in the id. Otherwise 'shape' is used.
+			//
+			str = str || "shape";
+			uidMap[str] = uidMap[str]===undefined ? start : uidMap[str] + 1;
+			return str + uidMap[str]; // String
+		},
+		
+		abbr: function(type){
+			// summary:
+			//		Converts a namespace (typically a tool or a stencil) into
+			//		an abbreviation
+			return type.substring(type.lastIndexOf(".")+1).charAt(0).toLowerCase()
+				+ type.substring(type.lastIndexOf(".")+2);
+		},
+		mixin: function(o1, o2){
+			// TODO: make faster
+			//return dojo.mixin(dojo.clone(o1), dojo.clone(o2));	
+		},
+		
+		objects:{}, //private?
+		register: function(/*Object*/obj){
+			// summary:
+			//		Since util is the only Singleton in Drawing (besides
+			//		keys) it is used to help connect the Drawing object
+			//		the Toolbar. Since multiple drawings can be on one
+			//		page, this function serves a little more use than
+			//		on first apearance.
+			this.objects[obj.id] = obj;	
+		},
+		byId: function(/*String*/id){
+			// summary:
+			//		Get an object that was registered with util.register
+			//
+			return this.objects[id];
+		},
+		attr: function(/* Object */ elem, /* property */ prop, /* ? value */ value, squelchErrors){
+			// summary:
+			//		Helper function to attach attributes to SVG and VML raw nodes.
+			//
+			
+			if(!elem){ return false; }
+			try{
+				
+				// util is a crappy check, but we need to tell the diff
+				// between a Drawing shape and a GFX shape
+				if(elem.shape && elem.util){
+					elem = elem.shape;
+				}
+				
+				if(!value && prop=="id" && elem.target){
+			
+					var n = elem.target;
+					while(!dojo.attr(n, "id")){
+						n = n.parentNode;
+					}
+					return dojo.attr(n, "id");
+				}
+				
+				if(elem.rawNode || elem.target){
+					var args = Array.prototype.slice.call(arguments);
+					args[0] = elem.rawNode || elem.target;
+					return dojo.attr.apply(dojo, args);	
+				}		
+				return dojo.attr(elem, "id");
+				
+				
+				
+			}catch(e){
+				if(!squelchErrors){
+					// For debugging only. These errors actually cause errors in IE's console
+					//console.error("BAD ATTR: prop:", prop, "el:", elem)
+					//console.error(e)
+					//console.trace();
+				}
+				return false;
+			}
+		}
+	};
+	
+})();
\ No newline at end of file
diff --git a/dojox/drawing/util/oo.js b/dojox/drawing/util/oo.js
old mode 100644
new mode 100755
index b8e040a..db416dc
--- a/dojox/drawing/util/oo.js
+++ b/dojox/drawing/util/oo.js
@@ -1,54 +1,122 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.util.oo");
 
+// TODO:
+// allow a declare without a mixin
 
-if(!dojo._hasResource["dojox.drawing.util.oo"]){
-dojo._hasResource["dojox.drawing.util.oo"]=true;
-dojo.provide("dojox.drawing.util.oo");
-dojox.drawing.util.oo={declare:function(){
-var f,o,_1=0,a=arguments;
-if(a.length<2){
-console.error("gfx.oo.declare; not enough arguments");
-}
-if(a.length==2){
-f=a[0];
-o=a[1];
-}else{
-a=Array.prototype.slice.call(arguments);
-o=a.pop();
-f=a.pop();
-_1=1;
-}
-for(var n in o){
-f.prototype[n]=o[n];
-}
-if(_1){
-a.unshift(f);
-f=this.extend.apply(this,a);
-}
-return f;
-},extend:function(){
-var a=arguments,_2=a[0];
-if(a.length<2){
-console.error("gfx.oo.extend; not enough arguments");
-}
-var f=function(){
-for(var i=1;i<a.length;i++){
-a[i].prototype.constructor.apply(this,arguments);
-}
-_2.prototype.constructor.apply(this,arguments);
-};
-for(var i=1;i<a.length;i++){
-for(var n in a[i].prototype){
-f.prototype[n]=a[i].prototype[n];
-}
-}
-for(var n in _2.prototype){
-f.prototype[n]=_2.prototype[n];
-}
-return f;
-}};
-}
+dojox.drawing.util.oo = {
+	// summary:
+	//		Inheritance utilities used in DojoX Drawing
+	// description:
+	//		Inheritance utilities used in DojoX Drawing.
+	//		There were designed in a effort to make Drawing as
+	//		fast as possible - especially in a case where thousands
+	//		of objects are being loaded. Drawing declare performs
+	//		about 3 times faster than Dojo declare and 2 times
+	//		faster than Dojox declare. This is not to say Drawing
+	//		declare is wthout limitations. It doesn't have the same
+	//		syntatic sugar and extensibility of the other two. You
+	//		can't inhert methods. It won't work with Dijit. But it
+	//		is simple and effective.
+	//
+	declare: function(){
+		// summary:
+		//		Creates a constructor Function from a
+		//		Function, and collection of methods, and
+		//		more Functions that are extended.
+		// description:
+		//		Similar in look and feel to Dojo declare as
+		//		far as order and number of arguments, although
+		//		constructed a little closer to prototypical
+		//		inheritance. All arguments passed into the
+		//		constructor are passed into all sub constructors.
+		// arguments:
+		//		Function, [Object|Function....]
+		//			The first argument is always the base
+		//			constructor. The last argument is always
+		//			an object of methods (or empty object) to
+		//			be mixed in (in the future would like to
+		//			make that object optional). Remaining
+		//			arguments are other constructors mixed in
+		//			using extend() (See below).
+		// example:
+		//		|	MyFunction = dojox.drawing.util.oo.declare(
+		//		|		MyOtherFunction,
+		//		|		YetAnotherFunction,
+		//		|		function(options){
+		//		|			// This is my constructor. It will fire last.
+		//		|			// The other constructors will fire before this.
+		//		|		},
+		//		|		{
+		//		|			customType:"equation", // mixed in property
+		//		|			doThing: function(){   // mixed in method
+		//		|					
+		//		|			}
+		//		|		}	
+		//		|	);
+		//		|
+		//		|	var f = new MyFunction();
+		//
+		var f, o, ext=0, a = arguments;
+				
+		if(a.length<2){ console.error("gfx.oo.declare; not enough arguments")}
+		if(a.length==2){
+			f = a[0]; o = a[1];
+		}else{
+			a = Array.prototype.slice.call(arguments);
+			o = a.pop();
+			f = a.pop();
+			ext = 1;
+		}
+		for(var n in o){
+			f.prototype[n] = o[n];
+		}
+		if(ext){
+			a.unshift(f);
+			f = this.extend.apply(this, a);
+		}
+		return f; // Function
+	},
+	extend: function(){
+		// summary:
+		//		Extends constructors to inherit from other
+		//		constructors .
+		// description:
+		//		Typically not used by itself - it's used as
+		//		part of declare(). Could be used by itself
+		//		however, to mix together two or more
+		//		constructors.
+		// arguments:
+		//		Function, [ Function...]
+		//			Any number of arguments, all must be
+		//			function constructors. The first is
+		//			considered the base object and its
+		//			constructor will fire first.
+		// example:
+		//		|	var A = function(){};
+		//		|	var B = function(){};
+		//		|	var C = function(){};
+		// 		|	var D = dojox.drawing.util.oo.extend(A, B, C);
+		//		|	var e = new D();
+		//
+		var a = arguments, sub = a[0];
+		if(a.length<2){ console.error("gfx.oo.extend; not enough arguments")}
+		var f = function (){
+			for(var i=1;i<a.length;i++){
+				a[i].prototype.constructor.apply(this, arguments);
+			}
+			// sub should fire last
+			sub.prototype.constructor.apply(this, arguments);
+			
+		}
+		for(var i=1;i<a.length;i++){
+			for(var n in a[i].prototype){
+				f.prototype[n] = a[i].prototype[n];
+			}
+		}
+			
+		for(n in sub.prototype){
+			f.prototype[n] = sub.prototype[n];
+		}
+		return f; // Function
+	}
+};
\ No newline at end of file
diff --git a/dojox/drawing/util/positioning.js b/dojox/drawing/util/positioning.js
old mode 100644
new mode 100755
index 5644e0e..677555a
--- a/dojox/drawing/util/positioning.js
+++ b/dojox/drawing/util/positioning.js
@@ -1,45 +1,65 @@
-/*
-	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
-*/
+dojo.provide("dojox.drawing.util.positioning");	
 
-
-if(!dojo._hasResource["dojox.drawing.util.positioning"]){
-dojo._hasResource["dojox.drawing.util.positioning"]=true;
-dojo.provide("dojox.drawing.util.positioning");
 (function(){
-var _1=4;
-var _2=20;
-dojox.drawing.util.positioning.label=function(_3,_4){
-var x=0.5*(_3.x+_4.x);
-var y=0.5*(_3.y+_4.y);
-var _5=dojox.drawing.util.common.slope(_3,_4);
-var _6=_1/Math.sqrt(1+_5*_5);
-if(_4.y>_3.y){
-_6=-_6;
-}
-x+=-_6*_5;
-y+=_6;
-var _7=_4.x<_3.x?"end":"start";
-if(_4.y>_3.y){
-y-=_2;
-}
-return {x:x,y:y,foo:"bar",align:_7};
-};
-dojox.drawing.util.positioning.angle=function(_8,_9){
-var x=0.7*_8.x+0.3*_9.x;
-var y=0.7*_8.y+0.3*_9.y;
-var _a=dojox.drawing.util.common.slope(_8,_9);
-var _b=_1/Math.sqrt(1+_a*_a);
-if(_9.x<_8.x){
-_b=-_b;
-}
-x+=-_b*_a;
-y+=_b;
-var _c=_9.y>_8.y?"end":"start";
-y+=_9.x>_8.x?0.5*_2:-0.5*_2;
-return {x:x,y:y,align:_c};
-};
+	
+	var textOffset = 4;  // distance from line to text box
+	var textYOffset = 20;  // height of text box
+	
+	
+	dojox.drawing.util.positioning.label = function(/*Object*/start, /*Object*/end){
+		// summary:
+		//		Returns the optimal position for annotations.Label.
+		//
+		// 	text position
+		// label at middle of vector
+		var x = 0.5*(start.x+end.x);
+		var y = 0.5*(start.y+end.y);
+		
+		// move label a set distance from the line
+		var slope = dojox.drawing.util.common.slope(start, end);
+		
+		var deltay = textOffset/Math.sqrt(1.0+slope*slope);
+		if(end.y>start.y){deltay = -deltay;}
+		x += -deltay*slope;
+		y += deltay;
+		
+		// want text to be away from start of vector
+		// This will make force diagrams less crowded
+		var align = end.x<start.x ? "end" : "start";
+		
+	        // box vertical aligned from top
+		if(end.y>start.y){
+			y -= textYOffset;
+		}
+		
+		return { x:x, y:y, foo:"bar", align:align}; // Object
+	};
+	
+	dojox.drawing.util.positioning.angle = function(/*Object*/start, /*Object*/end){
+		// summary:
+		//		Returns the optimal position for annotations.Angle.
+		//
+		// angle at first third of vector
+	        var x = 0.7*start.x+0.3*end.x;
+	        var y = 0.7*start.y+0.3*end.y;
+		// move label a set distance from the line
+		var slope = dojox.drawing.util.common.slope(start, end);
+		var deltay = textOffset/Math.sqrt(1.0+slope*slope);
+		
+		if(end.x<start.x){deltay = -deltay;}
+		x += -deltay * slope;
+		y += deltay;
+		
+		// want text to be clockwise from vector
+		// to match angle measurement from x-axis
+		var align = end.y>start.y ? "end" : "start";
+	        // box vertical aligned from middle
+	        y += end.x > start.x ? 0.5*textYOffset :  -0.5*textYOffset;
+		
+		return { x:x, y:y, align:align}; // Object
+	}
+	
 })();
-}
+
+
+
diff --git a/dojox/dtl.js b/dojox/dtl.js
index 7c24824..6c6fe85 100644
--- a/dojox/dtl.js
+++ b/dojox/dtl.js
@@ -1,16 +1,2 @@
-/*
-	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["dojox.string.Builder"]){dojo._hasResource["dojox.string.Builder"]=true;dojo.provide("dojox.string.Builder");dojox.string.Builder=function(_1){var b="";this.length=0;this.append=function(s){if(arguments.length>1){var _2="",l=arguments.length;switch(l){case 9:_2=""+arguments[8]+_2;case 8:_2=""+arguments[7]+_2;case 7:_2=""+arguments[6]+_2;case 6:_2=""+arguments[5]+_2;case 5:_2=""+arguments[4]+_2;case 4:_2=""+arguments[3]+_2;case 3:_2=""+arguments[2]+_2;case 2:b+=""+ar [...]
+dojo.provide("dojox.dtl");
+dojo.require("dojox.dtl._base");
\ No newline at end of file
diff --git a/dojox/dtl.js.uncompressed.js b/dojox/dtl.js.uncompressed.js
deleted file mode 100644
index 21460f2..0000000
--- a/dojox/dtl.js.uncompressed.js
+++ /dev/null
@@ -1,2855 +0,0 @@
-/*
-	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["dojox.string.Builder"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.string.Builder"] = true;
-dojo.provide("dojox.string.Builder");
-
-dojox.string.Builder = function(/*String?*/str){
-	//	summary:
-	//		A fast buffer for creating large strings.
-	//
-	//	length: Number
-	//		The current length of the internal string.
-
-	//	N.B. the public nature of the internal buffer is no longer
-	//	needed because the IE-specific fork is no longer needed--TRT.
-	var b = "";
-	this.length = 0;
-	
-	this.append = function(/* String... */s){ 
-		// summary: Append all arguments to the end of the buffer 
-		if(arguments.length>1){
-			/*  
-				This is a loop unroll was designed specifically for Firefox;
-				it would seem that static index access on an Arguments
-				object is a LOT faster than doing dynamic index access.
-				Therefore, we create a buffer string and take advantage
-				of JS's switch fallthrough.  The peformance of this method
-				comes very close to straight up string concatenation (+=).
-
-				If the arguments object length is greater than 9, we fall
-				back to standard dynamic access.
-
-				This optimization seems to have no real effect on either
-				Safari or Opera, so we just use it for all.
-
-				It turns out also that this loop unroll can increase performance
-				significantly with Internet Explorer, particularly when 
-				as many arguments are provided as possible.
-
-				Loop unroll per suggestion from Kris Zyp, implemented by 
-				Tom Trenka.
-
-				Note: added empty string to force a string cast if needed.
-			 */
-			var tmp="", l=arguments.length;
-			switch(l){
-				case 9: tmp=""+arguments[8]+tmp;
-				case 8: tmp=""+arguments[7]+tmp;
-				case 7: tmp=""+arguments[6]+tmp;
-				case 6: tmp=""+arguments[5]+tmp;
-				case 5: tmp=""+arguments[4]+tmp;
-				case 4: tmp=""+arguments[3]+tmp;
-				case 3: tmp=""+arguments[2]+tmp;
-				case 2: {
-					b+=""+arguments[0]+arguments[1]+tmp;
-					break;
-				}
-				default: {
-					var i=0;
-					while(i<arguments.length){
-						tmp += arguments[i++];
-					}
-					b += tmp;
-				}
-			}
-		} else {
-			b += s;
-		}
-		this.length = b.length;
-		return this;	//	dojox.string.Builder
-	};
-	
-	this.concat = function(/*String...*/s){
-		//	summary:
-		//		Alias for append.
-		return this.append.apply(this, arguments);	//	dojox.string.Builder
-	};
-	
-	this.appendArray = function(/*Array*/strings) {
-		//	summary:
-		//		Append an array of items to the internal buffer.
-
-		//	Changed from String.prototype.concat.apply because of IE.
-		return this.append.apply(this, strings);	//	dojox.string.Builder
-	};
-	
-	this.clear = function(){
-		//	summary: 
-		//		Remove all characters from the buffer.
-		b = "";
-		this.length = 0;
-		return this;	//	dojox.string.Builder
-	};
-	
-	this.replace = function(/* String */oldStr, /* String */ newStr){
-		// 	summary: 
-		//		Replace instances of one string with another in the buffer.
-		b = b.replace(oldStr,newStr);
-		this.length = b.length;
-		return this;	//	dojox.string.Builder
-	};
-	
-	this.remove = function(/* Number */start, /* Number? */len){
-		//	summary:
-		//		Remove len characters starting at index start.  If len
-		//		is not provided, the end of the string is assumed.
-		if(len===undefined){ len = b.length; }
-		if(len == 0){ return this; }
-		b = b.substr(0, start) + b.substr(start+len);
-		this.length = b.length;
-		return this;	//	dojox.string.Builder
-	};
-	
-	this.insert = function(/* Number */index, /* String */str){
-		//	summary: 
-		//		Insert string str starting at index.
-		if(index == 0){
-			b = str + b;
-		}else{
-			b = b.slice(0, index) + str + b.slice(index);
-		}
-		this.length = b.length;
-		return this;	//	dojox.string.Builder
-	};
-	
-	this.toString = function(){
-		//	summary:
-		//		Return the string representation of the internal buffer.
-		return b;	//	String
-	};
-
-	//	initialize the buffer.
-	if(str){ this.append(str); }
-};
-
-}
-
-if(!dojo._hasResource["dojox.string.tokenize"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.string.tokenize"] = true;
-dojo.provide("dojox.string.tokenize");
-
-dojox.string.tokenize = function(/*String*/ str, /*RegExp*/ re, /*Function?*/ parseDelim, /*Object?*/ instance){
-	// summary:
-	//		Split a string by a regular expression with the ability to capture the delimeters
-	// parseDelim:
-	//		Each group (excluding the 0 group) is passed as a parameter. If the function returns
-	//		a value, it's added to the list of tokens.
-	// instance:
-	//		Used as the "this" instance when calling parseDelim
-	var tokens = [];
-	var match, content, lastIndex = 0;
-	while(match = re.exec(str)){
-		content = str.slice(lastIndex, re.lastIndex - match[0].length);
-		if(content.length){
-			tokens.push(content);
-		}
-		if(parseDelim){
-			if(dojo.isOpera){
-				var copy = match.slice(0);
-				while(copy.length < match.length){
-					copy.push(null);
-				}
-				match = copy;
-			}
-			var parsed = parseDelim.apply(instance, match.slice(1).concat(tokens.length));
-			if(typeof parsed != "undefined"){
-				tokens.push(parsed);
-			}
-		}
-		lastIndex = re.lastIndex;
-	}
-	content = str.slice(lastIndex);
-	if(content.length){
-		tokens.push(content);
-	}
-	return tokens;
-}
-
-}
-
-if(!dojo._hasResource["dojox.dtl._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.dtl._base"] = true;
-dojo.provide("dojox.dtl._base");
-
-
-
-
-dojo.experimental("dojox.dtl");
-
-(function(){
-	var dd = dojox.dtl;
-
-	dd.TOKEN_BLOCK = -1;
-	dd.TOKEN_VAR = -2;
-	dd.TOKEN_COMMENT = -3;
-	dd.TOKEN_TEXT = 3;
-
-	dd._Context = dojo.extend(function(dict){
-		// summary: Pass one of these when rendering a template to tell the template what values to use.
-		dojo._mixin(this, dict || {});
-		this._dicts = [];
-	},
-	{
-		push: function(){
-			var last = this;
-			var context = dojo.delegate(this);
-			context.pop = function(){ return last; }
-			return context;
-		},
-		pop: function(){
-			throw new Error("pop() called on empty Context");
-		},
-		get: function(key, otherwise){
-			if(typeof this[key] != "undefined"){
-				return this._normalize(this[key]);
-			}
-
-			for(var i = 0, dict; dict = this._dicts[i]; i++){
-				if(typeof dict[key] != "undefined"){
-					return this._normalize(dict[key]);
-				}
-			}
-
-			return otherwise;
-		},
-		_normalize: function(value){
-			if(value instanceof Date){
-				value.year = value.getFullYear();
-				value.month = value.getMonth() + 1;
-				value.day = value.getDate();
-				value.date = value.year + "-" + ("0" + value.month).slice(-2) + "-" + ("0" + value.day).slice(-2);
-				value.hour = value.getHours();
-				value.minute = value.getMinutes();
-				value.second = value.getSeconds();
-				value.microsecond = value.getMilliseconds();
-			}
-			return value;
-		},
-		update: function(dict){
-			var context = this.push();
-			if(dict){
-				dojo._mixin(this, dict);
-			}
-			return context;
-		}
-	});
-
-	var smart_split_re = /("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+)/g;           
-	var split_re = /\s+/g;
-	var split = function(/*String|RegExp?*/ splitter, /*Integer?*/ limit){
-		splitter = splitter || split_re;
-		if(!(splitter instanceof RegExp)){
-			splitter = new RegExp(splitter, "g");
-		}
-		if(!splitter.global){
-			throw new Error("You must use a globally flagged RegExp with split " + splitter);
-		}
-		splitter.exec(""); // Reset the global
-
-		var part, parts = [], lastIndex = 0, i = 0;
-		while(part = splitter.exec(this)){
-			parts.push(this.slice(lastIndex, splitter.lastIndex - part[0].length));
-			lastIndex = splitter.lastIndex;
-			if(limit && (++i > limit - 1)){
-				break;
-			}
-		}
-		parts.push(this.slice(lastIndex));
-		return parts;
-	}
-
-	dd.Token = function(token_type, contents){
-		this.token_type = token_type;
-		this.contents = new String(dojo.trim(contents));
-		this.contents.split = split;
-		this.split = function(){
-			return String.prototype.split.apply(this.contents, arguments);
-		}
-	}
-	dd.Token.prototype.split_contents = function(/*Integer?*/ limit){
-		var bit, bits = [], i = 0;
-		limit = limit || 999;
-		while(i++ < limit && (bit = smart_split_re.exec(this.contents))){
-			bit = bit[0];
-			if(bit.charAt(0) == '"' && bit.slice(-1) == '"'){
-				bits.push('"' + bit.slice(1, -1).replace('\\"', '"').replace('\\\\', '\\') + '"');
-			}else if(bit.charAt(0) == "'" && bit.slice(-1) == "'"){
-				bits.push("'" + bit.slice(1, -1).replace("\\'", "'").replace('\\\\', '\\') + "'");
-			}else{
-				bits.push(bit);
-			}
-		}
-		return bits;
-	}
-
-	var ddt = dd.text = {
-		_get: function(module, name, errorless){
-			// summary: Used to find both tags and filters
-			var params = dd.register.get(module, name.toLowerCase(), errorless);
-			if(!params){
-				if(!errorless){
-					throw new Error("No tag found for " + name);
-				}
-				return null;
-			}
-
-			var fn = params[1];
-			var require = params[2];
-
-			var parts;
-			if(fn.indexOf(":") != -1){
-				parts = fn.split(":");
-				fn = parts.pop();
-			}
-
-			dojo["require"](require);
-
-			var parent = dojo.getObject(require);
-
-			return parent[fn || name] || parent[name + "_"] || parent[fn + "_"];
-		},
-		getTag: function(name, errorless){
-			return ddt._get("tag", name, errorless);
-		},
-		getFilter: function(name, errorless){
-			return ddt._get("filter", name, errorless);
-		},
-		getTemplate: function(file){
-			return new dd.Template(ddt.getTemplateString(file));
-		},
-		getTemplateString: function(file){
-			return dojo._getText(file.toString()) || "";
-		},
-		_resolveLazy: function(location, sync, json){
-			if(sync){
-				if(json){
-					return dojo.fromJson(dojo._getText(location)) || {};
-				}else{
-					return dd.text.getTemplateString(location);
-				}
-			}else{
-				return dojo.xhrGet({
-					handleAs: (json) ? "json" : "text",
-					url: location
-				});
-			}
-		},
-		_resolveTemplateArg: function(arg, sync){
-			if(ddt._isTemplate(arg)){
-				if(!sync){
-					var d = new dojo.Deferred();
-					d.callback(arg);
-					return d;
-				}
-				return arg;
-			}
-			return ddt._resolveLazy(arg, sync);
-		},
-		_isTemplate: function(arg){
-			return (typeof arg == "undefined") || (typeof arg == "string" && (arg.match(/^\s*[<{]/) || arg.indexOf(" ") != -1));
-		},
-		_resolveContextArg: function(arg, sync){
-			if(arg.constructor == Object){
-				if(!sync){
-					var d = new dojo.Deferred;
-					d.callback(arg);
-					return d;
-				}
-				return arg;
-			}
-			return ddt._resolveLazy(arg, sync, true);
-		},
-		_re: /(?:\{\{\s*(.+?)\s*\}\}|\{%\s*(load\s*)?(.+?)\s*%\})/g,
-		tokenize: function(str){
-			return dojox.string.tokenize(str, ddt._re, ddt._parseDelims);
-		},
-		_parseDelims: function(varr, load, tag){
-			if(varr){
-				return [dd.TOKEN_VAR, varr];
-			}else if(load){
-				var parts = dojo.trim(tag).split(/\s+/g);
-				for(var i = 0, part; part = parts[i]; i++){
-					dojo["require"](part);
-				}
-			}else{
-				return [dd.TOKEN_BLOCK, tag];
-			}
-		}
-	}
-
-	dd.Template = dojo.extend(function(/*String|dojo._Url*/ template, /*Boolean*/ isString){
-		// template:
-		//		The string or location of the string to
-		//		use as a template
-		var str = isString ? template : ddt._resolveTemplateArg(template, true) || "";
-		var tokens = ddt.tokenize(str);
-		var parser = new dd._Parser(tokens);
-		this.nodelist = parser.parse();
-	},
-	{
-		update: function(node, context){
-			// node: DOMNode|String|dojo.NodeList
-			//		A node reference or set of nodes
-			// context: dojo._Url|String|Object
-			//		The context object or location
-			return ddt._resolveContextArg(context).addCallback(this, function(contextObject){
-				var content = this.render(new dd._Context(contextObject));
-				if(node.forEach){
-					node.forEach(function(item){
-						item.innerHTML = content;
-					});
-				}else{
-					dojo.byId(node).innerHTML = content;
-				}
-				return this;
-			});
-		},
-		render: function(context, /*concatenatable?*/ buffer){
-			buffer = buffer || this.getBuffer();
-			context = context || new dd._Context({});
-			return this.nodelist.render(context, buffer) + "";
-		},
-		getBuffer: function(){
-			
-			return new dojox.string.Builder();
-		}
-	});
-
-	var qfRe = /\{\{\s*(.+?)\s*\}\}/g;
-	dd.quickFilter = function(str){
-		if(!str){
-			return new dd._NodeList();
-		}
-
-		if(str.indexOf("{%") == -1){
-			return new dd._QuickNodeList(dojox.string.tokenize(str, qfRe, function(token){
-				return new dd._Filter(token);
-			}));
-		}
-	}
-
-	dd._QuickNodeList = dojo.extend(function(contents){
-		this.contents = contents;
-	},
-	{
-		render: function(context, buffer){
-			for(var i=0, l=this.contents.length; i<l; i++){
-				if(this.contents[i].resolve){
-					buffer = buffer.concat(this.contents[i].resolve(context));
-				}else{
-					buffer = buffer.concat(this.contents[i]);
-				}
-			}
-			return buffer;
-		},
-		dummyRender: function(context){ return this.render(context, dd.Template.prototype.getBuffer()).toString(); },
-		clone: function(buffer){ return this; }
-	});
-
-	dd._Filter = dojo.extend(function(token){
-		// summary: Uses a string to find (and manipulate) a variable
-		if(!token) throw new Error("Filter must be called with variable name");
-		this.contents = token;
-
-		var cache = this._cache[token];
-		if(cache){
-			this.key = cache[0];
-			this.filters = cache[1];
-		}else{
-			this.filters = [];
-			dojox.string.tokenize(token, this._re, this._tokenize, this);
-			this._cache[token] = [this.key, this.filters];
-		}
-	},
-	{
-		_cache: {},
-		_re: /(?:^_\("([^\\"]*(?:\\.[^\\"])*)"\)|^"([^\\"]*(?:\\.[^\\"]*)*)"|^([a-zA-Z0-9_.]+)|\|(\w+)(?::(?:_\("([^\\"]*(?:\\.[^\\"])*)"\)|"([^\\"]*(?:\\.[^\\"]*)*)"|([a-zA-Z0-9_.]+)|'([^\\']*(?:\\.[^\\']*)*)'))?|^'([^\\']*(?:\\.[^\\']*)*)')/g,
-		_values: {
-			0: '"', // _("text")
-			1: '"', // "text"
-			2: "", // variable
-			8: '"' // 'text'
-		},
-		_args: {
-			4: '"', // :_("text")
-			5: '"', // :"text"
-			6: "", // :variable
-			7: "'"// :'text'
-		},
-		_tokenize: function(){
-			var pos, arg;
-
-			for(var i = 0, has = []; i < arguments.length; i++){
-				has[i] = (typeof arguments[i] != "undefined" && typeof arguments[i] == "string" && arguments[i]);
-			}
-
-			if(!this.key){
-				for(pos in this._values){
-					if(has[pos]){
-						this.key = this._values[pos] + arguments[pos] + this._values[pos];
-						break;
-					}
-				}
-			}else{
-				for(pos in this._args){
-					if(has[pos]){
-						var value = arguments[pos];
-						if(this._args[pos] == "'"){
-							value = value.replace(/\\'/g, "'");
-						}else if(this._args[pos] == '"'){
-							value = value.replace(/\\"/g, '"');
-						}
-						arg = [!this._args[pos], value];
-						break;
-					}
-				}
-				// Get a named filter
-				var fn = ddt.getFilter(arguments[3]);
-				if(!dojo.isFunction(fn)) throw new Error(arguments[3] + " is not registered as a filter");
-				this.filters.push([fn, arg]);
-			}
-		},
-		getExpression: function(){
-			return this.contents;
-		},
-		resolve: function(context){
-			if(typeof this.key == "undefined"){
-				return "";
-			}
-
-			var str = this.resolvePath(this.key, context);
-
-			for(var i = 0, filter; filter = this.filters[i]; i++){
-				// Each filter has the function in [0], a boolean in [1][0] of whether it's a variable or a string
-				// and [1][1] is either the variable name of the string content.
-				if(filter[1]){
-					if(filter[1][0]){
-						str = filter[0](str, this.resolvePath(filter[1][1], context));
-					}else{
-						str = filter[0](str, filter[1][1]);
-					}
-				}else{
-					str = filter[0](str);
-				}
-			}
-
-			return str;
-		},
-		resolvePath: function(path, context){
-			var current, parts;
-			var first = path.charAt(0);
-			var last = path.slice(-1);
-			if(!isNaN(parseInt(first))){
-				current = (path.indexOf(".") == -1) ? parseInt(path) : parseFloat(path);
-			}else if(first == '"' && first == last){
-				current = path.slice(1, -1);
-			}else{
-				if(path == "true"){ return true; }
-				if(path == "false"){ return false; }
-				if(path == "null" || path == "None"){ return null; }
-				parts = path.split(".");
-				current = context.get(parts[0]);
-
-				if(dojo.isFunction(current)){
-					var self = context.getThis && context.getThis();
-					if(current.alters_data){
-						current = "";
-					}else if(self){
-						current = current.call(self);
-					}else{
-						current = "";
-					}
-				}
-
-				for(var i = 1; i < parts.length; i++){
-					var part = parts[i];
-					if(current){
-						var base = current;
-						if(dojo.isObject(current) && part == "items" && typeof current[part] == "undefined"){
-							var items = [];
-							for(var key in current){
-								items.push([key, current[key]]);
-							}
-							current = items;
-							continue;
-						}
-
-						if(current.get && dojo.isFunction(current.get) && current.get.safe){
-							current = current.get(part);
-						}else if(typeof current[part] == "undefined"){
-							current = current[part];
-							break;
-						}else{
-							current = current[part];
-						}
-
-						if(dojo.isFunction(current)){
-							if(current.alters_data){
-								current = "";
-							}else{
-								current = current.call(base);
-							}
-						}else if(current instanceof Date){
-							current = dd._Context.prototype._normalize(current);
-						}
-					}else{
-						return "";
-					}
-				}
-			}
-			return current;
-		}
-	});
-
-	dd._TextNode = dd._Node = dojo.extend(function(/*Object*/ obj){
-		// summary: Basic catch-all node
-		this.contents = obj;
-	},
-	{
-		set: function(data){
-			this.contents = data;
-			return this;
-		},
-		render: function(context, buffer){
-			// summary: Adds content onto the buffer
-			return buffer.concat(this.contents);
-		},
-		isEmpty: function(){
-			return !dojo.trim(this.contents);
-		},
-		clone: function(){ return this; }
-	});
-
-	dd._NodeList = dojo.extend(function(/*Node[]*/ nodes){
-		// summary: Allows us to render a group of nodes
-		this.contents = nodes || [];
-		this.last = "";
-	},
-	{
-		push: function(node){
-			// summary: Add a new node to the list
-			this.contents.push(node);
-			return this;
-		},
-		concat: function(nodes){
-			this.contents = this.contents.concat(nodes);
-			return this;
-		},
-		render: function(context, buffer){
-			// summary: Adds all content onto the buffer
-			for(var i = 0; i < this.contents.length; i++){
-				buffer = this.contents[i].render(context, buffer);
-				if(!buffer) throw new Error("Template must return buffer");
-			}
-			return buffer;
-		},
-		dummyRender: function(context){
-			return this.render(context, dd.Template.prototype.getBuffer()).toString();
-		},
-		unrender: function(){ return arguments[1]; },
-		clone: function(){ return this; },
-		rtrim: function(){
-			while(1){
-				i = this.contents.length - 1;
-				if(this.contents[i] instanceof dd._TextNode && this.contents[i].isEmpty()){
-					this.contents.pop();
-				}else{
-					break;
-				}
-			}
-
-			return this;
-		}
-	});
-
-	dd._VarNode = dojo.extend(function(str){
-		// summary: A node to be processed as a variable
-		this.contents = new dd._Filter(str);
-	},
-	{
-		render: function(context, buffer){
-			var str = this.contents.resolve(context);
-			if(!str.safe){
-				str = dd._base.escape("" + str);
-			}
-			return buffer.concat(str);
-		}
-	});
-
-	dd._noOpNode = new function(){
-		// summary: Adds a no-op node. Useful in custom tags
-		this.render = this.unrender = function(){ return arguments[1]; }
-		this.clone = function(){ return this; }
-	}
-
-	dd._Parser = dojo.extend(function(tokens){
-		// summary: Parser used during initialization and for tag groups.
-		this.contents = tokens;
-	},
-	{
-		i: 0,
-		parse: function(/*Array?*/ stop_at){
-			// summary: Turns tokens into nodes
-			// description: Steps into tags are they're found. Blocks use the parse object
-			//		to find their closing tag (the stop_at array). stop_at is inclusive, it
-			//		returns the node that matched.
-			var terminators = {}, token;
-			stop_at = stop_at || [];
-			for(var i = 0; i < stop_at.length; i++){
-				terminators[stop_at[i]] = true;
-			}
-
-			var nodelist = new dd._NodeList();
-			while(this.i < this.contents.length){
-				token = this.contents[this.i++];
-				if(typeof token == "string"){
-					nodelist.push(new dd._TextNode(token));
-				}else{
-					var type = token[0];
-					var text = token[1];
-					if(type == dd.TOKEN_VAR){
-						nodelist.push(new dd._VarNode(text));
-					}else if(type == dd.TOKEN_BLOCK){
-						if(terminators[text]){
-							--this.i;
-							return nodelist;
-						}
-						var cmd = text.split(/\s+/g);
-						if(cmd.length){
-							cmd = cmd[0];
-							var fn = ddt.getTag(cmd);
-							if(fn){
-								nodelist.push(fn(this, new dd.Token(type, text)));
-							}
-						}
-					}
-				}
-			}
-
-			if(stop_at.length){
-				throw new Error("Could not find closing tag(s): " + stop_at.toString());
-			}
-
-			this.contents.length = 0;
-			return nodelist;
-		},
-		next_token: function(){
-			// summary: Returns the next token in the list.
-			var token = this.contents[this.i++];
-			return new dd.Token(token[0], token[1]);
-		},
-		delete_first_token: function(){
-			this.i++;
-		},
-		skip_past: function(endtag){
-			while(this.i < this.contents.length){
-				var token = this.contents[this.i++];
-				if(token[0] == dd.TOKEN_BLOCK && token[1] == endtag){
-					return;
-				}
-			}
-			throw new Error("Unclosed tag found when looking for " + endtag);
-		},
-		create_variable_node: function(expr){
-			return new dd._VarNode(expr);
-		},
-		create_text_node: function(expr){
-			return new dd._TextNode(expr || "");
-		},
-		getTemplate: function(file){
-			return new dd.Template(file);
-		}
-	});
-
-	dd.register = {
-		_registry: {
-			attributes: [],
-			tags: [],
-			filters: []
-		},
-		get: function(/*String*/ module, /*String*/ name){
-			var registry = dd.register._registry[module + "s"];
-			for(var i = 0, entry; entry = registry[i]; i++){
-				if(typeof entry[0] == "string"){
-					if(entry[0] == name){
-						return entry;
-					}
-				}else if(name.match(entry[0])){
-					return entry;
-				}
-			}
-		},
-		getAttributeTags: function(){
-			var tags = [];
-			var registry = dd.register._registry.attributes;
-			for(var i = 0, entry; entry = registry[i]; i++){
-				if(entry.length == 3){
-					tags.push(entry);
-				}else{
-					var fn = dojo.getObject(entry[1]);
-					if(fn && dojo.isFunction(fn)){
-						entry.push(fn);
-						tags.push(entry);
-					}
-				}
-			}
-			return tags;
-		},
-		_any: function(type, base, locations){
-			for(var path in locations){
-				for(var i = 0, fn; fn = locations[path][i]; i++){
-					var key = fn;
-					if(dojo.isArray(fn)){
-						key = fn[0];
-						fn = fn[1];
-					}
-					if(typeof key == "string"){
-						if(key.substr(0, 5) == "attr:"){
-							var attr = fn;
-							if(attr.substr(0, 5) == "attr:"){
-								attr = attr.slice(5);
-							}
-							dd.register._registry.attributes.push([attr.toLowerCase(), base + "." + path + "." + attr]);
-						}
-						key = key.toLowerCase()
-					}
-					dd.register._registry[type].push([
-						key,
-						fn,
-						base + "." + path
-					]);
-				}
-			}
-		},
-		tags: function(/*String*/ base, /*Object*/ locations){
-			dd.register._any("tags", base, locations);
-		},
-		filters: function(/*String*/ base, /*Object*/ locations){
-			dd.register._any("filters", base, locations);
-		}
-	}
-
-	var escapeamp = /&/g;
-	var escapelt = /</g;
-	var escapegt = />/g;
-	var escapeqt = /'/g;
-	var escapedblqt = /"/g;
-	dd._base.escape = function(value){
-		// summary: Escapes a string's HTML
-		return dd.mark_safe(value.replace(escapeamp, '&').replace(escapelt, '<').replace(escapegt, '>').replace(escapedblqt, '"').replace(escapeqt, '''));
-	}
-
-	dd._base.safe = function(value){
-		if(typeof value == "string"){
-			value = new String(value);
-		}
-		if(typeof value == "object"){
-			value.safe = true;
-		}
-		return value;
-	}
-	dd.mark_safe = dd._base.safe;
-
-	dd.register.tags("dojox.dtl.tag", {
-		"date": ["now"],
-		"logic": ["if", "for", "ifequal", "ifnotequal"],
-		"loader": ["extends", "block", "include", "load", "ssi"],
-		"misc": ["comment", "debug", "filter", "firstof", "spaceless", "templatetag", "widthratio", "with"],
-		"loop": ["cycle", "ifchanged", "regroup"]
-	});
-	dd.register.filters("dojox.dtl.filter", {
-		"dates": ["date", "time", "timesince", "timeuntil"],
-		"htmlstrings": ["linebreaks", "linebreaksbr", "removetags", "striptags"],
-		"integers": ["add", "get_digit"],
-		"lists": ["dictsort", "dictsortreversed", "first", "join", "length", "length_is", "random", "slice", "unordered_list"],
-		"logic": ["default", "default_if_none", "divisibleby", "yesno"],
-		"misc": ["filesizeformat", "pluralize", "phone2numeric", "pprint"],
-		"strings": ["addslashes", "capfirst", "center", "cut", "fix_ampersands", "floatformat", "iriencode", "linenumbers", "ljust", "lower", "make_list", "rjust", "slugify", "stringformat", "title", "truncatewords", "truncatewords_html", "upper", "urlencode", "urlize", "urlizetrunc", "wordcount", "wordwrap"]
-	});
-	dd.register.filters("dojox.dtl", {
-		"_base": ["escape", "safe"]
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.dtl"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.dtl"] = true;
-dojo.provide("dojox.dtl");
-
-
-}
-
-if(!dojo._hasResource["dojox.dtl.Context"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.dtl.Context"] = true;
-dojo.provide("dojox.dtl.Context");
-
-
-dojox.dtl.Context = dojo.extend(function(dict){
-	this._this = {};
-	dojox.dtl._Context.call(this, dict);
-}, dojox.dtl._Context.prototype,
-{
-	getKeys: function(){
-		var keys = [];
-		for(var key in this){
-			if(this.hasOwnProperty(key) && key != "_dicts" && key != "_this"){
-				keys.push(key);
-			}
-		}
-		return keys;
-	},
-	extend: function(/*dojox.dtl.Context|Object*/ obj){
-		// summary: Returns a clone of this context object, with the items from the
-		//		passed objecct mixed in.
-		return  dojo.delegate(this, obj);
-	},
-	filter: function(/*dojox.dtl.Context|Object|String...*/ filter){
-		// summary: Returns a clone of this context, only containing the items
-		//		defined in the filter.
-		var context = new dojox.dtl.Context();
-		var keys = [];
-		var i, arg;
-		if(filter instanceof dojox.dtl.Context){
-			keys = filter.getKeys();
-		}else if(typeof filter == "object"){
-			for(var key in filter){
-				keys.push(key);
-			}
-		}else{
-			for(i = 0; arg = arguments[i]; i++){
-				if(typeof arg == "string"){
-					keys.push(arg);
-				}
-			}
-		}
-
-		for(i = 0, key; key = keys[i]; i++){
-			context[key] = this[key];
-		}
-
-		return context;
-	},
-	setThis: function(/*Object*/ _this){
-		this._this = _this;
-	},
-	getThis: function(){
-		return this._this;
-	},
-	hasKey: function(key){
-		if(typeof this[key] != "undefined"){
-			return true;
-		}
-
-		for(var i = 0, dict; dict = this._dicts[i]; i++){
-			if(typeof dict[key] != "undefined"){
-				return true;
-			}
-		}
-
-		return false;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.dtl.tag.logic"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.dtl.tag.logic"] = true;
-dojo.provide("dojox.dtl.tag.logic");
-
-
-
-(function(){
-	var dd = dojox.dtl;
-	var ddt = dd.text;
-	var ddtl = dd.tag.logic;
-
-	ddtl.IfNode = dojo.extend(function(bools, trues, falses, type){
-		this.bools = bools;
-		this.trues = trues;
-		this.falses = falses;
-		this.type = type;
-	},
-	{
-		render: function(context, buffer){
-			var i, bool, ifnot, filter, value;
-			if(this.type == "or"){
-				for(i = 0; bool = this.bools[i]; i++){
-					ifnot = bool[0];
-					filter = bool[1];
-					value = filter.resolve(context);
-					if((value && !ifnot) || (ifnot && !value)){
-						if(this.falses){
-							buffer = this.falses.unrender(context, buffer);
-						}
-						return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
-					}
-				}
-				if(this.trues){
-					buffer = this.trues.unrender(context, buffer);
-				}
-				return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
-			}else{
-				for(i = 0; bool = this.bools[i]; i++){
-					ifnot = bool[0];
-					filter = bool[1];
-					value = filter.resolve(context);
-					// If we ever encounter a false value
-					if(value == ifnot){
-						if(this.trues){
-							buffer = this.trues.unrender(context, buffer);
-						}
-						return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
-					}
-				}
-				if(this.falses){
-					buffer = this.falses.unrender(context, buffer);
-				}
-				return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
-			}
-			return buffer;
-		},
-		unrender: function(context, buffer){
-			buffer = (this.trues) ? this.trues.unrender(context, buffer) : buffer;
-			buffer = (this.falses) ? this.falses.unrender(context, buffer) : buffer;
-			return buffer;
-		},
-		clone: function(buffer){
-			var trues = (this.trues) ? this.trues.clone(buffer) : null;
-			var falses = (this.falses) ? this.falses.clone(buffer) : null;
-			return new this.constructor(this.bools, trues, falses, this.type);
-		}
-	});
-
-	ddtl.IfEqualNode = dojo.extend(function(var1, var2, trues, falses, negate){
-		this.var1 = new dd._Filter(var1);
-		this.var2 = new dd._Filter(var2);
-		this.trues = trues;
-		this.falses = falses;
-		this.negate = negate;
-	},
-	{
-		render: function(context, buffer){
-			var var1 = this.var1.resolve(context);
-			var var2 = this.var2.resolve(context);
-			var1 = (typeof var1 != "undefined") ? var1 : "";
-			var2 = (typeof var1 != "undefined") ? var2 : "";
-			if((this.negate && var1 != var2) || (!this.negate && var1 == var2)){
-				if(this.falses){
-					buffer = this.falses.unrender(context, buffer, this);
-				}
-				return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
-			}
-			if(this.trues){
-				buffer = this.trues.unrender(context, buffer, this);
-			}
-			return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
-		},
-		unrender: function(context, buffer){
-			return ddtl.IfNode.prototype.unrender.call(this, context, buffer);
-		},
-		clone: function(buffer){
-			var trues = this.trues ? this.trues.clone(buffer) : null;
-			var falses = this.falses ? this.falses.clone(buffer) : null;
-			return new this.constructor(this.var1.getExpression(), this.var2.getExpression(), trues, falses, this.negate);
-		}
-	});
-
-	ddtl.ForNode = dojo.extend(function(assign, loop, reversed, nodelist){
-		this.assign = assign;
-		this.loop = new dd._Filter(loop);
-		this.reversed = reversed;
-		this.nodelist = nodelist;
-		this.pool = [];
-	},
-	{
-		render: function(context, buffer){
-			var i, j, k;
-			var dirty = false;
-			var assign = this.assign;
-
-			for(k = 0; k < assign.length; k++){
-				if(typeof context[assign[k]] != "undefined"){
-					dirty = true;
-					context = context.push();
-					break;
-				}
-			}
-			if(!dirty && context.forloop){
-				dirty = true;
-				context = context.push();
-			}
-
-			var items = this.loop.resolve(context) || [];
-			for(i = items.length; i < this.pool.length; i++){
-				this.pool[i].unrender(context, buffer, this);
-			}
-			if(this.reversed){
-				items = items.slice(0).reverse();
-			}
-
-			var isObject = dojo.isObject(items) && !dojo.isArrayLike(items);
-			var arred = [];
-			if(isObject){
-				for(var key in items){
-					arred.push(items[key]);
-				}
-			}else{
-				arred = items;
-			}
-
-			var forloop = context.forloop = {
-				parentloop: context.get("forloop", {})
-			};
-			var j = 0;
-			for(i = 0; i < arred.length; i++){
-				var item = arred[i];
-
-				forloop.counter0 = j;
-				forloop.counter = j + 1;
-				forloop.revcounter0 = arred.length - j - 1;
-				forloop.revcounter = arred.length - j;
-				forloop.first = !j;
-				forloop.last = (j == arred.length - 1);
-
-				if(assign.length > 1 && dojo.isArrayLike(item)){
-					if(!dirty){
-						dirty = true;
-						context = context.push();
-					}
-					var zipped = {};
-					for(k = 0; k < item.length && k < assign.length; k++){
-						zipped[assign[k]] = item[k];
-					}
-					dojo.mixin(context, zipped);
-				}else{
-					context[assign[0]] = item;
-				}
-
-				if(j + 1 > this.pool.length){
-					this.pool.push(this.nodelist.clone(buffer));
-				}
-				buffer = this.pool[j++].render(context, buffer, this);
-			}
-
-			delete context.forloop;
-			if(dirty){
-				context = context.pop();
-			}else{
-				for(k = 0; k < assign.length; k++){
-					delete context[assign[k]];
-				}
-			}
-			return buffer;
-		},
-		unrender: function(context, buffer){
-			for(var i = 0, pool; pool = this.pool[i]; i++){
-				buffer = pool.unrender(context, buffer);
-			}
-			return buffer;
-		},
-		clone: function(buffer){
-			return new this.constructor(this.assign, this.loop.getExpression(), this.reversed, this.nodelist.clone(buffer));
-		}
-	});
-
-	dojo.mixin(ddtl, {
-		if_: function(parser, token){
-			var i, part, type, bools = [], parts = token.contents.split();
-			parts.shift();
-			token = parts.join(" ");
-			parts = token.split(" and ");
-			if(parts.length == 1){
-				type = "or";
-				parts = token.split(" or ");
-			}else{
-				type = "and";
-				for(i = 0; i < parts.length; i++){
-					if(parts[i].indexOf(" or ") != -1){
-						// Note, since we split by and, this is the only place we need to error check
-						throw new Error("'if' tags can't mix 'and' and 'or'");
-					}
-				}
-			}
-			for(i = 0; part = parts[i]; i++){
-				var not = false;
-				if(part.indexOf("not ") == 0){
-					part = part.slice(4);
-					not = true;
-				}
-				bools.push([not, new dd._Filter(part)]);
-			}
-			var trues = parser.parse(["else", "endif"]);
-			var falses = false;
-			var token = parser.next_token();
-			if(token.contents == "else"){
-				falses = parser.parse(["endif"]);
-				parser.next_token();
-			}
-			return new ddtl.IfNode(bools, trues, falses, type);
-		},
-		_ifequal: function(parser, token, negate){
-			var parts = token.split_contents();
-			if(parts.length != 3){
-				throw new Error(parts[0] + " takes two arguments");
-			}
-			var end = 'end' + parts[0];
-			var trues = parser.parse(["else", end]);
-			var falses = false;
-			var token = parser.next_token();
-			if(token.contents == "else"){
-				falses = parser.parse([end]);
-				parser.next_token();
-			}
-			return new ddtl.IfEqualNode(parts[1], parts[2], trues, falses, negate);
-		},
-		ifequal: function(parser, token){
-			return ddtl._ifequal(parser, token);
-		},
-		ifnotequal: function(parser, token){
-			return ddtl._ifequal(parser, token, true);
-		},
-		for_: function(parser, token){
-			var parts = token.contents.split();
-			if(parts.length < 4){
-				throw new Error("'for' statements should have at least four words: " + token.contents);
-			}
-			var reversed = parts[parts.length - 1] == "reversed";
-			var index = (reversed) ? -3 : -2;
-			if(parts[parts.length + index] != "in"){
-				throw new Error("'for' tag received an invalid argument: " + token.contents);
-			}
-			var loopvars = parts.slice(1, index).join(" ").split(/ *, */);
-			for(var i = 0; i < loopvars.length; i++){
-				if(!loopvars[i] || loopvars[i].indexOf(" ") != -1){
-					throw new Error("'for' tag received an invalid argument: " + token.contents);
-				}
-			}
-			var nodelist = parser.parse(["endfor"]);
-			parser.next_token();
-			return new ddtl.ForNode(loopvars, parts[parts.length + index + 1], reversed, nodelist);
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.dtl.tag.loop"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.dtl.tag.loop"] = true;
-dojo.provide("dojox.dtl.tag.loop");
-
-
-
-
-(function(){
-	var dd = dojox.dtl;
-	var ddtl = dd.tag.loop;
-
-	ddtl.CycleNode = dojo.extend(function(cyclevars, name, text, shared){
-		this.cyclevars = cyclevars;
-		this.name = name;
-		this.contents = text;
-		this.shared = shared || {counter: -1, map: {}};
-	},
-	{
-		render: function(context, buffer){
-			if(context.forloop && !context.forloop.counter0){
-				this.shared.counter = -1;
-			}
-
-			++this.shared.counter;
-			var value = this.cyclevars[this.shared.counter % this.cyclevars.length];
-
-			var map = this.shared.map;
-			if(!map[value]){
-				map[value] = new dd._Filter(value);
-			}
-			value = map[value].resolve(context, buffer);
-
-			if(this.name){
-				context[this.name] = value;
-			}
-			this.contents.set(value);
-			return this.contents.render(context, buffer);
-		},
-		unrender: function(context, buffer){
-			return this.contents.unrender(context, buffer);
-		},
-		clone: function(buffer){
-			return new this.constructor(this.cyclevars, this.name, this.contents.clone(buffer), this.shared);
-		}
-	});
-
-	ddtl.IfChangedNode = dojo.extend(function(nodes, vars, shared){
-		this.nodes = nodes;
-		this._vars = vars;
-		this.shared = shared || {last: null, counter: 0};
-		this.vars = dojo.map(vars, function(item){
-			return new dojox.dtl._Filter(item);
-		});
-	}, {
-		render: function(context, buffer){
-			if(context.forloop){
-				if(context.forloop.counter <= this.shared.counter){
-					this.shared.last = null;
-				}
-				this.shared.counter = context.forloop.counter;
-			}
-
-			var change;
-			if(this.vars.length){
-				change = dojo.toJson(dojo.map(this.vars, function(item){
-					return item.resolve(context);
-				}));
-			}else{
-				change = this.nodes.dummyRender(context, buffer);
-			}
-
-			if(change != this.shared.last){
-				var firstloop = (this.shared.last === null);
-				this.shared.last = change;
-				context = context.push();
-				context.ifchanged = {firstloop: firstloop};
-				buffer = this.nodes.render(context, buffer);
-				context = context.pop();
-			}else{
-				buffer = this.nodes.unrender(context, buffer);
-			}
-			return buffer;
-		},
-		unrender: function(context, buffer){
-			return this.nodes.unrender(context, buffer);
-		},
-		clone: function(buffer){
-			return new this.constructor(this.nodes.clone(buffer), this._vars, this.shared);
-		}
-	});
-
-	ddtl.RegroupNode = dojo.extend(function(expression, key, alias){
-		this._expression = expression;
-		this.expression = new dd._Filter(expression);
-		this.key = key;
-		this.alias = alias;
-	},
-	{
-		_push: function(container, grouper, stack){
-			if(stack.length){
-				container.push({ grouper: grouper, list: stack });
-			}
-		},
-		render: function(context, buffer){
-			context[this.alias] = [];
-			var list = this.expression.resolve(context);
-			if(list){
-				var last = null;
-				var stack = [];
-				for(var i = 0; i < list.length; i++){
-					var id = list[i][this.key];
-					if(last !== id){
-						this._push(context[this.alias], last, stack);
-						last = id;
-						stack = [list[i]];
-					}else{
-						stack.push(list[i]);
-					}
-				}
-				this._push(context[this.alias], last, stack);
-			}
-			return buffer;
-		},
-		unrender: function(context, buffer){
-			return buffer;
-		},
-		clone: function(context, buffer){
-			return this;
-		}
-	});
-
-	dojo.mixin(ddtl, {
-		cycle: function(parser, token){
-			// summary: Cycle among the given strings each time this tag is encountered
-			var args = token.split_contents();
-
-			if(args.length < 2){
-				throw new Error("'cycle' tag requires at least two arguments");
-			}
-
-			if(args[1].indexOf(",") != -1){
-				var vars = args[1].split(",");
-				args = [args[0]];
-				for(var i = 0; i < vars.length; i++){
-					args.push('"' + vars[i] + '"');
-				}
-			}
-
-			if(args.length == 2){
-				var name = args[args.length - 1];
-
-				if(!parser._namedCycleNodes){
-					throw new Error("No named cycles in template: '" + name + "' is not defined");
-				}
-				if(!parser._namedCycleNodes[name]){
-					throw new Error("Named cycle '" + name + "' does not exist");
-				}
-
-		        return parser._namedCycleNodes[name];
-			}
-
-			if(args.length > 4 && args[args.length - 2] == "as"){
-				var name = args[args.length - 1];
-
-				var node = new ddtl.CycleNode(args.slice(1, args.length - 2), name, parser.create_text_node());
-
-				if(!parser._namedCycleNodes){
-					parser._namedCycleNodes = {};
-				}
-				parser._namedCycleNodes[name] = node;
-			}else{
-				node = new ddtl.CycleNode(args.slice(1), null, parser.create_text_node());
-			}
-
-			return node;
-		},
-		ifchanged: function(parser, token){
-			var parts = token.contents.split();
-			var nodes = parser.parse(["endifchanged"]);
-			parser.delete_first_token();
-			return new ddtl.IfChangedNode(nodes, parts.slice(1));
-		},
-		regroup: function(parser, token){
-			var tokens = dojox.string.tokenize(token.contents, /(\s+)/g, function(spaces){
-				return spaces;
-			});
-			if(tokens.length < 11 || tokens[tokens.length - 3] != "as" || tokens[tokens.length - 7] != "by"){
-				throw new Error("Expected the format: regroup list by key as newList");
-			}
-			var expression = tokens.slice(2, -8).join("");
-			var key = tokens[tokens.length - 5];
-			var alias = tokens[tokens.length - 1];
-			return new ddtl.RegroupNode(expression, key, alias);
-		}
-	});
-})();
-
-}
-
-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(+date1);
-	date2 = new Date(+(date2 || new Date()));
-
-	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(+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":
-		default:
-			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["dojox.date.php"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.date.php"] = true;
-dojo.provide("dojox.date.php");
-
-
-
-dojox.date.php.format = function(/*Date*/ date, /*String*/ format){
-	// summary: Get a formatted string for a given date object
-	var df = new dojox.date.php.DateFormat(format);
-	return df.format(date);	
-}
-
-dojox.date.php.DateFormat = function(/*String*/ format){
-	// summary: Format the internal date object
-	if(!this.regex){
-		var keys = [];
-		for(var key in this.constructor.prototype){
-			if(dojo.isString(key) && key.length == 1 && dojo.isFunction(this[key])){
-				keys.push(key);
-			}
-		}
-		this.constructor.prototype.regex = new RegExp("(?:(\\\\.)|([" + keys.join("") + "]))", "g");
-	}
-
-	var replacements = [];
-
-	this.tokens = dojox.string.tokenize(format, this.regex, function(escape, token, i){
-		if(token){
-			replacements.push([i, token]);
-			return token;
-		}
-		if(escape){
-			return escape.charAt(1);
-		}
-	});
-
-	this.replacements = replacements;
-}
-dojo.extend(dojox.date.php.DateFormat, {
-	weekdays: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
-	weekdays_3: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
-	months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
-	months_3: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
-	monthdays: [31,28,31,30,31,30,31,31,30,31,30,31],
-
-	format: function(/*Date*/ date){
-		this.date = date;
-		for(var i = 0, replacement; replacement = this.replacements[i]; i++){
-			this.tokens[replacement[0]] = this[replacement[1]]();
-		}
-		return this.tokens.join("");
-	},
-
-	// Day
-
-	d: function(){
-		// summary: Day of the month, 2 digits with leading zeros
-		var j = this.j();
-		return (j.length == 1) ? "0" + j : j;
-	},
-
-	D: function(){
-		// summary: A textual representation of a day, three letters
-		return this.weekdays_3[this.date.getDay()];
-	},
-
-	j: function(){
-		// summary: Day of the month without leading zeros
-		return this.date.getDate() + "";
-	},
-
-	l: function(){
-		// summary: A full textual representation of the day of the week
-		return this.weekdays[this.date.getDay()];
-	},
-	
-	N: function(){
-		// summary: ISO-8601 numeric representation of the day of the week (added in PHP 5.1.0)
-		var w = this.w();
-		return (!w) ? 7 : w;
-	},
-
-	S: function(){
-		// summary: English ordinal suffix for the day of the month, 2 characters
-		switch(this.date.getDate()){
-			case 11: case 12: case 13: return "th";
-			case 1: case 21: case 31: return "st";
-			case 2: case 22: return "nd";
-			case 3: case 23: return "rd";
-			default: return "th";
-		}
-	},
-
-	w: function(){
-		// summary: Numeric representation of the day of the week
-		return this.date.getDay() + "";
-	},
-
-	z: function(){
-		// summary: The day of the year (starting from 0)
-		var millis = this.date.getTime() - new Date(this.date.getFullYear(), 0, 1).getTime();
-		return Math.floor(millis/86400000) + "";
-	},
-
-	// Week
-
-	W: function(){
-		// summary: ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0)
-		var week;
-		var jan1_w = new Date(this.date.getFullYear(), 0, 1).getDay() + 1;
-		var w = this.date.getDay() + 1;
-		var z = parseInt(this.z());
-
-		if(z <= (8 - jan1_w) && jan1_w > 4){
-			var last_year = new Date(this.date.getFullYear() - 1, this.date.getMonth(), this.date.getDate());
-			if(jan1_w == 5 || (jan1_w == 6 && dojo.date.isLeapYear(last_year))){
-				week = 53;
-			}else{
-				week = 52;
-			}
-		}else{
-			var i;
-			if(Boolean(this.L())){
-				i = 366;
-			}else{
-				i = 365;
-			}
-			if((i - z) < (4 - w)){
-				week = 1;
-			}else{
-				var j = z + (7 - w) + (jan1_w - 1);
-				week = Math.ceil(j / 7);
-				if(jan1_w > 4){
-					--week;
-				}
-			}
-		}
-		
-		return week;
-	},
-
-	// Month
-
-	F: function(){
-		// summary: A full textual representation of a month, such as January or March
-		return this.months[this.date.getMonth()];
-	},
-
-	m: function(){
-		// summary: Numeric representation of a month, with leading zeros
-		var n = this.n();
-		return (n.length == 1) ? "0" + n : n;
-	},
-
-	M: function(){
-		// summary: A short textual representation of a month, three letters
-		return this.months_3[this.date.getMonth()];
-	},
-
-	n: function(){
-		// summary: Numeric representation of a month, without leading zeros
-		return this.date.getMonth() + 1 + "";
-	},
-
-	t: function(){
-		// summary: Number of days in the given month
-		return (Boolean(this.L()) && this.date.getMonth() == 1) ? 29 : this.monthdays[this.getMonth()];
-	},
-
-	// Year
-
-	L: function(){
-		// summary: Whether it's a leap year
-		return (dojo.date.isLeapYear(this.date)) ? "1" : "0";
-	},
-
-	o: function(){
-		// summary:
-		//		ISO-8601 year number. This has the same value as Y, except that if
-		//		the ISO week number (W) belongs to the previous or next year, that year is used instead. (added in PHP 5.1.0)
-		// TODO: Figure out what this means
-	},
-
-	Y: function(){
-		// summary: A full numeric representation of a year, 4 digits
-		return this.date.getFullYear() + "";
-	},
-
-	y: function(){
-		// summary: A two digit representation of a year
-		return this.Y().slice(-2);
-	},
-
-	// Time
-
-	a: function(){
-		// summary: Lowercase Ante meridiem and Post meridiem
-		return this.date.getHours() >= 12 ? "pm" : "am";
-	},
-
-	b: function(){
-		// summary: Uppercase Ante meridiem and Post meridiem
-		return this.a().toUpperCase();
-	},
-
-	B: function(){
-		// summary:
-		//	Swatch Internet time
-		//	A day is 1,000 beats. All time is measured from GMT + 1
-		var off = this.date.getTimezoneOffset() + 60;
-		var secs = (this.date.getHours() * 3600) + (this.date.getMinutes() * 60) + this.getSeconds() + (off * 60);
-		var beat = Math.abs(Math.floor(secs / 86.4) % 1000) + "";
-		while(beat.length <  2) beat = "0" + beat;
-		return beat;
-	},
-
-	g: function(){
-		// summary: 12-hour format of an hour without leading zeros
-		return (this.date.getHours() > 12) ? this.date.getHours() - 12 + "" : this.date.getHours() + "";
-	},
-
-	G: function(){
-		// summary: 24-hour format of an hour without leading zeros
-		return this.date.getHours() + "";
-	},
-
-	h: function(){
-		// summary: 12-hour format of an hour with leading zeros
-		var g = this.g();
-		return (g.length == 1) ? "0" + g : g;
-	},
-
-	H: function(){
-		// summary: 24-hour format of an hour with leading zeros
-		var G = this.G();
-		return (G.length == 1) ? "0" + G : G;
-	},
-
-	i: function(){
-		// summary: Minutes with leading zeros
-		var mins = this.date.getMinutes() + "";
-		return (mins.length == 1) ? "0" + mins : mins;
-	},
-
-	s: function(){
-		// summary: Seconds, with leading zeros
-		var secs = this.date.getSeconds() + "";
-		return (secs.length == 1) ? "0" + secs : secs;
-	},
-
-	// Timezone
-
-	e: function(){
-		// summary: Timezone identifier (added in PHP 5.1.0)
-		return dojo.date.getTimezoneName(this.date);
-	},
-
-	I: function(){
-		// summary: Whether or not the date is in daylight saving time
-		// TODO: Can dojo.date do this?
-	},
-
-	O: function(){
-		// summary: Difference to Greenwich time (GMT) in hours
-		var off = Math.abs(this.date.getTimezoneOffset());
-		var hours = Math.floor(off / 60) + "";
-		var mins = (off % 60) + "";
-		if(hours.length == 1) hours = "0" + hours;
-		if(mins.length == 1) hours = "0" + mins;
-		return ((this.date.getTimezoneOffset() < 0) ? "+" : "-") + hours + mins;
-	},
-
-	P: function(){
-		// summary: Difference to Greenwich time (GMT) with colon between hours and minutes (added in PHP 5.1.3)
-		var O = this.O();
-		return O.substring(0, 2) + ":" + O.substring(2, 4);
-	},
-
-	T: function(){
-		// summary: Timezone abbreviation
-
-		// Guess...
-		return this.e().substring(0, 3);
-	},
-
-	Z: function(){
-		// summary:
-		//		Timezone offset in seconds. The offset for timezones west of UTC is always negative,
-		//		and for those east of UTC is always positive.
-		return this.date.getTimezoneOffset() * -60;
-	},
-
-	// Full Date/Time
-
-	c: function(){
-		// summary: ISO 8601 date (added in PHP 5)
-		return this.Y() + "-" + this.m() + "-" + this.d() + "T" + this.h() + ":" + this.i() + ":" + this.s() + this.P();
-	},
-
-	r: function(){
-		// summary: RFC 2822 formatted date
-		return this.D() + ", " + this.d() + " " + this.M() + " " + this.Y() + " " + this.H() + ":" + this.i() + ":" + this.s() + " " + this.O();
-	},
-
-	U: function(){
-		// summary: Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
-		return Math.floor(this.date.getTime() / 1000);
-	}
-
-});
-
-}
-
-if(!dojo._hasResource["dojox.dtl.utils.date"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.dtl.utils.date"] = true;
-dojo.provide("dojox.dtl.utils.date");
-
-
-
-dojox.dtl.utils.date.DateFormat = function(/*String*/ format){
-	dojox.date.php.DateFormat.call(this, format);
-}
-dojo.extend(dojox.dtl.utils.date.DateFormat, dojox.date.php.DateFormat.prototype, {
-	f: function(){
-		// summary:
-		//		Time, in 12-hour hours and minutes, with minutes left off if they're zero.
-		// description: 
-		//		Examples: '1', '1:30', '2:05', '2'
-		//		Proprietary extension.
-		return (!this.date.getMinutes()) ? this.g() : this.g() + ":" + this.i();
-	},
-	N: function(){
-		// summary: Month abbreviation in Associated Press style. Proprietary extension.
-		return dojox.dtl.utils.date._months_ap[this.date.getMonth()];
-	},
-	P: function(){
-		// summary:
-		//		Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off
-		//		if they're zero and the strings 'midnight' and 'noon' if appropriate.
-		// description:
-		//		Examples: '1 a.m.', '1:30 p.m.', 'midnight', 'noon', '12:30 p.m.'
-		//		Proprietary extension.
-		if(!this.date.getMinutes() && !this.date.getHours()){
-			return 'midnight';
-		}
-		if(!this.date.getMinutes() && this.date.getHours() == 12){
-			return 'noon';
-		}
-		return this.f() + " " + this.a();
-	}
-});
-
-dojo.mixin(dojox.dtl.utils.date, {
-	format: function(/*Date*/ date, /*String*/ format){
-		var df = new dojox.dtl.utils.date.DateFormat(format);
-		return df.format(date);
-	},
-	timesince: function(d, now){
-		// summary:
-		//		Takes two datetime objects and returns the time between then and now
-		//		as a nicely formatted string, e.g "10 minutes"
-		// description:
-		//		Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
-		if(!(d instanceof Date)){
-			d = new Date(d.year, d.month, d.day);
-		}
-		if(!now){
-			now = new Date();
-		}
-
-		var delta = Math.abs(now.getTime() - d.getTime());
-		for(var i = 0, chunk; chunk = dojox.dtl.utils.date._chunks[i]; i++){
-			var count = Math.floor(delta / chunk[0]);
-			if(count) break;
-		}
-		return count + " " + chunk[1](count);
-	},
-	_chunks: [
-		[60 * 60 * 24 * 365 * 1000, function(n){ return (n == 1) ? 'year' : 'years'; }],
-		[60 * 60 * 24 * 30 * 1000, function(n){ return (n == 1) ? 'month' : 'months'; }],
-		[60 * 60 * 24 * 7 * 1000, function(n){ return (n == 1) ? 'week' : 'weeks'; }],
-		[60 * 60 * 24 * 1000, function(n){ return (n == 1) ? 'day' : 'days'; }],
-		[60 * 60 * 1000, function(n){ return (n == 1) ? 'hour' : 'hours'; }],
-		[60 * 1000, function(n){ return (n == 1) ? 'minute' : 'minutes'; }]
-	],
-	_months_ap: ["Jan.", "Feb.", "March", "April", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec."]
-});
-
-}
-
-if(!dojo._hasResource["dojox.dtl.tag.date"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.dtl.tag.date"] = true;
-dojo.provide("dojox.dtl.tag.date");
-
-
-
-
-dojox.dtl.tag.date.NowNode = function(format, node){
-	this._format = format;
-	this.format = new dojox.dtl.utils.date.DateFormat(format);
-	this.contents = node;
-}
-dojo.extend(dojox.dtl.tag.date.NowNode, {
-	render: function(context, buffer){
-		this.contents.set(this.format.format(new Date()));
-		return this.contents.render(context, buffer);
-	},
-	unrender: function(context, buffer){
-		return this.contents.unrender(context, buffer);
-	},
-	clone: function(buffer){
-		return new this.constructor(this._format, this.contents.clone(buffer));
-	}
-});
-
-dojox.dtl.tag.date.now = function(parser, token){
-	// Split by either :" or :'
-	var parts = token.split_contents();
-	if(parts.length != 2){
-		throw new Error("'now' statement takes one argument");
-	}
-	return new dojox.dtl.tag.date.NowNode(parts[1].slice(1, -1), parser.create_text_node());
-}
-
-}
-
-if(!dojo._hasResource["dojox.dtl.tag.loader"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.dtl.tag.loader"] = true;
-dojo.provide("dojox.dtl.tag.loader");
-
-
-
-(function(){
-	var dd = dojox.dtl;
-	var ddtl = dd.tag.loader;
-
-	ddtl.BlockNode = dojo.extend(function(name, nodelist){
-		this.name = name;
-		this.nodelist = nodelist; // Can be overridden
-	},
-	{
-		"super": function(){
-			if(this.parent){
-				var html = this.parent.nodelist.dummyRender(this.context, null, true);
-				if(typeof html == "string"){
-					html = new String(html);
-				}
-				html.safe = true;
-				return html;
-			}
-			return '';
-		},
-		render: function(context, buffer){
-			var name = this.name;
-			var nodelist = this.nodelist;
-			var parent;
-			if(buffer.blocks){
-				var block = buffer.blocks[name];
-				if(block){
-					parent = block.parent;
-					nodelist = block.nodelist;
-					block.used = true;
-				}
-			}
-
-			this.rendered = nodelist;
-
-			context = context.push();
-			this.context = context;
-			this.parent = null;
-			if(nodelist != this.nodelist){
-				this.parent = this;
-			}
-			context.block = this;
-
-			if(buffer.getParent){
-				var bufferParent = buffer.getParent();
-				var setParent = dojo.connect(buffer, "onSetParent", function(node, up, root){
-					if(up && root){
-						buffer.setParent(bufferParent);
-					}
-				});
-			}
-			buffer = nodelist.render(context, buffer, this);
-			setParent && dojo.disconnect(setParent);
-			context = context.pop();
-			return buffer;
-		},
-		unrender: function(context, buffer){
-			return this.rendered.unrender(context, buffer);
-		},
-		clone: function(buffer){
-			return new this.constructor(this.name, this.nodelist.clone(buffer));
-		},
-		toString: function(){ return "dojox.dtl.tag.loader.BlockNode"; }
-	});
-
-	ddtl.ExtendsNode = dojo.extend(function(getTemplate, nodelist, shared, parent, key){
-		this.getTemplate = getTemplate;
-		this.nodelist = nodelist;
-		this.shared = shared;
-		this.parent = parent;
-		this.key = key;
-	},
-	{
-		parents: {},
-		getParent: function(context){
-			var parent = this.parent;
-			if(!parent){
-				var string;
-				parent = this.parent = context.get(this.key, false);
-				if(!parent){
-					throw new Error("extends tag used a variable that did not resolve");
-				}
-				if(typeof parent == "object"){
-					var url = parent.url || parent.templatePath;
-					if(parent.shared){
-						this.shared = true;
-					}
-					if(url){
-						parent = this.parent = url.toString();
-					}else if(parent.templateString){
-						// Allow the builder's string interning to work
-						string = parent.templateString;
-						parent = this.parent = " ";
-					}else{
-						parent = this.parent = this.parent.toString();
-					}
-				}
-				if(parent && parent.indexOf("shared:") === 0){
-					this.shared = true;
-					parent = this.parent = parent.substring(7, parent.length);
-				}
-			}
-			if(!parent){
-				throw new Error("Invalid template name in 'extends' tag.");
-			}
-			if(parent.render){
-				return parent;
-			}
-			if(this.parents[parent]){
-				return this.parents[parent];
-			}
-			this.parent = this.getTemplate(string || dojox.dtl.text.getTemplateString(parent));
-			if(this.shared){
-				this.parents[parent] = this.parent;
-			}
-			return this.parent;
-		},
-		render: function(context, buffer){
-			var parent = this.getParent(context);
-
-			parent.blocks = parent.blocks || {};
-			buffer.blocks = buffer.blocks || {};
-
-			for(var i = 0, node; node = this.nodelist.contents[i]; i++){
-				if(node instanceof dojox.dtl.tag.loader.BlockNode){
-					var old = parent.blocks[node.name];
-					if(old && old.nodelist != node.nodelist){
-						// In a shared template, the individual blocks might change
-						buffer = old.nodelist.unrender(context, buffer);
-					}
-					parent.blocks[node.name] = buffer.blocks[node.name] = {
-						shared: this.shared,
-						nodelist: node.nodelist,
-						used: false
-					}
-				}
-			}
-
-			this.rendered = parent;
-			return parent.nodelist.render(context, buffer, this);
-		},
-		unrender: function(context, buffer){
-			return this.rendered.unrender(context, buffer, this);
-		},
-		toString: function(){ return "dojox.dtl.block.ExtendsNode"; }
-	});
-
-	ddtl.IncludeNode = dojo.extend(function(path, constant, getTemplate, text, parsed){
-		this._path = path;
-		this.constant = constant;
-		this.path = (constant) ? path : new dd._Filter(path);
-		this.getTemplate = getTemplate;
-		this.text = text;
-		this.parsed = (arguments.length == 5) ? parsed : true;
-	},
-	{
-		_cache: [{}, {}],
-		render: function(context, buffer){
-			var location = ((this.constant) ? this.path : this.path.resolve(context)).toString();
-			var parsed = Number(this.parsed);
-			var dirty = false;
-			if(location != this.last){
-				dirty = true;
-				if(this.last){
-					buffer = this.unrender(context, buffer);
-				}
-				this.last = location;
-			}
-
-			var cache = this._cache[parsed];
-
-			if(parsed){
-				if(!cache[location]){
-					cache[location] = dd.text._resolveTemplateArg(location, true);
-				}
-				if(dirty){
-					var template = this.getTemplate(cache[location]);
-					this.rendered = template.nodelist;
-				}
-				return this.rendered.render(context, buffer, this);
-			}else{
-				if(this.text instanceof dd._TextNode){
-					if(dirty){
-						this.rendered = this.text;
-						this.rendered.set(dd.text._resolveTemplateArg(location, true));
-					}
-					return this.rendered.render(context, buffer);
-				}else{
-					if(!cache[location]){
-						var nodelist = [];
-						var div = document.createElement("div");
-						div.innerHTML = dd.text._resolveTemplateArg(location, true);
-						var children = div.childNodes;
-						while(children.length){
-							var removed = div.removeChild(children[0]);
-							nodelist.push(removed);
-						}
-						cache[location] = nodelist;
-					}
-					if(dirty){
-						this.nodelist = [];
-						var exists = true;
-						for(var i = 0, child; child = cache[location][i]; i++){
-							this.nodelist.push(child.cloneNode(true));
-						}
-					}
-					for(var i = 0, node; node = this.nodelist[i]; i++){
-						buffer = buffer.concat(node);
-					}
-				}
-			}
-			return buffer;
-		},
-		unrender: function(context, buffer){
-			if(this.rendered){
-				buffer = this.rendered.unrender(context, buffer);
-			}
-			if(this.nodelist){
-				for(var i = 0, node; node = this.nodelist[i]; i++){
-					buffer = buffer.remove(node);
-				}
-			}
-			return buffer;
-		},
-		clone: function(buffer){
-			return new this.constructor(this._path, this.constant, this.getTemplate, this.text.clone(buffer), this.parsed);
-		}
-	});
-
-	dojo.mixin(ddtl, {
-		block: function(parser, token){
-			var parts = token.contents.split();
-			var name = parts[1];
-
-			parser._blocks = parser._blocks || {};
-			parser._blocks[name] = parser._blocks[name] || [];
-			parser._blocks[name].push(name);
-
-			var nodelist = parser.parse(["endblock", "endblock " + name]).rtrim();
-			parser.next_token();
-			return new dojox.dtl.tag.loader.BlockNode(name, nodelist);
-		},
-		extends_: function(parser, token){
-			var parts = token.contents.split();
-			var shared = false;
-			var parent = null;
-			var key = null;
-			if(parts[1].charAt(0) == '"' || parts[1].charAt(0) == "'"){
-				parent = parts[1].substring(1, parts[1].length - 1);
-			}else{
-				key = parts[1];
-			}
-			if(parent && parent.indexOf("shared:") == 0){
-				shared = true;
-				parent = parent.substring(7, parent.length);
-			}
-			var nodelist = parser.parse();
-			return new dojox.dtl.tag.loader.ExtendsNode(parser.getTemplate, nodelist, shared, parent, key);
-		},
-		include: function(parser, token){
-			var parts = token.contents.split();
-			if(parts.length != 2){
-				throw new Error(parts[0] + " tag takes one argument: the name of the template to be included");
-			}
-			var path = parts[1];
-			var constant = false;
-			if((path.charAt(0) == '"' || path.slice(-1) == "'") && path.charAt(0) == path.slice(-1)){
-				path = path.slice(1, -1);
-				constant = true;
-			}
-			return new ddtl.IncludeNode(path, constant, parser.getTemplate, parser.create_text_node());
-		},
-		ssi: function(parser, token){
-			// We're going to treat things a little differently here.
-			// First of all, this tag is *not* portable, so I'm not
-			// concerned about it being a "drop in" replacement.
-
-			// Instead, we'll just replicate the include tag, but with that
-			// optional "parsed" parameter.
-			var parts = token.contents.split();
-			var parsed = false;
-			if(parts.length == 3){
-				parsed = (parts.pop() == "parsed");
-				if(!parsed){
-					throw new Error("Second (optional) argument to ssi tag must be 'parsed'");
-				}
-			}
-			var node = ddtl.include(parser, new dd.Token(token.token_type, parts.join(" ")));
-			node.parsed = parsed;
-			return node;
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.dtl.tag.misc"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.dtl.tag.misc"] = true;
-dojo.provide("dojox.dtl.tag.misc");
-
-
-(function(){
-	var dd = dojox.dtl;
-	var ddtm = dd.tag.misc;
-
-	ddtm.DebugNode = dojo.extend(function(text){
-		this.text = text;
-	},
-	{
-		render: function(context, buffer){
-			var keys = context.getKeys();
-			var debug = [];
-			var only = {};
-			for(var i = 0, key; key = keys[i]; i++){
-				only[key] = context[key];
-				debug += "[" + key + ": " + typeof context[key] + "]\n";
-			}
-			console.debug(only);
-			return this.text.set(debug).render(context, buffer, this);
-		},
-		unrender: function(context, buffer){
-			return buffer;
-		},
-		clone: function(buffer){
-			return new this.constructor(this.text.clone(buffer));
-		},
-		toString: function(){ return "ddtm.DebugNode"; }
-	});
-
-	ddtm.FilterNode = dojo.extend(function(varnode, nodelist){
-		this._varnode = varnode;
-		this._nodelist = nodelist;
-	},
-	{
-		render: function(context, buffer){
-			// Doing this in HTML requires a different buffer with a fake root node
-			var output = this._nodelist.render(context, new dojox.string.Builder());
-			context = context.update({ "var": output.toString() });
-			var filtered = this._varnode.render(context, buffer);
-			context = context.pop();
-			return buffer;
-		},
-		unrender: function(context, buffer){
-			return buffer;
-		},
-		clone: function(buffer){
-			return new this.constructor(this._expression, this._nodelist.clone(buffer));
-		}
-	});
-
-	ddtm.FirstOfNode = dojo.extend(function(vars, text){
-		this._vars = vars;
-		this.vars = dojo.map(vars, function(item){
-			return new dojox.dtl._Filter(item);
-		});
-		this.contents = text;
-	},
-	{
-		render: function(context, buffer){
-			for(var i = 0, item; item = this.vars[i]; i++){
-				var resolved = item.resolve(context);
-				if(typeof resolved != "undefined"){
-					if(resolved === null){
-						resolved = "null";
-					}
-					this.contents.set(resolved);
-					return this.contents.render(context, buffer);
-				}
-			}
-			return this.contents.unrender(context, buffer);
-		},
-		unrender: function(context, buffer){
-			return this.contents.unrender(context, buffer);
-		},
-		clone: function(buffer){
-			return new this.constructor(this._vars, this.contents.clone(buffer));
-		}
-	});
-
-	ddtm.SpacelessNode = dojo.extend(function(nodelist, text){
-		this.nodelist = nodelist;
-		this.contents = text;
-	},
-	{
-		render: function(context, buffer){
-			if(buffer.getParent){
-				// Unfortunately, we have to branch here
-				var watch = [
-					dojo.connect(buffer, "onAddNodeComplete", this, "_watch"),
-					dojo.connect(buffer, "onSetParent", this, "_watchParent")
-				];
-				buffer = this.nodelist.render(context, buffer);
-				dojo.disconnect(watch[0]);
-				dojo.disconnect(watch[1]);
-			}else{
-				var value = this.nodelist.dummyRender(context);
-				this.contents.set(value.replace(/>\s+</g, '><'));
-				buffer = this.contents.render(context, buffer);
-			}
-			return buffer;
-		},
-		unrender: function(context, buffer){
-			return this.nodelist.unrender(context, buffer);
-		},
-		clone: function(buffer){
-			return new this.constructor(this.nodelist.clone(buffer), this.contents.clone(buffer));
-		},
-		_isEmpty: function(node){
-			return (node.nodeType == 3 && !node.data.match(/[^\s\n]/));
-		},
-		_watch: function(node){
-			if(this._isEmpty(node)){
-				var remove = false;
-				if(node.parentNode.firstChild == node){
-					node.parentNode.removeChild(node);
-				}
-			}else{
-				var children = node.parentNode.childNodes;
-				if(node.nodeType == 1 && children.length > 2){
-					for(var i = 2, child; child = children[i]; i++){
-						if(children[i - 2].nodeType == 1 && this._isEmpty(children[i - 1])){
-							node.parentNode.removeChild(children[i - 1]);
-							return;
-						}
-					}
-				}
-			}
-		},
-		_watchParent: function(node){
-			var children = node.childNodes;
-			if(children.length){
-				while(node.childNodes.length){
-					var last = node.childNodes[node.childNodes.length - 1];
-					if(!this._isEmpty(last)){
-						return;
-					}
-					node.removeChild(last);
-				}
-			}
-		}
-	});
-
-	ddtm.TemplateTagNode = dojo.extend(function(tag, text){
-		this.tag = tag;
-		this.contents = text;
-	},
-	{
-		mapping: {
-			openblock: "{%",
-			closeblock: "%}",
-			openvariable: "{{",
-			closevariable: "}}",
-			openbrace: "{",
-			closebrace: "}",
-			opencomment: "{#",
-			closecomment: "#}"
-		},
-		render: function(context, buffer){
-			this.contents.set(this.mapping[this.tag]);
-			return this.contents.render(context, buffer);
-		},
-		unrender: function(context, buffer){
-			return this.contents.unrender(context, buffer);
-		},
-		clone: function(buffer){
-			return new this.constructor(this.tag, this.contents.clone(buffer));
-		}
-	});
-
-	ddtm.WidthRatioNode = dojo.extend(function(current, max, width, text){
-		this.current = new dd._Filter(current);
-		this.max = new dd._Filter(max);
-		this.width = width;
-		this.contents = text;
-	},
-	{
-		render: function(context, buffer){
-			var current = +this.current.resolve(context);
-			var max = +this.max.resolve(context);
-			if(typeof current != "number" || typeof max != "number" || !max){
-				this.contents.set("");
-			}else{
-				this.contents.set("" + Math.round((current / max) * this.width));
-			}
-			return this.contents.render(context, buffer);
-		},
-		unrender: function(context, buffer){
-			return this.contents.unrender(context, buffer);
-		},
-		clone: function(buffer){
-			return new this.constructor(this.current.getExpression(), this.max.getExpression(), this.width, this.contents.clone(buffer));
-		}
-	});
-
-	ddtm.WithNode = dojo.extend(function(target, alias, nodelist){
-		this.target = new dd._Filter(target);
-		this.alias = alias;
-		this.nodelist = nodelist;
-	},
-	{
-		render: function(context, buffer){
-			var target = this.target.resolve(context);
-			context = context.push();
-			context[this.alias] = target;
-			buffer = this.nodelist.render(context, buffer);
-			context = context.pop();
-			return buffer;
-		},
-		unrender: function(context, buffer){
-			return buffer;
-		},
-		clone: function(buffer){
-			return new this.constructor(this.target.getExpression(), this.alias, this.nodelist.clone(buffer));
-		}
-	});
-
-	dojo.mixin(ddtm, {
-		comment: function(parser, token){
-			// summary: Ignore everything between {% comment %} and {% endcomment %}
-			parser.skip_past("endcomment");
-			return dd._noOpNode;
-		},
-		debug: function(parser, token){
-			// summary: Output the current context, maybe add more stuff later.
-			return new ddtm.DebugNode(parser.create_text_node());
-		},
-		filter: function(parser, token){
-			// summary: Filter the contents of the blog through variable filters.
-			var rest = token.contents.split(null, 1)[1];
-			var varnode = parser.create_variable_node("var|" + rest);
-			var nodelist = parser.parse(["endfilter"]);
-			parser.next_token();
-			return new ddtm.FilterNode(varnode, nodelist);
-		},
-		firstof: function(parser, token){
-			var parts = token.split_contents().slice(1);
-			if(!parts.length){
-				throw new Error("'firstof' statement requires at least one argument");
-			}
-			return new ddtm.FirstOfNode(parts, parser.create_text_node());
-		},
-		spaceless: function(parser, token){
-			var nodelist = parser.parse(["endspaceless"]);
-			parser.delete_first_token();
-			return new ddtm.SpacelessNode(nodelist, parser.create_text_node());
-		},
-		templatetag: function(parser, token){
-			var parts = token.contents.split();
-			if(parts.length != 2){
-				throw new Error("'templatetag' statement takes one argument");
-			}
-			var tag = parts[1];
-			var mapping = ddtm.TemplateTagNode.prototype.mapping;
-			if(!mapping[tag]){
-				var keys = [];
-				for(var key in mapping){
-					keys.push(key);
-				}
-				throw new Error("Invalid templatetag argument: '" + tag + "'. Must be one of: " + keys.join(", "));
-			}
-			return new ddtm.TemplateTagNode(tag, parser.create_text_node());
-		},
-		widthratio: function(parser, token){
-			var parts = token.contents.split();
-			if(parts.length != 4){
-				throw new Error("widthratio takes three arguments");
-			}
-			var width = +parts[3];
-			if(typeof width != "number"){
-				throw new Error("widthratio final argument must be an integer");
-			}
-			return new ddtm.WidthRatioNode(parts[1], parts[2], width, parser.create_text_node());
-		},
-		with_: function(parser, token){
-			var parts = token.split_contents();
-			if(parts.length != 4 || parts[2] != "as"){
-				throw new Error("do_width expected format as 'with value as name'");
-			}
-			var nodelist = parser.parse(["endwith"]);
-			parser.next_token();
-			return new ddtm.WithNode(parts[1], parts[3], nodelist);
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.dtl.ext-dojo.NodeList"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.dtl.ext-dojo.NodeList"] = true;
-dojo.provide("dojox.dtl.ext-dojo.NodeList");
-
-
-dojo.extend(dojo.NodeList, {
-	dtl: function(template, context){
-		// template: dojox.dtl.__StringArgs|String
-		//		The template string or location
-		// context: dojox.dtl.__ObjectArgs|Object
-		//		The context object or location
-		var d = dojox.dtl;
-
-		var self = this;
-		var render = function(template, context){
-			var content = template.render(new d._Context(context));
-			self.forEach(function(node){
-				node.innerHTML = content;
-			});
-		}
-
-		d.text._resolveTemplateArg(template).addCallback(function(templateString){
-			template = new d.Template(templateString);
-			d.text._resolveContextArg(context).addCallback(function(context){
-				render(template, context);
-			});
-		});
-
-		return this;
-	}
-});
-
-}
-
diff --git a/dojox/dtl/Context.js b/dojox/dtl/Context.js
index 28af49c..01bfd3c 100644
--- a/dojox/dtl/Context.js
+++ b/dojox/dtl/Context.js
@@ -1,63 +1,69 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.Context"]){
-dojo._hasResource["dojox.dtl.Context"]=true;
 dojo.provide("dojox.dtl.Context");
 dojo.require("dojox.dtl._base");
-dojox.dtl.Context=dojo.extend(function(_1){
-this._this={};
-dojox.dtl._Context.call(this,_1);
-},dojox.dtl._Context.prototype,{getKeys:function(){
-var _2=[];
-for(var _3 in this){
-if(this.hasOwnProperty(_3)&&_3!="_dicts"&&_3!="_this"){
-_2.push(_3);
-}
-}
-return _2;
-},extend:function(_4){
-return dojo.delegate(this,_4);
-},filter:function(_5){
-var _6=new dojox.dtl.Context();
-var _7=[];
-var i,_8;
-if(_5 instanceof dojox.dtl.Context){
-_7=_5.getKeys();
-}else{
-if(typeof _5=="object"){
-for(var _9 in _5){
-_7.push(_9);
-}
-}else{
-for(i=0;_8=arguments[i];i++){
-if(typeof _8=="string"){
-_7.push(_8);
-}
-}
-}
-}
-for(i=0,_9;_9=_7[i];i++){
-_6[_9]=this[_9];
-}
-return _6;
-},setThis:function(_a){
-this._this=_a;
-},getThis:function(){
-return this._this;
-},hasKey:function(_b){
-if(typeof this[_b]!="undefined"){
-return true;
-}
-for(var i=0,_c;_c=this._dicts[i];i++){
-if(typeof _c[_b]!="undefined"){
-return true;
-}
-}
-return false;
-}});
-}
+
+dojox.dtl.Context = dojo.extend(function(dict){
+	this._this = {};
+	dojox.dtl._Context.call(this, dict);
+}, dojox.dtl._Context.prototype,
+{
+	getKeys: function(){
+		var keys = [];
+		for(var key in this){
+			if(this.hasOwnProperty(key) && key != "_this"){
+				keys.push(key);
+			}
+		}
+		return keys;
+	},
+	extend: function(/*dojox.dtl.Context|Object*/ obj){
+		// summary: Returns a clone of this context object, with the items from the
+		//		passed objecct mixed in.
+		return  dojo.delegate(this, obj);
+	},
+	filter: function(/*dojox.dtl.Context|Object|String...*/ filter){
+		// summary: Returns a clone of this context, only containing the items
+		//		defined in the filter.
+		var context = new dojox.dtl.Context();
+		var keys = [];
+		var i, arg;
+		if(filter instanceof dojox.dtl.Context){
+			keys = filter.getKeys();
+		}else if(typeof filter == "object"){
+			for(var key in filter){
+				keys.push(key);
+			}
+		}else{
+			for(i = 0; arg = arguments[i]; i++){
+				if(typeof arg == "string"){
+					keys.push(arg);
+				}
+			}
+		}
+
+		for(i = 0, key; key = keys[i]; i++){
+			context[key] = this[key];
+		}
+
+		return context;
+	},
+	setThis: function(/*Object*/ _this){
+		this._this = _this;
+	},
+	getThis: function(){
+		return this._this;
+	},
+	hasKey: function(key){
+		if(this._getter){
+			var got = this._getter(key);
+			if(typeof got != "undefined"){
+				return true;
+			}
+		}
+
+		if(typeof this[key] != "undefined"){
+			return true;
+		}
+
+		return false;
+	}
+});
\ No newline at end of file
diff --git a/dojox/dtl/DomInline.js b/dojox/dtl/DomInline.js
index 9765ac5..a14fb53 100644
--- a/dojox/dtl/DomInline.js
+++ b/dojox/dtl/DomInline.js
@@ -1,35 +1,36 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.DomInline"]){
-dojo._hasResource["dojox.dtl.DomInline"]=true;
 dojo.provide("dojox.dtl.DomInline");
 dojo.require("dojox.dtl.dom");
+
 dojo.require("dijit._Widget");
-dojox.dtl.DomInline=dojo.extend(function(_1,_2){
-this.create(_1,_2);
-},dijit._Widget.prototype,{context:null,render:function(_3){
-this.context=_3||this.context;
-this.postMixInProperties();
-var _4=this.template.render(this.context).getRootNode();
-if(_4!=this.containerNode){
-this.containerNode.parentNode.replaceChild(_4,this.containerNode);
-this.containerNode=_4;
-}
-},declaredClass:"dojox.dtl.Inline",buildRendering:function(){
-var _5=this.domNode=document.createElement("div");
-this.containerNode=_5.appendChild(document.createElement("div"));
-var _6=this.srcNodeRef;
-if(_6.parentNode){
-_6.parentNode.replaceChild(_5,_6);
-}
-this.template=new dojox.dtl.DomTemplate(dojo.trim(_6.text),true);
-this.render();
-},postMixInProperties:function(){
-this.context=(this.context.get===dojox.dtl._Context.prototype.get)?this.context:new dojox.dtl.Context(this.context);
-}});
-}
+
+dojox.dtl.DomInline = dojo.extend(function(args, node){
+	this.create(args, node);
+},
+dijit._Widget.prototype,
+{
+	context: null,
+	render: function(/*dojox.dtl.Context?*/ context){
+		this.context = context || this.context;
+		this.postMixInProperties();
+		var root = this.template.render(this.context).getRootNode();
+		if(root != this.containerNode){
+			this.containerNode.parentNode.replaceChild(root, this.containerNode);
+			this.containerNode = root;
+		}
+	},
+	declaredClass: "dojox.dtl.Inline",
+	buildRendering: function(){
+		var div = this.domNode = document.createElement("div");
+		this.containerNode = div.appendChild(document.createElement("div"));
+		var node = this.srcNodeRef;
+		if(node.parentNode){
+			node.parentNode.replaceChild(div, node);
+		}
+
+		this.template = new dojox.dtl.DomTemplate(dojo.trim(node.text), true);
+		this.render();
+	},
+	postMixInProperties: function(){
+		this.context = (this.context.get === dojox.dtl._Context.prototype.get) ? this.context : new dojox.dtl.Context(this.context);
+	}
+});
\ No newline at end of file
diff --git a/dojox/dtl/HtmlInline.js b/dojox/dtl/HtmlInline.js
index 106abbb..0c135d0 100644
--- a/dojox/dtl/HtmlInline.js
+++ b/dojox/dtl/HtmlInline.js
@@ -1,15 +1,5 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.HtmlInline"]){
-dojo._hasResource["dojox.dtl.HtmlInline"]=true;
 dojo.provide("dojox.dtl.HtmlInline");
 dojo.require("dojox.dtl.DomInline");
-dojo.deprecated("dojox.dtl.html","All packages and classes in dojox.dtl that start with Html or html have been renamed to Dom or dom");
-dojox.dtl.HtmlInline=dojox.dtl.DomInline;
-dojox.dtl.HtmlInline.prototype.declaredClass="dojox.dtl.HtmlInline";
-}
+dojo.deprecated("dojox.dtl.html", "All packages and classes in dojox.dtl that start with Html or html have been renamed to Dom or dom");
+dojox.dtl.HtmlInline = dojox.dtl.DomInline;
+dojox.dtl.HtmlInline.prototype.declaredClass = "dojox.dtl.HtmlInline";
\ No newline at end of file
diff --git a/dojox/dtl/Inline.js b/dojox/dtl/Inline.js
index 1ad27c1..105a53e 100644
--- a/dojox/dtl/Inline.js
+++ b/dojox/dtl/Inline.js
@@ -1,31 +1,32 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.Inline"]){
-dojo._hasResource["dojox.dtl.Inline"]=true;
 dojo.provide("dojox.dtl.Inline");
 dojo.require("dojox.dtl._base");
+
 dojo.require("dijit._Widget");
-dojox.dtl.Inline=dojo.extend(function(_1,_2){
-this.create(_1,_2);
-},dijit._Widget.prototype,{context:null,render:function(_3){
-this.context=_3||this.context;
-this.postMixInProperties();
-dojo.query("*",this.domNode).orphan();
-this.domNode.innerHTML=this.template.render(this.context);
-},declaredClass:"dojox.dtl.Inline",buildRendering:function(){
-var _4=this.domNode=document.createElement("div");
-var _5=this.srcNodeRef;
-if(_5.parentNode){
-_5.parentNode.replaceChild(_4,_5);
-}
-this.template=new dojox.dtl.Template(dojo.trim(_5.text),true);
-this.render();
-},postMixInProperties:function(){
-this.context=(this.context.get===dojox.dtl._Context.prototype.get)?this.context:new dojox.dtl._Context(this.context);
-}});
-}
+
+dojox.dtl.Inline = dojo.extend(function(args, node){
+	this.create(args, node);
+},
+dijit._Widget.prototype,
+{
+	context: null,
+	render: function(/*Object|dojox.dtl.Context?*/ context){
+		this.context = context || this.context;
+		this.postMixInProperties();
+		dojo.query("*", this.domNode).orphan();
+		this.domNode.innerHTML = this.template.render(this.context);
+	},
+	declaredClass: "dojox.dtl.Inline",
+	buildRendering: function(){
+		var div = this.domNode = document.createElement("div");
+		var node = this.srcNodeRef;
+		if(node.parentNode){
+			node.parentNode.replaceChild(div, node);
+		}
+
+		this.template = new dojox.dtl.Template(dojo.trim(node.text), true);
+		this.render();
+	},
+	postMixInProperties: function(){
+		this.context = (this.context.get === dojox.dtl._Context.prototype.get) ? this.context : new dojox.dtl._Context(this.context);
+	}
+});
\ No newline at end of file
diff --git a/dojox/dtl/_DomTemplated.js b/dojox/dtl/_DomTemplated.js
index 62875d3..f09fa61 100644
--- a/dojox/dtl/_DomTemplated.js
+++ b/dojox/dtl/_DomTemplated.js
@@ -1,63 +1,80 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl._DomTemplated"]){
-dojo._hasResource["dojox.dtl._DomTemplated"]=true;
 dojo.provide("dojox.dtl._DomTemplated");
+
 dojo.require("dijit._Templated");
 dojo.require("dojox.dtl.dom");
 dojo.require("dojox.dtl.render.dom");
 dojo.require("dojox.dtl.contrib.dijit");
-dojox.dtl._DomTemplated=function(){
+
+dojox.dtl._DomTemplated = function(){};
+dojox.dtl._DomTemplated.prototype = {
+	_dijitTemplateCompat: false,
+	buildRendering: function(){
+		//	summary:
+		//		Construct the UI for this widget, setting this.domNode.
+
+		//render needs a domNode to work with
+		this.domNode = this.srcNodeRef;
+
+		if(!this._render){
+			var ddcd = dojox.dtl.contrib.dijit;
+			var old = ddcd.widgetsInTemplate;
+			ddcd.widgetsInTemplate = this.widgetsInTemplate;
+			this.template = this.template || this._getCachedTemplate(this.templatePath, this.templateString);
+			this._render = new dojox.dtl.render.dom.Render(this.domNode, this.template);
+			ddcd.widgetsInTemplate = old;
+		}
+
+		var context = this._getContext();
+		if(!this._created){
+			delete context._getter;
+		}
+		this.render(context);
+
+		this.domNode = this.template.getRootNode();
+		if(this.srcNodeRef && this.srcNodeRef.parentNode){
+			dojo.destroy(this.srcNodeRef);
+			delete this.srcNodeRef;
+		}
+	},
+	setTemplate: function(/*String|dojo._Url*/ template, /*dojox.dtl.Context?*/ context){
+		// summary:
+		//		Quickly switch between templated by location
+		if(dojox.dtl.text._isTemplate(template)){
+			this.template = this._getCachedTemplate(null, template);
+		}else{
+			this.template = this._getCachedTemplate(template);
+		}
+		this.render(context);
+	},
+	render: function(/*dojox.dtl.Context?*/ context, /*dojox.dtl.DomTemplate?*/ tpl){
+		if(tpl){
+			this.template = tpl;
+		}
+		this._render.render(this._getContext(context), this.template);
+	},
+	_getContext: function(context){
+		if (!(context instanceof dojox.dtl.Context)) {
+			context = false;
+		}
+		context = context || new dojox.dtl.Context(this);
+		context.setThis(this);
+		return context;
+	},
+	_getCachedTemplate: function(templatePath, templateString){
+		if(!this._templates){
+			this._templates = {};
+		}
+		var key = templateString || templatePath.toString();
+		var tmplts = this._templates;
+		if(tmplts[key]){
+			return tmplts[key];
+		}
+		return (tmplts[key] = new dojox.dtl.DomTemplate(
+			dijit._Templated.getCachedTemplate(
+				templatePath,
+				templateString,
+				true
+			)
+		));
+	}
 };
-dojox.dtl._DomTemplated.prototype={_dijitTemplateCompat:false,buildRendering:function(){
-this.domNode=this.srcNodeRef;
-if(!this._render){
-var _1=dojox.dtl.contrib.dijit;
-var _2=_1.widgetsInTemplate;
-_1.widgetsInTemplate=this.widgetsInTemplate;
-this.template=this.template||this._getCachedTemplate(this.templatePath,this.templateString);
-this._render=new dojox.dtl.render.dom.Render(this.domNode,this.template);
-_1.widgetsInTemplate=_2;
-}
-this.render();
-this.domNode=this.template.getRootNode();
-if(this.srcNodeRef&&this.srcNodeRef.parentNode){
-dojo.destroy(this.srcNodeRef);
-delete this.srcNodeRef;
-}
-},setTemplate:function(_3,_4){
-if(dojox.dtl.text._isTemplate(_3)){
-this.template=this._getCachedTemplate(null,_3);
-}else{
-this.template=this._getCachedTemplate(_3);
-}
-this.render(_4);
-},render:function(_5,_6){
-if(_6){
-this.template=_6;
-}
-this._render.render(this._getContext(_5),this.template);
-},_getContext:function(_7){
-if(!(_7 instanceof dojox.dtl.Context)){
-_7=false;
-}
-_7=_7||new dojox.dtl.Context(this);
-_7.setThis(this);
-return _7;
-},_getCachedTemplate:function(_8,_9){
-if(!this._templates){
-this._templates={};
-}
-var _a=_9||_8.toString();
-var _b=this._templates;
-if(_b[_a]){
-return _b[_a];
-}
-return (_b[_a]=new dojox.dtl.DomTemplate(dijit._Templated.getCachedTemplate(_8,_9,true)));
-}};
-}
diff --git a/dojox/dtl/_HtmlTemplated.js b/dojox/dtl/_HtmlTemplated.js
index fc87194..7efdb2e 100644
--- a/dojox/dtl/_HtmlTemplated.js
+++ b/dojox/dtl/_HtmlTemplated.js
@@ -1,15 +1,5 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl._HtmlTemplated"]){
-dojo._hasResource["dojox.dtl._HtmlTemplated"]=true;
 dojo.provide("dojox.dtl._HtmlTemplated");
 dojo.require("dojox.dtl._DomTemplated");
-dojo.deprecated("dojox.dtl.html","All packages and classes in dojox.dtl that start with Html or html have been renamed to Dom or dom");
-dojox.dtl._HtmlTemplated=dojox.dtl._DomTemplated;
-dojox.dtl._HtmlTemplated.prototype.declaredClass="dojox.dtl._HtmlTemplated";
-}
+dojo.deprecated("dojox.dtl.html", "All packages and classes in dojox.dtl that start with Html or html have been renamed to Dom or dom");
+dojox.dtl._HtmlTemplated = dojox.dtl._DomTemplated;
+dojox.dtl._HtmlTemplated.prototype.declaredClass = "dojox.dtl._HtmlTemplated";
\ No newline at end of file
diff --git a/dojox/dtl/_Templated.js b/dojox/dtl/_Templated.js
index 9f4e810..983a3f5 100644
--- a/dojox/dtl/_Templated.js
+++ b/dojox/dtl/_Templated.js
@@ -1,71 +1,127 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl._Templated"]){
-dojo._hasResource["dojox.dtl._Templated"]=true;
 dojo.provide("dojox.dtl._Templated");
 dojo.require("dijit._Templated");
 dojo.require("dojox.dtl._base");
-dojo.declare("dojox.dtl._Templated",dijit._Templated,{_dijitTemplateCompat:false,buildRendering:function(){
-var _1;
-if(this.domNode&&!this._template){
-return;
-}
-if(!this._template){
-var t=this.getCachedTemplate(this.templatePath,this.templateString,this._skipNodeCache);
-if(t instanceof dojox.dtl.Template){
-this._template=t;
-}else{
-_1=t;
-}
-}
-if(!_1){
-var _2=dojo._toDom(this._template.render(new dojox.dtl._Context(this)));
-if(_2.nodeType!==1&&_2.nodeType!==3){
-for(var i=0,l=_2.childNodes.length;i<l;++i){
-_1=_2.childNodes[i];
-if(_1.nodeType==1){
-break;
-}
-}
-}else{
-_1=_2;
-}
-}
-this._attachTemplateNodes(_1);
-if(this.widgetsInTemplate){
-var _3=dojo.parser.parse(_1);
-this._attachTemplateNodes(_3,function(n,p){
-return n[p];
+
+dojo.declare("dojox.dtl._Templated", dijit._Templated, {
+	_dijitTemplateCompat: false,
+	buildRendering: function(){
+		var node;
+
+		if(this.domNode && !this._template){
+			return;
+		}
+
+		if(!this._template){
+			var t = this.getCachedTemplate(
+				this.templatePath,
+				this.templateString,
+				this._skipNodeCache
+			);
+			if(t instanceof dojox.dtl.Template) {
+				this._template = t;
+			}else{
+				node = t;
+			}
+		}
+		if(!node){
+			var context = new dojox.dtl._Context(this);
+			if(!this._created){
+				delete context._getter;
+			}
+			var nodes = dojo._toDom(
+				this._template.render(context)
+			);
+			// TODO: is it really necessary to look for the first node?
+			if(nodes.nodeType !== 1 && nodes.nodeType !== 3){
+				// nodes.nodeType === 11
+				// the node is a document fragment
+				for(var i = 0, l = nodes.childNodes.length; i < l; ++i){
+					node = nodes.childNodes[i];
+					if(node.nodeType == 1){
+						break;
+					}
+				}
+			}else{
+				// the node is an element or a text
+				node = nodes;
+			}
+		}
+
+		this._attachTemplateNodes(node);
+
+		if(this.widgetsInTemplate){
+			//Make sure dojoType is used for parsing widgets in template.
+			//The dojo.parser.query could be changed from multiversion support.
+			var parser = dojo.parser, qry, attr;
+			if(parser._query != "[dojoType]"){
+				qry = parser._query;
+				attr = parser._attrName;
+				parser._query = "[dojoType]";
+				parser._attrName = "dojoType";
+			}
+
+			//Store widgets that we need to start at a later point in time
+			var cw = (this._startupWidgets = dojo.parser.parse(node, {
+				noStart: !this._earlyTemplatedStartup,
+				inherited: {dir: this.dir, lang: this.lang}
+			}));
+
+			//Restore the query. 
+			if(qry){
+				parser._query = qry;
+				parser._attrName = attr;
+			}
+
+			this._supportingWidgets = dijit.findWidgets(node);
+
+			this._attachTemplateNodes(cw, function(n,p){
+				return n[p];
+			});
+		}
+
+		if(this.domNode){
+			dojo.place(node, this.domNode, "before");
+			this.destroyDescendants();
+			dojo.destroy(this.domNode);
+		}
+		this.domNode = node;
+
+		this._fillContent(this.srcNodeRef);
+	},
+	_templateCache: {},
+	getCachedTemplate: function(templatePath, templateString, alwaysUseString){
+		// summary:
+		//		Layer for dijit._Templated.getCachedTemplate
+		var tmplts = this._templateCache;
+		var key = templateString || templatePath;
+		if(tmplts[key]){
+			return tmplts[key];
+		}
+
+		templateString = dojo.string.trim(templateString || dojo.cache(templatePath, {sanitize: true}));
+
+		if(	this._dijitTemplateCompat && 
+			(alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g))
+		){
+			templateString = this._stringRepl(templateString);
+		}
+
+		// If we always use a string, or find no variables, just store it as a node
+		if(alwaysUseString || !templateString.match(/\{[{%]([^\}]+)[%}]\}/g)){
+			return tmplts[key] = dojo._toDom(templateString);
+		}else{
+			return tmplts[key] = new dojox.dtl.Template(templateString);
+		}
+	},
+	render: function(){
+		this.buildRendering();
+	},
+	startup: function(){
+		dojo.forEach(this._startupWidgets, function(w){
+			if(w && !w._started && w.startup){
+				w.startup();
+			}
+		});
+		this.inherited(arguments);
+	}
 });
-}
-if(this.domNode){
-dojo.place(_1,this.domNode,"before");
-this.destroyDescendants();
-dojo.destroy(this.domNode);
-}
-this.domNode=_1;
-this._fillContent(this.srcNodeRef);
-},_templateCache:{},getCachedTemplate:function(_4,_5,_6){
-var _7=this._templateCache;
-var _8=_5||_4;
-if(_7[_8]){
-return _7[_8];
-}
-_5=dojo.string.trim(_5||dojo.cache(_4,{sanitize:true}));
-if(this._dijitTemplateCompat&&(_6||_5.match(/\$\{([^\}]+)\}/g))){
-_5=this._stringRepl(_5);
-}
-if(_6||!_5.match(/\{[{%]([^\}]+)[%}]\}/g)){
-return _7[_8]=dojo._toDom(_5);
-}else{
-return _7[_8]=new dojox.dtl.Template(_5);
-}
-},render:function(){
-this.buildRendering();
-}});
-}
diff --git a/dojox/dtl/_base.js b/dojox/dtl/_base.js
index b890ab3..6838bda 100644
--- a/dojox/dtl/_base.js
+++ b/dojox/dtl/_base.js
@@ -1,574 +1,710 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl._base"]){
-dojo._hasResource["dojox.dtl._base"]=true;
 dojo.provide("dojox.dtl._base");
+
 dojo.require("dojox.string.Builder");
 dojo.require("dojox.string.tokenize");
+
 dojo.experimental("dojox.dtl");
+
 (function(){
-var dd=dojox.dtl;
-dd.TOKEN_BLOCK=-1;
-dd.TOKEN_VAR=-2;
-dd.TOKEN_COMMENT=-3;
-dd.TOKEN_TEXT=3;
-dd._Context=dojo.extend(function(_1){
-dojo._mixin(this,_1||{});
-this._dicts=[];
-},{push:function(){
-var _2=this;
-var _3=dojo.delegate(this);
-_3.pop=function(){
-return _2;
-};
-return _3;
-},pop:function(){
-throw new Error("pop() called on empty Context");
-},get:function(_4,_5){
-if(typeof this[_4]!="undefined"){
-return this._normalize(this[_4]);
-}
-for(var i=0,_6;_6=this._dicts[i];i++){
-if(typeof _6[_4]!="undefined"){
-return this._normalize(_6[_4]);
-}
-}
-return _5;
-},_normalize:function(_7){
-if(_7 instanceof Date){
-_7.year=_7.getFullYear();
-_7.month=_7.getMonth()+1;
-_7.day=_7.getDate();
-_7.date=_7.year+"-"+("0"+_7.month).slice(-2)+"-"+("0"+_7.day).slice(-2);
-_7.hour=_7.getHours();
-_7.minute=_7.getMinutes();
-_7.second=_7.getSeconds();
-_7.microsecond=_7.getMilliseconds();
-}
-return _7;
-},update:function(_8){
-var _9=this.push();
-if(_8){
-dojo._mixin(this,_8);
-}
-return _9;
-}});
-var _a=/("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+)/g;
-var _b=/\s+/g;
-var _c=function(_d,_e){
-_d=_d||_b;
-if(!(_d instanceof RegExp)){
-_d=new RegExp(_d,"g");
-}
-if(!_d.global){
-throw new Error("You must use a globally flagged RegExp with split "+_d);
-}
-_d.exec("");
-var _f,_10=[],_11=0,i=0;
-while(_f=_d.exec(this)){
-_10.push(this.slice(_11,_d.lastIndex-_f[0].length));
-_11=_d.lastIndex;
-if(_e&&(++i>_e-1)){
-break;
-}
-}
-_10.push(this.slice(_11));
-return _10;
-};
-dd.Token=function(_12,_13){
-this.token_type=_12;
-this.contents=new String(dojo.trim(_13));
-this.contents.split=_c;
-this.split=function(){
-return String.prototype.split.apply(this.contents,arguments);
-};
-};
-dd.Token.prototype.split_contents=function(_14){
-var bit,_15=[],i=0;
-_14=_14||999;
-while(i++<_14&&(bit=_a.exec(this.contents))){
-bit=bit[0];
-if(bit.charAt(0)=="\""&&bit.slice(-1)=="\""){
-_15.push("\""+bit.slice(1,-1).replace("\\\"","\"").replace("\\\\","\\")+"\"");
-}else{
-if(bit.charAt(0)=="'"&&bit.slice(-1)=="'"){
-_15.push("'"+bit.slice(1,-1).replace("\\'","'").replace("\\\\","\\")+"'");
-}else{
-_15.push(bit);
-}
-}
-}
-return _15;
-};
-var ddt=dd.text={_get:function(_16,_17,_18){
-var _19=dd.register.get(_16,_17.toLowerCase(),_18);
-if(!_19){
-if(!_18){
-throw new Error("No tag found for "+_17);
-}
-return null;
-}
-var fn=_19[1];
-var _1a=_19[2];
-var _1b;
-if(fn.indexOf(":")!=-1){
-_1b=fn.split(":");
-fn=_1b.pop();
-}
-dojo["require"](_1a);
-var _1c=dojo.getObject(_1a);
-return _1c[fn||_17]||_1c[_17+"_"]||_1c[fn+"_"];
-},getTag:function(_1d,_1e){
-return ddt._get("tag",_1d,_1e);
-},getFilter:function(_1f,_20){
-return ddt._get("filter",_1f,_20);
-},getTemplate:function(_21){
-return new dd.Template(ddt.getTemplateString(_21));
-},getTemplateString:function(_22){
-return dojo._getText(_22.toString())||"";
-},_resolveLazy:function(_23,_24,_25){
-if(_24){
-if(_25){
-return dojo.fromJson(dojo._getText(_23))||{};
-}else{
-return dd.text.getTemplateString(_23);
-}
-}else{
-return dojo.xhrGet({handleAs:(_25)?"json":"text",url:_23});
-}
-},_resolveTemplateArg:function(arg,_26){
-if(ddt._isTemplate(arg)){
-if(!_26){
-var d=new dojo.Deferred();
-d.callback(arg);
-return d;
-}
-return arg;
-}
-return ddt._resolveLazy(arg,_26);
-},_isTemplate:function(arg){
-return (typeof arg=="undefined")||(typeof arg=="string"&&(arg.match(/^\s*[<{]/)||arg.indexOf(" ")!=-1));
-},_resolveContextArg:function(arg,_27){
-if(arg.constructor==Object){
-if(!_27){
-var d=new dojo.Deferred;
-d.callback(arg);
-return d;
-}
-return arg;
-}
-return ddt._resolveLazy(arg,_27,true);
-},_re:/(?:\{\{\s*(.+?)\s*\}\}|\{%\s*(load\s*)?(.+?)\s*%\})/g,tokenize:function(str){
-return dojox.string.tokenize(str,ddt._re,ddt._parseDelims);
-},_parseDelims:function(_28,_29,tag){
-if(_28){
-return [dd.TOKEN_VAR,_28];
-}else{
-if(_29){
-var _2a=dojo.trim(tag).split(/\s+/g);
-for(var i=0,_2b;_2b=_2a[i];i++){
-dojo["require"](_2b);
-}
-}else{
-return [dd.TOKEN_BLOCK,tag];
-}
-}
-}};
-dd.Template=dojo.extend(function(_2c,_2d){
-var str=_2d?_2c:ddt._resolveTemplateArg(_2c,true)||"";
-var _2e=ddt.tokenize(str);
-var _2f=new dd._Parser(_2e);
-this.nodelist=_2f.parse();
-},{update:function(_30,_31){
-return ddt._resolveContextArg(_31).addCallback(this,function(_32){
-var _33=this.render(new dd._Context(_32));
-if(_30.forEach){
-_30.forEach(function(_34){
-_34.innerHTML=_33;
-});
-}else{
-dojo.byId(_30).innerHTML=_33;
-}
-return this;
-});
-},render:function(_35,_36){
-_36=_36||this.getBuffer();
-_35=_35||new dd._Context({});
-return this.nodelist.render(_35,_36)+"";
-},getBuffer:function(){
-dojo.require("dojox.string.Builder");
-return new dojox.string.Builder();
-}});
-var _37=/\{\{\s*(.+?)\s*\}\}/g;
-dd.quickFilter=function(str){
-if(!str){
-return new dd._NodeList();
-}
-if(str.indexOf("{%")==-1){
-return new dd._QuickNodeList(dojox.string.tokenize(str,_37,function(_38){
-return new dd._Filter(_38);
-}));
-}
-};
-dd._QuickNodeList=dojo.extend(function(_39){
-this.contents=_39;
-},{render:function(_3a,_3b){
-for(var i=0,l=this.contents.length;i<l;i++){
-if(this.contents[i].resolve){
-_3b=_3b.concat(this.contents[i].resolve(_3a));
-}else{
-_3b=_3b.concat(this.contents[i]);
-}
-}
-return _3b;
-},dummyRender:function(_3c){
-return this.render(_3c,dd.Template.prototype.getBuffer()).toString();
-},clone:function(_3d){
-return this;
-}});
-dd._Filter=dojo.extend(function(_3e){
-if(!_3e){
-throw new Error("Filter must be called with variable name");
-}
-this.contents=_3e;
-var _3f=this._cache[_3e];
-if(_3f){
-this.key=_3f[0];
-this.filters=_3f[1];
-}else{
-this.filters=[];
-dojox.string.tokenize(_3e,this._re,this._tokenize,this);
-this._cache[_3e]=[this.key,this.filters];
-}
-},{_cache:{},_re:/(?:^_\("([^\\"]*(?:\\.[^\\"])*)"\)|^"([^\\"]*(?:\\.[^\\"]*)*)"|^([a-zA-Z0-9_.]+)|\|(\w+)(?::(?:_\("([^\\"]*(?:\\.[^\\"])*)"\)|"([^\\"]*(?:\\.[^\\"]*)*)"|([a-zA-Z0-9_.]+)|'([^\\']*(?:\\.[^\\']*)*)'))?|^'([^\\']*(?:\\.[^\\']*)*)')/g,_values:{0:"\"",1:"\"",2:"",8:"\""},_args:{4:"\"",5:"\"",6:"",7:"'"},_tokenize:function(){
-var pos,arg;
-for(var i=0,has=[];i<arguments.length;i++){
-has[i]=(typeof arguments[i]!="undefined"&&typeof arguments[i]=="string"&&arguments[i]);
-}
-if(!this.key){
-for(pos in this._values){
-if(has[pos]){
-this.key=this._values[pos]+arguments[pos]+this._values[pos];
-break;
-}
-}
-}else{
-for(pos in this._args){
-if(has[pos]){
-var _40=arguments[pos];
-if(this._args[pos]=="'"){
-_40=_40.replace(/\\'/g,"'");
-}else{
-if(this._args[pos]=="\""){
-_40=_40.replace(/\\"/g,"\"");
-}
-}
-arg=[!this._args[pos],_40];
-break;
-}
-}
-var fn=ddt.getFilter(arguments[3]);
-if(!dojo.isFunction(fn)){
-throw new Error(arguments[3]+" is not registered as a filter");
-}
-this.filters.push([fn,arg]);
-}
-},getExpression:function(){
-return this.contents;
-},resolve:function(_41){
-if(typeof this.key=="undefined"){
-return "";
-}
-var str=this.resolvePath(this.key,_41);
-for(var i=0,_42;_42=this.filters[i];i++){
-if(_42[1]){
-if(_42[1][0]){
-str=_42[0](str,this.resolvePath(_42[1][1],_41));
-}else{
-str=_42[0](str,_42[1][1]);
-}
-}else{
-str=_42[0](str);
-}
-}
-return str;
-},resolvePath:function(_43,_44){
-var _45,_46;
-var _47=_43.charAt(0);
-var _48=_43.slice(-1);
-if(!isNaN(parseInt(_47))){
-_45=(_43.indexOf(".")==-1)?parseInt(_43):parseFloat(_43);
-}else{
-if(_47=="\""&&_47==_48){
-_45=_43.slice(1,-1);
-}else{
-if(_43=="true"){
-return true;
-}
-if(_43=="false"){
-return false;
-}
-if(_43=="null"||_43=="None"){
-return null;
-}
-_46=_43.split(".");
-_45=_44.get(_46[0]);
-if(dojo.isFunction(_45)){
-var _49=_44.getThis&&_44.getThis();
-if(_45.alters_data){
-_45="";
-}else{
-if(_49){
-_45=_45.call(_49);
-}else{
-_45="";
-}
-}
-}
-for(var i=1;i<_46.length;i++){
-var _4a=_46[i];
-if(_45){
-var _4b=_45;
-if(dojo.isObject(_45)&&_4a=="items"&&typeof _45[_4a]=="undefined"){
-var _4c=[];
-for(var key in _45){
-_4c.push([key,_45[key]]);
-}
-_45=_4c;
-continue;
-}
-if(_45.get&&dojo.isFunction(_45.get)&&_45.get.safe){
-_45=_45.get(_4a);
-}else{
-if(typeof _45[_4a]=="undefined"){
-_45=_45[_4a];
-break;
-}else{
-_45=_45[_4a];
-}
-}
-if(dojo.isFunction(_45)){
-if(_45.alters_data){
-_45="";
-}else{
-_45=_45.call(_4b);
-}
-}else{
-if(_45 instanceof Date){
-_45=dd._Context.prototype._normalize(_45);
-}
-}
-}else{
-return "";
-}
-}
-}
-}
-return _45;
-}});
-dd._TextNode=dd._Node=dojo.extend(function(obj){
-this.contents=obj;
-},{set:function(_4d){
-this.contents=_4d;
-return this;
-},render:function(_4e,_4f){
-return _4f.concat(this.contents);
-},isEmpty:function(){
-return !dojo.trim(this.contents);
-},clone:function(){
-return this;
-}});
-dd._NodeList=dojo.extend(function(_50){
-this.contents=_50||[];
-this.last="";
-},{push:function(_51){
-this.contents.push(_51);
-return this;
-},concat:function(_52){
-this.contents=this.contents.concat(_52);
-return this;
-},render:function(_53,_54){
-for(var i=0;i<this.contents.length;i++){
-_54=this.contents[i].render(_53,_54);
-if(!_54){
-throw new Error("Template must return buffer");
-}
-}
-return _54;
-},dummyRender:function(_55){
-return this.render(_55,dd.Template.prototype.getBuffer()).toString();
-},unrender:function(){
-return arguments[1];
-},clone:function(){
-return this;
-},rtrim:function(){
-while(1){
-i=this.contents.length-1;
-if(this.contents[i] instanceof dd._TextNode&&this.contents[i].isEmpty()){
-this.contents.pop();
-}else{
-break;
-}
-}
-return this;
-}});
-dd._VarNode=dojo.extend(function(str){
-this.contents=new dd._Filter(str);
-},{render:function(_56,_57){
-var str=this.contents.resolve(_56);
-if(!str.safe){
-str=dd._base.escape(""+str);
-}
-return _57.concat(str);
-}});
-dd._noOpNode=new function(){
-this.render=this.unrender=function(){
-return arguments[1];
-};
-this.clone=function(){
-return this;
-};
-};
-dd._Parser=dojo.extend(function(_58){
-this.contents=_58;
-},{i:0,parse:function(_59){
-var _5a={},_5b;
-_59=_59||[];
-for(var i=0;i<_59.length;i++){
-_5a[_59[i]]=true;
-}
-var _5c=new dd._NodeList();
-while(this.i<this.contents.length){
-_5b=this.contents[this.i++];
-if(typeof _5b=="string"){
-_5c.push(new dd._TextNode(_5b));
-}else{
-var _5d=_5b[0];
-var _5e=_5b[1];
-if(_5d==dd.TOKEN_VAR){
-_5c.push(new dd._VarNode(_5e));
-}else{
-if(_5d==dd.TOKEN_BLOCK){
-if(_5a[_5e]){
---this.i;
-return _5c;
-}
-var cmd=_5e.split(/\s+/g);
-if(cmd.length){
-cmd=cmd[0];
-var fn=ddt.getTag(cmd);
-if(fn){
-_5c.push(fn(this,new dd.Token(_5d,_5e)));
-}
-}
-}
-}
-}
-}
-if(_59.length){
-throw new Error("Could not find closing tag(s): "+_59.toString());
-}
-this.contents.length=0;
-return _5c;
-},next_token:function(){
-var _5f=this.contents[this.i++];
-return new dd.Token(_5f[0],_5f[1]);
-},delete_first_token:function(){
-this.i++;
-},skip_past:function(_60){
-while(this.i<this.contents.length){
-var _61=this.contents[this.i++];
-if(_61[0]==dd.TOKEN_BLOCK&&_61[1]==_60){
-return;
-}
-}
-throw new Error("Unclosed tag found when looking for "+_60);
-},create_variable_node:function(_62){
-return new dd._VarNode(_62);
-},create_text_node:function(_63){
-return new dd._TextNode(_63||"");
-},getTemplate:function(_64){
-return new dd.Template(_64);
-}});
-dd.register={_registry:{attributes:[],tags:[],filters:[]},get:function(_65,_66){
-var _67=dd.register._registry[_65+"s"];
-for(var i=0,_68;_68=_67[i];i++){
-if(typeof _68[0]=="string"){
-if(_68[0]==_66){
-return _68;
-}
-}else{
-if(_66.match(_68[0])){
-return _68;
-}
-}
-}
-},getAttributeTags:function(){
-var _69=[];
-var _6a=dd.register._registry.attributes;
-for(var i=0,_6b;_6b=_6a[i];i++){
-if(_6b.length==3){
-_69.push(_6b);
-}else{
-var fn=dojo.getObject(_6b[1]);
-if(fn&&dojo.isFunction(fn)){
-_6b.push(fn);
-_69.push(_6b);
-}
-}
-}
-return _69;
-},_any:function(_6c,_6d,_6e){
-for(var _6f in _6e){
-for(var i=0,fn;fn=_6e[_6f][i];i++){
-var key=fn;
-if(dojo.isArray(fn)){
-key=fn[0];
-fn=fn[1];
-}
-if(typeof key=="string"){
-if(key.substr(0,5)=="attr:"){
-var _70=fn;
-if(_70.substr(0,5)=="attr:"){
-_70=_70.slice(5);
-}
-dd.register._registry.attributes.push([_70.toLowerCase(),_6d+"."+_6f+"."+_70]);
-}
-key=key.toLowerCase();
-}
-dd.register._registry[_6c].push([key,fn,_6d+"."+_6f]);
-}
-}
-},tags:function(_71,_72){
-dd.register._any("tags",_71,_72);
-},filters:function(_73,_74){
-dd.register._any("filters",_73,_74);
-}};
-var _75=/&/g;
-var _76=/</g;
-var _77=/>/g;
-var _78=/'/g;
-var _79=/"/g;
-dd._base.escape=function(_7a){
-return dd.mark_safe(_7a.replace(_75,"&").replace(_76,"<").replace(_77,">").replace(_79,""").replace(_78,"'"));
-};
-dd._base.safe=function(_7b){
-if(typeof _7b=="string"){
-_7b=new String(_7b);
-}
-if(typeof _7b=="object"){
-_7b.safe=true;
-}
-return _7b;
-};
-dd.mark_safe=dd._base.safe;
-dd.register.tags("dojox.dtl.tag",{"date":["now"],"logic":["if","for","ifequal","ifnotequal"],"loader":["extends","block","include","load","ssi"],"misc":["comment","debug","filter","firstof","spaceless","templatetag","widthratio","with"],"loop":["cycle","ifchanged","regroup"]});
-dd.register.filters("dojox.dtl.filter",{"dates":["date","time","timesince","timeuntil"],"htmlstrings":["linebreaks","linebreaksbr","removetags","striptags"],"integers":["add","get_digit"],"lists":["dictsort","dictsortreversed","first","join","length","length_is","random","slice","unordered_list"],"logic":["default","default_if_none","divisibleby","yesno"],"misc":["filesizeformat","pluralize","phone2numeric","pprint"],"strings":["addslashes","capfirst","center","cut","fix_ampersands","flo [...]
-dd.register.filters("dojox.dtl",{"_base":["escape","safe"]});
+	var dd = dojox.dtl;
+
+	dd.TOKEN_BLOCK = -1;
+	dd.TOKEN_VAR = -2;
+	dd.TOKEN_COMMENT = -3;
+	dd.TOKEN_TEXT = 3;
+
+	dd._Context = dojo.extend(function(dict){
+		// summary: Pass one of these when rendering a template to tell the template what values to use.
+		if(dict){
+			dojo._mixin(this, dict);
+			if(dict.get){
+				// Preserve passed getter and restore prototype get
+				this._getter = dict.get;
+				delete this.get;
+			}
+		}
+	},
+	{
+		push: function(){
+			var last = this;
+			var context = dojo.delegate(this);
+			context.pop = function(){ return last; }
+			return context;
+		},
+		pop: function(){
+			throw new Error("pop() called on empty Context");
+		},
+		get: function(key, otherwise){
+			var n = this._normalize;
+
+			if(this._getter){
+				var got = this._getter(key);
+				if(typeof got != "undefined"){
+					return n(got);
+				}
+			}
+
+			if(typeof this[key] != "undefined"){
+				return n(this[key]);
+			}
+
+			return otherwise;
+		},
+		_normalize: function(value){
+			if(value instanceof Date){
+				value.year = value.getFullYear();
+				value.month = value.getMonth() + 1;
+				value.day = value.getDate();
+				value.date = value.year + "-" + ("0" + value.month).slice(-2) + "-" + ("0" + value.day).slice(-2);
+				value.hour = value.getHours();
+				value.minute = value.getMinutes();
+				value.second = value.getSeconds();
+				value.microsecond = value.getMilliseconds();
+			}
+			return value;
+		},
+		update: function(dict){
+			var context = this.push();
+			if(dict){
+				dojo._mixin(this, dict);
+			}
+			return context;
+		}
+	});
+
+	var smart_split_re = /("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+)/g;           
+	var split_re = /\s+/g;
+	var split = function(/*String|RegExp?*/ splitter, /*Integer?*/ limit){
+		splitter = splitter || split_re;
+		if(!(splitter instanceof RegExp)){
+			splitter = new RegExp(splitter, "g");
+		}
+		if(!splitter.global){
+			throw new Error("You must use a globally flagged RegExp with split " + splitter);
+		}
+		splitter.exec(""); // Reset the global
+
+		var part, parts = [], lastIndex = 0, i = 0;
+		while(part = splitter.exec(this)){
+			parts.push(this.slice(lastIndex, splitter.lastIndex - part[0].length));
+			lastIndex = splitter.lastIndex;
+			if(limit && (++i > limit - 1)){
+				break;
+			}
+		}
+		parts.push(this.slice(lastIndex));
+		return parts;
+	}
+
+	dd.Token = function(token_type, contents){
+		this.token_type = token_type;
+		this.contents = new String(dojo.trim(contents));
+		this.contents.split = split;
+		this.split = function(){
+			return String.prototype.split.apply(this.contents, arguments);
+		}
+	}
+	dd.Token.prototype.split_contents = function(/*Integer?*/ limit){
+		var bit, bits = [], i = 0;
+		limit = limit || 999;
+		while(i++ < limit && (bit = smart_split_re.exec(this.contents))){
+			bit = bit[0];
+			if(bit.charAt(0) == '"' && bit.slice(-1) == '"'){
+				bits.push('"' + bit.slice(1, -1).replace('\\"', '"').replace('\\\\', '\\') + '"');
+			}else if(bit.charAt(0) == "'" && bit.slice(-1) == "'"){
+				bits.push("'" + bit.slice(1, -1).replace("\\'", "'").replace('\\\\', '\\') + "'");
+			}else{
+				bits.push(bit);
+			}
+		}
+		return bits;
+	}
+
+	var ddt = dd.text = {
+		_get: function(module, name, errorless){
+			// summary: Used to find both tags and filters
+			var params = dd.register.get(module, name.toLowerCase(), errorless);
+			if(!params){
+				if(!errorless){
+					throw new Error("No tag found for " + name);
+				}
+				return null;
+			}
+
+			var fn = params[1];
+			var require = params[2];
+
+			var parts;
+			if(fn.indexOf(":") != -1){
+				parts = fn.split(":");
+				fn = parts.pop();
+			}
+
+			dojo["require"](require);
+
+			var parent = dojo.getObject(require);
+
+			return parent[fn || name] || parent[name + "_"] || parent[fn + "_"];
+		},
+		getTag: function(name, errorless){
+			return ddt._get("tag", name, errorless);
+		},
+		getFilter: function(name, errorless){
+			return ddt._get("filter", name, errorless);
+		},
+		getTemplate: function(file){
+			return new dd.Template(ddt.getTemplateString(file));
+		},
+		getTemplateString: function(file){
+			return dojo._getText(file.toString()) || "";
+		},
+		_resolveLazy: function(location, sync, json){
+			if(sync){
+				if(json){
+					return dojo.fromJson(dojo._getText(location)) || {};
+				}else{
+					return dd.text.getTemplateString(location);
+				}
+			}else{
+				return dojo.xhrGet({
+					handleAs: (json) ? "json" : "text",
+					url: location
+				});
+			}
+		},
+		_resolveTemplateArg: function(arg, sync){
+			if(ddt._isTemplate(arg)){
+				if(!sync){
+					var d = new dojo.Deferred();
+					d.callback(arg);
+					return d;
+				}
+				return arg;
+			}
+			return ddt._resolveLazy(arg, sync);
+		},
+		_isTemplate: function(arg){
+			return (typeof arg == "undefined") || (typeof arg == "string" && (arg.match(/^\s*[<{]/) || arg.indexOf(" ") != -1));
+		},
+		_resolveContextArg: function(arg, sync){
+			if(arg.constructor == Object){
+				if(!sync){
+					var d = new dojo.Deferred;
+					d.callback(arg);
+					return d;
+				}
+				return arg;
+			}
+			return ddt._resolveLazy(arg, sync, true);
+		},
+		_re: /(?:\{\{\s*(.+?)\s*\}\}|\{%\s*(load\s*)?(.+?)\s*%\})/g,
+		tokenize: function(str){
+			return dojox.string.tokenize(str, ddt._re, ddt._parseDelims);
+		},
+		_parseDelims: function(varr, load, tag){
+			if(varr){
+				return [dd.TOKEN_VAR, varr];
+			}else if(load){
+				var parts = dojo.trim(tag).split(/\s+/g);
+				for(var i = 0, part; part = parts[i]; i++){
+					dojo["require"](part);
+				}
+			}else{
+				return [dd.TOKEN_BLOCK, tag];
+			}
+		}
+	}
+
+	dd.Template = dojo.extend(function(/*String|dojo._Url*/ template, /*Boolean*/ isString){
+		// template:
+		//		The string or location of the string to
+		//		use as a template
+		var str = isString ? template : ddt._resolveTemplateArg(template, true) || "";
+		var tokens = ddt.tokenize(str);
+		var parser = new dd._Parser(tokens);
+		this.nodelist = parser.parse();
+	},
+	{
+		update: function(node, context){
+			// node: DOMNode|String|dojo.NodeList
+			//		A node reference or set of nodes
+			// context: dojo._Url|String|Object
+			//		The context object or location
+			return ddt._resolveContextArg(context).addCallback(this, function(contextObject){
+				var content = this.render(new dd._Context(contextObject));
+				if(node.forEach){
+					node.forEach(function(item){
+						item.innerHTML = content;
+					});
+				}else{
+					dojo.byId(node).innerHTML = content;
+				}
+				return this;
+			});
+		},
+		render: function(context, /*concatenatable?*/ buffer){
+			buffer = buffer || this.getBuffer();
+			context = context || new dd._Context({});
+			return this.nodelist.render(context, buffer) + "";
+		},
+		getBuffer: function(){
+			dojo.require("dojox.string.Builder");
+			return new dojox.string.Builder();
+		}
+	});
+
+	var qfRe = /\{\{\s*(.+?)\s*\}\}/g;
+	dd.quickFilter = function(str){
+		if(!str){
+			return new dd._NodeList();
+		}
+
+		if(str.indexOf("{%") == -1){
+			return new dd._QuickNodeList(dojox.string.tokenize(str, qfRe, function(token){
+				return new dd._Filter(token);
+			}));
+		}
+	}
+
+	dd._QuickNodeList = dojo.extend(function(contents){
+		this.contents = contents;
+	},
+	{
+		render: function(context, buffer){
+			for(var i=0, l=this.contents.length; i<l; i++){
+				if(this.contents[i].resolve){
+					buffer = buffer.concat(this.contents[i].resolve(context));
+				}else{
+					buffer = buffer.concat(this.contents[i]);
+				}
+			}
+			return buffer;
+		},
+		dummyRender: function(context){ return this.render(context, dd.Template.prototype.getBuffer()).toString(); },
+		clone: function(buffer){ return this; }
+	});
+
+	dd._Filter = dojo.extend(function(token){
+		// summary: Uses a string to find (and manipulate) a variable
+		if(!token) throw new Error("Filter must be called with variable name");
+		this.contents = token;
+
+		var cache = this._cache[token];
+		if(cache){
+			this.key = cache[0];
+			this.filters = cache[1];
+		}else{
+			this.filters = [];
+			dojox.string.tokenize(token, this._re, this._tokenize, this);
+			this._cache[token] = [this.key, this.filters];
+		}
+	},
+	{
+		_cache: {},
+		_re: /(?:^_\("([^\\"]*(?:\\.[^\\"])*)"\)|^"([^\\"]*(?:\\.[^\\"]*)*)"|^([a-zA-Z0-9_.]+)|\|(\w+)(?::(?:_\("([^\\"]*(?:\\.[^\\"])*)"\)|"([^\\"]*(?:\\.[^\\"]*)*)"|([a-zA-Z0-9_.]+)|'([^\\']*(?:\\.[^\\']*)*)'))?|^'([^\\']*(?:\\.[^\\']*)*)')/g,
+		_values: {
+			0: '"', // _("text")
+			1: '"', // "text"
+			2: "", // variable
+			8: '"' // 'text'
+		},
+		_args: {
+			4: '"', // :_("text")
+			5: '"', // :"text"
+			6: "", // :variable
+			7: "'"// :'text'
+		},
+		_tokenize: function(){
+			var pos, arg;
+
+			for(var i = 0, has = []; i < arguments.length; i++){
+				has[i] = (typeof arguments[i] != "undefined" && typeof arguments[i] == "string" && arguments[i]);
+			}
+
+			if(!this.key){
+				for(pos in this._values){
+					if(has[pos]){
+						this.key = this._values[pos] + arguments[pos] + this._values[pos];
+						break;
+					}
+				}
+			}else{
+				for(pos in this._args){
+					if(has[pos]){
+						var value = arguments[pos];
+						if(this._args[pos] == "'"){
+							value = value.replace(/\\'/g, "'");
+						}else if(this._args[pos] == '"'){
+							value = value.replace(/\\"/g, '"');
+						}
+						arg = [!this._args[pos], value];
+						break;
+					}
+				}
+				// Get a named filter
+				var fn = ddt.getFilter(arguments[3]);
+				if(!dojo.isFunction(fn)) throw new Error(arguments[3] + " is not registered as a filter");
+				this.filters.push([fn, arg]);
+			}
+		},
+		getExpression: function(){
+			return this.contents;
+		},
+		resolve: function(context){
+			if(typeof this.key == "undefined"){
+				return "";
+			}
+
+			var str = this.resolvePath(this.key, context);
+
+			for(var i = 0, filter; filter = this.filters[i]; i++){
+				// Each filter has the function in [0], a boolean in [1][0] of whether it's a variable or a string
+				// and [1][1] is either the variable name of the string content.
+				if(filter[1]){
+					if(filter[1][0]){
+						str = filter[0](str, this.resolvePath(filter[1][1], context));
+					}else{
+						str = filter[0](str, filter[1][1]);
+					}
+				}else{
+					str = filter[0](str);
+				}
+			}
+
+			return str;
+		},
+		resolvePath: function(path, context){
+			var current, parts;
+			var first = path.charAt(0);
+			var last = path.slice(-1);
+			if(!isNaN(parseInt(first))){
+				current = (path.indexOf(".") == -1) ? parseInt(path) : parseFloat(path);
+			}else if(first == '"' && first == last){
+				current = path.slice(1, -1);
+			}else{
+				if(path == "true"){ return true; }
+				if(path == "false"){ return false; }
+				if(path == "null" || path == "None"){ return null; }
+				parts = path.split(".");
+				current = context.get(parts[0]);
+
+				if(dojo.isFunction(current)){
+					var self = context.getThis && context.getThis();
+					if(current.alters_data){
+						current = "";
+					}else if(self){
+						current = current.call(self);
+					}else{
+						current = "";
+					}
+				}
+
+				for(var i = 1; i < parts.length; i++){
+					var part = parts[i];
+					if(current){
+						var base = current;
+						if(dojo.isObject(current) && part == "items" && typeof current[part] == "undefined"){
+							var items = [];
+							for(var key in current){
+								items.push([key, current[key]]);
+							}
+							current = items;
+							continue;
+						}
+
+						if(current.get && dojo.isFunction(current.get) && current.get.safe){
+							current = current.get(part);
+						}else if(typeof current[part] == "undefined"){
+							current = current[part];
+							break;
+						}else{
+							current = current[part];
+						}
+
+						if(dojo.isFunction(current)){
+							if(current.alters_data){
+								current = "";
+							}else{
+								current = current.call(base);
+							}
+						}else if(current instanceof Date){
+							current = dd._Context.prototype._normalize(current);
+						}
+					}else{
+						return "";
+					}
+				}
+			}
+			return current;
+		}
+	});
+
+	dd._TextNode = dd._Node = dojo.extend(function(/*Object*/ obj){
+		// summary: Basic catch-all node
+		this.contents = obj;
+	},
+	{
+		set: function(data){
+			this.contents = data;
+			return this;
+		},
+		render: function(context, buffer){
+			// summary: Adds content onto the buffer
+			return buffer.concat(this.contents);
+		},
+		isEmpty: function(){
+			return !dojo.trim(this.contents);
+		},
+		clone: function(){ return this; }
+	});
+
+	dd._NodeList = dojo.extend(function(/*Node[]*/ nodes){
+		// summary: Allows us to render a group of nodes
+		this.contents = nodes || [];
+		this.last = "";
+	},
+	{
+		push: function(node){
+			// summary: Add a new node to the list
+			this.contents.push(node);
+			return this;
+		},
+		concat: function(nodes){
+			this.contents = this.contents.concat(nodes);
+			return this;
+		},
+		render: function(context, buffer){
+			// summary: Adds all content onto the buffer
+			for(var i = 0; i < this.contents.length; i++){
+				buffer = this.contents[i].render(context, buffer);
+				if(!buffer) throw new Error("Template must return buffer");
+			}
+			return buffer;
+		},
+		dummyRender: function(context){
+			return this.render(context, dd.Template.prototype.getBuffer()).toString();
+		},
+		unrender: function(){ return arguments[1]; },
+		clone: function(){ return this; },
+		rtrim: function(){
+			while(1){
+				i = this.contents.length - 1;
+				if(this.contents[i] instanceof dd._TextNode && this.contents[i].isEmpty()){
+					this.contents.pop();
+				}else{
+					break;
+				}
+			}
+
+			return this;
+		}
+	});
+
+	dd._VarNode = dojo.extend(function(str){
+		// summary: A node to be processed as a variable
+		this.contents = new dd._Filter(str);
+	},
+	{
+		render: function(context, buffer){
+			var str = this.contents.resolve(context);
+			if(!str.safe){
+				str = dd._base.escape("" + str);
+			}
+			return buffer.concat(str);
+		}
+	});
+
+	dd._noOpNode = new function(){
+		// summary: Adds a no-op node. Useful in custom tags
+		this.render = this.unrender = function(){ return arguments[1]; }
+		this.clone = function(){ return this; }
+	}
+
+	dd._Parser = dojo.extend(function(tokens){
+		// summary: Parser used during initialization and for tag groups.
+		this.contents = tokens;
+	},
+	{
+		i: 0,
+		parse: function(/*Array?*/ stop_at){
+			// summary: Turns tokens into nodes
+			// description: Steps into tags are they're found. Blocks use the parse object
+			//		to find their closing tag (the stop_at array). stop_at is inclusive, it
+			//		returns the node that matched.
+			var terminators = {}, token;
+			stop_at = stop_at || [];
+			for(var i = 0; i < stop_at.length; i++){
+				terminators[stop_at[i]] = true;
+			}
+
+			var nodelist = new dd._NodeList();
+			while(this.i < this.contents.length){
+				token = this.contents[this.i++];
+				if(typeof token == "string"){
+					nodelist.push(new dd._TextNode(token));
+				}else{
+					var type = token[0];
+					var text = token[1];
+					if(type == dd.TOKEN_VAR){
+						nodelist.push(new dd._VarNode(text));
+					}else if(type == dd.TOKEN_BLOCK){
+						if(terminators[text]){
+							--this.i;
+							return nodelist;
+						}
+						var cmd = text.split(/\s+/g);
+						if(cmd.length){
+							cmd = cmd[0];
+							var fn = ddt.getTag(cmd);
+							if(fn){
+								nodelist.push(fn(this, new dd.Token(type, text)));
+							}
+						}
+					}
+				}
+			}
+
+			if(stop_at.length){
+				throw new Error("Could not find closing tag(s): " + stop_at.toString());
+			}
+
+			this.contents.length = 0;
+			return nodelist;
+		},
+		next_token: function(){
+			// summary: Returns the next token in the list.
+			var token = this.contents[this.i++];
+			return new dd.Token(token[0], token[1]);
+		},
+		delete_first_token: function(){
+			this.i++;
+		},
+		skip_past: function(endtag){
+			while(this.i < this.contents.length){
+				var token = this.contents[this.i++];
+				if(token[0] == dd.TOKEN_BLOCK && token[1] == endtag){
+					return;
+				}
+			}
+			throw new Error("Unclosed tag found when looking for " + endtag);
+		},
+		create_variable_node: function(expr){
+			return new dd._VarNode(expr);
+		},
+		create_text_node: function(expr){
+			return new dd._TextNode(expr || "");
+		},
+		getTemplate: function(file){
+			return new dd.Template(file);
+		}
+	});
+
+	dd.register = {
+		_registry: {
+			attributes: [],
+			tags: [],
+			filters: []
+		},
+		get: function(/*String*/ module, /*String*/ name){
+			var registry = dd.register._registry[module + "s"];
+			for(var i = 0, entry; entry = registry[i]; i++){
+				if(typeof entry[0] == "string"){
+					if(entry[0] == name){
+						return entry;
+					}
+				}else if(name.match(entry[0])){
+					return entry;
+				}
+			}
+		},
+		getAttributeTags: function(){
+			var tags = [];
+			var registry = dd.register._registry.attributes;
+			for(var i = 0, entry; entry = registry[i]; i++){
+				if(entry.length == 3){
+					tags.push(entry);
+				}else{
+					var fn = dojo.getObject(entry[1]);
+					if(fn && dojo.isFunction(fn)){
+						entry.push(fn);
+						tags.push(entry);
+					}
+				}
+			}
+			return tags;
+		},
+		_any: function(type, base, locations){
+			for(var path in locations){
+				for(var i = 0, fn; fn = locations[path][i]; i++){
+					var key = fn;
+					if(dojo.isArray(fn)){
+						key = fn[0];
+						fn = fn[1];
+					}
+					if(typeof key == "string"){
+						if(key.substr(0, 5) == "attr:"){
+							var attr = fn;
+							if(attr.substr(0, 5) == "attr:"){
+								attr = attr.slice(5);
+							}
+							dd.register._registry.attributes.push([attr.toLowerCase(), base + "." + path + "." + attr]);
+						}
+						key = key.toLowerCase()
+					}
+					dd.register._registry[type].push([
+						key,
+						fn,
+						base + "." + path
+					]);
+				}
+			}
+		},
+		tags: function(/*String*/ base, /*Object*/ locations){
+			dd.register._any("tags", base, locations);
+		},
+		filters: function(/*String*/ base, /*Object*/ locations){
+			dd.register._any("filters", base, locations);
+		}
+	}
+
+	var escapeamp = /&/g;
+	var escapelt = /</g;
+	var escapegt = />/g;
+	var escapeqt = /'/g;
+	var escapedblqt = /"/g;
+	dd._base.escape = function(value){
+		// summary: Escapes a string's HTML
+		return dd.mark_safe(value.replace(escapeamp, '&').replace(escapelt, '<').replace(escapegt, '>').replace(escapedblqt, '"').replace(escapeqt, '''));
+	}
+
+	dd._base.safe = function(value){
+		if(typeof value == "string"){
+			value = new String(value);
+		}
+		if(typeof value == "object"){
+			value.safe = true;
+		}
+		return value;
+	}
+	dd.mark_safe = dd._base.safe;
+
+	dd.register.tags("dojox.dtl.tag", {
+		"date": ["now"],
+		"logic": ["if", "for", "ifequal", "ifnotequal"],
+		"loader": ["extends", "block", "include", "load", "ssi"],
+		"misc": ["comment", "debug", "filter", "firstof", "spaceless", "templatetag", "widthratio", "with"],
+		"loop": ["cycle", "ifchanged", "regroup"]
+	});
+	dd.register.filters("dojox.dtl.filter", {
+		"dates": ["date", "time", "timesince", "timeuntil"],
+		"htmlstrings": ["linebreaks", "linebreaksbr", "removetags", "striptags"],
+		"integers": ["add", "get_digit"],
+		"lists": ["dictsort", "dictsortreversed", "first", "join", "length", "length_is", "random", "slice", "unordered_list"],
+		"logic": ["default", "default_if_none", "divisibleby", "yesno"],
+		"misc": ["filesizeformat", "pluralize", "phone2numeric", "pprint"],
+		"strings": ["addslashes", "capfirst", "center", "cut", "fix_ampersands", "floatformat", "iriencode", "linenumbers", "ljust", "lower", "make_list", "rjust", "slugify", "stringformat", "title", "truncatewords", "truncatewords_html", "upper", "urlencode", "urlize", "urlizetrunc", "wordcount", "wordwrap"]
+	});
+	dd.register.filters("dojox.dtl", {
+		"_base": ["escape", "safe"]
+	});
 })();
-}
diff --git a/dojox/dtl/contrib/data.js b/dojox/dtl/contrib/data.js
index 2b9ba94..3bc54f8 100644
--- a/dojox/dtl/contrib/data.js
+++ b/dojox/dtl/contrib/data.js
@@ -1,121 +1,158 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.contrib.data"]){
-dojo._hasResource["dojox.dtl.contrib.data"]=true;
 dojo.provide("dojox.dtl.contrib.data");
 dojo.require("dojox.dtl._base");
+
 (function(){
-var dd=dojox.dtl;
-var _1=dd.contrib.data;
-var _2=true;
-_1._BoundItem=dojo.extend(function(_3,_4){
-this.item=_3;
-this.store=_4;
-},{get:function(_5){
-var _6=this.store;
-var _7=this.item;
-if(_5=="getLabel"){
-return _6.getLabel(_7);
-}else{
-if(_5=="getAttributes"){
-return _6.getAttributes(_7);
-}else{
-if(_5=="getIdentity"){
-if(_6.getIdentity){
-return _6.getIdentity(_7);
-}
-return "Store has no identity API";
-}else{
-if(!_6.hasAttribute(_7,_5)){
-if(_5.slice(-1)=="s"){
-if(_2){
-_2=false;
-dojo.deprecated("You no longer need an extra s to call getValues, it can be figured out automatically");
-}
-_5=_5.slice(0,-1);
-}
-if(!_6.hasAttribute(_7,_5)){
-return;
-}
-}
-var _8=_6.getValues(_7,_5);
-if(!_8){
-return;
-}
-if(!dojo.isArray(_8)){
-return new _1._BoundItem(_8,_6);
-}
-_8=dojo.map(_8,function(_9){
-if(dojo.isObject(_9)&&_6.isItem(_9)){
-return new _1._BoundItem(_9,_6);
-}
-return _9;
-});
-_8.get=_1._get;
-return _8;
-}
-}
-}
-}});
-_1._BoundItem.prototype.get.safe=true;
-_1.BindDataNode=dojo.extend(function(_a,_b,_c,_d){
-this.items=_a&&new dd._Filter(_a);
-this.query=_b&&new dd._Filter(_b);
-this.store=new dd._Filter(_c);
-this.alias=_d;
-},{render:function(_e,_f){
-var _10=this.items&&this.items.resolve(_e);
-var _11=this.query&&this.query.resolve(_e);
-var _12=this.store.resolve(_e);
-if(!_12||!_12.getFeatures){
-throw new Error("data_bind didn't receive a store");
-}
-if(_11){
-var _13=false;
-_12.fetch({query:_11,sync:true,scope:this,onComplete:function(it){
-_13=true;
-_10=it;
-}});
-if(!_13){
-throw new Error("The bind_data tag only works with a query if the store executed synchronously");
-}
-}
-var _14=[];
-if(_10){
-for(var i=0,_15;_15=_10[i];i++){
-_14.push(new _1._BoundItem(_15,_12));
-}
-}
-_e[this.alias]=_14;
-return _f;
-},unrender:function(_16,_17){
-return _17;
-},clone:function(){
-return this;
-}});
-dojo.mixin(_1,{_get:function(key){
-if(this.length){
-return (this[0] instanceof _1._BoundItem)?this[0].get(key):this[0][key];
-}
-},bind_data:function(_18,_19){
-var _1a=_19.contents.split();
-if(_1a[2]!="to"||_1a[4]!="as"||!_1a[5]){
-throw new Error("data_bind expects the format: 'data_bind items to store as varName'");
-}
-return new _1.BindDataNode(_1a[1],null,_1a[3],_1a[5]);
-},bind_query:function(_1b,_1c){
-var _1d=_1c.contents.split();
-if(_1d[2]!="to"||_1d[4]!="as"||!_1d[5]){
-throw new Error("data_bind expects the format: 'bind_query query to store as varName'");
-}
-return new _1.BindDataNode(null,_1d[1],_1d[3],_1d[5]);
-}});
-_1._get.safe=true;
-dd.register.tags("dojox.dtl.contrib",{"data":["bind_data","bind_query"]});
+	var dd = dojox.dtl;
+	var ddcd = dd.contrib.data;
+
+	var first = true;
+
+	ddcd._BoundItem = dojo.extend(function(item, store){
+		this.item = item;
+		this.store = store;
+	},
+	{
+		get: function(key){
+			var store = this.store;
+			var item = this.item;
+
+			if(key == "getLabel"){
+				return store.getLabel(item);
+			}else if(key == "getAttributes"){
+				return store.getAttributes(item);
+			}else if(key == "getIdentity"){
+				if(store.getIdentity){
+					return store.getIdentity(item);
+				}
+				return "Store has no identity API";
+			}else{
+				if(!store.hasAttribute(item, key)){
+					if(key.slice(-1) == "s"){
+						if(first){
+							first = false;
+							dojo.deprecated("You no longer need an extra s to call getValues, it can be figured out automatically");
+						}
+						key = key.slice(0, -1);
+					}
+					if(!store.hasAttribute(item, key)){
+						return;
+					}
+				}
+
+				var values = store.getValues(item, key);
+				if(!values){
+					return;
+				}
+				if(!dojo.isArray(values)){
+					return new ddcd._BoundItem(values, store);
+				}
+
+				values = dojo.map(values, function(value){
+					if(dojo.isObject(value) && store.isItem(value)){
+						return new ddcd._BoundItem(value, store);
+					}
+					return value;
+				});
+				values.get = ddcd._get;
+				return values;
+			}
+		}
+	});
+	ddcd._BoundItem.prototype.get.safe = true;
+
+	ddcd.BindDataNode = dojo.extend(function(items, query, store, alias){
+		this.items = items && new dd._Filter(items);
+		this.query = query && new dd._Filter(query);
+		this.store = new dd._Filter(store);
+		this.alias = alias;
+	},
+	{
+		render: function(context, buffer){
+			var items = this.items && this.items.resolve(context);
+			var query = this.query && this.query.resolve(context);
+			var store = this.store.resolve(context);
+			if(!store || !store.getFeatures){
+				throw new Error("data_bind didn't receive a store");
+			}
+
+			if(query){
+				var sync = false;
+
+				store.fetch({
+					query: query,
+					sync: true,
+					scope: this,
+					onComplete: function(it){
+						sync = true;
+						items = it;
+					}
+				});
+
+				if(!sync){
+					throw new Error("The bind_data tag only works with a query if the store executed synchronously");
+				}
+			}
+
+			var list = [];
+
+			if(items){
+				for(var i = 0, item; item = items[i]; i++){
+					list.push(new ddcd._BoundItem(item, store));
+				}
+			}
+
+			context[this.alias] = list;
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			return buffer;
+		},
+		clone: function(){
+			return this;
+		}
+	});
+
+	dojo.mixin(ddcd, {
+		_get: function(key){
+			if(this.length){
+				return (this[0] instanceof ddcd._BoundItem) ? this[0].get(key) : this[0][key];
+			}
+		},
+		bind_data: function(parser, token){
+			// summary: Turns a list of data store items into DTL compatible items
+			// example:
+			//	`contextItems` and `contextStore` should be an item list
+			//	and a data store that get assigned to `newVariable`
+			//
+			//	|	{% bind_data contextItems to contextStore as newVariable %}
+			var parts = token.contents.split();
+
+			if(parts[2] != 'to' || parts[4] != 'as' || !parts[5]){
+				throw new Error("data_bind expects the format: 'data_bind items to store as varName'");
+			}
+
+			return new ddcd.BindDataNode(parts[1], null, parts[3], parts[5]);
+		},
+		bind_query: function(parser, token){
+			// summary: Queries a data store and makes the returned items DTL compatible
+			// example:
+			//	You can only use this with data stores that work in a synchronous
+			//	way (meaning that `onComplete` is fired during the `fetch` call).
+			//	A `sync` flag is sent to the fetch call so that stores that usually
+			//	work asynchronously make themselves syncrhonous if possible.
+			//	|	{% bind_query contextQuery to contextStore as newVariable %}
+			var parts = token.contents.split();
+
+			if(parts[2] != 'to' || parts[4] != 'as' || !parts[5]){
+				throw new Error("data_bind expects the format: 'bind_query query to store as varName'");
+			}
+
+			return new ddcd.BindDataNode(null, parts[1], parts[3], parts[5]);
+		}
+	});
+	ddcd._get.safe = true;
+
+	dd.register.tags("dojox.dtl.contrib", {
+		"data": ["bind_data", "bind_query"]
+	});
 })();
-}
diff --git a/dojox/dtl/contrib/dijit.js b/dojox/dtl/contrib/dijit.js
index 0050188..e8135b3 100644
--- a/dojox/dtl/contrib/dijit.js
+++ b/dojox/dtl/contrib/dijit.js
@@ -1,184 +1,220 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.contrib.dijit"]){
-dojo._hasResource["dojox.dtl.contrib.dijit"]=true;
 dojo.provide("dojox.dtl.contrib.dijit");
+
 dojo.require("dojox.dtl.dom");
 dojo.require("dojo.parser");
+
 (function(){
-var dd=dojox.dtl;
-var _1=dd.contrib.dijit;
-_1.AttachNode=dojo.extend(function(_2,_3){
-this._keys=_2;
-this._object=_3;
-},{render:function(_4,_5){
-if(!this._rendered){
-this._rendered=true;
-for(var i=0,_6;_6=this._keys[i];i++){
-_4.getThis()[_6]=this._object||_5.getParent();
-}
-}
-return _5;
-},unrender:function(_7,_8){
-if(this._rendered){
-this._rendered=false;
-for(var i=0,_9;_9=this._keys[i];i++){
-if(_7.getThis()[_9]===(this._object||_8.getParent())){
-delete _7.getThis()[_9];
-}
-}
-}
-return _8;
-},clone:function(_a){
-return new this.constructor(this._keys,this._object);
-}});
-_1.EventNode=dojo.extend(function(_b,_c){
-this._command=_b;
-var _d,_e=_b.split(/\s*,\s*/);
-var _f=dojo.trim;
-var _10=[];
-var fns=[];
-while(_d=_e.pop()){
-if(_d){
-var fn=null;
-if(_d.indexOf(":")!=-1){
-var _11=_d.split(":");
-_d=_f(_11[0]);
-fn=_f(_11.slice(1).join(":"));
-}else{
-_d=_f(_d);
-}
-if(!fn){
-fn=_d;
-}
-_10.push(_d);
-fns.push(fn);
-}
-}
-this._types=_10;
-this._fns=fns;
-this._object=_c;
-this._rendered=[];
-},{_clear:false,render:function(_12,_13){
-for(var i=0,_14;_14=this._types[i];i++){
-if(!this._clear&&!this._object){
-_13.getParent()[_14]=null;
-}
-var fn=this._fns[i];
-var _15;
-if(fn.indexOf(" ")!=-1){
-if(this._rendered[i]){
-dojo.disconnect(this._rendered[i]);
-this._rendered[i]=false;
-}
-_15=dojo.map(fn.split(" ").slice(1),function(_16){
-return new dd._Filter(_16).resolve(_12);
-});
-fn=fn.split(" ",2)[0];
-}
-if(!this._rendered[i]){
-if(!this._object){
-this._rendered[i]=_13.addEvent(_12,_14,fn,_15);
-}else{
-this._rendered[i]=dojo.connect(this._object,_14,_12.getThis(),fn);
-}
-}
-}
-this._clear=true;
-return _13;
-},unrender:function(_17,_18){
-while(this._rendered.length){
-dojo.disconnect(this._rendered.pop());
-}
-return _18;
-},clone:function(){
-return new this.constructor(this._command,this._object);
-}});
-function _19(n1){
-var n2=n1.cloneNode(true);
-if(dojo.isIE){
-dojo.query("script",n2).forEach("item.text = this[index].text;",dojo.query("script",n1));
-}
-return n2;
-};
-_1.DojoTypeNode=dojo.extend(function(_1a,_1b){
-this._node=_1a;
-this._parsed=_1b;
-var _1c=_1a.getAttribute("dojoAttachEvent");
-if(_1c){
-this._events=new _1.EventNode(dojo.trim(_1c));
-}
-var _1d=_1a.getAttribute("dojoAttachPoint");
-if(_1d){
-this._attach=new _1.AttachNode(dojo.trim(_1d).split(/\s*,\s*/));
-}
-if(!_1b){
-this._dijit=dojo.parser.instantiate([_19(_1a)])[0];
-}else{
-_1a=_19(_1a);
-var old=_1.widgetsInTemplate;
-_1.widgetsInTemplate=false;
-this._template=new dd.DomTemplate(_1a);
-_1.widgetsInTemplate=old;
-}
-},{render:function(_1e,_1f){
-if(this._parsed){
-var _20=new dd.DomBuffer();
-this._template.render(_1e,_20);
-var _21=_19(_20.getRootNode());
-var div=document.createElement("div");
-div.appendChild(_21);
-var _22=div.innerHTML;
-div.removeChild(_21);
-if(_22!=this._rendered){
-this._rendered=_22;
-if(this._dijit){
-this._dijit.destroyRecursive();
-}
-this._dijit=dojo.parser.instantiate([_21])[0];
-}
-}
-var _23=this._dijit.domNode;
-if(this._events){
-this._events._object=this._dijit;
-this._events.render(_1e,_1f);
-}
-if(this._attach){
-this._attach._object=this._dijit;
-this._attach.render(_1e,_1f);
-}
-return _1f.concat(_23);
-},unrender:function(_24,_25){
-return _25.remove(this._dijit.domNode);
-},clone:function(){
-return new this.constructor(this._node,this._parsed);
-}});
-dojo.mixin(_1,{widgetsInTemplate:true,dojoAttachPoint:function(_26,_27){
-return new _1.AttachNode(_27.contents.slice(16).split(/\s*,\s*/));
-},dojoAttachEvent:function(_28,_29){
-return new _1.EventNode(_29.contents.slice(16));
-},dojoType:function(_2a,_2b){
-var _2c=false;
-if(_2b.contents.slice(-7)==" parsed"){
-_2c=true;
-}
-var _2d=_2b.contents.slice(9);
-var _2e=_2c?_2d.slice(0,-7):_2d.toString();
-if(_1.widgetsInTemplate){
-var _2f=_2a.swallowNode();
-_2f.setAttribute("dojoType",_2e);
-return new _1.DojoTypeNode(_2f,_2c);
-}
-return new dd.AttributeNode("dojoType",_2e);
-},on:function(_30,_31){
-var _32=_31.contents.split();
-return new _1.EventNode(_32[0]+":"+_32.slice(1).join(" "));
-}});
-dd.register.tags("dojox.dtl.contrib",{"dijit":["attr:dojoType","attr:dojoAttachPoint",["attr:attach","dojoAttachPoint"],"attr:dojoAttachEvent",[/(attr:)?on(click|key(up))/i,"on"]]});
-})();
-}
+	var dd = dojox.dtl;
+	var ddcd = dd.contrib.dijit;
+
+	ddcd.AttachNode = dojo.extend(function(keys, object){
+		this._keys = keys;
+		this._object = object;
+	},
+	{
+		render: function(context, buffer){
+			if(!this._rendered){
+				this._rendered = true;
+				for(var i=0, key; key = this._keys[i]; i++){
+					context.getThis()[key] = this._object || buffer.getParent();
+				}
+			}
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			if(this._rendered){
+				this._rendered = false;
+				for(var i=0, key; key = this._keys[i]; i++){
+					if(context.getThis()[key] === (this._object || buffer.getParent())){
+						delete context.getThis()[key];
+					}
+				}
+			}
+			return buffer;
+		},
+		clone: function(buffer){
+			return new this.constructor(this._keys, this._object);
+		}
+	});
+
+	ddcd.EventNode = dojo.extend(function(command, obj){
+		this._command = command;
+
+		var type, events = command.split(/\s*,\s*/);
+		var trim = dojo.trim;
+		var types = [];
+		var fns = [];
+		while(type = events.pop()){
+			if(type){
+				var fn = null;
+				if(type.indexOf(":") != -1){
+					// oh, if only JS had tuple assignment
+					var funcNameArr = type.split(":");
+					type = trim(funcNameArr[0]);
+					fn = trim(funcNameArr.slice(1).join(":"));
+				}else{
+					type = trim(type);
+				}
+				if(!fn){
+					fn = type;
+				}
+				types.push(type);
+				fns.push(fn);
+			}
+		}
+
+		this._types = types;
+		this._fns = fns;
+		this._object = obj;
+		this._rendered = [];
+	},
+	{
+		// _clear: Boolean
+		//		Make sure we kill the actual tags (onclick problems, etc)
+		_clear: false,
+		render: function(context, buffer){
+			for(var i = 0, type; type = this._types[i]; i++){
+				if(!this._clear && !this._object){
+					buffer.getParent()[type] = null;
+				}
+				var fn = this._fns[i];
+				var args;
+				if(fn.indexOf(" ") != -1){
+					if(this._rendered[i]){
+						dojo.disconnect(this._rendered[i]);
+						this._rendered[i] = false;
+					}
+					args = dojo.map(fn.split(" ").slice(1), function(item){
+						return new dd._Filter(item).resolve(context);
+					});
+					fn = fn.split(" ", 2)[0];
+				}
+				if(!this._rendered[i]){
+					if(!this._object){
+						this._rendered[i] = buffer.addEvent(context, type, fn, args);
+					}else{
+						this._rendered[i] = dojo.connect(this._object, type, context.getThis(), fn);
+					}
+				}
+			}
+			this._clear = true;
+
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			while(this._rendered.length){
+				dojo.disconnect(this._rendered.pop());
+			}
+			return buffer;
+		},
+		clone: function(){
+			return new this.constructor(this._command, this._object);
+		}
+	});
+
+	function cloneNode(n1){
+		var n2 = n1.cloneNode(true);
+		if(dojo.isIE){
+			dojo.query("script", n2).forEach("item.text = this[index].text;", dojo.query("script", n1));
+		}
+		return n2;
+	}
+
+	ddcd.DojoTypeNode = dojo.extend(function(node, parsed){
+		this._node = node;
+		this._parsed = parsed;
+
+		var events = node.getAttribute("dojoAttachEvent");
+		if(events){
+			this._events = new ddcd.EventNode(dojo.trim(events));
+		}
+		var attach = node.getAttribute("dojoAttachPoint");
+		if(attach){
+			this._attach = new ddcd.AttachNode(dojo.trim(attach).split(/\s*,\s*/));
+		}
+
+		if (!parsed){
+			this._dijit = dojo.parser.instantiate([cloneNode(node)])[0];
+		}else{
+			node = cloneNode(node);
+			var old = ddcd.widgetsInTemplate;
+			ddcd.widgetsInTemplate = false;
+			this._template = new dd.DomTemplate(node);
+			ddcd.widgetsInTemplate = old;
+		}
+	},
+	{
+		render: function(context, buffer){
+			if(this._parsed){
+				var _buffer = new dd.DomBuffer();
+				this._template.render(context, _buffer);
+				var root = cloneNode(_buffer.getRootNode());
+				var div = document.createElement("div");
+				div.appendChild(root);
+				var rendered = div.innerHTML;
+				div.removeChild(root);
+				if(rendered != this._rendered){
+					this._rendered = rendered;
+					if(this._dijit){
+						this._dijit.destroyRecursive();
+					}
+					this._dijit = dojo.parser.instantiate([root])[0];
+				}
+			}
+
+			var node = this._dijit.domNode;
+
+			if(this._events){
+				this._events._object = this._dijit;
+				this._events.render(context, buffer);
+			}
+			if(this._attach){
+				this._attach._object = this._dijit;
+				this._attach.render(context, buffer);
+			}
+
+			return buffer.concat(node);
+		},
+		unrender: function(context, buffer){
+			return buffer.remove(this._dijit.domNode);
+		},
+		clone: function(){
+			return new this.constructor(this._node, this._parsed);
+		}
+	});
+
+	dojo.mixin(ddcd, {
+		widgetsInTemplate: true,
+		dojoAttachPoint: function(parser, token){
+			return new ddcd.AttachNode(token.contents.slice(16).split(/\s*,\s*/));
+		},
+		dojoAttachEvent: function(parser, token){
+			return new ddcd.EventNode(token.contents.slice(16));
+		},
+		dojoType: function(parser, token){
+			var parsed = false;
+			if(token.contents.slice(-7) == " parsed"){
+				parsed = true;
+			}
+			var contents = token.contents.slice(9);
+			var dojoType = parsed ? contents.slice(0, -7) : contents.toString();
+
+			if(ddcd.widgetsInTemplate){
+				var node = parser.swallowNode();
+				node.setAttribute("dojoType", dojoType);
+				return new ddcd.DojoTypeNode(node, parsed);
+			}
+
+			return new dd.AttributeNode("dojoType", dojoType);
+		},
+		on: function(parser, token){
+			// summary: Associates an event type to a function (on the current widget) by name
+			var parts = token.contents.split();
+			return new ddcd.EventNode(parts[0] + ":" + parts.slice(1).join(" "));
+		}
+	});
+
+	dd.register.tags("dojox.dtl.contrib", {
+		"dijit": ["attr:dojoType", "attr:dojoAttachPoint", ["attr:attach", "dojoAttachPoint"], "attr:dojoAttachEvent", [/(attr:)?on(click|key(up))/i, "on"]]
+	});
+})();
\ No newline at end of file
diff --git a/dojox/dtl/contrib/dom.js b/dojox/dtl/contrib/dom.js
index b3af170..cd9c69e 100644
--- a/dojox/dtl/contrib/dom.js
+++ b/dojox/dtl/contrib/dom.js
@@ -1,131 +1,169 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.contrib.dom"]){
-dojo._hasResource["dojox.dtl.contrib.dom"]=true;
 dojo.provide("dojox.dtl.contrib.dom");
+
 dojo.require("dojox.dtl.dom");
+
 (function(){
-var dd=dojox.dtl;
-var _1=dd.contrib.dom;
-var _2={render:function(){
-return this.contents;
-}};
-_1.StyleNode=dojo.extend(function(_3){
-this.contents={};
-this._current={};
-this._styles=_3;
-for(var _4 in _3){
-if(_3[_4].indexOf("{{")!=-1){
-var _5=new dd.Template(_3[_4]);
-}else{
-var _5=dojo.delegate(_2);
-_5.contents=_3[_4];
-}
-this.contents[_4]=_5;
-}
-},{render:function(_6,_7){
-for(var _8 in this.contents){
-var _9=this.contents[_8].render(_6);
-if(this._current[_8]!=_9){
-dojo.style(_7.getParent(),_8,this._current[_8]=_9);
-}
-}
-return _7;
-},unrender:function(_a,_b){
-this._current={};
-return _b;
-},clone:function(_c){
-return new this.constructor(this._styles);
-}});
-_1.BufferNode=dojo.extend(function(_d,_e){
-this.nodelist=_d;
-this.options=_e;
-},{_swap:function(_f,_10){
-if(!this.swapped&&this.parent.parentNode){
-if(_f=="node"){
-if((_10.nodeType==3&&!this.options.text)||(_10.nodeType==1&&!this.options.node)){
-return;
-}
-}else{
-if(_f=="class"){
-if(_f!="class"){
-return;
-}
-}
-}
-this.onAddNode&&dojo.disconnect(this.onAddNode);
-this.onRemoveNode&&dojo.disconnect(this.onRemoveNode);
-this.onChangeAttribute&&dojo.disconnect(this.onChangeAttribute);
-this.onChangeData&&dojo.disconnect(this.onChangeData);
-this.swapped=this.parent.cloneNode(true);
-this.parent.parentNode.replaceChild(this.swapped,this.parent);
-}
-},render:function(_11,_12){
-this.parent=_12.getParent();
-if(this.options.node){
-this.onAddNode=dojo.connect(_12,"onAddNode",dojo.hitch(this,"_swap","node"));
-this.onRemoveNode=dojo.connect(_12,"onRemoveNode",dojo.hitch(this,"_swap","node"));
-}
-if(this.options.text){
-this.onChangeData=dojo.connect(_12,"onChangeData",dojo.hitch(this,"_swap","node"));
-}
-if(this.options["class"]){
-this.onChangeAttribute=dojo.connect(_12,"onChangeAttribute",dojo.hitch(this,"_swap","class"));
-}
-_12=this.nodelist.render(_11,_12);
-if(this.swapped){
-this.swapped.parentNode.replaceChild(this.parent,this.swapped);
-dojo.destroy(this.swapped);
-}else{
-this.onAddNode&&dojo.disconnect(this.onAddNode);
-this.onRemoveNode&&dojo.disconnect(this.onRemoveNode);
-this.onChangeAttribute&&dojo.disconnect(this.onChangeAttribute);
-this.onChangeData&&dojo.disconnect(this.onChangeData);
-}
-delete this.parent;
-delete this.swapped;
-return _12;
-},unrender:function(_13,_14){
-return this.nodelist.unrender(_13,_14);
-},clone:function(_15){
-return new this.constructor(this.nodelist.clone(_15),this.options);
-}});
-dojo.mixin(_1,{buffer:function(_16,_17){
-var _18=_17.contents.split().slice(1);
-var _19={};
-var _1a=false;
-for(var i=_18.length;i--;){
-_1a=true;
-_19[_18[i]]=true;
-}
-if(!_1a){
-_19.node=true;
-}
-var _1b=_16.parse(["endbuffer"]);
-_16.next_token();
-return new _1.BufferNode(_1b,_19);
-},html:function(_1c,_1d){
-dojo.deprecated("{% html someVariable %}","Use {{ someVariable|safe }} instead");
-return _1c.create_variable_node(_1d.contents.slice(5)+"|safe");
-},style_:function(_1e,_1f){
-var _20={};
-_1f=_1f.contents.replace(/^style\s+/,"");
-var _21=_1f.split(/\s*;\s*/g);
-for(var i=0,_22;_22=_21[i];i++){
-var _23=_22.split(/\s*:\s*/g);
-var key=_23[0];
-var _24=dojo.trim(_23[1]);
-if(_24){
-_20[key]=_24;
-}
-}
-return new _1.StyleNode(_20);
-}});
-dd.register.tags("dojox.dtl.contrib",{"dom":["html","attr:style","buffer"]});
-})();
-}
+	var dd = dojox.dtl;
+	var ddch = dd.contrib.dom;
+
+	var simple = {render: function(){ return this.contents; }};
+
+	ddch.StyleNode = dojo.extend(function(styles){
+		this.contents = {};
+		this._current = {};
+		this._styles = styles;
+		for(var key in styles){
+			if(styles[key].indexOf("{{") != -1){
+				var node = new dd.Template(styles[key]);
+			}else{
+				var node = dojo.delegate(simple);
+				node.contents = styles[key];
+			}
+			this.contents[key] = node;
+		}
+	},
+	{
+		render: function(context, buffer){
+			for(var key in this.contents){
+				var value = this.contents[key].render(context);
+				if(this._current[key] != value){
+					dojo.style(buffer.getParent(), key, this._current[key] = value);
+				}
+			}
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			this._current = {};
+			return buffer;
+		},
+		clone: function(buffer){
+			return new this.constructor(this._styles);
+		}
+	});
+
+	ddch.BufferNode = dojo.extend(function(nodelist, options){
+		this.nodelist = nodelist;
+		this.options = options;
+	},
+	{
+		_swap: function(type, node){
+			if(!this.swapped && this.parent.parentNode){
+				if(type == "node"){
+					if((node.nodeType == 3 && !this.options.text) || (node.nodeType == 1 && !this.options.node)){
+						return;
+					}
+				}else if(type == "class"){
+					if(type != "class"){
+						return;
+					}
+				}
+
+				this.onAddNode && dojo.disconnect(this.onAddNode);
+				this.onRemoveNode && dojo.disconnect(this.onRemoveNode);
+				this.onChangeAttribute && dojo.disconnect(this.onChangeAttribute);
+				this.onChangeData && dojo.disconnect(this.onChangeData);
+
+				this.swapped = this.parent.cloneNode(true);
+				this.parent.parentNode.replaceChild(this.swapped, this.parent);
+			}
+		},
+		render: function(context, buffer){
+			this.parent = buffer.getParent();
+			if(this.options.node){
+				this.onAddNode = dojo.connect(buffer, "onAddNode", dojo.hitch(this, "_swap", "node"));
+				this.onRemoveNode = dojo.connect(buffer, "onRemoveNode", dojo.hitch(this, "_swap", "node"));
+			}
+			if(this.options.text){
+				this.onChangeData = dojo.connect(buffer, "onChangeData", dojo.hitch(this, "_swap", "node"));
+			}
+			if(this.options["class"]){
+				this.onChangeAttribute = dojo.connect(buffer, "onChangeAttribute", dojo.hitch(this, "_swap", "class"));
+			}
+
+			buffer = this.nodelist.render(context, buffer);
+
+			if(this.swapped){
+				this.swapped.parentNode.replaceChild(this.parent, this.swapped);
+				dojo.destroy(this.swapped);
+			}else{
+				this.onAddNode && dojo.disconnect(this.onAddNode);
+				this.onRemoveNode && dojo.disconnect(this.onRemoveNode);
+				this.onChangeAttribute && dojo.disconnect(this.onChangeAttribute);
+				this.onChangeData && dojo.disconnect(this.onChangeData);
+			}
+
+			delete this.parent;
+			delete this.swapped;
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			return this.nodelist.unrender(context, buffer);
+		},
+		clone: function(buffer){
+			return new this.constructor(this.nodelist.clone(buffer), this.options);
+		}
+	});
+
+	dojo.mixin(ddch, {
+		buffer: function(parser, token){
+			// summary:
+			//		Buffer large DOM manipulations during re-render.
+			//	description:
+			//		When using DomTemplate, wrap any content
+			//		that you expect to change often during
+			//		re-rendering. It will then remove its parent
+			//		from the main document while it re-renders that
+			//		section of code. It will only remove it from
+			//		the main document if a mainpulation of somes sort
+			//		happens. ie It won't swap out if it diesn't have to.
+			// example:
+			//		By default, it considers only node addition/removal
+			//		to be "changing"
+			//
+			//		|	{% buffer %}{% for item in items %}<li>{{ item }}</li>{% endfor %}{% endbuffer %}
+			// example:
+			//		You can explicitly declare options:
+			//
+			//			* node: Watch node removal/addition
+			//			* class: Watch for a classname to be changed
+			//			* text: Watch for any text to be changed
+			//
+			//		|	{% buffer node class %}{% for item in items %}<li>{{ item }}</li>{% endfor %}{% endbuffer %}
+			var parts = token.contents.split().slice(1);
+			var options = {};
+			var found = false;
+			for(var i=parts.length; i--;){
+				found = true;
+				options[parts[i]] = true;
+			}
+			if(!found){
+				options.node = true;
+			}
+			var nodelist = parser.parse(["endbuffer"]);
+			parser.next_token();
+			return new ddch.BufferNode(nodelist, options);
+		},
+		html: function(parser, token){
+			dojo.deprecated("{% html someVariable %}", "Use {{ someVariable|safe }} instead");
+			return parser.create_variable_node(token.contents.slice(5) + "|safe");
+		},
+		style_: function(parser, token){
+			var styles = {};
+			token = token.contents.replace(/^style\s+/, "");
+			var rules = token.split(/\s*;\s*/g);
+			for(var i = 0, rule; rule = rules[i]; i++){
+				var parts = rule.split(/\s*:\s*/g);
+				var key = parts[0];
+				var value = dojo.trim(parts[1]);
+				if(value){
+					styles[key] = value;
+				}
+			}
+			return new ddch.StyleNode(styles);
+		}
+	});
+
+	dd.register.tags("dojox.dtl.contrib", {
+		"dom": ["html", "attr:style", "buffer"]
+	});
+})();
\ No newline at end of file
diff --git a/dojox/dtl/contrib/html.js b/dojox/dtl/contrib/html.js
index a8b7453..a8c60a0 100644
--- a/dojox/dtl/contrib/html.js
+++ b/dojox/dtl/contrib/html.js
@@ -1,13 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.contrib.html"]){
-dojo._hasResource["dojox.dtl.contrib.html"]=true;
 dojo.provide("dojox.dtl.contrib.html");
 dojo.require("dojox.dtl.contrib.dom");
-dojo.deprecated("dojox.dtl.html","All packages and classes in dojox.dtl that start with Html or html have been renamed to Dom or dom");
-}
+dojo.deprecated("dojox.dtl.html", "All packages and classes in dojox.dtl that start with Html or html have been renamed to Dom or dom");
\ No newline at end of file
diff --git a/dojox/dtl/contrib/objects.js b/dojox/dtl/contrib/objects.js
index 59cce93..fb4ed72 100644
--- a/dojox/dtl/contrib/objects.js
+++ b/dojox/dtl/contrib/objects.js
@@ -1,15 +1,11 @@
-/*
-	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
-*/
+dojo.provide("dojox.dtl.contrib.objects");
 
+dojo.mixin(dojox.dtl.contrib.objects, {
+	key: function(value, arg){
+		return value[arg];
+	}
+});
 
-if(!dojo._hasResource["dojox.dtl.contrib.objects"]){
-dojo._hasResource["dojox.dtl.contrib.objects"]=true;
-dojo.provide("dojox.dtl.contrib.objects");
-dojo.mixin(dojox.dtl.contrib.objects,{key:function(_1,_2){
-return _1[_2];
-}});
-dojox.dtl.register.filters("dojox.dtl.contrib",{"objects":["key"]});
-}
+dojox.dtl.register.filters("dojox.dtl.contrib", {
+	"objects": ["key"]
+});
\ No newline at end of file
diff --git a/dojox/dtl/demos/demo_Animation.html b/dojox/dtl/demos/demo_Animation.html
new file mode 100644
index 0000000..121395d
--- /dev/null
+++ b/dojox/dtl/demos/demo_Animation.html
@@ -0,0 +1,45 @@
+<html>
+	<head>
+		<title>Testing dojox.dtl using animation to change attributes</title>
+		<script src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, usePlainJson: true"></script>
+		<script>
+			dojo.require("dijit._Widget");
+			dojo.require("dojox.dtl._DomTemplated");
+
+			dojo.declare("demo.Animation", [dijit._Widget, dojox.dtl._DomTemplated],
+			{
+				buffer: 0, // Note: Sensitivity is 0 by default, but this is to emphasize we're not doing any buffering
+				templateString: dojo.cache("dojox.dtl.demos.templates", "animation.html"),
+				constructor: function(props, node){
+					console.debug("constructor");
+					this.x = 0;
+					this.y = 0;
+				},
+				postCreate: function(){
+					var anim = new dojo.Animation({
+						curve: [0, 300],
+						rate: 10,
+						duration: 5000,
+						easing: dojo._defaultEasing
+					});
+					dojo.connect(anim, "onAnimate", this, "_reDraw");
+					anim.play();
+				},
+				_reDraw: function(obj){
+					this.x = obj;
+					this.y = Math.sqrt(obj) * 10;
+
+					dojo.style(this.blue, "left", this.x);
+					dojo.style(this.blue, "top", this.y + 10);
+
+					this.render();
+				}
+			});
+
+			dojo.require("dojo.parser");
+		</script>
+	</head>
+	<body>
+		<div dojoType="demo.Animation" ></div>
+	</body>
+</html>
diff --git a/dojox/dtl/demos/demo_Blog.html b/dojox/dtl/demos/demo_Blog.html
new file mode 100644
index 0000000..d58c4ed
--- /dev/null
+++ b/dojox/dtl/demos/demo_Blog.html
@@ -0,0 +1,95 @@
+<html>
+	<head>
+		<title>Testing dojox.dtl using a blog example</title>
+		<script src="../../../dojo/dojo.js" djConfig="usePlainJson: true, parseOnLoad: true"></script>
+		<script>
+			dojo.require("dijit._Widget");
+			dojo.require("dojox.dtl._DomTemplated");
+			dojo.require("dojo.parser");
+
+			dojo.declare("demo.Blog", [dijit._Widget, dojox.dtl._DomTemplated],
+			{
+				templatePath: dojo.moduleUrl("dojox.dtl.demos.templates", "blog_list.html"),
+				base: {
+					url: dojo.moduleUrl("dojox.dtl.demos.templates", "blog_base.html"),
+					shared: true
+				},
+				constructor: function(props, node){
+					this.list = false;
+					this.blogs = {};
+					this.pages = {};
+				},
+				postCreate: function(){
+					if(!this.list){
+						dojo.xhrGet({
+							url: dojo.moduleUrl("dojox.dtl.demos.json.blog", "get_blog_list.json"),
+							handleAs: "json"
+						}).addCallback(this, "_loadList");
+					}
+				},
+				_showList: function(obj){
+					this.title = "Blog Posts";
+					this.setTemplate(this.templatePath);
+				},
+				_showDetail: function(obj){
+					var key = obj.target.className.substring(5);
+
+					if(this.blogs[key]){
+						this.title = "Blog Post";
+						this.blog = this.blogs[key];
+						this.blog.title = this.blog_list[key].title;
+						this.setTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "blog_detail.html"));
+					}else{
+						dojo.xhrGet({
+							url: dojo.moduleUrl("dojox.dtl.demos.json.blog", "get_blog_" + key + ".json"),
+							handleAs: "json",
+							load: function(data){
+								data.key = key;
+								return data;
+							}
+						}).addCallback(this, "_loadDetail");
+					}
+				},
+				_showPage: function(obj){
+					var key = obj.target.className.substring(5);
+
+					if(this.pages[key]){
+						this.title = this.pages[key].title;
+						this.body = this.pages[key].body;
+						this.setTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "blog_page.html"));
+					}else{
+						dojo.xhrGet({
+							url: dojo.moduleUrl("dojox.dtl.demos.json.blog", "get_page_" + key + ".json"),
+							handleAs: "json",
+							load: function(data){
+								data.key = key;
+								return data;
+							}
+						}).addCallback(this, "_loadPage");
+					}
+				},
+				_loadList: function(data){
+					this.title = "Blog Posts";
+					dojo.mixin(this, data);
+					this.render();
+				},
+				_loadDetail: function(data){
+					data.date = new Date(data.date);
+					this.blogs[data.key] = data;
+					this.title = "Blog Post";
+					this.blog = data;
+					this.blog.title = this.blog_list[data.key].title;
+					this.setTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "blog_detail.html"));
+				},
+				_loadPage: function(data){
+					this.pages[data.key] = data;
+					dojo.mixin(this, data);
+					this.setTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "blog_page.html"));
+				}
+			});
+		</script>
+	</head>
+	<body>
+		<div dojoType="demo.Blog"></div>
+	</body>
+</html>
diff --git a/dojox/dtl/demos/demo_Data.html b/dojox/dtl/demos/demo_Data.html
new file mode 100644
index 0000000..8f2f92b
--- /dev/null
+++ b/dojox/dtl/demos/demo_Data.html
@@ -0,0 +1,59 @@
+<html>
+	<head>
+			<title>Demo using the dojo.data bind_data tag</title>
+	    <script type="text/javascript" src="../../../dojo/dojo.js"
+				djConfig="isDebug: true, parseOnLoad: true"></script>
+	    <script type="text/javascript" src="../../../dijit/dijit.js"></script> 
+	    <script type="text/javascript">
+				dojo.require("dojox.dtl._Templated");
+				dojo.require("dojox.data.FlickrRestStore");
+				dojo.require("dojo.parser");
+
+				dojo.declare("demo.Gallery", [dijit._Widget, dojox.dtl._Templated], {
+					templateString: dojo.cache("dojox.dtl.demos.templates", "gallery.html"),
+					store: new dojox.data.FlickrRestStore(),
+					selectThumbnail: function(e){
+						this.selected = e.target.className;
+						this.render();
+					},
+					keyUp: function(e){
+						if(e.keyCode == dojo.keys.ENTER){
+							var search = e.target.value;
+							var query = {
+								query: {
+									userid: "44153025 at N00",
+									apikey: "8c6803164dbc395fb7131c9d54843627",
+									sort: [
+										   {
+											attribute: "interestingness",
+											descending: true
+											}
+									],
+									tags: search.split(/\s*,\s*/g),
+									tag_mode: "any"
+								},
+								start: 0,
+								count: 10,
+								onBegin: dojo.hitch(this, function(total){
+									console.debug(total);
+									this._maxPhotos = total;
+								}),
+								onComplete: dojo.hitch(this, function(items, request){
+									console.debug(items);
+									if(items && items.length) {
+										this.items = items;
+										this.render();
+									}
+								})
+							};
+							this.store.fetch(query);
+						}
+					}
+				});
+	    </script>
+	</head>
+	<body>
+		<p>Also see demo_Tree.html for an alternative way to use data stores.</p>
+		<div dojoType="demo.Gallery"></div>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/dtl/demos/demo_Dijitless.html b/dojox/dtl/demos/demo_Dijitless.html
new file mode 100644
index 0000000..e902ef6
--- /dev/null
+++ b/dojox/dtl/demos/demo_Dijitless.html
@@ -0,0 +1,50 @@
+<html>
+	<head>
+		<title>Demo using dojox.dtl._DomTemplated without Dijit</title>
+    <script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.dtl.dom");
+			dojo.require("dojox.dtl.render.dom");
+			dojo.require("dojox.dtl.Context");
+
+			dojo.addOnLoad(function(){
+				var context = new dojox.dtl.Context({
+					items: ["apple", "banana", "orange"]
+				});
+
+				var template = new dojox.dtl.DomTemplate("<ul><!--{% for item in items %}--><li><!--{{ item }}--></li><!--{% endfor %}--></ul>");
+				// Render it plain
+				var node = template.render(context).getRootNode();
+				dojo.body().appendChild(node);
+
+				// Now show an example of how hard it is to manage stuff if the root node changes
+				var template2 = new dojox.dtl.DomTemplate("<!--{% ifequal items.length 3 %}--><ul><!--{% for item in items %}--><li><!--{{ item }}--></li><!--{% endfor %}--></ul>{% else %}<div>More than 3 items!</div>{% endifequal %}");
+				// Render it plain
+				var node2 = template2.render(context).getRootNode();
+				dojo.body().appendChild(node2);
+
+				// Now show how the HTML Render object makes this easier
+				var renderer = new dojox.dtl.render.dom.Render(dojo.byId("attach"), new dojox.dtl.DomTemplate("<!--{% ifequal items.length 3 %}--><ul><!--{% for item in items reversed %}--><li><!--{{ item }}--></li><!--{% endfor %}--></ul>{% else %}<div>More than 3 items!</div>{% endifequal %}"));
+				renderer.render(context);
+
+				// Now re-render and break template2
+				setTimeout(function(){
+					context.items.push("guava");
+					template.render(context);
+					template2.render(context);
+					renderer.render(context);
+
+					// This is what has to be done to fix template2
+					setTimeout(function(){
+						var frag = template2.render(context).getRootNode();
+						node2.parentNode.replaceChild(frag, node2);
+					}, 3000);
+				}, 3000);
+			});
+		</script>
+	</head>
+	<body>
+		<div id="attach"></div>
+	</body>
+</html>
diff --git a/dojox/dtl/demos/demo_DomTemplated.html b/dojox/dtl/demos/demo_DomTemplated.html
new file mode 100644
index 0000000..28a88b6
--- /dev/null
+++ b/dojox/dtl/demos/demo_DomTemplated.html
@@ -0,0 +1,44 @@
+<html>
+	<head>
+			<title>Demo using dojox.dtl._DomTemplated</title>
+			<script type="text/javascript" src="../../../dojo/dojo.js"
+				djConfig="isDebug: true, parseOnLoad: true"></script>
+			<script type="text/javascript" src="../../../dijit/dijit.js"></script>
+			<style type="text/css">
+				@import "../../../dijit/themes/tundra/tundra.css";
+				#pane {
+				    border: 1px solid darkblue;
+				}
+			</style>
+	    <script type="text/javascript">
+					dojo.require("dojox.dtl._DomTemplated");
+					dojo.require("dijit.form.Button");
+                    dojo.require("dijit.layout.ContentPane");
+
+					dojo.declare("Fruit", [dijit._Widget, dojox.dtl._DomTemplated], {
+						widgetsInTemplate: true,
+						items: ["apple", "banana", "orange"],
+						keyUp: function(e){
+							if((e.type == "click" || e.keyCode == dojo.keys.ENTER) && this.input.value){
+								console.debug(this.button);
+								var i = dojo.indexOf(this.items, this.input.value);
+								if(i != -1){
+									this.items.splice(i, 1);
+								}else{
+									this.items.push(this.input.value);
+								}
+								this.input.value = "";
+								this.render();
+							}
+						},
+						// Note, the load tag here is superfluous, since _DomTemplate has a dojo.require for it.
+						templateString: '<!--{% load dojox.dtl.contrib.dijit %}--><div><input dojoAttachEvent="onkeyup: keyUp" dojoAttachPoint="input"> <button dojoType="dijit.form.Button" dojoAttachPoint="button" dojoAttachEvent="onClick: keyUp">Add/Remove Item</button><div id="pane" dojoType="dijit.layout.ContentPane parsed"><ul><!--{% for item in items %}--><li><button dojoType="dijit.form.Button parsed" title="Fruit: {{ item }}" otherAttr2="x_{{item}}"><!--{{ item }}--><script type="dojo/connect" even [...]
+					});
+
+					dojo.require("dojo.parser");
+	    </script>
+	</head>
+	<body class="tundra">
+		<div dojoType="Fruit" id="dtl"></div>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/dtl/demos/demo_Events.html b/dojox/dtl/demos/demo_Events.html
new file mode 100644
index 0000000..038a3d9
--- /dev/null
+++ b/dojox/dtl/demos/demo_Events.html
@@ -0,0 +1,46 @@
+<html>
+	<head>
+			<title>Demo using dojox.dtl._Templated</title>
+	    <script type="text/javascript" src="../../../dojo/dojo.js"
+				djConfig="isDebug: true, parseOnLoad: true"></script>
+	    <script type="text/javascript" src="../../../dijit/dijit.js"></script>
+			<style type="text/css">
+				@import "../../../dijit/themes/tundra/tundra.css";
+			</style>
+	    <script type="text/javascript">
+					dojo.require("dojox.dtl._DomTemplated");
+					dojo.require("dijit.form.Button");
+
+					dojo.declare("Fruit", [dijit._Widget, dojox.dtl._DomTemplated], {
+						widgetsInTemplate: true,
+						items: ["apple", "banana", "orange"],
+						keyUp: function(e){
+							if((e.type == "click" || e.keyCode == dojo.keys.ENTER) && this.input.value){
+								var i = dojo.indexOf(this.items, this.input.value);
+								if(i != -1){
+									this.items.splice(i, 1);
+								}else{
+									this.items.push(this.input.value);
+								}
+								this.input.value = "";
+								this.render();
+							}
+						},
+						postCreate: function(){
+						 	this.render();
+							dojo.connect(this.button, "onClick", this, "keyUp");
+						},
+						debug: function(e, verb, fruit){
+							console.debug("You " + verb + " a:", fruit);
+						},
+						// Note, the load tag here is superfluous, since _DomTemplate has a dojo.require for it.
+						templateString: '<!--{% load dojox.dtl.contrib.dijit %}--><div><input dojoAttachEvent="onkeyup: keyUp" dojoAttachPoint="input"> <button dojoType="dijit.form.Button" dojoAttachPoint="button">Add/Remove Item</button><ul><!--{% for item in items %}--><li onclick="debug \'ate\' item"><!--{{ item }}--></li><!--{% endfor %}--></ul></div>'
+					});
+
+	        dojo.require("dojo.parser");
+	    </script>
+	</head>
+	<body class="tundra">
+		<div dojoType="Fruit"></div>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/dtl/demos/demo_Inline.html b/dojox/dtl/demos/demo_Inline.html
new file mode 100644
index 0000000..7c16ea3
--- /dev/null
+++ b/dojox/dtl/demos/demo_Inline.html
@@ -0,0 +1,51 @@
+<html>
+	<head>
+		<title>Demo using dojox.dtl._DomTemplated inline in DOM</title>
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("dojox.dtl.Inline");
+			dojo.require("dojox.dtl.DomInline");
+
+			gContext = {items: ["apple", "banana", "orange"]};
+
+			dojo.addOnLoad(function(){
+				// The Re-render each with a new item
+				setTimeout(function(){
+					var inline = dijit.byId("inline");
+					inline.context.items.push("guava");
+					inline.render();
+					var dominline = dijit.byId("dominline");
+					dominline.context.items.push("pineapple");
+					dominline.render();
+
+					setTimeout(function(){
+						// You can define an altogether new context in either of the following ways
+						inline.context = {items: ["lions", "tigers", "bears"]};
+						inline.render();
+						dominline.render({items: ["duck", "chicken", "turkey"]});
+					}, 3000);
+				}, 3000);
+			});
+		</script>
+	</head>
+	<body>
+		<script type="text/html" dojoType="dojox.dtl.Inline" id="inline" context="{items: ['apple', 'banana', 'orange']}">
+			<ul>
+				{% for item in items %}
+					<li>{{ item }}</li>
+				{% endfor %}
+			</ul>
+		</script>
+
+		<!-- Use the DOM-based version with an external context -->
+		<script type="text/html" dojoType="dojox.dtl.DomInline" id="dominline" context="gContext">
+			<ul>
+				{% for item in items %}
+					<li>{{ item }}</li>
+				{% endfor %}
+			</ul>
+		</script>
+	</body>
+</html>
diff --git a/dojox/dtl/demos/demo_NodeList.html b/dojox/dtl/demos/demo_NodeList.html
new file mode 100644
index 0000000..d1ab0a8
--- /dev/null
+++ b/dojox/dtl/demos/demo_NodeList.html
@@ -0,0 +1,37 @@
+<html>
+	<head>
+		<title>Demo using dojox.dtl._Templated</title>
+    <script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.dtl.ext-dojo.NodeList");
+			dojo.require("dojox.dtl.Context");
+
+			dojo.addOnLoad(function(){
+				// First, look at the NodeList extension
+				dojo.query(".fruit").dtl(dojo.moduleUrl("dojox.dtl.demos.templates", "nodelist.html"), { items: ["apple", "banana", "pear"] });
+
+				dojo.query(".fruit2").dtl("<div><ul>{% for item in items %}<li>{{ item }}</li>{% endfor %}</ul></div", { items: ["apple", "banana", "pear"] });
+
+				// Now, create a real template object
+				var tpl = new dojox.dtl.Template(dojo.moduleUrl("dojox.dtl.demos.templates", "nodelist.html"));
+
+				// And test its update function with a dojo.query
+				tpl.update(dojo.query(".update"), dojo.moduleUrl("dojox.dtl.demos.json", "fruit.json"));
+
+				setTimeout(function(){
+					// And now test it with an ID reference
+					tpl.update("updateId", dojo.moduleUrl("dojox.dtl.demos.json", "morefruit.json"));
+					// And throw in a standard rendering just for fun
+					dojo.byId("updateId2").innerHTML = tpl.render(new dojox.dtl.Context({ items: ["pineapple", "orange", "tomato"] }));
+				}, 5000);
+			});
+		</script>
+	</head>
+	<body>
+		<div class="fruit"></div>
+		<div class="fruit2"></div>
+		<div class="update" id="updateId"></div>
+		<div class="update" id="updateId2"></div>
+	</body>
+</html>
diff --git a/dojox/dtl/demos/demo_Table.html b/dojox/dtl/demos/demo_Table.html
new file mode 100644
index 0000000..cc13e4c
--- /dev/null
+++ b/dojox/dtl/demos/demo_Table.html
@@ -0,0 +1,4073 @@
+<html>
+	<head>
+			<title>Demo to show a massive nested for loop to render a table</title>
+	    <script type="text/javascript" src="../../../dojo/dojo.js"
+				djConfig="isDebug: true, parseOnLoad: true"></script>
+	    <script type="text/javascript" src="../../../dijit/dijit.js"></script>
+			<style type="text/css">
+				@import "../../../dijit/themes/tundra/tundra.css";
+
+				table {
+					border-collapse: collapse;
+				}
+				th {
+					background-color: #ccf;
+				}
+				th, td {
+					border: 1px solid #aaa;
+					padding: 2px 15px;
+				}
+				tr.even td {
+					background-color: #ffc;
+				}
+			</style>
+	    <script type="text/javascript">
+					dojo.require("dojox.dtl._DomTemplated");
+					dojo.require("dojox.dtl.tag.logic");
+					dojo.require("dojox.dtl.tag.loop");
+					dojo.require("dojox.dtl.filter.lists");
+
+					dojo.declare("demo.Table", [dijit._Widget, dojox.dtl._DomTemplated], {
+						pos: 0,
+						postMixInProperties: function(){
+							this.ths = dojo.query("th", this.domNode).map(function(item){
+								return item.innerHTML;
+							});
+							this.trs = dojo.query("tbody tr", this.domNode).map(function(item){
+								return dojo.query("td", item).map(function(item){
+									return item.innerHTML;
+								});
+							});
+						},
+						postCreate: function(){
+							//unset display to show it (this is copied from the original node)
+							this.domNode.style.display="";
+						},
+						sortColumn: function(e){
+							this.pos = dojo.indexOf(this.ths, e.target.innerHTML);
+							console.time("render2");
+							this.render();
+							console.timeEnd("render2");
+						},
+						templateString: '<table><thead><tr><!--{% for th in ths %}--><th dojoAttachEvent="onclick: sortColumn"><!--{{ th }}--></th><!--{% endfor %}--></tr></thead><tbody><!--{% for tr in trs|dictsort:pos %}--><tr class="{% cycle \'odd\' \'even\' %}"><!--{% for td in tr %}--><td><!--{{ td }}--></td><!--{% endfor %}--></tr><!--{% endfor %}--></tbody></table>'
+					});
+
+	        dojo.require("dojo.parser");
+	    </script>
+	</head>
+			<body class="tundra">
+				<table dojoType="demo.Table" style="display: none;">
+					<thead>
+						<tr>
+							<th>Index</th>
+							<th>Numeric</th>
+							<th>Text</th>
+							<th>Currency</th>
+							<th>Date</th>
+						</tr>
+					</thead>
+					<tbody>
+						<tr>
+							<td>0</td>
+							<td>158.9</td>
+							<td>Bill</td>
+							<td>$22.44</td>
+
+							<td>2008-12-28</td>
+						</tr>
+						<tr>
+							<td>1</td>
+							<td>690.4</td>
+							<td>Joe</td>
+							<td>$3.03</td>
+
+							<td>2009-07-03</td>
+						</tr>
+						<tr>
+							<td>2</td>
+							<td>843</td>
+							<td>Bob</td>
+							<td>$11.14</td>
+
+							<td>2010-09-30</td>
+						</tr>
+						<tr>
+							<td>3</td>
+							<td>57.8</td>
+							<td>Matt</td>
+							<td>$70.64</td>
+
+							<td>2009-12-16</td>
+						</tr>
+						<tr>
+							<td>4</td>
+							<td>494.6</td>
+							<td>Mark</td>
+							<td>$9.13</td>
+
+							<td>2010-05-11</td>
+						</tr>
+						<tr>
+							<td>5</td>
+							<td>766.3</td>
+							<td>Tom</td>
+							<td>$55.34</td>
+
+							<td>2008-03-10</td>
+						</tr>
+						<tr>
+							<td>6</td>
+							<td>699.3</td>
+							<td>Jake</td>
+							<td>$26.24</td>
+
+							<td>2008-11-26</td>
+						</tr>
+						<tr>
+							<td>7</td>
+							<td>487.8</td>
+							<td>Greg</td>
+							<td>$72.94</td>
+
+							<td>2010-06-23</td>
+						</tr>
+						<tr>
+							<td>8</td>
+							<td>786.2</td>
+							<td>Adam</td>
+							<td>$34.64</td>
+
+							<td>2008-09-19</td>
+						</tr>
+						<tr>
+							<td>9</td>
+							<td>188.6</td>
+							<td>Steve</td>
+							<td>$6.33</td>
+
+							<td>2009-01-01</td>
+						</tr>
+						<tr>
+							<td>10</td>
+							<td>898.4</td>
+							<td>George</td>
+							<td>$22.24</td>
+
+							<td>2009-09-18</td>
+						</tr>
+						<tr>
+							<td>11</td>
+							<td>222.2</td>
+							<td>John</td>
+							<td>$91.24</td>
+
+							<td>2009-10-23</td>
+						</tr>
+						<tr>
+							<td>12</td>
+							<td>707.9</td>
+							<td>Phil</td>
+							<td>$75.54</td>
+
+							<td>2010-02-28</td>
+						</tr>
+						<tr>
+							<td>13</td>
+							<td>585.5</td>
+							<td>Jack</td>
+							<td>$81.34</td>
+
+							<td>2009-03-24</td>
+						</tr>
+						<tr>
+							<td>14</td>
+							<td>213.8</td>
+							<td>Paul</td>
+							<td>$30.74</td>
+
+							<td>2009-07-08</td>
+						</tr>
+						<tr>
+							<td>15</td>
+							<td>968.5</td>
+							<td>Rob</td>
+							<td>$7.33</td>
+
+							<td>2008-02-06</td>
+						</tr>
+						<tr>
+							<td>16</td>
+							<td>39.3</td>
+							<td>Walt</td>
+							<td>$77.34</td>
+
+							<td>2008-12-05</td>
+						</tr>
+						<tr>
+							<td>17</td>
+							<td>335.7</td>
+							<td>Nathan</td>
+							<td>$26.14</td>
+
+							<td>2008-01-27</td>
+						</tr>
+						<tr>
+							<td>18</td>
+							<td>127.6</td>
+							<td>Dan</td>
+							<td>$4.73</td>
+
+							<td>2009-03-03</td>
+						</tr>
+						<tr>
+							<td>19</td>
+							<td>365.3</td>
+							<td>Jeff</td>
+							<td>$23.54</td>
+
+							<td>2009-05-15</td>
+						</tr>
+						<tr>
+							<td>20</td>
+							<td>692.9</td>
+							<td>Bill</td>
+							<td>$13.34</td>
+
+							<td>2010-01-26</td>
+						</tr>
+						<tr>
+							<td>21</td>
+							<td>244.9</td>
+							<td>Joe</td>
+							<td>$35.64</td>
+
+							<td>2009-10-16</td>
+						</tr>
+						<tr>
+							<td>22</td>
+							<td>827</td>
+							<td>Bob</td>
+							<td>$6.33</td>
+
+							<td>2009-01-06</td>
+						</tr>
+						<tr>
+							<td>23</td>
+							<td>519.6</td>
+							<td>Matt</td>
+							<td>$64.94</td>
+
+							<td>2008-06-03</td>
+						</tr>
+						<tr>
+							<td>24</td>
+							<td>917.8</td>
+							<td>Mark</td>
+							<td>$86.34</td>
+
+							<td>2009-05-24</td>
+						</tr>
+						<tr>
+							<td>25</td>
+							<td>407.1</td>
+							<td>Tom</td>
+							<td>$83.14</td>
+
+							<td>2009-08-17</td>
+						</tr>
+						<tr>
+							<td>26</td>
+							<td>449.3</td>
+							<td>Jake</td>
+							<td>$87.04</td>
+
+							<td>2008-11-27</td>
+						</tr>
+						<tr>
+							<td>27</td>
+							<td>753.5</td>
+							<td>Greg</td>
+							<td>$20.64</td>
+
+							<td>2009-09-25</td>
+						</tr>
+						<tr>
+							<td>28</td>
+							<td>787</td>
+							<td>Adam</td>
+							<td>$33.44</td>
+
+							<td>2009-11-18</td>
+						</tr>
+						<tr>
+							<td>29</td>
+							<td>166.9</td>
+							<td>Steve</td>
+							<td>$69.94</td>
+
+							<td>2010-08-17</td>
+						</tr>
+						<tr>
+							<td>30</td>
+							<td>609.6</td>
+							<td>George</td>
+							<td>$39.24</td>
+
+							<td>2011-01-18</td>
+						</tr>
+						<tr>
+							<td>31</td>
+							<td>274</td>
+							<td>John</td>
+							<td>$63.64</td>
+
+							<td>2009-01-02</td>
+						</tr>
+						<tr>
+							<td>32</td>
+							<td>850.3</td>
+							<td>Phil</td>
+							<td>$46.34</td>
+
+							<td>2009-03-17</td>
+						</tr>
+						<tr>
+							<td>33</td>
+							<td>181.4</td>
+							<td>Jack</td>
+							<td>$98.34</td>
+
+							<td>2008-02-04</td>
+						</tr>
+						<tr>
+							<td>34</td>
+							<td>325.3</td>
+							<td>Paul</td>
+							<td>$90.14</td>
+
+							<td>2010-10-30</td>
+						</tr>
+						<tr>
+							<td>35</td>
+							<td>776.3</td>
+							<td>Rob</td>
+							<td>$30.84</td>
+
+							<td>2010-04-17</td>
+						</tr>
+						<tr>
+							<td>36</td>
+							<td>300.8</td>
+							<td>Walt</td>
+							<td>$75.74</td>
+
+							<td>2009-11-18</td>
+						</tr>
+						<tr>
+							<td>37</td>
+							<td>598</td>
+							<td>Nathan</td>
+							<td>$51.04</td>
+
+							<td>2010-07-15</td>
+						</tr>
+						<tr>
+							<td>38</td>
+							<td>155.6</td>
+							<td>Dan</td>
+							<td>$29.74</td>
+
+							<td>2008-06-04</td>
+						</tr>
+						<tr>
+							<td>39</td>
+							<td>759.8</td>
+							<td>Jeff</td>
+							<td>$46.44</td>
+
+							<td>2010-08-21</td>
+						</tr>
+						<tr>
+							<td>40</td>
+							<td>599.2</td>
+							<td>Bill</td>
+							<td>$7.43</td>
+
+							<td>2008-09-16</td>
+						</tr>
+						<tr>
+							<td>41</td>
+							<td>571.9</td>
+							<td>Joe</td>
+							<td>$34.84</td>
+
+							<td>2010-09-23</td>
+						</tr>
+						<tr>
+							<td>42</td>
+							<td>900.3</td>
+							<td>Bob</td>
+							<td>$19.84</td>
+
+							<td>2009-01-09</td>
+						</tr>
+						<tr>
+							<td>43</td>
+							<td>292.2</td>
+							<td>Matt</td>
+							<td>$37.94</td>
+
+							<td>2008-12-21</td>
+						</tr>
+						<tr>
+							<td>44</td>
+							<td>333</td>
+							<td>Mark</td>
+							<td>$70.54</td>
+
+							<td>2008-08-28</td>
+						</tr>
+						<tr>
+							<td>45</td>
+							<td>236.4</td>
+							<td>Tom</td>
+							<td>$48.14</td>
+
+							<td>2009-08-19</td>
+						</tr>
+						<tr>
+							<td>46</td>
+							<td>970.9</td>
+							<td>Jake</td>
+							<td>$78.24</td>
+
+							<td>2008-11-10</td>
+						</tr>
+						<tr>
+							<td>47</td>
+							<td>575.8</td>
+							<td>Greg</td>
+							<td>$37.94</td>
+
+							<td>2010-06-24</td>
+						</tr>
+						<tr>
+							<td>48</td>
+							<td>386.7</td>
+							<td>Adam</td>
+							<td>$53.54</td>
+
+							<td>2008-04-02</td>
+						</tr>
+						<tr>
+							<td>49</td>
+							<td>531.1</td>
+							<td>Steve</td>
+							<td>$29.54</td>
+
+							<td>2009-09-21</td>
+						</tr>
+						<tr>
+							<td>50</td>
+							<td>374.3</td>
+							<td>George</td>
+							<td>$89.44</td>
+
+							<td>2009-12-15</td>
+						</tr>
+						<tr>
+							<td>51</td>
+							<td>609.1</td>
+							<td>John</td>
+							<td>$46.64</td>
+
+							<td>2011-01-22</td>
+						</tr>
+						<tr>
+							<td>52</td>
+							<td>480.3</td>
+							<td>Phil</td>
+							<td>$36.64</td>
+
+							<td>2008-07-07</td>
+						</tr>
+						<tr>
+							<td>53</td>
+							<td>814.8</td>
+							<td>Jack</td>
+							<td>$65.84</td>
+
+							<td>2009-09-19</td>
+						</tr>
+						<tr>
+							<td>54</td>
+							<td>132.2</td>
+							<td>Paul</td>
+							<td>$99.14</td>
+
+							<td>2008-10-12</td>
+						</tr>
+						<tr>
+							<td>55</td>
+							<td>350.1</td>
+							<td>Rob</td>
+							<td>$22.84</td>
+
+							<td>2010-04-22</td>
+						</tr>
+						<tr>
+							<td>56</td>
+							<td>875.7</td>
+							<td>Walt</td>
+							<td>$19.84</td>
+
+							<td>2009-08-12</td>
+						</tr>
+						<tr>
+							<td>57</td>
+							<td>158.1</td>
+							<td>Nathan</td>
+							<td>$77.44</td>
+
+							<td>2010-10-25</td>
+						</tr>
+						<tr>
+							<td>58</td>
+							<td>950.9</td>
+							<td>Dan</td>
+							<td>$16.14</td>
+
+							<td>2009-05-05</td>
+						</tr>
+						<tr>
+							<td>59</td>
+							<td>41.1</td>
+							<td>Jeff</td>
+							<td>$69.24</td>
+
+							<td>2010-04-11</td>
+						</tr>
+						<tr>
+							<td>60</td>
+							<td>595.4</td>
+							<td>Bill</td>
+							<td>$6.63</td>
+
+							<td>2009-12-09</td>
+						</tr>
+						<tr>
+							<td>61</td>
+							<td>223.4</td>
+							<td>Joe</td>
+							<td>$67.54</td>
+
+							<td>2008-03-30</td>
+						</tr>
+						<tr>
+							<td>62</td>
+							<td>199.2</td>
+							<td>Bob</td>
+							<td>$15.64</td>
+
+							<td>2009-05-28</td>
+						</tr>
+						<tr>
+							<td>63</td>
+							<td>372.8</td>
+							<td>Matt</td>
+							<td>$97.04</td>
+
+							<td>2008-04-28</td>
+						</tr>
+						<tr>
+							<td>64</td>
+							<td>925.7</td>
+							<td>Mark</td>
+							<td>$10.24</td>
+
+							<td>2008-04-17</td>
+						</tr>
+						<tr>
+							<td>65</td>
+							<td>183.1</td>
+							<td>Tom</td>
+							<td>$45.34</td>
+
+							<td>2009-01-05</td>
+						</tr>
+						<tr>
+							<td>66</td>
+							<td>921.2</td>
+							<td>Jake</td>
+							<td>$32.84</td>
+
+							<td>2009-08-23</td>
+						</tr>
+						<tr>
+							<td>67</td>
+							<td>440.8</td>
+							<td>Greg</td>
+							<td>$48.64</td>
+
+							<td>2008-12-04</td>
+						</tr>
+						<tr>
+							<td>68</td>
+							<td>339.8</td>
+							<td>Adam</td>
+							<td>$43.74</td>
+
+							<td>2009-06-08</td>
+						</tr>
+						<tr>
+							<td>69</td>
+							<td>773.7</td>
+							<td>Steve</td>
+							<td>$47.84</td>
+
+							<td>2008-06-17</td>
+						</tr>
+						<tr>
+							<td>70</td>
+							<td>502.3</td>
+							<td>George</td>
+							<td>$7.33</td>
+
+							<td>2008-09-01</td>
+						</tr>
+						<tr>
+							<td>71</td>
+							<td>124.8</td>
+							<td>John</td>
+							<td>$29.74</td>
+
+							<td>2010-10-22</td>
+						</tr>
+						<tr>
+							<td>72</td>
+							<td>213</td>
+							<td>Phil</td>
+							<td>$49.64</td>
+
+							<td>2008-02-18</td>
+						</tr>
+						<tr>
+							<td>73</td>
+							<td>667.3</td>
+							<td>Jack</td>
+							<td>$86.94</td>
+
+							<td>2008-01-14</td>
+						</tr>
+						<tr>
+							<td>74</td>
+							<td>779.8</td>
+							<td>Paul</td>
+							<td>$79.44</td>
+
+							<td>2008-05-12</td>
+						</tr>
+						<tr>
+							<td>75</td>
+							<td>883.3</td>
+							<td>Rob</td>
+							<td>$97.74</td>
+
+							<td>2009-10-17</td>
+						</tr>
+						<tr>
+							<td>76</td>
+							<td>214.4</td>
+							<td>Walt</td>
+							<td>$89.94</td>
+
+							<td>2010-11-01</td>
+						</tr>
+						<tr>
+							<td>77</td>
+							<td>743.7</td>
+							<td>Nathan</td>
+							<td>$33.94</td>
+
+							<td>2009-03-16</td>
+						</tr>
+						<tr>
+							<td>78</td>
+							<td>47</td>
+							<td>Dan</td>
+							<td>$67.94</td>
+
+							<td>2010-08-04</td>
+						</tr>
+						<tr>
+							<td>79</td>
+							<td>511</td>
+							<td>Jeff</td>
+							<td>$45.34</td>
+
+							<td>2008-12-08</td>
+						</tr>
+						<tr>
+							<td>80</td>
+							<td>666.7</td>
+							<td>Bill</td>
+							<td>$95.54</td>
+
+							<td>2009-03-03</td>
+						</tr>
+						<tr>
+							<td>81</td>
+							<td>888.5</td>
+							<td>Joe</td>
+							<td>$8.03</td>
+
+							<td>2010-02-09</td>
+						</tr>
+						<tr>
+							<td>82</td>
+							<td>785.4</td>
+							<td>Bob</td>
+							<td>$29.34</td>
+
+							<td>2008-07-06</td>
+						</tr>
+						<tr>
+							<td>83</td>
+							<td>837.7</td>
+							<td>Matt</td>
+							<td>$96.04</td>
+
+							<td>2008-02-05</td>
+						</tr>
+						<tr>
+							<td>84</td>
+							<td>860.2</td>
+							<td>Mark</td>
+							<td>$74.04</td>
+
+							<td>2010-08-12</td>
+						</tr>
+						<tr>
+							<td>85</td>
+							<td>985</td>
+							<td>Tom</td>
+							<td>$62.34</td>
+
+							<td>2010-07-17</td>
+						</tr>
+						<tr>
+							<td>86</td>
+							<td>562.3</td>
+							<td>Jake</td>
+							<td>$83.74</td>
+
+							<td>2010-03-21</td>
+						</tr>
+						<tr>
+							<td>87</td>
+							<td>467.6</td>
+							<td>Greg</td>
+							<td>$58.14</td>
+
+							<td>2008-02-16</td>
+						</tr>
+						<tr>
+							<td>88</td>
+							<td>859</td>
+							<td>Adam</td>
+							<td>$62.84</td>
+
+							<td>2010-04-12</td>
+						</tr>
+						<tr>
+							<td>89</td>
+							<td>687.5</td>
+							<td>Steve</td>
+							<td>$13.94</td>
+
+							<td>2008-07-17</td>
+						</tr>
+						<tr>
+							<td>90</td>
+							<td>993.9</td>
+							<td>George</td>
+							<td>$80.54</td>
+
+							<td>2008-05-26</td>
+						</tr>
+						<tr>
+							<td>91</td>
+							<td>373.8</td>
+							<td>John</td>
+							<td>$69.44</td>
+
+							<td>2008-08-26</td>
+						</tr>
+						<tr>
+							<td>92</td>
+							<td>50.4</td>
+							<td>Phil</td>
+							<td>$47.94</td>
+
+							<td>2009-07-30</td>
+						</tr>
+						<tr>
+							<td>93</td>
+							<td>222.8</td>
+							<td>Jack</td>
+							<td>$31.74</td>
+
+							<td>2009-06-14</td>
+						</tr>
+						<tr>
+							<td>94</td>
+							<td>263.9</td>
+							<td>Paul</td>
+							<td>$17.74</td>
+
+							<td>2008-08-16</td>
+						</tr>
+						<tr>
+							<td>95</td>
+							<td>99.2</td>
+							<td>Rob</td>
+							<td>$16.24</td>
+
+							<td>2010-08-07</td>
+						</tr>
+						<tr>
+							<td>96</td>
+							<td>911.8</td>
+							<td>Walt</td>
+							<td>$72.44</td>
+
+							<td>2010-01-31</td>
+						</tr>
+						<tr>
+							<td>97</td>
+							<td>623</td>
+							<td>Nathan</td>
+							<td>$19.24</td>
+
+							<td>2008-10-03</td>
+						</tr>
+						<tr>
+							<td>98</td>
+							<td>673.4</td>
+							<td>Dan</td>
+							<td>$5.03</td>
+
+							<td>2010-09-29</td>
+						</tr>
+						<tr>
+							<td>99</td>
+							<td>402.8</td>
+							<td>Jeff</td>
+							<td>$73.84</td>
+
+							<td>2008-01-06</td>
+						</tr>
+						<tr>
+							<td>100</td>
+							<td>584.8</td>
+							<td>Bill</td>
+							<td>$73.24</td>
+
+							<td>2010-07-26</td>
+						</tr>
+						<tr>
+							<td>101</td>
+							<td>721.7</td>
+							<td>Joe</td>
+							<td>$10.64</td>
+
+							<td>2009-08-06</td>
+						</tr>
+						<tr>
+							<td>102</td>
+							<td>938.1</td>
+							<td>Bob</td>
+							<td>$15.64</td>
+
+							<td>2011-02-11</td>
+						</tr>
+						<tr>
+							<td>103</td>
+							<td>447.1</td>
+							<td>Matt</td>
+							<td>$37.94</td>
+
+							<td>2008-12-12</td>
+						</tr>
+						<tr>
+							<td>104</td>
+							<td>915.9</td>
+							<td>Mark</td>
+							<td>$64.34</td>
+
+							<td>2009-07-05</td>
+						</tr>
+						<tr>
+							<td>105</td>
+							<td>124.2</td>
+							<td>Tom</td>
+							<td>$74.24</td>
+
+							<td>2010-01-08</td>
+						</tr>
+						<tr>
+							<td>106</td>
+							<td>955.3</td>
+							<td>Jake</td>
+							<td>$65.34</td>
+
+							<td>2009-02-23</td>
+						</tr>
+						<tr>
+							<td>107</td>
+							<td>623.6</td>
+							<td>Greg</td>
+							<td>$27.64</td>
+
+							<td>2009-10-02</td>
+						</tr>
+						<tr>
+							<td>108</td>
+							<td>872.6</td>
+							<td>Adam</td>
+							<td>$95.04</td>
+
+							<td>2009-11-30</td>
+						</tr>
+						<tr>
+							<td>109</td>
+							<td>749.4</td>
+							<td>Steve</td>
+							<td>$35.34</td>
+
+							<td>2009-01-30</td>
+						</tr>
+						<tr>
+							<td>110</td>
+							<td>764.7</td>
+							<td>George</td>
+							<td>$93.74</td>
+
+							<td>2008-03-26</td>
+						</tr>
+						<tr>
+							<td>111</td>
+							<td>585.4</td>
+							<td>John</td>
+							<td>$65.94</td>
+
+							<td>2008-07-26</td>
+						</tr>
+						<tr>
+							<td>112</td>
+							<td>99.8</td>
+							<td>Phil</td>
+							<td>$59.74</td>
+
+							<td>2009-01-23</td>
+						</tr>
+						<tr>
+							<td>113</td>
+							<td>93.2</td>
+							<td>Jack</td>
+							<td>$4.43</td>
+
+							<td>2010-04-06</td>
+						</tr>
+						<tr>
+							<td>114</td>
+							<td>403.3</td>
+							<td>Paul</td>
+							<td>$96.04</td>
+
+							<td>2009-02-16</td>
+						</tr>
+						<tr>
+							<td>115</td>
+							<td>890.2</td>
+							<td>Rob</td>
+							<td>$8.43</td>
+
+							<td>2008-04-23</td>
+						</tr>
+						<tr>
+							<td>116</td>
+							<td>538.9</td>
+							<td>Walt</td>
+							<td>$3.93</td>
+
+							<td>2010-05-19</td>
+						</tr>
+						<tr>
+							<td>117</td>
+							<td>911.6</td>
+							<td>Nathan</td>
+							<td>$66.34</td>
+
+							<td>2008-02-02</td>
+						</tr>
+						<tr>
+							<td>118</td>
+							<td>475.9</td>
+							<td>Dan</td>
+							<td>$53.54</td>
+
+							<td>2011-02-05</td>
+						</tr>
+						<tr>
+							<td>119</td>
+							<td>90.7</td>
+							<td>Jeff</td>
+							<td>$28.54</td>
+
+							<td>2009-01-16</td>
+						</tr>
+						<tr>
+							<td>120</td>
+							<td>443.3</td>
+							<td>Bill</td>
+							<td>$5.03</td>
+
+							<td>2008-11-05</td>
+						</tr>
+						<tr>
+							<td>121</td>
+							<td>527.7</td>
+							<td>Joe</td>
+							<td>$63.54</td>
+
+							<td>2010-12-07</td>
+						</tr>
+						<tr>
+							<td>122</td>
+							<td>717.7</td>
+							<td>Bob</td>
+							<td>$73.54</td>
+
+							<td>2009-08-28</td>
+						</tr>
+						<tr>
+							<td>123</td>
+							<td>63.5</td>
+							<td>Matt</td>
+							<td>$82.84</td>
+
+							<td>2009-10-18</td>
+						</tr>
+						<tr>
+							<td>124</td>
+							<td>788</td>
+							<td>Mark</td>
+							<td>$23.14</td>
+
+							<td>2009-09-02</td>
+						</tr>
+						<tr>
+							<td>125</td>
+							<td>155</td>
+							<td>Tom</td>
+							<td>$12.14</td>
+
+							<td>2009-12-08</td>
+						</tr>
+						<tr>
+							<td>126</td>
+							<td>263.6</td>
+							<td>Jake</td>
+							<td>$66.04</td>
+
+							<td>2010-01-22</td>
+						</tr>
+						<tr>
+							<td>127</td>
+							<td>25.6</td>
+							<td>Greg</td>
+							<td>$57.24</td>
+
+							<td>2008-12-28</td>
+						</tr>
+						<tr>
+							<td>128</td>
+							<td>63.9</td>
+							<td>Adam</td>
+							<td>$4.73</td>
+
+							<td>2010-09-09</td>
+						</tr>
+						<tr>
+							<td>129</td>
+							<td>52</td>
+							<td>Steve</td>
+							<td>$13.84</td>
+
+							<td>2008-06-03</td>
+						</tr>
+						<tr>
+							<td>130</td>
+							<td>392.5</td>
+							<td>George</td>
+							<td>$58.14</td>
+
+							<td>2008-07-31</td>
+						</tr>
+						<tr>
+							<td>131</td>
+							<td>670.3</td>
+							<td>John</td>
+							<td>$10.94</td>
+
+							<td>2010-08-04</td>
+						</tr>
+						<tr>
+							<td>132</td>
+							<td>607</td>
+							<td>Phil</td>
+							<td>$82.74</td>
+
+							<td>2009-10-01</td>
+						</tr>
+						<tr>
+							<td>133</td>
+							<td>140.7</td>
+							<td>Jack</td>
+							<td>$89.04</td>
+
+							<td>2009-03-16</td>
+						</tr>
+						<tr>
+							<td>134</td>
+							<td>718.3</td>
+							<td>Paul</td>
+							<td>$67.84</td>
+
+							<td>2009-12-08</td>
+						</tr>
+						<tr>
+							<td>135</td>
+							<td>255.9</td>
+							<td>Rob</td>
+							<td>$83.34</td>
+
+							<td>2010-04-27</td>
+						</tr>
+						<tr>
+							<td>136</td>
+							<td>877.6</td>
+							<td>Walt</td>
+							<td>$9.73</td>
+
+							<td>2009-03-29</td>
+						</tr>
+						<tr>
+							<td>137</td>
+							<td>538.6</td>
+							<td>Nathan</td>
+							<td>$12.24</td>
+
+							<td>2011-01-20</td>
+						</tr>
+						<tr>
+							<td>138</td>
+							<td>862.5</td>
+							<td>Dan</td>
+							<td>$18.64</td>
+
+							<td>2008-01-13</td>
+						</tr>
+						<tr>
+							<td>139</td>
+							<td>721.9</td>
+							<td>Jeff</td>
+							<td>$23.84</td>
+
+							<td>2008-06-21</td>
+						</tr>
+						<tr>
+							<td>140</td>
+							<td>866.2</td>
+							<td>Bill</td>
+							<td>$63.04</td>
+
+							<td>2010-04-25</td>
+						</tr>
+						<tr>
+							<td>141</td>
+							<td>59.9</td>
+							<td>Joe</td>
+							<td>$30.14</td>
+
+							<td>2010-08-29</td>
+						</tr>
+						<tr>
+							<td>142</td>
+							<td>888.4</td>
+							<td>Bob</td>
+							<td>$90.84</td>
+
+							<td>2010-02-09</td>
+						</tr>
+						<tr>
+							<td>143</td>
+							<td>451.5</td>
+							<td>Matt</td>
+							<td>$4.83</td>
+
+							<td>2009-10-05</td>
+						</tr>
+						<tr>
+							<td>144</td>
+							<td>842.2</td>
+							<td>Mark</td>
+							<td>$76.74</td>
+
+							<td>2008-09-27</td>
+						</tr>
+						<tr>
+							<td>145</td>
+							<td>463.9</td>
+							<td>Tom</td>
+							<td>$2.23</td>
+
+							<td>2008-03-18</td>
+						</tr>
+						<tr>
+							<td>146</td>
+							<td>206.6</td>
+							<td>Jake</td>
+							<td>$90.04</td>
+
+							<td>2008-07-08</td>
+						</tr>
+						<tr>
+							<td>147</td>
+							<td>609.3</td>
+							<td>Greg</td>
+							<td>$43.84</td>
+
+							<td>2008-11-26</td>
+						</tr>
+						<tr>
+							<td>148</td>
+							<td>583.6</td>
+							<td>Adam</td>
+							<td>$30.14</td>
+
+							<td>2009-06-29</td>
+						</tr>
+						<tr>
+							<td>149</td>
+							<td>605.2</td>
+							<td>Steve</td>
+							<td>$2.33</td>
+
+							<td>2010-03-31</td>
+						</tr>
+						<tr>
+							<td>150</td>
+							<td>764.8</td>
+							<td>George</td>
+							<td>$88.94</td>
+
+							<td>2009-01-27</td>
+						</tr>
+						<tr>
+							<td>151</td>
+							<td>505.6</td>
+							<td>John</td>
+							<td>$94.94</td>
+
+							<td>2010-01-10</td>
+						</tr>
+						<tr>
+							<td>152</td>
+							<td>355.4</td>
+							<td>Phil</td>
+							<td>$83.74</td>
+
+							<td>2009-09-25</td>
+						</tr>
+						<tr>
+							<td>153</td>
+							<td>31.9</td>
+							<td>Jack</td>
+							<td>$28.84</td>
+
+							<td>2009-11-20</td>
+						</tr>
+						<tr>
+							<td>154</td>
+							<td>598.4</td>
+							<td>Paul</td>
+							<td>$13.14</td>
+
+							<td>2009-02-23</td>
+						</tr>
+						<tr>
+							<td>155</td>
+							<td>842.9</td>
+							<td>Rob</td>
+							<td>$59.44</td>
+
+							<td>2009-03-20</td>
+						</tr>
+						<tr>
+							<td>156</td>
+							<td>920.5</td>
+							<td>Walt</td>
+							<td>$80.14</td>
+
+							<td>2008-11-24</td>
+						</tr>
+						<tr>
+							<td>157</td>
+							<td>94.5</td>
+							<td>Nathan</td>
+							<td>$41.04</td>
+
+							<td>2010-04-16</td>
+						</tr>
+						<tr>
+							<td>158</td>
+							<td>390.6</td>
+							<td>Dan</td>
+							<td>$99.44</td>
+
+							<td>2008-01-28</td>
+						</tr>
+						<tr>
+							<td>159</td>
+							<td>872.6</td>
+							<td>Jeff</td>
+							<td>$59.94</td>
+
+							<td>2008-02-23</td>
+						</tr>
+						<tr>
+							<td>160</td>
+							<td>592.3</td>
+							<td>Bill</td>
+							<td>$36.44</td>
+
+							<td>2010-12-18</td>
+						</tr>
+						<tr>
+							<td>161</td>
+							<td>942.4</td>
+							<td>Joe</td>
+							<td>$86.94</td>
+
+							<td>2010-10-19</td>
+						</tr>
+						<tr>
+							<td>162</td>
+							<td>593</td>
+							<td>Bob</td>
+							<td>$22.44</td>
+
+							<td>2010-04-13</td>
+						</tr>
+						<tr>
+							<td>163</td>
+							<td>151.1</td>
+							<td>Matt</td>
+							<td>$25.64</td>
+
+							<td>2008-01-11</td>
+						</tr>
+						<tr>
+							<td>164</td>
+							<td>757.4</td>
+							<td>Mark</td>
+							<td>$85.54</td>
+
+							<td>2008-06-10</td>
+						</tr>
+						<tr>
+							<td>165</td>
+							<td>130</td>
+							<td>Tom</td>
+							<td>$69.84</td>
+
+							<td>2010-04-29</td>
+						</tr>
+						<tr>
+							<td>166</td>
+							<td>525</td>
+							<td>Jake</td>
+							<td>$61.84</td>
+
+							<td>2009-09-10</td>
+						</tr>
+						<tr>
+							<td>167</td>
+							<td>819.8</td>
+							<td>Greg</td>
+							<td>$71.34</td>
+
+							<td>2010-12-29</td>
+						</tr>
+						<tr>
+							<td>168</td>
+							<td>552.9</td>
+							<td>Adam</td>
+							<td>$10.34</td>
+
+							<td>2010-12-22</td>
+						</tr>
+						<tr>
+							<td>169</td>
+							<td>586.8</td>
+							<td>Steve</td>
+							<td>$97.54</td>
+
+							<td>2009-09-13</td>
+						</tr>
+						<tr>
+							<td>170</td>
+							<td>643.5</td>
+							<td>George</td>
+							<td>$56.84</td>
+
+							<td>2010-11-08</td>
+						</tr>
+						<tr>
+							<td>171</td>
+							<td>588.9</td>
+							<td>John</td>
+							<td>$51.04</td>
+
+							<td>2010-06-10</td>
+						</tr>
+						<tr>
+							<td>172</td>
+							<td>482.9</td>
+							<td>Phil</td>
+							<td>$10.34</td>
+
+							<td>2007-12-25</td>
+						</tr>
+						<tr>
+							<td>173</td>
+							<td>213.9</td>
+							<td>Jack</td>
+							<td>$25.44</td>
+
+							<td>2008-10-17</td>
+						</tr>
+						<tr>
+							<td>174</td>
+							<td>233.2</td>
+							<td>Paul</td>
+							<td>$1.13</td>
+
+							<td>2008-05-01</td>
+						</tr>
+						<tr>
+							<td>175</td>
+							<td>383</td>
+							<td>Rob</td>
+							<td>$14.24</td>
+
+							<td>2010-07-18</td>
+						</tr>
+						<tr>
+							<td>176</td>
+							<td>127.1</td>
+							<td>Walt</td>
+							<td>$66.74</td>
+
+							<td>2009-05-01</td>
+						</tr>
+						<tr>
+							<td>177</td>
+							<td>672.2</td>
+							<td>Nathan</td>
+							<td>$48.64</td>
+
+							<td>2008-06-03</td>
+						</tr>
+						<tr>
+							<td>178</td>
+							<td>627.4</td>
+							<td>Dan</td>
+							<td>$3.93</td>
+
+							<td>2008-09-30</td>
+						</tr>
+						<tr>
+							<td>179</td>
+							<td>576.3</td>
+							<td>Jeff</td>
+							<td>$62.64</td>
+
+							<td>2008-09-01</td>
+						</tr>
+						<tr>
+							<td>180</td>
+							<td>124.1</td>
+							<td>Bill</td>
+							<td>$26.94</td>
+
+							<td>2010-06-20</td>
+						</tr>
+						<tr>
+							<td>181</td>
+							<td>35.3</td>
+							<td>Joe</td>
+							<td>$85.84</td>
+
+							<td>2008-11-30</td>
+						</tr>
+						<tr>
+							<td>182</td>
+							<td>815.7</td>
+							<td>Bob</td>
+							<td>$34.14</td>
+
+							<td>2009-03-30</td>
+						</tr>
+						<tr>
+							<td>183</td>
+							<td>820.6</td>
+							<td>Matt</td>
+							<td>$55.54</td>
+
+							<td>2010-01-18</td>
+						</tr>
+						<tr>
+							<td>184</td>
+							<td>81.8</td>
+							<td>Mark</td>
+							<td>$78.84</td>
+
+							<td>2010-01-31</td>
+						</tr>
+						<tr>
+							<td>185</td>
+							<td>197.5</td>
+							<td>Tom</td>
+							<td>$17.14</td>
+
+							<td>2010-07-14</td>
+						</tr>
+						<tr>
+							<td>186</td>
+							<td>10.8</td>
+							<td>Jake</td>
+							<td>$29.84</td>
+
+							<td>2009-06-23</td>
+						</tr>
+						<tr>
+							<td>187</td>
+							<td>442</td>
+							<td>Greg</td>
+							<td>$97.04</td>
+
+							<td>2011-01-06</td>
+						</tr>
+						<tr>
+							<td>188</td>
+							<td>585.7</td>
+							<td>Adam</td>
+							<td>$59.74</td>
+
+							<td>2007-12-21</td>
+						</tr>
+						<tr>
+							<td>189</td>
+							<td>832.2</td>
+							<td>Steve</td>
+							<td>$17.44</td>
+
+							<td>2009-12-14</td>
+						</tr>
+						<tr>
+							<td>190</td>
+							<td>54.3</td>
+							<td>George</td>
+							<td>$29.84</td>
+
+							<td>2010-10-22</td>
+						</tr>
+						<tr>
+							<td>191</td>
+							<td>844</td>
+							<td>John</td>
+							<td>$33.34</td>
+
+							<td>2010-05-10</td>
+						</tr>
+						<tr>
+							<td>192</td>
+							<td>143.9</td>
+							<td>Phil</td>
+							<td>$14.94</td>
+
+							<td>2008-04-07</td>
+						</tr>
+						<tr>
+							<td>193</td>
+							<td>546.8</td>
+							<td>Jack</td>
+							<td>$96.94</td>
+
+							<td>2010-01-09</td>
+						</tr>
+						<tr>
+							<td>194</td>
+							<td>203.8</td>
+							<td>Paul</td>
+							<td>$5.13</td>
+
+							<td>2009-05-09</td>
+						</tr>
+						<tr>
+							<td>195</td>
+							<td>872.3</td>
+							<td>Rob</td>
+							<td>$24.84</td>
+
+							<td>2009-11-22</td>
+						</tr>
+						<tr>
+							<td>196</td>
+							<td>682.3</td>
+							<td>Walt</td>
+							<td>$25.94</td>
+
+							<td>2010-11-02</td>
+						</tr>
+						<tr>
+							<td>197</td>
+							<td>158.7</td>
+							<td>Nathan</td>
+							<td>$70.14</td>
+
+							<td>2010-09-28</td>
+						</tr>
+						<tr>
+							<td>198</td>
+							<td>121.2</td>
+							<td>Dan</td>
+							<td>$28.74</td>
+
+							<td>2009-06-19</td>
+						</tr>
+						<tr>
+							<td>199</td>
+							<td>122.6</td>
+							<td>Jeff</td>
+							<td>$11.94</td>
+
+							<td>2010-01-06</td>
+						</tr>
+						<tr>
+							<td>200</td>
+							<td>749.8</td>
+							<td>Bill</td>
+							<td>$17.34</td>
+
+							<td>2010-12-17</td>
+						</tr>
+						<tr>
+							<td>201</td>
+							<td>646.1</td>
+							<td>Joe</td>
+							<td>$1.73</td>
+
+							<td>2008-11-05</td>
+						</tr>
+						<tr>
+							<td>202</td>
+							<td>400.4</td>
+							<td>Bob</td>
+							<td>$16.14</td>
+
+							<td>2009-04-26</td>
+						</tr>
+						<tr>
+							<td>203</td>
+							<td>495.5</td>
+							<td>Matt</td>
+							<td>$70.84</td>
+
+							<td>2009-03-21</td>
+						</tr>
+						<tr>
+							<td>204</td>
+							<td>145.3</td>
+							<td>Mark</td>
+							<td>$91.24</td>
+
+							<td>2009-05-19</td>
+						</tr>
+						<tr>
+							<td>205</td>
+							<td>582.9</td>
+							<td>Tom</td>
+							<td>$78.44</td>
+
+							<td>2010-03-02</td>
+						</tr>
+						<tr>
+							<td>206</td>
+							<td>191.3</td>
+							<td>Jake</td>
+							<td>$46.64</td>
+
+							<td>2010-12-27</td>
+						</tr>
+						<tr>
+							<td>207</td>
+							<td>97.5</td>
+							<td>Greg</td>
+							<td>$62.54</td>
+
+							<td>2010-01-15</td>
+						</tr>
+						<tr>
+							<td>208</td>
+							<td>973.7</td>
+							<td>Adam</td>
+							<td>$74.64</td>
+
+							<td>2010-12-13</td>
+						</tr>
+						<tr>
+							<td>209</td>
+							<td>447.2</td>
+							<td>Steve</td>
+							<td>$86.84</td>
+
+							<td>2008-02-27</td>
+						</tr>
+						<tr>
+							<td>210</td>
+							<td>94.3</td>
+							<td>George</td>
+							<td>$61.84</td>
+
+							<td>2008-09-15</td>
+						</tr>
+						<tr>
+							<td>211</td>
+							<td>39</td>
+							<td>John</td>
+							<td>$26.44</td>
+
+							<td>2008-10-04</td>
+						</tr>
+						<tr>
+							<td>212</td>
+							<td>316.7</td>
+							<td>Phil</td>
+							<td>$66.54</td>
+
+							<td>2009-04-09</td>
+						</tr>
+						<tr>
+							<td>213</td>
+							<td>743</td>
+							<td>Jack</td>
+							<td>$16.04</td>
+
+							<td>2008-05-05</td>
+						</tr>
+						<tr>
+							<td>214</td>
+							<td>138.4</td>
+							<td>Paul</td>
+							<td>$30.54</td>
+
+							<td>2008-01-24</td>
+						</tr>
+						<tr>
+							<td>215</td>
+							<td>584.7</td>
+							<td>Rob</td>
+							<td>$88.84</td>
+
+							<td>2010-07-19</td>
+						</tr>
+						<tr>
+							<td>216</td>
+							<td>279.3</td>
+							<td>Walt</td>
+							<td>$7.93</td>
+
+							<td>2008-11-08</td>
+						</tr>
+						<tr>
+							<td>217</td>
+							<td>233</td>
+							<td>Nathan</td>
+							<td>$17.74</td>
+
+							<td>2010-11-01</td>
+						</tr>
+						<tr>
+							<td>218</td>
+							<td>887.8</td>
+							<td>Dan</td>
+							<td>$15.04</td>
+
+							<td>2010-01-11</td>
+						</tr>
+						<tr>
+							<td>219</td>
+							<td>829.3</td>
+							<td>Jeff</td>
+							<td>$59.84</td>
+
+							<td>2009-08-12</td>
+						</tr>
+						<tr>
+							<td>220</td>
+							<td>889.7</td>
+							<td>Bill</td>
+							<td>$69.24</td>
+
+							<td>2008-05-27</td>
+						</tr>
+						<tr>
+							<td>221</td>
+							<td>123.3</td>
+							<td>Joe</td>
+							<td>$73.14</td>
+
+							<td>2009-03-29</td>
+						</tr>
+						<tr>
+							<td>222</td>
+							<td>373.9</td>
+							<td>Bob</td>
+							<td>$4.73</td>
+
+							<td>2008-03-06</td>
+						</tr>
+						<tr>
+							<td>223</td>
+							<td>785.6</td>
+							<td>Matt</td>
+							<td>$79.04</td>
+
+							<td>2008-09-07</td>
+						</tr>
+						<tr>
+							<td>224</td>
+							<td>904.9</td>
+							<td>Mark</td>
+							<td>$92.94</td>
+
+							<td>2009-08-26</td>
+						</tr>
+						<tr>
+							<td>225</td>
+							<td>935.8</td>
+							<td>Tom</td>
+							<td>$51.34</td>
+
+							<td>2009-04-19</td>
+						</tr>
+						<tr>
+							<td>226</td>
+							<td>750.5</td>
+							<td>Jake</td>
+							<td>$79.34</td>
+
+							<td>2009-07-19</td>
+						</tr>
+						<tr>
+							<td>227</td>
+							<td>31.2</td>
+							<td>Greg</td>
+							<td>$2.53</td>
+
+							<td>2010-02-09</td>
+						</tr>
+						<tr>
+							<td>228</td>
+							<td>936.7</td>
+							<td>Adam</td>
+							<td>$91.34</td>
+
+							<td>2010-08-02</td>
+						</tr>
+						<tr>
+							<td>229</td>
+							<td>588</td>
+							<td>Steve</td>
+							<td>$74.24</td>
+
+							<td>2009-04-23</td>
+						</tr>
+						<tr>
+							<td>230</td>
+							<td>107.7</td>
+							<td>George</td>
+							<td>$63.24</td>
+
+							<td>2008-05-01</td>
+						</tr>
+						<tr>
+							<td>231</td>
+							<td>245.7</td>
+							<td>John</td>
+							<td>$75.54</td>
+
+							<td>2010-08-25</td>
+						</tr>
+						<tr>
+							<td>232</td>
+							<td>647.8</td>
+							<td>Phil</td>
+							<td>$12.94</td>
+
+							<td>2010-10-19</td>
+						</tr>
+						<tr>
+							<td>233</td>
+							<td>714.6</td>
+							<td>Jack</td>
+							<td>$91.54</td>
+
+							<td>2010-02-18</td>
+						</tr>
+						<tr>
+							<td>234</td>
+							<td>941.3</td>
+							<td>Paul</td>
+							<td>$82.04</td>
+
+							<td>2009-11-28</td>
+						</tr>
+						<tr>
+							<td>235</td>
+							<td>473.3</td>
+							<td>Rob</td>
+							<td>$75.54</td>
+
+							<td>2008-05-13</td>
+						</tr>
+						<tr>
+							<td>236</td>
+							<td>893.4</td>
+							<td>Walt</td>
+							<td>$50.64</td>
+
+							<td>2010-11-17</td>
+						</tr>
+						<tr>
+							<td>237</td>
+							<td>392.7</td>
+							<td>Nathan</td>
+							<td>$53.74</td>
+
+							<td>2010-12-16</td>
+						</tr>
+						<tr>
+							<td>238</td>
+							<td>68.8</td>
+							<td>Dan</td>
+							<td>$47.44</td>
+
+							<td>2010-09-06</td>
+						</tr>
+						<tr>
+							<td>239</td>
+							<td>895.2</td>
+							<td>Jeff</td>
+							<td>$6.13</td>
+
+							<td>2009-11-12</td>
+						</tr>
+						<tr>
+							<td>240</td>
+							<td>319.1</td>
+							<td>Bill</td>
+							<td>$16.94</td>
+
+							<td>2008-09-12</td>
+						</tr>
+						<tr>
+							<td>241</td>
+							<td>434.7</td>
+							<td>Joe</td>
+							<td>$41.54</td>
+
+							<td>2011-02-04</td>
+						</tr>
+						<tr>
+							<td>242</td>
+							<td>281.1</td>
+							<td>Bob</td>
+							<td>$6.33</td>
+
+							<td>2008-05-02</td>
+						</tr>
+						<tr>
+							<td>243</td>
+							<td>174.8</td>
+							<td>Matt</td>
+							<td>$77.74</td>
+
+							<td>2008-01-24</td>
+						</tr>
+						<tr>
+							<td>244</td>
+							<td>859</td>
+							<td>Mark</td>
+							<td>$71.84</td>
+
+							<td>2010-08-30</td>
+						</tr>
+						<tr>
+							<td>245</td>
+							<td>471.8</td>
+							<td>Tom</td>
+							<td>$19.14</td>
+
+							<td>2009-11-19</td>
+						</tr>
+						<tr>
+							<td>246</td>
+							<td>597.9</td>
+							<td>Jake</td>
+							<td>$8.53</td>
+
+							<td>2008-04-26</td>
+						</tr>
+						<tr>
+							<td>247</td>
+							<td>516.5</td>
+							<td>Greg</td>
+							<td>$47.84</td>
+
+							<td>2010-01-08</td>
+						</tr>
+						<tr>
+							<td>248</td>
+							<td>460.6</td>
+							<td>Adam</td>
+							<td>$54.64</td>
+
+							<td>2008-05-08</td>
+						</tr>
+						<tr>
+							<td>249</td>
+							<td>317.8</td>
+							<td>Steve</td>
+							<td>$44.14</td>
+
+							<td>2008-07-18</td>
+						</tr>
+						<tr>
+							<td>250</td>
+							<td>917.4</td>
+							<td>George</td>
+							<td>$76.04</td>
+
+							<td>2009-01-30</td>
+						</tr>
+						<tr>
+							<td>251</td>
+							<td>149.1</td>
+							<td>John</td>
+							<td>$19.54</td>
+
+							<td>2010-05-25</td>
+						</tr>
+						<tr>
+							<td>252</td>
+							<td>136.1</td>
+							<td>Phil</td>
+							<td>$47.64</td>
+
+							<td>2010-08-05</td>
+						</tr>
+						<tr>
+							<td>253</td>
+							<td>252.2</td>
+							<td>Jack</td>
+							<td>$65.14</td>
+
+							<td>2009-11-20</td>
+						</tr>
+						<tr>
+							<td>254</td>
+							<td>283</td>
+							<td>Paul</td>
+							<td>$51.04</td>
+
+							<td>2008-12-29</td>
+						</tr>
+						<tr>
+							<td>255</td>
+							<td>133.3</td>
+							<td>Rob</td>
+							<td>$98.24</td>
+
+							<td>2009-08-08</td>
+						</tr>
+						<tr>
+							<td>256</td>
+							<td>739</td>
+							<td>Walt</td>
+							<td>$57.94</td>
+
+							<td>2009-11-14</td>
+						</tr>
+						<tr>
+							<td>257</td>
+							<td>850.4</td>
+							<td>Nathan</td>
+							<td>$9.63</td>
+
+							<td>2008-03-19</td>
+						</tr>
+						<tr>
+							<td>258</td>
+							<td>498.6</td>
+							<td>Dan</td>
+							<td>$55.64</td>
+
+							<td>2009-12-11</td>
+						</tr>
+						<tr>
+							<td>259</td>
+							<td>620.3</td>
+							<td>Jeff</td>
+							<td>$87.44</td>
+
+							<td>2008-03-04</td>
+						</tr>
+						<tr>
+							<td>260</td>
+							<td>803.4</td>
+							<td>Bill</td>
+							<td>$79.14</td>
+
+							<td>2010-08-01</td>
+						</tr>
+						<tr>
+							<td>261</td>
+							<td>155.5</td>
+							<td>Joe</td>
+							<td>$94.04</td>
+
+							<td>2008-01-13</td>
+						</tr>
+						<tr>
+							<td>262</td>
+							<td>922.3</td>
+							<td>Bob</td>
+							<td>$7.63</td>
+
+							<td>2009-07-17</td>
+						</tr>
+						<tr>
+							<td>263</td>
+							<td>751.6</td>
+							<td>Matt</td>
+							<td>$32.94</td>
+
+							<td>2008-06-07</td>
+						</tr>
+						<tr>
+							<td>264</td>
+							<td>357.9</td>
+							<td>Mark</td>
+							<td>$61.14</td>
+
+							<td>2010-01-18</td>
+						</tr>
+						<tr>
+							<td>265</td>
+							<td>682.4</td>
+							<td>Tom</td>
+							<td>$74.54</td>
+
+							<td>2009-12-28</td>
+						</tr>
+						<tr>
+							<td>266</td>
+							<td>198.4</td>
+							<td>Jake</td>
+							<td>$48.44</td>
+
+							<td>2008-08-28</td>
+						</tr>
+						<tr>
+							<td>267</td>
+							<td>799.1</td>
+							<td>Greg</td>
+							<td>$33.44</td>
+
+							<td>2008-12-17</td>
+						</tr>
+						<tr>
+							<td>268</td>
+							<td>877.4</td>
+							<td>Adam</td>
+							<td>$83.34</td>
+
+							<td>2010-09-21</td>
+						</tr>
+						<tr>
+							<td>269</td>
+							<td>501.7</td>
+							<td>Steve</td>
+							<td>$45.34</td>
+
+							<td>2010-04-28</td>
+						</tr>
+						<tr>
+							<td>270</td>
+							<td>567.4</td>
+							<td>George</td>
+							<td>$25.64</td>
+
+							<td>2009-08-30</td>
+						</tr>
+						<tr>
+							<td>271</td>
+							<td>393.4</td>
+							<td>John</td>
+							<td>$41.14</td>
+
+							<td>2009-06-22</td>
+						</tr>
+						<tr>
+							<td>272</td>
+							<td>414.4</td>
+							<td>Phil</td>
+							<td>$33.44</td>
+
+							<td>2009-09-18</td>
+						</tr>
+						<tr>
+							<td>273</td>
+							<td>911.4</td>
+							<td>Jack</td>
+							<td>$8.53</td>
+
+							<td>2010-10-03</td>
+						</tr>
+						<tr>
+							<td>274</td>
+							<td>59.2</td>
+							<td>Paul</td>
+							<td>$44.34</td>
+
+							<td>2009-07-10</td>
+						</tr>
+						<tr>
+							<td>275</td>
+							<td>716.7</td>
+							<td>Rob</td>
+							<td>$12.64</td>
+
+							<td>2008-09-18</td>
+						</tr>
+						<tr>
+							<td>276</td>
+							<td>355.7</td>
+							<td>Walt</td>
+							<td>$32.44</td>
+
+							<td>2010-04-01</td>
+						</tr>
+						<tr>
+							<td>277</td>
+							<td>573.9</td>
+							<td>Nathan</td>
+							<td>$12.34</td>
+
+							<td>2008-02-20</td>
+						</tr>
+						<tr>
+							<td>278</td>
+							<td>887.7</td>
+							<td>Dan</td>
+							<td>$0.03</td>
+
+							<td>2010-10-10</td>
+						</tr>
+						<tr>
+							<td>279</td>
+							<td>757.8</td>
+							<td>Jeff</td>
+							<td>$50.24</td>
+
+							<td>2009-01-15</td>
+						</tr>
+						<tr>
+							<td>280</td>
+							<td>501.7</td>
+							<td>Bill</td>
+							<td>$6.93</td>
+
+							<td>2009-11-07</td>
+						</tr>
+						<tr>
+							<td>281</td>
+							<td>36.9</td>
+							<td>Joe</td>
+							<td>$46.34</td>
+
+							<td>2007-12-27</td>
+						</tr>
+						<tr>
+							<td>282</td>
+							<td>512.4</td>
+							<td>Bob</td>
+							<td>$87.74</td>
+
+							<td>2009-01-16</td>
+						</tr>
+						<tr>
+							<td>283</td>
+							<td>64.3</td>
+							<td>Matt</td>
+							<td>$78.84</td>
+
+							<td>2009-04-25</td>
+						</tr>
+						<tr>
+							<td>284</td>
+							<td>944.6</td>
+							<td>Mark</td>
+							<td>$84.74</td>
+
+							<td>2010-09-20</td>
+						</tr>
+						<tr>
+							<td>285</td>
+							<td>436.3</td>
+							<td>Tom</td>
+							<td>$56.44</td>
+
+							<td>2011-02-12</td>
+						</tr>
+						<tr>
+							<td>286</td>
+							<td>672.6</td>
+							<td>Jake</td>
+							<td>$92.04</td>
+
+							<td>2008-12-21</td>
+						</tr>
+						<tr>
+							<td>287</td>
+							<td>392.6</td>
+							<td>Greg</td>
+							<td>$49.44</td>
+
+							<td>2009-05-13</td>
+						</tr>
+						<tr>
+							<td>288</td>
+							<td>446.5</td>
+							<td>Adam</td>
+							<td>$38.14</td>
+
+							<td>2009-05-13</td>
+						</tr>
+						<tr>
+							<td>289</td>
+							<td>333</td>
+							<td>Steve</td>
+							<td>$13.94</td>
+
+							<td>2010-12-15</td>
+						</tr>
+						<tr>
+							<td>290</td>
+							<td>672.1</td>
+							<td>George</td>
+							<td>$64.14</td>
+
+							<td>2008-01-02</td>
+						</tr>
+						<tr>
+							<td>291</td>
+							<td>267.3</td>
+							<td>John</td>
+							<td>$67.84</td>
+
+							<td>2009-06-21</td>
+						</tr>
+						<tr>
+							<td>292</td>
+							<td>273.9</td>
+							<td>Phil</td>
+							<td>$19.04</td>
+
+							<td>2009-01-29</td>
+						</tr>
+						<tr>
+							<td>293</td>
+							<td>614.3</td>
+							<td>Jack</td>
+							<td>$25.44</td>
+
+							<td>2008-05-29</td>
+						</tr>
+						<tr>
+							<td>294</td>
+							<td>40</td>
+							<td>Paul</td>
+							<td>$19.94</td>
+
+							<td>2011-02-04</td>
+						</tr>
+						<tr>
+							<td>295</td>
+							<td>908.8</td>
+							<td>Rob</td>
+							<td>$63.54</td>
+
+							<td>2009-09-17</td>
+						</tr>
+						<tr>
+							<td>296</td>
+							<td>903.1</td>
+							<td>Walt</td>
+							<td>$30.84</td>
+
+							<td>2009-06-17</td>
+						</tr>
+						<tr>
+							<td>297</td>
+							<td>221.2</td>
+							<td>Nathan</td>
+							<td>$70.04</td>
+
+							<td>2011-01-09</td>
+						</tr>
+						<tr>
+							<td>298</td>
+							<td>662.1</td>
+							<td>Dan</td>
+							<td>$14.74</td>
+
+							<td>2009-01-23</td>
+						</tr>
+						<tr>
+							<td>299</td>
+							<td>103.2</td>
+							<td>Jeff</td>
+							<td>$47.94</td>
+
+							<td>2009-07-03</td>
+						</tr>
+						<tr>
+							<td>300</td>
+							<td>46.2</td>
+							<td>Bill</td>
+							<td>$15.24</td>
+
+							<td>2008-05-13</td>
+						</tr>
+						<tr>
+							<td>301</td>
+							<td>58.3</td>
+							<td>Joe</td>
+							<td>$41.94</td>
+
+							<td>2010-07-06</td>
+						</tr>
+						<tr>
+							<td>302</td>
+							<td>533</td>
+							<td>Bob</td>
+							<td>$69.34</td>
+
+							<td>2011-02-10</td>
+						</tr>
+						<tr>
+							<td>303</td>
+							<td>884.6</td>
+							<td>Matt</td>
+							<td>$30.74</td>
+
+							<td>2008-09-30</td>
+						</tr>
+						<tr>
+							<td>304</td>
+							<td>24.5</td>
+							<td>Mark</td>
+							<td>$34.74</td>
+
+							<td>2009-05-18</td>
+						</tr>
+						<tr>
+							<td>305</td>
+							<td>11.7</td>
+							<td>Tom</td>
+							<td>$25.64</td>
+
+							<td>2008-03-22</td>
+						</tr>
+						<tr>
+							<td>306</td>
+							<td>563</td>
+							<td>Jake</td>
+							<td>$15.94</td>
+
+							<td>2009-03-12</td>
+						</tr>
+						<tr>
+							<td>307</td>
+							<td>34.1</td>
+							<td>Greg</td>
+							<td>$38.04</td>
+
+							<td>2008-03-30</td>
+						</tr>
+						<tr>
+							<td>308</td>
+							<td>998.8</td>
+							<td>Adam</td>
+							<td>$4.23</td>
+
+							<td>2008-09-16</td>
+						</tr>
+						<tr>
+							<td>309</td>
+							<td>344.7</td>
+							<td>Steve</td>
+							<td>$14.54</td>
+
+							<td>2010-03-25</td>
+						</tr>
+						<tr>
+							<td>310</td>
+							<td>829.5</td>
+							<td>George</td>
+							<td>$19.14</td>
+
+							<td>2010-09-16</td>
+						</tr>
+						<tr>
+							<td>311</td>
+							<td>955</td>
+							<td>John</td>
+							<td>$24.94</td>
+
+							<td>2008-11-12</td>
+						</tr>
+						<tr>
+							<td>312</td>
+							<td>758</td>
+							<td>Phil</td>
+							<td>$78.34</td>
+
+							<td>2011-01-23</td>
+						</tr>
+						<tr>
+							<td>313</td>
+							<td>750.8</td>
+							<td>Jack</td>
+							<td>$66.74</td>
+
+							<td>2008-11-11</td>
+						</tr>
+						<tr>
+							<td>314</td>
+							<td>997.8</td>
+							<td>Paul</td>
+							<td>$69.14</td>
+
+							<td>2009-12-18</td>
+						</tr>
+						<tr>
+							<td>315</td>
+							<td>443.5</td>
+							<td>Rob</td>
+							<td>$70.34</td>
+
+							<td>2010-10-10</td>
+						</tr>
+						<tr>
+							<td>316</td>
+							<td>524</td>
+							<td>Walt</td>
+							<td>$26.64</td>
+
+							<td>2008-02-09</td>
+						</tr>
+						<tr>
+							<td>317</td>
+							<td>912</td>
+							<td>Nathan</td>
+							<td>$30.04</td>
+
+							<td>2009-04-24</td>
+						</tr>
+						<tr>
+							<td>318</td>
+							<td>1000</td>
+							<td>Dan</td>
+							<td>$29.94</td>
+
+							<td>2009-06-11</td>
+						</tr>
+						<tr>
+							<td>319</td>
+							<td>234.5</td>
+							<td>Jeff</td>
+							<td>$64.34</td>
+
+							<td>2009-11-26</td>
+						</tr>
+						<tr>
+							<td>320</td>
+							<td>948.4</td>
+							<td>Bill</td>
+							<td>$47.34</td>
+
+							<td>2010-07-05</td>
+						</tr>
+						<tr>
+							<td>321</td>
+							<td>813.7</td>
+							<td>Joe</td>
+							<td>$42.84</td>
+
+							<td>2008-02-18</td>
+						</tr>
+						<tr>
+							<td>322</td>
+							<td>97.7</td>
+							<td>Bob</td>
+							<td>$18.64</td>
+
+							<td>2010-08-11</td>
+						</tr>
+						<tr>
+							<td>323</td>
+							<td>74.3</td>
+							<td>Matt</td>
+							<td>$93.74</td>
+
+							<td>2009-07-22</td>
+						</tr>
+						<tr>
+							<td>324</td>
+							<td>357.7</td>
+							<td>Mark</td>
+							<td>$93.44</td>
+
+							<td>2008-07-29</td>
+						</tr>
+						<tr>
+							<td>325</td>
+							<td>988</td>
+							<td>Tom</td>
+							<td>$37.84</td>
+
+							<td>2010-10-21</td>
+						</tr>
+						<tr>
+							<td>326</td>
+							<td>873.8</td>
+							<td>Jake</td>
+							<td>$90.24</td>
+
+							<td>2008-06-24</td>
+						</tr>
+						<tr>
+							<td>327</td>
+							<td>918.3</td>
+							<td>Greg</td>
+							<td>$81.44</td>
+
+							<td>2009-06-06</td>
+						</tr>
+						<tr>
+							<td>328</td>
+							<td>342.7</td>
+							<td>Adam</td>
+							<td>$81.44</td>
+
+							<td>2010-05-18</td>
+						</tr>
+						<tr>
+							<td>329</td>
+							<td>809</td>
+							<td>Steve</td>
+							<td>$4.83</td>
+
+							<td>2009-03-31</td>
+						</tr>
+						<tr>
+							<td>330</td>
+							<td>420.4</td>
+							<td>George</td>
+							<td>$99.74</td>
+
+							<td>2010-09-30</td>
+						</tr>
+						<tr>
+							<td>331</td>
+							<td>223</td>
+							<td>John</td>
+							<td>$81.04</td>
+
+							<td>2008-12-06</td>
+						</tr>
+						<tr>
+							<td>332</td>
+							<td>275</td>
+							<td>Phil</td>
+							<td>$90.84</td>
+
+							<td>2009-07-09</td>
+						</tr>
+						<tr>
+							<td>333</td>
+							<td>109.5</td>
+							<td>Jack</td>
+							<td>$98.24</td>
+
+							<td>2009-04-27</td>
+						</tr>
+						<tr>
+							<td>334</td>
+							<td>610.9</td>
+							<td>Paul</td>
+							<td>$34.04</td>
+
+							<td>2009-02-10</td>
+						</tr>
+						<tr>
+							<td>335</td>
+							<td>803.7</td>
+							<td>Rob</td>
+							<td>$32.84</td>
+
+							<td>2010-04-23</td>
+						</tr>
+						<tr>
+							<td>336</td>
+							<td>699.6</td>
+							<td>Walt</td>
+							<td>$20.14</td>
+
+							<td>2009-12-30</td>
+						</tr>
+						<tr>
+							<td>337</td>
+							<td>861.4</td>
+							<td>Nathan</td>
+							<td>$12.04</td>
+
+							<td>2009-05-28</td>
+						</tr>
+						<tr>
+							<td>338</td>
+							<td>323.4</td>
+							<td>Dan</td>
+							<td>$46.24</td>
+
+							<td>2008-10-25</td>
+						</tr>
+						<tr>
+							<td>339</td>
+							<td>84.3</td>
+							<td>Jeff</td>
+							<td>$27.14</td>
+
+							<td>2008-12-19</td>
+						</tr>
+						<tr>
+							<td>340</td>
+							<td>488.6</td>
+							<td>Bill</td>
+							<td>$69.24</td>
+
+							<td>2008-12-15</td>
+						</tr>
+						<tr>
+							<td>341</td>
+							<td>365.7</td>
+							<td>Joe</td>
+							<td>$91.54</td>
+
+							<td>2008-05-10</td>
+						</tr>
+						<tr>
+							<td>342</td>
+							<td>670.8</td>
+							<td>Bob</td>
+							<td>$19.04</td>
+
+							<td>2008-01-24</td>
+						</tr>
+						<tr>
+							<td>343</td>
+							<td>161.5</td>
+							<td>Matt</td>
+							<td>$29.94</td>
+
+							<td>2008-01-03</td>
+						</tr>
+						<tr>
+							<td>344</td>
+							<td>588.8</td>
+							<td>Mark</td>
+							<td>$91.04</td>
+
+							<td>2009-01-30</td>
+						</tr>
+						<tr>
+							<td>345</td>
+							<td>950.3</td>
+							<td>Tom</td>
+							<td>$71.44</td>
+
+							<td>2010-02-13</td>
+						</tr>
+						<tr>
+							<td>346</td>
+							<td>689.5</td>
+							<td>Jake</td>
+							<td>$41.34</td>
+
+							<td>2010-10-04</td>
+						</tr>
+						<tr>
+							<td>347</td>
+							<td>330.4</td>
+							<td>Greg</td>
+							<td>$27.44</td>
+
+							<td>2007-12-20</td>
+						</tr>
+						<tr>
+							<td>348</td>
+							<td>785</td>
+							<td>Adam</td>
+							<td>$59.84</td>
+
+							<td>2009-06-07</td>
+						</tr>
+						<tr>
+							<td>349</td>
+							<td>53.2</td>
+							<td>Steve</td>
+							<td>$68.24</td>
+
+							<td>2010-04-17</td>
+						</tr>
+						<tr>
+							<td>350</td>
+							<td>369.6</td>
+							<td>George</td>
+							<td>$17.14</td>
+
+							<td>2009-04-25</td>
+						</tr>
+						<tr>
+							<td>351</td>
+							<td>682.4</td>
+							<td>John</td>
+							<td>$53.64</td>
+
+							<td>2009-01-17</td>
+						</tr>
+						<tr>
+							<td>352</td>
+							<td>805.3</td>
+							<td>Phil</td>
+							<td>$20.74</td>
+
+							<td>2009-08-24</td>
+						</tr>
+						<tr>
+							<td>353</td>
+							<td>836</td>
+							<td>Jack</td>
+							<td>$36.94</td>
+
+							<td>2010-08-05</td>
+						</tr>
+						<tr>
+							<td>354</td>
+							<td>848.6</td>
+							<td>Paul</td>
+							<td>$95.74</td>
+
+							<td>2010-04-23</td>
+						</tr>
+						<tr>
+							<td>355</td>
+							<td>201</td>
+							<td>Rob</td>
+							<td>$90.74</td>
+
+							<td>2009-05-26</td>
+						</tr>
+						<tr>
+							<td>356</td>
+							<td>880.9</td>
+							<td>Walt</td>
+							<td>$59.74</td>
+
+							<td>2010-09-16</td>
+						</tr>
+						<tr>
+							<td>357</td>
+							<td>762.2</td>
+							<td>Nathan</td>
+							<td>$92.74</td>
+
+							<td>2008-05-29</td>
+						</tr>
+						<tr>
+							<td>358</td>
+							<td>763.1</td>
+							<td>Dan</td>
+							<td>$71.24</td>
+
+							<td>2010-04-21</td>
+						</tr>
+						<tr>
+							<td>359</td>
+							<td>226.4</td>
+							<td>Jeff</td>
+							<td>$76.54</td>
+
+							<td>2009-04-18</td>
+						</tr>
+						<tr>
+							<td>360</td>
+							<td>960.8</td>
+							<td>Bill</td>
+							<td>$13.54</td>
+
+							<td>2009-11-02</td>
+						</tr>
+						<tr>
+							<td>361</td>
+							<td>386.9</td>
+							<td>Joe</td>
+							<td>$81.74</td>
+
+							<td>2008-05-14</td>
+						</tr>
+						<tr>
+							<td>362</td>
+							<td>727.6</td>
+							<td>Bob</td>
+							<td>$62.34</td>
+
+							<td>2009-01-08</td>
+						</tr>
+						<tr>
+							<td>363</td>
+							<td>257.8</td>
+							<td>Matt</td>
+							<td>$45.94</td>
+
+							<td>2010-03-11</td>
+						</tr>
+						<tr>
+							<td>364</td>
+							<td>87</td>
+							<td>Mark</td>
+							<td>$30.74</td>
+
+							<td>2010-01-20</td>
+						</tr>
+						<tr>
+							<td>365</td>
+							<td>826</td>
+							<td>Tom</td>
+							<td>$50.84</td>
+
+							<td>2009-10-05</td>
+						</tr>
+						<tr>
+							<td>366</td>
+							<td>278.6</td>
+							<td>Jake</td>
+							<td>$38.94</td>
+
+							<td>2008-06-25</td>
+						</tr>
+						<tr>
+							<td>367</td>
+							<td>144.2</td>
+							<td>Greg</td>
+							<td>$15.14</td>
+
+							<td>2008-04-02</td>
+						</tr>
+						<tr>
+							<td>368</td>
+							<td>284.2</td>
+							<td>Adam</td>
+							<td>$91.44</td>
+
+							<td>2010-07-05</td>
+						</tr>
+						<tr>
+							<td>369</td>
+							<td>22</td>
+							<td>Steve</td>
+							<td>$14.14</td>
+
+							<td>2009-10-07</td>
+						</tr>
+						<tr>
+							<td>370</td>
+							<td>441.8</td>
+							<td>George</td>
+							<td>$10.14</td>
+
+							<td>2010-03-12</td>
+						</tr>
+						<tr>
+							<td>371</td>
+							<td>32.2</td>
+							<td>John</td>
+							<td>$48.84</td>
+
+							<td>2009-08-13</td>
+						</tr>
+						<tr>
+							<td>372</td>
+							<td>158.8</td>
+							<td>Phil</td>
+							<td>$21.64</td>
+
+							<td>2008-06-02</td>
+						</tr>
+						<tr>
+							<td>373</td>
+							<td>492.4</td>
+							<td>Jack</td>
+							<td>$47.34</td>
+
+							<td>2009-11-14</td>
+						</tr>
+						<tr>
+							<td>374</td>
+							<td>194.4</td>
+							<td>Paul</td>
+							<td>$56.04</td>
+
+							<td>2010-11-05</td>
+						</tr>
+						<tr>
+							<td>375</td>
+							<td>853.5</td>
+							<td>Rob</td>
+							<td>$38.64</td>
+
+							<td>2009-04-14</td>
+						</tr>
+						<tr>
+							<td>376</td>
+							<td>420</td>
+							<td>Walt</td>
+							<td>$66.54</td>
+
+							<td>2010-07-09</td>
+						</tr>
+						<tr>
+							<td>377</td>
+							<td>583.4</td>
+							<td>Nathan</td>
+							<td>$80.94</td>
+
+							<td>2010-12-30</td>
+						</tr>
+						<tr>
+							<td>378</td>
+							<td>674</td>
+							<td>Dan</td>
+							<td>$9.33</td>
+
+							<td>2010-09-22</td>
+						</tr>
+						<tr>
+							<td>379</td>
+							<td>476.8</td>
+							<td>Jeff</td>
+							<td>$11.54</td>
+
+							<td>2008-01-01</td>
+						</tr>
+						<tr>
+							<td>380</td>
+							<td>44.9</td>
+							<td>Bill</td>
+							<td>$55.74</td>
+
+							<td>2008-04-27</td>
+						</tr>
+						<tr>
+							<td>381</td>
+							<td>748</td>
+							<td>Joe</td>
+							<td>$58.94</td>
+
+							<td>2009-11-13</td>
+						</tr>
+						<tr>
+							<td>382</td>
+							<td>268.4</td>
+							<td>Bob</td>
+							<td>$74.84</td>
+
+							<td>2010-07-21</td>
+						</tr>
+						<tr>
+							<td>383</td>
+							<td>411.3</td>
+							<td>Matt</td>
+							<td>$24.04</td>
+
+							<td>2008-11-18</td>
+						</tr>
+						<tr>
+							<td>384</td>
+							<td>12.8</td>
+							<td>Mark</td>
+							<td>$43.44</td>
+
+							<td>2010-08-29</td>
+						</tr>
+						<tr>
+							<td>385</td>
+							<td>921.3</td>
+							<td>Tom</td>
+							<td>$28.84</td>
+
+							<td>2008-09-18</td>
+						</tr>
+						<tr>
+							<td>386</td>
+							<td>337.8</td>
+							<td>Jake</td>
+							<td>$70.84</td>
+
+							<td>2010-10-27</td>
+						</tr>
+						<tr>
+							<td>387</td>
+							<td>143.3</td>
+							<td>Greg</td>
+							<td>$29.14</td>
+
+							<td>2010-03-20</td>
+						</tr>
+						<tr>
+							<td>388</td>
+							<td>99.8</td>
+							<td>Adam</td>
+							<td>$96.54</td>
+
+							<td>2010-07-06</td>
+						</tr>
+						<tr>
+							<td>389</td>
+							<td>970.4</td>
+							<td>Steve</td>
+							<td>$44.24</td>
+
+							<td>2010-11-16</td>
+						</tr>
+						<tr>
+							<td>390</td>
+							<td>981.5</td>
+							<td>George</td>
+							<td>$48.74</td>
+
+							<td>2009-06-21</td>
+						</tr>
+						<tr>
+							<td>391</td>
+							<td>93.8</td>
+							<td>John</td>
+							<td>$23.44</td>
+
+							<td>2008-03-02</td>
+						</tr>
+						<tr>
+							<td>392</td>
+							<td>694.2</td>
+							<td>Phil</td>
+							<td>$50.34</td>
+
+							<td>2010-07-16</td>
+						</tr>
+						<tr>
+							<td>393</td>
+							<td>510.3</td>
+							<td>Jack</td>
+							<td>$91.44</td>
+
+							<td>2008-02-17</td>
+						</tr>
+						<tr>
+							<td>394</td>
+							<td>799.7</td>
+							<td>Paul</td>
+							<td>$92.74</td>
+
+							<td>2009-07-04</td>
+						</tr>
+						<tr>
+							<td>395</td>
+							<td>649.5</td>
+							<td>Rob</td>
+							<td>$84.84</td>
+
+							<td>2010-06-02</td>
+						</tr>
+						<tr>
+							<td>396</td>
+							<td>885.6</td>
+							<td>Walt</td>
+							<td>$18.64</td>
+
+							<td>2009-06-28</td>
+						</tr>
+						<tr>
+							<td>397</td>
+							<td>786.6</td>
+							<td>Nathan</td>
+							<td>$32.94</td>
+
+							<td>2010-05-31</td>
+						</tr>
+						<tr>
+							<td>398</td>
+							<td>496.7</td>
+							<td>Dan</td>
+							<td>$42.94</td>
+
+							<td>2010-04-21</td>
+						</tr>
+						<tr>
+							<td>399</td>
+							<td>299.9</td>
+							<td>Jeff</td>
+							<td>$39.94</td>
+
+							<td>2008-07-13</td>
+						</tr>
+						<tr>
+							<td>400</td>
+							<td>218.1</td>
+							<td>Bill</td>
+							<td>$38.14</td>
+
+							<td>2010-01-27</td>
+						</tr>
+						<tr>
+							<td>401</td>
+							<td>693.2</td>
+							<td>Joe</td>
+							<td>$47.44</td>
+
+							<td>2010-10-26</td>
+						</tr>
+						<tr>
+							<td>402</td>
+							<td>757.2</td>
+							<td>Bob</td>
+							<td>$16.94</td>
+
+							<td>2009-03-29</td>
+						</tr>
+						<tr>
+							<td>403</td>
+							<td>568.9</td>
+							<td>Matt</td>
+							<td>$67.94</td>
+
+							<td>2008-12-20</td>
+						</tr>
+						<tr>
+							<td>404</td>
+							<td>620.5</td>
+							<td>Mark</td>
+							<td>$47.84</td>
+
+							<td>2008-09-26</td>
+						</tr>
+						<tr>
+							<td>405</td>
+							<td>106.4</td>
+							<td>Tom</td>
+							<td>$12.84</td>
+
+							<td>2008-04-04</td>
+						</tr>
+						<tr>
+							<td>406</td>
+							<td>880.1</td>
+							<td>Jake</td>
+							<td>$1.33</td>
+
+							<td>2008-11-05</td>
+						</tr>
+						<tr>
+							<td>407</td>
+							<td>361.5</td>
+							<td>Greg</td>
+							<td>$80.04</td>
+
+							<td>2009-11-20</td>
+						</tr>
+						<tr>
+							<td>408</td>
+							<td>133.8</td>
+							<td>Adam</td>
+							<td>$29.74</td>
+
+							<td>2008-01-29</td>
+						</tr>
+						<tr>
+							<td>409</td>
+							<td>871.1</td>
+							<td>Steve</td>
+							<td>$59.64</td>
+
+							<td>2009-05-05</td>
+						</tr>
+						<tr>
+							<td>410</td>
+							<td>50</td>
+							<td>George</td>
+							<td>$81.54</td>
+
+							<td>2010-07-20</td>
+						</tr>
+						<tr>
+							<td>411</td>
+							<td>715.4</td>
+							<td>John</td>
+							<td>$50.84</td>
+
+							<td>2008-11-18</td>
+						</tr>
+						<tr>
+							<td>412</td>
+							<td>615.3</td>
+							<td>Phil</td>
+							<td>$26.54</td>
+
+							<td>2009-06-01</td>
+						</tr>
+						<tr>
+							<td>413</td>
+							<td>18.1</td>
+							<td>Jack</td>
+							<td>$83.44</td>
+
+							<td>2008-05-25</td>
+						</tr>
+						<tr>
+							<td>414</td>
+							<td>335</td>
+							<td>Paul</td>
+							<td>$45.44</td>
+
+							<td>2009-11-30</td>
+						</tr>
+						<tr>
+							<td>415</td>
+							<td>578.7</td>
+							<td>Rob</td>
+							<td>$56.04</td>
+
+							<td>2010-04-27</td>
+						</tr>
+						<tr>
+							<td>416</td>
+							<td>670.5</td>
+							<td>Walt</td>
+							<td>$44.04</td>
+
+							<td>2010-05-12</td>
+						</tr>
+						<tr>
+							<td>417</td>
+							<td>948.2</td>
+							<td>Nathan</td>
+							<td>$80.24</td>
+
+							<td>2009-09-23</td>
+						</tr>
+						<tr>
+							<td>418</td>
+							<td>554.8</td>
+							<td>Dan</td>
+							<td>$93.64</td>
+
+							<td>2010-09-01</td>
+						</tr>
+						<tr>
+							<td>419</td>
+							<td>590.3</td>
+							<td>Jeff</td>
+							<td>$80.74</td>
+
+							<td>2009-05-22</td>
+						</tr>
+						<tr>
+							<td>420</td>
+							<td>24.8</td>
+							<td>Bill</td>
+							<td>$85.74</td>
+
+							<td>2008-10-19</td>
+						</tr>
+						<tr>
+							<td>421</td>
+							<td>839.9</td>
+							<td>Joe</td>
+							<td>$57.24</td>
+
+							<td>2010-05-29</td>
+						</tr>
+						<tr>
+							<td>422</td>
+							<td>129.3</td>
+							<td>Bob</td>
+							<td>$18.74</td>
+
+							<td>2008-01-29</td>
+						</tr>
+						<tr>
+							<td>423</td>
+							<td>587.2</td>
+							<td>Matt</td>
+							<td>$20.54</td>
+
+							<td>2010-09-20</td>
+						</tr>
+						<tr>
+							<td>424</td>
+							<td>723.7</td>
+							<td>Mark</td>
+							<td>$54.04</td>
+
+							<td>2008-12-27</td>
+						</tr>
+						<tr>
+							<td>425</td>
+							<td>338.5</td>
+							<td>Tom</td>
+							<td>$11.94</td>
+
+							<td>2010-10-07</td>
+						</tr>
+						<tr>
+							<td>426</td>
+							<td>81</td>
+							<td>Jake</td>
+							<td>$78.94</td>
+
+							<td>2008-12-28</td>
+						</tr>
+						<tr>
+							<td>427</td>
+							<td>836.9</td>
+							<td>Greg</td>
+							<td>$73.84</td>
+
+							<td>2008-05-13</td>
+						</tr>
+						<tr>
+							<td>428</td>
+							<td>392.7</td>
+							<td>Adam</td>
+							<td>$29.24</td>
+
+							<td>2008-02-29</td>
+						</tr>
+						<tr>
+							<td>429</td>
+							<td>245</td>
+							<td>Steve</td>
+							<td>$88.34</td>
+
+							<td>2010-09-19</td>
+						</tr>
+						<tr>
+							<td>430</td>
+							<td>693.7</td>
+							<td>George</td>
+							<td>$90.74</td>
+
+							<td>2010-04-06</td>
+						</tr>
+						<tr>
+							<td>431</td>
+							<td>956.8</td>
+							<td>John</td>
+							<td>$74.74</td>
+
+							<td>2008-11-27</td>
+						</tr>
+						<tr>
+							<td>432</td>
+							<td>727.5</td>
+							<td>Phil</td>
+							<td>$87.74</td>
+
+							<td>2009-07-02</td>
+						</tr>
+						<tr>
+							<td>433</td>
+							<td>763</td>
+							<td>Jack</td>
+							<td>$46.44</td>
+
+							<td>2010-02-24</td>
+						</tr>
+						<tr>
+							<td>434</td>
+							<td>632</td>
+							<td>Paul</td>
+							<td>$18.74</td>
+
+							<td>2008-09-10</td>
+						</tr>
+						<tr>
+							<td>435</td>
+							<td>955.1</td>
+							<td>Rob</td>
+							<td>$52.64</td>
+
+							<td>2009-01-26</td>
+						</tr>
+						<tr>
+							<td>436</td>
+							<td>838.7</td>
+							<td>Walt</td>
+							<td>$60.74</td>
+
+							<td>2008-05-27</td>
+						</tr>
+						<tr>
+							<td>437</td>
+							<td>162.7</td>
+							<td>Nathan</td>
+							<td>$44.44</td>
+
+							<td>2010-09-27</td>
+						</tr>
+						<tr>
+							<td>438</td>
+							<td>288.6</td>
+							<td>Dan</td>
+							<td>$83.64</td>
+
+							<td>2008-06-30</td>
+						</tr>
+						<tr>
+							<td>439</td>
+							<td>350.1</td>
+							<td>Jeff</td>
+							<td>$8.13</td>
+
+							<td>2008-02-15</td>
+						</tr>
+						<tr>
+							<td>440</td>
+							<td>218.4</td>
+							<td>Bill</td>
+							<td>$77.54</td>
+
+							<td>2010-12-31</td>
+						</tr>
+						<tr>
+							<td>441</td>
+							<td>943.2</td>
+							<td>Joe</td>
+							<td>$73.14</td>
+
+							<td>2010-03-14</td>
+						</tr>
+						<tr>
+							<td>442</td>
+							<td>240</td>
+							<td>Bob</td>
+							<td>$45.94</td>
+
+							<td>2009-10-22</td>
+						</tr>
+						<tr>
+							<td>443</td>
+							<td>724</td>
+							<td>Matt</td>
+							<td>$22.24</td>
+
+							<td>2008-02-09</td>
+						</tr>
+						<tr>
+							<td>444</td>
+							<td>413.3</td>
+							<td>Mark</td>
+							<td>$85.44</td>
+
+							<td>2008-09-13</td>
+						</tr>
+						<tr>
+							<td>445</td>
+							<td>642.8</td>
+							<td>Tom</td>
+							<td>$80.94</td>
+
+							<td>2010-05-14</td>
+						</tr>
+						<tr>
+							<td>446</td>
+							<td>991.3</td>
+							<td>Jake</td>
+							<td>$64.84</td>
+
+							<td>2009-02-13</td>
+						</tr>
+						<tr>
+							<td>447</td>
+							<td>129.2</td>
+							<td>Greg</td>
+							<td>$81.04</td>
+
+							<td>2010-07-11</td>
+						</tr>
+						<tr>
+							<td>448</td>
+							<td>4.6</td>
+							<td>Adam</td>
+							<td>$9.93</td>
+
+							<td>2010-01-02</td>
+						</tr>
+						<tr>
+							<td>449</td>
+							<td>172.2</td>
+							<td>Steve</td>
+							<td>$44.94</td>
+
+							<td>2010-04-06</td>
+						</tr>
+						<tr>
+							<td>450</td>
+							<td>222.3</td>
+							<td>George</td>
+							<td>$66.74</td>
+
+							<td>2009-07-19</td>
+						</tr>
+						<tr>
+							<td>451</td>
+							<td>179.7</td>
+							<td>John</td>
+							<td>$61.04</td>
+
+							<td>2008-09-11</td>
+						</tr>
+						<tr>
+							<td>452</td>
+							<td>884.3</td>
+							<td>Phil</td>
+							<td>$85.04</td>
+
+							<td>2010-02-24</td>
+						</tr>
+						<tr>
+							<td>453</td>
+							<td>465.3</td>
+							<td>Jack</td>
+							<td>$57.44</td>
+
+							<td>2010-11-08</td>
+						</tr>
+						<tr>
+							<td>454</td>
+							<td>510</td>
+							<td>Paul</td>
+							<td>$98.74</td>
+
+							<td>2010-05-22</td>
+						</tr>
+						<tr>
+							<td>455</td>
+							<td>741.8</td>
+							<td>Rob</td>
+							<td>$63.04</td>
+
+							<td>2009-10-13</td>
+						</tr>
+						<tr>
+							<td>456</td>
+							<td>499.2</td>
+							<td>Walt</td>
+							<td>$62.14</td>
+
+							<td>2008-08-31</td>
+						</tr>
+						<tr>
+							<td>457</td>
+							<td>863.3</td>
+							<td>Nathan</td>
+							<td>$75.04</td>
+
+							<td>2008-01-24</td>
+						</tr>
+						<tr>
+							<td>458</td>
+							<td>670.7</td>
+							<td>Dan</td>
+							<td>$75.54</td>
+
+							<td>2008-05-17</td>
+						</tr>
+						<tr>
+							<td>459</td>
+							<td>314.2</td>
+							<td>Jeff</td>
+							<td>$92.74</td>
+
+							<td>2009-10-19</td>
+						</tr>
+						<tr>
+							<td>460</td>
+							<td>38.7</td>
+							<td>Bill</td>
+							<td>$14.94</td>
+
+							<td>2008-09-28</td>
+						</tr>
+						<tr>
+							<td>461</td>
+							<td>537.8</td>
+							<td>Joe</td>
+							<td>$32.94</td>
+
+							<td>2010-09-05</td>
+						</tr>
+						<tr>
+							<td>462</td>
+							<td>768.2</td>
+							<td>Bob</td>
+							<td>$21.34</td>
+
+							<td>2010-03-15</td>
+						</tr>
+						<tr>
+							<td>463</td>
+							<td>457.5</td>
+							<td>Matt</td>
+							<td>$67.94</td>
+
+							<td>2008-11-07</td>
+						</tr>
+						<tr>
+							<td>464</td>
+							<td>368.5</td>
+							<td>Mark</td>
+							<td>$18.94</td>
+
+							<td>2008-10-23</td>
+						</tr>
+						<tr>
+							<td>465</td>
+							<td>133.3</td>
+							<td>Tom</td>
+							<td>$93.04</td>
+
+							<td>2010-10-22</td>
+						</tr>
+						<tr>
+							<td>466</td>
+							<td>706.9</td>
+							<td>Jake</td>
+							<td>$43.04</td>
+
+							<td>2009-08-10</td>
+						</tr>
+						<tr>
+							<td>467</td>
+							<td>927.9</td>
+							<td>Greg</td>
+							<td>$29.34</td>
+
+							<td>2008-10-25</td>
+						</tr>
+						<tr>
+							<td>468</td>
+							<td>959.1</td>
+							<td>Adam</td>
+							<td>$96.34</td>
+
+							<td>2008-01-16</td>
+						</tr>
+						<tr>
+							<td>469</td>
+							<td>88.8</td>
+							<td>Steve</td>
+							<td>$27.84</td>
+
+							<td>2010-12-24</td>
+						</tr>
+						<tr>
+							<td>470</td>
+							<td>667.2</td>
+							<td>George</td>
+							<td>$31.64</td>
+
+							<td>2008-04-13</td>
+						</tr>
+						<tr>
+							<td>471</td>
+							<td>912.6</td>
+							<td>John</td>
+							<td>$85.44</td>
+
+							<td>2009-04-29</td>
+						</tr>
+						<tr>
+							<td>472</td>
+							<td>768.1</td>
+							<td>Phil</td>
+							<td>$62.24</td>
+
+							<td>2010-01-01</td>
+						</tr>
+						<tr>
+							<td>473</td>
+							<td>473.8</td>
+							<td>Jack</td>
+							<td>$8.03</td>
+
+							<td>2008-12-25</td>
+						</tr>
+						<tr>
+							<td>474</td>
+							<td>753.4</td>
+							<td>Paul</td>
+							<td>$44.84</td>
+
+							<td>2009-07-31</td>
+						</tr>
+						<tr>
+							<td>475</td>
+							<td>20.3</td>
+							<td>Rob</td>
+							<td>$58.14</td>
+
+							<td>2009-05-11</td>
+						</tr>
+						<tr>
+							<td>476</td>
+							<td>917.3</td>
+							<td>Walt</td>
+							<td>$28.84</td>
+
+							<td>2010-09-20</td>
+						</tr>
+						<tr>
+							<td>477</td>
+							<td>435.6</td>
+							<td>Nathan</td>
+							<td>$21.64</td>
+
+							<td>2008-06-24</td>
+						</tr>
+						<tr>
+							<td>478</td>
+							<td>704.3</td>
+							<td>Dan</td>
+							<td>$17.54</td>
+
+							<td>2008-05-12</td>
+						</tr>
+						<tr>
+							<td>479</td>
+							<td>728.1</td>
+							<td>Jeff</td>
+							<td>$26.44</td>
+
+							<td>2009-03-29</td>
+						</tr>
+						<tr>
+							<td>480</td>
+							<td>678.9</td>
+							<td>Bill</td>
+							<td>$93.14</td>
+
+							<td>2010-03-30</td>
+						</tr>
+						<tr>
+							<td>481</td>
+							<td>779.1</td>
+							<td>Joe</td>
+							<td>$84.34</td>
+
+							<td>2009-10-12</td>
+						</tr>
+						<tr>
+							<td>482</td>
+							<td>208.3</td>
+							<td>Bob</td>
+							<td>$61.14</td>
+
+							<td>2008-07-31</td>
+						</tr>
+						<tr>
+							<td>483</td>
+							<td>850.8</td>
+							<td>Matt</td>
+							<td>$8.53</td>
+
+							<td>2008-10-31</td>
+						</tr>
+						<tr>
+							<td>484</td>
+							<td>171.8</td>
+							<td>Mark</td>
+							<td>$83.84</td>
+
+							<td>2010-04-03</td>
+						</tr>
+						<tr>
+							<td>485</td>
+							<td>681.4</td>
+							<td>Tom</td>
+							<td>$85.94</td>
+
+							<td>2008-12-04</td>
+						</tr>
+						<tr>
+							<td>486</td>
+							<td>121.1</td>
+							<td>Jake</td>
+							<td>$77.64</td>
+
+							<td>2009-11-02</td>
+						</tr>
+						<tr>
+							<td>487</td>
+							<td>990.2</td>
+							<td>Greg</td>
+							<td>$21.14</td>
+
+							<td>2010-07-10</td>
+						</tr>
+						<tr>
+							<td>488</td>
+							<td>152</td>
+							<td>Adam</td>
+							<td>$91.64</td>
+
+							<td>2011-01-28</td>
+						</tr>
+						<tr>
+							<td>489</td>
+							<td>277</td>
+							<td>Steve</td>
+							<td>$64.44</td>
+
+							<td>2008-09-28</td>
+						</tr>
+						<tr>
+							<td>490</td>
+							<td>679.5</td>
+							<td>George</td>
+							<td>$32.34</td>
+
+							<td>2008-07-10</td>
+						</tr>
+						<tr>
+							<td>491</td>
+							<td>398</td>
+							<td>John</td>
+							<td>$10.24</td>
+
+							<td>2008-01-10</td>
+						</tr>
+						<tr>
+							<td>492</td>
+							<td>970.4</td>
+							<td>Phil</td>
+							<td>$31.04</td>
+
+							<td>2009-12-18</td>
+						</tr>
+						<tr>
+							<td>493</td>
+							<td>164.7</td>
+							<td>Jack</td>
+							<td>$16.14</td>
+
+							<td>2010-03-26</td>
+						</tr>
+						<tr>
+							<td>494</td>
+							<td>438.5</td>
+							<td>Paul</td>
+							<td>$33.24</td>
+
+							<td>2009-09-20</td>
+						</tr>
+						<tr>
+							<td>495</td>
+							<td>160.2</td>
+							<td>Rob</td>
+							<td>$1.43</td>
+
+							<td>2009-04-10</td>
+						</tr>
+						<tr>
+							<td>496</td>
+							<td>463</td>
+							<td>Walt</td>
+							<td>$13.54</td>
+
+							<td>2008-07-24</td>
+						</tr>
+						<tr>
+							<td>497</td>
+							<td>53.9</td>
+							<td>Nathan</td>
+							<td>$12.54</td>
+
+							<td>2009-03-26</td>
+						</tr>
+						<tr>
+							<td>498</td>
+							<td>860.6</td>
+							<td>Dan</td>
+							<td>$27.74</td>
+
+							<td>2008-12-18</td>
+						</tr>
+						<tr>
+							<td>499</td>
+							<td>842.2</td>
+							<td>Jeff</td>
+							<td>$55.44</td>
+
+							<td>2011-01-02</td>
+						</tr>
+					</tbody>
+				</table>
+			</body>
+</html>
diff --git a/dojox/dtl/demos/demo_Templated.html b/dojox/dtl/demos/demo_Templated.html
new file mode 100644
index 0000000..94d2a6f
--- /dev/null
+++ b/dojox/dtl/demos/demo_Templated.html
@@ -0,0 +1,36 @@
+<html>
+	<head>
+			<title>Demo using dojox.dtl._Templated</title>
+	    <script type="text/javascript" src="../../../dojo/dojo.js"
+				djConfig="isDebug: false, parseOnLoad: true"></script>
+	    <script type="text/javascript" src="../../../dijit/dijit.js"></script> 
+	    <script type="text/javascript">
+					dojo.require("dojox.dtl._Templated");
+
+					dojo.declare("Fruit", [dijit._Widget, dojox.dtl._Templated], {
+						oldRepl: "Fruit: ",
+						_dijitTemplateCompat: true,
+						items: ["apple", "banana", "orange"],
+						keyUp: function(e){
+							if(e.keyCode == dojo.keys.ENTER){
+								var i = dojo.indexOf(this.items, e.target.value);
+								if(i != -1){
+									this.items.splice(i, 1);
+								}else{
+									this.items.push(e.target.value);
+								}
+								e.target.value = "";
+								this.render();
+								dojo.query("input", this.domNode).forEach("item.focus();");
+							}
+						},
+						templateString: '<div><input dojoAttachEvent="onkeyup: keyUp"><ul>{% for item in items %}<li>${oldRepl} {{ item }}</li>{% endfor %}</ul></div>'
+					});
+
+	        dojo.require("dojo.parser");
+	    </script>
+	</head>
+	<body>
+		<div dojoType="Fruit"></div>
+	</body>
+</html>
diff --git a/dojox/dtl/demos/demo_Tree.html b/dojox/dtl/demos/demo_Tree.html
new file mode 100644
index 0000000..434d20b
--- /dev/null
+++ b/dojox/dtl/demos/demo_Tree.html
@@ -0,0 +1,48 @@
+<html>
+	<head>
+			<title>Demo to show recursion in DTL</title>
+			<script type="text/javascript" src="../../../dojo/dojo.js"
+				djConfig="isDebug: true, parseOnLoad: true"></script>
+			<script type="text/javascript" src="../../../dijit/dijit.js"></script>
+			<script type="text/javascript">
+					dojo.require("dojox.dtl._DomTemplated");
+					dojo.require("dojo.data.ItemFileReadStore");
+					dojo.require("dojo.parser");
+
+					(function(){
+						var data = {};
+
+						// The only way to get ItemFileReadStore to work
+						// synchronously (necessary for the bind_query format
+						// we'll be using below) at the time of this writing
+						// was to feed it data
+						dojo.xhrGet({
+							url: dojo.moduleUrl("dijit.tests._data", "countries.json"),
+							handleAs: "json",
+							sync: true,
+							load: function(json){
+								data = json;
+							}
+						});
+
+						dojo.declare("demo.Tree", [dijit._Widget, dojox.dtl._DomTemplated], {
+							constructor: function(){
+								this.disabled = {};
+							},
+							toggle: function(e){
+								var dataid = dojo.attr(e.target, "dataid");
+								this.disabled[dataid] = !this.disabled[dataid];
+								this.render();
+							},
+							store: new dojo.data.ItemFileReadStore({ data: data }),
+							query: { type: "continent" },
+							templateString: '{% load dojox.dtl.contrib.objects %}{% load dojox.dtl.contrib.data %}{% bind_query query to store as countries %}<ul dojoAttachEvent="onclick: toggle">{% for country in countries %}{% include countrychildren %}{% endfor %}</ul>',
+							countrychildren: '<li dataid="{{ country.getIdentity }}">{{ country.type }}: {{ country.name }}{% if country.children %}{% if disabled|key:country.getIdentity %} ↵{% else %}<ul>{% for country in country.children %}{% include countrychildren %}{% endfor %}</ul>{% endif %}{% endif %}</li>'
+						});
+					})();
+			</script>
+	</head>
+	<body>
+		<div dojoType="demo.Tree"></div>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/dtl/demos/json/blog/get_blog_1.json b/dojox/dtl/demos/json/blog/get_blog_1.json
new file mode 100644
index 0000000..9c7dd9f
--- /dev/null
+++ b/dojox/dtl/demos/json/blog/get_blog_1.json
@@ -0,0 +1 @@
+{"teaser":"I'd be able to write a lot faster.","body":"I think I wouldn't be able to think.","date":1189125242601,"author":"jim"}
\ No newline at end of file
diff --git a/dojox/dtl/demos/json/blog/get_blog_3.json b/dojox/dtl/demos/json/blog/get_blog_3.json
new file mode 100644
index 0000000..7c0a937
--- /dev/null
+++ b/dojox/dtl/demos/json/blog/get_blog_3.json
@@ -0,0 +1 @@
+{"teaser":"There was SO much sand","body":"I tried to walk so fast that I wouldn't leave foot prints.","date":1190245842601,"author":"jim"}
\ No newline at end of file
diff --git a/dojox/dtl/demos/json/blog/get_blog_list.json b/dojox/dtl/demos/json/blog/get_blog_list.json
new file mode 100644
index 0000000..40f14a7
--- /dev/null
+++ b/dojox/dtl/demos/json/blog/get_blog_list.json
@@ -0,0 +1 @@
+{"blog_list":{"3":{"title":"My Trip to the Beach"},"1":{"title":"If I Were a Robot"}}}
\ No newline at end of file
diff --git a/dojox/dtl/demos/json/blog/get_page_about.json b/dojox/dtl/demos/json/blog/get_page_about.json
new file mode 100644
index 0000000..05ddb9c
--- /dev/null
+++ b/dojox/dtl/demos/json/blog/get_page_about.json
@@ -0,0 +1 @@
+{"title":"About Jim","body":"<p>Jim is an avid golfer, enjoys long walks on the beach, and eating hot pockets</p><p>When he's not scalding his mouth, you'll find him throwing rocks at pigeons.</p>"}
\ No newline at end of file
diff --git a/dojox/dtl/demos/json/fruit.json b/dojox/dtl/demos/json/fruit.json
new file mode 100644
index 0000000..e7a0bf8
--- /dev/null
+++ b/dojox/dtl/demos/json/fruit.json
@@ -0,0 +1 @@
+{ items: ["apple", "banana", "pear"] }
\ No newline at end of file
diff --git a/dojox/dtl/demos/json/morefruit.json b/dojox/dtl/demos/json/morefruit.json
new file mode 100644
index 0000000..6a8beea
--- /dev/null
+++ b/dojox/dtl/demos/json/morefruit.json
@@ -0,0 +1 @@
+{ items: ["pineapple", "orange", "tomato"] }
\ No newline at end of file
diff --git a/dojox/dtl/demos/templates/animation.html b/dojox/dtl/demos/templates/animation.html
new file mode 100644
index 0000000..d37908b
--- /dev/null
+++ b/dojox/dtl/demos/templates/animation.html
@@ -0,0 +1,5 @@
+{% load dojox.dtl.contrib.dijit dojox.dtl.contrib.dom %}
+<div>
+	<div style="top: {{ y }}px; left: {{ x }}px; width: 10px; height: 10px; background: red; position: absolute;"> </div>
+	<div dojoAttachPoint="blue" style="top: 10px; left: 0; width: 10px; height: 10px; background: blue; position: absolute;"> </div>
+</div>
\ No newline at end of file
diff --git a/dojox/dtl/demos/templates/blog_base.html b/dojox/dtl/demos/templates/blog_base.html
new file mode 100644
index 0000000..f01bbc4
--- /dev/null
+++ b/dojox/dtl/demos/templates/blog_base.html
@@ -0,0 +1,11 @@
+<!--{% load dojox.dtl.contrib.dom %}-->
+<div>
+	<h1><!--{{ title }}--></h1>
+	<ul style="float: left; width: 100px; height: 300px; margin-right: 20px; border: 1px solid #666;">
+		<li><a onclick="_showList" style="cursor: pointer;">Home</a></li>
+		<li><a onclick="_showPage" style="cursor: pointer;" class="page-about">About Jim</a></li>
+	</ul>
+	<!--{% buffer %}-->
+	<!--{% block body %}--><!--{% endblock %}-->
+	<!--{% endbuffer %}-->
+</div>
\ No newline at end of file
diff --git a/dojox/dtl/demos/templates/blog_detail.html b/dojox/dtl/demos/templates/blog_detail.html
new file mode 100644
index 0000000..2b6146d
--- /dev/null
+++ b/dojox/dtl/demos/templates/blog_detail.html
@@ -0,0 +1,10 @@
+<!--{% extends base %}-->
+
+<!--{% block body %}-->
+<div>
+<h3><!--{{ blog.title }}--></h3>
+<div><small>posted on <!--{{ blog.date|date }}--> by <!--{{ blog.author }}--></small></div>
+<p><!--{{ blog.teaser }}--></p>
+<p><!--{{ blog.body }}--></p>
+</div>
+<!--{% endblock %}-->
\ No newline at end of file
diff --git a/dojox/dtl/demos/templates/blog_list.html b/dojox/dtl/demos/templates/blog_list.html
new file mode 100644
index 0000000..2413605
--- /dev/null
+++ b/dojox/dtl/demos/templates/blog_list.html
@@ -0,0 +1,9 @@
+<!--{% extends base %}-->
+<!--{% load dojox.dtl.contrib.dijit %}-->
+<!--{% block body %}-->
+<ul>
+<!--{% for key, blog in blog_list.items %}-->
+<li onclick="_showDetail" class="blog-{{ key }}" style="cursor: pointer;">{{ blog.title }}</li>
+<!--{% endfor %}-->
+</ul>
+<!--{% endblock %}-->
\ No newline at end of file
diff --git a/dojox/dtl/demos/templates/blog_page.html b/dojox/dtl/demos/templates/blog_page.html
new file mode 100644
index 0000000..17be535
--- /dev/null
+++ b/dojox/dtl/demos/templates/blog_page.html
@@ -0,0 +1,7 @@
+<!--{% extends "shared:templates/blog_base.html" %}-->
+<!--{% load dojox.dtl.contrib.dom %}-->
+<!--{% block body %}-->
+<div>
+	<!--{{ body|safe }}-->
+</div>
+<!--{% endblock %}-->
\ No newline at end of file
diff --git a/dojox/dtl/demos/templates/gallery.html b/dojox/dtl/demos/templates/gallery.html
new file mode 100644
index 0000000..5c9cdb8
--- /dev/null
+++ b/dojox/dtl/demos/templates/gallery.html
@@ -0,0 +1,16 @@
+{% load dojox.dtl.contrib.data %}
+{% bind_data items to store as flickr %}
+<div>
+	Type a tag and press enter: <input dojoAttachEvent="onkeypress: keyUp" value="beach">
+	<table>
+		<tr>
+			{% for item in flickr %}<td><img src="{{ item.imageUrlThumb }}" dojoAttachEvent="onclick: selectThumbnail" class="{{ item.imageUrl }}" /></td>{% endfor %}
+			<td width="100%"></td>
+		</tr>
+		<tr>
+			<td colspan="{{ flickr|length|add:1 }}">
+				{% if selected %}<img src="{{ selected }}" />{% endif %}
+			</td>
+		</tr>
+	</table>
+</div>
\ No newline at end of file
diff --git a/dojox/dtl/demos/templates/nodelist.html b/dojox/dtl/demos/templates/nodelist.html
new file mode 100644
index 0000000..ddf7def
--- /dev/null
+++ b/dojox/dtl/demos/templates/nodelist.html
@@ -0,0 +1,5 @@
+<div>
+	<ul>
+		{% for item in items %}<li>{{ item }}</li>{% endfor %}
+	</ul>
+</div>
\ No newline at end of file
diff --git a/dojox/dtl/dom.js b/dojox/dtl/dom.js
old mode 100644
new mode 100755
index 4246b49..744d0b9
--- a/dojox/dtl/dom.js
+++ b/dojox/dtl/dom.js
@@ -1,864 +1,1031 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.dom"]){
-dojo._hasResource["dojox.dtl.dom"]=true;
 dojo.provide("dojox.dtl.dom");
+
 dojo.require("dojox.dtl._base");
 dojo.require("dojox.dtl.Context");
+
 (function(){
-var dd=dojox.dtl;
-dd.BOOLS={checked:1,disabled:1,readonly:1};
-dd.TOKEN_CHANGE=-11;
-dd.TOKEN_ATTR=-12;
-dd.TOKEN_CUSTOM=-13;
-dd.TOKEN_NODE=1;
-var _1=dd.text;
-var _2=dd.dom={_attributes:{},_uppers:{},_re4:/^function anonymous\(\)\s*{\s*(.*)\s*}$/,_reTrim:/(?:^[\n\s]*(\{%)?\s*|\s*(%\})?[\n\s]*$)/g,_reSplit:/\s*%\}[\n\s]*\{%\s*/g,getTemplate:function(_3){
-if(typeof this._commentable=="undefined"){
-this._commentable=false;
-var _4=document.createElement("div");
-_4.innerHTML="<!--Test comment handling, and long comments, using comments whenever possible.-->";
-if(_4.childNodes.length&&_4.childNodes[0].nodeType==8&&_4.childNodes[0].data=="comment"){
-this._commentable=true;
-}
-}
-if(!this._commentable){
-_3=_3.replace(/<!--({({|%).*?(%|})})-->/g,"$1");
-}
-if(dojo.isIE){
-_3=_3.replace(/\b(checked|disabled|readonly|style)="/g,"t$1=\"");
-}
-_3=_3.replace(/\bstyle="/g,"tstyle=\"");
-var _5;
-var _6=dojo.isWebKit;
-var _7=[[true,"select","option"],[_6,"tr","td|th"],[_6,"thead","tr","th"],[_6,"tbody","tr","td"],[_6,"table","tbody|thead|tr","tr","td"]];
-var _8=[];
-for(var i=0,_9;_9=_7[i];i++){
-if(!_9[0]){
-continue;
-}
-if(_3.indexOf("<"+_9[1])!=-1){
-var _a=new RegExp("<"+_9[1]+"(?:.|\n)*?>((?:.|\n)+?)</"+_9[1]+">","ig");
-tagLoop:
-while(_5=_a.exec(_3)){
-var _b=_9[2].split("|");
-var _c=[];
-for(var j=0,_d;_d=_b[j];j++){
-_c.push("<"+_d+"(?:.|\n)*?>(?:.|\n)*?</"+_d+">");
-}
-var _e=[];
-var _f=dojox.string.tokenize(_5[1],new RegExp("("+_c.join("|")+")","ig"),function(_10){
-var tag=/<(\w+)/.exec(_10)[1];
-if(!_e[tag]){
-_e[tag]=true;
-_e.push(tag);
-}
-return {data:_10};
-});
-if(_e.length){
-var tag=(_e.length==1)?_e[0]:_9[2].split("|")[0];
-var _11=[];
-for(var j=0,jl=_f.length;j<jl;j++){
-var _12=_f[j];
-if(dojo.isObject(_12)){
-_11.push(_12.data);
-}else{
-var _13=_12.replace(this._reTrim,"");
-if(!_13){
-continue;
-}
-_12=_13.split(this._reSplit);
-for(var k=0,kl=_12.length;k<kl;k++){
-var _14="";
-for(var p=2,pl=_9.length;p<pl;p++){
-if(p==2){
-_14+="<"+tag+" dtlinstruction=\"{% "+_12[k].replace("\"","\\\"")+" %}\">";
-}else{
-if(tag==_9[p]){
-continue;
-}else{
-_14+="<"+_9[p]+">";
-}
-}
-}
-_14+="DTL";
-for(var p=_9.length-1;p>1;p--){
-if(p==2){
-_14+="</"+tag+">";
-}else{
-if(tag==_9[p]){
-continue;
-}else{
-_14+="</"+_9[p]+">";
-}
-}
-}
-_11.push("ÿ"+_8.length);
-_8.push(_14);
-}
-}
-}
-_3=_3.replace(_5[1],_11.join(""));
-}
-}
-}
-}
-for(var i=_8.length;i--;){
-_3=_3.replace("ÿ"+i,_8[i]);
-}
-var re=/\b([a-zA-Z_:][a-zA-Z0-9_\-\.:]*)=['"]/g;
-while(_5=re.exec(_3)){
-var _15=_5[1].toLowerCase();
-if(_15=="dtlinstruction"){
-continue;
-}
-if(_15!=_5[1]){
-this._uppers[_15]=_5[1];
-}
-this._attributes[_15]=true;
-}
-var _4=document.createElement("div");
-_4.innerHTML=_3;
-var _16={nodes:[]};
-while(_4.childNodes.length){
-_16.nodes.push(_4.removeChild(_4.childNodes[0]));
-}
-return _16;
-},tokenize:function(_17){
-var _18=[];
-for(var i=0,_19;_19=_17[i++];){
-if(_19.nodeType!=1){
-this.__tokenize(_19,_18);
-}else{
-this._tokenize(_19,_18);
-}
-}
-return _18;
-},_swallowed:[],_tokenize:function(_1a,_1b){
-var _1c=false;
-var _1d=this._swallowed;
-var i,j,tag,_1e;
-if(!_1b.first){
-_1c=_1b.first=true;
-var _1f=dd.register.getAttributeTags();
-for(i=0;tag=_1f[i];i++){
-try{
-(tag[2])({swallowNode:function(){
-throw 1;
-}},new dd.Token(dd.TOKEN_ATTR,""));
-}
-catch(e){
-_1d.push(tag);
-}
-}
-}
-for(i=0;tag=_1d[i];i++){
-var _20=_1a.getAttribute(tag[0]);
-if(_20){
-var _1d=false;
-var _21=(tag[2])({swallowNode:function(){
-_1d=true;
-return _1a;
-}},new dd.Token(dd.TOKEN_ATTR,tag[0]+" "+_20));
-if(_1d){
-if(_1a.parentNode&&_1a.parentNode.removeChild){
-_1a.parentNode.removeChild(_1a);
-}
-_1b.push([dd.TOKEN_CUSTOM,_21]);
-return;
-}
-}
-}
-var _22=[];
-if(dojo.isIE&&_1a.tagName=="SCRIPT"){
-_22.push({nodeType:3,data:_1a.text});
-_1a.text="";
-}else{
-for(i=0;_1e=_1a.childNodes[i];i++){
-_22.push(_1e);
-}
-}
-_1b.push([dd.TOKEN_NODE,_1a]);
-var _23=false;
-if(_22.length){
-_1b.push([dd.TOKEN_CHANGE,_1a]);
-_23=true;
-}
-for(var key in this._attributes){
-var _24=false;
-var _25="";
-if(key=="class"){
-_25=_1a.className||_25;
-}else{
-if(key=="for"){
-_25=_1a.htmlFor||_25;
-}else{
-if(key=="value"&&_1a.value==_1a.innerHTML){
-continue;
-}else{
-if(_1a.getAttribute){
-_25=_1a.getAttribute(key,2)||_25;
-if(key=="href"||key=="src"){
-if(dojo.isIE){
-var _26=location.href.lastIndexOf(location.hash);
-var _27=location.href.substring(0,_26).split("/");
-_27.pop();
-_27=_27.join("/")+"/";
-if(_25.indexOf(_27)==0){
-_25=_25.replace(_27,"");
-}
-_25=decodeURIComponent(_25);
-}
-}else{
-if(key=="tstyle"){
-_24=key;
-key="style";
-}else{
-if(dd.BOOLS[key.slice(1)]&&dojo.trim(_25)){
-key=key.slice(1);
-}else{
-if(this._uppers[key]&&dojo.trim(_25)){
-_24=this._uppers[key];
-}
-}
-}
-}
-}
-}
-}
-}
-if(_24){
-_1a.setAttribute(_24,"");
-_1a.removeAttribute(_24);
-}
-if(typeof _25=="function"){
-_25=_25.toString().replace(this._re4,"$1");
-}
-if(!_23){
-_1b.push([dd.TOKEN_CHANGE,_1a]);
-_23=true;
-}
-_1b.push([dd.TOKEN_ATTR,_1a,key,_25]);
-}
-for(i=0,_1e;_1e=_22[i];i++){
-if(_1e.nodeType==1){
-var _28=_1e.getAttribute("dtlinstruction");
-if(_28){
-_1e.parentNode.removeChild(_1e);
-_1e={nodeType:8,data:_28};
-}
-}
-this.__tokenize(_1e,_1b);
-}
-if(!_1c&&_1a.parentNode&&_1a.parentNode.tagName){
-if(_23){
-_1b.push([dd.TOKEN_CHANGE,_1a,true]);
-}
-_1b.push([dd.TOKEN_CHANGE,_1a.parentNode]);
-_1a.parentNode.removeChild(_1a);
-}else{
-_1b.push([dd.TOKEN_CHANGE,_1a,true,true]);
-}
-},__tokenize:function(_29,_2a){
-var _2b=_29.data;
-switch(_29.nodeType){
-case 1:
-this._tokenize(_29,_2a);
-return;
-case 3:
-if(_2b.match(/[^\s\n]/)&&(_2b.indexOf("{{")!=-1||_2b.indexOf("{%")!=-1)){
-var _2c=_1.tokenize(_2b);
-for(var j=0,_2d;_2d=_2c[j];j++){
-if(typeof _2d=="string"){
-_2a.push([dd.TOKEN_TEXT,_2d]);
-}else{
-_2a.push(_2d);
-}
-}
-}else{
-_2a.push([_29.nodeType,_29]);
-}
-if(_29.parentNode){
-_29.parentNode.removeChild(_29);
-}
-return;
-case 8:
-if(_2b.indexOf("{%")==0){
-var _2d=dojo.trim(_2b.slice(2,-2));
-if(_2d.substr(0,5)=="load "){
-var _2e=dojo.trim(_2d).split(/\s+/g);
-for(var i=1,_2f;_2f=_2e[i];i++){
-dojo["require"](_2f);
-}
-}
-_2a.push([dd.TOKEN_BLOCK,_2d]);
-}
-if(_2b.indexOf("{{")==0){
-_2a.push([dd.TOKEN_VAR,dojo.trim(_2b.slice(2,-2))]);
-}
-if(_29.parentNode){
-_29.parentNode.removeChild(_29);
-}
-return;
-}
-}};
-dd.DomTemplate=dojo.extend(function(obj){
-if(!obj.nodes){
-var _30=dojo.byId(obj);
-if(_30&&_30.nodeType==1){
-dojo.forEach(["class","src","href","name","value"],function(_31){
-_2._attributes[_31]=true;
-});
-obj={nodes:[_30]};
-}else{
-if(typeof obj=="object"){
-obj=_1.getTemplateString(obj);
-}
-obj=_2.getTemplate(obj);
-}
-}
-var _32=_2.tokenize(obj.nodes);
-if(dd.tests){
-this.tokens=_32.slice(0);
-}
-var _33=new dd._DomParser(_32);
-this.nodelist=_33.parse();
-},{_count:0,_re:/\bdojo:([a-zA-Z0-9_]+)\b/g,setClass:function(str){
-this.getRootNode().className=str;
-},getRootNode:function(){
-return this.buffer.rootNode;
-},getBuffer:function(){
-return new dd.DomBuffer();
-},render:function(_34,_35){
-_35=this.buffer=_35||this.getBuffer();
-this.rootNode=null;
-var _36=this.nodelist.render(_34||new dd.Context({}),_35);
-for(var i=0,_37;_37=_35._cache[i];i++){
-if(_37._cache){
-_37._cache.length=0;
-}
-}
-return _36;
-},unrender:function(_38,_39){
-return this.nodelist.unrender(_38,_39);
-}});
-dd.DomBuffer=dojo.extend(function(_3a){
-this._parent=_3a;
-this._cache=[];
-},{concat:function(_3b){
-var _3c=this._parent;
-if(_3c&&_3b.parentNode&&_3b.parentNode===_3c&&!_3c._dirty){
-return this;
-}
-if(_3b.nodeType==1&&!this.rootNode){
-this.rootNode=_3b||true;
-return this;
-}
-if(!_3c){
-if(_3b.nodeType==3&&dojo.trim(_3b.data)){
-throw new Error("Text should not exist outside of the root node in template");
-}
-return this;
-}
-if(this._closed){
-if(_3b.nodeType==3&&!dojo.trim(_3b.data)){
-return this;
-}else{
-throw new Error("Content should not exist outside of the root node in template");
-}
-}
-if(_3c._dirty){
-if(_3b._drawn&&_3b.parentNode==_3c){
-var _3d=_3c._cache;
-if(_3d){
-for(var i=0,_3e;_3e=_3d[i];i++){
-this.onAddNode&&this.onAddNode(_3e);
-_3c.insertBefore(_3e,_3b);
-this.onAddNodeComplete&&this.onAddNodeComplete(_3e);
-}
-_3d.length=0;
-}
-}
-_3c._dirty=false;
-}
-if(!_3c._cache){
-_3c._cache=[];
-this._cache.push(_3c);
-}
-_3c._dirty=true;
-_3c._cache.push(_3b);
-return this;
-},remove:function(obj){
-if(typeof obj=="string"){
-if(this._parent){
-this._parent.removeAttribute(obj);
-}
-}else{
-if(obj.nodeType==1&&!this.getRootNode()&&!this._removed){
-this._removed=true;
-return this;
-}
-if(obj.parentNode){
-this.onRemoveNode&&this.onRemoveNode(obj);
-if(obj.parentNode){
-obj.parentNode.removeChild(obj);
-}
-}
-}
-return this;
-},setAttribute:function(key,_3f){
-var old=dojo.attr(this._parent,key);
-if(this.onChangeAttribute&&old!=_3f){
-this.onChangeAttribute(this._parent,key,old,_3f);
-}
-if(key=="style"){
-this._parent.style.cssText=_3f;
-}else{
-dojo.attr(this._parent,key,_3f);
-}
-return this;
-},addEvent:function(_40,_41,fn,_42){
-if(!_40.getThis()){
-throw new Error("You must use Context.setObject(instance)");
-}
-this.onAddEvent&&this.onAddEvent(this.getParent(),_41,fn);
-var _43=fn;
-if(dojo.isArray(_42)){
-_43=function(e){
-this[fn].apply(this,[e].concat(_42));
-};
-}
-return dojo.connect(this.getParent(),_41,_40.getThis(),_43);
-},setParent:function(_44,up,_45){
-if(!this._parent){
-this._parent=this._first=_44;
-}
-if(up&&_45&&_44===this._first){
-this._closed=true;
-}
-if(up){
-var _46=this._parent;
-var _47="";
-var ie=dojo.isIE&&_46.tagName=="SCRIPT";
-if(ie){
-_46.text="";
-}
-if(_46._dirty){
-var _48=_46._cache;
-var _49=(_46.tagName=="SELECT"&&!_46.options.length);
-for(var i=0,_4a;_4a=_48[i];i++){
-if(_4a!==_46){
-this.onAddNode&&this.onAddNode(_4a);
-if(ie){
-_47+=_4a.data;
-}else{
-_46.appendChild(_4a);
-if(_49&&_4a.defaultSelected&&i){
-_49=i;
-}
-}
-this.onAddNodeComplete&&this.onAddNodeComplete(_4a);
-}
-}
-if(_49){
-_46.options.selectedIndex=(typeof _49=="number")?_49:0;
-}
-_48.length=0;
-_46._dirty=false;
-}
-if(ie){
-_46.text=_47;
-}
-}
-this._parent=_44;
-this.onSetParent&&this.onSetParent(_44,up,_45);
-return this;
-},getParent:function(){
-return this._parent;
-},getRootNode:function(){
-return this.rootNode;
-}});
-dd._DomNode=dojo.extend(function(_4b){
-this.contents=_4b;
-},{render:function(_4c,_4d){
-this._rendered=true;
-return _4d.concat(this.contents);
-},unrender:function(_4e,_4f){
-if(!this._rendered){
-return _4f;
-}
-this._rendered=false;
-return _4f.remove(this.contents);
-},clone:function(_50){
-return new this.constructor(this.contents);
-}});
-dd._DomNodeList=dojo.extend(function(_51){
-this.contents=_51||[];
-},{push:function(_52){
-this.contents.push(_52);
-},unshift:function(_53){
-this.contents.unshift(_53);
-},render:function(_54,_55,_56){
-_55=_55||dd.DomTemplate.prototype.getBuffer();
-if(_56){
-var _57=_55.getParent();
-}
-for(var i=0;i<this.contents.length;i++){
-_55=this.contents[i].render(_54,_55);
-if(!_55){
-throw new Error("Template node render functions must return their buffer");
-}
-}
-if(_57){
-_55.setParent(_57);
-}
-return _55;
-},dummyRender:function(_58,_59,_5a){
-var div=document.createElement("div");
-var _5b=_59.getParent();
-var old=_5b._clone;
-_5b._clone=div;
-var _5c=this.clone(_59,div);
-if(old){
-_5b._clone=old;
-}else{
-_5b._clone=null;
-}
-_59=dd.DomTemplate.prototype.getBuffer();
-_5c.unshift(new dd.ChangeNode(div));
-_5c.unshift(new dd._DomNode(div));
-_5c.push(new dd.ChangeNode(div,true));
-_5c.render(_58,_59);
-if(_5a){
-return _59.getRootNode();
-}
-var _5d=div.innerHTML;
-return (dojo.isIE)?_5d.replace(/\s*_(dirty|clone)="[^"]*"/g,""):_5d;
-},unrender:function(_5e,_5f,_60){
-if(_60){
-var _61=_5f.getParent();
-}
-for(var i=0;i<this.contents.length;i++){
-_5f=this.contents[i].unrender(_5e,_5f);
-if(!_5f){
-throw new Error("Template node render functions must return their buffer");
-}
-}
-if(_61){
-_5f.setParent(_61);
-}
-return _5f;
-},clone:function(_62){
-var _63=_62.getParent();
-var _64=this.contents;
-var _65=new dd._DomNodeList();
-var _66=[];
-for(var i=0;i<_64.length;i++){
-var _67=_64[i].clone(_62);
-if(_67 instanceof dd.ChangeNode||_67 instanceof dd._DomNode){
-var _68=_67.contents._clone;
-if(_68){
-_67.contents=_68;
-}else{
-if(_63!=_67.contents&&_67 instanceof dd._DomNode){
-var _69=_67.contents;
-_67.contents=_67.contents.cloneNode(false);
-_62.onClone&&_62.onClone(_69,_67.contents);
-_66.push(_69);
-_69._clone=_67.contents;
-}
-}
-}
-_65.push(_67);
-}
-for(var i=0,_67;_67=_66[i];i++){
-_67._clone=null;
-}
-return _65;
-},rtrim:function(){
-while(1){
-var i=this.contents.length-1;
-if(this.contents[i] instanceof dd._DomTextNode&&this.contents[i].isEmpty()){
-this.contents.pop();
-}else{
-break;
-}
-}
-return this;
-}});
-dd._DomVarNode=dojo.extend(function(str){
-this.contents=new dd._Filter(str);
-},{render:function(_6a,_6b){
-var str=this.contents.resolve(_6a);
-var _6c="text";
-if(str){
-if(str.render&&str.getRootNode){
-_6c="injection";
-}else{
-if(str.safe){
-if(str.nodeType){
-_6c="node";
-}else{
-if(str.toString){
-str=str.toString();
-_6c="html";
-}
-}
-}
-}
-}
-if(this._type&&_6c!=this._type){
-this.unrender(_6a,_6b);
-}
-this._type=_6c;
-switch(_6c){
-case "text":
-this._rendered=true;
-this._txt=this._txt||document.createTextNode(str);
-if(this._txt.data!=str){
-var old=this._txt.data;
-this._txt.data=str;
-_6b.onChangeData&&_6b.onChangeData(this._txt,old,this._txt.data);
-}
-return _6b.concat(this._txt);
-case "injection":
-var _6d=str.getRootNode();
-if(this._rendered&&_6d!=this._root){
-_6b=this.unrender(_6a,_6b);
-}
-this._root=_6d;
-var _6e=this._injected=new dd._DomNodeList();
-_6e.push(new dd.ChangeNode(_6b.getParent()));
-_6e.push(new dd._DomNode(_6d));
-_6e.push(str);
-_6e.push(new dd.ChangeNode(_6b.getParent()));
-this._rendered=true;
-return _6e.render(_6a,_6b);
-case "node":
-this._rendered=true;
-if(this._node&&this._node!=str&&this._node.parentNode&&this._node.parentNode===_6b.getParent()){
-this._node.parentNode.removeChild(this._node);
-}
-this._node=str;
-return _6b.concat(str);
-case "html":
-if(this._rendered&&this._src!=str){
-_6b=this.unrender(_6a,_6b);
-}
-this._src=str;
-if(!this._rendered){
-this._rendered=true;
-this._html=this._html||[];
-var div=(this._div=this._div||document.createElement("div"));
-div.innerHTML=str;
-var _6f=div.childNodes;
-while(_6f.length){
-var _70=div.removeChild(_6f[0]);
-this._html.push(_70);
-_6b=_6b.concat(_70);
-}
-}
-return _6b;
-default:
-return _6b;
-}
-},unrender:function(_71,_72){
-if(!this._rendered){
-return _72;
-}
-this._rendered=false;
-switch(this._type){
-case "text":
-return _72.remove(this._txt);
-case "injection":
-return this._injection.unrender(_71,_72);
-case "node":
-if(this._node.parentNode===_72.getParent()){
-return _72.remove(this._node);
-}
-return _72;
-case "html":
-for(var i=0,l=this._html.length;i<l;i++){
-_72=_72.remove(this._html[i]);
-}
-return _72;
-default:
-return _72;
-}
-},clone:function(){
-return new this.constructor(this.contents.getExpression());
-}});
-dd.ChangeNode=dojo.extend(function(_73,up,_74){
-this.contents=_73;
-this.up=up;
-this.root=_74;
-},{render:function(_75,_76){
-return _76.setParent(this.contents,this.up,this.root);
-},unrender:function(_77,_78){
-if(!_78.getParent()){
-return _78;
-}
-return _78.setParent(this.contents);
-},clone:function(){
-return new this.constructor(this.contents,this.up,this.root);
-}});
-dd.AttributeNode=dojo.extend(function(key,_79){
-this.key=key;
-this.value=_79;
-this.contents=_79;
-if(this._pool[_79]){
-this.nodelist=this._pool[_79];
-}else{
-if(!(this.nodelist=dd.quickFilter(_79))){
-this.nodelist=(new dd.Template(_79,true)).nodelist;
-}
-this._pool[_79]=this.nodelist;
-}
-this.contents="";
-},{_pool:{},render:function(_7a,_7b){
-var key=this.key;
-var _7c=this.nodelist.dummyRender(_7a);
-if(dd.BOOLS[key]){
-_7c=!(_7c=="false"||_7c=="undefined"||!_7c);
-}
-if(_7c!==this.contents){
-this.contents=_7c;
-return _7b.setAttribute(key,_7c);
-}
-return _7b;
-},unrender:function(_7d,_7e){
-this.contents="";
-return _7e.remove(this.key);
-},clone:function(_7f){
-return new this.constructor(this.key,this.value);
-}});
-dd._DomTextNode=dojo.extend(function(str){
-this.contents=document.createTextNode(str);
-this.upcoming=str;
-},{set:function(_80){
-this.upcoming=_80;
-return this;
-},render:function(_81,_82){
-if(this.contents.data!=this.upcoming){
-var old=this.contents.data;
-this.contents.data=this.upcoming;
-_82.onChangeData&&_82.onChangeData(this.contents,old,this.upcoming);
-}
-return _82.concat(this.contents);
-},unrender:function(_83,_84){
-return _84.remove(this.contents);
-},isEmpty:function(){
-return !dojo.trim(this.contents.data);
-},clone:function(){
-return new this.constructor(this.contents.data);
-}});
-dd._DomParser=dojo.extend(function(_85){
-this.contents=_85;
-},{i:0,parse:function(_86){
-var _87={};
-var _88=this.contents;
-if(!_86){
-_86=[];
-}
-for(var i=0;i<_86.length;i++){
-_87[_86[i]]=true;
-}
-var _89=new dd._DomNodeList();
-while(this.i<_88.length){
-var _8a=_88[this.i++];
-var _8b=_8a[0];
-var _8c=_8a[1];
-if(_8b==dd.TOKEN_CUSTOM){
-_89.push(_8c);
-}else{
-if(_8b==dd.TOKEN_CHANGE){
-var _8d=new dd.ChangeNode(_8c,_8a[2],_8a[3]);
-_8c[_8d.attr]=_8d;
-_89.push(_8d);
-}else{
-if(_8b==dd.TOKEN_ATTR){
-var fn=_1.getTag("attr:"+_8a[2],true);
-if(fn&&_8a[3]){
-if(_8a[3].indexOf("{%")!=-1||_8a[3].indexOf("{{")!=-1){
-_8c.setAttribute(_8a[2],"");
-}
-_89.push(fn(null,new dd.Token(_8b,_8a[2]+" "+_8a[3])));
-}else{
-if(dojo.isString(_8a[3])){
-if(_8a[2]=="style"||_8a[3].indexOf("{%")!=-1||_8a[3].indexOf("{{")!=-1){
-_89.push(new dd.AttributeNode(_8a[2],_8a[3]));
-}else{
-if(dojo.trim(_8a[3])){
-try{
-dojo.attr(_8c,_8a[2],_8a[3]);
-}
-catch(e){
-}
-}
-}
-}
-}
-}else{
-if(_8b==dd.TOKEN_NODE){
-var fn=_1.getTag("node:"+_8c.tagName.toLowerCase(),true);
-if(fn){
-_89.push(fn(null,new dd.Token(_8b,_8c),_8c.tagName.toLowerCase()));
-}
-_89.push(new dd._DomNode(_8c));
-}else{
-if(_8b==dd.TOKEN_VAR){
-_89.push(new dd._DomVarNode(_8c));
-}else{
-if(_8b==dd.TOKEN_TEXT){
-_89.push(new dd._DomTextNode(_8c.data||_8c));
-}else{
-if(_8b==dd.TOKEN_BLOCK){
-if(_87[_8c]){
---this.i;
-return _89;
-}
-var cmd=_8c.split(/\s+/g);
-if(cmd.length){
-cmd=cmd[0];
-var fn=_1.getTag(cmd);
-if(typeof fn!="function"){
-throw new Error("Function not found for "+cmd);
-}
-var tpl=fn(this,new dd.Token(_8b,_8c));
-if(tpl){
-_89.push(tpl);
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-if(_86.length){
-throw new Error("Could not find closing tag(s): "+_86.toString());
-}
-return _89;
-},next_token:function(){
-var _8e=this.contents[this.i++];
-return new dd.Token(_8e[0],_8e[1]);
-},delete_first_token:function(){
-this.i++;
-},skip_past:function(_8f){
-return dd._Parser.prototype.skip_past.call(this,_8f);
-},create_variable_node:function(_90){
-return new dd._DomVarNode(_90);
-},create_text_node:function(_91){
-return new dd._DomTextNode(_91||"");
-},getTemplate:function(loc){
-return new dd.DomTemplate(_2.getTemplate(loc));
-}});
+	var dd = dojox.dtl;
+
+	dd.BOOLS = {checked: 1, disabled: 1, readonly: 1};
+	dd.TOKEN_CHANGE = -11;
+	dd.TOKEN_ATTR = -12;
+	dd.TOKEN_CUSTOM = -13;
+	dd.TOKEN_NODE = 1;
+
+	var ddt = dd.text;
+	var ddh = dd.dom = {
+		_attributes: {},
+		_uppers: {},
+		_re4: /^function anonymous\(\)\s*{\s*(.*)\s*}$/,
+		_reTrim: /(?:^[\n\s]*(\{%)?\s*|\s*(%\})?[\n\s]*$)/g,
+		_reSplit: /\s*%\}[\n\s]*\{%\s*/g,
+		getTemplate: function(text){
+			if(typeof this._commentable == "undefined"){
+				// Check to see if the browser can handle comments
+				this._commentable = false;
+				var div = document.createElement("div");
+				div.innerHTML = "<!--Test comment handling, and long comments, using comments whenever possible.-->";
+				if(div.childNodes.length && div.childNodes[0].nodeType == 8 && div.childNodes[0].data == "comment"){
+					this._commentable = true;
+				}
+			}
+
+			if(!this._commentable){
+				// Strip comments
+				text = text.replace(/<!--({({|%).*?(%|})})-->/g, "$1");
+			}
+
+			if(dojo.isIE){
+				text = text.replace(/\b(checked|disabled|readonly|style)="/g, 't$1="');
+			}
+			text = text.replace(/\bstyle="/g, 'tstyle="');
+
+			var match;
+			var table = dojo.isWebKit;
+			var pairs = [ // Format: [enable, parent, allowed children (first for nesting), nestings]
+				[true, "select", "option"],
+				[table, "tr", "td|th"],
+				[table, "thead", "tr", "th"],
+				[table, "tbody", "tr", "td"],
+				[table, "table", "tbody|thead|tr", "tr", "td"]
+			];
+			var replacements = [];
+			// Some tags can't contain text. So we wrap the text in tags that they can have.
+			for(var i = 0, pair; pair = pairs[i]; i++){
+				if(!pair[0]){
+					continue;
+				}
+				if(text.indexOf("<" + pair[1]) != -1){
+					var selectRe = new RegExp("<" + pair[1] + "(?:.|\n)*?>((?:.|\n)+?)</" + pair[1] + ">", "ig");
+					tagLoop: while(match = selectRe.exec(text)){
+						// Do it like this to make sure we don't double-wrap
+						var inners = pair[2].split("|");
+						var innerRe = [];
+						for(var j = 0, inner; inner = inners[j]; j++){
+							innerRe.push("<" + inner + "(?:.|\n)*?>(?:.|\n)*?</" + inner + ">");
+						}
+						var tags = [];
+						var tokens = dojox.string.tokenize(match[1], new RegExp("(" + innerRe.join("|") + ")", "ig"), function(data){
+							var tag = /<(\w+)/.exec(data)[1];
+							if(!tags[tag]){
+								tags[tag] = true;
+								tags.push(tag);
+							}
+							return {data: data};
+						});
+						if(tags.length){
+							var tag = (tags.length == 1) ? tags[0] : pair[2].split("|")[0];
+
+							var replace = [];
+							for(var j = 0, jl = tokens.length; j < jl; j++) {
+								var token = tokens[j];
+								if(dojo.isObject(token)){
+									replace.push(token.data);
+								}else{
+									var stripped = token.replace(this._reTrim, "");
+									if(!stripped){ continue; }
+									token = stripped.split(this._reSplit);
+									for(var k = 0, kl = token.length; k < kl; k++){
+										var replacement = "";
+										for(var p = 2, pl = pair.length; p < pl; p++){
+											if(p == 2){
+												replacement += "<" + tag + ' dtlinstruction="{% ' + token[k].replace('"', '\\"') + ' %}">';
+											}else if(tag == pair[p]) {
+												continue;
+											}else{
+												replacement += "<" + pair[p] + ">";
+											}
+										}
+										replacement += "DTL";
+										for(var p = pair.length - 1; p > 1; p--){
+											if(p == 2){
+												replacement += "</" + tag + ">";
+											}else if(tag == pair[p]) {
+												continue;
+											}else{
+												replacement += "</" + pair[p] + ">";
+											}
+										}
+										replace.push("\xFF" + replacements.length);
+										replacements.push(replacement);
+									}
+								}
+							}
+							text = text.replace(match[1], replace.join(""));
+						}
+					}
+				}
+			}
+
+			for(var i=replacements.length; i--;){
+				text = text.replace("\xFF" + i, replacements[i]);
+			}
+
+			var re = /\b([a-zA-Z_:][a-zA-Z0-9_\-\.:]*)=['"]/g;
+			while(match = re.exec(text)){
+				var lower = match[1].toLowerCase();
+				if(lower == "dtlinstruction"){ continue; }
+				if(lower != match[1]){
+					this._uppers[lower] = match[1];
+				}
+				this._attributes[lower] = true;
+			}
+			var div = document.createElement("div");
+			div.innerHTML = text;
+			var output = {nodes: []};
+			while(div.childNodes.length){
+				output.nodes.push(div.removeChild(div.childNodes[0]))
+			}
+
+			return output;
+		},
+		tokenize: function(/*Node*/ nodes){
+			var tokens = [];
+
+			for(var i = 0, node; node = nodes[i++];){
+				if(node.nodeType != 1){
+					this.__tokenize(node, tokens);
+				}else{
+					this._tokenize(node, tokens);
+				}
+			}
+
+			return tokens;
+		},
+		_swallowed: [],
+		_tokenize: function(/*Node*/ node, /*Array*/ tokens){
+			var first = false;
+			var swallowed = this._swallowed;
+			var i, j, tag, child;
+
+			if(!tokens.first){
+				// Try to efficiently associate tags that use an attribute to
+				// remove the node from DOM (eg dojoType) so that we can efficiently
+				// locate them later in the tokenizing.
+				first = tokens.first = true;
+				var tags = dd.register.getAttributeTags();
+				for(i = 0; tag = tags[i]; i++){
+					try{
+						(tag[2])({ swallowNode: function(){ throw 1; }}, new dd.Token(dd.TOKEN_ATTR, ""));
+					}catch(e){
+						swallowed.push(tag);
+					}
+				}
+			}
+
+			for(i = 0; tag = swallowed[i]; i++){
+				var text = node.getAttribute(tag[0]);
+				if(text){
+					var swallowed = false;
+					var custom = (tag[2])({ swallowNode: function(){ swallowed = true; return node; }}, new dd.Token(dd.TOKEN_ATTR, tag[0] + " " + text));
+					if(swallowed){
+						if(node.parentNode && node.parentNode.removeChild){
+							node.parentNode.removeChild(node);
+						}
+						tokens.push([dd.TOKEN_CUSTOM, custom]);
+						return;
+					}
+				}
+			}
+
+			var children = [];
+			if(dojo.isIE && node.tagName == "SCRIPT"){
+				children.push({
+					nodeType: 3,
+					data: node.text
+				});
+				node.text = "";
+			}else{
+				for(i = 0; child = node.childNodes[i]; i++){
+					children.push(child);
+				}
+			}
+
+			tokens.push([dd.TOKEN_NODE, node]);
+
+			var change = false;
+			if(children.length){
+				// Only do a change request if we need to
+				tokens.push([dd.TOKEN_CHANGE, node]);
+				change = true;
+			}
+
+			for(var key in this._attributes){
+				var clear = false;
+
+				var value = "";
+				if(key == "class"){
+					value = node.className || value;
+				}else if(key == "for"){
+					value = node.htmlFor || value;
+				}else if(key == "value" && node.value == node.innerHTML){
+					// Sometimes .value is set the same as the contents of the item (button)
+					continue;
+				}else if(node.getAttribute){
+					value = node.getAttribute(key, 2) || value;
+					if(key == "href" || key == "src"){
+						if(dojo.isIE){
+							var hash = location.href.lastIndexOf(location.hash);
+							var href = location.href.substring(0, hash).split("/");
+							href.pop();
+							href = href.join("/") + "/";
+							if(value.indexOf(href) == 0){
+								value = value.replace(href, "");
+							}
+							value = decodeURIComponent(value);
+						}
+					}else if(key == "tstyle"){
+						clear = key; // Placeholder because we can't use style
+						key = "style";
+					}else if(dd.BOOLS[key.slice(1)] && dojo.trim(value)){
+						key = key.slice(1);
+					}else if(this._uppers[key] && dojo.trim(value)){
+						clear = this._uppers[key]; // Replaced by lowercase
+					}
+				}
+
+				if(clear){
+					// Clear out values that are different than will
+					// be used in plugins
+					node.setAttribute(clear, "");
+					node.removeAttribute(clear);
+				}
+
+				if(typeof value == "function"){
+					value = value.toString().replace(this._re4, "$1");
+				}
+
+				if(!change){
+					// Only do a change request if we need to
+					tokens.push([dd.TOKEN_CHANGE, node]);
+					change = true;
+				}
+
+				// We'll have to resolve attributes during parsing (some ref plugins)
+
+				tokens.push([dd.TOKEN_ATTR, node, key, value]);
+			}
+
+			for(i = 0, child; child = children[i]; i++){
+				if(child.nodeType == 1){
+					var instruction = child.getAttribute("dtlinstruction");
+					if(instruction){
+						child.parentNode.removeChild(child);
+						child = {
+							nodeType: 8,
+							data: instruction
+						};
+					}
+				}
+				this.__tokenize(child, tokens);
+			}
+
+			if(!first && node.parentNode && node.parentNode.tagName){
+				if(change){
+					tokens.push([dd.TOKEN_CHANGE, node, true]);
+				}
+				tokens.push([dd.TOKEN_CHANGE, node.parentNode]);
+				node.parentNode.removeChild(node);
+			}else{
+				// If this node is parentless, it's a base node, so we have to "up" change to itself
+				// and note that it's a top-level to watch for errors
+				tokens.push([dd.TOKEN_CHANGE, node, true, true]);
+			}
+		},
+		__tokenize: function(child, tokens){
+			var data = child.data;
+			switch(child.nodeType){
+				case 1:
+					this._tokenize(child, tokens);
+					return;
+				case 3:
+					if(data.match(/[^\s\n]/) && (data.indexOf("{{") != -1 || data.indexOf("{%") != -1)){
+						var texts = ddt.tokenize(data);
+						for(var j = 0, text; text = texts[j]; j++){
+							if(typeof text == "string"){
+								tokens.push([dd.TOKEN_TEXT, text]);
+							}else{
+								tokens.push(text);
+							}
+						}
+					}else{
+						tokens.push([child.nodeType, child]);
+					}
+					if(child.parentNode) child.parentNode.removeChild(child);
+					return;
+				case 8:
+					if(data.indexOf("{%") == 0){
+						var text = dojo.trim(data.slice(2, -2));
+						if(text.substr(0, 5) == "load "){
+							var parts = dojo.trim(text).split(/\s+/g);
+							for(var i = 1, part; part = parts[i]; i++){
+								dojo["require"](part);
+							}
+						}
+						tokens.push([dd.TOKEN_BLOCK, text]);
+					}
+					if(data.indexOf("{{") == 0){
+						tokens.push([dd.TOKEN_VAR, dojo.trim(data.slice(2, -2))]);
+					}
+					if(child.parentNode) child.parentNode.removeChild(child);
+					return;
+			}
+		}
+	};
+
+	dd.DomTemplate = dojo.extend(function(/*String|DOMNode|dojo._Url*/ obj){
+		// summary: Use this object for DOM templating
+		if(!obj.nodes){
+			var node = dojo.byId(obj);
+			if(node && node.nodeType == 1){
+				dojo.forEach(["class", "src", "href", "name", "value"], function(item){
+					ddh._attributes[item] = true;
+				});
+				obj = {
+					nodes: [node]
+				};
+			}else{
+				if(typeof obj == "object"){
+					obj = ddt.getTemplateString(obj);
+				}
+				obj = ddh.getTemplate(obj);
+			}
+		}
+
+		var tokens = ddh.tokenize(obj.nodes);
+		if(dd.tests){
+			this.tokens = tokens.slice(0);
+		}
+
+		var parser = new dd._DomParser(tokens);
+		this.nodelist = parser.parse();
+	},
+	{
+		_count: 0,
+		_re: /\bdojo:([a-zA-Z0-9_]+)\b/g,
+		setClass: function(str){
+			this.getRootNode().className = str;
+		},
+		getRootNode: function(){
+			return this.buffer.rootNode;
+		},
+		getBuffer: function(){
+			return new dd.DomBuffer();
+		},
+		render: function(context, buffer){
+			buffer = this.buffer = buffer || this.getBuffer();
+			this.rootNode = null;
+			var output = this.nodelist.render(context || new dd.Context({}), buffer);
+			for(var i = 0, node; node = buffer._cache[i]; i++){
+				if(node._cache){
+					node._cache.length = 0;
+				}
+			}
+			return output;
+		},
+		unrender: function(context, buffer){
+			return this.nodelist.unrender(context, buffer);
+		}
+	});
+
+	dd.DomBuffer = dojo.extend(function(/*Node*/ parent){
+		// summary: Allows the manipulation of DOM
+		// description:
+		//		Use this to append a child, change the parent, or
+		//		change the attribute of the current node.
+		this._parent = parent;
+		this._cache = [];
+	},
+	{
+		concat: function(/*DOMNode*/ node){
+			var parent = this._parent;
+			if(parent && node.parentNode && node.parentNode === parent && !parent._dirty){
+				return this;
+			}
+
+			if(node.nodeType == 1 && !this.rootNode){
+				this.rootNode = node || true;
+				return this;
+			}
+
+			if(!parent){
+				if(node.nodeType == 3 && dojo.trim(node.data)){
+					throw new Error("Text should not exist outside of the root node in template");
+				}
+				return this;
+			}
+			if(this._closed){
+				if(node.nodeType == 3 && !dojo.trim(node.data)){
+					return this;
+				}else{
+					throw new Error("Content should not exist outside of the root node in template");
+				}
+			}
+			if(parent._dirty){
+				if(node._drawn && node.parentNode == parent){
+					var caches = parent._cache;
+					if(caches){
+						for(var i = 0, cache; cache = caches[i]; i++){
+							this.onAddNode && this.onAddNode(cache);
+							parent.insertBefore(cache, node);
+							this.onAddNodeComplete && this.onAddNodeComplete(cache);
+						}
+						caches.length = 0;
+					}
+				}
+				parent._dirty = false;
+			}
+			if(!parent._cache){
+				parent._cache = [];
+				this._cache.push(parent);
+			}
+			parent._dirty = true;
+			parent._cache.push(node);
+			return this;
+		},
+		remove: function(obj){
+			if(typeof obj == "string"){
+				if(this._parent){
+					this._parent.removeAttribute(obj);
+				}
+			}else{
+				if(obj.nodeType == 1 && !this.getRootNode() && !this._removed){
+					this._removed = true;
+					return this;
+				}
+				if(obj.parentNode){
+					this.onRemoveNode && this.onRemoveNode(obj);
+					if(obj.parentNode){
+						obj.parentNode.removeChild(obj);
+					}
+				}
+			}
+			return this;
+		},
+		setAttribute: function(key, value){
+			var old = dojo.attr(this._parent, key);
+			if(this.onChangeAttribute && old != value){
+				this.onChangeAttribute(this._parent, key, old, value);
+			}
+			if(key == "style"){
+				//console.log(value);
+				this._parent.style.cssText = value;
+			}else{
+				dojo.attr(this._parent, key, value);
+				//console.log(this._parent, key, value);
+			}
+			return this;
+		},
+		addEvent: function(context, type, fn, /*Array|Function*/ args){
+			if(!context.getThis()){ throw new Error("You must use Context.setObject(instance)"); }
+			this.onAddEvent && this.onAddEvent(this.getParent(), type, fn);
+			var resolved = fn;
+			if(dojo.isArray(args)){
+				resolved = function(e){
+					this[fn].apply(this, [e].concat(args));
+				}
+			}
+			return dojo.connect(this.getParent(), type, context.getThis(), resolved);
+		},
+		setParent: function(node, /*Boolean?*/ up, /*Boolean?*/ root){
+			if(!this._parent) this._parent = this._first = node;
+
+			if(up && root && node === this._first){
+				this._closed = true;
+			}
+
+			if(up){
+				var parent = this._parent;
+				var script = "";
+				var ie = dojo.isIE && parent.tagName == "SCRIPT";
+				if(ie){
+					parent.text = "";
+				}
+				if(parent._dirty){
+					var caches = parent._cache;
+					var select = (parent.tagName == "SELECT" && !parent.options.length);
+					for(var i = 0, cache; cache = caches[i]; i++){
+						if(cache !== parent){
+							this.onAddNode && this.onAddNode(cache);
+							if(ie){
+								script += cache.data;
+							}else{
+								parent.appendChild(cache);
+								if(select && cache.defaultSelected && i){
+									select = i;
+								}
+							}
+							this.onAddNodeComplete && this.onAddNodeComplete(cache);
+						}
+					}
+					if(select){
+						parent.options.selectedIndex = (typeof select == "number") ? select : 0;
+					}
+					caches.length = 0;
+					parent._dirty = false;
+				}
+				if(ie){
+					parent.text = script;
+				}
+			}
+
+			this._parent = node;
+			this.onSetParent && this.onSetParent(node, up, root);
+			return this;
+		},
+		getParent: function(){
+			return this._parent;
+		},
+		getRootNode: function(){
+			return this.rootNode;
+		}
+		/*=====
+		,
+		onSetParent: function(node, up){
+			// summary: Stub called when setParent is used.
+		},
+		onAddNode: function(node){
+			// summary: Stub called before new nodes are added
+		},
+		onAddNodeComplete: function(node){
+			// summary: Stub called after new nodes are added
+		},
+		onRemoveNode: function(node){
+			// summary: Stub called when nodes are removed
+		},
+		onChangeAttribute: function(node, attribute, old, updated){
+			// summary: Stub called when an attribute is changed
+		},
+		onChangeData: function(node, old, updated){
+			// summary: Stub called when a data in a node is changed
+		},
+		onClone: function(from, to){
+			// summary: Stub called when a node is duplicated
+			// from: DOMNode
+			// to: DOMNode
+		},
+		onAddEvent: function(node, type, description){
+			// summary: Stub to call when you're adding an event
+			// node: DOMNode
+			// type: String
+			// description: String
+		}
+		=====*/
+	});
+
+	dd._DomNode = dojo.extend(function(node){
+		// summary: Places a node into DOM
+		this.contents = node;
+	},
+	{
+		render: function(context, buffer){
+			this._rendered = true;
+			return buffer.concat(this.contents);
+		},
+		unrender: function(context, buffer){
+			if(!this._rendered){
+				return buffer;
+			}
+			this._rendered = false;
+			return buffer.remove(this.contents);
+		},
+		clone: function(buffer){
+			return new this.constructor(this.contents);
+		}
+	});
+
+	dd._DomNodeList = dojo.extend(function(/*Node[]*/ nodes){
+		// summary: A list of any DOM-specific node objects
+		// description:
+		//		Any object that's used in the constructor or added
+		//		through the push function much implement the
+		//		render, unrender, and clone functions.
+		this.contents = nodes || [];
+	},
+	{
+		push: function(node){
+			this.contents.push(node);
+		},
+		unshift: function(node){
+			this.contents.unshift(node);
+		},
+		render: function(context, buffer, /*Node*/ instance){
+			buffer = buffer || dd.DomTemplate.prototype.getBuffer();
+
+			if(instance){
+				var parent = buffer.getParent();
+			}
+			for(var i = 0; i < this.contents.length; i++){
+				buffer = this.contents[i].render(context, buffer);
+				if(!buffer) throw new Error("Template node render functions must return their buffer");
+			}
+			if(parent){
+				buffer.setParent(parent);
+			}
+			return buffer;
+		},
+		dummyRender: function(context, buffer, asNode){
+			// summary: A really expensive way of checking to see how a rendering will look.
+			//		Used in the ifchanged tag
+			var div = document.createElement("div");
+
+			var parent = buffer.getParent();
+			var old = parent._clone;
+			// Tell the clone system to attach itself to our new div
+			parent._clone = div;
+			var nodelist = this.clone(buffer, div);
+			if(old){
+				// Restore state if there was a previous clone
+				parent._clone = old;
+			}else{
+				// Remove if there was no clone
+				parent._clone = null;
+			}
+
+			buffer = dd.DomTemplate.prototype.getBuffer();
+			nodelist.unshift(new dd.ChangeNode(div));
+			nodelist.unshift(new dd._DomNode(div));
+			nodelist.push(new dd.ChangeNode(div, true));
+			nodelist.render(context, buffer);
+
+			if(asNode){
+				return buffer.getRootNode();
+			}
+
+			var html = div.innerHTML;
+			return (dojo.isIE) ? html.replace(/\s*_(dirty|clone)="[^"]*"/g, "") : html;
+		},
+		unrender: function(context, buffer, instance){
+			if(instance){
+				var parent = buffer.getParent();
+			}
+			for(var i = 0; i < this.contents.length; i++){
+				buffer = this.contents[i].unrender(context, buffer);
+				if(!buffer) throw new Error("Template node render functions must return their buffer");
+			}
+			if(parent){
+				buffer.setParent(parent);
+			}
+			return buffer;
+		},
+		clone: function(buffer){
+			// summary:
+			//		Used to create an identical copy of a NodeList, useful for things like the for tag.
+			var parent = buffer.getParent();
+			var contents = this.contents;
+			var nodelist = new dd._DomNodeList();
+			var cloned = [];
+			for(var i = 0; i < contents.length; i++){
+				var clone = contents[i].clone(buffer);
+				if(clone instanceof dd.ChangeNode || clone instanceof dd._DomNode){
+					var item = clone.contents._clone;
+					if(item){
+						clone.contents = item;
+					}else if(parent != clone.contents && clone instanceof dd._DomNode){
+						var node = clone.contents;
+						clone.contents = clone.contents.cloneNode(false);
+						buffer.onClone && buffer.onClone(node, clone.contents);
+						cloned.push(node);
+						node._clone = clone.contents;
+					}
+				}
+				nodelist.push(clone);
+			}
+
+			for(var i = 0, clone; clone = cloned[i]; i++){
+				clone._clone = null;
+			}
+
+			return nodelist;
+		},
+		rtrim: function(){
+			while(1){
+				var i = this.contents.length - 1;
+				if(this.contents[i] instanceof dd._DomTextNode && this.contents[i].isEmpty()){
+					this.contents.pop();
+				}else{
+					break;
+				}
+			}
+
+			return this;
+		}
+	});
+
+	dd._DomVarNode = dojo.extend(function(str){
+		// summary: A node to be processed as a variable
+		// description:
+		//		Will render an object that supports the render function
+		// 		and the getRootNode function
+		this.contents = new dd._Filter(str);
+	},
+	{
+		render: function(context, buffer){
+			var str = this.contents.resolve(context);
+
+			// What type of rendering?
+			var type = "text";
+			if(str){
+				if(str.render && str.getRootNode){
+					type = "injection";
+				}else if(str.safe){
+					if(str.nodeType){
+						type = "node";
+					}else if(str.toString){
+						str = str.toString();
+						type = "html";
+					}
+				}
+			}
+
+			// Has the typed changed?
+			if(this._type && type != this._type){
+				this.unrender(context, buffer);
+			}
+			this._type = type;
+
+			// Now render
+			switch(type){
+			case "text":
+				this._rendered = true;
+				this._txt = this._txt || document.createTextNode(str);
+				if(this._txt.data != str){
+					var old = this._txt.data;
+					this._txt.data = str;
+					buffer.onChangeData && buffer.onChangeData(this._txt, old, this._txt.data);
+				}
+				return buffer.concat(this._txt);
+			case "injection":
+				var root = str.getRootNode();
+
+				if(this._rendered && root != this._root){
+					buffer = this.unrender(context, buffer);
+				}
+				this._root = root;
+
+				var injected = this._injected = new dd._DomNodeList();
+				injected.push(new dd.ChangeNode(buffer.getParent()));
+				injected.push(new dd._DomNode(root));
+				injected.push(str);
+				injected.push(new dd.ChangeNode(buffer.getParent()));
+				this._rendered = true;
+
+				return injected.render(context, buffer);
+			case "node":
+				this._rendered = true;
+				if(this._node && this._node != str && this._node.parentNode && this._node.parentNode === buffer.getParent()){
+					this._node.parentNode.removeChild(this._node);
+				}
+				this._node = str;
+				return buffer.concat(str);
+			case "html":
+				if(this._rendered && this._src != str){
+					buffer = this.unrender(context, buffer);
+				}
+				this._src = str;
+
+				// This can get reset in the above tag
+				if(!this._rendered){
+					this._rendered = true;
+					this._html = this._html || [];
+					var div = (this._div = this._div || document.createElement("div"));
+					div.innerHTML = str;
+					var children = div.childNodes;
+					while(children.length){
+						var removed = div.removeChild(children[0]);
+						this._html.push(removed);
+						buffer = buffer.concat(removed);
+					}
+				}
+
+				return buffer;
+			default:
+				return buffer;
+			}
+		},
+		unrender: function(context, buffer){
+			if(!this._rendered){
+				return buffer;
+			}
+			this._rendered = false;
+
+			// Unrender injected nodes
+			switch(this._type){
+			case "text":
+				return buffer.remove(this._txt);
+			case "injection":
+				return this._injection.unrender(context, buffer);
+			case "node":
+				if(this._node.parentNode === buffer.getParent()){
+					return buffer.remove(this._node);
+				}
+				return buffer;
+			case "html":
+				for(var i=0, l=this._html.length; i<l; i++){
+					buffer = buffer.remove(this._html[i]);
+				}
+				return buffer;
+			default:
+				return buffer;
+			}
+		},
+		clone: function(){
+			return new this.constructor(this.contents.getExpression());
+		}
+	});
+
+	dd.ChangeNode = dojo.extend(function(node, /*Boolean?*/ up, /*Bookean*/ root){
+		// summary: Changes the parent during render/unrender
+		this.contents = node;
+		this.up = up;
+		this.root = root;
+	},
+	{
+		render: function(context, buffer){
+			return buffer.setParent(this.contents, this.up, this.root);
+		},
+		unrender: function(context, buffer){
+			if(!buffer.getParent()){
+				return buffer;
+			}
+			return buffer.setParent(this.contents);
+		},
+		clone: function(){
+			return new this.constructor(this.contents, this.up, this.root);
+		}
+	});
+
+	dd.AttributeNode = dojo.extend(function(key, value){
+		// summary: Works on attributes
+		this.key = key;
+		this.value = value;
+		this.contents = value;
+		if(this._pool[value]){
+			this.nodelist = this._pool[value];
+		}else{
+			if(!(this.nodelist = dd.quickFilter(value))){
+				this.nodelist = (new dd.Template(value, true)).nodelist;
+			}
+			this._pool[value] = this.nodelist;
+		}
+
+		this.contents = "";
+	},
+	{
+		_pool: {},
+		render: function(context, buffer){
+			var key = this.key;
+			var value = this.nodelist.dummyRender(context);
+			if(dd.BOOLS[key]){
+				value = !(value == "false" || value == "undefined" || !value);
+			}
+			if(value !== this.contents){
+				this.contents = value;
+				return buffer.setAttribute(key, value);
+			}
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			this.contents = "";
+			return buffer.remove(this.key);
+		},
+		clone: function(buffer){
+			return new this.constructor(this.key, this.value);
+		}
+	});
+
+	dd._DomTextNode = dojo.extend(function(str){
+		// summary: Adds a straight text node without any processing
+		this.contents = document.createTextNode(str);
+		this.upcoming = str;
+	},
+	{
+		set: function(data){
+			this.upcoming = data;
+			return this;
+		},
+		render: function(context, buffer){
+			if(this.contents.data != this.upcoming){
+				var old = this.contents.data;
+				this.contents.data = this.upcoming;
+				buffer.onChangeData && buffer.onChangeData(this.contents, old, this.upcoming);
+			}
+			return buffer.concat(this.contents);
+		},
+		unrender: function(context, buffer){
+			return buffer.remove(this.contents);
+		},
+		isEmpty: function(){
+			return !dojo.trim(this.contents.data);
+		},
+		clone: function(){
+			return new this.constructor(this.contents.data);
+		}
+	});
+
+	dd._DomParser = dojo.extend(function(tokens){
+		// summary: Turn a simple array into a set of objects
+		// description:
+		//	This is also used by all tags to move through
+		//	the list of nodes.
+		this.contents = tokens;
+	},
+	{
+		i: 0,
+		parse: function(/*Array?*/ stop_at){
+			var terminators = {};
+			var tokens = this.contents;
+			if(!stop_at){
+				stop_at = [];
+			}
+			for(var i = 0; i < stop_at.length; i++){
+				terminators[stop_at[i]] = true;
+			}
+			var nodelist = new dd._DomNodeList();
+			while(this.i < tokens.length){
+				var token = tokens[this.i++];
+				var type = token[0];
+				var value = token[1];
+				if(type == dd.TOKEN_CUSTOM){
+					nodelist.push(value);
+				}else if(type == dd.TOKEN_CHANGE){
+					var changeNode = new dd.ChangeNode(value, token[2], token[3]);
+					value[changeNode.attr] = changeNode;
+					nodelist.push(changeNode);
+				}else if(type == dd.TOKEN_ATTR){
+					var fn = ddt.getTag("attr:" + token[2], true);
+					if(fn && token[3]){
+						if (token[3].indexOf("{%") != -1 || token[3].indexOf("{{") != -1) {
+							value.setAttribute(token[2], "");
+						}
+						nodelist.push(fn(null, new dd.Token(type, token[2] + " " + token[3])));
+					}else if(dojo.isString(token[3])){
+						if(token[2] == "style" || token[3].indexOf("{%") != -1 || token[3].indexOf("{{") != -1){
+							nodelist.push(new dd.AttributeNode(token[2], token[3]));
+						}else if(dojo.trim(token[3])){
+							try{
+								dojo.attr(value, token[2], token[3]);
+							}catch(e){}
+						}
+					}
+				}else if(type == dd.TOKEN_NODE){
+					var fn = ddt.getTag("node:" + value.tagName.toLowerCase(), true);
+					if(fn){
+						// TODO: We need to move this to tokenization so that it's before the
+						// 				node and the parser can be passed here instead of null
+						nodelist.push(fn(null, new dd.Token(type, value), value.tagName.toLowerCase()));
+					}
+					nodelist.push(new dd._DomNode(value));
+				}else if(type == dd.TOKEN_VAR){
+					nodelist.push(new dd._DomVarNode(value));
+				}else if(type == dd.TOKEN_TEXT){
+					nodelist.push(new dd._DomTextNode(value.data || value));
+				}else if(type == dd.TOKEN_BLOCK){
+					if(terminators[value]){
+						--this.i;
+						return nodelist;
+					}
+					var cmd = value.split(/\s+/g);
+					if(cmd.length){
+						cmd = cmd[0];
+						var fn = ddt.getTag(cmd);
+						if(typeof fn != "function"){
+							throw new Error("Function not found for " + cmd);
+						}
+						var tpl = fn(this, new dd.Token(type, value));
+						if(tpl){
+							nodelist.push(tpl);
+						}
+					}
+				}
+			}
+
+			if(stop_at.length){
+				throw new Error("Could not find closing tag(s): " + stop_at.toString());
+			}
+
+			return nodelist;
+		},
+		next_token: function(){
+			// summary: Returns the next token in the list.
+			var token = this.contents[this.i++];
+			return new dd.Token(token[0], token[1]);
+		},
+		delete_first_token: function(){
+			this.i++;
+		},
+		skip_past: function(endtag){
+			return dd._Parser.prototype.skip_past.call(this, endtag);
+		},
+		create_variable_node: function(expr){
+			return new dd._DomVarNode(expr);
+		},
+		create_text_node: function(expr){
+			return new dd._DomTextNode(expr || "");
+		},
+		getTemplate: function(/*String*/ loc){
+			return new dd.DomTemplate(ddh.getTemplate(loc));
+		}
+	});
+
 })();
-}
diff --git a/dojox/dtl/ext-dojo/NodeList.js b/dojox/dtl/ext-dojo/NodeList.js
old mode 100644
new mode 100755
index 85a87fd..a185057
--- a/dojox/dtl/ext-dojo/NodeList.js
+++ b/dojox/dtl/ext-dojo/NodeList.js
@@ -1,29 +1,29 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.ext-dojo.NodeList"]){
-dojo._hasResource["dojox.dtl.ext-dojo.NodeList"]=true;
 dojo.provide("dojox.dtl.ext-dojo.NodeList");
 dojo.require("dojox.dtl._base");
-dojo.extend(dojo.NodeList,{dtl:function(_1,_2){
-var d=dojox.dtl;
-var _3=this;
-var _4=function(_5,_6){
-var _7=_5.render(new d._Context(_6));
-_3.forEach(function(_8){
-_8.innerHTML=_7;
-});
-};
-d.text._resolveTemplateArg(_1).addCallback(function(_9){
-_1=new d.Template(_9);
-d.text._resolveContextArg(_2).addCallback(function(_a){
-_4(_1,_a);
-});
-});
-return this;
-}});
-}
+
+dojo.extend(dojo.NodeList, {
+	dtl: function(template, context){
+		// template: dojox.dtl.__StringArgs|String
+		//		The template string or location
+		// context: dojox.dtl.__ObjectArgs|Object
+		//		The context object or location
+		var d = dojox.dtl;
+
+		var self = this;
+		var render = function(template, context){
+			var content = template.render(new d._Context(context));
+			self.forEach(function(node){
+				node.innerHTML = content;
+			});
+		}
+
+		d.text._resolveTemplateArg(template).addCallback(function(templateString){
+			template = new d.Template(templateString);
+			d.text._resolveContextArg(context).addCallback(function(context){
+				render(template, context);
+			});
+		});
+
+		return this;
+	}
+});
\ No newline at end of file
diff --git a/dojox/dtl/filter/dates.js b/dojox/dtl/filter/dates.js
index d155d26..3ddb89d 100644
--- a/dojox/dtl/filter/dates.js
+++ b/dojox/dtl/filter/dates.js
@@ -1,59 +1,62 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.filter.dates"]){
-dojo._hasResource["dojox.dtl.filter.dates"]=true;
 dojo.provide("dojox.dtl.filter.dates");
+
 dojo.require("dojox.dtl.utils.date");
+
 (function(){
-var _1=dojox.dtl.filter.dates;
-dojo.mixin(_1,{_toDate:function(_2){
-if(_2 instanceof Date){
-return _2;
-}
-_2=new Date(_2);
-if(_2.getTime()==new Date(0).getTime()){
-return "";
-}
-return _2;
-},date:function(_3,_4){
-_3=_1._toDate(_3);
-if(!_3){
-return "";
-}
-_4=_4||"N j, Y";
-return dojox.dtl.utils.date.format(_3,_4);
-},time:function(_5,_6){
-_5=_1._toDate(_5);
-if(!_5){
-return "";
-}
-_6=_6||"P";
-return dojox.dtl.utils.date.format(_5,_6);
-},timesince:function(_7,_8){
-_7=_1._toDate(_7);
-if(!_7){
-return "";
-}
-var _9=dojox.dtl.utils.date.timesince;
-if(_8){
-return _9(_8,_7);
-}
-return _9(_7);
-},timeuntil:function(_a,_b){
-_a=_1._toDate(_a);
-if(!_a){
-return "";
-}
-var _c=dojox.dtl.utils.date.timesince;
-if(_b){
-return _c(_b,_a);
-}
-return _c(new Date(),_a);
-}});
-})();
-}
+	var ddfd = dojox.dtl.filter.dates;
+
+	dojo.mixin(ddfd, {
+		_toDate: function(value){
+			if(value instanceof Date){
+				return value;
+			}
+			value = new Date(value);
+			if(value.getTime() == new Date(0).getTime()){
+				return "";
+			}
+			return value;
+		},
+		date: function(value, arg){
+			// summary: Formats a date according to the given format
+			value = ddfd._toDate(value);
+			if(!value){
+				return "";
+			}
+			arg = arg || "N j, Y";
+			return dojox.dtl.utils.date.format(value, arg);
+		},
+		time: function(value, arg){
+			// summary: Formats a time according to the given format
+			value = ddfd._toDate(value);
+			if(!value){
+				return "";
+			}
+			arg = arg || "P";
+			return dojox.dtl.utils.date.format(value, arg);
+		},
+		timesince: function(value, arg){
+			// summary: Formats a date as the time since that date (i.e. "4 days, 6 hours")
+			value = ddfd._toDate(value);
+			if(!value){
+				return "";
+			}
+			var timesince = dojox.dtl.utils.date.timesince;
+			if(arg){
+				return timesince(arg, value);
+			}
+			return timesince(value);
+		},
+		timeuntil: function(value, arg){
+			// summary: Formats a date as the time until that date (i.e. "4 days, 6 hours")
+			value = ddfd._toDate(value);
+			if(!value){
+				return "";
+			}
+			var timesince = dojox.dtl.utils.date.timesince;
+			if(arg){
+				return timesince(arg, value);
+			}
+			return timesince(new Date(), value);
+		}
+	});
+})();
\ No newline at end of file
diff --git a/dojox/dtl/filter/htmlstrings.js b/dojox/dtl/filter/htmlstrings.js
index 0972ce1..b6fb05b 100644
--- a/dojox/dtl/filter/htmlstrings.js
+++ b/dojox/dtl/filter/htmlstrings.js
@@ -1,37 +1,45 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.filter.htmlstrings"]){
-dojo._hasResource["dojox.dtl.filter.htmlstrings"]=true;
 dojo.provide("dojox.dtl.filter.htmlstrings");
+
 dojo.require("dojox.dtl._base");
-dojo.mixin(dojox.dtl.filter.htmlstrings,{_linebreaksrn:/(\r\n|\n\r)/g,_linebreaksn:/\n{2,}/g,_linebreakss:/(^\s+|\s+$)/g,_linebreaksbr:/\n/g,_removetagsfind:/[a-z0-9]+/g,_striptags:/<[^>]*?>/g,linebreaks:function(_1){
-var _2=[];
-var dh=dojox.dtl.filter.htmlstrings;
-_1=_1.replace(dh._linebreaksrn,"\n");
-var _3=_1.split(dh._linebreaksn);
-for(var i=0;i<_3.length;i++){
-var _4=_3[i].replace(dh._linebreakss,"").replace(dh._linebreaksbr,"<br />");
-_2.push("<p>"+_4+"</p>");
-}
-return _2.join("\n\n");
-},linebreaksbr:function(_5){
-var dh=dojox.dtl.filter.htmlstrings;
-return _5.replace(dh._linebreaksrn,"\n").replace(dh._linebreaksbr,"<br />");
-},removetags:function(_6,_7){
-var dh=dojox.dtl.filter.htmlstrings;
-var _8=[];
-var _9;
-while(_9=dh._removetagsfind.exec(_7)){
-_8.push(_9[0]);
-}
-_8="("+_8.join("|")+")";
-return _6.replace(new RegExp("</?s*"+_8+"s*[^>]*>","gi"),"");
-},striptags:function(_a){
-return _a.replace(dojox.dtl.filter.htmlstrings._striptags,"");
-}});
-}
+
+dojo.mixin(dojox.dtl.filter.htmlstrings, {
+	_linebreaksrn: /(\r\n|\n\r)/g,
+	_linebreaksn: /\n{2,}/g,
+	_linebreakss: /(^\s+|\s+$)/g,
+	_linebreaksbr: /\n/g,
+	_removetagsfind: /[a-z0-9]+/g,
+	_striptags: /<[^>]*?>/g,
+	linebreaks: function(value){
+		// summary: Converts newlines into <p> and <br />s
+		var output = [];
+		var dh = dojox.dtl.filter.htmlstrings;
+		value = value.replace(dh._linebreaksrn, "\n");
+		var parts = value.split(dh._linebreaksn);
+		for(var i = 0; i < parts.length; i++){
+			var part = parts[i].replace(dh._linebreakss, "").replace(dh._linebreaksbr, "<br />");
+			output.push("<p>" + part + "</p>");
+		}
+
+		return output.join("\n\n");
+	},
+	linebreaksbr: function(value){
+		// summary: Converts newlines into <br />s
+		var dh = dojox.dtl.filter.htmlstrings;
+		return value.replace(dh._linebreaksrn, "\n").replace(dh._linebreaksbr, "<br />");
+	},
+	removetags: function(value, arg){
+		// summary: Removes a space separated list of [X]HTML tags from the output"
+		var dh = dojox.dtl.filter.htmlstrings;
+		var tags = [];
+		var group;
+		while(group = dh._removetagsfind.exec(arg)){
+			tags.push(group[0]);
+		}
+		tags = "(" + tags.join("|") + ")";
+		return value.replace(new RegExp("</?\s*" + tags + "\s*[^>]*>", "gi"), "");
+	},
+	striptags: function(value){
+		// summary: Strips all [X]HTML tags
+		return value.replace(dojox.dtl.filter.htmlstrings._striptags, "");
+	}
+});
\ No newline at end of file
diff --git a/dojox/dtl/filter/integers.js b/dojox/dtl/filter/integers.js
index 49e67a0..890daa1 100644
--- a/dojox/dtl/filter/integers.js
+++ b/dojox/dtl/filter/integers.js
@@ -1,28 +1,28 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.filter.integers"]){
-dojo._hasResource["dojox.dtl.filter.integers"]=true;
 dojo.provide("dojox.dtl.filter.integers");
-dojo.mixin(dojox.dtl.filter.integers,{add:function(_1,_2){
-_1=parseInt(_1,10);
-_2=parseInt(_2,10);
-return isNaN(_2)?_1:_1+_2;
-},get_digit:function(_3,_4){
-_3=parseInt(_3,10);
-_4=parseInt(_4,10)-1;
-if(_4>=0){
-_3+="";
-if(_4<_3.length){
-_3=parseInt(_3.charAt(_4),10);
-}else{
-_3=0;
-}
-}
-return (isNaN(_3)?0:_3);
-}});
-}
+
+dojo.mixin(dojox.dtl.filter.integers, {
+	add: function(value, arg){
+		value = parseInt(value, 10);
+		arg = parseInt(arg, 10);
+		return isNaN(arg) ? value : value + arg;
+	},
+	get_digit: function(value, arg){
+		// summary:
+		//		Given a whole number, returns the 1-based requested digit of it
+		// desciprtion:
+		//		1 is the right-most digit, 2 is the second-right-most digit, etc. Returns the
+		//		original value for invalid input (if input or argument is not an integer,
+		//		or if argument is less than 1). Otherwise, output is always an integer.
+		value = parseInt(value, 10);
+		arg = parseInt(arg, 10) - 1;
+		if(arg >= 0){
+			value += "";
+			if(arg < value.length){
+				value = parseInt(value.charAt(arg), 10);
+			}else{
+				value = 0;
+			}
+		}
+		return (isNaN(value) ? 0 : value);
+	}
+});
\ No newline at end of file
diff --git a/dojox/dtl/filter/lists.js b/dojox/dtl/filter/lists.js
index 25c8e93..c83a15b 100644
--- a/dojox/dtl/filter/lists.js
+++ b/dojox/dtl/filter/lists.js
@@ -1,95 +1,137 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.filter.lists"]){
-dojo._hasResource["dojox.dtl.filter.lists"]=true;
 dojo.provide("dojox.dtl.filter.lists");
+
 dojo.require("dojox.dtl._base");
-dojo.mixin(dojox.dtl.filter.lists,{_dictsort:function(a,b){
-if(a[0]==b[0]){
-return 0;
-}
-return (a[0]<b[0])?-1:1;
-},dictsort:function(_1,_2){
-if(!_2){
-return _1;
-}
-var i,_3,_4=[];
-if(!dojo.isArray(_1)){
-var _5=_1,_1=[];
-for(var _6 in _5){
-_1.push(_5[_6]);
-}
-}
-for(i=0;i<_1.length;i++){
-_4.push([new dojox.dtl._Filter("var."+_2).resolve(new dojox.dtl._Context({"var":_1[i]})),_1[i]]);
-}
-_4.sort(dojox.dtl.filter.lists._dictsort);
-var _7=[];
-for(i=0;_3=_4[i];i++){
-_7.push(_3[1]);
-}
-return _7;
-},dictsortreversed:function(_8,_9){
-if(!_9){
-return _8;
-}
-var _a=dojox.dtl.filter.lists.dictsort(_8,_9);
-return _a.reverse();
-},first:function(_b){
-return (_b.length)?_b[0]:"";
-},join:function(_c,_d){
-return _c.join(_d||",");
-},length:function(_e){
-return (isNaN(_e.length))?(_e+"").length:_e.length;
-},length_is:function(_f,arg){
-return _f.length==parseInt(arg);
-},random:function(_10){
-return _10[Math.floor(Math.random()*_10.length)];
-},slice:function(_11,arg){
-arg=arg||"";
-var _12=arg.split(":");
-var _13=[];
-for(var i=0;i<_12.length;i++){
-if(!_12[i].length){
-_13.push(null);
-}else{
-_13.push(parseInt(_12[i]));
-}
-}
-if(_13[0]===null){
-_13[0]=0;
-}
-if(_13[0]<0){
-_13[0]=_11.length+_13[0];
-}
-if(_13.length<2||_13[1]===null){
-_13[1]=_11.length;
-}
-if(_13[1]<0){
-_13[1]=_11.length+_13[1];
-}
-return _11.slice(_13[0],_13[1]);
-},_unordered_list:function(_14,_15){
-var ddl=dojox.dtl.filter.lists;
-var i,_16="";
-for(i=0;i<_15;i++){
-_16+="\t";
-}
-if(_14[1]&&_14[1].length){
-var _17=[];
-for(i=0;i<_14[1].length;i++){
-_17.push(ddl._unordered_list(_14[1][i],_15+1));
-}
-return _16+"<li>"+_14[0]+"\n"+_16+"<ul>\n"+_17.join("\n")+"\n"+_16+"</ul>\n"+_16+"</li>";
-}else{
-return _16+"<li>"+_14[0]+"</li>";
-}
-},unordered_list:function(_18){
-return dojox.dtl.filter.lists._unordered_list(_18,1);
-}});
-}
+
+dojo.mixin(dojox.dtl.filter.lists, {
+	_dictsort: function(a, b){
+		if(a[0] == b[0]){
+			return 0;
+		}
+		return (a[0] < b[0]) ? -1 : 1;
+	},
+	dictsort: function(value, arg){
+		// summary: Takes a list of dicts, returns that list sorted by the property given in the argument.
+		if(!arg){
+			return value;
+		}
+
+		var i, item, items = [];
+		if(!dojo.isArray(value)){
+			var obj = value, value = [];
+			for(var key in obj){
+				value.push(obj[key]);
+			}
+		}
+		for(i = 0; i < value.length; i++){
+			items.push([new dojox.dtl._Filter('var.' + arg).resolve(new dojox.dtl._Context({ 'var' : value[i]})), value[i]]);
+		}
+		items.sort(dojox.dtl.filter.lists._dictsort);
+		var output = [];
+		for(i = 0; item = items[i]; i++){
+			output.push(item[1]);
+		}
+		return output;
+	},
+	dictsortreversed: function(value, arg){
+		// summary: Takes a list of dicts, returns that list sorted in reverse order by the property given in the argument.
+		if(!arg) return value;
+
+		var dictsort = dojox.dtl.filter.lists.dictsort(value, arg);
+		return dictsort.reverse();
+	},
+	first: function(value){
+		// summary: Returns the first item in a list
+		return (value.length) ? value[0] : "";
+	},
+	join: function(value, arg){
+		// summary: Joins a list with a string, like Python's ``str.join(list)``
+		// description:
+		//		Django throws a compile error, but JS can't do arg checks
+		//		so we're left with run time errors, which aren't wise for something
+		//		as trivial here as an empty arg.
+		return value.join(arg || ",");
+	},
+	length: function(value){
+		// summary: Returns the length of the value - useful for lists
+		return (isNaN(value.length)) ? (value + "").length : value.length;
+	},
+	length_is: function(value, arg){
+		// summary: Returns a boolean of whether the value's length is the argument
+		return value.length == parseInt(arg);
+	},
+	random: function(value){
+		// summary: Returns a random item from the list
+		return value[Math.floor(Math.random() * value.length)];
+	},
+	slice: function(value, arg){
+		// summary: Returns a slice of the list.
+		// description:
+		//		Uses the same syntax as Python's list slicing; see
+		//		http://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice
+		//		for an introduction.
+		//		Also uses the optional third value to denote every X item.
+		arg = arg || "";
+		var parts = arg.split(":");
+		var bits = [];
+		for(var i = 0; i < parts.length; i++){
+			if(!parts[i].length){
+				bits.push(null);
+			}else{
+				bits.push(parseInt(parts[i]));
+			}
+		}
+
+		if(bits[0] === null){
+			bits[0] = 0;
+		}
+		if(bits[0] < 0){
+			bits[0] = value.length + bits[0];
+		}
+		if(bits.length < 2 || bits[1] === null){
+			bits[1] = value.length;
+		}
+		if(bits[1] < 0){
+			bits[1] = value.length + bits[1];
+		}
+		
+		return value.slice(bits[0], bits[1]);
+	},
+	_unordered_list: function(value, tabs){
+		var ddl = dojox.dtl.filter.lists;
+		var i, indent = "";
+		for(i = 0; i < tabs; i++){
+			indent += "\t";
+		}
+		if(value[1] && value[1].length){
+			var recurse = [];
+			for(i = 0; i < value[1].length; i++){
+				recurse.push(ddl._unordered_list(value[1][i], tabs + 1))
+			}
+			return indent + "<li>" + value[0] + "\n" + indent + "<ul>\n" + recurse.join("\n") + "\n" + indent + "</ul>\n" + indent + "</li>";
+		}else{
+			return indent + "<li>" + value[0] + "</li>";
+		}
+	},
+	unordered_list: function(value){
+		// summary:
+		//		Recursively takes a self-nested list and returns an HTML unordered list --
+		//		WITHOUT opening and closing <ul> tags.
+		//	description:
+		//		The list is assumed to be in the proper format. For example, if ``var`` contains
+		//		``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``,
+		//		then ``{{ var|unordered_list }}`` would return::
+		//
+		//		|	<li>States
+		//		|	<ul>
+		//		|		<li>Kansas
+		//		|		<ul>
+		//		|			<li>Lawrence</li>
+		//		|			<li>Topeka</li>
+		//		|		</ul>
+		//		|		</li>
+		//		|		<li>Illinois</li>
+		//		|	</ul>
+		//		|	</li>
+		return dojox.dtl.filter.lists._unordered_list(value, 1);
+	}
+});
\ No newline at end of file
diff --git a/dojox/dtl/filter/logic.js b/dojox/dtl/filter/logic.js
index cdf47a6..13bf9a9 100644
--- a/dojox/dtl/filter/logic.js
+++ b/dojox/dtl/filter/logic.js
@@ -1,33 +1,36 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.filter.logic"]){
-dojo._hasResource["dojox.dtl.filter.logic"]=true;
 dojo.provide("dojox.dtl.filter.logic");
-dojo.mixin(dojox.dtl.filter.logic,{default_:function(_1,_2){
-return _1||_2||"";
-},default_if_none:function(_3,_4){
-return (_3===null)?_4||"":_3||"";
-},divisibleby:function(_5,_6){
-return (parseInt(_5,10)%parseInt(_6,10))===0;
-},_yesno:/\s*,\s*/g,yesno:function(_7,_8){
-if(!_8){
-_8="yes,no,maybe";
-}
-var _9=_8.split(dojox.dtl.filter.logic._yesno);
-if(_9.length<2){
-return _7;
-}
-if(_7){
-return _9[0];
-}
-if((!_7&&_7!==null)||_9.length<3){
-return _9[1];
-}
-return _9[2];
-}});
-}
+
+dojo.mixin(dojox.dtl.filter.logic, {
+	default_: function(value, arg){
+		// summary: If value is unavailable, use given default
+		return value || arg || "";
+	},
+	default_if_none: function(value, arg){
+		// summary: If value is null, use given default
+		return (value === null) ? arg || "" : value || "";
+	},
+	divisibleby: function(value, arg){
+		// summary: Returns true if the value is devisible by the argument"
+		return (parseInt(value, 10) % parseInt(arg, 10)) === 0;
+	},
+	_yesno: /\s*,\s*/g,
+	yesno: function(value, arg){
+		// summary:
+		//		arg being a comma-delimited string, value of true/false/none
+		//		chooses the appropriate item from the string
+		if(!arg){
+			arg = 'yes,no,maybe';
+		}
+		var parts = arg.split(dojox.dtl.filter.logic._yesno);
+		if(parts.length < 2){
+			return value;
+		}
+		if(value){
+			return parts[0];
+		}
+		if((!value && value !== null) || parts.length < 3){
+			return parts[1];
+		}
+		return parts[2];
+	}
+});
\ No newline at end of file
diff --git a/dojox/dtl/filter/misc.js b/dojox/dtl/filter/misc.js
index 1bfd28e..dccd526 100644
--- a/dojox/dtl/filter/misc.js
+++ b/dojox/dtl/filter/misc.js
@@ -1,52 +1,55 @@
-/*
-	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
-*/
+dojo.provide("dojox.dtl.filter.misc");
 
+dojo.mixin(dojox.dtl.filter.misc, {
+	filesizeformat: function(value){
+		// summary: Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102bytes, etc).
+		value = parseFloat(value);
+		if(value < 1024){
+			return (value == 1) ? value + " byte" : value + " bytes";
+		}else if(value < 1024 * 1024){
+			return (value / 1024).toFixed(1) + " KB";
+		}else if(value < 1024 * 1024 * 1024){
+			return (value / 1024 / 1024).toFixed(1) + " MB";
+		}
+		return (value / 1024 / 1024 / 1024).toFixed(1) + " GB";
+	},
+	pluralize: function(value, arg){
+		// summary:
+		//		Returns a plural suffix if the value is not 1, for '1 vote' vs. '2 votes'
+		//	description:
+		//		By default, 's' is used as a suffix; if an argument is provided, that string
+		//		is used instead. If the provided argument contains a comma, the text before
+		//		the comma is used for the singular case.
+		arg = arg || 's';
+		if(arg.indexOf(",") == -1){
+			arg = "," + arg;
+		}
+		var parts = arg.split(",");
+		if(parts.length > 2){
+			return "";
+		}
+		var singular = parts[0];
+		var plural = parts[1];
 
-if(!dojo._hasResource["dojox.dtl.filter.misc"]){
-dojo._hasResource["dojox.dtl.filter.misc"]=true;
-dojo.provide("dojox.dtl.filter.misc");
-dojo.mixin(dojox.dtl.filter.misc,{filesizeformat:function(_1){
-_1=parseFloat(_1);
-if(_1<1024){
-return (_1==1)?_1+" byte":_1+" bytes";
-}else{
-if(_1<1024*1024){
-return (_1/1024).toFixed(1)+" KB";
-}else{
-if(_1<1024*1024*1024){
-return (_1/1024/1024).toFixed(1)+" MB";
-}
-}
-}
-return (_1/1024/1024/1024).toFixed(1)+" GB";
-},pluralize:function(_2,_3){
-_3=_3||"s";
-if(_3.indexOf(",")==-1){
-_3=","+_3;
-}
-var _4=_3.split(",");
-if(_4.length>2){
-return "";
-}
-var _5=_4[0];
-var _6=_4[1];
-if(parseInt(_2,10)!=1){
-return _6;
-}
-return _5;
-},_phone2numeric:{a:2,b:2,c:2,d:3,e:3,f:3,g:4,h:4,i:4,j:5,k:5,l:5,m:6,n:6,o:6,p:7,r:7,s:7,t:8,u:8,v:8,w:9,x:9,y:9},phone2numeric:function(_7){
-var dm=dojox.dtl.filter.misc;
-_7=_7+"";
-var _8="";
-for(var i=0;i<_7.length;i++){
-var _9=_7.charAt(i).toLowerCase();
-(dm._phone2numeric[_9])?_8+=dm._phone2numeric[_9]:_8+=_7.charAt(i);
-}
-return _8;
-},pprint:function(_a){
-return dojo.toJson(_a);
-}});
-}
+		if(parseInt(value, 10) != 1){
+			return plural;
+		}
+		return singular;
+	},
+	_phone2numeric: { a: 2, b: 2, c: 2, d: 3, e: 3, f: 3, g: 4, h: 4, i: 4, j: 5, k: 5, l: 5, m: 6, n: 6, o: 6, p: 7, r: 7, s: 7, t: 8, u: 8, v: 8, w: 9, x: 9, y: 9 },
+	phone2numeric: function(value){
+		// summary: Takes a phone number and converts it in to its numerical equivalent
+		var dm = dojox.dtl.filter.misc;
+		value = value + "";
+		var output = "";
+		for(var i = 0; i < value.length; i++){
+			var chr = value.charAt(i).toLowerCase();
+			(dm._phone2numeric[chr]) ? output += dm._phone2numeric[chr] : output += value.charAt(i);
+		}
+		return output;
+	},
+	pprint: function(value){
+		// summary: A wrapper around toJson unless something better comes along
+		return dojo.toJson(value);
+	}
+});
\ No newline at end of file
diff --git a/dojox/dtl/filter/strings.js b/dojox/dtl/filter/strings.js
index 1f428cc..2de0179 100644
--- a/dojox/dtl/filter/strings.js
+++ b/dojox/dtl/filter/strings.js
@@ -1,270 +1,325 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.filter.strings"]){
-dojo._hasResource["dojox.dtl.filter.strings"]=true;
 dojo.provide("dojox.dtl.filter.strings");
+
 dojo.require("dojox.dtl.filter.htmlstrings");
 dojo.require("dojox.string.sprintf");
 dojo.require("dojox.string.tokenize");
-dojo.mixin(dojox.dtl.filter.strings,{_urlquote:function(_1,_2){
-if(!_2){
-_2="/";
-}
-return dojox.string.tokenize(_1,/([^\w-_.])/g,function(_3){
-if(_2.indexOf(_3)==-1){
-if(_3==" "){
-return "+";
-}else{
-return "%"+_3.charCodeAt(0).toString(16).toUpperCase();
-}
-}
-return _3;
-}).join("");
-},addslashes:function(_4){
-return _4.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/'/g,"\\'");
-},capfirst:function(_5){
-_5=""+_5;
-return _5.charAt(0).toUpperCase()+_5.substring(1);
-},center:function(_6,_7){
-_7=_7||_6.length;
-_6=_6+"";
-var _8=_7-_6.length;
-if(_8%2){
-_6=_6+" ";
-_8-=1;
-}
-for(var i=0;i<_8;i+=2){
-_6=" "+_6+" ";
-}
-return _6;
-},cut:function(_9,_a){
-_a=_a+""||"";
-_9=_9+"";
-return _9.replace(new RegExp(_a,"g"),"");
-},_fix_ampersands:/&(?!(\w+|#\d+);)/g,fix_ampersands:function(_b){
-return _b.replace(dojox.dtl.filter.strings._fix_ampersands,"&");
-},floatformat:function(_c,_d){
-_d=parseInt(_d||-1,10);
-_c=parseFloat(_c);
-var m=_c-_c.toFixed(0);
-if(!m&&_d<0){
-return _c.toFixed();
-}
-_c=_c.toFixed(Math.abs(_d));
-return (_d<0)?parseFloat(_c)+"":_c;
-},iriencode:function(_e){
-return dojox.dtl.filter.strings._urlquote(_e,"/#%[]=:;$&()+,!");
-},linenumbers:function(_f){
-var df=dojox.dtl.filter;
-var _10=_f.split("\n");
-var _11=[];
-var _12=(_10.length+"").length;
-for(var i=0,_13;i<_10.length;i++){
-_13=_10[i];
-_11.push(df.strings.ljust(i+1,_12)+". "+dojox.dtl._base.escape(_13));
-}
-return _11.join("\n");
-},ljust:function(_14,arg){
-_14=_14+"";
-arg=parseInt(arg,10);
-while(_14.length<arg){
-_14=_14+" ";
-}
-return _14;
-},lower:function(_15){
-return (_15+"").toLowerCase();
-},make_list:function(_16){
-var _17=[];
-if(typeof _16=="number"){
-_16=_16+"";
-}
-if(_16.charAt){
-for(var i=0;i<_16.length;i++){
-_17.push(_16.charAt(i));
-}
-return _17;
-}
-if(typeof _16=="object"){
-for(var key in _16){
-_17.push(_16[key]);
-}
-return _17;
-}
-return [];
-},rjust:function(_18,arg){
-_18=_18+"";
-arg=parseInt(arg,10);
-while(_18.length<arg){
-_18=" "+_18;
-}
-return _18;
-},slugify:function(_19){
-_19=_19.replace(/[^\w\s-]/g,"").toLowerCase();
-return _19.replace(/[\-\s]+/g,"-");
-},_strings:{},stringformat:function(_1a,arg){
-arg=""+arg;
-var _1b=dojox.dtl.filter.strings._strings;
-if(!_1b[arg]){
-_1b[arg]=new dojox.string.sprintf.Formatter("%"+arg);
-}
-return _1b[arg].format(_1a);
-},title:function(_1c){
-var _1d,_1e="";
-for(var i=0,_1f;i<_1c.length;i++){
-_1f=_1c.charAt(i);
-if(_1d==" "||_1d=="\n"||_1d=="\t"||!_1d){
-_1e+=_1f.toUpperCase();
-}else{
-_1e+=_1f.toLowerCase();
-}
-_1d=_1f;
-}
-return _1e;
-},_truncatewords:/[ \n\r\t]/,truncatewords:function(_20,arg){
-arg=parseInt(arg,10);
-if(!arg){
-return _20;
-}
-for(var i=0,j=_20.length,_21=0,_22,_23;i<_20.length;i++){
-_22=_20.charAt(i);
-if(dojox.dtl.filter.strings._truncatewords.test(_23)){
-if(!dojox.dtl.filter.strings._truncatewords.test(_22)){
-++_21;
-if(_21==arg){
-return _20.substring(0,j+1);
-}
-}
-}else{
-if(!dojox.dtl.filter.strings._truncatewords.test(_22)){
-j=i;
-}
-}
-_23=_22;
-}
-return _20;
-},_truncate_words:/(&.*?;|<.*?>|(\w[\w\-]*))/g,_truncate_tag:/<(\/)?([^ ]+?)(?: (\/)| .*?)?>/,_truncate_singlets:{br:true,col:true,link:true,base:true,img:true,param:true,area:true,hr:true,input:true},truncatewords_html:function(_24,arg){
-arg=parseInt(arg,10);
-if(arg<=0){
-return "";
-}
-var _25=dojox.dtl.filter.strings;
-var _26=0;
-var _27=[];
-var _28=dojox.string.tokenize(_24,_25._truncate_words,function(all,_29){
-if(_29){
-++_26;
-if(_26<arg){
-return _29;
-}else{
-if(_26==arg){
-return _29+" ...";
-}
-}
-}
-var tag=all.match(_25._truncate_tag);
-if(!tag||_26>=arg){
-return;
-}
-var _2a=tag[1];
-var _2b=tag[2].toLowerCase();
-var _2c=tag[3];
-if(_2a||_25._truncate_singlets[_2b]){
-}else{
-if(_2a){
-var i=dojo.indexOf(_27,_2b);
-if(i!=-1){
-_27=_27.slice(i+1);
-}
-}else{
-_27.unshift(_2b);
-}
-}
-return all;
-}).join("");
-_28=_28.replace(/\s+$/g,"");
-for(var i=0,tag;tag=_27[i];i++){
-_28+="</"+tag+">";
-}
-return _28;
-},upper:function(_2d){
-return _2d.toUpperCase();
-},urlencode:function(_2e){
-return dojox.dtl.filter.strings._urlquote(_2e);
-},_urlize:/^((?:[(>]|<)*)(.*?)((?:[.,)>\n]|>)*)$/,_urlize2:/^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$/,urlize:function(_2f){
-return dojox.dtl.filter.strings.urlizetrunc(_2f);
-},urlizetrunc:function(_30,arg){
-arg=parseInt(arg);
-return dojox.string.tokenize(_30,/(\S+)/g,function(_31){
-var _32=dojox.dtl.filter.strings._urlize.exec(_31);
-if(!_32){
-return _31;
-}
-var _33=_32[1];
-var _34=_32[2];
-var _35=_32[3];
-var _36=_34.indexOf("www.")==0;
-var _37=_34.indexOf("@")!=-1;
-var _38=_34.indexOf(":")!=-1;
-var _39=_34.indexOf("http://")==0;
-var _3a=_34.indexOf("https://")==0;
-var _3b=/[a-zA-Z0-9]/.test(_34.charAt(0));
-var _3c=_34.substring(_34.length-4);
-var _3d=_34;
-if(arg>3){
-_3d=_3d.substring(0,arg-3)+"...";
-}
-if(_36||(!_37&&!_39&&_34.length&&_3b&&(_3c==".org"||_3c==".net"||_3c==".com"))){
-return "<a href=\"http://"+_34+"\" rel=\"nofollow\">"+_3d+"</a>";
-}else{
-if(_39||_3a){
-return "<a href=\""+_34+"\" rel=\"nofollow\">"+_3d+"</a>";
-}else{
-if(_37&&!_36&&!_38&&dojox.dtl.filter.strings._urlize2.test(_34)){
-return "<a href=\"mailto:"+_34+"\">"+_34+"</a>";
-}
-}
-}
-return _31;
-}).join("");
-},wordcount:function(_3e){
-_3e=dojo.trim(_3e);
-if(!_3e){
-return 0;
-}
-return _3e.split(/\s+/g).length;
-},wordwrap:function(_3f,arg){
-arg=parseInt(arg);
-var _40=[];
-var _41=_3f.split(/\s+/g);
-if(_41.length){
-var _42=_41.shift();
-_40.push(_42);
-var pos=_42.length-_42.lastIndexOf("\n")-1;
-for(var i=0;i<_41.length;i++){
-_42=_41[i];
-if(_42.indexOf("\n")!=-1){
-var _43=_42.split(/\n/g);
-}else{
-var _43=[_42];
-}
-pos+=_43[0].length+1;
-if(arg&&pos>arg){
-_40.push("\n");
-pos=_43[_43.length-1].length;
-}else{
-_40.push(" ");
-if(_43.length>1){
-pos=_43[_43.length-1].length;
-}
-}
-_40.push(_42);
-}
-}
-return _40.join("");
-}});
-}
+
+dojo.mixin(dojox.dtl.filter.strings, {
+	_urlquote: function(/*String*/ url, /*String?*/ safe){
+		if(!safe){
+			safe = "/";
+		}
+		return dojox.string.tokenize(url, /([^\w-_.])/g, function(token){
+			if(safe.indexOf(token) == -1){
+				if(token == " "){
+					return "+";
+				}else{
+					return "%" + token.charCodeAt(0).toString(16).toUpperCase();
+				}
+			}
+			return token;
+		}).join("");
+	},
+	addslashes: function(value){
+		// summary: Adds slashes - useful for passing strings to JavaScript, for example.
+		return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/'/g, "\\'");
+	},
+	capfirst: function(value){
+		// summary: Capitalizes the first character of the value
+		value = "" + value;
+		return value.charAt(0).toUpperCase() + value.substring(1);
+	},
+	center: function(value, arg){
+		// summary: Centers the value in a field of a given width
+		arg = arg || value.length;
+		value = value + "";
+		var diff = arg - value.length;
+		if(diff % 2){
+			value = value + " ";
+			diff -= 1;
+		}
+		for(var i = 0; i < diff; i += 2){
+			value = " " + value + " ";
+		}
+		return value;
+	},
+	cut: function(value, arg){
+		// summary: Removes all values of arg from the given string
+		arg = arg + "" || "";
+		value = value + "";
+		return value.replace(new RegExp(arg, "g"), "");
+	},
+	_fix_ampersands: /&(?!(\w+|#\d+);)/g,
+	fix_ampersands: function(value){
+		// summary: Replaces ampersands with ``&`` entities
+		return value.replace(dojox.dtl.filter.strings._fix_ampersands, "&");
+	},
+	floatformat: function(value, arg){
+		// summary: Format a number according to arg
+		// description:
+		//		If called without an argument, displays a floating point
+		//		number as 34.2 -- but only if there's a point to be displayed.
+		//		With a positive numeric argument, it displays that many decimal places
+		//		always.
+		//		With a negative numeric argument, it will display that many decimal
+		//		places -- but only if there's places to be displayed.
+		arg = parseInt(arg || -1, 10);
+		value = parseFloat(value);
+		var m = value - value.toFixed(0);
+		if(!m && arg < 0){
+			return value.toFixed();
+		}
+		value = value.toFixed(Math.abs(arg));
+		return (arg < 0) ? parseFloat(value) + "" : value;
+	},
+	iriencode: function(value){
+		return dojox.dtl.filter.strings._urlquote(value, "/#%[]=:;$&()+,!");
+	},
+	linenumbers: function(value){
+		// summary: Displays text with line numbers
+		var df = dojox.dtl.filter;
+		var lines = value.split("\n");
+		var output = [];
+		var width = (lines.length + "").length;
+		for(var i = 0, line; i < lines.length; i++){
+			line = lines[i];
+			output.push(df.strings.ljust(i + 1, width) + ". " + dojox.dtl._base.escape(line));
+		}
+		return output.join("\n");
+	},
+	ljust: function(value, arg){
+		value = value + "";
+		arg = parseInt(arg, 10);
+		while(value.length < arg){
+			value = value + " ";
+		}
+		return value;
+	},
+	lower: function(value){
+		// summary: Converts a string into all lowercase
+		return (value + "").toLowerCase();
+	},
+	make_list: function(value){
+		// summary:
+		//		Returns the value turned into a list. For an integer, it's a list of
+		//		digits. For a string, it's a list of characters.
+		var output = [];
+		if(typeof value == "number"){
+			value = value + "";
+		}
+		if(value.charAt){
+			for(var i = 0; i < value.length; i++){
+				output.push(value.charAt(i));
+			}
+			return output;
+		}
+		if(typeof value == "object"){
+			for(var key in value){
+				output.push(value[key]);
+			}
+			return output;
+		}
+		return [];
+	},
+	rjust: function(value, arg){
+		value = value + "";
+		arg = parseInt(arg, 10);
+		while(value.length < arg){
+			value = " " + value;
+		}
+		return value;
+	},
+	slugify: function(value){
+		// summary: Converts to lowercase, removes
+		//		non-alpha chars and converts spaces to hyphens
+		value = value.replace(/[^\w\s-]/g, "").toLowerCase();
+		return value.replace(/[\-\s]+/g, "-");
+	},
+	_strings: {},
+	stringformat: function(value, arg){
+		// summary:
+		//		Formats the variable according to the argument, a string formatting specifier.
+		//		This specifier uses Python string formating syntax, with the exception that
+		//		the leading "%" is dropped.
+		arg = "" + arg;
+		var strings = dojox.dtl.filter.strings._strings;
+		if(!strings[arg]){
+			strings[arg] = new dojox.string.sprintf.Formatter("%" + arg);
+		}
+		return strings[arg].format(value);
+	},
+	title: function(value){
+		// summary: Converts a string into titlecase
+		var last, title = "";
+		for(var i = 0, current; i < value.length; i++){
+			current = value.charAt(i);
+			if(last == " " || last == "\n" || last == "\t" || !last){
+				title += current.toUpperCase();
+			}else{
+				title += current.toLowerCase();
+			}
+			last = current;
+		}
+		return title;
+	},
+	_truncatewords: /[ \n\r\t]/,
+	truncatewords: function(value, arg){
+		// summary: Truncates a string after a certain number of words
+		// arg: Integer
+		//		Number of words to truncate after
+		arg = parseInt(arg, 10);
+		if(!arg){
+			return value;
+		}
+
+		for(var i = 0, j = value.length, count = 0, current, last; i < value.length; i++){
+			current = value.charAt(i);
+			if(dojox.dtl.filter.strings._truncatewords.test(last)){
+				if(!dojox.dtl.filter.strings._truncatewords.test(current)){
+					++count;
+					if(count == arg){
+						return value.substring(0, j + 1);
+					}
+				}
+			}else if(!dojox.dtl.filter.strings._truncatewords.test(current)){
+				j = i;
+			}
+			last = current;
+		}
+		return value;
+	},
+	_truncate_words: /(&.*?;|<.*?>|(\w[\w\-]*))/g,
+	_truncate_tag: /<(\/)?([^ ]+?)(?: (\/)| .*?)?>/,
+	_truncate_singlets: { br: true, col: true, link: true, base: true, img: true, param: true, area: true, hr: true, input: true },
+	truncatewords_html: function(value, arg){
+		arg = parseInt(arg, 10);
+
+		if(arg <= 0){
+			return "";
+		}
+
+		var strings = dojox.dtl.filter.strings;
+		var words = 0;
+		var open = [];
+
+		var output = dojox.string.tokenize(value, strings._truncate_words, function(all, word){
+			if(word){
+				// It's an actual non-HTML word
+				++words;
+				if(words < arg){
+					return word;
+				}else if(words == arg){
+					return word + " ...";
+				}
+			}
+			// Check for tag
+			var tag = all.match(strings._truncate_tag);
+			if(!tag || words >= arg){
+				// Don't worry about non tags or tags after our truncate point
+				return;
+			}
+			var closing = tag[1];
+			var tagname = tag[2].toLowerCase();
+			var selfclosing = tag[3];
+			if(closing || strings._truncate_singlets[tagname]){
+			}else if(closing){
+				var i = dojo.indexOf(open, tagname);
+				if(i != -1){
+					open = open.slice(i + 1);
+				}
+			}else{
+				open.unshift(tagname);
+			}
+			return all;
+		}).join("");
+
+		output = output.replace(/\s+$/g, "");
+
+		for(var i = 0, tag; tag = open[i]; i++){
+			output += "</" + tag + ">";
+		}
+
+		return output;
+	},
+	upper: function(value){
+		return value.toUpperCase();
+	},
+	urlencode: function(value){
+		return dojox.dtl.filter.strings._urlquote(value);
+	},
+	_urlize: /^((?:[(>]|<)*)(.*?)((?:[.,)>\n]|>)*)$/,
+	_urlize2: /^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$/,
+	urlize: function(value){
+		return dojox.dtl.filter.strings.urlizetrunc(value);
+	},
+	urlizetrunc: function(value, arg){
+		arg = parseInt(arg);
+		return dojox.string.tokenize(value, /(\S+)/g, function(word){
+			var matches = dojox.dtl.filter.strings._urlize.exec(word);
+			if(!matches){
+				return word;
+			}
+			var lead = matches[1];
+			var middle = matches[2];
+			var trail = matches[3];
+
+			var startsWww = middle.indexOf("www.") == 0;
+			var hasAt = middle.indexOf("@") != -1;
+			var hasColon = middle.indexOf(":") != -1;
+			var startsHttp = middle.indexOf("http://") == 0;
+			var startsHttps = middle.indexOf("https://") == 0;
+			var firstAlpha = /[a-zA-Z0-9]/.test(middle.charAt(0));
+			var last4 = middle.substring(middle.length - 4);
+
+			var trimmed = middle;
+			if(arg > 3){
+				trimmed = trimmed.substring(0, arg - 3) + "...";
+			}
+
+			if(startsWww || (!hasAt && !startsHttp && middle.length && firstAlpha && (last4 == ".org" || last4 == ".net" || last4 == ".com"))){
+				return '<a href="http://' + middle + '" rel="nofollow">' + trimmed + '</a>';
+			}else if(startsHttp || startsHttps){
+				return '<a href="' + middle + '" rel="nofollow">' + trimmed + '</a>';
+			}else if(hasAt && !startsWww && !hasColon && dojox.dtl.filter.strings._urlize2.test(middle)){
+				return '<a href="mailto:' + middle + '">' + middle + '</a>';
+			}
+			return word;
+		}).join("");
+	},
+	wordcount: function(value){
+		value = dojo.trim(value);
+		if(!value){ return 0; }
+		return value.split(/\s+/g).length;
+	},
+	wordwrap: function(value, arg){
+		arg = parseInt(arg);
+		// summary: Wraps words at specified line length
+		var output = [];
+		var parts = value.split(/\s+/g);
+		if(parts.length){
+			var word = parts.shift();
+			output.push(word);
+			var pos = word.length - word.lastIndexOf("\n") - 1;
+			for(var i = 0; i < parts.length; i++){
+				word = parts[i];
+				if(word.indexOf("\n") != -1){
+					var lines = word.split(/\n/g);
+				}else{
+					var lines = [word];
+				}
+				pos += lines[0].length + 1;
+				if(arg && pos > arg){
+					output.push("\n");
+					pos = lines[lines.length - 1].length;
+				}else{
+					output.push(" ");
+					if(lines.length > 1){
+						pos = lines[lines.length - 1].length;
+					}
+				}
+				output.push(word);
+			}
+		}
+		return output.join("");
+	}
+});
\ No newline at end of file
diff --git a/dojox/dtl/html.js b/dojox/dtl/html.js
old mode 100644
new mode 100755
index c2aa37d..2d6ad04
--- a/dojox/dtl/html.js
+++ b/dojox/dtl/html.js
@@ -1,14 +1,4 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.html"]){
-dojo._hasResource["dojox.dtl.html"]=true;
 dojo.provide("dojox.dtl.html");
-dojo.deprecated("dojox.dtl.html","All packages and classes in dojox.dtl that start with Html or html have been renamed to Dom or dom");
+dojo.deprecated("dojox.dtl.html", "All packages and classes in dojox.dtl that start with Html or html have been renamed to Dom or dom");
 dojo.require("dojox.dtl.dom");
-dojox.dtl.HtmlTemplate=dojox.dtl.DomTemplate;
-}
+dojox.dtl.HtmlTemplate = dojox.dtl.DomTemplate;
\ No newline at end of file
diff --git a/dojox/dtl/render/dom.js b/dojox/dtl/render/dom.js
index 0cdcf11..fb9138a 100644
--- a/dojox/dtl/render/dom.js
+++ b/dojox/dtl/render/dom.js
@@ -1,35 +1,33 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.render.dom"]){
-dojo._hasResource["dojox.dtl.render.dom"]=true;
 dojo.provide("dojox.dtl.render.dom");
+
 dojo.require("dojox.dtl.Context");
 dojo.require("dojox.dtl.dom");
-dojox.dtl.render.dom.Render=function(_1,_2){
-this._tpl=_2;
-this.domNode=dojo.byId(_1);
-};
-dojo.extend(dojox.dtl.render.dom.Render,{setAttachPoint:function(_3){
-this.domNode=_3;
-},render:function(_4,_5,_6){
-if(!this.domNode){
-throw new Error("You cannot use the Render object without specifying where you want to render it");
-}
-this._tpl=_5=_5||this._tpl;
-_6=_6||_5.getBuffer();
-_4=_4||new dojox.dtl.Context();
-var _7=_5.render(_4,_6).getParent();
-if(!_7){
-throw new Error("Rendered template does not have a root node");
-}
-if(this.domNode!==_7){
-this.domNode.parentNode.replaceChild(_7,this.domNode);
-this.domNode=_7;
-}
-}});
+
+dojox.dtl.render.dom.Render = function(/*DOMNode?*/ attachPoint, /*dojox.dtl.DomTemplate?*/ tpl){
+	this._tpl = tpl;
+	this.domNode = dojo.byId(attachPoint);
 }
+dojo.extend(dojox.dtl.render.dom.Render, {
+	setAttachPoint: function(/*Node*/ node){
+		this.domNode = node;
+	},
+	render: function(/*Object*/ context, /*dojox.dtl.DomTemplate?*/ tpl, /*dojox.dtl.DomBuffer?*/ buffer){
+		if(!this.domNode){
+			throw new Error("You cannot use the Render object without specifying where you want to render it");
+		}
+
+		this._tpl = tpl = tpl || this._tpl;
+		buffer = buffer || tpl.getBuffer();
+		context = context || new dojox.dtl.Context();
+
+		var frag = tpl.render(context, buffer).getParent();
+		if(!frag){
+			throw new Error("Rendered template does not have a root node");
+		}
+
+		if(this.domNode !== frag){
+			this.domNode.parentNode.replaceChild(frag, this.domNode);
+			this.domNode = frag;
+		}
+	}
+});
\ No newline at end of file
diff --git a/dojox/dtl/render/html.js b/dojox/dtl/render/html.js
index 3079cbd..e14f82a 100644
--- a/dojox/dtl/render/html.js
+++ b/dojox/dtl/render/html.js
@@ -1,13 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.render.html"]){
-dojo._hasResource["dojox.dtl.render.html"]=true;
 dojo.provide("dojox.dtl.render.html");
 dojo.require("dojox.dtl.render.dom");
-dojox.dtl.render.html.Render=dojox.dtl.render.dom.Render;
-}
+dojox.dtl.render.html.Render = dojox.dtl.render.dom.Render;
\ No newline at end of file
diff --git a/dojox/dtl/tag/date.js b/dojox/dtl/tag/date.js
index 6d6e6a7..49aaa8e 100644
--- a/dojox/dtl/tag/date.js
+++ b/dojox/dtl/tag/date.js
@@ -1,33 +1,31 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.tag.date"]){
-dojo._hasResource["dojox.dtl.tag.date"]=true;
 dojo.provide("dojox.dtl.tag.date");
+
 dojo.require("dojox.dtl._base");
 dojo.require("dojox.dtl.utils.date");
-dojox.dtl.tag.date.NowNode=function(_1,_2){
-this._format=_1;
-this.format=new dojox.dtl.utils.date.DateFormat(_1);
-this.contents=_2;
-};
-dojo.extend(dojox.dtl.tag.date.NowNode,{render:function(_3,_4){
-this.contents.set(this.format.format(new Date()));
-return this.contents.render(_3,_4);
-},unrender:function(_5,_6){
-return this.contents.unrender(_5,_6);
-},clone:function(_7){
-return new this.constructor(this._format,this.contents.clone(_7));
-}});
-dojox.dtl.tag.date.now=function(_8,_9){
-var _a=_9.split_contents();
-if(_a.length!=2){
-throw new Error("'now' statement takes one argument");
-}
-return new dojox.dtl.tag.date.NowNode(_a[1].slice(1,-1),_8.create_text_node());
-};
+
+dojox.dtl.tag.date.NowNode = function(format, node){
+	this._format = format;
+	this.format = new dojox.dtl.utils.date.DateFormat(format);
+	this.contents = node;
 }
+dojo.extend(dojox.dtl.tag.date.NowNode, {
+	render: function(context, buffer){
+		this.contents.set(this.format.format(new Date()));
+		return this.contents.render(context, buffer);
+	},
+	unrender: function(context, buffer){
+		return this.contents.unrender(context, buffer);
+	},
+	clone: function(buffer){
+		return new this.constructor(this._format, this.contents.clone(buffer));
+	}
+});
+
+dojox.dtl.tag.date.now = function(parser, token){
+	// Split by either :" or :'
+	var parts = token.split_contents();
+	if(parts.length != 2){
+		throw new Error("'now' statement takes one argument");
+	}
+	return new dojox.dtl.tag.date.NowNode(parts[1].slice(1, -1), parser.create_text_node());
+}
\ No newline at end of file
diff --git a/dojox/dtl/tag/loader.js b/dojox/dtl/tag/loader.js
index 2216234..049be42 100644
--- a/dojox/dtl/tag/loader.js
+++ b/dojox/dtl/tag/loader.js
@@ -1,260 +1,297 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.tag.loader"]){
-dojo._hasResource["dojox.dtl.tag.loader"]=true;
 dojo.provide("dojox.dtl.tag.loader");
+
 dojo.require("dojox.dtl._base");
+
 (function(){
-var dd=dojox.dtl;
-var _1=dd.tag.loader;
-_1.BlockNode=dojo.extend(function(_2,_3){
-this.name=_2;
-this.nodelist=_3;
-},{"super":function(){
-if(this.parent){
-var _4=this.parent.nodelist.dummyRender(this.context,null,true);
-if(typeof _4=="string"){
-_4=new String(_4);
-}
-_4.safe=true;
-return _4;
-}
-return "";
-},render:function(_5,_6){
-var _7=this.name;
-var _8=this.nodelist;
-var _9;
-if(_6.blocks){
-var _a=_6.blocks[_7];
-if(_a){
-_9=_a.parent;
-_8=_a.nodelist;
-_a.used=true;
-}
-}
-this.rendered=_8;
-_5=_5.push();
-this.context=_5;
-this.parent=null;
-if(_8!=this.nodelist){
-this.parent=this;
-}
-_5.block=this;
-if(_6.getParent){
-var _b=_6.getParent();
-var _c=dojo.connect(_6,"onSetParent",function(_d,up,_e){
-if(up&&_e){
-_6.setParent(_b);
-}
-});
-}
-_6=_8.render(_5,_6,this);
-_c&&dojo.disconnect(_c);
-_5=_5.pop();
-return _6;
-},unrender:function(_f,_10){
-return this.rendered.unrender(_f,_10);
-},clone:function(_11){
-return new this.constructor(this.name,this.nodelist.clone(_11));
-},toString:function(){
-return "dojox.dtl.tag.loader.BlockNode";
-}});
-_1.ExtendsNode=dojo.extend(function(_12,_13,_14,_15,key){
-this.getTemplate=_12;
-this.nodelist=_13;
-this.shared=_14;
-this.parent=_15;
-this.key=key;
-},{parents:{},getParent:function(_16){
-var _17=this.parent;
-if(!_17){
-var _18;
-_17=this.parent=_16.get(this.key,false);
-if(!_17){
-throw new Error("extends tag used a variable that did not resolve");
-}
-if(typeof _17=="object"){
-var url=_17.url||_17.templatePath;
-if(_17.shared){
-this.shared=true;
-}
-if(url){
-_17=this.parent=url.toString();
-}else{
-if(_17.templateString){
-_18=_17.templateString;
-_17=this.parent=" ";
-}else{
-_17=this.parent=this.parent.toString();
-}
-}
-}
-if(_17&&_17.indexOf("shared:")===0){
-this.shared=true;
-_17=this.parent=_17.substring(7,_17.length);
-}
-}
-if(!_17){
-throw new Error("Invalid template name in 'extends' tag.");
-}
-if(_17.render){
-return _17;
-}
-if(this.parents[_17]){
-return this.parents[_17];
-}
-this.parent=this.getTemplate(_18||dojox.dtl.text.getTemplateString(_17));
-if(this.shared){
-this.parents[_17]=this.parent;
-}
-return this.parent;
-},render:function(_19,_1a){
-var _1b=this.getParent(_19);
-_1b.blocks=_1b.blocks||{};
-_1a.blocks=_1a.blocks||{};
-for(var i=0,_1c;_1c=this.nodelist.contents[i];i++){
-if(_1c instanceof dojox.dtl.tag.loader.BlockNode){
-var old=_1b.blocks[_1c.name];
-if(old&&old.nodelist!=_1c.nodelist){
-_1a=old.nodelist.unrender(_19,_1a);
-}
-_1b.blocks[_1c.name]=_1a.blocks[_1c.name]={shared:this.shared,nodelist:_1c.nodelist,used:false};
-}
-}
-this.rendered=_1b;
-return _1b.nodelist.render(_19,_1a,this);
-},unrender:function(_1d,_1e){
-return this.rendered.unrender(_1d,_1e,this);
-},toString:function(){
-return "dojox.dtl.block.ExtendsNode";
-}});
-_1.IncludeNode=dojo.extend(function(_1f,_20,_21,_22,_23){
-this._path=_1f;
-this.constant=_20;
-this.path=(_20)?_1f:new dd._Filter(_1f);
-this.getTemplate=_21;
-this.text=_22;
-this.parsed=(arguments.length==5)?_23:true;
-},{_cache:[{},{}],render:function(_24,_25){
-var _26=((this.constant)?this.path:this.path.resolve(_24)).toString();
-var _27=Number(this.parsed);
-var _28=false;
-if(_26!=this.last){
-_28=true;
-if(this.last){
-_25=this.unrender(_24,_25);
-}
-this.last=_26;
-}
-var _29=this._cache[_27];
-if(_27){
-if(!_29[_26]){
-_29[_26]=dd.text._resolveTemplateArg(_26,true);
-}
-if(_28){
-var _2a=this.getTemplate(_29[_26]);
-this.rendered=_2a.nodelist;
-}
-return this.rendered.render(_24,_25,this);
-}else{
-if(this.text instanceof dd._TextNode){
-if(_28){
-this.rendered=this.text;
-this.rendered.set(dd.text._resolveTemplateArg(_26,true));
-}
-return this.rendered.render(_24,_25);
-}else{
-if(!_29[_26]){
-var _2b=[];
-var div=document.createElement("div");
-div.innerHTML=dd.text._resolveTemplateArg(_26,true);
-var _2c=div.childNodes;
-while(_2c.length){
-var _2d=div.removeChild(_2c[0]);
-_2b.push(_2d);
-}
-_29[_26]=_2b;
-}
-if(_28){
-this.nodelist=[];
-var _2e=true;
-for(var i=0,_2f;_2f=_29[_26][i];i++){
-this.nodelist.push(_2f.cloneNode(true));
-}
-}
-for(var i=0,_30;_30=this.nodelist[i];i++){
-_25=_25.concat(_30);
-}
-}
-}
-return _25;
-},unrender:function(_31,_32){
-if(this.rendered){
-_32=this.rendered.unrender(_31,_32);
-}
-if(this.nodelist){
-for(var i=0,_33;_33=this.nodelist[i];i++){
-_32=_32.remove(_33);
-}
-}
-return _32;
-},clone:function(_34){
-return new this.constructor(this._path,this.constant,this.getTemplate,this.text.clone(_34),this.parsed);
-}});
-dojo.mixin(_1,{block:function(_35,_36){
-var _37=_36.contents.split();
-var _38=_37[1];
-_35._blocks=_35._blocks||{};
-_35._blocks[_38]=_35._blocks[_38]||[];
-_35._blocks[_38].push(_38);
-var _39=_35.parse(["endblock","endblock "+_38]).rtrim();
-_35.next_token();
-return new dojox.dtl.tag.loader.BlockNode(_38,_39);
-},extends_:function(_3a,_3b){
-var _3c=_3b.contents.split();
-var _3d=false;
-var _3e=null;
-var key=null;
-if(_3c[1].charAt(0)=="\""||_3c[1].charAt(0)=="'"){
-_3e=_3c[1].substring(1,_3c[1].length-1);
-}else{
-key=_3c[1];
-}
-if(_3e&&_3e.indexOf("shared:")==0){
-_3d=true;
-_3e=_3e.substring(7,_3e.length);
-}
-var _3f=_3a.parse();
-return new dojox.dtl.tag.loader.ExtendsNode(_3a.getTemplate,_3f,_3d,_3e,key);
-},include:function(_40,_41){
-var _42=_41.contents.split();
-if(_42.length!=2){
-throw new Error(_42[0]+" tag takes one argument: the name of the template to be included");
-}
-var _43=_42[1];
-var _44=false;
-if((_43.charAt(0)=="\""||_43.slice(-1)=="'")&&_43.charAt(0)==_43.slice(-1)){
-_43=_43.slice(1,-1);
-_44=true;
-}
-return new _1.IncludeNode(_43,_44,_40.getTemplate,_40.create_text_node());
-},ssi:function(_45,_46){
-var _47=_46.contents.split();
-var _48=false;
-if(_47.length==3){
-_48=(_47.pop()=="parsed");
-if(!_48){
-throw new Error("Second (optional) argument to ssi tag must be 'parsed'");
-}
-}
-var _49=_1.include(_45,new dd.Token(_46.token_type,_47.join(" ")));
-_49.parsed=_48;
-return _49;
-}});
-})();
-}
+	var dd = dojox.dtl;
+	var ddtl = dd.tag.loader;
+
+	ddtl.BlockNode = dojo.extend(function(name, nodelist){
+		this.name = name;
+		this.nodelist = nodelist; // Can be overridden
+	},
+	{
+		"super": function(){
+			if(this.parent){
+				var html = this.parent.nodelist.dummyRender(this.context, null, true);
+				if(typeof html == "string"){
+					html = new String(html);
+				}
+				html.safe = true;
+				return html;
+			}
+			return '';
+		},
+		render: function(context, buffer){
+			var name = this.name;
+			var nodelist = this.nodelist;
+			var parent;
+			if(buffer.blocks){
+				var block = buffer.blocks[name];
+				if(block){
+					parent = block.parent;
+					nodelist = block.nodelist;
+					block.used = true;
+				}
+			}
+
+			this.rendered = nodelist;
+
+			context = context.push();
+			this.context = context;
+			this.parent = null;
+			if(nodelist != this.nodelist){
+				this.parent = this;
+			}
+			context.block = this;
+
+			if(buffer.getParent){
+				var bufferParent = buffer.getParent();
+				var setParent = dojo.connect(buffer, "onSetParent", function(node, up, root){
+					if(up && root){
+						buffer.setParent(bufferParent);
+					}
+				});
+			}
+			buffer = nodelist.render(context, buffer, this);
+			setParent && dojo.disconnect(setParent);
+			context = context.pop();
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			return this.rendered.unrender(context, buffer);
+		},
+		clone: function(buffer){
+			return new this.constructor(this.name, this.nodelist.clone(buffer));
+		},
+		toString: function(){ return "dojox.dtl.tag.loader.BlockNode"; }
+	});
+
+	ddtl.ExtendsNode = dojo.extend(function(getTemplate, nodelist, shared, parent, key){
+		this.getTemplate = getTemplate;
+		this.nodelist = nodelist;
+		this.shared = shared;
+		this.parent = parent;
+		this.key = key;
+	},
+	{
+		parents: {},
+		getParent: function(context){
+			var parent = this.parent;
+			if(!parent){
+				var string;
+				parent = this.parent = context.get(this.key, false);
+				if(!parent){
+					throw new Error("extends tag used a variable that did not resolve");
+				}
+				if(typeof parent == "object"){
+					var url = parent.url || parent.templatePath;
+					if(parent.shared){
+						this.shared = true;
+					}
+					if(url){
+						parent = this.parent = url.toString();
+					}else if(parent.templateString){
+						// Allow the builder's string interning to work
+						string = parent.templateString;
+						parent = this.parent = " ";
+					}else{
+						parent = this.parent = this.parent.toString();
+					}
+				}
+				if(parent && parent.indexOf("shared:") === 0){
+					this.shared = true;
+					parent = this.parent = parent.substring(7, parent.length);
+				}
+			}
+			if(!parent){
+				throw new Error("Invalid template name in 'extends' tag.");
+			}
+			if(parent.render){
+				return parent;
+			}
+			if(this.parents[parent]){
+				return this.parents[parent];
+			}
+			this.parent = this.getTemplate(string || dojox.dtl.text.getTemplateString(parent));
+			if(this.shared){
+				this.parents[parent] = this.parent;
+			}
+			return this.parent;
+		},
+		render: function(context, buffer){
+			var parent = this.getParent(context);
+
+			parent.blocks = parent.blocks || {};
+			buffer.blocks = buffer.blocks || {};
+
+			for(var i = 0, node; node = this.nodelist.contents[i]; i++){
+				if(node instanceof dojox.dtl.tag.loader.BlockNode){
+					var old = parent.blocks[node.name];
+					if(old && old.nodelist != node.nodelist){
+						// In a shared template, the individual blocks might change
+						buffer = old.nodelist.unrender(context, buffer);
+					}
+					parent.blocks[node.name] = buffer.blocks[node.name] = {
+						shared: this.shared,
+						nodelist: node.nodelist,
+						used: false
+					}
+				}
+			}
+
+			this.rendered = parent;
+			return parent.nodelist.render(context, buffer, this);
+		},
+		unrender: function(context, buffer){
+			return this.rendered.unrender(context, buffer, this);
+		},
+		toString: function(){ return "dojox.dtl.block.ExtendsNode"; }
+	});
+
+	ddtl.IncludeNode = dojo.extend(function(path, constant, getTemplate, text, parsed){
+		this._path = path;
+		this.constant = constant;
+		this.path = (constant) ? path : new dd._Filter(path);
+		this.getTemplate = getTemplate;
+		this.text = text;
+		this.parsed = (arguments.length == 5) ? parsed : true;
+	},
+	{
+		_cache: [{}, {}],
+		render: function(context, buffer){
+			var location = ((this.constant) ? this.path : this.path.resolve(context)).toString();
+			var parsed = Number(this.parsed);
+			var dirty = false;
+			if(location != this.last){
+				dirty = true;
+				if(this.last){
+					buffer = this.unrender(context, buffer);
+				}
+				this.last = location;
+			}
+
+			var cache = this._cache[parsed];
+
+			if(parsed){
+				if(!cache[location]){
+					cache[location] = dd.text._resolveTemplateArg(location, true);
+				}
+				if(dirty){
+					var template = this.getTemplate(cache[location]);
+					this.rendered = template.nodelist;
+				}
+				return this.rendered.render(context, buffer, this);
+			}else{
+				if(this.text instanceof dd._TextNode){
+					if(dirty){
+						this.rendered = this.text;
+						this.rendered.set(dd.text._resolveTemplateArg(location, true));
+					}
+					return this.rendered.render(context, buffer);
+				}else{
+					if(!cache[location]){
+						var nodelist = [];
+						var div = document.createElement("div");
+						div.innerHTML = dd.text._resolveTemplateArg(location, true);
+						var children = div.childNodes;
+						while(children.length){
+							var removed = div.removeChild(children[0]);
+							nodelist.push(removed);
+						}
+						cache[location] = nodelist;
+					}
+					if(dirty){
+						this.nodelist = [];
+						var exists = true;
+						for(var i = 0, child; child = cache[location][i]; i++){
+							this.nodelist.push(child.cloneNode(true));
+						}
+					}
+					for(var i = 0, node; node = this.nodelist[i]; i++){
+						buffer = buffer.concat(node);
+					}
+				}
+			}
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			if(this.rendered){
+				buffer = this.rendered.unrender(context, buffer);
+			}
+			if(this.nodelist){
+				for(var i = 0, node; node = this.nodelist[i]; i++){
+					buffer = buffer.remove(node);
+				}
+			}
+			return buffer;
+		},
+		clone: function(buffer){
+			return new this.constructor(this._path, this.constant, this.getTemplate, this.text.clone(buffer), this.parsed);
+		}
+	});
+
+	dojo.mixin(ddtl, {
+		block: function(parser, token){
+			var parts = token.contents.split();
+			var name = parts[1];
+
+			parser._blocks = parser._blocks || {};
+			parser._blocks[name] = parser._blocks[name] || [];
+			parser._blocks[name].push(name);
+
+			var nodelist = parser.parse(["endblock", "endblock " + name]).rtrim();
+			parser.next_token();
+			return new dojox.dtl.tag.loader.BlockNode(name, nodelist);
+		},
+		extends_: function(parser, token){
+			var parts = token.contents.split();
+			var shared = false;
+			var parent = null;
+			var key = null;
+			if(parts[1].charAt(0) == '"' || parts[1].charAt(0) == "'"){
+				parent = parts[1].substring(1, parts[1].length - 1);
+			}else{
+				key = parts[1];
+			}
+			if(parent && parent.indexOf("shared:") == 0){
+				shared = true;
+				parent = parent.substring(7, parent.length);
+			}
+			var nodelist = parser.parse();
+			return new dojox.dtl.tag.loader.ExtendsNode(parser.getTemplate, nodelist, shared, parent, key);
+		},
+		include: function(parser, token){
+			var parts = token.contents.split();
+			if(parts.length != 2){
+				throw new Error(parts[0] + " tag takes one argument: the name of the template to be included");
+			}
+			var path = parts[1];
+			var constant = false;
+			if((path.charAt(0) == '"' || path.slice(-1) == "'") && path.charAt(0) == path.slice(-1)){
+				path = path.slice(1, -1);
+				constant = true;
+			}
+			return new ddtl.IncludeNode(path, constant, parser.getTemplate, parser.create_text_node());
+		},
+		ssi: function(parser, token){
+			// We're going to treat things a little differently here.
+			// First of all, this tag is *not* portable, so I'm not
+			// concerned about it being a "drop in" replacement.
+
+			// Instead, we'll just replicate the include tag, but with that
+			// optional "parsed" parameter.
+			var parts = token.contents.split();
+			var parsed = false;
+			if(parts.length == 3){
+				parsed = (parts.pop() == "parsed");
+				if(!parsed){
+					throw new Error("Second (optional) argument to ssi tag must be 'parsed'");
+				}
+			}
+			var node = ddtl.include(parser, new dd.Token(token.token_type, parts.join(" ")));
+			node.parsed = parsed;
+			return node;
+		}
+	});
+})();
\ No newline at end of file
diff --git a/dojox/dtl/tag/logic.js b/dojox/dtl/tag/logic.js
index 4492cfb..6f77f27 100644
--- a/dojox/dtl/tag/logic.js
+++ b/dojox/dtl/tag/logic.js
@@ -1,247 +1,276 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.tag.logic"]){
-dojo._hasResource["dojox.dtl.tag.logic"]=true;
 dojo.provide("dojox.dtl.tag.logic");
+
 dojo.require("dojox.dtl._base");
+
 (function(){
-var dd=dojox.dtl;
-var _1=dd.text;
-var _2=dd.tag.logic;
-_2.IfNode=dojo.extend(function(_3,_4,_5,_6){
-this.bools=_3;
-this.trues=_4;
-this.falses=_5;
-this.type=_6;
-},{render:function(_7,_8){
-var i,_9,_a,_b,_c;
-if(this.type=="or"){
-for(i=0;_9=this.bools[i];i++){
-_a=_9[0];
-_b=_9[1];
-_c=_b.resolve(_7);
-if((_c&&!_a)||(_a&&!_c)){
-if(this.falses){
-_8=this.falses.unrender(_7,_8);
-}
-return (this.trues)?this.trues.render(_7,_8,this):_8;
-}
-}
-if(this.trues){
-_8=this.trues.unrender(_7,_8);
-}
-return (this.falses)?this.falses.render(_7,_8,this):_8;
-}else{
-for(i=0;_9=this.bools[i];i++){
-_a=_9[0];
-_b=_9[1];
-_c=_b.resolve(_7);
-if(_c==_a){
-if(this.trues){
-_8=this.trues.unrender(_7,_8);
-}
-return (this.falses)?this.falses.render(_7,_8,this):_8;
-}
-}
-if(this.falses){
-_8=this.falses.unrender(_7,_8);
-}
-return (this.trues)?this.trues.render(_7,_8,this):_8;
-}
-return _8;
-},unrender:function(_d,_e){
-_e=(this.trues)?this.trues.unrender(_d,_e):_e;
-_e=(this.falses)?this.falses.unrender(_d,_e):_e;
-return _e;
-},clone:function(_f){
-var _10=(this.trues)?this.trues.clone(_f):null;
-var _11=(this.falses)?this.falses.clone(_f):null;
-return new this.constructor(this.bools,_10,_11,this.type);
-}});
-_2.IfEqualNode=dojo.extend(function(_12,_13,_14,_15,_16){
-this.var1=new dd._Filter(_12);
-this.var2=new dd._Filter(_13);
-this.trues=_14;
-this.falses=_15;
-this.negate=_16;
-},{render:function(_17,_18){
-var _19=this.var1.resolve(_17);
-var _1a=this.var2.resolve(_17);
-_19=(typeof _19!="undefined")?_19:"";
-_1a=(typeof _19!="undefined")?_1a:"";
-if((this.negate&&_19!=_1a)||(!this.negate&&_19==_1a)){
-if(this.falses){
-_18=this.falses.unrender(_17,_18,this);
-}
-return (this.trues)?this.trues.render(_17,_18,this):_18;
-}
-if(this.trues){
-_18=this.trues.unrender(_17,_18,this);
-}
-return (this.falses)?this.falses.render(_17,_18,this):_18;
-},unrender:function(_1b,_1c){
-return _2.IfNode.prototype.unrender.call(this,_1b,_1c);
-},clone:function(_1d){
-var _1e=this.trues?this.trues.clone(_1d):null;
-var _1f=this.falses?this.falses.clone(_1d):null;
-return new this.constructor(this.var1.getExpression(),this.var2.getExpression(),_1e,_1f,this.negate);
-}});
-_2.ForNode=dojo.extend(function(_20,_21,_22,_23){
-this.assign=_20;
-this.loop=new dd._Filter(_21);
-this.reversed=_22;
-this.nodelist=_23;
-this.pool=[];
-},{render:function(_24,_25){
-var i,j,k;
-var _26=false;
-var _27=this.assign;
-for(k=0;k<_27.length;k++){
-if(typeof _24[_27[k]]!="undefined"){
-_26=true;
-_24=_24.push();
-break;
-}
-}
-if(!_26&&_24.forloop){
-_26=true;
-_24=_24.push();
-}
-var _28=this.loop.resolve(_24)||[];
-for(i=_28.length;i<this.pool.length;i++){
-this.pool[i].unrender(_24,_25,this);
-}
-if(this.reversed){
-_28=_28.slice(0).reverse();
-}
-var _29=dojo.isObject(_28)&&!dojo.isArrayLike(_28);
-var _2a=[];
-if(_29){
-for(var key in _28){
-_2a.push(_28[key]);
-}
-}else{
-_2a=_28;
-}
-var _2b=_24.forloop={parentloop:_24.get("forloop",{})};
-var j=0;
-for(i=0;i<_2a.length;i++){
-var _2c=_2a[i];
-_2b.counter0=j;
-_2b.counter=j+1;
-_2b.revcounter0=_2a.length-j-1;
-_2b.revcounter=_2a.length-j;
-_2b.first=!j;
-_2b.last=(j==_2a.length-1);
-if(_27.length>1&&dojo.isArrayLike(_2c)){
-if(!_26){
-_26=true;
-_24=_24.push();
-}
-var _2d={};
-for(k=0;k<_2c.length&&k<_27.length;k++){
-_2d[_27[k]]=_2c[k];
-}
-dojo.mixin(_24,_2d);
-}else{
-_24[_27[0]]=_2c;
-}
-if(j+1>this.pool.length){
-this.pool.push(this.nodelist.clone(_25));
-}
-_25=this.pool[j++].render(_24,_25,this);
-}
-delete _24.forloop;
-if(_26){
-_24=_24.pop();
-}else{
-for(k=0;k<_27.length;k++){
-delete _24[_27[k]];
-}
-}
-return _25;
-},unrender:function(_2e,_2f){
-for(var i=0,_30;_30=this.pool[i];i++){
-_2f=_30.unrender(_2e,_2f);
-}
-return _2f;
-},clone:function(_31){
-return new this.constructor(this.assign,this.loop.getExpression(),this.reversed,this.nodelist.clone(_31));
-}});
-dojo.mixin(_2,{if_:function(_32,_33){
-var i,_34,_35,_36=[],_37=_33.contents.split();
-_37.shift();
-_33=_37.join(" ");
-_37=_33.split(" and ");
-if(_37.length==1){
-_35="or";
-_37=_33.split(" or ");
-}else{
-_35="and";
-for(i=0;i<_37.length;i++){
-if(_37[i].indexOf(" or ")!=-1){
-throw new Error("'if' tags can't mix 'and' and 'or'");
-}
-}
-}
-for(i=0;_34=_37[i];i++){
-var not=false;
-if(_34.indexOf("not ")==0){
-_34=_34.slice(4);
-not=true;
-}
-_36.push([not,new dd._Filter(_34)]);
-}
-var _38=_32.parse(["else","endif"]);
-var _39=false;
-var _33=_32.next_token();
-if(_33.contents=="else"){
-_39=_32.parse(["endif"]);
-_32.next_token();
-}
-return new _2.IfNode(_36,_38,_39,_35);
-},_ifequal:function(_3a,_3b,_3c){
-var _3d=_3b.split_contents();
-if(_3d.length!=3){
-throw new Error(_3d[0]+" takes two arguments");
-}
-var end="end"+_3d[0];
-var _3e=_3a.parse(["else",end]);
-var _3f=false;
-var _3b=_3a.next_token();
-if(_3b.contents=="else"){
-_3f=_3a.parse([end]);
-_3a.next_token();
-}
-return new _2.IfEqualNode(_3d[1],_3d[2],_3e,_3f,_3c);
-},ifequal:function(_40,_41){
-return _2._ifequal(_40,_41);
-},ifnotequal:function(_42,_43){
-return _2._ifequal(_42,_43,true);
-},for_:function(_44,_45){
-var _46=_45.contents.split();
-if(_46.length<4){
-throw new Error("'for' statements should have at least four words: "+_45.contents);
-}
-var _47=_46[_46.length-1]=="reversed";
-var _48=(_47)?-3:-2;
-if(_46[_46.length+_48]!="in"){
-throw new Error("'for' tag received an invalid argument: "+_45.contents);
-}
-var _49=_46.slice(1,_48).join(" ").split(/ *, */);
-for(var i=0;i<_49.length;i++){
-if(!_49[i]||_49[i].indexOf(" ")!=-1){
-throw new Error("'for' tag received an invalid argument: "+_45.contents);
-}
-}
-var _4a=_44.parse(["endfor"]);
-_44.next_token();
-return new _2.ForNode(_49,_46[_46.length+_48+1],_47,_4a);
-}});
+	var dd = dojox.dtl;
+	var ddt = dd.text;
+	var ddtl = dd.tag.logic;
+
+	ddtl.IfNode = dojo.extend(function(bools, trues, falses, type){
+		this.bools = bools;
+		this.trues = trues;
+		this.falses = falses;
+		this.type = type;
+	},
+	{
+		render: function(context, buffer){
+			var i, bool, ifnot, filter, value;
+			if(this.type == "or"){
+				for(i = 0; bool = this.bools[i]; i++){
+					ifnot = bool[0];
+					filter = bool[1];
+					value = filter.resolve(context);
+					if((value && !ifnot) || (ifnot && !value)){
+						if(this.falses){
+							buffer = this.falses.unrender(context, buffer);
+						}
+						return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+					}
+				}
+				if(this.trues){
+					buffer = this.trues.unrender(context, buffer);
+				}
+				return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+			}else{
+				for(i = 0; bool = this.bools[i]; i++){
+					ifnot = bool[0];
+					filter = bool[1];
+					value = filter.resolve(context);
+					// If we ever encounter a false value
+					if(value == ifnot){
+						if(this.trues){
+							buffer = this.trues.unrender(context, buffer);
+						}
+						return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+					}
+				}
+				if(this.falses){
+					buffer = this.falses.unrender(context, buffer);
+				}
+				return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+			}
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			buffer = (this.trues) ? this.trues.unrender(context, buffer) : buffer;
+			buffer = (this.falses) ? this.falses.unrender(context, buffer) : buffer;
+			return buffer;
+		},
+		clone: function(buffer){
+			var trues = (this.trues) ? this.trues.clone(buffer) : null;
+			var falses = (this.falses) ? this.falses.clone(buffer) : null;
+			return new this.constructor(this.bools, trues, falses, this.type);
+		}
+	});
+
+	ddtl.IfEqualNode = dojo.extend(function(var1, var2, trues, falses, negate){
+		this.var1 = new dd._Filter(var1);
+		this.var2 = new dd._Filter(var2);
+		this.trues = trues;
+		this.falses = falses;
+		this.negate = negate;
+	},
+	{
+		render: function(context, buffer){
+			var var1 = this.var1.resolve(context);
+			var var2 = this.var2.resolve(context);
+			var1 = (typeof var1 != "undefined") ? var1 : "";
+			var2 = (typeof var1 != "undefined") ? var2 : "";
+			if((this.negate && var1 != var2) || (!this.negate && var1 == var2)){
+				if(this.falses){
+					buffer = this.falses.unrender(context, buffer, this);
+				}
+				return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+			}
+			if(this.trues){
+				buffer = this.trues.unrender(context, buffer, this);
+			}
+			return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+		},
+		unrender: function(context, buffer){
+			return ddtl.IfNode.prototype.unrender.call(this, context, buffer);
+		},
+		clone: function(buffer){
+			var trues = this.trues ? this.trues.clone(buffer) : null;
+			var falses = this.falses ? this.falses.clone(buffer) : null;
+			return new this.constructor(this.var1.getExpression(), this.var2.getExpression(), trues, falses, this.negate);
+		}
+	});
+
+	ddtl.ForNode = dojo.extend(function(assign, loop, reversed, nodelist){
+		this.assign = assign;
+		this.loop = new dd._Filter(loop);
+		this.reversed = reversed;
+		this.nodelist = nodelist;
+		this.pool = [];
+	},
+	{
+		render: function(context, buffer){
+			var i, j, k;
+			var dirty = false;
+			var assign = this.assign;
+
+			for(k = 0; k < assign.length; k++){
+				if(typeof context[assign[k]] != "undefined"){
+					dirty = true;
+					context = context.push();
+					break;
+				}
+			}
+			if(!dirty && context.forloop){
+				dirty = true;
+				context = context.push();
+			}
+
+			var items = this.loop.resolve(context) || [];
+			for(i = items.length; i < this.pool.length; i++){
+				this.pool[i].unrender(context, buffer, this);
+			}
+			if(this.reversed){
+				items = items.slice(0).reverse();
+			}
+
+			var isObject = dojo.isObject(items) && !dojo.isArrayLike(items);
+			var arred = [];
+			if(isObject){
+				for(var key in items){
+					arred.push(items[key]);
+				}
+			}else{
+				arred = items;
+			}
+
+			var forloop = context.forloop = {
+				parentloop: context.get("forloop", {})
+			};
+			var j = 0;
+			for(i = 0; i < arred.length; i++){
+				var item = arred[i];
+
+				forloop.counter0 = j;
+				forloop.counter = j + 1;
+				forloop.revcounter0 = arred.length - j - 1;
+				forloop.revcounter = arred.length - j;
+				forloop.first = !j;
+				forloop.last = (j == arred.length - 1);
+
+				if(assign.length > 1 && dojo.isArrayLike(item)){
+					if(!dirty){
+						dirty = true;
+						context = context.push();
+					}
+					var zipped = {};
+					for(k = 0; k < item.length && k < assign.length; k++){
+						zipped[assign[k]] = item[k];
+					}
+					dojo.mixin(context, zipped);
+				}else{
+					context[assign[0]] = item;
+				}
+
+				if(j + 1 > this.pool.length){
+					this.pool.push(this.nodelist.clone(buffer));
+				}
+				buffer = this.pool[j++].render(context, buffer, this);
+			}
+
+			delete context.forloop;
+			if(dirty){
+				context = context.pop();
+			}else{
+				for(k = 0; k < assign.length; k++){
+					delete context[assign[k]];
+				}
+			}
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			for(var i = 0, pool; pool = this.pool[i]; i++){
+				buffer = pool.unrender(context, buffer);
+			}
+			return buffer;
+		},
+		clone: function(buffer){
+			return new this.constructor(this.assign, this.loop.getExpression(), this.reversed, this.nodelist.clone(buffer));
+		}
+	});
+
+	dojo.mixin(ddtl, {
+		if_: function(parser, token){
+			var i, part, type, bools = [], parts = token.contents.split();
+			parts.shift();
+			token = parts.join(" ");
+			parts = token.split(" and ");
+			if(parts.length == 1){
+				type = "or";
+				parts = token.split(" or ");
+			}else{
+				type = "and";
+				for(i = 0; i < parts.length; i++){
+					if(parts[i].indexOf(" or ") != -1){
+						// Note, since we split by and, this is the only place we need to error check
+						throw new Error("'if' tags can't mix 'and' and 'or'");
+					}
+				}
+			}
+			for(i = 0; part = parts[i]; i++){
+				var not = false;
+				if(part.indexOf("not ") == 0){
+					part = part.slice(4);
+					not = true;
+				}
+				bools.push([not, new dd._Filter(part)]);
+			}
+			var trues = parser.parse(["else", "endif"]);
+			var falses = false;
+			var token = parser.next_token();
+			if(token.contents == "else"){
+				falses = parser.parse(["endif"]);
+				parser.next_token();
+			}
+			return new ddtl.IfNode(bools, trues, falses, type);
+		},
+		_ifequal: function(parser, token, negate){
+			var parts = token.split_contents();
+			if(parts.length != 3){
+				throw new Error(parts[0] + " takes two arguments");
+			}
+			var end = 'end' + parts[0];
+			var trues = parser.parse(["else", end]);
+			var falses = false;
+			var token = parser.next_token();
+			if(token.contents == "else"){
+				falses = parser.parse([end]);
+				parser.next_token();
+			}
+			return new ddtl.IfEqualNode(parts[1], parts[2], trues, falses, negate);
+		},
+		ifequal: function(parser, token){
+			return ddtl._ifequal(parser, token);
+		},
+		ifnotequal: function(parser, token){
+			return ddtl._ifequal(parser, token, true);
+		},
+		for_: function(parser, token){
+			var parts = token.contents.split();
+			if(parts.length < 4){
+				throw new Error("'for' statements should have at least four words: " + token.contents);
+			}
+			var reversed = parts[parts.length - 1] == "reversed";
+			var index = (reversed) ? -3 : -2;
+			if(parts[parts.length + index] != "in"){
+				throw new Error("'for' tag received an invalid argument: " + token.contents);
+			}
+			var loopvars = parts.slice(1, index).join(" ").split(/ *, */);
+			for(var i = 0; i < loopvars.length; i++){
+				if(!loopvars[i] || loopvars[i].indexOf(" ") != -1){
+					throw new Error("'for' tag received an invalid argument: " + token.contents);
+				}
+			}
+			var nodelist = parser.parse(["endfor"]);
+			parser.next_token();
+			return new ddtl.ForNode(loopvars, parts[parts.length + index + 1], reversed, nodelist);
+		}
+	});
 })();
-}
diff --git a/dojox/dtl/tag/loop.js b/dojox/dtl/tag/loop.js
index 15b81e1..da44132 100644
--- a/dojox/dtl/tag/loop.js
+++ b/dojox/dtl/tag/loop.js
@@ -1,164 +1,194 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.tag.loop"]){
-dojo._hasResource["dojox.dtl.tag.loop"]=true;
 dojo.provide("dojox.dtl.tag.loop");
+
 dojo.require("dojox.dtl._base");
 dojo.require("dojox.string.tokenize");
+
 (function(){
-var dd=dojox.dtl;
-var _1=dd.tag.loop;
-_1.CycleNode=dojo.extend(function(_2,_3,_4,_5){
-this.cyclevars=_2;
-this.name=_3;
-this.contents=_4;
-this.shared=_5||{counter:-1,map:{}};
-},{render:function(_6,_7){
-if(_6.forloop&&!_6.forloop.counter0){
-this.shared.counter=-1;
-}
-++this.shared.counter;
-var _8=this.cyclevars[this.shared.counter%this.cyclevars.length];
-var _9=this.shared.map;
-if(!_9[_8]){
-_9[_8]=new dd._Filter(_8);
-}
-_8=_9[_8].resolve(_6,_7);
-if(this.name){
-_6[this.name]=_8;
-}
-this.contents.set(_8);
-return this.contents.render(_6,_7);
-},unrender:function(_a,_b){
-return this.contents.unrender(_a,_b);
-},clone:function(_c){
-return new this.constructor(this.cyclevars,this.name,this.contents.clone(_c),this.shared);
-}});
-_1.IfChangedNode=dojo.extend(function(_d,_e,_f){
-this.nodes=_d;
-this._vars=_e;
-this.shared=_f||{last:null,counter:0};
-this.vars=dojo.map(_e,function(_10){
-return new dojox.dtl._Filter(_10);
-});
-},{render:function(_11,_12){
-if(_11.forloop){
-if(_11.forloop.counter<=this.shared.counter){
-this.shared.last=null;
-}
-this.shared.counter=_11.forloop.counter;
-}
-var _13;
-if(this.vars.length){
-_13=dojo.toJson(dojo.map(this.vars,function(_14){
-return _14.resolve(_11);
-}));
-}else{
-_13=this.nodes.dummyRender(_11,_12);
-}
-if(_13!=this.shared.last){
-var _15=(this.shared.last===null);
-this.shared.last=_13;
-_11=_11.push();
-_11.ifchanged={firstloop:_15};
-_12=this.nodes.render(_11,_12);
-_11=_11.pop();
-}else{
-_12=this.nodes.unrender(_11,_12);
-}
-return _12;
-},unrender:function(_16,_17){
-return this.nodes.unrender(_16,_17);
-},clone:function(_18){
-return new this.constructor(this.nodes.clone(_18),this._vars,this.shared);
-}});
-_1.RegroupNode=dojo.extend(function(_19,key,_1a){
-this._expression=_19;
-this.expression=new dd._Filter(_19);
-this.key=key;
-this.alias=_1a;
-},{_push:function(_1b,_1c,_1d){
-if(_1d.length){
-_1b.push({grouper:_1c,list:_1d});
-}
-},render:function(_1e,_1f){
-_1e[this.alias]=[];
-var _20=this.expression.resolve(_1e);
-if(_20){
-var _21=null;
-var _22=[];
-for(var i=0;i<_20.length;i++){
-var id=_20[i][this.key];
-if(_21!==id){
-this._push(_1e[this.alias],_21,_22);
-_21=id;
-_22=[_20[i]];
-}else{
-_22.push(_20[i]);
-}
-}
-this._push(_1e[this.alias],_21,_22);
-}
-return _1f;
-},unrender:function(_23,_24){
-return _24;
-},clone:function(_25,_26){
-return this;
-}});
-dojo.mixin(_1,{cycle:function(_27,_28){
-var _29=_28.split_contents();
-if(_29.length<2){
-throw new Error("'cycle' tag requires at least two arguments");
-}
-if(_29[1].indexOf(",")!=-1){
-var _2a=_29[1].split(",");
-_29=[_29[0]];
-for(var i=0;i<_2a.length;i++){
-_29.push("\""+_2a[i]+"\"");
-}
-}
-if(_29.length==2){
-var _2b=_29[_29.length-1];
-if(!_27._namedCycleNodes){
-throw new Error("No named cycles in template: '"+_2b+"' is not defined");
-}
-if(!_27._namedCycleNodes[_2b]){
-throw new Error("Named cycle '"+_2b+"' does not exist");
-}
-return _27._namedCycleNodes[_2b];
-}
-if(_29.length>4&&_29[_29.length-2]=="as"){
-var _2b=_29[_29.length-1];
-var _2c=new _1.CycleNode(_29.slice(1,_29.length-2),_2b,_27.create_text_node());
-if(!_27._namedCycleNodes){
-_27._namedCycleNodes={};
-}
-_27._namedCycleNodes[_2b]=_2c;
-}else{
-_2c=new _1.CycleNode(_29.slice(1),null,_27.create_text_node());
-}
-return _2c;
-},ifchanged:function(_2d,_2e){
-var _2f=_2e.contents.split();
-var _30=_2d.parse(["endifchanged"]);
-_2d.delete_first_token();
-return new _1.IfChangedNode(_30,_2f.slice(1));
-},regroup:function(_31,_32){
-var _33=dojox.string.tokenize(_32.contents,/(\s+)/g,function(_34){
-return _34;
-});
-if(_33.length<11||_33[_33.length-3]!="as"||_33[_33.length-7]!="by"){
-throw new Error("Expected the format: regroup list by key as newList");
-}
-var _35=_33.slice(2,-8).join("");
-var key=_33[_33.length-5];
-var _36=_33[_33.length-1];
-return new _1.RegroupNode(_35,key,_36);
-}});
+	var dd = dojox.dtl;
+	var ddtl = dd.tag.loop;
+
+	ddtl.CycleNode = dojo.extend(function(cyclevars, name, text, shared){
+		this.cyclevars = cyclevars;
+		this.name = name;
+		this.contents = text;
+		this.shared = shared || {counter: -1, map: {}};
+	},
+	{
+		render: function(context, buffer){
+			if(context.forloop && !context.forloop.counter0){
+				this.shared.counter = -1;
+			}
+
+			++this.shared.counter;
+			var value = this.cyclevars[this.shared.counter % this.cyclevars.length];
+
+			var map = this.shared.map;
+			if(!map[value]){
+				map[value] = new dd._Filter(value);
+			}
+			value = map[value].resolve(context, buffer);
+
+			if(this.name){
+				context[this.name] = value;
+			}
+			this.contents.set(value);
+			return this.contents.render(context, buffer);
+		},
+		unrender: function(context, buffer){
+			return this.contents.unrender(context, buffer);
+		},
+		clone: function(buffer){
+			return new this.constructor(this.cyclevars, this.name, this.contents.clone(buffer), this.shared);
+		}
+	});
+
+	ddtl.IfChangedNode = dojo.extend(function(nodes, vars, shared){
+		this.nodes = nodes;
+		this._vars = vars;
+		this.shared = shared || {last: null, counter: 0};
+		this.vars = dojo.map(vars, function(item){
+			return new dojox.dtl._Filter(item);
+		});
+	}, {
+		render: function(context, buffer){
+			if(context.forloop){
+				if(context.forloop.counter <= this.shared.counter){
+					this.shared.last = null;
+				}
+				this.shared.counter = context.forloop.counter;
+			}
+
+			var change;
+			if(this.vars.length){
+				change = dojo.toJson(dojo.map(this.vars, function(item){
+					return item.resolve(context);
+				}));
+			}else{
+				change = this.nodes.dummyRender(context, buffer);
+			}
+
+			if(change != this.shared.last){
+				var firstloop = (this.shared.last === null);
+				this.shared.last = change;
+				context = context.push();
+				context.ifchanged = {firstloop: firstloop};
+				buffer = this.nodes.render(context, buffer);
+				context = context.pop();
+			}else{
+				buffer = this.nodes.unrender(context, buffer);
+			}
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			return this.nodes.unrender(context, buffer);
+		},
+		clone: function(buffer){
+			return new this.constructor(this.nodes.clone(buffer), this._vars, this.shared);
+		}
+	});
+
+	ddtl.RegroupNode = dojo.extend(function(expression, key, alias){
+		this._expression = expression;
+		this.expression = new dd._Filter(expression);
+		this.key = key;
+		this.alias = alias;
+	},
+	{
+		_push: function(container, grouper, stack){
+			if(stack.length){
+				container.push({ grouper: grouper, list: stack });
+			}
+		},
+		render: function(context, buffer){
+			context[this.alias] = [];
+			var list = this.expression.resolve(context);
+			if(list){
+				var last = null;
+				var stack = [];
+				for(var i = 0; i < list.length; i++){
+					var id = list[i][this.key];
+					if(last !== id){
+						this._push(context[this.alias], last, stack);
+						last = id;
+						stack = [list[i]];
+					}else{
+						stack.push(list[i]);
+					}
+				}
+				this._push(context[this.alias], last, stack);
+			}
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			return buffer;
+		},
+		clone: function(context, buffer){
+			return this;
+		}
+	});
+
+	dojo.mixin(ddtl, {
+		cycle: function(parser, token){
+			// summary: Cycle among the given strings each time this tag is encountered
+			var args = token.split_contents();
+
+			if(args.length < 2){
+				throw new Error("'cycle' tag requires at least two arguments");
+			}
+
+			if(args[1].indexOf(",") != -1){
+				var vars = args[1].split(",");
+				args = [args[0]];
+				for(var i = 0; i < vars.length; i++){
+					args.push('"' + vars[i] + '"');
+				}
+			}
+
+			if(args.length == 2){
+				var name = args[args.length - 1];
+
+				if(!parser._namedCycleNodes){
+					throw new Error("No named cycles in template: '" + name + "' is not defined");
+				}
+				if(!parser._namedCycleNodes[name]){
+					throw new Error("Named cycle '" + name + "' does not exist");
+				}
+
+		        return parser._namedCycleNodes[name];
+			}
+
+			if(args.length > 4 && args[args.length - 2] == "as"){
+				var name = args[args.length - 1];
+
+				var node = new ddtl.CycleNode(args.slice(1, args.length - 2), name, parser.create_text_node());
+
+				if(!parser._namedCycleNodes){
+					parser._namedCycleNodes = {};
+				}
+				parser._namedCycleNodes[name] = node;
+			}else{
+				node = new ddtl.CycleNode(args.slice(1), null, parser.create_text_node());
+			}
+
+			return node;
+		},
+		ifchanged: function(parser, token){
+			var parts = token.contents.split();
+			var nodes = parser.parse(["endifchanged"]);
+			parser.delete_first_token();
+			return new ddtl.IfChangedNode(nodes, parts.slice(1));
+		},
+		regroup: function(parser, token){
+			var tokens = dojox.string.tokenize(token.contents, /(\s+)/g, function(spaces){
+				return spaces;
+			});
+			if(tokens.length < 11 || tokens[tokens.length - 3] != "as" || tokens[tokens.length - 7] != "by"){
+				throw new Error("Expected the format: regroup list by key as newList");
+			}
+			var expression = tokens.slice(2, -8).join("");
+			var key = tokens[tokens.length - 5];
+			var alias = tokens[tokens.length - 1];
+			return new ddtl.RegroupNode(expression, key, alias);
+		}
+	});
 })();
-}
diff --git a/dojox/dtl/tag/misc.js b/dojox/dtl/tag/misc.js
index d094947..ea8dd5e 100644
--- a/dojox/dtl/tag/misc.js
+++ b/dojox/dtl/tag/misc.js
@@ -1,222 +1,286 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.tag.misc"]){
-dojo._hasResource["dojox.dtl.tag.misc"]=true;
 dojo.provide("dojox.dtl.tag.misc");
 dojo.require("dojox.dtl._base");
+
 (function(){
-var dd=dojox.dtl;
-var _1=dd.tag.misc;
-_1.DebugNode=dojo.extend(function(_2){
-this.text=_2;
-},{render:function(_3,_4){
-var _5=_3.getKeys();
-var _6=[];
-var _7={};
-for(var i=0,_8;_8=_5[i];i++){
-_7[_8]=_3[_8];
-_6+="["+_8+": "+typeof _3[_8]+"]\n";
-}
-return this.text.set(_6).render(_3,_4,this);
-},unrender:function(_9,_a){
-return _a;
-},clone:function(_b){
-return new this.constructor(this.text.clone(_b));
-},toString:function(){
-return "ddtm.DebugNode";
-}});
-_1.FilterNode=dojo.extend(function(_c,_d){
-this._varnode=_c;
-this._nodelist=_d;
-},{render:function(_e,_f){
-var _10=this._nodelist.render(_e,new dojox.string.Builder());
-_e=_e.update({"var":_10.toString()});
-var _11=this._varnode.render(_e,_f);
-_e=_e.pop();
-return _f;
-},unrender:function(_12,_13){
-return _13;
-},clone:function(_14){
-return new this.constructor(this._expression,this._nodelist.clone(_14));
-}});
-_1.FirstOfNode=dojo.extend(function(_15,_16){
-this._vars=_15;
-this.vars=dojo.map(_15,function(_17){
-return new dojox.dtl._Filter(_17);
-});
-this.contents=_16;
-},{render:function(_18,_19){
-for(var i=0,_1a;_1a=this.vars[i];i++){
-var _1b=_1a.resolve(_18);
-if(typeof _1b!="undefined"){
-if(_1b===null){
-_1b="null";
-}
-this.contents.set(_1b);
-return this.contents.render(_18,_19);
-}
-}
-return this.contents.unrender(_18,_19);
-},unrender:function(_1c,_1d){
-return this.contents.unrender(_1c,_1d);
-},clone:function(_1e){
-return new this.constructor(this._vars,this.contents.clone(_1e));
-}});
-_1.SpacelessNode=dojo.extend(function(_1f,_20){
-this.nodelist=_1f;
-this.contents=_20;
-},{render:function(_21,_22){
-if(_22.getParent){
-var _23=[dojo.connect(_22,"onAddNodeComplete",this,"_watch"),dojo.connect(_22,"onSetParent",this,"_watchParent")];
-_22=this.nodelist.render(_21,_22);
-dojo.disconnect(_23[0]);
-dojo.disconnect(_23[1]);
-}else{
-var _24=this.nodelist.dummyRender(_21);
-this.contents.set(_24.replace(/>\s+</g,"><"));
-_22=this.contents.render(_21,_22);
-}
-return _22;
-},unrender:function(_25,_26){
-return this.nodelist.unrender(_25,_26);
-},clone:function(_27){
-return new this.constructor(this.nodelist.clone(_27),this.contents.clone(_27));
-},_isEmpty:function(_28){
-return (_28.nodeType==3&&!_28.data.match(/[^\s\n]/));
-},_watch:function(_29){
-if(this._isEmpty(_29)){
-var _2a=false;
-if(_29.parentNode.firstChild==_29){
-_29.parentNode.removeChild(_29);
-}
-}else{
-var _2b=_29.parentNode.childNodes;
-if(_29.nodeType==1&&_2b.length>2){
-for(var i=2,_2c;_2c=_2b[i];i++){
-if(_2b[i-2].nodeType==1&&this._isEmpty(_2b[i-1])){
-_29.parentNode.removeChild(_2b[i-1]);
-return;
-}
-}
-}
-}
-},_watchParent:function(_2d){
-var _2e=_2d.childNodes;
-if(_2e.length){
-while(_2d.childNodes.length){
-var _2f=_2d.childNodes[_2d.childNodes.length-1];
-if(!this._isEmpty(_2f)){
-return;
-}
-_2d.removeChild(_2f);
-}
-}
-}});
-_1.TemplateTagNode=dojo.extend(function(tag,_30){
-this.tag=tag;
-this.contents=_30;
-},{mapping:{openblock:"{%",closeblock:"%}",openvariable:"{{",closevariable:"}}",openbrace:"{",closebrace:"}",opencomment:"{#",closecomment:"#}"},render:function(_31,_32){
-this.contents.set(this.mapping[this.tag]);
-return this.contents.render(_31,_32);
-},unrender:function(_33,_34){
-return this.contents.unrender(_33,_34);
-},clone:function(_35){
-return new this.constructor(this.tag,this.contents.clone(_35));
-}});
-_1.WidthRatioNode=dojo.extend(function(_36,max,_37,_38){
-this.current=new dd._Filter(_36);
-this.max=new dd._Filter(max);
-this.width=_37;
-this.contents=_38;
-},{render:function(_39,_3a){
-var _3b=+this.current.resolve(_39);
-var max=+this.max.resolve(_39);
-if(typeof _3b!="number"||typeof max!="number"||!max){
-this.contents.set("");
-}else{
-this.contents.set(""+Math.round((_3b/max)*this.width));
-}
-return this.contents.render(_39,_3a);
-},unrender:function(_3c,_3d){
-return this.contents.unrender(_3c,_3d);
-},clone:function(_3e){
-return new this.constructor(this.current.getExpression(),this.max.getExpression(),this.width,this.contents.clone(_3e));
-}});
-_1.WithNode=dojo.extend(function(_3f,_40,_41){
-this.target=new dd._Filter(_3f);
-this.alias=_40;
-this.nodelist=_41;
-},{render:function(_42,_43){
-var _44=this.target.resolve(_42);
-_42=_42.push();
-_42[this.alias]=_44;
-_43=this.nodelist.render(_42,_43);
-_42=_42.pop();
-return _43;
-},unrender:function(_45,_46){
-return _46;
-},clone:function(_47){
-return new this.constructor(this.target.getExpression(),this.alias,this.nodelist.clone(_47));
-}});
-dojo.mixin(_1,{comment:function(_48,_49){
-_48.skip_past("endcomment");
-return dd._noOpNode;
-},debug:function(_4a,_4b){
-return new _1.DebugNode(_4a.create_text_node());
-},filter:function(_4c,_4d){
-var _4e=_4d.contents.split(null,1)[1];
-var _4f=_4c.create_variable_node("var|"+_4e);
-var _50=_4c.parse(["endfilter"]);
-_4c.next_token();
-return new _1.FilterNode(_4f,_50);
-},firstof:function(_51,_52){
-var _53=_52.split_contents().slice(1);
-if(!_53.length){
-throw new Error("'firstof' statement requires at least one argument");
-}
-return new _1.FirstOfNode(_53,_51.create_text_node());
-},spaceless:function(_54,_55){
-var _56=_54.parse(["endspaceless"]);
-_54.delete_first_token();
-return new _1.SpacelessNode(_56,_54.create_text_node());
-},templatetag:function(_57,_58){
-var _59=_58.contents.split();
-if(_59.length!=2){
-throw new Error("'templatetag' statement takes one argument");
-}
-var tag=_59[1];
-var _5a=_1.TemplateTagNode.prototype.mapping;
-if(!_5a[tag]){
-var _5b=[];
-for(var key in _5a){
-_5b.push(key);
-}
-throw new Error("Invalid templatetag argument: '"+tag+"'. Must be one of: "+_5b.join(", "));
-}
-return new _1.TemplateTagNode(tag,_57.create_text_node());
-},widthratio:function(_5c,_5d){
-var _5e=_5d.contents.split();
-if(_5e.length!=4){
-throw new Error("widthratio takes three arguments");
-}
-var _5f=+_5e[3];
-if(typeof _5f!="number"){
-throw new Error("widthratio final argument must be an integer");
-}
-return new _1.WidthRatioNode(_5e[1],_5e[2],_5f,_5c.create_text_node());
-},with_:function(_60,_61){
-var _62=_61.split_contents();
-if(_62.length!=4||_62[2]!="as"){
-throw new Error("do_width expected format as 'with value as name'");
-}
-var _63=_60.parse(["endwith"]);
-_60.next_token();
-return new _1.WithNode(_62[1],_62[3],_63);
-}});
-})();
-}
+	var dd = dojox.dtl;
+	var ddtm = dd.tag.misc;
+
+	ddtm.DebugNode = dojo.extend(function(text){
+		this.text = text;
+	},
+	{
+		render: function(context, buffer){
+			var keys = context.getKeys();
+			var debug = [];
+			var only = {};
+			for(var i = 0, key; key = keys[i]; i++){
+				only[key] = context[key];
+				debug += "[" + key + ": " + typeof context[key] + "]\n";
+			}
+			console.debug(only);
+			return this.text.set(debug).render(context, buffer, this);
+		},
+		unrender: function(context, buffer){
+			return buffer;
+		},
+		clone: function(buffer){
+			return new this.constructor(this.text.clone(buffer));
+		},
+		toString: function(){ return "ddtm.DebugNode"; }
+	});
+
+	ddtm.FilterNode = dojo.extend(function(varnode, nodelist){
+		this._varnode = varnode;
+		this._nodelist = nodelist;
+	},
+	{
+		render: function(context, buffer){
+			// Doing this in HTML requires a different buffer with a fake root node
+			var output = this._nodelist.render(context, new dojox.string.Builder());
+			context = context.update({ "var": output.toString() });
+			var filtered = this._varnode.render(context, buffer);
+			context = context.pop();
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			return buffer;
+		},
+		clone: function(buffer){
+			return new this.constructor(this._expression, this._nodelist.clone(buffer));
+		}
+	});
+
+	ddtm.FirstOfNode = dojo.extend(function(vars, text){
+		this._vars = vars;
+		this.vars = dojo.map(vars, function(item){
+			return new dojox.dtl._Filter(item);
+		});
+		this.contents = text;
+	},
+	{
+		render: function(context, buffer){
+			for(var i = 0, item; item = this.vars[i]; i++){
+				var resolved = item.resolve(context);
+				if(typeof resolved != "undefined"){
+					if(resolved === null){
+						resolved = "null";
+					}
+					this.contents.set(resolved);
+					return this.contents.render(context, buffer);
+				}
+			}
+			return this.contents.unrender(context, buffer);
+		},
+		unrender: function(context, buffer){
+			return this.contents.unrender(context, buffer);
+		},
+		clone: function(buffer){
+			return new this.constructor(this._vars, this.contents.clone(buffer));
+		}
+	});
+
+	ddtm.SpacelessNode = dojo.extend(function(nodelist, text){
+		this.nodelist = nodelist;
+		this.contents = text;
+	},
+	{
+		render: function(context, buffer){
+			if(buffer.getParent){
+				// Unfortunately, we have to branch here
+				var watch = [
+					dojo.connect(buffer, "onAddNodeComplete", this, "_watch"),
+					dojo.connect(buffer, "onSetParent", this, "_watchParent")
+				];
+				buffer = this.nodelist.render(context, buffer);
+				dojo.disconnect(watch[0]);
+				dojo.disconnect(watch[1]);
+			}else{
+				var value = this.nodelist.dummyRender(context);
+				this.contents.set(value.replace(/>\s+</g, '><'));
+				buffer = this.contents.render(context, buffer);
+			}
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			return this.nodelist.unrender(context, buffer);
+		},
+		clone: function(buffer){
+			return new this.constructor(this.nodelist.clone(buffer), this.contents.clone(buffer));
+		},
+		_isEmpty: function(node){
+			return (node.nodeType == 3 && !node.data.match(/[^\s\n]/));
+		},
+		_watch: function(node){
+			if(this._isEmpty(node)){
+				var remove = false;
+				if(node.parentNode.firstChild == node){
+					node.parentNode.removeChild(node);
+				}
+			}else{
+				var children = node.parentNode.childNodes;
+				if(node.nodeType == 1 && children.length > 2){
+					for(var i = 2, child; child = children[i]; i++){
+						if(children[i - 2].nodeType == 1 && this._isEmpty(children[i - 1])){
+							node.parentNode.removeChild(children[i - 1]);
+							return;
+						}
+					}
+				}
+			}
+		},
+		_watchParent: function(node){
+			var children = node.childNodes;
+			if(children.length){
+				while(node.childNodes.length){
+					var last = node.childNodes[node.childNodes.length - 1];
+					if(!this._isEmpty(last)){
+						return;
+					}
+					node.removeChild(last);
+				}
+			}
+		}
+	});
+
+	ddtm.TemplateTagNode = dojo.extend(function(tag, text){
+		this.tag = tag;
+		this.contents = text;
+	},
+	{
+		mapping: {
+			openblock: "{%",
+			closeblock: "%}",
+			openvariable: "{{",
+			closevariable: "}}",
+			openbrace: "{",
+			closebrace: "}",
+			opencomment: "{#",
+			closecomment: "#}"
+		},
+		render: function(context, buffer){
+			this.contents.set(this.mapping[this.tag]);
+			return this.contents.render(context, buffer);
+		},
+		unrender: function(context, buffer){
+			return this.contents.unrender(context, buffer);
+		},
+		clone: function(buffer){
+			return new this.constructor(this.tag, this.contents.clone(buffer));
+		}
+	});
+
+	ddtm.WidthRatioNode = dojo.extend(function(current, max, width, text){
+		this.current = new dd._Filter(current);
+		this.max = new dd._Filter(max);
+		this.width = width;
+		this.contents = text;
+	},
+	{
+		render: function(context, buffer){
+			var current = +this.current.resolve(context);
+			var max = +this.max.resolve(context);
+			if(typeof current != "number" || typeof max != "number" || !max){
+				this.contents.set("");
+			}else{
+				this.contents.set("" + Math.round((current / max) * this.width));
+			}
+			return this.contents.render(context, buffer);
+		},
+		unrender: function(context, buffer){
+			return this.contents.unrender(context, buffer);
+		},
+		clone: function(buffer){
+			return new this.constructor(this.current.getExpression(), this.max.getExpression(), this.width, this.contents.clone(buffer));
+		}
+	});
+
+	ddtm.WithNode = dojo.extend(function(target, alias, nodelist){
+		this.target = new dd._Filter(target);
+		this.alias = alias;
+		this.nodelist = nodelist;
+	},
+	{
+		render: function(context, buffer){
+			var target = this.target.resolve(context);
+			context = context.push();
+			context[this.alias] = target;
+			buffer = this.nodelist.render(context, buffer);
+			context = context.pop();
+			return buffer;
+		},
+		unrender: function(context, buffer){
+			return buffer;
+		},
+		clone: function(buffer){
+			return new this.constructor(this.target.getExpression(), this.alias, this.nodelist.clone(buffer));
+		}
+	});
+
+	dojo.mixin(ddtm, {
+		comment: function(parser, token){
+			// summary: Ignore everything between {% comment %} and {% endcomment %}
+			parser.skip_past("endcomment");
+			return dd._noOpNode;
+		},
+		debug: function(parser, token){
+			// summary: Output the current context, maybe add more stuff later.
+			return new ddtm.DebugNode(parser.create_text_node());
+		},
+		filter: function(parser, token){
+			// summary: Filter the contents of the blog through variable filters.
+			var rest = token.contents.split(null, 1)[1];
+			var varnode = parser.create_variable_node("var|" + rest);
+			var nodelist = parser.parse(["endfilter"]);
+			parser.next_token();
+			return new ddtm.FilterNode(varnode, nodelist);
+		},
+		firstof: function(parser, token){
+			var parts = token.split_contents().slice(1);
+			if(!parts.length){
+				throw new Error("'firstof' statement requires at least one argument");
+			}
+			return new ddtm.FirstOfNode(parts, parser.create_text_node());
+		},
+		spaceless: function(parser, token){
+			var nodelist = parser.parse(["endspaceless"]);
+			parser.delete_first_token();
+			return new ddtm.SpacelessNode(nodelist, parser.create_text_node());
+		},
+		templatetag: function(parser, token){
+			var parts = token.contents.split();
+			if(parts.length != 2){
+				throw new Error("'templatetag' statement takes one argument");
+			}
+			var tag = parts[1];
+			var mapping = ddtm.TemplateTagNode.prototype.mapping;
+			if(!mapping[tag]){
+				var keys = [];
+				for(var key in mapping){
+					keys.push(key);
+				}
+				throw new Error("Invalid templatetag argument: '" + tag + "'. Must be one of: " + keys.join(", "));
+			}
+			return new ddtm.TemplateTagNode(tag, parser.create_text_node());
+		},
+		widthratio: function(parser, token){
+			var parts = token.contents.split();
+			if(parts.length != 4){
+				throw new Error("widthratio takes three arguments");
+			}
+			var width = +parts[3];
+			if(typeof width != "number"){
+				throw new Error("widthratio final argument must be an integer");
+			}
+			return new ddtm.WidthRatioNode(parts[1], parts[2], width, parser.create_text_node());
+		},
+		with_: function(parser, token){
+			var parts = token.split_contents();
+			if(parts.length != 4 || parts[2] != "as"){
+				throw new Error("do_width expected format as 'with value as name'");
+			}
+			var nodelist = parser.parse(["endwith"]);
+			parser.next_token();
+			return new ddtm.WithNode(parts[1], parts[3], nodelist);
+		}
+	});
+})();
\ No newline at end of file
diff --git a/dojox/dtl/tests/context.js b/dojox/dtl/tests/context.js
new file mode 100644
index 0000000..21ca0ac
--- /dev/null
+++ b/dojox/dtl/tests/context.js
@@ -0,0 +1,84 @@
+dojo.provide("dojox.dtl.tests.context");
+
+dojo.require("dojox.dtl");
+dojo.require("dojox.dtl.Context");
+
+doh.register("dojox.dtl.context", 
+	[
+		function test_context_creation(t){
+			var context = new dojox.dtl.Context({ foo: "foo", bar: "bar" });
+			t.is("foo", context.foo);
+			t.is("bar", context.bar);
+		},
+		function test_context_push(t){
+			var context = new dojox.dtl.Context({ foo: "foo", bar: "bar" });
+			context = context.push();
+			var found = false;
+			for(var key in context){
+				if(key == "foo" || key == "bar"){
+					found = true;
+				}
+			}
+			t.t(found);
+		},
+		function test_context_getter(t){
+			var context = new dojox.dtl.Context({foo: "foo", bar: "bar", get: function(key){ return key + "TEST"; }});
+			var tpl = new dojox.dtl.Template("{{ foo }}-{{ bar }}");
+			t.is("fooTEST-barTEST", tpl.render(context));
+		},
+		function test_context_pop(t){
+			var context = new dojox.dtl.Context({ foo: "foo", bar: "bar" });
+			context = context.push();
+			t.f(context.hasOwnProperty("foo"));
+			t.f(context.hasOwnProperty("bar"));
+			context = context.pop();
+			t.is("foo", context.foo);
+			t.is("bar", context.bar);
+		},
+		function test_context_overpop(t){
+			var context = new dojox.dtl.Context();
+			try{
+				context = context.pop();
+				t.t(false);
+			}catch(e){
+				t.is("pop() called on empty Context", e.message);
+			}
+		},
+		function test_context_filter(t){
+			var context = new dojox.dtl.Context({ foo: "one", bar: "two", baz: "three" });
+			var filtered = context.filter("foo", "bar");
+			t.is(filtered.foo, "one");
+			t.is(filtered.bar, "two");
+			t.f(filtered.baz);
+
+			filtered = context.filter({ bar: true, baz: true });
+			t.f(filtered.foo);
+			t.is(filtered.bar, "two");
+			t.is(filtered.baz, "three");
+
+			filtered = context.filter(new dojox.dtl.Context({ foo: true, baz: true }));
+			t.is(filtered.foo, "one");
+			t.f(filtered.bar);
+			t.is(filtered.baz, "three");
+		},
+		function test_context_extend(t){
+			var context = new dojox.dtl.Context({ foo: "one" });
+			var extended = context.extend({ bar: "two", baz: "three" });
+			t.is(extended.foo, "one");
+			t.is(extended.bar, "two");
+			t.is(extended.baz, "three");
+
+			extended = context.extend({ barr: "two", bazz: "three" });
+			t.is(extended.foo, "one");
+			t.f(extended.bar);
+			t.f(extended.baz);
+			t.is(extended.barr, "two");
+			t.is(extended.bazz, "three");
+
+			t.f(context.bar)
+			t.f(context.baz);
+			t.f(context.barr);
+			t.f(context.bazz);
+		}
+	]
+);
\ No newline at end of file
diff --git a/dojox/dtl/tests/demo_Templated_Jaxer.html b/dojox/dtl/tests/demo_Templated_Jaxer.html
new file mode 100644
index 0000000..f0f0a46
--- /dev/null
+++ b/dojox/dtl/tests/demo_Templated_Jaxer.html
@@ -0,0 +1,87 @@
+<html>
+	<head>
+			<title>Demo using dojox.dtl._Templated</title>
+		<script runat="server">
+			djConfig = {baseUrl:"/dojo/",usePlainJson: true, parseOnLoad: true};
+		</script>
+	    <script runat="server" type="text/javascript" src="../../../dojo/dojo.js"></script>
+	    <script runat="server" type="text/javascript">
+	    		dojo.require("dojo.jaxer");
+	    		dojo.require("dijit.dijit");
+				dojo.require("dojox.dtl._Templated");
+				dojo.require("dojo.parser");
+					
+					dojo.declare("Fruit", [dijit._Widget, dojox.dtl._Templated], {
+						oldRepl: "Fruit: ",
+						_dijitTemplateCompat: true,
+						items: ["apple", "banana", "orange"],
+						keyUp: function(e){
+							if(e.keyCode == dojo.keys.ENTER){
+								var i = dojo.indexOf(this.items, e.target.value);
+								if(i != -1){
+									this.items.splice(i, 1);
+								}else{
+									this.items.push(e.target.value);
+								}
+								e.target.value = "";
+								this.render();
+								dojo.query("input", this.domNode).forEach("item.focus();");
+							}
+						},
+						templateString: '<div><input dojoAttachEvent="onkeyup: keyUp"><ul>{% for item in items %}<li>${oldRepl} {{ item }}</li>{% endfor %}</ul></div>'
+					});
+	    </script>
+	</head>
+	<body>
+		<h1>Using Dojo's Django Template language on Jaxer</h1>
+		<div>
+			Aptana's Jaxer is server side JavaScript (SSJS) server. With some modifications to
+			a web page, Dojo can be run on the server. With Dojo running on the server, you can
+			utilize the Dojo's Django Template library rendering engine to do templating within
+			Jaxer. The latest build of Dojo includes some patches to properly work with Jaxer,
+			so you need a build of Dojo later than 2/18/08 to work with Jaxer. Next, the
+			following modifications to your page are needed to run Jaxer:
+			<ul>
+				<li>
+					You must explicitly set the base url of the Dojo library. Jaxer does not provide
+					the ability for Dojo to auto-detect the base url as it can in other environments.
+					Therefore you must declare the base url with the djConfig global variable:
+					<pre>
+<script runat="server">
+djConfig = {baseUrl:"/dojo/", // use the base path of dojo here
+			usePlainJson: true, parseOnLoad: true};
+</script>
+					</pre>
+				</li>
+				<li>
+					Next, you must add the runat attribute with a value of "server" to all of the script
+					tags that you want executed on the server. Your script tags should look like:
+					<pre>
+<script runat="server" type="text/javascript" src="../../../dojo/dojo.js"></script>
+					</pre>
+				</li>
+				<li>
+					Last, you must dojo.require("dojo.jaxer") with a script tag. This should immediately 
+					follow the declaration of dojo.js:
+					<pre>
+<script runat="server" type="text/javascript" src="../../../dojo/dojo.js"></script>
+<script runat="server" type="text/javascript">dojo.require("dojo.jaxer");</script>
+					</pre>
+				</li>
+			</ul>
+		</div>
+		<p>
+			Once this is done, Dojo should load in Jaxer, and you can utilize the library capabilities of
+			Dojo. In particular, you can now use DTL renderer as you would on
+			the browser. If you are running this in Jaxer, below should be a working demonstration of
+			a template that is rendered on the server.
+		</p>
+		<div dojoType="Fruit"></div>
+		<p>
+			It is important to note that Jaxer is not capable of transferring the programmaticaly set
+			event handlers for widgets, it can only send the static HTML to the browser. This means
+			you can use DTL as a templating engine to create HTML on the server, but Dojo client side widgets
+			are still necessary if you want to use interactive widgets on the browser.
+		</p>
+	</body>
+</html>
diff --git a/dojox/dtl/tests/dom/buffer.js b/dojox/dtl/tests/dom/buffer.js
new file mode 100644
index 0000000..9c2a844
--- /dev/null
+++ b/dojox/dtl/tests/dom/buffer.js
@@ -0,0 +1,31 @@
+dojo.provide("dojox.dtl.tests.dom.buffer");
+
+dojo.require("dojox.dtl.dom");
+dojo.require("dojox.dtl.Context");
+dojo.require("dojox.dtl.tests.dom.util");
+
+doh.register("dojox.dtl.dom.buffer", 
+	[
+		function test_insertion_order_text(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				first: false,
+				last: false
+			});
+
+			var template = new dd.DomTemplate("<div>{% if first %}first{% endif %}middle{% if last %}last{% endif %}</div>");
+			t.is("<div>middle</div>", dd.tests.dom.util.render(template, context));
+
+			context.first = true;
+			t.is("<div>firstmiddle</div>", dd.tests.dom.util.render(template, context));
+
+			context.first = false;
+			context.last = true;
+			t.is("<div>middlelast</div>", dd.tests.dom.util.render(template, context));
+
+			context.first = true;
+			t.is("<div>firstmiddlelast</div>", dd.tests.dom.util.render(template, context));
+		}
+	]
+);
\ No newline at end of file
diff --git a/dojox/dtl/tests/dom/tag.js b/dojox/dtl/tests/dom/tag.js
new file mode 100644
index 0000000..112dc79
--- /dev/null
+++ b/dojox/dtl/tests/dom/tag.js
@@ -0,0 +1,324 @@
+dojo.provide("dojox.dtl.tests.dom.tag");
+
+dojo.require("dojox.dtl.dom");
+dojo.require("dojox.dtl.Context");
+dojo.require("dojox.dtl.tests.dom.util");
+
+doh.register("dojox.dtl.dom.tag", 
+	[
+		function test_errors(t){
+			var dd = dojox.dtl;
+			var template;
+
+			// No root node after rendering
+			var found = false;
+			try {
+				template = new dd.DomTemplate('No div');
+				dd.tests.dom.util.render(template);
+			}catch(e){
+				t.is("Text should not exist outside of the root node in template", e.message);
+				found = true;
+			}
+			t.t(found);
+
+			var context = new dojox.dtl.Context({test: "Pocket"});
+			found = false;
+			try {
+				template = new dd.DomTemplate('{{ test }}');
+				dd.tests.dom.util.render(template, context);
+			}catch(e){
+				t.is("Text should not exist outside of the root node in template", e.message);
+				found = true;
+			}
+			t.t(found);
+
+			template = new dd.DomTemplate('<div></div>extra content');
+			found = false;
+			try {
+				dd.tests.dom.util.render(template);
+			}catch(e){
+				t.is("Content should not exist outside of the root node in template", e.message);
+				found = true;
+			}
+			t.t(found);
+
+			// More than one top-level node (except for blocks)
+			template = new dd.DomTemplate('<div></div><div></div>');
+			found = false;
+			try {
+				dd.tests.dom.util.render(template);
+			}catch(e){
+				t.is("Content should not exist outside of the root node in template", e.message);
+				found = true;
+			}
+			t.t(found);
+
+			// Logic block rules out any root node
+			template = new dd.DomTemplate('{% if missing %}<div></div>{% endif %}');
+			found = false;
+			try {
+				dd.tests.dom.util.render(template);
+			}catch(e){
+				t.is("Rendered template does not have a root node", e.message);
+				found = true;
+			}
+			t.t(found);
+		},
+		function test_tag_attributes(){
+			var dd = dojox.dtl;
+
+			var template = new dd.DomTemplate('<div>{% for item in items %}<a index="{{forloop.counter0}}" id="id_{{item.param}}">{{item.param}}</a>{% endfor %}</div>');
+			var context = new dd.Context({
+				items: [
+					{
+						name: "apple",
+						param: "appleparam"
+					},
+					{
+						name: "banana",
+						param: "bananaparam"
+					},
+					{
+						name: "orange",
+						param: "orangeparam"
+					}
+				]
+			});
+			doh.is('<div><a index="0" id="id_appleparam">appleparam</a><a index="1" id="id_bananaparam">bananaparam</a><a index="2" id="id_orangeparam">orangeparam</a></div>', dd.tests.dom.util.render(template, context));
+		},
+		function test_tag_extend(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				base: dojo.moduleUrl("dojox.dtl.tests.templates", "base.html")
+			});
+
+			var template = new dd.DomTemplate("{% extends base %}{% block base %}<p>1</p><p>2</p><ul><li>2a</li><li>2b</li><li>2c</li></ul><p>3</p><ul><li>3a</li><li>3b</li><li>3c</li></ul><p>4</p><ul><li>4a</li><li>4b</li><li>4c</li></ul><p>5</p>{% endblock %}");
+			t.is("<div>BaseBefore<p>1</p><p>2</p><ul><li>2a</li><li>2b</li><li>2c</li></ul><p>3</p><ul><li>3a</li><li>3b</li><li>3c</li></ul><p>4</p><ul><li>4a</li><li>4b</li><li>4c</li></ul><p>5</p>BaseAfter</div>", dd.tests.dom.util.render(template, context));
+		},
+		function test_tag_for(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				items: ["apple", "banana", "lemon"]
+			});
+			var template = new dd.DomTemplate('<div><ul>{% for item in items %}<li class="{{ item|length }}">{{ item }}</li>{% endfor %}</ul></div>');
+
+			t.is('<div><ul><li class="5">apple</li><li class="6">banana</li><li class="5">lemon</li></ul></div>', dd.tests.dom.util.render(template, context));
+
+			// The line break is there to make sure our regex works
+			template = new dd.DomTemplate('<div><select>{% for item in items %}<option>{{ item }}</option>\n{% endfor %}</select></div>');
+
+			t.is('<div><select><option>apple</option><option>banana</option><option>lemon</option></select></div>', dd.tests.dom.util.render(template, context));
+		},
+		function test_tag_if(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({key: true});
+			var template = new dd.DomTemplate('{% if key %}<div>has key</div>{% else %}<div>no key</div>{% endif %}');
+			t.is("<div>has key</div>", dd.tests.dom.util.render(template, context));
+			context.key = false;
+			t.is("<div>no key</div>", dd.tests.dom.util.render(template, context));
+		},
+		function test_tag_ifchanged(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				year: 2008,
+				days: [
+					new Date(2008, 0, 12),
+					new Date(2008, 0, 28),
+					new Date(2008, 1, 1),
+					new Date(2008, 1, 1),
+					new Date(2008, 1, 1)
+				]
+			});
+
+			var template = new dd.DomTemplate("<div><h1>Archive for {{ year }}</h1>"+
+"{% for date in days %}"+
+'{% ifchanged %}<h3>Month: </h3><h3>{{ date|date:"F" }}</h3>{% endifchanged %}'+
+'<a href="{{ date|date:\'M/d\'|lower }}/">{{ date|date:\'j\' }}</a>'+
+"{% endfor %}</div>");
+
+			t.is('<div><h1>Archive for 2008</h1>'+
+'<h3>Month: </h3><h3>January</h3>'+
+'<a href="jan/12/">12</a>'+
+'<a href="jan/28/">28</a>'+
+'<h3>Month: </h3><h3>February</h3>'+
+'<a href="feb/01/">1</a>'+
+'<a href="feb/01/">1</a>'+
+'<a href="feb/01/">1</a></div>', dd.tests.dom.util.render(template, context));
+
+			template = new dd.DomTemplate('<div>{% for date in days %}'+
+'{% ifchanged date.date %} {{ date.date }} {% endifchanged %}'+
+'{% ifchanged date.hour date.date %}'+
+'{{ date.hour }}'+
+'{% endifchanged %}'+
+'{% endfor %}</div>');
+			t.is('<div> 2008-01-12 0 2008-01-28 0 2008-02-01 0</div>', dd.tests.dom.util.render(template, context));
+		},
+		function test_tag_ifequal(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				items: [
+					{ name: "apple", color: "red" },
+					{ name: "banana", color: "yellow" },
+					{ name: "pear", color: "green" },
+					{ name: "kiwi", color: "brown" }
+				],
+				edit_item: "banana"
+			});
+
+			var template = new dd.DomTemplate("<div><ul>{% for item in items %}<li>{{ item.name }}</li>{% endfor %}</ul></div>");
+			t.is('<div><ul><li>apple</li><li>banana</li><li>pear</li><li>kiwi</li></ul></div>', dd.tests.dom.util.render(template, context));
+
+			template = new dd.DomTemplate("<div><ul>{% for item in items %}<li><span>{{ item.name }}</span><br/><p>{{ item.color }}</p></li>{% endfor %}</ul></div>");
+			t.is('<div><ul><li><span>apple</span><br/><p>red</p></li><li><span>banana</span><br/><p>yellow</p></li><li><span>pear</span><br/><p>green</p></li><li><span>kiwi</span><br/><p>brown</p></li></ul></div>', dd.tests.dom.util.render(template, context));
+
+			template = new dd.DomTemplate("<div><ul>{% for item in items %}<li>{% ifequal item.name edit_item %}<label>Name: <input type='text' name='name' value=\"{{ item.name }}\"/></label><br/><label>Color: <textarea name='color'>{{ item.color }}</textarea></label>{% else %}<span>{{ item.name }}</span><br/><p>{{ item.color }}</p>{% endifequal %}</li>{% endfor %}</ul></div>");
+			t.is('<div><ul><li><span>apple</span><br/><p>red</p></li><li><label>Name: <input name="name" value="banana"/></label><br/><label>Color: <textarea name="color">yellow</textarea></label></li><li><span>pear</span><br/><p>green</p></li><li><span>kiwi</span><br/><p>brown</p></li></ul></div>', dd.tests.dom.util.render(template, context));
+
+			template = new dd.DomTemplate("<div><ul>{% for item in items %}<li>{% ifequal item.name edit_item %}<div><label>Name: <input type='text' name='name' value=\"{{ item.name }}\"/></label><br/><label>Color: <textarea name='color'>{{ item.color }}</textarea></label></div>{% else %}<div><span>{{ item.name }}</span><br/><p>{{ item.color }}</p></div>{% endifequal %}</li>{% endfor %}</ul></div>");
+			t.is('<div><ul><li><div><span>apple</span><br/><p>red</p></div></li><li><div><label>Name: <input name="name" value="banana"/></label><br/><label>Color: <textarea name="color">yellow</textarea></label></div></li><li><div><span>pear</span><br/><p>green</p></div></li><li><div><span>kiwi</span><br/><p>brown</p></div></li></ul></div>', dd.tests.dom.util.render(template, context));
+
+			template = new dd.DomTemplate("<div><ul>{% for item in items %}{% ifequal item.name edit_item %}<li><label>Name: <input type='text' name='name' value=\"{{ item.name }}\"/></label><br/><label>Color: <textarea name='color'>{{ item.color }}</textarea></label></li>{% else %}<li><span>{{ item.name }}</span><br/><p>{{ item.color }}</p></li>{% endifequal %}{% endfor %}</ul></div>");
+			t.is('<div><ul><li><span>apple</span><br/><p>red</p></li><li><label>Name: <input name="name" value="banana"/></label><br/><label>Color: <textarea name="color">yellow</textarea></label></li><li><span>pear</span><br/><p>green</p></li><li><span>kiwi</span><br/><p>brown</p></li></ul></div>', dd.tests.dom.util.render(template, context));
+		},
+		function test_tag_include(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				hello: dojo.moduleUrl("dojox.dtl.tests.templates", "hello.html"),
+				person: "Bob",
+				people: ["Charles", "Ralph", "Julia"]
+			});
+
+			var template = new dd.DomTemplate("<div>{% include hello %}</div>");
+			t.is("<div>Hello, <span>Bob</span></div>", dd.tests.dom.util.render(template, context));
+
+			template = new dd.DomTemplate('<div>{% include "../../dojox/dtl/tests/templates/hello.html" %}</div>');
+			t.is("<div>Hello, <span>Bob</span></div>", dd.tests.dom.util.render(template, context));
+
+			template = new dd.DomTemplate('<div>{% for person in people %}<div class="include">{% include hello %} </div>{% endfor %}</div>');
+			t.is('<div><div class="include">Hello, <span>Charles</span> </div><div class="include">Hello, <span>Ralph</span> </div><div class="include">Hello, <span>Julia</span> </div></div>', dd.tests.dom.util.render(template, context));
+		},
+		function test_tag_spaceless(t){
+			var dd = dojox.dtl;
+
+			var template = new dd.DomTemplate("{% spaceless %}<ul> \n <li>Hot</li> \n\n<li>Pocket </li>\n </ul>{% endspaceless %}");
+			t.is("<ul><li>Hot</li><li>Pocket </li></ul>", dd.tests.dom.util.render(template));
+		},
+		function test_tag_ssi(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				hello: dojo.moduleUrl("dojox.dtl.tests.templates", "hello.html"),
+				person: "Bob",
+				people: ["Charles", "Ralph", "Julia"]
+			});
+
+			var template = new dd.DomTemplate("<div>{% ssi hello parsed %}</div>");
+			t.is("<div>Hello, <span>Bob</span></div>", dd.tests.dom.util.render(template, context));
+
+			template = new dd.DomTemplate("<div>{% ssi hello %}</div>");
+			t.is("<div>Hello, <span>{{ person }}</span></div>", dd.tests.dom.util.render(template, context));
+
+			template = new dd.DomTemplate('<div>{% ssi "../../dojox/dtl/tests/templates/hello.html" parsed %}</div>');
+			t.is("<div>Hello, <span>Bob</span></div>", dd.tests.dom.util.render(template, context));
+
+			template = new dd.DomTemplate('<div>{% for person in people %}{% ssi hello parsed %} {% endfor %}</div>');
+			t.is("<div>Hello, <span>Charles</span> Hello, <span>Ralph</span> Hello, <span>Julia</span> </div>", dd.tests.dom.util.render(template, context));
+		},
+		function test_tag_comment(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({});
+
+			var template = new dd.DomTemplate("<div>abc{% comment %}{% endif %}<div>{% ssi hello parsed %}</div>{% for item in items %}{% endcomment %}xyz</div>");
+			t.is("<div>abcxyz</div>", dd.tests.dom.util.render(template, context));
+		},
+		function test_annoying_nesting(){
+			// In Safari:  table/tr, tr/th, tr/td, thead/tr, tbody/tr
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({items: ["apple", "banana", "orange"]});
+
+			// All: select/option
+			var template = new dd.DomTemplate("<div><select>{% for item in items %}{% ifequal item 'apple' %}<option>=====</option>{% endifequal %}<option>{{ item }}</option>{% endfor %}</select></div>");
+			doh.is("<div><select><option>=====</option><option>apple</option><option>banana</option><option>orange</option></select></div>", dd.tests.dom.util.render(template, context));
+
+			// Safari: table/tr
+			template = new dd.DomTemplate('<div><table><tr><td>Fruit</td></tr>{% for fruit in items %}<tr><td>{{ fruit }}</td></tr>{% endfor %}</table></div>');
+			doh.is('<div><table><tbody><tr><td>Fruit</td></tr><tr><td>apple</td></tr><tr><td>banana</td></tr><tr><td>orange</td></tr></tbody></table></div>', dd.tests.dom.util.render(template, context));
+
+			// Safari: tbody/tr
+			template = new dd.DomTemplate('<div><table><tbody><tr><td>Fruit</td></tr>{% for fruit in items %}<tr><td>{{ fruit }}</td></tr>{% endfor %}</tbody></table></div>');
+			doh.is('<div><table><tbody><tr><td>Fruit</td></tr><tr><td>apple</td></tr><tr><td>banana</td></tr><tr><td>orange</td></tr></tbody></table></div>', dd.tests.dom.util.render(template, context));
+
+			// Safari: tr/th
+			template = new dd.DomTemplate("<div><table><tr>{% for item in items %}{% ifequal item 'apple' %}<th>=====</th>{% endifequal %}<th>{{ item }}</th>{% endfor %}</tr></table></div>");
+			doh.is("<div><table><tbody><tr><th>=====</th><th>apple</th><th>banana</th><th>orange</th></tr></tbody></table></div>", dd.tests.dom.util.render(template, context));
+
+			// Safari: tr/th
+			template = new dd.DomTemplate("<div><table><tr>{% for item in items %}{% ifequal item 'apple' %}<td>=====</td>{% endifequal %}<td>{{ item }}</td>{% endfor %}</tr></table></div>");
+			doh.is("<div><table><tbody><tr><td>=====</td><td>apple</td><td>banana</td><td>orange</td></tr></tbody></table></div>", dd.tests.dom.util.render(template, context));
+
+			var old = dojo.isWebKit;
+			dojo.isWebKit = true;
+			// Force WebKit because linebreaks work differently when nesting is parsed
+			template = new dd.DomTemplate('<div><table>\n<thead><tr><th>Name</th><th>Count</th></tr></thead>\n<tbody>\n{% for fruit in items %}\n<tr><td>{{ fruit }}</td><td>{{ fruit }}</td></tr>\n{% endfor %}\n</tbody></table></div>');
+			doh.is('<div><table><thead><tr><th>Name</th><th>Count</th></tr></thead><tbody><tr><td>apple</td><td>apple</td></tr><tr><td>banana</td><td>banana</td></tr><tr><td>orange</td><td>orange</td></tr></tbody></table></div>', dd.tests.dom.util.render(template, context));
+			dojo.isWebKit = old;
+		},
+		function test_custom_attributes(){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({frag: {start: 10, stop: 20}});
+
+			var template = new dd.DomTemplate('<div startLine="{{ frag.start }}" stopLine="{{ frag.stop }}">abc</div>');
+			doh.is('<div startline="10" stopline="20">abc</div>', dd.tests.dom.util.render(template, context));
+		},
+		function test_emptiness(){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({});
+			var template = new dd.DomTemplate('<div>{% if data %}{% else %}<p>Please select a file using the left panel.</p>{% endif %}</div>');
+			doh.is('<div><p>Please select a file using the left panel.</p></div>', dd.tests.dom.util.render(template, context));
+
+			context.data = true;
+			doh.is('<div/>', dd.tests.dom.util.render(template, context));
+		},
+		function test_bools(){
+			// checked, disabled, readonly
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({checked: false});
+			var template = new dd.DomTemplate('<div><input checked="{{ checked }}"></div>');
+			doh.is('<div><input checked="false"/></div>', dd.tests.dom.util.render(template, context));
+		},
+		function test_mixedCase(){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context();
+			var template = new dd.DomTemplate('<div simplecase="simple" mixedCase="mixed">content</div>');
+			doh.is('<div simplecase="simple" mixedcase="mixed">content</div>', dd.tests.dom.util.render(template, context));
+		},
+		function test_tabindex_lowercase(){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context();
+			var template = new dd.DomTemplate('<div tabindex="-1"></div>');
+			//the following should not throw errors
+			dd.tests.dom.util.render(template, context);
+		},
+		function test_tabIndex(){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context();
+			var template = new dd.DomTemplate('<div tabIndex="-1"></div>');
+			//the following should not throw errors in IE
+			dd.tests.dom.util.render(template, context);
+		}
+	]
+);
\ No newline at end of file
diff --git a/dojox/dtl/tests/dom/util.js b/dojox/dtl/tests/dom/util.js
new file mode 100644
index 0000000..b156dae
--- /dev/null
+++ b/dojox/dtl/tests/dom/util.js
@@ -0,0 +1,157 @@
+dojo.provide("dojox.dtl.tests.dom.util");
+
+dojo.require("dojox.dtl.dom");
+dojo.require("dojox.dtl.render.dom");
+dojo.require("dojox.string.Builder");
+
+dojox.dtl.DomBuffer.prototype.onClone = function(from, to){
+	var clones = this._clones = this._clones || [];
+
+	for(var i = 0, group; group = clones[i]; i++){
+		for(var j = 0, item; item = group[j]; j++){
+			if(item === from){
+				group.push(to);
+				return
+			}else if(item === to){
+				group.push(from);
+				return;
+			}
+		}
+	}
+
+	clones.push([from, to]);
+}
+dojox.dtl.DomBuffer.prototype.onAddEvent = function(node, type, description){
+	var events = this._events = this._events || [];
+
+	var found = false;
+	for(var i = 0, evt; evt = events[i]; i++){
+		if(evt[0] === node){
+			found = true;
+			evt[1] = type;
+			evt[2] = description;
+		}
+	}
+
+	if(!found){
+		events.push([node, type, description]);
+	}
+}
+
+dojox.dtl.tests.dom.util.render = function(/*DomTemplate*/ template, /*Context*/ context) {
+	try {
+		var div = document.createElement("div");
+		dojo.style(div, "visibility", "hidden");
+		var attach = document.createElement("div");
+		div.appendChild(attach);
+		dojo.body().appendChild(div);
+
+		var buffer = template.getBuffer();
+		var canvas = new dojox.dtl.render.dom.Render(attach, template);
+		canvas.render(context, template, buffer);
+		var clones = buffer._clones;
+		var events = buffer._events;
+
+		var first = dojox.dtl.tests.dom.util.serialize(canvas.domNode, template.tokens, clones, events).toString();
+
+		buffer = template.getBuffer();
+		buffer._clones = clones;
+		buffer._events = events;
+		canvas.render(context, template, buffer);
+
+		var second = dojox.dtl.tests.dom.util.serialize(canvas.domNode, template.tokens, clones, events).toString();
+
+		doh.is("Compare re-render: " + first, "Compare re-render: " + second);
+		return first;
+	}
+	catch(e){
+		throw e;
+	}finally{
+		div.parentNode.removeChild(div);
+	}
+}
+
+dojox.dtl.tests.dom.util.serialize = function(node, tokens, clones, events, output) {
+	var types = dojox.dtl.dom.types;
+	clones = clones || [];
+	events = events || [];
+
+	if (node.nodeType == 3) {
+		output.append(node.nodeValue);
+	}else{
+		var name = node.nodeName.toLowerCase();
+		if(!name){ return; }
+
+		if (!output) {
+			output = new dojox.string.Builder();
+		}
+		output.append("<").append(name);
+
+		var found = {};
+		var attributes = dojo.filter(tokens, function(item){
+			return item[0] == dojox.dtl.TOKEN_ATTR && dojo.isString(item[3]) && dojo.trim(item[3]);
+		});
+		attributes = dojo.map(attributes, "return item[2];");
+		attributes = dojo.filter(attributes, function(attribute){
+			if(!found[attribute]){
+				return found[attribute] = true;
+			}
+		});
+
+		for(var i = 0, attribute; attribute = attributes[i]; i++){
+			var value = "";
+			if(attribute == "class"){
+				value = node.className || value;
+			}else if(attribute == "for"){
+				value = node.htmlFor || value;
+			}else{
+				var bools = {checked: 1, disabled: 1, readonly: 1};
+				if(bools[attribute] && typeof node[attribute] == "boolean"){
+					value = dojo.attr(node, attribute) ? "true" : "false";
+				}else{
+					value = node.getAttribute(attribute, 2) || value;
+				}
+				if(node.tagName == "TEXTAREA" && (attribute == "type" || attribute == "value")){
+					continue;
+				}
+				if(node.tagName == "INPUT" && attribute == "type" && value == "text"){
+					continue;
+				}
+				if(dojo.isIE && (attribute == "href" || attribute == "src")){
+					var hash = location.href.lastIndexOf(location.hash);
+					var href = location.href.substring(0, hash).split("/");
+					href.pop();
+					href = href.join("/") + "/";
+					if(value.indexOf(href) == 0){
+						value = value.replace(href, "");
+					}
+					value = decodeURIComponent(value);
+				}
+			}
+			if(value !== ""){
+				output.append(" ").append(attribute).append('="').append(value.replace(/"/g, '\\"')).append('"');
+			}
+		}
+
+		// Deal with events
+		if(events){
+			for(var i = 0, evt; evt = events[i]; i++){
+				if(evt[0] === node){
+					output.append(" ").append(evt[1]).append('="').append(evt[2]).append('"');
+				}
+			}
+		}
+
+		if(!node.childNodes.length){
+			output.append("/>");
+		}else{
+			output.append(">");
+			dojo.forEach(node.childNodes, function(node){
+				dojox.dtl.tests.dom.util.serialize(node, tokens, clones, events, output);
+			});
+			output.append("</").append(name).append(">");
+		}
+
+		return output;
+	}
+}
\ No newline at end of file
diff --git a/dojox/dtl/tests/module.js b/dojox/dtl/tests/module.js
new file mode 100644
index 0000000..f91da1c
--- /dev/null
+++ b/dojox/dtl/tests/module.js
@@ -0,0 +1,11 @@
+dojo.provide("dojox.dtl.tests.module");
+
+try{
+	dojo.require("dojox.dtl.tests.text.filter");
+	dojo.require("dojox.dtl.tests.text.tag");
+	dojo.require("dojox.dtl.tests.dom.tag");
+	dojo.require("dojox.dtl.tests.dom.buffer");
+	dojo.require("dojox.dtl.tests.context");
+}catch(e){
+	doh.debug(e);
+}
\ No newline at end of file
diff --git a/dojox/dtl/tests/runTests.html b/dojox/dtl/tests/runTests.html
new file mode 100644
index 0000000..32338f6
--- /dev/null
+++ b/dojox/dtl/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Djanto Template Language D.O.H. Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.dtl.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML>
\ No newline at end of file
diff --git a/dojox/dtl/tests/templates/base.html b/dojox/dtl/tests/templates/base.html
new file mode 100644
index 0000000..30b731b
--- /dev/null
+++ b/dojox/dtl/tests/templates/base.html
@@ -0,0 +1 @@
+<div>BaseBefore{% block base %}foo{% endblock %}BaseAfter</div>
\ No newline at end of file
diff --git a/dojox/dtl/tests/templates/hello.html b/dojox/dtl/tests/templates/hello.html
new file mode 100644
index 0000000..18e4c1a
--- /dev/null
+++ b/dojox/dtl/tests/templates/hello.html
@@ -0,0 +1 @@
+Hello, <span>{{ person }}</span>
\ No newline at end of file
diff --git a/dojox/dtl/tests/templates/pocket.html b/dojox/dtl/tests/templates/pocket.html
new file mode 100644
index 0000000..f78c520
--- /dev/null
+++ b/dojox/dtl/tests/templates/pocket.html
@@ -0,0 +1 @@
+{% block pocket %}Hot{% endblock %} Pocket
\ No newline at end of file
diff --git a/dojox/dtl/tests/templates/pocket2.html b/dojox/dtl/tests/templates/pocket2.html
new file mode 100755
index 0000000..547f9a2
--- /dev/null
+++ b/dojox/dtl/tests/templates/pocket2.html
@@ -0,0 +1 @@
+{% for item in items %}({% block pocket %}Hot{% endblock %}) {% endfor %}Pocket
\ No newline at end of file
diff --git a/dojox/dtl/tests/text/filter.js b/dojox/dtl/tests/text/filter.js
new file mode 100644
index 0000000..afb74a4
--- /dev/null
+++ b/dojox/dtl/tests/text/filter.js
@@ -0,0 +1,736 @@
+dojo.provide("dojox.dtl.tests.text.filter");
+
+dojo.require("dojox.dtl");
+dojo.require("dojox.dtl.Context");
+dojo.require("dojox.dtl.utils.date");
+dojo.require("dojox.date.php");
+dojo.require("dojox.string.sprintf");
+
+// If you update something here, update it in the HTML tests
+doh.register("dojox.dtl.text.filter", 
+	[
+		function test_filter_add(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ four: 4 });
+			tpl = new dd.Template('{{ four|add:"6" }}');
+			t.is("10", tpl.render(context));
+			context.four = "4";
+			t.is("10", tpl.render(context));
+			tpl = new dd.Template('{{ four|add:"six" }}');
+			t.is("4", tpl.render(context));
+			tpl = new dd.Template('{{ four|add:"6.6" }}');
+			t.is("10", tpl.render(context));
+		},
+		function test_filter_addslashes(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ unslashed: "Test back slashes \\, double quotes \" and single quotes '" })
+			var tpl = new dd.Template('{{ unslashed|addslashes|safe }}');
+			t.is("Test back slashes \\\\, double quotes \\\" and single quotes \\'", tpl.render(context));
+		},
+		function test_filter_capfirst(t){
+			var dd = dojox.dtl;
+
+			var tpl = new dd.Template('{{ uncapped|capfirst }}');
+			t.is("Cap", tpl.render(new dd.Context({ uncapped: "cap" })));
+		},
+		function test_filter_center(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context();
+			var tpl = new dd.Template('{{ narrow|center }}');
+			context.narrow = "even";
+			t.is("even", tpl.render(context));
+			context.narrow = "odd";
+			t.is("odd", tpl.render(context));
+			tpl = new dd.Template('{{ narrow|center:"5" }}');
+			context.narrow = "even";
+			t.is("even ", tpl.render(context));
+			context.narrow = "odd";
+			t.is(" odd ", tpl.render(context));
+			tpl = new dd.Template('{{ narrow|center:"6" }}');
+			context.narrow = "even";
+			t.is(" even ", tpl.render(context));
+			context.narrow = "odd";
+			t.is(" odd  ", tpl.render(context));
+			tpl = new dd.Template('{{ narrow|center:"12" }}');
+			context.narrow = "even";
+			t.is("    even    ", tpl.render(context));
+			context.narrow = "odd";
+			t.is("    odd     ", tpl.render(context));
+		},
+		function test_filter_cut(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ uncut: "Apples and oranges" });
+			var tpl = new dd.Template('{{ uncut|cut }}');
+			t.is("Apples and oranges", tpl.render(context));
+			tpl = new dd.Template('{{ uncut|cut:"A" }}');
+			t.is("pples and oranges", tpl.render(context));
+			tpl = new dd.Template('{{ uncut|cut:" " }}');
+			t.is("Applesandoranges", tpl.render(context));
+			tpl = new dd.Template('{{ uncut|cut:"e" }}');
+			t.is("Appls and orangs", tpl.render(context));
+		},
+		function test_filter_date(t){
+			var dd = dojox.dtl;
+			var context = new dd.Context({ now: new Date(2007, 0, 1), then: new Date(2007, 1, 1) });
+
+			var tpl = new dd.Template('{{ now|date }}');
+			t.is(dojox.dtl.utils.date.format(context.now, "N j, Y"), tpl.render(context));
+
+			context.then = new Date(2007, 0, 1);
+			tpl = new dd.Template('{{ now|date:"d" }}');
+			t.is("01", tpl.render(context));
+
+			tpl = new dd.Template('{{ now|date:"D" }}');
+			t.is("Mon", tpl.render(context));
+
+			tpl = new dd.Template('{{ now|date:"j" }}');
+			t.is("1", tpl.render(context));
+
+			tpl = new dd.Template('{{ now|date:"l" }}');
+			t.is("Monday", tpl.render(context));
+
+			tpl = new dd.Template('{{ now|date:"N" }}');
+			t.is("Jan.", tpl.render(context));
+
+			tpl = new dd.Template('{{ now|date:"S" }}');
+			t.is("st", tpl.render(context));
+			context.now.setDate(2);
+			t.is("nd", tpl.render(context));
+			context.now.setDate(3);
+			t.is("rd", tpl.render(context));
+			context.now.setDate(4);
+			t.is("th", tpl.render(context));
+			context.now.setDate(5);
+			t.is("th", tpl.render(context));
+			context.now.setDate(6);
+			t.is("th", tpl.render(context));
+			context.now.setDate(7);
+			t.is("th", tpl.render(context));
+			context.now.setDate(8);
+			t.is("th", tpl.render(context));
+			context.now.setDate(9);
+			t.is("th", tpl.render(context));
+			context.now.setDate(10);
+			t.is("th", tpl.render(context));
+			context.now.setDate(11);
+			t.is("th", tpl.render(context));
+			context.now.setDate(12);
+			t.is("th", tpl.render(context));
+			context.now.setDate(13);
+			t.is("th", tpl.render(context));
+			context.now.setDate(14);
+			t.is("th", tpl.render(context));
+			context.now.setDate(15);
+			t.is("th", tpl.render(context));
+			context.now.setDate(16);
+			t.is("th", tpl.render(context));
+			context.now.setDate(17);
+			t.is("th", tpl.render(context));
+			context.now.setDate(18);
+			t.is("th", tpl.render(context));
+			context.now.setDate(19);
+			t.is("th", tpl.render(context));
+			context.now.setDate(20);
+			t.is("th", tpl.render(context));
+			context.now.setDate(21);
+			t.is("st", tpl.render(context));
+			context.now.setDate(22);
+			t.is("nd", tpl.render(context));
+			context.now.setDate(23);
+			t.is("rd", tpl.render(context));
+			context.now.setDate(24);
+			t.is("th", tpl.render(context));
+			context.now.setDate(25);
+			t.is("th", tpl.render(context));
+			context.now.setDate(26);
+			t.is("th", tpl.render(context));
+			context.now.setDate(27);
+			t.is("th", tpl.render(context));
+			context.now.setDate(28);
+			t.is("th", tpl.render(context));
+			context.now.setDate(29);
+			t.is("th", tpl.render(context));
+			context.now.setDate(30);
+			t.is("th", tpl.render(context));
+			context.now.setDate(31);
+			t.is("st", tpl.render(context));
+			context.now.setDate(1);
+
+			tpl = new dd.Template('{{ now|date:"w" }}');
+			t.is("1", tpl.render(context));
+
+			tpl = new dd.Template('{{ now|date:"z" }}');
+			t.is("0", tpl.render(context));
+		
+			tpl = new dd.Template('{{ now|date:"W" }}');
+			t.is("1", tpl.render(context));
+		},
+		function test_filter_default(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context();
+			tpl = new dd.Template('{{ empty|default }}');
+			t.is("", tpl.render(context));
+			tpl = new dd.Template('{{ empty|default:"full" }}');
+			t.is("full", tpl.render(context));
+			context.empty = "not empty";
+			t.is("not empty", tpl.render(context));
+		},
+		function test_filter_default_if_none(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context();
+			tpl = new dd.Template('{{ empty|default_if_none }}');
+			t.is("", tpl.render(context));
+			tpl = new dd.Template('{{ empty|default_if_none:"full" }}');
+			t.is("", tpl.render(context));
+			context.empty = null;
+			t.is("full", tpl.render(context));
+			context.empty = "not empty";
+			t.is("not empty", tpl.render(context));
+		},
+		function test_filter_dictsort(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				fruit: [
+					{ name: "lemons", toString: function(){ return this.name; } },
+					{ name: "apples", toString: function(){ return this.name; } },
+					{ name: "grapes", toString: function(){ return this.name; } }
+				]
+			});
+ 			tpl = new dd.Template('{{ fruit|dictsort|join:"|" }}');
+			t.is("lemons|apples|grapes", tpl.render(context));
+			tpl = new dd.Template('{{ fruit|dictsort:"name"|join:"|" }}');
+			t.is("apples|grapes|lemons", tpl.render(context));
+		},
+		function test_filter_dictsort_reversed(t){
+			var dd = dojox.dtl;
+
+			context = new dd.Context({
+				fruit: [
+					{ name: "lemons", toString: function(){ return this.name; } },
+					{ name: "apples", toString: function(){ return this.name; } },
+					{ name: "grapes", toString: function(){ return this.name; } }
+				]
+			});
+			tpl = new dd.Template('{{ fruit|dictsortreversed:"name"|join:"|" }}');
+			t.is("lemons|grapes|apples", tpl.render(context));
+		},
+		function test_filter_divisibleby(t){
+			var dd = dojox.dtl;
+
+			context = new dd.Context();
+			tpl = new dd.Template('{{ 4|divisibleby:"2" }}');
+			t.is("true", tpl.render(context));
+			context = new dd.Context({ number: 4 });
+			tpl = new dd.Template('{{ number|divisibleby:3 }}');
+			t.is("false", tpl.render(context));
+		},
+		function test_filter_escape(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ unescaped: "Try & cover <all> the \"major\" 'situations' at once" });
+			tpl = new dd.Template('{{ unescaped|escape }}');
+			t.is("Try & cover <all> the "major" 'situations' at once", tpl.render(context));
+		},
+		function test_filter_filesizeformat(t){
+			var dd = dojox.dtl;
+
+			var tpl = new dd.Template('{{ 1|filesizeformat }}');
+			t.is("1 byte", tpl.render());
+			tpl = new dd.Template('{{ 512|filesizeformat }}');
+			t.is("512 bytes", tpl.render());
+			tpl = new dd.Template('{{ 1024|filesizeformat }}');
+			t.is("1.0 KB", tpl.render());
+			tpl = new dd.Template('{{ 2048|filesizeformat }}');
+			t.is("2.0 KB", tpl.render());
+			tpl = new dd.Template('{{ 1048576|filesizeformat }}');
+			t.is("1.0 MB", tpl.render());
+			tpl = new dd.Template('{{ 1073741824|filesizeformat }}');
+			t.is("1.0 GB", tpl.render());
+		},
+		function test_filter_first(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				fruit: [
+					{ name: "lemons", toString: function(){ return this.name; } },
+					{ name: "apples", toString: function(){ return this.name; } },
+					{ name: "grapes", toString: function(){ return this.name; } }
+				]
+			});
+			tpl = new dd.Template('{{ fruit|first }}');
+			t.is("lemons", tpl.render(context));
+		},
+		function test_filter_fix_ampersands(t){
+			var dd = dojox.dtl;
+
+			var tpl = new dd.Template('{{ "One & Two"|fix_ampersands|safe }}');
+			t.is("One & Two", tpl.render());
+		},
+		function test_filter_floatformat(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ num1: 34.23234, num2: 34.00000 });
+			var tpl = new dd.Template('{{ num1|floatformat }}');
+			t.is("34.2", tpl.render(context));
+			tpl = new dd.Template('{{ num2|floatformat }}');
+			t.is("34", tpl.render(context));
+			tpl = new dd.Template('{{ num1|floatformat:3 }}');
+			t.is("34.232", tpl.render(context));
+			tpl = new dd.Template('{{ num2|floatformat:3 }}');
+			t.is("34.000", tpl.render(context));
+			tpl = new dd.Template('{{ num1|floatformat:-3 }}');
+			t.is("34.2", tpl.render(context));
+			tpl = new dd.Template('{{ num2|floatformat:-3 }}');
+			t.is("34", tpl.render(context));
+		},
+		function test_filter_get_digit(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ pi: 314159265 });
+			var tpl = new dd.Template('{{ pi|get_digit:1 }}');
+			t.is("3", tpl.render(context));
+			tpl = new dd.Template('{{ pi|get_digit:"2" }}');
+			t.is("1", tpl.render(context));
+			tpl = new dd.Template('{{ pi|get_digit:0 }}');
+			t.is("314159265", tpl.render(context));
+			tpl = new dd.Template('{{ "nada"|get_digit:1 }}');
+			t.is("0", tpl.render(context));
+		},
+		function test_filter_iriencode(t){
+			var dd = dojox.dtl;
+
+			var tpl = new dd.Template('{{ "http://homepage.com/~user"|urlencode|iriencode }}');
+			t.is("http%3A//homepage.com/%7Euser", tpl.render());
+			tpl = new dd.Template('{{ "pottedmeat at dojotoolkit.org"|iriencode }}');
+			t.is("pottedmeat%40dojotoolkit.org", tpl.render());
+		},
+		function test_filter_join(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ items: ["foo", "bar", "baz" ]});
+			var tpl = new dd.Template("{{ items|join }}");
+			t.is("foo,bar,baz", tpl.render(context));
+
+			tpl = new dd.Template('{{ items|join:"mustard" }}');
+			t.is("foomustardbarmustardbaz", tpl.render(context));
+		},
+		function test_filter_length(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				fruit: [
+					{ name: "lemons", toString: function(){ return this.name; } },
+					{ name: "apples", toString: function(){ return this.name; } },
+					{ name: "grapes", toString: function(){ return this.name; } }
+				]
+			});
+			tpl = new dd.Template('{{ fruit|length }}');
+			t.is("3", tpl.render(context));
+			tpl = new dd.Template('{{ fruit|first|length }}');
+			t.is("6", tpl.render(context));
+		},
+		function test_filter_length_is(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				fruit: [
+					{ name: "lemons", toString: function(){ return this.name; } },
+					{ name: "apples", toString: function(){ return this.name; } },
+					{ name: "grapes", toString: function(){ return this.name; } }
+				]
+			});
+			tpl = new dd.Template('{{ fruit|length_is:"3" }}');
+			t.is("true", tpl.render(context));
+			tpl = new dd.Template('{{ fruit|length_is:"4" }}');
+			t.is("false", tpl.render(context));
+		},
+		function test_filter_linebreaks(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ unbroken: "This is just\r\n\n\ra bunch\nof text\n\n\nand such" });
+			tpl = new dd.Template('{{ unbroken|linebreaks|safe }}');
+			t.is("<p>This is just</p>\n\n<p>a bunch<br />of text</p>\n\n<p>and such</p>", tpl.render(context));
+		},
+		function test_filter_linebreaksbr(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ unbroken: "This is just\r\n\n\ra bunch\nof text\n\n\nand such" });
+			tpl = new dd.Template('{{ unbroken|linebreaksbr|safe }}');
+			t.is("This is just<br /><br />a bunch<br />of text<br /><br /><br />and such", tpl.render(context));
+		},
+		function test_filter_linenumbers(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ lines: "One\nTwo\nThree\nFour\n" });
+			var tpl = new dd.Template('{{ lines|linenumbers }}');
+			t.is("1. One\n2. Two\n3. Three\n4. Four\n5. ", tpl.render(context));
+		},
+		function test_filter_ljust(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context();
+			var tpl = new dd.Template('{{ narrow|ljust }}');
+			context.narrow = "even";
+			t.is("even", tpl.render(context));
+			context.narrow = "odd";
+			t.is("odd", tpl.render(context));
+			tpl = new dd.Template('{{ narrow|ljust:"5" }}');
+			context.narrow = "even";
+			t.is("even ", tpl.render(context));
+			context.narrow = "odd";
+			t.is("odd  ", tpl.render(context));
+			tpl = new dd.Template('{{ narrow|ljust:"6" }}');
+			context.narrow = "even";
+			t.is("even  ", tpl.render(context));
+			context.narrow = "odd";
+			t.is("odd   ", tpl.render(context));
+			tpl = new dd.Template('{{ narrow|ljust:"12" }}');
+			context.narrow = "even";
+			t.is("even        ", tpl.render(context));
+			context.narrow = "odd";
+			t.is("odd         ", tpl.render(context));
+		},
+		function test_filter_lower(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ mixed: "MiXeD" });
+			var tpl  = new dd.Template('{{ mixed|lower }}');
+			t.is("mixed", tpl.render(context));
+		},
+		function test_filter_make_list(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ word: "foo", number: 314159265, arr: ["first", "second"], obj: {first: "first", second: "second"} });
+			var tpl = new dd.Template('{{ word|make_list|join:"|" }} {{ number|make_list|join:"|" }} {{ arr|make_list|join:"|" }} {{ obj|make_list|join:"|" }}');
+			t.is("f|o|o 3|1|4|1|5|9|2|6|5 first|second first|second", tpl.render(context));
+		},
+		function test_filter_phone2numeric(t){
+			var dd = dojox.dtl;
+
+			tpl = new dd.Template('{{ "1-800-pottedmeat"|phone2numeric }}');
+			t.is("1-800-7688336328", tpl.render());
+		},
+		function test_filter_pluralize(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ animals: ["bear", "cougar", "aardvark"] });
+			var tpl = new dd.Template('{{ animals|length }} animal{{ animals|length|pluralize }}');
+			t.is("3 animals", tpl.render(context));
+			context.animals = ["bear"];
+			t.is("1 animal", tpl.render(context));
+			context = new dd.Context({ fairies: ["tinkerbell", "Andy Dick" ]});
+			tpl = new dd.Template('{{ fairies|length }} fair{{ fairies|length|pluralize:"y,ies" }}');
+			t.is("2 fairies", tpl.render(context));
+			context.fairies.pop();
+			t.is("1 fairy", tpl.render(context));
+		},
+		function test_filter_pprint(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ animals: ["bear", "cougar", "aardvark"] });
+			tpl = new dd.Template("{{ animals|pprint|safe }}");
+			t.is('["bear","cougar","aardvark"]', tpl.render(context));
+		},
+		function test_filter_random(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				fruit: [
+					{ name: "lemons", toString: function(){ return this.name; } },
+					{ name: "apples", toString: function(){ return this.name; } },
+					{ name: "grapes", toString: function(){ return this.name; } }
+				]
+			});
+			tpl = new dd.Template('{{ fruit|random }}');
+			result = tpl.render(context);
+			t.t(result == "lemons" || result == "apples" || result == "grapes");
+			var different = false;
+			for(var i = 0; i < 10; i++){
+				// Check to see if it changes
+				if(result != tpl.render(context) && result == "lemons" || result == "apples" || result == "grapes"){
+					different = true;
+					break;
+				}
+			}
+			t.t(different);
+		},
+		function test_filter_removetags(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ tagged: "I'm gonna do something <script>evil</script> with the <html>filter" });
+			tpl = new dd.Template('{{ tagged|removetags:"script <html>"|safe }}');
+			t.is("I'm gonna do something evil with the filter", tpl.render(context));
+		},
+		function test_filter_rjust(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context();
+			var tpl = new dd.Template('{{ narrow|rjust }}');
+			context.narrow = "even";
+			t.is("even", tpl.render(context));
+			context.narrow = "odd";
+			t.is("odd", tpl.render(context));
+			tpl = new dd.Template('{{ narrow|rjust:"5" }}');
+			context.narrow = "even";
+			t.is(" even", tpl.render(context));
+			context.narrow = "odd";
+			t.is("  odd", tpl.render(context));
+			tpl = new dd.Template('{{ narrow|rjust:"6" }}');
+			context.narrow = "even";
+			t.is("  even", tpl.render(context));
+			context.narrow = "odd";
+			t.is("   odd", tpl.render(context));
+			tpl = new dd.Template('{{ narrow|rjust:"12" }}');
+			context.narrow = "even";
+			t.is("        even", tpl.render(context));
+			context.narrow = "odd";
+			t.is("         odd", tpl.render(context));
+		},
+		function test_filter_slice(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				fruit: [
+					{ name: "lemons", toString: function(){ return this.name; } },
+					{ name: "apples", toString: function(){ return this.name; } },
+					{ name: "grapes", toString: function(){ return this.name; } }
+				]
+			});
+			tpl = new dd.Template('{{ fruit|slice:":1"|join:"|" }}');
+			t.is("lemons", tpl.render(context));
+			tpl = new dd.Template('{{ fruit|slice:"1"|join:"|" }}');
+			t.is("apples|grapes", tpl.render(context));
+			tpl = new dd.Template('{{ fruit|slice:"1:3"|join:"|" }}');
+			t.is("apples|grapes", tpl.render(context));
+			tpl = new dd.Template('{{ fruit|slice:""|join:"|" }}');
+			t.is("lemons|apples|grapes", tpl.render(context));
+			tpl = new dd.Template('{{ fruit|slice:"-1"|join:"|" }}');
+			t.is("grapes", tpl.render(context));
+			tpl = new dd.Template('{{ fruit|slice:":-1"|join:"|" }}');
+			t.is("lemons|apples", tpl.render(context));
+			tpl = new dd.Template('{{ fruit|slice:"-2:-1"|join:"|" }}');
+			t.is("apples", tpl.render(context));
+		},
+		function test_filter_slugify(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ unslugged: "Apples and oranges()"});
+			tpl = new dd.Template('{{ unslugged|slugify }}');
+			t.is("apples-and-oranges", tpl.render(context));
+		},
+		function test_filter_stringformat(t){
+			var dd = dojox.dtl;
+
+			var tpl = new dd.Template('{{ 42|stringformat:"7.3f" }}');
+			t.is(" 42.000", tpl.render());
+		},
+		function test_filter_striptags(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ tagged: "I'm gonna do something <script>evil</script> with the <html>filter" });
+			tpl = new dd.Template('{{ tagged|striptags|safe }}');
+			t.is("I'm gonna do something evil with the filter", tpl.render(context));
+		},
+		function test_filter_time(t){
+			var dd = dojox.dtl;
+			var context = new dd.Context({ now: new Date(2007, 0, 1) });
+
+			tpl = new dd.Template('{{ now|time }}');
+			t.is(dojox.dtl.utils.date.format(context.now, "P"), tpl.render(context));
+		},
+		function test_filter_timesince(t){
+			var dd = dojox.dtl;
+			var context = new dd.Context({ now: new Date(2007, 0, 1), then: new Date(2007, 1, 1) });
+
+			tpl = new dd.Template('{{ now|timesince:then }}');
+			t.is("1 month", tpl.render(context));
+			context.then = new Date(2007, 0, 5);
+			t.is("4 days", tpl.render(context));
+			context.then = new Date(2007, 0, 17);
+			t.is("2 weeks", tpl.render(context));
+			context.then = new Date(2008, 1, 1);
+			t.is("1 year", tpl.render(context));
+		},
+		function test_filter_timeuntil(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ now: new Date(2007, 0, 1), then: new Date(2007, 1, 1) });
+			var tpl = new dd.Template('{{ now|timeuntil:then }}');
+			t.is("1 month", tpl.render(context));
+			context.then = new Date(2007, 0, 5);
+			t.is("4 days", tpl.render(context));
+			context.then = new Date(2007, 0, 17);
+			t.is("2 weeks", tpl.render(context));
+			context.then = new Date(2008, 1, 1);
+			t.is("1 year", tpl.render(context));	
+		},
+		function test_filter_title(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ name: "potted meat" });
+			var tpl = new dd.Template("{{ name|title|safe }}");
+			t.is("Potted Meat", tpl.render(context));
+
+			context.name = "What's going on?";
+			t.is("What's Going On?", tpl.render(context));
+
+			context.name = "use\nline\nbREAKs\tand tabs";
+			t.is("Use\nLine\nBreaks\tAnd Tabs", tpl.render(context));
+		},
+		function test_filter_truncatewords(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ word: "potted meat writes a lot of tests" });
+			var tpl = new dd.Template("{{ word|truncatewords }}");
+			t.is(context.word, tpl.render(context));
+
+			tpl = new dd.Template('{{ word|truncatewords:"1" }}');
+			t.is("potted", tpl.render(context));
+
+			tpl = new dd.Template('{{ word|truncatewords:"2" }}');
+			t.is("potted meat", tpl.render(context));
+
+			tpl = new dd.Template('{{ word|truncatewords:20" }}');
+			t.is(context.word, tpl.render(context));
+
+			context.word = "potted \nmeat   \nwrites  a lot of tests";
+			tpl = new dd.Template('{{ word|truncatewords:"3" }}');
+			t.is("potted \nmeat   \nwrites", tpl.render(context));
+		},
+		function test_filter_truncatewords_html(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				body: "Test a string <em>that ends <i>inside a</i> tag</em> with different args",
+				size: 2
+			})
+			var tpl = new dd.Template('{{ body|truncatewords_html:size|safe }}');
+			t.is("Test a ...", tpl.render(context));
+			context.size = 4;
+			t.is("Test a string <em>that ...</em>", tpl.render(context));
+			context.size = 6;
+			t.is("Test a string <em>that ends <i>inside ...</i></em>", tpl.render(context));
+		},
+		function test_filter_unordered_list(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ states: ["States", [["Kansas", [["Lawrence", []], ["Topeka", []]]], ["Illinois", []]]] });
+			tpl = new dd.Template('{{ states|unordered_list|safe }}');
+			t.is("\t<li>States\n\t<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>Lawrence</li>\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>\n\t\t<li>Illinois</li>\n\t</ul>\n\t</li>", tpl.render(context));
+		},
+		function test_filter_upper(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({ mixed: "MiXeD" });
+			var tpl  = new dd.Template('{{ mixed|upper }}');
+			t.is("MIXED", tpl.render(context));
+		},
+		function test_filter_urlencode(t){
+			var dd = dojox.dtl;
+
+			var tpl = new dd.Template('{{ "http://homepage.com/~user"|urlencode }}');
+			t.is("http%3A//homepage.com/%7Euser", tpl.render());
+		},
+		function test_filter_urlize(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				body: "My favorite websites are www.televisionwithoutpity.com, http://daringfireball.net and you can email me at pottedmeat at sitepen.com"
+			});
+			var tpl = new dd.Template("{{ body|urlize|safe }}");
+			t.is('My favorite websites are <a href="http://www.televisionwithoutpity.com" rel="nofollow">www.televisionwithoutpity.com</a> <a href="http://daringfireball.net" rel="nofollow">http://daringfireball.net</a> and you can email me at <a href="mailto:pottedmeat at sitepen.com">pottedmeat at sitepen.com</a>', tpl.render(context));
+		},
+		function test_filter_urlizetrunc(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				body: "My favorite websites are www.televisionwithoutpity.com, http://daringfireball.net and you can email me at pottedmeat at sitepen.com"
+			});
+			var tpl = new dd.Template("{{ body|urlizetrunc|safe }}");
+			t.is('My favorite websites are <a href="http://www.televisionwithoutpity.com" rel="nofollow">www.televisionwithoutpity.com</a> <a href="http://daringfireball.net" rel="nofollow">http://daringfireball.net</a> and you can email me at <a href="mailto:pottedmeat at sitepen.com">pottedmeat at sitepen.com</a>', tpl.render(context));
+			tpl = new dd.Template('{{ body|urlizetrunc:"2"|safe }}');
+			t.is('My favorite websites are <a href="http://www.televisionwithoutpity.com" rel="nofollow">www.televisionwithoutpity.com</a> <a href="http://daringfireball.net" rel="nofollow">http://daringfireball.net</a> and you can email me at <a href="mailto:pottedmeat at sitepen.com">pottedmeat at sitepen.com</a>', tpl.render(context));
+			tpl = new dd.Template('{{ body|urlizetrunc:"10"|safe }}');
+			t.is('My favorite websites are <a href="http://www.televisionwithoutpity.com" rel="nofollow">www.tel...</a> <a href="http://daringfireball.net" rel="nofollow">http://...</a> and you can email me at <a href="mailto:pottedmeat at sitepen.com">pottedmeat at sitepen.com</a>', tpl.render(context));
+		},
+		function test_filter_wordcount(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				food: "Hot Pocket"
+			});
+			var tpl = new dd.Template("{{ food|wordcount }}");
+			t.is("2", tpl.render(context));
+			context.food = "";
+			t.is("0", tpl.render(context));
+			context.food = "A nice barbecue, maybe a little grilled veggies, some cole slaw.";
+			t.is("11", tpl.render(context));
+		},
+		function test_filter_wordwrap(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				body: "shrimp gumbo, shrimp pie, shrimp scampi, shrimp stew, fried shrimp, baked shrimp, shrimp o grotten, grilled shrimp, shrimp on a stick, shrimp salad, shrimp pop overs, shrimp cake, shrimp legs, shrimp stuffed eggs, shrimp cre oll, shrimp soup, creamed shrimp on toast, shrimp crapes, shrimply good crescent rolls, shrimp pizza, scalloped shrimp, boiled shrimp, shrimp cocktail"
+			});
+			var tpl = new dd.Template("{{ body|wordwrap }}");
+			t.is(context.body, tpl.render(context));
+			tpl = new dd.Template("{{ body|wordwrap:width }}");
+			context.width = 10;
+			t.is("shrimp\ngumbo,\nshrimp\npie,\nshrimp\nscampi,\nshrimp\nstew,\nfried\nshrimp,\nbaked\nshrimp,\nshrimp o\ngrotten,\ngrilled\nshrimp,\nshrimp on\na stick,\nshrimp\nsalad,\nshrimp pop\novers,\nshrimp\ncake,\nshrimp\nlegs,\nshrimp\nstuffed\neggs,\nshrimp cre\noll,\nshrimp\nsoup,\ncreamed\nshrimp on\ntoast,\nshrimp\ncrapes,\nshrimply\ngood\ncrescent\nrolls,\nshrimp\npizza,\nscalloped\nshrimp,\nboiled\nshrimp,\nshrimp\ncocktail", tpl.render(context));
+			tpl = new dd.Template('{{ body|wordwrap:"80" }}');
+			t.is("shrimp gumbo, shrimp pie, shrimp scampi, shrimp stew, fried shrimp, baked\nshrimp, shrimp o grotten, grilled shrimp, shrimp on a stick, shrimp salad,\nshrimp pop overs, shrimp cake, shrimp legs, shrimp stuffed eggs, shrimp cre oll,\nshrimp soup, creamed shrimp on toast, shrimp crapes, shrimply good crescent\nrolls, shrimp pizza, scalloped shrimp, boiled shrimp, shrimp cocktail", tpl.render(context));
+		},
+		function test_filter_yesno(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context();
+			tpl = new dd.Template('{{ true|yesno }}');
+			t.is("yes", tpl.render(context));
+			context = new dd.Context({ test: "value" });
+			tpl = new dd.Template('{{ test|yesno }}');
+			t.is("yes", tpl.render(context));
+			tpl = new dd.Template('{{ false|yesno }}');
+			t.is("no", tpl.render(context));
+			tpl = new dd.Template('{{ null|yesno }}');
+			t.is("maybe", tpl.render(context));
+			tpl = new dd.Template('{{ true|yesno:"bling,whack,soso" }}');
+			t.is("bling", tpl.render(context));
+			context = new dd.Context({ test: "value" });
+			tpl = new dd.Template('{{ test|yesno:"bling,whack,soso" }}');
+			t.is("bling", tpl.render(context));
+			tpl = new dd.Template('{{ false|yesno:"bling,whack,soso" }}');
+			t.is("whack", tpl.render(context));
+			tpl = new dd.Template('{{ null|yesno:"bling,whack,soso" }}');
+			t.is("soso", tpl.render(context));
+			tpl = new dd.Template('{{ null|yesno:"bling,whack" }}');
+			t.is("whack", tpl.render(context));
+		},
+		function test_filter_contrib_key(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				headers: ["action", "type"],
+				items: [
+					{
+						action: "eat",
+						type: "apple"
+					},
+					{
+						action: "mash",
+						type: "banana"
+					}
+				]
+			});
+
+			var tpl = new dd.Template("{% load dojox.dtl.contrib.objects %}<ul>{% for item in items %}<li><ul>{% for header in headers %}<li>{{ header }}: {{ item|key:header }}</li>{% endfor %}</ul></li>{% endfor %}</ul>");
+			t.is('<ul><li><ul><li>action: eat</li><li>type: apple</li></ul></li><li><ul><li>action: mash</li><li>type: banana</li></ul></li></ul>', tpl.render(context));
+		}
+	]
+);
\ No newline at end of file
diff --git a/dojox/dtl/tests/text/load.js b/dojox/dtl/tests/text/load.js
new file mode 100644
index 0000000..06dd9da
--- /dev/null
+++ b/dojox/dtl/tests/text/load.js
@@ -0,0 +1,2 @@
+dojo.provide("dojox.dtl.tests.text.load");
+// Test for the {% load %} tag
\ No newline at end of file
diff --git a/dojox/dtl/tests/text/tag.js b/dojox/dtl/tests/text/tag.js
new file mode 100644
index 0000000..c8e72c3
--- /dev/null
+++ b/dojox/dtl/tests/text/tag.js
@@ -0,0 +1,490 @@
+dojo.provide("dojox.dtl.tests.text.tag");
+
+dojo.require("dojox.dtl");
+dojo.require("dojox.dtl.Context");
+
+doh.register("dojox.dtl.text.tag", 
+	[
+		function test_tag_block_and_extends(t){
+			var dd = dojox.dtl;
+
+			// Simple (messy) string-based extension
+			var template = new dd.Template('{% extends "../../dojox/dtl/tests/templates/pocket.html" %}{% block pocket %}Simple{% endblock %}');
+			t.is("Simple Pocket", template.render());
+
+			// Variable replacement
+			var context = new dd.Context({
+				parent: "../../dojox/dtl/tests/templates/pocket.html"
+			})
+			template = new dd.Template('{% extends parent %}{% block pocket %}Variabled{% endblock %}');
+			t.is("Variabled Pocket", template.render(context));
+
+			// Nicer dojo.moduleUrl and variable based extension
+			context.parent = dojo.moduleUrl("dojox.dtl.tests.templates", "pocket.html");
+			template = new dd.Template('{% extends parent %}{% block pocket %}Slightly More Advanced{% endblock %}');
+			t.is("Slightly More Advanced Pocket", template.render(context));
+
+			// dojo.moduleUrl with support for more variables.
+			// This is important for HTML templates where the "shared" flag will be important.
+			context.parent = {
+				url: dojo.moduleUrl("dojox.dtl.tests.templates", "pocket.html")
+			}
+			template = new dd.Template('{% extends parent %}{% block pocket %}Super{% endblock %}');
+			t.is("Super Pocket", template.render(context));
+		},
+		function test_tag_block(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				parent: dojo.moduleUrl("dojox.dtl.tests.templates", "pocket2.html"),
+				items: ["apple", "banana", "lemon" ]
+			});
+
+			var template = new dd.Template("{% extends parent %}{% block pocket %}My {{ item }}{% endblock %}");
+			t.is("(My apple) (My banana) (My lemon) Pocket", template.render(context));
+		},
+		function test_tag_block_super(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				parent: dojo.moduleUrl("dojox.dtl.tests.templates", "pocket2.html"),
+				items: ["apple", "banana", "lemon" ]
+			});
+
+			var template = new dd.Template("{% extends parent %}{% block pocket %}My {{ item }} {{ block.super }}{% endblock %}");
+			t.is("(My apple Hot) (My banana Hot) (My lemon Hot) Pocket", template.render(context));
+		},
+		function test_tag_comment(t){
+			var dd = dojox.dtl;
+
+			var template = new dd.Template('Hot{% comment %}<strong>Make me disappear</strong>{% endcomment %} Pocket');
+			t.is("Hot Pocket", template.render());
+
+			var found = false;
+			try{
+				template = new dd.Template('Hot{% comment %}<strong>Make me disappear</strong> Pocket');
+			}catch(e){
+				t.is("Unclosed tag found when looking for endcomment", e.message);
+				found = true;
+			}
+			t.t(found);
+		},
+		function test_tag_cycle(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				items: ["apple", "banana", "lemon"],
+				unplugged: "Torrey"
+			});
+			var template = new dd.Template("{% for item in items %}{% cycle 'Hot' 'Diarrhea' unplugged 'Extra' %} Pocket. {% endfor %}");
+			t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
+			// Make sure that it doesn't break on re-render
+			t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
+
+			// Test repeating the loop
+			context.items.push("guava", "mango", "pineapple");
+			t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. Extra Pocket. Hot Pocket. Diarrhea Pocket. ", template.render(context));
+
+			// Repeat the above tests for the old style
+			// ========================================
+			context.items = context.items.slice(0, 3);
+			template = new dd.Template("{% for item in items %}{% cycle Hot,Diarrhea,Torrey,Extra %} Pocket. {% endfor %}");
+			t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
+			// Make sure that it doesn't break on re-render
+			t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
+
+			// Test repeating the loop
+			context.items.push("guava", "mango", "pineapple");
+			t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. Extra Pocket. Hot Pocket. Diarrhea Pocket. ", template.render(context));
+
+			// Now test outside of the for loop
+			// ================================
+			context = new dojox.dtl.Context({ unplugged: "Torrey" });
+			template = new dd.Template("{% cycle 'Hot' 'Diarrhea' unplugged 'Extra' as steakum %} Pocket. {% cycle steakum %} Pocket. {% cycle steakum %} Pocket.");
+			t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket.", template.render(context));
+
+			template = new dd.Template("{% cycle 'Hot' 'Diarrhea' unplugged 'Extra' as steakum %} Pocket. {% cycle steakum %} Pocket. {% cycle steakum %} Pocket. {% cycle steakum %} Pocket. {% cycle steakum %} Pocket. {% cycle steakum %} Pocket.");
+			t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. Extra Pocket. Hot Pocket. Diarrhea Pocket.", template.render(context));
+//t.t(false)
+			// Test for nested objects
+			context.items = {
+				list: ["apple", "banana", "lemon"]
+			};
+			template = new dd.Template("{% for item in items.list %}{% cycle 'Hot' 'Diarrhea' unplugged 'Extra' %} Pocket. {% endfor %}");
+			t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
+			// Make sure that it doesn't break on re-render
+			t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
+		},
+		function test_tag_debug(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				items: ["apple", "banana", "lemon"],
+				unplugged: "Torrey"
+			});
+			var template = new dd.Template("{% debug %}");
+			t.is('[items: object]\n[unplugged: string]\n', template.render(context));
+		},
+		function test_tag_filter(t){
+			var dd = dojox.dtl;
+
+			var template = new dd.Template('{% filter lower|center:"15" %}Hot Pocket{% endfilter %}');
+			t.is("  hot pocket   ", template.render());
+		},
+		function test_tag_firstof(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				found: "unicorn"
+			});
+
+			var template = new dd.Template("{% firstof one two three four found %}");
+			t.is("unicorn", template.render(context));
+
+			context.four = null;
+			t.is("null", template.render(context));
+
+			context.three = false;
+			t.is("false", template.render(context));
+		},
+		function test_tag_for(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				items: ["apple", "banana", "lemon"]
+			});
+			var template = new dd.Template("{% for item in items %}<li>{{ item }}</li>{% endfor %}");
+			t.is("<li>apple</li><li>banana</li><li>lemon</li>", template.render(context));
+
+			template = new dd.Template("{% for item in items reversed %}<li>{{ item }}</li>{% endfor %}");
+			t.is("<li>lemon</li><li>banana</li><li>apple</li>", template.render(context));
+
+			context.items = {
+				apple: "Red Delicious",
+				banana: "Cavendish",
+				lemon: "Citrus"
+			};
+			template = new dd.Template("{% for key, value in items.items %}<li>{{ value }} {{ key|title }}</li>{% endfor %}");
+			t.is("<li>Red Delicious Apple</li><li>Cavendish Banana</li><li>Citrus Lemon</li>", template.render(context));
+
+			// The same thing above, but using "zipped" sets
+			context.items = [
+				["apple", "Red Delicious", 1.99],
+				["banana", "Cavendish", 0.49],
+				["lemon", "Citrus", 0.29]
+			];
+			template = new dd.Template("{% for fruit, type, price in items %}<li>{{ type }} {{ fruit|title }} costs ${{ price}}</li>{% endfor %}");
+			t.is("<li>Red Delicious Apple costs $1.99</li><li>Cavendish Banana costs $0.49</li><li>Citrus Lemon costs $0.29</li>", template.render(context));
+
+			template = new dd.Template("{% for fruit, type, price in items reversed %}<li>{{ type }} {{ fruit|title }} costs ${{ price}}</li>{% endfor %}");
+			t.is("<li>Citrus Lemon costs $0.29</li><li>Cavendish Banana costs $0.49</li><li>Red Delicious Apple costs $1.99</li>", template.render(context));
+
+			// Now to create some errors
+			var found = false;
+			try {
+				template = new dd.Template("{% for item initems %}<li>{{ item }}</li>{% endfor %}");
+			}catch(e){
+				found = true;
+				t.is("'for' statements should have at least four words: for item initems", e.message);
+			}
+			t.t(found);
+
+			found = false;
+			try {
+				template = new dd.Template("{% for item ni items %}<li>{{ item }}</li>{% endfor %}");
+			}catch(e){
+				found = true;
+				t.is("'for' tag received an invalid argument: for item ni items", e.message);
+			}
+			t.t(found);
+
+			found = false;
+			try {
+				template = new dd.Template("{% for my item in items %}<li>{{ item }}</li>{% endfor %}");
+			}catch(e){
+				found = true;
+				t.is("'for' tag received an invalid argument: for my item in items", e.message);
+			}
+			t.t(found);
+		},
+		function test_tag_if(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				jokes: {
+					hot_pockets: true,
+					unicycles: true,
+					bacon: true
+				}
+			});
+			var template = new dd.Template("Comedian is {% if jokes.hot_pockets and jokes.unicycles and jokes.bacon %}funny{% else %}not funny{% endif %}");
+			t.is("Comedian is funny", template.render(context));
+
+			context.jokes.unicycles = false;
+			t.is("Comedian is not funny", template.render(context));
+
+			context.comedians = {
+				hedberg: true,
+				gaffigan: true,
+				cook: true
+			};
+			template = new dd.Template("Show will be {% if comedians.hedberg or comedians.gaffigan %}worth seeing{% else %}not worth seeing{% endif %}");
+			t.is("Show will be worth seeing", template.render(context));
+
+			// NOTE: "and" is implied by nesting. eg {% if sunny %}{% if windy %}It's Sunny and Windy{% endif %}{% endif %}
+			// Not mixing ands and ors allows for MUCH faster rendering
+			template = new dd.Template("Show will {% if comedians.hedberg or comedians.gaffigan %}{% if comedians.cook %}not {% endif %}be worth seeing{% else %}not be worth seeing{% endif %}");
+			t.is("Show will not be worth seeing", template.render(context));
+
+			context.comedians.cook = false;
+			t.is("Show will be worth seeing", template.render(context));
+
+			template = new dd.Template("Show will be {% if comedians.hedberg and comedians.gaffigan and not comedians.cook %}AWESOME{% else %}almost awesome{% endif %}");
+			t.is("Show will be AWESOME", template.render(context));
+
+			context.comedians.cook = true;
+			t.is("Show will be almost awesome", template.render(context));
+
+			// Now we test for errors.
+			var found = false;
+			try {
+				template = new dd.Template("Show will be {% if comedians.hedberg or comedians.gaffigan and not comedians.cook %}worth seeing{% else %}not worth seeing{% endif %}");
+			}catch(e){
+				found = true;
+				t.is("'if' tags can't mix 'and' and 'or'", e.message);
+			}
+			t.t(found);
+		},
+		function test_tag_ifchanged(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				year: 2008,
+				days: [
+					new Date(2008, 0, 12),
+					new Date(2008, 0, 28),
+					new Date(2008, 1, 1),
+					new Date(2008, 1, 1),
+					new Date(2008, 1, 1)
+				]
+			});
+
+			var template = new dd.Template("<h1>Archive for {{ year }}</h1>"+
+"{% for date in days %}"+
+'{% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}'+
+'<a href="{{ date|date:\'M/d\'|lower }}/">{{ date|date:\'j\' }}</a>'+
+"{% endfor %}");
+			t.is('<h1>Archive for 2008</h1>'+
+'<h3>January</h3>'+
+'<a href="jan/12/">12</a>'+
+'<a href="jan/28/">28</a>'+
+'<h3>February</h3>'+
+'<a href="feb/01/">1</a>'+
+'<a href="feb/01/">1</a>'+
+'<a href="feb/01/">1</a>', template.render(context));
+
+			template = new dd.Template('{% for date in days %}'+
+'{% ifchanged date.date %} {{ date.date }} {% endifchanged %}'+
+'{% ifchanged date.hour date.date %}'+
+'{{ date.hour }}'+
+'{% endifchanged %}'+
+'{% endfor %}');
+			t.is(' 2008-01-12 0 2008-01-28 0 2008-02-01 0', template.render(context));
+		},
+		function test_tag_ifequal(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				user: {
+					id: 314
+				},
+				comment: {
+					user_id: 314
+				}
+			});
+
+			var template = new dd.Template("{% ifequal user.id comment.user_id %}You posted this{% endifequal %}");
+			t.is("You posted this", template.render(context));
+
+			context.user.id = 313;
+			t.is("", template.render(context));
+
+			// Errors
+			var found = false;
+			try {
+				template = new dd.Template("{% ifequal user.id %}You posted this{% endifequal %}");
+			}catch(e){
+				found = true;
+				t.is("ifequal takes two arguments", e.message);
+			}
+			t.t(found);
+
+			found = false;
+			try {
+				template = new dd.Template("{% ifequal user.id comment.user_id %}You posted this{% endif %}");
+			}catch(e){
+				found = true;
+				t.is("No tag found for endif", e.message);
+			}
+			t.t(found);
+
+			template = new dd.Template('{% ifequal empty "" %}empty{% endifequal %}');
+			doh.is('empty', template.render());
+		},
+		function test_tag_ifnotequal(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				favorite: "hedberg",
+				comedian: "cook"
+			});
+
+			var template = new dd.Template("{% ifnotequal favorite comedian %}Not your favorite{% else %}Your favorite{% endifnotequal %}");
+			t.is("Not your favorite", template.render(context));
+
+			context.comedian = "hedberg";
+			t.is("Your favorite", template.render(context));
+		},
+		function test_tag_include(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				hello: dojo.moduleUrl("dojox.dtl.tests.templates", "hello.html"),
+				person: "Bob",
+				people: ["Charles", "Ralph", "Julia"]
+			});
+
+			var template = new dd.Template("{% include hello %}");
+			t.is("Hello, <span>Bob</span>", template.render(context));
+
+			template = new dd.Template('{% include "../../dojox/dtl/tests/templates/hello.html" %}');
+			t.is("Hello, <span>Bob</span>", template.render(context));
+
+			template = new dd.Template('{% for person in people %}{% include hello %} {% endfor %}');
+			t.is("Hello, <span>Charles</span> Hello, <span>Ralph</span> Hello, <span>Julia</span> ", template.render(context));
+		},
+		function test_tag_load(t){
+			t.f(dojox.dtl.tests.text.load);
+			new dojox.dtl.Template("{% load dojox.dtl.tests.text.load %}");
+			t.t(dojox.dtl.tests.text.load);
+		},
+		function test_tag_now(t){
+			var dd = dojox.dtl;
+
+			var template = new dd.Template('It is {% now "jS F Y H:i" %}');
+			t.t(template.render().match(/^It is \d{1,2}[a-z]{2} [A-Z][a-z]+ [0-9]{4,} \d{2}:\d{2}$/));
+
+			template = new dd.Template('It is the {% now "jS \\o\\f F" %}');
+			t.t(template.render().match(/^It is the \d{1,2}[a-z]{2} of [A-Z][a-z]+$/));
+
+			template = new dd.Template("It is the {% now 'jS \\o\\f F' %}");
+			t.t(template.render().match(/^It is the \d{1,2}[a-z]{2} of [A-Z][a-z]+$/));
+
+			var found = false;
+			try{
+				template = new dd.Template("It is the {% now 'jS \\o\\f F %}");
+			}catch(e){
+				found = true;
+				t.is("'now' statement takes one argument", e.message);
+			}
+			t.t(found);
+
+			found = false;
+			try{
+				template = new dd.Template('It is the {% now "jS \\o\\f F %}');
+			}catch(e){
+				found = true;
+				t.is("'now' statement takes one argument", e.message);
+			}
+			t.t(found);
+		},
+		function test_tag_regroup(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				people: [
+					{ firstName: "Bill", lastName: "Clinton", gender: "Male" },
+					{ firstName: "Margaret", lastName: "Thatcher", gender: "Female" },
+					{ firstName: "Path", lastName: "Smith", gender: "Unkown" },
+					{ firstName: "Condoleezza", lastName: "Rice", gender: "Female" },
+					{ firstName: "George", lastName: "Bush", gender: "Male" }
+				]
+			});
+
+			var template = new dd.Template("{% regroup people|dictsort:'gender' by gender as grouped %}<ul>{% for group in grouped %}<li>{{ group.grouper }}<ul>{% for item in group.list %}<li>{{ item.firstName }} {{ item.lastName }}</li>{% endfor %}</ul></li>{% endfor %}</ul>");
+			t.t(template.render(context).match(new RegExp("^<ul><li>Female<ul><li>(Condoleezza Rice|Margaret Thatcher)</li><li>(Condoleezza Rice|Margaret Thatcher)</li></ul></li><li>Male<ul><li>(Bill Clinton|George Bush)</li><li>(Bill Clinton|George Bush)</li></ul></li><li>Unkown<ul><li>Path Smith</li></ul></li></ul>$")));
+		},
+		function test_tag_spaceless(t){
+			var dd = dojox.dtl;
+
+			var template = new dd.Template("{% spaceless %}<ul> \n <li>Hot</li> \n\n<li>Pocket </li>\n </ul>{% endspaceless %}");
+			t.is("<ul><li>Hot</li><li>Pocket </li></ul>", template.render());
+		},
+		function test_tag_ssi(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				hello: dojo.moduleUrl("dojox.dtl.tests.templates", "hello.html"),
+				person: "Bob",
+				people: ["Charles", "Ralph", "Julia"]
+			});
+
+			var template = new dd.Template("{% ssi hello parsed %}");
+			t.is("Hello, <span>Bob</span>", template.render(context));
+
+			template = new dd.Template("{% ssi hello %}");
+			t.is("Hello, <span>{{ person }}</span>", template.render(context));
+
+			template = new dd.Template('{% ssi "../../dojox/dtl/tests/templates/hello.html" parsed %}');
+			t.is("Hello, <span>Bob</span>", template.render(context));
+
+			template = new dd.Template('{% for person in people %}{% ssi hello parsed %} {% endfor %}');
+			t.is("Hello, <span>Charles</span> Hello, <span>Ralph</span> Hello, <span>Julia</span> ", template.render(context));
+		},
+		function test_tag_templatetag(t){
+			var dd = dojox.dtl;
+
+			var template = new dd.Template("{% templatetag openblock %}");
+			t.is("{%", template.render());
+			template = new dd.Template("{% templatetag closeblock %}");
+			t.is("%}", template.render());
+			template = new dd.Template("{% templatetag openvariable %}");
+			t.is("{{", template.render());
+			template = new dd.Template("{% templatetag closevariable %}");
+			t.is("}}", template.render());
+			template = new dd.Template("{% templatetag openbrace %}");
+			t.is("{", template.render());
+			template = new dd.Template("{% templatetag closebrace %}");
+			t.is("}", template.render());
+			template = new dd.Template("{% templatetag opencomment %}");
+			t.is("{#", template.render());
+			template = new dd.Template("{% templatetag closecomment %}");
+			t.is("#}", template.render());
+		},
+		function test_tag_widthratio(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				this_value: 175,
+				max_value: 200
+			});
+
+			var template = new dd.Template('<img src="bar.gif" height="10" width="{% widthratio this_value max_value 100 %}" />');
+			t.is('<img src="bar.gif" height="10" width="88" />', template.render(context));
+		},
+		function test_tag_with(t){
+			var dd = dojox.dtl;
+
+			var context = new dd.Context({
+				person: {
+					someSqlMethod: function(){
+						return 4815162342;
+					}
+				}
+			});
+
+			var template = new dd.Template('{% with person.someSqlMethod as total %}{{ total }} object{{ total|pluralize }}{% endwith %}')
+			t.is("4815162342 objects", template.render(context));
+		}
+	]
+);
\ No newline at end of file
diff --git a/dojox/dtl/utils/date.js b/dojox/dtl/utils/date.js
index aecdcb7..a2b6f70 100644
--- a/dojox/dtl/utils/date.js
+++ b/dojox/dtl/utils/date.js
@@ -1,59 +1,72 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.dtl.utils.date"]){
-dojo._hasResource["dojox.dtl.utils.date"]=true;
 dojo.provide("dojox.dtl.utils.date");
+
 dojo.require("dojox.date.php");
-dojox.dtl.utils.date.DateFormat=function(_1){
-dojox.date.php.DateFormat.call(this,_1);
-};
-dojo.extend(dojox.dtl.utils.date.DateFormat,dojox.date.php.DateFormat.prototype,{f:function(){
-return (!this.date.getMinutes())?this.g():this.g()+":"+this.i();
-},N:function(){
-return dojox.dtl.utils.date._months_ap[this.date.getMonth()];
-},P:function(){
-if(!this.date.getMinutes()&&!this.date.getHours()){
-return "midnight";
-}
-if(!this.date.getMinutes()&&this.date.getHours()==12){
-return "noon";
-}
-return this.f()+" "+this.a();
-}});
-dojo.mixin(dojox.dtl.utils.date,{format:function(_2,_3){
-var df=new dojox.dtl.utils.date.DateFormat(_3);
-return df.format(_2);
-},timesince:function(d,_4){
-if(!(d instanceof Date)){
-d=new Date(d.year,d.month,d.day);
-}
-if(!_4){
-_4=new Date();
-}
-var _5=Math.abs(_4.getTime()-d.getTime());
-for(var i=0,_6;_6=dojox.dtl.utils.date._chunks[i];i++){
-var _7=Math.floor(_5/_6[0]);
-if(_7){
-break;
-}
-}
-return _7+" "+_6[1](_7);
-},_chunks:[[60*60*24*365*1000,function(n){
-return (n==1)?"year":"years";
-}],[60*60*24*30*1000,function(n){
-return (n==1)?"month":"months";
-}],[60*60*24*7*1000,function(n){
-return (n==1)?"week":"weeks";
-}],[60*60*24*1000,function(n){
-return (n==1)?"day":"days";
-}],[60*60*1000,function(n){
-return (n==1)?"hour":"hours";
-}],[60*1000,function(n){
-return (n==1)?"minute":"minutes";
-}]],_months_ap:["Jan.","Feb.","March","April","May","June","July","Aug.","Sept.","Oct.","Nov.","Dec."]});
+
+dojox.dtl.utils.date.DateFormat = function(/*String*/ format){
+	dojox.date.php.DateFormat.call(this, format);
 }
+dojo.extend(dojox.dtl.utils.date.DateFormat, dojox.date.php.DateFormat.prototype, {
+	f: function(){
+		// summary:
+		//		Time, in 12-hour hours and minutes, with minutes left off if they're zero.
+		// description: 
+		//		Examples: '1', '1:30', '2:05', '2'
+		//		Proprietary extension.
+		return (!this.date.getMinutes()) ? this.g() : this.g() + ":" + this.i();
+	},
+	N: function(){
+		// summary: Month abbreviation in Associated Press style. Proprietary extension.
+		return dojox.dtl.utils.date._months_ap[this.date.getMonth()];
+	},
+	P: function(){
+		// summary:
+		//		Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off
+		//		if they're zero and the strings 'midnight' and 'noon' if appropriate.
+		// description:
+		//		Examples: '1 a.m.', '1:30 p.m.', 'midnight', 'noon', '12:30 p.m.'
+		//		Proprietary extension.
+		if(!this.date.getMinutes() && !this.date.getHours()){
+			return 'midnight';
+		}
+		if(!this.date.getMinutes() && this.date.getHours() == 12){
+			return 'noon';
+		}
+		return this.f() + " " + this.a();
+	}
+});
+
+dojo.mixin(dojox.dtl.utils.date, {
+	format: function(/*Date*/ date, /*String*/ format){
+		var df = new dojox.dtl.utils.date.DateFormat(format);
+		return df.format(date);
+	},
+	timesince: function(d, now){
+		// summary:
+		//		Takes two datetime objects and returns the time between then and now
+		//		as a nicely formatted string, e.g "10 minutes"
+		// description:
+		//		Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
+		if(!(d instanceof Date)){
+			d = new Date(d.year, d.month, d.day);
+		}
+		if(!now){
+			now = new Date();
+		}
+
+		var delta = Math.abs(now.getTime() - d.getTime());
+		for(var i = 0, chunk; chunk = dojox.dtl.utils.date._chunks[i]; i++){
+			var count = Math.floor(delta / chunk[0]);
+			if(count) break;
+		}
+		return count + " " + chunk[1](count);
+	},
+	_chunks: [
+		[60 * 60 * 24 * 365 * 1000, function(n){ return (n == 1) ? 'year' : 'years'; }],
+		[60 * 60 * 24 * 30 * 1000, function(n){ return (n == 1) ? 'month' : 'months'; }],
+		[60 * 60 * 24 * 7 * 1000, function(n){ return (n == 1) ? 'week' : 'weeks'; }],
+		[60 * 60 * 24 * 1000, function(n){ return (n == 1) ? 'day' : 'days'; }],
+		[60 * 60 * 1000, function(n){ return (n == 1) ? 'hour' : 'hours'; }],
+		[60 * 1000, function(n){ return (n == 1) ? 'minute' : 'minutes'; }]
+	],
+	_months_ap: ["Jan.", "Feb.", "March", "April", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec."]
+});
\ No newline at end of file
diff --git a/dojox/editor/README b/dojox/editor/README
index fa5616e..71619a9 100644
--- a/dojox/editor/README
+++ b/dojox/editor/README
@@ -11,8 +11,13 @@ Credits
 	Mike Wilcox 	 - Author
 	Jared Jurkiewicz - Author (PrettyPrint, PageBreak, ShowBlockNodes, 
 		Preview, Save, ToolbarLineBreak, InsertEntity, 
-		NormalizeIndentOutdent, Breadcrumb, FindReplace)
+		NormalizeIndentOutdent, Breadcrumb, FindReplace, 
+		CollapsibleToolbar, Blockquote, PasteFromWord, InsertAnchor,
+		TextColor, NormalizeStyle, StatusBar)
 	Dustin Machi 	 - Technical Assistance
+	David Schwartz and Gu Yi He (IBM) - Contributed enhancements to the
+		look and feel of FindReplace, as well as behavioral
+		improvements.
 -------------------------------------------------------------------------------
 Project description
 
@@ -94,12 +99,51 @@ dojox.editor.plugins.FindReplace:
 	support.  This is new and has been tested, but not extensively.  Therefore it is currently 
 	classed as experimental.
 
+dojox.editor.plugins.CollapsibleToolbar:
+	Status: Supported (Stable).
+	A plugin that modified the header node of the editor so that it is 'collapsible'.  Meaning that
+	it can be closed (reduced), and reopened.  Useful for increasing editor real-estate.
+
+dojox.editor.plugins.Blockquote:
+	Status: Supported (Stable).
+	A plugin that puts a button on the toolbar that allows users to select text for a semantic 
+	'blockquote' tag-wrap action.  It toggles on and off during state changes to determine if
+	the current section is contained within a blockquote.
+
+dojox.editor.plugins.PasteFromWord:
+	Status: Beta (unsupported).
+	A plugin that puts a button that opens a dialog to paste in content from Word and similar
+	programs like wordpad.  It will then filter out extraneous and bad html from the content
+	before injecting it into the RTE.   Experimental as the filter list may not be complete yet.
+	Feedback is welcome and appreciated.  Filters will be updated based on it.
+
+dojox.editor.plugins.InsertAnchor:
+	Status: Stable (supported).
+	A plugin that allows anchor points to be inserted into the document being edited.
+	The anchors are styled in the doc to make them easily visible/editable in the document.
+
+dojox.editor.plugins.TextColor:
+	Status: Experimental (unsupported).
+	A plugin that makes use of the dojox.widget.ColorPicker widget in lieu of the
+	dijit.ColorPalette.  
+
+dojox.editor.plugins.NormalizeStyle:
+	Status: Experimental (unsupported).
+	A plugin that tries to normalize the output from the editor as either CSS styled or semantic (<b>, <i>, etc)
+	style.
+
+dojox.editor.plugins.StatusBar:
+	Status: Experimental (unsupported).
+	A plugin that adds a status bar and an optional resize handle to the footer of the editor.
+
 -------------------------------------------------------------------------------
 Dependencies:
 
 dijit
 dojox.form
 dojox.html.format
+dojox.widget.ColorPicker
+dojox.layout.ResizeHandle
 
 -------------------------------------------------------------------------------
 Documentation
@@ -118,6 +162,13 @@ See also:
 	http://docs.dojocampus.org/dojox/editor/plugins/NormalizeIndentOutdent
 	http://docs.dojocampus.org/dojox/editor/plugins/Breadcrumb
         http://docs.dojocampus.org/dojox/editor/plugins/FindReplace
+        http://docs.dojocampus.org/dojox/editor/plugins/CollapsibleToolbar
+	http://docs.dojocampus.org/dojox/editor/plugins/Blockquote
+	http://docs.dojocampus.org/dojox/editor/plugins/PasteFromWord
+	http://docs.dojocampus.org/dojox/editor/plugins/InsertAnchor       
+	http://docs.dojocampus.org/dojox/editor/plugins/TextColor
+	http://docs.dojocampus.org/dojox/editor/plugins/NormalizeStyle
+	http://docs.dojocampus.org/dojox/editor/plugins/StatusBar 
 
 -------------------------------------------------------------------------------
 Plugin Installation instructions
@@ -172,7 +223,6 @@ For the InsertEntity plugin:
 	and CSS:
 	<link href="[path]dojox/editor/plugins/resources/css/InsertEntity.css" type="text/css" rel="stylesheet" />
 
-
 For the NormalizeIndentOutdent plugin:
 	dojo.require("dojox.editor.plugins.NormalizeIndentOutdent");
 	and CSS:
@@ -188,6 +238,41 @@ For the FindReplace plugin:
 	and CSS:
 	<link href="[path]dojox/editor/plugins/resources/css/FindReplace.css" type="text/css" rel="stylesheet" />
 
+For the CollapsibleToolbar plugin:
+	dojo.require("dojox.editor.plugins.CollapsibleToolbar");
+	and CSS:
+	<link href="[path]dojox/editor/plugins/resources/css/CollapsibleToolbar.css" type="text/css" rel="stylesheet" />
+
+For the Blockquote plugin:
+	dojo.require("dojox.editor.plugins.Blockquote");
+	and CSS:
+	<link href="[path]dojox/editor/plugins/resources/css/Blockquote.css" type="text/css" rel="stylesheet" />
+
+For the PasteFromWord plugin:
+	dojo.require("dojox.editor.plugins.PasteFromWord");
+	and CSS:
+	<link href="[path]dojox/editor/plugins/resources/css/PasteFromWord.css" type="text/css" rel="stylesheet" />
+
+For the InsertAnchor plugin:
+        dojo.require("dojox.editor.plugins.InsertAnchor");
+        and CSS:
+        <link href="[path]dojox/editor/plugins/resources/css/InsertAnchor.css" type="text/css" rel="stylesheet" />
+
+For the TextColor plugin:
+	dojo.require("dojox.editor.plugins.TextColor");
+	and CSS:
+	<link href="[path]dojox/editor/plugins/resources/css/TextColor.css" type="text/css" rel="stylesheet" />
+
+For the NormalizeStyle plugin:
+	dojo.require("dojox.editor.plugins.NormalizeStyle");
+	and CSS:
+	No CSS required.
+
+For the StatusBar plugin:
+        dojo.require("dojox.editor.plugins.StatusBar");
+        and CSS:
+        <link href="[path]dojox/editor/plugins/resources/css/StatusBar.css" type="text/css" rel="stylesheet" />
+
 See tests for examples:
 	dojox/editor/tests/editorTablePlugs.html
 	dojox/editor/tests/editorUploadPlug.html
@@ -201,3 +286,11 @@ See tests for examples:
 	dojox/editor/tests/editorNormalizeIndentOutdent.html
 	dojox/editor/tests/editorBreadcrumb.html
 	dojox/editor/tests/editorFindReplace.html
+	dojox/editor/tests/editorCollapsibleToolbar.html
+	dojox/editor/tests/editorBlockquote.html
+	dojox/editor/tests/editorPasteFromWord.html
+	dojox/editor/tests/editorInsertAnchor.html
+	dojox/editor/tests/editorTextColor.html
+	dojox/editor/tests/editorNormalizeStyle.html
+	dojox/editor/tests/editorStatusBar.html
+	dojox/editor/tests/testPluginsAll.html
diff --git a/dojox/editor/plugins/Blockquote.js b/dojox/editor/plugins/Blockquote.js
new file mode 100755
index 0000000..69e55a1
--- /dev/null
+++ b/dojox/editor/plugins/Blockquote.js
@@ -0,0 +1,506 @@
+dojo.provide("dojox.editor.plugins.Blockquote");
+
+dojo.require("dijit._editor._Plugin");
+dojo.require("dijit.form.Button");
+dojo.require("dojo.i18n");
+
+dojo.requireLocalization("dojox.editor.plugins", "Blockquote");
+
+dojo.declare("dojox.editor.plugins.Blockquote",dijit._editor._Plugin,{
+	//	summary:
+	//		This plugin provides Blockquote cabability to the editor. 
+	//		window/tab
+
+	// iconClassPrefix: [const] String
+	//		The CSS class name for the button node icon.
+	iconClassPrefix: "dijitAdditionalEditorIcon",
+
+	_initButton: function(){
+		// summary:
+		//		Over-ride for creation of the preview button.
+		this._nlsResources = dojo.i18n.getLocalization("dojox.editor.plugins", "Blockquote");
+		this.button = new dijit.form.ToggleButton({
+			label: this._nlsResources["blockquote"],
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "Blockquote",
+			tabIndex: "-1",
+			onClick: dojo.hitch(this, "_toggleQuote")
+		});
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._initButton();
+		this.connect(this.editor, "onNormalizedDisplayChanged", "updateState");
+		// We need the custom undo code since we manipulate the dom
+		// outside of the browser natives and only customUndo really handles 
+		// that.  It will incur a performance hit, but should hopefully be
+		// relatively small.  
+		editor.customUndo = true;
+	},
+
+	_toggleQuote: function(arg){
+		// summary:
+		//		Function to trigger previewing of the editor document
+		// tags:
+		//		private
+		try{
+			var ed = this.editor;
+			ed.focus();
+
+			var quoteIt = this.button.get("checked");
+			var sel = dijit.range.getSelection(ed.window);
+			var range, elem, start, end;
+			if(sel && sel.rangeCount > 0){
+				range = sel.getRangeAt(0);
+			}
+			if(range){
+				ed.beginEditing();
+				if(quoteIt){
+					// Lets see what we've got as a selection...
+					var bq, tag;
+					if(range.startContainer === range.endContainer){
+						// No selection, just cursor point, we need to see if we're
+						// in an indentable block, or similar.
+						if(this._isRootInline(range.startContainer)){
+							// Text at the 'root' of the document, so we need to gather all of it., 
+		
+							// First, we need to find the toplevel inline element that is rooted 
+							// to the document 'editNode'
+							start = range.startContainer;
+							while(start && start.parentNode !== ed.editNode){
+								start = start.parentNode;
+							}
+							// Now we need to walk up its siblings and look for the first one in the rooting
+							// that isn't inline or text, as we want to grab all of that for indent.
+							while(start && start.previousSibling && (
+									this._isTextElement(start) || 
+									(start.nodeType === 1 && 
+									 this._isInlineFormat(this._getTagName(start))
+								))){
+								start = start.previousSibling;
+							}
+							if(start && start.nodeType === 1 && 
+							   !this._isInlineFormat(this._getTagName(start))){
+								// Adjust slightly, we're one node too far back in this case.
+								start = start.nextSibling;
+							}
+		
+							// Okay, we have a configured start, lets grab everything following it that's 
+							// inline and make it part of the blockquote!
+							if(start){
+								bq = ed.document.createElement("blockquote");
+								dojo.place(bq, start, "after");
+								bq.appendChild(start);
+								end = bq.nextSibling;
+								while(end && (
+									this._isTextElement(end) ||
+									(end.nodeType === 1 && 
+										this._isInlineFormat(this._getTagName(end)))
+									)){
+									// Add it. 
+									bq.appendChild(end);
+									end = bq.nextSibling;
+								}
+							}
+						}else{
+							// Figure out what to do when not root inline....
+							var node = range.startContainer;
+							while ((this._isTextElement(node) || 
+									this._isInlineFormat(this._getTagName(node))
+									|| this._getTagName(node) === "li") && 
+								node !== ed.editNode && node !== ed.document.body){
+								node = node.parentNode;
+							}
+							if(node !== ed.editNode && node !==	node.ownerDocument.documentElement){
+								bq = ed.document.createElement("blockquote");
+								dojo.place(bq, node, "after");
+								bq.appendChild(node);
+							}
+						}
+						if(bq){
+							dojo.withGlobal(ed.window, 
+								"selectElementChildren", dijit._editor.selection, [bq]);
+							dojo.withGlobal(ed.window, 
+								"collapse", dijit._editor.selection, [true]);
+						}
+					}else{
+						var curNode;
+						// multi-node select.  We need to scan over them.
+						// Find the two containing nodes at start and end.
+						// then move the end one node past.  Then ... lets see
+						// what we can blockquote!
+						start = range.startContainer;
+						end = range.endContainer;
+						// Find the non-text nodes.
+
+						while(start && this._isTextElement(start) && start.parentNode !== ed.editNode){
+							start = start.parentNode;
+						}
+
+						// Try to find the end node.  We have to check the selection junk
+						curNode = start;
+						while(curNode.nextSibling && dojo.withGlobal(ed.window, 
+							"inSelection", dijit._editor.selection, [curNode])){
+							curNode = curNode.nextSibling;
+						}
+						end = curNode; 
+						if(end === ed.editNode || end === ed.document.body){
+							// Unable to determine real selection end, so just make it 
+							// a single node indent of start + all following inline styles, if
+							// present, then just exit.
+							bq = ed.document.createElement("blockquote");
+							dojo.place(bq, start, "after");
+							tag = this._getTagName(start);
+							if(this._isTextElement(start) || this._isInlineFormat(tag)){
+								// inline element or textnode
+								// Find and move all inline tags following the one we inserted also into the 
+								// blockquote so we don't split up content funny.
+								var next = start;
+								while(next && (
+									this._isTextElement(next) ||
+									(next.nodeType === 1 &&
+									this._isInlineFormat(this._getTagName(next))))){
+									bq.appendChild(next);
+									next = bq.nextSibling;
+								}
+							}else{
+								bq.appendChild(start);
+							}
+							return;
+						}
+
+						// Has a definite end somewhere, so lets try to blockquote up to it.
+						// requires looking at the selections and in some cases, moving nodes
+						// into separate blockquotes.
+						end = end.nextSibling;
+						curNode = start;
+						while(curNode && curNode !== end){
+							if(curNode.nodeType === 1){
+								tag = this._getTagName(curNode);
+								if(tag !== "br"){
+									if(!window.getSelection){
+										// IE sometimes inserts blank P tags, which we want to skip 
+										// as they end up blockquoted, which messes up layout.
+										if(tag === "p" && this._isEmpty(curNode)){
+											curNode = curNode.nextSibling;
+											continue;
+										}
+									}
+									if(this._isInlineFormat(tag)){
+										// inline tag.
+										if(!bq){
+											bq = ed.document.createElement("blockquote");
+											dojo.place(bq, curNode, "after");
+											bq.appendChild(curNode);
+										}else{
+											bq.appendChild(curNode);
+										}
+										curNode = bq;
+									}else{
+										if(bq){
+											if(this._isEmpty(bq)){
+												bq.parentNode.removeChild(bq);
+											}
+										}
+										bq = ed.document.createElement("blockquote");
+										dojo.place(bq, curNode, "after");
+										bq.appendChild(curNode);
+										curNode = bq;
+									}
+								}
+							}else if(this._isTextElement(curNode)){
+								if(!bq){
+									bq = ed.document.createElement("blockquote");
+									dojo.place(bq, curNode, "after");
+									bq.appendChild(curNode);
+								}else{
+									bq.appendChild(curNode);
+								}
+								curNode = bq;
+							}
+							curNode = curNode.nextSibling;
+						}
+						// Okay, check the last bq, remove it if no content.
+						if(bq){
+							if(this._isEmpty(bq)){
+								bq.parentNode.removeChild(bq);
+							}else{
+								dojo.withGlobal(ed.window, 
+									"selectElementChildren", dijit._editor.selection, [bq]);
+								dojo.withGlobal(ed.window, 
+									"collapse", dijit._editor.selection, [true]);
+							}
+							bq = null;
+						}
+					}
+				}else{
+					var found = false;
+					if(range.startContainer === range.endContainer){
+						elem = range.endContainer;
+						// Okay, now see if we can find one of the formatting types we're in.
+						while(elem && elem !== ed.editNode && elem !== ed.document.body){
+							var tg = elem.tagName?elem.tagName.toLowerCase():"";
+							if(tg === "blockquote"){
+								found = true;
+								break;
+							}
+							elem = elem.parentNode;
+						}
+						if(found){
+							var lastChild;
+							while(elem.firstChild){
+								lastChild = elem.firstChild;
+								dojo.place(lastChild, elem, "before");
+							}
+							elem.parentNode.removeChild(elem);
+							if(lastChild){
+								dojo.withGlobal(ed.window, 
+									"selectElementChildren", dijit._editor.selection, [lastChild]);
+								dojo.withGlobal(ed.window, 
+									"collapse", dijit._editor.selection, [true]);
+							}
+						}
+					}else{
+						// Multi-select!  Gotta find all the blockquotes contained within the selection area.
+						start = range.startContainer;
+						end = range.endContainer;
+						while(start && this._isTextElement(start) && start.parentNode !== ed.editNode){
+							start = start.parentNode;
+						}
+						var selectedNodes = [];
+						var cNode = start;
+						while(cNode && cNode.nextSibling && dojo.withGlobal(ed.window, 
+							"inSelection", dijit._editor.selection, [cNode])){
+							if(cNode.parentNode && this._getTagName(cNode.parentNode) === "blockquote"){
+								cNode = cNode.parentNode;
+							}
+							selectedNodes.push(cNode);
+							cNode = cNode.nextSibling;
+						}
+						
+						// Find all the blocknodes now that we know the selection area.
+						var bnNodes = this._findBlockQuotes(selectedNodes);
+						while(bnNodes.length){
+							var bn = bnNodes.pop();
+							if(bn.parentNode){
+								// Make sure we haven't seen this before and removed it.
+								while(bn.firstChild){
+									dojo.place(bn.firstChild, bn, "before");
+								}
+								bn.parentNode.removeChild(bn);
+							}
+						}
+					}
+				}
+				ed.endEditing();
+			}
+			ed.onNormalizedDisplayChanged();
+		}catch(e){ /* Squelch */ }
+	},
+
+	updateState: function(){
+		// summary:
+		//		Overrides _Plugin.updateState().  This controls whether or not the current
+		//		cursor position should toggle on the quote button or not.
+		// tags:
+		//		protected
+		var ed = this.editor;
+		if(!ed || !ed.isLoaded){ return; }
+		if(this.button){
+			// Some browsers (WebKit) doesn't actually get the tag info right.
+			// So ... lets check it manually.
+			var elem;
+			var found = false;
+			
+			// Try to find the ansestor element (and see if it is blockquote)
+			var sel = dijit.range.getSelection(ed.window);
+			if(sel && sel.rangeCount > 0){
+				var range = sel.getRangeAt(0);
+				if(range){
+					elem = range.endContainer;
+				}
+			}
+			// Okay, now see if we can find one of the formatting types we're in.
+			while(elem && elem !== ed.editNode && elem !== ed.document){
+				var tg = elem.tagName?elem.tagName.toLowerCase():"";
+				if(tg === "blockquote"){
+					found = true;
+					break;
+				}
+				elem = elem.parentNode;
+			}
+			// toggle whether or not the current selection is blockquoted.
+			this.button.set("checked", found);
+		}
+	},
+
+	_findBlockQuotes: function(nodeList){
+		// summary:
+		//		function to find a ll the blocknode elements in a collection of
+		//		nodes
+		// nodeList:
+		//		The list of nodes.
+		// tags:
+		//		private
+		var bnList = [];
+		if(nodeList){
+			var i;
+			for(i = 0; i < nodeList.length; i++){
+				var node = nodeList[i];
+				if(node.nodeType === 1){
+					if(this._getTagName(node) === "blockquote"){
+						bnList.push(node);   
+					}
+					if(node.childNodes && node.childNodes.length > 0){
+						bnList = bnList.concat(this._findBlockQuotes(node.childNodes));
+					}
+				}
+			}
+		}
+		return bnList;
+	},
+
+	/*****************************************************************/
+	/* Functions borrowed from NormalizeIndentOutdent                */
+	/*****************************************************************/
+
+	_getTagName: function(node){
+		// summary:
+		//		Internal function to get the tag name of an element
+		//		if any.
+		// node:
+		//		The node to look at.
+		// tags:
+		//		private
+		var tag = "";
+		if(node && node.nodeType === 1){
+			tag = node.tagName?node.tagName.toLowerCase():"";
+		}
+		return tag;
+	},
+
+	_isRootInline: function(node){
+		// summary:
+		//		This functions tests whether an indicated node is in root as inline
+		//		or rooted inline elements in the page.
+		// node:
+		//		The node to start at.
+		// tags:
+		//		private
+		var ed = this.editor;
+		if(this._isTextElement(node) && node.parentNode === ed.editNode){
+			return true;
+		}else if(node.nodeType === 1 && this._isInlineFormat(node) && node.parentNode === ed.editNode){
+			return true;
+		}else if(this._isTextElement(node) && this._isInlineFormat(this._getTagName(node.parentNode))){
+			node = node.parentNode;
+			while(node && node !== ed.editNode && this._isInlineFormat(this._getTagName(node))){
+				node = node.parentNode;
+			}
+			if(node === ed.editNode){
+				return true;
+			}
+		}
+		return false;
+	},
+
+	_isTextElement: function(node){
+		// summary:
+		//		Helper function to check for text nodes.
+		// node:
+		//		The node to check.
+		// tags:
+		//		private
+		if(node && node.nodeType === 3 || node.nodeType === 4){
+			return true;
+		}
+		return false;
+	},
+
+	_isEmpty: function(node){
+		// summary:
+		//		Internal function to determine if a node is 'empty'
+		//		Eg, contains only blank text.  Used to determine if
+		//		an empty list element should be removed or not.
+		// node:
+		//		The node to check.
+		// tags:
+		//		private
+		if(node.childNodes){
+			var empty = true;
+			var i;
+			for(i = 0; i < node.childNodes.length; i++){
+				var n = node.childNodes[i];
+				if(n.nodeType === 1){
+					if(this._getTagName(n) === "p"){
+						if(!dojo.trim(n.innerHTML)){
+							continue;	
+						}
+					}
+					empty = false;
+					break;
+				}else if(this._isTextElement(n)){
+					// Check for empty text.
+					var nv = dojo.trim(n.nodeValue);
+					if(nv && nv !==" " && nv !== "\u00A0"){
+						empty = false;
+						break;
+					}
+				}else{
+					empty = false;
+					break;
+				}
+			}
+			return empty;
+		}else{
+			return true;
+		}
+	},
+
+	_isInlineFormat: function(tag){
+		// summary:
+		//		Function to determine if the current tag is an inline
+		//		element that does formatting, as we don't want to 
+		//		break/indent around it, as it can screw up text.
+		// tag:
+		//		The tag to examine
+		// tags:
+		//		private
+		switch(tag){
+			case "a":
+			case "b":
+			case "strong":
+			case "s":
+			case "strike":
+			case "i":
+			case "u":
+			case "em":
+			case "sup":
+			case "sub":
+			case "span":
+			case "font":
+			case "big":
+			case "cite":
+			case "q":
+			case "img":
+			case "small":
+				return true;
+			default:
+				return false;
+		}
+	}
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "blockquote"){
+		o.plugin = new dojox.editor.plugins.Blockquote({});
+	}
+});
diff --git a/dojox/editor/plugins/Breadcrumb.js b/dojox/editor/plugins/Breadcrumb.js
old mode 100644
new mode 100755
index a35d2cf..6df3b71
--- a/dojox/editor/plugins/Breadcrumb.js
+++ b/dojox/editor/plugins/Breadcrumb.js
@@ -1,13 +1,5 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.Breadcrumb"]){
-dojo._hasResource["dojox.editor.plugins.Breadcrumb"]=true;
 dojo.provide("dojox.editor.plugins.Breadcrumb");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit._editor.range");
 dojo.require("dojo.i18n");
@@ -18,218 +10,338 @@ dojo.require("dijit._editor.selection");
 dojo.require("dijit.Menu");
 dojo.require("dijit.MenuItem");
 dojo.require("dijit.MenuSeparator");
+
 dojo.experimental("dojox.editor.plugins.Breadcrumb");
-dojo.requireLocalization("dojox.editor.plugins","Breadcrumb",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,zh,zh-tw");
-dojo.declare("dojox.editor.plugins._BreadcrumbMenuTitle",[dijit._Widget,dijit._Templated,dijit._Contained],{templateString:"<tr><td dojoAttachPoint=\"title\" colspan=\"4\" class=\"dijitToolbar\" style=\"font-weight: bold; padding: 3px;\"></td></tr>",menuTitle:"",postCreate:function(){
-dojo.setSelectable(this.domNode,false);
-var _1=this.id+"_text";
-dijit.setWaiState(this.domNode,"labelledby",_1);
-},_setMenuTitleAttr:function(_2){
-this.title.innerHTML=_2;
-},_getMenuTitleAttr:function(_3){
-return this.title.innerHTML;
-}});
-dojo.declare("dojox.editor.plugins.Breadcrumb",dijit._editor._Plugin,{_menu:null,breadcrumbBar:null,setEditor:function(_4){
-this.editor=_4;
-this._buttons=[];
-this.breadcrumbBar=new dijit.Toolbar();
-dojo.style(this.breadcrumbBar.domNode,"height","1.5em");
-var _5=dojo.i18n.getLocalization("dojox.editor.plugins","Breadcrumb");
-this._titleTemplate=_5.nodeActions;
-dojo.place(this.breadcrumbBar.domNode,this.editor.iframe,"after");
-this.editor.onLoadDeferred.addCallback(dojo.hitch(this,function(){
-this._menu=new dijit.Menu({});
-dojo.addClass(this.breadcrumbBar.domNode,"dojoxEditorBreadcrumbArrow");
-var _6=this;
-var _7=new dijit.form.ComboButton({showLabel:true,label:"body",_selNode:_4.editNode,dropDown:this._menu,onClick:dojo.hitch(this,function(){
-this._menuTarget=_4.editNode;
-this._selectContents();
-})});
-this._menuTitle=new dojox.editor.plugins._BreadcrumbMenuTitle({menuTitle:_5.nodeActions});
-this._selCMenu=new dijit.MenuItem({label:_5.selectContents,onClick:dojo.hitch(this,this._selectContents)});
-this._delCMenu=new dijit.MenuItem({label:_5.deleteContents,onClick:dojo.hitch(this,this._deleteContents)});
-this._selEMenu=new dijit.MenuItem({label:_5.selectElement,onClick:dojo.hitch(this,this._selectElement)});
-this._delEMenu=new dijit.MenuItem({label:_5.deleteElement,onClick:dojo.hitch(this,this._deleteElement)});
-this._moveSMenu=new dijit.MenuItem({label:_5.moveStart,onClick:dojo.hitch(this,this._moveCToStart)});
-this._moveEMenu=new dijit.MenuItem({label:_5.moveEnd,onClick:dojo.hitch(this,this._moveCToEnd)});
-this._menu.addChild(this._menuTitle);
-this._menu.addChild(this._selCMenu);
-this._menu.addChild(this._delCMenu);
-this._menu.addChild(new dijit.MenuSeparator({}));
-this._menu.addChild(this._selEMenu);
-this._menu.addChild(this._delEMenu);
-this._menu.addChild(new dijit.MenuSeparator({}));
-this._menu.addChild(this._moveSMenu);
-this._menu.addChild(this._moveEMenu);
-_7._ddConnect=dojo.connect(_7,"openDropDown",dojo.hitch(this,function(){
-this._menuTarget=_7._selNode;
-this._menuTitle.attr("menuTitle",dojo.string.substitute(this._titleTemplate,{"nodeName":"<body>"}));
-this._selEMenu.attr("disabled",true);
-this._delEMenu.attr("disabled",true);
-this._selCMenu.attr("disabled",false);
-this._delCMenu.attr("disabled",false);
-this._moveSMenu.attr("disabled",false);
-this._moveEMenu.attr("disabled",false);
-}));
-this.breadcrumbBar.addChild(_7);
-this.connect(this.editor,"onNormalizedDisplayChanged","updateState");
-}));
-this.breadcrumbBar.startup();
-},_selectContents:function(){
-this.editor.focus();
-if(this._menuTarget){
-var _8=this._menuTarget.tagName.toLowerCase();
-switch(_8){
-case "br":
-case "hr":
-case "img":
-case "input":
-case "base":
-case "meta":
-case "area":
-case "basefont":
-break;
-default:
-try{
-dojo.withGlobal(this.editor.window,"collapse",dijit._editor.selection,[null]);
-dojo.withGlobal(this.editor.window,"selectElementChildren",dijit._editor.selection,[this._menuTarget]);
-this.editor.onDisplayChanged();
-}
-catch(e){
-}
-}
-}
-},_deleteContents:function(){
-if(this._menuTarget){
-this.editor.beginEditing();
-this._selectContents();
-dojo.withGlobal(this.editor.window,"remove",dijit._editor.selection,[this._menuTarget]);
-this.editor.endEditing();
-this._updateBreadcrumb();
-this.editor.onDisplayChanged();
-}
-},_selectElement:function(){
-this.editor.focus();
-if(this._menuTarget){
-dojo.withGlobal(this.editor.window,"collapse",dijit._editor.selection,[null]);
-dojo.withGlobal(this.editor.window,"selectElement",dijit._editor.selection,[this._menuTarget]);
-this.editor.onDisplayChanged();
-}
-},_deleteElement:function(){
-if(this._menuTarget){
-this.editor.beginEditing();
-this._selectElement();
-dojo.withGlobal(this.editor.window,"remove",dijit._editor.selection,[this._menuTarget]);
-this.editor.endEditing();
-this._updateBreadcrumb();
-this.editor.onDisplayChanged();
-}
-},_moveCToStart:function(){
-this.editor.focus();
-if(this._menuTarget){
-this._selectContents();
-dojo.withGlobal(this.editor.window,"collapse",dijit._editor.selection,[true]);
-}
-},_moveCToEnd:function(){
-this.editor.focus();
-if(this._menuTarget){
-this._selectContents();
-dojo.withGlobal(this.editor.window,"collapse",dijit._editor.selection,[false]);
-}
-},_updateBreadcrumb:function(){
-var ed=this.editor;
-if(ed.window){
-var _9=dijit.range.getSelection(ed.window);
-if(_9&&_9.rangeCount>0){
-var _a=_9.getRangeAt(0);
-var _b=dojo.withGlobal(ed.window,"getSelectedElement",dijit._editor.selection)||_a.startContainer;
-var _c=[];
-if(_b&&_b.ownerDocument===ed.document){
-while(_b&&_b!==ed.editNode){
-if(_b.nodeType===1){
-_c.push({type:_b.tagName.toLowerCase(),node:_b});
-}
-_b=_b.parentNode;
-}
-_c=_c.reverse();
-while(this._buttons.length){
-var db=this._buttons.pop();
-dojo.disconnect(db._ddConnect);
-this.breadcrumbBar.removeChild(db);
-}
-this._buttons=[];
-var i;
-var _d=this;
-for(i=0;i<_c.length;i++){
-var bc=_c[i];
-var b=new dijit.form.ComboButton({showLabel:true,label:bc.type,_selNode:bc.node,dropDown:this._menu,onClick:function(){
-_d._menuTarget=this._selNode;
-_d._selectContents();
-}});
-b._ddConnect=dojo.connect(b,"openDropDown",dojo.hitch(b,function(){
-_d._menuTarget=this._selNode;
-var _e=_d._menuTarget.tagName.toLowerCase();
-var _f=dojo.string.substitute(_d._titleTemplate,{"nodeName":"<"+_e+">"});
-_d._menuTitle.attr("menuTitle",_f);
-switch(_e){
-case "br":
-case "hr":
-case "img":
-case "input":
-case "base":
-case "meta":
-case "area":
-case "basefont":
-_d._selCMenu.attr("disabled",true);
-_d._delCMenu.attr("disabled",true);
-_d._moveSMenu.attr("disabled",true);
-_d._moveEMenu.attr("disabled",true);
-_d._selEMenu.attr("disabled",false);
-_d._delEMenu.attr("disabled",false);
-break;
-default:
-_d._selCMenu.attr("disabled",false);
-_d._delCMenu.attr("disabled",false);
-_d._selEMenu.attr("disabled",false);
-_d._delEMenu.attr("disabled",false);
-_d._moveSMenu.attr("disabled",false);
-_d._moveEMenu.attr("disabled",false);
-}
-}));
-this._buttons.push(b);
-this.breadcrumbBar.addChild(b);
-}
-if(dojo.isIE){
-this.breadcrumbBar.domNode.className=this.breadcrumbBar.domNode.className;
-}
-}
-}
-}
-},updateState:function(){
-if(dojo.style(this.editor.iframe,"display")==="none"){
-dojo.style(this.breadcrumbBar.domNode,"display","none");
-}else{
-if(dojo.style(this.breadcrumbBar.domNode,"display")==="none"){
-dojo.style(this.breadcrumbBar.domNode,"display","block");
-}
-this._updateBreadcrumb();
-}
-},destroy:function(){
-if(this.breadcrumbBar){
-this.breadcrumbBar.destroy();
-this.breadcrumbBar=null;
-}
-this._buttons=null;
-delete this.editor.breadcrumbBar;
-this.inherited(arguments);
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _10=o.args.name.toLowerCase();
-if(_10==="breadcrumb"){
-o.plugin=new dojox.editor.plugins.Breadcrumb({});
-}
+
+dojo.requireLocalization("dojox.editor.plugins", "Breadcrumb");
+
+dojo.declare("dojox.editor.plugins._BreadcrumbMenuTitle",[dijit._Widget, dijit._Templated, dijit._Contained],{
+	// summary:
+	//		SImple internal, non-clickable, menu entry to act as a menu title bar.
+	templateString: "<tr><td dojoAttachPoint=\"title\" colspan=\"4\" class=\"dijitToolbar\" style=\"font-weight: bold; padding: 3px;\"></td></tr>",
+
+	menuTitle: "",
+
+	postCreate: function(){
+		dojo.setSelectable(this.domNode, false);
+		var label = this.id+"_text";
+		dijit.setWaiState(this.domNode, "labelledby", label);
+	},
+
+	_setMenuTitleAttr: function(str){
+		this.title.innerHTML = str;
+	},
+	_getMenuTitleAttr: function(str){
+		return this.title.innerHTML;
+	}
+});
+
+
+dojo.declare("dojox.editor.plugins.Breadcrumb",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides Breadcrumb cabability to the editor.  When 
+	//		As you move around the editor, it updates with your current indention 
+	//		depth.
+
+	//	_menu: [private]
+	//		The popup menu that is displayed.
+	_menu: null,
+
+	//	breadcrumbBar: [protected]
+	//		The toolbar containing the breadcrumb.
+	breadcrumbBar: null,
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._buttons = [];
+		this.breadcrumbBar = new dijit.Toolbar();
+        
+		var strings = dojo.i18n.getLocalization("dojox.editor.plugins", "Breadcrumb");
+		this._titleTemplate = strings.nodeActions;
+
+		dojo.place(this.breadcrumbBar.domNode, editor.footer);
+		this.editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){
+			this._menu = new dijit.Menu({});
+			dojo.addClass(this.breadcrumbBar.domNode, "dojoxEditorBreadcrumbArrow");
+			var self = this;
+			var body = new dijit.form.ComboButton({
+				showLabel: true,
+				label: "body",
+				_selNode: editor.editNode,
+				dropDown: this._menu,
+				onClick: dojo.hitch(this, function(){
+					this._menuTarget = editor.editNode;
+					this._selectContents();
+				})
+			});
+			
+			// Build the menu
+			this._menuTitle = new dojox.editor.plugins._BreadcrumbMenuTitle({menuTitle: strings.nodeActions});
+			this._selCMenu = new dijit.MenuItem({label: strings.selectContents, onClick: dojo.hitch(this, this._selectContents)});
+			this._delCMenu = new dijit.MenuItem({label: strings.deleteContents, onClick: dojo.hitch(this, this._deleteContents)});
+			this._selEMenu = new dijit.MenuItem({label: strings.selectElement, onClick: dojo.hitch(this, this._selectElement)});
+			this._delEMenu = new dijit.MenuItem({label: strings.deleteElement, onClick: dojo.hitch(this, this._deleteElement)});
+			this._moveSMenu = new dijit.MenuItem({label: strings.moveStart, onClick: dojo.hitch(this, this._moveCToStart)});
+			this._moveEMenu = new dijit.MenuItem({label: strings.moveEnd, onClick: dojo.hitch(this, this._moveCToEnd)});
+
+			this._menu.addChild(this._menuTitle); 
+			this._menu.addChild(this._selCMenu); 
+			this._menu.addChild(this._delCMenu); 
+			this._menu.addChild(new dijit.MenuSeparator({})); 
+			this._menu.addChild(this._selEMenu); 
+			this._menu.addChild(this._delEMenu); 
+			this._menu.addChild(new dijit.MenuSeparator({})); 
+			this._menu.addChild(this._moveSMenu); 
+			this._menu.addChild(this._moveEMenu);
+
+			body._ddConnect = dojo.connect(body, "openDropDown", dojo.hitch(this, function(){
+				this._menuTarget = body._selNode;
+				this._menuTitle.set("menuTitle", dojo.string.substitute(this._titleTemplate,{
+						"nodeName": "<body>"
+				}));
+				this._selEMenu.set("disabled", true);
+				this._delEMenu.set("disabled", true);
+				this._selCMenu.set("disabled", false);
+				this._delCMenu.set("disabled", false);
+				this._moveSMenu.set("disabled", false);
+				this._moveEMenu.set("disabled", false);
+			}));
+			this.breadcrumbBar.addChild(body);
+			this.connect(this.editor, "onNormalizedDisplayChanged", "updateState");
+		}));
+		this.breadcrumbBar.startup();
+		if(dojo.isIE){
+			// Sometimes IE will mess up layout and needs to be poked.
+            setTimeout(dojo.hitch(this, function(){this.breadcrumbBar.domNode.className = this.breadcrumbBar.domNode.className;}), 100);
+		}
+	},
+
+	_selectContents: function(){
+		// summary:
+		//		Internal function for selecting the contents of a node.
+		this.editor.focus();
+		if(this._menuTarget){
+			var nodeName = this._menuTarget.tagName.toLowerCase();
+			switch(nodeName){
+				case 'br':
+				case 'hr':
+				case 'img':
+				case 'input':
+				case 'base':
+				case 'meta':
+				case 'area':
+				case 'basefont':
+						break;
+				default: 
+					try{
+						dojo.withGlobal(this.editor.window, 
+							"collapse", dijit._editor.selection, [null]);
+						dojo.withGlobal(this.editor.window, 
+							"selectElementChildren", dijit._editor.selection, [this._menuTarget]);
+						this.editor.onDisplayChanged();
+					}catch(e){/*squelch*/}
+			}
+		}
+	},
+
+	_deleteContents: function(){
+		// summary:
+		//		Internal function for selecting the contents of a node.
+		if(this._menuTarget){
+			this.editor.beginEditing();
+			this._selectContents();
+			dojo.withGlobal(this.editor.window, 
+				"remove", dijit._editor.selection, [this._menuTarget]);
+			this.editor.endEditing();
+			this._updateBreadcrumb();
+			this.editor.onDisplayChanged();
+		}
+	},
+
+	_selectElement: function(){
+		// summary:
+		//		Internal function for selecting the contents of a node.
+		this.editor.focus();
+		if(this._menuTarget){
+			dojo.withGlobal(this.editor.window, 
+				"collapse", dijit._editor.selection, [null]);
+			dojo.withGlobal(this.editor.window, 
+				"selectElement", dijit._editor.selection, [this._menuTarget]);
+			this.editor.onDisplayChanged();
+			
+		}
+	},
+
+	_deleteElement: function(){
+		// summary:
+		//		Internal function for selecting the contents of a node.
+		if(this._menuTarget){
+			this.editor.beginEditing();
+			this._selectElement();
+			dojo.withGlobal(this.editor.window, 
+				"remove", dijit._editor.selection, [this._menuTarget]);
+			this.editor.endEditing();
+			this._updateBreadcrumb();
+			this.editor.onDisplayChanged();
+		}
+	},
+
+	_moveCToStart: function(){
+		// summary:
+		//		Internal function for selecting the contents of a node.
+		this.editor.focus();
+		if(this._menuTarget){
+			this._selectContents();
+			dojo.withGlobal(this.editor.window, 
+				"collapse", dijit._editor.selection, [true]);
+		}
+	},
+
+	_moveCToEnd: function(){
+		// summary:
+		//		Internal function for selecting the contents of a node.
+		this.editor.focus();
+		if(this._menuTarget){
+			this._selectContents();
+			dojo.withGlobal(this.editor.window, 
+				"collapse", dijit._editor.selection, [false]);
+		}
+	},
+
+	_updateBreadcrumb: function(){
+		// summary:
+		//		Function to trigger updating of the breadcrumb
+		// tags:
+		//		private
+		var ed = this.editor;
+		if(ed.window){
+			var sel = dijit.range.getSelection(ed.window);
+			if(sel && sel.rangeCount > 0){
+				var range = sel.getRangeAt(0);
+                
+				// Check the getSelectedElement call.  Needed when dealing with img tags.
+				var node = dojo.withGlobal(ed.window, 
+					"getSelectedElement", dijit._editor.selection) || range.startContainer;
+				//var node = range.startContainer;
+				var bcList = [];
+
+				// Make sure we get a selection within the editor document,
+				// have seen cases on IE where this wasn't true.
+				if(node && node.ownerDocument === ed.document){
+					while(node && node !== ed.editNode && node != ed.document.body && node != ed.document){
+						if(node.nodeType === 1){
+							bcList.push({type: node.tagName.toLowerCase(), node: node}); 
+						}
+						node = node.parentNode;
+					}
+					bcList = bcList.reverse();
+
+					while(this._buttons.length){
+						var db = this._buttons.pop();
+						dojo.disconnect(db._ddConnect);
+						this.breadcrumbBar.removeChild(db);
+					}
+					this._buttons = [];
+
+					var i;
+					var self = this;
+					for(i = 0; i < bcList.length; i++){
+						var bc = bcList[i];
+						var b = new dijit.form.ComboButton({
+							showLabel: true,
+							label: bc.type,
+							_selNode: bc.node,
+							dropDown: this._menu,
+							onClick: function(){
+								self._menuTarget = this._selNode;
+								self._selectContents();
+							}
+						});
+						b._ddConnect = dojo.connect(b, "openDropDown", dojo.hitch(b, function(){
+							self._menuTarget = this._selNode;
+							var nodeName = self._menuTarget.tagName.toLowerCase();
+							var title = dojo.string.substitute(self._titleTemplate,{
+								"nodeName": "<" + nodeName + ">"
+							});
+							self._menuTitle.set("menuTitle", title);
+							switch(nodeName){
+								case 'br':
+								case 'hr':
+								case 'img':
+								case 'input':
+								case 'base':
+								case 'meta':
+								case 'area':
+								case 'basefont':
+									self._selCMenu.set("disabled", true);
+									self._delCMenu.set("disabled", true);
+									self._moveSMenu.set("disabled", true);
+									self._moveEMenu.set("disabled", true);
+									self._selEMenu.set("disabled", false);
+									self._delEMenu.set("disabled", false);
+									break;
+								default:
+									self._selCMenu.set("disabled", false);
+									self._delCMenu.set("disabled", false);
+									self._selEMenu.set("disabled", false);
+									self._delEMenu.set("disabled", false);
+									self._moveSMenu.set("disabled", false);
+									self._moveEMenu.set("disabled", false);
+							}
+						}));
+						this._buttons.push(b);
+						this.breadcrumbBar.addChild(b);
+					}
+					if(dojo.isIE){
+						// Prod it to fix layout.
+						this.breadcrumbBar.domNode.className = this.breadcrumbBar.domNode.className;
+					}
+					
+				}
+			}
+		}
+	},
+
+	updateState: function(){
+		// summary:
+		//		Over-ride of updateState to hide the toolbar when the iframe is not visible.
+		//		Also triggers the breadcrumb update.
+		if(dojo.style(this.editor.iframe, "display") === "none"){
+			dojo.style(this.breadcrumbBar.domNode, "display", "none");
+		}else{
+			if(dojo.style(this.breadcrumbBar.domNode, "display") === "none"){
+				dojo.style(this.breadcrumbBar.domNode, "display", "block");
+			}
+			this._updateBreadcrumb();
+
+			// Some themes do padding, so we have to resize again after display.
+			var size = dojo.marginBox(this.editor.domNode);
+			this.editor.resize({h: size.h});
+		}
+	},
+
+	destroy: function(){
+		// summary:
+		//		Over-ride to clean up the breadcrumb toolbar.
+		if(this.breadcrumbBar){
+			this.breadcrumbBar.destroy();
+			this.breadcrumbBar = null;
+		}
+		this._buttons = null;
+		delete this.editor.breadcrumbBar;
+		this.inherited(arguments);
+	}
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "breadcrumb"){
+		o.plugin = new dojox.editor.plugins.Breadcrumb({});
+	}
 });
-}
diff --git a/dojox/editor/plugins/CollapsibleToolbar.js b/dojox/editor/plugins/CollapsibleToolbar.js
new file mode 100644
index 0000000..fd5df5c
--- /dev/null
+++ b/dojox/editor/plugins/CollapsibleToolbar.js
@@ -0,0 +1,174 @@
+dojo.provide("dojox.editor.plugins.CollapsibleToolbar");
+
+dojo.require("dijit._Widget")
+dojo.require("dijit._Templated");
+dojo.require("dijit._editor._Plugin");
+
+dojo.requireLocalization("dojox.editor.plugins", "CollapsibleToolbar");
+
+dojo.declare("dojox.editor.plugins._CollapsibleToolbarButton", [dijit._Widget, dijit._Templated], {
+	// summary:
+	//		Simple internal widget for representing a clickable button for expand/collapse
+	//		with A11Y support.
+	// tags:
+	//		private
+	templateString: "<div tabindex='0' role='button' title='${title}' class='${buttonClass}' " +
+		"dojoAttachEvent='ondijitclick: onClick'><span class='${textClass}'>${text}</span></div>",
+
+
+	// title [public] String
+	//		The text to read by a screen reader that gets button focus.
+	title: "",
+
+	// buttonClass [public] String
+	//		The classname to apply to the expand/collapse button.
+	buttonClass: "",
+
+	// text [public] String
+	//		The text to use as expand/collapse in A11Y mode.
+	text: "",
+	
+	// textClass [public] String
+	//		The classname to apply to the expand/collapse text.
+	textClass: "",
+
+	onClick: function(e){
+		// summary:
+		//		Simple synthetic event to listen for dijit click events (mouse or keyboard)
+	}
+});
+
+
+dojo.declare("dojox.editor.plugins.CollapsibleToolbar",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides a weappable toolbar container to allow expand/collapse
+	//		of the editor toolbars.  This plugin should be registered first in most cases to
+	//		avoid conflicts in toolbar construction.
+
+	// _myWidgets: [private] array
+	//		Container for widgets I allocate that will need to be destroyed.
+	_myWidgets: null,
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._constructContainer();
+	},
+
+	_constructContainer: function(){
+		// summary:
+		//		Internal function to construct a wrapper for the toolbar/header that allows
+		//		it to expand and collapse.  It effectively builds a containing table, 
+		//		which handles the layout nicely and gets BIDI support by default.
+		// tags:
+		//		private
+		var strings = dojo.i18n.getLocalization("dojox.editor.plugins", "CollapsibleToolbar");
+		this._myWidgets = [];
+		
+		// Build the containers.
+		var container = dojo.create("table", {style: { width: "100%" }, tabindex: -1, "class": "dojoxCollapsibleToolbarContainer"});
+		var tbody = dojo.create("tbody", {tabindex: -1}, container);
+		var row = dojo.create("tr", {tabindex: -1}, tbody);
+		var openTd = dojo.create("td", {"class": "dojoxCollapsibleToolbarControl", tabindex: -1}, row);
+		var closeTd = dojo.create("td", {"class": "dojoxCollapsibleToolbarControl",  tabindex: -1}, row);
+		var menuTd = dojo.create("td", {style: { width: "100%" }, tabindex: -1}, row);
+		var m = dojo.create("span", {style: { width: "100%" }, tabindex: -1}, menuTd);
+
+		var collapseButton = new dojox.editor.plugins._CollapsibleToolbarButton({
+			buttonClass: "dojoxCollapsibleToolbarCollapse",
+			title: strings.collapse,
+			text: "-",
+			textClass: "dojoxCollapsibleToolbarCollapseText"
+		});
+		dojo.place(collapseButton.domNode, openTd);
+		var expandButton = new dojox.editor.plugins._CollapsibleToolbarButton({
+			buttonClass: "dojoxCollapsibleToolbarExpand",
+			title: strings.expand,
+			text: "+",
+			textClass: "dojoxCollapsibleToolbarExpandText"
+		});
+		dojo.place(expandButton.domNode, closeTd);
+
+		this._myWidgets.push(collapseButton);
+		this._myWidgets.push(expandButton);
+
+		// Attach everything in now.
+		dojo.style(closeTd, "display", "none");
+		dojo.place(container, this.editor.toolbar.domNode, "after");
+		dojo.place(this.editor.toolbar.domNode, m);
+
+		this.openTd = openTd;
+		this.closeTd = closeTd;
+		this.menu = m;
+
+		// Establish the events to handle open/close.
+		this.connect(collapseButton, "onClick", "_onClose");
+		this.connect(expandButton, "onClick", "_onOpen");
+	},
+
+	_onClose: function(e){
+		// summary:
+		//		Internal function for handling a click event that will close the toolbar.
+		// e:
+		//		The click event.
+		// tags:
+		//		private
+		if(e){ dojo.stopEvent(e); }
+		var size = dojo.marginBox(this.editor.domNode);
+		dojo.style(this.openTd, "display", "none");
+		dojo.style(this.closeTd, "display", "");
+		dojo.style(this.menu, "display", "none");
+		this.editor.resize({h: size.h});
+		// work around IE rendering glitch in a11y mode.
+		if(dojo.isIE){
+			this.editor.header.className = this.editor.header.className;
+			this.editor.footer.className = this.editor.footer.className;
+		}
+		dijit.focus(this.closeTd.firstChild);
+	},
+
+	_onOpen: function(e) {
+		// summary:
+		//		Internal function for handling a click event that will open the toolbar.
+		// e:
+		//		The click event.
+		// tags:
+		//		private
+		if(e){ dojo.stopEvent(e); }
+		var size = dojo.marginBox(this.editor.domNode);
+		dojo.style(this.closeTd, "display", "none");
+		dojo.style(this.openTd, "display", "");
+		dojo.style(this.menu, "display", "");
+		this.editor.resize({h: size.h});
+		 // work around IE rendering glitch in a11y mode.
+		if(dojo.isIE){
+			this.editor.header.className = this.editor.header.className;
+			this.editor.footer.className = this.editor.footer.className;
+		}
+		dijit.focus(this.openTd.firstChild);
+	},
+
+	destroy: function(){
+		// summary:
+		//		Over-ride of destroy method for cleanup.
+		this.inherited(arguments);
+		if(this._myWidgets){
+			while(this._myWidgets.length){
+				this._myWidgets.pop().destroy();
+			}
+			delete this._myWidgets;
+		}
+	}
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "collapsibletoolbar"){
+		o.plugin = new dojox.editor.plugins.CollapsibleToolbar({});
+	}
+});
diff --git a/dojox/editor/plugins/EntityPalette.js b/dojox/editor/plugins/EntityPalette.js
old mode 100644
new mode 100755
index 88749ef..86c1b24
--- a/dojox/editor/plugins/EntityPalette.js
+++ b/dojox/editor/plugins/EntityPalette.js
@@ -1,158 +1,223 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.EntityPalette"]){
-dojo._hasResource["dojox.editor.plugins.EntityPalette"]=true;
 dojo.provide("dojox.editor.plugins.EntityPalette");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
+dojo.require("dijit._PaletteMixin");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojox.editor.plugins","latinEntities",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,zh,zh-tw");
+
+dojo.requireLocalization("dojox.editor.plugins", "latinEntities");
+
 dojo.experimental("dojox.editor.plugins.EntityPalette");
-dojo.declare("dojox.editor.plugins.EntityPalette",[dijit._Widget,dijit._Templated],{templateString:"<div class=\"dojoxEntityPalette\">\n"+"\t<table>\n"+"\t\t<tbody>\n"+"\t\t\t<tr>\n"+"\t\t\t\t<td>\n"+"\t\t\t\t\t<table class=\"dojoxEntityPaletteTable\"  waiRole=\"grid\" tabIndex=\"${tabIndex}\">\n"+"\t\t\t\t\t\t<tbody dojoAttachPoint=\"tableNode\"></tbody>\n"+"\t\t\t\t\t</table>\n"+"\t\t\t\t</td>\n"+"\t\t\t</tr>\n"+"\t\t\t<tr>\n"+"\t\t\t\t<td>\n"+"\t\t\t\t\t<table dojoAttachPoint=\"previe [...]
-if(!this._created){
-this._created=true;
-this.domNode.style.position="relative";
-this._cellNodes=[];
-this.entities={};
-this.entities[this.palette]=dojo.i18n.getLocalization("dojox.editor.plugins","latinEntities");
-var _1=this.entities[this.palette];
-var _2=0;
-var _3;
-for(_3 in _1){
-_2++;
-}
-var _4=Math.floor(Math.sqrt(_2));
-var _5=_4;
-var _6=0;
-var _7=null;
-var _8;
-dojo.style(this.codeHeader,"display",this.showCode?"":"none");
-dojo.style(this.codeNode,"display",this.showCode?"":"none");
-dojo.style(this.entityHeader,"display",this.showEntityName?"":"none");
-dojo.style(this.entityNode,"display",this.showEntityName?"":"none");
-for(_3 in _1){
-var _9=_6%_5===0;
-if(_9){
-_7=dojo.create("tr",{tabIndex:"-1"});
-}
-var _a="&"+_3+";";
-_8=dojo.create("td",{innerHTML:_a,tabIndex:"-1","class":"dojoxEntityPaletteCell"},_7);
-dojo.forEach(["Dijitclick","MouseEnter","Focus","Blur"],function(_b){
-this.connect(_8,"on"+_b.toLowerCase(),"_onCell"+_b);
-},this);
-if(_9){
-dojo.place(_7,this.tableNode);
-}
-dijit.setWaiRole(_8,"gridcell");
-_8.index=this._cellNodes.length;
-this._cellNodes.push({node:_8,html:_a});
-_6++;
-}
-var _c=_4-(_2%_4);
-while(_c>0){
-_8=dojo.create("td",{innerHTML:"",tabIndex:"-1","class":"dojoxEntityPaletteNullCell"},_7);
-_c--;
-}
-this._xDim=_4;
-this._yDim=_5;
-this.connect(this.tableNode,"onfocus","_onTableNodeFocus");
-var _d={UP_ARROW:-this._xDim,DOWN_ARROW:this._xDim,RIGHT_ARROW:1,LEFT_ARROW:-1};
-for(var _e in _d){
-this._connects.push(dijit.typematic.addKeyListener(this.domNode,{charOrCode:dojo.keys[_e],ctrlKey:false,altKey:false,shiftKey:false},this,function(){
-var _f=_d[_e];
-return function(_10){
-this._navigateByKey(_f,_10);
-};
-}(),this.timeoutChangeRate,this.defaultTimeout));
-}
-if(!this.showPreview){
-dojo.style(this.previewNode,"display","none");
-}
-}
-},focus:function(){
-this._focusFirst();
-},onChange:function(_11){
-},_focusFirst:function(){
-this._currentFocus=0;
-var _12=this._cellNodes[this._currentFocus].node;
-setTimeout(function(){
-dijit.focus(_12);
-},25);
-},_onTableNodeFocus:function(evt){
-if(evt.target===this.tableNode){
-this._focusFirst();
-}
-},_onFocus:function(){
-dojo.attr(this.tableNode,"tabIndex","-1");
-},_onBlur:function(){
-this._removeCellHighlight(this._currentFocus);
-dojo.attr(this.tableNode,"tabIndex",this.tabIndex);
-},_onCellDijitclick:function(evt){
-var _13=evt.currentTarget;
-if(this._currentFocus!=_13.index){
-this._currentFocus=_13.index;
-setTimeout(function(){
-dijit.focus(_13);
-},0);
-}
-this._selectEntity(_13);
-dojo.stopEvent(evt);
-},_onCellMouseEnter:function(evt){
-var _14=evt.currentTarget;
-this._setCurrent(_14);
-setTimeout(function(){
-dijit.focus(_14);
-},0);
-},_onCellFocus:function(evt){
-this._setCurrent(evt.currentTarget);
-},_setCurrent:function(_15){
-this._removeCellHighlight(this._currentFocus);
-this._currentFocus=_15.index;
-dojo.addClass(_15,"dojoxEntityPaletteCellHighlight");
-if(this.showPreview){
-this._displayDetails(_15);
-}
-},_displayDetails:function(_16){
-var _17=dojo.filter(this._cellNodes,function(_18){
-return _18.node==_16;
+
+dojo.declare("dojox.editor.plugins.EntityPalette",
+	[dijit._Widget, dijit._Templated, dijit._PaletteMixin],
+	{
+	// summary:
+	//		A keyboard accessible HTML entity-picking widget (for inserting symbol characters)
+	// description:
+	//		Grid showing various entities, so the user can pick a certain entity.
+	//		Can be used standalone, or as a popup.
+	//
+	// example:
+	// |	<div dojoType="dojox.editor.plugins.EntityPalette"></div>
+	//
+	// example:
+	// |	var picker = new dojox.editor.plugins.EntityPalette({ },srcNode);
+	// |	picker.startup();
+
+	// templateString: [protected] String
+	//		The basic template used to render the palette.
+	//		Should generally be over-ridden to define different classes.
+	templateString: '<div class="dojoxEntityPalette">\n' +
+					'	<table>\n' +
+					'		<tbody>\n' +
+					'			<tr>\n' +
+					'				<td>\n' +
+					'					<table class="dijitPaletteTable">\n' +
+					'						<tbody dojoAttachPoint="gridNode"></tbody>\n' +
+					'				   </table>\n' +
+					'				</td>\n' +
+					'			</tr>\n' +
+					'			<tr>\n' +
+					'				<td>\n'+
+					'					<table dojoAttachPoint="previewPane" class="dojoxEntityPalettePreviewTable">\n' +
+					'						<tbody>\n' +
+					'							<tr>\n' +
+					'								<th class="dojoxEntityPalettePreviewHeader">Preview</th>\n' +
+					'								<th class="dojoxEntityPalettePreviewHeader" dojoAttachPoint="codeHeader">Code</th>\n' +
+					'								<th class="dojoxEntityPalettePreviewHeader" dojoAttachPoint="entityHeader">Name</th>\n' +
+					'								<th class="dojoxEntityPalettePreviewHeader">Description</th>\n' +
+					'							</tr>\n' +
+					'							<tr>\n' +
+					'								<td class="dojoxEntityPalettePreviewDetailEntity" dojoAttachPoint="previewNode"></td>\n' +
+					'								<td class="dojoxEntityPalettePreviewDetail" dojoAttachPoint="codeNode"></td>\n' +
+					'								<td class="dojoxEntityPalettePreviewDetail" dojoAttachPoint="entityNode"></td>\n' +
+					'								<td class="dojoxEntityPalettePreviewDetail" dojoAttachPoint="descNode"></td>\n' +
+					'							</tr>\n' +
+					'						</tbody>\n' +
+					'					</table>\n' +
+					'				</td>\n' +
+					'			</tr>\n' +
+					'		</tbody>\n' +
+					'	</table>\n' +
+					'</div>',
+
+
+	baseClass: "dojoxEntityPalette",
+
+	// showPreview: [public] Boolean
+	//	  Whether the preview pane will be displayed, to show details about the selected entity.
+	showPreview: true,
+
+	// showCode: [public] boolean
+	//		Show the character code for the entity.
+	showCode: false,
+
+	// showentityName: [public] boolean
+	//		Show the entity name for the entity.
+	showEntityName: false,
+
+	// palette: [public] String
+	//		The symbol pallete to display.  The only current one is 'latin'.
+	palette: "latin",
+
+	dyeClass: 'dojox.editor.plugins.LatinEntity',
+
+	// domNodeClass [protected] String
+	paletteClass: 'editorLatinEntityPalette',
+
+	cellClass: "dojoxEntityPaletteCell",
+
+	postMixInProperties: function(){
+		// Convert hash of entities into two-dimensional rows/columns table (array of arrays)
+		var choices = dojo.i18n.getLocalization("dojox.editor.plugins", "latinEntities");
+		var numChoices = 0;
+		var entityKey;
+		for(entityKey in choices){numChoices++;}
+		var choicesPerRow = Math.floor(Math.sqrt(numChoices));
+		var numRows = choicesPerRow;
+		var currChoiceIdx = 0;
+		var rows = [];
+		var row = [];
+		for(entityKey in choices){
+			currChoiceIdx++;
+			row.push(entityKey);
+			if(currChoiceIdx % numRows === 0){
+				rows.push(row);
+				row = [];
+			}
+		}
+		if(row.length > 0){
+			rows.push(row);
+		}
+		this._palette = rows;
+	},
+
+	buildRendering: function(){
+		// Instantiate the template, which makes a skeleton table which we'll insert the entities
+		this.inherited(arguments);
+
+		var i18n = dojo.i18n.getLocalization("dojox.editor.plugins", "latinEntities");
+
+		this._preparePalette(
+			this._palette,
+			i18n
+		);
+
+		var cells = dojo.query(".dojoxEntityPaletteCell", this.gridNode);
+		dojo.forEach(cells, function(cellNode){
+			this.connect(cellNode, "onmouseenter", "_onCellMouseEnter");
+		}, this);
+	},
+
+	_onCellMouseEnter: function(e){
+		// summary:
+		//		Simple function to handle updating the display at the bottom of
+		//		the palette.
+		// e:
+		//		The event.
+		// tags:
+		//		private
+		this._displayDetails(e.target);
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+
+		// Show the code and entity name (if enabled to do so.)
+		dojo.style(this.codeHeader, "display", this.showCode?"":"none");
+		dojo.style(this.codeNode, "display", this.showCode?"":"none");
+		dojo.style(this.entityHeader, "display", this.showEntityName?"":"none");
+		dojo.style(this.entityNode, "display", this.showEntityName?"":"none");
+
+		if(!this.showPreview){
+			dojo.style(this.previewNode,"display","none");
+		}
+	},
+
+	_setCurrent: function(/*DOMNode*/ node){
+		// summary:
+		//		Called when a entity is hovered or focused.
+		// description:
+		//		Removes highlight of the old entity, and highlights
+		//		the new entity.
+		// tags:
+		//		protected
+		this.inherited(arguments);
+		if(this.showPreview){
+			this._displayDetails(node);
+		}
+	},
+
+	_displayDetails: function(/*DOMNode*/ cell){
+		// summary:
+		//	  Display the details of the currently focused entity in the preview pane
+		var dye = this._getDye(cell);
+		if(dye){
+			var ehtml = dye.getValue();
+			var ename = dye._alias;
+			this.previewNode.innerHTML=ehtml;
+			this.codeNode.innerHTML="&#"+parseInt(ehtml.charCodeAt(0), 10)+";";
+			this.entityNode.innerHTML="&"+ename+";";
+			var i18n = dojo.i18n.getLocalization("dojox.editor.plugins", "latinEntities");
+			this.descNode.innerHTML=i18n[ename].replace("\n", "<br>");
+
+		}else{
+			this.previewNode.innerHTML="";
+			this.codeNode.innerHTML="";
+			this.entityNode.innerHTML="";
+			this.descNode.innerHTML="";
+		}
+	}
 });
-if(_17.length>0){
-var _19=_17[0].html;
-var _1a=_19.substr(1,_19.length-2);
-this.previewNode.innerHTML=_16.innerHTML;
-this.codeNode.innerHTML="&#"+parseInt(_16.innerHTML.charCodeAt(0),10)+";";
-this.entityNode.innerHTML="&"+_1a+";";
-this.descNode.innerHTML=this.entities[this.palette][_1a].replace("\n","<br>");
-}else{
-this.previewNode.innerHTML="";
-this.codeNode.innerHTML="";
-this.entityNode.innerHTML="";
-this.descNode.innerHTML="";
-}
-},_onCellBlur:function(evt){
-this._removeCellHighlight(this._currentFocus);
-},_removeCellHighlight:function(_1b){
-dojo.removeClass(this._cellNodes[_1b].node,"dojoxEntityPaletteCellHighlight");
-},_selectEntity:function(_1c){
-var _1d=dojo.filter(this._cellNodes,function(_1e){
-return _1e.node==_1c;
+
+dojo.declare("dojox.editor.plugins.LatinEntity",
+	null,
+	{
+		// summary:
+		//		Represents a character.
+		//		Initialized using an alias for the character (like cent) rather
+		//		than with the character itself.
+
+ 		constructor: function(/*String*/ alias){
+			// summary:
+			//	 Construct JS object representing an entity (associated w/a cell
+			//		in the palette)
+			// value: String
+			//		alias name: 'cent', 'pound' ..
+			
+			this._alias = alias;
+		},
+
+		getValue: function(){
+			// summary:
+			//   Returns HTML representing the character, like &
+			//
+			return "&" + this._alias + ";";
+		},
+
+		fillCell: function(/*DOMNode*/ cell){
+			// Deal with entities that have keys which are reserved words.
+			cell.innerHTML = this.getValue();
+		}
 });
-if(_1d.length>0){
-this.onChange(this.value=_1d[0].html);
-}
-},_navigateByKey:function(_1f,_20){
-if(_20==-1){
-return;
-}
-var _21=this._currentFocus+_1f;
-if(_21<this._cellNodes.length&&_21>-1){
-var _22=this._cellNodes[_21].node;
-_22.focus();
-}
-}});
-}
diff --git a/dojox/editor/plugins/FindReplace.js b/dojox/editor/plugins/FindReplace.js
old mode 100644
new mode 100755
index 0185d99..bfbc71e
--- a/dojox/editor/plugins/FindReplace.js
+++ b/dojox/editor/plugins/FindReplace.js
@@ -1,289 +1,827 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.FindReplace"]){
-dojo._hasResource["dojox.editor.plugins.FindReplace"]=true;
 dojo.provide("dojox.editor.plugins.FindReplace");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.Toolbar");
 dojo.require("dijit.form.TextBox");
 dojo.require("dijit.form.CheckBox");
 dojo.require("dijit.form.Button");
 dojo.require("dijit.TooltipDialog");
-dojo.require("dijit.Menu");
-dojo.require("dijit.CheckedMenuItem");
 dojo.require("dojox.editor.plugins.ToolbarLineBreak");
 dojo.require("dojo.i18n");
 dojo.require("dojo.string");
-dojo.requireLocalization("dojox.editor.plugins","FindReplace",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,zh,zh-tw");
+
+dojo.requireLocalization("dojox.editor.plugins", "FindReplace");
+
 dojo.experimental("dojox.editor.plugins.FindReplace");
-dojo.declare("dojox.editor.plugins._FindReplaceTextBox",[dijit._Widget,dijit._Templated],{textId:"",label:"",widget:null,widgetsInTemplate:true,templateString:"<span style='white-space: nowrap' class='dijit dijitReset dijitInline findReplaceTextBox'>"+"<label class='dijitLeft dijitInline' for='${textId}'>${label}</label>"+"<input dojoType='dijit.form.TextBox' required=false intermediateChanges='true'"+"tabIndex='-1' id='${textId}' dojoAttachPoint='textBox' value='' style='width: 20em;'/> [...]
-this.inherited(arguments);
-this.id=dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
-this.textId=this.id+"_text";
-this.inherited(arguments);
-},postCreate:function(){
-this.textBox.attr("value","");
-this.disabled=this.textBox.attr("disabled");
-this.connect(this.textBox,"onChange","onChange");
-},_setValueAttr:function(_1){
-this.value=_1;
-this.textBox.attr("value",_1);
-},focus:function(){
-this.textBox.focus();
-},_setDisabledAttr:function(_2){
-this.disabled=_2;
-this.textBox.attr("disabled",_2);
-},onChange:function(_3){
-this.value=_3;
-}});
-dojo.declare("dojox.editor.plugins._FindReplaceCheckBox",[dijit._Widget,dijit._Templated],{checkId:"",label:"",widget:null,widgetsInTemplate:true,templateString:"<span style='white-space: nowrap' class='dijit dijitReset dijitInline findReplaceCheckBox'>"+"<input dojoType='dijit.form.CheckBox' required=false "+"tabIndex='-1' id='${checkId}' dojoAttachPoint='checkBox' value=''/>"+"<label class='dijitLeft dijitInline' for='${checkId}'>${label}</label>"+"</span>",postMixInProperties:function(){
-this.inherited(arguments);
-this.id=dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
-this.checkId=this.id+"_check";
-this.inherited(arguments);
-},postCreate:function(){
-this.checkBox.attr("checked",false);
-this.disabled=this.checkBox.attr("disabled");
-this.checkBox.isFocusable=function(){
-return false;
-};
-},_setValueAttr:function(_4){
-this.checkBox.attr("value",_4);
-},_getValueAttr:function(){
-return this.checkBox.attr("value");
-},focus:function(){
-this.checkBox.focus();
-},_setDisabledAttr:function(_5){
-this.disabled=_5;
-this.checkBox.attr("disabled",_5);
-}});
-dojo.declare("dojox.editor.plugins.FindReplace",[dijit._editor._Plugin],{buttonClass:dijit.form.ToggleButton,iconClassPrefix:"dijitAdditionalEditorIcon",_initButton:function(){
-var _6=dojo.i18n.getLocalization("dojox.editor.plugins","FindReplace");
-this.button=new dijit.form.ToggleButton({label:_6["findReplace"],showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"FindReplace",tabIndex:"-1",onChange:dojo.hitch(this,"_toggleFindReplace")});
-if(dojo.isOpera){
-this.button.attr("disabled",true);
-}
-this.connect(this.button,"attr",dojo.hitch(this,function(_7,_8){
-if(_7==="disabled"){
-this._toggleFindReplace((!_8&&this._displayed),true);
-}
-}));
-},setEditor:function(_9){
-this.editor=_9;
-this._initButton();
-},toggle:function(){
-this.button.attr("checked",!this.button.attr("checked"));
-},_toggleFindReplace:function(_a,_b){
-if(_a&&!dojo.isOpera){
-dojo.style(this._frToolbar.domNode,"display","block");
-if(!_b){
-this._displayed=true;
-}
-}else{
-dojo.style(this._frToolbar.domNode,"display","none");
-if(!_b){
-this._displayed=false;
-}
-}
-this.editor.resize();
-},setToolbar:function(_c){
-this.inherited(arguments);
-if(!dojo.isOpera){
-var _d=dojo.i18n.getLocalization("dojox.editor.plugins","FindReplace");
-this._frToolbar=new dijit.Toolbar();
-dojo.style(this._frToolbar.domNode,"display","none");
-dojo.place(this._frToolbar.domNode,_c.domNode,"after");
-this._frToolbar.startup();
-this._caseSensitive=new dojox.editor.plugins._FindReplaceCheckBox({label:_d["matchCase"]});
-this._backwards=new dojox.editor.plugins._FindReplaceCheckBox({label:_d["backwards"]});
-this._replaceAll=new dojox.editor.plugins._FindReplaceCheckBox({label:_d["replaceAll"]});
-this._findField=new dojox.editor.plugins._FindReplaceTextBox({label:_d.findLabel});
-this._frToolbar.addChild(this._findField);
-this._findButton=new dijit.form.Button({label:_d["findButton"],showLabel:true,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"FindRun"});
-this._frToolbar.addChild(this._findButton);
-this._frToolbar.addChild(this._caseSensitive);
-this._frToolbar.addChild(this._backwards);
-this._frToolbar.addChild(new dojox.editor.plugins._ToolbarLineBreak());
-this._replaceField=new dojox.editor.plugins._FindReplaceTextBox({label:_d.replaceLabel});
-this._frToolbar.addChild(this._replaceField);
-this._replaceButton=new dijit.form.Button({label:_d["replaceButton"],showLabel:true,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"ReplaceRun"});
-this._frToolbar.addChild(this._replaceButton);
-this._frToolbar.addChild(this._replaceAll);
-this._findButton.attr("disabled",true);
-this._replaceButton.attr("disabled",true);
-this.connect(this._findField,"onChange","_checkButtons");
-this.connect(this._replaceField,"onChange","_checkButtons");
-this.connect(this._findButton,"onClick","_find");
-this.connect(this._replaceButton,"onClick","_replace");
-this._replDialog=new dijit.TooltipDialog();
-this._replDialog.startup();
-this._replDialog.attr("content","");
-this._dialogTemplate=_d.replaceDialogText;
-}
-},_checkButtons:function(){
-var _e=this._findField.attr("value");
-var _f=this._replaceField.attr("value");
-if(_e){
-this._findButton.attr("disabled",false);
-}else{
-this._findButton.attr("disabled",true);
-}
-if(_e&&_f&&_e!==_f){
-this._replaceButton.attr("disabled",false);
-}else{
-this._replaceButton.attr("disabled",true);
-}
-},_find:function(){
-var txt=this._findField.attr("value");
-if(txt){
-var _10=this._caseSensitive.attr("value");
-var _11=this._backwards.attr("value");
-return this._findText(txt,_10,_11);
-}
-return false;
-},_replace:function(){
-var ed=this.editor;
-ed.focus();
-var txt=this._findField.attr("value");
-var _12=this._replaceField.attr("value");
-var _13=0;
-if(txt){
-if(this._replaceDialogTimeout){
-clearTimeout(this._replaceDialogTimeout);
-this._replaceDialogTimeout=null;
-dijit.popup.close(this._replDialog);
-}
-var _14=this._replaceAll.attr("value");
-var _15=this._caseSensitive.attr("value");
-var _16=this._backwards.attr("value");
-var _17=dojo.withGlobal(ed.window,"getSelectedText",dijit._editor.selection,[null]);
-if(dojo.isMoz){
-txt=dojo.trim(txt);
-_17=dojo.trim(_17);
-}
-var _18=this._filterRegexp(txt,!_15);
-if(_17&&_18.test(_17)){
-ed.execCommand("inserthtml",_12);
-_13++;
-}
-if(_14){
-var _19=this._findText(txt,_15,_16);
-var _1a=function(){
-ed.execCommand("inserthtml",_12);
-_13++;
-_19=this._findText(txt,_15,_16);
-if(_19){
-setTimeout(dojo.hitch(this,_1a),10);
-}else{
-this._replDialog.attr("content",dojo.string.substitute(this._dialogTemplate,{"0":""+_13}));
-dijit.popup.open({popup:this._replDialog,around:this._replaceButton.domNode});
-this._replaceDialogTimeout=setTimeout(dojo.hitch(this,function(){
-clearTimeout(this._replaceDialogTimeout);
-this._replaceDialogTimeout=null;
-dijit.popup.close(this._replDialog);
-}),5000);
-}
-};
-if(_19){
-var _1b=dojo.hitch(this,_1a);
-_1b();
-}
-}
-}
-},_findText:function(txt,_1c,_1d){
-var ed=this.editor;
-var win=ed.window;
-var _1e=false;
-if(txt){
-if(win.find){
-_1e=win.find(txt,_1c,_1d,false,false,false,false);
-}else{
-var doc=ed.document;
-if(doc.selection){
-this.editor.focus();
-var _1f=doc.body.createTextRange();
-var _20=doc.selection?doc.selection.createRange():null;
-if(_20){
-if(_1d){
-_1f.setEndPoint("EndToStart",_20);
-}else{
-_1f.setEndPoint("StartToEnd",_20);
-}
-}
-var _21=_1c?4:0;
-if(_1d){
-_21=_21|1;
-}
-_1e=_1f.findText(txt,null,_21);
-if(_1e){
-_1f.select();
-}
-}
-}
-}
-return _1e;
-},_filterRegexp:function(_22,_23){
-var rxp="";
-var c=null;
-for(var i=0;i<_22.length;i++){
-c=_22.charAt(i);
-switch(c){
-case "\\":
-rxp+=c;
-i++;
-rxp+=_22.charAt(i);
-break;
-case "$":
-case "^":
-case "/":
-case "+":
-case ".":
-case "|":
-case "(":
-case ")":
-case "{":
-case "}":
-case "[":
-case "]":
-rxp+="\\";
-default:
-rxp+=c;
-}
-}
-rxp="^"+rxp+"$";
-if(_23){
-return new RegExp(rxp,"mi");
-}else{
-return new RegExp(rxp,"m");
-}
-},destroy:function(){
-this.inherited(arguments);
-if(this._replaceDialogTimeout){
-clearTimeout(this._replaceDialogTimeout);
-this._replaceDialogTimeout=null;
-dijit.popup.close(this._replDialog);
-}
-if(this._frToolbar){
-this._frToolbar.destroyRecursive();
-this._frToolbar=null;
-}
-if(this._replDialog){
-this._replDialog.destroyRecursive();
-this._replDialog=null;
-}
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _24=o.args.name.toLowerCase();
-if(_24==="findreplace"){
-o.plugin=new dojox.editor.plugins.FindReplace({});
-}
+
+dojo.declare("dojox.editor.plugins._FindReplaceCloseBox", [dijit._Widget, dijit._Templated], {
+	// summary:
+	//		Base class for widgets that contains a button labeled X
+	//		to close the tool bar.
+	
+	btnId: "",
+	widget: null,
+	widgetsInTemplate: true,
+	
+	templateString:
+		"<span style='float: right' class='dijitInline' tabindex='-1'>" +
+			"<button class='dijit dijitReset dijitInline' " +
+				"id='${btnId}' dojoAttachPoint='button' dojoType='dijit.form.Button' tabindex='-1' iconClass='dijitEditorIconsFindReplaceClose' showLabel='false'>X</button>" +
+		"</span>",
+	
+	postMixInProperties: function(){
+		// Set some substitution variables used in the template
+		this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));		
+		this.btnId = this.id + "_close";
+		this.inherited(arguments);
+	},
+	startup: function(){
+		this.connect(this.button, "onClick", "onClick");
+	},
+	onClick: function(){
+	}
+});
+
+
+dojo.declare("dojox.editor.plugins._FindReplaceTextBox",
+	[dijit._Widget, dijit._Templated],{
+	// summary:
+	//		Base class for widgets that contains a label (like "Font:")
+	//		and a TextBox to pick a value.
+	//		Used as Toolbar entry.
+
+	// textId: [public] String
+	//		The id of the enhanced textbox
+	textId: "",
+	
+	// label: [public] String
+	//		The label of the enhanced textbox 
+	label: "",
+	
+	// tooltip: [public] String
+	//		The tooltip of the enhanced textbox when the mouse is hovering on it
+	toolTip: "",
+	widget: null,
+	widgetsInTemplate: true,
+
+	templateString:
+		"<span style='white-space: nowrap' class='dijit dijitReset dijitInline dijitEditorFindReplaceTextBox' " +
+			"title='${tooltip}' tabindex='-1'>" +
+			"<label class='dijitLeft dijitInline' for='${textId}' tabindex='-1'>${label}</label>" +
+			"<input dojoType='dijit.form.TextBox' required='false' intermediateChanges='true' class='focusTextBox'" +
+					"tabIndex='0' id='${textId}' dojoAttachPoint='textBox, focusNode' value='' dojoAttachEvent='onKeyPress: _onKeyPress'/>" +
+		"</span>",
+
+	postMixInProperties: function(){
+		// Set some substitution variables used in the template
+		this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));		
+		this.textId = this.id + "_text";
+		
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		this.textBox.set("value", "");
+		this.disabled =  this.textBox.get("disabled");
+		this.connect(this.textBox, "onChange", "onChange");
+	},
+
+	_setValueAttr: function(/*String*/ value){
+		//If the value is not a permitted value, just set empty string to prevent showing the warning icon
+		this.value = value;
+		this.textBox.set("value", value);
+	},
+
+	focus: function(){
+		this.textBox.focus();
+	},
+
+	_setDisabledAttr: function(/*Boolean*/ value){
+		// summary:
+		//		Over-ride for the textbox's 'disabled' attribute so that it can be 
+		//		disabled programmatically.
+		// value:
+		//		The boolean value to indicate if the textbox should be disabled or not
+		// tags:
+		//		private 
+		this.disabled = value;
+		this.textBox.set("disabled", value);
+	},
+
+	onChange: function(/*String*/ val){
+		// summary:
+		//		Stub function for change events on the box.
+		// tags:
+		//		public
+		this.value= val;
+	},
+	
+	_onKeyPress: function(/*Event*/ evt){
+		// summary:
+		//		Handle the arrow key events
+		// evt:
+		//		Event object passed to this handler
+		// tags:
+		//		private
+		var start = 0;
+		var end = 0;
+		
+		// If CTRL, ALT or SHIFT is not held on
+		if(evt.target && !evt.ctrlKey && !evt.altKey && !evt.shiftKey){
+			if(evt.keyCode == dojo.keys.LEFT_ARROW){
+				start = evt.target.selectionStart;
+				end = evt.target.selectionEnd;
+				if(start < end){
+					dijit.selectInputText(evt.target, start, start);
+					dojo.stopEvent(evt);
+				}
+			}else if(evt.keyCode == dojo.keys.RIGHT_ARROW){
+				start = evt.target.selectionStart;
+				end = evt.target.selectionEnd;
+				if(start < end){
+					dijit.selectInputText(evt.target, end, end);
+					dojo.stopEvent(evt);
+				}
+			}
+		}
+	}
+});
+
+
+dojo.declare("dojox.editor.plugins._FindReplaceCheckBox",
+	[dijit._Widget, dijit._Templated],{
+	// summary:
+	//		Base class for widgets that contains a label (like "Match case: ")
+	//		and a checkbox to indicate if it is checked or not.
+	//		Used as Toolbar entry.
+
+	// checkId: [public] String
+	//		The id of the enhanced checkbox
+	checkId: "",
+	
+	// label: [public] String
+	//		The label of the enhanced checkbox
+	label: "",
+	
+	// tooltip: [public] String
+	//		The tooltip of the enhanced checkbox when the mouse is hovering it
+	tooltip: "",
+	
+	widget: null,
+	widgetsInTemplate: true,
+
+	templateString:
+		"<span style='white-space: nowrap' tabindex='-1' " +
+			"class='dijit dijitReset dijitInline dijitEditorFindReplaceCheckBox' title='${tooltip}' >" +
+			"<input dojoType='dijit.form.CheckBox' required=false " +
+					"tabIndex='0' id='${checkId}' dojoAttachPoint='checkBox, focusNode' value=''/>" +
+			"<label tabindex='-1' class='dijitLeft dijitInline' for='${checkId}'>${label}</label>" +
+		"</span>",
+
+	postMixInProperties: function(){
+		// Set some substitution variables used in the template
+		this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));		
+		this.checkId = this.id + "_check";
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		this.checkBox.set("checked", false);
+		this.disabled =  this.checkBox.get("disabled");
+		this.checkBox.isFocusable = function(){ return false; };
+	},
+
+	_setValueAttr: function(/*Boolean*/ value){
+		// summary:
+		//		Passthrough for checkbox.
+		// tags:
+		//		private
+		this.checkBox.set('value', value);
+	},
+
+	_getValueAttr: function(){
+		// summary:
+		//		Passthrough for checkbox.
+		// tags:
+		//		private
+		return this.checkBox.get('value');
+	},
+
+	focus: function(){
+		// summary:
+		//		Handle the focus event when this widget gets focused
+		// tags:
+		//		private
+		this.checkBox.focus();
+	},
+
+	_setDisabledAttr: function(/*Boolean*/ value){
+		// summary:
+		//		Over-ride for the button's 'disabled' attribute so that it can be 
+		//		disabled programmatically.
+		// value:
+		//		The flag that indicates if the checkbox is disabled or not.
+		// tags:
+		//		private
+		this.disabled = value;
+		this.checkBox.set("disabled", value);
+	}
+});
+
+
+dojo.declare("dojox.editor.plugins._FindReplaceToolbar", dijit.Toolbar, {
+	// summary:
+	//		A toolbar that derived from dijit.Toolbar, which
+	//		eliminates some unnecessary event response such as LEFT_ARROW pressing
+	//		and click bubbling.
+
+	postCreate: function(){
+		this.connectKeyNavHandlers([], []); // Prevent arrow key navigation
+		this.connect(this.containerNode, "onclick", "_onToolbarEvent");
+		this.connect(this.containerNode, "onkeydown", "_onToolbarEvent");
+		dojo.addClass(this.domNode, "dijitToolbar");
+	},
+	
+	addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
+		// summary:
+		//		Add a child to our _Container and prevent the default
+		//		arrow key navigation function. This function may bring in
+		//		side effect
+		dijit._KeyNavContainer.superclass.addChild.apply(this, arguments);
+	},
+	
+	_onToolbarEvent: function(/*Event*/ evt){
+		// Editor may have special treatment to some events, so stop the bubbling.
+		// evt:
+		//		The Event object
+		// tages:
+		//		private
+		evt.stopPropagation();
+	}
+});
+
+dojo.declare("dojox.editor.plugins.FindReplace",[dijit._editor._Plugin],{
+	//	summary:
+	//		This plugin provides a Find/Replace cabability for the editor.
+	//		Note that this plugin is NOT supported on Opera currently, as opera
+	//		does not implement a window.find or equiv function.
+
+	//	buttonClass: [protected]
+	//		Define the class of button the editor uses.
+	buttonClass: dijit.form.ToggleButton,
+
+	// iconClassPrefix: [const] String
+	//		The CSS class name for the button node is formed from `iconClassPrefix` and `command`
+	iconClassPrefix: "dijitEditorIconsFindReplace",
+
+	// editor: [protected]
+	//		The editor this plugin belongs to
+	editor: null,
+	
+	// button: [protected]
+	//		The toggle button
+	button: null,
+	
+	// _frToolbar: [private]
+	//		The toolbar that contain all the entries and buttons
+	_frToolbar: null,
+	
+	// _closeBox: [private]
+	//		The close button of the F/R toolbar
+	_closeBox: null,
+	
+	// _findField: [private]
+	//		The Find field of the F/R toolbar
+	_findField: null,
+	
+	// _replaceField: [private]
+	//		The Replace field of the F/R toolbar
+	_replaceField: null,
+	
+	// _findButton: [private]
+	//		The Find button of the F/R toolbar
+	_findButton: null,
+	
+	// _replaceButton: [private]
+	//		The Replace button of the F/R toolbar
+	_replaceButton: null,
+	
+	// _replaceAllButton: [private]
+	//		The ReplaceAll button of the F/R toolbar
+	_replaceAllButton: null,
+	
+	// _caseSensitive: [private]
+	//		The case sensitive checkbox
+	_caseSensitive: null,
+	
+	// _backwards: [private]
+	//		The backwards checkbox
+	_backwards: null,
+	
+	// _promDialog: [private]
+	//		The prompt message box that shows the user some messages
+	//		such as the end of a search, the end of a replacement, etc.
+	_promDialog: null,
+	_promDialogTimeout: null,
+
+	// _strings: [private]
+	//		The array that contains globalized strings
+	_strings: null,
+
+	_initButton: function(){
+		//	summary:
+		//		Over-ride for creation of the resize button.
+		this._strings = dojo.i18n.getLocalization("dojox.editor.plugins", "FindReplace");
+		this.button = new dijit.form.ToggleButton({
+			label: this._strings["findReplace"],
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " dijitEditorIconFindString",
+			tabIndex: "-1",
+			onChange: dojo.hitch(this, "_toggleFindReplace")
+		});
+		if(dojo.isOpera){
+			// Not currently supported on Opera!
+			this.button.set("disabled", true);
+		}
+		//Link up so that if the toggle is disabled, then the view of Find/Replace is closed.
+		this.connect(this.button, "set", dojo.hitch(this, function(attr, val){
+			if(attr === "disabled"){
+				this._toggleFindReplace((!val && this._displayed), true, true);
+			}
+		}));
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		This is a callback handler that set a reference to the editor this plugin
+		//		hosts in
+		this.editor = editor;
+		this._initButton();
+	},
+
+	toggle: function(){
+		// summary:
+		//		Function to allow programmatic toggling of the find toolbar.
+		// tags:
+		//		public
+		this.button.set("checked", !this.button.get("checked"));
+	},
+
+	_toggleFindReplace: function(/*Boolean*/ show, /*Boolean?*/ ignoreState, /*Boolean?*/ buttonDisabled){
+		// summary:
+		//		Function to toggle whether or not find/replace is displayed.
+		// show:
+		//		Indicate if the toolbar is shown or not
+		// ignoreState:
+		//		Indicate if the status should be ignored or not
+		// blurEditor:
+		//		Indicate if the focus should be removed from the editor or not
+		// tags:
+		//		private
+		var size = dojo.marginBox(this.editor.domNode);
+		if(show && !dojo.isOpera){
+			dojo.style(this._frToolbar.domNode, "display", "block");
+			// Auto populate the Find field
+			this._populateFindField();
+			if(!ignoreState){
+				this._displayed = true;
+			}
+		}else{
+			dojo.style(this._frToolbar.domNode, "display", "none");
+			if(!ignoreState){
+				this._displayed = false;
+			}
+			
+			// If the toggle button is disabled, it is most likely that 
+			// another plugin such as ViewSource disables it.
+			// So we do not need to focus the text area of the editor to
+			// prevent the editor from an invalid status.
+			// Please refer to dijit._editor.plugins.ViewSource for more details.
+			if(!buttonDisabled){
+				this.editor.focus();
+			}
+		}
+
+		// Resize the editor.
+		this.editor.resize({h: size.h});
+	},
+
+	_populateFindField: function(){
+		// summary:
+		//		Populate the Find field with selected text when dialog initially displayed.
+		//		Auto-select text in Find field after it’s populated.
+		//		If nothing selected, restore previous entry from the same session.
+		// tags:
+		//		private
+		var ed = this.editor;
+		var win = ed.window;
+		var selectedTxt = dojo.withGlobal(ed.window, "getSelectedText", dijit._editor.selection, [null]);
+		if(this._findField && this._findField.textBox){
+			if(selectedTxt){
+				this._findField.textBox.set("value", selectedTxt);
+			}
+			this._findField.textBox.focus();
+			dijit.selectInputText(this._findField.textBox.focusNode);
+		}
+	},
+
+	setToolbar: function(/*dijit.Toolbar*/ toolbar){
+		// summary:
+		//		Over-ride so that find/replace toolbar is appended after the current toolbar.
+		// toolbar:
+		//		The current toolbar of the editor
+		// tags:
+		//		public
+		this.inherited(arguments);
+		if(!dojo.isOpera){
+			var _tb = this._frToolbar = new dojox.editor.plugins._FindReplaceToolbar();
+			dojo.style(_tb.domNode, "display", "none");
+			dojo.place(_tb.domNode, toolbar.domNode, "after");
+			_tb.startup();
+
+			// IE6 will put the close box in a new line when its style is "float: right".
+			// So place the close box ahead of the other fields, which makes it align with
+			// the other components.
+			this._closeBox = new dojox.editor.plugins._FindReplaceCloseBox();
+			_tb.addChild(this._closeBox);
+			
+			// Define the search/replace fields.
+			this._findField = new dojox.editor.plugins._FindReplaceTextBox(
+				{label: this._strings["findLabel"], tooltip: this._strings["findTooltip"]});
+			_tb.addChild(this._findField);
+			
+			this._replaceField = new dojox.editor.plugins._FindReplaceTextBox(
+				{label: this._strings["replaceLabel"], tooltip: this._strings["replaceTooltip"]});
+			_tb.addChild(this._replaceField);
+
+			// Define the Find/Replace/ReplaceAll buttons.
+			_tb.addChild(new dojox.editor.plugins._ToolbarLineBreak());
+			
+			this._findButton = new dijit.form.Button({label: this._strings["findButton"], showLabel: true, 
+				iconClass: this.iconClassPrefix + " dijitEditorIconFind"});
+			this._findButton.titleNode.title = this._strings["findButtonTooltip"];
+			_tb.addChild(this._findButton);
+			
+			this._replaceButton = new dijit.form.Button({label: this._strings["replaceButton"], showLabel: true,
+				iconClass: this.iconClassPrefix + " dijitEditorIconReplace"});
+			this._replaceButton.titleNode.title = this._strings["replaceButtonTooltip"];
+			_tb.addChild(this._replaceButton);
+			
+			this._replaceAllButton = new dijit.form.Button({label: this._strings["replaceAllButton"], showLabel: true,
+				iconClass: this.iconClassPrefix + " dijitEditorIconReplaceAll"});
+			this._replaceAllButton.titleNode.title = this._strings["replaceAllButtonTooltip"];
+			_tb.addChild(this._replaceAllButton);
+			
+			// Define the option checkboxes.
+			this._caseSensitive = new dojox.editor.plugins._FindReplaceCheckBox(
+				{label: this._strings["matchCase"], tooltip: this._strings["matchCaseTooltip"]});
+			_tb.addChild(this._caseSensitive);
+			
+			this._backwards = new dojox.editor.plugins._FindReplaceCheckBox(
+				{label: this._strings["backwards"], tooltip: this._strings["backwardsTooltip"]});
+			_tb.addChild(this._backwards);
+
+			// Set initial states, buttons should be disabled unless content is 
+			// present in the fields.
+			this._findButton.set("disabled", true);
+			this._replaceButton.set("disabled", true);
+			this._replaceAllButton.set("disabled", true);
+
+			// Connect the event to the status of the items
+			this.connect(this._findField, "onChange", "_checkButtons");
+			this.connect(this._findField, "onKeyDown", "_onFindKeyDown");
+			this.connect(this._replaceField, "onKeyDown", "_onReplaceKeyDown");
+
+			// Connect up the actual search events.
+			this.connect(this._findButton, "onClick", "_find");
+			this.connect(this._replaceButton, "onClick", "_replace");
+			this.connect(this._replaceAllButton, "onClick", "_replaceAll");
+			
+			// Connect up the close event
+			this.connect(this._closeBox, "onClick", "toggle");
+			
+			// Prompt for the message
+			this._promDialog = new dijit.TooltipDialog();
+			this._promDialog.startup();
+			this._promDialog.set("content", "");
+		}
+	},
+
+	_checkButtons: function(){
+		// summary:
+		//		Ensure that all the buttons are in a correct status
+		//		when certain events are fired.
+		var fText = this._findField.get("value");
+
+		if(fText){
+			// Only enable if find text is not empty or just blank/spaces.
+			this._findButton.set("disabled", false);
+			this._replaceButton.set("disabled", false);
+			this._replaceAllButton.set("disabled", false);
+		}else{
+			this._findButton.set("disabled", true);
+			this._replaceButton.set("disabled", true);
+			this._replaceAllButton.set("disabled", true);
+		}
+	},
+	
+	_onFindKeyDown: function(evt){
+		if(evt.keyCode == dojo.keys.ENTER){
+			// Perform the default search action
+			this._find();
+			dojo.stopEvent(evt);
+		}
+	},
+	
+	_onReplaceKeyDown: function(evt){
+		if(evt.keyCode == dojo.keys.ENTER){
+			// Perform the default replace action
+			if(!this._replace()) this._replace();
+			dojo.stopEvent(evt);
+		}
+	},
+
+	_find: function(/*Boolean?*/ showMessage){
+		// summary:
+		//		This function invokes a find on the editor document with the noted options for
+		//		find.
+		// showMessage:
+		//		Indicated whether the tooltip is shown or not when the search reaches the end
+		// tags:
+		//		private.
+		// returns:
+		//		Boolean indicating if the content was found or not.
+		var txt = this._findField.get("value") || ""; 
+		if(txt){
+			var caseSensitive = this._caseSensitive.get("value");
+			var backwards = this._backwards.get("value");
+			var isFound = this._findText(txt, caseSensitive, backwards);
+			if(!isFound && showMessage){
+				this._promDialog.set("content", dojo.string.substitute(
+					this._strings["eofDialogText"], {"0": this._strings["eofDialogTextFind"]}));
+				dijit.popup.open({popup: this._promDialog, around: this._findButton.domNode});
+				this._promDialogTimeout = setTimeout(dojo.hitch(this, function(){
+					clearTimeout(this._promDialogTimeout);
+					this._promDialogTimeout = null;
+					dijit.popup.close(this._promDialog);
+				}), 3000);
+				setTimeout(dojo.hitch(this, function(){
+					this.editor.focus();
+				}), 0);
+			}
+			return isFound;
+		}
+		
+		return false;
+	},
+
+	_replace: function(/*Boolean?*/ showMessage){
+		// summary:
+		//		This function invokes a replace on the editor document with the noted options for replace
+		// showMessage:
+		//		Indicate if the prompt message is shown or not when the replacement
+		//		reaches the end
+		// tags:
+		//		private
+		// returns:
+		//		Boolean indicating if the content was replaced or not.
+		var isReplaced = false;
+		var ed = this.editor;
+		ed.focus();
+		var txt = this._findField.get("value") || "";
+		var repTxt = this._replaceField.get("value") || "";
+		 
+		if(txt){
+			var caseSensitive = this._caseSensitive.get("value");
+			// Check if it is forced to be forwards or backwards
+			var backwards = this._backwards.get("value");
+			
+			//Replace the current selected text if it matches the pattern
+			var selected = dojo.withGlobal(ed.window, "getSelectedText", dijit._editor.selection, [null]);
+			// Handle checking/replacing current selection.  For some reason on Moz
+			// leading whitespace is trimmed, so we have to trim it down on this check
+			// or we don't always replace.  Moz bug!
+			if(dojo.isMoz){
+				txt = dojo.trim(txt);
+				selected = dojo.trim(selected);
+			}
+			
+			var regExp = this._filterRegexp(txt, !caseSensitive);
+			if(selected && regExp.test(selected)){
+				ed.execCommand("inserthtml", repTxt);
+				isReplaced = true;
+			
+				if(backwards){
+					// Move to the beginning of the replaced text
+					// to avoid the infinite recursive replace
+					this._findText(repTxt, caseSensitive, backwards);
+					dojo.withGlobal(ed.window, "collapse", dijit._editor.selection, [true]);
+				}	
+			}
+			
+			if(!this._find(false) && showMessage){	// Find the next
+				this._promDialog.set("content", dojo.string.substitute(
+					this._strings["eofDialogText"], {"0": this._strings["eofDialogTextReplace"]}));
+				dijit.popup.open({popup: this._promDialog, around: this._replaceButton.domNode});
+				this._promDialogTimeout = setTimeout(dojo.hitch(this, function(){
+					clearTimeout(this._promDialogTimeout);
+					this._promDialogTimeout = null;
+					dijit.popup.close(this._promDialog);
+				}), 3000);
+				setTimeout(dojo.hitch(this, function(){
+					this.editor.focus();
+				}), 0);
+			}
+			return isReplaced;
+		 }
+	},
+	
+	_replaceAll: function(/*Boolean?*/ showMessage){
+		// summary:
+		//		This function replaces all the matched content on the editor document
+		//		with the noted options for replace
+		// showMessage:
+		//		Indicate if the prompt message is shown or not when the action is done.
+		// tags:
+		//		private
+		var replaced = 0;
+		var backwards = this._backwards.get("value");
+		
+		if(backwards){
+			this.editor.placeCursorAtEnd();
+		}else{
+			this.editor.placeCursorAtStart();
+		}
+		
+		// The _replace will return false if the current selection deos not match
+		// the searched text. So try the first attempt so that the selection 
+		// is always the searched text if there is one that matches
+		if(this._replace(false)) { replaced++; }
+		// Do the replace via timeouts to avoid locking the browser up for a lot of replaces.
+		var loopBody = dojo.hitch(this, function(){
+			if(this._replace(false)){
+				replaced++;
+				setTimeout(loopBody, 10);
+			}else{
+				if(showMessage){
+					this._promDialog.set("content", dojo.string.substitute(
+						this._strings["replaceDialogText"], {"0": "" + replaced}));
+					dijit.popup.open({
+						popup: this._promDialog,
+						around: this._replaceAllButton.domNode
+					});
+					this._promDialogTimeout = setTimeout(dojo.hitch(this, function(){
+						clearTimeout(this._promDialogTimeout);
+						this._promDialogTimeout = null;
+						dijit.popup.close(this._promDialog);
+					}), 3000);
+					setTimeout(dojo.hitch(this, function(){
+						this._findField.focus();
+						this._findField.textBox.focusNode.select();
+					}), 0);
+				}
+			}
+		});
+		loopBody();
+	},
+
+	_findText: function(/*String*/ txt, /*Boolean*/ caseSensitive, /*Boolean*/ backwards){
+		// summary:
+		//		This function invokes a find with specific options
+		// txt: String
+		//		The text to locate in the document.
+		// caseSensitive: Boolean
+		//		Whether or ot to search case-sensitively.
+		// backwards: Boolean
+		//		Whether or not to search backwards in the document.
+		// tags:
+		//		private.
+		// returns:
+		//		Boolean indicating if the content was found or not.
+		var ed = this.editor;
+		var win = ed.window;
+		var found = false;
+		if(txt){
+			if(win.find){
+				found = win.find(txt, caseSensitive, backwards, false, false, false, false);
+			}else{
+				var doc = ed.document;
+				if(doc.selection){
+					/* IE */
+					// Focus to restore position/selection, 
+					// then shift to search from current position.
+					this.editor.focus();
+					var txtRg = doc.body.createTextRange();
+					var curPos = doc.selection?doc.selection.createRange():null;
+					if(curPos){
+						if(backwards){
+							txtRg.setEndPoint("EndToStart", curPos);
+						}else{
+							txtRg.setEndPoint("StartToEnd", curPos);
+						}
+					}
+					var flags = caseSensitive?4:0;
+					if(backwards){
+						flags = flags | 1;
+					}
+					//flags = flags |
+					found = txtRg.findText(txt,txtRg.text.length,flags);
+					if(found){
+						txtRg.select();
+					}
+				}
+			}
+		}
+		return found;
+	},
+
+	_filterRegexp: 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.
+		// tags:
+		//		private
+		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 '$':
+				case '^':
+				case '/':
+				case '+':
+				case '.':
+				case '|':
+				case '(':
+				case ')':
+				case '{':
+				case '}':
+				case '[':
+				case ']':
+					rxp += "\\"; //fallthrough
+				default:
+					rxp += c;
+			}
+		}
+		rxp = "^" + rxp + "$";
+		if(ignoreCase){
+			return new RegExp(rxp,"mi"); //RegExp
+		}else{
+			return new RegExp(rxp,"m"); //RegExp
+		}
+		
+	},
+
+	destroy: function(){
+		// summary:
+		//		Cleanup of our custom toolbar.
+		this.inherited(arguments);
+		if(this._promDialogTimeout){
+			clearTimeout(this._promDialogTimeout);
+			this._promDialogTimeout = null;
+			dijit.popup.close(this._promDialog);	
+		}
+		if(this._frToolbar){
+			this._frToolbar.destroyRecursive();
+			this._frToolbar = null;
+		}
+		if(this._promDialog){
+			this._promDialog.destroyRecursive();
+			this._promDialog = null;
+		}
+	}
+});
+
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name ===  "findreplace"){
+		o.plugin = new dojox.editor.plugins.FindReplace({});
+	}
 });
-}
diff --git a/dojox/editor/plugins/InsertAnchor.js b/dojox/editor/plugins/InsertAnchor.js
new file mode 100755
index 0000000..cede291
--- /dev/null
+++ b/dojox/editor/plugins/InsertAnchor.js
@@ -0,0 +1,430 @@
+dojo.provide("dojox.editor.plugins.InsertAnchor");
+
+dojo.require("dijit._Widget");
+dojo.require("dijit._Templated");
+dojo.require("dijit._editor._Plugin");
+dojo.require("dijit.TooltipDialog");
+dojo.require("dijit.form.Button");
+dojo.require("dijit.form.ValidationTextBox");
+dojo.require("dijit.form.Select");
+dojo.require("dijit._editor.range");
+dojo.require("dojo.i18n");
+dojo.require("dojo.string");
+dojo.requireLocalization("dijit", "common");
+dojo.requireLocalization("dojox.editor.plugins", "InsertAnchor");
+
+dojo.declare("dojox.editor.plugins.InsertAnchor", dijit._editor._Plugin, {
+	// summary:
+	//		This plugin provides the basis for an insert anchor dialog for the
+	//		dijit.Editor
+	//
+	// description:
+	//		The command provided by this plugin is:
+	//		* insertAnchor
+
+	// htmlTemplate: [protected] String
+	//		String used for templating the HTML to insert at the desired point.
+	htmlTemplate: "<a name=\"${anchorInput}\" class=\"dijitEditorPluginInsertAnchorStyle\">${textInput}</a>",
+
+	// iconClassPrefix: [const] String
+	//		The CSS class name for the button node icon.
+	iconClassPrefix: "dijitAdditionalEditorIcon",
+
+	// linkDialogTemplate: [private] String
+	//		Template for contents of TooltipDialog to pick URL
+	_template: [
+		"<table><tr><td>",
+		"<label for='${id}_anchorInput'>${anchor}</label>",
+		"</td><td>",
+		"<input dojoType='dijit.form.ValidationTextBox' required='true' " +
+		"id='${id}_anchorInput' name='anchorInput' intermediateChanges='true'>",
+		"</td></tr><tr><td>",
+		"<label for='${id}_textInput'>${text}</label>",
+		"</td><td>",
+		"<input dojoType='dijit.form.ValidationTextBox' required='true' id='${id}_textInput' " +
+		"name='textInput' intermediateChanges='true'>",
+		"</td></tr>",
+		"<tr><td colspan='2'>",
+		"<button dojoType='dijit.form.Button' type='submit' id='${id}_setButton'>${set}</button>",
+		"<button dojoType='dijit.form.Button' type='button' id='${id}_cancelButton'>${cancel}</button>",
+		"</td></tr></table>"
+	].join(""),
+
+	_initButton: function(){
+		// Override _Plugin._initButton() to initialize DropDownButton and TooltipDialog.
+		var _this = this;
+		var messages = dojo.i18n.getLocalization("dojox.editor.plugins", "InsertAnchor", this.lang);
+
+		// Build the dropdown dialog we'll use for the button
+		var dropDown = (this.dropDown = new dijit.TooltipDialog({
+			title: messages["title"],
+			execute: dojo.hitch(this, "setValue"),
+			onOpen: function(){
+				_this._onOpenDialog();
+				dijit.TooltipDialog.prototype.onOpen.apply(this, arguments);
+			},
+			onCancel: function(){
+				setTimeout(dojo.hitch(_this, "_onCloseDialog"),0);
+			}
+		}));
+
+		this.button = new dijit.form.DropDownButton({
+			label: messages["insertAnchor"],
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "InsertAnchor",
+			tabIndex: "-1",
+			dropDown: this.dropDown
+		});
+
+		messages.id = dijit.getUniqueId(this.editor.id);
+		this._uniqueId = messages.id;
+
+		this.dropDown.set('content', dropDown.title +
+			"<div style='border-bottom: 1px black solid;padding-bottom:2pt;margin-bottom:4pt'></div>" +
+			dojo.string.substitute(this._template, messages));
+
+		dropDown.startup();
+		this._anchorInput = dijit.byId(this._uniqueId + "_anchorInput");
+		this._textInput = dijit.byId(this._uniqueId + "_textInput");
+		this._setButton = dijit.byId(this._uniqueId + "_setButton");
+		this.connect(dijit.byId(this._uniqueId + "_cancelButton"), "onClick", function(){
+			this.dropDown.onCancel();
+		});
+
+		if(this._anchorInput){
+			this.connect(this._anchorInput, "onChange", "_checkInput");
+		}
+		if(this._textInput){
+			this.connect(this._anchorInput, "onChange", "_checkInput");
+		}
+
+		//Register some filters to handle setting/removing the class tags on anchors.
+		this.editor.contentDomPreFilters.push(dojo.hitch(this, this._preDomFilter));
+		this.editor.contentDomPostFilters.push(dojo.hitch(this, this._postDomFilter));
+		this._setup();
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._initButton();
+	},
+
+	_checkInput: function(){
+		// summary:
+		//		Function to check the input to the dialog is valid 
+		//		and enable/disable set button
+		// tags:
+		//		private
+		var disable = true;
+		if(this._anchorInput.isValid()){
+			disable = false;
+		}
+		this._setButton.set("disabled", disable);
+	},
+
+	_setup: function(){
+		// summary:
+		//		Over-ridable function that connects tag specific events.
+		this.editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){
+			this.connect(this.editor.editNode, "ondblclick", this._onDblClick);
+			setTimeout(dojo.hitch(this, function() {
+				this._applyStyles();
+			}), 100);
+		}));
+	},
+
+	getAnchorStyle: function(){
+		// summary:
+		//		Over-ridable function for getting the style to apply to the anchor.
+		//		The default is a dashed border with an anchor symbol.
+		// tags:
+		//		public
+		var style = "@media screen {\n" +
+				"\t.dijitEditorPluginInsertAnchorStyle {\n" +
+				"\t\tbackground-image: url({MODURL}/images/anchor.gif);\n" +
+				"\t\tbackground-repeat: no-repeat;\n"	+
+				"\t\tbackground-position: top left;\n" +
+				"\t\tborder-width: 1px;\n" +
+				"\t\tborder-style: dashed;\n" +
+				"\t\tborder-color: #D0D0D0;\n" +
+				 "\t\tpadding-left: 20px;\n" +
+			"\t}\n" +
+		"}\n";
+
+		//Finally associate in the image locations based off the module url.
+		var modurl = dojo.moduleUrl(dojox._scopeName, "editor/plugins/resources").toString();
+		if(!(modurl.match(/^https?:\/\//i)) &&
+			!(modurl.match(/^file:\/\//i))){
+			// We have to root it to the page location on webkit for some nutball reason. 
+			// Probably has to do with how iframe was loaded.
+			var bUrl;
+			if(modurl.charAt(0) === "/"){
+				//Absolute path on the server, so lets handle...
+				var proto = dojo.doc.location.protocol;
+				var hostn = dojo.doc.location.host;
+				bUrl = proto + "//" + hostn;
+			}else{
+				bUrl = this._calcBaseUrl(dojo.global.location.href);
+			}
+			if(bUrl[bUrl.length - 1] !== "/" && modurl.charAt(0) !== "/"){
+				bUrl += "/";
+			}
+			modurl = bUrl + modurl;
+		}
+		return style.replace(/\{MODURL\}/gi, modurl);
+	},
+
+	_applyStyles: function(){
+		// summary:
+		//		Function to apply a style to inserted anchor tags so that
+		//		they are obviously anchors.
+		if(!this._styled){
+			try{
+				//Attempt to inject our specialized style rules for doing this.
+				this._styled = true;
+				var doc = this.editor.document;
+				var style = this.getAnchorStyle();
+				if(!dojo.isIE){
+					var sNode = doc.createElement("style");
+					sNode.appendChild(doc.createTextNode(style));
+					doc.getElementsByTagName("head")[0].appendChild(sNode);
+				}else{
+					var ss = doc.createStyleSheet("");
+					ss.cssText = style;
+				}
+			 }catch(e){ /* Squelch */ }
+		 }
+	},
+
+	_calcBaseUrl: function(fullUrl) {
+		// summary:
+		//		Internal function used to figure out the full root url (no relatives)
+		//		for loading images in the styles in the iframe.
+		// fullUrl: String
+		//		The full url to tear down to the base.
+		// tags:
+		//		private
+		var baseUrl = null;
+		if (fullUrl !== null) {
+			// Check to see if we need to strip off any query parameters from the Url.
+			var index = fullUrl.indexOf("?");
+			if (index != -1) {
+				fullUrl = fullUrl.substring(0,index);
+			}
+
+			// Now we need to trim if necessary.  If it ends in /, then we don't 
+			// have a filename to trim off so we can return.
+			index = fullUrl.lastIndexOf("/");
+			if (index > 0 && index < fullUrl.length) {
+				baseUrl = fullUrl.substring(0,index);
+			}else{
+				baseUrl = fullUrl;
+			}
+		}
+		return baseUrl; //String
+	},
+
+	_checkValues: function(args){
+		// summary:
+		//		Function to check the values in args and 'fix' them up as needed.
+		// args: Object
+		//		Content being set.		
+		// tags: 
+		//		protected
+		if(args){
+			if(args.anchorInput){
+				args.anchorInput = args.anchorInput.replace(/"/g, """);
+			}
+			if(!args.textInput){
+				// WebKit doesn't work with double-click select unless there's
+				// a space in the anchor text, so put a in the case of
+				// empty desc.
+				args.textInput = " ";
+			}
+		}
+		return args;
+	},
+
+	setValue: function(args){
+		// summary:
+		//		Callback from the dialog when user presses "set" button.
+		// tags:
+		//		private
+		this._onCloseDialog();
+		if(!this.editor.window.getSelection){
+			// IE check without using user agent string.
+			var sel = dijit.range.getSelection(this.editor.window);
+			var range = sel.getRangeAt(0);
+			var a = range.endContainer;
+			if(a.nodeType === 3){
+				// Text node, may be the link contents, so check parent.
+				// This plugin doesn't really support nested HTML elements
+				// in the link, it assumes all link content is text.
+				a = a.parentNode;
+			}
+			if(a && (a.nodeName && a.nodeName.toLowerCase() !== "a")){
+				// Stll nothing, one last thing to try on IE, as it might be 'img'
+				// and thus considered a control.
+				a = dojo.withGlobal(this.editor.window,
+					"getSelectedElement", dijit._editor.selection, ["a"]);
+			}
+			if(a && (a.nodeName && a.nodeName.toLowerCase() === "a")){
+				// Okay, we do have a match.  IE, for some reason, sometimes pastes before
+				// instead of removing the targetted paste-over element, so we unlink the
+				// old one first.  If we do not the <a> tag remains, but it has no content,
+				// so isn't readily visible (but is wrong for the action).
+				if(this.editor.queryCommandEnabled("unlink")){
+					// Select all the link childent, then unlink.  The following insert will
+					// then replace the selected text.
+					dojo.withGlobal(this.editor.window,
+						"selectElementChildren", dijit._editor.selection, [a]);
+					this.editor.execCommand("unlink");
+				}
+			}
+		}
+		// make sure values are properly escaped, etc.
+		args = this._checkValues(args); 
+		this.editor.execCommand('inserthtml',
+			dojo.string.substitute(this.htmlTemplate, args));
+	},
+
+	_onCloseDialog: function(){
+		// summary:
+		//		Handler for close event on the dialog
+		this.editor.focus();
+	},
+
+	_getCurrentValues: function(a){
+		// summary:
+		//		Over-ride for getting the values to set in the dropdown.
+		// a:
+		//		The anchor/link to process for data for the dropdown.
+		// tags:
+		//		protected
+		var anchor, text;
+		if(a && a.tagName.toLowerCase() === "a" && dojo.attr(a, "name")){
+			anchor = dojo.attr(a, "name");
+			text = a.textContent || a.innerText;
+			dojo.withGlobal(this.editor.window, "selectElement", dijit._editor.selection, [a, true]);
+		}else{
+			text = dojo.withGlobal(this.editor.window, dijit._editor.selection.getSelectedText);
+		}
+		return {anchorInput: anchor || '', textInput: text || ''}; //Object;
+	},
+
+	_onOpenDialog: function(){
+		// summary:
+		//		Handler for when the dialog is opened.
+		//		If the caret is currently in a URL then populate the URL's info into the dialog.
+		var a;
+		if(!this.editor.window.getSelection){
+			// IE is difficult to select the element in, using the range unified
+			// API seems to work reasonably well.
+			var sel = dijit.range.getSelection(this.editor.window);
+			var range = sel.getRangeAt(0);
+			a = range.endContainer;
+			if(a.nodeType === 3){
+				// Text node, may be the link contents, so check parent.
+				// This plugin doesn't really support nested HTML elements
+				// in the link, it assumes all link content is text.
+				a = a.parentNode;
+			}
+			if(a && (a.nodeName && a.nodeName.toLowerCase() !== "a")){
+				// Stll nothing, one last thing to try on IE, as it might be 'img'
+				// and thus considered a control.
+				a = dojo.withGlobal(this.editor.window,
+					"getSelectedElement", dijit._editor.selection, ["a"]);
+			}
+		}else{
+			a = dojo.withGlobal(this.editor.window,
+				"getAncestorElement", dijit._editor.selection, ["a"]);
+		}
+		this.dropDown.reset();
+		this._setButton.set("disabled", true);
+		this.dropDown.set("value", this._getCurrentValues(a));
+	},
+
+	_onDblClick: function(e){
+		// summary:
+		//		Function to define a behavior on double clicks on the element
+		//		type this dialog edits to select it and pop up the editor
+		//		dialog.
+		// e: Object
+		//		The double-click event.
+		// tags:
+		//		protected.
+		if(e && e.target){
+			var t = e.target;
+			var tg = t.tagName? t.tagName.toLowerCase() : "";
+			if(tg === "a" && dojo.attr(t, "name")){
+				this.editor.onDisplayChanged();
+				dojo.withGlobal(this.editor.window,
+					 "selectElement",
+					 dijit._editor.selection, [t]);
+				setTimeout(dojo.hitch(this, function(){
+					// Focus shift outside the event handler.
+					// IE doesn't like focus changes in event handles.
+					this.button.set("disabled", false);
+					this.button.openDropDown();
+				}), 10);
+			}
+		}
+	},
+
+	_preDomFilter: function(node){
+		// summary:
+		//		A filter to identify the 'a' tags and if they're anchors, 
+		//		apply the right style to them.
+		// node:
+		//		The node to search from.
+		// tags:
+		//		private
+		var ed = this.editor;
+		dojo.withGlobal(ed.window, function(){
+			dojo.query("a", ed.editNode).forEach(function(a){
+				if(dojo.attr(a, "name") && !dojo.attr(a, "href")){
+					if(!dojo.hasClass(a,"dijitEditorPluginInsertAnchorStyle")){
+						dojo.addClass(a, "dijitEditorPluginInsertAnchorStyle");
+					}
+				}
+			});
+		});
+	},
+
+	_postDomFilter: function(node){
+		// summary:
+		//		A filter to identify the 'a' tags and if they're anchors, 
+		//		remove the class style that shows up in the editor from
+		//		them.
+		// node:
+		//		The node to search from.
+		// tags:
+		//		private
+		var ed = this.editor;
+		dojo.withGlobal(ed.window, function(){
+			dojo.query("a", node).forEach(function(a){
+				if(dojo.attr(a, "name") && !dojo.attr(a, "href")){
+					if(dojo.hasClass(a,"dijitEditorPluginInsertAnchorStyle")){
+						dojo.removeClass(a, "dijitEditorPluginInsertAnchorStyle");
+					}
+				}
+			});
+		});
+		return node;
+	}
+});
+
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name;
+	if(name) { name = name.toLowerCase(); }
+	if(name === "insertanchor"){
+		o.plugin = new dojox.editor.plugins.InsertAnchor();
+	}
+});
diff --git a/dojox/editor/plugins/InsertEntity.js b/dojox/editor/plugins/InsertEntity.js
old mode 100644
new mode 100755
index dd80924..c094174
--- a/dojox/editor/plugins/InsertEntity.js
+++ b/dojox/editor/plugins/InsertEntity.js
@@ -1,50 +1,94 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.InsertEntity"]){
-dojo._hasResource["dojox.editor.plugins.InsertEntity"]=true;
 dojo.provide("dojox.editor.plugins.InsertEntity");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.form.Button");
 dojo.require("dijit.TooltipDialog");
 dojo.require("dojox.editor.plugins.EntityPalette");
 dojo.require("dojox.html.entities");
+
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojox.editor.plugins","InsertEntity",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,zh,zh-tw");
-dojo.declare("dojox.editor.plugins.InsertEntity",dijit._editor._Plugin,{iconClassPrefix:"dijitAdditionalEditorIcon",_initButton:function(){
-this.dropDown=new dojox.editor.plugins.EntityPalette({showCode:this.showCode,showEntityName:this.showEntityName});
-this.connect(this.dropDown,"onChange",function(_1){
-this.button.closeDropDown();
-this.editor.focus();
-this.editor.execCommand("inserthtml",_1);
+
+dojo.requireLocalization("dojox.editor.plugins", "InsertEntity");
+
+dojo.declare("dojox.editor.plugins.InsertEntity",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin allows the user to select from standard Symbols (HTML Entities) 
+	//		to insert at the current cursor position.  It binds to the key pattern:
+	//		ctrl-shift-s for opening the insert symbol dropdown.
+	//
+	// description:
+	//		The commands provided by this plugin are:
+	//		* insertEntity - inserts the selected HTML entity character
+
+	// iconClassPrefix: [const] String
+	//		The CSS class name for the button node is formed from `iconClassPrefix` and `command`
+	iconClassPrefix: "dijitAdditionalEditorIcon",
+
+	_initButton: function(){
+		// summary:
+		//		Over-ride for creation of the save button.
+		this.dropDown = new dojox.editor.plugins.EntityPalette({showCode: this.showCode, showEntityName: this.showEntityName});
+		this.connect(this.dropDown, "onChange", function(entity){
+			this.button.closeDropDown();
+			this.editor.focus();
+			this.editor.execCommand("inserthtml",entity);
+		});
+		var strings = dojo.i18n.getLocalization("dojox.editor.plugins", "InsertEntity");
+		this.button = new dijit.form.DropDownButton({
+			label: strings["insertEntity"],
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "InsertEntity",
+			tabIndex: "-1",
+			dropDown: this.dropDown
+		});
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._initButton();
+
+		this.editor.addKeyHandler("s", true, true, dojo.hitch(this, function(){
+			this.button.openDropDown();
+			this.dropDown.focus();
+		}));
+
+		editor.contentPreFilters.push(this._preFilterEntities);
+		editor.contentPostFilters.push(this._postFilterEntities);
+	},
+
+	_preFilterEntities: function(s/*String content passed in*/){
+		// summary:
+		//		A function to filter out entity characters into their UTF-8 character form
+		//		displayed in the editor.  It gets registered with the preFilters
+		//		of the editor.
+		// tags:
+		//		private.
+		return dojox.html.entities.decode(s, dojox.html.entities.latin);
+	},
+
+	_postFilterEntities: function(s/*String content passed in*/){
+		// summary:
+		//		A function to filter out entity characters into encoded form so they 
+		//		are properly displayed in the editor.  It gets registered with the 
+		//		postFilters of the editor.
+		// tags:
+		//		private.
+		return dojox.html.entities.encode(s, dojox.html.entities.latin);
+	}
 });
-var _2=dojo.i18n.getLocalization("dojox.editor.plugins","InsertEntity");
-this.button=new dijit.form.DropDownButton({label:_2["insertEntity"],showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"InsertEntity",tabIndex:"-1",dropDown:this.dropDown});
-},setEditor:function(_3){
-this.editor=_3;
-this._initButton();
-this.editor.addKeyHandler("s",true,true,dojo.hitch(this,function(){
-this.button.openDropDown();
-this.dropDown.focus();
-}));
-_3.contentPreFilters.push(this._preFilterEntities);
-_3.contentPostFilters.push(this._postFilterEntities);
-},_preFilterEntities:function(s){
-return dojox.html.entities.decode(s,dojox.html.entities.latin);
-},_postFilterEntities:function(s){
-return dojox.html.entities.encode(s,dojox.html.entities.latin);
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _4=o.args.name?o.args.name.toLowerCase():"";
-if(_4==="insertentity"){
-o.plugin=new dojox.editor.plugins.InsertEntity({showCode:("showCode" in o.args)?o.args.showCode:false,showEntityName:("showEntityName" in o.args)?o.args.showEntityName:false});
-}
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name? o.args.name.toLowerCase() : "";
+	if(name === "insertentity"){
+		o.plugin = new dojox.editor.plugins.InsertEntity({
+			showCode: ("showCode" in o.args)?o.args.showCode:false,
+			showEntityName: ("showEntityName" in o.args)?o.args.showEntityName:false
+		});
+	}
 });
-}
diff --git a/dojox/editor/plugins/NormalizeIndentOutdent.js b/dojox/editor/plugins/NormalizeIndentOutdent.js
old mode 100644
new mode 100755
index b944789..19f7cd5
--- a/dojox/editor/plugins/NormalizeIndentOutdent.js
+++ b/dojox/editor/plugins/NormalizeIndentOutdent.js
@@ -1,640 +1,873 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.NormalizeIndentOutdent"]){
-dojo._hasResource["dojox.editor.plugins.NormalizeIndentOutdent"]=true;
 dojo.provide("dojox.editor.plugins.NormalizeIndentOutdent");
+
 dojo.require("dijit._editor._Plugin");
+dojo.require("dijit._editor.selection");
+
 dojo.experimental("dojox.editor.plugins.NormalizeIndentOutdent");
-dojo.declare("dojox.editor.plugins.NormalizeIndentOutdent",dijit._editor._Plugin,{indentBy:40,indentUnits:"px",setEditor:function(_1){
-this.editor=_1;
-_1._indentImpl=dojo.hitch(this,this._indentImpl);
-_1._outdentImpl=dojo.hitch(this,this._outdentImpl);
-if(!_1._indentoutdent_queryCommandEnabled){
-_1._indentoutdent_queryCommandEnabled=_1.queryCommandEnabled;
-}
-_1.queryCommandEnabled=dojo.hitch(this,this._queryCommandEnabled);
-_1.customUndo=true;
-},_queryCommandEnabled:function(_2){
-var c=_2.toLowerCase();
-var ed,_3,_4,_5,_6,_7;
-var _8="marginLeft";
-if(!this._isLtr()){
-_8="marginRight";
-}
-if(c==="indent"){
-ed=this.editor;
-_3=dijit.range.getSelection(ed.window);
-if(_3&&_3.rangeCount>0){
-_4=_3.getRangeAt(0);
-_5=_4.startContainer;
-while(_5&&_5!==ed.document&&_5!==ed.editNode){
-_6=this._getTagName(_5);
-if(_6==="li"){
-_7=_5.previousSibling;
-while(_7&&_7.nodeType!==1){
-_7=_7.previousSibling;
-}
-if(_7&&this._getTagName(_7)==="li"){
-return true;
-}else{
-return false;
-}
-}else{
-if(this._isIndentableElement(_6)){
-return true;
-}
-}
-_5=_5.parentNode;
-}
-if(this._isRootInline(_4.startContainer)){
-return true;
-}
-}
-}else{
-if(c==="outdent"){
-ed=this.editor;
-_3=dijit.range.getSelection(ed.window);
-if(_3&&_3.rangeCount>0){
-_4=_3.getRangeAt(0);
-_5=_4.startContainer;
-while(_5&&_5!==ed.document&&_5!==ed.editNode){
-_6=this._getTagName(_5);
-if(_6==="li"){
-return this.editor._indentoutdent_queryCommandEnabled(_2);
-}else{
-if(this._isIndentableElement(_6)){
-var _9=_5.style?_5.style[_8]:"";
-if(_9){
-_9=this._convertIndent(_9);
-if(_9/this.indentBy>=1){
-return true;
-}
-}
-return false;
-}
-}
-_5=_5.parentNode;
-}
-if(this._isRootInline(_4.startContainer)){
-return false;
-}
-}
-}else{
-return this.editor._indentoutdent_queryCommandEnabled(_2);
-}
-}
-return false;
-},_indentImpl:function(_a){
-var ed=this.editor;
-var _b=dijit.range.getSelection(ed.window);
-if(_b&&_b.rangeCount>0){
-var _c=_b.getRangeAt(0);
-var _d=_c.startContainer;
-var _e,_f,end,div;
-if(_c.startContainer===_c.endContainer){
-if(this._isRootInline(_c.startContainer)){
-_f=_c.startContainer;
-while(_f&&_f.parentNode!==ed.editNode){
-_f=_f.parentNode;
-}
-while(_f&&_f.previousSibling&&(this._isTextElement(_f)||(_f.nodeType===1&&this._isInlineFormat(this._getTagName(_f))))){
-_f=_f.previousSibling;
-}
-if(_f&&_f.nodeType===1&&!this._isInlineFormat(this._getTagName(_f))){
-_f=_f.nextSibling;
-}
-if(_f){
-div=ed.document.createElement("div");
-dojo.place(div,_f,"after");
-div.appendChild(_f);
-end=div.nextSibling;
-while(end&&(this._isTextElement(end)||(end.nodeType===1&&this._isInlineFormat(this._getTagName(end))))){
-div.appendChild(end);
-end=div.nextSibling;
-}
-this._indentElement(div);
-dojo.withGlobal(ed.window,"selectElementChildren",dijit._editor.selection,[div]);
-dojo.withGlobal(ed.window,"collapse",dijit._editor.selection,[true]);
-}
-}else{
-while(_d&&_d!==ed.document&&_d!==ed.editNode){
-_e=this._getTagName(_d);
-if(_e==="li"){
-this._indentList(_d);
-return;
-}else{
-if(this._isIndentableElement(_e)){
-this._indentElement(_d);
-return;
-}
-}
-_d=_d.parentNode;
-}
-}
-}else{
-var _10;
-_f=_c.startContainer;
-end=_c.endContainer;
-while(_f&&this._isTextElement(_f)&&_f.parentNode!==ed.editNode){
-_f=_f.parentNode;
-}
-while(end&&this._isTextElement(end)&&end.parentNode!==ed.editNode){
-end=end.parentNode;
-}
-if(end===ed.editNode||end===ed.document.body){
-_10=_f;
-while(_10.nextSibling&&this._inSelection(_10,_c)){
-_10=_10.nextSibling;
-}
-end=_10;
-if(end===ed.editNode||end===ed.document.body){
-_e=this._getTagName(_f);
-if(_e==="li"){
-this._indentList(_f);
-}else{
-if(this._isIndentableElement(_e)){
-this._indentElement(_f);
-}else{
-if(this._isTextElement(_f)||this._isInlineFormat(_e)){
-div=ed.document.createElement("div");
-dojo.place(div,_f,"after");
-var _11=_f;
-while(_11&&(this._isTextElement(_11)||(_11.nodeType===1&&this._isInlineFormat(this._getTagName(_11))))){
-div.appendChild(_11);
-_11=div.nextSibling;
-}
-this._indentElement(div);
-}
-}
-}
-return;
-}
-}
-end=end.nextSibling;
-_10=_f;
-while(_10&&_10!==end){
-if(_10.nodeType===1){
-_e=this._getTagName(_10);
-if(dojo.isIE){
-if(_e==="p"&&this._isEmpty(_10)){
-_10=_10.nextSibling;
-continue;
-}
-}
-if(_e==="li"){
-if(div){
-if(this._isEmpty(div)){
-div.parentNode.removeChild(div);
-}else{
-this._indentElement(div);
-}
-div=null;
-}
-this._indentList(_10);
-}else{
-if(!this._isInlineFormat(_e)&&this._isIndentableElement(_e)){
-if(div){
-if(this._isEmpty(div)){
-div.parentNode.removeChild(div);
-}else{
-this._indentElement(div);
-}
-div=null;
-}
-_10=this._indentElement(_10);
-}else{
-if(this._isInlineFormat(_e)){
-if(!div){
-div=ed.document.createElement("div");
-dojo.place(div,_10,"after");
-div.appendChild(_10);
-_10=div;
-}else{
-div.appendChild(_10);
-_10=div;
-}
-}
-}
-}
-}else{
-if(this._isTextElement(_10)){
-if(!div){
-div=ed.document.createElement("div");
-dojo.place(div,_10,"after");
-div.appendChild(_10);
-_10=div;
-}else{
-div.appendChild(_10);
-_10=div;
-}
-}
-}
-_10=_10.nextSibling;
-}
-if(div){
-if(this._isEmpty(div)){
-div.parentNode.removeChild(div);
-}else{
-this._indentElement(div);
-}
-div=null;
-}
-}
-}
-},_indentElement:function(_12){
-var _13="marginLeft";
-if(!this._isLtr()){
-_13="marginRight";
-}
-var tag=this._getTagName(_12);
-if(tag==="ul"||tag==="ol"){
-var div=this.editor.document.createElement("div");
-dojo.place(div,_12,"after");
-div.appendChild(_12);
-_12=div;
-}
-var _14=_12.style?_12.style[_13]:"";
-if(_14){
-_14=this._convertIndent(_14);
-_14=(parseInt(_14,10)+this.indentBy)+this.indentUnits;
-}else{
-_14=this.indentBy+this.indentUnits;
-}
-dojo.style(_12,_13,_14);
-return _12;
-},_outdentElement:function(_15){
-var _16="marginLeft";
-if(!this._isLtr()){
-_16="marginRight";
-}
-var _17=_15.style?_15.style[_16]:"";
-if(_17){
-_17=this._convertIndent(_17);
-if(_17-this.indentBy>0){
-_17=(parseInt(_17,10)-this.indentBy)+this.indentUnits;
-}else{
-_17="";
-}
-dojo.style(_15,_16,_17);
-}
-},_outdentImpl:function(_18){
-var ed=this.editor;
-var sel=dijit.range.getSelection(ed.window);
-if(sel&&sel.rangeCount>0){
-var _19=sel.getRangeAt(0);
-var _1a=_19.startContainer;
-var tag;
-if(_19.startContainer===_19.endContainer){
-while(_1a&&_1a!==ed.document&&_1a!==ed.editNode){
-tag=this._getTagName(_1a);
-if(tag==="li"){
-return this._outdentList(_1a);
-}else{
-if(this._isIndentableElement(tag)){
-return this._outdentElement(_1a);
-}
-}
-_1a=_1a.parentNode;
-}
-ed.document.execCommand("outdent",false,_18);
-}else{
-var _1b=_19.startContainer;
-var end=_19.endContainer;
-while(_1b&&_1b.nodeType===3){
-_1b=_1b.parentNode;
-}
-while(end&&end.nodeType===3){
-end=end.parentNode;
-}
-end=end.nextSibling;
-var _1c=_1b;
-while(_1c&&_1c!==end){
-if(_1c.nodeType===1){
-tag=this._getTagName(_1c);
-if(tag==="li"){
-this._outdentList(_1c);
-}else{
-if(this._isIndentableElement(tag)){
-this._outdentElement(_1c);
-}
-}
-}
-_1c=_1c.nextSibling;
-}
-}
-}
-return null;
-},_indentList:function(_1d){
-var ed=this.editor;
-var _1e,li;
-var _1f=_1d.parentNode;
-var _20=_1d.previousSibling;
-while(_20&&_20.nodeType!==1){
-_20=_20.previousSibling;
-}
-var _21=null;
-var tg=this._getTagName(_1f);
-if(tg==="ol"){
-_21="ol";
-}else{
-if(tg==="ul"){
-_21="ul";
-}
-}
-if(_21){
-if(_20&&_20.tagName.toLowerCase()=="li"){
-var _22;
-if(_20.childNodes){
-var i;
-for(i=0;i<_20.childNodes.length;i++){
-var n=_20.childNodes[i];
-if(n.nodeType===3){
-if(dojo.trim(n.nodeValue)){
-if(_22){
-break;
-}
-}
-}else{
-if(n.nodeType===1&&!_22){
-if(_21===n.tagName.toLowerCase()){
-_22=n;
-}
-}else{
-break;
-}
-}
-}
-}
-if(_22){
-_22.appendChild(_1d);
-}else{
-_1e=ed.document.createElement(_21);
-dojo.style(_1e,{paddingTop:"0px",paddingBottom:"0px"});
-li=ed.document.createElement("li");
-dojo.style(li,{listStyleImage:"none",listStyleType:"none"});
-_20.appendChild(_1e);
-_1e.appendChild(_1d);
-}
-dojo.withGlobal(ed.window,"selectElementChildren",dijit._editor.selection,[_1d]);
-dojo.withGlobal(ed.window,"collapse",dijit._editor.selection,[true]);
-}
-}
-},_outdentList:function(_23){
-var ed=this.editor;
-var _24=_23.parentNode;
-var _25=null;
-var tg=_24.tagName?_24.tagName.toLowerCase():"";
-var li;
-if(tg==="ol"){
-_25="ol";
-}else{
-if(tg==="ul"){
-_25="ul";
-}
-}
-var _26=_24.parentNode;
-var _27=this._getTagName(_26);
-if(_27==="li"||_27==="ol"||_27==="ul"){
-if(_27==="ol"||_27==="ul"){
-var _28=_24.previousSibling;
-while(_28&&(_28.nodeType!==1||(_28.nodeType===1&&this._getTagName(_28)!=="li"))){
-_28=_28.previousSibling;
-}
-if(_28){
-_28.appendChild(_24);
-_26=_28;
-}else{
-li=_23;
-var _29=_23;
-while(li.previousSibling){
-li=li.previousSibling;
-if(li.nodeType===1&&this._getTagName(li)==="li"){
-_29=li;
-}
-}
-if(_29!==_23){
-dojo.place(_29,_24,"before");
-_29.appendChild(_24);
-_26=_29;
-}else{
-li=ed.document.createElement("li");
-dojo.place(li,_24,"before");
-li.appendChild(_24);
-_26=li;
-}
-dojo.style(_24,{paddingTop:"0px",paddingBottom:"0px"});
-}
-}
-var _2a=_23.previousSibling;
-while(_2a&&_2a.nodeType!==1){
-_2a=_2a.previousSibling;
-}
-var _2b=_23.nextSibling;
-while(_2b&&_2b.nodeType!==1){
-_2b=_2b.nextSibling;
-}
-if(!_2a){
-dojo.place(_23,_26,"after");
-_23.appendChild(_24);
-}else{
-if(!_2b){
-dojo.place(_23,_26,"after");
-}else{
-var _2c=ed.document.createElement(_25);
-dojo.style(_2c,{paddingTop:"0px",paddingBottom:"0px"});
-_23.appendChild(_2c);
-while(_23.nextSibling){
-_2c.appendChild(_23.nextSibling);
-}
-dojo.place(_23,_26,"after");
-}
-}
-if(_24&&this._isEmpty(_24)){
-_24.parentNode.removeChild(_24);
-}
-if(_26&&this._isEmpty(_26)){
-_26.parentNode.removeChild(_26);
-}
-dojo.withGlobal(ed.window,"selectElementChildren",dijit._editor.selection,[_23]);
-dojo.withGlobal(ed.window,"collapse",dijit._editor.selection,[true]);
-}else{
-ed.document.execCommand("outdent",false,null);
-}
-},_isEmpty:function(_2d){
-if(_2d.childNodes){
-var _2e=true;
-var i;
-for(i=0;i<_2d.childNodes.length;i++){
-var n=_2d.childNodes[i];
-if(n.nodeType===1){
-if(this._getTagName(n)==="p"){
-if(!dojo.trim(n.innerHTML)){
-continue;
-}
-}
-_2e=false;
-break;
-}else{
-if(this._isTextElement(n)){
-var nv=dojo.trim(n.nodeValue);
-if(nv&&nv!==" "&&nv!==" "){
-_2e=false;
-break;
-}
-}else{
-_2e=false;
-break;
-}
-}
-}
-return _2e;
-}else{
-return true;
-}
-},_isIndentableElement:function(tag){
-switch(tag){
-case "p":
-case "div":
-case "h1":
-case "h2":
-case "h3":
-case "center":
-case "table":
-case "ul":
-case "ol":
-return true;
-default:
-return false;
-}
-},_convertIndent:function(_2f){
-var _30=12;
-_2f=_2f+"";
-_2f=_2f.toLowerCase();
-var _31=(_2f.indexOf("px")>0)?"px":(_2f.indexOf("em")>0)?"em":"px";
-_2f=_2f.replace(/(px;?|em;?)/gi,"");
-if(_31==="px"){
-if(this.indentUnits==="em"){
-_2f=Math.ceil(_2f/_30);
-}
-}else{
-if(this.indentUnits==="px"){
-_2f=_2f*_30;
-}
-}
-return _2f;
-},_isLtr:function(){
-var _32=this.editor.document.body;
-return dojo.withGlobal(this.editor.window,function(){
-var cs=dojo.getComputedStyle(_32);
-return cs?cs.direction=="ltr":true;
+
+dojo.declare("dojox.editor.plugins.NormalizeIndentOutdent",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides improved indent and outdent handling to
+	//		the editor.  It tries to generate valid HTML, as well as be
+	//		consistent about how it indents and outdents lists and blocks/elements.
+
+	// indentBy: [public] number
+	//		The amount to indent by.  Valid values are 1+.  This is combined with
+	//		the indentUnits parameter to determine how much to indent or outdent
+	//		by for regular text.  It does not affect lists.
+	indentBy: 40,
+	
+	// indentUnits: [public] String
+	//		The units to apply to the indent amount.  Usually 'px', but can also
+	//		be em.  
+	indentUnits: "px",
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+
+		// Register out indent handler via the builtin over-ride mechanism.
+		editor._indentImpl = dojo.hitch(this, this._indentImpl);
+		editor._outdentImpl = dojo.hitch(this, this._outdentImpl);
+
+		// Take over the query command enabled function, we want to prevent
+		// indent of first items in a list, etc.
+		if(!editor._indentoutdent_queryCommandEnabled){
+			editor._indentoutdent_queryCommandEnabled = editor.queryCommandEnabled;
+		}
+		editor.queryCommandEnabled = dojo.hitch(this, this._queryCommandEnabled);
+
+		// We need the custom undo code since we manipulate the dom
+		// outside of the browser natives and only customUndo really handles 
+		// that.  It will incur a performance hit, but should hopefully be
+		// relatively small.  
+		editor.customUndo = true;
+	},
+
+	_queryCommandEnabled: function(command){
+		// summary:
+		//		An over-ride for the editor's query command enabled,
+		//		so that we can prevent indents, etc, on bad elements
+		//		or positions (like first element in a list).
+		// command:
+		//		The command passed in to check enablement.
+		// tags:
+		//		private
+		var c = command.toLowerCase();
+		var ed, sel, range, node, tag, prevNode;
+		var style = "marginLeft";
+		if(!this._isLtr()){
+			style = "marginRight";
+		}
+		if(c === "indent"){
+			ed = this.editor;
+			sel = dijit.range.getSelection(ed.window);
+			if(sel && sel.rangeCount > 0){
+				range = sel.getRangeAt(0);
+				node = range.startContainer;
+
+				// Check for li nodes first, we handle them a certain way.
+				while(node && node !== ed.document && node !== ed.editNode){
+					tag = this._getTagName(node);
+					if(tag === "li"){
+						
+						prevNode = node.previousSibling;
+						while(prevNode && prevNode.nodeType !== 1){
+							prevNode = prevNode.previousSibling;
+						}
+						if(prevNode && this._getTagName(prevNode) === "li"){
+							return true;
+						}else{
+							// First item, disallow
+							return false;
+						}
+					}else if(this._isIndentableElement(tag)){
+						return true;
+					}
+					node = node.parentNode;
+				}
+				if(this._isRootInline(range.startContainer)){
+					return true;
+				}
+			}
+		}else if(c === "outdent"){
+			ed = this.editor;
+			sel = dijit.range.getSelection(ed.window);
+			if(sel && sel.rangeCount > 0){
+				range = sel.getRangeAt(0);
+				node = range.startContainer;
+				// Check for li nodes first, we handle them a certain way.
+				while(node && node !== ed.document && node !== ed.editNode){
+					tag = this._getTagName(node);
+					if(tag === "li"){
+						// Standard list, we can ask the browser.
+						return this.editor._indentoutdent_queryCommandEnabled(command);
+					}else if(this._isIndentableElement(tag)){
+						// Block, we need to handle the indent check.
+						var cIndent = node.style?node.style[style]:"";
+						if(cIndent){
+							cIndent = this._convertIndent(cIndent);
+							if(cIndent/this.indentBy >= 1){
+								return true;
+							}
+						}
+						return false;
+					}
+					node = node.parentNode;
+				}
+				if(this._isRootInline(range.startContainer)){
+					return false;
+				}
+			}
+		}else{
+			return this.editor._indentoutdent_queryCommandEnabled(command);
+		}
+		return false;
+	},
+
+	_indentImpl: function(/*String*/ html) {
+		// summary:
+		//		Improved implementation of indent, generates correct indent for 
+		//		ul/ol
+		var ed = this.editor;
+
+		var sel = dijit.range.getSelection(ed.window);
+		if(sel && sel.rangeCount > 0){
+			var range = sel.getRangeAt(0);
+			var node = range.startContainer;
+			var tag, start, end, div;
+			
+
+			if(range.startContainer === range.endContainer){
+				// No selection, just cursor point, we need to see if we're
+				// in an indentable block, or similar.
+				if(this._isRootInline(range.startContainer)){
+					// Text at the 'root' of the document, 
+					// we'll try to indent it and all inline selements around it 
+					// as they are visually a single line.
+
+					// First, we need to find the toplevel inline element that is rooted 
+					// to the document 'editNode'
+					start = range.startContainer;
+					while(start && start.parentNode !== ed.editNode){
+						start = start.parentNode;
+					}
+
+					// Now we need to walk up its siblings and look for the first one in the rooting
+					// that isn't inline or text, as we want to grab all of that for indent.
+					while(start && start.previousSibling && (
+							this._isTextElement(start) || 
+							(start.nodeType === 1 && this._isInlineFormat(this._getTagName(start))
+						))){
+						start = start.previousSibling;
+					}
+					if(start && start.nodeType === 1 && !this._isInlineFormat(this._getTagName(start))){
+						// Adjust slightly, we're one node too far back in this case.
+						start = start.nextSibling;
+					}
+
+					// Okay, we have a configured start, lets grab everything following it that's 
+					// inline and make it an indentable block!
+					if(start){
+						div = ed.document.createElement("div");
+						dojo.place(div, start, "after");
+						div.appendChild(start);
+						end = div.nextSibling;
+						while(end && (
+							this._isTextElement(end) ||
+							(end.nodeType === 1 && 
+								this._isInlineFormat(this._getTagName(end)))
+							)){
+							// Add it. 
+							div.appendChild(end);
+							end = div.nextSibling;
+						}
+						this._indentElement(div);
+						dojo.withGlobal(ed.window, 
+							"selectElementChildren", dijit._editor.selection, [div]);
+						dojo.withGlobal(ed.window, 
+							"collapse", dijit._editor.selection, [true]);
+					}
+				}else{
+					while(node && node !== ed.document && node !== ed.editNode){
+						tag = this._getTagName(node);
+						if(tag === "li"){
+							this._indentList(node);
+							return;
+						}else if(this._isIndentableElement(tag)){
+							this._indentElement(node);
+							return;
+						}
+						node = node.parentNode;
+					}
+				}
+			}else{
+				var curNode;
+				// multi-node select.  We need to scan over them.
+				// Find the two containing nodes at start and end.
+				// then move the end one node past.  Then ... lets see
+				// what we can indent!
+				start = range.startContainer;
+				end = range.endContainer;
+				// Find the non-text nodes.
+
+				while(start && this._isTextElement(start) && start.parentNode !== ed.editNode){
+					start = start.parentNode;
+				}
+				while(end && this._isTextElement(end) && end.parentNode !== ed.editNode){
+					end = end.parentNode;
+				}
+				if(end === ed.editNode || end === ed.document.body){
+					// Okay, selection end is somewhere after start, we need to find the last node
+					// that is safely in the range.
+					curNode = start;
+					while(curNode.nextSibling && 
+						dojo.withGlobal(ed.window, "inSelection", dijit._editor.selection, [curNode])){
+						curNode = curNode.nextSibling;
+					}
+					end = curNode; 
+					if(end === ed.editNode || end === ed.document.body){
+						// Unable to determine real selection end, so just make it 
+						// a single node indent of start + all following inline styles, if
+						// present, then just exit.
+						tag = this._getTagName(start);
+						if(tag === "li"){
+							this._indentList(start);
+						}else if(this._isIndentableElement(tag)){
+							this._indentElement(start);
+						}else if(this._isTextElement(start) ||
+								 this._isInlineFormat(tag)){
+							// inline element or textnode, So we want to indent it somehow
+							div = ed.document.createElement("div");
+							dojo.place(div, start, "after");
+
+							// Find and move all inline tags following the one we inserted also into the 
+							// div so we don't split up content funny.
+							var next = start;
+							while(next && (
+								this._isTextElement(next) ||
+								(next.nodeType === 1 &&
+								this._isInlineFormat(this._getTagName(next))))){
+								div.appendChild(next);
+								next = div.nextSibling;
+							}
+							this._indentElement(div);
+						}
+						return;
+					}
+				}
+				
+				// Has a definite end somewhere, so lets try to indent up to it.
+				// requires looking at the selections and in some cases, moving nodes
+				// into indentable blocks.
+				end = end.nextSibling;
+				curNode = start;
+				while(curNode && curNode !== end){
+					if(curNode.nodeType === 1){
+						tag = this._getTagName(curNode);
+						if(dojo.isIE){
+							// IE sometimes inserts blank P tags, which we want to skip 
+							// as they end up indented, which messes up layout.
+							if(tag === "p" && this._isEmpty(curNode)){
+								curNode = curNode.nextSibling;
+								continue;
+							}
+						}
+						if(tag === "li"){
+							if(div){
+								if(this._isEmpty(div)){
+									div.parentNode.removeChild(div);
+								}else{
+									this._indentElement(div);
+								}
+								div = null;
+							}
+							this._indentList(curNode);
+						}else if(!this._isInlineFormat(tag) && this._isIndentableElement(tag)){
+							if(div){
+								if(this._isEmpty(div)){
+									div.parentNode.removeChild(div);
+								}else{
+									this._indentElement(div);
+								}
+								div = null;
+							}
+							curNode = this._indentElement(curNode);
+						}else if(this._isInlineFormat(tag)){
+							// inline tag.
+							if(!div){
+								div = ed.document.createElement("div");
+								dojo.place(div, curNode, "after");
+								div.appendChild(curNode);
+								curNode = div;
+							}else{
+								div.appendChild(curNode);
+								curNode = div;
+							}
+						}
+					}else if(this._isTextElement(curNode)){
+						if(!div){
+							div = ed.document.createElement("div");
+							dojo.place(div, curNode, "after");
+							div.appendChild(curNode);
+							curNode = div;
+						}else{
+							div.appendChild(curNode);
+							curNode = div;
+						}
+					}
+					curNode = curNode.nextSibling;
+				}
+				// Okay, indent everything we merged if we haven't yet..
+				if(div){
+					if(this._isEmpty(div)){
+						div.parentNode.removeChild(div);
+					}else{
+						this._indentElement(div);
+					}
+					div = null;
+				}
+			}
+		}
+	},
+
+	_indentElement: function(node){
+		// summary:
+		//		Function to indent a block type tag.
+		// node:
+		//		The node who's content to indent.
+		// tags:
+		//		private
+		var style = "marginLeft";
+		if(!this._isLtr()){
+			style = "marginRight";
+		}
+		var tag = this._getTagName(node);
+		if(tag === "ul" || tag === "ol"){
+			// Lists indent funny, so lets wrap them in a div
+			// and indent the div instead.
+			var div = this.editor.document.createElement("div");
+			dojo.place(div, node, "after");
+			div.appendChild(node);
+			node = div;
+		}
+		var cIndent = node.style?node.style[style]:"";
+		if(cIndent){
+			cIndent = this._convertIndent(cIndent);
+			cIndent = (parseInt(cIndent, 10) + this.indentBy) + this.indentUnits;
+		}else{
+			cIndent = this.indentBy + this.indentUnits;
+		}
+		dojo.style(node, style, cIndent);
+		return node; //Return the node that was indented.
+	},
+
+	_outdentElement: function(node){
+		// summary:
+		//		Function to outdent a block type tag.
+		// node:
+		//		The node who's content to outdent.
+		// tags:
+		//		private
+		var style = "marginLeft";
+		if(!this._isLtr()){
+			style = "marginRight";
+		}
+		var cIndent = node.style?node.style[style]:"";
+		if(cIndent){
+			cIndent = this._convertIndent(cIndent);
+			if(cIndent - this.indentBy > 0){
+				cIndent = (parseInt(cIndent, 10) - this.indentBy) + this.indentUnits;
+			}else{
+				cIndent = "";
+			}
+			dojo.style(node, style, cIndent);
+		}
+	},
+
+	_outdentImpl: function(/*String*/ html) {
+		// summary:
+		//		Improved implementation of outdent, generates correct indent for 
+		//		ul/ol and other elements.
+		// tags:
+		//		private
+		var ed = this.editor;
+		var sel = dijit.range.getSelection(ed.window);
+		if(sel && sel.rangeCount > 0){
+			var range = sel.getRangeAt(0);
+			var node = range.startContainer;
+			var tag;
+
+			if(range.startContainer === range.endContainer){
+				// Check for li nodes first, we handle them a certain way.
+				while(node && node !== ed.document && node !== ed.editNode){
+					tag = this._getTagName(node);
+					if(tag === "li"){
+						return this._outdentList(node);
+					}else if(this._isIndentableElement(tag)){
+						return this._outdentElement(node);
+					}
+					node = node.parentNode;
+				}
+				ed.document.execCommand("outdent", false, html);
+			}else{
+				// multi-node select.  We need to scan over them.
+				// Find the two containing nodes at start and end.
+				// then move the end one node past.  Then ... lets see
+				// what we can outdent!
+				var start = range.startContainer;
+				var end =  range.endContainer;
+				// Find the non-text nodes.
+				while(start && start.nodeType === 3){
+					start = start.parentNode;
+				}
+				while(end && end.nodeType === 3){
+					end = end.parentNode;
+				}
+				end = end.nextSibling;
+				var curNode = start;
+				while(curNode && curNode !== end){
+					if(curNode.nodeType === 1){
+						tag = this._getTagName(curNode);
+						if(tag === "li"){
+							this._outdentList(curNode);
+						}else if(this._isIndentableElement(tag)){
+							this._outdentElement(curNode);
+						}
+
+					}
+					curNode = curNode.nextSibling;
+				}	
+			}
+		}
+		return null;
+	},
+
+
+	_indentList: function(listItem){
+		// summary:
+		//		Internal function to handle indenting a list element.
+		// listItem:
+		//		The list item to indent.
+		// tags:
+		//		private
+		var ed = this.editor;
+		var newList, li;
+		var listContainer = listItem.parentNode;
+		var prevTag = listItem.previousSibling;
+		
+		// Ignore text, we want elements.
+		while(prevTag && prevTag.nodeType !== 1){
+			prevTag = prevTag.previousSibling;
+		}
+		var type = null;
+		var tg = this._getTagName(listContainer);
+		
+		// Try to determine what kind of list item is here to indent.
+		if(tg === "ol"){
+			type = "ol";
+		}else if(tg === "ul"){
+			type = "ul";
+		}
+		
+		// Only indent list items actually in a list.
+		// Bail out if the list is malformed somehow.
+		if(type){
+			// There is a previous node in the list, so we want to append a new list
+			// element after it that contains a new list of the content to indent it.
+			if(prevTag && prevTag.tagName.toLowerCase() == "li"){
+				// Lets see if we can merge this into another  (Eg, 
+				// does the sibling li contain an embedded list already of 
+				// the same type?  if so, we move into that one.
+				var embList;
+				if(prevTag.childNodes){
+					var i;
+					for(i = 0; i < prevTag.childNodes.length; i++){
+						var n = prevTag.childNodes[i];
+						if(n.nodeType === 3){
+							if(dojo.trim(n.nodeValue)){
+								if(embList){
+									// Non-empty text after list, exit, can't embed.
+									break;
+								}
+							}
+						}else if(n.nodeType === 1 && !embList){
+							// See if this is a list container.
+							if(type === n.tagName.toLowerCase()){
+								embList = n;
+							}
+						}else{
+							// Other node present, break, can't embed.
+							break;
+						}
+					}
+				}
+				if(embList){
+					// We found a list to merge to, so merge.
+					embList.appendChild(listItem);
+				}else{
+					// Nope, wasn't an embedded list container,
+					// So lets just create a new one.
+					newList = ed.document.createElement(type);
+					dojo.style(newList, {
+						paddingTop: "0px",
+						paddingBottom: "0px"
+					});
+					li = ed.document.createElement("li");
+					dojo.style(li, {
+						listStyleImage: "none",
+						listStyleType: "none"
+					});
+					prevTag.appendChild(newList);
+					newList.appendChild(listItem);
+				}
+
+				// Move cursor.
+				dojo.withGlobal(ed.window, 
+					"selectElementChildren", dijit._editor.selection, [listItem]);
+				dojo.withGlobal(ed.window, 
+					"collapse", dijit._editor.selection, [true]);
+			}
+		}
+	},
+
+	_outdentList: function(listItem){
+		// summary:
+		//		Internal function to handle outdenting a list element.
+		// listItem:
+		//		The list item to outdent.
+		// tags:
+		//		private
+		var ed = this.editor;
+		var list = listItem.parentNode;
+		var type = null;
+		var tg = list.tagName ? list.tagName.toLowerCase() : "";
+		var li;
+
+		// Try to determine what kind of list contains the item.
+		if(tg === "ol"){
+			type = "ol";
+		}else if(tg === "ul"){
+			type = "ul";
+		}
+
+		// Check to see if it is a nested list, as outdenting is handled differently.
+		var listParent = list.parentNode;
+		var lpTg = this._getTagName(listParent);
+		
+		// We're in a list, so we need to outdent this specially.
+		// Check for welformed and malformed lists (<ul><ul></ul>U/ul> type stuff).
+		if(lpTg === "li" || lpTg === "ol" || lpTg === "ul"){
+			if(lpTg === "ol" || lpTg === "ul"){
+				// Okay, we need to fix this up, this is invalid html,
+				// So try to combine this into a previous element before 
+				// de do a shuffle of the nodes, to build an HTML compliant
+				// list.
+				var prevListLi = list.previousSibling;
+				while(prevListLi && (prevListLi.nodeType !== 1 ||
+						(prevListLi.nodeType === 1 &&
+						this._getTagName(prevListLi) !== "li"))
+					){
+					prevListLi = prevListLi.previousSibling;
+				}
+				if(prevListLi){
+					// Move this list up into the previous li
+					// to fix malformation.
+					prevListLi.appendChild(list);
+					listParent = prevListLi;
+				}else{
+					li = listItem;
+					var firstItem = listItem;
+					while(li.previousSibling){
+						li = li.previousSibling;
+						if(li.nodeType === 1 && this._getTagName(li) === "li"){
+							firstItem = li;
+						}
+					}
+
+					if(firstItem !== listItem){
+						dojo.place(firstItem, list, "before");
+						firstItem.appendChild(list);
+						listParent = firstItem;
+					}else{
+						// No previous list item in a malformed list
+						// ... so create one  and move into that.
+						li = ed.document.createElement("li");
+						dojo.place(li, list, "before");
+						li.appendChild(list);
+						listParent = li;
+					}
+					dojo.style(list, {
+						paddingTop: "0px",
+						paddingBottom: "0px"
+					});
+				}
+			}
+
+			// find the previous node, if any,
+			// non-text.
+			var prevLi = listItem.previousSibling;
+			while(prevLi && prevLi.nodeType !== 1){
+				prevLi = prevLi.previousSibling;
+			}
+			var nextLi = listItem.nextSibling;
+			while(nextLi && nextLi.nodeType !== 1){
+				nextLi = nextLi.nextSibling;
+			}
+
+			if(!prevLi){
+				// Top item in a nested list, so just move it out
+				// and then shuffle the remaining indented list into it.
+				dojo.place(listItem, listParent, "after");
+				listItem.appendChild(list);
+			}else if(!nextLi){
+				// Last item in a nested list, shuffle it out after 
+				// the nsted list only.
+				dojo.place(listItem, listParent, "after");
+			}else{
+				// Item is in the middle of an embedded  list, so we 
+				// have to split it.
+
+				// Move all the items following current list item into 
+				// a list after it.
+				var newList = ed.document.createElement(type);
+				dojo.style(newList, {
+					paddingTop: "0px",
+					paddingBottom: "0px"
+				});
+				listItem.appendChild(newList);
+				while(listItem.nextSibling){
+					newList.appendChild(listItem.nextSibling);
+				}
+
+				// Okay, now place the list item after the 
+				// current list parent (li).
+				dojo.place(listItem, listParent, "after");
+			}
+			
+			// Clean up any empty lists left behind.
+			if(list && this._isEmpty(list)){
+				list.parentNode.removeChild(list);	
+			}
+			if(listParent && this._isEmpty(listParent)){
+				listParent.parentNode.removeChild(listParent);
+			}
+			
+			// Move our cursor to the list item we moved.
+			dojo.withGlobal(ed.window, 
+				"selectElementChildren", dijit._editor.selection, [listItem]);
+			dojo.withGlobal(ed.window, 
+				"collapse", dijit._editor.selection, [true]);
+		}else{
+			// Not in a nested list, so we can just defer to the
+			// browser and hope it outdents right.
+			ed.document.execCommand("outdent", false, null);
+		}
+	},
+
+	_isEmpty: function(node){
+		// summary:
+		//		Internal function to determine if a node is 'empty'
+		//		Eg, contains only blank text.  Used to determine if
+		//		an empty list element should be removed or not.
+		// node:
+		//		The node to check.
+		// tags:
+		//		private
+		if(node.childNodes){
+			var empty = true;
+			var i;
+			for(i = 0; i < node.childNodes.length; i++){
+				var n = node.childNodes[i];
+				if(n.nodeType === 1){
+					if(this._getTagName(n) === "p"){
+						if(!dojo.trim(n.innerHTML)){
+							continue;	
+						}
+					}
+					empty = false;
+					break;
+				}else if(this._isTextElement(n)){
+					// Check for empty text.
+					var nv = dojo.trim(n.nodeValue);
+					if(nv && nv !==" " && nv !== "\u00A0"){
+						empty = false;
+						break;
+					}
+				}else{
+					empty = false;
+					break;
+				}
+			}
+			return empty;
+		}else{
+			return true;
+		}
+	},
+
+	_isIndentableElement: function(tag){
+		// summary:
+		//		Internal function to detect what element types
+		//		are indent-controllable by us.
+		// tag:
+		//		The tag to check
+		// tags:
+		//		private
+		switch(tag){
+			case "p":
+			case "div":
+			case "h1":
+			case "h2":
+			case "h3":
+			case "center":
+			case "table":
+			case "ul":
+			case "ol":
+				return true;
+			default:
+				return false;
+		}
+	},
+
+	_convertIndent: function(indent){
+		// summary:
+		//		Function to convert the current indent style to 
+		//		the units we're using by some heuristic.
+		// indent:
+		//		The indent amount to convert.
+		// tags:
+		//		private
+		var pxPerEm = 12;
+		indent = indent + "";
+		indent = indent.toLowerCase();
+		var curUnit = (indent.indexOf("px") > 0) ? "px" : (indent.indexOf("em") > 0) ? "em" : "px";
+		indent = indent.replace(/(px;?|em;?)/gi, "");
+		if(curUnit === "px"){
+			if(this.indentUnits === "em"){
+				indent = Math.ceil(indent/pxPerEm);
+			}
+		}else{
+			if(this.indentUnits === "px"){
+				indent = indent * pxPerEm;
+			}
+		}
+		return indent;
+	},
+
+	_isLtr: function(){
+		// summary:
+		//		Function to detect if the editor body is in RTL or LTR.
+		// tags:
+		//		private
+		var editDoc = this.editor.document.body;
+		return dojo.withGlobal(this.editor.window, function(){
+			var cs = dojo.getComputedStyle(editDoc);
+			return cs ? cs.direction == "ltr" : true;
+		});
+	},
+
+	_isInlineFormat: function(tag){
+		// summary:
+		//		Function to determine if the current tag is an inline
+		//		element that does formatting, as we don't want to 
+		//		break/indent around it, as it can screw up text.
+		// tag:
+		//		The tag to examine
+		// tags:
+		//		private
+		switch(tag){
+			case "a":
+			case "b":
+			case "strong":
+			case "s":
+			case "strike":
+			case "i":
+			case "u":
+			case "em":
+			case "sup":
+			case "sub":
+			case "span":
+			case "font":
+			case "big":
+			case "cite":
+			case "q":
+			case "img":
+			case "small":
+				return true;
+			default:
+				return false;
+		}
+	},
+
+	_getTagName: function(node){
+		// summary:
+		//		Internal function to get the tag name of an element
+		//		if any.
+		// node:
+		//		The node to look at.
+		// tags:
+		//		private
+		var tag = "";
+		if(node && node.nodeType === 1){
+			tag = node.tagName?node.tagName.toLowerCase():"";
+		}
+		return tag;
+	},
+
+	_isRootInline: function(node){
+		// summary:
+		//		This functions tests whether an indicated node is in root as inline
+		//		or rooted inline elements in the page.
+		// node:
+		//		The node to start at.
+		// tags:
+		//		private
+		var ed = this.editor;
+		if(this._isTextElement(node) && node.parentNode === ed.editNode){
+			return true;
+		}else if(node.nodeType === 1 && this._isInlineFormat(node) && node.parentNode === ed.editNode){
+			return true;
+		}else if(this._isTextElement(node) && this._isInlineFormat(this._getTagName(node.parentNode))){
+			node = node.parentNode;
+			while(node && node !== ed.editNode && this._isInlineFormat(this._getTagName(node))){
+				node = node.parentNode;
+			}
+			if(node === ed.editNode){
+				return true;
+			}
+		}
+		return false;
+	},
+
+	_isTextElement: function(node){
+		// summary:
+		//		Helper function to check for text nodes.
+		// node:
+		//		The node to check.
+		// tags:
+		//		private
+		if(node && node.nodeType === 3 || node.nodeType === 4){
+			return true;
+		}
+		return false;
+	}
 });
-},_isInlineFormat:function(tag){
-switch(tag){
-case "a":
-case "b":
-case "strong":
-case "s":
-case "strike":
-case "i":
-case "u":
-case "em":
-case "sup":
-case "sub":
-case "span":
-case "font":
-case "big":
-case "cite":
-case "q":
-case "img":
-case "small":
-return true;
-default:
-return false;
-}
-},_getTagName:function(_33){
-var tag="";
-if(_33&&_33.nodeType===1){
-tag=_33.tagName?_33.tagName.toLowerCase():"";
-}
-return tag;
-},_isRootInline:function(_34){
-var ed=this.editor;
-if(this._isTextElement(_34)&&_34.parentNode===ed.editNode){
-return true;
-}else{
-if(_34.nodeType===1&&this._isInlineFormat(_34)&&_34.parentNode===ed.editNode){
-return true;
-}else{
-if(this._isTextElement(_34)&&this._isInlineFormat(this._getTagName(_34.parentNode))){
-_34=_34.parentNode;
-while(_34&&_34!==ed.editNode&&this._isInlineFormat(this._getTagName(_34))){
-_34=_34.parentNode;
-}
-if(_34===ed.editNode){
-return true;
-}
-}
-}
-}
-return false;
-},_isTextElement:function(_35){
-if(_35&&_35.nodeType===3||_35.nodeType===4){
-return true;
-}
-return false;
-},_inSelection:function(_36,_37){
-if(_36&&_37){
-var _38;
-var doc=this.editor.document;
-if(_37.compareBoundaryPoints&&doc.createRange){
-try{
-_38=doc.createRange();
-_38.setStart(_36,0);
-if(_37.compareBoundaryPoints(_37.START_TO_END,_38)===1){
-return true;
-}
-}
-catch(e){
-}
-}else{
-if(doc.selection){
-_37=doc.selection.createRange();
-try{
-_38=_36.ownerDocument.body.createControlRange();
-if(_38){
-_38.addElement(_36);
-}
-}
-catch(e1){
-try{
-_38=_36.ownerDocument.body.createTextRange();
-_38.moveToElementText(_36);
-}
-catch(e2){
-}
-}
-if(_37&&_38){
-if(_37.compareEndPoints("EndToStart",_38)===1){
-return true;
-}
-}
-}
-}
-}
-return false;
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _39=o.args.name.toLowerCase();
-if(_39==="normalizeindentoutdent"){
-o.plugin=new dojox.editor.plugins.NormalizeIndentOutdent({indentBy:("indentBy" in o.args)?(o.args.indentBy>0?o.args.indentBy:40):40,indentUnits:("indentUnits" in o.args)?(o.args.indentUnits.toLowerCase()=="em"?"em":"px"):"px"});
-}
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "normalizeindentoutdent"){
+		o.plugin = new dojox.editor.plugins.NormalizeIndentOutdent({
+			indentBy: ("indentBy" in o.args) ? 
+				(o.args.indentBy > 0 ? o.args.indentBy : 40) : 
+				40,
+			indentUnits: ("indentUnits" in o.args) ? 
+				(o.args.indentUnits.toLowerCase() == "em"? "em" : "px") : 
+				"px"
+		});
+	}
 });
-}
diff --git a/dojox/editor/plugins/NormalizeStyle.js b/dojox/editor/plugins/NormalizeStyle.js
new file mode 100755
index 0000000..88f7020
--- /dev/null
+++ b/dojox/editor/plugins/NormalizeStyle.js
@@ -0,0 +1,551 @@
+dojo.provide("dojox.editor.plugins.NormalizeStyle");
+
+dojo.require("dijit._editor._Plugin");
+dojo.require("dijit._editor.html");
+
+dojo.experimental("dojox.editor.plugins.NormalizeStyle");
+
+dojo.declare("dojox.editor.plugins.NormalizeStyle",dijit._editor._Plugin,{
+	//	summary:
+	//		This plugin provides NormalizeStyle cabability to the editor.  It is
+	//		a headless plugin that tries to normalize how content is styled when
+	//		it comes out of th editor ('b' or css).   It also auto-converts
+	//		incoming content to the proper one expected by the browser as well so 
+	//		that the native styling buttons work.
+
+	// mode [public] String
+	//		A String variable indicating if it should use semantic tags 'b', 'i', etc, or 
+	//		CSS styling.  The default is semantic.
+	mode: "semantic",
+
+	// condenseSpans [public] Boolean
+	//		A boolean variable indicating if it should try to condense 
+	//		'span''span''span' styles  when in css mode 
+	//		The default is true, it will try to combine where it can.
+	condenseSpans: true,
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		editor.customUndo = true;
+
+		if(this.mode === "semantic"){
+			this.editor.contentDomPostFilters.push(dojo.hitch(this, this._convertToSemantic));
+		}else if(this.mode === "css"){
+			this.editor.contentDomPostFilters.push(dojo.hitch(this, this._convertToCss));
+		}
+
+		// Pre DOM filters are usually based on what browser, as they all use different ways to
+		// apply styles with actions and modify them.
+		if(dojo.isIE){
+			// IE still uses sematic tags most of the time, so convert to that.
+			this.editor.contentDomPreFilters.push(dojo.hitch(this, this._convertToSemantic));
+			this._browserFilter = this._convertToSemantic;
+		}else if(dojo.isWebKit){
+			this.editor.contentDomPreFilters.push(dojo.hitch(this, this._convertToCss));
+			this._browserFilter = this._convertToCss;
+		}else if(dojo.isMoz){
+			//Editor currently forces Moz into semantic mode, so we need to match.  Ideally
+			//editor could get rid of that and just use CSS mode, whitch would work cleaner
+			//That's why this is split out, to make it easy to change later.
+			this.editor.contentDomPreFilters.push(dojo.hitch(this, this._convertToSemantic));
+			this._browserFilter = this._convertToSemantic;
+		}else{
+			this.editor.contentDomPreFilters.push(dojo.hitch(this, this._convertToSemantic));
+			this._browserFilter = this._convertToSemantic;
+		}
+
+		// Set up the inserthtml impl over-ride.  This catches semi-paste events and
+		// tries to normalize them too.
+		if(this.editor._inserthtmlImpl){
+			this.editor._oldInsertHtmlImpl = this.editor._inserthtmlImpl;
+		}
+		this.editor._inserthtmlImpl = dojo.hitch(this, this._inserthtmlImpl);
+	},
+
+	_convertToSemantic: function(node){
+		// summary:
+		//		A function to convert the HTML structure of 'node' into 
+		//		sematic tags where possible.
+		// node: DOMNode
+		//		The node to process.
+		// tags:
+		//		private
+		if(node){
+			var w = this.editor.window;
+			var self = this;
+			var convertNode = function(cNode){
+				if(cNode.nodeType == 1){
+					if(cNode.id !== "dijitEditorBody"){
+						var style = cNode.style;
+						var tag = cNode.tagName?cNode.tagName.toLowerCase():"";
+						var sTag;
+						if(style && tag != "table" && tag != "ul" && tag != "ol"){
+							// Avoid wrapper blocks that have specific underlying structure, as injecting
+							// spans/etc there is invalid.
+							// Lets check and convert certain node/style types.
+							var fw = style.fontWeight? style.fontWeight.toLowerCase() : "";
+							var fs = style.fontStyle? style.fontStyle.toLowerCase() : "";
+							var td = style.textDecoration? style.textDecoration.toLowerCase() : "";
+							var s = style.fontSize?style.fontSize.toLowerCase() : "";
+							var bc = style.backgroundColor?style.backgroundColor.toLowerCase() : "";
+							var c = style.color?style.color.toLowerCase() : "";
+	
+							var wrapNodes = function(wrap, pNode){
+								if(wrap){
+									while(pNode.firstChild){
+										wrap.appendChild(pNode.firstChild);
+									}
+									if(tag == "span" && !pNode.style.cssText){
+										// A styler tag with nothing extra in it, so lets remove it.
+										dojo.place(wrap, pNode, "before");
+										pNode.parentNode.removeChild(pNode);
+										pNode = wrap;
+									}else{
+										pNode.appendChild(wrap);
+									}
+								}
+								return pNode;
+							};
+							switch(fw){
+								case "bold":
+								case "bolder":
+								case "700":
+								case "800":
+								case "900":
+									sTag = dojo.withGlobal(w, "create", dojo, ["b", {}] );
+									cNode.style.fontWeight = "";
+									break;
+							}
+							cNode = wrapNodes(sTag, cNode);
+							sTag = null;
+							if(fs == "italic"){
+								sTag = dojo.withGlobal(w, "create", dojo, ["i", {}] );
+								cNode.style.fontStyle = "";
+							}
+							cNode = wrapNodes(sTag, cNode);
+							sTag = null;
+							if(td){
+								var da = td.split(" ");
+								var count = 0;
+								dojo.forEach(da, function(s){
+									switch(s){
+										case "underline":
+											sTag = dojo.withGlobal(w, "create", dojo, ["u", {}] );
+											break;
+										case "line-through": 
+											sTag = dojo.withGlobal(w, "create", dojo, ["strike", {}] );
+											break;
+									}
+									count++;
+									if(count == da.length){
+										// Last one, clear the decor and see if we can span strip on wrap.
+										cNode.style.textDecoration = "";
+									}
+									cNode = wrapNodes(sTag, cNode);
+									sTag = null;
+								});
+								
+							}
+							if(s){
+								var sizeMap = {
+									"xx-small": 1,
+									"x-small": 2,
+									"small": 3,
+									"medium": 4,
+									"large": 5,
+									"x-large": 6,
+									"xx-large": 7,
+									"-webkit-xxx-large": 7
+								};
+
+								// Convert point or px size to size 
+								// to something roughly mappable.
+								if(s.indexOf("pt") > 0){
+									s = s.substring(0,s.indexOf("pt"));
+									s = parseInt(s);
+									if(s < 5){
+										s = "xx-small";
+									}else if(s < 10){
+										s = "x-small";
+									}else if(s < 15){
+										s = "small";
+									}else if(s < 20){
+										s = "medium";
+									}else if(s < 25){
+										s = "large";
+									}else if(s < 30){
+										s = "x-large";
+									}else if(s > 30){
+										s = "xx-large";
+									}
+								}else if(s.indexOf("px") > 0){
+									s = s.substring(0,s.indexOf("px"));
+									s = parseInt(s);
+									if(s < 5){
+										s = "xx-small";
+									}else if(s < 10){
+										s = "x-small";
+									}else if(s < 15){
+										s = "small";
+									}else if(s < 20){
+										s = "medium";
+									}else if(s < 25){
+										s = "large";
+									}else if(s < 30){
+										s = "x-large";
+									}else if(s > 30){
+										s = "xx-large";
+									}
+								}
+								var size = sizeMap[s];
+								if(!size){
+									size = 3;
+								}
+								sTag = dojo.withGlobal(w, "create", dojo, ["font", {size: size}] );
+								cNode.style.fontSize = "";
+							}
+							cNode = wrapNodes(sTag, cNode);
+							sTag = null;
+							if(bc && tag !== "font" && self._isInline(tag)){
+								// IE doesn't like non-font background color crud.
+								// Also, don't move it in if the background color is set on a block style node, 
+								// as it won't color properly once put on inline font.
+								bc = new dojo.Color(bc).toHex();
+								sTag = dojo.withGlobal(w, "create", dojo, ["font", {style: {backgroundColor: bc}}] );
+								cNode.style.backgroundColor = "";
+							}
+							if(c && tag !== "font"){
+								// IE doesn't like non-font background color crud.
+								c = new dojo.Color(c).toHex();
+								sTag = dojo.withGlobal(w, "create", dojo, ["font", {color: c}] );
+								cNode.style.color = "";
+							}
+							cNode = wrapNodes(sTag, cNode);
+							sTag = null;
+						}
+					}
+					if(cNode.childNodes){
+						// Clone it, since we may alter its position
+						var nodes = [];
+						dojo.forEach(cNode.childNodes, function(n){ nodes.push(n);});
+						dojo.forEach(nodes, convertNode);
+					}
+				}
+				return cNode;
+			};
+			return this._normalizeTags(convertNode(node));
+		}
+		return node;
+	},
+	
+	_normalizeTags: function(node){
+		// summary: 
+		//		A function to handle normalizing certain tag types contained under 'node'
+		// node:
+		//		The node to search from.
+		// tags:
+		//		Protected.
+		var w = this.editor.window;
+		var nodes = dojo.withGlobal(w, function() {
+			return dojo.query("em,s,strong", node);
+		});
+		if(nodes && nodes.length){
+			dojo.forEach(nodes, function(n){
+				if(n){
+					var tag = n.tagName?n.tagName.toLowerCase():"";
+					var tTag;
+					switch(tag){
+						case "s":
+								tTag = "strike";
+								break;
+						case "em":
+								tTag = "i";
+								break;
+						case "strong":
+								tTag = "b";
+								break;
+					}
+					if(tTag){
+						var nNode = dojo.withGlobal(w, "create", dojo, [tTag, null, n, "before"] );	 
+						while(n.firstChild){
+							nNode.appendChild(n.firstChild);
+						}
+						n.parentNode.removeChild(n);
+					}
+				}
+			});
+		}
+		return node;
+	},
+
+	_convertToCss: function(node){
+		// summary:
+		//		A function to convert the HTML structure of 'node' into 
+		//		css span styles around text instead of sematic tags.
+		//		Note:  It does not do compression of dpans together.
+		// node: DOMNode
+		//		The node to process
+		// tags:
+		//		private
+		if(node){
+			var w = this.editor.window;
+			var convertNode = function(cNode) {
+				if(cNode.nodeType == 1){
+					if(cNode.id !== "dijitEditorBody"){
+						var tag = cNode.tagName?cNode.tagName.toLowerCase():"";
+						if(tag){
+							var span;
+							switch(tag){
+								case "b":
+								case "strong": // Mainly IE
+									span = dojo.withGlobal(w, "create", dojo, ["span", {style: {"fontWeight": "bold"}}] );
+									break;
+								case "i":
+								case "em": // Mainly IE
+									span = dojo.withGlobal(w, "create", dojo, ["span", {style: {"fontStyle": "italic"}}] );
+									break;
+								case "u":
+									span = dojo.withGlobal(w, "create", dojo, ["span", {style: {"textDecoration": "underline"}}] );
+									break;
+								case "strike":
+								case "s": // Mainly WebKit.
+									span = dojo.withGlobal(w, "create", dojo, ["span", {style: {"textDecoration": "line-through"}}] );
+									break;
+								case "font": // Try to deal with colors
+									var styles = {};
+									if(dojo.attr(cNode, "color")){
+										styles.color = dojo.attr(cNode, "color");
+									}
+									if(dojo.attr(cNode, "face")){
+										styles.fontFace = dojo.attr(cNode, "face");
+									}
+									if(cNode.style && cNode.style.backgroundColor){
+										styles.backgroundColor = cNode.style.backgroundColor;
+									}
+									if(cNode.style && cNode.style.color){
+										styles.color = cNode.style.color;
+									}
+									var sizeMap = {
+										1: "xx-small",
+										2: "x-small",
+										3: "small",
+										4: "medium",
+										5: "large",
+										6: "x-large",
+										7: "xx-large"
+									};
+									if(dojo.attr(cNode, "size")){
+										styles.fontSize = sizeMap[dojo.attr(cNode, "size")];
+									}
+									span = dojo.withGlobal(w, "create", dojo, ["span", {style: styles}] );
+									break;
+							}
+							if(span){
+								while(cNode.firstChild){
+									span.appendChild(cNode.firstChild);
+								}
+								dojo.place(span, cNode, "before");
+								cNode.parentNode.removeChild(cNode);
+								cNode = span;
+							}
+						}
+					}
+					if(cNode.childNodes){
+						// Clone it, since we may alter its position
+						var nodes = [];
+						dojo.forEach(cNode.childNodes, function(n){ nodes.push(n);});
+						dojo.forEach(nodes, convertNode);
+					}
+				}
+				return cNode;
+			};
+			node = convertNode(node);
+			if(this.condenseSpans){
+				this._condenseSpans(node);
+			}
+		}
+		return node;
+	},
+
+	_condenseSpans: function(node){
+		// summary:
+		//		Method to condense spans if you end up with multi-wrapping from
+		//		from converting b, i, u, to span nodes.
+		// node:
+		//		The node (and its children), to process.
+		// tags:
+		//		private
+		var compressSpans = function(node){
+			// Okay, span with no class or id and it has styles.
+			// So, merge the styles, then collapse.  Merge requires determining
+			// all the common/different styles and anything that overlaps the style, 
+			// but a different value can't be merged.
+			var genStyleMap = function(styleText){
+				var m;
+				if(styleText){
+					m = {};
+					var styles = styleText.toLowerCase().split(";");
+					dojo.forEach(styles, function(s){
+						if(s){
+							var ss = s.split(":");
+							var key = ss[0] ? dojo.trim(ss[0]): "";
+							var val = ss[1] ? dojo.trim(ss[1]): "";
+							if(key && val){
+								var i;
+								var nKey = "";
+								for(i = 0; i < key.length; i++){
+									var ch = key.charAt(i);
+									if(ch == "-"){
+										i++;
+										ch = key.charAt(i);
+										nKey += ch.toUpperCase();
+									}else{
+										nKey += ch;
+									}
+								}
+								m[nKey] = val;
+							}
+						}
+					});
+				}
+				return m;
+			};
+			if(node && node.nodeType == 1){
+				var tag = node.tagName? node.tagName.toLowerCase() : "";
+				if(tag === "span" && node.childNodes && node.childNodes.length === 1){
+					// Okay, a possibly compressable span
+					var c = node.firstChild;
+					while(c && c.nodeType == 1 && c.tagName && c.tagName.toLowerCase() == "span"){
+						if(!dojo.attr(c, "class") && !dojo.attr(c, "id") && c.style){
+							var s1 = genStyleMap(node.style.cssText);
+							var s2 = genStyleMap(c.style.cssText);
+							if(s1 && s2){
+								// Maps, so lets see if we can combine them.
+								var combinedMap = {};
+								var i;
+								for(i in s1){
+									if(!s1[i] || !s2[i] || s1[i] == s2[i]){
+										combinedMap[i] = s1[i];
+										delete s2[i];
+									}else if(s1[i] != s2[i]){
+										// Collision, cannot merge.
+										// IE does not handle combined uderline strikethrough text
+										// decoraations on a single span.
+										if(i == "textDecoration"){
+											combinedMap[i] = s1[i] + " " + s2[i];
+											delete s2[i];
+										}else{
+											combinedMap = null;	
+										}
+										break;
+									}else{
+										combinedMap = null;
+										break;
+									}
+								}
+								if(combinedMap){
+									for(i in s2){
+										combinedMap[i] = s2[i];
+									}
+									dojo.style(node, combinedMap);
+									while(c.firstChild){
+										node.appendChild(c.firstChild);
+									}
+									var t = c.nextSibling;
+									c.parentNode.removeChild(c);
+									c = t;
+								}else{
+									c = c.nextSibling;
+								}
+							}else{
+								c = c.nextSibling;
+							}
+						}else{
+							c = c.nextSibling;
+						}
+					}
+				}
+			}
+			if(node.childNodes && node.childNodes.length){
+				dojo.forEach(node.childNodes, compressSpans);
+			}
+		};
+		compressSpans(node);
+	},
+	
+	_isInline: function(tag){
+		// summary:
+		//		Function to determine if the current tag is an inline
+		//		element that does formatting, as we don't want to 
+		//		try to combine inlines with divs on styles.
+		// tag:
+		//		The tag to examine
+		// tags:
+		//		private
+		switch(tag){
+			case "a":
+			case "b":
+			case "strong":
+			case "s":
+			case "strike":
+			case "i":
+			case "u":
+			case "em":
+			case "sup":
+			case "sub":
+			case "span":
+			case "font":
+			case "big":
+			case "cite":
+			case "q":
+			case "img":
+			case "small":
+				return true;
+			default:
+				return false;
+		}
+	},
+
+	_inserthtmlImpl: function(html){
+		// summary:
+		//		Function to trap and over-ride the editor inserthtml implementation
+		//		to try and filter it to match the editor's internal styling mode.
+		//		Helpful for plugins like PasteFromWord, in that it extra-filters
+		//		and normalizes the input if it can.
+		// html:
+		//		The HTML string to insert.
+		// tags:
+		//		private
+		if(html){
+			var div = this.editor.document.createElement("div");
+			div.innerHTML = html;
+			div = this._browserFilter(div);
+			html = dijit._editor.getChildrenHtml(div);
+			div.innerHTML = "";
+
+			// Call the over-ride, or if not available, just execute it.
+			if(this.editor._oldInsertHtmlImpl){
+				return this.editor._oldInsertHtmlImpl(html);
+			}else{
+				return this.editor.execCommand("inserthtml", html);
+			}
+		}
+		return false;
+	}
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "normalizestyle"){
+		o.plugin = new dojox.editor.plugins.NormalizeStyle({
+			mode: ("mode" in o.args)?o.args.mode:"semantic",
+			condenseSpans: ("condenseSpans" in o.args)?o.args.condenseSpans:true
+		});
+	}
+});
diff --git a/dojox/editor/plugins/PageBreak.js b/dojox/editor/plugins/PageBreak.js
old mode 100644
new mode 100755
index 8ea179f..ff73f97
--- a/dojox/editor/plugins/PageBreak.js
+++ b/dojox/editor/plugins/PageBreak.js
@@ -1,78 +1,159 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.PageBreak"]){
-dojo._hasResource["dojox.editor.plugins.PageBreak"]=true;
 dojo.provide("dojox.editor.plugins.PageBreak");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojox.editor.plugins","PageBreak",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,zh,zh-tw");
-dojo.declare("dojox.editor.plugins.PageBreak",dijit._editor._Plugin,{useDefaultCommand:false,iconClassPrefix:"dijitAdditionalEditorIcon",_unbreakableNodes:["li","ul","ol"],_pbContent:"<hr style='page-break-after: always;' class='dijitEditorPageBreak'>",_initButton:function(){
-var ed=this.editor;
-var _1=dojo.i18n.getLocalization("dojox.editor.plugins","PageBreak");
-this.button=new dijit.form.Button({label:_1["pageBreak"],showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"PageBreak",tabIndex:"-1",onClick:dojo.hitch(this,"_insertPageBreak")});
-ed.onLoadDeferred.addCallback(dojo.hitch(this,function(){
-ed.addKeyHandler(dojo.keys.ENTER,true,true,dojo.hitch(this,this._insertPageBreak));
-if(dojo.isWebKit||dojo.isOpera){
-this.connect(this.editor,"onKeyDown",dojo.hitch(this,function(e){
-if((e.keyCode===dojo.keys.ENTER)&&e.ctrlKey&&e.shiftKey){
-this._insertPageBreak();
-}
-}));
-}
-}));
-},setEditor:function(_2){
-this.editor=_2;
-this._initButton();
-},_style:function(){
-if(!this._styled){
-this._styled=true;
-var _3=this.editor.document;
-var _4=".dijitEditorPageBreak {\n"+"\tborder-top-style: solid;\n"+"\tborder-top-width: 3px;\n"+"\tborder-top-color: #585858;\n"+"\tborder-bottom-style: solid;\n"+"\tborder-bottom-width: 1px;\n"+"\tborder-bottom-color: #585858;\n"+"\tborder-left-style: solid;\n"+"\tborder-left-width: 1px;\n"+"\tborder-left-color: #585858;\n"+"\tborder-right-style: solid;\n"+"\tborder-right-width: 1px;\n"+"\tborder-right-color: #585858;\n"+"\tcolor: #A4A4A4;\n"+"\tbackground-color: #A4A4A4;\n"+"\theight: 1 [...]
-if(!dojo.isIE){
-var _5=_3.createElement("style");
-_5.appendChild(_3.createTextNode(_4));
-_3.getElementsByTagName("head")[0].appendChild(_5);
-}else{
-var ss=_3.createStyleSheet("");
-ss.cssText=_4;
-}
-}
-},_insertPageBreak:function(){
-try{
-if(!this._styled){
-this._style();
-}
-if(this._allowBreak()){
-this.editor.execCommand("inserthtml",this._pbContent);
-}
-}
-catch(e){
-console.warn(e);
-}
-},_allowBreak:function(){
-var ed=this.editor;
-var _6=ed.document;
-var _7=ed._sCall("getSelectedElement",null)||ed._sCall("getParentElement",null);
-while(_7&&_7!==_6.body&&_7!==_6.html){
-if(ed._sCall("isTag",[_7,this._unbreakableNodes])){
-return false;
-}
-_7=_7.parentNode;
-}
-return true;
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _8=o.args.name.toLowerCase();
-if(_8==="pagebreak"){
-o.plugin=new dojox.editor.plugins.PageBreak({});
-}
+
+dojo.requireLocalization("dojox.editor.plugins", "PageBreak");
+
+dojo.declare("dojox.editor.plugins.PageBreak",dijit._editor._Plugin,{
+	//	summary:
+	//		This plugin provides a simple CSS page break plugin that
+	//		lets you insert browser pring recognizable page breaks in
+	//		the document.
+	//		This plugin registers the hotkey command: CTRL-SHIFT-ENTER
+
+	//	useDefaultCommand [protected]
+	//		Over-ride indicating that the command processing is done all by this plugin.
+	useDefaultCommand: false,
+
+	// iconClassPrefix: [const] String
+	//		The CSS class name for the button node is formed from 
+	//		`iconClassPrefix` and `command`
+	iconClassPrefix: "dijitAdditionalEditorIcon",
+
+	// _unbreakableNodes: [private] Array
+	//		The nodes that should not allow page breaks to be inserted into them.
+	_unbreakableNodes: ["li", "ul", "ol"],
+
+	// _pbContent: [private] String
+	//		The markup used for the pagebreak insert.
+	_pbContent: "<hr style='page-break-after: always;' class='dijitEditorPageBreak'>",
+
+	_initButton: function(){
+		//	summary:
+		//		Over-ride for creation of the resize button.
+		var ed = this.editor;
+		var strings = dojo.i18n.getLocalization("dojox.editor.plugins", "PageBreak");
+		this.button = new dijit.form.Button({
+			label: strings["pageBreak"],
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "PageBreak",
+			tabIndex: "-1",
+			onClick: dojo.hitch(this, "_insertPageBreak")
+		});
+		ed.onLoadDeferred.addCallback(
+			dojo.hitch(this, function(){
+				//Register our hotkey to CTRL-SHIFT-ENTER.
+				ed.addKeyHandler(dojo.keys.ENTER, true, true, dojo.hitch(this, this._insertPageBreak));
+				if(dojo.isWebKit || dojo.isOpera){
+					// Webkit and Opera based browsers don't generate keypress events when ctrl and shift are 
+					// held then enter is pressed.  Odd, that.
+					this.connect(this.editor, "onKeyDown", dojo.hitch(this, function(e){
+						if((e.keyCode === dojo.keys.ENTER) && e.ctrlKey && e.shiftKey){
+							this._insertPageBreak();
+						}
+					}));
+				}
+			})
+		);
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._initButton();
+	},
+
+	_style: function(){
+		// summary:
+		//		Internal function for inserting dynamic css.  This was originally
+		//		in an editor.onLoadDeferred, but I ran into issues in Chrome with 
+		//		the tag being ignored.  Having it done at insert worked better.
+		// tags:
+		//		private
+		if(!this._styled){
+			this._styled = true;
+			var doc = this.editor.document;
+			var style = ".dijitEditorPageBreak {\n" +
+				"\tborder-top-style: solid;\n" +
+				"\tborder-top-width: 3px;\n" +
+				"\tborder-top-color: #585858;\n" +
+				"\tborder-bottom-style: solid;\n" +
+				"\tborder-bottom-width: 1px;\n" +
+				"\tborder-bottom-color: #585858;\n" +
+				"\tborder-left-style: solid;\n" +
+				"\tborder-left-width: 1px;\n" +
+				"\tborder-left-color: #585858;\n" +
+				"\tborder-right-style: solid;\n" +
+				"\tborder-right-width: 1px;\n" +
+				"\tborder-right-color: #585858;\n" +
+				"\tcolor: #A4A4A4;\n" +
+				"\tbackground-color: #A4A4A4;\n" +
+				"\theight: 10px;\n"+
+				"\tpage-break-after: always;\n" +
+				"\tpadding: 0px 0px 0px 0px;\n" +
+			"}\n\n" +
+			"@media print {\n" +
+				"\t.dijitEditorPageBreak { page-break-after: always; " +
+				"background-color: rgba(0,0,0,0); color: rgba(0,0,0,0); " +
+				"border: 0px none rgba(0,0,0,0); display: hidden; " +
+				"width: 0px; height: 0px;}\n" +
+			"}";
+
+			if(!dojo.isIE){
+				var sNode = doc.createElement("style");
+				sNode.appendChild(doc.createTextNode(style));
+				doc.getElementsByTagName("head")[0].appendChild(sNode);
+			}else{
+				var ss = doc.createStyleSheet("");
+				ss.cssText = style;
+			}
+		}
+	},
+
+	_insertPageBreak: function(){
+		// summary:
+		//		Function to insert a CSS page break at the current point in the document
+		// tags:
+		//		private
+		try{
+			if(!this._styled){ this._style(); }
+			//this.editor.focus();
+			if(this._allowBreak()){
+				this.editor.execCommand("inserthtml", this._pbContent);
+			}
+		}catch(e){
+			console.warn(e);
+		}
+	},
+
+	_allowBreak: function(){
+		// summary:
+		//		Internal function to see if we should allow a page break at the document
+		//		location.
+		// tags:
+		//		private
+		var ed = this.editor;
+		var doc = ed.document;
+		var node = ed._sCall("getSelectedElement", null) || ed._sCall("getParentElement", null);
+		while(node && node !== doc.body && node !== doc.html){
+			if(ed._sCall("isTag", [node, this._unbreakableNodes])){
+				return false;
+			}
+			node = node.parentNode;
+		}
+		return true;
+	}
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "pagebreak"){
+		o.plugin = new dojox.editor.plugins.PageBreak({});
+	}
 });
-}
diff --git a/dojox/editor/plugins/PasteFromWord.js b/dojox/editor/plugins/PasteFromWord.js
new file mode 100755
index 0000000..c42737f
--- /dev/null
+++ b/dojox/editor/plugins/PasteFromWord.js
@@ -0,0 +1,206 @@
+dojo.provide("dojox.editor.plugins.PasteFromWord");
+
+dojo.require("dijit._editor._Plugin");
+dojo.require("dijit.form.Button");
+dojo.require("dijit.Dialog");
+dojo.require("dojo.i18n");
+dojo.require("dojo.string");
+dojo.require("dojox.html.format");
+
+dojo.requireLocalization("dojox.editor.plugins", "PasteFromWord");
+
+dojo.declare("dojox.editor.plugins.PasteFromWord",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides PasteFromWord cabability to the editor.  When 
+	//		clicked, a dialog opens with a spartan RichText instance to paste
+	//		word content into via the keyboard commands.  The contents are 
+	//		then filtered to remove word style classes and other meta-junk
+	//		that tends to cause issues.
+
+	// iconClassPrefix: [const] String
+	//		The CSS class name for the button node is formed from `iconClassPrefix` 
+	//		and `command`
+	iconClassPrefix: "dijitAdditionalEditorIcon",
+
+	// width: [public] String
+	//		The width to use for the rich text area in the copy/pate dialog, in px.  Default is 400px.
+	width: "400px",
+
+	// height: [public] String
+	//		The height to use for the rich text area in the copy/pate dialog, in px.  Default is 300px.
+	height: "300px",
+
+	_template: ["<div class='dijitPasteFromWordEmbeddedRTE'>",
+				"<div style='width: ${width}; padding-top: 5px; padding-bottom: 5px;'>${instructions}</div>",
+				"<div id='${uId}_rte' style='width: ${width}; height: ${height}'></div>",
+				"<table style='width: ${width}' tabindex='-1'>", 
+					"<tbody>",
+						"<tr>",
+							"<td align='center'>",
+								"<button type='button' dojoType='dijit.form.Button' id='${uId}_paste'>${paste}</button>",
+								" ",
+								"<button type='button' dojoType='dijit.form.Button' id='${uId}_cancel'>${cancel}</button>",
+							"</td>",
+						"</tr>",
+					"</tbody>",
+				"</table>",
+			   "</div>"].join(""),
+
+	// _filters: [private] Array
+	//		The filters is an array of regular expressions to try and strip out a lot
+	//		of style data MS Word likes to insert when pasting into a contentEditable.
+	//		Prettymuch all of it is junk and not good html.  The hander is a place to put a function 
+	//		for match handling.  In most cases, it just handles it as empty string.  But the option is
+	//		there for more complex handling.
+	_filters: [
+		// Meta tags, link tags, and prefixed tags
+		{regexp: /(<meta\s*[^>]*\s*>)|(<\s*link\s* href="file:[^>]*\s*>)|(<\/?\s*\w+:[^>]*\s*>)/gi, handler: ""},  
+		// Style tags
+		{regexp: /(?:<style([^>]*)>([\s\S]*?)<\/style>|<link\s+(?=[^>]*rel=['"]?stylesheet)([^>]*?href=(['"])([^>]*?)\4[^>\/]*)\/?>)/gi, handler: ""}, 
+		// MS class tags and comment tags.
+		{regexp: /(class="Mso[^"]*")|(<!--(.|\s){1,}?-->)/gi, handler: ""},
+		// blank p tags
+		{regexp: /(<p[^>]*>\s*(\ |\u00A0)*\s*<\/p[^>]*>)|(<p[^>]*>\s*<font[^>]*>\s*(\ |\u00A0)*\s*<\/\s*font\s*>\s<\/p[^>]*>)/ig, handler: ""}, 
+		// Strip out styles containing mso defs and margins, as likely added in IE and are not good to have as it mangles presentation.
+		{regexp: /(style="[^"]*mso-[^;][^"]*")|(style="margin:\s*[^;"]*;")/gi, handler: ""},
+		// Scripts (if any)
+		{regexp: /(<\s*script[^>]*>((.|\s)*?)<\\?\/\s*script\s*>)|(<\s*script\b([^<>]|\s)*>?)|(<[^>]*=(\s|)*[("|')]javascript:[^$1][(\s|.)]*[$1][^>]*>)/ig, handler: ""}
+	],
+
+	_initButton: function(){
+		// summary:
+		//		Over-ride for creation of the save button.
+		var strings = dojo.i18n.getLocalization("dojox.editor.plugins", "PasteFromWord");
+		this.button = new dijit.form.Button({
+			label: strings["pasteFromWord"],
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "PasteFromWord",
+			tabIndex: "-1",
+			onClick: dojo.hitch(this, "_openDialog")
+		});
+
+		this._uId = dijit.getUniqueId(this.editor.id);
+
+		strings.uId = this._uId;
+		strings.width = this.width || "400px";
+		strings.height = this.height || "300px";
+
+		this._dialog = new dijit.Dialog({title: strings["pasteFromWord"]}).placeAt(dojo.body());
+		this._dialog.set("content", dojo.string.substitute(this._template, strings));
+
+		// Make it translucent so we can fade in the window when the RTE is created.
+		// the RTE has to be created 'visible, and this is a ncie trick to make the creation
+		// 'pretty'.
+		dojo.style(dojo.byId(this._uId + "_rte"), "opacity", 0.001);
+
+		// Link up the action buttons to perform the insert or cleanup.
+		this.connect(dijit.byId(this._uId + "_paste"), "onClick", "_paste");
+		this.connect(dijit.byId(this._uId + "_cancel"), "onClick", "_cancel");
+		this.connect(this._dialog, "onHide", "_clearDialog");
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._initButton();
+	},
+
+	_openDialog: function(){
+		// summary:
+		//		Function to trigger opening the copy dialog.
+		// tags:
+		//		private
+		this._dialog.show();
+		if(!this._rte){
+			// RTE hasn't been created yet, so we need to create it now that the 
+			// dialog is showing up.
+			setTimeout(dojo.hitch(this, function() {
+				this._rte = new dijit._editor.RichText({height: this.height || "300px"}, this._uId + "_rte");
+				this._rte.onLoadDeferred.addCallback(dojo.hitch(this, function() {
+					dojo.animateProperty({
+						node: this._rte.domNode, properties: { opacity: { start: 0.001, end: 1.0 } }
+					}).play();
+				}));
+			}), 100);
+		}
+	},
+
+	_paste: function(){
+		// summary:
+		//		Function to handle setting the contents of the copy from dialog 
+		//		into the editor.
+		// tags:
+		//		private
+
+		// Gather the content and try to format it a bit (makes regexp cleanup simpler).
+		// It also normalizes tag names and styles, so regexps are the same across browsers.
+		var content = dojox.html.format.prettyPrint(this._rte.get("value"));
+
+		//Close up the dialog and clear old content.
+		this._dialog.hide();
+		
+		// Apply all the filters to remove MS specific injected text.
+		var i;
+		for(i = 0; i < this._filters.length; i++){
+			var filter  = this._filters[i];
+			content = content.replace(filter.regexp, filter.handler);
+		}
+
+		// Format it again to make sure it is reasonably formatted as
+		// the regexp applies will have likely chewed up the formatting.
+		content = dojox.html.format.prettyPrint(content);
+
+		// Paste it in.
+		this.editor.execCommand("inserthtml", content);
+	},
+
+	_cancel: function(){
+		// summary:
+		//		Function to handle cancelling setting the contents of the 
+		//		copy from dialog into the editor.
+		// tags:
+		//		private
+		this._dialog.hide();
+	},
+
+	_clearDialog: function(){
+		// summary:
+		//		simple function to cleat the contents when hide is calledon dialog
+		//		copy from dialog into the editor.
+		// tags:
+		//		private
+		this._rte.set("value", "");
+	},
+
+	destroy: function(){
+		// sunnary:
+		//		Cleanup function
+		// tags:
+		//		public
+		if(this._rte){
+			this._rte.destroy();
+		}
+		if(this._dialog){
+			this._dialog.destroyRecursive();
+		}
+		delete this._dialog;
+		delete this._rte;
+		this.inherited(arguments);
+	}
+
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "pastefromword"){
+		o.plugin = new dojox.editor.plugins.PasteFromWord({
+			width: ("width" in o.args)?o.args.width:"400px",
+			height: ("height" in o.args)?o.args.width:"300px"
+		});
+	}
+});
diff --git a/dojox/editor/plugins/PrettyPrint.js b/dojox/editor/plugins/PrettyPrint.js
old mode 100644
new mode 100755
index c67218b..bdc24aa
--- a/dojox/editor/plugins/PrettyPrint.js
+++ b/dojox/editor/plugins/PrettyPrint.js
@@ -1,51 +1,100 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.PrettyPrint"]){
-dojo._hasResource["dojox.editor.plugins.PrettyPrint"]=true;
 dojo.provide("dojox.editor.plugins.PrettyPrint");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dojox.html.format");
-dojo.declare("dojox.editor.plugins.PrettyPrint",dijit._editor._Plugin,{indentBy:-1,lineLength:-1,useDefaultCommand:false,entityMap:null,_initButton:function(){
-delete this.command;
-},setToolbar:function(_1){
-},setEditor:function(_2){
-this.inherited(arguments);
-var _3=this;
-this.editor.onLoadDeferred.addCallback(function(){
-_3.editor._prettyprint_getValue=_3.editor.getValue;
-_3.editor.getValue=function(){
-var _4=_3.editor._prettyprint_getValue(arguments);
-return dojox.html.format.prettyPrint(_4,_3.indentBy,_3.lineLength,_3.entityMap,_3.xhtml);
-};
-_3.editor._prettyprint_endEditing=_3.editor._endEditing;
-_3.editor._prettyprint_onBlur=_3.editor._onBlur;
-_3.editor._endEditing=function(_5){
-var v=_3.editor._prettyprint_getValue(true);
-_3.editor._undoedSteps=[];
-_3.editor._steps.push({text:v,bookmark:_3.editor._getBookmark()});
-};
-_3.editor._onBlur=function(e){
-this.inherited("_onBlur",arguments);
-var _6=_3.editor._prettyprint_getValue(true);
-if(_6!=_3.editor.savedContent){
-_3.editor.onChange(_6);
-_3.editor.savedContent=_6;
-}
-};
+
+dojo.declare("dojox.editor.plugins.PrettyPrint",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides a mechanism by wich to 'beautify HTML'
+	//		generated by the editor.  It is by no means perfect.
+
+	// indentBy [public] Integer
+	//		The indentBy property configures if the plugin should use a 
+	//		set number of spaces for indent (between 1-5), or just tab.
+	//		The default value is -1, which means tab.
+	indentBy: -1,
+
+	// lineLength [public] Integer
+	//		The lineLength property configures if the plugin should break up long
+	//		text lines into N lines of 'lineLength' length.  This parameter does not 
+	//		take into account indention depth, only text line length.  The default is -1
+	//		which means unlimited line length.
+	lineLength: -1,
+
+	//	useDefaultCommand [protected]
+	//		Over-ride indicating that the command processing is done all by this plugin.
+	useDefaultCommand: false,
+	
+	// map [public] Array
+	//		An array of arrays that define out entity character to encoding mappings.
+	//		see the dojox.html.entities definitions for more details.  The default is
+	//		HTML + cent, pound, yen, ellipsis, copyright, registered trademark.
+	entityMap: null,
+
+	// xhtml: [public] boolean
+	//		Flag to denote that the PrettyPrint plugin try to generate XHTML compliant 
+	//		markup.
+
+	_initButton: function(){
+		// summary:
+		//		Over-ride for creation of the resize button.
+		delete this.command; 
+	},
+
+	setToolbar: function(toolbar){
+		// summary:
+		//		Over-ride to do nothing.  
+		//		We don't want to append a button, we take over getValue.
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride to take over getValue of editor so that
+		//		we can 'pretty' the output.
+		this.inherited(arguments);
+		var self = this;
+		this.editor.onLoadDeferred.addCallback(function(){
+			self.editor._prettyprint_getValue = self.editor.getValue;
+			self.editor.getValue = function(){
+				var val = self.editor._prettyprint_getValue(arguments);
+				return dojox.html.format.prettyPrint(val, self.indentBy, self.lineLength, self.entityMap, self.xhtml);
+			};
+
+			// The following are implemented as 'performance' functions.  Don't prettyprint
+			// content on internal state changes, just on calls to actually get values.
+			self.editor._prettyprint_endEditing = self.editor._endEditing;
+			self.editor._prettyprint_onBlur = self.editor._onBlur;
+			self.editor._endEditing = function(ignore_caret){
+				var v = self.editor._prettyprint_getValue(true);
+				self.editor._undoedSteps=[];//clear undoed steps
+				self.editor._steps.push({text: v, bookmark: self.editor._getBookmark()});
+			}
+			self.editor._onBlur = function(e){
+				this.inherited("_onBlur", arguments);
+				var _c=self.editor._prettyprint_getValue(true);
+				if(_c!=self.editor.savedContent){
+					self.editor.onChange(_c);
+					self.editor.savedContent=_c;
+				}
+			}
+		});
+	}
 });
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _7=o.args.name.toLowerCase();
-if(_7==="prettyprint"){
-o.plugin=new dojox.editor.plugins.PrettyPrint({indentBy:("indentBy" in o.args)?o.args.indentBy:-1,lineLength:("lineLength" in o.args)?o.args.lineLength:-1,entityMap:("entityMap" in o.args)?o.args.entityMap:dojox.html.entities.html.concat([["¢","cent"],["£","pound"],["€","euro"],["¥","yen"],["©","copy"],["§","sect"],["…","hellip"],["®","reg"]]),xhtml:("xhtml" in o.args)?o.args.xhtml:false});
-}
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "prettyprint"){
+		o.plugin = new dojox.editor.plugins.PrettyPrint({
+			indentBy: ("indentBy" in o.args)?o.args.indentBy:-1,
+			lineLength: ("lineLength" in o.args)?o.args.lineLength:-1,
+			entityMap: ("entityMap" in o.args)?o.args.entityMap:dojox.html.entities.html.concat([
+				["\u00A2","cent"],["\u00A3","pound"],["\u20AC","euro"],
+				["\u00A5","yen"],["\u00A9","copy"],["\u00A7","sect"],
+				["\u2026","hellip"],["\u00AE","reg"]
+			]),
+			xhtml: ("xhtml" in o.args)?o.args.xhtml:false
+		});
+	}
 });
-}
diff --git a/dojox/editor/plugins/Preview.js b/dojox/editor/plugins/Preview.js
old mode 100644
new mode 100755
index 3076a6e..28c1877
--- a/dojox/editor/plugins/Preview.js
+++ b/dojox/editor/plugins/Preview.js
@@ -1,53 +1,93 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.Preview"]){
-dojo._hasResource["dojox.editor.plugins.Preview"]=true;
 dojo.provide("dojox.editor.plugins.Preview");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.form.Button");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojox.editor.plugins","Preview",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,zh,zh-tw");
-dojo.declare("dojox.editor.plugins.Preview",dijit._editor._Plugin,{useDefaultCommand:false,styles:"",stylesheets:null,iconClassPrefix:"dijitAdditionalEditorIcon",_initButton:function(){
-this._nlsResources=dojo.i18n.getLocalization("dojox.editor.plugins","Preview");
-this.button=new dijit.form.Button({label:this._nlsResources["preview"],showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"Preview",tabIndex:"-1",onClick:dojo.hitch(this,"_preview")});
-},setEditor:function(_1){
-this.editor=_1;
-this._initButton();
-},_preview:function(){
-try{
-var _2=this.editor.attr("value");
-var _3="\t\t<meta http-equiv='Content-Type' content='text/html; charset='UTF-8'>\n";
-var i;
-if(this.stylesheets){
-for(i=0;i<this.stylesheets.length;i++){
-_3+="\t\t<link rel='stylesheet' type='text/css' href='"+this.stylesheets[i]+"'>\n";
-}
-}
-if(this.styles){
-_3+=("\t\t<style>"+this.styles+"</style>\n");
-}
-_2="<html>\n\t<head>\n"+_3+"\t</head>\n\t<body>\n"+_2+"\n\t</body>\n</html>";
-var _4=window.open("javascript: ''",this._nlsResources["preview"],"status=1,menubar=0,location=0,toolbar=0");
-_4.document.open();
-_4.document.write(_2);
-_4.document.close();
-}
-catch(e){
-console.warn(e);
-}
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _5=o.args.name.toLowerCase();
-if(_5==="preview"){
-o.plugin=new dojox.editor.plugins.Preview({styles:("styles" in o.args)?o.args.styles:"",stylesheets:("stylesheets" in o.args)?o.args.stylesheets:null});
-}
+
+dojo.requireLocalization("dojox.editor.plugins", "Preview");
+
+dojo.declare("dojox.editor.plugins.Preview",dijit._editor._Plugin,{
+	//	summary:
+	//		This plugin provides Preview cabability to the editor.  When 
+	//		clicked, the document in the editor frame will displayed in a separate
+	//		window/tab
+
+	//	useDefaultCommand [protected]
+	//		Over-ride indicating that the command processing is done all by this plugin.
+	useDefaultCommand: false,
+
+	// styles: [public] String
+	//		A string of CSS styles to apply to the previewed content, if any.
+	styles: "",
+
+	// stylesheets: [public] Array
+	//		An array of stylesheets to import into the preview, if any.
+	stylesheets: null,
+
+	// iconClassPrefix: [const] String
+	//		The CSS class name for the button node icon.
+	iconClassPrefix: "dijitAdditionalEditorIcon",
+
+	_initButton: function(){
+		// summary:
+		//		Over-ride for creation of the preview button.
+		this._nlsResources = dojo.i18n.getLocalization("dojox.editor.plugins", "Preview");
+		this.button = new dijit.form.Button({
+			label: this._nlsResources["preview"],
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "Preview",
+			tabIndex: "-1",
+			onClick: dojo.hitch(this, "_preview")
+		});
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._initButton();
+	},
+
+	_preview: function(){
+		// summary:
+		//		Function to trigger previewing of the editor document
+		// tags:
+		//		private
+		try{
+			var content = this.editor.get("value");
+			var head = "\t\t<meta http-equiv='Content-Type' content='text/html; charset='UTF-8'>\n";
+			var i;
+			// Apply the stylesheets, then apply the styles.
+			if(this.stylesheets){
+				for(i = 0; i < this.stylesheets.length; i++){
+					head += "\t\t<link rel='stylesheet' type='text/css' href='" + this.stylesheets[i] + "'>\n";
+				}
+			}
+			if(this.styles){
+				head += ("\t\t<style>" + this.styles + "</style>\n");
+			}
+			content = "<html>\n\t<head>\n" + head + "\t</head>\n\t<body>\n" + content + "\n\t</body>\n</html>";
+			var win = window.open("javascript: ''", this._nlsResources["preview"], "status=1,menubar=0,location=0,toolbar=0");
+			win.document.open();
+			win.document.write(content);
+			win.document.close();
+
+		}catch(e){
+			console.warn(e);
+		}
+	}
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "preview"){
+		o.plugin = new dojox.editor.plugins.Preview({
+			styles: ("styles" in o.args)?o.args.styles:"",
+			stylesheets: ("stylesheets" in o.args)? o.args.stylesheets:null
+		});
+	}
 });
-}
diff --git a/dojox/editor/plugins/Save.js b/dojox/editor/plugins/Save.js
old mode 100644
new mode 100755
index 97ad907..5bc9255
--- a/dojox/editor/plugins/Save.js
+++ b/dojox/editor/plugins/Save.js
@@ -1,52 +1,130 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.Save"]){
-dojo._hasResource["dojox.editor.plugins.Save"]=true;
 dojo.provide("dojox.editor.plugins.Save");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.form.Button");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojox.editor.plugins","Save",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,zh,zh-tw");
-dojo.declare("dojox.editor.plugins.Save",dijit._editor._Plugin,{iconClassPrefix:"dijitAdditionalEditorIcon",url:"",logResults:true,_initButton:function(){
-var _1=dojo.i18n.getLocalization("dojox.editor.plugins","Save");
-this.button=new dijit.form.Button({label:_1["save"],showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"Save",tabIndex:"-1",onClick:dojo.hitch(this,"_save")});
-},setEditor:function(_2){
-this.editor=_2;
-this._initButton();
-},_save:function(){
-var _3=this.editor.attr("value");
-this.save(_3);
-},save:function(_4){
-var _5={"Content-Type":"text/html"};
-if(this.url){
-var _6={url:this.url,postData:_4,headers:_5,handleAs:"text"};
-this.button.attr("disabled",true);
-var _7=dojo.xhrPost(_6);
-_7.addCallback(dojo.hitch(this,this.onSuccess));
-_7.addErrback(dojo.hitch(this,this.onError));
-}else{
-}
-},onSuccess:function(_8,_9){
-this.button.attr("disabled",false);
-if(this.logResults){
-}
-},onError:function(_a,_b){
-this.button.attr("disabled",false);
-if(this.logResults){
-}
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _c=o.args.name.toLowerCase();
-if(_c==="save"){
-o.plugin=new dojox.editor.plugins.Save({url:("url" in o.args)?o.args.url:"",logResults:("logResults" in o.args)?o.args.logResults:true});
-}
+
+dojo.requireLocalization("dojox.editor.plugins", "Save");
+
+dojo.declare("dojox.editor.plugins.Save",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides Save cabability to the editor.  When 
+	//		clicked, the document in the editor frame will be osted to the URL
+	//		provided, or none, if none provided.  Users who desire a different save
+	//		function can extend this plugin (via dojo.extend) and over-ride the 
+	//		save method	while save is in process, the save button is disabled.
+
+	// iconClassPrefix: [const] String
+	//		The CSS class name for the button node is formed from `iconClassPrefix` 
+	//		and `command`
+	iconClassPrefix: "dijitAdditionalEditorIcon",
+
+	// url [public]	String
+	//		The URL to POST the content back to.  Used by the save function. 
+	url: "",
+
+	// logErrors [public] boolean
+	//		Boolean flag to indicate that the default action for save and 
+	//		error handlers is to just log to console.  Default is true.
+	logResults: true,
+
+	_initButton: function(){
+		// summary:
+		//		Over-ride for creation of the save button.
+		var strings = dojo.i18n.getLocalization("dojox.editor.plugins", "Save");
+		this.button = new dijit.form.Button({
+			label: strings["save"],
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "Save",
+			tabIndex: "-1",
+			onClick: dojo.hitch(this, "_save")
+		});
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._initButton();
+	},
+
+	_save: function(){
+		// summary:
+		//		Function to trigger saving of the editor document
+		// tags:
+		//		private
+		var content = this.editor.get("value");
+		this.save(content);
+	},
+
+	save: function(content){
+		// summary:
+		//		User over-ridable save function for the editor content.
+		//		Please note that the service URL provided should do content
+		//		filtering of the posted content to avoid XSS injection via
+		//		the data from the editor.
+		// tags:
+		//		public
+
+		// Set the default header to post as a body of text/html.
+		var headers = {
+			"Content-Type": "text/html"
+		};
+		if(this.url){
+			var postArgs = {
+				url: this.url,
+				postData: content,
+				headers: headers,
+				handleAs: "text"
+			};
+			this.button.set("disabled", true);
+			var deferred = dojo.xhrPost(postArgs);
+			deferred.addCallback(dojo.hitch(this, this.onSuccess));
+			deferred.addErrback(dojo.hitch(this, this.onError));
+		}else{
+			console.log("No URL provided, no post-back of content: " + content);
+		}
+	},
+
+	onSuccess: function(resp, ioargs){
+		// summary:
+		//		User over-ridable save success function for editor content.  
+		//		Be sure to call this.inherited(arguments) if over-riding this method.
+		// resp:
+		//		The response from the server, if any, in text format.
+		// tags:
+		//		public
+		this.button.set("disabled", false);
+		if(this.logResults){
+			console.log(resp);
+		}
+	},
+
+	onError: function(error, ioargs){
+		// summary:
+		//		User over-ridable save success function for editor content.  
+		//		Be sure to call this.inherited(arguments) if over-riding this method.
+		// resp:
+		//		The response from the server, if any, in text format.
+		// tags:
+		//		public
+		this.button.set("disabled", false);
+		if(this.logResults){
+			console.log(error);
+		}
+	}
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "save"){
+		o.plugin = new dojox.editor.plugins.Save({
+			url: ("url" in o.args)?o.args.url:"",
+			logResults: ("logResults" in o.args)?o.args.logResults:true
+		});
+	}
 });
-}
diff --git a/dojox/editor/plugins/ShowBlockNodes.js b/dojox/editor/plugins/ShowBlockNodes.js
old mode 100644
new mode 100755
index 475ef77..8a3d225
--- a/dojox/editor/plugins/ShowBlockNodes.js
+++ b/dojox/editor/plugins/ShowBlockNodes.js
@@ -1,94 +1,172 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.ShowBlockNodes"]){
-dojo._hasResource["dojox.editor.plugins.ShowBlockNodes"]=true;
 dojo.provide("dojox.editor.plugins.ShowBlockNodes");
+
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.form.Button");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojox.editor.plugins","ShowBlockNodes",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,zh,zh-tw");
-dojo.declare("dojox.editor.plugins.ShowBlockNodes",dijit._editor._Plugin,{useDefaultCommand:false,iconClassPrefix:"dijitAdditionalEditorIcon",_styled:false,_initButton:function(){
-var _1=dojo.i18n.getLocalization("dojox.editor.plugins","ShowBlockNodes");
-this.button=new dijit.form.ToggleButton({label:_1["showBlockNodes"],showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"ShowBlockNodes",tabIndex:"-1",onChange:dojo.hitch(this,"_showBlocks")});
-this.editor.addKeyHandler(dojo.keys.F9,true,true,dojo.hitch(this,this.toggle));
-},setEditor:function(_2){
-this.editor=_2;
-this._initButton();
-},toggle:function(){
-this.button.attr("checked",!this.button.attr("checked"));
-},_showBlocks:function(_3){
-var _4=this.editor.document;
-if(!this._styled){
-try{
-this._styled=true;
-var _5="";
-var _6=["div","p","ul","ol","table","h1","h2","h3","h4","h5","h6","pre","dir","center","blockquote","form","fieldset","address","object","pre","hr","ins","noscript","li","map","button","dd","dt"];
-var _7="@media screen {\n"+"\t.editorShowBlocks {TAG} {\n"+"\t\tbackground-image: url({MODURL}/images/blockelems/{TAG}.gif);\n"+"\t\tbackground-repeat: no-repeat;\n"+"\t\tbackground-position: top left;\n"+"\t\tborder-width: 1px;\n"+"\t\tborder-style: dashed;\n"+"\t\tborder-color: #D0D0D0;\n"+"\t\tpadding-top: 15px;\n"+"\t\tpadding-left: 15px;\n"+"\t}\n"+"}\n";
-dojo.forEach(_6,function(_8){
-_5+=_7.replace(/\{TAG\}/gi,_8);
+
+dojo.requireLocalization("dojox.editor.plugins", "ShowBlockNodes");
+
+dojo.declare("dojox.editor.plugins.ShowBlockNodes",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides ShowBlockNodes cabability to the editor.  When 
+	//		clicked, the document in the editor will apply a class to specific
+	//		block nodes to make them visible in the layout.  This info is not
+	//		exposed/extracted when the editor value is obtained, it is purely for help
+	//		while working on the page.
+
+	// useDefaultCommand [protected] boolean
+	//		Over-ride indicating that the command processing is done all by this plugin.
+	useDefaultCommand: false,
+
+	// iconClassPrefix: [const] String
+	//		The CSS class name for the button node is formed from `iconClassPrefix` and `command`
+	iconClassPrefix: "dijitAdditionalEditorIcon",
+
+	// _styled [private] boolean
+	//		Flag indicating the document has had the style updates applied.
+	_styled: false,
+
+	_initButton: function(){
+		//	summary:
+		//		Over-ride for creation of the preview button.
+		var strings = dojo.i18n.getLocalization("dojox.editor.plugins", "ShowBlockNodes");
+		this.button = new dijit.form.ToggleButton({
+			label: strings["showBlockNodes"],
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "ShowBlockNodes",
+			tabIndex: "-1",
+			onChange: dojo.hitch(this, "_showBlocks")
+		});
+		this.editor.addKeyHandler(dojo.keys.F9, true, true, dojo.hitch(this, this.toggle));
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._initButton();
+	},
+
+	toggle: function(){
+		// summary:
+		//		Function to allow programmatic toggling of the view.
+		this.button.set("checked", !this.button.get("checked"));
+	},
+
+	_showBlocks: function(show){
+		// summary:
+		//		Function to trigger printing of the editor document
+		// tags:
+		//		private
+		var doc = this.editor.document;
+		if(!this._styled){
+			try{
+				//Attempt to inject our specialized style rules for doing this.
+				this._styled = true;
+
+				var style = "";
+				var blocks = ["div", "p", "ul", "ol", "table", "h1", 
+					"h2", "h3", "h4", "h5", "h6", "pre", "dir", "center", 
+					"blockquote", "form", "fieldset", "address", "object",
+					"pre", "hr", "ins", "noscript", "li", "map", "button", 
+					"dd", "dt"];
+
+				var template = "@media screen {\n" +
+						"\t.editorShowBlocks {TAG} {\n" +
+						"\t\tbackground-image: url({MODURL}/images/blockelems/{TAG}.gif);\n" +
+						"\t\tbackground-repeat: no-repeat;\n"	+
+						"\t\tbackground-position: top left;\n" +
+						"\t\tborder-width: 1px;\n" +
+						"\t\tborder-style: dashed;\n" +
+						"\t\tborder-color: #D0D0D0;\n" +
+						"\t\tpadding-top: 15px;\n" +
+						"\t\tpadding-left: 15px;\n" +
+					"\t}\n" +
+				"}\n";
+
+				dojo.forEach(blocks, function(tag){
+					style += template.replace(/\{TAG\}/gi, tag); 
+				});
+
+				//Finally associate in the image locations based off the module url.
+				var modurl = dojo.moduleUrl(dojox._scopeName, "editor/plugins/resources").toString();
+				if(!(modurl.match(/^https?:\/\//i)) &&
+					!(modurl.match(/^file:\/\//i))){
+					// We have to root it to the page location on webkit for some nutball reason. 
+					// Probably has to do with how iframe was loaded.
+					var bUrl;
+					if(modurl.charAt(0) === "/"){
+						//Absolute path on the server, so lets handle...
+						var proto = dojo.doc.location.protocol;
+						var hostn = dojo.doc.location.host;
+						bUrl = 	proto + "//" + hostn;
+					}else{
+						bUrl = this._calcBaseUrl(dojo.global.location.href);
+					}
+					if(bUrl[bUrl.length - 1] !== "/" && modurl.charAt(0) !== "/"){
+						bUrl += "/";
+					}
+					modurl = bUrl + modurl;
+				}
+				// Update all the urls.
+				style = style.replace(/\{MODURL\}/gi, modurl);
+				if(!dojo.isIE){
+					var sNode = doc.createElement("style");
+					sNode.appendChild(doc.createTextNode(style));
+					doc.getElementsByTagName("head")[0].appendChild(sNode);
+				}else{
+					var ss = doc.createStyleSheet("");
+					ss.cssText = style;
+				}
+			}catch(e){
+				console.warn(e);
+			}
+		}
+
+		// Apply/remove the classes based on state.
+		if(show){
+			dojo.addClass(this.editor.editNode, "editorShowBlocks");
+		}else{
+			dojo.removeClass(this.editor.editNode, "editorShowBlocks");
+		}
+	},
+
+	_calcBaseUrl: function(fullUrl) {
+		// summary:
+		//		Internal function used to figure out the full root url (no relatives)
+		//		for loading images in the styles in the iframe.
+		// fullUrl: String
+		//		The full url to tear down to the base.
+		// tags:
+		//		private
+		var baseUrl = null;
+		if (fullUrl !== null) {
+			// Check to see if we need to strip off any query parameters from the Url.
+			var index = fullUrl.indexOf("?");
+			if (index != -1) {
+				fullUrl = fullUrl.substring(0,index);
+			}
+
+			// Now we need to trim if necessary.  If it ends in /, then we don't 
+			// have a filename to trim off so we can return.
+			index = fullUrl.lastIndexOf("/");
+			if (index > 0 && index < fullUrl.length) {
+				baseUrl = fullUrl.substring(0,index);
+			}else{
+				baseUrl = fullUrl;
+			}
+		}
+		return baseUrl; //String
+	}
 });
-var _9=dojo.moduleUrl(dojox._scopeName,"editor/plugins/resources").toString();
-if(!(_9.match(/^https?:\/\//i))&&!(_9.match(/^file:\/\//i))){
-var _a;
-if(_9.charAt(0)==="/"){
-var _b=dojo.doc.location.protocol;
-var _c=dojo.doc.location.host;
-_a=_b+"//"+_c;
-}else{
-_a=this._calcBaseUrl(dojo.global.location.href);
-}
-if(_a[_a.length-1]!=="/"&&_9.charAt(0)!=="/"){
-_a+="/";
-}
-_9=_a+_9;
-}
-_5=_5.replace(/\{MODURL\}/gi,_9);
-if(!dojo.isIE){
-var _d=_4.createElement("style");
-_d.appendChild(_4.createTextNode(_5));
-_4.getElementsByTagName("head")[0].appendChild(_d);
-}else{
-var ss=_4.createStyleSheet("");
-ss.cssText=_5;
-}
-}
-catch(e){
-console.warn(e);
-}
-}
-if(_3){
-dojo.addClass(this.editor.editNode,"editorShowBlocks");
-}else{
-dojo.removeClass(this.editor.editNode,"editorShowBlocks");
-}
-},_calcBaseUrl:function(_e){
-var _f=null;
-if(_e!==null){
-var _10=_e.indexOf("?");
-if(_10!=-1){
-_e=_e.substring(0,_10);
-}
-_10=_e.lastIndexOf("/");
-if(_10>0&&_10<_e.length){
-_f=_e.substring(0,_10);
-}else{
-_f=_e;
-}
-}
-return _f;
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _11=o.args.name.toLowerCase();
-if(_11==="showblocknodes"){
-o.plugin=new dojox.editor.plugins.ShowBlockNodes();
-}
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name ===  "showblocknodes"){
+		o.plugin = new dojox.editor.plugins.ShowBlockNodes();
+	}
 });
-}
diff --git a/dojox/editor/plugins/Smiley.js b/dojox/editor/plugins/Smiley.js
index d6cb95e..0ca3813 100644
--- a/dojox/editor/plugins/Smiley.js
+++ b/dojox/editor/plugins/Smiley.js
@@ -1,41 +1,116 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.Smiley"]){
-dojo._hasResource["dojox.editor.plugins.Smiley"]=true;
 dojo.provide("dojox.editor.plugins.Smiley");
 dojo.experimental("dojox.editor.plugins.Smiley");
+
 dojo.require("dojo.i18n");
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit.form.ToggleButton");
 dojo.require("dijit.form.DropDownButton");
 dojo.require("dojox.editor.plugins._SmileyPalette");
-dojo.requireLocalization("dojox.editor.plugins","Smiley",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,zh,zh-tw");
-dojo.declare("dojox.editor.plugins.Smiley",dijit._editor._Plugin,{iconClassPrefix:"dijitAdditionalEditorIcon",_initButton:function(){
-this.dropDown=new dojox.editor.plugins._SmileyPalette();
-this.connect(this.dropDown,"onChange",function(_1){
-this.button.closeDropDown();
-this.editor.focus();
-this.editor.execCommand("inserthtml",_1);
+
+dojo.requireLocalization("dojox.editor.plugins", "Smiley");
+
+dojo.declare("dojox.editor.plugins.Smiley", dijit._editor._Plugin, {
+	// summary:
+	//		This plugin allows the user to select from emoticons or "smileys"
+	//		to insert at the current cursor position.
+	//
+	// description:
+	//		The commands provided by this plugin are:
+	//		* smiley - inserts the selected emoticon
+
+	// iconClassPrefix: [const] String
+	//		The CSS class name for the button node is formed from `iconClassPrefix` and `command`
+	iconClassPrefix: "dijitAdditionalEditorIcon",
+
+	// a marker for emoticon wrap like [:-)] for regexp convienent
+	// when a message which contains an emoticon stored in a database or view source, this marker include also
+	// but when user enter an emoticon by key board, user don't need to enter this marker.
+	// also emoticon definition character set can not contains this marker
+	emoticonMarker: '[]',
+
+	emoticonImageClass: 'dojoEditorEmoticon',
+
+	_initButton: function(){
+		// summary:
+		//
+		this.dropDown = new dojox.editor.plugins._SmileyPalette();
+		this.connect(this.dropDown, "onChange", function(ascii){
+			this.button.closeDropDown();
+			this.editor.focus();
+			//
+			ascii = this.emoticonMarker.charAt(0) + ascii + this.emoticonMarker.charAt(1);
+			this.editor.execCommand("inserthtml", ascii);
+		});
+		this.i18n = dojo.i18n.getLocalization("dojox.editor.plugins", "Smiley");
+		this.button = new dijit.form.DropDownButton({
+			label: this.i18n.smiley,
+			showLabel: false,
+			iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "Smiley",
+			tabIndex: "-1",
+			dropDown: this.dropDown
+		});
+		this.emoticonImageRegexp = new RegExp("class=(\"|\')" + this.emoticonImageClass + "(\"|\')");
+	},
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this._initButton();
+		this.editor.contentPreFilters.push(dojo.hitch(this, this._preFilterEntities));
+		this.editor.contentPostFilters.push(dojo.hitch(this, this._postFilterEntities));
+	},
+
+	_preFilterEntities: function(/*String content passed in*/ value){
+		// summary:
+		//		A function to filter out emoticons into their UTF-8 character form
+		//		displayed in the editor.  It gets registered with the preFilters
+		//		of the editor.
+		// tags:
+		//		private.
+		//
+		//
+		return value.replace(/\[([^\]]*)\]/g, dojo.hitch(this, this._decode));
+	},
+
+	_postFilterEntities: function(/*String content passed in*/ value){
+		// summary:
+		//		A function to filter out emoticons into encoded form so they
+		//		are properly displayed in the editor.  It gets registered with the
+		//		postFilters of the editor.
+		// tags:
+		//		private.
+		return value.replace(/<img [^>]*>/gi, dojo.hitch(this, this._encode));
+	},
+
+	_decode: function(str, ascii){
+		// summary:
+		//		Pre-filter for editor to convert strings like [:-)] into an <img> of the corresponding smiley
+		var emoticon = dojox.editor.plugins.Emoticon.fromAscii(ascii);
+		return emoticon ? emoticon.imgHtml(this.emoticonImageClass) : ascii;
+	},
+
+	_encode: function(str){
+		// summary:
+		//		Post-filter for editor to convert <img> nodes of smileys into strings like [:-)]
+		
+		// Each <img> node has an alt tag with it's ascii representation, so just use that.
+		// TODO: wouldn't this be easier as a postDomFilter ?
+		if(str.search(this.emoticonImageRegexp) > -1){
+			return this.emoticonMarker.charAt(0) + str.replace(/(<img [^>]*)alt="([^"]*)"([^>]*>)/, "$2") + this.emoticonMarker.charAt(1);
+		}
+		else{
+			return str;
+		}
+	}
 });
-var _2=dojo.i18n.getLocalization("dojox.editor.plugins","Smiley");
-this.button=new dijit.form.DropDownButton({label:_2.smiley,showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"Smiley",tabIndex:"-1",dropDown:this.dropDown});
-},setEditor:function(_3){
-this.editor=_3;
-this._initButton();
-},_preFilterEntities:function(s){
-},_postFilterEntities:function(s){
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-if(o.args.name==="smiley"){
-o.plugin=new dojox.editor.plugins.Smiley();
-}
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	if(o.args.name === "smiley"){
+		o.plugin = new dojox.editor.plugins.Smiley();
+	}
 });
-}
diff --git a/dojox/editor/plugins/StatusBar.js b/dojox/editor/plugins/StatusBar.js
new file mode 100755
index 0000000..79f1e69
--- /dev/null
+++ b/dojox/editor/plugins/StatusBar.js
@@ -0,0 +1,172 @@
+dojo.provide("dojox.editor.plugins.StatusBar");
+
+dojo.require("dijit._editor._Plugin");
+dojo.require("dijit.Toolbar");
+dojo.require("dojox.layout.ResizeHandle");
+
+dojo.experimental("dojox.editor.plugins.StatusBar");
+
+
+dojo.declare("dojox.editor.plugins._StatusBar", [dijit._Widget, dijit._Templated],{
+	// templateString: String
+	//		Template for the widget.  Currently using table to get the alignment behavior and
+	//		bordering I wanted.  Would prefer not to use table, though.
+	templateString: '<div class="dojoxEditorStatusBar">' +
+		'<table><tbody><tr>'+
+		'<td class="dojoxEditorStatusBarText" tabindex="-1" aria-role="presentation" aria-live="aggressive"><span dojoAttachPoint="barContent"> </span></td>' + 
+		'<td><span dojoAttachPoint="handle"></span></td>' +
+		'</tr></tbody><table>'+
+	'</div>',
+
+	_getValueAttr: function(){
+		// summary:
+		//		Over-ride to get the value of the status bar from the widget.
+		// tags:
+		//		Protected
+		return this.barContent.innerHTML;
+	},
+
+	_setValueAttr: function(str){
+		// summary:
+		//		Over-ride to set the value of the status bar from the widget.
+		//		If no value is set, it is replaced with a non-blocking space.
+		// str: String
+		//		The string to set as the status bar content.
+		// tags:
+		//		protected
+		if(str){
+			str = dojo.trim(str);
+			if(!str){
+				str = " ";
+			}
+		}else{
+			str = " ";
+		}
+		this.barContent.innerHTML = str;
+	}
+});
+
+dojo.declare("dojox.editor.plugins.StatusBar",dijit._editor._Plugin,{
+	// summary:
+	//		This plugin provides StatusBar cabability to the editor.
+	//		Basically a footer bar where status can be published.  It also
+	//		puts a resize handle on the status bar, allowing you to resize the
+	//		editor via mouse.
+
+	// statusBar: [protected]
+	//		The status bar and resizer.
+	statusBar: null,
+
+	// resizer: [public] Boolean
+	//		Flag indicating that a resizer should be shown or not.  Default is true.
+	//		There are cases (such as using center pane border container to autoresize the editor
+	//		That a resizer is not valued.
+	resizer: true,
+
+	setEditor: function(editor){
+		// summary:
+		//		Over-ride for the setting of the editor.
+		// editor: Object
+		//		The editor to configure for this plugin to use.
+		this.editor = editor;
+		this.statusBar = new dojox.editor.plugins._StatusBar();
+		if(this.resizer){
+			this.resizeHandle = new dojox.layout.ResizeHandle({targetId: this.editor, activeResize: true}, this.statusBar.handle);
+			this.resizeHandle.startup();
+		}else{
+			dojo.style(this.statusBar.handle.parentNode, "display", "none");
+		}
+		var pos = null;
+		if(editor.footer.lastChild){
+			pos = "after";
+		}
+		dojo.place(this.statusBar.domNode, editor.footer.lastChild || editor.footer, pos);
+		this.statusBar.startup();
+		this.editor.statusBar = this;
+
+		// Register a pub-sub event to listen for status bar messages, in addition to being available off
+		// the editor as a property 'statusBar'
+		this._msgListener = dojo.subscribe(this.editor.id + "_statusBar", dojo.hitch(this, this._setValueAttr));
+	},
+
+	_getValueAttr: function(){
+		// summary:
+		//		Over-ride to get the value of the status bar from the widget.
+		// tags:
+		//	protected
+		return this.statusBar.get("value");
+	},
+
+	_setValueAttr: function(str){
+		// summary:
+		//		Over-ride to set the value of the status bar from the widget.
+		//		If no value is set, it is replaced with a non-blocking space.
+		// str: String
+		//	The String value to set in the bar.
+		// tags:
+		//		protected
+		this.statusBar.set("value", str);
+	},
+
+	set: function(attr, val){
+		// summary:
+		//		Quick and dirty implementation of 'set' pattern
+		// attr:
+		//		The attribute to set.
+		// val:
+		//		The value to set it to.
+		if(attr){
+			var fName = "_set" + attr.charAt(0).toUpperCase() + attr.substring(1, attr.length) + "Attr";
+			if(dojo.isFunction(this[fName])){
+				this[fName](val);
+			}else{
+				this[attr] = val;
+			}
+		}
+	},
+
+	get: function(attr){
+		// summary:
+		//		Quick and dirty implementation of 'get' pattern
+		// attr:
+		//		The attribute to get.
+		if(attr){
+			var fName = "_get" + attr.charAt(0).toUpperCase() + attr.substring(1, attr.length) + "Attr";
+			var f = this[fName];
+			if(dojo.isFunction(f)){
+				return this[fName]();
+			}else{
+				return this[attr];
+			}
+		}
+		return null;
+	},
+
+	destroy: function(){
+		// summary:
+		//		Over-ride to clean up the breadcrumb toolbar.
+		if(this.statusBar){
+			this.statusBar.destroy();
+			delete this.statusBar;
+		}
+		if(this.resizeHandle){
+			this.resizeHandle.destroy();
+			delete this.resizeHandle;
+		}
+		if(this._msgListener){
+			dojo.unsubscribe(this._msgListener);
+			delete this._msgListener;
+		}
+		delete this.editor.statusBar;
+	}
+});
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name === "statusbar"){
+		var resizer = ("resizer" in o.args)?o.args.resizer:true;
+		o.plugin = new dojox.editor.plugins.StatusBar({resizer: resizer});
+	}
+});
diff --git a/dojox/editor/plugins/TablePlugins.js b/dojox/editor/plugins/TablePlugins.js
index 38cbd6b..552f43d 100644
--- a/dojox/editor/plugins/TablePlugins.js
+++ b/dojox/editor/plugins/TablePlugins.js
@@ -1,601 +1,1078 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.TablePlugins"]){
-dojo._hasResource["dojox.editor.plugins.TablePlugins"]=true;
 dojo.provide("dojox.editor.plugins.TablePlugins");
 dojo.require("dijit._editor._Plugin");
 dojo.require("dijit._editor.selection");
 dojo.require("dijit.Menu");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojox.editor.plugins","TableDialog",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
+dojo.requireLocalization("dojox.editor.plugins", "TableDialog");
+
 dojo.experimental("dojox.editor.plugins.TablePlugins");
-dojo.declare("dojox.editor.plugins.GlobalTableHandler",dijit._editor._Plugin,{tablesConnected:false,currentlyAvailable:false,alwaysAvailable:false,availableCurrentlySet:false,initialized:false,tableData:null,shiftKeyDown:false,editorDomNode:null,undoEnabled:dojo.isIE,doMixins:function(){
-dojo.mixin(this.editor,{getAncestorElement:function(_1){
-return dojo.withGlobal(this.window,"getAncestorElement",dijit._editor.selection,[_1]);
-},hasAncestorElement:function(_2){
-return true;
-return dojo.withGlobal(this.window,"hasAncestorElement",dijit._editor.selection,[_2]);
-},selectElement:function(_3){
-dojo.withGlobal(this.window,"selectElement",dijit._editor.selection,[_3]);
-},byId:function(id){
-return dojo.withGlobal(this.window,"byId",dojo,[id]);
-},query:function(_4,_5,_6){
-var ar=dojo.withGlobal(this.window,"query",dojo,[_4,_5]);
-return (_6)?ar[0]:ar;
-}});
-},initialize:function(_7){
-if(this.initialized){
-return;
-}
-this.initialized=true;
-this.editor=_7;
-_7.onLoadDeferred.addCallback(dojo.hitch(this,function(){
-this.editorDomNode=this.editor.editNode||this.editor.iframe.document.body.firstChild;
-dojo.connect(this.editorDomNode,"mouseup",this.editor,"onClick");
-dojo.connect(this.editor,"onDisplayChanged",this,"checkAvailable");
-this.doMixins();
-this.connectDraggable();
-}));
-},getTableInfo:function(_8){
-if(_8){
-this._tempStoreTableData(false);
-}
-if(this.tableData){
-return this.tableData;
-}
-var tr,_9,td,_a,_b,_c,_d,_e;
-td=this.editor.getAncestorElement("td");
-if(td){
-tr=td.parentNode;
-}
-_b=this.editor.getAncestorElement("table");
-_a=dojo.query("td",_b);
-_a.forEach(function(d,i){
-if(td==d){
-_d=i;
-}
-});
-_9=dojo.query("tr",_b);
-_9.forEach(function(r,i){
-if(tr==r){
-_e=i;
-}
-});
-_c=_a.length/_9.length;
-var o={tbl:_b,td:td,tr:tr,trs:_9,tds:_a,rows:_9.length,cols:_c,tdIndex:_d,trIndex:_e,colIndex:_d%_c};
-this.tableData=o;
-this._tempStoreTableData(500);
-return this.tableData;
-},connectDraggable:function(){
-if(!dojo.isIE){
-return;
-}
-this.editorDomNode.ondragstart=dojo.hitch(this,"onDragStart");
-this.editorDomNode.ondragend=dojo.hitch(this,"onDragEnd");
-},onDragStart:function(){
-var e=window.event;
-if(!e.srcElement.id){
-e.srcElement.id="tbl_"+(new Date().getTime());
-}
-},onDragEnd:function(){
-var e=window.event;
-var _f=e.srcElement;
-var id=_f.id;
-var win=this.editor.window;
-if(_f.tagName.toLowerCase()=="table"){
-setTimeout(function(){
-var _10=dojo.withGlobal(win,"byId",dojo,[id]);
-dojo.removeAttr(_10,"align");
-},100);
-}
-},checkAvailable:function(){
-if(this.availableCurrentlySet){
-return this.currentlyAvailable;
-}
-if(!this.editor){
-return false;
-}
-if(this.alwaysAvailable){
-return true;
-}
-this.currentlyAvailable=this.editor.hasAncestorElement("table");
-if(this.currentlyAvailable){
-this.connectTableKeys();
-}else{
-this.disconnectTableKeys();
-}
-this._tempAvailability(500);
-dojo.publish("available",[this.currentlyAvailable]);
-return this.currentlyAvailable;
-},_prepareTable:function(tbl){
-var tds=this.editor.query("td",tbl);
-if(!tds[0].id){
-tds.forEach(function(td,i){
-if(!td.id){
-td.id="tdid"+i+this.getTimeStamp();
-}
-},this);
-}
-return tds;
-},getTimeStamp:function(){
-return Math.floor(new Date().getTime()*1e-8);
-},_tempStoreTableData:function(_11){
-if(_11===true){
-}else{
-if(_11===false){
-this.tableData=null;
-}else{
-if(_11===undefined){
-console.warn("_tempStoreTableData must be passed an argument");
-}else{
-setTimeout(dojo.hitch(this,function(){
-this.tableData=null;
-}),_11);
-}
-}
-}
-},_tempAvailability:function(_12){
-if(_12===true){
-this.availableCurrentlySet=true;
-}else{
-if(_12===false){
-this.availableCurrentlySet=false;
-}else{
-if(_12===undefined){
-console.warn("_tempAvailability must be passed an argument");
-}else{
-this.availableCurrentlySet=true;
-setTimeout(dojo.hitch(this,function(){
-this.availableCurrentlySet=false;
-}),_12);
-}
-}
-}
-},connectTableKeys:function(){
-if(this.tablesConnected){
-return;
-}
-this.tablesConnected=true;
-var _13=(this.editor.iframe)?this.editor.document:this.editor.editNode;
-this.cnKeyDn=dojo.connect(_13,"onkeydown",this,"onKeyDown");
-this.cnKeyUp=dojo.connect(_13,"onkeyup",this,"onKeyUp");
-dojo.connect(_13,"onkeypress",this,"onKeyUp");
-},disconnectTableKeys:function(){
-dojo.disconnect(this.cnKeyDn);
-dojo.disconnect(this.cnKeyUp);
-this.tablesConnected=false;
-},onKeyDown:function(evt){
-var key=evt.keyCode;
-if(key==16){
-this.shiftKeyDown=true;
-}
-if(key==9){
-var o=this.getTableInfo();
-o.tdIndex=(this.shiftKeyDown)?o.tdIndex-1:tabTo=o.tdIndex+1;
-if(o.tdIndex>=0&&o.tdIndex<o.tds.length){
-this.editor.selectElement(o.tds[o.tdIndex]);
-this.currentlyAvailable=true;
-this._tempAvailability(true);
-this._tempStoreTableData(true);
-this.stopEvent=true;
-}else{
-this.stopEvent=false;
-this.onDisplayChanged();
-}
-if(this.stopEvent){
-dojo.stopEvent(evt);
-}
-}
-},onKeyUp:function(evt){
-var key=evt.keyCode;
-if(key==16){
-this.shiftKeyDown=false;
-}
-if(key==37||key==38||key==39||key==40){
-this.onDisplayChanged();
-}
-if(key==9&&this.stopEvent){
-dojo.stopEvent(evt);
-}
-},onDisplayChanged:function(){
-this.currentlyAvailable=false;
-this._tempStoreTableData(false);
-this._tempAvailability(false);
-this.checkAvailable();
-}});
-tablePluginHandler=new dojox.editor.plugins.GlobalTableHandler();
-dojo.declare("dojox.editor.plugins.TablePlugins",dijit._editor._Plugin,{iconClassPrefix:"editorIcon",useDefaultCommand:false,buttonClass:dijit.form.Button,commandName:"",label:"",alwaysAvailable:false,undoEnabled:false,constructor:function(){
-switch(this.commandName){
-case "colorTableCell":
-this.buttonClass=dijit.form.DropDownButton;
-this.dropDown=new dijit.ColorPalette();
-this.connect(this.dropDown,"onChange",function(_14){
-this.modTable(null,_14);
-});
-break;
-case "modifyTable":
-this.buttonClass=dijit.form.Button;
-this.modTable=this.launchModifyDialog;
-break;
-case "insertTable":
-this.alwaysAvailable=true;
-this.buttonClass=dijit.form.Button;
-this.modTable=this.launchInsertDialog;
-break;
-case "tableContextMenu":
-this.connect(this,"setEditor",function(_15){
-_15.onLoadDeferred.addCallback(dojo.hitch(this,function(){
-this._createContextMenu();
-}));
-this.button.domNode.style.display="none";
-});
-break;
-}
-dojo.subscribe("available",this,"onDisplayChanged");
-},onDisplayChanged:function(_16){
-if(!this.alwaysAvailable){
-this.available=_16;
-this.button.attr("disabled",!this.available);
-}
-},setEditor:function(){
-this.inherited(arguments);
-this.onEditorLoaded();
-},onEditorLoaded:function(){
-tablePluginHandler.initialize(this.editor);
-},_createContextMenu:function(){
-var _17=dojo.isMoz?this.editor.editNode:this.editorDomNode;
-var _18=new dijit.Menu({targetNodeIds:[_17],id:"progMenu",contextMenuForWindow:dojo.isIE});
-var _19=dijit.MenuItem;
-var _1a=dojo.i18n.getLocalization("dojox.editor.plugins","TableDialog",this.lang);
-_18.addChild(new _19({label:_1a.selectTableLabel,onClick:dojo.hitch(this,"selectTable")}));
-_18.addChild(new dijit.MenuSeparator());
-_18.addChild(new _19({label:_1a.insertTableRowBeforeLabel,onClick:dojo.hitch(this,"modTable","insertTableRowBefore")}));
-_18.addChild(new _19({label:_1a.insertTableRowAfterLabel,onClick:dojo.hitch(this,"modTable","insertTableRowAfter")}));
-_18.addChild(new _19({label:_1a.insertTableColumnBeforeLabel,onClick:dojo.hitch(this,"modTable","insertTableColumnBefore")}));
-_18.addChild(new _19({label:_1a.insertTableColumnAfterLabel,onClick:dojo.hitch(this,"modTable","insertTableColumnAfter")}));
-_18.addChild(new dijit.MenuSeparator());
-_18.addChild(new _19({label:_1a.deleteTableRowLabel,onClick:dojo.hitch(this,"modTable","deleteTableRow")}));
-_18.addChild(new _19({label:_1a.deleteTableColumnLabel,onClick:dojo.hitch(this,"modTable","deleteTableColumn")}));
-_18._openMyself=function(e){
-if(!tablePluginHandler.checkAvailable()){
-return;
-}
-if(this.leftClickToOpen&&e.button>0){
-return;
-}
-dojo.stopEvent(e);
-var x,y;
-if(dojo.isIE){
-x=e.x;
-y=e.y;
-}else{
-x=e.screenX;
-y=e.screenY+25;
-}
-var _1b=this;
-var _1c=dijit.getFocus(this);
-function _1d(){
-dijit.focus(_1c);
-dijit.popup.close(_1b);
-};
-var res=dijit.popup.open({popup:this,x:x,y:y,onExecute:_1d,onCancel:_1d,orient:this.isLeftToRight()?"L":"R"});
-var v=dijit.getViewport();
-if(res.y+res.h>v.h){
-if(e.screenY-res.h>=0){
-y=e.screenY-res.h;
-}else{
-y=0;
-}
-dijit.popup.close(this);
-res=dijit.popup.open({popup:this,x:x,y:y,onExecute:_1d,onCancel:_1d,orient:this.isLeftToRight()?"L":"R"});
-}
-this.focus();
-this._onBlur=function(){
-this.inherited("_onBlur",arguments);
-dijit.popup.close(this);
-};
-};
-this.menu=_18;
-},selectTable:function(){
-var o=this.getTableInfo();
-dojo.withGlobal(this.editor.window,"selectElement",dijit._editor.selection,[o.tbl]);
-},launchInsertDialog:function(){
-var w=new dojox.editor.plugins.EditorTableDialog({});
-w.show();
-var c=dojo.connect(w,"onBuildTable",this,function(obj){
-dojo.disconnect(c);
-var res=this.editor.execCommand("inserthtml",obj.htmlText);
-});
-},launchModifyDialog:function(){
-var o=this.getTableInfo();
-var w=new dojox.editor.plugins.EditorModifyTableDialog({table:o.tbl});
-w.show();
-this.connect(w,"onSetTable",function(_1e){
-var o=this.getTableInfo();
-dojo.attr(o.td,"bgcolor",_1e);
-});
-},_initButton:function(){
-this.command=this.commandName;
-this.label=this.editor.commands[this.command]=this._makeTitle(this.command);
-this.inherited(arguments);
-delete this.command;
-if(this.commandName!="colorTableCell"){
-this.connect(this.button.domNode,"click","modTable");
-}
-if(this.commandName=="tableContextMenu"){
-this.button.domNode.display="none";
-}
-this.onDisplayChanged(false);
-},modTable:function(cmd,_1f){
-this.begEdit();
-var o=this.getTableInfo();
-var sw=(dojo.isString(cmd))?cmd:this.commandName;
-var r,c,i;
-var _20=false;
-switch(sw){
-case "insertTableRowBefore":
-r=o.tbl.insertRow(o.trIndex);
-for(i=0;i<o.cols;i++){
-c=r.insertCell(-1);
-c.innerHTML=" ";
-}
-break;
-case "insertTableRowAfter":
-r=o.tbl.insertRow(o.trIndex+1);
-for(i=0;i<o.cols;i++){
-c=r.insertCell(-1);
-c.innerHTML=" ";
-}
-break;
-case "insertTableColumnBefore":
-o.trs.forEach(function(r){
-c=r.insertCell(o.colIndex);
-c.innerHTML=" ";
-});
-_20=true;
-break;
-case "insertTableColumnAfter":
-o.trs.forEach(function(r){
-c=r.insertCell(o.colIndex+1);
-c.innerHTML=" ";
-});
-_20=true;
-break;
-case "deleteTableRow":
-o.tbl.deleteRow(o.trIndex);
-break;
-case "deleteTableColumn":
-o.trs.forEach(function(tr){
-tr.deleteCell(o.colIndex);
-});
-_20=true;
-break;
-case "colorTableCell":
-var tds=this.getSelectedCells(o.tbl);
-dojo.forEach(tds,function(td){
-dojo.style(td,"backgroundColor",_1f);
+
+// summary:
+//		A series of plugins that give the Editor the ability to create and edit 
+//		HTML tables. See the end of this document for all avaiable plugins
+//		and dojox/editorPlugins/tests/editorTablePlugs.html for an example
+//
+// example:
+//		|	<div dojoType="dijit.Editor" plugins="[
+//		|			'bold','italic','|',
+//		|			{name: 'dojox.editor.plugins.TablePlugins', command: 'insertTable'},
+//		|			{name: 'dojox.editor.plugins.TablePlugins', command: 'modifyTable'}
+//		|		]">
+//		|		Editor text is here
+//		|	</div>
+//
+// TODO:	
+//		Currently not supporting merging or splitting cells
+//
+// FIXME:	Undo is very buggy, and therefore unimeplented in all browsers 
+//			except IE - which itself has only been lightly tested.
+//
+// FIXME:	Selecting multiple table cells in Firefox looks to be impossible.
+//			This affect the 'colorTableCell' plugin. Cells can still be 
+//			colored individually or in rows.
+
+dojo.declare("dojox.editor.plugins._TableHandler", dijit._editor._Plugin,{
+	// summary:
+	//		A global object that handles common tasks for all the plugins. Since 
+	//		there are several plugins that are all calling common methods, it's preferable
+	//		that they call a centralized location that either has a set variable or a 
+	//		timeout to only repeat code-heavy calls when necessary.
+	//
+	tablesConnected:false,
+	currentlyAvailable: false,
+	alwaysAvailable:false,
+	availableCurrentlySet:false,
+	initialized:false,
+	tableData: null,
+	shiftKeyDown:false,
+	editorDomNode: null,
+	undoEnabled: true, //Using custom undo for all browsers.
+	refCount: 0, 
+	
+	doMixins: function(){
+		
+		dojo.mixin(this.editor,{
+			getAncestorElement: function(tagName){
+				return dojo.withGlobal(this.window, "getAncestorElement",dijit._editor.selection, [tagName]);
+			},
+			hasAncestorElement: function(tagName){
+				return dojo.withGlobal(this.window, "hasAncestorElement",dijit._editor.selection, [tagName]);
+			},
+			selectElement: function(elem){
+				dojo.withGlobal(this.window, "selectElement",dijit._editor.selection, [elem]);
+			},
+			byId: function(id){
+				return dojo.withGlobal(this.window, "byId", dojo, [id]);
+			},
+			query: function(arg, scope, returnFirstOnly){
+				// this shortcut is dubious - not sure scoping is necessary
+				var ar = dojo.withGlobal(this.window, "query", dojo, [arg, scope]);
+				return (returnFirstOnly) ? ar[0] : ar;
+			}
+		});
+
+	},
+	initialize: function(editor){
+		// summary:
+		//		Initialize the global handler upon a plugin's first instance of setEditor
+		//
+		
+		// All plugins will attempt initialization. We only need to do so once.
+		// But keep track so that it is cleaned up when all usage of it for an editor has
+		// been removed.
+		this.refCount++;
+		
+		// Turn on custom undo for all.
+		editor.customUndo = true;
+
+		if(this.initialized){ return; }
+		
+		this.initialized = true;
+		this.editor = editor;
+
+		this.editor._tablePluginHandler = this;
+		
+		//Editor loads async, can't assume doc is ready yet.  So, use the deferred of the
+		//editor to init at the right time.
+		editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){
+			this.editorDomNode = this.editor.editNode || this.editor.iframe.document.body.firstChild;
+			
+			// RichText should have a mouseup connection to recognize drag-selections
+			// Example would be selecting multiple table cells
+			this._myListeners = [];
+			this._myListeners.push(dojo.connect(this.editorDomNode , "mouseup", this.editor, "onClick")); 
+			this._myListeners.push(dojo.connect(this.editor, "onDisplayChanged", this, "checkAvailable"));
+			this._myListeners.push(dojo.connect(this.editor, "onBlur", this, "checkAvailable"));
+			this.doMixins();
+			this.connectDraggable();
+		}));
+	},
+	
+	getTableInfo: function(forceNewData){
+		// summary:
+		//		Gets the table in focus
+		//		Collects info on the table - see return params
+		//
+		if(forceNewData){ this._tempStoreTableData(false); }
+		if(this.tableData){
+			// tableData is set for a short amount of time, so that all 
+			// plugins get the same return without doing the method over
+			//console.log("returning current tableData:", this.tableData);
+			return this.tableData;	
+		}
+		var tr, trs, td, tds, tbl, cols, tdIndex, trIndex;
+
+		td = this.editor.getAncestorElement("td");
+		if(td){ tr = td.parentNode; }
+		
+		tbl = this.editor.getAncestorElement("table");
+		//console.log("td:", td);console.log("tr:", tr);console.log("tbl:", tbl)
+		
+		tds = dojo.query("td", tbl);
+		tds.forEach(function(d, i){
+			if(td==d){tdIndex = i;}
+		});
+		trs = dojo.query("tr", tbl);
+		trs.forEach(function(r, i){
+			if(tr==r){trIndex = i;}
+		});
+		cols = tds.length/trs.length;
+		var o = {
+			tbl:tbl,		// focused table
+			td:td,			// focused TD
+			tr:tr,			// focused TR
+			trs:trs,		// rows
+			tds:tds,		// cells
+			rows:trs.length,// row amount
+			cols:cols,		// column amount
+			tdIndex:tdIndex,// index of focused cell
+			trIndex:trIndex,	// index of focused row
+			colIndex:tdIndex%cols
+		};
+		//console.log("NEW tableData:",o);
+		this.tableData = o;
+		this._tempStoreTableData(500);	
+		return this.tableData;
+	},
+	
+	connectDraggable: function(){
+		// summary:
+		//		Detects drag-n-drop in the editor (could probably be moved to there)
+		//		Currently only checks if item dragged was a TABLE, and removes its align attr
+		//		DOES NOT WORK IN FF - it could - but FF's drag detection is a monster
+		//
+		if(!dojo.isIE){
+			//console.warn("Drag and Drop is currently only detectable in IE.");
+			return;
+		}
+		
+		// IE ONLY
+		this.editorDomNode.ondragstart = dojo.hitch(this, "onDragStart");
+		this.editorDomNode.ondragend = dojo.hitch(this, "onDragEnd");
+		
+		//NOTES:
+		// FF _ Able to detect the drag-over object (the editor.domNode)
+		//	Not able to detect an item's ondrag() event
+		//	Don't know why - I actually got it working when there was an error
+		//	Something to do with different documents or windows I'm sure
+		//
+		//console.log("connectDraggable", tbl);
+		/*tbl.ondragstart=dojo.hitch(this, "onDragStart");
+		
+		tbl.addEventListener("dragstart", dojo.hitch(this, "onDragStart"), false);
+		tbl.addEventListener("drag", dojo.hitch(this, "onDragStart2"), false);
+		tbl.addEventListener("dragend", dojo.hitch(this, "onDragStart3"), false);
+	
+		dojo.withGlobal(this.editor.window, "selectElement",dijit._editor.selection, [tbl]);
+		
+		tbl.ondragstart = function(){
+			//console.log("ondragstart");									
+		};
+		tbl.ondrag = function(){
+			alert("drag")
+			//console.log("ondrag");											
+		*/		
+	},
+	onDragStart: function(){
+		var e = window.event;
+		if(!e.srcElement.id){
+			e.srcElement.id = "tbl_"+(new Date().getTime());	
+		}
+		//console.log("onDragStart", e.srcElement.id);
+	},
+	onDragEnd: function(){
+		// summary:
+		//		Detects that an object has been dragged into place
+		//		Currently, this code is only used for when a table is dragged
+		//		and clears the "align" attribute, so that the table will look
+		//		to be more in the place that the user expected.
+		//		TODO: This code can be used for other things, most 
+		//		notably UNDO, which currently is not quite usable.
+		//		This code could also find itself in the Editor code when it is 
+		//		complete.
+		
+		//console.log("onDragEnd");
+		var e = window.event;
+		var node = e.srcElement;
+		var id = node.id;
+		var win = this.editor.window;
+		//console.log("NODE:", node.tagName, node.id,  dojo.attr(node, "align"));
+		
+		// clearing a table's align attr
+		// TODO: when ondrag becomes more robust, this code block
+		//	should move to its own method
+		if(node.tagName.toLowerCase()=="table"){
+			setTimeout(function(){
+				var node =  dojo.withGlobal(win, "byId", dojo, [id]);
+				dojo.removeAttr(node, "align");
+				//console.log("set", node.tagName, dojo.attr(node, "align"))
+			}, 100);
+		}
+	},
+	checkAvailable: function(){
+		// summary:
+		//		For table plugs
+		//		Checking if a table or part of a table has focus so that 
+		//		Plugs can change their status
+		//
+		if(this.availableCurrentlySet){
+			// availableCurrentlySet is set for a short amount of time, so that all 
+			// plugins get the same return without doing the method over
+			//console.log("availableCurrentlySet:", this.availableCurrentlySet, "currentlyAvailable:", this.currentlyAvailable)
+			return this.currentlyAvailable;
+		}
+		//console.log("G - checkAvailable...");
+		
+		if(!this.editor) {
+			//console.log("editor not ready")
+			return false;
+		}
+		if(this.alwaysAvailable) {
+			//console.log(" return always available")
+			return true;
+		}
+		
+		// Only return avalable if the editor is focused.
+		this.currentlyAvailable = this.editor._focused ? this.editor.hasAncestorElement("table") : false;
+		
+		if(this.currentlyAvailable){
+			this.connectTableKeys();
+		}else{
+			this.disconnectTableKeys();
+		}
+		
+		this._tempAvailability(500);
+		dojo.publish(this.editor.id + "_tablePlugins", [ this.currentlyAvailable ]);
+		return this.currentlyAvailable;
+	},
+	
+	_prepareTable: function(tbl){
+		//	For IE's sake, we are adding IDs to the TDs if none is there
+		//	We go ahead and use it for other code for convenience
+		//	
+		var tds = this.editor.query("td", tbl);
+		console.log("prep:", tds, tbl);
+		if(!tds[0].id){
+			tds.forEach(function(td, i){
+				if(!td.id){
+					td.id = "tdid"+i+this.getTimeStamp();
+				}
+			}, this);
+		}
+		return tds;
+	},
+	
+	getTimeStamp: function(){
+		return Math.floor(new Date().getTime() * 0.00000001);
+	},
+	
+	_tempStoreTableData: function(type){
+		// caching or clearing table data, depending on the arg
+		//
+		if(type===true){
+			//store indefinitely	
+		}else if(type===false){
+			// clear object	
+			this.tableData = null;
+		}else if(type===undefined){
+			console.warn("_tempStoreTableData must be passed an argument");	
+		}else{ 
+			// type is a number/ms
+			setTimeout(dojo.hitch(this, function(){
+				this.tableData = null;											 
+			}), type);
+		}
+	},
+	
+	_tempAvailability: function(type){
+			// caching or clearing availability, depending on the arg
+		if(type===true){
+			//store indefinitely
+			this.availableCurrentlySet = true;
+		}else if(type===false){
+			// clear object	
+			this.availableCurrentlySet = false;
+		}else if(type===undefined){
+			console.warn("_tempAvailability must be passed an argument");	
+		}else{ 
+			// type is a number/ms
+			this.availableCurrentlySet = true;
+			setTimeout(dojo.hitch(this, function(){
+				this.availableCurrentlySet = false;
+			}), type);
+		}
+		
+	},
+	
+	connectTableKeys: function(){
+		// summary:
+		//		When a table is in focus, start detecting keys
+		//		Mainly checking for the TAB key so user can tab 
+		//		through a table (blocking the browser's desire to
+		//		tab away from teh editor completely)
+		if(this.tablesConnected){ return; }
+		this.tablesConnected = true;
+		var node = (this.editor.iframe) ? this.editor.document : this.editor.editNode;
+		this.cnKeyDn = dojo.connect(node, "onkeydown", this, "onKeyDown"); 
+		this.cnKeyUp = dojo.connect(node, "onkeyup", this, "onKeyUp");
+		this._myListeners.push(dojo.connect(node, "onkeypress", this, "onKeyUp"));
+	},
+	
+	disconnectTableKeys: function(){
+		//console.log("disconnect")
+		dojo.disconnect(this.cnKeyDn);
+		dojo.disconnect(this.cnKeyUp);
+		this.tablesConnected = false;
+	},
+	
+	onKeyDown: function(evt){
+		var key = evt.keyCode;
+		//console.log(" -> DOWN:", key);
+		if(key == 16){ this.shiftKeyDown = true;}
+		if(key == 9) {
+			var o = this.getTableInfo();
+			//console.log("TAB ", o.tdIndex, o);
+			// modifying the o.tdIndex in the tableData directly, because we may save it
+			// FIXME: tabTo is a global
+			o.tdIndex = (this.shiftKeyDown) ? o.tdIndex-1 : tabTo = o.tdIndex+1;
+			if(o.tdIndex>=0 && o.tdIndex<o.tds.length){
+				
+				this.editor.selectElement(o.tds[o.tdIndex]);
+				
+				// we know we are still within a table, so block the need
+				//	to run the method
+				this.currentlyAvailable = true;
+				this._tempAvailability(true);
+				// 
+				this._tempStoreTableData(true);
+				this.stopEvent = true;
+			}else{
+				//tabbed out of table
+				this.stopEvent = false;
+				this.onDisplayChanged();
+			}
+			if(this.stopEvent) {
+				dojo.stopEvent(evt);
+			}
+		}
+	},
+	
+	onKeyUp: function(evt){
+		var key = evt.keyCode;
+		//console.log(" -> UP:", key)
+		if(key == 16){ this.shiftKeyDown = false;}
+		if(key == 37 || key == 38 || key == 39 || key == 40 ){
+			// user can arrow or tab out of table - need to recheck
+			this.onDisplayChanged();
+		}
+		if(key == 9 && this.stopEvent){ dojo.stopEvent(evt);}
+	},
+	
+	onDisplayChanged: function(){
+		//console.log("onDisplayChanged")
+		this.currentlyAvailable = false;
+		this._tempStoreTableData(false);
+		this._tempAvailability(false);
+		this.checkAvailable();
+	},
+
+	uninitialize: function(editor){
+		// summary:
+		//		Function to handle cleaning up of connects
+		//		and such.  It only finally destroys everything once
+		//		all 'references' to it have gone.  As in all plugins
+		//		that called init on it destroyed their refs in their 
+		//		cleanup calls.
+		// editor:
+		//		The editor to detach from.
+		if(this.editor == editor){
+			this.refCount--;
+			if(!this.refCount && this.initialized){
+				if(this.tablesConnected){
+					this.disconnectTableKeys();
+				}
+				this.initialized = false;
+				dojo.forEach(this._myListeners, function(l){
+					dojo.disconnect(l);
+				});
+				delete this._myListeners;
+				delete this.editor._tablePluginHandler;
+				delete this.editor;
+			}
+			this.inherited(arguments);
+		}
+	}
 });
-break;
-case "modifyTable":
-break;
-case "insertTable":
-break;
-}
-if(_20){
-this.makeColumnsEven();
-}
-this.endEdit();
-},begEdit:function(){
-if(tablePluginHandler.undoEnabled){
-if(this.editor.customUndo){
-this.editor.beginEditing();
-}else{
-this.valBeforeUndo=this.editor.getValue();
-}
-}
-},endEdit:function(){
-if(tablePluginHandler.undoEnabled){
-if(this.editor.customUndo){
-this.editor.endEditing();
-}else{
-var _21=this.editor.getValue();
-this.editor.setValue(this.valBeforeUndo);
-this.editor.replaceValue(_21);
-}
-this.editor.onDisplayChanged();
-}
-},makeColumnsEven:function(){
-setTimeout(dojo.hitch(this,function(){
-var o=this.getTableInfo(true);
-var w=Math.floor(100/o.cols);
-o.tds.forEach(function(d){
-dojo.attr(d,"width",w+"%");
+
+dojo.declare("dojox.editor.plugins.TablePlugins",
+	dijit._editor._Plugin,
+	{
+		//summary: 
+		//		A collection of Plugins for inserting and modifying tables in the Editor
+		//		See end of this document for all avaiable plugs
+		//		and dojox/editorPlugins/tests/editorTablePlugs.html for an example
+		//
+		//		NOT IMPLEMENTED: Not handling cell merge, span or split
+		//
+		
+		iconClassPrefix: "editorIcon",
+		useDefaultCommand: false,
+		buttonClass: dijit.form.Button,
+		commandName:"",
+		label:"",
+		alwaysAvailable:false,
+		undoEnabled:true,
+		
+		onDisplayChanged: function(withinTable){
+			// subscribed to from the global object's publish method
+			//
+			//console.log("onDisplayChanged", this.commandName);
+			if(!this.alwaysAvailable){
+				this.available = withinTable;
+				this.button.set('disabled', !this.available);
+			}
+		},
+		
+		setEditor: function(editor){
+			this.editor = editor;
+			this.editor.customUndo = true;
+			this.inherited(arguments);
+			this._availableTopic = dojo.subscribe(this.editor.id + "_tablePlugins", this, "onDisplayChanged");
+			this.onEditorLoaded();
+		},
+		onEditorLoaded: function(){
+			if(!this.editor._tablePluginHandler){
+				// Create it and init it off the editor.  This
+				// will create the _tablePluginHandler reference on
+				// the dijit.Editor instance.  This avoids a global.
+				var tablePluginHandler = new dojox.editor.plugins._TableHandler(); 
+				tablePluginHandler.initialize(this.editor);
+			}else{
+				this.editor._tablePluginHandler.initialize(this.editor);
+			}
+		},
+		
+		selectTable: function(){
+			// selects table that is in focus 
+			var o = this.getTableInfo();
+			if(o && o.tbl){
+				dojo.withGlobal(this.editor.window, "selectElement",dijit._editor.selection, [o.tbl]);
+			}
+		},
+		
+		_initButton: function(){
+			this.command = this.commandName;
+			
+			this.label = this.editor.commands[this.command] = this._makeTitle(this.command);
+			this.inherited(arguments);
+			delete this.command;
+			
+			this.connect(this.button, "onClick", "modTable");
+			
+			this.onDisplayChanged(false);
+		},
+		
+		modTable: function(cmd, args){
+			// summary:
+			//		Where each plugin performs its action
+			//		Note: not using execCommand. In spite of their presence in the 
+			//		Editor as query-able plugins, I was not able to find any evidence
+			//		that they are supported (especially in NOT IE). If they are 
+			//		supported in other browsers, it may help with the undo problem.
+			//
+			this.begEdit();
+			var o = this.getTableInfo();
+			var sw = (dojo.isString(cmd))?cmd : this.commandName;
+			var r, c, i;
+			var adjustColWidth = false;
+			//console.log("modTable:", sw)
+
+			if(dojo.isIE){
+				// IE can lose selections on focus changes, so focus back
+				// in order to restore it.
+				this.editor.focus();
+			}
+			switch(sw){
+				case "insertTableRowBefore":
+					r = o.tbl.insertRow(o.trIndex);
+					for(i=0;i<o.cols;i++){
+						c = r.insertCell(-1);
+						c.innerHTML = " ";
+					}
+					break;
+				case "insertTableRowAfter":
+					r = o.tbl.insertRow(o.trIndex+1);
+					for(i=0;i<o.cols;i++){
+						c = r.insertCell(-1);
+						c.innerHTML = " ";
+					}
+					break;
+				case "insertTableColumnBefore":
+					o.trs.forEach(function(r){
+						c = r.insertCell(o.colIndex);
+						c.innerHTML = " ";
+					});
+					adjustColWidth = true;
+					break;
+				case "insertTableColumnAfter":
+					o.trs.forEach(function(r){
+						c = r.insertCell(o.colIndex+1);
+						c.innerHTML = " ";
+					});
+					adjustColWidth = true;
+					break;
+				case "deleteTableRow":
+					o.tbl.deleteRow(o.trIndex);
+					console.log("TableInfo:", this.getTableInfo());
+					break;
+				case "deleteTableColumn":
+					o.trs.forEach(function(tr){
+						tr.deleteCell(o.colIndex);
+					});
+					adjustColWidth = true;
+					break;
+
+				case "modifyTable":
+					break;
+				case "insertTable":
+					break;
+				
+			}
+			if(adjustColWidth){
+				this.makeColumnsEven();
+			}
+			this.endEdit();
+		},
+		
+		begEdit: function(){
+			if(this.editor._tablePluginHandler.undoEnabled){
+				//console.log("UNDO:", this.editor.customUndo);
+				if(this.editor.customUndo){
+					this.editor.beginEditing();
+				}else{
+					this.valBeforeUndo = this.editor.getValue();
+					//console.log("VAL:", this.valBeforeUndo);
+					
+				}
+			}
+		},
+		endEdit: function(){
+			if(this.editor._tablePluginHandler.undoEnabled){
+				if(this.editor.customUndo){
+					this.editor.endEditing();
+				}else{
+					// This code ALMOST works for undo - 
+					//	It seems to only work for one step
+					//	back in history however
+					var afterUndo = this.editor.getValue();
+					//this.editor.execCommand("inserthtml", "<p>mike</p>");
+					this.editor.setValue(this.valBeforeUndo);
+					this.editor.replaceValue(afterUndo);
+				}
+				
+				this.editor.onDisplayChanged();
+			}
+		},
+		
+		makeColumnsEven: function(){
+			//summary:
+			//		After changing column amount, change widths to
+			//		keep columns even
+			//
+			// the timeout helps prevent an occasional snafu
+			setTimeout(dojo.hitch(this, function(){
+				var o = this.getTableInfo(true);
+				var w = Math.floor(100/o.cols);
+				o.tds.forEach(function(d){
+					dojo.attr(d, "width", w+"%");
+				});
+			}), 10);
+		},
+		
+		getTableInfo: function(forceNewData){
+			// summary:
+			//		Gets the table in focus
+			//		Collects info on the table - see return params
+			//
+			return this.editor._tablePluginHandler.getTableInfo(forceNewData);
+		},
+		_makeTitle: function(str){
+			// Parses the commandName into a Title
+			//	based on camelCase
+			var ns = [];
+			dojo.forEach(str, function(c, i){
+				if(c.charCodeAt(0)<91 && i>0 && ns[i-1].charCodeAt(0)!=32){
+					ns.push(" ");
+				}
+				if(i===0){ c = c.toUpperCase();}
+				ns.push(c);
+			});
+			return ns.join("");	
+		},
+		
+		
+		
+		getSelectedCells: function(){
+			// summary:
+			//		Gets the selected cells from the passed table
+			//		Returns: array of TDs or empty array
+			var cells = [];
+			var tbl = this.getTableInfo().tbl;
+			this.editor._tablePluginHandler._prepareTable(tbl);
+			var e = this.editor;
+
+			// Lets do this the way IE originally was (Looking up ids).  Walking the selection
+			// is inconsistent in the browsers (and painful), so going by ids is simpler.
+			var text = dojo.withGlobal(e.window, "getSelectedHtml",dijit._editor.selection, [null]);
+			var str = text.match(/id="*\w*"*/g);
+			dojo.forEach(str, function(a){
+				var id = a.substring(3, a.length);
+				if(id.charAt(0) == "\"" && id.charAt(id.length - 1) == "\""){
+					id = id.substring(1, id.length - 1);
+				}
+				var node = e.byId(id);
+				if(node && node.tagName.toLowerCase() == "td"){
+					cells.push(node);
+				}
+			}, this);
+
+			if(!cells.length){
+				//May just be in a cell (cursor point, or selection in a cell), so look upwards.
+				//for a cell container.
+				var sel = dijit.range.getSelection(e.window);
+				if(sel.rangeCount){
+					var r = sel.getRangeAt(0);
+					var node = r.startContainer;
+					while(node && node != e.editNode && node != e.document){
+						if(node.nodeType === 1){
+							var tg = node.tagName ? node.tagName.toLowerCase() : "";
+							if(tg === "td"){
+								return [node];
+							}
+						}
+						node = node.parentNode;
+					}
+				}
+			}
+			return cells;
+		},
+
+		destroy: function(){
+			// summary:
+			//		Over-ridden destroy to do some cleanup.
+			this.inherited(arguments);
+			dojo.unsubscribe(this._availableTopic);
+
+			// Disconnect the editor from the handler
+			// to clean up refs.  Moved to using a per-editor
+			// 'handler' to avoid collisions on the old global.
+			this.editor._tablePluginHandler.uninitialize(this.editor);
+		}
+		
+	}
+);
+
+dojo.declare("dojox.editor.plugins.TableContextMenu",
+	dojox.editor.plugins.TablePlugins,
+	{
+		constructor: function(){
+			// summary:
+			//		Initialize certain plugins
+			//
+			this.connect(this, "setEditor", function(editor){
+				editor.onLoadDeferred.addCallback(dojo.hitch(this, function() {
+					this._createContextMenu();
+				}));
+				this.button.domNode.style.display = "none";
+			});
+		},	
+		
+		_initButton: function(){
+			this.inherited(arguments);
+			if(this.commandName=="tableContextMenu"){ this.button.domNode.display = "none";}
+		},
+		
+		_createContextMenu: function(){
+			// summary
+			//		Building context menu for right-click shortcuts within a table
+			//
+		
+			var pMenu = new dijit.Menu({targetNodeIds:[this.editor.iframe]});
+			var messages = dojo.i18n.getLocalization("dojox.editor.plugins", "TableDialog", this.lang);
+			pMenu.addChild(new dijit.MenuItem({label: messages.selectTableLabel, onClick: dojo.hitch(this, "selectTable")}));
+			pMenu.addChild(new dijit.MenuSeparator());
+			
+			pMenu.addChild(new dijit.MenuItem({label: messages.insertTableRowBeforeLabel, onClick: dojo.hitch(this, "modTable", "insertTableRowBefore" )}));
+			pMenu.addChild(new dijit.MenuItem({label: messages.insertTableRowAfterLabel, onClick: dojo.hitch(this, "modTable", "insertTableRowAfter" )}));
+			pMenu.addChild(new dijit.MenuItem({label: messages.insertTableColumnBeforeLabel, onClick: dojo.hitch(this, "modTable", "insertTableColumnBefore" )}));
+			pMenu.addChild(new dijit.MenuItem({label: messages.insertTableColumnAfterLabel, onClick: dojo.hitch(this, "modTable", "insertTableColumnAfter" )}));
+			pMenu.addChild(new dijit.MenuSeparator());
+			pMenu.addChild(new dijit.MenuItem({label: messages.deleteTableRowLabel, onClick: dojo.hitch(this, "modTable", "deleteTableRow" )}));
+			pMenu.addChild(new dijit.MenuItem({label: messages.deleteTableColumnLabel, onClick: dojo.hitch(this, "modTable", "deleteTableColumn" )}));
+
+			this.menu = pMenu;
+		}		
 });
-}),10);
-},getTableInfo:function(_22){
-return tablePluginHandler.getTableInfo(_22);
-},_makeTitle:function(str){
-var s=str.split(""),ns=[];
-dojo.forEach(str,function(c,i){
-if(c.charCodeAt(0)<91&&i>0&&ns[i-1].charCodeAt(0)!=32){
-ns.push(" ");
-}
-if(i==0){
-c=c.toUpperCase();
-}
-ns.push(c);
+
+dojo.declare("dojox.editor.plugins.InsertTable",
+	dojox.editor.plugins.TablePlugins,
+	{
+		alwaysAvailable: true,
+					
+		modTable: function(){
+			var w = new dojox.editor.plugins.EditorTableDialog({});
+			w.show();
+			var c = dojo.connect(w, "onBuildTable", this, function(obj){
+				dojo.disconnect(c);
+				
+				var res = this.editor.execCommand('inserthtml', obj.htmlText);
+				
+				// commenting this line, due to msg below
+				//var td = this.editor.query("td", this.editor.byId(obj.id));
+				
+				//HMMMM.... This throws a security error now. didn't used to.
+				//this.editor.selectElement(td);
+			});
+		}	
 });
-return ns.join("");
-},getSelectedCells:function(){
-var _23=[];
-var tbl=this.getTableInfo().tbl;
-var tds=tablePluginHandler._prepareTable(tbl);
-var e=this.editor;
-var r;
-if(!dojo.isIE){
-r=dijit.range.getSelection(e.window);
-var _24=false;
-var _25=false;
-if(r.anchorNode&&r.anchorNode.tagName&&r.anchorNode.tagName.toLowerCase()=="tr"){
-var trs=dojo.query("tr",tbl);
-var _26=[];
-trs.forEach(function(tr,i){
-if(!_24&&(tr==r.anchorNode||tr==r.focusNode)){
-_26.push(tr);
-_24=true;
-if(r.anchorNode==r.focusNode){
-_25=true;
-}
-}else{
-if(_24&&!_25){
-_26.push(tr);
-if(tr==r.anchorNode||tr==r.focusNode){
-_25=true;
-}
-}
-}
+
+dojo.declare("dojox.editor.plugins.ModifyTable",
+	dojox.editor.plugins.TablePlugins,
+	{
+		modTable: function(){
+			if (!this.editor._tablePluginHandler.checkAvailable()) {return;} 
+			var o = this.getTableInfo();
+			//console.log("LAUNCH DIALOG");
+			var w = new dojox.editor.plugins.EditorModifyTableDialog({table:o.tbl});
+			w.show();
+			this.connect(w, "onSetTable", function(color){
+				// uhm... not sure whats going on here...
+				var o = this.getTableInfo();
+				//console.log("set color:", color);
+				dojo.attr(o.td, "bgcolor", color);
+			});
+		}	
 });
-dojo.forEach(_26,function(tr){
-_23=_23.concat(dojo.query("td",tr));
-},this);
-}else{
-tds.forEach(function(td,i){
-if(!_24&&(td.id==r.anchorNode.parentNode.id||td.id==r.focusNode.parentNode.id)){
-_23.push(td);
-_24=true;
-if(r.anchorNode.parentNode.id==r.focusNode.parentNode.id){
-_25=true;
-}
-}else{
-if(_24&&!_25){
-_23.push(td);
-if(td.id==r.focusNode.parentNode.id||td.id==r.anchorNode.parentNode.id){
-_25=true;
-}
-}
-}
+
+dojo.declare("dojox.editor.plugins.ColorTableCell",
+	dojox.editor.plugins.TablePlugins,
+	{
+		
+		constructor: function(){
+			// summary:
+			//		Initialize certain plugins
+			//
+			this.buttonClass = dijit.form.DropDownButton;
+			this.dropDown = new dijit.ColorPalette();
+			this.connect(this.dropDown, "onChange", function(color){
+				this.modTable(null, color);
+			});
+		},
+		
+		_initButton: function(){
+			this.command = this.commandName;
+			
+			this.label = this.editor.commands[this.command] = this._makeTitle(this.command);
+			this.inherited(arguments);
+			delete this.command;
+			
+			this.onDisplayChanged(false);
+		},
+        
+		modTable: function(cmd, args){
+			// summary
+			//	Where each plugin performs its action
+			//	Note: not using execCommand. In spite of their presence in the 
+			//	Editor as query-able plugins, I was not able to find any evidence
+			//	that they are supported (especially in NOT IE). If they are 
+			//	supported in other browsers, it may help with the undo problem.
+			//
+			this.begEdit();
+			var o = this.getTableInfo();			
+			// The one plugin that really needs use of the very verbose
+			//	getSelectedCells()
+			var tds = this.getSelectedCells(o.tbl);
+			//console.debug("SELECTED CELLS ", tds , " FOR ", o);
+			dojo.forEach(tds, function(td){
+				dojo.style(td, "backgroundColor", args);				   
+			});
+			this.endEdit();
+		}
 });
-}
-}
-if(dojo.isIE){
-r=document.selection.createRange();
-var str=r.htmlText.match(/id=\w*/g);
-dojo.forEach(str,function(a){
-var id=a.substring(3,a.length);
-_23.push(e.byId(id));
-},this);
-}
-return _23;
-}});
+
 dojo.provide("dojox.editor.plugins.EditorTableDialog");
 dojo.require("dijit.Dialog");
 dojo.require("dijit.form.TextBox");
 dojo.require("dijit.form.FilteringSelect");
 dojo.require("dijit.form.Button");
-dojo.declare("dojox.editor.plugins.EditorTableDialog",[dijit.Dialog],{baseClass:"EditorTableDialog",widgetsInTemplate:true,templateString:dojo.cache("dojox.editor.plugins","resources/insertTable.html","<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\">${insertTableTitle}</span>\n\t<span do [...]
-var _27=dojo.i18n.getLocalization("dojox.editor.plugins","TableDialog",this.lang);
-dojo.mixin(this,_27);
-this.inherited(arguments);
-},postCreate:function(){
-dojo.addClass(this.domNode,this.baseClass);
-this.inherited(arguments);
-},onInsert:function(){
-var _28=this.selectRow.attr("value")||1,_29=this.selectCol.attr("value")||1,_2a=this.selectWidth.attr("value"),_2b=this.selectWidthType.attr("value"),_2c=this.selectBorder.attr("value"),pad=this.selectPad.attr("value"),_2d=this.selectSpace.attr("value"),_2e="tbl_"+(new Date().getTime()),t="<table id=\""+_2e+"\"width=\""+_2a+((_2b=="percent")?"%":"")+"\" border=\""+_2c+"\" cellspacing=\""+_2d+"\" cellpadding=\""+pad+"\">\n";
-for(var r=0;r<_28;r++){
-t+="\t<tr>\n";
-for(var c=0;c<_29;c++){
-t+="\t\t<td width=\""+(Math.floor(100/_29))+"%\"> </td>\n";
-}
-t+="\t</tr>\n";
-}
-t+="</table>";
-this.onBuildTable({htmlText:t,id:_2e});
-this.hide();
-},onBuildTable:function(_2f){
-}});
+
+dojo.declare("dojox.editor.plugins.EditorTableDialog", [dijit.Dialog], {
+	// summary:
+	//		Dialog box with options for table creation
+	//
+	baseClass:"EditorTableDialog",
+				
+	widgetsInTemplate:true,
+	templateString: dojo.cache("dojox.editor.plugins", "resources/insertTable.html"),
+
+	postMixInProperties: function(){
+		var messages = dojo.i18n.getLocalization("dojox.editor.plugins", "TableDialog", this.lang);
+		dojo.mixin(this, messages);
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		dojo.addClass(this.domNode, this.baseClass); //FIXME - why isn't Dialog accepting the baseClass?
+		this.inherited(arguments);
+	},
+
+	onInsert: function(){
+		console.log("insert");
+		
+		var rows =		this.selectRow.get("value") || 1,
+			cols =		this.selectCol.get("value") || 1,
+			width =		this.selectWidth.get("value"),
+			widthType = this.selectWidthType.get("value"),
+			border =	this.selectBorder.get("value"),
+			pad =		this.selectPad.get("value"),
+			space =		this.selectSpace.get("value"),
+			_id =		"tbl_"+(new Date().getTime()),
+			t = '<table id="'+_id+'"width="'+width+((widthType=="percent")?'%':'')+'" border="'+border+'" cellspacing="'+space+'" cellpadding="'+pad+'">\n';
+		
+		for(var r=0;r<rows;r++){
+			t += '\t<tr>\n';
+			for(var c=0;c<cols;c++){
+				t += '\t\t<td width="'+(Math.floor(100/cols))+'%"> </td>\n';
+			}
+			t += '\t</tr>\n';
+		}
+		t += '</table>';
+		
+		//console.log(t);
+		this.onBuildTable({htmlText:t, id:_id});
+		var cl = dojo.connect(this, "onHide", function(){
+			dojo.disconnect(cl);
+			var self = this;
+			setTimeout(function(){
+				self.destroyRecursive();
+			}, 10);
+		});
+		this.hide();
+	},
+
+	onCancel: function(){
+		// summary:
+		//		Function to clean up memory so that the dialog is destroyed 
+		//		when closed.
+		var c = dojo.connect(this, "onHide", function(){
+			dojo.disconnect(c);
+			var self = this;
+			setTimeout(function(){
+				self.destroyRecursive();
+			}, 10);
+		});
+	},
+
+	onBuildTable: function(tableText){
+		//stub
+	}
+});
+
+
 dojo.provide("dojox.editor.plugins.EditorModifyTableDialog");
 dojo.require("dijit.ColorPalette");
-dojo.declare("dojox.editor.plugins.EditorModifyTableDialog",[dijit.Dialog],{baseClass:"EditorTableDialog",widgetsInTemplate:true,table:null,tableAtts:{},templateString:dojo.cache("dojox.editor.plugins","resources/modifyTable.html","<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\">${modify [...]
-var _30=dojo.i18n.getLocalization("dojox.editor.plugins","TableDialog",this.lang);
-dojo.mixin(this,_30);
-this.inherited(arguments);
-},postCreate:function(){
-dojo.addClass(this.domNode,this.baseClass);
-this.inherited(arguments);
-this.connect(this.borderCol,"click",function(){
-var div=document.createElement("div");
-var w=new dijit.ColorPalette({},div);
-dijit.popup.open({popup:w,around:this.borderCol});
-this.connect(w,"onChange",function(_31){
-dijit.popup.close(w);
-this.setBrdColor(_31);
-});
-});
-this.connect(this.backgroundCol,"click",function(){
-var div=document.createElement("div");
-var w=new dijit.ColorPalette({},div);
-dijit.popup.open({popup:w,around:this.backgroundCol});
-this.connect(w,"onChange",function(_32){
-dijit.popup.close(w);
-this.setBkColor(_32);
-});
+
+dojo.declare("dojox.editor.plugins.EditorModifyTableDialog", [dijit.Dialog], {
+	
+	// summary:
+	//		Dialog box with options for editing a table
+	//
+	
+	baseClass:"EditorTableDialog",
+
+	widgetsInTemplate:true,
+	table:null, //html table to be modified
+	tableAtts:{},
+	templateString: dojo.cache("dojox.editor.plugins", "resources/modifyTable.html"),
+
+	postMixInProperties: function(){
+		var messages = dojo.i18n.getLocalization("dojox.editor.plugins", "TableDialog", this.lang);
+		dojo.mixin(this, messages);
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		dojo.addClass(this.domNode, this.baseClass); //FIXME - why isn't Dialog accepting the baseClass?
+		this.inherited(arguments);
+		this._cleanupWidgets = [];
+		var w1 = new dijit.ColorPalette({});
+		this.connect(w1, "onChange", function(color){
+			dijit.popup.close(w1);
+			this.setBrdColor(color);
+		});
+		this.connect(w1, "onBlur", function(){
+			dijit.popup.close(w1);	
+		});
+		this.connect(this.borderCol, "click", function(){
+			dijit.popup.open({popup:w1, around:this.borderCol});
+			w1.focus();
+		});
+		var w2 = new dijit.ColorPalette({});
+		this.connect(w2, "onChange", function(color){
+			dijit.popup.close(w2);
+			this.setBkColor(color);
+		});
+		this.connect(w2, "onBlur", function(){
+			dijit.popup.close(w2);	
+		});
+		this.connect(this.backgroundCol, "click", function(){
+            dijit.popup.open({popup:w2, around:this.backgroundCol});
+			w2.focus();
+		});
+		this._cleanupWidgets.push(w1);
+		this._cleanupWidgets.push(w2);
+		
+		this.setBrdColor(dojo.attr(this.table, "bordercolor"));
+		this.setBkColor(dojo.attr(this.table, "bgcolor"));
+		var w = dojo.attr(this.table, "width");
+		if(!w){
+			w = this.table.style.width;
+		}
+		var p = "pixels";
+		if(dojo.isString(w) && w.indexOf("%")>-1){
+			p = "percent";
+			w = w.replace(/%/, "");
+		}
+		
+		if(w){
+			this.selectWidth.set("value", w);
+			this.selectWidthType.set("value", p);
+		}else{
+			this.selectWidth.set("value", "");
+			this.selectWidthType.set("value", "percent");
+		}
+		
+		this.selectBorder.set("value", dojo.attr(this.table, "border"));
+		this.selectPad.set("value", dojo.attr(this.table, "cellPadding"));
+		this.selectSpace.set("value", dojo.attr(this.table, "cellSpacing"));
+		this.selectAlign.set("value", dojo.attr(this.table, "align"));
+	},
+	
+	setBrdColor: function(color){
+		this.brdColor = color;
+		dojo.style(this.borderCol, "backgroundColor", color);
+	},
+	
+	setBkColor: function(color){
+		this.bkColor = color;
+		dojo.style(this.backgroundCol, "backgroundColor", color);
+	},
+	onSet: function(){
+		dojo.attr(this.table, "borderColor", this.brdColor);
+		dojo.attr(this.table, "bgColor", this.bkColor);
+		if(this.selectWidth.get("value")){
+			// Just in case, remove it from style since we're setting it as a table attribute.
+			dojo.style(this.table, "width", "");
+			dojo.attr(this.table, "width", (this.selectWidth.get("value") + ((this.selectWidthType.get("value")=="pixels")?"":"%") ));
+		}
+		dojo.attr(this.table, "border", this.selectBorder.get("value"));
+		dojo.attr(this.table, "cellPadding", this.selectPad.get("value"));
+		dojo.attr(this.table, "cellSpacing", this.selectSpace.get("value"));
+		dojo.attr(this.table, "align", this.selectAlign.get("value"));
+		var c = dojo.connect(this, "onHide", function(){
+			dojo.disconnect(c);
+			var self = this;
+			setTimeout(function(){
+				self.destroyRecursive();
+			}, 10);
+		});
+		this.hide();
+	},
+
+	onCancel: function(){
+		// summary:
+		//		Function to clean up memory so that the dialog is destroyed 
+		//		when closed.
+		var c = dojo.connect(this, "onHide", function(){
+			dojo.disconnect(c);
+			var self = this;
+			setTimeout(function(){
+				self.destroyRecursive();
+			}, 10);
+		});
+	},
+
+	onSetTable: function(tableText){
+		//stub
+	},
+
+	destroy: function(){
+		// summary:
+		//		Cleanup function.
+		this.inherited(arguments);
+		dojo.forEach(this._cleanupWidgets, function(w){
+			if(w && w.destroy){
+				w.destroy();
+			}
+		});
+		delete this._cleanupWidgets;
+	}
 });
-this.setBrdColor(dojo.attr(this.table,"bordercolor"));
-this.setBkColor(dojo.attr(this.table,"bgcolor"));
-var w=dojo.attr(this.table,"width");
-var p="pixels";
-if(w.indexOf("%")>-1){
-p="percent";
-w=w.replace(/%/,"");
-}
-this.selectWidth.attr("value",w);
-this.selectWidthType.attr("value",p);
-this.selectBorder.attr("value",dojo.attr(this.table,"border"));
-this.selectPad.attr("value",dojo.attr(this.table,"cellpadding"));
-this.selectSpace.attr("value",dojo.attr(this.table,"cellspacing"));
-this.selectAlign.attr("value",dojo.attr(this.table,"align"));
-},setBrdColor:function(_33){
-this.brdColor=_33;
-dojo.style(this.borderCol,"backgroundColor",_33);
-},setBkColor:function(_34){
-this.bkColor=_34;
-dojo.style(this.backgroundCol,"backgroundColor",_34);
-},onSet:function(){
-dojo.attr(this.table,"bordercolor",this.brdColor);
-dojo.attr(this.table,"bgcolor",this.bkColor);
-dojo.attr(this.table,"width",(this.selectWidth.attr("value")+((this.selectWidthType.attr("value")=="pixels")?"":"%")));
-dojo.attr(this.table,"border",this.selectBorder.attr("value"));
-dojo.attr(this.table,"cellpadding",this.selectPad.attr("value"));
-dojo.attr(this.table,"cellspacing",this.selectSpace.attr("value"));
-dojo.attr(this.table,"align",this.selectAlign.attr("value"));
-this.hide();
-},onSetTable:function(_35){
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-if(o.args&&o.args.command){
-var cmd=o.args.command.charAt(0).toLowerCase()+o.args.command.substring(1,o.args.command.length);
-switch(cmd){
-case "insertTableRowBefore":
-case "insertTableRowAfter":
-case "insertTableColumnBefore":
-case "insertTableColumnAfter":
-case "deleteTableRow":
-case "deleteTableColumn":
-case "colorTableCell":
-case "modifyTable":
-case "insertTable":
-case "tableContextMenu":
-o.plugin=new dojox.editor.plugins.TablePlugins({commandName:cmd});
-break;
-}
-}
+
+
+
+
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	// make first character lower case
+	if(o.args && o.args.command){
+		var cmd = o.args.command.charAt(0).toLowerCase()+o.args.command.substring(1,o.args.command.length);
+		
+		switch(cmd){
+			case "insertTableRowBefore":
+			case "insertTableRowAfter":
+			case "insertTableColumnBefore":
+			case "insertTableColumnAfter":
+			case "deleteTableRow":
+			case "deleteTableColumn":
+				o.plugin = new dojox.editor.plugins.TablePlugins({commandName: cmd});
+				break;
+
+			case "colorTableCell":
+				o.plugin = new dojox.editor.plugins.ColorTableCell({commandName: cmd});
+				break;
+
+			case "modifyTable":
+				o.plugin = new dojox.editor.plugins.ModifyTable({commandName: cmd});
+				break;
+
+			case "insertTable":
+				o.plugin = new dojox.editor.plugins.InsertTable({commandName: cmd});
+				break;
+
+			case "tableContextMenu":
+				o.plugin = new dojox.editor.plugins.TableContextMenu({commandName: cmd});
+				break;
+		}
+	}
 });
-}
diff --git a/dojox/editor/plugins/TextColor.js b/dojox/editor/plugins/TextColor.js
new file mode 100755
index 0000000..37d9cf9
--- /dev/null
+++ b/dojox/editor/plugins/TextColor.js
@@ -0,0 +1,191 @@
+dojo.provide("dojox.editor.plugins.TextColor");
+
+dojo.require("dijit._editor._Plugin");
+dojo.require("dijit.TooltipDialog");
+dojo.require("dijit.form.Button");
+dojo.require("dojox.widget.ColorPicker");
+
+dojo.require("dojo.i18n");
+dojo.requireLocalization("dojox.editor.plugins", "TextColor");
+
+dojo.experimental("dojox.editor.plugins.TextColor");
+
+dojo.declare("dojox.editor.plugins._TextColorDropDown", [dijit._Widget, dijit._Templated], {
+	// summary:
+	//		A smple widget that uses/creates a dropdown with a dojox.widget.ColorPicker.  Also provides
+	//		passthroughs to the value of the color picker and convenient hook points.
+	// tags:
+	//		private
+
+	// templateString: String
+	//		The template used to create the ColorPicker.
+	templateString: "<div style='display: none; position: absolute; top: -10000; z-index: -10000'>" +
+		"<div dojoType='dijit.TooltipDialog' dojoAttachPoint='dialog' class='dojoxEditorColorPicker'>" +
+			"<div dojoType='dojox.widget.ColorPicker' dojoAttachPoint='_colorPicker'></div>" +
+			"<br>" + 
+			"<center>" + 
+				"<button dojoType='dijit.form.Button' type='button' dojoAttachPoint='_setButton'>${setButtonText}</button>" +
+				" " +
+				"<button dojoType='dijit.form.Button' type='button' dojoAttachPoint='_cancelButton'>${cancelButtonText}</button>" +
+			"</center>" +
+		"</div>" +
+		"</div>",
+
+	// widgetsInTemplate: Boolean
+	//		Flag denoting widgets are contained in the template.
+	widgetsInTemplate: true,
+
+	constructor: function(){
+		// summary:
+		//		Constructor over-ride so that the translated strings are mixsed in so
+		//		the template fills out.
+		var strings = dojo.i18n.getLocalization("dojox.editor.plugins", "TextColor");
+		dojo.mixin(this, strings);
+	},
+
+	startup: function(){
+		// summary:
+		//		Over-ride of startup to do the basic connect setups and such.
+		if(!this._started){
+			this.inherited(arguments);
+			this.connect(this._setButton, "onClick", dojo.hitch(this, function(){
+				this.onChange(this.get("value"));
+			}));
+			this.connect(this._cancelButton, "onClick", dojo.hitch(this, function(){
+				dijit.popup.close(this.dialog);
+				this.onCancel();
+			}));
+			// Fully statred, so go ahead and remove the hide.
+			dojo.style(this.domNode, "display", "block");
+		}
+	},
+
+	_setValueAttr: function(value, priorityChange){
+		// summary:
+		//		Passthrough function for the color picker value.
+		// value: String
+		//		The value to set in the color picker
+		// priorityChange:
+		//		Value to indicate whether or not to trigger an onChange event.
+		this._colorPicker.set("value", value, priorityChange);
+	},
+
+	_getValueAttr: function(){
+		// summary:
+		//		Passthrough function for the color picker value.
+		return this._colorPicker.get("value");
+	},
+
+	onChange: function(value){
+		// summary:
+		//		Hook point to get the value when the color picker value is selected.
+		// value: String
+		//		The value from the color picker.
+	},
+
+	onCancel: function(){
+		// summary:
+		//		Hook point to get when the dialog is canceled.
+	}
+});
+
+
+dojo.declare("dojox.editor.plugins.TextColor", dijit._editor._Plugin, {
+	// summary:
+	//		This plugin provides dropdown color pickers for setting text color and background color
+	//		and makes use of the nicer-looking (though not entirely accessible), dojox.widget.ColorPicker.
+	//
+	// description:
+	//		The commands provided by this plugin are:
+	//		* foreColor - sets the text color
+	//		* hiliteColor - sets the background color
+	
+	// Override _Plugin.buttonClass to use DropDownButton (with ColorPalette) to control this plugin
+	buttonClass: dijit.form.DropDownButton,
+	
+	// useDefaultCommand: Boolean
+	//		False as we do not use the default editor command/click behavior.
+	useDefaultCommand: false,
+
+	constructor: function(){
+		this._picker = new dojox.editor.plugins._TextColorDropDown();
+		dojo.body().appendChild(this._picker.domNode);
+		this._picker.startup();
+		this.dropDown = this._picker.dialog;
+		this.connect(this._picker, "onChange", function(color){
+			this.editor.execCommand(this.command, color);
+		});
+		this.connect(this._picker, "onCancel", function(){
+			this.editor.focus();
+		});
+	},
+
+	updateState: function(){
+		// summary:
+		//		Overrides _Plugin.updateState().  This updates the ColorPalette
+		//		to show the color of the currently selected text.
+		// tags:
+		//		protected
+		var _e = this.editor;
+		var _c = this.command;
+		if(!_e || !_e.isLoaded || !_c.length){
+			return;
+		}
+		
+		var value;
+		if(this.button){
+			try{
+				value = _e.queryCommandValue(_c)|| "";
+			}catch(e){
+				//Firefox may throw error above if the editor is just loaded, ignore it
+				value = "";
+			}
+		}
+		
+		if(value == ""){
+			value = "#000000";
+		}
+		if(value == "transparent"){
+			value = "#ffffff";
+		}
+
+		if(typeof value == "string"){
+			//if RGB value, convert to hex value	
+			if(value.indexOf("rgb")> -1){
+				value = dojo.colorFromRgb(value).toHex();
+			}
+		}else{	//it's an integer(IE returns an MS access #)
+			value =((value & 0x0000ff)<< 16)|(value & 0x00ff00)|((value & 0xff0000)>>> 16);
+			value = value.toString(16);
+			value = "#000000".slice(0, 7 - value.length)+ value;
+			
+		}
+		
+		if(value !== this._picker.get('value')){
+			this._picker.set('value', value, false);
+		}
+	},
+
+	destroy: function(){
+		// summary:
+		//		Over-ride cleanup function.
+		this.inherited(arguments);
+		this._picker.destroyRecursive();
+		delete this._picker;
+	}
+});
+
+// Register this plugin.  Uses the same name as the dijit one, so you 
+// use one or the other, not both.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin", null, function(o){
+	if(o.plugin){
+		return;
+	}
+	switch(o.args.name){
+		case "foreColor":
+		case "hiliteColor":
+			o.plugin = new dojox.editor.plugins.TextColor({
+				command: o.args.name
+			});
+	}
+});
diff --git a/dojox/editor/plugins/ToolbarLineBreak.js b/dojox/editor/plugins/ToolbarLineBreak.js
old mode 100644
new mode 100755
index c23c950..695e72a
--- a/dojox/editor/plugins/ToolbarLineBreak.js
+++ b/dojox/editor/plugins/ToolbarLineBreak.js
@@ -1,28 +1,37 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.ToolbarLineBreak"]){
-dojo._hasResource["dojox.editor.plugins.ToolbarLineBreak"]=true;
 dojo.provide("dojox.editor.plugins.ToolbarLineBreak");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._editor._Plugin");
-dojo.declare("dojox.editor.plugins._ToolbarLineBreak",[dijit._Widget,dijit._Templated],{templateString:"<span class='dijit dijitReset'><br></span>",postCreate:function(){
-dojo.setSelectable(this.domNode,false);
-},isFocusable:function(){
-return false;
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-var _1=o.args.name.toLowerCase();
-if(_1==="||"||_1==="toolbarlinebreak"){
-o.plugin=new dijit._editor._Plugin({button:new dojox.editor.plugins._ToolbarLineBreak()});
-}
+
+dojo.declare("dojox.editor.plugins._ToolbarLineBreak",
+	[ dijit._Widget, dijit._Templated ],
+	{
+	// summary:
+	//		A 'line break' between two `dijit.Toolbar` items so that very 
+	//		long toolbars can be organized a bit.
+	templateString: "<span class='dijit dijitReset'><br></span>",
+	postCreate: function(){ dojo.setSelectable(this.domNode, false); },
+	isFocusable: function(){ 
+		// summary:
+		//		This widget isn't focusable, so pass along that fact.
+		// tags:
+		//		protected
+		return false; 
+	}
+});
+
+
+// Register this plugin.
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	var name = o.args.name.toLowerCase();
+	if(name ===  "||" || name === "toolbarlinebreak"){
+		o.plugin = new dijit._editor._Plugin({
+			button: new dojox.editor.plugins._ToolbarLineBreak(),
+			setEditor: function(editor){
+				this.editor = editor;
+			}
+		});
+	}
 });
-}
diff --git a/dojox/editor/plugins/UploadImage.js b/dojox/editor/plugins/UploadImage.js
index 47ea06c..dece07c 100644
--- a/dojox/editor/plugins/UploadImage.js
+++ b/dojox/editor/plugins/UploadImage.js
@@ -1,58 +1,96 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins.UploadImage"]){
-dojo._hasResource["dojox.editor.plugins.UploadImage"]=true;
 dojo.provide("dojox.editor.plugins.UploadImage");
 dojo.require("dijit._editor._Plugin");
 dojo.require("dojox.form.FileUploader");
+
 dojo.experimental("dojox.editor.plugins.UploadImage");
-dojo.declare("dojox.editor.plugins.UploadImage",dijit._editor._Plugin,{tempImageUrl:"",iconClassPrefix:"editorIcon",useDefaultCommand:false,uploadUrl:"",button:null,label:"Upload",setToolbar:function(_1){
-this.button.destroy();
-this.createFileInput();
-_1.addChild(this.button);
-},_initButton:function(){
-this.command="uploadImage";
-this.editor.commands[this.command]="Upload Image";
-this.inherited("_initButton",arguments);
-delete this.command;
-},createFileInput:function(){
-var _2=dojo.create("span",{innerHTML:"."},document.body);
-dojo.style(_2,{width:"40px",height:"20px",paddingLeft:"8px",paddingRight:"8px"});
-this.button=new dojox.form.FileUploader({isDebug:true,uploadUrl:this.uploadUrl,uploadOnChange:true,selectMultipleFiles:false,baseClass:"dojoxEditorUploadNorm",hoverClass:"dojoxEditorUploadHover",activeClass:"dojoxEditorUploadActive",disabledClass:"dojoxEditorUploadDisabled"},_2);
-this.connect(this.button,"onChange","insertTempImage");
-this.connect(this.button,"onComplete","onComplete");
-},onComplete:function(_3,_4,_5){
-_3=_3[0];
-var _6=dojo.withGlobal(this.editor.window,"byId",dojo,[this.currentImageId]);
-var _7;
-if(this.downloadPath){
-_7=this.downloadPath+_3.name;
-}else{
-_7=_3.file;
-}
-_6.src=_7;
-dojo.attr(_6,"_djrealurl",_7);
-if(_3.width){
-_6.width=_3.width;
-_6.height=_3.height;
-}
-},insertTempImage:function(){
-this.currentImageId="img_"+(new Date().getTime());
-var _8="<img id=\""+this.currentImageId+"\" src=\""+this.tempImageUrl+"\" width=\"32\" height=\"32\"/>";
-this.editor.execCommand("inserthtml",_8);
-}});
-dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){
-if(o.plugin){
-return;
-}
-switch(o.args.name){
-case "uploadImage":
-o.plugin=new dojox.editor.plugins.UploadImage({url:o.args.url});
-}
+
+dojo.declare("dojox.editor.plugins.UploadImage",
+	dijit._editor._Plugin,
+	{
+		//summary: 
+		// 	Adds an icon to the Editor toolbar that when clicked, opens a system dialog
+		//	Although the toolbar icon is a tiny "image" the uploader could be used for 
+		//	any file type
+		
+		tempImageUrl: "",
+		iconClassPrefix: "editorIcon",
+		useDefaultCommand: false,
+		uploadUrl: "",
+		button:null,
+		label:"Upload",
+		
+		setToolbar: function(toolbar){
+			this.button.destroy();
+			this.createFileInput();
+			toolbar.addChild(this.button);
+		},
+		_initButton: function(){
+			this.command = "uploadImage";
+			this.editor.commands[this.command] = "Upload Image";
+			this.inherited("_initButton", arguments);
+			delete this.command;
+		},
+		
+		createFileInput: function(){
+			var node = dojo.create('span', {innerHTML:"."}, document.body)
+			dojo.style(node, {
+				width:"40px",
+				height:"20px",
+				paddingLeft:"8px",
+				paddingRight:"8px"
+			})
+			this.button = new dojox.form.FileUploader({
+				isDebug:true,
+				//force:"html",
+				uploadUrl:this.uploadUrl,
+				uploadOnChange:true,
+				selectMultipleFiles:false,
+				baseClass:"dojoxEditorUploadNorm",
+				hoverClass:"dojoxEditorUploadHover",
+				activeClass:"dojoxEditorUploadActive",
+				disabledClass:"dojoxEditorUploadDisabled"
+			}, node);
+			this.connect(this.button, "onChange", "insertTempImage");
+			this.connect(this.button, "onComplete", "onComplete");
+		},
+		
+		onComplete: function(data,ioArgs,widgetRef){
+			data = data[0];
+			// Image is ready to insert
+			var tmpImgNode = dojo.withGlobal(this.editor.window, "byId", dojo, [this.currentImageId]);
+			var file;
+			// download path is mainly used so we can access a PHP script
+			// not relative to this file. The server *should* return a qualified path.
+			if(this.downloadPath){
+				file = this.downloadPath+data.name
+			}else{
+				file = data.file;
+			}
+			
+			tmpImgNode.src = file;
+			dojo.attr(tmpImgNode,'_djrealurl',file);
+
+			if(data.width){
+				tmpImgNode.width = data.width;
+				tmpImgNode.height = data.height;
+			}
+		},
+		
+		insertTempImage: function(){
+			// inserting a "busy" image to show something is hapening
+			//	during upload and download of the image.
+			this.currentImageId = "img_"+(new Date().getTime()); 
+			var iTxt = '<img id="'+this.currentImageId+'" src="'+this.tempImageUrl+'" width="32" height="32"/>';
+			this.editor.execCommand('inserthtml', iTxt);
+		}
+		
+	}
+);
+
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+	if(o.plugin){ return; }
+	switch(o.args.name){
+	case "uploadImage":
+		o.plugin = new dojox.editor.plugins.UploadImage({url: o.args.url});
+	}
 });
-}
diff --git a/dojox/editor/plugins/_SmileyPalette.js b/dojox/editor/plugins/_SmileyPalette.js
index 8d46478..ecb0c7e 100644
--- a/dojox/editor/plugins/_SmileyPalette.js
+++ b/dojox/editor/plugins/_SmileyPalette.js
@@ -1,129 +1,142 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.editor.plugins._SmileyPalette"]){
-dojo._hasResource["dojox.editor.plugins._SmileyPalette"]=true;
 dojo.provide("dojox.editor.plugins._SmileyPalette");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dojo.i18n");
-dojo.requireLocalization("dojox.editor.plugins","Smiley",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,zh,zh-tw");
+
+dojo.require("dijit._PaletteMixin");
+
+dojo.requireLocalization("dojox.editor.plugins", "Smiley");
+
 dojo.experimental("dojox.editor.plugins._SmileyPalette");
-dojo.declare("dojox.editor.plugins._SmileyPalette",[dijit._Widget,dijit._Templated],{templateString:"<div class=\"dojoxEntityPalette\">\n"+"<table>\n"+"<tbody>\n"+"<tr>\n"+"<td>\n"+"<table class=\"dojoxEntityPaletteTable\"  waiRole=\"grid\" tabIndex=\"${tabIndex}\">\n"+"<tbody dojoAttachPoint=\"tableNode\"></tbody>\n"+"</table>\n"+"</td>\n"+"</tr>\n"+"</tbody>\n"+"</table>\n"+"</div>",defaultTimeout:500,timeoutChangeRate:0.9,smileys:{emoticonSmile:":-)",emoticonLaughing:"lol",emoticonWin [...]
-if(!this._created){
-this._created=true;
-this.domNode.style.position="relative";
-this._cellNodes=[];
-var _1=0;
-var _2;
-for(_2 in this.smileys){
-_1++;
-}
-var _3=Math.floor(Math.sqrt(_1));
-var _4=_3;
-var _5=0;
-var _6=null;
-var _7;
-for(_2 in this.smileys){
-var _8=_5%_4===0;
-if(_8){
-_6=dojo.create("tr",{tabIndex:"-1"});
-}
-var _9=this.smileys[_2],_a=dojo.i18n.getLocalization("dojox.editor.plugins","Smiley")[_2];
-_7=dojo.create("td",{tabIndex:"-1","class":"dojoxEntityPaletteCell"},_6);
-var _b=dojo.create("img",{src:dojo.moduleUrl("dojox.editor.plugins","resources/emoticons/"+_2+".gif"),"class":"dojoxSmileyPaletteImg dojoxSmiley"+_2.charAt(0).toUpperCase()+_2.substring(1),title:_a,alt:_a},_7);
-dojo.forEach(["Dijitclick","MouseEnter","Focus","Blur"],function(_c){
-this.connect(_7,"on"+_c.toLowerCase(),"_onCell"+_c);
-},this);
-if(_8){
-dojo.place(_6,this.tableNode);
-}
-dijit.setWaiRole(_7,"gridcell");
-_7.index=this._cellNodes.length;
-this._cellNodes.push({node:_7,html:"<span class='"+_2+"'>"+this.smileys[_2]+"</span>"});
-_5++;
-}
-var _d=_3-(_1%_3);
-while(_d>0){
-_7=dojo.create("td",{innerHTML:"",tabIndex:"-1","class":"dojoxEntityPaletteNullCell"},_6);
-_d--;
-}
-this._xDim=_3;
-this._yDim=_4;
-this.connect(this.tableNode,"onfocus","_onTableNodeFocus");
-var _e={UP_ARROW:-this._xDim,DOWN_ARROW:this._xDim,RIGHT_ARROW:1,LEFT_ARROW:-1};
-for(var _f in _e){
-this._connects.push(dijit.typematic.addKeyListener(this.domNode,{charOrCode:dojo.keys[_f],ctrlKey:false,altKey:false,shiftKey:false},this,function(){
-var _10=_e[_f];
-return function(_11){
-this._navigateByKey(_10,_11);
-};
-}(),this.timeoutChangeRate,this.defaultTimeout));
-}
-}
-},focus:function(){
-this._focusFirst();
-},onChange:function(_12){
-},_focusFirst:function(){
-this._currentFocus=0;
-var _13=this._cellNodes[this._currentFocus].node;
-setTimeout(function(){
-dijit.focus(_13);
-},25);
-},_onTableNodeFocus:function(evt){
-if(evt.target===this.tableNode){
-this._focusFirst();
-}
-},_onFocus:function(){
-dojo.attr(this.tableNode,"tabIndex","-1");
-},_onBlur:function(){
-this._removeCellHighlight(this._currentFocus);
-dojo.attr(this.tableNode,"tabIndex",this.tabIndex);
-},_onCellDijitclick:function(evt){
-var _14=evt.currentTarget;
-if(this._currentFocus!=_14.index){
-this._currentFocus=_14.index;
-setTimeout(function(){
-dijit.focus(_14);
-},0);
-}
-this._selectEntity(_14);
-dojo.stopEvent(evt);
-},_onCellMouseEnter:function(evt){
-var _15=evt.currentTarget;
-this._setCurrent(_15);
-setTimeout(function(){
-dijit.focus(_15);
-},0);
-},_onCellFocus:function(evt){
-this._setCurrent(evt.currentTarget);
-},_setCurrent:function(_16){
-this._removeCellHighlight(this._currentFocus);
-this._currentFocus=_16.index;
-dojo.addClass(_16,"dojoxEntityPaletteCellHighlight");
-},_onCellBlur:function(evt){
-this._removeCellHighlight(this._currentFocus);
-},_removeCellHighlight:function(_17){
-dojo.removeClass(this._cellNodes[_17].node,"dojoxEntityPaletteCellHighlight");
-},_selectEntity:function(_18){
-var _19=dojo.filter(this._cellNodes,function(_1a){
-return _1a.node==_18;
+
+dojo.declare("dojox.editor.plugins._SmileyPalette",
+	[dijit._Widget, dijit._Templated, dijit._PaletteMixin],
+	{
+	// summary:
+	//		A keyboard accessible emoticon-picking widget (for inserting smiley characters)
+	// description:
+	//		Grid showing various emoticons.
+	//		Can be used standalone, or as a popup.
+	//
+	// example:
+	// |	<div dojoType="dojox.editor.plugins._SmileyPalette"></div>
+	//
+	// example:
+	// |	var picker = new dojox.editor.plugins._SmileyPalette({ },srcNode);
+	// |	picker.startup();
+
+	//		The template of this widget.
+	templateString: 
+		'<table class="dijitInline dijitEditorSmileyPalette dijitPaletteTable"' +
+		' cellSpacing=0 cellPadding=0><tbody dojoAttachPoint="gridNode"></tbody></table>',
+
+	baseClass: "dijitEditorSmileyPalette",
+
+	_palette: [
+			["smile", "laughing", "wink", "grin"],
+			["cool", "angry", "half", "eyebrow"],
+			["frown", "shy", "goofy", "oops"],
+			["tongue", "idea", "angel", "happy"],
+			["yes", "no", "crying", ""]
+	],
+
+	dyeClass: 'dojox.editor.plugins.Emoticon',
+
+	buildRendering: function(){
+		// Instantiate the template, which makes a skeleton into which we'll insert a bunch of
+		// <img> nodes
+		this.inherited(arguments);
+
+		var i18n = dojo.i18n.getLocalization("dojox.editor.plugins", "Smiley");
+		
+		// Generate hash from emoticon standard name (like "smile") to translation
+		var emoticonI18n = {};
+		for(var name in i18n){
+			if(name.substr(0,8) == "emoticon"){
+				emoticonI18n[name.substr(8).toLowerCase()] = i18n[name]; 
+			}
+		}
+        this._preparePalette(
+			this._palette,
+			emoticonI18n
+		);
+	}
+});
+
+dojo.declare("dojox.editor.plugins.Emoticon",
+	null,
+	{
+		// summary:
+		//		JS Object representing an emoticon
+
+		constructor: function(/*String*/ id){
+			// summary:
+			//	 Create emoticon object from an id (like "smile")
+			// value: String
+			//		alias name 'smile', 'cool' ..
+			this.id = id;
+		},
+
+		getValue: function(){
+			// summary:
+			//   Returns a emoticon string in ascii representation, ex: :-)
+			return dojox.editor.plugins.Emoticon.ascii[this.id];
+		},
+
+		imgHtml: function(/*String*/ clazz){
+			// summary:
+			//		Return the HTML string for an <img> node that shows this smiley
+			var eId = "emoticon" + this.id.substr(0,1).toUpperCase() + this.id.substr(1),
+				src = dojo.moduleUrl("dojox.editor.plugins", "resources/emoticons/" + eId + ".gif"),
+				label = dojo.i18n.getLocalization("dojox.editor.plugins", "Smiley")[eId],
+					html = ['<img src=\"',
+					src,
+					'\" class=\"',
+					clazz,
+					'\" alt=\"',
+					this.getValue(),
+					'\" title=\"',
+					label,
+					'\">'];
+			return html.join("");
+		},
+
+		fillCell: function(/*DOMNode*/cell, /*String*/ blankGif){
+			dojo.place(this.imgHtml("dijitPaletteImg"), cell);
+		}
 });
-if(_19.length>0){
-this.onChange(this.value=_19[0].html);
-}
-},_navigateByKey:function(_1b,_1c){
-if(_1c==-1){
-return;
-}
-var _1d=this._currentFocus+_1b;
-if(_1d<this._cellNodes.length&&_1d>-1){
-var _1e=this._cellNodes[_1d].node;
-_1e.focus();
-}
-}});
-}
+
+dojox.editor.plugins.Emoticon.ascii = {
+	smile: ":-)",
+	laughing: "lol",
+	wink: ";-)",
+	grin: ":-D",
+	cool: "8-)",
+	angry: ":-@",
+	half: ":-/",
+	eyebrow: "/:)",
+	frown: ":-(",
+	shy: ":-$",
+	goofy: ":-S",
+	oops: ":-O",
+	tongue: ":-P",
+	idea: "(i)",
+	yes: "(y)",
+	no: "(n)",
+	angel: "0:-)",
+	crying: ":'(",
+	happy: "=)"
+};
+
+dojox.editor.plugins.Emoticon.fromAscii = function(/*String*/str){
+	// summary:
+	//		Factory to create Emoticon object based on string like ":-)" rather than id like "smile"
+	var ascii = dojox.editor.plugins.Emoticon.ascii;
+	for(var i in ascii){
+		if(str == ascii[i]){
+			return new dojox.editor.plugins.Emoticon(i);
+		}
+	}
+	return null;
+};
diff --git a/dojox/editor/plugins/nls/Blockquote.js b/dojox/editor/plugins/nls/Blockquote.js
new file mode 100755
index 0000000..423f216
--- /dev/null
+++ b/dojox/editor/plugins/nls/Blockquote.js
@@ -0,0 +1,3 @@
+({
+	"blockquote": "Blockquote"
+})
\ No newline at end of file
diff --git a/dojox/editor/plugins/nls/Breadcrumb.js b/dojox/editor/plugins/nls/Breadcrumb.js
old mode 100644
new mode 100755
index c498573..26a8ee7
--- a/dojox/editor/plugins/nls/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/Breadcrumb.js
@@ -1 +1,9 @@
-({"selectContents":"Select contents","deleteElement":"Delete element","moveEnd":"Move cursor to end","deleteContents":"Delete contents","nodeActions":"${nodeName} Actions","selectElement":"Select element","moveStart":"Move cursor to start"})
\ No newline at end of file
+({
+	"nodeActions": "${nodeName} Actions",
+	"selectContents": "Select contents",
+	"selectElement": "Select element",
+	"deleteElement": "Delete element",
+	"deleteContents": "Delete contents",
+	"moveStart": "Move cursor to start",
+	"moveEnd": "Move cursor to end"
+})
diff --git a/dojox/editor/plugins/nls/CollapsibleToolbar.js b/dojox/editor/plugins/nls/CollapsibleToolbar.js
new file mode 100755
index 0000000..13dd736
--- /dev/null
+++ b/dojox/editor/plugins/nls/CollapsibleToolbar.js
@@ -0,0 +1,4 @@
+({
+	"collapse": "Collapse Editor Toolbar",
+	"expand": "Expand Editor Toolbar"
+})
\ No newline at end of file
diff --git a/dojox/editor/plugins/nls/FindReplace.js b/dojox/editor/plugins/nls/FindReplace.js
old mode 100644
new mode 100755
index cb40bc4..21cff9a
--- a/dojox/editor/plugins/nls/FindReplace.js
+++ b/dojox/editor/plugins/nls/FindReplace.js
@@ -1 +1,21 @@
-({"backwards":"Backwards","findReplace":"Toggle Find/Replace","replaceAll":"All Occurances","replaceDialogText":"Replaced ${0} occurances.","replaceButton":"Replace","findButton":"Find","findLabel":"Find what:","matchCase":"Match Case","replaceLabel":"Replace with:"})
\ No newline at end of file
+({
+	"findLabel": "Find:",
+	"findTooltip": "Enter text to find",
+	"replaceLabel": "Replace with:",
+	"replaceTooltip": "Enter text to replace with",
+	"findReplace": "Find and Replace",
+	"matchCase": "Match case",
+	"matchCaseTooltip": "Match case",
+	"backwards": "Backwards",
+	"backwardsTooltip": "Search backwards for text",
+	"replaceAllButton": "Replace All",
+	"replaceAllButtonTooltip": "Replace all the text",
+	"findButton": "Find",
+	"findButtonTooltip": "Find the text",
+	"replaceButton": "Replace",
+	"replaceButtonTooltip": "Replace the text",
+	"replaceDialogText": "Replaced ${0} occurrences.",
+	"eofDialogText": "Last occurrence ${0}",
+	"eofDialogTextFind": "found",
+	"eofDialogTextReplace": "replaced"
+})
diff --git a/dojox/editor/plugins/nls/InsertAnchor.js b/dojox/editor/plugins/nls/InsertAnchor.js
new file mode 100755
index 0000000..4470ebe
--- /dev/null
+++ b/dojox/editor/plugins/nls/InsertAnchor.js
@@ -0,0 +1,8 @@
+({
+	insertAnchor: "Insert Anchor",
+	title: "Anchor Properties",
+	anchor: "Name:",
+	text: "Description:",
+	set: "Set",
+	cancel: "Cancel"
+})
diff --git a/dojox/editor/plugins/nls/InsertEntity.js b/dojox/editor/plugins/nls/InsertEntity.js
old mode 100644
new mode 100755
index 7914b89..9342d16
--- a/dojox/editor/plugins/nls/InsertEntity.js
+++ b/dojox/editor/plugins/nls/InsertEntity.js
@@ -1 +1,3 @@
-({"insertEntity":"Insert Symbol"})
\ No newline at end of file
+({
+	insertEntity: "Insert Symbol"
+})
\ No newline at end of file
diff --git a/dojox/editor/plugins/nls/PageBreak.js b/dojox/editor/plugins/nls/PageBreak.js
old mode 100644
new mode 100755
index 4eaca96..4f06fd6
--- a/dojox/editor/plugins/nls/PageBreak.js
+++ b/dojox/editor/plugins/nls/PageBreak.js
@@ -1 +1,3 @@
-({"pageBreak":"Page Break"})
\ No newline at end of file
+({
+	"pageBreak": "Page Break"
+})
\ No newline at end of file
diff --git a/dojox/editor/plugins/nls/PasteFromWord.js b/dojox/editor/plugins/nls/PasteFromWord.js
new file mode 100755
index 0000000..c062165
--- /dev/null
+++ b/dojox/editor/plugins/nls/PasteFromWord.js
@@ -0,0 +1,6 @@
+({
+	"pasteFromWord": "Paste From  Word",
+	"paste": "Paste",
+	"cancel": "Cancel",
+	"instructions": "Paste the content from Word into the text box below.  Once you are satisfied with the content to insert, press the paste button.  To abort inserting text, press the cancel button."
+})
\ No newline at end of file
diff --git a/dojox/editor/plugins/nls/Preview.js b/dojox/editor/plugins/nls/Preview.js
old mode 100644
new mode 100755
index f54aeb4..25d3e81
--- a/dojox/editor/plugins/nls/Preview.js
+++ b/dojox/editor/plugins/nls/Preview.js
@@ -1 +1,3 @@
-({"preview":"Preview"})
\ No newline at end of file
+({
+	"preview": "Preview"
+})
\ No newline at end of file
diff --git a/dojox/editor/plugins/nls/Save.js b/dojox/editor/plugins/nls/Save.js
old mode 100644
new mode 100755
index 8f8072a..253100a
--- a/dojox/editor/plugins/nls/Save.js
+++ b/dojox/editor/plugins/nls/Save.js
@@ -1 +1,3 @@
-({"save":"Save"})
\ No newline at end of file
+({
+	"save": "Save"
+})
\ No newline at end of file
diff --git a/dojox/editor/plugins/nls/ShowBlockNodes.js b/dojox/editor/plugins/nls/ShowBlockNodes.js
old mode 100644
new mode 100755
index d9c3dbd..bc84151
--- a/dojox/editor/plugins/nls/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/ShowBlockNodes.js
@@ -1 +1,3 @@
-({"showBlockNodes":"Show HTML Block Elements"})
\ No newline at end of file
+({
+	"showBlockNodes": "Show HTML Block Elements"
+})
diff --git a/dojox/editor/plugins/nls/Smiley.js b/dojox/editor/plugins/nls/Smiley.js
index 6a6b5a2..caf0623 100644
--- a/dojox/editor/plugins/nls/Smiley.js
+++ b/dojox/editor/plugins/nls/Smiley.js
@@ -1 +1,21 @@
-({"emoticonLaughing":"laughing","emoticonCool":"cool","emoticonTongue":"tongue","emoticonCrying":"crying","emoticonOops":"oops","emoticonFrown":"frown","emoticonAngry":"angry","emoticonShy":"shy","emoticonNo":"no","emoticonAngel":"angel","smiley":"Insert Emoticon","emoticonIdea":"idea","emoticonEyebrow":"eyebrow","emoticonSmile":"smile","emoticonWink":"wink","emoticonYes":"yes","emoticonGrin":"grin","emoticonGoofy":"goofy","emoticonHalf":"half"})
\ No newline at end of file
+({
+	smiley: "Insert Emoticon",
+	emoticonSmile: "smile",
+	emoticonLaughing: "laughing",
+	emoticonWink: "wink",
+	emoticonGrin: "grin",
+	emoticonCool: "cool",
+	emoticonAngry: "angry",  
+	emoticonHalf: "half", 
+	emoticonEyebrow: "eyebrow",
+	emoticonFrown: "frown",
+	emoticonShy: "shy",
+	emoticonGoofy: "goofy",
+	emoticonOops: "oops",
+	emoticonTongue: "tongue",
+	emoticonIdea: "idea",
+	emoticonYes: "yes",
+	emoticonNo: "no",	
+	emoticonAngel: "angel",
+	emoticonCrying: "crying"
+})
diff --git a/dojox/editor/plugins/nls/TableDialog.js b/dojox/editor/plugins/nls/TableDialog.js
index 3e2f71f..ca9001b 100644
--- a/dojox/editor/plugins/nls/TableDialog.js
+++ b/dojox/editor/plugins/nls/TableDialog.js
@@ -1 +1,29 @@
-({"buttonSet":"Set","insertTableTitle":"Insert Table","insertTableRowAfterLabel":"Add Row After","center":"center","deleteTableColumnLabel":"Delete Column","right":"right","insertTableColumnBeforeLabel":"Add Column Before","tableWidth":"Table Width:","buttonInsert":"Insert","default":"default","align":"Align:","insertTableRowBeforeLabel":"Add Row Before","cellSpacing":"Cell Spacing:","pixels":"pixels","selectTableLabel":"Select Table","rows":"Rows:","modifyTableTitle":"Modify Table","cel [...]
\ No newline at end of file
+({
+	insertTableTitle: "Insert Table",
+	modifyTableTitle: "Modify Table",
+	rows: "Rows:",
+	columns: "Columns:",
+	align: "Align:",
+	cellPadding: "Cell Padding:",
+	cellSpacing: "Cell Spacing:",
+	tableWidth: "Table Width:",
+	backgroundColor: "Background Color:",
+	borderColor: "Border Color:",
+	borderThickness: "BorderThickness",
+	percent: "percent",
+	pixels: "pixels",
+	"default": "default",
+	left: "left",
+	center: "center",
+	right: "right",
+	buttonSet: "Set", // translated elsewhere?
+	buttonInsert: "Insert",
+
+	selectTableLabel: "Select Table",
+	insertTableRowBeforeLabel: "Add Row Before",
+	insertTableRowAfterLabel: "Add Row After",
+	insertTableColumnBeforeLabel: "Add Column Before",
+	insertTableColumnAfterLabel: "Add Column After",
+	deleteTableRowLabel: "Delete Row",
+	deleteTableColumnLabel: "Delete Column"
+})
diff --git a/dojox/editor/plugins/nls/TextColor.js b/dojox/editor/plugins/nls/TextColor.js
new file mode 100755
index 0000000..3a623ab
--- /dev/null
+++ b/dojox/editor/plugins/nls/TextColor.js
@@ -0,0 +1,4 @@
+({
+	"setButtonText": "Set",
+	"cancelButtonText": "Cancel"
+})
diff --git a/dojox/editor/plugins/nls/ar/TableDialog.js b/dojox/editor/plugins/nls/ar/TableDialog.js
index d350f48..e44dbd1 100644
--- a/dojox/editor/plugins/nls/ar/TableDialog.js
+++ b/dojox/editor/plugins/nls/ar/TableDialog.js
@@ -1 +1,29 @@
-({"buttonSet":"تحديد","insertTableTitle":"‏ادراج جدول‏","insertTableRowAfterLabel":"اضافة صف بعد","center":"توسيط","deleteTableColumnLabel":"حذف عمود","right":"لليمين","insertTableColumnBeforeLabel":"اضافة عمود قبل","tableWidth":"عرض الجدول:","buttonInsert":"‏ادراج‏","default":"المفترض","align":"محاذاة:","insertTableRowBeforeLabel":"اضافة صف قبل","cellSpacing":"تباعد الخانة:","pixels":"عنصر صورة","selectTableLabel":"تحديد جدول","rows":"الصفوف:","modifyTableTitle":"تعديل جدول","cellPaddin [...]
\ No newline at end of file
+({
+	insertTableTitle: "‏ادراج جدول‏",
+	modifyTableTitle: "تعديل جدول",
+	rows: "الصفوف:",
+	columns: "الأعمدة:",
+	align: "محاذاة:",
+	cellPadding: "ملء الخانة:",
+	cellSpacing: "تباعد الخانة:",
+	tableWidth: "عرض الجدول:",
+	backgroundColor: "لون الخلفية:",
+	borderColor: "لون الحدود:",
+	borderThickness: "سمك الحدود",
+	percent: "نسبة مئوية",
+	pixels: "عنصر صورة",
+	"default": "المفترض",
+	left: "لليسار",
+	center: "توسيط",
+	right: "لليمين",
+	buttonSet: "تحديد", // translated elsewhere?
+	buttonInsert: "‏ادراج‏",
+
+	selectTableLabel: "تحديد جدول",
+	insertTableRowBeforeLabel: "اضافة صف قبل",
+	insertTableRowAfterLabel: "اضافة صف بعد",
+	insertTableColumnBeforeLabel: "اضافة عمود قبل",
+	insertTableColumnAfterLabel: "اضافة عمود بعد",
+	deleteTableRowLabel: "حذف صف",
+	deleteTableColumnLabel: "حذف عمود"
+})
diff --git a/dojox/editor/plugins/nls/ca/TableDialog.js b/dojox/editor/plugins/nls/ca/TableDialog.js
index 5d38c64..0e748ab 100644
--- a/dojox/editor/plugins/nls/ca/TableDialog.js
+++ b/dojox/editor/plugins/nls/ca/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Defineix","insertTableTitle":"Insereix taula","insertTableRowAfterLabel":"Afegeix fila després","center":"centrat","deleteTableColumnLabel":"Suprimeix columna","right":"dreta","insertTableColumnBeforeLabel":"Afegeix columna abans","tableWidth":"Amplada de taula:","buttonInsert":"Insereix","default":"default","align":"Alinea:","insertTableRowBeforeLabel":"Afegeix fila abans","cellSpacing":"Espaiat de cel·la:","pixels":"píxels","selectTableLabel":"Selecciona taula","rows":"F [...]
\ No newline at end of file
+({
+	insertTableTitle: "Insereix taula",
+	modifyTableTitle: "Modifica taula",
+	rows: "Files:",
+	columns: "Columnes:",
+	align: "Alinea:",
+	cellPadding: "Emplenat de cel·la:",
+	cellSpacing: "Espaiat de cel·la:",
+	tableWidth: "Amplada de taula:",
+	backgroundColor: "Color de fons:",
+	borderColor: "Color del contorn",
+	borderThickness: "Gruix del contorn",
+	percent: "percentatge",
+	pixels: "píxels",
+	"default": "default",
+	left: "esquerra",
+	center: "centrat",
+	right: "dreta",
+	buttonSet: "Defineix", // translated elsewhere?
+	buttonInsert: "Insereix",
+
+	selectTableLabel: "Selecciona taula",
+	insertTableRowBeforeLabel: "Afegeix fila abans",
+	insertTableRowAfterLabel: "Afegeix fila després",
+	insertTableColumnBeforeLabel: "Afegeix columna abans",
+	insertTableColumnAfterLabel: "Afegeix columna després",
+	deleteTableRowLabel: "Suprimeix fila",
+	deleteTableColumnLabel: "Suprimeix columna"
+})
+
diff --git a/dojox/editor/plugins/nls/cs/Breadcrumb.js b/dojox/editor/plugins/nls/cs/Breadcrumb.js
index b863ff3..b1ca156 100644
--- a/dojox/editor/plugins/nls/cs/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/cs/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"Vybrat obsah","deleteElement":"Odstranit prvek","moveEnd":"Přesunout ukazatel na konec","deleteContents":"Odstranit obsah","nodeActions":"Akce uzlu ${nodeName}","selectElement":"Vybrat prvek","moveStart":"Přesunout ukazatel na začátek"})
\ No newline at end of file
+({
+	"nodeActions": "Akce uzlu ${nodeName}",
+	"selectContents": "Vybrat obsah",
+	"selectElement": "Vybrat prvek",
+	"deleteElement": "Odstranit prvek",
+	"deleteContents": "Odstranit obsah",
+	"moveStart": "Přesunout ukazatel na začátek",
+	"moveEnd": "Přesunout ukazatel na konec"
+})
+
diff --git a/dojox/editor/plugins/nls/cs/FindReplace.js b/dojox/editor/plugins/nls/cs/FindReplace.js
index 0760ad2..1ce3dfd 100644
--- a/dojox/editor/plugins/nls/cs/FindReplace.js
+++ b/dojox/editor/plugins/nls/cs/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"V opačném směru","findReplace":"Přepnout hledání/nahrazování","replaceAll":"Všechny výskyty","replaceDialogText":"Počet nahrazených výskytů: ${0}. ","replaceButton":"Nahradit","findButton":"Najít","findLabel":"Hledaný řetězec:","matchCase":"S rozlišením velkých a malých písmen","replaceLabel":"Nahrazující řetězec:"})
\ No newline at end of file
+({
+	"findLabel": "Hledaný řetězec:",
+	"replaceLabel": "Nahrazující řetězec:",
+	"findReplace": "Přepnout hledání/nahrazování",
+	"matchCase": "S rozlišením velkých a malých písmen", 
+	"backwards": "V opačném směru",
+	"replaceAll": "Všechny výskyty", 
+	"findButton": "Najít",
+	"replaceButton": "Nahradit",
+	"replaceDialogText": "Počet nahrazených výskytů: ${0}. "
+})
+
diff --git a/dojox/editor/plugins/nls/cs/InsertEntity.js b/dojox/editor/plugins/nls/cs/InsertEntity.js
index a6b1acc..b66cbdf 100644
--- a/dojox/editor/plugins/nls/cs/InsertEntity.js
+++ b/dojox/editor/plugins/nls/cs/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"Vložit symbol"})
\ No newline at end of file
+({
+	insertEntity: "Vložit symbol"
+})
+
diff --git a/dojox/editor/plugins/nls/cs/PageBreak.js b/dojox/editor/plugins/nls/cs/PageBreak.js
index a762c2a..f8088d0 100644
--- a/dojox/editor/plugins/nls/cs/PageBreak.js
+++ b/dojox/editor/plugins/nls/cs/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"Zalomení stránky"})
\ No newline at end of file
+({
+	"pageBreak": "Zalomení stránky"
+})
+
diff --git a/dojox/editor/plugins/nls/cs/Preview.js b/dojox/editor/plugins/nls/cs/Preview.js
index 851fd45..f052206 100644
--- a/dojox/editor/plugins/nls/cs/Preview.js
+++ b/dojox/editor/plugins/nls/cs/Preview.js
@@ -1 +1,4 @@
-({"preview":"Náhled"})
\ No newline at end of file
+({
+	"preview": "Náhled"
+})
+
diff --git a/dojox/editor/plugins/nls/cs/Save.js b/dojox/editor/plugins/nls/cs/Save.js
index 5fb74e1..4e4e8a3 100644
--- a/dojox/editor/plugins/nls/cs/Save.js
+++ b/dojox/editor/plugins/nls/cs/Save.js
@@ -1 +1,4 @@
-({"save":"Uložit"})
\ No newline at end of file
+({
+	"save": "Uložit"
+})
+
diff --git a/dojox/editor/plugins/nls/cs/ShowBlockNodes.js b/dojox/editor/plugins/nls/cs/ShowBlockNodes.js
index 3310a6f..4812158 100644
--- a/dojox/editor/plugins/nls/cs/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/cs/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"Zobrazit prvky bloku kódu HTML"})
\ No newline at end of file
+({
+	"showBlockNodes": "Zobrazit prvky bloku kódu HTML"
+})
+
diff --git a/dojox/editor/plugins/nls/cs/Smiley.js b/dojox/editor/plugins/nls/cs/Smiley.js
index 946f6f4..5787737 100644
--- a/dojox/editor/plugins/nls/cs/Smiley.js
+++ b/dojox/editor/plugins/nls/cs/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"smích","emoticonCool":"skvělé","emoticonTongue":"jazyk","emoticonCrying":"pláč","emoticonOops":"ouha","emoticonFrown":"zamračení","emoticonAngry":"hněv","emoticonShy":"stud","emoticonNo":"ne","emoticonAngel":"anděl","smiley":"Vložit emotikonu","emoticonIdea":"nápad","emoticonEyebrow":"obočí","emoticonSmile":"úsměv","emoticonWink":"mrknutí","emoticonYes":"ano","emoticonGrin":"úšklebek","emoticonGoofy":"potrhlost","emoticonHalf":"polovina"})
\ No newline at end of file
+({
+	smiley: "Vložit emotikonu",
+	emoticonSmile: "úsměv",
+	emoticonLaughing: "smích",
+	emoticonWink: "mrknutí",
+	emoticonGrin: "úšklebek",
+	emoticonCool: "skvělé",
+	emoticonAngry: "hněv",  
+	emoticonHalf: "polovina", 
+	emoticonEyebrow: "obočí",
+	emoticonFrown: "zamračení",
+	emoticonShy: "stud",
+	emoticonGoofy: "potrhlost",
+	emoticonOops: "ouha",
+	emoticonTongue: "jazyk",
+	emoticonIdea: "nápad",
+	emoticonYes: "ano",
+	emoticonNo: "ne",	
+	emoticonAngel: "anděl",
+	emoticonCrying: "pláč"
+})
+
diff --git a/dojox/editor/plugins/nls/cs/TableDialog.js b/dojox/editor/plugins/nls/cs/TableDialog.js
index 3582263..7f0e406 100644
--- a/dojox/editor/plugins/nls/cs/TableDialog.js
+++ b/dojox/editor/plugins/nls/cs/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Nastavit","insertTableTitle":"Vložit tabulku","insertTableRowAfterLabel":"Přidat řádek za","center":"střed","deleteTableColumnLabel":"Odstranit sloupec","right":"vpravo","insertTableColumnBeforeLabel":"Přidat sloupec před","tableWidth":"Šířka tabulky:","buttonInsert":"Vložit","default":"výchozí","align":"Zarovnat:","insertTableRowBeforeLabel":"Přidat řádek před","cellSpacing":"Odstup buněk:","pixels":"pixelů","selectTableLabel":"Vybrat tabulku","rows":"Řádky:","modifyTable [...]
\ No newline at end of file
+({
+	insertTableTitle: "Vložit tabulku",
+	modifyTableTitle: "Upravit tabulku",
+	rows: "Řádky:",
+	columns: "Sloupce:",
+	align: "Zarovnat:",
+	cellPadding: "Okraj buňky:",
+	cellSpacing: "Odstup buněk:",
+	tableWidth: "Šířka tabulky:",
+	backgroundColor: "Barva pozadí:",
+	borderColor: "Barva ohraničení:",
+	borderThickness: "TloušťkaOhraničení",
+	percent: "procent",
+	pixels: "pixelů",
+	"default": "výchozí",
+	left: "vlevo",
+	center: "střed",
+	right: "vpravo",
+	buttonSet: "Nastavit", // translated elsewhere?
+	buttonInsert: "Vložit",
+
+	selectTableLabel: "Vybrat tabulku",
+	insertTableRowBeforeLabel: "Přidat řádek před",
+	insertTableRowAfterLabel: "Přidat řádek za",
+	insertTableColumnBeforeLabel: "Přidat sloupec před",
+	insertTableColumnAfterLabel: "Přidat sloupec za",
+	deleteTableRowLabel: "Odstranit řádek",
+	deleteTableColumnLabel: "Odstranit sloupec"
+})
+
diff --git a/dojox/editor/plugins/nls/cs/latinEntities.js b/dojox/editor/plugins/nls/cs/latinEntities.js
index 0b7e63e..bc45582 100644
--- a/dojox/editor/plugins/nls/cs/latinEntities.js
+++ b/dojox/editor/plugins/nls/cs/latinEntities.js
@@ -1 +1,257 @@
-({"le":"menší než nebo rovno","prod":"n-ární součin\nznak součin","zwj":"spojení, nulová šířka","mdash":"dlouhá pomlčka","frasl":"lomítko u zlomků","upsih":"symbol řeckého písmena ypsilon se zahnutým háčkem","prop":"úměrné","middot":"tečka uprostřed","hellip":"vodorovná výpustka\ntři tečky","eta":"malé řecké písmeno éta","iacute":"malé písmeno i s čárkou","yen":"znak yen\nznak yuan","rlm":"značka směru zprava doleva","macr":"nadtržítko","ldquo":"levé uvozovky","Icirc":"velké písmeno I se [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"obrácený vykřičník",
+	cent:"znak cent",
+	pound:"znak libra",
+	curren:"znak měna",
+	yen:"znak yen\nznak yuan",
+	brvbar:"přerušená čára\npřerušená svislá čára",
+	sect:"znak paragraf",
+	uml:"vodorovná dvojtečka\npřehláska",
+	copy:"znak copyright",
+	ordf:"indikátor ženského rodu",
+	laquo:"dvojitá levá šipka",
+	not:"znak negace",
+	shy:"spojovník\nrozdělovník",
+	reg:"znak registrováno\nznak registrovaná ochranná známka",
+	macr:"nadtržítko",
+	deg:"znak stupeň",
+	plusmn:"znak plus-minus\nznak plus nebo minus",
+	sup2:"2, horní index\ndruhá mocnina\nplošná míra",
+	sup3:"3, horní index\ntřetí mocnina\nkrychlová míra",
+	acute:"čárka nahoře",
+	micro:"znak mikro",
+	para:"znak konec odstavce",
+	middot:"tečka uprostřed",
+	cedil:"cedilla\nspodní háček",
+	sup1:"1, horní index",
+	ordm:"indikátor mužského rodu",
+	raquo:"dvojitá pravá šipka",
+	frac14:"jednoduchý zlomek jedna čtvrtina\nzlomek jedna čtvrtina",
+	frac12:"jednoduchý zlomek jedna polovina\nzlomek jedna polovina",
+	frac34:"jednoduchý zlomek tři čtvrtiny\nzlomek tři čtvrtiny",
+	iquest:"obrácený otazník\notočený otazník",
+	Agrave:"velké písmeno A s obrácenou čárkou",
+	Aacute:"velké písmeno A s čárkou",
+	Acirc:"velké písmeno A se stříškou",
+	Atilde:"velké písmeno A s vlnovkou",
+	Auml:"velké písmeno A s přehláskou",
+	Aring:"velké písmeno A s kroužkem nahoře",
+	AElig:"velké písmeno AE\nslitek AE, velký",
+	Ccedil:"velké písmeno C se spodním háčkem",
+	Egrave:"velké písmeno E s obrácenou čárkou",
+	Eacute:"velké písmeno E s čárkou",
+	Ecirc:"velké písmeno E se stříškou",
+	Euml:"velké písmeno E s přehláskou",
+	Igrave:"velké písmeno I s obrácenou čárkou",
+	Iacute:"velké písmeno I s čárkou",
+	Icirc:"velké písmeno I se stříškou",
+	Iuml:"velké písmeno I s přehláskou",
+	ETH:"velké písmeno ETH",
+	Ntilde:"velké písmeno N s vlnovkou",
+	Ograve:"velké písmeno O s obrácenou čárkou",
+	Oacute:"velké písmeno O s čárkou",
+	Ocirc:"velké písmeno O se stříškou",
+	Otilde:"velké písmeno O s vlnovkou",
+	Ouml:"velké písmeno O s přehláskou",
+	times:"znak násobení",
+	Oslash:"velké písmeno O s přeškrtnutím",
+	Ugrave:"velké písmeno U s obrácenou čárkou",
+	Uacute:"velké písmeno U s čárkou",
+	Ucirc:"velké písmeno U se stříškou",
+	Uuml:"velké písmeno U s přehláskou",
+	Yacute:"velké písmeno Y s čárkou",
+	THORN:"velké písmeno THORN",
+	szlig:"malé písmeno ostré s",
+	agrave:"malé písmeno a s obrácenou čárkou",
+	aacute:"malé písmeno a s čárkou",
+	acirc:"malé písmeno a se stříškou",
+	atilde:"malé písmeno a s vlnovkou",
+	auml:"malé písmeno a s přehláskou",
+	aring:"malé písmeno a s kroužkem nahoře",
+	aelig:"malé písmeno ae\nslitek ae, malý",
+	ccedil:"malé písmeno c se spodním háčkem",
+	egrave:"malé písmeno e s obrácenou čárkou",
+	eacute:"malé písmeno e s čárkou",
+	ecirc:"malé písmeno e se stříškou",
+	euml:"malé písmeno e s přehláskou",
+	igrave:"malé písmeno i s obrácenou čárkou",
+	iacute:"malé písmeno i s čárkou",
+	icirc:"malé písmeno i se stříškou",
+	iuml:"malé písmeno i s přehláskou",
+	eth:"malé písmeno eth",
+	ntilde:"malé písmeno n s vlnovkou",
+	ograve:"malé písmeno o s obrácenou čárkou",
+	oacute:"malé písmeno o s čárkou",
+	ocirc:"malé písmeno o se stříškou",
+	otilde:"malé písmeno o s vlnovkou",
+	ouml:"malé písmeno o s přehláskou",
+	divide:"znak dělení",
+	oslash:"malé písmeno o s přeškrtnutím",
+	ugrave:"malé písmeno u s obrácenou čárkou",
+	uacute:"malé písmeno u s čárkou",
+	ucirc:"malé písmeno u se stříškou",
+	uuml:"malé písmeno u s přehláskou",
+	yacute:"malé písmeno y s čárkou",
+	thorn:"malé písmeno thorn",
+	yuml:"malé písmeno y s přehláskou",
+
+// Greek Characters and Symbols
+	fnof:"malé písmeno f se zahnutým háčkem\nfunkce\nflorin",
+	Alpha:"velké řecké písmeno alfa",
+	Beta:"velké řecké písmeno beta",
+	Gamma:"velké řecké písmeno gama",
+	Delta:"velké řecké písmeno delta",
+	Epsilon:"velké řecké písmeno epsilon",
+	Zeta:"velké řecké písmeno zéta",
+	Eta:"velké řecké písmeno éta",
+	Theta:"velké řecké písmeno théta",
+	Iota:"velké řecké písmeno jóta",
+	Kappa:"velké řecké písmeno kappa",
+	Lambda:"velké řecké písmeno lambda",
+	Mu:"velké řecké písmeno mí",
+	Nu:"velké řecké písmeno ný",
+	Xi:"velké řecké písmeno ksí",
+	Omicron:"velké řecké písmeno omikrón",
+	Pi:"velké řecké písmeno pí",
+	Rho:"velké řecké písmeno ró",
+	Sigma:"velké řecké písmeno sigma",
+	Tau:"velké řecké písmeno tau",
+	Upsilon:"velké řecké písmeno ypsilon",
+	Phi:"velké řecké písmeno fí",
+	Chi:"velké řecké písmeno chí",
+	Psi:"velké řecké písmeno psí",
+	Omega:"velké řecké písmeno ómega",
+	alpha:"malé řecké písmeno alfa",
+	beta:"malé řecké písmeno beta",
+	gamma:"malé řecké písmeno gama",
+	delta:"malé řecké písmeno delta",
+	epsilon:"malé řecké písmeno epsilon",
+	zeta:"malé řecké písmeno zéta",
+	eta:"malé řecké písmeno éta",
+	theta:"malé řecké písmeno théta",
+	iota:"malé řecké písmeno jóta",
+	kappa:"malé řecké písmeno kappa",
+	lambda:"malé řecké písmeno lambda",
+	mu:"malé řecké písmeno mí",
+	nu:"malé řecké písmeno ný",
+	xi:"malé řecké písmeno ksí",
+	omicron:"malé řecké písmeno omikrón",
+	pi:"malé řecké písmeno pí",
+	rho:"malé řecké písmeno ró",
+	sigmaf:"malé řecké písmeno koncové sigma",
+	sigma:"malé řecké písmeno sigma",
+	tau:"malé řecké písmeno tau",
+	upsilon:"malé řecké písmeno ypsilon",
+	phi:"malé řecké písmeno fí",
+	chi:"malé řecké písmeno chí",
+	psi:"malé řecké písmeno psí",
+	omega:"malé řecké písmeno ómega",
+	thetasym:"symbol malého řeckého písmena théta",
+	upsih:"symbol řeckého písmena ypsilon se zahnutým háčkem",
+	piv:"řecký symbol pí",
+	bull:"odrážka\nmalý černý kroužek",
+	hellip:"vodorovná výpustka\ntři tečky",
+	prime:"čárka nahoře\nminuty\nstopy",
+	Prime:"dvojitá čárka nahoře\nsekundy\npalce",
+	oline:"nadtržítko\npruh",
+	frasl:"lomítko u zlomků",
+	weierp:"stylizované velké písmeno P\npotenční množina\nWeierstrassovo písmeno p",
+	image:"velké písmeno I, švabach\nimaginární část",
+	real:"velké písmeno R, švabach\nsymbol reálné části",
+	trade:"znak ochranná známka",
+	alefsym:"symbol alef\nprvní transfinitní kardinál",
+	larr:"šipka doleva",
+	uarr:"šipka nahoru",
+	rarr:"šipka doprava",
+	darr:"šipka dolů",
+	harr:"šipka doleva a doprava",
+	crarr:"šipka dolů zahnutá doleva\nnávrat vozíku, konec řádku",
+	lArr:"dvojitá šipka doleva",
+	uArr:"dvojitá šipka nahoru",
+	rArr:"dvojitá šipka doprava",
+	dArr:"dvojitá šipka dolů",
+	hArr:"dvojitá šipka doleva a doprava",
+	forall:"pro všechny",
+	part:"parciální diferenciál",
+	exist:"existuje",
+	empty:"prázdná množina\nnulová množina\nprůměr",
+	nabla:"nabla\nzpětná diference",
+	isin:"prvek množiny",
+	notin:"není prvkem množiny",
+	ni:"obsahuje jako člena",
+	prod:"n-ární součin\nznak součin",
+	sum:"n-ární součet",
+	minus:"znak minus",
+	lowast:"operátor hvězdička",
+	radic:"druhá odmocnina",
+	prop:"úměrné",
+	infin:"nekonečno",
+	ang:"úhel",
+	and:"logický operátor a\nklín s hrotem nahoru",
+	or:"logický operátor nebo\nklín s hrotem dolů",
+	cap:"průnik\noblouk vypouklý nahoru",
+	cup:"sjednocení\noblouk vypouklý dolů","int":"integrál",
+	there4:"a proto",
+	sim:"operátor tilda\nzměna podle\npodobné",
+	cong:"přibližně rovno",
+	asymp:"téměř rovno\nasymptotické k",
+	ne:"není rovno",
+	equiv:"shodné s",
+	le:"menší než nebo rovno",
+	ge:"větší než nebo rovno",
+	sub:"podmnožina",
+	sup:"nadmnožina",
+	nsub:"není podmnožinou",
+	sube:"podmnožina nebo shodné s",
+	supe:"nadmnožina nebo shodné s",
+	oplus:"znak plus v kroužku\npřímý součet",
+	otimes:"znak násobení v kroužku\nvektorový součin",
+	perp:"kolmice\nortogonální k\nkolmé na",
+	sdot:"operátor tečka",
+	lceil:"levá horní celá část",
+	rceil:"pravá horní celá část",
+	lfloor:"levá dolní celá část",
+	rfloor:"pravá dolní celá část",
+	lang:"levá lomená závorka",
+	rang:"pravá lomená závorka",
+	loz:"kosočtverec",
+	spades:"piky",
+	clubs:"kříže\ntrojlístek",
+	hearts:"srdce\nvalentýn",
+	diams:"káry",
+	OElig:"slitek OE, velký",
+	oelig:"slitek oe, malý",
+	Scaron:"velké písmeno S s háčkem",
+	scaron:"malé písmeno s s háčkem",
+	Yuml:"velké písmeno Y s přehláskou",
+	circ:"stříška, modifikátor písmen",
+	tilde:"malá vlnovka",
+	ensp:"úzká mezera",
+	emsp:"široká mezera",
+	thinsp:"zúžená mezera",
+	zwnj:"zákaz spojení, nulová šířka",
+	zwj:"spojení, nulová šířka",
+	lrm:"značka směru zleva doprava",
+	rlm:"značka směru zprava doleva",
+	ndash:"krátká pomlčka",
+	mdash:"dlouhá pomlčka",
+	lsquo:"levý apostrof",
+	rsquo:"pravý apostrof",
+	sbquo:"dolní apostrof",
+	ldquo:"levé uvozovky",
+	rdquo:"pravé uvozovky",
+	bdquo:"dolní uvozovky",
+	dagger:"křížek",
+	Dagger:"dvojitý křížek",
+	permil:"znak promile",
+	lsaquo:"levá šipka",
+	rsaquo:"pravá šipka",
+	euro:"znak euro"
+})
+
diff --git a/dojox/editor/plugins/nls/da/TableDialog.js b/dojox/editor/plugins/nls/da/TableDialog.js
index 1e4b8db..3b0ba7f 100644
--- a/dojox/editor/plugins/nls/da/TableDialog.js
+++ b/dojox/editor/plugins/nls/da/TableDialog.js
@@ -1 +1,29 @@
-({"buttonSet":"Definér","insertTableTitle":"Indsæt tabel","insertTableRowAfterLabel":"Tilføj række efter","center":"centreret","deleteTableColumnLabel":"Slet kolonne","right":"højre","insertTableColumnBeforeLabel":"Tilføj kolonne før","tableWidth":"Tabelbredde:","buttonInsert":"Indsæt","default":"standard","align":"Justér:","insertTableRowBeforeLabel":"Tilføj række før","cellSpacing":"Celleafstand:","pixels":"pixel","selectTableLabel":"Markér tabel","rows":"Rækker:","modifyTableTitle":"R [...]
\ No newline at end of file
+({
+	insertTableTitle: "Indsæt tabel",
+	modifyTableTitle: "Revidér tabel",
+	rows: "Rækker:",
+	columns: "Kolonner:",
+	align: "Justér:",
+	cellPadding: "Cellemargen:",
+	cellSpacing: "Celleafstand:",
+	tableWidth: "Tabelbredde:",
+	backgroundColor: "Baggrundsfarve:",
+	borderColor: "Kantfarve:",
+	borderThickness: "Kanttykkelse",
+	percent: "percent",
+	pixels: "pixel",
+	"default": "standard",
+	left: "venstre",
+	center: "centreret",
+	right: "højre",
+	buttonSet: "Definér", // translated elsewhere?
+	buttonInsert: "Indsæt",
+
+	selectTableLabel: "Markér tabel",
+	insertTableRowBeforeLabel: "Tilføj række før",
+	insertTableRowAfterLabel: "Tilføj række efter",
+	insertTableColumnBeforeLabel: "Tilføj kolonne før",
+	insertTableColumnAfterLabel: "Tilføj kolonne efter",
+	deleteTableRowLabel: "Slet række",
+	deleteTableColumnLabel: "Slet kolonne"
+})
diff --git a/dojox/editor/plugins/nls/de/Breadcrumb.js b/dojox/editor/plugins/nls/de/Breadcrumb.js
index 2c35bc0..a425ceb 100644
--- a/dojox/editor/plugins/nls/de/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/de/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"Inhalt auswählen","deleteElement":"Element löschen","moveEnd":"Cursor an Ende verschieben","deleteContents":"Inhalt löschen","nodeActions":"Aktionen für ${nodeName}","selectElement":"Element auswählen","moveStart":"Cursor an Anfang verschieben"})
\ No newline at end of file
+({
+	"nodeActions": "Aktionen für ${nodeName}",
+	"selectContents": "Inhalt auswählen",
+	"selectElement": "Element auswählen",
+	"deleteElement": "Element löschen",
+	"deleteContents": "Inhalt löschen",
+	"moveStart": "Cursor an Anfang verschieben",
+	"moveEnd": "Cursor an Ende verschieben"
+})
+
diff --git a/dojox/editor/plugins/nls/de/FindReplace.js b/dojox/editor/plugins/nls/de/FindReplace.js
index 25b4d43..a7e2d25 100644
--- a/dojox/editor/plugins/nls/de/FindReplace.js
+++ b/dojox/editor/plugins/nls/de/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"Zurück","findReplace":"Suchen/Ersetzen","replaceAll":"Alle Vorkommen","replaceDialogText":"Es wurden ${0} Vorkommen ersetzt.","replaceButton":"Ersetzen","findButton":"Suchen","findLabel":"Suchbegriff:","matchCase":"Groß- und Kleinschreibung abgleichen","replaceLabel":"Ersetzen durch:"})
\ No newline at end of file
+({
+	"findLabel": "Suchbegriff:",
+	"replaceLabel": "Ersetzen durch:",
+	"findReplace": "Suchen/Ersetzen",
+	"matchCase": "Groß- und Kleinschreibung abgleichen", 
+	"backwards": "Zurück",
+	"replaceAll": "Alle Vorkommen", 
+	"findButton": "Suchen",
+	"replaceButton": "Ersetzen",
+	"replaceDialogText": "Es wurden ${0} Vorkommen ersetzt."
+})
+
diff --git a/dojox/editor/plugins/nls/de/InsertEntity.js b/dojox/editor/plugins/nls/de/InsertEntity.js
index 4830561..e5bc34c 100644
--- a/dojox/editor/plugins/nls/de/InsertEntity.js
+++ b/dojox/editor/plugins/nls/de/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"Symbol einfügen"})
\ No newline at end of file
+({
+	insertEntity: "Symbol einfügen"
+})
+
diff --git a/dojox/editor/plugins/nls/de/PageBreak.js b/dojox/editor/plugins/nls/de/PageBreak.js
index 14a0ea2..4285093 100644
--- a/dojox/editor/plugins/nls/de/PageBreak.js
+++ b/dojox/editor/plugins/nls/de/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"Seitenumbruch"})
\ No newline at end of file
+({
+	"pageBreak": "Seitenumbruch"
+})
+
diff --git a/dojox/editor/plugins/nls/de/Preview.js b/dojox/editor/plugins/nls/de/Preview.js
index 396d562..701d9af 100644
--- a/dojox/editor/plugins/nls/de/Preview.js
+++ b/dojox/editor/plugins/nls/de/Preview.js
@@ -1 +1,4 @@
-({"preview":"Vorschau"})
\ No newline at end of file
+({
+	"preview": "Vorschau"
+})
+
diff --git a/dojox/editor/plugins/nls/de/Save.js b/dojox/editor/plugins/nls/de/Save.js
index 50af5b1..0655245 100644
--- a/dojox/editor/plugins/nls/de/Save.js
+++ b/dojox/editor/plugins/nls/de/Save.js
@@ -1 +1,4 @@
-({"save":"Speichern"})
\ No newline at end of file
+({
+	"save": "Speichern"
+})
+
diff --git a/dojox/editor/plugins/nls/de/ShowBlockNodes.js b/dojox/editor/plugins/nls/de/ShowBlockNodes.js
index 6a17d87..9929943 100644
--- a/dojox/editor/plugins/nls/de/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/de/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"HTML-Blockelemente anzeigen"})
\ No newline at end of file
+({
+	"showBlockNodes": "HTML-Blockelemente anzeigen"
+})
+
diff --git a/dojox/editor/plugins/nls/de/Smiley.js b/dojox/editor/plugins/nls/de/Smiley.js
index 07306d1..116f402 100644
--- a/dojox/editor/plugins/nls/de/Smiley.js
+++ b/dojox/editor/plugins/nls/de/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"Lachen","emoticonCool":"Cool","emoticonTongue":"Zunge","emoticonCrying":"Weinen","emoticonOops":"Hoppla","emoticonFrown":"Stirnrunzeln","emoticonAngry":"Zornig","emoticonShy":"Schüchtern","emoticonNo":"Nein","emoticonAngel":"Engel","smiley":"Emoticon einfügen","emoticonIdea":"Idee","emoticonEyebrow":"Hochgezogene Augenbraue","emoticonSmile":"Lächeln","emoticonWink":"Augenzwinkern","emoticonYes":"Ja","emoticonGrin":"Grinsen","emoticonGoofy":"Albern","emoticonHalf":"Halb"})
\ No newline at end of file
+({
+	smiley: "Emoticon einfügen",
+	emoticonSmile: "Lächeln",
+	emoticonLaughing: "Lachen",
+	emoticonWink: "Augenzwinkern",
+	emoticonGrin: "Grinsen",
+	emoticonCool: "Cool",
+	emoticonAngry: "Zornig",  
+	emoticonHalf: "Halb", 
+	emoticonEyebrow: "Hochgezogene Augenbraue",
+	emoticonFrown: "Stirnrunzeln",
+	emoticonShy: "Schüchtern",
+	emoticonGoofy: "Albern",
+	emoticonOops: "Hoppla",
+	emoticonTongue: "Zunge",
+	emoticonIdea: "Idee",
+	emoticonYes: "Ja",
+	emoticonNo: "Nein",	
+	emoticonAngel: "Engel",
+	emoticonCrying: "Weinen"
+})
+
diff --git a/dojox/editor/plugins/nls/de/TableDialog.js b/dojox/editor/plugins/nls/de/TableDialog.js
index 8e84d89..a3cb555 100644
--- a/dojox/editor/plugins/nls/de/TableDialog.js
+++ b/dojox/editor/plugins/nls/de/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Festlegen","insertTableTitle":"Tabelle einfügen","insertTableRowAfterLabel":"Zeile unterhalb einfügen","center":"Mitte","deleteTableColumnLabel":"Spalte löschen","right":"Rechts","insertTableColumnBeforeLabel":"Spalte oberhalb einfügen","tableWidth":"Tabellenbreite:","buttonInsert":"Einfügen","default":"Standard","align":"Ausrichten:","insertTableRowBeforeLabel":"Zeile oberhalb einfügen","cellSpacing":"Zellenabstand:","pixels":"Pixel","selectTableLabel":"Tabelle auswählen" [...]
\ No newline at end of file
+({
+	insertTableTitle: "Tabelle einfügen",
+	modifyTableTitle: "Tabelle ändern",
+	rows: "Zeilen:",
+	columns: "Spalten:",
+	align: "Ausrichten:",
+	cellPadding: "Zellenrandbreite:",
+	cellSpacing: "Zellenabstand:",
+	tableWidth: "Tabellenbreite:",
+	backgroundColor: "Hintergrundfarbe:",
+	borderColor: "Randfarbe:",
+	borderThickness: "Randbreite",
+	percent: "Prozent",
+	pixels: "Pixel",
+	"default": "Standard",
+	left: "Links",
+	center: "Mitte",
+	right: "Rechts",
+	buttonSet: "Festlegen", // translated elsewhere?
+	buttonInsert: "Einfügen",
+
+	selectTableLabel: "Tabelle auswählen",
+	insertTableRowBeforeLabel: "Zeile oberhalb einfügen",
+	insertTableRowAfterLabel: "Zeile unterhalb einfügen",
+	insertTableColumnBeforeLabel: "Spalte oberhalb einfügen",
+	insertTableColumnAfterLabel: "Spalte unterhalb einfügen",
+	deleteTableRowLabel: "Zeile löschen",
+	deleteTableColumnLabel: "Spalte löschen"
+})
+
diff --git a/dojox/editor/plugins/nls/de/latinEntities.js b/dojox/editor/plugins/nls/de/latinEntities.js
index e8b26e9..b291cdf 100644
--- a/dojox/editor/plugins/nls/de/latinEntities.js
+++ b/dojox/editor/plugins/nls/de/latinEntities.js
@@ -1 +1,257 @@
-({"le":"Kleiner-gleich","prod":"unäres Produkt\nProduktzeichen","zwj":"Verbinder mit Nullbreite","mdash":"Gedankenstrich von der Länge des Buchstabens m","frasl":"Schrägstrich für Bruch","upsih":"Griechisches Upsilon mit Haken","prop":"proportional zu","middot":"Multiplikationszeichen\nGeorgisches Komma\nGriechisches Multiplikationszeichen","hellip":"Auslassung\nDrei kleine Punkte","eta":"Griechischer Kleinbuchstabe Eta","iacute":"Kleinbuchstabe i mit Aktut","yen":"Yen-ZeichenNyuan-Zeich [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"Umgekehrtes Ausrufezeichen",
+	cent:"Cent-Zeichen",
+	pound:"Nummernzeichen",
+	curren:"Währungssymbol",
+	yen:"Yen-Zeichen\Nyuan-Zeichen",
+	brvbar:"Unterbrochener Balken\nUnterbrochener vertikaler Balken",
+	sect:"Abschnittszeichen",
+	uml:"Trema\nLeerzeichen mit Trema",
+	copy:"Copyrightzeichen",
+	ordf:"Weibliches Ordinalzeichen",
+	laquo:"Doppelte, winklige Anführungszeichen, die nach links weisen\linke französische Anführungszeichen",
+	not:"Nicht-Zeichen",
+	shy:"Veränderlicher Silbentrennstrich\nbedingter Trennstrich",
+	reg:"Registrierte Handelsmarke\nregistriertes Markenzeichen",
+	macr:"Makron\nLeerzeichen mit Makron\nÜberstrich\nQuerstrich über dem Buchstaben",
+	deg:"Gradzeichen",
+	plusmn:"Plus-Minus-Zeichen\nPlus-oder-Minus-Zeichen",
+	sup2:"Hochgestellte Zwei\nHoch 2\nzum Quadrat",
+	sup3:"Hochgestellte Drei\nHoch 3\nKubik",
+	acute:"Akut\nsLeerzeichen mit Akut",
+	micro:"Micro-Zeichen",
+	para:"Pilcrow-Zeichen (engl.)\nAbsatzzeichen",
+	middot:"Multiplikationszeichen\nGeorgisches Komma\nGriechisches Multiplikationszeichen",
+	cedil:"Cedilla\nLeerzeichen mit Cedilla",
+	sup1:"Hochgestellte Eins\nHoch 1",
+	ordm:"Männliches Ordinalzeichen",
+	raquo:"Doppelte, winklige Anführungszeichen, die nach rechts weisen\nRechtes französisches Anführungszeichen",
+	frac14:"Bruch 1 durch 4\nEin Viertel",
+	frac12:"Bruch 1 durch 2\nEinhalb",
+	frac34:"Bruch 3 durch 4\nDreiviertel",
+	iquest:"Umgekehrtes Fragezeichen\nFragezeichen auf dem Kopf",
+	Agrave:"Großes A mit Gravis\nGroßbuchstabe A mit Gravis",
+	Aacute:"Großbuchstabe A mit Akut",
+	Acirc:"Großbuchstabe A mit Zirkumflex",
+	Atilde:"Großbuchstabe A mit Tilde",
+	Auml:"Großbuchstabe A mit Trema",
+	Aring:"Großes A mit Ring darüber\nLateinischer Großbuchstabe A mit Ring darüber",
+	AElig:"Großes AE\nLigatur aus Großbuchstaben A und E",
+	Ccedil:"Großbuchstabe C mit Cedilla",
+	Egrave:"Großbuchstabe E mit Gravis",
+	Eacute:"Großbuchstabe E mit Akut",
+	Ecirc:"Großbuchstabe E mit Zirkumflex",
+	Euml:"Großbuchstabe E mit Trema",
+	Igrave:"Großbuchstabe I mit Gravis",
+	Iacute:"Großbuchstabe I mit Akut",
+	Icirc:"Großbuchstabe I mit Zirkumflex",
+	Iuml:"Großbuchstabe I mit Trema",
+	ETH:"Großes ETH",
+	Ntilde:"Großbuchstabe N mit Tilde",
+	Ograve:"Großbuchstabe O mit Gravis",
+	Oacute:"Großbuchstabe O mit Akut",
+	Ocirc:"Großbuchstabe O mit Zirkumflex",
+	Otilde:"Lateinischer Großbuchstabe O mit Tilde",
+	Ouml:"Lateinischer Großbuchstabe O mit Trema",
+	times:"Multiplikationszeichen",
+	Oslash:"Großes O mit Schrägstrich\nGroßer dänisch-norwegischer Umlaut ö",
+	Ugrave:"Großbuchstabe U mit Gravis",
+	Uacute:"Großbuchstabe U mit Akut",
+	Ucirc:"Großbuchstabe U mit Zirkumflex",
+	Uuml:"Großbuchstabe U mit Trema",
+	Yacute:"Großbuchstabe Y mit Akut",
+	THORN:"Großes THORN",
+	szlig:"Scharfes s\nEsszett",
+	agrave:"Kleines a mit Gravis\nKleinbuchstabe a mit Gravis",
+	aacute:"Kleinbuchstabe a mit Aktut",
+	acirc:"Kleinbuchstabe a mit Zirkumflex",
+	atilde:"Kleinbuchstabe a mit Tilde",
+	auml:"Kleinbuchstabe a mit Trema",
+	aring:"Kleines a mit Ring darüber\nKleinbuchstabe a mit Ring",
+	aelig:"Kleines ae\nLigatur aus Kleinbuchstaben a und e",
+	ccedil:"Kleinbuchstabe c mit Cedilla",
+	egrave:"Kleinbuchstabe e mit Gravis",
+	eacute:"Kleinbuchstabe e mit Aktut",
+	ecirc:"Kleinbuchstabe e mit Zirkumflex",
+	euml:"Kleinbuchstabe e mit Trema",
+	igrave:"Kleinbuchstabe i mit Gravis",
+	iacute:"Kleinbuchstabe i mit Aktut",
+	icirc:"Kleinbuchstabe i mit Zirkumflex",
+	iuml:"Kleinbuchstabe i mit Trema",
+	eth:"Kleines eth",
+	ntilde:"Kleinbuchstabe n mit Tilde",
+	ograve:"Kleinbuchstabe o mit Gravis",
+	oacute:"Kleinbuchstabe o mit Aktut",
+	ocirc:"Kleinbuchstabe o mit Zirkumflex",
+	otilde:"Kleinbuchstabe o mit Tilde",
+	ouml:"Kleinbuchstabe o mit Gravis",
+	divide:"Divisionszeichen",
+	oslash:"Kleines o mit Schrägstrich\nKleiner dänisch-norwegischer Umlaut ö",
+	ugrave:"Kleinbuchstabe u mit Gravis",
+	uacute:"Kleinbuchstabe u mit Aktut",
+	ucirc:"Kleinbuchstabe u mit Zirkumflex",
+	uuml:"Kleinbuchstabe u mit Trema",
+	yacute:"Kleinbuchstabe y mit Aktut",
+	thorn:"Kleines thorn",
+	yuml:"Kleinbuchstabe y mit Trema",
+
+// Greek Characters and Symbols
+	fnof:"Kleines mit Haken\nFunction\nFlorin",
+	Alpha:"Griechischer Großbuchstabe Alpha",
+	Beta:"Griechischer Großbuchstabe Beta",
+	Gamma:"Griechischer Großbuchstabe Gamma",
+	Delta:"Griechischer Großbuchstabe Delta",
+	Epsilon:"Griechischer Großbuchstabe Epsilon",
+	Zeta:"Griechischer Großbuchstabe Zeta",
+	Eta:"Griechischer Großbuchstabe Eta",
+	Theta:"Griechischer Großbuchstabe Theta",
+	Iota:"Griechischer Großbuchstabe Iota",
+	Kappa:"Griechischer Großbuchstabe Kappa",
+	Lambda:"Griechischer Großbuchstabe Lambda",
+	Mu:"Griechischer Großbuchstabe My",
+	Nu:"Griechischer Großbuchstabe Ny",
+	Xi:"Griechischer Großbuchstabe Xi",
+	Omicron:"Griechischer Großbuchstabe Omicron",
+	Pi:"Griechischer Großbuchstabe Pi",
+	Rho:"Griechischer Großbuchstabe Rho",
+	Sigma:"Griechischer Großbuchstabe Sigma",
+	Tau:"Griechischer Großbuchstabe Tau",
+	Upsilon:"Griechischer Großbuchstabe Upsilon",
+	Phi:"Griechischer Großbuchstabe Phi",
+	Chi:"Griechischer Großbuchstabe Chi",
+	Psi:"Griechischer Großbuchstabe Psi",
+	Omega:"Griechischer Großbuchstabe Omega",
+	alpha:"Griechischer Kleinbuchstabe Alpha",
+	beta:"Griechischer Kleinbuchstabe Beta",
+	gamma:"Griechischer Kleinbuchstabe Gamma",
+	delta:"Griechischer Kleinbuchstabe Delta",
+	epsilon:"Griechischer Kleinbuchstabe Epsilon",
+	zeta:"Griechischer Kleinbuchstabe Zeta",
+	eta:"Griechischer Kleinbuchstabe Eta",
+	theta:"Griechischer Kleinbuchstabe Theta",
+	iota:"Griechischer Kleinbuchstabe Iota",
+	kappa:"Griechischer Kleinbuchstabe Kappa",
+	lambda:"Griechischer Kleinbuchstabe Lambda",
+	mu:"Griechischer Kleinbuchstabe My",
+	nu:"Griechischer Kleinbuchstabe Ny",
+	xi:"Griechischer Kleinbuchstabe Xi",
+	omicron:"Griechischer Kleinbuchstabe Omicron",
+	pi:"Griechischer Kleinbuchstabe Pi",
+	rho:"Griechischer Kleinbuchstabe Rho",
+	sigmaf:"Griechischer Kleinbuchstabe Sigma am Wortende",
+	sigma:"Griechischer Kleinbuchstabe Sigma",
+	tau:"Griechischer Kleinbuchstabe Tau",
+	upsilon:"Griechischer Kleinbuchstabe Upsilon",
+	phi:"Griechischer Kleinbuchstabe Phi",
+	chi:"Griechischer Kleinbuchstabe Chi",
+	psi:"Griechischer Kleinbuchstabe Psi",
+	omega:"Griechischer Kleinbuchstabe Omega",
+	thetasym:"Griechischer Kleinbuchstabe Theta (Symbol)",
+	upsih:"Griechisches Upsilon mit Haken",
+	piv:"Griechisches Pi-Symbol",
+	bull:"Rundes Aufzählungszeichen\nSchwarzer kleiner Kreis",
+	hellip:"Auslassung\nDrei kleine Punkte",
+	prime:"Prime\nMinuten\nFuß",
+	Prime:"Doppelter Prime\nSekunden\nZoll",
+	oline:"Hochgestellter Querstrich\nLeerzeichen mit Oberstrich",
+	frasl:"Schrägstrich für Bruch",
+	weierp:"Kleines p in Schreibschrift\nPotenz\nWeierstrass'sche Ellipsen-Funktion",
+	image:"Großes I in Frakturschrift\nImaginärteil",
+	real:"Großes R in Frakturschrift\nRealteilsymbol",
+	trade:"Markenzeichen",
+	alefsym:"Alef-Symbol\nerste Transfinite Kardinalzahl",
+	larr:"Linkspfeil",
+	uarr:"Aufwärtspfeil",
+	rarr:"Rechtspfeil",
+	darr:"Abwärtspfeil",
+	harr:"Links-Rechts-Pfeil",
+	crarr:"Abwärtspfeil, der nach links abknickt\nZeilenumbruch",
+	lArr:"Doppelter Linkspfeil",
+	uArr:"Doppelter Aufwärtspfeil",
+	rArr:"Doppelter Rechtspfeil",
+	dArr:"Doppelter Abwärtspfeil",
+	hArr:"Doppelter Rechts-Links-Pfeil",
+	forall:"Für alle",
+	part:"Partielle Differenzialgleichung",
+	exist:"Es existiert",
+	empty:"Leermenge\nNullmenge\nDurchmesser",
+	nabla:"Nabla\nAbsteigende Differenz",
+	isin:"Element von",
+	notin:"Kein Element von",
+	ni:"Enthält als Member",
+	prod:"unäres Produkt\nProduktzeichen",
+	sum:"unäre Summation",
+	minus:"Minuszeichen",
+	lowast:"Sternoperator",
+	radic:"Quadratwurzel\nWurzelzeichen",
+	prop:"proportional zu",
+	infin:"Unendlich",
+	ang:"Winkel",
+	and:"Logisches Und\nKeil",
+	or:"Logisches Oder\nv-förmig",
+	cap:"Schnittpunkt\nHütchen",
+	cup:"Vereinigungsmenge\nCup","int":"Integral",
+	there4:"Deshalb",
+	sim:"Tilde (Operator)\nvariiert mit\nähnlich wie",
+	cong:"Etwa gleich mit",
+	asymp:"Ungefähr gleich mit\nasymptotisch",
+	ne:"Nicht gleich mit",
+	equiv:"Identisch mit",
+	le:"Kleiner-gleich",
+	ge:"Größer-gleich",
+	sub:"Teil von",
+	sup:"Obermenge von",
+	nsub:"Kein Teil von",
+	sube:"Teilmenge oder gleich mit",
+	supe:"Obermenge oder gleich mit",
+	oplus:"Pluszeichen mit Kreis\ndirekte Summe",
+	otimes:"Multiplikationszeichen mit Kreis\nVektorprodukt",
+	perp:"Senkrecht\nSenkrecht zu\nLotrecht",
+	sdot:"Punktoperator",
+	lceil:"Linke Ecke oben\nAPL upstile",
+	rceil:"Rechte Ecke oben",
+	lfloor:"Linke Ecke unten\nAPL downstile",
+	rfloor:"Rechte Ecke unten",
+	lang:"Linke spitze Klammer",
+	rang:"Rechte spitze Klammer",
+	loz:"Raute",
+	spades:"Schwarzes Pik (Kartenspiel)",
+	clubs:"Schwarzes Kreuz (Kartenspiel)\nKleeblatt",
+	hearts:"Schwarzes Herz (Kartenspiel)\nValentine",
+	diams:"Schwarzes Karo (Kartenspiel)",
+	OElig:"Ligatur aus Großbuchstaben O und E",
+	oelig:"Ligatur aus Kleinbuchstaben o und e",
+	Scaron:"Großbuchstabe S mit Caron",
+	scaron:"Kleinbuchstabe s mit Caron",
+	Yuml:"Großbuchstabe Y mit Trema",
+	circ:"Zirkumflex, Akzent",
+	tilde:"kleine Tilde",
+	ensp:"Leerschritt von der Breite des Buchstaben n",
+	emsp:"Leerschritt von der Breite des Buchstaben m",
+	thinsp:"Schmaler Leerschritt",
+	zwnj:"Nichtverbinder mit Nullbreite",
+	zwj:"Verbinder mit Nullbreite",
+	lrm:"Links-Rechts-Markierung",
+	rlm:"Rechts-Links-Markierung",
+	ndash:"Gedankenstrich von der Länge des Buchstabens n",
+	mdash:"Gedankenstrich von der Länge des Buchstabens m",
+	lsquo:"Linkes einfaches Anführungszeichen",
+	rsquo:"Rechtes einfaches Anführungszeichen",
+	sbquo:"Einfaches, gekrümmtes Anführungszeichen unten",
+	ldquo:"Linkes doppeltes Anführungszeichen",
+	rdquo:"Rechtes doppeltes Anführungszeichen",
+	bdquo:"Doppeltes, gekrümmtes Anführungszeichen unten",
+	dagger:"Kreuzzeichen",
+	Dagger:"Doppelkreuzzeichen",
+	permil:"Promillezeichen",
+	lsaquo:"Einfaches linkes Anführungszeichen",
+	rsaquo:"Einfaches rechtes Anführungszeichen",
+	euro:"Euro-Zeichen"
+})
+
diff --git a/dojox/editor/plugins/nls/el/TableDialog.js b/dojox/editor/plugins/nls/el/TableDialog.js
index 7e5b038..802ad47 100644
--- a/dojox/editor/plugins/nls/el/TableDialog.js
+++ b/dojox/editor/plugins/nls/el/TableDialog.js
@@ -1 +1,29 @@
-({"buttonSet":"Ορισμός","insertTableTitle":"Εισαγωγή πίνακα","insertTableRowAfterLabel":"Προσθήκη γραμμής μετά","center":"κέντρο","deleteTableColumnLabel":"Διαγραφή στήλης","right":"δεξιά","insertTableColumnBeforeLabel":"Προσθήκη στήλης πριν","tableWidth":"Πλάτος πίνακα:","buttonInsert":"Εισαγωγή","default":"προεπιλογή","align":"Στοίχιση:","insertTableRowBeforeLabel":"Προσθήκη γραμμής πριν","cellSpacing":"Απόσταση κελιών","pixels":"εικονοστοιχεία","selectTableLabel":"Επιλογή πίνακα","row [...]
\ No newline at end of file
+({
+	insertTableTitle: "Εισαγωγή πίνακα",
+	modifyTableTitle: "Τροποποίηση πίνακα",
+	rows: "Γραμμές:",
+	columns: "Στήλες:",
+	align: "Στοίχιση:",
+	cellPadding: "Περιθώριο κελιών:",
+	cellSpacing: "Απόσταση κελιών",
+	tableWidth: "Πλάτος πίνακα:",
+	backgroundColor: "Χρώμα φόντου:",
+	borderColor: "Χρώμα περιγράμματος:",
+	borderThickness: "Πάχος περιγράμματος",
+	percent: "ποσοστό",
+	pixels: "εικονοστοιχεία",
+	"default": "προεπιλογή",
+	left: "αριστερά",
+	center: "κέντρο",
+	right: "δεξιά",
+	buttonSet: "Ορισμός", // translated elsewhere?
+	buttonInsert: "Εισαγωγή",
+
+	selectTableLabel: "Επιλογή πίνακα",
+	insertTableRowBeforeLabel: "Προσθήκη γραμμής πριν",
+	insertTableRowAfterLabel: "Προσθήκη γραμμής μετά",
+	insertTableColumnBeforeLabel: "Προσθήκη στήλης πριν",
+	insertTableColumnAfterLabel: "Προσθήκη στήλης μετά",
+	deleteTableRowLabel: "Διαγραφή γραμμής",
+	deleteTableColumnLabel: "Διαγραφή στήλης"
+})
diff --git a/dojox/editor/plugins/nls/es/Breadcrumb.js b/dojox/editor/plugins/nls/es/Breadcrumb.js
index ce8cc3b..29ad69e 100644
--- a/dojox/editor/plugins/nls/es/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/es/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"Seleccionar contenido","deleteElement":"Suprimir elemento","moveEnd":"Mover cursor al final","deleteContents":"Suprimir contenido","nodeActions":"Acciones de ${nodeName}","selectElement":"Seleccionar elemento","moveStart":"Mover cursor al inicio"})
\ No newline at end of file
+({
+	"nodeActions": "Acciones de ${nodeName}",
+	"selectContents": "Seleccionar contenido",
+	"selectElement": "Seleccionar elemento",
+	"deleteElement": "Suprimir elemento",
+	"deleteContents": "Suprimir contenido",
+	"moveStart": "Mover cursor al inicio",
+	"moveEnd": "Mover cursor al final"
+})
+
diff --git a/dojox/editor/plugins/nls/es/FindReplace.js b/dojox/editor/plugins/nls/es/FindReplace.js
index f5bed74..3362263 100644
--- a/dojox/editor/plugins/nls/es/FindReplace.js
+++ b/dojox/editor/plugins/nls/es/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"Hacia atrás","findReplace":"Conmutar Buscar/Sustituir","replaceAll":"Todas las apariciones","replaceDialogText":"Se han sustituido ${0} apariciones.","replaceButton":"Sustituir","findButton":"Buscar","findLabel":"Buscar:","matchCase":"Coincidir mayúsculas y minúsculas","replaceLabel":"Sustituir por:"})
\ No newline at end of file
+({
+	"findLabel": "Buscar:",
+	"replaceLabel": "Sustituir por:",
+	"findReplace": "Conmutar Buscar/Sustituir",
+	"matchCase": "Coincidir mayúsculas y minúsculas", 
+	"backwards": "Hacia atrás",
+	"replaceAll": "Todas las apariciones", 
+	"findButton": "Buscar",
+	"replaceButton": "Sustituir",
+	"replaceDialogText": "Se han sustituido ${0} apariciones."
+})
+
diff --git a/dojox/editor/plugins/nls/es/InsertEntity.js b/dojox/editor/plugins/nls/es/InsertEntity.js
index 5d5fd22..cfc5f24 100644
--- a/dojox/editor/plugins/nls/es/InsertEntity.js
+++ b/dojox/editor/plugins/nls/es/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"Insertar símbolo"})
\ No newline at end of file
+({
+	insertEntity: "Insertar símbolo"
+})
+
diff --git a/dojox/editor/plugins/nls/es/PageBreak.js b/dojox/editor/plugins/nls/es/PageBreak.js
index 1e97e81..381e2f0 100644
--- a/dojox/editor/plugins/nls/es/PageBreak.js
+++ b/dojox/editor/plugins/nls/es/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"Salto de página"})
\ No newline at end of file
+({
+	"pageBreak": "Salto de página"
+})
+
diff --git a/dojox/editor/plugins/nls/es/Preview.js b/dojox/editor/plugins/nls/es/Preview.js
index ba400f6..581b725 100644
--- a/dojox/editor/plugins/nls/es/Preview.js
+++ b/dojox/editor/plugins/nls/es/Preview.js
@@ -1 +1,4 @@
-({"preview":"Previsualización"})
\ No newline at end of file
+({
+	"preview": "Previsualización"
+})
+
diff --git a/dojox/editor/plugins/nls/es/Save.js b/dojox/editor/plugins/nls/es/Save.js
index 426ca84..11af7ed 100644
--- a/dojox/editor/plugins/nls/es/Save.js
+++ b/dojox/editor/plugins/nls/es/Save.js
@@ -1 +1,4 @@
-({"save":"Guardar"})
\ No newline at end of file
+({
+	"save": "Guardar"
+})
+
diff --git a/dojox/editor/plugins/nls/es/ShowBlockNodes.js b/dojox/editor/plugins/nls/es/ShowBlockNodes.js
index ef0570f..2bfaf04 100644
--- a/dojox/editor/plugins/nls/es/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/es/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"Mostrar elementos de bloque HTML"})
\ No newline at end of file
+({
+	"showBlockNodes": "Mostrar elementos de bloque HTML"
+})
+
diff --git a/dojox/editor/plugins/nls/es/Smiley.js b/dojox/editor/plugins/nls/es/Smiley.js
index b0025d0..a5b20ef 100644
--- a/dojox/editor/plugins/nls/es/Smiley.js
+++ b/dojox/editor/plugins/nls/es/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"risa","emoticonCool":"guay","emoticonTongue":"burlón","emoticonCrying":"llorando","emoticonOops":"lo siento","emoticonFrown":"ceño fruncido","emoticonAngry":"enfadado","emoticonShy":"tímido","emoticonNo":"no","emoticonAngel":"ángel","smiley":"Insertar emoticono","emoticonIdea":"idea","emoticonEyebrow":"ceja levantada","emoticonSmile":"sonrisa","emoticonWink":"guiño","emoticonYes":"sí","emoticonGrin":"carcajada","emoticonGoofy":"patoso","emoticonHalf":"escéptico"})
\ No newline at end of file
+({
+	smiley: "Insertar emoticono",
+	emoticonSmile: "sonrisa",
+	emoticonLaughing: "risa",
+	emoticonWink: "guiño",
+	emoticonGrin: "carcajada",
+	emoticonCool: "guay",
+	emoticonAngry: "enfadado",  
+	emoticonHalf: "escéptico", 
+	emoticonEyebrow: "ceja levantada",
+	emoticonFrown: "ceño fruncido",
+	emoticonShy: "tímido",
+	emoticonGoofy: "patoso",
+	emoticonOops: "lo siento",
+	emoticonTongue: "burlón",
+	emoticonIdea: "idea",
+	emoticonYes: "sí",
+	emoticonNo: "no",	
+	emoticonAngel: "ángel",
+	emoticonCrying: "llorando"
+})
+
diff --git a/dojox/editor/plugins/nls/es/TableDialog.js b/dojox/editor/plugins/nls/es/TableDialog.js
index db69bbf..ff48725 100644
--- a/dojox/editor/plugins/nls/es/TableDialog.js
+++ b/dojox/editor/plugins/nls/es/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Establecer","insertTableTitle":"Insertar tabla","insertTableRowAfterLabel":"Añadir fila después","center":"centro","deleteTableColumnLabel":"Suprimir columna","right":"derecha","insertTableColumnBeforeLabel":"Añadir columna antes","tableWidth":"Ancho de tabla:","buttonInsert":"Insertar","default":"default","align":"Alinear:","insertTableRowBeforeLabel":"Añadir fila antes","cellSpacing":"Espaciado de celda:","pixels":"píxeles","selectTableLabel":"Seleccionar tabla","rows":" [...]
\ No newline at end of file
+({
+	insertTableTitle: "Insertar tabla",
+	modifyTableTitle: "Modificar tabla",
+	rows: "Filas:",
+	columns: "Columnas:",
+	align: "Alinear:",
+	cellPadding: "Relleno de celda:",
+	cellSpacing: "Espaciado de celda:",
+	tableWidth: "Ancho de tabla:",
+	backgroundColor: "Color de fondo:",
+	borderColor: "Color de borde:",
+	borderThickness: "Ancho de borde",
+	percent: "por ciento",
+	pixels: "píxeles",
+	"default": "default",
+	left: "izquierda",
+	center: "centro",
+	right: "derecha",
+	buttonSet: "Establecer", // translated elsewhere?
+	buttonInsert: "Insertar",
+
+	selectTableLabel: "Seleccionar tabla",
+	insertTableRowBeforeLabel: "Añadir fila antes",
+	insertTableRowAfterLabel: "Añadir fila después",
+	insertTableColumnBeforeLabel: "Añadir columna antes",
+	insertTableColumnAfterLabel: "Añadir columna después",
+	deleteTableRowLabel: "Suprimir fila",
+	deleteTableColumnLabel: "Suprimir columna"
+})
+
diff --git a/dojox/editor/plugins/nls/es/latinEntities.js b/dojox/editor/plugins/nls/es/latinEntities.js
index ecc7b5f..584f9c3 100644
--- a/dojox/editor/plugins/nls/es/latinEntities.js
+++ b/dojox/editor/plugins/nls/es/latinEntities.js
@@ -1 +1,257 @@
-({"le":"menor o igual que","prod":"productoria\nmultiplicatoria","zwj":"conector de anchura cero","mdash":"guión largo","frasl":"barra de fracción","upsih":"símbolo de letra ípsilon griega con gancho","prop":"proporcional","middot":"punto medio\ncoma georgiana\npunto medio griego","hellip":"puntos suspensivos","eta":"letra eta griega minúscula","iacute":"letra i latina minúscula con acento agudo","yen":"símbolo del yen\nsímbolo de yuan","rlm":"marca de derecha a izquierda","macr":"macrón [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"signo de exclamación inicial",
+	cent:"símbolo de centavos",
+	pound:"símbolo libra esterlina",
+	curren:"símbolo monetario",
+	yen:"símbolo del yen\nsímbolo de yuan",
+	brvbar:"barra dividida\nbarra vertical dividida",
+	sect:"signo de sección",
+	uml:"diéresis\ndiéresis de espaciado",
+	copy:"símbolo de copyright",
+	ordf:"indicador de ordinal femenino",
+	laquo:"comillas dobles en ángulo a la izquierda",
+	not:"signo de negación",
+	shy:"signo de guión corto",
+	reg:"símbolo de registrado\nsímbolo de marca registrada",
+	macr:"macrón\ndiacrítico largo\nlínea superior\nbarra superior APL",
+	deg:"signo de grados",
+	plusmn:"signo de más-menos\nsigno de más o menos",
+	sup2:"superíndice dos\nsuperíndice de dígito dos\nelevado al cuadrado",
+	sup3:"superíndice tres\nsuperíndice de dígito tres\nelevado al cubo",
+	acute:"acento agudo\nagudo de espaciado",
+	micro:"signo de micro",
+	para:"signo de párrafo",
+	middot:"punto medio\ncoma georgiana\npunto medio griego",
+	cedil:"cedilla\ncedilla de espaciado",
+	sup1:"superíndice uno\nsuperíndice de dígito uno",
+	ordm:"indicador de ordinal masculino",
+	raquo:"comillas dobles en ángulo a la derecha",
+	frac14:"fracción de cuarto vulgar\nfracción de cuarto",
+	frac12:"fracción de medio vulgar\nfracción de medio",
+	frac34:"fracción de tres cuartos vulgar\nfracción de tres cuartos",
+	iquest:"signo de interrogación inicial\nsigno de apertura de interrogación",
+	Agrave:"letra A latina mayúscula con acento grave\nletra A latina mayúscula grave",
+	Aacute:"letra A latina mayúscula con acento agudo",
+	Acirc:"letra A latina mayúscula con acento circunflejo",
+	Atilde:"letra A latina mayúscula con virgulilla\nletra A latina mayúscula con tilde",
+	Auml:"letra A latina mayúscula con diéresis",
+	Aring:"letra A latina mayúscula con anillo encima\nletra A latina mayúscula con anillo",
+	AElig:"diptongo AE latinas mayúsculas\nligadura de AE latinas mayúsculas",
+	Ccedil:"letra C latina mayúscula con cedilla",
+	Egrave:"letra E latina mayúscula con acento grave",
+	Eacute:"letra E latina mayúscula con acento agudo",
+	Ecirc:"letra E latina mayúscula con acento circunflejo",
+	Euml:"letra E latina mayúscula con acento diéresis",
+	Igrave:"letra I latina mayúscula con acento grave",
+	Iacute:"letra I latina mayúscula con acento agudo",
+	Icirc:"letra I latina mayúscula con acento circunflejo",
+	Iuml:"letra I latina mayúscula con diéresis",
+	ETH:"letra ETH latina mayúscula",
+	Ntilde:"letra N latina mayúscula con virgulilla\nletra N latina mayúscula con tilde\nletra Ñ latina mayúscula",
+	Ograve:"letra O latina mayúscula con acento grave",
+	Oacute:"letra O latina mayúscula con acento agudo",
+	Ocirc:"letra O latina mayúscula con acento circunflejo",
+	Otilde:"letra O latina mayúscula con virgulilla\nletra O latina mayúscula con tilde",
+	Ouml:"letra O latina mayúscula con diéresis",
+	times:"signo de multiplicación",
+	Oslash:"letra O latina mayúscula con barra\nletra O latina mayúscula con barra inclinada",
+	Ugrave:"letra U latina mayúscula con acento grave",
+	Uacute:"letra U latina mayúscula con acento agudo",
+	Ucirc:"letra U latina mayúscula con acento circunflejo",
+	Uuml:"letra U latina mayúscula con diéresis",
+	Yacute:"letra Y latina mayúscula con acento agudo",
+	THORN:"letra THORN latina mayúscula",
+	szlig:"letra s fuerte latina minúscula\nEszet",
+	agrave:"letra a latina minúscula con acento grave\nletra a latina minúscula grave",
+	aacute:"letra a latina minúscula con acento agudo",
+	acirc:"letra a latina minúscula con acento circunflejo",
+	atilde:"letra a latina minúscula con virgulilla\nletra a latina minúscula con tilde",
+	auml:"letra a latina minúscula con diéresis",
+	aring:"letra a latina minúscula con anillo encima\nletra a latina minúscula con anillo",
+	aelig:"Diptongo ae latinas minúsculas\nligadura de ae latinas minúsculas",
+	ccedil:"letra c latina minúscula con cedilla",
+	egrave:"letra e latina minúscula con acento grave",
+	eacute:"letra e latina minúscula con acento agudo",
+	ecirc:"letra e latina minúscula con acento circunflejo",
+	euml:"letra e latina minúscula con diéresis",
+	igrave:"letra i latina minúscula con acento grave",
+	iacute:"letra i latina minúscula con acento agudo",
+	icirc:"letra i latina minúscula con acento circunflejo",
+	iuml:"letra i latina minúscula con diéresis",
+	eth:"letra eth latina minúscula",
+	ntilde:"letra n latina minúscula con virgulilla\nletra n latina minúscula con tilde",
+	ograve:"letra o latina minúscula con acento grave",
+	oacute:"letra o latina minúscula con acento agudo",
+	ocirc:"letra o latina minúscula con acento circunflejo",
+	otilde:"letra o latina minúscula con virgulilla\nletra o latina minúscula con tilde",
+	ouml:"letra o latina minúscula con diéresis",
+	divide:"signo de división",
+	oslash:"letra o latina minúscula con barra\nletra o latina minúscula con barra inclinada",
+	ugrave:"letra u latina minúscula con acento grave",
+	uacute:"letra u latina minúscula con acento agudo",
+	ucirc:"letra u latina minúscula con acento circunflejo",
+	uuml:"letra u latina minúscula con diéresis",
+	yacute:"letra y latina minúscula con acento agudo",
+	thorn:"letra thorn latina minúscula",
+	yuml:"letra y latina minúscula con diéresis",
+
+// Greek Characters and Symbols
+	fnof:"letra f latina minúscula con gancho\nfunción\nflorín",
+	Alpha:"letra alpha griega mayúscula",
+	Beta:"letra beta griega mayúscula",
+	Gamma:"letra gamma griega mayúscula",
+	Delta:"letra delta griega mayúscula",
+	Epsilon:"letra épsilon griega mayúscula",
+	Zeta:"letra zeta griega mayúscula",
+	Eta:"letra eta griega mayúscula",
+	Theta:"letra theta griega mayúscula",
+	Iota:"letra iota griega mayúscula",
+	Kappa:"letra kappa griega mayúscula",
+	Lambda:"letra lambda griega mayúscula",
+	Mu:"letra mu griega mayúscula",
+	Nu:"letra nu griega mayúscula",
+	Xi:"letra xi griega mayúscula",
+	Omicron:"letra ómicron griega mayúscula",
+	Pi:"letra pi griega mayúscula",
+	Rho:"letra rho griega mayúscula",
+	Sigma:"letra sigma griega mayúscula",
+	Tau:"letra tau griega mayúscula",
+	Upsilon:"letra ípsilon griega mayúscula",
+	Phi:"letra phi griega mayúscula",
+	Chi:"letra chi griega mayúscula",
+	Psi:"letra psi griega mayúscula",
+	Omega:"letra omega griega mayúscula",
+	alpha:"letra alpha griega minúscula",
+	beta:"letra beta griega minúscula",
+	gamma:"letra gamma griega minúscula",
+	delta:"letra delta griega minúscula",
+	epsilon:"letra épsilon griega minúscula",
+	zeta:"letra zeta griega minúscula",
+	eta:"letra eta griega minúscula",
+	theta:"letra theta griega minúscula",
+	iota:"letra iota griega minúscula",
+	kappa:"letra kappa griega minúscula",
+	lambda:"letra lambda griega minúscula",
+	mu:"letra mu griega minúscula",
+	nu:"letra nu griega minúscula",
+	xi:"letra xi griega minúscula",
+	omicron:"letra ómicron griega minúscula",
+	pi:"letra pi griega minúscula",
+	rho:"letra rho griega minúscula",
+	sigmaf:"letra sigma final griega minúscula",
+	sigma:"letra sigma griega minúscula",
+	tau:"letra tau griega minúscula",
+	upsilon:"letra ípsilon griega minúscula",
+	phi:"letra phi griega minúscula",
+	chi:"letra chi griega minúscula",
+	psi:"letra psi griega minúscula",
+	omega:"letra omega griega minúscula",
+	thetasym:"símbolo de letra theta griega minúscula",
+	upsih:"símbolo de letra ípsilon griega con gancho",
+	piv:"símbolo pi griego",
+	bull:"viñeta\ncírculo negro pequeño",
+	hellip:"puntos suspensivos",
+	prime:"símbolo primo\nminutos\npies",
+	Prime:"símbolo primo doble\nsegundos\npulgadas",
+	oline:"sobrelínea\nsobre la letra",
+	frasl:"barra de fracción",
+	weierp:"letra P mayúscula cursiva",
+	image:"letra I mayúscula\nnúmeros imaginarios",
+	real:"letra R mayúscula\nnúmeros reales",
+	trade:"símbolo de marca registrada",
+	alefsym:"símbolo alef\nprimer número transfinito",
+	larr:"flecha a la izquierda",
+	uarr:"flecha hacia arriba",
+	rarr:"flecha a la derecha",
+	darr:"flecha hacia abajo",
+	harr:"flecha izquierda-derecha",
+	crarr:"flecha esquinada abajo a la izquierda\nretorno de carro",
+	lArr:"doble flecha a la izquierda",
+	uArr:"doble flecha hacia arriba",
+	rArr:"doble flecha a la derecha",
+	dArr:"doble flecha hacia abajo",
+	hArr:"doble flecha izquierda-derecha",
+	forall:"para todo",
+	part:"derivada parcial",
+	exist:"existe",
+	empty:"conjunto vacío\nconjunto nulo\ndiámetro",
+	nabla:"nabla\ngradiente",
+	isin:"pertenece",
+	notin:"no pertenece",
+	ni:"está incluido",
+	prod:"productoria\nmultiplicatoria",
+	sum:"sumatoria",
+	minus:"signo menos",
+	lowast:"operador asterisco",
+	radic:"raíz cuadrada\nsigno radical",
+	prop:"proporcional",
+	infin:"infinito",
+	ang:"ángulo",
+	and:"y lógico\ncuña",
+	or:"o lógico\nuve",
+	cap:"intersección\nconjuntos",
+	cup:"unión\nconjuntos","int":"integral",
+	there4:"por lo tanto",
+	sim:"operador de tilde\nno lógico\nparecido a",
+	cong:"aproximadamente igual a",
+	asymp:"parecido\ncasi igual a",
+	ne:"no igual a",
+	equiv:"idéntico a",
+	le:"menor o igual que",
+	ge:"mayor o igual que",
+	sub:"subconjunto de",
+	sup:"superconjunto de",
+	nsub:"no un subconjunto de",
+	sube:"subconjunto de o igual a",
+	supe:"superconjunto de o igual a",
+	oplus:"más en círculo\nsuma directa",
+	otimes:"cruz en círculo\nproducto vectorial",
+	perp:"ortogonal a\nperpendicular",
+	sdot:"operador punto",
+	lceil:"parte superior de corchete abierto",
+	rceil:"parte superior de corchete cerrado",
+	lfloor:"parte inferior de corchete abierto",
+	rfloor:"parte inferior de corchete abierto",
+	lang:"corchete angular hacia la izquierda",
+	rang:"corchete angular hacia la derecha",
+	loz:"rombo",
+	spades:"palo de picas",
+	clubs:"palo de tréboles",
+	hearts:"palo de corazones",
+	diams:"palo de diamantes",
+	OElig:"ligadura de OE latinas mayúsculas",
+	oelig:"ligadura de oe latinas minúsculas",
+	Scaron:"letra S latina mayúscula con anticircunflejo",
+	scaron:"letra s latina minúscula con anticircunflejo",
+	Yuml:"letra Y latina mayúscula con diéresis",
+	circ:"acento circunflejo",
+	tilde:"tilde pequeña",
+	ensp:"espacio",
+	emsp:"espacio largo",
+	thinsp:"espacio estrecho",
+	zwnj:"separador de anchura cero",
+	zwj:"conector de anchura cero",
+	lrm:"marca de izquierda a derecha",
+	rlm:"marca de derecha a izquierda",
+	ndash:"guión",
+	mdash:"guión largo",
+	lsquo:"comilla simple abierta",
+	rsquo:"comilla simple cerrada",
+	sbquo:"comilla simple inferior",
+	ldquo:"comillas dobles abiertas",
+	rdquo:"comillas dobles cerradas",
+	bdquo:"comillas dobles inferiores",
+	dagger:"daga",
+	Dagger:"daga doble",
+	permil:"signo de por mil",
+	lsaquo:"comilla simple angular abierta",
+	rsaquo:"comilla simple angular cerrada",
+	euro:"signo del euro"
+})
+
diff --git a/dojox/editor/plugins/nls/fi/TableDialog.js b/dojox/editor/plugins/nls/fi/TableDialog.js
index 07b5daa..12ff00d 100644
--- a/dojox/editor/plugins/nls/fi/TableDialog.js
+++ b/dojox/editor/plugins/nls/fi/TableDialog.js
@@ -1 +1,29 @@
-({"buttonSet":"Aseta","insertTableTitle":"Lisää taulukko","insertTableRowAfterLabel":"Lisää rivi jälkeen","center":"keskitetty","deleteTableColumnLabel":"Poista sarake","right":"oikea","insertTableColumnBeforeLabel":"Lisää sarake ennen","tableWidth":"Taulukon leveys:","buttonInsert":"Lisää","default":"oletus","align":"Tasaus:","insertTableRowBeforeLabel":"Lisää rivi ennen","cellSpacing":"Solujen väli:","pixels":"kuvapistettä","selectTableLabel":"Valitse taulukko","rows":"Rivit:","modifyT [...]
\ No newline at end of file
+({
+	insertTableTitle: "Lisää taulukko",
+	modifyTableTitle: "Muokkaa taulukkoa",
+	rows: "Rivit:",
+	columns: "Sarakkeet:",
+	align: "Tasaus:",
+	cellPadding: "Solun täyttö:",
+	cellSpacing: "Solujen väli:",
+	tableWidth: "Taulukon leveys:",
+	backgroundColor: "Taustaväri:",
+	borderColor: "Kehyksen väri:",
+	borderThickness: "Kehyksen paksuus",
+	percent: "prosenttia",
+	pixels: "kuvapistettä",
+	"default": "oletus",
+	left: "vasen",
+	center: "keskitetty",
+	right: "oikea",
+	buttonSet: "Aseta", // translated elsewhere?
+	buttonInsert: "Lisää",
+
+	selectTableLabel: "Valitse taulukko",
+	insertTableRowBeforeLabel: "Lisää rivi ennen",
+	insertTableRowAfterLabel: "Lisää rivi jälkeen",
+	insertTableColumnBeforeLabel: "Lisää sarake ennen",
+	insertTableColumnAfterLabel: "Lisää sarake jälkeen",
+	deleteTableRowLabel: "Poista rivi",
+	deleteTableColumnLabel: "Poista sarake"
+})
diff --git a/dojox/editor/plugins/nls/fr/Breadcrumb.js b/dojox/editor/plugins/nls/fr/Breadcrumb.js
index 98a2dcf..5899469 100644
--- a/dojox/editor/plugins/nls/fr/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/fr/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"Sélection de contenus","deleteElement":"Suppression d'un élément","moveEnd":"Déplacer le curseur vers la fin","deleteContents":"Suppression de contenus","nodeActions":"Actions ${nodeName}","selectElement":"Sélection d'un élément","moveStart":"Déplacer le curseur vers le début"})
\ No newline at end of file
+({
+	"nodeActions": "Actions ${nodeName}",
+	"selectContents": "Sélection de contenus",
+	"selectElement": "Sélection d'un élément",
+	"deleteElement": "Suppression d'un élément",
+	"deleteContents": "Suppression de contenus",
+	"moveStart": "Déplacer le curseur vers le début",
+	"moveEnd": "Déplacer le curseur vers la fin"
+})
+
diff --git a/dojox/editor/plugins/nls/fr/FindReplace.js b/dojox/editor/plugins/nls/fr/FindReplace.js
index b3514ad..23e12cc 100644
--- a/dojox/editor/plugins/nls/fr/FindReplace.js
+++ b/dojox/editor/plugins/nls/fr/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"Vers l'arrière","findReplace":"Rechercher/Remplacer","replaceAll":"Toutes les occurrences","replaceDialogText":"${0} occurrence(s) remplacée(s).","replaceButton":"Remplacer","findButton":"Rechercher","findLabel":"Que rechercher :","matchCase":"Respecter la casse","replaceLabel":"Remplacer par :"})
\ No newline at end of file
+({
+	"findLabel": "Que rechercher :",
+	"replaceLabel": "Remplacer par :",
+	"findReplace": "Rechercher/Remplacer",
+	"matchCase": "Respecter la casse", 
+	"backwards": "Vers l'arrière",
+	"replaceAll": "Toutes les occurrences", 
+	"findButton": "Rechercher",
+	"replaceButton": "Remplacer",
+	"replaceDialogText": "${0} occurrence(s) remplacée(s)."
+})
+
diff --git a/dojox/editor/plugins/nls/fr/InsertEntity.js b/dojox/editor/plugins/nls/fr/InsertEntity.js
index 9cdf961..31256eb 100644
--- a/dojox/editor/plugins/nls/fr/InsertEntity.js
+++ b/dojox/editor/plugins/nls/fr/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"Insertion d'un symbole"})
\ No newline at end of file
+({
+	insertEntity: "Insertion d'un symbole"
+})
+
diff --git a/dojox/editor/plugins/nls/fr/PageBreak.js b/dojox/editor/plugins/nls/fr/PageBreak.js
index f7e2e6f..4d89650 100644
--- a/dojox/editor/plugins/nls/fr/PageBreak.js
+++ b/dojox/editor/plugins/nls/fr/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"Saut de page"})
\ No newline at end of file
+({
+	"pageBreak": "Saut de page"
+})
+
diff --git a/dojox/editor/plugins/nls/fr/Preview.js b/dojox/editor/plugins/nls/fr/Preview.js
index 73d24e6..faead7f 100644
--- a/dojox/editor/plugins/nls/fr/Preview.js
+++ b/dojox/editor/plugins/nls/fr/Preview.js
@@ -1 +1,4 @@
-({"preview":"Aperçu"})
\ No newline at end of file
+({
+	"preview": "Aperçu"
+})
+
diff --git a/dojox/editor/plugins/nls/fr/Save.js b/dojox/editor/plugins/nls/fr/Save.js
index 74657ea..2adf8ab 100644
--- a/dojox/editor/plugins/nls/fr/Save.js
+++ b/dojox/editor/plugins/nls/fr/Save.js
@@ -1 +1,4 @@
-({"save":"Sauvegarder"})
\ No newline at end of file
+({
+	"save": "Sauvegarder"
+})
+
diff --git a/dojox/editor/plugins/nls/fr/ShowBlockNodes.js b/dojox/editor/plugins/nls/fr/ShowBlockNodes.js
index 243cda5..0da669b 100644
--- a/dojox/editor/plugins/nls/fr/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/fr/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"Affichage des éléments de bloc HTML"})
\ No newline at end of file
+({
+	"showBlockNodes": "Affichage des éléments de bloc HTML"
+})
+
diff --git a/dojox/editor/plugins/nls/fr/Smiley.js b/dojox/editor/plugins/nls/fr/Smiley.js
index 1c0ae69..0e6f8c5 100644
--- a/dojox/editor/plugins/nls/fr/Smiley.js
+++ b/dojox/editor/plugins/nls/fr/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"rire","emoticonCool":"calme","emoticonTongue":"langue","emoticonCrying":"pleurs","emoticonOops":"oops","emoticonFrown":"froncement de sourcils","emoticonAngry":"colère","emoticonShy":"timide","emoticonNo":"non","emoticonAngel":"ange","smiley":"Insérer une émoticône","emoticonIdea":"idée","emoticonEyebrow":"sourcils","emoticonSmile":"sourire","emoticonWink":"clin d'oeil","emoticonYes":"oui","emoticonGrin":"sourire large","emoticonGoofy":"dingo","emoticonHalf":"demi"})
\ No newline at end of file
+({
+	smiley: "Insérer une émoticône",
+	emoticonSmile: "sourire",
+	emoticonLaughing: "rire",
+	emoticonWink: "clin d'oeil",
+	emoticonGrin: "sourire large",
+	emoticonCool: "calme",
+	emoticonAngry: "colère",  
+	emoticonHalf: "demi", 
+	emoticonEyebrow: "sourcils",
+	emoticonFrown: "froncement de sourcils",
+	emoticonShy: "timide",
+	emoticonGoofy: "dingo",
+	emoticonOops: "oops",
+	emoticonTongue: "langue",
+	emoticonIdea: "idée",
+	emoticonYes: "oui",
+	emoticonNo: "non",	
+	emoticonAngel: "ange",
+	emoticonCrying: "pleurs"
+})
+
diff --git a/dojox/editor/plugins/nls/fr/TableDialog.js b/dojox/editor/plugins/nls/fr/TableDialog.js
index 72b0ef3..20edf5e 100644
--- a/dojox/editor/plugins/nls/fr/TableDialog.js
+++ b/dojox/editor/plugins/nls/fr/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Définir","insertTableTitle":"Insertion d'une table","insertTableRowAfterLabel":"Ajouter une ligne après","center":"au centre","deleteTableColumnLabel":"Supprimer une colonne","right":"à droite","insertTableColumnBeforeLabel":"Ajouter une colonne avant","tableWidth":"Largeur de la table :","buttonInsert":"Insérer","default":"valeur par défaut","align":"Aligner :","insertTableRowBeforeLabel":"Ajouter une ligne avant","cellSpacing":"Espacement des cellules :","pixels":"pixels [...]
\ No newline at end of file
+({
+	insertTableTitle: "Insertion d'une table",
+	modifyTableTitle: "Modification d'une table",
+	rows: "Lignes :",
+	columns: "Colonnes :",
+	align: "Aligner :",
+	cellPadding: "Remplissage des cellules",
+	cellSpacing: "Espacement des cellules :",
+	tableWidth: "Largeur de la table :",
+	backgroundColor: "Couleur d'arrière-plan :",
+	borderColor: "Couleur de la bordure :",
+	borderThickness: "Epaisseur de la bordure",
+	percent: "pourcentage",
+	pixels: "pixels",
+	"default": "valeur par défaut",
+	left: "à gauche",
+	center: "au centre",
+	right: "à droite",
+	buttonSet: "Définir", // translated elsewhere?
+	buttonInsert: "Insérer",
+
+	selectTableLabel: "Sélection d'une table",
+	insertTableRowBeforeLabel: "Ajouter une ligne avant",
+	insertTableRowAfterLabel: "Ajouter une ligne après",
+	insertTableColumnBeforeLabel: "Ajouter une colonne avant",
+	insertTableColumnAfterLabel: "Ajouter une colonne après",
+	deleteTableRowLabel: "Supprimer une ligne",
+	deleteTableColumnLabel: "Supprimer une colonne"
+})
+
diff --git a/dojox/editor/plugins/nls/fr/latinEntities.js b/dojox/editor/plugins/nls/fr/latinEntities.js
index ad0b1e1..d7aca89 100644
--- a/dojox/editor/plugins/nls/fr/latinEntities.js
+++ b/dojox/editor/plugins/nls/fr/latinEntities.js
@@ -1 +1,257 @@
-({"le":"inférieur ou égal à","prod":"produit n-aire\nsigne produit","zwj":"liant sans chasse","mdash":"tiret cadratin","frasl":"barre de fraction","upsih":"Greek - upsilon avec symbole de crochet","prop":"proportionnel à","middot":"point médian\nvirgule géorgiennea\npoint médian grec","hellip":"points de suspension\ntrois points de conduite","eta":"Grec - eta minuscule","iacute":"Latin - i minuscule avec accent aigu","yen":"signe yen\nsigne yuan","rlm":"marque de droite à gauche","macr": [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"point d'exclamation inversé",
+	cent:"signe cent",
+	pound:"signe livre sterling",
+	curren:"signe devise",
+	yen:"signe yen\nsigne yuan",
+	brvbar:"barre interrompue\nbarre verticale interrompue",
+	sect:"signe section",
+	uml:"tréma\ntréma d'espacement",
+	copy:"signe de droit d'auteur",
+	ordf:"indicateur ordinal féminin",
+	laquo:"guillemets fermants",
+	not:"signe non",
+	shy:"trait d'union conditionnel\ntiret conditionnel",
+	reg:"signe enregistré\nmarque commerciale enregistrée",
+	macr:"macron\nmacron d'espacement\nligne supérieure\nbarre supérieure APL",
+	deg:"signe degré",
+	plusmn:"signe plus-moins\nsigne plus-ou-moins",
+	sup2:"exposant deux\npuissance deux\ncarré",
+	sup3:"exposant trois\npuissance trois\ncube",
+	acute:"accent aigu\naccent aigu d'espacement",
+	micro:"signe micro",
+	para:"symbole de paragraphe",
+	middot:"point médian\nvirgule géorgiennea\npoint médian grec",
+	cedil:"cédille\ncédille d'espacement",
+	sup1:"exposant un\npuissance un",
+	ordm:"indicateur ordinal masculin",
+	raquo:"guillemets ouvrants",
+	frac14:"fraction commune un quart\nfraction un quart",
+	frac12:"fraction commune un demi\nfraction un demi",
+	frac34:"fraction commune trois quarts\nfraction trois quarts",
+	iquest:"point d'interrogation inversé\npoint d'interrogation retourné",
+	Agrave:"Latin - A majuscule avec accent grave\nLatin - A majuscule accent grave",
+	Aacute:"Latin - A majuscule avec accent aigu",
+	Acirc:"Latin - A majuscule avec accent circonflexe",
+	Atilde:"Latin - A majuscule avec tilde",
+	Auml:"Latin - A majuscule avec tréma",
+	Aring:"Latin - A majuscule rond en chef\nLatin - A majuscule rond",
+	AElig:"Latin - AE majuscule\nLatin - AE majuscule (ligature)",
+	Ccedil:"Latin - C majuscule avec cédille",
+	Egrave:"Latin - E majuscule avec accent grave",
+	Eacute:"Latin - E majuscule avec accent aigu",
+	Ecirc:"Latin - E majuscule avec accent circonflexe",
+	Euml:"Latin - E majuscule avec tréma",
+	Igrave:"Latin - I majuscule avec accent grave",
+	Iacute:"Latin - I majuscule avec accent aigu",
+	Icirc:"Latin - I majuscule avec accent circonflexe",
+	Iuml:"Latin - I majuscule avec tréma",
+	ETH:"Latin - ETH majuscule",
+	Ntilde:"Latin - N majuscule avec tilde",
+	Ograve:"Latin - O majuscule avec accent grave",
+	Oacute:"Latin - O majuscule avec accent aigu",
+	Ocirc:"Latin - O majuscule avec accent circonflexe",
+	Otilde:"Latin - O majuscule avec tilde",
+	Ouml:"Latin - O majuscule avec tréma",
+	times:"signe multiplication",
+	Oslash:"Latin - O majuscule barré\nLatin - Ensemble vide",
+	Ugrave:"Latin - U majuscule avec accent grave",
+	Uacute:"Latin - U majuscule avec accent aigu",
+	Ucirc:"Latin - U majuscule avec accent circonflexe",
+	Uuml:"Latin - U majuscule avec tréma",
+	Yacute:"Latin - Y majuscule avec accent aigu",
+	THORN:"Latin THORN majuscule",
+	szlig:"Latin - s dur minuscule\nss",
+	agrave:"Latin - a minuscule avec accent grave\nLatin - a minuscule accent grave",
+	aacute:"Latin - a minuscule avec accent aigu",
+	acirc:"Latin - a minuscule avec accent circonflexe",
+	atilde:"Latin - a minuscule avec tilde",
+	auml:"Latin - a minuscule avec tréma",
+	aring:"Latin - a minuscule rond en chef\nLatin - a minuscule rond",
+	aelig:"Latin - AE minuscule\nLatin - AE minuscule (ligature)",
+	ccedil:"Latin - c minuscule avec cédille",
+	egrave:"Latin - e minuscule avec accent grave",
+	eacute:"Latin - e minuscule avec accent aigu",
+	ecirc:"Latin - e minuscule avec accent circonflexe",
+	euml:"Latin - e minuscule avec tréma",
+	igrave:"Latin - i minuscule avec accent grave",
+	iacute:"Latin - i minuscule avec accent aigu",
+	icirc:"Latin - i minuscule avec accent circonflexe",
+	iuml:"Latin - i minuscule avec tréma",
+	eth:"Latin - eth minuscule",
+	ntilde:"Latin - n minuscule avec tilde",
+	ograve:"Latin - o minuscule avec accent grave",
+	oacute:"Latin - o minuscule avec accent aigu",
+	ocirc:"Latin - o minuscule avec accent circonflexe",
+	otilde:"Latin - o minuscule avec tilde",
+	ouml:"Latin - o minuscule avec tréma",
+	divide:"signe division",
+	oslash:"Latin - o minuscule barré\nLatin - Ensemble vide minuscule",
+	ugrave:"Latin - u minuscule avec accent grave",
+	uacute:"Latin - u minuscule avec accent aigu",
+	ucirc:"Latin - u minuscule avec accent circonflexe",
+	uuml:"Latin - u minuscule avec tréma",
+	yacute:"Latin - y minuscule avec accent aigu",
+	thorn:"Latin - thorn minuscule",
+	yuml:"Latin - y minuscule avec tréma",
+
+// Greek Characters and Symbols
+	fnof:"Latin - f minuscule avec crochet\nfonction\nflorin",
+	Alpha:"Grec - alpha majuscule",
+	Beta:"Grec - beta majuscule",
+	Gamma:"Grec - gamma majuscule",
+	Delta:"Grec - delta majuscule",
+	Epsilon:"Grec - epsilon majuscule",
+	Zeta:"Grec - zeta majuscule",
+	Eta:"Grec - eta majuscule",
+	Theta:"Grec - theta majuscule",
+	Iota:"Grec - iota majuscule",
+	Kappa:"Grec - kappa majuscule",
+	Lambda:"Grec - lambda majuscule",
+	Mu:"Grec - mu majuscule",
+	Nu:"Grec - nu majuscule",
+	Xi:"Grec - xi majuscule",
+	Omicron:"Grec - omicron majuscule",
+	Pi:"Grec - pi majuscule",
+	Rho:"Grec - rho majuscule",
+	Sigma:"Grec - sigma majuscule",
+	Tau:"Grec - tau majuscule",
+	Upsilon:"Grec - upsilon majuscule",
+	Phi:"Grec - phi majuscule",
+	Chi:"Grec - chi majuscule",
+	Psi:"Grec - psi majuscule",
+	Omega:"Grec - omega majuscule",
+	alpha:"Grec - alpha minuscule",
+	beta:"Grec - beta minuscule",
+	gamma:"Grec - gamma minuscule",
+	delta:"Grec - delta minuscule",
+	epsilon:"Grec - epsilon minuscule",
+	zeta:"Grec - zeta minuscule",
+	eta:"Grec - eta minuscule",
+	theta:"Grec - theta minuscule",
+	iota:"Grec - iota minuscule",
+	kappa:"Grec - kappa minuscule",
+	lambda:"Grec - lambda minuscule",
+	mu:"Grec - mu minuscule",
+	nu:"Grec - nu minuscule",
+	xi:"Grec - xi minuscule",
+	omicron:"Grec - omicron minuscule",
+	pi:"Grec - pi minuscule",
+	rho:"Grec - rho minuscule",
+	sigmaf:"Grec - sigma final minuscule",
+	sigma:"Grec - sigma minuscule",
+	tau:"Grec - tau minuscule",
+	upsilon:"Grec - upsilon minuscule",
+	phi:"Grec - phi minuscule",
+	chi:"Grec - chi minuscule",
+	psi:"Grec - psi minuscule",
+	omega:"Grec - omega minuscule",
+	thetasym:"Grec - theta minuscule",
+	upsih:"Greek - upsilon avec symbole de crochet",
+	piv:"Greek - symbole pi",
+	bull:"puce\npetit cercle noir",
+	hellip:"points de suspension\ntrois points de conduite",
+	prime:"apostrophe\nminutes\npieds",
+	Prime:"double apostrophe\nsecondes\npouces",
+	oline:"surligné\nbarre supérieure d'espacement",
+	frasl:"barre de fraction",
+	weierp:"P majuscule scripte\nensemble de puissances\nfonction elliptique de Weierstrass",
+	image:"I majuscule noir\npartie imaginaire",
+	real:"R majuscule noir\npartie réelle",
+	trade:"signe de marque commerciale",
+	alefsym:"symbole alef\npremier cardinal transfini",
+	larr:"flèche vers la gauche",
+	uarr:"flèche vers le haut",
+	rarr:"flèche vers la droite",
+	darr:"flèche vers le bas",
+	harr:"flèche vers la gauche et la droite",
+	crarr:"flèche vers le bas avec coin vers la gauche\nretour chariot",
+	lArr:"flèche double vers la gauche",
+	uArr:"flèche double vers le haut",
+	rArr:"flèche double vers la droite",
+	dArr:"flèche double vers le bas",
+	hArr:"flèche double vers la gauche",
+	forall:"pour tous",
+	part:"différentiel partiel",
+	exist:"il existe",
+	empty:"ensemble vide\nensemble null\ndiamètre",
+	nabla:"nabla\ndifférence arrière",
+	isin:"élément de",
+	notin:"non élément de",
+	ni:"contient comme membre",
+	prod:"produit n-aire\nsigne produit",
+	sum:"somme n-aire",
+	minus:"signe moins",
+	lowast:"astérisque",
+	radic:"racine carrée\nsigne radical",
+	prop:"proportionnel à",
+	infin:"infinité",
+	ang:"angle",
+	and:"et logique\nwedge",
+	or:"ou logique\nvee",
+	cap:"intersection\ncap",
+	cup:"union\ncup","int":"intégrale",
+	there4:"donc",
+	sim:"tilde\nvarie en fonction de\nsimilaire à",
+	cong:"approximativement égal à",
+	asymp:"presque égal à\nasymptotique à",
+	ne:"différente de",
+	equiv:"identique à",
+	le:"inférieur ou égal à",
+	ge:"supérieur ou égal à",
+	sub:"sous-ensemble de",
+	sup:"sur-ensemble de",
+	nsub:"non sous-ensemble de",
+	sube:"sous-ensemble de ou égal à",
+	supe:"sur-ensemble de ou égal à",
+	oplus:"plus entouré\nsomme directe",
+	otimes:"signe multiplié entouré\nproduit vectoriel",
+	perp:"orthogonal à\nperpendiculaire",
+	sdot:"point",
+	lceil:"plafond à gauche\nmontant APL",
+	rceil:"plafond à droite",
+	lfloor:"plancher à gauche\ndescendant APL",
+	rfloor:"plancher à droite",
+	lang:"chevron vers la gauche",
+	rang:"chevron vers la droite",
+	loz:"losange",
+	spades:"pic noir",
+	clubs:"trèfle noir",
+	hearts:"coeur noir\nvalentine",
+	diams:"carreau noir",
+	OElig:"Latin - Ligature OE majuscule",
+	oelig:"Latin - Ligature oe minuscule",
+	Scaron:"Latin - S majuscule avec caron",
+	scaron:"Latin - s minuscule avec caron",
+	Yuml:"Latin - Y majuscule avec tréma",
+	circ:"accent circonflexe de lettre modificateur",
+	tilde:"petit tilde",
+	ensp:"espace demi-cadratin",
+	emsp:"espace cadratin",
+	thinsp:"espace fin",
+	zwnj:"antiliant sans chasse",
+	zwj:"liant sans chasse",
+	lrm:"marque de gauche à droite",
+	rlm:"marque de droite à gauche",
+	ndash:"tiret demi-cadratin",
+	mdash:"tiret cadratin",
+	lsquo:"guillemet simple ouvrant",
+	rsquo:"guillemet simple fermant",
+	sbquo:"guillemet simple fermant bas",
+	ldquo:"guillemet double gauche",
+	rdquo:"guillemet double droit",
+	bdquo:"guillemet double fermant bas",
+	dagger:"obèle",
+	Dagger:"double obèle",
+	permil:"signe pour-mille",
+	lsaquo:"guillemet simple orienté vers la gauche",
+	rsaquo:"guillemet simple orienté vers la droite",
+	euro:"signe euro"
+})
+
diff --git a/dojox/editor/plugins/nls/he/TableDialog.js b/dojox/editor/plugins/nls/he/TableDialog.js
index b2a2132..3a488c0 100644
--- a/dojox/editor/plugins/nls/he/TableDialog.js
+++ b/dojox/editor/plugins/nls/he/TableDialog.js
@@ -1 +1,29 @@
-({"buttonSet":"הגדרה","insertTableTitle":"הוספת טבלה","insertTableRowAfterLabel":"הוספת שורה אחרי","center":"מרכז","deleteTableColumnLabel":"מחיקת עמודה","right":"שמאל","insertTableColumnBeforeLabel":"הוספת עמודה לפני","tableWidth":"רוחב טבלה:","buttonInsert":"הוספה","default":"ברירת מחדל","align":"יישור:","insertTableRowBeforeLabel":"הוספת שורה לפני","cellSpacing":"ריווח תאים:","pixels":"פיקסלים","selectTableLabel":"בחירת טבלה","rows":"שורות:","modifyTableTitle":"שינוי טבלה","cellPaddin [...]
\ No newline at end of file
+({
+	insertTableTitle: "הוספת טבלה",
+	modifyTableTitle: "שינוי טבלה",
+	rows: "שורות:",
+	columns: "עמודות:",
+	align: "יישור:",
+	cellPadding: "ריפוד תאים:",
+	cellSpacing: "ריווח תאים:",
+	tableWidth: "רוחב טבלה:",
+	backgroundColor: "צבע רקע:",
+	borderColor: "צבע גבול:",
+	borderThickness: "עובי גבול",
+	percent: "אחוז",
+	pixels: "פיקסלים",
+	"default": "ברירת מחדל",
+	left: "ימין",
+	center: "מרכז",
+	right: "שמאל",
+	buttonSet: "הגדרה", // translated elsewhere?
+	buttonInsert: "הוספה",
+
+	selectTableLabel: "בחירת טבלה",
+	insertTableRowBeforeLabel: "הוספת שורה לפני",
+	insertTableRowAfterLabel: "הוספת שורה אחרי",
+	insertTableColumnBeforeLabel: "הוספת עמודה לפני",
+	insertTableColumnAfterLabel: "הוספת עמודה אחרי",
+	deleteTableRowLabel: "מחיקת שורה",
+	deleteTableColumnLabel: "מחיקת עמודה"
+})
diff --git a/dojox/editor/plugins/nls/hu/Breadcrumb.js b/dojox/editor/plugins/nls/hu/Breadcrumb.js
index 84ba939..4f80b8e 100644
--- a/dojox/editor/plugins/nls/hu/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/hu/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"Tartalom kiválasztása","deleteElement":"Elem törlése","moveEnd":"Kurzor mozgatása a végére","deleteContents":"Tartalom törlése","nodeActions":"${nodeName} műveletek","selectElement":"Elem kiválasztása","moveStart":"Kurzor mozgatása az elejére"})
\ No newline at end of file
+({
+	"nodeActions": "${nodeName} műveletek",
+	"selectContents": "Tartalom kiválasztása",
+	"selectElement": "Elem kiválasztása",
+	"deleteElement": "Elem törlése",
+	"deleteContents": "Tartalom törlése",
+	"moveStart": "Kurzor mozgatása az elejére",
+	"moveEnd": "Kurzor mozgatása a végére"
+})
+
diff --git a/dojox/editor/plugins/nls/hu/FindReplace.js b/dojox/editor/plugins/nls/hu/FindReplace.js
index fd05617..c5b879f 100644
--- a/dojox/editor/plugins/nls/hu/FindReplace.js
+++ b/dojox/editor/plugins/nls/hu/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"Visszafelé","findReplace":"Keresés/Csere váltása","replaceAll":"Minden előfordulás","replaceDialogText":"${0} előfordulás cseréje megtörtént. ","replaceButton":"Csere","findButton":"Keresés","findLabel":"Keresés: ","matchCase":"Kis- és nagybetűk egyeztetése","replaceLabel":"Csere: "})
\ No newline at end of file
+({
+	"findLabel": "Keresés: ",
+	"replaceLabel": "Csere: ",
+	"findReplace": "Keresés/Csere váltása",
+	"matchCase": "Kis- és nagybetűk egyeztetése", 
+	"backwards": "Visszafelé",
+	"replaceAll": "Minden előfordulás", 
+	"findButton": "Keresés",
+	"replaceButton": "Csere",
+	"replaceDialogText": "${0} előfordulás cseréje megtörtént. "
+})
+
diff --git a/dojox/editor/plugins/nls/hu/InsertEntity.js b/dojox/editor/plugins/nls/hu/InsertEntity.js
index 6640c05..51dddf1 100644
--- a/dojox/editor/plugins/nls/hu/InsertEntity.js
+++ b/dojox/editor/plugins/nls/hu/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"Szimbólum beszúrása"})
\ No newline at end of file
+({
+	insertEntity: "Szimbólum beszúrása"
+})
+
diff --git a/dojox/editor/plugins/nls/hu/PageBreak.js b/dojox/editor/plugins/nls/hu/PageBreak.js
index 5b9cd97..5536e17 100644
--- a/dojox/editor/plugins/nls/hu/PageBreak.js
+++ b/dojox/editor/plugins/nls/hu/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"Oldaltörés"})
\ No newline at end of file
+({
+	"pageBreak": "Oldaltörés"
+})
+
diff --git a/dojox/editor/plugins/nls/hu/Preview.js b/dojox/editor/plugins/nls/hu/Preview.js
index 44233d5..4053ccb 100644
--- a/dojox/editor/plugins/nls/hu/Preview.js
+++ b/dojox/editor/plugins/nls/hu/Preview.js
@@ -1 +1,4 @@
-({"preview":"Előzetes"})
\ No newline at end of file
+({
+	"preview": "Előzetes"
+})
+
diff --git a/dojox/editor/plugins/nls/hu/Save.js b/dojox/editor/plugins/nls/hu/Save.js
index be39803..8d05ac5 100644
--- a/dojox/editor/plugins/nls/hu/Save.js
+++ b/dojox/editor/plugins/nls/hu/Save.js
@@ -1 +1,4 @@
-({"save":"Mentés"})
\ No newline at end of file
+({
+	"save": "Mentés"
+})
+
diff --git a/dojox/editor/plugins/nls/hu/ShowBlockNodes.js b/dojox/editor/plugins/nls/hu/ShowBlockNodes.js
index 16927f5..10d4d96 100644
--- a/dojox/editor/plugins/nls/hu/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/hu/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"HTML blokk elemek megjelenítése"})
\ No newline at end of file
+({
+	"showBlockNodes": "HTML blokk elemek megjelenítése"
+})
+
diff --git a/dojox/editor/plugins/nls/hu/Smiley.js b/dojox/editor/plugins/nls/hu/Smiley.js
index 6216584..ff80909 100644
--- a/dojox/editor/plugins/nls/hu/Smiley.js
+++ b/dojox/editor/plugins/nls/hu/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"nevetés","emoticonCool":"laza","emoticonTongue":"nyelv","emoticonCrying":"sírás","emoticonOops":"hoppá","emoticonFrown":"rosszallás","emoticonAngry":"mérges","emoticonShy":"szégyenlős","emoticonNo":"nem","emoticonAngel":"angyal","smiley":"Hangulatjel beszúrása","emoticonIdea":"ötlet","emoticonEyebrow":"szemöldök","emoticonSmile":"mosoly","emoticonWink":"kacsintás","emoticonYes":"igen","emoticonGrin":"vigyor","emoticonGoofy":"ostoba","emoticonHalf":"fél"})
\ No newline at end of file
+({
+	smiley: "Hangulatjel beszúrása",
+	emoticonSmile: "mosoly",
+	emoticonLaughing: "nevetés",
+	emoticonWink: "kacsintás",
+	emoticonGrin: "vigyor",
+	emoticonCool: "laza",
+	emoticonAngry: "mérges",  
+	emoticonHalf: "fél", 
+	emoticonEyebrow: "szemöldök",
+	emoticonFrown: "rosszallás",
+	emoticonShy: "szégyenlős",
+	emoticonGoofy: "ostoba",
+	emoticonOops: "hoppá",
+	emoticonTongue: "nyelv",
+	emoticonIdea: "ötlet",
+	emoticonYes: "igen",
+	emoticonNo: "nem",	
+	emoticonAngel: "angyal",
+	emoticonCrying: "sírás"
+})
+
diff --git a/dojox/editor/plugins/nls/hu/TableDialog.js b/dojox/editor/plugins/nls/hu/TableDialog.js
index 5a815f4..61078c1 100644
--- a/dojox/editor/plugins/nls/hu/TableDialog.js
+++ b/dojox/editor/plugins/nls/hu/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Beállítás","insertTableTitle":"Táblázat beszúrása","insertTableRowAfterLabel":"Sor hozzáadása utána","center":"középre","deleteTableColumnLabel":"Oszlop törlése","right":"jobbra","insertTableColumnBeforeLabel":"Oszlop hozzáadása előtte","tableWidth":"Táblázat szélessége: ","buttonInsert":"Beszúrás","default":"alapértelmezett","align":"Igazítás: ","insertTableRowBeforeLabel":"Sor hozzáadása előtte","cellSpacing":"Cella térköz: ","pixels":"képpont","selectTableLabel":"Tábláz [...]
\ No newline at end of file
+({
+	insertTableTitle: "Táblázat beszúrása",
+	modifyTableTitle: "Táblázat módosítása",
+	rows: "Sorok: ",
+	columns: "Oszlopok: ",
+	align: "Igazítás: ",
+	cellPadding: "Cellakitöltés: ",
+	cellSpacing: "Cella térköz: ",
+	tableWidth: "Táblázat szélessége: ",
+	backgroundColor: "Háttérszín: ",
+	borderColor: "Szegélyszín: ",
+	borderThickness: "Szegély vastagsága ",
+	percent: "százalék",
+	pixels: "képpont",
+	"default": "alapértelmezett",
+	left: "balra",
+	center: "középre",
+	right: "jobbra",
+	buttonSet: "Beállítás", // translated elsewhere?
+	buttonInsert: "Beszúrás",
+
+	selectTableLabel: "Táblázat kijelölése",
+	insertTableRowBeforeLabel: "Sor hozzáadása előtte",
+	insertTableRowAfterLabel: "Sor hozzáadása utána",
+	insertTableColumnBeforeLabel: "Oszlop hozzáadása előtte",
+	insertTableColumnAfterLabel: "Oszlop hozzáadása utána",
+	deleteTableRowLabel: "Sor törlése ",
+	deleteTableColumnLabel: "Oszlop törlése"
+})
+
diff --git a/dojox/editor/plugins/nls/hu/latinEntities.js b/dojox/editor/plugins/nls/hu/latinEntities.js
index 6d98833..5e40ef7 100644
--- a/dojox/editor/plugins/nls/hu/latinEntities.js
+++ b/dojox/editor/plugins/nls/hu/latinEntities.js
@@ -1 +1,257 @@
-({"le":"kisebb vagy egyenlő","prod":"n-tagú Descartes szorzat\nszorzatjel","zwj":"nem törhető üres jel","mdash":"m kötőjel","frasl":"tört osztásjel","upsih":"Görög üpszilon horog szimbólummal ","prop":"arányos ","middot":"középső pont\nGregorián vessző\nGörög középső pont","hellip":"vízszintes hármaspont\nbevezető hármas pont","eta":"Görög kis éta betű","iacute":"Latin kis i betű éles ékezettel","yen":"jen jel\nyuan jel","rlm":"jobbról balra jel","macr":"föléhúzás jel\nAPL felülhúzás","l [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"fordított felkiáltójel",
+	cent:"cent jel",
+	pound:"font jel",
+	curren:"pénznem jel",
+	yen:"jen jel\nyuan jel",
+	brvbar:"megszakított vonal\nmegszakított függőleges vonal",
+	sect:"paragrafusjel",
+	uml:"dupla ékezet\numlaut",
+	copy:"copyright jel",
+	ordf:"nőnemű sorszámnév jelzése a felső indexben",
+	laquo:"balra mutató dupla hegyes idézőjel\nbalra mutató belső idézőjel ",
+	not:"nem jel",
+	shy:"lágy kötőjel\nfeltételes kötőjel",
+	reg:"védjegy jel\nbejegyzett védjegy jel",
+	macr:"föléhúzás jel\nAPL felülhúzás",
+	deg:"fok jel",
+	plusmn:"plus-mínusz jel\nplusz-vagy-mínusz jel",
+	sup2:"2 felső indexben\nfelső indexbe írt kettes számjegy\nnégyzetre emelés",
+	sup3:"3 felső indexben\nfelső indexbe írt hármas számjegy\nköbre emelés",
+	acute:"hegyes ékezet\nkalapos ékezet",
+	micro:"mikro jel",
+	para:"sorvége jel\nbekezdés jel",
+	middot:"középső pont\nGregorián vessző\nGörög középső pont",
+	cedil:"cedill\nbalra hajló alsó hurok",
+	sup1:"1 a felső indexben\nfelső indexbe írt egyes számjegy",
+	ordm:"hímnemű sorszámnév jelzése a felső indexben",
+	raquo:"jobbra mutató dupla hegyes idézőjel\njobbra mutató belső idézőjel",
+	frac14:"közönséges egynegyed tört\nnegyed",
+	frac12:"közönséges fél tört\nfél",
+	frac34:"közönséges háromnegyed tört\nháromnegyed",
+	iquest:"fordított kérdőjel\nmegfordított kérdőjel",
+	Agrave:"Latin nagy A betű tompa ékezettel\nTompa ékezetes latin nagy A betű",
+	Aacute:"Latin nagy A betű éles ékezettel",
+	Acirc:"Latin kalapos nagy A betű ",
+	Atilde:"Latin hullámvonalas nagy A betű",
+	Auml:"Latin kétpontos nagy A betű",
+	Aring:"Latin nagy A betű felül körrel\nLatin nagy A betű felső körrel",
+	AElig:"Latin nagy AE\nLatin nagy AE ikerbetű  ",
+	Ccedil:"Latin nagy C betű cedillel ",
+	Egrave:"Latin nagy E betű tompa ékezettel",
+	Eacute:"Latin nagy E betű éles ékezettel",
+	Ecirc:"Latin kalapos nagy E betű ",
+	Euml:"Latin kétpontos nagy E betű",
+	Igrave:"Latin nagy I betű tompa ékezettel",
+	Iacute:"Latin nagy I betű éles ékezettel",
+	Icirc:"Latin kalapos nagy I betű ",
+	Iuml:"Latin kétpontos nagy I betű",
+	ETH:"Latin nagy ETH betű ",
+	Ntilde:"Latin hullámvonalas nagy N betű",
+	Ograve:"Latin nagy O betű tompa ékezettel",
+	Oacute:"Latin nagy O betű éles ékezettel",
+	Ocirc:"Latin kalapos nagy O betű ",
+	Otilde:"Latin hullámvonalas nagy O betű",
+	Ouml:"Latin kétpontos nagy O betű",
+	times:"szorzásjel",
+	Oslash:"Latin áthúzott nagy O betű\nLatin nagy O betű osztásjellel",
+	Ugrave:"Latin nagy U betű tompa ékezettel",
+	Uacute:"Latin nagy U betű éles ékezettel",
+	Ucirc:"Latin kalapos nagy U betű ",
+	Uuml:"Latin kétpontos nagy U betű",
+	Yacute:"Latin nagy Y betű éles ékezettel",
+	THORN:"Latin nagy THORN betű  ",
+	szlig:"Latin kis sharfes s\neszett",
+	agrave:"Latin kis a betű tompa ékezettel\nTompa ékezetes latin kis a betű",
+	aacute:"Latin kis a betű éles ékezettel",
+	acirc:"Latin kalapos kis a betű ",
+	atilde:"Latin hullámvonalas kis a betű",
+	auml:"Latin kétpontos kis a betű",
+	aring:"Latin kis a betű felül körrel\nLatin kis a betű felső körrel",
+	aelig:"Latin kis ae betű\nLatin kis ae ikerbetű  ",
+	ccedil:"Latin kis c betű cedillel ",
+	egrave:"Latin kis e betű tompa ékezettel",
+	eacute:"Latin kis e betű éles ékezettel",
+	ecirc:"Latin kalapos kis e betű ",
+	euml:"Latin kétpontos kis e betű",
+	igrave:"Latin kis i betű tompa ékezettel",
+	iacute:"Latin kis i betű éles ékezettel",
+	icirc:"Latin kalapos kis i betű ",
+	iuml:"Latin kétpontos kis i betű",
+	eth:"Latin kis eth betű ",
+	ntilde:"Latin hullámvonalas kis n betű",
+	ograve:"Latin kis o betű tompa ékezettel",
+	oacute:"Latin kis o betű éles ékezettel",
+	ocirc:"Latin kalapos kis o betű ",
+	otilde:"Latin hullámvonalas kis o betű",
+	ouml:"Latin kétpontos kis o betű",
+	divide:"osztásjel ",
+	oslash:"Latin áthúzott kis o betű\nLatin kis o betű osztásjellel",
+	ugrave:"Latin kis u betű tompa ékezettel",
+	uacute:"Latin kis u betű éles ékezettel",
+	ucirc:"Latin kalapos kis u betű ",
+	uuml:"Latin kétpontos kis u betű",
+	yacute:"Latin kis y éles ékezettel",
+	thorn:"Latin kis thorn betű ",
+	yuml:"Latin kétpontos kis y ",
+
+// Greek Characters and Symbols
+	fnof:"Latin kis f horoggal\nfüggvény\nforint",
+	Alpha:"Görög nagy alfa betű",
+	Beta:"Görög nagy béta betű ",
+	Gamma:"Görög nagy gamma betű",
+	Delta:"Görög nagy delta betű ",
+	Epsilon:"Görög nagy epszilon betű",
+	Zeta:"Görög nagy dzéta betű ",
+	Eta:"Görög nagy éta betű ",
+	Theta:"Görög nagy théta betű ",
+	Iota:"Görög nagy iota betű ",
+	Kappa:"Görög nagy kappa betű ",
+	Lambda:"Görög nagy lambda betű ",
+	Mu:"Görög nagy mű betű ",
+	Nu:"Görög nagy nű betű ",
+	Xi:"Görög nagy kszí betű ",
+	Omicron:"Görög nagy omikron betű ",
+	Pi:"Görög nagy pi betű ",
+	Rho:"Görög nagy ró betű ",
+	Sigma:"Görög nagy szigma betű ",
+	Tau:"Görög nagy tau betű ",
+	Upsilon:"Görög nagy üpszilon betű ",
+	Phi:"Görög nagy fí betű ",
+	Chi:"Görög nagy khí betű ",
+	Psi:"Görög nagy pszí betű ",
+	Omega:"Görög nagy ómega betű ",
+	alpha:"Görög kis alfa betű",
+	beta:"Görög kis béta betű ",
+	gamma:"Görög kis gamma betű",
+	delta:"Görög kis delta betű ",
+	epsilon:"Görög kis epszilon betű",
+	zeta:"Görög kis dzéta betű ",
+	eta:"Görög kis éta betű",
+	theta:"Görög kis théta betű ",
+	iota:"Görög kis ióta betű ",
+	kappa:"Görög kis kappa betű ",
+	lambda:"Görög kis lambda betű ",
+	mu:"Görög kis mű betű ",
+	nu:"Görög kis nű betű ",
+	xi:"Görög kis kszí betű ",
+	omicron:"Görög kis omikron betű ",
+	pi:"Görög kis pí betű ",
+	rho:"Görög kis ró betű ",
+	sigmaf:"Görög kis szigma betű utolsó helyen",
+	sigma:"Görög kis szigma betű  ",
+	tau:"Görög kis taú betű ",
+	upsilon:"Görög kis üpszilon betű ",
+	phi:"Görög kis fí betű ",
+	chi:"Görög kis khí betű ",
+	psi:"Görög kis pszí betű ",
+	omega:"Görög kis ómega betű ",
+	thetasym:"Görög kis théta betű szimbólum ",
+	upsih:"Görög üpszilon horog szimbólummal ",
+	piv:"Görög pí szimbólum ",
+	bull:"pont felsorolásjel\nkis fekete kör",
+	hellip:"vízszintes hármaspont\nbevezető hármas pont",
+	prime:"szimpla egyenes idézőjel\nperc\nláb",
+	Prime:"dupla egyenes idézőjel\nmásodperc\nhüvelyk",
+	oline:"felső vonal\nfelülvonás",
+	frasl:"tört osztásjel",
+	weierp:"írott nagy P\nhatványhalmaz\nWeierstrass p",
+	image:"megtört nagy I\nképzetes (imaginárius) rész",
+	real:"megtört nagy R\nvalós rész szimbólum",
+	trade:"védjegy jel",
+	alefsym:"alef szimbólum\nelső transzfinit pozitív egész szám",
+	larr:"balra mutató nyíl",
+	uarr:"felfelé mutató nyíl",
+	rarr:"jobbra mutató nyíl",
+	darr:"lefelé mutató nyíl",
+	harr:"balra-jobbra mutató nyíl",
+	crarr:"lefelé mutató nyíl bal oldalon sarokkal\nsoremelés",
+	lArr:"balra mutató dupla nyíl",
+	uArr:"felfelé mutató dupla nyíl",
+	rArr:"jobbra mutató dupla nyíl ",
+	dArr:"lefelé mutató dupla nyíl",
+	hArr:"balra-jobbra mutató dupla nyíl",
+	forall:"minden\nfordított nagy A betű",
+	part:"részleges differenciál",
+	exist:"létezik",
+	empty:"üres halmaz\nnull halmaz\nátmérő",
+	nabla:"nabla\nfordított különbség",
+	isin:"eleme ",
+	notin:"nem eleme ",
+	ni:"tagként tartalmazza ",
+	prod:"n-tagú Descartes szorzat\nszorzatjel",
+	sum:"n-tagú összegzés",
+	minus:"mínusz jel",
+	lowast:"csillag operátor",
+	radic:"négyzetgyök\nnégyzetgyök jel",
+	prop:"arányos ",
+	infin:"végtelen",
+	ang:"szög",
+	and:"logikai és\nék",
+	or:"logikai vagy\nv-alak",
+	cap:"metszet",
+	cup:"unió","int":"integrál",
+	there4:"ezért",
+	sim:"hullám operátor\nváltakozik\nhasonló",
+	cong:"megközelítőleg egyenlő",
+	asymp:"majdnem egyenlő\naszimptotikus",
+	ne:"nem egyenlő",
+	equiv:"azonos",
+	le:"kisebb vagy egyenlő",
+	ge:"nagyobb vagy egyenlő",
+	sub:"részhalmaza",
+	sup:"bővített halmaza ",
+	nsub:"nem részhalmaza",
+	sube:"részhalmaza vagy egyenlő",
+	supe:"bővített halmaza vagy egyenlő",
+	oplus:"bekarikázott plusz jel\nközvetlen összeg",
+	otimes:"bekarikázott x\nvektor szorzat",
+	perp:"merőleges\nortogonális",
+	sdot:"pont operátor",
+	lceil:"bal szögletes zárójel felső sarok\nAPL felső keret",
+	rceil:"jobb szögletes zárójel felső sarok",
+	lfloor:"bal szögletes zárójel alsó sarok\nAPL alsó keret",
+	rfloor:"jobb szögletes zárójel alsó sarok",
+	lang:"balra mutató hegyes zárójel",
+	rang:"jobbra mutató hegyes zárójel",
+	loz:"rombusz",
+	spades:"fekete pikk kártyajel ",
+	clubs:"fekete treff kártyjel\nlóhere",
+	hearts:"fekete kör kártyajel\nszívalak",
+	diams:"fekete káró káryajel",
+	OElig:"Latin nagy OE ikerbetű ",
+	oelig:"Latin kis oe ikerbetű ",
+	Scaron:"Latin nagy S betű csónakkal",
+	scaron:"Latin kis s betű csónakkal",
+	Yuml:"Latin kétpontos nagy Y betű ",
+	circ:"betűt módosító kalap ékezet",
+	tilde:"kis hullám",
+	ensp:"n szóköz",
+	emsp:"m szóköz",
+	thinsp:"szűk szóköz",
+	zwnj:"törhető üres jel",
+	zwj:"nem törhető üres jel",
+	lrm:"balról jobbra jel",
+	rlm:"jobbról balra jel",
+	ndash:"n kötőjel",
+	mdash:"m kötőjel",
+	lsquo:"bal szimpla idézőjel",
+	rsquo:"jobb szimpla idézőjel",
+	sbquo:"alsó 9-es szimpla idézőjel",
+	ldquo:"bal dupla idézőjel",
+	rdquo:"jobb dupla idézőjel",
+	bdquo:"alsó 9-es dupla idézőjel",
+	dagger:"kereszt",
+	Dagger:"dupla kereszt ",
+	permil:"ezrelékjel",
+	lsaquo:"szimpla balra mutató hegyes idézőjel",
+	rsaquo:"szimpla jobbra mutató hegyes idézőjel",
+	euro:"euro jel"
+})
+
diff --git a/dojox/editor/plugins/nls/it/Breadcrumb.js b/dojox/editor/plugins/nls/it/Breadcrumb.js
index 55377a2..964b81d 100644
--- a/dojox/editor/plugins/nls/it/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/it/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"Seleziona contenuto","deleteElement":"Elimina elemento","moveEnd":"Sposta il cursore per terminare","deleteContents":"Elimina contenuto","nodeActions":"Azioni ${nodeName}","selectElement":"Seleziona elemento","moveStart":"Sposta il cursore per iniziare"})
\ No newline at end of file
+({
+	"nodeActions": "Azioni ${nodeName}",
+	"selectContents": "Seleziona contenuto",
+	"selectElement": "Seleziona elemento",
+	"deleteElement": "Elimina elemento",
+	"deleteContents": "Elimina contenuto",
+	"moveStart": "Sposta il cursore per iniziare",
+	"moveEnd": "Sposta il cursore per terminare"
+})
+
diff --git a/dojox/editor/plugins/nls/it/FindReplace.js b/dojox/editor/plugins/nls/it/FindReplace.js
index 0910053..29f5a5e 100644
--- a/dojox/editor/plugins/nls/it/FindReplace.js
+++ b/dojox/editor/plugins/nls/it/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"Indietro","findReplace":"Mostra/Nascondi Trova/Sostituisci","replaceAll":"Tutte le occorrenze","replaceDialogText":"Occorrenze sostituite: ${0}.","replaceButton":"Sostituisci","findButton":"Trova","findLabel":"Trova:","matchCase":"Maiuscole/minuscole","replaceLabel":"Sostituisci con:"})
\ No newline at end of file
+({
+	"findLabel": "Trova:",
+	"replaceLabel": "Sostituisci con:",
+	"findReplace": "Mostra/Nascondi Trova/Sostituisci",
+	"matchCase": "Maiuscole/minuscole", 
+	"backwards": "Indietro",
+	"replaceAll": "Tutte le occorrenze", 
+	"findButton": "Trova",
+	"replaceButton": "Sostituisci",
+	"replaceDialogText": "Occorrenze sostituite: ${0}."
+})
+
diff --git a/dojox/editor/plugins/nls/it/InsertEntity.js b/dojox/editor/plugins/nls/it/InsertEntity.js
index 9e62180..838342b 100644
--- a/dojox/editor/plugins/nls/it/InsertEntity.js
+++ b/dojox/editor/plugins/nls/it/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"Inserisci simbolo"})
\ No newline at end of file
+({
+	insertEntity: "Inserisci simbolo"
+})
+
diff --git a/dojox/editor/plugins/nls/it/PageBreak.js b/dojox/editor/plugins/nls/it/PageBreak.js
index 3b526b0..8ffbce3 100644
--- a/dojox/editor/plugins/nls/it/PageBreak.js
+++ b/dojox/editor/plugins/nls/it/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"Interruzione di pagina"})
\ No newline at end of file
+({
+	"pageBreak": "Interruzione di pagina"
+})
+
diff --git a/dojox/editor/plugins/nls/it/Preview.js b/dojox/editor/plugins/nls/it/Preview.js
index d272803..74543b1 100644
--- a/dojox/editor/plugins/nls/it/Preview.js
+++ b/dojox/editor/plugins/nls/it/Preview.js
@@ -1 +1,4 @@
-({"preview":"Anteprima"})
\ No newline at end of file
+({
+	"preview": "Anteprima"
+})
+
diff --git a/dojox/editor/plugins/nls/it/Save.js b/dojox/editor/plugins/nls/it/Save.js
index 5e07c1c..4a1b9aa 100644
--- a/dojox/editor/plugins/nls/it/Save.js
+++ b/dojox/editor/plugins/nls/it/Save.js
@@ -1 +1,4 @@
-({"save":"Salva"})
\ No newline at end of file
+({
+	"save": "Salva"
+})
+
diff --git a/dojox/editor/plugins/nls/it/ShowBlockNodes.js b/dojox/editor/plugins/nls/it/ShowBlockNodes.js
index 58c41fa..5ada271 100644
--- a/dojox/editor/plugins/nls/it/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/it/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"Mostra elementi blocco HTML"})
\ No newline at end of file
+({
+	"showBlockNodes": "Mostra elementi blocco HTML"
+})
+
diff --git a/dojox/editor/plugins/nls/it/Smiley.js b/dojox/editor/plugins/nls/it/Smiley.js
index 625cb58..0e9b446 100644
--- a/dojox/editor/plugins/nls/it/Smiley.js
+++ b/dojox/editor/plugins/nls/it/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"risata","emoticonCool":"figo","emoticonTongue":"linguaccia","emoticonCrying":"in lacrime","emoticonOops":"ops","emoticonFrown":"triste","emoticonAngry":"arrabbiato","emoticonShy":"timido","emoticonNo":"no","emoticonAngel":"angelo","smiley":"Inserisci emoticon","emoticonIdea":"idea","emoticonEyebrow":"sopracciglia","emoticonSmile":"sorriso","emoticonWink":"occhiolino","emoticonYes":"yes","emoticonGrin":"ghigno","emoticonGoofy":"sciocco","emoticonHalf":"metà"})
\ No newline at end of file
+({
+	smiley: "Inserisci emoticon",
+	emoticonSmile: "sorriso",
+	emoticonLaughing: "risata",
+	emoticonWink: "occhiolino",
+	emoticonGrin: "ghigno",
+	emoticonCool: "figo",
+	emoticonAngry: "arrabbiato",  
+	emoticonHalf: "metà", 
+	emoticonEyebrow: "sopracciglia",
+	emoticonFrown: "triste",
+	emoticonShy: "timido",
+	emoticonGoofy: "sciocco",
+	emoticonOops: "ops",
+	emoticonTongue: "linguaccia",
+	emoticonIdea: "idea",
+	emoticonYes: "yes",
+	emoticonNo: "no",	
+	emoticonAngel: "angelo",
+	emoticonCrying: "in lacrime"
+})
+
diff --git a/dojox/editor/plugins/nls/it/TableDialog.js b/dojox/editor/plugins/nls/it/TableDialog.js
index 88d9f52..8fafa9e 100644
--- a/dojox/editor/plugins/nls/it/TableDialog.js
+++ b/dojox/editor/plugins/nls/it/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Imposta","insertTableTitle":"Inserisci tabella","insertTableRowAfterLabel":"Inserisci riga dopo","center":"centro","deleteTableColumnLabel":"Elimina colonna","right":"destra","insertTableColumnBeforeLabel":"Aggiungi colonna prima","tableWidth":"Larghezza tabella:","buttonInsert":"Inserisci","default":"predefinito","align":"Allinea:","insertTableRowBeforeLabel":"Inserisci riga prima","cellSpacing":"Spaziatura celle:","pixels":"pixel","selectTableLabel":"Seleziona tabella"," [...]
\ No newline at end of file
+({
+	insertTableTitle: "Inserisci tabella",
+	modifyTableTitle: "Modifica tabella",
+	rows: "Righe:",
+	columns: "Colonne:",
+	align: "Allinea:",
+	cellPadding: "Riempimento cella:",
+	cellSpacing: "Spaziatura celle:",
+	tableWidth: "Larghezza tabella:",
+	backgroundColor: "Colore sfondo:",
+	borderColor: "Colore bordo:",
+	borderThickness: "Spessore bordo",
+	percent: "percento",
+	pixels: "pixel",
+	"default": "predefinito",
+	left: "sinistra",
+	center: "centro",
+	right: "destra",
+	buttonSet: "Imposta", // translated elsewhere?
+	buttonInsert: "Inserisci",
+
+	selectTableLabel: "Seleziona tabella",
+	insertTableRowBeforeLabel: "Inserisci riga prima",
+	insertTableRowAfterLabel: "Inserisci riga dopo",
+	insertTableColumnBeforeLabel: "Aggiungi colonna prima",
+	insertTableColumnAfterLabel: "Aggiungi colonna dopo",
+	deleteTableRowLabel: "Elimina riga",
+	deleteTableColumnLabel: "Elimina colonna"
+})
+
diff --git a/dojox/editor/plugins/nls/it/latinEntities.js b/dojox/editor/plugins/nls/it/latinEntities.js
index 34a2a1e..7bd05bf 100644
--- a/dojox/editor/plugins/nls/it/latinEntities.js
+++ b/dojox/editor/plugins/nls/it/latinEntities.js
@@ -1 +1,257 @@
-({"le":"minore di o uguale a","prod":"prodotto n-ario\nsegno di prodotto","zwj":"congiuntore di larghezza zero","mdash":"trattino em","frasl":"barra obliqua di frazione","upsih":"simbolo della upsilon greca con uncino","prop":"proporzionale a","middot":"punto in mezzo\nvirgola georgiana\npunto centrale greco","hellip":"puntini di sospensione\ntre puntini di guida","eta":"lettera greca minuscola eta","iacute":"lettera latina i minuscola con accento acuto","yen":"simbolo dello yen\nsimbolo [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"punto esclamativo capovolto",
+	cent:"simbolo del centesimo",
+	pound:"simbolo della sterlina",
+	curren:"simbolo di valuta",
+	yen:"simbolo dello yen\nsimbolo dello yuan",
+	brvbar:"barra interrotta\nbarra verticale interrotta",
+	sect:"simbolo di sezione",
+	uml:"dieresi\ndieresi con spazio",
+	copy:"simbolo del copyright",
+	ordf:"indicatore ordinale femminile",
+	laquo:"virgolette doppie angolari indicanti a sinistra\nguillemet indicante a sinistra",
+	not:"simbolo di negazione",
+	shy:"trattino debole\ntrattino discrezionale",
+	reg:"simbolo di registrazione\nsimbolo di marchio registrato",
+	macr:"macron\nmacron con spaziatura\nlinea orizzontale superiore\nbarra sovrapposta APL",
+	deg:"simbolo dei gradi",
+	plusmn:"segno più-meno\nsegno più o meno",
+	sup2:"esponente due\nnumero due in esponente\nal quadrato",
+	sup3:"esponente tre\nnumero tre in esponente\nal cubo",
+	acute:"accento acuto\nacuto con spaziatura",
+	micro:"simbolo di micro",
+	para:"simbolo pilcrow\nsimbolo di paragrafo",
+	middot:"punto in mezzo\nvirgola georgiana\npunto centrale greco",
+	cedil:"cediglia\ncediglia con spazio",
+	sup1:"esponente uno\nnumero uno in esponente",
+	ordm:"indicatore ordinale maschile",
+	raquo:"virgolette doppie angolari indicanti a destra\n guillemet indicante a destra",
+	frac14:"frazione semplice un quarto\nfrazione un quarto",
+	frac12:"frazione semplice un mezzo\nfrazione un mezzo",
+	frac34:"frazione semplice tre quarti\nfrazione tre quarti",
+	iquest:"punto interrogativo invertito\npunto interrogativo rovesciato",
+	Agrave:"lettera latina A maiuscola con accento grave\nlettera latina A maiuscola grave",
+	Aacute:"lettera latina A maiuscola con accento acuto",
+	Acirc:"lettera latina A maiuscola con accento circonflesso",
+	Atilde:"lettera latina A maiuscola con tilde",
+	Auml:"lettera latina A maiuscola con dieresi",
+	Aring:"lettera latina A maiuscola con sormontata da anello\nlettera latina A maiuscola anellata",
+	AElig:"lettera latina AE maiuscola\nlegatura latina maiuscola AE",
+	Ccedil:"lettera latina C maiuscola con cediglia",
+	Egrave:"lettera latina E maiuscola con accento grave",
+	Eacute:"lettera latina E maiuscola con accento acuto",
+	Ecirc:"lettera latina E maiuscola con accento circonflesso",
+	Euml:"lettera latina E maiuscola con dieresi",
+	Igrave:"lettera latina I maiuscola con accento grave",
+	Iacute:"lettera latina I maiuscola con accento acuto",
+	Icirc:"lettera latina I maiuscola con accento circonflesso",
+	Iuml:"lettera latina I maiuscola con dieresi",
+	ETH:"lettera latina ETH maiuscola",
+	Ntilde:"lettera latina N maiuscola con tilde",
+	Ograve:"lettera latina O maiuscola con accento grave",
+	Oacute:"lettera latina O maiuscola con accento acuto",
+	Ocirc:"lettera latina O maiuscola con accento circonflesso",
+	Otilde:"lettera latina O maiuscola con tilde",
+	Ouml:"lettera latina O maiuscola con dieresi",
+	times:"segno di moltiplicazione",
+	Oslash:"lettera latina O maiuscola con barra obliqua\nlettera latina O maiuscola barrata",
+	Ugrave:"lettera latina U maiuscola con accento grave",
+	Uacute:"lettera latina U maiuscola con accento acuto",
+	Ucirc:"lettera latina U maiuscola con accento circonflesso",
+	Uuml:"lettera latina U maiuscola con dieresi",
+	Yacute:"lettera latina Y maiuscola con accento acuto",
+	THORN:"lettera latina THORN maiuscola",
+	szlig:"lettera latina s minuscola sonora\nesse-zeta",
+	agrave:"lettera latina a minuscola con accento grave\nlettera latina a minuscola grave",
+	aacute:"lettera latina a minuscola con accento acuto",
+	acirc:"lettera latina a minuscola con accento circonflesso",
+	atilde:"lettera latina a minuscola con tilde",
+	auml:"lettera latina a minuscola con dieresi",
+	aring:"lettera latina a minuscola sormontata da anello\nlettera latina a minuscola anellata",
+	aelig:"lettera latina ae minuscola\nlegatura latina minuscola ae",
+	ccedil:"lettera latina c minuscola con cediglia",
+	egrave:"lettera latina e minuscola con accento grave",
+	eacute:"lettera latina e minuscola con accento acuto",
+	ecirc:"lettera latina e minuscola con accento circonflesso",
+	euml:"lettera latina e minuscola con dieresi",
+	igrave:"lettera latina i minuscola con accento grave",
+	iacute:"lettera latina i minuscola con accento acuto",
+	icirc:"lettera latina i minuscola con accento circonflesso",
+	iuml:"lettera latina i minuscola con dieresi",
+	eth:"lettera latina eth minuscola",
+	ntilde:"lettera latina n minuscola con tilde",
+	ograve:"lettera latina o minuscola con accento grave",
+	oacute:"lettera latina o minuscola con accento acuto",
+	ocirc:"lettera latina o minuscola con accento circonflesso",
+	otilde:"lettera latina o minuscola con tilde",
+	ouml:"lettera latina o minuscola con dieresi",
+	divide:"segno di divisione",
+	oslash:"lettera latina o minuscola con barra obliqua\nlettera latina o minuscola barrata",
+	ugrave:"lettera latina u minuscola con accento grave",
+	uacute:"lettera latina u minuscola con accento acuto",
+	ucirc:"lettera latina u minuscola con accento circonflesso",
+	uuml:"lettera latina u minuscola con dieresi",
+	yacute:"lettera latina y minuscola con accento acuto",
+	thorn:"lettera latina thorn minuscola",
+	yuml:"lettera latina y minuscola con dieresi",
+
+// Greek Characters and Symbols
+	fnof:"f latina minuscola con uncino\nfunzione\nfiorino",
+	Alpha:"lettera greca maiuscola alpha",
+	Beta:"lettera greca maiuscola beta",
+	Gamma:"lettera greca maiuscola gamma",
+	Delta:"lettera greca maiuscola delta",
+	Epsilon:"lettera greca maiuscola epsilon",
+	Zeta:"lettera greca maiuscola zeta",
+	Eta:"lettera greca maiuscola eta",
+	Theta:"lettera greca maiuscola theta",
+	Iota:"lettera greca maiuscola iota",
+	Kappa:"lettera greca maiuscola kappa",
+	Lambda:"lettera greca maiuscola lambda",
+	Mu:"lettera greca maiuscola mu",
+	Nu:"lettera greca maiuscola nu",
+	Xi:"lettera greca maiuscola xi",
+	Omicron:"lettera greca maiuscola omicron",
+	Pi:"lettera greca maiuscola pi",
+	Rho:"lettera greca maiuscola rho",
+	Sigma:"lettera greca maiuscola sigma",
+	Tau:"lettera greca maiuscola tau",
+	Upsilon:"lettera greca maiuscola upsilon",
+	Phi:"lettera greca maiuscola phi",
+	Chi:"lettera greca maiuscola chi",
+	Psi:"lettera greca maiuscola psi",
+	Omega:"lettera greca maiuscola omega",
+	alpha:"lettera greca maiuscola alpha",
+	beta:"lettera greca minuscola beta",
+	gamma:"lettera greca minuscola gamma",
+	delta:"lettera greca minuscola delta",
+	epsilon:"lettera greca minuscola epsilon",
+	zeta:"lettera greca minuscola zeta",
+	eta:"lettera greca minuscola eta",
+	theta:"lettera greca minuscola theta",
+	iota:"lettera greca minuscola iota",
+	kappa:"lettera greca minuscola kappa",
+	lambda:"lettera greca minuscola lambda",
+	mu:"lettera greca minuscola mu",
+	nu:"lettera greca minuscola nu",
+	xi:"lettera greca minuscola xi",
+	omicron:"lettera greca minuscola omicron",
+	pi:"lettera greca minuscola pi",
+	rho:"lettera greca minuscola rho",
+	sigmaf:"lettera greca minuscola sigma finale",
+	sigma:"lettera greca minuscola sigma",
+	tau:"lettera greca minuscola tau",
+	upsilon:"lettera greca minuscola upsilon",
+	phi:"lettera greca minuscola phi",
+	chi:"lettera greca minuscola chi",
+	psi:"lettera greca minuscola psi",
+	omega:"lettera greca minuscola omega",
+	thetasym:"simbolo della lettera greca minuscola theta",
+	upsih:"simbolo della upsilon greca con uncino",
+	piv:"simbolo di pi greco",
+	bull:"pallino\npiccolo cerchio nero",
+	hellip:"puntini di sospensione\ntre puntini di guida",
+	prime:"apice\nminuti\npiedi",
+	Prime:"doppio apice\nsecondi\npollici",
+	oline:"linea sopra\noverscore con spazio",
+	frasl:"barra obliqua di frazione",
+	weierp:"P maiuscola scritta a mano\ninsieme potenza\np di Weierstrass",
+	image:"I maiuscola gotica\nelemento immaginario",
+	real:"R maiuscola gotica\nsimbolo di elemento reale",
+	trade:"simbolo di marchio commerciale",
+	alefsym:"simbolo alef\nprimo cardinale transfinito",
+	larr:"freccia verso sinistra",
+	uarr:"freccia verso l'alto",
+	rarr:"freccia verso destra",
+	darr:"freccia verso il basso",
+	harr:"freccia sinistra destra",
+	crarr:"freccia verso il basso con angolo a sinistra\nritorno a capo",
+	lArr:"doppia freccia verso sinistra",
+	uArr:"doppia freccia verso l'alto",
+	rArr:"doppia freccia verso destra",
+	dArr:"doppia freccia verso il basso",
+	hArr:"doppia freccia sinistra destra",
+	forall:"per tutti",
+	part:"differenziale parziale",
+	exist:"esiste",
+	empty:"insieme vuoto\ninsieme nullo\ndiametro",
+	nabla:"nabla\ndifferenza retrograda",
+	isin:"elemento di",
+	notin:"non un elemento di",
+	ni:"contiene come membro",
+	prod:"prodotto n-ario\nsegno di prodotto",
+	sum:"sommatoria n-aria",
+	minus:"segno meno",
+	lowast:"operatore asterisco",
+	radic:"radice quadrata\nsegno di radice",
+	prop:"proporzionale a",
+	infin:"infinito",
+	ang:"angolo",
+	and:"and logico\ncuneo",
+	or:"o logico\nvi",
+	cap:"intersezione\nberretto",
+	cup:"unione\ncoppa","int":"integrale",
+	there4:"pertanto",
+	sim:"operatore tilde\nvaria con\nsimile a",
+	cong:"approssimativamente uguale a",
+	asymp:"quasi uguale a\nasintotico a",
+	ne:"non uguale a",
+	equiv:"identico a",
+	le:"minore di o uguale a",
+	ge:"maggiore di o uguale a",
+	sub:"sottoinsieme di",
+	sup:"sovrainsieme di",
+	nsub:"non un sottoinsieme di",
+	sube:"sottoinsieme di o uguale a",
+	supe:"sovrainsieme di o uguale a",
+	oplus:"più cerchiato\nsomma diretta",
+	otimes:"per cerchiato\nprodotto vettoriale",
+	perp:"puntina in su\nortogonale a\nperpendicolare",
+	sdot:"operatore punto",
+	lceil:"soffitto sinistro\ngradino in su APL",
+	rceil:"soffitto destro",
+	lfloor:"pavimento sinistro\ngradino in giù APL",
+	rfloor:"pavimento destro",
+	lang:"parentesi angolare sinistra",
+	rang:"parentesi angolare destra",
+	loz:"losanga",
+	spades:"seme di picche nero",
+	clubs:"seme di fiori nero\ntrifoglio",
+	hearts:"seme di cuori nero\ninnamorato",
+	diams:"seme di quadri nero",
+	OElig:"legatura latina OE maiuscola",
+	oelig:"legatura latina oe minuscola",
+	Scaron:"lettera latina S maiuscola con caron",
+	scaron:"lettera latina s minuscola con caron",
+	Yuml:"lettera latina Y maiuscola con dieresi",
+	circ:"lettera modificatrice accento circonflesso",
+	tilde:"tilde piccola",
+	ensp:"spazio en",
+	emsp:"spazio em",
+	thinsp:"spazio finissimo",
+	zwnj:"non-congiuntore di larghezza zero",
+	zwj:"congiuntore di larghezza zero",
+	lrm:"segno da-sinistra-a-destra",
+	rlm:"segno da-destra-a-sinistra",
+	ndash:"trattino en",
+	mdash:"trattino em",
+	lsquo:"virgoletta sinistra singola",
+	rsquo:"virgoletta destra singola",
+	sbquo:"virgoletta singola in basso a destra",
+	ldquo:"virgolette doppie sinistre",
+	rdquo:"virgolette doppie destre",
+	bdquo:"virgolette doppie in basso a destra",
+	dagger:"croce latina",
+	Dagger:"croce latina doppia",
+	permil:"segno di per mille",
+	lsaquo:"virgoletta angolare singola rivolta a sinistra",
+	rsaquo:"virgoletta angolare singola rivolta a destra",
+	euro:"simbolo dell'euro"
+})
+
diff --git a/dojox/editor/plugins/nls/ja/Breadcrumb.js b/dojox/editor/plugins/nls/ja/Breadcrumb.js
index f5592a4..cca348e 100644
--- a/dojox/editor/plugins/nls/ja/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/ja/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"内容の選択","deleteElement":"要素の削除","moveEnd":"終了するためにカーソルを移動","deleteContents":"内容の削除","nodeActions":"${nodeName} アクション","selectElement":"要素の選択","moveStart":"開始するためにカーソルを移動"})
\ No newline at end of file
+({
+	"nodeActions": "${nodeName} アクション",
+	"selectContents": "内容の選択",
+	"selectElement": "要素の選択",
+	"deleteElement": "要素の削除",
+	"deleteContents": "内容の削除",
+	"moveStart": "開始するためにカーソルを移動",
+	"moveEnd": "終了するためにカーソルを移動"
+})
+
diff --git a/dojox/editor/plugins/nls/ja/FindReplace.js b/dojox/editor/plugins/nls/ja/FindReplace.js
index 55041d1..e5bd6fc 100644
--- a/dojox/editor/plugins/nls/ja/FindReplace.js
+++ b/dojox/editor/plugins/nls/ja/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"後方","findReplace":"検索/置換の切り替え","replaceAll":"すべてのオカレンス","replaceDialogText":"${0} 個のオカレンスを置換しました。","replaceButton":"置換","findButton":"検索","findLabel":"検索内容:","matchCase":"大/小文字を区別","replaceLabel":"次で置換:"})
\ No newline at end of file
+({
+	"findLabel": "検索内容:",
+	"replaceLabel": "次で置換:",
+	"findReplace": "検索/置換の切り替え",
+	"matchCase": "大/小文字を区別", 
+	"backwards": "後方",
+	"replaceAll": "すべてのオカレンス", 
+	"findButton": "検索",
+	"replaceButton": "置換",
+	"replaceDialogText": "${0} 個のオカレンスを置換しました。"
+})
+
diff --git a/dojox/editor/plugins/nls/ja/InsertEntity.js b/dojox/editor/plugins/nls/ja/InsertEntity.js
index 86e413b..f762af5 100644
--- a/dojox/editor/plugins/nls/ja/InsertEntity.js
+++ b/dojox/editor/plugins/nls/ja/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"記号の挿入"})
\ No newline at end of file
+({
+	insertEntity: "記号の挿入"
+})
+
diff --git a/dojox/editor/plugins/nls/ja/PageBreak.js b/dojox/editor/plugins/nls/ja/PageBreak.js
index b4ec56e..a3d63a7 100644
--- a/dojox/editor/plugins/nls/ja/PageBreak.js
+++ b/dojox/editor/plugins/nls/ja/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"改ページ"})
\ No newline at end of file
+({
+	"pageBreak": "改ページ"
+})
+
diff --git a/dojox/editor/plugins/nls/ja/Preview.js b/dojox/editor/plugins/nls/ja/Preview.js
index 6775b1c..26d3baa 100644
--- a/dojox/editor/plugins/nls/ja/Preview.js
+++ b/dojox/editor/plugins/nls/ja/Preview.js
@@ -1 +1,4 @@
-({"preview":"プレビュー"})
\ No newline at end of file
+({
+	"preview": "プレビュー"
+})
+
diff --git a/dojox/editor/plugins/nls/ja/Save.js b/dojox/editor/plugins/nls/ja/Save.js
index 6ca26ff..dcfcf05 100644
--- a/dojox/editor/plugins/nls/ja/Save.js
+++ b/dojox/editor/plugins/nls/ja/Save.js
@@ -1 +1,4 @@
-({"save":"保存"})
\ No newline at end of file
+({
+	"save": "保存"
+})
+
diff --git a/dojox/editor/plugins/nls/ja/ShowBlockNodes.js b/dojox/editor/plugins/nls/ja/ShowBlockNodes.js
index 49e0cfa..74ea4a3 100644
--- a/dojox/editor/plugins/nls/ja/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/ja/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"HTML ブロック要素の表示"})
\ No newline at end of file
+({
+	"showBlockNodes": "HTML ブロック要素の表示"
+})
+
diff --git a/dojox/editor/plugins/nls/ja/Smiley.js b/dojox/editor/plugins/nls/ja/Smiley.js
index 1016416..e39cbf1 100644
--- a/dojox/editor/plugins/nls/ja/Smiley.js
+++ b/dojox/editor/plugins/nls/ja/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"笑い","emoticonCool":"無愛想","emoticonTongue":"舌を出す","emoticonCrying":"泣く","emoticonOops":"おっと","emoticonFrown":"眉をひそめる","emoticonAngry":"怒り","emoticonShy":"はにかんだ","emoticonNo":"いいえ","emoticonAngel":"エンジェル","smiley":"顔文字の挿入","emoticonIdea":"アイデア","emoticonEyebrow":"眉毛","emoticonSmile":"微笑","emoticonWink":"ウィンク","emoticonYes":"はい","emoticonGrin":"笑顔","emoticonGoofy":"おろかな","emoticonHalf":"半分"})
\ No newline at end of file
+({
+	smiley: "顔文字の挿入",
+	emoticonSmile: "微笑",
+	emoticonLaughing: "笑い",
+	emoticonWink: "ウィンク",
+	emoticonGrin: "笑顔",
+	emoticonCool: "無愛想",
+	emoticonAngry: "怒り",  
+	emoticonHalf: "半分", 
+	emoticonEyebrow: "眉毛",
+	emoticonFrown: "眉をひそめる",
+	emoticonShy: "はにかんだ",
+	emoticonGoofy: "おろかな",
+	emoticonOops: "おっと",
+	emoticonTongue: "舌を出す",
+	emoticonIdea: "アイデア",
+	emoticonYes: "はい",
+	emoticonNo: "いいえ",	
+	emoticonAngel: "エンジェル",
+	emoticonCrying: "泣く"
+})
+
diff --git a/dojox/editor/plugins/nls/ja/TableDialog.js b/dojox/editor/plugins/nls/ja/TableDialog.js
index b4ef202..8e193fc 100644
--- a/dojox/editor/plugins/nls/ja/TableDialog.js
+++ b/dojox/editor/plugins/nls/ja/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"設定","insertTableTitle":"テーブルの挿入","insertTableRowAfterLabel":"行を後に追加","center":"中央","deleteTableColumnLabel":"列の削除","right":"右","insertTableColumnBeforeLabel":"列を前に追加","tableWidth":"テーブルの幅:","buttonInsert":"挿入","default":"default","align":"位置合わせ","insertTableRowBeforeLabel":"行を前に追加","cellSpacing":"セル間隔:","pixels":"ピクセル","selectTableLabel":"テーブルの選択","rows":"行","modifyTableTitle":"テーブルの変更","cellPadding":"セル余白:","deleteTableRowLabel":"行の削除","backgroundColor":"背景色:","insertTabl [...]
\ No newline at end of file
+({
+	insertTableTitle: "テーブルの挿入",
+	modifyTableTitle: "テーブルの変更",
+	rows: "行",
+	columns: "列",
+	align: "位置合わせ",
+	cellPadding: "セル余白:",
+	cellSpacing: "セル間隔:",
+	tableWidth: "テーブルの幅:",
+	backgroundColor: "背景色:",
+	borderColor: "ボーダー色:",
+	borderThickness: "ボーダー線幅",
+	percent: "パーセント",
+	pixels: "ピクセル",
+	"default": "default",
+	left: "左",
+	center: "中央",
+	right: "右",
+	buttonSet: "設定", // translated elsewhere?
+	buttonInsert: "挿入",
+
+	selectTableLabel: "テーブルの選択",
+	insertTableRowBeforeLabel: "行を前に追加",
+	insertTableRowAfterLabel: "行を後に追加",
+	insertTableColumnBeforeLabel: "列を前に追加",
+	insertTableColumnAfterLabel: "列を後に追加",
+	deleteTableRowLabel: "行の削除",
+	deleteTableColumnLabel: "列の削除"
+})
+
diff --git a/dojox/editor/plugins/nls/ja/latinEntities.js b/dojox/editor/plugins/nls/ja/latinEntities.js
index 1ec5cba..82830a5 100644
--- a/dojox/editor/plugins/nls/ja/latinEntities.js
+++ b/dojox/editor/plugins/nls/ja/latinEntities.js
@@ -1 +1,257 @@
-({"le":"小さいか等しい","prod":"n 乗\n積符号","zwj":"結合ありで幅ゼロ","mdash":"em ダッシュ","frasl":"分数のスラッシュ","upsih":"ギリシャ語のフック記号付きユプシロン","prop":"比例","middot":"中間ドット\nグルジア語のコンマ\nギリシャ語の中間ドット","hellip":"水平省略符号\n3 つのドット・リーダー","eta":"ギリシャ語の小文字イータ","iacute":"ラテン語の揚音付き小文字 i","yen":"円記号\n元記号","rlm":"右から左へのマーク","macr":"長音記号\n間隔長音記号\n上線\nAPL 上線","ldquo":"左二重引用符","Icirc":"ラテン語の曲折アクセント記号付き大文字 I","OElig":"ラテン語の大文字の合字 OE","hArr":"左右二重矢印","eth":"ラテン語の小文字 eth","divide":"除算記号","chi":"ギリシャ語の小文字カイ","eacute":"ラテン語の揚音付き小文字 e", [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"逆感嘆符",
+	cent:"セント記号",
+	pound:"ポンド記号",
+	curren:"通貨記号",
+	yen:"円記号\n元記号",
+	brvbar:"破線バー\n破線垂直バー",
+	sect:"セクション記号",
+	uml:"分音符号\n間隔分音符号",
+	copy:"著作権記号",
+	ordf:"女性序数標識",
+	laquo:"左二重角引用符\n左ギュメ",
+	not:"否定記号",
+	shy:"ソフト・ハイフン\n任意ハイフン",
+	reg:"登録記号\n登録商標",
+	macr:"長音記号\n間隔長音記号\n上線\nAPL 上線",
+	deg:"角度記号",
+	plusmn:"正符号\n正または負符号",
+	sup2:"上付き文字 2\n上付き文字数字 2\n平方",
+	sup3:"上付き文字 3\n上付き文字数字 3\n立方",
+	acute:"揚音アクセント\n間隔揚音",
+	micro:"マイクロ記号",
+	para:"段落記号\n段落記号",
+	middot:"中間ドット\nグルジア語のコンマ\nギリシャ語の中間ドット",
+	cedil:"セディーユ\n間隔セディーユ",
+	sup1:"上付き文字 1\n上付き文字数字 1",
+	ordm:"男性序数標識",
+	raquo:"右二重角引用符\n右ギュメ",
+	frac14:"分数の 4 分の 1\n分数の 4 分の 1",
+	frac12:"分数の 2 分の 1\n分数の 2 分の 1",
+	frac34:"分数の 4 分の 3\n分数の 4 分の 3",
+	iquest:"逆疑問符\n反転疑問符",
+	Agrave:"ラテン語の抑音付き大文字 A\nラテン語の抑音付き大文字 A",
+	Aacute:"ラテン語の揚音付き大文字 A",
+	Acirc:"ラテン語の曲折アクセント記号付き大文字 A",
+	Atilde:"ラテン語の波形記号付き大文字 A",
+	Auml:"ラテン語の分音符号付き大文字 A",
+	Aring:"ラテン語の上リング付き大文字 A\nラテン語のリング付き大文字 A",
+	AElig:"ラテン語の大文字 AE\nラテン語の大文字の合字 AE",
+	Ccedil:"ラテン語のセディーユ付き大文字 C",
+	Egrave:"ラテン語の抑音付き大文字 E",
+	Eacute:"ラテン語の揚音付き大文字 E",
+	Ecirc:"ラテン語の曲折アクセント記号付き大文字 E",
+	Euml:"ラテン語の分音符号付き大文字 E",
+	Igrave:"ラテン語の抑音付き大文字 I",
+	Iacute:"ラテン語の揚音付き大文字 I",
+	Icirc:"ラテン語の曲折アクセント記号付き大文字 I",
+	Iuml:"ラテン語の分音符号付き大文字 I",
+	ETH:"ラテン語の大文字 ETH",
+	Ntilde:"ラテン語の波形記号付き大文字 N",
+	Ograve:"ラテン語の抑音付き大文字 O",
+	Oacute:"ラテン語の揚音付き大文字 O",
+	Ocirc:"ラテン語の曲折アクセント記号付き大文字 O",
+	Otilde:"ラテン語の波形記号付き大文字 O",
+	Ouml:"ラテン語の分音符号付き大文字 O",
+	times:"乗算記号",
+	Oslash:"ラテン語の斜線付き大文字 O\nラテン語のスラッシュ付き大文字 O",
+	Ugrave:"ラテン語の抑音付き大文字 U",
+	Uacute:"ラテン語の揚音付き大文字 U",
+	Ucirc:"ラテン語の曲折アクセント記号付き大文字 U",
+	Uuml:"ラテン語の分音符号付き大文字 U",
+	Yacute:"ラテン語の揚音付き大文字 Y",
+	THORN:"ラテン語の大文字 THORN",
+	szlig:"ラテン語の小文字のシャープ s\n s 字形",
+	agrave:"ラテン語の抑音付き小文字 a\nラテン語の抑音付き小文字 a",
+	aacute:"ラテン語の揚音付き小文字 a",
+	acirc:"ラテン語の曲折アクセント記号付き小文字 a",
+	atilde:"ラテン語の波形記号付き小文字 a",
+	auml:"ラテン語の分音符号付き小文字 a",
+	aring:"ラテン語の上リング付き小文字 a\nラテン語のリング付き小文字 a",
+	aelig:"ラテン語の小文字 ae\nラテン語の小文字の合字 ae",
+	ccedil:"ラテン語のセディーユ付き小文字 c",
+	egrave:"ラテン語の抑音付き小文字 e",
+	eacute:"ラテン語の揚音付き小文字 e",
+	ecirc:"ラテン語の曲折アクセント記号付き小文字 e",
+	euml:"ラテン語の分音符号付き小文字 e",
+	igrave:"ラテン語の抑音付き小文字 i",
+	iacute:"ラテン語の揚音付き小文字 i",
+	icirc:"ラテン語の曲折アクセント記号付き小文字 i",
+	iuml:"ラテン語の分音符号付き小文字 i",
+	eth:"ラテン語の小文字 eth",
+	ntilde:"ラテン語の波形記号付き小文字 n",
+	ograve:"ラテン語の抑音付き小文字 o",
+	oacute:"ラテン語の揚音付き小文字 o",
+	ocirc:"ラテン語の曲折アクセント記号付き小文字 o",
+	otilde:"ラテン語の波形記号付き小文字 o",
+	ouml:"ラテン語の分音符号付き小文字 o",
+	divide:"除算記号",
+	oslash:"ラテン語の斜線付き小文字 o\nラテン語のスラッシュ付き小文字 o",
+	ugrave:"ラテン語の抑音付き小文字 u",
+	uacute:"ラテン語の揚音付き小文字 u",
+	ucirc:"ラテン語の曲折アクセント記号付き小文字 u",
+	uuml:"ラテン語の分音符号付き小文字 u",
+	yacute:"ラテン語の揚音付き小文字 y",
+	thorn:"ラテン語の小文字 thorn",
+	yuml:"ラテン語の分音符号付き小文字 y",
+
+// Greek Characters and Symbols
+	fnof:"ラテン語のフック付き小文字 f\n関数\nフロリン",
+	Alpha:"ギリシャ語の大文字アルファ",
+	Beta:"ギリシャ語の大文字ベータ",
+	Gamma:"ギリシャ語の大文字ガンマ",
+	Delta:"ギリシャ語の大文字デルタ",
+	Epsilon:"ギリシャ語の大文字イプシロン",
+	Zeta:"ギリシャ語の大文字ゼータ",
+	Eta:"ギリシャ語の大文字イータ",
+	Theta:"ギリシャ語の大文字シータ",
+	Iota:"ギリシャ語の大文字イオタ",
+	Kappa:"ギリシャ語の大文字カッパ",
+	Lambda:"ギリシャ語の大文字ラムダ",
+	Mu:"ギリシャ語の大文字ミュー",
+	Nu:"ギリシャ語の大文字ニュー",
+	Xi:"ギリシャ語の大文字クシー",
+	Omicron:"ギリシャ語の大文字オミクロン",
+	Pi:"ギリシャ語の大文字パイ",
+	Rho:"ギリシャ語の大文字ロー",
+	Sigma:"ギリシャ語の大文字シグマ",
+	Tau:"ギリシャ語の大文字タウ",
+	Upsilon:"ギリシャ語の大文字ユプシロン",
+	Phi:"ギリシャ語の大文字ファイ",
+	Chi:"ギリシャ語の大文字カイ",
+	Psi:"ギリシャ語の大文字プシー",
+	Omega:"ギリシャ語の大文字オメガ",
+	alpha:"ギリシャ語の小文字アルファ",
+	beta:"ギリシャ語の小文字ベータ",
+	gamma:"ギリシャ語の小文字ガンマ",
+	delta:"ギリシャ語の小文字デルタ",
+	epsilon:"ギリシャ語の小文字イプシロン",
+	zeta:"ギリシャ語の小文字ゼータ",
+	eta:"ギリシャ語の小文字イータ",
+	theta:"ギリシャ語の小文字シータ",
+	iota:"ギリシャ語の小文字イオタ",
+	kappa:"ギリシャ語の小文字カッパ",
+	lambda:"ギリシャ語の小文字ラムダ",
+	mu:"ギリシャ語の小文字ミュー",
+	nu:"ギリシャ語の小文字ニュー",
+	xi:"ギリシャ語の小文字クシー",
+	omicron:"ギリシャ語の小文字オミクロン",
+	pi:"ギリシャ語の小文字パイ",
+	rho:"ギリシャ語の小文字ロー",
+	sigmaf:"ギリシャ語の小文字ファイナルシグマ",
+	sigma:"ギリシャ語の小文字シグマ",
+	tau:"ギリシャ語の小文字タウ",
+	upsilon:"ギリシャ語の小文字ユプシロン",
+	phi:"ギリシャ語の小文字ファイ",
+	chi:"ギリシャ語の小文字カイ",
+	psi:"ギリシャ語の小文字プシー",
+	omega:"ギリシャ語の小文字オメガ",
+	thetasym:"ギリシャ語の小文字シータ記号",
+	upsih:"ギリシャ語のフック記号付きユプシロン",
+	piv:"ギリシャ語のパイ記号",
+	bull:"黒丸\n黒い小さな円",
+	hellip:"水平省略符号\n3 つのドット・リーダー",
+	prime:"プライム記号\n分\nフィート",
+	Prime:"二重プライム記号\n秒\nインチ",
+	oline:"上線\n間隔上線",
+	frasl:"分数のスラッシュ",
+	weierp:"添え字の大文字 P\n累乗集合\nWeierstrass p",
+	image:"ドイツ字体の大文字 I\n虚数部",
+	real:"ドイツ字体の大文字 R\n実数部記号",
+	trade:"商標",
+	alefsym:"アレフ記号\n1 番目の超限基数",
+	larr:"左矢印",
+	uarr:"上矢印",
+	rarr:"右矢印",
+	darr:"下矢印",
+	harr:"左右矢印",
+	crarr:"角が左向きの下矢印\復帰",
+	lArr:"左二重矢印",
+	uArr:"上二重矢印",
+	rArr:"右二重矢印",
+	dArr:"下二重矢印",
+	hArr:"左右二重矢印",
+	forall:"すべてについて",
+	part:"偏微分",
+	exist:"存在",
+	empty:"空集合\nヌル集合\n直径",
+	nabla:"ナブラ\n後方の差分",
+	isin:"右辺の要素である",
+	notin:"右辺の要素でない",
+	ni:"メンバーとして含まれる",
+	prod:"n 乗\n積符号",
+	sum:"n 回加算",
+	minus:"減算記号",
+	lowast:"アスタリスク演算子",
+	radic:"平方根\nルート記号",
+	prop:"比例",
+	infin:"無限",
+	ang:"角度",
+	and:"論理積\nくさび形",
+	or:"論理和\nV 字形",
+	cap:"集合の積\nキャップ形",
+	cup:"和集合\カップ形","int":"積分",
+	there4:"したがって",
+	sim:"チルド演算子\n多様性\n類似性",
+	cong:"おおよそ等しい",
+	asymp:"ほぼ等しい\n漸近",
+	ne:"等しくない",
+	equiv:"同一",
+	le:"小さいか等しい",
+	ge:"大きいか等しい",
+	sub:"左辺は右辺の部分集合",
+	sup:"左辺は右辺を包含する",
+	nsub:"部分集合でない",
+	sube:"部分集合または等しい",
+	supe:"包含集合または等しい",
+	oplus:"ベクトル和\n直和",
+	otimes:"ベクトル積\nベクトル積",
+	perp:"直角\n直交\n垂直",
+	sdot:"ドット演算子",
+	lceil:"左上限\nAPL 上限",
+	rceil:"右上限",
+	lfloor:"左下限\nAPL 下限",
+	rfloor:"右下限",
+	lang:"左角括弧",
+	rang:"右角括弧",
+	loz:"ひし形",
+	spades:"トランプの黒のスペードの組",
+	clubs:"トランプの黒のクラブの組\nシャムロック",
+	hearts:"トランプの黒のハートの組\nバレンタイン",
+	diams:"トランプの黒のダイヤモンドの組",
+	OElig:"ラテン語の大文字の合字 OE",
+	oelig:"ラテン語の小文字の合字 oe",
+	Scaron:"ラテン語のキャロン付き大文字 S",
+	scaron:"ラテン語のキャロン付き小文字 s",
+	Yuml:"ラテン語の分音符号付き大文字 Y",
+	circ:"修飾文字の曲折アクセント記号アクセント",
+	tilde:"小文字の波形記号",
+	ensp:"en スペース",
+	emsp:"em スペース",
+	thinsp:"薄いスペース",
+	zwnj:"結合なしで幅ゼロ",
+	zwj:"結合ありで幅ゼロ",
+	lrm:"左から右へのマーク",
+	rlm:"右から左へのマーク",
+	ndash:"en ダッシュ",
+	mdash:"em ダッシュ",
+	lsquo:"左単一引用符",
+	rsquo:"右単一引用符",
+	sbquo:"単一下付き右引用符",
+	ldquo:"左二重引用符",
+	rdquo:"右二重引用符",
+	bdquo:"二重下付き右引用符",
+	dagger:"剣標",
+	Dagger:"二重剣標",
+	permil:"パーミル記号",
+	lsaquo:"単一左角引用符",
+	rsaquo:"単一右角引用符",
+	euro:"ユーロ記号"
+})
+
diff --git a/dojox/editor/plugins/nls/ko/Breadcrumb.js b/dojox/editor/plugins/nls/ko/Breadcrumb.js
old mode 100644
new mode 100755
index 51014c1..a26516c
--- a/dojox/editor/plugins/nls/ko/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/ko/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"컨텐츠 선택","deleteElement":"요소 삭제","moveEnd":"커서를 이동하여 종료","deleteContents":"컨텐츠 삭제","nodeActions":"${nodeName} 조치","selectElement":"요소 선택","moveStart":"커서를 이동하여 시작"})
\ No newline at end of file
+({
+	"nodeActions": "${nodeName} 조치",
+	"selectContents": "컨텐츠 선택",
+	"selectElement": "요소 선택",
+	"deleteElement": "요소 삭제",
+	"deleteContents": "컨텐츠 삭제",
+	"moveStart": "커서를 이동하여 시작",
+	"moveEnd": "커서를 이동하여 종료"
+})
+
diff --git a/dojox/editor/plugins/nls/ko/FindReplace.js b/dojox/editor/plugins/nls/ko/FindReplace.js
old mode 100644
new mode 100755
index ccca3e6..61c34dc
--- a/dojox/editor/plugins/nls/ko/FindReplace.js
+++ b/dojox/editor/plugins/nls/ko/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"뒤로","findReplace":"토글 찾기/바꾸기","replaceAll":"모두 바꾸기","replaceDialogText":"${0}개를 바꿨습니다.","replaceButton":"바꾸기","findButton":"찾기","findLabel":"찾을 문자열:","matchCase":"대소문자 일치","replaceLabel":"바꿀 대상:"})
\ No newline at end of file
+({
+	"findLabel": "찾을 문자열:",
+	"replaceLabel": "바꿀 대상:",
+	"findReplace": "토글 찾기/바꾸기",
+	"matchCase": "대소문자 일치", 
+	"backwards": "뒤로",
+	"replaceAll": "모두 바꾸기", 
+	"findButton": "찾기",
+	"replaceButton": "바꾸기",
+	"replaceDialogText": "${0}개를 바꿨습니다."
+})
+
diff --git a/dojox/editor/plugins/nls/ko/InsertEntity.js b/dojox/editor/plugins/nls/ko/InsertEntity.js
old mode 100644
new mode 100755
index 45b74ee..0039e4b
--- a/dojox/editor/plugins/nls/ko/InsertEntity.js
+++ b/dojox/editor/plugins/nls/ko/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"기호 삽입"})
\ No newline at end of file
+({
+	insertEntity: "기호 삽입"
+})
+
diff --git a/dojox/editor/plugins/nls/ko/PageBreak.js b/dojox/editor/plugins/nls/ko/PageBreak.js
old mode 100644
new mode 100755
index 5dba6b1..6a0836a
--- a/dojox/editor/plugins/nls/ko/PageBreak.js
+++ b/dojox/editor/plugins/nls/ko/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"페이지 나누기"})
\ No newline at end of file
+({
+	"pageBreak": "페이지 나누기"
+})
+
diff --git a/dojox/editor/plugins/nls/ko/Preview.js b/dojox/editor/plugins/nls/ko/Preview.js
old mode 100644
new mode 100755
index 418b88d..b340961
--- a/dojox/editor/plugins/nls/ko/Preview.js
+++ b/dojox/editor/plugins/nls/ko/Preview.js
@@ -1 +1,4 @@
-({"preview":"미리보기"})
\ No newline at end of file
+({
+	"preview": "미리보기"
+})
+
diff --git a/dojox/editor/plugins/nls/ko/Save.js b/dojox/editor/plugins/nls/ko/Save.js
old mode 100644
new mode 100755
index 0e3436e..ba6eced
--- a/dojox/editor/plugins/nls/ko/Save.js
+++ b/dojox/editor/plugins/nls/ko/Save.js
@@ -1 +1,4 @@
-({"save":"저장"})
\ No newline at end of file
+({
+	"save": "저장"
+})
+
diff --git a/dojox/editor/plugins/nls/ko/ShowBlockNodes.js b/dojox/editor/plugins/nls/ko/ShowBlockNodes.js
old mode 100644
new mode 100755
index bac847b..1b8005c
--- a/dojox/editor/plugins/nls/ko/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/ko/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"HTML 블록 요소 표시"})
\ No newline at end of file
+({
+	"showBlockNodes": "HTML 블록 요소 표시"
+})
+
diff --git a/dojox/editor/plugins/nls/ko/Smiley.js b/dojox/editor/plugins/nls/ko/Smiley.js
index 04b3444..67872d3 100644
--- a/dojox/editor/plugins/nls/ko/Smiley.js
+++ b/dojox/editor/plugins/nls/ko/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"하하","emoticonCool":"멋진데","emoticonTongue":"메롱","emoticonCrying":"울음","emoticonOops":"어머나","emoticonFrown":"불만","emoticonAngry":"화남","emoticonShy":"부끄러움","emoticonNo":"아니오","emoticonAngel":"천사","smiley":"이모티콘 삽입","emoticonIdea":"아이디어","emoticonEyebrow":"글쎄","emoticonSmile":"미소","emoticonWink":"윙크","emoticonYes":"예","emoticonGrin":"씨익","emoticonGoofy":"바보","emoticonHalf":"고민 중"})
\ No newline at end of file
+({
+	smiley: "이모티콘 삽입",
+	emoticonSmile: "미소",
+	emoticonLaughing: "하하",
+	emoticonWink: "윙크",
+	emoticonGrin: "씨익",
+	emoticonCool: "멋진데",
+	emoticonAngry: "화남",  
+	emoticonHalf: "고민 중", 
+	emoticonEyebrow: "글쎄",
+	emoticonFrown: "불만",
+	emoticonShy: "부끄러움",
+	emoticonGoofy: "바보",
+	emoticonOops: "어머나",
+	emoticonTongue: "메롱",
+	emoticonIdea: "아이디어",
+	emoticonYes: "예",
+	emoticonNo: "아니오",	
+	emoticonAngel: "천사",
+	emoticonCrying: "울음"
+})
+
diff --git a/dojox/editor/plugins/nls/ko/TableDialog.js b/dojox/editor/plugins/nls/ko/TableDialog.js
index c11b6ff..788d588 100644
--- a/dojox/editor/plugins/nls/ko/TableDialog.js
+++ b/dojox/editor/plugins/nls/ko/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"설정","insertTableTitle":"테이블 삽입","insertTableRowAfterLabel":"사후 행 추가","center":"가운데","deleteTableColumnLabel":"열 삭제","right":"오른쪽","insertTableColumnBeforeLabel":"사전 열 추가","tableWidth":"테이블 너비:","buttonInsert":"삽입","default":"기본값","align":"맞추기:","insertTableRowBeforeLabel":"사전 행 추가","cellSpacing":"셀 간격:","pixels":"픽셀","selectTableLabel":"테이블 선택","rows":"행:","modifyTableTitle":"테이블 수정","cellPadding":"셀 채우기:","deleteTableRowLabel":"행 삭제","backgroundColor":"배경색:","insertTableC [...]
\ No newline at end of file
+({
+	insertTableTitle: "테이블 삽입",
+	modifyTableTitle: "테이블 수정",
+	rows: "행:",
+	columns: "열:",
+	align: "맞추기:",
+	cellPadding: "셀 채우기:",
+	cellSpacing: "셀 간격:",
+	tableWidth: "테이블 너비:",
+	backgroundColor: "배경색:",
+	borderColor: "테두리 색:",
+	borderThickness: "테두리 굵기",
+	percent: "백분율",
+	pixels: "픽셀",
+	"default": "기본값",
+	left: "왼쪽",
+	center: "가운데",
+	right: "오른쪽",
+	buttonSet: "설정", // translated elsewhere?
+	buttonInsert: "삽입",
+
+	selectTableLabel: "테이블 선택",
+	insertTableRowBeforeLabel: "사전 행 추가",
+	insertTableRowAfterLabel: "사후 행 추가",
+	insertTableColumnBeforeLabel: "사전 열 추가",
+	insertTableColumnAfterLabel: "사후 열 추가",
+	deleteTableRowLabel: "행 삭제",
+	deleteTableColumnLabel: "열 삭제"
+})
+
diff --git a/dojox/editor/plugins/nls/ko/latinEntities.js b/dojox/editor/plugins/nls/ko/latinEntities.js
index 8066e4b..9433b67 100644
--- a/dojox/editor/plugins/nls/ko/latinEntities.js
+++ b/dojox/editor/plugins/nls/ko/latinEntities.js
@@ -1 +1,257 @@
-({"le":"적거나 같다","prod":"n-ary product\n결과 기호","zwj":"제로 너비 조이너","mdash":"em 대시","frasl":"분수 사선","upsih":"그리스 upsilon에 고리 기호","prop":"비례","middot":"중앙 점\n중앙 점\n중앙 점","hellip":"수평 세 점\n수평 세 점","eta":"그리스소문자 eta","iacute":"라틴소문자 i 액센트","yen":"엔화 기호\n엔화 기호","rlm":"오른쪽에서 왼쪽으로 표시","macr":"장음 기호\n장음 기호\n장음 기호\n장음 기호","ldquo":"왼쪽 이중 따옴표","Icirc":"라틴대문자 I 위 꺾음 표시","OElig":"라틴대문자 ligature OE","hArr":"좌우 이중 화살표","eth":"라틴소문자 eth","divide":"나눗셈 기호","chi":"그리스소문자 chi","eacute":"라틴소문자 e 위 액센트","icirc" [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"거꾸로 느낌표",
+	cent:"센트 기호",
+	pound:"파운드 기호",
+	curren:"통화 기호",
+	yen:"엔화 기호\n엔화 기호",
+	brvbar:"수직 바\n수직 바",
+	sect:"섹션 기호",
+	uml:"두점 표시\n두점 표시",
+	copy:"저작권",
+	ordf:"줄 위의 소문자 a",
+	laquo:"이중 꺾어 열음\n이중 꺾어 열음",
+	not:"not 기호",
+	shy:"부드러운 하이픈\n부드러운 하이픈",
+	reg:"등록 상표 기호\n등록 상표 기호",
+	macr:"장음 기호\n장음 기호\n장음 기호\n장음 기호",
+	deg:"도 기호",
+	plusmn:"플러스 마이너스\n플러스 마이너스",
+	sup2:"위첨자 2\n위첨자 2\n위첨자 2",
+	sup3:"위첨자 3\n위첨자 3\n위첨자 3",
+	acute:"양음 액센트\n양음 액센트",
+	micro:"마이크로 기호",
+	para:"문단 기호\n문단 기호",
+	middot:"중앙 점\n중앙 점\n중앙 점",
+	cedil:"갈고리형 부호\n갈고리형 부호",
+	sup1:"위첨자 1\n위첨자 1",
+	ordm:"줄 위의 작은 원",
+	raquo:"이중 꺾어 닫음\n이중 꺾어 닫음",
+	frac14:"사분의 일\n사분의 일",
+	frac12:"이분의 일\n이분의 일",
+	frac34:"사분의 삼\n사분의 삼",
+	iquest:"거꾸로 물음표\n거꾸로 물음표",
+	Agrave:"라틴대문자 A 위 역액센트\n라틴대문자 A 위 역액센트",
+	Aacute:"라틴대문자 A 위 액센트",
+	Acirc:"라틴대문자 A 위 꺾음 표시",
+	Atilde:"라틴대문자 A 위 물결 표시",
+	Auml:"라틴대문자 A 위 두점 표시",
+	Aring:"라틴대문자 A 위 원 표시\n라틴대문자 A 위 원 표시",
+	AElig:"라틴대문자 AE\n라틴대문자 AE",
+	Ccedil:"라틴대문자 C 갈고리형 부호",
+	Egrave:"라틴대문자 E 위 역액센트",
+	Eacute:"라틴대문자 E 위 액센트",
+	Ecirc:"라틴대문자 E 위 꺾음 표시",
+	Euml:"라틴대문자 E 위 두점 표시",
+	Igrave:"라틴대문자 I 위 역액센트",
+	Iacute:"라틴대문자 I 위 액센트",
+	Icirc:"라틴대문자 I 위 꺾음 표시",
+	Iuml:"라틴대문자 I 위 두점 표시",
+	ETH:"라틴대문자 ETH",
+	Ntilde:"라틴대문자 N 위 물결 표시",
+	Ograve:"라틴대문자 O 위 역액센트",
+	Oacute:"라틴대문자 O 위 액센트",
+	Ocirc:"라틴대문자 O 위 꺾음 표시",
+	Otilde:"라틴대문자 O 위 물결 표시",
+	Ouml:"라틴대문자 O 위 두점 표시",
+	times:"곱셈 기호",
+	Oslash:"라틴대문자 O 슬래시 첨부",
+	Ugrave:"라틴대문자 U 위 역액센트",
+	Uacute:"라틴대문자 U 위 액센트",
+	Ucirc:"라틴대문자 U 위 꺾음 표시",
+	Uuml:"라틴대문자 U 위 두점 표시",
+	Yacute:"라틴대문자 Y 위 액센트",
+	THORN:"라틴대문자 THORN",
+	szlig:"라틴소문자 sharp\n라틴소문자 sharp",
+	agrave:"라틴소문자 a 위 역액센트\n라틴소문자 a 위 역액센트",
+	aacute:"라틴소문자 a 위 액센트",
+	acirc:"라틴소문자 a 위 꺾음 표시",
+	atilde:"라틴소문자 a 위 물결 표시",
+	auml:"라틴소문자 a 위 두점 표시",
+	aring:"라틴소문자 a 위 원 표시\n라틴소문자 a 위 원 표시",
+	aelig:"라틴소문자 ae\n라틴소문자 ae",
+	ccedil:"라틴소문자 c 갈고리형 부호",
+	egrave:"라틴소문자 e  위 역액센트",
+	eacute:"라틴소문자 e 위 액센트",
+	ecirc:"라틴소문자 e 위 꺾음 표시",
+	euml:"라틴소문자 e 위 두점 표시",
+	igrave:"라틴소문자 i 위 역액센트",
+	iacute:"라틴소문자 i 액센트",
+	icirc:"라틴소문자 i 위 꺾음 표시",
+	iuml:"라틴소문자 i 위 두점 표시",
+	eth:"라틴소문자 eth",
+	ntilde:"라틴소문자 n 위 물결 표시",
+	ograve:"라틴소문자 o 위 역액센트",
+	oacute:"라틴소문자 o 위 액센트",
+	ocirc:"라틴소문자 o 위 꺾음 표시",
+	otilde:"라틴소문자 o 위 물결 표시",
+	ouml:"라틴소문자 o 위 두점 표시",
+	divide:"나눗셈 기호",
+	oslash:"라틴소문자 o 슬래시 첨부\n라틴소문자 o 슬래시 첨부",
+	ugrave:"라틴소문자 u 위 역액센트",
+	uacute:"라틴소문자 u 위 액센트",
+	ucirc:"라틴소문자 u 위 꺾음 표시",
+	uuml:"라틴소문자 u 위 두점 표시",
+	yacute:"라틴소문자 y 위 액센트",
+	thorn:"라틴소문자 thorn",
+	yuml:"라틴소문자 y 위 두점 표시",
+
+// Greek Characters and Symbols
+	fnof:"라틴소문자 f에 고리 첨부\n라틴소문자 f에 고리 첨부\n라틴소문자 f에 고리 첨부",
+	Alpha:"그리스대문자 alpha",
+	Beta:"그리스대문자 beta",
+	Gamma:"그리스대문자 gamma",
+	Delta:"그리스대문자 delta",
+	Epsilon:"그리스대문자 epsilon",
+	Zeta:"그리스대문자 zeta",
+	Eta:"그리스대문자 eta",
+	Theta:"그리스대문자 theta",
+	Iota:"그리스대문자 iota",
+	Kappa:"그리스대문자 kappa",
+	Lambda:"그리스대문자 lambda",
+	Mu:"그리스대문자 mu",
+	Nu:"그리스대문자 nu",
+	Xi:"그리스대문자 xi",
+	Omicron:"그리스대문자 omicron",
+	Pi:"그리스대문자 pi",
+	Rho:"그리스대문자 rho",
+	Sigma:"그리스대문자 sigma",
+	Tau:"그리스대문자 tau",
+	Upsilon:"그리스대문자 upsilon",
+	Phi:"그리스대문자 phi",
+	Chi:"그리스대문자 chi",
+	Psi:"그리스대문자 psi",
+	Omega:"그리스대문자 omega",
+	alpha:"그리스소문자 alpha",
+	beta:"그리스소문자 beta",
+	gamma:"그리스소문자 gamma",
+	delta:"그리스소문자 delta",
+	epsilon:"그리스소문자 epsilon",
+	zeta:"그리스소문자 zeta",
+	eta:"그리스소문자 eta",
+	theta:"그리스소문자 theta",
+	iota:"그리스소문자 iota",
+	kappa:"그리스소문자 kappa",
+	lambda:"그리스소문자 lambda",
+	mu:"그리스소문자 mu",
+	nu:"그리스소문자 nu",
+	xi:"그리스소문자 xi",
+	omicron:"그리스소문자 omicron",
+	pi:"그리스소문자 pi",
+	rho:"그리스소문자 rho",
+	sigmaf:"그리스소문자 final sigma",
+	sigma:"그리스소문자 sigma",
+	tau:"그리스소문자 tau",
+	upsilon:"그리스소문자 upsilon",
+	phi:"그리스소문자 phi",
+	chi:"그리스소문자 chi",
+	psi:"그리스소문자 psi",
+	omega:"그리스소문자 omega",
+	thetasym:"그리스소문자 theta symbol",
+	upsih:"그리스 upsilon에 고리 기호",
+	piv:"그리스 pi symbol",
+	bull:"검은 원\n검은 원",
+	hellip:"수평 세 점\n수평 세 점",
+	prime:"프라임\n분\n피트",
+	Prime:"이중 프라임\n초\n인치",
+	oline:"윗 줄\n윗 줄",
+	frasl:"분수 사선",
+	weierp:"script 대문자 P\nscript 대문자 P\nscript 대문자 P",
+	image:"검정 글자 대문자 I\n검정 글자 대문자 I",
+	real:"검정 글자 대문자 R\n검정 글자 대문자 R",
+	trade:"TM(trade mark) 기호",
+	alefsym:"alef 기호\nalef 기호",
+	larr:"왼쪽 화살표",
+	uarr:"위쪽 화살표",
+	rarr:"오른쪽 화살표",
+	darr:"아래쪽 화살표",
+	harr:"좌우 화살표",
+	crarr:"캐리지 리턴\n캐리지 리턴]",
+	lArr:"왼쪽 이중 화살표",
+	uArr:"위쪽 이중 화살표",
+	rArr:"오른쪽 이중 화살표",
+	dArr:"아래쪽 이중 화살표",
+	hArr:"좌우 이중 화살표",
+	forall:"거꾸로 A",
+	part:"부분적으로 다름",
+	exist:"존재",
+	empty:"없음\n널\n직경",
+	nabla:"역 삼각형\n역 삼각형",
+	isin:"..의 요소",
+	notin:"..의 요소가 아님",
+	ni:"멤버로 포함",
+	prod:"n-ary product\n결과 기호",
+	sum:"n-ary 합",
+	minus:"마이너스 기호",
+	lowast:"별표 연산자",
+	radic:"제곱근 기호\n근호",
+	prop:"비례",
+	infin:"무한대",
+	ang:"각도",
+	and:"논리적 and\nwedge",
+	or:"논리적 or\nvee",
+	cap:"inter 항목\n모자",
+	cup:"유니온\n컵","int":"인티그랄",
+	there4:"따라서",
+	sim:"물결 표시\n물결 표시\n유사함",
+	cong:"대략 같다",
+	asymp:"거의 같다\n거의 같다",
+	ne:"같지 않다",
+	equiv:"합동, 같다",
+	le:"적거나 같다",
+	ge:"크거나 같다",
+	sub:"부분 집합",
+	sup:"상위 집합",
+	nsub:"부분 집합이 아님",
+	sube:"부분 집합이거나 같다",
+	supe:"상위 집합이거나 같다",
+	oplus:"circled plus\ndirect sum",
+	otimes:"circled times\nvector product",
+	perp:"수직\n수직\n수직",
+	sdot:"도트 연산자",
+	lceil:"왼쪽 씰링\nAPL 업스타일",
+	rceil:"오른쪽 씰링",
+	lfloor:"왼쪽 플로어\nAPL 다운스타일",
+	rfloor:"오른쪽 플로어",
+	lang:"왼쪽 열린 각도",
+	rang:"오른쪽 열린 각도",
+	loz:"마름모",
+	spades:"블랙 스페이드",
+	clubs:"블랙 크로버\n블랙 크로버",
+	hearts:"블랙 하트\n블랙 하트",
+	diams:"블랙 다이아몬드",
+	OElig:"라틴대문자 ligature OE",
+	oelig:"라틴소문자 ligature oe",
+	Scaron:"라틴대문자 S 위 v 표 ",
+	scaron:"라틴소문자 s 위 v 표",
+	Yuml:"라틴대문자 Y 위 두점 표시",
+	circ:"위 꺾기",
+	tilde:"소문자 위 물결 표시",
+	ensp:"en 공간",
+	emsp:"em 공간",
+	thinsp:"씬 공간",
+	zwnj:"제로 너비 비조이너",
+	zwj:"제로 너비 조이너",
+	lrm:"왼쪽에서 오른쪽으로 표시",
+	rlm:"오른쪽에서 왼쪽으로 표시",
+	ndash:"en 대시 ",
+	mdash:"em 대시",
+	lsquo:"왼쪽 단일 따옴표",
+	rsquo:"오른쪽 단일 따옴표",
+	sbquo:"단일 바닥 따옴표",
+	ldquo:"왼쪽 이중 따옴표",
+	rdquo:"오른쪽 이중 따옴표",
+	bdquo:"이중 바닥 따옴표",
+	dagger:"dagger",
+	Dagger:"이중 dagger",
+	permil:"퍼밀 기호",
+	lsaquo:"단일 왼쪽으로 각 따옴",
+	rsaquo:"단일 오른쪽으로 각 따옴",
+	euro:"euro 기호"
+})
+
diff --git a/dojox/editor/plugins/nls/latinEntities.js b/dojox/editor/plugins/nls/latinEntities.js
index f49065e..ca7f715 100644
--- a/dojox/editor/plugins/nls/latinEntities.js
+++ b/dojox/editor/plugins/nls/latinEntities.js
@@ -1 +1,256 @@
-({"le":"less-than or equal to","prod":"n-ary product\nproduct sign","zwj":"zero width joiner","mdash":"em dash","frasl":"fraction slash","upsih":"Greek upsilon with hook symbol","prop":"proportional to","middot":"middle dot\nGeorgian comma\nGreek middle dot","hellip":"horizontal ellipsis\nthree dot leader","eta":"Greek small letter eta","iacute":"Latin small letter i with acute","yen":"yen sign\nyuan sign","rlm":"right-to-left mark","macr":"macron\nspacing macron\noverline\nAPL overbar", [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"inverted exclamation mark",
+	cent:"cent sign",
+	pound:"pound sign",
+	curren:"currency sign",
+	yen:"yen sign\nyuan sign",
+	brvbar:"broken bar\nbroken vertical bar",
+	sect:"section sign",
+	uml:"diaeresis\nspacing diaeresis",
+	copy:"copyright sign",
+	ordf:"feminine ordinal indicator",
+	laquo:"left-pointing double angle quotation mark\nleft pointing guillemet",
+	not:"not sign",
+	shy:"soft hyphen\ndiscretionary hyphen",
+	reg:"registered sign\nregistered trade mark sign",
+	macr:"macron\nspacing macron\noverline\nAPL overbar",
+	deg:"degree sign",
+	plusmn:"plus-minus sign\nplus-or-minus sign",
+	sup2:"superscript two\nsuperscript digit two\nsquared",
+	sup3:"superscript three\nsuperscript digit three\ncubed",
+	acute:"acute accent\nspacing acute",
+	micro:"micro sign",
+	para:"pilcrow sign\nparagraph sign",
+	middot:"middle dot\nGeorgian comma\nGreek middle dot",
+	cedil:"cedilla\nspacing cedilla",
+	sup1:"superscript one\nsuperscript digit one",
+	ordm:"masculine ordinal indicator",
+	raquo:"right-pointing double angle quotation mark\nright pointing guillemet",
+	frac14:"vulgar fraction one quarter\nfraction one quarter",
+	frac12:"vulgar fraction one half\nfraction one half",
+	frac34:"vulgar fraction three quarters\nfraction three quarters",
+	iquest:"inverted question mark\nturned question mark",
+	Agrave:"Latin capital letter A with grave\nLatin capital letter A grave",
+	Aacute:"Latin capital letter A with acute",
+	Acirc:"Latin capital letter A with circumflex",
+	Atilde:"Latin capital letter A with tilde",
+	Auml:"Latin capital letter A with diaeresis",
+	Aring:"Latin capital letter A with ring above\nLatin capital letter A ring",
+	AElig:"Latin capital letter AE\nLatin capital ligature AE",
+	Ccedil:"Latin capital letter C with cedilla",
+	Egrave:"Latin capital letter E with grave",
+	Eacute:"Latin capital letter E with acute",
+	Ecirc:"Latin capital letter E with circumflex",
+	Euml:"Latin capital letter E with diaeresis",
+	Igrave:"Latin capital letter I with grave",
+	Iacute:"Latin capital letter I with acute",
+	Icirc:"Latin capital letter I with circumflex",
+	Iuml:"Latin capital letter I with diaeresis",
+	ETH:"Latin capital letter ETH",
+	Ntilde:"Latin capital letter N with tilde",
+	Ograve:"Latin capital letter O with grave",
+	Oacute:"Latin capital letter O with acute",
+	Ocirc:"Latin capital letter O with circumflex",
+	Otilde:"Latin capital letter O with tilde",
+	Ouml:"Latin capital letter O with diaeresis",
+	times:"multiplication sign",
+	Oslash:"Latin capital letter O with stroke\nLatin capital letter O slash",
+	Ugrave:"Latin capital letter U with grave",
+	Uacute:"Latin capital letter U with acute",
+	Ucirc:"Latin capital letter U with circumflex",
+	Uuml:"Latin capital letter U with diaeresis",
+	Yacute:"Latin capital letter Y with acute",
+	THORN:"Latin capital letter THORN",
+	szlig:"Latin small letter sharp s\ness-zed",
+	agrave:"Latin small letter a with grave\nLatin small letter a grave",
+	aacute:"Latin small letter a with acute",
+	acirc:"Latin small letter a with circumflex",
+	atilde:"Latin small letter a with tilde",
+	auml:"Latin small letter a with diaeresis",
+	aring:"Latin small letter a with ring above\nLatin small letter a ring",
+	aelig:"Latin small letter ae\nLatin small ligature ae",
+	ccedil:"Latin small letter c with cedilla",
+	egrave:"Latin small letter e with grave",
+	eacute:"Latin small letter e with acute",
+	ecirc:"Latin small letter e with circumflex",
+	euml:"Latin small letter e with diaeresis",
+	igrave:"Latin small letter i with grave",
+	iacute:"Latin small letter i with acute",
+	icirc:"Latin small letter i with circumflex",
+	iuml:"Latin small letter i with diaeresis",
+	eth:"Latin small letter eth",
+	ntilde:"Latin small letter n with tilde",
+	ograve:"Latin small letter o with grave",
+	oacute:"Latin small letter o with acute",
+	ocirc:"Latin small letter o with circumflex",
+	otilde:"Latin small letter o with tilde",
+	ouml:"Latin small letter o with diaeresis",
+	divide:"division sign",
+	oslash:"Latin small letter o with stroke\nLatin small letter o slash",
+	ugrave:"Latin small letter u with grave",
+	uacute:"Latin small letter u with acute",
+	ucirc:"Latin small letter u with circumflex",
+	uuml:"Latin small letter u with diaeresis",
+	yacute:"Latin small letter y with acute",
+	thorn:"Latin small letter thorn",
+	yuml:"Latin small letter y with diaeresis",
+
+// Greek Characters and Symbols
+	fnof:"Latin small f with hook\nfunction\nflorin",
+	Alpha:"Greek capital letter alpha",
+	Beta:"Greek capital letter beta",
+	Gamma:"Greek capital letter gamma",
+	Delta:"Greek capital letter delta",
+	Epsilon:"Greek capital letter epsilon",
+	Zeta:"Greek capital letter zeta",
+	Eta:"Greek capital letter eta",
+	Theta:"Greek capital letter theta",
+	Iota:"Greek capital letter iota",
+	Kappa:"Greek capital letter kappa",
+	Lambda:"Greek capital letter lambda",
+	Mu:"Greek capital letter mu",
+	Nu:"Greek capital letter nu",
+	Xi:"Greek capital letter xi",
+	Omicron:"Greek capital letter omicron",
+	Pi:"Greek capital letter pi",
+	Rho:"Greek capital letter rho",
+	Sigma:"Greek capital letter sigma",
+	Tau:"Greek capital letter tau",
+	Upsilon:"Greek capital letter upsilon",
+	Phi:"Greek capital letter phi",
+	Chi:"Greek capital letter chi",
+	Psi:"Greek capital letter psi",
+	Omega:"Greek capital letter omega",
+	alpha:"Greek small letter alpha",
+	beta:"Greek small letter beta",
+	gamma:"Greek small letter gamma",
+	delta:"Greek small letter delta",
+	epsilon:"Greek small letter epsilon",
+	zeta:"Greek small letter zeta",
+	eta:"Greek small letter eta",
+	theta:"Greek small letter theta",
+	iota:"Greek small letter iota",
+	kappa:"Greek small letter kappa",
+	lambda:"Greek small letter lambda",
+	mu:"Greek small letter mu",
+	nu:"Greek small letter nu",
+	xi:"Greek small letter xi",
+	omicron:"Greek small letter omicron",
+	pi:"Greek small letter pi",
+	rho:"Greek small letter rho",
+	sigmaf:"Greek small letter final sigma",
+	sigma:"Greek small letter sigma",
+	tau:"Greek small letter tau",
+	upsilon:"Greek small letter upsilon",
+	phi:"Greek small letter phi",
+	chi:"Greek small letter chi",
+	psi:"Greek small letter psi",
+	omega:"Greek small letter omega",
+	thetasym:"Greek small letter theta symbol",
+	upsih:"Greek upsilon with hook symbol",
+	piv:"Greek pi symbol",
+	bull:"bullet\nblack small circle",
+	hellip:"horizontal ellipsis\nthree dot leader",
+	prime:"prime\nminutes\nfeet",
+	Prime:"double prime\nseconds\ninches",
+	oline:"overline\nspacing overscore",
+	frasl:"fraction slash",
+	weierp:"script capital P\npower set\nWeierstrass p",
+	image:"blackletter capital I\nimaginary part",
+	real:"blackletter capital R\nreal part symbol",
+	trade:"trade mark sign",
+	alefsym:"alef symbol\nfirst transfinite cardinal",
+	larr:"leftwards arrow",
+	uarr:"upwards arrow",
+	rarr:"rightwards arrow",
+	darr:"downwards arrow",
+	harr:"left right arrow",
+	crarr:"downwards arrow with corner leftwards\ncarriage return",
+	lArr:"leftwards double arrow",
+	uArr:"upwards double arrow",
+	rArr:"rightwards double arrow",
+	dArr:"downwards double arrow",
+	hArr:"left right double arrow",
+	forall:"for all",
+	part:"partial differential",
+	exist:"there exists",
+	empty:"empty set\nnull set\ndiameter",
+	nabla:"nabla\nbackward difference",
+	isin:"element of",
+	notin:"not an element of",
+	ni:"contains as member",
+	prod:"n-ary product\nproduct sign",
+	sum:"n-ary sumation",
+	minus:"minus sign",
+	lowast:"asterisk operator",
+	radic:"square root\nradical sign",
+	prop:"proportional to",
+	infin:"infinity",
+	ang:"angle",
+	and:"logical and\nwedge",
+	or:"logical or\nvee",
+	cap:"intersection\ncap",
+	cup:"union\ncup","int":"integral",
+	there4:"therefore",
+	sim:"tilde operator\nvaries with\nsimilar to",
+	cong:"approximately equal to",
+	asymp:"almost equal to\nasymptotic to",
+	ne:"not equal to",
+	equiv:"identical to",
+	le:"less-than or equal to",
+	ge:"greater-than or equal to",
+	sub:"subset of",
+	sup:"superset of",
+	nsub:"not a subset of",
+	sube:"subset of or equal to",
+	supe:"superset of or equal to",
+	oplus:"circled plus\ndirect sum",
+	otimes:"circled times\nvector product",
+	perp:"up tack\northogonal to\nperpendicular",
+	sdot:"dot operator",
+	lceil:"left ceiling\nAPL upstile",
+	rceil:"right ceiling",
+	lfloor:"left floor\nAPL downstile",
+	rfloor:"right floor",
+	lang:"left-pointing angle bracket",
+	rang:"right-pointing angle bracket",
+	loz:"lozenge",
+	spades:"black spade suit",
+	clubs:"black club suit\nshamrock",
+	hearts:"black heart suit\nvalentine",
+	diams:"black diamond suit",
+	OElig:"Latin capital ligature OE",
+	oelig:"Latin small ligature oe",
+	Scaron:"Latin capital letter S with caron",
+	scaron:"Latin small letter s with caron",
+	Yuml:"Latin capital letter Y with diaeresis",
+	circ:"modifier letter circumflex accent",
+	tilde:"small tilde",
+	ensp:"en space",
+	emsp:"em space",
+	thinsp:"thin space",
+	zwnj:"zero width non-joiner",
+	zwj:"zero width joiner",
+	lrm:"left-to-right mark",
+	rlm:"right-to-left mark",
+	ndash:"en dash",
+	mdash:"em dash",
+	lsquo:"left single quotation mark",
+	rsquo:"right single quotation mark",
+	sbquo:"single low-9 quotation mark",
+	ldquo:"left double quotation mark",
+	rdquo:"right double quotation mark",
+	bdquo:"double low-9 quotation mark",
+	dagger:"dagger",
+	Dagger:"double dagger",
+	permil:"per mille sign",
+	lsaquo:"single left-pointing angle quotation mark",
+	rsaquo:"single right-pointing angle quotation mark",
+	euro:"euro sign"
+})
diff --git a/dojox/editor/plugins/nls/nb/TableDialog.js b/dojox/editor/plugins/nls/nb/TableDialog.js
index 8d3ad55..0d04820 100644
--- a/dojox/editor/plugins/nls/nb/TableDialog.js
+++ b/dojox/editor/plugins/nls/nb/TableDialog.js
@@ -1 +1,29 @@
-({"buttonSet":"Definer","insertTableTitle":"Sett inn tabell","insertTableRowAfterLabel":"Legg til rad etter","center":"midtstill","deleteTableColumnLabel":"Slett kolonne","right":"høyre","insertTableColumnBeforeLabel":"Legg til kolonne foran","tableWidth":"Tabellbredde:","buttonInsert":"Sett inn","default":"standard","align":"Juster:","insertTableRowBeforeLabel":"Legg til rad foran","cellSpacing":"Celleavstand:","pixels":"piksler","selectTableLabel":"Velg tabell","rows":"Rader:","modifyT [...]
\ No newline at end of file
+({
+	insertTableTitle: "Sett inn tabell",
+	modifyTableTitle: "Endre tabell",
+	rows: "Rader:",
+	columns: "Kolonner:",
+	align: "Juster:",
+	cellPadding: "Celleutfylling:",
+	cellSpacing: "Celleavstand:",
+	tableWidth: "Tabellbredde:",
+	backgroundColor: "Bakgrunnsfarge:",
+	borderColor: "Kantlinjefarge:",
+	borderThickness: "Kanttykkelse",
+	percent: "prosent",
+	pixels: "piksler",
+	"default": "standard",
+	left: "venstre",
+	center: "midtstill",
+	right: "høyre",
+	buttonSet: "Definer", // translated elsewhere?
+	buttonInsert: "Sett inn",
+
+	selectTableLabel: "Velg tabell",
+	insertTableRowBeforeLabel: "Legg til rad foran",
+	insertTableRowAfterLabel: "Legg til rad etter",
+	insertTableColumnBeforeLabel: "Legg til kolonne foran",
+	insertTableColumnAfterLabel: "Legg til kolonne etter",
+	deleteTableRowLabel: "Slett rad",
+	deleteTableColumnLabel: "Slett kolonne"
+})
diff --git a/dojox/editor/plugins/nls/nl/TableDialog.js b/dojox/editor/plugins/nls/nl/TableDialog.js
index bdb4ce9..16f23ea 100644
--- a/dojox/editor/plugins/nls/nl/TableDialog.js
+++ b/dojox/editor/plugins/nls/nl/TableDialog.js
@@ -1 +1,29 @@
-({"buttonSet":"Instellen","insertTableTitle":"Tabel invoegen","insertTableRowAfterLabel":"Rij onder toevoegen","center":"gecentreerd","deleteTableColumnLabel":"Kolom wissen","right":"rechts","insertTableColumnBeforeLabel":"Kolom voor toevoegen","tableWidth":"Tabelbreedte:","buttonInsert":"invoegen","default":"standaard","align":"Uitlijnen","insertTableRowBeforeLabel":"Rij boven toevoegen","cellSpacing":"Celspatiëring:","pixels":"pixels","selectTableLabel":"Tabel selecteren","rows":"Rijen [...]
\ No newline at end of file
+({
+	insertTableTitle: "Tabel invoegen",
+	modifyTableTitle: "Tabel wijzigen",
+	rows: "Rijen",
+	columns: "Kolommen",
+	align: "Uitlijnen",
+	cellPadding: "Celopvulling:",
+	cellSpacing: "Celspatiëring:",
+	tableWidth: "Tabelbreedte:",
+	backgroundColor: "Achtergrondkleur:",
+	borderColor: "Randkleur",
+	borderThickness: "Randdikte",
+	percent: "percent",
+	pixels: "pixels",
+	"default": "standaard",
+	left: "links",
+	center: "gecentreerd",
+	right: "rechts",
+	buttonSet: "Instellen", // translated elsewhere?
+	buttonInsert: "invoegen",
+
+	selectTableLabel: "Tabel selecteren",
+	insertTableRowBeforeLabel: "Rij boven toevoegen",
+	insertTableRowAfterLabel: "Rij onder toevoegen",
+	insertTableColumnBeforeLabel: "Kolom voor toevoegen",
+	insertTableColumnAfterLabel: "Kolom achter toevoegen",
+	deleteTableRowLabel: "Rij wissen",
+	deleteTableColumnLabel: "Kolom wissen"
+})
diff --git a/dojox/editor/plugins/nls/pl/Breadcrumb.js b/dojox/editor/plugins/nls/pl/Breadcrumb.js
index d4360df..8f58e55 100644
--- a/dojox/editor/plugins/nls/pl/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/pl/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"Zaznacz treść","deleteElement":"Usuń element","moveEnd":"Przenieś kursor na koniec","deleteContents":"Usuń treść","nodeActions":"${nodeName} - działania","selectElement":"Zaznacz element","moveStart":"Przenieś kursor na początek"})
\ No newline at end of file
+({
+	"nodeActions": "${nodeName} - działania",
+	"selectContents": "Zaznacz treść",
+	"selectElement": "Zaznacz element",
+	"deleteElement": "Usuń element",
+	"deleteContents": "Usuń treść",
+	"moveStart": "Przenieś kursor na początek",
+	"moveEnd": "Przenieś kursor na koniec"
+})
+
diff --git a/dojox/editor/plugins/nls/pl/FindReplace.js b/dojox/editor/plugins/nls/pl/FindReplace.js
index 39184d4..eabf728 100644
--- a/dojox/editor/plugins/nls/pl/FindReplace.js
+++ b/dojox/editor/plugins/nls/pl/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"Do tyłu","findReplace":"Przełącz znajdowanie/zastępowanie","replaceAll":"Wszystkie wystąpienia","replaceDialogText":"Zastąpione wystąpienia: ${0}.","replaceButton":"Zastąp","findButton":"Znajdź","findLabel":"Znajdź:","matchCase":"Uwzględniaj wielkość liter","replaceLabel":"Zastąp przez:"})
\ No newline at end of file
+({
+	"findLabel": "Znajdź:",
+	"replaceLabel": "Zastąp przez:",
+	"findReplace": "Przełącz znajdowanie/zastępowanie",
+	"matchCase": "Uwzględniaj wielkość liter", 
+	"backwards": "Do tyłu",
+	"replaceAll": "Wszystkie wystąpienia", 
+	"findButton": "Znajdź",
+	"replaceButton": "Zastąp",
+	"replaceDialogText": "Zastąpione wystąpienia: ${0}."
+})
+
diff --git a/dojox/editor/plugins/nls/pl/InsertEntity.js b/dojox/editor/plugins/nls/pl/InsertEntity.js
index 9136a8d..084dc91 100644
--- a/dojox/editor/plugins/nls/pl/InsertEntity.js
+++ b/dojox/editor/plugins/nls/pl/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"Wstaw symbol"})
\ No newline at end of file
+({
+	insertEntity: "Wstaw symbol"
+})
+
diff --git a/dojox/editor/plugins/nls/pl/PageBreak.js b/dojox/editor/plugins/nls/pl/PageBreak.js
index a8f6b00..07dcf7f 100644
--- a/dojox/editor/plugins/nls/pl/PageBreak.js
+++ b/dojox/editor/plugins/nls/pl/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"Podział strony"})
\ No newline at end of file
+({
+	"pageBreak": "Podział strony"
+})
+
diff --git a/dojox/editor/plugins/nls/pl/Preview.js b/dojox/editor/plugins/nls/pl/Preview.js
index 64cdc8b..3cb01c2 100644
--- a/dojox/editor/plugins/nls/pl/Preview.js
+++ b/dojox/editor/plugins/nls/pl/Preview.js
@@ -1 +1,4 @@
-({"preview":"Podgląd"})
\ No newline at end of file
+({
+	"preview": "Podgląd"
+})
+
diff --git a/dojox/editor/plugins/nls/pl/Save.js b/dojox/editor/plugins/nls/pl/Save.js
index 7f87eb2..3c1d4b0 100644
--- a/dojox/editor/plugins/nls/pl/Save.js
+++ b/dojox/editor/plugins/nls/pl/Save.js
@@ -1 +1,4 @@
-({"save":"Zapisz"})
\ No newline at end of file
+({
+	"save": "Zapisz"
+})
+
diff --git a/dojox/editor/plugins/nls/pl/ShowBlockNodes.js b/dojox/editor/plugins/nls/pl/ShowBlockNodes.js
index 79d057c..26fb420 100644
--- a/dojox/editor/plugins/nls/pl/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/pl/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"Pokaż elementy bloków HTML"})
\ No newline at end of file
+({
+	"showBlockNodes": "Pokaż elementy bloków HTML"
+})
+
diff --git a/dojox/editor/plugins/nls/pl/Smiley.js b/dojox/editor/plugins/nls/pl/Smiley.js
index ba3ac33..db95edf 100644
--- a/dojox/editor/plugins/nls/pl/Smiley.js
+++ b/dojox/editor/plugins/nls/pl/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"śmiech","emoticonCool":"na luzie","emoticonTongue":"język","emoticonCrying":"płacz","emoticonOops":"oj","emoticonFrown":"niezadowolenie","emoticonAngry":"złość","emoticonShy":"nieśmiałość","emoticonNo":"Nie","emoticonAngel":"anioł","smiley":"Wstaw emotikon","emoticonIdea":"pomysł","emoticonEyebrow":"brew","emoticonSmile":"uśmiech","emoticonWink":"mrugnięcie","emoticonYes":"Tak","emoticonGrin":"szeroki uśmiech","emoticonGoofy":"niezdarność","emoticonHalf":"niesmak"})
\ No newline at end of file
+({
+	smiley: "Wstaw emotikon",
+	emoticonSmile: "uśmiech",
+	emoticonLaughing: "śmiech",
+	emoticonWink: "mrugnięcie",
+	emoticonGrin: "szeroki uśmiech",
+	emoticonCool: "na luzie",
+	emoticonAngry: "złość",  
+	emoticonHalf: "niesmak", 
+	emoticonEyebrow: "brew",
+	emoticonFrown: "niezadowolenie",
+	emoticonShy: "nieśmiałość",
+	emoticonGoofy: "niezdarność",
+	emoticonOops: "oj",
+	emoticonTongue: "język",
+	emoticonIdea: "pomysł",
+	emoticonYes: "Tak",
+	emoticonNo: "Nie",	
+	emoticonAngel: "anioł",
+	emoticonCrying: "płacz"
+})
+
diff --git a/dojox/editor/plugins/nls/pl/TableDialog.js b/dojox/editor/plugins/nls/pl/TableDialog.js
index 26c009f..710ad5e 100644
--- a/dojox/editor/plugins/nls/pl/TableDialog.js
+++ b/dojox/editor/plugins/nls/pl/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Ustaw","insertTableTitle":"Wstawianie tabeli","insertTableRowAfterLabel":"Dodaj wiersz po","center":"środek","deleteTableColumnLabel":"Usuń kolumnę","right":"prawa strona","insertTableColumnBeforeLabel":"Dodaj kolumnę przed","tableWidth":"Szerokość tabeli:","buttonInsert":"Wstaw","default":"domyślna","align":"Wyrównanie:","insertTableRowBeforeLabel":"Dodaj wiersz przed","cellSpacing":"Odstępy między komórkami:","pixels":"piksle","selectTableLabel":"Wybierz tabelę","rows":" [...]
\ No newline at end of file
+({
+	insertTableTitle: "Wstawianie tabeli",
+	modifyTableTitle: "Modyfikowanie tabeli",
+	rows: "Wiersze:",
+	columns: "Kolumny:",
+	align: "Wyrównanie:",
+	cellPadding: "Dopełnianie komórek:",
+	cellSpacing: "Odstępy między komórkami:",
+	tableWidth: "Szerokość tabeli:",
+	backgroundColor: "Kolor tła:",
+	borderColor: "Kolor ramki:",
+	borderThickness: "Grubość ramki",
+	percent: "procent",
+	pixels: "piksle",
+	"default": "domyślna",
+	left: "lewa strona",
+	center: "środek",
+	right: "prawa strona",
+	buttonSet: "Ustaw", // translated elsewhere?
+	buttonInsert: "Wstaw",
+
+	selectTableLabel: "Wybierz tabelę",
+	insertTableRowBeforeLabel: "Dodaj wiersz przed",
+	insertTableRowAfterLabel: "Dodaj wiersz po",
+	insertTableColumnBeforeLabel: "Dodaj kolumnę przed",
+	insertTableColumnAfterLabel: "Dodaj kolumnę po",
+	deleteTableRowLabel: "Usuń wiersz",
+	deleteTableColumnLabel: "Usuń kolumnę"
+})
+
diff --git a/dojox/editor/plugins/nls/pl/latinEntities.js b/dojox/editor/plugins/nls/pl/latinEntities.js
index 73d071e..c1385f8 100644
--- a/dojox/editor/plugins/nls/pl/latinEntities.js
+++ b/dojox/editor/plugins/nls/pl/latinEntities.js
@@ -1 +1,257 @@
-({"le":"mniejsze niż lub równe","prod":"iloczyn n elementów\nznak iloczynu","zwj":"łącznik o zerowej szerokości","mdash":"pauza","frasl":"kreska ułamkowa","upsih":"grecka litera ipsylon z symbolem haczyka","prop":"proporcjonalnie do","middot":"kropka środkowa\ngruziński przecinek\ngrecka kropka środkowa","hellip":"wielokropek\ntrzy kropki","eta":"grecka mała litera eta","iacute":"łacińska mała litera i z akcentem ostrym","yen":"znak jena\nznak yuana","rlm":"znacznik zapisu od prawej do l [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"odwrócony wykrzyknik",
+	cent:"znak centa",
+	pound:"znak funta",
+	curren:"znak waluty",
+	yen:"znak jena\nznak yuana",
+	brvbar:"przerwana kreska\nprzerwana pionowa kreska",
+	sect:"znak sekcji",
+	uml:"diereza\ndiereza rozdzielająca",
+	copy:"znak praw autorskich",
+	ordf:"znak liczby rodzaju żeńskiego",
+	laquo:"lewy cudzysłów trójkątny\nlewy guillemet",
+	not:"znak negacji",
+	shy:"łącznik miękki\nłącznik opcjonalny",
+	reg:"symbol zastrzeżenia\nsymbol zastrzeżonego znaku towarowego",
+	macr:"makron\nmakron rozdzielający\nnadkreślenie\nkreska górna APL",
+	deg:"znak stopni",
+	plusmn:"znak plus-minus\nznak zakresu wartości przybliżonej",
+	sup2:"indeks górny dwa\ncyfra dwa w indeksie górnym\nkwadrat",
+	sup3:"indeks górny trzy\ncyfra trzy w indeksie górnym\nsześcian",
+	acute:"akcent ostry\nodstęp ostry",
+	micro:"znak mikro",
+	para:"znak pilcrow\nznak akapitu",
+	middot:"kropka środkowa\ngruziński przecinek\ngrecka kropka środkowa",
+	cedil:"cedilla\nodstęp cedilla",
+	sup1:"indeks górny jeden\ncyfra jeden w indeksie górnym",
+	ordm:"znak liczby rodzaju męskiego",
+	raquo:"prawy cudzysłów trójkątny\nprawy guillemet",
+	frac14:"znak ułamka jedna czwarta\nułamek jedna czwarta",
+	frac12:"znak ułamka jedna druga\nułamek jedna druga",
+	frac34:"znak ułamka trzy czwarte\nułamek trzy czwarte",
+	iquest:"odwrócony znak zapytania\nodwrotny znak zapytania",
+	Agrave:"łacińska wielka litera A z symbolem gravis\nłacińska wielka litera A z akcentem ciężkim",
+	Aacute:"łacińska wielka litera A z akcentem ostrym",
+	Acirc:"łacińska wielka litera A z daszkiem",
+	Atilde:"łacińska wielka litera A z tyldą",
+	Auml:"łacińska wielka litera A z diarezą",
+	Aring:"łacińska wielka litera A z pierścieniem powyżej\nłacińska wielka litera A z pierścieniem",
+	AElig:"łacińska wielka litera AE\nłacińska ligatura wielkich liter AE",
+	Ccedil:"łacińska wielka litera C z cedillą",
+	Egrave:"łacińska wielka litera E z akcentem ciężkim",
+	Eacute:"łacińska wielka litera E z akcentem ostrym",
+	Ecirc:"łacińska wielka litera E z daszkiem",
+	Euml:"łacińska wielka litera E z diarezą",
+	Igrave:"łacińska wielka litera I z akcentem ciężkim",
+	Iacute:"łacińska wielka litera I z akcentem ostrym",
+	Icirc:"łacińska wielka litera I z daszkiem",
+	Iuml:"łacińska wielka litera I z diarezą",
+	ETH:"łacińska wielka litera ETH",
+	Ntilde:"łacińska wielka litera N z tyldą",
+	Ograve:"łacińska wielka litera O z akcentem ciężkim",
+	Oacute:"łacińska wielka litera O z akcentem ostrym",
+	Ocirc:"łacińska wielka litera O z daszkiem",
+	Otilde:"łacińska wielka litera O z tyldą",
+	Ouml:"łacińska wielka litera O z diarezą",
+	times:"znak mnożenia",
+	Oslash:"łacińska wielka litera O z przekreśleniem\nłacińska wielka litera O z ukośnikiem",
+	Ugrave:"łacińska wielka litera U z akcentem ciężkim",
+	Uacute:"łacińska wielka litera U z akcentem ostrym",
+	Ucirc:"łacińska wielka litera U z daszkiem",
+	Uuml:"łacińska wielka litera U z diarezą",
+	Yacute:"łacińska wielka litera Y z akcentem ostrym",
+	THORN:"łacińska wielka litera THORN",
+	szlig:"łacińska mała litera ostre s\ness-zed",
+	agrave:"łacińska mała litera a z symbolem gravis\nłacińska mała litera a z akcentem ciężkim",
+	aacute:"łacińska mała litera a z akcentem ostrym",
+	acirc:"łacińska mała litera a z daszkiem",
+	atilde:"łacińska mała litera a z tyldą",
+	auml:"łacińska mała litera a z diarezą",
+	aring:"łacińska mała litera a z pierścieniem powyżej\nłacińska mała litera a z pierścieniem",
+	aelig:"łacińska mała litera ae\nłacińska ligatura małych liter ae",
+	ccedil:"łacińska mała litera c z cedillą",
+	egrave:"łacińska mała litera e z akcentem ciężkim",
+	eacute:"łacińska mała litera e z akcentem ostrym",
+	ecirc:"łacińska mała litera e z daszkiem",
+	euml:"łacińska mała litera e z diarezą",
+	igrave:"łacińska mała litera i z akcentem ciężkim",
+	iacute:"łacińska mała litera i z akcentem ostrym",
+	icirc:"łacińska mała litera i z daszkiem",
+	iuml:"łacińska mała litera i z diarezą",
+	eth:"łacińska mała litera eth",
+	ntilde:"łacińska mała litera n z tyldą",
+	ograve:"łacińska mała litera o z akcentem ciężkim",
+	oacute:"łacińska mała litera o z akcentem ostrym",
+	ocirc:"łacińska mała litera o z daszkiem",
+	otilde:"łacińska mała litera o z tyldą",
+	ouml:"łacińska mała litera o z diarezą",
+	divide:"znak dzielenia",
+	oslash:"łacińska mała litera o z przekreśleniem\nłacińska mała litera o z ukośnikiem",
+	ugrave:"łacińska mała litera u z akcentem ciężkim",
+	uacute:"łacińska mała litera u z akcentem ostrym",
+	ucirc:"łacińska mała litera u z daszkiem",
+	uuml:"łacińska mała litera u z diarezą",
+	yacute:"łacińska mała litera y z akcentem ostrym",
+	thorn:"łacińska mała litera thorn",
+	yuml:"łacińska mała litera y z diarezą",
+
+// Greek Characters and Symbols
+	fnof:"łacińska mała litera f z haczykiem\nfunkcja\nfloren",
+	Alpha:"grecka wielka litera alfa",
+	Beta:"grecka wielka litera beta",
+	Gamma:"grecka wielka litera gamma",
+	Delta:"grecka wielka litera delta",
+	Epsilon:"grecka wielka litera epsilon",
+	Zeta:"grecka wielka litera dzeta",
+	Eta:"grecka wielka litera eta",
+	Theta:"grecka wielka litera theta",
+	Iota:"grecka wielka litera jota",
+	Kappa:"grecka wielka litera kappa",
+	Lambda:"grecka wielka litera lambda",
+	Mu:"grecka wielka litera my",
+	Nu:"grecka wielka litera ni",
+	Xi:"grecka wielka litera ksi",
+	Omicron:"grecka wielka litera omikron",
+	Pi:"grecka wielka litera pi",
+	Rho:"grecka wielka litera rho",
+	Sigma:"grecka wielka litera sigma",
+	Tau:"grecka wielka litera tau",
+	Upsilon:"grecka wielka litera ipsylon",
+	Phi:"grecka wielka litera phi",
+	Chi:"grecka wielka litera chi",
+	Psi:"grecka wielka litera psi",
+	Omega:"grecka wielka litera omega",
+	alpha:"grecka wielka litera alfa",
+	beta:"grecka mała litera beta",
+	gamma:"grecka mała litera gamma",
+	delta:"grecka mała litera delta",
+	epsilon:"grecka mała litera epsilon",
+	zeta:"grecka mała litera dzeta",
+	eta:"grecka mała litera eta",
+	theta:"grecka mała litera theta",
+	iota:"grecka mała litera jota",
+	kappa:"grecka mała litera kappa",
+	lambda:"grecka mała litera lambda",
+	mu:"grecka mała litera my",
+	nu:"grecka mała litera ni",
+	xi:"grecka mała litera ksi",
+	omicron:"grecka mała litera omikron",
+	pi:"grecka mała litera phi",
+	rho:"grecka mała litera rho",
+	sigmaf:"grecka mała litera końcowa sigma",
+	sigma:"grecka mała litera sigma",
+	tau:"grecka mała litera tau",
+	upsilon:"grecka mała litera ipsylon",
+	phi:"grecka mała litera phi",
+	chi:"grecka mała litera chi",
+	psi:"grecka mała litera psi",
+	omega:"grecka mała litera omega",
+	thetasym:"grecka mała litera theta (symbol)",
+	upsih:"grecka litera ipsylon z symbolem haczyka",
+	piv:"grecki symbol pi",
+	bull:"znacznik podpunktu\nmałe czarne kółko",
+	hellip:"wielokropek\ntrzy kropki",
+	prime:"prim\nminuty\nstopy",
+	Prime:"bis\nsekundy\ncale",
+	oline:"nadkreślenie\nnadkreślenie tworzące odstęp",
+	frasl:"kreska ułamkowa",
+	weierp:"odręcznie pisana wielka litera P\nzbiór potęgowy\nP Weierstrassa",
+	image:"gotycka wielka litera I\nczęść urojona liczby zespolonej",
+	real:"gotycka wielka litera R\nsymbol części rzeczywistej liczby zespolonej",
+	trade:"symbol znaku zastrzeżonego",
+	alefsym:"znak alef\npoczątkowa liczba porządkowa",
+	larr:"strzałka w lewo",
+	uarr:"strzałka w górę",
+	rarr:"strzałka w prawo",
+	darr:"strzałka w dół",
+	harr:"strzałka w lewo i w prawo",
+	crarr:"strzałka w dół z rogiem w lewo\npowrót karetki",
+	lArr:"podwójna strzałka w lewo",
+	uArr:"podwójna strzałka w górę",
+	rArr:"podwójna strzałka w prawo",
+	dArr:"podwójna strzałka w dół",
+	hArr:"podwójna strzałka w lewo i w prawo",
+	forall:"dla każdego",
+	part:"pochodna cząstkowa",
+	exist:"istnieje",
+	empty:"zbiór pusty\nzbiór miary zero\nśrednica",
+	nabla:"nabla\nkoneksja",
+	isin:"należy do",
+	notin:"nie należy do",
+	ni:"zawiera",
+	prod:"iloczyn n elementów\nznak iloczynu",
+	sum:"suma n elementów",
+	minus:"znak minus",
+	lowast:"operator gwiazdka",
+	radic:"pierwiastek kwadratowy\nznak pierwiastka",
+	prop:"proporcjonalnie do",
+	infin:"nieskończoność",
+	ang:"kąt",
+	and:"iloczyn logiczny\nklin",
+	or:"suma logiczna\nlitera v",
+	cap:"część wspólna zbiorów\nczepek",
+	cup:"suma zbiorów\nfiliżanka","int":"całka",
+	there4:"dlatego",
+	sim:"operator tylda\nzmienia się w granicach\nokoło",
+	cong:"równa się w przybliżeniu",
+	asymp:"prawie równa się\nasymptotyczne do",
+	ne:"nie równa się",
+	equiv:"takie same jak",
+	le:"mniejsze niż lub równe",
+	ge:"większe niż lub równe",
+	sub:"jest podzbiorem",
+	sup:"jest nadzbiorem",
+	nsub:"nie jest podzbiorem",
+	sube:"jest podzbiorem lub równa się",
+	supe:"jest nadzbiorem lub równa się",
+	oplus:"znak plus w okręgu\nsuma bezpośrednia",
+	otimes:"znak mnożenia w okręgu\niloczyn wektorów",
+	perp:"odwrócona litera T\nprostopadłe do\nprostopadłe",
+	sdot:"operator kropka",
+	lceil:"lewy sufit\nhaczyk górny APL",
+	rceil:"prawy sufit",
+	lfloor:"lewa podłoga\nhaczyk dolny APL",
+	rfloor:"prawa podłoga",
+	lang:"lewy nawias trójkątny",
+	rang:"prawy nawias trójkątny",
+	loz:"romb",
+	spades:"symbol pik",
+	clubs:"symbol trefl\nkoniczyna",
+	hearts:"symbol kier\nserce",
+	diams:"symbol karo",
+	OElig:"łacińska ligatura wielkich liter OE",
+	oelig:"łacińska ligatura małych liter oe",
+	Scaron:"łacińska wielka litera S z daszkiem odwróconym",
+	scaron:"łacińska mała litera s z daszkiem odwróconym",
+	Yuml:"łacińska wielka litera Y z diarezą",
+	circ:"modyfikator litery - akcent w formie daszka",
+	tilde:"mała tylda",
+	ensp:"spacja średnia",
+	emsp:"spacja długa",
+	thinsp:"spacja krótka",
+	zwnj:"symbol rozdzielający o zerowej szerokości",
+	zwj:"łącznik o zerowej szerokości",
+	lrm:"znacznik zapisu od lewej do prawej",
+	rlm:"znacznik zapisu od prawej do lewej",
+	ndash:"półpauza",
+	mdash:"pauza",
+	lsquo:"lewy pojedynczy cudzysłów",
+	rsquo:"prawy pojedynczy cudzysłów",
+	sbquo:"pojedynczy cudzysłów dolny",
+	ldquo:"lewy podwójny cudzysłów",
+	rdquo:"prawy podwójny cudzysłów",
+	bdquo:"podwójny cudzysłów dolny",
+	dagger:"krzyżyk",
+	Dagger:"podwójny krzyżyk",
+	permil:"promile",
+	lsaquo:"pojedynczy lewy cudzysłów trójkątny",
+	rsaquo:"pojedynczy prawy cudzysłów trójkątny",
+	euro:"znak euro"
+})
+
diff --git a/dojox/editor/plugins/nls/pt-pt/TableDialog.js b/dojox/editor/plugins/nls/pt-pt/TableDialog.js
index 76394e4..2b81fe1 100644
--- a/dojox/editor/plugins/nls/pt-pt/TableDialog.js
+++ b/dojox/editor/plugins/nls/pt-pt/TableDialog.js
@@ -1 +1,29 @@
-({"buttonSet":"Definir","insertTableTitle":"Inserir tabela","insertTableRowAfterLabel":"Adicionar linha depois","center":"centro","deleteTableColumnLabel":"Eliminar coluna","right":"direita","insertTableColumnBeforeLabel":"Adicionar coluna antes","tableWidth":"Largura da tabela:","buttonInsert":"Inserir","default":"predefinição","align":"Alinhar:","insertTableRowBeforeLabel":"Adicionar linha antes","cellSpacing":"Espaçamento de células:","pixels":"píxeis","selectTableLabel":"Seleccionar  [...]
\ No newline at end of file
+({
+	insertTableTitle: "Inserir tabela",
+	modifyTableTitle: "Modificar tabela",
+	rows: "Linhas:",
+	columns: "Colunas:",
+	align: "Alinhar:",
+	cellPadding: "Preenchimento de células:",
+	cellSpacing: "Espaçamento de células:",
+	tableWidth: "Largura da tabela:",
+	backgroundColor: "Cor de segundo plano:",
+	borderColor: "Cor do contorno:",
+	borderThickness: "Espessura do contorno",
+	percent: "percentagem",
+	pixels: "píxeis",
+	"default": "predefinição",
+	left: "esquerda",
+	center: "centro",
+	right: "direita",
+	buttonSet: "Definir", // translated elsewhere?
+	buttonInsert: "Inserir",
+
+	selectTableLabel: "Seleccionar tabela",
+	insertTableRowBeforeLabel: "Adicionar linha antes",
+	insertTableRowAfterLabel: "Adicionar linha depois",
+	insertTableColumnBeforeLabel: "Adicionar coluna antes",
+	insertTableColumnAfterLabel: "Adicionar coluna depois",
+	deleteTableRowLabel: "Eliminar linha",
+	deleteTableColumnLabel: "Eliminar coluna"
+})
diff --git a/dojox/editor/plugins/nls/pt/Breadcrumb.js b/dojox/editor/plugins/nls/pt/Breadcrumb.js
index 1f5fe1a..ffd24e1 100644
--- a/dojox/editor/plugins/nls/pt/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/pt/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"Selecionar Conteúdo","deleteElement":"Excluir Elemento","moveEnd":"Mover Cursor para o Final","deleteContents":"Excluir Conteúdo","nodeActions":"${nodeName} Ações","selectElement":"Selecionar Elemento","moveStart":"Mover Cursor para o Início"})
\ No newline at end of file
+({
+	"nodeActions": "${nodeName} Ações",
+	"selectContents": "Selecionar Conteúdo",
+	"selectElement": "Selecionar Elemento",
+	"deleteElement": "Excluir Elemento",
+	"deleteContents": "Excluir Conteúdo",
+	"moveStart": "Mover Cursor para o Início",
+	"moveEnd": "Mover Cursor para o Final"
+})
+
diff --git a/dojox/editor/plugins/nls/pt/FindReplace.js b/dojox/editor/plugins/nls/pt/FindReplace.js
index cf5a942..7b9a364 100644
--- a/dojox/editor/plugins/nls/pt/FindReplace.js
+++ b/dojox/editor/plugins/nls/pt/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"Retroceder","findReplace":"Comutar Localizar/Substituir","replaceAll":"Todas as Ocorrências","replaceDialogText":"${0} ocorrências substituídas.","replaceButton":"Substituir","findButton":"Localizar","findLabel":"Localizar:","matchCase":"Caso de Correspondência","replaceLabel":"Substituir por:"})
\ No newline at end of file
+({
+	"findLabel": "Localizar:",
+	"replaceLabel": "Substituir por:",
+	"findReplace": "Comutar Localizar/Substituir",
+	"matchCase": "Caso de Correspondência", 
+	"backwards": "Retroceder",
+	"replaceAll": "Todas as Ocorrências", 
+	"findButton": "Localizar",
+	"replaceButton": "Substituir",
+	"replaceDialogText": "${0} ocorrências substituídas."
+})
+
diff --git a/dojox/editor/plugins/nls/pt/InsertEntity.js b/dojox/editor/plugins/nls/pt/InsertEntity.js
index 33eba66..b76fa26 100644
--- a/dojox/editor/plugins/nls/pt/InsertEntity.js
+++ b/dojox/editor/plugins/nls/pt/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"Inserir Símbolo"})
\ No newline at end of file
+({
+	insertEntity: "Inserir Símbolo"
+})
+
diff --git a/dojox/editor/plugins/nls/pt/PageBreak.js b/dojox/editor/plugins/nls/pt/PageBreak.js
index 32e538e..417a561 100644
--- a/dojox/editor/plugins/nls/pt/PageBreak.js
+++ b/dojox/editor/plugins/nls/pt/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"Quebra de Página"})
\ No newline at end of file
+({
+	"pageBreak": "Quebra de Página"
+})
+
diff --git a/dojox/editor/plugins/nls/pt/Preview.js b/dojox/editor/plugins/nls/pt/Preview.js
index f73f586..2b7fd5e 100644
--- a/dojox/editor/plugins/nls/pt/Preview.js
+++ b/dojox/editor/plugins/nls/pt/Preview.js
@@ -1 +1,4 @@
-({"preview":"Visualização"})
\ No newline at end of file
+({
+	"preview": "Visualização"
+})
+
diff --git a/dojox/editor/plugins/nls/pt/Save.js b/dojox/editor/plugins/nls/pt/Save.js
index ea1c362..60ffb59 100644
--- a/dojox/editor/plugins/nls/pt/Save.js
+++ b/dojox/editor/plugins/nls/pt/Save.js
@@ -1 +1,4 @@
-({"save":"Salvar"})
\ No newline at end of file
+({
+	"save": "Salvar"
+})
+
diff --git a/dojox/editor/plugins/nls/pt/ShowBlockNodes.js b/dojox/editor/plugins/nls/pt/ShowBlockNodes.js
index 870d951..4235eb3 100644
--- a/dojox/editor/plugins/nls/pt/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/pt/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"Mostrar Elementos de Bloco HTML"})
\ No newline at end of file
+({
+	"showBlockNodes": "Mostrar Elementos de Bloco HTML"
+})
+
diff --git a/dojox/editor/plugins/nls/pt/Smiley.js b/dojox/editor/plugins/nls/pt/Smiley.js
index 3795f28..22d76a5 100644
--- a/dojox/editor/plugins/nls/pt/Smiley.js
+++ b/dojox/editor/plugins/nls/pt/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"gargalhando","emoticonCool":"legal","emoticonTongue":"mostrando a língua","emoticonCrying":"chorando","emoticonOops":"surpreso","emoticonFrown":"sobrancelhas franzidas","emoticonAngry":"bravo","emoticonShy":"envergonhado","emoticonNo":"não","emoticonAngel":"angelical","smiley":"Inserir Emoticon","emoticonIdea":"ideia","emoticonEyebrow":"sarcástico","emoticonSmile":"sorriso","emoticonWink":"piscando","emoticonYes":"sim","emoticonGrin":"sorriso largo","emoticonGoofy": [...]
\ No newline at end of file
+({
+	smiley: "Inserir Emoticon",
+	emoticonSmile: "sorriso",
+	emoticonLaughing: "gargalhando",
+	emoticonWink: "piscando",
+	emoticonGrin: "sorriso largo",
+	emoticonCool: "legal",
+	emoticonAngry: "bravo",  
+	emoticonHalf: "confuso", 
+	emoticonEyebrow: "sarcástico",
+	emoticonFrown: "sobrancelhas franzidas",
+	emoticonShy: "envergonhado",
+	emoticonGoofy: "tonto",
+	emoticonOops: "surpreso",
+	emoticonTongue: "mostrando a língua",
+	emoticonIdea: "ideia",
+	emoticonYes: "sim",
+	emoticonNo: "não",	
+	emoticonAngel: "angelical",
+	emoticonCrying: "chorando"
+})
+
diff --git a/dojox/editor/plugins/nls/pt/TableDialog.js b/dojox/editor/plugins/nls/pt/TableDialog.js
index fd4affc..5258c26 100644
--- a/dojox/editor/plugins/nls/pt/TableDialog.js
+++ b/dojox/editor/plugins/nls/pt/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Configurar","insertTableTitle":"Inserir Tabela","insertTableRowAfterLabel":"Incluir Linha Depois","center":"centro","deleteTableColumnLabel":"Excluir Coluna","right":"direita","insertTableColumnBeforeLabel":"Incluir Coluna Antes","tableWidth":"Largura da Tabela:","buttonInsert":"Inserir","default":"default","align":"Alinhar:","insertTableRowBeforeLabel":"Incluir Linha Antes","cellSpacing":"Espaçamento de Célula:","pixels":"pixels","selectTableLabel":"Selecionar Tabela","ro [...]
\ No newline at end of file
+({
+	insertTableTitle: "Inserir Tabela",
+	modifyTableTitle: "Modificar Tabela",
+	rows: "Linhas:",
+	columns: "Colunas:",
+	align: "Alinhar:",
+	cellPadding: "Preenchimento de Célula:",
+	cellSpacing: "Espaçamento de Célula:",
+	tableWidth: "Largura da Tabela:",
+	backgroundColor: "Cor do Plano de Fundo:",
+	borderColor: "Cor da Borda:",
+	borderThickness: "Grossura da Borda",
+	percent: "percentual",
+	pixels: "pixels",
+	"default": "default",
+	left: "esquerda",
+	center: "centro",
+	right: "direita",
+	buttonSet: "Configurar", // translated elsewhere?
+	buttonInsert: "Inserir",
+
+	selectTableLabel: "Selecionar Tabela",
+	insertTableRowBeforeLabel: "Incluir Linha Antes",
+	insertTableRowAfterLabel: "Incluir Linha Depois",
+	insertTableColumnBeforeLabel: "Incluir Coluna Antes",
+	insertTableColumnAfterLabel: "Incluir Coluna Depois",
+	deleteTableRowLabel: "Excluir Linha",
+	deleteTableColumnLabel: "Excluir Coluna"
+})
+
diff --git a/dojox/editor/plugins/nls/pt/latinEntities.js b/dojox/editor/plugins/nls/pt/latinEntities.js
index af7c3d4..1c240b5 100644
--- a/dojox/editor/plugins/nls/pt/latinEntities.js
+++ b/dojox/editor/plugins/nls/pt/latinEntities.js
@@ -1 +1,257 @@
-({"le":"menor ou igual a","prod":"produto de n elementos\nsímbolo de produto","zwj":"conector de largura zero","mdash":"travessão","frasl":"barra de fração","upsih":"Símbolo da letra grega upsilon com gancho","prop":"proporcional a","middot":"ponto mediano\nvírgula georgiana\nponto mediano grego","hellip":"reticências horizontais\ntrês pontos","eta":"Letra grega minúscula eta","iacute":"Letra latina minúscula i com acento agudo","yen":"símbolo de ienesímbolo de yuan","rlm":"marca da dire [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"ponto de exclamação invertido",
+	cent:"símbolo de centavo",
+	pound:"símbolo de libra",
+	curren:"símbolo de moeda",
+	yen:"símbolo de iene\símbolo de yuan",
+	brvbar:"barra interrompida\nbarra vertical de interrompida",
+	sect:"símbolo de seção",
+	uml:"trema\ntrema de espaçamento",
+	copy:"símbolo de copyright",
+	ordf:"indicador ordinal feminino",
+	laquo:"aspas latinas duplas de encerramento\nsímbolo de citação esquerdo",
+	not:"nenhum símbolo",
+	shy:"hífen reformatável\nhífen discricionário",
+	reg:"símbolo de marca registrada\nsímbolo de marca comercial registrada",
+	macr:"macron\nmacron de espaçamento\nlinha sobreposta\nbarra superior de APL",
+	deg:"símbolo de grau",
+	plusmn:"símbolo de mais e menos\nsímbolo de mais ou menos",
+	sup2:"dois sobrescrito\ndígito dois sobrescrito\nraiz quadrada",
+	sup3:"três sobrescrito\ndígito três sobrescrito\nraiz cúbica",
+	acute:"acento agudo\nacento agudo para espaçamento",
+	micro:"símbolo de micro",
+	para:"símbolo pé-de-mosca\nsímbolo de parágrafo",
+	middot:"ponto mediano\nvírgula georgiana\nponto mediano grego",
+	cedil:"cedilha\ncedilha para espaçamento",
+	sup1:"um sobrescrito\ndígito um sobrescrito",
+	ordm:"indicador ordinal masculino",
+	raquo:"aspas latinas duplas de abertura\nsímbolo de citação direito",
+	frac14:"fração de um quarto\nfração de um quarto",
+	frac12:"fração de um meio\nfração de um meio",
+	frac34:"fração de três quartos\nfração de três quartos",
+	iquest:"ponto de interrogação invertido\nponto de interrogação invertido",
+	Agrave:"Letra latina maiúscula A com acento grave\nletra latina maiúscula A com acento grave",
+	Aacute:"Letra latina maiúscula A com acento agudo",
+	Acirc:"Letra latina maiúscula A com acento circunflexo",
+	Atilde:"Letra latina maiúscula A com til",
+	Auml:"Letra latina maiúscula A com trema",
+	Aring:"Letra latina maiúscula A com círculo em cima\nLetra latina maiúscula A com círculo",
+	AElig:"Letra latina maiúscula AE\nLetra latina maiúscula AE",
+	Ccedil:"Letra latina maiúscula C com cedilha",
+	Egrave:"Letra latina maiúscula E com acento grave",
+	Eacute:"Letra latina maiúscula E com acento agudo",
+	Ecirc:"Letra latina maiúscula E com acento circunflexo",
+	Euml:"Letra latina maiúscula E com trema",
+	Igrave:"Letra latina maiúscula I com acento grave",
+	Iacute:"Letra latina maiúscula I com acento agudo",
+	Icirc:"Letra latina maiúscula I com acento circunflexo",
+	Iuml:"Letra latina maiúscula I com trema",
+	ETH:"Letra latina maiúscula ETH",
+	Ntilde:"Letra latina maiúscula N com til",
+	Ograve:"Letra latina maiúscula O com acento grave",
+	Oacute:"Letra latina maiúscula O com acento agudo",
+	Ocirc:"Letra latina maiúscula O com acento circunflexo",
+	Otilde:"Letra latina maiúscula O com til",
+	Ouml:"Letra latina maiúscula O com trema",
+	times:"símbolo de multiplicação",
+	Oslash:"Letra latina maiúscula O traçada\nLetra latina maiúscula O cortada com barra",
+	Ugrave:"Letra latina maiúscula U com acento grave",
+	Uacute:"Letra latina maiúscula U com acento agudo",
+	Ucirc:"Letra latina maiúscula U com acento circunflexo",
+	Uuml:"Letra latina maiúscula U com trema",
+	Yacute:"Letra latina maiúscula Y com acento agudo",
+	THORN:"Letra latina maiúscula THORN",
+	szlig:"Letra latina minúscula scharfes S\ness-zed",
+	agrave:"Letra latina minúscula a com acento grave\nletra latina minúscula a com acento grave",
+	aacute:"Letra latina minúscula a com acento agudo",
+	acirc:"Letra latina minúscula a com acento circunflexo",
+	atilde:"Letra latina minúscula a com til",
+	auml:"Letra latina minúscula a com trema",
+	aring:"Letra latina minúscula a com círculo em cima\nLetra latina minúscula a com círculo",
+	aelig:"Letra latina minúscula ae\nLetra latina minúscula ae contraída",
+	ccedil:"Letra latina minúscula c com cedilha",
+	egrave:"Letra latina minúscula e com acento grave",
+	eacute:"Letra latina minúscula e com acento agudo",
+	ecirc:"Letra latina minúscula e com acento circunflexo",
+	euml:"Letra latina minúscula e com trema",
+	igrave:"Letra latina minúscula i com acento grave",
+	iacute:"Letra latina minúscula i com acento agudo",
+	icirc:"Letra latina minúscula i com acento circunflexo",
+	iuml:"Letra latina minúscula i com trema",
+	eth:"Letra latina minúscula eth",
+	ntilde:"Letra latina minúscula n com til",
+	ograve:"Letra latina minúscula o com acento grave",
+	oacute:"Letra latina minúscula o com acento agudo",
+	ocirc:"Letra latina minúscula o com acento circunflexo",
+	otilde:"Letra latina minúscula o com til",
+	ouml:"Letra latina minúscula o com trema",
+	divide:"símbolo de divisão",
+	oslash:"Letra latina minúscula o traçada\nLetra latina minúscula o cortada com barra",
+	ugrave:"Letra latina minúscula u com acento grave",
+	uacute:"Letra latina minúscula u com acento agudo",
+	ucirc:"Letra latina minúscula u com acento circunflexo",
+	uuml:"Letra latina minúscula u com trema",
+	yacute:"Letra latina minúscula y com acento agudo",
+	thorn:"Letra latina minúscula thorn",
+	yuml:"Letra latina minúscula y com trema",
+
+// Greek Characters and Symbols
+	fnof:"Letra latina minúscula f com gancho\nfunção\nflorim",
+	Alpha:"Letra grega maiúscula alfa",
+	Beta:"Letra grega maiúscula beta",
+	Gamma:"Letra grega maiúscula gama",
+	Delta:"Letra grega maiúscula delta",
+	Epsilon:"Letra grega maiúscula épsilon",
+	Zeta:"Letra grega maiúscula zeta",
+	Eta:"Letra grega maiúscula eta",
+	Theta:"Letra grega maiúscula teta",
+	Iota:"Letra grega maiúscula iota",
+	Kappa:"Letra grega maiúscula capa",
+	Lambda:"Letra grega maiúscula lambda",
+	Mu:"Letra grega maiúscula miu",
+	Nu:"Letra grega maiúscula nu",
+	Xi:"Letra grega maiúscula ksi",
+	Omicron:"Letra grega maiúscula ómicron",
+	Pi:"Letra grega maiúscula pi",
+	Rho:"Letra grega maiúscula rô",
+	Sigma:"Letra grega maiúscula sigma",
+	Tau:"Letra grega maiúscula tau",
+	Upsilon:"Letra grega maiúscula upsilon",
+	Phi:"Letra grega maiúscula fi",
+	Chi:"Letra grega maiúscula chi",
+	Psi:"Letra grega maiúscula psi",
+	Omega:"Letra grega maiúscula ômega",
+	alpha:"Letra grega minúscula alfa",
+	beta:"Letra grega minúscula beta",
+	gamma:"Letra grega minúscula gama",
+	delta:"Letra grega minúscula delta",
+	epsilon:"Letra grega minúscula épsilon",
+	zeta:"Letra grega minúscula zeta",
+	eta:"Letra grega minúscula eta",
+	theta:"Letra grega minúscula teta",
+	iota:"Letra grega minúscula iota",
+	kappa:"Letra grega minúscula capa",
+	lambda:"Letra grega minúscula lambda",
+	mu:"Letra grega minúscula miu",
+	nu:"Letra grega minúscula nu",
+	xi:"Letra grega minúscula ksi",
+	omicron:"Letra grega minúscula ómicron",
+	pi:"Letra grega minúscula pi",
+	rho:"Letra grega minúscula rô",
+	sigmaf:"Letra grega minúscula sigma final",
+	sigma:"Letra grega minúscula sigma",
+	tau:"Letra grega minúscula tau",
+	upsilon:"Letra grega minúscula upsilon",
+	phi:"Letra grega minúscula fi",
+	chi:"Letra grega minúscula chi",
+	psi:"Letra grega minúscula psi",
+	omega:"Letra grega minúscula ômega",
+	thetasym:"Símbolo da letra grega minúscula teta",
+	upsih:"Símbolo da letra grega upsilon com gancho",
+	piv:"Símbolo grego pi",
+	bull:"marcador\npequeno círculo preto",
+	hellip:"reticências horizontais\ntrês pontos",
+	prime:"linha simples\nminutos\npés",
+	Prime:"linha dupla\nsegundos\npolegadas",
+	oline:"linha sobreposta\nlinha superior para espaçamento",
+	frasl:"barra de fração",
+	weierp:"P maiúsculo cursivo\npotência\np de Weierstrass",
+	image:"letra I maiúscula gótica\nparte imaginária",
+	real:"letra R maiúscula gótica\nsímbolo da parte real",
+	trade:"símbolo de marca registrada",
+	alefsym:"símbolo alef\nprimeiro cardinal transfinito",
+	larr:"seta para esquerda",
+	uarr:"seta para cima",
+	rarr:"seta para direita",
+	darr:"seta para baixo",
+	harr:"seta para esquerda e direita",
+	crarr:"seta para baixo com curva para esquerda\nretorno de texto",
+	lArr:"seta dupla para esquerda",
+	uArr:"seta dupla para cima",
+	rArr:"seta dupla para direita",
+	dArr:"seta dupla para baixo",
+	hArr:"seta dupla para esquerda e direita",
+	forall:"para todos",
+	part:"diferença parcial",
+	exist:"existe pelo menos",
+	empty:"conjunto vazio\nconjunto nulo\ndiâmetro",
+	nabla:"nabla\ngradiente",
+	isin:"pertence a",
+	notin:"não pertence a",
+	ni:"contém",
+	prod:"produto de n elementos\nsímbolo de produto",
+	sum:"somatório de n elementos",
+	minus:"sinal de menos",
+	lowast:"asterisco",
+	radic:"raiz quadrada\nsímbolo de radical",
+	prop:"proporcional a",
+	infin:"infinito",
+	ang:"ângulo",
+	and:"'e' lógico\nwedge",
+	or:"'ou' lógico\nvee",
+	cap:"intersecção\nintersecção",
+	cup:"união\nreunião","int":"integral",
+	there4:"para isso",
+	sim:"operador til\nvaria com\nigual a",
+	cong:"aproximadamente igual a",
+	asymp:"quase igual a\nassintótico a",
+	ne:"diferente de",
+	equiv:"idêntico a",
+	le:"menor ou igual a",
+	ge:"maior ou igual a",
+	sub:"está contido em",
+	sup:"contém",
+	nsub:"não está contido em",
+	sube:"está contido ou é igual a",
+	supe:"contém ou é igual a",
+	oplus:"círculo mais\nsoma direta",
+	otimes:"símbolo de vezes circulado\nproduto dos vetores",
+	perp:"up tack\nortogonal a\nperpendicular",
+	sdot:"ponto de multiplicação",
+	lceil:"chave em L com o canto voltado para cima à esquerda\nAPL com o canto voltado para cima",
+	rceil:"chave em L com o canto voltado para cima à direita",
+	lfloor:"chave em L com o canto voltado para baixo à esquerda\nAPL com o canto voltado para baixo",
+	rfloor:"chave em L com o canto voltado para baixo à direita",
+	lang:"sinal de maior e menor para esquerda",
+	rang:"sinal de maior e menor para direita",
+	loz:"losango",
+	spades:"símbolo de espadas",
+	clubs:"símbolo de paus\ntrevo",
+	hearts:"coração negro\nsímbolo de copas",
+	diams:"diamante negro",
+	OElig:"Ligação latina maiúscula OE",
+	oelig:"Ligação latina minúscula oe",
+	Scaron:"Letra latina maiúscula S com caron",
+	scaron:"Letra latina minúscula s com caron",
+	Yuml:"Letra latina maiúscula Y com trema",
+	circ:"Acento circunflexo",
+	tilde:"til pequeno",
+	ensp:"espaço simples",
+	emsp:"espaço duplo",
+	thinsp:"espaço estreito",
+	zwnj:"separador de largura zero",
+	zwj:"conector de largura zero",
+	lrm:"marca da esquerda para a direita",
+	rlm:"marca da direita para a esquerda",
+	ndash:"traço",
+	mdash:"travessão",
+	lsquo:"aspas simples à esquerda",
+	rsquo:"aspas simples à direita",
+	sbquo:"aspas simples inferior à direita",
+	ldquo:"aspas duplas inferior à esquerda",
+	rdquo:"aspas duplas à direita",
+	bdquo:"aspas duplas inferiores à direita",
+	dagger:"cruz",
+	Dagger:"cruz dupla",
+	permil:"símbolo por mil",
+	lsaquo:"aspa latina de encerramento",
+	rsaquo:"aspa latina de abertura",
+	euro:"símbolo de euro"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/Blockquote.js b/dojox/editor/plugins/nls/ro/Blockquote.js
new file mode 100644
index 0000000..859084b
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/Blockquote.js
@@ -0,0 +1,4 @@
+({
+	"blockquote": "Blockquote"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/Breadcrumb.js b/dojox/editor/plugins/nls/ro/Breadcrumb.js
new file mode 100644
index 0000000..06d3485
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/Breadcrumb.js
@@ -0,0 +1,10 @@
+({
+	"nodeActions": "Acţiuni ${nodeName}",
+	"selectContents": "Selectare conţinut",
+	"selectElement": "Selectare element",
+	"deleteElement": "Ştergere element",
+	"deleteContents": "Ştergere conţinut",
+	"moveStart": "Mutare cursor la început",
+	"moveEnd": "Mutare cursor la sfârşit"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/CollapsibleToolbar.js b/dojox/editor/plugins/nls/ro/CollapsibleToolbar.js
new file mode 100644
index 0000000..cec6fcd
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/CollapsibleToolbar.js
@@ -0,0 +1,5 @@
+({
+	"collapse": "Restrângere bară de unelte Editor",
+	"expand": "Expandare bară de unelte Editor"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/FindReplace.js b/dojox/editor/plugins/nls/ro/FindReplace.js
new file mode 100644
index 0000000..f029cdb
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/FindReplace.js
@@ -0,0 +1,22 @@
+({
+	"findLabel": "Găsire:",
+	"findTooltip": "Introduceţi textul de găsit ",
+	"replaceLabel": "Înlocuire cu: ",
+	"replaceTooltip": "Introduceţi textul cu care se înlocuieşte",
+	"findReplace": "Găsire şi înlocuire",
+	"matchCase": "Potrivire majuscule ",
+	"matchCaseTooltip": "Potrivire majuscule ",
+	"backwards": "Înapoi",
+	"backwardsTooltip": "Căutaţi înapoi pentru text",
+	"replaceAllButton": "Înlocuire toate ",
+	"replaceAllButtonTooltip": "Înlocuiţi tot textul",
+	"findButton": "Găsire",
+	"findButtonTooltip": "Găsiţi textul",
+	"replaceButton": "Înlocuire ",
+	"replaceButtonTooltip": "Înlocuiţi textul",
+	"replaceDialogText": "Au fost înlocuite ${0} apariţii.",
+	"eofDialogText": "Ultima apariţie ${0}",
+	"eofDialogTextFind": "găsită",
+	"eofDialogTextReplace": "înlocuită"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/InsertAnchor.js b/dojox/editor/plugins/nls/ro/InsertAnchor.js
new file mode 100644
index 0000000..ac50e7e
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/InsertAnchor.js
@@ -0,0 +1,9 @@
+({
+	insertAnchor: "Inserare ancoră",
+	title: "Proprietăţi ancoră",
+	anchor: "Nume:",
+	text: "Descriere:",
+	set: "Setare",
+	cancel: "Anulare"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/InsertEntity.js b/dojox/editor/plugins/nls/ro/InsertEntity.js
new file mode 100644
index 0000000..bb91e35
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/InsertEntity.js
@@ -0,0 +1,4 @@
+({
+	insertEntity: "Inserare simbol"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/PageBreak.js b/dojox/editor/plugins/nls/ro/PageBreak.js
new file mode 100644
index 0000000..7d9d2dc
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/PageBreak.js
@@ -0,0 +1,4 @@
+({
+	"pageBreak": "Întrerupere pagină"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/PasteFromWord.js b/dojox/editor/plugins/nls/ro/PasteFromWord.js
new file mode 100644
index 0000000..394fe10
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/PasteFromWord.js
@@ -0,0 +1,7 @@
+({
+	"pasteFromWord": "Lipire din Word",
+	"paste": "Lipire",
+	"cancel": "Anulare",
+	"instructions": "Lipiţi conţinut din Word în caeta de text de mai jos. După ce sunteţi mulţumit de conţinutul de inserat, apăsaţi butonul Lipire. Pentru a renunţa la inserarea textului, apăsaţi butonul Anulare."
+})
+
diff --git a/dojox/editor/plugins/nls/ro/Preview.js b/dojox/editor/plugins/nls/ro/Preview.js
new file mode 100644
index 0000000..95a6462
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/Preview.js
@@ -0,0 +1,4 @@
+({
+	"preview": "Previzualizare "
+})
+
diff --git a/dojox/editor/plugins/nls/ro/Save.js b/dojox/editor/plugins/nls/ro/Save.js
new file mode 100644
index 0000000..9b82668
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/Save.js
@@ -0,0 +1,4 @@
+({
+	"save": "Salvare"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/ShowBlockNodes.js b/dojox/editor/plugins/nls/ro/ShowBlockNodes.js
new file mode 100644
index 0000000..5a75d78
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/ShowBlockNodes.js
@@ -0,0 +1,4 @@
+({
+	"showBlockNodes": "Afişare bloc elemente HTML"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/Smiley.js b/dojox/editor/plugins/nls/ro/Smiley.js
new file mode 100644
index 0000000..382910d
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/Smiley.js
@@ -0,0 +1,22 @@
+({
+	smiley: "Inserare emoticoane",
+	emoticonSmile: "zâmbet",
+	emoticonLaughing: "râs",
+	emoticonWink: "face cu ochiul",
+	emoticonGrin: "rânjet",
+	emoticonCool: "calm",
+	emoticonAngry: "furios",  
+	emoticonHalf: "jumătate", 
+	emoticonEyebrow: "sprânceană",
+	emoticonFrown: "posac",
+	emoticonShy: "timid",
+	emoticonGoofy: "tont",
+	emoticonOops: "vai",
+	emoticonTongue: "limbă",
+	emoticonIdea: "idee",
+	emoticonYes: "da",
+	emoticonNo: "nu",	
+	emoticonAngel: "înger",
+	emoticonCrying: "plâns"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/TableDialog.js b/dojox/editor/plugins/nls/ro/TableDialog.js
new file mode 100644
index 0000000..2af7f18
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/TableDialog.js
@@ -0,0 +1,30 @@
+({
+	insertTableTitle: "Inserare tabelă",
+	modifyTableTitle: "Modificare tabelă",
+	rows: "Rânduri:",
+	columns: "Coloane:",
+	align: "Aliniere:",
+	cellPadding: "Completare celulă:",
+	cellSpacing: "Spaţiere celulă:",
+	tableWidth: "Lăţime tabelă:",
+	backgroundColor: "Culoare fundal:",
+	borderColor: "Culoare bordură:",
+	borderThickness: "Grosime bordură",
+	percent: "procent",
+	pixels: "pixeli",
+	"default": "implicit",
+	left: "stânga",
+	center: "centru",
+	right: "dreapta",
+	buttonSet: "Setare", // translated elsewhere?
+	buttonInsert: "Inserare",
+
+	selectTableLabel: "Selectare tabelă ",
+	insertTableRowBeforeLabel: "Adăugare rând înainte",
+	insertTableRowAfterLabel: "Adăugare rând după",
+	insertTableColumnBeforeLabel: "Adăugare coloană înainte",
+	insertTableColumnAfterLabel: "Adăugare coloană după",
+	deleteTableRowLabel: "Ştergere rând ",
+	deleteTableColumnLabel: "Ştergere coloană"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/TextColor.js b/dojox/editor/plugins/nls/ro/TextColor.js
new file mode 100644
index 0000000..56c2a03
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/TextColor.js
@@ -0,0 +1,5 @@
+({
+	"setButtonText": "Setare",
+	"cancelButtonText": "Anulare"
+})
+
diff --git a/dojox/editor/plugins/nls/ro/latinEntities.js b/dojox/editor/plugins/nls/ro/latinEntities.js
new file mode 100644
index 0000000..a21a2b1
--- /dev/null
+++ b/dojox/editor/plugins/nls/ro/latinEntities.js
@@ -0,0 +1,257 @@
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"semnul exclamării inversat",
+	cent:"semnul cent",
+	pound:"semnul liră sterlină",
+	curren:"semnul monedă",
+	yen:"semnul yen\nsemnul nyuan",
+	brvbar:"bară ruptă\nbară verticală ruptă",
+	sect:"semn secţiune",
+	uml:"tremă\ntremă de spaţiere",
+	copy:"semnul copyright",
+	ordf:"indicator ordinal feminin",
+	laquo:"ghilimele unghi dublu arătând spre stânga\nghilimele arătând spre stânga",
+	not:"semn nu",
+	shy:"liniuţă de despărţire soft\nliniuţă de despărţire discreţionară",
+	reg:"semn de înregistrare\nsemn de marcă înregistrată",
+	macr:"macron\nmacron de spaţiere\nlinie deasupra\nAPL linie deasupra",
+	deg:"semn de grade",
+	plusmn:"semn plus-minus\nsemn plus-sau-minus",
+	sup2:"scriere indice superior doi\nscriere indice superior cifră doi\npătrat",
+	sup3:"scriere indice superior trei\nscriere indice superior cifră trei\ncub",
+	acute:"accent acut\nspaţiere acută",
+	micro:"semn micro",
+	para:"semn pilcrow\nsemn paragraf",
+	middot:"punct de mijloc\nvirgulă georgiană\npunct de mijloc grec",
+	cedil:"sedila\nsedila de spaţiere",
+	sup1:"scriere indice superior unu\nscriere indice superior cifră unu",
+	ordm:"indicator ordinal masculin",
+	raquo:"ghilimele unghi dublu arătând spre dreapta\nghilimele arătând spre dreapta",
+	frac14:"fracţie ordinară un sfert\nfracţie un sfert",
+	frac12:"fracţie ordinară o jumătate\nfracţie o jumătate",
+	frac34:"fracţie ordinară trei sferturi\nfracţie trei sferturi",
+	iquest:"semn de întrebare inversat\nsemn de întrebare răsturnat",
+	Agrave:"Literă mare latină A cu accent grav\nLiteră mare latină A grav",
+	Aacute:"Literă mare latină A cu accent acut",
+	Acirc:"Literă mare latină A cu circumflex",
+	Atilde:"Literă mare latină A cu tilda",
+	Auml:"Literă mare latină A cu tremă",
+	Aring:"Literă mare latină A cu inel deasupra\nLiteră mare latină A cu inel",
+	AElig:"Literă mare latină AE\nLigatură mare latină AE",
+	Ccedil:"Literă mare latină C cu sedilă",
+	Egrave:"Literă mare latină E cu accent grav",
+	Eacute:"Literă mare latină E cu accent acut",
+	Ecirc:"Literă mare latină E cu circumflex",
+	Euml:"Literă mare latină E cu tremă",
+	Igrave:"Literă mare latină I cu accent grav",
+	Iacute:"Literă mare latină I cu accent acut",
+	Icirc:"Literă mare latină I cu circumflex",
+	Iuml:"Literă mare latină I cu tremă",
+	ETH:"Literă mare latină ETH",
+	Ntilde:"Literă mare latină N cu tilda",
+	Ograve:"Literă mare latină O cu accent grav",
+	Oacute:"Literă mare latină O cu accent acut",
+	Ocirc:"Literă mare latină O cu circumflex",
+	Otilde:"Literă mare latină O cu tilda",
+	Ouml:"Literă mare latină O cu tremă",
+	times:"semn de înmulţire",
+	Oslash:"Literă latină majusculă O cu linie de taiere\nLiteră latină majusculă O cu o linie oblică",
+	Ugrave:"Literă mare latină U cu accent grav",
+	Uacute:"Literă mare latină U cu accent acut",
+	Ucirc:"Literă mare latină U cu circumflex",
+	Uuml:"Literă mare latină U cu tremă",
+	Yacute:"Literă mare latină Y cu accent acut",
+	THORN:"Literă mare latină THORN",
+	szlig:"Literă latină mică s diez\ness-zed",
+	agrave:"Literă latină mică a cu accent grav\nLiteră latină mică a grav",
+	aacute:"Literă latină mică a cu accent acut",
+	acirc:"Literă latină mică a cu circumflex",
+	atilde:"Literă latină mică a cu tilda",
+	auml:"Literă latină mică a cu tremă",
+	aring:"Literă latină mică a cu inel deasupra\nLiteră latină mică a cu inel",
+	aelig:"Literă latină mică ae\nLigatură latină mică ae",
+	ccedil:"Literă latină mică c cu sedilă",
+	egrave:"Literă latină mică e cu accent grav",
+	eacute:"Literă latină mică e cu accent acut",
+	ecirc:"Literă latină mică e cu circumflex",
+	euml:"Literă latină mică e cu tremă",
+	igrave:"Literă latină mică i cu accent grav",
+	iacute:"Literă latină mică i cu accent acut",
+	icirc:"Literă latină mică i cu circumflex",
+	iuml:"Literă latină mică i cu tremă",
+	eth:"Literă latină mică eth",
+	ntilde:"Literă latină mică n cu tilda",
+	ograve:"Literă latină mică o cu accent grav",
+	oacute:"Literă latină mică o cu accent acut",
+	ocirc:"Literă latină mică o cu circumflex",
+	otilde:"Literă latină mică o cu tilda",
+	ouml:"Literă latină mică o cu tremă",
+	divide:"semn împărţire",
+	oslash:"Literă latină mică o cu linie de taiere\nLiteră latină mică o cu o linie oblică",
+	ugrave:"Literă latină mică u cu accent grav",
+	uacute:"Literă latină mică u cu accent acut",
+	ucirc:"Literă latină mică u cu circumflex",
+	uuml:"Literă latină mică u cu tremă",
+	yacute:"Literă latină mică y cu accent acut",
+	thorn:"Literă latină mică thorn",
+	yuml:"Literă latină mică y cu tremă",
+
+// Greek Characters and Symbols
+	fnof:"Literă latină mică f cu cârlig\nfuncţie\nflorin",
+	Alpha:"Literă greacă mare alfa",
+	Beta:"Literă greacă mare beta",
+	Gamma:"Literă greacă mare gamma",
+	Delta:"Literă greacă mare delta",
+	Epsilon:"Literă greacă mare epsilon",
+	Zeta:"Literă greacă mare zeta",
+	Eta:"Literă greacă mare eta",
+	Theta:"Literă greacă mare theta",
+	Iota:"Literă greacă mare iota",
+	Kappa:"Literă greacă mare kappa",
+	Lambda:"Literă greacă mare lambda",
+	Mu:"Literă greacă mare miu",
+	Nu:"Literă greacă mare niu",
+	Xi:"Literă greacă mare xi",
+	Omicron:"Literă greacă mare omicron",
+	Pi:"Literă greacă mare pi",
+	Rho:"Literă greacă mare rho",
+	Sigma:"Literă greacă mare sigma",
+	Tau:"Literă greacă mare tau",
+	Upsilon:"Literă greacă mare upsilon",
+	Phi:"Literă greacă mare phi",
+	Chi:"Literă greacă mare chi",
+	Psi:"Literă greacă mare psi",
+	Omega:"Literă greacă mare omega",
+	alpha:"Literă greacă mică alfa",
+	beta:"Literă greacă mică beta",
+	gamma:"Literă greacă mică gamma",
+	delta:"Literă greacă mică delta",
+	epsilon:"Literă greacă mică epsilon",
+	zeta:"Literă greacă mică zeta",
+	eta:"Literă greacă mică eta",
+	theta:"Literă greacă mică theta",
+	iota:"Literă greacă mică iota",
+	kappa:"Literă greacă mică kappa",
+	lambda:"Literă greacă mică lambda",
+	mu:"Literă greacă mică miu",
+	nu:"Literă greacă mică niu",
+	xi:"Literă greacă mică xi",
+	omicron:"Literă greacă mică omicron",
+	pi:"Literă greacă mică pi",
+	rho:"Literă greacă mică rho",
+	sigmaf:"Literă greacă mică sigma final",
+	sigma:"Literă greacă mică sigma",
+	tau:"Literă greacă mică tau",
+	upsilon:"Literă greacă mică upsilon",
+	phi:"Literă greacă mică phi",
+	chi:"Literă greacă mică chi",
+	psi:"Literă greacă mică psi",
+	omega:"Literă greacă mică omega",
+	thetasym:"Literă greacă mică simbol theta",
+	upsih:"Simbolul grec upsilon cu cârlig",
+	piv:"Simbolul grec pi",
+	bull:"bullet\ncerc mic negru",
+	hellip:"elipse orizontale\ntrei puncte precursoare",
+	prime:"prim\nminute\npicioare",
+	Prime:"prim dublu\nsecunde\nţoli",
+	oline:"linie deasupra\nlinie de spaţiere deasupra",
+	frasl:"linie fracţie",
+	weierp:"script capital P\nputere\np Weierstrass",
+	image:"I majusculă înnegrită\nparte imaginară",
+	real:"R majusculă înnegrită\nsimbol parte reală",
+	trade:"semn marcă înregistrată",
+	alefsym:"simbol alef\nprimul cardinal transfinit",
+	larr:"săgeată spre stânga",
+	uarr:"săgeata în sus",
+	rarr:"săgeată spre dreapta",
+	darr:"săgeata în jos",
+	harr:"săgeata stânga dreapta",
+	crarr:"săgeata în jos cu colţ spre stânga",
+	lArr:"săgeata dublă spre stânga",
+	uArr:"săgeata dublă în sus",
+	rArr:"săgeata dublă spre dreapta",
+	dArr:"săgeata dublă în jos",
+	hArr:"săgeata dublă stânga dreapta",
+	forall:"pentru toate",
+	part:"diferenţiale parţiale",
+	exist:"Există",
+	empty:"set gol\nset zero\ndiametru",
+	nabla:"nabla\ndiferenţa înapoi",
+	isin:"element al",
+	notin:"nu este un element al",
+	ni:"conţine ca membru",
+	prod:"n produs\nsemnul produs",
+	sum:"n suma",
+	minus:"semnul minus",
+	lowast:"operatorul asterisk",
+	radic:"rădăcină pătrată\nsemnul radical",
+	prop:"proporţional cu",
+	infin:"infinit",
+	ang:"unghi",
+	and:"şi logic\npană",
+	or:"sau logic\nV",
+	cap:"intersecţie\ncăciulă",
+	cup:"reuniune\ncupă","int":"integral",
+	there4:"de aceea",
+	sim:"operator tilda\nvariază cu\nsimilar cu",
+	cong:"aproximativ egal cu",
+	asymp:"aproape egal cu\nasimptotic la",
+	ne:"nu este egal cu",
+	equiv:"identic cu",
+	le:"mai mic sau egal cu",
+	ge:"mai mare sau egal cu",
+	sub:"subset al",
+	sup:"superset al",
+	nsub:"nu este un subset al",
+	sube:"subset al sau egal cu",
+	supe:"superset al sau egal cu",
+	oplus:"plus încercuit\nsumă directă",
+	otimes:"multiplicator încercuit\nprodus vectorial",
+	perp:"t întors\nortogonal la\nerpendicular",
+	sdot:"operator punct",
+	lceil:"plafon stânga\nAPL upstile",
+	rceil:"plafon dreapta",
+	lfloor:"podea stânga\nAPL downstile",
+	rfloor:"podea dreapta",
+	lang:"paranteză unghiulară spre stânga",
+	rang:"paranteză unghiulară spre dreapta",
+	loz:"romb",
+	spades:"treflă neagră",
+	clubs:"pică neagră\nshamrock",
+	hearts:"inimă neagră\nvalentine",
+	diams:"romb negru",
+	OElig:"Ligatură mare latină OE",
+	oelig:"Ligatură mică latină oe",
+	Scaron:"Literă mare latină S cu caron",
+	scaron:"Literă mică latină s cu caron",
+	Yuml:"Literă mare latină Y cu tremă",
+	circ:"accent circumflex modificator de literă",
+	tilde:"tilda mică",
+	ensp:"spaţiu en",
+	emsp:"spaţiu em",
+	thinsp:"spaţiu îngust",
+	zwnj:"zero fără unificator",
+	zwj:"zero cu unificator",
+	lrm:"semn stânga spre dreapta",
+	rlm:"semn dreapta spre stânga",
+	ndash:"linie en",
+	mdash:"linie em",
+	lsquo:"ghilimele simple stânga",
+	rsquo:"ghilimele simple dreapta",
+	sbquo:"single low-9 semn de citare ",
+	ldquo:"ghilimele duble stânga",
+	rdquo:"ghilimele duble dreapta",
+	bdquo:"double low-9 semn de citare",
+	dagger:"cruce",
+	Dagger:"cruce dublă",
+	permil:"semn per mie",
+	lsaquo:"ghilimele singure unghiulare spre stânga",
+	rsaquo:"ghilimele singure unghiulare spre dreapta",
+	euro:"semn euro"
+})
+
diff --git a/dojox/editor/plugins/nls/ru/Breadcrumb.js b/dojox/editor/plugins/nls/ru/Breadcrumb.js
index 448318d..044430a 100644
--- a/dojox/editor/plugins/nls/ru/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/ru/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"Выбрать содержимое","deleteElement":"Удалить элемент","moveEnd":"Поместить курсор в конец","deleteContents":"Удалить содержимое","nodeActions":"${nodeName}: действия","selectElement":"Выбрать элемент","moveStart":"Поместить курсор в начало"})
\ No newline at end of file
+({
+	"nodeActions": "${nodeName}: действия",
+	"selectContents": "Выбрать содержимое",
+	"selectElement": "Выбрать элемент",
+	"deleteElement": "Удалить элемент",
+	"deleteContents": "Удалить содержимое",
+	"moveStart": "Поместить курсор в начало",
+	"moveEnd": "Поместить курсор в конец"
+})
+
diff --git a/dojox/editor/plugins/nls/ru/FindReplace.js b/dojox/editor/plugins/nls/ru/FindReplace.js
index 665961e..cd4ae13 100644
--- a/dojox/editor/plugins/nls/ru/FindReplace.js
+++ b/dojox/editor/plugins/nls/ru/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"Назад","findReplace":"Переключатель Поиск/Замена","replaceAll":"Все вхождения","replaceDialogText":"Заменено ${0} вхождений.","replaceButton":"Заменить","findButton":"Найти","findLabel":"Найти:","matchCase":"С учетом регистра","replaceLabel":"Заменить на:"})
\ No newline at end of file
+({
+	"findLabel": "Найти:",
+	"replaceLabel": "Заменить на:",
+	"findReplace": "Переключатель Поиск/Замена",
+	"matchCase": "С учетом регистра", 
+	"backwards": "Назад",
+	"replaceAll": "Все вхождения", 
+	"findButton": "Найти",
+	"replaceButton": "Заменить",
+	"replaceDialogText": "Заменено ${0} вхождений."
+})
+
diff --git a/dojox/editor/plugins/nls/ru/InsertEntity.js b/dojox/editor/plugins/nls/ru/InsertEntity.js
index b96e39b..55473ce 100644
--- a/dojox/editor/plugins/nls/ru/InsertEntity.js
+++ b/dojox/editor/plugins/nls/ru/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"Вставить символ"})
\ No newline at end of file
+({
+	insertEntity: "Вставить символ"
+})
+
diff --git a/dojox/editor/plugins/nls/ru/PageBreak.js b/dojox/editor/plugins/nls/ru/PageBreak.js
index e371e2c..9fffae7 100644
--- a/dojox/editor/plugins/nls/ru/PageBreak.js
+++ b/dojox/editor/plugins/nls/ru/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"Разделитель страниц"})
\ No newline at end of file
+({
+	"pageBreak": "Разделитель страниц"
+})
+
diff --git a/dojox/editor/plugins/nls/ru/Preview.js b/dojox/editor/plugins/nls/ru/Preview.js
index 0a8069d..eb25d1f 100644
--- a/dojox/editor/plugins/nls/ru/Preview.js
+++ b/dojox/editor/plugins/nls/ru/Preview.js
@@ -1 +1,4 @@
-({"preview":"Предварительный просмотр"})
\ No newline at end of file
+({
+	"preview": "Предварительный просмотр"
+})
+
diff --git a/dojox/editor/plugins/nls/ru/Save.js b/dojox/editor/plugins/nls/ru/Save.js
index 8e711ea..32affcb 100644
--- a/dojox/editor/plugins/nls/ru/Save.js
+++ b/dojox/editor/plugins/nls/ru/Save.js
@@ -1 +1,4 @@
-({"save":"Сохранить"})
\ No newline at end of file
+({
+	"save": "Сохранить"
+})
+
diff --git a/dojox/editor/plugins/nls/ru/ShowBlockNodes.js b/dojox/editor/plugins/nls/ru/ShowBlockNodes.js
index 308f6c2..56b9c59 100644
--- a/dojox/editor/plugins/nls/ru/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/ru/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"Показать элементы блока HTML"})
\ No newline at end of file
+({
+	"showBlockNodes": "Показать элементы блока HTML"
+})
+
diff --git a/dojox/editor/plugins/nls/ru/Smiley.js b/dojox/editor/plugins/nls/ru/Smiley.js
index 145f131..463e805 100644
--- a/dojox/editor/plugins/nls/ru/Smiley.js
+++ b/dojox/editor/plugins/nls/ru/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"смех","emoticonCool":"здорово","emoticonTongue":"насмешка","emoticonCrying":"плачь","emoticonOops":"уупс","emoticonFrown":"хмурый вид","emoticonAngry":"злость","emoticonShy":"застенчивость","emoticonNo":"нет","emoticonAngel":"ангел","smiley":"Вставить значок настроения","emoticonIdea":"есть идея","emoticonEyebrow":"удивление","emoticonSmile":"улыбка","emoticonWink":"подмигивание","emoticonYes":"да","emoticonGrin":"усмешка","emoticonGoofy":"глупый","emoticonHalf":"по [...]
\ No newline at end of file
+({
+	smiley: "Вставить значок настроения",
+	emoticonSmile: "улыбка",
+	emoticonLaughing: "смех",
+	emoticonWink: "подмигивание",
+	emoticonGrin: "усмешка",
+	emoticonCool: "здорово",
+	emoticonAngry: "злость",  
+	emoticonHalf: "половина", 
+	emoticonEyebrow: "удивление",
+	emoticonFrown: "хмурый вид",
+	emoticonShy: "застенчивость",
+	emoticonGoofy: "глупый",
+	emoticonOops: "уупс",
+	emoticonTongue: "насмешка",
+	emoticonIdea: "есть идея",
+	emoticonYes: "да",
+	emoticonNo: "нет",	
+	emoticonAngel: "ангел",
+	emoticonCrying: "плачь"
+})
+
diff --git a/dojox/editor/plugins/nls/ru/TableDialog.js b/dojox/editor/plugins/nls/ru/TableDialog.js
index e904440..5e79a01 100644
--- a/dojox/editor/plugins/nls/ru/TableDialog.js
+++ b/dojox/editor/plugins/nls/ru/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Задать","insertTableTitle":"Вставить таблицу","insertTableRowAfterLabel":"Добавить строку после","center":"по центру","deleteTableColumnLabel":"Удалить столбец","right":"по правому краю","insertTableColumnBeforeLabel":"Добавить столбец перед","tableWidth":"Ширина таблицы:","buttonInsert":"Вставить","default":"по умолчанию","align":"Выровнять:","insertTableRowBeforeLabel":"Добавить строку перед","cellSpacing":"Расстояние между ячейками:","pixels":"пикселов","selectTableLabe [...]
\ No newline at end of file
+({
+	insertTableTitle: "Вставить таблицу",
+	modifyTableTitle: "Изменить таблицу",
+	rows: "Строк:",
+	columns: "Столбцов:",
+	align: "Выровнять:",
+	cellPadding: "Отступ внутри ячеек:",
+	cellSpacing: "Расстояние между ячейками:",
+	tableWidth: "Ширина таблицы:",
+	backgroundColor: "Цвет фона:",
+	borderColor: "Цвет рамки:",
+	borderThickness: "Толщина рамки",
+	percent: "процентов",
+	pixels: "пикселов",
+	"default": "по умолчанию",
+	left: "по левому краю",
+	center: "по центру",
+	right: "по правому краю",
+	buttonSet: "Задать", // translated elsewhere?
+	buttonInsert: "Вставить",
+
+	selectTableLabel: "Выбрать таблицу",
+	insertTableRowBeforeLabel: "Добавить строку перед",
+	insertTableRowAfterLabel: "Добавить строку после",
+	insertTableColumnBeforeLabel: "Добавить столбец перед",
+	insertTableColumnAfterLabel: "Добавить столбец после",
+	deleteTableRowLabel: "Удалить строку",
+	deleteTableColumnLabel: "Удалить столбец"
+})
+
diff --git a/dojox/editor/plugins/nls/ru/latinEntities.js b/dojox/editor/plugins/nls/ru/latinEntities.js
index f8c9dae..9e5ec7f 100644
--- a/dojox/editor/plugins/nls/ru/latinEntities.js
+++ b/dojox/editor/plugins/nls/ru/latinEntities.js
@@ -1 +1,257 @@
-({"le":"меньше или равно","prod":"n-арное произведение\nсимвол произведения","zwj":"соединитель нулевой ширины","mdash":"тире длины M","frasl":"косая черта","upsih":"греческий ипсилон с хвостиком","prop":"пропорционально","middot":"средняя точка\nзапятая в грузинском\nсредняя точка в греческом","hellip":"многоточие\nтри точки","eta":"греческая строчная буква эта","iacute":"латинская строчная буква i с акутом","yen":"символ иены\nсимвол юаня","rlm":"знак справа-налево","macr":"знак долгот [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"инвертированный восклицательный знак",
+	cent:"символ цента",
+	pound:"символ фунта стерлингов",
+	curren:"символ денежной единицы",
+	yen:"символ иены\nсимвол юаня",
+	brvbar:"прерывистая черта\nвертикальная прерывистая черта",
+	sect:"символ раздела",
+	uml:"трема\nтрема с интервалом",
+	copy:"символ авторских прав",
+	ordf:"индикатор женского рода",
+	laquo:"левые двойный угловые кавычки\nлевые кавычки",
+	not:"знак отрицания",
+	shy:"мягкий перенос\nвозможный перенос",
+	reg:"символ Зарегистрирован\nсимвол зарегистрированного товарного знака",
+	macr:"знак долготы\nзнак долготы с интервалом\nверхняя черта\nнадчеркивание APL",
+	deg:"символ градусов",
+	plusmn:"символ плюс-минус\nсимвол плюса или минуса",
+	sup2:"верхний индекс два\nверхний индекс с цифрой два\nвозведение в квадрат",
+	sup3:"верхний индекс три\nверхний индекс с цифрой три\nвозведение в куб",
+	acute:"знак акут\nакут с интервалом",
+	micro:"знак микро",
+	para:"символ абзаца\nсимвол параграфа",
+	middot:"средняя точка\nзапятая в грузинском\nсредняя точка в греческом",
+	cedil:"седиль\nседиль с интервалом",
+	sup1:"верхний индекс один\nверхний индекс с цифрой один",
+	ordm:"индикатор мужского рода",
+	raquo:"правая двойная угловая кавычка\nправая кавычка",
+	frac14:"дробь одна четвертая\nодна четверть",
+	frac12:"дробь одна вторая\nодна вторая",
+	frac34:"дробь три четверти\nтри четверти",
+	iquest:"инвертированный знак вопроса\nперевернутый знак вопроса",
+	Agrave:"латинская прописная буква A с грависом",
+	Aacute:"латинская прописная буква A с акутом",
+	Acirc:"латинская прописная буква A с циркумфлексом",
+	Atilde:"латинская прописная буква A с тильдой",
+	Auml:"латинская прописная буква A с тремой",
+	Aring:"латинская прописная буква A с кружком сверху\nлатинская прописная буква A с кружком",
+	AElig:"латинская прописная буква AE\nлатинская прописная лигатура AE",
+	Ccedil:"латинская прописная буква C с седилью",
+	Egrave:"латинская прописная буква E с грависом",
+	Eacute:"латинская прописная буква E с акутом",
+	Ecirc:"латинская прописная буква E с циркумфлексом",
+	Euml:"латинская прописная буква E с тремой",
+	Igrave:"латинская прописная буква I с грависом",
+	Iacute:"латинская прописная буква I с акутом",
+	Icirc:"латинская прописная буква I с циркумфлексом",
+	Iuml:"латинская прописная буква I с тремой",
+	ETH:"латинская прописная буква ETH",
+	Ntilde:"латинская прописная буква N с тильдой",
+	Ograve:"латинская прописная буква O с грависом",
+	Oacute:"латинская прописная буква O с акутом",
+	Ocirc:"латинская прописная буква O с циркумфлексом",
+	Otilde:"латинская прописная буква O с тильдой",
+	Ouml:"латинская прописная буква O с тремой",
+	times:"знак умножения",
+	Oslash:"латинская прописная буква O перечеркнутая\nлатинская прописная буква O с вертикальной чертой",
+	Ugrave:"латинская прописная буква U с грависом",
+	Uacute:"латинская прописная буква U с акутом",
+	Ucirc:"латинская прописная буква U с циркумфлексом",
+	Uuml:"латинская прописная буква U с тремой",
+	Yacute:"латинская прописная буква Y с акутом",
+	THORN:"латинская прописная буква THORN",
+	szlig:"латинская строчная заостренная s\nэсцэт",
+	agrave:"латинская строчная буква a с грависом\nлатинская строчная a с грависом",
+	aacute:"латинская строчная буква a с акутом",
+	acirc:"латинская строчная буква a с циркумфлексом",
+	atilde:"латинская строчная буква a с тильдой",
+	auml:"латинская строчная буква a с тремой",
+	aring:"латинская строчная буква a с кружком сверху\nлатинская строчная a с кружком",
+	aelig:"латинская строчная буква ae\nлатинская строчная лигатура ae",
+	ccedil:"латинская строчная буква c с седилью",
+	egrave:"латинская строчная буква e с грависом",
+	eacute:"латинская строчная буква e с акутом",
+	ecirc:"латинская строчная буква e с циркумфлексом",
+	euml:"латинская строчная буква e с тремой",
+	igrave:"латинская строчная буква i с грависом",
+	iacute:"латинская строчная буква i с акутом",
+	icirc:"латинская строчная буква i с циркумфлексом",
+	iuml:"латинская строчная буква i с тремой",
+	eth:"латинская строчная буква eth",
+	ntilde:"латинская строчная буква n с тильдой",
+	ograve:"латинская строчная буква o с грависом",
+	oacute:"латинская строчная буква o с акутом",
+	ocirc:"латинская строчная буква o с циркумфлексом",
+	otilde:"латинская строчная буква o с тильдой",
+	ouml:"латинская строчная буква o с тремой",
+	divide:"знак деления",
+	oslash:"латинская строчная буква o перечеркнутая\nлатинская строчная буква o с вертикальной чертой",
+	ugrave:"латинская строчная буква u с грависом",
+	uacute:"латинская строчная буква u с акутом",
+	ucirc:"латинская строчная буква u с циркумфлексом",
+	uuml:"латинская строчная буква u с тремой",
+	yacute:"латинская строчная буква y с акутом",
+	thorn:"латинская строчная буква thorn",
+	yuml:"латинская строчная буква y с тремой",
+
+// Greek Characters and Symbols
+	fnof:"латинская строчная буква f с хвостиком\nфункция\nфлорин",
+	Alpha:"греческая прописная буква альфа",
+	Beta:"греческая прописная буква бета",
+	Gamma:"греческая прописная буква гамма",
+	Delta:"греческая прописная буква дельта",
+	Epsilon:"греческая прописная буква эпсилон",
+	Zeta:"греческая прописная буква дзета",
+	Eta:"греческая прописная буква эта",
+	Theta:"греческая прописная буква тета",
+	Iota:"греческая прописная буква йота",
+	Kappa:"греческая прописная буква каппа",
+	Lambda:"греческая прописная буква лямбда",
+	Mu:"греческая прописная буква мю",
+	Nu:"греческая прописная буква ню",
+	Xi:"греческая прописная буква кси",
+	Omicron:"греческая прописная буква омикрон",
+	Pi:"греческая прописная буква пи",
+	Rho:"греческая прописная буква ро",
+	Sigma:"греческая прописная буква сигма",
+	Tau:"греческая прописная буква тау",
+	Upsilon:"греческая прописная буква ипсилон",
+	Phi:"греческая прописная буква фи",
+	Chi:"греческая прописная буква хи",
+	Psi:"греческая прописная буква пси",
+	Omega:"греческая прописная буква омега",
+	alpha:"греческая строчная буква альфа",
+	beta:"греческая строчная буква бета",
+	gamma:"греческая строчная буква гамма",
+	delta:"греческая строчная буква дельта",
+	epsilon:"греческая строчная буква эпсилон",
+	zeta:"греческая строчная буква дзета",
+	eta:"греческая строчная буква эта",
+	theta:"греческая строчная буква тета",
+	iota:"греческая строчная буква йота",
+	kappa:"греческая строчная буква каппа",
+	lambda:"греческая строчная буква лямбда",
+	mu:"греческая строчная буква мю",
+	nu:"греческая строчная буква ню",
+	xi:"греческая строчная буква хи",
+	omicron:"греческая строчная буква омикрон",
+	pi:"греческая строчная буква пи",
+	rho:"греческая строчная буква ро",
+	sigmaf:"греческая строчная конечная сигма",
+	sigma:"греческая строчная буква сигма",
+	tau:"греческая строчная буква тау",
+	upsilon:"греческая строчная буква ипсилон",
+	phi:"греческая строчная буква фи",
+	chi:"греческая строчная буква хи",
+	psi:"греческая строчная буква пси",
+	omega:"греческая строчная буква омега",
+	thetasym:"греческая символьная тета",
+	upsih:"греческий ипсилон с хвостиком",
+	piv:"греческая символьная пи",
+	bull:"маркер списка\nчерный маленький кружок",
+	hellip:"многоточие\nтри точки",
+	prime:"штрих\nминуты\nфуты",
+	Prime:"двойной штрих\nсекунды\nдюймы",
+	oline:"верхняя черта\nнадчеркивание с интервалом",
+	frasl:"косая черта",
+	weierp:"рукописная прописная P\nстепенное множество\nфункции Вейерштрасса",
+	image:"черная прописная I\nмнимая часть",
+	real:"черная прописная R\nвещественная часть",
+	trade:"символ товарного знака",
+	alefsym:"буква Алеф\nкардинальное число",
+	larr:"стрелка влево",
+	uarr:"стрелка вверх",
+	rarr:"стрелка вправо",
+	darr:"стрелка вниз",
+	harr:"стрелка влево-вправо",
+	crarr:"стрелка вниз с углом вправо\nвозврат каретки",
+	lArr:"двойная стрелка влево",
+	uArr:"двойная стрелка вверх",
+	rArr:"двойная стрелка вправо",
+	dArr:"двойная стрелка вниз",
+	hArr:"двойная стрелка влево-вправо",
+	forall:"для всех",
+	part:"частичный дифференциал",
+	exist:"существует",
+	empty:"пустой набор\nпустое множество\nдиаметр",
+	nabla:"оператор набла\nразностное отношение назад",
+	isin:"является элементом",
+	notin:"не является элементом",
+	ni:"содержит в качестве элемента",
+	prod:"n-арное произведение\nсимвол произведения",
+	sum:"n-арное суммирование",
+	minus:"знак минуса",
+	lowast:"оператор звездочка",
+	radic:"квадратный корень\nзнак корня",
+	prop:"пропорционально",
+	infin:"бесконечность",
+	ang:"угол",
+	and:"логическое И\nклин вверх",
+	or:"логическое ИЛИ\nклин вниз",
+	cap:"пересечение\nшапочка",
+	cup:"объединение\nчашечка","int":"интеграл",
+	there4:"следовательно",
+	sim:"оператор тильда\nизменяться с\nподобно",
+	cong:"приблизительно равно",
+	asymp:"почти равно\nасимптотично",
+	ne:"не равно",
+	equiv:"идентично",
+	le:"меньше или равно",
+	ge:"больше или равно",
+	sub:"подмножество",
+	sup:"включает в себя",
+	nsub:"не является подмножеством",
+	sube:"является подмножеством или эквивалентно",
+	supe:"включает в себя или эквивалентно",
+	oplus:"плюс в круге\nпрямая сумма",
+	otimes:"умножение в круге\nвекторное произведение",
+	perp:"перевернутый гвоздь\nортогонально к\nперпендикулярно",
+	sdot:"оператор точка",
+	lceil:"левая скобка округления вверх\nAPL upstile",
+	rceil:"правая скобка округления вверх",
+	lfloor:"левая скобка округления вниз\nAPL downstile",
+	rfloor:"правая скобка округления вниз",
+	lang:"левая угловая скобка",
+	rang:"правая угловая скобка",
+	loz:"ромб",
+	spades:"пики",
+	clubs:"крести\nтрилистник",
+	hearts:"червы\nвалентинка",
+	diams:"бубны",
+	OElig:"латинская прописная лигатура OE",
+	oelig:"латинская строчная лигатура oe",
+	Scaron:"латинская прописная буква S с галочкой",
+	scaron:"латинская строчная буква s с галочкой",
+	Yuml:"латинская прописная буква Y с тремой",
+	circ:"надстрочный знак циркумфлекс",
+	tilde:"малая тильда",
+	ensp:"пробел длины N",
+	emsp:"пробел длины M",
+	thinsp:"узкий пробел",
+	zwnj:"разделитель нулевой ширины",
+	zwj:"соединитель нулевой ширины",
+	lrm:"знак слева-направо",
+	rlm:"знак справа-налево",
+	ndash:"тире длины N",
+	mdash:"тире длины M",
+	lsquo:"левая одинарная кавычка",
+	rsquo:"правая одинарная кавычка",
+	sbquo:"одиночная нижняя кавычка",
+	ldquo:"левая двойная кавычка",
+	rdquo:"правая двойная кавычка",
+	bdquo:"двойная нижняя кавычка",
+	dagger:"крест",
+	Dagger:"двойной крест",
+	permil:"знак промилле",
+	lsaquo:"одинарная левая угловая кавычка",
+	rsaquo:"одинарная правая угловая кавычка",
+	euro:"символ евро"
+})
+
diff --git a/dojox/editor/plugins/nls/sk/TableDialog.js b/dojox/editor/plugins/nls/sk/TableDialog.js
index 94a37ab..4999d00 100644
--- a/dojox/editor/plugins/nls/sk/TableDialog.js
+++ b/dojox/editor/plugins/nls/sk/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Nastaviť","insertTableTitle":"Vložiť tabuľku","insertTableRowAfterLabel":"Pridať riadok za","center":"na stred","deleteTableColumnLabel":"Vymazať stĺpec","right":"vpravo","insertTableColumnBeforeLabel":"Pridať stĺpec pred","tableWidth":"Šírka tabuľky:","buttonInsert":"Vložiť","default":"štandardne","align":"Zarovnať:","insertTableRowBeforeLabel":"Pridať riadok pred","cellSpacing":"Rozstupy buniek:","pixels":"pixely","selectTableLabel":"Vybrať tabuľku","rows":"Riadky:","mod [...]
\ No newline at end of file
+({
+	insertTableTitle: "Vložiť tabuľku",
+	modifyTableTitle: "Upraviť tabuľku",
+	rows: "Riadky:",
+	columns: "Stĺpce:",
+	align: "Zarovnať:",
+	cellPadding: "Odsadenie obsahu buniek:",
+	cellSpacing: "Rozstupy buniek:",
+	tableWidth: "Šírka tabuľky:",
+	backgroundColor: "Farba pozadia:",
+	borderColor: "Farba rámčeka:",
+	borderThickness: "Hrúbka rámčeka",
+	percent: "percentá",
+	pixels: "pixely",
+	"default": "štandardne",
+	left: "vľavo",
+	center: "na stred",
+	right: "vpravo",
+	buttonSet: "Nastaviť", // translated elsewhere?
+	buttonInsert: "Vložiť",
+
+	selectTableLabel: "Vybrať tabuľku",
+	insertTableRowBeforeLabel: "Pridať riadok pred",
+	insertTableRowAfterLabel: "Pridať riadok za",
+	insertTableColumnBeforeLabel: "Pridať stĺpec pred",
+	insertTableColumnAfterLabel: "Pridať stĺpec za",
+	deleteTableRowLabel: "Vymazať riadok",
+	deleteTableColumnLabel: "Vymazať stĺpec"
+})
+
diff --git a/dojox/editor/plugins/nls/sl/TableDialog.js b/dojox/editor/plugins/nls/sl/TableDialog.js
index 22446e9..d8c8e1f 100644
--- a/dojox/editor/plugins/nls/sl/TableDialog.js
+++ b/dojox/editor/plugins/nls/sl/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"Nastavi","insertTableTitle":"Vstavi tabelo","insertTableRowAfterLabel":"Dodaj vrstico za","center":"na sredini","deleteTableColumnLabel":"Izbriši stolpec","right":"desno","insertTableColumnBeforeLabel":"Dodaj stolpec pred","tableWidth":"Širina tabele:","buttonInsert":"Vstavi","default":"privzeto","align":"Poravnaj:","insertTableRowBeforeLabel":"Dodaj vrstico pred","cellSpacing":"Razmik med celicami:","pixels":"pikslov","selectTableLabel":"Izberi tabelo","rows":"Vrstice:"," [...]
\ No newline at end of file
+({
+	insertTableTitle: "Vstavi tabelo",
+	modifyTableTitle: "Spremeni tabelo",
+	rows: "Vrstice:",
+	columns: "Stolpci:",
+	align: "Poravnaj:",
+	cellPadding: "Odmik celic:",
+	cellSpacing: "Razmik med celicami:",
+	tableWidth: "Širina tabele:",
+	backgroundColor: "Barva ozadja:",
+	borderColor: "Barva obrobe:",
+	borderThickness: "Debelina obrobe",
+	percent: "odstotkov",
+	pixels: "pikslov",
+	"default": "privzeto",
+	left: "levo",
+	center: "na sredini",
+	right: "desno",
+	buttonSet: "Nastavi", // translated elsewhere?
+	buttonInsert: "Vstavi",
+
+	selectTableLabel: "Izberi tabelo",
+	insertTableRowBeforeLabel: "Dodaj vrstico pred",
+	insertTableRowAfterLabel: "Dodaj vrstico za",
+	insertTableColumnBeforeLabel: "Dodaj stolpec pred",
+	insertTableColumnAfterLabel: "Dodaj stolpec za",
+	deleteTableRowLabel: "Izbriši vrstico",
+	deleteTableColumnLabel: "Izbriši stolpec"
+})
+
diff --git a/dojox/editor/plugins/nls/sv/TableDialog.js b/dojox/editor/plugins/nls/sv/TableDialog.js
index bf7db0e..c1212da 100644
--- a/dojox/editor/plugins/nls/sv/TableDialog.js
+++ b/dojox/editor/plugins/nls/sv/TableDialog.js
@@ -1 +1,29 @@
-({"buttonSet":"Ange","insertTableTitle":"Infoga tabell","insertTableRowAfterLabel":"Lägg till rad efter","center":"centrera","deleteTableColumnLabel":"Ta bort kolumn","right":"högerjustera","insertTableColumnBeforeLabel":"Lägg till kolumn före","tableWidth":"Tabellbredd:","buttonInsert":"Infoga","default":"standard","align":"Justera:","insertTableRowBeforeLabel":"Lägg till rad före","cellSpacing":"Cellavstånd:","pixels":"bildpunkter","selectTableLabel":"Välj tabell","rows":"Rader:","modi [...]
\ No newline at end of file
+({
+	insertTableTitle: "Infoga tabell",
+	modifyTableTitle: "Ändra tabell",
+	rows: "Rader:",
+	columns: "Kolumner:",
+	align: "Justera:",
+	cellPadding: "Cellutfyllnad:",
+	cellSpacing: "Cellavstånd:",
+	tableWidth: "Tabellbredd:",
+	backgroundColor: "Bakgrundsfärg:",
+	borderColor: "Ramfärg:",
+	borderThickness: "Ramtjocklek",
+	percent: "%",
+	pixels: "bildpunkter",
+	"default": "standard",
+	left: "vänsterjustera",
+	center: "centrera",
+	right: "högerjustera",
+	buttonSet: "Ange", // translated elsewhere?
+	buttonInsert: "Infoga",
+
+	selectTableLabel: "Välj tabell",
+	insertTableRowBeforeLabel: "Lägg till rad före",
+	insertTableRowAfterLabel: "Lägg till rad efter",
+	insertTableColumnBeforeLabel: "Lägg till kolumn före",
+	insertTableColumnAfterLabel: "Lägg till kolumn efter",
+	deleteTableRowLabel: "Ta bort rad",
+	deleteTableColumnLabel: "Ta bort kolumn"
+})
diff --git a/dojox/editor/plugins/nls/th/TableDialog.js b/dojox/editor/plugins/nls/th/TableDialog.js
index 5baeba0..e0ba34d 100644
--- a/dojox/editor/plugins/nls/th/TableDialog.js
+++ b/dojox/editor/plugins/nls/th/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"ตั้งค่า","insertTableTitle":"แทรกตาราง","insertTableRowAfterLabel":"เพิ่มแถวหลัง","center":"กึ่งกลาง","deleteTableColumnLabel":"ลบคอลัมน์","right":"ขวา","insertTableColumnBeforeLabel":"เพิ่มคอลัมน์ก่อน","tableWidth":"ความกว้างของตาราง:","buttonInsert":"แทรก","default":"ดีฟอลต์","align":"จัดตำแหน่ง:","insertTableRowBeforeLabel":"เพิ่มแถวก่อน","cellSpacing":"ระยะห่างเซลล์:","pixels":"พิกเซล","selectTableLabel":"เลือกตาราง","rows":"แถว:","modifyTableTitle":"ปรับเปลี่ยนตาราง", [...]
\ No newline at end of file
+({
+	insertTableTitle: "แทรกตาราง",
+	modifyTableTitle: "ปรับเปลี่ยนตาราง",
+	rows: "แถว:",
+	columns: "คอลัมน์:",
+	align: "จัดตำแหน่ง:",
+	cellPadding: "ส่วนเสริมเซลล์:",
+	cellSpacing: "ระยะห่างเซลล์:",
+	tableWidth: "ความกว้างของตาราง:",
+	backgroundColor: "สีพื้นหลัง:",
+	borderColor: "สีเส้นขอบ:",
+	borderThickness: "ความหนาเส้นขอบ",
+	percent: "เปอร์เซ็นต์",
+	pixels: "พิกเซล",
+	"default": "ดีฟอลต์",
+	left: "ซ้าย",
+	center: "กึ่งกลาง",
+	right: "ขวา",
+	buttonSet: "ตั้งค่า", // translated elsewhere?
+	buttonInsert: "แทรก",
+
+	selectTableLabel: "เลือกตาราง",
+	insertTableRowBeforeLabel: "เพิ่มแถวก่อน",
+	insertTableRowAfterLabel: "เพิ่มแถวหลัง",
+	insertTableColumnBeforeLabel: "เพิ่มคอลัมน์ก่อน",
+	insertTableColumnAfterLabel: "เพิ่มคอลัมน์หลัง",
+	deleteTableRowLabel: "ลบแถว",
+	deleteTableColumnLabel: "ลบคอลัมน์"
+})
+
diff --git a/dojox/editor/plugins/nls/tr/TableDialog.js b/dojox/editor/plugins/nls/tr/TableDialog.js
index 0cfb948..9df7cce 100644
--- a/dojox/editor/plugins/nls/tr/TableDialog.js
+++ b/dojox/editor/plugins/nls/tr/TableDialog.js
@@ -1 +1,29 @@
-({"buttonSet":"Ayarla","insertTableTitle":"Tablo Ekle","insertTableRowAfterLabel":"Satırı Arkasına Ekle","center":"orta","deleteTableColumnLabel":"Sütunu Sil","right":"sağ","insertTableColumnBeforeLabel":"Sütunu Önüne Ekle","tableWidth":"Tablo Genişliği","buttonInsert":"Ekle","default":"varsayılan","align":"Hizala:","insertTableRowBeforeLabel":"Satırı Önüne Ekle","cellSpacing":"Hücre Aralığı:","pixels":"piksel","selectTableLabel":"Tablo Seç","rows":"Satırlar:","modifyTableTitle":"Tabloyu [...]
\ No newline at end of file
+({
+	insertTableTitle: "Tablo Ekle",
+	modifyTableTitle: "Tabloyu Değiştir",
+	rows: "Satırlar:",
+	columns: "Sütunlar:",
+	align: "Hizala:",
+	cellPadding: "Hücre Doldurma:",
+	cellSpacing: "Hücre Aralığı:",
+	tableWidth: "Tablo Genişliği",
+	backgroundColor: "Arka Plan Rengi:",
+	borderColor: "Kenarlık Rengi: ",
+	borderThickness: "Kenarlık Kalınlığı",
+	percent: "yüzde",
+	pixels: "piksel",
+	"default": "varsayılan",
+	left: "sol",
+	center: "orta",
+	right: "sağ",
+	buttonSet: "Ayarla", // translated elsewhere?
+	buttonInsert: "Ekle",
+
+	selectTableLabel: "Tablo Seç",
+	insertTableRowBeforeLabel: "Satırı Önüne Ekle",
+	insertTableRowAfterLabel: "Satırı Arkasına Ekle",
+	insertTableColumnBeforeLabel: "Sütunu Önüne Ekle",
+	insertTableColumnAfterLabel: "Sütunu Arkasına Ekle",
+	deleteTableRowLabel: "Satırı Sil",
+	deleteTableColumnLabel: "Sütunu Sil"
+})
diff --git a/dojox/editor/plugins/nls/zh-tw/Breadcrumb.js b/dojox/editor/plugins/nls/zh-tw/Breadcrumb.js
index bdbf254..f11be70 100644
--- a/dojox/editor/plugins/nls/zh-tw/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/zh-tw/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"選取內容","deleteElement":"刪除元素","moveEnd":"將游標移到末尾","deleteContents":"刪除內容","nodeActions":"${nodeName} 動作","selectElement":"選取元素","moveStart":"將游標移到開頭"})
\ No newline at end of file
+({
+	"nodeActions": "${nodeName} 動作",
+	"selectContents": "選取內容",
+	"selectElement": "選取元素",
+	"deleteElement": "刪除元素",
+	"deleteContents": "刪除內容",
+	"moveStart": "將游標移到開頭",
+	"moveEnd": "將游標移到末尾"
+})
+
diff --git a/dojox/editor/plugins/nls/zh-tw/FindReplace.js b/dojox/editor/plugins/nls/zh-tw/FindReplace.js
index 9085487..a47f3bd 100644
--- a/dojox/editor/plugins/nls/zh-tw/FindReplace.js
+++ b/dojox/editor/plugins/nls/zh-tw/FindReplace.js
@@ -1 +1,12 @@
-({"backwards":"向後","findReplace":"切換尋找/取代","replaceAll":"所有出現位置","replaceDialogText":"取代了 ${0} 項。","replaceButton":"取代","findButton":"尋找","findLabel":"尋找目標:","matchCase":"大小寫相符","replaceLabel":"取代為:"})
\ No newline at end of file
+({
+	"findLabel": "尋找目標:",
+	"replaceLabel": "取代為:",
+	"findReplace": "切換尋找/取代",
+	"matchCase": "大小寫相符", 
+	"backwards": "向後",
+	"replaceAll": "所有出現位置", 
+	"findButton": "尋找",
+	"replaceButton": "取代",
+	"replaceDialogText": "取代了 ${0} 項。"
+})
+
diff --git a/dojox/editor/plugins/nls/zh-tw/InsertEntity.js b/dojox/editor/plugins/nls/zh-tw/InsertEntity.js
index 5f3ae31..518c8bb 100644
--- a/dojox/editor/plugins/nls/zh-tw/InsertEntity.js
+++ b/dojox/editor/plugins/nls/zh-tw/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"插入符號"})
\ No newline at end of file
+({
+	insertEntity: "插入符號"
+})
+
diff --git a/dojox/editor/plugins/nls/zh-tw/PageBreak.js b/dojox/editor/plugins/nls/zh-tw/PageBreak.js
index d123553..06ee863 100644
--- a/dojox/editor/plugins/nls/zh-tw/PageBreak.js
+++ b/dojox/editor/plugins/nls/zh-tw/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"分頁"})
\ No newline at end of file
+({
+	"pageBreak": "分頁"
+})
+
diff --git a/dojox/editor/plugins/nls/zh-tw/Preview.js b/dojox/editor/plugins/nls/zh-tw/Preview.js
index f2129f8..fc90ca3 100644
--- a/dojox/editor/plugins/nls/zh-tw/Preview.js
+++ b/dojox/editor/plugins/nls/zh-tw/Preview.js
@@ -1 +1,4 @@
-({"preview":"預覽"})
\ No newline at end of file
+({
+	"preview": "預覽"
+})
+
diff --git a/dojox/editor/plugins/nls/zh-tw/Save.js b/dojox/editor/plugins/nls/zh-tw/Save.js
index eceafbc..427d545 100644
--- a/dojox/editor/plugins/nls/zh-tw/Save.js
+++ b/dojox/editor/plugins/nls/zh-tw/Save.js
@@ -1 +1,4 @@
-({"save":"儲存"})
\ No newline at end of file
+({
+	"save": "儲存"
+})
+
diff --git a/dojox/editor/plugins/nls/zh-tw/ShowBlockNodes.js b/dojox/editor/plugins/nls/zh-tw/ShowBlockNodes.js
index f23ec5c..808865a 100644
--- a/dojox/editor/plugins/nls/zh-tw/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/zh-tw/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"顯示 HTML 區塊元素"})
\ No newline at end of file
+({
+	"showBlockNodes": "顯示 HTML 區塊元素"
+})
+
diff --git a/dojox/editor/plugins/nls/zh-tw/Smiley.js b/dojox/editor/plugins/nls/zh-tw/Smiley.js
index eba6a60..07d3f50 100644
--- a/dojox/editor/plugins/nls/zh-tw/Smiley.js
+++ b/dojox/editor/plugins/nls/zh-tw/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"大笑","emoticonCool":"酷","emoticonTongue":"吐舌頭","emoticonCrying":"哭泣","emoticonOops":"哎喲","emoticonFrown":"皺眉","emoticonAngry":"生氣","emoticonShy":"羞怯","emoticonNo":"不對","emoticonAngel":"守護神","smiley":"插入表情符號","emoticonIdea":"思考","emoticonEyebrow":"揚眉","emoticonSmile":"微笑","emoticonWink":"眨眼","emoticonYes":"對","emoticonGrin":"露齒而笑","emoticonGoofy":"傻了","emoticonHalf":"左右為難"})
\ No newline at end of file
+({
+	smiley: "插入表情符號",
+	emoticonSmile: "微笑",
+	emoticonLaughing: "大笑",
+	emoticonWink: "眨眼",
+	emoticonGrin: "露齒而笑",
+	emoticonCool: "酷",
+	emoticonAngry: "生氣",  
+	emoticonHalf: "左右為難", 
+	emoticonEyebrow: "揚眉",
+	emoticonFrown: "皺眉",
+	emoticonShy: "羞怯",
+	emoticonGoofy: "傻了",
+	emoticonOops: "哎喲",
+	emoticonTongue: "吐舌頭",
+	emoticonIdea: "思考",
+	emoticonYes: "對",
+	emoticonNo: "不對",	
+	emoticonAngel: "守護神",
+	emoticonCrying: "哭泣"
+})
+
diff --git a/dojox/editor/plugins/nls/zh-tw/TableDialog.js b/dojox/editor/plugins/nls/zh-tw/TableDialog.js
index 00168b5..561d6df 100644
--- a/dojox/editor/plugins/nls/zh-tw/TableDialog.js
+++ b/dojox/editor/plugins/nls/zh-tw/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"設定","insertTableTitle":"插入表格","insertTableRowAfterLabel":"在後面新增一個列","center":"置中","deleteTableColumnLabel":"刪除欄","right":"靠右","insertTableColumnBeforeLabel":"在前面新增一個直欄","tableWidth":"表格寬度:","buttonInsert":"插入","default":"預設值","align":"對齊:","insertTableRowBeforeLabel":"在前面新增一個列","cellSpacing":"資料格間距:","pixels":"像素","selectTableLabel":"選取表格","rows":"列:","modifyTableTitle":"修改表格","cellPadding":"資料格行距:","deleteTableRowLabel":"刪除列","backgroundColor":"背景顏色:","insertTableColumnAf [...]
\ No newline at end of file
+({
+	insertTableTitle: "插入表格",
+	modifyTableTitle: "修改表格",
+	rows: "列:",
+	columns: "欄:",
+	align: "對齊:",
+	cellPadding: "資料格行距:",
+	cellSpacing: "資料格間距:",
+	tableWidth: "表格寬度:",
+	backgroundColor: "背景顏色:",
+	borderColor: "邊框顏色:",
+	borderThickness: "邊框寬度",
+	percent: "百分比",
+	pixels: "像素",
+	"default": "預設值",
+	left: "靠左",
+	center: "置中",
+	right: "靠右",
+	buttonSet: "設定", // translated elsewhere?
+	buttonInsert: "插入",
+
+	selectTableLabel: "選取表格",
+	insertTableRowBeforeLabel: "在前面新增一個列",
+	insertTableRowAfterLabel: "在後面新增一個列",
+	insertTableColumnBeforeLabel: "在前面新增一個直欄",
+	insertTableColumnAfterLabel: "在後面新增一個直欄",
+	deleteTableRowLabel: "刪除列",
+	deleteTableColumnLabel: "刪除欄"
+})
+
diff --git a/dojox/editor/plugins/nls/zh-tw/latinEntities.js b/dojox/editor/plugins/nls/zh-tw/latinEntities.js
index 7799926..3b7da3f 100644
--- a/dojox/editor/plugins/nls/zh-tw/latinEntities.js
+++ b/dojox/editor/plugins/nls/zh-tw/latinEntities.js
@@ -1 +1,257 @@
-({"le":"小於或等於","prod":"n 元積\n積符號","zwj":"零寬連字符","mdash":"長破折號","frasl":"分數斜線","upsih":"帶鉤的希臘文 upsilon 符號","prop":"成比例","middot":"中點號\n中心點\n希臘中點","hellip":"水平省略號\n三個點開頭","eta":"希臘文小寫字母 η","iacute":"帶揚音符的拉丁文小寫字母 i","yen":"日圓符號\n人民幣符號","rlm":"從右到左標記","macr":"長音符\n間隔長音符\n上線\nAPL 上線","ldquo":"左雙引號","Icirc":"帶抑揚音符的拉丁文大寫字母 I","OElig":"拉丁文大寫連字 OE","hArr":"左右雙箭頭","eth":"拉丁文小寫字母 eth","divide":"除號","chi":"希臘文小寫字母 χ","eacute":"帶揚音符的拉丁文小寫字母 e","icirc":"帶抑揚音符的拉丁文小寫字母 i","iexcl":"倒感歎號","ETH":"拉丁文大寫字母 E [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"倒感歎號",
+	cent:"英分",
+	pound:"英鎊",
+	curren:"貨幣符號",
+	yen:"日圓符號\n人民幣符號",
+	brvbar:"斷開的豎線\n斷開的垂直線",
+	sect:"小節符號",
+	uml:"分音符號\n元音分音",
+	copy:"著作權符號",
+	ordf:"陰性序數指示符",
+	laquo:"左尖雙角引號\n左尖雙引號",
+	not:"非符號",
+	shy:"軟連字號\n自由選定的連字號",
+	reg:"已註冊符號\n註冊商標符號",
+	macr:"長音符\n間隔長音符\n上線\nAPL 上線",
+	deg:"度號",
+	plusmn:"加減符號\n正負號",
+	sup2:"上標 2\n上標數字 2\n平方",
+	sup3:"上標 3\n上標數字 3\n立方",
+	acute:"揚音符\n揚音符",
+	micro:"µ 符號",
+	para:"¶ 符號\n段落符號",
+	middot:"中點號\n中心點\n希臘中點",
+	cedil:"軟音符號\n間距軟音符號",
+	sup1:"上標 1\n上標數字 1",
+	ordm:"陽性序數指示符",
+	raquo:"右尖雙角引號\n右尖雙引號",
+	frac14:"普通分數四分之一\n分數四分之一",
+	frac12:"普通分數二分之一\n分數二分之一",
+	frac34:"普通分數四分之三\n分數四分之三",
+	iquest:"顛倒的問號\n倒轉的問號",
+	Agrave:"帶抑音符的拉丁文大寫字母 A\n帶抑音符的拉丁文大寫字母 A",
+	Aacute:"帶揚音符的拉丁文大寫字母 A",
+	Acirc:"帶抑揚音符的拉丁文大寫字母 A",
+	Atilde:"帶顎化符的拉丁文大寫字母 A",
+	Auml:"帶分音符的拉丁文大寫字母 A",
+	Aring:"帶上圓圈的拉丁文大寫字母 A\n帶上圓圈的拉丁文大寫字母 A",
+	AElig:"拉丁文大寫字母 AE\n拉丁文大寫連字 AE",
+	Ccedil:"帶軟音符號的拉丁文大寫字母 C",
+	Egrave:"帶抑音符的拉丁文大寫字母 E",
+	Eacute:"帶揚音符的拉丁文大寫字母 E",
+	Ecirc:"帶抑揚音符的拉丁文大寫字母 E",
+	Euml:"帶分音符的拉丁文大寫字母 E",
+	Igrave:"帶抑音符的拉丁文大寫字母 I",
+	Iacute:"帶揚音符的拉丁文大寫字母 I",
+	Icirc:"帶抑揚音符的拉丁文大寫字母 I",
+	Iuml:"帶分音符的拉丁文大寫字母 I",
+	ETH:"拉丁文大寫字母 ETH",
+	Ntilde:"帶顎化符的拉丁文大寫字母 N",
+	Ograve:"帶抑音符的拉丁文大寫字母 O",
+	Oacute:"帶揚音符的拉丁文大寫字母 O",
+	Ocirc:"帶抑揚音符的拉丁文大寫字母 O",
+	Otilde:"帶顎化符的拉丁文大寫字母O",
+	Ouml:"帶分音符的拉丁文大寫字母 O",
+	times:"乘號",
+	Oslash:"帶斜線的拉丁文大寫字母 O\n帶斜線的大寫字母 O",
+	Ugrave:"帶抑音符的拉丁文大寫字母 U",
+	Uacute:"帶揚音符的拉丁文大寫字母 U",
+	Ucirc:"帶抑揚音符的拉丁文大寫字母 U",
+	Uuml:"帶分音符的拉丁文大寫字母 U",
+	Yacute:"帶揚音符的拉丁文大寫字母 Y",
+	THORN:"拉丁文大寫字母 THORN",
+	szlig:"拉丁文小寫字母 sharp s\ness-zed",
+	agrave:"帶抑音符的拉丁文小寫字母 a\n帶抑音符的拉丁文小寫字母 a",
+	aacute:"帶揚音符的拉丁文小寫字母 a",
+	acirc:"帶抑揚音符的拉丁文小寫字母 a",
+	atilde:"帶顎化符的拉丁文小寫字母 a",
+	auml:"帶分音符的拉丁文小寫字母 a",
+	aring:"帶上圓圈的拉丁文 a\n帶上圓圈的拉丁文 a",
+	aelig:"拉丁文小寫字母 ae\n拉丁文小寫連字 ae",
+	ccedil:"帶軟音符號的拉丁文小寫字母 c",
+	egrave:"帶抑音符的拉丁文小寫字母 e",
+	eacute:"帶揚音符的拉丁文小寫字母 e",
+	ecirc:"帶抑揚音符的拉丁文小寫字母 e",
+	euml:"帶分音符的拉丁文小寫字母 e",
+	igrave:"帶抑音符的拉丁文小寫字母 i",
+	iacute:"帶揚音符的拉丁文小寫字母 i",
+	icirc:"帶抑揚音符的拉丁文小寫字母 i",
+	iuml:"帶分音符的拉丁文小寫字母 i",
+	eth:"拉丁文小寫字母 eth",
+	ntilde:"帶顎化符的拉丁文小寫字母 n",
+	ograve:"帶抑音符的拉丁文小寫字母 o",
+	oacute:"帶揚音符的拉丁文小寫字母 o",
+	ocirc:"帶抑揚音符的拉丁文小寫字母 o",
+	otilde:"帶顎化符的拉丁文小寫字母 o",
+	ouml:"帶分音符的拉丁文小寫字母 o",
+	divide:"除號",
+	oslash:"帶斜線的拉丁文小寫字母 O\n帶斜線的小寫字母 o",
+	ugrave:"帶抑音符的拉丁文小寫字母 u",
+	uacute:"帶揚音符的拉丁文小寫字母 u",
+	ucirc:"帶抑揚音符的拉丁文小寫字母 u",
+	uuml:"帶分音符的拉丁文小寫字母 u",
+	yacute:"帶揚音符的拉丁文小寫字母 y",
+	thorn:"拉丁文小寫字母 thorn",
+	yuml:"帶分音符的拉丁文小寫字母 y",
+
+// Greek Characters and Symbols
+	fnof:"帶短畫的拉丁文小寫 f\n函數\n弗洛林幣",
+	Alpha:"希臘文大寫字母 Α",
+	Beta:"希臘文大寫字母 Β",
+	Gamma:"希臘文大寫字母 Γ",
+	Delta:"希臘文大寫字母 Δ",
+	Epsilon:"希臘文大寫字母 Ε",
+	Zeta:"希臘文大寫字母 Ζ",
+	Eta:"希臘文大寫字母 Η",
+	Theta:"希臘文大寫字母 Θ",
+	Iota:"希臘文大寫字母 Ι",
+	Kappa:"希臘文大寫字母 Κ",
+	Lambda:"希臘文大寫字母 Λ",
+	Mu:"希臘文大寫字母 Μ",
+	Nu:"希臘文大寫字母 Ν",
+	Xi:"希臘文大寫字母 Ξ",
+	Omicron:"希臘文大寫字母 Ο",
+	Pi:"希臘文大寫字母 Π",
+	Rho:"希臘文大寫字母 Ρ",
+	Sigma:"希臘文大寫字母 Σ",
+	Tau:"希臘文大寫字母 Τ",
+	Upsilon:"希臘文大寫字母 Υ",
+	Phi:"希臘文大寫字母 Φ",
+	Chi:"希臘文大寫字母 Χ",
+	Psi:"希臘文大寫字母 Ψ",
+	Omega:"希臘文大寫字母 Ω",
+	alpha:"希臘文小寫字母 α",
+	beta:"希臘文小寫字母 β",
+	gamma:"希臘文小寫字母 γ",
+	delta:"希臘文小寫字母 δ",
+	epsilon:"希臘文小寫字母 ε",
+	zeta:"希臘文小寫字母 ζ",
+	eta:"希臘文小寫字母 η",
+	theta:"希臘文小寫字母 θ",
+	iota:"希臘文小寫字母 ι",
+	kappa:"希臘文小寫字母 κ",
+	lambda:"希臘文小寫字母 λ",
+	mu:"希臘文小寫字母 μ",
+	nu:"希臘文小寫字母 ν",
+	xi:"希臘文小寫字母 ξ",
+	omicron:"希臘文小寫字母 ο",
+	pi:"希臘文小寫字母 π",
+	rho:"希臘文小寫字母 ρ",
+	sigmaf:"希臘文小寫字母 final sigma",
+	sigma:"希臘文小寫字母 σ",
+	tau:"希臘文小寫字母 τ",
+	upsilon:"希臘文小寫字母 υ",
+	phi:"希臘文小寫字母 φ",
+	chi:"希臘文小寫字母 χ",
+	psi:"希臘文小寫字母 ψ",
+	omega:"希臘文小寫字母 ω",
+	thetasym:"希臘文小寫字母 theta 符號",
+	upsih:"帶鉤的希臘文 upsilon 符號",
+	piv:"希臘文 pi 符號",
+	bull:"項目符號\n黑色小圓圈",
+	hellip:"水平省略號\n三個點開頭",
+	prime:"撇號\n分鐘\n英呎",
+	Prime:"雙撇號\n秒\n英吋",
+	oline:"上線\n間隔上線",
+	frasl:"分數斜線",
+	weierp:"Script 大寫 P\n冪集\nWeierstrass p",
+	image:"黑色大寫字母 I\n虛數部分",
+	real:"黑色大寫字母 R\n實數部分符號",
+	trade:"商標符號",
+	alefsym:"alef 符號\n第一個超窮基數",
+	larr:"向左箭頭",
+	uarr:"向上箭頭",
+	rarr:"向右箭頭",
+	darr:"向下箭頭",
+	harr:"左右箭頭",
+	crarr:"有向左轉的角的向下箭頭\n換行符號",
+	lArr:"向左雙箭頭",
+	uArr:"向上雙箭頭",
+	rArr:"向右雙箭頭",
+	dArr:"向下雙箭頭",
+	hArr:"左右雙箭頭",
+	forall:"全部",
+	part:"偏微分",
+	exist:"存在",
+	empty:"空集\n空集\n直徑",
+	nabla:"倒三角算子\n反向差分",
+	isin:"屬於",
+	notin:"不屬於",
+	ni:"包含",
+	prod:"n 元積\n積符號",
+	sum:"n 元和",
+	minus:"減號",
+	lowast:"星號運算子",
+	radic:"平方根\n根號",
+	prop:"成比例",
+	infin:"無限",
+	ang:"角符號",
+	and:"邏輯 AND\n楔形符號",
+	or:"邏輯 OR\nV 形符號",
+	cap:"交集\n蓋狀",
+	cup:"併集\n杯狀","int":"整數的",
+	there4:"因此",
+	sim:"波狀符號運算子\n偏離\n近似",
+	cong:"約等於",
+	asymp:"幾乎等於\n近似於",
+	ne:"不等於",
+	equiv:"完全相等",
+	le:"小於或等於",
+	ge:"大於或等於",
+	sub:"子集",
+	sup:"超集",
+	nsub:"非子集",
+	sube:"子集或等於",
+	supe:"超集或等於",
+	oplus:"帶圓圈的加號\n直和",
+	otimes:"帶圓圈的乘號\n向量積",
+	perp:"向上的釘子\n垂直於\n垂線",
+	sdot:"點運算子",
+	lceil:"左上限\nAPL 頂",
+	rceil:"右上限",
+	lfloor:"左下限\nAPL 底",
+	rfloor:"右下限",
+	lang:"左角括弧",
+	rang:"右角括弧",
+	loz:"菱形",
+	spades:"黑色黑桃",
+	clubs:"黑色梅花\n三葉草",
+	hearts:"黑色紅桃\n心形",
+	diams:"黑色方塊",
+	OElig:"拉丁文大寫連字 OE",
+	oelig:"拉丁文小寫連字 oe",
+	Scaron:"帶倒折音的拉丁文大寫字母 S",
+	scaron:"帶倒折音的拉丁文小寫字母 s",
+	Yuml:"帶分音符的拉丁文大寫字母 Y",
+	circ:"修飾元字母抑揚音符",
+	tilde:"小波狀符號",
+	ensp:"短破折號間距",
+	emsp:"長破折號間距",
+	thinsp:"薄間距",
+	zwnj:"零寬非連字符",
+	zwj:"零寬連字符",
+	lrm:"從左到右標記",
+	rlm:"從右到左標記",
+	ndash:"短破折號",
+	mdash:"長破折號",
+	lsquo:"左單引號",
+	rsquo:"右單引號",
+	sbquo:"9 形下標單引號",
+	ldquo:"左雙引號",
+	rdquo:"右雙引號",
+	bdquo:"9 形下標雙引號",
+	dagger:"單劍註釋符號",
+	Dagger:"雙劍註釋符號",
+	permil:"千分號",
+	lsaquo:"左尖單角引號",
+	rsaquo:"右尖單角引號",
+	euro:"歐元符號"
+})
+
diff --git a/dojox/editor/plugins/nls/zh/Breadcrumb.js b/dojox/editor/plugins/nls/zh/Breadcrumb.js
index 981e8ba..b813f20 100644
--- a/dojox/editor/plugins/nls/zh/Breadcrumb.js
+++ b/dojox/editor/plugins/nls/zh/Breadcrumb.js
@@ -1 +1,10 @@
-({"selectContents":"选择内容","deleteElement":"删除元素","moveEnd":"将光标移至结尾","deleteContents":"删除内容","nodeActions":"${nodeName} 操作","selectElement":"选择元素","moveStart":"将光标移至开头"})
\ No newline at end of file
+({
+	"nodeActions": "${nodeName} 操作",
+	"selectContents": "选择内容",
+	"selectElement": "选择元素",
+	"deleteElement": "删除元素",
+	"deleteContents": "删除内容",
+	"moveStart": "将光标移至开头",
+	"moveEnd": "将光标移至结尾"
+})
+
diff --git a/dojox/editor/plugins/nls/zh/FindReplace.js b/dojox/editor/plugins/nls/zh/FindReplace.js
index 12a17ae..21bdd40 100644
--- a/dojox/editor/plugins/nls/zh/FindReplace.js
+++ b/dojox/editor/plugins/nls/zh/FindReplace.js
@@ -1 +1,22 @@
-({"backwards":"向后","findReplace":"切换“查找/替换”","replaceAll":"所有出现位置","replaceDialogText":"已替换 ${0} 个出现位置。","replaceButton":"替换","findButton":"查找","findLabel":"查找对象:","matchCase":"大小写匹配","replaceLabel":"替换为:"})
\ No newline at end of file
+({
+	"findLabel": "查找对象:",
+	"findTooltip": "输入查找文本",
+	"replaceLabel": "替换为:",
+	"replaceTooltip": "输入替换文本",
+	"findReplace": "切换“查找/替换”",
+	"matchCase": "大小写匹配",
+	"matchCaseTooltip": "匹配大小写",
+	"backwards": "向后查找",
+	"backwardsTooltip": "向后查找文本",
+	"replaceAllButton": "全部替换",
+	"replaceAllButtonTooltip": "替换所有出现位置",
+	"findButton": "查找",
+	"findButtonTooltip": "查找该文本",
+	"replaceButton": "替换",
+	"replaceButtonTooltip": "替换该文本",
+	"replaceDialogText": "已替换 ${0} 个出现位置",
+	"eofDialogText": "已完成最后一次${0}",
+	"eofDialogTextFind": "查找",
+	"eofDialogTextReplace": "替换"
+})
+
diff --git a/dojox/editor/plugins/nls/zh/InsertEntity.js b/dojox/editor/plugins/nls/zh/InsertEntity.js
index 7a91988..86d00d3 100644
--- a/dojox/editor/plugins/nls/zh/InsertEntity.js
+++ b/dojox/editor/plugins/nls/zh/InsertEntity.js
@@ -1 +1,4 @@
-({"insertEntity":"插入符号"})
\ No newline at end of file
+({
+	insertEntity: "插入符号"
+})
+
diff --git a/dojox/editor/plugins/nls/zh/PageBreak.js b/dojox/editor/plugins/nls/zh/PageBreak.js
index 21dda43..49518ba 100644
--- a/dojox/editor/plugins/nls/zh/PageBreak.js
+++ b/dojox/editor/plugins/nls/zh/PageBreak.js
@@ -1 +1,4 @@
-({"pageBreak":"换页符"})
\ No newline at end of file
+({
+	"pageBreak": "换页符"
+})
+
diff --git a/dojox/editor/plugins/nls/zh/Preview.js b/dojox/editor/plugins/nls/zh/Preview.js
index c23904b..1ae149a 100644
--- a/dojox/editor/plugins/nls/zh/Preview.js
+++ b/dojox/editor/plugins/nls/zh/Preview.js
@@ -1 +1,4 @@
-({"preview":"预览"})
\ No newline at end of file
+({
+	"preview": "预览"
+})
+
diff --git a/dojox/editor/plugins/nls/zh/Save.js b/dojox/editor/plugins/nls/zh/Save.js
index 6ca26ff..dcfcf05 100644
--- a/dojox/editor/plugins/nls/zh/Save.js
+++ b/dojox/editor/plugins/nls/zh/Save.js
@@ -1 +1,4 @@
-({"save":"保存"})
\ No newline at end of file
+({
+	"save": "保存"
+})
+
diff --git a/dojox/editor/plugins/nls/zh/ShowBlockNodes.js b/dojox/editor/plugins/nls/zh/ShowBlockNodes.js
index 92b1038..322d393 100644
--- a/dojox/editor/plugins/nls/zh/ShowBlockNodes.js
+++ b/dojox/editor/plugins/nls/zh/ShowBlockNodes.js
@@ -1 +1,4 @@
-({"showBlockNodes":"显示 HTML 块元素"})
\ No newline at end of file
+({
+	"showBlockNodes": "显示 HTML 块元素"
+})
+
diff --git a/dojox/editor/plugins/nls/zh/Smiley.js b/dojox/editor/plugins/nls/zh/Smiley.js
index ec26e34..1c68e64 100644
--- a/dojox/editor/plugins/nls/zh/Smiley.js
+++ b/dojox/editor/plugins/nls/zh/Smiley.js
@@ -1 +1,22 @@
-({"emoticonLaughing":"大笑","emoticonCool":"酷","emoticonTongue":"吐舌","emoticonCrying":"哭泣","emoticonOops":"oops","emoticonFrown":"皱眉","emoticonAngry":"愤怒","emoticonShy":"害羞","emoticonNo":"摇头","emoticonAngel":"天使","smiley":"插入表情图标","emoticonIdea":"思考","emoticonEyebrow":"挑眉","emoticonSmile":"微笑","emoticonWink":"眨眼","emoticonYes":"点头","emoticonGrin":"咧着嘴笑","emoticonGoofy":"傻了","emoticonHalf":"左右为难"})
\ No newline at end of file
+({
+	smiley: "插入表情图标",
+	emoticonSmile: "微笑",
+	emoticonLaughing: "大笑",
+	emoticonWink: "眨眼",
+	emoticonGrin: "咧着嘴笑",
+	emoticonCool: "酷",
+	emoticonAngry: "愤怒",  
+	emoticonHalf: "左右为难", 
+	emoticonEyebrow: "挑眉",
+	emoticonFrown: "皱眉",
+	emoticonShy: "害羞",
+	emoticonGoofy: "傻了",
+	emoticonOops: "oops",
+	emoticonTongue: "吐舌",
+	emoticonIdea: "思考",
+	emoticonYes: "点头",
+	emoticonNo: "摇头",	
+	emoticonAngel: "天使",
+	emoticonCrying: "哭泣"
+})
+
diff --git a/dojox/editor/plugins/nls/zh/TableDialog.js b/dojox/editor/plugins/nls/zh/TableDialog.js
index 21e154d..0debf15 100644
--- a/dojox/editor/plugins/nls/zh/TableDialog.js
+++ b/dojox/editor/plugins/nls/zh/TableDialog.js
@@ -1 +1,30 @@
-({"buttonSet":"设置","insertTableTitle":"插入表","insertTableRowAfterLabel":"在之后添加行","center":"中间对齐","deleteTableColumnLabel":"删除列","right":"右边对齐","insertTableColumnBeforeLabel":"在之前添加列","tableWidth":"表宽度:","buttonInsert":"插入","default":"缺省值","align":"对齐:","insertTableRowBeforeLabel":"在之前添加行","cellSpacing":"单元格间距:","pixels":"像素","selectTableLabel":"选择表","rows":"行:","modifyTableTitle":"修改表","cellPadding":"单元格边距:","deleteTableRowLabel":"删除行","backgroundColor":"背景色:","insertTableColumnAfterLabel [...]
\ No newline at end of file
+({
+	insertTableTitle: "插入表",
+	modifyTableTitle: "修改表",
+	rows: "行:",
+	columns: "列:",
+	align: "对齐:",
+	cellPadding: "单元格边距:",
+	cellSpacing: "单元格间距:",
+	tableWidth: "表宽度:",
+	backgroundColor: "背景色:",
+	borderColor: "边框色:",
+	borderThickness: "边框厚度",
+	percent: "百分比",
+	pixels: "像素",
+	"default": "缺省值",
+	left: "左边对齐",
+	center: "中间对齐",
+	right: "右边对齐",
+	buttonSet: "设置", // translated elsewhere?
+	buttonInsert: "插入",
+
+	selectTableLabel: "选择表",
+	insertTableRowBeforeLabel: "在之前添加行",
+	insertTableRowAfterLabel: "在之后添加行",
+	insertTableColumnBeforeLabel: "在之前添加列",
+	insertTableColumnAfterLabel: "在之后添加列",
+	deleteTableRowLabel: "删除行",
+	deleteTableColumnLabel: "删除列"
+})
+
diff --git a/dojox/editor/plugins/nls/zh/latinEntities.js b/dojox/editor/plugins/nls/zh/latinEntities.js
index 29b3d8b..c1ad103 100644
--- a/dojox/editor/plugins/nls/zh/latinEntities.js
+++ b/dojox/editor/plugins/nls/zh/latinEntities.js
@@ -1 +1,257 @@
-({"le":"小于或等于","prod":"N 元积\n积符号","zwj":"零宽度连字符","mdash":"长破折号","frasl":"分数斜杠","upsih":"带挂钩符号的希腊字母 upsilon","prop":"成比例","middot":"中心点\n乔治逗号\n希腊中心点","hellip":"水平省略号\n三个点组成的标题","eta":"希腊小写字母 η","iacute":"带锐音符的拉丁小写字母 i","yen":"日元符号/人民币符号","rlm":"从右向左标记","macr":"长音符号\n间隔长音符号\n破折号\nAPL 破折号","ldquo":"左双引号","Icirc":"带抑扬符的拉丁大写字母 I","OElig":"拉丁大写连字 OE","hArr":"左右向双箭头","eth":"拉丁小写字母 eth","divide":"除号","chi":"希腊小写字母 χ","eacute":"带锐音符的拉丁小写字母 e","icirc":"带抑扬符的拉丁小写字母 i","iexcl":"反感叹号","ETH":"拉丁大写字母 E [...]
\ No newline at end of file
+({
+	/* These are already handled in the default RTE
+		amp:"ampersand",lt:"less-than sign",
+		gt:"greater-than sign",
+		nbsp:"no-break space\nnon-breaking space",
+		quot:"quote",
+	*/
+	iexcl:"反感叹号",
+	cent:"分币符号",
+	pound:"英镑符号",
+	curren:"货币符号",
+	yen:"日元符号/人民币符号",
+	brvbar:"横向虚线\n纵向虚线",
+	sect:"小节符号",
+	uml:"分音符\n间隔分音符",
+	copy:"版权符号",
+	ordf:"阴性序数指示符",
+	laquo:"左双尖括号\n左双尖括号",
+	not:"非符号",
+	shy:"软连字符\n自由选定连字符",
+	reg:"注册符号\n注册商标符号",
+	macr:"长音符号\n间隔长音符号\n破折号\nAPL 破折号",
+	deg:"度符号",
+	plusmn:"正负号\n正号或负号",
+	sup2:"上标 2\n上标数字 2\n平方",
+	sup3:"上标 3\n上标数字 3\n立方",
+	acute:"锐音符\n间隔锐音符",
+	micro:"μ 符号",
+	para:"段落符号\n段落符号",
+	middot:"中心点\n乔治逗号\n希腊中心点",
+	cedil:"软音符\n间隔软音符",
+	sup1:"上标 1\n上标数字 1",
+	ordm:"阳性序数指示符",
+	raquo:"右双尖括号\n右双尖括号",
+	frac14:"普通四分之一\n四分之一",
+	frac12:"普通二分之一\n二分之一",
+	frac34:"普通四分之三\n四分之三",
+	iquest:"倒问号\n倒问号",
+	Agrave:"带重音符的拉丁大写字母 A\n带重音符的拉丁大写字母 A",
+	Aacute:"带锐音符的拉丁大写字母 A",
+	Acirc:"带抑扬符的拉丁大写字母 A",
+	Atilde:"带颚化音的拉丁大写字母 A",
+	Auml:"带分音符的拉丁大写字母 A",
+	Aring:"带上圆圈的拉丁大写字母 A\n带圆圈的拉丁大写字母 A",
+	AElig:"拉丁大写字母 AE\n拉丁大写连字 AE",
+	Ccedil:"带软音符的拉丁大写字母 C",
+	Egrave:"带重音符的拉丁大写字母 E",
+	Eacute:"带锐音符的拉丁大写字母 E",
+	Ecirc:"带抑扬符的拉丁大写字母 E",
+	Euml:"带分音符的拉丁大写字母 E",
+	Igrave:"带重音符的拉丁大写字母 I",
+	Iacute:"带锐音符的拉丁大写字母 I",
+	Icirc:"带抑扬符的拉丁大写字母 I",
+	Iuml:"带分音符的拉丁大写字母 I",
+	ETH:"拉丁大写字母 ETH",
+	Ntilde:"带颚化音的拉丁大写字母 N",
+	Ograve:"带重音符的拉丁大写字母 O",
+	Oacute:"带锐音符的拉丁大写字母 O",
+	Ocirc:"带抑扬符的拉丁大写字母 O",
+	Otilde:"带颚化音的拉丁大写字母 O",
+	Ouml:"带分音符的拉丁大写字母 O",
+	times:"乘号",
+	Oslash:"带竖线的拉丁大写字母 O\n带斜杠的拉丁大写字母 O",
+	Ugrave:"带重音符的拉丁大写字母 U",
+	Uacute:"带锐音符的拉丁大写字母 U",
+	Ucirc:"带抑扬符的拉丁大写字母 U",
+	Uuml:"带分音符的拉丁大写字母 U",
+	Yacute:"带锐音符的拉丁大写字母 Y",
+	THORN:"拉丁大写字母 THORN",
+	szlig:"拉丁小写字母 sharp s\ness-zed",
+	agrave:"带重音符的拉丁小写字母 a\n带重音符的拉丁小写字母 a",
+	aacute:"带锐音符的拉丁小写字母 a",
+	acirc:"带抑扬符的拉丁小写字母 a",
+	atilde:"带颚化音的拉丁小写字母 a",
+	auml:"带分音符的拉丁小写字母 a",
+	aring:"带上圆圈的拉丁小写字母 a\n带圆圈的拉丁小写字母 a",
+	aelig:"拉丁小写字母 ae\n拉丁小写连字 ae",
+	ccedil:"带软音符的拉丁小写字母 c",
+	egrave:"带重音符的拉丁小写字母 e",
+	eacute:"带锐音符的拉丁小写字母 e",
+	ecirc:"带抑扬符的拉丁小写字母 e",
+	euml:"带分音符的拉丁小写字母 e",
+	igrave:"带重音符的拉丁小写字母 i",
+	iacute:"带锐音符的拉丁小写字母 i",
+	icirc:"带抑扬符的拉丁小写字母 i",
+	iuml:"带分音符的拉丁小写字母 i",
+	eth:"拉丁小写字母 eth",
+	ntilde:"带颚化音的拉丁小写字母 n",
+	ograve:"带重音符的拉丁小写字母 o",
+	oacute:"带锐音符的拉丁小写字母 o",
+	ocirc:"带抑扬符的拉丁小写字母 o",
+	otilde:"带颚化音的拉丁小写字母 o",
+	ouml:"带分音符的拉丁小写字母 o",
+	divide:"除号",
+	oslash:"带竖线的拉丁小写字母 o\n带斜杠的拉丁小写字母 o",
+	ugrave:"带重音符的拉丁小写字母 u",
+	uacute:"带锐音符的拉丁小写字母 u",
+	ucirc:"带抑扬符的拉丁小写字母 u",
+	uuml:"带分音符的拉丁小写字母 u",
+	yacute:"带锐音符的拉丁小写字母 y",
+	thorn:"拉丁小写字母 thorn",
+	yuml:"带分音符的拉丁小写字母 y",
+
+// Greek Characters and Symbols
+	fnof:"带挂钩符号的拉丁小写 f\n分数\nflorin",
+	Alpha:"希腊大写字母 Α",
+	Beta:"希腊大写字母 Β",
+	Gamma:"希腊大写字母 Γ",
+	Delta:"希腊大写字母 Δ",
+	Epsilon:"希腊大写字母 Ε",
+	Zeta:"希腊大写字母 Ζ",
+	Eta:"希腊大写字母 Η",
+	Theta:"希腊大写字母 Θ",
+	Iota:"希腊大写字母 Ι",
+	Kappa:"希腊大写字母 Κ",
+	Lambda:"希腊大写字母 Λ",
+	Mu:"希腊大写字母 Μ",
+	Nu:"希腊大写字母 Ν",
+	Xi:"希腊大写字母 Ξ",
+	Omicron:"希腊大写字母 Ο",
+	Pi:"希腊大写字母 Π",
+	Rho:"希腊大写字母 Ρ",
+	Sigma:"希腊大写字母 Σ",
+	Tau:"希腊大写字母 Τ",
+	Upsilon:"希腊大写字母 Υ",
+	Phi:"希腊大写字母 Φ",
+	Chi:"希腊大写字母 Χ",
+	Psi:"希腊大写字母 Ψ",
+	Omega:"希腊大写字母 Ω",
+	alpha:"希腊小写字母 α",
+	beta:"希腊小写字母 β",
+	gamma:"希腊小写字母 γ",
+	delta:"希腊小写字母 δ",
+	epsilon:"希腊小写字母 ε",
+	zeta:"希腊小写字母 ζ",
+	eta:"希腊小写字母 η",
+	theta:"希腊小写字母 θ",
+	iota:"希腊小写字母 ι",
+	kappa:"希腊小写字母 κ",
+	lambda:"希腊小写字母 λ",
+	mu:"希腊小写字母 μ",
+	nu:"希腊小写字母 ν",
+	xi:"希腊小写字母 ξ",
+	omicron:"希腊小写字母 ο",
+	pi:"希腊小写字母 π",
+	rho:"希腊小写字母 ρ",
+	sigmaf:"希腊小写字母 final sigma",
+	sigma:"希腊小写字母 σ",
+	tau:"希腊小写字母 τ",
+	upsilon:"希腊小写字母 υ",
+	phi:"希腊小写字母 φ",
+	chi:"希腊小写字母 χ",
+	psi:"希腊小写字母 ψ",
+	omega:"希腊小写字母 ω",
+	thetasym:"希腊小写字母 theta 符号",
+	upsih:"带挂钩符号的希腊字母 upsilon",
+	piv:"希腊 pi 符号",
+	bull:"子弹符号\n黑色小圆圈",
+	hellip:"水平省略号\n三个点组成的标题",
+	prime:"分钟符号\n分钟\n尺",
+	Prime:"秒符号\n秒\n寸",
+	oline:"顶线\n间隔顶线",
+	frasl:"分数斜杠",
+	weierp:"脚本大写 P\n幂集\nWeierstrass p",
+	image:"黑色大写字母 I\n虚部符号",
+	real:"黑色大写字母 R\n实部符号",
+	trade:"商标符号",
+	alefsym:"alef 符号\n第一个超限基数",
+	larr:"向左箭头",
+	uarr:"向上箭头",
+	rarr:"向右箭头",
+	darr:"向下箭头",
+	harr:"向左上箭头",
+	crarr:"回车符\n回车符",
+	lArr:"向左双箭头",
+	uArr:"向上双箭头",
+	rArr:"向右双箭头",
+	dArr:"向下双箭头",
+	hArr:"左右向双箭头",
+	forall:"全部",
+	part:"部分差分",
+	exist:"存在",
+	empty:"空集\n空集\n直径",
+	nabla:"劈形算符\n后向差分",
+	isin:"...的元素",
+	notin:"不是...的元素",
+	ni:"作为成员包含",
+	prod:"N 元积\n积符号",
+	sum:"N 元和",
+	minus:"负号",
+	lowast:"星号运算符",
+	radic:"平方根\n根号",
+	prop:"成比例",
+	infin:"无限",
+	ang:"角度",
+	and:"逻辑和\n尖三角形",
+	or:"逻辑或\n V 字形",
+	cap:"交集\n盖状",
+	cup:"并集n\n杯状","int":"整数",
+	there4:"因此",
+	sim:"颚化音运算符\n偏离\n相似",
+	cong:"约等于",
+	asymp:"几乎等于\n渐近",
+	ne:"不等于",
+	equiv:"完全相等",
+	le:"小于或等于",
+	ge:"大于或等于",
+	sub:"...的子集",
+	sup:"...的超集",
+	nsub:"不是...的子集",
+	sube:"...的子集或等于",
+	supe:"...的超集或等于",
+	oplus:"带圆圈的加号\n异或",
+	otimes:"带圆圈的乘号\n向量积",
+	perp:"倒 T\n正交于\n垂直",
+	sdot:"点运算符",
+	lceil:"左上限\nAPL 顶",
+	rceil:"右上限",
+	lfloor:"左下限\nAPL 底",
+	rfloor:"右下限",
+	lang:"左尖括号",
+	rang:"右尖括号",
+	loz:"菱形",
+	spades:"黑色桃形",
+	clubs:"黑色梅花形\n三叶草",
+	hearts:"黑色心形\n心形",
+	diams:"黑色菱形",
+	OElig:"拉丁大写连字 OE",
+	oelig:"拉丁小写连字 oe",
+	Scaron:"带倒折音的拉丁大写字母 S",
+	scaron:"带倒折音的拉丁小写字母 s",
+	Yuml:"带分音符的拉丁大写字母 Y",
+	circ:"修饰符字母抑扬符重音符",
+	tilde:"小颚化音符号",
+	ensp:"单倍间距",
+	emsp:"双倍间距",
+	thinsp:"窄空格",
+	zwnj:"零宽度非连字符",
+	zwj:"零宽度连字符",
+	lrm:"从左向右标记",
+	rlm:"从右向左标记",
+	ndash:"短破折号",
+	mdash:"长破折号",
+	lsquo:"左单引号",
+	rsquo:"右单引号",
+	sbquo:"低单引号",
+	ldquo:"左双引号",
+	rdquo:"右双引号",
+	bdquo:"低双引号",
+	dagger:"剑号",
+	Dagger:"双剑号",
+	permil:"千分率符号",
+	lsaquo:"左尖括号",
+	rsaquo:"右尖括号",
+	euro:"欧元符号"
+})
+
diff --git a/dojox/editor/plugins/resources/css/Blockquote.css b/dojox/editor/plugins/resources/css/Blockquote.css
new file mode 100755
index 0000000..5913042
--- /dev/null
+++ b/dojox/editor/plugins/resources/css/Blockquote.css
@@ -0,0 +1,17 @@
+.dijitAdditionalEditorIconBlockquote {
+	background-image: url(../icons/blockquote.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 18px;
+	height: 18px;
+}
+
+.dijitDisabled .dijitAdditionalEditorIconBlockquote {
+	background-image: url(../icons/blockquoteDisabled.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 18px;
+	height: 18px;
+}
+
+
diff --git a/dojox/editor/plugins/resources/css/Breadcrumb.css b/dojox/editor/plugins/resources/css/Breadcrumb.css
old mode 100644
new mode 100755
index 32b5c17..7b687be
--- a/dojox/editor/plugins/resources/css/Breadcrumb.css
+++ b/dojox/editor/plugins/resources/css/Breadcrumb.css
@@ -1,6 +1,7 @@
 .dojoxEditorBreadcrumbArrow .dijitDownArrowButton {
 	width: 10px;
 }
+
 .dojoxEditorBreadcrumbArrow .dijitArrowButtonInner {
 	background-image: url(../icons/breadcrumbDown.gif);
 	background-repeat: no-repeat;
@@ -8,3 +9,5 @@
 	width: 8px;
 	height: 8px;
 }
+
+
diff --git a/dojox/editor/plugins/resources/css/CollapsibleToolbar.css b/dojox/editor/plugins/resources/css/CollapsibleToolbar.css
new file mode 100644
index 0000000..fa9e40c
--- /dev/null
+++ b/dojox/editor/plugins/resources/css/CollapsibleToolbar.css
@@ -0,0 +1,173 @@
+.dojoxCollapsibleToolbarContainer {
+	border-collapse: collapse;
+	padding: 0px;
+	margin: 0px;
+	border-style: none;
+}
+
+.dojoxCollapsibleToolbarCollapse {
+	cursor: pointer;
+}
+
+.dojoxCollapsibleToolbarExpand {
+	cursor: pointer;
+}
+
+.claro .dojoxCollapsibleToolbarCollapse {
+	background-image: url(../images/claro/collapse.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 12px;
+	height: 12px;
+}
+
+.claro .dojoxCollapsibleToolbarExpand {
+	background-image: url(../images/claro/expand.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 12px;
+	height: 12px;
+}
+
+.claro .dojoxCollapsibleToolbarContainer {
+	background-color: #F1F1F1;
+}
+
+.claro .dojoxCollapsibleToolbarControl {
+	vertical-align: top;
+	border-bottom: 1px solid #ccc;
+	border-left: 1px solid #ccc;
+	border-right: 1px solid #ccc;
+        margin-bottom: 1px;
+}
+
+
+.tundra .dojoxCollapsibleToolbarCollapse {
+	background-image: url(../images/tundra/collapse.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 12px;
+	height: 12px;
+}
+
+.tundra .dojoxCollapsibleToolbarExpand {
+	background-image: url(../images/tundra/expand.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 12px;
+	height: 12px;
+}
+
+.tundra .dojoxCollapsibleToolbarContainer {
+	background-image: url(../images/tundra/sidebar.gif);
+	background-repeat: repeat-x;
+	background-position: top left;
+	background-color: #CCCCCC;
+}
+
+.tundra .dojoxCollapsibleToolbarControl {
+	vertical-align: top;
+	border-bottom: 1px solid #ccc;
+	border-left: 1px solid #ccc;
+	border-right: 1px solid #ccc;
+}
+
+.soria .dojoxCollapsibleToolbarCollapse {
+	background-image: url(../images/soria/collapse.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 12px;
+	height: 12px;
+}
+
+.soria .dojoxCollapsibleToolbarExpand {
+	background-image: url(../images/soria/expand.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 12px;
+	height: 12px;
+}
+
+.soria .dojoxCollapsibleToolbarContainer {
+	background-image: url(../images/soria/sidebar.gif);
+	background-repeat: repeat-x;
+	background-position: top left;
+	background-color: #CCCCCC;
+}
+
+.soria .dojoxCollapsibleToolbarControl {
+	vertical-align: top;    
+	border-bottom: 1px solid #ccc;
+	border-left: 1px solid #ccc;
+	border-right: 1px solid #ccc;
+}
+
+.nihilo .dojoxCollapsibleToolbarCollapse {
+	background-image: url(../images/nihilo/collapse.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 12px;
+	height: 12px;
+}
+
+.nihilo .dojoxCollapsibleToolbarExpand {
+	background-image: url(../images/nihilo/expand.gif);
+	background-repeat: no-repeat;
+	background-position: top left;
+	width: 12px;
+	height: 12px;
+}
+
+.nihilo .dojoxCollapsibleToolbarContainer {
+	background-image: url(../images/nihilo/sidebar.gif);
+	background-repeat: repeat-x;
+	background-position: top left;
+	background-color: #CCCCCC;
+}
+
+.nihilo .dojoxCollapsibleToolbarControl {
+	vertical-align: top;
+	border-bottom: 1px solid #ccc;
+	border-left: 1px solid #ccc;
+	border-right: 1px solid #ccc;
+}
+
+.dijit_a11y .dojoxCollapsibleToolbarCollapse {
+	border-style: outset;
+	border-width: 3px;
+	border-color: black;
+	width: 1.5em;
+	height: 100%;
+	text-align: center;
+	vertical-align: middle;
+}
+
+.dijit_a11y .dojoxCollapsibleToolbarExpand {
+	border-style: outset;
+	border-width: 3px;
+	border-color: black;
+	width: 1.5em;
+	height: 100%;
+	text-align: center;
+	vertical-align: middle;
+}
+
+.dojoxCollapsibleToolbarCollapseText {
+	display: none;
+}
+
+.dojoxCollapsibleToolbarExpandText {
+	display: none;
+}
+
+.dijit_a11y .dojoxCollapsibleToolbarCollapseText {
+	display: inline;
+	padding: 3px;
+	font-weight: bold;
+}
+
+.dijit_a11y .dojoxCollapsibleToolbarExpandText {
+	display: inline;
+	padding: 3px;
+	font-weight: bold; 
+}
diff --git a/dojox/editor/plugins/resources/css/FindReplace.css b/dojox/editor/plugins/resources/css/FindReplace.css
old mode 100644
new mode 100755
index 265925b..7e74456
--- a/dojox/editor/plugins/resources/css/FindReplace.css
+++ b/dojox/editor/plugins/resources/css/FindReplace.css
@@ -1,59 +1,72 @@
-.dijitAdditionalEditorIconFindReplace {
-        background-image: url(../icons/findReplace.gif);
-        background-repeat: no-repeat;
-        background-position: center center;
-        width: 18px;
-        height: 18px;
-}
-.dijitDisabled .dijitAdditionalEditorIconFindReplace {
-        background-image: url(../icons/findReplaceDisabled.gif);
-        background-repeat: no-repeat;
-        background-position: center center;
-        width: 18px;
-        height: 18px;
-}
-.dijitAdditionalEditorIconFindRun {
-        background-image: url(../icons/findIcon.gif);
-        background-repeat: no-repeat;
-        background-position: center center;
-        width: 18px;
-        height: 18px;
-        padding-left: 5px;
-        padding-right: 5px;
-}
-.dijitAdditionalEditorIconReplaceRun {
-        background-image: url(../icons/replaceIcon.gif);
-        background-repeat: no-repeat;
-        background-position: center center;
-        width: 18px;
-        height: 18px;
-        padding-left: 5px;
-        padding-right: 5px;
-}
-.dijitDisabled .dijitAdditionalEditorIconFindRun {
-        background-image: url(../icons/findIconDisabled.gif);
-        background-repeat: no-repeat;
-        background-position: center center;
-        width: 18px;
-        height: 18px;
-        padding-left: 5px;
-        padding-right: 5px;
-}
-.dijitDisabled .dijitAdditionalEditorIconReplaceRun {
-        background-image: url(../icons/replaceIconDisabled.gif);
-        background-repeat: no-repeat;
-        background-position: center center;
-        width: 18px;
-        height: 18px;
-        padding-left: 5px;
-        padding-right: 5px;
-}
-.findReplaceCheckBox {
-        padding-left: 10px;
-        padding-right: 10px;
-        text-align: center;
-}
-.findReplaceTextBox {
-        padding-top: 3px;
-        padding-bottom: 3px;
+.dijitEditorIconsFindReplace {
+	background-image: url('../icons/editorIconsFindReplaceEnabled.png');
+	background-repeat: no-repeat;
+	width: 18px;
+	height: 18px;
+	text-align: center;
 }
+
+.dijitDisabled .dijitEditorIconsFindReplace {
+	background-image: url('../icons/editorIconsFindReplaceDisabled.png');
+	background-repeat: no-repeat;
+	width: 18px;
+	height: 18px;
+	text-align: center;
+}
+
+.dijitEditorIconFindString { background-position: 0px; }
+
+.dijitEditorIconFind { background-position: -18px; }
+
+.dijitEditorIconReplace { background-position: -36px; }
+
+.dijitEditorIconReplaceAll { background-position: -54px; }
+
+.dijitEditorFindReplaceCheckBox {
+	padding-left: 10px;
+	padding-right: 10px;
+	text-align: center;
+}
+
+.dijitEditorFindReplaceTextBox {
+	padding-top: 3px;
+	padding-bottom: 3px;
+	padding-right: 5px;
+}
+
+.dijitEditorFindReplaceTextBox .focusTextBox {
+	width: 13em;
+}
+
+.tundra .dijitEditorIconsFindReplaceClose {
+        background-image: url('../icons/tundra/close.gif');
+	background-repeat: no-repeat;
+	width: 18px;
+	height: 18px;
+	background-position: center; 
+}
+
+.soria .dijitEditorIconsFindReplaceClose {
+        background-image: url('../icons/soria/close.gif');
+	background-repeat: no-repeat;
+	width: 18px;
+	height: 18px;
+	background-position: center; 
+}
+
+.nihilo .dijitEditorIconsFindReplaceClose {
+        background-image: url('../icons/nihilo/close.gif');
+	background-repeat: no-repeat;
+	width: 18px;
+	height: 18px;
+	background-position: center; 
+}
+
+.claro .dijitEditorIconsFindReplaceClose {
+        background-image: url('../icons/claro/close.gif');
+	background-repeat: no-repeat;
+	width: 18px;
+	height: 18px;
+	background-position: center; 
+}
+
diff --git a/dojox/editor/plugins/resources/css/InsertAnchor.css b/dojox/editor/plugins/resources/css/InsertAnchor.css
new file mode 100755
index 0000000..3f0dda5
--- /dev/null
+++ b/dojox/editor/plugins/resources/css/InsertAnchor.css
@@ -0,0 +1,17 @@
+.dijitAdditionalEditorIconInsertAnchor {
+	background-image: url(../icons/anchor.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 18px;
+	height: 18px;
+}
+
+.dijitDisabled .dijitAdditionalEditorIconInsertAnchor {
+	background-image: url(../icons/anchorDisabled.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 18px;
+	height: 18px;
+}
+
+
diff --git a/dojox/editor/plugins/resources/css/InsertEntity.css b/dojox/editor/plugins/resources/css/InsertEntity.css
old mode 100644
new mode 100755
index 735a8bb..cb790a0
--- a/dojox/editor/plugins/resources/css/InsertEntity.css
+++ b/dojox/editor/plugins/resources/css/InsertEntity.css
@@ -1,80 +1,69 @@
 .dijitAdditionalEditorIconInsertEntity {
+	/* icon in toolbar for this plugin */
 	background-image: url(../icons/insertEntity.gif);
 	background-repeat: no-repeat;
 	background-position: center center;
 	width: 18px;
 	height: 18px;
 }
+
 .dijitDisabled .dijitAdditionalEditorIconInsertEntity {
+	/* icon in toolbar for this plugin, when the plugin is disabled */
 	background-image: url(../icons/insertEntityDisabled.gif);
-	background-repeat: no-repeat;
-	background-position: center center;
-	width: 18px;
-	height: 18px;
 }
+
 .dojoxEntityPalette {
-	border:1px solid #999;
-	background:#fff;
-	-moz-border-radius:3pt;
-}
-.dojoxEntityPaletteTable {
-	position: relative;
-	overflow:hidden;
-	outline-color: black;
-	outline-style: none;
-	outline-width: 0;
-	border: 0px solid black;
-	border-collapse: separate;
-	border-spacing: 2px;
-	margin: 2px;
-	table-layout: auto;
+	/* outer node of the dropdown */
+	border: 1px solid #999;
+	background: #fff;
+	-moz-border-radius: 3pt;
 }
+
 .dojoxEntityPaletteCell {
+	/* individual cell of the drop down */
 	border: 1px dotted gray;
-	width: 20px;
-	height: 20px;
+	width: 20px;	/* todo: don't hardcode width/height; it's neither nececessary nor a11y safe */
+	line-height: 18px;
 	overflow: hidden;
 	z-index: 10;
 	text-align: center;
 }
-.dojoxEntityPaletteNullCell {
-	border: none;
-	width: 20px;
-	height: 20px;
-	overflow: hidden;
-}
-.dojoxEntityPaletteCellHighlight {
-	width: 16px; 
-	height: 14px; 
+
+.dojoxEntityPaletteCellHover, .dojoxEntityPaletteCellActive, .dojoxEntityPaletteCellFocused {
+	width: 18px;
+        line-height: 16px;
 	overflow: hidden;
 	cursor: default;
-	border:2px solid #000;
-	outline:1px solid #dedede;
+	border:1px dashed #000;
+	outline:1px dashed #dedede;
 }
+
+
 .dojoxEntityPalettePreviewTable {
 	table-layout: auto;
 	font-size: 1em;
 	width: 100%;
 }
+
 .dojoxEntityPalettePreviewHeader {
 	font-size: .8em;
 	padding: 3px 3px 3px 3px;
 }
+
 .dojoxEntityPalettePreviewDetailEntity {
 	font-size: 3em;
 	font-weight: bold;
 	width: 1em;
 	text-align: center;
 }
+
 .dojoxEntityPalettePreviewDetail {
 	font-size: 1em;
 	vertical-align: middle;
 	font-weight: bold;
 	padding: 3px 3px 3px 3px;
 }
+
 .dijit_a11y .dojoxEntityPaletteCell {
 	background-color:transparent !important;
 }
-.dijit_a11y .dojoxEntityPaletteImg {
-	background-color:transparent !important;
-}
diff --git a/dojox/editor/plugins/resources/css/PageBreak.css b/dojox/editor/plugins/resources/css/PageBreak.css
old mode 100644
new mode 100755
index 1a2bcd6..193b93b
--- a/dojox/editor/plugins/resources/css/PageBreak.css
+++ b/dojox/editor/plugins/resources/css/PageBreak.css
@@ -5,6 +5,7 @@
 	width: 18px;
 	height: 18px;
 }
+
 .dijitDisabled .dijitAdditionalEditorIconPageBreak {
 	background-image: url(../icons/pageBreakDisabled.gif);
 	background-repeat: no-repeat;
@@ -12,3 +13,5 @@
 	width: 18px;
 	height: 18px;
 }
+
+
diff --git a/dojox/editor/plugins/resources/css/PasteFromWord.css b/dojox/editor/plugins/resources/css/PasteFromWord.css
new file mode 100755
index 0000000..96622e5
--- /dev/null
+++ b/dojox/editor/plugins/resources/css/PasteFromWord.css
@@ -0,0 +1,30 @@
+.dijitAdditionalEditorIconPasteFromWord {
+	background-image: url(../icons/pasteFromWord.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 18px;
+	height: 18px;
+}
+
+.dijitDisabled .dijitAdditionalEditorIconPasteFromWord {
+	background-image: url(../icons/pasteFromWordDisabled.gif);
+	background-repeat: no-repeat;
+	background-position: center center;
+	width: 18px;
+	height: 18px;
+}
+
+.tundra .dijitPasteFromWordEmbeddedRTE .dijitEditor,
+.nihilo .dijitPasteFromWordEmbeddedRTE .dijitEditor {
+	border-color: #BFBFBF;
+	border-style: solid;
+	border-width: 1px;
+}
+
+.soria .dijitPasteFromWordEmbeddedRTE .dijitEditor {
+	border-color: #CCCCCC;
+	border-style: solid;
+	border-width: 1px;
+}
+
+
diff --git a/dojox/editor/plugins/resources/css/Preview.css b/dojox/editor/plugins/resources/css/Preview.css
old mode 100644
new mode 100755
index a5541eb..920f8d7
--- a/dojox/editor/plugins/resources/css/Preview.css
+++ b/dojox/editor/plugins/resources/css/Preview.css
@@ -5,6 +5,7 @@
 	width: 18px;
 	height: 18px;
 }
+
 .dijitDisabled .dijitAdditionalEditorIconPreview {
 	background-image: url(../icons/previewDisabled.gif);
 	background-repeat: no-repeat;
@@ -12,3 +13,5 @@
 	width: 18px;
 	height: 18px;
 }
+
+
diff --git a/dojox/editor/plugins/resources/css/Save.css b/dojox/editor/plugins/resources/css/Save.css
old mode 100644
new mode 100755
index 8970c56..e22b0f2
--- a/dojox/editor/plugins/resources/css/Save.css
+++ b/dojox/editor/plugins/resources/css/Save.css
@@ -5,6 +5,7 @@
 	width: 18px;
 	height: 18px;
 }
+
 .dijitDisabled .dijitAdditionalEditorIconSave {
 	background-image: url(../icons/saveDisabled.gif);
 	background-repeat: no-repeat;
@@ -12,3 +13,5 @@
 	width: 18px;
 	height: 18px;
 }
+
+
diff --git a/dojox/editor/plugins/resources/css/ShowBlockNodes.css b/dojox/editor/plugins/resources/css/ShowBlockNodes.css
old mode 100644
new mode 100755
index 8283480..48d139c
--- a/dojox/editor/plugins/resources/css/ShowBlockNodes.css
+++ b/dojox/editor/plugins/resources/css/ShowBlockNodes.css
@@ -5,6 +5,7 @@
 	width: 18px;
 	height: 18px;
 }
+
 .dijitDisabled .dijitAdditionalEditorIconShowBlockNodes {
 	background-image: url(../icons/showBlockNodesDisabled.gif);
 	background-repeat: no-repeat;
@@ -12,3 +13,5 @@
 	width: 18px;
 	height: 18px;
 }
+
+
diff --git a/dojox/editor/plugins/resources/css/Smiley.css b/dojox/editor/plugins/resources/css/Smiley.css
index 454f300..0aa19ab 100644
--- a/dojox/editor/plugins/resources/css/Smiley.css
+++ b/dojox/editor/plugins/resources/css/Smiley.css
@@ -1,69 +1,39 @@
 .dijitAdditionalEditorIconSmiley {
-	background-image: url(../icons/smiley.gif);
+	/* Toolbar icon for Smiley plugin */
 	background-repeat: no-repeat;
 	background-position: center center;
 	width: 18px;
 	height: 18px;
+	background-image: url(../icons/smiley.gif);
 }
+
 .dijitDisabled .dijitAdditionalEditorIconSmiley {
-	background-image: url(../icons/insertEntityDisabled.gif); 
-	background-repeat: no-repeat;
-	background-position: center center;
-	width: 18px;
-	height: 18px;
-}
-.dojoxEntityPalette {
-	border:1px solid #999;
-	background:#fff;
-	-moz-border-radius:3pt;
+	/* Toolbar icon for disabled Smiley plugin */
+	background-image: url(../icons/smileyDisabled.gif);
 }
-.dojoxEntityPaletteTable {
-	position: relative;
-	overflow:hidden;
-	outline-color: black;
-	outline-style: none;
-	outline-width: 0;
-	border: 0px solid black;
-	border-collapse: separate;
-	border-spacing: 2px;
-	margin: 2px;
-	table-layout: auto;
-}
-.dojoxEntityPaletteCell {
-	border: 1px dotted gray;
-	width: 20px;
-	height: 20px;
+
+.dijitEditorSmileyPalette {
+	border: 1px solid black;
+	background: white;
 	overflow: hidden;
-	z-index: 10;
-	text-align: center;
-}
-.dojoxEntityPaletteNullCell {
-	border: none;
-	width: 20px;
-	height: 20px;
-	overflow: hidden;
-}
-.dojoxEntityPaletteCellHighlight {
-	width: 16px; 
-	height: 14px; 
-	overflow: hidden;
-	cursor: default;
-	border:2px solid #000;
-	outline:1px solid #dedede;
-}
-.dijit_a11y .dojoxEntityPaletteCell {
-	background-color:transparent !important;
-}
-.dijit_a11y .dojoxSmileyPaletteImg {
-	background-color:transparent !important;
-}
-.dojoxSmileyPaletteImg {
-	width: 16px; 
-	height: 14px; 
-	top: 1px;
-	left: 1px;
-	overflow: hidden;
-	cursor: default;
-	border:1px solid #999;
-	
-}
+	overflow-x: hidden;
+	overflow-y: hidden;
+}
+
+.dijitEditorSmileyPalette .dijitPaletteCell {
+    height: 23px;
+    width: 27px;
+}
+
+.dijitEditorSmileyPalette .dijitPaletteImg {
+    border: none;
+    height: 20px;
+    width: 20px;
+    padding: 2px 2px;
+}
+
+.dijitEditorSmileyPalette .dijitPaletteCellHover .dijitPaletteImg {
+	border: 1px solid black;
+	padding: 1px 1px;
+}
+
diff --git a/dojox/editor/plugins/resources/css/StatusBar.css b/dojox/editor/plugins/resources/css/StatusBar.css
new file mode 100755
index 0000000..fd6414c
--- /dev/null
+++ b/dojox/editor/plugins/resources/css/StatusBar.css
@@ -0,0 +1,75 @@
+ at import "../../../../layout/resources/ResizeHandle.css"; 
+
+.dojoxEditorStatusBar {
+        overflow: hidden;
+        vertical-align: bottom;
+        padding: 2px; 
+}
+
+.dojoxEditorStatusBar table {
+        width: 100%;
+}
+
+.dojoxEditorStatusBar .dojoxResizeHandle {
+        position: static;
+        padding: 0px;
+        vertical-align: bottom; 
+}
+
+.dojoxEditorStatusBar .dojoxEditorStatusBarText{
+        height: 1.5em;
+        vertical-align: middle; 
+        width: 100%;
+        overflow: hidden;
+}
+
+.claro .dojoxEditorStatusBar {
+        background-color: #F1F1F1;
+}
+
+.claro .dojoxEditorStatusBar .dojoxEditorStatusBarText{
+        border-style: solid;
+        border-width: 1px;
+        border-color: #B5BCC7;
+        
+}
+
+.tundra .dojoxEditorStatusBar {
+        background-color: #EAEAEA;
+}
+
+.tundra .dojoxEditorStatusBar .dojoxEditorStatusBarText{
+        border-style: solid;
+        border-width: 1px;
+        border-color: #CCCCCC;
+        
+}
+
+.nihilo .dojoxEditorStatusBar {
+        border-style: solid;
+        background-color: #FFFFFF;
+        border-width: 1px;
+        border-color: #CCCCCC;
+}
+
+.nihilo .dojoxEditorStatusBar .dojoxEditorStatusBarText {
+        border-style: solid;
+        border-width: 1px;
+        border-color: #CCCCCC;
+        
+}
+
+.soria .dojoxEditorStatusBar {
+        border-style: solid;
+        background-color: #BDD6F0;
+        border-width: 1px;
+        border-color: #698FB3;
+}
+
+.soria .dojoxEditorStatusBar .dojoxEditorStatusBarText {
+        border-style: solid;
+        border-width: 1px;
+        border-color: #698FB3;
+        
+}
+
diff --git a/dojox/editor/plugins/resources/css/TextColor.css b/dojox/editor/plugins/resources/css/TextColor.css
new file mode 100644
index 0000000..196b1e2
--- /dev/null
+++ b/dojox/editor/plugins/resources/css/TextColor.css
@@ -0,0 +1,7 @@
+ at import "../../../../widget/ColorPicker/ColorPicker.css";
+
+.dojoxEditorColorPicker {
+	overflow: hidden;
+	overflow-x: hidden;
+	overflow-y: hidden;
+}
diff --git a/dojox/editor/plugins/resources/editorPlugins.css b/dojox/editor/plugins/resources/editorPlugins.css
index b3db6ce..d8c4661 100644
--- a/dojox/editor/plugins/resources/editorPlugins.css
+++ b/dojox/editor/plugins/resources/editorPlugins.css
@@ -1,5 +1,6 @@
-
+/* Editor Table Dialog */
 .EditorTableDialog{
+
 }
 .EditorTableDialog .etdTable{
 	width:350px;
@@ -46,6 +47,7 @@
 	margin-top:10px;
 	cursor:pointer;
 }
+
 .colorSwatchBtn{
 	display:block;
 	border:#666666 2px solid;
@@ -64,6 +66,8 @@
 	height:16px;
 	cursor:pointer;
 }
+
+/* Editor Buttons */
 .editorIcon{
 	background-image:url(images/tableIcons.png);
 	background-repeat: no-repeat;
@@ -74,8 +78,10 @@
 .editorIconUploadImage{
 	background:url(images/uploadImageIcon.gif) no-repeat 0px 4px;
 }
+
 .editorIconInsertTable{				
 	background-position:0px 0px;	}
+
 .editorIconInsertTableRowBefore{ 	
 	background-position:-19px 0px;	}
 .dijitDisabled .editorIconInsertTableRowBefore{ 	
@@ -85,6 +91,7 @@
 	background-position:-35px 0px;	}
 .dijitDisabled .editorIconInsertTableRowAfter{ 	
 	background-position:-136px 0px;	}
+
 .editorIconInsertTableColumnBefore{ 	
 	background-position:-52px 0px;	}
 .dijitDisabled .editorIconInsertTableColumnBefore{ 	
@@ -109,15 +116,21 @@
 	background-position:-222px 0px;	}
 .dijitDisabled .editorIconColorTableCell{ 	
 	background-position:-239px 0px;	}
+
 .editorIconModifyTable{ 	
 	background-position:-256px 0px;	}
 .dijitDisabled .editorIconModifyTable{ 	
 	background-position:-273px 0px;	}
+
+
+
+
 .RichTextEditable .dijitTextBox, 
 .RichTextEditable .dijitComboBox,
 .RichTextEditable  .dijitSpinner {
 	width: 5em;
 }
+
 .dojoxDropDownSelect {
 	background:#FFFFFF url(images/dropBk.png) repeat-x scroll left top;
 	border: 1px solid;
@@ -136,11 +149,13 @@
 	text-align:left;
 	color:#8397b9;
 }
+
 .dijitButtonNode .dijitArrowButtonInner{
-	
+	/* fixing the dijit drop arrows - can't figure why this broke */
 	background:url(../../../../dijit/themes/tundra/images/spriteArrows.png) no-repeat left top;
 	width:7px;
 }
+
 .dojoxEditorUploadNorm{
 	font-family:Arial;
 	font-size:12px;
@@ -156,6 +171,7 @@
 	cursor: pointer;
 	background: #ccc url("images/uploadImageIcon.gif") no-repeat 2px 2px;
 }
+
 .dojoxEditorUploadHover{
 	background: #ccc url("images/uploadImageIcon.gif") no-repeat 2px 0px;
 }
diff --git a/dojox/editor/plugins/resources/icons/anchor.gif b/dojox/editor/plugins/resources/icons/anchor.gif
new file mode 100755
index 0000000..f58992d
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/anchor.gif differ
diff --git a/dojox/editor/plugins/resources/icons/anchorDisabled.gif b/dojox/editor/plugins/resources/icons/anchorDisabled.gif
new file mode 100755
index 0000000..54e17b9
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/anchorDisabled.gif differ
diff --git a/dojox/editor/plugins/resources/icons/blockquote.gif b/dojox/editor/plugins/resources/icons/blockquote.gif
new file mode 100755
index 0000000..ec472c7
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/blockquote.gif differ
diff --git a/dojox/editor/plugins/resources/icons/blockquoteDisabled.gif b/dojox/editor/plugins/resources/icons/blockquoteDisabled.gif
new file mode 100755
index 0000000..0c5886d
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/blockquoteDisabled.gif differ
diff --git a/dojox/editor/plugins/resources/icons/breadcrumbDown.gif b/dojox/editor/plugins/resources/icons/breadcrumbDown.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/icons/claro/close.gif b/dojox/editor/plugins/resources/icons/claro/close.gif
new file mode 100755
index 0000000..7e792db
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/claro/close.gif differ
diff --git a/dojox/editor/plugins/resources/icons/editorIconsFindReplaceDisabled.png b/dojox/editor/plugins/resources/icons/editorIconsFindReplaceDisabled.png
new file mode 100644
index 0000000..c92ec86
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/editorIconsFindReplaceDisabled.png differ
diff --git a/dojox/editor/plugins/resources/icons/editorIconsFindReplaceEnabled.png b/dojox/editor/plugins/resources/icons/editorIconsFindReplaceEnabled.png
new file mode 100644
index 0000000..e28c71b
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/editorIconsFindReplaceEnabled.png differ
diff --git a/dojox/editor/plugins/resources/icons/findIcon.gif b/dojox/editor/plugins/resources/icons/findIcon.gif
deleted file mode 100644
index 93354f4..0000000
Binary files a/dojox/editor/plugins/resources/icons/findIcon.gif and /dev/null differ
diff --git a/dojox/editor/plugins/resources/icons/findIconDisabled.gif b/dojox/editor/plugins/resources/icons/findIconDisabled.gif
deleted file mode 100644
index e7a897b..0000000
Binary files a/dojox/editor/plugins/resources/icons/findIconDisabled.gif and /dev/null differ
diff --git a/dojox/editor/plugins/resources/icons/findReplace.gif b/dojox/editor/plugins/resources/icons/findReplace.gif
deleted file mode 100644
index d540a01..0000000
Binary files a/dojox/editor/plugins/resources/icons/findReplace.gif and /dev/null differ
diff --git a/dojox/editor/plugins/resources/icons/findReplaceDisabled.gif b/dojox/editor/plugins/resources/icons/findReplaceDisabled.gif
deleted file mode 100644
index 9f2f010..0000000
Binary files a/dojox/editor/plugins/resources/icons/findReplaceDisabled.gif and /dev/null differ
diff --git a/dojox/editor/plugins/resources/icons/insertEntity.gif b/dojox/editor/plugins/resources/icons/insertEntity.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/icons/insertEntityDisabled.gif b/dojox/editor/plugins/resources/icons/insertEntityDisabled.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/icons/nihilo/close.gif b/dojox/editor/plugins/resources/icons/nihilo/close.gif
new file mode 100755
index 0000000..285952a
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/nihilo/close.gif differ
diff --git a/dojox/editor/plugins/resources/icons/pageBreak.gif b/dojox/editor/plugins/resources/icons/pageBreak.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/icons/pageBreakDisabled.gif b/dojox/editor/plugins/resources/icons/pageBreakDisabled.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/icons/pasteFromWord.gif b/dojox/editor/plugins/resources/icons/pasteFromWord.gif
new file mode 100755
index 0000000..f9df2a5
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/pasteFromWord.gif differ
diff --git a/dojox/editor/plugins/resources/icons/pasteFromWordDisabled.gif b/dojox/editor/plugins/resources/icons/pasteFromWordDisabled.gif
new file mode 100755
index 0000000..bbe7de6
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/pasteFromWordDisabled.gif differ
diff --git a/dojox/editor/plugins/resources/icons/preview.gif b/dojox/editor/plugins/resources/icons/preview.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/icons/previewDisabled.gif b/dojox/editor/plugins/resources/icons/previewDisabled.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/icons/replaceIcon.gif b/dojox/editor/plugins/resources/icons/replaceIcon.gif
deleted file mode 100644
index 0d1f1e3..0000000
Binary files a/dojox/editor/plugins/resources/icons/replaceIcon.gif and /dev/null differ
diff --git a/dojox/editor/plugins/resources/icons/replaceIconDisabled.gif b/dojox/editor/plugins/resources/icons/replaceIconDisabled.gif
deleted file mode 100644
index 261f5b0..0000000
Binary files a/dojox/editor/plugins/resources/icons/replaceIconDisabled.gif and /dev/null differ
diff --git a/dojox/editor/plugins/resources/icons/save.gif b/dojox/editor/plugins/resources/icons/save.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/icons/saveDisabled.gif b/dojox/editor/plugins/resources/icons/saveDisabled.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/icons/showBlockNodes.gif b/dojox/editor/plugins/resources/icons/showBlockNodes.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/icons/showBlockNodesDisabled.gif b/dojox/editor/plugins/resources/icons/showBlockNodesDisabled.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/icons/smileyDisabled.gif b/dojox/editor/plugins/resources/icons/smileyDisabled.gif
new file mode 100644
index 0000000..e56ff0f
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/smileyDisabled.gif differ
diff --git a/dojox/editor/plugins/resources/icons/soria/close.gif b/dojox/editor/plugins/resources/icons/soria/close.gif
new file mode 100755
index 0000000..f019ae0
Binary files /dev/null and b/dojox/editor/plugins/resources/icons/soria/close.gif differ
diff --git a/dijit/themes/tundra/images/tabClose.gif b/dojox/editor/plugins/resources/icons/tundra/close.gif
old mode 100644
new mode 100755
similarity index 100%
copy from dijit/themes/tundra/images/tabClose.gif
copy to dojox/editor/plugins/resources/icons/tundra/close.gif
diff --git a/dojox/editor/plugins/resources/images/anchor.gif b/dojox/editor/plugins/resources/images/anchor.gif
new file mode 100755
index 0000000..f58992d
Binary files /dev/null and b/dojox/editor/plugins/resources/images/anchor.gif differ
diff --git a/dojox/editor/plugins/resources/images/blockelems/address.gif b/dojox/editor/plugins/resources/images/blockelems/address.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/blockquote.gif b/dojox/editor/plugins/resources/images/blockelems/blockquote.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/button.gif b/dojox/editor/plugins/resources/images/blockelems/button.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/center.gif b/dojox/editor/plugins/resources/images/blockelems/center.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/dd.gif b/dojox/editor/plugins/resources/images/blockelems/dd.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/del.gif b/dojox/editor/plugins/resources/images/blockelems/del.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/div.gif b/dojox/editor/plugins/resources/images/blockelems/div.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/dt.gif b/dojox/editor/plugins/resources/images/blockelems/dt.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/fieldset.gif b/dojox/editor/plugins/resources/images/blockelems/fieldset.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/form.gif b/dojox/editor/plugins/resources/images/blockelems/form.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/h1.gif b/dojox/editor/plugins/resources/images/blockelems/h1.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/h2.gif b/dojox/editor/plugins/resources/images/blockelems/h2.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/h3.gif b/dojox/editor/plugins/resources/images/blockelems/h3.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/h4.gif b/dojox/editor/plugins/resources/images/blockelems/h4.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/h5.gif b/dojox/editor/plugins/resources/images/blockelems/h5.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/h6.gif b/dojox/editor/plugins/resources/images/blockelems/h6.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/hr.gif b/dojox/editor/plugins/resources/images/blockelems/hr.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/iframe.gif b/dojox/editor/plugins/resources/images/blockelems/iframe.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/ins.gif b/dojox/editor/plugins/resources/images/blockelems/ins.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/li.gif b/dojox/editor/plugins/resources/images/blockelems/li.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/map.gif b/dojox/editor/plugins/resources/images/blockelems/map.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/noscript.gif b/dojox/editor/plugins/resources/images/blockelems/noscript.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/object.gif b/dojox/editor/plugins/resources/images/blockelems/object.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/ol.gif b/dojox/editor/plugins/resources/images/blockelems/ol.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/p.gif b/dojox/editor/plugins/resources/images/blockelems/p.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/pre.gif b/dojox/editor/plugins/resources/images/blockelems/pre.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/script.gif b/dojox/editor/plugins/resources/images/blockelems/script.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/table.gif b/dojox/editor/plugins/resources/images/blockelems/table.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/blockelems/ul.gif b/dojox/editor/plugins/resources/images/blockelems/ul.gif
old mode 100644
new mode 100755
diff --git a/dojox/editor/plugins/resources/images/claro/collapse.gif b/dojox/editor/plugins/resources/images/claro/collapse.gif
new file mode 100755
index 0000000..c18c53b
Binary files /dev/null and b/dojox/editor/plugins/resources/images/claro/collapse.gif differ
diff --git a/dojox/editor/plugins/resources/images/claro/expand.gif b/dojox/editor/plugins/resources/images/claro/expand.gif
new file mode 100755
index 0000000..56c5698
Binary files /dev/null and b/dojox/editor/plugins/resources/images/claro/expand.gif differ
diff --git a/dojox/editor/plugins/resources/images/nihilo/collapse.gif b/dojox/editor/plugins/resources/images/nihilo/collapse.gif
new file mode 100755
index 0000000..c18c53b
Binary files /dev/null and b/dojox/editor/plugins/resources/images/nihilo/collapse.gif differ
diff --git a/dojox/editor/plugins/resources/images/nihilo/expand.gif b/dojox/editor/plugins/resources/images/nihilo/expand.gif
new file mode 100755
index 0000000..56c5698
Binary files /dev/null and b/dojox/editor/plugins/resources/images/nihilo/expand.gif differ
diff --git a/dojox/editor/plugins/resources/images/nihilo/sidebar.gif b/dojox/editor/plugins/resources/images/nihilo/sidebar.gif
new file mode 100755
index 0000000..68a5986
Binary files /dev/null and b/dojox/editor/plugins/resources/images/nihilo/sidebar.gif differ
diff --git a/dojox/editor/plugins/resources/images/soria/collapse.gif b/dojox/editor/plugins/resources/images/soria/collapse.gif
new file mode 100755
index 0000000..c18c53b
Binary files /dev/null and b/dojox/editor/plugins/resources/images/soria/collapse.gif differ
diff --git a/dojox/editor/plugins/resources/images/soria/expand.gif b/dojox/editor/plugins/resources/images/soria/expand.gif
new file mode 100755
index 0000000..56c5698
Binary files /dev/null and b/dojox/editor/plugins/resources/images/soria/expand.gif differ
diff --git a/dojox/editor/plugins/resources/images/soria/sidebar.gif b/dojox/editor/plugins/resources/images/soria/sidebar.gif
new file mode 100755
index 0000000..f4dd076
Binary files /dev/null and b/dojox/editor/plugins/resources/images/soria/sidebar.gif differ
diff --git a/dojox/editor/plugins/resources/images/tundra/collapse.gif b/dojox/editor/plugins/resources/images/tundra/collapse.gif
new file mode 100755
index 0000000..c18c53b
Binary files /dev/null and b/dojox/editor/plugins/resources/images/tundra/collapse.gif differ
diff --git a/dojox/editor/plugins/resources/images/tundra/expand.gif b/dojox/editor/plugins/resources/images/tundra/expand.gif
new file mode 100755
index 0000000..56c5698
Binary files /dev/null and b/dojox/editor/plugins/resources/images/tundra/expand.gif differ
diff --git a/dojox/editor/plugins/resources/images/tundra/sidebar.gif b/dojox/editor/plugins/resources/images/tundra/sidebar.gif
new file mode 100755
index 0000000..11fb540
Binary files /dev/null and b/dojox/editor/plugins/resources/images/tundra/sidebar.gif differ
diff --git a/dojox/editor/tests/dummySave.php b/dojox/editor/tests/dummySave.php
new file mode 100644
index 0000000..2fd23ed
--- /dev/null
+++ b/dojox/editor/tests/dummySave.php
@@ -0,0 +1,5 @@
+<?php
+	header("Content-Type", "text/plain");
+	print("Obtained RAW POST data: \n");
+	print(htmlentities($HTTP_RAW_POST_DATA));
+?>
diff --git a/dojox/editor/tests/editorBlockquote.html b/dojox/editor/tests/editorBlockquote.html
new file mode 100755
index 0000000..00f4155
--- /dev/null
+++ b/dojox/editor/tests/editorBlockquote.html
@@ -0,0 +1,118 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Blockquote Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/Blockquote.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.Blockquote");
+		dojo.require("dojox.editor.plugins.PrettyPrint");
+		dojo.require("dijit._editor.plugins.ViewSource");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + Blockquote Plugin</h1>
+
+	<h2>This is an example editor with Blockquote enabled.</h2>  
+	The Blockquote plugin allows you to select a chunk of text and 'blockquote' it.
+	<br>
+
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['blockquote', 'viewsource', 'prettyprint']">
+		This instance is created from a div with an <b>extra</b> plugin, 'Blockquote' loaded.
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<li>List Item Three</li>
+			<li>List Item Four</li>
+		</ul>
+		<br>
+		<blockquote><a href="http://www.dojotoolkit.org">The Dojo Toolkit</a></blockquote>
+		<br>
+		<br>
+		<ol>
+			<li>One</li>
+			<li>Two
+			<ol>
+				<li>
+					Three
+				</li>
+			</ol>
+		</ol>
+		<br>
+		<h3>Malformed list #1</h3>
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<ul>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+				<li>List Item Five</li>
+			</ul>
+		</ul>
+		<h3>Malformed list #2</h3>
+		<ul>
+			<ul>
+				<li>List Item one</li>
+				<li>List Item two</li>
+				<li>List Item three</li>
+			</ul>
+			<li>List Item four</li>
+			<li>List Item five</li>
+		</ul>
+		<br>
+		<h3>A bunch of Lorum Ipsum Text:</h3>
+		<p style="color: #646060;">
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+			Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+			ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+			dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+			Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+			ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+			Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+			torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+			a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+			id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+			ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+			in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+			justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+		</p>
+		<p>
+			Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+			Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+			eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+			aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+			aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+			mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+			semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+		</p>
+		<p>
+			Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+			nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+			ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+			laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+			est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+			at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+			aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+			pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+			iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+			vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+			Proin at lorem turpis.
+		</p>
+		<center>Centered Text</center>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorBreadcrumb.html b/dojox/editor/tests/editorBreadcrumb.html
new file mode 100644
index 0000000..e1c7c65
--- /dev/null
+++ b/dojox/editor/tests/editorBreadcrumb.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Breadcrumb Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/Breadcrumb.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.Breadcrumb");
+		dojo.require("dijit._editor.plugins.LinkDialog");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + Breadcrumb Plugin</h1>
+
+	<h2>This is an example editor with Breadcrumb enabled.</h2>  
+	The Breadcrumb plugin adds a footer toolbar to the editor that shows the current node point you're at
+	in the editor.  You can also use it to select the contents, the entire element, and do operations like
+	delete contents or element, and position cursor in element.
+	<br>
+
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['insertImage', 'breadcrumb']">
+		This instance is created from a div with an <b>extra</b> plugin, 'Breadcrumb' loaded.
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<li>List Item Three</li>
+			<li>List Item Four</li>
+		</ul>
+		<br>
+		<div style="background-color: black"><img src="http://www.dojotoolkit.org/sites/all/themes/dtk/img/banner-logo-text.gif"></div>
+		<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+		<br>
+		<br>
+		<ol>
+			<li>One</li>
+			<li>Two
+			<ol>
+				<li>
+					Three
+				</li>
+			</ol>
+		</ol>
+		<br>
+		<h3>Malformed list #1</h3>
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<ul>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+				<li>List Item Five</li>
+			</ul>
+		</ul>
+		<h3>Malformed list #2</h3>
+		<ul>
+			<ul>
+				<li>List Item one</li>
+				<li>List Item two</li>
+				<li>List Item three</li>
+			</ul>
+			<li>List Item four</li>
+			<li>List Item five</li>
+		</ul>
+		<br>
+		<h3>A bunch of Lorum Ipsum Text:</h3>
+		<p style="color: #646060;">
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+			Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+			ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+			dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+			Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+			ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+			Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+			torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+			a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+			id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+			ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+			in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+			justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+		</p>
+		<p>
+			Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+			Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+			eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+			aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+			aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+			mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+			semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+		</p>
+		<p>
+			Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+			nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+			ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+			laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+			est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+			at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+			aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+			pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+			iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+			vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+			Proin at lorem turpis.
+		</p>
+		<center>Centered Text</center>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorCollapsibleToolbar.html b/dojox/editor/tests/editorCollapsibleToolbar.html
new file mode 100755
index 0000000..943cad2
--- /dev/null
+++ b/dojox/editor/tests/editorCollapsibleToolbar.html
@@ -0,0 +1,131 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor CollapsibleToolbar Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/editorPlugins.css";
+		@import "../plugins/resources/css/PageBreak.css";
+		@import "../plugins/resources/css/ShowBlockNodes.css";
+		@import "../plugins/resources/css/Preview.css";
+		@import "../plugins/resources/css/Save.css";
+		@import "../plugins/resources/css/InsertEntity.css";
+		@import "../plugins/resources/css/FindReplace.css";
+		@import "../plugins/resources/css/Breadcrumb.css";
+		@import "../plugins/resources/css/CollapsibleToolbar.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dojo.parser");
+		dojo.require("dijit._editor.plugins.FullScreen");
+		dojo.require("dijit._editor.plugins.NewPage");
+		dojo.require("dijit._editor.plugins.Print");
+		dojo.require("dijit._editor.plugins.ViewSource");
+		dojo.require("dijit._editor.plugins.FontChoice");
+		dojo.require("dijit._editor.plugins.TextColor");
+		dojo.require("dijit._editor.plugins.EnterKeyHandling");
+		dojo.require("dijit._editor.plugins.ToggleDir");
+		dojo.require("dojox.editor.plugins.ToolbarLineBreak");
+		dojo.require("dojox.editor.plugins.TablePlugins");
+		dojo.require("dojox.editor.plugins.PageBreak");
+		dojo.require("dojox.editor.plugins.PrettyPrint");
+		dojo.require("dojox.editor.plugins.ShowBlockNodes");
+		dojo.require("dojox.editor.plugins.Preview");
+		dojo.require("dojox.editor.plugins.Save");
+		dojo.require("dojox.editor.plugins.InsertEntity");
+		dojo.require("dijit._editor.plugins.LinkDialog");
+		dojo.require("dojox.editor.plugins.NormalizeIndentOutdent");
+		dojo.require("dojox.html.entities");
+		dojo.require("dojox.editor.plugins.FindReplace");
+		dojo.require("dojox.editor.plugins.Breadcrumb");
+		dojo.require("dojox.editor.plugins.CollapsibleToolbar");
+
+		var plugins = ['collapsibletoolbar', {name:'viewSource', stripComments: false}, 
+			{name: 'dijit._editor.plugins.EnterKeyHandling', blockNodeForEnter: "P"},
+			{name: 'prettyprint', indentBy: 3},'breadcrumb',
+			'showBlockNodes', '|', 
+			'fullscreen', 'preview', 'print', 'save', '|', 'findreplace','cut', 'copy','paste', 'delete', 'undo', 'redo', '|', 
+			'bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript', '|', 
+			'insertHorizontalRule', 'insertOrderedList', 'insertUnorderedList', 'indent', 'outdent', '|', 
+			'justifyLeft', 'justifyRight', 'justifyCenter', 'justifyFull', '|', 
+			'createLink', 'unlink','insertImage','||', 
+			'foreColor', 'hiliteColor','fontName', 'fontSize', 'formatBlock'];
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + CollapsibleToolbar Plugin</h1>
+
+	<h2>This is an example editor with CollapsibleToolbar enabled.</h2>  
+	The CollapsibleToolbar plugin allows the toolbar above to be collapsed out of view and expanded back in.
+	<br>
+
+	<div dojoType="dijit.Editor" id="editor1" plugins="plugins">
+		This instance is created from a div with an <b>extra</b> toolbar plugin, 'CollapsibleToolbar', loaded.
+		The plugin allows the toolbar above to be collapsed out of view and expanded back in.  
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<li>List Item Three</li>
+			<li>List Item Four</li>
+		</ul>
+		<br>
+		<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+		<br>
+		<br>
+		<ol>
+			<li>One</li>
+			<li>Two</li>
+		</ol>
+		<br>
+		<br>
+		<h3>A bunch of Lorum Ipsum Text:</h3>
+		<p>
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+			Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+			ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+			dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+			Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+			ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+			Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+			torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+			a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+			id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+			ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+			in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+			justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+		</p>
+		<p>
+			Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+			Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+			eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+			aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+			aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+			mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+			semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+		</p>
+		<p>
+			Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+			nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+			ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+			laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+			est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+			at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+			aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+			pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+			iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+			vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+			Proin at lorem turpis.
+		</p>
+		<center>Centered Text</center>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorFindReplace.html b/dojox/editor/tests/editorFindReplace.html
new file mode 100755
index 0000000..72682fa
--- /dev/null
+++ b/dojox/editor/tests/editorFindReplace.html
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor FindReplace Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/claro/claro.css";
+		@import "../plugins/resources/css/FindReplace.css";
+		@import "../plugins/resources/css/ShowBlockNodes.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.FindReplace");
+		dojo.require("dijit._editor.plugins.FullScreen");
+		dojo.require("dijit._editor.plugins.ViewSource");
+		dojo.require("dojox.editor.plugins.ShowBlockNodes");
+	</script>
+</head>
+<body class="claro">
+	<br>
+	<h1 class="testTitle">Editor + FindReplace Plugin</h1>
+
+	<h2>This is an example editor with FindReplace enabled.</h2>  
+	The FindReplace plugin adds a togglable toolbar to the editor that allows search/replace of text in the editor.
+	This plugin only supports IE, FF, and WebKit.  Opera will not function.  This is an experimental plugin.
+	<br>
+
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['findreplace', 'fullscreen', 'viewsource', 'tabIndent', 'showblocknodes']">
+		This instance is created from a div with an <b>extra</b> plugin, 'FindReplace' loaded.
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<li>List Item Three</li>
+			<li>List Item Four</li>
+		</ul>
+		<br>
+		<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+		<br>
+		<br>
+		<ol>
+			<li>One</li>
+			<li>Two
+			<ol>
+				<li>
+					Three
+				</li>
+			</ol>
+		</ol>
+		<br>
+		<h3>Malformed list #1</h3>
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<ul>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+				<li>List Item Five</li>
+			</ul>
+		</ul>
+		<h3>Malformed list #2</h3>
+		<ul>
+			<ul>
+				<li>List Item one</li>
+				<li>List Item two</li>
+				<li>List Item three</li>
+			</ul>
+			<li>List Item four</li>
+			<li>List Item five</li>
+		</ul>
+		<br>
+		<h3>A bunch of Lorum Ipsum Text:</h3>
+		<p style="color: #646060;">
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+			Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+			ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+			dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+			Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+			ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+			Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+			torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+			a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+			id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+			ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+			in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+			justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+		</p>
+		<p>
+			Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+			Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+			eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+			aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+			aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+			mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+			semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+		</p>
+		<p>
+			Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+			nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+			ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+			laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+			est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+			at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+			aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+			pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+			iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+			vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+			Proin at lorem turpis.
+		</p>
+		<center>Centered Text</center>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorInsertAnchor.html b/dojox/editor/tests/editorInsertAnchor.html
new file mode 100755
index 0000000..7a93d8c
--- /dev/null
+++ b/dojox/editor/tests/editorInsertAnchor.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor InsertAnchor Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/InsertAnchor.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.InsertAnchor");
+		dojo.require("dojox.editor.plugins.PrettyPrint");
+		dojo.require("dijit._editor.plugins.LinkDialog");
+		dojo.require("dijit._editor.plugins.ViewSource");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + InsertAnchor Plugin</h1>
+
+	<h2>This is an example editor with InsertAnchor enabled.</h2>  
+	The InsertAnchor plugin allows you create in-page 'anchors' for linking.
+	<br>
+
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['viewsource', 'createLink', 'insertanchor', 'prettyprint']">
+		This instance is created from a div with an <b>extra</b> plugin, 'InsertAnchor' loaded.
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<li>List Item Three</li>
+			<li>List Item Four</li>
+		</ul>
+		<br>
+		<blockquote><a href="http://www.dojotoolkit.org">The Dojo Toolkit</a></blockquote>
+		<br>
+		<br>
+		<ol>
+			<li>One</li>
+			<li>Two
+			<ol>
+				<li>
+					Three
+				</li>
+			</ol>
+		</ol>
+		<br>
+		<h3>Malformed list #1</h3>
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<ul>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+				<li>List Item Five</li>
+			</ul>
+		</ul>
+		<h3>Malformed list #2</h3>
+		<ul>
+			<ul>
+				<li>List Item one</li>
+				<li>List Item two</li>
+				<li>List Item three</li>
+			</ul>
+			<li>List Item four</li>
+			<li>List Item five</li>
+		</ul>
+		<br>
+		<h3>A bunch of Lorum Ipsum Text:</h3>
+		<p style="color: #646060;">
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+			Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+			ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+			dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+			Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+			ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+			Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+			torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+			a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+			id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+			ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+			in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+			justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+		</p>
+		<p>
+			Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+			Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+			eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+			aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+			aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+			mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+			semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+		</p>
+		<p>
+			Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+			nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+			ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+			laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+			est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+			at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+			aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+			pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+			iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+			vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+			Proin at lorem turpis.
+		</p>
+		<center>Centered Text</center>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorInsertEntity.html b/dojox/editor/tests/editorInsertEntity.html
new file mode 100755
index 0000000..15b6aaf
--- /dev/null
+++ b/dojox/editor/tests/editorInsertEntity.html
@@ -0,0 +1,170 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor InsertEntity Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/InsertEntity.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dijit._editor.plugins.ViewSource");
+		dojo.require("dojox.editor.plugins.InsertEntity");
+		dojo.require("dojox.editor.plugins.PrettyPrint");
+		dojo.require("dojox.html.entities");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + InsertEntity Plugin</h1>
+
+
+	<h2>This is an example editor with InsertEntity enabled.</h2>  
+	The InsertEntity plugin allows you to insert HTML/XML entity characters into the page
+	<br>
+	<br>
+	<b>Note:</b> The InsertEntity is hotkey enabled to CTRL-SHIFT-S as well as being button driven.  
+
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['insertentity', 'viewsource', {name: 'prettyprint', indentBy: 3, entityMap: dojox.html.entities.html.concat(dojox.html.entities.latin)}]">
+		This instance is created from a div with an extra plugin, 'InsertEntity' loaded.  It also has View Source and PrettyPrint 
+		enabled to make it easier to see the inserted entities.
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p style="color: #646060;">
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+
+	<h2>This is an example editor with InsertEntity enabled and showing the code and entity names</h2>  
+	The InsertEntity plugin allows you to insert HTML/XML entity characters into the page
+	<br>
+	<br>
+	<b>Note:</b> The InsertEntity is hotkey enabled to CTRL-SHIFT-S as well as being button driven.  
+
+	<div dojoType="dijit.Editor" id="editor2" extraPlugins="[{name: 'insertentity', showCode: true, showEntityName: true}, 'viewsource', {name: 'prettyprint', indentBy: 3, entityMap: dojox.html.entities.html.concat(dojox.html.entities.latin)}]">                                                              
+		This instance is created from a div with an extra plugin, 'InsertEntity' loaded.  It also has View Source and PrettyPrint 
+		enabled to make it easier to see the inserted entities.   The show code and show entity names is also enabled, so they
+		should appear in the entity picker.
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p style="color: #646060;">
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorNormalizeIndentOutdent.html b/dojox/editor/tests/editorNormalizeIndentOutdent.html
new file mode 100755
index 0000000..4fa637d
--- /dev/null
+++ b/dojox/editor/tests/editorNormalizeIndentOutdent.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor NormalizeIndentOutdent Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.NormalizeIndentOutdent");
+		dojo.require("dijit._editor.plugins.ViewSource");
+		dojo.require("dojox.editor.plugins.PrettyPrint");
+		dojo.require("dijit._editor.plugins.ToggleDir");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + NormalizeIndentOutdent Plugin</h1>
+
+	<h2>This is an example editor with NormalizeIndentOutdent enabled.</h2>  
+	The NormalizeIndentOutdent plugin tries to improve the behavior of indent and outdent, and make it generate 
+	sane HTML output.  The default browser behaviors usually do not generate valid HTML when indenting and
+	outdenting lists.  This tries to correct for that, as well as improve general handling of text indents.
+	<br>
+
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['normalizeindentoutdent', 'viewsource', {name: 'prettyprint', indentBy: 3, lineLength: 80}, 'toggleDir']">
+		This instance is created from a div with an <b>extra</b> plugin, 'NormalizeIndentOutdent' loaded.
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<li>List Item Three</li>
+			<li>List Item Four</li>
+		</ul>
+		<br>
+		<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+		<br>
+		<br>
+		<ol>
+			<li>One</li>
+			<li>Two
+			<ol>
+				<li>
+					Three
+				</li>
+			</ol>
+		</ol>
+		<br>
+		<h3>Malformed list #1</h3>
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<ul>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+				<li>List Item Five</li>
+			</ul>
+		</ul>
+		<h3>Malformed list #2</h3>
+		<ul>
+			<ul>
+				<li>List Item one</li>
+				<li>List Item two</li>
+				<li>List Item three</li>
+			</ul>
+			<li>List Item four</li>
+			<li>List Item five</li>
+		</ul>
+		<br>
+		<h3>A bunch of Lorum Ipsum Text:</h3>
+		<p style="color: #646060;">
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+			Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+			ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+			dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+			Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+			ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+			Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+			torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+			a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+			id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+			ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+			in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+			justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+		</p>
+		<p>
+			Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+			Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+			eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+			aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+			aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+			mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+			semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+		</p>
+		<p>
+			Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+			nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+			ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+			laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+			est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+			at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+			aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+			pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+			iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+			vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+			Proin at lorem turpis.
+		</p>
+		<center>Centered Text</center>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorNormalizeStyle.html b/dojox/editor/tests/editorNormalizeStyle.html
new file mode 100755
index 0000000..77e84df
--- /dev/null
+++ b/dojox/editor/tests/editorNormalizeStyle.html
@@ -0,0 +1,163 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor dojox NormalizeStyle Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/TextColor.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.NormalizeStyle");
+		dojo.require("dojox.editor.plugins.PrettyPrint");
+		dojo.require("dijit._editor.plugins.ViewSource");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + NormalizeStyle Plugin</h1>
+
+	<h2>This is an example editor with the dojox NormalizeStyle plugin enabled.</h2>  
+	The NormalizeStyle plugin's role is to try and force the editor output to be either CSS
+	style based (style="" spans), or semantic tag based (b, i, u, strike, etc).  This is user configurable.
+	Internally in the editor window, it tries to use the format that works the best for the browser.
+	<br>
+	<br>
+	<br>
+	<h2> NormalizeStyle with semantic mode enabled</h2>
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['normalizestyle', 'prettyprint', 'viewsource']">
+		This instance is created from a div with an extra plugin, 'NormalizeStyle' loaded in semantic mode
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p style="color: #646060;">
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+	<br>
+	<br>
+	<br>
+	<h2> NormalizeStyle with css mode enabled</h2>
+	<div dojoType="dijit.Editor" id="editor2" extraPlugins="[{name: 'normalizestyle', mode: 'css'}, 'prettyprint', 'viewsource']">
+		This instance is created from a div with an extra plugin, 'NormalizeStyle' loaded in CSS mode.
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p style="color: #646060;">
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorPageBreak.html b/dojox/editor/tests/editorPageBreak.html
new file mode 100755
index 0000000..1f553fa
--- /dev/null
+++ b/dojox/editor/tests/editorPageBreak.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor PageBreak Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/PageBreak.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.PageBreak");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + PageBreak Plugin</h1>
+
+	<h2>This is an example editor with PageBreak enabled.</h2>  
+	The PageBreak plugin allows you to insert pagebreak divs into the document that will cause the editor
+	contents to break to a new page while printing.  This can be useful in certain cases, particularly when combined
+	with a Print plugin for editor.
+	<br>
+	<br>
+	<b>Note:</b> The PageBreak is hotkey enabled to CTRL-SHIFT-ENTER as well as being button driven.  
+	Also, be aware that PageBreak is disabled for certain elements, such as UL, OL, and LI elements, as breaking there
+	tends to look odd.
+
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['pagebreak']">
+		This instance is created from a div with an extra plugin, 'PageBreak' loaded.
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p style="color: #646060;">
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorPasteFromWord.html b/dojox/editor/tests/editorPasteFromWord.html
new file mode 100755
index 0000000..08ac086
--- /dev/null
+++ b/dojox/editor/tests/editorPasteFromWord.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor PasteFromWord Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/PasteFromWord.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.PasteFromWord");
+		dojo.require("dojox.editor.plugins.PrettyPrint");
+		dojo.require("dijit._editor.plugins.ViewSource");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + PasteFromWord Plugin</h1>
+
+	<h2>This is an example editor with PasteFromWord enabled.</h2>  
+	The PasteFromWord plugin is a special dialog that allows you to paste in content from WordPad and Microsoft word and it will filter out extraneous tags and other items to make the content closer to standard HTML before inserting it.
+	<br>
+
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['pastefromword', 'viewsource', 'prettyprint']">
+		This instance is created from a div with an <b>extra</b> plugin, 'PasteFromWord' loaded.
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<li>List Item Three</li>
+			<li>List Item Four</li>
+		</ul>
+		<br>
+		<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+		<br>
+		<br>
+		<ol>
+			<li>One</li>
+			<li>Two
+			<ol>
+				<li>
+					Three
+				</li>
+			</ol>
+		</ol>
+		<br>
+		<br>
+		<h3>A bunch of Lorum Ipsum Text:</h3>
+		<p style="color: #646060;">
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+			Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+			ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+			dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+			Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+			ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+			Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+			torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+			a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+			id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+			ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+			in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+			justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+		</p>
+		<p>
+			Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+			Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+			eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+			aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+			aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+			mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+			semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+		</p>
+		<p>
+			Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+			nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+			ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+			laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+			est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+			at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+			aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+			pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+			iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+			vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+			Proin at lorem turpis.
+		</p>
+		<center>Centered Text</center>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorPrettyPrint.html b/dojox/editor/tests/editorPrettyPrint.html
new file mode 100755
index 0000000..e6900f9
--- /dev/null
+++ b/dojox/editor/tests/editorPrettyPrint.html
@@ -0,0 +1,327 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Pretty Print Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.ContentPane");    
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.Dialog");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.PrettyPrint");
+		dojo.require("dijit._editor.plugins.ViewSource");
+
+		var init = function(){
+			var deb = dijit.byId("bEditorDefault");
+			var sib = dijit.byId("bEditorSpaceIndent");
+			var slb = dijit.byId("bEditorSpaceLine");
+			var slx = dijit.byId("bEditorXhtml");
+
+			var editorDefault = dijit.byId("editor1");
+			var editorSpaceIndent = dijit.byId("editor2");
+			var editorSpaceLine = dijit.byId("editor3");
+			var editorXhtml = dijit.byId("editor4");
+			var dialog = dijit.byId("dialog");
+			dojo.connect(deb, "onClick", function(){
+				dialog.setContent("<textarea style=\"width: 800px; height: 600px;\" readOnly=\"true\">" + editorDefault.attr("value") + "</textarea>");
+				dialog.show();
+			});
+			dojo.connect(sib, "onClick", function(){
+				dialog.setContent("<textarea style=\"width: 800px; height: 600px;\" readOnly=\"true\">" + editorSpaceIndent.attr("value") + "</textarea>");
+				dialog.show();
+			});
+			dojo.connect(slb, "onClick", function(){
+				dialog.setContent("<textarea style=\"width: 800px; height: 600px;\" readOnly=\"true\">" + editorSpaceLine.attr("value") + "</textarea>");
+				dialog.show();
+			});
+			dojo.connect(slx, "onClick", function(){
+				dialog.setContent("<textarea style=\"width: 800px; height: 600px;\" readOnly=\"true\">" + editorXhtml.attr("value") + "</textarea>");
+				dialog.show();
+			});
+		}
+		dojo.addOnLoad(init);
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + PrettyPrint Plugin</h1>
+   	<div dojoType="dijit.layout.AccordionContainer" style="width: 100%x; height: 550px; overflow: hidden">
+		<div dojoType="dijit.layout.ContentPane" title="PrettyPrint (with defaults)">
+			<h2>This is an example editor with PrettyPrint enabled and the default settings for indent, entity character mapping, and line length</h2>
+			<div dojoType="dijit.Editor" id="editor1" extraPlugins="['prettyprint', 'viewsource']">
+				This instance is created from a div with an extra plugin, 'PrettyPrint' loaded.
+				<div>
+					<ul>
+						<li>List Item One</li>
+						<li>List Item Two</li>
+						<li>List Item Three</li>
+						<li>List Item Four</li>
+					</ul>
+					<br>
+					<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+					<br>
+					<br>
+					<ol>
+						<li>One</li>
+						<li>Two</li>
+					</ol>
+					<br>
+					<br>
+					<h3>A bunch of Lorum Ipsum Text:</h3>
+					<p style="color: #646060;">
+						Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+						Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+						ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+						dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+						Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+						ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+						Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+						torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+						a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+						id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+						ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+						in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+						justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+					</p>
+					<p>
+						Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+						Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+						eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+						aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+						aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+						Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+						mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+						semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+					</p>
+					<p>
+						Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+						nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+						ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+						laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+						est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+						at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+						aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+						pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+						iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+						vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+						Proin at lorem turpis.
+					</p>
+					<center>Centered Text</center>
+				</div>
+			</div>
+			<button dojoType="dijit.form.Button" id="bEditorDefault">Get Content</button>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="PrettyPrint (with 3 space indent)">
+			<h2>This is an example editor with PrettyPrint enabled and indent set to three spaces</h2>
+			<div dojoType="dijit.Editor" id="editor2" extraPlugins="[{name: 'prettyprint', indentBy: 3}]">
+				This instance is created from a div with an extra plugin, 'PrettyPrint' loaded.
+				It also has indent set to three spaces.
+				<div>
+					<ul>
+						<li>List Item One</li>
+						<li>List Item Two</li>
+						<li>List Item Three</li>
+						<li>List Item Four</li>
+					</ul>
+					<br>
+					<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+					<br>
+					<br>
+					<ol>
+						<li>One</li>
+						<li>Two</li>
+					</ol>
+					<br>
+					<br>
+					<h3>A bunch of Lorum Ipsum Text:</h3>
+					<p style="color: #646060;">
+						Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+						Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+						ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+						dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+						Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+						ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+						Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+						torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+						a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+						id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+						ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+						in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+						justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+					</p>
+					<p>
+						Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+						Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+						eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+						aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+						aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+						Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+						mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+						semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+					</p>
+					<p>
+						Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+						nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+						ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+						laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+						est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+						at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+						aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+						pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+						iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+						vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+						Proin at lorem turpis.
+					</p>
+					<center>Centered Text</center>
+				</div>
+			</div>
+			<button dojoType="dijit.form.Button" id="bEditorSpaceIndent">Get Content</button>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="PrettyPrint (with 3 space indent and 60 character lines)" style="width:100%; height:100%"> 
+			<h2>This is an example editor with PrettyPrint enabled, indent set to three spaces, and max text line length at 60 characters</h2>
+			<div dojoType="dijit.Editor" id="editor3" extraPlugins="[{name: 'prettyprint', indentBy: 3, lineLength: 60}]">
+				This instance is created from a div with an extra plugin, 'PrettyPrint' loaded.
+				It also has indent set to three spaces and text line length fixed at 60 characters (not including the indent).
+				<div>
+					<ul>
+						<li>List Item One</li>
+						<li>List Item Two</li>
+						<li>List Item Three</li>
+						<li>List Item Four</li>
+					</ul>
+					<br>
+					<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+					<br>
+					<br>
+					<ol>
+						<li>One</li>
+						<li>Two</li>
+					</ol>
+					<br>
+					<br>
+					<h3>A bunch of Lorum Ipsum Text:</h3>
+					<p style="color: #646060;">
+						Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+						Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+						ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+						dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+						Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+						ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+						Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+						torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+						a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+						id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+						ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+						in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+						justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+					</p>
+					<p>
+						Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+						Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+						eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+						aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+						aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+						Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+						mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+						semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+					</p>
+					<p>
+						Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+						nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+						ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+						laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+						est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+						at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+						aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+						pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+						iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+						vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+						Proin at lorem turpis.
+					</p>
+					<center>Centered Text</center>
+				</div>
+			</div>
+			<button dojoType="dijit.form.Button" id="bEditorSpaceLine">Get Content</button>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="PrettyPrint (with 3 space indent and 60 character lines), and XHTML output" style="width:100%; height:100%"> 
+			<h2>This is an example editor with PrettyPrint enabled, indent set to three spaces, and max text line length at 60 characters</h2>
+			<div dojoType="dijit.Editor" id="editor4" extraPlugins="[{name: 'prettyprint', indentBy: 3, lineLength: 60, xhtml: true}]">
+				This instance is created from a div with an extra plugin, 'PrettyPrint' loaded.
+				It also has indent set to three spaces and text line length fixed at 60 characters (not including the indent).
+                The output has also been configured to try to be XHTML compliant.
+				<div>
+					<ul>
+						<li>List Item One</li>
+						<li>List Item Two</li>
+						<li>List Item Three</li>
+						<li>List Item Four</li>
+					</ul>
+					<br>
+					<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+					<br>
+					<br>
+					<ol>
+						<li>One</li>
+						<li>Two</li>
+					</ol>
+					<br>
+					<br>
+					<h3>A bunch of Lorum Ipsum Text:</h3>
+					<p style="color: #646060;">
+						Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+						Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+						ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+						dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+						Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+						ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+						Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+						torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+						a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+						id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+						ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+						in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+						justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+					</p>
+					<p>
+						Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+						Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+						eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+						aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+						aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+						Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+						mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+						semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+					</p>
+					<p>
+						Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+						nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+						ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+						laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+						est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+						at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+						aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+						pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+						iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+						vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+						Proin at lorem turpis.
+					</p>
+					<center>Centered Text</center>
+				</div>
+			</div>
+			<button dojoType="dijit.form.Button" id="bEditorXhtml">Get Content</button>
+		</div>
+	</div>
+	<div dojoType="dijit.Dialog" id="dialog"></div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorPreview.html b/dojox/editor/tests/editorPreview.html
new file mode 100755
index 0000000..991d340
--- /dev/null
+++ b/dojox/editor/tests/editorPreview.html
@@ -0,0 +1,249 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Preview Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/Preview.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.Preview");
+
+		// Calculate the location of the test stylesheet to apply to the preview.
+		var _calcBaseUrl = function(fullUrl) {
+			var baseUrl = null;
+			if (fullUrl !== null) {
+				var index = fullUrl.indexOf("?");
+				if (index != -1) {
+					fullUrl = fullUrl.substring(0,index);
+				}
+				index = fullUrl.lastIndexOf("/");
+				if (index > 0 && index < fullUrl.length) {
+					baseUrl = fullUrl.substring(0,index);
+				}else{
+					baseUrl = fullUrl;
+				}
+			}
+			return baseUrl;
+		}
+		var baseUrl = _calcBaseUrl(window.location.href);
+		var sSheets = [ baseUrl + "/testBodySheet.css", baseUrl + "/testContentSheet.css"]
+		var sSheets1 = [ baseUrl + "/testContentSheet.css"]
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + Preview Plugin</h1>
+
+	<h2>These are example editors with Preview enabled</h2>  
+	The Preview plugin is a visual 'helper' plugin.  When clicked, it opens a new window with the contents of the editor 
+	plus any denoted stylesheets and/or styles applied to the page.  This is useful for when you are editing content
+	that will be displayed with styles different from what the editor applies.  When you click preview, a new window will open
+	with the styled content.  The styles chosen are not necessarily pretty, just something to make it very obvious styles are being applied.
+	<br>
+	<br>
+
+	<h3>Preview styled with inline styles</h3>
+	<div dojoType="dijit.Editor" id="editor1" 
+		extraPlugins="[{name: 'preview', styles: 'body {background-color: #657383; color: white;} p {background-color: #606070; border-style: inset; border-width: 1px; border-color: #5F5A59; padding: 5px 5px 5px 5px;} center {background-color: #800517; font-weight: bold; font-style: italic; border-style: outset; border-width: 1px; border-color: #800010;} h3 {border-style: outset; border-width: 1px;}'}]">
+		This instance is created from a div with an extra plugin, 'Preview', loaded.
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p>
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+	<br>
+	<br>
+	<h3>Preview styled with external stylesheet</h3>
+	<div dojoType="dijit.Editor" id="editor3" 
+		extraPlugins="[{name: 'preview', stylesheets: sSheets}]">
+		This instance is created from a div with an extra plugin, 'Preview', loaded and is styled in preview via external stylesheets.
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p>
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+	<br>
+	<br>
+	<h3>Preview styled with external stylesheet and defined styles</h3>
+	<div dojoType="dijit.Editor" id="editor2" 
+		extraPlugins="[{name: 'preview', styles: 'body {background-color: #657383; color: white;}', stylesheets: sSheets1}]">
+		This instance is created from a div with an extra plugin, 'Preview', loaded and is styled in preview via an external stylesheet as well as inline styles.
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p>
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorSave.html b/dojox/editor/tests/editorSave.html
new file mode 100644
index 0000000..6f3aa6c
--- /dev/null
+++ b/dojox/editor/tests/editorSave.html
@@ -0,0 +1,104 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Save Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/Save.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.Save");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + Save Plugin</h1>
+
+	<h2>This is an example editor with Save enabled.</h2>  
+	The Save plugin is a non-visual 'helper' plugin.  When enabled, it allows a quick way to POST back content to a
+	server.  The target URL for the default implementation uses xhrPost, and as such, it must POST back to the same
+	domain that served the page that instantiated the editor.  Users can extend this plugin to alter its save behavior, such
+	as use a different posting mechanism, or provide custom onSuccess and onError handlers.
+	<br>
+	<br>
+	<b>Note:</b> For nicely formatted HTML, consider also including the dojox.editor.plugins.PrettyPrint plugin to 
+	'clean up' the content the editor returns.
+	<br>
+	<br>
+	<b>Note:</b> This test makes use of PHP to simulate a back end service, so run it from a PHP enabled server!
+	Otherwise it may report errors.
+	<br>
+	<br>
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="[{name:'save', url: 'dummySave.php'}]">
+		This instance is created from a div with an extra plugin, 'Save' loaded.
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p style="color: #646060;">
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorShowBlockNodes.html b/dojox/editor/tests/editorShowBlockNodes.html
new file mode 100755
index 0000000..5c441f2
--- /dev/null
+++ b/dojox/editor/tests/editorShowBlockNodes.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor ShowBlockNodes Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/ShowBlockNodes.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.ShowBlockNodes");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + ShowBlockNodes Plugin</h1>
+
+	<h2>This is an example editor with ShowBlockNodes enabled.</h2>  
+	The ShowBlockNodes plugin is a visual 'helper' plugin.  When toggled on, it will show you in the editor window where all
+	the block nodes are ant their contents.  This can be vauluable in checking the layout, as content may be nested under nodes 
+	you didn't expect.
+	<br>
+	<br>
+	<b>Note:</b> The ShowBlockNodes is hotkey enabled to CTRL-SHIFT-F9 as well as being button driven.  
+
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['showblocknodes']">
+		This instance is created from a div with an extra plugin, 'ShowBlockNodes' loaded.
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p style="color: #646060;">
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorSmileyPlugin.html b/dojox/editor/tests/editorSmileyPlugin.html
new file mode 100644
index 0000000..dd106e0
--- /dev/null
+++ b/dojox/editor/tests/editorSmileyPlugin.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor Smiley Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/Smiley.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dojo.parser");
+        dojo.require("dojox.editor.plugins._SmileyPalette");
+        dojo.require("dojox.editor.plugins.Smiley");
+		dojo.require("dijit._editor.plugins.ViewSource");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + Smiley Plugin</h1>
+	<div dojoType="dijit.Editor" id="editor" extraPlugins="['smiley', 'viewsource']">
+		<p>
+			This editor is created with the 'smiley' plugin and 'viewsource' plugin.
+			Viewsource should convert the smiley images into ascii text, and vice-versa (on returning from view source to normal editing mode).
+			Also, the smiley plugin should be disabled while in view source mode.
+		</p>
+		<div>
+			<center>[:-)] Smiley Plugin is Ready !!!  [:-)]</center>
+		</div>
+        <ul>
+        <li>
+		emoticonSmile: "[:-)]",
+        </li>
+        <li>
+		emoticonLaughing: "[lol]",
+        </li>
+        <li>
+		emoticonWink: "[;-)]",
+        </li>
+        <li>
+		emoticonGrin: "[:-D]",
+        </li>
+        <li>
+		emoticonCool: "[8-)]",
+        </li>
+        <li>        
+		emoticonAngry: "[:-@]",
+        </li>
+        <li>
+		emoticonHalf: "[:-/]",
+        </li>
+        <li>
+		emoticonEyebrow: "[/:)]",
+        </li>
+        <li>
+		emoticonFrown: "[:-(]",
+        </li>
+        <li>
+		emoticonShy: "[:-$]",
+        </li>
+        <li>
+		emoticonGoofy: "[:-S]",
+        </li>
+        <li>
+		emoticonOops: "[:-O]",
+        </li>
+        <li>
+		emoticonTongue: "[:-P]",
+        </li>
+        <li>
+		emoticonIdea: "[(i)]",
+        </li>
+        <li>
+		emoticonYes: "[(y)]",
+        </li>
+        <li>
+		emoticonNo: "[(n)]",
+        </li>
+        <li>
+		emoticonAngel: "[0:-)]",
+        </li>
+        <li>
+		emoticonCrying: "[:'(]"
+         </li>
+	</ul>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorStatusBar.html b/dojox/editor/tests/editorStatusBar.html
new file mode 100755
index 0000000..ba1fe8e
--- /dev/null
+++ b/dojox/editor/tests/editorStatusBar.html
@@ -0,0 +1,232 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor StatusBar Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/claro/claro.css";
+		@import "../plugins/resources/css/Breadcrumb.css";
+		@import "../plugins/resources/css/StatusBar.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.Breadcrumb");
+		dojo.require("dojox.editor.plugins.StatusBar");
+
+		dojo.addOnLoad(function(){
+			dojo.connect(dijit.byId("editor1Set"), "onClick", function(){
+				dijit.byId("editor1").statusBar.set("value", "Set via direct access!");
+			});
+
+			dojo.connect(dijit.byId("editor1Pub"), "onClick", function(){
+				dojo.publish(dijit.byId("editor1").id + "_statusBar", ["Set via pubsub topic!"]);
+			});
+
+			dojo.connect(dijit.byId("editor2Set"), "onClick", function(){
+				dijit.byId("editor2").statusBar.set("value", "Set via direct access!");
+			});
+
+			dojo.connect(dijit.byId("editor2Pub"), "onClick", function(){
+				dojo.publish(dijit.byId("editor2").id + "_statusBar", ["Set via pubsub topic!"]);
+			});
+		});
+	</script>
+</head>
+<body class="claro">
+	<br>
+	<h1 class="testTitle">Editor + StatusBar Plugin</h1>
+
+	<h2>This is an example editor with Breadcrumb and StatusBar enabled.</h2>  
+	The status bar shows messages posted to a topic (editor.id + _statusBar), or by directly setting the status bar value. 
+	It also has a resize handle enabled.
+	<br>
+
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['breadcrumb', 'statusbar']">
+		This instance is created from a div with an <b>extra</b> plugin, 'StatusBar' loaded.
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<li>List Item Three</li>
+			<li>List Item Four</li>
+		</ul>
+		<br>
+		<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+		<br>
+		<br>
+		<ol>
+			<li>One</li>
+			<li>Two
+			<ol>
+				<li>
+					Three
+				</li>
+			</ol>
+		</ol>
+		<br>
+		<h3>Malformed list #1</h3>
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<ul>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+				<li>List Item Five</li>
+			</ul>
+		</ul>
+		<h3>Malformed list #2</h3>
+		<ul>
+			<ul>
+				<li>List Item one</li>
+				<li>List Item two</li>
+				<li>List Item three</li>
+			</ul>
+			<li>List Item four</li>
+			<li>List Item five</li>
+		</ul>
+		<br>
+		<h3>A bunch of Lorum Ipsum Text:</h3>
+		<p style="color: #646060;">
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+			Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+			ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+			dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+			Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+			ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+			Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+			torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+			a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+			id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+			ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+			in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+			justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+		</p>
+		<p>
+			Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+			Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+			eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+			aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+			aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+			mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+			semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+		</p>
+		<p>
+			Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+			nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+			ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+			laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+			est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+			at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+			aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+			pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+			iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+			vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+			Proin at lorem turpis.
+		</p>
+		<center>Centered Text</center>
+	</div>
+	<button type="button" dojoType="dijit.form.Button" id="editor1Set">Set message via bar</button>
+	<button type="button" dojoType="dijit.form.Button" id="editor1Pub">Set message via pubsub</button>
+    
+    
+	<h2>This is an example editor with Breadcrumb and StatusBar enabled with resize disabled.</h2>  
+	The status bar shows messages posted to a topic (editor.id + _statusBar), or by directly setting the status bar value. 
+	It also has the resize handle disabled.
+	<br>
+
+	<div dojoType="dijit.Editor" id="editor2" extraPlugins="['breadcrumb', {name: 'statusbar', resizer: false}]">
+		This instance is created from a div with an <b>extra</b> plugin, 'StatusBar' loaded.
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<li>List Item Three</li>
+			<li>List Item Four</li>
+		</ul>
+		<br>
+		<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+		<br>
+		<br>
+		<ol>
+			<li>One</li>
+			<li>Two
+			<ol>
+				<li>
+					Three
+				</li>
+			</ol>
+		</ol>
+		<br>
+		<h3>Malformed list #1</h3>
+		<ul>
+			<li>List Item One</li>
+			<li>List Item Two</li>
+			<ul>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+				<li>List Item Five</li>
+			</ul>
+		</ul>
+		<h3>Malformed list #2</h3>
+		<ul>
+			<ul>
+				<li>List Item one</li>
+				<li>List Item two</li>
+				<li>List Item three</li>
+			</ul>
+			<li>List Item four</li>
+			<li>List Item five</li>
+		</ul>
+		<br>
+		<h3>A bunch of Lorum Ipsum Text:</h3>
+		<p style="color: #646060;">
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+			Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+			ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+			dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+			Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+			ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+			Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+			torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+			a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+			id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+			ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+			in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+			justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+		</p>
+		<p>
+			Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+			Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+			eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+			aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+			aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+			mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+			semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+		</p>
+		<p>
+			Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+			nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+			ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+			laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+			est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+			at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+			aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+			pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+			iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+			vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+			Proin at lorem turpis.
+		</p>
+		<center>Centered Text</center>
+	</div>
+	<button type="button" dojoType="dijit.form.Button" id="editor2Set">Set message via bar</button>
+	<button type="button" dojoType="dijit.form.Button" id="editor2Pub">Set message via pubsub</button>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorTablePlugs.html b/dojox/editor/tests/editorTablePlugs.html
new file mode 100644
index 0000000..c900f6e
--- /dev/null
+++ b/dojox/editor/tests/editorTablePlugs.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+	<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+		<title>Editor Table Plugins</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			@import "../../../dijit/themes/dijit.css";
+		</style>
+
+		<link href="../plugins/resources/editorPlugins.css" type="text/css" rel="stylesheet" />
+
+		<script type="text/javascript">
+			var djConfig = {
+				isDebug: true,
+				parseOnLoad: true,
+				popup:true
+				//forceFirebugLite:true
+			};
+		</script>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+		<script>
+			dojo.require("dojo.parser");
+			dojo.require("dijit.Editor");
+			dojo.require("dijit.form.Button");
+			dojo.require("dojox.editor.plugins.TablePlugins");
+			dojo.addOnLoad(function(){
+				console.log(dojo.version.toString());
+			});
+
+			dojo.addOnLoad(function(){
+				var editor = dijit.byId("editor");
+				var button = dijit.byId("removeButton");
+				var c = dojo.connect(button, "onClick", function(){
+					dojo.disconnect(c);
+					editor.close();
+					editor.destroy();
+				});
+			});
+		</script>
+		<style>
+			#main{
+				width:auto;
+				margin:20px 100px;
+			}
+		</style>
+	</head>
+	<body class="tundra">
+		<div id="main">
+			<div id="editor" dojoType="dijit.Editor" height="200px" plugins="[
+				'undo', 'redo', 'bold','italic','|',
+				{name: 'dojox.editor.plugins.TablePlugins', command: 'insertTable'},
+				{name: 'dojox.editor.plugins.TablePlugins', command: 'modifyTable'},
+				{name: 'dojox.editor.plugins.TablePlugins', command: 'InsertTableRowBefore'},
+				{name: 'dojox.editor.plugins.TablePlugins', command: 'InsertTableRowAfter'},
+				{name: 'dojox.editor.plugins.TablePlugins', command: 'insertTableColumnBefore'},
+				{name: 'dojox.editor.plugins.TablePlugins', command: 'insertTableColumnAfter'},
+				{name: 'dojox.editor.plugins.TablePlugins', command: 'deleteTableRow'},
+				{name: 'dojox.editor.plugins.TablePlugins', command: 'deleteTableColumn'},
+				{name: 'dojox.editor.plugins.TablePlugins', command: 'colorTableCell'},
+				{name: 'dojox.editor.plugins.TablePlugins', command: 'tableContextMenu'}
+			]">
+				Dojo Rocks with a fox in socks. Red socks. In a box.
+			        <table width="200" border="2" align="center" cellpadding="2" cellspacing="2" bordercolor="#00FFFF" bgcolor="#FF0000" id="myTable">
+					<tr>
+						<td> </td>
+						<td> </td>
+						<td> </td>
+					</tr>
+					<tr>
+						<td> </td>
+						<td id="myCell"> </td>
+						<td> </td>
+					</tr>
+					<tr>
+						<td> </td>
+						<td> </td>
+						<td bgcolor="#00FFFF">Text</td>
+					</tr>
+				</table> 
+			</div>
+		</div>
+		<button id="removeButton" dojoType="dijit.form.Button">Remove Editor</button>
+	</body>
+</html>
diff --git a/dojox/editor/tests/editorTextColor.html b/dojox/editor/tests/editorTextColor.html
new file mode 100755
index 0000000..b7a22d7
--- /dev/null
+++ b/dojox/editor/tests/editorTextColor.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor dojox TextColor Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../plugins/resources/css/TextColor.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.editor.plugins.TextColor");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + TextColor Plugin</h1>
+
+	<h2>This is an example editor with the dojox TextColor plugin enabled.</h2>  
+	The TextColor plugin is similar to dijit._editor.plugins.TextColor in that it provides menus for selecting the color of
+	text as well as the background color of text.  It also will show you the current colors when you are inside a word/selection
+	based on what the browser claims they are.   This version uses the dojox.widget.ColorPicker in lieu of the dijit.ColorPalette.
+	<br>
+	<br>
+	<b>Note:</b> The dojox.widget.ColorPicker is <b>not</b> A11Y (accessibility) compliant.
+	<br>
+	<br>
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['foreColor', 'hiliteColor']">
+		This instance is created from a div with an extra plugin, 'Save' loaded.
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p style="color: #646060;">
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorToolbarLineBreak.html b/dojox/editor/tests/editorToolbarLineBreak.html
new file mode 100755
index 0000000..df99482
--- /dev/null
+++ b/dojox/editor/tests/editorToolbarLineBreak.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor ToolbarLineBreak Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+		dojo.require("dijit._editor.plugins.FontChoice");
+		dojo.require("dijit._editor.plugins.TextColor");
+		dojo.require("dojox.editor.plugins.ToolbarLineBreak");
+	</script>
+</head>
+<body class="tundra">
+	<br>
+	<h1 class="testTitle">Editor + ToolbarLineBreak Plugin</h1>
+
+	<h2>This is an example editor with ToolbarLineBreak enabled.</h2>  
+	The ToolbarLineBreak plugin is a plugin that lets you split the editor toolbar into multiple 'lines' so that long toolbars
+	can be grouped via reasonable breaks in the buttons	<br>
+	<br>
+
+	<div dojoType="dijit.Editor" id="editor1" extraPlugins="['||', 'fontName', 'fontSize', 'formatBlock', 'foreColor', 'hiliteColor']">
+		This instance is created from a div with an extra plugin, 'ToolbarLineBreak' loaded, along with several optional plugins for font options.
+		<div>
+			<ul>
+				<li>List Item One</li>
+				<li>List Item Two</li>
+				<li>List Item Three</li>
+				<li>List Item Four</li>
+			</ul>
+			<br>
+			<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+			<br>
+			<br>
+			<ol>
+				<li>One</li>
+				<li>Two</li>
+			</ol>
+			<br>
+			<br>
+			<h3>A bunch of Lorum Ipsum Text:</h3>
+			<p style="color: #646060;">
+				Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+				Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+				ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+				dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+				Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+				ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+				Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+				torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+				a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+				id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+				ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+				in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+				justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+			</p>
+			<p>
+				Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+				Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+				eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+				aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+				aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+				Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+				mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+				semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+			</p>
+			<p>
+				Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+				nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+				ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+				laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+				est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+				at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+				aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+				pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+				iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+				vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+				Proin at lorem turpis.
+			</p>
+			<center>Centered Text</center>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/editorUploadPlug.html b/dojox/editor/tests/editorUploadPlug.html
new file mode 100644
index 0000000..c89b8a9
--- /dev/null
+++ b/dojox/editor/tests/editorUploadPlug.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Editor File Upload Plugin</title>
+<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/dijit.css";
+	</style>
+    
+    <link href="../../form/resources/FileInput.css" type="text/css" rel="stylesheet" />
+    <link href="../plugins/resources/editorPlugins.css" type="text/css" rel="stylesheet" />
+
+<script type="text/javascript">
+passthrough = function(msg){
+	//for catching messages from Flash
+	if(window.console){
+		console.log(msg);	
+	}
+}
+var djConfig = {
+	isDebug: false,
+	parseOnLoad: true,
+	debugAtAllCosts:false
+	//popup:true,
+	//forceFirebugLite:true
+};
+</script>
+<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+<script>
+	dojo.require("dojo.parser");
+	dojo.require("dijit.Editor");
+	dojo.require("dojox.editor.plugins.UploadImage");
+	
+	dojo.addOnLoad(function(){
+		//
+	});
+		
+
+		
+</script>
+<style>
+#main{
+width:auto;
+margin:20px 100px;
+}
+</style>
+</head>
+<body class="tundra">
+<div id="main">
+	<div dojoType="dijit.Editor" plugins="[
+                       'undo', 'redo', 'bold','italic','underline','|', 'copy', 'cut', 				
+                       'paste','|',
+                        {name: 'dojox.editor.plugins.UploadImage', command: 'uploadImage',
+                        uploadUrl:'../../form/resources/UploadFile.php', 
+						downloadPath:'../../form/resources/uploads/', tempImageUrl:'../plugins/resources/images/busy.gif'} 
+                    ]">
+         <p>Click the upload icon to open a system dialog. Note that this will need to call a server script for the upload to work.</p>
+         <p> 
+         <font style="font-size:10px; color:#999;"><strong>Test Disclaimers:</strong><br />
+         A PHP test file is being used for server code.<br />
+         Folder permissions will need to be set to system level for uploads to work on your local system.<br />
+         The code uses the GD library (to get image sizes), that sometimes is not pre-installed in a standard PHP build.</font> 
+       </p>
+    </div>
+</div>
+</body>
+</html>
diff --git a/dojox/editor/tests/module.js b/dojox/editor/tests/module.js
new file mode 100644
index 0000000..d02818e
--- /dev/null
+++ b/dojox/editor/tests/module.js
@@ -0,0 +1,15 @@
+dojo.provide("dojox.editor.tests.module");
+
+try{
+	var userArgs = window.location.search.replace(/[\?&](dojoUrl|testUrl|testModule)=[^&]*/g,"").replace(/^&/,"?");
+
+	// Base editor functionality
+	doh.registerUrl("dojox.editor.tests.robot.Editor_Smiley", dojo.moduleUrl("dojox","editor/tests/robot/Editor_Smiley.html"+userArgs), 99999999);
+
+    
+}catch(e){
+	doh.debug(e);
+}
+
+
+
diff --git a/dojox/editor/tests/robot/Editor_Smiley.html b/dojox/editor/tests/robot/Editor_Smiley.html
new file mode 100644
index 0000000..93276be
--- /dev/null
+++ b/dojox/editor/tests/robot/Editor_Smiley.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>doh.robot Editor Smiley Plugin Test</title>
+
+		<style>
+			@import "../../../../util/doh/robot/robot.css";
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<!-- functions to help test -->
+		<script type="text/javascript" src="../../../../dijit/tests/helpers.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");
+
+			dojo.addOnLoad(function(){
+				doh.robot.initRobot('../editorSmileyPlugin.html');
+
+				var editor;
+				var value;
+
+				doh.register("SmileyPlugin_tests", [
+					{
+                        //
+						name: "Smiley preFilter test",
+						timeout: 20000,
+						setUp: function(){
+                            editor = dijit.byId("editor");
+                            value = editor.attr("value");
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+
+							try{
+								doh.robot.sequence(d.getTestCallback(function(){
+									//
+                                    // check smiley icon count
+                                    var nodes = dojo.query("img ", editor.editNode);
+                                    doh.assertEqual(20, nodes.length, editor.editNode.innerHTML);
+								}), 1000);                                
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						},
+						tearDown: function(){
+							if(editor){editor.attr("value", value);}
+						}
+					}
+				]);
+				doh.run();
+			});
+		</script>
+	</head>
+</html>
diff --git a/dojox/editor/tests/runTests.html b/dojox/editor/tests/runTests.html
new file mode 100644
index 0000000..e85585f
--- /dev/null
+++ b/dojox/editor/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+	<head>
+	<title>Dijit Unit Test Runner</title>
+	<meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.editor.tests.module"></HEAD>
+	<BODY>
+		Redirecting to D.O.H runner.
+	</BODY>
+</HTML>
diff --git a/dojox/editor/tests/testBodySheet.css b/dojox/editor/tests/testBodySheet.css
new file mode 100755
index 0000000..d000767
--- /dev/null
+++ b/dojox/editor/tests/testBodySheet.css
@@ -0,0 +1,4 @@
+body {
+	background-color: #657383; 
+	color: white;
+} 
diff --git a/dojox/editor/tests/testContentSheet.css b/dojox/editor/tests/testContentSheet.css
new file mode 100755
index 0000000..2dd6083
--- /dev/null
+++ b/dojox/editor/tests/testContentSheet.css
@@ -0,0 +1,20 @@
+p {
+	background-color: #606070; 
+	border-style: inset; 
+	border-width: 1px; border-color: #5F5A59; 
+	padding: 5px 5px 5px 5px;
+} 
+
+center {
+	background-color: #800517; 
+	font-weight: bold; 
+	font-style: italic;
+	border-style: outset; 
+	border-width: 1px; 
+	border-color: #800010
+} 
+
+h3 {
+	border-style: outset; 
+	border-width: 1px;
+} 
diff --git a/dojox/editor/tests/testPluginsAll.html b/dojox/editor/tests/testPluginsAll.html
new file mode 100644
index 0000000..9c22f74
--- /dev/null
+++ b/dojox/editor/tests/testPluginsAll.html
@@ -0,0 +1,206 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Editor with all plugins enabled (more or less)</title>
+
+	<style type="text/css">
+		@import "../../../dijit/themes/claro/claro.css";
+		@import "../../../dojox/editor/plugins/resources/css/PageBreak.css";
+		@import "../../../dojox/editor/plugins/resources/css/ShowBlockNodes.css";
+		@import "../../../dojox/editor/plugins/resources/css/Preview.css";
+		@import "../../../dojox/editor/plugins/resources/css/Save.css";
+		@import "../../../dojox/editor/plugins/resources/css/InsertEntity.css";
+		@import "../../../dojox/editor/plugins/resources/css/FindReplace.css";
+		@import "../../../dojox/editor/plugins/resources/css/Breadcrumb.css";
+		@import "../../../dojox/editor/plugins/resources/css/CollapsibleToolbar.css";
+		@import "../../../dojox/editor/plugins/resources/css/Blockquote.css";
+		@import "../../../dojox/editor/plugins/resources/css/PasteFromWord.css";
+		@import "../../../dojox/editor/plugins/resources/css/TextColor.css";
+		@import "../../../dojox/editor/plugins/resources/css/InsertAnchor.css";
+		@import "../../../dojox/editor/plugins/resources/editorPlugins.css";
+		@import "../../../dojox/editor/plugins/resources/css/StatusBar.css"; 
+
+		body, html { width:100%; height:100%; margin:0; padding:0; overflow:hidden;}
+		#borderContainer { width:100%; height:100%; overflow:hidden;}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.Editor");
+		dojo.require("dojo.parser");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit._editor.plugins.FullScreen");
+		dojo.require("dijit._editor.plugins.NewPage");
+		dojo.require("dijit._editor.plugins.Print");
+		dojo.require("dijit._editor.plugins.ViewSource");
+		dojo.require("dijit._editor.plugins.FontChoice");
+		dojo.require("dijit._editor.plugins.EnterKeyHandling");
+		dojo.require("dijit._editor.plugins.ToggleDir");
+		dojo.require("dojox.editor.plugins.ToolbarLineBreak");
+		dojo.require("dojox.editor.plugins.TablePlugins");
+		dojo.require("dojox.editor.plugins.PageBreak");
+		dojo.require("dojox.editor.plugins.PrettyPrint");
+		dojo.require("dojox.editor.plugins.ShowBlockNodes");
+		dojo.require("dojox.editor.plugins.Preview");
+		dojo.require("dojox.editor.plugins.Save");
+		dojo.require("dojox.editor.plugins.InsertEntity");
+		dojo.require("dojox.editor.plugins.Blockquote");
+		dojo.require("dijit._editor.plugins.LinkDialog");
+		dojo.require("dojox.editor.plugins.NormalizeIndentOutdent");
+		dojo.require("dojox.html.entities");
+		dojo.require("dojox.editor.plugins.FindReplace");
+		dojo.require("dojox.editor.plugins.Breadcrumb");
+		dojo.require("dojox.editor.plugins.CollapsibleToolbar");
+		dojo.require("dojox.editor.plugins.PasteFromWord");
+		dojo.require("dojox.editor.plugins.TablePlugins");
+		dojo.require("dojox.editor.plugins.NormalizeStyle");
+		dojo.require("dojox.editor.plugins.TextColor");
+		dojo.require("dojox.editor.plugins.InsertAnchor");
+		dojo.require("dojox.editor.plugins.StatusBar");
+		
+		var plugins = ['collapsibletoolbar', 'newPage', 'save', {name: 'viewSource', stripScripts: true, stripComments: true}, 'showBlockNodes', '|',
+			{name: 'fullscreen', zIndex: 900}, 'preview', 'print', '|',
+			'selectAll', 'cut', 'copy', 'findreplace', 'paste','pastefromword', 'delete', 'undo', 'redo', '|',
+			'pageBreak', 'insertHorizontalRule', 'insertOrderedList', 'insertUnorderedList', 'indent', 'outdent', 'blockquote', '|',
+			'justifyLeft', 'justifyRight', 'justifyCenter', 'justifyFull', 'toggleDir', '|',
+			'bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript',  'foreColor', 'hiliteColor', 'removeFormat', '||',
+			'fontName', 'fontSize', 'formatBlock', '||',
+			'insertEntity', 'createLink', 'unlink', 'insertanchor', 'insertImage',
+			{name: 'dojox.editor.plugins.TablePlugins', command: 'insertTable'},
+			{name: 'dojox.editor.plugins.TablePlugins', command: 'modifyTable'},
+			{name: 'dojox.editor.plugins.TablePlugins', command: 'InsertTableRowBefore'},
+			{name: 'dojox.editor.plugins.TablePlugins', command: 'InsertTableRowAfter'},
+			{name: 'dojox.editor.plugins.TablePlugins', command: 'insertTableColumnBefore'},
+			{name: 'dojox.editor.plugins.TablePlugins', command: 'insertTableColumnAfter'},
+			{name: 'dojox.editor.plugins.TablePlugins', command: 'deleteTableRow'},
+			{name: 'dojox.editor.plugins.TablePlugins', command: 'deleteTableColumn'},
+			{name: 'dojox.editor.plugins.TablePlugins', command: 'colorTableCell'},
+			{name: 'dojox.editor.plugins.TablePlugins', command: 'tableContextMenu'},
+			{name: 'prettyprint', indentBy: "3", entityMap: dojox.html.entities.html.concat(dojox.html.entities.latin)},
+			{name: 'dijit._editor.plugins.EnterKeyHandling', blockNodeForEnter: "P"},
+			'normalizeindentoutdent', 'breadcrumb', {name: 'normalizestyle', mode: "css"}, {name: 'statusbar', resizer: false}
+		];
+	</script>
+</head>
+<body class="claro">
+	<div dojoType="dijit.layout.BorderContainer" gutters="false" id="borderContainer"> 
+		<div dojoType="dijit.layout.ContentPane" region="top" style="height: 1.8em; font-size: 2em; font-weight: bold; background-color: #EEEEEE; vertical-align: middle;"">
+			<div style="vertical-align: middle;">Editor with Claro Theme and Most Plugins Enabled.</div>
+		</div> 
+		<div dojoType="dijit.layout.ContentPane" region="center">
+			<div dojoType="dijit.Editor" id="editor1" plugins="plugins" height="100%">
+				<h1>Lists:</h1>
+				<ul>
+					<li>List Item One</li>
+					<li>List Item Two
+						<ul>
+							<li>Sub Item One</li>
+						</ul>
+					</li>
+					<li>List Item Three</li>
+					<li>List Item Four</li>
+				</ul>
+				<ol>
+					<li>List Item One</li>
+					<li>List Item Two</li>
+					<li>List Item Three</li>
+					<li>List Item Four</li>
+				</ol>
+				<h1>Links:</h1>
+				<a href="http://www.dojotoolkit.org">The Dojo Toolkit</a>
+				<br>
+				Example E-Mail: <a href="mailto:johndoe at example.com">johndoe at example.com</a>
+				<br>
+				Example Anchor: <a name="myAnchor">Anchor</a>
+				<br>
+				<br>
+				<h1>Images:</h1>
+				<div style="background-color: #888888; border-style: solid; border-width: 1px; border-color: #888888l">
+					<img src="http://www.dojotoolkit.org/dojango/dojo-media/release/1.4.0-20100212/dtk/images/logo.png" alt="The Dojo Toolkit">
+				</div>
+				<br>
+				<br>
+				<h1>Tables:</h1>
+				<table align="" bgcolor="" border="2" bordercolor="" cellpadding="1" cellspacing="1">
+					<tbody>
+						<tr>
+							<td>Cell One</td>
+							<td>Cell Two</td>
+						</tr>
+						<tr>
+							<td>Cell Three</td>
+							<td>Cell Four</td>
+						</tr>
+					</tbody>
+				</table>
+				<br>
+				<br>
+				<h1>Text:</h1>
+				<h2>Normal Text</h2>
+				<p>
+					Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+					Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+					ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+					dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+					Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+					ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+					Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+					torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+					a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+					id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+					ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+					in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+					justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+				</p>
+				<h2>Styled Text</h2>
+				<p style="font-weight: bold; font-style: italic;">
+					Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eget turpis nunc.
+					Praesent ut metus ac mi gravida lobortis vel quis nulla. Sed elementum elit eget
+					ante viverra consectetur. Praesent pulvinar faucibus risus in pulvinar. Sed auctor,
+					dui sed suscipit semper, metus sapien feugiat urna, et auctor nisi est quis purus.
+					Aliquam eu tortor eu ante venenatis pellentesque nec sed massa. Nulla feugiat, nunc
+					ac aliquet elementum, lacus odio dictum nisl, vel molestie neque tellus eget nibh.
+					Curabitur et eros quam, non consectetur erat. Class aptent taciti sociosqu ad litora
+					torquent per conubia nostra, per inceptos himenaeos. Quisque luctus imperdiet felis,
+					a mollis sapien scelerisque ut. Quisque dui neque, vulputate eu consectetur et, fermentum
+					id est. Nulla euismod lorem at massa aliquam at cursus mi fermentum. Quisque rhoncus
+					ornare pharetra. Cras vestibulum convallis nisl, eget ultrices sem porta eget. Duis
+					in dolor id nibh volutpat sodales. Nullam eleifend, sapien accumsan convallis tincidunt,
+					justo mi pellentesque dolor, in suscipit dolor quam ac ligula.
+				</p>
+				<h2>Indented Text</h2>
+				<p style="margin-left: 40px;">
+					Ut molestie facilisis nisi sed consequat. Nunc in turpis quam, vel elementum lectus.
+					Suspendisse vel consequat augue. Praesent id orci orci. Praesent est tortor, consequat
+					eu posuere nec, volutpat ac diam. Cras pretium quam non diam dictum tincidunt. Mauris
+					aliquet lacinia odio vitae elementum. Nam rutrum semper metus, in consectetur lectus
+					aliquam a. Maecenas pharetra nibh nec leo consequat vitae rhoncus nibh volutpat.
+					Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
+					mus. Sed at odio turpis, sit amet molestie nisl. Curabitur in ligula id tortor feugiat
+					semper. Vestibulum id nunc magna, eu lacinia nibh. Ut congue adipiscing dictum.
+				</p>
+				<h2>Blockquoted Text</h2>
+				<blockquote>
+					<p>
+						Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia
+						nostra, per inceptos himenaeos. Phasellus in orci purus, sed aliquet quam. Aenean
+						ultrices tincidunt augue, in feugiat massa dignissim in. Nunc a dolor eu mi fringilla
+						laoreet. Praesent lacinia mi eu sapien imperdiet dignissim. Praesent a pellentesque
+						est. Sed augue eros, porttitor nec consequat bibendum, mattis lobortis diam. Sed
+						at massa ante. In volutpat ultrices mattis. Vestibulum tempus pretium risus quis
+						aliquet. Donec non ante vitae orci euismod eleifend. Aliquam at metus quis turpis
+						pharetra porta. Sed dignissim risus in erat aliquam et posuere nulla molestie. Nunc
+						iaculis lectus eget augue sollicitudin gravida ac non nisl. Vivamus bibendum gravida
+						vehicula. Aliquam vitae mi ligula. Nulla at augue velit, vitae ultricies libero.
+						Proin at lorem turpis.
+					</p>
+				</blockquote>
+				<center>Centered Text</center>
+			</div>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/embed/Flash.js b/dojox/embed/Flash.js
index 9b4bede..8912081 100644
--- a/dojox/embed/Flash.js
+++ b/dojox/embed/Flash.js
@@ -1,270 +1,544 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.embed.Flash"]){
-dojo._hasResource["dojox.embed.Flash"]=true;
 dojo.provide("dojox.embed.Flash");
+
 (function(){
-var _1,_2;
-var _3=9;
-var _4="dojox-embed-flash-",_5=0;
-var _6={expressInstall:false,width:320,height:240,swLiveConnect:"true",allowScriptAccess:"sameDomain",allowNetworking:"all",style:null,redirect:null};
-function _7(_8){
-_8=dojo.delegate(_6,_8);
-if(!("path" in _8)){
-console.error("dojox.embed.Flash(ctor):: no path reference to a Flash movie was provided.");
-return null;
-}
-if(!("id" in _8)){
-_8.id=(_4+_5++);
-}
-return _8;
-};
-if(dojo.isIE){
-_1=function(_9){
-_9=_7(_9);
-if(!_9){
-return null;
-}
-var p;
-var _a=_9.path;
-if(_9.vars){
-var a=[];
-for(p in _9.vars){
-a.push(p+"="+_9.vars[p]);
-}
-_9.params.FlashVars=a.join("&");
-delete _9.vars;
-}
-var s="<object id=\""+_9.id+"\" "+"classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" "+"width=\""+_9.width+"\" "+"height=\""+_9.height+"\""+((_9.style)?" style=\""+_9.style+"\"":"")+">"+"<param name=\"movie\" value=\""+_a+"\" />";
-if(_9.params){
-for(p in _9.params){
-s+="<param name=\""+p+"\" value=\""+_9.params[p]+"\" />";
-}
-}
-s+="</object>";
-return {id:_9.id,markup:s};
-};
-_2=(function(){
-var _b=10,_c=null;
-while(!_c&&_b>7){
-try{
-_c=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_b--);
-}
-catch(e){
-}
-}
-if(_c){
-var v=_c.GetVariable("$version").split(" ")[1].split(",");
-return {major:(v[0]!=null)?parseInt(v[0]):0,minor:(v[1]!=null)?parseInt(v[1]):0,rev:(v[2]!=null)?parseInt(v[2]):0};
-}
-return {major:0,minor:0,rev:0};
-})();
-dojo.addOnUnload(function(){
-var _d=function(){
-};
-var _e=dojo.query("object").reverse().style("display","none").forEach(function(i){
-for(var p in i){
-if((p!="FlashVars")&&dojo.isFunction(i[p])){
-try{
-i[p]=_d;
-}
-catch(e){
-}
-}
-}
-});
-});
-}else{
-_1=function(_f){
-_f=_7(_f);
-if(!_f){
-return null;
-}
-var p;
-var _10=_f.path;
-if(_f.vars){
-var a=[];
-for(p in _f.vars){
-a.push(p+"="+_f.vars[p]);
-}
-_f.params.flashVars=a.join("&");
-delete _f.vars;
-}
-var s="<embed type=\"application/x-shockwave-flash\" "+"src=\""+_10+"\" "+"id=\""+_f.id+"\" "+"width=\""+_f.width+"\" "+"height=\""+_f.height+"\""+((_f.style)?" style=\""+_f.style+"\" ":"")+"swLiveConnect=\""+_f.swLiveConnect+"\" "+"allowScriptAccess=\""+_f.allowScriptAccess+"\" "+"allowNetworking=\""+_f.allowNetworking+"\" "+"pluginspage=\""+window.location.protocol+"//www.adobe.com/go/getflashplayer\" ";
-if(_f.params){
-for(p in _f.params){
-s+=" "+p+"=\""+_f.params[p]+"\"";
-}
-}
-s+=" />";
-return {id:_f.id,markup:s};
-};
-_2=(function(){
-var _11=navigator.plugins["Shockwave Flash"];
-if(_11&&_11.description){
-var v=_11.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split(".");
-return {major:(v[0]!=null)?parseInt(v[0]):0,minor:(v[1]!=null)?parseInt(v[1]):0,rev:(v[2]!=null)?parseInt(v[2]):0};
-}
-return {major:0,minor:0,rev:0};
-})();
-}
-dojox.embed.Flash=function(_12,_13){
-if(location.href.toLowerCase().indexOf("file://")>-1){
-throw new Error("dojox.embed.Flash can't be run directly from a file. To instatiate the required SWF correctly it must be run from a server, like localHost.");
-}
-this.available=dojox.embed.Flash.available;
-this.minimumVersion=_12.minimumVersion||_3;
-this.id=null;
-this.movie=null;
-this.domNode=null;
-if(_13){
-_13=dojo.byId(_13);
-}
-setTimeout(dojo.hitch(this,function(){
-if(_12.expressInstall||this.available&&this.available>=this.minimumVersion){
-if(_12&&_13){
-this.init(_12,_13);
-}else{
-this.onError("embed.Flash was not provided with the proper arguments.");
-}
-}else{
-if(!this.available){
-this.onError("Flash is not installed.");
-}else{
-this.onError("Flash version detected: "+this.available+" is out of date. Minimum required: "+this.minimumVersion);
-}
-}
-}),100);
-};
-dojo.extend(dojox.embed.Flash,{onReady:function(_14){
-console.warn("embed.Flash.movie.onReady:",_14);
-},onLoad:function(_15){
-console.warn("embed.Flash.movie.onLoad:",_15);
-},onError:function(msg){
-},_onload:function(){
-clearInterval(this._poller);
-delete this._poller;
-delete this._pollCount;
-delete this._pollMax;
-this.onLoad(this.movie);
-},init:function(_16,_17){
-this.destroy();
-_17=dojo.byId(_17||this.domNode);
-if(!_17){
-throw new Error("dojox.embed.Flash: no domNode reference has been passed.");
-}
-var p=0,_18=false;
-this._poller=null;
-this._pollCount=0;
-this._pollMax=15;
-this.pollTime=100;
-if(dojox.embed.Flash.initialized){
-this.id=dojox.embed.Flash.place(_16,_17);
-this.domNode=_17;
-setTimeout(dojo.hitch(this,function(){
-this.movie=this.byId(this.id,_16.doc);
-this.onReady(this.movie);
-this._poller=setInterval(dojo.hitch(this,function(){
-try{
-p=this.movie.PercentLoaded();
-}
-catch(e){
-console.warn("this.movie.PercentLoaded() failed");
-}
-if(p==100){
-this._onload();
-}else{
-if(p==0&&this._pollCount++>this._pollMax){
-clearInterval(this._poller);
-throw new Error("Building SWF failed.");
-}
-}
-}),this.pollTime);
-}),1);
-}
-},_destroy:function(){
-try{
-this.domNode.removeChild(this.movie);
-}
-catch(e){
-}
-this.id=this.movie=this.domNode=null;
-},destroy:function(){
-if(!this.movie){
-return;
-}
-var _19=dojo.delegate({id:true,movie:true,domNode:true,onReady:true,onLoad:true});
-for(var p in this){
-if(!_19[p]){
-delete this[p];
-}
-}
-if(this._poller){
-dojo.connect(this,"onLoad",this,"_destroy");
-}else{
-this._destroy();
-}
-},byId:function(_1a,doc){
-doc=doc||document;
-if(doc.embeds[_1a]){
-return doc.embeds[_1a];
-}
-if(doc[_1a]){
-return doc[_1a];
-}
-if(window[_1a]){
-return window[_1a];
-}
-if(document[_1a]){
-return document[_1a];
-}
-return null;
-}});
-dojo.mixin(dojox.embed.Flash,{minSupported:8,available:_2.major,supported:(_2.major>=_2.required),minimumRequired:_2.required,version:_2,initialized:false,onInitialize:function(){
-dojox.embed.Flash.initialized=true;
-},__ie_markup__:function(_1b){
-return _1(_1b);
-},proxy:function(obj,_1c){
-dojo.forEach((dojo.isArray(_1c)?_1c:[_1c]),function(_1d){
-this[_1d]=dojo.hitch(this,function(){
-return (function(){
-return eval(this.movie.CallFunction("<invoke name=\""+_1d+"\" returntype=\"javascript\">"+"<arguments>"+dojo.map(arguments,function(_1e){
-return __flash__toXML(_1e);
-}).join("")+"</arguments>"+"</invoke>"));
-}).apply(this,arguments||[]);
-});
-},obj);
-}});
-if(dojo.isIE){
-if(dojo._initFired){
-var e=document.createElement("script");
-e.type="text/javascript";
-e.src=dojo.moduleUrl("dojox","embed/IE/flash.js");
-document.getElementsByTagName("head")[0].appendChild(e);
-}else{
-document.write("<scr"+"ipt type=\"text/javascript\" src=\""+dojo.moduleUrl("dojox","embed/IE/flash.js")+"\">"+"</scr"+"ipt>");
-}
-}else{
-dojox.embed.Flash.place=function(_1f,_20){
-var o=_1(_1f);
-_20=dojo.byId(_20);
-if(!_20){
-_20=dojo.doc.createElement("div");
-_20.id=o.id+"-container";
-dojo.body().appendChild(_20);
-}
-if(o){
-_20.innerHTML=o.markup;
-return o.id;
-}
-return null;
-};
-dojox.embed.Flash.onInitialize();
-}
+	/*******************************************************
+		dojox.embed.Flash
+
+		Base functionality to insert a flash movie into
+		a document on the fly.
+
+		Usage:
+		var movie=new dojox.embed.Flash({ args }, containerNode);
+	 ******************************************************/
+	var fMarkup, fVersion;
+	var minimumVersion = 9; // anything below this will throw an error (may overwrite)
+	var keyBase = "dojox-embed-flash-", keyCount=0;
+	var _baseKwArgs = {
+		expressInstall: false,
+		width: 320,
+		height: 240,
+		swLiveConnect: "true",
+		allowScriptAccess: "sameDomain",
+		allowNetworking:"all",
+		style: null,
+		redirect: null
+	};
+
+	function prep(kwArgs){
+		// console.warn("KWARGS:", kwArgs)
+		kwArgs = dojo.delegate(_baseKwArgs, kwArgs);
+
+		if(!("path" in kwArgs)){
+			console.error("dojox.embed.Flash(ctor):: no path reference to a Flash movie was provided.");
+			return null;
+		}
+
+		if(!("id" in kwArgs)){
+			kwArgs.id = (keyBase + keyCount++);
+		}
+		return kwArgs;
+	}
+
+	if(dojo.isIE){
+		fMarkup = function(kwArgs){
+			kwArgs = prep(kwArgs);
+			if(!kwArgs){ return null; }
+
+			var p;
+			var path = kwArgs.path;
+			if(kwArgs.vars){
+				var a = [];
+				for(p in kwArgs.vars){
+					a.push(p + '=' + kwArgs.vars[p]);
+				}
+				kwArgs.params.FlashVars = a.join("&");
+				delete kwArgs.vars;
+			}
+			// FIXME: really? +'s?
+			var s = '<object id="' + kwArgs.id + '" '
+				+ 'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" '
+				+ 'width="' + kwArgs.width + '" '
+				+ 'height="' + kwArgs.height + '"'
+				+ ((kwArgs.style)?' style="' + kwArgs.style + '"':'')
+				+ '>'
+				+ '<param name="movie" value="' + path + '" />';
+			if(kwArgs.params){
+				for(p in kwArgs.params){
+					s += '<param name="' + p + '" value="' + kwArgs.params[p] + '" />';
+				}
+			}
+			s += '</object>';
+			return { id: kwArgs.id, markup: s };
+		};
+
+		fVersion = (function(){
+			var testVersion = 10, testObj = null;
+			while(!testObj && testVersion > 7){
+				try {
+					testObj = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + testVersion--);
+				}catch(e){ }
+			}
+			if(testObj){
+				var v = testObj.GetVariable("$version").split(" ")[1].split(",");
+				return {
+					major: (v[0]!=null) ? parseInt(v[0]) : 0,
+					minor: (v[1]!=null) ? parseInt(v[1]) : 0,
+					rev: (v[2]!=null) ? parseInt(v[2]) : 0
+				};
+			}
+			return { major: 0, minor: 0, rev: 0 };
+		})();
+
+		//	attach some cleanup for IE, thanks to deconcept :)
+		dojo.addOnUnload(function(){
+			var dummy = function(){};
+			var objs = dojo.query("object").
+				reverse().
+				style("display", "none").
+				forEach(function(i){
+					for(var p in i){
+						if((p != "FlashVars") && dojo.isFunction(i[p])){
+							try{
+								i[p] = dummy;
+							}catch(e){}
+						}
+					}
+				});
+		});
+
+		//	TODO: ...and double check this fix; is IE really firing onbeforeunload with any kind of href="#" link?
+		/*
+		var beforeUnloadHandle = dojo.connect(dojo.global, "onbeforeunload", function(){
+			try{
+				if(__flash_unloadHandler){ __flash_unloadHandler=function(){ }; }
+				if(__flash_savedUnloadHandler){ __flash_savedUnloadHandler=function(){ }; }
+			} catch(e){ }
+			dojo.disconnect(beforeUnloadHandle);
+		});
+		*/
+	} else {
+		//	*** Sane browsers branch ******************************************************************
+		fMarkup = function(kwArgs){
+			kwArgs = prep(kwArgs);
+			if(!kwArgs){ return null; }
+
+			var p;
+			var path = kwArgs.path;
+			if(kwArgs.vars){
+				var a = [];
+				for(p in kwArgs.vars){
+					a.push(p + '=' + kwArgs.vars[p]);
+				}
+				kwArgs.params.flashVars = a.join("&");
+				delete kwArgs.vars;
+			}
+			var s = '<embed type="application/x-shockwave-flash" '
+				+ 'src="' + path + '" '
+				+ 'id="' + kwArgs.id + '" '
+				+ 'width="' + kwArgs.width + '" '
+				+ 'height="' + kwArgs.height + '"'
+				+ ((kwArgs.style)?' style="' + kwArgs.style + '" ':'')
+				+ 'swLiveConnect="'+kwArgs.swLiveConnect+'" '
+				+ 'allowScriptAccess="' +kwArgs.allowScriptAccess+  '" '
+				+ 'allowNetworking="' +kwArgs.allowNetworking+  '" '
+
+				+ 'pluginspage="' + window.location.protocol + '//www.adobe.com/go/getflashplayer" ';
+			if(kwArgs.params){
+				for(p in kwArgs.params){
+					s += ' ' + p + '="' + kwArgs.params[p] + '"';
+				}
+			}
+			s += ' />';
+			return { id: kwArgs.id, markup: s };
+		};
+
+		fVersion=(function(){
+			var plugin = navigator.plugins["Shockwave Flash"];
+			if(plugin && plugin.description){
+				var v = plugin.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split(".");
+				return {
+					major: (v[0]!=null) ? parseInt(v[0]) : 0,
+					minor: (v[1]!=null) ? parseInt(v[1]) : 0,
+					rev: (v[2]!=null) ? parseInt(v[2]) : 0
+				};
+			}
+			return { major: 0, minor: 0, rev: 0 };
+		})();
+	}
+
+
+/*=====
+dojox.embed.__flashArgs = function(path, id, width, height, style, params, vars, expressInstall, redirect){
+	//	path: String
+	//		The URL of the movie to embed.
+	//	id: String?
+	//		A unique key that will be used as the id of the created markup.  If you don't
+	//		provide this, a unique key will be generated.
+	//	width: Number?
+	//		The width of the embedded movie; the default value is 320px.
+	//	height: Number?
+	//		The height of the embedded movie; the default value is 240px
+	//	minimumVersion: Number ?
+	//		The minimum targeted version of the Flash Player (defaults to 9)
+	//	style: String?
+	//		Any CSS style information (i.e. style="background-color:transparent") you want
+	//		to define on the markup.
+	//	params: Object?
+	//		A set of key/value pairs that you want to define in the resultant markup.
+	//	vars: Object?
+	//		A set of key/value pairs that the Flash movie will interpret as FlashVars.
+	//	expressInstall: Boolean?
+	//		Whether or not to include any kind of expressInstall info. Default is false.
+	//	redirect: String?
+	//		A url to redirect the browser to if the current Flash version is not supported.
+	this.id=id;
+	this.path=path;
+	this.width=width;
+	this.minimumVersion=minimumVersion;
+	this.height=height;
+	this.style=style;
+	this.params=params;
+	this.vars=vars;
+	this.expressInstall=expressInstall;
+	this.redirect=redirect;
+}
+=====*/
+
+	//	the main entry point
+	dojox.embed.Flash = function(/*dojox.embed.__flashArgs*/ kwArgs, /*DOMNode*/ node){
+		//	summary:
+		//		Create a wrapper object around a Flash movie; this is the DojoX equivilent
+		//		to SWFObject.
+		//
+		//	description:
+		//		Creates a wrapper object around a Flash movie.  Wrapper object will
+		//		insert the movie reference in node; when the browser first starts
+		//		grabbing the movie, onReady will be fired; when the movie has finished
+		//		loading, it will fire onLoad.
+		//
+		//		If your movie uses ExternalInterface, you should use the onLoad event
+		//		to do any kind of proxy setup (see dojox.embed.Flash.proxy); this seems
+		//		to be the only consistent time calling EI methods are stable (since the
+		//		Flash movie will shoot several methods into the window object before
+		//		EI callbacks can be used properly).
+		//
+		//		*Important note*:  this code includes a workaround for the Eolas "fix" from
+		//		Microsoft; in order to work around the "click to activate this control" message
+		//		on any embedded Flash movie, this code will load a separate, non-dojo.require
+		//		javascript file in order to write the Flash movie into the document.  As such
+		//		it cannot be used with Dojo's scope map techniques for working with multiple
+		//		versions of Dojo on the same page.
+		//
+		//	kwArgs: dojox.embed.__flashArgs
+		//		The various arguments that will be used to help define the Flash movie.
+		//	node: DomNode
+		//		The node where the embed object will be placed
+		//
+		//	example:
+		//		Embed a flash movie in a document using the new operator, and get a reference to it.
+		//	|	var movie = new dojox.embed.Flash({
+		//	|		path: "path/to/my/movie.swf",
+		//	|		width: 400,
+		//	|		height: 300
+		//	|	}, myWrapperNode, "testLoaded");
+		//
+		//	example:
+		//		Embed a flash movie in a document without using the new operator.
+		//	|	var movie = dojox.embed.Flash({
+		//	|		path: "path/to/my/movie.swf",
+		//	|		width: 400,
+		//	|		height: 300,
+		//	|		style: "position:absolute;top:0;left:0"
+		//	|	}, myWrapperNode, "testLoaded");
+		//
+		// File can only be run from a server, due to SWF dependency.
+		if(location.href.toLowerCase().indexOf("file://")>-1){
+			throw new Error("dojox.embed.Flash can't be run directly from a file. To instatiate the required SWF correctly it must be run from a server, like localHost.");
+		}
+
+		//	available: Number
+		//		If there is a flash player available, and if so what version.
+		this.available = dojox.embed.Flash.available;
+
+		//	minimumVersion: Number
+		//		The minimum version of Flash required to run this movie.
+		this.minimumVersion = kwArgs.minimumVersion || minimumVersion;
+		//console.log("AVAILABLE:", this);
+
+		//	id: String
+		//		The id of the DOMNode to be used for this movie.  Can be used with dojo.byId to get a reference.
+		this.id = null;
+
+		//	movie: FlashObject
+		//		A reference to the movie itself.
+		this.movie = null;
+
+		//	domNode: DOMNode
+		//		A reference to the DOMNode that contains this movie.
+		this.domNode = null;
+		if(node){
+			node = dojo.byId(node);
+		}
+		// setTimeout Fixes #8743 - creating double SWFs
+		// also allows time for code to attach to onError
+		setTimeout(dojo.hitch(this, function(){
+			if(kwArgs.expressInstall || this.available && this.available >= this.minimumVersion){
+				if(kwArgs && node){
+					this.init(kwArgs, node);
+				}else{
+					this.onError("embed.Flash was not provided with the proper arguments.");
+				}
+			}else{
+				if(!this.available){
+					this.onError("Flash is not installed.");
+				}else{
+					this.onError("Flash version detected: "+this.available+" is out of date. Minimum required: "+this.minimumVersion);
+				}
+			}
+		}), 100);
+	};
+
+	dojo.extend(dojox.embed.Flash, {
+		onReady: function(/*HTMLObject*/ movie){
+			console.warn("embed.Flash.movie.onReady:", movie)
+			//	summary:
+			//		Stub function for you to attach to when the movie reference is first
+			//		pushed into the document.
+		},
+		onLoad: function(/*HTMLObject*/ movie){
+			console.warn("embed.Flash.movie.onLoad:", movie)
+			//	summary:
+			//		Stub function for you to attach to when the movie has finished downloading
+			//		and is ready to be manipulated.
+		},
+		onError: function(msg){
+
+		},
+		_onload: function(){
+			// summary:
+			//	Internal. Cleans up before calling onLoad.
+			clearInterval(this._poller);
+			delete this._poller;
+			delete this._pollCount;
+			delete this._pollMax;
+			this.onLoad(this.movie);
+		},
+		init: function(/*dojox.embed.__flashArgs*/ kwArgs, /*DOMNode?*/ node){
+			console.log("embed.Flash.movie.init")
+			//	summary
+			//		Initialize (i.e. place and load) the movie based on kwArgs.
+			this.destroy();		//	ensure we are clean first.
+			node = dojo.byId(node || this.domNode);
+			if(!node){ throw new Error("dojox.embed.Flash: no domNode reference has been passed."); }
+
+			// vars to help determine load status
+			var p = 0, testLoaded=false;
+			this._poller = null; this._pollCount = 0; this._pollMax = 15; this.pollTime = 100;
+
+			if(dojox.embed.Flash.initialized){
+
+				this.id = dojox.embed.Flash.place(kwArgs, node);
+				this.domNode = node;
+
+				setTimeout(dojo.hitch(this, function(){
+					this.movie = this.byId(this.id, kwArgs.doc);
+					this.onReady(this.movie);
+
+					this._poller = setInterval(dojo.hitch(this, function(){
+
+						// catch errors if not quite ready.
+						try{
+							p = this.movie.PercentLoaded();
+						}catch(e){
+							/* squelch */
+							console.warn("this.movie.PercentLoaded() failed");
+						}
+
+						if(p == 100){
+							// if percent = 100, movie is fully loaded and we're communicating
+							this._onload();
+
+						}else if(p==0 && this._pollCount++ > this._pollMax){
+							// after several attempts, we're not past zero.
+							// FIXME: What if we get stuck on 33% or something?
+							clearInterval(this._poller);
+							throw new Error("Building SWF failed.");
+						}
+					}), this.pollTime);
+				}), 1);
+			}
+		},
+		_destroy: function(){
+			//	summary
+			//		Kill the movie and reset all the properties of this object.
+			try{
+				this.domNode.removeChild(this.movie);
+			}catch(e){}
+			this.id = this.movie = this.domNode = null;
+		},
+		destroy: function(){
+			//	summary
+			//		Public interface for destroying all the properties in this object.
+			//		Will also clean all proxied methods.
+			if(!this.movie){ return; }
+
+			//	remove any proxy functions
+			var test = dojo.delegate({
+				id: true,
+				movie: true,
+				domNode: true,
+				onReady: true,
+				onLoad: true
+			});
+			for(var p in this){
+				if(!test[p]){
+					delete this[p];
+				}
+			}
+
+			//	poll the movie
+			if(this._poller){
+				//	wait until onLoad to destroy
+				dojo.connect(this, "onLoad", this, "_destroy");
+			} else {
+				this._destroy();
+			}
+		},
+		byId: function (movieName, doc){
+			// 	summary:
+			//		Gets Flash movie by id.
+			//	description:
+			//		Probably includes methods for outdated
+			//		browsers, but this should catch all cases.
+			// arguments:
+			//		movieName: String
+			//			The name of the SWF
+			//		doc: Object
+			//			The document, if not current window
+			//			(not fully supported)
+			//	example:
+			//	| var movie = dojox.embed.Flash.byId("myId");
+			//
+			doc = doc || document;
+			if(doc.embeds[movieName]){
+				return doc.embeds[movieName];
+			}
+			if(doc[movieName]){
+				return doc[movieName];
+			}
+			if(window[movieName]){
+				return window[movieName];
+			}
+			if(document[movieName]){
+				return document[movieName];
+			}
+			return null;
+		}
+	});
+
+	//	expose information through the constructor function itself.
+	dojo.mixin(dojox.embed.Flash, {
+		//	summary:
+		//		A singleton object used internally to get information
+		//		about the Flash player available in a browser, and
+		//		as the factory for generating and placing markup in a
+		//		document.
+		//
+		//	minSupported: Number
+		//		The minimum supported version of the Flash Player, defaults to 8.
+		//	available: Number
+		//		Used as both a detection (i.e. if(dojox.embed.Flash.available){ })
+		//		and as a variable holding the major version of the player installed.
+		//	supported: Boolean
+		//		Whether or not the Flash Player installed is supported by dojox.embed.
+		//	version: Object
+		//		The version of the installed Flash Player; takes the form of
+		//		{ major, minor, rev }.  To get the major version, you'd do this:
+		//		var v=dojox.embed.Flash.version.major;
+		//	initialized: Boolean
+		//		Whether or not the Flash engine is available for use.
+		//	onInitialize: Function
+		//		A stub you can connect to if you are looking to fire code when the
+		//		engine becomes available.  A note: DO NOT use this event to
+		//		place a movie in a document; it will usually fire before DOMContentLoaded
+		//		is fired, and you will get an error.  Use dojo.addOnLoad instead.
+		minSupported : 8,
+		available: fVersion.major,
+		supported: (fVersion.major >= fVersion.required),
+		minimumRequired: fVersion.required,
+		version: fVersion,
+		initialized: false,
+		onInitialize: function(){
+			dojox.embed.Flash.initialized = true;
+		},
+		__ie_markup__: function(kwArgs){
+			return fMarkup(kwArgs);
+		},
+		proxy: function(/*dojox.embed.Flash*/ obj, /*Array|String*/ methods){
+			//	summary:
+			//		Create the set of passed methods on the dojox.embed.Flash object
+			//		so that you can call that object directly, as opposed to having to
+			//		delve into the internal movie to do this.  Intended to make working
+			//		with Flash movies that use ExternalInterface much easier to use.
+			//
+			//	example:
+			//		Create "setMessage" and "getMessage" methods on foo.
+			//	|	var foo = new dojox.embed.Flash(args, someNode);
+			//	|	dojo.connect(foo, "onLoad", dojo.hitch(foo, function(){
+			//	|		dojox.embed.Flash.proxy(this, [ "setMessage", "getMessage" ]);
+			//	|		this.setMessage("dojox.embed.Flash.proxy is pretty cool...");
+			//	|		console.log(this.getMessage());
+			//	|	}));
+			dojo.forEach((dojo.isArray(methods) ? methods : [ methods ]), function(item){
+				this[item] = dojo.hitch(this, function(){
+					return (function(){
+						return eval(this.movie.CallFunction(
+							'<invoke name="' + item + '" returntype="javascript">'
+							+ '<arguments>'
+							+ dojo.map(arguments, function(item){
+								// FIXME:
+								//		investigate if __flash__toXML will
+								//		accept direct application via map()
+								//		(e.g., does it ignore args past the
+								//		first? or does it blow up?)
+								return __flash__toXML(item);
+							}).join("")
+							+ '</arguments>'
+							+ '</invoke>'
+						));
+					}).apply(this, arguments||[]);
+				});
+			}, obj);
+		}
+	});
+
+	/*if(dojo.isIE){
+		//	Ugh!
+		if(dojo._initFired){
+			var e = document.createElement("script");
+			e.type = "text/javascript";
+			e.src = dojo.moduleUrl("dojox", "embed/IE/flash.js");
+			document.getElementsByTagName("head")[0].appendChild(e);
+		}else{
+			//	we can use document.write.  What a kludge.
+			document.write('<scr'+'ipt type="text/javascript" src="' + dojo.moduleUrl("dojox", "embed/IE/flash.js") + '">'
+				+ '</scr'+'ipt>');
+		}
+	}else{*/
+		dojox.embed.Flash.place = function(kwArgs, node){
+			var o = fMarkup(kwArgs);
+			node = dojo.byId(node);
+			if(!node){
+				node = dojo.doc.createElement("div");
+				node.id = o.id+"-container";
+				dojo.body().appendChild(node);
+			}
+			if(o){
+				node.innerHTML = o.markup;
+				return o.id;
+			}
+			return null;
+		}
+		dojox.embed.Flash.onInitialize();
+	//}
 })();
-}
diff --git a/dojox/embed/IE/flash.js b/dojox/embed/IE/flash.js
index fc8b0de..ad20e89 100644
--- a/dojox/embed/IE/flash.js
+++ b/dojox/embed/IE/flash.js
@@ -1,22 +1,19 @@
-/*
-	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
-*/
+// *** Fricking Eolas.  This is here to get around the Eolas issue.  Sigh. ***************
+dojox.embed.Flash.place = function(kwArgs, node){
+	var o = dojox.embed.Flash.__ie_markup__(kwArgs);
+	node=dojo.byId(node);
 
-
-dojox.embed.Flash.place=function(_1,_2){
-var o=dojox.embed.Flash.__ie_markup__(_1);
-_2=dojo.byId(_2);
-if(!_2){
-_2=dojo.doc.createElement("div");
-_2.id=o.id+"-container";
-dojo.body().appendChild(_2);
-}
-if(o){
-_2.innerHTML=o.markup;
-return o.id;
+	if(!node){
+		node=dojo.doc.createElement("div");
+		node.id=o.id+"-container";
+		dojo.body().appendChild(node);
+	}
+	
+	if(o){
+		node.innerHTML = o.markup;
+		//return window[o.id];
+		return o.id;
+	}
+	return null;
 }
-return null;
-};
 dojox.embed.Flash.onInitialize();
diff --git a/dojox/embed/Object.js b/dojox/embed/Object.js
index be01ece..5b81c47 100644
--- a/dojox/embed/Object.js
+++ b/dojox/embed/Object.js
@@ -1,39 +1,105 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.embed.Object"]){
-dojo._hasResource["dojox.embed.Object"]=true;
 dojo.provide("dojox.embed.Object");
 dojo.experimental("dojox.embed.Object");
+
 dojo.require("dijit._Widget");
 dojo.require("dojox.embed.Flash");
 dojo.require("dojox.embed.Quicktime");
-dojo.declare("dojox.embed.Object",dijit._Widget,{width:0,height:0,src:"",movie:null,params:null,reFlash:/\.swf|\.flv/gi,reQtMovie:/\.3gp|\.avi|\.m4v|\.mov|\.mp4|\.mpg|\.mpeg|\.qt/gi,reQtAudio:/\.aiff|\.aif|\.m4a|\.m4b|\.m4p|\.midi|\.mid|\.mp3|\.mpa|\.wav/gi,postCreate:function(){
-if(!this.width||!this.height){
-var _1=dojo.marginBox(this.domNode);
-this.width=_1.w,this.height=_1.h;
-}
-var em=dojox.embed.Flash;
-if(this.src.match(this.reQtMovie)||this.src.match(this.reQtAudio)){
-em=dojox.embed.Quicktime;
-}
-if(!this.params){
-this.params={};
-if(this.domNode.hasAttributes()){
-var _2={dojoType:"",width:"",height:"","class":"",style:"",id:"",src:""};
-var _3=this.domNode.attributes;
-for(var i=0,l=_3.length;i<l;i++){
-if(!_2[_3[i].name]){
-this.params[_3[i].name]=_3[i].value;
-}
-}
-}
-}
-var _4={path:this.src,width:this.width,height:this.height,params:this.params};
-this.movie=new (em)(_4,this.domNode);
-}});
-}
+
+dojo.declare("dojox.embed.Object", dijit._Widget, {
+	//	summary:
+	//		A widget you can use to embed either a Flash or Quicktime
+	//		movie.
+	//
+	//	example:
+	//	From markup:
+	//	|	<div dojoType="dojox.embed.Object" src="path/to/movie.swf"></div>
+	//
+	//	example:
+	//	Programmatic:
+	//	|	var mov=new dojox.embed.Object({
+	//	|		src: "path/to/movie.swf"
+	//	|	}, node);
+	//
+	//	width: Number?
+	//		The width of the movie. If not provided, the width of this.domNode is used.
+	//	height: Number?
+	//		The height of the movie. If not provided, the height of this.domNode is used.
+	//	src: String
+	//		The URL of the movie to embed.
+	//	movie: HTMLEmbed
+	//		The eventual reference to the movie embedded.  If you are looking to script
+	//		control over the movie, you'd access it this way.
+	//	params: Object
+	//		A property bag that is created postCreate.  Any additional attributes you
+	//		define on your domNode will be collected and placed into this, which will
+	//		then be passed to the movie constructor.
+	//	reFlash: RegExp
+	//		Expression used on the src property to determine if this is Flash or Quicktime.
+	//	reQtMovie: RegExp
+	//		Expression used on the src property to determine if this is Flash or Quicktime.
+	//	reQtAudio: RegExp
+	//		Expression used on the src property to determine if this is Flash or Quicktime.
+	
+	width: 0,
+	height: 0,
+	src: "",
+	movie: null,
+	params: null,
+
+	reFlash: /\.swf|\.flv/gi,
+	reQtMovie: /\.3gp|\.avi|\.m4v|\.mov|\.mp4|\.mpg|\.mpeg|\.qt/gi,
+	reQtAudio:/\.aiff|\.aif|\.m4a|\.m4b|\.m4p|\.midi|\.mid|\.mp3|\.mpa|\.wav/gi,
+	
+	postCreate: function(){
+		//	summary
+		//		Constructs the movie and places it in the document.
+		if(!this.width || !this.height){
+			//	get the width and height from the domNode
+			var box=dojo.marginBox(this.domNode);
+			this.width=box.w, this.height=box.h;
+		}
+
+		//	the default embed constructor.
+		var em=dojox.embed.Flash;
+
+		//	figure out what kind of movie this is.
+		if(this.src.match(this.reQtMovie) || this.src.match(this.reQtAudio)){
+			em=dojox.embed.Quicktime;
+		}
+
+		//	loop through any attributes and set up our params object.
+		if(!this.params){
+			this.params={};
+			if(this.domNode.hasAttributes()){
+				// ignore list
+				var ignore = {
+					dojoType: "",
+					width: "",
+					height: "",
+					"class": "",
+					style: "",
+					id: "",
+					src: ""
+				};
+
+				var attrs=this.domNode.attributes;
+				for(var i=0, l=attrs.length; i<l; i++){
+					if(!ignore[attrs[i].name]){
+						this.params[attrs[i].name]=attrs[i].value;
+					}
+				}
+			}
+		}
+
+		//	set up our arguments.
+		var kwArgs={
+			path: this.src,
+			width: this.width,
+			height: this.height,
+			params: this.params
+		};
+
+		//	set up the movie.
+		this.movie=new (em)(kwArgs, this.domNode);
+	}
+});
diff --git a/dojox/embed/Quicktime.js b/dojox/embed/Quicktime.js
index 2382e14..8f2521d 100644
--- a/dojox/embed/Quicktime.js
+++ b/dojox/embed/Quicktime.js
@@ -1,139 +1,261 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.embed.Quicktime"]){
-dojo._hasResource["dojox.embed.Quicktime"]=true;
 dojo.provide("dojox.embed.Quicktime");
+
 (function(d){
-var _1,_2={major:0,minor:0,rev:0},_3,_4={width:320,height:240,redirect:null},_5="dojox-embed-quicktime-",_6=0,_7="This content requires the <a href=\"http://www.apple.com/quicktime/download/\" title=\"Download and install QuickTime.\">QuickTime plugin</a>.";
-function _8(_9){
-_9=d.mixin(d.clone(_4),_9||{});
-if(!("path" in _9)&&!_9.testing){
-console.error("dojox.embed.Quicktime(ctor):: no path reference to a QuickTime movie was provided.");
-return null;
-}
-if(_9.testing){
-_9.path="";
-}
-if(!("id" in _9)){
-_9.id=_5+_6++;
-}
-return _9;
-};
-if(d.isIE){
-_3=(function(){
-try{
-var o=new ActiveXObject("QuickTimeCheckObject.QuickTimeCheck.1");
-if(o!==undefined){
-var v=o.QuickTimeVersion.toString(16);
-function p(i){
-return (v.substring(i,i+1)-0)||0;
-};
-_2={major:p(0),minor:p(1),rev:p(2)};
-return o.IsQuickTimeAvailable(0);
-}
-}
-catch(e){
-}
-return false;
-})();
-_1=function(_a){
-if(!_3){
-return {id:null,markup:_7};
-}
-_a=_8(_a);
-if(!_a){
-return null;
-}
-var s="<object classid=\"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B\" "+"codebase=\"http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0\" "+"id=\""+_a.id+"\" "+"width=\""+_a.width+"\" "+"height=\""+_a.height+"\">"+"<param name=\"src\" value=\""+_a.path+"\"/>";
-for(var p in _a.params||{}){
-s+="<param name=\""+p+"\" value=\""+_a.params[p]+"\"/>";
-}
-s+="</object>";
-return {id:_a.id,markup:s};
-};
-}else{
-_3=(function(){
-for(var i=0,p=navigator.plugins,l=p.length;i<l;i++){
-if(p[i].name.indexOf("QuickTime")>-1){
-return true;
-}
-}
-return false;
-})();
-_1=function(_b){
-if(!_3){
-return {id:null,markup:_7};
-}
-_b=_8(_b);
-if(!_b){
-return null;
-}
-var s="<embed type=\"video/quicktime\" src=\""+_b.path+"\" "+"id=\""+_b.id+"\" "+"name=\""+_b.id+"\" "+"pluginspage=\"www.apple.com/quicktime/download\" "+"enablejavascript=\"true\" "+"width=\""+_b.width+"\" "+"height=\""+_b.height+"\"";
-for(var p in _b.params||{}){
-s+=" "+p+"=\""+_b.params[p]+"\"";
-}
-s+="></embed>";
-return {id:_b.id,markup:s};
-};
-}
-dojox.embed.Quicktime=function(_c,_d){
-return dojox.embed.Quicktime.place(_c,_d);
-};
-d.mixin(dojox.embed.Quicktime,{minSupported:6,available:_3,supported:_3,version:_2,initialized:false,onInitialize:function(){
-dojox.embed.Quicktime.initialized=true;
-},place:function(_e,_f){
-var o=_1(_e);
-if(!(_f=d.byId(_f))){
-_f=d.create("div",{id:o.id+"-container"},d.body());
-}
-if(o){
-_f.innerHTML=o.markup;
-if(o.id){
-return d.isIE?d.byId(o.id):document[o.id];
-}
-}
-return null;
-}});
-if(!d.isIE){
-var id="-qt-version-test",o=_1({testing:true,width:4,height:4}),c=10,top="-1000px",_10="1px";
-function _11(){
-setTimeout(function(){
-var qt=document[o.id],n=d.byId(id);
-if(qt){
-try{
-var v=qt.GetQuickTimeVersion().split(".");
-dojox.embed.Quicktime.version={major:parseInt(v[0]||0),minor:parseInt(v[1]||0),rev:parseInt(v[2]||0)};
-if(dojox.embed.Quicktime.supported=v[0]){
-dojox.embed.Quicktime.onInitialize();
-}
-c=0;
-}
-catch(e){
-if(c--){
-_11();
-}
-}
-}
-if(!c&&n){
-d.destroy(n);
-}
-},20);
-};
-if(d._initFired){
-d.create("div",{innerHTML:o.markup,id:id,style:{top:top,left:0,width:_10,height:_10,overflow:"hidden",position:"absolute"}},d.body());
-}else{
-document.write("<div style=\"top:"+top+";left:0;width:"+_10+";height:"+_10+";overflow:hidden;position:absolute\" id=\""+id+"\">"+o.markup+"</div>");
-}
-_11();
-}else{
-if(d.isIE&&_3){
-dojox.embed.Quicktime.onInitialize();
-}
-}
-})(dojo);
-}
+	/*******************************************************
+		dojox.embed.Quicktime
+
+		Base functionality to insert a QuickTime movie
+		into a document on the fly.
+	 ******************************************************/
+
+	var qtMarkup,
+		qtVersion = { major: 0, minor: 0, rev: 0 },
+		installed,
+		__def__ = {
+			width: 320,
+			height: 240,
+			redirect: null
+		},
+		keyBase = "dojox-embed-quicktime-",
+		keyCount = 0,
+		getQTMarkup = 'This content requires the <a href="http://www.apple.com/quicktime/download/" title="Download and install QuickTime.">QuickTime plugin</a>.';
+
+	//	*** private methods *********************************************************
+	function prep(kwArgs){
+		kwArgs = d.mixin(d.clone(__def__), kwArgs || {});
+		if(!("path" in kwArgs) && !kwArgs.testing){
+			console.error("dojox.embed.Quicktime(ctor):: no path reference to a QuickTime movie was provided.");
+			return null;
+		}
+		if(kwArgs.testing){
+			kwArgs.path = "";
+		}
+		if(!("id" in kwArgs)){
+			kwArgs.id = keyBase + keyCount++;
+		}
+		return kwArgs;
+	}
+
+	if(d.isIE){
+		installed = (function(){
+			try{
+				var o = new ActiveXObject("QuickTimeCheckObject.QuickTimeCheck.1");
+				if(o!==undefined){
+					//	pull the qt version too
+					var v = o.QuickTimeVersion.toString(16);
+					function p(i){ return (v.substring(i, i+1)-0) || 0; }
+					qtVersion = {
+						major: p(0),
+						minor: p(1),
+						rev: p(2)
+					};
+					return o.IsQuickTimeAvailable(0);
+				}
+			} catch(e){ }
+			return false;
+		})();
+
+		qtMarkup = function(kwArgs){
+			if(!installed){ return { id: null, markup: getQTMarkup }; }
+			
+			kwArgs = prep(kwArgs);
+			if(!kwArgs){ return null; }
+			var s = '<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" '
+				+ 'codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" '
+				+ 'id="' + kwArgs.id + '" '
+				+ 'width="' + kwArgs.width + '" '
+				+ 'height="' + kwArgs.height + '">'
+				+ '<param name="src" value="' + kwArgs.path + '"/>';
+			for(var p in kwArgs.params||{}){
+				s += '<param name="' + p + '" value="' + kwArgs.params[p] + '"/>';
+			}
+			s += '</object>';
+			return { id: kwArgs.id, markup: s };
+		}
+	} else {
+		installed = (function(){
+			for(var i=0, p=navigator.plugins, l=p.length; i<l; i++){
+				if(p[i].name.indexOf("QuickTime")>-1){
+					return true;
+				}
+			}
+			return false;
+		})();
+
+		qtMarkup = function(kwArgs){
+			if(!installed){ return { id: null, markup: getQTMarkup }; }
+
+			kwArgs = prep(kwArgs);
+			if(!kwArgs){ return null; }
+			var s = '<embed type="video/quicktime" src="' + kwArgs.path + '" '
+				+ 'id="' + kwArgs.id + '" '
+				+ 'name="' + kwArgs.id + '" '
+				+ 'pluginspage="www.apple.com/quicktime/download" '
+				+ 'enablejavascript="true" '
+				+ 'width="' + kwArgs.width + '" '
+				+ 'height="' + kwArgs.height + '"';
+			for(var p in kwArgs.params||{}){
+				s += ' ' + p + '="' + kwArgs.params[p] + '"';
+			}
+			s += '></embed>';
+			return { id: kwArgs.id, markup: s };
+		}
+	}
+
+	/*=====
+	dojox.embed.__QTArgs = function(path, id, width, height, params, redirect){
+		//	path: String
+		//		The URL of the movie to embed.
+		//	id: String?
+		//		A unique key that will be used as the id of the created markup.  If you don't
+		//		provide this, a unique key will be generated.
+		//	width: Number?
+		//		The width of the embedded movie; the default value is 320px.
+		//	height: Number?
+		//		The height of the embedded movie; the default value is 240px
+		//	params: Object?
+		//		A set of key/value pairs that you want to define in the resultant markup.
+		//	redirect: String?
+		//		A url to redirect the browser to if the current QuickTime version is not supported.
+		this.id=id;
+		this.path=path;
+		this.width=width;
+		this.height=height;
+		this.params=params;
+		this.redirect=redirect;
+	}
+	=====*/
+
+	dojox.embed.Quicktime=function(/* dojox.embed.__QTArgs */kwArgs, /* DOMNode */node){
+		//	summary:
+		//		Returns a reference to the HTMLObject/HTMLEmbed that is created to 
+		//		place the movie in the document.  You can use this either with or
+		//		without the new operator.  Note that with any other DOM manipulation,
+		//		you must wait until the document is finished loading before trying
+		//		to use this.
+		//
+		//	example:
+		//		Embed a QuickTime movie in a document using the new operator, and get a reference to it.
+		//	|	var movie = new dojox.embed.Quicktime({
+		//	|		path: "path/to/my/movie.mov",
+		//	|		width: 400,
+		//	|		height: 300
+		//	|	}, myWrapperNode);
+		//
+		//	example:
+		//		Embed a movie in a document without using the new operator.
+		//	|	var movie = dojox.embed.Quicktime({
+		//	|		path: "path/to/my/movie.mov",
+		//	|		width: 400,
+		//	|		height: 300
+		//	|	}, myWrapperNode);
+
+		return dojox.embed.Quicktime.place(kwArgs, node);	//	HTMLObject
+	};
+
+	d.mixin(dojox.embed.Quicktime, {
+		//	summary:
+		//		A singleton object used internally to get information
+		//		about the QuickTime player available in a browser, and
+		//		as the factory for generating and placing markup in a
+		//		document.
+		//
+		//	minSupported: Number
+		//		The minimum supported version of the QuickTime Player, defaults to
+		//		6.
+		//	available: Boolean
+		//		Whether or not QuickTime is available.
+		//	supported: Boolean
+		//		Whether or not the QuickTime Player installed is supported by
+		//		dojox.embed.
+		//	version: Object
+		//		The version of the installed QuickTime Player; takes the form of
+		//		{ major, minor, rev }.  To get the major version, you'd do this:
+		//		var v=dojox.embed.Quicktime.version.major;
+		//	initialized: Boolean
+		//		Whether or not the QuickTime engine is available for use.
+		//	onInitialize: Function
+		//		A stub you can connect to if you are looking to fire code when the 
+		//		engine becomes available.  A note: do NOT use this stub to embed
+		//		a movie in your document; this WILL be fired before DOMContentLoaded
+		//		is fired, and you will get an error.  You should use dojo.addOnLoad
+		//		to place your movie instead.
+
+		minSupported: 6,
+		available: installed,
+		supported: installed,
+		version: qtVersion,
+		initialized: false,
+		onInitialize: function(){ 
+			dojox.embed.Quicktime.initialized = true; 
+		},	//	stub function to let you know when this is ready
+
+		place: function(kwArgs, node){
+			var o = qtMarkup(kwArgs);
+
+			if(!(node = d.byId(node))){
+				node=d.create("div", { id:o.id+"-container" }, d.body());
+			}
+			
+			if(o){
+				node.innerHTML = o.markup;
+				if(o.id){
+					return d.isIE? d.byId(o.id) : document[o.id];	//	QuickTimeObject
+				}
+			}
+			return null;	//	QuickTimeObject
+		}
+	});
+
+	//	go get the info
+	if(!d.isIE){
+		var id = "-qt-version-test",
+			o = qtMarkup({ testing:true , width:4, height:4 }),
+			c = 10, // counter to prevent infinite looping
+			top = "-1000px",
+			widthHeight = "1px";
+
+		function getVer(){
+			setTimeout(function(){
+				var qt = document[o.id],
+					n = d.byId(id);
+
+				if(qt){
+					try{
+						var v = qt.GetQuickTimeVersion().split(".");
+						dojox.embed.Quicktime.version = { major: parseInt(v[0]||0), minor: parseInt(v[1]||0), rev: parseInt(v[2]||0) };
+						if(dojox.embed.Quicktime.supported = v[0]){
+							dojox.embed.Quicktime.onInitialize();
+						}
+						c = 0;
+					} catch(e){
+						if(c--){
+							getVer();
+						}
+					}
+				}
+
+				if(!c && n){ d.destroy(n); }
+			}, 20);
+		}
+
+		if(d._initFired){
+			// if onload has already fired, then body is available and we can create a new node
+			d.create("div", {
+				innerHTML: o.markup,
+				id: id,
+				style: { top:top, left:0, width:widthHeight, height:widthHeight, overflow:"hidden", position:"absolute" }
+			}, d.body());
+		}else{
+			// body isn't loaded yet, so we need to document.write the QuickTime markup
+			document.write(
+				'<div style="top:'+top+';left:0;width:'+widthHeight+';height:'+widthHeight+';overflow:hidden;position:absolute" id="' + id + '">'
+				+ o.markup
+				+ '</div>');
+		}
+		getVer();
+	}else if(d.isIE && installed){
+		// we already know if IE has QuickTime installed
+		dojox.embed.Quicktime.onInitialize();
+	}
+})(dojo);
\ No newline at end of file
diff --git a/dojox/embed/flashVars.js b/dojox/embed/flashVars.js
index f67d0ba..f5a83c5 100644
--- a/dojox/embed/flashVars.js
+++ b/dojox/embed/flashVars.js
@@ -1,37 +1,55 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.embed.flashVars"]){
-dojo._hasResource["dojox.embed.flashVars"]=true;
 dojo.provide("dojox.embed.flashVars");
-dojo.mixin(dojox.embed.flashVars,{serialize:function(n,o){
-var _1=function(_2){
-if(typeof _2=="string"){
-_2=_2.replace(/;/g,"_sc_");
-_2=_2.replace(/\./g,"_pr_");
-_2=_2.replace(/\:/g,"_cl_");
-}
-return _2;
-};
-var df=dojox.embed.flashVars.serialize;
-var _3="";
-if(dojo.isArray(o)){
-for(var i=0;i<o.length;i++){
-_3+=df(n+"."+i,_1(o[i]))+";";
-}
-return _3.replace(/;{2,}/g,";");
-}else{
-if(dojo.isObject(o)){
-for(var nm in o){
-_3+=df(n+"."+nm,_1(o[nm]))+";";
-}
-return _3.replace(/;{2,}/g,";");
-}
-}
-return n+":"+o;
-}});
-}
+
+dojo.mixin(dojox.embed.flashVars, {
+	//	summary
+	//		Handles flashvar serialization
+	//		Converting complex objects into a simple, clear string that can be appended
+	//		to the swf as a query: myMovie.swf?flashvars=foo.
+	//		Note this needs to work with the SWF, which must know what variables to expect.
+	//		Therefore this is something of an "internal" class - unless you know how to
+	//		modify or create SWFs.
+	//
+	//	description:
+	//		JSON could be done, but Deft does not yet have a JSON parser, and quotes are
+	//		very problematic since Flash cannot use eval(); JSON parsing was successful
+	//		when it was fully escaped, but that made it very large anyway. flashvar
+	//		serialization at most is 200% larger than JSON.
+	//
+	//	See:
+	//		Deft/common/flashVars.as
+	//
+	serialize: function(/* String */n, /*Object*/o){
+		// summary:
+		//		Key method. Serializes an object.
+		//	n:String
+		//		The name for the object, such as: "button"
+		//	o:Object
+		//		The object to serialize
+		//
+		var esc = function(val){
+			//	have to encode certain characters that indicate an object
+			if(typeof val=="string"){
+				val = val.replace(/;/g,"_sc_");
+				val = val.replace(/\./g,"_pr_");
+				val = val.replace(/\:/g,"_cl_");
+				//val = escape(val);
+			}
+			return val;
+		};
+		var df = dojox.embed.flashVars.serialize;
+		var txt = "";
+		if(dojo.isArray(o)){
+			for(var i=0;i<o.length;i++){
+				txt += df(n+"."+i, esc(o[i]))+";";
+			}
+			return txt.replace(/;{2,}/g,";");
+		}else if(dojo.isObject(o)){
+			for(var nm in o){
+				txt += df(n+"."+nm, esc(o[nm]))+";";
+			}
+			return txt.replace(/;{2,}/g,";");
+		}
+		// Dev note: important that there is no double semi-colons
+		return n+":"+o; // String
+	}
+});
\ No newline at end of file
diff --git a/dojox/embed/tests/flash.html b/dojox/embed/tests/flash.html
new file mode 100644
index 0000000..f4dcab4
--- /dev/null
+++ b/dojox/embed/tests/flash.html
@@ -0,0 +1,58 @@
+<html>
+	<head>
+		<title>dojox.embed.Flash Detection Test</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.embed.Flash");
+
+			/*******************************************************************
+				A note.
+
+				You *can* dojo.require dojox.embed.Flash on the fly (i.e.
+				after load), but if you do so, you *must* give Safari and IE
+				a little bit of time before you can start using any of the 
+				methods.  Quick tests showed that 200ms is more than enough,
+				but you should test intervals at your discretion.
+			********************************************************************/
+			var testMovieUrl=dojo.moduleUrl("dojox", "embed/tests/resources/hfp.swf"), movie;
+			var proxyMovieUrl=dojo.moduleUrl("dojox", "embed/tests/resources/TestFlash.swf"), proxy;
+
+			function log(msg){
+				dojo.byId("fakeconsole").innerHTML += "<div>"+msg+"</div>";
+			}
+			
+			dojo.addOnLoad(function(){
+				dojo.byId("results").innerHTML = dojo.toJson(dojox.embed.Flash.version);
+				movie=new dojox.embed.Flash({ path: testMovieUrl }, "flashHolder");
+				dojo.connect(movie, "onReady", function(mv){
+					console.log("The test movie loaded.");
+				});
+				
+				proxy = new dojox.embed.Flash({ path: proxyMovieUrl, width:4, height:4 }, "proxyHolder");
+				dojo.connect(proxy, "onLoad", function(m){
+					dojox.embed.Flash.proxy(proxy, [ "setMessage", "getMessage" ]);
+					console.log("Setting the message on the proxy to 'we love dojox.embed!'");
+					proxy.setMessage("we love dojox.embed");
+					console.log("The message stored in the test movie is: '", proxy.getMessage(), "'");
+				});
+			});
+		</script>
+	</head>
+	<body>
+		<h1>Dojo.embed.Flash detection tests.</h1>
+		<p>
+			This page is testing the base Flash movie generator.
+		</p>
+		<div id="fakeconsole"></div>	
+		<p>Installed Flash version: <span id="results"></span>.</p>
+		<div id="flashHolder" style="border:1px solid black;">
+			A movie will be inserted here on load.
+		</div>
+		<div id="proxyHolder" style="width:4px;height:4px;position:absolute;"></div>
+	</body>
+</html>
diff --git a/dojox/embed/tests/object.html b/dojox/embed/tests/object.html
new file mode 100644
index 0000000..d2db174
--- /dev/null
+++ b/dojox/embed/tests/object.html
@@ -0,0 +1,29 @@
+<html>
+	<head>
+		<title>dojox.embed.Object Test</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+			#flashTest {
+				border: 1px solid blue;
+				width: 400px;
+				height: 500px;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.embed.Object");
+			dojo.require("dojo.parser");
+		</script>
+	</head>
+	<body>
+		<h1>dojox.embed.Object</h1>
+		<p>
+		This is a test for the embedder widget.  Iron Man trailer is referenced directly from the Apple servers.
+		</p>
+		<div dojoType="dojox.embed.Object" src="http://movies.apple.com/movies/paramount/iron_man/iron_man-tlr2_h.320.mov" width="320" height="152"></div>
+		<div dojoType="dojox.embed.Object" src="resources/hfp.swf" style="float:right;width:100px;height:100px;border:1px solid black;"></div>
+		<div id="flashTest" dojoType="dojox.embed.Object" src="resources/hfp.swf"></div>
+	</body>
+</html>
diff --git a/dojox/embed/tests/quicktime.html b/dojox/embed/tests/quicktime.html
new file mode 100644
index 0000000..8888127
--- /dev/null
+++ b/dojox/embed/tests/quicktime.html
@@ -0,0 +1,46 @@
+<html>
+	<head>
+		<title>dojo.embed.QuickTime Detection Test</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.embed.Quicktime");
+
+			//	what a pain.  We hate having to deal with async loading issues.
+			dojo.addOnLoad(function(){
+				console.log("Getting the Quicktime version...");
+				var r=dojo.byId("results"),
+					fn=function(){
+						var v=dojox.embed.Quicktime.version || { major: 0, minor: 0, rev: 0 };
+						r.innerHTML = v.major
+							+ '.' + v.minor
+							+ '.' + v.rev;
+					};
+				if(!dojox.embed.Quicktime.available){
+					r.innerHTML = "QuickTime plugin not installed";
+				}else if(!dojox.embed.Quicktime.supported){
+					r.innerHTML = "QuickTime not supported";
+				}else if(dojox.embed.Quicktime.initialized){
+					fn();
+				}else{
+					console.log("dojox.embed.Quicktime not initialized yet... waiting");
+					var h=dojo.connect(dojox.embed.Quicktime, "onInitialize", function(){
+						fn();
+						dojo.disconnect(h);
+					});
+				}
+			});
+		</script>
+	</head>
+	<body>
+		<h1>DojoX A/V: QuickTime detection tests.</h1>
+		
+		<p>This page is testing the base QuickTime movie generator.  See the Firebug log for details.</p>
+		
+		<p>Installed QuickTime version: <span id="results"></span></p>
+	</body>
+</html>
diff --git a/dojox/embed/tests/resources/TestFlash.swf b/dojox/embed/tests/resources/TestFlash.swf
new file mode 100644
index 0000000..cfd3f8d
Binary files /dev/null and b/dojox/embed/tests/resources/TestFlash.swf differ
diff --git a/dojox/embed/tests/resources/hfp.swf b/dojox/embed/tests/resources/hfp.swf
new file mode 100644
index 0000000..b878f69
Binary files /dev/null and b/dojox/embed/tests/resources/hfp.swf differ
diff --git a/dojox/encoding/_base.js b/dojox/encoding/_base.js
index 8c60ddc..c3dfe82 100644
--- a/dojox/encoding/_base.js
+++ b/dojox/encoding/_base.js
@@ -1,11 +1,3 @@
-/*
-	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
-*/
+dojo.provide("dojox.encoding._base");
 
 
-if(!dojo._hasResource["dojox.encoding._base"]){
-dojo._hasResource["dojox.encoding._base"]=true;
-dojo.provide("dojox.encoding._base");
-}
diff --git a/dojox/encoding/ascii85.js b/dojox/encoding/ascii85.js
index f5eaa54..79c6991 100644
--- a/dojox/encoding/ascii85.js
+++ b/dojox/encoding/ascii85.js
@@ -1,71 +1,59 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.ascii85"]){
-dojo._hasResource["dojox.encoding.ascii85"]=true;
 dojo.provide("dojox.encoding.ascii85");
+
 (function(){
-var c=function(_1,_2,_3){
-var i,j,n,b=[0,0,0,0,0];
-for(i=0;i<_2;i+=4){
-n=((_1[i]*256+_1[i+1])*256+_1[i+2])*256+_1[i+3];
-if(!n){
-_3.push("z");
-}else{
-for(j=0;j<5;b[j++]=n%85+33,n=Math.floor(n/85)){
-}
-}
-_3.push(String.fromCharCode(b[4],b[3],b[2],b[1],b[0]));
-}
-};
-dojox.encoding.ascii85.encode=function(_4){
-var _5=[],_6=_4.length%4,_7=_4.length-_6;
-c(_4,_7,_5);
-if(_6){
-var t=_4.slice(_7);
-while(t.length<4){
-t.push(0);
-}
-c(t,4,_5);
-var x=_5.pop();
-if(x=="z"){
-x="!!!!!";
-}
-_5.push(x.substr(0,_6+1));
-}
-return _5.join("");
-};
-dojox.encoding.ascii85.decode=function(_8){
-var n=_8.length,r=[],b=[0,0,0,0,0],i,j,t,x,y,d;
-for(i=0;i<n;++i){
-if(_8.charAt(i)=="z"){
-r.push(0,0,0,0);
-continue;
-}
-for(j=0;j<5;++j){
-b[j]=_8.charCodeAt(i+j)-33;
-}
-d=n-i;
-if(d<5){
-for(j=d;j<4;b[++j]=0){
-}
-b[d]=85;
-}
-t=(((b[0]*85+b[1])*85+b[2])*85+b[3])*85+b[4];
-x=t&255;
-t>>>=8;
-y=t&255;
-t>>>=8;
-r.push(t>>>8,t&255,y,x);
-for(j=d;j<5;++j,r.pop()){
-}
-i+=4;
-}
-return r;
-};
+	var c = function(input, length, result){
+		var i, j, n, b = [0, 0, 0, 0, 0];
+		for(i = 0; i < length; i += 4){
+			n = ((input[i] * 256 + input[i+1]) * 256 + input[i+2]) * 256 + input[i+3];
+			if(!n){
+				result.push("z");
+			}else{
+				for(j = 0; j < 5; b[j++] = n % 85 + 33, n = Math.floor(n / 85));
+			}
+			result.push(String.fromCharCode(b[4], b[3], b[2], b[1], b[0]));
+		}
+	};
+	
+	dojox.encoding.ascii85.encode = function(input){
+		// summary: encodes input data in ascii85 string
+		// input: Array: an array of numbers (0-255) to encode
+		var result = [], reminder = input.length % 4, length = input.length - reminder;
+		c(input, length, result);
+		if(reminder){
+			var t = input.slice(length);
+			while(t.length < 4){ t.push(0); }
+			c(t, 4, result);
+			var x = result.pop();
+			if(x == "z"){ x = "!!!!!"; }
+			result.push(x.substr(0, reminder + 1));
+		}
+		return result.join("");	// String
+	};
+
+	dojox.encoding.ascii85.decode = function(input){
+		// summary: decodes the input string back to array of numbers
+		// input: String: the input string to decode
+		var n = input.length, r = [], b = [0, 0, 0, 0, 0], i, j, t, x, y, d;
+		for(i = 0; i < n; ++i){
+			if(input.charAt(i) == "z"){
+				r.push(0, 0, 0, 0);
+				continue;
+			}
+			for(j = 0; j < 5; ++j){ b[j] = input.charCodeAt(i + j) - 33; }
+			d = n - i;
+			if(d < 5){
+				for(j = d; j < 4; b[++j] = 0);
+				b[d] = 85;
+			}
+			t = (((b[0] * 85 + b[1]) * 85 + b[2]) * 85 + b[3]) * 85 + b[4];
+			x = t & 255;
+			t >>>= 8;
+			y = t & 255;
+			t >>>= 8;
+			r.push(t >>> 8, t & 255, y, x);
+			for(j = d; j < 5; ++j, r.pop());
+			i += 4;
+		}
+		return r;
+	};
 })();
-}
diff --git a/dojox/encoding/base64.js b/dojox/encoding/base64.js
index 307eafa..1b77bca 100644
--- a/dojox/encoding/base64.js
+++ b/dojox/encoding/base64.js
@@ -1,70 +1,62 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.base64"]){
-dojo._hasResource["dojox.encoding.base64"]=true;
 dojo.provide("dojox.encoding.base64");
+
 (function(){
-var p="=";
-var _1="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-var _2=dojox.encoding;
-_2.base64.encode=function(ba){
-var s=[],l=ba.length;
-var rm=l%3;
-var x=l-rm;
-for(var i=0;i<x;){
-var t=ba[i++]<<16|ba[i++]<<8|ba[i++];
-s.push(_1.charAt((t>>>18)&63));
-s.push(_1.charAt((t>>>12)&63));
-s.push(_1.charAt((t>>>6)&63));
-s.push(_1.charAt(t&63));
-}
-switch(rm){
-case 2:
-var t=ba[i++]<<16|ba[i++]<<8;
-s.push(_1.charAt((t>>>18)&63));
-s.push(_1.charAt((t>>>12)&63));
-s.push(_1.charAt((t>>>6)&63));
-s.push(p);
-break;
-case 1:
-var t=ba[i++]<<16;
-s.push(_1.charAt((t>>>18)&63));
-s.push(_1.charAt((t>>>12)&63));
-s.push(p);
-s.push(p);
-break;
-}
-return s.join("");
-};
-_2.base64.decode=function(_3){
-var s=_3.split(""),_4=[];
-var l=s.length;
-while(s[--l]==p){
-}
-for(var i=0;i<l;){
-var t=_1.indexOf(s[i++])<<18;
-if(i<=l){
-t|=_1.indexOf(s[i++])<<12;
-}
-if(i<=l){
-t|=_1.indexOf(s[i++])<<6;
-}
-if(i<=l){
-t|=_1.indexOf(s[i++]);
-}
-_4.push((t>>>16)&255);
-_4.push((t>>>8)&255);
-_4.push(t&255);
-}
-while(_4[_4.length-1]==0){
-_4.pop();
-}
-return _4;
-};
+	var p="=";
+	var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+	var dxe=dojox.encoding;
+
+	dxe.base64.encode=function(/* byte[] */ba){
+		//	summary
+		//	Encode an array of bytes as a base64-encoded string
+		var s=[], l=ba.length;
+		var rm=l%3;
+		var x=l-rm;
+		for (var i=0; i<x;){
+			var t=ba[i++]<<16|ba[i++]<<8|ba[i++];
+			s.push(tab.charAt((t>>>18)&0x3f)); 
+			s.push(tab.charAt((t>>>12)&0x3f));
+			s.push(tab.charAt((t>>>6)&0x3f));
+			s.push(tab.charAt(t&0x3f));
+		}
+		//	deal with trailers, based on patch from Peter Wood.
+		switch(rm){
+			case 2:{
+				var t=ba[i++]<<16|ba[i++]<<8;
+				s.push(tab.charAt((t>>>18)&0x3f));
+				s.push(tab.charAt((t>>>12)&0x3f));
+				s.push(tab.charAt((t>>>6)&0x3f));
+				s.push(p);
+				break;
+			}
+			case 1:{
+				var t=ba[i++]<<16;
+				s.push(tab.charAt((t>>>18)&0x3f));
+				s.push(tab.charAt((t>>>12)&0x3f));
+				s.push(p);
+				s.push(p);
+				break;
+			}
+		}
+		return s.join("");	//	string
+	};
+
+	dxe.base64.decode=function(/* string */str){
+		//	summary
+		//	Convert a base64-encoded string to an array of bytes
+		var s=str.split(""), out=[];
+		var l=s.length;
+		while(s[--l]==p){ }	//	strip off trailing padding
+		for (var i=0; i<l;){
+			var t=tab.indexOf(s[i++])<<18;
+			if(i<=l){ t|=tab.indexOf(s[i++])<<12 };
+			if(i<=l){ t|=tab.indexOf(s[i++])<<6 };
+			if(i<=l){ t|=tab.indexOf(s[i++]) };
+			out.push((t>>>16)&0xff);
+			out.push((t>>>8)&0xff);
+			out.push(t&0xff);
+		}
+		//	strip off any null bytes
+		while(out[out.length-1]==0){ out.pop(); }
+		return out;	//	byte[]
+	};
 })();
-}
diff --git a/dojox/encoding/bits.js b/dojox/encoding/bits.js
index 6f68c9d..348fd22 100644
--- a/dojox/encoding/bits.js
+++ b/dojox/encoding/bits.js
@@ -1,64 +1,64 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.bits"]){
-dojo._hasResource["dojox.encoding.bits"]=true;
 dojo.provide("dojox.encoding.bits");
-dojox.encoding.bits.OutputStream=function(){
-this.reset();
+
+dojox.encoding.bits.OutputStream = function(){
+	this.reset();
 };
-dojo.extend(dojox.encoding.bits.OutputStream,{reset:function(){
-this.buffer=[];
-this.accumulator=0;
-this.available=8;
-},putBits:function(_1,_2){
-while(_2){
-var w=Math.min(_2,this.available);
-var v=(w<=_2?_1>>>(_2-w):_1)<<(this.available-w);
-this.accumulator|=v&(255>>>(8-this.available));
-this.available-=w;
-if(!this.available){
-this.buffer.push(this.accumulator);
-this.accumulator=0;
-this.available=8;
-}
-_2-=w;
-}
-},getWidth:function(){
-return this.buffer.length*8+(8-this.available);
-},getBuffer:function(){
-var b=this.buffer;
-if(this.available<8){
-b.push(this.accumulator&(255<<this.available));
-}
-this.reset();
-return b;
-}});
-dojox.encoding.bits.InputStream=function(_3,_4){
-this.buffer=_3;
-this.width=_4;
-this.bbyte=this.bit=0;
+
+dojo.extend(dojox.encoding.bits.OutputStream, {
+	reset: function(){
+		this.buffer = [];
+		this.accumulator = 0;
+		this.available = 8;
+	},
+	putBits: function(value, width){
+		while(width){
+			var w = Math.min(width, this.available);
+			var v = (w <= width ? value >>> (width - w) : value) << (this.available - w);
+			this.accumulator |= v & (255 >>> (8 - this.available));
+			this.available -= w;
+			if(!this.available){
+				this.buffer.push(this.accumulator);
+				this.accumulator = 0;
+				this.available = 8;
+			}
+			width -= w;
+		}
+	},
+	getWidth: function(){
+		return this.buffer.length * 8 + (8 - this.available);
+	},
+	getBuffer: function(){
+		var b = this.buffer;
+		if(this.available < 8){ b.push(this.accumulator & (255 << this.available)); }
+		this.reset();
+		return b;
+	}
+});
+
+dojox.encoding.bits.InputStream = function(buffer, width){
+	this.buffer = buffer;
+	this.width = width;
+	this.bbyte = this.bit = 0;
 };
-dojo.extend(dojox.encoding.bits.InputStream,{getBits:function(_5){
-var r=0;
-while(_5){
-var w=Math.min(_5,8-this.bit);
-var v=this.buffer[this.bbyte]>>>(8-this.bit-w);
-r<<=w;
-r|=v&~(~0<<w);
-this.bit+=w;
-if(this.bit==8){
-++this.bbyte;
-this.bit=0;
-}
-_5-=w;
-}
-return r;
-},getWidth:function(){
-return this.width-this.bbyte*8-this.bit;
-}});
-}
+
+dojo.extend(dojox.encoding.bits.InputStream, {
+	getBits: function(width){
+		var r = 0;
+		while(width){
+			var w = Math.min(width, 8 - this.bit);
+			var v = this.buffer[this.bbyte] >>> (8 - this.bit - w);
+			r <<= w;
+			r |= v & ~(~0 << w);
+			this.bit += w;
+			if(this.bit == 8){
+				++this.bbyte;
+				this.bit = 0;
+			}
+			width -= w;
+		}
+		return r;
+	},
+	getWidth: function(){
+		return this.width - this.bbyte * 8 - this.bit;
+	}
+});
diff --git a/dojox/encoding/compression/lzw.js b/dojox/encoding/compression/lzw.js
index b61238a..272061e 100644
--- a/dojox/encoding/compression/lzw.js
+++ b/dojox/encoding/compression/lzw.js
@@ -1,83 +1,87 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.compression.lzw"]){
-dojo._hasResource["dojox.encoding.compression.lzw"]=true;
 dojo.provide("dojox.encoding.compression.lzw");
 dojo.require("dojox.encoding.bits");
+
 (function(){
-var _1=function(x){
-var w=1;
-for(var v=2;x>=v;v<<=1,++w){
-}
-return w;
-};
-dojox.encoding.compression.lzw.Encoder=function(n){
-this.size=n;
-this.init();
-};
-dojo.extend(dojox.encoding.compression.lzw.Encoder,{init:function(){
-this.dict={};
-for(var i=0;i<this.size;++i){
-this.dict[String.fromCharCode(i)]=i;
-}
-this.width=_1(this.code=this.size);
-this.p="";
-},encode:function(_2,_3){
-var c=String.fromCharCode(_2),p=this.p+c,r=0;
-if(p in this.dict){
-this.p=p;
-return r;
-}
-_3.putBits(this.dict[this.p],this.width);
-if((this.code&(this.code+1))==0){
-_3.putBits(this.code++,r=this.width++);
-}
-this.dict[p]=this.code++;
-this.p=c;
-return r+this.width;
-},flush:function(_4){
-if(this.p.length==0){
-return 0;
-}
-_4.putBits(this.dict[this.p],this.width);
-this.p="";
-return this.width;
-}});
-dojox.encoding.compression.lzw.Decoder=function(n){
-this.size=n;
-this.init();
-};
-dojo.extend(dojox.encoding.compression.lzw.Decoder,{init:function(){
-this.codes=new Array(this.size);
-for(var i=0;i<this.size;++i){
-this.codes[i]=String.fromCharCode(i);
-}
-this.width=_1(this.size);
-this.p=-1;
-},decode:function(_5){
-var c=_5.getBits(this.width),v;
-if(c<this.codes.length){
-v=this.codes[c];
-if(this.p>=0){
-this.codes.push(this.codes[this.p]+v.substr(0,1));
-}
-}else{
-if((c&(c+1))==0){
-this.codes.push("");
-++this.width;
-return "";
-}
-var x=this.codes[this.p];
-v=x+x.substr(0,1);
-this.codes.push(v);
-}
-this.p=c;
-return v;
-}});
+	var _bits = function(x){
+		var w = 1;
+		for(var v = 2; x >= v; v <<= 1, ++w);
+		return w;
+	};
+
+	dojox.encoding.compression.lzw.Encoder = function(n){
+		this.size = n;
+		this.init();
+	};
+
+	dojo.extend(dojox.encoding.compression.lzw.Encoder, {
+		init: function(){
+			this.dict = {};
+			for(var i = 0; i < this.size; ++i){
+				this.dict[String.fromCharCode(i)] = i;
+			}
+			this.width = _bits(this.code = this.size);
+			this.p = "";
+		},
+		encode: function(value, stream){
+			var c = String.fromCharCode(value), p = this.p + c, r = 0;
+			// if already in the dictionary
+			if(p in this.dict){
+				this.p = p;
+				return r;
+			}
+			stream.putBits(this.dict[this.p], this.width);
+			// if we need to increase the code length
+			if((this.code & (this.code + 1)) == 0){
+				stream.putBits(this.code++, r = this.width++);
+			}
+			// add new string
+			this.dict[p] = this.code++;
+			this.p = c;
+			return r + this.width;
+		},
+		flush: function(stream){
+			if(this.p.length == 0){
+				return 0;
+			}
+			stream.putBits(this.dict[this.p], this.width);
+			this.p = "";
+			return this.width;
+		}
+	});
+
+	dojox.encoding.compression.lzw.Decoder = function(n){
+		this.size = n;
+		this.init();
+	};
+
+	dojo.extend(dojox.encoding.compression.lzw.Decoder, {
+		init: function(){
+			this.codes = new Array(this.size);
+			for(var i = 0; i < this.size; ++i){
+				this.codes[i] = String.fromCharCode(i);
+			}
+			this.width = _bits(this.size);
+			this.p = -1;
+		},
+		decode: function(stream){
+			var c = stream.getBits(this.width), v;
+			if(c < this.codes.length){
+				v = this.codes[c];
+				if(this.p >= 0){
+					this.codes.push(this.codes[this.p] + v.substr(0, 1));
+				}
+			}else{
+				if((c & (c + 1)) == 0){
+					this.codes.push("");
+					++this.width;
+					return "";
+				}
+				var x = this.codes[this.p];
+				v = x + x.substr(0, 1);
+				this.codes.push(v);
+			}
+			this.p = c;
+			return v;
+		}
+	});
 })();
-}
diff --git a/dojox/encoding/compression/splay.js b/dojox/encoding/compression/splay.js
index 8f509f8..7582f8f 100644
--- a/dojox/encoding/compression/splay.js
+++ b/dojox/encoding/compression/splay.js
@@ -1,65 +1,60 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.compression.splay"]){
-dojo._hasResource["dojox.encoding.compression.splay"]=true;
 dojo.provide("dojox.encoding.compression.splay");
 dojo.require("dojox.encoding.bits");
-dojox.encoding.compression.Splay=function(n){
-this.up=new Array(2*n+1);
-this.left=new Array(n);
-this.right=new Array(n);
-this.reset();
+
+dojox.encoding.compression.Splay = function(n){
+	this.up = new Array(2 * n + 1);
+	this.left = new Array(n);
+	this.right = new Array(n);
+	this.reset();
 };
-dojo.extend(dojox.encoding.compression.Splay,{reset:function(){
-for(var i=1;i<this.up.length;this.up[i]=Math.floor((i-1)/2),++i){
-}
-for(var i=0;i<this.left.length;this.left[i]=2*i+1,this.right[i]=2*i+2,++i){
-}
-},splay:function(i){
-var a=i+this.left.length;
-do{
-var c=this.up[a];
-if(c){
-var d=this.up[c];
-var b=this.left[d];
-if(c==b){
-b=this.right[d];
-this.right[d]=a;
-}else{
-this.left[d]=a;
-}
-this[a==this.left[c]?"left":"right"][c]=b;
-this.up[a]=d;
-this.up[b]=c;
-a=d;
-}else{
-a=c;
-}
-}while(a);
-},encode:function(_1,_2){
-var s=[],a=_1+this.left.length;
-do{
-s.push(this.right[this.up[a]]==a);
-a=this.up[a];
-}while(a);
-this.splay(_1);
-var l=s.length;
-while(s.length){
-_2.putBits(s.pop()?1:0,1);
-}
-return l;
-},decode:function(_3){
-var a=0;
-do{
-a=this[_3.getBits(1)?"right":"left"][a];
-}while(a<this.left.length);
-a-=this.left.length;
-this.splay(a);
-return a;
-}});
-}
+
+dojo.extend(dojox.encoding.compression.Splay, {
+	reset: function(){
+		for(var i = 1; i < this.up.length; this.up[i] = Math.floor((i - 1) / 2), ++i);
+		for(var i = 0; i < this.left.length; this.left[i] = 2 * i + 1, this.right[i] = 2 * i + 2, ++i);
+	},
+	splay: function(i){
+		var a = i + this.left.length;
+		do{
+			var c = this.up[a];
+			if(c){	// root
+				// rotated pair
+				var d = this.up[c];
+				// swap descendants
+				var b = this.left[d];
+				if(c == b){
+					b = this.right[d];
+					this.right[d] = a;
+				} else {
+					this.left[d] = a;
+				}
+				this[a == this.left[c] ? "left" : "right"][c] = b;
+				this.up[a] = d;
+				this.up[b] = c;
+				a = d;
+			}else{
+				a = c;
+			}
+		}while(a);	// root
+	},
+	encode: function(value, stream){
+		var s = [], a = value + this.left.length;
+		do{
+			s.push(this.right[this.up[a]] == a);
+			a = this.up[a];
+		}while(a);	// root
+		this.splay(value);
+		var l = s.length;
+		while(s.length){ stream.putBits(s.pop() ? 1 : 0, 1); }
+		return	l;
+	},
+	decode: function(stream){
+		var a = 0;	// root;
+		do{
+			a = this[stream.getBits(1) ? "right" : "left"][a];
+		}while(a < this.left.length);
+		a -= this.left.length;
+		this.splay(a);
+		return	a;
+	}
+});
diff --git a/dojox/encoding/crypto/Blowfish.js b/dojox/encoding/crypto/Blowfish.js
index 696e775..69b21fd 100644
--- a/dojox/encoding/crypto/Blowfish.js
+++ b/dojox/encoding/crypto/Blowfish.js
@@ -1,275 +1,477 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.crypto.Blowfish"]){
-dojo._hasResource["dojox.encoding.crypto.Blowfish"]=true;
 dojo.provide("dojox.encoding.crypto.Blowfish");
+
 dojo.require("dojox.encoding.base64");
 dojo.require("dojox.encoding.crypto._base");
-dojox.encoding.crypto.Blowfish=new function(){
-var _1=Math.pow(2,2);
-var _2=Math.pow(2,3);
-var _3=Math.pow(2,4);
-var _4=Math.pow(2,8);
-var _5=Math.pow(2,16);
-var _6=Math.pow(2,24);
-var iv=null;
-var _7={p:[608135816,2242054355,320440878,57701188,2752067618,698298832,137296536,3964562569,1160258022,953160567,3193202383,887688300,3232508343,3380367581,1065670069,3041331479,2450970073,2306472731],s0:[3509652390,2564797868,805139163,3491422135,3101798381,1780907670,3128725573,4046225305,614570311,3012652279,134345442,2240740374,1667834072,1901547113,2757295779,4103290238,227898511,1921955416,1904987480,2182433518,2069144605,3260701109,2620446009,720527379,3318853667,677414384,339328 [...]
-function _8(x,y){
-return (((x>>16)+(y>>16)+(((x&65535)+(y&65535))>>16))<<16)|(((x&65535)+(y&65535))&65535);
-};
-function _9(x,y){
-return (((x>>16)^(y>>16))<<16)|(((x&65535)^(y&65535))&65535);
-};
-function $(v,_a){
-var d=_a.s3[v&255];
-v>>=8;
-var c=_a.s2[v&255];
-v>>=8;
-var b=_a.s1[v&255];
-v>>=8;
-var a=_a.s0[v&255];
-var r=(((a>>16)+(b>>16)+(((a&65535)+(b&65535))>>16))<<16)|(((a&65535)+(b&65535))&65535);
-r=(((r>>16)^(c>>16))<<16)|(((r&65535)^(c&65535))&65535);
-return (((r>>16)+(d>>16)+(((r&65535)+(d&65535))>>16))<<16)|(((r&65535)+(d&65535))&65535);
-};
-function eb(o,_b){
-var l=o.left;
-var r=o.right;
-l=_9(l,_b.p[0]);
-r=_9(r,_9($(l,_b),_b.p[1]));
-l=_9(l,_9($(r,_b),_b.p[2]));
-r=_9(r,_9($(l,_b),_b.p[3]));
-l=_9(l,_9($(r,_b),_b.p[4]));
-r=_9(r,_9($(l,_b),_b.p[5]));
-l=_9(l,_9($(r,_b),_b.p[6]));
-r=_9(r,_9($(l,_b),_b.p[7]));
-l=_9(l,_9($(r,_b),_b.p[8]));
-r=_9(r,_9($(l,_b),_b.p[9]));
-l=_9(l,_9($(r,_b),_b.p[10]));
-r=_9(r,_9($(l,_b),_b.p[11]));
-l=_9(l,_9($(r,_b),_b.p[12]));
-r=_9(r,_9($(l,_b),_b.p[13]));
-l=_9(l,_9($(r,_b),_b.p[14]));
-r=_9(r,_9($(l,_b),_b.p[15]));
-l=_9(l,_9($(r,_b),_b.p[16]));
-o.right=l;
-o.left=_9(r,_b.p[17]);
-};
-function db(o,_c){
-var l=o.left;
-var r=o.right;
-l=_9(l,_c.p[17]);
-r=_9(r,_9($(l,_c),_c.p[16]));
-l=_9(l,_9($(r,_c),_c.p[15]));
-r=_9(r,_9($(l,_c),_c.p[14]));
-l=_9(l,_9($(r,_c),_c.p[13]));
-r=_9(r,_9($(l,_c),_c.p[12]));
-l=_9(l,_9($(r,_c),_c.p[11]));
-r=_9(r,_9($(l,_c),_c.p[10]));
-l=_9(l,_9($(r,_c),_c.p[9]));
-r=_9(r,_9($(l,_c),_c.p[8]));
-l=_9(l,_9($(r,_c),_c.p[7]));
-r=_9(r,_9($(l,_c),_c.p[6]));
-l=_9(l,_9($(r,_c),_c.p[5]));
-r=_9(r,_9($(l,_c),_c.p[4]));
-l=_9(l,_9($(r,_c),_c.p[3]));
-r=_9(r,_9($(l,_c),_c.p[2]));
-l=_9(l,_9($(r,_c),_c.p[1]));
-o.right=l;
-o.left=_9(r,_c.p[0]);
-};
-function _d(_e){
-var k=_e;
-if(dojo.isString(k)){
-k=dojo.map(k.split(""),function(_f){
-return _f.charCodeAt(0)&255;
-});
-}
-var pos=0,_10=0,res={left:0,right:0},i,j,l;
-var box={p:dojo.map(_7.p.slice(0),function(_11){
-var l=k.length,j;
-for(j=0;j<4;j++){
-_10=(_10*_4)|k[pos++%l];
-}
-return (((_11>>16)^(_10>>16))<<16)|(((_11&65535)^(_10&65535))&65535);
-}),s0:_7.s0.slice(0),s1:_7.s1.slice(0),s2:_7.s2.slice(0),s3:_7.s3.slice(0)};
-for(i=0,l=box.p.length;i<l;){
-eb(res,box);
-box.p[i++]=res.left,box.p[i++]=res.right;
-}
-for(i=0;i<4;i++){
-for(j=0,l=box["s"+i].length;j<l;){
-eb(res,box);
-box["s"+i][j++]=res.left,box["s"+i][j++]=res.right;
-}
-}
-return box;
-};
-this.getIV=function(_12){
-var out=_12||dojox.encoding.crypto.outputTypes.Base64;
-switch(out){
-case dojox.encoding.crypto.outputTypes.Hex:
-return dojo.map(iv,function(_13){
-return (_13<=15?"0":"")+_13.toString(16);
-}).join("");
-case dojox.encoding.crypto.outputTypes.String:
-return iv.join("");
-case dojox.encoding.crypto.outputTypes.Raw:
-return iv;
-default:
-return dojox.encoding.base64.encode(iv);
-}
-};
-this.setIV=function(_14,_15){
-var ip=_15||dojox.encoding.crypto.outputTypes.Base64;
-var ba=null;
-switch(ip){
-case dojox.encoding.crypto.outputTypes.String:
-ba=dojo.map(_14.split(""),function(_16){
-return _16.charCodeAt(0);
-});
-break;
-case dojox.encoding.crypto.outputTypes.Hex:
-ba=[];
-for(var i=0,l=_14.length-1;i<l;i+=2){
-ba.push(parseInt(_14.substr(i,2),16));
-}
-break;
-case dojox.encoding.crypto.outputTypes.Raw:
-ba=_14;
-break;
-default:
-ba=dojox.encoding.base64.decode(_14);
-break;
-}
-iv={};
-iv.left=ba[0]*_6|ba[1]*_5|ba[2]*_4|ba[3];
-iv.right=ba[4]*_6|ba[5]*_5|ba[6]*_4|ba[7];
-};
-this.encrypt=function(_17,key,ao){
-var out=dojox.encoding.crypto.outputTypes.Base64;
-var _18=dojox.encoding.crypto.cipherModes.ECB;
-if(ao){
-if(ao.outputType){
-out=ao.outputType;
-}
-if(ao.cipherMode){
-_18=ao.cipherMode;
-}
-}
-var bx=_d(key),_19=8-(_17.length&7);
-for(var i=0;i<_19;i++){
-_17+=String.fromCharCode(_19);
-}
-var _1a=[],_1b=_17.length>>3,pos=0,o={},_1c=(_18==dojox.encoding.crypto.cipherModes.CBC);
-var _1d={left:iv.left||null,right:iv.right||null};
-for(var i=0;i<_1b;i++){
-o.left=_17.charCodeAt(pos)*_6|_17.charCodeAt(pos+1)*_5|_17.charCodeAt(pos+2)*_4|_17.charCodeAt(pos+3);
-o.right=_17.charCodeAt(pos+4)*_6|_17.charCodeAt(pos+5)*_5|_17.charCodeAt(pos+6)*_4|_17.charCodeAt(pos+7);
-if(_1c){
-o.left=(((o.left>>16)^(_1d.left>>16))<<16)|(((o.left&65535)^(_1d.left&65535))&65535);
-o.right=(((o.right>>16)^(_1d.right>>16))<<16)|(((o.right&65535)^(_1d.right&65535))&65535);
-}
-eb(o,bx);
-if(_1c){
-_1d.left=o.left;
-_1d.right=o.right;
-}
-_1a.push((o.left>>24)&255);
-_1a.push((o.left>>16)&255);
-_1a.push((o.left>>8)&255);
-_1a.push(o.left&255);
-_1a.push((o.right>>24)&255);
-_1a.push((o.right>>16)&255);
-_1a.push((o.right>>8)&255);
-_1a.push(o.right&255);
-pos+=8;
-}
-switch(out){
-case dojox.encoding.crypto.outputTypes.Hex:
-return dojo.map(_1a,function(_1e){
-return (_1e<=15?"0":"")+_1e.toString(16);
-}).join("");
-case dojox.encoding.crypto.outputTypes.String:
-return _1a.join("");
-case dojox.encoding.crypto.outputTypes.Raw:
-return _1a;
-default:
-return dojox.encoding.base64.encode(_1a);
-}
-};
-this.decrypt=function(_1f,key,ao){
-var ip=dojox.encoding.crypto.outputTypes.Base64;
-var _20=dojox.encoding.crypto.cipherModes.ECB;
-if(ao){
-if(ao.outputType){
-ip=ao.outputType;
-}
-if(ao.cipherMode){
-_20=ao.cipherMode;
-}
-}
-var bx=_d(key);
-var pt=[];
-var c=null;
-switch(ip){
-case dojox.encoding.crypto.outputTypes.Hex:
-c=[];
-for(var i=0,l=_1f.length-1;i<l;i+=2){
-c.push(parseInt(_1f.substr(i,2),16));
-}
-break;
-case dojox.encoding.crypto.outputTypes.String:
-c=dojo.map(_1f.split(""),function(_21){
-return _21.charCodeAt(0);
-});
-break;
-case dojox.encoding.crypto.outputTypes.Raw:
-c=_1f;
-break;
-default:
-c=dojox.encoding.base64.decode(_1f);
-break;
-}
-var _22=c.length>>3,pos=0,o={},_23=(_20==dojox.encoding.crypto.cipherModes.CBC);
-var _24={left:iv.left||null,right:iv.right||null};
-for(var i=0;i<_22;i++){
-o.left=c[pos]*_6|c[pos+1]*_5|c[pos+2]*_4|c[pos+3];
-o.right=c[pos+4]*_6|c[pos+5]*_5|c[pos+6]*_4|c[pos+7];
-if(_23){
-var _25=o.left;
-var _26=o.right;
-}
-db(o,bx);
-if(_23){
-o.left=(((o.left>>16)^(_24.left>>16))<<16)|(((o.left&65535)^(_24.left&65535))&65535);
-o.right=(((o.right>>16)^(_24.right>>16))<<16)|(((o.right&65535)^(_24.right&65535))&65535);
-_24.left=_25;
-_24.right=_26;
-}
-pt.push((o.left>>24)&255);
-pt.push((o.left>>16)&255);
-pt.push((o.left>>8)&255);
-pt.push(o.left&255);
-pt.push((o.right>>24)&255);
-pt.push((o.right>>16)&255);
-pt.push((o.right>>8)&255);
-pt.push(o.right&255);
-pos+=8;
-}
-if(pt[pt.length-1]==pt[pt.length-2]||pt[pt.length-1]==1){
-var n=pt[pt.length-1];
-pt.splice(pt.length-n,n);
-}
-return dojo.map(pt,function(_27){
-return String.fromCharCode(_27);
-}).join("");
-};
-this.setIV("0000000000000000",dojox.encoding.crypto.outputTypes.Hex);
+
+/*	Blowfish
+ *	Created based on the C# implementation by Marcus Hahn (http://www.hotpixel.net/)
+ *	Unsigned math based on Paul Johnstone and Peter Wood patches.
+ *	2005-12-08
+ */
+dojox.encoding.crypto.Blowfish = new function(){
+	//	summary
+	//	Object for doing Blowfish encryption/decryption.
+	var POW2=Math.pow(2,2);
+	var POW3=Math.pow(2,3);
+	var POW4=Math.pow(2,4);
+	var POW8=Math.pow(2,8);
+	var POW16=Math.pow(2,16);
+	var POW24=Math.pow(2,24);
+	var iv=null;	//	CBC mode initialization vector
+	var boxes={
+		p:[
+			0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 
+			0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 
+			0x9216d5d9, 0x8979fb1b
+		],
+		s0:[
+			0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+			0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+			0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+			0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+			0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+			0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+			0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+			0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+			0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+			0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+			0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 
+			0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 
+			0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 
+			0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+			0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+			0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+			0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 
+			0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 
+			0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 
+			0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 
+			0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+			0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 
+			0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+			0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 
+			0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+			0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+			0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+			0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+			0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+			0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+			0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+			0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
+		],
+		s1:[
+			0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+			0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+			0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+			0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+			0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+			0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+			0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+			0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 
+			0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 
+			0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+			0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 
+			0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+			0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 
+			0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 
+			0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+			0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 
+			0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+			0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 
+			0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+			0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 
+			0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 
+			0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 
+			0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+			0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+			0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 
+			0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+			0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+			0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+			0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+			0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+			0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+			0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
+		],
+		s2:[
+			0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+			0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+			0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+			0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+			0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+			0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+			0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+			0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+			0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+			0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+			0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+			0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+			0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+			0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+			0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+			0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+			0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+			0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+			0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+			0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+			0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 
+			0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+			0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+			0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 
+			0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 
+			0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 
+			0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 
+			0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+			0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+			0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 
+			0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+			0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
+		],
+		s3:[
+			0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+			0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+			0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 
+			0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+			0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 
+			0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 
+			0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+			0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 
+			0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 
+			0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 
+			0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+			0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 
+			0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 
+			0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 
+			0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+			0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+			0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 
+			0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+			0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 
+			0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 
+			0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 
+			0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 
+			0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+			0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 
+			0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+			0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 
+			0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 
+			0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 
+			0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 
+			0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+			0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+			0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
+		]
+	}
+////////////////////////////////////////////////////////////////////////////
+//	fixes based on patch submitted by Peter Wood (#5791)
+	function add(x,y){
+		return (((x>>0x10)+(y>>0x10)+(((x&0xffff)+(y&0xffff))>>0x10))<<0x10)|(((x&0xffff)+(y&0xffff))&0xffff);
+	}
+	function xor(x,y){
+		return (((x>>0x10)^(y>>0x10))<<0x10)|(((x&0xffff)^(y&0xffff))&0xffff);
+	}
+
+	function $(v, box){
+		var d=box.s3[v&0xff]; v>>=8;
+		var c=box.s2[v&0xff]; v>>=8;
+		var b=box.s1[v&0xff]; v>>=8;
+		var a=box.s0[v&0xff];
+
+		var r = (((a>>0x10)+(b>>0x10)+(((a&0xffff)+(b&0xffff))>>0x10))<<0x10)|(((a&0xffff)+(b&0xffff))&0xffff);
+		r = (((r>>0x10)^(c>>0x10))<<0x10)|(((r&0xffff)^(c&0xffff))&0xffff);
+		return (((r>>0x10)+(d>>0x10)+(((r&0xffff)+(d&0xffff))>>0x10))<<0x10)|(((r&0xffff)+(d&0xffff))&0xffff);
+	}
+////////////////////////////////////////////////////////////////////////////
+	function eb(o, box){
+		//	TODO: see if this can't be made more efficient
+		var l=o.left;
+		var r=o.right;
+		l=xor(l,box.p[0]);
+		r=xor(r,xor($(l,box),box.p[1]));
+		l=xor(l,xor($(r,box),box.p[2]));
+		r=xor(r,xor($(l,box),box.p[3]));
+		l=xor(l,xor($(r,box),box.p[4]));
+		r=xor(r,xor($(l,box),box.p[5]));
+		l=xor(l,xor($(r,box),box.p[6]));
+		r=xor(r,xor($(l,box),box.p[7]));
+		l=xor(l,xor($(r,box),box.p[8]));
+		r=xor(r,xor($(l,box),box.p[9]));
+		l=xor(l,xor($(r,box),box.p[10]));
+		r=xor(r,xor($(l,box),box.p[11]));
+		l=xor(l,xor($(r,box),box.p[12]));
+		r=xor(r,xor($(l,box),box.p[13]));
+		l=xor(l,xor($(r,box),box.p[14]));
+		r=xor(r,xor($(l,box),box.p[15]));
+		l=xor(l,xor($(r,box),box.p[16]));
+		o.right=l;
+		o.left=xor(r,box.p[17]);
+	}
+
+	function db(o, box){
+		var l=o.left;
+		var r=o.right;
+		l=xor(l,box.p[17]);
+		r=xor(r,xor($(l,box),box.p[16]));
+		l=xor(l,xor($(r,box),box.p[15]));
+		r=xor(r,xor($(l,box),box.p[14]));
+		l=xor(l,xor($(r,box),box.p[13]));
+		r=xor(r,xor($(l,box),box.p[12]));
+		l=xor(l,xor($(r,box),box.p[11]));
+		r=xor(r,xor($(l,box),box.p[10]));
+		l=xor(l,xor($(r,box),box.p[9]));
+		r=xor(r,xor($(l,box),box.p[8]));
+		l=xor(l,xor($(r,box),box.p[7]));
+		r=xor(r,xor($(l,box),box.p[6]));
+		l=xor(l,xor($(r,box),box.p[5]));
+		r=xor(r,xor($(l,box),box.p[4]));
+		l=xor(l,xor($(r,box),box.p[3]));
+		r=xor(r,xor($(l,box),box.p[2]));
+		l=xor(l,xor($(r,box),box.p[1]));
+		o.right=l;
+		o.left=xor(r,box.p[0]);
+	}
+
+	//	Note that we aren't caching contexts here; it might take a little longer
+	//	but we should be more secure this way.
+	function init(key){
+		var k=key;
+		if(dojo.isString(k)){
+			k = dojo.map(k.split(""), function(item){
+				return item.charCodeAt(0) & 0xff;
+			});
+		}
+
+		//	init the boxes
+		var pos=0, data=0, res={ left:0, right:0 }, i, j, l;
+		var box = { 
+			p: dojo.map(boxes.p.slice(0), function(item){
+				var l=k.length, j;
+				for(j=0; j<4; j++){ data=(data*POW8)|k[pos++ % l]; }
+				return (((item>>0x10)^(data>>0x10))<<0x10)|(((item&0xffff)^(data&0xffff))&0xffff);
+			}),
+			s0:boxes.s0.slice(0), 
+			s1:boxes.s1.slice(0), 
+			s2:boxes.s2.slice(0), 
+			s3:boxes.s3.slice(0) 
+		};
+
+		//	encrypt p and the s boxes
+		for(i=0, l=box.p.length; i<l;){
+			eb(res, box);
+			box.p[i++]=res.left, box.p[i++]=res.right;
+		}
+		for(i=0; i<4; i++){
+			for(j=0, l=box["s"+i].length; j<l;){
+				eb(res, box);
+				box["s"+i][j++]=res.left, box["s"+i][j++]=res.right;
+			}
+		}
+		return box;
+	}
+
+////////////////////////////////////////////////////////////////////////////
+//	PUBLIC FUNCTIONS
+////////////////////////////////////////////////////////////////////////////
+	this.getIV=function(/* dojox.encoding.crypto.outputTypes? */ outputType){
+		//	summary
+		//	returns the initialization vector in the output format specified by outputType
+		var out=outputType||dojox.encoding.crypto.outputTypes.Base64;
+		switch(out){
+			case dojox.encoding.crypto.outputTypes.Hex:{
+				return dojo.map(iv, function(item){
+					return (item<=0xf?'0':'')+item.toString(16);
+				}).join("");			//	string
+			}
+			case dojox.encoding.crypto.outputTypes.String:{
+				return iv.join("");		//	string
+			}
+			case dojox.encoding.crypto.outputTypes.Raw:{
+				return iv;				//	array
+			}
+			default:{
+				return dojox.encoding.base64.encode(iv); 	//	 string
+			}
+		}
+	};
+
+	this.setIV=function(/* string */data, /* dojox.encoding.crypto.outputTypes? */inputType){
+		//	summary
+		//	sets the initialization vector to data (as interpreted as inputType)
+		var ip=inputType||dojox.encoding.crypto.outputTypes.Base64;
+		var ba=null;
+		switch(ip){
+			case dojox.encoding.crypto.outputTypes.String:{
+				ba = dojo.map(data.split(""), function(item){
+					return item.charCodeAt(0);
+				});
+				break;
+			}
+			case dojox.encoding.crypto.outputTypes.Hex:{
+				ba=[];
+				for(var i=0, l=data.length-1; i<l; i+=2){
+					ba.push(parseInt(data.substr(i,2), 16));
+				}
+				break;
+			}
+			case dojox.encoding.crypto.outputTypes.Raw:{
+				ba=data;
+				break;
+			}
+			default:{
+				ba=dojox.encoding.base64.decode(data);
+				break;
+			}
+		}
+		//	make it a pair of words now
+		iv={};
+		iv.left=ba[0]*POW24|ba[1]*POW16|ba[2]*POW8|ba[3];
+		iv.right=ba[4]*POW24|ba[5]*POW16|ba[6]*POW8|ba[7];
+	};
+
+	this.encrypt = function(/* string */plaintext, /* string */key, /* object? */ao){
+		//	summary
+		//	encrypts plaintext using key; allows user to specify output type and cipher mode via keyword object "ao"
+		var out=dojox.encoding.crypto.outputTypes.Base64;
+		var mode=dojox.encoding.crypto.cipherModes.ECB;
+		if (ao){
+			if (ao.outputType) out=ao.outputType;
+			if (ao.cipherMode) mode=ao.cipherMode;
+		}
+
+		var bx = init(key), padding = 8-(plaintext.length&7);
+		for (var i=0; i<padding; i++){ plaintext+=String.fromCharCode(padding); }
+
+		var cipher=[], count=plaintext.length >> 3, pos=0, o={}, isCBC=(mode==dojox.encoding.crypto.cipherModes.CBC);
+		var vector={left:iv.left||null, right:iv.right||null};
+		for(var i=0; i<count; i++){
+			o.left=plaintext.charCodeAt(pos)*POW24
+				|plaintext.charCodeAt(pos+1)*POW16
+				|plaintext.charCodeAt(pos+2)*POW8
+				|plaintext.charCodeAt(pos+3);
+			o.right=plaintext.charCodeAt(pos+4)*POW24
+				|plaintext.charCodeAt(pos+5)*POW16
+				|plaintext.charCodeAt(pos+6)*POW8
+				|plaintext.charCodeAt(pos+7);
+
+			if(isCBC){
+				o.left=(((o.left>>0x10)^(vector.left>>0x10))<<0x10)|(((o.left&0xffff)^(vector.left&0xffff))&0xffff);
+				o.right=(((o.right>>0x10)^(vector.right>>0x10))<<0x10)|(((o.right&0xffff)^(vector.right&0xffff))&0xffff);
+			}
+
+			eb(o, bx);	//	encrypt the block
+
+			if(isCBC){
+				vector.left=o.left;
+				vector.right=o.right;
+			}
+
+			cipher.push((o.left>>24)&0xff); 
+			cipher.push((o.left>>16)&0xff); 
+			cipher.push((o.left>>8)&0xff);
+			cipher.push(o.left&0xff);
+			cipher.push((o.right>>24)&0xff); 
+			cipher.push((o.right>>16)&0xff); 
+			cipher.push((o.right>>8)&0xff);
+			cipher.push(o.right&0xff);
+			pos+=8;
+		}
+
+		switch(out){
+			case dojox.encoding.crypto.outputTypes.Hex:{
+				return dojo.map(cipher, function(item){
+					return (item<=0xf?'0':'')+item.toString(16);
+				}).join("");	//	string
+			}
+			case dojox.encoding.crypto.outputTypes.String:{
+				return cipher.join("");	//	string
+			}
+			case dojox.encoding.crypto.outputTypes.Raw:{
+				return cipher;	//	array
+			}
+			default:{
+				return dojox.encoding.base64.encode(cipher);	//	string
+			}
+		}
+	};
+
+	this.decrypt = function(/* string */ciphertext, /* string */key, /* object? */ao){
+		//	summary
+		//	decrypts ciphertext using key; allows specification of how ciphertext is encoded via ao.
+		var ip=dojox.encoding.crypto.outputTypes.Base64;
+		var mode=dojox.encoding.crypto.cipherModes.ECB;
+		if (ao){
+			if (ao.outputType) ip=ao.outputType;
+			if (ao.cipherMode) mode=ao.cipherMode;
+		}
+		var bx = init(key);
+		var pt=[];
+	
+		var c=null;
+		switch(ip){
+			case dojox.encoding.crypto.outputTypes.Hex:{
+				c = [];
+				for(var i=0, l=ciphertext.length-1; i<l; i+=2){
+					c.push(parseInt(ciphertext.substr(i,2), 16));
+				}
+				break;
+			}
+			case dojox.encoding.crypto.outputTypes.String:{
+				c = dojo.map(ciphertext.split(""), function(item){
+					return item.charCodeAt(0);
+				});
+				break;
+			}
+			case dojox.encoding.crypto.outputTypes.Raw:{
+				c=ciphertext;	//	should be a byte array
+				break;
+			}
+			default:{
+				c=dojox.encoding.base64.decode(ciphertext);
+				break;
+			}
+		}
+
+		var count=c.length >> 3, pos=0, o={}, isCBC=(mode==dojox.encoding.crypto.cipherModes.CBC);
+		var vector={left:iv.left||null, right:iv.right||null};
+		for(var i=0; i<count; i++){
+			o.left=c[pos]*POW24|c[pos+1]*POW16|c[pos+2]*POW8|c[pos+3];
+			o.right=c[pos+4]*POW24|c[pos+5]*POW16|c[pos+6]*POW8|c[pos+7];
+
+			if(isCBC){
+				var left=o.left;
+				var right=o.right;
+			}
+
+			db(o, bx);	//	decrypt the block
+
+			if(isCBC){
+				o.left=(((o.left>>0x10)^(vector.left>>0x10))<<0x10)|(((o.left&0xffff)^(vector.left&0xffff))&0xffff);
+				o.right=(((o.right>>0x10)^(vector.right>>0x10))<<0x10)|(((o.right&0xffff)^(vector.right&0xffff))&0xffff);
+				vector.left=left;
+				vector.right=right;
+			}
+
+			pt.push((o.left>>24)&0xff);
+			pt.push((o.left>>16)&0xff);
+			pt.push((o.left>>8)&0xff);
+			pt.push(o.left&0xff);
+			pt.push((o.right>>24)&0xff);
+			pt.push((o.right>>16)&0xff);
+			pt.push((o.right>>8)&0xff);
+			pt.push(o.right&0xff);
+			pos+=8;
+		}
+
+		//	check for padding, and remove.
+		if(pt[pt.length-1]==pt[pt.length-2]||pt[pt.length-1]==0x01){
+			var n=pt[pt.length-1];
+			pt.splice(pt.length-n, n);
+		}
+
+		//	convert to string
+		return dojo.map(pt, function(item){
+			return String.fromCharCode(item);
+		}).join("");	//	string
+	};
+
+	this.setIV("0000000000000000", dojox.encoding.crypto.outputTypes.Hex);
 }();
-}
diff --git a/dojox/encoding/crypto/RSAKey-ext.js b/dojox/encoding/crypto/RSAKey-ext.js
index cf24cd9..f7b85b5 100644
--- a/dojox/encoding/crypto/RSAKey-ext.js
+++ b/dojox/encoding/crypto/RSAKey-ext.js
@@ -1,107 +1,120 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.crypto.RSAKey-ext"]){
-dojo._hasResource["dojox.encoding.crypto.RSAKey-ext"]=true;
 dojo.provide("dojox.encoding.crypto.RSAKey-ext");
 dojo.experimental("dojox.encoding.crypto.RSAKey-ext");
+
 dojo.require("dojox.encoding.crypto.RSAKey");
 dojo.require("dojox.math.BigInteger-ext");
+
 (function(){
-var _1=dojox.math.BigInteger;
-function _2(d,n){
-var b=d.toByteArray();
-for(var i=0,_3=b.length;i<_3&&!b[i];++i){
-}
-if(b.length-i!==n-1||b[i]!==2){
-return null;
-}
-for(++i;b[i];){
-if(++i>=_3){
-return null;
-}
-}
-var _4="";
-while(++i<_3){
-_4+=String.fromCharCode(b[i]);
-}
-return _4;
-};
-dojo.extend(dojox.encoding.crypto.RSAKey,{setPrivate:function(N,E,D){
-if(N&&E&&N.length&&E.length){
-this.n=new _1(N,16);
-this.e=parseInt(E,16);
-this.d=new _1(D,16);
-}else{
-throw new Error("Invalid RSA private key");
-}
-},setPrivateEx:function(N,E,D,P,Q,DP,DQ,C){
-if(N&&E&&N.length&&E.length){
-this.n=new _1(N,16);
-this.e=parseInt(E,16);
-this.d=new _1(D,16);
-this.p=new _1(P,16);
-this.q=new _1(Q,16);
-this.dmp1=new _1(DP,16);
-this.dmq1=new _1(DQ,16);
-this.coeff=new _1(C,16);
-}else{
-throw new Error("Invalid RSA private key");
-}
-},generate:function(B,E){
-var _5=this.rngf(),qs=B>>1;
-this.e=parseInt(E,16);
-var ee=new _1(E,16);
-for(;;){
-for(;;){
-this.p=new _1(B-qs,1,_5);
-if(!this.p.subtract(_1.ONE).gcd(ee).compareTo(_1.ONE)&&this.p.isProbablePrime(10)){
-break;
-}
-}
-for(;;){
-this.q=new _1(qs,1,_5);
-if(!this.q.subtract(_1.ONE).gcd(ee).compareTo(_1.ONE)&&this.q.isProbablePrime(10)){
-break;
-}
-}
-if(this.p.compareTo(this.q)<=0){
-var t=this.p;
-this.p=this.q;
-this.q=t;
-}
-var p1=this.p.subtract(_1.ONE);
-var q1=this.q.subtract(_1.ONE);
-var _6=p1.multiply(q1);
-if(!_6.gcd(ee).compareTo(_1.ONE)){
-this.n=this.p.multiply(this.q);
-this.d=ee.modInverse(_6);
-this.dmp1=this.d.mod(p1);
-this.dmq1=this.d.mod(q1);
-this.coeff=this.q.modInverse(this.p);
-break;
-}
-}
-_5.destroy();
-},decrypt:function(_7){
-var c=new _1(_7,16),m;
-if(!this.p||!this.q){
-m=c.modPow(this.d,this.n);
-}else{
-var cp=c.mod(this.p).modPow(this.dmp1,this.p),cq=c.mod(this.q).modPow(this.dmq1,this.q);
-while(cp.compareTo(cq)<0){
-cp=cp.add(this.p);
-}
-m=cp.subtract(cq).multiply(this.coeff).mod(this.p).multiply(this.q).add(cq);
-}
-if(!m){
-return null;
-}
-return _2(m,(this.n.bitLength()+7)>>3);
-}});
+	var BigInteger = dojox.math.BigInteger;
+
+	// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
+	function pkcs1unpad2(d, n){
+		var b = d.toByteArray();
+		for(var i = 0, len = b.length; i < len && !b[i]; ++i);
+		if(b.length - i !== n - 1 || b[i] !== 2){
+			return null;
+		}
+		for(++i; b[i];){
+			if(++i >= len){
+				return null;
+			}
+		}
+		var ret = "";
+		while(++i < len){
+			ret += String.fromCharCode(b[i]);
+		}
+		return ret;
+	}
+
+	dojo.extend(dojox.encoding.crypto.RSAKey, {
+		setPrivate: function(N, E, D){
+			// summary:
+			//	Set the private key fields N, e, d and CRT params from hex strings
+			if(N && E && N.length && E.length){
+				this.n = new BigInteger(N, 16);
+				this.e = parseInt(E, 16);
+				this.d = new BigInteger(D, 16);
+			}else{
+				throw new Error("Invalid RSA private key");
+			}
+		},
+		setPrivateEx: function(N, E, D, P, Q, DP, DQ, C) {
+			// summary:
+			//	Set the private key fields N, e, d and CRT params from hex strings
+			if(N && E && N.length && E.length){
+				this.n = new BigInteger(N, 16);
+				this.e = parseInt(E, 16);
+				this.d = new BigInteger(D, 16);
+				this.p = new BigInteger(P, 16);
+				this.q = new BigInteger(Q, 16);
+				this.dmp1 = new BigInteger(DP, 16);
+				this.dmq1 = new BigInteger(DQ, 16);
+				this.coeff = new BigInteger(C, 16);
+			}else{
+				throw new Error("Invalid RSA private key");
+			}
+		},
+		generate: function(B, E){
+			// summary:
+			//	Generate a new random private key B bits long, using public expt E
+			var rng = this.rngf(), qs = B >> 1;
+			this.e = parseInt(E, 16);
+			var ee = new BigInteger(E, 16);
+			for(;;) {
+				for(;;) {
+					this.p = new BigInteger(B - qs, 1, rng);
+					if(!this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) && this.p.isProbablePrime(10)){
+						break;
+					}
+				}
+				for(;;) {
+					this.q = new BigInteger(qs, 1, rng);
+					if(!this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) && this.q.isProbablePrime(10)){
+						break;
+					}
+				}
+				if(this.p.compareTo(this.q) <= 0) {
+					var t = this.p;
+					this.p = this.q;
+					this.q = t;
+				}
+				var p1 = this.p.subtract(BigInteger.ONE);
+				var q1 = this.q.subtract(BigInteger.ONE);
+				var phi = p1.multiply(q1);
+				if(!phi.gcd(ee).compareTo(BigInteger.ONE)) {
+					this.n = this.p.multiply(this.q);
+					this.d = ee.modInverse(phi);
+					this.dmp1 = this.d.mod(p1);
+					this.dmq1 = this.d.mod(q1);
+					this.coeff = this.q.modInverse(this.p);
+					break;
+				}
+			}
+			rng.destroy();
+		},
+
+		decrypt: function(ctext){
+			// summary:
+			//	Return the PKCS#1 RSA decryption of "ctext".
+			// ctext: String:
+			//	an even-length hex string
+			// returns: a plain string.
+			var c = new BigInteger(ctext, 16), m;
+			if(!this.p || !this.q){
+				m = c.modPow(this.d, this.n);
+			}else{
+				// TODO: re-calculate any missing CRT params
+				var cp = c.mod(this.p).modPow(this.dmp1, this.p),
+					cq = c.mod(this.q).modPow(this.dmq1, this.q);
+				while(cp.compareTo(cq) < 0){
+					cp = cp.add(this.p);
+				}
+				m = cp.subtract(cq).multiply(this.coeff).mod(this.p).multiply(this.q).add(cq);
+			}
+			if(!m){
+				return null;
+			}
+			return pkcs1unpad2(m, (this.n.bitLength() + 7) >> 3);
+		}
+	});
 })();
-}
diff --git a/dojox/encoding/crypto/RSAKey.js b/dojox/encoding/crypto/RSAKey.js
index 8c37351..04d7042 100644
--- a/dojox/encoding/crypto/RSAKey.js
+++ b/dojox/encoding/crypto/RSAKey.js
@@ -1,66 +1,73 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.crypto.RSAKey"]){
-dojo._hasResource["dojox.encoding.crypto.RSAKey"]=true;
 dojo.provide("dojox.encoding.crypto.RSAKey");
 dojo.experimental("dojox.encoding.crypto.RSAKey");
+
 dojo.require("dojox.math.BigInteger");
 dojo.require("dojox.math.random.Simple");
+
+// Copyright (c) 2005  Tom Wu
+// All Rights Reserved.
+// See "LICENSE-BigInteger" in dojox.math for details.
+
 (function(){
-var dm=dojox.math,_1=dm.BigInteger,_2=dm.random.Simple,_3=function(){
-return new _2();
-};
-function _4(s,n,_5){
-if(n<s.length+11){
-throw new Error("Message too long for RSA");
-}
-var ba=new Array(n);
-var i=s.length;
-while(i&&n){
-ba[--n]=s.charCodeAt(--i);
-}
-ba[--n]=0;
-var _6=_5();
-var x=[0];
-while(n>2){
-x[0]=0;
-while(x[0]==0){
-_6.nextBytes(x);
-}
-ba[--n]=x[0];
-}
-ba[--n]=2;
-ba[--n]=0;
-_6.destroy();
-return new _1(ba);
-};
-dojo.declare("dojox.encoding.crypto.RSAKey",null,{constructor:function(_7){
-this.rngf=_7||_3;
-this.e=0;
-this.n=this.d=this.p=this.q=this.dmp1=this.dmq1=this.coeff=null;
-},setPublic:function(N,E){
-if(N&&E&&N.length&&E.length){
-this.n=new _1(N,16);
-this.e=parseInt(E,16);
-}else{
-throw new Error("Invalid RSA public key");
-}
-},encrypt:function(_8){
-var m=_4(_8,(this.n.bitLength()+7)>>3,this.rngf);
-if(!m){
-return null;
-}
-var c=m.modPowInt(this.e,this.n);
-if(!c){
-return null;
-}
-var h=c.toString(16);
-return h.length%2?"0"+h:h;
-}});
+	var dm = dojox.math, BigInteger = dm.BigInteger, Simple = dm.random.Simple,
+		defaultRngf = function(){ return new Simple(); };
+
+	// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
+	function pkcs1pad2(s, n, rngf) {
+		if(n < s.length + 11) {
+			throw new Error("Message too long for RSA");
+		}
+		var ba = new Array(n);
+		var i = s.length;
+		while(i && n) ba[--n] = s.charCodeAt(--i);
+		ba[--n] = 0;
+		var rng = rngf();
+		var x = [0];
+		while(n > 2) { // random non-zero pad
+			x[0] = 0;
+			while(x[0] == 0) rng.nextBytes(x);
+			ba[--n] = x[0];
+		}
+		ba[--n] = 2;
+		ba[--n] = 0;
+		rng.destroy();
+		return new BigInteger(ba);
+	}
+
+	dojo.declare("dojox.encoding.crypto.RSAKey", null, {
+		constructor: function(rngf){
+			// summary:
+			//	"empty" RSA key constructor
+			// rndf: Function?:
+			//	function that returns an instance of a random number generator
+			//	(see dojox.math.random for details)
+			this.rngf = rngf || defaultRngf;
+			this.e = 0;
+			this.n = this.d = this.p = this.q = this.dmp1 = this.dmq1 = this.coeff = null;
+		},
+
+		setPublic: function(N, E){
+			// summary:
+			//	Set the public key fields N and e from hex strings
+			if(N && E && N.length && E.length) {
+				this.n = new BigInteger(N, 16);
+				this.e = parseInt(E, 16);
+			}else{
+				throw new Error("Invalid RSA public key");
+			}
+		},
+
+		encrypt: function(text){
+			var m = pkcs1pad2(text, (this.n.bitLength() + 7) >> 3, this.rngf);
+			if(!m){
+				return null;
+			}
+			var c = m.modPowInt(this.e, this.n);
+			if(!c){
+				return null;
+			}
+			var h = c.toString(16);
+			return h.length % 2 ? "0" + h : h;
+		}
+	});
 })();
-}
diff --git a/dojox/encoding/crypto/SimpleAES.js b/dojox/encoding/crypto/SimpleAES.js
index 5b8c16b..adb8bbe 100644
--- a/dojox/encoding/crypto/SimpleAES.js
+++ b/dojox/encoding/crypto/SimpleAES.js
@@ -1,236 +1,335 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.crypto.SimpleAES"]){
-dojo._hasResource["dojox.encoding.crypto.SimpleAES"]=true;
 dojo.provide("dojox.encoding.crypto.SimpleAES");
+
 dojo.require("dojox.encoding.base64");
 dojo.require("dojox.encoding.crypto._base");
+
 (function(){
-var _1=[99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,95,151,68,23, [...]
-var _2=[[0,0,0,0],[1,0,0,0],[2,0,0,0],[4,0,0,0],[8,0,0,0],[16,0,0,0],[32,0,0,0],[64,0,0,0],[128,0,0,0],[27,0,0,0],[54,0,0,0]];
-function _3(_4,w){
-var Nb=4;
-var Nr=w.length/Nb-1;
-var _5=[[],[],[],[]];
-for(var i=0;i<4*Nb;i++){
-_5[i%4][Math.floor(i/4)]=_4[i];
-}
-_5=_6(_5,w,0,Nb);
-for(var _7=1;_7<Nr;_7++){
-_5=_8(_5,Nb);
-_5=_9(_5,Nb);
-_5=_a(_5,Nb);
-_5=_6(_5,w,_7,Nb);
-}
-_5=_8(_5,Nb);
-_5=_9(_5,Nb);
-_5=_6(_5,w,Nr,Nb);
-var _b=new Array(4*Nb);
-for(var i=0;i<4*Nb;i++){
-_b[i]=_5[i%4][Math.floor(i/4)];
-}
-return _b;
-};
-function _8(s,Nb){
-for(var r=0;r<4;r++){
-for(var c=0;c<Nb;c++){
-s[r][c]=_1[s[r][c]];
-}
-}
-return s;
-};
-function _9(s,Nb){
-var t=new Array(4);
-for(var r=1;r<4;r++){
-for(var c=0;c<4;c++){
-t[c]=s[r][(c+r)%Nb];
-}
-for(var c=0;c<4;c++){
-s[r][c]=t[c];
-}
-}
-return s;
-};
-function _a(s,Nb){
-for(var c=0;c<4;c++){
-var a=new Array(4);
-var b=new Array(4);
-for(var i=0;i<4;i++){
-a[i]=s[i][c];
-b[i]=s[i][c]&128?s[i][c]<<1^283:s[i][c]<<1;
-}
-s[0][c]=b[0]^a[1]^b[1]^a[2]^a[3];
-s[1][c]=a[0]^b[1]^a[2]^b[2]^a[3];
-s[2][c]=a[0]^a[1]^b[2]^a[3]^b[3];
-s[3][c]=a[0]^b[0]^a[1]^a[2]^b[3];
-}
-return s;
-};
-function _6(_c,w,_d,Nb){
-for(var r=0;r<4;r++){
-for(var c=0;c<Nb;c++){
-_c[r][c]^=w[_d*4+c][r];
-}
-}
-return _c;
-};
-function _e(_f){
-var Nb=4;
-var Nk=_f.length/4;
-var Nr=Nk+6;
-var w=new Array(Nb*(Nr+1));
-var _10=new Array(4);
-for(var i=0;i<Nk;i++){
-var r=[_f[4*i],_f[4*i+1],_f[4*i+2],_f[4*i+3]];
-w[i]=r;
-}
-for(var i=Nk;i<(Nb*(Nr+1));i++){
-w[i]=new Array(4);
-for(var t=0;t<4;t++){
-_10[t]=w[i-1][t];
-}
-if(i%Nk==0){
-_10=_11(_12(_10));
-for(var t=0;t<4;t++){
-_10[t]^=_2[i/Nk][t];
-}
-}else{
-if(Nk>6&&i%Nk==4){
-_10=_11(_10);
-}
-}
-for(var t=0;t<4;t++){
-w[i][t]=w[i-Nk][t]^_10[t];
-}
-}
-return w;
-};
-function _11(w){
-for(var i=0;i<4;i++){
-w[i]=_1[w[i]];
-}
-return w;
-};
-function _12(w){
-w[4]=w[0];
-for(var i=0;i<4;i++){
-w[i]=w[i+1];
-}
-return w;
-};
-function _13(_14,_15,_16){
-if(!(_16==128||_16==192||_16==256)){
-return "";
-}
-var _17=_16/8;
-var _18=new Array(_17);
-for(var i=0;i<_17;i++){
-_18[i]=_15.charCodeAt(i)&255;
-}
-var key=_3(_18,_e(_18));
-key=key.concat(key.slice(0,_17-16));
-var _19=16;
-var _1a=new Array(_19);
-var _1b=(new Date()).getTime();
-for(var i=0;i<4;i++){
-_1a[i]=(_1b>>>i*8)&255;
-}
-for(var i=0;i<4;i++){
-_1a[i+4]=(_1b/4294967296>>>i*8)&255;
-}
-var _1c=_e(key);
-var _1d=Math.ceil(_14.length/_19);
-var _1e=new Array(_1d);
-for(var b=0;b<_1d;b++){
-for(var c=0;c<4;c++){
-_1a[15-c]=(b>>>c*8)&255;
-}
-for(var c=0;c<4;c++){
-_1a[15-c-4]=(b/4294967296>>>c*8);
-}
-var _1f=_3(_1a,_1c);
-var _20=b<_1d-1?_19:(_14.length-1)%_19+1;
-var ct="";
-for(var i=0;i<_20;i++){
-var _21=_14.charCodeAt(b*_19+i);
-var _22=_21^_1f[i];
-ct+=((_22<16)?"0":"")+_22.toString(16);
-}
-_1e[b]=ct;
-}
-var _23="";
-for(var i=0;i<8;i++){
-_23+=((_1a[i]<16)?"0":"")+_1a[i].toString(16);
-}
-return _23+" "+_1e.join(" ");
-};
-function _24(s){
-var ret=[];
-s.replace(/(..)/g,function(str){
-ret.push(parseInt(str,16));
-});
-return ret;
-};
-function _25(_26,_27,_28){
-if(!(_28==128||_28==192||_28==256)){
-return "";
-}
-var _29=_28/8;
-var _2a=new Array(_29);
-for(var i=0;i<_29;i++){
-_2a[i]=_27.charCodeAt(i)&255;
-}
-var _2b=_e(_2a);
-var key=_3(_2a,_2b);
-key=key.concat(key.slice(0,_29-16));
-var _2c=_e(key);
-_26=_26.split(" ");
-var _2d=16;
-var _2e=new Array(_2d);
-var _2f=_26[0];
-_2e=_24(_2f);
-var _30=new Array(_26.length-1);
-for(var b=1;b<_26.length;b++){
-for(var c=0;c<4;c++){
-_2e[15-c]=((b-1)>>>c*8)&255;
-}
-for(var c=0;c<4;c++){
-_2e[15-c-4]=((b/4294967296-1)>>>c*8)&255;
-}
-var _31=_3(_2e,_2c);
-var pt="";
-var tmp=_24(_26[b]);
-for(var i=0;i<tmp.length;i++){
-var _32=_26[b].charCodeAt(i);
-var _33=tmp[i]^_31[i];
-pt+=String.fromCharCode(_33);
-}
-_30[b-1]=pt;
-}
-return _30.join("");
-};
-function _34(str){
-return str.replace(/[\0\t\n\v\f\r\xa0!-]/g,function(c){
-return "!"+c.charCodeAt(0)+"!";
-});
-};
-function _35(str){
-return str.replace(/!\d\d?\d?!/g,function(c){
-return String.fromCharCode(c.slice(1,-1));
-});
-};
-dojox.encoding.crypto.SimpleAES=new (function(){
-this.encrypt=function(_36,key){
-return _13(_36,key,256);
-};
-this.decrypt=function(_37,key){
-return _25(_37,key,256);
-};
-})();
+		// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [§5.1.1]
+		var Sbox =	[0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
+					 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
+					 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
+					 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
+					 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
+					 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
+					 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
+					 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
+					 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
+					 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
+					 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
+					 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
+					 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
+					 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
+					 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
+					 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16];
+
+		// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2]
+		var Rcon = [ [0x00, 0x00, 0x00, 0x00],
+					 [0x01, 0x00, 0x00, 0x00],
+					 [0x02, 0x00, 0x00, 0x00],
+					 [0x04, 0x00, 0x00, 0x00],
+					 [0x08, 0x00, 0x00, 0x00],
+					 [0x10, 0x00, 0x00, 0x00],
+					 [0x20, 0x00, 0x00, 0x00],
+					 [0x40, 0x00, 0x00, 0x00],
+					 [0x80, 0x00, 0x00, 0x00],
+					 [0x1b, 0x00, 0x00, 0x00],
+					 [0x36, 0x00, 0x00, 0x00] ]; 
+
+		/*
+		 * AES Cipher function: encrypt 'input' with Rijndael algorithm
+		 *
+		 *	 takes	 byte-array 'input' (16 bytes)
+		 *			 2D byte-array key schedule 'w' (Nr+1 x Nb bytes)
+		 *
+		 *	 applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage
+		 *
+		 *	 returns byte-array encrypted value (16 bytes)
+		 */
+		function Cipher(input, w) {	   // main Cipher function [§5.1]
+		  var Nb = 4;				// block size (in words): no of columns in state (fixed at 4 for AES)
+		  var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
+
+		  var state = [[],[],[],[]];  // initialise 4xNb byte-array 'state' with input [§3.4]
+		  for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i];
+
+		  state = AddRoundKey(state, w, 0, Nb);
+
+		  for (var round=1; round<Nr; round++) {
+			state = SubBytes(state, Nb);
+			state = ShiftRows(state, Nb);
+			state = MixColumns(state, Nb);
+			state = AddRoundKey(state, w, round, Nb);
+		  }
+
+		  state = SubBytes(state, Nb);
+		  state = ShiftRows(state, Nb);
+		  state = AddRoundKey(state, w, Nr, Nb);
+
+		  var output = new Array(4*Nb);	 // convert state to 1-d array before returning [§3.4]
+		  for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)];
+		  return output;
+		}
+
+
+		function SubBytes(s, Nb) {	  // apply SBox to state S [§5.1.1]
+		  for (var r=0; r<4; r++) {
+			for (var c=0; c<Nb; c++) s[r][c] = Sbox[s[r][c]];
+		  }
+		  return s;
+		}
+
+
+		function ShiftRows(s, Nb) {	   // shift row r of state S left by r bytes [§5.1.2]
+		  var t = new Array(4);
+		  for (var r=1; r<4; r++) {
+			for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb];	// shift into temp copy
+			for (var c=0; c<4; c++) s[r][c] = t[c];			// and copy back
+		  }			 // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
+		  return s;	 // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf 
+		}
+
+
+		function MixColumns(s, Nb) {   // combine bytes of each col of state S [§5.1.3]
+		  for (var c=0; c<4; c++) {
+			var a = new Array(4);  // 'a' is a copy of the current column from 's'
+			var b = new Array(4);  // 'b' is a•{02} in GF(2^8)
+			for (var i=0; i<4; i++) {
+			  a[i] = s[i][c];
+			  b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1;
+			}
+			// a[n] ^ b[n] is a•{03} in GF(2^8)
+			s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3
+			s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3
+			s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3
+			s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3
+		  }
+		  return s;
+		}
+
+
+		function AddRoundKey(state, w, rnd, Nb) {  // xor Round Key into state S [§5.1.4]
+		  for (var r=0; r<4; r++) {
+			for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r];
+		  }
+		  return state;
+		}
+
+
+		function KeyExpansion(key) {  // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2]
+		  var Nb = 4;			 // block size (in words): no of columns in state (fixed at 4 for AES)
+		  var Nk = key.length/4	 // key length (in words): 4/6/8 for 128/192/256-bit keys
+		  var Nr = Nk + 6;		 // no of rounds: 10/12/14 for 128/192/256-bit keys
+
+		  var w = new Array(Nb*(Nr+1));
+		  var temp = new Array(4);
+
+		  for (var i=0; i<Nk; i++) {
+			var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];
+			w[i] = r;
+		  }
+
+		  for (var i=Nk; i<(Nb*(Nr+1)); i++) {
+			w[i] = new Array(4);
+			for (var t=0; t<4; t++) temp[t] = w[i-1][t];
+			if (i % Nk == 0) {
+			  temp = SubWord(RotWord(temp));
+			  for (var t=0; t<4; t++) temp[t] ^= Rcon[i/Nk][t];
+			} else if (Nk > 6 && i%Nk == 4) {
+			  temp = SubWord(temp);
+			}
+			for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t];
+		  }
+
+		  return w;
+		}
+
+		function SubWord(w) {	 // apply SBox to 4-byte word w
+		  for (var i=0; i<4; i++) w[i] = Sbox[w[i]];
+		  return w;
+		}
+
+		function RotWord(w) {	 // rotate 4-byte word w left by one byte
+		  w[4] = w[0];
+		  for (var i=0; i<4; i++) w[i] = w[i+1];
+		  return w;
+		}
+
+		/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+		/* 
+		 * Use AES to encrypt 'plaintext' with 'password' using 'nBits' key, in 'Counter' mode of operation
+		 *							 - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+		 *	 for each block
+		 *	 - outputblock = cipher(counter, key)
+		 *	 - cipherblock = plaintext xor outputblock
+		 */
+		function AESEncryptCtr(plaintext, password, nBits) {
+		  if (!(nBits==128 || nBits==192 || nBits==256)) return '';	 // standard allows 128/192/256 bit keys
+
+		  // for this example script, generate the key by applying Cipher to 1st 16/24/32 chars of password; 
+		  // for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1
+		  var nBytes = nBits/8;	 // no bytes in key
+		  var pwBytes = new Array(nBytes);
+		  for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
+
+		  var key = Cipher(pwBytes, KeyExpansion(pwBytes));
+
+		  key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
+
+		  // initialise counter block (NIST SP800-38A §B.2): millisecond time-stamp for nonce in 1st 8 bytes,
+		  // block counter in 2nd 8 bytes
+		  var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
+		  var counterBlock = new Array(blockSize);	// block size fixed at 16 bytes / 128 bits (Nb=4) for AES
+		  var nonce = (new Date()).getTime();  // milliseconds since 1-Jan-1970
+
+		  // encode nonce in two stages to cater for JavaScript 32-bit limit on bitwise ops
+		  for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff;
+		  for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff; 
+
+		  // generate key schedule - an expansion of the key into distinct Key Rounds for each round
+		  var keySchedule = KeyExpansion(key);
+
+		  var blockCount = Math.ceil(plaintext.length/blockSize);
+		  var ciphertext = new Array(blockCount);  // ciphertext as array of strings
+ 
+		  for (var b=0; b<blockCount; b++) {
+			// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
+			// again done in two stages for 32-bit ops
+			for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;
+			for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8)
+
+			var cipherCntr = Cipher(counterBlock, keySchedule);	 // -- encrypt counter block --
+
+			// calculate length of final block:
+			var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1;
+
+			var ct = '';
+			for (var i=0; i<blockLength; i++) {	 // -- xor plaintext with ciphered counter byte-by-byte --
+			  var plaintextByte = plaintext.charCodeAt(b*blockSize+i);
+			  var cipherByte = plaintextByte ^ cipherCntr[i];
+			  //ct += String.fromCharCode(cipherByte);
+			  ct += ((cipherByte < 16) ? "0" : "") + cipherByte.toString(16);
+			}
+			// ct is now ciphertext for this block
+
+			ciphertext[b] = ct; // escCtrlChars(ct);  // escape troublesome characters in ciphertext
+		  }
+
+		  // convert the nonce to a string to go on the front of the ciphertext
+		  var ctrTxt = '';
+		  for (var i=0; i<8; i++) ctrTxt += ((counterBlock[i] < 16) ? "0" : "") + counterBlock[i].toString(16); //String.fromCharCode(counterBlock[i]);
+		  //ctrTxt = escCtrlChars(ctrTxt);
+
+		  // use '-' to separate blocks, use Array.join to concatenate arrays of strings for efficiency
+		  return ctrTxt + ' ' + ciphertext.join(' ');
+		}
+
+		function stringToHex(s){
+			var ret = [];
+			s.replace(/(..)/g, function(str){
+				ret.push(parseInt(str, 16));
+			});
+			return ret;
+		}
+
+		/* 
+		 * Use AES to decrypt 'ciphertext' with 'password' using 'nBits' key, in Counter mode of operation
+		 *
+		 *	 for each block
+		 *	 - outputblock = cipher(counter, key)
+		 *	 - cipherblock = plaintext xor outputblock
+		 */
+		function AESDecryptCtr(ciphertext, password, nBits) {
+		  if (!(nBits==128 || nBits==192 || nBits==256)) return '';	 // standard allows 128/192/256 bit keys
+
+		  var nBytes = nBits/8;	 // no bytes in key
+		  var pwBytes = new Array(nBytes);
+		  for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
+		  var pwKeySchedule = KeyExpansion(pwBytes);
+		  var key = Cipher(pwBytes, pwKeySchedule);
+		  key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
+
+		  var keySchedule = KeyExpansion(key);
+
+		  ciphertext = ciphertext.split(' ');  // split ciphertext into array of block-length strings 
+
+		  // recover nonce from 1st element of ciphertext
+		  var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
+		  var counterBlock = new Array(blockSize);
+		  var ctrTxt = ciphertext[0]; //unescCtrlChars(ciphertext[0]);
+		  counterBlock = stringToHex(ctrTxt);
+
+		  var plaintext = new Array(ciphertext.length-1);
+
+		  for (var b=1; b<ciphertext.length; b++) {
+			// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
+			for (var c=0; c<4; c++) counterBlock[15-c] = ((b-1) >>> c*8) & 0xff;
+			for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff;
+
+			var cipherCntr = Cipher(counterBlock, keySchedule);	 // encrypt counter block
+
+			//ciphertext[b] = ciphertext[b]; //unescCtrlChars(ciphertext[b]);
+
+			var pt = '';
+			var tmp = stringToHex(ciphertext[b]);
+			for (var i=0; i<tmp.length; i++) {
+			  // -- xor plaintext with ciphered counter byte-by-byte --
+			  var ciphertextByte = ciphertext[b].charCodeAt(i);
+			  var plaintextByte = tmp[i] ^ cipherCntr[i];
+			  pt += String.fromCharCode(plaintextByte);
+			}
+			// pt is now plaintext for this block
+
+			plaintext[b-1] = pt;  // b-1 'cos no initial nonce block in plaintext
+		  }
+
+		  return plaintext.join('');
+		}
+
+		/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+		function escCtrlChars(str) {  // escape control chars which might cause problems handling ciphertext
+		  return str.replace(/[\0\t\n\v\f\r\xa0!-]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });
+		}  // \xa0 to cater for bug in Firefox; include '-' to leave it free for use as a block marker
+
+		function unescCtrlChars(str) {	// unescape potentially problematic control characters
+		  return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });
+		}
+
+		/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+	dojox.encoding.crypto.SimpleAES = new (function(){
+		// summary:
+		// 		SimpleAES, ported from dojox.sql, and done without the need for
+		// 		a Google Gears worker pool.
+		// description: 
+		//		Taken from http://www.movable-type.co.uk/scripts/aes.html by
+		// 		Chris Veness (CLA signed); adapted for Dojo by Brad Neuberg
+		// 		(bkn3 AT columbia.edu) and moved to DojoX crypto by Tom Trenka
+		// 		(ttrenka AT gmail.com).
+		//
+		// 		A few notes:
+		// 		1) This algorithm uses a customized version of CBC mode by creating
+		// 		a nonce, using it as an initialization vector, and storing the 
+		// 		IV as the first portion of the encrypted text.  Because of this, it
+		// 		is HIGHLY PROBABLE that it will NOT be usable by other AES implementations.
+		// 		2) All encoding is done in hex format; other encoding formats (such
+		// 		as base 64) are not supported.
+		// 		3) The bit depth of the key is hardcoded at 256, despite the ability
+		// 		of the code to handle all three recommended bit depths.
+		// 		4) The passed key will be padded (as opposed to enforcing a strict
+		// 		length) with null bytes.
+		this.encrypt = function(/* String */plaintext, /* String */key){
+			//	summary:
+			//		Encrypt the passed plaintext using the key, with a 
+			//		hardcoded bit depth of 256.
+			return AESEncryptCtr(plaintext, key, 256);	//	String
+		};
+		this.decrypt = function(/* String */ciphertext, /* String */key){
+			//	summary:
+			//		Decrypt the passed ciphertext using the key at a fixed
+			//		bit depth of 256.
+			return AESDecryptCtr(ciphertext, key, 256);	//	String
+		};
+	})();	
 })();
-}
diff --git a/dojox/encoding/crypto/_base.js b/dojox/encoding/crypto/_base.js
index 94f62c0..c599b01 100644
--- a/dojox/encoding/crypto/_base.js
+++ b/dojox/encoding/crypto/_base.js
@@ -1,16 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.crypto._base"]){
-dojo._hasResource["dojox.encoding.crypto._base"]=true;
 dojo.provide("dojox.encoding.crypto._base");
+
 (function(){
-var c=dojox.encoding.crypto;
-c.cipherModes={ECB:0,CBC:1,PCBC:2,CFB:3,OFB:4,CTR:5};
-c.outputTypes={Base64:0,Hex:1,String:2,Raw:3};
+	var c=dojox.encoding.crypto;
+	c.cipherModes={
+		//	summary
+		//	Enumeration for various cipher modes.
+		ECB:0, CBC:1, PCBC:2, CFB:3, OFB:4, CTR:5 
+	};
+	c.outputTypes={ 
+		//	summary
+		//	Enumeration for input and output encodings.
+		Base64:0, Hex:1, String:2, Raw:3 
+	};
 })();
-}
diff --git a/dojox/encoding/digests/MD5.js b/dojox/encoding/digests/MD5.js
index b28f979..f061e91 100644
--- a/dojox/encoding/digests/MD5.js
+++ b/dojox/encoding/digests/MD5.js
@@ -1,158 +1,173 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.digests.MD5"]){
-dojo._hasResource["dojox.encoding.digests.MD5"]=true;
 dojo.provide("dojox.encoding.digests.MD5");
+
 dojo.require("dojox.encoding.digests._base");
+
+/*	A port of Paul Johnstone's MD5 implementation
+ *	http://pajhome.org.uk/crypt/md5/index.html
+ *
+ *	Copyright (C) Paul Johnston 1999 - 2002.
+ *	Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * 	Distributed under the BSD License
+ *
+ *	Dojo port by Tom Trenka
+ */
 (function(){
-var _1=dojox.encoding.digests;
-var _2=8;
-function R(n,c){
-return (n<<c)|(n>>>(32-c));
-};
-function C(q,a,b,x,s,t){
-return _1.addWords(R(_1.addWords(_1.addWords(a,q),_1.addWords(x,t)),s),b);
-};
-function FF(a,b,c,d,x,s,t){
-return C((b&c)|((~b)&d),a,b,x,s,t);
-};
-function GG(a,b,c,d,x,s,t){
-return C((b&d)|(c&(~d)),a,b,x,s,t);
-};
-function HH(a,b,c,d,x,s,t){
-return C(b^c^d,a,b,x,s,t);
-};
-function II(a,b,c,d,x,s,t){
-return C(c^(b|(~d)),a,b,x,s,t);
-};
-function _3(x,_4){
-x[_4>>5]|=128<<((_4)%32);
-x[(((_4+64)>>>9)<<4)+14]=_4;
-var a=1732584193;
-var b=-271733879;
-var c=-1732584194;
-var d=271733878;
-for(var i=0;i<x.length;i+=16){
-var _5=a;
-var _6=b;
-var _7=c;
-var _8=d;
-a=FF(a,b,c,d,x[i+0],7,-680876936);
-d=FF(d,a,b,c,x[i+1],12,-389564586);
-c=FF(c,d,a,b,x[i+2],17,606105819);
-b=FF(b,c,d,a,x[i+3],22,-1044525330);
-a=FF(a,b,c,d,x[i+4],7,-176418897);
-d=FF(d,a,b,c,x[i+5],12,1200080426);
-c=FF(c,d,a,b,x[i+6],17,-1473231341);
-b=FF(b,c,d,a,x[i+7],22,-45705983);
-a=FF(a,b,c,d,x[i+8],7,1770035416);
-d=FF(d,a,b,c,x[i+9],12,-1958414417);
-c=FF(c,d,a,b,x[i+10],17,-42063);
-b=FF(b,c,d,a,x[i+11],22,-1990404162);
-a=FF(a,b,c,d,x[i+12],7,1804603682);
-d=FF(d,a,b,c,x[i+13],12,-40341101);
-c=FF(c,d,a,b,x[i+14],17,-1502002290);
-b=FF(b,c,d,a,x[i+15],22,1236535329);
-a=GG(a,b,c,d,x[i+1],5,-165796510);
-d=GG(d,a,b,c,x[i+6],9,-1069501632);
-c=GG(c,d,a,b,x[i+11],14,643717713);
-b=GG(b,c,d,a,x[i+0],20,-373897302);
-a=GG(a,b,c,d,x[i+5],5,-701558691);
-d=GG(d,a,b,c,x[i+10],9,38016083);
-c=GG(c,d,a,b,x[i+15],14,-660478335);
-b=GG(b,c,d,a,x[i+4],20,-405537848);
-a=GG(a,b,c,d,x[i+9],5,568446438);
-d=GG(d,a,b,c,x[i+14],9,-1019803690);
-c=GG(c,d,a,b,x[i+3],14,-187363961);
-b=GG(b,c,d,a,x[i+8],20,1163531501);
-a=GG(a,b,c,d,x[i+13],5,-1444681467);
-d=GG(d,a,b,c,x[i+2],9,-51403784);
-c=GG(c,d,a,b,x[i+7],14,1735328473);
-b=GG(b,c,d,a,x[i+12],20,-1926607734);
-a=HH(a,b,c,d,x[i+5],4,-378558);
-d=HH(d,a,b,c,x[i+8],11,-2022574463);
-c=HH(c,d,a,b,x[i+11],16,1839030562);
-b=HH(b,c,d,a,x[i+14],23,-35309556);
-a=HH(a,b,c,d,x[i+1],4,-1530992060);
-d=HH(d,a,b,c,x[i+4],11,1272893353);
-c=HH(c,d,a,b,x[i+7],16,-155497632);
-b=HH(b,c,d,a,x[i+10],23,-1094730640);
-a=HH(a,b,c,d,x[i+13],4,681279174);
-d=HH(d,a,b,c,x[i+0],11,-358537222);
-c=HH(c,d,a,b,x[i+3],16,-722521979);
-b=HH(b,c,d,a,x[i+6],23,76029189);
-a=HH(a,b,c,d,x[i+9],4,-640364487);
-d=HH(d,a,b,c,x[i+12],11,-421815835);
-c=HH(c,d,a,b,x[i+15],16,530742520);
-b=HH(b,c,d,a,x[i+2],23,-995338651);
-a=II(a,b,c,d,x[i+0],6,-198630844);
-d=II(d,a,b,c,x[i+7],10,1126891415);
-c=II(c,d,a,b,x[i+14],15,-1416354905);
-b=II(b,c,d,a,x[i+5],21,-57434055);
-a=II(a,b,c,d,x[i+12],6,1700485571);
-d=II(d,a,b,c,x[i+3],10,-1894986606);
-c=II(c,d,a,b,x[i+10],15,-1051523);
-b=II(b,c,d,a,x[i+1],21,-2054922799);
-a=II(a,b,c,d,x[i+8],6,1873313359);
-d=II(d,a,b,c,x[i+15],10,-30611744);
-c=II(c,d,a,b,x[i+6],15,-1560198380);
-b=II(b,c,d,a,x[i+13],21,1309151649);
-a=II(a,b,c,d,x[i+4],6,-145523070);
-d=II(d,a,b,c,x[i+11],10,-1120210379);
-c=II(c,d,a,b,x[i+2],15,718787259);
-b=II(b,c,d,a,x[i+9],21,-343485551);
-a=_1.addWords(a,_5);
-b=_1.addWords(b,_6);
-c=_1.addWords(c,_7);
-d=_1.addWords(d,_8);
-}
-return [a,b,c,d];
-};
-function _9(_a,_b){
-var wa=_1.stringToWord(_b);
-if(wa.length>16){
-wa=_3(wa,_b.length*_2);
-}
-var l=[],r=[];
-for(var i=0;i<16;i++){
-l[i]=wa[i]^909522486;
-r[i]=wa[i]^1549556828;
-}
-var h=_3(l.concat(_1.stringToWord(_a)),512+_a.length*_2);
-return _3(r.concat(h),640);
-};
-_1.MD5=function(_c,_d){
-var _e=_d||_1.outputTypes.Base64;
-var wa=_3(_1.stringToWord(_c),_c.length*_2);
-switch(_e){
-case _1.outputTypes.Raw:
-return wa;
-case _1.outputTypes.Hex:
-return _1.wordToHex(wa);
-case _1.outputTypes.String:
-return _1.wordToString(wa);
-default:
-return _1.wordToBase64(wa);
-}
-};
-_1.MD5._hmac=function(_f,key,_10){
-var out=_10||_1.outputTypes.Base64;
-var wa=_9(_f,key);
-switch(out){
-case _1.outputTypes.Raw:
-return wa;
-case _1.outputTypes.Hex:
-return _1.wordToHex(wa);
-case _1.outputTypes.String:
-return _1.wordToString(wa);
-default:
-return _1.wordToBase64(wa);
-}
-};
+	var dxd=dojox.encoding.digests;
+	var chrsz=8;
+
+	//	MD5 rounds functions
+	function R(n,c){ return (n<<c)|(n>>>(32-c)); }
+	function C(q,a,b,x,s,t){ return dxd.addWords(R(dxd.addWords(dxd.addWords(a, q), dxd.addWords(x, t)), s), b); }
+	function FF(a,b,c,d,x,s,t){ return C((b&c)|((~b)&d),a,b,x,s,t); }
+	function GG(a,b,c,d,x,s,t){ return C((b&d)|(c&(~d)),a,b,x,s,t); }
+	function HH(a,b,c,d,x,s,t){ return C(b^c^d,a,b,x,s,t); }
+	function II(a,b,c,d,x,s,t){ return C(c^(b|(~d)),a,b,x,s,t); }
+
+	//	the core MD5 rounds method
+	function core(x,len){
+		x[len>>5]|=0x80<<((len)%32);
+		x[(((len+64)>>>9)<<4)+14]=len;
+		var a= 1732584193;
+		var b=-271733879;
+		var c=-1732584194;
+		var d= 271733878;
+		for(var i=0; i<x.length; i+=16){
+			var olda=a;
+			var oldb=b;
+			var oldc=c;
+			var oldd=d;
+
+			a=FF(a,b,c,d,x[i+ 0],7 ,-680876936);
+			d=FF(d,a,b,c,x[i+ 1],12,-389564586);
+			c=FF(c,d,a,b,x[i+ 2],17, 606105819);
+			b=FF(b,c,d,a,x[i+ 3],22,-1044525330);
+			a=FF(a,b,c,d,x[i+ 4],7 ,-176418897);
+			d=FF(d,a,b,c,x[i+ 5],12, 1200080426);
+			c=FF(c,d,a,b,x[i+ 6],17,-1473231341);
+			b=FF(b,c,d,a,x[i+ 7],22,-45705983);
+			a=FF(a,b,c,d,x[i+ 8],7 , 1770035416);
+			d=FF(d,a,b,c,x[i+ 9],12,-1958414417);
+			c=FF(c,d,a,b,x[i+10],17,-42063);
+			b=FF(b,c,d,a,x[i+11],22,-1990404162);
+			a=FF(a,b,c,d,x[i+12],7 , 1804603682);
+			d=FF(d,a,b,c,x[i+13],12,-40341101);
+			c=FF(c,d,a,b,x[i+14],17,-1502002290);
+			b=FF(b,c,d,a,x[i+15],22, 1236535329);
+
+			a=GG(a,b,c,d,x[i+ 1],5 ,-165796510);
+			d=GG(d,a,b,c,x[i+ 6],9 ,-1069501632);
+			c=GG(c,d,a,b,x[i+11],14, 643717713);
+			b=GG(b,c,d,a,x[i+ 0],20,-373897302);
+			a=GG(a,b,c,d,x[i+ 5],5 ,-701558691);
+			d=GG(d,a,b,c,x[i+10],9 , 38016083);
+			c=GG(c,d,a,b,x[i+15],14,-660478335);
+			b=GG(b,c,d,a,x[i+ 4],20,-405537848);
+			a=GG(a,b,c,d,x[i+ 9],5 , 568446438);
+			d=GG(d,a,b,c,x[i+14],9 ,-1019803690);
+			c=GG(c,d,a,b,x[i+ 3],14,-187363961);
+			b=GG(b,c,d,a,x[i+ 8],20, 1163531501);
+			a=GG(a,b,c,d,x[i+13],5 ,-1444681467);
+			d=GG(d,a,b,c,x[i+ 2],9 ,-51403784);
+			c=GG(c,d,a,b,x[i+ 7],14, 1735328473);
+			b=GG(b,c,d,a,x[i+12],20,-1926607734);
+
+			a=HH(a,b,c,d,x[i+ 5],4 ,-378558);
+			d=HH(d,a,b,c,x[i+ 8],11,-2022574463);
+			c=HH(c,d,a,b,x[i+11],16, 1839030562);
+			b=HH(b,c,d,a,x[i+14],23,-35309556);
+			a=HH(a,b,c,d,x[i+ 1],4 ,-1530992060);
+			d=HH(d,a,b,c,x[i+ 4],11, 1272893353);
+			c=HH(c,d,a,b,x[i+ 7],16,-155497632);
+			b=HH(b,c,d,a,x[i+10],23,-1094730640);
+			a=HH(a,b,c,d,x[i+13],4 , 681279174);
+			d=HH(d,a,b,c,x[i+ 0],11,-358537222);
+			c=HH(c,d,a,b,x[i+ 3],16,-722521979);
+			b=HH(b,c,d,a,x[i+ 6],23, 76029189);
+			a=HH(a,b,c,d,x[i+ 9],4 ,-640364487);
+			d=HH(d,a,b,c,x[i+12],11,-421815835);
+			c=HH(c,d,a,b,x[i+15],16, 530742520);
+			b=HH(b,c,d,a,x[i+ 2],23,-995338651);
+
+			a=II(a,b,c,d,x[i+ 0],6 ,-198630844);
+			d=II(d,a,b,c,x[i+ 7],10, 1126891415);
+			c=II(c,d,a,b,x[i+14],15,-1416354905);
+			b=II(b,c,d,a,x[i+ 5],21,-57434055);
+			a=II(a,b,c,d,x[i+12],6 , 1700485571);
+			d=II(d,a,b,c,x[i+ 3],10,-1894986606);
+			c=II(c,d,a,b,x[i+10],15,-1051523);
+			b=II(b,c,d,a,x[i+ 1],21,-2054922799);
+			a=II(a,b,c,d,x[i+ 8],6 , 1873313359);
+			d=II(d,a,b,c,x[i+15],10,-30611744);
+			c=II(c,d,a,b,x[i+ 6],15,-1560198380);
+			b=II(b,c,d,a,x[i+13],21, 1309151649);
+			a=II(a,b,c,d,x[i+ 4],6 ,-145523070);
+			d=II(d,a,b,c,x[i+11],10,-1120210379);
+			c=II(c,d,a,b,x[i+ 2],15, 718787259);
+			b=II(b,c,d,a,x[i+ 9],21,-343485551);
+
+			a=dxd.addWords(a, olda);
+			b=dxd.addWords(b, oldb);
+			c=dxd.addWords(c, oldc);
+			d=dxd.addWords(d, oldd);
+		}
+		return [a,b,c,d];
+	}
+
+	function hmac(data, key){
+		var wa=dxd.stringToWord(key);
+		if(wa.length>16){ 
+			wa=core(wa, key.length*chrsz);
+		}
+		var l=[], r=[];
+		for(var i=0; i<16; i++){
+			l[i]=wa[i]^0x36363636;
+			r[i]=wa[i]^0x5c5c5c5c;
+		}
+		var h=core(l.concat(dxd.stringToWord(data)), 512+data.length*chrsz);
+		return core(r.concat(h), 640);
+	}
+
+	//	public function
+	dxd.MD5=function(/* string */data, /* dojox.encoding.digests.outputTypes? */outputType){
+		//	summary
+		//	computes the digest of data, and returns the result according to type outputType
+		var out=outputType || dxd.outputTypes.Base64;
+		var wa=core(dxd.stringToWord(data), data.length*chrsz);
+		switch(out){
+			case dxd.outputTypes.Raw:{
+				return wa;	//	word[]
+			}
+			case dxd.outputTypes.Hex:{
+				return dxd.wordToHex(wa);	//	string
+			}
+			case dxd.outputTypes.String:{
+				return dxd.wordToString(wa);	//	string
+			}
+			default:{
+				return dxd.wordToBase64(wa);	//	string
+			}
+		}
+	};
+
+	//	make this private, for later use with a generic HMAC calculator.
+	dxd.MD5._hmac=function(/* string */data, /* string */key, /* dojox.encoding.digests.outputTypes? */outputType){
+		//	summary
+		//	computes the digest of data, and returns the result according to type outputType
+		var out=outputType || dxd.outputTypes.Base64;
+		var wa=hmac(data, key);
+		switch(out){
+			case dxd.outputTypes.Raw:{
+				return wa;	//	word[]
+			}
+			case dxd.outputTypes.Hex:{
+				return dxd.wordToHex(wa);	//	string
+			}
+			case dxd.outputTypes.String:{
+				return dxd.wordToString(wa);	//	string
+			}
+			default:{
+				return dxd.wordToBase64(wa);	//	string
+			}
+		}
+	};
 })();
-}
diff --git a/dojox/encoding/digests/SHA1.js b/dojox/encoding/digests/SHA1.js
index aec8483..6909218 100644
--- a/dojox/encoding/digests/SHA1.js
+++ b/dojox/encoding/digests/SHA1.js
@@ -1,137 +1,150 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.digests.SHA1"]){
-dojo._hasResource["dojox.encoding.digests.SHA1"]=true;
 dojo.provide("dojox.encoding.digests.SHA1");
 dojo.require("dojox.encoding.digests._base");
+
+/*
+ * A port of Paul Johnstone's SHA1 implementation
+ *
+ * Version 2.1a Copyright Paul Johnston 2000 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ *
+ * Dojo port by Tom Trenka
+ */
 (function(){
-var _1=dojox.encoding.digests;
-var _2=8,_3=(1<<_2)-1;
-function R(n,c){
-return (n<<c)|(n>>>(32-c));
-};
-function 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;
-};
-function KT(t){
-return (t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;
-};
-function _4(x,_5){
-x[_5>>5]|=128<<(24-_5%32);
-x[((_5+64>>9)<<4)+15]=_5;
-var w=new Array(80),a=1732584193,b=-271733879,c=-1732584194,d=271733878,e=-1009589776;
-for(var i=0;i<x.length;i+=16){
-var _6=a,_7=b,_8=c,_9=d,_a=e;
-for(var j=0;j<80;j++){
-if(j<16){
-w[j]=x[i+j];
-}else{
-w[j]=R(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);
-}
-var t=_1.addWords(_1.addWords(R(a,5),FT(j,b,c,d)),_1.addWords(_1.addWords(e,w[j]),KT(j)));
-e=d;
-d=c;
-c=R(b,30);
-b=a;
-a=t;
-}
-a=_1.addWords(a,_6);
-b=_1.addWords(b,_7);
-c=_1.addWords(c,_8);
-d=_1.addWords(d,_9);
-e=_1.addWords(e,_a);
-}
-return [a,b,c,d,e];
-};
-function _b(_c,_d){
-var wa=_e(_d);
-if(wa.length>16){
-wa=_4(wa,_d.length*_2);
-}
-var _f=new Array(16),_10=new Array(16);
-for(var i=0;i<16;i++){
-_f[i]=wa[i]^909522486;
-_10[i]=wa[i]^1549556828;
-}
-var _11=_4(_f.concat(_e(_c)),512+_c.length*_2);
-return _4(_10.concat(_11),512+160);
-};
-function _e(s){
-var wa=[];
-for(var i=0,l=s.length*_2;i<l;i+=_2){
-wa[i>>5]|=(s.charCodeAt(i/_2)&_3)<<(32-_2-i%32);
-}
-return wa;
-};
-function _12(wa){
-var h="0123456789abcdef",s=[];
-for(var i=0,l=wa.length*4;i<l;i++){
-s.push(h.charAt((wa[i>>2]>>((3-i%4)*8+4))&15),h.charAt((wa[i>>2]>>((3-i%4)*8))&15));
-}
-return s.join("");
-};
-function _13(wa){
-var s=[];
-for(var i=0,l=wa.length*32;i<l;i+=_2){
-s.push(String.fromCharCode((wa[i>>5]>>>(32-_2-i%32))&_3));
-}
-return s.join("");
-};
-function _14(wa){
-var p="=",tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=[];
-for(var i=0,l=wa.length*4;i<l;i+=3){
-var t=(((wa[i>>2]>>8*(3-i%4))&255)<<16)|(((wa[i+1>>2]>>8*(3-(i+1)%4))&255)<<8)|((wa[i+2>>2]>>8*(3-(i+2)%4))&255);
-for(var j=0;j<4;j++){
-if(i*8+j*6>wa.length*32){
-s.push(p);
-}else{
-s.push(tab.charAt((t>>6*(3-j))&63));
-}
-}
-}
-return s.join("");
-};
-_1.SHA1=function(_15,_16){
-var out=_16||_1.outputTypes.Base64;
-var wa=_4(_e(_15),_15.length*_2);
-switch(out){
-case _1.outputTypes.Raw:
-return wa;
-case _1.outputTypes.Hex:
-return _12(wa);
-case _1.outputTypes.String:
-return _13(wa);
-default:
-return _14(wa);
-}
-};
-_1.SHA1._hmac=function(_17,key,_18){
-var out=_18||_1.outputTypes.Base64;
-var wa=_b(_17,key);
-switch(out){
-case _1.outputTypes.Raw:
-return wa;
-case _1.outputTypes.Hex:
-return _12(wa);
-case _1.outputTypes.String:
-return _13(wa);
-default:
-return _14(wa);
-}
-};
+	var dxd=dojox.encoding.digests;
+	var chrsz=8,	//	change to 16 for unicode.
+		mask=(1<<chrsz)-1;
+	
+	function R(n,c){ return (n<<c)|(n>>>(32-c)); }
+	function 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;
+	}
+	function KT(t){ return (t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514; }
+
+	function core(x,len){
+		x[len>>5]|=0x80<<(24-len%32);
+		x[((len+64>>9)<<4)+15]=len;
+
+		var w=new Array(80), a=1732584193, b=-271733879, c=-1732584194, d=271733878, e=-1009589776;
+		for(var i=0; i<x.length; i+=16){
+			var olda=a, oldb=b, oldc=c, oldd=d, olde=e;
+			for(var j=0;j<80;j++){
+				if(j<16){ w[j]=x[i+j]; }
+				else { w[j]=R(w[j-3]^w[j-8]^w[j-14]^w[j-16],1); }
+				var t = dxd.addWords(dxd.addWords(R(a,5),FT(j,b,c,d)),dxd.addWords(dxd.addWords(e,w[j]),KT(j)));
+				e=d; d=c; c=R(b,30); b=a; a=t;
+			}
+			a=dxd.addWords(a,olda);
+			b=dxd.addWords(b,oldb);
+			c=dxd.addWords(c,oldc);
+			d=dxd.addWords(d,oldd);
+			e=dxd.addWords(e,olde);
+		}
+		return [a, b, c, d, e];
+	}
+
+	function hmac(data, key){
+		var wa=toWord(key);
+		if(wa.length>16){ wa=core(wa, key.length*chrsz); }
+
+		var ipad=new Array(16), opad=new Array(16);
+		for(var i=0;i<16;i++){
+			ipad[i]=wa[i]^0x36363636;
+			opad[i]=wa[i]^0x5c5c5c5c;
+		}
+
+		var hash=core(ipad.concat(toWord(data)),512+data.length*chrsz);
+		return core(opad.concat(hash), 512+160);
+	}
+
+	function toWord(s){
+		var wa=[];
+		for(var i=0, l=s.length*chrsz; i<l; i+=chrsz){
+			wa[i>>5]|=(s.charCodeAt(i/chrsz)&mask)<<(32-chrsz-i%32);
+		}
+		return wa;	//	word[]
+	}
+
+	function toHex(wa){
+		//	slightly different than the common one.
+		var h="0123456789abcdef", s=[];
+		for(var i=0, l=wa.length*4; i<l; i++){
+			s.push(h.charAt((wa[i>>2]>>((3-i%4)*8+4))&0xF), h.charAt((wa[i>>2]>>((3-i%4)*8))&0xF));
+		}
+		return s.join("");	//	string
+	}
+
+	function _toString(wa){
+		var s=[];
+		for(var i=0, l=wa.length*32; i<l; i+=chrsz){
+			s.push(String.fromCharCode((wa[i>>5]>>>(32-chrsz-i%32))&mask));
+		}
+		return s.join("");	//	string
+	}
+
+	function toBase64(/* word[] */wa){
+		//	summary:
+		//		convert an array of words to base64 encoding, should be more efficient
+		//		than using dojox.encoding.base64
+		var p="=", tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", s=[];
+		for(var i=0, l=wa.length*4; i<l; i+=3){
+			var t=(((wa[i>>2]>>8*(3-i%4))&0xFF)<<16)|(((wa[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((wa[i+2>>2]>>8*(3-(i+2)%4))&0xFF);
+			for(var j=0; j<4; j++){
+				if(i*8+j*6>wa.length*32){
+					s.push(p);
+				} else {
+					s.push(tab.charAt((t>>6*(3-j))&0x3F));
+				}
+			}
+		}
+		return s.join("");	//	string
+	};
+
+	//	public function
+	dxd.SHA1=function(/* String */data, /* dojox.encoding.digests.outputTypes? */outputType){
+		//	summary:
+		//		Computes the SHA1 digest of the data, and returns the result according to output type.
+		var out=outputType||dxd.outputTypes.Base64;
+		var wa=core(toWord(data), data.length*chrsz);
+		switch(out){
+			case dxd.outputTypes.Raw:{
+				return wa;	//	word[]
+			}
+			case dxd.outputTypes.Hex:{
+				return toHex(wa);	//	string
+			}
+			case dxd.outputTypes.String:{
+				return _toString(wa);	//	string
+			}
+			default:{
+				return toBase64(wa);	//	string
+			}
+		}
+	}
+
+	//	make this private, for later use with a generic HMAC calculator.
+	dxd.SHA1._hmac=function(/* string */data, /* string */key, /* dojox.encoding.digests.outputTypes? */outputType){
+		//	summary:
+		//		computes the digest of data, and returns the result according to type outputType
+		var out=outputType || dxd.outputTypes.Base64;
+		var wa=hmac(data, key);
+		switch(out){
+			case dxd.outputTypes.Raw:{
+				return wa;	//	word[]
+			}
+			case dxd.outputTypes.Hex:{
+				return toHex(wa);	//	string
+			}
+			case dxd.outputTypes.String:{
+				return _toString(wa);	//	string
+			}
+			default:{
+				return toBase64(wa);	//	string
+			}
+		}
+	};
 })();
-}
diff --git a/dojox/encoding/digests/_base.js b/dojox/encoding/digests/_base.js
index 7a379ef..7bc7c75 100644
--- a/dojox/encoding/digests/_base.js
+++ b/dojox/encoding/digests/_base.js
@@ -1,57 +1,74 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.digests._base"]){
-dojo._hasResource["dojox.encoding.digests._base"]=true;
 dojo.provide("dojox.encoding.digests._base");
+
 (function(){
-var d=dojox.encoding.digests;
-d.outputTypes={Base64:0,Hex:1,String:2,Raw:3};
-d.addWords=function(a,b){
-var l=(a&65535)+(b&65535);
-var m=(a>>16)+(b>>16)+(l>>16);
-return (m<<16)|(l&65535);
-};
-var _1=8;
-var _2=(1<<_1)-1;
-d.stringToWord=function(s){
-var wa=[];
-for(var i=0,l=s.length*_1;i<l;i+=_1){
-wa[i>>5]|=(s.charCodeAt(i/_1)&_2)<<(i%32);
-}
-return wa;
-};
-d.wordToString=function(wa){
-var s=[];
-for(var i=0,l=wa.length*32;i<l;i+=_1){
-s.push(String.fromCharCode((wa[i>>5]>>>(i%32))&_2));
-}
-return s.join("");
-};
-d.wordToHex=function(wa){
-var h="0123456789abcdef",s=[];
-for(var i=0,l=wa.length*4;i<l;i++){
-s.push(h.charAt((wa[i>>2]>>((i%4)*8+4))&15)+h.charAt((wa[i>>2]>>((i%4)*8))&15));
-}
-return s.join("");
-};
-d.wordToBase64=function(wa){
-var p="=",_3="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=[];
-for(var i=0,l=wa.length*4;i<l;i+=3){
-var t=(((wa[i>>2]>>8*(i%4))&255)<<16)|(((wa[i+1>>2]>>8*((i+1)%4))&255)<<8)|((wa[i+2>>2]>>8*((i+2)%4))&255);
-for(var j=0;j<4;j++){
-if(i*8+j*6>wa.length*32){
-s.push(p);
-}else{
-s.push(_3.charAt((t>>6*(3-j))&63));
-}
-}
-}
-return s.join("");
-};
+	//TODO: see if it makes sense to meld this into one with the
+	//	crypto base enums
+	var d=dojox.encoding.digests;
+	d.outputTypes={ 
+		//	summary:
+		//		Enumeration for input and output encodings.
+		Base64:0, Hex:1, String:2, Raw:3 
+	};
+
+	//	word-based addition
+	d.addWords=function(/* word */a, /* word */b){
+		//	summary:
+		//		add a pair of words together with rollover
+		var l=(a&0xFFFF)+(b&0xFFFF);
+		var m=(a>>16)+(b>>16)+(l>>16);
+		return (m<<16)|(l&0xFFFF);	//	word
+	};
+
+	//	word-based conversion method, for efficiency sake;
+	//	most digests operate on words, and this should be faster
+	//	than the encoding version (which works on bytes).
+	var chrsz=8;	//	16 for Unicode
+	var mask=(1<<chrsz)-1;
+	
+	d.stringToWord=function(/* string */s){
+		//	summary:
+		//		convert a string to a word array
+		var wa=[];
+		for(var i=0, l=s.length*chrsz; i<l; i+=chrsz){
+			wa[i>>5]|=(s.charCodeAt(i/chrsz)&mask)<<(i%32);
+		}
+		return wa;	//	word[]
+	};
+	
+	d.wordToString=function(/* word[] */wa){
+		//	summary:
+		//		convert an array of words to a string
+		var s=[];
+		for(var i=0, l=wa.length*32; i<l; i+=chrsz){
+			s.push(String.fromCharCode((wa[i>>5]>>>(i%32))&mask));
+		}
+		return s.join("");	//	string
+	}
+	
+	d.wordToHex=function(/* word[] */wa){
+		//	summary:
+		//		convert an array of words to a hex tab
+		var h="0123456789abcdef", s=[];
+		for(var i=0, l=wa.length*4; i<l; i++){
+			s.push(h.charAt((wa[i>>2]>>((i%4)*8+4))&0xF)+h.charAt((wa[i>>2]>>((i%4)*8))&0xF));
+		}
+		return s.join("");	//	string
+	}
+	d.wordToBase64=function(/* word[] */wa){
+		//	summary:
+		//		convert an array of words to base64 encoding, should be more efficient
+		//		than using dojox.encoding.base64
+		var p="=", tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", s=[];
+		for(var i=0, l=wa.length*4; i<l; i+=3){
+			var t=(((wa[i>>2]>>8*(i%4))&0xFF)<<16)|(((wa[i+1>>2]>>8*((i+1)%4))&0xFF)<<8)|((wa[i+2>>2]>>8*((i+2)%4))&0xFF);
+			for(var j=0; j<4; j++){
+				if(i*8+j*6>wa.length*32){
+					s.push(p);
+				} else {
+					s.push(tab.charAt((t>>6*(3-j))&0x3F));
+				}
+			}
+		}
+		return s.join("");	//	string
+	};
 })();
-}
diff --git a/dojox/encoding/easy64.js b/dojox/encoding/easy64.js
index 4d6b271..8f8fd50 100644
--- a/dojox/encoding/easy64.js
+++ b/dojox/encoding/easy64.js
@@ -1,47 +1,46 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.encoding.easy64"]){
-dojo._hasResource["dojox.encoding.easy64"]=true;
 dojo.provide("dojox.encoding.easy64");
+
 (function(){
-var c=function(_1,_2,_3){
-for(var i=0;i<_2;i+=3){
-_3.push(String.fromCharCode((_1[i]>>>2)+33),String.fromCharCode(((_1[i]&3)<<4)+(_1[i+1]>>>4)+33),String.fromCharCode(((_1[i+1]&15)<<2)+(_1[i+2]>>>6)+33),String.fromCharCode((_1[i+2]&63)+33));
-}
-};
-dojox.encoding.easy64.encode=function(_4){
-var _5=[],_6=_4.length%3,_7=_4.length-_6;
-c(_4,_7,_5);
-if(_6){
-var t=_4.slice(_7);
-while(t.length<3){
-t.push(0);
-}
-c(t,3,_5);
-for(var i=3;i>_6;_5.pop(),--i){
-}
-}
-return _5.join("");
-};
-dojox.encoding.easy64.decode=function(_8){
-var n=_8.length,r=[],b=[0,0,0,0],i,j,d;
-for(i=0;i<n;i+=4){
-for(j=0;j<4;++j){
-b[j]=_8.charCodeAt(i+j)-33;
-}
-d=n-i;
-for(j=d;j<4;b[++j]=0){
-}
-r.push((b[0]<<2)+(b[1]>>>4),((b[1]&15)<<4)+(b[2]>>>2),((b[2]&3)<<6)+b[3]);
-for(j=d;j<4;++j,r.pop()){
-}
-}
-return r;
-};
+	var c = function(input, length, result){
+		for(var i = 0; i < length; i += 3){
+			result.push(
+				String.fromCharCode((input[i] >>> 2) + 33),
+				String.fromCharCode(((input[i] & 3) << 4) + (input[i + 1] >>> 4) + 33),
+				String.fromCharCode(((input[i + 1] & 15) << 2) + (input[i + 2] >>> 6) + 33),
+				String.fromCharCode((input[i + 2] & 63) + 33)
+			);
+		}
+	};
+	
+	dojox.encoding.easy64.encode = function(input){
+		// summary: encodes input data in easy64 string
+		// input: Array: an array of numbers (0-255) to encode
+		var result = [], reminder = input.length % 3, length = input.length - reminder;
+		c(input, length, result);
+		if(reminder){
+			var t = input.slice(length);
+			while(t.length < 3){ t.push(0); }
+			c(t, 3, result);
+			for(var i = 3; i > reminder; result.pop(), --i);
+		}
+		return result.join("");	// String
+	};
+
+	dojox.encoding.easy64.decode = function(input){
+		// summary: decodes the input string back to array of numbers
+		// input: String: the input string to decode
+		var n = input.length, r = [], b = [0, 0, 0, 0], i, j, d;
+		for(i = 0; i < n; i += 4){
+			for(j = 0; j < 4; ++j){ b[j] = input.charCodeAt(i + j) - 33; }
+			d = n - i;
+			for(j = d; j < 4; b[++j] = 0);
+			r.push(
+				(b[0] << 2) + (b[1] >>> 4),
+				((b[1] & 15) << 4) + (b[2] >>> 2),
+				((b[2] & 3) << 6) + b[3]
+			);
+			for(j = d; j < 4; ++j, r.pop());
+		}
+		return r;
+	};
 })();
-}
diff --git a/dojox/encoding/tests/ascii85.js b/dojox/encoding/tests/ascii85.js
new file mode 100644
index 0000000..ad05690
--- /dev/null
+++ b/dojox/encoding/tests/ascii85.js
@@ -0,0 +1,31 @@
+dojo.provide("dojox.encoding.tests.ascii85");
+dojo.require("dojox.encoding.ascii85");
+
+(function(){
+	var msg1 = "The rain in Spain falls mainly on the plain.";
+	var msg2 = "The rain in Spain falls mainly on the plain.1";
+	var msg3 = "The rain in Spain falls mainly on the plain.ab";
+	var msg4 = "The rain in Spain falls mainly on the plain.!@#";
+	var dca = dojox.encoding.ascii85;
+	
+	var s2b = function(s){
+		var b = [];
+		for(var i = 0; i < s.length; ++i){
+			b.push(s.charCodeAt(i));
+		}
+		return b;
+	};
+
+	var b2s = function(b){
+		var s = [];
+		dojo.forEach(b, function(c){ s.push(String.fromCharCode(c)); });
+		return s.join("");
+	};
+
+	tests.register("dojox.encoding.tests.ascii85", [
+		function testMsg1(t){ t.assertEqual(msg1, b2s(dca.decode(dca.encode(s2b(msg1))))); },
+		function testMsg2(t){ t.assertEqual(msg2, b2s(dca.decode(dca.encode(s2b(msg2))))); },
+		function testMsg3(t){ t.assertEqual(msg3, b2s(dca.decode(dca.encode(s2b(msg3))))); },
+		function testMsg4(t){ t.assertEqual(msg4, b2s(dca.decode(dca.encode(s2b(msg4))))); }
+	]);
+})();
diff --git a/dojox/encoding/tests/bits.js b/dojox/encoding/tests/bits.js
new file mode 100644
index 0000000..2ae7f59
--- /dev/null
+++ b/dojox/encoding/tests/bits.js
@@ -0,0 +1,70 @@
+dojo.provide("dojox.encoding.tests.bits");
+dojo.require("dojox.encoding.bits");
+
+(function(){
+	var msg1 = "The rain in Spain falls mainly on the plain.";
+	var msg2 = "The rain in Spain falls mainly on the plain.1";
+	var msg3 = "The rain in Spain falls mainly on the plain.ab";
+	var msg4 = "The rain in Spain falls mainly on the plain.!@#";
+	var dcb = dojox.encoding.bits;
+	
+	var s2b = function(s){
+		var b = [];
+		for(var i = 0; i < s.length; ++i){
+			b.push(s.charCodeAt(i));
+		}
+		return b;
+	};
+
+	var b2s = function(b){
+		var s = [];
+		dojo.forEach(b, function(c){ s.push(String.fromCharCode(c)); });
+		return s.join("");
+	};
+	
+	var testOut = function(msg){
+		var a = new dojox.encoding.bits.OutputStream();
+		for(var i = 0; i < msg.length; ++i){
+			var v = msg.charCodeAt(i);
+			var j = Math.floor(Math.random() * 7) + 1;
+			a.putBits(v >>> (8 - j), j);
+			a.putBits(v, 8 - j);
+		}
+		return b2s(a.getBuffer());
+	};
+
+	var testIn = function(msg){
+		var a = new dojox.encoding.bits.InputStream(s2b(msg), msg.length * 8);
+		var r = [];
+		for(var i = 0; i < msg.length; ++i){
+			var j = Math.floor(Math.random() * 7) + 1;
+			r.push((a.getBits(j) << (8 - j)) | a.getBits(8 - j));
+		}
+		return b2s(r);
+	};
+	
+	var test = function(msg){
+		var a = new dojox.encoding.bits.InputStream(s2b(msg), msg.length * 8);
+		var o = new dojox.encoding.bits.OutputStream();
+		while(a.getWidth() > 0){
+			var w = Math.min(a.getWidth(), 3);
+			o.putBits(a.getBits(w), w);
+		}
+		return b2s(o.getBuffer());
+	};
+
+	tests.register("dojox.encoding.tests.bits", [
+		function testBitsOut1(t){ t.assertEqual(msg1, testOut(msg1)); },
+		function testBitsOut2(t){ t.assertEqual(msg2, testOut(msg2)); },
+		function testBitsOut3(t){ t.assertEqual(msg3, testOut(msg3)); },
+		function testBitsOut4(t){ t.assertEqual(msg4, testOut(msg4)); },
+		function testBitsIn1(t){ t.assertEqual(msg1, testIn(msg1)); },
+		function testBitsIn2(t){ t.assertEqual(msg2, testIn(msg2)); },
+		function testBitsIn3(t){ t.assertEqual(msg3, testIn(msg3)); },
+		function testBitsIn4(t){ t.assertEqual(msg4, testIn(msg4)); },
+		function testBits1(t){ t.assertEqual(msg1, test(msg1)); },
+		function testBits2(t){ t.assertEqual(msg2, test(msg2)); },
+		function testBits3(t){ t.assertEqual(msg3, test(msg3)); },
+		function testBits4(t){ t.assertEqual(msg4, test(msg4)); }
+	]);
+})();
diff --git a/dojox/encoding/tests/compression/_base.js b/dojox/encoding/tests/compression/_base.js
new file mode 100644
index 0000000..666149b
--- /dev/null
+++ b/dojox/encoding/tests/compression/_base.js
@@ -0,0 +1,8 @@
+dojo.provide("dojox.encoding.tests.compression._base");
+
+try{
+	dojo.require("dojox.encoding.tests.compression.splay");
+	dojo.require("dojox.encoding.tests.compression.lzw");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/encoding/tests/compression/colors.js b/dojox/encoding/tests/compression/colors.js
new file mode 100755
index 0000000..fb7b0bb
--- /dev/null
+++ b/dojox/encoding/tests/compression/colors.js
@@ -0,0 +1,152 @@
+dojo.provide("dojox.encoding.tests.compression.colors");
+
+// all CSS3 colors
+dojox.encoding.tests.compression.colors = {
+aliceblue:	[240,248,255],
+antiquewhite:	[250,235,215],
+aqua:	[0,255,255],
+aquamarine:	[127,255,212],
+azure:	[240,255,255],
+beige:	[245,245,220],
+bisque:	[255,228,196],
+black:	[0,0,0],
+blanchedalmond:	[255,235,205],
+blue:	[0,0,255],
+blueviolet:	[138,43,226],
+brown:	[165,42,42],
+burlywood:	[222,184,135],
+cadetblue:	[95,158,160],
+chartreuse:	[127,255,0],
+chocolate:	[210,105,30],
+coral:	[255,127,80],
+cornflowerblue:	[100,149,237],
+cornsilk:	[255,248,220],
+crimson:	[220,20,60],
+cyan:	[0,255,255],
+darkblue:	[0,0,139],
+darkcyan:	[0,139,139],
+darkgoldenrod:	[184,134,11],
+darkgray:	[169,169,169],
+darkgreen:	[0,100,0],
+darkgrey:	[169,169,169],
+darkkhaki:	[189,183,107],
+darkmagenta:	[139,0,139],
+darkolivegreen:	[85,107,47],
+darkorange:	[255,140,0],
+darkorchid:	[153,50,204],
+darkred:	[139,0,0],
+darksalmon:	[233,150,122],
+darkseagreen:	[143,188,143],
+darkslateblue:	[72,61,139],
+darkslategray:	[47,79,79],
+darkslategrey:	[47,79,79],
+darkturquoise:	[0,206,209],
+darkviolet:	[148,0,211],
+deeppink:	[255,20,147],
+deepskyblue:	[0,191,255],
+dimgray:	[105,105,105],
+dimgrey:	[105,105,105],
+dodgerblue:	[30,144,255],
+firebrick:	[178,34,34],
+floralwhite:	[255,250,240],
+forestgreen:	[34,139,34],
+fuchsia:	[255,0,255],
+gainsboro:	[220,220,220],
+ghostwhite:	[248,248,255],
+gold:	[255,215,0],
+goldenrod:	[218,165,32],
+gray:	[128,128,128],
+green:	[0,128,0],
+greenyellow:	[173,255,47],
+grey:	[128,128,128],
+honeydew:	[240,255,240],
+hotpink:	[255,105,180],
+indianred:	[205,92,92],
+indigo:	[75,0,130],
+ivory:	[255,255,240],
+khaki:	[240,230,140],
+lavender:	[230,230,250],
+lavenderblush:	[255,240,245],
+lawngreen:	[124,252,0],
+lemonchiffon:	[255,250,205],
+lightblue:	[173,216,230],
+lightcoral:	[240,128,128],
+lightcyan:	[224,255,255],
+lightgoldenrodyellow:	[250,250,210],
+lightgray:	[211,211,211],
+lightgreen:	[144,238,144],
+lightgrey:	[211,211,211],
+lightpink:	[255,182,193],
+lightsalmon:	[255,160,122],
+lightseagreen:	[32,178,170],
+lightskyblue:	[135,206,250],
+lightslategray:	[119,136,153],
+lightslategrey:	[119,136,153],
+lightsteelblue:	[176,196,222],
+lightyellow:	[255,255,224],
+lime:	[0,255,0],
+limegreen:	[50,205,50],
+linen:	[250,240,230],
+magenta:	[255,0,255],
+maroon:	[128,0,0],
+mediumaquamarine:	[102,205,170],
+mediumblue:	[0,0,205],
+mediumorchid:	[186,85,211],
+mediumpurple:	[147,112,219],
+mediumseagreen:	[60,179,113],
+mediumslateblue:	[123,104,238],
+mediumspringgreen:	[0,250,154],
+mediumturquoise:	[72,209,204],
+mediumvioletred:	[199,21,133],
+midnightblue:	[25,25,112],
+mintcream:	[245,255,250],
+mistyrose:	[255,228,225],
+moccasin:	[255,228,181],
+navajowhite:	[255,222,173],
+navy:	[0,0,128],
+oldlace:	[253,245,230],
+olive:	[128,128,0],
+olivedrab:	[107,142,35],
+orange:	[255,165,0],
+orangered:	[255,69,0],
+orchid:	[218,112,214],
+palegoldenrod:	[238,232,170],
+palegreen:	[152,251,152],
+paleturquoise:	[175,238,238],
+palevioletred:	[219,112,147],
+papayawhip:	[255,239,213],
+peachpuff:	[255,218,185],
+peru:	[205,133,63],
+pink:	[255,192,203],
+plum:	[221,160,221],
+powderblue:	[176,224,230],
+purple:	[128,0,128],
+red:	[255,0,0],
+rosybrown:	[188,143,143],
+royalblue:	[65,105,225],
+saddlebrown:	[139,69,19],
+salmon:	[250,128,114],
+sandybrown:	[244,164,96],
+seagreen:	[46,139,87],
+seashell:	[255,245,238],
+sienna:	[160,82,45],
+silver:	[192,192,192],
+skyblue:	[135,206,235],
+slateblue:	[106,90,205],
+slategray:	[112,128,144],
+slategrey:	[112,128,144],
+snow:	[255,250,250],
+springgreen:	[0,255,127],
+steelblue:	[70,130,180],
+tan:	[210,180,140],
+teal:	[0,128,128],
+thistle:	[216,191,216],
+tomato:	[255,99,71],
+turquoise:	[64,224,208],
+violet:	[238,130,238],
+wheat:	[245,222,179],
+white:	[255,255,255],
+whitesmoke:	[245,245,245],
+yellow:	[255,255,0],
+yellowgreen:	[154,205,50]
+};
diff --git a/dojox/encoding/tests/compression/colors2.html b/dojox/encoding/tests/compression/colors2.html
new file mode 100755
index 0000000..24bb9fe
--- /dev/null
+++ b/dojox/encoding/tests/compression/colors2.html
@@ -0,0 +1,104 @@
+<html>
+	<head>
+		<title>Compress colors</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../../../dijit/tests/css/dijitTests.css";
+			
+			.pane { margin-top: 2em; }
+		</style>
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.encoding.tests.compression.colors");
+			dojo.require("dojox.encoding.ascii85");
+			dojo.require("dojox.encoding.bits");
+			dojo.require("dojox.encoding.compression.splay");
+			dojo.require("dojox.encoding.compression.lzw");
+			
+			var dc = dojox.encoding, dcc = dc.compression, colors = dc.tests.compression.colors;
+			
+			var run = function(){
+				var empty = {}, names = [];
+				for(var i in colors){
+					if(i in empty){ continue; }
+					names.push(i);
+				}
+				names.sort();
+				var output = new dc.bits.OutputStream(), result = [];
+				// encode names
+				var s = names.join("{"), encoder = new dcc.lzw.Encoder(27);
+				result.push("<div>Input is " + s.length + " bytes long.</div>");
+				result.push("<div>Input: " + s + ".</div>");
+				for(var i = 0; i < s.length; ++i){
+					var v = s.charCodeAt(i) - 97;
+					if(v < 0 || v > 26) console.debug("error!", v);
+					encoder.encode(v, output);
+				}
+				encoder.flush(output);
+				var w = output.getWidth();
+				result.push("<div>Output is " + Math.ceil(w / 8) + " bytes (" + w + " bits) long.</div>");
+				var buf = output.getBuffer();
+				{
+					var input = new dc.bits.InputStream(buf, buf.length * 8), decoder = new dcc.lzw.Decoder(27);
+					var t = [];
+					for(var w = 0; w < s.length;){
+						var v = decoder.decode(input);
+						t.push(v);
+						w += v.length;
+					}
+					t = t.join("");
+					var p = [];
+					for(var i = 0; i < t.length; ++i){
+						p.push(String.fromCharCode(t.charCodeAt(i) + 97));
+					}
+					p = p.join("");
+					result.push("<div>Control: " + p + ".</div>");
+				}
+				while(buf.length % 4){ buf.push(0); }
+				var a85 = dc.ascii85.encode(buf);
+				result.push("<div>Encoded output is " + a85.length + " bytes.</div>");
+				result.push("<div><textarea>" + a85 + "</textarea></div>");
+				// test
+				{
+					var buf = dc.ascii85.decode(a85);
+					var input = new dc.bits.InputStream(buf, buf.length * 8), decoder = new dcc.lzw.Decoder(27);
+					var t = [];
+					for(var w = 0; w < s.length;){
+						var v = decoder.decode(input);
+						t.push(v);
+						w += v.length;
+					}
+					t = t.join("");
+					var p = [];
+					for(var i = 0; i < t.length; ++i){
+						p.push(String.fromCharCode(t.charCodeAt(i) + 97));
+					}
+					p = p.join("");
+					result.push("<div>Control: " + p + ".</div>");
+				}
+				// encode values
+				buf = [];
+				for(var i = 0; i < names.length; ++i){
+					var c = colors[names[i]];
+					buf.push(c[0], c[1], c[2]);
+				}
+				result.push("<div>Output is " + buf.length + " bytes long.</div>");
+				while(buf.length % 4){ buf.push(0); }
+				a85 = dc.ascii85.encode(buf);
+				result.push("<div>Encoded output is " + a85.length + " bytes.</div>");
+				result.push("<div><textarea>" + a85 + "</textarea></div>");
+				dojo.byId("status").innerHTML = result.join("\n");
+			};			
+			
+			dojo.addOnLoad(function(){
+				dojo.connect(dojo.byId("run"), "onclick", run);
+			});
+		</script>
+	</head>
+	<body>
+		<h1>Compress colors</h1>
+		<p><button id="run">Run</button></p>
+		<div id="status" class="pane"><em>No status yet.</em></div>
+	</body>
+</html>
diff --git a/dojox/encoding/tests/compression/colors2.js b/dojox/encoding/tests/compression/colors2.js
new file mode 100755
index 0000000..effb87b
--- /dev/null
+++ b/dojox/encoding/tests/compression/colors2.js
@@ -0,0 +1,60 @@
+dojo.provide("dojox.encoding.tests.compression.colors2");
+
+// all CSS3 colors
+dojox.encoding.tests.compression.colors2 = {};
+
+(function(){
+	var n = "!mi-='%@Md%8;F\"=E5(:$@nHf!(;HYAOL),#XJKa#UHDMYQ0 at q6C8='JBa#m1`YRS;3_\\P=@.(bN\\!)0d:Nar*Fo]]G`\\[X7Cb at r#pc;D3!k*8^\"bS8DAYbu'J5[`7Fh5S1e8`@1^N\"n8R:+ZQt]Ab.S>NP-jkO\"N$oQpbVbYtZl1&rSs%_;'!e8\"ij:*R!%9&P.+o0%cF&0F<\"eWn+rm!a<(02!d\\-J\\O@`K![IaPrqh6H4S!U<Nh]PS,\"!C;0W&Y]X[<[E&`1gQ?_;g\\mbQn^c!eV!05V['T@)Lio1O0QV>7CU!\"5jICR2\\X?!FilaO:$aE\"G1NIfMJ<.)1d;?OH9VU%LiGhi9=d?$EjW!BM0)1mGfg@\"os1\\E*A>+>YdjUK:P>T'7tj.UQ?<89]$:\\Li]GF*H8o*Z,o]Q_E]tq?C^%'^cfU9B9sH-^t.-R;J6P9!buNg*%$9#>Y' [...]
+	var c = "nG*%[ldl.:s*t'unGiO]p\"]T._uKc;s6Io0!<7p,ih\\+ShRJ>JStLT5!7GR&s*mjUQ0nVHgtWT+!<<'!!/gi8Mn\"KLWMuisA,rU.WP,cVMZAZ8CG5^H!1>UdMZ<bAQ?nV)O%;El02G at s:JUu9d?FX[rtLXs^]/\"^Bk_9q*g$E-+sR'`n03c7rrE)Sgt_]\"s8U[Ng8,pBJ:IWM!3Q8SJ:N1>s7$&&[*;i\\9)sSDs7#O?N99:!s7#]/quHcnc)oX\\n:6&Is8VrldaQ[oORA4Ze'n?*_>g0S+L8#&cMDa at R<OITYf,Dus53nW!&DeSqXEYI!<7QL!+sKU!!(9T<R[.NgH;f^HYDgIqO0t&bf:HP)&[Dds8)cViW%uHs5'jX!.b%@k(%s^CQ9Y>V#^Na!8;DCmc^[<qj=STmb;]Es6nM<g:>I^5QAOBh4WT.i9#OiJH#TL]T8+>C#Ot='Dd6\"oV>kIMc]r [...]
+	var a = function(s){
+		var n = s.length, r = [], b = [0, 0, 0, 0, 0], i, j, t, x, y, d;
+		for(i = 0; i < n; i += 5){
+			for(j = 0; j < 5; ++j){ b[j] = s.charCodeAt(i + j) - 33; }
+			t = (((b[0] * 85 + b[1]) * 85 + b[2]) * 85 + b[3]) * 85 + b[4];
+			x = t & 255; t >>>= 8; y = t & 255; t >>>= 8;
+			r.push(t >>> 8, t & 255, y, x);
+		}
+		return r;
+	};
+	var B = function(f){ this.f = f; this.y = this.t = 0; };
+	B.prototype.g = function(b){
+		var r = 0;
+		while(b){
+			var w = Math.min(b, 8 - this.t), v = this.f[this.y] >>> (8 - this.t - w);
+			r <<= w; r |= v & ~(~0 << w);
+			if((this.t += w) == 8){ ++this.y; this.t = 0; }
+			b -= w;
+		}
+		return r;
+	};
+	var D = function(n, w){
+		this.c = new Array(n); this.w = w; this.p = -1;
+		for(var i = 0; i < n; ++i){ this.c[i] = [i + 97]; }
+	};
+	D.prototype.d = function(s){
+		var c = s.g(this.w), v;
+		if(c < this.c.length){
+			v = this.c[c];
+			if(this.p >= 0){
+				this.c.push(this.c[this.p].concat(v[0]));
+			}
+		}else{
+			this.c.push([]);
+			++this.w;
+			return [];
+		}
+		this.p = c;
+		return v;
+	};
+	var i = new B(a(n)), d = new D(27, 5), t = [];
+	while(t.length < 1455){
+		var v = d.d(i);
+		dojo.forEach(v, function(x){ t.push(x); });
+	}
+	var n2 = dojo.map(t, function(x){ return String.fromCharCode(x); }).join("").split("{");
+	i = a(c);
+	for(var j = 0, k = 0; j < n2.length; ++j){
+		dojox.encoding.tests.compression.colors2[n2[j]] = [i[k++], i[k++], i[k++]];
+	}
+
+})();
diff --git a/dojox/encoding/tests/compression/colors3.html b/dojox/encoding/tests/compression/colors3.html
new file mode 100755
index 0000000..482c75d
--- /dev/null
+++ b/dojox/encoding/tests/compression/colors3.html
@@ -0,0 +1,104 @@
+<html>
+	<head>
+		<title>Compress colors</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../../../dijit/tests/css/dijitTests.css";
+			
+			.pane { margin-top: 2em; }
+		</style>
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.encoding.tests.compression.colors");
+			dojo.require("dojox.encoding.easy64");
+			dojo.require("dojox.encoding.bits");
+			dojo.require("dojox.encoding.compression.splay");
+			dojo.require("dojox.encoding.compression.lzw");
+			
+			var dc = dojox.encoding, dcc = dc.compression, colors = dc.tests.compression.colors;
+			
+			var run = function(){
+				var empty = {}, names = [];
+				for(var i in colors){
+					if(i in empty){ continue; }
+					names.push(i);
+				}
+				names.sort();
+				var output = new dc.bits.OutputStream(), result = [];
+				// encode names
+				var s = names.join("{"), encoder = new dcc.lzw.Encoder(27);
+				result.push("<div>Input is " + s.length + " bytes long.</div>");
+				result.push("<div>Input: " + s + ".</div>");
+				for(var i = 0; i < s.length; ++i){
+					var v = s.charCodeAt(i) - 97;
+					if(v < 0 || v > 26) console.debug("error!", v);
+					encoder.encode(v, output);
+				}
+				encoder.flush(output);
+				var w = output.getWidth();
+				result.push("<div>Output is " + Math.ceil(w / 8) + " bytes (" + w + " bits) long.</div>");
+				var buf = output.getBuffer();
+				{
+					var input = new dc.bits.InputStream(buf, buf.length * 8), decoder = new dcc.lzw.Decoder(27);
+					var t = [];
+					for(var w = 0; w < s.length;){
+						var v = decoder.decode(input);
+						t.push(v);
+						w += v.length;
+					}
+					t = t.join("");
+					var p = [];
+					for(var i = 0; i < t.length; ++i){
+						p.push(String.fromCharCode(t.charCodeAt(i) + 97));
+					}
+					p = p.join("");
+					result.push("<div>Control: " + p + ".</div>");
+				}
+				while(buf.length % 3){ buf.push(0); }
+				var e64 = dc.easy64.encode(buf);
+				result.push("<div>Encoded output is " + e64.length + " bytes.</div>");
+				result.push("<div><textarea>" + e64 + "</textarea></div>");
+				// test
+				{
+					var buf = dc.easy64.decode(e64);
+					var input = new dc.bits.InputStream(buf, buf.length * 8), decoder = new dcc.lzw.Decoder(27);
+					var t = [];
+					for(var w = 0; w < s.length;){
+						var v = decoder.decode(input);
+						t.push(v);
+						w += v.length;
+					}
+					t = t.join("");
+					var p = [];
+					for(var i = 0; i < t.length; ++i){
+						p.push(String.fromCharCode(t.charCodeAt(i) + 97));
+					}
+					p = p.join("");
+					result.push("<div>Control: " + p + ".</div>");
+				}
+				// encode values
+				buf = [];
+				for(var i = 0; i < names.length; ++i){
+					var c = colors[names[i]];
+					buf.push(c[0], c[1], c[2]);
+				}
+				result.push("<div>Output is " + buf.length + " bytes long.</div>");
+				while(buf.length % 4){ buf.push(0); }
+				e64 = dc.easy64.encode(buf);
+				result.push("<div>Encoded output is " + e64.length + " bytes.</div>");
+				result.push("<div><textarea>" + e64 + "</textarea></div>");
+				dojo.byId("status").innerHTML = result.join("\n");
+			};			
+			
+			dojo.addOnLoad(function(){
+				dojo.connect(dojo.byId("run"), "onclick", run);
+			});
+		</script>
+	</head>
+	<body>
+		<h1>Compress colors</h1>
+		<p><button id="run">Run</button></p>
+		<div id="status" class="pane"><em>No status yet.</em></div>
+	</body>
+</html>
diff --git a/dojox/encoding/tests/compression/colors3.js b/dojox/encoding/tests/compression/colors3.js
new file mode 100755
index 0000000..33dd282
--- /dev/null
+++ b/dojox/encoding/tests/compression/colors3.js
@@ -0,0 +1,49 @@
+dojo.provide("dojox.encoding.tests.compression.colors3");
+
+// all CSS3 colors
+dojox.encoding.tests.compression.colors3 = {};
+
+(function(){
+	var n = "!N!C@\",5%;!.4)1D7()4E!K!FS-!2).Q:52E`!B\"!;!)*+I!M!#&'E+9%(#!T9Q=.\"TE5F'6%$B91H/)DCQW=^&G#QY>:\"!!?*#D.57Z.]5**+0]/!G!!,X=/%2O'%1U&#W9%%86_BQU3#!N.!DA-%F>X'#9;6\"%+EK)X#A+A;+-+\"G\"T$76:L1;)'+?ENA1%L+C\\O+U+\"Q!+#,E+.E1H-[VA#\"5%O\\X)BS:%V2&2#,3I0NWE%F7?L8U!U\\\\B3C_GZ?P3N]A3\\]$)%TUK$E9EL6ZA`T%IFY$Q?/3;=Q)$QE#AQ\\11$&M!'$$XK!T?2%C7QU\"110A#/#:'U=C!7,\"=*!+BQ)%AG[)W&#CFBG\"A!/1E!5/$AU\"A/$J:*E+LQ77;%M6H/XD,H1'!)#U=&K1\"&R02U'$H5*[%Y+$3;/1'#\"-XQV8C(/GABVQQW+RS5U3QE!V<6[=YS@!0 [...]
+	var c = "]0D`_OP8!0``@``5]0``^@8=`_4%!!!!`_P.!!$`CCPCJ3IKXLC(8Z[A@`]!UGE?`X^1:*8N``D=X\"1]!0``!!#,!)O,O)9,K;GJ!'1!K;GJP<>LCQ#,67MP`YQ!G4,-CQ!![::[D\\S03$W,,U^0,U^0!-\\2F!$4`R34!,``;7FJ;7FJ(J$`MC)C``LQ)IMC`Q$`X.T=_0D``^=!WK5AA)#!!)!!L@]PA)#!]0`Q`WGUT6R=3Q##```Q]/;-ZO<[``$V at 0Q!``L.L>DG])#!Y0``_PL3U^04E/[1U^04`\\<\"`[\"[),+KB]\\[>YC:>YC:M-4?```A!0]!-MUS_P$G`Q$`A!!!:MWK!!$.OF84EX$<0,.R?WDO!0K;3.(-RR7&'2FQ^@`[`_4B`_3V`^[N!!#!`@8GA)!!;YYD`[5!`U5!WH$7\\OCKG0O9L_\\OWX#4`_`6`^KZT95``]$,X;$>M/$GA [...]
+	var B = function(f){ var t = this; t.f = f; t.y = t.t = 0; t.x = f.charCodeAt(0) - 33; };
+	B.prototype.g = function(b){
+		var r = 0, t = this;
+		while(b){
+			var w = Math.min(b, 6 - t.t), v = t.x >>> (6 - t.t - w);
+			r <<= w; r |= v & ~(~0 << w);
+			if((t.t += w) == 6){ t.x = t.f.charCodeAt(++t.y) - 33; t.t = 0; }
+			b -= w;
+		}
+		return r;
+	};
+	var D = function(n, w){
+		this.c = new Array(n); this.w = w; this.p = -1;
+		for(var i = 0; i < n; ++i){ this.c[i] = [i + 97]; }
+	};
+	D.prototype.d = function(s){
+		var c = s.g(this.w), t = this, v;
+		if(c < t.c.length){
+			v = t.c[c];
+			if(t.p >= 0){
+				t.c.push(t.c[t.p].concat(v[0]));
+			}
+		}else{
+			t.c.push([]);
+			++t.w;
+			return [];
+		}
+		t.p = c;
+		return v;
+	};
+	var i = new B(n), d = new D(27, 5), t = [];
+	while(t.length < 1455){
+		var v = d.d(i);
+		dojo.forEach(v, function(x){ t.push(x); });
+	}
+	var n2 = dojo.map(t, function(x){ return String.fromCharCode(x); }).join("").split("{");
+	i = new B(c);
+	for(var j = 0; j < n2.length; ++j){
+		dojox.encoding.tests.compression.colors3[n2[j]] = [i.g(8), i.g(8), i.g(8)];
+	}
+})();
diff --git a/dojox/encoding/tests/compression/lzw.js b/dojox/encoding/tests/compression/lzw.js
new file mode 100644
index 0000000..5dfa27f
--- /dev/null
+++ b/dojox/encoding/tests/compression/lzw.js
@@ -0,0 +1,50 @@
+dojo.provide("dojox.encoding.tests.compression.lzw");
+dojo.require("dojox.encoding.compression.lzw");
+dojo.require("dojox.encoding.bits");
+
+(function(){
+	var msg1 = "The rain in Spain falls mainly on the plain.";
+	var msg2 = "The rain in Spain falls mainly on the plain.1";
+	var msg3 = "The rain in Spain falls mainly on the plain.ab";
+	var msg4 = "The rain in Spain falls mainly on the plain.!@#";
+	var dc = dojox.encoding.compression, dcb = dojox.encoding.bits, dcl = dc.lzw;
+	
+	var s2b = function(s){
+		var b = [];
+		for(var i = 0; i < s.length; ++i){
+			b.push(s.charCodeAt(i));
+		}
+		return b;
+	};
+
+	var b2s = function(b){
+		var s = [];
+		dojo.forEach(b, function(c){ s.push(String.fromCharCode(c)); });
+		return s.join("");
+	};
+	
+	var encode = function(msg){
+		var x = new dcb.OutputStream(), encoder = new dcl.Encoder(128);
+		dojo.forEach(s2b(msg), function(v){ encoder.encode(v, x); });
+		encoder.flush(x);
+		console.debug("bits =", x.getWidth());
+		return x.getBuffer();
+	};
+	
+	var decode = function(n, buf){
+		var x = new dcb.InputStream(buf, buf.length * 8), decoder = new dcl.Decoder(128), t = [], w = 0;
+		while(w < n){
+			var v = decoder.decode(x);
+			t.push(v);
+			w += v.length;
+		}
+		return t.join("");
+	};
+
+	tests.register("dojox.encoding.tests.compression.lzw", [
+		function testLzwMsg1(t){ t.assertEqual(msg1, decode(msg1.length, encode(msg1))); },
+		function testLzwMsg2(t){ t.assertEqual(msg2, decode(msg2.length, encode(msg2))); },
+		function testLzwMsg3(t){ t.assertEqual(msg3, decode(msg3.length, encode(msg3))); },
+		function testLzwMsg4(t){ t.assertEqual(msg4, decode(msg4.length, encode(msg4))); }
+	]);
+})();
diff --git a/dojox/encoding/tests/compression/runTests.html b/dojox/encoding/tests/compression/runTests.html
new file mode 100755
index 0000000..4a24eef
--- /dev/null
+++ b/dojox/encoding/tests/compression/runTests.html
@@ -0,0 +1,9 @@
+<html>
+	<head>
+		<title>DojoX Compression Unit Test Runner</title>
+	    <meta http-equiv="REFRESH" content="0;url=../../../../util/doh/runner.html?testModule=dojox.encoding.tests.compression._base" />
+	</head>
+	<body>
+		<p>Redirecting to D.O.H runner.</p>	
+	</body>
+</html>
diff --git a/dojox/encoding/tests/compression/splay.js b/dojox/encoding/tests/compression/splay.js
new file mode 100644
index 0000000..09ad50e
--- /dev/null
+++ b/dojox/encoding/tests/compression/splay.js
@@ -0,0 +1,45 @@
+dojo.provide("dojox.encoding.tests.compression.splay");
+dojo.require("dojox.encoding.compression.splay");
+dojo.require("dojox.encoding.bits");
+
+(function(){
+	var msg1 = "The rain in Spain falls mainly on the plain.";
+	var msg2 = "The rain in Spain falls mainly on the plain.1";
+	var msg3 = "The rain in Spain falls mainly on the plain.ab";
+	var msg4 = "The rain in Spain falls mainly on the plain.!@#";
+	var dc = dojox.encoding.compression, dcb = dojox.encoding.bits;
+	
+	var s2b = function(s){
+		var b = [];
+		for(var i = 0; i < s.length; ++i){
+			b.push(s.charCodeAt(i));
+		}
+		return b;
+	};
+
+	var b2s = function(b){
+		var s = [];
+		dojo.forEach(b, function(c){ s.push(String.fromCharCode(c)); });
+		return s.join("");
+	};
+	
+	var encode = function(msg){
+		var x = new dcb.OutputStream(), encoder = new dc.Splay(256);
+		dojo.forEach(s2b(msg), function(v){ encoder.encode(v, x); });
+		console.debug("bits =", x.getWidth());
+		return x.getBuffer();
+	};
+	
+	var decode = function(n, buf){
+		var x = new dcb.InputStream(buf, buf.length * 8), decoder = new dc.Splay(256), t = [];
+		for(var i = 0; i < n; ++i){ t.push(decoder.decode(x)); }
+		return b2s(t);
+	};
+
+	tests.register("dojox.encoding.tests.compression.splay", [
+		function testSplayMsg1(t){ t.assertEqual(msg1, decode(msg1.length, encode(msg1))); },
+		function testSplayMsg2(t){ t.assertEqual(msg2, decode(msg2.length, encode(msg2))); },
+		function testSplayMsg3(t){ t.assertEqual(msg3, decode(msg3.length, encode(msg3))); },
+		function testSplayMsg4(t){ t.assertEqual(msg4, decode(msg4.length, encode(msg4))); }
+	]);
+})();
diff --git a/dojox/encoding/tests/compression/test.html b/dojox/encoding/tests/compression/test.html
new file mode 100755
index 0000000..8f07c59
--- /dev/null
+++ b/dojox/encoding/tests/compression/test.html
@@ -0,0 +1,61 @@
+<html>
+	<head>
+		<title>Test colors</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../../../dijit/tests/css/dijitTests.css";
+			
+			.pane { margin-top: 2em; }
+		</style>
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript" src="colors2.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.encoding.tests.compression.colors");
+			//dojo.require("dojox.encoding.tests.compression.colors2");
+			dojo.require("dojox.encoding.tests.compression.colors3");
+			var dct = dojox.encoding.tests.compression;
+			
+			var test = function(c1, c2, result){
+				var empty = {};
+				for(var i in c1){
+					if(i in empty){ continue; }
+					if(!(i in c2)){
+						result.push("<div>" + i + " is missing.</div>");
+						continue;
+					}
+					var v1 = c1[i], v2 = c2[i];
+					if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2]){
+						result.push("<div>" + i + " doesn't match.</div>");
+						continue;
+					}
+					result.push("<div style='color: green'>" + i + " is ok.</div>");
+				}
+			};
+			
+			var run = function(){
+				var result = [];
+				result.push("<p><strong>Comparing colors to colors3.</strong></p>");
+				test(dct.colors, dct.colors3, result);
+				result.push("<p><strong>Comparing colors3 to colors.</strong></p>");
+				test(dct.colors3, dct.colors, result);
+				/*
+				result.push("<p><strong>Comparing colors to colors2.</strong></p>");
+				test(dct.colors, dct.colors2, result);
+				result.push("<p><strong>Comparing colors2 to colors.</strong></p>");
+				test(dct.colors2, dct.colors, result);
+				*/
+				dojo.byId("status").innerHTML = result.join("\n");
+			};			
+			
+			dojo.addOnLoad(function(){
+				dojo.connect(dojo.byId("run"), "onclick", run);
+			});
+		</script>
+	</head>
+	<body>
+		<h1>Test colors</h1>
+		<p><button id="run">Run</button></p>
+		<div id="status" class="pane"><em>No status yet.</em></div>
+	</body>
+</html>
diff --git a/dojox/encoding/tests/compression/vq.html b/dojox/encoding/tests/compression/vq.html
new file mode 100755
index 0000000..7805bd4
--- /dev/null
+++ b/dojox/encoding/tests/compression/vq.html
@@ -0,0 +1,185 @@
+<html>
+	<head>
+		<title>Compress colors using VQ</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../../../dijit/tests/css/dijitTests.css";
+			
+			.pane { margin-top: 2em; }
+		</style>
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.encoding.tests.compression.colors");
+			dojo.require("dojox.encoding.compression.splay");
+			dojo.require("dojox.encoding.bits");
+			
+			var colors = dojox.encoding.tests.compression.colors;
+			
+			var dist = function(a, b){
+				var r = a[0] - b[0], g = a[1] - b[1], b = a[2] - b[2];
+				return r * r + g * g + b * b;				
+			};
+			
+			var hexcolor = function(c){
+				return "#" + (c[0] < 16 ? "0" : "") + c[0].toString(16) + 
+					(c[1] < 16 ? "0" : "") + c[1].toString(16) + 
+					(c[2] < 16 ? "0" : "") + c[2].toString(16);
+			};
+			
+			var maxdist = function(a, b, maxdist){
+				var r = Math.abs(a[0] - b[0]), g = Math.abs(a[1] - b[1]), b = Math.abs(a[2] - b[2]);
+				++maxdist[bits(r)];
+				++maxdist[bits(g)];
+				++maxdist[bits(b)];
+			};
+			
+			var encodeColor = function(a, b, splay, stream){
+				var r = a[0] - b[0], g = a[1] - b[1], b = a[2] - b[2];
+				stream.putBits(r < 0 ? 1 : 0, 1);
+				splay.encode(Math.abs(r), stream);
+				stream.putBits(g < 0 ? 1 : 0, 1);
+				splay.encode(Math.abs(g), stream);
+				stream.putBits(b < 0 ? 1 : 0, 1);
+				splay.encode(Math.abs(b), stream);
+			};
+			
+			var bits = function(x){
+				var w = 1;
+				for(var v = 2; x >= v; v <<= 1, ++w);
+				return w;
+			};
+			
+			var runVQ = function(n){
+				dojo.byId("status").innerHTML = "<em>Initializing...</em>";
+				dojo.byId("report").innerHTML = "<em>Running VQ...</em>";
+				var clusters = [];
+				// select initial cluster centers
+				var empty = {};
+				for(var i in colors){
+					if(i in empty){ continue; }
+					clusters.push({center: colors[i]});
+					if(clusters.length == n){ break; }
+				}
+				/*
+				for(var i = 0; i < n; ++i){
+					var r = Math.floor(Math.random() * 256), g = Math.floor(Math.random() * 256), b = Math.floor(Math.random() * 256);
+					clusters.push({center: [r, g, b]});
+				}
+				*/
+				// do runs
+				dojo.byId("status").innerHTML = "<div>Starting runs...</div>";
+				var jitter = 0, niter = 1;
+				do {
+					// save previous centers
+					var old_clusters = [];
+					dojo.forEach(clusters, function(c){	old_clusters.push({center: c.center}); c.members = []; });
+					// assign colors to clusters
+					for(var i in colors){
+						if(i in empty){ continue; }
+						var c = colors[i], k = -1, kd = Number.MAX_VALUE;
+						for(var j = 0; j < clusters.length; ++j){
+							var jd = dist(clusters[j].center, c);
+							if(jd < kd){ k = j, kd = jd; }
+						}
+						clusters[k].members.push(i);
+					}
+					// recalculate cluster centers
+					for(var i = 0; i < clusters.length; ++i){
+						if(!clusters[i].members.length){ continue; }
+						var r = 0, g = 0, b = 0;
+						dojo.forEach(clusters[i].members, function(name){
+							var c = colors[name];
+							r += c[0];
+							g += c[1];
+							b += c[2];
+						});
+						r = Math.round(r / clusters[i].members.length);
+						g = Math.round(g / clusters[i].members.length);
+						b = Math.round(b / clusters[i].members.length);
+						clusters[i].center = [r, g, b];
+					}
+					// calculate the jitter
+					jitter = 0;
+					for(var i = 0; i < clusters.length; ++i){
+						jitter = Math.max(jitter, dist(clusters[i].center, old_clusters[i].center));
+					}
+					var node = dojo.doc.createElement("div");
+					node.innerHTML = "Run #" + niter + ", jitter = " + jitter;
+					dojo.byId("status").appendChild(node);
+					++niter;
+				}while(jitter > 1 && niter < 1000);
+				// calculate the required number of bytes
+				var output = new dojox.encoding.bits.OutputStream(),
+					splay = new dojox.encoding.compression.Splay(256);
+				for(var i = 0; i < clusters.length; ++i){
+					var c = clusters[i], m = c.members, d = 0, ol = output.getWidth();
+					output.putBits(c.center[0], 8);
+					output.putBits(c.center[1], 8);
+					output.putBits(c.center[2], 8);
+					splay.reset();
+					c.maxdist = [0, 0, 0, 0, 0, 0, 0, 0, 0];
+					for(var j = 0; j < m.length; ++j){
+						var color = colors[m[j]];
+						maxdist(c.center, color, c.maxdist);
+						encodeColor(c.center, color, splay, output);
+					}
+					c.bits = output.getWidth() - ol;
+				}
+				var node = dojo.doc.createElement("div");
+				node.innerHTML = "Required " + Math.ceil(output.getWidth() / 8) + " bytes";
+				dojo.byId("status").appendChild(node);
+				// generate color tables
+				var reps = [];
+				for(var i = 0; i < clusters.length; ++i){
+					var c = clusters[i], m = c.members;
+					reps.push("<p>Cluster #" + i + " contains " + m.length + " members. Length histogram:");
+					for(var j = 0; j < c.maxdist.length; ++j){
+						if(c.maxdist[j]){
+							reps.push(" " + j + "—" + c.maxdist[j]);
+						}
+					}
+					reps.push(". It requires " + c.bits + " bits (" + Math.ceil(c.bits / 8) + " bytes) to be encoded.</p>");
+					reps.push("<table>");
+					var wd = dist([255,255,255], c.center), bd = dist([0,0,0], c.center);
+					reps.push("<tr><td style='background: " + hexcolor(c.center) + "; color: " + 
+						(wd < bd ? "black" : "white") + "'><strong>CENTER</strong></td><td>" + 
+						c.center[0] + "</td><td>" + c.center[1] + "</td><td>" + c.center[2] + "</td></tr>");
+					for(var j = 0; j < m.length; ++j){
+						var color = colors[m[j]];
+						wd = dist([255,255,255], color);
+						bd = dist([0,0,0], color);
+						reps.push("<tr><td style='background: " + m[j] + "; color: " +
+							(wd < bd ? "black" : "white") + "'><strong>" + m[j] + "</strong></td><td>" + 
+							color[0] + "</td><td>" + color[1] + "</td><td>" + color[2] + "</td></tr>");
+					}
+					reps.push("</table>");
+				}
+				dojo.byId("report").innerHTML = reps.join("\n");
+			};
+			
+			run = function(){
+				var n = parseInt(dojo.byId("ncluster").value);
+				runVQ(n);
+			};
+			
+			dojo.addOnLoad(function(){
+				dojo.connect(dojo.byId("run"), "onclick", run);
+			});
+		</script>
+	</head>
+	<body>
+		<h1>Compress colors using VQ</h1>
+		<p>Select desirable number of clusters: <select id="ncluster">
+			<option value="1">1</option>
+			<option value="2">2</option>
+			<option value="4">4</option>
+			<option value="8">8</option>
+			<option value="16">16</option>
+			<option value="32">32</option>
+			<option value="64">64</option>
+		</select> <button id="run">Run</button></p>
+		<div id="status" class="pane"><em>No status yet.</em></div>
+		<div id="report" class="pane"><em>No results yet.</em></div>
+	</body>
+</html>
diff --git a/dojox/encoding/tests/crypto/Blowfish.js b/dojox/encoding/tests/crypto/Blowfish.js
new file mode 100644
index 0000000..61a0bf2
--- /dev/null
+++ b/dojox/encoding/tests/crypto/Blowfish.js
@@ -0,0 +1,31 @@
+dojo.provide("dojox.encoding.tests.crypto.Blowfish");
+dojo.require("dojox.encoding.crypto.Blowfish");
+
+(function(){
+	var message="The rain in Spain falls mainly on the plain.";
+	var key="foobar";
+	var base64Encrypted="WI5J5BPPVBuiTniVcl7KlIyNMmCosmKTU6a/ueyQuoUXyC5dERzwwdzfFsiU4vBw";
+	var dxc=dojox.encoding.crypto;
+
+	tests.register("dojox.encoding.crypto.tests.Blowfish", [
+		function testEncrypt(t){
+			var dt=new Date();
+			t.assertEqual(base64Encrypted, dxc.Blowfish.encrypt(message, key));
+			doh.debug("testEncrypt: ", new Date()-dt, "ms.");
+		},
+		function testDecrypt(t){
+			var dt=new Date();
+			t.assertEqual(message, dxc.Blowfish.decrypt(base64Encrypted, key));
+			doh.debug("testDecrypt: ", new Date()-dt, "ms.");
+		},
+		function testShortMessage(t){
+			var msg="pass";
+			var pwd="foobar";
+			var dt=new Date();
+			var enc=dxc.Blowfish.encrypt(msg, pwd);
+			var dec=dxc.Blowfish.decrypt(enc, pwd);
+			t.assertEqual(dec, msg);
+			doh.debug("testShortMessage: ", new Date()-dt, "ms.");
+		}
+	]);
+})();
diff --git a/dojox/encoding/tests/crypto/RSA.js b/dojox/encoding/tests/crypto/RSA.js
new file mode 100644
index 0000000..de31d2e
--- /dev/null
+++ b/dojox/encoding/tests/crypto/RSA.js
@@ -0,0 +1,175 @@
+dojo.provide("dojox.encoding.tests.crypto.RSA");
+
+dojo.require("dojox.encoding.crypto.RSAKey");
+dojo.require("dojox.encoding.crypto.RSAKey-ext");
+dojo.require("dojox.math.random.Secure");
+dojo.require("dojox.math.random.prng4");
+
+(function(){
+	var dxc = dojox.encoding.crypto,
+		message = "The rain in Spain falls mainly on the plain.",
+
+		Secure = dojox.math.random.Secure, prng4 = dojox.math.random.prng4,
+		sec = function(){ return new Secure(prng4); },
+
+		keys = {
+			"512e3": {
+				N:		"BC86E3DC782C446EE756B874ACECF2A115E613021EAF1ED5EF295BEC2BED899D" +
+						"26FE2EC896BF9DE84FE381AF67A7B7CBB48D85235E72AB595ABF8FE840D5F8DB",
+				E:		"3",
+				D:		"7daf4292fac82d9f44e47af87348a1c0b9440cac1474bf394a1b929d729e5bbc" +
+						"f402f29a9300e11b478c091f7e5dacd3f8edae2effe3164d7e0eeada87ee817b",
+				P:		"ef3fc61e21867a900e01ee4b1ba69f5403274ed27656da03ed88d7902cce693f",
+				Q:		"c9b9fcc298b7d1af568f85b50e749539bc01b10a68472fe1302058104821cd65",
+				DMP1:	"9f7fd9696baefc6009569edcbd19bf8d576f89e1a439e6ad4905e50ac8899b7f",
+				DMQ1:	"867bfdd7107a8bca39b503ce09a30e267d567606f02f7540cac03ab5856bde43",
+				COEFF:	"412d6b551d93ee1bd7dccafc63d7a6d031fc66035ecc630ddf75f949a378cd9d"
+			},
+
+			"512f4": {
+				N:		"C4E3F7212602E1E396C0B6623CF11D26204ACE3E7D26685E037AD2507DCE82FC" +
+						"28F2D5F8A67FC3AFAB89A6D818D1F4C28CFA548418BD9F8E7426789A67E73E41",
+				E:		"10001",
+				D:		"7cd1745aec69096129b1f42da52ac9eae0afebbe0bc2ec89253598dcf454960e" +
+						"3e5e4ec9f8c87202b986601dd167253ee3fb3fa047e14f1dfd5ccd37e931b29d",
+				P:		"f0e4dd1eac5622bd3932860fc749bbc48662edabdf3d2826059acc0251ac0d3b",
+				Q:		"d13cb38fbcd06ee9bca330b4000b3dae5dae12b27e5173e4d888c325cda61ab3",
+				DMP1:	"b3d5571197fc31b0eb6b4153b425e24c033b054d22b9c8282254fe69d8c8c593",
+				DMQ1:	"968ffe89e50d7b72585a79b65cfdb9c1da0963cceb56c3759e57334de5a0ac3f",
+				COEFF:	"d9bc4f420e93adad9f007d0e5744c2fe051c9ed9d3c9b65f439a18e13d6e3908"
+			},
+
+			"1024e3": {
+				N:		"ABC30681295774F7CECA691EC17F4E762DA6DE70F198EAEE3CCE3A435FC006B9" +
+						"71DC24E55904F1D2705758C041C2B0B18E8BFAE2C9CD96B50082D7D8C7342CBA" +
+						"B7F6E0622DA53B8B56DBDB24174F00173263CFECAE604795CDA2A037BC3A69B7" +
+						"C0090AA2DE1568998BCD6D70CC2E0574755B9F7986AE01CE8714A26144279CDB",
+				E:		"3",
+				D:		"728204561b8fa34fdf319b69d654def973c4944b4bbb47497dded1823fd559d0" +
+						"f692c34390adf68c4ae4e5d5812c75cbb45d51ec86890f2355ac8fe5da22c87b" +
+						"62449e2aa754422bc43d3ca32efa866227ad58178e7803897d074f1312740aa7" +
+						"61cfc7ed753bb829d7a2ab091289d1676809bfd61276b43bb3a395714f167beb",
+				P:		"e200731c6e934a0fdc1d5ce5f66d08ba9478280f46e9cbed777029dd4811a7cd" +
+						"4aa66ad8365c5aa67b06b97e54ee8fec03adb2134f7359a427c7ffc468ef0231",
+				Q:		"c28f8005c4138e39d462a3495a6a2dc96267a3ba11c2765a1aa77fbdd87ab1ef" +
+						"62aaf3e677df79b44d52b364db70bb6d559f4da51b8899d0d1d74272e496e0cb",
+				DMP1:	"96aaf76849b786b53d68e8994ef35b270da5700a2f4687f3a4f5713e300bc533" +
+						"87199c90243d91c452047ba98df45ff2ad1e76b78a4ce66d6fdaaa82f09f56cb",
+				DMQ1:	"81b50003d80d097be2ec6cdb919c1e86419a6d26b681a43c11c4ffd3e5a7214a" +
+						"41c74d444fea5122de3722433cf5d248e3bf8918bd05bbe08be4d6f7430f4087",
+				COEFF:	"a318fb95d3b10d6cfb0096fc3a3173377cf0952bf5d50fd3ccf678dd636ca1a1" +
+						"aeed8da416c8fba4395b00dc3e22823d1b2add8a4e1222d562af11bd6c78ad94"
+			},
+
+			"1024f4": {
+				N:		"a5261939975948bb7a58dffe5ff54e65f0498f9175f5a09288810b8975871e99" +
+						"af3b5dd94057b0fc07535f5f97444504fa35169d461d0d30cf0192e307727c06" +
+						"5168c788771c561a9400fb49175e9e6aa4e23fe11af69e9412dd23b0cb6684c4" +
+						"c2429bce139e848ab26d0829073351f4acd36074eafd036a5eb83359d2a698d3",
+				E:		"10001",
+				D:		"8e9912f6d3645894e8d38cb58c0db81ff516cf4c7e5a14c7f1eddb1459d2cded" +
+						"4d8d293fc97aee6aefb861859c8b6a3d1dfe710463e1f9ddc72048c09751971c" +
+						"4a580aa51eb523357a3cc48d31cfad1d4a165066ed92d4748fb6571211da5cb1" +
+						"4bc11b6e2df7c1a559e6d5ac1cd5c94703a22891464fba23d0d965086277a161",
+				P:		"d090ce58a92c75233a6486cb0a9209bf3583b64f540c76f5294bb97d285eed33" +
+						"aec220bde14b2417951178ac152ceab6da7090905b478195498b352048f15e7d",
+				Q:		"cab575dc652bb66df15a0359609d51d1db184750c00c6698b90ef3465c996551" +
+						"03edbf0d54c56aec0ce3c4d22592338092a126a0cc49f65a4a30d222b411e58f",
+				DMP1:	"1a24bca8e273df2f0e47c199bbf678604e7df7215480c77c8db39f49b000ce2c" +
+						"f7500038acfff5433b7d582a01f1826e6f4d42e1c57f5e1fef7b12aabc59fd25",
+				DMQ1:	"3d06982efbbe47339e1f6d36b1216b8a741d410b0c662f54f7118b27b9a4ec9d" +
+						"914337eb39841d8666f3034408cf94f5b62f11c402fc994fe15a05493150d9fd",
+				COEFF:	"3a3e731acd8960b7ff9eb81a7ff93bd1cfa74cbd56987db58b4594fb09c09084" +
+						"db1734c8143f98b602b981aaa9243ca28deb69b5b280ee8dcee0fd2625e53250"
+			}
+		};
+
+	function roundTrip(text, key, rngf){
+		var rsa = rngf ? new dxc.RSAKey(rngf) : new dxc.RSAKey();
+		rsa.setPublic(key.N, key.E);
+		var encoded = rsa.encrypt(text);
+		rsa.setPrivateEx(key.N, key.E, key.D, key.P, key.Q, key.DMP1, key.DMQ1, key.COEFF);
+		var decoded = rsa.decrypt(encoded);
+		return decoded;
+	}
+
+	function generateKey(len, e, rngf){
+		var rsa = rngf ? new dxc.RSAKey(rngf) : new dxc.RSAKey();
+		rsa.generate(len, e);
+		return {
+			N: rsa.n.toString(),
+			E: rsa.e.toString(),
+			D: rsa.d.toString(),
+			P: rsa.p.toString(),
+			Q: rsa.q.toString(),
+			DMP1:  rsa.dmp1.toString(),
+			DMQ1:  rsa.dmq1.toString(),
+			COEFF: rsa.coeff.toString()
+		};
+	}
+
+	tests.register("dojox.encoding.crypto.tests.RSA", [
+		// simple round-trip
+		function testSimple_RoundTrip1(t){
+			t.is(message, roundTrip(message, keys["512e3"]));
+		},
+		function testSimple_RoundTrip2(t){
+			t.is(message, roundTrip(message, keys["512f4"]));
+		},
+		function testSimple_RoundTrip3(t){
+			t.is(message, roundTrip(message, keys["1024e3"]));
+		},
+		function testSimple_RoundTrip4(t){
+			t.is(message, roundTrip(message, keys["1024f4"]));
+		},
+		// secure round-trip
+		function testSecure_RoundTrip1(t){
+			t.is(message, roundTrip(message, keys["512e3"], sec));
+		},
+		function testSecure_RoundTrip2(t){
+			t.is(message, roundTrip(message, keys["512f4"], sec));
+		},
+		function testSecure_RoundTrip3(t){
+			t.is(message, roundTrip(message, keys["1024e3"], sec));
+		},
+		function testSecure_RoundTrip4(t){
+			t.is(message, roundTrip(message, keys["1024f4"], sec));
+		}
+/*
+		// generate a key + round-trip using simple rng
+		function testSimple_GenRT_512e3(t){
+			var key = generateKey(512, "3");
+			t.is(message, roundTrip(message, key));
+		},
+		function testSimple_GenRT_512f4(t){
+			var key = generateKey(512, "10001");
+			t.is(message, roundTrip(message, key));
+		},
+		function testSimple_GenRT_1024e3(t){
+			var key = generateKey(1024, "3");
+			t.is(message, roundTrip(message, key));
+		},
+		function testSimple_GenRT_1024f4(t){
+			var key = generateKey(1024, "10001");
+			t.is(message, roundTrip(message, key));
+		},
+		// generate a key + round-trip using secure rng
+		function testSecure_GenRT_512e3(t){
+			var key = generateKey(512, "3", sec);
+			t.is(message, roundTrip(message, key, sec));
+		},
+		function testSecure_GenRT_512f4(t){
+			var key = generateKey(512, "10001", sec);
+			t.is(message, roundTrip(message, key, sec));
+		},
+		function testSecure_GenRT_1024e3(t){
+			var key = generateKey(1024, "3", sec);
+			t.is(message, roundTrip(message, key, sec));
+		},
+		function testSecure_GenRT_1024f4(t){
+			var key = generateKey(1024, "10001", sec);
+			t.is(message, roundTrip(message, key, sec));
+		}
+*/
+	]);
+})();
diff --git a/dojox/encoding/tests/crypto/SimpleAES.js b/dojox/encoding/tests/crypto/SimpleAES.js
new file mode 100644
index 0000000..8a8e6cb
--- /dev/null
+++ b/dojox/encoding/tests/crypto/SimpleAES.js
@@ -0,0 +1,20 @@
+dojo.provide("dojox.encoding.tests.crypto.SimpleAES");
+dojo.require("dojox.encoding.crypto.SimpleAES");
+
+(function(){
+	var message="The rain in Spain falls mainly on the plain.";
+	var key="foo-bar-baz";
+	var enc = null;
+	var dxc=dojox.encoding.crypto;
+
+	tests.register("dojox.encoding.crypto.tests.SimpleAES", [
+		function testAES(t){
+			var dt = new Date();
+			enc = dxc.SimpleAES.encrypt(message, key);
+			doh.debug("Encrypt: ", new Date()-dt, "ms.");
+			var dt2 = new Date();
+			t.assertEqual(message, dxc.SimpleAES.decrypt(enc, key));
+			doh.debug("Decrypt: ", new Date()-dt2, "ms.");
+		}
+	]);
+})();
diff --git a/dojox/encoding/tests/crypto/_base.js b/dojox/encoding/tests/crypto/_base.js
new file mode 100644
index 0000000..11b4c3b
--- /dev/null
+++ b/dojox/encoding/tests/crypto/_base.js
@@ -0,0 +1,10 @@
+dojo.provide("dojox.encoding.tests.crypto._base");
+dojo.require("dojox.encoding.crypto.Blowfish");
+
+try{
+	dojo.require("dojox.encoding.tests.crypto.Blowfish");
+	dojo.require("dojox.encoding.tests.crypto.SimpleAES");
+	dojo.require("dojox.encoding.tests.crypto.RSA");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/encoding/tests/crypto/runTests.html b/dojox/encoding/tests/crypto/runTests.html
new file mode 100644
index 0000000..31e54ed
--- /dev/null
+++ b/dojox/encoding/tests/crypto/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox.wire Unit Test Runner</title>
+	<meta http-equiv="REFRESH" content="0;url=../../../../util/doh/runner.html?testModule=dojox.encoding.tests.crypto._base"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/encoding/tests/digests/MD5.js b/dojox/encoding/tests/digests/MD5.js
new file mode 100644
index 0000000..085abb5
--- /dev/null
+++ b/dojox/encoding/tests/digests/MD5.js
@@ -0,0 +1,22 @@
+dojo.provide("dojox.encoding.tests.digests.MD5");
+dojo.require("dojox.encoding.digests.MD5");
+
+(function(){
+	var message="The rain in Spain falls mainly on the plain.";
+	var base64="OUhxbVZ1Mtmu4zx9LzS5cA==";
+	var hex="3948716d567532d9aee33c7d2f34b970";
+	var s="9HqmVu2\xD9\xAE\xE3<}/4\xB9p";
+	var ded=dojox.encoding.digests;
+
+	tests.register("dojox.encoding.tests.digests.MD5", [
+		function testBase64Compute(t){
+			t.assertEqual(base64, ded.MD5(message));
+		},
+		function testHexCompute(t){
+			t.assertEqual(hex, ded.MD5(message, ded.outputTypes.Hex)); 
+		},
+		function testStringCompute(t){
+			t.assertEqual(s, ded.MD5(message, ded.outputTypes.String)); 
+		}
+	]);
+})();
diff --git a/dojox/encoding/tests/digests/SHA1.js b/dojox/encoding/tests/digests/SHA1.js
new file mode 100644
index 0000000..45bd42a
--- /dev/null
+++ b/dojox/encoding/tests/digests/SHA1.js
@@ -0,0 +1,22 @@
+dojo.provide("dojox.encoding.tests.digests.SHA1");
+dojo.require("dojox.encoding.digests.SHA1");
+
+(function(){
+	var message="abc";
+	var base64="qZk+NkcGgWq6PiVxeFDCbJzQ2J0=";
+	var hex="a9993e364706816aba3e25717850c26c9cd0d89d";
+	var s="\251\231\76\66\107\6\201\152\272\76\45\161\170\120\302\154\234\320\330\235";
+	var ded=dojox.encoding.digests;
+
+	tests.register("dojox.encoding.tests.digests.SHA1", [
+		function testBase64Compute(t){
+			t.assertEqual(base64, ded.SHA1(message));
+		},
+		function testHexCompute(t){
+			t.assertEqual(hex, ded.SHA1(message, ded.outputTypes.Hex)); 
+		},
+		function testStringCompute(t){
+			t.assertEqual(s, ded.SHA1(message, ded.outputTypes.String)); 
+		}
+	]);
+})();
diff --git a/dojox/encoding/tests/digests/_base.js b/dojox/encoding/tests/digests/_base.js
new file mode 100644
index 0000000..5baecc3
--- /dev/null
+++ b/dojox/encoding/tests/digests/_base.js
@@ -0,0 +1,9 @@
+dojo.provide("dojox.encoding.tests.digests._base");
+dojo.require("dojox.encoding.digests._base");
+
+try{
+	dojo.require("dojox.encoding.tests.digests.MD5");
+	dojo.require("dojox.encoding.tests.digests.SHA1");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/encoding/tests/digests/runTests.html b/dojox/encoding/tests/digests/runTests.html
new file mode 100644
index 0000000..6c41e6e
--- /dev/null
+++ b/dojox/encoding/tests/digests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+		<title>Dojox.wire Unit Test Runner</title>
+		<meta http-equiv="REFRESH" content="0;url=../../../../util/doh/runner.html?testModule=dojox.encoding.tests.digests._base"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/encoding/tests/easy64.js b/dojox/encoding/tests/easy64.js
new file mode 100644
index 0000000..6d23c66
--- /dev/null
+++ b/dojox/encoding/tests/easy64.js
@@ -0,0 +1,31 @@
+dojo.provide("dojox.encoding.tests.easy64");
+dojo.require("dojox.encoding.easy64");
+
+(function(){
+	var msg1 = "The rain in Spain falls mainly on the plain.";
+	var msg2 = "The rain in Spain falls mainly on the plain.1";
+	var msg3 = "The rain in Spain falls mainly on the plain.ab";
+	var msg4 = "The rain in Spain falls mainly on the plain.!@#";
+	var dce = dojox.encoding.easy64;
+	
+	var s2b = function(s){
+		var b = [];
+		for(var i = 0; i < s.length; ++i){
+			b.push(s.charCodeAt(i));
+		}
+		return b;
+	};
+
+	var b2s = function(b){
+		var s = [];
+		dojo.forEach(b, function(c){ s.push(String.fromCharCode(c)); });
+		return s.join("");
+	};
+
+	tests.register("dojox.encoding.tests.easy64", [
+		function testEasyMsg1(t){ t.assertEqual(msg1, b2s(dce.decode(dce.encode(s2b(msg1))))); },
+		function testEasyMsg2(t){ t.assertEqual(msg2, b2s(dce.decode(dce.encode(s2b(msg2))))); },
+		function testEasyMsg3(t){ t.assertEqual(msg3, b2s(dce.decode(dce.encode(s2b(msg3))))); },
+		function testEasyMsg4(t){ t.assertEqual(msg4, b2s(dce.decode(dce.encode(s2b(msg4))))); }
+	]);
+})();
diff --git a/dojox/encoding/tests/encoding.js b/dojox/encoding/tests/encoding.js
new file mode 100644
index 0000000..b2987fc
--- /dev/null
+++ b/dojox/encoding/tests/encoding.js
@@ -0,0 +1,9 @@
+dojo.provide("dojox.encoding.tests.encoding");
+
+try{
+	dojo.require("dojox.encoding.tests.ascii85");
+	dojo.require("dojox.encoding.tests.easy64");
+	dojo.require("dojox.encoding.tests.bits");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/encoding/tests/runTests.html b/dojox/encoding/tests/runTests.html
new file mode 100644
index 0000000..1200378
--- /dev/null
+++ b/dojox/encoding/tests/runTests.html
@@ -0,0 +1,9 @@
+<html>
+	<head>
+		<title>DojoX Compression Unit Test Runner</title>
+	    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.encoding.tests.encoding" />
+	</head>
+	<body>
+		<p>Redirecting to D.O.H runner.</p>	
+	</body>
+</html>
diff --git a/dojox/flash.js b/dojox/flash.js
index 147438c..84657ae 100644
--- a/dojox/flash.js
+++ b/dojox/flash.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.flash"]){
-dojo._hasResource["dojox.flash"]=true;
 dojo.provide("dojox.flash");
 dojo.require("dojox.flash._base");
-}
diff --git a/dojox/flash/_base.js b/dojox/flash/_base.js
index 8557a2d..8d9cd0f 100644
--- a/dojox/flash/_base.js
+++ b/dojox/flash/_base.js
@@ -1,299 +1,761 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.flash._base"]){
-dojo._hasResource["dojox.flash._base"]=true;
 dojo.provide("dojox.flash._base");
 dojo.experimental("dojox.flash");
-dojo.require("dijit._base.place");
-dojox.flash=function(){
-};
-dojox.flash={ready:false,url:null,_visible:true,_loadedListeners:[],_installingListeners:[],setSwf:function(_1,_2){
-this.url=_1;
-this._visible=true;
-if(_2!==null&&_2!==undefined){
-this._visible=_2;
-}
-this._initialize();
-},addLoadedListener:function(_3){
-this._loadedListeners.push(_3);
-},addInstallingListener:function(_4){
-this._installingListeners.push(_4);
-},loaded:function(){
-dojox.flash.ready=true;
-if(dojox.flash._loadedListeners.length){
-for(var i=0;i<dojox.flash._loadedListeners.length;i++){
-dojox.flash._loadedListeners[i].call(null);
-}
-}
-},installing:function(){
-if(dojox.flash._installingListeners.length){
-for(var i=0;i<dojox.flash._installingListeners.length;i++){
-dojox.flash._installingListeners[i].call(null);
-}
-}
-},_initialize:function(){
-var _5=new dojox.flash.Install();
-dojox.flash.installer=_5;
-if(_5.needed()){
-_5.install();
-}else{
-dojox.flash.obj=new dojox.flash.Embed(this._visible);
-dojox.flash.obj.write();
-dojox.flash.comm=new dojox.flash.Communicator();
-}
-}};
-dojox.flash.Info=function(){
-this._detectVersion();
-};
-dojox.flash.Info.prototype={version:-1,versionMajor:-1,versionMinor:-1,versionRevision:-1,capable:false,installing:false,isVersionOrAbove:function(_6,_7,_8){
-_8=parseFloat("."+_8);
-if(this.versionMajor>=_6&&this.versionMinor>=_7&&this.versionRevision>=_8){
-return true;
-}else{
-return false;
-}
-},_detectVersion:function(){
-var _9;
-for(var _a=25;_a>0;_a--){
-if(dojo.isIE){
-var _b;
-try{
-if(_a>6){
-_b=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_a);
-}else{
-_b=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
-}
-if(typeof _b=="object"){
-if(_a==6){
-_b.AllowScriptAccess="always";
-}
-_9=_b.GetVariable("$version");
-}
-}
-catch(e){
-continue;
-}
-}else{
-_9=this._JSFlashInfo(_a);
-}
-if(_9==-1){
-this.capable=false;
-return;
-}else{
-if(_9!=0){
-var _c;
-if(dojo.isIE){
-var _d=_9.split(" ");
-var _e=_d[1];
-_c=_e.split(",");
-}else{
-_c=_9.split(".");
-}
-this.versionMajor=_c[0];
-this.versionMinor=_c[1];
-this.versionRevision=_c[2];
-var _f=this.versionMajor+"."+this.versionRevision;
-this.version=parseFloat(_f);
-this.capable=true;
-break;
-}
-}
-}
-},_JSFlashInfo:function(_10){
-if(navigator.plugins!=null&&navigator.plugins.length>0){
-if(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]){
-var _11=navigator.plugins["Shockwave Flash 2.0"]?" 2.0":"";
-var _12=navigator.plugins["Shockwave Flash"+_11].description;
-var _13=_12.split(" ");
-var _14=_13[2].split(".");
-var _15=_14[0];
-var _16=_14[1];
-var _17=(_13[3]||_13[4]).split("r");
-var _18=_17[1]>0?_17[1]:0;
-var _19=_15+"."+_16+"."+_18;
-return _19;
-}
-}
-return -1;
-}};
-dojox.flash.Embed=function(_1a){
-this._visible=_1a;
-};
-dojox.flash.Embed.prototype={width:215,height:138,id:"flashObject",_visible:true,protocol:function(){
-switch(window.location.protocol){
-case "https:":
-return "https";
-break;
-default:
-return "http";
-break;
-}
-},write:function(_1b){
-var _1c;
-var _1d=dojox.flash.url;
-var _1e=_1d;
-var _1f=_1d;
-var _20=dojo.baseUrl;
-var _21=document.location.protocol+"//"+document.location.host;
-if(_1b){
-var _22=escape(window.location);
-document.title=document.title.slice(0,47)+" - Flash Player Installation";
-var _23=escape(document.title);
-_1e+="?MMredirectURL="+_22+"&MMplayerType=ActiveX"+"&MMdoctitle="+_23+"&baseUrl="+escape(_20)+"&xdomain="+escape(_21);
-_1f+="?MMredirectURL="+_22+"&MMplayerType=PlugIn"+"&baseUrl="+escape(_20)+"&xdomain="+escape(_21);
-}else{
-_1e+="?cachebust="+new Date().getTime();
-_1e+="&baseUrl="+escape(_20);
-_1e+="&xdomain="+escape(_21);
-}
-if(_1f.indexOf("?")==-1){
-_1f+="?baseUrl="+escape(_20);
-}else{
-_1f+="&baseUrl="+escape(_20);
-}
-_1f+="&xdomain="+escape(_21);
-_1c="<object classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" "+"codebase=\""+this.protocol()+"://fpdownload.macromedia.com/pub/shockwave/cabs/flash/"+"swflash.cab#version=8,0,0,0\"\n "+"width=\""+this.width+"\"\n "+"height=\""+this.height+"\"\n "+"id=\""+this.id+"\"\n "+"name=\""+this.id+"\"\n "+"align=\"middle\">\n "+"<param name=\"allowScriptAccess\" value=\"always\"></param>\n "+"<param name=\"movie\" value=\""+_1e+"\"></param>\n "+"<param name=\"quality\" value=\"high\"></para [...]
-dojo.connect(dojo,"loaded",dojo.hitch(this,function(){
-var _24=this.id+"Container";
-if(dojo.byId(_24)){
-return;
-}
-var div=document.createElement("div");
-div.id=this.id+"Container";
-div.style.width=this.width+"px";
-div.style.height=this.height+"px";
-if(!this._visible){
-div.style.position="absolute";
-div.style.zIndex="10000";
-div.style.top="-1000px";
-}
-div.innerHTML=_1c;
-var _25=document.getElementsByTagName("body");
-if(!_25||!_25.length){
-throw new Error("No body tag for this page");
-}
-_25=_25[0];
-_25.appendChild(div);
-}));
-},get:function(){
-if(dojo.isIE||dojo.isWebKit){
-return dojo.byId(this.id);
-}else{
-return document[this.id+"Embed"];
-}
-},setVisible:function(_26){
-var _27=dojo.byId(this.id+"Container");
-if(_26){
-_27.style.position="absolute";
-_27.style.visibility="visible";
-}else{
-_27.style.position="absolute";
-_27.style.y="-1000px";
-_27.style.visibility="hidden";
+
+// for dojo.window.getBox(), needed by dojox.flash.Embed.center()
+dojo.require("dojo.window");
+
+dojox.flash = function(){
+	// summary:
+	//	Utilities to embed and communicate with the Flash player from Javascript
+	//
+	// description:
+	//	The goal of dojox.flash is to make it easy to extend Flash's capabilities
+	//	into an Ajax/DHTML environment.
+	//  
+	//	dojox.flash provides an easy object for interacting with the Flash plugin. 
+	//	This object provides methods to determine the current version of the Flash
+	//	plugin (dojox.flash.info); write out the necessary markup to 
+	//	dynamically insert a Flash object into the page (dojox.flash.Embed; and 
+	//	do dynamic installation and upgrading of the current Flash plugin in 
+	//	use (dojox.flash.Install). If you want to call methods on the Flash object
+	//	embedded into the page it is your responsibility to use Flash's ExternalInterface
+	//	API and get a reference to the Flash object yourself.
+	//		
+	//	To use dojox.flash, you must first wait until Flash is finished loading 
+	//	and initializing before you attempt communication or interaction. 
+	//	To know when Flash is finished use dojo.connect:
+	//		
+	//|	dojo.connect(dojox.flash, "loaded", myInstance, "myCallback");
+	//		
+	//	Then, while the page is still loading provide the file name:
+	//		
+	//|	dojox.flash.setSwf(dojo.moduleUrl("dojox", "_storage/storage.swf"));
+	//			
+	//	If no SWF files are specified, then Flash is not initialized.
+	//		
+	//	Your Flash must use Flash's ExternalInterface to expose Flash methods and
+	//	to call JavaScript.
+	//		
+	//	setSwf can take an optional 'visible' attribute to control whether
+	//	the Flash object is visible or not on the page; the default is visible:
+	//		
+	//|	dojox.flash.setSwf(dojo.moduleUrl("dojox", "_storage/storage.swf"),
+	//						false);
+	//		
+	//	Once finished, you can query Flash version information:
+	//		
+	//|	dojox.flash.info.version
+	//		
+	//	Or can communicate with Flash methods that were exposed:	
+	//
+	//|	var f = dojox.flash.get();
+	//|	var results = f.sayHello("Some Message");	
+	// 
+	//	Your Flash files should use DojoExternalInterface.as to register methods;
+	//	this file wraps Flash's normal ExternalInterface but correct various
+	//	serialization bugs that ExternalInterface has.
+	//
+	//	Note that dojox.flash is not meant to be a generic Flash embedding
+	//	mechanism; it is as generic as necessary to make Dojo Storage's
+	//	Flash Storage Provider as clean and modular as possible. If you want 
+	//	a generic Flash embed mechanism see [SWFObject](http://blog.deconcept.com/swfobject/).
+	//
+	// 	Notes:
+	//	Note that dojox.flash can currently only work with one Flash object
+	//	on the page; it does not yet support multiple Flash objects on
+	//	the same page. 
+	//		
+	//	Your code can detect whether the Flash player is installing or having
+	//	its version revved in two ways. First, if dojox.flash detects that
+	//	Flash installation needs to occur, it sets dojox.flash.info.installing
+	//	to true. Second, you can detect if installation is necessary with the
+	//	following callback:
+	//		
+	//|	dojo.connect(dojox.flash, "installing", myInstance, "myCallback");
+	//		
+	//	You can use this callback to delay further actions that might need Flash;
+	//	when installation is finished the full page will be refreshed and the
+	//	user will be placed back on your page with Flash installed.
+	//		
+	//	-------------------
+	//	Todo/Known Issues
+	//	-------------------
+	//
+	//	* On Internet Explorer, after doing a basic install, the page is
+	//	not refreshed or does not detect that Flash is now available. The way
+	//	to fix this is to create a custom small Flash file that is pointed to
+	//	during installation; when it is finished loading, it does a callback
+	//	that says that Flash installation is complete on IE, and we can proceed
+	//	to initialize the dojox.flash subsystem.
+	//	* Things aren't super tested for sending complex objects to Flash
+	//	methods, since Dojo Storage only needs strings
+	//		
+	//	Author- Brad Neuberg, http://codinginparadise.org
 }
-},center:function(){
-var _28=this.width;
-var _29=this.height;
-var _2a=dijit.getViewport();
-var x=_2a.l+(_2a.w-_28)/2;
-var y=_2a.t+(_2a.h-_29)/2;
-var _2b=dojo.byId(this.id+"Container");
-_2b.style.top=y+"px";
-_2b.style.left=x+"px";
-}};
-dojox.flash.Communicator=function(){
+
+dojox.flash = {
+	ready: false,
+	url: null,
+	
+	_visible: true,
+	_loadedListeners: [],
+	_installingListeners: [],
+	
+	setSwf: function(/* String */ url, /* boolean? */ visible){
+		// summary: Sets the SWF files and versions we are using.
+		// url: String
+		//	The URL to this Flash file.
+		// visible: boolean?
+		//	Whether the Flash file is visible or not. If it is not visible we hide 
+		//	it off the screen. This defaults to true (i.e. the Flash file is
+		//	visible).
+		this.url = url;
+		
+		this._visible = true;
+		if(visible !== null && visible !== undefined){
+			this._visible = visible;
+		}
+		
+		// initialize ourselves		
+		this._initialize();
+	},
+	
+	addLoadedListener: function(/* Function */ listener){
+		// summary:
+		//	Adds a listener to know when Flash is finished loading. 
+		//	Useful if you don't want a dependency on dojo.event.
+		// listener: Function
+		//	A function that will be called when Flash is done loading.
+		
+		this._loadedListeners.push(listener);
+	},
+
+	addInstallingListener: function(/* Function */ listener){
+		// summary:
+		//	Adds a listener to know if Flash is being installed. 
+		//	Useful if you don't want a dependency on dojo.event.
+		// listener: Function
+		//	A function that will be called if Flash is being
+		//	installed
+		
+		this._installingListeners.push(listener);
+	},	
+	
+	loaded: function(){
+		// summary: Called back when the Flash subsystem is finished loading.
+		// description:
+		//	A callback when the Flash subsystem is finished loading and can be
+		//	worked with. To be notified when Flash is finished loading, add a
+		//  loaded listener: 
+		//
+		//  dojox.flash.addLoadedListener(loadedListener);
+	
+		dojox.flash.ready = true;
+		if(dojox.flash._loadedListeners.length){ // FIXME: redundant if? use forEach?
+			for(var i = 0;i < dojox.flash._loadedListeners.length; i++){
+				dojox.flash._loadedListeners[i].call(null);
+			}
+		}
+	},
+	
+	installing: function(){
+		// summary: Called if Flash is being installed.
+		// description:
+		//	A callback to know if Flash is currently being installed or
+		//	having its version revved. To be notified if Flash is installing, connect
+		//	your callback to this method using the following:
+		//	
+		//	dojo.event.connect(dojox.flash, "installing", myInstance, "myCallback");
+		
+		if(dojox.flash._installingListeners.length){ // FIXME: redundant if? use forEach?
+			for(var i = 0; i < dojox.flash._installingListeners.length; i++){
+				dojox.flash._installingListeners[i].call(null);
+			}
+		}
+	},
+	
+	// Initializes dojox.flash.
+	_initialize: function(){
+		//console.debug("dojox.flash._initialize");
+		// see if we need to rev or install Flash on this platform
+		var installer = new dojox.flash.Install();
+		dojox.flash.installer = installer;
+
+		if(installer.needed()){		
+			installer.install();
+		}else{
+			// write the flash object into the page
+			dojox.flash.obj = new dojox.flash.Embed(this._visible);
+			dojox.flash.obj.write();
+			
+			// setup the communicator
+			dojox.flash.comm = new dojox.flash.Communicator();
+		}
+	}
 };
-dojox.flash.Communicator.prototype={_addExternalInterfaceCallback:function(_2c){
-var _2d=dojo.hitch(this,function(){
-var _2e=new Array(arguments.length);
-for(var i=0;i<arguments.length;i++){
-_2e[i]=this._encodeData(arguments[i]);
-}
-var _2f=this._execFlash(_2c,_2e);
-_2f=this._decodeData(_2f);
-return _2f;
-});
-this[_2c]=_2d;
-},_encodeData:function(_30){
-if(!_30||typeof _30!="string"){
-return _30;
-}
-_30=_30.replace("\\","&custom_backslash;");
-_30=_30.replace(/\0/g,"&custom_null;");
-return _30;
-},_decodeData:function(_31){
-if(_31&&_31.length&&typeof _31!="string"){
-_31=_31[0];
-}
-if(!_31||typeof _31!="string"){
-return _31;
-}
-_31=_31.replace(/\&custom_null\;/g,"\x00");
-_31=_31.replace(/\&custom_lt\;/g,"<").replace(/\&custom_gt\;/g,">").replace(/\&custom_backslash\;/g,"\\");
-return _31;
-},_execFlash:function(_32,_33){
-var _34=dojox.flash.obj.get();
-_33=(_33)?_33:[];
-for(var i=0;i<_33;i++){
-if(typeof _33[i]=="string"){
-_33[i]=this._encodeData(_33[i]);
-}
+
+
+dojox.flash.Info = function(){
+	// summary: A class that helps us determine whether Flash is available.
+	// description:
+	//	A class that helps us determine whether Flash is available,
+	//	it's major and minor versions, and what Flash version features should
+	//	be used for Flash/JavaScript communication. Parts of this code
+	//	are adapted from the automatic Flash plugin detection code autogenerated 
+	//	by the Macromedia Flash 8 authoring environment. 
+	//	
+	//	An instance of this class can be accessed on dojox.flash.info after
+	//	the page is finished loading.
+
+	this._detectVersion();
 }
-var _35=function(){
-return eval(_34.CallFunction("<invoke name=\""+_32+"\" returntype=\"javascript\">"+__flash__argumentsToXML(_33,0)+"</invoke>"));
+
+dojox.flash.Info.prototype = {
+	// version: String
+	//		The full version string, such as "8r22".
+	version: -1,
+	
+	// versionMajor, versionMinor, versionRevision: String
+	//		The major, minor, and revisions of the plugin. For example, if the
+	//		plugin is 8r22, then the major version is 8, the minor version is 0,
+	//		and the revision is 22. 
+	versionMajor: -1,
+	versionMinor: -1,
+	versionRevision: -1,
+	
+	// capable: Boolean
+	//		Whether this platform has Flash already installed.
+	capable: false,
+	
+	// installing: Boolean
+	//	Set if we are in the middle of a Flash installation session.
+	installing: false,
+	
+	isVersionOrAbove: function(
+							/* int */ reqMajorVer, 
+							/* int */ reqMinorVer, 
+							/* int */ reqVer){ /* Boolean */
+		// summary: 
+		//	Asserts that this environment has the given major, minor, and revision
+		//	numbers for the Flash player.
+		// description:
+		//	Asserts that this environment has the given major, minor, and revision
+		//	numbers for the Flash player. 
+		//	
+		//	Example- To test for Flash Player 7r14:
+		//	
+		//	dojox.flash.info.isVersionOrAbove(7, 0, 14)
+		// returns:
+		//	Returns true if the player is equal
+		//	or above the given version, false otherwise.
+		
+		// make the revision a decimal (i.e. transform revision 14 into
+		// 0.14
+		reqVer = parseFloat("." + reqVer);
+		
+		if(this.versionMajor >= reqMajorVer && this.versionMinor >= reqMinorVer
+			 && this.versionRevision >= reqVer){
+			return true;
+		}else{
+			return false;
+		}
+	},
+	
+	_detectVersion: function(){
+		var versionStr;
+		
+		// loop backwards through the versions until we find the newest version	
+		for(var testVersion = 25; testVersion > 0; testVersion--){
+			if(dojo.isIE){
+				var axo;
+				try{
+					if(testVersion > 6){
+						axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." 
+																		+ testVersion);
+					}else{
+						axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
+					}
+					if(typeof axo == "object"){
+						if(testVersion == 6){
+							axo.AllowScriptAccess = "always";
+						}
+						versionStr = axo.GetVariable("$version");
+					}
+				}catch(e){
+					continue;
+				}
+			}else{
+				versionStr = this._JSFlashInfo(testVersion);		
+			}
+				
+			if(versionStr == -1 ){
+				this.capable = false; 
+				return;
+			}else if(versionStr != 0){
+				var versionArray;
+				if(dojo.isIE){
+					var tempArray = versionStr.split(" ");
+					var tempString = tempArray[1];
+					versionArray = tempString.split(",");
+				}else{
+					versionArray = versionStr.split(".");
+				}
+					
+				this.versionMajor = versionArray[0];
+				this.versionMinor = versionArray[1];
+				this.versionRevision = versionArray[2];
+				
+				// 7.0r24 == 7.24
+				var versionString = this.versionMajor + "." + this.versionRevision;
+				this.version = parseFloat(versionString);
+				
+				this.capable = true;
+				
+				break;
+			}
+		}
+	},
+	 
+	// JavaScript helper required to detect Flash Player PlugIn version 
+	// information. Internet Explorer uses a corresponding Visual Basic
+	// version to interact with the Flash ActiveX control. 
+	_JSFlashInfo: function(testVersion){
+		// NS/Opera version >= 3 check for Flash plugin in plugin array
+		if(navigator.plugins != null && navigator.plugins.length > 0){
+			if(navigator.plugins["Shockwave Flash 2.0"] || 
+				 navigator.plugins["Shockwave Flash"]){
+				var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
+				var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
+				var descArray = flashDescription.split(" ");
+				var tempArrayMajor = descArray[2].split(".");
+				var versionMajor = tempArrayMajor[0];
+				var versionMinor = tempArrayMajor[1];
+				var tempArrayMinor = (descArray[3] || descArray[4]).split("r");
+				var versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
+				var version = versionMajor + "." + versionMinor + "." + versionRevision;
+											
+				return version;
+			}
+		}
+		
+		return -1;
+	}
 };
-var _36=_35.call(_33);
-if(typeof _36=="string"){
-_36=this._decodeData(_36);
+
+dojox.flash.Embed = function(visible){
+	// summary: A class that is used to write out the Flash object into the page.
+	// description:
+	//	Writes out the necessary tags to embed a Flash file into the page. Note that
+	//	these tags are written out as the page is loaded using document.write, so
+	//	you must call this class before the page has finished loading.
+	
+	this._visible = visible;
 }
-return _36;
-}};
-dojox.flash.Install=function(){
+
+dojox.flash.Embed.prototype = {
+	// width: int
+	//	The width of this Flash applet. The default is the minimal width
+	//	necessary to show the Flash settings dialog. Current value is 
+	//  215 pixels.
+	width: 215,
+	
+	// height: int 
+	//	The height of this Flash applet. The default is the minimal height
+	//	necessary to show the Flash settings dialog. Current value is
+	// 138 pixels.
+	height: 138,
+	
+	// id: String
+	// 	The id of the Flash object. Current value is 'flashObject'.
+	id: "flashObject",
+	
+	// Controls whether this is a visible Flash applet or not.
+	_visible: true,
+
+	protocol: function(){
+		switch(window.location.protocol){
+			case "https:":
+				return "https";
+				break;
+			default:
+				return "http";
+				break;
+		}
+	},
+	
+	write: function(/* Boolean? */ doExpressInstall){
+		// summary: Writes the Flash into the page.
+		// description:
+		//	This must be called before the page
+		//	is finished loading. 
+		// doExpressInstall: Boolean
+		//	Whether to write out Express Install
+		//	information. Optional value; defaults to false.
+		
+		// figure out the SWF file to get and how to write out the correct HTML
+		// for this Flash version
+		var objectHTML;
+		var swfloc = dojox.flash.url;
+		var swflocObject = swfloc;
+		var swflocEmbed = swfloc;
+		var dojoUrl = dojo.baseUrl;
+		var xdomainBase = document.location.protocol + '//' + document.location.host;
+		if(doExpressInstall){
+			// the location to redirect to after installing
+			var redirectURL = escape(window.location);
+			document.title = document.title.slice(0, 47) + " - Flash Player Installation";
+			var docTitle = escape(document.title);
+			swflocObject += "?MMredirectURL=" + redirectURL
+			                + "&MMplayerType=ActiveX"
+			                + "&MMdoctitle=" + docTitle
+			                + "&baseUrl=" + escape(dojoUrl)
+			                + "&xdomain=" + escape(xdomainBase);
+			swflocEmbed += "?MMredirectURL=" + redirectURL 
+			                + "&MMplayerType=PlugIn"
+			                + "&baseUrl=" + escape(dojoUrl)
+			                + "&xdomain=" + escape(xdomainBase);
+		}else{
+			// IE/Flash has an evil bug that shows up some time: if we load the
+			// Flash and it isn't in the cache, ExternalInterface works fine --
+			// however, the second time when its loaded from the cache a timing
+			// bug can keep ExternalInterface from working. The trick below 
+			// simply invalidates the Flash object in the cache all the time to
+			// keep it loading fresh. -- Brad Neuberg
+			swflocObject += "?cachebust=" + new Date().getTime();
+			swflocObject += "&baseUrl=" + escape(dojoUrl);
+			swflocObject += "&xdomain=" + escape(xdomainBase);
+		}
+
+		if(swflocEmbed.indexOf("?") == -1){
+			swflocEmbed += '?baseUrl='+escape(dojoUrl);
+		}else{
+		  swflocEmbed += '&baseUrl='+escape(dojoUrl);
+		}
+		swflocEmbed += '&xdomain='+escape(xdomainBase);
+		
+		objectHTML =
+			'<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '
+			  + 'codebase="'
+				+ this.protocol()
+				+ '://fpdownload.macromedia.com/pub/shockwave/cabs/flash/'
+				+ 'swflash.cab#version=8,0,0,0"\n '
+			  + 'width="' + this.width + '"\n '
+			  + 'height="' + this.height + '"\n '
+			  + 'id="' + this.id + '"\n '
+			  + 'name="' + this.id + '"\n '
+			  + 'align="middle">\n '
+			  + '<param name="allowScriptAccess" value="always"></param>\n '
+			  + '<param name="movie" value="' + swflocObject + '"></param>\n '
+			  + '<param name="quality" value="high"></param>\n '
+			  + '<param name="bgcolor" value="#ffffff"></param>\n '
+			  + '<embed src="' + swflocEmbed + '" '
+			  	  + 'quality="high" '
+				  + 'bgcolor="#ffffff" '
+				  + 'width="' + this.width + '" '
+				  + 'height="' + this.height + '" '
+				  + 'id="' + this.id + 'Embed' + '" '
+				  + 'name="' + this.id + '" '
+				  + 'swLiveConnect="true" '
+				  + 'align="middle" '
+				  + 'allowScriptAccess="always" '
+				  + 'type="application/x-shockwave-flash" '
+				  + 'pluginspage="'
+				  + this.protocol()
+				  +'://www.macromedia.com/go/getflashplayer" '
+				  + '></embed>\n'
+			+ '</object>\n';
+					
+		// using same mechanism on all browsers now to write out
+		// Flash object into page
+
+		// document.write no longer works correctly due to Eolas patent workaround
+		// in IE; nothing happens (i.e. object doesn't go into page if we use it)
+		dojo.connect(dojo, "loaded", dojo.hitch(this, function(){
+			// Prevent putting duplicate SWFs onto the page
+			var containerId = this.id + "Container";
+			if(dojo.byId(containerId)){
+				return;
+			}
+			
+			var div = document.createElement("div");
+			div.id = this.id + "Container";
+			
+			div.style.width = this.width + "px";
+			div.style.height = this.height + "px";
+			if(!this._visible){
+				div.style.position = "absolute";
+				div.style.zIndex = "10000";
+				div.style.top = "-1000px";
+			}
+
+			div.innerHTML = objectHTML;
+
+			var body = document.getElementsByTagName("body");
+			if(!body || !body.length){
+				throw new Error("No body tag for this page");
+			}
+			body = body[0];
+			body.appendChild(div);
+		}));
+	},  
+	
+	get: function(){ /* Object */
+		// summary: Gets the Flash object DOM node.
+
+		if(dojo.isIE || dojo.isWebKit){
+			//TODO: should this really be the else?
+			return dojo.byId(this.id);
+		}else{
+			// different IDs on OBJECT and EMBED tags or
+			// else Firefox will return wrong one and
+			// communication won't work; 
+			// also, document.getElementById() returns a
+			// plugin but ExternalInterface calls don't
+			// work on it so we have to use
+			// document[id] instead
+			return document[this.id + "Embed"];
+		}
+	},
+	
+	setVisible: function(/* Boolean */ visible){
+		//console.debug("setVisible, visible="+visible);
+		
+		// summary: Sets the visibility of this Flash object.		
+		var container = dojo.byId(this.id + "Container");
+		if(visible){
+			container.style.position = "absolute"; // IE -- Brad Neuberg
+			container.style.visibility = "visible";
+		}else{
+			container.style.position = "absolute";
+			container.style.y = "-1000px";
+			container.style.visibility = "hidden";
+		}
+	},
+	
+	center: function(){
+		// summary: Centers the flash applet on the page.
+		
+		var elementWidth = this.width;
+		var elementHeight = this.height;
+
+		var viewport = dojo.window.getBox();
+
+		// compute the centered position    
+		var x = viewport.l + (viewport.w - elementWidth) / 2;
+		var y = viewport.t + (viewport.h - elementHeight) / 2; 
+		
+		// set the centered position
+		var container = dojo.byId(this.id + "Container");
+		container.style.top = y + "px";
+		container.style.left = x + "px";
+	}
 };
-dojox.flash.Install.prototype={needed:function(){
-if(!dojox.flash.info.capable){
-return true;
-}
-if(!dojox.flash.info.isVersionOrAbove(8,0,0)){
-return true;
-}
-return false;
-},install:function(){
-var _37;
-dojox.flash.info.installing=true;
-dojox.flash.installing();
-if(dojox.flash.info.capable==false){
-_37=new dojox.flash.Embed(false);
-_37.write();
-}else{
-if(dojox.flash.info.isVersionOrAbove(6,0,65)){
-_37=new dojox.flash.Embed(false);
-_37.write(true);
-_37.setVisible(true);
-_37.center();
-}else{
-alert("This content requires a more recent version of the Macromedia "+" Flash Player.");
-window.location.href=+dojox.flash.Embed.protocol()+"://www.macromedia.com/go/getflashplayer";
-}
-}
-},_onInstallStatus:function(msg){
-if(msg=="Download.Complete"){
-dojox.flash._initialize();
-}else{
-if(msg=="Download.Cancelled"){
-alert("This content requires a more recent version of the Macromedia "+" Flash Player.");
-window.location.href=dojox.flash.Embed.protocol()+"://www.macromedia.com/go/getflashplayer";
-}else{
-if(msg=="Download.Failed"){
-alert("There was an error downloading the Flash Player update. "+"Please try again later, or visit macromedia.com to download "+"the latest version of the Flash plugin.");
+
+
+dojox.flash.Communicator = function(){
+	// summary:
+	//	A class that is used to communicate between Flash and JavaScript.
+	// description:
+	//	This class helps mediate Flash and JavaScript communication. Internally
+	//	it uses Flash 8's ExternalInterface API, but adds functionality to fix 
+	//	various encoding bugs that ExternalInterface has.
 }
+
+dojox.flash.Communicator.prototype = {
+	// Registers the existence of a Flash method that we can call with
+	// JavaScript, using Flash 8's ExternalInterface. 
+	_addExternalInterfaceCallback: function(methodName){
+		//console.debug("addExternalInterfaceCallback, methodName="+methodName);
+		var wrapperCall = dojo.hitch(this, function(){
+			// some browsers don't like us changing values in the 'arguments' array, so
+			// make a fresh copy of it
+			var methodArgs = new Array(arguments.length);
+			for(var i = 0; i < arguments.length; i++){
+				methodArgs[i] = this._encodeData(arguments[i]);
+			}
+			
+			var results = this._execFlash(methodName, methodArgs);
+			results = this._decodeData(results);
+			
+			return results;
+		});
+		
+		this[methodName] = wrapperCall;
+	},
+	
+	// Encodes our data to get around ExternalInterface bugs that are still
+	// present even in Flash 9.
+	_encodeData: function(data){
+		//console.debug("encodeData, data=", data);
+		if(!data || typeof data != "string"){
+			return data;
+		}
+		
+		// transforming \ into \\ doesn't work; just use a custom encoding
+		data = data.replace("\\", "&custom_backslash;");
+
+		// also use custom encoding for the null character to avoid problems 
+		data = data.replace(/\0/g, "&custom_null;");
+
+		return data;
+	},
+	
+	// Decodes our data to get around ExternalInterface bugs that are still
+	// present even in Flash 9.
+	_decodeData: function(data){
+		//console.debug("decodeData, data=", data);
+		// wierdly enough, Flash sometimes returns the result as an
+		// 'object' that is actually an array, rather than as a String;
+		// detect this by looking for a length property; for IE
+		// we also make sure that we aren't dealing with a typeof string
+		// since string objects have length property there
+		if(data && data.length && typeof data != "string"){
+			data = data[0];
+		}
+		
+		if(!data || typeof data != "string"){
+			return data;
+		}
+		
+		// needed for IE; \0 is the NULL character 
+		data = data.replace(/\&custom_null\;/g, "\0");
+	
+		// certain XMLish characters break Flash's wire serialization for
+		// ExternalInterface; these are encoded on the 
+		// DojoExternalInterface side into a custom encoding, rather than
+		// the standard entity encoding, because otherwise we won't be able to
+		// differentiate between our own encoding and any entity characters
+		// that are being used in the string itself
+		data = data.replace(/\&custom_lt\;/g, "<")
+			.replace(/\&custom_gt\;/g, ">")
+			.replace(/\&custom_backslash\;/g, '\\');
+		
+		return data;
+	},
+	
+	// Executes a Flash method; called from the JavaScript wrapper proxy we
+	// create on dojox.flash.comm.
+	_execFlash: function(methodName, methodArgs){
+		//console.debug("execFlash, methodName="+methodName+", methodArgs=", methodArgs);
+		var plugin = dojox.flash.obj.get();
+		methodArgs = (methodArgs) ? methodArgs : [];
+		
+		// encode arguments that are strings
+		for(var i = 0; i < methodArgs; i++){
+			if(typeof methodArgs[i] == "string"){
+				methodArgs[i] = this._encodeData(methodArgs[i]);
+			}
+		}
+
+		// we use this gnarly hack below instead of 
+		// plugin[methodName] for two reasons:
+		// 1) plugin[methodName] has no call() method, which
+		// means we can't pass in multiple arguments dynamically
+		// to a Flash method -- we can only have one
+		// 2) On IE plugin[methodName] returns undefined -- 
+		// plugin[methodName] used to work on IE when we
+		// used document.write but doesn't now that
+		// we use dynamic DOM insertion of the Flash object
+		// -- Brad Neuberg
+		var flashExec = function(){ 
+			return eval(plugin.CallFunction(
+						 "<invoke name=\"" + methodName
+						+ "\" returntype=\"javascript\">" 
+						+ __flash__argumentsToXML(methodArgs, 0) 
+						+ "</invoke>")); 
+		};
+		var results = flashExec.call(methodArgs);
+		
+		if(typeof results == "string"){
+			results = this._decodeData(results);
+		}
+			
+		return results;
+	}
 }
+
+// FIXME: dojo.declare()-ify this
+
+// TODO: I did not test the Install code when I refactored Dojo Flash from 0.4 to 
+// 1.0, so am not sure if it works. If Flash is not present I now prefer 
+// that Gears is installed instead of Flash because GearsStorageProvider is
+// much easier to work with than Flash's hacky ExternalInteface. 
+// -- Brad Neuberg
+dojox.flash.Install = function(){
+	// summary: Helps install Flash plugin if needed.
+	// description:
+	//		Figures out the best way to automatically install the Flash plugin
+	//		for this browser and platform. Also determines if installation or
+	//		revving of the current plugin is needed on this platform.
 }
-}};
-dojox.flash.info=new dojox.flash.Info();
+
+dojox.flash.Install.prototype = {
+	needed: function(){ /* Boolean */
+		// summary:
+		//		Determines if installation or revving of the current plugin is
+		//		needed. 
+	
+		// do we even have flash?
+		if(!dojox.flash.info.capable){
+			return true;
+		}
+
+		// Must have ExternalInterface which came in Flash 8
+		if(!dojox.flash.info.isVersionOrAbove(8, 0, 0)){
+			return true;
+		}
+
+		// otherwise we don't need installation
+		return false;
+	},
+
+	install: function(){
+		// summary: Performs installation or revving of the Flash plugin.
+		var installObj;
+	
+		// indicate that we are installing
+		dojox.flash.info.installing = true;
+		dojox.flash.installing();
+		
+		if(dojox.flash.info.capable == false){ // we have no Flash at all
+			// write out a simple Flash object to force the browser to prompt
+			// the user to install things
+			installObj = new dojox.flash.Embed(false);
+			installObj.write(); // write out HTML for Flash
+		}else if(dojox.flash.info.isVersionOrAbove(6, 0, 65)){ // Express Install
+			installObj = new dojox.flash.Embed(false);
+			installObj.write(true); // write out HTML for Flash 8 version+
+			installObj.setVisible(true);
+			installObj.center();
+		}else{ // older Flash install than version 6r65
+			alert("This content requires a more recent version of the Macromedia "
+						+" Flash Player.");
+			window.location.href = + dojox.flash.Embed.protocol() +
+						"://www.macromedia.com/go/getflashplayer";
+		}
+	},
+	
+	// Called when the Express Install is either finished, failed, or was
+	// rejected by the user.
+	_onInstallStatus: function(msg){
+		if (msg == "Download.Complete"){
+			// Installation is complete.
+			dojox.flash._initialize();
+		}else if(msg == "Download.Cancelled"){
+			alert("This content requires a more recent version of the Macromedia "
+						+" Flash Player.");
+			window.location.href = dojox.flash.Embed.protocol() +
+						"://www.macromedia.com/go/getflashplayer";
+		}else if (msg == "Download.Failed"){
+			// The end user failed to download the installer due to a network failure
+			alert("There was an error downloading the Flash Player update. "
+						+ "Please try again later, or visit macromedia.com to download "
+						+ "the latest version of the Flash plugin.");
+		}	
+	}
 }
+
+// find out if Flash is installed
+dojox.flash.info = new dojox.flash.Info();
+
+// vim:ts=4:noet:tw=0:
diff --git a/dojox/flash/tests/TestFlash.as b/dojox/flash/tests/TestFlash.as
new file mode 100644
index 0000000..80e7cd2
--- /dev/null
+++ b/dojox/flash/tests/TestFlash.as
@@ -0,0 +1,42 @@
+import DojoExternalInterface;
+import ExpressInstall;
+
+class TestFlash{
+	private var message:String;
+	
+	public function TestFlash(){
+	}
+	
+	public static function main(){
+		//getURL("javascript:alert('main')");
+		trace("main");
+		DojoExternalInterface.initialize();
+		
+		var test = new TestFlash();
+		DojoExternalInterface.addCallback("setMessage", test, test.setMessage);
+		DojoExternalInterface.addCallback("getMessage", test, test.getMessage);
+		DojoExternalInterface.addCallback("multipleValues",  test, test.multipleValues);
+		DojoExternalInterface.addCallback("setMessageSlice", test, test.setMessageSlice);
+		
+		DojoExternalInterface.done();
+	}
+	
+	public function setMessage(message:String):Number{
+		this.message = message;
+		return message.length;
+	}
+	
+	public function setMessageSlice(message:String, start:Number, end:Number):Number{ 
+		this.message = message.slice(start,end); 
+		return message.length; 
+	}
+	
+	public function getMessage():String{
+		return this.message;
+	}
+	
+	public function multipleValues(key:String, value:String, 
+									namespace:String):String{
+		return namespace + key + value;
+	}
+}
\ No newline at end of file
diff --git a/dojox/flash/tests/TestFlash.swf b/dojox/flash/tests/TestFlash.swf
new file mode 100644
index 0000000..3499180
Binary files /dev/null and b/dojox/flash/tests/TestFlash.swf differ
diff --git a/dojox/flash/tests/buildFlashTest.sh b/dojox/flash/tests/buildFlashTest.sh
new file mode 100755
index 0000000..a73d20c
--- /dev/null
+++ b/dojox/flash/tests/buildFlashTest.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# TODO: FIXME: Get rid of this and hook it into Dojo's general build script
+# You must have mtasc to run this
+mtasc -trace DojoExternalInterface.trace -main -cp .. -swf TestFlash.swf -version 8 -header 215:138:10 TestFlash.as
\ No newline at end of file
diff --git a/dojox/flash/tests/test_flash.html b/dojox/flash/tests/test_flash.html
new file mode 100644
index 0000000..f220a37
--- /dev/null
+++ b/dojox/flash/tests/test_flash.html
@@ -0,0 +1,15 @@
+<html>
+	<head>
+		<script src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		
+		<script src="test_flash.js"></script>
+	</head>
+	
+	<body>
+		<h1>Test Dojox Flash</h1>
+		
+		<p>For detailed test output see Firebug console (if Firefox).
+			This test should be run on Firefox, Internet Explorer, and Safari
+			to confirm that Dojox Flash is working correctly.</p>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/flash/tests/test_flash.js b/dojox/flash/tests/test_flash.js
new file mode 100644
index 0000000..a514dca
--- /dev/null
+++ b/dojox/flash/tests/test_flash.js
@@ -0,0 +1,191 @@
+// TODO: FIXME: Refactor this to use D.O.H. instead of its own assertions
+
+dojo.require("dojox.flash");
+
+var flashLoaded = false;
+var pageLoaded = false;
+var testXML = testBook = null;
+
+function flashReady(){
+	console.debug("flashReady");
+	if (flashLoaded) {
+	  return; // prevent double loads
+	}
+	
+	flashLoaded = true;
+	
+	if(isReady()){
+		run();
+	}
+}
+
+function pageReady(){
+	console.debug("pageReady");
+	if (pageLoaded) { 
+	  return; // prevent double loads
+	}
+	
+	pageLoaded = true;
+	
+	loadResources();
+	
+	if(isReady()){
+		run();
+	}
+}
+
+function isReady(){
+	return testXML && testBook && pageLoaded && flashLoaded;
+}
+
+function loadResources(){
+	console.debug("Trying to load resources");
+	
+	var d = dojo.xhrGet({
+		url: "../../storage/tests/resources/testXML.xml",
+		handleAs: "text"
+	});
+
+	d.addCallback(function(results){
+		console.debug("testXML loaded");
+		testXML = results;
+		if(isReady()){
+			run();
+		}
+	});
+
+	d.addErrback(function(error){ 
+		console.debug("Unable to load testXML.xml: " + error);
+	});
+	
+	d = dojo.xhrGet({
+		url: "../../storage/tests/resources/testBook.txt",
+		handleAs: "text"
+	});
+
+	d.addCallback(function(results){
+		console.debug("testBook loaded");
+		testBook = results;
+		if(isReady()){
+			run();
+		}
+	});
+
+	d.addErrback(function(error){ 
+		console.debug("Unable to load testXML.xml: " + error);
+	});
+}
+
+function run(){
+	console.debug("run");
+	try{
+		var correct, actual;
+		
+		console.debug("Setting simple message...");
+		correct = "hello world";
+		dojox.flash.comm.setMessage(correct);
+		actual = dojox.flash.comm.getMessage();
+		assert(correct, actual, "Setting/getting simple message did not work");
+		chop(correct);
+	
+		console.debug("Setting message with evil characters...");
+		// our correct and actual values get tricky when we have double back
+		// slashes; do a trick so that they can be compared easier
+		var doubleSlash = "\\";
+		doubleSlash = doubleSlash.charAt(0);
+		correct = "hello world\n\n\nasdfasdf!@#$@#%^[]{}&<xml>" + doubleSlash 
+						+ "<div>$%^&%^&*^&()<><><>,./;\0\r\f\'][`~=\"+-]\\0MORE!\n\rLESS"; 
+		var putSize = dojox.flash.comm.setMessage(correct); 
+		assert(putSize, correct.length, "Failed putting. Correct length = " 
+						+ correct.length + ", Flash length = " + putSize);
+		dojox.flash.comm.setMessage(correct);
+		actual = dojox.flash.comm.getMessage();
+		assert(correct, actual, "Setting/getting message with evil characters did not work");
+		chop(correct);
+	
+		console.debug("Setting testXML...");
+		correct = testXML;
+		dojox.flash.comm.setMessage(correct);
+		actual = dojox.flash.comm.getMessage();
+		assert(correct, actual, "Setting/getting testXML did not work");
+		chop(correct);
+		
+		console.debug("Setting testBook(~300K)...");
+		correct = testBook;
+		dojox.flash.comm.setMessage(correct);
+		actual = dojox.flash.comm.getMessage();
+		assert(correct, actual, "Setting/getting testBook did not work");
+	
+		console.debug("Setting testBook 3 times (~900K)...");
+		correct = testBook + testBook + testBook;
+		dojox.flash.comm.setMessage(correct);
+		actual = dojox.flash.comm.getMessage();
+		assert(correct, actual, "Setting/getting testBook X 3 did not work");
+		
+		console.debug("Setting JSON...");
+		var obj = {type: "car", color: "red", model: "Ford", year: "2008",
+					features: ["A/C", "automatic", "4-wheel drive"]};
+		correct = dojo.toJson(obj, true);
+		dojox.flash.comm.setMessage(correct);
+		actual = dojox.flash.comm.getMessage();
+		assert(correct, actual, "Setting/getting JSON did not work");
+		chop(correct);
+		
+		console.debug("Calling method that takes multiple values...");
+		actual = dojox.flash.comm.multipleValues("key", "value", "namespace");
+		assert("namespacekeyvalue", actual, "Setting/getting multiple values did not work");
+		
+		var allPassed = document.createElement("p");
+		allPassed.style.backgroundColor = "green";
+		allPassed.style.color = "white";
+		allPassed.style.fontSize = "24pt";
+		allPassed.appendChild(document.createTextNode("All tests passed"));
+		var body = document.getElementsByTagName("body")[0];
+		body.appendChild(allPassed);
+	}catch(e){
+		console.debug(e.message || e);
+	}
+}
+
+function chop(testString){ 
+	console.debug("chopping '" + testString + "'"); 
+	for(var i = 0; i < Math.min(testString.length, 100); i++){ 
+		//console.debug("index = " + i); 
+		testSlice(testString, 0, i+1); 
+	} 
+} 
+ 
+function testSlice( testString, from, to){ 
+	var putSize = dojox.flash.comm.setMessageSlice( testString, from, to); 
+	var actual = dojox.flash.comm.getMessage(); 
+	var correct = testString.slice(from, to);
+	
+	var msg = "Put a string with " + testString.length 
+					+ " chars, but it got with " + putSize + " chars in the Flash layer";
+	assert(putSize, testString.length, msg);
+	
+	msg = "I got '" + actual + "' instead of '" + correct +"'";
+	assert(correct, actual, msg); 
+} 
+
+function assert(correct, actual, msg){
+	//alert("correct="+correct+",\n\nactual="+actual);
+	if(correct != actual){
+	  var failed = document.createElement("p");
+		failed.style.backgroundColor = "red";
+		failed.style.color = "white";
+		failed.style.fontSize = "24pt";
+		failed.appendChild(document.createTextNode("Test failed: " + msg));
+		var body = document.getElementsByTagName("body")[0];
+		body.appendChild(failed);
+		
+		throw new Error("ASSERTION FAILED: " + msg);
+	}else{
+		//console.debug("Assertion passed");
+	}
+}
+
+console.debug("adding listeners...");
+dojox.flash.addLoadedListener(flashReady);
+dojox.flash.setSwf("TestFlash.swf", false);
+dojo.connect(dojo, "loaded", pageReady);
\ No newline at end of file
diff --git a/dojox/form/BusyButton.js b/dojox/form/BusyButton.js
index 018b547..5ff18d7 100644
--- a/dojox/form/BusyButton.js
+++ b/dojox/form/BusyButton.js
@@ -1,79 +1,123 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.BusyButton"]){
-dojo._hasResource["dojox.form.BusyButton"]=true;
 dojo.provide("dojox.form.BusyButton");
+
 dojo.require("dijit.form.Button");
-dojo.requireLocalization("dijit","loading",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dojox.form._BusyButtonMixin",null,{isBusy:false,busyLabel:"",timeout:null,useIcon:true,postMixInProperties:function(){
-this.inherited(arguments);
-if(!this.busyLabel){
-this.busyLabel=dojo.i18n.getLocalization("dijit","loading",this.lang).loadingState;
-}
-},postCreate:function(){
-this.inherited(arguments);
-this._label=this.containerNode.innerHTML;
-this._initTimeout=this.timeout;
-if(this.isBusy){
-this.makeBusy();
-}
-},makeBusy:function(){
-this.isBusy=true;
-this.attr("disabled",true);
-this.setLabel(this.busyLabel,this.timeout);
-},cancel:function(){
-this.attr("disabled",false);
-this.isBusy=false;
-this.setLabel(this._label);
-if(this._timeout){
-clearTimeout(this._timeout);
-}
-this.timeout=this._initTimeout;
-},resetTimeout:function(_1){
-if(this._timeout){
-clearTimeout(this._timeout);
-}
-if(_1){
-this._timeout=setTimeout(dojo.hitch(this,function(){
-this.cancel();
-}),_1);
-}else{
-if(_1==undefined||_1===0){
-this.cancel();
-}
-}
-},setLabel:function(_2,_3){
-this.label=_2;
-while(this.containerNode.firstChild){
-this.containerNode.removeChild(this.containerNode.firstChild);
-}
-this.containerNode.innerHTML=this.label;
-if(this.showLabel==false&&!(dojo.attr(this.domNode,"title"))){
-this.titleNode.title=dojo.trim(this.containerNode.innerText||this.containerNode.textContent||"");
-}
-if(_3){
-this.resetTimeout(_3);
-}else{
-this.timeout=null;
-}
-if(this.useIcon&&this.isBusy){
-var _4=new Image();
-_4.src=this._blankGif;
-dojo.attr(_4,"id",this.id+"_icon");
-dojo.addClass(_4,"dojoxBusyButtonIcon");
-this.containerNode.appendChild(_4);
-}
-},_clicked:function(e){
-if(!this.isBusy){
-this.makeBusy();
-}
-}});
-dojo.declare("dojox.form.BusyButton",[dijit.form.Button,dojox.form._BusyButtonMixin],{});
-dojo.declare("dojox.form.BusyComboButton",[dijit.form.ComboButton,dojox.form._BusyButtonMixin],{});
-dojo.declare("dojox.form.BusyDropDownButton",[dijit.form.DropDownButton,dojox.form._BusyButtonMixin],{});
-}
+
+dojo.requireLocalization("dijit", "loading");
+
+dojo.declare("dojox.form._BusyButtonMixin",
+	null, 
+	{
+		
+	isBusy: false,	
+	busyLabel: "", // text while button is busy
+	timeout: null, // timeout, should be controlled by xhr call
+	useIcon: true, // use a busy icon
+ 
+	postMixInProperties: function(){
+		this.inherited(arguments);
+		if(!this.busyLabel){
+			this.busyLabel = dojo.i18n.getLocalization("dijit", "loading", this.lang).loadingState;
+		}
+	},
+	
+	postCreate: function(){
+		// summary:
+		//	stores initial label and timeout for reference
+		this.inherited(arguments);
+		this._label = this.containerNode.innerHTML;
+		this._initTimeout = this.timeout;
+		
+		// for initial busy buttons
+		if(this.isBusy){
+			this.makeBusy();
+		}
+	},
+	
+	makeBusy: function(){
+		// summary:
+		//	sets state from idle to busy
+		this.isBusy = true;
+		this.set("disabled", true);
+			
+		this.setLabel(this.busyLabel, this.timeout);
+	},
+	
+	cancel: function(){
+		// summary:
+		//	if no timeout is set or for other reason the user can put the button back
+		//  to being idle
+		this.set("disabled", false);
+		this.isBusy = false;
+		this.setLabel(this._label);
+		if(this._timeout){	clearTimeout(this._timeout); }
+		this.timeout = this._initTimeout;
+	},
+	
+	resetTimeout: function(/*Int*/ timeout){
+		// summary:
+		//	to reset existing timeout and setting a new timeout
+		if(this._timeout){	
+			clearTimeout(this._timeout); 
+		}
+		
+		// new timeout
+		if(timeout){
+			this._timeout = setTimeout(dojo.hitch(this, function(){
+				this.cancel();
+			}), timeout);			
+		}else if(timeout == undefined || timeout === 0){
+			this.cancel();
+		}
+	},
+	
+	setLabel: function(/*String*/ content, /*Int*/ timeout){
+		// summary:
+		//	setting a label and optional timeout of the labels state
+		
+		// this.inherited(arguments); FIXME: throws an Unknown runtime error
+		
+		// Begin IE hack
+		// summary: reset the label (text) of the button; takes an HTML string
+		this.label = content;
+		// remove children
+		while (this.containerNode.firstChild){
+			this.containerNode.removeChild(this.containerNode.firstChild);
+		}
+		this.containerNode.innerHTML = this.label;
+		
+		if(this.showLabel == false && !(dojo.attr(this.domNode, "title"))){
+			this.titleNode.title=dojo.trim(this.containerNode.innerText || this.containerNode.textContent || '');
+		}
+		// End IE hack
+		
+		// setting timeout
+		if(timeout){
+			this.resetTimeout(timeout);
+		}else{
+			this.timeout = null;
+		}
+		
+		// create optional busy image
+		if(this.useIcon && this.isBusy){
+			var node = new Image();
+			node.src = this._blankGif;
+			dojo.attr(node, "id", this.id+"_icon");
+			dojo.addClass(node, "dojoxBusyButtonIcon");
+			this.containerNode.appendChild(node);
+		}
+	},
+	
+	_clicked: function(e){
+		// summary:
+		//	on button click the button state gets changed 
+		
+		// only do something if button is not busy
+		if(!this.isBusy){ 
+			this.makeBusy();
+		}
+	}
+});
+
+dojo.declare("dojox.form.BusyButton", [dijit.form.Button, dojox.form._BusyButtonMixin], {});
+dojo.declare("dojox.form.BusyComboButton", [dijit.form.ComboButton, dojox.form._BusyButtonMixin], {});
+dojo.declare("dojox.form.BusyDropDownButton", [dijit.form.DropDownButton, dojox.form._BusyButtonMixin], {});
diff --git a/dojox/form/CheckedMultiSelect.js b/dojox/form/CheckedMultiSelect.js
index cb0fdd3..db8e0bf 100644
--- a/dojox/form/CheckedMultiSelect.js
+++ b/dojox/form/CheckedMultiSelect.js
@@ -1,100 +1,176 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.CheckedMultiSelect"]){
-dojo._hasResource["dojox.form.CheckedMultiSelect"]=true;
 dojo.provide("dojox.form.CheckedMultiSelect");
+
 dojo.require("dijit.form.CheckBox");
 dojo.require("dijit.form._FormSelectWidget");
-dojo.declare("dojox.form._CheckedMultiSelectItem",[dijit._Widget,dijit._Templated],{widgetsInTemplate:true,templateString:dojo.cache("dojox.form","resources/_CheckedMultiSelectItem.html","<div class=\"dijitReset ${baseClass}\"\n\t><input class=\"${baseClass}Box\" dojoType=\"dijit.form.CheckBox\" dojoAttachPoint=\"checkBox\" \n\t\tdojoAttachEvent=\"_onClick:_changeBox\" type=\"${_type.type}\" baseClass=\"${_type.baseClass}\"\n\t><div class=\"dijitInline ${baseClass}Label\" dojoAttachPoint [...]
-if(this.parent.multiple){
-this._type={type:"checkbox",baseClass:"dijitCheckBox"};
-}else{
-this._type={type:"radio",baseClass:"dijitRadio"};
-}
-this.disabled=this.option.disabled=this.option.disabled||false;
-this.inherited(arguments);
-},postCreate:function(){
-this.inherited(arguments);
-this.labelNode.innerHTML=this.option.label;
-},_changeBox:function(){
-if(this.attr("disabled")||this.attr("readOnly")){
-return;
-}
-if(this.parent.multiple){
-this.option.selected=this.checkBox.attr("value")&&true;
-}else{
-this.parent.attr("value",this.option.value);
-}
-this.parent._updateSelection();
-this.parent.focus();
-},_onMouse:function(e){
-if(this.attr("disabled")||this.attr("readOnly")){
-dojo.stopEvent(e);
-}else{
-this.checkBox._onMouse(e);
-}
-},_onClick:function(e){
-if(this.attr("disabled")||this.attr("readOnly")){
-dojo.stopEvent(e);
-}else{
-this.checkBox._onClick(e);
-}
-},_updateBox:function(){
-this.checkBox.attr("value",this.option.selected);
-},_setDisabledAttr:function(_1){
-this.disabled=_1||this.option.disabled;
-this.checkBox.attr("disabled",this.disabled);
-dojo.toggleClass(this.domNode,"dojoxMultiSelectDisabled",this.disabled);
-},_setReadOnlyAttr:function(_2){
-this.checkBox.attr("readOnly",_2);
-this.checkBox._setStateClass();
-this.readOnly=_2;
-}});
-dojo.declare("dojox.form.CheckedMultiSelect",dijit.form._FormSelectWidget,{templateString:dojo.cache("dojox.form","resources/CheckedMultiSelect.html","<div class=\"dijit dijitReset dijitInline\" dojoAttachEvent=\"onmousedown:_mouseDown,onclick:focus\"\n\t><select class=\"${baseClass}Select\" multiple=\"true\" dojoAttachPoint=\"containerNode,focusNode\"></select\n\t><div dojoAttachPoint=\"wrapperDiv\"></div\n></div>\n"),baseClass:"dojoxMultiSelect",_mouseDown:function(e){
-dojo.stopEvent(e);
-},_addOptionItem:function(_3){
-this.wrapperDiv.appendChild(new dojox.form._CheckedMultiSelectItem({option:_3,parent:this}).domNode);
-},_updateSelection:function(){
-this.inherited(arguments);
-dojo.forEach(this._getChildren(),function(c){
-c._updateBox();
-});
-},_getChildren:function(){
-return dojo.map(this.wrapperDiv.childNodes,function(n){
-return dijit.byNode(n);
-});
-},invertSelection:function(_4){
-dojo.forEach(this.options,function(i){
-i.selected=!i.selected;
-});
-this._updateSelection();
-},_setDisabledAttr:function(_5){
-this.inherited(arguments);
-dojo.forEach(this._getChildren(),function(_6){
-if(_6&&_6.attr){
-_6.attr("disabled",_5);
-}
-});
-},_setReadOnlyAttr:function(_7){
-if("readOnly" in this.attributeMap){
-this._attrToDom("readOnly",_7);
-}
-this.readOnly=_7;
-dojo.forEach(this._getChildren(),function(_8){
-if(_8&&_8.attr){
-_8.attr("readOnly",_7);
-}
+
+dojo.declare("dojox.form._CheckedMultiSelectItem", 
+	[dijit._Widget, dijit._Templated],
+	{
+	// summary:
+	//		The individual items for a CheckedMultiSelect
+
+	widgetsInTemplate: true,
+	templateString: dojo.cache("dojox.form", "resources/_CheckedMultiSelectItem.html"),
+
+	baseClass: "dojoxMultiSelectItem",
+
+	// option: dojox.form.__SelectOption
+	//		The option that is associated with this item
+	option: null,
+	parent: null,
+	
+	// disabled: boolean
+	//		Whether or not this widget is disabled
+	disabled: false,
+
+	// readOnly: boolean
+	//		Whether or not this widget is readOnly
+	readOnly: false,
+
+	postMixInProperties: function(){
+		// summary:
+		//		Set the appropriate _subClass value - based on if we are multi-
+		//		or single-select
+		if(this.parent.multiple){
+			this._type = {type: "checkbox", baseClass: "dijitCheckBox"};
+		}else{
+			this._type = {type: "radio", baseClass: "dijitRadio"};
+		}
+		this.disabled = this.option.disabled = this.option.disabled||false;
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		// summary:
+		//		Set innerHTML here - since the template gets messed up sometimes
+		//		with rich text
+		this.inherited(arguments);
+		this.labelNode.innerHTML = this.option.label;
+	},
+
+	_changeBox: function(){
+		// summary:
+		//		Called to force the select to match the state of the check box
+		//		(only on click of the checkbox)  Radio-based calls _setValueAttr
+		//		instead.
+		if(this.get("disabled") || this.get("readOnly")){ return; }
+		if(this.parent.multiple){
+			this.option.selected = this.checkBox.attr('value') && true;
+		}else{
+			this.parent.attr('value', this.option.value);
+		}
+		// fire the parent's change
+		this.parent._updateSelection();
+		
+		// refocus the parent
+		this.parent.focus();
+	},
+	
+	_onClick: function(e){
+		// summary:
+		//		Sets the click state (passes through to the check box)
+		if(this.get("disabled") || this.get("readOnly")){
+			dojo.stopEvent(e);
+		}else{
+			this.checkBox._onClick(e);
+		}
+	},
+	
+	_updateBox: function(){
+		// summary:
+		//		Called to force the box to match the state of the select
+		this.checkBox.attr('value', this.option.selected);
+	},
+	
+	_setDisabledAttr: function(value){
+		// summary:
+		//		Disables (or enables) all the children as well
+		this.disabled = value||this.option.disabled;
+		this.checkBox.attr("disabled", this.disabled);
+		dojo.toggleClass(this.domNode, "dojoxMultiSelectDisabled", this.disabled);
+	},
+	
+	_setReadOnlyAttr: function(value){
+		// summary:
+		//		Sets read only (or unsets) all the children as well
+		this.checkBox.attr("readOnly", value);
+		this.readOnly = value;
+	}
 });
-this._setStateClass();
-},uninitialize:function(){
-dojo.forEach(this._getChildren(),function(_9){
-_9.destroyRecursive();
+
+dojo.declare("dojox.form.CheckedMultiSelect", dijit.form._FormSelectWidget, {
+	// summary:
+	//		Extends the core dijit MultiSelect to provide a "checkbox" selector
+
+	templateString: dojo.cache("dojox.form", "resources/CheckedMultiSelect.html"),
+
+	baseClass: "dojoxMultiSelect",
+
+	_onMouseDown: function(e){
+		// summary:
+		//		Cancels the mousedown event to prevent others from stealing
+		//		focus
+		dojo.stopEvent(e);
+	},
+	
+	_addOptionItem: function(/* dojox.form.__SelectOption */ option){
+		this.wrapperDiv.appendChild(new dojox.form._CheckedMultiSelectItem({
+			option: option,
+			parent: this
+		}).domNode);
+	},
+	
+	_updateSelection: function(){
+		this.inherited(arguments);
+		dojo.forEach(this._getChildren(), function(c){ c._updateBox(); });
+	},
+	
+	_getChildren: function(){
+		return dojo.map(this.wrapperDiv.childNodes, function(n){
+			return dijit.byNode(n);
+		});
+	},
+
+	invertSelection: function(onChange){
+		// summary: Invert the selection
+		// onChange: Boolean
+		//		If null, onChange is not fired.
+		dojo.forEach(this.options, function(i){
+			i.selected = !i.selected;
+		});
+		this._updateSelection();
+	},
+
+	_setDisabledAttr: function(value){
+		// summary:
+		//		Disable (or enable) all the children as well
+		this.inherited(arguments);
+		dojo.forEach(this._getChildren(), function(node){
+			if(node && node.attr){
+				node.attr("disabled", value);
+			}
+		});
+	},
+	
+	_setReadOnlyAttr: function(value){
+		// summary:
+		//		Sets read only (or unsets) all the children as well
+		if("readOnly" in this.attributeMap){
+			this._attrToDom("readOnly", value);
+		}
+		this.readOnly = value;
+		dojo.forEach(this._getChildren(), function(node){
+			if(node && node.attr){
+				node.attr("readOnly", value);
+			}
+		});
+	},
+
+	uninitialize: function(){
+		// Make sure these children are destroyed
+		dojo.forEach(this._getChildren(), function(child){
+			child.destroyRecursive();
+		});
+		this.inherited(arguments);
+	}
 });
-this.inherited(arguments);
-}});
-}
diff --git a/dojox/form/DateTextBox.js b/dojox/form/DateTextBox.js
index 67a8289..a7d7126 100644
--- a/dojox/form/DateTextBox.js
+++ b/dojox/form/DateTextBox.js
@@ -1,82 +1,157 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.DateTextBox"]){
-dojo._hasResource["dojox.form.DateTextBox"]=true;
 dojo.provide("dojox.form.DateTextBox");
 dojo.experimental("dojox.form.DateTextBox");
+
 dojo.require("dojox.widget.Calendar");
 dojo.require("dojox.widget.CalendarViews");
 dojo.require("dijit.form._DateTimeTextBox");
-dojo.declare("dojox.form.DateTextBox",dijit.form._DateTimeTextBox,{popupClass:"dojox.widget.Calendar",_selector:"date",_open:function(){
-this.inherited(arguments);
-dojo.style(this._picker.domNode.parentNode,"position","absolute");
-}});
-dojo.declare("dojox.form.DayTextBox",dojox.form.DateTextBox,{popupClass:"dojox.widget.DailyCalendar",parse:function(_1){
-return _1;
-},format:function(_2){
-return _2.getDate?_2.getDate():_2;
-},validator:function(_3){
-var _4=Number(_3);
-var _5=/(^-?\d\d*$)/.test(String(_3));
-return _3==""||_3==null||(_5&&_4>=1&&_4<=31);
-},_open:function(){
-this.inherited(arguments);
-this._picker.onValueSelected=dojo.hitch(this,function(_6){
-this.focus();
-setTimeout(dojo.hitch(this,"_close"),1);
-dijit.form.TextBox.prototype._setValueAttr.call(this,String(_6.getDate()),true,String(_6.getDate()));
-});
-}});
-dojo.declare("dojox.form.MonthTextBox",dojox.form.DateTextBox,{popupClass:"dojox.widget.MonthlyCalendar",selector:"date",postMixInProperties:function(){
-this.inherited(arguments);
-this.constraints.datePattern="MM";
-},format:function(_7){
-return Number(_7)+1;
-},parse:function(_8,_9){
-return Number(_8)-1;
-},serialize:function(_a,_b){
-return String(_a);
-},validator:function(_c){
-var _d=Number(_c);
-var _e=/(^-?\d\d*$)/.test(String(_c));
-return _c==""||_c==null||(_e&&_d>=1&&_d<=12);
-},_open:function(){
-this.inherited(arguments);
-this._picker.onValueSelected=dojo.hitch(this,function(_f){
-this.focus();
-setTimeout(dojo.hitch(this,"_close"),1);
-dijit.form.TextBox.prototype._setValueAttr.call(this,_f,true,_f);
-});
-}});
-dojo.declare("dojox.form.YearTextBox",dojox.form.DateTextBox,{popupClass:"dojox.widget.YearlyCalendar",format:function(_10){
-if(typeof _10=="string"){
-return _10;
-}else{
-if(_10.getFullYear){
-return _10.getFullYear();
-}
-}
-return _10;
-},validator:function(_11){
-return _11==""||_11==null||/(^-?\d\d*$)/.test(String(_11));
-},_open:function(){
-this.inherited(arguments);
-this._picker.onValueSelected=dojo.hitch(this,function(_12){
-this.focus();
-setTimeout(dojo.hitch(this,"_close"),1);
-dijit.form.TextBox.prototype._setValueAttr.call(this,_12,true,_12);
-});
-},parse:function(_13,_14){
-return _13||(this._isEmpty(_13)?null:undefined);
-},filter:function(val){
-if(val&&val.getFullYear){
-return val.getFullYear().toString();
-}
-return this.inherited(arguments);
-}});
-}
+
+dojo.declare(
+	"dojox.form.DateTextBox",
+	dijit.form._DateTimeTextBox,
+	{
+		// summary:
+		//		A validating, serializable, range-bound date text box with a popup calendar
+
+		// popupClass: String
+		//  The popup widget to use. In this case, a calendar with Day, Month and Year views.
+		popupClass: "dojox.widget.Calendar",
+		_selector: "date",
+		
+		_open: function(){
+			this.inherited(arguments);
+			dojo.style(this._picker.domNode.parentNode, "position", "absolute");
+		}
+	}
+);
+
+
+dojo.declare(
+	"dojox.form.DayTextBox",
+	dojox.form.DateTextBox,
+	{
+		// summary:
+		//		A validating, serializable, range-bound date text box with a popup calendar that contains just months.
+		
+		// popupClass: String
+		//  The popup widget to use. In this case, a calendar with just a Month view.
+		popupClass: "dojox.widget.DailyCalendar",
+		
+		parse: function(displayVal){
+			return displayVal;
+		},
+		
+		format: function(value){
+			return value.getDate ? value.getDate() : value;
+		},
+		validator: function(value) {
+			var num = Number(value);
+			var isInt = /(^-?\d\d*$)/.test(String(value));
+			return value == "" || value == null || (isInt && num >= 1 && num <= 31);
+		},		
+		_open: function(){
+			this.inherited(arguments);
+			
+			this._picker.onValueSelected = dojo.hitch(this, function(value){
+				this.focus(); // focus the textbox before the popup closes to avoid reopening the popup
+				setTimeout(dojo.hitch(this, "_close"), 1); // allow focus time to take
+
+				dijit.form.TextBox.prototype._setValueAttr.call(this, String(value.getDate()), true, String(value.getDate()));
+			});			
+		}
+	}
+);
+
+dojo.declare(
+	"dojox.form.MonthTextBox",
+	dojox.form.DateTextBox, 
+	{
+		// summary:
+		//		A validating, serializable, range-bound date text box with a popup calendar that contains only years
+		
+		// popupClass: String
+		//  The popup widget to use. In this case, a calendar with just a Year view.
+		popupClass: "dojox.widget.MonthlyCalendar",
+
+		selector: "date",
+		
+		postMixInProperties: function(){
+			this.inherited(arguments);
+			this.constraints.datePattern = "MM";
+		},
+		
+		format: function(value) {
+			return Number(value) + 1;
+		},
+		
+		parse: function(value, constraints){
+			return Number(value) - 1;
+		},
+		
+		serialize: function(value, constraints) {
+			return String(value);
+		},
+
+		validator: function(value) {
+			var num = Number(value);
+			var isInt = /(^-?\d\d*$)/.test(String(value));
+			return value == "" || value == null || (isInt && num >= 1 && num <= 12);
+		},
+		
+		_open: function(){
+			this.inherited(arguments);
+
+			this._picker.onValueSelected = dojo.hitch(this, function(value){
+				this.focus(); // focus the textbox before the popup closes to avoid reopening the popup
+				setTimeout(dojo.hitch(this, "_close"), 1); // allow focus time to take
+				dijit.form.TextBox.prototype._setValueAttr.call(this,value, true, value);
+			});						
+		}
+	}
+);
+
+
+dojo.declare(
+	"dojox.form.YearTextBox",
+	dojox.form.DateTextBox, 
+	{
+		// summary:
+		//		A validating, serializable, range-bound date text box with a popup calendar that contains only years
+		
+		popupClass: "dojox.widget.YearlyCalendar",
+
+		format: function(value) {
+			if (typeof value == "string"){
+				return value;
+			}
+			else if (value.getFullYear){
+				return value.getFullYear();
+			}
+			return value;
+		},
+		
+		validator: function(value) {
+			return value == "" || value == null || /(^-?\d\d*$)/.test(String(value));
+		},
+		
+		_open: function(){
+			this.inherited(arguments);
+			
+			this._picker.onValueSelected = dojo.hitch(this, function(value){
+				this.focus(); // focus the textbox before the popup closes to avoid reopening the popup
+				setTimeout(dojo.hitch(this, "_close"), 1); // allow focus time to take
+				dijit.form.TextBox.prototype._setValueAttr.call(this,value, true, value);
+			});						
+		},
+		
+		parse: function(/*String*/value, /*dojo.date.locale.__FormatOptions*/constraints) {
+			return value || (this._isEmpty(value) ? null : undefined); // Date
+		},
+
+		filter: function(val) {
+			if (val && val.getFullYear){
+				return val.getFullYear().toString();
+			}
+			return this.inherited(arguments);
+		}
+	}
+);
diff --git a/dojox/form/DropDownSelect.js b/dojox/form/DropDownSelect.js
index 0418228..ef39077 100644
--- a/dojox/form/DropDownSelect.js
+++ b/dojox/form/DropDownSelect.js
@@ -1,14 +1,6 @@
-/*
-	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
-*/
+dojo.deprecated("dojox.form.DropDownSelect", "Use dijit.form.Select instead", "2.0");
 
-
-if(!dojo._hasResource["dojox.form.DropDownSelect"]){
-dojo._hasResource["dojox.form.DropDownSelect"]=true;
-dojo.deprecated("dojox.form.DropDownSelect","Use dijit.form.Select instead","2.0");
 dojo.provide("dojox.form.DropDownSelect");
 dojo.require("dijit.form.Select");
-dojo.setObject("dojox.form.DropDownSelect",dijit.form.Select);
-}
+
+dojo.setObject("dojox.form.DropDownSelect", dijit.form.Select);
\ No newline at end of file
diff --git a/dojox/form/DropDownStack.js b/dojox/form/DropDownStack.js
index 04b2d96..7282bae 100644
--- a/dojox/form/DropDownStack.js
+++ b/dojox/form/DropDownStack.js
@@ -1,14 +1,10 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.DropDownStack"]){
-dojo._hasResource["dojox.form.DropDownStack"]=true;
 dojo.provide("dojox.form.DropDownStack");
+
 dojo.require("dijit.form.Select");
 dojo.require("dojox.form._SelectStackMixin");
-dojo.declare("dojox.form.DropDownStack",[dijit.form.Select,dojox.form._SelectStackMixin],{});
-}
+
+dojo.declare("dojox.form.DropDownStack",
+	[ dijit.form.Select, dojox.form._SelectStackMixin ], {
+	// summary: A dropdown-based select stack.
+	
+});
diff --git a/dojox/form/FileInput.js b/dojox/form/FileInput.js
index dd5eff4..e21b48b 100644
--- a/dojox/form/FileInput.js
+++ b/dojox/form/FileInput.js
@@ -1,42 +1,80 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.FileInput"]){
-dojo._hasResource["dojox.form.FileInput"]=true;
 dojo.provide("dojox.form.FileInput");
-dojo.experimental("dojox.form.FileInput");
+dojo.experimental("dojox.form.FileInput"); 
+
 dojo.require("dijit.form._FormWidget");
-dojo.require("dijit._Templated");
-dojo.declare("dojox.form.FileInput",dijit.form._FormWidget,{label:"Browse ...",cancelText:"Cancel",name:"uploadFile",templateString:dojo.cache("dojox.form","resources/FileInput.html","<div class=\"dijitFileInput\">\n\t<input id=\"${id}\" class=\"dijitFileInputReal\" type=\"file\" dojoAttachPoint=\"fileInput\" name=\"${name}\" />\n\t<div class=\"dijitFakeInput\">\n\t\t<input class=\"dijitFileInputVisible\" type=\"text\" dojoAttachPoint=\"focusNode, inputNode\" />\n\t\t<div class=\"dijitIn [...]
-this._listener=this.connect(this.fileInput,"onchange","_matchValue");
-this._keyListener=this.connect(this.fileInput,"onkeyup","_matchValue");
-},_matchValue:function(){
-this.inputNode.value=this.fileInput.value;
-if(this.inputNode.value){
-this.cancelNode.style.visibility="visible";
-dojo.fadeIn({node:this.cancelNode,duration:275}).play();
-}
-},setLabel:function(_1,_2){
-this.titleNode.innerHTML=_1;
-},reset:function(e){
-this.disconnect(this._listener);
-this.disconnect(this._keyListener);
-if(this.fileInput){
-this.domNode.removeChild(this.fileInput);
-}
-dojo.fadeOut({node:this.cancelNode,duration:275}).play();
-this.fileInput=document.createElement("input");
-this.fileInput.setAttribute("type","file");
-this.fileInput.setAttribute("id",this.id);
-this.fileInput.setAttribute("name",this.name);
-dojo.addClass(this.fileInput,"dijitFileInputReal");
-this.domNode.appendChild(this.fileInput);
-this._keyListener=this.connect(this.fileInput,"onkeyup","_matchValue");
-this._listener=this.connect(this.fileInput,"onchange","_matchValue");
-this.inputNode.value="";
-}});
-}
+dojo.require("dijit._Templated"); 
+
+dojo.declare("dojox.form.FileInput",
+	dijit.form._FormWidget,
+	{
+	// summary: A styled input type="file"
+	//
+	// description: A input type="file" form widget, with a button for uploading to be styled via css,
+	//	a cancel button to clear selection, and FormWidget mixin to provide standard dijit.form.Form
+	//	support (FIXME: maybe not fully implemented) 
+
+	// label: String
+	//	the title text of the "Browse" button
+	label: "Browse ...",
+
+	// cancelText: String
+	//	the title of the "Cancel" button
+	cancelText: "Cancel",
+
+	// name: String
+	//	ugh, this should be pulled from this.domNode
+	name: "uploadFile",
+
+	templateString: dojo.cache("dojox.form","resources/FileInput.html"),
+	
+	startup: function(){
+		// summary: listen for changes on our real file input
+		this._listener = this.connect(this.fileInput,"onchange","_matchValue");
+		this._keyListener = this.connect(this.fileInput,"onkeyup","_matchValue");
+	},
+
+	//get rid of the this.connect in _FormWidget.postCreate to allow IE to show
+	//the file picker dialog properly
+	postCreate: function(){},
+	
+	_matchValue: function(){
+		// summary: set the content of the upper input based on the semi-hidden file input
+		this.inputNode.value = this.fileInput.value;
+		if(this.inputNode.value){
+			this.cancelNode.style.visibility = "visible";
+			dojo.fadeIn({ node: this.cancelNode, duration:275 }).play();
+		}
+	},
+
+	setLabel: function(/* String */label,/* String? */cssClass){
+		// summary: method to allow use to change button label
+		this.titleNode.innerHTML = label;
+	},
+
+	reset: function(/* Event */e){
+		// summary: on click of cancel button, since we can't clear the input because of
+		// 	security reasons, we destroy it, and add a new one in it's place.
+		this.disconnect(this._listener);
+		this.disconnect(this._keyListener);
+		if(this.fileInput){
+			this.domNode.removeChild(this.fileInput);
+		}
+		dojo.fadeOut({ node: this.cancelNode, duration:275 }).play(); 
+
+		// should we use cloneNode()? can we?
+		this.fileInput = document.createElement('input');
+		// dojo.attr(this.fileInput,{
+		//	"type":"file", "id":this.id, "name": this.name	
+		//});
+		this.fileInput.setAttribute("type","file");
+		this.fileInput.setAttribute("id", this.id);
+		this.fileInput.setAttribute("name", this.name);
+		dojo.addClass(this.fileInput,"dijitFileInputReal");
+		this.domNode.appendChild(this.fileInput);
+
+		this._keyListener = this.connect(this.fileInput, "onkeyup", "_matchValue");
+		this._listener = this.connect(this.fileInput, "onchange", "_matchValue"); 
+		this.inputNode.value = ""; 
+	}
+
+});
\ No newline at end of file
diff --git a/dojox/form/FileInputAuto.js b/dojox/form/FileInputAuto.js
index 2c47ded..860701b 100644
--- a/dojox/form/FileInputAuto.js
+++ b/dojox/form/FileInputAuto.js
@@ -1,95 +1,209 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.FileInputAuto"]){
-dojo._hasResource["dojox.form.FileInputAuto"]=true;
 dojo.provide("dojox.form.FileInputAuto");
+
 dojo.require("dojox.form.FileInput");
-dojo.require("dojo.io.iframe");
-dojo.declare("dojox.form.FileInputAuto",dojox.form.FileInput,{url:"",blurDelay:2000,duration:500,uploadMessage:"Uploading ...",triggerEvent:"onblur",_sent:false,templateString:dojo.cache("dojox.form","resources/FileInputAuto.html","<div class=\"dijitFileInput\">\n\t<input id=\"${id}\" name=\"${name}\" class=\"dijitFileInputReal\" type=\"file\" dojoAttachPoint=\"fileInput\" />\n\t<div class=\"dijitFakeInput\" dojoAttachPoint=\"fakeNodeHolder\">\n\t\t<input class=\"dijitFileInputVisible\"  [...]
-this._blurListener=this.connect(this.fileInput,this.triggerEvent,"_onBlur");
-this._focusListener=this.connect(this.fileInput,"onfocus","_onFocus");
-this.inherited(arguments);
-},_onFocus:function(){
-if(this._blurTimer){
-clearTimeout(this._blurTimer);
-}
-},_onBlur:function(){
-if(this._blurTimer){
-clearTimeout(this._blurTimer);
-}
-if(!this._sent){
-this._blurTimer=setTimeout(dojo.hitch(this,"_sendFile"),this.blurDelay);
-}
-},setMessage:function(_1){
-this.overlay.removeChild(this.overlay.firstChild);
-this.overlay.appendChild(document.createTextNode(_1));
-},_sendFile:function(e){
-if(this._sent||this._sending||!this.fileInput.value){
-return;
-}
-this._sending=true;
-dojo.style(this.fakeNodeHolder,"display","none");
-dojo.style(this.overlay,{opacity:0,display:"block"});
-this.setMessage(this.uploadMessage);
-dojo.fadeIn({node:this.overlay,duration:this.duration}).play();
-var _2;
-if(dojo.isIE){
-_2=document.createElement("<form enctype=\"multipart/form-data\" method=\"post\">");
-_2.encoding="multipart/form-data";
-}else{
-_2=document.createElement("form");
-_2.setAttribute("enctype","multipart/form-data");
-}
-_2.appendChild(this.fileInput);
-dojo.body().appendChild(_2);
-dojo.io.iframe.send({url:this.url,form:_2,handleAs:"json",handle:dojo.hitch(this,"_handleSend")});
-},_handleSend:function(_3,_4){
-this.overlay.removeChild(this.overlay.firstChild);
-this._sent=true;
-this._sending=false;
-dojo.style(this.overlay,{opacity:0,border:"none",background:"none"});
-this.overlay.style.backgroundImage="none";
-this.fileInput.style.display="none";
-this.fakeNodeHolder.style.display="none";
-dojo.fadeIn({node:this.overlay,duration:this.duration}).play(250);
-this.disconnect(this._blurListener);
-this.disconnect(this._focusListener);
-dojo.body().removeChild(_4.args.form);
-this.fileInput=null;
-this.onComplete(_3,_4,this);
-},reset:function(e){
-if(this._blurTimer){
-clearTimeout(this._blurTimer);
-}
-this.disconnect(this._blurListener);
-this.disconnect(this._focusListener);
-this.overlay.style.display="none";
-this.fakeNodeHolder.style.display="";
-this.inherited(arguments);
-this._sent=false;
-this._sending=false;
-this._blurListener=this.connect(this.fileInput,this.triggerEvent,"_onBlur");
-this._focusListener=this.connect(this.fileInput,"onfocus","_onFocus");
-},onComplete:function(_5,_6,_7){
-}});
-dojo.declare("dojox.form.FileInputBlind",dojox.form.FileInputAuto,{startup:function(){
-this.inherited(arguments);
-this._off=dojo.style(this.inputNode,"width");
-this.inputNode.style.display="none";
-this._fixPosition();
-},_fixPosition:function(){
-if(dojo.isIE){
-dojo.style(this.fileInput,"width","1px");
-}else{
-dojo.style(this.fileInput,"left","-"+(this._off)+"px");
-}
-},reset:function(e){
-this.inherited(arguments);
-this._fixPosition();
-}});
-}
+dojo.require("dojo.io.iframe"); 
+
+dojo.declare("dojox.form.FileInputAuto",
+	dojox.form.FileInput,
+	{
+	// summary: An extension on dojox.form.FileInput providing background upload progress
+	//
+	// description: An extended version of FileInput - when the user focuses away from the input
+	//	the selected file is posted via dojo.io.iframe to the url. example implementation
+	//	comes with PHP solution for handling upload, and returning required data.
+	//	
+	// notes: the return data from the io.iframe is used to populate the input element with 
+	//	data regarding the results. it will be a JSON object, like:
+	//	
+	//	results = { size: "1024", filename: "file.txt" }
+	//	
+	//	all the parameters allowed to dojox.form.FileInput apply
+
+	// url: String
+	// 	the URL where our background FileUpload will be sent
+	url: "",
+
+	// blurDelay: Integer
+	//	time in ms before an un-focused widget will wait before uploading the file to the url="" specified
+	//	default: 2 seconds
+	blurDelay: 2000,
+
+	// duration: Integer
+	//	The time in ms to use as the generic timing mechanism for the animations
+	//	set to 1 or 0 for "immediate respose"
+	duration: 500,
+
+	// uploadMessage: String
+	//	
+	//	FIXME: i18n somehow?
+	uploadMessage: "Uploading ...", 
+	
+	// triggerEvent: String
+	//		Event which triggers the upload. Defaults to onblur, sending the file selected
+	//		'blurDelay' milliseconds after losing focus. Set to "onchange" with a low blurDelay
+	// 		to send files immediately after uploading.
+	triggerEvent: "onblur",
+	
+	_sent: false,
+	
+	// small template changes, new attachpoint: overlay
+	templateString: dojo.cache("dojox.form","resources/FileInputAuto.html"),
+	
+	onBeforeSend: function(){
+		// summary: Called immediately before a FileInput sends it's file via io.iframe.send. 
+		//		The return of this function is passed as the `content` member in the io.iframe IOArgs
+		//		object.
+		return {};
+	},
+	
+	startup: function(){
+		// summary: add our extra blur listeners
+		this._blurListener = this.connect(this.fileInput, this.triggerEvent, "_onBlur");
+		this._focusListener = this.connect(this.fileInput, "onfocus", "_onFocus"); 
+		this.inherited(arguments);
+	},
+
+	_onFocus: function(){
+		// summary: clear the upload timer
+		if(this._blurTimer){ clearTimeout(this._blurTimer); }
+	},
+
+	_onBlur: function(){
+		// summary: start the upload timer
+		if(this._blurTimer){ clearTimeout(this._blurTimer); }
+		if(!this._sent){
+			this._blurTimer = setTimeout(dojo.hitch(this,"_sendFile"),this.blurDelay);		
+		}
+	},
+
+	setMessage: function(/*String*/title){
+		// summary: set the text of the progressbar
+		
+		// innerHTML throws errors in IE! so use DOM manipulation instead
+		//this.overlay.innerHTML = title;
+		this.overlay.removeChild(this.overlay.firstChild);
+		this.overlay.appendChild(document.createTextNode(title));
+	},
+	
+	_sendFile: function(/* Event */e){
+		// summary: triggers the chain of events needed to upload a file in the background.
+		if(this._sent || this._sending || !this.fileInput.value){ return; }
+
+		this._sending = true;
+
+		dojo.style(this.fakeNodeHolder,"display","none");
+		dojo.style(this.overlay,{
+			opacity:0,
+			display:"block"
+		});
+
+		this.setMessage(this.uploadMessage);
+
+		dojo.fadeIn({ node: this.overlay, duration:this.duration }).play();
+
+		var _newForm; 
+		if(dojo.isIE){
+			// just to reiterate, IE is a steaming pile of code. 
+			_newForm = document.createElement('<form enctype="multipart/form-data" method="post">');
+			_newForm.encoding = "multipart/form-data";
+			
+		}else{
+			// this is how all other sane browsers do it
+			_newForm = document.createElement('form');
+			_newForm.setAttribute("enctype","multipart/form-data");
+		}
+		_newForm.appendChild(this.fileInput);
+		dojo.body().appendChild(_newForm);
+	
+		dojo.io.iframe.send({
+			url: this.url,
+			form: _newForm,
+			handleAs: "json",
+			handle: dojo.hitch(this,"_handleSend"),
+			content: this.onBeforeSend()
+		});
+	},
+	
+	_handleSend: function(data,ioArgs){
+		// summary: The callback to toggle the progressbar, and fire the user-defined callback
+
+		// innerHTML throws errors in IE! so use DOM manipulation instead
+		this.overlay.removeChild(this.overlay.firstChild);
+		
+		this._sent = true;
+		this._sending = false;
+		dojo.style(this.overlay,{
+			opacity:0,
+			border:"none",
+			background:"none"
+		}); 
+
+		this.overlay.style.backgroundImage = "none";
+		this.fileInput.style.display = "none";
+		this.fakeNodeHolder.style.display = "none";
+		dojo.fadeIn({ node:this.overlay, duration:this.duration }).play(250);
+
+		this.disconnect(this._blurListener);
+		this.disconnect(this._focusListener);
+
+		//remove the form used to send the request
+		dojo.body().removeChild(ioArgs.args.form);
+		this.fileInput = null;
+
+		this.onComplete(data,ioArgs,this);
+	},
+
+	reset: function(e){
+		// summary: accomodate our extra focusListeners
+		if(this._blurTimer){ clearTimeout(this._blurTimer); }
+
+		this.disconnect(this._blurListener);
+		this.disconnect(this._focusListener);
+
+		this.overlay.style.display = "none";
+		this.fakeNodeHolder.style.display = "";
+		this.inherited(arguments);
+		this._sent = false;
+		this._sending = false;
+		this._blurListener = this.connect(this.fileInput, this.triggerEvent,"_onBlur");
+		this._focusListener = this.connect(this.fileInput,"onfocus","_onFocus"); 
+	},
+
+	onComplete: function(data,ioArgs,widgetRef){
+		// summary: stub function fired when an upload has finished. 
+		// data: the raw data found in the first [TEXTAREA] tag of the post url
+		// ioArgs: the dojo.Deferred data being passed from the handle: callback
+		// widgetRef: this widget pointer, so you can set this.overlay to a completed/error message easily
+	}
+});
+
+dojo.declare("dojox.form.FileInputBlind",
+	dojox.form.FileInputAuto,
+	{
+	// summary: An extended version of dojox.form.FileInputAuto
+	//	that does not display an input node, but rather only a button
+	// 	and otherwise behaves just like FileInputAuto
+	
+	startup: function(){
+		// summary: hide our fileInput input field
+		this.inherited(arguments);
+		this._off = dojo.style(this.inputNode,"width");
+		this.inputNode.style.display = "none";
+		this._fixPosition();
+	},
+	
+	_fixPosition: function(){		
+		// summary: in this case, set the button under where the visible button is 
+		if(dojo.isIE){
+			dojo.style(this.fileInput,"width","1px");
+		}else{
+			dojo.style(this.fileInput,"left","-"+(this._off)+"px");
+		}
+	},
+
+	reset: function(e){
+		// summary: onclick, we need to reposition our newly created input type="file"
+		this.inherited(arguments);
+		this._fixPosition(); 
+	}
+});
diff --git a/dojox/form/FileInputBlind.js b/dojox/form/FileInputBlind.js
index 3730ba8..52af5e9 100644
--- a/dojox/form/FileInputBlind.js
+++ b/dojox/form/FileInputBlind.js
@@ -1,12 +1,4 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.FileInputBlind"]){
-dojo._hasResource["dojox.form.FileInputBlind"]=true;
 dojo.provide("dojox.form.FileInputBlind");
-dojo.require("dojox.form.FileInputAuto");
-}
+// FIXME: break out code in 2.0. Leave this stub in place until then. Leave FileInputBlind code in Auto.js for
+// backwards compatibility.
+dojo.require("dojox.form.FileInputAuto");
\ No newline at end of file
diff --git a/dojox/form/FilePickerTextBox.js b/dojox/form/FilePickerTextBox.js
index 767628c..2ed1bfe 100644
--- a/dojox/form/FilePickerTextBox.js
+++ b/dojox/form/FilePickerTextBox.js
@@ -1,264 +1,317 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.FilePickerTextBox"]){
-dojo._hasResource["dojox.form.FilePickerTextBox"]=true;
 dojo.provide("dojox.form.FilePickerTextBox");
-dojo.require("dojox.widget.FilePicker");
+
+dojo.require("dojo.window");
 dojo.require("dijit.form.ValidationTextBox");
 dojo.require("dijit._HasDropDown");
-dojo.declare("dojox.form.FilePickerTextBox",[dijit.form.ValidationTextBox,dijit._HasDropDown],{baseClass:"dojoxFilePickerTextBox",templateString:dojo.cache("dojox.form","resources/FilePickerTextBox.html","<div class=\"dijit dijitReset dijitInlineTable dijitLeft\"\n\tid=\"widget_${id}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\" waiRole=\"combobox\" tabIndex=\"-1\"\n\t><div style=\"overflow:hidden;\"\n\t\t><div class='dijitReset dijitRight diji [...]
-this.inherited(arguments);
-this.dropDown=new dojox.widget.FilePicker(this.constraints);
-},postCreate:function(){
-this.inherited(arguments);
-this.connect(this.dropDown,"onChange",this._onWidgetChange);
-this.connect(this.focusNode,"onblur","_focusBlur");
-this.connect(this.focusNode,"onfocus","_focusFocus");
-this.connect(this.focusNode,"ondblclick",function(){
-dijit.selectInputText(this.focusNode);
-});
-},_setValueAttr:function(_1,_2,_3){
-if(!this._searchInProgress){
-this.inherited(arguments);
-_1=_1||"";
-var _4=this.dropDown.attr("pathValue")||"";
-if(_1!==_4){
-this._skip=true;
-var fx=dojo.hitch(this,"_setBlurValue");
-this.dropDown._setPathValueAttr(_1,!_3,this._settingBlurValue?fx:null);
-}
-}
-},_onWidgetChange:function(_5){
-if(!_5&&this.focusNode.value){
-this._hasValidPath=false;
-this.focusNode.value="";
-}else{
-this.valueItem=_5;
-var _6=this.dropDown._getPathValueAttr(_5);
-if(_6){
-this._hasValidPath=true;
-}
-if(!this._skip){
-this._setValueAttr(_6,undefined,true);
-}
-delete this._skip;
-}
-this.validate();
-},startup:function(){
-if(!this.dropDown._started){
-this.dropDown.startup();
-}
-this.inherited(arguments);
-},openDropDown:function(){
-this.dropDown.domNode.style.width="0px";
-if(!("minPaneWidth" in (this.constraints||{}))){
-this.dropDown.attr("minPaneWidth",(this.domNode.offsetWidth/this.numPanes));
-}
-this.inherited(arguments);
-},toggleDropDown:function(){
-this.inherited(arguments);
-if(this._opened){
-this.dropDown.attr("pathValue",this.attr("value"));
-}
-},_focusBlur:function(e){
-if(e.explicitOriginalTarget==this.focusNode&&!this._allowBlur){
-window.setTimeout(dojo.hitch(this,function(){
-if(!this._allowBlur){
-this.focus();
-}
-}),1);
-}else{
-if(this._menuFocus){
-this.dropDown._updateClass(this._menuFocus,"Item",{"Hover":false});
-delete this._menuFocus;
-}
-}
-},_focusFocus:function(e){
-if(this._menuFocus){
-this.dropDown._updateClass(this._menuFocus,"Item",{"Hover":false});
-}
-delete this._menuFocus;
-var _7=dijit.getFocus(this);
-if(_7&&_7.node){
-_7=dijit.byNode(_7.node);
-if(_7){
-this._menuFocus=_7.domNode;
-}
-}
-if(this._menuFocus){
-this.dropDown._updateClass(this._menuFocus,"Item",{"Hover":true});
-}
-delete this._allowBlur;
-},_onBlur:function(){
-this._allowBlur=true;
-delete this.dropDown._savedFocus;
-this.inherited(arguments);
-},_setBlurValue:function(){
-if(this.dropDown&&!this._settingBlurValue){
-this._settingBlurValue=true;
-this.attr("value",this.focusNode.value);
-}else{
-delete this._settingBlurValue;
-this.inherited(arguments);
-}
-},parse:function(_8,_9){
-if(this._hasValidPath||this._hasSelection){
-return _8;
-}
-var dd=this.dropDown,_a=dd.topDir,_b=dd.pathSeparator;
-var _c=dd.attr("pathValue");
-var _d=function(v){
-if(_a.length&&v.indexOf(_a)===0){
-v=v.substring(_a.length);
-}
-if(_b&&v[v.length-1]==_b){
-v=v.substring(0,v.length-1);
-}
-return v;
-};
-_c=_d(_c);
-var _e=_d(_8);
-if(_e==_c){
-return _8;
-}
-return undefined;
-},_startSearchFromInput:function(){
-var dd=this.dropDown,fn=this.focusNode;
-var _f=fn.value,_10=_f,_11=dd.topDir;
-if(this._hasSelection){
-dijit.selectInputText(fn,_10.length);
-}
-this._hasSelection=false;
-if(_11.length&&_f.indexOf(_11)===0){
-_f=_f.substring(_11.length);
-}
-var _12=_f.split(dd.pathSeparator);
-var _13=dojo.hitch(this,function(idx){
-var dir=_12[idx];
-var _14=dd.getChildren()[idx];
-var _15;
-this._searchInProgress=true;
-var _16=dojo.hitch(this,function(){
-delete this._searchInProgress;
-});
-if((dir||_14)&&!this._opened){
-this.toggleDropDown();
-}
-if(dir&&_14){
-var fx=dojo.hitch(this,function(){
-if(_15){
-this.disconnect(_15);
-}
-delete _15;
-var _17=_14._menu.getChildren();
-var _18=dojo.filter(_17,function(i){
-return i.label==dir;
-})[0];
-var _19=dojo.filter(_17,function(i){
-return (i.label.indexOf(dir)===0);
-})[0];
-if(_18&&((_12.length>idx+1&&_18.children)||(!_18.children))){
-idx++;
-_14._menu.onItemClick(_18,{type:"internal",stopPropagation:function(){
-},preventDefault:function(){
-}});
-if(_12[idx]){
-_13(idx);
-}else{
-_16();
-}
-}else{
-_14._setSelected(null);
-if(_19&&_12.length===idx+1){
-dd._setInProgress=true;
-dd._removeAfter(_14);
-delete dd._setInProgress;
-var _1a=_19.label;
-if(_19.children){
-_1a+=dd.pathSeparator;
-}
-_1a=_1a.substring(dir.length);
-window.setTimeout(function(){
-dijit.scrollIntoView(_19.domNode);
-},1);
-fn.value=_10+_1a;
-dijit.selectInputText(fn,_10.length);
-this._hasSelection=true;
-try{
-_19.focusNode.focus();
-}
-catch(e){
-}
-}else{
-if(this._menuFocus){
-this.dropDown._updateClass(this._menuFocus,"Item",{"Hover":false,"Focus":false});
-}
-delete this._menuFocus;
-}
-_16();
-}
-});
-if(!_14.isLoaded){
-_15=this.connect(_14,"onLoad",fx);
-}else{
-fx();
-}
-}else{
-if(_14){
-_14._setSelected(null);
-dd._setInProgress=true;
-dd._removeAfter(_14);
-delete dd._setInProgress;
-}
-_16();
-}
-});
-_13(0);
-},_onKey:function(e){
-if(this.disabled||this.readOnly){
-return;
-}
-var dk=dojo.keys;
-var c=e.charOrCode;
-if(c==dk.DOWN_ARROW){
-this._allowBlur=true;
-}
-if(c==dk.ENTER&&this._opened){
-this.dropDown.onExecute();
-dijit.selectInputText(this.focusNode,this.focusNode.value.length);
-this._hasSelection=false;
-dojo.stopEvent(e);
-return;
-}
-if((c==dk.RIGHT_ARROW||c==dk.LEFT_ARROW||c==dk.TAB)&&this._hasSelection){
-this._startSearchFromInput();
-dojo.stopEvent(e);
-return;
-}
-this.inherited(arguments);
-var _1b=false;
-if((c==dk.BACKSPACE||c==dk.DELETE)&&this._hasSelection){
-this._hasSelection=false;
-}else{
-if(c==dk.BACKSPACE||c==dk.DELETE||c==" "){
-_1b=true;
-}else{
-_1b=e.keyChar!=="";
-}
-}
-if(this._searchTimer){
-window.clearTimeout(this._searchTimer);
-}
-delete this._searchTimer;
-if(_1b){
-this._hasValidPath=false;
-this._hasSelection=false;
-this._searchTimer=window.setTimeout(dojo.hitch(this,"_startSearchFromInput"),this.searchDelay+1);
-}
-}});
-}
+dojo.require("dojox.widget.FilePicker");
+
+dojo.declare(
+	"dojox.form.FilePickerTextBox",
+	[dijit.form.ValidationTextBox, dijit._HasDropDown],
+	{
+		// summary:
+		//		A validating text box tied to a file picker popup
+		
+		baseClass: "dojoxFilePickerTextBox",
+		
+		templateString: dojo.cache("dojox.form", "resources/FilePickerTextBox.html"),
+		
+		// searchDelay: Integer
+		//		Delay in milliseconds between when user types something and we start
+		//		searching based on that value
+		searchDelay: 500,
+		
+		// valueItem: item
+		//		The item, in our store, of the directory relating to our value
+		valueItem: null,
+		
+		// numPanes: number
+		//	The number of panes to display in our box (if we don't have any
+		//	minPaneWidth specified by our constraints)
+		numPanes: 2.25,
+		
+		postMixInProperties: function(){
+			this.inherited(arguments);
+			this.dropDown = new dojox.widget.FilePicker(this.constraints);
+		},
+
+		postCreate: function(){
+			this.inherited(arguments);
+			// Make our connections we want
+			this.connect(this.dropDown, "onChange", this._onWidgetChange);
+			this.connect(this.focusNode, "onblur", "_focusBlur");
+			this.connect(this.focusNode, "onfocus", "_focusFocus");
+			this.connect(this.focusNode, "ondblclick", function(){
+				dijit.selectInputText(this.focusNode);
+			});
+		},
+		
+		_setValueAttr: function(/*string*/value, priorityChange, fromWidget){
+			// summary: sets the value of this widget
+			if(!this._searchInProgress){
+				this.inherited(arguments);
+				value = value||"";
+				var tVal = this.dropDown.attr("pathValue")||"";
+				if(value !== tVal){
+					this._skip = true;
+					var fx = dojo.hitch(this, "_setBlurValue");
+					this.dropDown._setPathValueAttr(value, !fromWidget, 
+											this._settingBlurValue ? fx : null);
+				}
+			}
+		},
+		
+		_onWidgetChange: function(/*item*/item){
+			// summary: called when the path gets changed in the dropdown
+			if(!item && this.focusNode.value){
+				this._hasValidPath = false;
+				this.focusNode.value = "";
+			}else{
+				this.valueItem = item;
+				var value = this.dropDown._getPathValueAttr(item);
+				if(value){
+					this._hasValidPath = true;
+				}
+				if(!this._skip){
+					this._setValueAttr(value, undefined, true);
+				}
+				delete this._skip;
+			}
+			this.validate();
+		},
+		
+		startup: function(){
+			if(!this.dropDown._started){
+				this.dropDown.startup();
+			}
+			this.inherited(arguments);
+		},
+
+		openDropDown: function(){
+			// set width to 0 so that it will resize automatically
+			this.dropDown.domNode.style.width="0px";
+			if(!("minPaneWidth" in (this.constraints||{}))){
+				this.dropDown.attr("minPaneWidth", (this.domNode.offsetWidth / this.numPanes));
+			}
+			this.inherited(arguments);
+		},
+		
+		toggleDropDown: function(){
+			this.inherited(arguments);
+			// Make sure our display is up-to-date with our value
+			if(this._opened){ 
+				this.dropDown.attr("pathValue", this.get("value"));
+			}
+		},
+		
+		_focusBlur: function(/*Event*/ e){
+			// summary: called when the focus node gets blurred
+			if(e.explicitOriginalTarget == this.focusNode && !this._allowBlur){
+				window.setTimeout(dojo.hitch(this, function(){
+					if(!this._allowBlur){
+						this.focus();
+					}
+				}), 1);
+			}else if(this._menuFocus){
+				this.dropDown._updateClass(this._menuFocus, "Item", {"Hover": false});
+				delete this._menuFocus;
+			}
+		},
+		
+		_focusFocus: function(/*Event*/ e){
+			// summary: called when the focus node gets focus
+			if(this._menuFocus){
+				this.dropDown._updateClass(this._menuFocus, "Item", {"Hover": false});
+			}
+			delete this._menuFocus;
+			var focusNode = dijit.getFocus(this);
+			if(focusNode && focusNode.node){
+				focusNode = dijit.byNode(focusNode.node);
+				if(focusNode){
+					this._menuFocus = focusNode.domNode;
+				}
+			}
+			if(this._menuFocus){
+				this.dropDown._updateClass(this._menuFocus, "Item", {"Hover": true});
+			}
+			delete this._allowBlur;
+		},
+		
+		_onBlur: function(){
+			// summary: called when focus is shifted away from this widget
+			this._allowBlur = true;
+			delete this.dropDown._savedFocus;
+			this.inherited(arguments);
+		},
+		
+		_setBlurValue: function(){
+			// summary: sets the value of the widget once focus has left
+			if(this.dropDown && !this._settingBlurValue){
+				this._settingBlurValue = true;
+				this.set("value", this.focusNode.value);
+			}else{
+				delete this._settingBlurValue;
+				this.inherited(arguments);
+			}
+		},
+		
+		parse: function(/* String */ value, /* Object */ constraints){
+			//	summary:
+			//		Function to convert a formatted string to a value - we use
+			//		it to verify that it *really* is a valid value
+			if(this._hasValidPath || this._hasSelection){
+				return value;
+			}
+			var dd = this.dropDown, topDir = dd.topDir, sep = dd.pathSeparator;
+			var ddVal = dd.attr("pathValue");
+			var norm = function(v){
+				if(topDir.length && v.indexOf(topDir) === 0){
+					v = v.substring(topDir.length);
+				}
+				if(sep && v[v.length - 1] == sep){
+					v = v.substring(0, v.length - 1);
+				}
+				return v;
+			};
+			ddVal = norm(ddVal);
+			var val = norm(value);
+			if(val == ddVal){
+				return value;
+			}
+			return undefined;
+		},
+		
+		_startSearchFromInput: function(){
+			// summary: kicks off a search based off the current text value of the widget
+			var dd = this.dropDown, fn = this.focusNode;
+			var val = fn.value, oVal = val, topDir = dd.topDir;
+			if(this._hasSelection){
+				dijit.selectInputText(fn, oVal.length);
+			}
+			this._hasSelection = false;
+			if(topDir.length && val.indexOf(topDir) === 0){
+				val = val.substring(topDir.length);
+			}
+			var dirs = val.split(dd.pathSeparator);
+			var setFromChain = dojo.hitch(this, function(idx){
+				var dir = dirs[idx];
+				var child = dd.getChildren()[idx];
+				var conn;
+				this._searchInProgress = true;
+				var _cleanup = dojo.hitch(this, function(){
+					delete this._searchInProgress;
+				});
+				if((dir || child) && !this._opened){
+					this.toggleDropDown();
+				}
+				if(dir && child){
+					var fx = dojo.hitch(this, function(){
+						if(conn){
+							this.disconnect(conn);
+						}
+						delete conn;
+						var children = child._menu.getChildren();
+						var exact = dojo.filter(children, function(i){
+							return i.label == dir;
+						})[0];
+						var first = dojo.filter(children, function(i){
+							return (i.label.indexOf(dir) === 0);
+						})[0];
+						if(exact && 
+							((dirs.length > idx + 1 && exact.children) || 
+							(!exact.children))){
+							idx++;
+							child._menu.onItemClick(exact, {type: "internal",
+													stopPropagation: function(){},
+													preventDefault: function(){}});
+							if(dirs[idx]){
+								setFromChain(idx);
+							}else{
+								_cleanup();
+							}
+						}else{
+							child._setSelected(null);
+							if(first && dirs.length === idx + 1){
+								dd._setInProgress = true;
+								dd._removeAfter(child);
+								delete dd._setInProgress;
+								var targetString = first.label;
+								if(first.children){
+									targetString += dd.pathSeparator;
+								}
+								targetString = targetString.substring(dir.length);
+								window.setTimeout(function(){
+									dojo.window.scrollIntoView(first.domNode);
+								}, 1);
+								fn.value = oVal + targetString;
+								dijit.selectInputText(fn, oVal.length);
+								this._hasSelection = true;
+								try{first.focusNode.focus();}catch(e){}
+							}else{
+								if(this._menuFocus){
+									this.dropDown._updateClass(this._menuFocus, "Item", {"Hover": false, "Focus": false});
+								}
+								delete this._menuFocus;							
+							}
+							_cleanup();
+						}
+					});
+					if(!child.isLoaded){
+						conn = this.connect(child, "onLoad", fx);
+					}else{
+						fx();
+					}
+				}else{
+					if(child){
+						child._setSelected(null);
+						dd._setInProgress = true;
+						dd._removeAfter(child);
+						delete dd._setInProgress;
+					}
+					_cleanup();
+				}
+			});
+			setFromChain(0);
+		},
+		
+		_onKey: function(/*Event*/ e){
+			// summary: callback when the user presses a key on menu popup node
+			if(this.disabled || this.readOnly){ return; }
+			var dk = dojo.keys;
+			var c = e.charOrCode;
+			if(c==dk.DOWN_ARROW){
+				this._allowBlur = true;
+			}
+			if(c==dk.ENTER && this._opened){
+				this.dropDown.onExecute();
+				dijit.selectInputText(this.focusNode, this.focusNode.value.length);
+				this._hasSelection = false;
+				dojo.stopEvent(e);
+				return;
+			}
+			if((c==dk.RIGHT_ARROW || c==dk.LEFT_ARROW || c==dk.TAB) && this._hasSelection){
+				this._startSearchFromInput();
+				dojo.stopEvent(e);
+				return;
+			}
+			this.inherited(arguments);
+			var doSearch = false;
+			if((c==dk.BACKSPACE || c==dk.DELETE) && this._hasSelection){
+				this._hasSelection = false;
+			}else if(c==dk.BACKSPACE || c==dk.DELETE || c==" "){
+				doSearch = true;
+			}else{
+				doSearch = e.keyChar !== "";
+			}
+			if(this._searchTimer){
+				window.clearTimeout(this._searchTimer);
+			}
+			delete this._searchTimer;
+			if(doSearch){
+				this._hasValidPath = false;
+				this._hasSelection = false;
+				this._searchTimer = window.setTimeout(dojo.hitch(this, "_startSearchFromInput"), this.searchDelay + 1);
+			}
+		}
+	}
+);
diff --git a/dojox/form/FileUploader.js b/dojox/form/FileUploader.js
index 84780fc..08c0b18 100644
--- a/dojox/form/FileUploader.js
+++ b/dojox/form/FileUploader.js
@@ -1,12 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.FileUploader"]){
-dojo._hasResource["dojox.form.FileUploader"]=true;
 dojo.provide("dojox.form.FileUploader");
 dojo.require("dojox.embed.Flash");
 dojo.require("dojo.io.iframe");
@@ -15,713 +6,1479 @@ dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dojox.embed.flashVars");
 dojo.require("dijit._Contained");
+
 dojo.experimental("dojox.form.FileUploader");
-(function(){
-var _1=dojo.config.uploaderPath||dojo.moduleUrl("dojox.form","resources/uploader.swf");
-var _2=function(_3){
-if(!_3||_3=="none"){
-return false;
-}
-return _3.replace(/:/g,"||").replace(/\./g,"^^").replace("url(","").replace(")","").replace(/'/g,"").replace(/"/g,"");
-};
-var _4=function(_5){
-var tn=_5.tagName.toLowerCase();
-return tn=="button"||tn=="input";
-};
-var _6=function(_7){
-var o={};
-o.ff=dojo.style(_7,"fontFamily");
-if(o.ff){
-o.ff=o.ff.replace(", ",",");
-o.ff=o.ff.replace(/\"|\'/g,"");
-o.ff=o.ff=="sans-serif"?"Arial":o.ff;
-o.fw=dojo.style(_7,"fontWeight");
-o.fi=dojo.style(_7,"fontStyle");
-o.fs=parseInt(dojo.style(_7,"fontSize"),10);
-if(dojo.style(_7,"fontSize").indexOf("%")>-1){
-var n=_7;
-while(n.tagName){
-if(dojo.style(n,"fontSize").indexOf("%")==-1){
-o.fs=parseInt(dojo.style(n,"fontSize"),10);
-break;
-}
-if(n.tagName.toLowerCase()=="body"){
-o.fs=16*0.01*parseInt(dojo.style(n,"fontSize"),10);
-}
-n=n.parentNode;
-}
-}
-o.fc=new dojo.Color(dojo.style(_7,"color")).toHex();
-o.fc=parseInt(o.fc.substring(1,Infinity),16);
-}
-o.lh=dojo.style(_7,"lineHeight");
-o.ta=dojo.style(_7,"textAlign");
-o.ta=o.ta=="start"||!o.ta?"left":o.ta;
-o.va=_4(_7)?"middle":o.lh==o.h?"middle":dojo.style(_7,"verticalAlign");
-return o;
-};
-var _8=function(_9){
-var cn=dojo.trim(_9.innerHTML);
-if(cn.indexOf("<")>-1){
-cn=escape(cn);
-}
-return cn;
-};
-var _a=function(_b){
-var o={};
-var _c=dojo.contentBox(_b);
-var _d=dojo._getPadExtents(_b);
-o.p=[_d.t,_d.w-_d.l,_d.h-_d.t,_d.l];
-o.w=_c.w+_d.w;
-o.h=_c.h+_d.h;
-o.d=dojo.style(_b,"display");
-var _e=new dojo.Color(dojo.style(_b,"backgroundColor"));
-o.bc=_e.a==0?"#ffffff":_e.toHex();
-o.bc=parseInt(o.bc.substring(1,Infinity),16);
-var _f=_2(dojo.style(_b,"backgroundImage"));
-if(_f){
-o.bi={url:_f,rp:dojo.style(_b,"backgroundRepeat"),pos:escape(dojo.style(_b,"backgroundPosition"))};
-if(!o.bi.pos){
-var rx=dojo.style(_b,"backgroundPositionX");
-var ry=dojo.style(_b,"backgroundPositionY");
-rx=(rx=="left")?"0%":(rx=="right")?"100%":rx;
-ry=(ry=="top")?"0%":(ry=="bottom")?"100%":ry;
-o.bi.pos=escape(rx+" "+ry);
-}
-}
-return dojo.mixin(o,_6(_b));
-};
-var _10=function(_11,_12,_13){
-var _14,_15;
-if(_13){
-_14=dojo.place("<"+_11.tagName+"><span>"+_11.innerHTML+"</span></"+_11.tagName+">",_11.parentNode);
-var _16=_14.firstChild;
-dojo.addClass(_16,_11.className);
-dojo.addClass(_14,_12);
-_15=_a(_16);
-}else{
-_14=dojo.place("<"+_11.tagName+">"+_11.innerHTML+"</"+_11.tagName+">",_11.parentNode);
-dojo.addClass(_14,_11.className);
-dojo.addClass(_14,_12);
-_14.id=_11.id;
-_15=_a(_14);
-}
-dojo.destroy(_14);
-return _15;
-};
-var _17=function(ltr){
-return ltr.charCodeAt(0)<91;
-};
-dojo.declare("dojox.form.FileUploader",[dijit._Widget,dijit._Templated,dijit._Contained],{templateString:"<div><div dojoAttachPoint=\"progNode\"><div dojoAttachPoint=\"progTextNode\"></div></div><div dojoAttachPoint=\"insideNode\" class=\"uploaderInsideNode\"></div></div>",uploadUrl:"",isDebug:false,devMode:false,baseClass:"dojoxUploaderNorm",hoverClass:"dojoxUploaderHover",activeClass:"dojoxUploaderActive",disabledClass:"dojoxUploaderDisabled",force:"",uploaderType:"",flashObject:null,f [...]
-if(this.isDebug){
-console.log.apply(console,arguments);
-}
-},constructor:function(){
-this._subs=[];
-},postMixInProperties:function(){
-this.fileList=[];
-this._cons=[];
-this.fileMask=[];
-this.fileInputs=[];
-this.fileCount=0;
-this.flashReady=false;
-this._disabled=false;
-this.force=this.force.toLowerCase();
-this.uploaderType=((dojox.embed.Flash.available>=this.minFlashVersion||this.force=="flash")&&this.force!="html")?"flash":"html";
-this.deferredUploading=this.deferredUploading===true?1:this.deferredUploading;
-if(!this.swfPath){
-this.swfPath=_1;
-}
-this._refNode=this.srcNodeRef;
-this.getButtonStyle();
-},startup:function(){
-},postCreate:function(){
-this.inherited(arguments);
-this.setButtonStyle();
-var _18;
-if(this.uploaderType=="flash"){
-_18="createFlashUploader";
-}else{
-this.uploaderType="html";
-_18="createHtmlUploader";
-}
-if(this._hiddenNode){
-var w=dijit.byNode(this._hiddenNode);
-this.connect(w,"onShow",_18);
-}else{
-this[_18]();
-}
-if(this.fileListId){
-this.connect(dojo.byId(this.fileListId),"click",function(evt){
-var p=evt.target.parentNode.parentNode.parentNode;
-if(p.id&&p.id.indexOf("file_")>-1){
-this.removeFile(p.id.split("file_")[1]);
-}
-});
-}
-dojo.addOnUnload(this,this.destroy);
-},getButtonStyle:function(){
-var _19=this.srcNodeRef;
-var p=_19.parentNode;
-while(p.tagName.toLowerCase()!="body"){
-var d=dojo.style(p,"display");
-if(d=="none"){
-this._hiddenNode=p;
-break;
-}
-p=p.parentNode;
-}
-if(this._hiddenNode){
-dojo.style(this._hiddenNode,"display","block");
-}
-if(this.button){
-console.warn("DEPRECATED: FileUploader.button - will be removed in 1.5. FileUploader should be created as widget.");
-}
-if(!_19&&this.button&&this.button.domNode){
-var _1a=true;
-var cls=this.button.domNode.className+" dijitButtonNode";
-var txt=_8(dojo.query(".dijitButtonText",this.button.domNode)[0]);
-var _1b="<button id=\""+this.button.id+"\" class=\""+cls+"\">"+txt+"</button>";
-_19=dojo.place(_1b,this.button.domNode,"after");
-this.srcNodeRef=_19;
-this.button.destroy();
-this.baseClass="dijitButton";
-this.hoverClass="dijitButtonHover";
-this.pressClass="dijitButtonActive";
-this.disabledClass="dijitButtonDisabled";
-}else{
-if(!this.srcNodeRef&&this.button){
-_19=this.button;
-}
-}
-if(dojo.attr(_19,"class")){
-this.baseClass+=" "+dojo.attr(_19,"class");
-}
-dojo.attr(_19,"class",this.baseClass);
-this.norm=_a(_19);
-this.width=this.norm.w;
-this.height=this.norm.h;
-if(this.uploaderType=="flash"){
-this.over=_10(_19,this.baseClass+" "+this.hoverClass,_1a);
-this.down=_10(_19,this.baseClass+" "+this.activeClass,_1a);
-this.dsbl=_10(_19,this.baseClass+" "+this.disabledClass,_1a);
-this.fhtml={cn:_8(_19),nr:this.norm,ov:this.over,dn:this.down,ds:this.dsbl};
-}else{
-this.fhtml={cn:_8(_19),nr:this.norm};
-if(this.norm.va=="middle"){
-this.norm.lh=this.norm.h;
-}
-}
-if(this.devMode){
-this.log("classes - base:",this.baseClass," hover:",this.hoverClass,"active:",this.activeClass);
-this.log("fhtml:",this.fhtml);
-this.log("norm:",this.norm);
-this.log("over:",this.over);
-this.log("down:",this.down);
-}
-},setButtonStyle:function(){
-dojo.style(this.domNode,{width:this.fhtml.nr.w+"px",height:(this.fhtml.nr.h)+"px",padding:"0px",lineHeight:"normal",position:"relative"});
-if(this.uploaderType=="html"&&this.norm.va=="middle"){
-dojo.style(this.domNode,"lineHeight",this.norm.lh+"px");
-}
-if(this.showProgress){
-this.progTextNode.innerHTML=this.progressMessage;
-dojo.style(this.progTextNode,{width:this.fhtml.nr.w+"px",height:(this.fhtml.nr.h+0)+"px",padding:"0px",margin:"0px",left:"0px",lineHeight:(this.fhtml.nr.h+0)+"px",position:"absolute"});
-dojo.style(this.progNode,{width:this.fhtml.nr.w+"px",height:(this.fhtml.nr.h+0)+"px",padding:"0px",margin:"0px",left:"0px",position:"absolute",display:"none",backgroundImage:"url("+this.progressBackgroundUrl+")",backgroundPosition:"bottom",backgroundRepeat:"repeat-x",backgroundColor:this.progressBackgroundColor});
-}else{
-dojo.destroy(this.progNode);
-}
-dojo.style(this.insideNode,{position:"absolute",top:"0px",left:"0px",display:""});
-dojo.addClass(this.domNode,this.srcNodeRef.className);
-if(this.fhtml.nr.d.indexOf("inline")>-1){
-dojo.addClass(this.domNode,"dijitInline");
-}
-try{
-this.insideNode.innerHTML=this.fhtml.cn;
-}
-catch(e){
-if(this.uploaderType=="flash"){
-this.insideNode=this.insideNode.parentNode.removeChild(this.insideNode);
-dojo.body().appendChild(this.insideNode);
-this.insideNode.innerHTML=this.fhtml.cn;
-var c=dojo.connect(this,"onReady",this,function(){
-dojo.disconnect(c);
-this.insideNode=this.insideNode.parentNode.removeChild(this.insideNode);
-this.domNode.appendChild(this.insideNode);
-});
-}else{
-this.insideNode.appendChild(document.createTextNode(this.fhtml.cn));
-}
-}
-this.flashDiv=this.insideNode;
-if(this._hiddenNode){
-dojo.style(this._hiddenNode,"display","none");
-}
-},onChange:function(_1c){
-},onProgress:function(_1d){
-},onComplete:function(_1e){
-},onCancel:function(){
-},onError:function(_1f){
-},onReady:function(_20){
-},onLoad:function(_21){
-},submit:function(_22){
-var _23=_22?dojo.formToObject(_22):null;
-this.upload(_23);
-return false;
-},upload:function(_24){
-if(!this.fileList.length){
-return false;
-}
-if(!this.uploadUrl){
-console.warn("uploadUrl not provided. Aborting.");
-return false;
-}
-if(!this.showProgress){
-this.attr("disabled",true);
-}
-if(this.progressWidgetId){
-var _25=dijit.byId(this.progressWidgetId).domNode;
-if(dojo.style(_25,"display")=="none"){
-this.restoreProgDisplay="none";
-dojo.style(_25,"display","block");
-}
-if(dojo.style(_25,"visibility")=="hidden"){
-this.restoreProgDisplay="hidden";
-dojo.style(_25,"visibility","visible");
-}
-}
-if(_24&&!_24.target){
-this.postData=_24;
-}
-this.log("upload type:",this.uploaderType," - postData:",this.postData);
-for(var i=0;i<this.fileList.length;i++){
-var f=this.fileList[i];
-f.bytesLoaded=0;
-f.bytesTotal=f.size||100000;
-f.percent=0;
-}
-if(this.uploaderType=="flash"){
-this.uploadFlash();
-}else{
-this.uploadHTML();
-}
-return false;
-},removeFile:function(_26,_27){
-var i;
-for(i=0;i<this.fileList.length;i++){
-if(this.fileList[i].name==_26){
-if(!_27){
-this.fileList.splice(i,1);
-}
-break;
-}
-}
-if(this.uploaderType=="flash"){
-this.flashMovie.removeFile(_26);
-}else{
-if(!_27){
-dojo.destroy(this.fileInputs[i]);
-this.fileInputs.splice(i,1);
-this._renumberInputs();
-}
-}
-if(this.fileListId){
-dojo.destroy("file_"+_26);
-}
-},destroyAll:function(){
-console.warn("DEPRECATED for 1.5 - use destroy() instead");
-this.destroy();
-},destroy:function(){
-if(this.uploaderType=="flash"&&!this.flashMovie){
-this._cons.push(dojo.connect(this,"onLoad",this,"destroy"));
-return;
-}
-dojo.forEach(this._subs,dojo.unsubscribe,dojo);
-dojo.forEach(this._cons,dojo.disconnect,dojo);
-if(this.scrollConnect){
-dojo.disconnect(this.scrollConnect);
-}
-if(this.uploaderType=="flash"){
-this.flashObject.destroy();
-dojo.destroy(this.flashDiv);
-}else{
-dojo.destroy("dojoIoIframe");
-dojo.destroy(this._fileInput);
-dojo.destroy(this._formNode);
-}
-this.inherited(arguments);
-},hide:function(){
-console.warn("DEPRECATED for 1.5 - use dojo.style(domNode, 'display', 'none' instead");
-dojo.style(this.domNode,"display","none");
-},show:function(){
-console.warn("DEPRECATED for 1.5 - use dojo.style(domNode, 'display', '') instead");
-dojo.style(this.domNode,"display","");
-},disable:function(_28){
-console.warn("DEPRECATED: FileUploader.disable() - will be removed in 1.5. Use attr('disable', true) instead.");
-this.attr("disable",_28);
-},_displayProgress:function(_29){
-if(_29===true){
-if(this.uploaderType=="flash"){
-dojo.style(this.insideNode,"left","-2500px");
-}else{
-dojo.style(this.insideNode,"display","none");
-}
-dojo.style(this.progNode,"display","");
-}else{
-if(_29===false){
-dojo.style(this.insideNode,{display:"",left:"0px"});
-dojo.style(this.progNode,"display","none");
-}else{
-var w=_29*this.fhtml.nr.w;
-dojo.style(this.progNode,"width",w+"px");
-}
-}
-},_animateProgress:function(){
-this._displayProgress(true);
-var _2a=false;
-var c=dojo.connect(this,"_complete",function(){
-dojo.disconnect(c);
-_2a=true;
-});
-var w=0;
-var _2b=setInterval(dojo.hitch(this,function(){
-w+=5;
-if(w>this.fhtml.nr.w){
-w=0;
-_2a=true;
-}
-this._displayProgress(w/this.fhtml.nr.w);
-if(_2a){
-clearInterval(_2b);
-setTimeout(dojo.hitch(this,function(){
-this._displayProgress(false);
-}),500);
-}
-}),50);
-},_error:function(evt){
-if(typeof (evt)=="string"){
-evt=new Error(evt);
-}
-this.onError(evt);
-},_addToFileList:function(){
-if(this.fileListId){
-var str="";
-dojo.forEach(this.fileList,function(d){
-str+="<table id=\"file_"+d.name+"\" class=\"fileToUpload\"><tr><td class=\"fileToUploadClose\"></td><td class=\"fileToUploadName\">"+d.name+"</td><td class=\"fileToUploadSize\">"+Math.ceil(d.size*0.001)+"kb</td></tr></table>";
-},this);
-dojo.byId(this.fileListId).innerHTML=str;
-}
-},_change:function(_2c){
-if(dojo.isIE){
-dojo.forEach(_2c,function(f){
-f.name=f.name.split("\\")[f.name.split("\\").length-1];
-});
-}
-if(this.selectMultipleFiles){
-this.fileList=this.fileList.concat(_2c);
-}else{
-if(this.fileList[0]){
-this.removeFile(this.fileList[0].name,true);
-}
-this.fileList=_2c;
-}
-this._addToFileList();
-this.onChange(_2c);
-if(this.uploadOnChange){
-this._buildFileInput();
-this.upload();
-}else{
-if(this.uploaderType=="html"&&this.selectMultipleFiles){
-this._buildFileInput();
-this._connectInput();
-}
-}
-},_complete:function(_2d){
-_2d=dojo.isArray(_2d)?_2d:[_2d];
-dojo.forEach(_2d,function(f){
-if(f.ERROR){
-this._error(f.ERROR);
-}
-},this);
-dojo.forEach(this.fileList,function(f){
-f.bytesLoaded=1;
-f.bytesTotal=1;
-f.percent=100;
-this._progress(f);
-},this);
-dojo.forEach(this.fileList,function(f){
-this.removeFile(f.name,true);
-},this);
-this.onComplete(_2d);
-this.fileList=[];
-this._resetHTML();
-this.attr("disabled",false);
-if(this.restoreProgDisplay){
-setTimeout(dojo.hitch(this,function(){
-dojo.style(dijit.byId(this.progressWidgetId).domNode,this.restoreProgDisplay=="none"?"display":"visibility",this.restoreProgDisplay);
-}),500);
-}
-},_progress:function(_2e){
-var _2f=0;
-var _30=0;
-for(var i=0;i<this.fileList.length;i++){
-var f=this.fileList[i];
-if(f.name==_2e.name){
-f.bytesLoaded=_2e.bytesLoaded;
-f.bytesTotal=_2e.bytesTotal;
-f.percent=Math.ceil(f.bytesLoaded/f.bytesTotal*100);
-this.log(f.name,"percent:",f.percent);
-}
-_30+=Math.ceil(0.001*f.bytesLoaded);
-_2f+=Math.ceil(0.001*f.bytesTotal);
-}
-var _31=Math.ceil(_30/_2f*100);
-if(this.progressWidgetId){
-dijit.byId(this.progressWidgetId).update({progress:_31+"%"});
-}
-if(this.showProgress){
-this._displayProgress(_31*0.01);
-}
-this.onProgress(this.fileList);
-},_getDisabledAttr:function(){
-return this._disabled;
-},_setDisabledAttr:function(_32){
-if(this._disabled==_32){
-return;
-}
-if(this.uploaderType=="flash"){
-if(!this.flashReady){
-var _33=dojo.connect(this,"onLoad",this,function(){
-dojo.disconnect(_33);
-this._setDisabledAttr(_32);
-});
-return;
-}
-this._disabled=_32;
-this.flashMovie.doDisable(_32);
-}else{
-this._disabled=_32;
-dojo.style(this._fileInput,"display",this._disabled?"none":"");
-}
-dojo.toggleClass(this.domNode,this.disabledClass,_32);
-},_onFlashBlur:function(){
-this.flashMovie.blur();
-if(!this.nextFocusObject&&this.tabIndex){
-var _34=dojo.query("[tabIndex]");
-for(var i=0;i<_34.length;i++){
-if(_34[i].tabIndex>=Number(this.tabIndex)+1){
-this.nextFocusObject=_34[i];
-break;
-}
-}
-}
-this.nextFocusObject.focus();
-},_disconnect:function(){
-dojo.forEach(this._cons,dojo.disconnect,dojo);
-},uploadHTML:function(){
-if(this.selectMultipleFiles){
-dojo.destroy(this._fileInput);
-}
-this._setHtmlPostData();
-if(this.showProgress){
-this._animateProgress();
-}
-var dfd=dojo.io.iframe.send({url:this.uploadUrl,form:this._formNode,handleAs:"json",error:dojo.hitch(this,function(err){
-this._error("HTML Upload Error:"+err.message);
-}),load:dojo.hitch(this,function(_35,_36,_37){
-this._complete(_35);
-})});
-},createHtmlUploader:function(){
-this._buildForm();
-this._setFormStyle();
-this._buildFileInput();
-this._connectInput();
-this._styleContent();
-dojo.style(this.insideNode,"visibility","visible");
-this.onReady();
-},_connectInput:function(){
-this._disconnect();
-this._cons.push(dojo.connect(this._fileInput,"mouseover",this,function(evt){
-dojo.addClass(this.domNode,this.hoverClass);
-this.onMouseOver(evt);
-}));
-this._cons.push(dojo.connect(this._fileInput,"mouseout",this,function(evt){
-dojo.removeClass(this.domNode,this.activeClass);
-dojo.removeClass(this.domNode,this.hoverClass);
-this.onMouseOut(evt);
-this._checkHtmlCancel("off");
-}));
-this._cons.push(dojo.connect(this._fileInput,"mousedown",this,function(evt){
-dojo.addClass(this.domNode,this.activeClass);
-dojo.removeClass(this.domNode,this.hoverClass);
-this.onMouseDown(evt);
-}));
-this._cons.push(dojo.connect(this._fileInput,"mouseup",this,function(evt){
-dojo.removeClass(this.domNode,this.activeClass);
-this.onMouseUp(evt);
-this.onClick(evt);
-this._checkHtmlCancel("up");
-}));
-this._cons.push(dojo.connect(this._fileInput,"change",this,function(){
-this._checkHtmlCancel("change");
-this._change([{name:this._fileInput.value,type:"",size:0}]);
-}));
-if(this.tabIndex>=0){
-dojo.attr(this.domNode,"tabIndex",this.tabIndex);
-}
-},_checkHtmlCancel:function(_38){
-if(_38=="change"){
-this.dialogIsOpen=false;
-}
-if(_38=="up"){
-this.dialogIsOpen=true;
-}
-if(_38=="off"){
-if(this.dialogIsOpen){
-this.onCancel();
-}
-this.dialogIsOpen=false;
-}
-},_styleContent:function(){
-var o=this.fhtml.nr;
-dojo.style(this.insideNode,{width:o.w+"px",height:o.va=="middle"?o.h+"px":"auto",textAlign:o.ta,paddingTop:o.p[0]+"px",paddingRight:o.p[1]+"px",paddingBottom:o.p[2]+"px",paddingLeft:o.p[3]+"px"});
-try{
-dojo.style(this.insideNode,"lineHeight","inherit");
-}
-catch(e){
-}
-},_resetHTML:function(){
-if(this.uploaderType=="html"&&this._formNode){
-this.fileInputs=[];
-dojo.query("*",this._formNode).forEach(function(n){
-dojo.destroy(n);
-});
-this.fileCount=0;
-this._buildFileInput();
-this._connectInput();
-}
-},_buildForm:function(){
-if(this._formNode){
-return;
-}
-if(dojo.isIE){
-this._formNode=document.createElement("<form enctype=\"multipart/form-data\" method=\"post\">");
-this._formNode.encoding="multipart/form-data";
-}else{
-this._formNode=document.createElement("form");
-this._formNode.setAttribute("enctype","multipart/form-data");
-}
-this._formNode.id=dijit.getUniqueId("FileUploaderForm");
-this.domNode.appendChild(this._formNode);
-},_buildFileInput:function(){
-if(this._fileInput){
-this._disconnect();
-this._fileInput.id=this._fileInput.id+this.fileCount;
-dojo.style(this._fileInput,"display","none");
-}
-this._fileInput=document.createElement("input");
-this.fileInputs.push(this._fileInput);
-var nm=this.htmlFieldName;
-var _39=this.id;
-if(this.selectMultipleFiles){
-nm+=this.fileCount;
-_39+=this.fileCount;
-this.fileCount++;
-}
-dojo.attr(this._fileInput,{id:this.id,name:nm,type:"file"});
-dojo.addClass(this._fileInput,"dijitFileInputReal");
-this._formNode.appendChild(this._fileInput);
-var _3a=dojo.marginBox(this._fileInput);
-dojo.style(this._fileInput,{position:"relative",left:(this.fhtml.nr.w-_3a.w)+"px",opacity:0});
-},_renumberInputs:function(){
-if(!this.selectMultipleFiles){
-return;
-}
-var nm;
-this.fileCount=0;
-dojo.forEach(this.fileInputs,function(inp){
-nm=this.htmlFieldName+this.fileCount;
-this.fileCount++;
-dojo.attr(inp,"name",nm);
-},this);
-},_setFormStyle:function(){
-var _3b=Math.max(2,Math.max(Math.ceil(this.fhtml.nr.w/60),Math.ceil(this.fhtml.nr.h/15)));
-dojox.html.insertCssRule("#"+this._formNode.id+" input","font-size:"+_3b+"em");
-dojo.style(this.domNode,{overflow:"hidden",position:"relative"});
-dojo.style(this.insideNode,"position","absolute");
-},_setHtmlPostData:function(){
-if(this.postData){
-for(var nm in this.postData){
-dojo.create("input",{type:"hidden",name:nm,value:this.postData[nm]},this._formNode);
-}
-}
-},uploadFlash:function(){
-try{
-if(this.showProgress){
-this._displayProgress(true);
-var c=dojo.connect(this,"_complete",this,function(){
-dojo.disconnect(c);
-this._displayProgress(false);
-});
-}
-this.flashMovie.doUpload(this.postData);
-}
-catch(err){
-this._error("FileUploader - Sorry, the SWF failed to initialize."+err);
-}
-},createFlashUploader:function(){
-this.uploadUrl=this.uploadUrl.toString();
-if(this.uploadUrl){
-if(this.uploadUrl.toLowerCase().indexOf("http")<0&&this.uploadUrl.indexOf("/")!=0){
-var loc=window.location.href.split("/");
-loc.pop();
-loc=loc.join("/")+"/";
-this.uploadUrl=loc+this.uploadUrl;
-this.log("SWF Fixed - Relative loc:",loc," abs loc:",this.uploadUrl);
-}else{
-this.log("SWF URL unmodified:",this.uploadUrl);
-}
-}else{
-console.warn("Warning: no uploadUrl provided.");
-}
-var w=this.fhtml.nr.w;
-var h=this.fhtml.nr.h;
-var _3c={expressInstall:true,path:this.swfPath.uri||this.swfPath,width:w,height:h,allowScriptAccess:"always",allowNetworking:"all",vars:{uploadDataFieldName:this.flashFieldName,uploadUrl:this.uploadUrl,uploadOnSelect:this.uploadOnChange,deferredUploading:this.deferredUploading||0,selectMultipleFiles:this.selectMultipleFiles,id:this.id,isDebug:this.isDebug,devMode:this.devMode,flashButton:dojox.embed.flashVars.serialize("fh",this.fhtml),fileMask:dojox.embed.flashVars.serialize("fm",this.f [...]
-this.flashObject=new dojox.embed.Flash(_3c,this.insideNode);
-this.flashObject.onError=dojo.hitch(function(msg){
-this._error("Flash Error: "+msg);
-});
-this.flashObject.onReady=dojo.hitch(this,function(){
-dojo.style(this.insideNode,"visibility","visible");
-this.log("FileUploader flash object ready");
-this.onReady(this);
-});
-this.flashObject.onLoad=dojo.hitch(this,function(mov){
-this.flashMovie=mov;
-this.flashReady=true;
-this.onLoad(this);
-});
-this._connectFlash();
-},_connectFlash:function(){
-this._doSub("/filesSelected","_change");
-this._doSub("/filesUploaded","_complete");
-this._doSub("/filesProgress","_progress");
-this._doSub("/filesError","_error");
-this._doSub("/filesCanceled","onCancel");
-this._doSub("/stageBlur","_onFlashBlur");
-this._doSub("/up","onMouseUp");
-this._doSub("/down","onMouseDown");
-this._doSub("/over","onMouseOver");
-this._doSub("/out","onMouseOut");
-this.connect(this.domNode,"focus",function(){
-this.flashMovie.focus();
-this.flashMovie.doFocus();
+
+
+	//	Usage Notes:
+	//		To center text vertically, use vertical-align:middle;
+	//			which emulates a boxModel button. Using line-height to center text
+	//			can cause height problems in IE6
+
+
+dojo.declare("dojox.form.FileUploader", [dijit._Widget, dijit._Templated, dijit._Contained], {
+	// version:
+	//		1.4
+	// summary:
+	// 		Handles File Uploading to a server (PHP script included for testing)
+	//
+	//		***NEW: FileUploader is now a WIDGET. You do not have to pass a button
+	//		in. Passing a button is still supported until version 1.5 to maintain
+	//		backwards compatibility, but it is not reccomended. Just create your
+	//		uploader like any other widget.
+	//
+	// description:
+	//		If the correct version of Flash Player is available (> 9.0) , a SWF
+	//		is used. If Flash Player is not installed or is outdated, a typical
+	//		html fileInput is used. This process can be overridden with
+	//		force:"flash" or force:"html".
+	//
+	//		FileUploader works with Flash 10.
+	//
+	//		***NEW: The button styles are now recreated in Flash, so there is no longer
+	//		using an invisible Flash movie with wmode=transparent. This way the Flash button
+	//		is actually placed inline with the DOM, not floating above it and constantly
+	//		resetting its position. The "Windows Firefox clickable bug" should be fixed (and
+	//		hopefully some Linux problems).
+	//
+	//		***NEW: The HTML button is created in a new way and it is now inline as is the
+	//		FLash button. Styling is much easier and more versatile.
+	//
+	//	Dependencies:
+	//		FileUploader no longer uses FileInput.css. It now uses FileUploader.css
+	//		See requires for JavaScript dependencies.
+	//
+	//	NEW FEATURES -
+	//		There are a ton of features and fixes in this version.
+	//			Disabled: Can be toggled with widget.attr("disable", true|false)
+	//			Submit: A convenience method has been added for if the uploader is in a form.
+	//					Instead of submitting the form, call uploader.submit(theForm), and the
+	//					Uploader will handle all of the form values and post the data.
+	//			Selected List: If passing the ID of a container, the Uploaders will populate it
+	//					with the selected files.
+	//			Deleting Files: You can now delete pending files.
+	//			Progress Built in: showProgress:true will change the button to a progress
+	//					bar on upload.
+	//			Progress Attach: Passing progressWidgetId will tell the Uploader of a progress
+	//					widget. If the Progress widget is initially hidden, it will change to
+	//					visible and then restored after upload.
+	//			A11Y: The Flash button can be accessed with the TAB key. (The HTML cannot due
+	//					to browser limtations)
+	//			Deferred Uploading: (Flash only) throttles the upload to one file at a time
+	//
+	//
+	//	CDN USERS -
+	//		FileUpload now works with the CDN but with limitations. The SWF must
+	//		be from the same domain as the HTML page. 'swfPath' has been exposed
+	//		so that you may link to that file (could of course be the same SWF in
+	//		dojox resource folder). The SWF will *NOT* work from the
+	//		CDN server. This would require a special XML file that would allow
+	//		access to your server, and the logistics to that is impossible.
+	//
+	//	LIMITATIONS
+	//		- This is not designed to be a part of a form, it contains its own. (See submit())
+	//		- Currently does not in a Dialog box or a Tab where it is not initially visible,
+	//		- The default style inherits font sizes - but a parent container should have a font size
+	//			set somewhere of the results could be inconsistent.
+	//
+	//	OPERA USERS -
+	//		It works better than the 1.3 version. fileInputs apperantly can't have opacity
+	//		set to zero. The Flash uploader works but files are auto-uploaded. Must be a
+	//		flashVar problem.
+	//
+	//	Safari Bug note:
+	//	The bug is in the way Safari handles the connection:
+	//		https://bugs.webkit.org/show_bug.cgi?id=5760
+	//		I added this to the virtual host in the Apache conf file, and now it
+	//		works like a charm:
+	//		BrowserMatch Safari nokeepalive
+	//
+	swfPath: dojo.config.uploaderPath || dojo.moduleUrl("dojox.form", "resources/uploader.swf"),
+
+
+	templateString:'<div><div dojoAttachPoint="progNode"><div dojoAttachPoint="progTextNode"></div></div><div dojoAttachPoint="insideNode" class="uploaderInsideNode"></div></div>',
+
+	// uploadUrl: String
+	//		The url targeted for upload. An absolute URL is preferred. Relative URLs are
+	//		changed to absolute.
+	uploadUrl: "",
+	//
+	//	button: dijit.form.Button or a domNode
+	// 		DEPRECATED: The "fake" button that when clicked, launches the upload dialog
+	// button:"",
+	//
+	//	isDebug: Boolean
+	//		If true, outputs traces from the SWF to console. What exactly gets passed
+	//		is very relative, and depends upon what traces have been left in the DEFT SWF.
+	isDebug:false,
+	//
+	//	devMode: Boolean.
+	//		Re-implemented. devMode increases the logging, adding style tracing from the SWF.
+	devMode:false,
+	//
+	//	id: String
+	//		The object id, just like any other widget in Dojo. However, this id
+	//		is also used as a reference for the SWF
+	// id: "",
+	//
+	//	baseClass: String
+	//		The name of the class that will style the button in a "normal" state.
+	//		If baseClass is not defined, 'class' will be used.
+	//		NOTE: By default the uploader will be styled like a dijit buttons and
+	//		adhere to the the themes. Tundra, Soria, and Nihilo are supported.
+	//		You can cascade the existing style by using 'class' or 'style'. If you
+	//		overwrite baseClass, you should overwrite the remaing state classes
+	//		that follow) as well.
+	baseClass:"dojoxUploaderNorm",
+	//
+	//	hoverClass: String
+	//		The name of the class that will style the button in a "hover" state. A specific
+	//		class should be made to do this. Do not rely on a target like button:hover{...}
+	hoverClass:"dojoxUploaderHover",
+	//
+	//	activeClass: String
+	//		The name of the class that will style the button in a "press" state. A specific
+	//		class should be made to do this. Do not rely on a target like button:active{...}
+	activeClass:"dojoxUploaderActive",
+	//
+	//	disabledClass: String
+	//		The name of the class that will style the button when its disabled.
+	disabledClass:"dojoxUploaderDisabled",
+	//
+	//	force: String
+	//		Use "flash" to always use Flash (and hopefully force the user to download the plugin
+	//		if they don't have it). Use "html" to always use the HTML uploader. An empty string
+	//		(default) will check for the right version of Flash and use HTML if not available.
+	force:"",
+	//
+	//	uploaderType: [readonly] String
+	//		Internal. What type of uploader is being used: "flash" or "html"
+	uploaderType:"",
+	//
+	//	flashObject: [readonly] dojox.embed.Flash
+	//		The object that creates the SWF embed object. Mostly Internal.
+	flashObject: null,
+	//
+	//	flashMovie: [readonly] Function
+	//		The SWF. Mostly Internal.
+	flashMovie: null,
+	//
+	//	flashDiv: [readonly] HTMLNode
+	//		DEPRECATED for insideNode
+	//		The div that holds the SWF and form/fileInput
+	flashDiv: null,
+	//
+	//	insideNode: [readonly] HTMLNode
+	//		The div that holds the SWF and form/fileInput
+	insideNode: null,
+	//
+	//	deferredUploading: Number (1 - X)
+	//		(Flash only) throttles the upload to a certain amount of files at a time.
+	//		By default, Flash uploads file one at a time to the server, but in parallel.
+	//		Firefox will try to queue all files at once, leading to problems. Set this
+	//		to the amount to upload in parallel at a time.
+	//		Generally, 1 should work fine, but you can experiment with queuing more than
+	//		one at a time.
+	//		This is of course ignored if selectMultipleFiles equals false.
+	deferredUploading:1,
+	//
+	//	fileListId: String
+	//		The id of a dom node to be used as a container for the pending file list.
+	fileListId:"",
+	//
+	//	uploadOnChange: Boolean
+	//		If true, uploads imediately after a file has been selected. If false,
+	//		waits for upload() to be called.
+	uploadOnChange: false,
+	//
+	//	selectMultipleFiles: Boolean
+	//		If true and flash mode, multiple files may be selected from the dialog.
+	//		If html mode, files are not uploaded until upload() is called. The references
+	//		to each file is incremented:uploadedfile0, uploadedfile1, uploadedfile2... etc.
+	selectMultipleFiles: true,
+	//
+	//	htmlFieldName: String
+	//		The name of the field of the fileInput that the server is expecting
+	htmlFieldName:"uploadedfile",
+	//
+	//	flashFieldName: String
+	//		The name of the field of the flash uploaded files that the server is expecting
+	flashFieldName:"flashUploadFiles",
+	//
+	// fileMask:  Array[ Array[Description, FileTypes], Array[...]...]
+	// 		(an array, or an array of arrays)
+	//		Restrict file selection to certain file types
+	// 		Empty array defaults to "All Files"
+	// example:
+	//	fileMask = ["Images", "*.jpg;*.jpeg;*.gif;*.png"]
+	//	or
+	//	fileMask = [
+	//		["Jpeg File", 	"*.jpg;*.jpeg"],
+	//		["GIF File", 	"*.gif"],
+	//		["PNG File", 	"*.png"],
+	//		["All Images", 	"*.jpg;*.jpeg;*.gif;*.png"],
+	//	]
+	//	NOTE: MacType is not supported, as it does not work very well.
+	//			fileMask will work on a Mac, but differently than
+	//			Windows.
+	fileMask: null,
+	//
+	//	minFlashVersion: Number
+	//		The minimum of version of Flash player to target. 0 would always install Flash, 100
+	//		would never install it. The Flash Player has supported multiple uploads since
+	//		version 8, so it could go as low as that safely.
+	minFlashVersion:9,
+	//
+	//	tabIndex: Number|String
+	//		The tab order in the DOM. Only supported by Flash. HTML Uploaders have security
+	//		protection to prevent you from tabbing to the uploader. Stupid.
+	tabIndex:-1,
+	//
+	//	showProgress: Boolean
+	//		If true, the button changes to a progress bar during upload.
+	showProgress:false,
+	//
+	//	progressMessage: String
+	//		The message shown while the button is changed to a progress bar
+	progressMessage:"Loading",
+	//
+	//	progressBackgroundUrl: String|Uri
+	//		The background image to use for the button-progress
+	progressBackgroundUrl:dojo.moduleUrl("dijit", "themes/tundra/images/buttonActive.png"),
+	//
+	//	progressBackgroundColor: String|Number
+	//		The background color to use for the button-progress
+	progressBackgroundColor:"#ededed",
+	//
+	//	progressWidgetId:String
+	//		The widget id of a Dijit Progress bar. The Uploader will bind to it and update it
+	//		automatically.
+	progressWidgetId:"",
+	//
+	// skipServerCheck: Boolean
+	// 		If true, will not verify that the server was sent the correct format.
+	//		This can be safely set to true. The purpose of the server side check
+	//		is mainly to show the dev if they've implemented the different returns
+	//		correctly.
+	skipServerCheck:false,
+	//
+	// serverTimeout:Number (milliseconds)
+	//		The amount of time given to the uploaded file
+	//		to wait for a server response. After this amount
+	//		of time, the onComplete is fired but with a 'server timeout'
+	//		error in the returned item.
+	serverTimeout: 5000,
+
+
+	log: function(){
+		//	summary:
+		//		Due to the excessive logging necessary to make this code happen,
+		//		It's easier to turn it on and off here in one place.
+		//		Also helpful if there are multiple uploaders on one page.
+		if(this.isDebug){
+			console["log"](Array.prototype.slice.call(arguments).join(" "));
+		}
+	},
+
+	constructor: function(){
+		this._subs = [];
+	},
+
+	postMixInProperties: function(){
+		// internal stuff:
+		this.fileList = [];
+		this._cons = [];
+		this.fileMask = this.fileMask || [];
+		this.fileInputs = [];
+		this.fileCount = 0;
+		this.flashReady = false;
+		this._disabled = false;
+		this.force = this.force.toLowerCase(); // Pete FTW.
+		this.uploaderType = ((dojox.embed.Flash.available >= this.minFlashVersion || this.force=="flash") && this.force != "html") ? "flash" : "html";
+		this.deferredUploading = this.deferredUploading===true ? 1 : this.deferredUploading;
+
+		this._refNode = this.srcNodeRef;
+
+		this.getButtonStyle();
+
+
+	},
+
+	startup: function(){
+
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+
+		// internal stuff:
+		this.setButtonStyle();
+		var createMethod;
+		if(this.uploaderType == "flash"){
+			createMethod = "createFlashUploader";
+		}else{
+			this.uploaderType = "html";
+			createMethod = "createHtmlUploader";
+
+		}
+
+		var w = this.getHiddenWidget();
+		if(w){
+			var __c = dojo.connect(w, "onShow", this, function(){
+				dojo.disconnect(__c);
+				this[createMethod]();
+			});
+		}else{
+			this[createMethod]();
+		}
+
+		if(this.fileListId){
+			this.connect(dojo.byId(this.fileListId), "click", function(evt){
+				var p = evt.target.parentNode.parentNode.parentNode; // in a table
+				if(p.id && p.id.indexOf("file_")>-1){
+					this.removeFile(p.id.split("file_")[1]);
+				}
+			});
+		}
+
+		// cleaning up solves memory leak issues in the HTML version
+		dojo.addOnUnload(this, this.destroy);
+	},
+
+	getHiddenWidget: function(){
+		// summary:
+		//		Internal.
+		//		If a parent widget has an onShow event, it is assumed
+		//		that it is hidden and the parsing of the uploader is
+		//		delayed until onShow fires. Note that the widget must
+		//		fire onShow even if it is defaulted to showing/selected.
+		//		this seems to work for Tabs (the primary fix).
+		//
+		var node = this.domNode.parentNode;
+		while(node){
+			var id = node.getAttribute && node.getAttribute("widgetId");
+			if(id && dijit.byId(id).onShow){
+				return dijit.byId(id);
+			}
+			node = node.parentNode;
+		}
+		return null;
+	},
+
+	getHiddenNode: function(/*DomNode*/ node){
+		// summary:
+		//		Internal.
+		//		If a parent node is styled as display:none,
+		//		returns that node. This node will be temporarilly
+		//		changed to display:block. Note if the node is in
+		//		a widget that has an onShow event, this is
+		//		overridden.
+		//
+		if(!node){ return null; }
+		var hidden = null;
+		var p = node.parentNode;
+		while(p.tagName.toLowerCase() != "body"){
+			var d = dojo.style(p, "display");
+			if(d == "none"){
+				hidden = p;
+				break;
+			}
+			p = p.parentNode
+		}
+		return hidden;
+	},
+
+	getButtonStyle: function(){
+		// summary:
+		//		Internal.
+		//		Get necessary style information from srcRefNode and
+		//		assigned styles
+		//
+
+
+		// TODO:
+		//		To call this from postCreate....
+		//		could do the style stuff initially, but if hidden they will be bad sizes
+		//		could then redo the sizes
+		//		alt is to create a genuine button and copy THAT	instead of how doing now
+
+		var refNode = this.srcNodeRef;
+		this._hiddenNode = this.getHiddenNode(refNode);
+		if(this._hiddenNode){
+			console.info("Turning on hidden node")
+			dojo.style(this._hiddenNode, "display", "block");
+		}
+
+
+		if(this.button){
+			console.warn("DEPRECATED: FileUploader.button - will be removed in 1.5. FileUploader should be created as widget.");
+		}
+		if(!refNode && this.button && this.button.domNode){
+			// backwards compat for a Dijit button
+			var isDijitButton = true;
+			var cls = this.button.domNode.className + " dijitButtonNode";
+			var txt = this.getText(dojo.query(".dijitButtonText", this.button.domNode)[0]);
+			var domTxt = '<button id="'+this.button.id+'" class="'+cls+'">'+txt+'</button>';
+			refNode = dojo.place(domTxt, this.button.domNode, "after");	 /// Pete doesn't like this?
+			this.srcNodeRef = refNode;
+			this.button.destroy();
+
+			this.baseClass = "dijitButton";
+			this.hoverClass = "dijitButtonHover";
+			this.pressClass = "dijitButtonActive";
+			this.disabledClass = "dijitButtonDisabled";
+
+		}else if(!this.srcNodeRef && this.button){
+			refNode = this.button;
+		}
+
+		if(dojo.attr(refNode, "class")){
+			this.baseClass += " " + dojo.attr(refNode, "class");
+		}
+		dojo.attr(refNode, "class", this.baseClass);
+
+
+		this.norm = this.getStyle(refNode);
+		this.width = this.norm.w;
+		this.height = this.norm.h;
+
+		if(this.uploaderType == "flash"){
+
+			this.over = this.getTempNodeStyle(refNode, this.baseClass+" "+this.hoverClass, isDijitButton);
+			this.down = this.getTempNodeStyle(refNode, this.baseClass+" "+this.activeClass, isDijitButton);
+			this.dsbl = this.getTempNodeStyle(refNode, this.baseClass+" "+this.disabledClass, isDijitButton);
+
+			this.fhtml = {
+				cn:this.getText(refNode),
+				nr:this.norm,
+				ov:this.over,
+				dn:this.down,
+				ds:this.dsbl
+			};
+		}else{
+			this.fhtml = {
+				cn:this.getText(refNode),
+				nr:this.norm
+			}
+			if(this.norm.va == "middle"){
+				this.norm.lh = this.norm.h;
+			}
+		}
+
+		if(this.devMode){
+			this.log("classes - base:", this.baseClass, " hover:", this.hoverClass, "active:", this.activeClass);
+			this.log("fhtml:", this.fhtml)
+			this.log("norm:", this.norm)
+			this.log("over:", this.over)
+			this.log("down:", this.down)
+
+		}
+	},
+
+	setButtonStyle: function(){
+		// summary:
+		//		Internal.
+		//		Set up internal dom nodes for button construction.
+		//
+		dojo.style(this.domNode, {
+			width:this.fhtml.nr.w+"px",
+			height:(this.fhtml.nr.h)+"px",
+			padding:"0px",
+			lineHeight: "normal",
+			position:"relative"
+		});
+		if(this.uploaderType == "html" && this.norm.va == "middle"){
+			dojo.style(this.domNode, "lineHeight", this.norm.lh + "px");
+		}
+		if(this.showProgress){
+			this.progTextNode.innerHTML = this.progressMessage;
+			dojo.style(this.progTextNode, {
+				width:this.fhtml.nr.w+"px",
+				height:(this.fhtml.nr.h+0)+"px",
+				padding:"0px",
+				margin:"0px",
+				left:"0px",
+				lineHeight:(this.fhtml.nr.h+0)+"px",
+				position:"absolute"
+			});
+			dojo.style(this.progNode, {
+				width:this.fhtml.nr.w+"px",
+				height:(this.fhtml.nr.h+0)+"px",
+				padding:"0px",
+				margin:"0px",
+				left:"0px",
+				position:"absolute",
+				display:"none",
+				backgroundImage:"url("+this.progressBackgroundUrl+")",
+				backgroundPosition:"bottom",
+				backgroundRepeat:"repeat-x",
+				backgroundColor:this.progressBackgroundColor
+			});
+		}else{
+			dojo.destroy(this.progNode);
+		}
+		dojo.style(this.insideNode,{
+			position:"absolute",
+			top:"0px",
+			left:"0px",
+			display:""
+		});
+		dojo.addClass(this.domNode, this.srcNodeRef.className);
+		if(this.fhtml.nr.d.indexOf("inline")>-1){
+			dojo.addClass(this.domNode, "dijitInline");
+		}
+
+		try{
+			this.insideNode.innerHTML = this.fhtml.cn;
+		}catch(e){
+			// You have got to be kidding me. IE does us he favor of checking that
+			//	we aren't inserting the improper type of content with innerHTML into
+			//	an inline element. Alert us with an "Unknown Runtime Error". You can't
+			//	MAKE this stuff up.
+			//
+			if(this.uploaderType == "flash"){
+			this.insideNode = this.insideNode.parentNode.removeChild(this.insideNode);
+				dojo.body().appendChild(this.insideNode);
+				this.insideNode.innerHTML = this.fhtml.cn;
+				var c = dojo.connect(this, "onReady", this, function(){ dojo.disconnect(c);
+					this.insideNode = this.insideNode.parentNode.removeChild(this.insideNode);
+					this.domNode.appendChild(this.insideNode);
+				});
+			}else{
+				this.insideNode.appendChild(document.createTextNode(this.fhtml.cn));
+			}
+		}
+		this.flashDiv = this.insideNode; //backwards compat - rem in 1.5
+		if(this._hiddenNode){
+			dojo.style(this._hiddenNode, "display", "none");
+		}
+	},
+
+
+	/*************************
+	 *	   Public Events	 *
+	 *************************/
+
+	// The following events are inherited from _Widget and still may be connected:
+	// onClick
+	// onMouseUp
+	// onMouseDown
+	// onMouseOver
+	// onMouseOut
+
+	onChange: function(dataArray){
+		//	summary:
+		// 		stub to connect
+		// 		Fires when files are selected
+		// 		Event is an array of last files selected
+	},
+
+	onProgress: function(dataArray){
+		// summary:
+		// 		Stub to connect
+		// 		Fires as progress returns from SWF
+		// 		Event is an array of all files uploading
+		//		Can be connected to for HTML uploader,
+		//		but will not return anything.
+	},
+
+	onComplete: function(dataArray){
+		// summary:
+		// 		stub to connect
+		// 		Fires when all files have uploaded
+		// 		Event is an array of all files
+	},
+
+	onCancel: function(){
+		// summary:
+		// 		Stub to connect
+		// 		Fires when dialog box has been closed
+		//		without a file selection
+	},
+
+	onError: function(/* Object or String */evtObject){
+		// summary:
+		//		Fires on errors
+		//
+		//FIXME: Unsure of a standard form for receiving errors
+	},
+
+	onReady: function(/* dojox.form.FileUploader */ uploader){
+		// summary:
+		//		Stub - Fired when dojox.embed.Flash has created the
+		//		Flash object, but it has not necessarilly finished
+		//		downloading, and is ready to be communicated with.
+	},
+
+	onLoad: function(/* dojox.form.FileUploader */ uploader){
+		// summary:
+		//		Stub - SWF has been downloaded 100%.
+	},
+
+	/*************************
+	 *	   Public Methods	 *
+	 *************************/
+	submit: function(/* form node ? */form){
+		// summary:
+		//		If FileUploader is in a form, and other data should be sent
+		//		along with the files, use this instead of form submit.
+		//
+		var data = form ? dojo.formToObject(form) : null;
+		this.upload(data);
+		return false; // Boolean
+	},
+	upload: function(/*Object ? */data){
+		// summary:
+		// 		When called, begins file upload
+		//	data: Object
+		//		postData to be sent to server
+		//
+		if(!this.fileList.length){
+			return false;
+		}
+		if(!this.uploadUrl){
+			console.warn("uploadUrl not provided. Aborting.");
+			return false;
+		}
+		if(!this.showProgress){
+			this.set("disabled", true);
+		}
+
+		if(this.progressWidgetId){
+
+			var node = dijit.byId(this.progressWidgetId).domNode;
+			if(dojo.style(node, "display") == "none"){
+				this.restoreProgDisplay = "none";
+				dojo.style(node, "display", "block");
+			}
+			if(dojo.style(node, "visibility") == "hidden"){
+				this.restoreProgDisplay = "hidden";
+				dojo.style(node, "visibility", "visible");
+			}
+		}
+
+		if(data && !data.target){
+			this.postData = data;
+		}
+		this.log("upload type:", this.uploaderType, " - postData:", this.postData);
+
+		for (var i = 0; i < this.fileList.length; i++){
+			var f = this.fileList[i];
+			f.bytesLoaded = 0;
+			f.bytesTotal = f.size || 100000;
+			f.percent = 0;
+		}
+		if(this.uploaderType == "flash"){
+			this.uploadFlash();
+		}else{
+			this.uploadHTML();
+		}
+		// prevent form submit
+		return false;
+	},
+	removeFile: function(/*String*/name, /*Boolean*/noListEdit){
+		// summary:
+		//		Removes a file from the pending file list.
+		//		Removes pending data from the Flash movie
+		//		and fileInputes from the HTML uploader.
+		//		If a file container node is bound, the file
+		//		will also be removed.
+		// name:String
+		//		The name of the file to be removed. Typically the file name,
+		//		such as: picture01.png
+		// noListEdit:Boolean
+		//		Internal. If true don't remove files from list.
+		//
+		var i;
+		for(i = 0; i < this.fileList.length; i++){
+			if(this.fileList[i].name == name){
+				if(!noListEdit){ // if onComplete, don't do this
+					this.fileList.splice(i,1);
+				}
+				break;
+			}
+		}
+		if(this.uploaderType == "flash"){
+			this.flashMovie.removeFile(name);
+		}else if(!noListEdit){
+			dojo.destroy(this.fileInputs[i]);
+			this.fileInputs.splice(i,1);
+			this._renumberInputs();
+		}
+		if(this.fileListId){
+			dojo.destroy("file_"+name);
+		}
+	},
+	destroyAll: function(){
+		//	summary:
+		// 		Destroys button
+		console.warn("DEPRECATED for 1.5 - use destroy() instead");
+		this.destroy();
+	},
+
+	destroy: function(){
+		//	summary:
+		//		Destroys uploader button
+		if(this.uploaderType == "flash" && !this.flashMovie){
+			this._cons.push(dojo.connect(this, "onLoad", this, "destroy"));
+			return;
+		}
+		dojo.forEach(this._subs, dojo.unsubscribe, dojo);
+		dojo.forEach(this._cons, dojo.disconnect, dojo);
+		if(this.scrollConnect){
+			dojo.disconnect(this.scrollConnect);
+		}
+		if(this.uploaderType == "flash"){
+			this.flashObject.destroy();
+			dojo.destroy(this.flashDiv);
+		}else{
+			dojo.destroy("dojoIoIframe");
+			dojo.destroy(this._fileInput);
+			dojo.destroy(this._formNode);
+		}
+		this.inherited(arguments);
+	},
+	hide: function(){
+		//	summary:
+		//		Hides the upload button.
+		console.warn("DEPRECATED for 1.5 - use dojo.style(domNode, 'display', 'none' instead");
+		dojo.style(this.domNode, 'display', 'none');
+	},
+
+	show: function(){
+		//	summary:
+		//		Shows the upload button. This is called
+		//		when within a dialog.
+		console.warn("DEPRECATED for 1.5 - use dojo.style(domNode, 'display', '') instead");
+		dojo.style(this.domNode, 'display', '');
+	},
+	disable: function(/*Boolean*/disabled){
+		console.warn("DEPRECATED: FileUploader.disable() - will be removed in 1.5. Use set('disable', true) instead.")
+		this.set("disable", disabled);
+	},
+	/*************************
+	 *	   Private Events	 *
+	 *************************/
+	_displayProgress: function(/*Boolean or Number */display){
+		// summary:
+		//		Shows and updates the built-in progress bar.
+		//
+		if(display === true){
+			if(this.uploaderType == "flash"){
+				dojo.style(this.insideNode,"left", "-2500px");
+			}else{
+				dojo.style(this.insideNode,"display", "none");
+			}
+			dojo.style(this.progNode,"display","");
+		}else if(display === false){
+			dojo.style(this.insideNode,{
+				display: "",
+				left: "0px"
+			});
+			dojo.style(this.progNode,"display","none");
+		}else{
+			var w = display * this.fhtml.nr.w;
+			dojo.style(this.progNode, "width", w + "px");
+		}
+	},
+	_animateProgress: function(){
+		// summary:
+		//		Internal. Animated the built-in progress bar
+		this._displayProgress(true);
+		var _uploadDone = false;
+		var c = dojo.connect(this, "_complete", function(){
+			dojo.disconnect(c);
+			_uploadDone = true;
+		});
+		var w = 0;
+		var interval = setInterval(dojo.hitch(this, function(){
+			w+=5;
+			if(w>this.fhtml.nr.w){
+				w = 0;
+				_uploadDone = true;
+			}
+			this._displayProgress(w/this.fhtml.nr.w);
+
+			if(_uploadDone){
+				clearInterval(interval);
+				setTimeout(dojo.hitch(this, function(){
+					this._displayProgress(false);
+				}), 500);
+			}
+
+		}),50);
+	},
+
+	_error: function(evt){
+		//var type = evtObject.type ? evtObject.type.toUpperCase() : "ERROR";
+		//var msg = evtObject.msg ? evtObject.msg : evtObject;
+		if(typeof(evt)=="string"){
+			evt = new Error(evt);
+		}
+		this.onError(evt);
+	},
+
+	_addToFileList: function(){
+		// summary:
+		//		Internal only. If there is a file list, adds a file to it.
+		//		If you need to use a function such as this, connect to
+		//		onChange and update outside of this widget.
+		//
+		if(this.fileListId){
+			var str = '';
+			dojo.forEach(this.fileList, function(d){
+				// have to use tables because of IE. Grumble.
+				str += '<table id="file_'+d.name+'" class="fileToUpload"><tr><td class="fileToUploadClose"></td><td class="fileToUploadName">'+d.name+'</td><td class="fileToUploadSize">'+(d.size ? Math.ceil(d.size*.001) +"kb" : "")+'</td></tr></table>'
+			}, this);
+			dojo.byId(this.fileListId).innerHTML = str;
+		}
+	},
+
+	_change: function(dataArray){
+		// summary:
+		//		Internal. Updates uploader selection
+		if(dojo.isIE){
+			//IE6 uses the entire path in the name, which isn't terrible, but much different
+			// than everything else
+			dojo.forEach(dataArray, function(f){
+				f.name = f.name.split("\\")[f.name.split("\\").length-1];
+			});
+		}
+		if(this.selectMultipleFiles){
+			this.fileList = this.fileList.concat(dataArray);
+		}else{
+			if(this.fileList[0]){
+				this.removeFile(this.fileList[0].name, true);
+			}
+			this.fileList = dataArray;
+		}
+		this._addToFileList();
+		this.onChange(dataArray);
+		if(this.uploadOnChange){
+			if(this.uploaderType == "html"){
+				this._buildFileInput();
+			}
+			this.upload();
+		}else if(this.uploaderType == "html" && this.selectMultipleFiles){
+			this._buildFileInput();
+			this._connectInput();
+		}
+	},
+
+	_complete: function(dataArray){
+		// summary:
+		//		Internal. Handles tasks after files have finished uploading
+		//
+		dataArray = dojo.isArray(dataArray) ? dataArray : [dataArray];
+
+		// Yes. Yes I do have to do three loops here. ugh.
+		//
+		// Check if one of the files had an error
+		dojo.forEach(dataArray, function(f){
+			if(f.ERROR){ this._error(f.ERROR); }
+		}, this);
+
+		// Have to be set them all too 100%, because
+		// onProgress does not always fire
+		dojo.forEach(this.fileList, function(f){
+			f.bytesLoaded = 1;
+			f.bytesTotal = 1;
+			f.percent = 100;
+			this._progress(f);
+		}, this);
+		// we're done. remove files.
+		dojo.forEach(this.fileList, function(f){
+			this.removeFile(f.name, true);
+		}, this);
+
+		this.onComplete(dataArray);
+
+		this.fileList = [];
+		this._resetHTML();
+		this.set("disabled", false);
+
+
+		if(this.restoreProgDisplay){
+			// using timeout so prog shows on screen for at least a short time
+			setTimeout(dojo.hitch(this, function(){
+				dojo.style(dijit.byId(this.progressWidgetId).domNode,
+					this.restoreProgDisplay == "none" ? "display" : "visibility",
+					this.restoreProgDisplay
+				);
+			}), 500);
+		}
+
+	},
+
+	_progress: function(dataObject){
+		// summary:
+		//		Internal. Calculate progress
+		var total = 0;
+		var loaded = 0;
+		for (var i = 0; i < this.fileList.length; i++){
+			var f = this.fileList[i];
+			if(f.name == dataObject.name){
+				f.bytesLoaded = dataObject.bytesLoaded;
+				f.bytesTotal = dataObject.bytesTotal;
+				f.percent = Math.ceil(f.bytesLoaded / f.bytesTotal * 100);
+				this.log(f.name, "percent:", f.percent)
+			}
+			loaded += Math.ceil(.001 * f.bytesLoaded);
+			total += Math.ceil(.001 * f.bytesTotal);
+		}
+		var percent = Math.ceil(loaded / total * 100);
+		if(this.progressWidgetId){
+			dijit.byId(this.progressWidgetId).update({progress:percent+"%"});
+		}
+		if(this.showProgress){
+			this._displayProgress(percent * .01);
+		}
+		this.onProgress(this.fileList);
+
+	},
+	_getDisabledAttr: function(){
+		// summary:
+		//		Internal. To get disabled use: widget.attr("disabled");
+		return this._disabled;
+	},
+
+	_setDisabledAttr: function(disabled){
+		// summary:
+		//		Internal. To set disabled use: widget.attr("disabled", true | false);
+		if(this._disabled == disabled){ return; }
+
+		if(this.uploaderType == "flash"){
+			if(!this.flashReady){
+				var _fc = dojo.connect(this, "onLoad", this, function(){
+					dojo.disconnect(_fc);
+					this._setDisabledAttr(disabled);
+				});
+				return;
+			}
+			this._disabled = disabled;
+			this.flashMovie.doDisable(disabled);
+		}else{
+			this._disabled = disabled;
+			dojo.style(this._fileInput, "display", this._disabled ? "none" : "");
+		}
+		dojo.toggleClass(this.domNode, this.disabledClass, disabled);
+	},
+
+	_onFlashBlur: function(){
+		// summary:
+		//		Internal. Detects when Flash movies reliquishes focus.
+		//		We have to find all the tabIndexes in the doc and figure
+		//		out whom to give focus to next.
+		this.flashMovie.blur();
+		if(!this.nextFocusObject && this.tabIndex){
+			var nodes = dojo.query("[tabIndex]");
+			for(var i = 0; i<nodes.length; i++){
+				if(nodes[i].tabIndex >= Number(this.tabIndex)+1){
+					this.nextFocusObject = nodes[i];
+					break;
+				}
+			}
+		}
+		this.nextFocusObject.focus();
+	},
+	_disconnect: function(){
+		// summary:
+		//		Internal. Disconnects fileInput in favor of new one.
+		dojo.forEach(this._cons, dojo.disconnect, dojo);
+	},
+
+	/*************************
+	 *			HTML		 *
+	 *************************/
+	uploadHTML: function(){
+		// summary:
+		//		Internal. You could use this, but you should use upload() or submit();
+		//		which can also handle the post data.
+		//
+		// NOTE on deferredUploading:
+		// 		This is not enabled for HTML. Workaround would be to force
+		//		singleFile uploads.
+		//	TODO:
+		//		Investigate removing fileInputs and resending form
+		//		multiple times adding each fileInput
+		//
+		if(this.selectMultipleFiles){
+			dojo.destroy(this._fileInput);
+		}
+		this._setHtmlPostData();
+		if(this.showProgress){
+			this._animateProgress();
+		}
+		var dfd = dojo.io.iframe.send({
+			url: this.uploadUrl,
+			form: this._formNode,
+			handleAs: "json",
+			error: dojo.hitch(this, function(err){
+				this._error("HTML Upload Error:" + err.message);
+			}),
+			load: dojo.hitch(this, function(data, ioArgs, widgetRef){
+				this._complete(data);
+			})
+		});
+	},
+
+	createHtmlUploader: function(){
+		// summary:
+		//		Internal. Fires of methods to build HTML Uploader.
+		this._buildForm();
+		this._setFormStyle();
+		this._buildFileInput();
+		this._connectInput();
+		this._styleContent();
+		dojo.style(this.insideNode, "visibility", "visible");
+		this.onReady();
+	},
+
+	_connectInput: function(){
+		// summary:
+		//		Internal. HTML Uploader connections. These get disconnected
+		//		after upload or if multi upload.
+		this._disconnect();
+		this._cons.push(dojo.connect(this._fileInput, "mouseover", this, function(evt){
+			dojo.addClass(this.domNode, this.hoverClass);
+			this.onMouseOver(evt);
+		}));
+		this._cons.push(dojo.connect(this._fileInput, "mouseout", this, function(evt){
+			dojo.removeClass(this.domNode, this.activeClass);
+			dojo.removeClass(this.domNode, this.hoverClass);
+			this.onMouseOut(evt);
+			this._checkHtmlCancel("off");
+		}));
+		this._cons.push(dojo.connect(this._fileInput, "mousedown", this, function(evt){
+			dojo.addClass(this.domNode, this.activeClass);
+			dojo.removeClass(this.domNode, this.hoverClass);
+			this.onMouseDown(evt);
+		}));
+		this._cons.push(dojo.connect(this._fileInput, "mouseup", this, function(evt){
+			dojo.removeClass(this.domNode, this.activeClass);
+			this.onMouseUp(evt);
+			this.onClick(evt);
+			this._checkHtmlCancel("up");
+		}));
+		this._cons.push(dojo.connect(this._fileInput, "change", this, function(){
+			this._checkHtmlCancel("change");
+			this._change([{
+				name: this._fileInput.value,
+				type: "",
+				size: 0
+			}]);
+		}));
+		if(this.tabIndex>=0){
+			dojo.attr(this.domNode, "tabIndex", this.tabIndex);
+		}
+	},
+
+	_checkHtmlCancel: function(mouseType){
+		// summary:
+		//		Internal. Check if the dialog was opened and canceled without file selection.
+		if(mouseType == "change"){
+			this.dialogIsOpen = false;
+		}
+		if(mouseType == "up"){
+			this.dialogIsOpen = true;
+		}
+		if(mouseType == "off"){
+			if(this.dialogIsOpen){
+				this.onCancel();
+			}
+			this.dialogIsOpen = false;
+		}
+	},
+
+	_styleContent: function(){
+		// summary:
+		//		Internal.Apply style to node
+		var o = this.fhtml.nr;
+
+		dojo.style(this.insideNode, {
+			width:o.w+"px",
+			height:o.va == "middle"?o.h+"px":"auto",
+			textAlign:o.ta,
+			paddingTop:o.p[0]+"px",
+			paddingRight:o.p[1]+"px",
+			paddingBottom:o.p[2]+"px",
+			paddingLeft:o.p[3]+"px"
+		});
+
+		try{
+			dojo.style(this.insideNode, "lineHeight", "inherit");
+		}catch(e){
+			// There are certain cases where IE refuses to set lineHeight.
+			// For the life of me I cannot figure out the combination of
+			// styles that IE doesn't like. Steaming... Pile...
+		}
+
+	},
+	_resetHTML: function(){
+		// summary:
+		//		Internal. After upload, this is called to clear the form and build a new
+		//		fileInput.
+		if(this.uploaderType == "html" && this._formNode){
+			this.fileInputs = [];
+			dojo.query("*", this._formNode).forEach(function(n){
+				dojo.destroy(n);
+			});
+			this.fileCount = 0;
+			this._buildFileInput();
+			this._connectInput();
+		}
+	},
+	_buildForm: function(){
+		// summary:
+		//		Build the form that holds the fileInput
+		//
+		if(this._formNode){ return; }
+
+		if(dojo.isIE){
+			this._formNode = document.createElement('<form enctype="multipart/form-data" method="post">');
+			this._formNode.encoding = "multipart/form-data";
+		}else{
+			this._formNode = document.createElement('form');
+			this._formNode.setAttribute("enctype", "multipart/form-data");
+		}
+		this._formNode.id = dijit.getUniqueId("FileUploaderForm"); // needed for dynamic style
+		this.domNode.appendChild(this._formNode);
+	},
+
+	_buildFileInput: function(){
+		// summary:
+		//		Build the fileInput field
+		//
+		if(this._fileInput){
+			this._disconnect();
+			// FIXME:
+			//	Just hiding it which works, but we lose
+			//	reference to it and can't remove it from
+			//	the upload list.
+			this._fileInput.id = this._fileInput.id + this.fileCount;
+			dojo.style(this._fileInput, "display", "none");
+		}
+		this._fileInput = document.createElement('input');
+		this.fileInputs.push(this._fileInput);
+		// server will need to know this variable:
+		var nm = this.htmlFieldName;
+		var _id = this.id;
+		if(this.selectMultipleFiles){
+			nm += this.fileCount;
+			_id += this.fileCount;
+			this.fileCount++;
+		}
+
+		dojo.attr(this._fileInput, {
+			id:this.id,
+			name:nm,
+			type:"file"
+		});
+
+		dojo.addClass(this._fileInput, "dijitFileInputReal");
+		console.warn("BUILD FI")
+		this._formNode.appendChild(this._fileInput);
+		var real = dojo.marginBox(this._fileInput);
+		dojo.style(this._fileInput, {
+			position:"relative",
+			left:(this.fhtml.nr.w - real.w) + "px",
+			opacity:0
+		});
+	},
+
+	_renumberInputs: function(){
+		if(!this.selectMultipleFiles){ return; }
+		var nm;
+		this.fileCount = 0;
+		dojo.forEach(this.fileInputs, function(inp){
+			nm = this.htmlFieldName + this.fileCount;
+			this.fileCount++;
+			dojo.attr(inp, "name", nm);
+		}, this);
+	},
+
+	_setFormStyle: function(){
+		// summary:
+		//		Apply a dynamic style to the form and input
+		var size = Math.max(2, Math.max(Math.ceil(this.fhtml.nr.w / 60), Math.ceil(this.fhtml.nr.h / 15)));
+		// Now create a style associated with the form ID
+		dojox.html.insertCssRule("#" + this._formNode.id + " input", "font-size:" + size + "em");
+		dojo.style(this.domNode, {
+			overflow:"hidden",
+			position:"relative"
+		});
+		dojo.style(this.insideNode, "position", "absolute");
+	},
+
+	_setHtmlPostData: function(){
+		// summary:
+		//		Internal.Apply postData to hidden fields in form
+		if(this.postData){
+			for (var nm in this.postData){
+				dojo.create("input", {
+					type: "hidden",
+					name: nm,
+					value: this.postData[nm]
+				}, this._formNode);
+			}
+		}
+	},
+
+	/*************************
+	 *			FLASH		 *
+	 *************************/
+	uploadFlash: function(){
+		// summary:
+		//		Internal. You should use upload() or submit();
+		try{
+			if(this.showProgress){
+				this._displayProgress(true);
+				var c = dojo.connect(this, "_complete", this, function(){
+					dojo.disconnect(c);
+					this._displayProgress(false);
+				});
+			}
+
+			var o = {};
+			for(var nm in this.postData){
+				o[nm] = this.postData[nm];
+			}
+			console.warn("this.postData:", o)
+			this.flashMovie.doUpload(o);
+
+		}catch(err){
+			this._error("FileUploader - Sorry, the SWF failed to initialize." + err);
+		}
+	},
+
+	createFlashUploader: function(){
+		// summary:
+		//		Internal. Creates Flash Uploader
+		this.uploadUrl = this.uploadUrl.toString();
+		if(this.uploadUrl){
+			if(this.uploadUrl.toLowerCase().indexOf("http")<0 && this.uploadUrl.indexOf("/")!=0){
+				// Appears to be a relative path. Attempt to
+				//	convert it to absolute, so it will better
+				//target the SWF.
+				//
+				var loc = window.location.href.split("/");
+				loc.pop();
+				loc = loc.join("/")+"/";
+				this.uploadUrl = loc+this.uploadUrl;
+				this.log("SWF Fixed - Relative loc:", loc, " abs loc:", this.uploadUrl);
+			}else{
+				this.log("SWF URL unmodified:", this.uploadUrl)
+			}
+		}else{
+			console.warn("Warning: no uploadUrl provided.");
+		}
+
+		var w = this.fhtml.nr.w;
+		var h = this.fhtml.nr.h;
+
+		var args = {
+			expressInstall:true,
+			path: this.swfPath.uri || this.swfPath,
+			width: w,
+			height: h,
+			allowScriptAccess:"always",
+			allowNetworking:"all",
+			vars: {
+				uploadDataFieldName: this.flashFieldName,
+				uploadUrl: this.uploadUrl,
+				uploadOnSelect: this.uploadOnChange,
+				deferredUploading:this.deferredUploading || 0,
+				selectMultipleFiles: this.selectMultipleFiles,
+				id: this.id,
+				isDebug: this.isDebug,
+				devMode:this.devMode,
+				flashButton:dojox.embed.flashVars.serialize("fh", this.fhtml),
+				fileMask:dojox.embed.flashVars.serialize("fm", this.fileMask),
+				noReturnCheck: this.skipServerCheck,
+				serverTimeout:this.serverTimeout
+			},
+			params: {
+				scale:"noscale",
+				wmode:"opaque"
+			}
+
+		};
+
+		this.flashObject = new dojox.embed.Flash(args, this.insideNode);
+		this.flashObject.onError = dojo.hitch(function(msg){
+			this._error("Flash Error: " + msg);
+		});
+		this.flashObject.onReady = dojo.hitch(this, function(){
+			dojo.style(this.insideNode, "visibility", "visible");
+			this.log("FileUploader flash object ready");
+			this.onReady(this);
+		});
+		this.flashObject.onLoad = dojo.hitch(this, function(mov){
+			this.flashMovie = mov;
+			this.flashReady = true;
+
+			this.onLoad(this);
+		});
+		this._connectFlash();
+
+	},
+
+	_connectFlash: function(){
+		// 	summary:
+		//		Subscribing to published topics coming from the
+		//		Flash uploader.
+		// 	description:
+		//		Sacrificing some readbilty for compactness. this.id
+		//		will be on the beginning of the topic, so more than
+		//		one uploader can be on a page and can have unique calls.
+		//
+		this._doSub("/filesSelected", "_change");
+		this._doSub("/filesUploaded", "_complete");
+		this._doSub("/filesProgress", "_progress");
+		this._doSub("/filesError", "_error");
+		this._doSub("/filesCanceled", "onCancel");
+		this._doSub("/stageBlur", "_onFlashBlur");
+		this._doSub("/up", "onMouseUp");
+		this._doSub("/down", "onMouseDown");
+		this._doSub("/over", "onMouseOver");
+		this._doSub("/out", "onMouseOut");
+
+		this.connect(this.domNode, "focus", function(){
+			// TODO: some kind of indicator that the Flash button
+			//	is in focus
+			this.flashMovie.focus();
+			this.flashMovie.doFocus();
+		});
+		if(this.tabIndex>=0){
+			dojo.attr(this.domNode, "tabIndex", this.tabIndex);
+		}
+	},
+
+	_doSub: function(subStr, funcStr){
+		// summary:
+		//		Internal. Shortcut for subscribes to Flash movie
+		this._subs.push(dojo.subscribe(this.id + subStr, this, funcStr));
+	},
+
+	/*************************************
+	 *		DOM INSPECTION METHODS		 *
+	 *************************************/
+
+	urlencode: function(url){
+		// Using symbols in place of URL chars that will break in Flash serialization.
+		if(!url || url == "none"){
+			return false;
+		}
+		return url.replace(/:/g,"||").replace(/\./g,"^^").replace("url(", "").replace(")","").replace(/'/g,"").replace(/"/g,"");
+	},
+
+	isButton: function(node){
+		// testing if button for styling purposes
+		var tn = node.tagName.toLowerCase();
+		return tn == "button" || tn == "input";
+	},
+
+	getTextStyle: function(node){
+		// getting font info
+		var o = {};
+		o.ff = dojo.style(node, "fontFamily");
+		if(o.ff){
+			o.ff = o.ff.replace(", ", ","); // remove spaces. IE in Flash no likee
+			o.ff = o.ff.replace(/\"|\'/g, "");
+			o.ff = o.ff == "sans-serif" ? "Arial" : o.ff; // Flash doesn't know what sans-serif is
+			o.fw = dojo.style(node, "fontWeight");
+			o.fi = dojo.style(node, "fontStyle");
+			o.fs = parseInt(dojo.style(node, "fontSize"), 10);
+			if(dojo.style(node, "fontSize").indexOf("%") > -1){
+				// IE doesn't convert % to px. For god sakes.
+				var n = node;
+				while(n.tagName){
+					console.log(" P FONT:", dojo.style(node, "fontSize"))
+					if(dojo.style(n, "fontSize").indexOf("%") == -1){
+						o.fs = parseInt(dojo.style(n, "fontSize"), 10);
+						break;
+					}
+					if(n.tagName.toLowerCase()=="body"){
+						// if everyting is %, the the font size is 16px * the %
+						o.fs = 16 * .01 * parseInt(dojo.style(n, "fontSize"), 10);
+					}
+					n = n.parentNode;
+				}
+			}
+			o.fc = new dojo.Color(dojo.style(node, "color")).toHex();
+			o.fc = parseInt(o.fc.substring(1,Infinity),16);
+		}
+		o.lh = dojo.style(node, "lineHeight");
+		o.ta = dojo.style(node, "textAlign");
+		o.ta = o.ta == "start" || !o.ta ? "left" : o.ta;
+		o.va = this.isButton(node) ? "middle" : o.lh == o.h ? "middle" : dojo.style(node, "verticalAlign");
+		return o;
+	},
+
+	getText: function(node){
+		// Get the text of the button. It's possible to use HTML in the Flash Button,
+		//	but the results are not spectacular.
+		var cn = dojo.trim(node.innerHTML);
+		if(cn.indexOf("<") >- 1){
+			cn = escape(cn);
+		}
+		return cn;
+	},
+
+	getStyle: function(node){
+		// getting the style of a node. Using very abbreviated characters which the
+		//	Flash movie understands.
+		var o = {};
+		var dim = dojo.contentBox(node);
+		var pad = dojo._getPadExtents(node);
+		o.p = [pad.t, pad.w-pad.l, pad.h-pad.t, pad.l];
+		o.w = dim.w + pad.w;
+		o.h = dim.h + pad.h;
+		o.d = dojo.style(node, "display");
+		var clr = new dojo.Color(dojo.style(node, "backgroundColor"));
+		// if no color, Safari sets #000000 and alpha=0 since we don't support alpha,
+		// it makes black - make it white
+		o.bc = clr.a == 0 ? "#ffffff" : clr.toHex();
+		o.bc = parseInt(o.bc.substring(1,Infinity),16);
+		var url = this.urlencode(dojo.style(node, "backgroundImage"));
+		if(url){
+			o.bi = {
+				url:url,
+				rp:dojo.style(node, "backgroundRepeat"),
+				pos: escape(dojo.style(node, "backgroundPosition"))
+			};
+			if(!o.bi.pos){
+				// IE does Xpx and Ypx, not "X% Y%"
+				var rx = dojo.style(node, "backgroundPositionX");
+				var ry = dojo.style(node, "backgroundPositionY");
+				rx = (rx == "left") ? "0%" : (rx == "right") ? "100%" : rx;
+				ry = (ry == "top") ? "0%" : (ry == "bottom") ? "100%" : ry;
+				o.bi.pos = escape(rx+" "+ry);
+			}
+		}
+		return dojo.mixin(o, this.getTextStyle(node));
+	},
+
+	getTempNodeStyle: function(node, _class, isDijitButton){
+		// This sets up a temp node to get the style of the hover, active, and disabled states
+		var temp, style;
+		if(isDijitButton){
+			// backwards compat until dojo 1.5
+			temp = dojo.place("<"+node.tagName+"><span>"+node.innerHTML+"</span></"+node.tagName+">", node.parentNode); //+" "+_class+"
+			var first = temp.firstChild;
+			dojo.addClass(first, node.className);
+			dojo.addClass(temp, _class);
+			style = this.getStyle(first);
+		}else{
+			temp = dojo.place("<"+node.tagName+">"+node.innerHTML+"</"+node.tagName+">", node.parentNode);
+			dojo.addClass(temp, node.className);
+			dojo.addClass(temp, _class);
+			temp.id = node.id;
+			style = this.getStyle(temp);
+		}
+		// dev note: comment out this line to see what the
+		// button states look like to the FileUploader
+		dojo.destroy(temp);
+		return style;
+	}
 });
-if(this.tabIndex>=0){
-dojo.attr(this.domNode,"tabIndex",this.tabIndex);
-}
-},_doSub:function(_3d,_3e){
-this._subs.push(dojo.subscribe(this.id+_3d,this,_3e));
-}});
-})();
-}
diff --git a/dojox/form/ListInput.js b/dojox/form/ListInput.js
old mode 100644
new mode 100755
index 02a4a25..94f7e0f
--- a/dojox/form/ListInput.js
+++ b/dojox/form/ListInput.js
@@ -1,440 +1,999 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.ListInput"]){
-dojo._hasResource["dojox.form.ListInput"]=true;
 dojo.experimental("dojox.form.ListInput");
+
 dojo.provide("dojox.form.ListInput");
+
 dojo.require("dijit.form._FormWidget");
 dojo.require("dijit.form.ValidationTextBox");
 dojo.require("dijit.InlineEditBox");
-dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dojox.form.ListInput",[dijit.form._FormValueWidget],{constructor:function(){
-this._items=[];
-if(!dojo.isArray(this.delimiter)){
-this.delimiter=[this.delimiter];
-}
-var r="("+this.delimiter.join("|")+")?";
-this.regExp="^"+this.regExp+r+"$";
-},inputClass:"dojox.form._ListInputInputBox",inputHandler:"onChange",inputProperties:{minWidth:50},submitOnlyValidValue:true,useOnBlur:true,readOnlyInput:false,maxItems:null,showCloseButtonWhenValid:true,showCloseButtonWhenInvalid:true,regExp:".*",delimiter:",",constraints:{},baseClass:"dojoxListInput",type:"select",value:"",templateString:"<div dojoAttachPoint=\"focusNode\" class=\"dijit dijitReset dijitLeft dojoxListInput\"><select dojoAttachpoint=\"_selectNode\" multiple=\"multiple\"  [...]
-this.inherited(arguments);
-this._createInputBox();
-},_setReadOnlyInputAttr:function(_1){
-console.warn("_setReadOnlyInputAttr",this.id,_1);
-if(!this._started){
-return this._createInputBox();
-}
-this.readOnlyInput=_1;
-this._createInputBox();
-},_setReadOnlyItemAttr:function(_2){
-if(!this._started){
-return;
-}
-for(var i in this._items){
-this._items[i].attr("readOnlyItem",_2);
-}
-},_createInputBox:function(){
-console.warn("_createInputBox",this.id,this.readOnlyInput);
-dojo[(this.readOnlyInput?"add":"remove")+"Class"](this._inputNode,"dijitHidden");
-if(this.readOnlyInput){
-return;
-}
-if(this._input){
-return;
-}
-if(this.inputHandler===null){
-return !console.warn("you must add some handler to connect to input field");
-}
-if(dojo.isString(this.inputHandler)){
-this.inputHandler=this.inputHandler.split(",");
-}
-if(dojo.isString(this.inputProperties)){
-this.inputProperties=dojo.fromJson(this.inputProperties);
-}
-var _3=dojo.getObject(this.inputClass,false);
-this.inputProperties.regExp=this.regExpGen(this.constraints);
-this._input=new _3(this.inputProperties);
-this._input.startup();
-this._inputNode.appendChild(this._input.domNode);
-dojo.forEach(this.inputHandler,function(_4){
-this.connect(this._input,dojo.string.trim(_4),"_onHandler");
-},this);
-this.connect(this._input,"onKeyDown","_inputOnKeyDown");
-this.connect(this._input,"onBlur","_inputOnBlur");
-},compare:function(_5,_6){
-_5=_5.join(",");
-_6=_6.join(",");
-if(_5>_6){
-return 1;
-}else{
-if(_5<_6){
-return -1;
-}else{
-return 0;
-}
-}
-},add:function(_7){
-if(this._count>=this.maxItems&&this.maxItems!==null){
-return;
-}
-this._lastValueReported=this._getValues();
-if(!dojo.isArray(_7)){
-_7=[_7];
-}
-for(var i in _7){
-var _8=_7[i];
-if(_8===""||typeof _8!="string"){
-continue;
-}
-this._count++;
-var re=new RegExp(this.regExpGen(this.constraints));
-this._lastAddedItem=new dojox.form._ListInputInputItem({"index":this._items.length,readOnlyItem:this.readOnlyItem,value:_8,regExp:this.regExpGen(this.constraints)});
-this._lastAddedItem.startup();
-this._testItem(this._lastAddedItem,_8);
-this._lastAddedItem.onClose=dojo.hitch(this,"_onItemClose",this._lastAddedItem);
-this._lastAddedItem.onChange=dojo.hitch(this,"_onItemChange",this._lastAddedItem);
-this._lastAddedItem.onEdit=dojo.hitch(this,"_onItemEdit",this._lastAddedItem);
-this._lastAddedItem.onKeyDown=dojo.hitch(this,"_onItemKeyDown",this._lastAddedItem);
-if(this.useAnim){
-dojo.style(this._lastAddedItem.domNode,{opacity:0,display:""});
-}
-this._placeItem(this._lastAddedItem.domNode);
-if(this.useAnim){
-var _9=dojo.fadeIn({node:this._lastAddedItem.domNode,duration:this.duration,easing:this.easingIn}).play();
-}
-this._items[this._lastAddedItem.index]=this._lastAddedItem;
-if(this._onChangeActive&&this.intermediateChanges){
-this.onChange(_8);
-}
-if(this._count>=this.maxItems&&this.maxItems!==null){
-break;
-}
-}
-this._updateValues();
-if(this._lastValueReported.length==0){
-this._lastValueReported=this.value;
-}
-if(!this.readOnlyInput){
-this._input.attr("value","");
-}
-if(this._onChangeActive){
-this.onChange(this.value);
-}
-this._setReadOnlyWhenMaxItemsReached();
-},_setReadOnlyWhenMaxItemsReached:function(){
-this.attr("readOnlyInput",(this._count>=this.maxItems&&this.maxItems!==null));
-},_setSelectNode:function(){
-this._selectNode.options.length=0;
-var _a=this.submitOnlyValidValue?this.attr("MatchedValue"):this.value;
-if(!dojo.isArray(_a)){
-return;
-}
-dojo.forEach(_a,function(_b){
-this._selectNode.options[this._selectNode.options.length]=new Option(_b,_b,true,true);
-},this);
-},_placeItem:function(_c){
-dojo.place(_c,this._inputNode,"before");
-},_getCursorPos:function(_d){
-if(typeof _d.selectionStart!="undefined"){
-return _d.selectionStart;
-}
-try{
-_d.focus();
-}
-catch(e){
-}
-var _e=_d.createTextRange();
-_e.moveToBookmark(dojo.doc.selection.createRange().getBookmark());
-_e.moveEnd("character",_d.value.length);
-try{
-return _d.value.length-_e.text.length;
-}
-finally{
-_e=null;
-}
-},_onItemClose:function(_f){
-if(this.disabled){
-return;
-}
-if(this.useAnim){
-var _10=dojo.fadeOut({node:_f.domNode,duration:this.duration,easing:this.easingOut,onEnd:dojo.hitch(this,"_destroyItem",_f)}).play();
-}else{
-this._destroyItem(_f);
-}
-},_onItemKeyDown:function(_11,e){
-if(this.readOnlyItem||!this.useArrowForEdit){
-return;
-}
-if(e.keyCode==dojo.keys.LEFT_ARROW&&this._getCursorPos(e.target)==0){
-this._editBefore(_11);
-}else{
-if(e.keyCode==dojo.keys.RIGHT_ARROW&&this._getCursorPos(e.target)==e.target.value.length){
-this._editAfter(_11);
-}
-}
-},_editBefore:function(_12){
-this._currentItem=this._getPreviousItem(_12);
-if(this._currentItem!==null){
-this._currentItem.edit();
-}
-},_editAfter:function(_13){
-this._currentItem=this._getNextItem(_13);
-if(this._currentItem!==null){
-this._currentItem.edit();
-}
-if(!this.readOnlyInput){
-if(this._currentItem===null){
-this._focusInput();
-}
-}
-},_onItemChange:function(_14,_15){
-if(!_15){
-_15=_14.attr("value");
-}
-this._testItem(_14,_15);
-this._updateValues();
-},_onItemEdit:function(_16){
-dojo.removeClass(_16.domNode,"dijitError");
-dojo.removeClass(_16.domNode,this.baseClass+"Match");
-dojo.removeClass(_16.domNode,this.baseClass+"Mismatch");
-},_testItem:function(_17,_18){
-var re=new RegExp(this.regExpGen(this.constraints));
-var _19=_18.match(re);
-dojo.removeClass(_17.domNode,this.baseClass+(!_19?"Match":"Mismatch"));
-dojo.addClass(_17.domNode,this.baseClass+(_19?"Match":"Mismatch"));
-dojo[(!_19?"add":"remove")+"Class"](_17.domNode,"dijitError");
-if((this.showCloseButtonWhenValid&&_19)||(this.showCloseButtonWhenInvalid&&!_19)){
-dojo.addClass(_17.domNode,this.baseClass+"Closable");
-}else{
-dojo.removeClass(_17.domNode,this.baseClass+"Closable");
-}
-},_getValueAttr:function(){
-return this.value;
-},_setValueAttr:function(_1a){
-this._destroyAllItems();
-this.add(this._parseValue(_1a));
-},_parseValue:function(_1b){
-if(typeof _1b=="string"){
-if(dojo.isString(this.delimiter)){
-this.delimiter=[this.delimiter];
-}
-var re=new RegExp("^.*("+this.delimiter.join("|")+").*");
-if(_1b.match(re)){
-re=new RegExp(this.delimiter.join("|"));
-return _1b.split(re);
-}
-}
-return _1b;
-},regExpGen:function(_1c){
-return this.regExp;
-},_setDisabledAttr:function(_1d){
-if(!this.readOnlyItem){
-for(var i in this._items){
-this._items[i].attr("disabled",_1d);
-}
-}
-if(!this.readOnlyInput){
-this._input.attr("disabled",_1d);
-}
-this.inherited(arguments);
-},_onHandler:function(_1e){
-var _1f=this._parseValue(_1e);
-if(dojo.isArray(_1f)){
-this.add(_1f);
-}
-},_onClick:function(e){
-this._focusInput();
-},_focusInput:function(){
-if(!this.readOnlyInput&&this._input.focus){
-this._input.focus();
-}
-},_inputOnKeyDown:function(e){
-this._currentItem=null;
-if(e.keyCode==dojo.keys.BACKSPACE&&this._input.attr("value")==""&&this.attr("lastItem")){
-this._destroyItem(this.attr("lastItem"));
-}else{
-if(e.keyCode==dojo.keys.ENTER&&this._input.attr("value")!=""){
-this.add(this._input.attr("value"));
-}else{
-if(e.keyCode==dojo.keys.LEFT_ARROW&&this._getCursorPos(this._input.focusNode)==0&&!this.readOnlyItem&&this.useArrowForEdit){
-this._editBefore();
-}
-}
-}
-},_inputOnBlur:function(){
-if(this.useOnBlur&&this._input.attr("value")!=""){
-this.add(this._input.attr("value"));
-}
-},_getMatchedValueAttr:function(){
-return this._getValues(dojo.hitch(this,this._matchValidator));
-},_getMismatchedValueAttr:function(){
-return this._getValues(dojo.hitch(this,this._mismatchValidator));
-},_getValues:function(_20){
-var _21=[];
-_20=_20||this._nullValidator;
-for(var i in this._items){
-var _22=this._items[i];
-if(_22===null){
-continue;
-}
-var _23=_22.attr("value");
-if(_20(_23)){
-_21.push(_23);
-}
-}
-return _21;
-},_nullValidator:function(_24){
-return true;
-},_matchValidator:function(_25){
-var re=new RegExp(this.regExpGen(this.constraints));
-return _25.match(re);
-},_mismatchValidator:function(_26){
-var re=new RegExp(this.regExpGen(this.constraints));
-return !(_26.match(re));
-},_getLastItemAttr:function(){
-return this._getSomeItem();
-},_getSomeItem:function(_27,_28){
-_27=_27||false;
-_28=_28||"last";
-var _29=null;
-var _2a=-1;
-for(var i in this._items){
-if(this._items[i]===null){
-continue;
-}
-if(_28=="before"&&this._items[i]===_27){
-break;
-}
-_29=this._items[i];
-if(_28=="first"||_2a==0){
-_2a=1;
-break;
-}
-if(_28=="after"&&this._items[i]===_27){
-_2a=0;
-}
-}
-if(_28=="after"&&_2a==0){
-_29=null;
-}
-return _29;
-},_getPreviousItem:function(_2b){
-return this._getSomeItem(_2b,"before");
-},_getNextItem:function(_2c){
-return this._getSomeItem(_2c,"after");
-},_destroyItem:function(_2d,_2e){
-this._items[_2d.index]=null;
-_2d.destroy();
-this._count--;
-if(_2e!==false){
-this._updateValues();
-this._setReadOnlyWhenMaxItemsReached();
-}
-},_updateValues:function(){
-this.value=this._getValues();
-this._setSelectNode();
-},_destroyAllItems:function(){
-for(var i in this._items){
-if(this._items[i]==null){
-continue;
-}
-this._destroyItem(this._items[i],false);
-}
-this._items=[];
-this._count=0;
-this.value=null;
-this._setSelectNode();
-this._setReadOnlyWhenMaxItemsReached();
-},destroy:function(){
-this._destroyAllItems();
-this._lastAddedItem=null;
-if(!this._input){
-this._input.destroy();
-}
-this.inherited(arguments);
-}});
-dojo.declare("dojox.form._ListInputInputItem",[dijit._Widget,dijit._Templated],{templateString:"<li class=\"dijit dijitReset dijitLeft dojoxListInputItem\" dojoAttachEvent=\"onclick: onClick\" ><span dojoAttachPoint=\"labelNode\"></span></li>",closeButtonNode:null,readOnlyItem:true,baseClass:"dojoxListInputItem",value:"",regExp:".*",_editBox:null,_handleKeyDown:null,attributeMap:{value:{node:"labelNode",type:"innerHTML"}},postMixInProperties:function(){
-var _2f=dojo.i18n.getLocalization("dijit","common");
-dojo.mixin(this,_2f);
-this.inherited(arguments);
-},postCreate:function(){
-this.inherited(arguments);
-this.closeButtonNode=dojo.create("span",{"class":"dijitButtonNode dijitDialogCloseIcon",title:this.itemClose,onclick:dojo.hitch(this,"onClose"),onmouseenter:dojo.hitch(this,"_onCloseEnter"),onmouseleave:dojo.hitch(this,"_onCloseLeave")},this.domNode);
-dojo.create("span",{"class":"closeText",title:this.itemClose,innerHTML:"x"},this.closeButtonNode);
-},startup:function(){
-this.inherited(arguments);
-this._createInlineEditBox();
-},_setReadOnlyItemAttr:function(_30){
-this.readOnlyItem=_30;
-if(!_30){
-this._createInlineEditBox();
-}else{
-if(this._editBox){
-this._editBox.attr("disabled",true);
-}
-}
-},_createInlineEditBox:function(){
-if(this.readOnlyItem){
-return;
-}
-if(!this._started){
-return;
-}
-if(this._editBox){
-this._editBox.attr("disabled",false);
-return;
-}
-this._editBox=new dijit.InlineEditBox({value:this.value,editor:"dijit.form.ValidationTextBox",editorParams:{regExp:this.regExp}},this.labelNode);
-this.connect(this._editBox,"edit","_onEdit");
-this.connect(this._editBox,"onChange","_onCloseEdit");
-this.connect(this._editBox,"onCancel","_onCloseEdit");
-},edit:function(){
-if(!this.readOnlyItem){
-this._editBox.edit();
-}
-},_onCloseEdit:function(_31){
-dojo.removeClass(this.closeButtonNode,this.baseClass+"Edited");
-dojo.disconnect(this._handleKeyDown);
-this.onChange(_31);
-},_onEdit:function(){
-dojo.addClass(this.closeButtonNode,this.baseClass+"Edited");
-this._handleKeyDown=dojo.connect(this._editBox.editWidget,"_onKeyPress",this,"onKeyDown");
-this.onEdit();
-},_setDisabledAttr:function(_32){
-if(!this.readOnlyItem){
-this._editBox.attr("disabled",_32);
-}
-},_getValueAttr:function(){
-return (!this.readOnlyItem&&this._started?this._editBox.attr("value"):this.value);
-},destroy:function(){
-if(this._editBox){
-this._editBox.destroy();
-}
-this.inherited(arguments);
-},_onCloseEnter:function(){
-dojo.addClass(this.closeButtonNode,"dijitDialogCloseIcon-hover");
-},_onCloseLeave:function(){
-dojo.removeClass(this.closeButtonNode,"dijitDialogCloseIcon-hover");
-},onClose:function(){
-},onEdit:function(){
-},onClick:function(){
-},onChange:function(_33){
-},onKeyDown:function(_34){
-}});
-dojo.declare("dojox.form._ListInputInputBox",[dijit.form.ValidationTextBox],{minWidth:50,intermediateChanges:true,regExp:".*",_sizer:null,onChange:function(_35){
-this.inherited(arguments);
-if(this._sizer===null){
-this._sizer=dojo.create("div",{style:{position:"absolute",left:"-10000px",top:"-10000px"}},dojo.body());
-}
-this._sizer.innerHTML=_35;
-var w=dojo.contentBox(this._sizer).w+this.minWidth;
-dojo.contentBox(this.domNode,{w:w});
-},destroy:function(){
-dojo.destroy(this._sizer);
-this.inherited(arguments);
-}});
-}
+dojo.requireLocalization("dijit", "common");
+
+dojo.declare("dojox.form.ListInput", 
+	[dijit.form._FormValueWidget],
+	{
+	// summary: 
+	//		An automatic list maker
+	// description:
+	//		you can add value to list with add method.
+	//		you can only remove by clicking close button
+	
+	constructor: function(){
+		this._items = [];
+		
+		
+		if(!dojo.isArray(this.delimiter)){
+			this.delimiter=[this.delimiter];
+		}
+		var r="("+this.delimiter.join("|")+")?";
+		this.regExp="^"+this.regExp+r+"$";
+	},
+	
+	// inputClass: String
+	//		Class which will be used to create the input box. You can implements yours.
+	//		It must be a widget, focusNode or domNode must have "onkeydown" event
+	//		It must have .attr("value") to get value
+	//		It also must impement an (or more) handler for the "onChange" method
+	inputClass: "dojox.form._ListInputInputBox",
+	
+	// inputHandler: String || Array
+	//		The widget will connect on all handler to check input value
+	//		You can use comma separated list
+	inputHandler: "onChange",
+	
+	// inputProperties: String || Object
+	//		Properties used to create input box
+	//		If String, it must be a valid JSON
+	inputProperties: {
+		minWidth:50
+	},
+	
+	// submitOnlyValidValue: Boolean
+	//		If true, only valid value will be submited with form
+	submitOnlyValidValue:true,
+	
+	// useOnBlur: Boolean
+	//		If true, onBlur event do a validate (like pressing ENTER)
+	useOnBlur:true,
+	
+	// readOnlyInput: Boolean
+	//		if false, the list will be editable
+	//		Can only be set when instanciate
+	readOnlyInput: false,
+	
+	// maxItems: Int
+	//		Specify max item the list can have
+	//		null = infiny
+	maxItems: null,
+	
+	// showCloseButtonWhenValid: Boolean
+	//		if true, a close button will be added on valid item
+	showCloseButtonWhenValid: true,
+	
+	// showCloseButtonWhenInvalid: Boolean
+	//		if true, a close button will be added on invalid item
+	showCloseButtonWhenInvalid: true,
+	
+	// regExp: [extension protected] String
+	//		regular expression string used to validate the input
+	//		Do not specify both regExp and regExpGen
+	regExp: ".*", //"[a-zA-Z.-_]+@[a-zA-Z.-_]+.[a-zA-Z]+",
+	
+	// delimiter: String || Array
+	//		delimiter for the string. Every match will be splitted
+	//		The string can contain only one delimiter
+	delimiter: ",",
+	
+	// constraints: dijit.form.ValidationTextBox.__Constraints
+	//		user-defined object needed to pass parameters to the validator functions
+	constraints: {},
+
+	baseClass:"dojoxListInput",
+	
+	type: "select",
+	
+	value: "",
+	
+	templateString: "<div dojoAttachPoint=\"focusNode\" class=\"dijit dijitReset dijitLeft dojoxListInput\"><select dojoAttachpoint=\"_selectNode\" multiple=\"multiple\" class=\"dijitHidden\" ${!nameAttrSetting}></select><ul dojoAttachPoint=\"_listInput\"><li dojoAttachEvent=\"onclick: _onClick\" class=\"dijitInputField dojoxListInputNode dijitHidden\" dojoAttachPoint=\"_inputNode\"></li></ul></div>",
+	
+	// useAnim: Boolean
+	//		If true, then item will use an anime to show hide itself 
+	useAnim: true,
+	
+	// duration: Integer
+	//		Animation duration
+	duration: 500,
+	
+	// easingIn: function
+	//		function used to easing on fadeIn end
+	easingIn: null,
+	
+	// easingOut: function
+	//		function used to easing on fadeOut end
+	easingOut: null,
+
+	// readOnlyItem: Boolean
+	//		If true, items can be edited
+	//		Can only be set when instanciate
+	readOnlyItem: false,
+	
+	// useArrowForEdit: Boolean
+	//		If true, arraow left and right can be used for editing
+	//		Can only be set when instanciate
+	useArrowForEdit: true,
+	
+	// _items: Array
+	//		Array of widget.
+	//		Contain all reference to _ListInputInputItem
+	_items: null,
+	
+	// _lastAddedItem: Widget
+	//		Contain a reference to the last created item
+	_lastAddedItem: null,
+	
+	// _currentItem: Widget
+	//		Widget currently in edition
+	_currentItem: null,
+	
+	// _input: Widget
+	//		Widget use for input box
+	_input: null,
+	
+	// _count: Int
+	//		Count items
+	_count: 0,
+	
+	postCreate: function(){
+		// summary:
+		//		If closeButton is used, add a class
+		this.inherited(arguments);
+		this._createInputBox();
+	},
+	
+	_setReadOnlyInputAttr: function(/*Boolean*/value){
+		// summary:
+		//		Change status and if needed, create the inputbox
+		// tags:
+		//		private
+		console.warn("_setReadOnlyInputAttr",this.id,value);
+		if(!this._started){ return this._createInputBox(); }
+		this.readOnlyInput=value;
+		this._createInputBox();
+	},
+	
+	_setReadOnlyItemAttr: function(/*Boolean*/value){
+		// summary: 
+		//		set read only items
+		// tags:
+		//		private
+		if(!this._started){ return; }
+		for(var i in this._items){
+			this._items[i].attr("readOnlyItem",value);
+		}
+	},
+	
+	_createInputBox: function(){
+		// summary:
+		//		Create the input box
+		// tags:
+		//		private
+		console.warn("_createInputBox",this.id,this.readOnlyInput);
+		dojo[(this.readOnlyInput?"add":"remove")+"Class"](this._inputNode,"dijitHidden");
+		if(this.readOnlyInput){ return; }
+		if(this._input){ return; }
+				
+		if(this.inputHandler === null){
+			return !console.warn("you must add some handler to connect to input field");
+		}
+		if(dojo.isString(this.inputHandler)){
+			this.inputHandler = this.inputHandler.split(",");
+		}
+		if(dojo.isString(this.inputProperties)){
+			this.inputProperties = dojo.fromJson(this.inputProperties);
+		}
+		
+
+		var input = dojo.getObject(this.inputClass, false);
+		
+		this.inputProperties.regExp = this.regExpGen(this.constraints);
+		
+		this._input = new input(this.inputProperties);
+		this._input.startup();
+		this._inputNode.appendChild(this._input.domNode);
+		dojo.forEach(this.inputHandler, function(handler){
+			this.connect(this._input,dojo.string.trim(handler),"_onHandler");
+		},this);
+	
+		this.connect(this._input, "onKeyDown", "_inputOnKeyDown");
+		this.connect(this._input, "onBlur", "_inputOnBlur");
+	},
+	
+	compare: function(/*Array*/val1,/*Array*/val2){
+		// summary:
+		//		Compare 2 values (as returned by attr('value') for this widget).
+		// tags:
+		//		protected
+		val1=val1.join(",");
+		val2=val2.join(",");
+		if(val1 > val2){
+			return 1;
+		}else if(val1 < val2){
+			return -1;
+		}else{
+			return 0;
+		}
+	},
+	
+	add: function(/*String || Array*/values){
+		// summary: 
+		//		Create new list element
+		if(this._count>=this.maxItems && this.maxItems !== null){return;}
+		this._lastValueReported = this._getValues();
+		
+		if(!dojo.isArray(values)){
+			values = [values];
+		}
+		
+		for(var i in values){
+			var value=values[i];
+			if(value === "" || typeof value != "string"){
+				continue;
+			}
+			this._count++;
+			var re = new RegExp(this.regExpGen(this.constraints));
+
+			this._lastAddedItem = new dojox.form._ListInputInputItem({
+				"index" : this._items.length,
+				readOnlyItem : this.readOnlyItem,
+				value : value,
+				regExp: this.regExpGen(this.constraints)
+			});
+			this._lastAddedItem.startup();
+			
+			this._testItem(this._lastAddedItem,value);
+			
+			this._lastAddedItem.onClose = dojo.hitch(this,"_onItemClose",this._lastAddedItem);
+			this._lastAddedItem.onChange = dojo.hitch(this,"_onItemChange",this._lastAddedItem);
+			this._lastAddedItem.onEdit = dojo.hitch(this,"_onItemEdit",this._lastAddedItem);
+			this._lastAddedItem.onKeyDown = dojo.hitch(this,"_onItemKeyDown",this._lastAddedItem);
+
+			if(this.useAnim){
+				dojo.style(this._lastAddedItem.domNode, {opacity:0, display:""});
+			}
+
+			this._placeItem(this._lastAddedItem.domNode);
+			
+			if(this.useAnim){
+				var anim = dojo.fadeIn({
+					node : this._lastAddedItem.domNode,
+					duration : this.duration,
+					easing : this.easingIn
+				}).play();
+			}
+			
+			this._items[this._lastAddedItem.index] = this._lastAddedItem;
+			
+			if(this._onChangeActive && this.intermediateChanges){ this.onChange(value); }
+			
+			if(this._count>=this.maxItems && this.maxItems !== null){
+				break;
+			}
+		}
+		
+		this._updateValues();
+		if(this._lastValueReported.length==0){
+			this._lastValueReported = this.value;
+		}
+		
+		if(!this.readOnlyInput){
+			this._input.attr("value","");
+		}
+		
+		if(this._onChangeActive){ this.onChange(this.value); }
+		
+		this._setReadOnlyWhenMaxItemsReached();
+	},
+	
+	_setReadOnlyWhenMaxItemsReached: function(){
+		// summary: 
+		//		set input to readonly when max is reached
+		// tags:
+		//		private
+		this.set("readOnlyInput",(this._count>=this.maxItems && this.maxItems !== null));
+	},
+	
+	_setSelectNode: function(){
+		// summary: 
+		//		put all item in the select (for a submit)
+		// tags:
+		//		private
+		this._selectNode.options.length = 0;
+		
+		var values=this.submitOnlyValidValue?this.get("MatchedValue"):this.value;
+		
+		if(!dojo.isArray(values)){
+			return;
+		}
+		dojo.forEach(values,function(item){
+			this._selectNode.options[this._selectNode.options.length]=new Option(item,item,true,true);
+		},this);
+	},
+	
+	_placeItem: function(/*domNode*/node){
+		// summary: 
+		//		Place item in the list
+		// tags:
+		//		private
+		dojo.place(node,this._inputNode,"before");
+	},
+	
+	_getCursorPos: function(/*domNode*/node){
+		// summary: 
+		//		get current cursor pos
+		// tags:
+		//		private
+		if(typeof node.selectionStart != 'undefined'){
+			return node.selectionStart;
+		}
+		
+		// IE Support
+		try{ node.focus(); }catch(e){}
+		var range = node.createTextRange();
+		range.moveToBookmark(dojo.doc.selection.createRange().getBookmark());
+		range.moveEnd('character', node.value.length);
+		try{
+			return node.value.length - range.text.length;
+		}finally{ range=null; }
+	},
+	
+	_onItemClose: function(/*dijit._Widget*/ item){
+		// summary: 
+		//		Destroy a list element when close button is clicked
+		// tags:
+		//		private
+		if(this.disabled){ return; }
+		
+		if(this.useAnim){
+			var anim = dojo.fadeOut({
+				node : item.domNode,
+				duration : this.duration,
+				easing : this.easingOut,
+				onEnd : dojo.hitch(this, "_destroyItem", item)
+			}).play();
+		}else{
+			this._destroyItem(item);
+		}
+	},
+	
+	_onItemKeyDown:  function(/*dijit._Widget*/ item, /*Event*/ e){
+		// summary: 
+		//		Call when item get a keypress
+		// tags:
+		//		private
+		if(this.readOnlyItem || !this.useArrowForEdit){ return; }
+		
+		if(e.keyCode == dojo.keys.LEFT_ARROW && this._getCursorPos(e.target)==0){
+			this._editBefore(item);
+		}else if(e.keyCode == dojo.keys.RIGHT_ARROW && this._getCursorPos(e.target)==e.target.value.length){
+			this._editAfter(item);
+		}
+	},
+	
+	_editBefore: function(/*widget*/item) {
+		// summary: 
+		//		move trough items
+		// tags:
+		//		private
+		this._currentItem = this._getPreviousItem(item);
+		if(this._currentItem !== null){
+			this._currentItem.edit();
+		}
+	},
+	_editAfter: function(/*widget*/item) {
+		// summary: 
+		//		move trough items
+		// tags:
+		//		private
+		this._currentItem = this._getNextItem(item);
+		if(this._currentItem !== null){
+			this._currentItem.edit();
+		}
+		
+		if(!this.readOnlyInput){
+			if(this._currentItem === null){
+				//no more item ?
+				//so edit input (if available)
+				this._focusInput();
+			}
+		}
+	},
+	
+	_onItemChange: function(/*dijit._Widget*/ item, /*String*/ value){
+		// summary: 
+		//		Call when item value change
+		// tags:
+		//		private
+		if(!value){
+			value=item.attr("value");
+		}
+		
+		//revalidate content
+		this._testItem(item,value);
+		
+		//update value
+		this._updateValues();
+	},
+	
+	_onItemEdit: function(/*dijit._Widget*/ item){
+		// summary: 
+		//		Call when item is edited
+		// tags:
+		//		private
+		dojo.removeClass(item.domNode,"dijitError");
+		dojo.removeClass(item.domNode,this.baseClass+"Match");
+		dojo.removeClass(item.domNode,this.baseClass+"Mismatch");
+	},
+	
+	_testItem: function(/*Object*/item,/*String*/value){
+		// summary: 
+		//		Change class of item (match, mismatch)
+		// tags:
+		//		private
+		var re = new RegExp(this.regExpGen(this.constraints));
+		var match = value.match(re);
+		
+		dojo.removeClass(item.domNode, this.baseClass+(!match ? "Match":"Mismatch"));
+		dojo.addClass(item.domNode, this.baseClass+(match ? "Match":"Mismatch"));
+		dojo[(!match?"add":"remove")+"Class"](item.domNode, "dijitError");
+		
+		if((this.showCloseButtonWhenValid && match) ||
+			(this.showCloseButtonWhenInvalid && !match)){
+			dojo.addClass(item.domNode,this.baseClass+"Closable");
+		}else {
+			dojo.removeClass(item.domNode,this.baseClass+"Closable");
+		}
+	},
+	
+	_getValueAttr: function(){
+		// summary: 
+		//		get all value in then list and return an array
+		// tags:
+		//		private
+		return this.value;
+	},
+	
+	_setValueAttr: function(/*Array || String*/ newValue){
+		// 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._destroyAllItems();
+		
+		this.add(this._parseValue(newValue));
+	},
+	
+	_parseValue: function(/*String*/newValue){
+		// summary: 
+		//		search for delemiters and split if needed
+		// tags:
+		//		private
+		if(typeof newValue == "string"){
+			if(dojo.isString(this.delimiter)){
+				this.delimiter = [this.delimiter];
+			}
+			var re = new RegExp("^.*("+this.delimiter.join("|")+").*");
+			if(newValue.match(re)){
+				re = new RegExp(this.delimiter.join("|"));
+				return newValue.split(re);
+			}
+		}
+		return newValue;
+	},
+	
+	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
+	},
+	
+	_setDisabledAttr: function(/*Boolean*/ value){
+		// summary: 
+		//		also enable/disable editable items
+		// tags:
+		//		private
+		if(!this.readOnlyItem){
+			for(var i in this._items){
+				this._items[i].attr("disabled",value);
+			}
+		}
+		
+		if(!this.readOnlyInput){
+			this._input.attr("disabled",value);
+		}
+		this.inherited(arguments);
+	},
+	
+	_onHandler: function(/*String*/value){
+		// summary: 
+		//		When handlers of input are fired, this method check input value and (if needed) modify it
+		// tags:
+		//		private
+		var parsedValue = this._parseValue(value);
+		if(dojo.isArray(parsedValue)){
+			this.add(parsedValue);
+		}
+	},
+	
+	_onClick:  function(/*event*/e){
+		// summary: 
+		//		give focus to inputbox
+		// tags:
+		//		private
+		this._focusInput();
+	},
+	
+	_focusInput: function(){
+		// summary: 
+		//		give focus to input
+		// tags:
+		//		private
+		if(!this.readOnlyInput && this._input.focus){
+			this._input.focus();
+		}
+	},
+
+	_inputOnKeyDown: function(/*event*/e){
+		// summary: 
+		//		Used to add keybord interactivity
+		// tags:
+		//		private
+		this._currentItem=null;
+		
+		if(e.keyCode == dojo.keys.BACKSPACE && this._input.attr("value") == "" && this.get("lastItem")){
+			this._destroyItem(this.get("lastItem"));
+		}else if(e.keyCode == dojo.keys.ENTER && this._input.attr("value") != ""){
+			this.add(this._input.attr("value"));
+		}else if(e.keyCode == dojo.keys.LEFT_ARROW && this._getCursorPos(this._input.focusNode)==0 &&
+			!this.readOnlyItem && this.useArrowForEdit){
+				this._editBefore();
+		}
+	},
+	
+	_inputOnBlur: function(){
+		// summary: 
+		//		Remove focus class and act like pressing ENTER key
+		// tags:
+		//		private
+		if(this.useOnBlur && this._input.attr("value") != ""){
+			this.add(this._input.attr("value"));
+		}
+	},
+	
+	_getMatchedValueAttr: function(){
+		// summary: 
+		//		get value that match regexp in then list and return an array
+		// tags:
+		//		private
+		return this._getValues(dojo.hitch(this,this._matchValidator));
+	},
+	
+	_getMismatchedValueAttr: function(){
+		// summary: 
+		//		get value that mismatch regexp in then list and return an array
+		// tags:
+		//		private
+		return this._getValues(dojo.hitch(this,this._mismatchValidator));
+	},
+	
+	_getValues: function(/*function*/validator){
+		// summary: 
+		//		return values with comparator constraint
+		// tags:
+		//		private
+		var value = [];
+		validator = validator||this._nullValidator;
+		for(var i in this._items){
+			var item = this._items[i];
+			if(item === null){
+				continue;
+			}
+			var itemValue=item.attr("value");
+			if (validator(itemValue)){
+				value.push(itemValue);
+			}
+		}
+		return value;
+	},
+	
+	_nullValidator: function(/*String*/itemValue){
+		// summary: 
+		//		return true or false
+		// tags:
+		//		private
+		return true;
+	},
+	_matchValidator: function(/*String*/itemValue){
+		// summary: 
+		//		return true or false
+		// tags:
+		//		private
+		var re = new RegExp(this.regExpGen(this.constraints));
+		return itemValue.match(re);
+	},
+	_mismatchValidator: function(/*String*/itemValue){
+		// summary: 
+		//		return true or false
+		// tags:
+		//		private
+		var re = new RegExp(this.regExpGen(this.constraints));
+		return !(itemValue.match(re));
+	},
+	
+	_getLastItemAttr: function(){
+		// summary: 
+		//		return the last item in list
+		// tags:
+		//		private
+		return this._getSomeItem();
+	},
+	_getSomeItem: function(/*dijit._Widget*/ item,/*String*/ position){
+		// summary: 
+		//		return the item before the one in params
+		// tags:
+		//		private
+		item=item||false;
+		position=position||"last";
+		
+		var lastItem = null;
+		var stop=-1;
+		for(var i in this._items){
+			if(this._items[i] === null){ continue; }
+			
+			if(position=="before" && this._items[i] === item){
+				break;
+			}
+			
+			lastItem = this._items[i];
+			
+			if(position=="first" ||stop==0){
+				stop=1;
+				break;
+			}
+			if(position=="after" && this._items[i] === item){
+				stop=0;
+			}
+		}
+		if(position=="after" && stop==0){
+			lastItem = null;
+		}
+		return lastItem;
+	},
+	_getPreviousItem: function(/*dijit._Widget*/ item){
+		// summary: 
+		//		return the item before the one in params
+		// tags:
+		//		private
+		return this._getSomeItem(item,"before");
+	},
+	_getNextItem: function(/*dijit._Widget*/ item){
+		// summary: 
+		//		return the item before the one in params
+		// tags:
+		//		private
+		return this._getSomeItem(item,"after");
+	},
+	
+	_destroyItem: function(/*dijit._Widget*/ item, /*Boolean?*/ updateValue){
+		// summary: 
+		//		destroy an item
+		// tags:
+		//		private
+		this._items[item.index] = null;
+		item.destroy();
+		this._count--;
+		if(updateValue!==false){
+			this._updateValues();
+			this._setReadOnlyWhenMaxItemsReached();
+		}
+	},
+	
+	_updateValues: function(){
+		// summary: 
+		//		update this.value and the select node
+		// tags:
+		//		private
+		this.value = this._getValues();
+		this._setSelectNode();
+	},
+	
+	_destroyAllItems: function(){
+		// summary: 
+		//		destroy all items
+		// tags:
+		//		private
+		for(var i in this._items){
+			if(this._items[i]==null){ continue; }
+			this._destroyItem(this._items[i],false);
+		}
+		this._items = [];
+		this._count = 0;
+		this.value = null;
+		this._setSelectNode();
+		this._setReadOnlyWhenMaxItemsReached();
+	},
+	
+	destroy: function(){
+		// summary:
+		//		Destroy all widget
+		this._destroyAllItems();
+		this._lastAddedItem = null;
+		
+		if(!this._input){
+			this._input.destroy();
+		}
+		
+		this.inherited(arguments);
+	}
+});
+
+dojo.declare("dojox.form._ListInputInputItem", 
+	[dijit._Widget, dijit._Templated],
+	{
+	// summary: 
+	//	Item created by ListInputInput when delimiter is found
+	// description:
+	//		Simple <li> with close button added to ListInputInput when delimiter is found
+	
+	templateString: "<li class=\"dijit dijitReset dijitLeft dojoxListInputItem\" dojoAttachEvent=\"onclick: onClick\" ><span dojoAttachPoint=\"labelNode\"></span></li>",
+	
+	// closeButtonNode: domNode
+	//		ref to the close button node
+	closeButtonNode: null,
+	
+	// readOnlyItem: Boolean
+	//		if true, item is editable
+	readOnlyItem: true,
+	
+	baseClass:"dojoxListInputItem",
+	
+	// value: String
+	//		value of item
+	value: "",
+	
+	// regExp: [extension protected] String
+	//		regular expression string used to validate the input
+	//		Do not specify both regExp and regExpGen
+	regExp: ".*",
+	
+	// _editBox: Widget
+	//		inline edit box
+	_editBox: null,
+	
+	// _handleKeyDown: handle
+	//		handle for the keyDown connect
+	_handleKeyDown: null,
+	
+	attributeMap: {
+		value: { node: "labelNode", type: "innerHTML" }
+	},
+	
+	postMixInProperties: function(){
+		var _nlsResources = dojo.i18n.getLocalization("dijit", "common");
+		dojo.mixin(this, _nlsResources);
+		this.inherited(arguments);
+	},
+	
+	postCreate: function(){
+		// summary:
+		//		Create the close button if needed
+		this.inherited(arguments);
+		
+		this.closeButtonNode = dojo.create("span",{
+			"class" : "dijitButtonNode dijitDialogCloseIcon",
+			title : this.itemClose,
+			onclick: dojo.hitch(this, "onClose"),
+			onmouseenter: dojo.hitch(this, "_onCloseEnter"),
+			onmouseleave: dojo.hitch(this, "_onCloseLeave")
+		}, this.domNode);
+		
+		dojo.create("span",{
+			"class" : "closeText",
+			title : this.itemClose,
+			innerHTML : "x"
+		}, this.closeButtonNode);
+	},
+	
+	startup: function(){
+		// summary:
+		//		add the edit box
+		this.inherited(arguments);
+		this._createInlineEditBox();
+	},
+	
+	_setReadOnlyItemAttr: function(/*Boolean*/value){
+		// summary:
+		//		change the readonly state
+		// tags:
+		//		private
+		this.readOnlyItem = value;
+		if(!value){
+			this._createInlineEditBox();
+		}else if(this._editBox){
+			this._editBox.attr("disabled",true);
+		}
+	},
+	
+	_createInlineEditBox: function(){
+		// summary:
+		//		create the inline editbox if needed
+		// tags:
+		//		private
+		if(this.readOnlyItem){ return; }
+		if(!this._started){ return; }
+		if(this._editBox){ 
+			this._editBox.attr("disabled",false);
+			return; 
+		}
+		this._editBox=new dijit.InlineEditBox({
+			value:this.value,
+			editor: "dijit.form.ValidationTextBox",
+			editorParams:{
+				regExp:this.regExp
+			}
+		},this.labelNode);
+		this.connect(this._editBox,"edit","_onEdit");
+		this.connect(this._editBox,"onChange","_onCloseEdit");
+		this.connect(this._editBox,"onCancel","_onCloseEdit");
+	},
+	
+	edit: function(){
+		// summary:
+		//		enter inline editbox in edit mode
+		if(!this.readOnlyItem){
+			this._editBox.edit();
+		}
+	},
+	
+	_onCloseEdit: function(/*String*/value){
+		// summary:
+		//		call when inline editor close himself
+		// tags:
+		//		private
+		dojo.removeClass(this.closeButtonNode,this.baseClass + "Edited");
+		dojo.disconnect(this._handleKeyDown);
+		this.onChange(value);
+	},
+	
+	_onEdit: function(){
+		// summary:
+		//		call when inline editor start editing
+		// tags:
+		//		private
+		dojo.addClass(this.closeButtonNode,this.baseClass + "Edited");
+		this._handleKeyDown = dojo.connect(this._editBox.editWidget,"_onKeyPress",this,"onKeyDown");
+		this.onEdit();
+	},
+	
+	_setDisabledAttr: function(/*Boolean*/value){
+		// summary:
+		//		disable inline edit box
+		// tags:
+		//		private
+		if(!this.readOnlyItem){
+			this._editBox.attr("disabled",value);
+		}
+	},
+	
+	_getValueAttr: function(){
+		// summary:
+		//		return value
+		// tags:
+		//		private
+		return (!this.readOnlyItem && this._started ? this._editBox.attr("value") : this.value);
+	},
+	
+	destroy: function(){
+		// summary:
+		//		Destroy the inline editbox
+		if(this._editBox){
+			this._editBox.destroy();
+		}
+		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");
+	},
+	
+	onClose: function(){
+		// summary: 
+		//		callback when close button is clicked
+	},
+	
+	onEdit: function(){
+		// summary: 
+		//		callback when widget come in edition
+	},
+	
+	onClick: function(){
+		// summary: 
+		//		callback when widget is click
+	},
+	
+	onChange: function(/*String*/value){
+		// summary: 
+		//		callback when widget change its content
+	},
+	
+	
+	onKeyDown: function(/*String*/value){
+		// summary:
+		//		callback when widget get a KeyDown
+	}
+});
+dojo.declare("dojox.form._ListInputInputBox", 
+	[dijit.form.ValidationTextBox],
+	{
+	// summary: 
+	//	auto-sized text box
+	// description:
+	//		Auto sized textbox based on dijit.form.TextBox
+	
+	// minWidth: Integer
+	//		Min width of the input box
+	minWidth:50,
+	
+	// intermediateChanges: Boolean
+	//		Fires onChange for each value change or only on demand
+	//		Force to true in order to get onChanged called
+	intermediateChanges:true,
+	
+	// regExp: [extension protected] String
+	//		regular expression string used to validate the input
+	//		Do not specify both regExp and regExpGen
+	regExp: ".*",
+	
+	// _sizer: DomNode
+	//		Used to get size of textbox content
+	_sizer:null,
+	
+	onChange: function(/*string*/value){
+		// summary: 
+		//		compute content width
+		this.inherited(arguments);
+		if(this._sizer === null){
+			this._sizer = dojo.create("div",{
+				style : {
+					position : "absolute",
+					left : "-10000px",
+					top : "-10000px"
+				}
+			},dojo.body());
+		}
+		this._sizer.innerHTML = value;
+		var w = dojo.contentBox(this._sizer).w + this.minWidth;
+		dojo.contentBox(this.domNode,{ w : w });
+	}, 
+	
+	destroy: function(){
+		// summary:
+		//		destroy the widget
+		dojo.destroy(this._sizer);
+		this.inherited(arguments);
+	}
+});
\ No newline at end of file
diff --git a/dojox/form/Manager.js b/dojox/form/Manager.js
index 16f767f..aa9406d 100644
--- a/dojox/form/Manager.js
+++ b/dojox/form/Manager.js
@@ -1,15 +1,8 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.Manager"]){
-dojo._hasResource["dojox.form.Manager"]=true;
 dojo.provide("dojox.form.Manager");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
+
 dojo.require("dojox.form.manager._Mixin");
 dojo.require("dojox.form.manager._NodeMixin");
 dojo.require("dojox.form.manager._FormMixin");
@@ -17,14 +10,34 @@ dojo.require("dojox.form.manager._ValueMixin");
 dojo.require("dojox.form.manager._EnableMixin");
 dojo.require("dojox.form.manager._DisplayMixin");
 dojo.require("dojox.form.manager._ClassMixin");
-dojo.declare("dojox.form.Manager",[dijit._Widget,dojox.form.manager._Mixin,dojox.form.manager._NodeMixin,dojox.form.manager._FormMixin,dojox.form.manager._ValueMixin,dojox.form.manager._EnableMixin,dojox.form.manager._DisplayMixin,dojox.form.manager._ClassMixin],{buildRendering:function(){
-var _1=this.domNode=this.srcNodeRef;
-if(!this.containerNode){
-this.containerNode=_1;
-}
-this._attachPoints=[];
-dijit._Templated.prototype._attachTemplateNodes.call(this,_1);
-},destroyRendering:function(){
-dijit._Templated.prototype.destroyRendering.call(this);
-}});
-}
+
+dojo.declare("dojox.form.Manager", [
+		dijit._Widget,
+		dojox.form.manager._Mixin,
+		dojox.form.manager._NodeMixin,
+		dojox.form.manager._FormMixin,
+		dojox.form.manager._ValueMixin,
+		dojox.form.manager._EnableMixin,
+		dojox.form.manager._DisplayMixin,
+		dojox.form.manager._ClassMixin
+], {
+	// summary:
+	//		The widget to orchestrate dynamic forms.
+	// description:
+	//		This widget hosts dojox.form.manager mixins.
+	//		See dojox.form.manager._Mixin for more info.
+
+	buildRendering: function(){
+		var node = this.domNode = this.srcNodeRef;
+		if(!this.containerNode){
+			// all widgets with descendants must set containerNode
+				this.containerNode = node;
+		}
+		this._attachPoints = [];
+		dijit._Templated.prototype._attachTemplateNodes.call(this, node);
+	},
+	
+	destroyRendering: function(){
+		dijit._Templated.prototype.destroyRendering.call(this);
+	}
+});
diff --git a/dojox/form/MultiComboBox.js b/dojox/form/MultiComboBox.js
index 32ea2a2..4bb9a78 100644
--- a/dojox/form/MultiComboBox.js
+++ b/dojox/form/MultiComboBox.js
@@ -1,46 +1,57 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.MultiComboBox"]){
-dojo._hasResource["dojox.form.MultiComboBox"]=true;
 dojo.provide("dojox.form.MultiComboBox");
-dojo.experimental("dojox.form.MultiComboBox");
+dojo.experimental("dojox.form.MultiComboBox"); 
 dojo.require("dijit.form.ComboBox");
 dojo.require("dijit.form.ValidationTextBox");
-dojo.declare("dojox.form.MultiComboBox",[dijit.form.ValidationTextBox,dijit.form.ComboBoxMixin],{delimiter:",",_previousMatches:false,_setValueAttr:function(_1){
-if(this.delimiter&&_1.length!=0){
-_1=_1+this.delimiter+" ";
-arguments[0]=this._addPreviousMatches(_1);
-}
-this.inherited(arguments);
-},_addPreviousMatches:function(_2){
-if(this._previousMatches){
-if(!_2.match(new RegExp("^"+this._previousMatches))){
-_2=this._previousMatches+_2;
-}
-_2=this._cleanupDelimiters(_2);
-}
-return _2;
-},_cleanupDelimiters:function(_3){
-if(this.delimiter){
-_3=_3.replace(new RegExp("  +")," ");
-_3=_3.replace(new RegExp("^ *"+this.delimiter+"* *"),"");
-_3=_3.replace(new RegExp(this.delimiter+" *"+this.delimiter),this.delimiter);
-}
-return _3;
-},_autoCompleteText:function(_4){
-arguments[0]=this._addPreviousMatches(_4);
-this.inherited(arguments);
-},_startSearch:function(_5){
-_5=this._cleanupDelimiters(_5);
-var re=new RegExp("^.*"+this.delimiter+" *");
-if((this._previousMatches=_5.match(re))){
-arguments[0]=_5.replace(re,"");
-}
-this.inherited(arguments);
-}});
-}
+
+dojo.declare("dojox.form.MultiComboBox",
+	[dijit.form.ValidationTextBox, dijit.form.ComboBoxMixin],{
+	//
+	// summary: A ComboBox that accpets multiple inputs on a single line?
+	//
+	// delimiter: String
+	// 	The character to use to separate items in the ComboBox input
+	delimiter: ",",
+	_previousMatches: false,
+
+	_setValueAttr: function(value){
+		if (this.delimiter && value.length != 0){
+			value = value+this.delimiter+" ";
+			arguments[0] = this._addPreviousMatches(value);
+		}
+		this.inherited(arguments);
+	},
+
+	_addPreviousMatches: function(/* String */text){
+		if(this._previousMatches){
+			if(!text.match(new RegExp("^"+this._previousMatches))){
+				text = this._previousMatches+text;
+			}
+			text = this._cleanupDelimiters(text);
+		}
+		return text; // String
+	},
+
+	_cleanupDelimiters: function(/* String */text){
+		if(this.delimiter){
+			text = text.replace(new RegExp("  +"), " ");
+			text = text.replace(new RegExp("^ *"+this.delimiter+"* *"), "");
+			text = text.replace(new RegExp(this.delimiter+" *"+this.delimiter), this.delimiter);
+		}
+		return text;
+	},
+			
+	_autoCompleteText: function(/* String */text){
+		arguments[0] = this._addPreviousMatches(text);
+		this.inherited(arguments);
+	},
+
+	_startSearch: function(/* String */text){
+		text = this._cleanupDelimiters(text);
+		var re = new RegExp("^.*"+this.delimiter+" *");
+		
+		if((this._previousMatches = text.match(re))){
+			arguments[0] = text.replace(re, "");
+		}
+		this.inherited(arguments);
+	}		
+});
diff --git a/dojox/form/PasswordValidator.js b/dojox/form/PasswordValidator.js
index 2a205a2..49235c2 100644
--- a/dojox/form/PasswordValidator.js
+++ b/dojox/form/PasswordValidator.js
@@ -1,159 +1,312 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.PasswordValidator"]){
-dojo._hasResource["dojox.form.PasswordValidator"]=true;
 dojo.provide("dojox.form.PasswordValidator");
+
 dojo.require("dijit.form._FormWidget");
 dojo.require("dijit.form.ValidationTextBox");
-dojo.requireLocalization("dojox.form","PasswordValidator",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dojox.form._ChildTextBox",dijit.form.ValidationTextBox,{containerWidget:null,type:"password",reset:function(){
-dijit.form.ValidationTextBox.prototype._setValueAttr.call(this,"",true);
-this._hasBeenBlurred=false;
-},postCreate:function(){
-this.inherited(arguments);
-if(!this.name){
-dojo.removeAttr(this.focusNode,"name");
-}
-this.connect(this.focusNode,"onkeypress","_onChildKeyPress");
-},_onChildKeyPress:function(e){
-if(e&&e.keyCode==dojo.keys.ENTER){
-this._setBlurValue();
-}
-}});
-dojo.declare("dojox.form._OldPWBox",dojox.form._ChildTextBox,{_isPWValid:false,_setValueAttr:function(_1,_2){
-if(_1===""){
-_1=dojox.form._OldPWBox.superclass.attr.call(this,"value");
-}
-if(_2!==null){
-this._isPWValid=this.containerWidget.pwCheck(_1);
-}
-this.inherited(arguments);
-this.containerWidget._childValueAttr(this.containerWidget._inputWidgets[1].attr("value"));
-},isValid:function(_3){
-return this.inherited("isValid",arguments)&&this._isPWValid;
-},_update:function(e){
-if(this._hasBeenBlurred){
-this.validate(true);
-}
-this._onMouse(e);
-},_getValueAttr:function(){
-if(this.containerWidget._started&&this.containerWidget.isValid()){
-return this.inherited(arguments);
-}
-return "";
-},_setBlurValue:function(){
-var _4=dijit.form.ValidationTextBox.prototype._getValueAttr.call(this);
-this._setValueAttr(_4,(this.isValid?this.isValid():true));
-}});
-dojo.declare("dojox.form._NewPWBox",dojox.form._ChildTextBox,{required:true,onChange:function(){
-this.containerWidget._inputWidgets[2].validate(false);
-this.inherited(arguments);
-}});
-dojo.declare("dojox.form._VerifyPWBox",dojox.form._ChildTextBox,{isValid:function(_5){
-return this.inherited("isValid",arguments)&&(this.attr("value")==this.containerWidget._inputWidgets[1].attr("value"));
-}});
-dojo.declare("dojox.form.PasswordValidator",dijit.form._FormValueWidget,{required:true,_inputWidgets:null,oldName:"",templateString:dojo.cache("dojox.form","resources/PasswordValidator.html","<div dojoAttachPoint=\"containerNode\">\n\t<input type=\"hidden\" name=\"${name}\" value=\"\" dojoAttachPoint=\"focusNode\" />\n</div>\n"),_hasBeenBlurred:false,isValid:function(_6){
-return dojo.every(this._inputWidgets,function(i){
-if(i&&i._setStateClass){
-i._setStateClass();
-}
-return (!i||i.isValid());
+
+dojo.requireLocalization("dojox.form", "PasswordValidator");
+
+dojo.declare("dojox.form._ChildTextBox", dijit.form.ValidationTextBox, {
+	// summary:
+	//		A class that is shared between all our children - extends 
+	//		ValidationTextBox and provides some shared functionality
+	//
+	// containerWidget: widget
+	//		Our parent (the PasswordValidator)
+	containerWidget: null,
+	
+	// type: string
+	//		Don't override this - we are all "password" types
+	type: "password",
+	
+	reset: function(){
+		// summary:
+		//		Force-set to empty string (we don't save passwords EVER)...and 
+		//		since _OldPWBox overrides _setValueAttr to check for empty string, 
+		//		call our parent class directly (not this.inherited())
+		dijit.form.ValidationTextBox.prototype._setValueAttr.call(this, "", true);
+		this._hasBeenBlurred = false;
+	},
+	
+	postCreate: function(){
+		// summary:
+		//		We want to remove the "name" attribute from our focus node if
+		//		we don't have one set - this prevents all our extra values
+		//		from being posted on submit
+		this.inherited(arguments);
+		if(!this.name){
+			dojo.removeAttr(this.focusNode, "name");
+		}
+		this.connect(this.focusNode, "onkeypress", "_onChildKeyPress");
+	},
+	
+	_onChildKeyPress: function(e){
+		// Check if we pressed <enter> - if so, set our blur value so that
+		// the parent widget will be updated correctly.
+		if(e && e.keyCode == dojo.keys.ENTER){
+			this._setBlurValue();
+		}
+	}
 });
-},validate:function(_7){
-return dojo.every(dojo.map(this._inputWidgets,function(i){
-if(i&&i.validate){
-i._hasBeenBlurred=(i._hasBeenBlurred||this._hasBeenBlurred);
-return i.validate();
-}
-return true;
-},this),"return item;");
-},reset:function(){
-this._hasBeenBlurred=false;
-dojo.forEach(this._inputWidgets,function(i){
-if(i&&i.reset){
-i.reset();
-}
-},this);
-},_createSubWidgets:function(){
-var _8=this._inputWidgets,_9=dojo.i18n.getLocalization("dojox.form","PasswordValidator",this.lang);
-dojo.forEach(_8,function(i,_a){
-if(i){
-var p={containerWidget:this},c;
-if(_a===0){
-p.name=this.oldName;
-p.invalidMessage=_9.badPasswordMessage;
-c=dojox.form._OldPWBox;
-}else{
-if(_a===1){
-p.required=this.required;
-c=dojox.form._NewPWBox;
-}else{
-if(_a===2){
-p.invalidMessage=_9.nomatchMessage;
-c=dojox.form._VerifyPWBox;
-}
-}
-}
-_8[_a]=new c(p,i);
-}
-},this);
-},pwCheck:function(_b){
-return false;
-},postCreate:function(){
-this.inherited(arguments);
-var _c=this._inputWidgets=[];
-dojo.forEach(["old","new","verify"],function(i){
-_c.push(dojo.query("input[pwType="+i+"]",this.containerNode)[0]);
-},this);
-if(!_c[1]||!_c[2]){
-throw new Error("Need at least pwType=\"new\" and pwType=\"verify\"");
-}
-if(this.oldName&&!_c[0]){
-throw new Error("Need to specify pwType=\"old\" if using oldName");
-}
-this.containerNode=this.domNode;
-this._createSubWidgets();
-this.connect(this._inputWidgets[1],"_setValueAttr","_childValueAttr");
-this.connect(this._inputWidgets[2],"_setValueAttr","_childValueAttr");
-},_childValueAttr:function(v){
-this.attr("value",this.isValid()?v:"");
-},_setDisabledAttr:function(_d){
-this.inherited(arguments);
-dojo.forEach(this._inputWidgets,function(i){
-if(i&&i.attr){
-i.attr("disabled",_d);
-}
+
+
+
+dojo.declare("dojox.form._OldPWBox", dojox.form._ChildTextBox, {
+	// summary:
+	//		A class representing our "old password" box.
+	//
+	// _isPWValid: boolean
+	//		Whether or not the password is valid
+	_isPWValid: false,
+	
+	_setValueAttr: function(/* anything */ newVal, /* boolean? */ priority){
+		// summary:
+		//		Updates _isPWValid if this isn't our initial update by calling
+		//		our PasswordValidator's pwCheck function
+		if(newVal === ""){
+			newVal = dojox.form._OldPWBox.superclass.attr.call(this, "value");
+		}
+		if(priority !== null){
+			//  Priority is passed in as null, explicitly when this is an 
+			//	update (not initially set).  We want to check our password now.
+			this._isPWValid = this.containerWidget.pwCheck(newVal);
+		}
+		this.inherited(arguments);
+		// Trigger the containerWidget to recheck its value, if needed
+		this.containerWidget._childValueAttr(this.containerWidget._inputWidgets[1].attr("value"));
+	},
+
+	isValid: function(/* boolean */ isFocused){
+		// Take into account the isPWValid setting
+		return this.inherited("isValid", arguments) && this._isPWValid;
+	},
+
+	_update: function(/* event */ e){
+		// Only call validate() if we've been blurred or else we get popups 
+		// too early.
+		if(this._hasBeenBlurred){ this.validate(true); }
+		this._onMouse(e);
+	},
+
+	_getValueAttr: function(){
+		if(this.containerWidget._started && this.containerWidget.isValid()){
+			return this.inherited(arguments);
+		}
+		return "";
+	},
+
+	_setBlurValue: function(){
+		// TextBox._setBlurValue calls this._setValueAttr(this.get('value'), ...)
+		// Because we are overridding _getValueAttr to return "" when the containerWidget
+		// is not valid, TextBox._setBlurValue will cause OldPWBox's value to be set to ""
+		//
+		// So, we directly call ValidationTextBox._getValueAttr to bypass our _getValueAttr
+		var value = dijit.form.ValidationTextBox.prototype._getValueAttr.call(this);
+		this._setValueAttr(value, (this.isValid ? this.isValid() : true));
+	}
 });
-},_setRequiredAttribute:function(_e){
-this.required=_e;
-dojo.attr(this.focusNode,"required",_e);
-dijit.setWaiState(this.focusNode,"required",_e);
-this._refreshState();
-dojo.forEach(this._inputWidgets,function(i){
-if(i&&i.attr){
-i.attr("required",_e);
-}
+
+
+dojo.declare("dojox.form._NewPWBox", dojox.form._ChildTextBox, {
+	// summary:
+	//		A class representing our new password textbox
+
+	// required: boolean
+	//		Whether or not this widget is required (default: true)
+	required: true,
+	
+	onChange: function(){
+		// summary:
+		//		Validates our verify box - to make sure that a change to me is
+		//		reflected there
+		this.containerWidget._inputWidgets[2].validate(false);
+		this.inherited(arguments);
+	}
 });
-},_setValueAttr:function(v){
-this.inherited(arguments);
-dojo.attr(this.focusNode,"value",v);
-},_getValueAttr:function(){
-return this.inherited(arguments)||"";
-},focus:function(){
-var f=false;
-dojo.forEach(this._inputWidgets,function(i){
-if(i&&!i.isValid()&&!f){
-i.focus();
-f=true;
-}
+
+dojo.declare("dojox.form._VerifyPWBox", dojox.form._ChildTextBox, {
+	// summary:
+	//		A class representing our verify textbox
+
+	isValid: function(isFocused){
+		// summary:
+		//		Validates that we match the "real" password
+		return this.inherited("isValid", arguments) &&
+			(this.get("value") == this.containerWidget._inputWidgets[1].attr("value"));
+	}
 });
-if(!f){
-this._inputWidgets[1].focus();
-}
-}});
-}
+
+dojo.declare("dojox.form.PasswordValidator", dijit.form._FormValueWidget, {
+	// summary:
+	//		A password validation widget that simplifies the "old/new/verify" 
+	//		style of requesting passwords.  You will probably want to override
+	//		this class and implement your own pwCheck function.
+	//
+	// required: boolean
+	//		Whether or not it is required for form submission
+	required: true,
+	
+	// inputWidgets: TextBox[]
+	//		An array of text boxes that are our components
+	_inputWidgets: null,
+
+	// oldName: string?
+	//		The name to send our old password as (when form is posted)
+	oldName: "",
+	
+	templateString: dojo.cache("dojox.form", "resources/PasswordValidator.html"),
+	
+	_hasBeenBlurred: false,
+
+	isValid: function(/* boolean */ isFocused){
+		// summary: we are valid if ALL our children are valid
+		return dojo.every(this._inputWidgets, function(i){
+			if(i && i._setStateClass){ i._setStateClass(); }
+			return (!i || i.isValid());
+		});
+	},
+
+	validate: function(/* boolean */ isFocused){
+		// summary: Validating this widget validates all our children
+		return dojo.every(dojo.map(this._inputWidgets, function(i){
+			if(i && i.validate){
+				i._hasBeenBlurred = (i._hasBeenBlurred || this._hasBeenBlurred);
+				return i.validate();
+			}
+			return true;
+		}, this), "return item;");
+	},
+
+	reset: function(){
+		// summary: Resetting this widget resets all our children
+		this._hasBeenBlurred = false;
+		dojo.forEach(this._inputWidgets, function(i){
+			if(i && i.reset){ i.reset(); }
+		}, this);
+	},
+
+	_createSubWidgets: function(){
+		// summary:
+		//		Turns the inputs inside this widget into "real" validation
+		//		widgets - and sets up the needed connections.
+		var widgets = this._inputWidgets,
+			msg = dojo.i18n.getLocalization("dojox.form", "PasswordValidator", 
+																	this.lang);
+		dojo.forEach(widgets, function(i, idx){
+			if(i){
+				var p = {containerWidget: this}, c;
+				if(idx === 0){
+					p.name = this.oldName;
+					p.invalidMessage = msg.badPasswordMessage;
+					c = dojox.form._OldPWBox;
+				}else if(idx === 1){
+					p.required = this.required;
+					c = dojox.form._NewPWBox;
+				}else if(idx === 2){
+					p.invalidMessage = msg.nomatchMessage;
+					c = dojox.form._VerifyPWBox;
+				}
+				widgets[idx] = new c(p, i);
+			}
+		}, this);	
+	},
+
+	pwCheck: function(/* string */ password){ 
+		// summary:
+		//		Overridable function for validation of the old password box.
+		//
+		//		This function is called and passed the old password.  Return
+		//		true if it's OK to continue, and false if it is not.
+		//		
+		//		IMPORTANT SECURITY NOTE:  Do NOT EVER EVER EVER check this in
+		//									HTML or JavaScript!!!
+		//
+		//		You will probably want to override this function to callback 
+		//		to a server to verify the password (the callback will need to 
+		//		be syncronous) - and it's probably a good idea to validate
+		//		it again on form submission before actually doing
+		//		anything destructive - that's why the "oldName" value 
+		//		is available.
+		//
+		//		And don't just fetch the password from the server 
+		//		either :)  Send the test password (probably hashed, for
+		//		security) and return from the server a status instead.
+		//				
+		//		Again - DON'T BE INSECURE!!!  Security is left as an exercise 
+		//		for the reader :)
+		return false; 
+	},
+
+	postCreate: function(){
+		//	summary:
+		//		Sets up the correct widgets.  You *MUST* specify one child
+		//		text box (a simple HTML <input> element) with pwType="new" 
+		//		*and* one child text box with pwType="verify".  You *MAY* 
+		//		specify a third child text box with pwType="old" in order to 
+		//		prompt the user to enter in their old password before the 
+		//		widget returns that it is valid.
+		
+		this.inherited(arguments);
+		
+		// Turn my inputs into the correct stuff....
+		var widgets = this._inputWidgets = [];
+		dojo.forEach(["old","new","verify"], function(i){
+			widgets.push(dojo.query("input[pwType=" + i + "]", 
+									this.containerNode)[0]);
+		}, this);
+		if (!widgets[1] || !widgets[2]){
+			throw new Error("Need at least pwType=\"new\" and pwType=\"verify\"");
+		}
+		if (this.oldName && !widgets[0]){
+			throw new Error("Need to specify pwType=\"old\" if using oldName");
+		}
+		this.containerNode = this.domNode;
+		this._createSubWidgets();
+		this.connect(this._inputWidgets[1], "_setValueAttr", "_childValueAttr");
+		this.connect(this._inputWidgets[2], "_setValueAttr", "_childValueAttr");		
+	},
+	
+	_childValueAttr: function(v){
+		this.set("value", this.isValid() ? v : "");
+	},
+	
+	_setDisabledAttr: function(value){
+		this.inherited(arguments);
+		dojo.forEach(this._inputWidgets, function(i){
+			if(i && i.attr){ i.attr("disabled", value);}
+		});
+	},
+	
+	_setRequiredAttribute: function(value){
+		this.required = value;
+		dojo.attr(this.focusNode, "required", value);
+		dijit.setWaiState(this.focusNode, "required", value);
+		this._refreshState();
+		dojo.forEach(this._inputWidgets, function(i){
+			if(i && i.attr){ i.attr("required", value);}
+		});
+	},
+
+	_setValueAttr: function(v){
+		this.inherited(arguments);
+		dojo.attr(this.focusNode, "value", v);
+	},
+	
+	_getValueAttr: function(){
+		// Make sure we don't return undefined....
+		return this.inherited(arguments)||"";
+	},
+	
+	focus: function(){
+		// summary: 
+		//		places focus on the first invalid input widget - if all
+		//		input widgets are valid, the first widget is focused.
+		var f = false;
+		dojo.forEach(this._inputWidgets, function(i){
+			if(i && !i.isValid() && !f){
+				i.focus();
+				f = true;
+			}
+		});
+		if(!f){ this._inputWidgets[1].focus(); }
+	}
+});
\ No newline at end of file
diff --git a/dojox/form/RadioStack.js b/dojox/form/RadioStack.js
index c9b89bd..cd65673 100644
--- a/dojox/form/RadioStack.js
+++ b/dojox/form/RadioStack.js
@@ -1,14 +1,9 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.RadioStack"]){
-dojo._hasResource["dojox.form.RadioStack"]=true;
 dojo.provide("dojox.form.RadioStack");
+
 dojo.require("dojox.form.CheckedMultiSelect");
 dojo.require("dojox.form._SelectStackMixin");
-dojo.declare("dojox.form.RadioStack",[dojox.form.CheckedMultiSelect,dojox.form._SelectStackMixin],{});
-}
+
+dojo.declare("dojox.form.RadioStack",
+	[ dojox.form.CheckedMultiSelect, dojox.form._SelectStackMixin ], {
+	// summary: A radio-based select stack.
+});
\ No newline at end of file
diff --git a/dojox/form/RangeSlider.js b/dojox/form/RangeSlider.js
index a4f4e8d..60dd19f 100644
--- a/dojox/form/RangeSlider.js
+++ b/dojox/form/RangeSlider.js
@@ -1,297 +1,389 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.RangeSlider"]){
-dojo._hasResource["dojox.form.RangeSlider"]=true;
 dojo.provide("dojox.form.RangeSlider");
 dojo.require("dijit.form.HorizontalSlider");
 dojo.require("dijit.form.VerticalSlider");
 dojo.require("dojox.fx");
+
 (function(){
-var _1=function(a,b){
-return b-a;
-},_2=function(a,b){
-return a-b;
-};
-dojo.declare("dojox.form._RangeSliderMixin",null,{value:[0,100],postMixInProperties:function(){
-this.value=dojo.map(this.value,function(i){
-return parseInt(i,10);
-});
-},postCreate:function(){
-this.inherited(arguments);
-this.value.sort(this._isReversed()?_1:_2);
-var _3=this;
-var _4=function(){
-dijit.form._SliderMoverMax.apply(this,arguments);
-this.widget=_3;
-};
-dojo.extend(_4,dijit.form._SliderMoverMax.prototype);
-this._movableMax=new dojo.dnd.Moveable(this.sliderHandleMax,{mover:_4});
-dijit.setWaiState(this.focusNodeMax,"valuemin",this.minimum);
-dijit.setWaiState(this.focusNodeMax,"valuemax",this.maximum);
-var _5=function(){
-dijit.form._SliderBarMover.apply(this,arguments);
-this.widget=_3;
-};
-dojo.extend(_5,dijit.form._SliderBarMover.prototype);
-this._movableBar=new dojo.dnd.Moveable(this.progressBar,{mover:_5});
-},destroy:function(){
-this.inherited(arguments);
-this._movableMax.destroy();
-this._movableBar.destroy();
-},_onKeyPress:function(e){
-if(this.disabled||this.readOnly||e.altKey||e.ctrlKey){
-return;
-}
-var _6=e.currentTarget,_7=false,_8=false,k=dojo.keys;
-if(_6==this.sliderHandle){
-_7=true;
-}else{
-if(_6==this.progressBar){
-_8=_7=true;
-}else{
-if(_6==this.sliderHandleMax){
-_8=true;
-}
-}
-}
-switch(e.keyCode){
-case k.HOME:
-this._setValueAttr(this.minimum,true,_8);
-break;
-case k.END:
-this._setValueAttr(this.maximum,true,_8);
-break;
-case ((this._descending||this.isLeftToRight())?k.RIGHT_ARROW:k.LEFT_ARROW):
-case (this._descending===false?k.DOWN_ARROW:k.UP_ARROW):
-case (this._descending===false?k.PAGE_DOWN:k.PAGE_UP):
-if(_7&&_8){
-this._bumpValue([{"change":e.keyCode==k.PAGE_UP?this.pageIncrement:1,"useMaxValue":true},{"change":e.keyCode==k.PAGE_UP?this.pageIncrement:1,"useMaxValue":false}]);
-}else{
-if(_7){
-this._bumpValue(e.keyCode==k.PAGE_UP?this.pageIncrement:1,true);
-}else{
-if(_8){
-this._bumpValue(e.keyCode==k.PAGE_UP?this.pageIncrement:1);
-}
-}
-}
-break;
-case ((this._descending||this.isLeftToRight())?k.LEFT_ARROW:k.RIGHT_ARROW):
-case (this._descending===false?k.UP_ARROW:k.DOWN_ARROW):
-case (this._descending===false?k.PAGE_UP:k.PAGE_DOWN):
-if(_7&&_8){
-this._bumpValue([{change:e.keyCode==k.PAGE_DOWN?-this.pageIncrement:-1,useMaxValue:false},{change:e.keyCode==k.PAGE_DOWN?-this.pageIncrement:-1,useMaxValue:true}]);
-}else{
-if(_7){
-this._bumpValue(e.keyCode==k.PAGE_DOWN?-this.pageIncrement:-1);
-}else{
-if(_8){
-this._bumpValue(e.keyCode==k.PAGE_DOWN?-this.pageIncrement:-1,true);
-}
-}
-}
-break;
-default:
-dijit.form._FormValueWidget.prototype._onKeyPress.apply(this,arguments);
-this.inherited(arguments);
-return;
-}
-dojo.stopEvent(e);
-},_onHandleClickMax:function(e){
-if(this.disabled||this.readOnly){
-return;
-}
-if(!dojo.isIE){
-dijit.focus(this.sliderHandleMax);
-}
-dojo.stopEvent(e);
-},_onClkIncBumper:function(){
-this._setValueAttr(this._descending===false?this.minimum:this.maximum,true,true);
-},_bumpValue:function(_9,_a){
-var _b=dojo.isArray(_9)?[this._getBumpValue(_9[0].change,_9[0].useMaxValue),this._getBumpValue(_9[1].change,_9[1].useMaxValue)]:this._getBumpValue(_9,_a);
-this._setValueAttr(_b,true,!dojo.isArray(_9)&&((_9>0&&!_a)||(_a&&_9<0)));
-},_getBumpValue:function(_c,_d){
-var s=dojo.getComputedStyle(this.sliderBarContainer),c=dojo._getContentBox(this.sliderBarContainer,s),_e=this.discreteValues,_f=!_d?this.value[0]:this.value[1];
-if(_e<=1||_e==Infinity){
-_e=c[this._pixelCount];
-}
-_e--;
-if((this._isReversed()&&_c<0)||(_c>0&&!this._isReversed())){
-_f=!_d?this.value[1]:this.value[0];
-}
-var _10=(_f-this.minimum)*_e/(this.maximum-this.minimum)+_c;
-if(_10<0){
-_10=0;
-}
-if(_10>_e){
-_10=_e;
-}
-return _10*(this.maximum-this.minimum)/_e+this.minimum;
-},_onBarClick:function(e){
-if(this.disabled||this.readOnly){
-return;
-}
-if(!dojo.isIE){
-dijit.focus(this.progressBar);
-}
-dojo.stopEvent(e);
-},_onRemainingBarClick:function(e){
-if(this.disabled||this.readOnly){
-return;
-}
-if(!dojo.isIE){
-dijit.focus(this.progressBar);
-}
-var _11=dojo.coords(this.sliderBarContainer,true),bar=dojo.coords(this.progressBar,true),_12=e[this._mousePixelCoord]-_11[this._startingPixelCoord],_13=bar[this._startingPixelCount],_14=_13+bar[this._pixelCount],_15=this._isReversed()?_12<=_13:_12>=_14,p=this._isReversed()?_11[this._pixelCount]-_12:_12;
-this._setPixelValue(p,_11[this._pixelCount],true,_15);
-dojo.stopEvent(e);
-},_setPixelValue:function(_16,_17,_18,_19){
-if(this.disabled||this.readOnly){
-return;
-}
-var _1a=this._getValueByPixelValue(_16,_17);
-this._setValueAttr(_1a,_18,_19);
-},_getValueByPixelValue:function(_1b,_1c){
-_1b=_1b<0?0:_1c<_1b?_1c:_1b;
-var _1d=this.discreteValues;
-if(_1d<=1||_1d==Infinity){
-_1d=_1c;
-}
-_1d--;
-var _1e=_1c/_1d;
-var _1f=Math.round(_1b/_1e);
-return (this.maximum-this.minimum)*_1f/_1d+this.minimum;
-},_setValueAttr:function(_20,_21,_22){
-var _23=this.value;
-if(!dojo.isArray(_20)){
-if(_22){
-if(this._isReversed()){
-_23[0]=_20;
-}else{
-_23[1]=_20;
-}
-}else{
-if(this._isReversed()){
-_23[1]=_20;
-}else{
-_23[0]=_20;
-}
-}
-}else{
-_23=_20;
-}
-this._lastValueReported="";
-this.valueNode.value=this.value=_20=_23;
-dijit.setWaiState(this.focusNode,"valuenow",_23[0]);
-dijit.setWaiState(this.focusNodeMax,"valuenow",_23[1]);
-this.value.sort(this._isReversed()?_1:_2);
-dijit.form._FormValueWidget.prototype._setValueAttr.apply(this,arguments);
-this._printSliderBar(_21,_22);
-},_printSliderBar:function(_24,_25){
-var _26=(this.value[0]-this.minimum)/(this.maximum-this.minimum);
-var _27=(this.value[1]-this.minimum)/(this.maximum-this.minimum);
-var _28=_26;
-if(_26>_27){
-_26=_27;
-_27=_28;
-}
-var _29=this._isReversed()?((1-_26)*100):(_26*100);
-var _2a=this._isReversed()?((1-_27)*100):(_27*100);
-var _2b=this._isReversed()?((1-_27)*100):(_26*100);
-if(_24&&this.slideDuration>0&&this.progressBar.style[this._progressPixelSize]){
-var _2c=_25?_27:_26;
-var _2d=this;
-var _2e={};
-var _2f=parseFloat(this.progressBar.style[this._handleOffsetCoord]);
-var _30=this.slideDuration/10;
-if(_30===0){
-return;
-}
-if(_30<0){
-_30=0-_30;
-}
-var _31={};
-var _32={};
-var _33={};
-_31[this._handleOffsetCoord]={start:this.sliderHandle.style[this._handleOffsetCoord],end:_29,units:"%"};
-_32[this._handleOffsetCoord]={start:this.sliderHandleMax.style[this._handleOffsetCoord],end:_2a,units:"%"};
-_33[this._handleOffsetCoord]={start:this.progressBar.style[this._handleOffsetCoord],end:_2b,units:"%"};
-_33[this._progressPixelSize]={start:this.progressBar.style[this._progressPixelSize],end:(_27-_26)*100,units:"%"};
-var _34=dojo.animateProperty({node:this.sliderHandle,duration:_30,properties:_31});
-var _35=dojo.animateProperty({node:this.sliderHandleMax,duration:_30,properties:_32});
-var _36=dojo.animateProperty({node:this.progressBar,duration:_30,properties:_33});
-var _37=dojo.fx.combine([_34,_35,_36]);
-_37.play();
-}else{
-this.sliderHandle.style[this._handleOffsetCoord]=_29+"%";
-this.sliderHandleMax.style[this._handleOffsetCoord]=_2a+"%";
-this.progressBar.style[this._handleOffsetCoord]=_2b+"%";
-this.progressBar.style[this._progressPixelSize]=((_27-_26)*100)+"%";
-}
-}});
-dojo.declare("dijit.form._SliderMoverMax",dijit.form._SliderMover,{onMouseMove:function(e){
-var _38=this.widget;
-var _39=_38._abspos;
-if(!_39){
-_39=_38._abspos=dojo.coords(_38.sliderBarContainer,true);
-_38._setPixelValue_=dojo.hitch(_38,"_setPixelValue");
-_38._isReversed_=_38._isReversed();
-}
-var _3a=e[_38._mousePixelCoord]-_39[_38._startingPixelCoord];
-_38._setPixelValue_(_38._isReversed_?(_39[_38._pixelCount]-_3a):_3a,_39[_38._pixelCount],false,true);
-},destroy:function(e){
-dojo.dnd.Mover.prototype.destroy.apply(this,arguments);
-var _3b=this.widget;
-_3b._abspos=null;
-_3b._setValueAttr(_3b.value,true);
-}});
-dojo.declare("dijit.form._SliderBarMover",dojo.dnd.Mover,{onMouseMove:function(e){
-var _3c=this.widget;
-if(_3c.disabled||_3c.readOnly){
-return;
-}
-var _3d=_3c._abspos;
-var bar=_3c._bar;
-var _3e=_3c._mouseOffset;
-if(!_3d){
-_3d=_3c._abspos=dojo.coords(_3c.sliderBarContainer,true);
-_3c._setPixelValue_=dojo.hitch(_3c,"_setPixelValue");
-_3c._getValueByPixelValue_=dojo.hitch(_3c,"_getValueByPixelValue");
-_3c._isReversed_=_3c._isReversed();
-}
-if(!bar){
-bar=_3c._bar=dojo.coords(_3c.progressBar,true);
-}
-if(!_3e){
-_3e=_3c._mouseOffset=e[_3c._mousePixelCoord]-_3d[_3c._startingPixelCoord]-bar[_3c._startingPixelCount];
-}
-var _3f=e[_3c._mousePixelCoord]-_3d[_3c._startingPixelCoord]-_3e,_40=_3f+bar[_3c._pixelCount];
-pixelValues=[_3f,_40];
-pixelValues.sort(_2);
-if(pixelValues[0]<=0){
-pixelValues[0]=0;
-pixelValues[1]=bar[_3c._pixelCount];
-}
-if(pixelValues[1]>=_3d[_3c._pixelCount]){
-pixelValues[1]=_3d[_3c._pixelCount];
-pixelValues[0]=_3d[_3c._pixelCount]-bar[_3c._pixelCount];
-}
-var _41=[_3c._getValueByPixelValue(_3c._isReversed_?(_3d[_3c._pixelCount]-pixelValues[0]):pixelValues[0],_3d[_3c._pixelCount]),_3c._getValueByPixelValue(_3c._isReversed_?(_3d[_3c._pixelCount]-pixelValues[1]):pixelValues[1],_3d[_3c._pixelCount])];
-_3c._setValueAttr(_41,false,false);
-},destroy:function(){
-dojo.dnd.Mover.prototype.destroy.apply(this,arguments);
-var _42=this.widget;
-_42._abspos=null;
-_42._bar=null;
-_42._mouseOffset=null;
-_42._setValueAttr(_42.value,true);
-}});
-dojo.declare("dojox.form.HorizontalRangeSlider",[dijit.form.HorizontalSlider,dojox.form._RangeSliderMixin],{templateString:dojo.cache("dojox.form","resources/HorizontalRangeSlider.html","<table class=\"dijit dijitReset dijitSlider dojoxRangeSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\"\n    ><tr class=\"dijitReset\"\n        ><td class=\"dijitReset\" colspan=\"2\"></td\n        ><td dojoAttachPoint=\"containerNode,topDecoration\" class=\"dijitReset\" style=\"te [...]
-dojo.declare("dojox.form.VerticalRangeSlider",[dijit.form.VerticalSlider,dojox.form._RangeSliderMixin],{templateString:dojo.cache("dojox.form","resources/VerticalRangeSlider.html","<table class=\"dijitReset dijitSlider dojoxRangeSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\"\n><tbody class=\"dijitReset\"\n    ><tr class=\"dijitReset\"\n        ><td class=\"dijitReset\"></td\n        ><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV\" [...]
+
+	// make these functions once:
+	var sortReversed = function(a, b){ return b - a; },
+		sortForward = function(a, b){ return a - b; }
+	;
+
+	dojo.declare("dojox.form._RangeSliderMixin", null, {
+
+		value: [0,100],
+		postMixInProperties: function(){
+			this.inherited(arguments);
+			this.value = dojo.map(this.value, function(i){ return parseInt(i, 10); });
+		},
+	
+		postCreate: function(){
+			this.inherited(arguments);
+			// we sort the values!
+			// TODO: re-think, how to set the value
+			this.value.sort(this._isReversed() ? sortReversed : sortForward);
+
+			// define a custom constructor for a SliderMoverMax that points back to me
+			var _self = this;
+			var mover = function(){
+				dijit.form._SliderMoverMax.apply(this, arguments);
+				this.widget = _self;
+			};
+			dojo.extend(mover, dijit.form._SliderMoverMax.prototype);
+
+			this._movableMax = new dojo.dnd.Moveable(this.sliderHandleMax,{ mover: mover });
+			dijit.setWaiState(this.focusNodeMax, "valuemin", this.minimum);
+			dijit.setWaiState(this.focusNodeMax, "valuemax", this.maximum);
+		
+			// a dnd for the bar!
+			var barMover = function(){
+				dijit.form._SliderBarMover.apply(this, arguments);
+				this.widget = _self;
+			};
+			dojo.extend(barMover, dijit.form._SliderBarMover.prototype);
+			this._movableBar = new dojo.dnd.Moveable(this.progressBar,{ mover: barMover });
+		},
+	
+		destroy: function(){
+			this.inherited(arguments);
+			this._movableMax.destroy();
+			this._movableBar.destroy(); 
+		},
+	
+		_onKeyPress: function(/*Event*/ e){
+			if(this.disabled || this.readOnly || e.altKey || e.ctrlKey){ return; }
+		
+			var focusedEl = e.currentTarget,
+				minSelected = false,
+				maxSelected = false,
+				k = dojo.keys
+			;
+		
+			if(focusedEl == this.sliderHandle){
+				minSelected = true;
+			}else if(focusedEl == this.progressBar){
+				maxSelected = minSelected = true;
+			}else if(focusedEl == this.sliderHandleMax){
+				maxSelected = true;
+			}
+			
+			switch(e.keyCode){
+				case k.HOME:
+					this._setValueAttr(this.minimum, true, maxSelected);
+					break;
+				case k.END:
+					this._setValueAttr(this.maximum, true, maxSelected);
+					break;
+				// this._descending === false: if ascending vertical (min on top)
+				// (this._descending || this.isLeftToRight()): if left-to-right horizontal or descending vertical
+				case ((this._descending || this.isLeftToRight()) ? k.RIGHT_ARROW : k.LEFT_ARROW):
+				case (this._descending === false ? k.DOWN_ARROW : k.UP_ARROW):
+				case (this._descending === false ? k.PAGE_DOWN : k.PAGE_UP):
+					if(minSelected && maxSelected){
+						this._bumpValue([
+							{'change': e.keyCode == k.PAGE_UP ? this.pageIncrement : 1, 'useMaxValue': true},
+							{'change': e.keyCode == k.PAGE_UP ? this.pageIncrement : 1, 'useMaxValue': false}
+						]);
+					}else if(minSelected){
+						this._bumpValue(e.keyCode == k.PAGE_UP ? this.pageIncrement : 1, true);
+					}else if(maxSelected){
+						this._bumpValue(e.keyCode == k.PAGE_UP ? this.pageIncrement : 1);
+					}
+					break;
+				case ((this._descending || this.isLeftToRight()) ? k.LEFT_ARROW : k.RIGHT_ARROW) :
+				case (this._descending === false ? k.UP_ARROW : k.DOWN_ARROW):
+				case (this._descending === false ? k.PAGE_UP : k.PAGE_DOWN):
+					if (minSelected && maxSelected){
+						this._bumpValue([
+							{ change: e.keyCode == k.PAGE_DOWN ? -this.pageIncrement : -1, useMaxValue: false },
+							{ change: e.keyCode == k.PAGE_DOWN ? -this.pageIncrement : -1, useMaxValue: true }
+						]);
+					}else if(minSelected){
+						this._bumpValue(e.keyCode == k.PAGE_DOWN ? -this.pageIncrement : -1);
+					}else if(maxSelected){
+						this._bumpValue(e.keyCode == k.PAGE_DOWN ? -this.pageIncrement : -1, true);
+					}
+					break;
+				default:
+					dijit.form._FormValueWidget.prototype._onKeyPress.apply(this, arguments);
+					this.inherited(arguments);
+					return;
+			}
+			dojo.stopEvent(e);
+		},
+	
+		_onHandleClickMax: function(e){
+			if(this.disabled || this.readOnly){ return; }
+			if(!dojo.isIE){
+				// make sure you get focus when dragging the handle
+				// (but don't do on IE because it causes a flicker on mouse up (due to blur then focus)
+				dijit.focus(this.sliderHandleMax);
+			}
+			dojo.stopEvent(e);
+		},
+	
+		_onClkIncBumper: function(){
+			this._setValueAttr(this._descending === false ? this.minimum : this.maximum, true, true);
+		},
+	
+		_bumpValue: function(signedChange, useMaxValue){
+
+			// we pass an array to _setValueAttr when signedChange is an array
+			var value = dojo.isArray(signedChange) ? [
+					this._getBumpValue(signedChange[0].change, signedChange[0].useMaxValue),
+					this._getBumpValue(signedChange[1].change, signedChange[1].useMaxValue)
+				] 
+				: this._getBumpValue(signedChange, useMaxValue)
+
+			this._setValueAttr(value, true, 
+				// conditional passed the valueAttr
+				!dojo.isArray(signedChange) && 
+				((signedChange > 0 && !useMaxValue) || (useMaxValue && signedChange < 0))
+			);
+		},
+	
+		_getBumpValue: function(signedChange, useMaxValue){
+			var s = dojo.getComputedStyle(this.sliderBarContainer),
+				c = dojo._getContentBox(this.sliderBarContainer, s),
+				count = this.discreteValues,
+				myValue = !useMaxValue ? this.value[0] : this.value[1]
+			;
+
+			if(count <= 1 || count == Infinity){ count = c[this._pixelCount]; }
+			count--;
+
+			if((this._isReversed() && signedChange < 0) || (signedChange > 0 && !this._isReversed())){
+				myValue = !useMaxValue ? this.value[1] : this.value[0];
+			}
+			
+			var value = (myValue - this.minimum) * count / (this.maximum - this.minimum) + signedChange;
+			if(value < 0){ value = 0; }
+			if(value > count){ value = count; }
+			
+			return value * (this.maximum - this.minimum) / count + this.minimum;
+		},
+	
+		_onBarClick: function(e){
+			if(this.disabled || this.readOnly){ return; }
+			if(!dojo.isIE){
+				// make sure you get focus when dragging the handle
+				// (but don't do on IE because it causes a flicker on mouse up (due to blur then focus)
+				dijit.focus(this.progressBar);
+			}
+			dojo.stopEvent(e);	
+		},
+	
+		_onRemainingBarClick: function(e){
+			if(this.disabled || this.readOnly){ return; }
+			if(!dojo.isIE){
+				// make sure you get focus when dragging the handle
+				// (but don't do on IE because it causes a flicker on mouse up (due to blur then focus)
+				dijit.focus(this.progressBar);
+			}
+
+			// now we set the min/max-value of the slider!
+			var abspos = dojo.coords(this.sliderBarContainer, true),
+				bar = dojo.coords(this.progressBar, true),
+				relMousePos = e[this._mousePixelCoord] - abspos[this._startingPixelCoord],
+				leftPos = bar[this._startingPixelCount],
+				rightPos = leftPos + bar[this._pixelCount],
+				isMaxVal = this._isReversed() ? relMousePos <= leftPos : relMousePos >= rightPos,
+				p = this._isReversed() ? abspos[this._pixelCount] - relMousePos : relMousePos
+			;
+
+			this._setPixelValue(p, abspos[this._pixelCount], true, isMaxVal);
+			dojo.stopEvent(e);
+		},
+	
+		_setPixelValue: function(/*Number*/ pixelValue, /*Number*/ maxPixels, /*Boolean*/ priorityChange, /*Boolean*/ isMaxVal){
+			if(this.disabled || this.readOnly){ return; }
+			var myValue = this._getValueByPixelValue(pixelValue, maxPixels);
+			this._setValueAttr(myValue, priorityChange, isMaxVal);
+		},
+	
+		_getValueByPixelValue: function(/*Number*/ pixelValue, /*Number*/ maxPixels){
+			pixelValue = pixelValue < 0 ? 0 : maxPixels < pixelValue ? maxPixels : pixelValue;
+			var count = this.discreteValues;
+			if(count <= 1 || count == Infinity){ count = maxPixels; }
+			count--;
+			var pixelsPerValue = maxPixels / count;
+			var wholeIncrements = Math.round(pixelValue / pixelsPerValue);
+			return (this.maximum-this.minimum)*wholeIncrements/count + this.minimum;
+		},
+	
+		_setValueAttr: function(/*Array or Number*/ value, /*Boolean, optional*/ priorityChange, /*Boolean, optional*/ isMaxVal){
+			// we pass an array, when we move the slider with the bar
+			var actValue = this.value;
+			if(!dojo.isArray(value)){
+				if(isMaxVal){
+					if(this._isReversed()){
+						actValue[0] = value;
+					}else{
+						actValue[1] = value;
+					}
+				}else{
+					if(this._isReversed()){
+						actValue[1] = value;
+					}else{
+						actValue[0] = value;
+					}
+				}
+			}else{
+				actValue = value;
+			}
+			// we have to reset this values. don't know the reason for that
+			this._lastValueReported = "";
+			this.valueNode.value = this.value = value = actValue;
+			dijit.setWaiState(this.focusNode, "valuenow", actValue[0]);
+			dijit.setWaiState(this.focusNodeMax, "valuenow", actValue[1]);
+		
+			this.value.sort(this._isReversed() ? sortReversed : sortForward);
+			
+			// not calling the _setValueAttr-function of dijit.form.Slider, but the super-super-class (needed for the onchange-event!)
+			dijit.form._FormValueWidget.prototype._setValueAttr.apply(this, arguments);
+			this._printSliderBar(priorityChange, isMaxVal);
+		},
+	
+		_printSliderBar: function(priorityChange, isMaxVal){
+			var percentMin = (this.value[0] - this.minimum) / (this.maximum - this.minimum);
+			var percentMax = (this.value[1] - this.minimum) / (this.maximum - this.minimum);
+			var percentMinSave = percentMin;
+			if(percentMin > percentMax){
+				percentMin = percentMax;
+				percentMax = percentMinSave;
+			}
+			var sliderHandleVal = this._isReversed() ? ((1-percentMin)*100) : (percentMin * 100);
+			var sliderHandleMaxVal = this._isReversed() ? ((1-percentMax)*100) : (percentMax * 100);
+			var progressBarVal = this._isReversed() ? ((1-percentMax)*100) : (percentMin * 100);
+			if (priorityChange && this.slideDuration > 0 && this.progressBar.style[this._progressPixelSize]){
+				// animate the slider
+				var percent = isMaxVal ? percentMax : percentMin;
+				var _this = this;
+				var props = {};
+				var start = parseFloat(this.progressBar.style[this._handleOffsetCoord]);
+				var duration = this.slideDuration / 10; // * (percent-start/100);
+				if(duration === 0){ return; }
+				if(duration < 0){ duration = 0 - duration; }
+				var propsHandle = {};
+				var propsHandleMax = {};
+				var propsBar = {};
+				// hui, a lot of animations :-)
+				propsHandle[this._handleOffsetCoord] = { start: this.sliderHandle.style[this._handleOffsetCoord], end: sliderHandleVal, units:"%"};
+				propsHandleMax[this._handleOffsetCoord] = { start: this.sliderHandleMax.style[this._handleOffsetCoord], end: sliderHandleMaxVal, units:"%"};
+				propsBar[this._handleOffsetCoord] = { start: this.progressBar.style[this._handleOffsetCoord], end: progressBarVal, units:"%"};
+				propsBar[this._progressPixelSize] = { start: this.progressBar.style[this._progressPixelSize], end: (percentMax - percentMin) * 100, units:"%"};
+				var animHandle = dojo.animateProperty({node: this.sliderHandle,duration: duration, properties: propsHandle}); 
+				var animHandleMax = dojo.animateProperty({node: this.sliderHandleMax,duration: duration, properties: propsHandleMax}); 
+				var animBar = dojo.animateProperty({node: this.progressBar,duration: duration, properties: propsBar});
+				var animCombine = dojo.fx.combine([animHandle, animHandleMax, animBar]);
+				animCombine.play();
+			}else{
+				this.sliderHandle.style[this._handleOffsetCoord] = sliderHandleVal + "%";
+				this.sliderHandleMax.style[this._handleOffsetCoord] = sliderHandleMaxVal + "%";
+				this.progressBar.style[this._handleOffsetCoord] = progressBarVal + "%";
+				this.progressBar.style[this._progressPixelSize] = ((percentMax - percentMin) * 100) + "%";
+			}
+		}
+	});
+
+	dojo.declare("dijit.form._SliderMoverMax", dijit.form._SliderMover, {	
+
+		onMouseMove: function(e){
+			var widget = this.widget;
+			var abspos = widget._abspos;
+			if(!abspos){
+				abspos = widget._abspos = dojo.coords(widget.sliderBarContainer, true);
+				widget._setPixelValue_ = dojo.hitch(widget, "_setPixelValue");
+				widget._isReversed_ = widget._isReversed();
+			}
+			var pixelValue = e[widget._mousePixelCoord] - abspos[widget._startingPixelCoord];
+			widget._setPixelValue_(widget._isReversed_ ? (abspos[widget._pixelCount]-pixelValue) : pixelValue, abspos[widget._pixelCount], false, true);
+		},
+	
+		destroy: function(e){
+			dojo.dnd.Mover.prototype.destroy.apply(this, arguments);
+			var widget = this.widget;
+			widget._abspos = null;
+			widget._setValueAttr(widget.value, true);
+		}
+	});
+
+	dojo.declare("dijit.form._SliderBarMover", dojo.dnd.Mover, {
+
+		onMouseMove: function(e){
+			var widget = this.widget;
+			if(widget.disabled || widget.readOnly){ return; }
+			var abspos = widget._abspos;
+			var bar = widget._bar;
+			var mouseOffset = widget._mouseOffset;
+			if(!abspos){
+				abspos = widget._abspos = dojo.coords(widget.sliderBarContainer, true);
+				widget._setPixelValue_ = dojo.hitch(widget, "_setPixelValue");
+				widget._getValueByPixelValue_ = dojo.hitch(widget, "_getValueByPixelValue");
+				widget._isReversed_ = widget._isReversed();
+			}
+			
+			if(!bar){
+				bar = widget._bar = dojo.coords(widget.progressBar, true);
+			}
+			
+			if(!mouseOffset){
+				mouseOffset = widget._mouseOffset = e[widget._mousePixelCoord] - abspos[widget._startingPixelCoord] - bar[widget._startingPixelCount];
+			}
+			
+			var pixelValueMin = e[widget._mousePixelCoord] - abspos[widget._startingPixelCoord] - mouseOffset,
+				pixelValueMax = pixelValueMin + bar[widget._pixelCount];
+				// we don't narrow the slider when it reaches the bumper!
+				// maybe there is a simpler way
+				pixelValues = [pixelValueMin, pixelValueMax]
+			;
+
+			pixelValues.sort(sortForward);
+
+			if(pixelValues[0] <= 0){
+				pixelValues[0] = 0;
+				pixelValues[1] = bar[widget._pixelCount];
+			}
+			if(pixelValues[1] >= abspos[widget._pixelCount]){
+				pixelValues[1] = abspos[widget._pixelCount];
+				pixelValues[0] = abspos[widget._pixelCount] - bar[widget._pixelCount];
+			}
+			// getting the real values by pixel
+			var myValues = [
+				widget._getValueByPixelValue(widget._isReversed_ ? (abspos[widget._pixelCount] - pixelValues[0]) : pixelValues[0], abspos[widget._pixelCount]), 
+				widget._getValueByPixelValue(widget._isReversed_ ? (abspos[widget._pixelCount] - pixelValues[1]) : pixelValues[1], abspos[widget._pixelCount])
+			];
+			// and setting the value of the widget
+			widget._setValueAttr(myValues, false, false);
+		},
+	
+		destroy: function(){
+			dojo.dnd.Mover.prototype.destroy.apply(this, arguments);
+			var widget = this.widget;
+			widget._abspos = null;
+			widget._bar = null;
+			widget._mouseOffset = null;
+			widget._setValueAttr(widget.value, true);
+		}
+	});
+
+	dojo.declare("dojox.form.HorizontalRangeSlider",
+		[dijit.form.HorizontalSlider, dojox.form._RangeSliderMixin],
+		{
+			// summary:
+			// 	A form widget that allows one to select a range with two horizontally draggable images
+			templateString: dojo.cache('dojox.form','resources/HorizontalRangeSlider.html')
+		}
+	);
+
+	dojo.declare("dojox.form.VerticalRangeSlider",
+		[dijit.form.VerticalSlider, dojox.form._RangeSliderMixin],
+		{
+			// summary:
+			// 	A form widget that allows one to select a range with two vertically draggable images
+			templateString: dojo.cache('dojox.form','resources/VerticalRangeSlider.html')
+		}
+	);
+
 })();
-}
diff --git a/dojox/form/Rating.js b/dojox/form/Rating.js
index a910f96..01ab1e8 100644
--- a/dojox/form/Rating.js
+++ b/dojox/form/Rating.js
@@ -1,56 +1,95 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.Rating"]){
-dojo._hasResource["dojox.form.Rating"]=true;
 dojo.provide("dojox.form.Rating");
+
 dojo.require("dijit.form._FormWidget");
-dojo.declare("dojox.form.Rating",dijit.form._FormWidget,{templateString:null,numStars:3,value:0,constructor:function(_1){
-dojo.mixin(this,_1);
-var _2="<div dojoAttachPoint=\"domNode\" class=\"dojoxRating dijitInline\">"+"<input type=\"hidden\" value=\"0\" dojoAttachPoint=\"focusNode\" /><ul>${stars}</ul>"+"</div>";
-var _3="<li class=\"dojoxRatingStar dijitInline\" dojoAttachEvent=\"onclick:onStarClick,onmouseover:_onMouse,onmouseout:_onMouse\" value=\"${value}\"></li>";
-var _4="";
-for(var i=0;i<this.numStars;i++){
-_4+=dojo.string.substitute(_3,{value:i+1});
-}
-this.templateString=dojo.string.substitute(_2,{stars:_4});
-},postCreate:function(){
-this.inherited(arguments);
-this._renderStars(this.value);
-},_onMouse:function(_5){
-this.inherited(arguments);
-if(this._hovering){
-var _6=+dojo.attr(_5.target,"value");
-this.onMouseOver(_5,_6);
-this._renderStars(_6,true);
-}else{
-this._renderStars(this.value);
-}
-},_renderStars:function(_7,_8){
-dojo.query(".dojoxRatingStar",this.domNode).forEach(function(_9,i){
-if(i+1>_7){
-dojo.removeClass(_9,"dojoxRatingStarHover");
-dojo.removeClass(_9,"dojoxRatingStarChecked");
-}else{
-dojo.removeClass(_9,"dojoxRatingStar"+(_8?"Checked":"Hover"));
-dojo.addClass(_9,"dojoxRatingStar"+(_8?"Hover":"Checked"));
-}
+
+dojo.declare("dojox.form.Rating",
+	dijit.form._FormWidget,{
+	// summary:
+	//		A widget for rating using stars.
+	//
+	// required: Boolean
+	//		TODO: Can be true or false, default is false.
+	// required: false,
+
+	templateString: null,
+	
+	// numStars: Integer/Float
+	//		The number of stars to show, default is 3.
+	numStars: 3,
+	// value: Integer/Float
+	//		The current value of the Rating
+	value: 0,
+
+	constructor:function(/*Object*/params){
+		// Build the templateString. The number of stars is given by this.numStars,
+		// which is normally an attribute to the widget node.
+		dojo.mixin(this, params);
+		
+		// TODO actually "dijitInline" should be applied to the surrounding div, but FF2
+		// screws up when we dojo.query() for the star nodes, it orders them randomly, because of the use
+		// of display:--moz-inline-box ... very strange bug
+		// Since using ul and li in combintaion with dijitInline this problem doesnt exist anymore.
+		
+		// The focusNode is normally used to store the value, i dont know if that is right here, but seems standard for _FormWidgets
+		var tpl = '<div dojoAttachPoint="domNode" class="dojoxRating dijitInline">' +
+					'<input type="hidden" value="0" dojoAttachPoint="focusNode" /><ul>${stars}</ul>' +
+				'</div>';
+		// The value-attribute is used to "read" the value for processing in the widget class
+		var starTpl = '<li class="dojoxRatingStar dijitInline" dojoAttachEvent="onclick:onStarClick,onmouseover:_onMouse,onmouseout:_onMouse" value="${value}"></li>';
+		var rendered = "";
+		for(var i = 0; i < this.numStars; i++){
+			rendered += dojo.string.substitute(starTpl, {value:i+1});
+		}
+		this.templateString = dojo.string.substitute(tpl, {stars:rendered});
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+		this._renderStars(this.value);
+	},
+
+	_onMouse: function(evt){
+		if(this._hovering){
+			var hoverValue = +dojo.attr(evt.target, "value");
+			this.onMouseOver(evt, hoverValue);
+			this._renderStars(hoverValue, true);
+		}else{
+			this._renderStars(this.value);
+		}
+	},
+
+	_renderStars: function(value, hover){
+		// summary: Render the stars depending on the value.
+		dojo.query(".dojoxRatingStar", this.domNode).forEach(function(star, i){
+			if(i + 1 > value){
+				dojo.removeClass(star, "dojoxRatingStarHover");
+				dojo.removeClass(star, "dojoxRatingStarChecked");
+			}else{
+				dojo.removeClass(star, "dojoxRatingStar" + (hover ? "Checked" : "Hover"));
+				dojo.addClass(star, "dojoxRatingStar" + (hover ? "Hover" : "Checked"));
+			}
+		});
+	},
+
+	onStarClick:function(/* Event */evt){
+		// summary: Connect on this method to get noticed when a star was clicked.
+		// example: dojo.connect(widget, "onStarClick", function(event){ ... })
+		var newVal = +dojo.attr(evt.target, "value");
+		this.setAttribute("value", newVal == this.value ? 0 : newVal);
+		this._renderStars(this.value);
+		this.onChange(this.value); // Do I have to call this by hand?
+	},
+	
+	onMouseOver: function(/*evt, value*/){
+		// summary: Connect here, the value is passed to this function as the second parameter!
+	},
+	
+	setAttribute: function(/*String*/key, /**/value){
+		// summary: When calling setAttribute("value", 4), set the value and render the stars accordingly.
+		this.inherited("setAttribute", arguments);
+		if (key=="value"){
+			this._renderStars(this.value);
+			this.onChange(this.value); // Do I really have to call this by hand? :-(
+		}
+	}
 });
-},onStarClick:function(_a){
-var _b=+dojo.attr(_a.target,"value");
-this.setAttribute("value",_b==this.value?0:_b);
-this._renderStars(this.value);
-this.onChange(this.value);
-},onMouseOver:function(){
-},setAttribute:function(_c,_d){
-this.inherited("setAttribute",arguments);
-if(_c=="value"){
-this._renderStars(this.value);
-this.onChange(this.value);
-}
-}});
-}
diff --git a/dojox/form/TimeSpinner.js b/dojox/form/TimeSpinner.js
index da296ad..829e975 100644
--- a/dojox/form/TimeSpinner.js
+++ b/dojox/form/TimeSpinner.js
@@ -1,36 +1,56 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.TimeSpinner"]){
-dojo._hasResource["dojox.form.TimeSpinner"]=true;
 dojo.provide("dojox.form.TimeSpinner");
+
 dojo.require("dijit.form._Spinner");
-dojo.require("dijit.form.NumberTextBox");
 dojo.require("dojo.date");
 dojo.require("dojo.date.locale");
 dojo.require("dojo.date.stamp");
-dojo.declare("dojox.form.TimeSpinner",[dijit.form._Spinner],{required:false,adjust:function(_1,_2){
-return dojo.date.add(_1,"minute",_2);
-},isValid:function(){
-return true;
-},smallDelta:5,largeDelta:30,timeoutChangeRate:0.5,parse:function(_3,_4){
-return dojo.date.locale.parse(_3,{selector:"time",formatLength:"short"});
-},format:function(_5,_6){
-if(dojo.isString(_5)){
-return _5;
-}
-return dojo.date.locale.format(_5,{selector:"time",formatLength:"short"});
-},serialize:dojo.date.stamp.toISOString,value:"12:00 AM",_onKeyPress:function(e){
-if((e.charOrCode==dojo.keys.HOME||e.charOrCode==dojo.keys.END)&&!(e.ctrlKey||e.altKey||e.metaKey)&&typeof this.attr("value")!="undefined"){
-var _7=this.constraints[(e.charOrCode==dojo.keys.HOME?"min":"max")];
-if(_7){
-this._setValueAttr(_7,true);
-}
-dojo.stopEvent(e);
-}
-}});
-}
+
+dojo.declare(
+"dojox.form.TimeSpinner",
+[dijit.form._Spinner],
+{
+	// summary: Time Spinner
+	// description: This widget is the same as a normal NumberSpinner, but for the time component of a date object instead
+
+	required: false,
+
+	adjust: function(/* Object */ val, /*Number*/ delta){
+		return dojo.date.add(val, "minute", delta)
+	},
+
+	//FIXME should we allow for constraints in this widget?
+	isValid: function(){return true;},
+
+	smallDelta: 5,
+
+	largeDelta: 30,
+
+	timeoutChangeRate: 0.50,	
+
+	parse: function(time, locale){
+		return dojo.date.locale.parse(time, {selector:"time", formatLength:"short"});
+	},
+
+	format: function(time, locale){
+		if (dojo.isString(time)) { return time; }
+		return dojo.date.locale.format(time, {selector:"time", formatLength:"short"});
+	},
+
+	serialize: dojo.date.stamp.toISOString,
+
+	value: "12:00 AM",
+
+       _onKeyPress: function(e){
+                if((e.charOrCode == dojo.keys.HOME || e.charOrCode == dojo.keys.END) && !(e.ctrlKey || e.altKey || e.metaKey)
+                && typeof this.get('value') != 'undefined' /* gibberish, so HOME and END are default editing keys*/){
+                        var value = this.constraints[(e.charOrCode == dojo.keys.HOME ? "min" : "max")];
+                        if(value){
+                                this._setValueAttr(value,true);
+                        }
+                        // eat home or end key whether we change the value or not
+                        dojo.stopEvent(e);
+                }
+        }
+
+
+});
diff --git a/dojox/form/_FormSelectWidget.js b/dojox/form/_FormSelectWidget.js
index 3963dc3..5620fd9 100644
--- a/dojox/form/_FormSelectWidget.js
+++ b/dojox/form/_FormSelectWidget.js
@@ -1,14 +1,6 @@
-/*
-	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
-*/
+dojo.deprecated("dojox.form._FormSelectWidget", "Use dijit.form._FormSelectWidget instead", "2.0");
 
-
-if(!dojo._hasResource["dojox.form._FormSelectWidget"]){
-dojo._hasResource["dojox.form._FormSelectWidget"]=true;
-dojo.deprecated("dojox.form._FormSelectWidget","Use dijit.form._FormSelectWidget instead","2.0");
 dojo.provide("dojox.form._FormSelectWidget");
 dojo.require("dijit.form._FormSelectWidget");
-dojo.setObject("dojox.form._FormSelectWidget",dijit.form._FormSelectWidget);
-}
+
+dojo.setObject("dojox.form._FormSelectWidget", dijit.form._FormSelectWidget);
\ No newline at end of file
diff --git a/dojox/form/_HasDropDown.js b/dojox/form/_HasDropDown.js
index ba38e00..4c9d7e6 100644
--- a/dojox/form/_HasDropDown.js
+++ b/dojox/form/_HasDropDown.js
@@ -1,14 +1,6 @@
-/*
-	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
-*/
+dojo.deprecated("dojox.form._HasDropDown", "Use dijit._HasDropDown instead", "2.0");
 
-
-if(!dojo._hasResource["dojox.form._HasDropDown"]){
-dojo._hasResource["dojox.form._HasDropDown"]=true;
-dojo.deprecated("dojox.form._HasDropDown","Use dijit._HasDropDown instead","2.0");
 dojo.provide("dojox.form._HasDropDown");
 dojo.require("dijit._HasDropDown");
-dojo.setObject("dojox.form._HasDropDown",dijit._HasDropDown);
-}
+
+dojo.setObject("dojox.form._HasDropDown", dijit._HasDropDown);
\ No newline at end of file
diff --git a/dojox/form/_SelectStackMixin.js b/dojox/form/_SelectStackMixin.js
index 3a35d1b..04f5191 100644
--- a/dojox/form/_SelectStackMixin.js
+++ b/dojox/form/_SelectStackMixin.js
@@ -1,151 +1,214 @@
-/*
-	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
-*/
+dojo.provide("dojox.form._SelectStackMixin");
 
+dojo.declare("dojox.form._SelectStackMixin", null, {
+	// summary:
+	//		Mix this class in to a dijit.form._FormSelectWidget in order to 
+	//		provide support for "selectable" multiforms.  The widget is pointed
+	//		to a dijit.layout.StackContainer and will handle displaying and 
+	//		submitting the values of only the appropriate pane.
+	//
+	//		The options for this widget will be automatically set - based on 
+	//		the panes that are in the stack container.  The "title" attribute of
+	//		the pane will be used for the display of the option.  The "id" attribute
+	//		of the pane will be used as the value of the option.  In order to 
+	//		avoid running into unique ID constraint issues, a stackPrefix mechanism
+	//		is provided.
 
-if(!dojo._hasResource["dojox.form._SelectStackMixin"]){
-dojo._hasResource["dojox.form._SelectStackMixin"]=true;
-dojo.provide("dojox.form._SelectStackMixin");
-dojo.declare("dojox.form._SelectStackMixin",null,{stackId:"",stackPrefix:"",_paneIdFromOption:function(_1){
-return (this.stackPrefix||"")+_1;
-},_optionValFromPane:function(id){
-var sp=this.stackPrefix;
-if(sp&&id.indexOf(sp)===0){
-return id.substring(sp.length);
-}
-return id;
-},_togglePane:function(_2,_3){
-if(_2._shown!=undefined&&_2._shown==_3){
-return;
-}
-var _4=dojo.filter(_2.getDescendants(),"return item.name;");
-if(!_3){
-_5={};
-dojo.forEach(_4,function(w){
-_5[w.id]=w.disabled;
-w.attr("disabled",true);
-});
-_2._savedStates=_5;
-}else{
-var _5=_2._savedStates||{};
-dojo.forEach(_4,function(w){
-var _6=_5[w.id];
-if(_6==undefined){
-_6=false;
-}
-w.attr("disabled",_6);
-});
-delete _2._savedStates;
-}
-_2._shown=_3;
-},_connectTitle:function(_7,_8){
-var fx=dojo.hitch(this,function(_9){
-this.updateOption({value:_8,label:_9});
-});
-if(_7._setTitleAttr){
-this.connect(_7,"_setTitleAttr",fx);
-}else{
-this.connect(_7,"attr",function(_a,_b){
-if(_a=="title"&&arguments.length>1){
-fx(_b);
-}
-});
-}
-},onAddChild:function(_c,_d){
-if(!this._panes[_c.id]){
-this._panes[_c.id]=_c;
-var v=this._optionValFromPane(_c.id);
-this.addOption({value:v,label:_c.title});
-this._connectTitle(_c,v);
-}
-if(!_c.onShow||!_c.onHide||_c._shown==undefined){
-_c.onShow=dojo.hitch(this,"_togglePane",_c,true);
-_c.onHide=dojo.hitch(this,"_togglePane",_c,false);
-_c.onHide();
-}
-},_setValueAttr:function(v){
-if("_savedValue" in this){
-return;
-}
-this.inherited(arguments);
-},attr:function(_e,_f){
-if(_e=="value"&&arguments.length==2&&"_savedValue" in this){
-this._savedValue=_f;
-}
-return this.inherited(arguments);
-},onRemoveChild:function(_10){
-if(this._panes[_10.id]){
-delete this._panes[_10.id];
-this.removeOption(this._optionValFromPane(_10.id));
-}
-},onSelectChild:function(_11){
-this._setValueAttr(this._optionValFromPane(_11.id));
-},onStartup:function(_12){
-var _13=_12.selected;
-this.addOption(dojo.filter(dojo.map(_12.children,function(c){
-var v=this._optionValFromPane(c.id);
-this._connectTitle(c,v);
-var _14=null;
-if(!this._panes[c.id]){
-this._panes[c.id]=c;
-_14={value:v,label:c.title};
-}
-if(!c.onShow||!c.onHide||c._shown==undefined){
-c.onShow=dojo.hitch(this,"_togglePane",c,true);
-c.onHide=dojo.hitch(this,"_togglePane",c,false);
-c.onHide();
-}
-if("_savedValue" in this&&v===this._savedValue){
-_13=c;
-}
-return _14;
-},this),function(i){
-return i;
-}));
-var _15=this;
-var fx=function(){
-delete _15._savedValue;
-_15.onSelectChild(_13);
-if(!_13._shown){
-_15._togglePane(_13,true);
-}
-};
-if(_13!==_12.selected){
-var _16=dijit.byId(this.stackId);
-var c=this.connect(_16,"_showChild",function(sel){
-this.disconnect(c);
-fx();
+	// stackId: string
+	//		The id of the stack that this widget is supposed to control
+	stackId: "",
+	
+	// stackPrefix: string
+	//		A prefix to remove from our stack pane ids when setting our options.
+	//		This exists so that we won't run into unique ID constraints.  For 
+	//		example, if stackPrefix is set to "foo_", and there are three panes
+	//		in our stack with ids of "foo_a", "foo_b", and "foo_c", then the values
+	//		of the options created for the stack controller widget will be "a",
+	//		"b", and "c".  This allows you to have multiple select stack widgets
+	//		with the same values - without having to have the panes require the
+	//		same ids.
+	stackPrefix: "",
+	
+	_paneIdFromOption: function(/*String*/ oVal){
+		// summary: Gets the pane ID given an option value
+		return (this.stackPrefix || "") + oVal; // String
+	},
+	
+	_optionValFromPane: function(/*String*/ id){
+		// summary: Gets the option value given a pane ID
+		var sp = this.stackPrefix;
+		if(sp && id.indexOf(sp) === 0){
+			return id.substring(sp.length); // String
+		}
+		return id; // String
+	},
+	
+	_togglePane: function(/*dijit._Widget*/ pane, /*Boolean*/ shown){
+		// summary: called when a pane is either shown or hidden (so that
+		//  we can toggle the widgets on it)
+		
+		if(pane._shown != undefined && pane._shown == shown){ return; }
+		var widgets = dojo.filter(pane.getDescendants(), "return item.name;");
+		if(!shown){
+			// We are hiding - save the current state and then disable them
+			savedStates = {};
+			dojo.forEach(widgets, function(w){
+				savedStates[w.id] = w.disabled;
+				w.attr("disabled", true);
+			});
+			pane._savedStates = savedStates;
+		}else{
+			// We are showing - restore our saved states
+			var savedStates = pane._savedStates||{};
+			dojo.forEach(widgets, function(w){
+				var state = savedStates[w.id];
+				if(state == undefined){
+					state = false;
+				}
+				w.attr("disabled", state);
+			});
+			delete pane._savedStates;
+		}
+		pane._shown = shown;
+	},
+	
+	_connectTitle: function(/*dijit._Widget*/ pane, /*String*/ value){
+		var fx = dojo.hitch(this, function(title){
+			this.updateOption({value: value, label: title});
+		});
+		if(pane._setTitleAttr){
+			this.connect(pane, "_setTitleAttr", fx);
+		}else{
+			this.connect(pane, "attr", function(attr, val){
+				if(attr == "title" && arguments.length > 1){
+					fx(val);
+				}
+			});
+		}
+	},
+
+	onAddChild: function(/*dijit._Widget*/ pane, /*Integer?*/ insertIndex){
+		// summary: Called when the stack container adds a new pane
+		if(!this._panes[pane.id]){
+			this._panes[pane.id] = pane;
+			var v = this._optionValFromPane(pane.id);
+			this.addOption({value: v, label: pane.title});
+			this._connectTitle(pane, v);
+		}
+		if(!pane.onShow || !pane.onHide || pane._shown == undefined){
+			pane.onShow = dojo.hitch(this, "_togglePane", pane, true);
+			pane.onHide = dojo.hitch(this, "_togglePane", pane, false);
+			pane.onHide();
+		}
+	},
+	
+	_setValueAttr: function(v){
+		if("_savedValue" in this){
+			return;
+		}
+		this.inherited(arguments);
+	},
+	attr: function(/*String|Object*/name, /*Object?*/value){
+		if(name == "value" && arguments.length == 2 && "_savedValue" in this){
+			this._savedValue = value;
+		}
+		return this.inherited(arguments);
+	},
+
+	onRemoveChild: function(/*dijit._Widget*/ pane){
+		// summary: Called when the stack container removes a pane
+		if(this._panes[pane.id]){
+			delete this._panes[pane.id];
+			this.removeOption(this._optionValFromPane(pane.id));
+		}
+	},
+	
+	onSelectChild: function(/*dijit._Widget*/ pane){
+		// summary: Called when the stack container selects a new pane
+		this._setValueAttr(this._optionValFromPane(pane.id));
+	},
+	
+	onStartup: function(/*Object*/ info){
+		// summary: Called when the stack container is started up
+		var selPane = info.selected;
+		this.addOption(dojo.filter(dojo.map(info.children, function(c){
+			var v = this._optionValFromPane(c.id);
+			this._connectTitle(c, v);
+			var toAdd = null;
+			if(!this._panes[c.id]){
+				this._panes[c.id] = c;
+				toAdd = {value: v, label: c.title};
+			}
+			if(!c.onShow || !c.onHide || c._shown == undefined){
+				c.onShow = dojo.hitch(this, "_togglePane", c, true);
+				c.onHide = dojo.hitch(this, "_togglePane", c, false);
+				c.onHide();
+			}
+			if("_savedValue" in this && v === this._savedValue){
+				selPane = c;
+			}
+			return toAdd;
+		}, this), function(i){ return i;}));
+		var _this = this;
+		var fx = function(){
+			// This stuff needs to be run after we show our child, if
+			// the stack is going to show a different child than is 
+			// selected - see trac #9396
+			delete _this._savedValue;
+			_this.onSelectChild(selPane);
+			if(!selPane._shown){
+				_this._togglePane(selPane, true);
+			}			
+		};
+		if(selPane !== info.selected){
+			var stack = dijit.byId(this.stackId);
+			var c = this.connect(stack, "_showChild", function(sel){
+				this.disconnect(c);
+				fx();
+			});
+		}else{
+			fx();
+		}
+	},
+	
+	postMixInProperties: function(){
+		this._savedValue = this.value;
+		this.inherited(arguments);
+		this.connect(this, "onChange", "_handleSelfOnChange");
+	},
+	
+	postCreate: function(){
+		this.inherited(arguments);
+		this._panes = {};
+		this._subscriptions = [
+			dojo.subscribe(this.stackId + "-startup", this, "onStartup"),
+			dojo.subscribe(this.stackId + "-addChild", this, "onAddChild"),
+			dojo.subscribe(this.stackId + "-removeChild", this, "onRemoveChild"),
+			dojo.subscribe(this.stackId + "-selectChild", this, "onSelectChild")
+		];
+		var stack = dijit.byId(this.stackId);
+		if(stack && stack._started){
+			// If we have a stack, and it's already started, call our onStartup now
+			this.onStartup({children: stack.getChildren(), selected: stack.selectedChildWidget});
+		}
+	},
+	
+	destroy: function(){
+		dojo.forEach(this._subscriptions, dojo.unsubscribe);
+		delete this._panes; // Fixes memory leak in IE
+		this.inherited("destroy", arguments);
+	},
+	
+	_handleSelfOnChange: function(/*String*/ val){
+		// summary: Called when form select widget's value has changed
+		var pane = this._panes[this._paneIdFromOption(val)];
+		if (pane){
+			var s = dijit.byId(this.stackId);
+			if(pane == s.selectedChildWidget){
+				s._transition(pane);
+			}else{
+				s.selectChild(pane);
+			}
+		}
+	}
 });
-}else{
-fx();
-}
-},postMixInProperties:function(){
-this._savedValue=this.value;
-this.inherited(arguments);
-this.connect(this,"onChange","_handleSelfOnChange");
-},postCreate:function(){
-this.inherited(arguments);
-this._panes={};
-this._subscriptions=[dojo.subscribe(this.stackId+"-startup",this,"onStartup"),dojo.subscribe(this.stackId+"-addChild",this,"onAddChild"),dojo.subscribe(this.stackId+"-removeChild",this,"onRemoveChild"),dojo.subscribe(this.stackId+"-selectChild",this,"onSelectChild")];
-var _17=dijit.byId(this.stackId);
-if(_17&&_17._started){
-this.onStartup({children:_17.getChildren(),selected:_17.selectedChildWidget});
-}
-},destroy:function(){
-dojo.forEach(this._subscriptions,dojo.unsubscribe);
-delete this._panes;
-this.inherited("destroy",arguments);
-},_handleSelfOnChange:function(val){
-var _18=this._panes[this._paneIdFromOption(val)];
-if(_18){
-var s=dijit.byId(this.stackId);
-if(_18==s.selectedChildWidget){
-s._transition(_18);
-}else{
-s.selectChild(_18);
-}
-}
-}});
-}
diff --git a/dojox/form/manager/_ClassMixin.js b/dojox/form/manager/_ClassMixin.js
index 572af7a..74dc747 100644
--- a/dojox/form/manager/_ClassMixin.js
+++ b/dojox/form/manager/_ClassMixin.js
@@ -1,31 +1,70 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.manager._ClassMixin"]){
-dojo._hasResource["dojox.form.manager._ClassMixin"]=true;
 dojo.provide("dojox.form.manager._ClassMixin");
+
 dojo.require("dojox.form.manager._Mixin");
+
 (function(){
-var fm=dojox.form.manager,aa=fm.actionAdapter,ia=fm.inspectorAdapter;
-dojo.declare("dojox.form.manager._ClassMixin",null,{gatherClassState:function(_1,_2){
-var _3=this.inspect(ia(function(_4,_5){
-return dojo.hasClass(_5,_1);
-}),_2);
-return _3;
-},addClass:function(_6,_7){
-this.inspect(aa(function(_8,_9){
-dojo.addClass(_9,_6);
-}),_7);
-return this;
-},removeClass:function(_a,_b){
-this.inspect(aa(function(_c,_d){
-dojo.removeClass(_d,_a);
-}),_b);
-return this;
-}});
+	var fm = dojox.form.manager,
+		aa = fm.actionAdapter,
+		ia = fm.inspectorAdapter;
+
+	dojo.declare("dojox.form.manager._ClassMixin", null, {
+		// summary:
+		//		Form manager's mixin for testing/assigning/removing
+		//		classes of controlled elements.
+		// description:
+		//		This mixin provides unified way to check/add/remove a class
+		//		of controlled elements.
+		//		It should be used together with dojox.form.manager.Mixin.
+
+		gatherClassState: function(className, names){
+			// summary:
+			//		Gather the presence of a certain class in all controlled elements.
+			// className: String:
+			//		The class name to test for.
+			// names: Object?:
+			//		If it is an array, it is a list of names to be processed.
+			//		If it is an object, dictionary keys are names to be processed.
+			//		If it is omitted, all known form elements are to be processed.
+
+			var result = this.inspect(ia(function(name, node){
+				return dojo.hasClass(node, className);
+			}), names);
+
+			return result;	// Object
+		},
+
+		addClass: function(className, names){
+			// summary:
+			//		Add a class to nodes according to the supplied set of names
+			// className: String:
+			//		Class name to add.
+			// names: Object?:
+			//		If it is an array, it is a list of names to be processed.
+			//		If it is an object, dictionary keys are names to be processed.
+			//		If it is omitted, all known form elements are to be processed.
+
+			this.inspect(aa(function(name, node){
+				dojo.addClass(node, className);
+			}), names);
+
+			return this;	// self
+		},
+
+		removeClass: function(className, names){
+			// summary:
+			//		Remove a class from nodes according to the supplied set of names
+			// className: String:
+			//		Class name to remove.
+			// names: Object?:
+			//		If it is an array, it is a list of names to be processed.
+			//		If it is an object, dictionary keys are names to be processed.
+			//		If it is omitted, all known form elements are to be processed.
+
+			this.inspect(aa(function(name, node){
+				dojo.removeClass(node, className);
+			}), names);
+
+			return this;	// self
+		}
+	});
 })();
-}
diff --git a/dojox/form/manager/_DisplayMixin.js b/dojox/form/manager/_DisplayMixin.js
index 326abc7..c4b84e9 100644
--- a/dojox/form/manager/_DisplayMixin.js
+++ b/dojox/form/manager/_DisplayMixin.js
@@ -1,27 +1,61 @@
-/*
-	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
-*/
+dojo.provide("dojox.form.manager._DisplayMixin");
 
+dojo.declare("dojox.form.manager._DisplayMixin", null, {
+	// summary:
+	//		Form manager's mixin for controlling show/hide state of
+	//		controlled elements (defined by dojoAttachPoint attributes).
+	// description:
+	//		This mixin provides unified show/hide functionality for
+	//		controlled elements (indicated by dojoAttachPoint attribute).
+	//		Essentially it provides a way to change "style.display"
+	//		parameter of controlled nodes.
+	//		It should be used together with dojox.form.manager.Mixin.
 
-if(!dojo._hasResource["dojox.form.manager._DisplayMixin"]){
-dojo._hasResource["dojox.form.manager._DisplayMixin"]=true;
-dojo.provide("dojox.form.manager._DisplayMixin");
-dojo.declare("dojox.form.manager._DisplayMixin",null,{gatherDisplayState:function(_1){
-var _2=this.inspectAttachedPoints(function(_3,_4){
-return dojo.style(_4,"display")!="none";
-},_1);
-return _2;
-},show:function(_5,_6){
-if(arguments.length<2){
-_6=true;
-}
-this.inspectAttachedPoints(function(_7,_8,_9){
-dojo.style(_8,"display",_9?"":"none");
-},_5,_6);
-return this;
-},hide:function(_a){
-return this.show(_a,false);
-}});
-}
+	gatherDisplayState: function(names){
+		// summary:
+		//		Gather display state of all attached elements and return as a dictionary.
+		// names: Object?:
+		//		If it is an array, it is a list of names to be processed.
+		//		If it is an object, dictionary keys are names to be processed.
+		//		If it is omitted, all known attach point nodes are to be processed.
+
+		var result = this.inspectAttachedPoints(function(name, node){
+			return dojo.style(node, "display") != "none";
+		}, names);
+
+		return result;	// Object
+	},
+
+	show: function(state, defaultState){
+		// summary:
+		//		Show attached nodes according to the supplied state object.
+		// state: Object?:
+		//		Optional. If a name-value dictionary, the value is true
+		//		to show and false to hide. If an array, all names in the
+		//		array will be set to defaultState. If omitted, all form
+		//		elements will be set to defaultState.
+		// defaultState: Boolean?:
+		//		The default state (true, if omitted).
+
+		if(arguments.length < 2){
+			defaultState = true;
+		}
+
+		this.inspectAttachedPoints(function(name, node, value){
+			dojo.style(node, "display", value ? "" : "none");
+		}, state, defaultState);
+
+		return this;	// self
+	},
+
+	hide: function(state){
+		// summary:
+		//		Hide attached nodes according to the supplied state object.
+		// state: Object?:
+		//		Optional. If a name-value dictionary, the value is true
+		//		to show and false to hide. If an array, all names in the
+		//		array will be hidden. If omitted, all form elements
+		//		will be hidden.
+		return this.show(state, false);	// self
+	}
+});
diff --git a/dojox/form/manager/_EnableMixin.js b/dojox/form/manager/_EnableMixin.js
index 7b45e88..6182f5b 100644
--- a/dojox/form/manager/_EnableMixin.js
+++ b/dojox/form/manager/_EnableMixin.js
@@ -1,43 +1,81 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.manager._EnableMixin"]){
-dojo._hasResource["dojox.form.manager._EnableMixin"]=true;
 dojo.provide("dojox.form.manager._EnableMixin");
+
 dojo.require("dojox.form.manager._Mixin");
+
 (function(){
-var fm=dojox.form.manager,aa=fm.actionAdapter,ia=fm.inspectorAdapter;
-dojo.declare("dojox.form.manager._EnableMixin",null,{gatherEnableState:function(_1){
-var _2=this.inspectFormWidgets(ia(function(_3,_4){
-return !_4.attr("disabled");
-}),_1);
-if(this.inspectFormNodes){
-dojo.mixin(_2,this.inspectFormNodes(ia(function(_5,_6){
-return !dojo.attr(_6,"disabled");
-}),_1));
-}
-return _2;
-},enable:function(_7,_8){
-if(arguments.length<2||_8===undefined){
-_8=true;
-}
-this.inspectFormWidgets(aa(function(_9,_a,_b){
-_a.attr("disabled",!_b);
-}),_7,_8);
-if(this.inspectFormNodes){
-this.inspectFormNodes(aa(function(_c,_d,_e){
-dojo.attr(_d,"disabled",!_e);
-}),_7,_8);
-}
-return this;
-},disable:function(_f){
-var _10=this.gatherEnableState();
-this.enable(_f,false);
-return _10;
-}});
+	var fm = dojox.form.manager,
+		aa = fm.actionAdapter,
+		ia = fm.inspectorAdapter;
+
+	dojo.declare("dojox.form.manager._EnableMixin", null, {
+		// summary:
+		//		Form manager's mixin for controlling enable/disable state of
+		//		form elements.
+		// description:
+		//		This mixin provides unified enable/disable functionality for
+		//		form widgets and form elements. It should be used together
+		//		with dojox.form.manager.Mixin.
+
+		gatherEnableState: function(names){
+			// summary:
+			//		Gather enable state of all form elements and return as a dictionary.
+			// names: Object?:
+			//		If it is an array, it is a list of names to be processed.
+			//		If it is an object, dictionary keys are names to be processed.
+			//		If it is omitted, all known form elements are to be processed.
+
+			var result = this.inspectFormWidgets(ia(function(name, widget){
+				return !widget.attr("disabled");
+			}), names);
+
+			if(this.inspectFormNodes){
+				dojo.mixin(result, this.inspectFormNodes(ia(function(name, node){
+					return !dojo.attr(node, "disabled");
+				}), names));
+			}
+
+			return result;	// Object
+		},
+
+		enable: function(state, defaultState){
+			// summary:
+			//		Enable form controls according to the supplied state object.
+			// state: Object?:
+			//		Optional. If a name-value dictionary, the value is true
+			//		to enable and false to disable. If an array, all names in the
+			//		array will be set to defaultState. If omitted, all form
+			//		elements will be set to defaultState.
+			// defaultState: Boolean:
+			//		The default state (true, if omitted).
+
+			if(arguments.length < 2 || defaultState === undefined){
+				defaultState = true;
+			}
+
+			this.inspectFormWidgets(aa(function(name, widget, value){
+				widget.attr("disabled", !value);
+			}), state, defaultState);
+
+			if(this.inspectFormNodes){
+				this.inspectFormNodes(aa(function(name, node, value){
+					dojo.attr(node, "disabled", !value);
+				}), state, defaultState);
+			}
+
+			return this;	// self
+		},
+
+		disable: function(state){
+			// summary:
+			//		Disable form controls according to the supplied state object
+			//		returning the previous state.
+			// state: Object?:
+			//		Optional. If a name-value dictionary, the value is true
+			//		to enable and false to disable. If an array, all names in the
+			//		array will be disabled. If omitted, disables all.
+			var oldState = this.gatherEnableState();
+			this.enable(state, false);
+			return oldState;	// Object
+		}
+	});
 })();
-}
diff --git a/dojox/form/manager/_FormMixin.js b/dojox/form/manager/_FormMixin.js
index 341788f..3dd7e6a 100644
--- a/dojox/form/manager/_FormMixin.js
+++ b/dojox/form/manager/_FormMixin.js
@@ -1,70 +1,129 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.manager._FormMixin"]){
-dojo._hasResource["dojox.form.manager._FormMixin"]=true;
 dojo.provide("dojox.form.manager._FormMixin");
+
 dojo.require("dojox.form.manager._Mixin");
+
 (function(){
-var fm=dojox.form.manager,aa=fm.actionAdapter;
-dojo.declare("dojox.form.manager._FormMixin",null,{name:"",action:"",method:"",encType:"","accept-charset":"",accept:"",target:"",startup:function(){
-this.isForm=this.domNode.tagName.toLowerCase()=="form";
-if(this.isForm){
-this.connect(this.domNode,"onreset","_onReset");
-this.connect(this.domNode,"onsubmit","_onSubmit");
-}
-this.inherited(arguments);
-},_onReset:function(_1){
-var _2={returnValue:true,preventDefault:function(){
-this.returnValue=false;
-},stopPropagation:function(){
-},currentTarget:_1.currentTarget,target:_1.target};
-if(!(this.onReset(_2)===false)&&_2.returnValue){
-this.reset();
-}
-dojo.stopEvent(_1);
-return false;
-},onReset:function(){
-return true;
-},reset:function(){
-this.inspectFormWidgets(aa(function(_3,_4){
-if(_4.reset){
-_4.reset();
-}
-}));
-if(this.isForm){
-this.domNode.reset();
-}
-return this;
-},_onSubmit:function(_5){
-if(this.onSubmit(_5)===false){
-dojo.stopEvent(_5);
-}
-},onSubmit:function(){
-return this.isValid();
-},submit:function(){
-if(this.isForm){
-if(!(this.onSubmit()===false)){
-this.domNode.submit();
-}
-}
-},isValid:function(){
-for(var _6 in this.formWidgets){
-var _7=false;
-aa(function(_8,_9){
-if(!_9.attr("disabled")&&_9.isValid&&!_9.isValid()){
-_7=true;
-}
-}).call(this,null,this.formWidgets[_6].widget);
-if(_7){
-return false;
-}
-}
-return true;
-}});
+	var fm = dojox.form.manager,
+		aa = fm.actionAdapter;
+
+	dojo.declare("dojox.form.manager._FormMixin", null, {
+		// summary:
+		//		Form manager's mixin for form-specific functionality.
+		// description:
+		//		This mixin adds automated "onreset", and "onsubmit" event processing
+		//		if we are based on a form node, defines onReset(), onSubmit(),
+		//		reset(), submit(), and isValid() methods like dijit.form.Form.
+		//		It should be used together with dojox.form.manager.Mixin.
+
+		// HTML <FORM> attributes (if we are based on the form element)
+		name: "",
+		action: "",
+		method: "",
+		encType: "",
+		"accept-charset": "",
+		accept: "",
+		target: "",
+
+		startup: function(){
+			this.isForm = this.domNode.tagName.toLowerCase() == "form";
+			if(this.isForm){
+				this.connect(this.domNode, "onreset", "_onReset");
+				this.connect(this.domNode, "onsubmit", "_onSubmit");
+			}
+			this.inherited(arguments);
+		},
+
+		// form-specific functionality
+
+		_onReset: function(evt){
+			// NOTE: this function is taken from dijit.formForm, it works only
+			// for form-based managers.
+
+			// 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: evt.currentTarget, target: evt.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(evt);
+			return false;
+		},
+
+		onReset: function(){
+			//	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
+			return true; // Boolean
+		},
+
+		reset: function(){
+			// summary:
+			//		Resets form widget values.
+			this.inspectFormWidgets(aa(function(_, widget){
+				if(widget.reset){
+					widget.reset();
+				}
+			}));
+			if(this.isForm){
+				this.domNode.reset();
+			}
+			return this;
+		},
+
+		_onSubmit: function(evt){
+			// NOTE: this function is taken from dijit.formForm, it works only
+			// for form-based managers.
+
+			if(this.onSubmit(evt) === false){ // only exactly false stops submit
+				dojo.stopEvent(evt);
+			}
+		},
+
+		onSubmit: function(){
+			//	summary:
+			//		Callback when user submits the form. 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
+
+			return this.isValid(); // Boolean
+		},
+
+		submit: function(){
+			// summary:
+			//		programmatically submit form if and only if the `onSubmit` returns true
+			if(this.isForm){
+				if(!(this.onSubmit() === false)){
+					this.domNode.submit();
+				}
+			}
+		},
+
+		isValid: function(){
+			// summary:
+			//		Make sure that every widget that has a validator function returns true.
+			for(var name in this.formWidgets){
+				var stop = false;
+				aa(function(_, widget){
+					if(!widget.attr("disabled") && widget.isValid && !widget.isValid()){
+						stop = true;
+					}
+				}).call(this, null, this.formWidgets[name].widget);
+				if(stop){
+					return false;
+				}
+			}
+			return true;
+		}
+	});
 })();
-}
diff --git a/dojox/form/manager/_Mixin.js b/dojox/form/manager/_Mixin.js
index 1d68232..a91633c 100644
--- a/dojox/form/manager/_Mixin.js
+++ b/dojox/form/manager/_Mixin.js
@@ -1,274 +1,484 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.manager._Mixin"]){
-dojo._hasResource["dojox.form.manager._Mixin"]=true;
 dojo.provide("dojox.form.manager._Mixin");
+
 dojo.require("dijit._Widget");
+
 (function(){
-var fm=dojox.form.manager,aa=fm.actionAdapter=function(_1){
-return function(_2,_3,_4){
-if(dojo.isArray(_3)){
-dojo.forEach(_3,function(_5){
-_1.call(this,_2,_5,_4);
-},this);
-}else{
-_1.apply(this,arguments);
-}
-};
-},ia=fm.inspectorAdapter=function(_6){
-return function(_7,_8,_9){
-return _6.call(this,_7,dojo.isArray(_8)?_8[0]:_8,_9);
-};
-},_a={domNode:1,containerNode:1,srcNodeRef:1,bgIframe:1},_b=fm._keys=function(o){
-var _c=[],_d;
-for(_d in o){
-if(o.hasOwnProperty(_d)){
-_c.push(_d);
-}
-}
-return _c;
-},_e=function(_f){
-var _10=_f.attr("name");
-if(_10&&_f instanceof dijit.form._FormWidget){
-if(_10 in this.formWidgets){
-var a=this.formWidgets[_10].widget;
-if(dojo.isArray(a)){
-a.push(_f);
-}else{
-this.formWidgets[_10].widget=[a,_f];
-}
-}else{
-this.formWidgets[_10]={widget:_f,connections:[]};
-}
-}else{
-_10=null;
-}
-return _10;
-},_11=function(_12){
-var _13={};
-aa(function(_14,w){
-var o=w.attr("observer");
-if(o&&typeof o=="string"){
-dojo.forEach(o.split(","),function(o){
-o=dojo.trim(o);
-if(o&&dojo.isFunction(this[o])){
-_13[o]=1;
-}
-},this);
-}
-}).call(this,null,this.formWidgets[_12].widget);
-return _b(_13);
-},_15=function(_16,_17){
-var t=this.formWidgets[_16],w=t.widget,c=t.connections;
-if(c.length){
-dojo.forEach(c,dojo.disconnect);
-c=t.connections=[];
-}
-if(dojo.isArray(w)){
-dojo.forEach(w,function(w){
-dojo.forEach(_17,function(o){
-c.push(dojo.connect(w,"onChange",this,function(evt){
-if(this.watch&&dojo.attr(w.focusNode,"checked")){
-this[o](w.attr("value"),_16,w,evt);
-}
-}));
-},this);
-},this);
-}else{
-var _18=w.declaredClass=="dijit.form.Button"?"onClick":"onChange";
-dojo.forEach(_17,function(o){
-c.push(dojo.connect(w,_18,this,function(evt){
-if(this.watch){
-this[o](w.attr("value"),_16,w,evt);
-}
-}));
-},this);
-}
-};
-dojo.declare("dojox.form.manager._Mixin",null,{watch:true,startup:function(){
-if(this._started){
-return;
-}
-this.formWidgets={};
-this.formNodes={};
-this.registerWidgetDescendants(this);
-this.inherited(arguments);
-},destroy:function(){
-for(var _19 in this.formWidgets){
-dojo.forEach(this.formWidgets[_19].connections,dojo.disconnect);
-}
-this.formWidgets={};
-this.inherited(arguments);
-},registerWidget:function(_1a){
-if(typeof _1a=="string"){
-_1a=dijit.byId(_1a);
-}else{
-if(_1a.tagName&&_1a.cloneNode){
-_1a=dijit.byNode(_1a);
-}
-}
-var _1b=_e.call(this,_1a);
-if(_1b){
-_15.call(this,_1b,_11.call(this,_1b));
-}
-return this;
-},unregisterWidget:function(_1c){
-if(_1c in this.formWidgets){
-dojo.forEach(this.formWidgets[_1c].connections,this.disconnect,this);
-delete this.formWidgets[_1c];
-}
-return this;
-},registerWidgetDescendants:function(_1d){
-if(typeof _1d=="string"){
-_1d=dijit.byId(_1d);
-}else{
-if(_1d.tagName&&_1d.cloneNode){
-_1d=dijit.byNode(_1d);
-}
-}
-var _1e=dojo.map(_1d.getDescendants(),_e,this);
-dojo.forEach(_1e,function(_1f){
-if(_1f){
-_15.call(this,_1f,_11.call(this,_1f));
-}
-},this);
-return this.registerNodeDescendants?this.registerNodeDescendants(_1d.domNode):this;
-},unregisterWidgetDescendants:function(_20){
-if(typeof _20=="string"){
-_20=dijit.byId(_20);
-}else{
-if(_20.tagName&&_20.cloneNode){
-_20=dijit.byNode(_20);
-}
-}
-dojo.forEach(dojo.map(_20.getDescendants(),function(w){
-return w instanceof dijit.form._FormWidget&&w.attr("name")||null;
-}),function(_21){
-if(_21){
-this.unregisterNode(_21);
-}
-},this);
-return this.unregisterNodeDescendants?this.unregisterNodeDescendants(_20.domNode):this;
-},formWidgetValue:function(_22,_23){
-var _24=arguments.length==2&&_23!==undefined,_25;
-if(typeof _22=="string"){
-_22=this.formWidgets[_22];
-if(_22){
-_22=_22.widget;
-}
-}
-if(!_22){
-return null;
-}
-if(dojo.isArray(_22)){
-if(_24){
-dojo.forEach(_22,function(_26){
-_26.attr("checked",false);
-});
-dojo.forEach(_22,function(_27){
-_27.attr("checked",_27.attr("value")===_23);
-});
-return this;
-}
-dojo.some(_22,function(_28){
-if(dojo.attr(_28.focusNode,"checked")){
-_25=_28;
-return true;
-}
-return false;
-});
-return _25?_25.attr("value"):"";
-}
-if(_24){
-_22.attr("value",_23);
-return this;
-}
-return _22.attr("value");
-},formPointValue:function(_29,_2a){
-if(_29&&typeof _29=="string"){
-_29=this[_29];
-}
-if(!_29||!_29.tagName||!_29.cloneNode){
-return null;
-}
-if(!dojo.hasClass(_29,"dojoFormValue")){
-return null;
-}
-if(arguments.length==2&&_2a!==undefined){
-_29.innerHTML=_2a;
-return this;
-}
-return _29.innerHTML;
-},inspectFormWidgets:function(_2b,_2c,_2d){
-var _2e,_2f={};
-if(_2c){
-if(dojo.isArray(_2c)){
-dojo.forEach(_2c,function(_30){
-if(_30 in this.formWidgets){
-_2f[_30]=_2b.call(this,_30,this.formWidgets[_30].widget,_2d);
-}
-},this);
-}else{
-for(_2e in _2c){
-if(_2e in this.formWidgets){
-_2f[_2e]=_2b.call(this,_2e,this.formWidgets[_2e].widget,_2c[_2e]);
-}
-}
-}
-}else{
-for(_2e in this.formWidgets){
-_2f[_2e]=_2b.call(this,_2e,this.formWidgets[_2e].widget,_2d);
-}
-}
-return _2f;
-},inspectAttachedPoints:function(_31,_32,_33){
-var _34,_35={};
-if(_32){
-if(dojo.isArray(_32)){
-dojo.forEach(_32,function(_36){
-var _37=this[_36];
-if(_37&&_37.tagName&&_37.cloneNode){
-_35[_36]=_31.call(this,_36,_37,_33);
-}
-},this);
-}else{
-for(_34 in _32){
-var _38=this[_34];
-if(_38&&_38.tagName&&_38.cloneNode){
-_35[_34]=_31.call(this,_34,_38,_32[_34]);
-}
-}
-}
-}else{
-for(_34 in this){
-if(!(_34 in _a)){
-var _38=this[_34];
-if(_38&&_38.tagName&&_38.cloneNode){
-_35[_34]=_31.call(this,_34,_38,_33);
-}
-}
-}
-}
-return _35;
-},inspect:function(_39,_3a,_3b){
-var _3c=this.inspectFormWidgets(function(_3d,_3e,_3f){
-if(dojo.isArray(_3e)){
-return _39.call(this,_3d,dojo.map(_3e,function(w){
-return w.domNode;
-}),_3f);
-}
-return _39.call(this,_3d,_3e.domNode,_3f);
-},_3a,_3b);
-if(this.inspectFormNodes){
-dojo.mixin(_3c,this.inspectFormNodes(_39,_3a,_3b));
-}
-return dojo.mixin(_3c,this.inspectAttachedPoints(_39,_3a,_3b));
-}});
+	var fm = dojox.form.manager,
+
+		aa = fm.actionAdapter = function(action){
+			// summary:
+			//		Adapter that automates application of actions to arrays.
+			// action: Function:
+			//		Function that takes three parameters: a name, an object
+			//		(usually node or widget), and a value. This action will
+			//		be applied to all elements of array.
+			return function(name, elems, value){
+				if(dojo.isArray(elems)){
+					dojo.forEach(elems, function(elem){
+						action.call(this, name, elem, value);
+					}, this);
+				}else{
+					action.apply(this, arguments);
+				}
+			};
+		},
+
+		ia = fm.inspectorAdapter = function(inspector){
+			// summary:
+			//		Adapter that applies an inspector only to the first item of the array.
+			// inspector: Function:
+			//		Function that takes three parameters: a name, an object
+			//		(usually node or widget), and a value.
+			return function(name, elem, value){
+				return inspector.call(this, name, dojo.isArray(elem) ? elem[0] : elem, value);
+			};
+		},
+
+		skipNames = {domNode: 1, containerNode: 1, srcNodeRef: 1, bgIframe: 1},
+
+		keys = fm._keys = function(o){
+			// similar to dojox.lang.functional.keys
+			var list = [], key;
+			for(key in o){
+				if(o.hasOwnProperty(key)){
+					list.push(key);
+				}
+			}
+			return list;
+		},
+
+		registerWidget = function(widget){
+			var name = widget.get("name");
+			if(name && widget instanceof dijit.form._FormWidget){
+				if(name in this.formWidgets){
+					var a = this.formWidgets[name].widget;
+					if(dojo.isArray(a)){
+						a.push(widget);
+					}else{
+						this.formWidgets[name].widget = [a, widget];
+					}
+				}else{
+					this.formWidgets[name] = {widget: widget, connections: []};
+				}
+			}else{
+				name = null;
+			}
+			return name;
+		},
+
+		getObserversFromWidget = function(name){
+			var observers = {};
+			aa(function(_, w){
+				var o = w.get("observer");
+				if(o && typeof o == "string"){
+					dojo.forEach(o.split(","), function(o){
+						o = dojo.trim(o);
+						if(o && dojo.isFunction(this[o])){
+							observers[o] = 1;
+						}
+					}, this);
+				}
+			}).call(this, null, this.formWidgets[name].widget);
+			return keys(observers);
+		},
+
+		connectWidget = function(name, observers){
+			var t = this.formWidgets[name], w = t.widget, c = t.connections;
+			if(c.length){
+				dojo.forEach(c, dojo.disconnect);
+				c = t.connections = [];
+			}
+			if(dojo.isArray(w)){
+				// radio buttons
+				dojo.forEach(w, function(w){
+					dojo.forEach(observers, function(o){
+						c.push(dojo.connect(w, "onChange", this, function(evt){
+							// TODO: for some reason for radio button widgets
+							// w.checked != w.focusNode.checked when value changes.
+							// We test the underlying value to be 100% sure.
+							if(this.watch && dojo.attr(w.focusNode, "checked")){
+								this[o](w.get("value"), name, w, evt);
+							}
+						}));
+					}, this);
+				}, this);
+			}else{
+				// the rest
+				// the next line is a crude workaround for dijit.form.Button that fires onClick instead of onChange
+				var eventName = w.declaredClass == "dijit.form.Button" ?
+						"onClick" : "onChange";
+				dojo.forEach(observers, function(o){
+					c.push(dojo.connect(w, eventName, this, function(evt){
+						if(this.watch){
+							this[o](w.get("value"), name, w, evt);
+						}
+					}));
+				}, this);
+			}
+		};
+
+	dojo.declare("dojox.form.manager._Mixin", null, {
+		// summary:
+		//		Mixin to orchestrate dynamic forms.
+		// description:
+		//		This mixin provideas a foundation for an enhanced form
+		//		functionality: unified access to individual form elements,
+		//		unified "onchange" event processing, general event
+		//		processing, I/O orchestration, and common form-related
+		//		functionality. See additional mixins in dojox.form.manager
+		//		namespace.
+
+		watch: true,
+
+		startup: function(){
+			// summary:
+			//		Called after all the widgets have been instantiated and their
+			//		dom nodes have been inserted somewhere under dojo.doc.body.
+
+			if(this._started){ return; }
+
+			this.formWidgets = {};
+			this.formNodes = {};
+			this.registerWidgetDescendants(this);
+
+			this.inherited(arguments);
+		},
+
+		destroy: function(){
+			// summary:
+			//		Called when the widget is being destroyed
+
+			for(var name in this.formWidgets){
+				dojo.forEach(this.formWidgets[name].connections, dojo.disconnect);
+			}
+			this.formWidgets = {};
+
+			this.inherited(arguments);
+		},
+
+		// register/unregister widgets and nodes
+
+		registerWidget: function(widget){
+			// summary:
+			//		Register a widget with the form manager
+			// widget: String|Node|dijit.form._FormWidget:
+			//		A widget, or its widgetId, or its DOM node
+			// returns: Object:
+			//		Returns self
+			if(typeof widget == "string"){
+				widget = dijit.byId(widget);
+			}else if(widget.tagName && widget.cloneNode){
+				widget = dijit.byNode(widget);
+			}
+			var name = registerWidget.call(this, widget);
+			if(name){
+				connectWidget.call(this, name, getObserversFromWidget.call(this, name));
+			}
+			return this;
+		},
+
+		unregisterWidget: function(name){
+			// summary:
+			//		Removes the widget by name from internal tables unregistering
+			//		connected observers
+			// name: String:
+			//		Name of the to unregister
+			// returns: Object:
+			//		Returns self
+			if(name in this.formWidgets){
+				dojo.forEach(this.formWidgets[name].connections, this.disconnect, this);
+				delete this.formWidgets[name];
+			}
+			return this;
+		},
+
+		registerWidgetDescendants: function(widget){
+			// summary:
+			//		Register widget's descendants with the form manager
+			// widget: String|Node|dijit._Widget:
+			//		A widget, or its widgetId, or its DOM node
+			// returns: Object:
+			//		Returns self
+
+			// convert to widget, if required
+			if(typeof widget == "string"){
+				widget = dijit.byId(widget);
+			}else if(widget.tagName && widget.cloneNode){
+				widget = dijit.byNode(widget);
+			}
+
+			// build the map of widgets
+			var widgets = dojo.map(widget.getDescendants(), registerWidget, this);
+
+			// process observers for widgets
+			dojo.forEach(widgets, function(name){
+				if(name){
+					connectWidget.call(this, name, getObserversFromWidget.call(this, name));
+				}
+			}, this);
+
+			// do the same with nodes, if available
+			return this.registerNodeDescendants ?
+				this.registerNodeDescendants(widget.domNode) : this;
+		},
+
+		unregisterWidgetDescendants: function(widget){
+			// summary:
+			//		Unregister widget's descendants with the form manager
+			// widget: String|Node|dijit._Widget:
+			//		A widget, or its widgetId, or its DOM node
+			// returns: Object:
+			//		Returns self
+
+			// convert to widget, if required
+			if(typeof widget == "string"){
+				widget = dijit.byId(widget);
+			}else if(widget.tagName && widget.cloneNode){
+				widget = dijit.byNode(widget);
+			}
+
+			// unregister widgets by names
+			dojo.forEach(
+				dojo.map(
+					widget.getDescendants(),
+					function(w){
+						return w instanceof dijit.form._FormWidget && w.get("name") || null;
+					}
+				),
+				function(name){
+					if(name){
+						this.unregisterNode(name);
+					}
+				},
+				this
+			);
+
+			// do the same with nodes, if available
+			return this.unregisterNodeDescendants ?
+				this.unregisterNodeDescendants(widget.domNode) : this;
+		},
+
+		// value accessors
+
+		formWidgetValue: function(elem, value){
+			// summary:
+			//		Set or get a form widget by name.
+			// elem: String|Object|Array:
+			//		Form element's name, widget object, or array or radio widgets.
+			// value: Object?:
+			//		Optional. The value to set.
+			// returns: Object:
+			//		For a getter it returns the value, for a setter it returns
+			//		self. If the elem is not valid, null will be returned.
+
+			var isSetter = arguments.length == 2 && value !== undefined, result;
+
+			if(typeof elem == "string"){
+				elem = this.formWidgets[elem];
+				if(elem){
+					elem = elem.widget;
+				}
+			}
+
+			if(!elem){
+				return null;	// Object
+			}
+
+			if(dojo.isArray(elem)){
+				// input/radio array of widgets
+				if(isSetter){
+					dojo.forEach(elem, function(widget){
+						widget.set("checked", false, !this.watch);
+					});
+					dojo.forEach(elem, function(widget){
+						widget.set("checked", widget.value === value, !this.watch);
+					});
+					return this;	// self
+				}
+				// getter
+				dojo.some(elem, function(widget){
+					// TODO: for some reason for radio button widgets
+					// w.checked != w.focusNode.checked when value changes.
+					// We test the underlying value to be 100% sure.
+					if(dojo.attr(widget.focusNode, "checked")){
+					//if(widget.get("checked")){
+						result = widget;
+						return true;
+					}
+					return false;
+				});
+				return result ? result.get("value") : "";	// String
+			}
+
+			// checkbox widget is a special case :-(
+			if(elem.declaredClass == "dijit.form.CheckBox"){
+				if(isSetter){
+					elem.set("value", Boolean(value), !this.watch);
+					return this;	// self
+				}
+				return Boolean(elem.get("value"));	// Object
+			}
+
+			// all other elements
+			if(isSetter){
+				elem.set("value", value, !this.watch);
+				return this;	// self
+			}
+			return elem.get("value");	// Object
+		},
+
+		formPointValue: function(elem, value){
+			// summary:
+			//		Set or get a node context by name (using dojoAttachPoint).
+			// elem: String|Object|Array:
+			//		A node.
+			// value: Object?:
+			//		Optional. The value to set.
+			// returns: Object:
+			//		For a getter it returns the value, for a setter it returns
+			//		self. If the elem is not valid, null will be returned.
+
+			if(elem && typeof elem == "string"){
+				elem = this[elem];
+			}
+
+			if(!elem || !elem.tagName || !elem.cloneNode){
+				return null;	// Object
+			}
+
+			if(!dojo.hasClass(elem, "dojoFormValue")){
+				// accessing the value of the attached point not marked with CSS class 'dojoFormValue'
+				return null;
+			}
+
+			if(arguments.length == 2 && value !== undefined){
+				// setter
+				elem.innerHTML = value;
+				return this;	// self
+			}
+			// getter
+			return elem.innerHTML;	// String
+		},
+
+		// inspectors
+
+		inspectFormWidgets: function(inspector, state, defaultValue){
+			// summary:
+			//		Run an inspector function on controlled widgets returning a result object.
+			// inspector: Function:
+			//		A function to be called on a widget. Takes three arguments: a name, a widget object
+			//		or an array of widget objects, and a supplied value. Runs in the context of
+			//		the form manager. Returns a value that will be collected and returned as a state.
+			// state: Object?:
+			//		Optional. If a name-value dictionary --- only listed names will be processed.
+			//		If an array, all names in the array will be processed with defaultValue.
+			//		If omitted or null, all widgets will be processed with defaultValue.
+			// defaultValue: Object?:
+			//		Optional. The default state (true, if omitted).
+
+			var name, result = {};
+
+			if(state){
+				if(dojo.isArray(state)){
+					dojo.forEach(state, function(name){
+						if(name in this.formWidgets){
+							result[name] = inspector.call(this, name, this.formWidgets[name].widget, defaultValue);
+						}
+					}, this);
+				}else{
+					for(name in state){
+						if(name in this.formWidgets){
+							result[name] = inspector.call(this, name, this.formWidgets[name].widget, state[name]);
+						}
+					}
+				}
+			}else{
+				for(name in this.formWidgets){
+					result[name] = inspector.call(this, name, this.formWidgets[name].widget, defaultValue);
+				}
+			}
+
+			return result;	// Object
+		},
+
+		inspectAttachedPoints: function(inspector, state, defaultValue){
+			// summary:
+			//		Run an inspector function on "dojoAttachPoint" nodes returning a result object.
+			// inspector: Function:
+			//		A function to be called on a node. Takes three arguments: a name, a node or
+			//		an array of nodes, and a supplied value. Runs in the context of the form manager.
+			//		Returns a value that will be collected and returned as a state.
+			// state: Object?:
+			//		Optional. If a name-value dictionary --- only listed names will be processed.
+			//		If an array, all names in the array will be processed with defaultValue.
+			//		If omitted or null, all attached point nodes will be processed with defaultValue.
+			// defaultValue: Object?:
+			//		Optional. The default state (true, if omitted).
+
+			var name, result = {};
+
+			if(state){
+				if(dojo.isArray(state)){
+					dojo.forEach(state, function(name){
+						var elem = this[name];
+						if(elem && elem.tagName && elem.cloneNode){
+							result[name] = inspector.call(this, name, elem, defaultValue);
+						}
+					}, this);
+				}else{
+					for(name in state){
+						var elem = this[name];
+						if(elem && elem.tagName && elem.cloneNode){
+							result[name] = inspector.call(this, name, elem, state[name]);
+						}
+					}
+				}
+			}else{
+				for(name in this){
+					if(!(name in skipNames)){
+						var elem = this[name];
+						if(elem && elem.tagName && elem.cloneNode){
+							result[name] = inspector.call(this, name, elem, defaultValue);
+						}
+					}
+				}
+			}
+
+			return result;	// Object
+		},
+
+		inspect: function(inspector, state, defaultValue){
+			// summary:
+			//		Run an inspector function on controlled elements returning a result object.
+			// inspector: Function:
+			//		A function to be called on a widget, form element, and an attached node.
+			//		Takes three arguments: a name, a node (domNode in the case of widget) or
+			//		an array of such objects, and a supplied value. Runs in the context of
+			//		the form manager. Returns a value that will be collected and returned as a state.
+			// state: Object?:
+			//		Optional. If a name-value dictionary --- only listed names will be processed.
+			//		If an array, all names in the array will be processed with defaultValue.
+			//		If omitted or null, all controlled elements will be processed with defaultValue.
+			// defaultValue: Object?:
+			//		Optional. The default state (true, if omitted).
+
+			var result = this.inspectFormWidgets(function(name, widget, value){
+				if(dojo.isArray(widget)){
+					return inspector.call(this, name, dojo.map(widget, function(w){ return w.domNode; }), value);
+				}
+				return inspector.call(this, name, widget.domNode, value);
+			}, state, defaultValue);
+			if(this.inspectFormNodes){
+				dojo.mixin(result, this.inspectFormNodes(inspector, state, defaultValue));
+			}
+			return dojo.mixin(result, this.inspectAttachedPoints(inspector, state, defaultValue));	// Object
+		}
+	});
 })();
-dojo.extend(dijit._Widget,{observer:""});
-}
+
+// These arguments can be specified for widgets which are used in forms.
+// Since any widget can be specified as sub widgets, mix it into the base
+// widget class.  (This is a hack, but it's effective.)
+dojo.extend(dijit._Widget, {
+	observer: ""
+});
diff --git a/dojox/form/manager/_NodeMixin.js b/dojox/form/manager/_NodeMixin.js
index 1fbb251..c691494 100644
--- a/dojox/form/manager/_NodeMixin.js
+++ b/dojox/form/manager/_NodeMixin.js
@@ -1,239 +1,360 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.form.manager._NodeMixin"]){
-dojo._hasResource["dojox.form.manager._NodeMixin"]=true;
 dojo.provide("dojox.form.manager._NodeMixin");
+
 dojo.require("dojox.form.manager._Mixin");
+
 (function(){
-var fm=dojox.form.manager,aa=fm.actionAdapter,_1=fm._keys,ce=fm.changeEvent=function(_2){
-var _3="onclick";
-switch(_2.tagName.toLowerCase()){
-case "textarea":
-_3="onkeyup";
-break;
-case "select":
-_3="onchange";
-break;
-case "input":
-switch(_2.type.toLowerCase()){
-case "text":
-case "password":
-_3="onkeyup";
-break;
-}
-break;
-}
-return _3;
-},_4=function(_5,_6){
-var _7=dojo.attr(_5,"name");
-_6=_6||this.domNode;
-if(_7&&!(_7 in this.formWidgets)){
-for(var n=_5;n&&n!==_6;n=n.parentNode){
-if(dojo.attr(n,"widgetId")&&dijit.byNode(n) instanceof dijit.form._FormWidget){
-return null;
-}
-}
-if(_5.tagName.toLowerCase()=="input"&&_5.type.toLowerCase()=="radio"){
-var a=this.formNodes[_7];
-a=a&&a.node;
-if(a&&dojo.isArray(a)){
-a.push(_5);
-}else{
-this.formNodes[_7]={node:[_5],connections:[]};
-}
-}else{
-this.formNodes[_7]={node:_5,connections:[]};
-}
-}else{
-_7=null;
-}
-return _7;
-},_8=function(_9){
-var _a={};
-aa(function(_b,n){
-var o=dojo.attr(n,"observer");
-if(o&&typeof o=="string"){
-dojo.forEach(o.split(","),function(o){
-o=dojo.trim(o);
-if(o&&dojo.isFunction(this[o])){
-_a[o]=1;
-}
-},this);
-}
-}).call(this,null,this.formNodes[_9].node);
-return _1(_a);
-},_c=function(_d,_e){
-var t=this.formNodes[_d],c=t.connections;
-if(c.length){
-dojo.forEach(c,dojo.disconnect);
-c=t.connections=[];
-}
-aa(function(_f,n){
-var _10=ce(n);
-dojo.forEach(_e,function(o){
-c.push(dojo.connect(n,_10,this,function(evt){
-if(this.watch){
-this[o](this.formNodeValue(_d),_d,n,evt);
-}
-}));
-},this);
-}).call(this,null,t.node);
-};
-dojo.declare("dojox.form.manager._NodeMixin",null,{destroy:function(){
-for(var _11 in this.formNodes){
-dojo.forEach(this.formNodes[_11].connections,dojo.disconnect);
-}
-this.formNodes={};
-this.inherited(arguments);
-},registerNode:function(_12){
-if(typeof _12=="string"){
-_12=dojo.byId(_12);
-}
-var _13=_4.call(this,_12);
-if(_13){
-_c.call(this,_13,_8.call(this,_13));
-}
-return this;
-},unregisterNode:function(_14){
-if(_14 in this.formNodes){
-dojo.forEach(this.formNodes[_14].connections,this.disconnect,this);
-delete this.formNodes[_14];
-}
-return this;
-},registerNodeDescendants:function(_15){
-if(typeof _15=="string"){
-_15=dojo.byId(_15);
-}
-dojo.query("input, select, textarea, button",_15).map(function(n){
-return _4.call(this,n,_15);
-},this).forEach(function(_16){
-if(_16){
-_c.call(this,_16,_8.call(this,_16));
-}
-},this);
-return this;
-},unregisterNodeDescendants:function(_17){
-if(typeof _17=="string"){
-_17=dojo.byId(_17);
-}
-dojo.query("input, select, textarea, button",_17).map(function(n){
-return dojo.attr(_17,"name")||null;
-}).forEach(function(_18){
-if(_18){
-this.unregisterNode(_18);
-}
-},this);
-return this;
-},formNodeValue:function(_19,_1a){
-var _1b=arguments.length==2&&_1a!==undefined,_1c;
-if(typeof _19=="string"){
-_19=this.formNodes[_19];
-if(_19){
-_19=_19.node;
-}
-}
-if(!_19){
-return null;
-}
-if(dojo.isArray(_19)){
-if(_1b){
-dojo.forEach(_19,function(_1d){
-_1d.checked="";
-});
-dojo.forEach(_19,function(_1e){
-_1e.checked=_1e.value===_1a?"checked":"";
-});
-return this;
-}
-dojo.some(_19,function(_1f){
-if(_1f.checked){
-_1c=_1f;
-return true;
-}
-return false;
-});
-return _1c?_1c.value:"";
-}
-switch(_19.tagName.toLowerCase()){
-case "select":
-if(_19.multiple){
-if(_1b){
-if(dojo.isArray(_1a)){
-var _20={};
-dojo.forEach(_1a,function(v){
-_20[v]=1;
-});
-dojo.query("> option",_19).forEach(function(opt){
-opt.selected=opt.value in _20;
-});
-return this;
-}
-dojo.query("> option",_19).forEach(function(opt){
-opt.selected=opt.value===_1a;
-});
-return this;
-}
-var _1c=dojo.query("> option",_19).filter(function(opt){
-return opt.selected;
-}).map(function(opt){
-return opt.value;
-});
-return _1c.length==1?_1c[0]:_1c;
-}
-if(_1b){
-dojo.query("> option",_19).forEach(function(opt){
-opt.selected=opt.value===_1a;
-});
-return this;
-}
-return _19.value||"";
-case "button":
-if(_1b){
-_19.innerHTML=""+_1a;
-return this;
-}
-return _19.innerHTML;
-case "input":
-if(_19.type.toLowerCase()=="checkbox"){
-if(_1b){
-_19.checked=_1a?"checked":"";
-return this;
-}
-return Boolean(_19.checked);
-}
-}
-if(_1b){
-_19.value=""+_1a;
-return this;
-}
-return _19.value;
-},inspectFormNodes:function(_21,_22,_23){
-var _24,_25={};
-if(_22){
-if(dojo.isArray(_22)){
-dojo.forEach(_22,function(_26){
-if(_26 in this.formNodes){
-_25[_26]=_21.call(this,_26,this.formNodes[_26].node,_23);
-}
-},this);
-}else{
-for(_24 in _22){
-if(_24 in this.formNodes){
-_25[_24]=_21.call(this,_24,this.formNodes[_24].node,_22[_24]);
-}
-}
-}
-}else{
-for(_24 in this.formNodes){
-_25[_24]=_21.call(this,_24,this.formNodes[_24].node,_23);
-}
-}
-return _25;
-}});
+	var fm = dojox.form.manager,
+		aa = fm.actionAdapter,
+		keys = fm._keys,
+
+		ce = fm.changeEvent = function(node){
+			// summary:
+			//		Function that returns a valid "onchange" event for a given form node.
+			// node: Node:
+			//		Form node.
+
+			var eventName = "onclick";
+			switch(node.tagName.toLowerCase()){
+				case "textarea":
+					eventName = "onkeyup";
+					break;
+				case "select":
+					eventName = "onchange";
+					break;
+				case "input":
+					switch(node.type.toLowerCase()){
+						case "text":
+						case "password":
+							eventName = "onkeyup";
+							break;
+					}
+					break;
+				// button, input/button, input/checkbox, input/radio,
+				// input/file, input/image, input/submit, input/reset
+				// use "onclick" (the default)
+			}
+			return eventName;	// String
+		},
+
+		registerNode = function(node, groupNode){
+			var name = dojo.attr(node, "name");
+			groupNode = groupNode || this.domNode;
+			if(name && !(name in this.formWidgets)){
+				// verify that it is not part of any widget
+				for(var n = node; n && n !== groupNode; n = n.parentNode){
+					if(dojo.attr(n, "widgetId") && dijit.byNode(n) instanceof dijit.form._FormWidget){
+						// this is a child of some widget --- bail out
+						return null;
+					}
+				}
+				// register the node
+				if(node.tagName.toLowerCase() == "input" && node.type.toLowerCase() == "radio"){
+					var a = this.formNodes[name];
+					a = a && a.node;
+					if(a && dojo.isArray(a)){
+						a.push(node);
+					}else{
+						this.formNodes[name] = {node: [node], connections: []};
+					}
+				}else{
+					this.formNodes[name] = {node: node, connections: []};
+				}
+			}else{
+				name = null;
+			}
+			return name;
+		},
+
+		getObserversFromNode = function(name){
+			var observers = {};
+			aa(function(_, n){
+				var o = dojo.attr(n, "observer");
+				if(o && typeof o == "string"){
+					dojo.forEach(o.split(","), function(o){
+						o = dojo.trim(o);
+						if(o && dojo.isFunction(this[o])){
+							observers[o] = 1;
+						}
+					}, this);
+				}
+			}).call(this, null, this.formNodes[name].node);
+			return keys(observers);
+		},
+
+		connectNode = function(name, observers){
+			var t = this.formNodes[name], c = t.connections;
+			if(c.length){
+				dojo.forEach(c, dojo.disconnect);
+				c = t.connections = [];
+			}
+			aa(function(_, n){
+				// the next line is a crude workaround for dijit.form.Button that fires onClick instead of onChange
+				var eventName = ce(n);
+				dojo.forEach(observers, function(o){
+					c.push(dojo.connect(n, eventName, this, function(evt){
+						if(this.watch){
+							this[o](this.formNodeValue(name), name, n, evt);
+						}
+					}));
+				}, this);
+			}).call(this, null, t.node);
+		};
+	dojo.declare("dojox.form.manager._NodeMixin", null, {
+		// summary:
+		//		Mixin to orchestrate dynamic forms (works with DOM nodes).
+		// description:
+		//		This mixin provideas a foundation for an enhanced form
+		//		functionality: unified access to individual form elements,
+		//		unified "onchange" event processing, and general event
+		//		processing. It complements dojox.form.manager._Mixin
+		//		extending the functionality to DOM nodes.
+
+		destroy: function(){
+			// summary:
+			//		Called when the widget is being destroyed
+
+			for(var name in this.formNodes){
+				dojo.forEach(this.formNodes[name].connections, dojo.disconnect);
+			}
+			this.formNodes = {};
+
+			this.inherited(arguments);
+		},
+
+		// register/unregister widgets and nodes
+
+		registerNode: function(node){
+			// summary:
+			//		Register a node with the form manager
+			// node: String|Node:
+			//		A node, or its id
+			// returns: Object:
+			//		Returns self
+			if(typeof node == "string"){
+				node = dojo.byId(node);
+			}
+			var name = registerNode.call(this, node);
+			if(name){
+				connectNode.call(this, name, getObserversFromNode.call(this, name));
+			}
+			return this;
+		},
+
+		unregisterNode: function(name){
+			// summary:
+			//		Removes the node by name from internal tables unregistering
+			//		connected observers
+			// name: String:
+			//		Name of the to unregister
+			// returns: Object:
+			//		Returns self
+			if(name in this.formNodes){
+				dojo.forEach(this.formNodes[name].connections, this.disconnect, this);
+				delete this.formNodes[name];
+			}
+			return this;
+		},
+
+		registerNodeDescendants: function(node){
+			// summary:
+			//		Register node's descendants (form nodes) with the form manager
+			// node: String|Node:
+			//		A widget, or its widgetId, or its DOM node
+			// returns: Object:
+			//		Returns self
+
+			if(typeof node == "string"){
+				node = dojo.byId(node);
+			}
+
+			dojo.query("input, select, textarea, button", node).
+				map(function(n){
+					return registerNode.call(this, n, node);
+				}, this).
+				forEach(function(name){
+					if(name){
+						connectNode.call(this, name, getObserversFromNode.call(this, name));
+					}
+				}, this);
+
+			return this;
+		},
+
+		unregisterNodeDescendants: function(node){
+			// summary:
+			//		Unregister node's descendants (form nodes) with the form manager
+			// node: String|Node:
+			//		A widget, or its widgetId, or its DOM node
+			// returns: Object:
+			//		Returns self
+
+			if(typeof node == "string"){
+				node = dojo.byId(node);
+			}
+
+			dojo.query("input, select, textarea, button", node).
+				map(function(n){ return dojo.attr(node, "name") || null; }).
+				forEach(function(name){
+					if(name){
+						this.unregisterNode(name);
+					}
+				}, this);
+
+			return this;
+		},
+
+		// value accessors
+
+		formNodeValue: function(elem, value){
+			// summary:
+			//		Set or get a form element by name.
+			// elem: String|Node|Array:
+			//		Form element's name, DOM node, or array or radio nodes.
+			// value: Object?:
+			//		Optional. The value to set.
+			// returns: Object:
+			//		For a getter it returns the value, for a setter it returns
+			//		self. If the elem is not valid, null will be returned.
+
+			var isSetter = arguments.length == 2 && value !== undefined, result;
+
+			if(typeof elem == "string"){
+				elem = this.formNodes[elem];
+				if(elem){
+					elem = elem.node;
+				}
+			}
+
+			if(!elem){
+				return null;	// Object
+			}
+
+			if(dojo.isArray(elem)){
+				// input/radio array
+				if(isSetter){
+					dojo.forEach(elem, function(node){
+						node.checked = "";
+					});
+					dojo.forEach(elem, function(node){
+						node.checked = node.value === value ? "checked" : "";
+					});
+					return this;	// self
+				}
+				// getter
+				dojo.some(elem, function(node){
+					if(node.checked){
+						result = node;
+						return true;
+					}
+					return false;
+				});
+				return result ? result.value : "";	// String
+			}
+			// all other elements
+			switch(elem.tagName.toLowerCase()){
+				case "select":
+					if(elem.multiple){
+						// multiple is allowed
+						if(isSetter){
+							if(dojo.isArray(value)){
+								var dict = {};
+								dojo.forEach(value, function(v){
+									dict[v] = 1;
+								});
+								dojo.query("> option", elem).forEach(function(opt){
+									opt.selected = opt.value in dict;
+								});
+								return this;	// self
+							}
+							// singular property
+							dojo.query("> option", elem).forEach(function(opt){
+								opt.selected = opt.value === value;
+							});
+							return this;	// self
+						}
+						// getter
+						var result = dojo.query("> option", elem).filter(function(opt){
+							return opt.selected;
+						}).map(function(opt){
+							return opt.value;
+						});
+						return result.length == 1 ? result[0] : result;	// Object
+					}
+					// singular
+					if(isSetter){
+						dojo.query("> option", elem).forEach(function(opt){
+							opt.selected = opt.value === value;
+						});
+						return this;	// self
+					}
+					// getter
+					return elem.value || ""; // String
+				case "button":
+					if(isSetter){
+						elem.innerHTML = "" + value;
+						return this;
+					}
+					// getter
+					return elem.innerHTML;
+				case "input":
+					if(elem.type.toLowerCase() == "checkbox"){
+						// input/checkbox element
+						if(isSetter){
+							elem.checked = value ? "checked" : "";
+							return this;
+						}
+						// getter
+						return Boolean(elem.checked);
+					}
+			}
+			// the rest of inputs
+			if(isSetter){
+				elem.value = "" + value;
+				return this;
+			}
+			// getter
+			return elem.value;
+		},
+
+		// inspectors
+
+		inspectFormNodes: function(inspector, state, defaultValue){
+			// summary:
+			//		Run an inspector function on controlled form elements returning a result object.
+			// inspector: Function:
+			//		A function to be called on a form element. Takes three arguments: a name, a node or
+			//		an array of nodes, and a supplied value. Runs in the context of the form manager.
+			//		Returns a value that will be collected and returned as a state.
+			// state: Object?:
+			//		Optional. If a name-value dictionary --- only listed names will be processed.
+			//		If an array, all names in the array will be processed with defaultValue.
+			//		If omitted or null, all form elements will be processed with defaultValue.
+			// defaultValue: Object?:
+			//		Optional. The default state (true, if omitted).
+
+			var name, result = {};
+
+			if(state){
+				if(dojo.isArray(state)){
+					dojo.forEach(state, function(name){
+						if(name in this.formNodes){
+							result[name] = inspector.call(this, name, this.formNodes[name].node, defaultValue);
+						}
+					}, this);
+				}else{
+					for(name in state){
+						if(name in this.formNodes){
+							result[name] = inspector.call(this, name, this.formNodes[name].node, state[name]);
+						}
+					}
+				}
+			}else{
+				for(name in this.formNodes){
+					result[name] = inspector.call(this, name, this.formNodes[name].node, defaultValue);
+				}
+			}
+
+			return result;	// Object
+		}
+	});
 })();
-}
diff --git a/dojox/form/manager/_ValueMixin.js b/dojox/form/manager/_ValueMixin.js
index 013ac11..6d20986 100644
--- a/dojox/form/manager/_ValueMixin.js
+++ b/dojox/form/manager/_ValueMixin.js
@@ -1,48 +1,77 @@
-/*
-	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
-*/
+dojo.provide("dojox.form.manager._ValueMixin");
 
+dojo.declare("dojox.form.manager._ValueMixin", null, {
+	// summary:
+	//		Form manager's mixin for getting/setting form values in the unified manner.
+	// description:
+	//		This mixin adds unified access to form widgets and form elements
+	//		in terms of name-value regardless of the underlying type of
+	//		an element. It should be used together with dojox.form.manager.Mixin.
 
-if(!dojo._hasResource["dojox.form.manager._ValueMixin"]){
-dojo._hasResource["dojox.form.manager._ValueMixin"]=true;
-dojo.provide("dojox.form.manager._ValueMixin");
-dojo.declare("dojox.form.manager._ValueMixin",null,{elementValue:function(_1,_2){
-if(_1 in this.formWidgets){
-return this.formWidgetValue(_1,_2);
-}
-if(this.formNodes&&_1 in this.formNodes){
-return this.formNodeValue(_1,_2);
-}
-return this.formPointValue(_1,_2);
-},gatherFormValues:function(_3){
-var _4=this.inspectFormWidgets(function(_5){
-return this.formWidgetValue(_5);
-},_3);
-if(this.inspectFormNodes){
-dojo.mixin(_4,this.inspectFormNodes(function(_6){
-return this.formNodeValue(_6);
-},_3));
-}
-dojo.mixin(_4,this.inspectAttachedPoints(function(_7){
-return this.formPointValue(_7);
-},_3));
-return _4;
-},setFormValues:function(_8){
-if(_8){
-this.inspectFormWidgets(function(_9,_a,_b){
-this.formWidgetValue(_9,_b);
-},_8);
-if(this.inspectFormNodes){
-this.inspectFormNodes(function(_c,_d,_e){
-this.formNodeValue(_c,_e);
-},_8);
-}
-this.inspectAttachedPoints(function(_f,_10,_11){
-this.formPointValue(_f,_11);
-},_8);
-}
-return this;
-}});
-}
+	elementValue: function(name, value){
+		// summary:
+		//		Set or get a form widget/element or an attached point node by name.
+		// name: String:
+		//		The name.
+		// value: Object?:
+		//		Optional. The value to set.
+
+		if(name in this.formWidgets){
+			return this.formWidgetValue(name, value);	// Object
+		}
+
+		if(this.formNodes && name in this.formNodes){
+			return this.formNodeValue(name, value);	// Object
+		}
+
+		return this.formPointValue(name, value);	// Object
+	},
+
+	gatherFormValues: function(names){
+		// summary:
+		//		Collect form values.
+		// names: Object?:
+		//		If it is an array, it is a list of names of form elements to be collected.
+		//		If it is an object, dictionary keys are names to be collected.
+		//		If it is omitted, all known form elements are to be collected.
+
+		var result = this.inspectFormWidgets(function(name){
+			return this.formWidgetValue(name);
+		}, names);
+
+		if(this.inspectFormNodes){
+			dojo.mixin(result, this.inspectFormNodes(function(name){
+				return this.formNodeValue(name);
+			}, names));
+		}
+
+		dojo.mixin(result, this.inspectAttachedPoints(function(name){
+			return this.formPointValue(name);
+		}, names));
+
+		return result;	// Object
+	},
+
+	setFormValues: function(values){
+		// summary:
+		//		Set values to form elements
+		// values: Object:
+		//		A dictionary of key-value pairs.
+		if(values){
+			this.inspectFormWidgets(function(name, widget, value){
+				this.formWidgetValue(name, value);
+			}, values);
+
+			if(this.inspectFormNodes){
+				this.inspectFormNodes(function(name, node, value){
+					this.formNodeValue(name, value);
+				}, values);
+			}
+
+			this.inspectAttachedPoints(function(name, node, value){
+				this.formPointValue(name, value);
+			}, values);
+		}
+		return this;
+	}
+});
diff --git a/dojox/form/nls/PasswordValidator.js b/dojox/form/nls/PasswordValidator.js
index 4887d27..276f75f 100644
--- a/dojox/form/nls/PasswordValidator.js
+++ b/dojox/form/nls/PasswordValidator.js
@@ -1 +1,4 @@
-({"badPasswordMessage":"Invalid Password.","nomatchMessage":"Passwords do not match."})
\ No newline at end of file
+({
+        nomatchMessage: "Passwords do not match.",
+		badPasswordMessage: "Invalid Password."
+})
diff --git a/dojox/form/nls/ar/PasswordValidator.js b/dojox/form/nls/ar/PasswordValidator.js
index 83a7761..7760eba 100644
--- a/dojox/form/nls/ar/PasswordValidator.js
+++ b/dojox/form/nls/ar/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"كلمة سرية غير صحيحة.","nomatchMessage":"كلمة السرية غير مطابقة."})
\ No newline at end of file
+({
+        nomatchMessage: "كلمة السرية غير مطابقة.",
+		badPasswordMessage: "كلمة سرية غير صحيحة."
+})
+
diff --git a/dojox/form/nls/ca/PasswordValidator.js b/dojox/form/nls/ca/PasswordValidator.js
index 8b9ce17..4f52779 100644
--- a/dojox/form/nls/ca/PasswordValidator.js
+++ b/dojox/form/nls/ca/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"La contrasenya no és correcta","nomatchMessage":"Les contrasenyes no coincideixen"})
\ No newline at end of file
+({
+        nomatchMessage: "Les contrasenyes no coincideixen",
+		badPasswordMessage: "La contrasenya no és correcta"
+})
+
diff --git a/dojox/form/nls/cs/PasswordValidator.js b/dojox/form/nls/cs/PasswordValidator.js
index 0659853..ca07c3c 100644
--- a/dojox/form/nls/cs/PasswordValidator.js
+++ b/dojox/form/nls/cs/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Neplatné heslo.","nomatchMessage":"Hesla se neshodují."})
\ No newline at end of file
+({
+        nomatchMessage: "Hesla se neshodují.",
+		badPasswordMessage: "Neplatné heslo."
+})
+
diff --git a/dojox/form/nls/da/PasswordValidator.js b/dojox/form/nls/da/PasswordValidator.js
index 3321341..d516b77 100644
--- a/dojox/form/nls/da/PasswordValidator.js
+++ b/dojox/form/nls/da/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Ugyldig adgangskode.","nomatchMessage":"Adgangskoderne stemmer ikke overens."})
\ No newline at end of file
+({
+        nomatchMessage: "Adgangskoderne stemmer ikke overens.",
+		badPasswordMessage: "Ugyldig adgangskode."
+})
+
diff --git a/dojox/form/nls/de/PasswordValidator.js b/dojox/form/nls/de/PasswordValidator.js
index 201893b..64c5472 100644
--- a/dojox/form/nls/de/PasswordValidator.js
+++ b/dojox/form/nls/de/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Ungültiges Kennwort.","nomatchMessage":"Die Kennwörter stimmen nicht überein."})
\ No newline at end of file
+({
+        nomatchMessage: "Die Kennwörter stimmen nicht überein.",
+		badPasswordMessage: "Ungültiges Kennwort."
+})
+
diff --git a/dojox/form/nls/el/PasswordValidator.js b/dojox/form/nls/el/PasswordValidator.js
index ab8b9be..5e256a1 100644
--- a/dojox/form/nls/el/PasswordValidator.js
+++ b/dojox/form/nls/el/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Μη έγκυρος κωδικός πρόσβασης.","nomatchMessage":"Οι κωδικοί πρόσβασης δεν συμφωνούν."})
\ No newline at end of file
+({
+        nomatchMessage: "Οι κωδικοί πρόσβασης δεν συμφωνούν.",
+		badPasswordMessage: "Μη έγκυρος κωδικός πρόσβασης."
+})
+
diff --git a/dojox/form/nls/es/PasswordValidator.js b/dojox/form/nls/es/PasswordValidator.js
index 131ecda..d984e1a 100644
--- a/dojox/form/nls/es/PasswordValidator.js
+++ b/dojox/form/nls/es/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Contraseña no válida.","nomatchMessage":"Las contraseñas no coinciden."})
\ No newline at end of file
+({
+        nomatchMessage: "Las contraseñas no coinciden.",
+		badPasswordMessage: "Contraseña no válida."
+})
+
diff --git a/dojox/form/nls/fi/PasswordValidator.js b/dojox/form/nls/fi/PasswordValidator.js
index 291e49c..f46212d 100644
--- a/dojox/form/nls/fi/PasswordValidator.js
+++ b/dojox/form/nls/fi/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Salasana ei kelpaa.","nomatchMessage":"Salasanat eivät täsmää."})
\ No newline at end of file
+({
+        nomatchMessage: "Salasanat eivät täsmää.",
+		badPasswordMessage: "Salasana ei kelpaa."
+})
+
diff --git a/dojox/form/nls/fr/PasswordValidator.js b/dojox/form/nls/fr/PasswordValidator.js
index 590cbce..a573834 100644
--- a/dojox/form/nls/fr/PasswordValidator.js
+++ b/dojox/form/nls/fr/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Mot de passe incorrect.","nomatchMessage":"Les mots de passe ne correspondent pas."})
\ No newline at end of file
+({
+        nomatchMessage: "Les mots de passe ne correspondent pas.",
+		badPasswordMessage: "Mot de passe incorrect."
+})
+
diff --git a/dojox/form/nls/he/PasswordValidator.js b/dojox/form/nls/he/PasswordValidator.js
index 4995881..6e6eae6 100644
--- a/dojox/form/nls/he/PasswordValidator.js
+++ b/dojox/form/nls/he/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"סיסמה לא חוקית.","nomatchMessage":"הסיסמאות אינן זהות."})
\ No newline at end of file
+({
+        nomatchMessage: "הסיסמאות אינן זהות.",
+		badPasswordMessage: "סיסמה לא חוקית."
+})
+
diff --git a/dojox/form/nls/hu/PasswordValidator.js b/dojox/form/nls/hu/PasswordValidator.js
index 1202b56..95d705c 100644
--- a/dojox/form/nls/hu/PasswordValidator.js
+++ b/dojox/form/nls/hu/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Érvénytelen jelszó.","nomatchMessage":"A jelszavak nem egyeznek."})
\ No newline at end of file
+({
+        nomatchMessage: "A jelszavak nem egyeznek.",
+		badPasswordMessage: "Érvénytelen jelszó."
+})
+
diff --git a/dojox/form/nls/it/PasswordValidator.js b/dojox/form/nls/it/PasswordValidator.js
index af224e4..1486b3d 100644
--- a/dojox/form/nls/it/PasswordValidator.js
+++ b/dojox/form/nls/it/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Password non valida.","nomatchMessage":"Le password non corrispondono."})
\ No newline at end of file
+({
+        nomatchMessage: "Le password non corrispondono.",
+		badPasswordMessage: "Password non valida."
+})
+
diff --git a/dojox/form/nls/ja/PasswordValidator.js b/dojox/form/nls/ja/PasswordValidator.js
index ac73c4b..890931e 100644
--- a/dojox/form/nls/ja/PasswordValidator.js
+++ b/dojox/form/nls/ja/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"無効なパスワードです。","nomatchMessage":"パスワードが一致しません。"})
\ No newline at end of file
+({
+        nomatchMessage: "パスワードが一致しません。",
+		badPasswordMessage: "無効なパスワードです。"
+})
+
diff --git a/dojox/form/nls/ko/PasswordValidator.js b/dojox/form/nls/ko/PasswordValidator.js
index 52ac9cc..fdc771d 100644
--- a/dojox/form/nls/ko/PasswordValidator.js
+++ b/dojox/form/nls/ko/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"비밀번호가 올바르지 않습니다.","nomatchMessage":"비밀번호가 일치하지 않습니다."})
\ No newline at end of file
+({
+        nomatchMessage: "비밀번호가 일치하지 않습니다.",
+		badPasswordMessage: "비밀번호가 올바르지 않습니다."
+})
+
diff --git a/dojox/form/nls/nb/PasswordValidator.js b/dojox/form/nls/nb/PasswordValidator.js
index 79ebab1..12d3ea6 100644
--- a/dojox/form/nls/nb/PasswordValidator.js
+++ b/dojox/form/nls/nb/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Ugyldig passord.","nomatchMessage":"Passordene samsvarer ikke."})
\ No newline at end of file
+({
+        nomatchMessage: "Passordene samsvarer ikke.",
+		badPasswordMessage: "Ugyldig passord."
+})
+
diff --git a/dojox/form/nls/nl/PasswordValidator.js b/dojox/form/nls/nl/PasswordValidator.js
index 27df062..075aca7 100644
--- a/dojox/form/nls/nl/PasswordValidator.js
+++ b/dojox/form/nls/nl/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Ongeldig wachtwoord. ","nomatchMessage":"Wachtwoorden komen niet overeen."})
\ No newline at end of file
+({
+        nomatchMessage: "Wachtwoorden komen niet overeen.",
+		badPasswordMessage: "Ongeldig wachtwoord. "
+})
+
diff --git a/dojox/form/nls/pl/PasswordValidator.js b/dojox/form/nls/pl/PasswordValidator.js
index d646c5d..0a0b136 100644
--- a/dojox/form/nls/pl/PasswordValidator.js
+++ b/dojox/form/nls/pl/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Niepoprawne hasło.","nomatchMessage":"Hasła nie są zgodne."})
\ No newline at end of file
+({
+        nomatchMessage: "Hasła nie są zgodne.",
+		badPasswordMessage: "Niepoprawne hasło."
+})
+
diff --git a/dojox/form/nls/pt-pt/PasswordValidator.js b/dojox/form/nls/pt-pt/PasswordValidator.js
index 4350e30..4ca422c 100644
--- a/dojox/form/nls/pt-pt/PasswordValidator.js
+++ b/dojox/form/nls/pt-pt/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Palavra-passe não válida.","nomatchMessage":"As palavras-passe não correspondem."})
\ No newline at end of file
+({
+        nomatchMessage: "As palavras-passe não correspondem.",
+		badPasswordMessage: "Palavra-passe não válida."
+})
+
diff --git a/dojox/form/nls/pt/PasswordValidator.js b/dojox/form/nls/pt/PasswordValidator.js
index e2184d6..102add5 100644
--- a/dojox/form/nls/pt/PasswordValidator.js
+++ b/dojox/form/nls/pt/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Senha Inválida.","nomatchMessage":"As senhas não correspondem."})
\ No newline at end of file
+({
+        nomatchMessage: "As senhas não correspondem.",
+		badPasswordMessage: "Senha Inválida."
+})
+
diff --git a/dojox/form/nls/ro/PasswordValidator.js b/dojox/form/nls/ro/PasswordValidator.js
new file mode 100644
index 0000000..5ac1688
--- /dev/null
+++ b/dojox/form/nls/ro/PasswordValidator.js
@@ -0,0 +1,5 @@
+({
+        nomatchMessage: "Parolele nu se potrivesc. ",
+		badPasswordMessage: "Parola nu este validă. "
+})
+
diff --git a/dojox/form/nls/ru/PasswordValidator.js b/dojox/form/nls/ru/PasswordValidator.js
index 8cf8df5..01ce959 100644
--- a/dojox/form/nls/ru/PasswordValidator.js
+++ b/dojox/form/nls/ru/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Неправильный пароль.","nomatchMessage":"Пароли не совпадают."})
\ No newline at end of file
+({
+        nomatchMessage: "Пароли не совпадают.",
+		badPasswordMessage: "Неправильный пароль."
+})
+
diff --git a/dojox/form/nls/sk/PasswordValidator.js b/dojox/form/nls/sk/PasswordValidator.js
index a4880b3..c3de5ef 100644
--- a/dojox/form/nls/sk/PasswordValidator.js
+++ b/dojox/form/nls/sk/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Neplatné heslo.","nomatchMessage":"Heslá sa nezhodujú."})
\ No newline at end of file
+({
+        nomatchMessage: "Heslá sa nezhodujú.",
+		badPasswordMessage: "Neplatné heslo."
+})
+
diff --git a/dojox/form/nls/sl/PasswordValidator.js b/dojox/form/nls/sl/PasswordValidator.js
index 4d8faba..5247524 100644
--- a/dojox/form/nls/sl/PasswordValidator.js
+++ b/dojox/form/nls/sl/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Neveljavno geslo.","nomatchMessage":"Gesli se ne ujemata."})
\ No newline at end of file
+({
+        nomatchMessage: "Gesli se ne ujemata.",
+		badPasswordMessage: "Neveljavno geslo."
+})
+
diff --git a/dojox/form/nls/sv/PasswordValidator.js b/dojox/form/nls/sv/PasswordValidator.js
index 1c3abd0..94e4e80 100644
--- a/dojox/form/nls/sv/PasswordValidator.js
+++ b/dojox/form/nls/sv/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Ogiltigt lösenord.","nomatchMessage":"Lösenorden stämmer inte överens."})
\ No newline at end of file
+({
+        nomatchMessage: "Lösenorden stämmer inte överens.",
+		badPasswordMessage: "Ogiltigt lösenord."
+})
+
diff --git a/dojox/form/nls/th/PasswordValidator.js b/dojox/form/nls/th/PasswordValidator.js
index e7371bf..6f7e2ad 100644
--- a/dojox/form/nls/th/PasswordValidator.js
+++ b/dojox/form/nls/th/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"รหัสผ่านไม่ถูกต้อง","nomatchMessage":"รหัสผ่านไม่ตรงกัน"})
\ No newline at end of file
+({
+        nomatchMessage: "รหัสผ่านไม่ตรงกัน",
+		badPasswordMessage: "รหัสผ่านไม่ถูกต้อง"
+})
+
diff --git a/dojox/form/nls/tr/PasswordValidator.js b/dojox/form/nls/tr/PasswordValidator.js
index 3e09bb0..f024ca8 100644
--- a/dojox/form/nls/tr/PasswordValidator.js
+++ b/dojox/form/nls/tr/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"Geçersiz Parola.","nomatchMessage":"Parolalar eşleşmiyor."})
\ No newline at end of file
+({
+        nomatchMessage: "Parolalar eşleşmiyor.",
+		badPasswordMessage: "Geçersiz Parola."
+})
+
diff --git a/dojox/form/nls/zh-tw/PasswordValidator.js b/dojox/form/nls/zh-tw/PasswordValidator.js
index 498f428..173d589 100644
--- a/dojox/form/nls/zh-tw/PasswordValidator.js
+++ b/dojox/form/nls/zh-tw/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"無效的密碼。","nomatchMessage":"密碼不符合。"})
\ No newline at end of file
+({
+        nomatchMessage: "密碼不符合。",
+		badPasswordMessage: "無效的密碼。"
+})
+
diff --git a/dojox/form/nls/zh/PasswordValidator.js b/dojox/form/nls/zh/PasswordValidator.js
index 433aa7a..42acd78 100644
--- a/dojox/form/nls/zh/PasswordValidator.js
+++ b/dojox/form/nls/zh/PasswordValidator.js
@@ -1 +1,5 @@
-({"badPasswordMessage":"密码无效。","nomatchMessage":"密码不匹配。"})
\ No newline at end of file
+({
+        nomatchMessage: "密码不匹配。",
+		badPasswordMessage: "密码无效。"
+})
+
diff --git a/dojox/form/resources/BusyButton.css b/dojox/form/resources/BusyButton.css
index 668ee5c..c4be3ee 100644
--- a/dojox/form/resources/BusyButton.css
+++ b/dojox/form/resources/BusyButton.css
@@ -1,4 +1,8 @@
-
+/*
+**----------------------------------------------------------------------------
+**  BusyButton
+**----------------------------------------------------------------------------
+*/
 .dojoxBusyButtonIcon {
 	width: 10px;
 	height: 10px;
@@ -6,4 +10,4 @@
 	margin-left: 4px;
 	background-image: url('images/loading_wheel.gif');
 	background-repeat: no-repeat;
-}
+}
\ No newline at end of file
diff --git a/dojox/form/resources/CheckedMultiSelect.css b/dojox/form/resources/CheckedMultiSelect.css
index 7a1464e..311f8f0 100644
--- a/dojox/form/resources/CheckedMultiSelect.css
+++ b/dojox/form/resources/CheckedMultiSelect.css
@@ -1,5 +1,10 @@
-
+/*
+**----------------------------------------------------------------------------
+**  CheckedMultiSelect
+**----------------------------------------------------------------------------
+*/
 .dojoxMultiSelectSelect { display: none; }
+
 .dojoxMultiSelect {
 	border: solid black 1px;
 	margin: 1px 0;
@@ -8,59 +13,118 @@
 	overflow-x: hidden; 
 	height: 100px;
 }
+
 .dj_ie .dojoxMultiSelect,
 .dj_webkit .dojoxMultiSelect {
-	
+	/* So that the scroll bar doesn't cover stuff up */
 	padding-right: 15px;
 }
+
 .dojoxMultiSelectItem {
 	white-space: nowrap;
 	padding:.1em .2em;
 	cursor:default;
 }
+
 .dojoxMultiSelectDisabled *,
 .dojoxMultiSelectReadOnly * {
 	color:gray !important;
 }
+
 .dojoxMultiSelectItemLabel {
 	margin-left: .2em;
 }
+
+/*
+**----------------------------------------------------------------------------
+**  Tundra theme (make look similar to text box)
+**----------------------------------------------------------------------------
+*/
 .tundra .dojoxMultiSelect {
 	margin: 0em 0.1em;
 }
+
 .tundra .dojoxMultiSelect {
 	background:#fff url("../../../dijit/themes/tundra/images/validationInputBg.png") repeat-x top left;
 	#background:#fff url('../../../dijit/themes/tundra/images/validationInputBg.gif') repeat-x top left;
 	border:1px solid #b3b3b3;
 	line-height: normal;
 }
+
 .tundra .dojoxMultiSelectFocused {
-	
+	/* input field when focused (ie: typing affects it) */
 	border-color:#406b9b;
 }
+
+/*
+**----------------------------------------------------------------------------
+**  Soria theme (make look similar to text box)
+**----------------------------------------------------------------------------
+*/
 .soria .dojoxMultiSelect {
 	margin: 0em 0.1em;
 }
+
 .soria .dojoxMultiSelect {
 	background:#fff url("../../../dijit/themes/soria/images/validationInputBg.png") repeat-x top left;
 	#background:#fff url('../../../dijit/themes/soria/images/validationInputBg.gif') repeat-x top left;
 	border:1px solid #8ba0bd;
 	line-height: normal;
 }
+
 .soria .dojoxMultiSelectFocused {
-	
+	/* input field when focused (ie: typing affects it) */
 	border-color:#406b9b;
 }
+
+/*
+**----------------------------------------------------------------------------
+**  Nihilo theme (make look similar to text box)
+**----------------------------------------------------------------------------
+*/
 .nihilo .dojoxMultiSelect {
 	margin: 0em 0.1em;
 }
+
 .nihilo .dojoxMultiSelect {
 	background:#fff url("../../../dijit/themes/nihilo/images/validationInputBg.png") repeat-x top left;
 	#background:#fff url('../../../dijit/themes/nihilo/images/validationInputBg.gif') repeat-x top left;
 	border:1px solid #d3d3d3;
 	line-height: normal;
 }
+
 .nihilo .dojoxMultiSelectFocused {
-	
+	/* input field when focused (ie: typing affects it) */
 	border-color:#b3b3b3;
 }
+
+/*
+**----------------------------------------------------------------------------
+**  Claro theme (make look similar to text box)
+**----------------------------------------------------------------------------
+*/
+
+.claro .dojoxMultiSelect {
+	margin: 0em 0.1em;
+}
+
+.claro .dojoxMultiSelect {
+	border: 1px solid #b5bcc7;
+	background-color: #f7fcff;
+	line-height: normal;
+	-webkit-transition-property:background-color, border;
+ 	-webkit-transition-duration:.35s;
+}
+
+.claro .dojoxMultiSelectHover {
+	border-color: #769dc0;
+	background-color: #e9f4fe;
+	background-image: url('../../../dijit/themes/claro/form/images/textBox_back.png');
+	background-repeat: repeat-x;
+	-webkit-transition-duration:.25s;
+}
+
+.claro .dojoxMultiSelectFocused {
+	border: 1px solid #769dc0;
+	-webkit-transition-duration:.1s;
+}
diff --git a/dojox/form/resources/CheckedMultiSelect.html b/dojox/form/resources/CheckedMultiSelect.html
index 4144d82..c7b66dc 100644
--- a/dojox/form/resources/CheckedMultiSelect.html
+++ b/dojox/form/resources/CheckedMultiSelect.html
@@ -1,4 +1,4 @@
-<div class="dijit dijitReset dijitInline" dojoAttachEvent="onmousedown:_mouseDown,onclick:focus"
+<div class="dijit dijitReset dijitInline" dojoAttachEvent="onmousedown:_onMouseDown,onclick:focus"
 	><select class="${baseClass}Select" multiple="true" dojoAttachPoint="containerNode,focusNode"></select
 	><div dojoAttachPoint="wrapperDiv"></div
 ></div>
\ No newline at end of file
diff --git a/dojox/form/resources/FileInput.css b/dojox/form/resources/FileInput.css
index ffe477a..f9865f8 100644
--- a/dojox/form/resources/FileInput.css
+++ b/dojox/form/resources/FileInput.css
@@ -1,8 +1,9 @@
 .dijitFileInput {
 	position:relative;
 	height:1.3em;
-	
+	/*padding:2px;*/
 }
+
 .dijitFileInputReal {
 	position:absolute;
 	z-index:2;
@@ -14,17 +15,20 @@
 	right:0;
 }
 .dijitFileInputReal:hover { cursor:pointer; } 
+
 .dijitFileInputButton,
 .dijitFileInputText {
 	border:1px solid #333;
 	padding:2px 12px 2px 12px; 
 	cursor:pointer;
 }
+
 .dijitFileInputButton {
 	z-index:3;
 	visibility:hidden;
 }
 .dijitFakeInput { position:absolute; top:0; left:0; z-index:1; white-space: nowrap; }
+
 .dijitProgressOverlay {
 	display:none;
 	width:250px;
@@ -35,12 +39,14 @@
 	background:#cad2de url('../../../dijit/themes/tundra/images/dijitProgressBarAnim.gif') repeat-x top left;
 	padding:2px;	
 }
+
+/* tundra */
 .tundra .dijitProgressOverlay {
 	border:1px solid #84a3d1;
 	background-color:#cad2de;
 }
 .tundra .dijitFakeInput input {
-	
+	/*font-size: inherit;*/
 	padding: 0;
 	background:#fff url("../../../dijit/themes/tundra/images/validationInputBg.png") repeat-x top left;
 	border:1px solid #9b9b9b;
@@ -49,9 +55,11 @@
 .tundra .dijitFileInputButton, 
 .tundra .dijitFileInputText {
 	border:1px solid #9b9b9b;
-	padding:0px 12px 0px 12px; 
+	padding:0px 12px 0px 12px; /* .3em .4em .2em .4em; */
 	background:#e9e9e9 url("../../../dijit/themes/tundra/images/buttonEnabled.png") repeat-x top;
 }
+
+/* Soria */
 .soria .dijitProgressOverlay {
 	border:1px solid #8BA0BD;
 	background-color:#cad2de; 
@@ -69,6 +77,8 @@
 	padding:2px 12px 2px 12px;
 	background:#b7cdee url('../../../dijit/themes/soria/images/buttonEnabled.png') repeat-x; 
 }
+
+/* Nihilo */
 .nihilo .dijitProgressOverlay {
 	border:1px solid #DEDEDE;
 	background-color:#cad2de; 
@@ -86,3 +96,33 @@
 	padding:2px 12px 2px 12px;
 	background:#b7cdee url('../../../dijit/themes/nihilo/images/buttonEnabled.png') repeat-x; 
 }
+
+/* Claro */
+.claro .dijitProgressOverlay {
+	border:1px solid #769dc0;
+	background-color:#769dc0; 
+}
+.claro .dijitFakeInput input {
+	border: 1px solid #bcc8dd;
+	background-color: #fff;
+	background-repeat: repeat-x;
+	background-position: top left;
+	background-image:url("../../../dijit/themes/claro/images/textBox_back.png");
+	line-height:normal;
+	padding:0.2em 0.3em;
+}
+
+.claro .dijitFileInputButton,
+.claro .dijitFileInputText {
+	background-image: url("../../../dijit/themes/claro/form/images/button_back_full.png");
+	background-position: center top;
+	background-repeat: repeat-x;
+	background-color: #cde3f6;
+	border: 1px solid #799ab7;
+	border-radius: 4px;
+	-moz-border-radius: 4px;
+	-webkit-border-radius: 4px;
+	box-shadow:0px 1px 1px rgba(0,0,0,0.2);
+	-webkit-box-shadow:0px 1px 1px rgba(0,0,0,0.2);
+	-moz-box-shadow: 0px 1px 1px rgba(0,0,0,0.2);
+}
diff --git a/dojox/form/resources/FilePickerTextBox.css b/dojox/form/resources/FilePickerTextBox.css
index f63c8a0..17ff8aa 100644
--- a/dojox/form/resources/FilePickerTextBox.css
+++ b/dojox/form/resources/FilePickerTextBox.css
@@ -1,210 +1,5 @@
-.dojoxRollingList {
-	border: 1px solid #000;
-	height: 20em;
-	background-color: #FFF;
-	position: relative;
-}
-.dijitPopup .dojoxRollingList {
-	position: static;
-}
-.dojoxRollingListContainer {
-	overflow: scroll;
-	overflow-y: hidden;
-	overflow-x: scroll;
-	white-space: nowrap;
-}
-.dojoxRollingListButtons {
-	position: absolute;
-	right: 5px;
-	padding: 5px 0px;
-}
-.dojoxRollingListButtonsHidden .dojoxRollingListButtons {
-	display: none;
-}
-.dojoxRollingListPane {
-	overflow: scroll;
-	overflow-x: hidden;
-	overflow-y: scroll;
-	display:-moz-inline-box;		
-	display:inline-block;			
-	#zoom: 1; 
-	#display:inline; 
-	border:0;
-	padding:0;
-	vertical-align:middle;
-	#vertical-align: auto;	
-}
-.dojoxRollingListPane .dijitMenuItem td {
-	width: 1px;
-}
-.dojoxRollingListPane .dijitMenuItem td.dijitMenuItemLabel {
-	width: auto;
-}
-.dojoxRollingListPane .dijitMenuItemLabel,
-.dojoxRollingListPane .dijitMenuItemIcon {
-	position: static !important;
-}
-.dj_webkit .dojoxRollingListPane,
-.dj_ie .dojoxRollingListPane {
-	padding-right: 15px; 
-}
-.dojoxRollingListPane .dijitMenu {
-	border: none !important;
-}
-.dojoxRollingListItem {
-	cursor: default;
-}
-.tundra .dojoxRollingList {
-	border-color: #b3b3b3;
-}
-.tundra .dijitPopup .dojoxRollingList {
-	border-color: #406b9b;
-}
-.tundra .dojoxRollingListPane {
-	background-color: #f7f7f7;
-}
-.tundra .dojoxRollingListPane .dojoxRollingListItemHover,
-.tundra .dojoxRollingListPane .dojoxRollingListItemFocus {
-	background-color: #e3e3e3;
-}
-.tundra .dojoxRollingListPane .dojoxRollingListItemSelected {
-	color: #fff;
-	background-color: #999;
-	font-weight: bold;
-}
-.tundra .dojoxRollingListPaneCurrentSelected .dojoxRollingListItemSelected {
-	background-color: #3559ac;
-}
-.tundra .dojoxRollingListPane .dojoxRollingListItemHoverSelected,
-.tundra .dojoxRollingListPane .dojoxRollingListItemFocusSelected {
-	background-color: #9aacd6;
-}
-.tundra .dojoxRollingListItem {
-	font-family: inherit;
-}
-.soria .dojoxRollingList {
-	border-color: #8ba0bd;
-}
-.soria .dijitPopup .dojoxRollingList {
-	border-color: #406b9b;
-}
-.soria .dojoxRollingListPane {
-	background-color: #fff;
-}
-.soria .dojoxRollingListPane .dojoxRollingListItemHover, 
-.soria .dojoxRollingListPane .dojoxRollingListItemFocus {
-	background-color: #e3e3e3;
-}
-.soria .dojoxRollingListPane .dojoxRollingListItemSelected {
-	color: #243C5F;
-	background-color: #ccc;
-	font-weight: bold;
-}
-.soria .dojoxRollingListPaneCurrentSelected .dojoxRollingListItemSelected {
-	background-color: #d9e6f9;
-}
-.soria .dojoxRollingListPane .dojoxRollingListItemHoverSelected,
-.soria .dojoxRollingListPane .dojoxRollingListItemFocusSelected {
-	background-color: #ecf3fc;
-}
-.soria .dojoxRollingListItem {
-	font-family: inherit;
-}
-.nihilo .dojoxRollingList {
-	border-color: #d3d3d3;
-}
-.nihilo .dijitPopup .dojoxRollingList {
-	border-color: #b3b3b3;
-}
-.nihilo .dojoxRollingListPane {
-	background-color: #fff;
-}
-.nihilo .dojoxRollingListPane .dojoxRollingListItemHover,
-.nihilo .dojoxRollingListPane .dojoxRollingListItemFocus {
-	background-color: #e3e3e3;
-}
-.nihilo .dojoxRollingListPane .dojoxRollingListItemSelected {
-	color: #243C5F;
-	background-color: #ccc;
-	font-weight: bold;
-}
-.nihilo .dojoxRollingListPaneCurrentSelected .dojoxRollingListItemSelected {
-	background-color: #ffe284;
-}
-.nihilo .dojoxRollingListPane .dojoxRollingListItemHoverSelected,
-.nihilo .dojoxRollingListPane .dojoxRollingListItemFocusSelected {
-	background-color: #fff1c2;
-}
-.nihilo .dojoxRollingListItem {
-	font-family: inherit;
-}
-.dojoxFileInfoPane *{
-	white-space: normal;
-}
-.dojoxFileInfoLabel {
-	font-weight: bold;
-	white-space: nowrap;
-}
-.dojoxFileInfoPane {
-	width: 20em;
-}
-.tundra .dojoxFilePickerItem .dijitMenuItemIcon {
-	background-image: url(../../widget/FilePicker/images/tundraFileIcons.gif);
-	background-repeat: no-repeat;
-}
-.tundra .dojoxFilePickerItem .dojoxEmpty {
-	background-image: none;
-}
-.tundra .dojoxFilePickerItem .dojoxDirectoryItemIcon {
-	background-position: 0px;
-}
-.tundra .dojoxFilePickerItemSelected .dojoxDirectoryItemIcon {
-	background-position: -16px;
-}
-.tundra .dojoxFilePickerItem .dojoxFileItemIcon {
-	background-position: -32px;
-}
-.tundra .dojoxFilePickerItemSelected .dojoxFileItemIcon {
-	background-position: -48px;
-}
-.soria .dojoxFilePickerItem .dijitMenuItemIcon {
-	background-image: url(../../widget/FilePicker/images/soriaFileIcons.gif);
-	background-repeat: no-repeat;
-}
-.soria .dojoxFilePickerItem .dojoxEmpty {
-	background-image: none;
-}
-.soria .dojoxFilePickerItem .dojoxDirectoryItemIcon {
-	background-position: 0px;
-}
-.soria .dojoxFilePickerItemSelected .dojoxDirectoryItemIcon {
-	background-position: -16px;
-}
-.soria .dojoxFilePickerItem .dojoxFileItemIcon {
-	background-position: -32px;
-}
-.soria .dojoxFilePickerItemSelected .dojoxFileItemIcon {
-	background-position: -48px;
-}
-.nihilo .dojoxFilePickerItem .dijitMenuItemIcon {
-	background-image: url(../../widget/FilePicker/images/nihiloFileIcons.gif);
-	background-repeat: no-repeat;
-}
-.nihilo .dojoxFilePickerItem .dojoxEmpty {
-	background-image: none;
-}
-.nihilo .dojoxFilePickerItem .dojoxDirectoryItemIcon {
-	background-position: 0px;
-}
-.nihilo .dojoxFilePickerItemSelected .dojoxDirectoryItemIcon {
-	background-position: -16px;
-}
-.nihilo .dojoxFilePickerItem .dojoxFileItemIcon {
-	background-position: -32px;
-}
-.nihilo .dojoxFilePickerItemSelected .dojoxFileItemIcon {
-	background-position: -48px;
-}
+ at import url("../../widget/FilePicker/FilePicker.css");
+
 .dojoxFilePickerTextBox{
 	width: 30em;
 	vertical-align: middle;
@@ -231,6 +26,8 @@
 	border-right-width:1px !important;
 	border-left-width:0 !important;
 }
+
+/* Tundra stylings */
 .tundra .dojoxFilePickerTextBoxDisabled *
 {
 	cursor: not-allowed !important;
@@ -299,6 +96,7 @@
 .tundra .dojoxFilePickerTextBox .dojoxHasDropDownOpen .dijitArrowButtonInner {
 	background-position: -16px;
 }
+
 .tundra .dojoxFilePickerTextBoxError {
 	background-color:#f9f7ba;
 	background-image:none;
@@ -313,6 +111,8 @@
 .dj_ie6 .tundra .dojoxFilePickerTextBoxErrorFocused INPUT {
 	background-color:#f9f999 !important;
 }
+
+/* nihilo theme */
 .nihilo .dojoxFilePickerTextBoxDisabled *
 {
 	cursor: not-allowed !important;
@@ -381,6 +181,7 @@
 .dj_ie6 .nihilo .dojoxFilePickerTextBoxError INPUT {
 	background-color:#f9f7ba !important;
 }
+
 .nihilo .dojoxFilePickerTextBoxErrorFocused {
 	background-color:#ff6;
 	background-image:none;
@@ -388,6 +189,8 @@
 .dj_ie6 .nihilo .dojoxFilePickerTextBoxErrorFocused INPUT {
 	background-color:#ff6 !important;
 }
+
+/* soria theme */
 .soria .dojoxFilePickerTextBoxDisabled *
 {
 	cursor: not-allowed !important;
@@ -431,7 +234,7 @@
 .soria .dojoxFilePickerTextBoxDisabled{
 	border-color: #b9bbdd #b9bbdd #b9bbdd #b9bbdd;
 	background:#c3d3e5 url("../../../dijit/themes/soria/buttonDisabled.png") top repeat-x;
-	opacity: 0.60; 
+	opacity: 0.60; /* Safari, Opera and Mozilla */
 }
 .soria .dojoxFilePickerTextBoxHover .dijitDownArrowButton{
 	color:#000;
@@ -459,6 +262,7 @@
 .dj_ie6 .soria .dojoxFilePickerTextBoxError INPUT {
 	background-color:#f9f7ba !important;
 }
+
 .soria .dojoxFilePickerTextBoxErrorFocused {
 	background-color:#ff6;
 	background-image:none;
diff --git a/dojox/form/resources/FilePickerTextBox.html b/dojox/form/resources/FilePickerTextBox.html
index e86b9d8..e2a0f00 100644
--- a/dojox/form/resources/FilePickerTextBox.html
+++ b/dojox/form/resources/FilePickerTextBox.html
@@ -1,6 +1,6 @@
 <div class="dijit dijitReset dijitInlineTable dijitLeft"
 	id="widget_${id}"
-	dojoAttachEvent="onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse" waiRole="combobox" tabIndex="-1"
+	waiRole="combobox" tabIndex="-1"
 	><div style="overflow:hidden;"
 		><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton'
 			dojoAttachPoint="downArrowNode,_buttonNode,_popupStateNode" waiRole="presentation"
@@ -10,7 +10,7 @@
 		><div class="dijitReset dijitValidationIcon"><br></div
 		><div class="dijitReset dijitValidationIconText">Χ</div
 		><div class="dijitReset dijitInputField"
-			><input type="text" autocomplete="off" ${nameAttrSetting} class='dijitReset'
+			><input type="text" autocomplete="off" ${!nameAttrSetting} class='dijitReset'
 				dojoAttachEvent='onkeypress:_onKey' 
 				dojoAttachPoint='textbox,focusNode' waiRole="textbox" waiState="haspopup-true,autocomplete-list"
 		/></div
diff --git a/dojox/form/resources/FileUploader.css b/dojox/form/resources/FileUploader.css
index 4d071af..2d268b4 100644
--- a/dojox/form/resources/FileUploader.css
+++ b/dojox/form/resources/FileUploader.css
@@ -15,6 +15,7 @@
 	
 	cursor: pointer;
 }
+
 .uploaderInsideNode{
 	visibility:hidden;
 }
@@ -33,6 +34,8 @@
 	border-color: #d5d5d5 #d5d5d5 #bdbdbd #d5d5d5; 
 	background:#e4e4e4 url("../../../dijit/themes/tundra/images/buttonDisabled.png") top repeat-x;
 }
+
+
 .soria .dojoxUploaderNorm {
 	border: 1px solid #8ba0bd;
 	border-bottom:1px solid #657c9c;
@@ -52,6 +55,8 @@
 	background:#c3d3e5 url("../../../dijit/themes/soria/images/buttonDisabled.png") top repeat-x !important;
 	opacity: 0.60;
 }
+
+
 .nihilo .dojoxUploaderNorm {
 	border:1px solid #dedede;
 	border-bottom:1px solid #dedede;
@@ -71,26 +76,7 @@
 	background:#fafafa url("../../../dijit/themes/nihilo/images/buttonDisabled.png") top repeat-x !important;
 	opacity: 0.60;
 }
-.noir .dojoxUploaderNorm {
-	vertical-align:top;
-	height:30px;
-	font-family:inherit;
-	font-size:inherit;
-	background-color:transparent;
-	background-image:none;
-	padding:0px !important;
-	line-height:25px;	
-	color:#cccccc;
-}
-.noir .dojoxUploaderHover{
-	color:#fa4242;
-}
-.noir .dojoxUploaderActive{
-	color:#31d397;
-}
-.noir .dojoxUploaderDisabled{
-	color:#3f3f3f;
-}
+
 .fileToUpload,
 .fileToUploadClose,
 .fileToUploadName,
@@ -98,6 +84,7 @@
 	height:18px;
 	line-height:18px;
 }
+
 .fileToUpload{
 	font-size:12px;
 	font-family:sans-serif;
@@ -124,6 +111,8 @@
 .fileToUploadClose:hover{
 	background:url(../../../dijit/themes/tundra/images/tabCloseHover.png) no-repeat 2px center;
 }
+
+
 .thumb{
 	height:50px;
 	padding:3px;
@@ -149,6 +138,7 @@
 	font-size:10px;
 }
 .dj_ie object{
-	
+	/* When clicking on the object inspector in Firebug Lite, IE
+	sets display:none on (flash) objects. Amazing!! */
 	display:block !important;
-}
+}
\ No newline at end of file
diff --git a/dojox/form/resources/HorizontalRangeSlider.html b/dojox/form/resources/HorizontalRangeSlider.html
index 32c0532..6d66db6 100644
--- a/dojox/form/resources/HorizontalRangeSlider.html
+++ b/dojox/form/resources/HorizontalRangeSlider.html
@@ -1,39 +1,39 @@
-<table class="dijit dijitReset dijitSlider dojoxRangeSlider" cellspacing="0" cellpadding="0" border="0" rules="none"
-    ><tr class="dijitReset"
-        ><td class="dijitReset" colspan="2"></td
-        ><td dojoAttachPoint="containerNode,topDecoration" class="dijitReset" style="text-align:center;width:100%;"></td
-        ><td class="dijitReset" colspan="2"></td
-    ></tr
-    ><tr class="dijitReset"
-        ><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH"
-            ><div class="dijitSliderDecrementIconH" tabIndex="-1" style="display:none" dojoAttachPoint="decrementButton" dojoAttachEvent="onclick: decrement"><span class="dijitSliderButtonInner">-</span></div
-        ></td
-        ><td class="dijitReset"
-            ><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderLeftBumper dijitSliderLeftBumperH" dojoAttachEvent="onclick:_onClkDecBumper"></div
-        ></td
-        ><td class="dijitReset"
-            ><input dojoAttachPoint="valueNode" type="hidden" name="${name}"
-            /><div waiRole="presentation" class="dojoxRangeSliderBarContainer" dojoAttachPoint="sliderBarContainer"
-                ><div dojoAttachPoint="sliderHandle" tabIndex="${tabIndex}" class="dijitSliderMoveable" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onHandleClick" waiRole="slider" valuemin="${minimum}" valuemax="${maximum}"
-                    ><div class="dijitSliderImageHandle dijitSliderImageHandleH"></div
-                ></div
-                ><div waiRole="presentation" dojoAttachPoint="progressBar,focusNode" class="dijitSliderBar dijitSliderBarH dijitSliderProgressBar dijitSliderProgressBarH" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onBarClick"></div
-                ><div dojoAttachPoint="sliderHandleMax,focusNodeMax" tabIndex="${tabIndex}" class="dijitSliderMoveable" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onHandleClickMax" waiRole="sliderMax" valuemin="${minimum}" valuemax="${maximum}"
-                    ><div class="dijitSliderImageHandle dijitSliderImageHandleH"></div
-                ></div
-                ><div waiRole="presentation" dojoAttachPoint="remainingBar" class="dijitSliderBar dijitSliderBarH dijitSliderRemainingBar dijitSliderRemainingBarH" dojoAttachEvent="onmousedown:_onRemainingBarClick"></div
-            ></div
-        ></td
-        ><td class="dijitReset"
-            ><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderRightBumper dijitSliderRightBumperH" dojoAttachEvent="onclick:_onClkIncBumper"></div
-        ></td
-        ><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH"
-            ><div class="dijitSliderIncrementIconH" tabIndex="-1" style="display:none" dojoAttachPoint="incrementButton" dojoAttachEvent="onclick: increment"><span class="dijitSliderButtonInner">+</span></div
-        ></td
-    ></tr
-    ><tr class="dijitReset"
-        ><td class="dijitReset" colspan="2"></td
-        ><td dojoAttachPoint="containerNode,bottomDecoration" class="dijitReset" style="text-align:center;"></td
-        ><td class="dijitReset" colspan="2"></td
-    ></tr
+<table class="dijit dijitReset dijitSlider dijitSliderH dojoxRangeSlider" cellspacing="0" cellpadding="0" border="0" rules="none" dojoAttachEvent="onkeypress:_onKeyPress,onkeyup:_onKeyUp"
+	><tr class="dijitReset"
+		><td class="dijitReset" colspan="2"></td
+		><td dojoAttachPoint="topDecoration" class="dijitReset dijitSliderDecoration dijitSliderDecorationT dijitSliderDecorationH"></td
+		><td class="dijitReset" colspan="2"></td
+	></tr
+	><tr class="dijitReset"
+		><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH"
+			><div class="dijitSliderDecrementIconH" tabIndex="-1" style="display:none" dojoAttachPoint="decrementButton"><span class="dijitSliderButtonInner">-</span></div
+		></td
+		><td class="dijitReset"
+			><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderLeftBumper" dojoAttachEvent="onmousedown:_onClkDecBumper"></div
+		></td
+		><td class="dijitReset"
+			><input dojoAttachPoint="valueNode" type="hidden" ${!nameAttrSetting}
+			/><div waiRole="presentation" class="dojoxRangeSliderBarContainer" dojoAttachPoint="sliderBarContainer"
+				><div dojoAttachPoint="sliderHandle" tabIndex="${tabIndex}" class="dijitSliderMoveable dijitSliderMoveableH" dojoAttachEvent="onmousedown:_onHandleClick" waiRole="slider" valuemin="${minimum}" valuemax="${maximum}"
+					><div class="dijitSliderImageHandle dijitSliderImageHandleH"></div
+				></div
+				><div waiRole="presentation" dojoAttachPoint="progressBar,focusNode" class="dijitSliderBar dijitSliderBarH dijitSliderProgressBar dijitSliderProgressBarH" dojoAttachEvent="onmousedown:_onBarClick"></div
+				><div dojoAttachPoint="sliderHandleMax,focusNodeMax" tabIndex="${tabIndex}" class="dijitSliderMoveable dijitSliderMoveableH" dojoAttachEvent="onmousedown:_onHandleClickMax" waiRole="sliderMax" valuemin="${minimum}" valuemax="${maximum}"
+					><div class="dijitSliderImageHandle dijitSliderImageHandleH"></div
+				></div
+				><div waiRole="presentation" dojoAttachPoint="remainingBar" class="dijitSliderBar dijitSliderBarH dijitSliderRemainingBar dijitSliderRemainingBarH" dojoAttachEvent="onmousedown:_onRemainingBarClick"></div
+			></div
+		></td
+		><td class="dijitReset"
+			><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderRightBumper" dojoAttachEvent="onmousedown:_onClkIncBumper"></div
+		></td
+		><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH"
+			><div class="dijitSliderIncrementIconH" tabIndex="-1" style="display:none" dojoAttachPoint="incrementButton"><span class="dijitSliderButtonInner">+</span></div
+		></td
+	></tr
+	><tr class="dijitReset"
+		><td class="dijitReset" colspan="2"></td
+		><td dojoAttachPoint="containerNode,bottomDecoration" class="dijitReset dijitSliderDecoration dijitSliderDecorationB dijitSliderDecorationH"></td
+		><td class="dijitReset" colspan="2"></td
+	></tr
 ></table>
diff --git a/dojox/form/resources/ListInput.css b/dojox/form/resources/ListInput.css
old mode 100644
new mode 100755
index 4d96bb0..5f4a83b
--- a/dojox/form/resources/ListInput.css
+++ b/dojox/form/resources/ListInput.css
@@ -54,6 +54,7 @@
 }
 .dojoxListInput .dijitTextBox {
 	background:#efefef !important;
+
 	border:0 !important;
 }
 .dojoxListInputFocused .dijitTextBox {
diff --git a/dojox/form/resources/RangeSlider.css b/dojox/form/resources/RangeSlider.css
index 12b6da9..5914467 100644
--- a/dojox/form/resources/RangeSlider.css
+++ b/dojox/form/resources/RangeSlider.css
@@ -1,18 +1,30 @@
-.dojoxRangeSlider .dijitSliderLeftBumperH, .dojoxRangeSlider .dijitSliderBottomBumperV  {
+.dojoxRangeSlider .dijitSliderLeftBumper, .dojoxRangeSlider .dijitSliderBottomBumper  {
     background:#FFFFFF !important;
 }
+
 .dojoxRangeSliderBarContainer {
     position:relative;
 }
+
 .dojoxRangeSlider .dijitSliderProgressBarV {
     position:relative !important;
 }
+
 .dojoxRangeSlider .dijitSliderProgressBar {
     overflow:hidden;
     cursor:pointer;
-    
+    /* background:yellow !important; */
 }
+
 .dojoxRangeSlider .dijitSliderProgressBarV {
     position:absolute !important;
     border-width: 0px;
 }
+
+.dojoxRangeSlider .dijitSliderImageHandleH {
+	left: -50%;
+}
+.dijitSlider .dojoxRangeSliderBarContainer .dijitSliderProgressBarH,
+.dojoxRangeSlider .dijitSliderMoveableH {
+        right:auto !important;
+}
diff --git a/dojox/form/resources/Rating.css b/dojox/form/resources/Rating.css
index fb190e7..1f2054f 100644
--- a/dojox/form/resources/Rating.css
+++ b/dojox/form/resources/Rating.css
@@ -2,6 +2,7 @@
 	padding:0;
 	margin:0;
 }
+
 .dojoxRatingStar {
 	display:inline-block;
 	background-image:url(images/rating_empty.gif);
@@ -11,10 +12,13 @@
 	width:15px;
 	float:left;
 }
+
 .dojoxRatingStarChecked {
 	background-image:url(images/rating_full.gif);
 }
+
 .dojoxRatingStarHover {
 	background-image:url(images/rating_full.gif);
 	opacity:.5;
 }
+
diff --git a/dojox/form/resources/RecieveFile.php b/dojox/form/resources/RecieveFile.php
new file mode 100644
index 0000000..aca541f
--- /dev/null
+++ b/dojox/form/resources/RecieveFile.php
@@ -0,0 +1,37 @@
+<?php
+
+// THIS IS AN EXAMPLE
+// you will obviously need to do more server side work than I am doing here to check and move your upload.
+// API is up for discussion, jump on http://dojotoolkit.org/forums
+
+// JSON.php is available in dojo svn checkout
+require("../../../dojo/tests/resources/JSON.php");
+$json = new Services_JSON();
+
+// fake delay
+sleep(3);
+$name = empty($_REQUEST['name'])? "default" : $_REQUEST['name'];
+if(is_array($_FILES)){
+	$ar = array(
+		// lets just pass lots of stuff back and see what we find.
+		// the _FILES aren't coming through in IE6 (maybe 7)
+		'status' => "success",
+		'name' => $name,
+		'request' => $_REQUEST,
+		'postvars' => $_POST,
+		'details' => $_FILES,
+		// and some static subarray just to see
+		'foo' => array('foo'=>"bar")
+	);
+
+}else{
+	$ar = array(
+		'status' => "failed",
+		'details' => ""
+	);
+}
+
+// yeah, seems you have to wrap iframeIO stuff in textareas?
+$foo = $json->encode($ar);
+?>
+<textarea><?php print $foo; ?></textarea>
diff --git a/dojox/form/resources/VerticalRangeSlider.html b/dojox/form/resources/VerticalRangeSlider.html
index 777380c..24791bb 100644
--- a/dojox/form/resources/VerticalRangeSlider.html
+++ b/dojox/form/resources/VerticalRangeSlider.html
@@ -1,50 +1,49 @@
-<table class="dijitReset dijitSlider dojoxRangeSlider" cellspacing="0" cellpadding="0" border="0" rules="none"
-><tbody class="dijitReset"
-    ><tr class="dijitReset"
-        ><td class="dijitReset"></td
-        ><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV"
-            ><div class="dijitSliderIncrementIconV" tabIndex="-1" style="display:none" dojoAttachPoint="incrementButton" dojoAttachEvent="onclick: increment"><span class="dijitSliderButtonInner">+</span></div
-        ></td
-        ><td class="dijitReset"></td
-    ></tr
-    ><tr class="dijitReset"
-        ><td class="dijitReset"></td
-        ><td class="dijitReset"
-            ><center><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperV dijitSliderTopBumper dijitSliderTopBumperV" dojoAttachEvent="onclick:_onClkIncBumper"></div></center
-        ></td
-        ><td class="dijitReset"></td
-    ></tr
-    ><tr class="dijitReset"
-        ><td dojoAttachPoint="leftDecoration" class="dijitReset" style="text-align:center;height:100%;"></td
-        ><td class="dijitReset" style="height:100%;"
-            ><input dojoAttachPoint="valueNode" type="hidden" name="${name}"
-            /><center waiRole="presentation" style="position:relative;height:100%;" dojoAttachPoint="sliderBarContainer"
-                ><div waiRole="presentation" dojoAttachPoint="remainingBar" class="dijitSliderBar dijitSliderBarV dijitSliderRemainingBar dijitSliderRemainingBarV" dojoAttachEvent="onmousedown:_onRemainingBarClick"
-                    ><div dojoAttachPoint="sliderHandle" tabIndex="${tabIndex}" class="dijitSliderMoveable" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onHandleClick" style="vertical-align:top;" waiRole="slider" valuemin="${minimum}" valuemax="${maximum}"
-                        ><div class="dijitSliderImageHandle dijitSliderImageHandleV"></div
-                    ></div
-                    ><div waiRole="presentation" dojoAttachPoint="progressBar,focusNode" tabIndex="${tabIndex}" class="dijitSliderBar dijitSliderBarV dijitSliderProgressBar dijitSliderProgressBarV" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onBarClick"
-                    ></div
-                    ><div dojoAttachPoint="sliderHandleMax,focusNodeMax" tabIndex="${tabIndex}" class="dijitSliderMoveable" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onHandleClickMax" style="vertical-align:top;" waiRole="slider" valuemin="${minimum}" valuemax="${maximum}"
-                        ><div class="dijitSliderImageHandle dijitSliderImageHandleV"></div
-                    ></div
-                ></div
-            ></center
-        ></td
-        ><td dojoAttachPoint="containerNode,rightDecoration" class="dijitReset" style="text-align:center;height:100%;"></td
-    ></tr
-    ><tr class="dijitReset"
-        ><td class="dijitReset"></td
-        ><td class="dijitReset"
-            ><center><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperV dijitSliderBottomBumper dijitSliderBottomBumperV" dojoAttachEvent="onclick:_onClkDecBumper"></div></center
-        ></td
-        ><td class="dijitReset"></td
-    ></tr
-    ><tr class="dijitReset"
-        ><td class="dijitReset"></td
-        ><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV"
-            ><div class="dijitSliderDecrementIconV" tabIndex="-1" style="display:none" dojoAttachPoint="decrementButton" dojoAttachEvent="onclick: decrement"><span class="dijitSliderButtonInner">-</span></div
-        ></td
-        ><td class="dijitReset"></td
-    ></tr
-></tbody></table>
+<table class="dijitReset dijitSlider dijitSliderV dojoxRangeSlider" cellspacing="0" cellpadding="0" border="0" rules="none"
+	><tr class="dijitReset"
+		><td class="dijitReset"></td
+		><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV"
+			><div class="dijitSliderIncrementIconV" tabIndex="-1" style="display:none" dojoAttachPoint="decrementButton" dojoAttachEvent="onclick: increment"><span class="dijitSliderButtonInner">+</span></div
+		></td
+		><td class="dijitReset"></td
+	></tr
+	><tr class="dijitReset"
+		><td class="dijitReset"></td
+		><td class="dijitReset"
+			><center><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperV dijitSliderTopBumper" dojoAttachEvent="onclick:_onClkIncBumper"></div></center
+		></td
+		><td class="dijitReset"></td
+	></tr
+	><tr class="dijitReset"
+		><td dojoAttachPoint="leftDecoration" class="dijitReset dijitSliderDecoration dijitSliderDecorationL dijitSliderDecorationV" style="text-align:center;height:100%;"></td
+		><td class="dijitReset" style="height:100%;"
+			><input dojoAttachPoint="valueNode" type="hidden" ${!nameAttrSetting}
+			/><center waiRole="presentation" style="position:relative;height:100%;" dojoAttachPoint="sliderBarContainer"
+				><div waiRole="presentation" dojoAttachPoint="remainingBar" class="dijitSliderBar dijitSliderBarV dijitSliderRemainingBar dijitSliderRemainingBarV" dojoAttachEvent="onmousedown:_onRemainingBarClick"
+					><div dojoAttachPoint="sliderHandle" tabIndex="${tabIndex}" class="dijitSliderMoveable dijitSliderMoveableV" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onHandleClick" style="vertical-align:top;" waiRole="slider" valuemin="${minimum}" valuemax="${maximum}"
+						><div class="dijitSliderImageHandle dijitSliderImageHandleV"></div
+					></div
+					><div waiRole="presentation" dojoAttachPoint="progressBar,focusNode" tabIndex="${tabIndex}" class="dijitSliderBar dijitSliderBarV dijitSliderProgressBar dijitSliderProgressBarV" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onBarClick"
+					></div
+					><div dojoAttachPoint="sliderHandleMax,focusNodeMax" tabIndex="${tabIndex}" class="dijitSliderMoveable dijitSliderMoveableV" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onHandleClickMax" style="vertical-align:top;" waiRole="slider" valuemin="${minimum}" valuemax="${maximum}"
+						><div class="dijitSliderImageHandle dijitSliderImageHandleV"></div
+					></div
+				></div
+			></center
+		></td
+		><td dojoAttachPoint="containerNode,rightDecoration" class="dijitReset dijitSliderDecoration dijitSliderDecorationR dijitSliderDecorationV" style="text-align:center;height:100%;"></td
+	></tr
+	><tr class="dijitReset"
+		><td class="dijitReset"></td
+		><td class="dijitReset"
+			><center><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperV dijitSliderBottomBumper" dojoAttachEvent="onclick:_onClkDecBumper"></div></center
+		></td
+		><td class="dijitReset"></td
+	></tr
+	><tr class="dijitReset"
+		><td class="dijitReset"></td
+		><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV"
+			><div class="dijitSliderDecrementIconV" tabIndex="-1" style="display:none" dojoAttachPoint="incrementButton" dojoAttachEvent="onclick: decrement"><span class="dijitSliderButtonInner">-</span></div
+		></td
+		><td class="dijitReset"></td
+	></tr
+></table>
diff --git a/dojox/form/resources/_CheckedMultiSelectItem.html b/dojox/form/resources/_CheckedMultiSelectItem.html
index fd7f421..3ee1f10 100644
--- a/dojox/form/resources/_CheckedMultiSelectItem.html
+++ b/dojox/form/resources/_CheckedMultiSelectItem.html
@@ -1,5 +1,5 @@
 <div class="dijitReset ${baseClass}"
 	><input class="${baseClass}Box" dojoType="dijit.form.CheckBox" dojoAttachPoint="checkBox" 
 		dojoAttachEvent="_onClick:_changeBox" type="${_type.type}" baseClass="${_type.baseClass}"
-	><div class="dijitInline ${baseClass}Label" dojoAttachPoint="labelNode" dojoAttachEvent="onmousedown:_onMouse,onmouseover:_onMouse,onmouseout:_onMouse,onclick:_onClick"></div
+	/><div class="dijitInline ${baseClass}Label" dojoAttachPoint="labelNode" dojoAttachEvent="onclick:_onClick"></div
 ></div>
diff --git a/dojox/form/tests/UploadFile.php.disabled b/dojox/form/tests/UploadFile.php.disabled
new file mode 100644
index 0000000..be491e2
--- /dev/null
+++ b/dojox/form/tests/UploadFile.php.disabled
@@ -0,0 +1,235 @@
+<?php
+// summary
+//		Test file to handle image uploads (remove the image size check to upload non-images)
+//
+//		This file handles both Flash and HTML uploads
+//
+//		NOTE: This is obviously a PHP file, and thus you need PHP running for this to work
+//		NOTE: Directories must have write permissions
+//		NOTE: This code uses the GD library (to get image sizes), that sometimes is not pre-installed in a 
+//				standard PHP build. 
+//
+require("cLOG.php");
+function findTempDirectory()
+  {
+    if(isset($_ENV["TMP"]) && is_writable($_ENV["TMP"])) return $_ENV["TMP"];
+    elseif( is_writable(ini_get('upload_tmp_dir'))) return ini_get('upload_tmp_dir');
+    elseif(isset($_ENV["TEMP"]) && is_writable($_ENV["TEMP"])) return $_ENV["TEMP"];
+    elseif(is_writable("/tmp")) return "/tmp";
+    elseif(is_writable("/windows/temp")) return "/windows/temp";
+    elseif(is_writable("/winnt/temp")) return "/winnt/temp";
+    else return null;
+  }
+function trace($txt, $isArray=false){
+	//creating a text file that we can log to
+	// this is helpful on a remote server if you don't
+	//have access to the log files
+	//
+	$log = new cLOG("../tests/upload.txt", false);
+	//$log->clear();
+	if($isArray){
+		$log->printr($txt);
+	}else{
+		$log->write($txt);
+	}
+}
+function getImageType($filename){
+	return strtolower(substr(strrchr($filename,"."),1));
+}
+trace("---------------------------------------------------------");
+
+//
+//
+//	EDIT ME: According to your local directory structure.
+// 	NOTE: Folders must have write permissions
+//
+$upload_path = "../tests/uploads/"; 	// where image will be uploaded, relative to this file
+$download_path = "../tests/uploads/";	// same folder as above, but relative to the HTML file
+
+//
+// 	NOTE: maintain this path for JSON services
+//
+require("../../../dojo/tests/resources/JSON.php");
+$json = new Services_JSON();
+
+//
+// 	Determine if this is a Flash upload, or an HTML upload
+//	
+//
+
+//		First combine relavant postVars
+$postdata = array();
+$htmldata = array();
+$data = "";
+foreach ($_POST as $nm => $val) {
+	$data .= $nm ."=" . $val . ",";	// string for flash
+	$postdata[$nm] = $val;			// array for html
+}
+trace("POSTDATA:");
+trace($postdata, true);
+
+$fieldName = "flashUploadFiles";//Filedata";
+
+if( isset($_FILES[$fieldName])){
+	//
+	// If the data passed has $fieldName, then it's Flash.
+	// NOTE: "Filedata" is the default fieldname, but we're using a custom fieldname.
+	//
+	trace("returnFlashdata.... ");
+	
+	trace("");
+	trace("ID:");
+	trace($_POST['testId']);
+	
+	trace("Flash POST:");
+	trace($_POST, true);
+	
+	
+	
+	trace("GET:");
+	trace($_GET, true);
+	
+	trace("FILES:");
+	trace($_FILES[$fieldName], true);
+	
+	trace("REQUEST:");
+	trace($_REQUEST, true);
+	
+	
+	
+	
+	
+	$returnFlashdata = true; //for dev
+	$m = move_uploaded_file($_FILES[$fieldName]['tmp_name'],  $upload_path . $_FILES[$fieldName]['name']);
+	$name = $_FILES[$fieldName]['name'];
+	$file = $upload_path . $name;
+	try{
+	  list($width, $height) = getimagesize($file);
+	} catch(Exception $e){
+	  $width=0;
+	  $height=0;
+	}
+	$type = getImageType($file);
+	trace("file: " . $file ."  ".$type." ".$width);
+	// 		Flash gets a string back:
+	
+	//exit;
+	
+	$data .='file='.$file.',name='.$name.',width='.$width.',height='.$height.',type='.$type;
+	if($returnFlashdata){
+		trace("returnFlashdata:\n=======================");
+		trace($data);
+		trace("=======================");
+		// echo sends data to Flash:
+		echo($data);
+		// return is just to stop the script:
+		return;
+	}
+
+
+
+
+}elseif( isset($_FILES['uploadedfile']) ){
+	//
+	// 	If the data passed has 'uploadedfile', then it's HTML. 
+	//	There may be better ways to check this, but this *is* just a test file.
+	//
+	$m = move_uploaded_file($_FILES['uploadedfile']['tmp_name'],  $upload_path . $_FILES['uploadedfile']['name']);
+	
+	trace("HTML single POST:");
+	trace($postdata, true);
+	
+	$name = $_FILES['uploadedfile']['name'];
+	$file = $upload_path . $name;
+	$type = getImageType($file);
+	try{
+	  list($width, $height) = getimagesize($file);
+	} catch(Exception $e){
+	  $width=0;
+	  $height=0;
+	}
+	trace("file: " . $file );
+	
+	foreach($postdata as $m){
+		
+	}
+	
+	$htmldata['file'] = $file;
+	$htmldata['name'] = $name;
+	$htmldata['width'] = $width;
+	$htmldata['height'] = $height;
+	$htmldata['type'] = $type;
+	$htmldata['size'] = filesize($file);
+	$htmldata['additionalParams'] = $postdata;
+	
+}elseif( isset($_FILES['uploadedfile0']) ){
+	//
+	//	Multiple files have been passed from HTML
+	//
+	$cnt = 0;
+	trace("HTML multiple POST:");
+	trace($postdata, true);
+	
+	$_post = $htmldata;
+	$htmldata = array();
+	
+	while(isset($_FILES['uploadedfile'.$cnt])){
+	  trace("HTML multiple POST");
+		$moved = move_uploaded_file($_FILES['uploadedfile'.$cnt]['tmp_name'],  $upload_path . $_FILES['uploadedfile'.$cnt]['name']);
+		trace("moved:" . $moved ."  ". $_FILES['uploadedfile'.$cnt]['name']);
+		if($moved){
+			$name = $_FILES['uploadedfile'.$cnt]['name'];
+			$file = $upload_path . $name;
+			$type = getImageType($file);
+			try{
+			  list($width, $height) = getimagesize($file);
+			} catch(Exception $e){
+			  $width=0;
+			  $height=0;
+			}
+			trace("file: " . $file );
+			
+			$_post['file'] = $file;
+			$_post['name'] = $name;
+			$_post['width'] = $width;
+			$_post['height'] = $height;
+			$_post['type'] = $type;
+			$_post['size'] = filesize($file);
+			$_post['additionalParams'] = $postdata;
+			trace($_post, true);
+			
+			$htmldata[$cnt] = $_post;
+			
+		}elseif(strlen($_FILES['uploadedfile'.$cnt]['name'])){
+		  $htmldata[$cnt] = array("ERROR" => "File could not be moved: ".$_FILES['uploadedfile'.$cnt]['name']);
+		}
+		$cnt++;
+	}
+	trace("HTML multiple POST done:");
+	foreach($htmldata as $key => $value){
+		trace($value, true);
+	}
+}elseif(isset($_GET['rmFiles'])){
+	trace("DELETING FILES" . $_GET['rmFiles']);
+	$rmFiles = explode(";", $_GET['rmFiles']);
+	foreach($rmFiles as $f){
+		if($f && file_exists($f)){
+			trace("deleted:" . $f. ":" .unlink($f));
+		}
+	}
+
+}else{
+	trace("IMROPER DATA SENT... $FILES:");
+	trace($_FILES);
+	$htmldata = array("ERROR" => "Improper data sent - no files found");
+}
+
+//HTML gets a json array back:
+$data = $json->encode($htmldata);
+trace("Json Data Returned:");
+trace($data);
+// in a text field:
+?>
+
+<textarea><?php print $data; ?></textarea>
+
diff --git a/dojox/form/tests/_tags.json b/dojox/form/tests/_tags.json
new file mode 100644
index 0000000..421031a
--- /dev/null
+++ b/dojox/form/tests/_tags.json
@@ -0,0 +1,100 @@
+{identifier:"tag",
+items: [
+	{tag: "accounting"},
+	{tag: "attorney"},
+	{tag: "atv"},
+	{tag: "backcountry"},
+	{tag: "bakery"},
+	{tag: "bandb"},
+	{tag: "bank"},
+	{tag: "bar"},
+	{tag: "bicycle"},
+	{tag: "cabin"},
+	{tag: "cabinoutside"},
+	{tag: "camp"},
+	{tag: "campoutside"},
+	{tag: "catering"},
+	{tag: "chamber"},
+	{tag: "church"},
+	{tag: "city"},
+	{tag: "classes"},
+	{tag: "coffeehouse"},
+	{tag: "condo"},
+	{tag: "condooutside"},
+	{tag: "conference"},
+	{tag: "county"},
+	{tag: "crosscountryski"},
+	{tag: "dentist"},
+	{tag: "dining"},
+	{tag: "fishing"},
+	{tag: "gallery"},
+	{tag: "general"},
+	{tag: "golf"},
+	{tag: "graphicart"},
+	{tag: "grocery"},
+	{tag: "guideservice"},
+	{tag: "hair"},
+	{tag: "health"},
+	{tag: "home"},
+	{tag: "homeoutside"},
+	{tag: "horse"},
+	{tag: "hotel"},
+	{tag: "hoteloutside"},
+	{tag: "hotsprings"},
+	{tag: "hotspringspool"},
+	{tag: "hunting"},
+	{tag: "iceclimbing"},
+	{tag: "iceskating"},
+	{tag: "inspection"},
+	{tag: "insurance"},
+	{tag: "internet"},
+	{tag: "jeeping"},
+	{tag: "jewelry"},
+	{tag: "live"},
+	{tag: "liveentertainment"},
+	{tag: "lodging"},
+	{tag: "manicure"},
+	{tag: "manufacturing"},
+	{tag: "maps"},
+	{tag: "massage"},
+	{tag: "menu:aboutouray"},
+	{tag: "menu:recreation"},
+	{tag: "minetour"},
+	{tag: "mining"},
+	{tag: "mountaineering"},
+	{tag: "museum"},
+	{tag: "nonprofit"},
+	{tag: "offroad"},
+	{tag: "online"},
+	{tag: "ouraymuseum"},
+	{tag: "park"},
+	{tag: "performingarts"},
+	{tag: "pet"},
+	{tag: "pharmacy"},
+	{tag: "photographer"},
+	{tag: "photography"},
+	{tag: "printing"},
+	{tag: "publishing"},
+	{tag: "rafting"},
+	{tag: "railroad"},
+	{tag: "realestate"},
+	{tag: "recreation"},
+	{tag: "rentals"},
+	{tag: "retail"},
+	{tag: "rockclimbing"},
+	{tag: "rv"},
+	{tag: "rvoutside"},
+	{tag: "school"},
+	{tag: "shop"},
+	{tag: "skirentals"},
+	{tag: "snowmobiling"},
+	{tag: "spa"},
+	{tag: "summer"},
+	{tag: "tours"},
+	{tag: "trails"},
+	{tag: "utility"},
+	{tag: "waterfall"},
+	{tag: "wedding"},
+	{tag: "weddingplanner"},
+	{tag: "winter"}
+]}
diff --git a/dojox/form/tests/cLOG.php.disabled b/dojox/form/tests/cLOG.php.disabled
new file mode 100644
index 0000000..6a9a217
--- /dev/null
+++ b/dojox/form/tests/cLOG.php.disabled
@@ -0,0 +1,54 @@
+<?php
+//
+//	summary
+//		Creates/Opens files for logging data
+//		Useful for logging iinformation on a remote server
+//		when you don't have access to log files
+//		Also helpful for XHRs - since the page doesn't change
+//		to the PHP location which normally shows log data
+//		or errors.
+//
+//
+ class cLOG {
+	var $logfile;
+	var $boolTimestamp;
+	function cLOG($filename, $boolTimestamp){
+		$this->boolTimestamp = $boolTimestamp;
+		$this->logfile = $filename;
+	}
+	function write($txt){
+		if($this->boolTimestamp){
+			$dt = date("y.m.d G.i.s");
+			$txt = "[". $dt ."]: ".$txt;
+		}
+		$fh = fopen($this->logfile, "a");
+		if(is_array($txt)){
+			//$txt = "::::::::".$txt;
+			$ar = $txt;
+			$txt = "Array:::::\n";
+			foreach($ar as $key => $value){
+				$txt += $key."=".$value."\n";
+			}
+		}
+		fwrite($fh, $txt."\n");
+		fclose($fh);
+	}
+	function clear(){
+		$fh = fopen($this->logfile, "w");
+		fwrite($fh, "");
+		fclose($fh);
+	}
+	function newline(){
+		$fh = fopen($this->logfile, "a");
+		fwrite($fh, "\n\n");
+		fclose($fh);
+	}
+	function printr($ar){
+		$txt = "";
+		foreach ($ar as $nm => $val) {
+			$txt .= "    ".$nm ." = " . $val . "\n";
+		}
+		$this->write($txt);
+	}
+}
+?>
\ No newline at end of file
diff --git a/dojox/form/tests/images/grad.jpg b/dojox/form/tests/images/grad.jpg
new file mode 100644
index 0000000..52cf2af
Binary files /dev/null and b/dojox/form/tests/images/grad.jpg differ
diff --git a/dojox/form/tests/images/grad_down.jpg b/dojox/form/tests/images/grad_down.jpg
new file mode 100644
index 0000000..7bcec94
Binary files /dev/null and b/dojox/form/tests/images/grad_down.jpg differ
diff --git a/dojox/form/tests/images/grad_over.jpg b/dojox/form/tests/images/grad_over.jpg
new file mode 100644
index 0000000..7626ce1
Binary files /dev/null and b/dojox/form/tests/images/grad_over.jpg differ
diff --git a/dojox/form/tests/images/rating_empty.gif b/dojox/form/tests/images/rating_empty.gif
new file mode 100644
index 0000000..dc6ecd8
Binary files /dev/null and b/dojox/form/tests/images/rating_empty.gif differ
diff --git a/dojox/form/tests/images/rating_full.gif b/dojox/form/tests/images/rating_full.gif
new file mode 100644
index 0000000..2e816a8
Binary files /dev/null and b/dojox/form/tests/images/rating_full.gif differ
diff --git a/dojox/form/tests/images/rndBtnSprite.png b/dojox/form/tests/images/rndBtnSprite.png
new file mode 100644
index 0000000..432e592
Binary files /dev/null and b/dojox/form/tests/images/rndBtnSprite.png differ
diff --git a/dojox/form/tests/images/rndBtn_down.png b/dojox/form/tests/images/rndBtn_down.png
new file mode 100644
index 0000000..1f2f28b
Binary files /dev/null and b/dojox/form/tests/images/rndBtn_down.png differ
diff --git a/dojox/form/tests/images/rndBtn_norm.png b/dojox/form/tests/images/rndBtn_norm.png
new file mode 100644
index 0000000..0be88a9
Binary files /dev/null and b/dojox/form/tests/images/rndBtn_norm.png differ
diff --git a/dojox/form/tests/images/rndBtn_over.png b/dojox/form/tests/images/rndBtn_over.png
new file mode 100644
index 0000000..f6084c1
Binary files /dev/null and b/dojox/form/tests/images/rndBtn_over.png differ
diff --git a/dojox/form/tests/test_BusyButton.html b/dojox/form/tests/test_BusyButton.html
new file mode 100644
index 0000000..53769e0
--- /dev/null
+++ b/dojox/form/tests/test_BusyButton.html
@@ -0,0 +1,104 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>BusyButton Test</title>
+
+		<!-- for tests -->
+		<style type="text/css">
+			@import url(../../../dojo/resources/dojo.css);
+			@import url(../../../dijit/themes/tundra/tundra.css);
+			@import url(../../../dijit/tests/css/dijitTests.css);
+			
+			@import url(../resources/BusyButton.css);
+		</style>
+		
+		<!-- required: a default dijit theme: -->
+		<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+		
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="parseOnLoad: true, isDebug: true"></script>
+		<script type="text/javascript" src="../BusyButton.js"></script>
+		<script type="text/javascript">
+			dojo.require("dijit.Menu");
+			dojo.addOnLoad(function(){
+				dojo.connect(dijit.byId("buttonCancel"), "onClick", function(){
+					dijit.byId("button_noTimeout").cancel();
+				});
+				dojo.connect(dijit.byId("buttonCancel2"), "onClick", function(){
+					dijit.byId("button_noTimeout2").attr("label", "Chargeback failed...", 1000);
+				});
+				dojo.connect(dijit.byId("button_noTimeout3"), "_onClick", function(){
+					dijit.byId("button_noTimeout3").attr("label", "Creating account...");
+					dijit.byId("button_noTimeout3").resetTimeout();
+				});
+			});
+			function makeBusy(id){
+				var widget = dijit.byId(id);
+				if(widget && !widget.isBusy){
+					widget.makeBusy();
+				}
+			}
+		</script>
+	</head>
+	<body class="tundra">
+		<h1 class="testTitle">Test: dojox.form.BusyButton</h1>
+		<p>
+		Normal busy button, 5000 miliseconds timeout<br />
+		<button dojoType="dojox.form.BusyButton" timeout="5000" >Click</button>
+		</p>
+	
+		<p>
+		Busy button, no timeout, custom label<br />
+		<button dojoType="dojox.form.BusyButton" id="button_noTimeout" busyLabel="Charging creditcard..." >Pay now</button> <button dojoType="dijit.form.Button" id="buttonCancel">Cancel button</button>
+		</p>
+		<p>
+		Busy button, no initial timeout, changing state and setting timeout on button press<br />
+		<button dojoType="dojox.form.BusyButton" id="button_noTimeout2" busyLabel="Canceling payment...">Cancel payment</button> <button dojoType="dijit.form.Button" id="buttonCancel2">Change state</button>
+		</p>
+		<p>
+		Busy button, initially busy with 10 sec timeout<br />
+		<button dojoType="dojox.form.BusyButton" id="button_noTimeout3" isBusy="true" busyLabel="Please read the agreement..." timeout="10000">I Agree</button>
+		</p>
+		<p>
+		Combo and DropDown Buttons (5000 ms timeout)<br />
+			<button dojoType="dojox.form.BusyComboButton" id="comboBusy" timeout="5000" optionsTitle='save options' onClick='console.log("clicked combo save")'
+					iconClass="plusIcon">
+				<span>Create</span>
+				<div dojoType="dijit.Menu" id="createMenu" style="display: none;">
+					<div dojoType="dijit.MenuItem"  iconClass="dijitEditorIcon dijitEditorIconSave"
+						onClick="makeBusy('comboBusy'); console.log('not actually saving anything, just a test!')">Create blank</div>
+					<div dojoType="dijit.MenuItem"
+						onClick="makeBusy('comboBusy'); console.log('not actually saving anything, just a test!')">Create from template</div>
+				</div>
+			</button>
+			<button dojoType="dojox.form.BusyDropDownButton" id="dropDownBusy" timeout="5000" iconClass="noteIcon">
+				<span>Edit<b>!</b></span>
+				<div dojoType="dijit.Menu">
+					<div dojoType="dijit.MenuItem"  iconClass="dijitEditorIcon dijitEditorIconCut"
+						onClick="makeBusy('dropDownBusy'); console.log('not actually cutting anything, just a test!')">Cut</div>
+					<div dojoType="dijit.MenuItem"  iconClass="dijitEditorIcon dijitEditorIconCopy"
+						onClick="makeBusy('dropDownBusy'); console.log('not actually copying anything, just a test!')">Copy</div>
+					<div dojoType="dijit.MenuItem"  iconClass="dijitEditorIcon dijitEditorIconPaste"
+						onClick="makeBusy('dropDownBusy'); console.log('not actually pasting anything, just a test!')">Paste</div>
+					<div dojoType="dijit.MenuSeparator"></div>
+					<div dojoType="dijit.PopupMenuItem">
+						<span>Submenu</span>
+						<div dojoType="dijit.Menu" id="submenu2">
+							<div dojoType="dijit.MenuItem" onClick="makeBusy('dropDownBusy'); console.log('Submenu 1!')">Submenu Item One</div>
+							<div dojoType="dijit.MenuItem" onClick="makeBusy('dropDownBusy'); console.log('Submenu 2!')">Submenu Item Two</div>
+							<div dojoType="dijit.PopupMenuItem">
+								<span>Deeper Submenu</span>
+								<div dojoType="dijit.Menu" id="submenu4">
+									<div dojoType="dijit.MenuItem" onClick="makeBusy('dropDownBusy'); console.log('Sub-submenu 1!')">Sub-sub-menu Item One</div>
+									<div dojoType="dijit.MenuItem" onClick="makeBusy('dropDownBusy'); console.log('Sub-submenu 2!')">Sub-sub-menu Item Two</div>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+			</button>
+		</p>
+	</body>
+</hmtl>
\ No newline at end of file
diff --git a/dojox/form/tests/test_CheckedMultiSelect.html b/dojox/form/tests/test_CheckedMultiSelect.html
new file mode 100644
index 0000000..cd1c45d
--- /dev/null
+++ b/dojox/form/tests/test_CheckedMultiSelect.html
@@ -0,0 +1,323 @@
+<html>
+	<head>
+	    <script type="text/javascript" 
+	        src="../../../dojo/dojo.js"
+	        djConfig="isDebug: true, parseOnLoad: true">
+	    </script>
+	    <script type="text/javascript">
+			dojo.require("doh.runner");
+	        dojo.require("dojo.parser");
+			dojo.require("dojox.form.CheckedMultiSelect");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.form.Form");
+			dojo.require("dojo.data.ItemFileWriteStore");
+		
+			var data = {
+				identifier: "value",
+				label: "label",
+				items: [
+					{value: "AL", label: "Alabama"},
+					{value: "AK", label: "Alaska"},
+					{value: "AZ", label: "Arizona"},
+					{value: "AR", label: "Arkansas"},
+					{value: "CA", label: "California"},
+					{value: "CO", label: "Colorado"},
+					{value: "CT", label: "Connecticut"}
+				]
+			};
+			
+			var readStore = new dojo.data.ItemFileReadStore({data:dojo.clone(data)});
+			var writeStore = new dojo.data.ItemFileWriteStore({data:dojo.clone(data)});
+			
+			var numOptions = 0;
+			var addNum = 10;
+			var testType;
+			// Uncomment below line to run perf tests - note SLOW to run
+			//testType = "perf";
+		
+			dojo.addOnLoad(function(){
+				doh.register("tests",
+					[
+						function test_setValue(t){
+							t.is(["VA","WA"], form.attr("value").ms1);
+							t.is(["TX","GA"], form.attr("value").ms2);
+							ms1.attr("value", ["TN","CA"]);
+							t.is(["TN","CA"], form.attr("value").ms1);
+							ms1.invertSelection();
+							t.is(["VA","WA","FL"], form.attr("value").ms1);							
+						},
+						function test_addSelected(t){
+							dojo.forEach(ms2.getOptions(ms2.getValue()), function(i){
+								ms2.removeOption(i);
+								ms1.addOption(i);
+							});
+							t.is([], form.attr("value").ms2);
+							ms1.invertSelection();
+							t.is(["TN","CA"], form.attr("value").ms1);
+						},
+						function delete_selected(t){
+							t.is(["TN","CA"], ms1.getValue());
+							var d = new doh.Deferred();
+							ms1.removeOption("CA");
+							window.setTimeout(function(){
+								try{
+									t.is(["TN"], ms1.getValue());
+									d.callback(true);
+								}catch(e){ d.errback(e); }
+							}, 100);
+							return d;
+						},
+						function test_storeBased(t){
+							t.is([], ms4.attr("value"));
+							ms4.attr("value", ["CA","AL"]);
+							t.is(["AL","CA"], ms4.attr("value"));
+						},
+						function test_changeSelected(t){
+							t.is([], ms5.attr("value"));
+							ms5.attr("value", ["AL", "AK"]);
+							var d = new doh.Deferred();
+							var cb = function(item){
+								try{
+									writeStore.setValue(item, "label", "North Pole");
+									try{
+										t.is(["AL","AK"], ms5.attr("value"));
+										t.is(writeStore.getValue(item, "label"), 
+												dojo.filter(ms5._getChildren(), function(n){return n.option.value==="AK";})[0].labelNode.innerHTML);
+										d.callback(true);
+									}catch(e){ d.errback(e);}
+								}
+								catch(e){
+									d.errback(e);
+								}
+							}
+							writeStore.fetchItemByIdentity({identity: "AK", onItem: cb});
+							return d;
+						},
+						function test_deleteNonSelected(t){
+							t.is(["AL","AK"], ms5.attr("value"));
+							var d = new doh.Deferred();
+							var cb = function(item){
+								try{
+									t.is(7, ms5._getChildren().length);
+									writeStore.deleteItem(item);
+									try{
+										t.is(["AL","AK"], ms5.attr("value"));
+										t.is(6, ms5._getChildren().length);
+										d.callback(true);
+									}catch(e){ d.errback(e);}
+								}catch (e){
+									d.errback(e);
+								}
+							}
+							writeStore.fetchItemByIdentity({identity: "AZ", onItem: cb});
+							return d;
+						},
+						function test_deleteSelected(t){
+							t.is(["AL","AK"], ms5.attr("value"));
+							var d = new doh.Deferred();
+							var cb = function(item){
+								try{
+									t.is(6, ms5._getChildren().length);
+									writeStore.deleteItem(item);
+									try{
+										t.is(["AL"], ms5.attr("value"));
+										t.is(5, ms5._getChildren().length);
+										d.callback(true);
+									}catch(e){ d.errback(e);}
+								}catch (e){
+									d.errback(e);
+								}
+							}
+							writeStore.fetchItemByIdentity({identity: "AK", onItem: cb});
+							return d;
+						},
+						function test_newItem(t){
+							t.is(["AL"], ms5.attr("value"));
+							t.is(5, ms5._getChildren().length);
+							ms5.attr("value", ["AL","NY"]);
+							t.is(["AL"], ms5.attr("value"));
+							var d = new doh.Deferred();
+							writeStore.newItem({value: "NY", label: "New York"});
+							try{
+								t.is(6, ms5._getChildren().length);
+								ms5.attr("value", ["AL","NY"]);
+								t.is(["AL","NY"], ms5.attr("value"));
+								d.callback(true);
+							}catch(e){d.errback(e);}
+							return d;
+						},
+						{
+							name: "test_performance_single",
+							testType: testType,
+							trialDuration: 100,
+							trialIterations: 100,
+							trialDelay: 100,
+							runTest: function(t){
+								var opt = {value: "Test", label: "Test Option"};
+								ms3.addOption(opt);
+								ms3.removeOption(opt);
+							}
+						},
+						{
+							name: "test_performance_separate",
+							testType: testType,
+							trialDuration: 100,
+							trialIterations: 100,
+							trialDelay: 100,
+							setUp: function(t){
+								var opts = t.options = [];
+								for(var i = 0; i < addNum; i++){
+									opts.push({value: i + "", label: "Option " + (i + 1)});
+								}
+							},
+							runTest: function(t){
+								dojo.forEach(t.options, function(opt){
+									ms3.addOption(opt);
+								});
+								dojo.forEach(t.options, function(opt){
+									ms3.removeOption(opt);
+								});
+							},
+							tearDown: function(t){
+								delete t.options;
+							}
+						},
+						{
+							name: "test_performance_batch",
+							testType: testType,
+							trialDuration: 100,
+							trialIterations: 100,
+							trialDelay: 100,
+							setUp: function(t){
+								var opts = t.options = [];
+								for(var i = 0; i < addNum; i++){
+									opts.push({value: i + "", label: "Option " + (i + 1)});
+								}
+							},
+							runTest: function(t){
+								ms3.addOption(t.options);
+								ms3.removeOption(t.options);
+							},
+							tearDown: function(t){
+								delete t.options;
+							}
+						}
+					]
+				);
+				doh.run();
+				dojo.connect(ms1, "onChange", function(val){
+					console.log("First Select Changed to " + val);
+				});
+				dojo.connect(ss1, "onChange", function(val){
+					console.log("First Radio Select Changed to " + val);
+				});
+			});
+		</script>
+		<style>
+			@import url(../../../dojo/resources/dojo.css);
+			@import url(../../../dijit/themes/tundra/tundra.css);
+			@import url(../resources/CheckedMultiSelect.css);
+			@import url(../../../dijit/tests/css/dijitTests.css);
+		</style>
+		<style>
+		.ark { text-decoration: underline; }
+		</style>
+	</head>	
+	<body class="tundra">
+		<h1 class="testTitle">Test: dojox.form.CheckedMultiSelect</h1>
+		<form dojoType="dijit.form.Form" jsId="form">
+			<h2>Check Boxes</h2>
+			<select jsId="ms1" multiple="true" name="ms1" dojoType="dojox.form.CheckedMultiSelect">
+				<option value="TN">Tennessee</option>
+				<option value="VA" selected="selected">Virginia</option>
+				<option value="WA" selected="selected">Washington</option>
+				<option value="FL">Florida</option>
+				<option value="CA">California</option>
+			</select>
+			<select jsId="ms2" multiple="true" name="ms2" dojoType="dojox.form.CheckedMultiSelect">
+				<option value="UT">Utah</option>
+				<option value="TX" selected="selected">Texas</option>
+				<option value="GA" selected="selected">Georgia</option>
+				<option value="ID">Idaho</option>
+				<option value="WY">Wyoming</option>
+				<option value="OR">Oregon</option>
+				<option value="PA">Pennsylvania</option>
+			</select>
+			<select jsId="ms3" multiple="true" name="ms3" dojoType="dojox.form.CheckedMultiSelect">
+			</select>
+		<hr>
+			<h2>Radio Buttons</h2>
+			<select jsId="ss1" name="ss1" dojoType="dojox.form.CheckedMultiSelect">
+				<option value="TN">Tennessee</option>
+				<option value="VA" selected="selected">Virginia</option>
+				<option value="WA">Washington</option>
+				<option value="FL">Florida</option>
+				<option value="CA">California</option>
+			</select>
+			<select jsId="ss2" name="ss2" value="TX" dojoType="dojox.form.CheckedMultiSelect">
+				<option value="UT">Utah</option>
+				<option value="TX">Texas</option>
+				<option value="GA">Georgia</option>
+				<option value="ID">Idaho</option>
+				<option value="WY">Wyoming</option>
+				<option value="OR">Oregon</option>
+				<option value="PA">Pennsylvania</option>
+			</select>
+			<select jsId="ss3" name="ss3" dojoType="dojox.form.CheckedMultiSelect">
+			</select>
+		<hr>
+			<h4 class="testSubtitle">Store-based</h4>
+			<select jsId="ms4" multiple="true" size="5" name="ms4" store="readStore" dojoType="dojox.form.CheckedMultiSelect">
+			</select>
+			<select jsId="ms5" multiple="true" size="5" name="ms5" store="writeStore" dojoType="dojox.form.CheckedMultiSelect">
+			</select>
+		<hr>
+			<button dojoType="dijit.form.Button">
+				<script type="dojo/method" event="onClick">
+					console.dir(form.attr("value"));
+				</script>
+				Get Values
+			</button>
+			<button dojoType="dijit.form.Button">
+				<script type="dojo/method" event="onClick">
+					numOptions++;
+					ms3.addOption({value: numOptions + "", label: "Option " + (numOptions)});
+				</script>
+				Add Check Option
+			</button>
+			<button dojoType="dijit.form.Button">
+				<script type="dojo/method" event="onClick">
+					numOptions++;
+					ss3.addOption({value: numOptions + "", label: "Option " + (numOptions)});
+				</script>
+				Add Radio Option
+			</button>
+			<button dojoType="dijit.form.Button">
+				<script type="dojo/method" event="onClick">
+					ms3.attr("disabled", !ms3.disabled);
+					ss3.attr("disabled", !ss3.disabled);
+				</script>
+				Toggle Disabled
+			</button>
+			<button dojoType="dijit.form.Button">
+				<script type="dojo/method" event="onClick">
+					ms2.attr("readOnly", !ms2.readOnly);
+					ss2.attr("readOnly", !ss2.readOnly);
+				</script>
+				Toggle Read Only
+			</button>
+			<button dojoType="dijit.form.Button">
+				<script type="dojo/method" event="onClick">
+					ms1.invertSelection(true);
+				</script>
+				Invert Selection
+			</button>
+			<button dojoType="dijit.form.Button">
+				<script type="dojo/method" event="onClick">
+					console.log(ms1.attr("displayedValue"));
+				</script>
+				Get Displayed Value
+			</button>
+		</form>
+	</body>
+</html>
diff --git a/dojox/form/tests/test_DateTextBox.html b/dojox/form/tests/test_DateTextBox.html
new file mode 100644
index 0000000..b9e7e39
--- /dev/null
+++ b/dojox/form/tests/test_DateTextBox.html
@@ -0,0 +1,192 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Test DateTextBox Widget</title>
+
+		<!-- required: a default theme file -->
+		<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+		<link rel="stylesheet" href="../../widget/Calendar/Calendar.css">
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+
+			.testExample {
+				background-color:#fbfbfb;
+				padding:1em;
+				margin-bottom:1em;
+				border:1px solid #bfbfbf;
+			}
+
+			body .medium {
+				width: 10em;
+			}
+
+			.noticeMessage {
+				color:#093669;
+				font-size:0.95em;
+				margin-left:0.5em;
+			}
+
+			.dojoTitlePaneLabel label {
+				font-weight:bold;
+			}
+		</style>
+
+		<!-- required: dojo.js -->
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true, extraLocale: ['de-de', 'en-us']"></script>
+			
+		<!-- do not use, only for dynamic themes -->
+		<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+		<script type="text/javascript" src="../../../dijit/form/ValidationTextBox.js"></script>
+		<script type="text/javascript" src="../../../dijit/form/_DateTimeTextBox.js"></script>
+		<script type="text/javascript" src="../../widget/Calendar.js"></script>
+		<script type="text/javascript" src="../DateTextBox.js"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojox.form.DateTextBox");
+			dojo.require("dijit.form.Form");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+		</script>
+	</head>
+
+	<body class="tundra">
+		<h1 class="testTitle">Test DateTextBox Widget</h1>
+		<!--	to test form submission, you'll need to create an action handler similar to
+			http://www.utexas.edu/teamweb/cgi-bin/generic.cgi -->
+		<form id="form1" dojoType='dijit.form.Form' action="" name="example" method="">
+			<div class="dojoTitlePaneLabel">
+				<label for="q1"> Date (local format) </label>
+				<span class="noticeMessage">DateTextBox class, no attributes</span>
+			</div>
+			<div class="testExample">
+				<input id="q1" name="noDOMvalue" type="text" dojoType="dojox.form.DateTextBox"
+				         onChange="dojo.byId('oc1').value=arguments[0]"
+				>
+				onChange:<input id="oc1" size="34" disabled value="not fired yet!" autocomplete="off">
+			</div>
+
+			<div class="testExample">
+				Day Only
+				<input id="q1Day" name="q1Day" type="text" dojoType="dojox.form.DayTextBox"
+				         onChange="dojo.byId('oc1day').value=arguments[0]"
+				>
+				onChange:<input id="oc1day" size="34" disabled value="not fired yet!" autocomplete="off">
+			</div>
+			<div class="testExample">
+				Month Only
+				<input id="q1Month" name="q1Month" type="text" dojoType="dojox.form.MonthTextBox"
+				         onChange="dojo.byId('oc1month').value=arguments[0]"
+				>
+				onChange:<input id="oc1month" size="34" disabled value="not fired yet!" autocomplete="off">
+			</div>
+
+			<div class="testExample">
+				Year Only
+				<input id="q1Year" name="q1Year" type="text" dojoType="dojox.form.YearTextBox"
+				         onChange="dojo.byId('oc1year').value=arguments[0]"
+				>
+				onChange:<input id="oc1year" size="34" disabled value="not fired yet!" autocomplete="off">
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<label for="q2"> Date (local format - long) </label>
+				<span class="noticeMessage">DateTextBox class,
+					Attributes: required="true", trim="true", constraints={min:'2004-01-01',max:'2006-12-31',formatLength:'long'}. Works for leap years</span>
+			</div>
+			<div class="testExample">
+				<input id="q2" type="text" name="date1" class="medium" value="2005-12-30"
+					dojoType="dojox.form.DateTextBox"
+					constraints="{min:'2004-01-01',max:'2006-12-31',formatLength:'long'}"
+					required="true"
+					trim="true"
+					onChange="dojo.byId('oc2').value=arguments[0]"
+					invalidMessage="Invalid date." />
+ 				onChange:<input id="oc2" size="34" disabled value="not fired yet!" autocomplete="off">
+				<input type="button" value="Destroy" onClick="dijit.byId('q2').destroy(); return false;">
+				<input type="button" value="set max to 2007-12-31" onClick="dijit.byId('q2').constraints.max = new Date(2007,11,31); return false;">
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<label for="q3"> Date (American format) </label>
+				<span class="noticeMessage">DateTextBox class,
+					Attributes: lang="en-us", required="true", constraints={min:'2004-01-01',max:'2006-12-31'}. Works for leap years</span>
+			</div>
+			<div class="testExample">
+				<input id="q3" type="text" name="date2" class="medium" value="2005-12-30"
+					dojoType="dojox.form.DateTextBox"
+					constraints="{min:'2004-01-01',max:'2006-12-31'}"
+					lang="en-us"
+					required="true"
+					promptMessage="mm/dd/yyyy"
+					invalidMessage="Invalid date. Use mm/dd/yyyy format." />
+			</div>
+			<div class="dojoTitlePaneLabel">
+				<label for="q4"> Date (German format) </label>
+				<span class="noticeMessage">DateTextBox class,
+					Attributes: lang="de-de", constraints={min:2004-01-01, max:2006-12-31}. Works for leap years</span>
+			</div>
+			<div class="testExample">
+				<input id="q4" class="medium"/>
+			</div>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="q5"> Date, overriding pattern</label>
+				<span class="noticeMessage">Date, overriding pattern with dd-MM-yyyy</span>
+			</div>
+			<div class="testExample">
+				<input id="q5" name="noDOMvalue" type="text" dojoType="dojox.form.DateTextBox" constraints="{datePattern:'dd-MM-yyyy', strict:true}">
+			</div>
+
+			<script>
+			// See if we can make a widget in script and attach it to the DOM ourselves.
+			dojo.addOnLoad(function(){
+				var props = {
+					name: "date4",
+					value: new Date(2006,10,29),
+					constraints: {min:new Date(2004,0,1),max:new Date(2006,11,31)},
+					lang: "de-de",
+					promptMessage: "dd.mm.yy",
+					rangeMessage: "Enter a date in the year range 2004-2006.",
+					invalidMessage: "Invalid date. Use dd.mm.yy format."
+				};
+				var w = new dojox.form.DateTextBox(props, "q4");
+			});
+			</script>
+
+			<script>
+				function displayData() {
+					var f = document.getElementById("form1");
+					var s = "";
+					for (var i = 0; i < f.elements.length; i++) {
+						var elem = f.elements[i];
+						if (elem.name == "button")  { continue; }
+						s += elem.name + ": " + elem.value + "\n";
+					}
+					alert(s);
+				}
+			</script>
+
+			<div class="dojoTitlePaneLabel">
+				<label for="fromDate"> Date pairs, to/from</label>
+			</div>
+			<div class="testExample">
+				From: <input id="fromDate" type="text" name="fromDate" dojoType="dojox.form.DateTextBox"
+					required="true"
+					onChange="dijit.byId('toDate').constraints.min = this.getValue();" />
+				To: <input id="toDate" type="text" name="toDate" dojoType="dojox.form.DateTextBox"
+					required="true"
+					onChange="dijit.byId('fromDate').constraints.max = this.getValue();" />
+			</div>
+
+			<div>
+				<button name="button" onclick="displayData(); return false;">view data</button>
+				<input type="submit" name="submit" />
+				<input type="reset" name="reset" />
+			</div>
+
+		</form>
+	</body>
+</html>
diff --git a/dojox/form/tests/test_FileInput.html b/dojox/form/tests/test_FileInput.html
new file mode 100644
index 0000000..e570d9a
--- /dev/null
+++ b/dojox/form/tests/test_FileInput.html
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.form.FileInput | The Dojo Toolkit</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		@import "../resources/FileInput.css"; 
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../FileInput.js"></script>
+	<script type="text/javascript" src="../FileInputAuto.js"></script>
+	<script type="text/javascript">
+		// dojo.require("dojox.form.FileInput"); 
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+		
+		var sampleCallback = function(data,ioArgs,widgetRef){
+			// this function is fired for every programatic FileUploadAuto
+			// when the upload is complete. It uses dojo.io.iframe, which
+			// expects the results to come wrapped in TEXTAREA tags.
+			// this is IMPORTANT. to utilize FileUploadAuto (or Blind)
+			// you have to pass your response data in a TEXTAREA tag.
+			// in our sample file (if you have php5 installed and have
+			// file uploads enabled) it _should_ return some text in the
+			// form of valid JSON data, like:
+			// { status: "success", details: { size: "1024" } }
+			// you can do whatever.
+			//
+			// the ioArgs is the standard ioArgs ref found in all dojo.xhr* methods.
+			//
+			// widget is a reference to the calling widget. you can manipulate the widget
+			// from within this callback function 
+			if(data){
+				if(data.status && data.status == "success"){
+					widgetRef.overlay.innerHTML = "success!";
+				}else{
+					widgetRef.overlay.innerHTML = "error? ";
+					console.log('error',data,ioArgs);
+				}
+			}else{
+				// debug assist
+				console.log('ugh?',arguments);
+			}
+		}
+
+		var i = 0;
+		function addNewUpload(){
+			var node = document.createElement('input'); 
+			dojo.byId('dynamic').appendChild(node);
+			var widget = new dojox.form.FileInputAuto({
+				id: "dynamic"+(++i),
+				url: "../resources/RecieveFile.php",
+				//url:"http://archive.dojotoolkit.org/nightly/checkout/dojox/widget/resources/RecieveFile.php",
+				name: "dynamic"+i,
+				onComplete: sampleCallback
+			},node);
+			widget.startup();
+		}
+
+	</script>
+</head>
+<body>
+
+	<h1 class="testTitle">dojox FileInput widget:</h1>
+	<p>This is a prototype of a dojo input type="file" with a FormWidget mixin, to be styled to match tundra and soria themes</p>
+	<p>The API is up for discussion, nor is it known to drop into forms and "just work" yet</p>
+	<p>FileInputAuto API is up for discussion, as well, though by use of the url="" attrib, you can basically
+	do all your file-processing server side, and just use the filename sent that remains in the form input</p>
+	<p>There are two parts. dojo.require("dojox.form.FileInput") for just the base class, or dojo.require("dojox.form.FileInputAuto"); 
+	to provide the Auto Uploading widget (on blur), and the Blind Auto Upload widget.</p>
+	<p>Both themes are defined in the FileInput.css file, as well as basic styling needed to run</p>
+
+	<h3>A standard file input:</h3>
+	<input type="file" id="normal" name="inputFile" />
+
+	<h3>The default dojox.form.FileInput:</h3>
+	<p>
+	<input dojoType="dojox.form.FileInput" id="default" name="inputFile" />
+	</p>
+
+	<h3>default dojox.form.FileInput, tundra:</h3>
+	<p class="tundra">
+	<input dojoType="dojox.form.FileInput" id="default2" name="inputFile" />
+	</p>
+
+	<h3>dojox.form.FileInputAuto, soria theme:</h3>
+	<p class="soria">
+	<input dojoType="dojox.form.FileInputAuto" id="defaultAuto" name="inputFileAuto" url="../resources/RecieveFile.php" />
+	</p>
+
+	<h3>another one, tundra theme (with callback)</h3>
+	<p class="tundra">
+	<input dojoType="dojox.form.FileInputAuto" id="defaultAuto2" name="inputFileAuto2" url="../resources/RecieveFile.php" onComplete="sampleCallback"/>
+	</p>
+
+	<h3>dojox.form.FileInputAuto -  tundra theme (with callback) - and onchange triggerEvent</h3>
+	<p class="tundra">
+	<input dojoType="dojox.form.FileInputAuto" id="defaultAuto2onchange" blurDelay="10" name="inputFileAuto2" triggerEvent="onchange" url="../resources/RecieveFile.php" onComplete="sampleCallback"/>
+	</p>
+
+
+	<h3>a blind auto upload widget, tundra:</h3>
+	<p class="tundra">
+		<input dojoType="dojox.form.FileInputBlind" id="blind1" name="blind1" url="../resources/RecieveFile.php" />
+	</p>
+
+	<h3>dojox.form.FileInputBlind - soria</h3>
+	<p class="soria">
+		<input dojoType="dojox.form.FileInputBlind" id="blind2" name="blind2" label="do my upload" url="../resources/RecieveFile.php" />
+	</p>
+
+	<h3>dynamic, tundra, dojox.form.FileInputAuto:</h3>
+	<button onclick="addNewUpload()">add new file upload</button>
+	<br><br>
+	<div id="dynamic" class="tundra"></div>
+
+</body>
+</html>
diff --git a/dojox/form/tests/test_FilePickerTextBox.html b/dojox/form/tests/test_FilePickerTextBox.html
new file mode 100644
index 0000000..8bb4dc3
--- /dev/null
+++ b/dojox/form/tests/test_FilePickerTextBox.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>File Picker Demo</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/soria/soria.css">
+	
+	<!-- the additional styles for the widget -->
+	<link id="widgetStyle" rel="stylesheet" href="../resources/FilePickerTextBox.css">
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true, useCommentedJson: true"></script>
+	
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.form.FilePickerTextBox");
+		dojo.require("dojox.data.FileStore");
+		dojo.require("dijit.form.Form");
+		dojo.require("dijit.form.Button");
+	</script>
+</head>
+
+<body class="soria">
+	<h1>
+		Demo: File Picker text box widget using dojox.data.FileStore
+	</h1>
+	<p>The picker below uses the dojox.data.FileStore and a PHP implementation for the serverside to browse the dojo tree hierarchy in a lazy-load fashion.</p>
+	<p><i><b>This demo must be run from a web-server with PHP support enabled.  Without PHP support, this demo cannot function.</b></i></p>
+	<hr>
+	<div dojoType="dojox.data.FileStore" url="../../data/demos/stores/filestore_dojotree.php" jsId="fileStore" pathAsQueryParam="true"></div>
+	<form dojoType="dijit.form.Form" onSubmit="if(this.validate()){console.dir(this.getValues());}else{console.log('NOT VALID');} return false;">
+		<label>Choose a file:<input required="true" name="fileName" type="text" dojoType="dojox.form.FilePickerTextBox" constraints="{store: fileStore, query:{}}" /></label><br>
+		<button dojoType="dijit.form.Button" type="submit">Submit</button>
+	</form>
+</body>
+</html>
+
+
diff --git a/dojox/form/tests/test_FileUploader.html b/dojox/form/tests/test_FileUploader.html
new file mode 100644
index 0000000..80bbec3
--- /dev/null
+++ b/dojox/form/tests/test_FileUploader.html
@@ -0,0 +1,272 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.form.FileUploader</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/form/Button.css";
+		/*@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../resources/FileUploader.css";*/
+	</style>
+	<script>
+		passthrough = function(msg){
+			//for catching messages from Flash
+			if(window.console){
+				console.log(msg);
+			}
+		}
+		forceNoFlash = false;
+		selectMultipleFiles = false;
+		var qs = window.location.href.split("?");
+		if(qs.length>1){
+			qs = qs[1];
+			if(qs.indexOf("forceNoFlash")>-1){
+				forceNoFlash = true;
+			}
+			if(qs.indexOf("multiMode")>-1){
+				selectMultipleFiles = true;
+			}
+		 }
+
+		 setLoc = function(href){
+		 	window.location.href = window.location.href.split("?")[0] + href;
+		 }
+		 showWithFlash = function(){
+		 	if(forceNoFlash){
+				setLoc("");
+			}
+		 }
+		 showWithoutFlash = function(){
+		 	if(!forceNoFlash){
+				setLoc((selectMultipleFiles) ? "?forceNoFlash&multiMode" : "?forceNoFlash");
+			}
+		 }
+		 showMulti = function(){
+		 	if(!selectMultipleFiles){
+				setLoc((forceNoFlash) ? "?forceNoFlash&multiMode" : "?multiMode");
+			}
+		 }
+		 showSingle = function(){
+		 	if(selectMultipleFiles){
+				setLoc((forceNoFlash) ? "?forceNoFlash" : "");
+			}
+		 }
+    </script>
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+    	djConfig="isDebug:true, parseOnLoad: true, debugAtAllCosts:false"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.form.FileUploader");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+
+		//using this early for the forceNoFlash test:
+		dojo.require("dojox.embed.Flash");
+
+		var uploadUrl = "../tests/UploadFile.php";
+
+		var rmFiles = "";
+		var fileMask = [
+			["Jpeg File", 	"*.jpg;*.jpeg"],
+			["GIF File", 	"*.gif"],
+			["PNG File", 	"*.png"],
+			["All Images", 	"*.jpg;*.jpeg;*.gif;*.png"]
+		];
+		// For testing 1D array masks:
+		// var fileMask = 	["All Images", 	"*.jpg;*.jpeg;*.gif;*.png"];
+		// var fileMask = 	["PNG File", 	"*.png"];
+
+		dojo.addOnLoad(function(){
+			if(forceNoFlash){
+				dojox.embed.Flash.available = 0;
+				dojo.byId("hasFlash").style.display = "none";
+				dojo.byId("fTypes").style.display = "none";
+			}else{
+				dojo.byId("noFlash").style.display = "none";
+				if(dojo.isArray(fileMask[0])){
+					dojo.byId("fTypes").innerHTML+=fileMask[fileMask.length-1][1];
+				}else{
+					dojo.byId("fTypes").innerHTML+=fileMask[1];
+				}
+			}
+
+			if(selectMultipleFiles){
+				dojo.byId("fmode").innerHTML = dojo.byId("hmode").innerHTML = "Multi-File Mode";
+				dojo.byId("fSingle").style.display = "none";
+				dojo.byId("hSingle").style.display = "none";
+				dijit.byId("fbm").domNode.style.display = "none";
+				dijit.byId("hbm").domNode.style.display = "none";
+			}else{
+				dojo.byId("fmode").innerHTML = dojo.byId("hmode").innerHTML = "Single-File Mode";
+				dojo.byId("fMulti").style.display = "none";
+				dojo.byId("hMulti").style.display = "none";
+				dijit.byId("fbs").domNode.style.display = "none";
+				dijit.byId("hbs").domNode.style.display = "none";
+			}
+			dojo.byId("uploadedFiles").value = "";
+			dojo.byId("fileToUpload").value = "";
+
+
+			var f0 = new dojox.form.FileUploader({
+				degradable:true,
+				uploadUrl:uploadUrl,
+				uploadOnChange:false,
+				selectMultipleFiles:selectMultipleFiles,
+				fileMask:fileMask,
+				isDebug:true,
+				devMode:true
+			}, "selectBtn");
+
+			doUpload = function(){
+				dojo.byId("fileToUpload").innerHTML = "uploading...";
+				f0.upload();
+			}
+			dojo.connect(f0, "onChange", function(data){
+				console.log("DATA:", data);
+				dojo.forEach(data, function(d){
+					//file.type no workie from flash selection (Mac?)
+					if(selectMultipleFiles){
+						dojo.byId("fileToUpload").value += d.name+" "+Math.ceil(d.size*.001)+"kb \n";
+					}else{
+						dojo.byId("fileToUpload").value = d.name+" "+Math.ceil(d.size*.001)+"kb \n";
+					}
+				});
+			});
+			dojo.connect(f0, "onProgress", function(data){
+				dojo.byId("fileToUpload").value = "";
+				dojo.forEach(data, function(d){
+					dojo.byId("fileToUpload").value += "("+d.percent+"%) "+d.name+" \n";
+
+				});
+			});
+			dojo.connect(f0, "onComplete", function(data){
+				dojo.forEach(data, function(d){
+					dojo.byId("uploadedFiles").value += d.file+" \n";
+					dojo.byId("rgtCol").innerHTML += '<img src="'+d.file+'" />';
+					rmFiles+=d.file+";";
+				});
+			});
+
+			Destroy = function(){
+				f0.destroyAll();
+			}
+
+		});
+
+		cleanUp = function(){
+			dojo.byId("rgtCol").innerHTML = "";
+			dojo.byId("uploadedFiles").value = "";
+			dojo.xhrGet({
+				url:uploadUrl,
+				handleAs:"text",
+				content:{
+					rmFiles:rmFiles
+				}
+			});
+			rmFiles = "";
+
+		}
+		dojo.addOnUnload(function(){
+			console.log("You're leaving the page");
+			cleanUp();
+		});
+
+
+	</script>
+    <style>
+		body{
+			font-size:100%;
+		}
+		#wrapper{
+			width:100%;
+		}
+		#fileToUpload{
+			border:#CCCCCC 1px solid;
+			overflow-y:auto;
+			overflow-x:hidden;
+		}
+		.uploadedFilesLabel{
+
+		}
+		#uploadedFiles{
+			border:#CCCC00 1px solid;
+			background:#FFFFCC;
+		}
+		.leftCol{
+			width:500px;
+			padding:5px;
+			vertical-align:top;
+		}
+		.rgtCol{
+			vertical-align:top;
+		}
+		textarea{
+			display:block;
+		}
+		#noFlash button, #hasFlash button{
+			font-size:9px;
+		}
+	</style>
+</head>
+<body class="tundra">
+	<p style="font-size:14px; width:480px; border:2px solid #ff0000; padding:3px;">
+		<strong>NOTE:</strong> This test does upload,
+		but the server scripts are renamed to <em>tests/UploadFile.php.<strong>disabled</strong></em> and
+		<em>tests/cLOG.php.<strong>disabled</strong></em> to prevent security attacks on hosted servers.
+		You should rename these files (removing <em>.disabled</em>) in your local copy to conduct tests.
+	</p>
+
+<table width="100%" border="0" cellspacing="0" cellpadding="0">
+  <tr>
+    <td class="leftCol">
+
+    	<div id="hasFlash">
+            <h1>
+            	dojox.form.FileUploader - FileInputFlash Test
+            	<br/> Flash Mode - <span id="fmode"></span>
+            </h1>
+            <div onClick="showWithoutFlash()" dojoType="dijit.form.Button">Emulate No Flash Plugin</div>
+            <div id="fbm" onClick="showMulti()" dojoType="dijit.form.Button">Switch to Multi-File mode</div>
+            <div id="fbs" onClick="showSingle()" dojoType="dijit.form.Button">Switch to Single-File mode</div>
+
+            <p>The following is an example of FileUploader trigger FileInputFlash act's with the same APIs as FileInputOverlay, so you can build your own file input. <em>For the file to actually upload, you'll need to have PHP enabled. </em></p>
+            <p id="fMulti">Multiple-file mode. You may choose multiple files from the System Dialog.</p>
+            <p id="fSingle">Single-file mode. You may choose only one from the System Dialog.</p>
+        </div>
+
+        <div id="noFlash">
+            <h1>
+            	dojox.form.FileUploader - Degraded to FileInputOverlay
+            	<br/>HTML Mode - <span id="hmode"></span>
+			</h1>
+            <div onClick="showWithFlash()" dojoType="dijit.form.Button">Normal Flash Plugin Mode</div>
+            <div id="hbm" onClick="showMulti()" dojoType="dijit.form.Button">Switch to Multi-File mode</div>
+            <div id="hbs" onClick="showSingle()" dojoType="dijit.form.Button">Switch to Single-File mode</div>
+
+            <p>The following is an example of the user not having the Flash plugin installed, and the FileUploader degrading to the FileInputOverlay, except in Opera, which does not support the HTML file input overlay.</p>
+            <p id="hMulti">Multiple-file mode. You may upload multiple files by adding files to the upload list, one at a time.</p>
+            <p id="hSingle">Single-file mode. You may choose only one from the System Dialog.</p>
+        </div>
+
+
+		<span id="selectBtn">Select Images...</span>
+
+		<span id="fTypes">Choose from these types:</span>
+
+        <textarea cols="50" rows="6" id="fileToUpload"></textarea>
+
+        <div id="uploadBtn" class="uploadBtn" onClick="doUpload();" dojoType="dijit.form.Button">Upload</div>
+
+        <div class="uploadedFilesLabel">Uploaded Files:</div>
+
+        <textarea cols="50" rows="4" id="uploadedFiles"></textarea>
+
+        <div onClick="cleanUp()" dojoType="dijit.form.Button">Remove Files</div>
+        <!-- Test destroy: <div onClick="Destroy()" dojoType="dijit.form.Button">Destroy()</div> -->
+    </td>
+    <td id="rgtCol"> </td>
+  </tr>
+</table>
+</body>
+</html>
diff --git a/dojox/form/tests/test_FileUploaderCSS.html b/dojox/form/tests/test_FileUploaderCSS.html
new file mode 100644
index 0000000..53877df
--- /dev/null
+++ b/dojox/form/tests/test_FileUploaderCSS.html
@@ -0,0 +1,264 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html lang="en">
+<head>
+    <title>FileUploader CSS Test</title>
+    <link href="../../../dijit/themes/dijit.css" rel="stylesheet" />
+    <link href="../../../dijit/themes/tundra/form/Button.css" rel="stylesheet" />
+    <link href="../resources/FileUploader.css" rel="stylesheet" />
+	<script>
+        djConfig = {
+            isDebug: true,
+			popup:true,
+            parseOnLoad: true
+        }
+    </script>
+    <script src="../../../dojo/dojo.js"></script>
+    <script>
+        dojo.require("dojox.form.FileUploader");
+        dojo.require("dijit.form.Button");
+		
+        dojo.addOnLoad(function(){
+			
+			var props = {
+				isDebug:false,
+				hoverClass:"btnDftHover",
+				activeClass:"btnDftActive"
+			}
+			if(dijit.byId("btnD"))
+				new dojox.form.FileUploader(dojo.mixin({button:dijit.byId("btnD")}, props));
+			
+		});
+        
+        
+    </script>
+    <style>
+		body{
+			font-family:sans-serif;
+		}
+		table td{
+			width:33%;
+			vertical-align:top;
+		}
+		.scrolls{
+			width:100%;
+			height:75px;
+			overflow-y:scroll;
+			position:relative;
+		}
+		.note{
+			font-size:11px;
+			font-family:sans-serif;
+			color:#666;
+			width:400px;
+			margin-top:15px;
+		}
+		.note.nw{
+			width:auto !important;
+		}
+		h3{
+			width:600px;
+			font-weight:normal;
+			font-size:14px;
+		}
+    </style>
+	
+	<style>
+		.flashBtn{
+            border:2px solid #333333;
+            background:url(images/grad.jpg) #d0d0d0 repeat-x scroll 0px bottom;
+            font-size:12px;
+            font-family:Arial;
+            padding:5px;
+            width:100px;
+            height:100px;
+			vertical-align:middle; /* emulates a <button> */
+			text-align:center;
+        }
+        .flashBtnHover{
+            background-image:url(images/grad_over.jpg);
+			color:#fff;
+            cursor:pointer;
+        }
+        .flashBtnPress{
+            background-image:url(images/grad_down.jpg);
+        }
+		.top{
+			vertical-align:top;
+		}
+		.bot{
+			vertical-align:bottom;
+			padding-bottom:15px;
+		}
+		.ctr{
+			border:#666 solid 6px;
+			margin-left:60px;
+		}
+		.left{
+			text-align:left;
+		}
+		
+		
+		.gfx{
+			width:197px;
+			height:29px;
+			background:url(images/rndBtn_norm.png) no-repeat;
+			border:0;
+			text-align:left;
+			padding-left:55px;
+			
+			font-size:14px;
+			color:#fff;
+			font-weight:bold;
+			font-style:italic;
+			vertical-align:middle;
+		}
+		.gfxOver{
+			background:url(images/rndBtn_over.png) no-repeat;
+			color:#fdfc9f;
+		}
+		.gfxDown{
+			background:url(images/rndBtn_down.png) no-repeat;
+			color:#c6dfe3;
+		}
+		
+		.sprite{
+			width:197px;
+			height:29px;
+			background:url(images/rndBtnSprite.png) #fff no-repeat 0px -0px;
+			border:0;
+			text-align:left;
+			padding-left:55px;
+			
+			font-size:14px;
+			color:#fff;
+			font-weight:bold;
+			font-style:italic;
+			
+		}
+		.spriteOver{
+			background:url(images/rndBtnSprite.png) no-repeat 0px -30px;
+			color:#fdfc9f;
+		}
+		.spriteDown{
+			background:url(images/rndBtnSprite.png) no-repeat 0px -60px;
+			color:#c6dfe3;
+		}
+		.floatLeft{
+			float:left;
+			margin-left:5px;
+			width:150px;
+		}
+		.block{
+			display:block;
+		}
+		.wrapping{
+			width:100px;
+			height:60px;
+			
+			white-space:normal;
+			line-height:12px !important;
+			vertical-align:top;
+			padding-top:10px;
+		}
+	</style>
+</head>
+<body class="tundra">
+	<h1>FileUploader CSS Test</h1>
+	
+	<h3>
+		All the buttons on this page are either Flash or HTML uploaders. They all should open a
+		file-browse dialog, but otherwise the uploading is non-functional. This page is for testing
+		rendering and layout. This takes a while to render in IE, but it's not a real-world test.
+		<strong>NOTE: This test opens a Browse Dialog, but does not upload.</strong>
+	</h3>
+
+	<div class="note">
+		Testing default, markup (don't use a DIV unless you style it, the width is not controlled by default)
+	</div>
+	<button isDebug="true" devMode="true" dojoType="dojox.form.FileUploader">Default Markup Flash</button>
+	<button force="html" dojoType="dojox.form.FileUploader">Default Markup HTML</button>
+	
+	<div class="note">
+		Testing float right and left, and using style="" to override class. The buttons should cascade properly when resizing
+		the window.
+	</div>
+	<div style="padding:10px; border:1px solid #ccc;float:left; width:60%; margin-bottom:20px;">
+		<button class="floatLeft" dojoType="dojox.form.FileUploader">Flash Float Left</button>
+		<button force="html" class="floatLeft" dojoType="dojox.form.FileUploader">Flash Float Left</button>
+		
+		<button dojoType="dojox.form.FileUploader" style="display:block; width:150px;float:right;">Flash Float Right</button>
+		<button force="html" dojoType="dojox.form.FileUploader" style="display:block; width:150px;float:right;margin-right:5px;">HTML Float Right</button>	
+	</div>
+	
+	<div class="note">
+		Text wrapping - FileUploader does not support text wrapping natively, it needs some CSS massaging to make it happen. 
+	</div>
+	<button class="wrapping" dojoType="dojox.form.FileUploader">Using a Flash button with long wrapping text</button>
+	<button force="html" class="wrapping" dojoType="dojox.form.FileUploader">Using an HTML button with long wrapping text</button>
+	
+	<div class="note">
+		Testing Dijit Button for backward compatibility. Use of a dijit button is
+		deprecated and will be removed in 1.5. On the right is the Flash Upload button and on the left a
+		Dijit button for comparison. Note there is a bug getting the hover font style correct.
+	</div>
+	<button id="btnX" class="dBtn" dojoType="dijit.form.Button">Using Dijit Button</button>
+	<button id="btnD" class="dBtn" dojoType="dijit.form.Button">Using Dijit Button</button>
+	
+	
+	<div class="note">Testing top-center</div>
+	<div baseClass="flashBtn top" hoverClass="flashBtnHover" activeClass="flashBtnPress" dojoType="dojox.form.FileUploader">Flash Top</div>
+	
+	<div class="note">Testing bottom-center with 20px bottom padding</div>
+	<div baseClass="flashBtn bot" hoverClass="flashBtnHover" activeClass="flashBtnPress" dojoType="dojox.form.FileUploader">Flash Bottom</div>
+	
+	<div class="note">Testing centered text, wide border and a left margin</div>
+	<div id="btn1" class="flashBtn ctr" hoverClass="flashBtnHover" activeClass="flashBtnPress" dojoType="dojox.form.FileUploader">Flash Center</div>
+	
+	<div class="note">Testing left align</div>
+	<button id="btn3" class="flashBtn left" hoverClass="flashBtnHover" activeClass="flashBtnPress" dojoType="dojox.form.FileUploader">Flash Left</button>
+	
+	<div class="note">
+		Testing background images for HTML and Flash buttons. "GFX" uses three
+		different images, "SPRITE" uses one sprited image with the background-position changed. The
+		uploader doesn't support icons (you can use html in the Flash button, but it's not very good) so
+		this example uses backgrounds with icons in them, and the text shifted with a 55px left padding.
+		All of these buttons are inline.
+	</div>
+	<button class="sprite" hoverClass="spriteOver" activeClass="spriteDown" dojoType="dojox.form.FileUploader">HTML BK SPRITE</button>
+	<button class="sprite" hoverClass="spriteOver" activeClass="spriteDown" dojoType="dojox.form.FileUploader">FLASH BK SPRITE</button>
+	<button class="gfx" hoverClass="gfxOver" activeClass="gfxDown" dojoType="dojox.form.FileUploader">HTML BK GFX</button>
+	<button class="gfx" hoverClass="gfxOver" activeClass="gfxDown" dojoType="dojox.form.FileUploader">Flash BK GFX</button>
+	
+	
+	<table style="margin-bottom:30px;">
+		<tr>
+		<td>
+			<div class="scrolls">
+				<p>
+					Testing <button dojoType="dojox.form.FileUploader">Flash inline buttons</button> in a
+					scrolling pane. Also testing
+					<button dojoType="dojox.form.FileUploader">HTML inline buttons</button>.
+					Because we are no longer using an invisible Flash movie using wmode=transparent.
+					The Windows Firefox clickable bug should be fixed (and hopefully some Linux
+					problems).
+				</p>
+			</div>
+		</td>
+		<td>
+			<div class="scrolls">
+				Testing a
+			<div>	
+				<button class="block" dojoType="dojox.form.FileUploader">HTML Block Display Button</button>
+			</div>
+			in a scrolling pane. This is really just to see if IE blows up on this as well as the
+			inline test (it does). IE is not liking using innerHTML in a scrolling pane. This should
+			still work however - the button is built outside of the pane and inserted (as well as
+			the previous inline test). This will cause a slower render time.
+			</div>
+			
+		</td>
+		</tr>
+	</table>
+	
+</body>
+</html>
diff --git a/dojox/form/tests/test_FileUploaderDialog.html b/dojox/form/tests/test_FileUploaderDialog.html
new file mode 100644
index 0000000..48653f9
--- /dev/null
+++ b/dojox/form/tests/test_FileUploaderDialog.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html lang="en">
+<head>
+    <title>FileUploader Dialog Test</title>
+    <link href="../../../dijit/themes/dijit.css" rel="stylesheet" />
+	<link href="../../../dijit/themes/dijit.css" rel="stylesheet" />
+    <link href="../../../dijit/themes/tundra/form/Button.css" rel="stylesheet" />
+	<link href="../../../dijit/themes/tundra/Dialog.css" rel="stylesheet" />
+	<link href="../../../dijit/themes/tundra/layout/TabContainer.css" rel="stylesheet" />
+    <link href="../resources/FileUploader.css" rel="stylesheet" />
+	<script>
+        djConfig = {
+            isDebug: true,
+			popup:true,
+            parseOnLoad: true
+        }
+    </script>
+    <script src="../../../dojo/dojo.js"></script>
+    <script>
+        dojo.require("dojox.form.FileUploader");
+        dojo.require("dijit.form.Button");
+		dojo.require("dijit.Dialog");
+		dojo.require("dijit.form.Form");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		
+        dojo.addOnLoad(function(){
+			console.warn("show")
+			console.log("CP:", dijit.byId("dialogContentPane"))
+			var w = dijit.byId("myDialog");
+			if(w){
+				w.show();
+			}
+		});
+        
+        
+    </script>
+    <style>
+		html{
+			height:100%;
+		}
+		body{
+			font-family:sans-serif;
+			font-size:12px;
+			height:100%;
+		}
+		#tabs{
+			width:100%;
+			height:100%;
+		}
+		.dijitContentPane{
+			padding:10px;
+		}
+		table td{
+			width:33%;
+			vertical-align:top;
+		}
+		.scrolls{
+			width:100%;
+			height:75px;
+			overflow-y:scroll;
+			position:relative;
+		}
+		.note{
+			font-size:11px;
+			font-family:sans-serif;
+			color:#666;
+			width:400px;
+			margin-top:15px;
+		}
+		.note.nw{
+			width:auto !important;
+		}
+		h3{
+			width:600px;
+			font-weight:normal;
+			font-size:14px;
+		}
+		.formContent{
+			width:300px;
+			height:150px;
+		}
+		
+		#myDialog #dialogContentPane{
+			width:400px;
+			height:200px;
+			
+		}
+    </style>
+	
+	
+</head>
+<body class="tundra">
+	<h1>FileUploader Dialog Test</h1>
+	<p>
+		Tests that FileUploader will load in a dialog box. Its detecting that an ancestor is
+		a dialog and if so makes it display="block" while it gets measurements, then changes it
+		back. It then connects to the dialog's onShow and is built at that time.
+		<strong>NOTE: This test opens a Browse Dialog, but does not upload.</strong>
+	</p>
+		<div id="myDialog" class="dialog" dojoType="dijit.Dialog" title="Edit Account">
+		<div id="dialogContentPane" dojoType="dijit.layout.ContentPane">
+			<label>Dummy Upload:</label>
+			<span id="editUsername"></span>
+			<label>Password:</label>
+			<div id="editerror"></div>
+			<div id="editSubmitBtn" class="authButton" dojoType="dijit.form.Button">Submit</div>
+			
+			<button isDebug="false" devMode="false" dojoType="dojox.form.FileUploader">Default Markup Flash</button>
+			<button isDebug="true" devMode="true" force="html" dojoType="dojox.form.FileUploader">Default Markup HTML</button>
+		</div>
+	</div>
+	
+</body>
+</html>
diff --git a/dojox/form/tests/test_FileUploaderForm.html b/dojox/form/tests/test_FileUploaderForm.html
new file mode 100644
index 0000000..0ca0ce2
--- /dev/null
+++ b/dojox/form/tests/test_FileUploaderForm.html
@@ -0,0 +1,298 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html lang="en">
+<head>
+    <title>Test dojox.form.FileUploader - Form</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/form/Button.css";
+		@import "../../../dijit/themes/tundra/ProgressBar.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		@import "../resources/FileUploader.css"; 
+	</style>
+	<script>
+        djConfig = {
+            isDebug: false,
+			popup:true,
+            parseOnLoad: true
+        }
+    </script>
+    <script src="../../../dojo/dojo.js"></script>
+    <script>
+        dojo.require("dojox.form.FileUploader");
+        dojo.require("dijit.form.Button");
+		dojo.require("dijit.ProgressBar");
+		
+		addThumb = function(d, id){
+			console.log("THUMB:", d);
+			var fileRoot = dojo.moduleUrl("dojox.form", "tests").toString();
+			var img = '<img src='+fileRoot+"/"+escape(d.file)+
+			(d.width>d.height ?
+			' width="50"/>' :
+			' height="50"/>');
+			console.log("IMG:", img)
+			var str = '<div id="file_'+d.name+'" class="thumb"><div class="thumbPic">'+img+'</div>';
+			str += '<div class="thumbText">';
+			if(d.fGroup || d.hGroup){
+				str += 'Group: '+(d.fGroup || d.hGroup)+'<br/>';
+			}
+			str += 'Title: '+d.name+'<br/>';
+			if(d.author){
+				str += 'Author: '+ d.author+'<br/>';
+			}
+			if(d.date){
+				str += d.date+' ';
+			}
+			str += Math.ceil(d.size*.001)+'kb</div></div>';
+			dojo.byId(id).innerHTML += str;
+		}
+        dojo.addOnLoad(function(){
+		
+			var props = {
+				isDebug:true,
+				devmode:true,
+				hoverClass:"uploadHover",
+				activeClass:"uploadPress",
+				disabledClass:"uploadDisabled",
+				uploadUrl:dojo.moduleUrl("dojox.form", "tests/UploadFile.php"),
+				fileMask:[
+					["Jpeg File", 	"*.jpg;*.jpeg"],
+					["GIF File", 	"*.gif"],
+					["PNG File", 	"*.png"],
+					["All Images", 	"*.jpg;*.jpeg;*.gif;*.png"]
+				]
+			}
+			
+			if(dojo.byId("btnF")){
+				dojo.byId("fFiles").value = ""; 
+				var f = new dojox.form.FileUploader(dojo.mixin({
+					progressWidgetId:"progressBar",
+					showProgress:true,
+					fileListId:"fFiles",
+					tabIndex:5,
+					selectMultipleFiles:true,
+					//uploadOnChange:true,
+					deferredUploading:false
+				},props), "btnF");
+				f.attr("disabled", dojo.byId("fGroup").value=="");
+				dojo.connect(dojo.byId("fGroup"), "keyup", function(){
+					f.attr("disabled", dojo.byId("fGroup").value=="");
+				});
+				dojo.connect(dijit.byId("fSubmit"), "onClick", function(){
+					f.submit(dojo.byId("formF"));
+				});
+				dojo.connect(f, "onChange", function(dataArray){
+					console.log("onChange.data:", dataArray);
+				});
+				dojo.connect(f, "onComplete", function(dataArray){
+					console.log("onComplete Data:", dataArray)
+					dojo.forEach(dataArray, function(d){
+						addThumb(d, "fThumbs");
+					});
+				});
+			}
+
+
+			if(dojo.byId("btnH")){
+				dojo.byId("hFiles").value = "";
+				var h = new dojox.form.FileUploader(dojo.mixin({
+					force:"html",
+					showProgress:true,
+					progressWidgetId:"progressBarHtml",
+					selectMultipleFiles:true,
+					//uploadOnChange:true,
+					fileListId:"hFiles",
+					tabIndex:11,
+					devMode:true
+				}, props), "btnH");
+				
+				h.attr("disabled", dojo.byId("hGroup").value=="");
+				dojo.connect(dojo.byId("hGroup"), "keyup", function(){
+					h.attr("disabled", dojo.byId("hGroup").value=="");
+				});
+				dojo.connect(dijit.byId("hSubmit"), "onClick", function(evt){
+					h.submit(dojo.byId("formH"));
+					dojo.stopEvent(evt);
+				});
+				dojo.connect(h, "onComplete", function(dataArray){
+					console.warn("html onComplete", dataArray)
+					dojo.forEach(dataArray, function(d){
+						addThumb(d, "hThumbs");
+					});
+				});
+				dojo.connect(h, "onError", function(err){
+					console.error("html error", err)
+				});
+			}
+			if(dijit.byId("btnD")){
+				var d = new FlashHTML.widget(dojo.mixin({button:dijit.byId("btnD")}, props));
+				d.attr("disabled", dojo.byId("dTitle").value=="");
+				dojo.connect(dojo.byId("dTitle"), "keyup", function(){
+					d.attr("disabled", dojo.byId("dTitle").value=="");
+				});
+				dojo.connect(dijit.byId("fSubmit"), "onClick", function(evt){
+					f.submit(dojo.byId("formF"));
+					dojo.stopEvent(evt);
+				});
+			}
+			
+			
+		});
+        
+        
+    </script>
+    <style>
+       html, body{
+		font-family:sans-serif;
+		font-size:12px;
+	   }
+		.uploadBtn{
+			border:1px solid #333333;
+			background:url(../../../dijit/themes/soria/images/buttonEnabled.png) #d0d0d0 repeat-x scroll 0px top;
+			font-size:14px;
+			font-family:Arial;
+			width:201px;
+			height:30px;
+			line-height:50px;
+			vertical-align:middle; /* emulates a <button> */
+			text-align:center;
+		}
+		.uploadHover{
+			background-image:url(../../../dijit/themes/soria/images/buttonHover.png);
+			cursor:pointer;
+			font-weight:bold;
+			font-style:italic;
+			font-family:serif;
+		}
+		.uploadPress{
+			background-image:url(../../../dijit/themes/soria/images/buttonActive.png);
+		}
+		.uploadDisabled{
+			background-image:none;
+			background-color:#666;
+			color:#999;
+			border:1px solid #999;
+			font-family:serif;
+			font-style:italic;
+		}
+		.progBar{
+			width:294px;
+			display:none;
+		}
+		.form{
+			width:300px;
+			border:1px solid #ccc;
+			margin:5px;
+			padding:3px;
+			position:relative;
+		}
+		.form, .thumbList{
+			float:left;
+		}
+		.thumbList{
+			width:300px;
+			border:1px solid #ccc;
+			min-height:100px;
+			margin:5px;
+			padding:3px;
+		}
+		#fFiles, #hFiles{
+			width:200px;
+			height:75px;
+			overflow-x:hidden;
+			overflow-y:auto;
+			border:1px solid #ccc;
+		}
+		.form .field{
+			width:197px;
+		}
+		.tbl{
+			width:100%;
+		}
+		.tbl td{
+			width:50%;
+			vertical-align:top;
+		}
+		.form label{
+			position:absolute;
+			width:80px;
+			text-align:right;
+			left:0px;
+		}
+		.form .field, .form .btn{
+			margin-left:85px;
+			margin-bottom:5px;
+		}
+		h3{
+			width:600px;
+			font-weight:normal;
+			font-size:14px;
+		}
+		ul{
+			font-size:12px;
+			width:600px;
+		}
+    </style>
+</head>
+<body class="tundra">
+  <h1>FileUploader Widget Form Test</h1>
+	<p style="font-size:14px; width:480px; border:2px solid #ff0000; padding:3px;">
+		<strong>NOTE:</strong> This test does upload,
+		but the server scripts are renamed to <em>tests/UploadFile.php.<strong>disabled</strong></em> and
+		<em>tests/cLOG.php.<strong>disabled</strong></em> to prevent security attacks on hosted servers.
+		You should rename these files (removing <em>.disabled</em>) in your local copy to conduct tests. 
+	</p>
+	<h3>Both forms on this page are the same except one is for testing the Flash Uploader and one
+	is for the HTML Uploader. The following features are being tested:</h3>
+	<ul>
+		<li>Disabled: The Uploaders are disabled unless the Group field is populated.</li>
+		<li>Submit: The Submit buttons actually submit to the uploaders, and they post the data.</li>
+		<li>Post Data: Post data is tested. The field data should be in the thumbnails.</li>
+		<li>Selected List: If passing the ID of a container, the Uploaders will populate it with
+		the selected files.</li>
+		<li>Deleting Files: You can now delete pending files.</li>
+		<li>Progress Built in: showProgress:true will change the button to a progress bar on upload.</li>
+		<li>Progress Attach: Passing progressWidgetId will tell the Uploader of a progress widget.
+		If the Progress widget is initially hidden, it will change to visible and then restored after
+		upload.</li>
+		<li>A11Y: The Flash button can be accessed with the TAB key. (The HTML cannot due to browser
+		limtations)</li>
+	</ul>
+	<table class="tbl">
+		<tr>
+			<td>
+			<form id="formF" class="form">
+				<label>Group Name:</label>
+				<input class="field" tabIndex="1" type="text" value="" id="fGroup" name='fGroup' /><br/>
+				<label>Date:</label>
+				<input class="field" tabIndex="2" type="text" value="" id="fDate" name='date' /><br/>
+				<label>Author:</label>
+				<input class="field" tabIndex="3" type="text" value="" id="fAuthor" name='author' /><br/>
+				<label>Files:</label>
+				<div id="fFiles" class="field"></div>
+				<div tabIndex="5" id="btnF" class="uploadBtn btn">Flash Select Files</div>
+				<button tabIndex="6" id="fSubmit" class="btn" dojoType="dijit.form.Button" onclick="return false;">Submit</button>
+				<div indeterminate="false" id="progressBar" class="progBar" dojoType="dijit.ProgressBar"></div>
+			</form>
+			<div id="fThumbs" class="thumbList"></div>
+		</td>
+		<td>
+			<form id="formH" class="form">	
+				<label>Group Name:</label>
+				<input class="field" tabIndex="7" type="text" value="" id="hGroup" name='hGroup' /><br/>
+				<label>Date:</label>
+				<input class="field" tabIndex="8" type="text" value="" id="hDate" name='date' /><br/>
+				<label>Author:</label>
+				<input class="field" tabIndex="9" type="text" value="" id="hAuthor" name='author' /><br/>
+				<label>Files:</label>
+				<div  class="field" id="hFiles"></div>
+				<div tabIndex="11"  id="btnH" class="uploadBtn btn">HTML Select Files</div>
+				<button tabIndex="12"  class="btn" id="hSubmit" class="" onclick="return false;" dojoType="dijit.form.Button">Submit</button>
+				<div indeterminate="false" id="progressBarHtml" class="progBar" dojoType="dijit.ProgressBar"></div>
+			</form>
+			<div id="hThumbs" class="thumbList"></div>
+		</td>
+		</tr>
+	</table>
+</body>
+</html>
diff --git a/dojox/form/tests/test_FileUploaderTabs.html b/dojox/form/tests/test_FileUploaderTabs.html
new file mode 100644
index 0000000..2e87947
--- /dev/null
+++ b/dojox/form/tests/test_FileUploaderTabs.html
@@ -0,0 +1,147 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html lang="en">
+<head>
+    <title>FileUploader TabContainer Test</title>
+    <link href="../../../dijit/themes/dijit.css" rel="stylesheet" />
+	<link href="../../../dijit/themes/dijit.css" rel="stylesheet" />
+    <link href="../../../dijit/themes/tundra/form/Button.css" rel="stylesheet" />
+	<link href="../../../dijit/themes/tundra/Dialog.css" rel="stylesheet" />
+	<link href="../../../dijit/themes/tundra/layout/TabContainer.css" rel="stylesheet" />
+    <link href="../resources/FileUploader.css" rel="stylesheet" />
+	<script>
+        djConfig = {
+            isDebug: true,
+			popup:true,
+            parseOnLoad: true
+        }
+    </script>
+    <script src="../../../dojo/dojo.js"></script>
+    <script>
+        dojo.require("dojox.form.FileUploader");
+        dojo.require("dijit.form.Button");
+		dojo.require("dijit.Dialog");
+		dojo.require("dijit.form.Form");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		
+		var fakeTab;
+		showFake = function(){
+			dojo.style(fakeTab, "left", "0px");
+		}
+		hideFake = function(){
+			dojo.style(fakeTab, "left",  "-2000px");
+		}
+        dojo.addOnLoad(function(){
+			var tab = dijit.byId("tab3");
+			fakeTab = dojo.byId("fakeTab");
+			hideFake();
+			dojo.connect(tab, "onShow", showFake);
+			dojo.connect(tab, "onHide", hideFake);
+		});
+        
+        
+    </script>
+    <style>
+		html{
+			height:100%;
+		}
+		body{
+			font-family:sans-serif;
+			font-size:12px;
+			height:100%;
+		}
+		#tabs{
+			width:60%;
+			height:250px;
+			margin:0px 20%;
+		}
+		.dijitContentPane{
+			padding:10px;
+		}
+		table td{
+			width:33%;
+			vertical-align:top;
+		}
+		.scrolls{
+			width:100%;
+			height:75px;
+			overflow-y:scroll;
+			position:relative;
+		}
+		.note{
+			font-size:11px;
+			font-family:sans-serif;
+			color:#666;
+			width:400px;
+			margin-top:15px;
+		}
+		.note.nw{
+			width:auto !important;
+		}
+		h3{
+			width:600px;
+			font-weight:normal;
+			font-size:14px;
+		}
+		.formContent{
+			width:300px;
+			height:150px;
+		}
+		
+		#myDialog #dialogContentPane{
+			width:400px;
+			height:200px;
+			
+		}
+		#fakeTab{
+			position:absolute;
+			left:0px;
+			top:125px;
+			width:60%;
+			height:250px;
+			margin:0px 20%;
+			padding:15px;
+		}
+    </style>
+	
+	
+</head>
+<body class="tundra">
+	<h1>FileUploader TabContainer Test</h1>
+	<h3>
+		Testing that FileUploader works in Tabs initially shown and initially hidden.
+		<strong>See important node below</strong>
+	</h3>
+	
+	 <div id="tabs" dojoType="dijit.layout.TabContainer" persist="false" tabStrip="true">
+		<div id="tab1" dojoType="dijit.layout.ContentPane" title="Tab 1">
+			<button isDebug="false" devMode="false" dojoType="dojox.form.FileUploader">Tab #1 Flash</button>
+			<button isDebug="false" devMode="false" force="html" dojoType="dojox.form.FileUploader">Tab #1 HTML</button>
+		</div>
+		<div id="tab2" dojoType="dijit.layout.ContentPane" title="Tab 2">			
+			<button isDebug="false" devMode="false" dojoType="dojox.form.FileUploader">Tab #2 Flash</button>
+			<button isDebug="false" devMode="false" force="html" dojoType="dojox.form.FileUploader">Tab #2 HTML</button>
+		</div>
+		<div id="tab3" dojoType="dijit.layout.ContentPane" title="Tab 3">			
+		</div>
+	</div>
+	 
+	<div id="fakeTab">
+			<button isDebug="false" devMode="false" dojoType="dojox.form.FileUploader">Tab #3 Flash</button>
+			<button isDebug="false" devMode="false" force="html" dojoType="dojox.form.FileUploader">Tab #3 HTML</button>
+	</div>
+	
+	<p style="font-size:12px; border:2px solid #ff0000; padding:3px;">
+		<strong>NOTE:</strong> This test shows FileUploader successfully being created in TabContainers, <strong>BUT</strong>
+		there is a serious limitation in the Flash version for Firefox and Safari. When a node in those browsers is hidden
+		(or essentially repainted which can mean other style applications) the SWF is reloaded. This means that if you browse
+		for a file but don't upload upload it, change the tab and return, the files will no longer be in the FileUploader.
+		This problem can be seen when tabbing between Tab 1 and Tab 2 and observing the console logs and you will see the
+		SWF reinitializes. This problem does not exist in Internet Explorer. The HTML version of the Uploader should also
+		work fine.
+		<br/><br/>
+		This test also shows work around for the problem. View source of this test and see that in Tab 3, the FileUploader
+		is in a seperate div floating over the TabContainer. When Tab #3 is shown and hidden, the div is moved off and on screen.
+	</p>
+</body>
+</html>
diff --git a/dojox/form/tests/test_ListInput.html b/dojox/form/tests/test_ListInput.html
new file mode 100755
index 0000000..083911e
--- /dev/null
+++ b/dojox/form/tests/test_ListInput.html
@@ -0,0 +1,189 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="pragma" content="no-cache" />
+	<meta http-equiv="expires" content="-1" />
+	<title>test ListInput</title>
+	<style type="text/css" title="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		
+		@import "../../../dojox/form/resources/ListInput.css";
+		
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="debugAtAllCost:true,isDebug: true,parseOnLoad:true"></script>
+	
+	<script type="text/javascript">
+		//not for test
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.form.Button");
+		var current="list_0";
+		dojo.addOnLoad(function(){
+			dojo.connect(tabC,"selectChild",function(pageId) {
+				current=(typeof pageId=="object")?pageId.id:pageId;
+				current="list_" + current.split("_").pop();
+			});
+		});
+		
+		
+		//test begining
+		dojo.require("dojox.form.ListInput");
+		dojo.require("dojox.validate.regexp");
+		
+		
+		getValues=function() {
+			console.warn(window[current].attr("value"));
+		};
+		getValuesMatch=function() {
+			console.warn(window[current].attr("MatchedValue"));
+		};
+		getValuesMisMatch=function() {
+			console.warn(window[current].attr("MismatchedValue"));
+		};
+		
+		disable=function(disable) {
+			window[current].attr("disabled",disable);
+		};
+		reset=function() {
+			window[current].reset();
+		};
+		undo=function() {
+			window[current].undo();
+		};
+		
+		addedVal=0;
+		addValue=function() {
+			window[current].add("new item " + (++addedVal));
+		};
+		addValues=function() {
+			var vals=[];
+			for (var i=0;i<3;i++) {
+				vals.push("new item " + (++addedVal));
+			}
+			window[current].add(vals);
+		};
+	</script>
+</head>
+<body class="tundra">
+	<h1>ListInput</h1>
+	<div>
+		<a href="dl.php?file=dojox/form/ListInput.js">Download ListInput.js</a><br />
+		<a href="dl.php?file=dojox/form/resources/ListInput.css">Download ListInput.css</a><br />
+	</div>
+	
+	<blockquote>
+		Enter some element in the list. <br />
+		Separate them by comma or just press enter
+	</blockquote>
+	
+	<h1>Actions</h1>
+	<a dojoType="dijit.form.Button" onclick="disable(true);">Disable</a>
+	<a dojoType="dijit.form.Button" onclick="disable(false);">Enable</a>
+	<a dojoType="dijit.form.Button" onclick="undo();">Undo</a>
+	<a dojoType="dijit.form.Button" onclick="reset();">Reset</a>
+	<a dojoType="dijit.form.Button" onclick="addValue();">Add an item</a>
+	<a dojoType="dijit.form.Button" onclick="addValues();">Add 3 items</a>
+	<a dojoType="dijit.form.Button" onclick="getValues();">See all values in firebug</a>
+	<a dojoType="dijit.form.Button" onclick="getValuesMatch();">See validated values in firebug</a>
+	<a dojoType="dijit.form.Button" onclick="getValuesMisMatch();">See unvalidated values in firebug</a>
+	
+	<h1>Demos</h1>
+	<div jsId="tabC" dojoType="dijit.layout.TabContainer" tabStrip="true" style="width: 100%; height:300px;">
+		<div dojoType="dijit.layout.ContentPane" title="Demo 1">
+			<h1>With inputbox and editable items</h1>
+			
+			<blockquote>
+				note : you can move between all editable area with left and right arrow.<br />
+				This feature can be desactivated
+			</blockquote>
+			
+			<div value="initial item 1" jsId="list_0" name="list" dojoType="dojox.form.ListInput"></div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Demo 2">
+			<h1>Without inputbox and with editable items</h1>
+			
+			<blockquote>
+				note : you can move between all editable area with left and right arrow<br />
+				This feature can be desactivated
+			</blockquote>
+			
+			<div value="initial item 1" jsId="list_1" readOnlyInput="true" dojoType="dojox.form.ListInput"></div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Demo 3">
+			<h1>Without initial value</h1>
+			<div jsId="list_2" dojoType="dojox.form.ListInput"></div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Demo 4">
+			<h1>With inputbox and without editable items</h1>
+			<div value="initial item 1" jsId="list_3" readOnlyItem="true"  dojoType="dojox.form.ListInput"></div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Demo 5">
+			<h1>Without inputbox and without editable items</h1>
+			<div value="initial item 1" jsId="list_4" readOnlyItem="true" readOnlyInput="true" dojoType="dojox.form.ListInput"></div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Demo 6">
+			<h1>With validation</h1>
+			<blockquote>
+				note : enter only digits
+			</blockquote>
+			<div value="1234" jsId="list_5" regExp="[0-9]+" dojoType="dojox.form.ListInput"></div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Demo 7">
+			<h1>With custom separator</h1>
+			<blockquote>
+				note : you can use semi-colon for separate item<br />
+				You also can use an array of separators
+			</blockquote>
+			<div value="initial item 1" jsId="list_6" delimiter=";" dojoType="dojox.form.ListInput"></div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Demo 8">
+			<h1>With a submit form</h1>
+			<blockquote>
+				note : after submit, see url
+			</blockquote>
+			<form action="?" method="get">
+				<div value="initial item 1" name="demo8" jsId="list_7" dojoType="dojox.form.ListInput"></div>
+				<input type="submit" />
+			</form>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Demo 9">
+			<h1>With a submit form - submit only validated value</h1>
+			<blockquote>
+				note : after submit, see url<br />
+				enter only digits
+			</blockquote>
+			<form action="?" method="get">
+				<div name="demo9" jsId="list_8" value="invalid value,1234" regExp="[0-9]+" submitOnlyValidValue="true" dojoType="dojox.form.ListInput"></div>
+				<input type="submit" />
+			</form>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Demo 10">
+			<h1>With a max number of items</h1>
+			<blockquote>
+				note : you can only add 3 items
+			</blockquote>
+			<div value="initial item 1" jsId="list_9" maxItems="3" dojoType="dojox.form.ListInput"></div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Demo 11">
+			<h1>Without close button</h1>
+			<blockquote>
+				note : you can specify if you want close button : <br />
+				- only on validated value<br />
+				- only on unvalidated value<br />
+				- never<br />
+				- always<br />
+			</blockquote>
+			<div jsId="list_10" showCloseButtonWhenValid="false" showCloseButtonWhenInvalid="false" dojoType="dojox.form.ListInput"></div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" title="Demo 12">
+			<h1>Without anim</h1>
+			<div value="initial item 1" jsId="list_11" useAnim="false" dojoType="dojox.form.ListInput"></div>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/form/tests/test_Manager1.html b/dojox/form/tests/test_Manager1.html
new file mode 100644
index 0000000..42faeb7
--- /dev/null
+++ b/dojox/form/tests/test_Manager1.html
@@ -0,0 +1,213 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.form.Manager (test #1)</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		fieldset		{ border: 1px solid; margin: 1em; padding: 1em; }
+		legend 			{ font-weight: bolder; font-size: larger; }
+
+		#result			{ background-color: white; }
+		#result th		{ font-weight: bolder; }
+		#result .hilite	{ background-color: #fd8; }
+
+		.makeYellow		{ background-color: #ffa; }
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../manager/Mixin.js"></script>
+	<script type="text/javascript" src="../manager/FormMixin.js"></script>
+	<script type="text/javascript" src="../manager/ValueMixin.js"></script>
+	<script type="text/javascript" src="../manager/EnableMixin.js"></script>
+	<script type="text/javascript" src="../manager/DisplayMixin.js"></script>
+	<script type="text/javascript" src="../manager/ClassMixin.js"></script>
+	<script type="text/javascript" src="../Manager.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.form.Manager");
+
+		dojo.require("dijit.dijit");			// optimize: load dijit layer
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.CheckBox");	// includes dijit.form.RadioButton
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.SimpleTextarea");
+		dojo.require("dijit.form.Select");
+
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.ContentPane");
+
+		dojo.require("dojo.parser");
+
+		dojo.addOnLoad(function(){
+			// show values the first time
+			dijit.byId("form").showValues();
+		});
+	</script>
+</head>
+<body class="tundra">
+
+	<div dojoType="dijit.layout.BorderContainer" design="sidebar" gutters="false" liveSplitters="false" style="height: 50em;">
+		<div dojoType="dijit.layout.ContentPane" region="left" splitter="true" style="width: 15em;">
+			<table id="result" border="1">
+				<thead>
+					<th>Name</th>
+					<th>Value</th>
+				</thead>
+				<tbody id="table"></tbody>
+			</table>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="center" splitter="true" style="width: 50em;">
+			<form dojoType="dojox.form.Manager" id="form">
+				<fieldset dojoAttachPoint="part1">
+					<legend>HTML form elements</legend>
+					<div>
+						<input type="checkbox" id="e01" name="e01" value="e01" observer="showValues, logRadio">
+						 <label for="e01">e01 input/checkbox</label>
+					</div>
+					<div>
+						<input type="radio" id="e021" name="e02" value="e02-1" observer="showValues">
+						 <label for="e021">e02-1 input/radio</label>
+						 
+						<input type="radio" id="e022" name="e02" value="e02-2" checked="checked">
+						 <label for="e022">e02-2 input/radio</label>
+					</div>
+					<div>
+						<input type="text" id="e03" name="e03" value="e03" observer="showValues">
+						 <label for="e03">e03 input/text</label>
+					</div>
+					<div>
+						<input type="password" id="e04" name="e04" value="e04" observer="showValues">
+						 <label for="e04">e04 input/password</label>
+					</div>
+					<div>
+						<input type="hidden" id="e05" name="e05" value="e05" observer="showValues">
+						 <label for="e05">e05 input/hidden</label>
+					</div>
+					<div>
+						<select id="e06" name="e06" observer="showValues">
+							<option value="e06-1">e06-1 first</option>
+							<option value="e06-2" selected="selected">e06-2 second</option>
+						</select>
+						 <label for="e06">e06 select</label>
+					</div>
+					<div>
+						<label for="e07">e07 textarea</label><br>
+						<textarea id="e07" name="e07" observer="showValues"
+							rows="3" cols="15" style="width: 15em;">e07</textarea>
+					</div>
+					<div>
+						<button name="e08" observer="showValues">e08 button</button> 
+						<input type="button" name="e09" value="e09 input/button" observer="showValues"> 
+						<input type="reset" name="e10" value="e10 input/reset" observer="showValues"> 
+						<input type="submit" name="e11" value="e11 input/submit" observer="showValues">
+					</div>
+				</fieldset>
+				<fieldset dojoAttachPoint="part2">
+					<legend>Dijit form widgets</legend>
+					<div>
+						<input type="checkbox" dojoType="dijit.form.CheckBox" id="w01" name="w01" value="w01" observer="showValues">
+						 <label for="w01">w01 input/checkbox dijit.form.CheckBox</label>
+					</div>
+					<div>
+						<input type="radio" dojoType="dijit.form.RadioButton" id="w021" name="w02" value="w02-1" observer="showValues">
+						 <label for="w021">w02-1 input/radio dijit.form.RadioButton</label>
+						 
+						<input type="radio" dojoType="dijit.form.RadioButton" id="w022" name="w02" value="w02-2" checked="checked" observer="logRadio">
+						 <label for="w022">w02-2 input/radio dijit.form.RadioButton</label>
+					</div>
+					<div>
+						<input type="text" dojoType="dijit.form.TextBox" id="w03" name="w03" value="w03" observer="showValues" intermediateChanges="true">
+						 <label for="w03">w03 input/text dijit.form.TextBox with intermediateChanges="true"</label>
+					</div>
+					<div>
+						<input type="password" dojoType="dijit.form.TextBox" id="w04" name="w04" value="w04" observer="showValues">
+						 <label for="w04">w04 input/password dijit.form.TextBox</label>
+					</div>
+					<div>
+						<select dojoType="dijit.form.Select" id="w06" name="w06" observer="showValues">
+							<option value="w06-1">w06-1 first</option>
+							<option value="w06-2" selected="selected">w06-2 second</option>
+						</select>
+						 <label for="w06">w06 select dijit.form.Select</label>
+					</div>
+					<div>
+						<label for="w07">w07 textarea dijit.form.SimpleTextarea with intermediateChanges="true"</label><br>
+						<textarea dojoType="dijit.form.SimpleTextarea" id="w07" name="w07" observer="showValues"
+							rows="3" cols="15" style="width: 15em;" intermediateChanges="true">w07</textarea>
+					</div>
+					<div>
+						<button dojoType="dijit.form.Button" name="w08" observer="showValues">w08 button</button> 
+						<button type="button" dojoType="dijit.form.Button" name="w09" observer="showValues">w09 type=button</button> 
+						<button type="reset" dojoType="dijit.form.Button" name="w10" observer="showValues">w10 type=reset</button> 
+						<button type="submit" dojoType="dijit.form.Button" name="w11" observer="showValues">w11 typesubmit</button>
+					</div>
+				</fieldset>
+				<script type="dojo/method" event="onSubmit">
+					// do not submit this form
+					return false;
+				</script>
+				<script type="dojo/method" event="logRadio">
+					// sample observer: logs radio buttons by name
+					var values = this.gatherFormValues(["e02", "w02"]);
+					console.log("e02: " + values.e02 + ", w02: " + values.w02);
+				</script>
+				<script type="dojo/method" event="showValues" args="value,name">
+					if(name){
+						// first time this method is called with no parameters
+						// show the name and the value otherwise
+						console.log("name = ", name, " value = ", value);
+					}
+					var values = this.gatherFormValues(),
+						table = dojo.byId("table"), names = [];
+					// clear the table
+					while(table.lastChild){
+						dojo.destroy(table.lastChild);
+					}
+					// show gathered values
+					for(var name in values){
+						if(values.hasOwnProperty(name)){
+							names.push(name);
+						}
+					}
+					names.sort();
+					dojo.forEach(names, function(name){
+						var tr  = dojo.doc.createElement("tr"),
+							tdn = dojo.doc.createElement("td"),
+							tdv = dojo.doc.createElement("td");
+						tdn.innerHTML = name;
+						tdv.innerHTML = "" + values[name];
+						if(this._oldValues && this._oldValues[name] != values[name]){
+							dojo.addClass(tr, "hilite");
+						}
+						tr.appendChild(tdn);
+						tr.appendChild(tdv);
+						table.appendChild(tr);
+					}, this);
+					this._oldValues = values;
+				</script>
+			</form>
+		</div>
+	</div>
+
+	<p>
+		<input type="checkbox" id="c01" name="c01" value="c01" checked="checked"
+			onclick="dijit.byId('form')[this.checked ? 'enable' : 'disable']()">
+		 <label for="c01">enable the form elements and widgets</label>
+		<br>
+		<input type="checkbox" id="c02" name="c02" value="c02"
+			onclick="dijit.byId('form')[this.checked ? 'addClass' : 'removeClass']('makeYellow', ['part1', 'part2'])">
+		 <label for="c02">add/remove yellow background</label>
+		<br>
+		<input type="checkbox" id="c03" name="c03" value="c03" checked="checked"
+			onclick="dijit.byId('form')[this.checked ? 'show' : 'hide'](['part1'])">
+		 <label for="c03">show form elements</label>
+		<br>
+		<input type="checkbox" id="c04" name="c04" value="c04" checked="checked"
+			onclick="dijit.byId('form')[this.checked ? 'show' : 'hide'](['part2'])">
+		 <label for="c04">show form widgets</label>
+	</p>
+</body>
+</html>
diff --git a/dojox/form/tests/test_MultiComboBox.html b/dojox/form/tests/test_MultiComboBox.html
new file mode 100644
index 0000000..ce2689f
--- /dev/null
+++ b/dojox/form/tests/test_MultiComboBox.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+	<title>Multi-input ComboBox widget</title>
+		<style type="text/css">
+			@import "../../../dijit/themes/tundra/tundra.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+			@import "../../../dojo/resources/dojo.css";
+
+			body { margin:20px; } 
+			#widget_frogin,
+			#widget_frogin2 
+			{ width: 30em; height:1.2em; }
+
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.form.MultiComboBox"); 
+			dojo.require("dojo.data.ItemFileReadStore"); 
+			dojo.require("dijit.form.Button"); 
+		</script>
+	</head>
+	<body class="tundra">
+		
+		<h1 class="testTitle">dojox.form.MultiComboBox</h1>
+		<p>
+		This widget is an extension to ComboBox to allow "tag" style input using a datastore. Start typing
+		into the box, and your options will be presented. The default delimiter is a comma, which can be over-ridden
+		by the delimiter="" attrbute.
+		</p>
+
+		<div dojoType="dojo.data.ItemFileReadStore" jsId="memberTagStore"
+			url="_tags.json"></div>
+		
+		<h3>Default:</h3>		
+		<input dojoType="dojox.form.MultiComboBox" id="frogin"
+			store="memberTagStore"
+			value=""
+			searchAttr="tag"
+			name="tags" />
+
+		<h3>Alternate delimiter (:)</h3>
+		<input dojoType="dojox.form.MultiComboBox" id="frogin2"
+			store="memberTagStore"
+			value=""
+			delimiter=":"
+			searchAttr="tag"
+			name="tags2" />
+
+		<h3>From code:</h3>
+		<button dojoType="dijit.form.Button">
+			Make it.
+			<script type="dojo/method" event="onClick">
+				var widget = new dojox.form.MultiComboBox({
+					store:memberTagStore,
+					searchAttr:"tag"
+				},"frogin3");
+				widget.startup();
+				// only make it once. 
+				this.set('disabled', true); 
+			</script>
+		</button><br>
+
+		<input id="frogin3" name="tags3" value="" />
+		
+
+	</body>
+</html>
diff --git a/dojox/form/tests/test_PasswordValidator.html b/dojox/form/tests/test_PasswordValidator.html
new file mode 100644
index 0000000..5d1a4ef
--- /dev/null
+++ b/dojox/form/tests/test_PasswordValidator.html
@@ -0,0 +1,236 @@
+<html>
+	<head>
+	    <script type="text/javascript" 
+	        src="../../../dojo/dojo.js"
+	        djConfig="isDebug: true, parseOnLoad: true">
+	    </script>
+		<script type="text/javascript" src="../PasswordValidator.js"></script>
+	    <script type="text/javascript">
+			dojo.require("doh.runner");
+	        dojo.require("dojo.parser");
+			dojo.require("dojox.form.PasswordValidator");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.form.Form");
+			
+			dojo.addOnLoad(function(){
+				doh.register("tests",
+					[
+						function test_setDisabled(t){
+							valid1.attr("disabled", true);
+							t.t(dojo.every(dojo.query("[widgetId]", 
+													valid1.domNode).map(function(i){
+														return dijit.byNode(i);
+													}), function(i){return i.disabled;}));
+							valid1.attr("disabled", false);
+							t.t(dojo.every(dojo.query("[widgetId]", 
+													valid1.domNode).map(function(i){
+														return dijit.byNode(i);
+													}), function(i){return !i.disabled;}));
+						},
+						function test_isValid(t){
+							t.f(form1.isValid());
+							dijit.byId("nv1").attr("value", "test");
+							dijit.byId("vv1").attr("value", "Test");
+							t.f(form1.isValid());
+							dijit.byId("vv1").attr("value", "test");
+							t.t(form1.isValid());
+							t.t(form6.isValid());
+							t.is({password: ""}, form6.attr("value"));
+							dijit.byId("nv6").attr("value", "test");
+							t.f(form6.isValid());
+							t.is({password: ""}, form6.attr("value"));
+							dijit.byId("vv6").attr("value", "test");
+							t.t(form6.isValid());
+							t.is({password: "test"}, form6.attr("value"));
+						},
+						function test_getValue(t){
+							dijit.byId("nv1").attr("value", "test");
+							dijit.byId("vv1").attr("value", "Test");
+							t.is({password: ""}, form1.attr("value"));
+							dijit.byId("vv1").attr("value", "test123");
+							dijit.byId("nv1").attr("value", "test123");
+							t.is({password: "test123"}, form1.attr("value"));
+						},
+						function test_oldPW(t){
+							dijit.byId("nv2").attr("value", "test");
+							dijit.byId("vv2").attr("value", "test");
+							t.f(form2.isValid());
+							dijit.byId("ov2").attr("value", "oldpw4");
+							t.f(form2.isValid());
+							dijit.byId("ov2").attr("value", "oldpw2");
+							t.t(form2.isValid());
+						},
+						function test_getOldValue(t){
+							t.is({password: "test"}, form2.attr("value"));
+							dijit.byId("nv3").attr("value", "test");
+							dijit.byId("vv3").attr("value", "test");
+							dijit.byId("ov3").attr("value", "oldpw4");
+							t.is({password: "", oldPassword: ""}, form3.attr("value"));
+							dijit.byId("ov3").attr("value", "oldpw3");
+							dijit.byId("vv3").attr("value", "Test");
+							t.is({password: "", oldPassword: ""}, form3.attr("value"));
+							dijit.byId("vv3").attr("value", "test");
+							t.is({password: "test", oldPassword: "oldpw3"}, form3.attr("value"));							
+						},
+						function test_getValuesInTable(t){ 
+							dijit.byId("nv4").attr("value", "test"); 
+							dijit.byId("vv4").attr("value", "test"); 
+							dijit.byId("ov4").attr("value", "oldpw4"); 
+							t.is({password: "test"}, form4.attr("value")); 
+							dijit.byId("nv5").attr("value", "test"); 
+							dijit.byId("vv5").attr("value", "test"); 
+							dijit.byId("ov5").attr("value", "oldpw5"); 
+							t.is({password: "test", oldPassword: "oldpw5"}, form5.attr("value")); 
+						} 
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<link rel="stylesheet" type="text/css" href="../../../dijit/themes/tundra/tundra.css">
+		<link rel="stylesheet" type="text/css" href="../../../dijit/tests/css/dijitTests.css">
+	</head>	
+	<body class="tundra">
+		<h1 class="testTitle">Test: dojox.form.PasswordValidator</h1>
+		<h2>Automated test</h2>
+		<h4 class="testSubtitle">No old password</h4>
+		<form dojoType="dijit.form.Form" jsId="form1" action="" method="GET">
+			<div dojoType="dojox.form.PasswordValidator" jsId="valid1" name="password">
+				<label>Password: <input type="password" id="nv1" pwType="new" /></label><br>
+				<label>Validate: <input type="password" id="vv1" pwType="verify" /></label><br>
+			</div>
+		</form>
+		<hr>
+		<h4 class="testSubtitle">Old password (hard-coded to "oldpw2") - not passed to getValues</h4>
+		<form dojoType="dijit.form.Form" jsId="form2" action="" method="GET">
+			<div dojoType="dojox.form.PasswordValidator" jsId="valid2" name="password">
+				<script type="dojo/method" event="pwCheck" args="password">
+					/* 
+						NOTE:  Do NOT EVER EVER EVER do this sort of a check!!!
+						
+						This is only as an example.  You will probably want to 
+						override the pwCheck function to callback to a server to
+						verify the password (the callback will need to be 
+						syncronous) - and it's probably a good idea to validate
+						it again on form submission before actually doing
+						anything destructive - that's why the "oldName" value 
+						is there.
+						
+						And don't just fetch the password from the server 
+						either :)  Send the test password (probably hashed, for
+						security) and return from the server a status instead.
+						
+						Again - DON'T DO THIS - it is HORRIBLY INSECURE!!!!
+						
+						Security is left as an exercise to the reader :)
+					*/
+					return password === "oldpw2";
+				</script>
+				<label>Old Password: <input type="password" id="ov2" pwType="old" /></label><br>
+				<label>Password: <input type="password" id="nv2" pwType="new" /></label><br>
+				<label>Validate: <input type="password" id="vv2" pwType="verify" /></label><br>
+			</div>
+		</form>
+		<hr>
+		<h4 class="testSubtitle">Old password (hard-coded to "oldpw3") - passed to getValues</h4>
+		<form dojoType="dijit.form.Form" jsId="form3" action="" method="GET">
+			<div dojoType="dojox.form.PasswordValidator" jsId="valid3" name="password" oldName="oldPassword">
+				<script type="dojo/method" event="pwCheck" args="password">
+					console.log("Checking " + password);
+					return password === "oldpw3";
+				</script>
+				<label>Old Password: <input type="password" id="ov3" pwType="old" /></label><br>
+				<label>Password: <input type="password" id="nv3" pwType="new" /></label><br>
+				<label>Validate: <input type="password" id="vv3" pwType="verify" /></label><br>
+			</div>
+		</form>
+		<hr>
+		<h4 class="testSubtitle">In Table, Old password (hard-coded to "oldpw4") - not passed to getValues</h4> 
+		<form dojoType="dijit.form.Form" jsId="form4"> 
+				<div dojoType="dojox.form.PasswordValidator" jsId="valid4" name="password"> 
+						<script type="dojo/method" event="pwCheck" args="password"> 
+								return password === "oldpw4"; 
+						</script> 
+						<table> 
+								<tr> 
+										<td><label for="ov4">Old Password:</label></td> 
+										<td><input type="password" id="ov4" pwType="old" /></td> 
+								</tr> 
+								<tr> 
+										<td><label for="nv4">Password:</label></td> 
+										<td><input type="password" id="nv4" pwType="new" /></td> 
+								</tr> 
+								<tr> 
+										<td><label for="vv4">Validate:</label></td> 
+										<td><input type="password" id="vv4" pwType="verify" /></td> 
+								</tr> 
+						</table> 
+				</div> 
+		</form> 
+		<hr>
+		<h4 class="testSubtitle">In Table, Old password (hard-coded to "oldpw5") - passed to getValues</h4> 
+		<form dojoType="dijit.form.Form" jsId="form5"> 
+				<div dojoType="dojox.form.PasswordValidator" jsId="valid5" name="password" oldName="oldPassword"> 
+						<script type="dojo/method" event="pwCheck" args="password"> 
+								return password === "oldpw5"; 
+						</script> 
+						<table> 
+								<tr> 
+										<td><label for="ov5">Old Password:</label></td> 
+										<td><input type="password" id="ov5" pwType="old" /></td> 
+								</tr> 
+								<tr> 
+										<td><label for="nv5">Password:</label></td> 
+										<td><input type="password" id="nv5" pwType="new" /></td> 
+								</tr> 
+								<tr> 
+										<td><label for="vv5">Validate:</label></td> 
+										<td><input type="password" id="vv5" pwType="verify" /></td> 
+								</tr> 
+						</table> 
+				</div> 
+		</form> 
+		<hr>
+		<h4 class="testSubtitle">No old password, not required</h4>
+		<form dojoType="dijit.form.Form" jsId="form6">
+			<div dojoType="dojox.form.PasswordValidator" required="false" jsId="valid6" name="password">
+				<label>Password: <input type="password" id="nv6" pwType="new" /></label><br>
+				<label>Validate: <input type="password" id="vv6" pwType="verify" /></label><br>
+			</div>
+		</form>
+		<hr>
+		<button dojoType="dijit.form.Button">
+			<script type="dojo/method" event="onClick">
+				dojo.forEach([form1, form2, form3, form4, form5, form6], function(i){
+					console.dir(i.attr("value"));
+				});
+			</script>
+			Get Values
+		</button>
+		<button dojoType="dijit.form.Button">
+			<script type="dojo/method" event="onClick">
+				valid5.attr("disabled", !valid5.disabled);
+			</script>
+			Toggle Disabled
+		</button>
+		<button dojoType="dijit.form.Button">
+			<script type="dojo/method" event="onClick">
+				form1.submit();
+			</script>
+			Submit Form 1
+		</button>
+		<button dojoType="dijit.form.Button">
+			<script type="dojo/method" event="onClick">
+				form2.submit();
+			</script>
+			Submit Form 2
+		</button>
+		<button dojoType="dijit.form.Button">
+			<script type="dojo/method" event="onClick">
+				form3.submit();
+			</script>
+			Submit Form 3
+		</button>
+		
+	</body>
+</html>
diff --git a/dojox/form/tests/test_RangeSlider.html b/dojox/form/tests/test_RangeSlider.html
new file mode 100644
index 0000000..341d5b0
--- /dev/null
+++ b/dojox/form/tests/test_RangeSlider.html
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox RangeSlider Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../resources/RangeSlider.css";
+	</style>
+	
+	<style>
+		/* showing a big yellow bar */
+		#hrCustomSlider .dijitSliderProgressBar {
+			background:yellow !important;
+			height:12px;
+			overflow:visible;
+			margin-top: -5px;
+		}
+
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.form.RangeSlider");
+		dojo.require("dijit.form.HorizontalRule");
+		dojo.require("dijit.form.HorizontalRuleLabels");
+		dojo.require("dijit.form.VerticalRule");
+		dojo.require("dijit.form.VerticalRuleLabels");
+		
+		var horizOnChange = function(){
+		
+			dojo.byId('minValue').value = dojo.number.format(arguments[0][0]/100, { places:1, pattern:'#%' });
+			dojo.byId('maxValue').value = dojo.number.format(arguments[0][1]/100, { places:1, pattern:'#%' });
+	
+		}
+		
+		var vertOnChange = function(){
+			
+			console.log(arguments);
+			dojo.byId('vMinValue').value = dojo.number.format(arguments[0][1],{places:1,pattern:'#'});
+			dojo.byId('vMaxValue').value = dojo.number.format(arguments[0][0],{places:1,pattern:'#'});
+			
+		}
+		
+	</script>
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">Dojox RangeSlider test</h1>
+	Just try to drag the slider endpoints and the bar in the middle. You can also use the bumper and the arrows on the left and right to manipulate the range. It's also possible to tab through the slider parts and move the handlers or bar with left/right/up/down-button. 
+	<h2>Horizontal slider</h2>
+	<div 
+		id="hrSlider" 
+		discreteValues="11"
+		onChange="horizOnChange"
+		style="width:500px;" 
+		value="80,20" 
+		intermediateChanges="true"
+		dojoType="dojox.form.HorizontalRangeSlider">
+		<ol dojoType="dijit.form.HorizontalRuleLabels" container="topDecoration" style="height:1.2em;font-size:75%;color:gray;" count="7" constraints="{pattern:'#.00%'}"></ol>
+		<div dojoType="dijit.form.HorizontalRule" container="topDecoration" count=7 style="height:10px;margin-bottom:-5px;"></div>
+	</div>
+	Horizontal Slider Min Value:<input readonly id="minValue" size="10" value="20.0%"/><br/>
+	Horizontal Slider Max Value:<input readonly id="maxValue" size="10" value="80.0%"/><br/>
+	<button id="disableButton" dojoType="dijit.form.Button" onClick="dijit.byId('hrSlider').attr('disabled', true);dijit.byId('disableButton').attr('disabled',true);dijit.byId('enableButton').attr('disabled',false);">Disable previous slider</button>
+	<button id="enableButton"  dojoType="dijit.form.Button" onClick="dijit.byId('hrSlider').attr('disabled', false);dijit.byId('disableButton').attr('disabled',false);dijit.byId('enableButton').attr('disabled', true);" disabled>Enable previous slider</button>
+	
+	<h2>A customized horizontal slider</h2>
+	<div 
+		id="hrCustomSlider"
+		discreteValues="22"
+		dojoType="dojox.form.HorizontalRangeSlider"
+		showButtons="false"
+	></div>
+	<button id="getValues" dojoType="dijit.form.Button" onClick="console.dir(dijit.byId('hrCustomSlider').attr('value'));">Get Value</button>
+
+	<h2>Vertical slider</h2>
+	<div id="vrSlider"
+		onChange="vertOnChange"
+		style="height:300px;" 
+		value="10,90"
+		dojoType="dojox.form.VerticalRangeSlider">
+		<ol dojoType="dijit.form.VerticalRuleLabels" container="leftDecoration" style="width:2em;color:gray;" labelStyle="right:0px;">
+			<li>0</li>
+			<li>100</li>
+		</ol>
+		<div dojoType="dijit.form.VerticalRule" container="leftDecoration" count=11 style="width:5px;" ruleStyle="border-color:gray;"></div>
+		<div dojoType="dijit.form.VerticalRule" container="rightDecoration" count=11 style="width:5px;" ruleStyle="border-color:gray;"></div>
+		<ol dojoType="dijit.form.VerticalRuleLabels" 
+			container="rightDecoration" 
+			style="width:2em;color:gray;" count="4" numericMargin="100" maximum="10" constraints="{pattern:'#'}"
+		></ol>
+	</div>
+	<p>
+	Vertical Slider Max Value:<input readonly id="vMaxValue" size="10" value="50.0"/><br/>
+	Vertical Slider Min Value:<input readonly id="vMinValue" size="10" value="20.0"/><br/>
+	</p>
+</body>
+</html>
diff --git a/dojox/form/tests/test_Rating.html b/dojox/form/tests/test_Rating.html
new file mode 100644
index 0000000..99b2fed
--- /dev/null
+++ b/dojox/form/tests/test_Rating.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox Rating Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		@import "../resources/Rating.css"; 
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../../../dijit/_Templated.js"></script>
+	<script type="text/javascript" src="../../../dijit/_Container.js"></script>
+	<script type="text/javascript" src="../../../dijit/form/_FormWidget.js"></script>
+	<script type="text/javascript" src="../Rating.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser"); // scan page for widgets and instantiate them
+	</script>
+	<style>
+		/* Use bigger stars and make the node wider than the star actually is,
+		   this creates some space around the stars (use background-position to center the stars)*/
+		#rating1Box .dojoxRatingStar {
+			background-image:url(images/rating_empty.gif);
+			background-position:top center;
+			background-repeat:no-repeat;
+			height:30px;
+			width:40px;
+		}
+		
+		#rating1Box .dojoxRatingStarChecked {
+			background-image:url(images/rating_full.gif);
+		}
+		
+		#rating1Box .dojoxRatingStarHover {
+			background-image:url(images/rating_full.gif);
+			background-color:lightgrey;
+		}
+
+	</style>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">Dojox Rating test</h1>
+
+	<h3>default usage:</h3>
+	The attribute "numStars" is not given, so the default 3 stars are shown.<br />
+	<span id="rating0" dojoType="dojox.form.Rating" onChange="dojo.query('#rating0Value')[0].innerHTML = this.value"></span>
+	The value is: <b><span id="rating0Value">0</span></b>
+	<br /><br />
+
+	<h3>5 stars:</h3>
+	The attribute "numStars" is given and set to 5, the initial value is 3.<br />
+	<span dojoType="dojox.form.Rating" numStars="5" value="3"></span>
+	<br /><br />
+
+	<h3>Customized, "my big stars":</h3>
+	The stars are bigger, and styled this way that there is space around each.
+	When hovering the background color is changed too. All this is achieved via CSS, see top of this file.
+	<br />
+	The attribute "numStars" is set to 10, so we see ten stars.
+	<div id="rating1Box">
+		<span id="rating1" dojoType="dojox.form.Rating" numStars="10">
+			<script type="dojo/event" event="onChange">
+				dojo.query('#rating1Value')[0].innerHTML = this.value;
+			</script>
+			<script type="dojo/event" event="onMouseOver" args="evt,value">
+				dojo.query('#rating1HoverValue')[0].innerHTML = value;
+			</script>
+		</span>
+		<br /><br />
+		The value is: <b><span id="rating1Value">0</span></b>
+		<br />
+		The mouse is over: <b><span id="rating1HoverValue">0</span></b>
+	</div>
+
+	<h3>Spacing</h3>
+	Surrounded by text to see that it really takes all it's space
+	Surrounded by text to see that it really takes all it's space 
+	Surrounded by text to see that it really takes all it's space
+	Surrounded by text to see that it really takes all it's space 
+	Surrounded by text to see that it really takes all it's space<div dojoType="dojox.form.Rating" numStars="5" value="1"></div>
+	Surrounded by text to see that it really takes all it's space
+	Surrounded by text to see that it really takes all it's space 
+	Surrounded by text to see that it really takes all it's space
+	Surrounded by text to see that it really takes all it's space 
+	<br /><br />
+	
+	<h3>Inside a dojo form</h3>
+	<script type="text/javascript">
+		dojo.require("dijit.form.Form");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dijit.form.Button");
+	</script>
+	<form dojoType="dijit.form.Form">
+		<select dojoType="dijit.form.FilteringSelect">
+			<option>Does</option>
+			<option>this</option>
+			<option>work?</option>
+		</select>
+		<br /><br />
+		<div dojoType="dojox.form.Rating" numStars="5" value="1"></div>
+		<br /><br />
+		<button dojoType="dijit.form.Button">Click me</button>
+	</form>
+</body>
+</html>
diff --git a/dojox/form/tests/test_SelectStack.html b/dojox/form/tests/test_SelectStack.html
new file mode 100644
index 0000000..1978752
--- /dev/null
+++ b/dojox/form/tests/test_SelectStack.html
@@ -0,0 +1,129 @@
+<html>
+	<head>
+	    <script type="text/javascript" 
+	        src="../../../dojo/dojo.js"
+	        djConfig="isDebug: true, parseOnLoad: true">
+	    </script>
+	    <script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.require("dojox.form.DropDownStack");
+			dojo.require("dojox.form.RadioStack");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.form.Form");
+			dojo.require("dijit.layout.StackContainer");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dijit.form.TextBox");
+	        dojo.require("dojo.parser");
+			
+			dojo.addOnLoad(function(){
+				doh.register("tests",
+					[
+						function test_getValues(t){
+							t.is({
+								dropDown: "first",
+								dropDownFirstBox: "First Value",
+								radio: "second",
+								radioSecondBox2: "Radio Another Value",
+								dual: "second",
+								dualSecondBox: "Dual First Value on Second (RO)",
+								dualSecondBox2: "Dual Another Value"
+								}, form.attr("value"));
+						},
+						function test_setValues(t){
+							form.attr("value", {
+								dropDown: "first",
+								dropDownSecondBox: "Changed First Value",
+								radio: "first",
+								radioFirstBox: "Changed Radio Value",
+								radioSecondBox: "Changed disabled value",
+								dual: "first",
+								dualFirstBox: "Changed Dual (DIS)",
+								dualSecondBox: "Changed read only value",
+								dualSecondBox: "Changed me too"
+							});
+							t.is({
+								dropDown: "first",
+								dropDownFirstBox: "First Value",
+								radio: "first",
+								radioFirstBox: "Changed Radio Value",
+								dual: "first"
+							}, form.attr("value"));
+							form.attr("value", {
+								dropDown: "second",
+								radio: "second",
+								dual: "second"});
+							t.is({
+								dropDown: "second",
+								dropDownSecondBox: "Changed First Value",
+								dropDownSecondBox2: "Another Value",
+								radio: "second",
+								radioSecondBox2: "Radio Another Value",
+								dual: "second",
+								dualSecondBox: "Changed me too",
+								dualSecondBox2: "Dual Another Value"
+								}, form.attr("value"));
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<style>
+			@import url(../../../dojo/resources/dojo.css);
+			@import url(../../../dijit/themes/tundra/tundra.css);
+			@import url(../resources/DropDownSelect.css);
+			@import url(../resources/CheckedMultiSelect.css);
+			@import url(../../../dijit/tests/css/dijitTests.css);
+		</style>
+	</head>	
+	<body class="tundra">
+		<h1 class="testTitle">Test: dojox.form.SelectStack</h1>
+		<form dojoType="dijit.form.Form" jsId="form">
+			<h4 class="testSubtitle">DropDown-based Select</h4>
+			<select dojoType="dojox.form.DropDownStack" name="dropDown" 
+				stackId="dropDownStack"></select>
+			<div dojoType="dijit.layout.StackContainer" class="dijitInline" doLayout="false" id="dropDownStack">
+				<div title="First" id="first" dojoType="dijit.layout.ContentPane">
+					Options for "First": <input dojoType="dijit.form.TextBox" name="dropDownFirstBox" value="First Value" />
+				</div>
+				<div title="Second" id="second" dojoType="dijit.layout.ContentPane">
+					Options for "Second": <input dojoType="dijit.form.TextBox" name="dropDownSecondBox" value="First Value on Second" /><br>
+					More Options for "Second": <input dojoType="dijit.form.TextBox" name="dropDownSecondBox2" value="Another Value" />
+				</div>
+			</div>
+		<hr>
+			<h4 class="testSubtitle">Radio-based Select</h4>
+			<select dojoType="dojox.form.RadioStack" name="radio" 
+				stackId="radioStack" stackPrefix="radio_" value="second"></select>
+			<div dojoType="dijit.layout.StackContainer" class="dijitInline" doLayout="false" id="radioStack">
+				<div title="First" id="radio_first" dojoType="dijit.layout.ContentPane">
+					Options for "First": <input dojoType="dijit.form.TextBox" name="radioFirstBox" value="Radio First Value" />
+				</div>
+				<div title="Second" id="radio_second" dojoType="dijit.layout.ContentPane">
+					Options for "Second": <input dojoType="dijit.form.TextBox" disabled="disabled" name="radioSecondBox" value="Radio First Value on Second (DIS)" /><br>
+					More Options for "Second": <input dojoType="dijit.form.TextBox" name="radioSecondBox2" value="Radio Another Value" />
+				</div>
+			</div>
+		<hr>
+			<h4 class="testSubtitle">*Two* controllers</h4>
+			<select dojoType="dojox.form.DropDownStack" stackId="dualStack" stackPrefix="dual_"></select><br>
+			<div dojoType="dijit.layout.StackContainer" doLayout="false" id="dualStack">
+				<div title="First" id="dual_first" dojoType="dijit.layout.ContentPane">
+					Options for "First": <input dojoType="dijit.form.TextBox" disabled="disabled" name="dualFirstBox" value="Dual First Value (DIS)" />
+				</div>
+				<div title="Second" selected="true" id="dual_second" dojoType="dijit.layout.ContentPane">
+					Options for "Second": <input dojoType="dijit.form.TextBox" readOnly="readOnly" name="dualSecondBox" value="Dual First Value on Second (RO)" /><br>
+					More Options for "Second": <input dojoType="dijit.form.TextBox" name="dualSecondBox2" value="Dual Another Value" />
+				</div>
+			</div>
+			<select dojoType="dojox.form.DropDownStack" name="dual" stackId="dualStack" stackPrefix="dual_"></select><br>
+		<hr>
+			<button dojoType="dijit.form.Button">
+				<script type="dojo/method" event="onClick">
+					console.dir(form.attr("value"));
+				</script>
+				Get Values
+			</button>
+		</form>
+	</body>
+</html>
diff --git a/dojox/form/tests/test_TimeSpinner.html b/dojox/form/tests/test_TimeSpinner.html
new file mode 100644
index 0000000..cb3f84b
--- /dev/null
+++ b/dojox/form/tests/test_TimeSpinner.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Dojo Spinner Widget Test</title>
+
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+			@import "../../../dijit/themes/claro/claro.css";
+		</style>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojox.form.TimeSpinner");
+
+			function displayData() {
+				var spinner = dijit.byId("timeSpinner");
+
+				//accessing the widget property directly
+				console.log("TimeSpinner Value (raw, unserialized): ", spinner.get('value'));
+
+				//accessing the widget from the form elements
+				var theForm = dojo.byId("form1");
+				var s = "";
+				for (var i=0; i<theForm.elements.length;i++){
+					var elem = theForm.elements[i];
+					if (!elem.name || elem.name =="button") { continue ; }
+					s+=elem.name + ": " + elem.value + "\n";
+				}
+				console.log(s);
+				
+                	}
+
+		</script>
+	</head>
+
+	<body class="claro">
+	<h1 class="testTitle">Dojox TimeSpinner Test</h1>
+		Try typing values, and use the up/down arrow keys and/or the arrow push
+		buttons to spin
+		<br>
+	<form id="form1" action="" name="example" method="post">
+		<h1>time spinner</h1>
+		<br>
+		<input id="timeSpinner" dojoType="dojox.form.TimeSpinner"
+			onChange="console.debug('onChange fired for widget id = ' + this.id + ' with value = ' + arguments[0]);"
+			value="12:30 PM"
+			name="timeSpinner"
+			hours="12"
+			id="timeSpinner" />
+	</form>
+
+	<div>
+		<button name="button" onclick="displayData(); return false;">view data</button>
+	</div>
+
+	</body>
+</html>
diff --git a/dojox/form/tests/uploads/README b/dojox/form/tests/uploads/README
new file mode 100644
index 0000000..3d752af
--- /dev/null
+++ b/dojox/form/tests/uploads/README
@@ -0,0 +1,11 @@
+-------------------------------------------------------------------------------
+This folder is used for dojox.form.FileUploader tests
+	I had resisted adding an empty folder to the SVN, but I'm sure
+	I was not the only one frustrated by the FileUploader dumping
+	images into the resources folder and making a mess. Now at least
+	they will be in one place. I did want to put this in "tests". but
+	that folder is not included in downloads and could break some things.
+	
+	Mike Wilcox
+-------------------------------------------------------------------------------
+
diff --git a/dojox/fx.js b/dojox/fx.js
index d8003ad..662581b 100644
--- a/dojox/fx.js
+++ b/dojox/fx.js
@@ -1,12 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.fx"]){
-dojo._hasResource["dojox.fx"]=true;
 dojo.provide("dojox.fx");
-dojo.require("dojox.fx._base");
-}
+
+dojo.require("dojox.fx._base"); 
diff --git a/dojox/fx/Shadow.js b/dojox/fx/Shadow.js
index 510757a..5d75eda 100644
--- a/dojox/fx/Shadow.js
+++ b/dojox/fx/Shadow.js
@@ -1,119 +1,146 @@
-/*
-	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
-*/
+dojo.provide("dojox.fx.Shadow");
+dojo.experimental("dojox.fx.Shadow"); 
 
+dojo.require("dijit._Widget"); 
+dojo.require("dojo.NodeList-fx"); 
 
-if(!dojo._hasResource["dojox.fx.Shadow"]){
-dojo._hasResource["dojox.fx.Shadow"]=true;
-dojo.provide("dojox.fx.Shadow");
-dojo.experimental("dojox.fx.Shadow");
-dojo.require("dijit._Widget");
-dojo.require("dojo.NodeList-fx");
-dojo.declare("dojox.fx.Shadow",dijit._Widget,{shadowPng:dojo.moduleUrl("dojox.fx","resources/shadow"),shadowThickness:7,shadowOffset:3,opacity:0.75,animate:false,node:null,startup:function(){
-this.inherited(arguments);
-this.node.style.position="relative";
-this.pieces={};
-var x1=-1*this.shadowThickness;
-var y0=this.shadowOffset;
-var y1=this.shadowOffset+this.shadowThickness;
-this._makePiece("tl","top",y0,"left",x1);
-this._makePiece("l","top",y1,"left",x1,"scale");
-this._makePiece("tr","top",y0,"left",0);
-this._makePiece("r","top",y1,"left",0,"scale");
-this._makePiece("bl","top",0,"left",x1);
-this._makePiece("b","top",0,"left",0,"crop");
-this._makePiece("br","top",0,"left",0);
-this.nodeList=dojo.query(".shadowPiece",this.node);
-this.setOpacity(this.opacity);
-this.resize();
-},_makePiece:function(_1,_2,_3,_4,_5,_6){
-var _7;
-var _8=this.shadowPng+_1.toUpperCase()+".png";
-if(dojo.isIE<7){
-_7=dojo.create("div");
-_7.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+_8+"'"+(_6?", sizingMethod='"+_6+"'":"")+")";
-}else{
-_7=dojo.create("img",{src:_8});
-}
-_7.style.position="absolute";
-_7.style[_2]=_3+"px";
-_7.style[_4]=_5+"px";
-_7.style.width=this.shadowThickness+"px";
-_7.style.height=this.shadowThickness+"px";
-dojo.addClass(_7,"shadowPiece");
-this.pieces[_1]=_7;
-this.node.appendChild(_7);
-},setOpacity:function(n,_9){
-if(dojo.isIE){
-return;
-}
-if(!_9){
-_9={};
-}
-if(this.animate){
-var _a=[];
-this.nodeList.forEach(function(_b){
-_a.push(dojo._fade(dojo.mixin(_9,{node:_b,end:n})));
+dojo.declare("dojox.fx.Shadow",
+	dijit._Widget,{
+	// summary: Adds a drop-shadow to a node.
+	// 
+	// example:
+	// |	// add drop shadows to all nodes with class="hasShadow"
+	// |	dojo.query(".hasShadow").forEach(function(n){
+	// |		var foo = new dojox.fx.Shadow({ node: n });
+	// |		foo.startup();
+	// |	});
+	//
+	// shadowPng: String
+	// 	Base location for drop-shadow images
+	shadowPng: dojo.moduleUrl("dojox.fx", "resources/shadow"),
+
+	// shadowThickness: Integer
+	// 	How wide (in px) to make the shadow
+	shadowThickness: 7,
+
+	// shadowOffset: Integer
+	//	How deep to make the shadow appear to be
+	shadowOffset: 3,
+
+	// opacity: Float
+	//	Overall opacity of the shadow
+	opacity: 0.75,
+
+	// animate: Boolean	
+	// 	A toggle to disable animated transitions
+	animate: false,
+
+	// node: DomNode
+	// 	The node we will be applying this shadow to
+	node: null,
+
+	startup: function(){
+		// summary: Initializes the shadow.
+
+		this.inherited(arguments);
+		this.node.style.position = "relative";
+		// make all the pieces of the shadow, and position/size them as much
+		// as possible (but a lot of the coordinates are set in sizeShadow
+		this.pieces={};
+		var x1 = -1 * this.shadowThickness;
+		var y0 = this.shadowOffset;
+		var y1 = this.shadowOffset + this.shadowThickness;
+		this._makePiece("tl", "top", y0, "left", x1);
+		this._makePiece("l", "top", y1, "left", x1, "scale");
+		this._makePiece("tr", "top", y0, "left", 0);
+		this._makePiece("r", "top", y1, "left", 0, "scale");
+		this._makePiece("bl", "top", 0, "left", x1);
+		this._makePiece("b", "top", 0, "left", 0, "crop");
+		this._makePiece("br", "top", 0, "left", 0);
+
+		this.nodeList = dojo.query(".shadowPiece",this.node);
+
+		this.setOpacity(this.opacity);
+		this.resize();
+	},
+
+	_makePiece: function(name, vertAttach, vertCoord, horzAttach, horzCoord, sizing){
+		// summary: append a shadow pieces to the node, and position it
+		var img;
+		var url = this.shadowPng + name.toUpperCase() + ".png";
+		if(dojo.isIE < 7){
+			img = dojo.create("div");
+			img.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+url+"'"+
+				(sizing?", sizingMethod='"+sizing+"'":"") + ")";
+		}else{
+			img = dojo.create("img", { src:url });
+		}
+
+		img.style.position="absolute"; 
+		img.style[vertAttach]=vertCoord+"px";
+		img.style[horzAttach]=horzCoord+"px";
+		img.style.width=this.shadowThickness+"px";
+		img.style.height=this.shadowThickness+"px";
+		dojo.addClass(img,"shadowPiece"); 
+		this.pieces[name]=img;
+		this.node.appendChild(img);
+
+	},
+
+	setOpacity: function(/* Float */n,/* Object? */animArgs){
+		// summary: set the opacity of the underlay
+		// note: does not work in IE? FIXME.
+		if(dojo.isIE){ return; } 
+		if(!animArgs){ animArgs = {}; } 
+		if(this.animate){
+			var _anims = [];
+			this.nodeList.forEach(function(node){
+				_anims.push(dojo._fade(dojo.mixin(animArgs,{ node: node, end: n })));
+			});
+			dojo.fx.combine(_anims).play();
+		}else{
+			this.nodeList.style("opacity",n);
+		}	
+
+	},
+
+	setDisabled: function(/* Boolean */disabled){
+		// summary: enable / disable the shadow
+		if(disabled){
+			if(this.disabled){ return; }
+			if(this.animate){ this.nodeList.fadeOut().play(); 
+			}else{ this.nodeList.style("visibility","hidden"); }
+			this.disabled = true;
+		}else{
+			if(!this.disabled){ return; }
+			if(this.animate){ this.nodeList.fadeIn().play(); 
+			}else{ this.nodeList.style("visibility","visible"); }
+			this.disabled = false;
+		}
+	},
+
+	resize: function(/* dojox.fx._arg.ShadowResizeArgs */args){
+		// summary: Resizes the shadow based on width and height.
+		var x; var y;
+		if(args){ x = args.x; y = args.y;
+		}else{
+			var co = dojo._getBorderBox(this.node); 
+			x = co.w; y = co.h; 
+		}
+		var sideHeight = y - (this.shadowOffset+this.shadowThickness);
+		if (sideHeight < 0) { sideHeight = 0; }
+		if (y < 1) { y = 1; }
+		if (x < 1) { x = 1; }
+		with(this.pieces){
+			l.style.height = sideHeight+"px";
+			r.style.height = sideHeight+"px";
+			b.style.width = x+"px";
+			bl.style.top = y+"px";
+			b.style.top = y+"px";
+			br.style.top = y+"px";
+			tr.style.left = x+"px";
+			r.style.left = x+"px";
+			br.style.left = x+"px";
+		}
+	}
 });
-dojo.fx.combine(_a).play();
-}else{
-this.nodeList.style("opacity",n);
-}
-},setDisabled:function(_c){
-if(_c){
-if(this.disabled){
-return;
-}
-if(this.animate){
-this.nodeList.fadeOut().play();
-}else{
-this.nodeList.style("visibility","hidden");
-}
-this.disabled=true;
-}else{
-if(!this.disabled){
-return;
-}
-if(this.animate){
-this.nodeList.fadeIn().play();
-}else{
-this.nodeList.style("visibility","visible");
-}
-this.disabled=false;
-}
-},resize:function(_d){
-var x;
-var y;
-if(_d){
-x=_d.x;
-y=_d.y;
-}else{
-var co=dojo._getBorderBox(this.node);
-x=co.w;
-y=co.h;
-}
-var _e=y-(this.shadowOffset+this.shadowThickness);
-if(_e<0){
-_e=0;
-}
-if(y<1){
-y=1;
-}
-if(x<1){
-x=1;
-}
-with(this.pieces){
-l.style.height=_e+"px";
-r.style.height=_e+"px";
-b.style.width=x+"px";
-bl.style.top=y+"px";
-b.style.top=y+"px";
-br.style.top=y+"px";
-tr.style.left=x+"px";
-r.style.left=x+"px";
-br.style.left=x+"px";
-}
-}});
-}
diff --git a/dojox/fx/Timeline.js b/dojox/fx/Timeline.js
new file mode 100644
index 0000000..62ad309
--- /dev/null
+++ b/dojox/fx/Timeline.js
@@ -0,0 +1,210 @@
+dojo.provide("dojox.fx.Timeline");
+dojo.require("dojo.fx.easing");
+
+dojox.fx.animateTimeline = function(/* Object */options, /* DomNode|String */node){
+	// options: Object
+	// 		The paramters passed to the timeline animation. Includes:
+	// 			keys: Array
+	// 				An array of objects, with style properties and values.
+	// 			duration:
+	// 				Duration of the animation in milliseconds.
+	// 				Defaults to 1000.
+	// node: DomNode
+	// 		The DomNode or id to be animated.
+	// 			
+	// summary:
+	//		An add-on to dojo.fx that provides the ability to create
+	//		a complex property animation based on an array of "keyframes".
+	// description:
+	//		The Timeline is a replacement for the default dojo._Line.
+	//		Instead of _Line.getValue returning a float between 0-1,
+	//		_Timeline.getValue returns an object with all properties and
+	//		their current values.
+	//		A property does not have to appear in every keyframe.
+	//		As in the example below, "height" is transitioned from the first
+	//		keyframe to the third. "width" is transitioned from the first
+	//		to the second to the third.
+	//		Each keyframe can accept the following custom properties:
+	//	step: String
+	//		The start, finish or percentage that this keyframe represents.
+	//		Allowed parameters are:
+	//			0%-100%
+	//			from (same as 0%, used to conform with the Webkit animation spec)
+	//			to (same as 100%, used to conform with the Webkit animation spec)
+	//	ease: String
+	//		The string name of a dojo.fx.easing ease. Defaults to "linear". Use
+	//		the suffix name of the ease, like: "quadIn", not: "dojo.fx.quadIn".
+	//		
+	// example:
+	// 		|	var keys = [
+	// 		|	{
+	// 		|		step:"0px",
+	// 		|		ease:"quadInOut",
+	// 		|		width:"50px",
+	// 		|		height:"50px",
+	// 		|	},{
+	// 		|		step:"25%",
+	// 		|		width:"190px"
+	// 		|	},{
+	// 		|		step:"100%",
+	// 		|		width:"10px",
+	// 		|		height:"200px",
+	// 		|	}
+	// 		|	];
+	// 		|	ani = dojox.fx.animateTimeline({keys:keys, duration:2000}, "myDiv").play();
+	//
+	var _curve = new dojox.fx._Timeline(options.keys);
+	var ani = dojo.animateProperty({
+		node:dojo.byId(node || options.node),
+		duration:options.duration || 1000,
+		properties:_curve._properties,
+		// don't change! This easing is for the timeline,
+		// not individual properties
+		easing:dojo.fx.easing.linear, 
+		onAnimate: function(v){
+			//console.log("   ani:", v);
+		}
+	});
+	dojo.connect(ani, "onEnd", function(node){
+		// Setting the final style. Hiccups in the browser
+		// can cause the animation to lose track. This ensures
+		// that it finishes in the proper location.
+		var sty = ani.curve.getValue(ani.reversed ? 0 : 1);
+		dojo.style(node, sty);
+	});
+	dojo.connect(ani, "beforeBegin", function(){
+		// remove default curve and replace it with Timeline
+		if(ani.curve){ delete ani.curve; }
+		ani.curve = _curve;
+		_curve.ani = ani;
+	})
+	return ani; // dojo.Animation
+}
+
+dojox.fx._Timeline = function(/* Array */keys){
+	// summary:
+	//		The dojox.fx._Timeline object from which an instance
+	//		is created
+	// tags:
+	//		private
+	this.keys = dojo.isArray(keys) ? this.flatten(keys) : keys;
+}
+
+dojox.fx._Timeline.prototype.flatten = function(keys){
+	// summary:
+	//		An internally used function that converts the keyframes
+	//		as used in the example above into a series of key values
+	//		which is what is used in the animation parsing.
+	var getPercent = function(str, idx){
+		if(str == "from"){ return 0; }
+		if(str == "to"){ return 1; }
+		if(str === undefined){
+			return idx==0 ? 0 : idx / (keys.length - 1)
+		}
+		return parseInt(str, 10) * .01
+	}
+	var p = {}, o = {};
+	dojo.forEach(keys, function(k, i){
+		var step = getPercent(k.step, i);
+		var ease = dojo.fx.easing[k.ease] || dojo.fx.easing.linear;
+		
+		for(var nm in k){
+			if(nm == "step" || nm == "ease" || nm == "from" || nm == "to"){ continue; }
+			if(!o[nm]){
+				o[nm] = {
+					steps:[],
+					values:[],
+					eases:[],
+					ease:ease
+				};
+				p[nm] = {};
+				if(!/#/.test(k[nm])){
+					p[nm].units = o[nm].units = /\D{1,}/.exec(k[nm]).join("");	
+				}else{
+					p[nm].units = o[nm].units = "isColor";
+				}
+			}
+			
+			o[nm].eases.push(dojo.fx.easing[k.ease || "linear"]);
+			
+			o[nm].steps.push(step);
+			if(p[nm].units == "isColor"){
+				o[nm].values.push(new dojo.Color(k[nm]));
+			}else{
+				o[nm].values.push(parseInt(/\d{1,}/.exec(k[nm]).join("")));
+			}
+			
+			if(p[nm].start === undefined){
+				p[nm].start = o[nm].values[o[nm].values.length-1];
+			}else{
+				p[nm].end = o[nm].values[o[nm].values.length-1]
+			}
+		}
+	});
+	
+	
+	this._properties = p;
+	return o; // Object
+	
+}
+
+dojox.fx._Timeline.prototype.getValue = function(/*float*/ p){
+	// summary:
+	//		Replaces the native getValue in dojo.fx.Animation.
+	//		Returns an object with all propeties used in the animation
+	//		and the property's current value
+	p = this.ani._reversed ? 1-p : p;
+	var o = {}, self = this;
+	
+	var getProp = function(nm, i){
+		return self._properties[nm].units!="isColor" ?
+			self.keys[nm].values[i] + self._properties[nm].units :
+			self.keys[nm].values[i].toCss();
+	}
+	
+	for(var nm in this.keys){
+		var k = this.keys[nm];
+		for(var i=0; i<k.steps.length; i++){
+			
+			var step = k.steps[i];
+			var ns = k.steps[i+1];
+			var next = i < k.steps.length ? true : false;
+			var ease = k.eases[i] || function(n){return n;};
+			
+			if(p == step){
+				// first or last
+				o[nm] = getProp(nm, i);
+				if(!next || (next &&  this.ani._reversed)) break;
+			
+			}else if(p > step){
+				
+				if(next && p < k.steps[i+1]){ 
+					// inbetween steps
+					var end = k.values[i+1];
+					var beg = k.values[i];
+					
+					var seg = (1 / (ns - step)) * (p - step);
+					seg = ease(seg);
+					
+					if(beg instanceof dojo.Color){
+						o[nm] = dojo.blendColors(beg, end, seg).toCss(false);	
+					}else{
+						var df = end - beg;
+						o[nm] = beg + seg * df + this._properties[nm].units;
+					}
+					break;
+				
+				}else{
+					// completed keys before 100%
+					o[nm] = getProp(nm, i);
+				}
+				
+			}else if((next && !this.ani._reversed) || (!next && this.ani._reversed)){
+				o[nm] = getProp(nm, i);
+			}
+		}
+	}
+	return o; // Object
+};
+
+
diff --git a/dojox/fx/_arg.js b/dojox/fx/_arg.js
index 7dff984..bcfc401 100644
--- a/dojox/fx/_arg.js
+++ b/dojox/fx/_arg.js
@@ -1,19 +1,23 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.fx._arg"]){
-dojo._hasResource["dojox.fx._arg"]=true;
 dojo.provide("dojox.fx._arg");
-dojox.fx._arg.StyleArgs=function(_1){
-this.node=_1.node;
-this.cssClass=_1.cssClass;
-};
-dojox.fx._arg.ShadowResizeArgs=function(_2){
-this.x=_2.x;
-this.y=_2.y;
-};
+
+dojox.fx._arg.StyleArgs = function(/*Object*/ args){
+	// summary:
+	//		The node and CSS class to use for style manipulations.
+	// node: DOMNode
+	//		The node to manipulate
+	// cssClass: String
+	//		The class to use during the manipulation
+	this.node = args.node;
+	this.cssClass = args.cssClass;
 }
+
+dojox.fx._arg.ShadowResizeArgs = function(/*Object*/ args){
+	// summary: 
+	//	The odd way to document object parameters.
+	// x: Integer
+	//	the width to set
+	// y: Integer
+	//	the height to set	
+	this.x = args.x;
+	this.y = args.y;
+}
\ No newline at end of file
diff --git a/dojox/fx/_base.js b/dojox/fx/_base.js
index 8296f35..9f72bbf 100644
--- a/dojox/fx/_base.js
+++ b/dojox/fx/_base.js
@@ -1,118 +1,313 @@
-/*
-	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
-*/
+dojo.provide("dojox.fx._base");
+// summary: Experimental and extended Animations beyond Dojo Core / Base functionality. 
+//	Provides advanced Lines, Animations, and convenience aliases.
+dojo.require("dojo.fx"); 
 
+dojo.mixin(dojox.fx, {
+
+	// anim: Function
+	//	Alias of `dojo.anim` - the shorthand `dojo.animateProperty` with auto-play
+	anim: dojo.anim,
+
+	// animateProperty: Function
+	//	Alias of `dojo.animateProperty` - animate any CSS property
+	animateProperty: dojo.animateProperty,
+
+	// fadeTo: Function 
+	//		Fade an element from an opacity to an opacity.
+	//		Omit `start:` property to detect. `end:` property is required.
+	//		Ultimately an alias to `dojo._fade`
+	fadeTo: dojo._fade,
+
+	// fadeIn: Function
+	//	Alias of `dojo.fadeIn` - Fade a node in.
+	fadeIn: dojo.fadeIn,
+	
+	// fadeOut: Function
+	//	Alias of `dojo.fadeOut` - Fades a node out.
+	fadeOut: dojo.fadeOut,
+
+	// combine: Function
+	//	Alias of `dojo.fx.combine` - Run an array of animations in parallel
+	combine: dojo.fx.combine,
+
+	// chain: Function
+	//	Alias of `dojo.fx.chain` - Run an array of animations in sequence
+	chain: dojo.fx.chain,
+
+	// slideTo: Function
+	//	Alias of `dojo.fx.slideTo` - Slide a node to a defined top/left coordinate
+	slideTo: dojo.fx.slideTo,
+
+	// wipeIn: Function
+	//	Alias of `dojo.fx.wipeIn` - Wipe a node to visible
+	wipeIn: dojo.fx.wipeIn,
+
+	// wipeOut: Function
+	//	Alias of `dojo.fx.wipeOut` - Wipe a node to non-visible
+	wipeOut: dojo.fx.wipeOut
+
+});
+
+dojox.fx.sizeTo = function(/* Object */args){
+	// summary: 
+	//		Creates an animation that will size a node
+	//
+	// description:
+	//		Returns an animation that will size the target node
+	//		defined in args Object about it's center to
+	//		a width and height defined by (args.width, args.height), 
+	//		supporting an optional method: chain||combine mixin
+	//		(defaults to chain).	
+	//
+	//	- works best on absolutely or relatively positioned elements
+	//	
+	// example:
+	//	|	// size #myNode to 400px x 200px over 1 second
+	//	|	dojo.fx.sizeTo({
+	//	|		node:'myNode',
+	//	|		duration: 1000,
+	//	|		width: 400,
+	//	|		height: 200,
+	//	|		method: "combine"
+	//	|	}).play();
+	//
+
+	var node = args.node = dojo.byId(args.node),
+		abs = "absolute";
+
+	var method = args.method || "chain"; 
+	if(!args.duration){ args.duration = 500; } // default duration needed
+	if(method == "chain"){ args.duration = Math.floor(args.duration / 2); } 
+	
+	var top, newTop, left, newLeft, width, height = null;
+
+	var init = (function(n){
+		return function(){
+			var cs = dojo.getComputedStyle(n),
+				pos = cs.position,
+				w = cs.width,
+				h = cs.height
+			;
+			
+			top = (pos == abs ? n.offsetTop : parseInt(cs.top) || 0);
+			left = (pos == abs ? n.offsetLeft : parseInt(cs.left) || 0);
+			width = (w == "auto" ? 0 : parseInt(w));
+			height = (h == "auto" ? 0 : parseInt(h));
+			
+			newLeft = left - Math.floor((args.width - width) / 2); 
+			newTop = top - Math.floor((args.height - height) / 2); 
+
+			if(pos != abs && pos != 'relative'){
+				var ret = dojo.coords(n, true);
+				top = ret.y;
+				left = ret.x;
+				n.style.position = abs;
+				n.style.top = top + "px";
+				n.style.left = left + "px";
+			}
+		}
+	})(node);
+
+	var anim1 = dojo.animateProperty(dojo.mixin({
+		properties: {
+			height: function(){
+				init();
+				return { end: args.height || 0, start: height };
+			},
+			top: function(){
+				return { start: top, end: newTop };
+			}
+		}
+	}, args));
+	var anim2 = dojo.animateProperty(dojo.mixin({
+		properties: {
+			width: function(){
+				return { start: width, end: args.width || 0 }
+			},
+			left: function(){
+				return { start: left, end: newLeft }
+			}
+		}
+	}, args));
+
+	var anim = dojo.fx[(args.method == "combine" ? "combine" : "chain")]([anim1, anim2]);
+	return anim; // dojo.Animation
 
-if(!dojo._hasResource["dojox.fx._base"]){
-dojo._hasResource["dojox.fx._base"]=true;
-dojo.provide("dojox.fx._base");
-dojo.require("dojo.fx");
-dojo.mixin(dojox.fx,{anim:dojo.anim,animateProperty:dojo.animateProperty,fadeTo:dojo._fade,fadeIn:dojo.fadeIn,fadeOut:dojo.fadeOut,combine:dojo.fx.combine,chain:dojo.fx.chain,slideTo:dojo.fx.slideTo,wipeIn:dojo.fx.wipeIn,wipeOut:dojo.fx.wipeOut});
-dojox.fx.sizeTo=function(_1){
-var _2=_1.node=dojo.byId(_1.node),_3="absolute";
-var _4=_1.method||"chain";
-if(!_1.duration){
-_1.duration=500;
-}
-if(_4=="chain"){
-_1.duration=Math.floor(_1.duration/2);
-}
-var _5,_6,_7,_8,_9,_a=null;
-var _b=(function(n){
-return function(){
-var cs=dojo.getComputedStyle(n),_c=cs.position,w=cs.width,h=cs.height;
-_5=(_c==_3?n.offsetTop:parseInt(cs.top)||0);
-_7=(_c==_3?n.offsetLeft:parseInt(cs.left)||0);
-_9=(w=="auto"?0:parseInt(w));
-_a=(h=="auto"?0:parseInt(h));
-_8=_7-Math.floor((_1.width-_9)/2);
-_6=_5-Math.floor((_1.height-_a)/2);
-if(_c!=_3&&_c!="relative"){
-var _d=dojo.coords(n,true);
-_5=_d.y;
-_7=_d.x;
-n.style.position=_3;
-n.style.top=_5+"px";
-n.style.left=_7+"px";
-}
-};
-})(_2);
-var _e=dojo.animateProperty(dojo.mixin({properties:{height:function(){
-_b();
-return {end:_1.height||0,start:_a};
-},top:function(){
-return {start:_5,end:_6};
-}}},_1));
-var _f=dojo.animateProperty(dojo.mixin({properties:{width:function(){
-return {start:_9,end:_1.width||0};
-},left:function(){
-return {start:_7,end:_8};
-}}},_1));
-var _10=dojo.fx[(_1.method=="combine"?"combine":"chain")]([_e,_f]);
-return _10;
-};
-dojox.fx.slideBy=function(_11){
-var _12=_11.node=dojo.byId(_11.node),top,_13;
-var _14=(function(n){
-return function(){
-var cs=dojo.getComputedStyle(n);
-var pos=cs.position;
-top=(pos=="absolute"?n.offsetTop:parseInt(cs.top)||0);
-_13=(pos=="absolute"?n.offsetLeft:parseInt(cs.left)||0);
-if(pos!="absolute"&&pos!="relative"){
-var ret=dojo.coords(n,true);
-top=ret.y;
-_13=ret.x;
-n.style.position="absolute";
-n.style.top=top+"px";
-n.style.left=_13+"px";
-}
 };
-})(_12);
-_14();
-var _15=dojo.animateProperty(dojo.mixin({properties:{top:top+(_11.top||0),left:_13+(_11.left||0)}},_11));
-dojo.connect(_15,"beforeBegin",_15,_14);
-return _15;
+
+dojox.fx.slideBy = function(/* Object */args){
+	// summary: 
+	//		Returns an animation to slide a node by a defined offset.
+	//
+	// description:
+	//		Returns an animation that will slide a node (args.node) from it's
+	//		current position to it's current posision plus the numbers defined
+	//		in args.top and args.left. standard dojo.fx mixin's apply. 
+	//	
+	// example:
+	//	|	// slide domNode 50px down, and 22px left
+	//	|	dojox.fx.slideBy({ 
+	//	|		node: domNode, duration:400, 
+	//	|		top: 50, left: -22 
+	//	|	}).play();
+
+	var node = args.node = dojo.byId(args.node),
+		top, left;
+
+	var init = (function(n){
+		return function(){
+			var cs = dojo.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 = dojo.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 = dojo.animateProperty(dojo.mixin({
+		properties: {
+			// FIXME: is there a way to update the _Line after creation?
+			// null start values allow chaining to work, animateProperty will
+			// determine them for us (except in ie6? -- ugh)
+			top: top + (args.top || 0),
+			left: left + (args.left || 0) 
+		}
+	}, args));
+	dojo.connect(_anim, "beforeBegin", _anim, init);
+	return _anim; // dojo.Animation
 };
-dojox.fx.crossFade=function(_16){
-var _17=_16.nodes[0]=dojo.byId(_16.nodes[0]),op1=dojo.style(_17,"opacity"),_18=_16.nodes[1]=dojo.byId(_16.nodes[1]),op2=dojo.style(_18,"opacity");
-var _19=dojo.fx.combine([dojo[(op1==0?"fadeIn":"fadeOut")](dojo.mixin({node:_17},_16)),dojo[(op1==0?"fadeOut":"fadeIn")](dojo.mixin({node:_18},_16))]);
-return _19;
+
+dojox.fx.crossFade = function(/* Object */args){
+	// summary: 
+	//		Returns an animation cross fading two element simultaneously
+	// 
+	// args:
+	//	args.nodes: Array - two element array of domNodes, or id's
+	//
+	//	all other standard animation args mixins apply. args.node ignored.
+	//
+
+	// simple check for which node is visible, maybe too simple?
+	var node1 = args.nodes[0] = dojo.byId(args.nodes[0]),
+		op1 = dojo.style(node1,"opacity"),
+		node2 = args.nodes[1] = dojo.byId(args.nodes[1]),
+		op2 = dojo.style(node2, "opacity")
+	;
+	
+	var _anim = dojo.fx.combine([
+		dojo[(op1 == 0 ? "fadeIn" : "fadeOut")](dojo.mixin({
+			node: node1
+		},args)),
+		dojo[(op1 == 0 ? "fadeOut" : "fadeIn")](dojo.mixin({
+			node: node2
+		},args))
+	]);
+	return _anim; // dojo.Animation
 };
-dojox.fx.highlight=function(_1a){
-var _1b=_1a.node=dojo.byId(_1a.node);
-_1a.duration=_1a.duration||400;
-var _1c=_1a.color||"#ffff99",_1d=dojo.style(_1b,"backgroundColor");
-if(_1d=="rgba(0, 0, 0, 0)"){
-_1d="transparent";
-}
-var _1e=dojo.animateProperty(dojo.mixin({properties:{backgroundColor:{start:_1c,end:_1d}}},_1a));
-if(_1d=="transparent"){
-dojo.connect(_1e,"onEnd",_1e,function(){
-_1b.style.backgroundColor=_1d;
-});
-}
-return _1e;
+
+dojox.fx.highlight = function(/*Object*/ args){
+	// summary: 
+	//		Highlight a node
+	//
+	// description:
+	//		Returns an animation that sets the node background to args.color
+	//		then gradually fades back the original node background color
+	//	
+	// example:
+	//	|	dojox.fx.highlight({ node:"foo" }).play(); 
+
+	var node = args.node = dojo.byId(args.node);
+
+	args.duration = args.duration || 400;
+	
+	// Assign default color light yellow
+	var startColor = args.color || '#ffff99',
+		endColor = dojo.style(node, "backgroundColor")
+	;
+
+	// safari "fix"
+	// safari reports rgba(0, 0, 0, 0) (black) as transparent color, while
+	// other browsers return "transparent", rendered as white by default by
+	// dojo.Color; now dojo.Color maps "transparent" to
+	// djConfig.transparentColor ([r, g, b]), if present; so we can use
+	// the color behind the effect node
+	if(endColor == "rgba(0, 0, 0, 0)"){
+		endColor = "transparent";
+	}
+
+	var anim = dojo.animateProperty(dojo.mixin({
+		properties: {
+			backgroundColor: { start: startColor, end: endColor }
+		}
+	}, args));
+
+	if(endColor == "transparent"){
+		dojo.connect(anim, "onEnd", anim, function(){
+			node.style.backgroundColor = endColor;
+		});
+	}
+
+	return anim; // dojo.Animation
 };
-dojox.fx.wipeTo=function(_1f){
-_1f.node=dojo.byId(_1f.node);
-var _20=_1f.node,s=_20.style;
-var dir=(_1f.width?"width":"height"),_21=_1f[dir],_22={};
-_22[dir]={start:function(){
-s.overflow="hidden";
-if(s.visibility=="hidden"||s.display=="none"){
-s[dir]="1px";
-s.display="";
-s.visibility="";
-return 1;
-}else{
-var now=dojo.style(_20,dir);
-return Math.max(now,1);
-}
-},end:_21};
-var _23=dojo.animateProperty(dojo.mixin({properties:_22},_1f));
-return _23;
+
+ 
+dojox.fx.wipeTo = function(/*Object*/ args){
+	// summary:
+	//		Animate a node wiping to a specific width or height
+	//	
+	// description:
+	//		Returns an animation that will expand the
+	//		node defined in 'args' object from it's current to
+	//		the height or width value given by the args object.
+	//
+	//		default to height:, so leave height null and specify width:
+	//		to wipeTo a width. note: this may be deprecated by a 
+	//
+	//		Note that the final value should not include
+	//		units and should be an integer.  Thus a valid args object
+	//		would look something like this:
+	//
+	//		|	dojox.fx.wipeTo({ node: "nodeId", height: 200 }).play();
+	//
+	//		Node must have no margin/border/padding, so put another
+	//		node inside your target node for additional styling.
+
+	args.node = dojo.byId(args.node);
+	var node = args.node, s = node.style;
+
+	var dir = (args.width ? "width" : "height"),
+		endVal = args[dir],
+		props = {}
+	;
+
+	props[dir] = {
+		// 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
+			s.overflow = "hidden";
+			if(s.visibility == "hidden" || s.display == "none"){
+				s[dir] = "1px";
+				s.display = "";
+				s.visibility = "";
+				return 1;
+			}else{
+				var now = dojo.style(node,dir);
+				return Math.max(now, 1);
+			}
+		},
+		end: endVal
+	};
+
+	var anim = dojo.animateProperty(dojo.mixin({ properties: props }, args));
+	return anim; // dojo.Animation
 };
-}
diff --git a/dojox/fx/_core.js b/dojox/fx/_core.js
index 2e0617d..5cca70b 100644
--- a/dojox/fx/_core.js
+++ b/dojox/fx/_core.js
@@ -1,32 +1,58 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.fx._core"]){
-dojo._hasResource["dojox.fx._core"]=true;
 dojo.provide("dojox.fx._core");
-dojox.fx._Line=function(_1,_2){
-this.start=_1;
-this.end=_2;
-var _3=dojo.isArray(_1),d=(_3?[]:_2-_1);
-if(_3){
-dojo.forEach(this.start,function(s,i){
-d[i]=this.end[i]-s;
-},this);
-this.getValue=function(n){
-var _4=[];
-dojo.forEach(this.start,function(s,i){
-_4[i]=(d[i]*n)+s;
-},this);
-return _4;
-};
-}else{
-this.getValue=function(n){
-return (d*n)+this.start;
-};
-}
+
+dojox.fx._Line = function(start, end){
+	// summary: a custom _Line to accomodate multi-dimensional values
+	//	
+	// description: 
+	//	a normal dojo._Line is the curve, and does Line(start,end)
+	//	for propertyAnimation. as we make more complicatied animations, we realize
+	//	some properties can have 2, or 4 values relevant (x,y) or (t,l,r,b) for example 
+	//
+	// 	this function provides support for those Lines, and is ported directly from 0.4
+	//	this is a lot of extra code for something so seldom used, so we'll put it here as
+	//	and optional core addition. you can create a new line, and use it during onAnimate
+	//	as you see fit.
+	//
+	// start: Integer|Array
+	//	An Integer (or an Array of integers) to use as a starting point
+	// end: Integer|Array
+	//	An Integer (or an Array of integers) to use as an ending point
+	//
+	// example: see dojox.fx.smoothScroll 
+	//
+	// example: 
+	// |	// this is 10 .. 100 and 50 .. 500
+	// |	var curve = new dojox.fx._Line([10,50],[100,500]);
+	// |	// dojo.Animation.onAnimate is called at every step of the animation
+	// |	// to define current values. this _Line returns an array
+	// | 	// at each step. arguments[0] and [1] in this example. 
+	//
+	this.start = start;
+	this.end = end;
+	
+	var isArray = dojo.isArray(start), 
+		d = (isArray ? [] : end - start);
+	
+	if(isArray){
+		// multi-dimensional branch
+		dojo.forEach(this.start, function(s, i){
+			d[i] = this.end[i] - s;
+		}, this);
+		
+		this.getValue = function(/*float*/ n){
+			var res = [];
+			dojo.forEach(this.start, function(s, i){
+				res[i] = (d[i] * n) + s;
+			}, this);
+			return res; // Array
+		}
+	}else{
+		// single value branch, document here for both branches:
+		this.getValue = function(/*float*/ n){
+			// summary: Returns the point on the line, or an array of points
+			// n: a floating point number greater than 0 and less than 1
+			// returns: Mixed 
+			return (d * n) + this.start; // Decimal
+		}
+	}
 };
-}
diff --git a/dojox/fx/easing.js b/dojox/fx/easing.js
index 771eb4e..34deb86 100644
--- a/dojox/fx/easing.js
+++ b/dojox/fx/easing.js
@@ -1,14 +1,10 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.fx.easing"]){
-dojo._hasResource["dojox.fx.easing"]=true;
 dojo.provide("dojox.fx.easing");
 dojo.deprecated("dojox.fx.easing","Upgraded to Core, use dojo.fx.easing instead","2.0");
 dojo.require("dojo.fx.easing");
-dojox.fx.easing=dojo.fx.easing;
-}
+/*=====
+	dojox.fx.easing = {
+		// summary:
+		//		An Alias to `dojo.fx.easing`. Moved to Core in Dojo 1.2.
+	};
+=====*/
+dojox.fx.easing = dojo.fx.easing;
diff --git a/dojox/fx/ext-dojo/NodeList-style.js b/dojox/fx/ext-dojo/NodeList-style.js
index c4ede54..17d85f7 100644
--- a/dojox/fx/ext-dojo/NodeList-style.js
+++ b/dojox/fx/ext-dojo/NodeList-style.js
@@ -1,27 +1,62 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.fx.ext-dojo.NodeList-style"]){
-dojo._hasResource["dojox.fx.ext-dojo.NodeList-style"]=true;
 dojo.provide("dojox.fx.ext-dojo.NodeList-style");
 dojo.experimental("dojox.fx.ext-dojo.NodeList-style");
+// summary: 
+//		Core extensions to `dojo.NodeList` providing addtional fx to `dojo.NodeList-fx`
+// 		from `dojox.fx.style`
+//
+// description:
+//		A Package to extend dojo base NodeList with fx provided by the `dojox.fx` project.
+//		These are experimental animations, in an experimental 
+
 dojo.require("dojo.NodeList-fx");
 dojo.require("dojox.fx.style");
-dojo.extend(dojo.NodeList,{addClassFx:function(_1,_2){
-return dojo.fx.combine(this.map(function(n){
-return dojox.fx.addClass(n,_1,_2);
-}));
-},removeClassFx:function(_3,_4){
-return dojo.fx.combine(this.map(function(n){
-return dojox.fx.removeClass(n,_3,_4);
-}));
-},toggleClassFx:function(_5,_6,_7){
-return dojo.fx.combine(this.map(function(n){
-return dojox.fx.toggleClass(n,_5,_6,_7);
-}));
-}});
-}
+
+dojo.extend(dojo.NodeList, {
+
+	addClassFx: function(cssClass, args){
+		// 	summary:
+		//		Animate the effects of adding a class to all nodes in this list.
+		//		see `dojox.fx.addClass`
+		//
+		//	tags: FX, NodeList
+		//
+		//	example:
+		//	|	// fade all elements with class "bar" to to 50% opacity
+		//	|	dojo.query(".bar").addClassFx("bar").play();
+
+		return dojo.fx.combine(this.map(function(n){ // dojo.Animation
+			return dojox.fx.addClass(n, cssClass, args);
+		}));
+	},
+	
+	removeClassFx: function(cssClass, args){
+		// summary:
+		//		Animate the effect of removing a class to all nodes in this list.
+		//		see `dojox.fx.removeClass`
+		//
+		//	tags: FX, NodeList
+		//
+		// example:
+		//	| dojo.query(".box").removeClassFx("bar").play();
+
+		return dojo.fx.combine(this.map(function(n){ // dojo.Animation
+			return dojox.fx.removeClass(n, cssClass, args);
+		}));
+	},
+	
+	toggleClassFx: function(cssClass, force, args){
+		// summary:
+		//		Animate the effect of adding or removing a class to all nodes in this list.
+		//		see `dojox.fx.toggleClass`
+		//
+		//	tags: FX, NodeList
+		//
+		// example:
+		//	| dojo.query(".box").toggleClass("bar").play();
+
+		return dojo.fx.combine(this.map(function(n){ // dojo.Animation
+			return dojox.fx.toggleClass(n, cssClass, force, args);
+		}));
+	}
+
+});
diff --git a/dojox/fx/ext-dojo/NodeList.js b/dojox/fx/ext-dojo/NodeList.js
index 59e8265..ffb5bdf 100644
--- a/dojox/fx/ext-dojo/NodeList.js
+++ b/dojox/fx/ext-dojo/NodeList.js
@@ -1,25 +1,62 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.fx.ext-dojo.NodeList"]){
-dojo._hasResource["dojox.fx.ext-dojo.NodeList"]=true;
 dojo.provide("dojox.fx.ext-dojo.NodeList");
 dojo.experimental("dojox.fx.ext-dojo.NodeList");
+// summary: Core extensions to dojo.NodeList providing addtional fx to dojo.NodeList-fx
+// description:
+//	A Package to extend dojo base NodeList with fx provided by the dojox.fx project.
+//	These are experimental animations, in an experimental 
+
 dojo.require("dojo.NodeList-fx");
 dojo.require("dojox.fx");
-dojo.extend(dojo.NodeList,{sizeTo:function(_1){
-return this._anim(dojox.fx,"sizeTo",_1);
-},slideBy:function(_2){
-return this._anim(dojox.fx,"slideBy",_2);
-},highlight:function(_3){
-return this._anim(dojox.fx,"highlight",_3);
-},fadeTo:function(_4){
-return this._anim(dojo,"_fade",_4);
-},wipeTo:function(_5){
-return this._anim(dojox.fx,"wipeTo",_5);
-}});
-}
+
+dojo.extend(dojo.NodeList, {
+
+	sizeTo: function(args){
+		//	summary:
+		//		size all elements of this NodeList. Returns an instance of dojo.Animation
+		//	example:
+		//	|	// size all divs with class "blah"
+		//	|	dojo.query("div.blah").sizeTo({
+		//	|		width:50,
+		//	|		height:50
+		//	|	}).play();
+		return this._anim(dojox.fx, "sizeTo", args); // dojo.Animation
+	},
+
+	slideBy: function(args){
+		//	summary:
+		//		slide all elements of this NodeList. Returns an instance of dojo.Animation
+		//		
+		//	example:
+		//	|	// slide all tables with class "blah" 10 px 
+		//	|	dojo.query("table.blah").slideBy({ top:10, left:10 }).play();
+		return this._anim(dojox.fx, "slideBy", args); // dojo.Animation
+	},
+
+	highlight: function(args){
+		//	summary:
+		//		highlight all elements of the node list.
+		//		Returns an instance of dojo.Animation
+		//	example:
+		//	|	// highlight all links with class "foo" 
+		//	|	dojo.query("a.foo").hightlight().play();
+		return this._anim(dojox.fx, "highlight", args); // dojo.Animation
+	},
+
+	fadeTo: function(args){
+		// 	summary:
+		//		fade all elements of the node list to a specified opacity
+		//	example:
+		//	|	// fade all elements with class "bar" to to 50% opacity
+		//	|	dojo.query(".bar").fadeTo({ end: 0.5 }).play();
+		return this._anim(dojo,"_fade",args);
+	},
+	
+	wipeTo: function(args){
+		// summary:
+		//		Wipe all elements of the NodeList to a specified width: or height:
+		// example:
+		//	| dojo.query(".box").wipeTo({ width: 300px }).play();
+		return this._anim(dojox.fx, "wipeTo", args);
+	}
+
+});
diff --git a/dojox/fx/ext-dojo/complex.js b/dojox/fx/ext-dojo/complex.js
new file mode 100644
index 0000000..7673b6f
--- /dev/null
+++ b/dojox/fx/ext-dojo/complex.js
@@ -0,0 +1,169 @@
+dojo.provide("dojox.fx.ext-dojo.complex");
+
+(function(){
+	var da = dojo.animateProperty;
+	dojo.animateProperty = function(options){
+		// summary:
+		//		An extension of dojo.animateProperty which adds functionality
+		//		that animates a "complex property". The primary example is the
+		//		clip style: rect(10px 30px 10px 50px).
+		//		Note this can also be used with (and is actually intended for)
+		//		CSS3 properties, such as transform:
+		//		transform: rotate(10deg) translateX(0px)
+		//		
+		//	description:
+		//		The standard animation doesn't know what to do with something like
+		//		rect(...). This class identifies complex properties by they being a
+		//		string and having parenthesis. If so, that property is made into a
+		//		dojox.fx._Complex object and the getValue() is obtained from
+		//		there.
+		//		
+		//	example:
+		//		|	var ani = dojo.animateProperty({
+		//		|		node:dojo.byId("myDiv"),
+		//		|		duration:600,
+		//		|		properties:{
+		//		|			clip:{start:'rect(0px 50px 50px 0px)', end:'rect(10px 30px 30px 10px)'}
+		//		|		}
+		//		|	}).play();
+		//		
+		var d = dojo;
+		var ani = da(options);
+		
+		dojo.connect(ani, "beforeBegin", function(){
+			// dojo.Animate original still invokes and still
+			// works. We're appending this functionality to
+			// modify targeted properties.
+			ani.curve.getValue = function(r){
+				// Overwriting dojo.Animate's curve.getValue
+				// This is mostly duplicate code, except it looks
+				// for an instance of dojox.fx._Complex.
+				var ret = {};
+				for(var p in this._properties){
+					var prop = this._properties[p],
+						start = prop.start;
+					if(start instanceof d.Color){
+						ret[p] = d.blendColors(start, prop.end, r, prop.tempColor).toCss();
+					}else if(start instanceof dojox.fx._Complex){
+						ret[p] = start.getValue(r);
+					}else if(!d.isArray(start)){
+						ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units || "px" : 0);
+					}
+				}
+				return ret;
+			};
+			
+			// this.properties has already been set, as has this.curve._properties.
+			// We're fixing the props in curve which will have NaN attributes from
+			// our string property.
+			var pm = {};
+			for(var p in this.properties){
+				var o = this.properties[p];
+				if(typeof(o.start) == "string" && /\(/.test(o.start)){
+					this.curve._properties[p].start = new dojox.fx._Complex(o);
+				}
+			}
+		
+		});
+		return ani; // dojo.Animation
+	}
+})();
+
+dojo.declare("dojox.fx._Complex", null, {
+	// summary:
+	//		A class that takes a complex property such as
+	//		clip style: rect(10px 30px 10px 50px), and breaks it
+	//		into seperate animatable units. The object has a getValue()
+	//		that will return a string with the modified units.
+	//
+	PROP: /\([+-]?[\w|,|#|\.|\s]*\)/g,
+	constructor: function(options){
+		var beg = options.start.match(this.PROP);
+		var end = options.end.match(this.PROP);
+
+		var begProps = dojo.map(beg, this.getProps, this);
+		var endProps = dojo.map(end, this.getProps, this);
+
+		this._properties = {};
+		this.strProp = options.start;
+		dojo.forEach(begProps, function(prop, i){
+			dojo.forEach(prop, function(p, j){
+				this.strProp = this.strProp.replace(p, "PROP_"+i+""+j);
+				this._properties["PROP_"+i+""+j] = this.makePropObject(p, endProps[i][j])
+			},this);
+		},this);
+	},
+
+	getValue: function(/*Float*/r){
+		// summary:
+		// 		Returns a string with teh same integrity as the
+		// 		original star and end, but with the modified units.
+		var str = this.strProp, u;
+		for(var nm in this._properties){
+			var v, o = this._properties[nm];
+			if(o.units == "isColor"){
+				v = dojo.blendColors(o.beg, o.end, r).toCss(false);
+				u = "";
+			}else{
+				v = ((o.end - o.beg) * r) + o.beg;
+				u = o.units;
+			}
+			str = str.replace(nm, v + u);
+		}
+		
+		return str; // String
+	},
+	
+	makePropObject: function(/* String */beg, /* String */end){
+		// summary:
+		//		Returns an object that stores the numeric value and
+		//		units of the beggining and ending properties.
+		//		
+		var b = this.getNumAndUnits(beg);
+		var e = this.getNumAndUnits(end);
+		return {
+			beg:b.num,
+			end:e.num,
+			units:b.units
+		}; // Object
+	},
+	
+	getProps: function(/* String */str){
+		// summary:
+		//		Helper function that splits a stringified set of properties
+		//		into individual units.
+		//		
+		str = str.substring(1, str.length-1);
+		var s;
+		if(/,/.test(str)){
+			str = str.replace(/\s/g, "");
+			s = str.split(",");
+		}else{
+			str = str.replace(/\s{2,}/g, " ");
+			s = str.split(" ");
+		}
+		return s; // String
+	},
+	getNumAndUnits: function(prop){
+		// summary:
+		//		Helper function that returns the numeric verion of the string
+		//		property (or dojo.Color object) and the unit in which it was
+		//		defined.
+		//		
+		if(!prop){ return {}; }
+		if(/#/.test(prop)){
+			return {
+				num: new dojo.Color(prop),
+				units:"isColor"
+			}; // Object
+		}
+		var o = {
+			num:parseFloat(/-*[\d\.\d|\d]{1,}/.exec(prop).join(""))
+		};
+		o.units = /[a-z]{1,}/.exec(prop);//.join("");
+		o.units = o.units && o.units.length ? o.units.join("") : "";
+		return o; // Object
+	}
+});
+
+
diff --git a/dojox/fx/ext-dojo/reverse.js b/dojox/fx/ext-dojo/reverse.js
new file mode 100644
index 0000000..d442356
--- /dev/null
+++ b/dojox/fx/ext-dojo/reverse.js
@@ -0,0 +1,98 @@
+dojo.provide("dojox.fx.ext-dojo.reverse");
+dojo.require("dojo.fx.easing");
+dojo.require("dojo.fx");
+
+			
+dojo.extend(dojo.Animation, {
+	// summary:
+	//		A dojo.Animation extension that enables an easy reversal.
+	//	description:
+	//		To use, simply require dojox.fx.ext-dojo.reverse and a reverse()
+	//		method will be added to all dojo.Animations.
+	//		It can be used at any time during the animation. It does not
+	//		need to be called when it ends. It also reverses the easing -
+	//		if dojo.fx.easing.quadIn is used, dojo.fx.easing.quadOut will
+	//		be used when animating backwards.
+	//
+	_reversed: false,
+	reverse: function(/*Boolean*/keepPaused, /*Function ? */reverseEase){
+		// summary:
+		// 		The key method added to an animation to enable reversal.
+		// 	keepPaused: Boolean
+		// 		By default, calling reverse() will play the animation if
+		// 		it was paused. Pass in true to keep it paused (will have
+		// 		no effect if reverse is called while animation is playing).
+		// 	reverseEase: Function
+		// 		A function to use for the reverse easing. This allows for
+		// 		the possibility of custom eases that are not in the dojo.fx
+		// 		library.
+		// 		
+		var playing = this.status() == "playing";
+		this.pause();
+		this._reversed = !this._reversed;
+		var d = this.duration,
+			sofar = d * this._percent,
+			togo = d - sofar,
+			curr = new Date().valueOf(),
+			cp = this.curve._properties,
+			p = this.properties,
+			nm
+		;
+		this._endTime = curr + sofar;
+		this._startTime = curr - togo;
+		
+		if(playing){
+			this.gotoPercent(togo / d)
+		}
+		for(nm in p){
+			var tmp = p[nm].start;
+			p[nm].start = cp[nm].start = p[nm].end;
+			p[nm].end = cp[nm].end = tmp;
+		}
+		
+		if(this._reversed){
+			if(!this.rEase){
+				this.fEase = this.easing;
+				if(reverseEase){
+					this.rEase = reverseEase;
+				}else{
+					// loop through dojo.fx.easing to find the matching ease
+					var de = dojo.fx.easing, found, eName;
+					for(nm in de){
+						if(this.easing == de[nm]){
+							// get ease's name
+							found = nm; break;
+						}
+					}
+					
+					if(found){
+						// find ease's opposite
+						if(/InOut/.test(nm) || !/In|Out/i.test(nm)){
+							this.rEase = this.easing;
+						}else if(/In/.test(nm)){
+							eName = nm.replace("In", "Out");
+						}else{
+							eName = nm.replace("Out", "In");
+						}
+						if(eName){
+							this.rEase = dojo.fx.easing[eName];
+						}
+					}else{
+						// default ease, and other's like linear do not have an opposite
+						console.info("ease function to reverse not found");
+						this.rEase = this.easing;
+					}
+				}
+				
+			}
+			this.easing = this.rEase;
+		}else{
+			this.easing = this.fEase;
+		}
+		if(!keepPaused && this.status() != "playing"){
+			this.play();
+		}
+		
+		return this;
+	}
+});
\ No newline at end of file
diff --git a/dojox/fx/flip.js b/dojox/fx/flip.js
index be9e263..ddbeb4a 100644
--- a/dojox/fx/flip.js
+++ b/dojox/fx/flip.js
@@ -1,183 +1,503 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.fx.flip"]){
-dojo._hasResource["dojox.fx.flip"]=true;
 dojo.provide("dojox.fx.flip");
 dojo.experimental("dojox.fx.flip");
 dojo.require("dojo.fx");
 (function(){
-var _1="border",_2="Width",_3="Height",_4="Top",_5="Right",_6="Left",_7="Bottom";
-dojox.fx.flip=function(_8){
-var _9=dojo.create("div"),_a=_8.node=dojo.byId(_8.node),s=_a.style,_b=null,hs=null,pn=null,_c=_8.lightColor||"#dddddd",_d=_8.darkColor||"#555555",_e=dojo.style(_a,"backgroundColor"),_f=_8.endColor||_e,_10={},_11=[],_12=_8.duration?_8.duration/2:250,dir=_8.dir||"left",_13=0.9,_14="transparent",_15=_8.whichAnim,_16=_8.axis||"center",_17=_8.depth;
-var _18=function(_19){
-return ((new dojo.Color(_19)).toHex()==="#000000")?"#000001":_19;
-};
-if(dojo.isIE<7){
-_f=_18(_f);
-_c=_18(_c);
-_d=_18(_d);
-_e=_18(_e);
-_14="black";
-_9.style.filter="chroma(color='#000000')";
-}
-var _1a=(function(n){
-return function(){
-var ret=dojo.coords(n,true);
-_b={top:ret.y,left:ret.x,width:ret.w,height:ret.h};
-};
-})(_a);
-_1a();
-hs={position:"absolute",top:_b["top"]+"px",left:_b["left"]+"px",height:"0",width:"0",zIndex:_8.zIndex||(s.zIndex||0),border:"0 solid "+_14,fontSize:"0",visibility:"hidden"};
-var _1b=[{},{top:_b["top"],left:_b["left"]}];
-var _1c={left:[_6,_5,_4,_7,_2,_3,"end"+_3+"Min",_6,"end"+_3+"Max"],right:[_5,_6,_4,_7,_2,_3,"end"+_3+"Min",_6,"end"+_3+"Max"],top:[_4,_7,_6,_5,_3,_2,"end"+_2+"Min",_4,"end"+_2+"Max"],bottom:[_7,_4,_6,_5,_3,_2,"end"+_2+"Min",_4,"end"+_2+"Max"]};
-pn=_1c[dir];
-if(typeof _17!="undefined"){
-_17=Math.max(0,Math.min(1,_17))/2;
-_13=0.4+(0.5-_17);
-}else{
-_13=Math.min(0.9,Math.max(0.4,_b[pn[5].toLowerCase()]/_b[pn[4].toLowerCase()]));
-}
-var p0=_1b[0];
-for(var i=4;i<6;i++){
-if(_16=="center"||_16=="cube"){
-_b["end"+pn[i]+"Min"]=_b[pn[i].toLowerCase()]*_13;
-_b["end"+pn[i]+"Max"]=_b[pn[i].toLowerCase()]/_13;
-}else{
-if(_16=="shortside"){
-_b["end"+pn[i]+"Min"]=_b[pn[i].toLowerCase()];
-_b["end"+pn[i]+"Max"]=_b[pn[i].toLowerCase()]/_13;
-}else{
-if(_16=="longside"){
-_b["end"+pn[i]+"Min"]=_b[pn[i].toLowerCase()]*_13;
-_b["end"+pn[i]+"Max"]=_b[pn[i].toLowerCase()];
-}
-}
-}
-}
-if(_16=="center"){
-p0[pn[2].toLowerCase()]=_b[pn[2].toLowerCase()]-(_b[pn[8]]-_b[pn[6]])/4;
-}else{
-if(_16=="shortside"){
-p0[pn[2].toLowerCase()]=_b[pn[2].toLowerCase()]-(_b[pn[8]]-_b[pn[6]])/2;
-}
-}
-_10[pn[5].toLowerCase()]=_b[pn[5].toLowerCase()]+"px";
-_10[pn[4].toLowerCase()]="0";
-_10[_1+pn[1]+_2]=_b[pn[4].toLowerCase()]+"px";
-_10[_1+pn[1]+"Color"]=_e;
-p0[_1+pn[1]+_2]=0;
-p0[_1+pn[1]+"Color"]=_d;
-p0[_1+pn[2]+_2]=p0[_1+pn[3]+_2]=_16!="cube"?(_b["end"+pn[5]+"Max"]-_b["end"+pn[5]+"Min"])/2:_b[pn[6]]/2;
-p0[pn[7].toLowerCase()]=_b[pn[7].toLowerCase()]+_b[pn[4].toLowerCase()]/2+(_8.shift||0);
-p0[pn[5].toLowerCase()]=_b[pn[6]];
-var p1=_1b[1];
-p1[_1+pn[0]+"Color"]={start:_c,end:_f};
-p1[_1+pn[0]+_2]=_b[pn[4].toLowerCase()];
-p1[_1+pn[2]+_2]=0;
-p1[_1+pn[3]+_2]=0;
-p1[pn[5].toLowerCase()]={start:_b[pn[6]],end:_b[pn[5].toLowerCase()]};
-dojo.mixin(hs,_10);
-dojo.style(_9,hs);
-dojo.body().appendChild(_9);
-var _1d=function(){
-dojo.destroy(_9);
-s.backgroundColor=_f;
-s.visibility="visible";
-};
-if(_15=="last"){
-for(i in p0){
-p0[i]={start:p0[i]};
-}
-p0[_1+pn[1]+"Color"]={start:_d,end:_f};
-p1=p0;
-}
-if(!_15||_15=="first"){
-_11.push(dojo.animateProperty({node:_9,duration:_12,properties:p0}));
-}
-if(!_15||_15=="last"){
-_11.push(dojo.animateProperty({node:_9,duration:_12,properties:p1,onEnd:_1d}));
-}
-dojo.connect(_11[0],"play",function(){
-_9.style.visibility="visible";
-s.visibility="hidden";
-});
-return dojo.fx.chain(_11);
-};
-dojox.fx.flipCube=function(_1e){
-var _1f=[],mb=dojo.marginBox(_1e.node),_20=mb.w/2,_21=mb.h/2,_22={top:{pName:"height",args:[{whichAnim:"first",dir:"top",shift:-_21},{whichAnim:"last",dir:"bottom",shift:_21}]},right:{pName:"width",args:[{whichAnim:"first",dir:"right",shift:_20},{whichAnim:"last",dir:"left",shift:-_20}]},bottom:{pName:"height",args:[{whichAnim:"first",dir:"bottom",shift:_21},{whichAnim:"last",dir:"top",shift:-_21}]},left:{pName:"width",args:[{whichAnim:"first",dir:"left",shift:-_20},{whichAnim:"last",dir [...]
-var d=_22[_1e.dir||"left"],p=d.args;
-_1e.duration=_1e.duration?_1e.duration*2:500;
-_1e.depth=0.8;
-_1e.axis="cube";
-for(var i=p.length-1;i>=0;i--){
-dojo.mixin(_1e,p[i]);
-_1f.push(dojox.fx.flip(_1e));
-}
-return dojo.fx.combine(_1f);
-};
-dojox.fx.flipPage=function(_23){
-var n=_23.node,_24=dojo.coords(n,true),x=_24.x,y=_24.y,w=_24.w,h=_24.h,_25=dojo.style(n,"backgroundColor"),_26=_23.lightColor||"#dddddd",_27=_23.darkColor,_28=dojo.create("div"),_29=[],hn=[],dir=_23.dir||"right",pn={left:["left","right","x","w"],top:["top","bottom","y","h"],right:["left","left","x","w"],bottom:["top","top","y","h"]},_2a={right:[1,-1],left:[-1,1],top:[-1,1],bottom:[1,-1]};
-dojo.style(_28,{position:"absolute",width:w+"px",height:h+"px",top:y+"px",left:x+"px",visibility:"hidden"});
-var hs=[];
-for(var i=0;i<2;i++){
-var r=i%2,d=r?pn[dir][1]:dir,wa=r?"last":"first",_2b=r?_25:_26,_2c=r?_2b:_23.startColor||n.style.backgroundColor;
-hn[i]=dojo.clone(_28);
-var _2d=function(x){
-return function(){
-dojo.destroy(hn[x]);
-};
-}(i);
-dojo.body().appendChild(hn[i]);
-hs[i]={backgroundColor:r?_2c:_25};
-hs[i][pn[dir][0]]=_24[pn[dir][2]]+_2a[dir][0]*i*_24[pn[dir][3]]+"px";
-dojo.style(hn[i],hs[i]);
-_29.push(dojox.fx.flip({node:hn[i],dir:d,axis:"shortside",depth:_23.depth,duration:_23.duration/2,shift:_2a[dir][i]*_24[pn[dir][3]]/2,darkColor:_27,lightColor:_26,whichAnim:wa,endColor:_2b}));
-dojo.connect(_29[i],"onEnd",_2d);
-}
-return dojo.fx.chain(_29);
-};
-dojox.fx.flipGrid=function(_2e){
-var _2f=_2e.rows||4,_30=_2e.cols||4,_31=[],_32=dojo.create("div"),n=_2e.node,_33=dojo.coords(n,true),x=_33.x,y=_33.y,nw=_33.w,nh=_33.h,w=_33.w/_30,h=_33.h/_2f,_34=[];
-dojo.style(_32,{position:"absolute",width:w+"px",height:h+"px",backgroundColor:dojo.style(n,"backgroundColor")});
-for(var i=0;i<_2f;i++){
-var r=i%2,d=r?"right":"left",_35=r?1:-1;
-var cn=dojo.clone(n);
-dojo.style(cn,{position:"absolute",width:nw+"px",height:nh+"px",top:y+"px",left:x+"px",clip:"rect("+i*h+"px,"+nw+"px,"+nh+"px,0)"});
-dojo.body().appendChild(cn);
-_31[i]=[];
-for(var j=0;j<_30;j++){
-var hn=dojo.clone(_32),l=r?j:_30-(j+1);
-var _36=function(xn,_37,_38){
-return function(){
-if(!(_37%2)){
-dojo.style(xn,{clip:"rect("+_37*h+"px,"+(nw-(_38+1)*w)+"px,"+((_37+1)*h)+"px,0px)"});
-}else{
-dojo.style(xn,{clip:"rect("+_37*h+"px,"+nw+"px,"+((_37+1)*h)+"px,"+((_38+1)*w)+"px)"});
-}
-};
-}(cn,i,j);
-dojo.body().appendChild(hn);
-dojo.style(hn,{left:x+l*w+"px",top:y+i*h+"px",visibility:"hidden"});
-var a=dojox.fx.flipPage({node:hn,dir:d,duration:_2e.duration||900,shift:_35*w/2,depth:0.2,darkColor:_2e.darkColor,lightColor:_2e.lightColor,startColor:_2e.startColor||_2e.node.style.backgroundColor}),_39=function(xn){
-return function(){
-dojo.destroy(xn);
-};
-}(hn);
-dojo.connect(a,"play",this,_36);
-dojo.connect(a,"play",this,_39);
-_31[i].push(a);
-}
-_34.push(dojo.fx.chain(_31[i]));
-}
-dojo.connect(_34[0],"play",function(){
-dojo.style(n,{visibility:"hidden"});
-});
-return dojo.fx.combine(_34);
-};
+	
+	// because ShrinkSafe will eat this up: 
+	var borderConst = "border",
+		widthConst = "Width",
+		heightConst = "Height",
+		topConst = "Top",
+		rightConst = "Right",
+		leftConst = "Left",
+		bottomConst = "Bottom"
+	;
+
+	dojox.fx.flip = function(/*Object*/ args){
+		// summary: Animate a node flipping following a specific direction
+		//	
+		// description:
+		//		Returns an animation that will flip the
+		//		node around a central axis:
+		//		if args.dir is "left" or "right" --> y axis
+		//		if args.dir is "top" or "bottom" --> x axis
+		//
+		//		This effect is obtained using a border distorsion applied to a helper node.
+		//
+		//		The user can specify three background colors for the helper node:
+		//		darkColor: the darkest color reached during the animation 
+		//		lightColor: the brightest color
+		//		endColor: the final backgroundColor for the node
+        //
+        //		depth: Float
+		//			 0 <= depth <= 1 overrides the computed "depth"
+        //          (0: min distorsion, 1: max distorsion)
+        //
+        //      whichAnim: String
+        //          "first"          : the first half animation
+        //          "last"           : the second one
+        //          "both" (default) : both
+        //
+        //      axis: String
+        //          "center" (default)    : the node is flipped around his center
+        //          "shortside"           : the node is flipped around his "short" (in perspective) side
+        //          "longside"            : the node is flipped around his "long" (in perspective) side
+        //          "cube"                : the node flips around the central axis of the cube
+        //
+        //      shift: Integer
+        //          node translation, perpendicular to the rotation axis
+		//
+		//	example:
+		//	|	var anim = dojox.fx.flip({ 
+		//	|		node: dojo.byId("nodeId"),
+		//	|		dir: "top",
+		//	|		darkColor: "#555555",
+		//	|		lightColor: "#dddddd",
+		//	|		endColor: "#666666",
+		//	|		depth: .5,
+		//	|		shift: 50,
+		//	|		duration:300
+		//	|	  });
+
+		var helperNode = dojo.create("div"),
+			node = args.node = dojo.byId(args.node), 
+			s = node.style,
+			dims = null, 
+			hs = null, 
+			pn = null,
+			lightColor = args.lightColor || "#dddddd", 
+			darkColor = args.darkColor || "#555555",
+			bgColor = dojo.style(node, "backgroundColor"), 
+			endColor = args.endColor || bgColor,
+			staticProps = {}, 
+			anims = [],
+			duration = args.duration ? args.duration / 2 : 250,
+			dir = args.dir || "left", 
+			pConst = .9,
+			transparentColor = "transparent",
+			whichAnim = args.whichAnim,
+			axis = args.axis || "center",
+			depth = args.depth
+		;
+		// IE6 workaround: IE6 doesn't support transparent borders
+		var convertColor = function(color){
+			return ((new dojo.Color(color)).toHex() === "#000000") ? "#000001" : color;
+		};
+
+		if(dojo.isIE < 7){
+			endColor = convertColor(endColor);
+			lightColor = convertColor(lightColor);
+			darkColor = convertColor(darkColor);
+			bgColor = convertColor(bgColor);
+			transparentColor = "black";
+			helperNode.style.filter = "chroma(color='#000000')";
+		}
+
+		var init = (function(n){
+			return function(){
+				var ret = dojo.coords(n, true);
+				dims = {
+					top: ret.y,
+					left: ret.x,
+					width: ret.w,
+					height: ret.h
+				};
+			}
+		})(node);
+		init();
+		// helperNode initialization
+		hs = {
+			position: "absolute",
+			top: dims["top"] + "px",
+			left: dims["left"] + "px",
+			height: "0",
+			width: "0",
+			zIndex: args.zIndex || (s.zIndex || 0),
+			border: "0 solid " + transparentColor,
+			fontSize: "0",
+			visibility: "hidden"
+		};
+		var props = [ {}, 
+			{
+				top: dims["top"],
+				left: dims["left"]
+			}
+		];
+		var dynProperties = {
+			left: [leftConst, rightConst, topConst, bottomConst, widthConst, heightConst, "end" + heightConst + "Min", leftConst, "end" + heightConst + "Max"],
+			right: [rightConst, leftConst, topConst, bottomConst, widthConst, heightConst, "end" + heightConst + "Min", leftConst, "end" + heightConst + "Max"],
+			top: [topConst, bottomConst, leftConst, rightConst, heightConst, widthConst, "end" + widthConst + "Min", topConst, "end" + widthConst + "Max"],
+			bottom: [bottomConst, topConst, leftConst, rightConst, heightConst, widthConst, "end" + widthConst + "Min", topConst, "end" + widthConst + "Max"] 
+		};
+		// property names
+		pn = dynProperties[dir];
+
+		// .4 <= pConst <= .9
+		if(typeof depth != "undefined"){
+			depth = Math.max(0, Math.min(1, depth)) / 2;
+			pConst = .4 + (.5 - depth);
+		}else{
+			pConst = Math.min(.9, Math.max(.4, dims[pn[5].toLowerCase()] / dims[pn[4].toLowerCase()]));
+		}
+		var p0 = props[0];
+		for(var i = 4; i < 6; i++){
+			if(axis == "center" || axis == "cube"){ // find a better name for "cube" 
+				dims["end" + pn[i] + "Min"] = dims[pn[i].toLowerCase()] * pConst; 
+				dims["end" + pn[i] + "Max"] = dims[pn[i].toLowerCase()] / pConst; 
+			}else if(axis == "shortside"){
+				dims["end" + pn[i] + "Min"] = dims[pn[i].toLowerCase()];
+				dims["end" + pn[i] + "Max"] = dims[pn[i].toLowerCase()] / pConst; 
+			}else if(axis == "longside"){
+				dims["end" + pn[i] + "Min"] = dims[pn[i].toLowerCase()] * pConst;
+				dims["end" + pn[i] + "Max"] = dims[pn[i].toLowerCase()];  
+			}
+		}
+		if(axis == "center"){
+			p0[pn[2].toLowerCase()] = dims[pn[2].toLowerCase()] - (dims[pn[8]] - dims[pn[6]]) / 4;
+		}else if(axis == "shortside"){
+			p0[pn[2].toLowerCase()] = dims[pn[2].toLowerCase()] - (dims[pn[8]] - dims[pn[6]]) / 2;
+		}
+
+		staticProps[pn[5].toLowerCase()] = dims[pn[5].toLowerCase()] + "px";
+		staticProps[pn[4].toLowerCase()] = "0";
+		staticProps[borderConst + pn[1] + widthConst] = dims[pn[4].toLowerCase()] + "px";
+		staticProps[borderConst + pn[1] + "Color"] = bgColor;
+
+		p0[borderConst + pn[1] + widthConst] = 0; 
+		p0[borderConst + pn[1] + "Color"] = darkColor; 
+		p0[borderConst + pn[2] + widthConst] = p0[borderConst + pn[3] + widthConst] = axis != "cube" 
+			? (dims["end" + pn[5] +  "Max"] - dims["end" + pn[5] + "Min"]) / 2
+			: dims[pn[6]] / 2
+		;
+		p0[pn[7].toLowerCase()] = dims[pn[7].toLowerCase()] + dims[pn[4].toLowerCase()] / 2 + (args.shift || 0);
+		p0[pn[5].toLowerCase()] = dims[pn[6]];
+
+		var p1 = props[1];
+		p1[borderConst + pn[0] + "Color"] = { start: lightColor, end: endColor };
+		p1[borderConst + pn[0] + widthConst] = dims[pn[4].toLowerCase()];
+		p1[borderConst + pn[2] + widthConst] = 0;
+		p1[borderConst + pn[3] + widthConst] = 0;
+		p1[pn[5].toLowerCase()] = { start: dims[pn[6]], end: dims[pn[5].toLowerCase()] };
+
+		dojo.mixin(hs, staticProps);
+		dojo.style(helperNode, hs);
+		dojo.body().appendChild(helperNode);
+
+		var finalize = function(){
+//			helperNode.parentNode.removeChild(helperNode);
+			dojo.destroy(helperNode);
+			// fixes a flicker when the animation ends
+			s.backgroundColor = endColor;
+			s.visibility = "visible";
+		};
+		if(whichAnim == "last"){
+			for(i in p0){
+				p0[i] = { start: p0[i] };
+			}
+			p0[borderConst + pn[1] + "Color"] = { start: darkColor, end: endColor }; 
+			p1 = p0;
+		}
+		if(!whichAnim || whichAnim == "first"){
+			anims.push(dojo.animateProperty({
+				node: helperNode, 
+				duration: duration,
+				properties: p0
+			}));
+		}
+		if(!whichAnim || whichAnim == "last"){
+			anims.push(dojo.animateProperty({
+				node: helperNode, 
+				duration: duration,
+				properties: p1,
+				onEnd: finalize
+			}));
+		}
+
+		// hide the original node
+		dojo.connect(anims[0], "play", function(){
+			helperNode.style.visibility = "visible";
+			s.visibility = "hidden"; 
+		});
+
+		return dojo.fx.chain(anims); // dojo.Animation
+
+	}
+
+	dojox.fx.flipCube = function(/*Object*/ args){
+		// summary: An extension to `dojox.fx.flip` providing a more 3d-like rotation
+		//
+		// description:
+		//		An extension to `dojox.fx.flip` providing a more 3d-like rotation. 
+		//		Behaves the same as `dojox.fx.flip`, using the same attributes and 
+		//		other standard `dojo.Animation` properties.
+		//
+		//	example:
+		//		See `dojox.fx.flip`
+		var anims = [],
+			mb = dojo.marginBox(args.node),
+			shiftX = mb.w / 2,
+			shiftY = mb.h / 2,
+			dims = {
+				top: {
+					pName: "height",
+					args:[
+						{
+							whichAnim: "first",
+							dir: "top",
+							shift: -shiftY
+						},
+						{
+							whichAnim: "last",
+							dir: "bottom",
+							shift: shiftY
+						}
+					]
+				},
+				right: {
+					pName: "width",
+					args:[
+						{
+							whichAnim: "first",
+							dir: "right",
+							shift: shiftX
+						},
+						{
+							whichAnim: "last",
+							dir: "left",
+							shift: -shiftX
+						}
+					]
+				},
+				bottom: {
+					pName: "height",
+					args:[
+						{
+							whichAnim: "first",
+							dir: "bottom",
+							shift: shiftY
+						},
+						{
+							whichAnim: "last",
+							dir: "top",
+							shift: -shiftY
+						}
+					]
+				},
+				left: {
+					pName: "width",
+					args:[
+						{
+							whichAnim: "first",
+							dir: "left",
+							shift: -shiftX
+						},
+						{
+							whichAnim: "last",
+							dir: "right",
+							shift: shiftX
+						}
+					]
+				}
+			}
+		;
+		var d = dims[args.dir || "left"],
+			p = d.args
+		;
+		args.duration = args.duration ? args.duration * 2 : 500; 
+		args.depth = .8;
+		args.axis = "cube";
+		for(var i = p.length - 1; i >= 0; i--){
+			dojo.mixin(args, p[i]);
+			anims.push(dojox.fx.flip(args));
+		}
+		return dojo.fx.combine(anims);
+	};
+	
+	dojox.fx.flipPage = function(/*Object*/ args){
+		// summary: An extension to `dojox.fx.flip` providing a page flip like animation.
+		//
+		// description:
+		//		An extension to `dojox.fx.flip` providing a page flip effect.
+		//		Behaves the same as `dojox.fx.flip`, using the same attributes and
+		//		other standard `dojo.Animation` properties.
+		//
+		//	example:
+		//		See `dojox.fx.flip`
+		var n = args.node,
+			coords = dojo.coords(n, true),
+			x = coords.x,
+			y = coords.y,
+			w = coords.w,
+			h = coords.h,
+			bgColor = dojo.style(n, "backgroundColor"), 
+			lightColor = args.lightColor || "#dddddd",
+			darkColor = args.darkColor, 
+			helperNode = dojo.create("div"),
+			anims = [],
+			hn = [],
+			dir = args.dir || "right",
+			pn = {
+				left: ["left", "right", "x", "w"],
+				top: ["top", "bottom", "y", "h"],
+				right: ["left", "left", "x", "w"],
+				bottom: ["top", "top", "y", "h"]
+			},
+			shiftMultiplier = {
+				right: [1, -1],
+				left: [-1, 1],
+				top: [-1, 1],
+				bottom: [1, -1]
+			}
+		;
+		dojo.style(helperNode, {
+			position: "absolute",
+			width  : w + "px",
+			height : h + "px",
+			top    : y + "px",
+			left   : x + "px",
+			visibility: "hidden"
+		});
+		var hs = [];
+		for(var i = 0; i < 2; i++){
+			var r = i % 2,
+				d = r ? pn[dir][1] : dir,
+				wa = r ? "last" : "first",
+				endColor = r ? bgColor : lightColor,
+				startColor = r ? endColor : args.startColor || n.style.backgroundColor
+			;
+			hn[i] = dojo.clone(helperNode);
+			var	finalize = function(x){
+					return function(){
+						dojo.destroy(hn[x]);
+					}
+				}(i)
+			;
+			dojo.body().appendChild(hn[i]);
+			hs[i] = {
+				backgroundColor: r ? startColor : bgColor
+			};
+			
+			hs[i][pn[dir][0]] = coords[pn[dir][2]] + shiftMultiplier[dir][0] * i * coords[pn[dir][3]] + "px";
+			dojo.style(hn[i], hs[i]);
+			anims.push(dojox.fx.flip({
+			    node: hn[i],
+			    dir: d,
+			    axis: "shortside",
+			    depth: args.depth,
+			    duration: args.duration / 2,
+			    shift: shiftMultiplier[dir][i] * coords[pn[dir][3]] / 2,
+				darkColor: darkColor,
+				lightColor: lightColor,
+			    whichAnim: wa,
+			    endColor: endColor
+			}));
+			dojo.connect(anims[i], "onEnd", finalize);
+		}
+		return dojo.fx.chain(anims);
+	};
+	
+	
+	dojox.fx.flipGrid = function(/*Object*/ args){
+		// summary: An extension to `dojox.fx.flip` providing a decomposition in rows * cols flipping elements
+		//
+		// description:
+		//		An extension to `dojox.fx.flip` providing a page flip effect.
+		//		Behaves the same as `dojox.fx.flip`, using the same attributes and
+		//		other standard `dojo.Animation` properties and
+		//
+        //      cols: Integer columns
+        //      rows: Integer rows
+		//
+		//      duration: the single flip duration
+		//
+		//	example:
+		//		See `dojox.fx.flip`
+		var rows = args.rows || 4,
+			cols = args.cols || 4,
+			anims = [],
+			helperNode = dojo.create("div"),
+			n = args.node,
+			coords = dojo.coords(n, true),
+			x = coords.x,
+			y = coords.y,
+			nw = coords.w,
+			nh = coords.h,
+			w = coords.w / cols,
+			h = coords.h / rows,
+			cAnims = []
+		;
+		dojo.style(helperNode, {
+			position: "absolute",
+			width: w + "px",
+			height: h + "px",
+			backgroundColor: dojo.style(n, "backgroundColor")
+		});
+		for(var i = 0; i < rows; i++){
+			var r = i % 2,
+				d = r ? "right" : "left",
+				signum = r ? 1 : -1
+			;
+			// cloning
+			var cn = dojo.clone(n);
+			dojo.style(cn, {
+				position: "absolute",
+				width: nw + "px",
+				height: nh + "px",
+				top: y + "px",
+				left: x + "px",
+				clip: "rect(" + i * h + "px," + nw + "px," + nh + "px,0)"	
+			});
+	     	dojo.body().appendChild(cn);
+			anims[i] = [];
+			for(var j = 0; j < cols; j++){
+				var hn = dojo.clone(helperNode),
+					l = r ? j : cols - (j + 1)
+				; 
+				var adjustClip = function(xn, yCounter, xCounter){
+					return function(){
+						if(!(yCounter % 2)){
+							dojo.style(xn, {
+								clip: "rect(" + yCounter * h + "px," + (nw - (xCounter + 1) * w ) + "px," + ((yCounter + 1) * h) + "px,0px)"
+							});
+						}else{
+							dojo.style(xn, {
+								clip: "rect(" + yCounter * h + "px," + nw + "px," + ((yCounter + 1) * h) + "px," + ((xCounter + 1) * w) + "px)"
+							});
+						}
+					}
+				}(cn, i, j);
+	     		dojo.body().appendChild(hn);
+	     		dojo.style(hn, {
+	     		    left: x + l * w + "px",
+	     		    top: y + i * h + "px",
+					visibility: "hidden"
+	     		});
+				var a = dojox.fx.flipPage({
+				   node: hn,
+				   dir: d,
+				   duration: args.duration || 900,
+				   shift: signum * w/2,
+				   depth: .2,
+				   darkColor: args.darkColor,
+				   lightColor: args.lightColor,
+				   startColor: args.startColor || args.node.style.backgroundColor
+				}),
+				removeHelper = function(xn){
+					return function(){
+						dojo.destroy(xn);
+					}
+				}(hn)
+				;
+				dojo.connect(a, "play", this, adjustClip);
+				dojo.connect(a, "play", this, removeHelper);
+				anims[i].push(a);
+			}
+			cAnims.push(dojo.fx.chain(anims[i]));
+			
+		}
+		dojo.connect(cAnims[0], "play", function(){
+			dojo.style(n, {visibility: "hidden"});
+		});
+		return dojo.fx.combine(cAnims);
+	};
 })();
-}
diff --git a/dojox/fx/scroll.js b/dojox/fx/scroll.js
index 9368372..6f610a6 100644
--- a/dojox/fx/scroll.js
+++ b/dojox/fx/scroll.js
@@ -1,33 +1,43 @@
-/*
-	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
-*/
+dojo.provide("dojox.fx.scroll");
+dojo.experimental("dojox.fx.scroll"); 
 
+dojo.require("dojox.fx._core"); 
 
-if(!dojo._hasResource["dojox.fx.scroll"]){
-dojo._hasResource["dojox.fx.scroll"]=true;
-dojo.provide("dojox.fx.scroll");
-dojo.experimental("dojox.fx.scroll");
-dojo.require("dojox.fx._core");
-dojox.fx.smoothScroll=function(_1){
-if(!_1.target){
-_1.target=dojo.coords(_1.node,true);
-}
-var _2=dojo[(dojo.isIE?"isObject":"isFunction")](_1["win"].scrollTo);
-var _3=(_2)?(function(_4){
-_1.win.scrollTo(_4[0],_4[1]);
-}):(function(_5){
-_1.win.scrollLeft=_5[0];
-_1.win.scrollTop=_5[1];
-});
-var _6=new dojo.Animation(dojo.mixin({beforeBegin:function(){
-if(this.curve){
-delete this.curve;
-}
-var _7=_2?dojo._docScroll():{x:_1.win.scrollLeft,y:_1.win.scrollTop};
-_6.curve=new dojox.fx._Line([_7.x,_7.y],[_1.target.x,_1.target.y]);
-},onAnimate:_3},_1));
-return _6;
+dojox.fx.smoothScroll = function(/* Object */args){
+	// summary: Returns an animation that will smooth-scroll to a node
+	// description: This implementation support either horizontal or vertical scroll, as well as
+	// both. In addition, element in iframe can be scrolled to correctly.
+	// offset: {x: int, y: int} this will be added to the target position
+	// duration: Duration of the animation in milliseconds.
+	// win: a node or window object to scroll
+	
+	if(!args.target){ args.target = dojo.position(args.node,true); }
+
+	var isWindow = dojo[(dojo.isIE ? "isObject" : "isFunction")](args["win"].scrollTo),
+		delta = { x: args.target.x, y: args.target.y }
+	;
+	if(!isWindow){
+		var winPos = dojo.position(args.win);
+		delta.x -= winPos.x;
+		delta.y -= winPos.y;
+	}
+
+	var _anim = (isWindow) ?
+		(function(val){
+			args.win.scrollTo(val[0],val[1]);
+		}) :
+		(function(val){
+			args.win.scrollLeft = val[0];
+			args.win.scrollTop = val[1];
+		});
+
+	var anim = new dojo.Animation(dojo.mixin({
+		beforeBegin: function(){
+			if(this.curve){ delete this.curve; }
+			var current = isWindow ? dojo._docScroll() : {x: args.win.scrollLeft, y: args.win.scrollTop};
+			anim.curve = new dojox.fx._Line([current.x,current.y],[delta.x,delta.y]);
+		},
+		onAnimate: _anim
+	},args));
+	return anim; // dojo.Animation
 };
-}
diff --git a/dojox/fx/split.js b/dojox/fx/split.js
index c0909f1..83fc2a9 100644
--- a/dojox/fx/split.js
+++ b/dojox/fx/split.js
@@ -1,318 +1,662 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.fx.split"]){
-dojo._hasResource["dojox.fx.split"]=true;
 dojo.provide("dojox.fx.split");
+
 dojo.require("dojo.fx");
 dojo.require("dojo.fx.easing");
-dojo.mixin(dojox.fx,{_split:function(_1){
-_1.rows=_1.rows||3;
-_1.columns=_1.columns||3;
-_1.duration=_1.duration||1000;
-var _2=_1.node=dojo.byId(_1.node),_3=_2.parentNode,_4=_3,_5=dojo.body(),_6="position";
-while(_4&&_4!=_5&&dojo.style(_4,_6)=="static"){
-_4=_4.parentNode;
-}
-var _7=_4!=_5?dojo.position(_4,true):{x:0,y:0},_8=dojo.position(_2,true),_9=dojo.style(_2,"height"),_a=dojo.style(_2,"width"),_b=dojo.style(_2,"borderLeftWidth")+dojo.style(_2,"borderRightWidth"),_c=dojo.style(_2,"borderTopWidth")+dojo.style(_2,"borderBottomWidth"),_d=Math.ceil(_9/_1.rows),_e=Math.ceil(_a/_1.columns),_f=dojo.create(_2.tagName,{style:{position:"absolute",padding:0,margin:0,border:"none",top:_8.y-_7.y+"px",left:_8.x-_7.x+"px",height:_9+_c+"px",width:_a+_b+"px",background:" [...]
-for(var y=0,ly=_1.rows;y<ly;y++){
-for(var x=0,lx=_1.columns;x<lx;x++){
-var _12=dojo.clone(_11),_13=dojo.clone(_2),_14=y*_d,_15=x*_e;
-_13.style.filter="";
-dojo.removeAttr(_13,"id");
-dojo.style(_12,{border:"none",overflow:"hidden",top:_14+"px",left:_15+"px"});
-dojo.style(_13,{position:"static",opacity:"1",marginTop:-_14+"px",marginLeft:-_15+"px"});
-_12.appendChild(_13);
-_f.appendChild(_12);
-var _16=_1.pieceAnimation(_12,x,y,_8);
-if(dojo.isArray(_16)){
-_10=_10.concat(_16);
-}else{
-_10.push(_16);
-}
-}
-}
-var _17=dojo.fx.combine(_10);
-dojo.connect(_17,"onEnd",_17,function(){
-_f.parentNode.removeChild(_f);
-});
-if(_1.onPlay){
-dojo.connect(_17,"onPlay",_17,_1.onPlay);
-}
-if(_1.onEnd){
-dojo.connect(_17,"onEnd",_17,_1.onEnd);
-}
-return _17;
-},explode:function(_18){
-var _19=_18.node=dojo.byId(_18.node);
-_18.rows=_18.rows||3;
-_18.columns=_18.columns||3;
-_18.distance=_18.distance||1;
-_18.duration=_18.duration||1000;
-_18.random=_18.random||0;
-if(!_18.fade){
-_18.fade=true;
-}
-if(typeof _18.sync=="undefined"){
-_18.sync=true;
-}
-_18.random=Math.abs(_18.random);
-_18.pieceAnimation=function(_1a,x,y,_1b){
-var _1c=_1b.h/_18.rows,_1d=_1b.w/_18.columns,_1e=_18.distance*2,_1f=_18.duration,ps=_1a.style,_20=parseInt(ps.top),_21=parseInt(ps.left),_22=0,_23=0,_24=0;
-if(_18.random){
-var _25=(Math.random()*_18.random)+Math.max(1-_18.random,0);
-_1e*=_25;
-_1f*=_25;
-_22=((_18.unhide&&_18.sync)||(!_18.unhide&&!_18.sync))?(_18.duration-_1f):0;
-_23=Math.random()-0.5;
-_24=Math.random()-0.5;
-}
-var _26=((_1b.h-_1c)/2-_1c*y),_27=((_1b.w-_1d)/2-_1d*x),_28=Math.sqrt(Math.pow(_27,2)+Math.pow(_26,2)),_29=parseInt(_20-_26*_1e+_28*_24),_2a=parseInt(_21-_27*_1e+_28*_23);
-var _2b=dojo.animateProperty({node:_1a,duration:_1f,delay:_22,easing:(_18.easing||(_18.unhide?dojo.fx.easing.sinOut:dojo.fx.easing.circOut)),beforeBegin:(_18.unhide?function(){
-if(_18.fade){
-dojo.style(_1a,{opacity:"0"});
-}
-ps.top=_29+"px";
-ps.left=_2a+"px";
-}:undefined),properties:{top:(_18.unhide?{start:_29,end:_20}:{start:_20,end:_29}),left:(_18.unhide?{start:_2a,end:_21}:{start:_21,end:_2a})}});
-if(_18.fade){
-var _2c=dojo.animateProperty({node:_1a,duration:_1f,delay:_22,easing:(_18.fadeEasing||dojo.fx.easing.quadOut),properties:{opacity:(_18.unhide?{start:"0",end:"1"}:{start:"1",end:"0"})}});
-return (_18.unhide?[_2c,_2b]:[_2b,_2c]);
-}else{
-return _2b;
-}
-};
-var _2d=dojox.fx._split(_18);
-if(_18.unhide){
-dojo.connect(_2d,"onEnd",null,function(){
-dojo.style(_19,{opacity:"1"});
-});
-}else{
-dojo.connect(_2d,"onPlay",null,function(){
-dojo.style(_19,{opacity:"0"});
-});
-}
-return _2d;
-},converge:function(_2e){
-_2e.unhide=true;
-return dojox.fx.explode(_2e);
-},disintegrate:function(_2f){
-var _30=_2f.node=dojo.byId(_2f.node);
-_2f.rows=_2f.rows||5;
-_2f.columns=_2f.columns||5;
-_2f.duration=_2f.duration||1500;
-_2f.interval=_2f.interval||_2f.duration/(_2f.rows+_2f.columns*2);
-_2f.distance=_2f.distance||1.5;
-_2f.random=_2f.random||0;
-if(typeof _2f.fade=="undefined"){
-_2f.fade=true;
-}
-var _31=Math.abs(_2f.random),_32=_2f.duration-(_2f.rows+_2f.columns)*_2f.interval;
-_2f.pieceAnimation=function(_33,x,y,_34){
-var _35=Math.random()*(_2f.rows+_2f.columns)*_2f.interval,ps=_33.style,_36=(_2f.reverseOrder||_2f.distance<0)?((x+y)*_2f.interval):(((_2f.rows+_2f.columns)-(x+y))*_2f.interval),_37=_35*_31+Math.max(1-_31,0)*_36,_38={};
-if(_2f.unhide){
-_38.top={start:(parseInt(ps.top)-_34.h*_2f.distance),end:parseInt(ps.top)};
-if(_2f.fade){
-_38.opacity={start:"0",end:"1"};
-}
-}else{
-_38.top={end:(parseInt(ps.top)+_34.h*_2f.distance)};
-if(_2f.fade){
-_38.opacity={end:"0"};
-}
-}
-var _39=dojo.animateProperty({node:_33,duration:_32,delay:_37,easing:(_2f.easing||(_2f.unhide?dojo.fx.easing.sinIn:dojo.fx.easing.circIn)),properties:_38,beforeBegin:(_2f.unhide?function(){
-if(_2f.fade){
-dojo.style(_33,{opacity:"0"});
-}
-ps.top=_38.top.start+"px";
-}:undefined)});
-return _39;
-};
-var _3a=dojox.fx._split(_2f);
-if(_2f.unhide){
-dojo.connect(_3a,"onEnd",_3a,function(){
-dojo.style(_30,{opacity:"1"});
-});
-}else{
-dojo.connect(_3a,"onPlay",_3a,function(){
-dojo.style(_30,{opacity:"0"});
-});
-}
-return _3a;
-},build:function(_3b){
-_3b.unhide=true;
-return dojox.fx.disintegrate(_3b);
-},shear:function(_3c){
-var _3d=_3c.node=dojo.byId(_3c.node);
-_3c.rows=_3c.rows||6;
-_3c.columns=_3c.columns||6;
-_3c.duration=_3c.duration||1000;
-_3c.interval=_3c.interval||0;
-_3c.distance=_3c.distance||1;
-_3c.random=_3c.random||0;
-if(typeof (_3c.fade)=="undefined"){
-_3c.fade=true;
-}
-var _3e=Math.abs(_3c.random),_3f=(_3c.duration-(_3c.rows+_3c.columns)*Math.abs(_3c.interval));
-_3c.pieceAnimation=function(_40,x,y,_41){
-var _42=!(x%2),_43=!(y%2),_44=Math.random()*_3f,_45=(_3c.reverseOrder)?(((_3c.rows+_3c.columns)-(x+y))*_3c.interval):((x+y)*_3c.interval),_46=_44*_3e+Math.max(1-_3e,0)*_45,_47={},ps=_40.style;
-if(_3c.fade){
-_47.opacity=(_3c.unhide?{start:"0",end:"1"}:{end:"0"});
-}
-if(_3c.columns==1){
-_42=_43;
-}else{
-if(_3c.rows==1){
-_43=!_42;
-}
-}
-var _48=parseInt(ps.left),top=parseInt(ps.top),_49=_3c.distance*_41.w,_4a=_3c.distance*_41.h;
-if(_3c.unhide){
-if(_42==_43){
-_47.left=_42?{start:(_48-_49),end:_48}:{start:(_48+_49),end:_48};
-}else{
-_47.top=_42?{start:(top+_4a),end:top}:{start:(top-_4a),end:top};
-}
-}else{
-if(_42==_43){
-_47.left=_42?{end:(_48-_49)}:{end:(_48+_49)};
-}else{
-_47.top=_42?{end:(top+_4a)}:{end:(top-_4a)};
-}
-}
-var _4b=dojo.animateProperty({node:_40,duration:_3f,delay:_46,easing:(_3c.easing||dojo.fx.easing.sinInOut),properties:_47,beforeBegin:(_3c.unhide?function(){
-if(_3c.fade){
-ps.opacity="0";
-}
-if(_42==_43){
-ps.left=_47.left.start+"px";
-}else{
-ps.top=_47.top.start+"px";
-}
-}:undefined)});
-return _4b;
-};
-var _4c=dojox.fx._split(_3c);
-if(_3c.unhide){
-dojo.connect(_4c,"onEnd",_4c,function(){
-dojo.style(_3d,{opacity:"1"});
-});
-}else{
-dojo.connect(_4c,"onPlay",_4c,function(){
-dojo.style(_3d,{opacity:"0"});
-});
-}
-return _4c;
-},unShear:function(_4d){
-_4d.unhide=true;
-return dojox.fx.shear(_4d);
-},pinwheel:function(_4e){
-var _4f=_4e.node=dojo.byId(_4e.node);
-_4e.rows=_4e.rows||4;
-_4e.columns=_4e.columns||4;
-_4e.duration=_4e.duration||1000;
-_4e.interval=_4e.interval||0;
-_4e.distance=_4e.distance||1;
-_4e.random=_4e.random||0;
-if(typeof _4e.fade=="undefined"){
-_4e.fade=true;
-}
-var _50=(_4e.duration-(_4e.rows+_4e.columns)*Math.abs(_4e.interval));
-_4e.pieceAnimation=function(_51,x,y,_52){
-var _53=_52.h/_4e.rows,_54=_52.w/_4e.columns,_55=!(x%2),_56=!(y%2),_57=Math.random()*_50,_58=(_4e.interval<0)?(((_4e.rows+_4e.columns)-(x+y))*_4e.interval*-1):((x+y)*_4e.interval),_59=_57*_4e.random+Math.max(1-_4e.random,0)*_58,_5a={},ps=_51.style;
-if(_4e.fade){
-_5a.opacity=(_4e.unhide?{start:0,end:1}:{end:0});
-}
-if(_4e.columns==1){
-_55=!_56;
-}else{
-if(_4e.rows==1){
-_56=_55;
-}
-}
-var _5b=parseInt(ps.left),top=parseInt(ps.top);
-if(_55){
-if(_56){
-_5a.top=_4e.unhide?{start:top+_53*_4e.distance,end:top}:{start:top,end:top+_53*_4e.distance};
-}else{
-_5a.left=_4e.unhide?{start:_5b+_54*_4e.distance,end:_5b}:{start:_5b,end:_5b+_54*_4e.distance};
-}
-}
-if(_55!=_56){
-_5a.width=_4e.unhide?{start:_54*(1-_4e.distance),end:_54}:{start:_54,end:_54*(1-_4e.distance)};
-}else{
-_5a.height=_4e.unhide?{start:_53*(1-_4e.distance),end:_53}:{start:_53,end:_53*(1-_4e.distance)};
-}
-var _5c=dojo.animateProperty({node:_51,duration:_50,delay:_59,easing:(_4e.easing||dojo.fx.easing.sinInOut),properties:_5a,beforeBegin:(_4e.unhide?function(){
-if(_4e.fade){
-dojo.style(_51,"opacity",0);
-}
-if(_55){
-if(_56){
-ps.top=(top+_53*(1-_4e.distance))+"px";
-}else{
-ps.left=(_5b+_54*(1-_4e.distance))+"px";
-}
-}else{
-ps.left=_5b+"px";
-ps.top=top+"px";
-}
-if(_55!=_56){
-ps.width=(_54*(1-_4e.distance))+"px";
-}else{
-ps.height=(_53*(1-_4e.distance))+"px";
-}
-}:undefined)});
-return _5c;
-};
-var _5d=dojox.fx._split(_4e);
-if(_4e.unhide){
-dojo.connect(_5d,"onEnd",_5d,function(){
-dojo.style(_4f,{opacity:"1"});
-});
-}else{
-dojo.connect(_5d,"play",_5d,function(){
-dojo.style(_4f,{opacity:"0"});
-});
-}
-return _5d;
-},unPinwheel:function(_5e){
-_5e.unhide=true;
-return dojox.fx.pinwheel(_5e);
-},blockFadeOut:function(_5f){
-var _60=_5f.node=dojo.byId(_5f.node);
-_5f.rows=_5f.rows||5;
-_5f.columns=_5f.columns||5;
-_5f.duration=_5f.duration||1000;
-_5f.interval=_5f.interval||_5f.duration/(_5f.rows+_5f.columns*2);
-_5f.random=_5f.random||0;
-var _61=Math.abs(_5f.random),_62=_5f.duration-(_5f.rows+_5f.columns)*_5f.interval;
-_5f.pieceAnimation=function(_63,x,y,_64){
-var _65=Math.random()*_5f.duration,_66=(_5f.reverseOrder)?(((_5f.rows+_5f.columns)-(x+y))*Math.abs(_5f.interval)):((x+y)*_5f.interval),_67=_65*_61+Math.max(1-_61,0)*_66,_68=dojo.animateProperty({node:_63,duration:_62,delay:_67,easing:(_5f.easing||dojo.fx.easing.sinInOut),properties:{opacity:(_5f.unhide?{start:"0",end:"1"}:{start:"1",end:"0"})},beforeBegin:(_5f.unhide?function(){
-dojo.style(_63,{opacity:"0"});
-}:function(){
-_63.style.filter="";
-})});
-return _68;
-};
-var _69=dojox.fx._split(_5f);
-if(_5f.unhide){
-dojo.connect(_69,"onEnd",_69,function(){
-dojo.style(_60,{opacity:"1"});
-});
-}else{
-dojo.connect(_69,"onPlay",_69,function(){
-dojo.style(_60,{opacity:"0"});
-});
-}
-return _69;
-},blockFadeIn:function(_6a){
-_6a.unhide=true;
-return dojox.fx.blockFadeOut(_6a);
-}});
-}
+
+dojo.mixin(dojox.fx,{
+	_split: function(/*Object*/ args){
+		// summary: Split a node into rectangular pieces and animate them.
+		//
+		// description:
+		//		Returns an animation that will split the node into a grid
+		//		of pieces that move independently.
+		//
+		//	args:
+		//		args.crop: Boolean - If true, pieces will only be visible inside node's boundries
+		//		args.rows: Integer - The number of horizontal pieces (default is 3)
+		//		args.columns: Integer - The number of vertical pieces (default is 3)
+		//		args.pieceAnimation: Function(piece, x, y, coords) - Returns either the dojo.Animation
+		//		or an array of dojo.Animation objects for the piece at location (x, y) in the node's grid;
+		//		coords is the result of dojo.coords(args.node, true);
+
+		args.rows = args.rows || 3;
+		args.columns = args.columns || 3;
+		args.duration = args.duration || 1000;
+
+		var node = args.node = dojo.byId(args.node),
+			parentNode = node.parentNode,
+			pNode = parentNode,
+			body = dojo.body(),
+			_pos = "position"
+		;
+
+		while(pNode && pNode != body && dojo.style(pNode, _pos) == "static"){
+			pNode = pNode.parentNode;
+		}
+
+		var pCoords = pNode != body ? dojo.position(pNode, true) : { x: 0, y: 0 },
+			coords = dojo.position(node, true),
+			nodeHeight = dojo.style(node, "height"),
+			nodeWidth = dojo.style(node, "width"),
+			hBorder = dojo.style(node, "borderLeftWidth") + dojo.style(node, "borderRightWidth"),
+			vBorder = dojo.style(node, "borderTopWidth") + dojo.style(node, "borderBottomWidth"),
+			pieceHeight = Math.ceil(nodeHeight / args.rows),
+			pieceWidth = Math.ceil(nodeWidth / args.columns),
+			container = dojo.create(node.tagName, {
+				style: {
+					position: "absolute",
+					padding: 0,
+					margin: 0,
+					border:"none",
+					top: coords.y - pCoords.y + "px",
+					left: coords.x - pCoords.x + "px",
+					height: nodeHeight + vBorder + "px",
+					width: nodeWidth + hBorder + "px",
+					background: "none",
+					overflow: args.crop ? "hidden" : "visible",
+					zIndex: dojo.style(node, "zIndex")
+				}
+			}, node, "after"),
+			animations = [],
+			pieceHelper = dojo.create(node.tagName, {
+				style: {
+					position: "absolute",
+					border: "none",
+					padding: 0,
+					margin: 0,
+					height: pieceHeight + hBorder + "px",
+					width: pieceWidth + vBorder + "px",
+					overflow: "hidden"
+				}
+			});
+
+		// Create the pieces and their animations
+		for(var y = 0, ly = args.rows; y < ly; y++){
+			for(var x = 0, lx = args.columns; x < lx; x++){
+				// Create the piece
+				var piece = dojo.clone(pieceHelper),
+					pieceContents = dojo.clone(node),
+					pTop = y * pieceHeight,
+					pLeft = x * pieceWidth
+				;
+
+				// IE hack
+				pieceContents.style.filter = "";
+
+				// removing the id attribute from the cloned nodes
+				dojo.removeAttr(pieceContents, "id");
+
+				dojo.style(piece, {
+					border: "none",
+					overflow: "hidden",
+					top: pTop + "px",
+					left: pLeft + "px"
+				});
+				dojo.style(pieceContents, {
+					position: "static",
+					opacity: "1",
+					marginTop: -pTop + "px",
+					marginLeft: -pLeft + "px"
+				});
+				piece.appendChild(pieceContents);
+				container.appendChild(piece);
+
+				var pieceAnimation = args.pieceAnimation(piece, x, y, coords);
+				if(dojo.isArray(pieceAnimation)){
+					// if pieceAnimation is an array, append its elements
+					animations = animations.concat(pieceAnimation);
+				}else{
+					// otherwise, append it
+					animations.push(pieceAnimation);
+				}
+			}
+		}
+		var anim = dojo.fx.combine(animations);
+		dojo.connect(anim, "onEnd", anim, function(){
+			container.parentNode.removeChild(container);
+		});
+		if(args.onPlay){
+			dojo.connect(anim, "onPlay", anim, args.onPlay);
+		}
+		if(args.onEnd){
+			dojo.connect(anim, "onEnd", anim, args.onEnd);
+		}
+		return anim; // dojo.Animation
+	},
+
+	explode: function(/*Object*/ args){
+		// summary: Explode a node into rectangular pieces
+		//
+		// description:
+		//		Returns an animation that will split the node into a grid
+		//		of pieces that fly away from the center.
+		//
+		//	args:
+		//		args.rows: Integer - The number of horizontal pieces (default is 3)
+		//		args.columns: Integer - The number of vertical pieces (default is 3)
+		//		args.random: Float - If set, pieces fly to random distances, for random durations,
+		//							   and in slightly random directions.  The value defines how much
+		//							   randomness is introduced.
+		//		args.distance: Float - Multiplier for the distance the pieces fly (even when random)
+		//		args.fade: Boolean - If true, pieces fade out while in motion (default is true)
+		//		args.fadeEasing: Function - If args.fade is true, the fade animations use this easing function
+		//		args.unhide: Boolean - If true, the animation is reversed
+		//		args.sync: Boolean - If args.unhide is true, all the pieces converge at the same time
+		//							 (default is true)
+
+		var node = args.node = dojo.byId(args.node);
+		args.rows = args.rows || 3;
+		args.columns = args.columns || 3;
+		args.distance = args.distance || 1;
+		args.duration = args.duration || 1000;
+		args.random = args.random || 0;
+		if(!args.fade){
+			args.fade = true;
+		}
+		if(typeof args.sync == "undefined"){
+			args.sync = true;
+		}
+		args.random = Math.abs(args.random);
+
+		// Returns the animation object for each piece
+		args.pieceAnimation = function(piece, x, y, coords){
+			var pieceHeight = coords.h / args.rows,
+				pieceWidth = coords.w / args.columns,
+				distance = args.distance * 2,
+				duration = args.duration,
+				ps = piece.style,
+				startTop = parseInt(ps.top),
+				startLeft = parseInt(ps.left),
+				delay = 0,
+				randomX = 0,
+				randomY = 0;
+
+			if(args.random){
+				var seed = (Math.random() * args.random) + Math.max(1 - args.random, 0);
+				distance *= seed;
+				duration *= seed;
+				// To syncronize, give each piece an appropriate delay so they end together
+				delay = ((args.unhide && args.sync) || (!args.unhide && !args.sync)) ? (args.duration - duration) : 0;
+				// Slightly randomize the direction of each piece
+				randomX = Math.random() - 0.5;
+				randomY = Math.random() - 0.5;
+			}
+
+			var distanceY = ((coords.h - pieceHeight) / 2 - pieceHeight * y),
+				distanceX = ((coords.w - pieceWidth) / 2 - pieceWidth * x),
+				distanceXY = Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2)),
+				endTop = parseInt(startTop - distanceY * distance + distanceXY * randomY),
+				endLeft = parseInt(startLeft - distanceX * distance + distanceXY * randomX)
+			;
+
+			// Create the animation objects for the piece
+			// These are separate anim objects so they can have different curves
+			var pieceSlide = dojo.animateProperty({
+				node: piece,
+				duration: duration,
+				delay: delay,
+				easing: (args.easing || (args.unhide ? dojo.fx.easing.sinOut : dojo.fx.easing.circOut)),
+				beforeBegin: (args.unhide ? function(){
+						if(args.fade){
+							dojo.style(piece, { opacity: "0"});
+						}
+						ps.top = endTop + "px";
+						ps.left = endLeft + "px";
+					} : undefined),
+				properties: {
+					top: (args.unhide ? { start: endTop, end: startTop } : { start: startTop, end: endTop }),
+					left: (args.unhide ? { start: endLeft, end: startLeft } : { start: startLeft, end: endLeft })
+				}
+			});
+			if(args.fade){
+				var pieceFade = dojo.animateProperty({
+					node: piece,
+					duration: duration,
+					delay: delay,
+					easing: (args.fadeEasing || dojo.fx.easing.quadOut),
+					properties: {
+						opacity: (args.unhide ? { start: "0", end: "1" } : { start: "1", end: "0" })
+					}
+				});
+
+				// return both animations as an array
+				return (args.unhide ? [pieceFade, pieceSlide] : [pieceSlide, pieceFade]);
+			}else{
+				// Otherwise return only the slide animation
+				return pieceSlide;
+			}
+		};
+
+		var anim = dojox.fx._split(args);
+		if(args.unhide){
+			dojo.connect(anim, "onEnd", null, function(){
+				dojo.style(node, {opacity: "1" });
+			});
+		}else{
+			dojo.connect(anim, "onPlay", null, function(){
+				dojo.style(node, { opacity: "0" });
+			});
+		}
+		return anim; // dojo.Animation
+	},
+
+	converge: function(/*Object*/ args){
+		args.unhide = true;
+		return dojox.fx.explode(args);
+	},
+
+	disintegrate: function(/*Object*/ args){
+		// summary: Split a node into rectangular pieces and let them fall
+		//
+		// description:
+		//		Returns an animation that will split the node into a grid
+		//		of pieces that drop.
+		//
+		//	args:
+		//		args.rows: Integer - The number of horizontal pieces (default is 5)
+		//		args.columns: Integer - The number of vertical pieces (default is 5)
+		//		args.interval: Float - The number of milliseconds between each piece's animation
+		//		args.distance: Float - The number of the node's heights to drop (default is 1.5)
+		//		args.fade: Boolean - If true, pieces fade out while in motion (default is true)
+		//		args.random: Float - If set, pieces fall in random order. The value defines how much
+		//							   randomness is introduced.
+		//		args.reverseOrder: Boolean - If true, pieces animate in reversed order
+		//		args.unhide: Boolean - If true, the peices fall from above and land in place
+		var node = args.node = dojo.byId(args.node);
+
+		args.rows = args.rows || 5;
+		args.columns = args.columns || 5;
+		args.duration = args.duration || 1500;
+		args.interval = args.interval || args.duration / (args.rows + args.columns * 2);
+		args.distance = args.distance || 1.5;
+		args.random = args.random || 0;
+		if(typeof args.fade == "undefined"){
+			args.fade = true;
+		}
+
+		var random = Math.abs(args.random),
+			duration = args.duration - (args.rows + args.columns) * args.interval;
+
+		// Returns the animation object for each piece
+		args.pieceAnimation = function(piece, x, y, coords){
+
+			var randomDelay = Math.random() * (args.rows + args.columns) * args.interval,
+				ps = piece.style,
+
+			// If distance is negative, start from the top right instead of bottom left
+				uniformDelay = (args.reverseOrder || args.distance < 0) ?
+					((x + y) * args.interval) :
+					(((args.rows + args.columns) - (x + y)) * args.interval),
+				delay = randomDelay * random + Math.max(1 - random, 0) * uniformDelay,
+			// Create the animation object for the piece
+				properties = {}
+			;
+			if(args.unhide){
+				properties.top = {
+					start: (parseInt(ps.top) - coords.h * args.distance),
+					end: parseInt(ps.top)
+				};
+				if(args.fade){
+					properties.opacity = {start: "0", end: "1"};
+				}
+			}else{
+				properties.top = {end: (parseInt(ps.top) + coords.h * args.distance)};
+				if(args.fade){
+					properties.opacity = {end: "0"};
+				}
+			}
+			var pieceAnimation = dojo.animateProperty({
+				node: piece,
+				duration: duration,
+				delay: delay,
+				easing: (args.easing || (args.unhide ? dojo.fx.easing.sinIn : dojo.fx.easing.circIn)),
+				properties: properties,
+				beforeBegin: (args.unhide ? function(){
+					if(args.fade){
+						dojo.style(piece, { opacity: "0" });
+					}
+					ps.top = properties.top.start + "px";
+				} : undefined)
+			});
+
+			return pieceAnimation;
+		};
+
+		var anim = dojox.fx._split(args);
+		if(args.unhide){
+			dojo.connect(anim, "onEnd", anim, function(){
+				dojo.style(node, { opacity: "1" });
+			});
+		}else{
+			dojo.connect(anim, "onPlay", anim, function(){
+				dojo.style(node, { opacity: "0" });
+			});
+		}
+		return anim; // dojo.Animation
+	},
+
+	build: function(/*Object*/ args){
+		args.unhide = true;
+		return dojox.fx.disintegrate(args);
+	},
+
+	shear: function(/*Object*/ args){
+		// summary: Split a node into rectangular pieces and slide them in alternating directions
+		//
+		// description:
+		//		Returns an animation that will split the node into a grid
+		//		of pieces that slide in alternating directions.
+		//
+		//	args:
+		//		args.rows: Integer - The number of horizontal pieces (default is 6)
+		//		args.columns: Integer - The number of vertical pieces (default is 6)
+		//		args.interval: Float - The number of milliseconds between each piece's animation (default is 0)
+		//		args.distance: Float - The multiple of the node's dimensions to slide (default is 1)
+		//		args.fade: Boolean - If true, pieces fade out while in motion (default is true)
+		//		args.random: Float - If true, pieces have a random delay. The value defines how much
+		//							   randomness is introduced
+		//		args.reverseOrder: Boolean - If true, pieces animate in reversed order
+		//		args.unhide: Boolean - If true, the animation is reversed
+
+		var node = args.node = dojo.byId(args.node);
+
+		args.rows = args.rows || 6;
+		args.columns = args.columns || 6;
+		args.duration = args.duration || 1000;
+		args.interval = args.interval || 0;
+		args.distance = args.distance || 1;
+		args.random = args.random || 0;
+		if(typeof(args.fade) == "undefined"){
+			args.fade = true;
+		}
+		var random = Math.abs(args.random),
+			duration = (args.duration - (args.rows + args.columns) * Math.abs(args.interval))
+		;
+
+		// Returns the animation object for each piece
+		args.pieceAnimation = function(piece, x, y, coords){
+
+			// Since x an y start at 0, the opposite is true...
+			var colIsOdd = !(x % 2),
+				rowIsOdd = !(y % 2),
+				randomDelay = Math.random() * duration,
+				uniformDelay = (args.reverseOrder) ?
+					(((args.rows + args.columns) - (x + y)) * args.interval) :
+					((x + y) * args.interval),
+				delay = randomDelay * random + Math.max(1 - random, 0) * uniformDelay,
+				properties = {},
+				ps = piece.style
+			;
+
+			if(args.fade){
+				properties.opacity = (args.unhide ? { start: "0", end: "1" } : { end: "0" });
+			}
+
+			// If we have only rows or columns, ignore the other dimension
+			if(args.columns == 1){
+				colIsOdd = rowIsOdd;
+			}else if(args.rows == 1){
+				rowIsOdd = !colIsOdd;
+			}
+
+			// Determine the piece's direction
+			var left = parseInt(ps.left),
+				top = parseInt(ps.top),
+				distanceX = args.distance*coords.w,
+				distanceY = args.distance*coords.h
+			;
+			if(args.unhide){
+				if(colIsOdd == rowIsOdd){
+					properties.left = colIsOdd ? {start: (left - distanceX), end: left} : {start: (left + distanceX), end: left};
+				}else{
+					properties.top = colIsOdd ? {start: (top + distanceY), end: top} : {start: (top - distanceY), end: top};
+				}
+			}else{
+				if(colIsOdd == rowIsOdd){
+					properties.left = colIsOdd ? {end: (left - distanceX)} : {end: (left + distanceX)};
+				}else{
+					properties.top = colIsOdd ? {end: (top + distanceY)} : {end: (top - distanceY)};
+				}
+			}
+
+			// Create the animation object for the piece
+			var pieceAnimation = dojo.animateProperty({
+				node: piece,
+				duration: duration,
+				delay: delay,
+				easing: (args.easing || dojo.fx.easing.sinInOut),
+				properties: properties,
+				beforeBegin: (args.unhide ? function(){
+					if(args.fade){
+						ps.opacity = "0";
+					}
+					if(colIsOdd == rowIsOdd){
+						ps.left = properties.left.start + "px";
+					}else{
+						ps.top = properties.top.start + "px";
+					}
+				} : undefined)
+			});
+
+			return pieceAnimation;
+		};
+
+		var anim = dojox.fx._split(args);
+		if(args.unhide){
+			dojo.connect(anim, "onEnd", anim, function(){
+				dojo.style(node, { opacity: "1" });
+			});
+		}else{
+			dojo.connect(anim, "onPlay", anim, function(){
+				dojo.style(node, { opacity: "0" });
+			});
+		}
+		return anim; // dojo.Animation
+	},
+
+	unShear: function(/*Object*/ args){
+		args.unhide = true;
+		return dojox.fx.shear(args);
+	},
+
+	pinwheel: function(/*Object*/ args){
+		// summary: Split a node into rectangular pieces and wipe them in alternating directions
+		//
+		// description:
+		//		Returns an animation that will split the node into a grid
+		//		of pieces that wipe in alternating directions.
+		//
+		//	args:
+		//		args.rows: Integer - The number of horizontal pieces (default is 4)
+		//		args.columns: Integer - The number of vertical pieces (default is 4)
+		//		args.interval: Float - The number of milliseconds between each piece's animation (default is 0)
+		//		args.distance: Float - The percentage of the piece's dimensions the piece should wipe
+		//		args.fade: Boolean - If true, pieces fade out while in motion (default is true)
+		//		args.random: Float - If true, pieces have a random delay. The value defines how much
+		//							   randomness is introduced.
+		//		args.unhide: Boolean - If true, the animation is reversed
+
+		var node = args.node = dojo.byId(args.node);
+
+		args.rows = args.rows || 4;
+		args.columns = args.columns || 4;
+		args.duration = args.duration || 1000;
+		args.interval = args.interval || 0;
+		args.distance = args.distance || 1;
+		args.random = args.random || 0;
+		if(typeof args.fade == "undefined"){
+			args.fade = true;
+		}
+		var duration = (args.duration - (args.rows + args.columns) * Math.abs(args.interval));
+
+		// Returns the animation object for each piece
+		args.pieceAnimation = function(piece, x, y, coords){
+			var pieceHeight = coords.h / args.rows,
+				pieceWidth = coords.w / args.columns,
+
+				// because x an y start at 0, the opposite is true...
+				colIsOdd = !(x % 2),
+				rowIsOdd = !(y % 2),
+
+				randomDelay = Math.random() * duration,
+				uniformDelay = (args.interval < 0) ?
+					(((args.rows + args.columns) - (x + y)) * args.interval * -1) :
+					((x + y) * args.interval),
+				delay = randomDelay * args.random + Math.max(1 - args.random, 0) * uniformDelay,
+				properties = {},
+				ps = piece.style
+			;
+
+			if(args.fade){
+				properties.opacity = (args.unhide ? {start: 0, end: 1} : {end:0});
+			}
+
+			// If we have only rows or columns, ignore the other dimension
+			if(args.columns == 1){
+				colIsOdd = !rowIsOdd;
+			}else if(args.rows == 1){
+				rowIsOdd = colIsOdd;
+			}
+
+			// Determine the piece's direction
+			var left = parseInt(ps.left),
+				top = parseInt(ps.top)
+			;
+			if(colIsOdd){
+				if(rowIsOdd){
+					properties.top = args.unhide ?
+						{ start: top + pieceHeight * args.distance, end: top} :
+						{ start: top, end: top + pieceHeight * args.distance} ;
+				}else{
+					properties.left = args.unhide ?
+						{ start: left + pieceWidth * args.distance, end: left } :
+						{ start: left, end: left + pieceWidth * args.distance } ;
+				}
+			}
+			if(colIsOdd != rowIsOdd){
+				properties.width = args.unhide ?
+					{ start: pieceWidth * (1 - args.distance), end: pieceWidth } :
+					{ start: pieceWidth, end: pieceWidth * (1 - args.distance) } ;
+			}else{
+				properties.height = args.unhide ?
+					{ start: pieceHeight * (1 - args.distance), end: pieceHeight } :
+					{ start: pieceHeight, end: pieceHeight * (1 - args.distance) } ;
+			}
+
+			// Create the animation object for the piece
+			var pieceAnimation = dojo.animateProperty({
+				node: piece,
+				duration: duration,
+				delay: delay,
+				easing: (args.easing || dojo.fx.easing.sinInOut),
+				properties: properties,
+				beforeBegin: (args.unhide ? function(){
+					if(args.fade){
+						dojo.style(piece, "opacity", 0);
+					}
+					if(colIsOdd){
+						if(rowIsOdd){
+							ps.top = (top + pieceHeight * (1 - args.distance)) + "px";
+						}else{
+							ps.left = (left + pieceWidth * (1 - args.distance)) + "px";
+						}
+					}else{
+						ps.left = left + "px";
+						ps.top = top + "px";
+					}
+					if(colIsOdd != rowIsOdd){
+						ps.width = (pieceWidth * (1 - args.distance)) + "px";
+					}else{
+						ps.height = (pieceHeight * (1 - args.distance)) + "px";
+					}
+				} : undefined)
+			});
+
+			return pieceAnimation;
+		};
+
+		var anim = dojox.fx._split(args);
+		if(args.unhide){
+			dojo.connect(anim, "onEnd", anim, function(){
+				dojo.style(node, { opacity: "1" });
+			});
+		}else{
+			dojo.connect(anim, "play", anim, function(){
+				dojo.style(node, { opacity: "0" });
+			});
+		}
+		return anim; // dojo.Animation
+	},
+
+	unPinwheel: function(/*Object*/ args){
+		args.unhide = true;
+		return dojox.fx.pinwheel(args); // dojo.Animation
+	},
+
+	blockFadeOut: function(/*Object*/ args){
+		// summary: Split a node into rectangular pieces and fade them
+		//
+		// description:
+		//		Returns an animation that will split the node into a grid
+		//		of pieces that fade in or out.
+		//
+		//	args:
+		//		args.rows: Integer - The number of horizontal pieces (default is 5)
+		//		args.columns: Integer - The number of vertical pieces (default is 5)
+		//		args.interval: Float - The number of milliseconds between each piece's animation (default is 0)
+		//		args.random: Float - If true, pieces have a random delay. The value defines how much
+		//							   randomness is introduced
+		//		args.reverseOrder: Boolean - If true, pieces animate in reversed order
+		//		args.unhide: Boolean - If true, the animation is reversed
+
+		var node = args.node = dojo.byId(args.node);
+
+		args.rows = args.rows || 5;
+		args.columns = args.columns || 5;
+		args.duration = args.duration || 1000;
+		args.interval = args.interval || args.duration / (args.rows + args.columns * 2);
+		args.random = args.random || 0;
+		var random = Math.abs(args.random),
+			duration = args.duration - (args.rows + args.columns) * args.interval
+		;
+
+		// Returns the animation object for each piece
+		args.pieceAnimation = function(piece, x, y, coords){
+			var randomDelay = Math.random() * args.duration,
+				uniformDelay = (args.reverseOrder) ?
+					(((args.rows + args.columns) - (x + y)) * Math.abs(args.interval)) :
+					((x + y) * args.interval),
+				delay = randomDelay * random + Math.max(1 - random, 0) * uniformDelay,
+			// Create the animation object for the piece
+				pieceAnimation = dojo.animateProperty({
+					node: piece,
+					duration: duration,
+					delay: delay,
+					easing: (args.easing || dojo.fx.easing.sinInOut),
+					properties: {
+						opacity: (args.unhide ? {start: "0", end: "1"} : {start: "1", end: "0"})
+					},
+					beforeBegin: (args.unhide ? function(){ dojo.style(piece, { opacity: "0" });} : function(){ piece.style.filter = ""; })
+				});
+
+			return pieceAnimation;
+		};
+		var anim = dojox.fx._split(args);
+		if(args.unhide){
+			dojo.connect(anim, "onEnd", anim, function(){
+				dojo.style(node, { opacity: "1" });
+			});
+		}else{
+			dojo.connect(anim, "onPlay", anim, function(){
+				dojo.style(node, { opacity: "0" });
+			});
+		}
+		return anim; // dojo.Animation
+	},
+
+	blockFadeIn: function(/*Object*/ args){
+		args.unhide = true;
+		return dojox.fx.blockFadeOut(args); // dojo.Animation
+	}
+
+});
\ No newline at end of file
diff --git a/dojox/fx/style.js b/dojox/fx/style.js
index 577d49a..0f6ca3d 100644
--- a/dojox/fx/style.js
+++ b/dojox/fx/style.js
@@ -1,69 +1,239 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.fx.style"]){
-dojo._hasResource["dojox.fx.style"]=true;
 dojo.provide("dojox.fx.style");
-dojo.experimental("dojox.fx.style");
-dojo.require("dojo.fx");
+dojo.experimental("dojox.fx.style"); 
+//
+// summary: 
+//		dojox.fx CSS Class Animations: 
+//
+// description: 
+//		a set of functions to animate properties based on
+//		normalized CSS class definitions.
+//
+//	provides: addClass, removeClass, and toggleClass
+//	
+dojo.require("dojo.fx"); 
+
 (function(){
-var d=dojo;
-var _1=function(_2){
-return d.map(dojox.fx._allowedProperties,function(_3){
-return _2[_3];
-});
-};
-var _4=function(_5,_6,_7){
-_5=d.byId(_5);
-var cs=d.getComputedStyle(_5);
-var _8=_1(cs);
-d[(_7?"addClass":"removeClass")](_5,_6);
-var _9=_1(cs);
-d[(_7?"removeClass":"addClass")](_5,_6);
-var _a={},i=0;
-d.forEach(dojox.fx._allowedProperties,function(_b){
-if(_8[i]!=_9[i]){
-_a[_b]=parseInt(_9[i]);
-}
-i++;
-});
-return _a;
-};
-d.mixin(dojox.fx,{addClass:function(_c,_d,_e){
-_c=d.byId(_c);
-var _f=(function(n){
-return function(){
-d.addClass(n,_d);
-n.style.cssText=_10;
-};
-})(_c);
-var _11=_4(_c,_d,true);
-var _10=_c.style.cssText;
-var _12=d.animateProperty(d.mixin({node:_c,properties:_11},_e));
-d.connect(_12,"onEnd",_12,_f);
-return _12;
-},removeClass:function(_13,_14,_15){
-_13=d.byId(_13);
-var _16=(function(n){
-return function(){
-d.removeClass(n,_14);
-n.style.cssText=_17;
-};
-})(_13);
-var _18=_4(_13,_14);
-var _17=_13.style.cssText;
-var _19=d.animateProperty(d.mixin({node:_13,properties:_18},_15));
-d.connect(_19,"onEnd",_19,_16);
-return _19;
-},toggleClass:function(_1a,_1b,_1c,_1d){
-if(typeof _1c=="undefined"){
-_1c=!d.hasClass(_1a,_1b);
-}
-return dojox.fx[(_1c?"addClass":"removeClass")](_1a,_1b,_1d);
-},_allowedProperties:["width","height","left","top","backgroundColor","color","borderBottomWidth","borderTopWidth","borderLeftWidth","borderRightWidth","paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginTop","marginRight","marginBottom","lineHeight","letterSpacing","fontSize"]});
+		
+	var d = dojo;
+
+	var _getStyleSnapshot = function(/* Object */cache){
+		// summary: 
+		//		uses a dojo.getComputedStyle(node) cache reference and
+		// 		iterates through the 'documented/supported animate-able'
+		// 		properties. 
+		//
+		// returns:  Array
+		//		an array of raw, calculcated values (no keys), to be normalized/compared
+		//		elsewhere	
+		return d.map(dojox.fx._allowedProperties, function(style){
+			return cache[style]; // String
+		}); // Array
+	};
+
+	var _getCalculatedStyleChanges = function(node, cssClass, addClass){
+		// summary: Calculate the difference in style properties between two states
+		// description:
+		//	calculate and normalize(?) the differences between two states
+		//	of a node (args.node) by quickly adding or removing a class, and
+		//	iterateing over the results of dojox.fx._getStyleSnapshot()
+		//
+		// addClass: 
+		// 	true to calculate what adding a class would do, 
+		// 	false to calculate what removing the class would do
+
+		node = d.byId(node);
+		var	cs = d.getComputedStyle(node);
+
+		// take our snapShots
+		var _before = _getStyleSnapshot(cs);
+		d[(addClass ? "addClass" : "removeClass")](node, cssClass); 
+		var _after = _getStyleSnapshot(cs);
+		d[(addClass ? "removeClass" : "addClass")](node, cssClass); 
+
+		var calculated = {}, i = 0;
+		d.forEach(dojox.fx._allowedProperties, function(prop){
+			if(_before[i] != _after[i]){
+				// FIXME: the static units: px is not good, either. need to parse unit from computed style?
+				calculated[prop] = parseInt(_after[i]) /* start: parseInt(_before[i]), units: 'px' */ ; 
+			} 
+			i++;
+		});
+		return calculated; 
+	};
+
+	d.mixin(dojox.fx,{
+
+		addClass: function(node, cssClass, args){
+			// summary: 
+			//		Animate the effects of adding a class to a node
+			//
+			// description:
+			//		Creates an animation that will animate
+			//		the properties of a node to the properties
+			//		defined in a standard CSS .class definition.
+			//		(calculating the differences itself)
+			//
+			// node: String|DomNode
+			//		A String ID or DomNode referce to animate
+			//
+			// cssClass: String
+			//		The CSS class name to add to the node
+			//
+			// args: Object?
+			//		Additional optional `dojo.animateProperty` arguments, such as 
+			//		duration, easing and so on.
+			//	
+			// example:
+			//	| 
+			//	|	.bar { line-height: 12px; }
+			//	|	.foo { line-height: 40px; }
+			//	|	<div class="bar" id="test">
+			//	|	Multi<br>line<br>text
+			//	|	</div> 
+			//	|
+			//	|	// animate to line-height:40px
+			//	|	dojo.fx.addClass("test", "foo").play();
+			// 
+			node = d.byId(node); 
+
+			var pushClass = (function(n){
+				// summary: onEnd we want to add the class to the node 
+				//	(as dojo.addClass naturally would) in case our 
+				//	class parsing misses anything the browser would 
+				// 	otherwise interpret. this may cause some flicker,
+				//	and will only apply the class so children can inherit 
+				//	after the animation is done (potentially more flicker)
+				return function(){
+					d.addClass(n, cssClass); 
+					n.style.cssText = _beforeStyle; 
+				}
+			})(node);
+
+			// _getCalculatedStleChanges is the core of our style/class animations
+			var mixedProperties = _getCalculatedStyleChanges(node, cssClass, true);
+			var _beforeStyle = node.style.cssText; 
+			var _anim = d.animateProperty(d.mixin({
+				node: node,
+				properties: mixedProperties
+			}, args));
+			d.connect(_anim, "onEnd", _anim, pushClass); 
+			return _anim; // dojo.Animation
+		},
+	
+		removeClass: function(node, cssClass, args){
+			// summary: Animate the effects of removing a class from a node
+			// description:
+			//	Creates an animation that will animate the properties of a 
+			// 	node (args.node) to the properties calculated after removing 
+			//	a standard CSS className from a that node.
+			//	
+			//	calls dojo.removeClass(args.cssClass) onEnd of animation		
+			//
+			//	standard dojo.Animation object rules apply. 
+			//
+			// example:
+			// |	// animate the removal of "foo" from a node with id="bar"
+			// |	dojox.fx.removeClass("bar", "foo").play()
+
+			node = d.byId(node); 
+
+			var pullClass = (function(n){
+				// summary: onEnd we want to remove the class from the node 
+				//	(as dojo.removeClass naturally would) in case our class
+				//	parsing misses anything the browser would otherwise 
+				//	interpret. this may cause some flicker, and will only 
+				//	apply the class so children can inherit after the
+				//	animation is done (potentially more flicker)
+				//
+				return function(){
+					d.removeClass(n, cssClass); 
+					n.style.cssText = _beforeStyle; 
+				}
+			})(node);
+
+			var mixedProperties = _getCalculatedStyleChanges(node, cssClass);
+			var _beforeStyle = node.style.cssText; 
+			var _anim = d.animateProperty(d.mixin({
+				node: node,
+				properties: mixedProperties
+			}, args));
+			d.connect(_anim, "onEnd", _anim, pullClass); 
+			return _anim; // dojo.Animation
+		},
+
+		toggleClass: function(node, cssClass, condition, args){
+			// summary:
+			//		Animate the effects of Toggling a class on a Node
+			//
+			// description:
+			//		creates an animation that will animate the effect of 
+			//		toggling a class on or off of a node.
+			//		Adds a class to node if not present, or removes if present.
+			//		Pass a boolean condition if you want to explicitly add or remove.
+			//
+			// node: String|DomNode
+			//		The domNode (or string of the id) to toggle
+			// cssClass: String
+			//		String of the classname to add to the node	
+			// condition: Boolean?
+			//		If passed, true means to add the class, false means to remove.
+			// args: Object?
+			//		Additional `dojo.Animation` args to pass along.
+			//
+			// example:
+			// |	// add the class "sampleClass" to a node id="theNode"
+			// |	dojox.fx.toggleClass("theNode","sampleClass",true).play();
+			// example:
+			// |	// toggle the class "sampleClass" on the node id="theNode"
+			// |	dojox.fx.toggleClass("theNode","sampleClass").play();
+
+			if(typeof condition == "undefined"){
+				condition = !d.hasClass(node, cssClass);
+			}
+			return dojox.fx[(condition ? "addClass" : "removeClass")](node, cssClass, args); // dojo.Animation
+		},
+	
+		_allowedProperties: [
+			// summary: Our pseudo map of properties we will check for.
+			// description:
+			//	it should be much more intuitive. a way to normalize and
+			//	"predict" intent, or even something more clever ... 
+			//	open to suggestions.
+
+			// no-brainers:
+			"width",
+			"height",
+			// only if position = absolute || relative?
+			"left", "top", // "right", "bottom", 
+			// these need to be filtered through dojo.colors?
+			// "background", // normalize to:
+			/* "backgroundImage", */
+			// "backgroundPosition", // FIXME: to be effective, this needs "#px #px"?
+			"backgroundColor",
+
+			"color",
+
+			// "border", 
+			//"borderBottomColor",
+			"borderBottomWidth",
+			//"borderTopColor",
+			"borderTopWidth",
+			//"borderLeftColor",
+			"borderLeftWidth",
+			//"borderRightColor",
+			"borderRightWidth",
+
+			// "padding", // normalize to: 
+			"paddingLeft", "paddingRight", "paddingTop", "paddingBottom",
+			// "margin", // normalize to:
+			"marginLeft", "marginTop", "marginRight", "marginBottom",
+
+			// unit import/delicate?:
+			"lineHeight",
+			"letterSpacing",
+			"fontSize"
+		]
+	
+	});
+
 })();
-}
diff --git a/dojox/fx/tests/_animation.css b/dojox/fx/tests/_animation.css
new file mode 100644
index 0000000..7819142
--- /dev/null
+++ b/dojox/fx/tests/_animation.css
@@ -0,0 +1,113 @@
+.testBox {
+        border:1px solid #333;
+        width:75px;
+        height:75px;
+}
+.absolutely { position:absolute;
+        top:0; left:0;
+}
+.floating {
+        float:left;
+}
+.wide {
+        width:200px;
+}
+.tall {
+        height:200px;
+}
+.tiny {
+        width:3px;
+        height:3px;
+}
+
+
+.black {
+        color:#fff;
+        background-color:#000;        
+}
+
+.white {
+        color:#666;
+        background-color:#fff;        
+}
+
+.green {
+        color:#000;
+        background-color:#eef;
+}
+.red    {
+        color:#fff;
+        background-color:#ffe;        
+}
+.blue {
+        color:#000;
+        background-color:#fef !important;
+}
+
+/* font sizes */
+.baseFont {
+        line-height:14px;
+        font:12px Arial,sans-serif;
+        letter-spacing:0.1em;
+}
+
+.spacedVertical {
+        line-height:42px;
+}
+.spacedHorizontal {
+        letter-spacing:0.42em;        
+}
+.fontSizeTest {
+        font:20px Arial,sans-serif;
+}
+
+/* margins */
+.bigMargin {
+        margin:30px;        
+}
+.noMargin {
+        margin:0;
+}
+.mediumMargin {
+        margin:15px;
+}
+.bigMarginLeft {
+        margin-left:150px;
+}
+
+/* padding */
+.padded {
+        padding:3px;
+}
+.noPadding {
+        padding:0;
+}
+.topPadding {
+        padding-top:50px;
+}
+.bigPadding {
+        padding:30px; 
+}
+
+/* positioning */
+
+.offsetSome {
+        top:50px;
+        left:75px; 
+}
+
+.topLeft {
+        top:0;
+        left:0;
+}
+.bottomRight {
+        bottom:0;
+        right:0;
+}
+
+.bothAxis {
+        top:10px;
+        left:10px;
+        right:10px;
+        bottom:10px; 
+}
\ No newline at end of file
diff --git a/dojox/fx/tests/_base.js b/dojox/fx/tests/_base.js
new file mode 100644
index 0000000..4fb9963
--- /dev/null
+++ b/dojox/fx/tests/_base.js
@@ -0,0 +1,63 @@
+dojo.provide("dojox.fx.tests._base");
+
+dojo.require("dojox.fx._core");
+dojo.require("dojox.fx");
+
+tests.register("dojox.fx.tests._base", [
+
+	function simpleLineTest(t){
+
+		var line = new dojox.fx._Line(
+			[0, 100],
+			[100, 0]
+		);
+
+		var first = line.getValue(0);
+		t.assertEqual(first[0], 0);
+		t.assertEqual(first[1], 100);
+		
+		var mid = line.getValue(0.5);
+		t.assertEqual(mid[0], 50);
+		t.assertEqual(mid[1], 50);
+		
+		var end = line.getValue(1);
+		t.assertEqual(end[0], 100);
+		t.assertEqual(end[1], 0);
+
+	},
+	
+	function singleLineTest(t){
+		
+		var line = new dojox.fx._Line(0,100);
+		t.assertEqual(line.getValue(0), 0);
+		t.assertEqual(line.getValue(0.5), 50);
+		t.assertEqual(line.getValue(1), 100);
+		
+	},
+	
+	function multiDimensionalTest(t){
+		
+		var startSet = [5, 10, 15, 20, 25, 30, 35];
+		var endSet = [35, 30, 25, 20, 15, 10, 5];
+				
+		var line = new dojox.fx._Line(startSet, endSet);
+		
+		var start = line.getValue(0);
+		var mid = line.getValue(0.5);
+		var end = line.getValue(1);
+		
+		t.assertEqual(start.length, 7);
+		t.assertEqual(end.length, 7);
+		
+		t.assertEqual(startSet[0], start[0]);
+		t.assertEqual(startSet[1], start[1]);
+		t.assertEqual(startSet[5], start[5]);
+		
+		var expectedMid = 20;
+		dojo.forEach(line.getValue(0.5), function(val, i){
+			t.assertEqual(expectedMid, val)
+		});
+		
+	}
+	
+]);
diff --git a/dojox/fx/tests/example_Line.html b/dojox/fx/tests/example_Line.html
new file mode 100644
index 0000000..0e2ba25
--- /dev/null
+++ b/dojox/fx/tests/example_Line.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>using a dojo._Line and dojo.Animation</title>
+	<style type="text/css">
+	        @import "../../../dojo/resources/dojo.css";
+	        @import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		#node {
+			position:absolute;
+			top:100px; left:100px; 
+			width:400px;
+			height:400px; 
+			padding:12px;
+			-moz-border-radius:5pt;
+			overflow:hidden;
+			border:1px solid #333; 
+		}
+	</style>
+	<script type="text/javascript"
+	        djConfig="parseOnLoad: true, isDebug:false"
+	        src="../../../dojo/dojo.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojo.fx.easing");
+		dojo.require("dojox.gfx");
+
+		var surface, shape, line, node; 
+		dojo.addOnLoad(function(){
+			// dojo._Line is just a simple class to hold some numbers, and return a given point
+			// on the line as a percentage, essentially
+			var _line = new dojo._Line(20,75); // a holder for the numbers 20 .. 75
+			node = dojo.byId('node');
+
+			surface = dojox.gfx.createSurface(node,400,400);
+			shape = surface.createCircle({ cx: 200, cy: 200, r: 20 })
+				.setFill([0,0,255])
+				.setStroke({ color:[128,128,128], width: 1});
+			
+			// so we just make a raw Animation
+			var _anim = new dojo.Animation({
+				// the id of the shape	
+				node: node,
+				// some easing options
+				easing: dojo.fx.easing.easeInOut,
+				// our radius start and end values
+				curve:_line,
+				// call transform on the shape with the values
+				onAnimate: function(){
+					shape.setShape({ r: arguments[0] });
+				},
+				duration:1200 // ms
+				// rate:100 // ms, so duration/rate iterations
+			});
+
+
+			dojo.connect(_anim,"onEnd",function(){
+				dojo.animateProperty({
+					node: node,
+					duration:1000,
+					properties: {
+						left:300
+					},
+					onEnd: function(){
+						dojo.fadeOut({ node: node, duration:3000 }).play();
+					}	
+				}).play(500);
+			});
+			_anim.play(2000);
+		});
+	</script>
+</head>
+<body class="tundra">
+	
+	<h1>an "animateProperty" for dojox.gfx</h1>
+	<div id="node"></div>
+
+</body>
+</html>
diff --git a/dojox/fx/tests/example_backgroundPosition.html b/dojox/fx/tests/example_backgroundPosition.html
new file mode 100644
index 0000000..45dd5c3
--- /dev/null
+++ b/dojox/fx/tests/example_backgroundPosition.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Animated background position example | The Dojo Toolkit</title>
+		
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		#theNode {
+			background:#dedede url('images/longBg.png') 0px 0px;
+			padding:3px 10px 3px 10px; 
+			border:1px solid #b7b7b7;
+			color:#666;
+			cursor:pointer; 
+		}
+	
+	</style>
+	<script type="text/javascript">
+		dojo.require("dojo.fx");
+		var anim = null; 
+		var init = function(){
+			var node = dojo.byId('theNode');
+			anim = new dojo.Animation({
+				curve: new dojo._Line(0,-500),
+				duration: 3000,
+				onEnd: (function(){ anim.play(); }), // loop indefinately
+				onAnimate: function(){
+					var str = Math.floor(parseInt(arguments[0]))+"px 0px";
+					dojo.style(node,"backgroundPosition",str);
+				}
+			});
+
+			// dojo.query "magic"
+			dojo.query("#theNode")
+				.connect("onmouseenter",anim,"play")
+				.connect("onmouseout",anim,"pause")
+				.connect("onclick",function(){
+					alert('clicked the button');
+				});
+		};
+		dojo.addOnLoad(init);
+
+	</script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">dojo.Animation test:</h1>
+
+	<div class="dijitInline" id="theNode">Test</div>
+
+</body>
+</html>
diff --git a/dojox/fx/tests/example_dojoAnimations.html b/dojox/fx/tests/example_dojoAnimations.html
new file mode 100644
index 0000000..f32b3a5
--- /dev/null
+++ b/dojox/fx/tests/example_dojoAnimations.html
@@ -0,0 +1,439 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+   <head>
+
+	<title>skeleton page | The Dojo Toolkit</title>
+
+	<style type="text/css">		
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body, html {
+			width:100%;
+			margin:0;
+			padding:0;
+			font:11pt Arial,sans-serif;
+			color:#666; 
+		}
+		
+		#container {
+			width:760px;
+			margin:0 auto;
+		}
+		
+		div.testBox {
+			border:2px solid #ededed;
+			background:#fefefe;
+			height:200px;
+			margin:0 auto;
+			position:relative;
+		}
+		
+		div.testItem {
+			position:absolute;
+			background:#fff url('images/averycutedog.jpg') no-repeat center center;
+			border:2px solid #f0f0f0;
+			margin:0;
+			padding:0;
+			height:175px;
+			width:175px;
+			top:10px;
+			left:10px;
+		}
+		
+		.altItem {
+			position:absolute;
+			top:10px;
+			left:295px;
+		}
+		
+		.pad {
+			padding:4px;
+		}
+		
+		.trick {
+			height:175px;
+			width:175px;
+			visibility:hidden;
+		}
+		.odd,
+		.even { margin-left:1px; }
+		
+		#lorem {
+			position:absolute;
+			top:10px;
+			left:15px;
+			font:8pt Arial,sans-serif;
+			width:175px;
+			padding:4px;
+			background:#ededed;
+		}
+		
+		#fisheyeList {
+			width:95px;
+			background:#666;
+			padding:7px;
+		}
+		#fisheyeList li {
+			color:#fff;
+		}
+	</style>
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad:true, isDebug:true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.form.Button"); // for the tests
+		
+		// core animations:
+		dojo.require("dojo.fx");
+		
+		// provides dojo.query() animations:
+		dojo.require("dojo.NodeList-fx");
+		dojo.require("dojox.fx.ext-dojo.NodeList");
+		
+		// core dojox package:
+		dojo.require("dojox.fx");
+		dojo.require("dojox.fx._core"); // _Line
+		
+		// addons:
+		dojo.require("dojox.fx.style");
+		dojo.require("dojo.fx.easing");
+		
+		// examples inline:
+		dojo.require("dojox.widget.FisheyeLite");
+	</script>
+	
+</head>
+<body class="tundra">
+	<div id="container">
+
+	<h2>Dojo FX: base animations</h2>
+	
+	<button dojoType="dijit.form.Button">
+		Fade In/Out
+		<script type="dojo/method" event="onClick">
+			dojo.fadeOut({ node:"testSlide",
+				onEnd:function(){
+					dojo.fadeIn({ node:"testSlide", delay:300 }).play();	
+				}
+			}).play();
+		</script>
+	</button>
+	
+	<button dojoType="dijit.form.Button">
+		animateProperty: height
+		<script type="dojo/method" event="onClick">
+			dojo.animateProperty({
+				node:"testSlide",
+				properties:{ height:{ end:1 } },
+				onEnd:function(){
+					dojo.animateProperty({
+						node:"testSlide",
+						delay:300,
+						properties:{ height:175 }
+					}).play();	
+				}
+			}).play();
+		</script>
+	</button>
+	
+	<button dojoType="dijit.form.Button">
+		animateProperty: width
+		<script type="dojo/method" event="onClick">
+			dojo.animateProperty({
+				node:"testSlide",
+				properties:{ width:1 },
+				onEnd:function(){
+					dojo.animateProperty({
+						node:"testSlide",
+						delay:300,
+						properties:{ width:175 }
+					}).play();	
+				}
+			}).play();
+		</script>
+	</button>
+
+	<div class="testBox" id="testSlideWrapper">
+		<div class="testItem" id="testSlide">
+			<div class="trick"> </div>	
+		</div>
+	</div>
+
+
+	<h2>Animate CSS Properties:</h2>
+	
+	<button dojoType="dijit.form.Button">
+		marginLeft
+		<script type="dojo/method" event="onClick">
+			dojo.animateProperty({
+				node:"lorem",
+				properties:{
+					marginLeft:{ end:322, start:1 }
+				},
+				onEnd: function(){
+					dojo.animateProperty({
+						node:"lorem",
+						properties:{
+							marginLeft:{ end:1, start:322 }
+						},
+						delay:300
+					}).play();
+				}
+			}).play();
+		</script>
+	</button>
+	
+	<button dojoType="dijit.form.Button">
+		left / paddingTop
+		<script type="dojo/method" event="onClick">
+			dojo.animateProperty({
+				node:"lorem",
+				properties:{
+					left: {
+						end: dojo.marginBox("cssNodeWrap").w - 195,
+						units:"px"
+					},
+					paddingTop:{ end:17, start:4 }
+				},
+				onEnd: function(){
+					dojo.animateProperty({
+						node:"lorem",
+						properties:{
+							paddingTop:{ end:4, start:17 },
+							left:10
+						},
+						delay:300
+					}).play();
+				}
+			}).play();
+		</script>
+	</button>
+	
+	<button dojoType="dijit.form.Button">
+		fontSize / width
+		<script type="dojo/method" event="onClick">
+			dojo.animateProperty({
+				node:"lorem",
+				properties:{
+					width: { end:700, start:175 },
+					fontSize:{ end:21, units:"pt", start:11 }
+				},
+				onEnd: function(){
+					dojo.animateProperty({
+						node:"lorem",
+						properties:{
+							width:175, 
+							fontSize:{ end:11, start:21, units:"pt" }
+						},
+						delay:700
+					}).play();
+				}
+			}).play();
+		</script>
+	</button>
+	
+	<div class="testBox" id="cssNodeWrap">
+		<div id="cssNode">
+			<p id="lorem">Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+			Nam facilisis enim. Pellentesque in elit et lacus euismod dignissim.
+			Aliquam dolor pede, convallis eget, dictum a, blandit ac, urna.
+			Pellentesque sed nunc ut justo volutpat egestas. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos.
+			In erat.
+			</p>
+		</div>
+	</div>
+
+	<h2>dojo.fx - Core animations</h2>
+
+	<button dojoType="dijit.form.Button">
+		Slide
+		<script type="dojo/method" event="onClick">
+			// we're 175px, slide to containerWidth - 195
+			var left = dojo.marginBox("testSlideWrapper").w - 195;
+			// make and play the animation
+			dojo.fx.slideTo({
+				top:10,
+				left:left,
+				node:"testSlideToo",
+				onEnd: function(){
+					// slide'er back:
+					dojo.fx.slideTo({ top:10, left:10, node:"testSlideToo" }).play();
+				}
+			}).play()
+		</script>
+	</button>
+
+	<button dojoType="dijit.form.Button">
+		Combine Slide / Fade
+		<script type="dojo/method" event="onClick">
+			var anim1 = dojo.fx.slideTo({
+				top: 10,
+				left: dojo.marginBox("testSlideWrapper").w - 195,
+				node: "testSlideToo",
+				onEnd: function(){
+					// slide'er back:
+					dojo.fx.slideTo({ top:10, left:10, node:"testSlideToo" }).play();
+				}
+			});
+			var anim2 = dojo.fadeOut({
+				node: "testSlideToo",
+				onEnd: function(){
+					// we could switch out the backgroundImage property here.
+					dojo.fadeIn({ node:"testSlideToo" }).play();
+				}
+			});
+			var combined = dojo.fx.combine([anim1,anim2]);
+			combined.play();
+		</script>
+	</button>
+	
+	<button dojoType="dijit.form.Button">
+		Chain (4)
+		<script type="dojo/method" event="onClick">
+			var anim1 = dojo.fadeOut({ node:"testSlideToo",
+				// so anim1 is over, making this onEnd and anim2 basically
+				// a combine() (depending on the duration: )
+				onEnd:function(){
+					var delay = 125;
+					dojo.fadeIn({ node:'testSlideToo' }).play(delay);	
+				}
+			});
+
+			var anim2 = dojo.animateProperty({
+				node:"testSlideToo",
+				properties:{
+					left: dojo.marginBox("testSlideTooWrap").w - 195
+				},
+				onEnd: function(){
+					dojo.fx.slideTo({ node:"testSlideToo", top:10, left:10 }).play(123);
+				}
+			});
+			dojo.fx.chain([anim1,anim2]).play();
+		</script>
+	</button>
+
+	<div class="testBox" id="testSlideTooWrap">
+		<div class="testItem" id="testSlideToo">
+			<div class="trick"></div>
+		</div>
+	</div>
+
+	<h2>dojo.query FX</h2>
+	
+	<button dojoType="dijit.form.Button">
+		fade .even
+		<script type="dojo/method" event="onClick">
+			dojo.query(".even","queryUl").fadeOut({
+				onEnd:function(){
+					dojo.query(".even","queryUl").fadeIn({ delay: 300 }).play();	
+				}
+			}).play();
+		</script>
+	</button>	
+
+	<button dojoType="dijit.form.Button">
+		fade .odd
+		<script type="dojo/method" event="onClick">
+			dojo.query(".odd","queryUl").fadeOut({
+				onEnd:function(){
+					dojo.query(".odd","queryUl").fadeIn({ delay: 300 }).play();	
+				}
+			}).play();
+		</script>
+	</button>	
+	
+	<button dojoType="dijit.form.Button">
+		shift .odd
+		<script type="dojo/method" event="onClick">
+			dojo.query(".odd","queryUl").animateProperty({
+				properties:{
+					marginLeft:34
+				},
+				duration:300,
+				onEnd:function(){
+					dojo.query(".odd","queryUl").animateProperty({
+						delay: 300,
+						properties:{
+							marginLeft:1
+						}
+					}).play();	
+				}
+			}).play();
+		</script>
+	</button>	
+
+	<button dojoType="dijit.form.Button">
+		mmm, easing
+		<script type="dojo/method" event="onClick">
+			dojo.query(".odd","queryUl").animateProperty({
+				easing:dojo.fx.easing.backOut,
+				properties:{
+					marginLeft:34
+				},
+				duration:600,
+				onEnd:function(){
+					dojo.query(".odd","queryUl").animateProperty({
+						delay: 300,
+						duration:1300,
+						easing:dojo.fx.easing.bounceOut,
+						properties:{
+							marginLeft:1
+						}
+					}).play();	
+				}
+			}).play();
+		</script>
+	</button>	
+	
+	<button dojoType="dijit.form.Button">
+		Setup FisheyeList
+		<script type="dojo/method" event="onClick">
+			this.setAttribute("disabled",true);
+			dojo.query("li","fisheyeList").forEach(function(n){
+				new dojox.widget.FisheyeLite({
+					properties:{
+						marginLeft:17,
+						width:1.175
+					},
+					onClick:function(){
+						dojo.byId("clickAlert").innerHTML = "clicked: " + this.id;
+					},
+					easeIn:dojo.fx.easing.elasticOut,
+					durationIn:1700
+				},n).startup();
+			}).style("cursor","pointer");
+		</script>
+	</button>
+	
+	<div class="testBox" id="queryParent">
+		<ul id="queryUl">
+			<li class="odd">odd row</li>
+			<li class="even">even row</li>
+			<li class="odd">odd row</li>
+			<li class="even">even row</li>
+			<li class="odd">odd row</li>
+			<li class="even">even row</li>
+			<li class="odd">odd row</li>
+			<li class="even">even row</li>
+			<li class="odd">odd row</li>
+		</ul>
+		<div class="altItem">
+			<p>(FisheyeLite makes this easy. be creative:)</p>
+			<ul id="fisheyeList">
+				<li class="odd">odd row</li>
+				<li class="even">even row</li>
+				<li class="odd">odd row</li>
+				<li class="even">even row</li>
+				<li class="odd">odd row</li>
+				<li class="even" id="testIdFish">with id</li>
+				<li class="odd">odd row</li>
+			</ul>
+			<p id="clickAlert"></p>
+		</div>
+	</div>
+
+	</div>
+</body>
+</html>
diff --git a/dojox/fx/tests/example_easingChart2D.html b/dojox/fx/tests/example_easingChart2D.html
new file mode 100644
index 0000000..e1caf59
--- /dev/null
+++ b/dojox/fx/tests/example_easingChart2D.html
@@ -0,0 +1,147 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>visualising dojo.Animation.easing via dojox.charting</title>
+
+	<link rel="stylesheet" type="text/css" media="screen"
+		href="../../../dojo/resources/dojo.css">
+
+	<link rel="stylesheet" type="text/css" media="screen"
+		href="../../../dijit/themes/tundra/tundra.css">
+
+	<style type="text/css">
+	.box { padding:14px; 
+		border:1px solid #b7b7b7;
+		-moz-border-radius:8pt;
+	}
+	</style>
+	
+	<script type="text/javascript" djConfig="isDebug:false, parseOnLoad: true"
+		src="../../../dojo/dojo.js"></script>
+
+	<script type="text/javascript">
+		// one simple theme, and the charting engine:
+		dojo.require("dojox.charting.Chart2D");
+		// and easing functions:
+		dojo.require("dojo.fx.easing"); 
+
+		var d=0;
+		var masterData = {};
+		var makeSeries = function(/* string */str, /* Function */ func){
+			// make some data by running a 2sec animation with an easing function
+			// and adding it to the chart
+			var seriesData = [];
+			if(str in masterData){
+				seriesData=masterData[str];
+			}
+
+			if(!seriesData.length){
+				var func = func || dojox.fx.easing[str];
+				func = (dojo.isFunction(func) ? func : dojo._defaultEasing);
+
+				for(var i=0; i<=120; i++){
+					var pct = i/120;
+					seriesData.push({ y: 30 * func(pct), x: (pct) * 30});
+				}
+				if(!str.match(/^dynSeries/)){
+					masterData[str] = seriesData;
+				}
+				chart.addSeries(str,
+					seriesData,
+					{ stroke: { color: "black", width: 0 }, fill: "rgba(30,0,255,0.10)" }
+				).render();
+			}else{
+				chart.updateSeries(str, seriesData).render();
+			}
+		};
+
+		var removeSeries = function(str){
+			chart.updateSeries(str, []);
+			if(!clearAll){ chart.render(); }
+		};
+
+		var toggleChart = function(widget, str){
+			if(!chart) return;
+			if(widget.checked){
+				makeSeries(str);
+			}else{
+				removeSeries(str);
+			}
+		}
+
+		var chart;
+		var clearAll=false;
+		
+		dojo.addOnLoad(function(){
+				
+			// setup our chart
+			chart = new dojox.charting.Chart2D("easingChart");
+			chart.addAxis("x", {
+				fixLower: "major",
+				fixUpper: "major",
+				majorTickStep: 10,
+				minorTickStep: 1,
+				minorLabels: false,
+				htmlLabels: false
+			});
+			chart.addAxis("y", {
+				vertical: true,
+				fixLower: "major",
+				fixUpper: "major",
+				majorTickStep: 10,
+				minorTickStep: 1,
+				htmlLabels: false
+			});
+			chart.addPlot("default", {type: "Areas"});
+		});
+		
+		var opt;
+		dojo.addOnLoad(function(){
+			
+			var c = dojo.query(".clone")[0];	
+			opt = dojo.byId("select");
+			
+			for(var i in dojo.fx.easing){
+				var n = opt.appendChild(dojo.clone(c));
+				n.value = n.innerHTML = i
+				// n.innerHTML = i;
+			}
+		
+		    dojo.connect(opt,"onchange",function(e){
+				dojo.query("option",opt)
+				     // we only want "selected" nodes
+				    .filter(function(n){ return n.selected; })
+					 // yay, here they are:
+					.forEach(function(n){
+						console.log(n);
+				    });
+				makeSeries(opt.value, dojo.fx.easing[opt.value]);
+			});
+				
+			dojo.query(".box").connect("onclick",function(e){
+				console.log(opt.value, dojo.fx.easing[opt.value]);	
+			});
+			
+			makeSeries("visible",dojo._defaultEasing);	
+				
+		});
+		
+	</script>
+</head>
+<body class="tundra" style="padding:20px">
+
+	<h1>dojo.fx.easing</h1>
+	
+	<p>this chart shows time (x axis) vs. position (y axis) for a movement from 0px to 30px modified by easing functions</p>
+
+		<select id="select" multiple="true" size="7" name="easing">
+				<option class="clone" value="dojo._defaultEasing">dojo._defaultEasing</option>
+		</select>
+	
+		<div class="box">
+			<div id="easingChart" style="height:300px"></div>
+		</div>
+
+</body>
+</html>
diff --git a/dojox/fx/tests/images/averycutedog.jpg b/dojox/fx/tests/images/averycutedog.jpg
new file mode 100755
index 0000000..335855e
Binary files /dev/null and b/dojox/fx/tests/images/averycutedog.jpg differ
diff --git a/dojox/fx/tests/images/dot.png b/dojox/fx/tests/images/dot.png
new file mode 100755
index 0000000..1287a73
Binary files /dev/null and b/dojox/fx/tests/images/dot.png differ
diff --git a/dojox/fx/tests/images/longBg.png b/dojox/fx/tests/images/longBg.png
new file mode 100755
index 0000000..f89d23a
Binary files /dev/null and b/dojox/fx/tests/images/longBg.png differ
diff --git a/dojox/fx/tests/runTests.html b/dojox/fx/tests/runTests.html
new file mode 100644
index 0000000..ad812f5
--- /dev/null
+++ b/dojox/fx/tests/runTests.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox.wire Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.fx.tests._base">
+	</head>
+    <body>
+        Redirecting to D.O.H runner.
+    </body>
+</html> 
diff --git a/dojox/fx/tests/test_Nodelist-fx.html b/dojox/fx/tests/test_Nodelist-fx.html
new file mode 100644
index 0000000..f298e1d
--- /dev/null
+++ b/dojox/fx/tests/test_Nodelist-fx.html
@@ -0,0 +1,282 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojo.NodeList-fx and dojox.fx.ext-dojo.Nodelist | fx add-ons to dojo.query()</title>
+		
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad:true, isDebug:true"></script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		.testBoxContainer {
+			position:relative;
+			width:418px;
+			height:240px;
+			margin-left:50px; 
+			border-top:1px dashed #b7b7b7;
+			border-bottom:1px dashed #b7b7b7;
+		}
+
+		.testBox {
+			position:absolute;
+			top:0; left:0;
+			width:50px;
+			height:50px;
+			background:#ededed;
+			border:1px solid #b7b7b7;
+			-moz-border-radius:6pt;
+			-webkit-border-radius:5pt;
+			overflow:hidden; 
+		}
+		.rowOne { top:0; }
+		.rowTwo { top:60px; }
+		.rowThree { top:120px; }
+		.rowFour { top:180px; }
+		
+		.iOne { left:0; }
+		.iTwo { left:60px; }
+		.iThree { left:120px; }
+		.iFour { left:180px; }
+		.iFive { left:240px; }
+		.iSix { left:300px; }
+		.iSeven { left:360px; }
+		
+	</style>
+	<script type="text/javascript">
+
+	dojo.require("dojox.fx.ext-dojo.NodeList"); 
+	dojo.require("dijit.form.Button");
+	dojo.require("dijit.form.CheckBox");
+
+	// its funny...
+	var dQuery = dojo.query;
+	var d$ = dQuery;
+	
+	var anim2 = null;
+
+	var init = function(){
+		var anim = d$(".rowOne").highlight({
+			duration:700,
+			onEnd: function(){
+				d$(".rowTwo").fadeTo({ end: 0.5, 
+					duration:700,
+					onEnd: function(){
+						
+						anim2 = d$(".rowThree").fadeOut({
+							top:20, left:20,
+							duration:500
+						}).play(700);
+					}
+				}).play(300);	
+			}
+		});
+
+		dojo.connect(anim,"onEnd",function(){
+
+			var q1v = true;
+			var q1 = ".iSix"; // colum six 
+			// this will setup a connection on each of the nodes to toggle their fade state
+			d$(q1).connect("onclick",function(){
+				d$(q1)[(q1v ? "fadeOut" : "fadeIn")]().play();
+				q1v = !q1v;
+			});
+
+			// this highlights all the nodes via a mouseenter event, which automatically
+			// 
+			d$(".testBox").connect("onmouseenter",function(e){
+				dojox.fx.highlight({ node: e.target, duration:250 }).play(); 
+			});
+
+
+			var q3 = ".rowOne.iSeven"; // top right node
+			d$(q3).connect("onclick",function(){
+				d$(q3).sizeTo({ 
+					width:300, height:300, duration:300, 
+					onEnd: function(){
+						// FIXME: sizeTo isn't calculating it's start value properly
+						d$(q3).sizeTo({ width: 50, height:50, duration:115, delay:1000, method:"combine" }).play(); 	
+					}
+				}).play(); 
+			});
+
+			
+
+		});
+		// main animation
+		anim.play(700); 
+	};
+	// start the code
+	dojo.addOnLoad(init);
+	
+	// for our dojo.query() form, some animations take different params which would be kind of difficult
+	// to make both dynamic and robust and easy to explain. see each function individually in the API
+	// for the breakdown. just going to hard-code some values in for somet things:
+	var animArgs = {
+		// dojo.NodeList-fx ones:
+		animateProperty: {
+			properties: {
+				borderWidth:5,
+				marginTop:8 
+			}
+	
+		},
+		
+		slideTo: { top:0, left: 0 },
+		
+		// dojox extension ones:
+		sizeTo: {
+			width: 75, height:75
+		},
+		fadeTo: {
+			end: 0.35
+		},
+		slideBy: {
+			top:55, left: 55
+		},
+		
+		// mix these into every 'custom query animation'
+		defaultArgs: {
+			// duration: 500 //,
+			// onEnd: function(){ console.log('ended animation') }
+		}
+	};
+	
+	
+
+	</script>
+</head>
+<body class="tundra">
+
+        <h1 class="testTitle">NodeList and dojo.query "magic"</h1>
+
+	<div style="width:200px; float:right; padding:10px">
+		<h4>stuff going on:</h4>
+		<ul>
+			<li>watch the startup cycle</li>
+			<li>click col 6</li>
+			<li>click top right box</li>	
+			<li>hover to highlight() node</li>
+		</ul> 
+	</div>
+
+	<div style="width:200px; float:right; padding:10px">
+		<h4>custom query:</h4>
+		<form id="whichAnim">
+		<p>
+			dojo.query("<input type="text" name="str" id="customStr" value=".noIdHere" size="10" />");	
+			<br>(dojo:)<br>
+			<input type="radio" name="g2" id="g2rb1" value="fadeIn" dojoType="dijit.form.RadioButton" checked="checked"/>
+			<label for="g2rb1">.fadeIn</label><br>
+
+			<input type="radio" name="g2" id="g2rb2" value="fadeOut" dojoType="dijit.form.RadioButton"/>
+			<label for="g2rb2">.fadeOut</label><br>
+
+			<input type="radio" name="g2" id="g2rb3" value="wipeOut" dojoType="dijit.form.RadioButton"/>
+			<label for="g2rb3">.wipeOut</label><br>
+
+			<input type="radio" name="g2" id="g2rb4" value="wipeIn" dojoType="dijit.form.RadioButton"/>
+			<label for="g2rb4">.wipeIn</label><br>
+
+			<input type="radio" name="g2" id="g2rb0" value="slideTo" dojoType="dijit.form.RadioButton"/>
+			<label for="g2rb0">.slideTo</label> (x: 0, y:0)<br>
+
+			<br>(dojox:)<br>
+		
+			<input type="radio" name="g2" id="g2rb5" value="highlight" dojoType="dijit.form.RadioButton"/>
+			<label for="g2rb5">.highlight</label><br>
+
+			<input type="radio" name="g2" id="g2rb6" value="sizeTo" dojoType="dijit.form.RadioButton"/>
+			<label for="g2rb6">.sizeTo (a fixed size)</label><br>
+
+			<input type="radio" name="g2" id="g2rb7" value="slideBy" dojoType="dijit.form.RadioButton"/>
+			<label for="g2rb7">.slideBy (top: left: offset fixed)</label><br>
+
+			<input type="radio" name="g2" id="g2rb8" value="fadeTo" dojoType="dijit.form.RadioButton"/>
+			<label for="g2rb8">.fadeTo (35% opacity)</label><br>
+
+		</p>
+		<script type="dojo/method" event="onSubmit">
+			// it's like cheating, but we don't event want this form to submit. you can type
+			// a query(), use the arrows to select a method, and hit enter. (or should be able to)
+			return false; 
+		</script>
+
+		<button dojoType="dijit.form.Button" type="submit" id="runnerButton" />
+			Run
+			<script type="dojo/method" event="onClick">
+				// our runner / submit button				
+				var str = dojo.byId("customStr").value;
+				var animType;
+				dojo.query('.dijitRadioChecked').forEach(function(n){
+					animType = dijit.byNode(n).attr("value");
+				});
+				if(str && animType){
+					var theseArgs = animArgs[animType] || {};
+					// combine our base args with 'theseArgs' if they exist
+					var args = dojo.mixin(theseArgs,animArgs.defaultArgs)
+					//var nodelist = dojo.query(str); 
+					dojo.query(str)[(animType)](args).play();
+				}
+				return false; 
+			</script>
+		</button>
+
+		</form>
+	</div>
+
+        <div class="testBoxContainer">        
+                <div id="node1" class="testBox rowOne iOne">1</div>
+                <div id="node2" class="testBox rowOne iTwo">2</div>
+                <div class="testBox noIdHere rowOne iThree">3</div>
+		<div class="testBox noIdHere rowOne iFour">4</div>
+		<div class="testBox noIdHere rowOne iFive">5</div>
+		<div class="testBox noIdHere rowOne iSix">6</div>
+		<div class="testBox noIdHere rowOne iSeven">7</div>
+
+                <div id="node4" class="testBox rowTwo iOne">2</div>
+                <div class="testBox noIdHere rowTwo iTwo"></div>
+                <div id="node6" class="testBox rowTwo iThree"></div>
+		<div class="testBox noIdHere rowTwo iFour"></div>
+		<div class="testBox noIdHere rowTwo iFive"></div>
+		<div class="testBox noIdHere rowTwo iSix"></div>
+		<div class="testBox noIdHere rowTwo iSeven"></div>
+
+                <div id="node7" class="testBox rowThree iOne">3</div>
+                <div class="testBox noIdHere rowThree iTwo"></div>
+                <div id="node9" class="testBox rowThree iThree"></div>
+		<div class="testBox noIdHere rowThree iFour"></div>
+		<div class="testBox noIdHere rowThree iFive"></div>
+		<div class="testBox noIdHere rowThree iSix"></div>
+		<div id="aNode" class="testBox rowThree iSeven"></div>
+
+                <div id="node7" class="testBox rowFour iOne">4</div>
+                <div class="testBox noIdHere rowFour iTwo"></div>
+                <div id="node9" class="testBox rowFour iThree"></div>
+		<div class="testBox noIdHere rowFour iFour"></div>
+		<div class="testBox noIdHere rowFour iFive"></div>
+		<div id="randomNode" class="testBox rowFour iSix"></div>
+		<div class="testBox noIdHere rowFour iSeven"></div>
+
+        </div>
+
+        <br style="clear:both;">
+	HTML AFTER
+	<br>
+		
+	<h3>classes available to play with:</h3>
+	
+	<pre><code style="border:0px;"
+>	.testBox
+	.noIdHere
+	each row: .rowOne .rowTwo .rowThree .rowFour
+	each col: .iOne .iTwo .. iSeven
+	#randomNode, #node9, #node7, #aNode, #node1, #node2, #node4, #node6</code
+	></pre>
+
+	<p>the dojo.query() isn't limited to the testDiv, it parses the body. try: dojo.query("fieldset") and slideBy animation</p>
+
+</body>
+</html>
diff --git a/dojox/fx/tests/test_Shadow.html b/dojox/fx/tests/test_Shadow.html
new file mode 100644
index 0000000..26cc283
--- /dev/null
+++ b/dojox/fx/tests/test_Shadow.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.fx.Shadow - Drop Shadows for DomNodes | The Dojo Toolkit</title>
+		
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+	<script type="text/javascript" src="../Shadow.js"></script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	<script type="text/javascript">
+		dojo.require("dojo.dnd.Moveable");
+		dojo.require("dojox.layout.FloatingPane");
+		dojo.require("dijit.Calendar"); 
+		var enabled = true, randInt=0;
+		dojo.addOnLoad(function(){
+			
+			dojo.query(".hasShadow").forEach(function(n){
+				var foo = new dojox.fx.Shadow({ node:n });
+				foo.startup();
+
+				if(++randInt%2===0){
+					var tmp = new dojo.dnd.Moveable(n);
+				}
+				
+				setTimeout(dojo.hitch(foo,"resize"),4000);
+				//setTimeout(dojo.hitch(foo,"setOpacity","0.6",{ duration: 500 }),2000);
+				dojo.connect(n,"onmouseover",dojo.hitch(foo,function(){
+					this.setOpacity(1);
+				}));
+				dojo.connect(n,"onmouseout",dojo.hitch(foo,function(){
+					if(!dojo.isIE){
+						this.setOpacity(0.5);
+					}
+				}));
+				dojo.connect(n,"onclick",dojo.hitch(foo,function(){
+					this.setDisabled(!this.disabled);
+				}));
+
+			});
+
+			/*
+			var div = document.createElement('div');
+			var testNode = document.createElement('div'); 
+
+			testNode.appendChild(div);
+			div.innerHTML = "Lorem Ipsum";
+			dojo.body().appendChild(testNode);
+
+			//dojo.addClass(testNode,"dijitInline"); 
+
+			var aDijit = new dijit.Calendar({},div);
+			aDijit.startup();
+
+			var testShadow = new dojox.fx.Shadow({ node: aDijit.domNode }); 
+			testShadow.startup(); 
+			testShadow.resize();
+				*/
+		});
+
+
+	</script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">dojox.fx.Shadow tests</h1>
+
+	<div>
+		<h2>with margin:</h2>
+		<div class="hasShadow" style="background:#fff; border:1px solid #a0a0a0; width:100px; height:100px; margin:20px;"> <p>Lorem</p> </div>
+
+		<h2>with padding:</h2>
+		<div class="hasShadow" style="background:#fff; border:1px solid #a0a0a0; width:100px; height:100px; padding:10px; "> <p>Lorem</p> </div>
+
+		<h2>no padding:</h2>
+		<div class="hasShadow" style="background:#fff; border:1px solid #a0a0a0; width:100px; height:100px;"> <p>Lorem</p> </div>
+
+		<h2>position:absolute</h2>
+		<div class="hasShadow" style="background:#fff; border:1px solid #a0a0a0; width:100px; height:100px; position:absolute; top:0px; left:200px; "> <p>Lorem</p> </div>
+
+		<br style="clear:both;">
+	</div>
+
+	
+	<br><br>
+
+
+</body>
+</html>
diff --git a/dojox/fx/tests/test_Timeline.html b/dojox/fx/tests/test_Timeline.html
new file mode 100644
index 0000000..0c55eaf
--- /dev/null
+++ b/dojox/fx/tests/test_Timeline.html
@@ -0,0 +1,173 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+    "http://www.w3.org/TR/html4/strict.dtd"
+    >
+<html lang="en">
+<head>
+    <title>Test dojox.fx.Timeline</title>
+	<style>
+		@import "../../../dijit/tests/css/dijitTests.css";
+		body{
+			font-family:sans-serif;
+		}
+		p{
+			width:700px;
+			font-size:12px;
+		}
+		.wrap{
+			
+		}
+		.lft{
+			width:500px;
+			height:400px;
+			border:1px solid #666;
+			position:relative;
+			float:left;
+		}
+		.rgt{
+			width:300px;
+			height:400px;
+			border:1px solid #666;
+			position:relative;
+			float:left;
+			margin-left:10px;
+		}
+		
+		#ball{
+			width:50px;
+			height:50px;
+			position:relative;
+			border:1px solid #000;
+			background:#0000ff;
+		}
+		
+		#text{
+			font-family:sans-serif;
+			font-size:16px;
+			position:absolute;
+			bottom:90%;
+			left:0%;
+		}
+	</style>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+		<script>
+			dojo.require("dojox.fx.ext-dojo.reverse");
+			dojo.require("dojox.fx.Timeline");
+
+			var keys = [
+				{
+					width:"50px",
+					height:"50px",
+					marginTop:"0px",
+					borderWidth:"10px",
+					borderColor:"#ffff00",
+					left:"0px",
+					ease:"quadIn"
+				},
+				{
+					height:"250px",
+					marginTop:"50px",
+					left:"300px",
+					ease:"quadOut"
+				},
+				{
+					width:"250px",
+					height:"50px",
+					borderWidth:"20px",
+					borderColor:"#ff0000",
+					left:"0px"
+				},
+				{
+					width:"50px",
+					height:"50px"
+				},
+				{
+					marginTop:"300px",
+					left:"0px",
+					ease:"bounceOut"
+				},
+				{
+					left:"300px"
+				}
+			];
+			
+			var keys2 = [
+				{
+					step:"0%",
+					bottom:"90%",
+					ease:"quadIn"
+				},
+				{
+					step:"1%",
+					left:"0%",
+					fontSize:"36px",
+					
+				},
+				
+				{
+					step:"20%",
+					bottom:"0%",
+					ease:"quadOut"
+				},
+				{
+					step:"40%",
+					bottom:"70%",
+					ease:"quadIn"
+				},
+				{
+					step:"60%",
+					bottom:"0%",
+					ease:"quadOut"
+				},
+				{
+					step:"80%",
+					bottom:"30%",
+					ease:"quadIn"
+				},
+				
+				
+				
+				{
+					step:"99%",
+					fontSize:"2px",
+					left:"90%"
+				},{
+					step:"100%",
+					bottom:"0%"
+				}
+			];
+			
+			var ani, ani2;
+			reverse = function(){
+				ani.reverse();
+				ani2.reverse();
+			}
+			dojo.addOnLoad(function(){
+				ani = dojox.fx.animateTimeline({keys:keys, duration:4000}, "ball").play();
+				ani2 = dojox.fx.animateTimeline({keys:keys2, duration:2000}, "text").play();
+			});
+			
+		</script>
+</head>
+<body>
+    <h1>Test Timeline</h1>
+	<p>
+		This is a test for the dojo.Animation extension, dojox.fx.Timeline.
+		This works by replacing <em>dojo._Line</em> with <em>dojox.fx._Timeline</em>. The keyframes
+		are an array of object properties. Properties can skip steps, so <em>width</em> will still
+		transition if it is in key #1 and key #5.
+	</p>
+	<p>
+		This is reversable as well, using <em>dojox.fx.ext-dojo.reverse</em>. Note the Reverse button.
+	</p>
+	<button onclick="reverse();">Reverse</button>
+	<div class="wrap">
+		<div class="lft">
+			<div id="ball"></div>
+		</div>
+		<div class="rgt">
+			<div id="text">Dojo</div>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/fx/tests/test_animateClass.html b/dojox/fx/tests/test_animateClass.html
new file mode 100644
index 0000000..7e0a07b
--- /dev/null
+++ b/dojox/fx/tests/test_animateClass.html
@@ -0,0 +1,221 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.fx.style - animatated CSS functions | The Dojo Toolkit</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "_animation.css"; /* external stylesheets to enhance readability in this test */
+	</style>
+		
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true" ></script>
+		
+	<!-- debugging -->
+	<script type="text/javascript" src="../style.js"></script>
+	<script type="text/javascript" src="../ext-dojo/NodeList-style.js"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dojox.fx.style");
+		dojo.require("dojox.fx.ext-dojo.NodeList-style");
+		
+		dojo.require("dijit.form.Button"); 
+	</script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">dojox.fx.style tests</h1>
+
+	<p id="fontTest">
+		dojox.fx.style provides a few methods to animate the changes that would occur
+		when adding or removing a class from a domNode.
+	</p>
+	<ul class="testUl" id="test1">
+			<li class="baseFont">dojox.fx.addClass(node, className, animargs); // Returns dojo.Animation</li>
+			<li class="baseFont">dojox.fx.removeClass(node, className, animargs); // Returns dojo.Animation</li>
+			<li class="baseFont">dojox.fx.toggleClass(node, className, force, animargs)</li>
+	</ul>
+
+	<button dojoType="dijit.form.Button">
+			spacing test
+			<script type="dojo/method" event="onClick">
+				dojo.query("li.baseFont").toggleClassFx("spacedHorizontal").play(5);
+			</script>
+	</button>
+
+	<button dojoType="dijit.form.Button">
+			line-height test
+			<script type="dojo/method" event="onClick">
+				dojo.query("li.baseFont").toggleClassFx("spacedVertical").play(5);
+			</script>
+	</button>
+
+	<button dojoType="dijit.form.Button">
+			font-size test
+			<script type="dojo/method" event="onClick">
+				dojo.query("li.baseFont").toggleClassFx("fontSizeTest").play(5);
+			</script>
+	</button>
+
+	<h2>testing sizes</h2>
+
+	<button dojoType="dijit.form.Button" id="addTall">
+		add .tall
+		<script type="dojo/method" event="onClick">
+				var delay = 500;
+				var _anims = [];
+				dojo.query("#colorTest > .testBox").forEach(function(n){
+					_anims.push(dojox.fx.addClass(n, "tall", {
+						delay: delay
+					}));
+					delay += 200;
+				});
+				this.attr('disabled',true);
+				dijit.byId('removeTall').attr('disabled',false);
+				dojo.fx.combine(_anims).play();
+		</script>
+	</button>
+	<button dojoType="dijit.form.Button" id="removeTall" disabled="true">
+		remove .tall
+		<script type="dojo/method" event="onClick">
+				var delay = 500;
+				var _anims = [];
+				dojo.query("#colorTest > .testBox").forEach(function(n){
+						_anims.push(dojox.fx.removeClass(n, "tall", {
+								delay: delay
+						}));
+						delay += 200;
+				});
+				this.attr('disabled', true);
+				dijit.byId('addTall').attr('disabled',false);
+				dojo.fx.combine(_anims).play();
+		</script>
+	</button>		 
+	<button dojoType="dijit.form.Button" id="addWide">
+		add .wide
+		<script type="dojo/method" event="onClick">
+				var delay = 500;
+				var _anims = [];
+				dojo.query("#colorTest > .testBox").forEach(function(n){
+						_anims.push(dojox.fx.addClass(n, "wide", {
+								delay: delay
+						}));
+						delay += 200;
+				});
+				this.attr('disabled',true);
+				dijit.byId('removeWide').attr('disabled',false);
+				dojo.fx.combine(_anims).play();
+		</script>
+	</button>
+	<button dojoType="dijit.form.Button" id="removeWide" disabled="true">
+		remove .wide
+		<script type="dojo/method" event="onClick">
+				var delay = 500;
+				var _anims = [];
+				dojo.query("#colorTest > .testBox").forEach(function(n){
+					_anims.push(dojox.fx.removeClass(n, "wide", {
+						delay: delay
+					}));
+					delay += 200;
+				});
+				this.attr('disabled',true);
+				dijit.byId('addWide').attr('disabled',false);
+				dojo.fx.combine(_anims).play();
+		</script>
+	</button>
+	<button dojoType="dijit.form.Button">
+		toggle .tiny
+		<script type="dojo/method" event="onClick">
+				var _anims = [];
+				// until dojox.fx.NodeList-fx is ready:
+				dojo.query("#colorTest > .testBox").forEach(function(node){
+					_anims.push(dojox.fx.toggleClass(node, "tiny"));
+				})
+				dojo.fx.combine(_anims).play(5);
+		</script>
+	</button>
+
+	<button dojoType="dijit.form.Button">
+		query add tall
+		<script type="dojo/method" event="onClick">
+			dojo.query("#colorTest > .testBox").addClassFx("tall").play();
+		</script>		
+	</button>
+	<button dojoType="dijit.form.Button">
+		query remove tall
+		<script type="dojo/method" event="onClick">
+			dojo.query("#colorTest > .testBox").removeClassFx("tall").play();
+		</script>
+	</button>
+	
+	
+
+	<div id="colorTest">
+		<div id="colorTest1" class="floating testBox white"></div>
+		<div id="colorTest2" class="floating testBox black"></div>
+		<div id="colorTest3" class="floating testBox green"></div>
+	</div>		  
+
+	<br style="clear:both">
+		   
+	<h2>testing position</h2>
+	<p>This is a div position:relative with a position:absolute div inside. testing various t/l/b/r combos.
+	normal css inheritance rules apply, so setting .foo .bar if .foo was defined last in the css text, .bar
+	will take precedent. the below position test shows the results of this:
+	</p>
+	
+	<button dojoType="dijit.form.Button">
+		.offsetSome
+		<script type="dojo/method" event="onClick">
+				dojox.fx.toggleClass("positionTest","offsetSome").play();		 
+		</script>
+	</button>
+	<button dojoType="dijit.form.Button">
+		.topLeft
+		<script type="dojo/method" event="onClick">
+				dojox.fx.toggleClass("positionTest","topLeft").play();		  
+		</script>
+	</button>
+	<button dojoType="dijit.form.Button">
+		.bottomRight
+		<script type="dojo/method" event="onClick">
+				dojox.fx.toggleClass("positionTest","bottomRight").play();		  
+		</script>
+	</button>
+	
+	<div style="position:relative; height:175px; width:500px; border:1px solid #666;" id="positionBlock">
+		<div class="testBox absolutely" id="positionTest"></div>
+	</div>
+			
+	<button dojoType="dijit.form.Button">
+		toggle .green
+		<script type="dojo/method" event="onClick">
+				dojox.fx.toggleClass("positionTest","green").play();
+		</script>
+	</button>
+	<button dojoType="dijit.form.Button">
+		toggle .black
+		<script type="dojo/method" event="onClick">
+				dojox.fx.toggleClass("positionTest","black").play();
+		</script>
+	</button>
+	<button dojoType="dijit.form.Button">
+		toggle .blue
+		<script type="dojo/method" event="onClick">
+				dojox.fx.toggleClass("positionTest","blue").play();
+		</script>
+	</button>
+
+	<p>Some properties
+	cannot be modified (fontFace, and so on), so to ensure the results at the end
+	of the animation are applied correctly and fully, the class name is set on the node
+	via dojo.add/removeClass().
+	</p>
+
+</body>
+</html>
+
diff --git a/dojox/fx/tests/test_complex.html b/dojox/fx/tests/test_complex.html
new file mode 100644
index 0000000..33b5a45
--- /dev/null
+++ b/dojox/fx/tests/test_complex.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+    "http://www.w3.org/TR/html4/strict.dtd"
+    >
+<html lang="en">
+<head>
+    <title>Test dojox.fx.ext-dojo.complex</title>
+	<style>
+		@import "../../../dijit/tests/css/dijitTests.css";
+		body{
+			font-family:sans-serif;
+			font-size:14px;
+		}
+		#cnt{
+			width:300px;
+			height:300px;
+			border:1px solid #666;
+			position:relative;
+		}
+		#words{
+			width:300px;
+			height:300px;
+			margin:0px;
+			padding:5px;
+			top:0px;
+			position:absolute;
+			border:1px solid #000;
+			background:#0000ff;
+			clip:rect(10px 30px 30px 10px);
+		}
+		code{
+			font-family:monospace;
+			font-size:11px;
+			white-space:nowrap;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+		<script>
+			dojo.require("dojox.fx.ext-dojo.complex");
+			
+			dojo.addOnLoad(function(){
+				var ani = dojo.animateProperty({
+					node:dojo.byId("words"),
+					duration:800,
+					properties:{
+						clip:{start:'rect(150px 150px 150px 150px)', end:'rect(0px 300px 300px 0px)'}
+					}
+				}).play();
+			});
+			
+		</script>
+</head>
+<body>
+	<h1>Test dojox.fx.ext-dojo.complex</h1>
+	<p>
+		The <em>dojox.fx.ext-dojo.complex</em> class is an extension of dojo.animateProperty which adds functionality
+		that animates a "complex property". The primary example is the
+		clip style: <code>rect(10px 30px 10px 50px)</code>.
+	</p>
+	<p>
+		Frankly, the clip style is not very useful nor exciting. But the <em>dojox.fx.ext-dojo.complex</em> class
+		will animate any property contained within parenthesis. So it can also be used with (and is actually intended for)
+		CSS3 properties, such as transform:
+		<code>transform: rotate(10deg) translateX(0px)</code>
+		or even gradients (it would only affect the properties within the color-stops):
+		<code>background-image: -webkit-gradient(linear, right top, left top, color-stop(0, #ff0000),color-stop(1.0, #0000FF));</code>
+	</p>
+	<p>
+		A few notes on the clip:rect() property. IE only accepts no commas - Firefox & Safari accepts both. So.... don't use commas!
+		Also, the node must be set to position:absolute to work.
+	</p>
+	<div id="cnt">
+		<div id="words">
+			<p>
+				Dojo saves you time, performs better, and scales to meet your needs.
+				It's the toolkit that experienced designers and developers turn to for building great experiences. 
+				<br/><br/>
+				Dojo is a set of integrated libraries that accelerate development from simple pages to the most sophisticated web applications.
+				Great resources are available to help you take advantage of all that power.
+				<br/><br/>
+				Dojo Campus hosts the official documentation wiki, short how-to articles, and a rich set of examples
+				to help you leverage the power and depth of Dojo.
+			</p>
+		</div>
+	</div>
+	
+</body>
+</html>
diff --git a/dojox/fx/tests/test_crossFade.html b/dojox/fx/tests/test_crossFade.html
new file mode 100644
index 0000000..330a34a
--- /dev/null
+++ b/dojox/fx/tests/test_crossFade.html
@@ -0,0 +1,145 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.fx - animation sets to use!</title>
+		
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+	<script type="text/javascript" src="../_base.js"></script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	
+		#crossfade {
+			position:absolute;
+			top:0;
+			left:300px; 
+			border:2px solid #ededed; 
+			width:50px; height:50px; 
+			background:#fff; 
+			text-align:center; 
+		}
+	
+		table tr { padding:5px; margin:5px; border:1px solid #ccc; }
+
+		.box { 
+			width:75px; height:75px; float:left;
+			border:1px solid #ededed;
+			padding:20px;
+			background-color:#fee; 
+		}
+		.two { background-color:#c7bedd; } 
+		.nopad { padding:0 !important;
+			width:100px; height:100px; border:0;
+		 } 
+		.hidden {
+			opacity:0;
+		}
+	</style>
+	<script type="text/javascript">
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.TitlePane");
+	
+		function basicXfade(){
+			dojox.fx.crossFade({
+				nodes: [dojo.byId('node1'),dojo.byId('node2')],
+				duration: 1000
+			}).play();
+		};
+
+		function absoluteXfade(){
+			dojox.fx.crossFade({
+				nodes: ["node3","node4"],
+				duration:1000
+			}).play();
+		};
+
+		var _anim; 
+		function simpleLoop(){
+			dojo.byId('button').disabled = "disabled"; 
+			_anim = dojox.fx.crossFade({
+				nodes: ["node5","node6"],
+				duration:1000
+			});
+			dojo.connect(_anim,"onEnd","simpleLoop");
+			_anim.play(500);
+		};
+		function stopLoop(){ _anim.stop(); }
+
+		function buttonExample(){
+			dojox.fx.crossFade({
+				nodes: [
+					// FIXME: fails in ie6?!?
+					dijit.byId('node7').domNode, 
+					dijit.byId('node8').domNode
+					],
+				duration: 350
+			}).play();
+		}
+
+		dojo.addOnLoad(function(){
+			// this is a hack to make nodes with class="hidden" hidden
+			// because ie6 is a horrible wretched beast
+			dojo.query(".hidden").forEach(function(node){
+				dojo.style(node,"opacity","0"); 
+			});
+
+
+		});
+
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">dojox.fx.crossFade test</h1>
+
+	
+	<h3>a simple demonstration of two nodes fading simultaneously</h3>
+	<div>
+	<input type="button" onclick="basicXfade()" value="run" />
+	<div style="padding:20px">
+		<div id="node1" style="display:inline;" class="box hidden">box1</div>
+		<div id="node2" class="box">box2</div>
+	</div>
+	<br style="clear:both">
+	</div>
+
+	<h3>two nodes with position:relative in a container with position:absolute, crossfading together.</h3>
+	<input type="button" onclick="absoluteXfade()" value="run" />
+	<div>
+		<div style="width:100px; height:100px; position:relative; border:1px solid #666; ">
+			<div id="node3" style="position:absolute; top:0; left:0;" class="box nopad hidden">box one</div>
+			<div id="node4" style="position:absolute; top:0; left:0;" class="box two nopad">box two</div>
+		</div>
+	<br style="clear:both">
+	</div>
+
+	<h3>simple looping crossfade</h3>
+	<input type="button" onclick="simpleLoop()" value="run" id="button" />
+	<div>
+	<div style="padding:20px;">
+			<div id="node5" class="box nopad">box one</div>
+			<div id="node6" class="box two nopad hidden">box two</div>
+	</div>
+	<br style="clear:both">
+	</div>
+
+	<!-- FIXME: acting oddly, only in IE though 
+	<h3>An example of cross-fading a dijit.form.Button</h3>
+	<input type="button" onclick="buttonExample()" value="run" id="button" />
+	<div>
+	<div style="position:relative;">
+		<div dojoType="dijit.TitlePane" id="node7" 
+			style="position:absolute; top:0; left:0;">Lorem content two</div>
+		<div dojoTYpe="dijit.TitlePane" id="node8" class="hidden"
+			style="position:absolute; top:0; left:0;">Lorem content one</div>
+	</div>
+	<br style="clear:both;">
+	</div>
+	-->
+
+	<h3>that's all, folks...</h3>
+
+</body>
+</html>
diff --git a/dojox/fx/tests/test_easing.html b/dojox/fx/tests/test_easing.html
new file mode 100644
index 0000000..b96e94d
--- /dev/null
+++ b/dojox/fx/tests/test_easing.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.fx.easing functions:</title>
+		
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		.bounce {
+			position:absolute;
+			top:300px;
+			left:400px;
+			width:25px;
+			height:25px;
+			border:1px solid #b7b7b7;
+			background:#ededed;
+		}
+
+		.block {
+			width:200px;
+			height:100px;
+			background:#666;
+			border:1px solid #ccc;
+			display:block; 
+			color:#fff;
+			text-align:center; 
+		}
+	
+	</style>
+	<script type="text/javascript">
+		dojo.require("dojo.fx"); // chain and combine should be in core :) (when they work)
+		dojo.require("dojo.fx.easing"); 
+
+
+		var allAnim = null; 
+		dojo.addOnLoad(function(){
+
+		var easeInAnim = dojo.fx.chain([
+			dojo.fadeOut({
+				node: 'easeIn',
+				duration:2000,
+				easing: dojo.fx.easing.easeIn
+			}),
+			dojo.fadeIn({	
+				node: 'easeIn',
+				duration:2000,
+				easing: dojo.fx.easing.easeIn
+			})
+		]);
+
+
+		var easeOutAnim = dojo.fx.chain([
+			dojo.fadeOut({
+				node: 'easeOut',
+				duration:2000,
+				easing: dojo.fx.easing.easeOut
+			}),
+			dojo.fadeIn({	
+				node: 'easeOut',
+				duration:2000,
+				easing: dojo.fx.easing.easeOut
+			})
+		]);
+
+		var easeInOutAnim = dojo.fx.chain([
+			dojo.fadeOut({
+				node: 'easeInOut',
+				duration:2000
+			}),
+			dojo.fadeIn({	
+				node: 'easeInOut',
+				duration:2000
+			})
+		]);
+
+		var linearEaseAnim = dojo.fx.chain([
+			dojo.fadeOut({
+				node: 'linearEase',
+				duration:2000,
+				easing: dojo.fx.easing.linear
+			}),
+			dojo.fadeIn({
+				node: 'linearEase',
+				duration:2000,
+				easing: dojo.fx.easing.linear
+			})
+		]);
+
+		dojo.connect(dojo.byId('easeIn'),"onclick",easeInAnim,"play");
+		dojo.connect(dojo.byId('easeOut'),"onclick",easeOutAnim,"play");
+		dojo.connect(dojo.byId('easeInOut'),"onclick",easeInOutAnim,"play");
+		dojo.connect(dojo.byId('linearEase'),"onclick",linearEaseAnim,"play");
+
+		allAnim = { play: function(){ 
+			easeInAnim.play();
+			easeOutAnim.play();
+			easeInOutAnim.play(); 
+			linearEaseAnim.play();
+			} 
+		}; 
+
+		}); // dojo.addOnLoad
+	</script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">dojox.fx.easing function tests:</h1>
+
+	(click block to play animation, or <a href="#" onclick="allAnim.play()">here to do all three</a>)
+
+	<div id="easeIn" class="block">dojo.fx.easing.easeIn</div>
+	<br><br>
+	<div id="easeOut" class="block">dojo.fx.easing.easeOut</div>
+	<br><br>
+	<div id="linearEase" class="block">dojo.fx.easing.linear</div>
+	<br><br>
+	<div id="easeInOut" class="block">dojo default easing</div>
+	
+	<p>
+	dojo.fx.easing is stand-alone, and does not require the dojox.fx base files. to see a chart
+	of these functions see <a href="example_easingChart2D.html">example_easingChart2D.html</a> 
+	</p>	
+
+</body>
+</html>
diff --git a/dojox/fx/tests/test_flip.html b/dojox/fx/tests/test_flip.html
new file mode 100644
index 0000000..b278a71
--- /dev/null
+++ b/dojox/fx/tests/test_flip.html
@@ -0,0 +1,531 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.fx.flip | experimental fx add-ons for the Dojo Toolkit</title>
+		
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+	<script type="text/javascript" src="../_base.js"></script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+	    @import "../../../dijit/themes/tundra/tundra.css";
+		.testBox {
+			overflow:hidden;
+            font: 20px arial, sans-serif;
+            line-height:200px;
+            text-align:center;
+            width:300px;
+            height:200px;
+		}
+        .pageContainer{
+            position:relative;
+            border:1px solid #999;
+        }
+        .page{
+            padding:13px;
+            width:200px;
+            height:360px;
+            background:#f0ecec;
+            color:#333;
+            font:11px arial, sans-serif;
+        }
+        table.demoContainer{
+            border-collapse: collapse;
+            margin-top:20px;
+        }
+        table.demoContainer thead th{
+            font: 20px arial, sans-serif;
+            border-bottom:1px solid #999;
+            text-align:center;
+            color: #666;
+        }
+        table.demoContainer thead th.view{
+            border-right:1px solid #999;            
+        }
+        table.demoContainer td.view{
+            border-right: 1px solid #999;
+            width:400px;
+            padding:10px 0px 30px 100px;
+            text-align:center;
+        }
+        div.controls{
+            width:300px;
+            height:200px;
+            margin: 40px 20px 0 20px;
+        }
+        div.topBottom{
+            width:100%;
+            text-align:center;
+        }
+        div.middle{
+            margin:40px 0;
+            width:100%;
+            height:40px;
+            line-height:40px;
+            text-align:center;
+            position:relative;
+        }
+        input.button{
+            border:1px solid #999;
+            color: #333;
+            background: #ddd;
+            padding:5px;
+        }
+    </style>
+	<script type="text/javascript">
+		dojo.require("dojox.fx.flip");
+
+
+		// fx.flip example:
+		var flipinit = function(){
+			dojo.connect(dojo.byId("flipTop"), "onclick", function(e){
+				var anim = dojox.fx.flip({ 
+					node: "flip1",
+					dir: "top",
+					depth: .5,
+					endColor: "#666",
+					duration:400
+				});
+				dojo.connect(anim, "onEnd", this, function(){ 
+					var n = dojo.byId("flip1");
+					n.innerHTML = "TOP";
+                    dojo.style(n, {
+                        color: "#ddd",
+                        background: "#666"
+                    });
+				})
+				anim.play(); 
+			});
+			dojo.connect(dojo.byId("flipRight"), "onclick", function(e){
+				var anim = dojox.fx.flip({ 
+					node: "flip1",
+					dir: "right",
+					depth: .5,
+					endColor: "yellow",
+					duration:400
+				})											  
+				dojo.connect(anim, "onEnd", this, function(){ 
+					var n = dojo.byId("flip1");
+					n.innerHTML = "RIGHT";
+                    dojo.style(n, {
+                        color: "red",
+                        background: "yellow"
+                    });
+				})
+				anim.play(); 
+			});
+			dojo.connect(dojo.byId("flipBottom"), "onclick", function(e){
+				var anim = dojox.fx.flip({ 
+					node: "flip1",
+					dir: "bottom",
+					depth: .5,
+					endColor: "red",
+					duration: 400
+				})											  
+				dojo.connect(anim, "onEnd", this, function(){ 
+					var n = dojo.byId("flip1");
+					n.innerHTML = "BOTTOM";
+                    dojo.style(n, {
+                        color: "yellow",
+                        background: "red"
+                    });
+				})
+				anim.play(); 
+			});
+
+			dojo.connect(dojo.byId("flipLeft"), "onclick", function(e){
+				var anim = dojox.fx.flip({ 
+					node: "flip1",
+					dir: "left",
+					depth: .5,
+					endColor: "blue",
+					duration:400
+				});		
+													  
+				dojo.connect(anim, "onEnd", this, function(){ 
+                    var n = dojo.byId("flip1");
+					n.innerHTML = "LEFT";
+                    dojo.style(n, {
+                        color: "white",
+                        background: "blue"
+                    });
+				});
+				anim.play(); 
+			});
+		};
+
+        // fx.flip, half flip example:
+        var halfflipinit = function(){
+            dojo.connect(dojo.byId("halfflipreset"), "onclick", function(){
+                dojo.style(dojo.byId("hflip1"), {
+                    visibility: "hidden"
+                });
+            });
+            dojo.connect(dojo.byId("halfflip"), "onclick", function(e){
+                var anim = dojox.fx.flip({
+                    node: "hflip1",
+                    dir: "top",
+                    shift: -150,
+                    whichAnim: "last",
+                    depth: .5,
+                    endColor: "#666",
+                    duration: 1000
+                })
+                dojo.connect(anim, "onEnd", this, function(){
+                    var n = dojo.byId("hflip1");
+                })
+                anim.play();
+            });
+        };
+
+		// fx.flipCube example:
+		var cubeinit = function(){
+			dojo.connect(dojo.byId("cflipTop"), "onclick", function(e){
+				var anim = dojox.fx.flipCube({ 
+					node: dojo.byId("cflip1"),
+					dir: "top",
+					endColor: "#666666",
+					duration:500
+				});
+				dojo.connect(anim, "onEnd", this, function(){
+                    var n = dojo.byId("cflip1");
+					n.innerHTML = "TOP";
+                    dojo.style(n, {
+                        color: "#ddd",
+                        background: "#666"
+                    });
+				});											  
+				anim.play(); 
+			});
+			dojo.connect(dojo.byId("cflipRight"), "onclick", function(e){
+				var anim = dojox.fx.flipCube({ 
+					node: dojo.byId("cflip1"),
+					dir: "right",
+					endColor: "yellow",
+					duration:500
+				});											  
+				dojo.connect(anim, "onEnd", this, function(){ 
+                    var n = dojo.byId("cflip1");
+					n.innerHTML = "RIGHT";
+                    dojo.style(n, {
+                        color: "red",
+                        background: "yellow"
+                    });
+				});											  
+				anim.play(); 
+			});
+			dojo.connect(dojo.byId("cflipBottom"), "onclick", function(e){
+				var anim = dojox.fx.flipCube({ 
+					node: dojo.byId("cflip1"),
+					dir: "bottom",
+					endColor: "red",
+					duration: 500
+				});											  
+				dojo.connect(anim, "onEnd", this, function(){ 
+                    var n = dojo.byId("cflip1");
+					n.innerHTML = "BOTTOM";
+                    dojo.style(n, {
+                        color: "yellow",
+                        background: "red"
+                    });
+				});											  
+				anim.play(); 
+			});
+			dojo.connect(dojo.byId("cflipLeft"), "onclick", function(e){
+				var anim = dojox.fx.flipCube({ 
+					node: "cflip1",
+					dir: "left",
+					endColor: "blue",
+					duration: 500
+				});											  
+				dojo.connect(anim, "onEnd", this, function(){ 
+                    var n = dojo.byId("cflip1");
+					n.innerHTML = "LEFT";
+                    dojo.style(n, {
+                        color: "white",
+                        background: "blue"
+                    });
+				});
+				anim.play(); 
+			});
+		};
+
+        // fx.flipGrid example:
+        var gridinit = function(){
+			dojo.connect(dojo.byId("reset"), "onclick", function(e){
+			    dojo.byId("flipGrid").disabled = "";
+			    dojo.style(dojo.byId("gflip1"), {
+					visibility: "visible"
+				});
+			});
+			dojo.connect(dojo.byId("flipGrid"), "onclick", function(e){
+				var anim = dojox.fx.flipGrid({
+					node: dojo.byId("gflip1"),
+					dir: "right",
+					cols: 7,
+					rows: 5,
+					duration:900
+				});
+				dojo.connect(anim, "play", this, function(){
+				    dojo.byId("flipGrid").disabled = "disabled";
+   				});
+				anim.play();
+			});
+        };
+
+        // fx.flipPage example:
+		var currentPage = 0,
+			pages = 4
+		;
+		var pageinit = function(){
+			dojo.connect(dojo.byId("flipPageRight"), "onclick", function(e){
+				var anim = dojox.fx.flipPage({
+					node: dojo.byId("page" + (currentPage + 1)),
+					dir: "left",
+					endColor: "yellow",
+					depth: .3,
+					duration:3000
+				});
+				dojo.connect(anim, "play", this, function(){
+					dojo.byId("page" + (currentPage + 1)).style.display = "none";
+					dojo.byId("page" + ((currentPage + 3) % pages)).style.display = "block";
+				});
+				dojo.connect(anim, "onEnd", this, function(){
+					dojo.byId("page" + currentPage).style.display = "none";
+					dojo.byId("page" + (currentPage + 1)).style.display = "none";
+					currentPage = (currentPage + 2) % pages;
+					dojo.byId("page" + currentPage).style.display = "block";
+					dojo.byId("page" + (currentPage + 1)).style.display = "block";
+				});
+				anim.play();
+			});
+			dojo.connect(dojo.byId("flipPageLeft"), "onclick", function(e){
+				var anim = dojox.fx.flipPage({
+					node: dojo.byId("page" + currentPage),
+					dir: "right",
+					endColor: "blue",
+					depth: .3,
+					duration:3000
+				});
+				dojo.connect(anim, "play", this, function(){
+					dojo.byId("page" + (currentPage) % pages).style.display = "none";
+					dojo.byId("page" + ((currentPage + 2) % pages)).style.display = "block";
+				});
+				dojo.connect(anim, "onEnd", this, function(){
+					dojo.byId("page" + currentPage).style.display = "none";
+					dojo.byId("page" + (currentPage + 1)).style.display = "none";
+					currentPage = (currentPage + 2) % pages;
+					dojo.byId("page" + currentPage).style.display = "block";
+					dojo.byId("page" + (currentPage + 1)).style.display = "block";
+				});
+				anim.play();
+			});
+		};
+
+		dojo.addOnLoad(flipinit);
+        dojo.addOnLoad(halfflipinit);
+		dojo.addOnLoad(cubeinit);
+		dojo.addOnLoad(gridinit);
+		dojo.addOnLoad(pageinit);
+	</script>
+</head>
+<body class="tundra">
+	    <table class="demoContainer">
+            <thead>
+                <tr><th class="view">dojox.fx.flip test</th><th></th></tr>
+            </thead>
+            <tbody>
+            <tr>
+                <td class="view">
+                    <div style="width:300px;height:200px;background:#666;color:#ddd;" id="flip1" class="testBox">
+                        dojox.fx.flip
+                    </div>
+                </td>
+                <td>
+                    <div class="controls">
+                        <div class="topBottom"><input type="button" class="button" style="margin:auto" id="flipTop" value="flip top" /></div>
+                        <div class="middle">
+                            <div style="position:absolute;margin:auto;right:0;top:0"><input type="button" class="button" id="flipRight" value="flip right" /></div>
+                            controls
+                            <div style="position:absolute;margin:auto;left:0;top:0"><input type="button" class="button" id="flipLeft" value="flip left" /></div>
+                        </div>
+                        <div class="topBottom"><input type="button" class="button" id="flipBottom" value="flip bottom" /></div>
+                    </div>
+                </td>
+            </tr>
+            </tbody>
+            <thead>
+                <tr><th class="view">dojox.fx.flip test - half flip</th><th></th></tr>
+            </thead>
+            <tbody>
+            <tr>
+                <td class="view">
+                    <div style="width:300px;height:200px;background:#666;color:#ddd;visibility:hidden" id="hflip1" class="testBox">
+                        WOOT!
+                    </div>
+                </td>
+                <td>
+                    <div class="controls">
+                        <div class="middle">
+                            <div style="position:absolute;left:60px;top:0"><input type="button" class="button" id="halfflip" value="half flip" /></div>
+                            <div style="position:absolute;right:60px;top:0"><input type="button" class="button" id="halfflipreset" value="reset" /></div>
+                        </div>
+                    </div>
+                </td>
+            </tr>
+            </tbody>
+            <thead>
+                <tr><th class="view">dojox.fx.flipCube test</th><th></th></tr>
+            </thead>
+            <tbody>
+            <tr>
+                <td class="view">
+                    <div style="width:300px;height:200px;background:#666;color:#ddd" id="cflip1" class="testBox">
+                        dojox.fx.flipCube
+                    </div>
+                </td>
+                <td>
+                    <div class="controls">
+                        <div class="topBottom"><input type="button" class="button" style="margin:auto" id="cflipTop" value="flip top" /></div>
+                        <div class="middle">
+                            <div style="position:absolute;margin:auto;right:0;top:0"><input type="button" class="button" id="cflipRight" value="flip right" /></div>
+                            controls
+                            <div style="position:absolute;margin:auto;left:0;top:0"><input type="button" class="button" id="cflipLeft" value="flip left" /></div>
+                        </div>
+                        <div class="topBottom"><input type="button" class="button" id="cflipBottom" value="flip bottom" /></div>
+                    </div>
+                </td>
+            </tr>
+            </tbody>
+            <thead>
+                <tr><th class="view">dojox.fx.flipGrid test</th><th></th></tr>
+            </thead>
+            <tbody>
+            <tr>
+                <td class="view">
+                    <div style="width:300px;height:200px;background:#666;color:#ddd" id="gflip1" class="testBox">
+                        dojox.fx.flipGrid
+                    </div>
+                <td>
+                <div class="controls">
+                    <div class="middle">
+                        <div style="position:absolute;left:60px;top:0"><input type="button" class="button" id="flipGrid" value="flip grid" /></div>
+                        <div style="position:absolute;right:60px;top:0"><input type="button" class="button" id="reset" value="reset" /></div>
+                    </div>
+                </div>
+                </td>
+            </tr>
+            </tbody>
+            <thead>
+                <tr><th class="view">dojox.fx.flipPage test</th><th></th></tr>
+            </thead>
+            <tbody>
+            <tr>
+                <td class="view" style="padding-left:20px">
+                    <table style="height:300px; width:400px; border-collapse:collapse">
+                        <tbody>
+                            <tr>
+                                <td>
+                                    <div id="pageContainer0" class="pageContainer">
+                                        <div style="display:none" id="page2" class="page">
+                                            Ed una lupa, che di tutte brame
+                                            sembiava carca ne la sua magrezza,
+                                            e molte genti fé già viver grame,
+                                            questa mi porse tanto di gravezza
+                                            con la paura ch'uscia di sua vista,
+                                            ch'io perdei la speranza de l'altezza.
+                                            E qual è quei che volontieri acquista,
+                                            e giugne 'l tempo che perder lo face,
+                                            che 'n tutt'i suoi pensier piange e s'attrista;
+                                            tal mi fece la bestia sanza pace,
+                                            che, venendomi 'ncontro, a poco a poco
+                                            mi ripigneva là dove 'l sol tace.
+                                            Mentre ch'i' rovinava in basso loco,
+                                            dinanzi a li occhi mi si fu offerto
+                                            chi per lungo silenzio parea fioco.
+                                            Quando vidi costui nel gran diserto,
+                                            «Miserere di me», gridai a lui,
+                                            «qual che tu sii, od ombra od omo certo!».
+                                            Rispuosemi: «Non omo, omo già fui,
+                                            e li parenti miei furon lombardi,
+                                            mantoani per patria ambedui.
+                                            Nacqui sub Iulio, ancor che fosse tardi,
+                                            e vissi a Roma sotto 'l buono Augusto
+                                            nel tempo de li dèi falsi e bugiardi.
+                                            Poeta fui, e cantai di quel giusto [...]
+                                        </div>
+                                        <div class="page" id="page0">
+                                            Nel mezzo del cammin di nostra vita
+                                            mi ritrovai per una selva oscura
+                                            ché la diritta via era smarrita.
+                                            Ahi quanto a dir qual era è cosa dura
+                                            esta selva selvaggia e aspra e forte
+                                            che nel pensier rinova la paura!
+                                            Tant'è amara che poco è più morte;
+                                            ma per trattar del ben ch'i' vi trovai,
+                                            dirò de l'altre cose ch'i' v'ho scorte.
+                                            Io non so ben ridir com'i' v'intrai,
+                                            tant'era pien di sonno a quel punto
+                                            che la verace via abbandonai.
+                                            Ma poi ch'i' fui al piè d'un colle giunto,
+                                            là dove terminava quella valle
+                                            che m'avea di paura il cor compunto,
+                                            guardai in alto, e vidi le sue spalle
+                                            vestite già de' raggi del pianeta
+                                            che mena dritto altrui per ogne calle.
+                                            Allor fu la paura un poco queta
+                                            che nel lago del cor m'era durata
+                                            la notte ch'i' passai con tanta pieta.
+                                            E come quei che con lena affannata
+                                            uscito fuor del pelago a la riva
+                                            si volge a l'acqua perigliosa e guata,
+                                            così l'animo mio, ch'ancor fuggiva,
+                                        </div>
+                                    </div>
+                                </td>
+                                <td>
+                                    <div id="pageContainer1" class="pageContainer">
+                                        <div style="display:none;" id="page3" class="page"></div>
+                                        <div id="page1" class="page">
+                                            si volse a retro a rimirar lo passo
+                                            che non lasciò già mai persona viva.
+                                            Poi ch'èi posato un poco il corpo lasso,
+                                            ripresi via per la piaggia diserta,
+                                            sì che 'l piè fermo sempre era 'l più basso.
+                                            Ed ecco, quasi al cominciar de l'erta,
+                                            una lonza leggera e presta molto,
+                                            che di pel macolato era coverta;
+                                            e non mi si partia dinanzi al volto,
+                                            anzi 'mpediva tanto il mio cammino,
+                                            ch'i' fui per ritornar più volte vòlto.
+                                            Temp'era dal principio del mattino,
+                                            e 'l sol montava 'n sù con quelle stelle
+                                            ch'eran con lui quando l'amor divino
+                                            mosse di prima quelle cose belle;
+                                            sì ch'a bene sperar m'era cagione
+                                            di quella fiera a la gaetta pelle
+                                            l'ora del tempo e la dolce stagione;
+                                            ma non sì che paura non mi desse
+                                            la vista che m'apparve d'un leone.
+                                            Questi parea che contra me venisse
+                                            con la test'alta e con rabbiosa fame,
+                                            sì che parea che l'aere ne tremesse.
+                                        </div>
+                                    </div>
+                                </td>
+                            </tr>
+                    </tbody>
+                    </table>
+                </td>
+                <td>
+                    <div class="middle">
+                        <div style="position:absolute;left:30px;top:0"><input type="button" class="button" value="previous page" id="flipPageLeft" /></div>
+                        <div style="position:absolute;right:30px;top:0"><input type="button" class="button" id="flipPageRight" value="next page" /></div>
+                    </div>
+                </td>
+            </tr>
+            </tbody>
+	    </table>
+
+</body>
+</html>
diff --git a/dojox/fx/tests/test_highlight.html b/dojox/fx/tests/test_highlight.html
new file mode 100644
index 0000000..1d5947e
--- /dev/null
+++ b/dojox/fx/tests/test_highlight.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.fx.highlight</title>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+	<script type="text/javascript">	
+		dojo.require("dojox.fx");
+		dojo.require("dojox.fx.ext-dojo.NodeList"); 
+	</script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">dojox.fx.highlight tests</h1>
+
+	<div id="attention" style="position:absolute; left:300px; top:200px; padding:10px;" >
+		<h3>This is the default highlight</h3>
+	</div>
+
+	<div id="attention2" style="position:absolute; left:300px; top:80px; padding:10px;" >
+		<h3>BRING ATTENTION HERE!</h3>
+	</div>
+
+	<div id="attention3"  style="position:absolute; left:350px; top:150px; padding:10px; background-color:#CCCCCC" >
+		<h3>Highlight me</h3>
+	</div>
+
+	<a href="javascript:void(0)" onClick="dojox.fx.highlight({node:'attention'}).play()">test #1 (default)</a>
+    <br>
+	<a href="javascript:void(0)" onClick="dojox.fx.highlight({node:'attention', repeat:1}).play()">test #2 (default - play twice)</a>
+	<br>
+	<a href="javascript:void(0)" onClick="dojox.fx.highlight({node:'attention2', color:'#0066FF', duration:800}).play()">test #3</a>
+    <br>
+	<a href="javascript:void(0)" onClick="dojox.fx.highlight({node:'attention3', color:'#0066FF', duration:800}).play()">test #4</a>
+    <br>
+	<a href="javascript:void(0)" onClick="dojo.query('a').highlight().play(100)">highlight via dojo.query</a>
+
+
+</body></html>
diff --git a/dojox/fx/tests/test_reverse.html b/dojox/fx/tests/test_reverse.html
new file mode 100644
index 0000000..941e455
--- /dev/null
+++ b/dojox/fx/tests/test_reverse.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+    "http://www.w3.org/TR/html4/strict.dtd"
+    >
+<html lang="en">
+<head>
+    <title>Test dojox.fx.ext-dojo.reverse</title>
+	<style>
+		@import "../../../dijit/tests/css/dijitTests.css";
+		body{
+			font-family:sans-serif;
+		}
+		p{
+			width:700px;
+			font-size:12px;
+		}
+		.wrap{
+			
+		}
+		.lft{
+			width:300px;
+			height:300px;
+			border:1px solid #666;
+			position:relative;
+			float:left;
+		}
+		#ball{
+			width:50px;
+			height:50px;
+			margin:0px auto;
+			top:125px;
+			position:relative;
+			border:1px solid #000;
+			background:#0000ff;
+		}
+		
+	</style>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+		<script>
+			dojo.require("dojox.fx.ext-dojo.reverse");
+			dojo.addOnLoad(function(){
+				var ani = dojo.animateProperty({
+					node:dojo.byId("ball"),
+					duration:1000,
+					easing:dojo.fx.easing.bounceOut,
+					properties:{
+						width:{
+							start:50,
+							end:150,
+							units:"px"
+						},
+						height:{
+							start:50,
+							end:150,
+							units:"px"
+						},
+						top:{
+							start:125,
+							end:75,
+							units:"px"
+						},
+						opacity:{
+							start:1,
+							end:.2
+						},
+						backgroundColor:{
+							start:"#0000ff",
+							end:"#ff0000"
+						}
+					}
+				});
+				ani.play();
+				
+				dojo.connect(dojo.byId("btn"), "click", function(){
+					ani.reverse();
+				})
+			});
+			
+		</script>
+</head>
+<body>
+    <h1>Test dojo.fx.reverse</h1>
+	<p>
+		This is a test for the dojo.Animation extension, dojox.fx.ext-dojo.reverse.
+		To use, simply require <em>dojox.fx.ext-dojo.reverse</em> and a reverse() method
+		will be added to all dojo.Animations.
+	</p>
+	<p>
+		dojox.fx.ext-dojo.reverse can be used at any time during the animation. It does not
+		need to be called when it ends. It also reverses the easing — if dojo.fx.easing.quadIn
+		is used, dojo.fx.easing.quadOut will be used when animating backwards.
+	</p>
+	<button id="btn">Reverse</button>
+	<div class="wrap">
+		<div class="lft">
+			<div id="ball"></div>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/fx/tests/test_scroll.html b/dojox/fx/tests/test_scroll.html
new file mode 100644
index 0000000..c4d7712
--- /dev/null
+++ b/dojox/fx/tests/test_scroll.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.fx.scroll</title>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	<!-- <script type="text/javascript" src="../scroll.js"></script> -->
+	<script type="text/javascript">	
+		dojo.require("dojo.fx.easing"); 
+		dojo.require("dojox.fx.scroll");
+
+		function gotoName(name){
+			// summary; searches for a <a name=""></a> attrib, and scrolls to it
+			dojo.query('a[name="'+name+'"]').forEach(function(node){
+				// first one wins
+				var anim = dojox.fx.smoothScroll({
+					node: node,
+					win:window,
+					duration:300,
+					easing:dojo.fx.easing.easeOut
+				}).play();
+				return;
+			});
+		}
+
+		dojo.addOnLoad(function(){
+			/*dojo.connect(dojo.byId("goToHeader0"), "onclick", function (e) {
+				var h2s = dojo.html.iframeContentDocument(dojo.byId("embed0")).getElementsByTagName('h2');
+				var h2 = h2s[h2s.length-1];
+				var anm = new dojo.lfx.smoothScroll(h2,dojo.html.iframeContentWindow(dojo.byId("embed0")),null,500);
+				anm.play();
+			});
+			*/
+
+			dojo.connect(dojo.byId("goToHeader"), "onclick", function (e) {
+				var node = dojo.byId('targetHeader3');
+				var anim0 = dojox.fx.smoothScroll({ node: node, win: window, duration:500, easing:dojo.fx.easing.easeOut });
+				anim0.play();
+			});
+
+			dojo.connect(dojo.byId("goToHeader1"), "onclick", function(/* Event */e){
+				var node = dojo.byId('targetHeader1');
+				var anim0 = dojox.fx.smoothScroll({ node: node, win: window, duration:1000, easing:dojo.fx.easing.easeOut });
+				anim0.play();
+			});
+		}); 
+	</script>
+</head>
+<body class="tundra">
+
+	<a name="top"></a>
+	<h1 class="testTitle">dojox.fx.scroll tests</h1>
+
+	<div id="targetHeader3" style="position:absolute; left:0px; top:3000px; padding:100px;" ><h3>YOU FOUND ME!</h3>
+	<p>neat.</p>
+	</div>
+
+	<p>dojox.fx.scroll provides:</p>
+	<ul>
+	   <li>dojox.fx.smoothScroll()</li>
+	</ul>
+	<p>
+	which will create and return a dojo.Animation to scroll 
+	a window to a desired offset. (or a node that has overflow:auto/hidden, if you pass the domNode as the win: argument)
+	</p> 
+	
+	
+	<h2><code>getScroll</code></h2>
+	<p>
+	Scroll top: <span id="scrollTop">0</span><br>
+	Scroll left: <span id="scrollLeft">0</span>
+	</p>
+
+	<table style="position:fixed;top:20px;right:20px;">
+	<tr><td>
+		<!-- <input type="button" id="goToHeader0" value="scroll only the iframe (to a node in iframe)"><br> -->
+		<input type="button" id="goToHeader" value="scroll to to far node"><br>
+		<input type="button" id="goToHeader1" value="scroll to a node in top window">
+	</td></tr>
+	</table>
+
+	<p style="font:10pt Arial,sans-serif; color:#666;">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis. Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitaerisus.</p><p style="font:10pt Arial,sans-serif; color:#666;">Lorem ipsum dolor sit amet, consectet [...]
+
+
+	<h2 id='targetHeader1'><code>getElementsByClass</code></h2>
+
+	<p style="font:10pt Arial,sans-serif; color:#666;">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis. Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitaerisus.</p><p style="font:10pt Arial,sans-serif; color:#666;">Lorem ipsum dolor sit amet, consectet [...]
+
+	<h3 id='targetHeader2'>ContainsAny</h3>
+	<input type="button" onclick="gotoName('top');" value="back to top">
+	<p style="font:10pt Arial,sans-serif; color:#666;">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis. Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitaerisus.</p><p style="font:10pt Arial,sans-serif; color:#666;">Lorem ipsum dolor sit amet, consectet [...]
+
+
+</body></html>
diff --git a/dojox/fx/tests/test_sizeTo.html b/dojox/fx/tests/test_sizeTo.html
new file mode 100644
index 0000000..ba4df7f
--- /dev/null
+++ b/dojox/fx/tests/test_sizeTo.html
@@ -0,0 +1,171 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.fx.sizeTo | experimental fx add-ons for the Dojo Toolkit</title>
+		
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+	<script type="text/javascript" src="../_base.js"></script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+				.testBox {
+						position:absolute;
+						top:0; left:0;
+						width:50px;
+						height:50px;
+						background:#ededed;
+						border:1px solid #b7b7b7;
+						-moz-border-radius:6pt;
+						-webkit-border-radius:5pt;
+						overflow:hidden; 
+				}
+	</style>
+		<script type="text/javascript">
+		
+	dojo.require("dojox.fx.ext-dojo.NodeList"); 
+
+		var test1 = function(e){
+			// this is our click test,
+			dojox.fx.sizeTo({
+					node: e.target,
+					width: 120,
+					height:120,
+					duration:250
+			}).play(5);
+		};
+		
+		var testundo = function(e){
+			dojox.fx.sizeTo({
+					node: e.target,
+					width:50,
+					height:50,
+					duration:320
+			}).play(5);
+				
+		};
+		
+		var test2 = function(e){
+			dojox.fx.sizeTo({
+				  node: e.target,
+				  width: 120,
+				  height:120,
+				  duration:120,
+				  method:"combine"
+			}).play(5);
+		};
+
+		var noIdTest = function(){
+			var myNode = dojo.query(".noIdHere")[0]; // first one wins
+			if(myNode){
+					// mmm, fake events (all we're using is the target anyway ... ) 
+					(!dojo.hasClass(myNode,"testRun") ? test2 : testundo)({ target: myNode });
+					dojo.toggleClass(myNode,"testRun");
+			}
+		};
+		
+		var resizeTest = function(e){
+			
+			// this is our click test,
+			var animation = dojox.fx.sizeTo({
+				node: e.target,
+				width: 30,
+				height:30,
+				duration:1250,
+				method:"combine"
+			});
+
+			dojo.style(e.target, {
+				width:"500px",
+				top:0, left:0, 
+				height:"500px"
+			});
+
+			setTimeout(dojo.hitch(animation, "play"), 1250);
+		};
+
+		var init = function(){
+			
+			// lets setup out connections, etc ...
+			dojo.connect(dojo.byId("sizer1"),"onmousedown","test1");
+			dojo.connect(dojo.byId("sizer1"),"onmouseup","testundo"); // generic resest 
+
+			// did you know dojo normalizes onmouseenter onmouseleave!?!? neat. ie got _one_ thing right.
+			dojo.connect(dojo.byId("sizer2"),"onmouseenter","test2");
+			dojo.connect(dojo.byId("sizer2"),"onmouseout","testundo");		   
+			
+			dojo.connect(dojo.byId("testNodeCache"), "onclick", "resizeTest");
+			
+			// example using dojo.query to get a couple of nodes and roll into one anim
+			var hasRun = false; 
+			dojo.connect(dojo.byId("sizer3"),"onclick",function(e){
+				var _anims = []; 
+				dojo.query(".testBox").forEach(function(n){
+					_anims.push(
+						dojox.fx.sizeTo({ node: n,
+							width: ( hasRun ? "50" : "150"),
+							height: ( hasRun ? "50" : "150"),
+							method:"chain",
+							duration:720
+						})
+					);		  
+				});
+				hasRun=!hasRun; 
+				var anim = dojo.fx.combine(_anims);
+				anim.play(); 
+			});
+		};
+		dojo.addOnLoad(init);
+		
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">dojox.fx.sizeTo test</h1>
+		
+		<p>quick sizeTo API overview:</p>
+
+		<pre>
+		dojox.fx.sizeTo({
+				// basic requirements:
+				node: "aDomNodeId", // or a domNode reference
+				width: 200, // measured in px
+				height: 200, // measured in px
+				method: "chain" // is default, or "combine"
+		});
+		</pre>
+		<p>
+		little test blocks (works in FF/win/mac + ie6) <a href="javascript:void(0)" onClick="dojo.query('.testBox').sizeTo({ width: 200, height: 200, duration:400 }).play()">dojo.query() test</a>
+		</p>
+
+		<div style="position:relative; height:60px; width:600px; margin:0 auto;">
+			<div id="sizer1" class="testBox">
+			mouse down / mouse up
+			</div>
+			<div id="sizer2" class="testBox" style="left:60px;" >
+			hover / exit
+			</div>
+			<div class="testBox noIdHere" style="left:120px; ">
+			<a href="javascript:noIdTest()">noIdTest()</a>
+			</div>
+			<div class="testBox" id="sizer3" style="left:180px;">
+			all of em'
+			</div>
+		</div>
+		<br style="clear:both;">
+		
+		(click the box labeled "all of em'" again to reset all nodes)
+				
+	HTML AFTER
+	<br>
+
+	<div style="position:relative; height:110px; width:600px; margin:0 auto;">
+		<div id="testNodeCache"	class="testBox" style="top: 0px; left: 0px; z-index: 1; height:90px; width:90px; margin:0 auto; background-color: black; color:#fff">This box moves when clicked to test parameter caching
+		</div>
+	</div>
+
+	<p>That's all, Folks!</p>
+
+</body>
+</html>
diff --git a/dojox/fx/tests/test_slideBy.html b/dojox/fx/tests/test_slideBy.html
new file mode 100644
index 0000000..a1a1960
--- /dev/null
+++ b/dojox/fx/tests/test_slideBy.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.fx - animation sets to use!</title>
+		
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+	<script type="text/javascript" src="../_base.js"></script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		
+		#sizeToTest {
+			position:absolute;
+			top:0;
+			left:300px; 
+			border:2px solid #ededed; 
+			width:50px; height:50px; 
+			background:#fff; 
+			text-align:center; 
+		}	
+		.test { width:100px; height:50px; border:3px solid #333; 
+			position:absolute; 
+		} 
+		.box1 { top:20px; left:10px; }
+		.box2 { top:85px; left:10px; }
+		.box3 { top:170px; left:10px; } 
+		.holder { position:relative; height:300px; } 
+
+	</style>
+	<script type="text/javascript">
+		dojo.require("dojox.fx.ext-dojo.NodeList"); 
+
+		function chainTest(){
+			// FIXME: not recalculating mixin in init? or not re-mixing, rather. 
+			// happens to a lot of propertyAnimations, actually when chaining, with a
+			// fixed 'start' property in the mixin. see _base/fx.js:slideBy() 
+			dojo.fx.chain([
+				dojox.fx.slideBy({ node: 'sizeToTest', top:50, left:50, duration:400 }),
+				dojox.fx.slideBy({ node: 'sizeToTest', top:25, left:-25, duration:400 })
+			]).play();
+		}
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">dojox.fx.slideBy test</h1>
+
+	<a href="#" onclick="javascript:dojox.fx.slideBy({node:'sizeToTest', top:50,  left:50,  duration:200 }).play()">top: 50, left:50</a>
+	<a href="#" onclick="javascript:dojox.fx.slideBy({node:'sizeToTest', top:-50, left:50,  duration:400 }).play()">top:-50, left:50</a>
+	<a href="#" onclick="javascript:dojox.fx.slideBy({node:'sizeToTest', top:-50, left:-50, duration:400 }).play()">top:-50, left:-50</a>
+	<a href="#" onclick="javascript:dojox.fx.slideBy({node:'sizeToTest', top:50,  left:-50, duration:400 }).play()">top:50, left:-50</a>
+	<a href="#" onclick="javascript:dojo.query('.test').slideBy({ top:0, left:300 }).play()">dojo.query()</a>
+	<a href="#" onclick="javascript:chainTest()">chainTest</a>
+
+	<div id="sizeToTest">
+	lorem. ipsum. 
+	</div>
+
+	<br style="clear:both;">
+
+	<div class="holder">
+		<div class="test box1">a</div><div class="test box2">b</div><div class="test box3">c</div>
+	</div>
+
+
+	HTML AFTER
+	<br>
+
+
+
+</body>
+</html>
diff --git a/dojox/fx/tests/test_split.html b/dojox/fx/tests/test_split.html
new file mode 100644
index 0000000..26550a5
--- /dev/null
+++ b/dojox/fx/tests/test_split.html
@@ -0,0 +1,443 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Gruppler's Effect Demos</title>
+
+	<link rel="stylesheet" href="../../../dijit/tests/css/dijitTests.css" />
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad:true, isDebug:false"></script>
+		
+	<script type="text/javascript">
+		dojo.require("dojox.fx.split");
+
+		var intro1, intro2;
+		var currentAnimation;
+		var originalText;
+
+		var init = function(){
+			
+			// Intro //
+			dojo.style("header1", { "opacity":0, "visibility":"visible" });
+			intro1 = dojox.fx.build({
+				node: "header1",
+				duration: 2000,
+				rows: 8,
+				columns: 1,
+				interval: 125
+			});
+
+			intro1.play();
+			// Split Effects //
+			dojo.connect(dojo.byId("box_blockfade_1"), "onclick", null,
+				function(){
+					var node = dojo.byId("box_blockfade_1");
+					if(parseFloat(node.style.opacity) < 1){
+						return false;
+					}
+					var properties = {
+						node: node,
+						rows: 1,
+						columns: 10
+					};
+					properties.onEnd = function(){
+						currentAnimation = dojox.fx.blockFadeIn(dojo.mixin(properties, {onEnd: undefined}));
+						currentAnimation.play();
+					};
+					currentAnimation = dojox.fx.blockFadeOut(properties);
+					currentAnimation.play();
+
+					/*
+					// This is how we /should/ be able to do it...
+					dojo.fx.chain([
+						dojox.fx.blockFadeOut(properties),
+						dojox.fx.blockFadeIn(properties)
+					]).play();
+					*/
+				}
+			);
+			dojo.connect(dojo.byId("box_blockfade_2"), "onclick", null,
+				function(){
+					var node = dojo.byId("box_blockfade_2");
+					if(parseFloat(dojo.style(node,"opacity")) < 1){
+						return false;
+					}
+					var properties = {
+						node: node,
+						random: 0.25,
+						reverseOrder: true
+					};
+					properties.onEnd = function(){
+						currentAnimation = dojox.fx.blockFadeIn(dojo.mixin(properties, {onEnd: undefined}));
+						currentAnimation.play();
+					};
+					currentAnimation = dojox.fx.blockFadeOut(properties);
+					currentAnimation.play();
+				}
+			);
+
+			dojo.connect(dojo.byId("box_disintegrate_1"), "onclick", null,
+				function(){
+					var node = dojo.byId("box_disintegrate_1");
+					if(parseFloat(dojo.style(node,"opacity")) < 1){
+						return false;
+					}
+					var properties = {
+						node: node,
+						distance: 1,
+						crop: true,
+						fade: false
+					};
+					properties.onEnd = function(){
+						currentAnimation = dojox.fx.build(dojo.mixin(properties, {onEnd: undefined}));
+						currentAnimation.play();
+					};
+					currentAnimation = dojox.fx.disintegrate(properties);
+					currentAnimation.play();
+				}
+			);
+
+			dojo.connect(dojo.byId("box_disintegrate_2"), "onclick", null,
+				function(){
+					var node = dojo.byId("box_disintegrate_2");
+					if(parseFloat(dojo.style(node,"opacity")) < 1){
+						return false;
+					}
+					var properties = {
+						node: node,
+						random: 0.5,
+						distance: 2.5
+					};
+					properties.onEnd = function(){
+						currentAnimation = dojox.fx.build(dojo.mixin(properties, {onEnd: undefined}));
+						currentAnimation.play();
+					};
+					currentAnimation = dojox.fx.disintegrate(properties);
+					currentAnimation.play();
+				}
+			);
+
+			dojo.connect(dojo.byId("box_explode_1"), "onclick", null,
+				function(){
+					var node = dojo.byId("box_explode_1");
+					if(parseFloat(dojo.style(node,"opacity")) < 1){
+						return false;
+					}
+					var properties = {
+						node: node,
+						rows: 2,
+						columns: 2,
+						distance: 0.75,
+						easing: dojo.fx.easing.elasticOut,
+						fade: false,
+						crop: true
+					};
+					properties.onEnd = function(){
+						currentAnimation = dojox.fx.converge(dojo.mixin(properties,
+						{
+							onEnd: undefined,
+							easing: dojo.fx.easing.bounceOut
+						}));
+						currentAnimation.play()
+					};
+					currentAnimation = dojox.fx.explode(properties);
+					currentAnimation.play();
+				}
+			);
+
+			dojo.connect(dojo.byId("box_explode_2"), "onclick", null,
+				function(){
+					var node = dojo.byId("box_explode_2");
+					if(parseFloat(dojo.style(node,"opacity")) < 1){
+						return false;
+					}
+					var properties = {
+						node: node,
+						rows: 5,
+						columns: 5,
+						distance: 1.5,
+						duration: 1500,
+						random: 0.75
+					};
+					properties.onEnd = function(){
+						currentAnimation = dojox.fx.converge(dojo.mixin(properties, {onEnd: undefined}));
+						currentAnimation.play();
+					};
+					currentAnimation = dojox.fx.explode(properties);
+					currentAnimation.play();
+				}
+			);
+
+			dojo.connect(dojo.byId("box_shear_1"), "onclick", null,
+				function(){
+					var node = dojo.byId("box_shear_1");
+					if(parseFloat(dojo.style(node,"opacity")) < 1){
+						return false;
+					}
+					var properties = {
+						node: node,
+						interval: 50,
+						distance: 0.95,
+						rows: 10,
+						columns: 1,
+						fade: false,
+						crop: true,
+						reverseOrder: true
+					};
+					properties.onEnd = function(){
+						currentAnimation = dojox.fx.unShear(dojo.mixin(properties, {onEnd: undefined}));
+						currentAnimation.play();
+					};
+					currentAnimation = dojox.fx.shear(properties);
+					currentAnimation.play();
+				}
+			);
+
+			dojo.connect(dojo.byId("box_shear_2"), "onclick", null,
+				function(){
+					var node = dojo.byId("box_shear_2");
+					if(parseFloat(dojo.style(node,"opacity")) < 1){
+						return false;
+					}
+					var properties = {
+						node: node,
+						random: 1
+					};
+					properties.onEnd = function(){
+						currentAnimation = dojox.fx.unShear(dojo.mixin(properties, {onEnd: undefined}));
+						currentAnimation.play();
+					};
+					currentAnimation = dojox.fx.shear(properties);
+					currentAnimation.play();
+				}
+			);
+
+			dojo.connect(dojo.byId("box_pinwheel_1"), "onclick", null,
+				function(){
+					var node = dojo.byId("box_pinwheel_1");
+					if(parseFloat(dojo.style(node,"opacity")) < 1){
+						return false;
+					}
+					var properties = {
+						node: node,
+						fade: false
+					};
+					properties.onEnd = function(){
+						currentAnimation = dojox.fx.unPinwheel(dojo.mixin(properties, {onEnd: undefined}));
+						currentAnimation.play();
+					};
+					currentAnimation = dojox.fx.pinwheel(properties);
+					currentAnimation.play();
+				}
+			);
+
+			dojo.connect(dojo.byId("box_pinwheel_2"), "onclick", null,
+				function(){
+					var node = dojo.byId("box_pinwheel_2");
+					if(parseFloat(dojo.style(node,"opacity")) < 1){
+						return false;
+					}
+					var properties = {
+						node: node,
+						random: 1,
+						rows: 5,
+						columns: 5
+					};
+					properties.onEnd = function(){
+						currentAnimation = dojox.fx.unPinwheel(dojo.mixin(properties, {onEnd: undefined}));
+						currentAnimation.play();
+					};
+					currentAnimation = dojox.fx.pinwheel(properties);
+					currentAnimation.play();
+				}
+			);
+		} // end init
+		dojo.addOnLoad(init);
+	</script>
+
+	<style type="text/css">
+		h1 {
+			margin: 0;
+	  	}
+
+		hr {
+		}
+
+	  hr.thick {
+	  }
+
+	  .box {
+		height: 100px;
+		width: 100px;
+		overflow: visible;
+	  }
+
+	  .box {
+		color: #292929;
+		border: 1px solid #999;
+		background-color: #ddd;
+		cursor: pointer;
+		overflow: hidden;
+		margin: 0;
+		padding: 0;
+	  }
+
+
+	  .textBox p {
+		width: 100px;
+		height: 100px;
+	  }
+
+	  .box p, .box code {
+		margin: 0;
+		text-align: left;
+	  }
+
+	  .effectList {
+		list-style: none;
+		padding: 0;
+		font-size: 10px;
+		margin: 0;
+	  }
+
+	  .effectList li {
+		float: left;
+		display:block;
+		padding: 1em;
+	  }
+
+	  .vl, .vr {
+		border: 0px dotted #999;
+	  }
+
+	  .vl {
+		border-left-width: 4px;
+	  }
+
+	  .vr {
+		border-right-width: 4px;
+	  }
+	</style>
+</head>
+<body>
+	<h1 id="header1">dojox.fx.split</h1>
+	Each effect is highly configurable.	 Here is a general list of the options available in each effect:
+	<ul>
+		<li>The number of rows and columns in which to split the element</li>
+		<li>The distance the pieces travel (as a multiple of the element's respective dimensions)</li>
+		<li>Whether or not to fade the pieces in/out</li>
+		<li>How much the effect should be randomized (a percentage)</li>
+		<li>Whether or not the pieces should appear outside the element's boundries</li>
+	</ul>
+	<p style="font-weight: bold">
+		Just click each box to play its animation!
+	</p>
+	<hr />
+	<ul class="effectList">
+	  <li>BlockFadeOut,<br />BlockFadeIn uniformly
+		<div id='box_blockfade_1' class="box">
+		  <code>
+			rows: 1<br />
+			columns: 10
+		  </code><hr />
+		  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li class="vr">BlockFadeOut,<br />BlockFadeIn randomly
+		<div id='box_blockfade_2' class="box">
+		  <code>
+			random: 0.25<br />
+			reverseOrder: true
+		  </code><hr />
+		  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li>Disintegrate, Build<br />uniformly (cropped)
+		<div id='box_disintegrate_1' class="box">
+		  <code>
+			distance: 1<br />
+			crop: true<br />
+			fade: false
+		  </code><hr />
+		  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li class="vr">Disintegrate, Build<br />randomly
+		<div id='box_disintegrate_2' class="box">
+		  <code>
+			random: 0.5<br />
+			distance: 2.5
+		  </code><hr />
+		  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li>Explode, Converge<br />uniformly (cropped)
+		<div id='box_explode_1' class="box">
+		  <code>
+			rows: 2<br />
+			columns: 2<br />
+			distance: 0.75<br />
+			fade: false<br />
+			crop: true<br />
+			(custom easing)
+		  </code><hr />
+		  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li class="vr">Explode, Converge<br />randomly
+		<div id='box_explode_2' class="box">
+		  <code>
+			rows: 5<br />
+			columns: 5<br />
+			distance: 1.5<br />
+			duration: 1500<br />
+			random: 0.75
+		  </code><hr />
+		  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li>Shear, UnShear<br />rows (cropped)
+		<div id='box_shear_1' class="box">
+		  <code>
+			interval: 50<br />
+			distance: 0.95<br />
+			rows: 10<br />
+			columns: 1<br />
+			fade: false<br />
+			crop: true<br />
+			reverseOrder: true
+		  </code><hr />
+		  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li class="vr">Shear, UnShear<br />rows and columns
+		<div id='box_shear_2' class="box">
+		  <code>
+			random: 1
+		  </code><hr />
+		  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li>Pinwheel, UnPinwheel<br />uniformly
+		<div id='box_pinwheel_1' class="box">
+		  <code>
+			fade: false
+		  </code><hr />
+		  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+		<li>Pinwheel, UnPinwheel<br />randomly
+		<div id='box_pinwheel_2' class="box">
+		  <code>
+			random: 1<br />
+			rows: 5<br />
+			columns: 5
+		  </code><hr />
+		  <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+		</li>
+	</ul>
+	<div style="height:400px"></div>
+</body>
+</html>
diff --git a/dojox/fx/tests/test_text.html b/dojox/fx/tests/test_text.html
new file mode 100644
index 0000000..ee161cd
--- /dev/null
+++ b/dojox/fx/tests/test_text.html
@@ -0,0 +1,373 @@
+<html>
+<head>
+	
+	<title>dojox.fx Text Effect Tests | The Dojo Toolkit</title>
+
+	<link rel="stylesheet" href="../../../dijit/tests/css/dijitTests.css" />
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad:true, isDebug:false"></script>
+		
+	<script type="text/javascript">
+		dojo.require("dojox.fx.text");
+		dojo.require("dojo.fx.easing");
+
+		var intro1, intro2;
+		var text_blockfade_1, text_blockfade_2;
+		var text_disintegrate_1, text_disintegrate_2
+		var text_explode_1, text_explode_2;
+		var text_backspace_1, text_backspace_2;
+
+		var currentAnimation;
+
+		var originalText;
+		var originalReplacementText = replacementText = "<center><u>This </u><br>is " +
+			"a <br><i>little </i>bit <br>of <br><b>replacement text</b>...</center>";
+
+		var init = function(){
+
+			originalText = dojo.byId("text_blockfade_1").innerHTML;
+			dojo.byId("replacementText").value = replacementText;
+
+			// Intro //
+			intro2 = dojox.fx.text.build({
+				node: "header2",
+				duration: 2500,
+				interval: 80,
+				reverseOrder: true,
+				distance: 3,
+				easing:dojo.fx.easing.backOut, 
+				onPlay: function(){ dojo.style("header2","opacity", 1); }
+			}).play();
+			
+
+			// Text Effects //
+
+			text_blockfade_1 = function(node){
+				if(node.style.height){
+					return false;
+				}
+				var properties = {
+					node: node,
+					words: true
+				};
+				properties.onEnd = function(){
+					currentAnimation = dojox.fx.text.blockFadeIn(dojo.mixin(properties, {
+						onEnd: undefined,
+						text: (replacementText && node.innerHTML != replacementText) ?
+							replacementText :
+							originalText
+					}));
+					currentAnimation.play()
+				};
+				currentAnimation = dojox.fx.text.blockFadeOut(properties);
+				currentAnimation.play();
+			};
+			text_blockfade_2 = function(node){
+				if(node.style.height){
+					return false;
+				}
+				var properties = {
+					node: node,
+					duration: 1500,
+					random: 0.3,
+					reverseOrder: true
+				};
+				properties.onEnd = function(){
+					currentAnimation = dojox.fx.text.blockFadeIn(dojo.mixin(properties, {
+						onEnd: undefined,
+						text: (replacementText && node.innerHTML != replacementText) ?
+							replacementText :
+							originalText
+					}));
+					currentAnimation.play();
+				};
+				currentAnimation = dojox.fx.text.blockFadeOut(properties);
+				currentAnimation.play();
+			};
+
+			text_disintegrate_1 = function(node){
+				if(node.style.height){
+					return false;
+				}
+				var properties = {
+					node: node,
+					words: true,
+					crop: true,
+					distance: 1
+				};
+				properties.onEnd = function(){
+					currentAnimation = dojox.fx.text.build(dojo.mixin(properties, {
+						onEnd: undefined,
+						text: (replacementText && node.innerHTML != replacementText) ?
+							replacementText :
+							originalText
+					}));
+					currentAnimation.play();
+				};
+				currentAnimation = dojox.fx.text.disintegrate(properties);
+				currentAnimation.play();
+			};
+			text_disintegrate_2 = function(node){
+				if(node.style.height){
+					return false;
+				}
+				var properties = {
+					node: node,
+					random: 0.5,
+					distance: 2.5,
+					reverseOrder: true
+				};
+				properties.onEnd = function(){
+					currentAnimation = dojox.fx.text.build(dojo.mixin(properties, {
+						onEnd: undefined,
+						text: (replacementText && node.innerHTML != replacementText) ?
+							replacementText :
+							originalText
+					}));
+					currentAnimation.play();
+				};
+				currentAnimation = dojox.fx.text.disintegrate(properties);
+				currentAnimation.play();
+			};
+
+			text_explode_1 = function(node){
+				if(node.style.height){
+					return false;
+				}
+				var properties = {
+					node: node,
+					distance: 0.5
+				};
+				properties.onEnd = function(){
+					currentAnimation = dojox.fx.text.converge(dojo.mixin(properties,
+					{
+						onEnd: undefined,
+						text: (replacementText && node.innerHTML != replacementText) ?
+							replacementText :
+							originalText
+					}));
+					currentAnimation.play();
+				};
+				currentAnimation = dojox.fx.text.explode(properties);
+				currentAnimation.play();
+			};
+			text_explode_2 = function(node){
+				if(node.style.height){
+					return false;
+				}
+				var properties = {
+					node: node,
+					words: true,
+					distance: 1.5,
+					duration: 1500,
+					random: 0.5,
+					//crop: true
+				};
+				properties.onEnd = function(){
+					currentAnimation = dojox.fx.text.converge(dojo.mixin(properties,{
+						onEnd: undefined,
+						text: (replacementText && node.innerHTML != replacementText) ?
+							replacementText :
+							originalText
+					}));
+					currentAnimation.play();
+				};
+				currentAnimation = dojox.fx.text.explode(properties).play();
+			};
+
+			text_backspace_1 = function(node){
+				if(node.style.height){
+					return false;
+				}
+				var properties = {
+					node: node,
+					duration: 2500,
+					wordDelay: 0,
+					fixed: true
+				};
+				properties.onEnd = function(){
+					currentAnimation = dojox.fx.text.type(dojo.mixin(properties,{
+						onEnd: undefined,
+						text: (replacementText && node.innerHTML != replacementText) ?
+							replacementText :
+							originalText
+					}));
+					currentAnimation.play();
+				};
+				currentAnimation = dojox.fx.text.backspace(properties);
+				currentAnimation.play();
+			};
+			text_backspace_2 = function(node){
+				if(node.style.height){
+					return false;
+				}
+				var properties = {
+					node: node,
+					interval: 40,
+					random: 0.75
+				};
+				properties.onEnd = function(){
+					currentAnimation = dojox.fx.text.type(dojo.mixin(properties,
+					{
+						onEnd: undefined,
+						interval: 200,
+						text: (replacementText && node.innerHTML != replacementText) ?
+							replacementText :
+							originalText
+					}));
+					currentAnimation.play();
+				};
+				currentAnimation = dojox.fx.text.backspace(properties).play();
+			};
+		};
+		dojo.addOnLoad(init);
+	</script>
+	<style type="text/css">
+	  body {
+		font-family: verdana, arial;
+	  }
+
+	  h1 {
+		margin: 0;
+	  }
+
+	  hr {
+		clear: both;
+		border: 0px solid #999;
+		border-top-width: 1px;
+		margin: 0;
+	  }
+
+	  hr.thick {
+		border-top-width: 5px;
+	  }
+
+	  .box, .boxContainer {
+		height: 100px;
+		width: 100px;
+		overflow: visible;
+	  }
+
+	  .box {
+		color: #292929;
+		border: 1px solid #999;
+		background-color: #ddd;
+		cursor: pointer;
+		overflow: hidden;
+		margin: 0;
+		padding: 0;
+	  }
+
+
+	  .textBox p {
+		width: 100px;
+		height: 100px;
+	  }
+
+	  .box p, .box code {
+		margin: 0;
+		text-align: left;
+	  }
+
+	  .effectList {
+		list-style: none;
+		padding: 0;
+		font-size: 10px;
+		margin: 0;
+	  }
+
+	  .effectList li {
+		float: left;
+		padding: 1em;
+	  }
+
+	  .vl, .vr {
+		border: 0px dotted #999;
+	  }
+
+	  .vl {
+		border-left-width: 4px;
+	  }
+
+	  .vr {
+		border-right-width: 4px;
+	  }
+	</style>
+</head>
+<body>
+
+	<h1 id="header2" style="opacity:0">dojox.fx.text</h1>
+
+	<div style="float:right;">
+
+		<label for="replacementText">Replacement Text:</label>
+		<input type="button" value="Clear" onclick="dojo.byId('replacementText').value = replacementText = '';">
+		<input type="button" value="Reset" onclick="dojo.byId('replacementText').value = replacementText = originalReplacementText;"><br />
+		<textarea id="replacementText" rows=8 cols=30 onkeyup="replacementText = this.value"></textarea>
+	</div>
+
+	<p>
+		The following effects are very similar to the previous; rather than separating an element into 
+		rectangular blocks, these separate the text inside the element into either words or characters, preserving any HTML.
+	</p>
+	
+	Each effect is highly configurable.	Here is a general list of the options available in each effect:
+	<ul>
+		<li>Whether or not the text should be split into words rather than characers</li>
+		<li>Text to use instead of the element's innerHTML</li>
+		<li>The distance the pieces travel (as a multiple of the element's respective dimensions)</li>
+		<li>Whether or not to fade the pieces in/out</li>
+		<li>How much the effect should be randomized (a percentage)</li>
+		<li>Whether or not the pieces should appear outside the element's boundries</li>
+	</ul>
+	<p style="font-weight: bold">
+		Just click each block of text to play its animation!<br />
+		(Some of these are very cpu-hungry)
+	</p>
+	<hr />
+	<ul class="effectList">
+	  <li>BlockFadeOut,<br />BlockFadeIn uniformly<br />(by word)
+		<div class="box textBox">
+		  <p id="text_blockfade_1" onclick="text_blockfade_1(this)">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li class="vr">BlockFadeOut,<br />BlockFadeIn randomly<br />(by character)
+		<div class="box textBox">
+		  <p id="text_blockfade_2" onclick="text_blockfade_2(this)">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li>Disintegrate, Build<br />uniformly<br />(by word, cropped)
+		<div class="box textBox">
+		  <p id="text_disintegrate_1" onclick="text_disintegrate_1(this)">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li class="vr">Disintegrate, Build<br />randomly<br />(by character)
+		<div class="box textBox">
+		  <p id="text_disintegrate_2" onclick="text_disintegrate_2(this)">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li>Explode, Converge<br />uniformly<br />(by character)
+		<div class="box textBox">
+		  <p id="text_explode_1" onclick="text_explode_1(this)">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li class="vr">Explode, Converge<br />randomly<br />(by word)
+		<div class="box textBox">
+		  <p id="text_explode_2" onclick="text_explode_2(this)">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li>Backspace, Type<br />uniformly<br />(by duration, fixed)
+		<div class="box textBox">
+		  <p id="text_backspace_1" onclick="text_backspace_1(this)">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	  <li>Backspace, Type<br />randomly<br />(by interval)
+		<div class="box textBox">
+		  <p id="text_backspace_2" onclick="text_backspace_2(this)">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi nibh. Maecenas metus nisi, tempus sed.</p>
+		</div>
+	  </li>
+	</ul>
+	<div style="height:400px"></div>
+  </body>
+</html>
diff --git a/dojox/fx/tests/test_transform.html b/dojox/fx/tests/test_transform.html
new file mode 100644
index 0000000..8cea1c3
--- /dev/null
+++ b/dojox/fx/tests/test_transform.html
@@ -0,0 +1,210 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+    "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+    <title>Test dojox.fx.ext-dojo.complex (fx using transform)</title>
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+		html,body{
+			font-family:sans-serif;
+			font-size:14px;
+			padding:0;
+			margin:0;
+		}
+		code{
+			font-family:monospace;
+			font-size:15px;
+			white-space:pre;
+		}
+		.box{
+			border:1px solid #999;
+			padding:0;
+			position:absolute;
+			width:1024px;
+			height:190px;
+			overflow:hidden;
+			left:40px;
+		}
+		.message{
+			width:100%;
+			background: #999;
+			color: #ddd;
+			margin:0;
+			padding:3px 0;
+		}
+		.message span{
+			padding: 0 3px;
+			color:#009;
+			cursor:pointer;
+			text-decoration:underline;
+		}
+		#rotate{
+			top:100px;
+		}
+		#skewX{
+			top:300px;
+		}
+		#skewY{
+			top:500px;
+		}
+		#skew{
+			top:700px;
+		}
+		#scaleX{
+			top:900px;
+		}
+		#scaleY{
+			top:1100px;
+		}
+		#scale{
+			top:1300px;
+		}
+	</style>
+</head>
+<body>
+	<h1>Test dojox.fx.ext-dojo.complex using css3 transforms</h1>
+	<div>
+		<div class="box" id="rotate">
+			<div class="message"><span id="rotateLabel">rotate - click me!</span></div>
+			<code>
+			dojo.animateProperty({
+				node:"rotate",
+				duration: 1000,
+				properties:{
+					transform:{start:'rotate(0deg)', end:'rotate(360deg)'}
+				}
+			}).play();
+			</code>
+		</div>
+	</div>
+	<div class="box" id="skewX">
+		<div class="message"><span id="skewXLabel">skewX - click me!</span></div>
+		<code>
+		dojo.animateProperty({
+			node:"skewX",
+			duration: 1000,
+			properties:{
+				transform:{start:'skewX(0deg)', end:'skewX(20deg)'}
+			}
+		}).play();
+		</code>
+	</div>
+	<div class="box" id="skewY">
+		<div class="message"><span id="skewYLabel">skewY - click me!</span></div>
+		<code>
+		dojo.animateProperty({
+			node:"skewY",
+			duration: 1000,
+			properties:{
+				transform:{start:'skewY(0deg)', end:'skewY(10deg)'}
+			}
+		}).play();
+		</code>
+	</div>
+	<div class="box" id="skew">
+		<div class="message"><span id="skewLabel">skew - click me!</span></div>
+		<code>
+		dojo.animateProperty({
+			node:"skew",
+			duration: 1000,
+			properties:{
+				transform:{start:'skew(0deg,0deg)', end:'skew(20deg,10deg)'}
+			}
+		}).play();
+		</code>
+	</div>
+	<div class="box" id="scaleX">
+		<div class="message"><span id="scaleXLabel">scaleX - click me!</span></div>
+		<code>
+			dojo.animateProperty({
+				node: "scaleX",
+				properties:{
+					transform:{start:'scaleX(1)', end:'scaleX(2)'}
+				}
+			}).play()
+		</code>
+	</div>
+	<div class="box" id="scaleY">
+		<div class="message"><span id="scaleYLabel">scaleY - click me!</span></div>
+		<code>
+			dojo.animateProperty({
+				node: "scaleY",
+				properties:{
+					transform:{start:'scaleY(1)', end:'scaleY(.5)'}
+				}
+			}).play()
+		</code>
+	</div>
+	<div class="box" id="scale">
+		<div class="message"><span id="scaleLabel">scale - click me!</span></div>
+		<code>
+			dojo.animateProperty({
+				node: "scaleY",
+				properties:{
+					transform:{start:'scale(1,1)', end:'scale(2,.5)'}
+				}
+			}).play()
+		</code>
+	</div>
+	<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.html.ext-dojo.style");
+		dojo.require("dojox.fx.ext-dojo.complex");
+
+		dojo.ready(function(){
+			var animations = {
+				rotate: dojo.animateProperty({
+					node: "rotate",
+					duration: 1000,
+					properties:{
+						transform:{start:'rotate(0deg)', end:'rotate(360deg)'}
+					}
+				}),
+				skew: dojo.animateProperty({
+					node: "skew",
+					properties:{
+						transform:{start:'skew(0deg,0deg)', end:'skew(20deg,10deg)'}
+					}
+				}),
+				skewX: dojo.animateProperty({
+					node: "skewX",
+					properties:{
+						transform:{start:'skewX(0deg)', end:'skewX(20deg)'}
+					}
+				}),
+				skewY: dojo.animateProperty({
+					node: "skewY",
+					properties:{
+						transform:{start:'skewY(0deg)', end:'skewY(10deg)'}
+					}
+				}),
+				scaleX: dojo.animateProperty({
+					node: "scaleX",
+					properties:{
+						transform:{start:'scaleX(1)', end:'scaleX(2)'}
+					}
+				}),
+				scaleY: dojo.animateProperty({
+					node: "scaleY",
+					properties:{
+						transform:{start:'scaleY(1)', end:'scaleY(.5)'}
+					}
+				}),
+				scale: dojo.animateProperty({
+					node: "scale",
+					properties:{
+						transform:{start:'scale(1,1)', end:'scale(2,.5)'}
+					}
+				})
+
+			};
+			dojo.forEach(["rotate", "skewX", "skewY", "skew", "scaleX", "scaleY", "scale"], function(i){
+				dojo.connect(dojo.byId(i + "Label"), "onclick", function(){
+					animations[i].play();
+				});
+			})
+		});
+
+	</script>
+</body>
+</html>
diff --git a/dojox/fx/tests/test_wipeTo.html b/dojox/fx/tests/test_wipeTo.html
new file mode 100644
index 0000000..539453b
--- /dev/null
+++ b/dojox/fx/tests/test_wipeTo.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.fx.wipeTo | experimental fx add-ons for the Dojo Toolkit</title>
+		
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+	<script type="text/javascript" src="../_base.js"></script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		.testBox {
+			margin:8px;
+			width:80px;
+			height:80px;
+			background:#ededed;
+			border:1px solid #b7b7b7;
+			-moz-border-radius:6pt;
+			-webkit-border-radius:5pt;      
+		}
+	</style>
+        <script type="text/javascript">
+			dojo.require("dojox.fx.ext-dojo.NodeList");
+			dojo.require("dojox.fx");
+			dojo.require("dojo.fx");
+			dojo.require("dijit.form.Button");
+			var delayAnims = function(obj){
+				console.log('yo');
+				var delay = 0;
+				var _anims = [];
+				dojo.query(".testBox").forEach(function(n){
+					_anims.push(
+						dojox.fx.wipeTo(dojo.mixin({ node:n, delay:(delay+=200) },obj))
+					);
+				});
+				console.log(_anims);
+				dojo.fx.combine(_anims).play();
+				
+			}
+        </script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">dojox.fx.wipeTo test</h1>
+        
+        <p>quick sizeTo API overview:</p>
+
+        <pre>
+        dojox.fx.wipeTo({
+                // basic requirements:
+                node: "aDomNodeId", // or a domNode reference        
+                width: 200 // measured in px
+                // height: 200 // measured in px (only one at a time, see sizeTo)         
+        });
+        </pre>
+
+		<p>Some test boxes: (id="box1,box2,box3" etc ...)</p>
+
+		<button dojoType="dijit.form.Button">
+			wipeTo width: 400
+			<script type="dojo/method" event="onClick">
+				delayAnims({ width: 400 });
+			</script>
+		</button>
+		<button dojoType="dijit.form.Button">
+			wipeTo width: 100
+			<script type="dojo/method" event="onClick">
+				delayAnims({ width: 100 });
+			</script>
+		</button>
+		<button dojoType="dijit.form.Button">
+			wipeTo height: 400
+			<script type="dojo/method" event="onClick">
+				delayAnims({ height: 400 });
+			</script>
+		</button>
+		<button dojoType="dijit.form.Button">
+			wipeTo height: 25
+			<script type="dojo/method" event="onClick">
+				delayAnims({ height: 25 });
+			</script>
+		</button>
+		<button dojoType="dijit.form.Button">
+			wipeTo height: 100
+			<script type="dojo/method" event="onClick">
+				delayAnims({ height: 100 });
+			</script>
+		</button>
+
+		<div class="testBox" id="box1">
+			I am some small text
+		</div>
+
+		<div class="testBox" id="box2">
+			I am some small text
+		</div>
+
+		<div class="testBox" id="box3">
+			I am some small text
+		</div>
+
+
+        <br style="clear:both;">
+        
+	<br>
+
+</body>
+</html>
diff --git a/dojox/fx/text.js b/dojox/fx/text.js
index 5c9acd2..4fa7a05 100644
--- a/dojox/fx/text.js
+++ b/dojox/fx/text.js
@@ -1,256 +1,463 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.fx.text"]){
-dojo._hasResource["dojox.fx.text"]=true;
 dojo.provide("dojox.fx.text");
+
+// dojo.require("dojox.fx._split");
 dojo.require("dojo.fx");
 dojo.require("dojo.fx.easing");
-dojox.fx.text._split=function(_1){
-var _2=_1.node=dojo.byId(_1.node),s=_2.style,cs=dojo.getComputedStyle(_2),_3=dojo.coords(_2,true);
-_1.duration=_1.duration||1000;
-_1.words=_1.words||false;
-var _4=(_1.text&&typeof (_1.text)=="string")?_1.text:_2.innerHTML,_5=s.height,_6=s.width,_7=[];
-dojo.style(_2,{height:cs.height,width:cs.width});
-var _8=/(<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>)/g;
-var _9=(_1.words?/(<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>)\s*|([^\s<]+\s*)/g:/(<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>)\s*|([^\s<]\s*)/g);
-var _a=(typeof _1.text=="string")?_1.text.match(_9):_2.innerHTML.match(_9);
-var _b="";
-var _c=0;
-var _d=0;
-for(var i=0;i<_a.length;i++){
-var _e=_a[i];
-if(!_e.match(_8)){
-_b+="<span>"+_e+"</span>";
-_c++;
-}else{
-_b+=_e;
-}
-}
-_2.innerHTML=_b;
-function _f(_10){
-var _11=_10.nextSibling;
-if(_10.tagName=="SPAN"&&_10.childNodes.length==1&&_10.firstChild.nodeType==3){
-var _12=dojo.coords(_10,true);
-_d++;
-dojo.style(_10,{padding:0,margin:0,top:(_1.crop?"0px":_12.t+"px"),left:(_1.crop?"0px":_12.l+"px"),display:"inline"});
-var _13=_1.pieceAnimation(_10,_12,_3,_d,_c);
-if(dojo.isArray(_13)){
-_7=_7.concat(_13);
-}else{
-_7[_7.length]=_13;
-}
-}else{
-if(_10.firstChild){
-_f(_10.firstChild);
-}
-}
-if(_11){
-_f(_11);
-}
-};
-_f(_2.firstChild);
-var _14=dojo.fx.combine(_7);
-dojo.connect(_14,"onEnd",_14,function(){
-_2.innerHTML=_4;
-dojo.style(_2,{height:_5,width:_6});
-});
-if(_1.onPlay){
-dojo.connect(_14,"onPlay",_14,_1.onPlay);
-}
-if(_1.onEnd){
-dojo.connect(_14,"onEnd",_14,_1.onEnd);
-}
-return _14;
-};
-dojox.fx.text.explode=function(_15){
-var _16=_15.node=dojo.byId(_15.node);
-var s=_16.style;
-_15.distance=_15.distance||1;
-_15.duration=_15.duration||1000;
-_15.random=_15.random||0;
-if(typeof (_15.fade)=="undefined"){
-_15.fade=true;
-}
-if(typeof (_15.sync)=="undefined"){
-_15.sync=true;
-}
-_15.random=Math.abs(_15.random);
-_15.pieceAnimation=function(_17,_18,_19,_1a,_1b){
-var _1c=_18.h;
-var _1d=_18.w;
-var _1e=_15.distance*2;
-var _1f=_15.duration;
-var _20=parseFloat(_17.style.top);
-var _21=parseFloat(_17.style.left);
-var _22=0;
-var _23=0;
-var _24=0;
-if(_15.random){
-var _25=(Math.random()*_15.random)+Math.max(1-_15.random,0);
-_1e*=_25;
-_1f*=_25;
-_22=((_15.unhide&&_15.sync)||(!_15.unhide&&!_15.sync))?(_15.duration-_1f):0;
-_23=Math.random()-0.5;
-_24=Math.random()-0.5;
-}
-var _26=((_19.h-_1c)/2-(_18.y-_19.y));
-var _27=((_19.w-_1d)/2-(_18.x-_19.x));
-var _28=Math.sqrt(Math.pow(_27,2)+Math.pow(_26,2));
-var _29=_20-_26*_1e+_28*_24;
-var _2a=_21-_27*_1e+_28*_23;
-var _2b=dojo.animateProperty({node:_17,duration:_1f,delay:_22,easing:(_15.easing||(_15.unhide?dojo.fx.easing.sinOut:dojo.fx.easing.circOut)),beforeBegin:(_15.unhide?function(){
-if(_15.fade){
-dojo.style(_17,"opacity",0);
-}
-_17.style.position=_15.crop?"relative":"absolute";
-_17.style.top=_29+"px";
-_17.style.left=_2a+"px";
-}:function(){
-_17.style.position=_15.crop?"relative":"absolute";
-}),properties:{top:(_15.unhide?{start:_29,end:_20}:{start:_20,end:_29}),left:(_15.unhide?{start:_2a,end:_21}:{start:_21,end:_2a})}});
-if(_15.fade){
-var _2c=dojo.animateProperty({node:_17,duration:_1f,delay:_22,easing:(_15.fadeEasing||dojo.fx.easing.quadOut),properties:{opacity:(_15.unhide?{start:0,end:1}:{end:0})}});
-return (_15.unhide?[_2c,_2b]:[_2b,_2c]);
-}else{
-return _2b;
-}
-};
-var _2d=dojox.fx.text._split(_15);
-return _2d;
-};
-dojox.fx.text.converge=function(_2e){
-_2e.unhide=true;
-return dojox.fx.text.explode(_2e);
-};
-dojox.fx.text.disintegrate=function(_2f){
-var _30=_2f.node=dojo.byId(_2f.node);
-var s=_30.style;
-_2f.duration=_2f.duration||1500;
-_2f.distance=_2f.distance||1.5;
-_2f.random=_2f.random||0;
-if(!_2f.fade){
-_2f.fade=true;
-}
-var _31=Math.abs(_2f.random);
-_2f.pieceAnimation=function(_32,_33,_34,_35,_36){
-var _37=_33.h;
-var _38=_33.w;
-var _39=_2f.interval||(_2f.duration/(1.5*_36));
-var _3a=(_2f.duration-_36*_39);
-var _3b=Math.random()*_36*_39;
-var _3c=(_2f.reverseOrder||_2f.distance<0)?(_35*_39):((_36-_35)*_39);
-var _3d=_3b*_31+Math.max(1-_31,0)*_3c;
-var _3e={};
-if(_2f.unhide){
-_3e.top={start:(parseFloat(_32.style.top)-_34.h*_2f.distance),end:parseFloat(_32.style.top)};
-if(_2f.fade){
-_3e.opacity={start:0,end:1};
-}
-}else{
-_3e.top={end:(parseFloat(_32.style.top)+_34.h*_2f.distance)};
-if(_2f.fade){
-_3e.opacity={end:0};
-}
-}
-var _3f=dojo.animateProperty({node:_32,duration:_3a,delay:_3d,easing:(_2f.easing||(_2f.unhide?dojo.fx.easing.sinIn:dojo.fx.easing.circIn)),properties:_3e,beforeBegin:(_2f.unhide?function(){
-if(_2f.fade){
-dojo.style(_32,"opacity",0);
-}
-_32.style.position=_2f.crop?"relative":"absolute";
-_32.style.top=_3e.top.start+"px";
-}:function(){
-_32.style.position=_2f.crop?"relative":"absolute";
-})});
-return _3f;
-};
-var _40=dojox.fx.text._split(_2f);
-return _40;
-};
-dojox.fx.text.build=function(_41){
-_41.unhide=true;
-return dojox.fx.text.disintegrate(_41);
-};
-dojox.fx.text.blockFadeOut=function(_42){
-var _43=_42.node=dojo.byId(_42.node);
-var s=_43.style;
-_42.duration=_42.duration||1000;
-_42.random=_42.random||0;
-var _44=Math.abs(_42.random);
-_42.pieceAnimation=function(_45,_46,_47,_48,_49){
-var _4a=_42.interval||(_42.duration/(1.5*_49));
-var _4b=(_42.duration-_49*_4a);
-var _4c=Math.random()*_49*_4a;
-var _4d=(_42.reverseOrder)?((_49-_48)*_4a):(_48*_4a);
-var _4e=_4c*_44+Math.max(1-_44,0)*_4d;
-var _4f=dojo.animateProperty({node:_45,duration:_4b,delay:_4e,easing:(_42.easing||dojo.fx.easing.sinInOut),properties:{opacity:(_42.unhide?{start:0,end:1}:{end:0})},beforeBegin:(_42.unhide?function(){
-dojo.style(_45,"opacity",0);
-}:undefined)});
-return _4f;
-};
-var _50=dojox.fx.text._split(_42);
-return _50;
-};
-dojox.fx.text.blockFadeIn=function(_51){
-_51.unhide=true;
-return dojox.fx.text.blockFadeOut(_51);
+
+dojox.fx.text._split = function(/*Object*/ args){
+	// summary: Split a block of text into words or letters
+	//
+	// description:
+	//		Returns an animation that will split the node into a grid
+	//		of pieces that move independently.
+	//
+	// NOTE:
+	//		In some rendering engines, the text will appear to "jump" from its initial position
+	//		when the animation begins.	To work around this bug, enclose the node's text in a <p> or <div>.
+	//
+	//	args:
+	//		args.crop: Boolean - If true, pieces will be positioned relatively rather than absolutely
+	//		args.text: String - Text to place inside the node (otherwise node.innerHTML is used)
+	//		args.words: Boolean - If true, the text will be split into words rather than characters
+	//		args.pieceAnimation: Function(piece, pieceCoords, nodeCoords, number, numPieces)
+	//			- Returns either the dojo.Animation or an array of dojo.Animation objects for the piece;
+	//			pieceCoords is the result of dojo.coords(piece, true);
+	//			nodeCoords is the result of dojo.coords(args.node, true);
+	//			number is the piece's position in the array of pieces, and numPieces is the array.length
+
+	var node = args.node = dojo.byId(args.node),
+		s = node.style,
+		cs = dojo.getComputedStyle(node),
+		nodeCoords = dojo.coords(node, true);
+		
+	args.duration = args.duration || 1000;
+	args.words = args.words || false;
+	
+	var originalHTML = (args.text && typeof(args.text) == "string") ? args.text : node.innerHTML,
+		originalHeight = s.height,
+		originalWidth = s.width,
+		animations = [];
+
+	dojo.style(node, {
+		height: cs.height,
+		width: cs.width
+	});
+
+	// The following regular expression courtesy of Phil Haack
+	// http://haacked.com/archive/2004/10/25/usingregularexpressionstomatchhtml.aspx
+	var tagReg = /(<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>)/g;
+
+	// Translation: /(HTML tag plus spaces)|(word/letter without '<' plus spaces)/g
+	var reg = (args.words ?
+		/(<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>)\s*|([^\s<]+\s*)/g :
+		/(<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>)\s*|([^\s<]\s*)/g
+	);
+
+	// Split the text into pieces
+	var pieces = (typeof args.text == "string") ? args.text.match(reg) : node.innerHTML.match(reg);
+	var html = "";
+	var numPieces = 0;
+	var number = 0;
+	for(var i = 0; i < pieces.length; i++){
+		var piece = pieces[i];
+		if(!piece.match(tagReg)){
+			html += "<span>" + piece + "</span>";
+			numPieces++;
+		}else{
+			html += piece;
+		}
+	}
+	node.innerHTML = html;
+
+	// Find the newly-created spans and create their animations
+	function animatePieces(piece){
+		var next = piece.nextSibling;
+		if(piece.tagName == "SPAN" && piece.childNodes.length == 1 && piece.firstChild.nodeType == 3){
+			var pieceCoords = dojo.coords(piece, true);
+			number++;
+			dojo.style(piece, {
+				padding: 0,
+				margin: 0,
+				top: (args.crop ? "0px" : pieceCoords.t + "px"),
+				left: (args.crop ? "0px" : pieceCoords.l + "px"),
+				display: "inline"
+			});
+			var pieceAnimation = args.pieceAnimation(piece, pieceCoords, nodeCoords, number, numPieces);
+			if(dojo.isArray(pieceAnimation)){
+				// if pieceAnimation is an array, append its elements
+				animations = animations.concat(pieceAnimation);
+			}else{
+				// otherwise, append it
+				animations[animations.length] = pieceAnimation;
+			}
+		}else if(piece.firstChild){
+			animatePieces(piece.firstChild);
+		}
+
+		if(next){
+			animatePieces(next);
+		}
+	}
+
+	animatePieces(node.firstChild);
+	var anim = dojo.fx.combine(animations);
+	dojo.connect(anim, "onEnd", anim, function(){
+		node.innerHTML = originalHTML;
+		dojo.style(node, {
+			height: originalHeight,
+			width: originalWidth
+		});
+	});
+	if(args.onPlay){
+		dojo.connect(anim, "onPlay", anim, args.onPlay);
+	}
+	if(args.onEnd){
+		dojo.connect(anim, "onEnd", anim, args.onEnd);
+	}
+	return anim; // dojo.Animation
 };
-dojox.fx.text.backspace=function(_52){
-var _53=_52.node=dojo.byId(_52.node);
-var s=_53.style;
-_52.words=false;
-_52.duration=_52.duration||2000;
-_52.random=_52.random||0;
-var _54=Math.abs(_52.random);
-var _55=10;
-_52.pieceAnimation=function(_56,_57,_58,_59,_5a){
-var _5b=_52.interval||(_52.duration/(1.5*_5a));
-var _5c=_56.textContent;
-var _5d=_5c.match(/\s/g);
-if(typeof (_52.wordDelay)=="undefined"){
-_52.wordDelay=_5b*2;
-}
-if(!_52.unhide){
-_55=(_5a-_59-1)*_5b;
-}
-var _5e,_5f;
-if(_52.fixed){
-if(_52.unhide){
-var _5e=function(){
-dojo.style(_56,"opacity",0);
+
+dojox.fx.text.explode = function(/*Object*/ args){
+	// summary: Explode a block of text into words or letters
+	//
+	// description:
+	//		Returns an animation that will split the text into a spans
+	//		of words or characters that fly away from the center.
+	//
+	//	args:
+	//		args.crop: Boolean - If true, pieces will be positioned relatively rather than absolutely
+	//		args.words: Boolean - If true, text will be split into words rather than characters
+	//		args.random: Float - If set, pieces fly to random distances, for random durations,
+	//							   and in slightly random directions. The value defines how much
+	//							   randomness is introduced.
+	//		args.distance: Float - Multiplier for the distance the pieces fly (even when random)
+	//		args.fade: Boolean - If true, pieces fade out while in motion (default is true)
+	//		args.fadeEasing: Function - If args.fade is true, the fade animations use this easing function
+	//		args.unhide: Boolean - If true, the animation is reversed
+	//		args.sync: Boolean - If args.unhide is true, all the pieces converge at the same time
+	//							 (default is true)
+
+	var node = args.node = dojo.byId(args.node);
+	var s = node.style;
+
+	args.distance = args.distance || 1;
+	args.duration = args.duration || 1000;
+	args.random = args.random || 0;
+	if(typeof(args.fade) == "undefined"){
+		args.fade = true;
+	}
+	if(typeof(args.sync) == "undefined"){
+		args.sync = true;
+	}
+	args.random = Math.abs(args.random);
+
+	// Returns the animation object for each piece
+	args.pieceAnimation = function(piece, pieceCoords, coords, number, numPieces){
+		var pieceHeight = pieceCoords.h;
+		var pieceWidth = pieceCoords.w;
+		var distance = args.distance * 2;
+		var duration = args.duration;
+		var startTop = parseFloat(piece.style.top);
+		var startLeft = parseFloat(piece.style.left);
+		var delay = 0;
+		var randomX = 0;
+		var randomY = 0;
+		if(args.random){
+			var seed = (Math.random() * args.random) + Math.max(1 - args.random, 0);
+			distance *= seed;
+			duration *= seed;
+			// To syncronize, give each piece an appropriate delay so they end together
+			delay = ((args.unhide && args.sync) || (!args.unhide && !args.sync)) ? (args.duration - duration) : 0;
+
+			// Slightly randomize the direction of each piece
+			randomX = Math.random() - 0.5;
+			randomY = Math.random() - 0.5;
+		}
+		var distanceY = ((coords.h - pieceHeight) / 2 - (pieceCoords.y - coords.y));
+		var distanceX = ((coords.w - pieceWidth) / 2 - (pieceCoords.x - coords.x));
+		var distanceXY = Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2));
+		var endTop = startTop - distanceY * distance + distanceXY * randomY;
+		var endLeft = startLeft - distanceX * distance + distanceXY * randomX;
+
+		// Create the animation objects for the piece
+		// These are separate anim objects so they can have different curves
+		var pieceSlide = dojo.animateProperty({
+			node: piece,
+			duration: duration,
+			delay: delay,
+			easing: (args.easing || (args.unhide ? dojo.fx.easing.sinOut : dojo.fx.easing.circOut)),
+			beforeBegin: (args.unhide ? function(){
+					if(args.fade){
+						//piece.style.opacity = 0;
+						dojo.style(piece,"opacity", 0);
+					}
+					piece.style.position = args.crop ? "relative" : "absolute";
+					piece.style.top = endTop + "px";
+					piece.style.left = endLeft + "px";
+				} : function(){piece.style.position = args.crop ? "relative" : "absolute";}),
+			properties: {
+				top: (args.unhide ? { start: endTop, end: startTop } : { start: startTop, end: endTop }),
+				left: (args.unhide ? { start: endLeft, end: startLeft } : { start: startLeft, end: endLeft })
+			}
+		});
+
+		if(args.fade){
+			var pieceFade = dojo.animateProperty({
+				node: piece,
+				duration: duration,
+				delay: delay,
+				easing: (args.fadeEasing || dojo.fx.easing.quadOut),
+				properties: {
+					opacity: (args.unhide ? {start: 0, end: 1} : {end: 0})
+				}
+			});
+
+			// return both animations as an array
+			return (args.unhide ? [pieceFade, pieceSlide] : [pieceSlide, pieceFade]);
+		}else{
+			// Otherwise return only the slide animation
+			return pieceSlide;
+		}
+	};
+
+	var anim = dojox.fx.text._split(args);
+	return anim; // dojo.Animation
 };
-}
-}else{
-if(_52.unhide){
-var _5e=function(){
-_56.style.display="none";
+
+dojox.fx.text.converge = function(/*Object*/ args){
+	args.unhide = true;
+	return dojox.fx.text.explode(args);
 };
-var _5f=function(){
-_56.style.display="inline";
+
+dojox.fx.text.disintegrate = function(/*Object*/ args){
+	// summary: Split a block of text into words or letters and let them fall
+	//
+	// description:
+	//		Returns an animation that will split the text into spans of words
+	//		or characters that drop.
+	//
+	//	args:
+	//		args.crop: Boolean - If true, pieces will be positioned relatively rather than absolutely
+	//		args.words: Boolean - If true, text will be split into words rather than characters
+	//		args.interval: Float - The number of milliseconds between each piece's animation
+	//		args.distance: Float - The number of the node's heights to drop (default is 1.5)
+	//		args.fade: Boolean - If true, pieces fade out while in motion (default is true)
+	//		args.random: Float - If set, pieces fall in random order. The value defines how much
+	//							   randomness is introduced
+	//		args.reverseOrder: Boolean - If true, pieces animate in reversed order
+	//		args.unhide: Boolean - If true, the peices fall from above and land in place
+
+	var node = args.node = dojo.byId(args.node);
+	var s = node.style;
+
+	args.duration = args.duration || 1500;
+	args.distance = args.distance || 1.5;
+	args.random = args.random || 0;
+	if(!args.fade){
+		args.fade = true;
+	}
+	var random = Math.abs(args.random);
+
+	// Returns the animation object for each piece
+	args.pieceAnimation = function(piece, pieceCoords, coords, number, numPieces){
+		var pieceHeight = pieceCoords.h;
+		var pieceWidth = pieceCoords.w;
+
+		var interval = args.interval || (args.duration / (1.5 * numPieces));
+		var duration = (args.duration - numPieces * interval);
+
+		var randomDelay = Math.random() * numPieces * interval;
+		// If distance is negative, start from the top right instead of bottom left
+		var uniformDelay = (args.reverseOrder || args.distance < 0) ?
+			(number * interval) : ((numPieces - number) * interval);
+		var delay = randomDelay * random + Math.max(1 - random, 0) * uniformDelay;
+
+		// Create the animation object for the piece
+		var properties = {};
+		if(args.unhide){
+			properties.top = {
+				start: (parseFloat(piece.style.top) - coords.h * args.distance),
+				end: parseFloat(piece.style.top)
+			};
+			if(args.fade){
+				properties.opacity = {start: 0, end: 1};
+			}
+		}else{
+			properties.top = {end: (parseFloat(piece.style.top) + coords.h * args.distance)};
+			if(args.fade){
+				properties.opacity = {end: 0};
+			}
+		}
+		var pieceAnimation = dojo.animateProperty({
+			node: piece,
+			duration: duration,
+			delay: delay,
+			easing: (args.easing || (args.unhide ? dojo.fx.easing.sinIn : dojo.fx.easing.circIn)),
+			properties: properties,
+			beforeBegin: (args.unhide ? function(){
+				if(args.fade){
+					// piece.style.opacity = 0;
+					dojo.style(piece, "opacity", 0);
+				}
+				piece.style.position = args.crop ? "relative" : "absolute";
+				piece.style.top = properties.top.start + "px";
+			} : function(){ piece.style.position = args.crop ? "relative" : "absolute";})
+		});
+
+		return pieceAnimation;
+	};
+
+	var anim = dojox.fx.text._split(args);
+	return anim; // dojo.Animation
 };
-}else{
-var _5f=function(){
-_56.style.display="none";
+
+dojox.fx.text.build = function(/*Object*/ args){
+	args.unhide = true;
+	return dojox.fx.text.disintegrate(args);
 };
-}
-}
-var _60=dojo.animateProperty({node:_56,duration:1,delay:_55,easing:(_52.easing||dojo.fx.easing.sinInOut),properties:{opacity:(_52.unhide?{start:0,end:1}:{end:0})},beforeBegin:_5e,onEnd:_5f});
-if(_52.unhide){
-var _61=Math.random()*_5c.length*_5b;
-var _62=_61*_54/2+Math.max(1-_54/2,0)*_52.wordDelay;
-_55+=_61*_54+Math.max(1-_54,0)*_5b*_5c.length+(_62*(_5d&&_5c.lastIndexOf(_5d[_5d.length-1])==_5c.length-1));
-}
-return _60;
+
+dojox.fx.text.blockFadeOut = function(/*Object*/ args){
+	// summary: Split a block of text into words or letters and fade them
+	//
+	// description:
+	//		Returns an animation that will split the text into spans of words
+	//		or characters that fade in or out.
+	//
+	//	args:
+	//		args.words: Boolean - If true, text will be split into words rather than characters
+	//		args.interval: Float - The number of milliseconds between each piece's animation (default is 0)
+	//		args.random: Float - If true, pieces have a random delay. The value defines how much
+	//							   randomness is introduced
+	//		args.reverseOrder: Boolean - If true, pieces animate in reversed order
+	//		args.unhide: Boolean - If true, the animation is reversed
+
+	var node = args.node = dojo.byId(args.node);;
+	var s = node.style;
+
+	args.duration = args.duration || 1000;
+	args.random = args.random || 0;
+	var random = Math.abs(args.random);
+
+	// Returns the animation object for each piece
+	args.pieceAnimation = function(piece, pieceCoords, coords, number, numPieces){
+		var interval = args.interval || (args.duration / (1.5 * numPieces));
+		var duration = (args.duration - numPieces * interval);
+
+		var randomDelay = Math.random() * numPieces * interval;
+		// If interval or random is negative, start from the bottom instead of top
+		var uniformDelay = (args.reverseOrder) ?
+			((numPieces - number) * interval) : (number * interval);
+		var delay = randomDelay * random + Math.max(1 - random, 0) * uniformDelay;
+
+		// Create the animation object for the piece
+		var pieceAnimation = dojo.animateProperty({
+			node: piece,
+			duration: duration,
+			delay: delay,
+			easing: (args.easing || dojo.fx.easing.sinInOut),
+			properties: {
+				opacity: (args.unhide ? {start: 0, end: 1} : {end:0})
+			},
+			beforeBegin: (args.unhide ? function(){ dojo.style(piece,"opacity",0); } : undefined)
+		});
+
+		return pieceAnimation;
+	};
+
+	var anim = dojox.fx.text._split(args);
+	return anim; // dojo.Animation
 };
-var _63=dojox.fx.text._split(_52);
-return _63;
+
+dojox.fx.text.blockFadeIn = function(/*Object*/ args){
+	args.unhide = true;
+	return dojox.fx.text.blockFadeOut(args);
 };
-dojox.fx.text.type=function(_64){
-_64.unhide=true;
-return dojox.fx.text.backspace(_64);
+
+dojox.fx.text.backspace = function(/*Object*/ args){
+	// summary: Split a block of text into words or letters and backspace them in sequence
+	//
+	// description:
+	//		Returns an animation that will split the text into spans of words
+	//		or characters that appear as if they were being backspaced (or typed) in real-time.
+	//
+	//	args:
+	//		args.interval: Float - The number of milliseconds between each piece's animation
+	//							   (default is determined by text length and args.duration);
+	//		args.wordDelay: Integer - The number of milliseconds between each word
+	//								  (only effective when args.unhide = true)
+	//		args.fixed: Boolean - If true, only style.opacity changes; otherwise, style.display
+	//							  changes between none and inline, adding realism (default = false)
+	//		args.random: Float - If true, pieces have a random delay. The value defines how much
+	//							   randomness is introduced (only effective when args.unhide = true)
+	//		args.unhide: Boolean - If true, the animation is reversed
+
+	var node = args.node = dojo.byId(args.node);
+	var s = node.style;
+
+	args.words = false;
+	args.duration = args.duration || 2000;
+	args.random = args.random || 0;
+	var random = Math.abs(args.random);
+	var delay = 10;
+
+	// Returns the animation object for each piece
+	args.pieceAnimation = function(piece, pieceCoords, coords, number, numPieces){
+		var interval = args.interval || (args.duration / (1.5 * numPieces)),
+			text = ("textContent" in piece) ? piece.textContent : piece.innerText,
+			whitespace = text.match(/\s/g);
+
+		if(typeof(args.wordDelay) == "undefined"){
+			args.wordDelay = interval * 2;
+		}
+
+		if(!args.unhide){
+			delay = (numPieces - number - 1) * interval;
+		}
+
+		var beforeBegin, onEnd;
+
+		if(args.fixed){
+			if(args.unhide){
+				var beforeBegin = function(){ dojo.style(piece,"opacity",0); };
+			}
+		}else{
+			if(args.unhide){
+				var beforeBegin = function(){piece.style.display = "none";};
+				var onEnd = function(){piece.style.display = "inline";};
+			}else{
+				var onEnd = function(){piece.style.display = "none";};
+			}
+		}
+
+		// Create the animation object for the piece
+		var pieceAnimation = dojo.animateProperty({
+			node: piece,
+			duration: 1,
+			delay: delay,
+			easing: (args.easing || dojo.fx.easing.sinInOut),
+			properties: {
+				opacity: (args.unhide ? {start: 0, end: 1} : {end:0})
+			},
+			beforeBegin: beforeBegin,
+			onEnd: onEnd
+		});
+
+		if(args.unhide){
+			var randomDelay = Math.random() * text.length * interval;
+			var wordDelay = randomDelay * random / 2 + Math.max(1 - random / 2, 0) * args.wordDelay;
+
+			delay += randomDelay * random + Math.max(1 - random, 0) * interval * text.length +
+				(wordDelay * (whitespace && text.lastIndexOf(whitespace[whitespace.length-1]) == text.length - 1));
+		}
+
+		return pieceAnimation;
+	};
+
+	var anim = dojox.fx.text._split(args);
+	return anim; // dojo.Animation
 };
-}
+
+dojox.fx.text.type = function(/*Object*/ args){
+	args.unhide = true;
+	return dojox.fx.text.backspace(args);
+};
\ No newline at end of file
diff --git a/dojox/geo/README b/dojox/geo/README
new file mode 100644
index 0000000..85d638d
--- /dev/null
+++ b/dojox/geo/README
@@ -0,0 +1,37 @@
+-------------------------------------------------------------------------------
+dojox.geo
+-------------------------------------------------------------------------------
+Version 0.100
+Release date: 04/04/2010
+-------------------------------------------------------------------------------
+Project state:
+alpha
+-------------------------------------------------------------------------------
+Credits
+	dojox.geo.charting:
+		Dean Williams (deanw at ca.ibm.com)
+		Qi Ruan (ruanqi at cn.ibm.com)
+		Wei CDL Huang (hwcdl at cn.ibm.com)
+
+	Tom Trenka (ttrenka at gmail.com)
+-------------------------------------------------------------------------------
+Project description
+
+Project to house any geographical-related code.  First project is 
+dojox.geo.charting, contributed to DTK by IBM (CCLA on file).
+-------------------------------------------------------------------------------
+Dependencies:
+
+Dojo Core, dojox.gfx, dojox.lang, Dijit.
+-------------------------------------------------------------------------------
+Documentation
+
+Not ready yet.
+-------------------------------------------------------------------------------
+Installation instructions
+
+Grab the following from the Dojo SVN Repository:
+http://svn.dojotoolkit.org/src/dojox/trunk/geo
+
+You will need dojox.gfx, dojox.lang, and the Dijit core + Tooltip.
+-------------------------------------------------------------------------------
diff --git a/dojox/geo/charting/Map.js b/dojox/geo/charting/Map.js
new file mode 100644
index 0000000..7979195
--- /dev/null
+++ b/dojox/geo/charting/Map.js
@@ -0,0 +1,140 @@
+dojo.provide("dojox.geo.charting.Map");
+
+dojo.require("dojox.gfx");
+dojo.require("dojox.geo.charting._base");
+dojo.require("dojox.geo.charting._Feature");
+dojo.require("dojox.geo.charting._Marker");
+
+dojo.declare("dojox.geo.charting.Map", null, {
+	//	summary:
+	//		Map widget interacted with charting.
+	//	description:
+	//		Support rendering Americas, AsiaPacific, ContinentalEurope, EuropeMiddleEastAfrica, 
+	//		USStates, WorldCountries, and WorldCountriesMercator by default.
+	//	example:
+	//	|	var usaMap = new dojox.geo.charting.Map(srcNode, "dojotoolkit/dojox/geo/charting/resources/data/USStates.json");
+	//	|	<div id="map" style="width:600px;height:400px;"></div>
+	
+	//	defaultColor: String
+	//		Default map feature color, e.g: "#B7B7B7"
+	defaultColor:"#B7B7B7",
+	//	highlightColor: String
+	//		Map feature color when mouse over it, e.g: "#"
+	highlightColor:"#D5D5D5",
+	//	series: Array
+	//		stack to data range, e.g: [{name:'label 1', min:20, max:70, color:'#DDDDDD'},{...},...]
+	series:[],
+	constructor: function(/*HTML Node*/container, /*String*/shapeFile){
+		//	container:
+		//		map container html node/id
+		//	shapeFile:
+		//		map shape data url, handled as json style
+		//		data format: 
+		
+		// get map container coords
+		dojo.style(container, "display", "block");
+		this.containerSize = {
+			x: dojo.coords(container).x,
+			y: dojo.coords(container).y,
+			w: dojo.coords(container).w || 100,
+			h: dojo.coords(container).h || 100
+		};
+		this.surface = dojox.gfx.createSurface(container, this.containerSize.w, this.containerSize.h);
+		this.container = container;
+	    
+		this._createZoomingCursor();
+		
+		this.mapObj = this.surface.createGroup();
+		this.mapObj.features = {};
+        // load map shape file
+		dojo.xhrGet({
+			url: shapeFile,
+			handleAs: "json",
+			sync:true,
+			load: dojo.hitch(this, "_init")
+		});
+	},
+	setMarkerData: function(/*String*/ markerFile){
+		//	summary:
+		//		import markers from outside file, associate with map feature by feature id 
+		//		which identified in map shape file, e.g: "NY":"New York"
+		//	markerFile:
+		//		outside marker data url, handled as json style.
+		//		data format: {"NY":"New York",.....}
+		dojo.xhrGet({
+			url: markerFile,
+			handleAs: "json",
+			handle: dojo.hitch(this, "_appendMarker")
+		});
+	},
+	setDataStore: function(/*ItemFileReadStore*/ dataStore, /*Object*/ query){
+		//	summary:
+		//		populate data for each map feature from fetched data store
+		this.dataStore = dataStore;
+		var self = this;
+		this.dataStore.fetch({
+			query: query,
+			onComplete: function(items){
+				var item = items[0];
+				var attributes = self.dataStore.getAttributes(item);
+				dojo.forEach(attributes, function(name){
+					if(self.mapObj.features[name]){
+						self.mapObj.features[name].setValue(self.dataStore.getValue(item, name));
+					}
+				});
+			}
+		});
+	},
+	addSeries: function(series){
+		this.series = series;
+	},
+	_init: function(shapeData){
+		//transform map to fit container
+		var mapWidth = shapeData.layerExtent[2] - shapeData.layerExtent[0];
+		var mapHeight = shapeData.layerExtent[3] - shapeData.layerExtent[1];
+		this.mapObj.scale = Math.min(this.containerSize.w / mapWidth, this.containerSize.h / mapHeight);
+		this.mapObj.currentScale = this.mapObj.scale;
+		this.mapObj.boundBox = shapeData.layerExtent;
+		this.mapObj.currentBBox = {
+			x: shapeData.layerExtent[0],
+			y:shapeData.layerExtent[1]
+		};
+		this.mapObj.setTransform([
+			dojox.gfx.matrix.scale(this.mapObj.scale), 
+			dojox.gfx.matrix.translate(-shapeData.layerExtent[0], -shapeData.layerExtent[1])
+		]);
+
+		//	if there are "features", then implement them now.
+		dojo.forEach(shapeData.featureNames, function(item){
+			var featureShape = shapeData.features[item];
+			featureShape.bbox.x = featureShape.bbox[0];
+			featureShape.bbox.y = featureShape.bbox[1];
+			featureShape.bbox.w = featureShape.bbox[2];
+			featureShape.bbox.h = featureShape.bbox[3];
+			var feature = new dojox.geo.charting._Feature(this, item, featureShape);
+			feature.init();
+			this.mapObj.features[item] = feature;
+		}, this);
+
+		//	set up a marker.
+		this.mapObj.marker = new dojox.geo.charting._Marker({}, this);
+	},
+	_appendMarker: function(markerData){
+		this.mapObj.marker = new dojox.geo.charting._Marker(markerData, this);
+	},
+	_createZoomingCursor: function(){
+		if(!dojo.byId("mapZoomCursor")){
+			var mapZoomCursor = dojo.doc.createElement("div");
+			dojo.attr(mapZoomCursor,"id","mapZoomCursor");
+			dojo.addClass(mapZoomCursor,"mapZoomIn");
+			dojo.style(mapZoomCursor,"display","none");
+			dojo.body().appendChild(mapZoomCursor);
+		}
+	},
+	onFeatureClick: function(feature){
+	},
+	onFeatureOver: function(feature){
+	},
+	onZoomEnd:function(feature){
+	}
+});
diff --git a/dojox/geo/charting/_Feature.js b/dojox/geo/charting/_Feature.js
new file mode 100644
index 0000000..b2b7792
--- /dev/null
+++ b/dojox/geo/charting/_Feature.js
@@ -0,0 +1,169 @@
+dojo.provide("dojox.geo.charting._Feature");
+dojo.require("dojox.gfx.fx");
+
+dojo.declare("dojox.geo.charting._Feature", null, {
+	_isZoomIn: false,
+	_isFocused: false,
+	markerText:null,
+
+	constructor: function(parent, name, shapeData){
+		this.id = name;
+		this.shape = parent.mapObj.createGroup();
+		this.parent = parent;
+		this.mapObj = parent.mapObj;
+		this._bbox = shapeData.bbox;
+		this._center = shapeData.center;
+		//TODO: fill color would be defined by charting data and legend
+		//this._defaultFill = ["#FFCE52", "#CE6342", "#63A584"][Math.floor(Math.random() * 3)];
+		this._defaultFill = parent.defaultColor;
+		this._highlightFill = parent.highlightColor;
+		this._defaultStroke = {
+			width: this._normalizeStrokeWeight(.5),
+			color: "white"
+		};
+		this._scale = Math.min(this.parent.containerSize.w / this._bbox.w, this.parent.containerSize.h / this._bbox.h);
+		
+		var shapes = (dojo.isArray(shapeData.shape[0])) ? shapeData.shape : [shapeData.shape];
+		dojo.forEach(shapes, function(points){
+			this.shape.createPolyline(points).setStroke(this._defaultStroke).setFill(this._defaultFill);
+		}, this);
+	},
+	setValue:function(value){
+		this.value = value;
+		if(this.parent.series.length != 0){
+			for(var i = 0;i < this.parent.series.length;i++){
+				var range = this.parent.series[i];
+				if((value>=range.min)&&(value<range.max)){
+					this._setFillWith(range.color);
+					this._defaultFill = range.color;
+				}
+			}
+		}
+	},
+	_setFillWith: function(color){
+		var borders = (dojo.isArray(this.shape.children)) ? this.shape.children : [this.shape.children];
+		dojo.forEach(borders, function(item){
+			item.setFill(color);
+		});
+	},
+	_setStrokeWith: function(stroke){
+		var borders = (dojo.isArray(this.shape.children)) ? this.shape.children : [this.shape.children];
+		dojo.forEach(borders, function(item){
+			item.setStroke({
+				color: stroke.color,
+				width: stroke.width,
+				join: "round"
+			});
+		});
+	},
+	_normalizeStrokeWeight: function(weight){
+		var matrix = this.shape._getRealMatrix();
+		return (dojox.gfx.renderer != "vml")?weight/(this.shape._getRealMatrix()||{xx:1}).xx:weight;
+	},
+	_onmouseoverHandler: function(evt){
+		this.parent.onFeatureOver(this);
+		this._setFillWith(this._highlightFill);
+		this.mapObj.marker.show(this.id);
+	},
+	_onmouseoutHandler: function(){
+		this._setFillWith(this._defaultFill);
+		this.mapObj.marker.hide();
+		dojo.style("mapZoomCursor", "display", "none");
+	},
+	_onmousemoveHandler: function(evt){
+		if(this._isFocused){
+			var evt = dojo.fixEvent(evt || window.event);
+			dojo.style("mapZoomCursor", "left", evt.pageX + 12 + "px");
+			dojo.style("mapZoomCursor", "top", evt.pageY + "px");
+			dojo.byId("mapZoomCursor").className = (this._isZoomIn)?"mapZoomOut":"mapZoomIn";
+			dojo.style("mapZoomCursor", "display", "block");
+		}
+	},
+	_onclickHandler: function(){
+		if(!this._isFocused){
+			for (var name in this.mapObj.features){
+				if (this.mapObj.features[name] != this){
+					this.mapObj.features[name]._setStrokeWith(this._defaultStroke);
+					this.mapObj.features[name]._setFillWith(this.mapObj.features[name]._defaultFill);
+					this.mapObj.features[name]._isFocused = false;
+					this.mapObj.features[name]._isZoomIn = false;
+				}
+			}
+			this._focus();
+		}
+		else if (this._isZoomIn){
+			this._zoomOut();
+		}
+		else {
+			this._zoomIn();
+		}
+	},
+	_focus: function(){
+		this.shape._moveToFront();
+		this._setStrokeWith({color:"black",width:this._normalizeStrokeWeight(2)});
+		this.parent.onFeatureClick(this);
+		this._isFocused = true;
+	},
+	_zoomIn: function(){
+		var anim = dojox.gfx.fx.animateTransform({
+			duration: 1000,
+			shape: this.mapObj,
+			transform: [{
+				name: "translate",
+				start: [-this.mapObj.currentBBox.x, -this.mapObj.currentBBox.y],
+				end: [-this._bbox.x, -this._bbox.y]
+			},{
+				name: "scaleAt",
+				start: [this.mapObj.currentScale, this.mapObj.currentBBox.x, this.mapObj.currentBBox.y],
+				end: [this._scale, this._bbox.x, this._bbox.y]
+			}]
+		});
+		dojo.connect(anim,"onEnd",this,function(){
+			this._setStrokeWith({color:"black",width:this._normalizeStrokeWeight(2)});
+			this.parent.onZoomEnd(this);
+		});
+		anim.play();
+		this.mapObj.currentScale = this._scale;
+		this.mapObj.currentBBox = {
+			x: this._bbox.x,
+			y: this._bbox.y
+		};
+		this._isZoomIn = true;
+		dojo.byId("mapZoomCursor").className = "";
+	},
+	_zoomOut: function(){
+		var anim = dojox.gfx.fx.animateTransform({
+			duration: 1000,
+			shape: this.mapObj,
+			transform: [{
+				name: "translate",
+				start: [-this._bbox.x, -this._bbox.y],
+				end: [-this.mapObj.boundBox[0], -this.mapObj.boundBox[1]]
+			}, {
+				name: "scaleAt",
+				start: [this._scale, this._bbox.x, this._bbox.y],
+				end: [this.mapObj.scale, this.mapObj.boundBox[0], this.mapObj.boundBox[1]]
+			}]
+		});
+		dojo.connect(anim,"onEnd",this,function(){
+			this._setStrokeWith({color:"black",width:this._normalizeStrokeWeight(2)});
+		});
+		anim.play();
+		this.mapObj.currentScale = this.mapObj.scale;
+		this.mapObj.currentBBox = {
+			x: this.mapObj.boundBox[0],
+			y: this.mapObj.boundBox[1]
+		};
+		this._isZoomIn = false;
+		dojo.byId("mapZoomCursor").className = "";
+	},
+	
+	init: function(){
+		this.shape.rawNode.id = this.id;
+		this.tooltip = null;
+		this.shape.connect("onmouseover", this, this._onmouseoverHandler);
+		this.shape.connect("onmouseout", this, this._onmouseoutHandler);
+		this.shape.connect("onmousemove", this, this._onmousemoveHandler);
+		this.shape.connect("onclick", this, this._onclickHandler);
+	}
+});
diff --git a/dojox/geo/charting/_Marker.js b/dojox/geo/charting/_Marker.js
new file mode 100644
index 0000000..78d9418
--- /dev/null
+++ b/dojox/geo/charting/_Marker.js
@@ -0,0 +1,52 @@
+dojo.provide("dojox.geo.charting._Marker");
+
+dojo.declare("dojox.geo.charting._Marker", null, {
+	constructor: function(markerData, map){
+		var mapObj = map.mapObj;
+		this.features = mapObj.features;
+		this.markerData = markerData;
+	},
+
+	show: function(featureId){
+		this.markerText = this.features[featureId].markerText || this.markerData[featureId] || featureId;
+		this.currentFeature = this.features[featureId];
+		dojox.geo.charting.showTooltip(this.markerText, this.currentFeature.shape, "before");
+	},
+
+	hide: function(){
+		dojox.geo.charting.hideTooltip(this.currentFeature.shape);
+	},
+
+	_getGroupBoundingBox: function(group){
+		var shapes = group.children;
+		var feature = shapes[0];
+		var bbox = feature.getBoundingBox();
+		this._arround = dojo.clone(bbox);
+		dojo.forEach(shapes, function(item){
+			var _bbox = item.getBoundingBox();
+			this._arround.x = Math.min(this._arround.x, _bbox.x);
+			this._arround.y = Math.min(this._arround.y, _bbox.y);
+		},this);
+	},
+
+	_toWindowCoords: function(arround, coords, containerSize){
+		var toLeft = (arround.x - this.topLeft[0]) * this.scale;
+		var toTop = (arround.y - this.topLeft[1]) * this.scale
+		if (dojo.isFF == 3.5) {
+			arround.x = coords.x;
+			arround.y = coords.y;
+		}
+		else if (dojo.isChrome) {
+			arround.x = containerSize.x + toLeft;
+			arround.y = containerSize.y + toTop;
+		}
+		else {
+			arround.x = coords.x + toLeft;
+			arround.y = coords.y + toTop;
+		}
+		arround.width = (this.currentFeature._bbox[2]) * this.scale;
+		arround.height = (this.currentFeature._bbox[3]) * this.scale;
+		arround.x += arround.width / 6;
+		arround.y += arround.height / 4;
+	}
+});
diff --git a/dojox/geo/charting/_base.js b/dojox/geo/charting/_base.js
new file mode 100644
index 0000000..b6bdc6a
--- /dev/null
+++ b/dojox/geo/charting/_base.js
@@ -0,0 +1,53 @@
+dojo.provide("dojox.geo.charting._base");
+
+dojo.require("dojo.NodeList-traverse");
+dojo.require("dojox.gfx.matrix");
+dojo.require("dijit.Tooltip");
+
+(function(){
+	var dgc = dojox.geo.charting;
+	dgc.showTooltip = function(/*String*/innerHTML, /*dojox.gfx.shape*/ gfxObject, /*String[]?*/ position){
+		var arroundNode = dgc._normalizeArround(gfxObject);
+		return dijit.showTooltip(innerHTML, arroundNode, position);
+	};
+
+	dgc.hideTooltip = function( /*dojox.gfx.shape*/gfxObject){
+		return dijit.hideTooltip(gfxObject);
+	};
+
+	dgc._normalizeArround = function(gfxObject){
+		var bbox = dgc._getRealBBox(gfxObject);
+		//var bbox = gfxObject.getBoundingBox();
+		//get the real screen coords for gfx object
+		var realMatrix = gfxObject._getRealMatrix() || {xx:1,xy:0,yx:0,yy:1,dx:0,dy:0};
+		var point = dojox.gfx.matrix.multiplyPoint(realMatrix, bbox.x, bbox.y);
+		var gfxDomContainer = dojo.coords(dgc._getGfxContainer(gfxObject));
+		gfxObject.x = dojo.coords(gfxDomContainer,true).x + point.x,
+		gfxObject.y = dojo.coords(gfxDomContainer,true).y + point.y,
+		gfxObject.width = bbox.width * realMatrix.xx,
+		gfxObject.height = bbox.height * realMatrix.yy
+		return gfxObject;
+	};
+
+	dgc._getGfxContainer = function(gfxObject){
+		return (new dojo.NodeList(gfxObject.rawNode)).parents("div")[0];
+	};
+
+	dgc._getRealBBox = function(gfxObject){
+		var bboxObject = gfxObject.getBoundingBox();
+		if(!bboxObject){//the gfx object is group
+			var shapes = gfxObject.children;
+			var bboxObject = dojo.clone(dgc._getRealBBox(shapes[0]));
+			dojo.forEach(shapes, function(item){
+				var nextBBox = dgc._getRealBBox(item);
+				bboxObject.x = Math.min(bboxObject.x, nextBBox.x);
+				bboxObject.y = Math.min(bboxObject.y, nextBBox.y);
+				bboxObject.endX = Math.max(bboxObject.x + bboxObject.width, nextBBox.x + nextBBox.width);
+				bboxObject.endY = Math.max(bboxObject.y + bboxObject.height, nextBBox.y + nextBBox.height);
+			});
+			bboxObject.width = bboxObject.endX - bboxObject.x;
+			bboxObject.height = bboxObject.endY - bboxObject.y;
+		}
+		return bboxObject;
+	};
+})();
diff --git a/dojox/geo/charting/resources/Map.css b/dojox/geo/charting/resources/Map.css
new file mode 100644
index 0000000..2370b26
--- /dev/null
+++ b/dojox/geo/charting/resources/Map.css
@@ -0,0 +1,30 @@
+.tundra .dijitTooltipAbove .dijitTooltipConnector, .dj_ie .tundra .dijitTooltipAbove .dijitTooltipConnector {
+	display: none;
+}
+
+.dojoxLegendNode {
+	border: 1px solid #ccc;
+	margin: 5px 10px 5px 10px;
+	padding: 3px;
+	float:right;
+}
+
+.dojoxLegendText {
+	vertical-align: text-top;
+	padding-right: 10px
+}
+
+.mapZoomIn {
+	width: 21px;
+	height: 21px;
+	background: url(img/zoomin.png) no-repeat;
+	position: absolute;
+}
+
+.mapZoomOut {
+	width: 21px;
+	height: 21px;
+	background: url(img/zoomout.png) no-repeat;
+	position: absolute;
+}
+
diff --git a/dojox/geo/charting/resources/data/NOTICES b/dojox/geo/charting/resources/data/NOTICES
new file mode 100644
index 0000000..5d62e07
--- /dev/null
+++ b/dojox/geo/charting/resources/data/NOTICES
@@ -0,0 +1,63 @@
+Mapping data in this directory was obtained from the United States Geological Survey (USGS) at http://nationalatlas.gov/atlasftp.html.  
+Data and information authored or produced by the USGS are in the public domain:  http://nationalatlas.gov/policies.html.  
+The following notices and information are provided by the USGS:
+-----------------------------------------------------------------------------------------------------------------------------------------------
+
+	
+	Are there legal restrictions on access or use of the data?
+
+		Access_Constraints: None 
+		Use_Constraints: 
+			None. Acknowledgment of the National Atlas of the United States 
+			of America and (or) the U.S. Geological Survey would be 
+			appreciated in products derived from these data. 
+
+	1. Who distributes the data set? (Distributor 1 of 1)
+
+		Earth Science Information Center, U.S. Geological Survey
+		507 National Center
+		Reston, VA 20192
+
+		1-888-ASK-USGS (1-888-275-8747) (voice)
+
+
+		Contact_Instructions: 
+			In addition to the address above there are other ESIC offices throughout the 	
+			country. A full list of these offices is at 
+			<http://mapping.usgs.gov/esic/esic_index.html>. 
+
+	2. What's the catalog number I need to order this data set?
+
+	3. What legal disclaimers am I supposed to read?
+
+		Although these data have been processed successfully on a computer system 
+		at the U.S. Geological Survey, no warranty expressed or implied is made by the U.S. Geological Survey regarding the utility of the data on any other system, nor shall the act of distribution constitute any such warranty. No responsibility is assumed by the U.S. Geological Survey in the use of these data. 
+
+	4. How can I download or order the data?
+
+		Availability in digital form:
+			
+		Data format: ESRI Shapefile  
+		Network links: <http://nationalatlas.gov/atlasftp.html>
+ 
+		Data format: SDTS  
+		Network links: <http://nationalatlas.gov/atlasftp.html>
+ 
+
+		Cost to order the data: 
+
+		There is no charge for the online option. For National Atlas files ordered on CD-ROM 
+		there is a base price of $45.00 per disc, a handling fee of $5.00, and a per-file 
+		charge based on file size. The charge for files less than 10 megabytes in size is 
+		$1.00. The charge for files that range in size from 10 to 150 megabytes is $7.50. The 
+		charge for files of 150 megabytes or larger is $15.00. The charge is $7.50 for the 
+		Major Roads of the United States data set.
+
+
+		Special instructions:
+
+			To order files on CD-ROM, please see <http://nationalatlas.gov/atlasftp.html#q12>. 
+
+---------------------------------------------------------------------------------------------------------------------
+
+This Shapefile data is then reformatted into a simple JSON format
diff --git a/dojox/geo/charting/resources/data/USStates.json b/dojox/geo/charting/resources/data/USStates.json
new file mode 100644
index 0000000..509034a
--- /dev/null
+++ b/dojox/geo/charting/resources/data/USStates.json
@@ -0,0 +1,261 @@
+{
+  "layerExtent":[0, 0, 8036, 5263],
+  "featureNames":["RI", "VT", "HI", "ME", "VA", "MI", "DE", "ID", "IA", "MD", "MA", "AR", "IL", "UT", "IN", "MN", "AZ", "MO", "MT", "MS", "NH", "NJ", "NM", "AK", "TX", "AL", "NC", "ND", "NE", "NY", "GA", "NV", "TN", "CA", "OK", "OH", "WY", "FL", "SD", "SC", "CT", "WV", "DC", "WI", "KY", "KS", "OR", "LA", "WA", "CO", "PA"],
+  "features":{
+    "RI":{
+      "shape":[[7641, 1436, 7651, 1437, 7661, 1467, 7661, 1467, 7653, 1478, 7641, 1436], [7541, 1398, 7559, 1392, 7598, 1380, 7615, 1420, 7635, 1430, 7635, 1431, 7627, 1445, 7626, 1427, 7615, 1429, 7607, 1410, 7618, 1435, 7606, 1444, 7617, 1460, 7618, 1506, 7612, 1496, 7568, 1527, 7568, 1526, 7541, 1398], [7633, 1474, 7639, 1442, 7645, 1476, 7631, 1485, 7633, 1474]],
+      "center":[7585, 1442],
+      "bbox":[7541, 1380, 120, 147]
+    },
+    "VT":{
+      "shape":[7427, 828, 7434, 848, 7424, 882, 7445, 909, 7444, 926, 7390, 984, 7404, 1022, 7383, 1128, 7402, 1236, 7394, 1266, 7414, 1289, 7393, 1294, 7309, 1313, 7302, 1314, 7267, 1166, 7255, 1151, 7239, 1162, 7241, 1126, 7216, 1076, 7218, 999, 7196, 969, 7184, 893, 7202, 888, 7427, 828],
+      "center":[7317, 1057],
+      "bbox":[7184, 828, 261, 487]
+    },
+    "HI":{
+      "shape":[[2254, 4585, 2254, 4606, 2228, 4628, 2227, 4605, 2254, 4585], [2319, 4564, 2350, 4551, 2385, 4559, 2393, 4577, 2383, 4610, 2361, 4625, 2334, 4617, 2305, 4588, 2319, 4564], [2597, 4694, 2619, 4684, 2634, 4731, 2654, 4734, 2664, 4766, 2634, 4772, 2610, 4758, 2611, 4743, 2600, 4747, 2608, 4758, 2584, 4760, 2558, 4702, 2597, 4694], [2790, 4803, 2827, 4807, 2796, 4829, 2719, 4809, 2731, 4787, 2790, 4803], [2835, 4839, 2851, 4839, 2864, 4864, 2908, 4860, 2948, 4903, 2921, 4921,  [...]
+      "center":[2703, 4833],
+      "bbox":[2227, 4551, 916, 711]
+    },
+    "ME":{
+      "shape":[7610, 288, 7625, 320, 7647, 327, 7714, 269, 7794, 304, 7867, 514, 7872, 558, 7925, 560, 7935, 577, 7924, 583, 7942, 600, 7938, 620, 7951, 635, 7967, 644, 7989, 630, 8016, 661, 8002, 670, 8009, 678, 7997, 675, 8010, 692, 8012, 675, 8023, 684, 8018, 671, 8036, 683, 8015, 725, 7984, 720, 7990, 744, 7983, 731, 7983, 745, 7967, 737, 7971, 762, 7958, 759, 7952, 775, 7939, 756, 7937, 801, 7931, 783, 7932, 800, 7922, 784, 7916, 789, 7929, 803, 7920, 819, 7884, 779, 7876, 786, 7891 [...]
+      "center":[7710, 682],
+      "bbox":[7468, 269, 569, 888]
+    },
+    "VA":{
+      "shape":[[7177, 2288, 7216, 2271, 7216, 2271, 7186, 2362, 7195, 2366, 7166, 2410, 7166, 2458, 7149, 2420, 7162, 2388, 7151, 2391, 7152, 2377, 7165, 2373, 7151, 2366, 7172, 2341, 7161, 2341, 7171, 2335, 7160, 2328, 7182, 2314, 7176, 2301, 7163, 2305, 7177, 2288], [6817, 2100, 6818, 2100, 6841, 2099, 6860, 2110, 6855, 2132, 6921, 2156, 6921, 2156, 6928, 2160, 6929, 2161, 6940, 2194, 6923, 2201, 6931, 2212, 6914, 2210, 6913, 2262, 6903, 2256, 6919, 2269, 6907, 2273, 6953, 2253, 6967,  [...]
+      "center":[6750, 2455],
+      "bbox":[6012, 2092, 1204, 676]
+    },
+    "MI":{
+      "shape":[[5098, 797, 5138, 760, 5201, 760, 5169, 771, 5115, 855, 5107, 841, 5115, 813, 5106, 835, 5083, 821, 5098, 797], [5071, 647, 5077, 644, 5024, 682, 5036, 684, 4995, 694, 5003, 677, 5095, 620, 5071, 647], [5296, 933, 5311, 924, 5362, 943, 5421, 886, 5578, 848, 5574, 904, 5628, 898, 5637, 911, 5670, 891, 5694, 937, 5683, 947, 5717, 955, 5713, 963, 5739, 981, 5654, 996, 5635, 982, 5627, 1025, 5589, 996, 5520, 987, 5503, 1014, 5421, 1028, 5412, 1058, 5384, 1077, 5382, 1099, 5366 [...]
+      "center":[5662, 1450],
+      "bbox":[4855, 620, 1168, 1218]
+    },
+    "DE":{
+      "shape":[7082, 1965, 7100, 1940, 7132, 1937, 7133, 1938, 7135, 1938, 7119, 1976, 7130, 2008, 7129, 2009, 7158, 2039, 7187, 2099, 7225, 2115, 7236, 2145, 7222, 2135, 7217, 2144, 7232, 2147, 7205, 2160, 7219, 2166, 7236, 2147, 7246, 2177, 7246, 2178, 7242, 2179, 7242, 2179, 7239, 2180, 7234, 2181, 7150, 2199, 7082, 1965],
+      "center":[7157, 2107],
+      "bbox":[7082, 1937, 163, 261]
+    },
+    "ID":{
+      "shape":[1428, 192, 1536, 217, 1550, 220, 1507, 416, 1537, 477, 1537, 498, 1526, 505, 1539, 522, 1521, 528, 1570, 572, 1620, 694, 1634, 689, 1638, 710, 1676, 715, 1641, 802, 1630, 805, 1638, 859, 1610, 874, 1616, 891, 1602, 915, 1628, 941, 1691, 907, 1704, 930, 1697, 943, 1706, 945, 1707, 996, 1731, 1041, 1724, 1076, 1764, 1103, 1769, 1166, 1787, 1189, 1802, 1167, 1854, 1183, 1871, 1163, 1982, 1188, 1979, 1168, 2000, 1150, 2037, 1210, 2037, 1210, 1959, 1681, 1903, 1671, 1536, 1604, [...]
+      "center":[1499, 1209],
+      "bbox":[1117, 192, 920, 1489]
+    },
+    "IA":{
+      "shape":[4779, 1552, 4779, 1554, 4782, 1580, 4804, 1599, 4789, 1625, 4809, 1695, 4860, 1714, 4871, 1739, 4871, 1740, 4911, 1792, 4944, 1810, 4945, 1869, 4908, 1927, 4825, 1952, 4817, 1986, 4843, 2012, 4843, 2044, 4825, 2066, 4822, 2096, 4782, 2118, 4789, 2150, 4781, 2154, 4781, 2154, 4734, 2111, 4171, 2132, 4143, 2131, 4125, 2102, 4136, 2071, 4126, 2040, 4131, 2018, 4119, 2014, 4127, 1995, 4115, 1986, 4121, 1965, 4095, 1948, 4099, 1898, 4089, 1865, 4074, 1860, 4059, 1827, 4054, 176 [...]
+      "center":[4463, 1860],
+      "bbox":[4018, 1552, 927, 602]
+    },
+    "MD":{
+      "shape":[[7242, 2179, 7246, 2178, 7246, 2180, 7245, 2203, 7242, 2179], [6546, 2075, 6559, 2073, 7050, 1972, 7082, 1965, 7150, 2199, 7234, 2181, 7233, 2182, 7240, 2190, 7225, 2191, 7243, 2203, 7215, 2270, 7216, 2271, 7177, 2288, 7177, 2288, 7142, 2302, 7158, 2270, 7138, 2277, 7150, 2256, 7125, 2268, 7144, 2239, 7125, 2242, 7133, 2204, 7122, 2248, 7107, 2224, 7111, 2256, 7075, 2228, 7068, 2236, 7054, 2214, 7065, 2220, 7082, 2197, 7064, 2193, 7061, 2204, 7056, 2185, 7095, 2191, 7108,  [...]
+      "center":[7052, 2222],
+      "bbox":[6546, 1965, 699, 337]
+    },
+    "MA":{
+      "shape":[[7758, 1469, 7708, 1483, 7719, 1484, 7734, 1449, 7758, 1469], [7302, 1314, 7309, 1313, 7393, 1294, 7414, 1289, 7429, 1285, 7575, 1251, 7591, 1222, 7631, 1200, 7632, 1202, 7623, 1212, 7635, 1211, 7646, 1230, 7639, 1232, 7674, 1236, 7634, 1264, 7649, 1271, 7632, 1292, 7640, 1303, 7626, 1303, 7631, 1317, 7671, 1313, 7707, 1352, 7696, 1344, 7692, 1357, 7719, 1364, 7728, 1388, 7767, 1391, 7757, 1396, 7800, 1365, 7776, 1328, 7753, 1328, 7777, 1323, 7817, 1385, 7806, 1370, 7814,  [...]
+      "center":[7490, 1333],
+      "bbox":[7302, 1200, 533, 284]
+    },
+    "AR":{
+      "shape":[4323, 2915, 4351, 2914, 5015, 2888, 5031, 2925, 4986, 2986, 5087, 2978, 5089, 2978, 5089, 2979, 5102, 2996, 5083, 3000, 5093, 3013, 5055, 3032, 5073, 3047, 5057, 3059, 5065, 3073, 5046, 3067, 5048, 3098, 5038, 3082, 5026, 3095, 5041, 3100, 5028, 3122, 5045, 3148, 5009, 3177, 5009, 3178, 5020, 3191, 5011, 3206, 4986, 3199, 4990, 3227, 4974, 3219, 4972, 3234, 4988, 3238, 4978, 3250, 4969, 3241, 4974, 3291, 4961, 3311, 4944, 3302, 4932, 3333, 4919, 3328, 4939, 3340, 4915, 335 [...]
+      "center":[4662, 3220],
+      "bbox":[4323, 2888, 779, 695]
+    },
+    "IL":{
+      "shape":[4871, 1739, 4872, 1739, 5275, 1711, 5276, 1714, 5277, 1759, 5328, 1857, 5328, 1858, 5370, 2310, 5358, 2319, 5366, 2336, 5355, 2353, 5379, 2385, 5386, 2426, 5342, 2519, 5321, 2525, 5333, 2543, 5316, 2567, 5323, 2594, 5311, 2594, 5322, 2613, 5322, 2614, 5305, 2642, 5320, 2674, 5261, 2698, 5266, 2759, 5185, 2735, 5158, 2769, 5164, 2782, 5166, 2783, 5147, 2769, 5138, 2770, 5143, 2784, 5127, 2775, 5103, 2732, 5116, 2710, 5098, 2652, 5045, 2615, 5030, 2621, 5032, 2605, 4964, 256 [...]
+      "center":[5115, 2145],
+      "bbox":[4770, 1711, 615, 1073]
+    },
+    "UT":{
+      "shape":[1536, 1604, 1903, 1671, 1959, 1681, 1956, 1693, 1927, 1871, 2214, 1915, 2213, 1925, 2105, 2676, 2039, 2667, 1351, 2546, 1345, 2545, 1536, 1604],
+      "center":[1781, 2167],
+      "bbox":[1345, 1604, 869, 1072]
+    },
+    "IN":{
+      "shape":[5428, 1839, 5717, 1806, 5718, 1819, 5721, 1845, 5778, 2313, 5777, 2313, 5768, 2324, 5779, 2338, 5773, 2350, 5788, 2355, 5786, 2374, 5734, 2399, 5695, 2396, 5701, 2433, 5675, 2455, 5666, 2484, 5645, 2489, 5637, 2538, 5620, 2553, 5585, 2539, 5567, 2513, 5574, 2523, 5553, 2530, 5550, 2566, 5531, 2585, 5501, 2558, 5472, 2578, 5462, 2603, 5385, 2574, 5383, 2602, 5340, 2587, 5340, 2610, 5323, 2613, 5322, 2613, 5311, 2594, 5323, 2594, 5316, 2567, 5333, 2543, 5321, 2525, 5342, 251 [...]
+      "center":[5553, 2130],
+      "bbox":[5311, 1806, 477, 807]
+    },
+    "MN":{
+      "shape":[3957, 591, 3967, 564, 3950, 502, 3976, 503, 4218, 503, 4217, 428, 4242, 430, 4260, 439, 4284, 553, 4388, 573, 4395, 595, 4463, 568, 4503, 569, 4544, 585, 4534, 600, 4562, 603, 4581, 646, 4594, 641, 4593, 620, 4621, 617, 4635, 642, 4688, 664, 4687, 676, 4779, 632, 4793, 661, 4874, 652, 4906, 674, 4958, 667, 4798, 754, 4628, 929, 4629, 930, 4604, 948, 4609, 1063, 4558, 1095, 4534, 1135, 4532, 1162, 4550, 1165, 4566, 1188, 4551, 1218, 4548, 1321, 4585, 1355, 4614, 1357, 4667, [...]
+      "center":[4328, 1050],
+      "bbox":[3950, 428, 1007, 1142]
+    },
+    "AZ":{
+      "shape":[2105, 2676, 1948, 3757, 1919, 3753, 1616, 3706, 1051, 3370, 1074, 3333, 1075, 3331, 1106, 3331, 1121, 3315, 1121, 3280, 1092, 3262, 1105, 3229, 1097, 3220, 1102, 3200, 1139, 3179, 1153, 3106, 1178, 3078, 1229, 3058, 1196, 3013, 1193, 2962, 1174, 2927, 1179, 2903, 1179, 2903, 1179, 2902, 1195, 2871, 1202, 2695, 1260, 2695, 1276, 2722, 1293, 2725, 1315, 2697, 1345, 2545, 1345, 2545, 1351, 2546, 2039, 2667, 2105, 2676],
+      "center":[1610, 3091],
+      "bbox":[1051, 2545, 1054, 1212]
+    },
+    "MO":{
+      "shape":[4781, 2154, 4780, 2155, 4770, 2203, 4796, 2279, 4895, 2364, 4915, 2433, 4940, 2417, 4992, 2437, 4960, 2538, 4964, 2560, 5032, 2605, 5030, 2621, 5045, 2615, 5098, 2652, 5116, 2710, 5103, 2732, 5127, 2775, 5143, 2784, 5138, 2770, 5147, 2769, 5166, 2783, 5167, 2783, 5161, 2817, 5171, 2825, 5159, 2831, 5160, 2860, 5137, 2853, 5129, 2880, 5128, 2881, 5118, 2882, 5118, 2880, 5110, 2865, 5109, 2880, 5110, 2881, 5115, 2907, 5100, 2914, 5113, 2927, 5089, 2931, 5107, 2950, 5089, 297 [...]
+      "center":[4649, 2529],
+      "bbox":[4142, 2111, 1030, 875]
+    },
+    "MT":{
+      "shape":[3074, 458, 3023, 1050, 3022, 1057, 3005, 1232, 3001, 1232, 2053, 1110, 2042, 1174, 2037, 1210, 2000, 1150, 1979, 1168, 1982, 1188, 1871, 1163, 1854, 1183, 1802, 1167, 1787, 1189, 1769, 1166, 1764, 1103, 1724, 1076, 1731, 1041, 1707, 996, 1706, 945, 1697, 943, 1704, 930, 1691, 907, 1628, 941, 1602, 915, 1616, 891, 1610, 874, 1638, 859, 1630, 805, 1641, 802, 1676, 715, 1638, 710, 1634, 689, 1620, 694, 1570, 572, 1521, 528, 1539, 522, 1526, 505, 1537, 498, 1537, 477, 1507, 41 [...]
+      "center":[2366, 706],
+      "bbox":[1507, 220, 1567, 1012]
+    },
+    "MS":{
+      "shape":[5342, 3152, 5360, 3170, 5349, 3751, 5385, 4042, 5385, 4042, 5370, 4056, 5286, 4042, 5308, 4047, 5237, 4070, 5243, 4062, 5228, 4057, 5213, 4094, 5200, 4096, 5199, 4096, 5183, 4090, 5138, 4007, 5153, 3940, 4836, 3959, 4848, 3948, 4831, 3910, 4853, 3903, 4842, 3879, 4858, 3885, 4850, 3857, 4869, 3845, 4850, 3837, 4867, 3838, 4872, 3813, 4891, 3811, 4873, 3810, 4877, 3794, 4892, 3798, 4918, 3759, 4905, 3747, 4918, 3752, 4929, 3733, 4903, 3736, 4902, 3724, 4931, 3722, 4948, 368 [...]
+      "center":[5130, 3618],
+      "bbox":[4831, 3152, 554, 944]
+    },
+    "NH":{
+      "shape":[7427, 828, 7425, 784, 7467, 758, 7468, 758, 7581, 1111, 7613, 1135, 7616, 1152, 7616, 1153, 7608, 1172, 7618, 1155, 7636, 1165, 7631, 1199, 7631, 1200, 7591, 1222, 7575, 1251, 7429, 1285, 7414, 1289, 7394, 1266, 7402, 1236, 7383, 1128, 7404, 1022, 7390, 984, 7444, 926, 7445, 909, 7424, 882, 7434, 848, 7427, 828],
+      "center":[7487, 1110],
+      "bbox":[7383, 758, 253, 531]
+    },
+    "NJ":{
+      "shape":[7167, 1623, 7175, 1625, 7297, 1663, 7292, 1722, 7290, 1722, 7255, 1776, 7310, 1776, 7302, 1788, 7313, 1783, 7311, 1794, 7305, 1766, 7312, 1771, 7319, 1834, 7309, 1835, 7321, 1839, 7325, 1898, 7317, 1844, 7308, 1847, 7317, 1847, 7308, 1852, 7315, 1867, 7304, 1869, 7317, 1870, 7319, 1912, 7299, 1943, 7306, 1955, 7288, 1950, 7297, 1971, 7285, 1979, 7298, 1986, 7264, 2005, 7281, 2005, 7260, 2061, 7254, 2048, 7258, 2069, 7235, 2086, 7234, 2040, 7200, 2046, 7131, 2007, 7130, 200 [...]
+      "center":[7248, 1862],
+      "bbox":[7119, 1623, 206, 464]
+    },
+    "NM":{
+      "shape":[2105, 2676, 2182, 2687, 3017, 2778, 3031, 2779, 3030, 2791, 3023, 2874, 3017, 2874, 2946, 3738, 2363, 3681, 2358, 3706, 2373, 3724, 2337, 3720, 2098, 3690, 2086, 3776, 1953, 3758, 1948, 3757, 2105, 2676],
+      "center":[2533, 3173],
+      "bbox":[1948, 2676, 1083, 1100]
+    },
+    "AK":{
+      "shape":[620, 3939, 642, 3931, 650, 3935, 643, 3931, 675, 3922, 680, 3925, 667, 3924, 694, 3939, 689, 3941, 699, 3939, 714, 3945, 716, 3951, 700, 3957, 686, 3954, 692, 3958, 682, 3955, 685, 3953, 664, 3953, 690, 3958, 684, 3960, 693, 3962, 682, 3961, 693, 3964, 689, 3969, 696, 3965, 713, 3966, 721, 3973, 725, 3971, 714, 3968, 714, 3961, 731, 3962, 728, 3956, 734, 3954, 738, 3960, 738, 3953, 741, 3955, 737, 3962, 744, 3956, 760, 3968, 750, 3974, 776, 3987, 791, 3982, 827, 3987, 846, [...]
+      "center":[813, 4358],
+      "bbox":[17, 3922, 1806, 1313]
+    },
+    "TX":{
+      "shape":[[3960, 4548, 3926, 4590, 3956, 4534, 4038, 4483, 3960, 4548], [3765, 3367, 3774, 3393, 3796, 3396, 3793, 3416, 3813, 3422, 3840, 3397, 3880, 3431, 3914, 3413, 3927, 3451, 3950, 3405, 3986, 3430, 4014, 3417, 4009, 3427, 4053, 3458, 4085, 3428, 4145, 3427, 4173, 3408, 4222, 3421, 4233, 3404, 4291, 3445, 4352, 3464, 4354, 3465, 4369, 3483, 4424, 3481, 4426, 3583, 4426, 3596, 4431, 3781, 4468, 3822, 4467, 3859, 4487, 3873, 4481, 3881, 4500, 3900, 4492, 3912, 4519, 3935, 4524,  [...]
+      "center":[3629, 3892],
+      "bbox":[2358, 2874, 2166, 2107]
+    },
+    "AL":{
+      "shape":[5342, 3152, 5751, 3113, 5757, 3137, 5866, 3512, 5911, 3591, 5907, 3611, 5927, 3621, 5902, 3649, 5896, 3708, 5919, 3762, 5916, 3831, 5939, 3865, 5910, 3869, 5508, 3912, 5506, 3942, 5548, 3975, 5545, 4009, 5544, 4009, 5552, 4017, 5539, 4037, 5516, 4037, 5518, 4048, 5534, 4045, 5527, 4052, 5450, 4070, 5500, 4054, 5480, 4029, 5466, 4030, 5458, 3981, 5441, 3978, 5426, 4000, 5435, 4008, 5430, 4053, 5386, 4042, 5385, 4042, 5349, 3751, 5360, 3170, 5342, 3152],
+      "center":[5617, 3547],
+      "bbox":[5342, 3113, 596, 956]
+    },
+    "NC":{
+      "shape":[[7201, 2563, 7205, 2562, 7205, 2563, 7287, 2693, 7245, 2651, 7201, 2563], [6319, 2725, 6333, 2723, 7179, 2568, 7180, 2569, 7175, 2579, 7200, 2600, 7202, 2588, 7236, 2649, 7199, 2610, 7200, 2632, 7214, 2636, 7164, 2617, 7193, 2645, 7174, 2653, 7155, 2639, 7171, 2659, 7130, 2648, 7157, 2663, 7130, 2669, 7142, 2671, 7119, 2688, 7091, 2665, 7093, 2636, 7052, 2626, 7089, 2638, 7098, 2707, 7206, 2677, 7191, 2684, 7209, 2684, 7198, 2697, 7209, 2714, 7198, 2716, 7215, 2729, 7199,  [...]
+      "center":[6700, 2826],
+      "bbox":[5952, 2562, 1361, 590]
+    },
+    "ND":{
+      "shape":[3950, 502, 3967, 564, 3957, 591, 3957, 592, 3959, 670, 3996, 776, 3997, 891, 4008, 907, 4001, 959, 4028, 1023, 4033, 1100, 4002, 1099, 3164, 1062, 3023, 1050, 3074, 458, 3116, 461, 3950, 502],
+      "center":[3524, 756],
+      "bbox":[3023, 458, 1010, 642]
+    },
+    "NE":{
+      "shape":[2971, 1616, 2976, 1616, 3755, 1662, 3820, 1709, 3848, 1690, 3931, 1693, 4010, 1732, 4020, 1761, 4043, 1765, 4044, 1765, 4045, 1765, 4054, 1768, 4059, 1827, 4074, 1860, 4089, 1865, 4099, 1898, 4095, 1948, 4121, 1965, 4115, 1986, 4127, 1995, 4119, 2014, 4131, 2018, 4126, 2040, 4136, 2071, 4125, 2102, 4143, 2131, 4142, 2133, 4159, 2139, 4159, 2184, 4185, 2197, 4195, 2236, 4211, 2244, 4206, 2243, 3243, 2215, 3215, 2213, 3228, 2022, 3006, 2005, 2937, 1999, 2971, 1616, 2971, 1616],
+      "center":[3612, 1930],
+      "bbox":[2937, 1616, 1274, 628]
+    },
+    "NY":{
+      "shape":[[7362, 1671, 7357, 1658, 7401, 1659, 7402, 1642, 7477, 1620, 7517, 1573, 7481, 1633, 7506, 1626, 7517, 1598, 7550, 1598, 7581, 1575, 7480, 1659, 7339, 1731, 7361, 1728, 7312, 1749, 7333, 1725, 7294, 1740, 7303, 1702, 7327, 1700, 7328, 1680, 7341, 1689, 7346, 1667, 7362, 1671], [7184, 893, 7196, 969, 7218, 999, 7216, 1076, 7241, 1126, 7239, 1162, 7255, 1151, 7267, 1166, 7302, 1314, 7302, 1327, 7304, 1452, 7307, 1462, 7331, 1595, 7345, 1608, 7315, 1637, 7331, 1657, 7330, 165 [...]
+      "center":[6982, 1368],
+      "bbox":[6418, 893, 1163, 873]
+    },
+    "GA":{
+      "shape":[6143, 3060, 6144, 3060, 6113, 3123, 6176, 3156, 6176, 3156, 6196, 3157, 6258, 3247, 6374, 3325, 6375, 3348, 6410, 3379, 6457, 3400, 6481, 3470, 6523, 3496, 6545, 3561, 6579, 3568, 6580, 3568, 6593, 3574, 6582, 3589, 6576, 3573, 6575, 3590, 6562, 3577, 6582, 3595, 6574, 3607, 6549, 3590, 6554, 3602, 6539, 3599, 6557, 3608, 6523, 3597, 6568, 3616, 6555, 3636, 6545, 3622, 6548, 3636, 6521, 3624, 6546, 3641, 6534, 3650, 6555, 3641, 6558, 3655, 6553, 3669, 6540, 3655, 6547, 366 [...]
+      "center":[6159, 3499],
+      "bbox":[5751, 3060, 842, 864]
+    },
+    "NV":{
+      "shape":[1536, 1604, 1345, 2545, 1345, 2545, 1315, 2697, 1293, 2725, 1276, 2722, 1260, 2695, 1202, 2695, 1195, 2871, 1179, 2902, 1179, 2903, 553, 1964, 701, 1416, 703, 1408, 722, 1413, 1117, 1512, 1117, 1512, 1118, 1512, 1535, 1604, 1536, 1604],
+      "center":[1045, 1927],
+      "bbox":[553, 1408, 983, 1495]
+    },
+    "TN":{
+      "shape":[6012, 2768, 6017, 2767, 6319, 2725, 6319, 2725, 6322, 2773, 6293, 2785, 6278, 2822, 6229, 2830, 6202, 2866, 6186, 2847, 6165, 2877, 6147, 2879, 6140, 2910, 6114, 2916, 6067, 2961, 6009, 2978, 5990, 3001, 5989, 3028, 5952, 3042, 5953, 3088, 5944, 3089, 5772, 3111, 5751, 3113, 5342, 3152, 5341, 3152, 5014, 3177, 5009, 3177, 5045, 3148, 5028, 3122, 5041, 3100, 5026, 3095, 5038, 3082, 5048, 3098, 5046, 3067, 5065, 3073, 5057, 3059, 5073, 3047, 5055, 3032, 5093, 3013, 5083, 300 [...]
+      "center":[5533, 2967],
+      "bbox":[5009, 2725, 1313, 453]
+    },
+    "CA":{
+      "shape":[124, 1236, 703, 1408, 701, 1416, 553, 1964, 1179, 2903, 1179, 2903, 1174, 2927, 1193, 2962, 1196, 3013, 1229, 3058, 1178, 3078, 1153, 3106, 1139, 3179, 1102, 3200, 1097, 3220, 1105, 3229, 1092, 3262, 1121, 3280, 1121, 3315, 1106, 3331, 1075, 3331, 1073, 3331, 684, 3281, 675, 3245, 689, 3269, 691, 3255, 679, 3241, 671, 3251, 680, 3184, 663, 3123, 582, 3010, 537, 3005, 544, 2987, 533, 2946, 487, 2941, 442, 2909, 390, 2833, 254, 2790, 232, 2760, 261, 2654, 231, 2628, 243, 260 [...]
+      "center":[507, 2428],
+      "bbox":[0, 1236, 1229, 2095]
+    },
+    "OK":{
+      "shape":[3178, 2791, 3178, 2791, 4284, 2819, 4321, 2819, 4322, 2863, 4323, 2915, 4327, 2945, 4356, 3126, 4352, 3449, 4352, 3464, 4291, 3445, 4233, 3404, 4222, 3421, 4173, 3408, 4145, 3427, 4085, 3428, 4053, 3458, 4009, 3427, 4014, 3417, 3986, 3430, 3950, 3405, 3927, 3451, 3914, 3413, 3880, 3431, 3840, 3397, 3813, 3422, 3793, 3416, 3796, 3396, 3774, 3393, 3765, 3367, 3765, 3367, 3729, 3362, 3710, 3380, 3692, 3360, 3598, 3347, 3595, 3323, 3571, 3299, 3565, 3315, 3520, 3312, 3484, 327 [...]
+      "center":[3930, 3108],
+      "bbox":[3023, 2779, 1332, 686]
+    },
+    "OH":{
+      "shape":[5911, 1786, 5991, 1817, 6004, 1801, 5999, 1814, 6023, 1808, 5975, 1832, 6041, 1829, 6027, 1817, 6061, 1832, 6123, 1797, 6162, 1796, 6219, 1734, 6320, 1675, 6321, 1675, 6364, 1929, 6364, 1929, 6345, 1942, 6363, 1991, 6345, 2130, 6303, 2183, 6281, 2195, 6267, 2184, 6254, 2214, 6237, 2217, 6224, 2255, 6236, 2284, 6216, 2296, 6209, 2275, 6192, 2271, 6172, 2320, 6184, 2354, 6168, 2361, 6166, 2388, 6127, 2398, 6127, 2398, 6084, 2371, 6074, 2341, 6017, 2380, 5981, 2364, 5961, 238 [...]
+      "center":[6096, 2082],
+      "bbox":[5718, 1675, 646, 724]
+    },
+    "WY":{
+      "shape":[3005, 1232, 3004, 1235, 2971, 1616, 2971, 1616, 2937, 1999, 2924, 1998, 2225, 1917, 2214, 1915, 1927, 1871, 1956, 1693, 1959, 1681, 2037, 1210, 2037, 1210, 2042, 1174, 2053, 1110, 3001, 1232, 3005, 1232],
+      "center":[2487, 1535],
+      "bbox":[1927, 1110, 1078, 889]
+    },
+    "FL":{
+      "shape":[6508, 3840, 6528, 3854, 6539, 3839, 6543, 3875, 6530, 3858, 6584, 4003, 6595, 4014, 6587, 3987, 6675, 4136, 6637, 4084, 6664, 4136, 6750, 4223, 6762, 4245, 6748, 4256, 6756, 4285, 6793, 4358, 6731, 4264, 6724, 4233, 6740, 4221, 6739, 4270, 6756, 4303, 6745, 4219, 6711, 4219, 6718, 4202, 6694, 4187, 6727, 4263, 6862, 4481, 6836, 4471, 6851, 4487, 6868, 4482, 6890, 4522, 6876, 4517, 6902, 4547, 6896, 4539, 6921, 4741, 6919, 4751, 6915, 4716, 6894, 4786, 6893, 4872, 6861, 486 [...]
+      "center":[6585, 4335],
+      "bbox":[5506, 3827, 1414, 1079]
+    },
+    "SD":{
+      "shape":[3023, 1050, 3164, 1062, 4002, 1099, 4033, 1100, 4029, 1123, 3992, 1163, 4047, 1222, 4045, 1570, 4025, 1570, 4035, 1591, 4026, 1613, 4047, 1642, 4018, 1718, 4044, 1765, 4043, 1765, 4020, 1761, 4010, 1732, 3931, 1693, 3848, 1690, 3820, 1709, 3755, 1662, 2976, 1616, 2971, 1616, 3004, 1235, 3005, 1232, 3022, 1057, 3023, 1050],
+      "center":[3544, 1347],
+      "bbox":[2971, 1050, 1076, 715]
+    },
+    "SC":{
+      "shape":[6176, 3156, 6113, 3123, 6144, 3060, 6143, 3060, 6249, 3003, 6461, 2982, 6465, 3002, 6480, 2987, 6509, 3016, 6511, 3038, 6686, 3010, 6891, 3152, 6891, 3152, 6826, 3243, 6815, 3270, 6821, 3298, 6801, 3279, 6812, 3254, 6800, 3266, 6799, 3286, 6821, 3302, 6814, 3316, 6806, 3304, 6812, 3316, 6795, 3313, 6807, 3317, 6785, 3340, 6797, 3341, 6769, 3342, 6758, 3362, 6768, 3367, 6729, 3404, 6719, 3386, 6734, 3368, 6716, 3392, 6709, 3373, 6716, 3402, 6698, 3393, 6727, 3408, 6714, 342 [...]
+      "center":[6541, 3231],
+      "bbox":[6113, 2982, 779, 586]
+    },
+    "CT":{
+      "shape":[7541, 1398, 7568, 1526, 7567, 1528, 7539, 1536, 7531, 1523, 7535, 1539, 7521, 1547, 7504, 1553, 7491, 1539, 7496, 1559, 7426, 1581, 7424, 1569, 7401, 1605, 7331, 1655, 7331, 1657, 7315, 1637, 7345, 1608, 7331, 1595, 7307, 1462, 7304, 1452, 7321, 1448, 7541, 1398],
+      "center":[7442, 1505],
+      "bbox":[7304, 1398, 264, 259]
+    },
+    "WV":{
+      "shape":[6364, 1929, 6369, 1959, 6394, 2102, 6546, 2075, 6549, 2091, 6565, 2173, 6610, 2111, 6632, 2114, 6652, 2069, 6669, 2087, 6701, 2086, 6702, 2065, 6726, 2061, 6736, 2044, 6790, 2051, 6785, 2062, 6804, 2069, 6817, 2100, 6817, 2101, 6809, 2139, 6720, 2092, 6723, 2150, 6670, 2239, 6647, 2227, 6621, 2315, 6560, 2293, 6550, 2358, 6492, 2481, 6507, 2491, 6493, 2505, 6500, 2512, 6479, 2534, 6467, 2527, 6433, 2553, 6418, 2545, 6415, 2567, 6368, 2591, 6344, 2575, 6301, 2608, 6258, 258 [...]
+      "center":[6378, 2332],
+      "bbox":[6127, 1929, 690, 680]
+    },
+    "DC":{
+      "shape":[6928, 2160, 6921, 2156, 6921, 2156, 6924, 2150, 6930, 2142, 6953, 2157, 6940, 2177, 6939, 2177, 6944, 2161, 6928, 2160],
+      "center":[6934, 2153],
+      "bbox":[6921, 2142, 33, 36]
+    },
+    "WI":{
+      "shape":[[5338, 1169, 5315, 1247, 5302, 1264, 5292, 1258, 5286, 1242, 5305, 1190, 5314, 1193, 5326, 1164, 5338, 1169], [4702, 927, 4791, 882, 4806, 895, 4783, 954, 4818, 940, 4808, 931, 4855, 954, 4855, 954, 4883, 965, 4898, 996, 5176, 1057, 5173, 1078, 5222, 1098, 5217, 1122, 5225, 1135, 5213, 1163, 5244, 1157, 5236, 1192, 5255, 1208, 5256, 1209, 5255, 1232, 5227, 1244, 5210, 1289, 5214, 1313, 5205, 1316, 5221, 1322, 5264, 1256, 5284, 1246, 5301, 1264, 5282, 1331, 5285, 1384, 5268 [...]
+      "center":[4969, 1326],
+      "bbox":[4532, 882, 805, 857]
+    },
+    "KY":{
+      "shape":[[5118, 2880, 5110, 2881, 5109, 2880, 5110, 2865, 5118, 2880], [5778, 2313, 5780, 2312, 5831, 2303, 5874, 2358, 5927, 2360, 5961, 2382, 5981, 2364, 6017, 2380, 6074, 2341, 6084, 2371, 6127, 2398, 6127, 2398, 6127, 2399, 6128, 2452, 6159, 2478, 6155, 2489, 6192, 2533, 6212, 2535, 6222, 2552, 6247, 2551, 6247, 2552, 6230, 2571, 6144, 2648, 6127, 2694, 6098, 2707, 6091, 2729, 6012, 2768, 6011, 2769, 5334, 2828, 5339, 2863, 5140, 2878, 5129, 2880, 5137, 2853, 5160, 2860, 5159,  [...]
+      "center":[5828, 2581],
+      "bbox":[5109, 2303, 1138, 577]
+    },
+    "KS":{
+      "shape":[3215, 2213, 3243, 2215, 4206, 2243, 4211, 2244, 4210, 2245, 4242, 2269, 4266, 2264, 4277, 2292, 4262, 2293, 4241, 2331, 4274, 2360, 4282, 2393, 4319, 2406, 4321, 2819, 4284, 2819, 3178, 2791, 3178, 2791, 3210, 2296, 3215, 2213],
+      "center":[3753, 2506],
+      "bbox":[3178, 2213, 1143, 606]
+    },
+    "OR":{
+      "shape":[477, 509, 504, 509, 532, 539, 534, 584, 521, 593, 534, 585, 521, 632, 526, 623, 577, 662, 633, 657, 633, 657, 691, 657, 734, 693, 810, 686, 863, 705, 955, 690, 1008, 704, 1037, 696, 1297, 762, 1309, 764, 1309, 766, 1319, 800, 1346, 822, 1352, 851, 1276, 949, 1267, 976, 1234, 998, 1194, 1057, 1195, 1080, 1231, 1110, 1197, 1168, 1117, 1512, 1117, 1512, 722, 1413, 703, 1408, 124, 1236, 124, 1235, 110, 1211, 113, 1167, 135, 1113, 125, 1067, 178, 985, 186, 997, 204, 973, 210, 9 [...]
+      "center":[746, 1019],
+      "bbox":[110, 466, 1241, 1045]
+    },
+    "LA":{
+      "shape":[4426, 3583, 4464, 3582, 4879, 3569, 4894, 3568, 4894, 3569, 4889, 3586, 4903, 3571, 4912, 3587, 4897, 3615, 4915, 3623, 4900, 3641, 4922, 3637, 4913, 3654, 4928, 3664, 4910, 3656, 4908, 3669, 4932, 3675, 4928, 3692, 4948, 3689, 4931, 3722, 4902, 3724, 4903, 3736, 4929, 3733, 4918, 3752, 4905, 3747, 4918, 3759, 4892, 3798, 4877, 3794, 4873, 3810, 4891, 3811, 4872, 3813, 4867, 3838, 4850, 3837, 4869, 3845, 4850, 3857, 4858, 3885, 4842, 3879, 4853, 3903, 4831, 3910, 4848, 394 [...]
+      "center":[4688, 3984],
+      "bbox":[4426, 3568, 872, 772]
+    },
+    "WA":{
+      "shape":[717, 0, 1411, 188, 1428, 192, 1306, 692, 1315, 731, 1304, 745, 1309, 764, 1297, 762, 1037, 696, 1008, 704, 955, 690, 863, 705, 810, 686, 734, 693, 691, 657, 633, 657, 633, 656, 586, 660, 539, 635, 528, 620, 541, 567, 535, 534, 510, 509, 483, 507, 446, 465, 392, 456, 416, 389, 407, 438, 415, 443, 422, 427, 431, 442, 422, 423, 431, 419, 429, 393, 435, 403, 437, 387, 456, 393, 444, 375, 417, 370, 422, 336, 433, 355, 435, 342, 468, 337, 434, 312, 419, 331, 430, 294, 436, 171,  [...]
+      "center":[952, 376],
+      "bbox":[392, 0, 1036, 764]
+    },
+    "CO":{
+      "shape":[2214, 1915, 2225, 1917, 2924, 1998, 2937, 1999, 3006, 2005, 3228, 2022, 3215, 2213, 3210, 2296, 3178, 2791, 3134, 2787, 3031, 2779, 3017, 2778, 2182, 2687, 2105, 2676, 2213, 1925, 2214, 1915],
+      "center":[2749, 2301],
+      "bbox":[2105, 1915, 1123, 875]
+    },
+    "PA":{
+      "shape":[6321, 1675, 6417, 1602, 6418, 1601, 6427, 1652, 7046, 1524, 7066, 1546, 7094, 1550, 7103, 1589, 7121, 1609, 7167, 1623, 7166, 1623, 7122, 1706, 7138, 1727, 7125, 1764, 7132, 1786, 7151, 1788, 7157, 1810, 7217, 1848, 7133, 1938, 7132, 1937, 7100, 1940, 7082, 1965, 7050, 1972, 6559, 2073, 6546, 2075, 6394, 2102, 6369, 1959, 6364, 1929, 6321, 1675],
+      "center":[6777, 1802],
+      "bbox":[6321, 1524, 896, 578]
+    }
+  }
+}
diff --git a/dojox/geo/charting/resources/img/zoomin.gif b/dojox/geo/charting/resources/img/zoomin.gif
new file mode 100644
index 0000000..45fc12b
Binary files /dev/null and b/dojox/geo/charting/resources/img/zoomin.gif differ
diff --git a/dojox/geo/charting/resources/img/zoomin.png b/dojox/geo/charting/resources/img/zoomin.png
new file mode 100644
index 0000000..fed568a
Binary files /dev/null and b/dojox/geo/charting/resources/img/zoomin.png differ
diff --git a/dojox/geo/charting/resources/img/zoomout.gif b/dojox/geo/charting/resources/img/zoomout.gif
new file mode 100644
index 0000000..780b747
Binary files /dev/null and b/dojox/geo/charting/resources/img/zoomout.gif differ
diff --git a/dojox/geo/charting/resources/img/zoomout.png b/dojox/geo/charting/resources/img/zoomout.png
new file mode 100644
index 0000000..f62af36
Binary files /dev/null and b/dojox/geo/charting/resources/img/zoomout.png differ
diff --git a/dojox/geo/charting/resources/markers/USStates.json b/dojox/geo/charting/resources/markers/USStates.json
new file mode 100644
index 0000000..929dab3
--- /dev/null
+++ b/dojox/geo/charting/resources/markers/USStates.json
@@ -0,0 +1 @@
+{"AK":"Alaska","AZ":"Arizona","AR":"Arkansas","AL":"Alabama","CA":"California","CO":"Colorado","CT":"Connecticut","DE":"Delaware","FL":"Florida","GA":"Georgia","HI":"Hawaii","ID":"Idaho","IL":"Illinois","IN":"Indiana","IA":"Iowa","KS":"Kansas","KY":"Kentucky","LA":"Louisiana","ME":"Maine","MD":"Maryland","MA":"Massachusetts","MI":"Michigan","MN":"Minnesota","MS":"Mississippi","MO":"Missouri","MT":"Montana","NE":"Nebraska","NV":"Nevada","NH":"New Hampshire","NJ":"New Jersey","NM":"New Mex [...]
diff --git a/dojox/geo/charting/tests/datastore/dataStore.json b/dojox/geo/charting/tests/datastore/dataStore.json
new file mode 100644
index 0000000..73459db
--- /dev/null
+++ b/dojox/geo/charting/tests/datastore/dataStore.json
@@ -0,0 +1 @@
+{"identifier":"product","idAttribute":"product","label":"product","items":[{"product":"A","RI":7.462633468705088,"VT":1.0747727711335298,"HI":5.799375636164497,"ME":1.451271727380056,"VA":2.829702713495596,"MI":5.642995600110112,"DE":2.739617463034918,"ID":2.363980549092777,"IA":7.431769770088566,"MD":3.0785135982470684,"MA":1.7526041060228308,"AR":3.8586965961630613,"IL":4.429268677942292,"UT":1.4132568641617622,"IN":4.278380121077843,"MN":1.7667677604047078,"AZ":3.1685622594553893,"MO" [...]
\ No newline at end of file
diff --git a/dojox/geo/charting/tests/test_mapWithCharting.html b/dojox/geo/charting/tests/test_mapWithCharting.html
new file mode 100644
index 0000000..2544633
--- /dev/null
+++ b/dojox/geo/charting/tests/test_mapWithCharting.html
@@ -0,0 +1,72 @@
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>Chart: Map&Chart</title>
+		<style type="text/css">
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../../../dijit/tests/css/dijitTests.css";
+			@import "../../../../dijit/themes/tundra/tundra.css";
+			@import "../resources/Map.css";
+			.mapContainer {
+				display: none;
+				width: 810px;
+				height: 400px;
+				border: solid 1px;
+			}
+			
+			.mapVerticalContainer {
+				display: none;
+				width: 405px;
+				height: 500px;
+				border: solid 1px;
+			}
+		</style>
+		<script type="text/javascript" djConfig="parseOnLoad:true,gfxRenderer:'svg,vml,silverlight'" src="../../../../dojo/dojo.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.geo.charting.Map");
+			dojo.require("dojox.charting.DataChart");
+			dojo.require("dojo.data.ItemFileReadStore");
+			var chartStore = new dojo.data.ItemFileReadStore({
+				url: "datastore/dataStore.json"
+			});
+			var chart;
+			dojo.addOnLoad(function(){
+				chart = new dojox.charting.DataChart("chartDiv", {
+					displayRange: 8,
+					yaxis: {
+						max: 8,
+						min: 1,
+						majorTickStep: 1,
+						labelFunc: "seriesLabels",
+						maxLabelSize: 30
+					},
+					scroll: false
+				});
+				chart.addPlot("default", {
+					type: "Bars",
+					gap: 2,
+					animate: {
+						duration: 1000
+					}
+				});
+				
+				var map = new dojox.geo.charting.Map("map", "../resources/data/USStates.json");
+				map.setMarkerData("../resources/markers/USStates.json");
+				map.onFeatureClick = function(feature){
+					if (!feature._isFocused) {
+						chart.setStore(chartStore, {
+							product: "*"
+						}, feature.id);
+					}
+				};
+			});
+		</script>
+	</head>
+	<body class="tundra">
+		<h1>Map connect with DataChart(Click on map)</h1>
+		<div style="width:610px;height:400px;border:solid 1px;background:#f5f5f5;" id="map">
+		</div>
+		<div id="chartDiv" style="width: 400px; height: 150px;">
+		</div>
+	</body>
+</html>
diff --git a/dojox/geo/charting/tests/test_mapWithLegend.html b/dojox/geo/charting/tests/test_mapWithLegend.html
new file mode 100644
index 0000000..6606a35
--- /dev/null
+++ b/dojox/geo/charting/tests/test_mapWithLegend.html
@@ -0,0 +1,63 @@
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<title>Chart: Map&Legend</title>
+		<style type="text/css">
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../../../dijit/tests/css/dijitTests.css";
+			@import "../../../../dijit/themes/tundra/tundra.css";
+			@import "../resources/Map.css";
+		</style>
+		<script type="text/javascript" djConfig="parseOnLoad:true,gfxRenderer:'svg,vml,silverlight'" src="../../../../dojo/dojo.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.geo.charting.Map");
+			dojo.require("dojox.geo.charting.widget.Legend");
+			dojo.require("dojo.data.ItemFileReadStore");
+			dojo.addOnLoad(function(){
+				//create new map
+				var map = new dojox.geo.charting.Map("USStates", "../resources/data/USStates.json");
+				//add outside map marker file
+				map.setMarkerData("../resources/markers/USStates.json");
+				//set data store to map
+				var dataStore = new dojo.data.ItemFileReadStore({
+					url: "datastore/dataStore.json"
+				});
+				map.setDataStore(dataStore, {
+					product: "A"
+				});
+				//add series to map 
+				map.addSeries([{
+					name: "Low sales state(0~$3.0M)",
+					min: "0.0",
+					max: "3.0",
+					color: "#FFCE52"
+				}, {
+					name: "Normal sales state($3.0M~$6.0M)",
+					min: "3.0",
+					max: "6.0",
+					color: "#63A584"
+				}, {
+					name: "High sales state($6.0M~$10.0M)",
+					min: "6.0",
+					max: "9.0",
+					color: "#CE6342"
+				}]);
+				//declare associated legend
+				var legend = new dojox.geo.charting.widget.Legend({
+					map: map
+				});
+				//map marker customization
+				map.onFeatureOver = function(feature){
+					if(!feature.markerText){
+						feature.markerText = map.mapObj.marker.markerData[feature.id] + ": $" + feature.value.toFixed(3) + "M";
+					}
+				};
+			});
+		</script>
+	</head>
+	<body class="tundra">
+		<h1>Map with series, data, legend</h1>
+		<div id="USStates" style="width:900px;height:500px;border:1px solid;">
+		</div>
+	</body>
+</html>
diff --git a/dojox/geo/charting/tests/test_maps.html b/dojox/geo/charting/tests/test_maps.html
new file mode 100644
index 0000000..88d7ab8
--- /dev/null
+++ b/dojox/geo/charting/tests/test_maps.html
@@ -0,0 +1,37 @@
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		<title>Chart: Map</title>
+		<style type="text/css">
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../../../dijit/tests/css/dijitTests.css";
+			@import "../../../../dijit/themes/tundra/tundra.css";
+			@import "../resources/Map.css";
+			.mapContainer {
+				display: none;
+				width: 810px;
+				height: 400px;
+				border: solid 1px;
+			}
+			
+			.mapVerticalContainer {
+				display: none;
+				width: 405px;
+				height: 500px;
+				border: solid 1px;
+			}
+		</style>
+		<script type="text/javascript" djConfig="parseOnLoad:true,gfxRenderer:'svg,vml,silverlight'" src="../../../../dojo/dojo.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.geo.charting.Map");
+			dojo.addOnLoad(function(){
+				var USStates = new dojox.geo.charting.Map("USStates", "../resources/data/USStates.json");
+				USStates.setMarkerData("../resources/markers/USStates.json");
+			});
+		</script>
+	</head>
+	<body class="tundra">
+		<h1>Simple Maps,support zoom in and zoom out.</h1>
+		<div class="mapContainer" style="display:block;" id="USStates"></div>
+	</body>
+</html>
diff --git a/dojox/geo/charting/widget/Legend.js b/dojox/geo/charting/widget/Legend.js
new file mode 100644
index 0000000..740bbca
--- /dev/null
+++ b/dojox/geo/charting/widget/Legend.js
@@ -0,0 +1,62 @@
+dojo.provide("dojox.geo.charting.widget.Legend");
+
+dojo.require("dijit._Widget");
+dojo.require("dijit._Templated");
+dojo.require("dojox.lang.functional.array");
+dojo.require("dojox.lang.functional.fold");
+
+dojo.declare("dojox.geo.charting.widget.Legend",[dijit._Widget, dijit._Templated], {
+	templateString: "<table dojoAttachPoint='legendNode' class='dojoxLegendNode'><tbody dojoAttachPoint='legendBody'></tbody></table>",
+	horizontal:true,
+	legendNode:null,
+	legendBody:null,
+	swatchSize:18,
+	postCreate: function(){
+		if(!this.map){return;}
+		this.series = this.map.series;
+		dojo.byId(this.map.container).appendChild(this.domNode);
+		this.refresh();
+	},
+	refresh:function(){
+		// cleanup
+		while(this.legendBody.lastChild){
+			dojo.destroy(this.legendBody.lastChild);
+		}
+		
+		if(this.horizontal){
+			dojo.addClass(this.legendNode,"dojoxLegendHorizontal");
+			this._tr = dojo.doc.createElement("tr");
+			this.legendBody.appendChild(this._tr);
+		}
+		
+		var s = this.series;
+		if(s.length == 0){return;}
+		
+		dojo.forEach(s,function(x){
+			this._addLabel(x.color, x.name);
+		},this);
+	},
+	_addLabel:function(color,label){
+		var icon = dojo.doc.createElement("td");
+		var text = dojo.doc.createElement("td");
+		var div = dojo.doc.createElement("div");
+		dojo.addClass(icon, "dojoxLegendIcon");
+		dojo.addClass(text, "dojoxLegendText");
+		div.style.width  = this.swatchSize + "px";
+		div.style.height = this.swatchSize + "px";
+		icon.appendChild(div);
+		
+		if(this.horizontal){
+			this._tr.appendChild(icon);
+			this._tr.appendChild(text);
+		}else{
+			var tr = dojo.doc.createElement("tr");
+			this.legendBody.appendChild(tr);
+			tr.appendChild(icon);
+			tr.appendChild(text);
+		}
+		
+		div.style.background = color;
+		text.innerHTML = String(label);
+	}
+});
diff --git a/dojox/gfx.js b/dojox/gfx.js
index 717f9eb..0b78ffb 100644
--- a/dojox/gfx.js
+++ b/dojox/gfx.js
@@ -1,16 +1,102 @@
-/*
-	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
-*/
+dojo.provide("dojox.gfx");
 
-/*
-	This is a compiled version of Dojo, built for deployment and not for
-	development. To get an editable version, please visit:
+dojo.require("dojox.gfx.matrix");
+dojo.require("dojox.gfx._base");
 
-		http://dojotoolkit.org
+dojo.loadInit(function(){
+	//Since loaderInit can be fired before any dojo.provide/require calls,
+	//make sure the dojox.gfx object exists and only run this logic if dojox.gfx.renderer
+	//has not been defined yet.
+	var gfx = dojo.getObject("dojox.gfx", true), sl, flag, match;
+	if(!gfx.renderer){
+		//Have a way to force a GFX renderer, if so desired.
+		//Useful for being able to serialize GFX data in a particular format.
+		if(dojo.config.forceGfxRenderer){
+			dojox.gfx.renderer = dojo.config.forceGfxRenderer;
+			return;
+		}
+		var renderers = (typeof dojo.config.gfxRenderer == "string" ?
+			dojo.config.gfxRenderer : "svg,vml,silverlight,canvas").split(",");
 
-	for documentation and information on getting the source.
-*/
+		// mobile platform detection
+		// TODO: move to the base?
 
-if(!dojo._hasResource["dojox.gfx.matrix"]){dojo._hasResource["dojox.gfx.matrix"]=true;dojo.provide("dojox.gfx.matrix");(function(){var m=dojox.gfx.matrix;var _1={};m._degToRad=function(_2){return _1[_2]||(_1[_2]=(Math.PI*_2/180));};m._radToDeg=function(_3){return _3/Math.PI*180;};m.Matrix2D=function(_4){if(_4){if(typeof _4=="number"){this.xx=this.yy=_4;}else{if(_4 instanceof Array){if(_4.length>0){var _5=m.normalize(_4[0]);for(var i=1;i<_4.length;++i){var l=_5,r=dojox.gfx.matrix.normaliz [...]
+		var ua = navigator.userAgent, iPhoneOsBuild = 0, androidVersion = 0;
+		if(dojo.isSafari >= 3){
+			// detect mobile version of WebKit starting with "version 3"
+
+			//	comprehensive iPhone test.  Have to figure out whether it's SVG or Canvas based on the build.
+			//	iPhone OS build numbers from en.wikipedia.org.
+			if(ua.indexOf("iPhone") >= 0 || ua.indexOf("iPod") >= 0){
+				//	grab the build out of this.  Expression is a little nasty because we want
+				//		to be sure we have the whole version string.
+				match = ua.match(/Version\/(\d(\.\d)?(\.\d)?)\sMobile\/([^\s]*)\s?/);
+				if(match){
+					//	grab the build out of the match.  Only use the first three because of specific builds.
+					iPhoneOsBuild = parseInt(match[4].substr(0,3), 16);
+				}
+			}
+		}
+		if(dojo.isWebKit){
+			// Android detection
+			if(!iPhoneOsBuild){
+				match = ua.match(/Android\s+(\d+\.\d+)/);
+				if(match){
+					androidVersion = parseFloat(match[1]);
+					// Android 1.0-1.1 doesn't support SVG but supports Canvas
+				}
+			}
+		}
+
+		for(var i = 0; i < renderers.length; ++i){
+			switch(renderers[i]){
+				case "svg":
+					//	iPhone OS builds greater than 5F1 should have SVG.
+					if(!dojo.isIE && (!iPhoneOsBuild || iPhoneOsBuild >= 0x5f1) && !androidVersion && !dojo.isAIR){
+						dojox.gfx.renderer = "svg";
+					}
+					break;
+				case "vml":
+					if(dojo.isIE){
+						dojox.gfx.renderer = "vml";
+					}
+					break;
+				case "silverlight":
+					try{
+						if(dojo.isIE){
+							sl = new ActiveXObject("AgControl.AgControl");
+							if(sl && sl.IsVersionSupported("1.0")){
+								flag = true;
+							}
+						}else{
+							if(navigator.plugins["Silverlight Plug-In"]){
+								flag = true;
+							}
+						}
+					}catch(e){
+						flag = false;
+					}finally{
+						sl = null;
+					}
+					if(flag){ dojox.gfx.renderer = "silverlight"; }
+					break;
+				case "canvas":
+					//TODO: need more comprehensive test for Canvas
+					if(!dojo.isIE){
+						dojox.gfx.renderer = "canvas";
+					}
+					break;
+			}
+			if(dojox.gfx.renderer){ break; }
+		}
+		if(dojo.config.isDebug){
+			console.log("gfx renderer = " + dojox.gfx.renderer);
+		}
+	}
+});
+
+// include a renderer conditionally
+dojo.requireIf(dojox.gfx.renderer == "svg", "dojox.gfx.svg");
+dojo.requireIf(dojox.gfx.renderer == "vml", "dojox.gfx.vml");
+dojo.requireIf(dojox.gfx.renderer == "silverlight", "dojox.gfx.silverlight");
+dojo.requireIf(dojox.gfx.renderer == "canvas", "dojox.gfx.canvas");
diff --git a/dojox/gfx.js.uncompressed.js b/dojox/gfx.js.uncompressed.js
deleted file mode 100644
index 0913a62..0000000
--- a/dojox/gfx.js.uncompressed.js
+++ /dev/null
@@ -1,945 +0,0 @@
-/*
-	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["dojox.gfx.matrix"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.gfx.matrix"] = true;
-dojo.provide("dojox.gfx.matrix");
-
-(function(){
-	var m = dojox.gfx.matrix;
-
-	// candidates for dojox.math:
-	var _degToRadCache = {};
-	m._degToRad = function(degree){
-		return _degToRadCache[degree] || (_degToRadCache[degree] = (Math.PI * degree / 180));
-	};
-	m._radToDeg = function(radian){ return radian / Math.PI * 180; };
-
-	m.Matrix2D = function(arg){
-		// summary: a 2D matrix object
-		// description: Normalizes a 2D matrix-like object. If arrays is passed,
-		//		all objects of the array are normalized and multiplied sequentially.
-		// arg: Object
-		//		a 2D matrix-like object, a number, or an array of such objects
-		if(arg){
-			if(typeof arg == "number"){
-				this.xx = this.yy = arg;
-			}else if(arg instanceof Array){
-				if(arg.length > 0){
-					var matrix = m.normalize(arg[0]);
-					// combine matrices
-					for(var i = 1; i < arg.length; ++i){
-						var l = matrix, r = dojox.gfx.matrix.normalize(arg[i]);
-						matrix = new m.Matrix2D();
-						matrix.xx = l.xx * r.xx + l.xy * r.yx;
-						matrix.xy = l.xx * r.xy + l.xy * r.yy;
-						matrix.yx = l.yx * r.xx + l.yy * r.yx;
-						matrix.yy = l.yx * r.xy + l.yy * r.yy;
-						matrix.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
-						matrix.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
-					}
-					dojo.mixin(this, matrix);
-				}
-			}else{
-				dojo.mixin(this, arg);
-			}
-		}
-	};
-
-	// the default (identity) matrix, which is used to fill in missing values
-	dojo.extend(m.Matrix2D, {xx: 1, xy: 0, yx: 0, yy: 1, dx: 0, dy: 0});
-
-	dojo.mixin(m, {
-		// summary: class constants, and methods of dojox.gfx.matrix
-
-		// matrix constants
-
-		// identity: dojox.gfx.matrix.Matrix2D
-		//		an identity matrix constant: identity * (x, y) == (x, y)
-		identity: new m.Matrix2D(),
-
-		// flipX: dojox.gfx.matrix.Matrix2D
-		//		a matrix, which reflects points at x = 0 line: flipX * (x, y) == (-x, y)
-		flipX:    new m.Matrix2D({xx: -1}),
-
-		// flipY: dojox.gfx.matrix.Matrix2D
-		//		a matrix, which reflects points at y = 0 line: flipY * (x, y) == (x, -y)
-		flipY:    new m.Matrix2D({yy: -1}),
-
-		// flipXY: dojox.gfx.matrix.Matrix2D
-		//		a matrix, which reflects points at the origin of coordinates: flipXY * (x, y) == (-x, -y)
-		flipXY:   new m.Matrix2D({xx: -1, yy: -1}),
-
-		// matrix creators
-
-		translate: function(a, b){
-			// summary: forms a translation matrix
-			// description: The resulting matrix is used to translate (move) points by specified offsets.
-			// a: Number: an x coordinate value
-			// b: Number: a y coordinate value
-			if(arguments.length > 1){
-				return new m.Matrix2D({dx: a, dy: b}); // dojox.gfx.matrix.Matrix2D
-			}
-			// branch
-			// a: dojox.gfx.Point: a point-like object, which specifies offsets for both dimensions
-			// b: null
-			return new m.Matrix2D({dx: a.x, dy: a.y}); // dojox.gfx.matrix.Matrix2D
-		},
-		scale: function(a, b){
-			// summary: forms a scaling matrix
-			// description: The resulting matrix is used to scale (magnify) points by specified offsets.
-			// a: Number: a scaling factor used for the x coordinate
-			// b: Number: a scaling factor used for the y coordinate
-			if(arguments.length > 1){
-				return new m.Matrix2D({xx: a, yy: b}); // dojox.gfx.matrix.Matrix2D
-			}
-			if(typeof a == "number"){
-				// branch
-				// a: Number: a uniform scaling factor used for the both coordinates
-				// b: null
-				return new m.Matrix2D({xx: a, yy: a}); // dojox.gfx.matrix.Matrix2D
-			}
-			// branch
-			// a: dojox.gfx.Point: a point-like object, which specifies scale factors for both dimensions
-			// b: null
-			return new m.Matrix2D({xx: a.x, yy: a.y}); // dojox.gfx.matrix.Matrix2D
-		},
-		rotate: function(angle){
-			// summary: forms a rotating matrix
-			// description: The resulting matrix is used to rotate points
-			//		around the origin of coordinates (0, 0) by specified angle.
-			// angle: Number: an angle of rotation in radians (>0 for CW)
-			var c = Math.cos(angle);
-			var s = Math.sin(angle);
-			return new m.Matrix2D({xx: c, xy: -s, yx: s, yy: c}); // dojox.gfx.matrix.Matrix2D
-		},
-		rotateg: function(degree){
-			// summary: forms a rotating matrix
-			// description: The resulting matrix is used to rotate points
-			//		around the origin of coordinates (0, 0) by specified degree.
-			//		See dojox.gfx.matrix.rotate() for comparison.
-			// degree: Number: an angle of rotation in degrees (>0 for CW)
-			return m.rotate(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
-		},
-		skewX: function(angle) {
-			// summary: forms an x skewing matrix
-			// description: The resulting matrix is used to skew points in the x dimension
-			//		around the origin of coordinates (0, 0) by specified angle.
-			// angle: Number: an skewing angle in radians
-			return new m.Matrix2D({xy: Math.tan(angle)}); // dojox.gfx.matrix.Matrix2D
-		},
-		skewXg: function(degree){
-			// summary: forms an x skewing matrix
-			// description: The resulting matrix is used to skew points in the x dimension
-			//		around the origin of coordinates (0, 0) by specified degree.
-			//		See dojox.gfx.matrix.skewX() for comparison.
-			// degree: Number: an skewing angle in degrees
-			return m.skewX(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
-		},
-		skewY: function(angle){
-			// summary: forms a y skewing matrix
-			// description: The resulting matrix is used to skew points in the y dimension
-			//		around the origin of coordinates (0, 0) by specified angle.
-			// angle: Number: an skewing angle in radians
-			return new m.Matrix2D({yx: Math.tan(angle)}); // dojox.gfx.matrix.Matrix2D
-		},
-		skewYg: function(degree){
-			// summary: forms a y skewing matrix
-			// description: The resulting matrix is used to skew points in the y dimension
-			//		around the origin of coordinates (0, 0) by specified degree.
-			//		See dojox.gfx.matrix.skewY() for comparison.
-			// degree: Number: an skewing angle in degrees
-			return m.skewY(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
-		},
-		reflect: function(a, b){
-			// summary: forms a reflection matrix
-			// description: The resulting matrix is used to reflect points around a vector,
-			//		which goes through the origin.
-			// a: dojox.gfx.Point: a point-like object, which specifies a vector of reflection
-			// b: null
-			if(arguments.length == 1){
-				b = a.y;
-				a = a.x;
-			}
-			// branch
-			// a: Number: an x coordinate value
-			// b: Number: a y coordinate value
-
-			// make a unit vector
-			var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = 2 * a * b / n2;
-			return new m.Matrix2D({xx: 2 * a2 / n2 - 1, xy: xy, yx: xy, yy: 2 * b2 / n2 - 1}); // dojox.gfx.matrix.Matrix2D
-		},
-		project: function(a, b){
-			// summary: forms an orthogonal projection matrix
-			// description: The resulting matrix is used to project points orthogonally on a vector,
-			//		which goes through the origin.
-			// a: dojox.gfx.Point: a point-like object, which specifies a vector of projection
-			// b: null
-			if(arguments.length == 1){
-				b = a.y;
-				a = a.x;
-			}
-			// branch
-			// a: Number: an x coordinate value
-			// b: Number: a y coordinate value
-
-			// make a unit vector
-			var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = a * b / n2;
-			return new m.Matrix2D({xx: a2 / n2, xy: xy, yx: xy, yy: b2 / n2}); // dojox.gfx.matrix.Matrix2D
-		},
-
-		// ensure matrix 2D conformance
-		normalize: function(matrix){
-			// summary: converts an object to a matrix, if necessary
-			// description: Converts any 2D matrix-like object or an array of
-			//		such objects to a valid dojox.gfx.matrix.Matrix2D object.
-			// matrix: Object: an object, which is converted to a matrix, if necessary
-			return (matrix instanceof m.Matrix2D) ? matrix : new m.Matrix2D(matrix); // dojox.gfx.matrix.Matrix2D
-		},
-
-		// common operations
-
-		clone: function(matrix){
-			// summary: creates a copy of a 2D matrix
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to be cloned
-			var obj = new m.Matrix2D();
-			for(var i in matrix){
-				if(typeof(matrix[i]) == "number" && typeof(obj[i]) == "number" && obj[i] != matrix[i]) obj[i] = matrix[i];
-			}
-			return obj; // dojox.gfx.matrix.Matrix2D
-		},
-		invert: function(matrix){
-			// summary: inverts a 2D matrix
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to be inverted
-			var M = m.normalize(matrix),
-				D = M.xx * M.yy - M.xy * M.yx,
-				M = new m.Matrix2D({
-					xx: M.yy/D, xy: -M.xy/D,
-					yx: -M.yx/D, yy: M.xx/D,
-					dx: (M.xy * M.dy - M.yy * M.dx) / D,
-					dy: (M.yx * M.dx - M.xx * M.dy) / D
-				});
-			return M; // dojox.gfx.matrix.Matrix2D
-		},
-		_multiplyPoint: function(matrix, x, y){
-			// summary: applies a matrix to a point
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
-			// x: Number: an x coordinate of a point
-			// y: Number: a y coordinate of a point
-			return {x: matrix.xx * x + matrix.xy * y + matrix.dx, y: matrix.yx * x + matrix.yy * y + matrix.dy}; // dojox.gfx.Point
-		},
-		multiplyPoint: function(matrix, /* Number||Point */ a, /* Number, optional */ b){
-			// summary: applies a matrix to a point
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
-			// a: Number: an x coordinate of a point
-			// b: Number: a y coordinate of a point
-			var M = m.normalize(matrix);
-			if(typeof a == "number" && typeof b == "number"){
-				return m._multiplyPoint(M, a, b); // dojox.gfx.Point
-			}
-			// branch
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
-			// a: dojox.gfx.Point: a point
-			// b: null
-			return m._multiplyPoint(M, a.x, a.y); // dojox.gfx.Point
-		},
-		multiply: function(matrix){
-			// summary: combines matrices by multiplying them sequentially in the given order
-			// matrix: dojox.gfx.matrix.Matrix2D...: a 2D matrix-like object,
-			//		all subsequent arguments are matrix-like objects too
-			var M = m.normalize(matrix);
-			// combine matrices
-			for(var i = 1; i < arguments.length; ++i){
-				var l = M, r = m.normalize(arguments[i]);
-				M = new m.Matrix2D();
-				M.xx = l.xx * r.xx + l.xy * r.yx;
-				M.xy = l.xx * r.xy + l.xy * r.yy;
-				M.yx = l.yx * r.xx + l.yy * r.yx;
-				M.yy = l.yx * r.xy + l.yy * r.yy;
-				M.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
-				M.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
-			}
-			return M; // dojox.gfx.matrix.Matrix2D
-		},
-
-		// high level operations
-
-		_sandwich: function(matrix, x, y){
-			// summary: applies a matrix at a centrtal point
-			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object, which is applied at a central point
-			// x: Number: an x component of the central point
-			// y: Number: a y component of the central point
-			return m.multiply(m.translate(x, y), matrix, m.translate(-x, -y)); // dojox.gfx.matrix.Matrix2D
-		},
-		scaleAt: function(a, b, c, d){
-			// summary: scales a picture using a specified point as a center of scaling
-			// description: Compare with dojox.gfx.matrix.scale().
-			// a: Number: a scaling factor used for the x coordinate
-			// b: Number: a scaling factor used for the y coordinate
-			// c: Number: an x component of a central point
-			// d: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) uniform scale factor, Point
-			//	2) uniform scale factor, x, y
-			//	3) x scale, y scale, Point
-			//	4) x scale, y scale, x, y
-
-			switch(arguments.length){
-				case 4:
-					// a and b are scale factor components, c and d are components of a point
-					return m._sandwich(m.scale(a, b), c, d); // dojox.gfx.matrix.Matrix2D
-				case 3:
-					if(typeof c == "number"){
-						// branch
-						// a: Number: a uniform scaling factor used for both coordinates
-						// b: Number: an x component of a central point
-						// c: Number: a y component of a central point
-						// d: null
-						return m._sandwich(m.scale(a), b, c); // dojox.gfx.matrix.Matrix2D
-					}
-					// branch
-					// a: Number: a scaling factor used for the x coordinate
-					// b: Number: a scaling factor used for the y coordinate
-					// c: dojox.gfx.Point: a central point
-					// d: null
-					return m._sandwich(m.scale(a, b), c.x, c.y); // dojox.gfx.matrix.Matrix2D
-			}
-			// branch
-			// a: Number: a uniform scaling factor used for both coordinates
-			// b: dojox.gfx.Point: a central point
-			// c: null
-			// d: null
-			return m._sandwich(m.scale(a), b.x, b.y); // dojox.gfx.matrix.Matrix2D
-		},
-		rotateAt: function(angle, a, b){
-			// summary: rotates a picture using a specified point as a center of rotation
-			// description: Compare with dojox.gfx.matrix.rotate().
-			// angle: Number: an angle of rotation in radians (>0 for CW)
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) rotation angle in radians, Point
-			//	2) rotation angle in radians, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.rotate(angle), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// angle: Number: an angle of rotation in radians (>0 for CCW)
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.rotate(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		},
-		rotategAt: function(degree, a, b){
-			// summary: rotates a picture using a specified point as a center of rotation
-			// description: Compare with dojox.gfx.matrix.rotateg().
-			// degree: Number: an angle of rotation in degrees (>0 for CW)
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) rotation angle in degrees, Point
-			//	2) rotation angle in degrees, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.rotateg(degree), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// degree: Number: an angle of rotation in degrees (>0 for CCW)
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.rotateg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		},
-		skewXAt: function(angle, a, b){
-			// summary: skews a picture along the x axis using a specified point as a center of skewing
-			// description: Compare with dojox.gfx.matrix.skewX().
-			// angle: Number: an skewing angle in radians
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) skew angle in radians, Point
-			//	2) skew angle in radians, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.skewX(angle), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// angle: Number: an skewing angle in radians
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.skewX(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		},
-		skewXgAt: function(degree, a, b){
-			// summary: skews a picture along the x axis using a specified point as a center of skewing
-			// description: Compare with dojox.gfx.matrix.skewXg().
-			// degree: Number: an skewing angle in degrees
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) skew angle in degrees, Point
-			//	2) skew angle in degrees, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.skewXg(degree), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// degree: Number: an skewing angle in degrees
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.skewXg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		},
-		skewYAt: function(angle, a, b){
-			// summary: skews a picture along the y axis using a specified point as a center of skewing
-			// description: Compare with dojox.gfx.matrix.skewY().
-			// angle: Number: an skewing angle in radians
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) skew angle in radians, Point
-			//	2) skew angle in radians, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.skewY(angle), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// angle: Number: an skewing angle in radians
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.skewY(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		},
-		skewYgAt: function(/* Number */ degree, /* Number||Point */ a, /* Number, optional */ b){
-			// summary: skews a picture along the y axis using a specified point as a center of skewing
-			// description: Compare with dojox.gfx.matrix.skewYg().
-			// degree: Number: an skewing angle in degrees
-			// a: Number: an x component of a central point
-			// b: Number: a y component of a central point
-
-			// accepts several signatures:
-			//	1) skew angle in degrees, Point
-			//	2) skew angle in degrees, x, y
-
-			if(arguments.length > 2){
-				return m._sandwich(m.skewYg(degree), a, b); // dojox.gfx.matrix.Matrix2D
-			}
-
-			// branch
-			// degree: Number: an skewing angle in degrees
-			// a: dojox.gfx.Point: a central point
-			// b: null
-			return m._sandwich(m.skewYg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
-		}
-
-		//TODO: rect-to-rect mapping, scale-to-fit (isotropic and anisotropic versions)
-
-	});
-})();
-
-// propagate Matrix2D up
-dojox.gfx.Matrix2D = dojox.gfx.matrix.Matrix2D;
-
-}
-
-if(!dojo._hasResource["dojox.gfx._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.gfx._base"] = true;
-dojo.provide("dojox.gfx._base");
-
-(function(){
-	var g = dojox.gfx, b = g._base;
-
-	// candidates for dojox.style (work on VML and SVG nodes)
-	g._hasClass = function(/*DomNode*/node, /*String*/classStr){
-		//	summary:
-		//		Returns whether or not the specified classes are a portion of the
-		//		class list currently applied to the node.
-		// return (new RegExp('(^|\\s+)'+classStr+'(\\s+|$)')).test(node.className)	// Boolean
-		var cls = node.getAttribute("className");
-		return cls && (" " + cls + " ").indexOf(" " + classStr + " ") >= 0;  // Boolean
-	}
-	g._addClass = function(/*DomNode*/node, /*String*/classStr){
-		//	summary:
-		//		Adds the specified classes to the end of the class list on the
-		//		passed node.
-		var cls = node.getAttribute("className") || "";
-		if(!cls || (" " + cls + " ").indexOf(" " + classStr + " ") < 0){
-			node.setAttribute("className", cls + (cls ? " " : "") + classStr);
-		}
-	}
-	g._removeClass = function(/*DomNode*/node, /*String*/classStr){
-		//	summary: Removes classes from node.
-		var cls = node.getAttribute("className");
-		if(cls){
-			node.setAttribute(
-				"className", 
-				cls.replace(new RegExp('(^|\\s+)' + classStr + '(\\s+|$)'), "$1$2")
-			);
-		}
-	}
-
-	// candidate for dojox.html.metrics (dynamic font resize handler is not implemented here)
-
-	//	derived from Morris John's emResized measurer
-	b._getFontMeasurements = function(){
-		//	summary:
-		//		Returns an object that has pixel equivilents of standard font
-		//		size values.
-		var heights = {
-			'1em': 0, '1ex': 0, '100%': 0, '12pt': 0, '16px': 0, 'xx-small': 0,
-			'x-small': 0, 'small': 0, 'medium': 0, 'large': 0, 'x-large': 0,
-			'xx-large': 0
-		};
-
-		if(dojo.isIE){
-			//	we do a font-size fix if and only if one isn't applied already.
-			//	NOTE: If someone set the fontSize on the HTML Element, this will kill it.
-			dojo.doc.documentElement.style.fontSize="100%";
-		}
-
-		//	set up the measuring node.
-		var div = dojo.doc.createElement("div");
-		var s = div.style;
-		s.position = "absolute";
-		s.left = "-100px";
-		s.top = "0px";
-		s.width = "30px";
-		s.height = "1000em";
-		s.border = "0px";
-		s.margin = "0px";
-		s.padding = "0px";
-		s.outline = "none";
-		s.lineHeight = "1";
-		s.overflow = "hidden";
-		dojo.body().appendChild(div);
-
-		//	do the measurements.
-		for(var p in heights){
-			div.style.fontSize = p;
-			heights[p] = Math.round(div.offsetHeight * 12/16) * 16/12 / 1000;
-		}
-
-		dojo.body().removeChild(div);
-		div = null;
-		return heights; 	//	object
-	};
-
-	var fontMeasurements = null;
-
-	b._getCachedFontMeasurements = function(recalculate){
-		if(recalculate || !fontMeasurements){
-			fontMeasurements = b._getFontMeasurements();
-		}
-		return fontMeasurements;
-	};
-
-	// candidate for dojox.html.metrics
-
-	var measuringNode = null, empty = {};
-	b._getTextBox = function(	/*String*/ text,
-								/*Object*/ style,
-								/*String?*/ className){
-		var m, s, al = arguments.length;
-		if(!measuringNode){
-			m = measuringNode = dojo.doc.createElement("div");
-			s = m.style;
-			s.position = "absolute";
-			s.left = "-10000px";
-			s.top = "0";
-			dojo.body().appendChild(m);
-		}else{
-			m = measuringNode;
-			s = m.style;
-		}
-		// reset styles
-		m.className = "";
-		s.border = "0";
-		s.margin = "0";
-		s.padding = "0";
-		s.outline = "0";
-		// set new style
-		if(al > 1 && style){
-			for(var i in style){
-				if(i in empty){ continue; }
-				s[i] = style[i];
-			}
-		}
-		// set classes
-		if(al > 2 && className){
-			m.className = className;
-		}
-		// take a measure
-		m.innerHTML = text;
-
-		if(m["getBoundingClientRect"]){
-			var bcr = m.getBoundingClientRect();
-			return {l: bcr.left, t: bcr.top, w: bcr.width || (bcr.right - bcr.left), h: bcr.height || (bcr.bottom - bcr.top)};
-		}else{
-			return dojo.marginBox(m);
-		}
-	};
-
-	// candidate for dojo.dom
-
-	var uniqueId = 0;
-	b._getUniqueId = function(){
-		// summary: returns a unique string for use with any DOM element
-		var id;
-		do{
-			id = dojo._scopeName + "Unique" + (++uniqueId);
-		}while(dojo.byId(id));
-		return id;
-	};
-})();
-
-dojo.mixin(dojox.gfx, {
-	//	summary:
-	// 		defines constants, prototypes, and utility functions
-
-	// default shapes, which are used to fill in missing parameters
-	defaultPath: {
-		type: "path", path: ""
-	},
-	defaultPolyline: {
-		type: "polyline", points: []
-	},
-	defaultRect: {
-		type: "rect", x: 0, y: 0, width: 100, height: 100, r: 0
-	},
-	defaultEllipse: {
-		type: "ellipse", cx: 0, cy: 0, rx: 200, ry: 100
-	},
-	defaultCircle: {
-		type: "circle", cx: 0, cy: 0, r: 100
-	},
-	defaultLine: {
-		type: "line", x1: 0, y1: 0, x2: 100, y2: 100
-	},
-	defaultImage: {
-		type: "image", x: 0, y: 0, width: 0, height: 0, src: ""
-	},
-	defaultText: {
-		type: "text", x: 0, y: 0, text: "", align: "start",
-		decoration: "none", rotated: false, kerning: true
-	},
-	defaultTextPath: {
-		type: "textpath", text: "", align: "start",
-		decoration: "none", rotated: false, kerning: true
-	},
-
-	// default geometric attributes
-	defaultStroke: {
-		type: "stroke", color: "black", style: "solid", width: 1, 
-		cap: "butt", join: 4
-	},
-	defaultLinearGradient: {
-		type: "linear", x1: 0, y1: 0, x2: 100, y2: 100,
-		colors: [
-			{ offset: 0, color: "black" }, { offset: 1, color: "white" }
-		]
-	},
-	defaultRadialGradient: {
-		type: "radial", cx: 0, cy: 0, r: 100,
-		colors: [
-			{ offset: 0, color: "black" }, { offset: 1, color: "white" }
-		]
-	},
-	defaultPattern: {
-		type: "pattern", x: 0, y: 0, width: 0, height: 0, src: ""
-	},
-	defaultFont: {
-		type: "font", style: "normal", variant: "normal", 
-		weight: "normal", size: "10pt", family: "serif"
-	},
-
-	getDefault: (function(){
-		var typeCtorCache = {};
-		// a memoized delegate()
-		return function(/*String*/ type){
-			var t = typeCtorCache[type];
-			if(t){
-				return new t();
-			}
-			t = typeCtorCache[type] = new Function;
-			t.prototype = dojox.gfx[ "default" + type ];
-			return new t();
-		}
-	})(),
-
-	normalizeColor: function(/*Color*/ color){
-		//	summary:
-		// 		converts any legal color representation to normalized
-		// 		dojo.Color object
-		return (color instanceof dojo.Color) ? color : new dojo.Color(color); // dojo.Color
-	},
-	normalizeParameters: function(existed, update){
-		//	summary:
-		// 		updates an existing object with properties from an "update"
-		// 		object
-		//	existed: Object
-		//		the "target" object to be updated
-		//	update:  Object
-		//		the "update" object, whose properties will be used to update
-		//		the existed object
-		if(update){
-			var empty = {};
-			for(var x in existed){
-				if(x in update && !(x in empty)){
-					existed[x] = update[x];
-				}
-			}
-		}
-		return existed;	// Object
-	},
-	makeParameters: function(defaults, update){
-		//	summary:
-		// 		copies the original object, and all copied properties from the
-		// 		"update" object
-		//	defaults: Object
-		//		the object to be cloned before updating
-		//	update:   Object
-		//		the object, which properties are to be cloned during updating
-		if(!update){
-			// return dojo.clone(defaults);
-			return dojo.delegate(defaults);
-		}
-		var result = {};
-		for(var i in defaults){
-			if(!(i in result)){
-				result[i] = dojo.clone((i in update) ? update[i] : defaults[i]);
-			}
-		}
-		return result; // Object
-	},
-	formatNumber: function(x, addSpace){
-		// summary: converts a number to a string using a fixed notation
-		// x:			Number:		number to be converted
-		// addSpace:	Boolean?:	if it is true, add a space before a positive number
-		var val = x.toString();
-		if(val.indexOf("e") >= 0){
-			val = x.toFixed(4);
-		}else{
-			var point = val.indexOf(".");
-			if(point >= 0 && val.length - point > 5){
-				val = x.toFixed(4);
-			}
-		}
-		if(x < 0){
-			return val; // String
-		}
-		return addSpace ? " " + val : val; // String
-	},
-	// font operations
-	makeFontString: function(font){
-		// summary: converts a font object to a CSS font string
-		// font:	Object:	font object (see dojox.gfx.defaultFont)
-		return font.style + " " + font.variant + " " + font.weight + " " + font.size + " " + font.family; // Object
-	},
-	splitFontString: function(str){
-		// summary:
-		//		converts a CSS font string to a font object
-		// description:
-		//		Converts a CSS font string to a gfx font object. The CSS font
-		//		string components should follow the W3C specified order
-		//		(see http://www.w3.org/TR/CSS2/fonts.html#font-shorthand):
-		//		style, variant, weight, size, optional line height (will be
-		//		ignored), and family.
-		// str: String
-		//		a CSS font string
-		var font = dojox.gfx.getDefault("Font");
-		var t = str.split(/\s+/);
-		do{
-			if(t.length < 5){ break; }
-			font.style   = t[0];
-			font.variant = t[1];
-			font.weight  = t[2];
-			var i = t[3].indexOf("/");
-			font.size = i < 0 ? t[3] : t[3].substring(0, i);
-			var j = 4;
-			if(i < 0){
-				if(t[4] == "/"){
-					j = 6;
-				}else if(t[4].charAt(0) == "/"){
-					j = 5;
-				}
-			}
-			if(j < t.length){
-				font.family = t.slice(j).join(" ");
-			}
-		}while(false);
-		return font;	// Object
-	},
-	// length operations
-	cm_in_pt: 72 / 2.54,	// Number: points per centimeter
-	mm_in_pt: 7.2 / 2.54,	// Number: points per millimeter
-	px_in_pt: function(){
-		// summary: returns a number of pixels per point
-		return dojox.gfx._base._getCachedFontMeasurements()["12pt"] / 12;	// Number
-	},
-	pt2px: function(len){
-		// summary: converts points to pixels
-		// len: Number: a value in points
-		return len * dojox.gfx.px_in_pt();	// Number
-	},
-	px2pt: function(len){
-		// summary: converts pixels to points
-		// len: Number: a value in pixels
-		return len / dojox.gfx.px_in_pt();	// Number
-	},
-	normalizedLength: function(len) {
-		// summary: converts any length value to pixels
-		// len: String: a length, e.g., "12pc"
-		if(len.length == 0) return 0;
-		if(len.length > 2){
-			var px_in_pt = dojox.gfx.px_in_pt();
-			var val = parseFloat(len);
-			switch(len.slice(-2)){
-				case "px": return val;
-				case "pt": return val * px_in_pt;
-				case "in": return val * 72 * px_in_pt;
-				case "pc": return val * 12 * px_in_pt;
-				case "mm": return val * dojox.gfx.mm_in_pt * px_in_pt;
-				case "cm": return val * dojox.gfx.cm_in_pt * px_in_pt;
-			}
-		}
-		return parseFloat(len);	// Number
-	},
-
-	// a constant used to split a SVG/VML path into primitive components
-	pathVmlRegExp: /([A-Za-z]+)|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,
-	pathSvgRegExp: /([A-Za-z])|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,
-
-	equalSources: function(a, b){
-		// summary: compares event sources, returns true if they are equal
-		return a && b && a == b;
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.gfx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.gfx"] = true;
-dojo.provide("dojox.gfx");
-
-
-
-
-dojo.loadInit(function(){
-	//Since loaderInit can be fired before any dojo.provide/require calls,
-	//make sure the dojox.gfx object exists and only run this logic if dojox.gfx.renderer
-	//has not been defined yet.
-	var gfx = dojo.getObject("dojox.gfx", true), sl, flag, match;
-	if(!gfx.renderer){
-		//Have a way to force a GFX renderer, if so desired.
-		//Useful for being able to serialize GFX data in a particular format.
-		if(dojo.config.forceGfxRenderer){
-			dojox.gfx.renderer = dojo.config.forceGfxRenderer;
-			return;
-		}
-		var renderers = (typeof dojo.config.gfxRenderer == "string" ?
-			dojo.config.gfxRenderer : "svg,vml,silverlight,canvas").split(",");
-
-		// mobile platform detection
-		// TODO: move to the base?
-
-		var ua = navigator.userAgent, iPhoneOsBuild = 0, androidVersion = 0;
-		if(dojo.isSafari >= 3){
-			// detect mobile version of WebKit starting with "version 3"
-
-			//	comprehensive iPhone test.  Have to figure out whether it's SVG or Canvas based on the build.
-			//	iPhone OS build numbers from en.wikipedia.org.
-			if(ua.indexOf("iPhone") >= 0 || ua.indexOf("iPod") >= 0){
-				//	grab the build out of this.  Expression is a little nasty because we want
-				//		to be sure we have the whole version string.
-				match = ua.match(/Version\/(\d(\.\d)?(\.\d)?)\sMobile\/([^\s]*)\s?/);
-				if(match){
-					//	grab the build out of the match.  Only use the first three because of specific builds.
-					iPhoneOsBuild = parseInt(match[4].substr(0,3), 16);
-				}
-			}
-		}
-		if(dojo.isWebKit){
-			// Android detection
-			if(!iPhoneOsBuild){
-				match = ua.match(/Android\s+(\d+\.\d+)/);
-				if(match){
-					androidVersion = parseFloat(match[1]);
-					// Android 1.0-1.1 doesn't support SVG but supports Canvas
-				}
-			}
-		}
-
-		for(var i = 0; i < renderers.length; ++i){
-			switch(renderers[i]){
-				case "svg":
-					//	iPhone OS builds greater than 5F1 should have SVG.
-					if(!dojo.isIE && (!iPhoneOsBuild || iPhoneOsBuild >= 0x5f1) && !androidVersion && !dojo.isAIR){
-						dojox.gfx.renderer = "svg";
-					}
-					break;
-				case "vml":
-					if(dojo.isIE){
-						dojox.gfx.renderer = "vml";
-					}
-					break;
-				case "silverlight":
-					try{
-						if(dojo.isIE){
-							sl = new ActiveXObject("AgControl.AgControl");
-							if(sl && sl.IsVersionSupported("1.0")){
-								flag = true;
-							}
-						}else{
-							if(navigator.plugins["Silverlight Plug-In"]){
-								flag = true;
-							}
-						}
-					}catch(e){
-						flag = false;
-					}finally{
-						sl = null;
-					}
-					if(flag){ dojox.gfx.renderer = "silverlight"; }
-					break;
-				case "canvas":
-					//TODO: need more comprehensive test for Canvas
-					if(!dojo.isIE){
-						dojox.gfx.renderer = "canvas";
-					}
-					break;
-			}
-			if(dojox.gfx.renderer){ break; }
-		}
-		if(dojo.config.isDebug){
-			console.log("gfx renderer = " + dojox.gfx.renderer);
-		}
-	}
-});
-
-// include a renderer conditionally
-dojo.requireIf(dojox.gfx.renderer == "svg", "dojox.gfx.svg");
-dojo.requireIf(dojox.gfx.renderer == "vml", "dojox.gfx.vml");
-dojo.requireIf(dojox.gfx.renderer == "silverlight", "dojox.gfx.silverlight");
-dojo.requireIf(dojox.gfx.renderer == "canvas", "dojox.gfx.canvas");
-
-}
-
diff --git a/dojox/gfx/Moveable.js b/dojox/gfx/Moveable.js
index 9459d04..5a0796b 100644
--- a/dojox/gfx/Moveable.js
+++ b/dojox/gfx/Moveable.js
@@ -1,53 +1,97 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.Moveable"]){
-dojo._hasResource["dojox.gfx.Moveable"]=true;
 dojo.provide("dojox.gfx.Moveable");
+
 dojo.require("dojox.gfx.Mover");
-dojo.declare("dojox.gfx.Moveable",null,{constructor:function(_1,_2){
-this.shape=_1;
-this.delay=(_2&&_2.delay>0)?_2.delay:0;
-this.mover=(_2&&_2.mover)?_2.mover:dojox.gfx.Mover;
-this.events=[this.shape.connect("onmousedown",this,"onMouseDown")];
-},destroy:function(){
-dojo.forEach(this.events,this.shape.disconnect,this.shape);
-this.events=this.shape=null;
-},onMouseDown:function(e){
-if(this.delay){
-this.events.push(this.shape.connect("onmousemove",this,"onMouseMove"));
-this.events.push(this.shape.connect("onmouseup",this,"onMouseUp"));
-this._lastX=e.clientX;
-this._lastY=e.clientY;
-}else{
-new this.mover(this.shape,e,this);
-}
-dojo.stopEvent(e);
-},onMouseMove:function(e){
-if(Math.abs(e.clientX-this._lastX)>this.delay||Math.abs(e.clientY-this._lastY)>this.delay){
-this.onMouseUp(e);
-new this.mover(this.shape,e,this);
-}
-dojo.stopEvent(e);
-},onMouseUp:function(e){
-this.shape.disconnect(this.events.pop());
-this.shape.disconnect(this.events.pop());
-},onMoveStart:function(_3){
-dojo.publish("/gfx/move/start",[_3]);
-dojo.addClass(dojo.body(),"dojoMove");
-},onMoveStop:function(_4){
-dojo.publish("/gfx/move/stop",[_4]);
-dojo.removeClass(dojo.body(),"dojoMove");
-},onFirstMove:function(_5){
-},onMove:function(_6,_7){
-this.onMoving(_6,_7);
-this.shape.applyLeftTransform(_7);
-this.onMoved(_6,_7);
-},onMoving:function(_8,_9){
-},onMoved:function(_a,_b){
-}});
-}
+
+dojo.declare("dojox.gfx.Moveable", null, {
+	constructor: function(shape, params){
+		// summary: an object, which makes a shape moveable
+		// shape: dojox.gfx.Shape: a shape object to be moved
+		// params: Object: an optional object with additional parameters;
+		//	following parameters are recognized:
+		//		delay: Number: delay move by this number of pixels
+		//		mover: Object: a constructor of custom Mover
+		this.shape = shape;
+		this.delay = (params && params.delay > 0) ? params.delay : 0;
+		this.mover = (params && params.mover) ? params.mover : dojox.gfx.Mover;
+		this.events = [
+			this.shape.connect("onmousedown", this, "onMouseDown")
+			// cancel text selection and text dragging
+			//, dojo.connect(this.handle, "ondragstart",   dojo, "stopEvent")
+			//, dojo.connect(this.handle, "onselectstart", dojo, "stopEvent")
+		];
+	},
+
+	// methods
+	destroy: function(){
+		// summary: stops watching for possible move, deletes all references, so the object can be garbage-collected
+		dojo.forEach(this.events, this.shape.disconnect, this.shape);
+		this.events = this.shape = null;
+	},
+
+	// mouse event processors
+	onMouseDown: function(e){
+		// summary: event processor for onmousedown, creates a Mover for the shape
+		// e: Event: mouse event
+		if(this.delay){
+			this.events.push(this.shape.connect("onmousemove", this, "onMouseMove"));
+			this.events.push(this.shape.connect("onmouseup", this, "onMouseUp"));
+			this._lastX = e.clientX;
+			this._lastY = e.clientY;
+		}else{
+			new this.mover(this.shape, e, this);
+		}
+		dojo.stopEvent(e);
+	},
+	onMouseMove: function(e){
+		// summary: event processor for onmousemove, used only for delayed drags
+		// e: Event: mouse event
+		if(Math.abs(e.clientX - this._lastX) > this.delay || Math.abs(e.clientY - this._lastY) > this.delay){
+			this.onMouseUp(e);
+			new this.mover(this.shape, e, this);
+		}
+		dojo.stopEvent(e);
+	},
+	onMouseUp: function(e){
+		// summary: event processor for onmouseup, used only for delayed delayed drags
+		// e: Event: mouse event
+		this.shape.disconnect(this.events.pop());
+		this.shape.disconnect(this.events.pop());
+	},
+
+	// local events
+	onMoveStart: function(/* dojox.gfx.Mover */ mover){
+		// summary: called before every move operation
+		dojo.publish("/gfx/move/start", [mover]);
+		dojo.addClass(dojo.body(), "dojoMove");
+	},
+	onMoveStop: function(/* dojox.gfx.Mover */ mover){
+		// summary: called after every move operation
+		dojo.publish("/gfx/move/stop", [mover]);
+		dojo.removeClass(dojo.body(), "dojoMove");
+	},
+	onFirstMove: function(/* dojox.gfx.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(/* dojox.gfx.Mover */ mover, /* Object */ shift){
+		// summary: called during every move notification,
+		//	should actually move the node, can be overwritten.
+		this.onMoving(mover, shift);
+		this.shape.applyLeftTransform(shift);
+		this.onMoved(mover, shift);
+	},
+	onMoving: function(/* dojox.gfx.Mover */ mover, /* Object */ shift){
+		// summary: called before every incremental move,
+		//	can be overwritten.
+
+		// default implementation does nothing
+	},
+	onMoved: function(/* dojox.gfx.Mover */ mover, /* Object */ shift){
+		// summary: called after every incremental move,
+		//	can be overwritten.
+
+		// default implementation does nothing
+	}
+});
diff --git a/dojox/gfx/Mover.js b/dojox/gfx/Mover.js
index dcc0765..5134582 100644
--- a/dojox/gfx/Mover.js
+++ b/dojox/gfx/Mover.js
@@ -1,38 +1,58 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.Mover"]){
-dojo._hasResource["dojox.gfx.Mover"]=true;
 dojo.provide("dojox.gfx.Mover");
-dojo.declare("dojox.gfx.Mover",null,{constructor:function(_1,e,_2){
-this.shape=_1;
-this.lastX=e.clientX;
-this.lastY=e.clientY;
-var h=this.host=_2,d=document,_3=dojo.connect(d,"onmousemove",this,"onFirstMove");
-this.events=[dojo.connect(d,"onmousemove",this,"onMouseMove"),dojo.connect(d,"onmouseup",this,"destroy"),dojo.connect(d,"ondragstart",dojo,"stopEvent"),dojo.connect(d,"onselectstart",dojo,"stopEvent"),_3];
-if(h&&h.onMoveStart){
-h.onMoveStart(this);
-}
-},onMouseMove:function(e){
-var x=e.clientX;
-var y=e.clientY;
-this.host.onMove(this,{dx:x-this.lastX,dy:y-this.lastY});
-this.lastX=x;
-this.lastY=y;
-dojo.stopEvent(e);
-},onFirstMove:function(){
-this.host.onFirstMove(this);
-dojo.disconnect(this.events.pop());
-},destroy:function(){
-dojo.forEach(this.events,dojo.disconnect);
-var h=this.host;
-if(h&&h.onMoveStop){
-h.onMoveStop(this);
-}
-this.events=this.shape=null;
-}});
-}
+
+dojo.declare("dojox.gfx.Mover", null, {
+	constructor: function(shape, e, host){
+		// summary: an object, which makes a shape follow the mouse,
+		//	used as a default mover, and as a base class for custom movers
+		// shape: dojox.gfx.Shape: a shape object to be moved
+		// e: Event: a mouse event, which started the move;
+		//	only clientX and clientY properties are used
+		// host: Object?: object which implements the functionality of the move,
+		//	 and defines proper events (onMoveStart and onMoveStop)
+		this.shape = shape;
+		this.lastX = e.clientX
+		this.lastY = e.clientY;
+		var h = this.host = host, d = document,
+			firstEvent = dojo.connect(d, "onmousemove", this, "onFirstMove");
+		this.events = [
+			dojo.connect(d, "onmousemove", this, "onMouseMove"),
+			dojo.connect(d, "onmouseup",   this, "destroy"),
+			// cancel text selection and text dragging
+			dojo.connect(d, "ondragstart",   dojo, "stopEvent"),
+			dojo.connect(d, "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
+		var x = e.clientX;
+		var y = e.clientY;
+		this.host.onMove(this, {dx: x - this.lastX, dy: y - this.lastY});
+		this.lastX = x;
+		this.lastY = y;
+		dojo.stopEvent(e);
+	},
+	// utilities
+	onFirstMove: function(){
+		// summary: it is meant to be called only once
+		this.host.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.shape = null;
+	}
+});
diff --git a/dojox/gfx/README b/dojox/gfx/README
index 808ba6b..485f628 100644
--- a/dojox/gfx/README
+++ b/dojox/gfx/README
@@ -5,13 +5,17 @@ Version 1.100
 Release date: 08/01/2006
 -------------------------------------------------------------------------------
 Project state:
-beta
-HTMLCanvas renderer: experimental
+SVG renderer: production
+VML renderer: production
+Silverlight renderer: beta
+HTMLCanvas renderer: beta
+SVGWeb integration: experimental
 -------------------------------------------------------------------------------
 Credits
 	Eugene Lazutkin (eugene.lazutkin at gmail.com)
 	Kun Xi (bookstack at gmail.com)
 	Chris Mitchell (ccmitchellusa at gmail.com) HTML Canvas
+	Yang Li () SVGWeb integration
 -------------------------------------------------------------------------------
 Project description
 
@@ -87,6 +91,9 @@ Known Bugs:
    track skew matrix with Shape, and perform other trans/rot/scale transformations without
    using canvas transform functions.
 
+SVGWeb Integration Status
+
+See README-svgweb.
 
 -------------------------------------------------------------------------------
 Installation instructions
diff --git a/dojox/gfx/README-svgweb b/dojox/gfx/README-svgweb
new file mode 100644
index 0000000..f701bb3
--- /dev/null
+++ b/dojox/gfx/README-svgweb
@@ -0,0 +1,98 @@
+NOTICE of 3rd party code included
+=================================
+For ease of testing, latest SVGWeb release is included, see
+dojox/gfx/tests/svgweb/README for details.
+
+
+============================================================
+Enable or disable the SVGWeb with dojo gfx
+------------------------------------------------------------
+
+The function is only enabled when SVGWeb JS is included and the gfx renderer is
+'svg'. If either SVGWeb is not available or the renderer is not 'svg', dojox.gfx
+works as usual.
+
+To enable SVGWeb with dojo gfx:
+
+1. Include SVGWeb JS at the FIRST of all your javascripts
+
+	<meta name="svg.render.forceflash" content="true"/>
+	<script src="<path>/svgweb/src/svg.js" data-path="<path>/svgweb/src"></script>
+
+2. Force 'svg' renderer with the 'forceGfxRenderer' config
+
+	<script src="<path>/dojo/dojo.js" djConfig="forceGfxRenderer:'svg'"></script>
+
+
+============================================================
+Test dojo gfx + SVGWeb
+------------------------------------------------------------
+
+All SVGWeb-specific tests are in dojox/gfx/tests/svgweb.
+
+============================================================
+GFX Performance Test Status
+------------------------------------------------------------
+
+Runs dojo gfx performance tests on IE7 with different renderers, compare their
+performance. The result so far is
+
+    * Silverlight is the fastest: 27,546 ms;
+    * Tuned SVGWeb is the 2nd place: 38,690 ms, almost 3 times faster than
+	  before
+    * VML is the slowest: 50,250 ms
+
+
+============================================================
+GFX Functional Test Status
+------------------------------------------------------------
+
+Summary / General findings
+
+    * Pass rate 83%, 25 out of 30 pass
+    * The behavior is very consistent on IE & FF
+    * Transformation of Text is not working
+    * Line style is not working
+    * getTextWidth() does not work, see svgweb bug 417
+    * IE7 has memory issue, see svgweb bug 418 (IE8 seems fine)
+
+PASS test.roundrect.html
+PASS test_arc.html
+PASS test_bezier.html
+PASS test_decompose.html
+PASS test_destroy.html
+PASS test_fill.html
+
+FAIL test_fx.html: mostly works, except for the transformation of text (svgweb bug 158)
+
+PASS test_fx_shapes.html
+PASS test_gfx.html
+PASS test_gradient.html: works, but performance is slow due to the creation of a lot of shapes; using suspendRedraw() helps, but not much; current time is 8.5 seconds on IE7, 3 seconds on FF 3.5
+PASS test_group1.html: partly works, but rect highlight change has problem (svgweb bug 296)
+PASS test_group2.html: works, with source changed from 'dijit.byId()' to 'dojo.byId()'
+PASS test_image1.html
+PASS test_image2.html: picture shows, but move and transform has serious problem (svgweb bug 296)
+
+FAIL test_image3.html: picture shows, but move and transform has serious problem (svgweb bug 427, 436)
+
+PASS test_image4.html
+PASS test_image5.html: still image gets cropped after dragging, but mostly it's working (svgweb bug 244)
+PASS test_linearGradient.html
+
+FAIL test_linestyle.html: not work (svgweb bug 65)
+
+PASS test_pattern.html
+PASS test_poly.html
+PASS test_resize.html
+PASS test_setPath.html
+PASS test_tbbox.html: output drawing is incorrect (svgweb bug 296)
+
+FAIL test_text.html: text shows, but the rotation still fails (svgweb bug 158)
+
+FAIL test_textpath.html: not work (svgweb bug 169)
+
+PASS test_transform.html: output drawing is incorrect (svgweb bug 296)
+PASS test_utils.html
+PASS test_vectortext_draw.html
+PASS test_vectortext_load.html: functionally, this works, but very very slow; Reduced the test case to print just 26 chars, in FF it takes 30+ seconds, in IE7 it's more than a minute...
+
diff --git a/dojox/gfx/VectorText.js b/dojox/gfx/VectorText.js
index cf4e459..83b9dd5 100644
--- a/dojox/gfx/VectorText.js
+++ b/dojox/gfx/VectorText.js
@@ -1,366 +1,777 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.VectorText"]){
-dojo._hasResource["dojox.gfx.VectorText"]=true;
 dojo.provide("dojox.gfx.VectorText");
 dojo.require("dojox.gfx");
 dojo.require("dojox.xml.DomParser");
 dojo.require("dojox.html.metrics");
+
 (function(){
-dojo.mixin(dojox.gfx,{vectorFontFitting:{NONE:0,FLOW:1,FIT:2},defaultVectorText:{type:"vectortext",x:0,y:0,width:null,height:null,text:"",align:"start",decoration:"none",fitting:0,leading:1.5},defaultVectorFont:{type:"vectorfont",size:"10pt",family:null},_vectorFontCache:{},_svgFontCache:{},getVectorFont:function(_1){
-if(dojox.gfx._vectorFontCache[_1]){
-return dojox.gfx._vectorFontCache[_1];
-}
-return new dojox.gfx.VectorFont(_1);
-}});
-dojo.declare("dojox.gfx.VectorFont",null,{_entityRe:/&(quot|apos|lt|gt|amp|#x[^;]+|#\d+);/g,_decodeEntitySequence:function(_2){
-if(!_2.match(this._entityRe)){
-return;
-}
-var _3={amp:"&",apos:"'",quot:"\"",lt:"<",gt:">"};
-var r,_4="";
-while((r=this._entityRe.exec(_2))!==null){
-if(r[1].charAt(1)=="x"){
-_4+=String.fromCharCode(r[1].slice(2),16);
-}else{
-if(!isNaN(parseInt(r[1].slice(1),10))){
-_4+=String.fromCharCode(r[1].slice(1));
-}else{
-_4+=_3(r[1]);
-}
-}
-}
-return _4;
-},_parse:function(_5,_6){
-var _7=dojox.gfx._svgFontCache[_6]||dojox.xml.DomParser.parse(_5);
-var f=_7.documentElement.byName("font")[0],_8=_7.documentElement.byName("font-face")[0];
-var _9=parseFloat(_8.getAttribute("units-per-em")||1000,10);
-var _a={x:parseFloat(f.getAttribute("horiz-adv-x"),10),y:parseFloat(f.getAttribute("vert-adv-y")||0,10)};
-if(!_a.y){
-_a.y=_9;
-}
-var _b={horiz:{x:parseFloat(f.getAttribute("horiz-origin-x")||0,10),y:parseFloat(f.getAttribute("horiz-origin-y")||0,10)},vert:{x:parseFloat(f.getAttribute("vert-origin-x")||0,10),y:parseFloat(f.getAttribute("vert-origin-y")||0,10)}};
-var _c=_8.getAttribute("font-family"),_d=_8.getAttribute("font-style")||"all",_e=_8.getAttribute("font-variant")||"normal",_f=_8.getAttribute("font-weight")||"all",_10=_8.getAttribute("font-stretch")||"normal",_11=_8.getAttribute("unicode-range")||"U+0-10FFFF",_12=_8.getAttribute("panose-1")||"0 0 0 0 0 0 0 0 0 0",_13=_8.getAttribute("cap-height"),_14=parseFloat(_8.getAttribute("ascent")||(_9-_b.vert.y),10),_15=parseFloat(_8.getAttribute("descent")||_b.vert.y,10),_16={};
-var _17=_c;
-if(_8.byName("font-face-name")[0]){
-_17=_8.byName("font-face-name")[0].getAttribute("name");
-}
-if(dojox.gfx._vectorFontCache[_17]){
-return;
-}
-dojo.forEach(["alphabetic","ideographic","mathematical","hanging"],function(_18){
-var a=_8.getAttribute(_18);
-if(a!==null){
-_16[_18]=parseFloat(a,10);
-}
-});
-var _19=parseFloat(_7.documentElement.byName("missing-glyph")[0].getAttribute("horiz-adv-x")||_a.x,10);
-var _1a={},_1b={},g=_7.documentElement.byName("glyph");
-dojo.forEach(g,function(_1c){
-var _1d=_1c.getAttribute("unicode"),_17=_1c.getAttribute("glyph-name"),_1e=parseFloat(_1c.getAttribute("horiz-adv-x")||_a.x,10),_1f=_1c.getAttribute("d");
-if(_1d.match(this._entityRe)){
-_1d=this._decodeEntitySequence(_1d);
-}
-var o={code:_1d,name:_17,xAdvance:_1e,path:_1f};
-_1a[_1d]=o;
-_1b[_17]=o;
-},this);
-var _20=_7.documentElement.byName("hkern");
-dojo.forEach(_20,function(_21,i){
-var k=-parseInt(_21.getAttribute("k"),10);
-var u1=_21.getAttribute("u1"),g1=_21.getAttribute("g1"),u2=_21.getAttribute("u2"),g2=_21.getAttribute("g2"),gl;
-if(u1){
-u1=this._decodeEntitySequence(u1);
-if(_1a[u1]){
-gl=_1a[u1];
-}
-}else{
-if(_1b[g1]){
-gl=_1b[g1];
-}
-}
-if(gl){
-if(!gl.kern){
-gl.kern={};
-}
-if(u2){
-u2=this._decodeEntitySequence(u2);
-gl.kern[u2]={x:k};
-}else{
-if(_1b[g2]){
-gl.kern[_1b[g2].code]={x:k};
-}
-}
-}
-},this);
-dojo.mixin(this,{family:_c,name:_17,style:_d,variant:_e,weight:_f,stretch:_10,range:_11,viewbox:{width:_9,height:_9},origin:_b,advance:dojo.mixin(_a,{missing:{x:_19,y:_19}}),ascent:_14,descent:_15,baseline:_16,glyphs:_1a});
-dojox.gfx._vectorFontCache[_17]=this;
-dojox.gfx._vectorFontCache[_6]=this;
-if(_17!=_c&&!dojox.gfx._vectorFontCache[_c]){
-dojox.gfx._vectorFontCache[_c]=this;
-}
-if(!dojox.gfx._svgFontCache[_6]){
-dojox.gfx._svgFontCache[_6]=_7;
-}
-},_clean:function(){
-var _22=this.name,_23=this.family;
-dojo.forEach(["family","name","style","variant","weight","stretch","range","viewbox","origin","advance","ascent","descent","baseline","glyphs"],function(_24){
-try{
-delete this[_24];
-}
-catch(e){
-}
-},this);
-if(dojox.gfx._vectorFontCache[_22]){
-delete dojox.gfx._vectorFontCache[_22];
-}
-if(dojox.gfx._vectorFontCache[_23]){
-delete dojox.gfx._vectorFontCache[_23];
-}
-return this;
-},constructor:function(url){
-this._defaultLeading=1.5;
-if(url!==undefined){
-this.load(url);
-}
-},load:function(url){
-this.onLoadBegin(url.toString());
-this._parse(dojox.gfx._svgFontCache[url.toString()]||dojo._getText(url.toString()),url.toString());
-this.onLoad(this);
-return this;
-},initialized:function(){
-return (this.glyphs!==null);
-},_round:function(n){
-return Math.round(1000*n)/1000;
-},_leading:function(_25){
-return this.viewbox.height*(_25||this._defaultLeading);
-},_normalize:function(str){
-return str.replace(/\s+/g,String.fromCharCode(32));
-},_getWidth:function(_26){
-var w=0,_27=0,_28=null;
-dojo.forEach(_26,function(_29,i){
-_27=_29.xAdvance;
-if(_26[i]&&_29.kern&&_29.kern[_26[i].code]){
-_27+=_29.kern[_26[i].code].x;
-}
-w+=_27;
-_28=_29;
-});
-if(_28&&_28.code==" "){
-w-=_28.xAdvance;
-}
-return this._round(w);
-},_getLongestLine:function(_2a){
-var _2b=0,idx=0;
-dojo.forEach(_2a,function(_2c,i){
-var max=Math.max(_2b,this._getWidth(_2c));
-if(max>_2b){
-_2b=max;
-idx=i;
-}
-},this);
-return {width:_2b,index:idx,line:_2a[idx]};
-},_trim:function(_2d){
-var fn=function(arr){
-if(!arr.length){
-return;
-}
-if(arr[arr.length-1].code==" "){
-arr.splice(arr.length-1,1);
-}
-if(!arr.length){
-return;
-}
-if(arr[0].code==" "){
-arr.splice(0,1);
-}
-};
-if(dojo.isArray(_2d[0])){
-dojo.forEach(_2d,fn);
-}else{
-fn(_2d);
-}
-return _2d;
-},_split:function(_2e,_2f){
-var w=this._getWidth(_2e),_30=Math.floor(w/_2f),_31=[],cw=0,c=[],_32=false;
-for(var i=0,l=_2e.length;i<l;i++){
-if(_2e[i].code==" "){
-_32=true;
-}
-cw+=_2e[i].xAdvance;
-if(i+1<l&&_2e[i].kern&&_2e[i].kern[_2e[i+1].code]){
-cw+=_2e[i].kern[_2e[i+1].code].x;
-}
-if(cw>=_30){
-var chr=_2e[i];
-while(_32&&chr.code!=" "&&i>=0){
-chr=c.pop();
-i--;
-}
-_31.push(c);
-c=[];
-cw=0;
-_32=false;
-}
-c.push(_2e[i]);
-}
-if(c.length){
-_31.push(c);
-}
-return this._trim(_31);
-},_getSizeFactor:function(_33){
-_33+="";
-var _34=dojox.html.metrics.getCachedFontMeasurements(),_35=this.viewbox.height,f=_34["1em"],_36=parseFloat(_33,10);
-if(_33.indexOf("em")>-1){
-return this._round((_34["1em"]*_36)/_35);
-}else{
-if(_33.indexOf("ex")>-1){
-return this._round((_34["1ex"]*_36)/_35);
-}else{
-if(_33.indexOf("pt")>-1){
-return this._round(((_34["12pt"]/12)*_36)/_35);
-}else{
-if(_33.indexOf("px")>-1){
-return this._round(((_34["16px"]/16)*_36)/_35);
-}else{
-if(_33.indexOf("%")>-1){
-return this._round((_34["1em"]*(_36/100))/_35);
-}else{
-f=_34[_33]||_34.medium;
-return this._round(f/_35);
-}
-}
-}
-}
-}
-},_getFitFactor:function(_37,w,h,l){
-if(!h){
-return this._round(w/this._getWidth(_37));
-}else{
-var _38=this._getLongestLine(_37).width,_39=(_37.length*(this.viewbox.height*l))-((this.viewbox.height*l)-this.viewbox.height);
-return this._round(Math.min(w/_38,h/_39));
-}
-},_getBestFit:function(_3a,w,h,_3b){
-var _3c=32,_3d=0,_3e=_3c;
-while(_3c>0){
-var f=this._getFitFactor(this._split(_3a,_3c),w,h,_3b);
-if(f>_3d){
-_3d=f;
-_3e=_3c;
-}
-_3c--;
-}
-return {scale:_3d,lines:this._split(_3a,_3e)};
-},_getBestFlow:function(_3f,w,_40){
-var _41=[],cw=0,c=[],_42=false;
-for(var i=0,l=_3f.length;i<l;i++){
-if(_3f[i].code==" "){
-_42=true;
-}
-var tw=_3f[i].xAdvance;
-if(i+1<l&&_3f[i].kern&&_3f[i].kern[_3f[i+1].code]){
-tw+=_3f[i].kern[_3f[i+1].code].x;
-}
-cw+=_40*tw;
-if(cw>=w){
-var chr=_3f[i];
-while(_42&&chr.code!=" "&&i>=0){
-chr=c.pop();
-i--;
-}
-_41.push(c);
-c=[];
-cw=0;
-_42=false;
-}
-c.push(_3f[i]);
-}
-if(c.length){
-_41.push(c);
-}
-return this._trim(_41);
-},getWidth:function(_43,_44){
-return this._getWidth(dojo.map(this._normalize(_43).split(""),function(chr){
-return this.glyphs[chr]||{xAdvance:this.advance.missing.x};
-},this))*(_44||1);
-},getLineHeight:function(_45){
-return this.viewbox.height*(_45||1);
-},getCenterline:function(_46){
-return (_46||1)*(this.viewbox.height/2);
-},getBaseline:function(_47){
-return (_47||1)*(this.viewbox.height+this.descent);
-},draw:function(_48,_49,_4a,_4b,_4c){
-if(!this.initialized()){
-throw new Error("dojox.gfx.VectorFont.draw(): we have not been initialized yet.");
-}
-var g=_48.createGroup();
-if(_49.x||_49.y){
-_48.applyTransform({dx:_49.x||0,dy:_49.y||0});
-}
-var _4d=dojo.map(this._normalize(_49.text).split(""),function(chr){
-return this.glyphs[chr]||{path:null,xAdvance:this.advance.missing.x};
-},this);
-var _4e=_4a.size,_4f=_49.fitting,_50=_49.width,_51=_49.height,_52=_49.align,_53=_49.leading||this._defaultLeading;
-if(_4f){
-if((_4f==dojox.gfx.vectorFontFitting.FLOW&&!_50)||(_4f==dojox.gfx.vectorFontFitting.FIT&&(!_50||!_51))){
-_4f=dojox.gfx.vectorFontFitting.NONE;
-}
-}
-var _54,_55;
-switch(_4f){
-case dojox.gfx.vectorFontFitting.FIT:
-var o=this._getBestFit(_4d,_50,_51,_53);
-_55=o.scale;
-_54=o.lines;
-break;
-case dojox.gfx.vectorFontFitting.FLOW:
-_55=this._getSizeFactor(_4e);
-_54=this._getBestFlow(_4d,_50,_55);
-break;
-default:
-_55=this._getSizeFactor(_4e);
-_54=[_4d];
-}
-_54=dojo.filter(_54,function(_56){
-return _56.length>0;
-});
-var cy=0,_57=this._getLongestLine(_54).width;
-for(var i=0,l=_54.length;i<l;i++){
-var cx=0,_58=_54[i],_59=this._getWidth(_58),lg=g.createGroup();
-for(var j=0;j<_58.length;j++){
-var _5a=_58[j];
-if(_5a.path!==null){
-var p=lg.createPath(_5a.path).setFill(_4b);
-if(_4c){
-p.setStroke(_4c);
-}
-p.setTransform([dojox.gfx.matrix.flipY,dojox.gfx.matrix.translate(cx,-this.viewbox.height-this.descent)]);
-}
-cx+=_5a.xAdvance;
-if(j+1<_58.length&&_5a.kern&&_5a.kern[_58[j+1].code]){
-cx+=_5a.kern[_58[j+1].code].x;
-}
-}
-var dx=0;
-if(_52=="middle"){
-dx=_57/2-_59/2;
-}else{
-if(_52=="end"){
-dx=_57-_59;
-}
-}
-lg.setTransform({dx:dx,dy:cy});
-cy+=this.viewbox.height*_53;
-}
-g.setTransform(dojox.gfx.matrix.scale(_55));
-return g;
-},onLoadBegin:function(url){
-},onLoad:function(_5b){
-}});
+	/*
+		dojox.gfx.VectorText
+		An implementation of the SVG Font 1.1 spec, using dojox.gfx.
+
+		Basic interface:
+		var f = new dojox.gfx.Font(url|string);
+		surface||group.createVectorText(text)
+			.setFill(fill)
+			.setStroke(stroke)
+			.setFont(fontStyleObject);
+
+		The arguments passed to createVectorText are the same as you would
+		pass to surface||group.createText; the difference is that this
+		is entirely renderer-agnostic, and the return value is a subclass
+		of dojox.gfx.Group.
+
+		Note also that the "defaultText" object is slightly different:
+		{ type:"vectortext", x:0, y:0, width:null, height: null,
+			text: "", align: "start", decoration: "none" }
+
+		...as well as the "defaultVectorFont" object:
+		{ type:"vectorfont", size:"10pt" }
+
+		The reason for this should be obvious: most of the style for the font is defined
+		by the font object itself.
+
+		Note that this will only render IF and WHEN you set the font.
+	 */
+	dojo.mixin(dojox.gfx, {
+		vectorFontFitting: {
+			NONE: 0,	//	render text according to passed size.
+			FLOW: 1,		//	render text based on the passed width and size
+			FIT: 2			//	render text based on a passed viewbox.
+		},
+		defaultVectorText: {
+			type:"vectortext", x:0, y:0, width: null, height: null,
+			text: "", align: "start", decoration: "none", fitting: 0,	//	vectorFontFitting.NONE
+			leading: 1.5	//	in ems.
+		},
+		defaultVectorFont: {
+			type:"vectorfont", size: "10pt", family: null
+		},
+		_vectorFontCache: {},
+		_svgFontCache: {},
+		getVectorFont: function(/* String */url){
+			if(dojox.gfx._vectorFontCache[url]){
+				return dojox.gfx._vectorFontCache[url];
+			}
+			return new dojox.gfx.VectorFont(url);
+		}
+	});
+
+	dojo.declare("dojox.gfx.VectorFont", null, {
+		_entityRe: /&(quot|apos|lt|gt|amp|#x[^;]+|#\d+);/g,
+		_decodeEntitySequence: function(str){
+			//	unescape the unicode sequences
+
+			//	nothing to decode
+			if(!str.match(this._entityRe)){ return; }  // undefined
+			var xmlEntityMap = {
+				amp:"&", apos:"'", quot:'"', lt:"<", gt:">"
+			};
+
+			//	we have at least one encoded entity.
+			var r, tmp="";
+			while((r=this._entityRe.exec(str))!==null){
+				if(r[1].charAt(1)=="x"){
+					tmp += String.fromCharCode(parseInt(r[1].slice(2), 16));
+				}
+				else if(!isNaN(parseInt(r[1].slice(1),10))){
+					tmp += String.fromCharCode(parseInt(r[1].slice(1), 10));
+				}
+				else {
+					tmp += xmlEntityMap[r[1]] || "";
+				}
+			}
+			return tmp;	//	String
+		},
+		_parse: function(/* String */svg, /* String */url){
+			//	summary:
+			//		Take the loaded SVG Font definition file and convert the info
+			//		into things we can use. The SVG Font definition must follow
+			//		the SVG 1.1 Font specification.
+			var doc = dojox.gfx._svgFontCache[url]||dojox.xml.DomParser.parse(svg);
+
+			//	font information
+			var f = doc.documentElement.byName("font")[0], face = doc.documentElement.byName("font-face")[0];
+			var unitsPerEm = parseFloat(face.getAttribute("units-per-em")||1000, 10);
+			var advance = {
+				x: parseFloat(f.getAttribute("horiz-adv-x"), 10),
+				y: parseFloat(f.getAttribute("vert-adv-y")||0, 10)
+			};
+			if(!advance.y){
+				advance.y = unitsPerEm;
+			}
+
+			var origin = {
+				horiz: {
+					x: parseFloat(f.getAttribute("horiz-origin-x")||0, 10),
+					y: parseFloat(f.getAttribute("horiz-origin-y")||0, 10)
+				},
+				vert: {
+					x: parseFloat(f.getAttribute("vert-origin-x")||0, 10),
+					y: parseFloat(f.getAttribute("vert-origin-y")||0, 10)
+				}
+			};
+
+			//	face information
+			var family = face.getAttribute("font-family"),
+				style = face.getAttribute("font-style")||"all",
+				variant = face.getAttribute("font-variant")||"normal",
+				weight = face.getAttribute("font-weight")||"all",
+				stretch = face.getAttribute("font-stretch")||"normal",
+
+				//	additional info, may not be needed
+				range = face.getAttribute("unicode-range")||"U+0-10FFFF",
+				panose = face.getAttribute("panose-1") || "0 0 0 0 0 0 0 0 0 0",
+				capHeight = face.getAttribute("cap-height"),
+				ascent = parseFloat(face.getAttribute("ascent")||(unitsPerEm-origin.vert.y), 10),
+				descent = parseFloat(face.getAttribute("descent")||origin.vert.y, 10),
+				baseline = {};
+
+			//	check for font-face-src/font-face-name
+			var name = family;
+			if(face.byName("font-face-name")[0]){
+				name = face.byName("font-face-name")[0].getAttribute("name");
+			}
+
+			//	see if this is cached already, and if so, forget the rest of the parsing.
+			if(dojox.gfx._vectorFontCache[name]){ return; }
+
+			//	get any provided baseline alignment offsets.
+			dojo.forEach(["alphabetic", "ideographic", "mathematical", "hanging" ], function(attr){
+				var a = face.getAttribute(attr);
+				if(a !== null /* be explicit, might be 0 */){
+					baseline[attr] = parseFloat(a, 10);
+				}
+			});
+
+		/*
+			//	TODO: decoration hinting.
+			var decoration = { };
+			dojo.forEach(["underline", "strikethrough", "overline"], function(type){
+				if(face.getAttribute(type+"-position")!=null){
+					decoration[type]={ };
+				}
+			});
+		*/
+
+			//	missing glyph info
+			var missing = parseFloat(doc.documentElement.byName("missing-glyph")[0].getAttribute("horiz-adv-x")||advance.x, 10);
+
+			//	glyph information
+			var glyphs = {}, glyphsByName={}, g=doc.documentElement.byName("glyph");
+			dojo.forEach(g, function(node){
+				//	we are going to assume the following:
+				//		1) we have the unicode attribute
+				//		2) we have the name attribute
+				//		3) we have the horiz-adv-x and d attributes.
+				var code = node.getAttribute("unicode"),
+					name = node.getAttribute("glyph-name"),
+					xAdv = parseFloat(node.getAttribute("horiz-adv-x")||advance.x, 10),
+					path = node.getAttribute("d");
+
+				//	unescape the unicode sequences
+				if(code.match(this._entityRe)){
+					code = this._decodeEntitySequence(code);
+				}
+
+				// build our glyph objects
+				var o = { code: code, name: name, xAdvance: xAdv, path: path };
+				glyphs[code]=o;
+				glyphsByName[name]=o;
+			}, this);
+
+			//	now the fun part: look for kerning pairs.
+			var hkern=doc.documentElement.byName("hkern");
+			dojo.forEach(hkern, function(node, i){
+				var k = -parseInt(node.getAttribute("k"),10);
+				//	look for either a code or a name
+				var u1=node.getAttribute("u1"),
+					g1=node.getAttribute("g1"),
+					u2=node.getAttribute("u2"),
+					g2=node.getAttribute("g2"),
+					gl;
+
+				if(u1){
+					//	the first of the pair is a sequence of unicode characters.
+					//	TODO: deal with unicode ranges and mulitple characters.
+					u1 = this._decodeEntitySequence(u1);
+					if(glyphs[u1]){
+						gl = glyphs[u1];
+					}
+				} else {
+					//	we are referring to a name.
+					//	TODO: deal with multiple names
+					if(glyphsByName[g1]){
+						gl = glyphsByName[g1];
+					}
+				}
+
+				if(gl){
+					if(!gl.kern){ gl.kern = {}; }
+					if(u2){
+						//	see the notes above.
+						u2 = this._decodeEntitySequence(u2);
+						gl.kern[u2] = { x: k };
+					} else {
+						if(glyphsByName[g2]){
+							gl.kern[glyphsByName[g2].code] = { x: k };
+						}
+					}
+				}
+			}, this);
+
+			//	pop the final definition in the font cache.
+			dojo.mixin(this, {
+				family: family,
+				name: name,
+				style: style,
+				variant: variant,
+				weight: weight,
+				stretch: stretch,
+				range: range,
+				viewbox: { width: unitsPerEm, height: unitsPerEm },
+				origin: origin,
+				advance: dojo.mixin(advance, {
+					missing:{ x: missing, y: missing }
+				}),
+				ascent: ascent,
+				descent: descent,
+				baseline: baseline,
+				glyphs: glyphs
+			});
+
+			//	cache the parsed font
+			dojox.gfx._vectorFontCache[name] = this;
+			dojox.gfx._vectorFontCache[url] = this;
+			if(name!=family && !dojox.gfx._vectorFontCache[family]){
+				dojox.gfx._vectorFontCache[family] = this;
+			}
+
+			//	cache the doc
+			if(!dojox.gfx._svgFontCache[url]){
+				dojox.gfx._svgFontCache[url]=doc;
+			}
+		},
+		_clean: function(){
+			//	summary:
+			//		Clean off all of the given mixin parameters.
+			var name = this.name, family = this.family;
+			dojo.forEach(["family","name","style","variant",
+				"weight","stretch","range","viewbox",
+				"origin","advance","ascent","descent",
+				"baseline","glyphs"], function(prop){
+					try{ delete this[prop]; } catch(e) { }
+			}, this);
+
+			//	try to pull out of the font cache.
+			if(dojox.gfx._vectorFontCache[name]){
+				delete dojox.gfx._vectorFontCache[name];
+			}
+			if(dojox.gfx._vectorFontCache[family]){
+				delete dojox.gfx._vectorFontCache[family];
+			}
+			return this;
+		},
+
+		constructor: function(/* String|dojo._Url */url){
+			//	summary::
+			//		Create this font object based on the SVG Font definition at url.
+			this._defaultLeading = 1.5;
+			if(url!==undefined){
+				this.load(url);
+			}
+		},
+		load: function(/* String|dojo._Url */url){
+			//	summary::
+			//		Load the passed SVG and send it to the parser for parsing.
+			this.onLoadBegin(url.toString());
+			this._parse(
+				dojox.gfx._svgFontCache[url.toString()]||dojo._getText(url.toString()),
+				url.toString()
+			);
+			this.onLoad(this);
+			return this;	//	dojox.gfx.VectorFont
+		},
+		initialized: function(){
+			//	summary::
+			//		Return if we've loaded a font def, and the parsing was successful.
+			return (this.glyphs!==null);	//	Boolean
+		},
+
+		//	preset round to 3 places.
+		_round: function(n){ return Math.round(1000*n)/1000; },
+		_leading: function(unit){ return this.viewbox.height * (unit||this._defaultLeading); },
+		_normalize: function(str){
+			return str.replace(/\s+/g, String.fromCharCode(0x20));
+		},
+
+		_getWidth: function(glyphs){
+			var w=0, last=0, lastGlyph=null;
+			dojo.forEach(glyphs, function(glyph, i){
+				last=glyph.xAdvance;
+				if(glyphs[i] && glyph.kern && glyph.kern[glyphs[i].code]){
+					last += glyph.kern[glyphs[i].code].x;
+				}
+				w += last;
+				lastGlyph = glyph;
+			});
+
+			//	if the last glyph was a space, pull it off.
+			if(lastGlyph && lastGlyph.code == " "){
+				w -= lastGlyph.xAdvance;
+			}
+
+			return this._round(w/*-last*/);
+		},
+
+		_getLongestLine: function(lines){
+			var maxw=0, idx=0;
+			dojo.forEach(lines, function(line, i){
+				var max = Math.max(maxw, this._getWidth(line));
+				if(max > maxw){
+					maxw = max;
+					idx=i;
+				}
+			}, this);
+			return { width: maxw, index: idx, line: lines[idx] };
+		},
+
+		_trim: function(lines){
+			var fn = function(arr){
+				//	check if the first or last character is a space and if so, remove it.
+				if(!arr.length){ return; }
+				if(arr[arr.length-1].code == " "){ arr.splice(arr.length-1, 1); }
+				if(!arr.length){ return; }
+				if(arr[0].code == " "){ arr.splice(0, 1); }
+			};
+
+			if(dojo.isArray(lines[0])){
+				//	more than one line.
+				dojo.forEach(lines, fn);
+			} else {
+				fn(lines);
+			}
+			return lines;
+		},
+
+		_split: function(chars, nLines){
+			//	summary:
+			//		split passed chars into nLines by finding the closest whitespace.
+			var w = this._getWidth(chars),
+				limit = Math.floor(w/nLines),
+				lines = [],
+				cw = 0,
+				c = [],
+				found = false;
+
+			for(var i=0, l=chars.length; i<l; i++){
+				if(chars[i].code == " "){ found = true; }
+				cw += chars[i].xAdvance;
+				if(i+1<l && chars[i].kern && chars[i].kern[chars[i+1].code]){
+					cw += chars[i].kern[chars[i+1].code].x;
+				}
+
+				if(cw>=limit){
+					var chr=chars[i];
+					while(found && chr.code != " " && i>=0){
+						chr = c.pop(); i--;
+					}
+					lines.push(c);
+					c=[];
+					cw=0;
+					found=false;
+				}
+				c.push(chars[i]);
+			}
+			if(c.length){ lines.push(c); }
+			//	"trim" it
+			return this._trim(lines);
+		},
+
+		_getSizeFactor: function(size){
+			//	given the size, return a scaling factor based on the height of the
+			//	font as defined in the font definition file.
+			size += "";	//	force the string cast.
+			var metrics = dojox.html.metrics.getCachedFontMeasurements(),
+				height=this.viewbox.height,
+				f=metrics["1em"],
+				unit=parseFloat(size, 10);	//	the default.
+			if(size.indexOf("em")>-1){
+				return this._round((metrics["1em"]*unit)/height);
+			}
+			else if(size.indexOf("ex")>-1){
+				return this._round((metrics["1ex"]*unit)/height);
+			}
+			else if(size.indexOf("pt")>-1){
+				return this._round(((metrics["12pt"] / 12)*unit) / height);
+			}
+			else if(size.indexOf("px")>-1){
+				return this._round(((metrics["16px"] / 16)*unit) / height);
+			}
+			else if(size.indexOf("%")>-1){
+				return this._round((metrics["1em"]*(unit / 100)) / height);
+			}
+			else {
+				f=metrics[size]||metrics.medium;
+				return this._round(f/height);
+			}
+		},
+
+		_getFitFactor: function(lines, w, h, l){
+			//	summary:
+			//		Find the scaling factor for the given phrase set.
+			if(!h){
+				//	if no height was passed, we assume an array of glyphs instead of lines.
+				return this._round(w/this._getWidth(lines));
+			} else {
+				var maxw = this._getLongestLine(lines).width,
+					maxh = (lines.length*(this.viewbox.height*l))-((this.viewbox.height*l)-this.viewbox.height);
+				return this._round(Math.min(w/maxw, h/maxh));
+			}
+		},
+		_getBestFit: function(chars, w, h, ldng){
+			//	summary:
+			//		Get the best number of lines to return given w and h.
+			var limit=32,
+				factor=0,
+				lines=limit;
+			while(limit>0){
+				var f=this._getFitFactor(this._split(chars, limit), w, h, ldng);
+				if(f>factor){
+					factor = f;
+					lines=limit;
+				}
+				limit--;
+			}
+			return { scale: factor, lines: this._split(chars, lines) };
+		},
+
+		_getBestFlow: function(chars, w, scale){
+			//	summary:
+			//		Based on the given scale, do the best line splitting possible.
+			var lines = [],
+				cw = 0,
+				c = [],
+				found = false;
+			for(var i=0, l=chars.length; i<l; i++){
+				if(chars[i].code == " "){ found = true; }
+				var tw = chars[i].xAdvance;
+				if(i+1<l && chars[i].kern && chars[i].kern[chars[i+1].code]){
+					tw += chars[i].kern[chars[i+1].code].x;
+				}
+				cw += scale*tw;
+
+				if(cw>=w){
+					var chr=chars[i];
+					while(found && chr.code != " " && i>=0){
+						chr = c.pop(); i--;
+					}
+					lines.push(c);
+					c=[];
+					cw=0;
+					found=false;
+				}
+				c.push(chars[i]);
+			}
+			if(c.length){ lines.push(c); }
+			return this._trim(lines);
+		},
+
+		//	public functions
+		getWidth: function(/* String */text, /* Float? */scale){
+			//	summary:
+			//		Get the width of the rendered text without actually rendering it.
+			return this._getWidth(dojo.map(this._normalize(text).split(""), function(chr){
+				return this.glyphs[chr] || { xAdvance: this.advance.missing.x };
+			}, this)) * (scale || 1);	//	Float
+		},
+		getLineHeight: function(/* Float? */scale){
+			//	summary:
+			//		return the height of a single line, sans leading, based on scale.
+			return this.viewbox.height * (scale || 1);	//	Float
+		},
+
+		//	A note:
+		//		Many SVG exports do not include information such as x-height, caps-height
+		//		and other coords that may help alignment.  We can calc the baseline and
+		//		we can get a mean line (i.e. center alignment) but that's about all, reliably.
+		getCenterline: function(/* Float? */scale){
+			//	summary:
+			//		return the y coordinate that is the center of the viewbox.
+			return (scale||1) * (this.viewbox.height/2);
+		},
+		getBaseline: function(/* Float? */scale){
+			//	summary:
+			//		Find the baseline coord for alignment; adjust for scale if passed.
+			return (scale||1) * (this.viewbox.height+this.descent);	//	Float
+		},
+
+		draw: function(/* dojox.gfx.Container */group, /* dojox.gfx.__TextArgs */textArgs, /* dojox.gfx.__FontArgs */fontArgs, /* dojox.gfx.__FillArgs */fillArgs, /* dojox.gfx.__StrokeArgs? */strokeArgs){
+			//	summary:
+			//		based on the passed parameters, draw the given text using paths
+			//		defined by this font.
+			//
+			//	description:
+			//		The main method of a VectorFont, draw() will take a text fragment
+			//		and render it in a set of groups and paths based on the parameters
+			//		passed.
+			//
+			//		The basics of drawing text are simple enough: pass it your text as
+			//		part of the textArgs object, pass size and family info as part of
+			//		the fontArgs object, pass at least a color as the fillArgs object,
+			//		and if you are looking to create an outline, pass the strokeArgs
+			//		object as well. fillArgs and strokeArgs are the same as any other
+			//		gfx fill and stroke arguments; they are simply applied to any path
+			//		object generated by this method.
+			//
+			//		Resulting GFX structure
+			//		-----------------------
+			//
+			//		The result of this function is a set of gfx objects in the following
+			//		structure:
+			//
+			//	|	dojox.gfx.Group 			//	the parent group generated by this function
+			//	|	+	dojox.gfx.Group[]		//	a group generated for each line of text
+			//	|		+	dojox.gfx.Path[]	//	each glyph/character in the text
+			//
+			//		Scaling transformations (i.e. making the generated text the correct size)
+			//		are always applied to the parent Group that is generated (i.e. the top
+			//		node in the above example).  In theory, if you are looking to do any kind
+			//		of other transformations (such as a translation), you should apply it to
+			//		the group reference you pass to this method.  If you find that you need
+			//		to apply transformations to the group that is returned by this method,
+			//		you will need to reapply the scaling transformation as the *last* transform,
+			//		like so:
+			//
+			//	|	textGroup.setTransform(new dojox.gfx.Matrix2D([
+			//	|		dojox.gfx.matrix.translate({ dx: dx, dy: dy }),
+			//	|		textGroup.getTransform()
+			//	|	]));
+			//
+			//		In general, this should never be necessary unless you are doing advanced
+			//		placement of your text.
+			//
+			//		Advanced Layout Functionality
+			//		-----------------------------
+			//
+			//		In addition to straight text fragments, draw() supports a few advanced
+			//		operations not normally available with vector graphics:
+			//
+			//		* Flow operations (i.e. wrap to a given width)
+			//		* Fitting operations (i.e. find a best fit to a given rectangle)
+			//
+			//		To enable either, pass a `fitting` property along with the textArgs object.
+			//		The possible values are contained in the dojox.gfx.vectorFontFitting enum
+			//		(NONE, FLOW, FIT).
+			//
+			//		`Flow fitting`
+			//		Flow fitting requires both a passed size (in the fontArgs object) and a
+			//		width (passed with the textArgs object).  draw() will attempt to split the
+			//		passed text up into lines, at the closest whitespace according to the
+			//		passed width.  If a width is missing, it will revert to NONE.
+			//
+			//		`Best fit fitting`
+			//		Doing a "best fit" means taking the passed text, and finding the largest
+			//		size and line breaks so that it is the closest fit possible.  With best
+			//		fit, any size arguments are ignored; if a height is missing, it will revert
+			//		to NONE.
+			//
+			//		Other notes
+			//		-----------
+			//
+			//		`a11y`
+			//		Since the results of this method are rendering using pure paths (think
+			//		"convert to outlines" in Adobe Illustrator), any text rendered by this
+			//		code is NOT considered a11y-friendly.  If a11y is a requirement, we
+			//		suggest using other, more a11y-friendly methods.
+			//
+			//		`Font sources`
+			//		Always make sure that you are legally allowed to use any fonts that you
+			//		convert to SVG format; we claim no responsibility for any licensing
+			//		infractions that may be caused by the use of this code.
+			if(!this.initialized()){
+				throw new Error("dojox.gfx.VectorFont.draw(): we have not been initialized yet.");
+			}
+			//	TODO: BIDI handling.  Deal with layout/alignments based on font parameters.
+
+			//	start by creating the overall group.  This is the INNER group (the caller
+			//	should be the outer).
+			var g = group.createGroup();
+
+			//	do the x/y translation on the parent group
+			//	FIXME: this is probably not the best way of doing this.
+			if(textArgs.x || textArgs.y){
+				group.applyTransform({ dx: textArgs.x||0, dy: textArgs.y||0 });
+			}
+
+			//	go get the glyph array.
+			var text = dojo.map(this._normalize(textArgs.text).split(""), function(chr){
+				return this.glyphs[chr] || { path:null, xAdvance: this.advance.missing.x };
+			}, this);
+
+			//	determine the font style info, ignore decoration.
+			var size = fontArgs.size,
+				fitting = textArgs.fitting,
+				width = textArgs.width,
+				height = textArgs.height,
+				align = textArgs.align,
+				leading = textArgs.leading||this._defaultLeading;
+
+			//	figure out if we have to do fitting at all.
+			if(fitting){
+				//	more than zero.
+				if((fitting==dojox.gfx.vectorFontFitting.FLOW && !width) || (fitting==dojox.gfx.vectorFontFitting.FIT && (!width || !height))){
+					//	reset the fitting if we don't have everything we need.
+					fitting = dojox.gfx.vectorFontFitting.NONE;
+				}
+			}
+
+			//	set up the lines array and the scaling factor.
+			var lines, scale;
+			switch(fitting){
+				case dojox.gfx.vectorFontFitting.FIT:
+					var o=this._getBestFit(text, width, height, leading);
+					scale = o.scale;
+					lines = o.lines;
+					break;
+
+				case dojox.gfx.vectorFontFitting.FLOW:
+					scale = this._getSizeFactor(size);
+					lines = this._getBestFlow(text, width, scale);
+					break;
+
+				default:
+					scale = this._getSizeFactor(size);
+					lines = [ text ];
+
+			}
+
+			//	make sure lines doesn't have any empty lines.
+			lines = dojo.filter(lines, function(item){
+				return item.length>0;
+			});
+
+			//	let's start drawing.
+			var cy = 0,
+				maxw = this._getLongestLine(lines).width;
+
+			for(var i=0, l=lines.length; i<l; i++){
+				var cx = 0,
+					line=lines[i],
+					linew = this._getWidth(line),
+					lg=g.createGroup();
+
+				//	loop through the glyphs and add them to the line group (lg)
+				for (var j=0; j<line.length; j++){
+					var glyph=line[j];
+					if(glyph.path!==null){
+						var p = lg.createPath(glyph.path).setFill(fillArgs);
+						if(strokeArgs){ p.setStroke(strokeArgs); }
+						p.setTransform([
+							dojox.gfx.matrix.flipY,
+							dojox.gfx.matrix.translate(cx, -this.viewbox.height-this.descent)
+						]);
+					}
+					cx += glyph.xAdvance;
+					if(j+1<line.length && glyph.kern && glyph.kern[line[j+1].code]){
+						cx += glyph.kern[line[j+1].code].x;
+					}
+				}
+
+				//	transform the line group.
+				var dx = 0;
+				if(align=="middle"){ dx = maxw/2 - linew/2; }
+				else if(align=="end"){ dx = maxw - linew; }
+				lg.setTransform({ dx: dx, dy: cy });
+				cy += this.viewbox.height * leading;
+			}
+
+			//	scale the group
+			g.setTransform(dojox.gfx.matrix.scale(scale));
+
+			//	return the overall group
+			return g;	//	dojox.gfx.Group
+		},
+
+		//	events
+		onLoadBegin: function(/* String */url){ },
+		onLoad: function(/* dojox.gfx.VectorFont */font){ }
+	});
+
+	//	TODO: dojox.gfx integration
+/*
+
+	//	Inherit from Group but attach Text properties to it.
+	dojo.declare("dojox.gfx.VectorText", dojox.gfx.Group, {
+		constructor: function(rawNode){
+			dojox.gfx.Group._init.call(this);
+			this.fontStyle = null;
+		},
+
+		//	private methods.
+		_setFont: function(){
+			//	render this using the font code.
+			var f = this.fontStyle;
+			var font = dojox.gfx._vectorFontCache[f.family];
+			if(!font){
+				throw new Error("dojox.gfx.VectorText._setFont: the passed font family '" + f.family + "' was not found.");
+			}
+
+			//	the actual rendering belongs to the font itself.
+			font.draw(this, this.shape, this.fontStyle, this.fillStyle, this.strokeStyle);
+		},
+
+		getFont: function(){ return this.fontStyle; },
+
+		//	overridden public methods.
+		setShape: function(newShape){
+			dojox.gfx.Group.setShape.call(this);
+			this.shape = dojox.gfx.makeParameters(this.shape, newShape);
+			this.bbox = null;
+			this._setFont();
+			return this;
+		},
+
+		//	if we've been drawing, we should have exactly one child, and that
+		//		child will contain the real children.
+		setFill: function(fill){
+			this.fillStyle = fill;
+			if(this.children[0]){
+				dojo.forEach(this.children[0].children, function(group){
+					dojo.forEach(group.children, function(path){
+						path.setFill(fill);
+					});
+				}, this);
+			}
+			return this;
+		},
+		setStroke: function(stroke){
+			this.strokeStyle = stroke;
+			if(this.children[0]){
+				dojo.forEach(this.children[0].children, function(group){
+					dojo.forEach(group.children, function(path){
+						path.setStroke(stroke);
+					});
+				}, this);
+			}
+			return this;
+		},
+
+		setFont: function(newFont){
+			//	this will do the real rendering.
+			this.fontStyle = typeof newFont == "string" ? dojox.gfx.splitFontString(newFont)
+				: dojox.gfx.makeParameters(dojox.gfx.defaultFont, newFont);
+			this._setFont();
+			return this;
+		},
+
+		getBoundingBox: function(){
+			return this.bbox;
+		}
+	});
+
+	//	TODO: figure out how to add this to container objects!
+	dojox.gfx.shape.Creator.createVectorText = function(text){
+		return this.createObject(dojox.gfx.VectorText, text);
+	}
+*/
 })();
-}
diff --git a/dojox/gfx/_base.js b/dojox/gfx/_base.js
index 7b2f04a..bdecc6d 100644
--- a/dojox/gfx/_base.js
+++ b/dojox/gfx/_base.js
@@ -1,219 +1,370 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx._base"]){
-dojo._hasResource["dojox.gfx._base"]=true;
 dojo.provide("dojox.gfx._base");
+
 (function(){
-var g=dojox.gfx,b=g._base;
-g._hasClass=function(_1,_2){
-var _3=_1.getAttribute("className");
-return _3&&(" "+_3+" ").indexOf(" "+_2+" ")>=0;
-};
-g._addClass=function(_4,_5){
-var _6=_4.getAttribute("className")||"";
-if(!_6||(" "+_6+" ").indexOf(" "+_5+" ")<0){
-_4.setAttribute("className",_6+(_6?" ":"")+_5);
-}
-};
-g._removeClass=function(_7,_8){
-var _9=_7.getAttribute("className");
-if(_9){
-_7.setAttribute("className",_9.replace(new RegExp("(^|\\s+)"+_8+"(\\s+|$)"),"$1$2"));
-}
-};
-b._getFontMeasurements=function(){
-var _a={"1em":0,"1ex":0,"100%":0,"12pt":0,"16px":0,"xx-small":0,"x-small":0,"small":0,"medium":0,"large":0,"x-large":0,"xx-large":0};
-if(dojo.isIE){
-dojo.doc.documentElement.style.fontSize="100%";
-}
-var _b=dojo.doc.createElement("div");
-var s=_b.style;
-s.position="absolute";
-s.left="-100px";
-s.top="0px";
-s.width="30px";
-s.height="1000em";
-s.border="0px";
-s.margin="0px";
-s.padding="0px";
-s.outline="none";
-s.lineHeight="1";
-s.overflow="hidden";
-dojo.body().appendChild(_b);
-for(var p in _a){
-_b.style.fontSize=p;
-_a[p]=Math.round(_b.offsetHeight*12/16)*16/12/1000;
-}
-dojo.body().removeChild(_b);
-_b=null;
-return _a;
-};
-var _c=null;
-b._getCachedFontMeasurements=function(_d){
-if(_d||!_c){
-_c=b._getFontMeasurements();
-}
-return _c;
-};
-var _e=null,_f={};
-b._getTextBox=function(_10,_11,_12){
-var m,s,al=arguments.length;
-if(!_e){
-m=_e=dojo.doc.createElement("div");
-s=m.style;
-s.position="absolute";
-s.left="-10000px";
-s.top="0";
-dojo.body().appendChild(m);
-}else{
-m=_e;
-s=m.style;
-}
-m.className="";
-s.border="0";
-s.margin="0";
-s.padding="0";
-s.outline="0";
-if(al>1&&_11){
-for(var i in _11){
-if(i in _f){
-continue;
-}
-s[i]=_11[i];
-}
-}
-if(al>2&&_12){
-m.className=_12;
-}
-m.innerHTML=_10;
-if(m["getBoundingClientRect"]){
-var bcr=m.getBoundingClientRect();
-return {l:bcr.left,t:bcr.top,w:bcr.width||(bcr.right-bcr.left),h:bcr.height||(bcr.bottom-bcr.top)};
-}else{
-return dojo.marginBox(m);
-}
-};
-var _13=0;
-b._getUniqueId=function(){
-var id;
-do{
-id=dojo._scopeName+"Unique"+(++_13);
-}while(dojo.byId(id));
-return id;
-};
+	var g = dojox.gfx, b = g._base;
+
+	// candidates for dojox.style (work on VML and SVG nodes)
+	g._hasClass = function(/*DomNode*/node, /*String*/classStr){
+		//	summary:
+		//		Returns whether or not the specified classes are a portion of the
+		//		class list currently applied to the node.
+		// return (new RegExp('(^|\\s+)'+classStr+'(\\s+|$)')).test(node.className)	// Boolean
+		var cls = node.getAttribute("className");
+		return cls && (" " + cls + " ").indexOf(" " + classStr + " ") >= 0;  // Boolean
+	}
+	g._addClass = function(/*DomNode*/node, /*String*/classStr){
+		//	summary:
+		//		Adds the specified classes to the end of the class list on the
+		//		passed node.
+		var cls = node.getAttribute("className") || "";
+		if(!cls || (" " + cls + " ").indexOf(" " + classStr + " ") < 0){
+			node.setAttribute("className", cls + (cls ? " " : "") + classStr);
+		}
+	}
+	g._removeClass = function(/*DomNode*/node, /*String*/classStr){
+		//	summary: Removes classes from node.
+		var cls = node.getAttribute("className");
+		if(cls){
+			node.setAttribute(
+				"className", 
+				cls.replace(new RegExp('(^|\\s+)' + classStr + '(\\s+|$)'), "$1$2")
+			);
+		}
+	}
+
+	// candidate for dojox.html.metrics (dynamic font resize handler is not implemented here)
+
+	//	derived from Morris John's emResized measurer
+	b._getFontMeasurements = function(){
+		//	summary:
+		//		Returns an object that has pixel equivilents of standard font
+		//		size values.
+		var heights = {
+			'1em': 0, '1ex': 0, '100%': 0, '12pt': 0, '16px': 0, 'xx-small': 0,
+			'x-small': 0, 'small': 0, 'medium': 0, 'large': 0, 'x-large': 0,
+			'xx-large': 0
+		};
+
+		if(dojo.isIE){
+			//	we do a font-size fix if and only if one isn't applied already.
+			//	NOTE: If someone set the fontSize on the HTML Element, this will kill it.
+			dojo.doc.documentElement.style.fontSize="100%";
+		}
+
+		//	set up the measuring node.
+		var div = dojo.doc.createElement("div");
+		var s = div.style;
+		s.position = "absolute";
+		s.left = "-100px";
+		s.top = "0px";
+		s.width = "30px";
+		s.height = "1000em";
+		s.borderWidth = "0px";
+		s.margin = "0px";
+		s.padding = "0px";
+		s.outline = "none";
+		s.lineHeight = "1";
+		s.overflow = "hidden";
+		dojo.body().appendChild(div);
+
+		//	do the measurements.
+		for(var p in heights){
+			div.style.fontSize = p;
+			heights[p] = Math.round(div.offsetHeight * 12/16) * 16/12 / 1000;
+		}
+
+		dojo.body().removeChild(div);
+		div = null;
+		return heights; 	//	object
+	};
+
+	var fontMeasurements = null;
+
+	b._getCachedFontMeasurements = function(recalculate){
+		if(recalculate || !fontMeasurements){
+			fontMeasurements = b._getFontMeasurements();
+		}
+		return fontMeasurements;
+	};
+
+	// candidate for dojox.html.metrics
+
+	var measuringNode = null, empty = {};
+	b._getTextBox = function(	/*String*/ text,
+								/*Object*/ style,
+								/*String?*/ className){
+		var m, s, al = arguments.length;
+		if(!measuringNode){
+			m = measuringNode = dojo.doc.createElement("div");
+			s = m.style;
+			s.position = "absolute";
+			s.left = "-10000px";
+			s.top = "0";
+			dojo.body().appendChild(m);
+		}else{
+			m = measuringNode;
+			s = m.style;
+		}
+		// reset styles
+		m.className = "";
+		s.borderWidth = "0";
+		s.margin = "0";
+		s.padding = "0";
+		s.outline = "0";
+		// set new style
+		if(al > 1 && style){
+			for(var i in style){
+				if(i in empty){ continue; }
+				s[i] = style[i];
+			}
+		}
+		// set classes
+		if(al > 2 && className){
+			m.className = className;
+		}
+		// take a measure
+		m.innerHTML = text;
+
+		if(m["getBoundingClientRect"]){
+			var bcr = m.getBoundingClientRect();
+			return {l: bcr.left, t: bcr.top, w: bcr.width || (bcr.right - bcr.left), h: bcr.height || (bcr.bottom - bcr.top)};
+		}else{
+			return dojo.marginBox(m);
+		}
+	};
+
+	// candidate for dojo.dom
+
+	var uniqueId = 0;
+	b._getUniqueId = function(){
+		// summary: returns a unique string for use with any DOM element
+		var id;
+		do{
+			id = dojo._scopeName + "Unique" + (++uniqueId);
+		}while(dojo.byId(id));
+		return id;
+	};
 })();
-dojo.mixin(dojox.gfx,{defaultPath:{type:"path",path:""},defaultPolyline:{type:"polyline",points:[]},defaultRect:{type:"rect",x:0,y:0,width:100,height:100,r:0},defaultEllipse:{type:"ellipse",cx:0,cy:0,rx:200,ry:100},defaultCircle:{type:"circle",cx:0,cy:0,r:100},defaultLine:{type:"line",x1:0,y1:0,x2:100,y2:100},defaultImage:{type:"image",x:0,y:0,width:0,height:0,src:""},defaultText:{type:"text",x:0,y:0,text:"",align:"start",decoration:"none",rotated:false,kerning:true},defaultTextPath:{typ [...]
-var _14={};
-return function(_15){
-var t=_14[_15];
-if(t){
-return new t();
-}
-t=_14[_15]=new Function;
-t.prototype=dojox.gfx["default"+_15];
-return new t();
-};
-})(),normalizeColor:function(_16){
-return (_16 instanceof dojo.Color)?_16:new dojo.Color(_16);
-},normalizeParameters:function(_17,_18){
-if(_18){
-var _19={};
-for(var x in _17){
-if(x in _18&&!(x in _19)){
-_17[x]=_18[x];
-}
-}
-}
-return _17;
-},makeParameters:function(_1a,_1b){
-if(!_1b){
-return dojo.delegate(_1a);
-}
-var _1c={};
-for(var i in _1a){
-if(!(i in _1c)){
-_1c[i]=dojo.clone((i in _1b)?_1b[i]:_1a[i]);
-}
-}
-return _1c;
-},formatNumber:function(x,_1d){
-var val=x.toString();
-if(val.indexOf("e")>=0){
-val=x.toFixed(4);
-}else{
-var _1e=val.indexOf(".");
-if(_1e>=0&&val.length-_1e>5){
-val=x.toFixed(4);
-}
-}
-if(x<0){
-return val;
-}
-return _1d?" "+val:val;
-},makeFontString:function(_1f){
-return _1f.style+" "+_1f.variant+" "+_1f.weight+" "+_1f.size+" "+_1f.family;
-},splitFontString:function(str){
-var _20=dojox.gfx.getDefault("Font");
-var t=str.split(/\s+/);
-do{
-if(t.length<5){
-break;
-}
-_20.style=t[0];
-_20.variant=t[1];
-_20.weight=t[2];
-var i=t[3].indexOf("/");
-_20.size=i<0?t[3]:t[3].substring(0,i);
-var j=4;
-if(i<0){
-if(t[4]=="/"){
-j=6;
-}else{
-if(t[4].charAt(0)=="/"){
-j=5;
-}
-}
-}
-if(j<t.length){
-_20.family=t.slice(j).join(" ");
-}
-}while(false);
-return _20;
-},cm_in_pt:72/2.54,mm_in_pt:7.2/2.54,px_in_pt:function(){
-return dojox.gfx._base._getCachedFontMeasurements()["12pt"]/12;
-},pt2px:function(len){
-return len*dojox.gfx.px_in_pt();
-},px2pt:function(len){
-return len/dojox.gfx.px_in_pt();
-},normalizedLength:function(len){
-if(len.length==0){
-return 0;
-}
-if(len.length>2){
-var _21=dojox.gfx.px_in_pt();
-var val=parseFloat(len);
-switch(len.slice(-2)){
-case "px":
-return val;
-case "pt":
-return val*_21;
-case "in":
-return val*72*_21;
-case "pc":
-return val*12*_21;
-case "mm":
-return val*dojox.gfx.mm_in_pt*_21;
-case "cm":
-return val*dojox.gfx.cm_in_pt*_21;
-}
-}
-return parseFloat(len);
-},pathVmlRegExp:/([A-Za-z]+)|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,pathSvgRegExp:/([A-Za-z])|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,equalSources:function(a,b){
-return a&&b&&a==b;
-}});
-}
+
+dojo.mixin(dojox.gfx, {
+	//	summary:
+	// 		defines constants, prototypes, and utility functions
+
+	// default shapes, which are used to fill in missing parameters
+	defaultPath: {
+		type: "path", path: ""
+	},
+	defaultPolyline: {
+		type: "polyline", points: []
+	},
+	defaultRect: {
+		type: "rect", x: 0, y: 0, width: 100, height: 100, r: 0
+	},
+	defaultEllipse: {
+		type: "ellipse", cx: 0, cy: 0, rx: 200, ry: 100
+	},
+	defaultCircle: {
+		type: "circle", cx: 0, cy: 0, r: 100
+	},
+	defaultLine: {
+		type: "line", x1: 0, y1: 0, x2: 100, y2: 100
+	},
+	defaultImage: {
+		type: "image", x: 0, y: 0, width: 0, height: 0, src: ""
+	},
+	defaultText: {
+		type: "text", x: 0, y: 0, text: "", align: "start",
+		decoration: "none", rotated: false, kerning: true
+	},
+	defaultTextPath: {
+		type: "textpath", text: "", align: "start",
+		decoration: "none", rotated: false, kerning: true
+	},
+
+	// default geometric attributes
+	defaultStroke: {
+		type: "stroke", color: "black", style: "solid", width: 1, 
+		cap: "butt", join: 4
+	},
+	defaultLinearGradient: {
+		type: "linear", x1: 0, y1: 0, x2: 100, y2: 100,
+		colors: [
+			{ offset: 0, color: "black" }, { offset: 1, color: "white" }
+		]
+	},
+	defaultRadialGradient: {
+		type: "radial", cx: 0, cy: 0, r: 100,
+		colors: [
+			{ offset: 0, color: "black" }, { offset: 1, color: "white" }
+		]
+	},
+	defaultPattern: {
+		type: "pattern", x: 0, y: 0, width: 0, height: 0, src: ""
+	},
+	defaultFont: {
+		type: "font", style: "normal", variant: "normal", 
+		weight: "normal", size: "10pt", family: "serif"
+	},
+
+	getDefault: (function(){
+		var typeCtorCache = {};
+		// a memoized delegate()
+		return function(/*String*/ type){
+			var t = typeCtorCache[type];
+			if(t){
+				return new t();
+			}
+			t = typeCtorCache[type] = new Function;
+			t.prototype = dojox.gfx[ "default" + type ];
+			return new t();
+		}
+	})(),
+
+	normalizeColor: function(/*Color*/ color){
+		//	summary:
+		// 		converts any legal color representation to normalized
+		// 		dojo.Color object
+		return (color instanceof dojo.Color) ? color : new dojo.Color(color); // dojo.Color
+	},
+	normalizeParameters: function(existed, update){
+		//	summary:
+		// 		updates an existing object with properties from an "update"
+		// 		object
+		//	existed: Object
+		//		the "target" object to be updated
+		//	update:  Object
+		//		the "update" object, whose properties will be used to update
+		//		the existed object
+		if(update){
+			var empty = {};
+			for(var x in existed){
+				if(x in update && !(x in empty)){
+					existed[x] = update[x];
+				}
+			}
+		}
+		return existed;	// Object
+	},
+	makeParameters: function(defaults, update){
+		//	summary:
+		// 		copies the original object, and all copied properties from the
+		// 		"update" object
+		//	defaults: Object
+		//		the object to be cloned before updating
+		//	update:   Object
+		//		the object, which properties are to be cloned during updating
+		if(!update){
+			// return dojo.clone(defaults);
+			return dojo.delegate(defaults);
+		}
+		var result = {};
+		for(var i in defaults){
+			if(!(i in result)){
+				result[i] = dojo.clone((i in update) ? update[i] : defaults[i]);
+			}
+		}
+		return result; // Object
+	},
+	formatNumber: function(x, addSpace){
+		// summary: converts a number to a string using a fixed notation
+		// x:			Number:		number to be converted
+		// addSpace:	Boolean?:	if it is true, add a space before a positive number
+		var val = x.toString();
+		if(val.indexOf("e") >= 0){
+			val = x.toFixed(4);
+		}else{
+			var point = val.indexOf(".");
+			if(point >= 0 && val.length - point > 5){
+				val = x.toFixed(4);
+			}
+		}
+		if(x < 0){
+			return val; // String
+		}
+		return addSpace ? " " + val : val; // String
+	},
+	// font operations
+	makeFontString: function(font){
+		// summary: converts a font object to a CSS font string
+		// font:	Object:	font object (see dojox.gfx.defaultFont)
+		return font.style + " " + font.variant + " " + font.weight + " " + font.size + " " + font.family; // Object
+	},
+	splitFontString: function(str){
+		// summary:
+		//		converts a CSS font string to a font object
+		// description:
+		//		Converts a CSS font string to a gfx font object. The CSS font
+		//		string components should follow the W3C specified order
+		//		(see http://www.w3.org/TR/CSS2/fonts.html#font-shorthand):
+		//		style, variant, weight, size, optional line height (will be
+		//		ignored), and family.
+		// str: String
+		//		a CSS font string
+		var font = dojox.gfx.getDefault("Font");
+		var t = str.split(/\s+/);
+		do{
+			if(t.length < 5){ break; }
+			font.style   = t[0];
+			font.variant = t[1];
+			font.weight  = t[2];
+			var i = t[3].indexOf("/");
+			font.size = i < 0 ? t[3] : t[3].substring(0, i);
+			var j = 4;
+			if(i < 0){
+				if(t[4] == "/"){
+					j = 6;
+				}else if(t[4].charAt(0) == "/"){
+					j = 5;
+				}
+			}
+			if(j < t.length){
+				font.family = t.slice(j).join(" ");
+			}
+		}while(false);
+		return font;	// Object
+	},
+	// length operations
+	cm_in_pt: 72 / 2.54,	// Number: points per centimeter
+	mm_in_pt: 7.2 / 2.54,	// Number: points per millimeter
+	px_in_pt: function(){
+		// summary: returns a number of pixels per point
+		return dojox.gfx._base._getCachedFontMeasurements()["12pt"] / 12;	// Number
+	},
+	pt2px: function(len){
+		// summary: converts points to pixels
+		// len: Number: a value in points
+		return len * dojox.gfx.px_in_pt();	// Number
+	},
+	px2pt: function(len){
+		// summary: converts pixels to points
+		// len: Number: a value in pixels
+		return len / dojox.gfx.px_in_pt();	// Number
+	},
+	normalizedLength: function(len) {
+		// summary: converts any length value to pixels
+		// len: String: a length, e.g., "12pc"
+		if(len.length == 0) return 0;
+		if(len.length > 2){
+			var px_in_pt = dojox.gfx.px_in_pt();
+			var val = parseFloat(len);
+			switch(len.slice(-2)){
+				case "px": return val;
+				case "pt": return val * px_in_pt;
+				case "in": return val * 72 * px_in_pt;
+				case "pc": return val * 12 * px_in_pt;
+				case "mm": return val * dojox.gfx.mm_in_pt * px_in_pt;
+				case "cm": return val * dojox.gfx.cm_in_pt * px_in_pt;
+			}
+		}
+		return parseFloat(len);	// Number
+	},
+
+	// a constant used to split a SVG/VML path into primitive components
+	pathVmlRegExp: /([A-Za-z]+)|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,
+	pathSvgRegExp: /([A-Za-z])|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,
+
+	equalSources: function(a, b){
+		// summary: compares event sources, returns true if they are equal
+		return a && b && a == b;
+	}
+});
diff --git a/dojox/gfx/arc.js b/dojox/gfx/arc.js
index 42fc959..30c8cea 100644
--- a/dojox/gfx/arc.js
+++ b/dojox/gfx/arc.js
@@ -1,65 +1,118 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.arc"]){
-dojo._hasResource["dojox.gfx.arc"]=true;
 dojo.provide("dojox.gfx.arc");
+
 dojo.require("dojox.gfx.matrix");
+
 (function(){
-var m=dojox.gfx.matrix,_1=function(_2){
-var _3=Math.cos(_2),_4=Math.sin(_2),p2={x:_3+(4/3)*(1-_3),y:_4-(4/3)*_3*(1-_3)/_4};
-return {s:{x:_3,y:-_4},c1:{x:p2.x,y:-p2.y},c2:p2,e:{x:_3,y:_4}};
-},_5=2*Math.PI,_6=Math.PI/4,_7=Math.PI/8,_8=_6+_7,_9=_1(_7);
-dojo.mixin(dojox.gfx.arc,{unitArcAsBezier:_1,curvePI4:_9,arcAsBezier:function(_a,rx,ry,_b,_c,_d,x,y){
-_c=Boolean(_c);
-_d=Boolean(_d);
-var _e=m._degToRad(_b),_f=rx*rx,ry2=ry*ry,pa=m.multiplyPoint(m.rotate(-_e),{x:(_a.x-x)/2,y:(_a.y-y)/2}),_10=pa.x*pa.x,_11=pa.y*pa.y,c1=Math.sqrt((_f*ry2-_f*_11-ry2*_10)/(_f*_11+ry2*_10));
-if(isNaN(c1)){
-c1=0;
-}
-var ca={x:c1*rx*pa.y/ry,y:-c1*ry*pa.x/rx};
-if(_c==_d){
-ca={x:-ca.x,y:-ca.y};
-}
-var c=m.multiplyPoint([m.translate((_a.x+x)/2,(_a.y+y)/2),m.rotate(_e)],ca);
-var _12=m.normalize([m.translate(c.x,c.y),m.rotate(_e),m.scale(rx,ry)]);
-var _13=m.invert(_12),sp=m.multiplyPoint(_13,_a),ep=m.multiplyPoint(_13,x,y),_14=Math.atan2(sp.y,sp.x),_15=Math.atan2(ep.y,ep.x),_16=_14-_15;
-if(_d){
-_16=-_16;
-}
-if(_16<0){
-_16+=_5;
-}else{
-if(_16>_5){
-_16-=_5;
-}
-}
-var _17=_7,_18=_9,_19=_d?_17:-_17,_1a=[];
-for(var _1b=_16;_1b>0;_1b-=_6){
-if(_1b<_8){
-_17=_1b/2;
-_18=_1(_17);
-_19=_d?_17:-_17;
-_1b=0;
-}
-var c1,c2,e,M=m.normalize([_12,m.rotate(_14+_19)]);
-if(_d){
-c1=m.multiplyPoint(M,_18.c1);
-c2=m.multiplyPoint(M,_18.c2);
-e=m.multiplyPoint(M,_18.e);
-}else{
-c1=m.multiplyPoint(M,_18.c2);
-c2=m.multiplyPoint(M,_18.c1);
-e=m.multiplyPoint(M,_18.s);
-}
-_1a.push([c1.x,c1.y,c2.x,c2.y,e.x,e.y]);
-_14+=2*_19;
-}
-return _1a;
-}});
+	var m = dojox.gfx.matrix,
+		unitArcAsBezier = function(alpha){
+			// summary: return a start point, 1st and 2nd control points, and an end point of
+			//		a an arc, which is reflected on the x axis
+			// alpha: Number: angle in radians, the arc will be 2 * angle size
+			var cosa  = Math.cos(alpha), sina  = Math.sin(alpha),
+				p2 = {x: cosa + (4 / 3) * (1 - cosa), y: sina - (4 / 3) * cosa * (1 - cosa) / sina};
+			return {	// Object
+				s:  {x: cosa, y: -sina},
+				c1: {x: p2.x, y: -p2.y},
+				c2: p2,
+				e:  {x: cosa, y: sina}
+			};
+		},
+		twoPI = 2 * Math.PI, pi4 = Math.PI / 4, pi8 = Math.PI / 8,
+		pi48 = pi4 + pi8, curvePI4 = unitArcAsBezier(pi8);
+
+	dojo.mixin(dojox.gfx.arc, {
+		unitArcAsBezier: unitArcAsBezier,
+		curvePI4: curvePI4,
+		arcAsBezier: function(last, rx, ry, xRotg, large, sweep, x, y){
+			// summary: calculates an arc as a series of Bezier curves
+			//	given the last point and a standard set of SVG arc parameters,
+			//	it returns an array of arrays of parameters to form a series of
+			//	absolute Bezier curves.
+			// last: Object: a point-like object as a start of the arc
+			// rx: Number: a horizontal radius for the virtual ellipse
+			// ry: Number: a vertical radius for the virtual ellipse
+			// xRotg: Number: a rotation of an x axis of the virtual ellipse in degrees
+			// large: Boolean: which part of the ellipse will be used (the larger arc if true)
+			// sweep: Boolean: direction of the arc (CW if true)
+			// x: Number: the x coordinate of the end point of the arc
+			// y: Number: the y coordinate of the end point of the arc
+
+			// calculate parameters
+			large = Boolean(large);
+			sweep = Boolean(sweep);
+			var xRot = m._degToRad(xRotg),
+				rx2 = rx * rx, ry2 = ry * ry,
+				pa = m.multiplyPoint(
+					m.rotate(-xRot),
+					{x: (last.x - x) / 2, y: (last.y - y) / 2}
+				),
+				pax2 = pa.x * pa.x, pay2 = pa.y * pa.y,
+				c1 = Math.sqrt((rx2 * ry2 - rx2 * pay2 - ry2 * pax2) / (rx2 * pay2 + ry2 * pax2));
+			if(isNaN(c1)){ c1 = 0; }
+			var	ca = {
+					x:  c1 * rx * pa.y / ry,
+					y: -c1 * ry * pa.x / rx
+				};
+			if(large == sweep){
+				ca = {x: -ca.x, y: -ca.y};
+			}
+			// the center
+			var c = m.multiplyPoint(
+				[
+					m.translate(
+						(last.x + x) / 2,
+						(last.y + y) / 2
+					),
+					m.rotate(xRot)
+				],
+				ca
+			);
+			// calculate the elliptic transformation
+			var elliptic_transform = m.normalize([
+				m.translate(c.x, c.y),
+				m.rotate(xRot),
+				m.scale(rx, ry)
+			]);
+			// start, end, and size of our arc
+			var inversed = m.invert(elliptic_transform),
+				sp = m.multiplyPoint(inversed, last),
+				ep = m.multiplyPoint(inversed, x, y),
+				startAngle = Math.atan2(sp.y, sp.x),
+				endAngle   = Math.atan2(ep.y, ep.x),
+				theta = startAngle - endAngle;	// size of our arc in radians
+			if(sweep){ theta = -theta; }
+			if(theta < 0){
+				theta += twoPI;
+			}else if(theta > twoPI){
+				theta -= twoPI;
+			}
+
+			// draw curve chunks
+			var alpha = pi8, curve = curvePI4, step  = sweep ? alpha : -alpha,
+				result = [];
+			for(var angle = theta; angle > 0; angle -= pi4){
+				if(angle < pi48){
+					alpha = angle / 2;
+					curve = unitArcAsBezier(alpha);
+					step  = sweep ? alpha : -alpha;
+					angle = 0;	// stop the loop
+				}
+				var c1, c2, e,
+					M = m.normalize([elliptic_transform, m.rotate(startAngle + step)]);
+				if(sweep){
+					c1 = m.multiplyPoint(M, curve.c1);
+					c2 = m.multiplyPoint(M, curve.c2);
+					e  = m.multiplyPoint(M, curve.e );
+				}else{
+					c1 = m.multiplyPoint(M, curve.c2);
+					c2 = m.multiplyPoint(M, curve.c1);
+					e  = m.multiplyPoint(M, curve.s );
+				}
+				// draw the curve
+				result.push([c1.x, c1.y, c2.x, c2.y, e.x, e.y]);
+				startAngle += 2 * step;
+			}
+			return result;	// Array
+		}
+	});
 })();
-}
diff --git a/dojox/gfx/attach.js b/dojox/gfx/attach.js
index b41d64b..901f66f 100644
--- a/dojox/gfx/attach.js
+++ b/dojox/gfx/attach.js
@@ -1,12 +1,7 @@
-/*
-	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
-*/
-
-
 dojo.require("dojox.gfx");
-dojo.requireIf(dojox.gfx.renderer=="svg","dojox.gfx.svg_attach");
-dojo.requireIf(dojox.gfx.renderer=="vml","dojox.gfx.vml_attach");
-dojo.requireIf(dojox.gfx.renderer=="silverlight","dojox.gfx.silverlight_attach");
-dojo.requireIf(dojox.gfx.renderer=="canvas","dojox.gfx.canvas_attach");
+
+// include an attacher conditionally
+dojo.requireIf(dojox.gfx.renderer == "svg", "dojox.gfx.svg_attach");
+dojo.requireIf(dojox.gfx.renderer == "vml", "dojox.gfx.vml_attach");
+dojo.requireIf(dojox.gfx.renderer == "silverlight", "dojox.gfx.silverlight_attach");
+dojo.requireIf(dojox.gfx.renderer == "canvas", "dojox.gfx.canvas_attach");
diff --git a/dojox/gfx/canvas.js b/dojox/gfx/canvas.js
index 2535bff..758605e 100644
--- a/dojox/gfx/canvas.js
+++ b/dojox/gfx/canvas.js
@@ -1,503 +1,695 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.canvas"]){
-dojo._hasResource["dojox.gfx.canvas"]=true;
 dojo.provide("dojox.gfx.canvas");
+
 dojo.require("dojox.gfx._base");
 dojo.require("dojox.gfx.shape");
 dojo.require("dojox.gfx.path");
 dojo.require("dojox.gfx.arc");
 dojo.require("dojox.gfx.decompose");
+
 dojo.experimental("dojox.gfx.canvas");
+
 (function(){
-var d=dojo,g=dojox.gfx,gs=g.shape,ga=g.arc,m=g.matrix,mp=m.multiplyPoint,pi=Math.PI,_1=2*pi,_2=pi/2;
-d.extend(g.Shape,{_render:function(_3){
-_3.save();
-this._renderTransform(_3);
-this._renderShape(_3);
-this._renderFill(_3,true);
-this._renderStroke(_3,true);
-_3.restore();
-},_renderTransform:function(_4){
-if("canvasTransform" in this){
-var t=this.canvasTransform;
-_4.translate(t.dx,t.dy);
-_4.rotate(t.angle2);
-_4.scale(t.sx,t.sy);
-_4.rotate(t.angle1);
-}
-},_renderShape:function(_5){
-},_renderFill:function(_6,_7){
-if("canvasFill" in this){
-if("canvasFillImage" in this){
-this.canvasFill=_6.createPattern(this.canvasFillImage,"repeat");
-delete this.canvasFillImage;
-}
-_6.fillStyle=this.canvasFill;
-if(_7){
-_6.fill();
-}
-}else{
-_6.fillStyle="rgba(0,0,0,0.0)";
-}
-},_renderStroke:function(_8,_9){
-var s=this.strokeStyle;
-if(s){
-_8.strokeStyle=s.color.toString();
-_8.lineWidth=s.width;
-_8.lineCap=s.cap;
-if(typeof s.join=="number"){
-_8.lineJoin="miter";
-_8.miterLimit=s.join;
-}else{
-_8.lineJoin=s.join;
-}
-if(_9){
-_8.stroke();
-}
-}else{
-if(!_9){
-_8.strokeStyle="rgba(0,0,0,0.0)";
-}
-}
-},getEventSource:function(){
-return null;
-},connect:function(){
-},disconnect:function(){
-}});
-var _a=function(_b,_c,_d){
-var _e=_b.prototype[_c];
-_b.prototype[_c]=_d?function(){
-this.surface.makeDirty();
-_e.apply(this,arguments);
-_d.call(this);
-return this;
-}:function(){
-this.surface.makeDirty();
-return _e.apply(this,arguments);
-};
-};
-_a(g.Shape,"setTransform",function(){
-if(this.matrix){
-this.canvasTransform=g.decompose(this.matrix);
-}else{
-delete this.canvasTransform;
-}
-});
-_a(g.Shape,"setFill",function(){
-var fs=this.fillStyle,f;
-if(fs){
-if(typeof (fs)=="object"&&"type" in fs){
-var _f=this.surface.rawNode.getContext("2d");
-switch(fs.type){
-case "linear":
-case "radial":
-f=fs.type=="linear"?_f.createLinearGradient(fs.x1,fs.y1,fs.x2,fs.y2):_f.createRadialGradient(fs.cx,fs.cy,0,fs.cx,fs.cy,fs.r);
-d.forEach(fs.colors,function(_10){
-f.addColorStop(_10.offset,g.normalizeColor(_10.color).toString());
-});
-break;
-case "pattern":
-var img=new Image(fs.width,fs.height);
-this.surface.downloadImage(img,fs.src);
-this.canvasFillImage=img;
-}
-}else{
-f=fs.toString();
-}
-this.canvasFill=f;
-}else{
-delete this.canvasFill;
-}
-});
-_a(g.Shape,"setStroke");
-_a(g.Shape,"setShape");
-dojo.declare("dojox.gfx.Group",g.Shape,{constructor:function(){
-gs.Container._init.call(this);
-},_render:function(ctx){
-ctx.save();
-this._renderTransform(ctx);
-this._renderFill(ctx);
-this._renderStroke(ctx);
-for(var i=0;i<this.children.length;++i){
-this.children[i]._render(ctx);
-}
-ctx.restore();
-}});
-dojo.declare("dojox.gfx.Rect",gs.Rect,{_renderShape:function(ctx){
-var s=this.shape,r=Math.min(s.r,s.height/2,s.width/2),xl=s.x,xr=xl+s.width,yt=s.y,yb=yt+s.height,xl2=xl+r,xr2=xr-r,yt2=yt+r,yb2=yb-r;
-ctx.beginPath();
-ctx.moveTo(xl2,yt);
-if(r){
-ctx.arc(xr2,yt2,r,-_2,0,false);
-ctx.arc(xr2,yb2,r,0,_2,false);
-ctx.arc(xl2,yb2,r,_2,pi,false);
-ctx.arc(xl2,yt2,r,pi,pi+_2,false);
-}else{
-ctx.lineTo(xr2,yt);
-ctx.lineTo(xr,yb2);
-ctx.lineTo(xl2,yb);
-ctx.lineTo(xl,yt2);
-}
-ctx.closePath();
-}});
-var _11=[];
-(function(){
-var u=ga.curvePI4;
-_11.push(u.s,u.c1,u.c2,u.e);
-for(var a=45;a<360;a+=45){
-var r=m.rotateg(a);
-_11.push(mp(r,u.c1),mp(r,u.c2),mp(r,u.e));
-}
-})();
-dojo.declare("dojox.gfx.Ellipse",gs.Ellipse,{setShape:function(){
-g.Ellipse.superclass.setShape.apply(this,arguments);
-var s=this.shape,t,c1,c2,r=[],M=m.normalize([m.translate(s.cx,s.cy),m.scale(s.rx,s.ry)]);
-t=mp(M,_11[0]);
-r.push([t.x,t.y]);
-for(var i=1;i<_11.length;i+=3){
-c1=mp(M,_11[i]);
-c2=mp(M,_11[i+1]);
-t=mp(M,_11[i+2]);
-r.push([c1.x,c1.y,c2.x,c2.y,t.x,t.y]);
-}
-this.canvasEllipse=r;
-return this;
-},_renderShape:function(ctx){
-var r=this.canvasEllipse;
-ctx.beginPath();
-ctx.moveTo.apply(ctx,r[0]);
-for(var i=1;i<r.length;++i){
-ctx.bezierCurveTo.apply(ctx,r[i]);
-}
-ctx.closePath();
-}});
-dojo.declare("dojox.gfx.Circle",gs.Circle,{_renderShape:function(ctx){
-var s=this.shape;
-ctx.beginPath();
-ctx.arc(s.cx,s.cy,s.r,0,_1,1);
-}});
-dojo.declare("dojox.gfx.Line",gs.Line,{_renderShape:function(ctx){
-var s=this.shape;
-ctx.beginPath();
-ctx.moveTo(s.x1,s.y1);
-ctx.lineTo(s.x2,s.y2);
-}});
-dojo.declare("dojox.gfx.Polyline",gs.Polyline,{setShape:function(){
-g.Polyline.superclass.setShape.apply(this,arguments);
-var p=this.shape.points,f=p[0],r=[],c,i;
-if(p.length){
-if(typeof f=="number"){
-r.push(f,p[1]);
-i=2;
-}else{
-r.push(f.x,f.y);
-i=1;
-}
-for(;i<p.length;++i){
-c=p[i];
-if(typeof c=="number"){
-r.push(c,p[++i]);
-}else{
-r.push(c.x,c.y);
-}
-}
-}
-this.canvasPolyline=r;
-return this;
-},_renderShape:function(ctx){
-var p=this.canvasPolyline;
-if(p.length){
-ctx.beginPath();
-ctx.moveTo(p[0],p[1]);
-for(var i=2;i<p.length;i+=2){
-ctx.lineTo(p[i],p[i+1]);
-}
-}
-}});
-dojo.declare("dojox.gfx.Image",gs.Image,{setShape:function(){
-g.Image.superclass.setShape.apply(this,arguments);
-var img=new Image();
-this.surface.downloadImage(img,this.shape.src);
-this.canvasImage=img;
-return this;
-},_renderShape:function(ctx){
-var s=this.shape;
-ctx.drawImage(this.canvasImage,s.x,s.y,s.width,s.height);
-}});
-dojo.declare("dojox.gfx.Text",gs.Text,{_renderShape:function(ctx){
-var s=this.shape;
-}});
-_a(g.Text,"setFont");
-var _12={M:"_moveToA",m:"_moveToR",L:"_lineToA",l:"_lineToR",H:"_hLineToA",h:"_hLineToR",V:"_vLineToA",v:"_vLineToR",C:"_curveToA",c:"_curveToR",S:"_smoothCurveToA",s:"_smoothCurveToR",Q:"_qCurveToA",q:"_qCurveToR",T:"_qSmoothCurveToA",t:"_qSmoothCurveToR",A:"_arcTo",a:"_arcTo",Z:"_closePath",z:"_closePath"};
-dojo.declare("dojox.gfx.Path",g.path.Path,{constructor:function(){
-this.lastControl={};
-},setShape:function(){
-this.canvasPath=[];
-return g.Path.superclass.setShape.apply(this,arguments);
-},_updateWithSegment:function(_13){
-var _14=d.clone(this.last);
-this[_12[_13.action]](this.canvasPath,_13.action,_13.args);
-this.last=_14;
-g.Path.superclass._updateWithSegment.apply(this,arguments);
-},_renderShape:function(ctx){
-var r=this.canvasPath;
-ctx.beginPath();
-for(var i=0;i<r.length;i+=2){
-ctx[r[i]].apply(ctx,r[i+1]);
-}
-},_moveToA:function(_15,_16,_17){
-_15.push("moveTo",[_17[0],_17[1]]);
-for(var i=2;i<_17.length;i+=2){
-_15.push("lineTo",[_17[i],_17[i+1]]);
-}
-this.last.x=_17[_17.length-2];
-this.last.y=_17[_17.length-1];
-this.lastControl={};
-},_moveToR:function(_18,_19,_1a){
-if("x" in this.last){
-_18.push("moveTo",[this.last.x+=_1a[0],this.last.y+=_1a[1]]);
-}else{
-_18.push("moveTo",[this.last.x=_1a[0],this.last.y=_1a[1]]);
-}
-for(var i=2;i<_1a.length;i+=2){
-_18.push("lineTo",[this.last.x+=_1a[i],this.last.y+=_1a[i+1]]);
-}
-this.lastControl={};
-},_lineToA:function(_1b,_1c,_1d){
-for(var i=0;i<_1d.length;i+=2){
-_1b.push("lineTo",[_1d[i],_1d[i+1]]);
-}
-this.last.x=_1d[_1d.length-2];
-this.last.y=_1d[_1d.length-1];
-this.lastControl={};
-},_lineToR:function(_1e,_1f,_20){
-for(var i=0;i<_20.length;i+=2){
-_1e.push("lineTo",[this.last.x+=_20[i],this.last.y+=_20[i+1]]);
-}
-this.lastControl={};
-},_hLineToA:function(_21,_22,_23){
-for(var i=0;i<_23.length;++i){
-_21.push("lineTo",[_23[i],this.last.y]);
-}
-this.last.x=_23[_23.length-1];
-this.lastControl={};
-},_hLineToR:function(_24,_25,_26){
-for(var i=0;i<_26.length;++i){
-_24.push("lineTo",[this.last.x+=_26[i],this.last.y]);
-}
-this.lastControl={};
-},_vLineToA:function(_27,_28,_29){
-for(var i=0;i<_29.length;++i){
-_27.push("lineTo",[this.last.x,_29[i]]);
-}
-this.last.y=_29[_29.length-1];
-this.lastControl={};
-},_vLineToR:function(_2a,_2b,_2c){
-for(var i=0;i<_2c.length;++i){
-_2a.push("lineTo",[this.last.x,this.last.y+=_2c[i]]);
-}
-this.lastControl={};
-},_curveToA:function(_2d,_2e,_2f){
-for(var i=0;i<_2f.length;i+=6){
-_2d.push("bezierCurveTo",_2f.slice(i,i+6));
-}
-this.last.x=_2f[_2f.length-2];
-this.last.y=_2f[_2f.length-1];
-this.lastControl.x=_2f[_2f.length-4];
-this.lastControl.y=_2f[_2f.length-3];
-this.lastControl.type="C";
-},_curveToR:function(_30,_31,_32){
-for(var i=0;i<_32.length;i+=6){
-_30.push("bezierCurveTo",[this.last.x+_32[i],this.last.y+_32[i+1],this.lastControl.x=this.last.x+_32[i+2],this.lastControl.y=this.last.y+_32[i+3],this.last.x+_32[i+4],this.last.y+_32[i+5]]);
-this.last.x+=_32[i+4];
-this.last.y+=_32[i+5];
-}
-this.lastControl.type="C";
-},_smoothCurveToA:function(_33,_34,_35){
-for(var i=0;i<_35.length;i+=4){
-var _36=this.lastControl.type=="C";
-_33.push("bezierCurveTo",[_36?2*this.last.x-this.lastControl.x:this.last.x,_36?2*this.last.y-this.lastControl.y:this.last.y,_35[i],_35[i+1],_35[i+2],_35[i+3]]);
-this.lastControl.x=_35[i];
-this.lastControl.y=_35[i+1];
-this.lastControl.type="C";
-}
-this.last.x=_35[_35.length-2];
-this.last.y=_35[_35.length-1];
-},_smoothCurveToR:function(_37,_38,_39){
-for(var i=0;i<_39.length;i+=4){
-var _3a=this.lastControl.type=="C";
-_37.push("bezierCurveTo",[_3a?2*this.last.x-this.lastControl.x:this.last.x,_3a?2*this.last.y-this.lastControl.y:this.last.y,this.last.x+_39[i],this.last.y+_39[i+1],this.last.x+_39[i+2],this.last.y+_39[i+3]]);
-this.lastControl.x=this.last.x+_39[i];
-this.lastControl.y=this.last.y+_39[i+1];
-this.lastControl.type="C";
-this.last.x+=_39[i+2];
-this.last.y+=_39[i+3];
-}
-},_qCurveToA:function(_3b,_3c,_3d){
-for(var i=0;i<_3d.length;i+=4){
-_3b.push("quadraticCurveTo",_3d.slice(i,i+4));
-}
-this.last.x=_3d[_3d.length-2];
-this.last.y=_3d[_3d.length-1];
-this.lastControl.x=_3d[_3d.length-4];
-this.lastControl.y=_3d[_3d.length-3];
-this.lastControl.type="Q";
-},_qCurveToR:function(_3e,_3f,_40){
-for(var i=0;i<_40.length;i+=4){
-_3e.push("quadraticCurveTo",[this.lastControl.x=this.last.x+_40[i],this.lastControl.y=this.last.y+_40[i+1],this.last.x+_40[i+2],this.last.y+_40[i+3]]);
-this.last.x+=_40[i+2];
-this.last.y+=_40[i+3];
-}
-this.lastControl.type="Q";
-},_qSmoothCurveToA:function(_41,_42,_43){
-for(var i=0;i<_43.length;i+=2){
-var _44=this.lastControl.type=="Q";
-_41.push("quadraticCurveTo",[this.lastControl.x=_44?2*this.last.x-this.lastControl.x:this.last.x,this.lastControl.y=_44?2*this.last.y-this.lastControl.y:this.last.y,_43[i],_43[i+1]]);
-this.lastControl.type="Q";
-}
-this.last.x=_43[_43.length-2];
-this.last.y=_43[_43.length-1];
-},_qSmoothCurveToR:function(_45,_46,_47){
-for(var i=0;i<_47.length;i+=2){
-var _48=this.lastControl.type=="Q";
-_45.push("quadraticCurveTo",[this.lastControl.x=_48?2*this.last.x-this.lastControl.x:this.last.x,this.lastControl.y=_48?2*this.last.y-this.lastControl.y:this.last.y,this.last.x+_47[i],this.last.y+_47[i+1]]);
-this.lastControl.type="Q";
-this.last.x+=_47[i];
-this.last.y+=_47[i+1];
-}
-},_arcTo:function(_49,_4a,_4b){
-var _4c=_4a=="a";
-for(var i=0;i<_4b.length;i+=7){
-var x1=_4b[i+5],y1=_4b[i+6];
-if(_4c){
-x1+=this.last.x;
-y1+=this.last.y;
-}
-var _4d=ga.arcAsBezier(this.last,_4b[i],_4b[i+1],_4b[i+2],_4b[i+3]?1:0,_4b[i+4]?1:0,x1,y1);
-d.forEach(_4d,function(p){
-_49.push("bezierCurveTo",p);
-});
-this.last.x=x1;
-this.last.y=y1;
-}
-this.lastControl={};
-},_closePath:function(_4e,_4f,_50){
-_4e.push("closePath",[]);
-this.lastControl={};
-}});
-d.forEach(["moveTo","lineTo","hLineTo","vLineTo","curveTo","smoothCurveTo","qCurveTo","qSmoothCurveTo","arcTo","closePath"],function(_51){
-_a(g.Path,_51);
-});
-dojo.declare("dojox.gfx.TextPath",g.path.TextPath,{_renderShape:function(ctx){
-var s=this.shape;
-}});
-dojo.declare("dojox.gfx.Surface",gs.Surface,{constructor:function(){
-gs.Container._init.call(this);
-this.pendingImageCount=0;
-this.makeDirty();
-},setDimensions:function(_52,_53){
-this.width=g.normalizedLength(_52);
-this.height=g.normalizedLength(_53);
-if(!this.rawNode){
-return this;
-}
-this.rawNode.width=_52;
-this.rawNode.height=_53;
-this.makeDirty();
-return this;
-},getDimensions:function(){
-return this.rawNode?{width:this.rawNode.width,height:this.rawNode.height}:null;
-},_render:function(){
-if(this.pendingImageCount){
-return;
-}
-var ctx=this.rawNode.getContext("2d");
-ctx.save();
-ctx.clearRect(0,0,this.rawNode.width,this.rawNode.height);
-for(var i=0;i<this.children.length;++i){
-this.children[i]._render(ctx);
-}
-ctx.restore();
-if("pendingRender" in this){
-clearTimeout(this.pendingRender);
-delete this.pendingRender;
-}
-},makeDirty:function(){
-if(!this.pendingImagesCount&&!("pendingRender" in this)){
-this.pendingRender=setTimeout(d.hitch(this,this._render),0);
-}
-},downloadImage:function(img,url){
-var _54=d.hitch(this,this.onImageLoad);
-if(!this.pendingImageCount++&&"pendingRender" in this){
-clearTimeout(this.pendingRender);
-delete this.pendingRender;
-}
-img.onload=_54;
-img.onerror=_54;
-img.onabort=_54;
-img.src=url;
-},onImageLoad:function(){
-if(!--this.pendingImageCount){
-this._render();
-}
-},getEventSource:function(){
-return null;
-},connect:function(){
-},disconnect:function(){
-}});
-g.createSurface=function(_55,_56,_57){
-if(!_56&&!_57){
-var pos=d.position(_55);
-_56=_56||pos.w;
-_57=_57||pos.h;
-}
-if(typeof _56=="number"){
-_56=_56+"px";
-}
-if(typeof _57=="number"){
-_57=_57+"px";
-}
-var s=new g.Surface(),p=d.byId(_55),c=p.ownerDocument.createElement("canvas");
-c.width=dojox.gfx.normalizedLength(_56);
-c.height=dojox.gfx.normalizedLength(_57);
-p.appendChild(c);
-s.rawNode=c;
-s._parent=p;
-s.surface=s;
-return s;
-};
-var C=gs.Container,_58={add:function(_59){
-this.surface.makeDirty();
-return C.add.apply(this,arguments);
-},remove:function(_5a,_5b){
-this.surface.makeDirty();
-return C.remove.apply(this,arguments);
-},clear:function(){
-this.surface.makeDirty();
-return C.clear.apply(this,arguments);
-},_moveChildToFront:function(_5c){
-this.surface.makeDirty();
-return C._moveChildToFront.apply(this,arguments);
-},_moveChildToBack:function(_5d){
-this.surface.makeDirty();
-return C._moveChildToBack.apply(this,arguments);
-}};
-d.mixin(gs.Creator,{createObject:function(_5e,_5f){
-var _60=new _5e();
-_60.surface=this.surface;
-_60.setShape(_5f);
-this.add(_60);
-return _60;
-}});
-d.extend(g.Group,_58);
-d.extend(g.Group,gs.Creator);
-d.extend(g.Surface,_58);
-d.extend(g.Surface,gs.Creator);
+	var d = dojo, g = dojox.gfx, gs = g.shape, ga = g.arc,
+		m = g.matrix, mp = m.multiplyPoint, pi = Math.PI, twoPI = 2 * pi, halfPI = pi /2;
+
+	d.extend(g.Shape, {
+		_render: function(/* Object */ ctx){
+			// summary: render the shape
+			ctx.save();
+			this._renderTransform(ctx);
+			this._renderShape(ctx);
+			this._renderFill(ctx, true);
+			this._renderStroke(ctx, true);
+			ctx.restore();
+		},
+		_renderTransform: function(/* Object */ ctx){
+			if("canvasTransform" in this){
+				var t = this.canvasTransform;
+				ctx.translate(t.dx, t.dy);
+				ctx.rotate(t.angle2);
+				ctx.scale(t.sx, t.sy);
+				ctx.rotate(t.angle1);
+				// The future implementation when vendors catch up with the spec:
+				// var t = this.matrix;
+				// ctx.transform(t.xx, t.yx, t.xy, t.yy, t.dx, t.dy);
+			}
+		},
+		_renderShape: function(/* Object */ ctx){
+			// nothing
+		},
+		_renderFill: function(/* Object */ ctx, /* Boolean */ apply){
+			if("canvasFill" in this){
+				if("canvasFillImage" in this){
+					this.canvasFill = ctx.createPattern(this.canvasFillImage, "repeat");
+					delete this.canvasFillImage;
+				}
+				ctx.fillStyle = this.canvasFill;
+				if(apply){ ctx.fill(); }
+			}else{
+				ctx.fillStyle = "rgba(0,0,0,0.0)";
+			}
+		},
+		_renderStroke: function(/* Object */ ctx, /* Boolean */ apply){
+			var s = this.strokeStyle;
+			if(s){
+				ctx.strokeStyle = s.color.toString();
+				ctx.lineWidth = s.width;
+				ctx.lineCap = s.cap;
+				if(typeof s.join == "number"){
+					ctx.lineJoin = "miter";
+					ctx.miterLimit = s.join;
+				}else{
+					ctx.lineJoin = s.join;
+				}
+				if(apply){ ctx.stroke(); }
+			}else if(!apply){
+				ctx.strokeStyle = "rgba(0,0,0,0.0)";
+			}
+		},
+
+		// events are not implemented
+		getEventSource: function(){ return null; },
+		connect:		function(){},
+		disconnect:		function(){}
+	});
+
+	var modifyMethod = function(shape, method, extra){
+			var old = shape.prototype[method];
+			shape.prototype[method] = extra ?
+				function(){
+					this.surface.makeDirty();
+					old.apply(this, arguments);
+					extra.call(this);
+					return this;
+				} :
+				function(){
+					this.surface.makeDirty();
+					return old.apply(this, arguments);
+				};
+		};
+
+	modifyMethod(g.Shape, "setTransform",
+		function(){
+			// prepare Canvas-specific structures
+			if(this.matrix){
+				this.canvasTransform = g.decompose(this.matrix);
+			}else{
+				delete this.canvasTransform;
+			}
+		});
+
+	modifyMethod(g.Shape, "setFill",
+		function(){
+			// prepare Canvas-specific structures
+			var fs = this.fillStyle, f;
+			if(fs){
+				if(typeof(fs) == "object" && "type" in fs){
+					var ctx = this.surface.rawNode.getContext("2d");
+					switch(fs.type){
+						case "linear":
+						case "radial":
+							f = fs.type == "linear" ?
+								ctx.createLinearGradient(fs.x1, fs.y1, fs.x2, fs.y2) :
+								ctx.createRadialGradient(fs.cx, fs.cy, 0, fs.cx, fs.cy, fs.r);
+							d.forEach(fs.colors, function(step){
+								f.addColorStop(step.offset, g.normalizeColor(step.color).toString());
+							});
+							break;
+						case "pattern":
+							var img = new Image(fs.width, fs.height);
+							this.surface.downloadImage(img, fs.src);
+							this.canvasFillImage = img;
+					}
+				}else{
+					// Set fill color using CSS RGBA func style
+					f = fs.toString();
+				}
+				this.canvasFill = f;
+			}else{
+				delete this.canvasFill;
+			}
+		});
+
+	modifyMethod(g.Shape, "setStroke");
+	modifyMethod(g.Shape, "setShape");
+
+	dojo.declare("dojox.gfx.Group", g.Shape, {
+		// summary: a group shape (Canvas), which can be used
+		//	to logically group shapes (e.g, to propagate matricies)
+		constructor: function(){
+			gs.Container._init.call(this);
+		},
+		_render: function(/* Object */ ctx){
+			// summary: render the group
+			ctx.save();
+			this._renderTransform(ctx);
+			this._renderFill(ctx);
+			this._renderStroke(ctx);
+			for(var i = 0; i < this.children.length; ++i){
+				this.children[i]._render(ctx);
+			}
+			ctx.restore();
+		}
+	});
+
+	dojo.declare("dojox.gfx.Rect", gs.Rect, {
+		// summary: a rectangle shape (Canvas)
+		_renderShape: function(/* Object */ ctx){
+			var s = this.shape, r = Math.min(s.r, s.height / 2, s.width / 2),
+				xl = s.x, xr = xl + s.width, yt = s.y, yb = yt + s.height,
+				xl2 = xl + r, xr2 = xr - r, yt2 = yt + r, yb2 = yb - r;
+			ctx.beginPath();
+			ctx.moveTo(xl2, yt);
+			if(r){
+				ctx.arc(xr2, yt2, r, -halfPI, 0, false);
+				ctx.arc(xr2, yb2, r, 0, halfPI, false);
+				ctx.arc(xl2, yb2, r, halfPI, pi, false);
+				ctx.arc(xl2, yt2, r, pi, pi + halfPI, false);
+			}else{
+				ctx.lineTo(xr2, yt);
+				ctx.lineTo(xr, yb2);
+				ctx.lineTo(xl2, yb);
+				ctx.lineTo(xl, yt2);
+			}
+	 		ctx.closePath();
+		}
+	});
+
+	var bezierCircle = [];
+	(function(){
+		var u = ga.curvePI4;
+		bezierCircle.push(u.s, u.c1, u.c2, u.e);
+		for(var a = 45; a < 360; a += 45){
+			var r = m.rotateg(a);
+			bezierCircle.push(mp(r, u.c1), mp(r, u.c2), mp(r, u.e));
+		}
+	})();
+
+	dojo.declare("dojox.gfx.Ellipse", gs.Ellipse, {
+		// summary: an ellipse shape (Canvas)
+		setShape: function(){
+			g.Ellipse.superclass.setShape.apply(this, arguments);
+			// prepare Canvas-specific structures
+			var s = this.shape, t, c1, c2, r = [],
+				M = m.normalize([m.translate(s.cx, s.cy), m.scale(s.rx, s.ry)]);
+			t = mp(M, bezierCircle[0]);
+			r.push([t.x, t.y]);
+			for(var i = 1; i < bezierCircle.length; i += 3){
+				c1 = mp(M, bezierCircle[i]);
+				c2 = mp(M, bezierCircle[i + 1]);
+				t  = mp(M, bezierCircle[i + 2]);
+				r.push([c1.x, c1.y, c2.x, c2.y, t.x, t.y]);
+			}
+			this.canvasEllipse = r;
+			return this;
+		},
+		_renderShape: function(/* Object */ ctx){
+			var r = this.canvasEllipse;
+			ctx.beginPath();
+			ctx.moveTo.apply(ctx, r[0]);
+			for(var i = 1; i < r.length; ++i){
+				ctx.bezierCurveTo.apply(ctx, r[i]);
+			}
+			ctx.closePath();
+		}
+	});
+
+	dojo.declare("dojox.gfx.Circle", gs.Circle, {
+		// summary: a circle shape (Canvas)
+		_renderShape: function(/* Object */ ctx){
+			var s = this.shape;
+			ctx.beginPath();
+			ctx.arc(s.cx, s.cy, s.r, 0, twoPI, 1);
+		}
+	});
+
+	dojo.declare("dojox.gfx.Line", gs.Line, {
+		// summary: a line shape (Canvas)
+		_renderShape: function(/* Object */ ctx){
+			var s = this.shape;
+			ctx.beginPath();
+			ctx.moveTo(s.x1, s.y1);
+			ctx.lineTo(s.x2, s.y2);
+		}
+	});
+
+	dojo.declare("dojox.gfx.Polyline", gs.Polyline, {
+		// summary: a polyline/polygon shape (Canvas)
+		setShape: function(){
+			g.Polyline.superclass.setShape.apply(this, arguments);
+			// dojo.inherited("setShape", arguments);
+			// prepare Canvas-specific structures
+			var p = this.shape.points, f = p[0], r = [], c, i;
+			if(p.length){
+				if(typeof f == "number"){
+					r.push(f, p[1]);
+					i = 2;
+				}else{
+					r.push(f.x, f.y);
+					i = 1;
+				}
+				for(; i < p.length; ++i){
+					c = p[i];
+					if(typeof c == "number"){
+						r.push(c, p[++i]);
+					}else{
+						r.push(c.x, c.y);
+					}
+				}
+			}
+			this.canvasPolyline = r;
+			return this;
+		},
+		_renderShape: function(/* Object */ ctx){
+			// console.debug("Polyline::_renderShape");
+			var p = this.canvasPolyline;
+			if(p.length){
+				ctx.beginPath();
+				ctx.moveTo(p[0], p[1]);
+				for(var i = 2; i < p.length; i += 2){
+					ctx.lineTo(p[i], p[i + 1]);
+				}
+			}
+		}
+	});
+
+	dojo.declare("dojox.gfx.Image", gs.Image, {
+		// summary: an image shape (Canvas)
+		setShape: function(){
+			g.Image.superclass.setShape.apply(this, arguments);
+			// prepare Canvas-specific structures
+			var img = new Image();
+			this.surface.downloadImage(img, this.shape.src);
+			this.canvasImage = img;
+			return this;
+		},
+		_renderShape: function(/* Object */ ctx){
+			var s = this.shape;
+			ctx.drawImage(this.canvasImage, s.x, s.y, s.width, s.height);
+		}
+	});
+
+	dojo.declare("dojox.gfx.Text", gs.Text, {
+		// summary: a text shape (Canvas)
+		_renderShape: function(/* Object */ ctx){
+			var s = this.shape;
+			// nothing for the moment
+		}
+	});
+	modifyMethod(g.Text, "setFont");
+
+	var pathRenderers = {
+		M: "_moveToA", m: "_moveToR",
+		L: "_lineToA", l: "_lineToR",
+		H: "_hLineToA", h: "_hLineToR",
+		V: "_vLineToA", v: "_vLineToR",
+		C: "_curveToA", c: "_curveToR",
+		S: "_smoothCurveToA", s: "_smoothCurveToR",
+		Q: "_qCurveToA", q: "_qCurveToR",
+		T: "_qSmoothCurveToA", t: "_qSmoothCurveToR",
+		A: "_arcTo", a: "_arcTo",
+		Z: "_closePath", z: "_closePath"
+	};
+
+	dojo.declare("dojox.gfx.Path", g.path.Path, {
+		// summary: a path shape (Canvas)
+		constructor: function(){
+			this.lastControl = {};
+		},
+		setShape: function(){
+			this.canvasPath = [];
+			return g.Path.superclass.setShape.apply(this, arguments);
+		},
+		_updateWithSegment: function(segment){
+			var last = d.clone(this.last);
+			this[pathRenderers[segment.action]](this.canvasPath, segment.action, segment.args);
+			this.last = last;
+			g.Path.superclass._updateWithSegment.apply(this, arguments);
+		},
+		_renderShape: function(/* Object */ ctx){
+			var r = this.canvasPath;
+			ctx.beginPath();
+			for(var i = 0; i < r.length; i += 2){
+				ctx[r[i]].apply(ctx, r[i + 1]);
+			}
+		},
+		_moveToA: function(result, action, args){
+			result.push("moveTo", [args[0], args[1]]);
+			for(var i = 2; i < args.length; i += 2){
+				result.push("lineTo", [args[i], args[i + 1]]);
+			}
+			this.last.x = args[args.length - 2];
+			this.last.y = args[args.length - 1];
+			this.lastControl = {};
+		},
+		_moveToR: function(result, action, args){
+			if("x" in this.last){
+				result.push("moveTo", [this.last.x += args[0], this.last.y += args[1]]);
+			}else{
+				result.push("moveTo", [this.last.x = args[0], this.last.y = args[1]]);
+			}
+			for(var i = 2; i < args.length; i += 2){
+				result.push("lineTo", [this.last.x += args[i], this.last.y += args[i + 1]]);
+			}
+			this.lastControl = {};
+		},
+		_lineToA: function(result, action, args){
+			for(var i = 0; i < args.length; i += 2){
+				result.push("lineTo", [args[i], args[i + 1]]);
+			}
+			this.last.x = args[args.length - 2];
+			this.last.y = args[args.length - 1];
+			this.lastControl = {};
+		},
+		_lineToR: function(result, action, args){
+			for(var i = 0; i < args.length; i += 2){
+				result.push("lineTo", [this.last.x += args[i], this.last.y += args[i + 1]]);
+			}
+			this.lastControl = {};
+		},
+		_hLineToA: function(result, action, args){
+			for(var i = 0; i < args.length; ++i){
+				result.push("lineTo", [args[i], this.last.y]);
+			}
+			this.last.x = args[args.length - 1];
+			this.lastControl = {};
+		},
+		_hLineToR: function(result, action, args){
+			for(var i = 0; i < args.length; ++i){
+				result.push("lineTo", [this.last.x += args[i], this.last.y]);
+			}
+			this.lastControl = {};
+		},
+		_vLineToA: function(result, action, args){
+			for(var i = 0; i < args.length; ++i){
+				result.push("lineTo", [this.last.x, args[i]]);
+			}
+			this.last.y = args[args.length - 1];
+			this.lastControl = {};
+		},
+		_vLineToR: function(result, action, args){
+			for(var i = 0; i < args.length; ++i){
+				result.push("lineTo", [this.last.x, this.last.y += args[i]]);
+			}
+			this.lastControl = {};
+		},
+		_curveToA: function(result, action, args){
+			for(var i = 0; i < args.length; i += 6){
+				result.push("bezierCurveTo", args.slice(i, i + 6));
+			}
+			this.last.x = args[args.length - 2];
+			this.last.y = args[args.length - 1];
+			this.lastControl.x = args[args.length - 4];
+			this.lastControl.y = args[args.length - 3];
+			this.lastControl.type = "C";
+		},
+		_curveToR: function(result, action, args){
+			for(var i = 0; i < args.length; i += 6){
+				result.push("bezierCurveTo", [
+					this.last.x + args[i],
+					this.last.y + args[i + 1],
+					this.lastControl.x = this.last.x + args[i + 2],
+					this.lastControl.y = this.last.y + args[i + 3],
+					this.last.x + args[i + 4],
+					this.last.y + args[i + 5]
+				]);
+				this.last.x += args[i + 4];
+				this.last.y += args[i + 5];
+			}
+			this.lastControl.type = "C";
+		},
+		_smoothCurveToA: function(result, action, args){
+			for(var i = 0; i < args.length; i += 4){
+				var valid = this.lastControl.type == "C";
+				result.push("bezierCurveTo", [
+					valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+					valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+					args[i],
+					args[i + 1],
+					args[i + 2],
+					args[i + 3]
+				]);
+				this.lastControl.x = args[i];
+				this.lastControl.y = args[i + 1];
+				this.lastControl.type = "C";
+			}
+			this.last.x = args[args.length - 2];
+			this.last.y = args[args.length - 1];
+		},
+		_smoothCurveToR: function(result, action, args){
+			for(var i = 0; i < args.length; i += 4){
+				var valid = this.lastControl.type == "C";
+				result.push("bezierCurveTo", [
+					valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+					valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+					this.last.x + args[i],
+					this.last.y + args[i + 1],
+					this.last.x + args[i + 2],
+					this.last.y + args[i + 3]
+				]);
+				this.lastControl.x = this.last.x + args[i];
+				this.lastControl.y = this.last.y + args[i + 1];
+				this.lastControl.type = "C";
+				this.last.x += args[i + 2];
+				this.last.y += args[i + 3];
+			}
+		},
+		_qCurveToA: function(result, action, args){
+			for(var i = 0; i < args.length; i += 4){
+				result.push("quadraticCurveTo", args.slice(i, i + 4));
+			}
+			this.last.x = args[args.length - 2];
+			this.last.y = args[args.length - 1];
+			this.lastControl.x = args[args.length - 4];
+			this.lastControl.y = args[args.length - 3];
+			this.lastControl.type = "Q";
+		},
+		_qCurveToR: function(result, action, args){
+			for(var i = 0; i < args.length; i += 4){
+				result.push("quadraticCurveTo", [
+					this.lastControl.x = this.last.x + args[i],
+					this.lastControl.y = this.last.y + args[i + 1],
+					this.last.x + args[i + 2],
+					this.last.y + args[i + 3]
+				]);
+				this.last.x += args[i + 2];
+				this.last.y += args[i + 3];
+			}
+			this.lastControl.type = "Q";
+		},
+		_qSmoothCurveToA: function(result, action, args){
+			for(var i = 0; i < args.length; i += 2){
+				var valid = this.lastControl.type == "Q";
+				result.push("quadraticCurveTo", [
+					this.lastControl.x = valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+					this.lastControl.y = valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+					args[i],
+					args[i + 1]
+				]);
+				this.lastControl.type = "Q";
+			}
+			this.last.x = args[args.length - 2];
+			this.last.y = args[args.length - 1];
+		},
+		_qSmoothCurveToR: function(result, action, args){
+			for(var i = 0; i < args.length; i += 2){
+				var valid = this.lastControl.type == "Q";
+				result.push("quadraticCurveTo", [
+					this.lastControl.x = valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+					this.lastControl.y = valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+					this.last.x + args[i],
+					this.last.y + args[i + 1]
+				]);
+				this.lastControl.type = "Q";
+				this.last.x += args[i];
+				this.last.y += args[i + 1];
+			}
+		},
+		_arcTo: function(result, action, args){
+			var relative = action == "a";
+			for(var i = 0; i < args.length; i += 7){
+				var x1 = args[i + 5], y1 = args[i + 6];
+				if(relative){
+					x1 += this.last.x;
+					y1 += this.last.y;
+				}
+				var arcs = ga.arcAsBezier(
+					this.last, args[i], args[i + 1], args[i + 2],
+					args[i + 3] ? 1 : 0, args[i + 4] ? 1 : 0,
+					x1, y1
+				);
+				d.forEach(arcs, function(p){
+					result.push("bezierCurveTo", p);
+				});
+				this.last.x = x1;
+				this.last.y = y1;
+			}
+			this.lastControl = {};
+		},
+		_closePath: function(result, action, args){
+			result.push("closePath", []);
+			this.lastControl = {};
+		}
+	});
+	d.forEach(["moveTo", "lineTo", "hLineTo", "vLineTo", "curveTo",
+		"smoothCurveTo", "qCurveTo", "qSmoothCurveTo", "arcTo", "closePath"],
+		function(method){ modifyMethod(g.Path, method); }
+	);
+
+	dojo.declare("dojox.gfx.TextPath", g.path.TextPath, {
+		// summary: a text shape (Canvas)
+		_renderShape: function(/* Object */ ctx){
+			var s = this.shape;
+			// nothing for the moment
+		}
+	});
+
+	dojo.declare("dojox.gfx.Surface", gs.Surface, {
+		// summary: a surface object to be used for drawings (Canvas)
+		constructor: function(){
+			gs.Container._init.call(this);
+			this.pendingImageCount = 0;
+			this.makeDirty();
+		},
+		setDimensions: function(width, height){
+			// summary: sets the width and height of the rawNode
+			// width: String: width of surface, e.g., "100px"
+			// height: String: height of surface, e.g., "100px"
+			this.width  = g.normalizedLength(width);	// in pixels
+			this.height = g.normalizedLength(height);	// in pixels
+			if(!this.rawNode) return this;
+			this.rawNode.width = width;
+			this.rawNode.height = height;
+			this.makeDirty();
+			return this;	// self
+		},
+		getDimensions: function(){
+			// summary: returns an object with properties "width" and "height"
+			return this.rawNode ? {width:  this.rawNode.width, height: this.rawNode.height} : null;	// Object
+		},
+		_render: function(){
+			// summary: render the all shapes
+			if(this.pendingImageCount){ return; }
+			var ctx = this.rawNode.getContext("2d");
+			ctx.save();
+			ctx.clearRect(0, 0, this.rawNode.width, this.rawNode.height);
+			for(var i = 0; i < this.children.length; ++i){
+				this.children[i]._render(ctx);
+			}
+			ctx.restore();
+			if("pendingRender" in this){
+				clearTimeout(this.pendingRender);
+				delete this.pendingRender;
+			}
+		},
+		makeDirty: function(){
+			// summary: internal method, which is called when we may need to redraw
+			if(!this.pendingImagesCount && !("pendingRender" in this)){
+				this.pendingRender = setTimeout(d.hitch(this, this._render), 0);
+			}
+		},
+		downloadImage: function(img, url){
+			// summary:
+			//		internal method, which starts an image download and renders, when it is ready
+			// img: Image:
+			//		the image object
+			// url: String:
+			//		the url of the image
+			var handler = d.hitch(this, this.onImageLoad);
+			if(!this.pendingImageCount++ && "pendingRender" in this){
+				clearTimeout(this.pendingRender);
+				delete this.pendingRender;
+			}
+			img.onload  = handler;
+			img.onerror = handler;
+			img.onabort = handler;
+			img.src = url;
+		},
+		onImageLoad: function(){
+			if(!--this.pendingImageCount){ this._render(); }
+		},
+
+		// events are not implemented
+		getEventSource: function(){ return null; },
+		connect:		function(){},
+		disconnect:		function(){}
+	});
+
+	g.createSurface = function(parentNode, width, height){
+		// summary: creates a surface (Canvas)
+		// parentNode: Node: a parent node
+		// width: String: width of surface, e.g., "100px"
+		// height: String: height of surface, e.g., "100px"
+
+		if(!width && !height){
+			var pos = d.position(parentNode);
+			width  = width  || pos.w;
+			height = height || pos.h;
+		}
+		if(typeof width == "number"){
+			width = width + "px";
+		}
+		if(typeof height == "number"){
+			height = height + "px";
+		}
+
+		var s = new g.Surface(),
+			p = d.byId(parentNode),
+			c = p.ownerDocument.createElement("canvas");
+
+		c.width  = dojox.gfx.normalizedLength(width);	// in pixels
+		c.height = dojox.gfx.normalizedLength(height);	// in pixels
+
+		p.appendChild(c);
+		s.rawNode = c;
+		s._parent = p;
+		s.surface = s;
+		return s;	// dojox.gfx.Surface
+	};
+
+	// Extenders
+
+	var C = gs.Container, Container = {
+		add: function(shape){
+			this.surface.makeDirty();
+			return C.add.apply(this, arguments);
+		},
+		remove: function(shape, silently){
+			this.surface.makeDirty();
+			return C.remove.apply(this, arguments);
+		},
+		clear: function(){
+			this.surface.makeDirty();
+			return C.clear.apply(this, arguments);
+		},
+		_moveChildToFront: function(shape){
+			this.surface.makeDirty();
+			return C._moveChildToFront.apply(this, arguments);
+		},
+		_moveChildToBack: function(shape){
+			this.surface.makeDirty();
+			return C._moveChildToBack.apply(this, arguments);
+		}
+	};
+
+	d.mixin(gs.Creator, {
+		// summary: Canvas shape creators
+		createObject: function(shapeType, rawShape) {
+			// summary: creates an instance of the passed shapeType class
+			// shapeType: Function: a class constructor to create an instance of
+			// rawShape: Object: properties to be passed in to the classes "setShape" method
+			// overrideSize: Boolean: set the size explicitly, if true
+			var shape = new shapeType();
+			shape.surface = this.surface;
+			shape.setShape(rawShape);
+			this.add(shape);
+			return shape;	// dojox.gfx.Shape
+		}
+	});
+
+	d.extend(g.Group, Container);
+	d.extend(g.Group, gs.Creator);
+
+	d.extend(g.Surface, Container);
+	d.extend(g.Surface, gs.Creator);
 })();
-}
diff --git a/dojox/gfx/canvas_attach.js b/dojox/gfx/canvas_attach.js
index 8862ba3..82ccd13 100644
--- a/dojox/gfx/canvas_attach.js
+++ b/dojox/gfx/canvas_attach.js
@@ -1,12 +1,8 @@
-/*
-	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
-*/
-
-
 dojo.require("dojox.gfx.canvas");
+
 dojo.experimental("dojox.gfx.canvas_attach");
-dojox.gfx.attachNode=function(){
-return null;
+
+// not implemented
+dojox.gfx.attachNode = function(){
+	return null;	// for now
 };
diff --git a/dojox/gfx/decompose.js b/dojox/gfx/decompose.js
index fcdb844..997c60d 100644
--- a/dojox/gfx/decompose.js
+++ b/dojox/gfx/decompose.js
@@ -1,106 +1,135 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.decompose"]){
-dojo._hasResource["dojox.gfx.decompose"]=true;
 dojo.provide("dojox.gfx.decompose");
+
 dojo.require("dojox.gfx.matrix");
+
 (function(){
-var m=dojox.gfx.matrix;
-var eq=function(a,b){
-return Math.abs(a-b)<=0.000001*(Math.abs(a)+Math.abs(b));
-};
-var _1=function(r1,m1,r2,m2){
-if(!isFinite(r1)){
-return r2;
-}else{
-if(!isFinite(r2)){
-return r1;
-}
-}
-m1=Math.abs(m1),m2=Math.abs(m2);
-return (m1*r1+m2*r2)/(m1+m2);
-};
-var _2=function(_3){
-var M=new m.Matrix2D(_3);
-return dojo.mixin(M,{dx:0,dy:0,xy:M.yx,yx:M.xy});
-};
-var _4=function(_5){
-return (_5.xx*_5.yy<0||_5.xy*_5.yx>0)?-1:1;
-};
-var _6=function(_7){
-var M=m.normalize(_7),b=-M.xx-M.yy,c=M.xx*M.yy-M.xy*M.yx,d=Math.sqrt(b*b-4*c),l1=-(b+(b<0?-d:d))/2,l2=c/l1,_8=M.xy/(l1-M.xx),_9=1,_a=M.xy/(l2-M.xx),_b=1;
-if(eq(l1,l2)){
-_8=1,_9=0,_a=0,_b=1;
-}
-if(!isFinite(_8)){
-_8=1,_9=(l1-M.xx)/M.xy;
-if(!isFinite(_9)){
-_8=(l1-M.yy)/M.yx,_9=1;
-if(!isFinite(_8)){
-_8=1,_9=M.yx/(l1-M.yy);
-}
-}
-}
-if(!isFinite(_a)){
-_a=1,_b=(l2-M.xx)/M.xy;
-if(!isFinite(_b)){
-_a=(l2-M.yy)/M.yx,_b=1;
-if(!isFinite(_a)){
-_a=1,_b=M.yx/(l2-M.yy);
-}
-}
-}
-var d1=Math.sqrt(_8*_8+_9*_9),d2=Math.sqrt(_a*_a+_b*_b);
-if(!isFinite(_8/=d1)){
-_8=0;
-}
-if(!isFinite(_9/=d1)){
-_9=0;
-}
-if(!isFinite(_a/=d2)){
-_a=0;
-}
-if(!isFinite(_b/=d2)){
-_b=0;
-}
-return {value1:l1,value2:l2,vector1:{x:_8,y:_9},vector2:{x:_a,y:_b}};
-};
-var _c=function(M,_d){
-var _e=_4(M),a=_d.angle1=(Math.atan2(M.yx,M.yy)+Math.atan2(-_e*M.xy,_e*M.xx))/2,_f=Math.cos(a),sin=Math.sin(a);
-_d.sx=_1(M.xx/_f,_f,-M.xy/sin,sin);
-_d.sy=_1(M.yy/_f,_f,M.yx/sin,sin);
-return _d;
-};
-var _10=function(M,_11){
-var _12=_4(M),a=_11.angle2=(Math.atan2(_12*M.yx,_12*M.xx)+Math.atan2(-M.xy,M.yy))/2,cos=Math.cos(a),sin=Math.sin(a);
-_11.sx=_1(M.xx/cos,cos,M.yx/sin,sin);
-_11.sy=_1(M.yy/cos,cos,-M.xy/sin,sin);
-return _11;
-};
-dojox.gfx.decompose=function(_13){
-var M=m.normalize(_13),_14={dx:M.dx,dy:M.dy,sx:1,sy:1,angle1:0,angle2:0};
-if(eq(M.xy,0)&&eq(M.yx,0)){
-return dojo.mixin(_14,{sx:M.xx,sy:M.yy});
-}
-if(eq(M.xx*M.yx,-M.xy*M.yy)){
-return _c(M,_14);
-}
-if(eq(M.xx*M.xy,-M.yx*M.yy)){
-return _10(M,_14);
-}
-var MT=_2(M),u=_6([M,MT]),v=_6([MT,M]),U=new m.Matrix2D({xx:u.vector1.x,xy:u.vector2.x,yx:u.vector1.y,yy:u.vector2.y}),VT=new m.Matrix2D({xx:v.vector1.x,xy:v.vector1.y,yx:v.vector2.x,yy:v.vector2.y}),S=new m.Matrix2D([m.invert(U),M,m.invert(VT)]);
-_c(VT,_14);
-S.xx*=_14.sx;
-S.yy*=_14.sy;
-_10(U,_14);
-S.xx*=_14.sx;
-S.yy*=_14.sy;
-return dojo.mixin(_14,{sx:S.xx,sy:S.yy});
-};
+	var m = dojox.gfx.matrix;
+
+	var eq = function(/* Number */ a, /* Number */ b){
+		// summary: compare two FP numbers for equality
+		return Math.abs(a - b) <= 1e-6 * (Math.abs(a) + Math.abs(b));	// Boolean
+	};
+
+	var calcFromValues = function(/* Number */ r1, /* Number */ m1, /* Number */ r2, /* Number */ m2){
+		// summary: uses two close FP ration and their original magnitudes to approximate the result
+		if(!isFinite(r1)){
+			return r2;	// Number
+		}else if(!isFinite(r2)){
+			return r1;	// Number
+		}
+		m1 = Math.abs(m1), m2 = Math.abs(m2);
+		return (m1 * r1 + m2 * r2) / (m1 + m2);	// Number
+	};
+
+	var transpose = function(/* dojox.gfx.matrix.Matrix2D */ matrix){
+		// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object
+		var M = new m.Matrix2D(matrix);
+		return dojo.mixin(M, {dx: 0, dy: 0, xy: M.yx, yx: M.xy});	// dojox.gfx.matrix.Matrix2D
+	};
+
+	var scaleSign = function(/* dojox.gfx.matrix.Matrix2D */ matrix){
+		return (matrix.xx * matrix.yy < 0 || matrix.xy * matrix.yx > 0) ? -1 : 1;	// Number
+	};
+
+	var eigenvalueDecomposition = function(/* dojox.gfx.matrix.Matrix2D */ matrix){
+		// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object
+		var M = m.normalize(matrix),
+			b = -M.xx - M.yy,
+			c = M.xx * M.yy - M.xy * M.yx,
+			d = Math.sqrt(b * b - 4 * c),
+			l1 = -(b + (b < 0 ? -d : d)) / 2,
+			l2 = c / l1,
+			vx1 = M.xy / (l1 - M.xx), vy1 = 1,
+			vx2 = M.xy / (l2 - M.xx), vy2 = 1;
+		if(eq(l1, l2)){
+			vx1 = 1, vy1 = 0, vx2 = 0, vy2 = 1;
+		}
+		if(!isFinite(vx1)){
+			vx1 = 1, vy1 = (l1 - M.xx) / M.xy;
+			if(!isFinite(vy1)){
+				vx1 = (l1 - M.yy) / M.yx, vy1 = 1;
+				if(!isFinite(vx1)){
+					vx1 = 1, vy1 = M.yx / (l1 - M.yy);
+				}
+			}
+		}
+		if(!isFinite(vx2)){
+			vx2 = 1, vy2 = (l2 - M.xx) / M.xy;
+			if(!isFinite(vy2)){
+				vx2 = (l2 - M.yy) / M.yx, vy2 = 1;
+				if(!isFinite(vx2)){
+					vx2 = 1, vy2 = M.yx / (l2 - M.yy);
+				}
+			}
+		}
+		var d1 = Math.sqrt(vx1 * vx1 + vy1 * vy1),
+			d2 = Math.sqrt(vx2 * vx2 + vy2 * vy2);
+		if(!isFinite(vx1 /= d1)){ vx1 = 0; }
+		if(!isFinite(vy1 /= d1)){ vy1 = 0; }
+		if(!isFinite(vx2 /= d2)){ vx2 = 0; }
+		if(!isFinite(vy2 /= d2)){ vy2 = 0; }
+		return {	// Object
+			value1: l1,
+			value2: l2,
+			vector1: {x: vx1, y: vy1},
+			vector2: {x: vx2, y: vy2}
+		};
+	};
+
+	var decomposeSR = function(/* dojox.gfx.matrix.Matrix2D */ M, /* Object */ result){
+		// summary: decomposes a matrix into [scale, rotate]; no checks are done.
+		var sign = scaleSign(M),
+			a = result.angle1 = (Math.atan2(M.yx, M.yy) + Math.atan2(-sign * M.xy, sign * M.xx)) / 2,
+			cos = Math.cos(a), sin = Math.sin(a);
+		result.sx = calcFromValues(M.xx / cos, cos, -M.xy / sin, sin);
+		result.sy = calcFromValues(M.yy / cos, cos,  M.yx / sin, sin);
+		return result;	// Object
+	};
+
+	var decomposeRS = function(/* dojox.gfx.matrix.Matrix2D */ M, /* Object */ result){
+		// summary: decomposes a matrix into [rotate, scale]; no checks are done
+		var sign = scaleSign(M),
+			a = result.angle2 = (Math.atan2(sign * M.yx, sign * M.xx) + Math.atan2(-M.xy, M.yy)) / 2,
+			cos = Math.cos(a), sin = Math.sin(a);
+		result.sx = calcFromValues(M.xx / cos, cos,  M.yx / sin, sin);
+		result.sy = calcFromValues(M.yy / cos, cos, -M.xy / sin, sin);
+		return result;	// Object
+	};
+
+	dojox.gfx.decompose = function(matrix){
+		// summary: decompose a 2D matrix into translation, scaling, and rotation components
+		// description: this function decompose a matrix into four logical components:
+		//	translation, rotation, scaling, and one more rotation using SVD.
+		//	The components should be applied in following order:
+		//	| [translate, rotate(angle2), scale, rotate(angle1)]
+		// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object
+		var M = m.normalize(matrix),
+			result = {dx: M.dx, dy: M.dy, sx: 1, sy: 1, angle1: 0, angle2: 0};
+		// detect case: [scale]
+		if(eq(M.xy, 0) && eq(M.yx, 0)){
+			return dojo.mixin(result, {sx: M.xx, sy: M.yy});	// Object
+		}
+		// detect case: [scale, rotate]
+		if(eq(M.xx * M.yx, -M.xy * M.yy)){
+			return decomposeSR(M, result);	// Object
+		}
+		// detect case: [rotate, scale]
+		if(eq(M.xx * M.xy, -M.yx * M.yy)){
+			return decomposeRS(M, result);	// Object
+		}
+		// do SVD
+		var	MT = transpose(M),
+			u  = eigenvalueDecomposition([M, MT]),
+			v  = eigenvalueDecomposition([MT, M]),
+			U  = new m.Matrix2D({xx: u.vector1.x, xy: u.vector2.x, yx: u.vector1.y, yy: u.vector2.y}),
+			VT = new m.Matrix2D({xx: v.vector1.x, xy: v.vector1.y, yx: v.vector2.x, yy: v.vector2.y}),
+			S = new m.Matrix2D([m.invert(U), M, m.invert(VT)]);
+		decomposeSR(VT, result);
+		S.xx *= result.sx;
+		S.yy *= result.sy;
+		decomposeRS(U, result);
+		S.xx *= result.sx;
+		S.yy *= result.sy;
+		return dojo.mixin(result, {sx: S.xx, sy: S.yy});	// Object
+	};
 })();
-}
diff --git a/dojox/gfx/demos/PI.html b/dojox/gfx/demos/PI.html
new file mode 100644
index 0000000..6e87214
--- /dev/null
+++ b/dojox/gfx/demos/PI.html
@@ -0,0 +1,75 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Pi calculation</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var iterations = 0, inCounter = 0, totalCounter = 0,
+	interval, surface;
+
+var compute = function(){
+	var x = Math.random();
+	var y = Math.random();
+	var pointX = Math.round(x * 300);
+	var pointY = Math.round(y * 300);
+
+	var pointColor = "red";
+	if(x*x + y*y < 1){
+		inCounter++;
+		pointColor = "green";
+	}
+	
+	surface.createCircle({cx: pointX, cy: pointY, r: 3}).
+		setFill(pointColor).setStroke({color: pointColor, width: 2});
+
+	totalCounter++;
+	
+	if(totalCounter % 100 == 0 || totalCounter == iterations){
+		var PI = parseFloat(inCounter / totalCounter) * 4;
+		var error = (PI - Math.PI) / Math.PI * 100;	// in %
+		dojo.byId("result").innerHTML = PI + " (error = " + error.toFixed(2) + 
+			"%) after " + totalCounter + " points";
+	}
+
+	if(totalCounter == iterations){
+		clearInterval(interval);
+		dojo.byId("startButton").disabled = false;
+	}
+};
+
+var go = function(){
+	dojo.byId("startButton").disabled = true;
+	dojo.byId("result").innerHTML = " ";
+	inCounter = totalCounter = 0;
+	iterations = parseInt(0 + parseInt(dojo.byId("iterations").value), 10);
+	interval = setInterval(compute, 20);
+};
+
+var init = function(){
+	surface = dojox.gfx.createSurface("test", 300, 300);
+	dojo.connect(dojo.byId("startButton"), "onclick", this, go);
+};
+
+dojo.addOnLoad(init);
+
+</script>
+</head>
+<body>
+<h1>PI demo</h1>
+<p>Visualization of calculating PI using the Monte Carlo method.</p>
+<p>
+<label>Iterations:</label> <input type="text" name="iterations" value="500" id="iterations"/>
+<input type="button" name="start" value="start" id="startButton" />
+</p>
+<p><span style="color:green">Green</span>: x^2 + y^2 <= 1, <span style="color:red">Red</span>: x^2 + y^2 > 1</p>
+<p>Estimated value for PI: <span id="result" style="font-weight: bold"></span></p>
+<div id="test" style="width: 300px; height: 300px;border:1px solid black"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/demos/beautify.html b/dojox/gfx/demos/beautify.html
new file mode 100644
index 0000000..d1f02f5
--- /dev/null
+++ b/dojox/gfx/demos/beautify.html
@@ -0,0 +1,48 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Beautify JSON</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+trimPath = function(o){
+	if(o instanceof Array){
+		for(var i = 0; i < o.length; ++i){
+			trimPath(o[i]);
+		}
+		return;
+	}
+	if(("shape" in o) && ("path" in o.shape)){
+		o.shape.path = dojo.trim(o.shape.path.replace(/\s\s+/g, " "));
+	}
+	if("children" in o){
+		trimPath(o.children);
+	}
+};
+
+beautify = function(){
+	var t = dojo.byId("io");
+	var v = dojo.fromJson(t.value);
+	if(dojo.byId("path").checked){
+		trimPath(v);
+	}
+	t.value = dojo.toJson(v, dojo.byId("pprint").checked);
+};
+
+</script>
+</head>
+<body>
+	<h1>Beautify JSON</h1>
+	<p>Paste valid JSON in this textarea and receive a pretty-printed version of it. Use Firefox, if you want to be able to read comma-ended sequences (Python style).
+	Additionally it knows how to remove extra spaces from path elements.</p>
+	<p><textarea id="io" cols="80" rows="10" wrap="off"></textarea></p>
+	<p><button onclick="beautify()">Beautify!</button>
+	   <input type="checkbox" id="path" checked="checked" /> Process "path" elements
+	   <input type="checkbox" id="pprint" checked="checked" /> Pretty-print JSON</p>
+	<p><em>This program is a companion for inspector.html.</em></p>
+</body>
+</html>
diff --git a/dojox/gfx/demos/butterfly.html b/dojox/gfx/demos/butterfly.html
new file mode 100644
index 0000000..a54a4c5
--- /dev/null
+++ b/dojox/gfx/demos/butterfly.html
@@ -0,0 +1,87 @@
+<html>
+<head>
+<title>dojox.gfx: Butterfly</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+<script type="text/javascript">
+
+dojo.require("dijit.form.HorizontalSlider");
+dojo.require("dijit.form.HorizontalRule");
+dojo.require("dijit.form.HorizontalRuleLabels");
+
+dojo.require("dojo.parser"); // scan page for widgets
+
+dojo.require("dojox.gfx");
+
+var rotation = 0, scaling = 1;
+var surface, g, m = dojox.gfx.matrix;
+var initial_matrix = m.translate(140, 180);
+
+var updateMatrix = function(){
+	if(g){ g.setTransform([m.rotategAt(rotation, 350, 350), m.scaleAt(scaling, 350, 350), initial_matrix]); }
+};
+
+var rotatingEvent = function(value){
+	rotation = value;
+	dojo.byId("rotationValue").innerHTML = rotation;
+	updateMatrix();
+};
+
+var scalingEvent = function(value){
+	scaling = Math.exp(Math.LN10 * (value - 1));
+	dojo.byId("scaleValue").innerHTML = scaling.toFixed(3);
+	updateMatrix();
+};
+
+var makeShapes = function(){
+	surface = dojox.gfx.createSurface(dojo.byId("gfx_holder"), 700, 700);
+	surface.createRect({x: 0, y: 0, width: 700, height: 700}).setFill("#eee");
+	g = surface.createGroup().setTransform(initial_matrix);
+    g.createPath("M204.33 139.83 C196.33 133.33 206.68 132.82 206.58 132.58 C192.33 97.08 169.35 81.41 167.58 80.58 C162.12 78.02 159.48 78.26 160.45 76.97 C161.41 75.68 167.72 79.72 168.58 80.33 C193.83 98.33 207.58 132.33 207.58 132.33 C207.58 132.33 209.33 133.33 209.58 132.58 C219.58 103.08 239.58 87.58 246.33 81.33 C253.08 75.08 256.63 74.47 247.33 81.58 C218.58 103.58 210.34 132.23 210.83 132.33 C222.33 134.83 211.33 140.33 211.83 139.83 C214.85 136.81 214.83 145.83 214.83 145.83 C [...]
+    g.createPath("M203.62 139.62 C195.62 133.12 205.96 132.6 205.87 132.37 C191.62 96.87 168.64 81.2 166.87 80.37 C161.41 77.81 158.77 78.05 159.73 76.76 C160.69 75.47 167.01 79.51 167.87 80.12 C193.12 98.12 206.87 132.12 206.87 132.12 C206.87 132.12 208.62 133.12 208.87 132.37 C218.87 102.87 238.87 87.37 245.62 81.12 C252.37 74.87 255.92 74.26 246.62 81.37 C217.87 103.37 209.63 132.01 210.12 132.12 C221.62 134.62 210.62 140.12 211.12 139.62 C214.14 136.6 214.12 145.62 214.12 145.62 C214 [...]
+    g.createPath("M363.73 85.73 C359.27 86.29 355.23 86.73 354.23 81.23 C353.23 75.73 355.73 73.73 363.23 75.73 C370.73 77.73 375.73 84.23 363.73 85.73 zM327.23 89.23 C327.23 89.23 308.51 93.65 325.73 80.73 C333.73 74.73 334.23 79.73 334.73 82.73 C335.48 87.2 327.23 89.23 327.23 89.23 zM384.23 48.73 C375.88 47.06 376.23 42.23 385.23 40.23 C386.7 39.91 389.23 49.73 384.23 48.73 zM389.23 48.73 C391.73 48.23 395.73 49.23 396.23 52.73 C396.73 56.23 392.73 58.23 390.23 56.23 C387.73 54.23 386 [...]
+	//surface.createLine({x1: 0, y1: 350, x2: 700, y2: 350}).setStroke("green");
+	//surface.createLine({y1: 0, x1: 350, y2: 700, x2: 350}).setStroke("green");
+    dojo.connect(dijit.byId("rotatingSlider"), "onChange", rotatingEvent);
+    dojo.connect(dijit.byId("scalingSlider"), "onChange", scalingEvent);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+<style type="text/css">
+	td.pad { padding: 0px 5px 0px 5px; }
+</style>
+</head>
+<body class="tundra">
+	<h1>dojox.gfx: Butterfly</h1>
+	<p>This example was directly converted from SVG file.</p>
+	<p>This is a slightly modified version of a sample that shipped with JASC's WebDraw (www.jasc.com). Generated by Jasc WebDraw PR4(tm) on 06/07/01 12:18:39.</p>
+	<table>
+		<tr><td align="center" class="pad">Rotation (<span id="rotationValue">0</span>)</td></tr>
+		<tr><td>
+			<div id="rotatingSlider" dojoType="dijit.form.HorizontalSlider" 
+					value="0" minimum="-180" maximum="180" discreteValues="72" showButtons="false" intermediateChanges="true"
+					style="width: 600px;">
+				<div dojoType="dijit.form.HorizontalRule" container="topDecoration" count="73" style="height:5px;"></div>
+				<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="9" style="height:5px;"></div>
+				<div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" labels="-180,-135,-90,-45,0,45,90,135,180" style="height:1.2em;font-size:75%;color:gray;"></div>
+			</div>
+		</td></tr>
+		<tr><td align="center" class="pad">Scaling (<span id="scaleValue">1.000</span>)</td></tr>
+		<tr><td>
+			<div id="scalingSlider" dojoType="dijit.form.HorizontalSlider"  intermediateChanges="true"
+					value="1" minimum="0" maximum="1"  showButtons="false" style="width: 600px;">
+				<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="5" style="height:5px;"></div>
+				<div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" labels="10%,18%,32%,56%,100%" style="height:1.2em;font-size:75%;color:gray;"></div>
+			</div>
+		</td></tr>
+	</table>
+	<div id="gfx_holder" style="width: 700px; height: 700px;"></div>
+</body>
+</html>
diff --git a/dojox/gfx/demos/career_test.html b/dojox/gfx/demos/career_test.html
new file mode 100644
index 0000000..5b31ea1
--- /dev/null
+++ b/dojox/gfx/demos/career_test.html
@@ -0,0 +1,463 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
+<head>
+<title>dojox.gfx: Career Aptitude Test</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+
+<!--
+<script type="text/javascript" src="../Mover.js"></script>
+<script type="text/javascript" src="../Moveable.js"></script>
+<script type="text/javascript" src="../move.js"></script>
+<script type="text/javascript" src="../fx.js"></script>
+<script type="text/javascript" src="../shape.js"></script>
+-->
+
+<script type="text/javascript">
+
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.move");
+dojo.require("dojox.gfx.fx");
+dojo.require("dojo.colors");
+dojo.require("dojo.fx");
+
+var g = dojox.gfx, m = g.matrix;
+
+var container, surface, surface_size,
+	vat, freezer, broiler, score, startTime, endTime;
+
+var totalItems = 10, goodItems = 0, badItems = 0;
+
+var radius = 30,		// pixels
+	slowRate = 10,		// speed in ms per pixel
+	fastRate = 2,		// speed in ms per pixel
+	freezeTime = 5000,	// ms
+	frostTime = 2000,	// ms
+	broilTime = 5000,	// ms
+	burnTime = 2000,	// ms
+	pulseTime = 200;	// ms
+	
+function getRand(from, to){
+	return Math.random() * (to - from) + from;
+}
+
+function inRect(rect, crd){
+	return	rect.x <= crd.x && crd.x < rect.x + rect.width &&
+			rect.y <= crd.y && crd.y < rect.y + rect.height;
+}
+
+function getCenter(circle){
+	var shape = circle.getShape(), matrix = circle.getTransform();
+	return m.multiplyPoint(matrix ? matrix : m.identity, shape.cx, shape.cy);
+}
+
+function getDuration(x1, y1, x2, y2, rate){
+	return Math.floor(Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) * rate);
+}
+
+function updateScore(){
+	var shape = score.getShape();
+	endTime = (new Date()).getTime();
+	shape.text = goodItems + " item" + (goodItems != 1 ? "s" : "") + 
+		" in " + ((endTime - startTime) / 1000) + "s"
+	score.setShape(shape);
+	
+	if(goodItems + badItems != totalItems){ return; }
+	
+	var rating = goodItems / (endTime - startTime) * 60000 * (40 - radius) / 10;
+	dojo.byId("result_pass").style.display = badItems || rating < 5 ? "none" : "";
+	dojo.byId("result_dollar").innerHTML = rating.toFixed(2);
+	dojo.byId("result_but").style.display = badItems ? "" : "none";
+	dojo.byId("result_waste").innerHTML = (badItems * 5).toFixed(2);
+	dojo.byId("result_and").style.display = badItems ? "none" : "";
+	dojo.byId("result_fail").style.display = badItems ? "" : "none";
+	if(!badItems){
+		var pos;
+		if(rating < 1){
+			pos = "Junior Speciment Flipper";
+		}else if(rating < 2){
+			pos = "Senior Speciment Flipper";
+		}else if(rating < 4){
+			pos = "Shift Supervisor";
+		}else if(rating < 6){
+			pos = "Joint Manager";
+		}else if(rating < 8){
+			pos = "Night Director";
+		}else if(rating < 10){
+			pos = "Morning Director";
+		}else if(rating < 12){
+			pos = "Vice President";
+		}else if(rating < 14){
+			pos = "Senior Vice President";
+		}else if(rating < 16){
+			pos = "Chief of Something";
+		}else{
+			pos = "Nominal President";
+		}
+		dojo.byId("result_pos").innerHTML = pos;
+	}
+	var anim1 = dojo.fx.wipeOut({
+			node: "gfx_holder",
+			duration: 500,
+			delay: 1000
+		}),
+		anim2 = dojo.fx.wipeIn({
+			node: "result",
+			duration: 500,
+			delay: 1000
+		});
+	anim1.play();
+	anim2.play();
+}
+
+function showStatus(circle, text){
+	var c = getCenter(circle),
+		status = surface.createText({});
+	status.moveToBack().setFill(new dojo.Color([0, 0, 0, 0.5]))
+		.setFont({family: "serif", variant: "small-caps", weight: "bold"})
+		.setShape({x: c.x, y: c.y, text: text, align: "middle"});
+	var anim = dojo.fx.combine([
+		g.fx.animateFill({
+			shape:		status,
+			duration:	3000,
+			color:		{end: "transparent"}
+		}),
+		g.fx.animateTransform({
+			shape:		status,
+			duration:	3000,
+			transform:	[
+				{name: "translate", start: [0, 0], end: [0, 300]},
+				{name: "original"}
+			]
+		})
+	]);
+	dojo.connect(anim, "onEnd", function(){ status.removeShape(); });
+	anim.play();
+}
+
+function moveToPile(shape, bad){
+	if(shape.moveable){
+		shape.moveable.destroy();
+		delete shape.moveable;
+	}
+	
+	var oldColor = shape.getFill(), c = getCenter(shape),
+		newX = 80 + (bad ? badItems++ : goodItems++) * 2.25 * 10,
+		newY = bad ? 445 : 415,
+		duration = getDuration(newX, newY, c.x, c.y, fastRate),
+		anim = dojo.fx.chain([
+			g.fx.animateFill({
+				shape: shape,
+				duration: 250,
+				color: {end: "transparent"}
+			}),
+			g.fx.animateTransform({
+				shape: shape,
+				duration: duration,
+				transform:	[
+					{name: "translate", start: [0, 0], end: [newX - c.x, newY - c.y]},
+					{name: "original"}
+				]
+			}),
+			g.fx.animateFill({
+				shape: shape,
+				duration: 250,
+				color: {end: oldColor}
+			}),
+			g.fx.animateTransform({
+				shape: shape,
+				duration: duration,
+				transform:	[
+					{name: "scaleAt", start: [1, newX, newY], end: [10 / radius, newX, newY]},
+					{name: "original"}
+				]
+			})
+		]);
+	dojo.connect(anim, "onEnd", updateScore);
+	anim.play();
+}
+
+function repeatMove(){
+	var rect = vat.getShape(), c = getCenter(this),
+		x = getRand(rect.x + radius, rect.x + rect.width - radius),
+		y = getRand(rect.y + radius, rect.y + rect.height - radius),
+		duration = getDuration(x, y, c.x, c.y, slowRate);
+	this.anim = g.fx.animateTransform({
+		duration:	duration,
+		shape: 		this,
+		transform:	[
+			{name: "translate", start: [0, 0], end: [x - c.x, y - c.y]},
+			{name: "original"}
+		]
+	});
+	dojo.connect(this.anim, "onEnd", this, repeatMove);
+	this.anim.play();
+}
+
+function repeatFrost(){
+	this.status = "frozen";
+	this.setStroke({color: "orange", width: 3});
+	showStatus(this, "Ready");
+	this.anim = g.fx.animateFill({
+		duration:	frostTime,
+		shape:		this,
+		color:		{end: "white"}
+	});
+	// calculate a shift
+	var dx = getRand(-radius, radius) / 2, dy = getRand(-radius, radius) / 2, sign = 1;
+	this.applyLeftTransform({dx: -dx / 2, dy: -dy / 2});
+	dojo.connect(this.anim, "onAnimate", this, function(){
+		this.applyLeftTransform({dx: sign * dx, dy: sign * dy});
+		sign = -sign;
+	});
+	dojo.connect(this.anim, "onEnd", this, function(){
+		showStatus(this, "Frozen");
+		moveToPile(this, true);
+	});
+	this.anim.play();
+}
+
+function repeatFreeze(){
+	this.status = "freezing";
+	this.setStroke({color: "black", width: 3});
+	this.anim = g.fx.animateFill({
+		duration:	freezeTime,
+		shape:		this,
+		color:		{end: "blue"}
+	});
+	// calculate a shift
+	var dx = getRand(-radius, radius) / 2, dy = getRand(-radius, radius) / 2, sign = 1;
+	this.applyLeftTransform({dx: -dx / 2, dy: -dy / 2});
+	dojo.connect(this.anim, "onAnimate", this, function(){
+		this.applyLeftTransform({dx: sign * dx, dy: sign * dy});
+		sign = -sign;
+	});
+	dojo.connect(this.anim, "onEnd", this, repeatFrost);
+	this.anim.play();
+}
+
+function repeatBurn(){
+	this.status = "burnt";
+	this.setStroke({color: "orange", width: 3});
+	showStatus(this, "Done");
+	var anim1 = g.fx.animateFill({
+		duration:	burnTime,
+		shape:		this,
+		color:		{end: "black"}
+	});
+	var anim2 = new dojo.Animation({
+		duration:	freezeTime,
+		curve:		[0, freezeTime]
+	});
+	var matrix = this.getTransform(), c = getCenter(this);
+	dojo.connect(anim2, "onAnimate", this, function(val){
+		var scale = (val % pulseTime) / pulseTime / 4 + 1;
+		this.setTransform([m.scaleAt(scale, c), matrix]);
+	});
+	this.anim = dojo.fx.combine([anim1, anim2]);
+	dojo.connect(this.anim, "onEnd", this, function(){
+		showStatus(this, "Burnt");
+		moveToPile(this, true);
+	});
+	this.anim.play();
+}
+
+function repeatBroil(){
+	this.status = "broiling";
+	this.setStroke({color: "black", width: 3});
+	var anim1 = g.fx.animateFill({
+		duration:	broilTime,
+		shape:		this,
+		color:		{end: "red"}
+	});
+	var anim2 = new dojo.Animation({
+		duration:	freezeTime,
+		curve:		[0, freezeTime]
+	});
+	var matrix = this.getTransform(), c = getCenter(this);
+	dojo.connect(anim2, "onAnimate", this, function(val){
+		var scale = (val % pulseTime) / pulseTime / 4 + 1;
+		this.setTransform([m.scaleAt(scale, c), matrix]);
+	});
+	this.anim = dojo.fx.combine([anim1, anim2]);
+	dojo.connect(this.anim, "onEnd", this, repeatBurn);
+	this.anim.play();
+}
+
+function drag(mover){
+	var shape = mover.shape;
+	shape.anim.stop();
+	shape.anim = null;
+}
+
+function drop(mover){
+	var c = getCenter(mover.shape);
+	do{	// break block
+		if(inRect(vat.getShape(), c)){
+			if(mover.shape.status == "fresh"){
+				repeatMove.call(mover.shape);
+				return;
+			}
+			break;
+		}
+		if(inRect(freezer.getShape(), c)){
+			if(mover.shape.status == "fresh"){
+				repeatFreeze.call(mover.shape);
+				return;
+			}
+			break;
+		}
+		if(inRect(broiler.getShape(), c)){
+			if(mover.shape.status == "frozen"){
+				repeatBroil.call(mover.shape);
+				return;
+			}
+			break;
+		}
+		if(mover.shape.status == "burnt"){
+			moveToPile(mover.shape, false);	// good
+			return;
+		}
+	}while(false);
+	moveToPile(mover.shape, true);	// bad
+}
+
+function makePatties(n){
+	var rect = vat.getShape();
+	for(var i = 0; i < n; ++i){
+		var cx = getRand(rect.x + radius, rect.x + rect.width - radius),
+			cy = getRand(rect.y + radius, rect.y + rect.height - radius),
+			patty = surface.createCircle({
+				cx: cx, cy: cy, r: radius
+			}).setFill("green").setStroke({
+				color: "black",
+				width: 3
+			});
+		patty.status = "fresh";
+		patty.moveable = new g.Moveable(patty);
+		repeatMove.call(patty);
+	}
+}
+
+function initGfx(){
+	container = dojo.byId("gfx_holder");
+	surface = g.createSurface(container, 500, 500);
+	surface_size = {width: 500, height: 500};
+	
+	vat = surface.createRect({x: 10, y: 210, width: 480, height: 180})
+		.setStroke({color: "black", width: 7, join: "round"});
+	surface.createText({x: 15, y: 230, text: "Ye Olde Vat v3.2"})
+		.setFill("black");
+			
+	freezer = surface.createRect({x: 10, y: 10, width: 230, height: 180})
+		.setStroke({color: "blue", width: 7, join: "round"});
+	surface.createText({x: 15, y: 30, text: "Deep Freeze 7000"})
+		.setFill("blue");
+			
+	broiler = surface.createRect({x: 260, y: 10, width: 230, height: 180})
+		.setStroke({color: "red", width: 7, join: "round"});
+	surface.createText({x: 265, y: 30, text: "Hellfire Broiler A4"})
+		.setFill("red");
+			
+	surface.createText({x: 15, y: 420, text: "Good:"})
+		.setFont({weight: "bold"}).setFill("green");
+	surface.createText({x: 15, y: 450, text: "Bad:"})
+		.setFont({weight: "bold"}).setFill("red");
+	surface.createText({x: 15, y: 480, text: "Total:"})
+		.setFont({weight: "bold"}).setFill("black");
+	score = surface.createText({x: 80, y: 485, text: "0"})
+		.setFont({weight: "bold", size: "24pt"}).setFill("black");
+	surface.createText({x: 120, y: 460, text: "DROP HERE!"})
+		.setFont({size: "50px"})
+		.setFill(new dojo.Color([0, 0, 0, 0.1])).moveToBack();
+
+	dojo.subscribe("/gfx/move/start", drag);
+	dojo.subscribe("/gfx/move/stop",  drop);
+	makePatties(totalItems);
+	
+	startTime = (new Date()).getTime();
+
+	// cancel text selection and text dragging
+	dojo.connect(container, "ondragstart",   dojo, "stopEvent");
+	dojo.connect(container, "onselectstart", dojo, "stopEvent");
+}
+
+//dojo.addOnLoad(initGfx);
+
+function startTest(level){
+	radius = level;
+	var anim = dojo.fx.wipeOut({
+		node: "explanation",
+		duration: 500
+	});
+	dojo.connect(anim, "onEnd", function(){
+		dojo.byId("gfx_holder").style.display = "";
+		initGfx();
+	});
+	anim.play();
+}
+
+</script>
+
+<style type="text/css">
+.movable { cursor: pointer; }
+</style>
+
+</head>
+<body>
+<h1>dojox.gfx: Career Aptitude Test</h1>
+<p>Warning: Canvas renderer doesn't implement event handling.</p>
+
+<div id="explanation">
+<p>Thank you for your interest in <em>"I can't believe it's manure" Eateries™</em> 
+and for submitting your resume for our review. While this is an automated response, 
+please be assured that every resume is reviewed by us, and forwarded to the hiring
+managers if the skills fit our needs.</p>
+<p>In order order to evaluate your skills we ask you to take a career aptitude test. 
+You will have an exciting chance to operate one of our state-of-the-art workstations 
+remotely. Don't forget:
+</p>
+<ol>
+	<li>Fish out a live speciment of <em>dung-42</em> from the container.</li>
+	<li>Freeze it until you see an orange glow to kill the elements and make it less green.</li>
+	<li>Broil it until you see the orange glow again, and drop it on the table below.</li>
+	<li>You have to process all items without wasting resources and in minimal time.</li>
+</ol>
+<p>Warnings: don't overfreeze, don't overheat, don't drop the speciment, don't change the sequence, 
+don't touch the speciment in heating and freezing chambers until it is's ready.</p>
+<p>Use your head and your mouse!</p>
+<p>Please select the desired position:</p>
+<table>
+	<tr>
+		<td>Workstation Supervisor </td>
+		<td><button onclick="startTest(30);">Apply</button></td>
+	</tr>
+	<tr>
+		<td>Shift Director </td>
+		<td><button onclick="startTest(20);">Apply</button></td>
+	</tr>
+	<tr>
+		<td>Vice President #49653 </td>
+		<td><button onclick="startTest(10);">Apply</button></td>
+	</tr>
+</table>
+</div>
+
+<div id="gfx_holder" style="width: 500px; height: 500px; display: none;"></div>
+
+<div id="result" style="display: none;">
+<p id="result_pass"><strong>Impressive! Please contact us immediately.</strong></p>
+<p>You have made $<span id="result_dollar"></span> per minute for us.
+<span id="result_but">But you wasted $<span id="result_waste"></span> in materials.</span>
+<span id="result_and">It qualifies you to be a <em id="result_pos"></em>.</span>
+</p>
+<p id="result_fail">Should our hiring managers have an interest in your skills and
+capabilities, they will contact you directly. In addition, we will keep
+your resume on file for one year.</p>
+</div>
+
+</body>
+</html>
diff --git a/dojox/gfx/demos/circles.html b/dojox/gfx/demos/circles.html
new file mode 100644
index 0000000..0f59dd8
--- /dev/null
+++ b/dojox/gfx/demos/circles.html
@@ -0,0 +1,83 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
+<head>
+<title>dojox.gfx: 100 draggable circles</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.move");
+
+var container = null,
+	surface = null,
+	surface_size = null;
+
+function getRand(from, to){
+	return Math.random() * (to - from) + from;
+}
+
+var skew_stat_factor = 15;
+
+function getRandSkewed(from, to){
+	// let skew stats to smaller values
+	var seed = 0;
+	for(var i = 0; i < skew_stat_factor; ++i){
+		seed += Math.random();
+	}
+	seed = 2 * Math.abs(seed / skew_stat_factor - 0.5);
+	return seed * (to - from) + from;
+}
+
+function randColor(alpha){
+	var red   = Math.floor(getRand(0, 255)),
+		green = Math.floor(getRand(0, 255)),
+		blue  = Math.floor(getRand(0, 255)),
+		opacity = alpha ? getRand(0.1, 1) : 1;
+	return [red, green, blue, opacity];
+}
+
+function makeCircleGrid(itemCount){
+	var minR = 10, maxR = surface_size.width / 3;
+	for(var j = 0; j < itemCount; ++j){
+		var r = getRandSkewed(minR, maxR),
+			cx = getRand(r, surface_size.width  - r),
+			cy = getRand(r, surface_size.height - r),
+			shape = surface.createCircle({cx: cx, cy: cy, r: r})
+				.setFill(randColor(true))
+				.setStroke({color: randColor(true), width: getRand(0, 3)})
+				;
+		new dojox.gfx.Moveable(shape);
+	}
+}
+
+function initGfx(){
+	container = dojo.byId("gfx_holder");
+	surface = dojox.gfx.createSurface(container, 500, 500);
+	surface_size = {width: 500, height: 500};
+
+	makeCircleGrid(100);
+
+	// cancel text selection and text dragging
+	dojo.connect(container, "ondragstart",   dojo, "stopEvent");
+	dojo.connect(container, "onselectstart", dojo, "stopEvent");
+}
+
+dojo.addOnLoad(initGfx);
+
+</script>
+
+<style type="text/css">
+.movable { cursor: pointer; }
+</style>
+
+</head>
+<body>
+<h1>dojox.gfx: 100 draggable circles</h1>
+<p>Warning: Canvas renderer doesn't implement event handling.</p>
+<div id="gfx_holder" style="width: 500px; height: 500px;"></div>
+</body>
+</html>
diff --git a/dojox/gfx/demos/circles2.html b/dojox/gfx/demos/circles2.html
new file mode 100644
index 0000000..67afacb
--- /dev/null
+++ b/dojox/gfx/demos/circles2.html
@@ -0,0 +1,69 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
+<head>
+<title>dojox.gfx: 2 draggable circles</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.move");
+
+var container = null,
+	surface = null,
+	surface_size = null;
+
+function makeCircles(){
+	// our geometry
+	var x1 = 100, y1 = 100, x2 = 400, y2 = 400, r = 50;
+	
+	// our shapes
+	var line = surface.createLine({x1: x1, y1: y1, x2: x2, y2: y2}).setStroke("red"),
+		circle1 = surface.createCircle({cx: x1, cy: y1, r: r}).setStroke("red").setFill("white"),
+		circle2 = surface.createCircle({cx: x2, cy: y2, r: r}).setStroke("red").setFill("white");
+	
+	// circle movers
+	var m1 = new dojox.gfx.Moveable(circle1),
+		m2 = new dojox.gfx.Moveable(circle2);
+		
+	// custom event processing
+	dojo.connect(m1, "onMoved", function(mover, shift){
+		var o = line.getShape();
+		line.setShape({x1: o.x1 + shift.dx, y1: o.y1 + shift.dy, x2: o.x2, y2: o.y2});
+	});
+	dojo.connect(m2, "onMoved", function(mover, shift){
+		var o = line.getShape();
+		line.setShape({x1: o.x1, y1: o.y1, x2: o.x2 + shift.dx, y2: o.y2 + shift.dy});
+	});
+}
+
+function initGfx(){
+	container = dojo.byId("gfx_holder");
+	surface = dojox.gfx.createSurface(container, 500, 500);
+	surface_size = {width: 500, height: 500};
+
+	makeCircles();
+
+	// cancel text selection and text dragging
+	dojo.connect(container, "ondragstart",   dojo, "stopEvent");
+	dojo.connect(container, "onselectstart", dojo, "stopEvent");
+}
+
+dojo.addOnLoad(initGfx);
+
+</script>
+
+<style type="text/css">
+.movable { cursor: pointer; }
+</style>
+
+</head>
+<body>
+<h1>dojox.gfx: 2 draggable circles</h1>
+<p>Warning: Canvas renderer doesn't implement event handling.</p>
+<div id="gfx_holder" style="width: 500px; height: 500px;"></div>
+</body>
+</html>
diff --git a/dojox/gfx/demos/clock.html b/dojox/gfx/demos/clock.html
new file mode 100644
index 0000000..fcd6ccb
--- /dev/null
+++ b/dojox/gfx/demos/clock.html
@@ -0,0 +1,249 @@
+<html>
+<head>
+<title>dojox.gfx: interactive analog clock</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx");
+dojo.require("dojo.date.locale");
+
+var current_time = new Date();
+
+var hour_hand   = null;
+var minute_hand = null;
+var second_hand = null;
+
+var hour_shadow   = null;
+var minute_shadow = null;
+var second_shadow = null;
+
+var center = {x: 385 / 2, y: 385 / 2};
+
+var hour_shadow_shift   = {dx: 2, dy: 2};
+var minute_shadow_shift = {dx: 3, dy: 3};
+var second_shadow_shift = {dx: 4, dy: 4};
+
+var selected_hand = null;
+var container = null;
+var container_position = null;
+var text_time = null;
+var diff_time = new Date();
+
+placeHand = function(shape, angle, shift){
+	var move = {dx: center.x + (shift ? shift.dx : 0), dy: center.y + (shift ? shift.dy : 0)};
+	return shape.setTransform([move, dojox.gfx.matrix.rotateg(angle)]);
+};
+
+placeHourHand = function(h, m, s){
+	var angle = 30 * (h % 12 + m / 60 + s / 3600);
+	placeHand(hour_hand, angle);
+	placeHand(hour_shadow, angle, hour_shadow_shift);
+};
+
+placeMinuteHand = function(m, s){
+	var angle = 6 * (m + s / 60);
+	placeHand(minute_hand, angle);
+	placeHand(minute_shadow, angle, minute_shadow_shift);
+};
+
+placeSecondHand = function(s){
+	var angle = 6 * s;
+	placeHand(second_hand, angle);
+	placeHand(second_shadow, angle, second_shadow_shift);
+};
+
+reflectTime = function(time, hold_second_hand, hold_minute_hand, hold_hour_hand){
+	if(!time) time = current_time;
+	var h = time.getHours();
+	var m = time.getMinutes();
+	var s = time.getSeconds();
+	if(!hold_hour_hand) placeHourHand(h, m, s);
+	if(!hold_minute_hand) placeMinuteHand(m, s);
+	if(!hold_second_hand) placeSecondHand(s);
+	text_time.innerHTML = dojo.date.locale.format(
+		time, {selector: "time", timePattern: "h:mm:ss a"});
+};
+
+resetTime = function(){
+	current_time = new Date();
+	reflectTime();
+};
+
+tick = function(){
+	current_time.setSeconds(current_time.getSeconds() + 1);
+	reflectTime();
+};
+
+advanceTime = function(){
+	if(!selected_hand) {
+		tick();
+	}
+};
+
+normalizeAngle = function(angle){
+	if(angle > Math.PI) {
+		angle -= 2 * Math.PI;
+	} else if(angle < -Math.PI) {
+		angle += 2 * Math.PI;
+	}
+	return angle;
+};
+
+calculateAngle = function(x, y, handAngle){
+	try {
+		return normalizeAngle(Math.atan2(y - center.y, x - center.x) - handAngle);
+	} catch(e) {
+		// supress
+	}
+	return 0;
+};
+
+getSecondAngle = function(time){
+	if(!time) time = current_time;
+	return (6 * time.getSeconds() - 90) / 180 * Math.PI;
+};
+
+getMinuteAngle = function(time){
+	if(!time) time = current_time;
+	return (6 * (time.getMinutes() + time.getSeconds() / 60) - 90) / 180 * Math.PI;
+};
+
+getHourAngle = function(time){
+	if(!time) time = current_time;
+	return (30 * (time.getHours() + (time.getMinutes() + time.getSeconds() / 60) / 60) - 90) / 180 * Math.PI;
+};
+
+onMouseDown = function(evt){
+	selected_hand = evt.target;
+	diff_time.setTime(current_time.getTime());
+	dojo.stopEvent(evt);
+};
+
+onMouseMove = function(evt){
+	if(!selected_hand) return;
+	if(evt.target == second_hand.getEventSource() || 
+			evt.target == minute_hand.getEventSource() || 
+			evt.target == hour_hand.getEventSource()){
+		dojo.stopEvent(evt);
+		return;
+	}
+	if(dojox.gfx.equalSources(selected_hand, second_hand.getEventSource())){
+		var angle = calculateAngle(
+			evt.clientX - container_position.x, 
+			evt.clientY - container_position.y, 
+			normalizeAngle(getSecondAngle())
+		);
+		var diff = Math.round(angle / Math.PI * 180 / 6); // in whole seconds
+		current_time.setSeconds(current_time.getSeconds() + Math.round(diff));
+		reflectTime();
+	}else if(dojox.gfx.equalSources(selected_hand, minute_hand.getEventSource())){
+		var angle = calculateAngle(
+			evt.clientX - container_position.x, 
+			evt.clientY - container_position.y, 
+			normalizeAngle(getMinuteAngle(diff_time))
+		);
+		var diff = Math.round(angle / Math.PI * 180 / 6 * 60); // in whole seconds
+		diff_time.setTime(diff_time.getTime() + 1000 * diff);
+		reflectTime(diff_time, true);
+		
+	}else if(dojox.gfx.equalSources(selected_hand, hour_hand.getEventSource())){
+		var angle = calculateAngle(
+			evt.clientX - container_position.x, 
+			evt.clientY - container_position.y, 
+			normalizeAngle(getHourAngle(diff_time))
+		);
+		var diff = Math.round(angle / Math.PI * 180 / 30 * 60 * 60); // in whole seconds
+		diff_time.setTime(diff_time.getTime() + 1000 * diff);
+		reflectTime(diff_time, true, true);
+	}else{
+		return;
+	}
+	dojo.stopEvent(evt);
+};
+
+onMouseUp = function(evt){
+	if(selected_hand && !dojox.gfx.equalSources(selected_hand, second_hand.getEventSource())){
+		current_time.setTime(diff_time.getTime());
+		reflectTime();
+	}
+	selected_hand = null;
+	dojo.stopEvent(evt);
+};
+
+makeShapes = function(){
+	// prerequisites
+	container = dojo.byId("gfx_holder");
+	container_position = dojo.coords(container, true);
+	text_time = dojo.byId("time");
+	var surface = dojox.gfx.createSurface(container, 385, 385);
+    surface.createImage({width: 385, height: 385, src: "images/clock_face.jpg"});
+    
+    // hand shapes
+    var hour_hand_points = [{x: -7, y: 15}, {x: 7, y: 15}, {x: 0, y: -60}, {x: -7, y: 15}];
+    var minute_hand_points = [{x: -5, y: 15}, {x: 5, y: 15}, {x: 0, y: -100}, {x: -5, y: 15}];
+    var second_hand_points = [{x: -2, y: 15}, {x: 2, y: 15}, {x: 2, y: -105}, {x: 6, y: -105}, {x: 0, y: -116}, {x: -6, y: -105}, {x: -2, y: -105}, {x: -2, y: 15}];
+    
+    // create shapes
+    hour_shadow = surface.createPolyline(hour_hand_points)
+		.setFill([0, 0, 0, 0.1])
+		;
+    hour_hand = surface.createPolyline(hour_hand_points)
+		.setStroke({color: "black", width: 2})
+		.setFill("#889")
+		;
+    minute_shadow = surface.createPolyline(minute_hand_points)
+		.setFill([0, 0, 0, 0.1])
+		;
+    minute_hand = surface.createPolyline(minute_hand_points)
+		.setStroke({color: "black", width: 2})
+		.setFill("#ccd")
+		;
+    second_shadow = surface.createPolyline(second_hand_points)
+		.setFill([0, 0, 0, 0.1])
+		;
+    second_hand = surface.createPolyline(second_hand_points)
+		.setStroke({color: "#800", width: 1})
+		.setFill("#d00")
+		;
+
+	// next 3 lines kill Silverlight because its nodes do not support CSS		
+	//dojox.gfx._addClass(hour_hand  .getEventSource(), "movable");
+	//dojox.gfx._addClass(minute_hand.getEventSource(), "movable");
+	//dojox.gfx._addClass(second_hand.getEventSource(), "movable");
+		
+	surface.createCircle({r: 1}).setFill("black").setTransform({dx: 192.5, dy: 192.5});
+	
+	// attach events
+	hour_hand  .connect("onmousedown", onMouseDown);
+	minute_hand.connect("onmousedown", onMouseDown);
+	second_hand.connect("onmousedown", onMouseDown);
+	dojo.connect(container, "onmousemove", onMouseMove);
+	dojo.connect(container, "onmouseup",   onMouseUp);
+	dojo.connect(dojo.byId("reset"), "onclick", resetTime);
+
+	// start the clock		
+	resetTime();
+	window.setInterval(advanceTime, 1000);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+<style type="text/css">
+.movable { cursor: hand; }
+</style>
+</head>
+<body>
+<h1>dojox.gfx: interactive analog clock</h1>
+<p>Grab hands and set your own time.</p>
+<p>Warning: Canvas renderer doesn't implement event handling.</p>
+<div id="gfx_holder" style="width: 385px; height: 385px;"></div>
+<p>Current time: <span id="time"></span>.</p>
+<p><button id="reset">Reset</button></p>
+</body>
+</html>
diff --git a/dojox/gfx/demos/clockWidget.html b/dojox/gfx/demos/clockWidget.html
new file mode 100644
index 0000000..6912c93
--- /dev/null
+++ b/dojox/gfx/demos/clockWidget.html
@@ -0,0 +1,328 @@
+<html>
+<head>
+<title>dojox.gfx: interactive analog clock</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/themes/dijit.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad:true"></script>
+<script type="text/javascript">
+	dojo.require("dijit._Widget");
+	dojo.require("dijit._Templated");
+	dojo.require("dojox.gfx");
+	dojo.require("dojo.date.locale");
+	dojo.declare("demo.Clock",dijit._Widget,{
+		
+		time:"",
+		
+		img:"images/clock_face_black.jpg",
+		
+		postCreate:function(){
+			this.inherited(arguments);
+			if(!this.time){ this.current_time = new Date(); }else{
+				this.current_time = this.time;
+			}
+			dojo.mixin(this,{
+				
+				diff_time: new Date(),
+				
+				hour_hand:null,
+				hour_shadow:null,
+				hour_shadow_shift:{dx: 2, dy: 2},
+
+				minute_hand:null,
+				minute_shadow:null,
+				minute_shadow_shift:{dx: 3, dy: 3},
+				
+				second_hand:null,
+				second_shadow:null,
+				second_shadow_shift:{dx: 4, dy: 4},
+				
+				container_position: null
+				
+			});
+
+			this._setSize();
+
+			this._init();
+		},
+		
+		_setSize:function(){
+
+			this.container_position = dojo.coords(this.domNode, true);
+			this.mb = dojo.marginBox(this.domNode);
+			this.center = {
+				x: (this.mb.w / 2),
+				y: (this.mb.h / 2)
+			};
+			
+		},
+		
+		_init:function(){
+			
+			this.surface = dojox.gfx.createSurface(this.domNode, this.mb.w, this.mb.h);
+			this.group = this.surface.createGroup();
+			this.group.createImage({
+				width: this.center.x * 2,
+				height:this.center.y * 2,
+				src: this.img
+			});
+			
+			// hand shapes
+			var _off = 15;
+			var mar = ((this.mb.w / 2) - _off) * -1;
+			var _c = mar * 0.7; // -105; 
+			var _a = mar * 0.5; //-60;
+			var _b = mar * 0.75; // -100;
+			var _d = mar * 0.8; // -116;
+			var _e = mar * 0.0523; // -7ish
+			var _f = mar * 0.042;
+			var _g = mar * 0.01234;
+			
+			var hour_hand_points = [{x: _e, y: _off }, {x: _e * -1, y: _off }, {x: 0, y: _a }, {x: _e, y: _off }];
+			var minute_hand_points = [{x: _f, y: _off }, {x: _f * -1, y: _off }, {x: 0, y: _b }, {x: _f, y: _off }];
+			var second_hand_points = [
+				{x: _g, y: _off }, {x: _g * -1, y: _off }, {x: _g * -1, y: _c },
+				{x: _e * -1, y: _c }, {x: 0, y: _d }, {x: _e, y: _c },
+				{x: _g, y: _c }, {x: _g, y: _off }
+			];
+			
+			// create shapes
+			this.hour_shadow = this.group.createPolyline(hour_hand_points)
+				.setFill([0, 0, 0, 0.1])
+				;
+			this.hour_hand = this.group.createPolyline(hour_hand_points)
+				.setStroke({color: "black", width: 2})
+				.setFill("#889")
+				;
+			this.minute_shadow = this.group.createPolyline(minute_hand_points)
+				.setFill([0, 0, 0, 0.1])
+				;
+			this.minute_hand = this.group.createPolyline(minute_hand_points)
+				.setStroke({color: "black", width: 2})
+				.setFill("#ccd")
+				;
+			this.second_shadow = this.group.createPolyline(second_hand_points)
+				.setFill([0, 0, 0, 0.1])
+				;
+			this.second_hand = this.group.createPolyline(second_hand_points)
+				.setStroke({color: "#800", width: 1})
+				.setFill("#d00")
+				;
+						
+			this.group.createCircle({r: 1}).setFill("black").setTransform({dx: this.center.x, dy: this.center.y });
+			
+			// start the clock		
+			this.resetTime();
+		
+			window.setInterval(dojo.hitch(this,"advanceTime"), 1000);
+		},
+		
+		placeHand: function(shape, angle, shift){
+			var move = {dx: this.center.x + (shift ? shift.dx : 0), dy: this.center.y + (shift ? shift.dy : 0)};
+			return shape.setTransform([move, dojox.gfx.matrix.rotateg(angle)]);
+		},
+		
+		placeHourHand: function(h, m, s){
+			var angle = 30 * (h % 12 + m / 60 + s / 3600);
+			this.placeHand(this.hour_hand, angle);
+			this.placeHand(this.hour_shadow, angle, this.hour_shadow_shift);
+		},
+		
+		placeMinuteHand: function(m, s){
+			var angle = 6 * (m + s / 60);
+			this.placeHand(this.minute_hand, angle);
+			this.placeHand(this.minute_shadow, angle, this.minute_shadow_shift);
+		},
+		
+		placeSecondHand:function(s){
+			var angle = 6 * s;
+			this.placeHand(this.second_hand, angle);
+			this.placeHand(this.second_shadow, angle, this.second_shadow_shift);
+		},
+		
+		reflectTime: function(time, hold_second_hand, hold_minute_hand, hold_hour_hand){
+			if(!time){ time = this.current_time; }
+			var h = time.getHours();
+			var m = time.getMinutes();
+			var s = time.getSeconds();
+
+			if(!hold_hour_hand) this.placeHourHand(h, m, s);
+			if(!hold_minute_hand) this.placeMinuteHand(m, s);
+			if(!hold_second_hand) this.placeSecondHand(s);
+
+			this.text_time = dojo.date.locale.format(
+				time, {selector: "time", timePattern: "h:mm:ss a"}
+			);
+		},
+		
+		resetTime: function(){
+			this.current_time = new Date();
+			this.reflectTime();
+		},
+		
+		tick: function(){
+			this.current_time.setSeconds(this.current_time.getSeconds()+1);
+			this.reflectTime();
+		},
+		
+		advanceTime: function(){
+			if(!this.selected_hand){
+				this.tick();
+			}
+		},
+
+		normalizeAngle: function(angle){
+			if(angle > Math.PI) {
+				angle -= 2 * Math.PI;
+			} else if(angle < -Math.PI) {
+				angle += 2 * Math.PI;
+			}
+			return angle;
+		},
+	
+		calculateAngle: function(x, y, handAngle){
+			try {
+				return this.normalizeAngle(Math.atan2(y - this.center.y, x - this.center.x) - handAngle);
+			}catch(e){ /* supress */ }
+			return 0;
+		},
+	
+		getSecondAngle: function(time){
+			if(!time) time = this.current_time;
+			return (6 * time.getSeconds() - 90) / 180 * Math.PI;
+		},
+	
+		getMinuteAngle: function(time){
+			if(!time) time = this.current_time;
+			return (6 * (time.getMinutes() + time.getSeconds() / 60) - 90) / 180 * Math.PI;
+		},
+	
+		getHourAngle: function(time){
+			if(!time) time = this.current_time;
+			return (30 * (time.getHours() + (time.getMinutes() + time.getSeconds() / 60) / 60) - 90) / 180 * Math.PI;
+		},
+		
+		resize: function(size){
+			this.surface.setDimensions(size.w, size.h);
+			this.group.setTransform(dojox.gfx.matrix.scale(size.w/this.mb.w, size.h/this.mb.h));
+			this._setSize();
+		}
+	
+	});
+	
+	dojo.declare("demo.InteractiveClock",demo.Clock,{
+	 
+		_init: function(){
+			this.inherited(arguments);
+			// attach events
+			this.diff_time = new Date();
+			this.hour_hand  .connect("onmousedown", this,"onMouseDown");
+			this.minute_hand.connect("onmousedown", this,"onMouseDown");
+			this.second_hand.connect("onmousedown", this,"onMouseDown");
+			this.connect(this.domNode, "onmousemove", "onMouseMove");
+			this.connect(this.domNode, "onmouseup", "onMouseUp");
+			
+		},
+	
+		onMouseDown: function(evt){
+			this.selected_hand = evt.target;
+			this.diff_time.setTime(this.current_time.getTime());
+			dojo.stopEvent(evt);
+		},
+	
+		onMouseMove: function(evt){
+			if(!this.selected_hand) return;
+			if(evt.target == this.second_hand.getEventSource() || 
+					evt.target == this.minute_hand.getEventSource() || 
+					evt.target == this.hour_hand.getEventSource()){
+					dojo.stopEvent(evt);
+				return;
+			}
+			if(dojox.gfx.equalSources(this.selected_hand, this.second_hand.getEventSource())){
+				var angle = this.calculateAngle(
+					evt.clientX - this.container_position.x, 
+					evt.clientY - this.container_position.y, 
+					this.normalizeAngle(this.getSecondAngle())
+				);
+				var diff = Math.round(angle / Math.PI * 180 / 6); // in whole seconds
+				this.current_time.setSeconds(this.current_time.getSeconds() + Math.round(diff));
+				this.reflectTime();
+			}else if(dojox.gfx.equalSources(this.selected_hand, this.minute_hand.getEventSource())){
+				var angle = this.calculateAngle(
+					evt.clientX - this.container_position.x, 
+					evt.clientY - this.container_position.y, 
+					this.normalizeAngle(this.getMinuteAngle(this.diff_time))
+				);
+				var diff = Math.round(angle / Math.PI * 180 / 6 * 60); // in whole seconds
+				this.diff_time.setTime(this.diff_time.getTime() + 1000 * diff);
+				this.reflectTime(this.diff_time, true);
+				
+			}else if(dojox.gfx.equalSources(this.selected_hand, this.hour_hand.getEventSource())){
+				var angle = this.calculateAngle(
+					evt.clientX - this.container_position.x, 
+					evt.clientY - this.container_position.y, 
+					this.normalizeAngle(this.getHourAngle(this.diff_time))
+				);
+				var diff = Math.round(angle / Math.PI * 180 / 30 * 60 * 60); // in whole seconds
+				this.diff_time.setTime(this.diff_time.getTime() + 1000 * diff);
+				this.reflectTime(this.diff_time, true, true);
+			}else{
+				return;
+			}
+			dojo.stopEvent(evt);
+		},
+		
+		onMouseUp:function(evt){
+			if(this.selected_hand && !dojox.gfx.equalSources(this.selected_hand, this.second_hand.getEventSource())){
+				this.current_time.setTime(this.diff_time.getTime());
+				this.reflectTime();
+			}
+			this.selected_hand = null;
+			dojo.stopEvent(evt);
+		}
+	});
+	dojo.require("dijit.form.Button");
+	dojo.addOnLoad(function(){
+		var n = dojo.doc.createElement('div');
+		dojo.body().appendChild(n);
+		dojo.style(n,{
+			height:"200px", width:"200px",
+			border:"5px solid #ededed"
+		});
+		new demo.Clock({},n);
+	});
+
+</script>
+<style type="text/css">
+.movable { cursor: hand; }
+</style>
+</head>
+<body>
+<h1>dojox.gfx: interactive analog clock</h1>
+<p>Grab hands and set your own time.</p>
+<p>Warning: Canvas renderer doesn't implement event handling.</p>
+
+<button dojoType="dijit.form.Button">
+	Resize
+	<script type="dojo/method" event="onClick">
+		dijit.byId("one").resize({ w:250, h:250 });
+	</script>
+</button>
+
+<hr noshade size="0" />
+
+<div class="dijitInline" dojoType="demo.Clock" id="gfx_holder" style="width: 300px; height: 300px;"></div>
+<div class="dijitInline" img="images/clock_face.jpg" dojoType="demo.InteractiveClock" style="width: 225px; height: 225px;"></div>
+<div class="dijitInline" id="one" dojoType="demo.Clock" style="width: 150px; height: 150px;"></div>
+<div class="dijitInline" dojoType="demo.Clock" style="width: 75px; height: 75px;"></div>
+
+<hr noshade size="0" />
+
+
+
+
+</body>
+</html>
diff --git a/dojox/gfx/demos/clock_black.html b/dojox/gfx/demos/clock_black.html
new file mode 100644
index 0000000..dda939d
--- /dev/null
+++ b/dojox/gfx/demos/clock_black.html
@@ -0,0 +1,249 @@
+<html>
+<head>
+<title>dojox.gfx: interactive analog clock</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx");
+dojo.require("dojo.date.locale");
+
+var current_time = new Date();
+
+var hour_hand   = null;
+var minute_hand = null;
+var second_hand = null;
+
+var hour_shadow   = null;
+var minute_shadow = null;
+var second_shadow = null;
+
+var center = {x: 385 / 2, y: 385 / 2};
+
+var hour_shadow_shift   = {dx: 2, dy: 2};
+var minute_shadow_shift = {dx: 3, dy: 3};
+var second_shadow_shift = {dx: 4, dy: 4};
+
+var selected_hand = null;
+var container = null;
+var container_position = null;
+var text_time = null;
+var diff_time = new Date();
+
+placeHand = function(shape, angle, shift){
+	var move = {dx: center.x + (shift ? shift.dx : 0), dy: center.y + (shift ? shift.dy : 0)};
+	return shape.setTransform([move, dojox.gfx.matrix.rotateg(angle)]);
+};
+
+placeHourHand = function(h, m, s){
+	var angle = 30 * (h % 12 + m / 60 + s / 3600);
+	placeHand(hour_hand, angle);
+	placeHand(hour_shadow, angle, hour_shadow_shift);
+};
+
+placeMinuteHand = function(m, s){
+	var angle = 6 * (m + s / 60);
+	placeHand(minute_hand, angle);
+	placeHand(minute_shadow, angle, minute_shadow_shift);
+};
+
+placeSecondHand = function(s){
+	var angle = 6 * s;
+	placeHand(second_hand, angle);
+	placeHand(second_shadow, angle, second_shadow_shift);
+};
+
+reflectTime = function(time, hold_second_hand, hold_minute_hand, hold_hour_hand){
+	if(!time) time = current_time;
+	var h = time.getHours();
+	var m = time.getMinutes();
+	var s = time.getSeconds();
+	if(!hold_hour_hand) placeHourHand(h, m, s);
+	if(!hold_minute_hand) placeMinuteHand(m, s);
+	if(!hold_second_hand) placeSecondHand(s);
+	text_time.innerHTML = dojo.date.locale.format(
+		time, {selector: "time", timePattern: "h:mm:ss a"});
+};
+
+resetTime = function(){
+	current_time = new Date();
+	reflectTime();
+};
+
+tick = function(){
+	current_time.setSeconds(current_time.getSeconds() + 1);
+	reflectTime();
+};
+
+advanceTime = function(){
+	if(!selected_hand) {
+		tick();
+	}
+};
+
+normalizeAngle = function(angle){
+	if(angle > Math.PI) {
+		angle -= 2 * Math.PI;
+	} else if(angle < -Math.PI) {
+		angle += 2 * Math.PI;
+	}
+	return angle;
+};
+
+calculateAngle = function(x, y, handAngle){
+	try {
+		return normalizeAngle(Math.atan2(y - center.y, x - center.x) - handAngle);
+	} catch(e) {
+		// supress
+	}
+	return 0;
+};
+
+getSecondAngle = function(time){
+	if(!time) time = current_time;
+	return (6 * time.getSeconds() - 90) / 180 * Math.PI;
+};
+
+getMinuteAngle = function(time){
+	if(!time) time = current_time;
+	return (6 * (time.getMinutes() + time.getSeconds() / 60) - 90) / 180 * Math.PI;
+};
+
+getHourAngle = function(time){
+	if(!time) time = current_time;
+	return (30 * (time.getHours() + (time.getMinutes() + time.getSeconds() / 60) / 60) - 90) / 180 * Math.PI;
+};
+
+onMouseDown = function(evt){
+	selected_hand = evt.target;
+	diff_time.setTime(current_time.getTime());
+	dojo.stopEvent(evt);
+};
+
+onMouseMove = function(evt){
+	if(!selected_hand) return;
+	if(evt.target == second_hand.getEventSource() || 
+			evt.target == minute_hand.getEventSource() || 
+			evt.target == hour_hand.getEventSource()){
+		dojo.stopEvent(evt);
+		return;
+	}
+	if(dojox.gfx.equalSources(selected_hand, second_hand.getEventSource())){
+		var angle = calculateAngle(
+			evt.clientX - container_position.x, 
+			evt.clientY - container_position.y, 
+			normalizeAngle(getSecondAngle())
+		);
+		var diff = Math.round(angle / Math.PI * 180 / 6); // in whole seconds
+		current_time.setSeconds(current_time.getSeconds() + Math.round(diff));
+		reflectTime();
+	}else if(dojox.gfx.equalSources(selected_hand, minute_hand.getEventSource())){
+		var angle = calculateAngle(
+			evt.clientX - container_position.x, 
+			evt.clientY - container_position.y, 
+			normalizeAngle(getMinuteAngle(diff_time))
+		);
+		var diff = Math.round(angle / Math.PI * 180 / 6 * 60); // in whole seconds
+		diff_time.setTime(diff_time.getTime() + 1000 * diff);
+		reflectTime(diff_time, true);
+		
+	}else if(dojox.gfx.equalSources(selected_hand, hour_hand.getEventSource())){
+		var angle = calculateAngle(
+			evt.clientX - container_position.x, 
+			evt.clientY - container_position.y, 
+			normalizeAngle(getHourAngle(diff_time))
+		);
+		var diff = Math.round(angle / Math.PI * 180 / 30 * 60 * 60); // in whole seconds
+		diff_time.setTime(diff_time.getTime() + 1000 * diff);
+		reflectTime(diff_time, true, true);
+	}else{
+		return;
+	}
+	dojo.stopEvent(evt);
+};
+
+onMouseUp = function(evt){
+	if(selected_hand && !dojox.gfx.equalSources(selected_hand, second_hand.getEventSource())){
+		current_time.setTime(diff_time.getTime());
+		reflectTime();
+	}
+	selected_hand = null;
+	dojo.stopEvent(evt);
+};
+
+makeShapes = function(){
+	// prerequisites
+	container = dojo.byId("gfx_holder");
+	container_position = dojo.coords(container, true);
+	text_time = dojo.byId("time");
+	var surface = dojox.gfx.createSurface(container, 385, 385);
+    surface.createImage({width: 385, height: 385, src: "images/clock_face_black.jpg"});
+    
+    // hand shapes
+    var hour_hand_points = [{x: -7, y: 15}, {x: 7, y: 15}, {x: 0, y: -60}, {x: -7, y: 15}];
+    var minute_hand_points = [{x: -5, y: 15}, {x: 5, y: 15}, {x: 0, y: -100}, {x: -5, y: 15}];
+    var second_hand_points = [{x: -2, y: 15}, {x: 2, y: 15}, {x: 2, y: -105}, {x: 6, y: -105}, {x: 0, y: -116}, {x: -6, y: -105}, {x: -2, y: -105}, {x: -2, y: 15}];
+    
+    // create shapes
+    hour_shadow = surface.createPolyline(hour_hand_points)
+		.setFill([0, 0, 0, 0.1])
+		;
+    hour_hand = surface.createPolyline(hour_hand_points)
+		.setStroke({color: "black", width: 2})
+		.setFill("#889")
+		;
+    minute_shadow = surface.createPolyline(minute_hand_points)
+		.setFill([0, 0, 0, 0.1])
+		;
+    minute_hand = surface.createPolyline(minute_hand_points)
+		.setStroke({color: "black", width: 2})
+		.setFill("#ccd")
+		;
+    second_shadow = surface.createPolyline(second_hand_points)
+		.setFill([0, 0, 0, 0.1])
+		;
+    second_hand = surface.createPolyline(second_hand_points)
+		.setStroke({color: "#800", width: 1})
+		.setFill("#d00")
+		;
+
+	// next 3 lines kill Silverlight because its nodes do not support CSS		
+	//dojox.gfx._addClass(hour_hand  .getEventSource(), "movable");
+	//dojox.gfx._addClass(minute_hand.getEventSource(), "movable");
+	//dojox.gfx._addClass(second_hand.getEventSource(), "movable");
+		
+	surface.createCircle({r: 1}).setFill("black").setTransform({dx: 192.5, dy: 192.5});
+	
+	// attach events
+	hour_hand  .connect("onmousedown", onMouseDown);
+	minute_hand.connect("onmousedown", onMouseDown);
+	second_hand.connect("onmousedown", onMouseDown);
+	dojo.connect(container, "onmousemove", onMouseMove);
+	dojo.connect(container, "onmouseup",   onMouseUp);
+	dojo.connect(dojo.byId("reset"), "onclick", resetTime);
+
+	// start the clock		
+	resetTime();
+	window.setInterval(advanceTime, 1000);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+<style type="text/css">
+.movable { cursor: hand; }
+</style>
+</head>
+<body>
+<h1>dojox.gfx: interactive analog clock</h1>
+<p>Grab hands and set your own time.</p>
+<p>Warning: Canvas renderer doesn't implement event handling.</p>
+<div id="gfx_holder" style="width: 385px; height: 385px;"></div>
+<p>Current time: <span id="time"></span>.</p>
+<p><button id="reset">Reset</button></p>
+</body>
+</html>
diff --git a/dojox/gfx/demos/creator.html b/dojox/gfx/demos/creator.html
new file mode 100644
index 0000000..59d5801
--- /dev/null
+++ b/dojox/gfx/demos/creator.html
@@ -0,0 +1,119 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
+<head>
+<title>Create DojoX GFX JSON</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	td.cell { padding: 1em 1em 0em 0em; }
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.utils");
+
+surface = null;
+grid_size = 500;
+grid_step = 50;
+
+init = function(){
+	// initialize graphics
+	var container = dojo.byId("gfx");
+	surface = dojox.gfx.createSurface(container, 500, 500);
+	// create a picture
+
+	// make a grid
+	var grid = surface.createGroup();
+	for(var i = 0; i <= grid_size; i += grid_step){
+		grid.createLine({x1: 0, x2: grid_size, y1: i, y2: i}).setStroke("black");
+		grid.createLine({y1: 0, y2: grid_size, x1: i, x2: i}).setStroke("black");
+	}
+	
+	// make a checkerboard
+	var board = surface.createGroup(), gs2 = grid_step * 2;
+	for(var i = 0; i < grid_size; i += grid_step){
+		for(var j = 0; j < grid_size; j += grid_step){
+			if(i % gs2 == j % gs2) {
+				board.createRect({x: i, y: j, width: grid_step, height: grid_step}).setFill([255, 0, 0, 0.1]);
+			}
+		}
+	}
+	
+	// draw test_transform shapes
+	var g1 = surface.createGroup();
+	var r1 = g1.createShape({type: "rect", x: 200, y: 200})
+				.setFill("green")
+				.setStroke({})
+				;
+	var r2 = surface.createShape({type: "rect"}).setStroke({})
+				.setFill({type: "linear", to: {x: 50, y: 100},
+					colors: [{offset: 0, color: "green"}, {offset: 0.5, color: "red"}, {offset: 1, color: "blue"}] })
+				.setTransform({dx: 100, dy: 100})
+				;
+	var r3 = surface.createRect().setStroke({})
+				.setFill({ type: "linear" })
+				;
+	var r4 = g1.createShape({type: "rect"})
+				.setFill("blue")
+				.setTransform([dojox.gfx.matrix.rotategAt(-30, 350, 250), { dx: 300, dy: 200 }])
+				;
+	var p1 = g1.createShape({type: "path"})
+				.setStroke({})
+				.moveTo(300, 100)
+				.lineTo(400, 200)
+				.lineTo(400, 300)
+				.lineTo(300, 400)
+				.curveTo(400, 300, 400, 200, 300, 100)
+				.setTransform({})
+				;
+	var p2 = g1.createShape(p1.getShape())
+				.setStroke({color: "red", width: 2})
+				.setTransform({dx: 100})
+				;
+	var p3 = g1.createShape({type: "path"})
+				.setStroke({color: "blue", width: 2})
+				.moveTo(300, 100)
+				.setAbsoluteMode(false)
+				.lineTo ( 100,  100)
+				.lineTo (   0,  100)
+				.lineTo (-100,  100)
+				.curveTo( 100, -100, 100, -200, 0, -300)
+				//.setTransform(dojox.gfx.matrix.rotategAt(135, 250, 250))
+				.setTransform(dojox.gfx.matrix.rotategAt(180, 250, 250))
+				;
+	g1.moveToFront();
+	g1.setTransform(dojox.gfx.matrix.rotategAt(-15, 250, 250));
+	
+	// dump everything
+	dump();
+};
+
+dump = function(){
+	var objects = dojox.gfx.utils.serialize(surface);
+	// name top-level objects
+	for(var i = 0; i < objects.length; ++i){
+		objects[i].name = "shape" + i;
+	}
+	// format and show
+	dojo.byId("io").value = dojo.toJson(objects, dojo.byId("pprint").checked);
+};
+
+dojo.addOnLoad(init);
+</script>
+</head>
+<body>
+	<h1>Create DojoX GFX JSON</h1>
+	<p>This is a helper file, which serves as a template to generate static pictures.</p>
+	<table>
+		<tr>
+			<td align="left" valign="top" class="cell">
+				<div id="gfx" style="width: 500px; height: 500px; border: solid 1px black;">
+				</div>
+			</td>
+		</tr>
+	</table>
+	<p><textarea id="io" cols="80" rows="10" wrap="off"></textarea></p>
+	<p><button onclick="dump()">Dump!</button>
+	   <input type="checkbox" id="pprint" checked="checked" /> <label for="pprint">Pretty-print JSON</label></p>
+</body>
+</html>
diff --git a/dojox/gfx/demos/data/Lars.json b/dojox/gfx/demos/data/Lars.json
new file mode 100644
index 0000000..c00a48f
--- /dev/null
+++ b/dojox/gfx/demos/data/Lars.json
@@ -0,0 +1,1823 @@
+[
+	{
+		"name": "torso", 
+		"children": [
+			{
+				"name": "leftArm", 
+				"shape": {
+					"type": "path", 
+					"path": "M156.007,292.674c2.737,1.779,5.563,3.322,8.752,3.947c7.098,1.39,19.25-5.666,23.136-11.699 c1.572-2.441,8.077-21.031,11.177-14.271c1.224,2.67-1.59,4-1.399,6.462c3.108-1.425,5.48-5.242,8.918-2.182 c0.672,4.019-4.472,4.343-3.918,7.669c1.376,0.218,5.394-1.595,6.285-0.535c1.707,2.027-2.933,3.561-4.072,4.018 c-1.852,0.741-4.294,1.233-5.988,2.369c-2.636,1.768-4.766,5.143-7.034,7.4c-11.657,11.604-26.183,10.553-40.646,5.515 c-4.713-1.642-17.399-4.472-18.655-9.427c-1.647-6.502,5.523- [...]
+				}, 
+				"fill": "#FFE8B0", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"name": "leftArmThumb", 
+				"shape": {
+					"type": "path", 
+					"path": "M188.257,284.902c-1.932-1.391-3.314-4.206-3.506-6.494c-0.149-1.786,0.59-6.522,3.199-3.95c0.792,0.78,0.083,2.155,0.558,2.943 c0.885,1.47,1.071,0.493,2.748,1.002c1.406,0.426,3.827,2.05,4.251,3.499"
+				}, 
+				"fill": "#FFE8B0", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"name": "rightArm", 
+				"shape": {
+					"type": "path", 
+					"path": "M57.05,283.306c-5.502,5.354-13.185,8.541-18.249,14.221c-4.303,4.827-7.721,11.575-11.138,17.112 c-6.752,10.939-10.794,26.076-19.912,35.185c-3.869,3.866-7.637,5.721-7.251,12.032c0.932,0.372,1.548,0.589,2.418,0.683 c0.605-2.746,2.569-4.199,5.362-3.799c-0.14,3.365-3.512,5.941-3.228,9.235c0.364,4.223,3.983,5.968,7.181,2.662 c2.61-2.699,0.192-7.848,3.338-10.179c5.535-4.103,2.889,2.998,4.13,5.514c5.19,10.519,8.634-1.859,7.35-7.996 c-2.336-11.159-3.003-15.126,3.267-24.416c6.358-9.4 [...]
+				}, 
+				"fill": "#FFE8B0", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"name": "shirt", 
+				"children": [
+					{
+						"name": "tShirt", 
+						"shape": {
+							"type": "path", 
+							"path": "M96.509,268.264 c-2.301,0.323-4.69,0.205-6.945,0.72c-2.234,0.509-4.5,0.8-6.749,1.249c-4.369,0.872-8.206,3.265-12.3,5.024 c-3.259,1.401-6.644,2.571-9.763,4.26c-1.923,1.041-3.688,2.616-5.487,3.97c-1.543,1.16-3.495,2.11-4.854,3.562 c-2.205,2.354,0.896,7.408,1.854,9.873c0.92,2.368,2.149,4.82,2.749,7.29c0.228,0.937,0.235,2.058,0.875,2.873 c0.644,0.821,0.64,0.735,1.822,0.048c1.513-0.878,2.873-1.993,4.329-2.993c2.431-1.67,5.462-2.848,7.434-5.111 c-3.335,1.652-5.335,4.679-6.931,8 [...]
+						}, 
+						"fill": "#4459A5", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round"
+						}
+					}, 
+					{
+						"name": "shirtNeck", 
+						"shape": {
+							"type": "path", 
+							"path": "M99.759,268.889 c-0.984,0.152-1.746-0.549-2.75-0.5c-1.369,0.066-1.649,0.872-2.153,2c-1.037,2.325-2.442,4.974,0.064,6.946 c2.53,1.991,6.964,1.717,9.829,0.803c1.616-0.516,3.045-1.24,3.825-2.867c0.508-1.061,0.935-2.771,0.149-3.598 c-0.231-0.243-0.562-0.376-0.84-0.534"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round"
+						}
+					}, 
+					{
+						"name": "shirtLogo", 
+						"children": [
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M104.864,296.92c-0.151-0.003,7.101,0.41,7.052,0.404c0.132,0.028-0.172,0.633-0.021,0.632 c-0.226,0.028-7.244-0.454-7.28-0.464C104.657,297.518,104.776,296.904,104.864,296.92z"
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}, 
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M90.071,295.919c-0.199,0.004,6.792,0.43,6.79,0.446c0.153,0.005-0.031,0.663,0.012,0.665 c0.272,0.015-6.79-0.471-6.875-0.459C89.881,296.56,89.796,295.899,90.071,295.919z"
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M84.407,306.476c0.2-0.159,0.322-1.04,0.254,0.057 c-0.542-0.356-2.02,2.083-4.215,2.001c-1.887-1.706-4.559-3.384-4.302-7.092c0.652-2.599,3.082-4.084,5.213-3.942 c1.889,0.377,2.899,0.716,4,1.318c-0.497,0.957-0.175,0.866-0.459,0.703c0.456-2.398,0.598-5.75,0.312-7.855 c0.594-0.554,0.714,0.125,1.249,0.941c0.502-0.727,0.509-1.425,0.875-0.571c-0.207,1.328-0.809,7.186-0.711,10.174 c-0.126,2.797-0.375,4.354-0.051,4.985c-0.718,0.613-0.667,1.006-0.981,1.381c-0.72-1.33-1.056-0.132-1 [...]
+								}, 
+								"stroke": {
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M93.321,297.766c2.592,0.148,5.688,2.315,5.696,5.627 c-0.611,4.576-3.69,5.316-6.158,5.581c-2.68-0.76-5.708-1.872-5.413-6.472C88.086,299.394,90.653,297.875,93.321,297.766z M92.939,307.46c2.531,0.735,3.706-1.297,3.666-3.935c0.114-2.219-0.641-4.584-3.389-4.896c-2.29-0.552-3.366,2.188-3.661,4.688 C89.339,305.264,89.934,307.95,92.939,307.46z"
+								}, 
+								"stroke": {
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M99.688,303.916c0.03-1.511,0.055-4.731,0.022-4.646 c0.481-1.355,0.658-0.556,1.034-1.297c0.263,1.473,0.653,0.326,1.186,0.066c-0.386,2.517-0.513,3.347-0.574,4.949 c-0.068-0.47-0.128,2.28-0.238,2.188c-0.055,1.935-0.036,2.201-0.047,4.219c-0.079,0.914-0.28,2.412-1.126,3.831 c-0.61,1.212-1.73,1.146-3.24,1.651c0.073-0.945-0.065-1.242-0.096-1.822c0.098,0.138,0.213,0.604,0.225,0.398 c1.892,0.228,2.209-1.896,2.362-3.366c0.042,0.304,0.512-6.933,0.415-7.061C99.73,302.636,99.75,303. [...]
+								}, 
+								"stroke": {
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M108.115,298.791c3.028-0.067,5.283,1.359,5.256,5.757 c-0.264,3.479-3.366,4.63-5.883,5.12c-2.429-0.034-5.619-2.241-5.16-5.811C102.322,300.085,105.715,298.845,108.115,298.791z M107.351,309.232c2.675-0.132,3.839-2.333,3.841-4.497c0.246-2.344-0.263-4.833-2.923-5.396 c-2.844,0.299-3.974,1.917-4.053,4.48C104.136,306.655,104.854,308.372,107.351,309.232z"
+								}, 
+								"stroke": {
+								}
+							}
+						]
+					}
+				]
+			}
+		]
+	}, 
+	{
+		"name": "heads", 
+		"children": [
+			{
+				"name": "head1", 
+				"children": [
+					{
+						"name": "leftEart", 
+						"children": [
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M201.557,195.474 c7.734-4.547,16.591-5.012,18.405,4.443c2.43,12.659-3.317,13.328-14.598,13.328"
+								}, 
+								"fill": "#FFE8B0", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M211.711,203.09 c0.523,0.004,0.946-0.208,1.27-0.635"
+								}, 
+								"fill": "#FFE8B0", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M211.076,197.377 c3.062,3.013,5.489,5.624,4.443,10.155"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "bgHairTop", 
+						"shape": {
+							"type": "path", 
+							"path": "M54.384,199.306c-5.253-4.402-7.511-11.061-15.779-10.632c3.449-1.277,7.116-2.397,10.911-2.666 c-2.873-1.397-5.865-2.575-8.231-4.718c3.986-1.119,11.47-1.817,14.864,0.75c-5.183-2.758-8.397-7.816-13.062-10.598 c6.014-0.643,12.377,0.978,18.022,2.265c-2.547-4.486-6.682-10.83-10.523-14.297c5.033,1.052,10.647,4.518,15.062,7.177 c-1.614-4.176-5.634-8.406-7.859-12.513c10.312-1.125,12.522,4.919,19.7,9.932c-0.412-0.127-1.114-0.113-1.527,0.015 c0.875-7.261,3.058-12.8,8.258-18.566c6.77 [...]
+						}, 
+						"fill": "#FFF471", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"name": "bgHairLeft", 
+						"shape": {
+							"type": "path", 
+							"path": "M92.384,243.972c-6.334,7.929-12.601,12.241-22.465,15.362c3.65-1.263,7.735-5.86,7.695-9.928 c-2.208,0.218-4.49,0.605-6.498,1.097c1.244-1.097,2.087-3.239,3.198-4.396c-5.77,0.001-12.131,1.133-18.396,1.23 c5.013-2.809,10.665-3.25,12.398-9.246c-3.59,0.313-7.233,1.606-11.033,1.097c1.731-2.022,3.953-3.995,5.049-6.447 c-3.781,0.056-6.665,3.098-10.547,2.465c0.962-2.863,3.187-5.208,4.531-7.766c-5.59-0.273-11.658,2.45-17.732,2.564 c5.494-2.857,8.967-7.819,12.3-12.718c5.233-7.693,10. [...]
+						}, 
+						"fill": "#FFF471", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"name": "bgHair", 
+						"shape": {
+							"type": "path", 
+							"path": "M142.384,255.306c2.984,6.076,3.567,11.856,10.531,14.6c-0.134-3.114-0.094-6.664,1.619-9.033 c1.605,1.968,3.122,4.211,5.048,5.698c-0.29-1.769,0.412-4.024,0.233-5.828c3.445,0.26,4.979,3.965,8.468,4.479 c0.066-2.78,0.427-5.151,0.868-7.813c2.687,0.2,4.768,1.565,7.132,2.997c0.452-4.921-0.409-10.579-0.667-15.666 c-5.795-0.756-12.291,2.827-17.899,3.899c-4.414,0.844-14.136,0.524-15.333,6"
+						}, 
+						"fill": "#FFF471", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"name": "neck", 
+						"shape": {
+							"type": "path", 
+							"path": "M106.989,254.499c-2.932,6.063-4.613,11.997-8.947,17.137c7.288,10.195,16.311-10.9,15.183-17.026 c-1.926-1.138-3.928-1.589-6.236-1.38"
+						}, 
+						"fill": "#FFE8B0", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"name": "headShape", 
+						"shape": {
+							"type": "path", 
+							"path": "M210.941,207.665c-0.843,3.985-2.081,7.982-3.769,11.783c-3.374,7.604-8.543,14.427-16.052,18.899 c-2.94,2.13-5.983,4.167-9.109,6.085c-25.013,15.342-55.353,23.08-82.254,10.57c-3.433-1.557-6.785-3.431-10.053-5.66 c-1.821-1.184-3.592-2.46-5.308-3.832c-1.715-1.373-3.375-2.842-4.972-4.412c-2.352-2.148-4.576-4.425-6.631-6.814 c-6.168-7.169-10.823-15.358-12.87-24.185c-0.649-3.284-0.84-6.634-0.5-9.975c4.48-13.743,14.22-24.364,26.109-32.149 c2.973-1.946,6.079-3.715,9.271-5.309c30.58 [...]
+						}, 
+						"fill": "#FFE8B0", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"name": "rightEar", 
+						"children": [
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M64.857,195.606 c-6.59-7.181-15.047-10.664-19.467,3.676c-1.235,4.007-1.87,14.468,1.29,17.786c4.223,4.435,13.591,0.529,19.055-0.015"
+								}, 
+								"fill": "#FFE8B0", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M52.407,196.743 c-1.702,3.613-1.257,7.505-1.27,11.424"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M51.772,209.437 c-3.39-4.661,0.922-5.769,5.078-6.347"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "fgHair", 
+						"shape": {
+							"type": "path", 
+							"path": "M90.384,154.639c8.453-11.353,15.678-13.458,28.581-15.915c-1.382,3.376-3.89,7.352-5.179,11.16 c5.01-1.816,9.571-6.545,15.218-8.413c11.355-3.755,23.852-1.903,35.671-2.213c-3.004,3.712-4.912,7.88-2.026,11.447 c5.856-2.212,13.37-6.871,19.635-6.646c0.263,4.561-0.024,9.278,0.201,13.841c3.509-1.201,6.015-3.04,8.277-5.148 s3.761-4.049,4.942-5.2c1.063,2.408,2.134,5.334,2.24,8.494c-0.182,3.462-0.866,6.794-2.66,9.291 c3.663,0.65,6.098-2.021,8.35-4.479c-0.655,4.349-3.164,8.604-3.851, [...]
+						}, 
+						"fill": "#FFF471", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}
+				]
+			}
+		]
+	}, 
+	{
+		"name": "eyes", 
+		"children": [
+			{
+				"name": "eyes1", 
+				"children": [
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M123.163,176.668 c-5.066,1.17-9.01,7.888-13.666,10.335c-4.238,2.227-8.648,6.636-7.009,12.332c1.971,6.848,12.042,3.991,16.261,1.165 c5.282-3.539,9.59-8.517,12.006-14.524c1.523-3.787,2.568-7.272-1.509-9.391c-2.905-1.51-8.174-1.386-11.417-0.583"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M182.545,179.865 c-3.533,0.169-4.854-1.166-8.408-0.001c-3,0.983-6.24,1.936-8.852,3.743c-3.938,2.725-7.46,5.555-4.73,13.592 c1.973,5.811,8.791,7.571,14.656,6.667c5.537-0.854,9.078-4.977,11.408-10.007c3.666-7.918,0.943-11.639-6.742-13.659"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M108.829,183.668c-1.308-1.03-4.557,0.011-5.6-1.733 c-1.056-1.765,1.735-5.409,2.984-6.192c5.684-3.562,15.946-0.39,19.95-6.742"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M163.877,167.198c2.369,1.282,6.539,0.307,9.408,0.815 c3.449,0.612,7.066,2.657,10.592,2.851"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M127.496,192.002c-4.917-2.12-9.188-1.708-8.608,4.942 c3.132,1.734,5.428-2.82,7.275-4.942"
+						}, 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M174.852,203.143c-0.293,0.12-0.307,0.577-0.943,0.282 c-1.605-3.188-0.404-6.507,2.676-8.192c2.15-1.176,5.67-1.759,7.471,0.359c0.199,0.234,0.412,0.521,0.514,0.813 c0.229,0.649-0.285,0.95-0.285,0.95s-3.988,6.009-3.285,1.934c0.438,1.743-5.537,5.743-2.287,1.653 c-1.955,2.583-2.525,1.977-3.859,2.868"
+						}, 
+						"stroke": {
+							"color": "#000000"
+						}
+					}
+				]
+			}, 
+			{
+				"name": "eyes2", 
+				"children": [
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M98.668,186.108c0.668-8.915,15.545-13.749,22.667-15"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M169.667,178.108 c5.307,3.436,16.928,5.632,19.668,12.333"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M105.334,197.775c8.085-4.283,17.059-2.8,25-6.333"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M164.001,198.775c4.656-0.417,9.664,1.805,14.334,2.017 c3.951,0.18,5.773,0.189,9,2.316"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M124.001,188.108c3.039-0.258,4.594,2.571,5.301,4.983 c-1.096,1.242-2.065,2.646-2.968,4.017"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M168.335,194.108c-1.77,2.293-4.869,3.271-6.299,5.91 c1.377,0.991,3.02,2.122,3.965,3.424"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}
+				]
+			}
+		]
+	}, 
+	{
+		"name": "beard", 
+		"children": [
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M96.05,213.639 c-0.366,0.21-0.783,0.389-1.167,0.5"
+				}, 
+				"fill": "#AFA8A5", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M102.55,211.972 c0.314-0.01,0.554-0.198,0.667-0.5"
+				}, 
+				"fill": "#AFA8A5", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M105.717,208.805 c0.164-0.109,0.336-0.224,0.5-0.333"
+				}, 
+				"fill": "#AFA8A5", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M111.05,207.972 c-0.651-1.81,0.859-2.262,2.333-1.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M117.717,209.805 c1.738,0,3.653,0.369,5.333,0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M132.717,214.472 c0.104-0.21,0.162-0.435,0.167-0.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M139.551,216.972 c0.215-0.175,0.465-0.426,0.666-0.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M144.551,213.305 c0.277-0.056,0.556-0.111,0.833-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M147.884,216.639 c0.195,0.045,0.369-0.013,0.5-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M148.384,214.139 c0.112-0.168,0.222-0.332,0.333-0.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M98.217,219.305c1.697-1.772,4.233-2.109,5.967-4.046c1.519-1.696,3.812-3.001,4.2-5.454"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M152.717,216.139 c0.611,0,1.223,0,1.834,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M160.384,217.472 c0.333,0,0.667,0,1,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M163.217,215.972 c0.321-0.042,0.658-0.175,0.834-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M164.217,218.805 c0.167,0,0.333,0,0.5,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M168.384,217.972 c0.056-0.056,0.111-0.111,0.167-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M169.884,225.805 c0.491-0.397,0.882-0.926,1.167-1.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M172.717,221.972 c0.056,0,0.111,0,0.167,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M171.717,229.805 c0.334,0.075,0.659,0.025,0.834-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M190.051,227.805 c0.163-0.242,0.398-0.423,0.666-0.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M197.384,221.472 c0.258-0.007,0.485-0.125,0.667-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M199.384,214.972 c-0.04-0.333,0.075-0.609,0.333-0.833"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M117.884,257.305 c0.056,0,0.111,0,0.167,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M142.717,252.472 c0.358,0.069,0.71,0.016,1-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M137.884,256.472 c0.277,0,0.556,0,0.833,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M160.884,252.972 c0.366-0.138,0.765-0.402,1-0.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M171.384,250.139 c0.235-0.263,0.475-0.561,0.667-0.834"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M89.384,243.972 c0.537,0.378,1.329,0.876,1.833,1.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M79.05,225.472 c0.087,0.272,0.143,0.55,0.167,0.833"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M73.884,222.639 c0,0.167,0,0.333,0,0.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M72.55,219.805c0.466-0.325,0.875-0.797,1.167-1.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M71.717,211.972c0.422-0.553,0.776-1.305,1-2"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M78.55,214.472c0-0.111,0-0.222,0-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M79.384,218.805c-0.001-0.137,0.055-0.248,0.167-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M80.217,221.139c0.111,0,0.222,0,0.333,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M75.55,226.472c0.103-0.5,0.156-0.977,0.167-1.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M78.55,230.139c0.111,0,0.222,0,0.333,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M83.384,227.639c0.118-0.059,0.215-0.107,0.333-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M81.55,237.139c0.056,0,0.111,0,0.167,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M86.217,233.805c0.056,0,0.111,0,0.167,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M87.884,230.472c0.595-0.181,1.219-0.527,1.833-0.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M88.717,222.139 c-0.929,2.359-1.615,4.865-2.667,7.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M89.05,216.139 c0.784-0.736,1.709-1.565,2.833-1.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M94.217,210.139 c1.599-0.089,3.199-0.167,4.833-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M94.884,224.639 c0.052-0.588-0.004-1.155-0.167-1.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M92.384,228.305 c0.585-0.062,1.244-0.132,1.667-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M88.717,240.139 c0.111,0,0.222,0,0.333,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M95.884,243.305 c0.526,0.1,1.017-0.015,1.333-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M98.55,248.305 c0.069-0.24,0.265-0.926,0.333-1.166"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M96.55,249.805 c0.125,0.014,0.18-0.042,0.167-0.166"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M104.55,250.139 c0.01-0.238,0.126-0.428,0.333-0.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M106.884,251.972 c0.195,0.045,0.37-0.013,0.5-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M113.884,254.805 c0.758-0.586,1.595-1.171,2.382-1.774c0.072,0.376,0.418,0.685,0.48,1.079c0.833,0.265,1.624-0.021,1.638-0.971"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M122.217,254.639 c0.063-0.165,0.179-0.288,0.333-0.334"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M125.884,255.805 c1.13-0.745,2.783-0.962,3.667-2"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M132.217,255.972 c0.638-0.492,1.104-1.173,1.141-1.975c-1.11,0.062-1.449-0.888-1.475-1.858"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M129.717,249.305 c-0.045,0.154-0.168,0.271-0.333,0.334"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M136.551,252.305 c0.222,0,0.444,0,0.666,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M110.217,251.305 c0.056-0.056,0.111-0.11,0.167-0.166"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M140.717,251.805 c0.111,0,0.223,0,0.334,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M150.051,249.472 c0.111,0,0.222,0,0.333,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M143.217,255.472 c1.022-0.313,1.724-1.175,2.646-1.654c0.203,0.321,0.44,0.626,0.521,0.987"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M152.217,253.472 c0.165-0.063,0.288-0.179,0.334-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M155.051,254.639 c0.222,0,0.444,0,0.666,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M157.717,256.472 c0.326-0.027,0.546-0.073,0.834-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M163.217,252.639 c0.552-0.891,2.082-1.512,2.341-2.334c0.37-1.177-1.156-3.069-1.007-4.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M167.384,235.972 c0.118-0.54,0.353-1.064,0.667-1.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M170.717,242.805 c0-0.333,0-0.667,0-1"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M170.217,236.972 c0-0.333,0-0.667,0-1"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M179.051,235.805 c0.378-0.101,0.738-0.35,1-0.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M185.051,232.805 c0.379-0.319,0.656-0.702,0.833-1.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M188.051,231.139 c0.063-0.39,0.178-0.792,0.333-1.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M197.884,223.305 c-0.166,0.277-0.334,0.556-0.5,0.833"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}
+		]
+	}, 
+	{
+		"name": "mouths", 
+		"children": [
+			{
+				"name": "mouth1", 
+				"children": [
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M177.122,216.821c-0.515,2.282-5.213,3.21-7.433,3.854 c-3.254,0.945-6.596,1.345-9.895,1.851c-3.26,0.5-6.665,0.671-10.107,0.671c-3.596,0-6.645,0.559-10.107,0.671 c-3.105,0.1-6.898-0.474-9.694-1.3c-3.527-1.043-6.672-1.666-10.096-3.062c-2.823-1.152-5.746-1.876-8.462-3.143 c-2.594-1.209-6.084-1.994-8.221-3.552c-1.068,1.834-5.867,3.748-8.1,4.546c-2.444,0.874-8.881,2.725-7.817,5.512 c0.457,1.195,1.948,2.273,2.63,3.385c0.774,1.261,1.139,2.601,2.057,3.859c1.83,2.5,4.506,4.773,6,7. [...]
+						}, 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M135.25,241.319 c0.723-4.757-10.487-8.47-14.898-9.526c-3.09-0.74-6.68-1.17-9.858-1.712c-2.758-0.47-6.865-0.836-9.437,0.369 c-1.385,0.649-2.843,1.724-4.141,2.513c2.156,3.964,4.728,8.861,9.468,11.506c3.229,1.801,5.511,0.777,8.859,0.373 c3.045-0.369,6.046-0.703,9.029-1.72c3.479-1.186,7.228-2.385,10.978-2.475"
+						}, 
+						"fill": "#FFC0C0", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M148.656,225.547c1.267,0.697,1.301,2.838,0.671,3.9 c-0.702,1.182-2.063,1.4-3.306,2.01c-2.271,1.116-4.581,2.624-7.482,2.638c-4.619,0.023-2.143-4.067-0.253-5.869 c2.405-2.292,5.057-2.72,8.72-2.512c0.588,0.034,1.095,0.041,1.65,0.168"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M130.299,223.365 c2.687,0.437,5.619,4.384,3.727,6.422c-1.234,1.33-7.94,1.391-9.915,1.296c-4.896-0.233-2.502-2.445-0.613-4.525 c1.604-1.767,5.088-3.249,7.833-3.36"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M113.178,217.157 c2.56,0.958,4.922,5.057,5.352,7.215c0.377,1.885-0.324,2.106-2.526,2.643c-1.366,0.333-3.636,0.723-5.105,0.385 c-2.506-0.577-5.883-5.051-4.909-7.223c1.03-2.298,5.944-2.923,8.427-2.852"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M99.359,217.661 c2.038,0.432,4.015,4.279,2.468,5.625c-1.083,0.943-5.221,1.795-6.799,1.589c-4.032-0.526-2.265-4.102-0.866-5.872 c0.706-0.894,1.049-1.976,2.514-2.186c1.627-0.233,2.501,0.99,3.921,1.346"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M181.815,222.895c-3.101-2.75-4.764-8.777-9.282-10.403"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}
+				]
+			}, 
+			{
+				"name": "mouth2", 
+				"children": [
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M87.57,221.951c5.563-1.759,11.066-1.32,16.694-1.782c2.93-0.24,5.228-1.14,8.309-0.927c3.142,0.217,6.085-0.235,9.289,0.176 c7.136,0.914,13.96,0.598,21.112,1.506c3.654,0.464,7.218,0.609,10.81,0.869c4.017,0.291,7.646,1.582,11.433,2.623 c2.948,0.812,6.347,1.618,9.011,2.99c2.521,1.298,6.354,2.856,8.3,4.72c-2.775,0.027-5.601,2.603-8.021,3.769 c-2.93,1.412-5.741,2.949-8.656,4.432c-5.599,2.849-11.885,5.468-18.104,6.53c-6.793,1.161-13.195,2.107-20.067,2.197 c-7.699,0.102-14.313-4.7 [...]
+						}, 
+						"stroke": {
+							"color": "#000000", 
+							"width": "3", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M87.785,228.193 c-5.907-3.235-0.344-9.531,3.971-11.424"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000", 
+							"width": "2"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M184.679,227.228c-1.534,2.583-2.548,5.334-4.025,7.889"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000", 
+							"width": "2", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M106.862,219.528 c-3.071-0.74-5.608,2.166-6.318,4.738c-0.379,1.375-0.494,2.55,0.748,3.337c1.519,0.962,2.905-0.052,4.418-0.332 c2.518-0.467,7.293,0.053,6.461-4.248c-0.568-2.938-3.743-3.682-6.338-3.335c-0.451,0.06-0.758,0.212-1.205,0.229"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M119.764,218.479 c-2.648,1.243-4.657,3.518-5.346,6.377c-0.866,3.594,3.9,3.711,6.356,2.865c2.64-0.91,4.77-3.351,3.299-6.133 c-1.01-1.91-3.979-2.548-6.026-2.823"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M130.388,219.492 c-1.753,1.382-4.069,4.525-4.835,6.61c-1.159,3.156,2.296,3.371,4.868,3.348c3.061-0.028,6.6-1.148,5.022-4.78 c-1.168-2.691-2.552-4.85-5.551-5.241"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M142.954,221.087 c-1.502,0.337-5.418,3.249-5.638,4.997c-0.292,2.311,4.856,4.536,6.854,4.234c2.503-0.377,4.384-3.175,3.167-5.65 c-0.92-1.873-3.36-2.252-4.508-3.932"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M155.354,222.663 c-2.039,0.426-4.212,2.287-4.766,4.444c-0.723,2.821,3.225,3.383,5.458,3.331c2.541-0.059,5.126-1.752,3.249-4.32 c-1.394-1.908-3.707-3.189-5.304-4.636"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M168.367,237.924 c-1.554-1.217-3.302-2.557-5.203-2.976c-2.973-0.654-3.537,2.131-3.377,4.406c0.205,2.913,1.032,3.883,3.901,2.344 c1.988-1.066,4.272-1.997,4.599-4.456"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M151.524,246.202 c-1.912-0.166-4.003-4.491-2.91-6.25c0.771-1.239,5.456-1.688,6.858-1.292c0.271,0.917,0.979,1.841,0.829,2.771 c-0.088,0.54-0.994,1.645-1.296,2.188c-1.08,1.951-2.133,1.866-3.998,2.684"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M145.911,241.457 c-0.209,1.649-0.215,2.702-1.528,3.801c-0.885,0.739-1.773,1.19-2.54,2.1c-0.786,0.933-1.226,2.38-2.792,1.812 c-1.042-0.377-1.959-2.318-2.138-3.311c-0.299-1.676-1.003-5.228,0.783-6.158c1.155-0.603,7.067-0.18,7.43,1.32"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M133.12,238.991 c-1.495-0.087-2.253-1.33-3.918-0.964c-1.42,0.311-2.489,1.354-2.54,2.836c-0.052,1.527,0.99,5.581,1.852,6.956 c2.363,3.771,4.329-1.535,5.516-3.159c1.117-1.526,2.643-2.053,2.271-3.958c-0.318-1.632-1.118-2.047-2.766-2.329 c-0.382-0.065-0.773-0.095-1.158-0.147"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M116.853,237.429 c-1.049,2.211-0.173,5.147,0.047,7.566c0.357,3.929,3.827,2.028,5.831,0.067c1.575-1.541,4.599-4.86,2.209-6.484 c-1.881-1.279-5.727-2.458-7.756-1.107"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M107.455,233.38 c-0.813,2.487-1.704,5.049,0.073,7.364c1.91,2.486,4.009,1.229,5.537-0.939c1.056-1.5,3.316-4.481,1.563-6.017 c-1.347-1.179-6.468-1.518-7.854-0.325"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}
+				]
+			}, 
+			{
+				"name": "mouth3", 
+				"children": [
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M99.05,218.972 c1.691-0.875,3.313-2.39,4.833-3.537c1.231-0.928,2.782-1.671,3.5-3.072c1.846,3.486,7.661,4.669,11.003,6.067 c3.553,1.486,7.174,3.066,10.784,4.166c4.271,1.301,9.277,1.67,13.721,2.343c4.155,0.629,9.979,1.365,14.162,0.496 c1.181-0.245,2.343-1.024,3.462-1.446c0.162,1.905-3.637,3.023-4.933,3.487c-2.435,0.871-4.18,2.541-6.362,3.871 c-1.623,0.989-2.974,1.669-4.755,2.117c-1.77,0.445-3.353,0.806-4.825,1.878c-5.915,4.311-15.264,3.247-22.424,3.13 c-5.384-0.088-6.719-5. [...]
+						}, 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M107.217,227.972 c1.182-2.033,4.375-2.176,6.5-1.963c2.879,0.289,4.124,1.217,6.168,3.167c1.834,1.749,5.906,5.509,5.64,8.271 c-2.808,0.89-7.847,0.402-10.346-1.104c-1.334-0.804-1.151-2.256-2.246-3.588c-0.712-0.866-1.836-2.673-2.855-3.311 c-0.209-0.94-2.106-1.499-3.028-1.805"
+						}, 
+						"fill": "#F4BDBD", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}
+				]
+			}
+		]
+	}, 
+	{
+		"name": "personalProps", 
+		"children": [
+			{
+				"name": "hat", 
+				"children": [
+					{
+						"children": [
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M88.374,173.144c0.474-0.074,16.606,2.725,18.01,5.879 c1.145,2.572,28.184,4.568,28.184,4.568l35.971-5.618l5.025,1.132l7.211,0.315l9.295,0.851l10.188,3.248l5.75,2.935 l1.615-1.832l-0.264-5.27l-3.967-7.087c0,0-22.045-13.031-23.273-13.703c-1.229-0.669-4.941-2.294-6.484-4.542 c-8.584-12.528-8.404-18.05-3.371-6.461c0,0,2.662-7.592,2.52-8.575c-0.143-0.982,0.355-5.031,0.355-5.031l2.396-6.832 c0,0-1.379-5.341-2.738-7.19c-1.357-1.844-15.793-4.078-18.162-4.011c-24.933,0.706-3.78 [...]
+										}, 
+										"fill": "#FF0000", 
+										"stroke": {
+										}
+									}, 
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M156.605,114.92l-13.936,0.381l-11.633,0.343c-10.646,0.319-11.973-0.155-12.021-0.175l-0.599-0.238 l-0.577,0.514l0.049-0.047c-0.118,0.09-1.43,0.957-11.145,3.53c-9.989,2.646-12.812,2.931-13.421,2.704 c-0.822-0.306-0.821-0.306-7.791,2.604l-2.104,0.878c-16.037,6.689-17.342,7.324-17.342,10.316c0,0.019,0.001,0.041,0.001,0.06 c-0.224-0.108-0.459-0.199-0.787-0.04c-0.357,0.173-0.565,0.275-0.565,0.672c0,0.557,0.411,1.697,1.399,4.438 c0.924,2.561,1.71,3.671,2.714,3.833c0.083,0.01 [...]
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}, 
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M155.146,147.929c4.879-9.398-5.344-20.199-12.65-21.176 c-12.05-1.61-13.404,10.426-13.684,21.258c3.73,2.016,8.915,3.425,11.721,6.534"
+										}, 
+										"fill": "#FFFFFF", 
+										"stroke": {
+										}
+									}, 
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M133.446,127.979c-4.599,3.921-5.426,11.933-5.635,20.006l-0.017,0.654l4.415,2.067 c2.849,1.244,5.793,2.529,7.581,4.509c0.371,0.41,1.004,0.442,1.412,0.072c0.219-0.197,0.33-0.469,0.33-0.743 c0-0.239-0.084-0.479-0.258-0.67c-2.076-2.299-5.222-3.673-8.266-5.001c0,0-2.377-1.112-3.174-1.486 c0.223-7.385,1.021-14.572,4.909-17.887c1.892-1.614,4.386-2.189,7.621-1.757c4.143,0.554,9.086,4.472,11.5,9.113 c1.348,2.591,2.51,6.535,0.395,10.611c-0.254,0.49-0.064,1.093,0.426,1.348c0.49, [...]
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}, 
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M154.077,146.278c-2.156,1.18-4.24,2.619-6.256,4.01c-3.635,2.509-7.068,4.878-10.941,5.924 c-2.991,0.808-6.055,1.058-9.3,1.324c-3.222,0.263-6.553,0.536-9.783,1.406c-2.027,0.546-4.117,1.397-6.137,2.221 c-3.491,1.423-7.102,2.895-10.528,2.866c-0.552-0.005-1.004,0.439-1.009,0.991s0.439,1.004,0.991,1.009 c3.828,0.033,7.627-1.516,11.301-3.014c2.054-0.837,3.994-1.628,5.902-2.142c3.054-0.823,6.292-1.088,9.425-1.344 c3.191-0.261,6.492-0.531,9.659-1.386c4.205-1.135,7.941-3.714,11 [...]
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}, 
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M156.458,153.549c-2.619,0.064-5.709,0.812-8.98,1.604c-4.279,1.035-8.701,2.104-11.902,1.536 c-0.543-0.096-1.063,0.267-1.159,0.81c-0.097,0.544,0.267,1.063,0.81,1.16c3.613,0.641,8.24-0.481,12.72-1.562 c3.166-0.766,6.154-1.489,8.561-1.548c5.664-0.141,7.961,0.698,13.508,2.724c0.518,0.189,1.094-0.077,1.281-0.596 c0.189-0.519-0.076-1.091-0.596-1.282C165.069,154.337,162.501,153.399,156.458,153.549z"
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}
+						]
+					}
+				]
+			}, 
+			{
+				"name": "textSurface", 
+				"children": [
+					{
+						"name": "spokenBubble", 
+						"children": [
+							{
+								"name": "textContainer", 
+								"shape": {
+									"type": "path", 
+									"path": "M225.719,45.306c0-6.627,5.373-12,12-12h181.333 c6.627,0,12,5.373,12,12V150.64c0,6.627-5.373,12-12,12H237.719c-6.627,0-12-5.373-12-12V45.306z"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"name": "textArrowBelow", 
+								"shape": {
+									"type": "path", 
+									"path": "M249.052,160.639 c-0.775,14.251-1.676,18.525-9.1,30.565c9.705-0.79,21.952-21.605,25.1-30.045"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "thoughtBubble", 
+						"children": [
+							{
+								"name": "textContainer_1_", 
+								"shape": {
+									"type": "path", 
+									"path": "M202.698,21.089 c19.686-26.45,59.686-24.45,79.747-0.084c2.697,1.349,5.571,1.709,7.472,0.781c15.28-13.888,33.272-14.043,49.893-7.839 c2.771,1.034,5.478,2.219,8.031,3.421c28.543-21.729,75.543-10.729,83.166,27.658c0,0-1.324,3.889,1.165,6.603 c18.212,11.011,26.212,32.011,22.212,53.011c-1,5.333-3.223,9.667-6.037,13.52c-2.814,3.854-1.381,0-2.613-0.591 c-1.35-0.929-3.35-0.929-4.35-1.929c16,7,27,22,30,39c2,21-8,41-27,50c-16,7.5-32.5,5.5-45.745-2.556 c-2.532-1.384-4.229-1.856-5. [...]
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M269.719,186.306c0,4.602-4.179,8.333-9.333,8.333c-5.155,0-9.334-3.731-9.334-8.333 c0-4.603,4.179-8.333,9.334-8.333C265.54,177.973,269.719,181.704,269.719,186.306z"
+										}, 
+										"fill": "#FFFFFF", 
+										"stroke": {
+										}
+									}, 
+									{
+										"children": [
+											{
+												"shape": {
+													"type": "path", 
+													"path": "M269.719,186.306c0,4.602-4.179,8.333-9.333,8.333c-5.155,0-9.334-3.731-9.334-8.333 c0-4.603,4.179-8.333,9.334-8.333C265.54,177.973,269.719,181.704,269.719,186.306z"
+												}, 
+												"fill": "none", 
+												"stroke": {
+												}
+											}, 
+											{
+												"shape": {
+													"type": "path", 
+													"path": "M268.225,186.165c-0.564,8.736-13.982,9.286-15.633,0.853 c-1.785-9.125,15.017-10.254,15.649-0.451c0.125,1.929,3.078,1.388,2.955-0.521c-0.814-12.597-20.828-12.412-21.639,0.119 c-0.827,12.813,20.831,13.028,21.655,0.283C271.337,184.518,268.35,184.235,268.225,186.165z"
+												}, 
+												"fill": "#FFFFFF", 
+												"stroke": {
+												}
+											}
+										]
+									}
+								]
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M260.386,188.306c0,3.498-2.985,6.333-6.667,6.333 s-6.667-2.835-6.667-6.333c0-3.498,2.985-6.333,6.667-6.333S260.386,184.808,260.386,188.306z"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M238.386,196.973c0,1.289-1.045,2.333-2.334,2.333 c-1.288,0-2.333-1.045-2.333-2.333s1.045-2.333,2.333-2.333C237.341,194.639,238.386,195.684,238.386,196.973z"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M285.719,179.973c0,4.602-4.253,8.333-9.5,8.333 s-9.5-3.731-9.5-8.333c0-4.603,4.253-8.333,9.5-8.333S285.719,175.371,285.719,179.973z"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "yellBubble", 
+						"children": [
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M251.156,176.051 l40.228-15.992"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M280.932,149.385 l-40.667,36.42"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"name": "textContainer_2_", 
+								"shape": {
+									"type": "path", 
+									"path": "M217.778,34.643 c8.609,6.684,9.952,3.684,7.987-5.785c6.308,5.125,9.308,3.782,10.188-4.309c2.433,8.091,5.266,8.091,9.12-1.703 c6.063,9.793,13.146,9.793,24.043,3.878c6.103,5.915,16.02,5.915,20.094-4.64c17.178,10.555,28.511,10.555,45.233-5.505 c5.941,16.06,17.273,16.06,18.835,1.458c19.688,14.603,29.605,14.603,46.749-17.802c-0.144,32.405,6.939,32.405,29.26,16.182 c-12.403,16.223-9.57,16.223,4.813,6.576c-11.07,9.646-8.07,10.99,4.333,9.089c-8.061,6.244-6.717,9.244,2.533,11.06 [...]
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}
+				]
+			}
+		]
+	}
+]
\ No newline at end of file
diff --git a/dojox/gfx/demos/data/Lars.svg b/dojox/gfx/demos/data/Lars.svg
new file mode 100644
index 0000000..177385e
--- /dev/null
+++ b/dojox/gfx/demos/data/Lars.svg
@@ -0,0 +1,532 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/">
+	<g id="torso" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#000000000000">
+		<path id="leftArm" i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M156.007,292.674c2.737,1.779,5.563,3.322,8.752,3.947c7.098,1.39,19.25-5.666,23.136-11.699
+			c1.572-2.441,8.077-21.031,11.177-14.271c1.224,2.67-1.59,4-1.399,6.462c3.108-1.425,5.48-5.242,8.918-2.182
+			c0.672,4.019-4.472,4.343-3.918,7.669c1.376,0.218,5.394-1.595,6.285-0.535c1.707,2.027-2.933,3.561-4.072,4.018
+			c-1.852,0.741-4.294,1.233-5.988,2.369c-2.636,1.768-4.766,5.143-7.034,7.4c-11.657,11.604-26.183,10.553-40.646,5.515
+			c-4.713-1.642-17.399-4.472-18.655-9.427c-1.647-6.502,5.523-7.999,10.184-6.74C147.658,286.528,151.725,289.891,156.007,292.674z
+			"/>
+		<path id="leftArmThumb" i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M188.257,284.902c-1.932-1.391-3.314-4.206-3.506-6.494c-0.149-1.786,0.59-6.522,3.199-3.95c0.792,0.78,0.083,2.155,0.558,2.943
+			c0.885,1.47,1.071,0.493,2.748,1.002c1.406,0.426,3.827,2.05,4.251,3.499"/>
+		<path id="rightArm" i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M57.05,283.306c-5.502,5.354-13.185,8.541-18.249,14.221c-4.303,4.827-7.721,11.575-11.138,17.112
+			c-6.752,10.939-10.794,26.076-19.912,35.185c-3.869,3.866-7.637,5.721-7.251,12.032c0.932,0.372,1.548,0.589,2.418,0.683
+			c0.605-2.746,2.569-4.199,5.362-3.799c-0.14,3.365-3.512,5.941-3.228,9.235c0.364,4.223,3.983,5.968,7.181,2.662
+			c2.61-2.699,0.192-7.848,3.338-10.179c5.535-4.103,2.889,2.998,4.13,5.514c5.19,10.519,8.634-1.859,7.35-7.996
+			c-2.336-11.159-3.003-15.126,3.267-24.416c6.358-9.419,12.194-18.708,19.399-27.588c1.116-1.375,2.08-2.728,3.333-4"/>
+		<g id="shirt" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F008000FFFF">
+			<path id="tShirt" i:knockout="Off" fill="#4459A5" stroke="#000000" stroke-linecap="round" d="M96.509,268.264
+				c-2.301,0.323-4.69,0.205-6.945,0.72c-2.234,0.509-4.5,0.8-6.749,1.249c-4.369,0.872-8.206,3.265-12.3,5.024
+				c-3.259,1.401-6.644,2.571-9.763,4.26c-1.923,1.041-3.688,2.616-5.487,3.97c-1.543,1.16-3.495,2.11-4.854,3.562
+				c-2.205,2.354,0.896,7.408,1.854,9.873c0.92,2.368,2.149,4.82,2.749,7.29c0.228,0.937,0.235,2.058,0.875,2.873
+				c0.644,0.821,0.64,0.735,1.822,0.048c1.513-0.878,2.873-1.993,4.329-2.993c2.431-1.67,5.462-2.848,7.434-5.111
+				c-3.335,1.652-5.335,4.679-6.931,8.012c-1.398,2.92-4.482,35.854-5.389,38.947c-0.195,0.003-0.775,0.003-0.749,0.013
+				c20.561,0,41.123-0.07,61.684,0c2.1,0.007,3.607-0.497,5.529-1.252c0.715-0.281,2.257-0.356,2.807-0.745
+				c1.412-0.998-0.094-3.916-0.646-5.302c-1.425-3.579-2.111-37.767-4.726-40.543c1.842,0.057,4.127,1.311,5.937,1.95
+				c1.351,0.478,2.633,1.092,3.956,1.66c1.39,0.597,3.667,1.927,5.168,1.858c0.296-1.873,1.045-3.286,1.839-5.02
+				c0.943-2.061,1.155-4.214,1.528-6.415c0.351-2.07,0.898-3.787,1.939-5.635c0.531-0.942,1.356-1.73,1.693-2.768
+				c-0.443-0.402-1.043-0.907-1.603-1.125c-0.56-0.219-1.292-0.111-1.908-0.33c-1.237-0.438-2.44-1.089-3.669-1.576
+				c-3.773-1.499-7.519-2.983-11.319-4.466c-3.575-1.396-6.977-3.239-10.784-3.872c-1.735-0.289-3.467-0.529-5.073-0.906"/>
+			<path id="shirtNeck" i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" d="M99.759,268.889
+				c-0.984,0.152-1.746-0.549-2.75-0.5c-1.369,0.066-1.649,0.872-2.153,2c-1.037,2.325-2.442,4.974,0.064,6.946
+				c2.53,1.991,6.964,1.717,9.829,0.803c1.616-0.516,3.045-1.24,3.825-2.867c0.508-1.061,0.935-2.771,0.149-3.598
+				c-0.231-0.243-0.562-0.376-0.84-0.534"/>
+			<g id="shirtLogo" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F008000FFFF">
+				<g i:knockout="Off">
+					<path i:knockout="Off" d="M104.864,296.92c-0.151-0.003,7.101,0.41,7.052,0.404c0.132,0.028-0.172,0.633-0.021,0.632
+						c-0.226,0.028-7.244-0.454-7.28-0.464C104.657,297.518,104.776,296.904,104.864,296.92z"/>
+				</g>
+				<g i:knockout="Off">
+					<path i:knockout="Off" d="M90.071,295.919c-0.199,0.004,6.792,0.43,6.79,0.446c0.153,0.005-0.031,0.663,0.012,0.665
+						c0.272,0.015-6.79-0.471-6.875-0.459C89.881,296.56,89.796,295.899,90.071,295.919z"/>
+				</g>
+				<path i:isolated="yes" i:knockout="Off" enable-background="new    " d="M84.407,306.476c0.2-0.159,0.322-1.04,0.254,0.057
+					c-0.542-0.356-2.02,2.083-4.215,2.001c-1.887-1.706-4.559-3.384-4.302-7.092c0.652-2.599,3.082-4.084,5.213-3.942
+					c1.889,0.377,2.899,0.716,4,1.318c-0.497,0.957-0.175,0.866-0.459,0.703c0.456-2.398,0.598-5.75,0.312-7.855
+					c0.594-0.554,0.714,0.125,1.249,0.941c0.502-0.727,0.509-1.425,0.875-0.571c-0.207,1.328-0.809,7.186-0.711,10.174
+					c-0.126,2.797-0.375,4.354-0.051,4.985c-0.718,0.613-0.667,1.006-0.981,1.381c-0.72-1.33-1.056-0.132-1.339-0.157
+					C84.632,308.442,84.493,305.791,84.407,306.476z M81.186,307.176c2.403,0.206,3.734-2.164,3.841-4.222
+					c0.269-2.72-0.896-5.104-3.198-5.04c-1.972,0.437-3.46,2.188-3.331,4.638C78.171,306.265,79.847,306.961,81.186,307.176z"/>
+				<path i:isolated="yes" i:knockout="Off" enable-background="new    " d="M93.321,297.766c2.592,0.148,5.688,2.315,5.696,5.627
+					c-0.611,4.576-3.69,5.316-6.158,5.581c-2.68-0.76-5.708-1.872-5.413-6.472C88.086,299.394,90.653,297.875,93.321,297.766z
+					 M92.939,307.46c2.531,0.735,3.706-1.297,3.666-3.935c0.114-2.219-0.641-4.584-3.389-4.896c-2.29-0.552-3.366,2.188-3.661,4.688
+					C89.339,305.264,89.934,307.95,92.939,307.46z"/>
+				<path i:isolated="yes" i:knockout="Off" enable-background="new    " d="M99.688,303.916c0.03-1.511,0.055-4.731,0.022-4.646
+					c0.481-1.355,0.658-0.556,1.034-1.297c0.263,1.473,0.653,0.326,1.186,0.066c-0.386,2.517-0.513,3.347-0.574,4.949
+					c-0.068-0.47-0.128,2.28-0.238,2.188c-0.055,1.935-0.036,2.201-0.047,4.219c-0.079,0.914-0.28,2.412-1.126,3.831
+					c-0.61,1.212-1.73,1.146-3.24,1.651c0.073-0.945-0.065-1.242-0.096-1.822c0.098,0.138,0.213,0.604,0.225,0.398
+					c1.892,0.228,2.209-1.896,2.362-3.366c0.042,0.304,0.512-6.933,0.415-7.061C99.73,302.636,99.75,303.178,99.688,303.916z
+					 M100.978,295.564c0.717,0.14,1.11,0.61,1.099,1.156c0.052,0.552-0.595,0.993-1.286,1.015c-0.541-0.074-1.025-0.548-1.022-1.054
+					C99.813,296.084,100.292,295.643,100.978,295.564z"/>
+				<path i:isolated="yes" i:knockout="Off" enable-background="new    " d="M108.115,298.791c3.028-0.067,5.283,1.359,5.256,5.757
+					c-0.264,3.479-3.366,4.63-5.883,5.12c-2.429-0.034-5.619-2.241-5.16-5.811C102.322,300.085,105.715,298.845,108.115,298.791z
+					 M107.351,309.232c2.675-0.132,3.839-2.333,3.841-4.497c0.246-2.344-0.263-4.833-2.923-5.396
+					c-2.844,0.299-3.974,1.917-4.053,4.48C104.136,306.655,104.854,308.372,107.351,309.232z"/>
+			</g>
+		</g>
+	</g>
+	<g id="heads" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F004F00FFFF">
+		<g id="head1" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFFFFFF4F00">
+			<g id="leftEart" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFFFFFF4F00">
+				<path i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M201.557,195.474
+					c7.734-4.547,16.591-5.012,18.405,4.443c2.43,12.659-3.317,13.328-14.598,13.328"/>
+				<path i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M211.711,203.09
+					c0.523,0.004,0.946-0.208,1.27-0.635"/>
+				<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M211.076,197.377
+					c3.062,3.013,5.489,5.624,4.443,10.155"/>
+			</g>
+			<path id="bgHairTop" i:knockout="Off" fill="#FFF471" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M54.384,199.306c-5.253-4.402-7.511-11.061-15.779-10.632c3.449-1.277,7.116-2.397,10.911-2.666
+				c-2.873-1.397-5.865-2.575-8.231-4.718c3.986-1.119,11.47-1.817,14.864,0.75c-5.183-2.758-8.397-7.816-13.062-10.598
+				c6.014-0.643,12.377,0.978,18.022,2.265c-2.547-4.486-6.682-10.83-10.523-14.297c5.033,1.052,10.647,4.518,15.062,7.177
+				c-1.614-4.176-5.634-8.406-7.859-12.513c10.312-1.125,12.522,4.919,19.7,9.932c-0.412-0.127-1.114-0.113-1.527,0.015
+				c0.875-7.261,3.058-12.8,8.258-18.566c6.771-7.507,17.812-9.131,24.095-15.381c-4.699,1.821-4.518,23.765-4.875,28.955"/>
+			<path id="bgHairLeft" i:knockout="Off" fill="#FFF471" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M92.384,243.972c-6.334,7.929-12.601,12.241-22.465,15.362c3.65-1.263,7.735-5.86,7.695-9.928
+				c-2.208,0.218-4.49,0.605-6.498,1.097c1.244-1.097,2.087-3.239,3.198-4.396c-5.77,0.001-12.131,1.133-18.396,1.23
+				c5.013-2.809,10.665-3.25,12.398-9.246c-3.59,0.313-7.233,1.606-11.033,1.097c1.731-2.022,3.953-3.995,5.049-6.447
+				c-3.781,0.056-6.665,3.098-10.547,2.465c0.962-2.863,3.187-5.208,4.531-7.766c-5.59-0.273-11.658,2.45-17.732,2.564
+				c5.494-2.857,8.967-7.819,12.3-12.718c5.233-7.693,10.625-9.96,20.349-9.981c11.059-0.024,15.558,6.714,20.984,16
+				c2.786,4.767,7.249,14.375,0.832,18"/>
+			<path id="bgHair" i:knockout="Off" fill="#FFF471" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M142.384,255.306c2.984,6.076,3.567,11.856,10.531,14.6c-0.134-3.114-0.094-6.664,1.619-9.033
+				c1.605,1.968,3.122,4.211,5.048,5.698c-0.29-1.769,0.412-4.024,0.233-5.828c3.445,0.26,4.979,3.965,8.468,4.479
+				c0.066-2.78,0.427-5.151,0.868-7.813c2.687,0.2,4.768,1.565,7.132,2.997c0.452-4.921-0.409-10.579-0.667-15.666
+				c-5.795-0.756-12.291,2.827-17.899,3.899c-4.414,0.844-14.136,0.524-15.333,6"/>
+			<path id="neck" i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M106.989,254.499c-2.932,6.063-4.613,11.997-8.947,17.137c7.288,10.195,16.311-10.9,15.183-17.026
+				c-1.926-1.138-3.928-1.589-6.236-1.38"/>
+			<path id="headShape" i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M210.941,207.665c-0.843,3.985-2.081,7.982-3.769,11.783c-3.374,7.604-8.543,14.427-16.052,18.899
+				c-2.94,2.13-5.983,4.167-9.109,6.085c-25.013,15.342-55.353,23.08-82.254,10.57c-3.433-1.557-6.785-3.431-10.053-5.66
+				c-1.821-1.184-3.592-2.46-5.308-3.832c-1.715-1.373-3.375-2.842-4.972-4.412c-2.352-2.148-4.576-4.425-6.631-6.814
+				c-6.168-7.169-10.823-15.358-12.87-24.185c-0.649-3.284-0.84-6.634-0.5-9.975c4.48-13.743,14.22-24.364,26.109-32.149
+				c2.973-1.946,6.079-3.715,9.271-5.309c30.581-15.027,69.581-10.027,95.851,12.209c2.564,2.254,4.988,4.651,7.244,7.178
+				c4.513,5.054,8.354,10.626,11.312,16.64C210.178,201.505,210.798,204.496,210.941,207.665z"/>
+			<g id="rightEar" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFFFFFF4F00">
+				<path i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M64.857,195.606
+					c-6.59-7.181-15.047-10.664-19.467,3.676c-1.235,4.007-1.87,14.468,1.29,17.786c4.223,4.435,13.591,0.529,19.055-0.015"/>
+				<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M52.407,196.743
+					c-1.702,3.613-1.257,7.505-1.27,11.424"/>
+				<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M51.772,209.437
+					c-3.39-4.661,0.922-5.769,5.078-6.347"/>
+			</g>
+			<path id="fgHair" i:knockout="Off" fill="#FFF471" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M90.384,154.639c8.453-11.353,15.678-13.458,28.581-15.915c-1.382,3.376-3.89,7.352-5.179,11.16
+				c5.01-1.816,9.571-6.545,15.218-8.413c11.355-3.755,23.852-1.903,35.671-2.213c-3.004,3.712-4.912,7.88-2.026,11.447
+				c5.856-2.212,13.37-6.871,19.635-6.646c0.263,4.561-0.024,9.278,0.201,13.841c3.509-1.201,6.015-3.04,8.277-5.148
+				s3.761-4.049,4.942-5.2c1.063,2.408,2.134,5.334,2.24,8.494c-0.182,3.462-0.866,6.794-2.66,9.291
+				c3.663,0.65,6.098-2.021,8.35-4.479c-0.655,4.349-3.164,8.604-3.851,13.013c2.178-0.072,4.382,0.216,6.367-0.48
+				c-1.389,3.093-3.069,7.287-6.616,8.414c-4.475,1.423-4.354-0.992-7.315-4.332c-4.892-5.518-9.774-6.791-15.872-9.464
+				c-6.585-2.887-10.983-6.47-17.963-8.219c-8.994-2.255-19.864-3.867-28.093-5.196c2.466,1.967,1.138,5.594,0.659,8.625
+				c-2.729-0.645-4.41-3.813-6.301-5.158c0.953,3.195,0.983,6.953-2.134,8.491c-6.145-5.226-9.199-9.721-17.527-11.647
+				c1,1.83,1.728,4.208,1.396,6.402c-0.751,4.971-0.289,3.134-3.836,2.466c-5.192-0.977-9.953-3.677-15.815-4.496
+				c3.292,2.002,5.469,5.017,7.418,8.21c-2.651,0.404-6.238,0.257-8.382,1.671c2.456,0.38,3.44,2.166,3.197,4.714
+				c-7.45,0.386-13.623,0.731-19.915,5.434"/>
+		</g>
+	</g>
+	<g id="eyes" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFF4F00FFFF">
+		<g id="eyes1" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#4F00FFFFFFFF" display="none">
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M123.163,176.668
+				c-5.066,1.17-9.01,7.888-13.666,10.335c-4.238,2.227-8.648,6.636-7.009,12.332c1.971,6.848,12.042,3.991,16.261,1.165
+				c5.282-3.539,9.59-8.517,12.006-14.524c1.523-3.787,2.568-7.272-1.509-9.391c-2.905-1.51-8.174-1.386-11.417-0.583"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" stroke-linecap="round" d="M182.545,179.865
+				c-3.533,0.169-4.854-1.166-8.408-0.001c-3,0.983-6.24,1.936-8.852,3.743c-3.938,2.725-7.46,5.555-4.73,13.592
+				c1.973,5.811,8.791,7.571,14.656,6.667c5.537-0.854,9.078-4.977,11.408-10.007c3.666-7.918,0.943-11.639-6.742-13.659"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M108.829,183.668c-1.308-1.03-4.557,0.011-5.6-1.733
+				c-1.056-1.765,1.735-5.409,2.984-6.192c5.684-3.562,15.946-0.39,19.95-6.742"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M163.877,167.198c2.369,1.282,6.539,0.307,9.408,0.815
+				c3.449,0.612,7.066,2.657,10.592,2.851"/>
+			<path i:knockout="Off" display="inline" stroke="#000000" d="M127.496,192.002c-4.917-2.12-9.188-1.708-8.608,4.942
+				c3.132,1.734,5.428-2.82,7.275-4.942"/>
+			<path i:knockout="Off" display="inline" stroke="#000000" d="M174.852,203.143c-0.293,0.12-0.307,0.577-0.943,0.282
+				c-1.605-3.188-0.404-6.507,2.676-8.192c2.15-1.176,5.67-1.759,7.471,0.359c0.199,0.234,0.412,0.521,0.514,0.813
+				c0.229,0.649-0.285,0.95-0.285,0.95s-3.988,6.009-3.285,1.934c0.438,1.743-5.537,5.743-2.287,1.653
+				c-1.955,2.583-2.525,1.977-3.859,2.868"/>
+		</g>
+		<g id="eyes2" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#800080008000" display="none">
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M98.668,186.108c0.668-8.915,15.545-13.749,22.667-15"
+				/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M169.667,178.108
+				c5.307,3.436,16.928,5.632,19.668,12.333"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M105.334,197.775c8.085-4.283,17.059-2.8,25-6.333"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M164.001,198.775c4.656-0.417,9.664,1.805,14.334,2.017
+				c3.951,0.18,5.773,0.189,9,2.316"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M124.001,188.108c3.039-0.258,4.594,2.571,5.301,4.983
+				c-1.096,1.242-2.065,2.646-2.968,4.017"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M168.335,194.108c-1.77,2.293-4.869,3.271-6.299,5.91
+				c1.377,0.991,3.02,2.122,3.965,3.424"/>
+		</g>
+	</g>
+	<g id="beard" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFF4F00">
+		<path i:knockout="Off" fill="#AFA8A5" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M96.05,213.639
+			c-0.366,0.21-0.783,0.389-1.167,0.5"/>
+		<path i:knockout="Off" fill="#AFA8A5" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M102.55,211.972
+			c0.314-0.01,0.554-0.198,0.667-0.5"/>
+		<path i:knockout="Off" fill="#AFA8A5" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M105.717,208.805
+			c0.164-0.109,0.336-0.224,0.5-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M111.05,207.972
+			c-0.651-1.81,0.859-2.262,2.333-1.5"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M117.717,209.805
+			c1.738,0,3.653,0.369,5.333,0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M132.717,214.472
+			c0.104-0.21,0.162-0.435,0.167-0.667"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M139.551,216.972
+			c0.215-0.175,0.465-0.426,0.666-0.667"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M144.551,213.305
+			c0.277-0.056,0.556-0.111,0.833-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M147.884,216.639
+			c0.195,0.045,0.369-0.013,0.5-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M148.384,214.139
+			c0.112-0.168,0.222-0.332,0.333-0.5"/>
+		<path i:knockout="Off" display="none" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M98.217,219.305c1.697-1.772,4.233-2.109,5.967-4.046c1.519-1.696,3.812-3.001,4.2-5.454"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M152.717,216.139
+			c0.611,0,1.223,0,1.834,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M160.384,217.472
+			c0.333,0,0.667,0,1,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M163.217,215.972
+			c0.321-0.042,0.658-0.175,0.834-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M164.217,218.805
+			c0.167,0,0.333,0,0.5,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M168.384,217.972
+			c0.056-0.056,0.111-0.111,0.167-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M169.884,225.805
+			c0.491-0.397,0.882-0.926,1.167-1.5"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M172.717,221.972
+			c0.056,0,0.111,0,0.167,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M171.717,229.805
+			c0.334,0.075,0.659,0.025,0.834-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M190.051,227.805
+			c0.163-0.242,0.398-0.423,0.666-0.5"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M197.384,221.472
+			c0.258-0.007,0.485-0.125,0.667-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M199.384,214.972
+			c-0.04-0.333,0.075-0.609,0.333-0.833"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M117.884,257.305
+			c0.056,0,0.111,0,0.167,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M142.717,252.472
+			c0.358,0.069,0.71,0.016,1-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M137.884,256.472
+			c0.277,0,0.556,0,0.833,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M160.884,252.972
+			c0.366-0.138,0.765-0.402,1-0.667"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M171.384,250.139
+			c0.235-0.263,0.475-0.561,0.667-0.834"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M89.384,243.972
+			c0.537,0.378,1.329,0.876,1.833,1.333"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M79.05,225.472
+			c0.087,0.272,0.143,0.55,0.167,0.833"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M73.884,222.639
+			c0,0.167,0,0.333,0,0.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M72.55,219.805c0.466-0.325,0.875-0.797,1.167-1.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M71.717,211.972c0.422-0.553,0.776-1.305,1-2"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M78.55,214.472c0-0.111,0-0.222,0-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M79.384,218.805c-0.001-0.137,0.055-0.248,0.167-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M80.217,221.139c0.111,0,0.222,0,0.333,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M75.55,226.472c0.103-0.5,0.156-0.977,0.167-1.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M78.55,230.139c0.111,0,0.222,0,0.333,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M83.384,227.639c0.118-0.059,0.215-0.107,0.333-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M81.55,237.139c0.056,0,0.111,0,0.167,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M86.217,233.805c0.056,0,0.111,0,0.167,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M87.884,230.472c0.595-0.181,1.219-0.527,1.833-0.667"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M88.717,222.139
+			c-0.929,2.359-1.615,4.865-2.667,7.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M89.05,216.139
+			c0.784-0.736,1.709-1.565,2.833-1.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M94.217,210.139
+			c1.599-0.089,3.199-0.167,4.833-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M94.884,224.639
+			c0.052-0.588-0.004-1.155-0.167-1.667"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M92.384,228.305
+			c0.585-0.062,1.244-0.132,1.667-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M88.717,240.139
+			c0.111,0,0.222,0,0.333,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M95.884,243.305
+			c0.526,0.1,1.017-0.015,1.333-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M98.55,248.305
+			c0.069-0.24,0.265-0.926,0.333-1.166"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M96.55,249.805
+			c0.125,0.014,0.18-0.042,0.167-0.166"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M104.55,250.139
+			c0.01-0.238,0.126-0.428,0.333-0.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M106.884,251.972
+			c0.195,0.045,0.37-0.013,0.5-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M113.884,254.805
+			c0.758-0.586,1.595-1.171,2.382-1.774c0.072,0.376,0.418,0.685,0.48,1.079c0.833,0.265,1.624-0.021,1.638-0.971"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M122.217,254.639
+			c0.063-0.165,0.179-0.288,0.333-0.334"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M125.884,255.805
+			c1.13-0.745,2.783-0.962,3.667-2"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M132.217,255.972
+			c0.638-0.492,1.104-1.173,1.141-1.975c-1.11,0.062-1.449-0.888-1.475-1.858"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M129.717,249.305
+			c-0.045,0.154-0.168,0.271-0.333,0.334"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M136.551,252.305
+			c0.222,0,0.444,0,0.666,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M110.217,251.305
+			c0.056-0.056,0.111-0.11,0.167-0.166"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M140.717,251.805
+			c0.111,0,0.223,0,0.334,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M150.051,249.472
+			c0.111,0,0.222,0,0.333,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M143.217,255.472
+			c1.022-0.313,1.724-1.175,2.646-1.654c0.203,0.321,0.44,0.626,0.521,0.987"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M152.217,253.472
+			c0.165-0.063,0.288-0.179,0.334-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M155.051,254.639
+			c0.222,0,0.444,0,0.666,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M157.717,256.472
+			c0.326-0.027,0.546-0.073,0.834-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M163.217,252.639
+			c0.552-0.891,2.082-1.512,2.341-2.334c0.37-1.177-1.156-3.069-1.007-4.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M167.384,235.972
+			c0.118-0.54,0.353-1.064,0.667-1.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M170.717,242.805
+			c0-0.333,0-0.667,0-1"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M170.217,236.972
+			c0-0.333,0-0.667,0-1"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M179.051,235.805
+			c0.378-0.101,0.738-0.35,1-0.667"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M185.051,232.805
+			c0.379-0.319,0.656-0.702,0.833-1.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M188.051,231.139
+			c0.063-0.39,0.178-0.792,0.333-1.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M197.884,223.305
+			c-0.166,0.277-0.334,0.556-0.5,0.833"/>
+	</g>
+	<g id="mouths" i:isolated="yes" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFF4F004F00" enable-background="new    ">
+		<g id="mouth1" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#4F00FFFF4F00" display="none">
+			<path i:knockout="Off" display="inline" stroke="#000000" d="M177.122,216.821c-0.515,2.282-5.213,3.21-7.433,3.854
+				c-3.254,0.945-6.596,1.345-9.895,1.851c-3.26,0.5-6.665,0.671-10.107,0.671c-3.596,0-6.645,0.559-10.107,0.671
+				c-3.105,0.1-6.898-0.474-9.694-1.3c-3.527-1.043-6.672-1.666-10.096-3.062c-2.823-1.152-5.746-1.876-8.462-3.143
+				c-2.594-1.209-6.084-1.994-8.221-3.552c-1.068,1.834-5.867,3.748-8.1,4.546c-2.444,0.874-8.881,2.725-7.817,5.512
+				c0.457,1.195,1.948,2.273,2.63,3.385c0.774,1.261,1.139,2.601,2.057,3.859c1.83,2.5,4.506,4.773,6,7.34
+				c1.308,2.249,2.096,4.74,4.01,6.67c2.214,2.233,5.792,2.634,9.231,2.399c7.028-0.479,13.982-2.129,20.481-3.983
+				c3.295-0.941,6.699-1.536,10.087-2.686c3.272-1.111,6.641-3,9.402-4.777c5.248-3.377,10.278-6.409,14.283-10.705
+				c1.479-1.587,3.429-2.503,5.15-3.859"/>
+			<path i:knockout="Off" display="inline" fill="#FFC0C0" stroke="#000000" d="M135.25,241.319
+				c0.723-4.757-10.487-8.47-14.898-9.526c-3.09-0.74-6.68-1.17-9.858-1.712c-2.758-0.47-6.865-0.836-9.437,0.369
+				c-1.385,0.649-2.843,1.724-4.141,2.513c2.156,3.964,4.728,8.861,9.468,11.506c3.229,1.801,5.511,0.777,8.859,0.373
+				c3.045-0.369,6.046-0.703,9.029-1.72c3.479-1.186,7.228-2.385,10.978-2.475"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M148.656,225.547c1.267,0.697,1.301,2.838,0.671,3.9
+				c-0.702,1.182-2.063,1.4-3.306,2.01c-2.271,1.116-4.581,2.624-7.482,2.638c-4.619,0.023-2.143-4.067-0.253-5.869
+				c2.405-2.292,5.057-2.72,8.72-2.512c0.588,0.034,1.095,0.041,1.65,0.168"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M130.299,223.365
+				c2.687,0.437,5.619,4.384,3.727,6.422c-1.234,1.33-7.94,1.391-9.915,1.296c-4.896-0.233-2.502-2.445-0.613-4.525
+				c1.604-1.767,5.088-3.249,7.833-3.36"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M113.178,217.157
+				c2.56,0.958,4.922,5.057,5.352,7.215c0.377,1.885-0.324,2.106-2.526,2.643c-1.366,0.333-3.636,0.723-5.105,0.385
+				c-2.506-0.577-5.883-5.051-4.909-7.223c1.03-2.298,5.944-2.923,8.427-2.852"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M99.359,217.661
+				c2.038,0.432,4.015,4.279,2.468,5.625c-1.083,0.943-5.221,1.795-6.799,1.589c-4.032-0.526-2.265-4.102-0.866-5.872
+				c0.706-0.894,1.049-1.976,2.514-2.186c1.627-0.233,2.501,0.99,3.921,1.346"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M181.815,222.895c-3.101-2.75-4.764-8.777-9.282-10.403
+				"/>
+		</g>
+		<g id="mouth2" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#4F00FFFF4F00" display="none">
+			<path i:knockout="Off" display="inline" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M87.57,221.951c5.563-1.759,11.066-1.32,16.694-1.782c2.93-0.24,5.228-1.14,8.309-0.927c3.142,0.217,6.085-0.235,9.289,0.176
+				c7.136,0.914,13.96,0.598,21.112,1.506c3.654,0.464,7.218,0.609,10.81,0.869c4.017,0.291,7.646,1.582,11.433,2.623
+				c2.948,0.812,6.347,1.618,9.011,2.99c2.521,1.298,6.354,2.856,8.3,4.72c-2.775,0.027-5.601,2.603-8.021,3.769
+				c-2.93,1.412-5.741,2.949-8.656,4.432c-5.599,2.849-11.885,5.468-18.104,6.53c-6.793,1.161-13.195,2.107-20.067,2.197
+				c-7.699,0.102-14.313-4.705-20.735-8.396c-2.071-1.19-4.69-2.182-6.504-3.666c-1.792-1.466-3.469-3.386-5.154-4.984
+				c-2.703-2.564-7.519-5.649-8.13-9.438"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" stroke-width="2" d="M87.785,228.193
+				c-5.907-3.235-0.344-9.531,3.971-11.424"/>
+			
+				<path i:knockout="Off" display="inline" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M184.679,227.228c-1.534,2.583-2.548,5.334-4.025,7.889"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M106.862,219.528
+				c-3.071-0.74-5.608,2.166-6.318,4.738c-0.379,1.375-0.494,2.55,0.748,3.337c1.519,0.962,2.905-0.052,4.418-0.332
+				c2.518-0.467,7.293,0.053,6.461-4.248c-0.568-2.938-3.743-3.682-6.338-3.335c-0.451,0.06-0.758,0.212-1.205,0.229"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M119.764,218.479
+				c-2.648,1.243-4.657,3.518-5.346,6.377c-0.866,3.594,3.9,3.711,6.356,2.865c2.64-0.91,4.77-3.351,3.299-6.133
+				c-1.01-1.91-3.979-2.548-6.026-2.823"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M130.388,219.492
+				c-1.753,1.382-4.069,4.525-4.835,6.61c-1.159,3.156,2.296,3.371,4.868,3.348c3.061-0.028,6.6-1.148,5.022-4.78
+				c-1.168-2.691-2.552-4.85-5.551-5.241"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M142.954,221.087
+				c-1.502,0.337-5.418,3.249-5.638,4.997c-0.292,2.311,4.856,4.536,6.854,4.234c2.503-0.377,4.384-3.175,3.167-5.65
+				c-0.92-1.873-3.36-2.252-4.508-3.932"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M155.354,222.663
+				c-2.039,0.426-4.212,2.287-4.766,4.444c-0.723,2.821,3.225,3.383,5.458,3.331c2.541-0.059,5.126-1.752,3.249-4.32
+				c-1.394-1.908-3.707-3.189-5.304-4.636"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M168.367,237.924
+				c-1.554-1.217-3.302-2.557-5.203-2.976c-2.973-0.654-3.537,2.131-3.377,4.406c0.205,2.913,1.032,3.883,3.901,2.344
+				c1.988-1.066,4.272-1.997,4.599-4.456"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M151.524,246.202
+				c-1.912-0.166-4.003-4.491-2.91-6.25c0.771-1.239,5.456-1.688,6.858-1.292c0.271,0.917,0.979,1.841,0.829,2.771
+				c-0.088,0.54-0.994,1.645-1.296,2.188c-1.08,1.951-2.133,1.866-3.998,2.684"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M145.911,241.457
+				c-0.209,1.649-0.215,2.702-1.528,3.801c-0.885,0.739-1.773,1.19-2.54,2.1c-0.786,0.933-1.226,2.38-2.792,1.812
+				c-1.042-0.377-1.959-2.318-2.138-3.311c-0.299-1.676-1.003-5.228,0.783-6.158c1.155-0.603,7.067-0.18,7.43,1.32"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M133.12,238.991
+				c-1.495-0.087-2.253-1.33-3.918-0.964c-1.42,0.311-2.489,1.354-2.54,2.836c-0.052,1.527,0.99,5.581,1.852,6.956
+				c2.363,3.771,4.329-1.535,5.516-3.159c1.117-1.526,2.643-2.053,2.271-3.958c-0.318-1.632-1.118-2.047-2.766-2.329
+				c-0.382-0.065-0.773-0.095-1.158-0.147"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M116.853,237.429
+				c-1.049,2.211-0.173,5.147,0.047,7.566c0.357,3.929,3.827,2.028,5.831,0.067c1.575-1.541,4.599-4.86,2.209-6.484
+				c-1.881-1.279-5.727-2.458-7.756-1.107"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M107.455,233.38
+				c-0.813,2.487-1.704,5.049,0.073,7.364c1.91,2.486,4.009,1.229,5.537-0.939c1.056-1.5,3.316-4.481,1.563-6.017
+				c-1.347-1.179-6.468-1.518-7.854-0.325"/>
+		</g>
+		<g id="mouth3" i:isolated="yes" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFF4F00" enable-background="new    ">
+			<path i:knockout="Off" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M99.05,218.972
+				c1.691-0.875,3.313-2.39,4.833-3.537c1.231-0.928,2.782-1.671,3.5-3.072c1.846,3.486,7.661,4.669,11.003,6.067
+				c3.553,1.486,7.174,3.066,10.784,4.166c4.271,1.301,9.277,1.67,13.721,2.343c4.155,0.629,9.979,1.365,14.162,0.496
+				c1.181-0.245,2.343-1.024,3.462-1.446c0.162,1.905-3.637,3.023-4.933,3.487c-2.435,0.871-4.18,2.541-6.362,3.871
+				c-1.623,0.989-2.974,1.669-4.755,2.117c-1.77,0.445-3.353,0.806-4.825,1.878c-5.915,4.311-15.264,3.247-22.424,3.13
+				c-5.384-0.088-6.719-5.372-9.337-9c-1.437-1.991-2.843-3.854-3.796-6.138c-0.871-2.086-1.119-4.582-2.033-6.528"/>
+			<path i:knockout="Off" fill="#F4BDBD" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M107.217,227.972
+				c1.182-2.033,4.375-2.176,6.5-1.963c2.879,0.289,4.124,1.217,6.168,3.167c1.834,1.749,5.906,5.509,5.64,8.271
+				c-2.808,0.89-7.847,0.402-10.346-1.104c-1.334-0.804-1.151-2.256-2.246-3.588c-0.712-0.866-1.836-2.673-2.855-3.311
+				c-0.209-0.94-2.106-1.499-3.028-1.805"/>
+		</g>
+	</g>
+	<g id="personalProps" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F004F00FFFF">
+		<g id="hat" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#FFFFFFFF4F00" display="none">
+			<g display="inline">
+				<g i:knockout="Off">
+					<path i:knockout="Off" fill="#FF0000" d="M88.374,173.144c0.474-0.074,16.606,2.725,18.01,5.879
+						c1.145,2.572,28.184,4.568,28.184,4.568l35.971-5.618l5.025,1.132l7.211,0.315l9.295,0.851l10.188,3.248l5.75,2.935
+						l1.615-1.832l-0.264-5.27l-3.967-7.087c0,0-22.045-13.031-23.273-13.703c-1.229-0.669-4.941-2.294-6.484-4.542
+						c-8.584-12.528-8.404-18.05-3.371-6.461c0,0,2.662-7.592,2.52-8.575c-0.143-0.982,0.355-5.031,0.355-5.031l2.396-6.832
+						c0,0-1.379-5.341-2.738-7.19c-1.357-1.844-15.793-4.078-18.162-4.011c-24.933,0.706-3.783,0.071-25.567,0.724
+						c-24.317,0.728-0.882-2.591-24.068,3.551c-24.228,6.418-5.35-1.298-23.187,6.142c-18.301,7.633-16.67,7.186-16.704,10.685
+						c-0.034,3.499-3.057-4.884-0.034,3.499c3.023,8.381,3.037-3.871,3.023,8.381c-0.015,12.252,6.696,4.557,1.678,12.373
+						c-5.017,7.813-3.831,7.91-0.179,8.543c17.017,2.953,4.157,4.378,17.427,3.175"/>
+					<path i:knockout="Off" d="M156.605,114.92l-13.936,0.381l-11.633,0.343c-10.646,0.319-11.973-0.155-12.021-0.175l-0.599-0.238
+						l-0.577,0.514l0.049-0.047c-0.118,0.09-1.43,0.957-11.145,3.53c-9.989,2.646-12.812,2.931-13.421,2.704
+						c-0.822-0.306-0.821-0.306-7.791,2.604l-2.104,0.878c-16.037,6.689-17.342,7.324-17.342,10.316c0,0.019,0.001,0.041,0.001,0.06
+						c-0.224-0.108-0.459-0.199-0.787-0.04c-0.357,0.173-0.565,0.275-0.565,0.672c0,0.557,0.411,1.697,1.399,4.438
+						c0.924,2.561,1.71,3.671,2.714,3.833c0.083,0.014,0.164,0.02,0.241,0.02c0.007,0.584,0.01,1.339,0.01,2.313
+						c0,0.561-0.001,1.902-0.001,1.916c0,6.908,2.176,8.105,3.347,8.749c0,0,0.075,0.045,0.151,0.09
+						c-0.095,0.332-0.47,1.1-1.661,2.955c-2.509,3.908-3.516,5.931-3.516,7.303c0,0.358,0.068,0.671,0.196,0.962
+						c0.544,1.237,1.926,1.477,3.677,1.78l0.135,0.023c8.138,1.412,9.14,2.422,9.568,2.854c0.923,0.931,1.511,0.928,7.224,0.413
+						c0.06,0.014,0.102,0.068,0.165,0.071c2.167,0.105,16.131,3.138,17.087,5.288c1.147,2.578,16.416,4.228,29.023,5.159
+						l0.115,0.009c0,0,35.523-5.548,35.896-5.606c0.345,0.078,4.927,1.11,4.927,1.11l7.3,0.319c0,0,8.927,0.818,9.139,0.837
+						c0.202,0.064,9.854,3.142,10.006,3.19c0.143,0.073,6.368,3.251,6.368,3.251l2.398-2.719l-0.296-5.911l-4.213-7.526
+						l-0.232-0.137c-0.9-0.532-22.073-13.047-23.303-13.72c-0.001,0-0.735-0.38-0.735-0.38c-1.48-0.752-4.238-2.151-5.404-3.85
+						c-1.357-1.982-2.451-3.729-3.355-5.268c0.022-0.064,0.104-0.296,0.104-0.296c1.193-3.402,2.576-7.619,2.576-8.885
+						c0-0.063-0.004-0.118-0.011-0.165c-0.012-0.083-0.017-0.204-0.017-0.356c0-0.909,0.194-2.911,0.363-4.307
+						c0.072-0.205,2.46-7.013,2.46-7.013l-0.076-0.294c-0.146-0.566-1.468-5.584-2.9-7.532
+						C173.721,116.784,158.242,114.874,156.605,114.92z M131.097,117.643l11.614-0.342l13.951-0.382
+						c2.575-0.073,16.104,2.238,17.336,3.614c0.956,1.3,2.058,4.938,2.49,6.549c-0.188,0.536-2.33,6.642-2.33,6.642l-0.013,0.107
+						c-0.073,0.592-0.387,3.224-0.387,4.658c0,0.258,0.011,0.477,0.034,0.639c-0.006,0.493-0.768,3.026-1.659,5.709
+						c-2.14-4.566-2.792-4.606-3.242-4.629l-0.62-0.031l-0.354,0.571c-0.069,0.124-0.102,0.29-0.102,0.492
+						c0,2.273,4.134,9.172,6.993,13.346c1.456,2.12,4.509,3.669,6.149,4.501l0.682,0.353c1.138,0.622,20.813,12.25,23.011,13.549
+						c0.239,0.427,3.513,6.275,3.721,6.647c0.02,0.393,0.199,3.971,0.231,4.629c-0.23,0.262-0.472,0.535-0.832,0.944
+						c-1.07-0.546-5.132-2.619-5.132-2.619l-10.369-3.306l-9.404-0.86c0,0-6.995-0.307-7.169-0.315
+						c-0.168-0.038-5.124-1.155-5.124-1.155s-35.814,5.594-36.044,5.63c-12.419-0.922-25.993-2.687-27.285-4.058
+						c-1.366-3.097-13.245-5.574-17.517-6.211c-0.203-0.212-0.479-0.346-0.793-0.318c-3.083,0.28-5.996,0.544-6.4,0.369
+						c0-0.003-0.12-0.117-0.12-0.117c-0.703-0.708-1.879-1.895-10.646-3.416l-0.135-0.023c-0.827-0.143-2.075-0.359-2.188-0.614
+						c-0.021-0.048-0.033-0.111-0.033-0.193c0-0.592,0.632-2.179,3.205-6.187c1.488-2.318,2.024-3.388,2.024-4.188
+						c0-0.15-0.019-0.291-0.054-0.428c-0.181-0.712-0.758-1.03-1.179-1.261c-0.865-0.476-2.311-1.271-2.311-6.993
+						c0-0.014,0.001-1.098,0.001-1.56c0-4.969-0.065-4.992-0.833-5.258c-0.424-0.146-0.816,0.001-1.178,0.377
+						c-0.208-0.289-0.558-0.898-1.073-2.324c-0.205-0.568-0.385-1.068-0.542-1.506c0.587-0.423,0.632-1.277,0.636-1.644
+						l-0.014-0.825c-0.004-0.119-0.007-0.231-0.007-0.338c0-1.702,0.899-2.264,16.109-8.608l2.105-0.878
+						c4.165-1.739,5.948-2.482,6.375-2.562c0.817,0.296,2.292,0.597,14.579-2.658c8.169-2.164,10.697-3.187,11.58-3.704
+						C120.451,117.773,124.529,117.84,131.097,117.643z"/>
+				</g>
+				<g i:knockout="Off">
+					<path i:knockout="Off" fill="#FFFFFF" d="M155.146,147.929c4.879-9.398-5.344-20.199-12.65-21.176
+						c-12.05-1.61-13.404,10.426-13.684,21.258c3.73,2.016,8.915,3.425,11.721,6.534"/>
+					<path i:knockout="Off" d="M133.446,127.979c-4.599,3.921-5.426,11.933-5.635,20.006l-0.017,0.654l4.415,2.067
+						c2.849,1.244,5.793,2.529,7.581,4.509c0.371,0.41,1.004,0.442,1.412,0.072c0.219-0.197,0.33-0.469,0.33-0.743
+						c0-0.239-0.084-0.479-0.258-0.67c-2.076-2.299-5.222-3.673-8.266-5.001c0,0-2.377-1.112-3.174-1.486
+						c0.223-7.385,1.021-14.572,4.909-17.887c1.892-1.614,4.386-2.189,7.621-1.757c4.143,0.554,9.086,4.472,11.5,9.113
+						c1.348,2.591,2.51,6.535,0.395,10.611c-0.254,0.49-0.064,1.093,0.426,1.348c0.49,0.254,1.094,0.063,1.35-0.427
+						c1.959-3.775,1.818-8.199-0.395-12.456c-2.732-5.251-8.203-9.53-13.012-10.172C138.853,125.257,135.763,126,133.446,127.979z"
+						/>
+				</g>
+				<g i:knockout="Off">
+					<path i:knockout="Off" d="M154.077,146.278c-2.156,1.18-4.24,2.619-6.256,4.01c-3.635,2.509-7.068,4.878-10.941,5.924
+						c-2.991,0.808-6.055,1.058-9.3,1.324c-3.222,0.263-6.553,0.536-9.783,1.406c-2.027,0.546-4.117,1.397-6.137,2.221
+						c-3.491,1.423-7.102,2.895-10.528,2.866c-0.552-0.005-1.004,0.439-1.009,0.991s0.439,1.004,0.991,1.009
+						c3.828,0.033,7.627-1.516,11.301-3.014c2.054-0.837,3.994-1.628,5.902-2.142c3.054-0.823,6.292-1.088,9.425-1.344
+						c3.191-0.261,6.492-0.531,9.659-1.386c4.205-1.135,7.941-3.714,11.557-6.208c1.973-1.362,4.014-2.771,6.08-3.901
+						c0.484-0.265,0.662-0.873,0.396-1.357S154.562,146.013,154.077,146.278z"/>
+				</g>
+				<g i:knockout="Off">
+					<path i:knockout="Off" d="M156.458,153.549c-2.619,0.064-5.709,0.812-8.98,1.604c-4.279,1.035-8.701,2.104-11.902,1.536
+						c-0.543-0.096-1.063,0.267-1.159,0.81c-0.097,0.544,0.267,1.063,0.81,1.16c3.613,0.641,8.24-0.481,12.72-1.562
+						c3.166-0.766,6.154-1.489,8.561-1.548c5.664-0.141,7.961,0.698,13.508,2.724c0.518,0.189,1.094-0.077,1.281-0.596
+						c0.189-0.519-0.076-1.091-0.596-1.282C165.069,154.337,162.501,153.399,156.458,153.549z"/>
+				</g>
+			</g>
+		</g>
+		<g id="textSurface" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFFFFFF4F00">
+			<g id="spokenBubble" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFF4F00FFFF">
+				<path id="textContainer" i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M225.719,45.306c0-6.627,5.373-12,12-12h181.333
+					c6.627,0,12,5.373,12,12V150.64c0,6.627-5.373,12-12,12H237.719c-6.627,0-12-5.373-12-12V45.306z"/>
+				<path id="textArrowBelow" i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M249.052,160.639
+					c-0.775,14.251-1.676,18.525-9.1,30.565c9.705-0.79,21.952-21.605,25.1-30.045"/>
+			</g>
+			<g id="thoughtBubble" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#FFFF4F00FFFF" display="none">
+				<path id="textContainer_1_" i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M202.698,21.089
+					c19.686-26.45,59.686-24.45,79.747-0.084c2.697,1.349,5.571,1.709,7.472,0.781c15.28-13.888,33.272-14.043,49.893-7.839
+					c2.771,1.034,5.478,2.219,8.031,3.421c28.543-21.729,75.543-10.729,83.166,27.658c0,0-1.324,3.889,1.165,6.603
+					c18.212,11.011,26.212,32.011,22.212,53.011c-1,5.333-3.223,9.667-6.037,13.52c-2.814,3.854-1.381,0-2.613-0.591
+					c-1.35-0.929-3.35-0.929-4.35-1.929c16,7,27,22,30,39c2,21-8,41-27,50c-16,7.5-32.5,5.5-45.745-2.556
+					c-2.532-1.384-4.229-1.856-5.336-1.551c-1.919,0.107-3.919,2.107-5.919,2.107c4-1,6-5,10-6c-15,11-35,12-52,3c-13-7-20-20-24-34
+					c1,5,3,9,3.299,13.505c-0.397,0.708-3.423,2.219-6.655,3.466c-22.627,8.729-49.423,1.729-65.241-19.971
+					c-3.453,0-6.263,0.589-8.723,0.879c-17.3,3.2-32.381-7.709-40.771-22.689c-1.678-2.996-3.089-6.153-4.195-9.396
+					c-15.714-7.795-29.714-18.795-33.714-37.795c-5-25,11-45,29.842-57.667c0.719-2.335,1.697-4.636,3.006-6.896
+					C201.159,23.306,202.698,21.089,202.698,21.089z"/>
+				<g i:knockout="Off" display="inline">
+					<path i:knockout="Off" fill="#FFFFFF" d="M269.719,186.306c0,4.602-4.179,8.333-9.333,8.333c-5.155,0-9.334-3.731-9.334-8.333
+						c0-4.603,4.179-8.333,9.334-8.333C265.54,177.973,269.719,181.704,269.719,186.306z"/>
+					<g>
+						<path i:knockout="Off" fill="none" d="M269.719,186.306c0,4.602-4.179,8.333-9.333,8.333c-5.155,0-9.334-3.731-9.334-8.333
+							c0-4.603,4.179-8.333,9.334-8.333C265.54,177.973,269.719,181.704,269.719,186.306z"/>
+						<path i:knockout="Off" fill="#FFFFFF" d="M268.225,186.165c-0.564,8.736-13.982,9.286-15.633,0.853
+							c-1.785-9.125,15.017-10.254,15.649-0.451c0.125,1.929,3.078,1.388,2.955-0.521c-0.814-12.597-20.828-12.412-21.639,0.119
+							c-0.827,12.813,20.831,13.028,21.655,0.283C271.337,184.518,268.35,184.235,268.225,186.165z"/>
+					</g>
+				</g>
+				<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M260.386,188.306c0,3.498-2.985,6.333-6.667,6.333
+					s-6.667-2.835-6.667-6.333c0-3.498,2.985-6.333,6.667-6.333S260.386,184.808,260.386,188.306z"/>
+				<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M238.386,196.973c0,1.289-1.045,2.333-2.334,2.333
+					c-1.288,0-2.333-1.045-2.333-2.333s1.045-2.333,2.333-2.333C237.341,194.639,238.386,195.684,238.386,196.973z"/>
+				<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M285.719,179.973c0,4.602-4.253,8.333-9.5,8.333
+					s-9.5-3.731-9.5-8.333c0-4.603,4.253-8.333,9.5-8.333S285.719,175.371,285.719,179.973z"/>
+			</g>
+			<g id="yellBubble" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#FFFF4F00FFFF" display="none">
+				<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M251.156,176.051
+					l40.228-15.992"/>
+				<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M280.932,149.385
+					l-40.667,36.42"/>
+				<path id="textContainer_2_" i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M217.778,34.643
+					c8.609,6.684,9.952,3.684,7.987-5.785c6.308,5.125,9.308,3.782,10.188-4.309c2.433,8.091,5.266,8.091,9.12-1.703
+					c6.063,9.793,13.146,9.793,24.043,3.878c6.103,5.915,16.02,5.915,20.094-4.64c17.178,10.555,28.511,10.555,45.233-5.505
+					c5.941,16.06,17.273,16.06,18.835,1.458c19.688,14.603,29.605,14.603,46.749-17.802c-0.144,32.405,6.939,32.405,29.26,16.182
+					c-12.403,16.223-9.57,16.223,4.813,6.576c-11.07,9.646-8.07,10.99,4.333,9.089c-8.061,6.244-6.717,9.244,2.533,11.068
+					c-9.25,1.489-9.25,5.703-0.315,13.07c-8.935,6.115-8.935,15.385,7.513,10.932c-16.447,24.677-16.447,35.631,14.938,36.553
+					c-31.385,19.303-31.385,28.571-4.39,40.526c-26.995,1.528-26.995,5.741-5.942,17.857c-21.053-8.801-22.396-5.802-9.526,11.916
+					c-17.213-13.374-20.213-12.03-12.048,8.029c-11.479-20.06-14.312-20.06-10.553,3.532c-13.676-23.591-20.759-23.591-29.814-2.664
+					c-7.944-20.927-17.861-20.927-27.072,12.467c-12.039-33.395-23.373-33.395-23.148-1.581
+					c-22.89-31.814-34.224-31.814-61.517-8.479c6.042-23.335-3.874-23.335-11.9-9.703c-8.975-13.632-16.058-13.632-23.926,4.361
+					c-2.049-17.993-4.882-17.993-10.51-1.486c2.314-16.508-0.686-17.851-12.385-5.019c7.356-17.175,6.013-20.176-10.27-7.879
+					c16.283-15.61,16.283-19.824-9.255-12.972c25.538-20.334,25.538-29.603,1.919-46.578c23.619-3.249,23.619-14.204-0.313-25.522
+					c23.933-8.905,23.933-18.175,7.798-37.429C226.385,48.854,226.385,44.64,217.778,34.643z"/>
+			</g>
+		</g>
+	</g>
+</svg>
diff --git a/dojox/gfx/demos/data/LarsDreaming.json b/dojox/gfx/demos/data/LarsDreaming.json
new file mode 100644
index 0000000..e0999bd
--- /dev/null
+++ b/dojox/gfx/demos/data/LarsDreaming.json
@@ -0,0 +1,1823 @@
+[
+	{
+		"name": "torso", 
+		"children": [
+			{
+				"name": "leftArm", 
+				"shape": {
+					"type": "path", 
+					"path": "M156.007,292.675c2.737,1.778,5.563,3.321,8.752,3.946c7.099,1.391,19.25-5.666,23.136-11.698 c1.572-2.441,8.077-21.031,11.178-14.271c1.224,2.67-1.59,4-1.399,6.462c3.108-1.425,5.48-5.242,8.918-2.182 c0.672,4.019-4.472,4.343-3.918,7.669c1.376,0.218,5.395-1.595,6.285-0.535c1.707,2.027-2.933,3.561-4.072,4.018 c-1.852,0.741-4.294,1.233-5.988,2.369c-2.636,1.769-4.766,5.144-7.033,7.4c-11.657,11.604-26.184,10.553-40.646,5.515 c-4.713-1.642-17.399-4.472-18.655-9.427c-1.647-6.502,5.523 [...]
+				}, 
+				"fill": "#FFE8B0", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"name": "leftArmThumb", 
+				"shape": {
+					"type": "path", 
+					"path": "M188.257,284.902c-1.932-1.391-3.313-4.206-3.506-6.494c-0.149-1.786,0.59-6.521,3.199-3.95c0.792,0.78,0.083,2.155,0.558,2.943 c0.885,1.47,1.071,0.493,2.748,1.002c1.406,0.426,3.827,2.05,4.251,3.499"
+				}, 
+				"fill": "#FFE8B0", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"name": "rightArm", 
+				"shape": {
+					"type": "path", 
+					"path": "M57.05,283.307c-5.502,5.354-13.185,8.541-18.249,14.221c-4.303,4.827-7.721,11.575-11.138,17.112 c-6.752,10.938-10.794,26.076-19.912,35.185c-3.869,3.866-7.637,5.722-7.251,12.032c0.932,0.372,1.548,0.589,2.418,0.683 c0.605-2.745,2.569-4.198,5.362-3.799c-0.14,3.365-3.512,5.941-3.228,9.235c0.364,4.223,3.983,5.968,7.181,2.662 c2.61-2.699,0.192-7.849,3.338-10.18c5.535-4.103,2.889,2.998,4.13,5.515c5.19,10.519,8.634-1.859,7.35-7.996 c-2.336-11.159-3.003-15.126,3.267-24.416c6.358-9.41 [...]
+				}, 
+				"fill": "#FFE8B0", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"name": "shirt", 
+				"children": [
+					{
+						"name": "tShirt", 
+						"shape": {
+							"type": "path", 
+							"path": "M96.509,268.265 c-2.301,0.323-4.69,0.205-6.945,0.72c-2.234,0.509-4.5,0.8-6.749,1.249c-4.369,0.872-8.206,3.265-12.3,5.024 c-3.259,1.4-6.644,2.57-9.763,4.26c-1.923,1.041-3.688,2.616-5.487,3.97c-1.543,1.16-3.495,2.11-4.854,3.563 c-2.205,2.354,0.896,7.407,1.854,9.873c0.92,2.367,2.149,4.819,2.749,7.29c0.228,0.937,0.235,2.058,0.875,2.872 c0.644,0.821,0.64,0.735,1.822,0.049c1.513-0.878,2.873-1.993,4.329-2.993c2.431-1.67,5.462-2.849,7.434-5.111 c-3.335,1.652-5.335,4.679-6.931,8.0 [...]
+						}, 
+						"fill": "#4459A5", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round"
+						}
+					}, 
+					{
+						"name": "shirtNeck", 
+						"shape": {
+							"type": "path", 
+							"path": "M99.759,268.89 c-0.984,0.151-1.746-0.549-2.75-0.5c-1.369,0.065-1.649,0.872-2.153,2c-1.037,2.325-2.442,4.974,0.064,6.945 c2.53,1.991,6.964,1.718,9.829,0.804c1.616-0.517,3.045-1.24,3.825-2.867c0.508-1.062,0.935-2.771,0.149-3.598 c-0.231-0.243-0.562-0.376-0.84-0.534"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round"
+						}
+					}, 
+					{
+						"name": "shirtLogo", 
+						"children": [
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M104.864,296.921c-0.151-0.004,7.101,0.409,7.052,0.403c0.132,0.028-0.172,0.633-0.021,0.632 c-0.226,0.028-7.244-0.454-7.28-0.464C104.657,297.519,104.776,296.904,104.864,296.921z"
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}, 
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M90.071,295.919c-0.199,0.005,6.792,0.431,6.79,0.446c0.153,0.005-0.031,0.663,0.012,0.665 c0.272,0.016-6.79-0.471-6.875-0.459C89.881,296.561,89.796,295.899,90.071,295.919z"
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M84.407,306.477c0.2-0.159,0.322-1.04,0.254,0.057c-0.542-0.355-2.02,2.083-4.215,2.001 c-1.887-1.706-4.559-3.384-4.302-7.092c0.652-2.599,3.082-4.084,5.213-3.942c1.889,0.378,2.899,0.717,4,1.318 c-0.497,0.957-0.175,0.866-0.459,0.703c0.456-2.398,0.598-5.75,0.312-7.855c0.594-0.554,0.714,0.125,1.249,0.941 c0.502-0.727,0.509-1.425,0.875-0.571c-0.207,1.328-0.809,7.187-0.711,10.174c-0.126,2.798-0.375,4.354-0.051,4.985 c-0.718,0.613-0.667,1.006-0.981,1.381c-0.72-1.33-1.056-0.132-1 [...]
+								}, 
+								"stroke": {
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M93.321,297.767c2.592,0.147,5.688,2.314,5.696,5.627c-0.611,4.576-3.69,5.316-6.158,5.581 c-2.68-0.76-5.708-1.872-5.413-6.472C88.086,299.395,90.653,297.875,93.321,297.767z M92.939,307.46 c2.531,0.735,3.706-1.297,3.666-3.935c0.114-2.219-0.641-4.584-3.389-4.896c-2.29-0.553-3.366,2.188-3.661,4.688 C89.339,305.265,89.934,307.95,92.939,307.46z"
+								}, 
+								"stroke": {
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M99.688,303.916c0.03-1.511,0.055-4.73,0.022-4.646c0.481-1.355,0.658-0.556,1.034-1.297 c0.263,1.473,0.653,0.326,1.186,0.065c-0.386,2.518-0.513,3.348-0.574,4.949c-0.068-0.47-0.128,2.28-0.238,2.188 c-0.055,1.935-0.036,2.201-0.047,4.219c-0.079,0.914-0.28,2.412-1.126,3.831c-0.61,1.212-1.73,1.146-3.24,1.651 c0.073-0.945-0.065-1.242-0.096-1.822c0.098,0.138,0.213,0.604,0.225,0.397c1.892,0.229,2.209-1.896,2.362-3.365 c0.042,0.304,0.512-6.934,0.415-7.062C99.73,302.637,99.75,303.1 [...]
+								}, 
+								"stroke": {
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M108.115,298.791c3.028-0.066,5.283,1.359,5.256,5.758c-0.264,3.479-3.366,4.63-5.883,5.119 c-2.429-0.033-5.619-2.24-5.16-5.811C102.322,300.085,105.715,298.846,108.115,298.791z M107.351,309.232 c2.675-0.132,3.839-2.333,3.841-4.497c0.246-2.344-0.263-4.833-2.923-5.396c-2.844,0.299-3.974,1.917-4.053,4.479 C104.136,306.655,104.854,308.372,107.351,309.232z"
+								}, 
+								"stroke": {
+								}
+							}
+						]
+					}
+				]
+			}
+		]
+	}, 
+	{
+		"name": "heads", 
+		"children": [
+			{
+				"name": "head1", 
+				"children": [
+					{
+						"name": "leftEart", 
+						"children": [
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M201.557,195.475 c7.734-4.547,16.592-5.012,18.405,4.443c2.43,12.659-3.317,13.328-14.598,13.328"
+								}, 
+								"fill": "#FFE8B0", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M211.711,203.09 c0.523,0.004,0.946-0.208,1.271-0.635"
+								}, 
+								"fill": "#FFE8B0", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M211.076,197.377 c3.062,3.013,5.489,5.624,4.442,10.155"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "bgHairTop", 
+						"shape": {
+							"type": "path", 
+							"path": "M54.384,199.307c-5.253-4.402-7.511-11.061-15.779-10.632c3.449-1.277,7.116-2.397,10.911-2.666 c-2.873-1.397-5.865-2.575-8.231-4.718c3.986-1.119,11.47-1.817,14.864,0.75c-5.183-2.758-8.397-7.816-13.062-10.598 c6.014-0.643,12.377,0.978,18.022,2.265c-2.547-4.486-6.682-10.83-10.523-14.297c5.033,1.052,10.647,4.518,15.062,7.177 c-1.614-4.176-5.634-8.406-7.859-12.513c10.312-1.125,12.522,4.919,19.7,9.932c-0.412-0.127-1.114-0.113-1.527,0.015 c0.875-7.261,3.058-12.8,8.258-18.566c6.77 [...]
+						}, 
+						"fill": "#FFF471", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"name": "bgHairLeft", 
+						"shape": {
+							"type": "path", 
+							"path": "M92.384,243.973c-6.334,7.929-12.601,12.241-22.465,15.361c3.65-1.263,7.735-5.859,7.695-9.928 c-2.208,0.218-4.49,0.605-6.498,1.098c1.244-1.098,2.087-3.239,3.198-4.396c-5.77,0.001-12.131,1.133-18.396,1.23 c5.013-2.81,10.665-3.25,12.398-9.247c-3.59,0.313-7.233,1.606-11.033,1.097c1.731-2.022,3.953-3.995,5.049-6.447 c-3.781,0.056-6.665,3.098-10.547,2.465c0.962-2.863,3.187-5.208,4.531-7.766c-5.59-0.273-11.658,2.45-17.732,2.564 c5.494-2.857,8.967-7.819,12.3-12.718c5.233-7.693,10. [...]
+						}, 
+						"fill": "#FFF471", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"name": "bgHair", 
+						"shape": {
+							"type": "path", 
+							"path": "M142.384,255.307c2.984,6.076,3.567,11.855,10.531,14.6c-0.134-3.114-0.094-6.664,1.619-9.033 c1.604,1.969,3.122,4.211,5.048,5.698c-0.29-1.769,0.412-4.023,0.233-5.828c3.444,0.261,4.979,3.965,8.468,4.479 c0.065-2.78,0.427-5.151,0.868-7.813c2.687,0.2,4.768,1.565,7.132,2.997c0.452-4.921-0.409-10.579-0.667-15.666 c-5.795-0.756-12.291,2.827-17.899,3.899c-4.414,0.844-14.136,0.523-15.333,6"
+						}, 
+						"fill": "#FFF471", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"name": "neck", 
+						"shape": {
+							"type": "path", 
+							"path": "M106.989,254.499c-2.932,6.063-4.613,11.997-8.947,17.138c7.288,10.194,16.311-10.9,15.183-17.026 c-1.926-1.138-3.928-1.589-6.236-1.38"
+						}, 
+						"fill": "#FFE8B0", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"name": "headShape", 
+						"shape": {
+							"type": "path", 
+							"path": "M210.941,207.666c-0.844,3.985-2.081,7.982-3.77,11.783c-3.374,7.604-8.543,14.427-16.052,18.899 c-2.94,2.13-5.983,4.167-9.109,6.085c-25.013,15.342-55.353,23.08-82.254,10.57c-3.433-1.558-6.785-3.432-10.053-5.66 c-1.821-1.185-3.592-2.46-5.308-3.832c-1.715-1.373-3.375-2.842-4.972-4.412c-2.352-2.148-4.576-4.425-6.631-6.814 c-6.168-7.169-10.823-15.358-12.87-24.185c-0.649-3.284-0.84-6.634-0.5-9.975c4.48-13.743,14.22-24.364,26.109-32.149 c2.973-1.946,6.079-3.715,9.271-5.309c30.581 [...]
+						}, 
+						"fill": "#FFE8B0", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"name": "rightEar", 
+						"children": [
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M64.857,195.606 c-6.59-7.181-15.047-10.664-19.467,3.676c-1.235,4.007-1.87,14.468,1.29,17.786c4.223,4.435,13.591,0.529,19.055-0.015"
+								}, 
+								"fill": "#FFE8B0", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M52.407,196.744 c-1.702,3.613-1.257,7.505-1.27,11.424"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M51.772,209.438 c-3.39-4.661,0.922-5.769,5.078-6.347"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "fgHair", 
+						"shape": {
+							"type": "path", 
+							"path": "M90.384,154.64c8.453-11.353,15.678-13.458,28.581-15.915c-1.382,3.376-3.89,7.352-5.179,11.16 c5.01-1.816,9.571-6.545,15.218-8.413c11.355-3.755,23.853-1.903,35.671-2.213c-3.004,3.712-4.912,7.88-2.025,11.447 c5.855-2.212,13.369-6.871,19.635-6.646c0.263,4.561-0.024,9.278,0.201,13.841c3.509-1.201,6.015-3.04,8.276-5.148 c2.263-2.108,3.761-4.049,4.942-5.2c1.063,2.408,2.134,5.334,2.24,8.494c-0.183,3.462-0.866,6.794-2.66,9.291 c3.663,0.65,6.098-2.021,8.35-4.479c-0.655,4.349-3.164, [...]
+						}, 
+						"fill": "#FFF471", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}
+				]
+			}
+		]
+	}, 
+	{
+		"name": "eyes", 
+		"children": [
+			{
+				"name": "eyes1", 
+				"children": [
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M123.163,176.668 c-5.066,1.17-9.01,7.888-13.666,10.335c-4.238,2.227-8.648,6.636-7.009,12.332c1.971,6.848,12.042,3.991,16.261,1.165 c5.282-3.539,9.59-8.517,12.006-14.524c1.523-3.787,2.568-7.272-1.509-9.391c-2.905-1.51-8.174-1.386-11.417-0.583"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M182.545,179.865 c-3.533,0.169-4.854-1.166-8.408-0.001c-3,0.983-6.239,1.936-8.852,3.743c-3.938,2.725-7.46,5.555-4.73,13.592 c1.974,5.811,8.791,7.571,14.656,6.667c5.537-0.854,9.078-4.977,11.408-10.007c3.666-7.918,0.942-11.639-6.742-13.659"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M108.829,183.668c-1.308-1.03-4.557,0.011-5.6-1.733 c-1.056-1.765,1.735-5.409,2.984-6.192c5.684-3.562,15.946-0.39,19.95-6.742"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M163.877,167.198c2.369,1.282,6.539,0.307,9.408,0.815 c3.449,0.612,7.065,2.657,10.592,2.851"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M127.496,192.002c-4.917-2.12-9.188-1.708-8.608,4.942 c3.132,1.734,5.428-2.82,7.275-4.942"
+						}, 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M174.852,203.144c-0.293,0.12-0.307,0.577-0.942,0.282 c-1.605-3.188-0.404-6.507,2.676-8.192c2.15-1.176,5.67-1.759,7.471,0.359c0.199,0.234,0.412,0.521,0.515,0.813 c0.229,0.649-0.285,0.95-0.285,0.95s-3.988,6.009-3.285,1.934c0.438,1.743-5.537,5.743-2.287,1.653 c-1.955,2.583-2.524,1.977-3.859,2.868"
+						}, 
+						"stroke": {
+							"color": "#000000"
+						}
+					}
+				]
+			}, 
+			{
+				"name": "eyes2", 
+				"children": [
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M98.668,186.108c0.668-8.915,15.545-13.749,22.667-15"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M169.667,178.108c5.307,3.436,16.928,5.632,19.668,12.333"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M105.334,197.775c8.085-4.283,17.059-2.8,25-6.333"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M164.001,198.775c4.656-0.417,9.664,1.805,14.334,2.017 c3.951,0.18,5.773,0.189,9,2.316"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M124.001,188.108c3.039-0.258,4.594,2.571,5.301,4.983 c-1.096,1.242-2.065,2.646-2.968,4.017"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M168.335,194.108c-1.77,2.293-4.869,3.271-6.299,5.91 c1.377,0.991,3.02,2.122,3.965,3.424"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}
+				]
+			}
+		]
+	}, 
+	{
+		"name": "beard", 
+		"children": [
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M96.05,213.64 c-0.366,0.21-0.783,0.389-1.167,0.5"
+				}, 
+				"fill": "#AFA8A5", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M102.55,211.973 c0.314-0.01,0.554-0.198,0.667-0.5"
+				}, 
+				"fill": "#AFA8A5", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M105.717,208.806 c0.164-0.109,0.336-0.224,0.5-0.333"
+				}, 
+				"fill": "#AFA8A5", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M111.05,207.973 c-0.651-1.81,0.859-2.262,2.333-1.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M117.717,209.806 c1.738,0,3.653,0.369,5.333,0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M132.717,214.473 c0.104-0.21,0.162-0.435,0.167-0.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M139.551,216.973 c0.215-0.175,0.465-0.426,0.666-0.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M144.551,213.306 c0.277-0.056,0.557-0.111,0.833-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M147.884,216.64 c0.195,0.045,0.369-0.013,0.5-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M148.384,214.14 c0.112-0.168,0.223-0.332,0.333-0.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M98.217,219.306c1.697-1.772,4.233-2.109,5.967-4.046c1.519-1.696,3.812-3.001,4.2-5.454"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M152.717,216.14 c0.611,0,1.224,0,1.834,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M160.384,217.473 c0.333,0,0.667,0,1,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M163.217,215.973 c0.321-0.042,0.658-0.175,0.834-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M164.217,218.806 c0.167,0,0.333,0,0.5,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M168.384,217.973 c0.057-0.056,0.111-0.111,0.167-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M169.884,225.806 c0.491-0.397,0.882-0.926,1.167-1.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M172.717,221.973 c0.057,0,0.111,0,0.167,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M171.717,229.806 c0.334,0.075,0.659,0.025,0.834-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M190.051,227.806 c0.163-0.242,0.398-0.423,0.666-0.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M197.384,221.473 c0.258-0.007,0.485-0.125,0.667-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M199.384,214.973 c-0.04-0.333,0.075-0.609,0.333-0.833"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M117.884,257.306 c0.056,0,0.111,0,0.167,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M142.717,252.473 c0.358,0.068,0.71,0.016,1-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M137.884,256.473 c0.277,0,0.557,0,0.833,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M160.884,252.973 c0.366-0.139,0.766-0.402,1-0.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M171.384,250.14 c0.235-0.264,0.476-0.562,0.667-0.834"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M89.384,243.973 c0.537,0.378,1.329,0.876,1.833,1.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M79.05,225.473 c0.087,0.272,0.143,0.55,0.167,0.833"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M73.884,222.64 c0,0.167,0,0.333,0,0.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#AAAAAA", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M72.55,219.806c0.466-0.325,0.875-0.797,1.167-1.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M71.717,211.973c0.422-0.553,0.776-1.305,1-2"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M78.55,214.473c0-0.111,0-0.222,0-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M79.384,218.806c-0.001-0.137,0.055-0.248,0.167-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M80.217,221.14c0.111,0,0.222,0,0.333,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M75.55,226.473c0.103-0.5,0.156-0.977,0.167-1.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M78.55,230.14c0.111,0,0.222,0,0.333,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M83.384,227.64c0.118-0.059,0.215-0.107,0.333-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M81.55,237.14c0.056,0,0.111,0,0.167,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M86.217,233.806c0.056,0,0.111,0,0.167,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M87.884,230.473c0.595-0.181,1.219-0.527,1.833-0.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"width": "2", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M88.717,222.14 c-0.929,2.359-1.615,4.865-2.667,7.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M89.05,216.14 c0.784-0.736,1.709-1.565,2.833-1.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M94.217,210.14 c1.599-0.089,3.199-0.167,4.833-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M94.884,224.64 c0.052-0.588-0.004-1.155-0.167-1.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M92.384,228.306 c0.585-0.062,1.244-0.132,1.667-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M88.717,240.14 c0.111,0,0.222,0,0.333,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M95.884,243.306 c0.526,0.1,1.017-0.016,1.333-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M98.55,248.306 c0.069-0.24,0.265-0.926,0.333-1.166"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M96.55,249.806 c0.125,0.014,0.18-0.042,0.167-0.166"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M104.55,250.14 c0.01-0.238,0.126-0.428,0.333-0.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M106.884,251.973 c0.195,0.045,0.37-0.014,0.5-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M113.884,254.806 c0.758-0.586,1.595-1.171,2.382-1.774c0.072,0.376,0.418,0.686,0.48,1.079c0.833,0.265,1.624-0.021,1.638-0.971"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M122.217,254.64 c0.063-0.165,0.179-0.288,0.333-0.334"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M125.884,255.806 c1.13-0.745,2.783-0.962,3.667-2"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M132.217,255.973 c0.638-0.492,1.104-1.173,1.141-1.976c-1.11,0.063-1.449-0.888-1.475-1.857"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M129.717,249.306 c-0.045,0.153-0.168,0.271-0.333,0.334"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M136.551,252.306 c0.223,0,0.444,0,0.666,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M110.217,251.306 c0.056-0.057,0.111-0.11,0.167-0.166"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M140.717,251.806 c0.111,0,0.224,0,0.334,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M150.051,249.473 c0.111,0,0.223,0,0.333,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M143.217,255.473 c1.022-0.313,1.725-1.175,2.646-1.654c0.203,0.321,0.439,0.626,0.521,0.987"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M152.217,253.473 c0.165-0.063,0.288-0.179,0.334-0.333"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M155.051,254.64 c0.223,0,0.444,0,0.666,0"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M157.717,256.473 c0.326-0.027,0.546-0.073,0.834-0.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M163.217,252.64 c0.552-0.892,2.082-1.512,2.341-2.334c0.37-1.178-1.155-3.069-1.007-4.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M167.384,235.973 c0.118-0.54,0.354-1.064,0.667-1.5"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M170.717,242.806 c0-0.333,0-0.667,0-1"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M170.217,236.973 c0-0.333,0-0.667,0-1"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M179.051,235.806 c0.378-0.101,0.738-0.35,1-0.667"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M185.051,232.806 c0.379-0.319,0.656-0.702,0.833-1.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M188.051,231.14 c0.063-0.39,0.178-0.792,0.333-1.167"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M197.884,223.306 c-0.166,0.277-0.334,0.556-0.5,0.833"
+				}, 
+				"fill": "none", 
+				"stroke": {
+					"color": "#000000", 
+					"cap": "round", 
+					"join": "bevel"
+				}
+			}
+		]
+	}, 
+	{
+		"name": "mouths", 
+		"children": [
+			{
+				"name": "mouth1", 
+				"children": [
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M177.122,216.821c-0.515,2.282-5.213,3.21-7.434,3.854 c-3.254,0.945-6.596,1.345-9.895,1.851c-3.26,0.5-6.665,0.671-10.107,0.671c-3.596,0-6.645,0.559-10.106,0.671 c-3.105,0.1-6.898-0.474-9.694-1.3c-3.527-1.043-6.672-1.666-10.096-3.062c-2.823-1.152-5.746-1.876-8.462-3.143 c-2.594-1.209-6.084-1.994-8.221-3.552c-1.068,1.834-5.867,3.748-8.1,4.546c-2.444,0.874-8.881,2.725-7.817,5.512 c0.457,1.195,1.948,2.273,2.63,3.385c0.774,1.261,1.139,2.601,2.057,3.859c1.83,2.5,4.506,4.773,6,7. [...]
+						}, 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M135.25,241.319 c0.723-4.757-10.487-8.47-14.898-9.526c-3.09-0.74-6.68-1.17-9.858-1.712c-2.758-0.47-6.865-0.836-9.437,0.369 c-1.385,0.649-2.843,1.724-4.141,2.513c2.156,3.964,4.728,8.861,9.468,11.506c3.229,1.801,5.511,0.776,8.859,0.373 c3.045-0.369,6.046-0.703,9.029-1.721c3.479-1.186,7.228-2.385,10.978-2.475"
+						}, 
+						"fill": "#FFC0C0", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M148.656,225.547c1.267,0.697,1.301,2.838,0.671,3.9 c-0.702,1.182-2.063,1.4-3.307,2.01c-2.271,1.116-4.58,2.624-7.481,2.638c-4.619,0.023-2.144-4.067-0.253-5.869 c2.405-2.292,5.057-2.72,8.72-2.512c0.588,0.034,1.095,0.041,1.65,0.168"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M130.299,223.365 c2.687,0.437,5.619,4.384,3.727,6.422c-1.234,1.33-7.94,1.391-9.915,1.296c-4.896-0.233-2.502-2.445-0.613-4.525 c1.604-1.767,5.088-3.249,7.833-3.36"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M113.178,217.157 c2.56,0.958,4.922,5.057,5.352,7.215c0.377,1.885-0.324,2.106-2.526,2.643c-1.366,0.333-3.636,0.723-5.105,0.385 c-2.506-0.577-5.883-5.051-4.909-7.223c1.03-2.298,5.944-2.923,8.427-2.852"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M99.359,217.662 c2.038,0.432,4.015,4.279,2.468,5.625c-1.083,0.943-5.221,1.795-6.799,1.589c-4.032-0.526-2.265-4.102-0.866-5.872 c0.706-0.894,1.049-1.976,2.514-2.186c1.627-0.233,2.501,0.99,3.921,1.346"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M181.815,222.896c-3.102-2.75-4.765-8.777-9.282-10.403"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}
+				]
+			}, 
+			{
+				"name": "mouth2", 
+				"children": [
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M87.57,221.951c5.563-1.759,11.066-1.32,16.694-1.782c2.93-0.24,5.228-1.14,8.309-0.927c3.142,0.217,6.085-0.235,9.289,0.176 c7.136,0.914,13.96,0.598,21.112,1.506c3.654,0.464,7.219,0.609,10.811,0.869c4.017,0.291,7.646,1.582,11.433,2.623 c2.948,0.812,6.347,1.618,9.011,2.99c2.521,1.298,6.354,2.856,8.301,4.72c-2.775,0.027-5.602,2.603-8.021,3.769 c-2.93,1.412-5.741,2.949-8.656,4.432c-5.599,2.849-11.885,5.468-18.104,6.53c-6.793,1.161-13.195,2.107-20.067,2.197 c-7.699,0.102-14.313- [...]
+						}, 
+						"stroke": {
+							"color": "#000000", 
+							"width": "3", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M87.785,228.193 c-5.907-3.235-0.344-9.531,3.971-11.424"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000", 
+							"width": "2"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M184.679,227.229c-1.534,2.583-2.548,5.334-4.024,7.889"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000", 
+							"width": "2", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M106.862,219.528 c-3.071-0.74-5.608,2.166-6.318,4.738c-0.379,1.375-0.494,2.55,0.748,3.337c1.519,0.962,2.905-0.052,4.418-0.332 c2.518-0.467,7.293,0.053,6.461-4.248c-0.568-2.938-3.743-3.682-6.338-3.335c-0.451,0.06-0.758,0.212-1.205,0.229"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M119.764,218.479 c-2.648,1.243-4.657,3.518-5.346,6.377c-0.866,3.594,3.9,3.711,6.356,2.865c2.64-0.91,4.77-3.351,3.299-6.133 c-1.01-1.91-3.979-2.548-6.026-2.823"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M130.388,219.492 c-1.753,1.382-4.069,4.525-4.835,6.61c-1.159,3.156,2.296,3.371,4.868,3.348c3.061-0.028,6.6-1.148,5.022-4.78 c-1.168-2.691-2.552-4.85-5.551-5.241"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M142.954,221.087 c-1.502,0.337-5.418,3.249-5.638,4.997c-0.292,2.311,4.855,4.536,6.854,4.234c2.503-0.377,4.384-3.175,3.167-5.65 c-0.92-1.873-3.36-2.252-4.508-3.932"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M155.354,222.664 c-2.038,0.426-4.212,2.287-4.766,4.444c-0.723,2.821,3.226,3.383,5.458,3.331c2.541-0.059,5.126-1.752,3.249-4.32 c-1.394-1.908-3.707-3.189-5.304-4.636"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M168.367,237.924 c-1.554-1.217-3.302-2.557-5.203-2.976c-2.973-0.654-3.537,2.131-3.377,4.406c0.205,2.913,1.032,3.883,3.901,2.344 c1.987-1.066,4.271-1.997,4.599-4.456"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M151.524,246.202 c-1.912-0.166-4.004-4.491-2.91-6.25c0.771-1.239,5.456-1.688,6.857-1.292c0.271,0.917,0.979,1.841,0.829,2.771 c-0.088,0.54-0.994,1.645-1.296,2.188c-1.08,1.951-2.133,1.866-3.998,2.685"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M145.911,241.458 c-0.209,1.649-0.215,2.702-1.528,3.801c-0.885,0.738-1.772,1.189-2.54,2.1c-0.786,0.933-1.226,2.38-2.792,1.813 c-1.042-0.377-1.959-2.318-2.138-3.312c-0.299-1.676-1.003-5.228,0.783-6.158c1.154-0.603,7.066-0.18,7.43,1.32"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M133.12,238.991 c-1.495-0.087-2.253-1.33-3.918-0.964c-1.42,0.311-2.489,1.354-2.54,2.836c-0.052,1.527,0.99,5.581,1.852,6.956 c2.363,3.771,4.329-1.535,5.516-3.159c1.117-1.525,2.643-2.053,2.271-3.958c-0.318-1.632-1.118-2.047-2.766-2.329 c-0.382-0.065-0.773-0.095-1.158-0.147"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M116.853,237.43 c-1.049,2.211-0.173,5.147,0.047,7.565c0.357,3.93,3.827,2.028,5.831,0.067c1.575-1.541,4.599-4.86,2.209-6.484 c-1.881-1.279-5.727-2.458-7.756-1.107"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M107.455,233.38 c-0.813,2.487-1.704,5.049,0.073,7.364c1.91,2.486,4.009,1.229,5.537-0.939c1.056-1.5,3.316-4.481,1.563-6.017 c-1.347-1.179-6.468-1.518-7.854-0.325"
+						}, 
+						"fill": "#FFFFFF", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}
+				]
+			}, 
+			{
+				"name": "mouth3", 
+				"children": [
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M99.05,218.973c1.691-0.875,3.313-2.39,4.833-3.537c1.231-0.928,2.782-1.671,3.5-3.072c1.846,3.486,7.661,4.669,11.003,6.067 c3.553,1.486,7.174,3.066,10.784,4.166c4.271,1.301,9.277,1.67,13.721,2.343c4.155,0.629,9.979,1.365,14.162,0.496 c1.182-0.245,2.343-1.024,3.462-1.446c0.162,1.905-3.637,3.023-4.933,3.487c-2.435,0.871-4.18,2.541-6.362,3.871 c-1.623,0.989-2.974,1.669-4.755,2.117c-1.77,0.445-3.353,0.806-4.825,1.878c-5.915,4.311-15.264,3.247-22.424,3.13 c-5.384-0.088-6.719-5.3 [...]
+						}, 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M107.217,227.973c1.182-2.033,4.375-2.176,6.5-1.963c2.879,0.289,4.124,1.217,6.168,3.167c1.834,1.749,5.906,5.509,5.64,8.271 c-2.808,0.89-7.847,0.402-10.346-1.104c-1.334-0.804-1.151-2.256-2.246-3.588c-0.712-0.866-1.836-2.673-2.855-3.311 c-0.209-0.94-2.106-1.499-3.028-1.805"
+						}, 
+						"fill": "#F4BDBD", 
+						"stroke": {
+							"color": "#000000", 
+							"cap": "round", 
+							"join": "bevel"
+						}
+					}
+				]
+			}
+		]
+	}, 
+	{
+		"name": "personalProps", 
+		"children": [
+			{
+				"name": "hat", 
+				"children": [
+					{
+						"children": [
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M88.374,173.145c0.474-0.074,16.606,2.725,18.01,5.879 c1.145,2.572,28.184,4.568,28.184,4.568l35.971-5.618l5.024,1.132l7.212,0.315l9.295,0.851l10.188,3.248l5.75,2.935 l1.615-1.832l-0.264-5.27l-3.968-7.087c0,0-22.045-13.031-23.272-13.703c-1.229-0.669-4.941-2.294-6.484-4.542 c-8.584-12.528-8.403-18.05-3.371-6.461c0,0,2.662-7.592,2.521-8.575c-0.144-0.982,0.354-5.031,0.354-5.031l2.396-6.832 c0,0-1.379-5.341-2.738-7.19c-1.356-1.844-15.793-4.078-18.162-4.011c-24.933,0.706-3.7 [...]
+										}, 
+										"fill": "#FF0000", 
+										"stroke": {
+										}
+									}, 
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M156.604,114.92l-13.936,0.381l-11.633,0.343c-10.646,0.319-11.973-0.155-12.021-0.175l-0.599-0.238 l-0.577,0.514l0.049-0.047c-0.118,0.09-1.43,0.957-11.145,3.53c-9.989,2.646-12.812,2.931-13.421,2.704 c-0.822-0.306-0.821-0.306-7.791,2.604l-2.104,0.878c-16.037,6.689-17.342,7.324-17.342,10.316c0,0.019,0.001,0.041,0.001,0.06 c-0.224-0.108-0.459-0.199-0.787-0.04c-0.357,0.173-0.565,0.275-0.565,0.672c0,0.557,0.411,1.697,1.399,4.438 c0.924,2.561,1.71,3.671,2.714,3.833c0.083,0.01 [...]
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}, 
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M155.146,147.93c4.88-9.398-5.344-20.199-12.649-21.176 c-12.05-1.61-13.404,10.426-13.684,21.258c3.73,2.016,8.915,3.425,11.721,6.534"
+										}, 
+										"fill": "#FFFFFF", 
+										"stroke": {
+										}
+									}, 
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M133.446,127.979c-4.599,3.921-5.426,11.933-5.635,20.006l-0.017,0.654l4.415,2.067 c2.849,1.244,5.793,2.529,7.581,4.509c0.371,0.41,1.004,0.442,1.412,0.072c0.219-0.197,0.33-0.469,0.33-0.743 c0-0.239-0.084-0.479-0.258-0.67c-2.076-2.299-5.223-3.673-8.267-5.001c0,0-2.377-1.112-3.174-1.486 c0.223-7.385,1.021-14.572,4.909-17.887c1.892-1.614,4.386-2.189,7.621-1.757c4.143,0.554,9.086,4.472,11.5,9.113 c1.348,2.591,2.51,6.535,0.395,10.611c-0.254,0.49-0.063,1.093,0.426,1.348c0.49, [...]
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}, 
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M154.077,146.278c-2.156,1.18-4.24,2.619-6.256,4.01c-3.636,2.509-7.068,4.878-10.941,5.924 c-2.991,0.808-6.055,1.058-9.3,1.324c-3.222,0.263-6.553,0.536-9.783,1.406c-2.027,0.546-4.117,1.397-6.137,2.221 c-3.491,1.423-7.102,2.895-10.528,2.866c-0.552-0.005-1.004,0.439-1.009,0.991c-0.005,0.552,0.439,1.004,0.991,1.009 c3.828,0.033,7.627-1.516,11.301-3.014c2.054-0.837,3.994-1.628,5.902-2.142c3.054-0.823,6.292-1.088,9.425-1.344 c3.191-0.261,6.492-0.531,9.659-1.386c4.205-1.135,7 [...]
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}, 
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M156.458,153.549c-2.619,0.064-5.709,0.812-8.98,1.604c-4.278,1.035-8.7,2.104-11.901,1.536 c-0.543-0.096-1.063,0.267-1.159,0.81c-0.097,0.544,0.267,1.063,0.81,1.16c3.613,0.641,8.24-0.481,12.72-1.562 c3.166-0.766,6.153-1.489,8.561-1.548c5.664-0.141,7.961,0.698,13.508,2.724c0.519,0.189,1.095-0.077,1.281-0.596 c0.189-0.519-0.076-1.091-0.596-1.282C165.069,154.337,162.501,153.399,156.458,153.549z"
+										}, 
+										"stroke": {
+										}
+									}
+								]
+							}
+						]
+					}
+				]
+			}, 
+			{
+				"name": "textSurface", 
+				"children": [
+					{
+						"name": "spokenBubble", 
+						"children": [
+							{
+								"name": "textContainer", 
+								"shape": {
+									"type": "path", 
+									"path": "M225.719,45.307 c0-6.627,5.373-12,12-12h181.333c6.627,0,12,5.373,12,12v105.334c0,6.627-5.373,12-12,12H237.719c-6.627,0-12-5.373-12-12 V45.307z"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"name": "textArrowBelow", 
+								"shape": {
+									"type": "path", 
+									"path": "M249.052,160.64 c-0.774,14.251-1.676,18.525-9.1,30.565c9.705-0.79,21.952-21.605,25.1-30.045"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "thoughtBubble", 
+						"children": [
+							{
+								"name": "textContainer_1_", 
+								"shape": {
+									"type": "path", 
+									"path": "M202.698,21.089 c19.686-26.45,59.686-24.45,79.747-0.084c2.696,1.349,5.57,1.709,7.472,0.781c15.28-13.888,33.271-14.043,49.893-7.839 c2.771,1.034,5.479,2.219,8.031,3.421C376.384-4.36,423.384,6.64,431.007,45.026c0,0-1.324,3.889,1.165,6.603 c18.212,11.011,26.212,32.011,22.212,53.011c-1,5.333-3.223,9.667-6.037,13.52c-2.813,3.854-1.381,0-2.612-0.591 c-1.351-0.929-3.351-0.929-4.351-1.929c16,7,27,22,30,39c2,21-8,41-27,50c-16,7.5-32.5,5.5-45.745-2.556 c-2.531-1.384-4.229-1.856-5 [...]
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"children": [
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M269.719,186.307c0,4.602-4.179,8.333-9.333,8.333s-9.334-3.731-9.334-8.333 c0-4.603,4.18-8.333,9.334-8.333S269.719,181.705,269.719,186.307z"
+										}, 
+										"fill": "#FFFFFF", 
+										"stroke": {
+										}
+									}, 
+									{
+										"children": [
+											{
+												"shape": {
+													"type": "path", 
+													"path": "M269.719,186.307c0,4.602-4.179,8.333-9.333,8.333s-9.334-3.731-9.334-8.333 c0-4.603,4.18-8.333,9.334-8.333S269.719,181.705,269.719,186.307z"
+												}, 
+												"fill": "none", 
+												"stroke": {
+												}
+											}, 
+											{
+												"shape": {
+													"type": "path", 
+													"path": "M268.225,186.166c-0.563,8.736-13.981,9.286-15.633,0.853 c-1.785-9.125,15.018-10.254,15.649-0.451c0.125,1.929,3.078,1.388,2.955-0.521c-0.814-12.597-20.828-12.412-21.64,0.119 c-0.827,12.813,20.831,13.028,21.655,0.283C271.337,184.519,268.35,184.235,268.225,186.166z"
+												}, 
+												"fill": "#FFFFFF", 
+												"stroke": {
+												}
+											}
+										]
+									}
+								]
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M260.386,188.307c0,3.498-2.984,6.333-6.667,6.333 c-3.682,0-6.667-2.835-6.667-6.333s2.985-6.333,6.667-6.333C257.401,181.974,260.386,184.809,260.386,188.307z"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M238.386,196.974c0,1.289-1.045,2.333-2.334,2.333 c-1.288,0-2.333-1.045-2.333-2.333c0-1.288,1.045-2.333,2.333-2.333C237.341,194.64,238.386,195.685,238.386,196.974z"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M285.719,179.974c0,4.602-4.253,8.333-9.5,8.333 s-9.5-3.731-9.5-8.333c0-4.603,4.253-8.333,9.5-8.333S285.719,175.372,285.719,179.974z"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "yellBubble", 
+						"children": [
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M251.156,176.051l40.228-15.992"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M280.932,149.385l-40.667,36.42"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000", 
+									"cap": "round", 
+									"join": "bevel"
+								}
+							}, 
+							{
+								"name": "textContainer_2_", 
+								"shape": {
+									"type": "path", 
+									"path": "M217.778,34.644 c8.608,6.684,9.951,3.684,7.986-5.785c6.309,5.125,9.309,3.782,10.188-4.309c2.433,8.091,5.266,8.091,9.12-1.703 c6.063,9.793,13.146,9.793,24.043,3.878c6.103,5.915,16.02,5.915,20.094-4.64c17.178,10.555,28.511,10.555,45.233-5.505 c5.94,16.06,17.272,16.06,18.835,1.458c19.688,14.603,29.604,14.603,46.749-17.802c-0.145,32.405,6.938,32.405,29.26,16.182 c-12.403,16.223-9.57,16.223,4.813,6.576c-11.069,9.646-8.069,10.99,4.333,9.089c-8.061,6.244-6.717,9.244,2.533,11.0 [...]
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}
+				]
+			}
+		]
+	}
+]
\ No newline at end of file
diff --git a/dojox/gfx/demos/data/LarsDreaming.svg b/dojox/gfx/demos/data/LarsDreaming.svg
new file mode 100644
index 0000000..bd82204
--- /dev/null
+++ b/dojox/gfx/demos/data/LarsDreaming.svg
@@ -0,0 +1,537 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/">
+	<g id="torso" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F008000FFFF">
+		<path id="leftArm" i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M156.007,292.675c2.737,1.778,5.563,3.321,8.752,3.946c7.099,1.391,19.25-5.666,23.136-11.698
+			c1.572-2.441,8.077-21.031,11.178-14.271c1.224,2.67-1.59,4-1.399,6.462c3.108-1.425,5.48-5.242,8.918-2.182
+			c0.672,4.019-4.472,4.343-3.918,7.669c1.376,0.218,5.395-1.595,6.285-0.535c1.707,2.027-2.933,3.561-4.072,4.018
+			c-1.852,0.741-4.294,1.233-5.988,2.369c-2.636,1.769-4.766,5.144-7.033,7.4c-11.657,11.604-26.184,10.553-40.646,5.515
+			c-4.713-1.642-17.399-4.472-18.655-9.427c-1.647-6.502,5.523-7.999,10.184-6.74C147.658,286.528,151.725,289.892,156.007,292.675z
+			"/>
+		<path id="leftArmThumb" i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M188.257,284.902c-1.932-1.391-3.313-4.206-3.506-6.494c-0.149-1.786,0.59-6.521,3.199-3.95c0.792,0.78,0.083,2.155,0.558,2.943
+			c0.885,1.47,1.071,0.493,2.748,1.002c1.406,0.426,3.827,2.05,4.251,3.499"/>
+		<path id="rightArm" i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M57.05,283.307c-5.502,5.354-13.185,8.541-18.249,14.221c-4.303,4.827-7.721,11.575-11.138,17.112
+			c-6.752,10.938-10.794,26.076-19.912,35.185c-3.869,3.866-7.637,5.722-7.251,12.032c0.932,0.372,1.548,0.589,2.418,0.683
+			c0.605-2.745,2.569-4.198,5.362-3.799c-0.14,3.365-3.512,5.941-3.228,9.235c0.364,4.223,3.983,5.968,7.181,2.662
+			c2.61-2.699,0.192-7.849,3.338-10.18c5.535-4.103,2.889,2.998,4.13,5.515c5.19,10.519,8.634-1.859,7.35-7.996
+			c-2.336-11.159-3.003-15.126,3.267-24.416c6.358-9.419,12.194-18.708,19.399-27.588c1.116-1.375,2.08-2.729,3.333-4"/>
+		<g id="shirt" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFF4F00">
+			<path id="tShirt" i:knockout="Off" fill="#4459A5" stroke="#000000" stroke-linecap="round" d="M96.509,268.265
+				c-2.301,0.323-4.69,0.205-6.945,0.72c-2.234,0.509-4.5,0.8-6.749,1.249c-4.369,0.872-8.206,3.265-12.3,5.024
+				c-3.259,1.4-6.644,2.57-9.763,4.26c-1.923,1.041-3.688,2.616-5.487,3.97c-1.543,1.16-3.495,2.11-4.854,3.563
+				c-2.205,2.354,0.896,7.407,1.854,9.873c0.92,2.367,2.149,4.819,2.749,7.29c0.228,0.937,0.235,2.058,0.875,2.872
+				c0.644,0.821,0.64,0.735,1.822,0.049c1.513-0.878,2.873-1.993,4.329-2.993c2.431-1.67,5.462-2.849,7.434-5.111
+				c-3.335,1.652-5.335,4.679-6.931,8.012c-1.398,2.921-4.482,35.854-5.389,38.947c-0.195,0.003-0.775,0.003-0.749,0.013
+				c20.561,0,41.123-0.069,61.684,0c2.1,0.008,3.607-0.496,5.529-1.252c0.715-0.28,2.257-0.355,2.807-0.744
+				c1.412-0.998-0.094-3.916-0.646-5.303c-1.425-3.579-2.111-37.767-4.726-40.543c1.842,0.058,4.127,1.312,5.938,1.95
+				c1.351,0.478,2.633,1.092,3.956,1.66c1.39,0.597,3.667,1.927,5.168,1.857c0.296-1.872,1.045-3.285,1.839-5.02
+				c0.942-2.061,1.155-4.214,1.528-6.415c0.351-2.07,0.897-3.787,1.938-5.635c0.531-0.942,1.356-1.73,1.693-2.769
+				c-0.443-0.401-1.043-0.906-1.604-1.125c-0.56-0.219-1.292-0.11-1.908-0.33c-1.236-0.438-2.439-1.089-3.668-1.575
+				c-3.773-1.499-7.519-2.983-11.319-4.467c-3.575-1.396-6.977-3.238-10.784-3.871c-1.735-0.289-3.467-0.529-5.073-0.906"/>
+			<path id="shirtNeck" i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" d="M99.759,268.89
+				c-0.984,0.151-1.746-0.549-2.75-0.5c-1.369,0.065-1.649,0.872-2.153,2c-1.037,2.325-2.442,4.974,0.064,6.945
+				c2.53,1.991,6.964,1.718,9.829,0.804c1.616-0.517,3.045-1.24,3.825-2.867c0.508-1.062,0.935-2.771,0.149-3.598
+				c-0.231-0.243-0.562-0.376-0.84-0.534"/>
+			<g id="shirtLogo" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F004F00FFFF">
+				<g i:knockout="Off">
+					<path i:knockout="Off" d="M104.864,296.921c-0.151-0.004,7.101,0.409,7.052,0.403c0.132,0.028-0.172,0.633-0.021,0.632
+						c-0.226,0.028-7.244-0.454-7.28-0.464C104.657,297.519,104.776,296.904,104.864,296.921z"/>
+				</g>
+				<g i:knockout="Off">
+					<path i:knockout="Off" d="M90.071,295.919c-0.199,0.005,6.792,0.431,6.79,0.446c0.153,0.005-0.031,0.663,0.012,0.665
+						c0.272,0.016-6.79-0.471-6.875-0.459C89.881,296.561,89.796,295.899,90.071,295.919z"/>
+				</g>
+				<path i:knockout="Off" d="M84.407,306.477c0.2-0.159,0.322-1.04,0.254,0.057c-0.542-0.355-2.02,2.083-4.215,2.001
+					c-1.887-1.706-4.559-3.384-4.302-7.092c0.652-2.599,3.082-4.084,5.213-3.942c1.889,0.378,2.899,0.717,4,1.318
+					c-0.497,0.957-0.175,0.866-0.459,0.703c0.456-2.398,0.598-5.75,0.312-7.855c0.594-0.554,0.714,0.125,1.249,0.941
+					c0.502-0.727,0.509-1.425,0.875-0.571c-0.207,1.328-0.809,7.187-0.711,10.174c-0.126,2.798-0.375,4.354-0.051,4.985
+					c-0.718,0.613-0.667,1.006-0.981,1.381c-0.72-1.33-1.056-0.132-1.339-0.157C84.632,308.442,84.493,305.791,84.407,306.477z
+					 M81.186,307.177c2.403,0.206,3.734-2.164,3.841-4.223c0.269-2.72-0.896-5.104-3.198-5.04c-1.972,0.438-3.46,2.188-3.331,4.639
+					C78.171,306.266,79.847,306.962,81.186,307.177z"/>
+				<path i:knockout="Off" d="M93.321,297.767c2.592,0.147,5.688,2.314,5.696,5.627c-0.611,4.576-3.69,5.316-6.158,5.581
+					c-2.68-0.76-5.708-1.872-5.413-6.472C88.086,299.395,90.653,297.875,93.321,297.767z M92.939,307.46
+					c2.531,0.735,3.706-1.297,3.666-3.935c0.114-2.219-0.641-4.584-3.389-4.896c-2.29-0.553-3.366,2.188-3.661,4.688
+					C89.339,305.265,89.934,307.95,92.939,307.46z"/>
+				<path i:knockout="Off" d="M99.688,303.916c0.03-1.511,0.055-4.73,0.022-4.646c0.481-1.355,0.658-0.556,1.034-1.297
+					c0.263,1.473,0.653,0.326,1.186,0.065c-0.386,2.518-0.513,3.348-0.574,4.949c-0.068-0.47-0.128,2.28-0.238,2.188
+					c-0.055,1.935-0.036,2.201-0.047,4.219c-0.079,0.914-0.28,2.412-1.126,3.831c-0.61,1.212-1.73,1.146-3.24,1.651
+					c0.073-0.945-0.065-1.242-0.096-1.822c0.098,0.138,0.213,0.604,0.225,0.397c1.892,0.229,2.209-1.896,2.362-3.365
+					c0.042,0.304,0.512-6.934,0.415-7.062C99.73,302.637,99.75,303.179,99.688,303.916z M100.978,295.564
+					c0.717,0.14,1.11,0.61,1.099,1.156c0.052,0.552-0.595,0.993-1.286,1.015c-0.541-0.074-1.025-0.548-1.022-1.054
+					C99.813,296.084,100.292,295.644,100.978,295.564z"/>
+				<path i:knockout="Off" d="M108.115,298.791c3.028-0.066,5.283,1.359,5.256,5.758c-0.264,3.479-3.366,4.63-5.883,5.119
+					c-2.429-0.033-5.619-2.24-5.16-5.811C102.322,300.085,105.715,298.846,108.115,298.791z M107.351,309.232
+					c2.675-0.132,3.839-2.333,3.841-4.497c0.246-2.344-0.263-4.833-2.923-5.396c-2.844,0.299-3.974,1.917-4.053,4.479
+					C104.136,306.655,104.854,308.372,107.351,309.232z"/>
+			</g>
+		</g>
+	</g>
+	<g id="heads" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFFFFFF4F00">
+		<g id="head1" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFF4F00FFFF">
+			<g id="leftEart" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFFFFFF">
+				<path i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M201.557,195.475
+					c7.734-4.547,16.592-5.012,18.405,4.443c2.43,12.659-3.317,13.328-14.598,13.328"/>
+				<path i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M211.711,203.09
+					c0.523,0.004,0.946-0.208,1.271-0.635"/>
+				<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M211.076,197.377
+					c3.062,3.013,5.489,5.624,4.442,10.155"/>
+			</g>
+			<path id="bgHairTop" i:knockout="Off" fill="#FFF471" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M54.384,199.307c-5.253-4.402-7.511-11.061-15.779-10.632c3.449-1.277,7.116-2.397,10.911-2.666
+				c-2.873-1.397-5.865-2.575-8.231-4.718c3.986-1.119,11.47-1.817,14.864,0.75c-5.183-2.758-8.397-7.816-13.062-10.598
+				c6.014-0.643,12.377,0.978,18.022,2.265c-2.547-4.486-6.682-10.83-10.523-14.297c5.033,1.052,10.647,4.518,15.062,7.177
+				c-1.614-4.176-5.634-8.406-7.859-12.513c10.312-1.125,12.522,4.919,19.7,9.932c-0.412-0.127-1.114-0.113-1.527,0.015
+				c0.875-7.261,3.058-12.8,8.258-18.566c6.771-7.507,17.813-9.131,24.095-15.381c-4.699,1.821-4.518,23.765-4.875,28.955"/>
+			<path id="bgHairLeft" i:knockout="Off" fill="#FFF471" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M92.384,243.973c-6.334,7.929-12.601,12.241-22.465,15.361c3.65-1.263,7.735-5.859,7.695-9.928
+				c-2.208,0.218-4.49,0.605-6.498,1.098c1.244-1.098,2.087-3.239,3.198-4.396c-5.77,0.001-12.131,1.133-18.396,1.23
+				c5.013-2.81,10.665-3.25,12.398-9.247c-3.59,0.313-7.233,1.606-11.033,1.097c1.731-2.022,3.953-3.995,5.049-6.447
+				c-3.781,0.056-6.665,3.098-10.547,2.465c0.962-2.863,3.187-5.208,4.531-7.766c-5.59-0.273-11.658,2.45-17.732,2.564
+				c5.494-2.857,8.967-7.819,12.3-12.718c5.233-7.693,10.625-9.96,20.349-9.981c11.059-0.024,15.558,6.714,20.984,16
+				c2.786,4.767,7.249,14.375,0.832,18"/>
+			<path id="bgHair" i:knockout="Off" fill="#FFF471" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M142.384,255.307c2.984,6.076,3.567,11.855,10.531,14.6c-0.134-3.114-0.094-6.664,1.619-9.033
+				c1.604,1.969,3.122,4.211,5.048,5.698c-0.29-1.769,0.412-4.023,0.233-5.828c3.444,0.261,4.979,3.965,8.468,4.479
+				c0.065-2.78,0.427-5.151,0.868-7.813c2.687,0.2,4.768,1.565,7.132,2.997c0.452-4.921-0.409-10.579-0.667-15.666
+				c-5.795-0.756-12.291,2.827-17.899,3.899c-4.414,0.844-14.136,0.523-15.333,6"/>
+			<path id="neck" i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M106.989,254.499c-2.932,6.063-4.613,11.997-8.947,17.138c7.288,10.194,16.311-10.9,15.183-17.026
+				c-1.926-1.138-3.928-1.589-6.236-1.38"/>
+			<path id="headShape" i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M210.941,207.666c-0.844,3.985-2.081,7.982-3.77,11.783c-3.374,7.604-8.543,14.427-16.052,18.899
+				c-2.94,2.13-5.983,4.167-9.109,6.085c-25.013,15.342-55.353,23.08-82.254,10.57c-3.433-1.558-6.785-3.432-10.053-5.66
+				c-1.821-1.185-3.592-2.46-5.308-3.832c-1.715-1.373-3.375-2.842-4.972-4.412c-2.352-2.148-4.576-4.425-6.631-6.814
+				c-6.168-7.169-10.823-15.358-12.87-24.185c-0.649-3.284-0.84-6.634-0.5-9.975c4.48-13.743,14.22-24.364,26.109-32.149
+				c2.973-1.946,6.079-3.715,9.271-5.309c30.581-15.027,69.581-10.027,95.852,12.209c2.563,2.254,4.987,4.651,7.244,7.178
+				c4.513,5.054,8.354,10.626,11.312,16.64C210.178,201.505,210.798,204.497,210.941,207.666z"/>
+			<g id="rightEar" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#800080008000">
+				<path i:knockout="Off" fill="#FFE8B0" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M64.857,195.606
+					c-6.59-7.181-15.047-10.664-19.467,3.676c-1.235,4.007-1.87,14.468,1.29,17.786c4.223,4.435,13.591,0.529,19.055-0.015"/>
+				<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M52.407,196.744
+					c-1.702,3.613-1.257,7.505-1.27,11.424"/>
+				<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M51.772,209.438
+					c-3.39-4.661,0.922-5.769,5.078-6.347"/>
+			</g>
+			<path id="fgHair" i:knockout="Off" fill="#FFF471" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M90.384,154.64c8.453-11.353,15.678-13.458,28.581-15.915c-1.382,3.376-3.89,7.352-5.179,11.16
+				c5.01-1.816,9.571-6.545,15.218-8.413c11.355-3.755,23.853-1.903,35.671-2.213c-3.004,3.712-4.912,7.88-2.025,11.447
+				c5.855-2.212,13.369-6.871,19.635-6.646c0.263,4.561-0.024,9.278,0.201,13.841c3.509-1.201,6.015-3.04,8.276-5.148
+				c2.263-2.108,3.761-4.049,4.942-5.2c1.063,2.408,2.134,5.334,2.24,8.494c-0.183,3.462-0.866,6.794-2.66,9.291
+				c3.663,0.65,6.098-2.021,8.35-4.479c-0.655,4.349-3.164,8.604-3.851,13.013c2.178-0.072,4.382,0.216,6.367-0.48
+				c-1.39,3.093-3.069,7.287-6.616,8.414c-4.476,1.423-4.354-0.992-7.315-4.332c-4.892-5.518-9.773-6.791-15.872-9.464
+				c-6.585-2.887-10.982-6.47-17.963-8.219c-8.994-2.255-19.864-3.867-28.093-5.196c2.466,1.967,1.138,5.594,0.659,8.625
+				c-2.729-0.646-4.41-3.813-6.301-5.158c0.953,3.195,0.983,6.953-2.134,8.491c-6.145-5.226-9.199-9.721-17.527-11.647
+				c1,1.83,1.728,4.208,1.396,6.402c-0.751,4.971-0.289,3.134-3.836,2.466c-5.192-0.977-9.953-3.677-15.815-4.496
+				c3.292,2.002,5.469,5.017,7.418,8.21c-2.651,0.404-6.238,0.257-8.382,1.671c2.456,0.38,3.44,2.166,3.197,4.714
+				c-7.45,0.386-13.623,0.731-19.915,5.434"/>
+		</g>
+	</g>
+	<g id="eyes" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#000000000000">
+		<g id="eyes1" i:knockout="Off" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#4F008000FFFF" display="none">
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M123.163,176.668
+				c-5.066,1.17-9.01,7.888-13.666,10.335c-4.238,2.227-8.648,6.636-7.009,12.332c1.971,6.848,12.042,3.991,16.261,1.165
+				c5.282-3.539,9.59-8.517,12.006-14.524c1.523-3.787,2.568-7.272-1.509-9.391c-2.905-1.51-8.174-1.386-11.417-0.583"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" stroke-linecap="round" d="M182.545,179.865
+				c-3.533,0.169-4.854-1.166-8.408-0.001c-3,0.983-6.239,1.936-8.852,3.743c-3.938,2.725-7.46,5.555-4.73,13.592
+				c1.974,5.811,8.791,7.571,14.656,6.667c5.537-0.854,9.078-4.977,11.408-10.007c3.666-7.918,0.942-11.639-6.742-13.659"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M108.829,183.668c-1.308-1.03-4.557,0.011-5.6-1.733
+				c-1.056-1.765,1.735-5.409,2.984-6.192c5.684-3.562,15.946-0.39,19.95-6.742"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M163.877,167.198c2.369,1.282,6.539,0.307,9.408,0.815
+				c3.449,0.612,7.065,2.657,10.592,2.851"/>
+			<path i:knockout="Off" display="inline" stroke="#000000" d="M127.496,192.002c-4.917-2.12-9.188-1.708-8.608,4.942
+				c3.132,1.734,5.428-2.82,7.275-4.942"/>
+			<path i:knockout="Off" display="inline" stroke="#000000" d="M174.852,203.144c-0.293,0.12-0.307,0.577-0.942,0.282
+				c-1.605-3.188-0.404-6.507,2.676-8.192c2.15-1.176,5.67-1.759,7.471,0.359c0.199,0.234,0.412,0.521,0.515,0.813
+				c0.229,0.649-0.285,0.95-0.285,0.95s-3.988,6.009-3.285,1.934c0.438,1.743-5.537,5.743-2.287,1.653
+				c-1.955,2.583-2.524,1.977-3.859,2.868"/>
+		</g>
+		<g id="eyes2" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFF4F004F00">
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M98.668,186.108c0.668-8.915,15.545-13.749,22.667-15"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M169.667,178.108c5.307,3.436,16.928,5.632,19.668,12.333"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M105.334,197.775c8.085-4.283,17.059-2.8,25-6.333"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M164.001,198.775c4.656-0.417,9.664,1.805,14.334,2.017
+				c3.951,0.18,5.773,0.189,9,2.316"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M124.001,188.108c3.039-0.258,4.594,2.571,5.301,4.983
+				c-1.096,1.242-2.065,2.646-2.968,4.017"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M168.335,194.108c-1.77,2.293-4.869,3.271-6.299,5.91
+				c1.377,0.991,3.02,2.122,3.965,3.424"/>
+		</g>
+	</g>
+	<g id="beard" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFF4F00">
+		<path i:knockout="Off" fill="#AFA8A5" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M96.05,213.64
+			c-0.366,0.21-0.783,0.389-1.167,0.5"/>
+		<path i:knockout="Off" fill="#AFA8A5" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M102.55,211.973
+			c0.314-0.01,0.554-0.198,0.667-0.5"/>
+		<path i:knockout="Off" fill="#AFA8A5" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M105.717,208.806
+			c0.164-0.109,0.336-0.224,0.5-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M111.05,207.973
+			c-0.651-1.81,0.859-2.262,2.333-1.5"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M117.717,209.806
+			c1.738,0,3.653,0.369,5.333,0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M132.717,214.473
+			c0.104-0.21,0.162-0.435,0.167-0.667"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M139.551,216.973
+			c0.215-0.175,0.465-0.426,0.666-0.667"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M144.551,213.306
+			c0.277-0.056,0.557-0.111,0.833-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M147.884,216.64
+			c0.195,0.045,0.369-0.013,0.5-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M148.384,214.14
+			c0.112-0.168,0.223-0.332,0.333-0.5"/>
+		<path i:knockout="Off" display="none" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M98.217,219.306c1.697-1.772,4.233-2.109,5.967-4.046c1.519-1.696,3.812-3.001,4.2-5.454"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M152.717,216.14
+			c0.611,0,1.224,0,1.834,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M160.384,217.473
+			c0.333,0,0.667,0,1,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M163.217,215.973
+			c0.321-0.042,0.658-0.175,0.834-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M164.217,218.806
+			c0.167,0,0.333,0,0.5,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M168.384,217.973
+			c0.057-0.056,0.111-0.111,0.167-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M169.884,225.806
+			c0.491-0.397,0.882-0.926,1.167-1.5"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M172.717,221.973
+			c0.057,0,0.111,0,0.167,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M171.717,229.806
+			c0.334,0.075,0.659,0.025,0.834-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M190.051,227.806
+			c0.163-0.242,0.398-0.423,0.666-0.5"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M197.384,221.473
+			c0.258-0.007,0.485-0.125,0.667-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M199.384,214.973
+			c-0.04-0.333,0.075-0.609,0.333-0.833"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M117.884,257.306
+			c0.056,0,0.111,0,0.167,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M142.717,252.473
+			c0.358,0.068,0.71,0.016,1-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M137.884,256.473
+			c0.277,0,0.557,0,0.833,0"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M160.884,252.973
+			c0.366-0.139,0.766-0.402,1-0.667"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M171.384,250.14
+			c0.235-0.264,0.476-0.562,0.667-0.834"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M89.384,243.973
+			c0.537,0.378,1.329,0.876,1.833,1.333"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M79.05,225.473
+			c0.087,0.272,0.143,0.55,0.167,0.833"/>
+		<path i:knockout="Off" fill="none" stroke="#AAAAAA" stroke-linecap="round" stroke-linejoin="bevel" d="M73.884,222.64
+			c0,0.167,0,0.333,0,0.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M72.55,219.806c0.466-0.325,0.875-0.797,1.167-1.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M71.717,211.973c0.422-0.553,0.776-1.305,1-2"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M78.55,214.473c0-0.111,0-0.222,0-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M79.384,218.806c-0.001-0.137,0.055-0.248,0.167-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M80.217,221.14c0.111,0,0.222,0,0.333,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M75.55,226.473c0.103-0.5,0.156-0.977,0.167-1.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M78.55,230.14c0.111,0,0.222,0,0.333,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M83.384,227.64c0.118-0.059,0.215-0.107,0.333-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M81.55,237.14c0.056,0,0.111,0,0.167,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M86.217,233.806c0.056,0,0.111,0,0.167,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+			M87.884,230.473c0.595-0.181,1.219-0.527,1.833-0.667"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M88.717,222.14
+			c-0.929,2.359-1.615,4.865-2.667,7.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M89.05,216.14
+			c0.784-0.736,1.709-1.565,2.833-1.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M94.217,210.14
+			c1.599-0.089,3.199-0.167,4.833-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M94.884,224.64
+			c0.052-0.588-0.004-1.155-0.167-1.667"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M92.384,228.306
+			c0.585-0.062,1.244-0.132,1.667-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M88.717,240.14
+			c0.111,0,0.222,0,0.333,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M95.884,243.306
+			c0.526,0.1,1.017-0.016,1.333-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M98.55,248.306
+			c0.069-0.24,0.265-0.926,0.333-1.166"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M96.55,249.806
+			c0.125,0.014,0.18-0.042,0.167-0.166"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M104.55,250.14
+			c0.01-0.238,0.126-0.428,0.333-0.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M106.884,251.973
+			c0.195,0.045,0.37-0.014,0.5-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M113.884,254.806
+			c0.758-0.586,1.595-1.171,2.382-1.774c0.072,0.376,0.418,0.686,0.48,1.079c0.833,0.265,1.624-0.021,1.638-0.971"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M122.217,254.64
+			c0.063-0.165,0.179-0.288,0.333-0.334"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M125.884,255.806
+			c1.13-0.745,2.783-0.962,3.667-2"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M132.217,255.973
+			c0.638-0.492,1.104-1.173,1.141-1.976c-1.11,0.063-1.449-0.888-1.475-1.857"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M129.717,249.306
+			c-0.045,0.153-0.168,0.271-0.333,0.334"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M136.551,252.306
+			c0.223,0,0.444,0,0.666,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M110.217,251.306
+			c0.056-0.057,0.111-0.11,0.167-0.166"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M140.717,251.806
+			c0.111,0,0.224,0,0.334,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M150.051,249.473
+			c0.111,0,0.223,0,0.333,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M143.217,255.473
+			c1.022-0.313,1.725-1.175,2.646-1.654c0.203,0.321,0.439,0.626,0.521,0.987"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M152.217,253.473
+			c0.165-0.063,0.288-0.179,0.334-0.333"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M155.051,254.64
+			c0.223,0,0.444,0,0.666,0"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M157.717,256.473
+			c0.326-0.027,0.546-0.073,0.834-0.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M163.217,252.64
+			c0.552-0.892,2.082-1.512,2.341-2.334c0.37-1.178-1.155-3.069-1.007-4.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M167.384,235.973
+			c0.118-0.54,0.354-1.064,0.667-1.5"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M170.717,242.806
+			c0-0.333,0-0.667,0-1"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M170.217,236.973
+			c0-0.333,0-0.667,0-1"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M179.051,235.806
+			c0.378-0.101,0.738-0.35,1-0.667"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M185.051,232.806
+			c0.379-0.319,0.656-0.702,0.833-1.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M188.051,231.14
+			c0.063-0.39,0.178-0.792,0.333-1.167"/>
+		<path i:knockout="Off" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="M197.884,223.306
+			c-0.166,0.277-0.334,0.556-0.5,0.833"/>
+	</g>
+	
+		<g id="mouths" i:isolated="yes" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F004F00FFFF" enable-background="new    ">
+		<g id="mouth1" i:knockout="Off" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#FFFFFFFF4F00" display="none">
+			<path i:knockout="Off" display="inline" stroke="#000000" d="M177.122,216.821c-0.515,2.282-5.213,3.21-7.434,3.854
+				c-3.254,0.945-6.596,1.345-9.895,1.851c-3.26,0.5-6.665,0.671-10.107,0.671c-3.596,0-6.645,0.559-10.106,0.671
+				c-3.105,0.1-6.898-0.474-9.694-1.3c-3.527-1.043-6.672-1.666-10.096-3.062c-2.823-1.152-5.746-1.876-8.462-3.143
+				c-2.594-1.209-6.084-1.994-8.221-3.552c-1.068,1.834-5.867,3.748-8.1,4.546c-2.444,0.874-8.881,2.725-7.817,5.512
+				c0.457,1.195,1.948,2.273,2.63,3.385c0.774,1.261,1.139,2.601,2.057,3.859c1.83,2.5,4.506,4.773,6,7.34
+				c1.308,2.249,2.096,4.74,4.01,6.669c2.214,2.233,5.792,2.635,9.231,2.399c7.028-0.479,13.982-2.129,20.481-3.983
+				c3.295-0.941,6.699-1.536,10.086-2.686c3.272-1.111,6.642-3,9.402-4.777c5.248-3.377,10.278-6.409,14.283-10.705
+				c1.479-1.587,3.429-2.503,5.149-3.859"/>
+			<path i:knockout="Off" display="inline" fill="#FFC0C0" stroke="#000000" d="M135.25,241.319
+				c0.723-4.757-10.487-8.47-14.898-9.526c-3.09-0.74-6.68-1.17-9.858-1.712c-2.758-0.47-6.865-0.836-9.437,0.369
+				c-1.385,0.649-2.843,1.724-4.141,2.513c2.156,3.964,4.728,8.861,9.468,11.506c3.229,1.801,5.511,0.776,8.859,0.373
+				c3.045-0.369,6.046-0.703,9.029-1.721c3.479-1.186,7.228-2.385,10.978-2.475"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M148.656,225.547c1.267,0.697,1.301,2.838,0.671,3.9
+				c-0.702,1.182-2.063,1.4-3.307,2.01c-2.271,1.116-4.58,2.624-7.481,2.638c-4.619,0.023-2.144-4.067-0.253-5.869
+				c2.405-2.292,5.057-2.72,8.72-2.512c0.588,0.034,1.095,0.041,1.65,0.168"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M130.299,223.365
+				c2.687,0.437,5.619,4.384,3.727,6.422c-1.234,1.33-7.94,1.391-9.915,1.296c-4.896-0.233-2.502-2.445-0.613-4.525
+				c1.604-1.767,5.088-3.249,7.833-3.36"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M113.178,217.157
+				c2.56,0.958,4.922,5.057,5.352,7.215c0.377,1.885-0.324,2.106-2.526,2.643c-1.366,0.333-3.636,0.723-5.105,0.385
+				c-2.506-0.577-5.883-5.051-4.909-7.223c1.03-2.298,5.944-2.923,8.427-2.852"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M99.359,217.662
+				c2.038,0.432,4.015,4.279,2.468,5.625c-1.083,0.943-5.221,1.795-6.799,1.589c-4.032-0.526-2.265-4.102-0.866-5.872
+				c0.706-0.894,1.049-1.976,2.514-2.186c1.627-0.233,2.501,0.99,3.921,1.346"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M181.815,222.896c-3.102-2.75-4.765-8.777-9.282-10.403
+				"/>
+		</g>
+		<g id="mouth2" i:knockout="Off" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#FFFF4F00FFFF" display="none">
+			<path i:knockout="Off" display="inline" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M87.57,221.951c5.563-1.759,11.066-1.32,16.694-1.782c2.93-0.24,5.228-1.14,8.309-0.927c3.142,0.217,6.085-0.235,9.289,0.176
+				c7.136,0.914,13.96,0.598,21.112,1.506c3.654,0.464,7.219,0.609,10.811,0.869c4.017,0.291,7.646,1.582,11.433,2.623
+				c2.948,0.812,6.347,1.618,9.011,2.99c2.521,1.298,6.354,2.856,8.301,4.72c-2.775,0.027-5.602,2.603-8.021,3.769
+				c-2.93,1.412-5.741,2.949-8.656,4.432c-5.599,2.849-11.885,5.468-18.104,6.53c-6.793,1.161-13.195,2.107-20.067,2.197
+				c-7.699,0.102-14.313-4.705-20.735-8.396c-2.071-1.19-4.69-2.182-6.504-3.666c-1.792-1.466-3.469-3.386-5.154-4.984
+				c-2.703-2.564-7.519-5.649-8.13-9.438"/>
+			<path i:knockout="Off" display="inline" fill="none" stroke="#000000" stroke-width="2" d="M87.785,228.193
+				c-5.907-3.235-0.344-9.531,3.971-11.424"/>
+			
+				<path i:knockout="Off" display="inline" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="bevel" d="
+				M184.679,227.229c-1.534,2.583-2.548,5.334-4.024,7.889"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M106.862,219.528
+				c-3.071-0.74-5.608,2.166-6.318,4.738c-0.379,1.375-0.494,2.55,0.748,3.337c1.519,0.962,2.905-0.052,4.418-0.332
+				c2.518-0.467,7.293,0.053,6.461-4.248c-0.568-2.938-3.743-3.682-6.338-3.335c-0.451,0.06-0.758,0.212-1.205,0.229"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M119.764,218.479
+				c-2.648,1.243-4.657,3.518-5.346,6.377c-0.866,3.594,3.9,3.711,6.356,2.865c2.64-0.91,4.77-3.351,3.299-6.133
+				c-1.01-1.91-3.979-2.548-6.026-2.823"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M130.388,219.492
+				c-1.753,1.382-4.069,4.525-4.835,6.61c-1.159,3.156,2.296,3.371,4.868,3.348c3.061-0.028,6.6-1.148,5.022-4.78
+				c-1.168-2.691-2.552-4.85-5.551-5.241"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M142.954,221.087
+				c-1.502,0.337-5.418,3.249-5.638,4.997c-0.292,2.311,4.855,4.536,6.854,4.234c2.503-0.377,4.384-3.175,3.167-5.65
+				c-0.92-1.873-3.36-2.252-4.508-3.932"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M155.354,222.664
+				c-2.038,0.426-4.212,2.287-4.766,4.444c-0.723,2.821,3.226,3.383,5.458,3.331c2.541-0.059,5.126-1.752,3.249-4.32
+				c-1.394-1.908-3.707-3.189-5.304-4.636"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M168.367,237.924
+				c-1.554-1.217-3.302-2.557-5.203-2.976c-2.973-0.654-3.537,2.131-3.377,4.406c0.205,2.913,1.032,3.883,3.901,2.344
+				c1.987-1.066,4.271-1.997,4.599-4.456"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M151.524,246.202
+				c-1.912-0.166-4.004-4.491-2.91-6.25c0.771-1.239,5.456-1.688,6.857-1.292c0.271,0.917,0.979,1.841,0.829,2.771
+				c-0.088,0.54-0.994,1.645-1.296,2.188c-1.08,1.951-2.133,1.866-3.998,2.685"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M145.911,241.458
+				c-0.209,1.649-0.215,2.702-1.528,3.801c-0.885,0.738-1.772,1.189-2.54,2.1c-0.786,0.933-1.226,2.38-2.792,1.813
+				c-1.042-0.377-1.959-2.318-2.138-3.312c-0.299-1.676-1.003-5.228,0.783-6.158c1.154-0.603,7.066-0.18,7.43,1.32"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M133.12,238.991
+				c-1.495-0.087-2.253-1.33-3.918-0.964c-1.42,0.311-2.489,1.354-2.54,2.836c-0.052,1.527,0.99,5.581,1.852,6.956
+				c2.363,3.771,4.329-1.535,5.516-3.159c1.117-1.525,2.643-2.053,2.271-3.958c-0.318-1.632-1.118-2.047-2.766-2.329
+				c-0.382-0.065-0.773-0.095-1.158-0.147"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M116.853,237.43
+				c-1.049,2.211-0.173,5.147,0.047,7.565c0.357,3.93,3.827,2.028,5.831,0.067c1.575-1.541,4.599-4.86,2.209-6.484
+				c-1.881-1.279-5.727-2.458-7.756-1.107"/>
+			<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M107.455,233.38
+				c-0.813,2.487-1.704,5.049,0.073,7.364c1.91,2.486,4.009,1.229,5.537-0.939c1.056-1.5,3.316-4.481,1.563-6.017
+				c-1.347-1.179-6.468-1.518-7.854-0.325"/>
+		</g>
+		
+			<g id="mouth3" i:isolated="yes" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFFFFFF" enable-background="new    ">
+			
+				<path i:isolated="yes" i:knockout="Off" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" enable-background="new    " d="
+				M99.05,218.973c1.691-0.875,3.313-2.39,4.833-3.537c1.231-0.928,2.782-1.671,3.5-3.072c1.846,3.486,7.661,4.669,11.003,6.067
+				c3.553,1.486,7.174,3.066,10.784,4.166c4.271,1.301,9.277,1.67,13.721,2.343c4.155,0.629,9.979,1.365,14.162,0.496
+				c1.182-0.245,2.343-1.024,3.462-1.446c0.162,1.905-3.637,3.023-4.933,3.487c-2.435,0.871-4.18,2.541-6.362,3.871
+				c-1.623,0.989-2.974,1.669-4.755,2.117c-1.77,0.445-3.353,0.806-4.825,1.878c-5.915,4.311-15.264,3.247-22.424,3.13
+				c-5.384-0.088-6.719-5.372-9.337-9c-1.437-1.991-2.843-3.854-3.796-6.138c-0.871-2.086-1.119-4.582-2.033-6.528"/>
+			
+				<path i:isolated="yes" i:knockout="Off" fill="#F4BDBD" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" enable-background="new    " d="
+				M107.217,227.973c1.182-2.033,4.375-2.176,6.5-1.963c2.879,0.289,4.124,1.217,6.168,3.167c1.834,1.749,5.906,5.509,5.64,8.271
+				c-2.808,0.89-7.847,0.402-10.346-1.104c-1.334-0.804-1.151-2.256-2.246-3.588c-0.712-0.866-1.836-2.673-2.855-3.311
+				c-0.209-0.94-2.106-1.499-3.028-1.805"/>
+		</g>
+	</g>
+	<g id="personalProps" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#800080008000">
+		<g id="hat" i:knockout="Off" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#000000000000" display="none">
+			<g i:knockout="Off" display="inline">
+				<g i:knockout="Off">
+					<path i:knockout="Off" fill="#FF0000" d="M88.374,173.145c0.474-0.074,16.606,2.725,18.01,5.879
+						c1.145,2.572,28.184,4.568,28.184,4.568l35.971-5.618l5.024,1.132l7.212,0.315l9.295,0.851l10.188,3.248l5.75,2.935
+						l1.615-1.832l-0.264-5.27l-3.968-7.087c0,0-22.045-13.031-23.272-13.703c-1.229-0.669-4.941-2.294-6.484-4.542
+						c-8.584-12.528-8.403-18.05-3.371-6.461c0,0,2.662-7.592,2.521-8.575c-0.144-0.982,0.354-5.031,0.354-5.031l2.396-6.832
+						c0,0-1.379-5.341-2.738-7.19c-1.356-1.844-15.793-4.078-18.162-4.011c-24.933,0.706-3.783,0.071-25.567,0.724
+						c-24.317,0.728-0.882-2.591-24.068,3.551c-24.228,6.418-5.35-1.298-23.187,6.142c-18.301,7.633-16.67,7.186-16.704,10.685
+						c-0.034,3.499-3.057-4.884-0.034,3.499c3.023,8.381,3.037-3.871,3.023,8.381c-0.015,12.252,6.696,4.557,1.678,12.373
+						c-5.017,7.813-3.831,7.91-0.179,8.543c17.017,2.953,4.157,4.378,17.427,3.175"/>
+					<path i:knockout="Off" d="M156.604,114.92l-13.936,0.381l-11.633,0.343c-10.646,0.319-11.973-0.155-12.021-0.175l-0.599-0.238
+						l-0.577,0.514l0.049-0.047c-0.118,0.09-1.43,0.957-11.145,3.53c-9.989,2.646-12.812,2.931-13.421,2.704
+						c-0.822-0.306-0.821-0.306-7.791,2.604l-2.104,0.878c-16.037,6.689-17.342,7.324-17.342,10.316c0,0.019,0.001,0.041,0.001,0.06
+						c-0.224-0.108-0.459-0.199-0.787-0.04c-0.357,0.173-0.565,0.275-0.565,0.672c0,0.557,0.411,1.697,1.399,4.438
+						c0.924,2.561,1.71,3.671,2.714,3.833c0.083,0.014,0.164,0.02,0.241,0.02c0.007,0.584,0.01,1.339,0.01,2.313
+						c0,0.561-0.001,1.902-0.001,1.916c0,6.908,2.176,8.105,3.347,8.749c0,0,0.075,0.045,0.151,0.09
+						c-0.095,0.332-0.47,1.1-1.661,2.955c-2.509,3.908-3.516,5.931-3.516,7.303c0,0.358,0.068,0.671,0.196,0.962
+						c0.544,1.237,1.926,1.477,3.677,1.78l0.135,0.023c8.138,1.412,9.14,2.422,9.568,2.854c0.923,0.931,1.511,0.928,7.224,0.413
+						c0.06,0.014,0.102,0.068,0.165,0.071c2.167,0.105,16.131,3.138,17.087,5.288c1.147,2.578,16.416,4.228,29.023,5.159
+						l0.115,0.009c0,0,35.523-5.548,35.896-5.606c0.345,0.078,4.927,1.11,4.927,1.11l7.301,0.319c0,0,8.927,0.818,9.139,0.837
+						c0.202,0.064,9.854,3.142,10.006,3.19c0.143,0.073,6.368,3.251,6.368,3.251l2.397-2.719l-0.296-5.911l-4.213-7.526
+						l-0.231-0.137c-0.9-0.532-22.073-13.047-23.304-13.72c-0.001,0-0.734-0.38-0.734-0.38c-1.48-0.752-4.238-2.151-5.404-3.85
+						c-1.357-1.982-2.451-3.729-3.354-5.268c0.021-0.064,0.104-0.296,0.104-0.296c1.193-3.402,2.576-7.619,2.576-8.885
+						c0-0.063-0.004-0.118-0.011-0.165c-0.013-0.083-0.018-0.204-0.018-0.356c0-0.909,0.194-2.911,0.363-4.307
+						c0.072-0.205,2.46-7.013,2.46-7.013l-0.076-0.294c-0.146-0.566-1.468-5.584-2.9-7.532
+						C173.721,116.784,158.242,114.875,156.604,114.92z M131.097,117.644l11.614-0.342l13.951-0.382
+						c2.575-0.073,16.104,2.238,17.336,3.614c0.956,1.3,2.058,4.938,2.49,6.549c-0.188,0.536-2.33,6.642-2.33,6.642l-0.014,0.107
+						c-0.072,0.592-0.387,3.224-0.387,4.658c0,0.258,0.011,0.477,0.034,0.639c-0.006,0.493-0.768,3.026-1.659,5.709
+						c-2.14-4.566-2.792-4.606-3.242-4.629l-0.62-0.031l-0.354,0.571c-0.069,0.124-0.102,0.29-0.102,0.492
+						c0,2.273,4.134,9.172,6.992,13.346c1.456,2.12,4.51,3.669,6.149,4.501l0.682,0.353c1.139,0.622,20.813,12.25,23.012,13.549
+						c0.238,0.427,3.513,6.275,3.721,6.647c0.02,0.393,0.199,3.971,0.23,4.629c-0.229,0.262-0.472,0.535-0.832,0.944
+						c-1.069-0.546-5.132-2.619-5.132-2.619l-10.369-3.306l-9.403-0.86c0,0-6.995-0.307-7.169-0.315
+						c-0.168-0.038-5.124-1.155-5.124-1.155s-35.814,5.594-36.044,5.63c-12.419-0.922-25.993-2.687-27.285-4.058
+						c-1.366-3.097-13.245-5.574-17.517-6.211c-0.203-0.212-0.479-0.346-0.793-0.318c-3.083,0.28-5.996,0.544-6.4,0.369
+						c0-0.003-0.12-0.117-0.12-0.117c-0.703-0.708-1.879-1.895-10.646-3.416l-0.135-0.023c-0.827-0.143-2.075-0.359-2.188-0.614
+						c-0.021-0.048-0.033-0.111-0.033-0.193c0-0.592,0.632-2.179,3.205-6.187c1.488-2.318,2.024-3.388,2.024-4.188
+						c0-0.15-0.019-0.291-0.054-0.428c-0.181-0.712-0.758-1.03-1.179-1.261c-0.865-0.476-2.311-1.271-2.311-6.993
+						c0-0.014,0.001-1.098,0.001-1.56c0-4.969-0.065-4.992-0.833-5.258c-0.424-0.146-0.816,0.001-1.178,0.377
+						c-0.208-0.289-0.558-0.898-1.073-2.324c-0.205-0.568-0.385-1.068-0.542-1.506c0.587-0.423,0.632-1.277,0.636-1.644
+						l-0.014-0.825c-0.004-0.119-0.007-0.231-0.007-0.338c0-1.702,0.899-2.264,16.109-8.608l2.105-0.878
+						c4.165-1.739,5.948-2.482,6.375-2.562c0.817,0.296,2.292,0.597,14.579-2.658c8.169-2.164,10.697-3.187,11.58-3.704
+						C120.451,117.773,124.529,117.84,131.097,117.644z"/>
+				</g>
+				<g i:knockout="Off">
+					<path i:knockout="Off" fill="#FFFFFF" d="M155.146,147.93c4.88-9.398-5.344-20.199-12.649-21.176
+						c-12.05-1.61-13.404,10.426-13.684,21.258c3.73,2.016,8.915,3.425,11.721,6.534"/>
+					<path i:knockout="Off" d="M133.446,127.979c-4.599,3.921-5.426,11.933-5.635,20.006l-0.017,0.654l4.415,2.067
+						c2.849,1.244,5.793,2.529,7.581,4.509c0.371,0.41,1.004,0.442,1.412,0.072c0.219-0.197,0.33-0.469,0.33-0.743
+						c0-0.239-0.084-0.479-0.258-0.67c-2.076-2.299-5.223-3.673-8.267-5.001c0,0-2.377-1.112-3.174-1.486
+						c0.223-7.385,1.021-14.572,4.909-17.887c1.892-1.614,4.386-2.189,7.621-1.757c4.143,0.554,9.086,4.472,11.5,9.113
+						c1.348,2.591,2.51,6.535,0.395,10.611c-0.254,0.49-0.063,1.093,0.426,1.348c0.49,0.254,1.095,0.063,1.351-0.427
+						c1.959-3.775,1.817-8.199-0.396-12.456c-2.731-5.251-8.203-9.53-13.012-10.172C138.853,125.257,135.763,126,133.446,127.979z"
+						/>
+				</g>
+				<g i:knockout="Off">
+					<path i:knockout="Off" d="M154.077,146.278c-2.156,1.18-4.24,2.619-6.256,4.01c-3.636,2.509-7.068,4.878-10.941,5.924
+						c-2.991,0.808-6.055,1.058-9.3,1.324c-3.222,0.263-6.553,0.536-9.783,1.406c-2.027,0.546-4.117,1.397-6.137,2.221
+						c-3.491,1.423-7.102,2.895-10.528,2.866c-0.552-0.005-1.004,0.439-1.009,0.991c-0.005,0.552,0.439,1.004,0.991,1.009
+						c3.828,0.033,7.627-1.516,11.301-3.014c2.054-0.837,3.994-1.628,5.902-2.142c3.054-0.823,6.292-1.088,9.425-1.344
+						c3.191-0.261,6.492-0.531,9.659-1.386c4.205-1.135,7.94-3.714,11.557-6.208c1.973-1.362,4.014-2.771,6.08-3.901
+						c0.484-0.265,0.662-0.873,0.396-1.357C155.168,146.193,154.562,146.014,154.077,146.278z"/>
+				</g>
+				<g i:knockout="Off">
+					<path i:knockout="Off" d="M156.458,153.549c-2.619,0.064-5.709,0.812-8.98,1.604c-4.278,1.035-8.7,2.104-11.901,1.536
+						c-0.543-0.096-1.063,0.267-1.159,0.81c-0.097,0.544,0.267,1.063,0.81,1.16c3.613,0.641,8.24-0.481,12.72-1.562
+						c3.166-0.766,6.153-1.489,8.561-1.548c5.664-0.141,7.961,0.698,13.508,2.724c0.519,0.189,1.095-0.077,1.281-0.596
+						c0.189-0.519-0.076-1.091-0.596-1.282C165.069,154.337,162.501,153.399,156.458,153.549z"/>
+				</g>
+			</g>
+		</g>
+		<g id="textSurface" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F008000FFFF">
+			
+				<g id="spokenBubble" i:knockout="Off" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#FFFF4F004F00" display="none">
+				<path id="textContainer" i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M225.719,45.307
+					c0-6.627,5.373-12,12-12h181.333c6.627,0,12,5.373,12,12v105.334c0,6.627-5.373,12-12,12H237.719c-6.627,0-12-5.373-12-12
+					V45.307z"/>
+				<path id="textArrowBelow" i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M249.052,160.64
+					c-0.774,14.251-1.676,18.525-9.1,30.565c9.705-0.79,21.952-21.605,25.1-30.045"/>
+			</g>
+			<g id="thoughtBubble" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFF4F00">
+				<path id="textContainer_1_" i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M202.698,21.089
+					c19.686-26.45,59.686-24.45,79.747-0.084c2.696,1.349,5.57,1.709,7.472,0.781c15.28-13.888,33.271-14.043,49.893-7.839
+					c2.771,1.034,5.479,2.219,8.031,3.421C376.384-4.36,423.384,6.64,431.007,45.026c0,0-1.324,3.889,1.165,6.603
+					c18.212,11.011,26.212,32.011,22.212,53.011c-1,5.333-3.223,9.667-6.037,13.52c-2.813,3.854-1.381,0-2.612-0.591
+					c-1.351-0.929-3.351-0.929-4.351-1.929c16,7,27,22,30,39c2,21-8,41-27,50c-16,7.5-32.5,5.5-45.745-2.556
+					c-2.531-1.384-4.229-1.856-5.336-1.551c-1.919,0.107-3.919,2.107-5.919,2.107c4-1,6-5,10-6c-15,11-35,12-52,3c-13-7-20-20-24-34
+					c1,5,3,9,3.299,13.505c-0.396,0.708-3.423,2.219-6.654,3.466c-22.627,8.729-49.423,1.729-65.241-19.971
+					c-3.453,0-6.263,0.589-8.723,0.879c-17.301,3.2-32.382-7.709-40.771-22.689c-1.678-2.996-3.089-6.153-4.195-9.396
+					c-15.714-7.795-29.714-18.795-33.714-37.795c-5-25,11-45,29.842-57.667c0.72-2.335,1.697-4.636,3.007-6.896
+					C201.159,23.307,202.698,21.089,202.698,21.089z"/>
+				<g i:knockout="Off">
+					<path i:knockout="Off" fill="#FFFFFF" d="M269.719,186.307c0,4.602-4.179,8.333-9.333,8.333s-9.334-3.731-9.334-8.333
+						c0-4.603,4.18-8.333,9.334-8.333S269.719,181.705,269.719,186.307z"/>
+					<g i:knockout="Off">
+						<path i:knockout="Off" fill="none" d="M269.719,186.307c0,4.602-4.179,8.333-9.333,8.333s-9.334-3.731-9.334-8.333
+							c0-4.603,4.18-8.333,9.334-8.333S269.719,181.705,269.719,186.307z"/>
+						<path i:knockout="Off" fill="#FFFFFF" d="M268.225,186.166c-0.563,8.736-13.981,9.286-15.633,0.853
+							c-1.785-9.125,15.018-10.254,15.649-0.451c0.125,1.929,3.078,1.388,2.955-0.521c-0.814-12.597-20.828-12.412-21.64,0.119
+							c-0.827,12.813,20.831,13.028,21.655,0.283C271.337,184.519,268.35,184.235,268.225,186.166z"/>
+					</g>
+				</g>
+				<path i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M260.386,188.307c0,3.498-2.984,6.333-6.667,6.333
+					c-3.682,0-6.667-2.835-6.667-6.333s2.985-6.333,6.667-6.333C257.401,181.974,260.386,184.809,260.386,188.307z"/>
+				<path i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M238.386,196.974c0,1.289-1.045,2.333-2.334,2.333
+					c-1.288,0-2.333-1.045-2.333-2.333c0-1.288,1.045-2.333,2.333-2.333C237.341,194.64,238.386,195.685,238.386,196.974z"/>
+				<path i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M285.719,179.974c0,4.602-4.253,8.333-9.5,8.333
+					s-9.5-3.731-9.5-8.333c0-4.603,4.253-8.333,9.5-8.333S285.719,175.372,285.719,179.974z"/>
+			</g>
+			
+				<g id="yellBubble" i:knockout="Off" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#4F004F00FFFF" display="none">
+				<path i:knockout="Off" display="inline" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+					M251.156,176.051l40.228-15.992"/>
+				<path i:knockout="Off" display="inline" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="bevel" d="
+					M280.932,149.385l-40.667,36.42"/>
+				<path id="textContainer_2_" i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M217.778,34.644
+					c8.608,6.684,9.951,3.684,7.986-5.785c6.309,5.125,9.309,3.782,10.188-4.309c2.433,8.091,5.266,8.091,9.12-1.703
+					c6.063,9.793,13.146,9.793,24.043,3.878c6.103,5.915,16.02,5.915,20.094-4.64c17.178,10.555,28.511,10.555,45.233-5.505
+					c5.94,16.06,17.272,16.06,18.835,1.458c19.688,14.603,29.604,14.603,46.749-17.802c-0.145,32.405,6.938,32.405,29.26,16.182
+					c-12.403,16.223-9.57,16.223,4.813,6.576c-11.069,9.646-8.069,10.99,4.333,9.089c-8.061,6.244-6.717,9.244,2.533,11.068
+					c-9.25,1.489-9.25,5.703-0.314,13.07c-8.936,6.115-8.936,15.385,7.513,10.932c-16.447,24.677-16.447,35.631,14.938,36.553
+					c-31.385,19.303-31.385,28.571-4.39,40.526c-26.995,1.528-26.995,5.741-5.942,17.857c-21.053-8.801-22.396-5.802-9.525,11.916
+					c-17.213-13.374-20.213-12.03-12.048,8.029c-11.479-20.06-14.313-20.06-10.554,3.532c-13.676-23.591-20.759-23.591-29.813-2.664
+					c-7.944-20.927-17.861-20.927-27.072,12.467c-12.039-33.395-23.373-33.395-23.147-1.581
+					c-22.891-31.814-34.225-31.814-61.518-8.479c6.042-23.335-3.874-23.335-11.899-9.703c-8.976-13.632-16.059-13.632-23.927,4.361
+					c-2.049-17.993-4.882-17.993-10.51-1.486c2.314-16.508-0.686-17.851-12.385-5.019c7.355-17.175,6.013-20.176-10.271-7.879
+					c16.283-15.61,16.283-19.824-9.255-12.972c25.538-20.334,25.538-29.603,1.919-46.578c23.619-3.249,23.619-14.204-0.313-25.522
+					c23.933-8.905,23.933-18.175,7.798-37.429C226.385,48.854,226.385,44.641,217.778,34.644z"/>
+			</g>
+		</g>
+	</g>
+</svg>
diff --git a/dojox/gfx/demos/data/Nils.json b/dojox/gfx/demos/data/Nils.json
new file mode 100644
index 0000000..eee2a9f
--- /dev/null
+++ b/dojox/gfx/demos/data/Nils.json
@@ -0,0 +1,717 @@
+[
+	{
+		"name": "nils_1_", 
+		"children": [
+			{
+				"name": "lowerBody", 
+				"children": [
+					{
+						"name": "leftShoe", 
+						"children": [
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M44.787,442.042c13.536-0.097,28.515-2.647,40.667-8.815 c13.064-6.631,3.188-24.604,0.553-34.404c-5.771-1.73-10.549-4.837-16.568-0.148c-4.371,3.405-6.025,11.462-2.07,15.501 c-3.212,7.339-17.804,1.912-23.732,6.7c-5.825,4.706-7.32,17.966,0.484,21.167"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M133.453,425.375c0.901-2.979,2.793-5.781,4.667-8"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M56.787,426.708c-2.551-2.07-3.97-5.252-5.333-8"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "rightShoe", 
+						"children": [
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M111.453,402.042c-2.005-0.426-3.947-0.363-5.899-0.566 c-0.104,2.376,0.438,5.478,0.048,7.751c-0.4,2.327-1.597,4.06-2.146,6.817c-0.975,4.9,0.412,10.561,3.813,13.517 c3.718,3.23,8.442,2.56,12.87,3.797c4.256,1.189,7.959,3.502,12.5,4.849c9.169,2.717,20.433,7.657,25.649-4.685 c2.797-6.618-0.894-5.624-6.331-7.982c-4.049-1.757-6.774-4.353-10.32-7.014c-4.123-3.095-8.203-5.957-13.415-6.584 c-0.11-3.353,1.616-5.692,1.132-9.117c-5.299-2.318-13.883-3.984-19.233-0.116"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M62.787,424.708c-1.417-2.271-3.012-5.388-2.667-8.666"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M141.453,428.042c2.076-1.991,4.274-3.745,6-6"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "leftLeft", 
+						"shape": {
+							"type": "path", 
+							"path": "M111.687,360.891c0.036,4.747,1.844,9.223,1.56,14.078 c-0.24,4.099-1.372,8.075-1.553,12.199c-0.2,4.558-1.141,9.069-1.142,13.648c0,3.48-0.275,5.533,3.084,7.379 c2.301,1.264,4.909,1.163,7.094-0.113c2.993-1.748,2.841-3.747,2.868-6.904c0.025-2.952,0.712-5.943,1.162-8.841 c0.446-2.868,0.401-5.667,0.398-8.578c-0.004-3.788,0.138-7.556,0.003-11.357c-0.118-3.318-1.49-6.782-1.279-10.093"
+						}, 
+						"fill": "#FFF0A9", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"name": "rightLeg", 
+						"shape": {
+							"type": "path", 
+							"path": "M74.107,353.8c-0.57,1.485-0.055,3.729-0.142,5.357 c-0.076,1.44-0.315,2.774-0.571,4.184c-0.786,4.316-1,8.786-1.732,13.181c-1.158,6.942-0.906,14.193-1.777,21.167 c-0.456,3.648,0.862,8.169,5.499,7.139c2.579-0.572,4.859-3.016,5.846-5.361c2.937-6.981-0.974-13.832-0.457-21.057 c0.331-4.619,2.141-8.637,3.402-13.056c0.769-2.694,1.709-5.131,1.703-7.972c-0.004-1.809,0-3.616,0-5.425"
+						}, 
+						"fill": "#FFF0A9", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"name": "pants", 
+						"children": [
+							{
+								"name": "pants_1_", 
+								"shape": {
+									"type": "path", 
+									"path": "M72.453,299.375 c1.947,19.47-1.848,38.143-0.849,57.849c3.905,0.681,11.166,0.417,14.849-0.849c7.135-2.453,6.497-2.631,7-11 c0.81-13.479-2.849-20.278,12.845-17.853c-1.125,13.305-9.43,25.115-3.42,38.649c8.404-0.38,20.265,0.661,28.427-1.944 c0.505-10.198-1.523-17.622-2.853-26.853c-1.398-9.708,3.313-18.866-1.174-27.826c-9.218,0.693-18.358,2.747-27.722,0.798 c-9.863-2.054-18.89-8.623-29.104-8.972"
+								}, 
+								"fill": "#ADA274", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}
+				]
+			}, 
+			{
+				"name": "leftArm_1_", 
+				"children": [
+					{
+						"name": "leftArm", 
+						"shape": {
+							"type": "path", 
+							"path": "M161.453,199.375c-6.73,0.606-12.711,7.192-9.248,13.248 c3.358,5.87,13.618,5.538,19.021,6.979c4,1.066,16.837,3.192,19.52,5.703c3.974,3.72,5.243,15.844,5.854,20.924 c13.641,4.354,26.949-0.671,33.102-13.826c5.331-11.398-5.783-19.505-17.098-22.174c1.771-8.465,14.167-32.061-0.128-36.899 c-4.761-1.611-15.726,3.346-17.801,7.272c-3.095,5.855-0.055,15.902-0.374,22.623c-13.399,0.68-27.351-3.555-39.849-1.849"
+						}, 
+						"fill": "#FFF0A9", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M221.453,220.375c-4.604-1.889-17.369-6.456-21.801-1.801 c-4.797,5.039,1.256,14.077,6.027,16.578c4.118,2.159,20.628,4.348,24.575,1c4.999-4.241,2.906-14.993-2.801-17.777"
+						}, 
+						"fill": "#FFF0A9", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M214.453,253.375c-1.006,3.482-0.767,9-3.174,12.826 c-15.878,0.834-16.244-5.43-25.674-14.571c10.53-5.253,19.583,4.754,29.849,2.745"
+						}, 
+						"fill": "#FFF0A9", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M226.453,239.375c0.54,16.962-8.377,15.391-21.023,12.023 c-17.34-4.617-11.577-7.176,3.023-13.023"
+						}, 
+						"fill": "#FFF0A9", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M208.453,188.375c-4.474,0.83-8.972-0.434-11-4"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M203.453,221.375c6.112-0.45,18.967,6.649,8,10"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M195.453,258.375c3.441-0.666,5.408-2.2,4-5"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}
+				]
+			}, 
+			{
+				"name": "rightArm", 
+				"children": [
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M39.453,187.375c-3.104,7.216-3.137,14.998-7.278,21.997 c-5.137,8.684-9.794,6.9-17.5,12.281c-8.803,6.146-12.141,29.697-14.095,40.548c20.2,3.536,18.779-23.776,21.649-34.524 c0.975,13.012-0.289,26.468,0.374,39.546c2.257,0.582,6.44,0.582,8.697,0c2.04-10.494-3.53-22.034-0.852-33.546 c0.009,7.58-2.598,32.2,10.852,28.546c0.514-10.124-1.899-18.938-4.868-25.972c2.181,8.766,4.798,18.48,15.845,15.949 c6.407-12.781-3.909-15.105-8.048-25.604c-2.531-6.422,0.527-25.44,6.223-31.223"
+						}, 
+						"fill": "#FFF0A9", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M6.453,248.042c2.111,0,6.324-0.997,6.667,1.666"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M22.453,255.375c2.85-0.37,4.155,0.539,4.999,3.001 c1.085,3.168-0.233,4.173-2.999,5.332"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M31.787,255.042c3.675-0.503,7.077,4.971,3,6"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M48.453,235.708c-5.387-0.935-3.676,10.551,3.667,8.667"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}, 
+					{
+						"shape": {
+							"type": "path", 
+							"path": "M207.453,241.375c2.63,1.686,2.368,4.909,1.884,7.884 c-0.744,0.175-1.23,0.456-1.884,0.783"
+						}, 
+						"fill": "none", 
+						"stroke": {
+							"color": "#000000"
+						}
+					}
+				]
+			}, 
+			{
+				"name": "shirt", 
+				"children": [
+					{
+						"name": "mainShirt", 
+						"shape": {
+							"type": "path", 
+							"path": "M39.453,189.375 c0.777-3.467,1.211-7.217,1.151-10.849c14.871-1.403,32.372-7.656,46.875-11.125c9.423-2.254,31.959-20.14,39.244-11.079 c3.778,4.7,2.066,16.102,5.456,22.08c2.827,4.986,9.093,12.445,13.003,16.217c5.193,5.009,15.695-3.271,18.271,2.754 c3.024,7.075-0.511,20.739-10.02,18.016c-5.084-1.456-12.238-5.093-15.228-9.769c-4.055-6.341-8.831-13.012-10.53-19.167 c-0.713,10.697,1.173,22.369,2.726,32.92c1.637,11.128,1.886,22.261,3.052,34c2.02,20.336,6.915,42.053,10.845,61.855 [...]
+						}, 
+						"fill": "#4867FF", 
+						"stroke": {
+							"color": "#000000", 
+							"width": "2"
+						}
+					}, 
+					{
+						"name": "highlight", 
+						"shape": {
+							"type": "path", 
+							"path": "M99.453,179.375 c-5.364,2.937-10.603,8.065-17,8"
+						}, 
+						"fill": "#4867FF", 
+						"stroke": {
+							"color": "#000000", 
+							"width": "2"
+						}
+					}, 
+					{
+						"name": "logo", 
+						"children": [
+						]
+					}
+				]
+			}, 
+			{
+				"name": "heads", 
+				"children": [
+					{
+						"name": "head1", 
+						"children": [
+							{
+								"name": "hair_1_", 
+								"shape": {
+									"type": "path", 
+									"path": "M60.453,97.375c-3.965-0.012-7.98,0.045-11.897-0.147 c2.645-5.735,10.791-8.417,14.794-13.65c-2.384,0.19-5.083-0.61-7.543-0.154c2.395-1.359,4.008-3.487,6.347-4.846 c-2.993-0.207-6.326-0.467-9.399-0.18c2.893-0.874,5.243-2.063,7.821-3.05c-0.92-0.166-4.625-2.732-6.772-4.221 c5.187-4.255,12.317-5.834,17.573-8.534c-2.844-0.13-5.037-1.713-7.75-2.393c-0.424-7.244-1.302-14.461-1.223-21.475 c2.166,2.761,3.541,5.976,4.849,8.546c-0.996-11.489,4.773-13.594,13.025-18.797c0.403,1.91,1. [...]
+								}, 
+								"fill": "#605542", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"name": "neck", 
+								"shape": {
+									"type": "path", 
+									"path": "M108.453,132.375c0.902,8.412-0.835,20.235-3.849,27.797 c4.164,2.769,15.721,4.339,19.868,0c3.538-3.701,1.964-17.522,1.98-22.797"
+								}, 
+								"fill": "#FFF0A9", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"name": "leftEar_1_", 
+								"children": [
+									{
+										"name": "leftEar", 
+										"shape": {
+											"type": "path", 
+											"path": "M232.453,76.375c10.186-6.915,21.465,6.994,19.052,17 c-2.781,11.53-20.253,15.518-27.052,5"
+										}, 
+										"fill": "#FFF0A9", 
+										"stroke": {
+											"color": "#000000"
+										}
+									}, 
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M245.453,91.375c-0.398-2.267-1.99-4.77-3.171-6.829 c-2.738-0.936-5.713-1.545-8.829-1.171"
+										}, 
+										"fill": "none", 
+										"stroke": {
+											"color": "#000000"
+										}
+									}, 
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M238.453,90.375c1.863-0.367,3.589-1.433,5-3"
+										}, 
+										"fill": "none", 
+										"stroke": {
+											"color": "#000000"
+										}
+									}
+								]
+							}, 
+							{
+								"name": "headShape", 
+								"shape": {
+									"type": "path", 
+									"path": "M116.453,35.375 c-13.417,2.219-31.83,24.639-39.777,35.055c-8.128,10.652-24.737,25.747-20.219,39.945 c5.161,16.221,22.089,14.526,34.025,19.972c15.448,7.047,30.645,11.875,46.749,14.251c18.146,2.676,27.633,0.161,44.223-7.972 c15.701-7.697,29.862-9.589,41.801-24.303c8.182-10.084,15.033-28.733,8.174-38.923c-6.159-9.151-21.79-19.289-31.201-25.75 c-12.144-8.339-26.876-10.032-41-11.274c-15.007-1.32-33.207-3.056-47.774,1"
+								}, 
+								"fill": "#FFF0A9", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"name": "rightEar_1_", 
+								"children": [
+									{
+										"name": "rightEar", 
+										"shape": {
+											"type": "path", 
+											"path": "M66.453,94.375 c-10.188-4.124-23.701-5.729-27.774,7.226c-4.779,15.198,14.506,23.077,25.774,15.774"
+										}, 
+										"fill": "#FFF0A9", 
+										"stroke": {
+											"color": "#000000"
+										}
+									}, 
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M42.453,106.375c4.149-4.954,11.06-7.737,16-10"
+										}, 
+										"fill": "none", 
+										"stroke": {
+											"color": "#000000"
+										}
+									}, 
+									{
+										"shape": {
+											"type": "path", 
+											"path": "M48.453,100.375c1.337,3.541,2.787,6.955,5,10"
+										}, 
+										"fill": "none", 
+										"stroke": {
+											"color": "#000000"
+										}
+									}
+								]
+							}, 
+							{
+								"name": "adamsApple", 
+								"shape": {
+									"type": "path", 
+									"path": "M113.453,152.375c-0.526-2.327,1.546-3.837,5-4"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}
+				]
+			}, 
+			{
+				"name": "expressions", 
+				"children": [
+					{
+						"name": "confused", 
+						"children": [
+							{
+								"name": "mouth_1_", 
+								"children": [
+									{
+										"name": "mouth", 
+										"shape": {
+											"type": "path", 
+											"path": "M102.148,120.014c13.398-6.9,33.568-7.688,49-10.026 c12.555-1.903,36.519-2.575,44,9.026"
+										}, 
+										"fill": "none", 
+										"stroke": {
+											"color": "#000000"
+										}
+									}, 
+									{
+										"name": "tooth_1_", 
+										"shape": {
+											"type": "path", 
+											"path": "M178.148,109.014 c-0.563-2.655-0.017-6.196,0.151-8.849c4.788-0.944,9.637,0.768,13.675,3.022c0.664,3.187,0.065,6.267-1.826,8.826"
+										}, 
+										"fill": "#FFFFFF", 
+										"stroke": {
+											"color": "#000000"
+										}
+									}, 
+									{
+										"name": "tooth", 
+										"shape": {
+											"type": "path", 
+											"path": "M168.148,108.014c-2.021-7.958,5.04-7.752,10.826-6.826 c1.286,2.446,1.752,5.863,1.022,8.675c-3.801,0.292-8.049,0.308-10.849-0.849"
+										}, 
+										"fill": "#FFFFFF", 
+										"stroke": {
+											"color": "#000000"
+										}
+									}
+								]
+							}, 
+							{
+								"name": "eyes", 
+								"children": [
+									{
+										"name": "rightEye", 
+										"shape": {
+											"type": "path", 
+											"path": "M121.148,52.014 c-6.562,8.145-20.057,16.28-21.023,26.977c-1.104,12.227,10.759,15.164,21.02,11.798c18.8-6.168,24.482-40.499,0.004-39.774"
+										}, 
+										"fill": "#FFFFFF", 
+										"stroke": {
+											"color": "#000000"
+										}
+									}, 
+									{
+										"name": "pupilRight", 
+										"shape": {
+											"type": "path", 
+											"path": "M112.148,61.014c-7.625,3.067-4.047,12.428,3.826,10.826 C118.354,67.432,118.046,61.261,112.148,61.014"
+										}, 
+										"stroke": {
+											"color": "#000000"
+										}
+									}, 
+									{
+										"name": "leftEye", 
+										"shape": {
+											"type": "path", 
+											"path": "M184.148,55.014c-13.391-8.758-17.664,28.504,5,25.996 c10.862-1.201,14.124-12.581,8.004-19.996c-6.121-7.415-14.988-4.947-22.004-8"
+										}, 
+										"fill": "#FFFFFF", 
+										"stroke": {
+											"color": "#000000"
+										}
+									}, 
+									{
+										"name": "pupilLeft", 
+										"shape": {
+											"type": "path", 
+											"path": "M176.148,54.014c-2.04,2.896-2.657,6.347-1.849,9.849 C184.707,66.621,182.108,56.322,176.148,54.014"
+										}, 
+										"stroke": {
+											"color": "#000000"
+										}
+									}
+								]
+							}
+						]
+					}, 
+					{
+						"name": "confused2", 
+						"children": [
+							{
+								"name": "rightEye_1_", 
+								"shape": {
+									"type": "path", 
+									"path": "M121.148,52.014 c-6.562,8.145-20.057,16.28-21.023,26.977c-1.104,12.227,10.759,15.164,21.02,11.798c18.8-6.168,24.482-40.499,0.004-39.774"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"name": "pupilRight_1_", 
+								"shape": {
+									"type": "path", 
+									"path": "M112.148,61.014 c-7.625,3.067-4.047,12.428,3.826,10.826C118.354,67.432,118.046,61.261,112.148,61.014"
+								}, 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"name": "leftEye_1_", 
+								"shape": {
+									"type": "path", 
+									"path": "M184.148,55.014 c-13.391-8.758-17.664,28.504,5,25.996c10.862-1.201,14.124-12.581,8.004-19.996c-6.121-7.415-14.988-4.947-22.004-8"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"name": "pupilLeft_1_", 
+								"shape": {
+									"type": "path", 
+									"path": "M176.148,54.014 c-2.04,2.896-2.657,6.347-1.849,9.849C184.707,66.621,182.108,56.322,176.148,54.014"
+								}, 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M114.934,118.74 c18.933-4.896,31.704-2.456,49.826,1.171c6.734,1.348,17.654,7.566,23.408,0.323c5.436-6.841-0.011-16.179-7.237-17.994"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "talking", 
+						"children": [
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M150.536,116.479c0.413,18.115,48.746,18.222,37.276-7.278 c-10.396-1.757-28.836,2.451-38.776,5.778"
+								}, 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M103.453,104.875c-2.277,2.169-1.729,7.324-4.849,8 c8.889,3.074,18.975,7.877,28.849,6.998c6.759-0.602,18.439-1.511,23.5-5.998"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M104.453,64.875 c-6.218-0.224-17.093,9.247-13.875,15.887c2.822,5.825,15.087,4.174,20.375,3.113c4.505-0.904,7.783-1.37,9.889-6.123 c1.107-2.499,2.855-9.088,1.623-11.889c-2.859-6.496-15.374-3.248-19.512,0.012"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M176.953,59.875 c-4.742,8.403,0.46,13.596,6.486,18.376c4.779,3.791,15.903,8.529,19.512,0.622c8.012-17.554-22.026-19.554-32.498-17.887 c-0.345,0.055-1.151,0.291-1.5,0.389"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M98.953,66.875c-6.969-2.545-10.165,5.418-3.002,8.05 c2.178-2.129,5.596-6.88,2.502-9.05"
+								}, 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M178.453,60.875c-5.534,0.708-5.259,9.173,0.5,7.387 c6.145-1.906,5.217-9.047-1.5-8.387"
+								}, 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}, 
+					{
+						"name": "talking2", 
+						"children": [
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M102.87,94.503c-2.279,15.037-5.934,27.828,15.027,23.027 c15.334-3.512,25.379-13.239,28.973-28.027"
+								}, 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M92.87,104.503 c4.248-16.004,34.717-10.765,47.052-11.948c8.414-0.807,15.879-1.97,24.948-1.055c8.295,0.837,19.3,2.941,27-0.997"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M84.87,73.503c2.341-8.752,12.467-12.772,19-18"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M181.87,59.503c8.968-3.27,16.681,2.245,25,3"
+								}, 
+								"fill": "none", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M98.87,68.503 c-7.218,11.165,3.031,17.234,13.003,17.997c13.201,1.009,21.125-8.677,18.845-21.842c-11.637-0.604-21.219,1.818-31.849,2.845"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M178.87,67.503 c-9.045,2.007-6.264,11.616-1.249,15.249c3.778,2.737,13.479,4.477,18.249,2.528C210.946,79.123,185.327,71.038,178.87,67.503"
+								}, 
+								"fill": "#FFFFFF", 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M115.87,85.503c2.365-1.63,3.646-3.553,2.826-6.826 c-16.491-8.159-17.436,11.182-1.826,8.826"
+								}, 
+								"stroke": {
+									"color": "#000000"
+								}
+							}, 
+							{
+								"shape": {
+									"type": "path", 
+									"path": "M174.87,80.503c-0.492-1.165-0.677-2.687-0.872-3.826 c3.483-0.285,7.207-0.292,10.698-0.023c3.568,7.301-6.079,7.593-10.826,5.849"
+								}, 
+								"stroke": {
+									"color": "#000000"
+								}
+							}
+						]
+					}
+				]
+			}
+		]
+	}
+]
\ No newline at end of file
diff --git a/dojox/gfx/demos/data/Nils.svg b/dojox/gfx/demos/data/Nils.svg
new file mode 100644
index 0000000..e2e57be
--- /dev/null
+++ b/dojox/gfx/demos/data/Nils.svg
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/">
+	<g id="nils_1_" i:isolated="yes" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFF4F004F00" enable-background="new    ">
+		<g id="lowerBody" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFFFFFF4F00">
+			<g id="leftShoe" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFF4F00FFFF">
+				<path i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M44.787,442.042c13.536-0.097,28.515-2.647,40.667-8.815
+					c13.064-6.631,3.188-24.604,0.553-34.404c-5.771-1.73-10.549-4.837-16.568-0.148c-4.371,3.405-6.025,11.462-2.07,15.501
+					c-3.212,7.339-17.804,1.912-23.732,6.7c-5.825,4.706-7.32,17.966,0.484,21.167"/>
+				<path i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M133.453,425.375c0.901-2.979,2.793-5.781,4.667-8"/>
+				<path i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M56.787,426.708c-2.551-2.07-3.97-5.252-5.333-8"/>
+			</g>
+			<g id="rightShoe" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFFFFFF">
+				<path i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M111.453,402.042c-2.005-0.426-3.947-0.363-5.899-0.566
+					c-0.104,2.376,0.438,5.478,0.048,7.751c-0.4,2.327-1.597,4.06-2.146,6.817c-0.975,4.9,0.412,10.561,3.813,13.517
+					c3.718,3.23,8.442,2.56,12.87,3.797c4.256,1.189,7.959,3.502,12.5,4.849c9.169,2.717,20.433,7.657,25.649-4.685
+					c2.797-6.618-0.894-5.624-6.331-7.982c-4.049-1.757-6.774-4.353-10.32-7.014c-4.123-3.095-8.203-5.957-13.415-6.584
+					c-0.11-3.353,1.616-5.692,1.132-9.117c-5.299-2.318-13.883-3.984-19.233-0.116"/>
+				<path i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M62.787,424.708c-1.417-2.271-3.012-5.388-2.667-8.666"/>
+				<path i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M141.453,428.042c2.076-1.991,4.274-3.745,6-6"/>
+			</g>
+			<path id="leftLeft" i:knockout="Off" fill="#FFF0A9" stroke="#000000" d="M111.687,360.891c0.036,4.747,1.844,9.223,1.56,14.078
+				c-0.24,4.099-1.372,8.075-1.553,12.199c-0.2,4.558-1.141,9.069-1.142,13.648c0,3.48-0.275,5.533,3.084,7.379
+				c2.301,1.264,4.909,1.163,7.094-0.113c2.993-1.748,2.841-3.747,2.868-6.904c0.025-2.952,0.712-5.943,1.162-8.841
+				c0.446-2.868,0.401-5.667,0.398-8.578c-0.004-3.788,0.138-7.556,0.003-11.357c-0.118-3.318-1.49-6.782-1.279-10.093"/>
+			<path id="rightLeg" i:knockout="Off" fill="#FFF0A9" stroke="#000000" d="M74.107,353.8c-0.57,1.485-0.055,3.729-0.142,5.357
+				c-0.076,1.44-0.315,2.774-0.571,4.184c-0.786,4.316-1,8.786-1.732,13.181c-1.158,6.942-0.906,14.193-1.777,21.167
+				c-0.456,3.648,0.862,8.169,5.499,7.139c2.579-0.572,4.859-3.016,5.846-5.361c2.937-6.981-0.974-13.832-0.457-21.057
+				c0.331-4.619,2.141-8.637,3.402-13.056c0.769-2.694,1.709-5.131,1.703-7.972c-0.004-1.809,0-3.616,0-5.425"/>
+			<g id="pants" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFF4F00">
+				<path id="pants_1_" i:knockout="Off" fill="#ADA274" stroke="#000000" d="M72.453,299.375
+					c1.947,19.47-1.848,38.143-0.849,57.849c3.905,0.681,11.166,0.417,14.849-0.849c7.135-2.453,6.497-2.631,7-11
+					c0.81-13.479-2.849-20.278,12.845-17.853c-1.125,13.305-9.43,25.115-3.42,38.649c8.404-0.38,20.265,0.661,28.427-1.944
+					c0.505-10.198-1.523-17.622-2.853-26.853c-1.398-9.708,3.313-18.866-1.174-27.826c-9.218,0.693-18.358,2.747-27.722,0.798
+					c-9.863-2.054-18.89-8.623-29.104-8.972"/>
+			</g>
+		</g>
+		<g id="leftArm_1_" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFFFFFF">
+			<path id="leftArm" i:knockout="Off" fill="#FFF0A9" stroke="#000000" d="M161.453,199.375c-6.73,0.606-12.711,7.192-9.248,13.248
+				c3.358,5.87,13.618,5.538,19.021,6.979c4,1.066,16.837,3.192,19.52,5.703c3.974,3.72,5.243,15.844,5.854,20.924
+				c13.641,4.354,26.949-0.671,33.102-13.826c5.331-11.398-5.783-19.505-17.098-22.174c1.771-8.465,14.167-32.061-0.128-36.899
+				c-4.761-1.611-15.726,3.346-17.801,7.272c-3.095,5.855-0.055,15.902-0.374,22.623c-13.399,0.68-27.351-3.555-39.849-1.849"/>
+			<path i:knockout="Off" fill="#FFF0A9" stroke="#000000" d="M221.453,220.375c-4.604-1.889-17.369-6.456-21.801-1.801
+				c-4.797,5.039,1.256,14.077,6.027,16.578c4.118,2.159,20.628,4.348,24.575,1c4.999-4.241,2.906-14.993-2.801-17.777"/>
+			<path i:knockout="Off" fill="#FFF0A9" stroke="#000000" d="M214.453,253.375c-1.006,3.482-0.767,9-3.174,12.826
+				c-15.878,0.834-16.244-5.43-25.674-14.571c10.53-5.253,19.583,4.754,29.849,2.745"/>
+			<path i:knockout="Off" fill="#FFF0A9" stroke="#000000" d="M226.453,239.375c0.54,16.962-8.377,15.391-21.023,12.023
+				c-17.34-4.617-11.577-7.176,3.023-13.023"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M208.453,188.375c-4.474,0.83-8.972-0.434-11-4"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M203.453,221.375c6.112-0.45,18.967,6.649,8,10"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M195.453,258.375c3.441-0.666,5.408-2.2,4-5"/>
+		</g>
+		<g id="rightArm" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFF4F00">
+			<path i:knockout="Off" fill="#FFF0A9" stroke="#000000" d="M39.453,187.375c-3.104,7.216-3.137,14.998-7.278,21.997
+				c-5.137,8.684-9.794,6.9-17.5,12.281c-8.803,6.146-12.141,29.697-14.095,40.548c20.2,3.536,18.779-23.776,21.649-34.524
+				c0.975,13.012-0.289,26.468,0.374,39.546c2.257,0.582,6.44,0.582,8.697,0c2.04-10.494-3.53-22.034-0.852-33.546
+				c0.009,7.58-2.598,32.2,10.852,28.546c0.514-10.124-1.899-18.938-4.868-25.972c2.181,8.766,4.798,18.48,15.845,15.949
+				c6.407-12.781-3.909-15.105-8.048-25.604c-2.531-6.422,0.527-25.44,6.223-31.223"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M6.453,248.042c2.111,0,6.324-0.997,6.667,1.666"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M22.453,255.375c2.85-0.37,4.155,0.539,4.999,3.001
+				c1.085,3.168-0.233,4.173-2.999,5.332"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M31.787,255.042c3.675-0.503,7.077,4.971,3,6"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M48.453,235.708c-5.387-0.935-3.676,10.551,3.667,8.667"/>
+			<path i:knockout="Off" fill="none" stroke="#000000" d="M207.453,241.375c2.63,1.686,2.368,4.909,1.884,7.884
+				c-0.744,0.175-1.23,0.456-1.884,0.783"/>
+		</g>
+		<g id="shirt" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFFFFFF4F00">
+			<path id="mainShirt" i:knockout="Off" fill="#4867FF" stroke="#000000" stroke-width="2" d="M39.453,189.375
+				c0.777-3.467,1.211-7.217,1.151-10.849c14.871-1.403,32.372-7.656,46.875-11.125c9.423-2.254,31.959-20.14,39.244-11.079
+				c3.778,4.7,2.066,16.102,5.456,22.08c2.827,4.986,9.093,12.445,13.003,16.217c5.193,5.009,15.695-3.271,18.271,2.754
+				c3.024,7.075-0.511,20.739-10.02,18.016c-5.084-1.456-12.238-5.093-15.228-9.769c-4.055-6.341-8.831-13.012-10.53-19.167
+				c-0.713,10.697,1.173,22.369,2.726,32.92c1.637,11.128,1.886,22.261,3.052,34c2.02,20.336,6.915,42.053,10.845,61.855
+				c-14.599,4.091-47.868-3.832-47.868-3.832s-14.457-3.595-21.2-5.801c-8.131-2.661-21.777-11.223-13.777-11.223
+				s-3.063-9.756,2.468-40.878s14.003-39.61,19.806-56.122c1.387-3.946,2.399-8.004,4.375-11.845
+				c-17.565,1.273-26.117,7.964-40.475,16.742c-2.413-9.11-9.707-14.336-17.174-18.897"/>
+			<path id="highlight" i:knockout="Off" fill="#4867FF" stroke="#000000" stroke-width="2" d="M99.453,179.375
+				c-5.364,2.937-10.603,8.065-17,8"/>
+			<g id="logo" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFF4F00FFFF">
+			</g>
+		</g>
+		<g id="heads" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFF4F004F00">
+			<g id="head1" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFF4F00">
+				<path id="hair_1_" i:knockout="Off" fill="#605542" stroke="#000000" d="M60.453,97.375c-3.965-0.012-7.98,0.045-11.897-0.147
+					c2.645-5.735,10.791-8.417,14.794-13.65c-2.384,0.19-5.083-0.61-7.543-0.154c2.395-1.359,4.008-3.487,6.347-4.846
+					c-2.993-0.207-6.326-0.467-9.399-0.18c2.893-0.874,5.243-2.063,7.821-3.05c-0.92-0.166-4.625-2.732-6.772-4.221
+					c5.187-4.255,12.317-5.834,17.573-8.534c-2.844-0.13-5.037-1.713-7.75-2.393c-0.424-7.244-1.302-14.461-1.223-21.475
+					c2.166,2.761,3.541,5.976,4.849,8.546c-0.996-11.489,4.773-13.594,13.025-18.797c0.403,1.91,1.943,3.845,2.229,5.546
+					c1.27-13.312,22.924-28.644,34.016-33.272c0.039,6.247-2.955,11.957-5.365,17.475c-0.365,0.375-0.375,0.366-0.028-0.028
+					c5.849-6.92,14-8.882,22.143-10.721c-1.215,5.635-5.28,10.684-6.698,16.602c6.258-10.069,20.421-4.135,27.949-11.351
+					c-1.011,3.251-2.028,6.254-3.143,9.276c7.035-8.774,15.902-11.37,25.894-14.499c-0.668,7.995-10.243,18.061-0.822,20.872
+					c8.889,2.653,17.435-7.31,26.698-6.075c-2.976,1.954-5.822,4.12-8.614,6.345c7.596,2.01,18.243,0.852,26.614,0.658
+					c-4.125,3.304-9.116,7.352-9.593,12.943c3.896-0.826,8.6-1.318,12.741-0.725c-1.013,1.726-1.479,5.845-2.718,7.678
+					c3.136-0.265,6.17,1.053,8.519,1.452c-3.019,0.804-5.247,3.16-7.566,4.52c3.765,0.755,7.282,2.001,10.844,3.398
+					c-3.322,1.78-5.724,5.475-4.776,9.657c0.798,0.374,2.536,0.977,2.995,1.147c-6.481,3.645-21.331-1.522-28.945-2.752
+					c-13.967-2.257-27.844-4.641-41.913-6.244c-17.039-1.941-37.716-3.446-54.359,1.025C83.983,67.42,68.871,76.651,58.453,98.375"
+					/>
+				<path id="neck" i:knockout="Off" fill="#FFF0A9" stroke="#000000" d="M108.453,132.375c0.902,8.412-0.835,20.235-3.849,27.797
+					c4.164,2.769,15.721,4.339,19.868,0c3.538-3.701,1.964-17.522,1.98-22.797"/>
+				<g id="leftEar_1_" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F00FFFFFFFF">
+					<path id="leftEar" i:knockout="Off" fill="#FFF0A9" stroke="#000000" d="M232.453,76.375c10.186-6.915,21.465,6.994,19.052,17
+						c-2.781,11.53-20.253,15.518-27.052,5"/>
+					<path i:knockout="Off" fill="none" stroke="#000000" d="M245.453,91.375c-0.398-2.267-1.99-4.77-3.171-6.829
+						c-2.738-0.936-5.713-1.545-8.829-1.171"/>
+					<path i:knockout="Off" fill="none" stroke="#000000" d="M238.453,90.375c1.863-0.367,3.589-1.433,5-3"/>
+				</g>
+				<path id="headShape" i:knockout="Off" fill="#FFF0A9" stroke="#000000" d="M116.453,35.375
+					c-13.417,2.219-31.83,24.639-39.777,35.055c-8.128,10.652-24.737,25.747-20.219,39.945
+					c5.161,16.221,22.089,14.526,34.025,19.972c15.448,7.047,30.645,11.875,46.749,14.251c18.146,2.676,27.633,0.161,44.223-7.972
+					c15.701-7.697,29.862-9.589,41.801-24.303c8.182-10.084,15.033-28.733,8.174-38.923c-6.159-9.151-21.79-19.289-31.201-25.75
+					c-12.144-8.339-26.876-10.032-41-11.274c-15.007-1.32-33.207-3.056-47.774,1"/>
+				<g id="rightEar_1_" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#FFFF4F00FFFF">
+					<path id="rightEar" i:knockout="Off" fill="#FFF0A9" stroke="#000000" d="M66.453,94.375
+						c-10.188-4.124-23.701-5.729-27.774,7.226c-4.779,15.198,14.506,23.077,25.774,15.774"/>
+					<path i:knockout="Off" fill="none" stroke="#000000" d="M42.453,106.375c4.149-4.954,11.06-7.737,16-10"/>
+					<path i:knockout="Off" fill="none" stroke="#000000" d="M48.453,100.375c1.337,3.541,2.787,6.955,5,10"/>
+				</g>
+				<path id="adamsApple" i:knockout="Off" fill="none" stroke="#000000" d="M113.453,152.375c-0.526-2.327,1.546-3.837,5-4"/>
+			</g>
+		</g>
+		<g id="expressions" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#800080008000">
+			<g id="confused" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#000000000000">
+				<g id="mouth_1_" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F008000FFFF">
+					<path id="mouth" i:knockout="Off" fill="none" stroke="#000000" d="M102.148,120.014c13.398-6.9,33.568-7.688,49-10.026
+						c12.555-1.903,36.519-2.575,44,9.026"/>
+					<path id="tooth_1_" i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M178.148,109.014
+						c-0.563-2.655-0.017-6.196,0.151-8.849c4.788-0.944,9.637,0.768,13.675,3.022c0.664,3.187,0.065,6.267-1.826,8.826"/>
+					<path id="tooth" i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M168.148,108.014c-2.021-7.958,5.04-7.752,10.826-6.826
+						c1.286,2.446,1.752,5.863,1.022,8.675c-3.801,0.292-8.049,0.308-10.849-0.849"/>
+				</g>
+				<g id="eyes" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F008000FFFF">
+					<path id="rightEye" i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M121.148,52.014
+						c-6.562,8.145-20.057,16.28-21.023,26.977c-1.104,12.227,10.759,15.164,21.02,11.798c18.8-6.168,24.482-40.499,0.004-39.774"/>
+					<path id="pupilRight" i:knockout="Off" stroke="#000000" d="M112.148,61.014c-7.625,3.067-4.047,12.428,3.826,10.826
+						C118.354,67.432,118.046,61.261,112.148,61.014"/>
+					<path id="leftEye" i:knockout="Off" fill="#FFFFFF" stroke="#000000" d="M184.148,55.014c-13.391-8.758-17.664,28.504,5,25.996
+						c10.862-1.201,14.124-12.581,8.004-19.996c-6.121-7.415-14.988-4.947-22.004-8"/>
+					<path id="pupilLeft" i:knockout="Off" stroke="#000000" d="M176.148,54.014c-2.04,2.896-2.657,6.347-1.849,9.849
+						C184.707,66.621,182.108,56.322,176.148,54.014"/>
+				</g>
+			</g>
+			<g id="confused2" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#000000000000" display="none">
+				<path id="rightEye_1_" i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M121.148,52.014
+					c-6.562,8.145-20.057,16.28-21.023,26.977c-1.104,12.227,10.759,15.164,21.02,11.798c18.8-6.168,24.482-40.499,0.004-39.774"/>
+				<path id="pupilRight_1_" i:knockout="Off" display="inline" stroke="#000000" d="M112.148,61.014
+					c-7.625,3.067-4.047,12.428,3.826,10.826C118.354,67.432,118.046,61.261,112.148,61.014"/>
+				<path id="leftEye_1_" i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M184.148,55.014
+					c-13.391-8.758-17.664,28.504,5,25.996c10.862-1.201,14.124-12.581,8.004-19.996c-6.121-7.415-14.988-4.947-22.004-8"/>
+				<path id="pupilLeft_1_" i:knockout="Off" display="inline" stroke="#000000" d="M176.148,54.014
+					c-2.04,2.896-2.657,6.347-1.849,9.849C184.707,66.621,182.108,56.322,176.148,54.014"/>
+				<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M114.934,118.74
+					c18.933-4.896,31.704-2.456,49.826,1.171c6.734,1.348,17.654,7.566,23.408,0.323c5.436-6.841-0.011-16.179-7.237-17.994"/>
+			</g>
+			<g id="talking" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#000000000000" display="none">
+				<path i:knockout="Off" display="inline" stroke="#000000" d="M150.536,116.479c0.413,18.115,48.746,18.222,37.276-7.278
+					c-10.396-1.757-28.836,2.451-38.776,5.778"/>
+				<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M103.453,104.875c-2.277,2.169-1.729,7.324-4.849,8
+					c8.889,3.074,18.975,7.877,28.849,6.998c6.759-0.602,18.439-1.511,23.5-5.998"/>
+				<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M104.453,64.875
+					c-6.218-0.224-17.093,9.247-13.875,15.887c2.822,5.825,15.087,4.174,20.375,3.113c4.505-0.904,7.783-1.37,9.889-6.123
+					c1.107-2.499,2.855-9.088,1.623-11.889c-2.859-6.496-15.374-3.248-19.512,0.012"/>
+				<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M176.953,59.875
+					c-4.742,8.403,0.46,13.596,6.486,18.376c4.779,3.791,15.903,8.529,19.512,0.622c8.012-17.554-22.026-19.554-32.498-17.887
+					c-0.345,0.055-1.151,0.291-1.5,0.389"/>
+				<path i:knockout="Off" display="inline" stroke="#000000" d="M98.953,66.875c-6.969-2.545-10.165,5.418-3.002,8.05
+					c2.178-2.129,5.596-6.88,2.502-9.05"/>
+				<path i:knockout="Off" display="inline" stroke="#000000" d="M178.453,60.875c-5.534,0.708-5.259,9.173,0.5,7.387
+					c6.145-1.906,5.217-9.047-1.5-8.387"/>
+			</g>
+			<g id="talking2" i:layer="yes" i:visible="no" i:dimmedPercent="50" i:rgbTrio="#000000000000" display="none">
+				<path i:knockout="Off" display="inline" stroke="#000000" d="M102.87,94.503c-2.279,15.037-5.934,27.828,15.027,23.027
+					c15.334-3.512,25.379-13.239,28.973-28.027"/>
+				<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M92.87,104.503
+					c4.248-16.004,34.717-10.765,47.052-11.948c8.414-0.807,15.879-1.97,24.948-1.055c8.295,0.837,19.3,2.941,27-0.997"/>
+				<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M84.87,73.503c2.341-8.752,12.467-12.772,19-18"/>
+				<path i:knockout="Off" display="inline" fill="none" stroke="#000000" d="M181.87,59.503c8.968-3.27,16.681,2.245,25,3"/>
+				<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M98.87,68.503
+					c-7.218,11.165,3.031,17.234,13.003,17.997c13.201,1.009,21.125-8.677,18.845-21.842c-11.637-0.604-21.219,1.818-31.849,2.845"
+					/>
+				<path i:knockout="Off" display="inline" fill="#FFFFFF" stroke="#000000" d="M178.87,67.503
+					c-9.045,2.007-6.264,11.616-1.249,15.249c3.778,2.737,13.479,4.477,18.249,2.528C210.946,79.123,185.327,71.038,178.87,67.503"
+					/>
+				<path i:knockout="Off" display="inline" stroke="#000000" d="M115.87,85.503c2.365-1.63,3.646-3.553,2.826-6.826
+					c-16.491-8.159-17.436,11.182-1.826,8.826"/>
+				<path i:knockout="Off" display="inline" stroke="#000000" d="M174.87,80.503c-0.492-1.165-0.677-2.687-0.872-3.826
+					c3.483-0.285,7.207-0.292,10.698-0.023c3.568,7.301-6.079,7.593-10.826,5.849"/>
+			</g>
+		</g>
+	</g>
+</svg>
diff --git a/dojox/gfx/demos/data/buratino-bg.png b/dojox/gfx/demos/data/buratino-bg.png
new file mode 100644
index 0000000..ee50a15
Binary files /dev/null and b/dojox/gfx/demos/data/buratino-bg.png differ
diff --git a/dojox/gfx/demos/data/buratino-head.png b/dojox/gfx/demos/data/buratino-head.png
new file mode 100644
index 0000000..d576873
Binary files /dev/null and b/dojox/gfx/demos/data/buratino-head.png differ
diff --git a/dojox/gfx/demos/data/buratino-left-arm.png b/dojox/gfx/demos/data/buratino-left-arm.png
new file mode 100644
index 0000000..1e620f3
Binary files /dev/null and b/dojox/gfx/demos/data/buratino-left-arm.png differ
diff --git a/dojox/gfx/demos/data/buratino-left-leg.png b/dojox/gfx/demos/data/buratino-left-leg.png
new file mode 100644
index 0000000..1ae5600
Binary files /dev/null and b/dojox/gfx/demos/data/buratino-left-leg.png differ
diff --git a/dojox/gfx/demos/data/buratino-lollipop.png b/dojox/gfx/demos/data/buratino-lollipop.png
new file mode 100644
index 0000000..9a52c1e
Binary files /dev/null and b/dojox/gfx/demos/data/buratino-lollipop.png differ
diff --git a/dojox/gfx/demos/data/buratino-nose-large.png b/dojox/gfx/demos/data/buratino-nose-large.png
new file mode 100644
index 0000000..a0e38fd
Binary files /dev/null and b/dojox/gfx/demos/data/buratino-nose-large.png differ
diff --git a/dojox/gfx/demos/data/buratino-nose-medium.png b/dojox/gfx/demos/data/buratino-nose-medium.png
new file mode 100644
index 0000000..f38e205
Binary files /dev/null and b/dojox/gfx/demos/data/buratino-nose-medium.png differ
diff --git a/dojox/gfx/demos/data/buratino-right-arm.png b/dojox/gfx/demos/data/buratino-right-arm.png
new file mode 100644
index 0000000..206bdb1
Binary files /dev/null and b/dojox/gfx/demos/data/buratino-right-arm.png differ
diff --git a/dojox/gfx/demos/data/buratino-right-leg.png b/dojox/gfx/demos/data/buratino-right-leg.png
new file mode 100644
index 0000000..cd0e172
Binary files /dev/null and b/dojox/gfx/demos/data/buratino-right-leg.png differ
diff --git a/dojox/gfx/demos/data/buratino-torso.png b/dojox/gfx/demos/data/buratino-torso.png
new file mode 100644
index 0000000..64c2336
Binary files /dev/null and b/dojox/gfx/demos/data/buratino-torso.png differ
diff --git a/dojox/gfx/demos/data/buratino.jpg b/dojox/gfx/demos/data/buratino.jpg
new file mode 100644
index 0000000..95aaf05
Binary files /dev/null and b/dojox/gfx/demos/data/buratino.jpg differ
diff --git a/dojox/gfx/demos/data/buratino.json b/dojox/gfx/demos/data/buratino.json
new file mode 100644
index 0000000..1218ca7
--- /dev/null
+++ b/dojox/gfx/demos/data/buratino.json
@@ -0,0 +1,12 @@
+[
+	{name: "bg",			shape: {type: "image", width: 321, height: 355, src: "data/buratino-bg.png"}},
+	{name: "left-arm",		shape: {type: "image", width: 111, height:  40, src: "data/buratino-left-arm.png"}},
+	{name: "right-arm",		shape: {type: "image", width:  59, height: 130, src: "data/buratino-right-arm.png"}},
+	{name: "left-leg",		shape: {type: "image", width: 152, height:  99, src: "data/buratino-left-leg.png"}},
+	{name: "right-leg",		shape: {type: "image", width: 104, height: 158, src: "data/buratino-right-leg.png"}},
+	{name: "torso",			shape: {type: "image", width:  90, height: 130, src: "data/buratino-torso.png"}},
+	{name: "head",			shape: {type: "image", width: 116, height: 139, src: "data/buratino-head.png"}},
+	{name: "nose-medium",	shape: {type: "image", width:  50, height:  43, src: "data/buratino-nose-medium.png"}},
+	{name: "nose-large",	shape: {type: "image", width:  70, height:  66, src: "data/buratino-nose-large.png"}},
+	{name: "lollipop",		shape: {type: "image", width:  82, height: 144, src: "data/buratino-lollipop.png"}}
+]
diff --git a/dojox/gfx/demos/data/transform.json b/dojox/gfx/demos/data/transform.json
new file mode 100644
index 0000000..60bd466
--- /dev/null
+++ b/dojox/gfx/demos/data/transform.json
@@ -0,0 +1,1567 @@
+[
+	{
+		"children": [
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 0, 
+					"x2": 500, 
+					"y2": 0
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 0, 
+					"x2": 0, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 50, 
+					"x2": 500, 
+					"y2": 50
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 50, 
+					"y1": 0, 
+					"x2": 50, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 100, 
+					"x2": 500, 
+					"y2": 100
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 100, 
+					"y1": 0, 
+					"x2": 100, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 150, 
+					"x2": 500, 
+					"y2": 150
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 150, 
+					"y1": 0, 
+					"x2": 150, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 200, 
+					"x2": 500, 
+					"y2": 200
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 200, 
+					"y1": 0, 
+					"x2": 200, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 250, 
+					"x2": 500, 
+					"y2": 250
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 250, 
+					"y1": 0, 
+					"x2": 250, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 300, 
+					"x2": 500, 
+					"y2": 300
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 300, 
+					"y1": 0, 
+					"x2": 300, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 350, 
+					"x2": 500, 
+					"y2": 350
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 350, 
+					"y1": 0, 
+					"x2": 350, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 400, 
+					"x2": 500, 
+					"y2": 400
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 400, 
+					"y1": 0, 
+					"x2": 400, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 450, 
+					"x2": 500, 
+					"y2": 450
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 450, 
+					"y1": 0, 
+					"x2": 450, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 0, 
+					"y1": 500, 
+					"x2": 500, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}, 
+			{
+				"shape": {
+					"type": "line", 
+					"x1": 500, 
+					"y1": 0, 
+					"x2": 500, 
+					"y2": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}
+			}
+		], 
+		"name": "grid"
+	}, 
+	{
+		"children": [
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 0, 
+					"y": 0, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 0, 
+					"y": 100, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 0, 
+					"y": 200, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 0, 
+					"y": 300, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 0, 
+					"y": 400, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 50, 
+					"y": 50, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 50, 
+					"y": 150, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 50, 
+					"y": 250, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 50, 
+					"y": 350, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 50, 
+					"y": 450, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 100, 
+					"y": 0, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 100, 
+					"y": 100, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 100, 
+					"y": 200, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 100, 
+					"y": 300, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 100, 
+					"y": 400, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 150, 
+					"y": 50, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 150, 
+					"y": 150, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 150, 
+					"y": 250, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 150, 
+					"y": 350, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 150, 
+					"y": 450, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 200, 
+					"y": 0, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 200, 
+					"y": 100, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 200, 
+					"y": 200, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 200, 
+					"y": 300, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 200, 
+					"y": 400, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 250, 
+					"y": 50, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 250, 
+					"y": 150, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 250, 
+					"y": 250, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 250, 
+					"y": 350, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 250, 
+					"y": 450, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 300, 
+					"y": 0, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 300, 
+					"y": 100, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 300, 
+					"y": 200, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 300, 
+					"y": 300, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 300, 
+					"y": 400, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 350, 
+					"y": 50, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 350, 
+					"y": 150, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 350, 
+					"y": 250, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 350, 
+					"y": 350, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 350, 
+					"y": 450, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 400, 
+					"y": 0, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 400, 
+					"y": 100, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 400, 
+					"y": 200, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 400, 
+					"y": 300, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 400, 
+					"y": 400, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 450, 
+					"y": 50, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 450, 
+					"y": 150, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 450, 
+					"y": 250, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 450, 
+					"y": 350, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 450, 
+					"y": 450, 
+					"width": 50, 
+					"height": 50, 
+					"r": 0
+				}, 
+				"fill": {
+					"g": 0, 
+					"b": 0, 
+					"a": 0.1, 
+					"r": 255
+				}
+			}
+		], 
+		"name": "checkerboard"
+	}, 
+	{
+		"shape": {
+			"type": "rect", 
+			"x": 0, 
+			"y": 0, 
+			"width": 100, 
+			"height": 100, 
+			"r": 0
+		}, 
+		"transform": {
+			"dx": 100, 
+			"dy": 100, 
+			"xx": 1, 
+			"xy": 0, 
+			"yx": 0, 
+			"yy": 1
+		}, 
+		"stroke": {
+			"type": "stroke", 
+			"color": {
+				"r": 0, 
+				"g": 0, 
+				"b": 0, 
+				"a": 1
+			}, 
+			"style": "solid", 
+			"width": 1, 
+			"cap": "butt", 
+			"join": 4
+		}, 
+		"fill": {
+			"type": "linear", 
+			"x1": 0, 
+			"y1": 0, 
+			"x2": 100, 
+			"y2": 100, 
+			"colors": [
+				{
+					"offset": 0, 
+					"color": {
+						"r": 0, 
+						"g": 128, 
+						"b": 0, 
+						"a": 1
+					}
+				}, 
+				{
+					"offset": 0.5, 
+					"color": {
+						"g": 0, 
+						"b": 0, 
+						"r": 255, 
+						"a": 1
+					}
+				}, 
+				{
+					"offset": 1, 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 255, 
+						"a": 1
+					}
+				}
+			]
+		}, 
+		"name": "rect with color gradient"
+	}, 
+	{
+		"shape": {
+			"type": "rect", 
+			"x": 0, 
+			"y": 0, 
+			"width": 100, 
+			"height": 100, 
+			"r": 0
+		}, 
+		"stroke": {
+			"type": "stroke", 
+			"color": {
+				"r": 0, 
+				"g": 0, 
+				"b": 0, 
+				"a": 1
+			}, 
+			"style": "solid", 
+			"width": 1, 
+			"cap": "butt", 
+			"join": 4
+		}, 
+		"fill": {
+			"type": "linear", 
+			"x1": 0, 
+			"y1": 0, 
+			"x2": 100, 
+			"y2": 100, 
+			"colors": [
+				{
+					"offset": 0, 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}
+				}, 
+				{
+					"offset": 1, 
+					"color": {
+						"r": 255, 
+						"g": 255, 
+						"b": 255, 
+						"a": 1
+					}
+				}
+			]
+		}, 
+		"name": "rect with gray gradient"
+	}, 
+	{
+		"children": [
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 200, 
+					"y": 200, 
+					"width": 100, 
+					"height": 100, 
+					"r": 0
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				}, 
+				"fill": {
+					"r": 0, 
+					"g": 128, 
+					"b": 0, 
+					"a": 1
+				},
+				name: "green rect"
+			}, 
+			{
+				"shape": {
+					"type": "rect", 
+					"x": 0, 
+					"y": 0, 
+					"width": 100, 
+					"height": 100, 
+					"r": 0
+				}, 
+				"transform": {
+					"xx": 0.8660254037844387, 
+					"xy": 0.49999999999999994, 
+					"yx": -0.49999999999999994, 
+					"yy": 0.8660254037844387, 
+					"dx": 281.69872981077805, 
+					"dy": 231.69872981077808
+				}, 
+				"fill": {
+					"r": 0, 
+					"g": 0, 
+					"b": 255, 
+					"a": 1
+				},
+				name: "blue rect"
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M 300 100L 400 200L 400 300L 300 400C 400 300 400 200 300 100"
+				}, 
+				"transform": {
+					"xx": 1, 
+					"xy": 0, 
+					"yx": 0, 
+					"yy": 1, 
+					"dx": 0, 
+					"dy": 0
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 0, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 1, 
+					"cap": "butt", 
+					"join": 4
+				},
+				name: "black path"
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M 300 100L 400 200L 400 300L 300 400C 400 300 400 200 300 100"
+				}, 
+				"transform": {
+					"dx": 100, 
+					"xx": 1, 
+					"xy": 0, 
+					"yx": 0, 
+					"yy": 1, 
+					"dy": 0
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"g": 0, 
+						"b": 0, 
+						"r": 255, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 2, 
+					"cap": "butt", 
+					"join": 4
+				},
+				name: "red path"
+			}, 
+			{
+				"shape": {
+					"type": "path", 
+					"path": "M 300 100l 100 100l 0 100l-100 100c 100-100 100-200 0-300"
+				}, 
+				"transform": {
+					"xx": -1, 
+					"xy": -1.2246063538223773e-16, 
+					"yx": 1.2246063538223773e-16, 
+					"yy": -1, 
+					"dx": 500, 
+					"dy": 500
+				}, 
+				"stroke": {
+					"type": "stroke", 
+					"color": {
+						"r": 0, 
+						"g": 0, 
+						"b": 255, 
+						"a": 1
+					}, 
+					"style": "solid", 
+					"width": 2, 
+					"cap": "butt", 
+					"join": 4
+				},
+				name: "blue path"
+			}
+		], 
+		"transform": {
+			"xx": 0.9659258262890683, 
+			"xy": 0.25881904510252074, 
+			"yx": -0.25881904510252074, 
+			"yy": 0.9659258262890683, 
+			"dx": -56.1862178478973, 
+			"dy": 73.22330470336311
+		}, 
+		"name": "rotated group"
+	}
+]
diff --git a/dojox/gfx/demos/images/clock_face.jpg b/dojox/gfx/demos/images/clock_face.jpg
new file mode 100644
index 0000000..12f1903
Binary files /dev/null and b/dojox/gfx/demos/images/clock_face.jpg differ
diff --git a/dojox/gfx/demos/images/clock_face_black.jpg b/dojox/gfx/demos/images/clock_face_black.jpg
new file mode 100644
index 0000000..dbef7cd
Binary files /dev/null and b/dojox/gfx/demos/images/clock_face_black.jpg differ
diff --git a/dojox/gfx/demos/inspector.html b/dojox/gfx/demos/inspector.html
new file mode 100644
index 0000000..2e12666
--- /dev/null
+++ b/dojox/gfx/demos/inspector.html
@@ -0,0 +1,161 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Inspect DojoX GFX JSON</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	td.cell { padding: 1em 1em 0em 0em; }
+	td.note { font-size: 80%; }
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.move");
+dojo.require("dojox.gfx.utils");
+
+surface = null;
+container_pos = null;
+mover = null;
+
+init = function(){
+	// initialize graphics
+	var container = dojo.byId("gfx");
+	surface = dojox.gfx.createSurface(container, 500, 500);
+	container_pos = dojo.coords(container, true);
+	// wire UI
+	dojo.connect(dojo.byId("load"), "onclick", onLoad);
+	dojo.connect(dojo.byId("add"),  "onclick", onAdd);
+	// handle moves
+	dojo.subscribe("/gfx/move/start", function(m){ mover = m; });
+	dojo.subscribe("/gfx/move/stop", function(){ mover = null; });
+	// handle shape operations
+	dojo.connect(document, "onkeydown", onKeyDown);
+	// cancel text selection and text dragging
+	dojo.connect(container, "ondragstart",   dojo, "stopEvent");
+	dojo.connect(container, "onselectstart", dojo, "stopEvent");
+};
+
+onLoad = function(){
+	var s = dojo.byId("source");
+	if(!s.value){
+		alert("Name of the file is required.");
+		return;
+	}
+	dojo.xhrGet({
+		url:			s.value,
+		preventCache:	true,
+		handleAs:		"json",
+		load:			loadObjects,
+		error:			function(r){ alert("Error: " + r); }
+	});
+};
+
+mainObject = null;
+names = [];
+
+loadObjects = function(r){
+	if(!r){
+		alert("Wrong JSON object. Did you type the file name correctly?");
+		return;
+	}
+	mainObject = r;
+	// clear old object names
+	names = [];
+	var s = dojo.byId("names"), ni = dojo.byId("names_info");
+	ni.innerHTML = "";
+	while(s.childNodes.length){ s.removeChild(s.lastChild); }
+	// find new names
+	findNames(s, dojo.byId("named").checked, "", mainObject);
+	ni.innerHTML = " (" + names.length + ")";
+};
+
+findNames = function(selector, named_only, prefix, o){
+	if(o instanceof Array){
+		for(var i = 0; i < o.length; ++i){
+			findNames(selector, named_only, prefix, o[i]);
+		}
+		return;
+	}
+	if(named_only && !("name" in o)) return;
+	var name = ("name" in o) ? o.name : "*",
+		full = prefix ? prefix + "/" + name : name,
+		opt  = document.createElement("option");
+	opt.value = names.length;
+	opt.innerHTML = full;
+	names.push(o);
+	selector.appendChild(opt);
+	if("children" in o){
+		findNames(selector, named_only, full, o.children);
+	}
+};
+
+onAdd = function(){
+	var s = dojo.byId("names");
+	for(var i = 0; i < s.options.length; ++i){
+		var opt = s.options[i];
+		if(!opt.selected) continue;
+		var object = names[Number(opt.value)];
+		var group = surface.createGroup();
+		dojox.gfx.utils.deserialize(group, object);
+		new dojox.gfx.Moveable(group); // make it moveable as whole
+	}
+};
+
+// event handling
+
+onKeyDown = function(e){
+	if(!mover) return;
+	switch(e.keyCode){
+		case "f".charCodeAt(0): case "F".charCodeAt(0):
+			mover.shape.moveToFront();
+			break;
+		case "b".charCodeAt(0): case "B".charCodeAt(0):
+			mover.shape.moveToBack();
+			break;
+		case "q".charCodeAt(0): case "Q".charCodeAt(0):
+			mover.shape.applyLeftTransform(dojox.gfx.matrix.rotategAt(-15, mover.lastX - container_pos.x, mover.lastY - container_pos.y));
+			break;
+		case "w".charCodeAt(0): case "W".charCodeAt(0):
+			mover.shape.applyLeftTransform(dojox.gfx.matrix.rotategAt(15, mover.lastX - container_pos.x, mover.lastY - container_pos.y));
+			break;
+		case "d".charCodeAt(0): case "D".charCodeAt(0):
+			mover.shape.parent.remove(mover.shape);
+			mover.shape.rawNode = null;
+			mover.destroy();
+			break;
+	}
+	dojo.stopEvent(e);
+};
+
+dojo.addOnLoad(init);
+</script>
+</head>
+<body>
+	<h1>Inspect DojoX GFX JSON</h1>
+	<p>Help: load a file, select an object, and add it, move it around, or apply operations to selected items:<br />
+	F — bring to front, B — bring to back, Q — rotate CCW, W — rotate CW, D — delete.<br />
+	(all operations work on currently dragged item).</p>
+	<p><strong>VML note:</strong> VML doesn't process PNG images with opacity correctly.</p>
+	<table><tr>
+		<td align="left" valign="top" class="cell"><div id="gfx" style="width: 500px; height: 500px; border: solid 1px black;"></div></td>
+		<td align="left" valign="top" class="cell"><table>
+			<tr><td>Source:</td></tr>
+			<tr><td><input type="text" id="source" value="data/Lars.json" size="30" /> <button id="load">Load</button><br />
+			<input type="checkbox" id="named" checked="checked" /> <label for="named">Load only named objects</label></td></tr>
+			<tr><td class="note"><em>Available sources:</em></td></tr>
+			<tr><td class="note"><em>data/Lars.json — vectors from SVG</em></td></tr>
+			<tr><td class="note"><em>data/Nils.json — vectors from SVG</em></td></tr>
+			<tr><td class="note"><em>data/LarsDreaming.json — vectors from SVG</em></td></tr>
+			<tr><td class="note"><em>data/buratino.json — images</em></td></tr>
+			<tr><td class="note"><em>data/transform.json — from dojox.gfx</em></td></tr>
+			<tr><td> </td></tr>
+			<tr><td>Objects<span id="names_info"></span>:</td></tr>
+			<tr><td><select id="names" multiple="multiple" size="10" style="width: 300px;"></select></td></tr>
+			<tr><td><button id="add">Add Selected</button></td></tr>
+			<tr><td class="note"><div  style="width: 300px;">Object names are hierarchical and separated by "/". Adding a selected object creates a group for this object. 
+			A higher-level object (a group) always includes lower-level objects as children.</div></td></tr>
+		</table></td>
+	</tr></table>
+</body>
+</html>
diff --git a/dojox/gfx/demos/lion.html b/dojox/gfx/demos/lion.html
new file mode 100644
index 0000000..0ce33c4
--- /dev/null
+++ b/dojox/gfx/demos/lion.html
@@ -0,0 +1,234 @@
+<html>
+<head>
+<title>dojox.gfx: Lion</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+<!--
+<script type="text/javascript" src="../_base.js"></script>
+<script type="text/javascript" src="../shape.js"></script>
+<script type="text/javascript" src="../path.js"></script>
+<script type="text/javascript" src="../arc.js"></script>
+-->
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../canvas.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+
+dojo.require("dijit.form.HorizontalSlider");
+dojo.require("dijit.form.HorizontalRule");
+dojo.require("dijit.form.HorizontalRuleLabels");
+
+dojo.require("dojo.parser"); // scan page for widgets
+
+dojo.require("dojox.gfx");
+
+var rotation = 0, scaling = 1;
+var surface, g, m = dojox.gfx.matrix;
+var initial_matrix = m.normalize([m.rotateg(10), m.translate(300, 100)]);
+
+var updateMatrix = function(){
+	if(g){ g.setTransform([m.rotategAt(rotation, 350, 350), m.scaleAt(scaling, 350, 350), initial_matrix]); }
+};
+
+var rotatingEvent = function(value){
+	rotation = value;
+	dojo.byId("rotationValue").innerHTML = rotation;
+	updateMatrix();
+};
+
+var scalingEvent = function(value){
+	scaling = Math.exp(Math.LN10 * (value - 1));
+	dojo.byId("scaleValue").innerHTML = scaling.toFixed(3);
+	updateMatrix();
+};
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface(dojo.byId("gfx_holder"), 700, 700);
+	surface.createRect({x: 0, y: 0, width: 700, height: 700}).setFill("#eee");
+	g = surface.createGroup().setTransform(initial_matrix);
+	g.createPolyline([69,18,82,8,99,3,118,5,135,12,149,21,156,13,165,9,177,13,183,28,180,50,164,91,155,107,154,114,151,121,141,127,139,136,155,206,157,251,126,342,133,357,128,376,83,376,75,368,67,350,61,350,53,369,4,369,2,361,5,354,12,342,16,321,4,257,4,244,7,218,9,179,26,127,43,93,32,77,30,70,24,67,16,49,17,35,18,23,30,12,40,7,53,7,62,12]).setFill("#f2cc99");
+	g.createPolyline([142,79,136,74,138,82,133,78,133,84,127,78,128,85,124,80,125,87,119,82,119,90,125,99,125,96,128,100,128,94,131,98,132,93,135,97,136,93,138,97,139,94,141,98,143,94,144,85]).setFill("#e5b27f");
+	g.createPolyline([127,101,132,100,137,99,144,101,143,105,135,110]).setFill("#eb8080");
+	g.createPolyline([178,229,157,248,139,296,126,349,137,356,158,357,183,342,212,332,235,288,235,261,228,252,212,250,188,251]).setFill("#f2cc99");
+	var c = new dojo.Color("#9c826b");
+	g.createPolyline([56,229,48,241,48,250,57,281,63,325,71,338,81,315,76,321,79,311,83,301,75,308,80,298,73,303,76,296,71,298,74,292,69,293,74,284,78,278,71,278,74,274,68,273,70,268,66,267,68,261,60,266,62,259,65,253,57,258,59,251,55,254,55,248,60,237,54,240,58,234,54,236]).setFill(c);
+	g.createPolyline([74,363,79,368,81,368,85,362,89,363,92,370,96,373,101,372,108,361,110,371,113,373,116,371,120,358,122,363,123,371,126,371,129,367,132,357,135,361,130,376,127,377,94,378,84,376,76,371]).setFill(c);
+	g.createPolyline([212,250,219,251,228,258,236,270,235,287,225,304,205,332,177,343,171,352,158,357,166,352,168,346,168,339,165,333,155,327,155,323,161,320,165,316,169,316,167,312,171,313,168,308,173,309,170,306,177,306,175,308,177,311,174,311,176,316,171,315,174,319,168,320,168,323,175,327,179,332,183,326,184,332,189,323,190,328,194,320,194,325,199,316,201,320,204,313,206,316,208,310,211,305,219,298,226,288,229,279,228,266,224,259,217,253]).setFill(c);
+	g.createPolyline([151,205,151,238,149,252,141,268,128,282,121,301,130,300,126,313,118,324,116,337,120,346,133,352,133,340,137,333,145,329,156,327,153,319,153,291,157,271,170,259,178,277,193,250,174,216]).setFill(c);
+	g.createPolyline([78,127,90,142,95,155,108,164,125,167,139,175,150,206,152,191,141,140,121,148,100,136]).setFill(c);
+	g.createPolyline([21,58,35,63,38,68,32,69,42,74,40,79,47,80,54,83,45,94,34,81,32,73,24,66]).setFill(c);
+	g.createPolyline([71,34,67,34,66,27,59,24,54,17,48,17,39,22,30,26,28,31,31,39,38,46,29,45,36,54,41,61,41,70,50,69,54,71,55,58,67,52,76,43,76,39,68,44]).setFill(c);
+	g.createPolyline([139,74,141,83,143,89,144,104,148,104,155,106,154,86,157,77,155,72,150,77,144,77]).setFill(c);
+	g.createPolyline([105,44,102,53,108,58,111,62,112,55]).setFill(c);
+	g.createPolyline([141,48,141,54,144,58,139,62,137,66,136,59,137,52]).setFill(c);
+	g.createPolyline([98,135,104,130,105,134,108,132,108,135,112,134,113,137,116,136,116,139,119,139,124,141,128,140,133,138,140,133,139,140,126,146,104,144]).setFill(c);
+	g.createPolyline([97,116,103,119,103,116,111,118,116,117,122,114,127,107,135,111,142,107,141,114,145,118,149,121,145,125,140,124,127,121,113,125,100,124]).setFill(c);
+	g.createPolyline([147,33,152,35,157,34,153,31,160,31,156,28,161,28,159,24,163,25,163,21,165,22,170,23,167,17,172,21,174,18,175,23,176,22,177,28,177,33,174,37,176,39,174,44,171,49,168,53,164,57,159,68,156,70,154,60,150,51,146,43,144,35]).setFill(c);
+	g.createPolyline([85,72,89,74,93,75,100,76,105,75,102,79,94,79,88,76]).setFill(c);
+	g.createPolyline([86,214,79,221,76,232,82,225,78,239,82,234,78,245,81,243,79,255,84,250,84,267,87,254,90,271,90,257,95,271,93,256,95,249,92,252,93,243,89,253,89,241,86,250,87,236,83,245,87,231,82,231,90,219,84,221]).setFill(c);
+	c = new dojo.Color("#ffcc7f");
+	g.createPolyline([93,68,96,72,100,73,106,72,108,66,105,63,100,62]).setFill(c);
+	g.createPolyline([144,64,142,68,142,73,146,74,150,73,154,64,149,62]).setFill(c);
+	c = new dojo.Color("#9c826b");
+	g.createPolyline([57,91,42,111,52,105,41,117,53,112,46,120,53,116,50,124,57,119,55,127,61,122,60,130,67,126,66,134,71,129,72,136,77,130,76,137,80,133,82,138,86,135,96,135,94,129,86,124,83,117,77,123,79,117,73,120,75,112,68,116,71,111,65,114,69,107,63,110,68,102,61,107,66,98,61,103,63,97,57,99]).setFill(c);
+	g.createPolyline([83,79,76,79,67,82,75,83,65,88,76,87,65,92,76,91,68,96,77,95,70,99,80,98,72,104,80,102,76,108,85,103,92,101,87,98,93,96,86,94,91,93,85,91,93,89,99,89,105,93,107,85,102,82,92,80]).setFill(c);
+	g.createPolyline([109,77,111,83,109,89,113,94,117,90,117,81,114,78]).setFill(c);
+	g.createPolyline([122,128,127,126,134,127,136,129,134,130,130,128,124,129]).setFill(c);
+	g.createPolyline([78,27,82,32,80,33,82,36,78,37,82,40,78,42,81,46,76,47,78,49,74,50,82,52,87,50,83,48,91,46,86,45,91,42,88,40,92,37,86,34,90,31,86,29,89,26]).setFill(c);
+	g.createPolyline([82,17,92,20,79,21,90,25,81,25,94,28,93,26,101,30,101,26,107,33,108,28,111,40,113,34,115,45,117,39,119,54,121,46,124,58,126,47,129,59,130,49,134,58,133,44,137,48,133,37,137,40,133,32,126,20,135,26,132,19,138,23,135,17,142,18,132,11,116,6,94,6,78,11,92,12,80,14,90,16]).setFill(c);
+	g.createPolyline([142,234,132,227,124,223,115,220,110,225,118,224,127,229,135,236,122,234,115,237,113,242,121,238,139,243,121,245,111,254,95,254,102,244,104,235,110,229,100,231,104,224,113,216,122,215,132,217,141,224,145,230,149,240]).setFill(c);
+	g.createPolyline([115,252,125,248,137,249,143,258,134,255,125,254]).setFill(c);
+	g.createPolyline([114,212,130,213,140,219,147,225,144,214,137,209,128,207]).setFill(c);
+	g.createPolyline([102,263,108,258,117,257,131,258,116,260,109,265]).setFill(c);
+	g.createPolyline([51,241,35,224,40,238,23,224,31,242,19,239,28,247,17,246,25,250,37,254,39,263,44,271,47,294,48,317,51,328,60,351,60,323,53,262,47,246]).setFill(c);
+	g.createPolyline([2,364,9,367,14,366,18,355,20,364,26,366,31,357,35,364,39,364,42,357,47,363,53,360,59,357,54,369,7,373]).setFill(c);
+	g.createPolyline([7,349,19,345,25,339,18,341,23,333,28,326,23,326,27,320,23,316,25,311,20,298,15,277,12,264,9,249,10,223,3,248,5,261,15,307,17,326,11,343]).setFill(c);
+	g.createPolyline([11,226,15,231,25,236,18,227]).setFill(c);
+	g.createPolyline([13,214,19,217,32,227,23,214,16,208,15,190,24,148,31,121,24,137,14,170,8,189]).setFill(c);
+	g.createPolyline([202,254,195,258,199,260,193,263,197,263,190,268,196,268,191,273,188,282,200,272,194,272,201,266,197,265,204,262,200,258,204,256]).setFill(c);
+	c = new dojo.Color("#845433");
+	g.createPolyline([151,213,165,212,179,225,189,246,187,262,179,275,176,263,177,247,171,233,163,230,165,251,157,264,146,298,145,321,133,326,143,285,154,260,153,240]).setFill(c);
+	g.createPolyline([91,132,95,145,97,154,104,148,107,155,109,150,111,158,115,152,118,159,120,153,125,161,126,155,133,164,132,154,137,163,137,152,142,163,147,186,152,192,148,167,141,143,124,145,105,143]).setFill(c);
+	c = new dojo.Color("#9c826b");
+	g.createPolyline([31,57,23,52,26,51,20,44,23,42,21,36,22,29,25,23,24,32,30,43,26,41,30,50,26,48]).setFill(c);
+	g.createPolyline([147,21,149,28,155,21,161,16,167,14,175,15,173,11,161,9]).setFill(c);
+	g.createPolyline([181,39,175,51,169,57,171,65,165,68,165,75,160,76,162,91,171,71,180,51]).setFill(c);
+	g.createPolyline([132,346,139,348,141,346,142,341,147,342,143,355,133,350]).setFill(c);
+	g.createPolyline([146,355,151,352,155,348,157,343,160,349,151,356,147,357]).setFill(c);
+	g.createPolyline([99,266,100,281,94,305,86,322,78,332,72,346,73,331,91,291]).setFill(c);
+	g.createPolyline([20,347,32,342,45,340,54,345,45,350,42,353,38,350,31,353,29,356,23,350,19,353,15,349]).setFill(c);
+	g.createPolyline([78,344,86,344,92,349,88,358,84,352]).setFill(c);
+	g.createPolyline([93,347,104,344,117,345,124,354,121,357,116,351,112,351,108,355,102,351]).setFill(c);
+	c = new dojo.Color("black");
+	g.createPolyline([105,12,111,18,113,24,113,29,119,34,116,23,112,16]).setFill(c);
+	g.createPolyline([122,27,125,34,127,43,128,34,125,29]).setFill(c);
+	g.createPolyline([115,13,122,19,122,15,113,10]).setFill(c);
+	c = new dojo.Color("#ffe5b2");
+	g.createPolyline([116,172,107,182,98,193,98,183,90,199,89,189,84,207,88,206,87,215,95,206,93,219,91,230,98,216,97,226,104,214,112,209,104,208,113,202,126,200,139,207,132,198,142,203,134,192,142,195,134,187,140,185,130,181,136,177,126,177,125,171,116,180]).setFill(c);
+	g.createPolyline([74,220,67,230,67,221,59,235,63,233,60,248,70,232,65,249,71,243,67,256,73,250,69,262,73,259,71,267,76,262,72,271,78,270,76,275,82,274,78,290,86,279,86,289,92,274,88,275,87,264,82,270,82,258,77,257,78,247,73,246,77,233,72,236]).setFill(c);
+	g.createPolyline([133,230,147,242,148,250,145,254,138,247,129,246,142,245,138,241,128,237,137,238]).setFill(c);
+	g.createPolyline([133,261,125,261,116,263,111,267,125,265]).setFill(c);
+	g.createPolyline([121,271,109,273,103,279,99,305,92,316,85,327,83,335,89,340,97,341,94,336,101,336,96,331,103,330,97,327,108,325,99,322,109,321,100,318,110,317,105,314,110,312,107,310,113,308,105,306,114,303,105,301,115,298,107,295,115,294,108,293,117,291,109,289,117,286,109,286,118,283,112,281,118,279,114,278,119,276,115,274]).setFill(c);
+	g.createPolyline([79,364,74,359,74,353,76,347,80,351,83,356,82,360]).setFill(c);
+	g.createPolyline([91,363,93,356,97,353,103,355,105,360,103,366,99,371,94,368]).setFill(c);
+	g.createPolyline([110,355,114,353,118,357,117,363,113,369,111,362]).setFill(c);
+	g.createPolyline([126,354,123,358,124,367,126,369,129,361,129,357]).setFill(c);
+	g.createPolyline([30,154,24,166,20,182,23,194,29,208,37,218,41,210,41,223,46,214,46,227,52,216,52,227,61,216,59,225,68,213,73,219,70,207,77,212,69,200,77,202,70,194,78,197,68,187,76,182,64,182,58,175,58,185,53,177,50,186,46,171,44,182,39,167,36,172,36,162,30,166]).setFill(c);
+	g.createPolyline([44,130,41,137,45,136,43,150,48,142,48,157,53,150,52,164,60,156,61,169,64,165,66,175,70,167,74,176,77,168,80,183,85,172,90,182,93,174,98,181,99,173,104,175,105,169,114,168,102,163,95,157,94,166,90,154,87,162,82,149,75,159,72,148,68,155,67,143,62,148,62,138,58,145,56,133,52,142,52,128,49,134,47,125]).setFill(c);
+	g.createPolyline([13,216,19,219,36,231,22,223,16,222,22,227,12,224,13,220,16,220]).setFill(c);
+	g.createPolyline([10,231,14,236,25,239,27,237,19,234]).setFill(c);
+	g.createPolyline([9,245,14,242,25,245,13,245]).setFill(c);
+	g.createPolyline([33,255,26,253,18,254,25,256,18,258,27,260,18,263,27,265,19,267,29,270,21,272,29,276,21,278,30,281,22,283,31,287,24,288,32,292,23,293,34,298,26,299,37,303,32,305,39,309,33,309,39,314,34,314,40,318,34,317,40,321,34,321,41,326,33,326,40,330,33,332,39,333,33,337,42,337,54,341,49,337,52,335,47,330,50,330,45,325,49,325,45,321,48,321,45,316,46,306,45,286,43,274,36,261]).setFill(c);
+	g.createPolyline([7,358,9,351,14,351,17,359,11,364]).setFill(c);
+	g.createPolyline([44,354,49,351,52,355,49,361]).setFill(c);
+	g.createPolyline([32,357,37,353,40,358,36,361]).setFill(c);
+	g.createPolyline([139,334,145,330,154,330,158,334,154,341,152,348,145,350,149,340,147,336,141,339,139,345,136,342,136,339]).setFill(c);
+	g.createPolyline([208,259,215,259,212,255,220,259,224,263,225,274,224,283,220,292,208,300,206,308,203,304,199,315,197,309,195,318,193,313,190,322,190,316,185,325,182,318,180,325,172,321,178,320,176,313,186,312,180,307,188,307,184,303,191,302,186,299,195,294,187,290,197,288,192,286,201,283,194,280,203,277,198,275,207,271,200,269,209,265,204,265,212,262]).setFill(c);
+	g.createPolyline([106,126,106,131,109,132,111,134,115,132,115,135,119,133,118,137,123,137,128,137,133,134,136,130,136,127,132,124,118,128,112,128,106,126,106,126,106,126]).setFill(c);
+	g.createPolyline([107,114,101,110,98,102,105,97,111,98,119,102,121,108,118,112,113,115]).setFill(c);
+	g.createPolyline([148,106,145,110,146,116,150,118,152,111,151,107]).setFill(c);
+	g.createPolyline([80,55,70,52,75,58,63,57,72,61,57,61,67,66,57,67,62,69,54,71,61,73,54,77,63,78,53,85,60,84,56,90,69,84,63,82,75,76,70,75,77,72,72,71,78,69,72,66,81,67,78,64,82,63,80,60,86,62]).setFill(c);
+	g.createPolyline([87,56,91,52,96,50,102,56,98,56,92,60]).setFill(c);
+	g.createPolyline([85,68,89,73,98,76,106,74,96,73,91,70]).setFill(c);
+	g.createPolyline([115,57,114,64,111,64,115,75,122,81,122,74,126,79,126,74,131,78,130,72,133,77,131,68,126,61,119,57]).setFill(c);
+	g.createPolyline([145,48,143,53,147,59,151,59,150,55]).setFill(c);
+	g.createPolyline([26,22,34,15,43,10,52,10,59,16,47,15,32,22]).setFill(c);
+	g.createPolyline([160,19,152,26,149,34,154,33,152,30,157,30,155,26,158,27,157,23,161,23]).setFill(c);
+	c = new dojo.Color("black");
+	g.createPolyline([98,117,105,122,109,122,105,117,113,120,121,120,130,112,128,108,123,103,123,99,128,101,132,106,135,109,142,105,142,101,145,101,145,91,148,101,145,105,136,112,135,116,143,124,148,120,150,122,142,128,133,122,121,125,112,126,103,125,100,129,96,124]).setFill(c);
+	g.createPolyline([146,118,152,118,152,115,149,115]).setFill(c);
+	g.createPolyline([148,112,154,111,154,109,149,109]).setFill(c);
+	g.createPolyline([106,112,108,115,114,116,118,114]).setFill(c);
+	g.createPolyline([108,108,111,110,116,110,119,108]).setFill(c);
+	g.createPolyline([106,104,109,105,117,106,115,104]).setFill(c);
+	g.createPolyline([50,25,41,26,34,33,39,43,49,58,36,51,47,68,55,69,54,59,61,57,74,46,60,52,67,42,57,48,61,40,54,45,60,36,59,29,48,38,52,30,47,32]).setFill(c);
+	g.createPolyline([147,34,152,41,155,49,161,53,157,47,164,47,158,43,168,44,159,40,164,37,169,37,164,33,169,34,165,28,170,30,170,25,173,29,175,27,176,32,173,36,175,39,172,42,172,46,168,49,170,55,162,57,158,63,155,58,153,50,149,46]).setFill(c);
+	g.createPolyline([155,71,159,80,157,93,157,102,155,108,150,101,149,93,154,101,152,91,151,83,155,79]).setFill(c);
+	g.createPolyline([112,78,115,81,114,91,112,87,113,82]).setFill(c);
+	g.createPolyline([78,28,64,17,58,11,47,9,36,10,28,16,21,26,18,41,20,51,23,61,33,65,28,68,37,74,36,81,43,87,48,90,43,100,40,98,39,90,31,80,30,72,22,71,17,61,14,46,16,28,23,17,33,9,45,6,54,6,65,12]).setFill(c);
+	g.createPolyline([67,18,76,9,87,5,101,2,118,3,135,8,149,20,149,26,144,19,132,12,121,9,105,7,89,8,76,14,70,20]).setFill(c);
+	g.createPolyline([56,98,48,106,56,103,47,112,56,110,52,115,57,113,52,121,62,115,58,123,65,119,63,125,69,121,68,127,74,125,74,129,79,128,83,132,94,135,93,129,85,127,81,122,76,126,75,121,71,124,71,117,66,121,66,117,62,117,64,112,60,113,60,110,57,111,61,105,57,107,60,101,55,102]).setFill(c);
+	g.createPolyline([101,132,103,138,106,134,106,139,112,136,111,142,115,139,114,143,119,142,125,145,131,142,135,138,140,134,140,129,143,135,145,149,150,171,149,184,145,165,141,150,136,147,132,151,131,149,126,152,125,150,121,152,117,148,111,152,110,148,105,149,104,145,98,150,96,138,94,132,94,130,98,132]).setFill(c);
+	g.createPolyline([41,94,32,110,23,132,12,163,6,190,7,217,5,236,3,247,9,230,12,211,12,185,18,160,26,134,35,110,43,99]).setFill(c);
+	g.createPolyline([32,246,41,250,50,257,52,267,53,295,53,323,59,350,54,363,51,365,44,366,42,360,40,372,54,372,59,366,62,353,71,352,75,335,73,330,66,318,68,302,64,294,67,288,63,286,63,279,59,275,58,267,56,262,50,247,42,235,44,246,32,236,35,244]).setFill(c);
+	g.createPolyline([134,324,146,320,159,322,173,327,179,337,179,349,172,355,158,357,170,350,174,343,170,333,163,328,152,326,134,329]).setFill(c);
+	g.createPolyline([173,339,183,334,184,338,191,329,194,332,199,323,202,325,206,318,209,320,213,309,221,303,228,296,232,289,234,279,233,269,230,262,225,256,219,253,208,252,198,252,210,249,223,250,232,257,237,265,238,277,238,291,232,305,221,323,218,335,212,342,200,349,178,348]).setFill(c);
+	g.createPolyline([165,296,158,301,156,310,156,323,162,324,159,318,162,308,162,304]).setFill(c);
+	g.createPolyline([99,252,105,244,107,234,115,228,121,228,131,235,122,233,113,235,109,246,121,239,133,243,121,243,110,251]).setFill(c);
+	g.createPolyline([117,252,124,247,134,249,136,253,126,252]).setFill(c);
+	g.createPolyline([117,218,132,224,144,233,140,225,132,219,117,218,117,218,117,218]).setFill(c);
+	g.createPolyline([122,212,134,214,143,221,141,213,132,210]).setFill(c);
+	g.createPolyline([69,352,70,363,76,373,86,378,97,379,108,379,120,377,128,378,132,373,135,361,133,358,132,366,127,375,121,374,121,362,119,367,117,374,110,376,110,362,107,357,106,371,104,375,97,376,90,375,90,368,86,362,83,364,86,369,85,373,78,370,73,362,71,351]).setFill(c);
+	g.createPolyline([100,360,96,363,99,369,102,364]).setFill(c);
+	g.createPolyline([115,360,112,363,114,369,117,364]).setFill(c);
+	g.createPolyline([127,362,125,364,126,369,128,365]).setFill(c);
+	g.createPolyline([5,255,7,276,11,304,15,320,13,334,6,348,2,353,0,363,5,372,12,374,25,372,38,372,44,369,42,367,36,368,31,369,30,360,27,368,20,370,16,361,15,368,10,369,3,366,3,359,6,352,11,348,17,331,19,316,12,291,9,274]).setFill(c);
+	g.createPolyline([10,358,7,362,10,366,11,362]).setFill(c);
+	g.createPolyline([25,357,22,360,24,366,27,360]).setFill(c);
+	g.createPolyline([37,357,34,361,36,365,38,361]).setFill(c);
+	g.createPolyline([49,356,46,359,47,364,50,360]).setFill(c);
+	g.createPolyline([130,101,132,102,135,101,139,102,143,103,142,101,137,100,133,100]).setFill(c);
+	g.createPolyline([106,48,105,52,108,56,109,52]).setFill(c);
+	g.createPolyline([139,52,139,56,140,60,142,58,141,56]).setFill(c);
+	g.createPolyline([25,349,29,351,30,355,33,350,37,348,42,351,45,347,49,345,44,343,36,345]).setFill(c);
+	g.createPolyline([98,347,105,351,107,354,109,349,115,349,120,353,118,349,113,346,104,346]).setFill(c);
+	g.createPolyline([83,348,87,352,87,357,89,351,87,348]).setFill(c);
+	g.createPolyline([155,107,163,107,170,107,186,108,175,109,155,109]).setFill(c);
+	g.createPolyline([153,114,162,113,175,112,192,114,173,114,154,115]).setFill(c);
+	g.createPolyline([152,118,164,120,180,123,197,129,169,123,151,120]).setFill(c);
+	g.createPolyline([68,109,87,106,107,106,106,108,88,108]).setFill(c);
+	g.createPolyline([105,111,95,112,79,114,71,116,85,115,102,113]).setFill(c);
+	g.createPolyline([108,101,98,99,87,99,78,99,93,100,105,102]).setFill(c);
+	g.createPolyline([85,63,91,63,97,60,104,60,108,62,111,69,112,75,110,74,108,71,103,73,106,69,105,65,103,64,103,67,102,70,99,70,97,66,94,67,97,72,88,67,84,66]).setFill(c);
+	g.createPolyline([140,74,141,66,144,61,150,61,156,62,153,70,150,73,152,65,150,65,151,68,149,71,146,71,144,66,143,70,143,74]).setFill(c);
+	g.createPolyline([146,20,156,11,163,9,172,9,178,14,182,18,184,32,182,42,182,52,177,58,176,67,171,76,165,90,157,105,160,92,164,85,168,78,167,73,173,66,172,62,175,59,174,55,177,53,180,46,181,29,179,21,173,13,166,11,159,13,153,18,148,23]).setFill(c);
+	g.createPolyline([150,187,148,211,150,233,153,247,148,267,135,283,125,299,136,292,131,313,122,328,122,345,129,352,133,359,133,367,137,359,148,356,140,350,131,347,129,340,132,332,140,328,137,322,140,304,154,265,157,244,155,223,161,220,175,229,186,247,185,260,176,275,178,287,185,277,188,261,196,253,189,236,174,213]).setFill(c);
+	g.createPolyline([147,338,142,341,143,345,141,354,147,343]).setFill(c);
+	g.createPolyline([157,342,156,349,150,356,157,353,163,346,162,342]).setFill(c);
+	g.createPolyline([99,265,96,284,92,299,73,339,73,333,87,300]).setFill(c);
+	//surface.createLine({x1: 0, y1: 350, x2: 700, y2: 350}).setStroke("green");
+	//surface.createLine({y1: 0, x1: 350, y2: 700, x2: 350}).setStroke("green");
+    dojo.connect(dijit.byId("rotatingSlider"), "onChange", rotatingEvent);
+    dojo.connect(dijit.byId("scalingSlider"), "onChange", scalingEvent);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+<style type="text/css">
+	td.pad { padding: 0px 5px 0px 5px; }
+</style>
+</head>
+<body class="tundra">
+	<h1>dojox.gfx: Lion</h1>
+	<p>This example was directly converted from SVG file.</p>
+	<table>
+		<tr><td align="center" class="pad">Rotation (<span id="rotationValue">0</span>)</td></tr>
+		<tr><td>
+			<div id="rotatingSlider" dojoType="dijit.form.HorizontalSlider" 
+					value="0" minimum="-180" maximum="180" discreteValues="72" showButtons="false" intermediateChanges="true"
+					style="width: 600px;">
+				<div dojoType="dijit.form.HorizontalRule" container="topDecoration" count="73" style="height:5px;"></div>
+				<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="9" style="height:5px;"></div>
+				<div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" labels="-180,-135,-90,-45,0,45,90,135,180" style="height:1.2em;font-size:75%;color:gray;"></div>
+			</div>
+		</td></tr>
+		<tr><td align="center" class="pad">Scaling (<span id="scaleValue">1.000</span>)</td></tr>
+		<tr><td>
+			<div id="scalingSlider" dojoType="dijit.form.HorizontalSlider" 
+				value="1" minimum="0" maximum="1"  showButtons="false"  intermediateChanges="true"
+				style="width: 600px;">
+				<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="5" style="height:5px;"></div>
+				<div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" labels="10%,18%,32%,56%,100%" style="height:1.2em;font-size:75%;color:gray;"></div>
+			</div>
+		</td></tr>
+	</table>
+	<div id="gfx_holder" style="width: 700px; height: 700px;"></div>
+</body>
+</html>
diff --git a/dojox/gfx/demos/roundedPane.html b/dojox/gfx/demos/roundedPane.html
new file mode 100644
index 0000000..4abb775
--- /dev/null
+++ b/dojox/gfx/demos/roundedPane.html
@@ -0,0 +1,191 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+
+		<title>rounded skeleton page | The Dojo Toolkit</title>
+			
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+				djConfig="parseOnLoad:true, isDebug:true"></script>
+
+		<script type="text/javascript">
+		
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dijit._Templated");
+			dojo.require("dojox.gfx");
+			dojo.require("dojo.dnd.TimedMoveable");
+			
+			dojo.declare("my.RoundedContentPane",[dijit.layout.ContentPane,dijit._Templated],{
+				// radius: Integer
+				//		radius of the corners
+				radius:15,
+				// moveable: Boolean
+				// 		if true, the node is movable by either the containerNode, or an optional node
+				//		found by the handle attribute
+				moveable:false,
+				// handle: String
+				// 		a CSS3 selector query to match the handle for this node, scoped to this.domNode
+				handle:".handle",
+				
+				// template:
+				templateString:
+					'<div><div style="position:relative;">' +
+						'<div dojoAttachPoint="surfaceNode"></div>' +
+						'<div dojoAttachPoint="containerNode"></div>' +
+					'</div></div>',
+				
+				startup:function(){
+					
+					this.inherited(arguments);
+					this._initSurface();
+					dojo.style(this.surfaceNode,{
+						position:"absolute",
+						top:0,
+						left:0
+					});
+					
+					if(this.moveable){
+						this._mover = new dojo.dnd.TimedMoveable(this.domNode,{
+							handle: dojo.query(this.handle,this.domNode)[0] ||this.containerNode,
+							timeout:69
+						});
+					}
+			
+				},
+				
+				_initSurface: function(){
+			
+					var s = dojo.marginBox(this.domNode);
+					var stroke = 2;
+					
+					this.surface = dojox.gfx.createSurface(this.surfaceNode, s.w + stroke * 2, s.h + stroke * 2);
+					this.roundedShape = this.surface.createRect({
+							r: this.radius,
+							width: s.w,
+							height: s.h
+						})
+						.setFill([0, 0, 0, 0.5]) // black, 50% transparency
+						.setStroke({ color:[255,255,255,1], width:stroke }) // solid white
+					;
+					this.resize(s);
+					
+				},
+				
+				resize:function(size){
+					
+					if(!this.surface){ this._initSurfce(); }
+			
+					this.surface.setDimensions(size.w,size.h);
+					this.roundedShape.setShape({
+						width: size.w,
+						height: size.h
+					});
+			
+					var _offset = Math.floor(this.radius / 2);		
+					dojo.style(this.containerNode,{
+						color: "#fff",
+						position: "absolute",
+						overflow: "auto",
+						top: _offset + "px",
+						left: _offset + "px",
+						height: (size.h - _offset * 2) + "px",
+						width: (size.w - _offset * 2) + "px"
+					});
+					
+				}
+				
+			});
+		</script>
+			
+		<style type="text/css">
+			body { background:#ededed; }
+		</style>
+	
+    </head>
+    <body>
+		
+		<h1>Some gfx + ContentPane's</h1>
+
+		<div dojoType="my.RoundedContentPane" radius="55" title="Pane 2" style="width:200px; height:400px; float:right">
+			<h3>YO!</h3>
+			<p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p><p>lorem</p>
+		</div>
+
+		<div style="width:400px; height:200px;" dojoType="my.RoundedContentPane">
+			LOREM, ipsum, dollllllllllor:
+			.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}<p>.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}</p><p>.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}</p><p>.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}</p><p>.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}</p><p>.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}</p><p>.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}</p><p>.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}</p><p>.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}</p><p>.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}</p><p>.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}</p><p>.roundedContent {
+				padding: 31px;
+				font-family: 'Tahoma';
+				font-size: 12px;
+				color:#fff; 
+			}</p>
+			
+		</div>
+	
+	
+		<div radius="45" style="width:400px; height:200px;" moveable="true" dojoType="my.RoundedContentPane" handle=".myHandle">
+			<h4 class="myHandle" style="cursor:move; margin-top:0; border:1px solid #666">Moveable Handle</h4>
+			LOREM, ipsum, dollllllllllor:			
+		</div>
+	
+	
+		<div dojoType="my.RoundedContentPane" title="Pane 1" moveable="true" style="width:100px; height:100px;">
+			lorem ipsum (small moveable)
+		</div>		
+	
+    </body>
+</html>
diff --git a/dojox/gfx/demos/tiger.html b/dojox/gfx/demos/tiger.html
new file mode 100644
index 0000000..2d03fed
--- /dev/null
+++ b/dojox/gfx/demos/tiger.html
@@ -0,0 +1,565 @@
+<html>
+<head>
+<title>dojox.gfx: Tiger</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+<script type="text/javascript">
+
+dojo.require("dijit.form.HorizontalSlider");
+dojo.require("dijit.form.HorizontalRule");
+dojo.require("dijit.form.HorizontalRuleLabels");
+
+dojo.require("dojo.parser"); // scan page for widgets
+
+dojo.require("dojox.gfx");
+
+var rotation = 0, scaling = 1;
+var surface, g, m = dojox.gfx.matrix;
+var initial_matrix = m.translate(250, 250);
+
+var updateMatrix = function(){
+	if(g){ g.setTransform([m.rotategAt(rotation, 350, 350), m.scaleAt(scaling, 350, 350), initial_matrix]); }
+};
+
+var rotatingEvent = function(value){
+	rotation = value;
+	dojo.byId("rotationValue").innerHTML = rotation;
+	updateMatrix();
+};
+
+var scalingEvent = function(value){
+	scaling = Math.exp(Math.LN10 * (value - 1));
+	dojo.byId("scaleValue").innerHTML = scaling.toFixed(3);
+	updateMatrix();
+};
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface(dojo.byId("gfx_holder"), 700, 700);
+	surface.createRect({x: 0, y: 0, width: 700, height: 700}).setFill("#eee");
+	g = surface.createGroup().setTransform(initial_matrix);
+	var f, s = {color: "black", width: 1};
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-118.774 81.262C-118.774 81.262 -119.323 83.078 -120.092 82.779C-120.86 82.481 -119.977 31.675 -140.043 26.801C-140.043 26.801 -120.82 25.937 -118.774 81.262z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-91.284 123.59C-91.284 123.59 -89.648 124.55 -90.118 125.227C-90.589 125.904 -139.763 113.102 -149.218 131.459C-149.218 131.459 -145.539 112.572 -91.284 123.59z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-94.093 133.801C-94.093 133.801 -92.237 134.197 -92.471 134.988C-92.704 135.779 -143.407 139.121 -146.597 159.522C-146.597 159.522 -149.055 140.437 -94.093 133.801z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-98.304 128.276C-98.304 128.276 -96.526 128.939 -96.872 129.687C-97.218 130.435 -147.866 126.346 -153.998 146.064C-153.998 146.064 -153.646 126.825 -98.304 128.276z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-109.009 110.072C-109.009 110.072 -107.701 111.446 -108.34 111.967C-108.979 112.488 -152.722 86.634 -166.869 101.676C-166.869 101.676 -158.128 84.533 -109.009 110.072z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-116.554 114.263C-116.554 114.263 -115.098 115.48 -115.674 116.071C-116.25 116.661 -162.638 95.922 -174.992 112.469C-174.992 112.469 -168.247 94.447 -116.554 114.263z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-119.154 118.335C-119.154 118.335 -117.546 119.343 -118.036 120.006C-118.526 120.669 -167.308 106.446 -177.291 124.522C-177.291 124.522 -173.066 105.749 -119.154 118.335z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-108.42 118.949C-108.42 118.949 -107.298 120.48 -107.999 120.915C-108.7 121.35 -148.769 90.102 -164.727 103.207C-164.727 103.207 -153.862 87.326 -108.42 118.949z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-128.2 90C-128.2 90 -127.6 91.8 -128.4 92C-129.2 92.2 -157.8 50.2 -177.001 57.8C-177.001 57.8 -161.8 46 -128.2 90z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-127.505 96.979C-127.505 96.979 -126.53 98.608 -127.269 98.975C-128.007 99.343 -164.992 64.499 -182.101 76.061C-182.101 76.061 -169.804 61.261 -127.505 96.979z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.172};
+	g.createPath("M-127.62 101.349C-127.62 101.349 -126.498 102.88 -127.199 103.315C-127.9 103.749 -167.969 72.502 -183.927 85.607C-183.927 85.607 -173.062 69.726 -127.62 101.349z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = "#000000";
+	g.createPath("M-129.83 103.065C-129.327 109.113 -128.339 115.682 -126.6 118.801C-126.6 118.801 -130.2 131.201 -121.4 144.401C-121.4 144.401 -121.8 151.601 -120.2 154.801C-120.2 154.801 -116.2 163.201 -111.4 164.001C-107.516 164.648 -98.793 167.717 -88.932 169.121C-88.932 169.121 -71.8 183.201 -75 196.001C-75 196.001 -75.4 212.401 -79 214.001C-79 214.001 -67.4 202.801 -77 219.601L-81.4 238.401C-81.4 238.401 -55.8 216.801 -71.4 235.201L-81.4 261.201C-81.4 261.201 -61.8 242.801 -69 251.201 [...]
+	f = "#cc7226"; s = "#000000";
+	g.createPath("M299.717 80.245C300.345 80.426 302.551 81.55 303.801 83.2C303.801 83.2 310.601 94 305.401 75.6C305.401 75.6 296.201 46.8 305.001 58C305.001 58 311.001 65.2 307.801 51.6C303.936 35.173 301.401 28.8 301.401 28.8C301.401 28.8 313.001 33.6 286.201 -6L295.001 -2.4C295.001 -2.4 275.401 -42 253.801 -47.2L245.801 -53.2C245.801 -53.2 284.201 -91.2 271.401 -128C271.401 -128 264.601 -133.2 255.001 -124C255.001 -124 248.601 -119.2 242.601 -120.8C242.601 -120.8 211.801 -119.6 209.801 - [...]
+	f = "#cc7226"; s = null;
+	g.createPath("M-115.6 102.6C-140.6 63.2 -126.2 119.601 -126.2 119.601C-117.4 154.001 12.2 116.401 12.2 116.401C12.2 116.401 181.001 86 192.201 82C203.401 78 298.601 84.4 298.601 84.4L293.001 67.6C228.201 21.2 209.001 44.4 195.401 40.4C181.801 36.4 184.201 46 181.001 46.8C177.801 47.6 138.601 22.8 132.201 23.6C125.801 24.4 100.459 0.649 115.401 32.4C131.401 66.4 57 71.6 40.2 60.4C23.4 49.2 47.4 78.8 47.4 78.8C65.8 98.8 31.4 82 31.4 82C-3 69.2 -27 94.8 -30.2 95.6C-33.4 96.4 -38.2 99.6 -39 [...]
+	f = "#e87f3a";
+	g.createPath("M133.51 25.346C127.11 26.146 101.743 2.407 116.71 34.146C133.31 69.346 58.31 73.346 41.51 62.146C24.709 50.946 48.71 80.546 48.71 80.546C67.11 100.546 32.709 83.746 32.709 83.746C-1.691 70.946 -25.691 96.546 -28.891 97.346C-32.091 98.146 -36.891 101.346 -37.691 94.946C-38.491 88.546 -45.87 72.012 -77.691 98.146C-98.927 115.492 -112.418 94.037 -112.418 94.037L-115.618 104.146C-140.618 64.346 -125.546 122.655 -125.546 122.655C-116.745 157.056 13.509 118.146 13.509 118.146C13 [...]
+	f = "#ea8c4d";
+	g.createPath("M134.819 27.091C128.419 27.891 103.685 3.862 118.019 35.891C134.219 72.092 59.619 75.092 42.819 63.892C26.019 52.692 50.019 82.292 50.019 82.292C68.419 102.292 34.019 85.492 34.019 85.492C-0.381 72.692 -24.382 98.292 -27.582 99.092C-30.782 99.892 -35.582 103.092 -36.382 96.692C-37.182 90.292 -44.43 73.925 -76.382 99.892C-98.855 117.983 -112.036 97.074 -112.036 97.074L-115.636 105.692C-139.436 66.692 -124.891 125.71 -124.891 125.71C-116.091 160.11 14.819 119.892 14.819 119. [...]
+	f = "#ec9961";
+	g.createPath("M136.128 28.837C129.728 29.637 104.999 5.605 119.328 37.637C136.128 75.193 60.394 76.482 44.128 65.637C27.328 54.437 51.328 84.037 51.328 84.037C69.728 104.037 35.328 87.237 35.328 87.237C0.928 74.437 -23.072 100.037 -26.272 100.837C-29.472 101.637 -34.272 104.837 -35.072 98.437C-35.872 92.037 -42.989 75.839 -75.073 101.637C-98.782 120.474 -111.655 100.11 -111.655 100.11L-115.655 107.237C-137.455 70.437 -124.236 128.765 -124.236 128.765C-115.436 163.165 16.128 121.637 16.1 [...]
+	f = "#eea575";
+	g.createPath("M137.438 30.583C131.037 31.383 106.814 7.129 120.637 39.383C137.438 78.583 62.237 78.583 45.437 67.383C28.637 56.183 52.637 85.783 52.637 85.783C71.037 105.783 36.637 88.983 36.637 88.983C2.237 76.183 -21.763 101.783 -24.963 102.583C-28.163 103.383 -32.963 106.583 -33.763 100.183C-34.563 93.783 -41.548 77.752 -73.763 103.383C-98.709 122.965 -111.273 103.146 -111.273 103.146L-115.673 108.783C-135.473 73.982 -123.582 131.819 -123.582 131.819C-114.782 166.22 17.437 123.383 17 [...]
+	f = "#f1b288";
+	g.createPath("M138.747 32.328C132.347 33.128 106.383 9.677 121.947 41.128C141.147 79.928 63.546 80.328 46.746 69.128C29.946 57.928 53.946 87.528 53.946 87.528C72.346 107.528 37.946 90.728 37.946 90.728C3.546 77.928 -20.454 103.528 -23.654 104.328C-26.854 105.128 -31.654 108.328 -32.454 101.928C-33.254 95.528 -40.108 79.665 -72.454 105.128C-98.636 125.456 -110.891 106.183 -110.891 106.183L-115.691 110.328C-133.691 77.128 -122.927 134.874 -122.927 134.874C-114.127 169.274 18.746 125.128 1 [...]
+	f = "#f3bf9c";
+	g.createPath("M140.056 34.073C133.655 34.873 107.313 11.613 123.255 42.873C143.656 82.874 64.855 82.074 48.055 70.874C31.255 59.674 55.255 89.274 55.255 89.274C73.655 109.274 39.255 92.474 39.255 92.474C4.855 79.674 -19.145 105.274 -22.345 106.074C-25.545 106.874 -30.345 110.074 -31.145 103.674C-31.945 97.274 -38.668 81.578 -71.145 106.874C-98.564 127.947 -110.509 109.219 -110.509 109.219L-115.709 111.874C-131.709 81.674 -122.273 137.929 -122.273 137.929C-113.473 172.329 20.055 126.874  [...]
+	f = "#f5ccb0";
+	g.createPath("M141.365 35.819C134.965 36.619 107.523 13.944 124.565 44.619C146.565 84.219 66.164 83.819 49.364 72.619C32.564 61.419 56.564 91.019 56.564 91.019C74.964 111.019 40.564 94.219 40.564 94.219C6.164 81.419 -17.836 107.019 -21.036 107.819C-24.236 108.619 -29.036 111.819 -29.836 105.419C-30.636 99.019 -37.227 83.492 -69.836 108.619C-98.491 130.438 -110.127 112.256 -110.127 112.256L-115.727 113.419C-130.128 85.019 -121.618 140.983 -121.618 140.983C-112.818 175.384 21.364 128.619  [...]
+	f = "#f8d8c4";
+	g.createPath("M142.674 37.565C136.274 38.365 108.832 15.689 125.874 46.365C147.874 85.965 67.474 85.565 50.674 74.365C33.874 63.165 57.874 92.765 57.874 92.765C76.274 112.765 41.874 95.965 41.874 95.965C7.473 83.165 -16.527 108.765 -19.727 109.565C-22.927 110.365 -27.727 113.565 -28.527 107.165C-29.327 100.765 -35.786 85.405 -68.527 110.365C-98.418 132.929 -109.745 115.293 -109.745 115.293L-115.745 114.965C-129.346 88.564 -120.963 144.038 -120.963 144.038C-112.163 178.438 22.673 130.365 [...]
+	f = "#fae5d7";
+	g.createPath("M143.983 39.31C137.583 40.11 110.529 17.223 127.183 48.11C149.183 88.91 68.783 87.31 51.983 76.11C35.183 64.91 59.183 94.51 59.183 94.51C77.583 114.51 43.183 97.71 43.183 97.71C8.783 84.91 -15.217 110.51 -18.417 111.31C-21.618 112.11 -26.418 115.31 -27.218 108.91C-28.018 102.51 -34.346 87.318 -67.218 112.11C-98.345 135.42 -109.363 118.329 -109.363 118.329L-115.764 116.51C-128.764 92.51 -120.309 147.093 -120.309 147.093C-111.509 181.493 23.983 132.11 23.983 132.11C23.983 13 [...]
+	f = "#fcf2eb";
+	g.createPath("M145.292 41.055C138.892 41.855 112.917 18.411 128.492 49.855C149.692 92.656 70.092 89.056 53.292 77.856C36.492 66.656 60.492 96.256 60.492 96.256C78.892 116.256 44.492 99.456 44.492 99.456C10.092 86.656 -13.908 112.256 -17.108 113.056C-20.308 113.856 -25.108 117.056 -25.908 110.656C-26.708 104.256 -32.905 89.232 -65.908 113.856C-98.273 137.911 -108.982 121.365 -108.982 121.365L-115.782 118.056C-128.582 94.856 -119.654 150.147 -119.654 150.147C-110.854 184.547 25.292 133.85 [...]
+	f = "#ffffff";
+	g.createPath("M-115.8 119.601C-128.6 97.6 -119 153.201 -119 153.201C-110.2 187.601 26.6 135.601 26.6 135.601C26.6 135.601 195.401 105.2 206.601 101.2C217.801 97.2 303.401 102.8 303.401 102.8L298.601 80.4C233.801 34 223.401 63.6 209.801 59.6C196.201 55.6 198.601 65.2 195.401 66C192.201 66.8 153.001 42 146.601 42.8C140.201 43.6 114.981 19.793 129.801 51.6C152.028 99.307 69.041 89.227 54.6 79.6C37.8 68.4 61.8 98 61.8 98C80.2 118.001 45.8 101.2 45.8 101.2C11.4 88.4 -12.6 114.001 -15.8 114.8 [...]
+	f = "#000000";
+	g.createPath("M-74.2 149.601C-74.2 149.601 -81.4 161.201 -60.6 174.401C-60.6 174.401 -59.2 175.801 -77.2 171.601C-77.2 171.601 -83.4 169.601 -85 159.201C-85 159.201 -89.8 154.801 -94.6 149.201C-99.4 143.601 -74.2 149.601 -74.2 149.601z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M65.8 102C65.8 102 83.498 128.821 82.9 133.601C81.6 144.001 81.4 153.601 84.6 157.601C87.801 161.601 96.601 194.801 96.601 194.801C96.601 194.801 96.201 196.001 108.601 158.001C108.601 158.001 120.201 142.001 100.201 123.601C100.201 123.601 65 94.8 65.8 102z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-54.2 176.401C-54.2 176.401 -43 183.601 -57.4 214.801L-51 212.401C-51 212.401 -51.8 223.601 -55 226.001L-47.8 222.801C-47.8 222.801 -43 230.801 -47 235.601C-47 235.601 -30.2 243.601 -31 250.001C-31 250.001 -24.6 242.001 -28.6 235.601C-32.6 229.201 -39.8 233.201 -39 214.801L-47.8 218.001C-47.8 218.001 -42.2 209.201 -42.2 202.801L-50.2 205.201C-50.2 205.201 -34.731 178.623 -45.4 177.201C-51.4 176.401 -54.2 176.401 -54.2 176.401z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-21.8 193.201C-21.8 193.201 -19 188.801 -21.8 189.601C-24.6 190.401 -55.8 205.201 -61.8 214.801C-61.8 214.801 -27.4 190.401 -21.8 193.201z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-11.4 201.201C-11.4 201.201 -8.6 196.801 -11.4 197.601C-14.2 198.401 -45.4 213.201 -51.4 222.801C-51.4 222.801 -17 198.401 -11.4 201.201z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M1.8 186.001C1.8 186.001 4.6 181.601 1.8 182.401C-1 183.201 -32.2 198.001 -38.2 207.601C-38.2 207.601 -3.8 183.201 1.8 186.001z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-21.4 229.601C-21.4 229.601 -21.4 223.601 -24.2 224.401C-27 225.201 -63 242.801 -69 252.401C-69 252.401 -27 226.801 -21.4 229.601z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-20.2 218.801C-20.2 218.801 -19 214.001 -21.8 214.801C-23.8 214.801 -50.2 226.401 -56.2 236.001C-56.2 236.001 -26.6 214.401 -20.2 218.801z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-34.6 266.401L-44.6 274.001C-44.6 274.001 -34.2 266.401 -30.6 267.601C-30.6 267.601 -37.4 278.801 -38.2 284.001C-38.2 284.001 -27.8 271.201 -22.2 271.601C-22.2 271.601 -14.6 272.001 -14.6 282.801C-14.6 282.801 -9 272.401 -5.8 272.801C-5.8 272.801 -4.6 279.201 -5.8 286.001C-5.8 286.001 -1.8 278.401 2.2 280.001C2.2 280.001 8.6 278.001 7.8 289.601C7.8 289.601 7.8 300.001 7 302.801C7 302.801 12.6 276.401 15 276.001C15 276.001 23 274.801 27.8 283.601C27.8 283.601 23.8 276.001  [...]
+	f = "#000000";
+	g.createPath("M-29.8 173.601C-29.8 173.601 -15 167.601 25 173.601C25 173.601 32.2 174.001 39 165.201C45.8 156.401 72.6 149.201 79 151.201L88.601 157.601L89.401 158.801C89.401 158.801 101.801 169.201 102.201 176.801C102.601 184.401 87.801 232.401 78.2 248.401C68.6 264.401 59 276.801 39.8 274.401C39.8 274.401 19 270.401 -6.6 274.401C-6.6 274.401 -35.8 272.801 -38.6 264.801C-41.4 256.801 -27.4 241.601 -27.4 241.601C-27.4 241.601 -23 233.201 -24.2 218.801C-25.4 204.401 -25 176.401 -29.8 173 [...]
+	f = "#e5668c";
+	g.createPath("M-7.8 175.601C0.6 194.001 -29 259.201 -29 259.201C-31 260.801 -16.34 266.846 -6.2 264.401C4.746 261.763 45 266.001 45 266.001C68.6 250.401 81.4 206.001 81.4 206.001C81.4 206.001 91.801 182.001 74.2 178.801C56.6 175.601 -7.8 175.601 -7.8 175.601z").setFill(f).setStroke(s);
+	f = "#b23259";
+	g.createPath("M-9.831 206.497C-6.505 193.707 -4.921 181.906 -7.8 175.601C-7.8 175.601 54.6 182.001 65.8 161.201C70.041 153.326 84.801 184.001 84.4 193.601C84.4 193.601 21.4 208.001 6.6 196.801L-9.831 206.497z").setFill(f).setStroke(s);
+	f = "#a5264c";
+	g.createPath("M-5.4 222.801C-5.4 222.801 -3.4 230.001 -5.8 234.001C-5.8 234.001 -7.4 234.801 -8.6 235.201C-8.6 235.201 -7.4 238.801 -1.4 240.401C-1.4 240.401 0.6 244.801 3 245.201C5.4 245.601 10.2 251.201 14.2 250.001C18.2 248.801 29.4 244.801 29.4 244.801C29.4 244.801 35 241.601 43.8 245.201C43.8 245.201 46.175 244.399 46.6 240.401C47.1 235.701 50.2 232.001 52.2 230.001C54.2 228.001 63.8 215.201 62.6 214.801C61.4 214.401 -5.4 222.801 -5.4 222.801z").setFill(f).setStroke(s);
+	f = "#ff727f"; s = "#000000";
+	g.createPath("M-9.8 174.401C-9.8 174.401 -12.6 196.801 -9.4 205.201C-6.2 213.601 -7 215.601 -7.8 219.601C-8.6 223.601 -4.2 233.601 1.4 239.601L13.4 241.201C13.4 241.201 28.6 237.601 37.8 240.401C37.8 240.401 46.794 241.744 50.2 226.801C50.2 226.801 55 220.401 62.2 217.601C69.4 214.801 76.6 173.201 72.6 165.201C68.6 157.201 54.2 152.801 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-8.2 249.201C-8.2 249.201 -9 247.201 -13.4 246.801C-13.4 246.801 -35.8 243.201 -44.2 230.801C-44.2 230.801 -51 225.201 -46.6 236.801C-46.6 236.801 -36.2 257.201 -29.4 260.001C-29.4 260.001 -13 264.001 -8.2 249.201z").setFill(f).setStroke(s);
+	f = "#cc3f4c"; s = null;
+	g.createPath("M71.742 185.229C72.401 177.323 74.354 168.709 72.6 165.201C66.154 152.307 49.181 157.695 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401C-9.8 174.401 -11.545 188.364 -10.705 198.376C-10.705 198.376 26.6 186.801 27.4 192.401C27.4 192.401 29 189.201 38.2 189.201C47.4 189.201 70.142 188.029 71.742 185.229z").setFill(f).setStroke(s);
+	s = {color: "#a51926", width: 2}; f = null;
+	g.createPath("M28.6 175.201C28.6 175.201 33.4 180.001 29.8 189.601C29.8 189.601 15.4 205.601 17.4 219.601").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-19.4 260.001C-19.4 260.001 -23.8 247.201 -15 254.001C-15 254.001 -10.2 256.001 -11.4 257.601C-12.6 259.201 -18.2 263.201 -19.4 260.001z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-14.36 261.201C-14.36 261.201 -17.88 250.961 -10.84 256.401C-10.84 256.401 -6.419 258.849 -7.96 259.281C-12.52 260.561 -7.96 263.121 -14.36 261.201z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-9.56 261.201C-9.56 261.201 -13.08 250.961 -6.04 256.401C-6.04 256.401 -1.665 258.711 -3.16 259.281C-6.52 260.561 -3.16 263.121 -9.56 261.201z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-2.96 261.401C-2.96 261.401 -6.48 251.161 0.56 256.601C0.56 256.601 4.943 258.933 3.441 259.481C0.48 260.561 3.441 263.321 -2.96 261.401z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M3.52 261.321C3.52 261.321 0 251.081 7.041 256.521C7.041 256.521 10.881 258.121 9.921 259.401C8.961 260.681 9.921 263.241 3.52 261.321z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M10.2 262.001C10.2 262.001 5.4 249.601 14.6 256.001C14.6 256.001 19.4 258.001 18.2 259.601C17 261.201 18.2 264.401 10.2 262.001z").setFill(f).setStroke(s);
+	s = {color: "#a5264c", width: 2}; f = null;
+	g.createPath("M-18.2 244.801C-18.2 244.801 -5 242.001 1 245.201C1 245.201 7 246.401 8.2 246.001C9.4 245.601 12.6 245.201 12.6 245.201").setFill(f).setStroke(s);
+	s = {color: "#a5264c", width: 2};
+	g.createPath("M15.8 253.601C15.8 253.601 27.8 240.001 39.8 244.401C46.816 246.974 45.8 243.601 46.6 240.801C47.4 238.001 47.6 233.801 52.6 230.801").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M33 237.601C33 237.601 29 226.801 26.2 239.601C23.4 252.401 20.2 256.001 18.6 258.801C18.6 258.801 18.6 264.001 27 263.601C27 263.601 37.8 263.201 38.2 260.401C38.6 257.601 37 246.001 33 237.601z").setFill(f).setStroke(s);
+	s = {color: "#a5264c", width: 2}; f = null;
+	g.createPath("M47 244.801C47 244.801 50.6 242.401 53 243.601").setFill(f).setStroke(s);
+	s = {color: "#a5264c", width: 2};
+	g.createPath("M53.5 228.401C53.5 228.401 56.4 223.501 61.2 222.701").setFill(f).setStroke(s);
+	f = "#b2b2b2"; s = null;
+	g.createPath("M-25.8 265.201C-25.8 265.201 -7.8 268.401 -3.4 266.801C-3.4 266.801 5.4 266.801 -3 268.801C-3 268.801 -15.8 268.801 -23.8 267.601C-23.8 267.601 -35.4 262.001 -25.8 265.201z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-11.8 172.001C-11.8 172.001 5.8 172.001 7.8 172.801C7.8 172.801 15 203.601 11.4 211.201C11.4 211.201 10.2 214.001 7.4 208.401C7.4 208.401 -11 175.601 -14.2 173.601C-17.4 171.601 -13 172.001 -11.8 172.001z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-88.9 169.301C-88.9 169.301 -80 171.001 -67.4 173.601C-67.4 173.601 -62.6 196.001 -59.4 200.801C-56.2 205.601 -59.8 205.601 -63.4 202.801C-67 200.001 -81.8 186.001 -83.8 181.601C-85.8 177.201 -88.9 169.301 -88.9 169.301z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-67.039 173.818C-67.039 173.818 -61.239 175.366 -60.23 177.581C-59.222 179.795 -61.432 183.092 -61.432 183.092C-61.432 183.092 -62.432 186.397 -63.634 184.235C-64.836 182.072 -67.708 174.412 -67.039 173.818z").setFill(f).setStroke(s);
+	f = "#000000"; s = null;
+	g.createPath("M-67 173.601C-67 173.601 -63.4 178.801 -59.8 178.801C-56.2 178.801 -55.818 178.388 -53 179.001C-48.4 180.001 -48.8 178.001 -42.2 179.201C-39.56 179.681 -37 178.801 -34.2 180.001C-31.4 181.201 -28.2 180.401 -27 178.401C-25.8 176.401 -21 172.201 -21 172.201C-21 172.201 -33.8 174.001 -36.6 174.801C-36.6 174.801 -59 176.001 -67 173.601z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-22.4 173.801C-22.4 173.801 -28.85 177.301 -29.25 179.701C-29.65 182.101 -24 185.801 -24 185.801C-24 185.801 -21.25 190.401 -20.65 188.001C-20.05 185.601 -21.6 174.201 -22.4 173.801z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-59.885 179.265C-59.885 179.265 -52.878 190.453 -52.661 179.242C-52.661 179.242 -52.104 177.984 -53.864 177.962C-59.939 177.886 -58.418 173.784 -59.885 179.265z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-52.707 179.514C-52.707 179.514 -44.786 190.701 -45.422 179.421C-45.422 179.421 -45.415 179.089 -47.168 178.936C-51.915 178.522 -51.57 174.004 -52.707 179.514z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-45.494 179.522C-45.494 179.522 -37.534 190.15 -38.203 180.484C-38.203 180.484 -38.084 179.251 -39.738 178.95C-43.63 178.244 -43.841 174.995 -45.494 179.522z").setFill(f).setStroke(s);
+	f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+	g.createPath("M-38.618 179.602C-38.618 179.602 -30.718 191.163 -30.37 181.382C-30.37 181.382 -28.726 180.004 -30.472 179.782C-36.29 179.042 -35.492 174.588 -38.618 179.602z").setFill(f).setStroke(s);
+	f = "#e5e5b2"; s = null;
+	g.createPath("M-74.792 183.132L-82.45 181.601C-85.05 176.601 -87.15 170.451 -87.15 170.451C-87.15 170.451 -80.8 171.451 -68.3 174.251C-68.3 174.251 -67.424 177.569 -65.952 183.364L-74.792 183.132z").setFill(f).setStroke(s);
+	f = "#e5e5b2";
+	g.createPath("M-9.724 178.47C-11.39 175.964 -12.707 174.206 -13.357 173.8C-16.37 171.917 -12.227 172.294 -11.098 172.294C-11.098 172.294 5.473 172.294 7.356 173.047C7.356 173.047 7.88 175.289 8.564 178.68C8.564 178.68 -1.524 176.67 -9.724 178.47z").setFill(f).setStroke(s);
+	f = "#cc7226";
+	g.createPath("M43.88 40.321C71.601 44.281 97.121 8.641 98.881 -1.04C100.641 -10.72 90.521 -22.6 90.521 -22.6C91.841 -25.68 87.001 -39.76 81.721 -49C76.441 -58.24 60.54 -57.266 43 -58.24C27.16 -59.12 8.68 -35.8 7.36 -34.04C6.04 -32.28 12.2 6.001 13.52 11.721C14.84 17.441 12.2 43.841 12.2 43.841C46.44 34.741 16.16 36.361 43.88 40.321z").setFill(f).setStroke(s);
+	f = "#ea8e51";
+	g.createPath("M8.088 -33.392C6.792 -31.664 12.84 5.921 14.136 11.537C15.432 17.153 12.84 43.073 12.84 43.073C45.512 34.193 16.728 35.729 43.944 39.617C71.161 43.505 96.217 8.513 97.945 -0.992C99.673 -10.496 89.737 -22.16 89.737 -22.16C91.033 -25.184 86.281 -39.008 81.097 -48.08C75.913 -57.152 60.302 -56.195 43.08 -57.152C27.528 -58.016 9.384 -35.12 8.088 -33.392z").setFill(f).setStroke(s);
+	f = "#efaa7c";
+	g.createPath("M8.816 -32.744C7.544 -31.048 13.48 5.841 14.752 11.353C16.024 16.865 13.48 42.305 13.48 42.305C44.884 33.145 17.296 35.097 44.008 38.913C70.721 42.729 95.313 8.385 97.009 -0.944C98.705 -10.272 88.953 -21.72 88.953 -21.72C90.225 -24.688 85.561 -38.256 80.473 -47.16C75.385 -56.064 60.063 -55.125 43.16 -56.064C27.896 -56.912 10.088 -34.44 8.816 -32.744z").setFill(f).setStroke(s);
+	f = "#f4c6a8";
+	g.createPath("M9.544 -32.096C8.296 -30.432 14.12 5.761 15.368 11.169C16.616 16.577 14.12 41.537 14.12 41.537C43.556 32.497 17.864 34.465 44.072 38.209C70.281 41.953 94.409 8.257 96.073 -0.895C97.737 -10.048 88.169 -21.28 88.169 -21.28C89.417 -24.192 84.841 -37.504 79.849 -46.24C74.857 -54.976 59.824 -54.055 43.24 -54.976C28.264 -55.808 10.792 -33.76 9.544 -32.096z").setFill(f).setStroke(s);
+	f = "#f9e2d3";
+	g.createPath("M10.272 -31.448C9.048 -29.816 14.76 5.681 15.984 10.985C17.208 16.289 14.76 40.769 14.76 40.769C42.628 31.849 18.432 33.833 44.136 37.505C69.841 41.177 93.505 8.129 95.137 -0.848C96.769 -9.824 87.385 -20.84 87.385 -20.84C88.609 -23.696 84.121 -36.752 79.225 -45.32C74.329 -53.888 59.585 -52.985 43.32 -53.888C28.632 -54.704 11.496 -33.08 10.272 -31.448z").setFill(f).setStroke(s);
+	f = "#ffffff";
+	g.createPath("M44.2 36.8C69.4 40.4 92.601 8 94.201 -0.8C95.801 -9.6 86.601 -20.4 86.601 -20.4C87.801 -23.2 83.4 -36 78.6 -44.4C73.8 -52.8 59.346 -51.914 43.4 -52.8C29 -53.6 12.2 -32.4 11 -30.8C9.8 -29.2 15.4 5.6 16.6 10.8C17.8 16 15.4 40 15.4 40C40.9 31.4 19 33.2 44.2 36.8z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M90.601 2.8C90.601 2.8 62.8 10.4 51.2 8.8C51.2 8.8 35.4 2.2 26.6 24C26.6 24 23 31.2 21 33.2C19 35.2 90.601 2.8 90.601 2.8z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M94.401 0.6C94.401 0.6 65.4 12.8 55.4 12.4C55.4 12.4 39 7.8 30.6 22.4C30.6 22.4 22.2 31.6 19 33.2C19 33.2 18.6 34.8 25 30.8L35.4 36C35.4 36 50.2 45.6 59.8 29.6C59.8 29.6 63.8 18.4 63.8 16.4C63.8 14.4 85 8.8 86.601 8.4C88.201 8 94.801 3.8 94.401 0.6z").setFill(f).setStroke(s);
+	f = "#99cc32";
+	g.createPath("M47 36.514C40.128 36.514 31.755 32.649 31.755 26.4C31.755 20.152 40.128 13.887 47 13.887C53.874 13.887 59.446 18.952 59.446 25.2C59.446 31.449 53.874 36.514 47 36.514z").setFill(f).setStroke(s);
+	f = "#659900";
+	g.createPath("M43.377 19.83C38.531 20.552 33.442 22.055 33.514 21.839C35.054 17.22 41.415 13.887 47 13.887C51.296 13.887 55.084 15.865 57.32 18.875C57.32 18.875 52.004 18.545 43.377 19.83z").setFill(f).setStroke(s);
+	f = "#ffffff";
+	g.createPath("M55.4 19.6C55.4 19.6 51 16.4 51 18.6C51 18.6 54.6 23 55.4 19.6z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M45.4 27.726C42.901 27.726 40.875 25.7 40.875 23.2C40.875 20.701 42.901 18.675 45.4 18.675C47.9 18.675 49.926 20.701 49.926 23.2C49.926 25.7 47.9 27.726 45.4 27.726z").setFill(f).setStroke(s);
+	f = "#cc7226";
+	g.createPath("M-58.6 14.4C-58.6 14.4 -61.8 -6.8 -59.4 -11.2C-59.4 -11.2 -48.6 -21.2 -49 -24.8C-49 -24.8 -49.4 -42.8 -50.6 -43.6C-51.8 -44.4 -59.4 -50.4 -65.4 -44C-65.4 -44 -75.8 -26 -75 -19.6L-75 -17.6C-75 -17.6 -82.6 -18 -84.2 -16C-84.2 -16 -85.4 -10.8 -86.6 -10.4C-86.6 -10.4 -89.4 -8 -87.4 -5.2C-87.4 -5.2 -89.4 -2.8 -89 1.2L-81.4 5.2C-81.4 5.2 -79.4 19.6 -68.6 24.8C-63.764 27.129 -60.6 20.4 -58.6 14.4z").setFill(f).setStroke(s);
+	f = "#ffffff";
+	g.createPath("M-59.6 12.56C-59.6 12.56 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.48 -40.36 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.96 -59.6 12.56z").setFill( [...]
+	f = "#eb955c";
+	g.createPath("M-51.05 -42.61C-52.14 -43.47 -59.63 -49.24 -65.48 -43C-65.48 -43 -75.62 -25.45 -74.84 -19.21L-74.84 -17.26C-74.84 -17.26 -82.25 -17.65 -83.81 -15.7C-83.81 -15.7 -84.98 -10.63 -86.15 -10.24C-86.15 -10.24 -88.88 -7.9 -86.93 -5.17C-86.93 -5.17 -88.88 -2.83 -88.49 1.07L-81.08 4.97C-81.08 4.97 -79.13 19.01 -68.6 24.08C-63.886 26.35 -60.8 19.79 -58.85 13.94C-58.85 13.94 -61.97 -6.73 -59.63 -11.02C-59.63 -11.02 -49.1 -20.77 -49.49 -24.28C-49.49 -24.28 -49.88 -41.83 -51.05 -42.61z [...]
+	f = "#f2b892";
+	g.createPath("M-51.5 -41.62C-52.48 -42.54 -59.86 -48.08 -65.56 -42C-65.56 -42 -75.44 -24.9 -74.68 -18.82L-74.68 -16.92C-74.68 -16.92 -81.9 -17.3 -83.42 -15.4C-83.42 -15.4 -84.56 -10.46 -85.7 -10.08C-85.7 -10.08 -88.36 -7.8 -86.46 -5.14C-86.46 -5.14 -88.36 -2.86 -87.98 0.94L-80.76 4.74C-80.76 4.74 -78.86 18.42 -68.6 23.36C-64.006 25.572 -61 19.18 -59.1 13.48C-59.1 13.48 -62.14 -6.66 -59.86 -10.84C-59.86 -10.84 -49.6 -20.34 -49.98 -23.76C-49.98 -23.76 -50.36 -40.86 -51.5 -41.62z").setFill [...]
+	f = "#f8dcc8";
+	g.createPath("M-51.95 -40.63C-52.82 -41.61 -60.09 -46.92 -65.64 -41C-65.64 -41 -75.26 -24.35 -74.52 -18.43L-74.52 -16.58C-74.52 -16.58 -81.55 -16.95 -83.03 -15.1C-83.03 -15.1 -84.14 -10.29 -85.25 -9.92C-85.25 -9.92 -87.84 -7.7 -85.99 -5.11C-85.99 -5.11 -87.84 -2.89 -87.47 0.81L-80.44 4.51C-80.44 4.51 -78.59 17.83 -68.6 22.64C-64.127 24.794 -61.2 18.57 -59.35 13.02C-59.35 13.02 -62.31 -6.59 -60.09 -10.66C-60.09 -10.66 -50.1 -19.91 -50.47 -23.24C-50.47 -23.24 -50.84 -39.89 -51.95 -40.63z" [...]
+	f = "#ffffff";
+	g.createPath("M-59.6 12.46C-59.6 12.46 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.16 -40.68 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.86 -59.6 12.46z").setFill( [...]
+	f = "#cccccc";
+	g.createPath("M-62.7 6.2C-62.7 6.2 -84.3 -4 -85.2 -4.8C-85.2 -4.8 -76.1 3.4 -75.3 3.4C-74.5 3.4 -62.7 6.2 -62.7 6.2z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-79.8 0C-79.8 0 -61.4 3.6 -61.4 8C-61.4 10.912 -61.643 24.331 -67 22.8C-75.4 20.4 -71.8 6 -79.8 0z").setFill(f).setStroke(s);
+	f = "#99cc32";
+	g.createPath("M-71.4 3.8C-71.4 3.8 -62.422 5.274 -61.4 8C-60.8 9.6 -60.137 17.908 -65.6 19C-70.152 19.911 -72.382 9.69 -71.4 3.8z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M14.595 46.349C14.098 44.607 15.409 44.738 17.2 44.2C19.2 43.6 31.4 39.8 32.2 37.2C33 34.6 46.2 39 46.2 39C48 39.8 52.4 42.4 52.4 42.4C57.2 43.6 63.8 44 63.8 44C66.2 45 69.6 47.8 69.6 47.8C84.2 58 96.601 50.8 96.601 50.8C116.601 44.2 110.601 27 110.601 27C107.601 18 110.801 14.6 110.801 14.6C111.001 10.8 118.201 17.2 118.201 17.2C120.801 21.4 121.601 26.4 121.601 26.4C129.601 37.6 126.201 19.8 126.201 19.8C126.401 18.8 123.601 15.2 123.601 14C123.601 12.8 121.801 9.4 121.8 [...]
+	f = "#000000";
+	g.createPath("M209.401 -120C209.401 -120 183.801 -112 181.001 -93.2C181.001 -93.2 178.601 -70.4 199.001 -52.8C199.001 -52.8 199.401 -46.4 201.401 -43.2C201.401 -43.2 199.801 -38.4 218.601 -46L245.801 -54.4C245.801 -54.4 252.201 -56.8 257.401 -65.6C262.601 -74.4 277.801 -93.2 274.201 -118.4C274.201 -118.4 275.401 -129.6 269.401 -130C269.401 -130 261.001 -131.6 253.801 -124C253.801 -124 247.001 -120.8 244.601 -121.2L209.401 -120z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M264.022 -120.99C264.022 -120.99 266.122 -129.92 261.282 -125.08C261.282 -125.08 254.242 -119.36 246.761 -119.36C246.761 -119.36 232.241 -117.16 227.841 -103.96C227.841 -103.96 223.881 -77.12 231.801 -71.4C231.801 -71.4 236.641 -63.92 243.681 -70.52C250.722 -77.12 266.222 -107.35 264.022 -120.99z").setFill(f).setStroke(s);
+	f = "#323232";
+	g.createPath("M263.648 -120.632C263.648 -120.632 265.738 -129.376 260.986 -124.624C260.986 -124.624 254.074 -119.008 246.729 -119.008C246.729 -119.008 232.473 -116.848 228.153 -103.888C228.153 -103.888 224.265 -77.536 232.041 -71.92C232.041 -71.92 236.793 -64.576 243.705 -71.056C250.618 -77.536 265.808 -107.24 263.648 -120.632z").setFill(f).setStroke(s);
+	f = "#666666";
+	g.createPath("M263.274 -120.274C263.274 -120.274 265.354 -128.832 260.69 -124.168C260.69 -124.168 253.906 -118.656 246.697 -118.656C246.697 -118.656 232.705 -116.536 228.465 -103.816C228.465 -103.816 224.649 -77.952 232.281 -72.44C232.281 -72.44 236.945 -65.232 243.729 -71.592C250.514 -77.952 265.394 -107.13 263.274 -120.274z").setFill(f).setStroke(s);
+	f = "#999999";
+	g.createPath("M262.9 -119.916C262.9 -119.916 264.97 -128.288 260.394 -123.712C260.394 -123.712 253.738 -118.304 246.665 -118.304C246.665 -118.304 232.937 -116.224 228.777 -103.744C228.777 -103.744 225.033 -78.368 232.521 -72.96C232.521 -72.96 237.097 -65.888 243.753 -72.128C250.41 -78.368 264.98 -107.02 262.9 -119.916z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M262.526 -119.558C262.526 -119.558 264.586 -127.744 260.098 -123.256C260.098 -123.256 253.569 -117.952 246.633 -117.952C246.633 -117.952 233.169 -115.912 229.089 -103.672C229.089 -103.672 225.417 -78.784 232.761 -73.48C232.761 -73.48 237.249 -66.544 243.777 -72.664C250.305 -78.784 264.566 -106.91 262.526 -119.558z").setFill(f).setStroke(s);
+	f = "#ffffff";
+	g.createPath("M262.151 -119.2C262.151 -119.2 264.201 -127.2 259.801 -122.8C259.801 -122.8 253.401 -117.6 246.601 -117.6C246.601 -117.6 233.401 -115.6 229.401 -103.6C229.401 -103.6 225.801 -79.2 233.001 -74C233.001 -74 237.401 -67.2 243.801 -73.2C250.201 -79.2 264.151 -106.8 262.151 -119.2z").setFill(f).setStroke(s);
+	f = "#992600";
+	g.createPath("M50.6 84C50.6 84 30.2 64.8 22.2 64C22.2 64 -12.2 60 -27 78C-27 78 -9.4 57.6 18.2 63.2C18.2 63.2 -3.4 58.8 -15.8 62C-15.8 62 -32.6 62 -42.2 76L-45 80.8C-45 80.8 -41 66 -22.6 60C-22.6 60 0.2 55.2 11 60C11 60 -10.6 53.2 -20.6 55.2C-20.6 55.2 -51 52.8 -63.8 79.2C-63.8 79.2 -59.8 64.8 -45 57.6C-45 57.6 -31.4 48.8 -11 51.6C-11 51.6 3.4 54.8 8.6 57.2C13.8 59.6 12.6 56.8 4.2 52C4.2 52 -1.4 42 -15.4 42.4C-15.4 42.4 -58.2 46 -68.6 58C-68.6 58 -55 46.8 -44.6 44C-44.6 44 -22.2 36 -13. [...]
+	f = "#cccccc";
+	g.createPath("M189 278C189 278 173.5 241.5 161 232C161 232 187 248 190.5 266C190.5 266 190.5 276 189 278z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M236 285.5C236 285.5 209.5 230.5 191 206.5C191 206.5 234.5 244 239.5 270.5L240 276L237 273.5C237 273.5 236.5 282.5 236 285.5z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M292.5 237C292.5 237 230 177.5 228.5 175C228.5 175 289 241 292 248.5C292 248.5 290 239.5 292.5 237z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M104 280.5C104 280.5 123.5 228.5 142.5 251C142.5 251 157.5 261 157 264C157 264 153 257.5 135 258C135 258 116 255 104 280.5z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M294.5 153C294.5 153 249.5 124.5 242 123C230.193 120.639 291.5 152 296.5 162.5C296.5 162.5 298.5 160 294.5 153z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M143.801 259.601C143.801 259.601 164.201 257.601 171.001 250.801L175.401 254.401L193.001 216.001L196.601 221.201C196.601 221.201 211.001 206.401 210.201 198.401C209.401 190.401 223.001 204.401 223.001 204.401C223.001 204.401 222.201 192.801 229.401 199.601C229.401 199.601 227.001 184.001 235.401 192.001C235.401 192.001 224.864 161.844 247.401 187.601C253.001 194.001 248.601 187.201 248.601 187.201C248.601 187.201 222.601 139.201 244.201 153.601C244.201 153.601 246.201 130. [...]
+	f = "#000000";
+	g.createPath("M109.401 -97.2C109.401 -97.2 97.801 -105.2 93.801 -104.8C89.801 -104.4 121.401 -113.6 162.601 -86C162.601 -86 167.401 -83.2 171.001 -83.6C171.001 -83.6 174.201 -81.2 171.401 -77.6C171.401 -77.6 162.601 -68 173.801 -56.8C173.801 -56.8 192.201 -50 186.601 -58.8C186.601 -58.8 197.401 -54.8 199.801 -50.8C202.201 -46.8 201.001 -50.8 201.001 -50.8C201.001 -50.8 194.601 -58 188.601 -63.2C188.601 -63.2 183.401 -65.2 180.601 -73.6C177.801 -82 175.401 -92 179.801 -95.2C179.801 -95.2 [...]
+	f = "#cc7226";
+	g.createPath("M180.801 -106.4C180.801 -106.4 170.601 -113.8 168.601 -113.8C166.601 -113.8 154.201 -124 150.001 -123.6C145.801 -123.2 133.601 -133.2 106.201 -125C106.201 -125 105.601 -127 109.201 -127.8C109.201 -127.8 115.601 -130 116.001 -130.6C116.001 -130.6 136.201 -134.8 143.401 -131.2C143.401 -131.2 152.601 -128.6 158.801 -122.4C158.801 -122.4 170.001 -119.2 173.201 -120.2C173.201 -120.2 182.001 -118 182.401 -116.2C182.401 -116.2 188.201 -113.2 186.401 -110.6C186.401 -110.6 186.801  [...]
+	f = "#cc7226";
+	g.createPath("M168.33 -108.509C169.137 -107.877 170.156 -107.779 170.761 -106.97C170.995 -106.656 170.706 -106.33 170.391 -106.233C169.348 -105.916 168.292 -106.486 167.15 -105.898C166.748 -105.691 166.106 -105.873 165.553 -106.022C163.921 -106.463 162.092 -106.488 160.401 -105.8C158.416 -106.929 156.056 -106.345 153.975 -107.346C153.917 -107.373 153.695 -107.027 153.621 -107.054C150.575 -108.199 146.832 -107.916 144.401 -110.2C141.973 -110.612 139.616 -111.074 137.188 -111.754C135.37 - [...]
+	f = "#cc7226";
+	g.createPath("M91.696 -122.739C89.178 -124.464 86.81 -125.57 84.368 -127.356C84.187 -127.489 83.827 -127.319 83.625 -127.441C82.618 -128.05 81.73 -128.631 80.748 -129.327C80.209 -129.709 79.388 -129.698 78.88 -129.956C76.336 -131.248 73.707 -131.806 71.2 -133C71.882 -133.638 73.004 -133.394 73.6 -134.2C73.795 -133.92 74.033 -133.636 74.386 -133.827C76.064 -134.731 77.914 -134.884 79.59 -134.794C81.294 -134.702 83.014 -134.397 84.789 -134.125C85.096 -134.078 85.295 -133.555 85.618 -133.4 [...]
+	f = "#cc7226";
+	g.createPath("M59.198 -115.391C56.044 -116.185 52.994 -116.07 49.978 -117.346C49.911 -117.374 49.688 -117.027 49.624 -117.054C48.258 -117.648 47.34 -118.614 46.264 -119.66C45.351 -120.548 43.693 -120.161 42.419 -120.648C42.095 -120.772 41.892 -121.284 41.591 -121.323C40.372 -121.48 39.445 -122.429 38.4 -123C40.736 -123.795 43.147 -123.764 45.609 -124.148C45.722 -124.166 45.867 -123.845 46 -123.845C46.136 -123.845 46.266 -124.066 46.4 -124.2C46.595 -123.92 46.897 -123.594 47.154 -123.848 [...]
+	f = "#cc7226";
+	g.createPath("M45.338 -71.179C43.746 -72.398 43.162 -74.429 42.034 -76.221C41.82 -76.561 42.094 -76.875 42.411 -76.964C42.971 -77.123 43.514 -76.645 43.923 -76.443C45.668 -75.581 47.203 -74.339 49.2 -74.2C51.19 -71.966 55.45 -71.581 55.457 -68.2C55.458 -67.341 54.03 -68.259 53.6 -67.4C51.149 -68.403 48.76 -68.3 46.38 -69.767C45.763 -70.148 46.093 -70.601 45.338 -71.179z").setFill(f).setStroke(s);
+	f = "#cc7226";
+	g.createPath("M17.8 -123.756C17.935 -123.755 24.966 -123.522 24.949 -123.408C24.904 -123.099 17.174 -122.05 16.81 -122.22C16.646 -122.296 9.134 -119.866 9 -120C9.268 -120.135 17.534 -123.756 17.8 -123.756z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M33.2 -114C33.2 -114 18.4 -112.2 14 -111C9.6 -109.8 -9 -102.2 -12 -100.2C-12 -100.2 -25.4 -94.8 -42.4 -74.8C-42.4 -74.8 -34.8 -78.2 -32.6 -81C-32.6 -81 -19 -93.6 -19.2 -91C-19.2 -91 -7 -99.6 -7.6 -97.4C-7.6 -97.4 16.8 -108.6 14.8 -105.4C14.8 -105.4 36.4 -110 35.4 -108C35.4 -108 54.2 -103.6 51.4 -103.4C51.4 -103.4 45.6 -102.2 52 -98.6C52 -98.6 48.6 -94.2 43.2 -98.2C37.8 -102.2 40.8 -100 35.8 -99C35.8 -99 33.2 -98.2 28.6 -102.2C28.6 -102.2 23 -106.8 14.2 -103.2C14.2 -103.2 - [...]
+	s = {color: "#4c0000", width: 2}; f = null;
+	g.createPath("M51.4 85C51.4 85 36.4 68.2 28 65.6C28 65.6 14.6 58.8 -10 66.6").setFill(f).setStroke(s);
+	s = {color: "#4c0000", width: 2};
+	g.createPath("M24.8 64.2C24.8 64.2 -0.4 56.2 -15.8 60.4C-15.8 60.4 -34.2 62.4 -42.6 76.2").setFill(f).setStroke(s);
+	s = {color: "#4c0000", width: 2};
+	g.createPath("M21.2 63C21.2 63 4.2 55.8 -10.6 53.6C-10.6 53.6 -27.2 51 -43.8 58.2C-43.8 58.2 -56 64.2 -61.4 74.4").setFill(f).setStroke(s);
+	s = {color: "#4c0000", width: 2};
+	g.createPath("M22.2 63.4C22.2 63.4 6.8 52.4 5.8 51C5.8 51 -1.2 40 -14.2 39.6C-14.2 39.6 -35.6 40.4 -52.8 48.4").setFill(f).setStroke(s);
+	f = "#000000"; s = null;
+	g.createPath("M20.895 54.407C22.437 55.87 49.4 84.8 49.4 84.8C84.6 121.401 56.6 87.2 56.6 87.2C49 82.4 39.8 63.6 39.8 63.6C38.6 60.8 53.8 70.8 53.8 70.8C57.8 71.6 71.4 90.8 71.4 90.8C64.6 88.4 69.4 95.6 69.4 95.6C72.2 97.6 92.601 113.201 92.601 113.201C96.201 117.201 100.201 118.801 100.201 118.801C114.201 113.601 107.801 126.801 107.801 126.801C110.201 133.601 115.801 122.001 115.801 122.001C127.001 105.2 110.601 107.601 110.601 107.601C80.6 110.401 73.8 94.4 73.8 94.4C71.4 92 80.2 94. [...]
+	f = "#4c0000";
+	g.createPath("M-3 42.8C-3 42.8 8.6 48.4 11.2 51.2C13.8 54 27.8 65.4 27.8 65.4C27.8 65.4 22.4 63.4 19.8 61.6C17.2 59.8 6.4 51.6 6.4 51.6C6.4 51.6 2.6 45.6 -3 42.8z").setFill(f).setStroke(s);
+	f = "#99cc32";
+	g.createPath("M-61.009 11.603C-60.672 11.455 -61.196 8.743 -61.4 8.2C-62.422 5.474 -71.4 4 -71.4 4C-71.627 5.365 -71.682 6.961 -71.576 8.599C-71.576 8.599 -66.708 14.118 -61.009 11.603z").setFill(f).setStroke(s);
+	f = "#659900";
+	g.createPath("M-61.009 11.403C-61.458 11.561 -61.024 8.669 -61.2 8.2C-62.222 5.474 -71.4 3.9 -71.4 3.9C-71.627 5.265 -71.682 6.861 -71.576 8.499C-71.576 8.499 -67.308 13.618 -61.009 11.403z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-65.4 11.546C-66.025 11.546 -66.531 10.406 -66.531 9C-66.531 7.595 -66.025 6.455 -65.4 6.455C-64.775 6.455 -64.268 7.595 -64.268 9C-64.268 10.406 -64.775 11.546 -65.4 11.546z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-65.4 9z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-111 109.601C-111 109.601 -116.6 119.601 -91.8 113.601C-91.8 113.601 -77.8 112.401 -75.4 110.001C-74.2 110.801 -65.834 113.734 -63 114.401C-56.2 116.001 -47.8 106 -47.8 106C-47.8 106 -43.2 95.5 -40.4 95.5C-37.6 95.5 -40.8 97.1 -40.8 97.1C-40.8 97.1 -47.4 107.201 -47 108.801C-47 108.801 -52.2 128.801 -68.2 129.601C-68.2 129.601 -84.35 130.551 -83 136.401C-83 136.401 -74.2 134.001 -71.8 136.401C-71.8 136.401 -61 136.001 -69 142.401L-75.8 154.001C-75.8 154.001 -75.66 157.919 [...]
+	f = "#e59999";
+	g.createPath("M-112.2 113.601C-112.2 113.601 -114.2 123.201 -77.4 112.801C-77.4 112.801 -73 112.801 -70.6 113.601C-68.2 114.401 -56.2 117.201 -54.2 116.001C-54.2 116.001 -61.4 129.601 -73 128.001C-73 128.001 -86.2 129.601 -85.8 134.401C-85.8 134.401 -81.8 141.601 -77 144.001C-77 144.001 -74.2 146.401 -74.6 149.601C-75 152.801 -77.8 154.401 -79.8 155.201C-81.8 156.001 -85 152.801 -86.6 152.801C-88.2 152.801 -96.6 146.401 -101 141.601C-105.4 136.801 -113.8 124.801 -113.4 122.001C-113 119. [...]
+	f = "#b26565";
+	g.createPath("M-109 131.051C-106.4 135.001 -103.2 139.201 -101 141.601C-96.6 146.401 -88.2 152.801 -86.6 152.801C-85 152.801 -81.8 156.001 -79.8 155.201C-77.8 154.401 -75 152.801 -74.6 149.601C-74.2 146.401 -77 144.001 -77 144.001C-80.066 142.468 -82.806 138.976 -84.385 136.653C-84.385 136.653 -84.2 139.201 -89.4 138.401C-94.6 137.601 -99.8 134.801 -101.4 131.601C-103 128.401 -105.4 126.001 -103.8 129.601C-102.2 133.201 -99.8 136.801 -98.2 137.201C-96.6 137.601 -97 138.801 -99.4 138.401 [...]
+	f = "#992600";
+	g.createPath("M-111.6 110.001C-111.6 110.001 -109.8 96.4 -108.6 92.4C-108.6 92.4 -109.4 85.6 -107 81.4C-104.6 77.2 -102.6 71 -99.6 65.6C-96.6 60.2 -96.4 56.2 -92.4 54.6C-88.4 53 -82.4 44.4 -79.6 43.4C-76.8 42.4 -77 43.2 -77 43.2C-77 43.2 -70.2 28.4 -56.6 32.4C-56.6 32.4 -72.8 29.6 -57 20.2C-57 20.2 -61.8 21.3 -58.5 14.3C-56.299 9.632 -56.8 16.4 -67.8 28.2C-67.8 28.2 -72.8 36.8 -78 39.8C-83.2 42.8 -95.2 49.8 -96.4 53.6C-97.6 57.4 -100.8 63.2 -102.8 64.8C-104.8 66.4 -107.6 70.6 -108 74C-1 [...]
+	f = "#ffffff";
+	g.createPath("M-120.2 114.601C-120.2 114.601 -122.2 113.201 -126.6 119.201C-126.6 119.201 -119.3 152.201 -119.3 153.601C-119.3 153.601 -118.2 151.501 -119.5 144.301C-120.8 137.101 -121.7 124.401 -121.7 124.401L-120.2 114.601z").setFill(f).setStroke(s);
+	f = "#992600";
+	g.createPath("M-98.6 54C-98.6 54 -116.2 57.2 -115.8 86.4L-116.6 111.201C-116.6 111.201 -117.8 85.6 -119 84C-120.2 82.4 -116.2 71.2 -119.4 77.2C-119.4 77.2 -133.4 91.2 -125.4 112.401C-125.4 112.401 -123.9 115.701 -126.9 111.101C-126.9 111.101 -131.5 98.5 -130.4 92.1C-130.4 92.1 -130.2 89.9 -128.3 87.1C-128.3 87.1 -119.7 75.4 -117 73.1C-117 73.1 -115.2 58.7 -99.8 53.5C-99.8 53.5 -94.1 51.2 -98.6 54z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M40.8 -12.2C41.46 -12.554 41.451 -13.524 42.031 -13.697C43.18 -14.041 43.344 -15.108 43.862 -15.892C44.735 -17.211 44.928 -18.744 45.51 -20.235C45.782 -20.935 45.809 -21.89 45.496 -22.55C44.322 -25.031 43.62 -27.48 42.178 -29.906C41.91 -30.356 41.648 -31.15 41.447 -31.748C40.984 -33.132 39.727 -34.123 38.867 -35.443C38.579 -35.884 39.104 -36.809 38.388 -36.893C37.491 -36.998 36.042 -37.578 35.809 -36.552C35.221 -33.965 36.232 -31.442 37.2 -29C36.418 -28.308 36.752 -27.387  [...]
+	f = "#000000";
+	g.createPath("M31.959 -16.666C32.083 -16.743 31.928 -17.166 32.037 -17.382C32.199 -17.706 32.602 -17.894 32.764 -18.218C32.873 -18.434 32.71 -18.814 32.846 -18.956C35.179 -21.403 35.436 -24.427 34.4 -27.4C35.424 -28.02 35.485 -29.282 35.06 -30.129C34.207 -31.829 34.014 -33.755 33.039 -35.298C32.237 -36.567 30.659 -37.811 29.288 -36.508C28.867 -36.108 28.546 -35.321 28.824 -34.609C28.888 -34.446 29.173 -34.3 29.146 -34.218C29.039 -33.894 28.493 -33.67 28.487 -33.398C28.457 -31.902 27.503 [...]
+	f = "#000000";
+	g.createPath("M94.771 -26.977C96.16 -25.185 96.45 -22.39 94.401 -21C94.951 -17.691 98.302 -19.67 100.401 -20.2C100.292 -20.588 100.519 -20.932 100.802 -20.937C101.859 -20.952 102.539 -21.984 103.601 -21.8C104.035 -23.357 105.673 -24.059 106.317 -25.439C108.043 -29.134 107.452 -33.407 104.868 -36.653C104.666 -36.907 104.883 -37.424 104.759 -37.786C104.003 -39.997 101.935 -40.312 100.001 -41C98.824 -44.875 98.163 -48.906 96.401 -52.6C94.787 -52.85 94.089 -54.589 92.752 -55.309C91.419 -56. [...]
+	f = "#000000";
+	g.createPath("M57.611 -8.591C56.124 -6.74 52.712 -4.171 55.629 -2.243C55.823 -2.114 56.193 -2.11 56.366 -2.244C58.387 -3.809 60.39 -4.712 62.826 -5.294C62.95 -5.323 63.224 -4.856 63.593 -5.017C65.206 -5.72 67.216 -5.662 68.4 -7C72.167 -6.776 75.732 -7.892 79.123 -9.2C80.284 -9.648 81.554 -10.207 82.755 -10.709C84.131 -11.285 85.335 -12.213 86.447 -13.354C86.58 -13.49 86.934 -13.4 87.201 -13.4C87.161 -14.263 88.123 -14.39 88.37 -15.012C88.462 -15.244 88.312 -15.64 88.445 -15.742C90.583 - [...]
+	f = "#000000";
+	g.createPath("M2.2 -58C2.2 -58 -7.038 -60.872 -18.2 -35.2C-18.2 -35.2 -20.6 -30 -23 -28C-25.4 -26 -36.6 -22.4 -38.6 -18.4L-49 -2.4C-49 -2.4 -34.2 -18.4 -31 -20.8C-31 -20.8 -23 -29.2 -26.2 -22.4C-26.2 -22.4 -40.2 -11.6 -39 -2.4C-39 -2.4 -44.6 12 -45.4 14C-45.4 14 -29.4 -18 -27 -19.2C-24.6 -20.4 -23.4 -20.4 -24.6 -16.8C-25.8 -13.2 -26.2 3.2 -29 5.2C-29 5.2 -21 -15.2 -21.8 -18.4C-21.8 -18.4 -18.6 -22 -16.2 -16.8L-17.4 -0.8L-13 11.2C-13 11.2 -15.4 0 -13.8 -15.6C-13.8 -15.6 -15.8 -26 -11.8 - [...]
+	f = "#000000";
+	g.createPath("M-17.8 -41.6C-17.8 -41.6 -30.6 -41.6 -33.8 -36.4L-41 -26.8C-41 -26.8 -23.8 -36.8 -19.8 -38C-15.8 -39.2 -17.8 -41.6 -17.8 -41.6z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-57.8 -35.2C-57.8 -35.2 -59.8 -34 -60.2 -31.2C-60.6 -28.4 -63 -28 -62.2 -25.2C-61.4 -22.4 -59.4 -20 -59.4 -24C-59.4 -28 -57.8 -30 -57 -31.2C-56.2 -32.4 -54.6 -36.8 -57.8 -35.2z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-66.6 26C-66.6 26 -75 22 -78.2 18.4C-81.4 14.8 -80.948 19.966 -85.8 19.6C-91.647 19.159 -90.6 3.2 -90.6 3.2L-94.6 10.8C-94.6 10.8 -95.8 25.2 -87.8 22.8C-83.893 21.628 -82.6 23.2 -84.2 24C-85.8 24.8 -78.6 25.2 -81.4 26.8C-84.2 28.4 -69.8 23.2 -72.2 33.6L-66.6 26z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-79.2 40.4C-79.2 40.4 -94.6 44.8 -98.2 35.2C-98.2 35.2 -103 37.6 -100.8 40.6C-98.6 43.6 -97.4 44 -97.4 44C-97.4 44 -92 45.2 -92.6 46C-93.2 46.8 -95.6 50.2 -95.6 50.2C-95.6 50.2 -85.4 44.2 -79.2 40.4z").setFill(f).setStroke(s);
+	f = "#ffffff";
+	g.createPath("M149.201 118.601C148.774 120.735 147.103 121.536 145.201 122.201C143.284 121.243 140.686 118.137 138.801 120.201C138.327 119.721 137.548 119.661 137.204 118.999C136.739 118.101 137.011 117.055 136.669 116.257C136.124 114.985 135.415 113.619 135.601 112.201C137.407 111.489 138.002 109.583 137.528 107.82C137.459 107.563 137.03 107.366 137.23 107.017C137.416 106.694 137.734 106.467 138.001 106.2C137.866 106.335 137.721 106.568 137.61 106.548C137 106.442 137.124 105.805 137.25 [...]
+	f = "#ffffff";
+	g.createPath("M139.6 138.201C139.593 136.463 137.992 134.707 139.201 133.001C139.336 133.135 139.467 133.356 139.601 133.356C139.736 133.356 139.867 133.135 140.001 133.001C141.496 135.217 145.148 136.145 145.006 138.991C144.984 139.438 143.897 140.356 144.801 141.001C142.988 142.349 142.933 144.719 142.001 146.601C140.763 146.315 139.551 145.952 138.401 145.401C138.753 143.915 138.636 142.231 139.456 140.911C139.89 140.213 139.603 139.134 139.6 138.201z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-26.6 129.201C-26.6 129.201 -43.458 139.337 -29.4 124.001C-20.6 114.401 -10.6 108.801 -10.6 108.801C-10.6 108.801 -0.2 104.4 3.4 103.2C7 102 22.2 96.8 25.4 96.4C28.6 96 38.2 92 45 96C51.8 100 59.8 104.4 59.8 104.4C59.8 104.4 43.4 96 39.8 98.4C36.2 100.8 29 100.4 23 103.6C23 103.6 8.2 108.001 5 110.001C1.8 112.001 -8.6 123.601 -10.2 122.801C-11.8 122.001 -9.8 121.601 -8.6 118.801C-7.4 116.001 -9.4 114.401 -17.4 120.801C-25.4 127.201 -26.6 129.201 -26.6 129.201z").setFill(f [...]
+	f = "#000000";
+	g.createPath("M-19.195 123.234C-19.195 123.234 -17.785 110.194 -9.307 111.859C-9.307 111.859 -1.081 107.689 1.641 105.721C1.641 105.721 9.78 104.019 11.09 103.402C29.569 94.702 44.288 99.221 44.835 98.101C45.381 96.982 65.006 104.099 68.615 108.185C69.006 108.628 58.384 102.588 48.686 100.697C40.413 99.083 18.811 100.944 7.905 106.48C4.932 107.989 -4.013 113.773 -6.544 113.662C-9.075 113.55 -19.195 123.234 -19.195 123.234z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-23 148.801C-23 148.801 -38.2 146.401 -21.4 144.801C-21.4 144.801 -3.4 142.801 0.6 137.601C0.6 137.601 14.2 128.401 17 128.001C19.8 127.601 49.8 120.401 50.2 118.001C50.6 115.601 56.2 115.601 57.8 116.401C59.4 117.201 58.6 118.401 55.8 119.201C53 120.001 21.8 136.401 15.4 137.601C9 138.801 -2.6 146.401 -7.4 147.601C-12.2 148.801 -23 148.801 -23 148.801z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-3.48 141.403C-3.48 141.403 -12.062 140.574 -3.461 139.755C-3.461 139.755 5.355 136.331 7.403 133.668C7.403 133.668 14.367 128.957 15.8 128.753C17.234 128.548 31.194 124.861 31.399 123.633C31.604 122.404 65.67 109.823 70.09 113.013C73.001 115.114 63.1 113.437 53.466 117.847C52.111 118.467 18.258 133.054 14.981 133.668C11.704 134.283 5.765 138.174 3.307 138.788C0.85 139.403 -3.48 141.403 -3.48 141.403z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-11.4 143.601C-11.4 143.601 -6.2 143.201 -7.4 144.801C-8.6 146.401 -11 145.601 -11 145.601L-11.4 143.601z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-18.6 145.201C-18.6 145.201 -13.4 144.801 -14.6 146.401C-15.8 148.001 -18.2 147.201 -18.2 147.201L-18.6 145.201z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-29 146.801C-29 146.801 -23.8 146.401 -25 148.001C-26.2 149.601 -28.6 148.801 -28.6 148.801L-29 146.801z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-36.6 147.601C-36.6 147.601 -31.4 147.201 -32.6 148.801C-33.8 150.401 -36.2 149.601 -36.2 149.601L-36.6 147.601z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M1.8 108.001C1.8 108.001 6.2 108.001 5 109.601C3.8 111.201 0.6 110.801 0.6 110.801L1.8 108.001z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-8.2 113.601C-8.2 113.601 -1.694 111.46 -4.2 114.801C-5.4 116.401 -7.8 115.601 -7.8 115.601L-8.2 113.601z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-19.4 118.401C-19.4 118.401 -14.2 118.001 -15.4 119.601C-16.6 121.201 -19 120.401 -19 120.401L-19.4 118.401z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-27 124.401C-27 124.401 -21.8 124.001 -23 125.601C-24.2 127.201 -26.6 126.401 -26.6 126.401L-27 124.401z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-33.8 129.201C-33.8 129.201 -28.6 128.801 -29.8 130.401C-31 132.001 -33.4 131.201 -33.4 131.201L-33.8 129.201z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M5.282 135.598C5.282 135.598 12.203 135.066 10.606 137.195C9.009 139.325 5.814 138.26 5.814 138.26L5.282 135.598z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M15.682 130.798C15.682 130.798 22.603 130.266 21.006 132.395C19.409 134.525 16.214 133.46 16.214 133.46L15.682 130.798z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M26.482 126.398C26.482 126.398 33.403 125.866 31.806 127.995C30.209 130.125 27.014 129.06 27.014 129.06L26.482 126.398z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M36.882 121.598C36.882 121.598 43.803 121.066 42.206 123.195C40.609 125.325 37.414 124.26 37.414 124.26L36.882 121.598z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M9.282 103.598C9.282 103.598 16.203 103.066 14.606 105.195C13.009 107.325 9.014 107.06 9.014 107.06L9.282 103.598z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M19.282 100.398C19.282 100.398 26.203 99.866 24.606 101.995C23.009 104.125 18.614 103.86 18.614 103.86L19.282 100.398z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-3.4 140.401C-3.4 140.401 1.8 140.001 0.6 141.601C-0.6 143.201 -3 142.401 -3 142.401L-3.4 140.401z").setFill(f).setStroke(s);
+	f = "#992600";
+	g.createPath("M-76.6 41.2C-76.6 41.2 -81 50 -81.4 53.2C-81.4 53.2 -80.6 44.4 -79.4 42.4C-78.2 40.4 -76.6 41.2 -76.6 41.2z").setFill(f).setStroke(s);
+	f = "#992600";
+	g.createPath("M-95 55.2C-95 55.2 -98.2 69.6 -97.8 72.4C-97.8 72.4 -99 60.8 -98.6 59.6C-98.2 58.4 -95 55.2 -95 55.2z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-74.2 -19.4L-74.4 -16.2L-76.6 -16C-76.6 -16 -62.4 -3.4 -61.8 4.2C-61.8 4.2 -61 -4 -74.2 -19.4z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-70.216 -18.135C-70.647 -18.551 -70.428 -19.296 -70.836 -19.556C-71.645 -20.072 -69.538 -20.129 -69.766 -20.845C-70.149 -22.051 -69.962 -22.072 -70.084 -23.348C-70.141 -23.946 -69.553 -25.486 -69.168 -25.926C-67.722 -27.578 -69.046 -30.51 -67.406 -32.061C-67.102 -32.35 -66.726 -32.902 -66.441 -33.32C-65.782 -34.283 -64.598 -34.771 -63.648 -35.599C-63.33 -35.875 -63.531 -36.702 -62.962 -36.61C-62.248 -36.495 -61.007 -36.625 -61.052 -35.784C-61.165 -33.664 -62.494 -31.944 - [...]
+	f = "#000000";
+	g.createPath("M-73.8 -16.4C-73.8 -16.4 -73.4 -9.6 -71 -8C-68.6 -6.4 -69.8 -7.2 -73 -8.4C-76.2 -9.6 -75 -10.4 -75 -10.4C-75 -10.4 -77.8 -10 -75.4 -8C-73 -6 -69.4 -3.6 -71 -3.6C-72.6 -3.6 -80.2 -7.6 -80.2 -10.4C-80.2 -13.2 -81.2 -17.3 -81.2 -17.3C-81.2 -17.3 -80.1 -18.1 -75.3 -18C-75.3 -18 -73.9 -17.3 -73.8 -16.4z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-74.6 2.2C-74.6 2.2 -83.12 -0.591 -101.6 2.8C-101.6 2.8 -92.569 0.722 -73.8 3C-63.5 4.25 -74.6 2.2 -74.6 2.2z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-72.502 2.129C-72.502 2.129 -80.748 -1.389 -99.453 0.392C-99.453 0.392 -90.275 -0.897 -71.774 2.995C-61.62 5.131 -72.502 2.129 -72.502 2.129z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-70.714 2.222C-70.714 2.222 -78.676 -1.899 -97.461 -1.514C-97.461 -1.514 -88.213 -2.118 -70.052 3.14C-60.086 6.025 -70.714 2.222 -70.714 2.222z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-69.444 2.445C-69.444 2.445 -76.268 -1.862 -93.142 -2.96C-93.142 -2.96 -84.803 -2.79 -68.922 3.319C-60.206 6.672 -69.444 2.445 -69.444 2.445z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M45.84 12.961C45.84 12.961 44.91 13.605 45.124 12.424C45.339 11.243 73.547 -1.927 77.161 -1.677C77.161 -1.677 46.913 11.529 45.84 12.961z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M42.446 13.6C42.446 13.6 41.57 14.315 41.691 13.121C41.812 11.927 68.899 -3.418 72.521 -3.452C72.521 -3.452 43.404 12.089 42.446 13.6z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M39.16 14.975C39.16 14.975 38.332 15.747 38.374 14.547C38.416 13.348 58.233 -2.149 68.045 -4.023C68.045 -4.023 50.015 4.104 39.16 14.975z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M36.284 16.838C36.284 16.838 35.539 17.532 35.577 16.453C35.615 15.373 53.449 1.426 62.28 -0.26C62.28 -0.26 46.054 7.054 36.284 16.838z").setFill(f).setStroke(s);
+	f = "#cccccc"; s = null;
+	g.createPath("M4.6 164.801C4.6 164.801 -10.6 162.401 6.2 160.801C6.2 160.801 24.2 158.801 28.2 153.601C28.2 153.601 41.8 144.401 44.6 144.001C47.4 143.601 63.8 140.001 64.2 137.601C64.6 135.201 70.6 132.801 72.2 133.601C73.8 134.401 73.8 143.601 71 144.401C68.2 145.201 49.4 152.401 43 153.601C36.6 154.801 25 162.401 20.2 163.601C15.4 164.801 4.6 164.801 4.6 164.801z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M77.6 127.401C77.6 127.401 74.6 129.001 73.4 131.601C73.4 131.601 67 142.201 52.8 145.401C52.8 145.401 29.8 154.401 22 156.401C22 156.401 8.6 161.401 1.2 160.601C1.2 160.601 -5.8 160.801 0.4 162.401C0.4 162.401 20.6 160.401 24 158.601C24 158.601 39.6 153.401 42.6 150.801C45.6 148.201 63.8 143.201 66 141.201C68.2 139.201 78 130.801 77.6 127.401z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M18.882 158.911C18.882 158.911 24.111 158.685 22.958 160.234C21.805 161.784 19.357 160.91 19.357 160.91L18.882 158.911z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M11.68 160.263C11.68 160.263 16.908 160.037 15.756 161.586C14.603 163.136 12.155 162.263 12.155 162.263L11.68 160.263z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M1.251 161.511C1.251 161.511 6.48 161.284 5.327 162.834C4.174 164.383 1.726 163.51 1.726 163.51L1.251 161.511z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-6.383 162.055C-6.383 162.055 -1.154 161.829 -2.307 163.378C-3.46 164.928 -5.908 164.054 -5.908 164.054L-6.383 162.055z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M35.415 151.513C35.415 151.513 42.375 151.212 40.84 153.274C39.306 155.336 36.047 154.174 36.047 154.174L35.415 151.513z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M45.73 147.088C45.73 147.088 51.689 143.787 51.155 148.849C50.885 151.405 46.362 149.749 46.362 149.749L45.73 147.088z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M54.862 144.274C54.862 144.274 62.021 140.573 60.287 146.035C59.509 148.485 55.493 146.935 55.493 146.935L54.862 144.274z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M64.376 139.449C64.376 139.449 68.735 134.548 69.801 141.21C70.207 143.748 65.008 142.11 65.008 142.11L64.376 139.449z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M26.834 155.997C26.834 155.997 32.062 155.77 30.91 157.32C29.757 158.869 27.308 157.996 27.308 157.996L26.834 155.997z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M62.434 34.603C62.434 34.603 61.708 35.268 61.707 34.197C61.707 33.127 79.191 19.863 88.034 18.479C88.034 18.479 71.935 25.208 62.434 34.603z").setFill(f).setStroke(s);
+	f = "#000000"; s = null;
+	g.createPath("M65.4 98.4C65.4 98.4 87.401 120.801 96.601 124.401C96.601 124.401 105.801 135.601 101.801 161.601C101.801 161.601 98.601 169.201 95.401 148.401C95.401 148.401 98.601 123.201 87.401 139.201C87.401 139.201 79 129.301 85.4 129.601C85.4 129.601 88.601 131.601 89.001 130.001C89.401 128.401 81.4 114.801 64.2 100.4C47 86 65.4 98.4 65.4 98.4z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M7 137.201C7 137.201 6.8 135.401 8.6 136.201C10.4 137.001 104.601 143.201 136.201 167.201C136.201 167.201 91.001 144.001 7 137.201z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M17.4 132.801C17.4 132.801 17.2 131.001 19 131.801C20.8 132.601 157.401 131.601 181.001 164.001C181.001 164.001 159.001 138.801 17.4 132.801z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M29 128.801C29 128.801 28.8 127.001 30.6 127.801C32.4 128.601 205.801 115.601 229.401 148.001C229.401 148.001 219.801 122.401 29 128.801z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M39 124.001C39 124.001 38.8 122.201 40.6 123.001C42.4 123.801 164.601 85.2 188.201 117.601C188.201 117.601 174.801 93 39 124.001z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-19 146.801C-19 146.801 -19.2 145.001 -17.4 145.801C-15.6 146.601 2.2 148.801 4.2 187.601C4.2 187.601 -3 145.601 -19 146.801z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-27.8 148.401C-27.8 148.401 -28 146.601 -26.2 147.401C-24.4 148.201 -10.2 143.601 -13 182.401C-13 182.401 -11.8 147.201 -27.8 148.401z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-35.8 148.801C-35.8 148.801 -36 147.001 -34.2 147.801C-32.4 148.601 -17 149.201 -29.4 171.601C-29.4 171.601 -19.8 147.601 -35.8 148.801z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M11.526 104.465C11.526 104.465 11.082 106.464 12.631 105.247C28.699 92.622 61.141 33.72 116.826 28.086C116.826 28.086 78.518 15.976 11.526 104.465z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M22.726 102.665C22.726 102.665 21.363 101.472 23.231 100.847C25.099 100.222 137.541 27.72 176.826 35.686C176.826 35.686 149.719 28.176 22.726 102.665z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M1.885 108.767C1.885 108.767 1.376 110.366 3.087 109.39C12.062 104.27 15.677 47.059 59.254 45.804C59.254 45.804 26.843 31.09 1.885 108.767z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-18.038 119.793C-18.038 119.793 -19.115 121.079 -17.162 120.825C-6.916 119.493 14.489 78.222 58.928 83.301C58.928 83.301 26.962 68.955 -18.038 119.793z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-6.8 113.667C-6.8 113.667 -7.611 115.136 -5.742 114.511C4.057 111.237 17.141 66.625 61.729 63.078C61.729 63.078 27.603 55.135 -6.8 113.667z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-25.078 124.912C-25.078 124.912 -25.951 125.954 -24.369 125.748C-16.07 124.669 1.268 91.24 37.264 95.354C37.264 95.354 11.371 83.734 -25.078 124.912z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-32.677 130.821C-32.677 130.821 -33.682 131.866 -32.091 131.748C-27.923 131.439 2.715 98.36 21.183 113.862C21.183 113.862 9.168 95.139 -32.677 130.821z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M36.855 98.898C36.855 98.898 35.654 97.543 37.586 97.158C39.518 96.774 160.221 39.061 198.184 51.927C198.184 51.927 172.243 41.053 36.855 98.898z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M3.4 163.201C3.4 163.201 3.2 161.401 5 162.201C6.8 163.001 22.2 163.601 9.8 186.001C9.8 186.001 19.4 162.001 3.4 163.201z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M13.8 161.601C13.8 161.601 13.6 159.801 15.4 160.601C17.2 161.401 35 163.601 37 202.401C37 202.401 29.8 160.401 13.8 161.601z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M20.6 160.001C20.6 160.001 20.4 158.201 22.2 159.001C24 159.801 48.6 163.201 72.2 195.601C72.2 195.601 36.6 158.801 20.6 160.001z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M28.225 157.972C28.225 157.972 27.788 156.214 29.678 156.768C31.568 157.322 52.002 155.423 90.099 189.599C90.099 189.599 43.924 154.656 28.225 157.972z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M38.625 153.572C38.625 153.572 38.188 151.814 40.078 152.368C41.968 152.922 76.802 157.423 128.499 192.399C128.499 192.399 54.324 150.256 38.625 153.572z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-1.8 142.001C-1.8 142.001 -2 140.201 -0.2 141.001C1.6 141.801 55 144.401 85.4 171.201C85.4 171.201 50.499 146.426 -1.8 142.001z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M-11.8 146.001C-11.8 146.001 -12 144.201 -10.2 145.001C-8.4 145.801 16.2 149.201 39.8 181.601C39.8 181.601 4.2 144.801 -11.8 146.001z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M49.503 148.962C49.503 148.962 48.938 147.241 50.864 147.655C52.79 148.068 87.86 150.004 141.981 181.098C141.981 181.098 64.317 146.704 49.503 148.962z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M57.903 146.562C57.903 146.562 57.338 144.841 59.264 145.255C61.19 145.668 96.26 147.604 150.381 178.698C150.381 178.698 73.317 143.904 57.903 146.562z").setFill(f).setStroke(s);
+	f = "#ffffff"; s = {color: "#000000", width: 0.1};
+	g.createPath("M67.503 141.562C67.503 141.562 66.938 139.841 68.864 140.255C70.79 140.668 113.86 145.004 203.582 179.298C203.582 179.298 82.917 138.904 67.503 141.562z").setFill(f).setStroke(s);
+	f = "#000000"; s = null;
+	g.createPath("M-43.8 148.401C-43.8 148.401 -38.6 148.001 -39.8 149.601C-41 151.201 -43.4 150.401 -43.4 150.401L-43.8 148.401z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-13 162.401C-13 162.401 -7.8 162.001 -9 163.601C-10.2 165.201 -12.6 164.401 -12.6 164.401L-13 162.401z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-21.8 162.001C-21.8 162.001 -16.6 161.601 -17.8 163.201C-19 164.801 -21.4 164.001 -21.4 164.001L-21.8 162.001z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-117.169 150.182C-117.169 150.182 -112.124 151.505 -113.782 152.624C-115.439 153.744 -117.446 152.202 -117.446 152.202L-117.169 150.182z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-115.169 140.582C-115.169 140.582 -110.124 141.905 -111.782 143.024C-113.439 144.144 -115.446 142.602 -115.446 142.602L-115.169 140.582z").setFill(f).setStroke(s);
+	f = "#000000";
+	g.createPath("M-122.369 136.182C-122.369 136.182 -117.324 137.505 -118.982 138.624C-120.639 139.744 -122.646 138.202 -122.646 138.202L-122.369 136.182z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-42.6 211.201C-42.6 211.201 -44.2 211.201 -48.2 213.201C-50.2 213.201 -61.4 216.801 -67 226.801C-67 226.801 -54.6 217.201 -42.6 211.201z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M45.116 303.847C45.257 304.105 45.312 304.525 45.604 304.542C46.262 304.582 47.495 304.883 47.37 304.247C46.522 299.941 45.648 295.004 41.515 293.197C40.876 292.918 39.434 293.331 39.36 294.215C39.233 295.739 39.116 297.088 39.425 298.554C39.725 299.975 41.883 299.985 42.8 298.601C43.736 300.273 44.168 302.116 45.116 303.847z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M34.038 308.581C34.786 309.994 34.659 311.853 36.074 312.416C36.814 312.71 38.664 311.735 38.246 310.661C37.444 308.6 37.056 306.361 35.667 304.55C35.467 304.288 35.707 303.755 35.547 303.427C34.953 302.207 33.808 301.472 32.4 301.801C31.285 304.004 32.433 306.133 33.955 307.842C34.091 307.994 33.925 308.37 34.038 308.581z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-5.564 303.391C-5.672 303.014 -5.71 302.551 -5.545 302.23C-5.014 301.197 -4.221 300.075 -4.558 299.053C-4.906 297.997 -6.022 298.179 -6.672 298.748C-7.807 299.742 -7.856 301.568 -8.547 302.927C-8.743 303.313 -8.692 303.886 -9.133 304.277C-9.607 304.698 -10.047 306.222 -9.951 306.793C-9.898 307.106 -10.081 317.014 -9.859 316.751C-9.24 316.018 -6.19 306.284 -6.121 305.392C-6.064 304.661 -5.332 304.196 -5.564 303.391z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-31.202 296.599C-28.568 294.1 -25.778 291.139 -26.22 287.427C-26.336 286.451 -28.111 286.978 -28.298 287.824C-29.1 291.449 -31.139 294.11 -33.707 296.502C-35.903 298.549 -37.765 304.893 -38 305.401C-34.303 300.145 -32.046 297.399 -31.202 296.599z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-44.776 290.635C-44.253 290.265 -44.555 289.774 -44.338 289.442C-43.385 287.984 -42.084 286.738 -42.066 285C-42.063 284.723 -42.441 284.414 -42.776 284.638C-43.053 284.822 -43.395 284.952 -43.503 285.082C-45.533 287.531 -46.933 290.202 -48.376 293.014C-48.559 293.371 -49.703 297.862 -49.39 297.973C-49.151 298.058 -47.431 293.877 -47.221 293.763C-45.958 293.077 -45.946 291.462 -44.776 290.635z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-28.043 310.179C-27.599 309.31 -26.023 308.108 -26.136 307.219C-26.254 306.291 -25.786 304.848 -26.698 305.536C-27.955 306.484 -31.404 307.833 -31.674 313.641C-31.7 314.212 -28.726 311.519 -28.043 310.179z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-13.6 293.001C-13.2 292.333 -12.492 292.806 -12.033 292.543C-11.385 292.171 -10.774 291.613 -10.482 290.964C-9.512 288.815 -7.743 286.995 -7.6 284.601C-9.091 283.196 -9.77 285.236 -10.4 286.201C-11.723 284.554 -12.722 286.428 -14.022 286.947C-14.092 286.975 -14.305 286.628 -14.38 286.655C-15.557 287.095 -16.237 288.176 -17.235 288.957C-17.406 289.091 -17.811 288.911 -17.958 289.047C-18.61 289.65 -19.583 289.975 -19.863 290.657C-20.973 293.364 -24.113 295.459 -26 303.001C- [...]
+	f = "#cccccc";
+	g.createPath("M46.2 347.401C46.2 347.401 53.6 327.001 49.2 315.801C49.2 315.801 60.6 337.401 56 348.601C56 348.601 55.6 338.201 51.6 333.201C51.6 333.201 47.6 346.001 46.2 347.401z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M31.4 344.801C31.4 344.801 36.8 336.001 28.8 317.601C28.8 317.601 28 338.001 21.2 349.001C21.2 349.001 35.4 328.801 31.4 344.801z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M21.4 342.801C21.4 342.801 21.2 322.801 21.6 319.801C21.6 319.801 17.8 336.401 7.6 346.001C7.6 346.001 22 334.001 21.4 342.801z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M11.8 310.801C11.8 310.801 17.8 324.401 7.8 342.801C7.8 342.801 14.2 330.601 9.4 323.601C9.4 323.601 12 320.201 11.8 310.801z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-7.4 342.401C-7.4 342.401 -8.4 326.801 -6.6 324.601C-6.6 324.601 -6.4 318.201 -6.8 317.201C-6.8 317.201 -2.8 311.001 -2.6 318.401C-2.6 318.401 -1.2 326.201 1.6 330.801C1.6 330.801 5.2 336.201 5 342.601C5 342.601 -5 312.401 -7.4 342.401z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-11 314.801C-11 314.801 -17.6 325.601 -19.4 344.601C-19.4 344.601 -20.8 338.401 -17 324.001C-17 324.001 -12.8 308.601 -11 314.801z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-32.8 334.601C-32.8 334.601 -27.8 329.201 -26.4 324.201C-26.4 324.201 -22.8 308.401 -29.2 317.001C-29.2 317.001 -29 325.001 -37.2 332.401C-37.2 332.401 -32.4 330.001 -32.8 334.601z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-38.6 329.601C-38.6 329.601 -35.2 312.201 -34.4 311.401C-34.4 311.401 -32.6 308.001 -35.4 311.201C-35.4 311.201 -44.2 330.401 -48.2 337.001C-48.2 337.001 -40.2 327.801 -38.6 329.601z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-44.4 313.001C-44.4 313.001 -32.8 290.601 -54.6 316.401C-54.6 316.401 -43.6 306.601 -44.4 313.001z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M-59.8 298.401C-59.8 298.401 -55 279.601 -52.4 279.801C-52.4 279.801 -44.2 270.801 -50.8 281.401C-50.8 281.401 -56.8 291.001 -56.2 300.801C-56.2 300.801 -56.8 291.201 -59.8 298.401z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M270.5 287C270.5 287 258.5 277 256 273.5C256 273.5 269.5 292 269.5 299C269.5 299 272 291.5 270.5 287z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M276 265C276 265 255 250 251.5 242.5C251.5 242.5 278 272 278 276.5C278 276.5 278.5 267.5 276 265z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M293 111C293 111 281 103 279.5 105C279.5 105 290 111.5 292.5 120C292.5 120 291 111 293 111z").setFill(f).setStroke(s);
+	f = "#cccccc";
+	g.createPath("M301.5 191.5L284 179.5C284 179.5 303 196.5 303.5 200.5L301.5 191.5z").setFill(f).setStroke(s);
+	s = "#000000"; f = null;
+	g.createPath("M-89.25 169L-67.25 173.75").setFill(f).setStroke(s);
+	s = "#000000";
+	g.createPath("M-39 331C-39 331 -39.5 327.5 -48.5 338").setFill(f).setStroke(s);
+	s = "#000000";
+	g.createPath("M-33.5 336C-33.5 336 -31.5 329.5 -38 334").setFill(f).setStroke(s);
+	s = "#000000";
+	g.createPath("M20.5 344.5C20.5 344.5 22 333.5 10.5 346.5").setFill(f).setStroke(s);
+	//surface.createLine({x1: 0, y1: 350, x2: 700, y2: 350}).setStroke("green");
+	//surface.createLine({y1: 0, x1: 350, y2: 700, x2: 350}).setStroke("green");
+    dojo.connect(dijit.byId("rotatingSlider"), "onChange", rotatingEvent);
+    dojo.connect(dijit.byId("scalingSlider"), "onChange", scalingEvent);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+<style type="text/css">
+	td.pad { padding: 0px 5px 0px 5px; }
+</style>
+</head>
+<body class="tundra">
+	<h1>dojox.gfx: Tiger</h1>
+	<p>This example was directly converted from SVG file.</p>
+	<table>
+		<tr><td align="center" class="pad">Rotation (<span id="rotationValue">0</span>)</td></tr>
+		<tr><td>
+			<div id="rotatingSlider" dojoType="dijit.form.HorizontalSlider" 
+					value="0" minimum="-180" maximum="180" discreteValues="72" showButtons="false" intermediateChanges="true"
+					style="width: 600px;">
+				<div dojoType="dijit.form.HorizontalRule" container="topDecoration" count="73" style="height:5px;"></div>
+				<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="9" style="height:5px;"></div>
+				<div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" labels="-180,-135,-90,-45,0,45,90,135,180" style="height:1.2em;font-size:75%;color:gray;"></div>
+			</div>
+		</td></tr>
+		<tr><td align="center" class="pad">Scaling (<span id="scaleValue">1.000</span>)</td></tr>
+		<tr><td>
+			<div id="scalingSlider" dojoType="dijit.form.HorizontalSlider" 
+				value="1" minimum="0" maximum="1"  showButtons="false"  intermediateChanges="true"
+				style="width: 600px;">
+				<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="5" style="height:5px;"></div>
+				<div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" labels="10%,18%,32%,56%,100%" style="height:1.2em;font-size:75%;color:gray;"></div>
+			</div>
+		</td></tr>
+	</table>
+	<div id="gfx_holder" style="width: 700px; height: 700px;"></div>
+</body>
+</html>
diff --git a/dojox/gfx/demos/tooltip.html b/dojox/gfx/demos/tooltip.html
new file mode 100644
index 0000000..0ccfa11
--- /dev/null
+++ b/dojox/gfx/demos/tooltip.html
@@ -0,0 +1,234 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
+<head>
+	<title>A Sample ToolTip using dijit and dojox.gfx</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		.tooltipBody {
+			color:#fff;
+		}
+	</style>
+	<script type="text/javascript" djConfig="parseOnLoad:true, isDebug:true" src="../../../dojo/dojo.js"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.form.Button");
+	
+		dojo.require("dojox.gfx");
+		dojo.require("dojox.gfx.move");
+		dojo.require("dijit._Widget"); dojo.require("dijit._Templated");
+		
+		dojo.declare("demo.Tooltip",[dijit._Widget,dijit._Templated],{
+			
+			// attachId: String|DomNode?
+			// 		the Id or domNode to attach this tooltip to
+			attachId:"",
+
+			// attachHover: Boolean
+			// 		disable hover behavior for the target
+			attachHover:true,
+
+			// attachParent: Boolean
+			//		automatically attach to our parentnode rather than byId or query
+			attachParent:false,
+
+			// attachQuery: String?
+			//		an optional selector query to attach this tooltip to
+			attachQuery:"",
+
+			// attachScope: String|DomNode?
+			//		and optional scope to run the query against, passed as the
+			//		second arg to dojo.query()
+			queryScope:"",
+
+			// hideDelay: Int
+			// 		time in my to delay automatically closing the node
+			hideDelay: 123, // ms
+
+			// persists: Boolean
+			//		if true, the node will stay visible until explicitly closed
+			//		via _hide() or click on closeIcon
+			persists:false,
+			
+			templateString:
+				'<div class="foo">'
+					+'<div style="position:relative;">'
+						+'<div dojoAttachPoint="surfaceNode"></div>'
+						+'<div class="tooltipBody" dojoAttachPoint="containerNode"></div>'
+					+'</div>'
+				+'</div>',
+			
+			postCreate:function(){
+				// call _Widget postCreate first
+				this.inherited(arguments);
+				// gfx version of "_Templated" idea:
+				this._initSurface();
+				
+				if(this.attachParent){
+					// over-ride and reuse attachId as domNode from now on
+					this.attachId = this.domNode.parentNode;
+				}
+				if(this.attachId){
+					// domNode again. setup connections
+					this.attachId = dojo.byId(this.attachId);
+					if(this.attachHover){
+						this.connect(this.attachId,"onmouseenter","_show");
+					}
+					if(!this.persists){
+						this.connect(this.attachId,"onmouseleave","_initHide");
+					}
+				}else if(this.attachQuery){
+					// setup connections via dojo.query for multi-tooltips
+					var nl = dojo.query(this.attachQuery,this.queryScope);
+					if(this.attachHover){ nl.connect("onmouseenter",this,"_show") }
+					if(!this.persists){ nl.connect("onmouseleave",this,"_initHide") }
+				}
+				// place the tooltip			
+				dojo.body().appendChild(this.domNode);
+				dojo.style(this.domNode,{
+					position:"absolute"
+				});
+				// could do this in css:
+				dojo.style(this.containerNode,{
+					position:"absolute",
+					top:"15px",
+					left:"12px",
+					height:"83px",
+					width:"190px"
+				});
+				// setup our animations
+				this._hideAnim = dojo.fadeOut({ node:this.domNode, duration:150 });
+				this._showAnim = dojo.fadeIn({ node:this.domNode, duration:75 });
+				this.connect(this._hideAnim,"onEnd","_postHide");
+				if(!this.persists){
+					this.connect(this.domNode,"onmouseleave","_initHide");
+				}
+				// hide quickly
+				this._postHide();
+			},
+			
+			_initHide: function(e){
+				// summary: start the timer for the hideDelay
+				if(!this.persists && this.hideDelay){
+					this._delay = setTimeout(dojo.hitch(this,"_hide",e||null),this.hideDelay);
+				}
+			},
+			
+			_clearDelay: function(){
+				// summary: clear our hide delay timeout
+				if(this._delay){ clearTimeout(this._delay); }
+			},
+			
+			_show: function(e){
+				// summary: show the widget
+				this._clearDelay();
+				var pos = dojo.coords(e.target || this.attachId,true)
+				// we need to more accurately position the domNode:
+				dojo.style(this.domNode,{
+					top: pos.y - (pos.h / 2) - 50,
+					left: pos.x + pos.w - 25,
+					display:"block"
+				});
+				dojo.fadeIn({ node: this.domNode, duration:75 }).play();
+			},
+			
+			_hide: function(e){
+				// summary: hide the tooltip
+				this._hideAnim.play();
+			},
+			
+			_postHide: function(){
+				// summary: after hide animation cleanup
+				dojo.style(this.domNode,"display","none");
+			},
+			
+			_initSurface:function(){
+				// made generally from an SVG file:
+				this.surface = dojox.gfx.createSurface(this.surfaceNode,220,120);
+				this.tooltip = this.surface.createGroup();
+				this.tooltip.createPath("M213,101.072c0,6.675-5.411,12.086-12.086,12.086H13.586 c-6.675,0-12.086-5.411-12.086-12.086V21.004c0-6.675,5.411-12.086,12.086-12.086h187.328c6.675,0,12.086,5.411,12.086,12.086 V101.072z")
+					.setFill("rgba(0,0,0,0.25)");
+				
+				this.tooltip.createPath("M211.5,97.418c0,6.627-5.373,12-12,12 h-186c-6.627,0-12-5.373-12-12v-79.5c0-6.627,5.373-12,12-12h186c6.627,0,12,5.373,12,12V97.418z")
+					.setStroke({ width:2, color:"#FFF" })
+					.setFill("rgba(0,0,0,0.5)")
+					.connect("onmouseover",dojo.hitch(this,"_clearDelay"));
+				
+				if(this.persists){
+					// make the close icon
+					this._toolButton = this.surface.createGroup();
+					this._toolButton.createEllipse({ cx:207.25, cy:12.32, rx: 7.866, ry: 7.099 })
+						.setFill("#ededed");
+					this._toolButton.createCircle({ cx:207.25, cy: 9.25, r:8.25 })
+						.setStroke({ width:2, color:"#FFF" })
+						.setFill("#000")
+					;
+					this._toolButton.connect("onclick",dojo.hitch(this,"_hide"));	
+					// the X	
+					this._toolButton.createLine({ x1:203.618, y1:5.04, x2: 210.89, y2:12.979 })
+						.setStroke({ width:2, color:"#d6d6d6" });
+					this._toolButton.createLine({ x1:203.539, y1:12.979, x2: 210.89, y2:5.04 })
+						.setStroke({ width:2, color:"#d6d6d6" });
+				}
+			}	
+		});
+	</script>
+	
+</head>
+<body class="tundra">
+
+	<h1>dojox.gfx: A Sample tooltip</h1>
+
+	<ul style="width:150px; border:2px solid #ededed; cursor:pointer">
+		
+	
+		<!-- you can put any content you want in there -->
+		<li id="warn2">
+			Tooltip + Button
+			<div attachId="warn2" id="warn2tt" dojoType="demo.Tooltip"><p style="margin-top:0">Canvas renderer doesn't implement event handling.
+				<button dojoType="dijit.form.Button">
+					Button
+					<script type="dojo/method" event="onClick">
+						alert(" woo hoo! ");
+						dijit.byId("warn2tt")._hide();
+					</script>
+				</button>
+			</p></div>
+		</li>
+
+		<!-- a simple tooltip -->
+		<li id="warn1">
+			Hover trigger / persists
+			<div persists="true" attachId="warn1" dojoType="demo.Tooltip">Canvas renderer doesn't implement event handling.</div>
+		</li>
+
+		<!-- these get the same tooltip from the attachQuery=".multitip" below -->
+		<li class="multitip">MultiTip trigger 1</li>
+		<li>I do nothing</li>
+		<li class="multitip">Trigger two</li>
+
+		<li><a href="#" onclick="dijit.byId('nohover')._show(arguments[0])">show this way
+			<label dojoType="demo.Tooltip" attachParent="true" attachHover="false" id="nohover">some text</label>
+			</a>	
+		</li>
+
+		<!-- attachParent makes the tooltip look for domNode.parentNode before moving to body() -->
+		<li>
+			Parent Attached Tooltip
+			<div attachParent="true" persists="true" dojoType="demo.Tooltip">
+				<form id="fooForm">
+					<p style="margin-top:0;">
+					Name:<br> <input type="text" name="username" style="border:1px solid #ededed" /><br>
+					Pass:<br> <input type="password" name="password" style="border:1px solid #ededed" />
+					</p>
+				</form>
+			</div>
+		</li>
+
+	</ul>
+
+	<!-- attach a single tooltip message to a number of nodes at once -->
+	<div attachQuery=".multitip" dojoType="demo.Tooltip">Canvas renderer doesn't implement event handling. (shared tooltip)</div>
+
+</body>
+</html>
diff --git a/dojox/gfx/fx.js b/dojox/gfx/fx.js
index 46a44d9..c0cefff 100644
--- a/dojox/gfx/fx.js
+++ b/dojox/gfx/fx.js
@@ -1,227 +1,277 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.fx"]){
-dojo._hasResource["dojox.gfx.fx"]=true;
 dojo.provide("dojox.gfx.fx");
+
 dojo.require("dojox.gfx.matrix");
+
 (function(){
-var d=dojo,g=dojox.gfx,m=g.matrix;
-var _1=function(_2,_3){
-this.start=_2,this.end=_3;
-};
-d.extend(_1,{getValue:function(r){
-return (this.end-this.start)*r+this.start;
-}});
-var _4=function(_5,_6,_7){
-this.start=_5,this.end=_6;
-this.units=_7;
-};
-d.extend(_4,{getValue:function(r){
-return (this.end-this.start)*r+this.start+this.units;
-}});
-var _8=function(_9,_a){
-this.start=_9,this.end=_a;
-this.temp=new dojo.Color();
-};
-d.extend(_8,{getValue:function(r){
-return d.blendColors(this.start,this.end,r,this.temp);
-}});
-var _b=function(_c){
-this.values=_c;
-this.length=_c.length;
-};
-d.extend(_b,{getValue:function(r){
-return this.values[Math.min(Math.floor(r*this.length),this.length-1)];
-}});
-var _d=function(_e,_f){
-this.values=_e;
-this.def=_f?_f:{};
-};
-d.extend(_d,{getValue:function(r){
-var ret=dojo.clone(this.def);
-for(var i in this.values){
-ret[i]=this.values[i].getValue(r);
-}
-return ret;
-}});
-var _10=function(_11,_12){
-this.stack=_11;
-this.original=_12;
-};
-d.extend(_10,{getValue:function(r){
-var ret=[];
-dojo.forEach(this.stack,function(t){
-if(t instanceof m.Matrix2D){
-ret.push(t);
-return;
-}
-if(t.name=="original"&&this.original){
-ret.push(this.original);
-return;
-}
-if(!(t.name in m)){
-return;
-}
-var f=m[t.name];
-if(typeof f!="function"){
-ret.push(f);
-return;
-}
-var val=dojo.map(t.start,function(v,i){
-return (t.end[i]-v)*r+v;
-}),_13=f.apply(m,val);
-if(_13 instanceof m.Matrix2D){
-ret.push(_13);
-}
-},this);
-return ret;
-}});
-var _14=new d.Color(0,0,0,0);
-var _15=function(_16,obj,_17,def){
-if(_16.values){
-return new _b(_16.values);
-}
-var _18,_19,end;
-if(_16.start){
-_19=g.normalizeColor(_16.start);
-}else{
-_19=_18=obj?(_17?obj[_17]:obj):def;
-}
-if(_16.end){
-end=g.normalizeColor(_16.end);
-}else{
-if(!_18){
-_18=obj?(_17?obj[_17]:obj):def;
-}
-end=_18;
-}
-return new _8(_19,end);
-};
-var _1a=function(_1b,obj,_1c,def){
-if(_1b.values){
-return new _b(_1b.values);
-}
-var _1d,_1e,end;
-if(_1b.start){
-_1e=_1b.start;
-}else{
-_1e=_1d=obj?obj[_1c]:def;
-}
-if(_1b.end){
-end=_1b.end;
-}else{
-if(typeof _1d!="number"){
-_1d=obj?obj[_1c]:def;
-}
-end=_1d;
-}
-return new _1(_1e,end);
-};
-g.fx.animateStroke=function(_1f){
-if(!_1f.easing){
-_1f.easing=d._defaultEasing;
-}
-var _20=new d.Animation(_1f),_21=_1f.shape,_22;
-d.connect(_20,"beforeBegin",_20,function(){
-_22=_21.getStroke();
-var _23=_1f.color,_24={},_25,_26,end;
-if(_23){
-_24.color=_15(_23,_22,"color",_14);
-}
-_23=_1f.style;
-if(_23&&_23.values){
-_24.style=new _b(_23.values);
-}
-_23=_1f.width;
-if(_23){
-_24.width=_1a(_23,_22,"width",1);
-}
-_23=_1f.cap;
-if(_23&&_23.values){
-_24.cap=new _b(_23.values);
-}
-_23=_1f.join;
-if(_23){
-if(_23.values){
-_24.join=new _b(_23.values);
-}else{
-_26=_23.start?_23.start:(_22&&_22.join||0);
-end=_23.end?_23.end:(_22&&_22.join||0);
-if(typeof _26=="number"&&typeof end=="number"){
-_24.join=new _1(_26,end);
-}
-}
-}
-this.curve=new _d(_24,_22);
-});
-d.connect(_20,"onAnimate",_21,"setStroke");
-return _20;
-};
-g.fx.animateFill=function(_27){
-if(!_27.easing){
-_27.easing=d._defaultEasing;
-}
-var _28=new d.Animation(_27),_29=_27.shape,_2a;
-d.connect(_28,"beforeBegin",_28,function(){
-_2a=_29.getFill();
-var _2b=_27.color,_2c={};
-if(_2b){
-this.curve=_15(_2b,_2a,"",_14);
-}
-});
-d.connect(_28,"onAnimate",_29,"setFill");
-return _28;
-};
-g.fx.animateFont=function(_2d){
-if(!_2d.easing){
-_2d.easing=d._defaultEasing;
-}
-var _2e=new d.Animation(_2d),_2f=_2d.shape,_30;
-d.connect(_2e,"beforeBegin",_2e,function(){
-_30=_2f.getFont();
-var _31=_2d.style,_32={},_33,_34,end;
-if(_31&&_31.values){
-_32.style=new _b(_31.values);
-}
-_31=_2d.variant;
-if(_31&&_31.values){
-_32.variant=new _b(_31.values);
-}
-_31=_2d.weight;
-if(_31&&_31.values){
-_32.weight=new _b(_31.values);
-}
-_31=_2d.family;
-if(_31&&_31.values){
-_32.family=new _b(_31.values);
-}
-_31=_2d.size;
-if(_31&&_31.units){
-_34=parseFloat(_31.start?_31.start:(_2f.font&&_2f.font.size||"0"));
-end=parseFloat(_31.end?_31.end:(_2f.font&&_2f.font.size||"0"));
-_32.size=new _4(_34,end,_31.units);
-}
-this.curve=new _d(_32,_30);
-});
-d.connect(_2e,"onAnimate",_2f,"setFont");
-return _2e;
-};
-g.fx.animateTransform=function(_35){
-if(!_35.easing){
-_35.easing=d._defaultEasing;
-}
-var _36=new d.Animation(_35),_37=_35.shape,_38;
-d.connect(_36,"beforeBegin",_36,function(){
-_38=_37.getTransform();
-this.curve=new _10(_35.transform,_38);
-});
-d.connect(_36,"onAnimate",_37,"setTransform");
-return _36;
-};
+	var d = dojo, g = dojox.gfx, m = g.matrix;
+
+	// Generic interpolators. Should they be moved to dojox.fx?
+
+	var InterpolNumber = function(start, end){
+		this.start = start, this.end = end;
+	};
+	d.extend(InterpolNumber, {
+		getValue: function(r){
+			return (this.end - this.start) * r + this.start;
+		}
+	});
+
+	var InterpolUnit = function(start, end, units){
+		this.start = start, this.end = end;
+		this.units = units;
+	};
+	d.extend(InterpolUnit, {
+		getValue: function(r){
+			return (this.end - this.start) * r + this.start + this.units;
+		}
+	});
+
+	var InterpolColor = function(start, end){
+		this.start = start, this.end = end;
+		this.temp = new dojo.Color();
+	};
+	d.extend(InterpolColor, {
+		getValue: function(r){
+			return d.blendColors(this.start, this.end, r, this.temp);
+		}
+	});
+
+	var InterpolValues = function(values){
+		this.values = values;
+		this.length = values.length;
+	};
+	d.extend(InterpolValues, {
+		getValue: function(r){
+			return this.values[Math.min(Math.floor(r * this.length), this.length - 1)];
+		}
+	});
+
+	var InterpolObject = function(values, def){
+		this.values = values;
+		this.def = def ? def : {};
+	};
+	d.extend(InterpolObject, {
+		getValue: function(r){
+			var ret = dojo.clone(this.def);
+			for(var i in this.values){
+				ret[i] = this.values[i].getValue(r);
+			}
+			return ret;
+		}
+	});
+
+	var InterpolTransform = function(stack, original){
+		this.stack = stack;
+		this.original = original;
+	};
+	d.extend(InterpolTransform, {
+		getValue: function(r){
+			var ret = [];
+			dojo.forEach(this.stack, function(t){
+				if(t instanceof m.Matrix2D){
+					ret.push(t);
+					return;
+				}
+				if(t.name == "original" && this.original){
+					ret.push(this.original);
+					return;
+				}
+				if(!(t.name in m)){ return; }
+				var f = m[t.name];
+				if(typeof f != "function"){
+					// constant
+					ret.push(f);
+					return;
+				}
+				var val = dojo.map(t.start, function(v, i){
+								return (t.end[i] - v) * r + v;
+							}),
+					matrix = f.apply(m, val);
+				if(matrix instanceof m.Matrix2D){
+					ret.push(matrix);
+				}
+			}, this);
+			return ret;
+		}
+	});
+
+	var transparent = new d.Color(0, 0, 0, 0);
+
+	var getColorInterpol = function(prop, obj, name, def){
+		if(prop.values){
+			return new InterpolValues(prop.values);
+		}
+		var value, start, end;
+		if(prop.start){
+			start = g.normalizeColor(prop.start);
+		}else{
+			start = value = obj ? (name ? obj[name] : obj) : def;
+		}
+		if(prop.end){
+			end = g.normalizeColor(prop.end);
+		}else{
+			if(!value){
+				value = obj ? (name ? obj[name] : obj) : def;
+			}
+			end = value;
+		}
+		return new InterpolColor(start, end);
+	};
+
+	var getNumberInterpol = function(prop, obj, name, def){
+		if(prop.values){
+			return new InterpolValues(prop.values);
+		}
+		var value, start, end;
+		if(prop.start){
+			start = prop.start;
+		}else{
+			start = value = obj ? obj[name] : def;
+		}
+		if(prop.end){
+			end = prop.end;
+		}else{
+			if(typeof value != "number"){
+				value = obj ? obj[name] : def;
+			}
+			end = value;
+		}
+		return new InterpolNumber(start, end);
+	};
+
+	g.fx.animateStroke = function(/*Object*/ args){
+		// summary:
+		//	Returns an animation which will change stroke properties over time
+		// example:
+		//	|	dojox.gfx.fx.animateStroke{{
+		//	|		shape: shape,
+		//	|		duration: 500,
+		//	|		color: {start: "red", end: "green"},
+		//	|		width: {end: 15},
+		//	|		join:  {values: ["miter", "bevel", "round"]}
+		//	|	}).play();
+		if(!args.easing){ args.easing = d._defaultEasing; }
+		var anim = new d.Animation(args), shape = args.shape, stroke;
+		d.connect(anim, "beforeBegin", anim, function(){
+			stroke = shape.getStroke();
+			var prop = args.color, values = {}, value, start, end;
+			if(prop){
+				values.color = getColorInterpol(prop, stroke, "color", transparent);
+			}
+			prop = args.style;
+			if(prop && prop.values){
+				values.style = new InterpolValues(prop.values);
+			}
+			prop = args.width;
+			if(prop){
+				values.width = getNumberInterpol(prop, stroke, "width", 1);
+			}
+			prop = args.cap;
+			if(prop && prop.values){
+				values.cap = new InterpolValues(prop.values);
+			}
+			prop = args.join;
+			if(prop){
+				if(prop.values){
+					values.join = new InterpolValues(prop.values);
+				}else{
+					start = prop.start ? prop.start : (stroke && stroke.join || 0);
+					end = prop.end ? prop.end : (stroke && stroke.join || 0);
+					if(typeof start == "number" && typeof end == "number"){
+						values.join = new InterpolNumber(start, end);
+					}
+				}
+			}
+			this.curve = new InterpolObject(values, stroke);
+		});
+		d.connect(anim, "onAnimate", shape, "setStroke");
+		return anim; // dojo.Animation
+	};
+
+	g.fx.animateFill = function(/*Object*/ args){
+		// summary:
+		//	Returns an animation which will change fill color over time.
+		//	Only solid fill color is supported at the moment
+		// example:
+		//	|	dojox.gfx.fx.animateFill{{
+		//	|		shape: shape,
+		//	|		duration: 500,
+		//	|		color: {start: "red", end: "green"}
+		//	|	}).play();
+		if(!args.easing){ args.easing = d._defaultEasing; }
+		var anim = new d.Animation(args), shape = args.shape, fill;
+		d.connect(anim, "beforeBegin", anim, function(){
+			fill = shape.getFill();
+			var prop = args.color, values = {};
+			if(prop){
+				this.curve = getColorInterpol(prop, fill, "", transparent);
+			}
+		});
+		d.connect(anim, "onAnimate", shape, "setFill");
+		return anim; // dojo.Animation
+	};
+
+	g.fx.animateFont = function(/*Object*/ args){
+		// summary:
+		//	Returns an animation which will change font properties over time
+		// example:
+		//	|	dojox.gfx.fx.animateFont{{
+		//	|		shape: shape,
+		//	|		duration: 500,
+		//	|		variant: {values: ["normal", "small-caps"]},
+		//	|		size:  {end: 10, units: "pt"}
+		//	|	}).play();
+		if(!args.easing){ args.easing = d._defaultEasing; }
+		var anim = new d.Animation(args), shape = args.shape, font;
+		d.connect(anim, "beforeBegin", anim, function(){
+			font = shape.getFont();
+			var prop = args.style, values = {}, value, start, end;
+			if(prop && prop.values){
+				values.style = new InterpolValues(prop.values);
+			}
+			prop = args.variant;
+			if(prop && prop.values){
+				values.variant = new InterpolValues(prop.values);
+			}
+			prop = args.weight;
+			if(prop && prop.values){
+				values.weight = new InterpolValues(prop.values);
+			}
+			prop = args.family;
+			if(prop && prop.values){
+				values.family = new InterpolValues(prop.values);
+			}
+			prop = args.size;
+			if(prop && prop.units){
+				start = parseFloat(prop.start ? prop.start : (shape.font && shape.font.size || "0"));
+				end = parseFloat(prop.end ? prop.end : (shape.font && shape.font.size || "0"));
+				values.size = new InterpolUnit(start, end, prop.units);
+			}
+			this.curve = new InterpolObject(values, font);
+		});
+		d.connect(anim, "onAnimate", shape, "setFont");
+		return anim; // dojo.Animation
+	};
+
+	g.fx.animateTransform = function(/*Object*/ args){
+		// summary:
+		//	Returns an animation which will change transformation over time
+		// example:
+		//	|	dojox.gfx.fx.animateTransform{{
+		//	|		shape: shape,
+		//	|		duration: 500,
+		//	|		transform: [
+		//	|			{name: "translate", start: [0, 0], end: [200, 200]},
+		//	|			{name: "original"}
+		//	|		]
+		//	|	}).play();
+		if(!args.easing){ args.easing = d._defaultEasing; }
+		var anim = new d.Animation(args), shape = args.shape, original;
+		d.connect(anim, "beforeBegin", anim, function(){
+			original = shape.getTransform();
+			this.curve = new InterpolTransform(args.transform, original);
+		});
+		d.connect(anim, "onAnimate", shape, "setTransform");
+		return anim; // dojo.Animation
+	};
 })();
-}
diff --git a/dojox/gfx/gradient.js b/dojox/gfx/gradient.js
new file mode 100644
index 0000000..ee5847e
--- /dev/null
+++ b/dojox/gfx/gradient.js
@@ -0,0 +1,160 @@
+dojo.provide("dojox.gfx.gradient");
+
+dojo.require("dojox.gfx.matrix");
+
+// Various utilities to deal with a linear gradient (mostly VML-specific)
+
+(function(){
+	var d = dojo, m = dojox.gfx.matrix, C = d.Color;
+	
+	dojox.gfx.gradient.rescale = function(stops, from, to){
+		// summary:
+		//		recalculates a gradient from 0-1 window to
+		//		"from"-"to" window blending and replicating colors,
+		//		if necessary
+		// stops: Array:
+		//		input gradient as a list of colors with offsets
+		//		(see dojox.gfx.defaultLinearGradient and dojox.gfx.defaultRadialGradient)
+		// from: Number:
+		//		the beginning of the window, should be less than "to"
+		// to: Number:
+		//		the end of the window, should be more than "from"
+
+		var len = stops.length, reverseFlag = (to < from), newStops;
+
+		// do we need to reverse the color table?
+		if(reverseFlag){
+			var tmp = from;
+			from = to;
+			to = tmp;
+		}
+		
+		// various edge cases
+		if(!len){
+			// no colors
+			return [];
+		}
+		if(to <= stops[0].offset){
+			// all colors are before the color table
+			newStops = [
+				{offset: 0, color: stops[0].color},
+				{offset: 1, color: stops[0].color}
+			];
+		}else if(from >= stops[len - 1].offset){
+			// all colors are after the color table
+			newStops = [
+				{offset: 0, color: stops[len - 1].color},
+				{offset: 1, color: stops[len - 1].color}
+			];
+		}else{
+			// main scanning algorithm
+			var span = to - from, stop, prev, i;
+			newStops = [];
+			if(from < 0){
+				newStops.push({offset: 0, color: new C(stops[0].color)});
+			}
+			for(i = 0; i < len; ++i){
+				stop = stops[i];
+				if(stop.offset >= from){
+					break;
+				}
+				// skip this color
+			}
+			if(i){
+				prev = stops[i - 1];
+				newStops.push({
+					offset: 0,
+					color: d.blendColors(new C(prev.color), new C(stop.color), (from - prev.offset) / (stop.offset - prev.offset))
+				});
+			}else{
+				newStops.push({offset: 0, color: new C(stop.color)});
+			}
+			for(; i < len; ++i){
+				stop = stops[i];
+				if(stop.offset >= to){
+					break;
+				}
+				newStops.push({offset: (stop.offset - from) / span, color: new C(stop.color)});
+			}
+			if(i < len){
+				prev = stops[i - 1];
+				newStops.push({
+					offset: 1,
+					color: d.blendColors(new C(prev.color), new C(stop.color), (to - prev.offset) / (stop.offset - prev.offset))
+				});
+			}else{
+				newStops.push({offset: 1, color: new C(stops[len - 1].color)});
+			}
+		}
+		
+		// reverse the color table, if needed
+		if(reverseFlag){
+			newStops.reverse();
+			for(i = 0, len = newStops.length; i < len; ++i){
+				stop = newStops[i];
+				stop.offset = 1 - stop.offset;
+			}
+		}
+		
+		return newStops;
+	};
+	
+	function getPoint(x, y, matrix, project, shiftAndRotate, scale){
+		var r = m.multiplyPoint(matrix, x, y),
+			p = m.multiplyPoint(project, r);
+		return {r: r, p: p, o: m.multiplyPoint(shiftAndRotate, p).x / scale};
+	}
+	
+	function sortPoints(a, b){
+		return a.o - b.o;
+	}
+	
+	dojox.gfx.gradient.project = function(matrix, grad, tl, rb, ttl, trb){
+		// summary:
+		//		return a new gradient using the "VML algorithm" and suitable for VML
+		// matrix: dojox.gfx.Matrix2D|Null:
+		//		matrix to apply to a shape and its gradient
+		// grad: Object:
+		//		a linear gradient object to be transformed
+		// tl: dojox.gfx.Point:
+		//		top-left corner of shape's bounding box
+		// rb: dojox.gfx.Point:
+		//		right-bottom corner of shape's bounding box
+		// ttl: dojox.gfx.Point:
+		//		top-left corner of shape's transformed bounding box
+		// trb: dojox.gfx.Point:
+		//		right-bottom corner of shape's transformed bounding box
+		
+		matrix = matrix || m.identity;
+
+		var f1 = m.multiplyPoint(matrix, grad.x1, grad.y1),
+			f2 = m.multiplyPoint(matrix, grad.x2, grad.y2),
+			angle = Math.atan2(f2.y - f1.y, f2.x - f1.x),
+			project = m.project(f2.x - f1.x, f2.y - f1.y),
+			pf1 = m.multiplyPoint(project, f1),
+			pf2 = m.multiplyPoint(project, f2),
+			shiftAndRotate = new m.Matrix2D([m.rotate(-angle), {dx: -pf1.x, dy: -pf1.y}]),
+			scale = m.multiplyPoint(shiftAndRotate, pf2).x,
+			//comboMatrix = new m.Matrix2D([shiftAndRotate, project, matrix]),
+			// bbox-specific calculations
+			points = [
+					getPoint(tl.x, tl.y, matrix, project, shiftAndRotate, scale),
+					getPoint(rb.x, rb.y, matrix, project, shiftAndRotate, scale),
+					getPoint(tl.x, rb.y, matrix, project, shiftAndRotate, scale),
+					getPoint(rb.x, tl.y, matrix, project, shiftAndRotate, scale)
+				].sort(sortPoints),
+			from = points[0].o,
+			to   = points[3].o,
+			stops = dojox.gfx.gradient.rescale(grad.colors, from, to),
+			//angle2 = Math.atan2(Math.abs(points[3].r.y - points[0].r.y) * (f2.y - f1.y), Math.abs(points[3].r.x - points[0].r.x) * (f2.x - f1.x));
+			angle2 = Math.atan2(points[3].r.y - points[0].r.y, points[3].r.x - points[0].r.x);
+
+		return {
+			type: "linear",
+			x1: points[0].p.x, y1: points[0].p.y, x2: points[3].p.x, y2: points[3].p.y,
+			colors: stops,
+			// additional helpers (for VML)
+			angle: angle
+		};
+	};
+})();
diff --git a/dojox/gfx/gradutils.js b/dojox/gfx/gradutils.js
new file mode 100644
index 0000000..2ec00e1
--- /dev/null
+++ b/dojox/gfx/gradutils.js
@@ -0,0 +1,91 @@
+dojo.provide("dojox.gfx.gradutils");
+
+dojo.require("dojox.gfx.matrix");
+
+// Various generic utilities to deal with a linear gradient
+
+(function(){
+	var d = dojo, m = dojox.gfx.matrix, C = d.Color;
+	
+	function findColor(o, c){
+		if(o <= 0){
+			return c[0].color;
+		}
+		var len = c.length;
+		if(o >= 1){
+			return c[len - 1].color;
+		}
+		//TODO: use binary search
+		for(var i = 0; i < len; ++i){
+			var stop = c[i];
+			if(stop.offset >= o){
+				if(i){
+					var prev = c[i - 1];
+					return d.blendColors(new C(prev.color), new C(stop.color),
+						(o - prev.offset) / (stop.offset - prev.offset));
+				}
+				return stop.color;
+			}
+		}
+		return c[len - 1].color;
+	}
+
+	dojox.gfx.gradutils.getColor = function(fill, pt){
+		// summary:
+		//		sample a color from a gradient using a point
+		// fill: Object:
+		//		fill object
+		// pt: dojox.gfx.Point:
+		//		point where to sample a color
+		var o;
+		if(fill){
+			switch(fill.type){
+				case "linear":
+					var angle = Math.atan2(fill.y2 - fill.y1, fill.x2 - fill.x1),
+						rotation = m.rotate(-angle),
+						projection = m.project(fill.x2 - fill.x1, fill.y2 - fill.y1),
+						p = m.multiplyPoint(projection, pt),
+						pf1 = m.multiplyPoint(projection, fill.x1, fill.y1),
+						pf2 = m.multiplyPoint(projection, fill.x2, fill.y2),
+						scale = m.multiplyPoint(rotation, pf2.x - pf1.x, pf2.y - pf1.y).x,
+						o = m.multiplyPoint(rotation, p.x - pf1.x, p.y - pf1.y).x / scale;
+					break;
+				case "radial":
+					var dx = pt.x - fill.cx, dy = pt.y - fill.cy,
+						o = Math.sqrt(dx * dx + dy * dy) / fill.r;
+					break;
+			}
+			return findColor(o, fill.colors);	// dojo.Color
+		}
+		// simple color
+		return new C(fill || [0, 0, 0, 0]);	// dojo.Color
+	};
+
+	dojox.gfx.gradutils.reverse = function(fill){
+		// summary:
+		//		reverses a gradient
+		// fill: Object:
+		//		fill object
+		if(fill){
+			switch(fill.type){
+				case "linear":
+				case "radial":
+					fill = dojo.delegate(fill);
+					if(fill.colors){
+						var c = fill.colors, l = c.length, i = 0, stop,
+							n = fill.colors = new Array(c.length);
+						for(; i < l; ++i){
+							stop = c[i];
+							n[i] = {
+								offset: 1 - stop.offset,
+								color:  stop.color
+							};
+						}
+						n.sort(function(a, b){ return a.offset - b.offset; });
+					}
+					break;
+			}
+		}
+		return fill;	// Object
+	};
+})();
diff --git a/dojox/gfx/matrix.js b/dojox/gfx/matrix.js
index 7b9a02a..45b0855 100644
--- a/dojox/gfx/matrix.js
+++ b/dojox/gfx/matrix.js
@@ -1,168 +1,443 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.matrix"]){
-dojo._hasResource["dojox.gfx.matrix"]=true;
 dojo.provide("dojox.gfx.matrix");
+
 (function(){
-var m=dojox.gfx.matrix;
-var _1={};
-m._degToRad=function(_2){
-return _1[_2]||(_1[_2]=(Math.PI*_2/180));
-};
-m._radToDeg=function(_3){
-return _3/Math.PI*180;
-};
-m.Matrix2D=function(_4){
-if(_4){
-if(typeof _4=="number"){
-this.xx=this.yy=_4;
-}else{
-if(_4 instanceof Array){
-if(_4.length>0){
-var _5=m.normalize(_4[0]);
-for(var i=1;i<_4.length;++i){
-var l=_5,r=dojox.gfx.matrix.normalize(_4[i]);
-_5=new m.Matrix2D();
-_5.xx=l.xx*r.xx+l.xy*r.yx;
-_5.xy=l.xx*r.xy+l.xy*r.yy;
-_5.yx=l.yx*r.xx+l.yy*r.yx;
-_5.yy=l.yx*r.xy+l.yy*r.yy;
-_5.dx=l.xx*r.dx+l.xy*r.dy+l.dx;
-_5.dy=l.yx*r.dx+l.yy*r.dy+l.dy;
-}
-dojo.mixin(this,_5);
-}
-}else{
-dojo.mixin(this,_4);
-}
-}
-}
-};
-dojo.extend(m.Matrix2D,{xx:1,xy:0,yx:0,yy:1,dx:0,dy:0});
-dojo.mixin(m,{identity:new m.Matrix2D(),flipX:new m.Matrix2D({xx:-1}),flipY:new m.Matrix2D({yy:-1}),flipXY:new m.Matrix2D({xx:-1,yy:-1}),translate:function(a,b){
-if(arguments.length>1){
-return new m.Matrix2D({dx:a,dy:b});
-}
-return new m.Matrix2D({dx:a.x,dy:a.y});
-},scale:function(a,b){
-if(arguments.length>1){
-return new m.Matrix2D({xx:a,yy:b});
-}
-if(typeof a=="number"){
-return new m.Matrix2D({xx:a,yy:a});
-}
-return new m.Matrix2D({xx:a.x,yy:a.y});
-},rotate:function(_6){
-var c=Math.cos(_6);
-var s=Math.sin(_6);
-return new m.Matrix2D({xx:c,xy:-s,yx:s,yy:c});
-},rotateg:function(_7){
-return m.rotate(m._degToRad(_7));
-},skewX:function(_8){
-return new m.Matrix2D({xy:Math.tan(_8)});
-},skewXg:function(_9){
-return m.skewX(m._degToRad(_9));
-},skewY:function(_a){
-return new m.Matrix2D({yx:Math.tan(_a)});
-},skewYg:function(_b){
-return m.skewY(m._degToRad(_b));
-},reflect:function(a,b){
-if(arguments.length==1){
-b=a.y;
-a=a.x;
-}
-var a2=a*a,b2=b*b,n2=a2+b2,xy=2*a*b/n2;
-return new m.Matrix2D({xx:2*a2/n2-1,xy:xy,yx:xy,yy:2*b2/n2-1});
-},project:function(a,b){
-if(arguments.length==1){
-b=a.y;
-a=a.x;
-}
-var a2=a*a,b2=b*b,n2=a2+b2,xy=a*b/n2;
-return new m.Matrix2D({xx:a2/n2,xy:xy,yx:xy,yy:b2/n2});
-},normalize:function(_c){
-return (_c instanceof m.Matrix2D)?_c:new m.Matrix2D(_c);
-},clone:function(_d){
-var _e=new m.Matrix2D();
-for(var i in _d){
-if(typeof (_d[i])=="number"&&typeof (_e[i])=="number"&&_e[i]!=_d[i]){
-_e[i]=_d[i];
-}
-}
-return _e;
-},invert:function(_f){
-var M=m.normalize(_f),D=M.xx*M.yy-M.xy*M.yx,M=new m.Matrix2D({xx:M.yy/D,xy:-M.xy/D,yx:-M.yx/D,yy:M.xx/D,dx:(M.xy*M.dy-M.yy*M.dx)/D,dy:(M.yx*M.dx-M.xx*M.dy)/D});
-return M;
-},_multiplyPoint:function(_10,x,y){
-return {x:_10.xx*x+_10.xy*y+_10.dx,y:_10.yx*x+_10.yy*y+_10.dy};
-},multiplyPoint:function(_11,a,b){
-var M=m.normalize(_11);
-if(typeof a=="number"&&typeof b=="number"){
-return m._multiplyPoint(M,a,b);
-}
-return m._multiplyPoint(M,a.x,a.y);
-},multiply:function(_12){
-var M=m.normalize(_12);
-for(var i=1;i<arguments.length;++i){
-var l=M,r=m.normalize(arguments[i]);
-M=new m.Matrix2D();
-M.xx=l.xx*r.xx+l.xy*r.yx;
-M.xy=l.xx*r.xy+l.xy*r.yy;
-M.yx=l.yx*r.xx+l.yy*r.yx;
-M.yy=l.yx*r.xy+l.yy*r.yy;
-M.dx=l.xx*r.dx+l.xy*r.dy+l.dx;
-M.dy=l.yx*r.dx+l.yy*r.dy+l.dy;
-}
-return M;
-},_sandwich:function(_13,x,y){
-return m.multiply(m.translate(x,y),_13,m.translate(-x,-y));
-},scaleAt:function(a,b,c,d){
-switch(arguments.length){
-case 4:
-return m._sandwich(m.scale(a,b),c,d);
-case 3:
-if(typeof c=="number"){
-return m._sandwich(m.scale(a),b,c);
-}
-return m._sandwich(m.scale(a,b),c.x,c.y);
-}
-return m._sandwich(m.scale(a),b.x,b.y);
-},rotateAt:function(_14,a,b){
-if(arguments.length>2){
-return m._sandwich(m.rotate(_14),a,b);
-}
-return m._sandwich(m.rotate(_14),a.x,a.y);
-},rotategAt:function(_15,a,b){
-if(arguments.length>2){
-return m._sandwich(m.rotateg(_15),a,b);
-}
-return m._sandwich(m.rotateg(_15),a.x,a.y);
-},skewXAt:function(_16,a,b){
-if(arguments.length>2){
-return m._sandwich(m.skewX(_16),a,b);
-}
-return m._sandwich(m.skewX(_16),a.x,a.y);
-},skewXgAt:function(_17,a,b){
-if(arguments.length>2){
-return m._sandwich(m.skewXg(_17),a,b);
-}
-return m._sandwich(m.skewXg(_17),a.x,a.y);
-},skewYAt:function(_18,a,b){
-if(arguments.length>2){
-return m._sandwich(m.skewY(_18),a,b);
-}
-return m._sandwich(m.skewY(_18),a.x,a.y);
-},skewYgAt:function(_19,a,b){
-if(arguments.length>2){
-return m._sandwich(m.skewYg(_19),a,b);
-}
-return m._sandwich(m.skewYg(_19),a.x,a.y);
-}});
+	var m = dojox.gfx.matrix;
+
+	// candidates for dojox.math:
+	var _degToRadCache = {};
+	m._degToRad = function(degree){
+		return _degToRadCache[degree] || (_degToRadCache[degree] = (Math.PI * degree / 180));
+	};
+	m._radToDeg = function(radian){ return radian / Math.PI * 180; };
+
+	m.Matrix2D = function(arg){
+		// summary: a 2D matrix object
+		// description: Normalizes a 2D matrix-like object. If arrays is passed,
+		//		all objects of the array are normalized and multiplied sequentially.
+		// arg: Object
+		//		a 2D matrix-like object, a number, or an array of such objects
+		if(arg){
+			if(typeof arg == "number"){
+				this.xx = this.yy = arg;
+			}else if(arg instanceof Array){
+				if(arg.length > 0){
+					var matrix = m.normalize(arg[0]);
+					// combine matrices
+					for(var i = 1; i < arg.length; ++i){
+						var l = matrix, r = dojox.gfx.matrix.normalize(arg[i]);
+						matrix = new m.Matrix2D();
+						matrix.xx = l.xx * r.xx + l.xy * r.yx;
+						matrix.xy = l.xx * r.xy + l.xy * r.yy;
+						matrix.yx = l.yx * r.xx + l.yy * r.yx;
+						matrix.yy = l.yx * r.xy + l.yy * r.yy;
+						matrix.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
+						matrix.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
+					}
+					dojo.mixin(this, matrix);
+				}
+			}else{
+				dojo.mixin(this, arg);
+			}
+		}
+	};
+
+	// the default (identity) matrix, which is used to fill in missing values
+	dojo.extend(m.Matrix2D, {xx: 1, xy: 0, yx: 0, yy: 1, dx: 0, dy: 0});
+
+	dojo.mixin(m, {
+		// summary: class constants, and methods of dojox.gfx.matrix
+
+		// matrix constants
+
+		// identity: dojox.gfx.matrix.Matrix2D
+		//		an identity matrix constant: identity * (x, y) == (x, y)
+		identity: new m.Matrix2D(),
+
+		// flipX: dojox.gfx.matrix.Matrix2D
+		//		a matrix, which reflects points at x = 0 line: flipX * (x, y) == (-x, y)
+		flipX:    new m.Matrix2D({xx: -1}),
+
+		// flipY: dojox.gfx.matrix.Matrix2D
+		//		a matrix, which reflects points at y = 0 line: flipY * (x, y) == (x, -y)
+		flipY:    new m.Matrix2D({yy: -1}),
+
+		// flipXY: dojox.gfx.matrix.Matrix2D
+		//		a matrix, which reflects points at the origin of coordinates: flipXY * (x, y) == (-x, -y)
+		flipXY:   new m.Matrix2D({xx: -1, yy: -1}),
+
+		// matrix creators
+
+		translate: function(a, b){
+			// summary: forms a translation matrix
+			// description: The resulting matrix is used to translate (move) points by specified offsets.
+			// a: Number: an x coordinate value
+			// b: Number: a y coordinate value
+			if(arguments.length > 1){
+				return new m.Matrix2D({dx: a, dy: b}); // dojox.gfx.matrix.Matrix2D
+			}
+			// branch
+			// a: dojox.gfx.Point: a point-like object, which specifies offsets for both dimensions
+			// b: null
+			return new m.Matrix2D({dx: a.x, dy: a.y}); // dojox.gfx.matrix.Matrix2D
+		},
+		scale: function(a, b){
+			// summary: forms a scaling matrix
+			// description: The resulting matrix is used to scale (magnify) points by specified offsets.
+			// a: Number: a scaling factor used for the x coordinate
+			// b: Number: a scaling factor used for the y coordinate
+			if(arguments.length > 1){
+				return new m.Matrix2D({xx: a, yy: b}); // dojox.gfx.matrix.Matrix2D
+			}
+			if(typeof a == "number"){
+				// branch
+				// a: Number: a uniform scaling factor used for the both coordinates
+				// b: null
+				return new m.Matrix2D({xx: a, yy: a}); // dojox.gfx.matrix.Matrix2D
+			}
+			// branch
+			// a: dojox.gfx.Point: a point-like object, which specifies scale factors for both dimensions
+			// b: null
+			return new m.Matrix2D({xx: a.x, yy: a.y}); // dojox.gfx.matrix.Matrix2D
+		},
+		rotate: function(angle){
+			// summary: forms a rotating matrix
+			// description: The resulting matrix is used to rotate points
+			//		around the origin of coordinates (0, 0) by specified angle.
+			// angle: Number: an angle of rotation in radians (>0 for CW)
+			var c = Math.cos(angle);
+			var s = Math.sin(angle);
+			return new m.Matrix2D({xx: c, xy: -s, yx: s, yy: c}); // dojox.gfx.matrix.Matrix2D
+		},
+		rotateg: function(degree){
+			// summary: forms a rotating matrix
+			// description: The resulting matrix is used to rotate points
+			//		around the origin of coordinates (0, 0) by specified degree.
+			//		See dojox.gfx.matrix.rotate() for comparison.
+			// degree: Number: an angle of rotation in degrees (>0 for CW)
+			return m.rotate(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
+		},
+		skewX: function(angle) {
+			// summary: forms an x skewing matrix
+			// description: The resulting matrix is used to skew points in the x dimension
+			//		around the origin of coordinates (0, 0) by specified angle.
+			// angle: Number: an skewing angle in radians
+			return new m.Matrix2D({xy: Math.tan(angle)}); // dojox.gfx.matrix.Matrix2D
+		},
+		skewXg: function(degree){
+			// summary: forms an x skewing matrix
+			// description: The resulting matrix is used to skew points in the x dimension
+			//		around the origin of coordinates (0, 0) by specified degree.
+			//		See dojox.gfx.matrix.skewX() for comparison.
+			// degree: Number: an skewing angle in degrees
+			return m.skewX(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
+		},
+		skewY: function(angle){
+			// summary: forms a y skewing matrix
+			// description: The resulting matrix is used to skew points in the y dimension
+			//		around the origin of coordinates (0, 0) by specified angle.
+			// angle: Number: an skewing angle in radians
+			return new m.Matrix2D({yx: Math.tan(angle)}); // dojox.gfx.matrix.Matrix2D
+		},
+		skewYg: function(degree){
+			// summary: forms a y skewing matrix
+			// description: The resulting matrix is used to skew points in the y dimension
+			//		around the origin of coordinates (0, 0) by specified degree.
+			//		See dojox.gfx.matrix.skewY() for comparison.
+			// degree: Number: an skewing angle in degrees
+			return m.skewY(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
+		},
+		reflect: function(a, b){
+			// summary: forms a reflection matrix
+			// description: The resulting matrix is used to reflect points around a vector,
+			//		which goes through the origin.
+			// a: dojox.gfx.Point: a point-like object, which specifies a vector of reflection
+			// b: null
+			if(arguments.length == 1){
+				b = a.y;
+				a = a.x;
+			}
+			// branch
+			// a: Number: an x coordinate value
+			// b: Number: a y coordinate value
+
+			// make a unit vector
+			var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = 2 * a * b / n2;
+			return new m.Matrix2D({xx: 2 * a2 / n2 - 1, xy: xy, yx: xy, yy: 2 * b2 / n2 - 1}); // dojox.gfx.matrix.Matrix2D
+		},
+		project: function(a, b){
+			// summary: forms an orthogonal projection matrix
+			// description: The resulting matrix is used to project points orthogonally on a vector,
+			//		which goes through the origin.
+			// a: dojox.gfx.Point: a point-like object, which specifies a vector of projection
+			// b: null
+			if(arguments.length == 1){
+				b = a.y;
+				a = a.x;
+			}
+			// branch
+			// a: Number: an x coordinate value
+			// b: Number: a y coordinate value
+
+			// make a unit vector
+			var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = a * b / n2;
+			return new m.Matrix2D({xx: a2 / n2, xy: xy, yx: xy, yy: b2 / n2}); // dojox.gfx.matrix.Matrix2D
+		},
+
+		// ensure matrix 2D conformance
+		normalize: function(matrix){
+			// summary: converts an object to a matrix, if necessary
+			// description: Converts any 2D matrix-like object or an array of
+			//		such objects to a valid dojox.gfx.matrix.Matrix2D object.
+			// matrix: Object: an object, which is converted to a matrix, if necessary
+			return (matrix instanceof m.Matrix2D) ? matrix : new m.Matrix2D(matrix); // dojox.gfx.matrix.Matrix2D
+		},
+
+		// common operations
+
+		clone: function(matrix){
+			// summary: creates a copy of a 2D matrix
+			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to be cloned
+			var obj = new m.Matrix2D();
+			for(var i in matrix){
+				if(typeof(matrix[i]) == "number" && typeof(obj[i]) == "number" && obj[i] != matrix[i]) obj[i] = matrix[i];
+			}
+			return obj; // dojox.gfx.matrix.Matrix2D
+		},
+		invert: function(matrix){
+			// summary: inverts a 2D matrix
+			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to be inverted
+			var M = m.normalize(matrix),
+				D = M.xx * M.yy - M.xy * M.yx,
+				M = new m.Matrix2D({
+					xx: M.yy/D, xy: -M.xy/D,
+					yx: -M.yx/D, yy: M.xx/D,
+					dx: (M.xy * M.dy - M.yy * M.dx) / D,
+					dy: (M.yx * M.dx - M.xx * M.dy) / D
+				});
+			return M; // dojox.gfx.matrix.Matrix2D
+		},
+		_multiplyPoint: function(matrix, x, y){
+			// summary: applies a matrix to a point
+			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
+			// x: Number: an x coordinate of a point
+			// y: Number: a y coordinate of a point
+			return {x: matrix.xx * x + matrix.xy * y + matrix.dx, y: matrix.yx * x + matrix.yy * y + matrix.dy}; // dojox.gfx.Point
+		},
+		multiplyPoint: function(matrix, /* Number||Point */ a, /* Number, optional */ b){
+			// summary: applies a matrix to a point
+			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
+			// a: Number: an x coordinate of a point
+			// b: Number: a y coordinate of a point
+			var M = m.normalize(matrix);
+			if(typeof a == "number" && typeof b == "number"){
+				return m._multiplyPoint(M, a, b); // dojox.gfx.Point
+			}
+			// branch
+			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
+			// a: dojox.gfx.Point: a point
+			// b: null
+			return m._multiplyPoint(M, a.x, a.y); // dojox.gfx.Point
+		},
+		multiply: function(matrix){
+			// summary: combines matrices by multiplying them sequentially in the given order
+			// matrix: dojox.gfx.matrix.Matrix2D...: a 2D matrix-like object,
+			//		all subsequent arguments are matrix-like objects too
+			var M = m.normalize(matrix);
+			// combine matrices
+			for(var i = 1; i < arguments.length; ++i){
+				var l = M, r = m.normalize(arguments[i]);
+				M = new m.Matrix2D();
+				M.xx = l.xx * r.xx + l.xy * r.yx;
+				M.xy = l.xx * r.xy + l.xy * r.yy;
+				M.yx = l.yx * r.xx + l.yy * r.yx;
+				M.yy = l.yx * r.xy + l.yy * r.yy;
+				M.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
+				M.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
+			}
+			return M; // dojox.gfx.matrix.Matrix2D
+		},
+
+		// high level operations
+
+		_sandwich: function(matrix, x, y){
+			// summary: applies a matrix at a centrtal point
+			// matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object, which is applied at a central point
+			// x: Number: an x component of the central point
+			// y: Number: a y component of the central point
+			return m.multiply(m.translate(x, y), matrix, m.translate(-x, -y)); // dojox.gfx.matrix.Matrix2D
+		},
+		scaleAt: function(a, b, c, d){
+			// summary: scales a picture using a specified point as a center of scaling
+			// description: Compare with dojox.gfx.matrix.scale().
+			// a: Number: a scaling factor used for the x coordinate
+			// b: Number: a scaling factor used for the y coordinate
+			// c: Number: an x component of a central point
+			// d: Number: a y component of a central point
+
+			// accepts several signatures:
+			//	1) uniform scale factor, Point
+			//	2) uniform scale factor, x, y
+			//	3) x scale, y scale, Point
+			//	4) x scale, y scale, x, y
+
+			switch(arguments.length){
+				case 4:
+					// a and b are scale factor components, c and d are components of a point
+					return m._sandwich(m.scale(a, b), c, d); // dojox.gfx.matrix.Matrix2D
+				case 3:
+					if(typeof c == "number"){
+						// branch
+						// a: Number: a uniform scaling factor used for both coordinates
+						// b: Number: an x component of a central point
+						// c: Number: a y component of a central point
+						// d: null
+						return m._sandwich(m.scale(a), b, c); // dojox.gfx.matrix.Matrix2D
+					}
+					// branch
+					// a: Number: a scaling factor used for the x coordinate
+					// b: Number: a scaling factor used for the y coordinate
+					// c: dojox.gfx.Point: a central point
+					// d: null
+					return m._sandwich(m.scale(a, b), c.x, c.y); // dojox.gfx.matrix.Matrix2D
+			}
+			// branch
+			// a: Number: a uniform scaling factor used for both coordinates
+			// b: dojox.gfx.Point: a central point
+			// c: null
+			// d: null
+			return m._sandwich(m.scale(a), b.x, b.y); // dojox.gfx.matrix.Matrix2D
+		},
+		rotateAt: function(angle, a, b){
+			// summary: rotates a picture using a specified point as a center of rotation
+			// description: Compare with dojox.gfx.matrix.rotate().
+			// angle: Number: an angle of rotation in radians (>0 for CW)
+			// a: Number: an x component of a central point
+			// b: Number: a y component of a central point
+
+			// accepts several signatures:
+			//	1) rotation angle in radians, Point
+			//	2) rotation angle in radians, x, y
+
+			if(arguments.length > 2){
+				return m._sandwich(m.rotate(angle), a, b); // dojox.gfx.matrix.Matrix2D
+			}
+
+			// branch
+			// angle: Number: an angle of rotation in radians (>0 for CCW)
+			// a: dojox.gfx.Point: a central point
+			// b: null
+			return m._sandwich(m.rotate(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
+		},
+		rotategAt: function(degree, a, b){
+			// summary: rotates a picture using a specified point as a center of rotation
+			// description: Compare with dojox.gfx.matrix.rotateg().
+			// degree: Number: an angle of rotation in degrees (>0 for CW)
+			// a: Number: an x component of a central point
+			// b: Number: a y component of a central point
+
+			// accepts several signatures:
+			//	1) rotation angle in degrees, Point
+			//	2) rotation angle in degrees, x, y
+
+			if(arguments.length > 2){
+				return m._sandwich(m.rotateg(degree), a, b); // dojox.gfx.matrix.Matrix2D
+			}
+
+			// branch
+			// degree: Number: an angle of rotation in degrees (>0 for CCW)
+			// a: dojox.gfx.Point: a central point
+			// b: null
+			return m._sandwich(m.rotateg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
+		},
+		skewXAt: function(angle, a, b){
+			// summary: skews a picture along the x axis using a specified point as a center of skewing
+			// description: Compare with dojox.gfx.matrix.skewX().
+			// angle: Number: an skewing angle in radians
+			// a: Number: an x component of a central point
+			// b: Number: a y component of a central point
+
+			// accepts several signatures:
+			//	1) skew angle in radians, Point
+			//	2) skew angle in radians, x, y
+
+			if(arguments.length > 2){
+				return m._sandwich(m.skewX(angle), a, b); // dojox.gfx.matrix.Matrix2D
+			}
+
+			// branch
+			// angle: Number: an skewing angle in radians
+			// a: dojox.gfx.Point: a central point
+			// b: null
+			return m._sandwich(m.skewX(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
+		},
+		skewXgAt: function(degree, a, b){
+			// summary: skews a picture along the x axis using a specified point as a center of skewing
+			// description: Compare with dojox.gfx.matrix.skewXg().
+			// degree: Number: an skewing angle in degrees
+			// a: Number: an x component of a central point
+			// b: Number: a y component of a central point
+
+			// accepts several signatures:
+			//	1) skew angle in degrees, Point
+			//	2) skew angle in degrees, x, y
+
+			if(arguments.length > 2){
+				return m._sandwich(m.skewXg(degree), a, b); // dojox.gfx.matrix.Matrix2D
+			}
+
+			// branch
+			// degree: Number: an skewing angle in degrees
+			// a: dojox.gfx.Point: a central point
+			// b: null
+			return m._sandwich(m.skewXg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
+		},
+		skewYAt: function(angle, a, b){
+			// summary: skews a picture along the y axis using a specified point as a center of skewing
+			// description: Compare with dojox.gfx.matrix.skewY().
+			// angle: Number: an skewing angle in radians
+			// a: Number: an x component of a central point
+			// b: Number: a y component of a central point
+
+			// accepts several signatures:
+			//	1) skew angle in radians, Point
+			//	2) skew angle in radians, x, y
+
+			if(arguments.length > 2){
+				return m._sandwich(m.skewY(angle), a, b); // dojox.gfx.matrix.Matrix2D
+			}
+
+			// branch
+			// angle: Number: an skewing angle in radians
+			// a: dojox.gfx.Point: a central point
+			// b: null
+			return m._sandwich(m.skewY(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
+		},
+		skewYgAt: function(/* Number */ degree, /* Number||Point */ a, /* Number, optional */ b){
+			// summary: skews a picture along the y axis using a specified point as a center of skewing
+			// description: Compare with dojox.gfx.matrix.skewYg().
+			// degree: Number: an skewing angle in degrees
+			// a: Number: an x component of a central point
+			// b: Number: a y component of a central point
+
+			// accepts several signatures:
+			//	1) skew angle in degrees, Point
+			//	2) skew angle in degrees, x, y
+
+			if(arguments.length > 2){
+				return m._sandwich(m.skewYg(degree), a, b); // dojox.gfx.matrix.Matrix2D
+			}
+
+			// branch
+			// degree: Number: an skewing angle in degrees
+			// a: dojox.gfx.Point: a central point
+			// b: null
+			return m._sandwich(m.skewYg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
+		}
+
+		//TODO: rect-to-rect mapping, scale-to-fit (isotropic and anisotropic versions)
+
+	});
 })();
-dojox.gfx.Matrix2D=dojox.gfx.matrix.Matrix2D;
-}
+
+// propagate Matrix2D up
+dojox.gfx.Matrix2D = dojox.gfx.matrix.Matrix2D;
diff --git a/dojox/gfx/move.js b/dojox/gfx/move.js
index a67c27e..60b14a7 100644
--- a/dojox/gfx/move.js
+++ b/dojox/gfx/move.js
@@ -1,13 +1,4 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.move"]){
-dojo._hasResource["dojox.gfx.move"]=true;
 dojo.provide("dojox.gfx.move");
+
 dojo.require("dojox.gfx.Mover");
 dojo.require("dojox.gfx.Moveable");
-}
diff --git a/dojox/gfx/path.js b/dojox/gfx/path.js
index 81f9455..37a52ce 100644
--- a/dojox/gfx/path.js
+++ b/dojox/gfx/path.js
@@ -1,277 +1,419 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.path"]){
-dojo._hasResource["dojox.gfx.path"]=true;
 dojo.provide("dojox.gfx.path");
+
+dojo.require("dojox.gfx.matrix");
 dojo.require("dojox.gfx.shape");
-dojo.declare("dojox.gfx.path.Path",dojox.gfx.Shape,{constructor:function(_1){
-this.shape=dojo.clone(dojox.gfx.defaultPath);
-this.segments=[];
-this.absolute=true;
-this.last={};
-this.rawNode=_1;
-},setAbsoluteMode:function(_2){
-this.absolute=typeof _2=="string"?(_2=="absolute"):_2;
-return this;
-},getAbsoluteMode:function(){
-return this.absolute;
-},getBoundingBox:function(){
-return (this.bbox&&("l" in this.bbox))?{x:this.bbox.l,y:this.bbox.t,width:this.bbox.r-this.bbox.l,height:this.bbox.b-this.bbox.t}:null;
-},getLastPosition:function(){
-return "x" in this.last?this.last:null;
-},_updateBBox:function(x,y){
-if(this.bbox&&("l" in this.bbox)){
-if(this.bbox.l>x){
-this.bbox.l=x;
-}
-if(this.bbox.r<x){
-this.bbox.r=x;
-}
-if(this.bbox.t>y){
-this.bbox.t=y;
-}
-if(this.bbox.b<y){
-this.bbox.b=y;
-}
-}else{
-this.bbox={l:x,b:y,r:x,t:y};
-}
-},_updateWithSegment:function(_3){
-var n=_3.args,l=n.length;
-switch(_3.action){
-case "M":
-case "L":
-case "C":
-case "S":
-case "Q":
-case "T":
-for(var i=0;i<l;i+=2){
-this._updateBBox(n[i],n[i+1]);
-}
-this.last.x=n[l-2];
-this.last.y=n[l-1];
-this.absolute=true;
-break;
-case "H":
-for(var i=0;i<l;++i){
-this._updateBBox(n[i],this.last.y);
-}
-this.last.x=n[l-1];
-this.absolute=true;
-break;
-case "V":
-for(var i=0;i<l;++i){
-this._updateBBox(this.last.x,n[i]);
-}
-this.last.y=n[l-1];
-this.absolute=true;
-break;
-case "m":
-var _4=0;
-if(!("x" in this.last)){
-this._updateBBox(this.last.x=n[0],this.last.y=n[1]);
-_4=2;
-}
-for(var i=_4;i<l;i+=2){
-this._updateBBox(this.last.x+=n[i],this.last.y+=n[i+1]);
-}
-this.absolute=false;
-break;
-case "l":
-case "t":
-for(var i=0;i<l;i+=2){
-this._updateBBox(this.last.x+=n[i],this.last.y+=n[i+1]);
-}
-this.absolute=false;
-break;
-case "h":
-for(var i=0;i<l;++i){
-this._updateBBox(this.last.x+=n[i],this.last.y);
-}
-this.absolute=false;
-break;
-case "v":
-for(var i=0;i<l;++i){
-this._updateBBox(this.last.x,this.last.y+=n[i]);
-}
-this.absolute=false;
-break;
-case "c":
-for(var i=0;i<l;i+=6){
-this._updateBBox(this.last.x+n[i],this.last.y+n[i+1]);
-this._updateBBox(this.last.x+n[i+2],this.last.y+n[i+3]);
-this._updateBBox(this.last.x+=n[i+4],this.last.y+=n[i+5]);
-}
-this.absolute=false;
-break;
-case "s":
-case "q":
-for(var i=0;i<l;i+=4){
-this._updateBBox(this.last.x+n[i],this.last.y+n[i+1]);
-this._updateBBox(this.last.x+=n[i+2],this.last.y+=n[i+3]);
-}
-this.absolute=false;
-break;
-case "A":
-for(var i=0;i<l;i+=7){
-this._updateBBox(n[i+5],n[i+6]);
-}
-this.last.x=n[l-2];
-this.last.y=n[l-1];
-this.absolute=true;
-break;
-case "a":
-for(var i=0;i<l;i+=7){
-this._updateBBox(this.last.x+=n[i+5],this.last.y+=n[i+6]);
-}
-this.absolute=false;
-break;
-}
-var _5=[_3.action];
-for(var i=0;i<l;++i){
-_5.push(dojox.gfx.formatNumber(n[i],true));
-}
-if(typeof this.shape.path=="string"){
-this.shape.path+=_5.join("");
-}else{
-Array.prototype.push.apply(this.shape.path,_5);
-}
-},_validSegments:{m:2,l:2,h:1,v:1,c:6,s:4,q:4,t:2,a:7,z:0},_pushSegment:function(_6,_7){
-var _8=this._validSegments[_6.toLowerCase()];
-if(typeof _8=="number"){
-if(_8){
-if(_7.length>=_8){
-var _9={action:_6,args:_7.slice(0,_7.length-_7.length%_8)};
-this.segments.push(_9);
-this._updateWithSegment(_9);
-}
-}else{
-var _9={action:_6,args:[]};
-this.segments.push(_9);
-this._updateWithSegment(_9);
-}
-}
-},_collectArgs:function(_a,_b){
-for(var i=0;i<_b.length;++i){
-var t=_b[i];
-if(typeof t=="boolean"){
-_a.push(t?1:0);
-}else{
-if(typeof t=="number"){
-_a.push(t);
-}else{
-if(t instanceof Array){
-this._collectArgs(_a,t);
-}else{
-if("x" in t&&"y" in t){
-_a.push(t.x,t.y);
-}
-}
-}
-}
-}
-},moveTo:function(){
-var _c=[];
-this._collectArgs(_c,arguments);
-this._pushSegment(this.absolute?"M":"m",_c);
-return this;
-},lineTo:function(){
-var _d=[];
-this._collectArgs(_d,arguments);
-this._pushSegment(this.absolute?"L":"l",_d);
-return this;
-},hLineTo:function(){
-var _e=[];
-this._collectArgs(_e,arguments);
-this._pushSegment(this.absolute?"H":"h",_e);
-return this;
-},vLineTo:function(){
-var _f=[];
-this._collectArgs(_f,arguments);
-this._pushSegment(this.absolute?"V":"v",_f);
-return this;
-},curveTo:function(){
-var _10=[];
-this._collectArgs(_10,arguments);
-this._pushSegment(this.absolute?"C":"c",_10);
-return this;
-},smoothCurveTo:function(){
-var _11=[];
-this._collectArgs(_11,arguments);
-this._pushSegment(this.absolute?"S":"s",_11);
-return this;
-},qCurveTo:function(){
-var _12=[];
-this._collectArgs(_12,arguments);
-this._pushSegment(this.absolute?"Q":"q",_12);
-return this;
-},qSmoothCurveTo:function(){
-var _13=[];
-this._collectArgs(_13,arguments);
-this._pushSegment(this.absolute?"T":"t",_13);
-return this;
-},arcTo:function(){
-var _14=[];
-this._collectArgs(_14,arguments);
-this._pushSegment(this.absolute?"A":"a",_14);
-return this;
-},closePath:function(){
-this._pushSegment("Z",[]);
-return this;
-},_setPath:function(_15){
-var p=dojo.isArray(_15)?_15:_15.match(dojox.gfx.pathSvgRegExp);
-this.segments=[];
-this.absolute=true;
-this.bbox={};
-this.last={};
-if(!p){
-return;
-}
-var _16="",_17=[],l=p.length;
-for(var i=0;i<l;++i){
-var t=p[i],x=parseFloat(t);
-if(isNaN(x)){
-if(_16){
-this._pushSegment(_16,_17);
-}
-_17=[];
-_16=t;
-}else{
-_17.push(x);
-}
-}
-this._pushSegment(_16,_17);
-},setShape:function(_18){
-dojox.gfx.Shape.prototype.setShape.call(this,typeof _18=="string"?{path:_18}:_18);
-var _19=this.shape.path;
-this.shape.path=[];
-this._setPath(_19);
-this.shape.path=this.shape.path.join("");
-return this;
-},_2PI:Math.PI*2});
-dojo.declare("dojox.gfx.path.TextPath",dojox.gfx.path.Path,{constructor:function(_1a){
-if(!("text" in this)){
-this.text=dojo.clone(dojox.gfx.defaultTextPath);
-}
-if(!("fontStyle" in this)){
-this.fontStyle=dojo.clone(dojox.gfx.defaultFont);
-}
-},getText:function(){
-return this.text;
-},setText:function(_1b){
-this.text=dojox.gfx.makeParameters(this.text,typeof _1b=="string"?{text:_1b}:_1b);
-this._setText();
-return this;
-},getFont:function(){
-return this.fontStyle;
-},setFont:function(_1c){
-this.fontStyle=typeof _1c=="string"?dojox.gfx.splitFontString(_1c):dojox.gfx.makeParameters(dojox.gfx.defaultFont,_1c);
-this._setFont();
-return this;
-}});
-}
+
+dojo.declare("dojox.gfx.path.Path", dojox.gfx.Shape, {
+	// summary: a generalized path shape
+
+	constructor: function(rawNode){
+		// summary: a path constructor
+		// rawNode: Node: a DOM node to be used by this path object
+		this.shape = dojo.clone(dojox.gfx.defaultPath);
+		this.segments = [];
+		this.tbbox = null;
+		this.absolute = true;
+		this.last = {};
+		this.rawNode = rawNode;
+		this.segmented = false;
+	},
+
+	// mode manipulations
+	setAbsoluteMode: function(mode){
+		// summary: sets an absolute or relative mode for path points
+		// mode: Boolean: true/false or "absolute"/"relative" to specify the mode
+		this._confirmSegmented();
+		this.absolute = typeof mode == "string" ? (mode == "absolute") : mode;
+		return this; // self
+	},
+	getAbsoluteMode: function(){
+		// summary: returns a current value of the absolute mode
+		this._confirmSegmented();
+		return this.absolute; // Boolean
+	},
+
+	getBoundingBox: function(){
+		// summary: returns the bounding box {x, y, width, height} or null
+		this._confirmSegmented();
+		return (this.bbox && ("l" in this.bbox)) ? {x: this.bbox.l, y: this.bbox.t, width: this.bbox.r - this.bbox.l, height: this.bbox.b - this.bbox.t} : null; // dojox.gfx.Rectangle
+	},
+
+	_getRealBBox: function(){
+		// summary: returns an array of four points or null
+		//	four points represent four corners of the untransformed bounding box
+		this._confirmSegmented();
+		if(this.tbbox){
+			return this.tbbox;	// Array
+		}
+		var bbox = this.bbox, matrix = this._getRealMatrix();
+		this.bbox = null;
+		for(var i = 0, len = this.segments.length; i < len; ++i){
+			this._updateWithSegment(this.segments[i], matrix);
+		}
+		var t = this.bbox;
+		this.bbox = bbox;
+		this.tbbox = t ? [
+			{x: t.l, y: t.t},
+			{x: t.r, y: t.t},
+			{x: t.r, y: t.b},
+			{x: t.l, y: t.b}
+		] : null;
+		return this.tbbox;	// Array
+	},
+
+	getLastPosition: function(){
+		// summary: returns the last point in the path, or null
+		this._confirmSegmented();
+		return "x" in this.last ? this.last : null; // Object
+	},
+
+	_applyTransform: function(){
+		this.tbbox = null;
+		return dojox.gfx.Shape.prototype._applyTransform.call(this);
+	},
+
+	// segment interpretation
+	_updateBBox: function(x, y, matrix){
+		// summary: updates the bounding box of path with new point
+		// x: Number: an x coordinate
+		// y: Number: a y coordinate
+		
+		if(matrix){
+			var t = dojox.gfx.matrix.multiplyPoint(matrix, x, y);
+			x = t.x;
+			y = t.y;
+		}
+
+		// we use {l, b, r, t} representation of a bbox
+		if(this.bbox && ("l" in this.bbox)){
+			if(this.bbox.l > x) this.bbox.l = x;
+			if(this.bbox.r < x) this.bbox.r = x;
+			if(this.bbox.t > y) this.bbox.t = y;
+			if(this.bbox.b < y) this.bbox.b = y;
+		}else{
+			this.bbox = {l: x, b: y, r: x, t: y};
+		}
+	},
+	_updateWithSegment: function(segment, matrix){
+		// summary: updates the bounding box of path with new segment
+		// segment: Object: a segment
+		var n = segment.args, l = n.length;
+		// update internal variables: bbox, absolute, last
+		switch(segment.action){
+			case "M":
+			case "L":
+			case "C":
+			case "S":
+			case "Q":
+			case "T":
+				for(var i = 0; i < l; i += 2){
+					this._updateBBox(n[i], n[i + 1], matrix);
+				}
+				this.last.x = n[l - 2];
+				this.last.y = n[l - 1];
+				this.absolute = true;
+				break;
+			case "H":
+				for(var i = 0; i < l; ++i){
+					this._updateBBox(n[i], this.last.y, matrix);
+				}
+				this.last.x = n[l - 1];
+				this.absolute = true;
+				break;
+			case "V":
+				for(var i = 0; i < l; ++i){
+					this._updateBBox(this.last.x, n[i], matrix);
+				}
+				this.last.y = n[l - 1];
+				this.absolute = true;
+				break;
+			case "m":
+				var start = 0;
+				if(!("x" in this.last)){
+					this._updateBBox(this.last.x = n[0], this.last.y = n[1], matrix);
+					start = 2;
+				}
+				for(var i = start; i < l; i += 2){
+					this._updateBBox(this.last.x += n[i], this.last.y += n[i + 1], matrix);
+				}
+				this.absolute = false;
+				break;
+			case "l":
+			case "t":
+				for(var i = 0; i < l; i += 2){
+					this._updateBBox(this.last.x += n[i], this.last.y += n[i + 1], matrix);
+				}
+				this.absolute = false;
+				break;
+			case "h":
+				for(var i = 0; i < l; ++i){
+					this._updateBBox(this.last.x += n[i], this.last.y, matrix);
+				}
+				this.absolute = false;
+				break;
+			case "v":
+				for(var i = 0; i < l; ++i){
+					this._updateBBox(this.last.x, this.last.y += n[i], matrix);
+				}
+				this.absolute = false;
+				break;
+			case "c":
+				for(var i = 0; i < l; i += 6){
+					this._updateBBox(this.last.x + n[i], this.last.y + n[i + 1], matrix);
+					this._updateBBox(this.last.x + n[i + 2], this.last.y + n[i + 3], matrix);
+					this._updateBBox(this.last.x += n[i + 4], this.last.y += n[i + 5], matrix);
+				}
+				this.absolute = false;
+				break;
+			case "s":
+			case "q":
+				for(var i = 0; i < l; i += 4){
+					this._updateBBox(this.last.x + n[i], this.last.y + n[i + 1], matrix);
+					this._updateBBox(this.last.x += n[i + 2], this.last.y += n[i + 3], matrix);
+				}
+				this.absolute = false;
+				break;
+			case "A":
+				for(var i = 0; i < l; i += 7){
+					this._updateBBox(n[i + 5], n[i + 6], matrix);
+				}
+				this.last.x = n[l - 2];
+				this.last.y = n[l - 1];
+				this.absolute = true;
+				break;
+			case "a":
+				for(var i = 0; i < l; i += 7){
+					this._updateBBox(this.last.x += n[i + 5], this.last.y += n[i + 6], matrix);
+				}
+				this.absolute = false;
+				break;
+		}
+		// add an SVG path segment
+		var path = [segment.action];
+		for(var i = 0; i < l; ++i){
+			path.push(dojox.gfx.formatNumber(n[i], true));
+		}
+		if(typeof this.shape.path == "string"){
+			this.shape.path += path.join("");
+		}else{
+			Array.prototype.push.apply(this.shape.path, path);
+		}
+	},
+
+	// a dictionary, which maps segment type codes to a number of their arguments
+	_validSegments: {m: 2, l: 2, h: 1, v: 1, c: 6, s: 4, q: 4, t: 2, a: 7, z: 0},
+
+	_pushSegment: function(action, args){
+		// summary: adds a segment
+		// action: String: valid SVG code for a segment's type
+		// args: Array: a list of parameters for this segment
+		this.tbbox = null;
+		var group = this._validSegments[action.toLowerCase()];
+		if(typeof group == "number"){
+			if(group){
+				if(args.length >= group){
+					var segment = {action: action, args: args.slice(0, args.length - args.length % group)};
+					this.segments.push(segment);
+					this._updateWithSegment(segment);
+				}
+			}else{
+				var segment = {action: action, args: []};
+				this.segments.push(segment);
+				this._updateWithSegment(segment);
+			}
+		}
+	},
+
+	_collectArgs: function(array, args){
+		// summary: converts an array of arguments to plain numeric values
+		// array: Array: an output argument (array of numbers)
+		// args: Array: an input argument (can be values of Boolean, Number, dojox.gfx.Point, or an embedded array of them)
+		for(var i = 0; i < args.length; ++i){
+			var t = args[i];
+			if(typeof t == "boolean"){
+				array.push(t ? 1 : 0);
+			}else if(typeof t == "number"){
+				array.push(t);
+			}else if(t instanceof Array){
+				this._collectArgs(array, t);
+			}else if("x" in t && "y" in t){
+				array.push(t.x, t.y);
+			}
+		}
+	},
+
+	// segments
+	moveTo: function(){
+		// summary: formes a move segment
+		this._confirmSegmented();
+		var args = [];
+		this._collectArgs(args, arguments);
+		this._pushSegment(this.absolute ? "M" : "m", args);
+		return this; // self
+	},
+	lineTo: function(){
+		// summary: formes a line segment
+		this._confirmSegmented();
+		var args = [];
+		this._collectArgs(args, arguments);
+		this._pushSegment(this.absolute ? "L" : "l", args);
+		return this; // self
+	},
+	hLineTo: function(){
+		// summary: formes a horizontal line segment
+		this._confirmSegmented();
+		var args = [];
+		this._collectArgs(args, arguments);
+		this._pushSegment(this.absolute ? "H" : "h", args);
+		return this; // self
+	},
+	vLineTo: function(){
+		// summary: formes a vertical line segment
+		this._confirmSegmented();
+		var args = [];
+		this._collectArgs(args, arguments);
+		this._pushSegment(this.absolute ? "V" : "v", args);
+		return this; // self
+	},
+	curveTo: function(){
+		// summary: formes a curve segment
+		this._confirmSegmented();
+		var args = [];
+		this._collectArgs(args, arguments);
+		this._pushSegment(this.absolute ? "C" : "c", args);
+		return this; // self
+	},
+	smoothCurveTo: function(){
+		// summary: formes a smooth curve segment
+		this._confirmSegmented();
+		var args = [];
+		this._collectArgs(args, arguments);
+		this._pushSegment(this.absolute ? "S" : "s", args);
+		return this; // self
+	},
+	qCurveTo: function(){
+		// summary: formes a quadratic curve segment
+		this._confirmSegmented();
+		var args = [];
+		this._collectArgs(args, arguments);
+		this._pushSegment(this.absolute ? "Q" : "q", args);
+		return this; // self
+	},
+	qSmoothCurveTo: function(){
+		// summary: formes a quadratic smooth curve segment
+		this._confirmSegmented();
+		var args = [];
+		this._collectArgs(args, arguments);
+		this._pushSegment(this.absolute ? "T" : "t", args);
+		return this; // self
+	},
+	arcTo: function(){
+		// summary: formes an elliptic arc segment
+		this._confirmSegmented();
+		var args = [];
+		this._collectArgs(args, arguments);
+		this._pushSegment(this.absolute ? "A" : "a", args);
+		return this; // self
+	},
+	closePath: function(){
+		// summary: closes a path
+		this._confirmSegmented();
+		this._pushSegment("Z", []);
+		return this; // self
+	},
+
+	_confirmSegmented: function() {
+		if (!this.segmented) {
+			var path = this.shape.path;
+			// switch to non-updating version of path building
+			this.shape.path = [];
+			this._setPath(path);
+			// switch back to the string path
+			this.shape.path = this.shape.path.join("");
+			// become segmented
+			this.segmented = true;
+		}
+	},
+
+	// setShape
+	_setPath: function(path){
+		// summary: forms a path using an SVG path string
+		// path: String: an SVG path string
+		var p = dojo.isArray(path) ? path : path.match(dojox.gfx.pathSvgRegExp);
+		this.segments = [];
+		this.absolute = true;
+		this.bbox = {};
+		this.last = {};
+		if(!p) return;
+		// create segments
+		var action = "",	// current action
+			args = [],		// current arguments
+			l = p.length;
+		for(var i = 0; i < l; ++i){
+			var t = p[i], x = parseFloat(t);
+			if(isNaN(x)){
+				if(action){
+					this._pushSegment(action, args);
+				}
+				args = [];
+				action = t;
+			}else{
+				args.push(x);
+			}
+		}
+		this._pushSegment(action, args);
+	},
+	setShape: function(newShape){
+		// summary: forms a path using a shape
+		// newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+		dojox.gfx.Shape.prototype.setShape.call(this, typeof newShape == "string" ? {path: newShape} : newShape);
+		
+		this.segmented = false;
+		this.segments = [];
+		if(!dojox.gfx.lazyPathSegmentation){
+			this._confirmSegmented();
+		}
+		return this; // self
+	},
+
+	// useful constant for descendants
+	_2PI: Math.PI * 2
+});
+
+dojo.declare("dojox.gfx.path.TextPath", dojox.gfx.path.Path, {
+	// summary: a generalized TextPath shape
+
+	constructor: function(rawNode){
+		// summary: a TextPath shape constructor
+		// rawNode: Node: a DOM node to be used by this TextPath object
+		if(!("text" in this)){
+			this.text = dojo.clone(dojox.gfx.defaultTextPath);
+		}
+		if(!("fontStyle" in this)){
+			this.fontStyle = dojo.clone(dojox.gfx.defaultFont);
+		}
+	},
+	getText: function(){
+		// summary: returns the current text object or null
+		return this.text;	// Object
+	},
+	setText: function(newText){
+		// summary: sets a text to be drawn along the path
+		this.text = dojox.gfx.makeParameters(this.text,
+			typeof newText == "string" ? {text: newText} : newText);
+		this._setText();
+		return this;	// self
+	},
+	getFont: function(){
+		// summary: returns the current font object or null
+		return this.fontStyle;	// Object
+	},
+	setFont: function(newFont){
+		// summary: sets a font for text
+		this.fontStyle = typeof newFont == "string" ?
+			dojox.gfx.splitFontString(newFont) :
+			dojox.gfx.makeParameters(dojox.gfx.defaultFont, newFont);
+		this._setFont();
+		return this;	// self
+	}
+});
diff --git a/dojox/gfx/resources/svg2gfx.xsl b/dojox/gfx/resources/svg2gfx.xsl
index a8dc5cd..91ba90f 100644
--- a/dojox/gfx/resources/svg2gfx.xsl
+++ b/dojox/gfx/resources/svg2gfx.xsl
@@ -707,7 +707,10 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<xsl:call-template name="transform-processor">
 			<xsl:with-param name="transforms" select="."/>
 		</xsl:call-template>
-		<xsl:text>},</xsl:text>		
+		<xsl:text>}</xsl:text>		
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 
 	<!-- SVG Element Handling -->
@@ -741,7 +744,10 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<xsl:call-template name="common-attributes">
 			<xsl:with-param name="node" select="."/>
 		</xsl:call-template>
-		<xsl:text>},</xsl:text>
+		<xsl:text>}</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 
 	<xsl:template match="svg:ellipse">
@@ -750,12 +756,15 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<xsl:apply-templates select="@id"/>
 		<xsl:text>shape:{type:"ellipse",</xsl:text>
 		<xsl:apply-templates select="@cx|@cy|@rx|@ry"/>
-		<xsl:text>},</xsl:text>
+		<xsl:text>}</xsl:text>
 		<xsl:value-of select="$groupAttrs"/>
 		<xsl:call-template name="common-attributes">
 			<xsl:with-param name="node" select="."/>
 		</xsl:call-template>
-		<xsl:text>},</xsl:text>
+		<xsl:text>}</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 
 	<xsl:template match="svg:g">
@@ -780,13 +789,19 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<xsl:apply-templates select="&SupportedElements;">
 			<xsl:with-param name="groupAttrs" select="$newGroupAttrs"/>
 		</xsl:apply-templates>
-		<xsl:text>],</xsl:text>
+		<xsl:text>]</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 		<!-- When GFX gets group fills etc., remove the following line and uncomment the ones below. -->
 		<xsl:apply-templates select="@transform"/>
 		<!--<xsl:call-template name="common-attributes">-->
 		<!--	<xsl:with-param name="node" select="."/>-->
 		<!--</xsl:call-template>-->
-		<xsl:text>},</xsl:text>
+		<xsl:text>}</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 
 	<xsl:template match="svg:image">
@@ -823,7 +838,10 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<xsl:call-template name="common-attributes">
 			<xsl:with-param name="node" select="."/>
 		</xsl:call-template>
-		<xsl:text>},</xsl:text>
+		<xsl:text>}</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 
 	<xsl:template match="svg:linearGradient">
@@ -849,7 +867,10 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<!-- Uncommenting the following would support it here. -->
 		<!-- <xsl:apply-templates select="@x1|@x2|@y1|@y2"/> -->
 		<!-- <xsl:apply-templates select="@gradientTransform"/> -->
-		<xsl:text>]},</xsl:text>
+		<xsl:text>]}</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 
 	<xsl:template match="svg:path">
@@ -875,7 +896,10 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<!-- GFX only seems to handle image pattern type fills, so that's all we do -->
 		<xsl:text>{type:"pattern",</xsl:text>
 		<xsl:apply-templates select="@width|@height|@xlink:href"/>
-		<xsl:text>},</xsl:text>
+		<xsl:text>}</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 
 	<xsl:template match="svg:polygon|svg:polyline">
@@ -910,7 +934,10 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<xsl:call-template name="common-attributes">
 			<xsl:with-param name="node" select="."/>
 		</xsl:call-template>
-		<xsl:text>},</xsl:text>
+		<xsl:text>}</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 
 	<xsl:template match="svg:radialGradient">
@@ -939,7 +966,10 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<!-- Uncommenting the following would support it here. -->
 		<!-- <xsl:apply-templates select="@cx|@cy|@r"/> -->
 		<!-- <xsl:apply-templates select="@gradientTransform"/> -->
-		<xsl:text>]},</xsl:text>
+		<xsl:text>]}</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 
 	<xsl:template match="svg:rect">
@@ -959,7 +989,10 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<xsl:call-template name="common-attributes">
 			<xsl:with-param name="node" select="."/>
 		</xsl:call-template>
-		<xsl:text>},</xsl:text>
+		<xsl:text>}</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 
 	<xsl:template match="svg:stop">
@@ -968,7 +1001,10 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<xsl:apply-templates select="@offset"/>
 		<xsl:text>color:</xsl:text>
 		<xsl:apply-templates select="@style"/>
-		<xsl:text>},</xsl:text>
+		<xsl:text>}</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 
 	<xsl:template match="svg:text|svg:textPath">
@@ -1013,7 +1049,10 @@ GMail, etc.) or Eric (Saugus.net, ShellTown, etc.)
 		<xsl:call-template name="common-attributes">
 			<xsl:with-param name="node" select="."/>
 		</xsl:call-template>
-		<xsl:text>},</xsl:text>
+		<xsl:text>}</xsl:text>
+		<xsl:if test="not(position()=last())"> 
+			<xsl:text >,</xsl:text> 
+		</xsl:if>
 	</xsl:template>
 	
 	<xsl:template match="svg:use">
diff --git a/dojox/gfx/shape.js b/dojox/gfx/shape.js
index 4c70837..fc8f18b 100644
--- a/dojox/gfx/shape.js
+++ b/dojox/gfx/shape.js
@@ -1,375 +1,750 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.shape"]){
-dojo._hasResource["dojox.gfx.shape"]=true;
 dojo.provide("dojox.gfx.shape");
+
 dojo.require("dojox.gfx._base");
-dojo.declare("dojox.gfx.Shape",null,{constructor:function(){
-this.rawNode=null;
-this.shape=null;
-this.matrix=null;
-this.fillStyle=null;
-this.strokeStyle=null;
-this.bbox=null;
-this.parent=null;
-this.parentMatrix=null;
-},getNode:function(){
-return this.rawNode;
-},getShape:function(){
-return this.shape;
-},getTransform:function(){
-return this.matrix;
-},getFill:function(){
-return this.fillStyle;
-},getStroke:function(){
-return this.strokeStyle;
-},getParent:function(){
-return this.parent;
-},getBoundingBox:function(){
-return this.bbox;
-},getTransformedBoundingBox:function(){
-var b=this.getBoundingBox();
-if(!b){
-return null;
-}
-var m=this._getRealMatrix();
-var r=[];
-var g=dojox.gfx.matrix;
-r.push(g.multiplyPoint(m,b.x,b.y));
-r.push(g.multiplyPoint(m,b.x+b.width,b.y));
-r.push(g.multiplyPoint(m,b.x+b.width,b.y+b.height));
-r.push(g.multiplyPoint(m,b.x,b.y+b.height));
-return r;
-},getEventSource:function(){
-return this.rawNode;
-},setShape:function(_1){
-this.shape=dojox.gfx.makeParameters(this.shape,_1);
-this.bbox=null;
-return this;
-},setFill:function(_2){
-if(!_2){
-this.fillStyle=null;
-return this;
-}
-var f=null;
-if(typeof (_2)=="object"&&"type" in _2){
-switch(_2.type){
-case "linear":
-f=dojox.gfx.makeParameters(dojox.gfx.defaultLinearGradient,_2);
-break;
-case "radial":
-f=dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient,_2);
-break;
-case "pattern":
-f=dojox.gfx.makeParameters(dojox.gfx.defaultPattern,_2);
-break;
-}
-}else{
-f=dojox.gfx.normalizeColor(_2);
-}
-this.fillStyle=f;
-return this;
-},setStroke:function(_3){
-if(!_3){
-this.strokeStyle=null;
-return this;
-}
-if(typeof _3=="string"||dojo.isArray(_3)||_3 instanceof dojo.Color){
-_3={color:_3};
-}
-var s=this.strokeStyle=dojox.gfx.makeParameters(dojox.gfx.defaultStroke,_3);
-s.color=dojox.gfx.normalizeColor(s.color);
-return this;
-},setTransform:function(_4){
-this.matrix=dojox.gfx.matrix.clone(_4?dojox.gfx.matrix.normalize(_4):dojox.gfx.matrix.identity);
-return this._applyTransform();
-},_applyTransform:function(){
-return this;
-},moveToFront:function(){
-var p=this.getParent();
-if(p){
-p._moveChildToFront(this);
-this._moveToFront();
-}
-return this;
-},moveToBack:function(){
-var p=this.getParent();
-if(p){
-p._moveChildToBack(this);
-this._moveToBack();
-}
-return this;
-},_moveToFront:function(){
-},_moveToBack:function(){
-},applyRightTransform:function(_5){
-return _5?this.setTransform([this.matrix,_5]):this;
-},applyLeftTransform:function(_6){
-return _6?this.setTransform([_6,this.matrix]):this;
-},applyTransform:function(_7){
-return _7?this.setTransform([this.matrix,_7]):this;
-},removeShape:function(_8){
-if(this.parent){
-this.parent.remove(this,_8);
-}
-return this;
-},_setParent:function(_9,_a){
-this.parent=_9;
-return this._updateParentMatrix(_a);
-},_updateParentMatrix:function(_b){
-this.parentMatrix=_b?dojox.gfx.matrix.clone(_b):null;
-return this._applyTransform();
-},_getRealMatrix:function(){
-var m=this.matrix;
-var p=this.parent;
-while(p){
-if(p.matrix){
-m=dojox.gfx.matrix.multiply(p.matrix,m);
-}
-p=p.parent;
-}
-return m;
-}});
-dojox.gfx.shape._eventsProcessing={connect:function(_c,_d,_e){
-return arguments.length>2?dojo.connect(this.getEventSource(),_c,_d,_e):dojo.connect(this.getEventSource(),_c,_d);
-},disconnect:function(_f){
-dojo.disconnect(_f);
-}};
-dojo.extend(dojox.gfx.Shape,dojox.gfx.shape._eventsProcessing);
-dojox.gfx.shape.Container={_init:function(){
-this.children=[];
-},add:function(_10){
-var _11=_10.getParent();
-if(_11){
-_11.remove(_10,true);
-}
-this.children.push(_10);
-return _10._setParent(this,this._getRealMatrix());
-},remove:function(_12,_13){
-for(var i=0;i<this.children.length;++i){
-if(this.children[i]==_12){
-if(_13){
-}else{
-_12.parent=null;
-_12.parentMatrix=null;
-}
-this.children.splice(i,1);
-break;
-}
-}
-return this;
-},clear:function(){
-this.children=[];
-return this;
-},_moveChildToFront:function(_14){
-for(var i=0;i<this.children.length;++i){
-if(this.children[i]==_14){
-this.children.splice(i,1);
-this.children.push(_14);
-break;
-}
-}
-return this;
-},_moveChildToBack:function(_15){
-for(var i=0;i<this.children.length;++i){
-if(this.children[i]==_15){
-this.children.splice(i,1);
-this.children.unshift(_15);
-break;
-}
-}
-return this;
-}};
-dojo.declare("dojox.gfx.shape.Surface",null,{constructor:function(){
-this.rawNode=null;
-this._parent=null;
-this._nodes=[];
-this._events=[];
-},destroy:function(){
-dojo.forEach(this._nodes,dojo.destroy);
-this._nodes=[];
-dojo.forEach(this._events,dojo.disconnect);
-this._events=[];
-this.rawNode=null;
-if(dojo.isIE){
-while(this._parent.lastChild){
-dojo.destroy(this._parent.lastChild);
-}
-}else{
-this._parent.innerHTML="";
-}
-this._parent=null;
-},getEventSource:function(){
-return this.rawNode;
-},_getRealMatrix:function(){
-return null;
-},isLoaded:true,onLoad:function(_16){
-},whenLoaded:function(_17,_18){
-var f=dojo.hitch(_17,_18);
-if(this.isLoaded){
-f(this);
-}else{
-var h=dojo.connect(this,"onLoad",function(_19){
-dojo.disconnect(h);
-f(_19);
+
+dojo.declare("dojox.gfx.Shape", null, {
+	// summary: a Shape object, which knows how to apply
+	// graphical attributes and transformations
+
+	constructor: function(){
+		// rawNode: Node: underlying node
+		this.rawNode = null;
+
+		// shape: Object: an abstract shape object
+		//	(see dojox.gfx.defaultPath,
+		//	dojox.gfx.defaultPolyline,
+		//	dojox.gfx.defaultRect,
+		//	dojox.gfx.defaultEllipse,
+		//	dojox.gfx.defaultCircle,
+		//	dojox.gfx.defaultLine,
+		//	or dojox.gfx.defaultImage)
+		this.shape = null;
+
+		// matrix: dojox.gfx.Matrix2D: a transformation matrix
+		this.matrix = null;
+
+		// fillStyle: Object: a fill object
+		//	(see dojox.gfx.defaultLinearGradient,
+		//	dojox.gfx.defaultRadialGradient,
+		//	dojox.gfx.defaultPattern,
+		//	or dojo.Color)
+		this.fillStyle = null;
+
+		// strokeStyle: Object: a stroke object
+		//	(see dojox.gfx.defaultStroke)
+		this.strokeStyle = null;
+
+		// bbox: dojox.gfx.Rectangle: a bounding box of this shape
+		//	(see dojox.gfx.defaultRect)
+		this.bbox = null;
+
+		// virtual group structure
+
+		// parent: Object: a parent or null
+		//	(see dojox.gfx.Surface,
+		//	dojox.gfx.shape.VirtualGroup,
+		//	or dojox.gfx.Group)
+		this.parent = null;
+
+		// parentMatrix: dojox.gfx.Matrix2D
+		//	a transformation matrix inherited from the parent
+		this.parentMatrix = null;
+	},
+
+	// trivial getters
+
+	getNode: function(){
+		// summary: returns the current DOM Node or null
+		return this.rawNode; // Node
+	},
+	getShape: function(){
+		// summary: returns the current shape object or null
+		//	(see dojox.gfx.defaultPath,
+		//	dojox.gfx.defaultPolyline,
+		//	dojox.gfx.defaultRect,
+		//	dojox.gfx.defaultEllipse,
+		//	dojox.gfx.defaultCircle,
+		//	dojox.gfx.defaultLine,
+		//	or dojox.gfx.defaultImage)
+		return this.shape; // Object
+	},
+	getTransform: function(){
+		// summary: returns the current transformation matrix or null
+		return this.matrix;	// dojox.gfx.Matrix2D
+	},
+	getFill: function(){
+		// summary: returns the current fill object or null
+		//	(see dojox.gfx.defaultLinearGradient,
+		//	dojox.gfx.defaultRadialGradient,
+		//	dojox.gfx.defaultPattern,
+		//	or dojo.Color)
+		return this.fillStyle;	// Object
+	},
+	getStroke: function(){
+		// summary: returns the current stroke object or null
+		//	(see dojox.gfx.defaultStroke)
+		return this.strokeStyle;	// Object
+	},
+	getParent: function(){
+		// summary: returns the parent or null
+		//	(see dojox.gfx.Surface,
+		//	dojox.gfx.shape.VirtualGroup,
+		//	or dojox.gfx.Group)
+		return this.parent;	// Object
+	},
+	getBoundingBox: function(){
+		// summary: returns the bounding box or null
+		//	(see dojox.gfx.defaultRect)
+		return this.bbox;	// dojox.gfx.Rectangle
+	},
+	getTransformedBoundingBox: function(){
+		// summary: returns an array of four points or null
+		//	four points represent four corners of the untransformed bounding box
+		var b = this.getBoundingBox();
+		if(!b){
+			return null;	// null
+		}
+		var m = this._getRealMatrix();
+			gm = dojox.gfx.matrix;
+		return [	// Array
+				gm.multiplyPoint(m, b.x, b.y),
+				gm.multiplyPoint(m, b.x + b.width, b.y),
+				gm.multiplyPoint(m, b.x + b.width, b.y + b.height),
+				gm.multiplyPoint(m, b.x, b.y + b.height)
+			];
+	},
+	getEventSource: function(){
+		// summary: returns a Node, which is used as
+		//	a source of events for this shape
+
+		// COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+		return this.rawNode;	// Node
+	},
+
+	// empty settings
+
+	setShape: function(shape){
+		// summary: sets a shape object
+		//	(the default implementation simply ignores it)
+		// shape: Object: a shape object
+		//	(see dojox.gfx.defaultPath,
+		//	dojox.gfx.defaultPolyline,
+		//	dojox.gfx.defaultRect,
+		//	dojox.gfx.defaultEllipse,
+		//	dojox.gfx.defaultCircle,
+		//	dojox.gfx.defaultLine,
+		//	or dojox.gfx.defaultImage)
+
+		// COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+		this.shape = dojox.gfx.makeParameters(this.shape, shape);
+		this.bbox = null;
+		return this;	// self
+	},
+	setFill: function(fill){
+		// summary: sets a fill object
+		//	(the default implementation simply ignores it)
+		// fill: Object: a fill object
+		//	(see dojox.gfx.defaultLinearGradient,
+		//	dojox.gfx.defaultRadialGradient,
+		//	dojox.gfx.defaultPattern,
+		//	or dojo.Color)
+
+		// COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+		if(!fill){
+			// don't fill
+			this.fillStyle = null;
+			return this;	// self
+		}
+		var f = null;
+		if(typeof(fill) == "object" && "type" in fill){
+			// gradient or pattern
+			switch(fill.type){
+				case "linear":
+					f = dojox.gfx.makeParameters(dojox.gfx.defaultLinearGradient, fill);
+					break;
+				case "radial":
+					f = dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient, fill);
+					break;
+				case "pattern":
+					f = dojox.gfx.makeParameters(dojox.gfx.defaultPattern, fill);
+					break;
+			}
+		}else{
+			// color object
+			f = dojox.gfx.normalizeColor(fill);
+		}
+		this.fillStyle = f;
+		return this;	// self
+	},
+	setStroke: function(stroke){
+		// summary: sets a stroke object
+		//	(the default implementation simply ignores it)
+		// stroke: Object: a stroke object
+		//	(see dojox.gfx.defaultStroke)
+
+		// COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+		if(!stroke){
+			// don't stroke
+			this.strokeStyle = null;
+			return this;	// self
+		}
+		// normalize the stroke
+		if(typeof stroke == "string" || dojo.isArray(stroke) || stroke instanceof dojo.Color){
+			stroke = {color: stroke};
+		}
+		var s = this.strokeStyle = dojox.gfx.makeParameters(dojox.gfx.defaultStroke, stroke);
+		s.color = dojox.gfx.normalizeColor(s.color);
+		return this;	// self
+	},
+	setTransform: function(matrix){
+		// summary: sets a transformation matrix
+		// matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx.Matrix2D
+		//	constructor for a list of acceptable arguments)
+
+		// COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+		this.matrix = dojox.gfx.matrix.clone(matrix ? dojox.gfx.matrix.normalize(matrix) : dojox.gfx.matrix.identity);
+		return this._applyTransform();	// self
+	},
+
+	_applyTransform: function(){
+		// summary: physically sets a matrix
+
+		// COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+		return this;	// self
+	},
+
+	// z-index
+
+	moveToFront: function(){
+		// summary: moves a shape to front of its parent's list of shapes
+		var p = this.getParent();
+		if(p){
+			p._moveChildToFront(this);
+			this._moveToFront();	// execute renderer-specific action
+		}
+		return this;	// self
+	},
+	moveToBack: function(){
+		// summary: moves a shape to back of its parent's list of shapes
+		var p = this.getParent();
+		if(p){
+			p._moveChildToBack(this);
+			this._moveToBack();	// execute renderer-specific action
+		}
+		return this;
+	},
+	_moveToFront: function(){
+		// summary: renderer-specific hook, see dojox.gfx.shape.Shape.moveToFront()
+
+		// COULD BE RE-IMPLEMENTED BY THE RENDERER!
+	},
+	_moveToBack: function(){
+		// summary: renderer-specific hook, see dojox.gfx.shape.Shape.moveToFront()
+
+		// COULD BE RE-IMPLEMENTED BY THE RENDERER!
+	},
+
+	// apply left & right transformation
+
+	applyRightTransform: function(matrix){
+		// summary: multiplies the existing matrix with an argument on right side
+		//	(this.matrix * matrix)
+		// matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx.Matrix2D
+		//	constructor for a list of acceptable arguments)
+		return matrix ? this.setTransform([this.matrix, matrix]) : this;	// self
+	},
+	applyLeftTransform: function(matrix){
+		// summary: multiplies the existing matrix with an argument on left side
+		//	(matrix * this.matrix)
+		// matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx.Matrix2D
+		//	constructor for a list of acceptable arguments)
+		return matrix ? this.setTransform([matrix, this.matrix]) : this;	// self
+	},
+	applyTransform: function(matrix){
+		// summary: a shortcut for dojox.gfx.Shape.applyRightTransform
+		// matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx.Matrix2D
+		//	constructor for a list of acceptable arguments)
+		return matrix ? this.setTransform([this.matrix, matrix]) : this;	// self
+	},
+
+	// virtual group methods
+
+	removeShape: function(silently){
+		// summary: removes the shape from its parent's list of shapes
+		// silently: Boolean?: if true, do not redraw a picture yet
+		if(this.parent){
+			this.parent.remove(this, silently);
+		}
+		return this;	// self
+	},
+	_setParent: function(parent, matrix){
+		// summary: sets a parent
+		// parent: Object: a parent or null
+		//	(see dojox.gfx.Surface,
+		//	dojox.gfx.shape.VirtualGroup,
+		//	or dojox.gfx.Group)
+		// matrix: dojox.gfx.Matrix2D:
+		//	a 2D matrix or a matrix-like object
+		this.parent = parent;
+		return this._updateParentMatrix(matrix);	// self
+	},
+	_updateParentMatrix: function(matrix){
+		// summary: updates the parent matrix with new matrix
+		// matrix: dojox.gfx.Matrix2D:
+		//	a 2D matrix or a matrix-like object
+		this.parentMatrix = matrix ? dojox.gfx.matrix.clone(matrix) : null;
+		return this._applyTransform();	// self
+	},
+	_getRealMatrix: function(){
+		// summary: returns the cumulative ("real") transformation matrix
+		//	by combining the shape's matrix with its parent's matrix
+		var m = this.matrix;
+		var p = this.parent;
+		while(p){
+			if(p.matrix){
+				m = dojox.gfx.matrix.multiply(p.matrix, m);
+			}
+			p = p.parent;
+		}
+		return m;	// dojox.gfx.Matrix2D
+	}
 });
-}
-}});
-dojo.extend(dojox.gfx.shape.Surface,dojox.gfx.shape._eventsProcessing);
-dojo.declare("dojox.gfx.Point",null,{});
-dojo.declare("dojox.gfx.Rectangle",null,{});
-dojo.declare("dojox.gfx.shape.Rect",dojox.gfx.Shape,{constructor:function(_1a){
-this.shape=dojox.gfx.getDefault("Rect");
-this.rawNode=_1a;
-},getBoundingBox:function(){
-return this.shape;
-}});
-dojo.declare("dojox.gfx.shape.Ellipse",dojox.gfx.Shape,{constructor:function(_1b){
-this.shape=dojox.gfx.getDefault("Ellipse");
-this.rawNode=_1b;
-},getBoundingBox:function(){
-if(!this.bbox){
-var _1c=this.shape;
-this.bbox={x:_1c.cx-_1c.rx,y:_1c.cy-_1c.ry,width:2*_1c.rx,height:2*_1c.ry};
-}
-return this.bbox;
-}});
-dojo.declare("dojox.gfx.shape.Circle",dojox.gfx.Shape,{constructor:function(_1d){
-this.shape=dojox.gfx.getDefault("Circle");
-this.rawNode=_1d;
-},getBoundingBox:function(){
-if(!this.bbox){
-var _1e=this.shape;
-this.bbox={x:_1e.cx-_1e.r,y:_1e.cy-_1e.r,width:2*_1e.r,height:2*_1e.r};
-}
-return this.bbox;
-}});
-dojo.declare("dojox.gfx.shape.Line",dojox.gfx.Shape,{constructor:function(_1f){
-this.shape=dojox.gfx.getDefault("Line");
-this.rawNode=_1f;
-},getBoundingBox:function(){
-if(!this.bbox){
-var _20=this.shape;
-this.bbox={x:Math.min(_20.x1,_20.x2),y:Math.min(_20.y1,_20.y2),width:Math.abs(_20.x2-_20.x1),height:Math.abs(_20.y2-_20.y1)};
-}
-return this.bbox;
-}});
-dojo.declare("dojox.gfx.shape.Polyline",dojox.gfx.Shape,{constructor:function(_21){
-this.shape=dojox.gfx.getDefault("Polyline");
-this.rawNode=_21;
-},setShape:function(_22,_23){
-if(_22&&_22 instanceof Array){
-dojox.gfx.Shape.prototype.setShape.call(this,{points:_22});
-if(_23&&this.shape.points.length){
-this.shape.points.push(this.shape.points[0]);
-}
-}else{
-dojox.gfx.Shape.prototype.setShape.call(this,_22);
-}
-return this;
-},_normalizePoints:function(){
-var p=this.shape.points,l=p&&p.length;
-if(l&&typeof p[0]=="number"){
-var _24=[];
-for(var i=0;i<l;i+=2){
-_24.push({x:p[i],y:p[i+1]});
-}
-this.shape.points=_24;
-}
-},getBoundingBox:function(){
-if(!this.bbox&&this.shape.points.length){
-var p=this.shape.points;
-var l=p.length;
-var t=p[0];
-var _25={l:t.x,t:t.y,r:t.x,b:t.y};
-for(var i=1;i<l;++i){
-t=p[i];
-if(_25.l>t.x){
-_25.l=t.x;
-}
-if(_25.r<t.x){
-_25.r=t.x;
-}
-if(_25.t>t.y){
-_25.t=t.y;
-}
-if(_25.b<t.y){
-_25.b=t.y;
-}
-}
-this.bbox={x:_25.l,y:_25.t,width:_25.r-_25.l,height:_25.b-_25.t};
-}
-return this.bbox;
-}});
-dojo.declare("dojox.gfx.shape.Image",dojox.gfx.Shape,{constructor:function(_26){
-this.shape=dojox.gfx.getDefault("Image");
-this.rawNode=_26;
-},getBoundingBox:function(){
-return this.shape;
-},setStroke:function(){
-return this;
-},setFill:function(){
-return this;
-}});
-dojo.declare("dojox.gfx.shape.Text",dojox.gfx.Shape,{constructor:function(_27){
-this.fontStyle=null;
-this.shape=dojox.gfx.getDefault("Text");
-this.rawNode=_27;
-},getFont:function(){
-return this.fontStyle;
-},setFont:function(_28){
-this.fontStyle=typeof _28=="string"?dojox.gfx.splitFontString(_28):dojox.gfx.makeParameters(dojox.gfx.defaultFont,_28);
-this._setFont();
-return this;
-}});
-dojox.gfx.shape.Creator={createShape:function(_29){
-var gfx=dojox.gfx;
-switch(_29.type){
-case gfx.defaultPath.type:
-return this.createPath(_29);
-case gfx.defaultRect.type:
-return this.createRect(_29);
-case gfx.defaultCircle.type:
-return this.createCircle(_29);
-case gfx.defaultEllipse.type:
-return this.createEllipse(_29);
-case gfx.defaultLine.type:
-return this.createLine(_29);
-case gfx.defaultPolyline.type:
-return this.createPolyline(_29);
-case gfx.defaultImage.type:
-return this.createImage(_29);
-case gfx.defaultText.type:
-return this.createText(_29);
-case gfx.defaultTextPath.type:
-return this.createTextPath(_29);
-}
-return null;
-},createGroup:function(){
-return this.createObject(dojox.gfx.Group);
-},createRect:function(_2a){
-return this.createObject(dojox.gfx.Rect,_2a);
-},createEllipse:function(_2b){
-return this.createObject(dojox.gfx.Ellipse,_2b);
-},createCircle:function(_2c){
-return this.createObject(dojox.gfx.Circle,_2c);
-},createLine:function(_2d){
-return this.createObject(dojox.gfx.Line,_2d);
-},createPolyline:function(_2e){
-return this.createObject(dojox.gfx.Polyline,_2e);
-},createImage:function(_2f){
-return this.createObject(dojox.gfx.Image,_2f);
-},createText:function(_30){
-return this.createObject(dojox.gfx.Text,_30);
-},createPath:function(_31){
-return this.createObject(dojox.gfx.Path,_31);
-},createTextPath:function(_32){
-return this.createObject(dojox.gfx.TextPath,{}).setText(_32);
-},createObject:function(_33,_34){
-return null;
-}};
-}
+
+dojox.gfx.shape._eventsProcessing = {
+	connect: function(name, object, method){
+		// summary: connects a handler to an event on this shape
+
+		// COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+		return arguments.length > 2 ?	// Object
+			dojo.connect(this.getEventSource(), name, object, method) :
+			dojo.connect(this.getEventSource(), name, object);
+	},
+	disconnect: function(token){
+		// summary: connects a handler by token from an event on this shape
+
+		// COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+		dojo.disconnect(token);
+	}
+};
+
+dojo.extend(dojox.gfx.Shape, dojox.gfx.shape._eventsProcessing);
+
+dojox.gfx.shape.Container = {
+	// summary: a container of shapes, which can be used
+	//	as a foundation for renderer-specific groups, or as a way
+	//	to logically group shapes (e.g, to propagate matricies)
+
+	_init: function() {
+		// children: Array: a list of children
+		this.children = [];
+	},
+
+	// group management
+
+	openBatch: function() {
+		// summary: starts a new batch, subsequent new child shapes will be held in
+		//	the batch instead of appending to the container directly
+	},
+	closeBatch: function() {
+		// summary: submits the current batch, append all pending child shapes to DOM
+	},
+	add: function(shape){
+		// summary: adds a shape to the list
+		// shape: dojox.gfx.Shape: a shape
+		var oldParent = shape.getParent();
+		if(oldParent){
+			oldParent.remove(shape, true);
+		}
+		this.children.push(shape);
+		return shape._setParent(this, this._getRealMatrix());	// self
+	},
+	remove: function(shape, silently){
+		// summary: removes a shape from the list
+		// silently: Boolean?: if true, do not redraw a picture yet
+		for(var i = 0; i < this.children.length; ++i){
+			if(this.children[i] == shape){
+				if(silently){
+					// skip for now
+				}else{
+					shape.parent = null;
+					shape.parentMatrix = null;
+				}
+				this.children.splice(i, 1);
+				break;
+			}
+		}
+		return this;	// self
+	},
+	clear: function(){
+		// summary: removes all shapes from a group/surface
+		this.children = [];
+		return this;	// self
+	},
+
+	// moving child nodes
+
+	_moveChildToFront: function(shape){
+		// summary: moves a shape to front of the list of shapes
+		for(var i = 0; i < this.children.length; ++i){
+			if(this.children[i] == shape){
+				this.children.splice(i, 1);
+				this.children.push(shape);
+				break;
+			}
+		}
+		return this;	// self
+	},
+	_moveChildToBack: function(shape){
+		// summary: moves a shape to back of the list of shapes
+		for(var i = 0; i < this.children.length; ++i){
+			if(this.children[i] == shape){
+				this.children.splice(i, 1);
+				this.children.unshift(shape);
+				break;
+			}
+		}
+		return this;	// self
+	}
+};
+
+dojo.declare("dojox.gfx.shape.Surface", null, {
+	// summary: a surface object to be used for drawings
+	constructor: function(){
+		// underlying node
+		this.rawNode = null;
+		// the parent node
+		this._parent = null;
+		// the list of DOM nodes to be deleted in the case of destruction
+		this._nodes = [];
+		// the list of events to be detached in the case of destruction
+		this._events = [];
+	},
+	destroy: function(){
+		// summary: destroy all relevant external resources and release all
+		//	external references to make this object garbage-collectible
+		dojo.forEach(this._nodes, dojo.destroy);
+		this._nodes = [];
+		dojo.forEach(this._events, dojo.disconnect);
+		this._events = [];
+		this.rawNode = null;	// recycle it in _nodes, if it needs to be recycled
+		if(dojo.isIE){
+			while(this._parent.lastChild){
+				dojo.destroy(this._parent.lastChild);
+			}
+		}else{
+			this._parent.innerHTML = "";
+		}
+		this._parent = null;
+	},
+	getEventSource: function(){
+		// summary: returns a node, which can be used to attach event listeners
+		return this.rawNode; // Node
+	},
+	_getRealMatrix: function(){
+		// summary: always returns the identity matrix
+		return null;	// dojox.gfx.Matrix2D
+	},
+	isLoaded: true,
+	onLoad: function(/*dojox.gfx.Surface*/ surface){
+		// summary: local event, fired once when the surface is created
+		// asynchronously, used only when isLoaded is false, required
+		// only for Silverlight.
+	},
+	whenLoaded: function(
+		/*Object?*/ context,
+		/*Function|String*/ method
+	){
+		var f = dojo.hitch(context, method);
+		if(this.isLoaded){
+			f(this);
+		}else{
+			var h = dojo.connect(this, "onLoad", function(surface){
+				dojo.disconnect(h);
+				f(surface);
+			});
+		}
+	}
+});
+
+dojo.extend(dojox.gfx.shape.Surface, dojox.gfx.shape._eventsProcessing);
+
+dojo.declare("dojox.gfx.Point", null, {
+	// summary: a hypothetical 2D point to be used for drawings - {x, y}
+	// description: This object is defined for documentation purposes.
+	//	You should use the naked object instead: {x: 1, y: 2}.
+});
+
+dojo.declare("dojox.gfx.Rectangle", null, {
+	// summary: a hypothetical rectangle - {x, y, width, height}
+	// description: This object is defined for documentation purposes.
+	//	You should use the naked object instead: {x: 1, y: 2, width: 100, height: 200}.
+});
+
+dojo.declare("dojox.gfx.shape.Rect", dojox.gfx.Shape, {
+	// summary: a generic rectangle
+	constructor: function(rawNode){
+		// rawNode: Node: a DOM Node
+		this.shape = dojox.gfx.getDefault("Rect");
+		this.rawNode = rawNode;
+	},
+	getBoundingBox: function(){
+		// summary: returns the bounding box (its shape in this case)
+		return this.shape;	// dojox.gfx.Rectangle
+	}
+});
+
+dojo.declare("dojox.gfx.shape.Ellipse", dojox.gfx.Shape, {
+	// summary: a generic ellipse
+	constructor: function(rawNode){
+		// rawNode: Node: a DOM Node
+		this.shape = dojox.gfx.getDefault("Ellipse");
+		this.rawNode = rawNode;
+	},
+	getBoundingBox: function(){
+		// summary: returns the bounding box
+		if(!this.bbox){
+			var shape = this.shape;
+			this.bbox = {x: shape.cx - shape.rx, y: shape.cy - shape.ry,
+				width: 2 * shape.rx, height: 2 * shape.ry};
+		}
+		return this.bbox;	// dojox.gfx.Rectangle
+	}
+});
+
+dojo.declare("dojox.gfx.shape.Circle", dojox.gfx.Shape, {
+	// summary: a generic circle
+	//	(this is a helper object, which is defined for convenience)
+	constructor: function(rawNode){
+		// rawNode: Node: a DOM Node
+		this.shape = dojox.gfx.getDefault("Circle");
+		this.rawNode = rawNode;
+	},
+	getBoundingBox: function(){
+		// summary: returns the bounding box
+		if(!this.bbox){
+			var shape = this.shape;
+			this.bbox = {x: shape.cx - shape.r, y: shape.cy - shape.r,
+				width: 2 * shape.r, height: 2 * shape.r};
+		}
+		return this.bbox;	// dojox.gfx.Rectangle
+	}
+});
+
+dojo.declare("dojox.gfx.shape.Line", dojox.gfx.Shape, {
+	// summary: a generic line
+	//	(this is a helper object, which is defined for convenience)
+	constructor: function(rawNode){
+		// rawNode: Node: a DOM Node
+		this.shape = dojox.gfx.getDefault("Line");
+		this.rawNode = rawNode;
+	},
+	getBoundingBox: function(){
+		// summary: returns the bounding box
+		if(!this.bbox){
+			var shape = this.shape;
+			this.bbox = {
+				x:		Math.min(shape.x1, shape.x2),
+				y:		Math.min(shape.y1, shape.y2),
+				width:	Math.abs(shape.x2 - shape.x1),
+				height:	Math.abs(shape.y2 - shape.y1)
+			};
+		}
+		return this.bbox;	// dojox.gfx.Rectangle
+	}
+});
+
+dojo.declare("dojox.gfx.shape.Polyline", dojox.gfx.Shape, {
+	// summary: a generic polyline/polygon
+	//	(this is a helper object, which is defined for convenience)
+	constructor: function(rawNode){
+		// rawNode: Node: a DOM Node
+		this.shape = dojox.gfx.getDefault("Polyline");
+		this.rawNode = rawNode;
+	},
+	setShape: function(points, closed){
+		// summary: sets a polyline/polygon shape object
+		// points: Object: a polyline/polygon shape object
+		// closed: Boolean: close the polyline to make a polygon
+		if(points && points instanceof Array){
+			// points: Array: an array of points
+			dojox.gfx.Shape.prototype.setShape.call(this, {points: points});
+			if(closed && this.shape.points.length){
+				this.shape.points.push(this.shape.points[0]);
+			}
+		}else{
+			dojox.gfx.Shape.prototype.setShape.call(this, points);
+		}
+		return this;	// self
+	},
+	_normalizePoints: function(){
+		// summary: normalize points to array of {x:number, y:number}
+		var p = this.shape.points, l = p && p.length;
+		if(l && typeof p[0] == "number"){
+			var points = [];
+			for(var i = 0; i < l; i += 2){
+				points.push({x: p[i], y: p[i + 1]});
+			}
+			this.shape.points = points;
+		}
+	},
+	getBoundingBox: function(){
+		// summary: returns the bounding box
+		if(!this.bbox && this.shape.points.length){
+			var p = this.shape.points;
+			var l = p.length;
+			var t = p[0];
+			var bbox = {l: t.x, t: t.y, r: t.x, b: t.y};
+			for(var i = 1; i < l; ++i){
+				t = p[i];
+				if(bbox.l > t.x) bbox.l = t.x;
+				if(bbox.r < t.x) bbox.r = t.x;
+				if(bbox.t > t.y) bbox.t = t.y;
+				if(bbox.b < t.y) bbox.b = t.y;
+			}
+			this.bbox = {
+				x:		bbox.l,
+				y:		bbox.t,
+				width:	bbox.r - bbox.l,
+				height:	bbox.b - bbox.t
+			};
+		}
+		return this.bbox;	// dojox.gfx.Rectangle
+	}
+});
+
+dojo.declare("dojox.gfx.shape.Image", dojox.gfx.Shape, {
+	// summary: a generic image
+	//	(this is a helper object, which is defined for convenience)
+	constructor: function(rawNode){
+		// rawNode: Node: a DOM Node
+		this.shape = dojox.gfx.getDefault("Image");
+		this.rawNode = rawNode;
+	},
+	getBoundingBox: function(){
+		// summary: returns the bounding box (its shape in this case)
+		return this.shape;	// dojox.gfx.Rectangle
+	},
+	setStroke: function(){
+		// summary: ignore setting a stroke style
+		return this;	// self
+	},
+	setFill: function(){
+		// summary: ignore setting a fill style
+		return this;	// self
+	}
+});
+
+dojo.declare("dojox.gfx.shape.Text", dojox.gfx.Shape, {
+	// summary: a generic text
+	constructor: function(rawNode){
+		// rawNode: Node: a DOM Node
+		this.fontStyle = null;
+		this.shape = dojox.gfx.getDefault("Text");
+		this.rawNode = rawNode;
+	},
+	getFont: function(){
+		// summary: returns the current font object or null
+		return this.fontStyle;	// Object
+	},
+	setFont: function(newFont){
+		// summary: sets a font for text
+		// newFont: Object: a font object (see dojox.gfx.defaultFont) or a font string
+		this.fontStyle = typeof newFont == "string" ? dojox.gfx.splitFontString(newFont) :
+			dojox.gfx.makeParameters(dojox.gfx.defaultFont, newFont);
+		this._setFont();
+		return this;	// self
+	}
+});
+
+dojox.gfx.shape.Creator = {
+	// summary: shape creators
+	createShape: function(shape){
+		// summary: creates a shape object based on its type; it is meant to be used
+		//	by group-like objects
+		// shape: Object: a shape descriptor object
+		var gfx = dojox.gfx;
+		switch(shape.type){
+			case gfx.defaultPath.type:		return this.createPath(shape);
+			case gfx.defaultRect.type:		return this.createRect(shape);
+			case gfx.defaultCircle.type:		return this.createCircle(shape);
+			case gfx.defaultEllipse.type:		return this.createEllipse(shape);
+			case gfx.defaultLine.type:		return this.createLine(shape);
+			case gfx.defaultPolyline.type:	return this.createPolyline(shape);
+			case gfx.defaultImage.type:		return this.createImage(shape);
+			case gfx.defaultText.type:		return this.createText(shape);
+			case gfx.defaultTextPath.type:	return this.createTextPath(shape);
+		}
+		return null;
+	},
+	createGroup: function(){
+		// summary: creates a group shape
+		return this.createObject(dojox.gfx.Group);	// dojox.gfx.Group
+	},
+	createRect: function(rect){
+		// summary: creates a rectangle shape
+		// rect: Object: a path object (see dojox.gfx.defaultRect)
+		return this.createObject(dojox.gfx.Rect, rect);	// dojox.gfx.Rect
+	},
+	createEllipse: function(ellipse){
+		// summary: creates an ellipse shape
+		// ellipse: Object: an ellipse object (see dojox.gfx.defaultEllipse)
+		return this.createObject(dojox.gfx.Ellipse, ellipse);	// dojox.gfx.Ellipse
+	},
+	createCircle: function(circle){
+		// summary: creates a circle shape
+		// circle: Object: a circle object (see dojox.gfx.defaultCircle)
+		return this.createObject(dojox.gfx.Circle, circle);	// dojox.gfx.Circle
+	},
+	createLine: function(line){
+		// summary: creates a line shape
+		// line: Object: a line object (see dojox.gfx.defaultLine)
+		return this.createObject(dojox.gfx.Line, line);	// dojox.gfx.Line
+	},
+	createPolyline: function(points){
+		// summary: creates a polyline/polygon shape
+		// points: Object: a points object (see dojox.gfx.defaultPolyline)
+		//	or an Array of points
+		return this.createObject(dojox.gfx.Polyline, points);	// dojox.gfx.Polyline
+	},
+	createImage: function(image){
+		// summary: creates a image shape
+		// image: Object: an image object (see dojox.gfx.defaultImage)
+		return this.createObject(dojox.gfx.Image, image);	// dojox.gfx.Image
+	},
+	createText: function(text){
+		// summary: creates a text shape
+		// text: Object: a text object (see dojox.gfx.defaultText)
+		return this.createObject(dojox.gfx.Text, text);	// dojox.gfx.Text
+	},
+	createPath: function(path){
+		// summary: creates a path shape
+		// path: Object: a path object (see dojox.gfx.defaultPath)
+		return this.createObject(dojox.gfx.Path, path);	// dojox.gfx.Path
+	},
+	createTextPath: function(text){
+		// summary: creates a text shape
+		// text: Object: a textpath object (see dojox.gfx.defaultTextPath)
+		return this.createObject(dojox.gfx.TextPath, {}).setText(text);	// dojox.gfx.TextPath
+	},
+	createObject: function(shapeType, rawShape){
+		// summary: creates an instance of the passed shapeType class
+		// shapeType: Function: a class constructor to create an instance of
+		// rawShape: Object: properties to be passed in to the classes "setShape" method
+
+		// SHOULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+		return null;	// dojox.gfx.Shape
+	}
+};
diff --git a/dojox/gfx/silverlight.js b/dojox/gfx/silverlight.js
index ab38466..589cbd7 100644
--- a/dojox/gfx/silverlight.js
+++ b/dojox/gfx/silverlight.js
@@ -1,506 +1,786 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.silverlight"]){
-dojo._hasResource["dojox.gfx.silverlight"]=true;
 dojo.provide("dojox.gfx.silverlight");
+
 dojo.require("dojox.gfx._base");
 dojo.require("dojox.gfx.shape");
 dojo.require("dojox.gfx.path");
+
 dojo.experimental("dojox.gfx.silverlight");
-dojox.gfx.silverlight.dasharray={solid:"none",shortdash:[4,1],shortdot:[1,1],shortdashdot:[4,1,1,1],shortdashdotdot:[4,1,1,1,1,1],dot:[1,3],dash:[4,3],longdash:[8,3],dashdot:[4,3,1,3],longdashdot:[8,3,1,3],longdashdotdot:[8,3,1,3,1,3]};
-dojox.gfx.silverlight.fontweight={normal:400,bold:700};
-dojox.gfx.silverlight.caps={butt:"Flat",round:"Round",square:"Square"};
-dojox.gfx.silverlight.joins={bevel:"Bevel",round:"Round"};
-dojox.gfx.silverlight.fonts={serif:"Times New Roman",times:"Times New Roman","sans-serif":"Arial",helvetica:"Arial",monotone:"Courier New",courier:"Courier New"};
-dojox.gfx.silverlight.hexColor=function(_1){
-var c=dojox.gfx.normalizeColor(_1),t=c.toHex(),a=Math.round(c.a*255);
-a=(a<0?0:a>255?255:a).toString(16);
-return "#"+(a.length<2?"0"+a:a)+t.slice(1);
+
+dojox.gfx.silverlight.dasharray = {
+	solid:				"none",
+	shortdash:			[4, 1],
+	shortdot:			[1, 1],
+	shortdashdot:		[4, 1, 1, 1],
+	shortdashdotdot:	[4, 1, 1, 1, 1, 1],
+	dot:				[1, 3],
+	dash:				[4, 3],
+	longdash:			[8, 3],
+	dashdot:			[4, 3, 1, 3],
+	longdashdot:		[8, 3, 1, 3],
+	longdashdotdot:		[8, 3, 1, 3, 1, 3]
 };
-dojo.extend(dojox.gfx.Shape,{setFill:function(_2){
-var p=this.rawNode.getHost().content,r=this.rawNode,f;
-if(!_2){
-this.fillStyle=null;
-this._setFillAttr(null);
-return this;
-}
-if(typeof (_2)=="object"&&"type" in _2){
-switch(_2.type){
-case "linear":
-this.fillStyle=f=dojox.gfx.makeParameters(dojox.gfx.defaultLinearGradient,_2);
-var _3=p.createFromXaml("<LinearGradientBrush/>");
-_3.mappingMode="Absolute";
-_3.startPoint=f.x1+","+f.y1;
-_3.endPoint=f.x2+","+f.y2;
-dojo.forEach(f.colors,function(c){
-var t=p.createFromXaml("<GradientStop/>");
-t.offset=c.offset;
-t.color=dojox.gfx.silverlight.hexColor(c.color);
-_3.gradientStops.add(t);
-});
-this._setFillAttr(_3);
-break;
-case "radial":
-this.fillStyle=f=dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient,_2);
-var _4=p.createFromXaml("<RadialGradientBrush/>"),c=dojox.gfx.matrix.multiplyPoint(dojox.gfx.matrix.invert(this._getAdjustedMatrix()),f.cx,f.cy),pt=c.x+","+c.y;
-_4.mappingMode="Absolute";
-_4.gradientOrigin=pt;
-_4.center=pt;
-_4.radiusX=_4.radiusY=f.r;
-dojo.forEach(f.colors,function(c){
-var t=p.createFromXaml("<GradientStop/>");
-t.offset=c.offset;
-t.color=dojox.gfx.silverlight.hexColor(c.color);
-_4.gradientStops.add(t);
-});
-this._setFillAttr(_4);
-break;
-case "pattern":
-this.fillStyle=null;
-this._setFillAttr(null);
-break;
-}
-return this;
-}
-this.fillStyle=f=dojox.gfx.normalizeColor(_2);
-var _5=p.createFromXaml("<SolidColorBrush/>");
-_5.color=f.toHex();
-_5.opacity=f.a;
-this._setFillAttr(_5);
-return this;
-},_setFillAttr:function(f){
-this.rawNode.fill=f;
-},setStroke:function(_6){
-var p=this.rawNode.getHost().content,r=this.rawNode;
-if(!_6){
-this.strokeStyle=null;
-r.stroke=null;
-return this;
-}
-if(typeof _6=="string"||dojo.isArray(_6)||_6 instanceof dojo.Color){
-_6={color:_6};
-}
-var s=this.strokeStyle=dojox.gfx.makeParameters(dojox.gfx.defaultStroke,_6);
-s.color=dojox.gfx.normalizeColor(s.color);
-if(s){
-var _7=p.createFromXaml("<SolidColorBrush/>");
-_7.color=s.color.toHex();
-_7.opacity=s.color.a;
-r.stroke=_7;
-r.strokeThickness=s.width;
-r.strokeStartLineCap=r.strokeEndLineCap=r.strokeDashCap=dojox.gfx.silverlight.caps[s.cap];
-if(typeof s.join=="number"){
-r.strokeLineJoin="Miter";
-r.strokeMiterLimit=s.join;
-}else{
-r.strokeLineJoin=dojox.gfx.silverlight.joins[s.join];
-}
-var da=s.style.toLowerCase();
-if(da in dojox.gfx.silverlight.dasharray){
-da=dojox.gfx.silverlight.dasharray[da];
-}
-if(da instanceof Array){
-da=dojo.clone(da);
-var i;
-if(s.cap!="butt"){
-for(i=0;i<da.length;i+=2){
---da[i];
-if(da[i]<1){
-da[i]=1;
-}
-}
-for(i=1;i<da.length;i+=2){
-++da[i];
-}
-}
-r.strokeDashArray=da.join(",");
-}else{
-r.strokeDashArray=null;
-}
-}
-return this;
-},_getParentSurface:function(){
-var _8=this.parent;
-for(;_8&&!(_8 instanceof dojox.gfx.Surface);_8=_8.parent){
-}
-return _8;
-},_applyTransform:function(){
-var tm=this._getAdjustedMatrix(),r=this.rawNode;
-if(tm){
-var p=this.rawNode.getHost().content,m=p.createFromXaml("<MatrixTransform/>"),mm=p.createFromXaml("<Matrix/>");
-mm.m11=tm.xx;
-mm.m21=tm.xy;
-mm.m12=tm.yx;
-mm.m22=tm.yy;
-mm.offsetX=tm.dx;
-mm.offsetY=tm.dy;
-m.matrix=mm;
-r.renderTransform=m;
-}else{
-r.renderTransform=null;
-}
-return this;
-},setRawNode:function(_9){
-_9.fill=null;
-_9.stroke=null;
-this.rawNode=_9;
-},_moveToFront:function(){
-var c=this.parent.rawNode.children,r=this.rawNode;
-c.remove(r);
-c.add(r);
-return this;
-},_moveToBack:function(){
-var c=this.parent.rawNode.children,r=this.rawNode;
-c.remove(r);
-c.insert(0,r);
-return this;
-},_getAdjustedMatrix:function(){
-return this.matrix;
-}});
-dojo.declare("dojox.gfx.Group",dojox.gfx.Shape,{constructor:function(){
-dojox.gfx.silverlight.Container._init.call(this);
-},setRawNode:function(_a){
-this.rawNode=_a;
-}});
-dojox.gfx.Group.nodeType="Canvas";
-dojo.declare("dojox.gfx.Rect",dojox.gfx.shape.Rect,{setShape:function(_b){
-this.shape=dojox.gfx.makeParameters(this.shape,_b);
-this.bbox=null;
-var r=this.rawNode,n=this.shape;
-r.width=n.width;
-r.height=n.height;
-r.radiusX=r.radiusY=n.r;
-return this._applyTransform();
-},_getAdjustedMatrix:function(){
-var m=this.matrix,s=this.shape,d={dx:s.x,dy:s.y};
-return new dojox.gfx.Matrix2D(m?[m,d]:d);
-}});
-dojox.gfx.Rect.nodeType="Rectangle";
-dojo.declare("dojox.gfx.Ellipse",dojox.gfx.shape.Ellipse,{setShape:function(_c){
-this.shape=dojox.gfx.makeParameters(this.shape,_c);
-this.bbox=null;
-var r=this.rawNode,n=this.shape;
-r.width=2*n.rx;
-r.height=2*n.ry;
-return this._applyTransform();
-},_getAdjustedMatrix:function(){
-var m=this.matrix,s=this.shape,d={dx:s.cx-s.rx,dy:s.cy-s.ry};
-return new dojox.gfx.Matrix2D(m?[m,d]:d);
-}});
-dojox.gfx.Ellipse.nodeType="Ellipse";
-dojo.declare("dojox.gfx.Circle",dojox.gfx.shape.Circle,{setShape:function(_d){
-this.shape=dojox.gfx.makeParameters(this.shape,_d);
-this.bbox=null;
-var r=this.rawNode,n=this.shape;
-r.width=r.height=2*n.r;
-return this._applyTransform();
-},_getAdjustedMatrix:function(){
-var m=this.matrix,s=this.shape,d={dx:s.cx-s.r,dy:s.cy-s.r};
-return new dojox.gfx.Matrix2D(m?[m,d]:d);
-}});
-dojox.gfx.Circle.nodeType="Ellipse";
-dojo.declare("dojox.gfx.Line",dojox.gfx.shape.Line,{setShape:function(_e){
-this.shape=dojox.gfx.makeParameters(this.shape,_e);
-this.bbox=null;
-var r=this.rawNode,n=this.shape;
-r.x1=n.x1;
-r.y1=n.y1;
-r.x2=n.x2;
-r.y2=n.y2;
-return this;
-}});
-dojox.gfx.Line.nodeType="Line";
-dojo.declare("dojox.gfx.Polyline",dojox.gfx.shape.Polyline,{setShape:function(_f,_10){
-if(_f&&_f instanceof Array){
-this.shape=dojox.gfx.makeParameters(this.shape,{points:_f});
-if(_10&&this.shape.points.length){
-this.shape.points.push(this.shape.points[0]);
-}
-}else{
-this.shape=dojox.gfx.makeParameters(this.shape,_f);
-}
-this.bbox=null;
-this._normalizePoints();
-var p=this.shape.points,rp=[];
-for(var i=0;i<p.length;++i){
-rp.push(p[i].x,p[i].y);
-}
-this.rawNode.points=rp.join(",");
-return this;
-}});
-dojox.gfx.Polyline.nodeType="Polyline";
-dojo.declare("dojox.gfx.Image",dojox.gfx.shape.Image,{setShape:function(_11){
-this.shape=dojox.gfx.makeParameters(this.shape,_11);
-this.bbox=null;
-var r=this.rawNode,n=this.shape;
-r.width=n.width;
-r.height=n.height;
-r.source=n.src;
-return this._applyTransform();
-},_getAdjustedMatrix:function(){
-var m=this.matrix,s=this.shape,d={dx:s.x,dy:s.y};
-return new dojox.gfx.Matrix2D(m?[m,d]:d);
-},setRawNode:function(_12){
-this.rawNode=_12;
-}});
-dojox.gfx.Image.nodeType="Image";
-dojo.declare("dojox.gfx.Text",dojox.gfx.shape.Text,{setShape:function(_13){
-this.shape=dojox.gfx.makeParameters(this.shape,_13);
-this.bbox=null;
-var r=this.rawNode,s=this.shape;
-r.text=s.text;
-r.textDecorations=s.decoration==="underline"?"Underline":"None";
-r["Canvas.Left"]=-10000;
-r["Canvas.Top"]=-10000;
-if(!this._delay){
-this._delay=window.setTimeout(dojo.hitch(this,"_delayAlignment"),10);
-}
-return this;
-},_delayAlignment:function(){
-var r=this.rawNode,s=this.shape,w=r.actualWidth,h=r.actualHeight,x=s.x,y=s.y-h*0.75;
-switch(s.align){
-case "middle":
-x-=w/2;
-break;
-case "end":
-x-=w;
-break;
-}
-this._delta={dx:x,dy:y};
-r["Canvas.Left"]=0;
-r["Canvas.Top"]=0;
-this._applyTransform();
-delete this._delay;
-},_getAdjustedMatrix:function(){
-var m=this.matrix,d=this._delta,x;
-if(m){
-x=d?[m,d]:m;
-}else{
-x=d?d:{};
-}
-return new dojox.gfx.Matrix2D(x);
-},setStroke:function(){
-return this;
-},_setFillAttr:function(f){
-this.rawNode.foreground=f;
-},setRawNode:function(_14){
-this.rawNode=_14;
-},getTextWidth:function(){
-return this.rawNode.actualWidth;
-}});
-dojox.gfx.Text.nodeType="TextBlock";
-dojo.declare("dojox.gfx.Path",dojox.gfx.path.Path,{_updateWithSegment:function(_15){
-dojox.gfx.Path.superclass._updateWithSegment.apply(this,arguments);
-var p=this.shape.path;
-if(typeof (p)=="string"){
-this.rawNode.data=p?p:null;
-}
-},setShape:function(_16){
-dojox.gfx.Path.superclass.setShape.apply(this,arguments);
-var p=this.shape.path;
-this.rawNode.data=p?p:null;
-return this;
-}});
-dojox.gfx.Path.nodeType="Path";
-dojo.declare("dojox.gfx.TextPath",dojox.gfx.path.TextPath,{_updateWithSegment:function(_17){
-},setShape:function(_18){
-},_setText:function(){
-}});
-dojox.gfx.TextPath.nodeType="text";
-dojox.gfx.silverlight.surfaces={};
-dojox.gfx.silverlight.nullFunc=function(){
+
+dojox.gfx.silverlight.fontweight = {
+	normal: 400,
+	bold:   700
+};
+
+dojox.gfx.silverlight.caps  = {butt: "Flat", round: "Round", square: "Square"};
+dojox.gfx.silverlight.joins = {bevel: "Bevel", round: "Round"};
+
+dojox.gfx.silverlight.fonts = {
+	serif: "Times New Roman",
+	times: "Times New Roman",
+	"sans-serif": "Arial",
+	helvetica: "Arial",
+	monotone: "Courier New",
+	courier: "Courier New"
 };
-dojo.declare("dojox.gfx.Surface",dojox.gfx.shape.Surface,{constructor:function(){
-dojox.gfx.silverlight.Container._init.call(this);
-},destroy:function(){
-window[this._onLoadName]=dojox.gfx.silverlight.nullFunc;
-delete dojox.gfx.silverlight.surfaces[this.rawNode.name];
-this.inherited(arguments);
-},setDimensions:function(_19,_1a){
-this.width=dojox.gfx.normalizedLength(_19);
-this.height=dojox.gfx.normalizedLength(_1a);
-var p=this.rawNode&&this.rawNode.getHost();
-if(p){
-p.width=_19;
-p.height=_1a;
-}
-return this;
-},getDimensions:function(){
-var p=this.rawNode&&this.rawNode.getHost();
-var t=p?{width:p.content.actualWidth,height:p.content.actualHeight}:null;
-if(t.width<=0){
-t.width=this.width;
-}
-if(t.height<=0){
-t.height=this.height;
-}
-return t;
-}});
-dojox.gfx.createSurface=function(_1b,_1c,_1d){
-if(!_1c&&!_1d){
-var pos=d.position(_1b);
-_1c=_1c||pos.w;
-_1d=_1d||pos.h;
-}
-if(typeof _1c=="number"){
-_1c=_1c+"px";
-}
-if(typeof _1d=="number"){
-_1d=_1d+"px";
-}
-var s=new dojox.gfx.Surface();
-_1b=dojo.byId(_1b);
-s._parent=_1b;
-var t=_1b.ownerDocument.createElement("script");
-t.type="text/xaml";
-t.id=dojox.gfx._base._getUniqueId();
-t.text="<?xml version='1.0'?><Canvas xmlns='http://schemas.microsoft.com/client/2007' Name='"+dojox.gfx._base._getUniqueId()+"'/>";
-_1b.parentNode.insertBefore(t,_1b);
-s._nodes.push(t);
-var obj,_1e=dojox.gfx._base._getUniqueId(),_1f="__"+dojox.gfx._base._getUniqueId()+"_onLoad";
-s._onLoadName=_1f;
-window[_1f]=function(_20){
-if(!s.rawNode){
-s.rawNode=dojo.byId(_1e).content.root;
-dojox.gfx.silverlight.surfaces[s.rawNode.name]=_1b;
-s.onLoad(s);
-}
+
+dojox.gfx.silverlight.hexColor = function(/*String|Array|dojo.Color*/ color){
+	// summary: converts a color object to a Silverlight hex color string (#aarrggbb)
+	var c = dojox.gfx.normalizeColor(color),
+		t = c.toHex(), a = Math.round(c.a * 255);
+	a = (a < 0 ? 0 : a > 255 ? 255 : a).toString(16);
+	return "#" + (a.length < 2 ? "0" + a : a) + t.slice(1);	// String
 };
-if(dojo.isSafari){
-obj="<embed type='application/x-silverlight' id='"+_1e+"' width='"+_1c+"' height='"+_1d+" background='transparent'"+" source='#"+t.id+"'"+" windowless='true'"+" maxFramerate='60'"+" onLoad='"+_1f+"'"+" onError='__dojoSilverlightError'"+" /><iframe style='visibility:hidden;height:0;width:0'/>";
-}else{
-obj="<object type='application/x-silverlight' data='data:application/x-silverlight,' id='"+_1e+"' width='"+_1c+"' height='"+_1d+"'>"+"<param name='background' value='transparent' />"+"<param name='source' value='#"+t.id+"' />"+"<param name='windowless' value='true' />"+"<param name='maxFramerate' value='60' />"+"<param name='onLoad' value='"+_1f+"' />"+"<param name='onError' value='__dojoSilverlightError' />"+"</object>";
-}
-_1b.innerHTML=obj;
-var _21=dojo.byId(_1e);
-if(_21.content&&_21.content.root){
-s.rawNode=_21.content.root;
-dojox.gfx.silverlight.surfaces[s.rawNode.name]=_1b;
-}else{
-s.rawNode=null;
-s.isLoaded=false;
-}
-s._nodes.push(_21);
-s.width=dojox.gfx.normalizedLength(_1c);
-s.height=dojox.gfx.normalizedLength(_1d);
-return s;
+
+dojo.extend(dojox.gfx.Shape, {
+	// summary: Silverlight-specific implementation of dojox.gfx.Shape methods
+
+	setFill: function(fill){
+		// summary: sets a fill object (Silverlight)
+		// fill: Object: a fill object
+		//	(see dojox.gfx.defaultLinearGradient,
+		//	dojox.gfx.defaultRadialGradient,
+		//	dojox.gfx.defaultPattern,
+		//	or dojo.Color)
+
+		var p = this.rawNode.getHost().content, r = this.rawNode, f;
+		if(!fill){
+			// don't fill
+			this.fillStyle = null;
+			this._setFillAttr(null);
+			return this;	// self
+		}
+		if(typeof(fill) == "object" && "type" in fill){
+			// gradient
+			switch(fill.type){
+				case "linear":
+					this.fillStyle = f = dojox.gfx.makeParameters(dojox.gfx.defaultLinearGradient, fill);
+					var lgb = p.createFromXaml("<LinearGradientBrush/>");
+					lgb.mappingMode = "Absolute";
+					lgb.startPoint = f.x1 + "," + f.y1;
+					lgb.endPoint = f.x2 + "," + f.y2;
+					dojo.forEach(f.colors, function(c){
+						var t = p.createFromXaml("<GradientStop/>");
+						t.offset = c.offset;
+						t.color = dojox.gfx.silverlight.hexColor(c.color);
+						lgb.gradientStops.add(t);
+					});
+					this._setFillAttr(lgb);
+					break;
+				case "radial":
+					this.fillStyle = f = dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient, fill);
+					var rgb = p.createFromXaml("<RadialGradientBrush/>"),
+						c = dojox.gfx.matrix.multiplyPoint(
+								dojox.gfx.matrix.invert(this._getAdjustedMatrix()), f.cx, f.cy),
+						pt = c.x + "," + c.y;
+					rgb.mappingMode = "Absolute";
+					rgb.gradientOrigin = pt;
+					rgb.center = pt;
+					rgb.radiusX = rgb.radiusY = f.r;
+					dojo.forEach(f.colors, function(c){
+						var t = p.createFromXaml("<GradientStop/>");
+						t.offset = c.offset;
+						t.color = dojox.gfx.silverlight.hexColor(c.color);
+						rgb.gradientStops.add(t);
+					});
+					this._setFillAttr(rgb);
+					break;
+				case "pattern":
+					// don't fill: Silverlight doesn't define TileBrush for some reason
+					this.fillStyle = null;
+					this._setFillAttr(null);
+					break;
+			}
+			return this;	// self
+		}
+		// color object
+		this.fillStyle = f = dojox.gfx.normalizeColor(fill);
+		var scb = p.createFromXaml("<SolidColorBrush/>");
+		scb.color = f.toHex();
+		scb.opacity = f.a;
+		this._setFillAttr(scb);
+		return this;	// self
+	},
+	_setFillAttr: function(f){
+		this.rawNode.fill = f;
+	},
+
+	setStroke: function(stroke){
+		// summary: sets a stroke object (Silverlight)
+		// stroke: Object: a stroke object
+		//	(see dojox.gfx.defaultStroke)
+
+		var p = this.rawNode.getHost().content, r = this.rawNode;
+		if(!stroke){
+			// don't stroke
+			this.strokeStyle = null;
+			r.stroke = null;
+			return this;
+		}
+		// normalize the stroke
+		if(typeof stroke == "string" || dojo.isArray(stroke) || stroke instanceof dojo.Color){
+			stroke = {color: stroke};
+		}
+		var s = this.strokeStyle = dojox.gfx.makeParameters(dojox.gfx.defaultStroke, stroke);
+		s.color = dojox.gfx.normalizeColor(s.color);
+		// generate attributes
+		if(s){
+			var scb = p.createFromXaml("<SolidColorBrush/>");
+			scb.color = s.color.toHex();
+			scb.opacity = s.color.a;
+			r.stroke = scb;
+			r.strokeThickness = s.width;
+			r.strokeStartLineCap = r.strokeEndLineCap = r.strokeDashCap =
+				dojox.gfx.silverlight.caps[s.cap];
+			if(typeof s.join == "number"){
+				r.strokeLineJoin = "Miter";
+				r.strokeMiterLimit = s.join;
+			}else{
+				r.strokeLineJoin = dojox.gfx.silverlight.joins[s.join];
+			}
+			var da = s.style.toLowerCase();
+			if(da in dojox.gfx.silverlight.dasharray){ da = dojox.gfx.silverlight.dasharray[da]; }
+			if(da instanceof Array){
+				da = dojo.clone(da);
+				var i;
+				/*
+				for(var i = 0; i < da.length; ++i){
+					da[i] *= s.width;
+				}
+				*/
+				if(s.cap != "butt"){
+					for(i = 0; i < da.length; i += 2){
+						//da[i] -= s.width;
+						--da[i]
+						if(da[i] < 1){ da[i] = 1; }
+					}
+					for(i = 1; i < da.length; i += 2){
+						//da[i] += s.width;
+						++da[i];
+					}
+				}
+				r.strokeDashArray = da.join(",");
+			}else{
+				r.strokeDashArray = null;
+			}
+		}
+		return this;	// self
+	},
+
+	_getParentSurface: function(){
+		var surface = this.parent;
+		for(; surface && !(surface instanceof dojox.gfx.Surface); surface = surface.parent);
+		return surface;
+	},
+
+	_applyTransform: function() {
+		var tm = this._getAdjustedMatrix(), r = this.rawNode;
+		if(tm){
+			var p = this.rawNode.getHost().content,
+				m = p.createFromXaml("<MatrixTransform/>"),
+				mm = p.createFromXaml("<Matrix/>");
+			mm.m11 = tm.xx;
+			mm.m21 = tm.xy;
+			mm.m12 = tm.yx;
+			mm.m22 = tm.yy;
+			mm.offsetX = tm.dx;
+			mm.offsetY = tm.dy;
+			m.matrix = mm;
+			r.renderTransform = m;
+		}else{
+			r.renderTransform = null;
+		}
+		return this;
+	},
+
+	setRawNode: function(rawNode){
+		// summary:
+		//	assigns and clears the underlying node that will represent this
+		//	shape. Once set, transforms, gradients, etc, can be applied.
+		//	(no fill & stroke by default)
+		rawNode.fill = null;
+		rawNode.stroke = null;
+		this.rawNode = rawNode;
+	},
+
+	// move family
+
+	_moveToFront: function(){
+		// summary: moves a shape to front of its parent's list of shapes (Silverlight)
+		var c = this.parent.rawNode.children, r = this.rawNode;
+		c.remove(r);
+		c.add(r);
+		return this;	// self
+	},
+	_moveToBack: function(){
+		// summary: moves a shape to back of its parent's list of shapes (Silverlight)
+		var c = this.parent.rawNode.children, r = this.rawNode;
+		c.remove(r);
+		c.insert(0, r);
+		return this;	// self
+	},
+
+	_getAdjustedMatrix: function(){
+		// summary: returns the adjusted ("real") transformation matrix
+		return this.matrix;	// dojox.gfx.Matrix2D
+	}
+});
+
+dojo.declare("dojox.gfx.Group", dojox.gfx.Shape, {
+	// summary: a group shape (Silverlight), which can be used
+	//	to logically group shapes (e.g, to propagate matricies)
+	constructor: function(){
+		dojox.gfx.silverlight.Container._init.call(this);
+	},
+	setRawNode: function(rawNode){
+		// summary: sets a raw Silverlight node to be used by this shape
+		// rawNode: Node: an Silverlight node
+		this.rawNode = rawNode;
+	}
+});
+dojox.gfx.Group.nodeType = "Canvas";
+
+dojo.declare("dojox.gfx.Rect", dojox.gfx.shape.Rect, {
+	// summary: a rectangle shape (Silverlight)
+	setShape: function(newShape){
+		// summary: sets a rectangle shape object (Silverlight)
+		// newShape: Object: a rectangle shape object
+		this.shape = dojox.gfx.makeParameters(this.shape, newShape);
+		this.bbox = null;
+		var r = this.rawNode, n = this.shape;
+		r.width   = n.width;
+		r.height  = n.height;
+		r.radiusX = r.radiusY = n.r;
+		return this._applyTransform();	// self
+	},
+	_getAdjustedMatrix: function(){
+		// summary: returns the adjusted ("real") transformation matrix
+		var m = this.matrix, s = this.shape, d = {dx: s.x, dy: s.y};
+		return new dojox.gfx.Matrix2D(m ? [m, d] : d);	// dojox.gfx.Matrix2D
+	}
+});
+dojox.gfx.Rect.nodeType = "Rectangle";
+
+dojo.declare("dojox.gfx.Ellipse", dojox.gfx.shape.Ellipse, {
+	// summary: an ellipse shape (Silverlight)
+	setShape: function(newShape){
+		// summary: sets an ellipse shape object (Silverlight)
+		// newShape: Object: an ellipse shape object
+		this.shape = dojox.gfx.makeParameters(this.shape, newShape);
+		this.bbox = null;
+		var r = this.rawNode, n = this.shape;
+		r.width  = 2 * n.rx;
+		r.height = 2 * n.ry;
+		return this._applyTransform();	// self
+	},
+	_getAdjustedMatrix: function(){
+		// summary: returns the adjusted ("real") transformation matrix
+		var m = this.matrix, s = this.shape, d = {dx: s.cx - s.rx, dy: s.cy - s.ry};
+		return new dojox.gfx.Matrix2D(m ? [m, d] : d);	// dojox.gfx.Matrix2D
+	}
+});
+dojox.gfx.Ellipse.nodeType = "Ellipse";
+
+dojo.declare("dojox.gfx.Circle", dojox.gfx.shape.Circle, {
+	// summary: a circle shape (Silverlight)
+	setShape: function(newShape){
+		// summary: sets a circle shape object (Silverlight)
+		// newShape: Object: a circle shape object
+		this.shape = dojox.gfx.makeParameters(this.shape, newShape);
+		this.bbox = null;
+		var r = this.rawNode, n = this.shape;
+		r.width = r.height = 2 * n.r;
+		return this._applyTransform();	// self
+	},
+	_getAdjustedMatrix: function(){
+		// summary: returns the adjusted ("real") transformation matrix
+		var m = this.matrix, s = this.shape, d = {dx: s.cx - s.r, dy: s.cy - s.r};
+		return new dojox.gfx.Matrix2D(m ? [m, d] : d);	// dojox.gfx.Matrix2D
+	}
+});
+dojox.gfx.Circle.nodeType = "Ellipse";
+
+dojo.declare("dojox.gfx.Line", dojox.gfx.shape.Line, {
+	// summary: a line shape (Silverlight)
+	setShape: function(newShape){
+		// summary: sets a line shape object (Silverlight)
+		// newShape: Object: a line shape object
+		this.shape = dojox.gfx.makeParameters(this.shape, newShape);
+		this.bbox = null;
+		var r = this.rawNode, n = this.shape;
+		r.x1 = n.x1; r.y1 = n.y1; r.x2 = n.x2; r.y2 = n.y2;
+		return this;	// self
+	}
+});
+dojox.gfx.Line.nodeType = "Line";
+
+dojo.declare("dojox.gfx.Polyline", dojox.gfx.shape.Polyline, {
+	// summary: a polyline/polygon shape (Silverlight)
+	setShape: function(points, closed){
+		// summary: sets a polyline/polygon shape object (Silverlight)
+		// points: Object: a polyline/polygon shape object
+		if(points && points instanceof Array){
+			// branch
+			// points: Array: an array of points
+			this.shape = dojox.gfx.makeParameters(this.shape, {points: points});
+			if(closed && this.shape.points.length){
+				this.shape.points.push(this.shape.points[0]);
+			}
+		}else{
+			this.shape = dojox.gfx.makeParameters(this.shape, points);
+		}
+		this.bbox = null;
+		this._normalizePoints();
+		var p = this.shape.points, rp = [];
+		for(var i = 0; i < p.length; ++i){
+			rp.push(p[i].x, p[i].y);
+		}
+		this.rawNode.points = rp.join(",");
+		return this;	// self
+	}
+});
+dojox.gfx.Polyline.nodeType = "Polyline";
+
+dojo.declare("dojox.gfx.Image", dojox.gfx.shape.Image, {
+	// summary: an image (Silverlight)
+	setShape: function(newShape){
+		// summary: sets an image shape object (Silverlight)
+		// newShape: Object: an image shape object
+		this.shape = dojox.gfx.makeParameters(this.shape, newShape);
+		this.bbox = null;
+		var r = this.rawNode, n = this.shape;
+		r.width  = n.width;
+		r.height = n.height;
+		r.source = n.src;
+		return this._applyTransform();	// self
+	},
+	_getAdjustedMatrix: function(){
+		// summary: returns the adjusted ("real") transformation matrix
+		var m = this.matrix, s = this.shape, d = {dx: s.x, dy: s.y};
+		return new dojox.gfx.Matrix2D(m ? [m, d] : d);	// dojox.gfx.Matrix2D
+	},
+	setRawNode: function(rawNode){
+		// summary:
+		//	assigns and clears the underlying node that will represent this
+		//	shape. Once set, transforms, gradients, etc, can be applied.
+		//	(no fill & stroke by default)
+		this.rawNode = rawNode;
+	}
+});
+dojox.gfx.Image.nodeType = "Image";
+
+dojo.declare("dojox.gfx.Text", dojox.gfx.shape.Text, {
+	// summary: an anchored text (Silverlight)
+	setShape: function(newShape){
+		// summary: sets a text shape object (Silverlight)
+		// newShape: Object: a text shape object
+		this.shape = dojox.gfx.makeParameters(this.shape, newShape);
+		this.bbox = null;
+		var r = this.rawNode, s = this.shape;
+		r.text = s.text;
+		r.textDecorations = s.decoration === "underline" ? "Underline" : "None";
+		r["Canvas.Left"] = -10000;
+		r["Canvas.Top"]  = -10000;
+		if(!this._delay){
+			this._delay = window.setTimeout(dojo.hitch(this, "_delayAlignment"), 10);
+		}
+		return this;	// self
+	},
+	_delayAlignment: function(){
+		// handle alignment
+		var r = this.rawNode, s = this.shape,
+			w = r.actualWidth, h = r.actualHeight, x = s.x, y = s.y - h * 0.75;
+		switch(s.align){
+			case "middle":
+				x -= w / 2;
+				break;
+			case "end":
+				x -= w;
+				break;
+		}
+		this._delta = {dx: x, dy: y};
+		r["Canvas.Left"] = 0;
+		r["Canvas.Top"]  = 0;
+		this._applyTransform();
+		delete this._delay;
+	},
+	_getAdjustedMatrix: function(){
+		// summary: returns the adjusted ("real") transformation matrix
+		var m = this.matrix, d = this._delta, x;
+		if(m){
+			x = d ? [m, d] : m;
+		}else{
+			x = d ? d : {};
+		}
+		return new dojox.gfx.Matrix2D(x);
+	},
+	setStroke: function(){
+		// summary: ignore setting a stroke style
+		return this;	// self
+	},
+	_setFillAttr: function(f){
+		this.rawNode.foreground = f;
+	},
+	setRawNode: function(rawNode){
+		// summary:
+		//	assigns and clears the underlying node that will represent this
+		//	shape. Once set, transforms, gradients, etc, can be applied.
+		//	(no fill & stroke by default)
+		this.rawNode = rawNode;
+	},
+	getTextWidth: function(){
+		// summary: get the text width in pixels
+		return this.rawNode.actualWidth;
+	}
+});
+dojox.gfx.Text.nodeType = "TextBlock";
+
+dojo.declare("dojox.gfx.Path", dojox.gfx.path.Path, {
+	// summary: a path shape (Silverlight)
+	_updateWithSegment: function(segment){
+		// summary: updates the bounding box of path with new segment
+		// segment: Object: a segment
+		dojox.gfx.Path.superclass._updateWithSegment.apply(this, arguments);
+		var p = this.shape.path;
+		if(typeof(p) == "string"){
+			this.rawNode.data = p ? p : null;
+		}
+	},
+	setShape: function(newShape){
+		// summary: forms a path using a shape (Silverlight)
+		// newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+		dojox.gfx.Path.superclass.setShape.apply(this, arguments);
+		var p = this.shape.path;
+		this.rawNode.data = p ? p : null;
+		return this;	// self
+	}
+});
+dojox.gfx.Path.nodeType = "Path";
+
+dojo.declare("dojox.gfx.TextPath", dojox.gfx.path.TextPath, {
+	// summary: a textpath shape (Silverlight)
+	_updateWithSegment: function(segment){
+		// summary: updates the bounding box of path with new segment
+		// segment: Object: a segment
+	},
+	setShape: function(newShape){
+		// summary: forms a path using a shape (Silverlight)
+		// newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+	},
+	_setText: function(){
+	}
+});
+dojox.gfx.TextPath.nodeType = "text";
+
+dojox.gfx.silverlight.surfaces = {};
+dojox.gfx.silverlight.nullFunc = function(){};
+
+dojo.declare("dojox.gfx.Surface", dojox.gfx.shape.Surface, {
+	// summary: a surface object to be used for drawings (Silverlight)
+	constructor: function(){
+		dojox.gfx.silverlight.Container._init.call(this);
+	},
+	destroy: function(){
+		window[this._onLoadName] = dojox.gfx.silverlight.nullFunc;
+		delete dojox.gfx.silverlight.surfaces[this.rawNode.name];
+		this.inherited(arguments);
+	},
+	setDimensions: function(width, height){
+		// summary: sets the width and height of the rawNode
+		// width: String: width of surface, e.g., "100px"
+		// height: String: height of surface, e.g., "100px"
+		this.width  = dojox.gfx.normalizedLength(width);	// in pixels
+		this.height = dojox.gfx.normalizedLength(height);	// in pixels
+		var p = this.rawNode && this.rawNode.getHost();
+		if(p){
+			p.width = width;
+			p.height = height;
+		}
+		return this;	// self
+	},
+	getDimensions: function(){
+		// summary: returns an object with properties "width" and "height"
+		var p = this.rawNode && this.rawNode.getHost();
+		var t = p ? {width: p.content.actualWidth, height: p.content.actualHeight} : null;
+		if(t.width  <= 0){ t.width  = this.width; }
+		if(t.height <= 0){ t.height = this.height; }
+		return t;	// Object
+	}
+});
+
+dojox.gfx.createSurface = function(parentNode, width, height){
+	// summary: creates a surface (Silverlight)
+	// parentNode: Node: a parent node
+	// width: String: width of surface, e.g., "100px"
+	// height: String: height of surface, e.g., "100px"
+
+	if(!width && !height){
+		var pos = d.position(parentNode);
+		width  = width  || pos.w;
+		height = height || pos.h;
+	}
+	if(typeof width == "number"){
+		width = width + "px";
+	}
+	if(typeof height == "number"){
+		height = height + "px";
+	}
+
+	var s = new dojox.gfx.Surface();
+	parentNode = dojo.byId(parentNode);
+	s._parent = parentNode;
+
+	// create an empty canvas
+	var t = parentNode.ownerDocument.createElement("script");
+	t.type = "text/xaml";
+	t.id = dojox.gfx._base._getUniqueId();
+	t.text = "<?xml version='1.0'?><Canvas xmlns='http://schemas.microsoft.com/client/2007' Name='" +
+		dojox.gfx._base._getUniqueId() + "'/>";
+	parentNode.parentNode.insertBefore(t, parentNode);
+	s._nodes.push(t);
+
+	// build the object
+	var obj, pluginName = dojox.gfx._base._getUniqueId(),
+		onLoadName = "__" + dojox.gfx._base._getUniqueId() + "_onLoad";
+	s._onLoadName = onLoadName;
+	window[onLoadName] = function(sender){
+		console.log("Silverlight: loaded");
+		if(!s.rawNode){
+			s.rawNode = dojo.byId(pluginName).content.root;
+			// register the plugin with its parent node
+			dojox.gfx.silverlight.surfaces[s.rawNode.name] = parentNode;
+			s.onLoad(s);
+			console.log("Silverlight: assigned");
+		}
+	};
+	if(dojo.isSafari){
+		obj = "<embed type='application/x-silverlight' id='" +
+		pluginName + "' width='" + width + "' height='" + height +
+		" background='transparent'" +
+		" source='#" + t.id + "'" +
+		" windowless='true'" +
+		" maxFramerate='60'" +
+		" onLoad='" + onLoadName + "'" +
+		" onError='__dojoSilverlightError'" +
+		" /><iframe style='visibility:hidden;height:0;width:0'/>";
+	}else{
+		obj = "<object type='application/x-silverlight' data='data:application/x-silverlight,' id='" +
+		pluginName + "' width='" + width + "' height='" + height + "'>" +
+		"<param name='background' value='transparent' />" +
+		"<param name='source' value='#" + t.id + "' />" +
+		"<param name='windowless' value='true' />" +
+		"<param name='maxFramerate' value='60' />" +
+		"<param name='onLoad' value='" + onLoadName + "' />" +
+		"<param name='onError' value='__dojoSilverlightError' />" +
+		"</object>";
+	}
+	parentNode.innerHTML = obj;
+
+	var pluginNode = dojo.byId(pluginName);
+	if(pluginNode.content && pluginNode.content.root){
+		// the plugin was created synchronously
+		s.rawNode = pluginNode.content.root;
+		// register the plugin with its parent node
+		dojox.gfx.silverlight.surfaces[s.rawNode.name] = parentNode;
+	}else{
+		// the plugin is being created asynchronously
+		s.rawNode = null;
+		s.isLoaded = false;
+	}
+	s._nodes.push(pluginNode);
+
+	s.width  = dojox.gfx.normalizedLength(width);	// in pixels
+	s.height = dojox.gfx.normalizedLength(height);	// in pixels
+
+	return s;	// dojox.gfx.Surface
 };
-__dojoSilverlightError=function(_22,err){
-var t="Silverlight Error:\n"+"Code: "+err.ErrorCode+"\n"+"Type: "+err.ErrorType+"\n"+"Message: "+err.ErrorMessage+"\n";
-switch(err.ErrorType){
-case "ParserError":
-t+="XamlFile: "+err.xamlFile+"\n"+"Line: "+err.lineNumber+"\n"+"Position: "+err.charPosition+"\n";
-break;
-case "RuntimeError":
-t+="MethodName: "+err.methodName+"\n";
-if(err.lineNumber!=0){
-t+="Line: "+err.lineNumber+"\n"+"Position: "+err.charPosition+"\n";
-}
-break;
-}
-console.error(t);
+
+// the function below is meant to be global, it is called from
+// the Silverlight's error handler
+__dojoSilverlightError = function(sender, err){
+	var t = "Silverlight Error:\n" +
+		"Code: " + err.ErrorCode + "\n" +
+		"Type: " + err.ErrorType + "\n" +
+		"Message: " + err.ErrorMessage + "\n";
+	switch(err.ErrorType){
+		case "ParserError":
+			t += "XamlFile: " + err.xamlFile + "\n" +
+				"Line: " + err.lineNumber + "\n" +
+				"Position: " + err.charPosition + "\n";
+			break;
+		case "RuntimeError":
+			t += "MethodName: " + err.methodName + "\n";
+			if(err.lineNumber != 0){
+				t +=
+					"Line: " + err.lineNumber + "\n" +
+					"Position: " + err.charPosition + "\n";
+			}
+			break;
+	}
+	console.error(t);
 };
-dojox.gfx.silverlight.Font={_setFont:function(){
-var f=this.fontStyle,r=this.rawNode,fw=dojox.gfx.silverlight.fontweight,fo=dojox.gfx.silverlight.fonts,t=f.family.toLowerCase();
-r.fontStyle=f.style=="italic"?"Italic":"Normal";
-r.fontWeight=f.weight in fw?fw[f.weight]:f.weight;
-r.fontSize=dojox.gfx.normalizedLength(f.size);
-r.fontFamily=t in fo?fo[t]:f.family;
-if(!this._delay){
-this._delay=window.setTimeout(dojo.hitch(this,"_delayAlignment"),10);
-}
-}};
-dojox.gfx.silverlight.Container={_init:function(){
-dojox.gfx.shape.Container._init.call(this);
-},add:function(_23){
-if(this!=_23.getParent()){
-dojox.gfx.shape.Container.add.apply(this,arguments);
-this.rawNode.children.add(_23.rawNode);
-}
-return this;
-},remove:function(_24,_25){
-if(this==_24.getParent()){
-var _26=_24.rawNode.getParent();
-if(_26){
-_26.children.remove(_24.rawNode);
-}
-dojox.gfx.shape.Container.remove.apply(this,arguments);
-}
-return this;
-},clear:function(){
-this.rawNode.children.clear();
-return dojox.gfx.shape.Container.clear.apply(this,arguments);
-},_moveChildToFront:dojox.gfx.shape.Container._moveChildToFront,_moveChildToBack:dojox.gfx.shape.Container._moveChildToBack};
-dojo.mixin(dojox.gfx.shape.Creator,{createObject:function(_27,_28){
-if(!this.rawNode){
-return null;
-}
-var _29=new _27();
-var _2a=this.rawNode.getHost().content.createFromXaml("<"+_27.nodeType+"/>");
-_29.setRawNode(_2a);
-_29.setShape(_28);
-this.add(_29);
-return _29;
-}});
-dojo.extend(dojox.gfx.Text,dojox.gfx.silverlight.Font);
-dojo.extend(dojox.gfx.Group,dojox.gfx.silverlight.Container);
-dojo.extend(dojox.gfx.Group,dojox.gfx.shape.Creator);
-dojo.extend(dojox.gfx.Surface,dojox.gfx.silverlight.Container);
-dojo.extend(dojox.gfx.Surface,dojox.gfx.shape.Creator);
-(function(){
-var _2b=dojox.gfx.silverlight.surfaces;
-var _2c=function(s,a){
-var ev={target:s,currentTarget:s,preventDefault:function(){
-},stopPropagation:function(){
-}};
-if(a){
-try{
-ev.ctrlKey=a.ctrl;
-ev.shiftKey=a.shift;
-var p=a.getPosition(null);
-ev.x=ev.offsetX=ev.layerX=p.x;
-ev.y=ev.offsetY=ev.layerY=p.y;
-var _2d=_2b[s.getHost().content.root.name];
-var t=dojo.position(_2d);
-ev.clientX=t.x+p.x;
-ev.clientY=t.y+p.y;
-}
-catch(e){
-}
-}
-return ev;
+
+// Extenders
+
+dojox.gfx.silverlight.Font = {
+	_setFont: function(){
+		// summary: sets a font object (Silverlight)
+		var f = this.fontStyle, r = this.rawNode,
+			fw = dojox.gfx.silverlight.fontweight,
+			fo = dojox.gfx.silverlight.fonts, t = f.family.toLowerCase();
+		r.fontStyle = f.style == "italic" ? "Italic" : "Normal";
+		r.fontWeight = f.weight in fw ? fw[f.weight] : f.weight;
+		r.fontSize = dojox.gfx.normalizedLength(f.size);
+		r.fontFamily = t in fo ? fo[t] : f.family;
+
+		// update the transform
+		if(!this._delay){
+			this._delay = window.setTimeout(dojo.hitch(this, "_delayAlignment"), 10);
+		}
+	}
 };
-var _2e=function(s,a){
-var ev={keyCode:a.platformKeyCode,ctrlKey:a.ctrl,shiftKey:a.shift};
-return ev;
+
+dojox.gfx.silverlight.Container = {
+	_init: function(){
+		dojox.gfx.shape.Container._init.call(this);
+	},
+	add: function(shape){
+		// summary: adds a shape to a group/surface
+		// shape: dojox.gfx.Shape: a Silverlight shape object
+		if(this != shape.getParent()){
+			//dojox.gfx.Group.superclass.add.apply(this, arguments);
+			//this.inherited(arguments);
+			dojox.gfx.shape.Container.add.apply(this, arguments);
+			this.rawNode.children.add(shape.rawNode);
+		}
+		return this;	// self
+	},
+	remove: function(shape, silently){
+		// summary: remove a shape from a group/surface
+		// shape: dojox.gfx.Shape: a Silverlight shape object
+		// silently: Boolean?: if true, regenerate a picture
+		if(this == shape.getParent()){
+			var parent = shape.rawNode.getParent();
+			if(parent){
+				parent.children.remove(shape.rawNode);
+			}
+			//dojox.gfx.Group.superclass.remove.apply(this, arguments);
+			//this.inherited(arguments);
+			dojox.gfx.shape.Container.remove.apply(this, arguments);
+		}
+		return this;	// self
+	},
+	clear: function(){
+		// summary: removes all shapes from a group/surface
+		this.rawNode.children.clear();
+		//return this.inherited(arguments);	// self
+		return dojox.gfx.shape.Container.clear.apply(this, arguments);
+	},
+	_moveChildToFront: dojox.gfx.shape.Container._moveChildToFront,
+	_moveChildToBack:  dojox.gfx.shape.Container._moveChildToBack
 };
-var _2f={onclick:{name:"MouseLeftButtonUp",fix:_2c},onmouseenter:{name:"MouseEnter",fix:_2c},onmouseleave:{name:"MouseLeave",fix:_2c},onmouseover:{name:"MouseEnter",fix:_2c},onmouseout:{name:"MouseLeave",fix:_2c},onmousedown:{name:"MouseLeftButtonDown",fix:_2c},onmouseup:{name:"MouseLeftButtonUp",fix:_2c},onmousemove:{name:"MouseMove",fix:_2c},onkeydown:{name:"KeyDown",fix:_2e},onkeyup:{name:"KeyUp",fix:_2e}};
-var _30={connect:function(_31,_32,_33){
-var _34,n=_31 in _2f?_2f[_31]:{name:_31,fix:function(){
-return {};
-}};
-if(arguments.length>2){
-_34=this.getEventSource().addEventListener(n.name,function(s,a){
-dojo.hitch(_32,_33)(n.fix(s,a));
-});
-}else{
-_34=this.getEventSource().addEventListener(n.name,function(s,a){
-_32(n.fix(s,a));
+
+dojo.mixin(dojox.gfx.shape.Creator, {
+	createObject: function(shapeType, rawShape){
+		// summary: creates an instance of the passed shapeType class
+		// shapeType: Function: a class constructor to create an instance of
+		// rawShape: Object: properties to be passed in to the classes "setShape" method
+		if(!this.rawNode){ return null; }
+		var shape = new shapeType();
+		var node = this.rawNode.getHost().content.createFromXaml("<" + shapeType.nodeType + "/>");
+		shape.setRawNode(node);
+		shape.setShape(rawShape);
+		this.add(shape);
+		return shape;	// dojox.gfx.Shape
+	}
 });
-}
-return {name:n.name,token:_34};
-},disconnect:function(_35){
-this.getEventSource().removeEventListener(_35.name,_35.token);
-}};
-dojo.extend(dojox.gfx.Shape,_30);
-dojo.extend(dojox.gfx.Surface,_30);
-dojox.gfx.equalSources=function(a,b){
-return a&&b&&a.equals(b);
-};
+
+dojo.extend(dojox.gfx.Text, dojox.gfx.silverlight.Font);
+//dojo.extend(dojox.gfx.TextPath, dojox.gfx.silverlight.Font);
+
+dojo.extend(dojox.gfx.Group, dojox.gfx.silverlight.Container);
+dojo.extend(dojox.gfx.Group, dojox.gfx.shape.Creator);
+
+dojo.extend(dojox.gfx.Surface, dojox.gfx.silverlight.Container);
+dojo.extend(dojox.gfx.Surface, dojox.gfx.shape.Creator);
+
+(function(){
+	var surfaces = dojox.gfx.silverlight.surfaces;
+	var mouseFix = function(s, a){
+		var ev = {target: s, currentTarget: s,
+			preventDefault: function(){}, stopPropagation: function(){}};
+		if(a){
+			try{
+				ev.ctrlKey = a.ctrl;
+				ev.shiftKey = a.shift;
+				var p = a.getPosition(null);
+				ev.x = ev.offsetX = ev.layerX = p.x;
+				ev.y = ev.offsetY = ev.layerY = p.y;
+				// calculate clientX and clientY
+				var parent = surfaces[s.getHost().content.root.name];
+				var t = dojo.position(parent);
+				ev.clientX = t.x + p.x;
+				ev.clientY = t.y + p.y;
+			}catch(e){
+				// squelch bugs in MouseLeave's implementation
+			}
+		}
+		return ev;
+	};
+	var keyFix = function(s, a){
+		var ev = {
+			keyCode:  a.platformKeyCode,
+			ctrlKey:  a.ctrl,
+			shiftKey: a.shift
+		};
+		return ev;
+	};
+	var eventNames = {
+		onclick:		{name: "MouseLeftButtonUp", fix: mouseFix},
+		onmouseenter:	{name: "MouseEnter", fix: mouseFix},
+		onmouseleave:	{name: "MouseLeave", fix: mouseFix},
+		onmouseover:	{name: "MouseEnter", fix: mouseFix},
+		onmouseout:		{name: "MouseLeave", fix: mouseFix},
+		onmousedown:	{name: "MouseLeftButtonDown", fix: mouseFix},
+		onmouseup:		{name: "MouseLeftButtonUp", fix: mouseFix},
+		onmousemove:	{name: "MouseMove", fix: mouseFix},
+		onkeydown:		{name: "KeyDown", fix: keyFix},
+		onkeyup:		{name: "KeyUp", fix: keyFix}
+	};
+	var eventsProcessing = {
+		connect: function(name, object, method){
+			var token, n = name in eventNames ? eventNames[name] :
+				{name: name, fix: function(){ return {}; }};
+			if(arguments.length > 2){
+				token = this.getEventSource().addEventListener(n.name,
+					function(s, a){ dojo.hitch(object, method)(n.fix(s, a)); });
+			}else{
+				token = this.getEventSource().addEventListener(n.name,
+					function(s, a){ object(n.fix(s, a)); });
+			}
+			return {name: n.name, token: token};
+		},
+		disconnect: function(token){
+			this.getEventSource().removeEventListener(token.name, token.token);
+		}
+	};
+	dojo.extend(dojox.gfx.Shape, eventsProcessing);
+	dojo.extend(dojox.gfx.Surface, eventsProcessing);
+	dojox.gfx.equalSources = function(a, b){
+		return a && b && a.equals(b);
+	}
+
 })();
-}
diff --git a/dojox/gfx/silverlight_attach.js b/dojox/gfx/silverlight_attach.js
index 66a9800..f426db8 100644
--- a/dojox/gfx/silverlight_attach.js
+++ b/dojox/gfx/silverlight_attach.js
@@ -1,73 +1,87 @@
-/*
-	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
-*/
-
-
 dojo.require("dojox.gfx.silverlight");
+
 dojo.experimental("dojox.gfx.silverlight_attach");
+
 (function(){
-dojox.gfx.attachNode=function(_1){
-return null;
-if(!_1){
-return null;
-}
-var s=null;
-switch(_1.tagName.toLowerCase()){
-case dojox.gfx.Rect.nodeType:
-s=new dojox.gfx.Rect(_1);
-break;
-case dojox.gfx.Ellipse.nodeType:
-if(_1.width==_1.height){
-s=new dojox.gfx.Circle(_1);
-}else{
-s=new dojox.gfx.Ellipse(_1);
-}
-break;
-case dojox.gfx.Polyline.nodeType:
-s=new dojox.gfx.Polyline(_1);
-break;
-case dojox.gfx.Path.nodeType:
-s=new dojox.gfx.Path(_1);
-break;
-case dojox.gfx.Line.nodeType:
-s=new dojox.gfx.Line(_1);
-break;
-case dojox.gfx.Image.nodeType:
-s=new dojox.gfx.Image(_1);
-break;
-case dojox.gfx.Text.nodeType:
-s=new dojox.gfx.Text(_1);
-_2(s);
-break;
-default:
-return null;
-}
-_3(s);
-if(!(s instanceof dojox.gfx.Image)){
-_4(s);
-_5(s);
-}
-_6(s);
-return s;
-};
-dojox.gfx.attachSurface=function(_7){
-return null;
-};
-var _4=function(_8){
-return null;
-};
-var _5=function(_9){
-return null;
-};
-var _6=function(_a){
-return null;
-};
-var _2=function(_b){
-return null;
-};
-var _3=function(_c){
-return null;
-};
+	dojox.gfx.attachNode = function(node){
+		// summary: creates a shape from a Node
+		// node: Node: an Silverlight node
+		return null;	// for now
+		if(!node) return null;
+		var s = null;
+		switch(node.tagName.toLowerCase()){
+			case dojox.gfx.Rect.nodeType:
+				s = new dojox.gfx.Rect(node);
+				break;
+			case dojox.gfx.Ellipse.nodeType:
+				if(node.width == node.height){
+					s = new dojox.gfx.Circle(node);
+				}else{
+					s = new dojox.gfx.Ellipse(node);
+				}
+				break;
+			case dojox.gfx.Polyline.nodeType:
+				s = new dojox.gfx.Polyline(node);
+				break;
+			case dojox.gfx.Path.nodeType:
+				s = new dojox.gfx.Path(node);
+				break;
+			case dojox.gfx.Line.nodeType:
+				s = new dojox.gfx.Line(node);
+				break;
+			case dojox.gfx.Image.nodeType:
+				s = new dojox.gfx.Image(node);
+				break;
+			case dojox.gfx.Text.nodeType:
+				s = new dojox.gfx.Text(node);
+				attachFont(s);
+				break;
+			default:
+				//console.debug("FATAL ERROR! tagName = " + node.tagName);
+				return null;
+		}
+		attachShape(s);
+		if(!(s instanceof dojox.gfx.Image)){
+			attachFill(s);
+			attachStroke(s);
+		}
+		attachTransform(s);
+		return s;	// dojox.gfx.Shape
+	};
+
+	dojox.gfx.attachSurface = function(node){
+		// summary: creates a surface from a Node
+		// node: Node: an Silverlight node
+		return null;	// dojox.gfx.Surface
+	};
+
+	var attachFill = function(rawNode){
+		// summary: deduces a fill style from a Node.
+		// rawNode: Node: an Silverlight node
+		return null;	// Object
+	};
+
+	var attachStroke = function(rawNode){
+		// summary: deduces a stroke style from a Node.
+		// rawNode: Node: an SVG node
+		return null;	// Object
+	};
+
+	var attachTransform = function(rawNode){
+		// summary: deduces a transformation matrix from a Node.
+		// rawNode: Node: an Silverlight node
+		return null;	// dojox.gfx.matrix.Matrix
+	};
+
+	var attachFont = function(rawNode){
+		// summary: deduces a font style from a Node.
+		// rawNode: Node: an Silverlight node
+		return null;	// Object
+	};
+
+	var attachShape = function(rawNode){
+		// summary: builds a shape from a Node.
+		// rawNode: Node: an Silverlight node
+		return null;	// dojox.gfx.Shape
+	};
 })();
diff --git a/dojox/gfx/svg.js b/dojox/gfx/svg.js
index b6f2441..dc2fe89 100644
--- a/dojox/gfx/svg.js
+++ b/dojox/gfx/svg.js
@@ -1,465 +1,782 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.svg"]){
-dojo._hasResource["dojox.gfx.svg"]=true;
 dojo.provide("dojox.gfx.svg");
+
 dojo.require("dojox.gfx._base");
 dojo.require("dojox.gfx.shape");
 dojo.require("dojox.gfx.path");
+
 (function(){
-var d=dojo,g=dojox.gfx,gs=g.shape,_1=g.svg;
-var _2=function(ns,_3){
-if(document.createElementNS){
-return document.createElementNS(ns,_3);
-}else{
-return document.createElement(_3);
-}
-};
-_1.xmlns={xlink:"http://www.w3.org/1999/xlink",svg:"http://www.w3.org/2000/svg"};
-_1.getRef=function(_4){
-if(!_4||_4=="none"){
-return null;
-}
-if(_4.match(/^url\(#.+\)$/)){
-return d.byId(_4.slice(5,-1));
-}
-if(_4.match(/^#dojoUnique\d+$/)){
-return d.byId(_4.slice(1));
-}
-return null;
-};
-_1.dasharray={solid:"none",shortdash:[4,1],shortdot:[1,1],shortdashdot:[4,1,1,1],shortdashdotdot:[4,1,1,1,1,1],dot:[1,3],dash:[4,3],longdash:[8,3],dashdot:[4,3,1,3],longdashdot:[8,3,1,3],longdashdotdot:[8,3,1,3,1,3]};
-d.extend(g.Shape,{setFill:function(_5){
-if(!_5){
-this.fillStyle=null;
-this.rawNode.setAttribute("fill","none");
-this.rawNode.setAttribute("fill-opacity",0);
-return this;
-}
-var f;
-var _6=function(x){
-this.setAttribute(x,f[x].toFixed(8));
-};
-if(typeof (_5)=="object"&&"type" in _5){
-switch(_5.type){
-case "linear":
-f=g.makeParameters(g.defaultLinearGradient,_5);
-var _7=this._setFillObject(f,"linearGradient");
-d.forEach(["x1","y1","x2","y2"],_6,_7);
-break;
-case "radial":
-f=g.makeParameters(g.defaultRadialGradient,_5);
-var _7=this._setFillObject(f,"radialGradient");
-d.forEach(["cx","cy","r"],_6,_7);
-break;
-case "pattern":
-f=g.makeParameters(g.defaultPattern,_5);
-var _8=this._setFillObject(f,"pattern");
-d.forEach(["x","y","width","height"],_6,_8);
-break;
-}
-this.fillStyle=f;
-return this;
-}
-var f=g.normalizeColor(_5);
-this.fillStyle=f;
-this.rawNode.setAttribute("fill",f.toCss());
-this.rawNode.setAttribute("fill-opacity",f.a);
-this.rawNode.setAttribute("fill-rule","evenodd");
-return this;
-},setStroke:function(_9){
-var rn=this.rawNode;
-if(!_9){
-this.strokeStyle=null;
-rn.setAttribute("stroke","none");
-rn.setAttribute("stroke-opacity",0);
-return this;
-}
-if(typeof _9=="string"||d.isArray(_9)||_9 instanceof d.Color){
-_9={color:_9};
-}
-var s=this.strokeStyle=g.makeParameters(g.defaultStroke,_9);
-s.color=g.normalizeColor(s.color);
-if(s){
-rn.setAttribute("stroke",s.color.toCss());
-rn.setAttribute("stroke-opacity",s.color.a);
-rn.setAttribute("stroke-width",s.width);
-rn.setAttribute("stroke-linecap",s.cap);
-if(typeof s.join=="number"){
-rn.setAttribute("stroke-linejoin","miter");
-rn.setAttribute("stroke-miterlimit",s.join);
-}else{
-rn.setAttribute("stroke-linejoin",s.join);
-}
-var da=s.style.toLowerCase();
-if(da in _1.dasharray){
-da=_1.dasharray[da];
-}
-if(da instanceof Array){
-da=d._toArray(da);
-for(var i=0;i<da.length;++i){
-da[i]*=s.width;
-}
-if(s.cap!="butt"){
-for(var i=0;i<da.length;i+=2){
-da[i]-=s.width;
-if(da[i]<1){
-da[i]=1;
-}
-}
-for(var i=1;i<da.length;i+=2){
-da[i]+=s.width;
-}
-}
-da=da.join(",");
-}
-rn.setAttribute("stroke-dasharray",da);
-rn.setAttribute("dojoGfxStrokeStyle",s.style);
-}
-return this;
-},_getParentSurface:function(){
-var _a=this.parent;
-for(;_a&&!(_a instanceof g.Surface);_a=_a.parent){
-}
-return _a;
-},_setFillObject:function(f,_b){
-var _c=_1.xmlns.svg;
-this.fillStyle=f;
-var _d=this._getParentSurface(),_e=_d.defNode,_f=this.rawNode.getAttribute("fill"),ref=_1.getRef(_f);
-if(ref){
-_f=ref;
-if(_f.tagName.toLowerCase()!=_b.toLowerCase()){
-var id=_f.id;
-_f.parentNode.removeChild(_f);
-_f=_2(_c,_b);
-_f.setAttribute("id",id);
-_e.appendChild(_f);
-}else{
-while(_f.childNodes.length){
-_f.removeChild(_f.lastChild);
-}
-}
-}else{
-_f=_2(_c,_b);
-_f.setAttribute("id",g._base._getUniqueId());
-_e.appendChild(_f);
-}
-if(_b=="pattern"){
-_f.setAttribute("patternUnits","userSpaceOnUse");
-var img=_2(_c,"image");
-img.setAttribute("x",0);
-img.setAttribute("y",0);
-img.setAttribute("width",f.width.toFixed(8));
-img.setAttribute("height",f.height.toFixed(8));
-img.setAttributeNS(_1.xmlns.xlink,"href",f.src);
-_f.appendChild(img);
-}else{
-_f.setAttribute("gradientUnits","userSpaceOnUse");
-for(var i=0;i<f.colors.length;++i){
-var c=f.colors[i],t=_2(_c,"stop"),cc=c.color=g.normalizeColor(c.color);
-t.setAttribute("offset",c.offset.toFixed(8));
-t.setAttribute("stop-color",cc.toCss());
-t.setAttribute("stop-opacity",cc.a);
-_f.appendChild(t);
-}
-}
-this.rawNode.setAttribute("fill","url(#"+_f.getAttribute("id")+")");
-this.rawNode.removeAttribute("fill-opacity");
-this.rawNode.setAttribute("fill-rule","evenodd");
-return _f;
-},_applyTransform:function(){
-var _10=this.matrix;
-if(_10){
-var tm=this.matrix;
-this.rawNode.setAttribute("transform","matrix("+tm.xx.toFixed(8)+","+tm.yx.toFixed(8)+","+tm.xy.toFixed(8)+","+tm.yy.toFixed(8)+","+tm.dx.toFixed(8)+","+tm.dy.toFixed(8)+")");
-}else{
-this.rawNode.removeAttribute("transform");
-}
-return this;
-},setRawNode:function(_11){
-var r=this.rawNode=_11;
-if(this.shape.type!="image"){
-r.setAttribute("fill","none");
-}
-r.setAttribute("fill-opacity",0);
-r.setAttribute("stroke","none");
-r.setAttribute("stroke-opacity",0);
-r.setAttribute("stroke-width",1);
-r.setAttribute("stroke-linecap","butt");
-r.setAttribute("stroke-linejoin","miter");
-r.setAttribute("stroke-miterlimit",4);
-},setShape:function(_12){
-this.shape=g.makeParameters(this.shape,_12);
-for(var i in this.shape){
-if(i!="type"){
-this.rawNode.setAttribute(i,this.shape[i]);
-}
-}
-this.bbox=null;
-return this;
-},_moveToFront:function(){
-this.rawNode.parentNode.appendChild(this.rawNode);
-return this;
-},_moveToBack:function(){
-this.rawNode.parentNode.insertBefore(this.rawNode,this.rawNode.parentNode.firstChild);
-return this;
-}});
-dojo.declare("dojox.gfx.Group",g.Shape,{constructor:function(){
-_1.Container._init.call(this);
-},setRawNode:function(_13){
-this.rawNode=_13;
-}});
-g.Group.nodeType="g";
-dojo.declare("dojox.gfx.Rect",gs.Rect,{setShape:function(_14){
-this.shape=g.makeParameters(this.shape,_14);
-this.bbox=null;
-for(var i in this.shape){
-if(i!="type"&&i!="r"){
-this.rawNode.setAttribute(i,this.shape[i]);
-}
-}
-if(this.shape.r){
-this.rawNode.setAttribute("ry",this.shape.r);
-this.rawNode.setAttribute("rx",this.shape.r);
-}
-return this;
-}});
-g.Rect.nodeType="rect";
-g.Ellipse=gs.Ellipse;
-g.Ellipse.nodeType="ellipse";
-g.Circle=gs.Circle;
-g.Circle.nodeType="circle";
-g.Line=gs.Line;
-g.Line.nodeType="line";
-dojo.declare("dojox.gfx.Polyline",gs.Polyline,{setShape:function(_15,_16){
-if(_15&&_15 instanceof Array){
-this.shape=g.makeParameters(this.shape,{points:_15});
-if(_16&&this.shape.points.length){
-this.shape.points.push(this.shape.points[0]);
-}
-}else{
-this.shape=g.makeParameters(this.shape,_15);
-}
-this.bbox=null;
-this._normalizePoints();
-var _17=[],p=this.shape.points;
-for(var i=0;i<p.length;++i){
-_17.push(p[i].x.toFixed(8),p[i].y.toFixed(8));
-}
-this.rawNode.setAttribute("points",_17.join(" "));
-return this;
-}});
-g.Polyline.nodeType="polyline";
-dojo.declare("dojox.gfx.Image",gs.Image,{setShape:function(_18){
-this.shape=g.makeParameters(this.shape,_18);
-this.bbox=null;
-var _19=this.rawNode;
-for(var i in this.shape){
-if(i!="type"&&i!="src"){
-_19.setAttribute(i,this.shape[i]);
-}
-}
-_19.setAttribute("preserveAspectRatio","none");
-_19.setAttributeNS(_1.xmlns.xlink,"href",this.shape.src);
-return this;
-}});
-g.Image.nodeType="image";
-dojo.declare("dojox.gfx.Text",gs.Text,{setShape:function(_1a){
-this.shape=g.makeParameters(this.shape,_1a);
-this.bbox=null;
-var r=this.rawNode,s=this.shape;
-r.setAttribute("x",s.x);
-r.setAttribute("y",s.y);
-r.setAttribute("text-anchor",s.align);
-r.setAttribute("text-decoration",s.decoration);
-r.setAttribute("rotate",s.rotated?90:0);
-r.setAttribute("kerning",s.kerning?"auto":0);
-r.setAttribute("text-rendering","optimizeLegibility");
-if(!dojo.isIE){
-r.textContent=s.text;
-}else{
-r.appendChild(document.createTextNode(s.text));
-}
-return this;
-},getTextWidth:function(){
-var _1b=this.rawNode,_1c=_1b.parentNode,_1d=_1b.cloneNode(true);
-_1d.style.visibility="hidden";
-var _1e=0,_1f=_1d.firstChild.nodeValue;
-_1c.appendChild(_1d);
-if(_1f!=""){
-while(!_1e){
-_1e=parseInt(_1d.getBBox().width);
-}
-}
-_1c.removeChild(_1d);
-return _1e;
-}});
-g.Text.nodeType="text";
-dojo.declare("dojox.gfx.Path",g.path.Path,{_updateWithSegment:function(_20){
-g.Path.superclass._updateWithSegment.apply(this,arguments);
-if(typeof (this.shape.path)=="string"){
-this.rawNode.setAttribute("d",this.shape.path);
-}
-},setShape:function(_21){
-g.Path.superclass.setShape.apply(this,arguments);
-this.rawNode.setAttribute("d",this.shape.path);
-return this;
-}});
-g.Path.nodeType="path";
-dojo.declare("dojox.gfx.TextPath",g.path.TextPath,{_updateWithSegment:function(_22){
-g.Path.superclass._updateWithSegment.apply(this,arguments);
-this._setTextPath();
-},setShape:function(_23){
-g.Path.superclass.setShape.apply(this,arguments);
-this._setTextPath();
-return this;
-},_setTextPath:function(){
-if(typeof this.shape.path!="string"){
-return;
-}
-var r=this.rawNode;
-if(!r.firstChild){
-var tp=_2(_1.xmlns.svg,"textPath"),tx=document.createTextNode("");
-tp.appendChild(tx);
-r.appendChild(tp);
-}
-var ref=r.firstChild.getAttributeNS(_1.xmlns.xlink,"href"),_24=ref&&_1.getRef(ref);
-if(!_24){
-var _25=this._getParentSurface();
-if(_25){
-var _26=_25.defNode;
-_24=_2(_1.xmlns.svg,"path");
-var id=g._base._getUniqueId();
-_24.setAttribute("id",id);
-_26.appendChild(_24);
-r.firstChild.setAttributeNS(_1.xmlns.xlink,"href","#"+id);
-}
-}
-if(_24){
-_24.setAttribute("d",this.shape.path);
-}
-},_setText:function(){
-var r=this.rawNode;
-if(!r.firstChild){
-var tp=_2(_1.xmlns.svg,"textPath"),tx=document.createTextNode("");
-tp.appendChild(tx);
-r.appendChild(tp);
-}
-r=r.firstChild;
-var t=this.text;
-r.setAttribute("alignment-baseline","middle");
-switch(t.align){
-case "middle":
-r.setAttribute("text-anchor","middle");
-r.setAttribute("startOffset","50%");
-break;
-case "end":
-r.setAttribute("text-anchor","end");
-r.setAttribute("startOffset","100%");
-break;
-default:
-r.setAttribute("text-anchor","start");
-r.setAttribute("startOffset","0%");
-break;
-}
-r.setAttribute("baseline-shift","0.5ex");
-r.setAttribute("text-decoration",t.decoration);
-r.setAttribute("rotate",t.rotated?90:0);
-r.setAttribute("kerning",t.kerning?"auto":0);
-r.firstChild.data=t.text;
-}});
-g.TextPath.nodeType="text";
-dojo.declare("dojox.gfx.Surface",gs.Surface,{constructor:function(){
-_1.Container._init.call(this);
-},destroy:function(){
-this.defNode=null;
-this.inherited(arguments);
-},setDimensions:function(_27,_28){
-if(!this.rawNode){
-return this;
-}
-this.rawNode.setAttribute("width",_27);
-this.rawNode.setAttribute("height",_28);
-return this;
-},getDimensions:function(){
-var t=this.rawNode?{width:g.normalizedLength(this.rawNode.getAttribute("width")),height:g.normalizedLength(this.rawNode.getAttribute("height"))}:null;
-return t;
-}});
-g.createSurface=function(_29,_2a,_2b){
-var s=new g.Surface();
-s.rawNode=_2(_1.xmlns.svg,"svg");
-if(_2a){
-s.rawNode.setAttribute("width",_2a);
-}
-if(_2b){
-s.rawNode.setAttribute("height",_2b);
-}
-var _2c=_2(_1.xmlns.svg,"defs");
-s.rawNode.appendChild(_2c);
-s.defNode=_2c;
-s._parent=d.byId(_29);
-s._parent.appendChild(s.rawNode);
-return s;
-};
-_1.Font={_setFont:function(){
-var f=this.fontStyle;
-this.rawNode.setAttribute("font-style",f.style);
-this.rawNode.setAttribute("font-variant",f.variant);
-this.rawNode.setAttribute("font-weight",f.weight);
-this.rawNode.setAttribute("font-size",f.size);
-this.rawNode.setAttribute("font-family",f.family);
-}};
-_1.Container={_init:function(){
-gs.Container._init.call(this);
-},add:function(_2d){
-if(this!=_2d.getParent()){
-this.rawNode.appendChild(_2d.rawNode);
-gs.Container.add.apply(this,arguments);
-}
-return this;
-},remove:function(_2e,_2f){
-if(this==_2e.getParent()){
-if(this.rawNode==_2e.rawNode.parentNode){
-this.rawNode.removeChild(_2e.rawNode);
-}
-gs.Container.remove.apply(this,arguments);
-}
-return this;
-},clear:function(){
-var r=this.rawNode;
-while(r.lastChild){
-r.removeChild(r.lastChild);
-}
-var _30=this.defNode;
-if(_30){
-while(_30.lastChild){
-_30.removeChild(_30.lastChild);
-}
-r.appendChild(_30);
-}
-return gs.Container.clear.apply(this,arguments);
-},_moveChildToFront:gs.Container._moveChildToFront,_moveChildToBack:gs.Container._moveChildToBack};
-d.mixin(gs.Creator,{createObject:function(_31,_32){
-if(!this.rawNode){
-return null;
-}
-var _33=new _31(),_34=_2(_1.xmlns.svg,_31.nodeType);
-_33.setRawNode(_34);
-this.rawNode.appendChild(_34);
-_33.setShape(_32);
-this.add(_33);
-return _33;
-}});
-d.extend(g.Text,_1.Font);
-d.extend(g.TextPath,_1.Font);
-d.extend(g.Group,_1.Container);
-d.extend(g.Group,gs.Creator);
-d.extend(g.Surface,_1.Container);
-d.extend(g.Surface,gs.Creator);
+	var d = dojo, g = dojox.gfx, gs = g.shape, svg = g.svg;
+	svg.useSvgWeb = (typeof(window.svgweb)!=='undefined');
+	
+	var _createElementNS = function(ns, nodeType){
+		// summary:
+		//		Internal helper to deal with creating elements that
+		//		are namespaced.  Mainly to get SVG markup output
+		//		working on IE.
+		if(dojo.doc.createElementNS){
+			return dojo.doc.createElementNS(ns,nodeType);
+		}else{
+			return dojo.doc.createElement(nodeType);
+		}
+	}
+	
+	var _createTextNode = function(text) {
+		if (svg.useSvgWeb) {
+			return dojo.doc.createTextNode(text, true);
+		} else {
+			return dojo.doc.createTextNode(text);
+		}
+	}
+	
+	var _createFragment = function() {
+		if (svg.useSvgWeb) {
+			return dojo.doc.createDocumentFragment(true);
+		} else {
+			return dojo.doc.createDocumentFragment();
+		}
+	}
+
+	svg.xmlns = {
+		xlink: "http://www.w3.org/1999/xlink",
+		svg:   "http://www.w3.org/2000/svg"
+	};
+
+	svg.getRef = function(name){
+		// summary: returns a DOM Node specified by the name argument or null
+		// name: String: an SVG external reference
+		if(!name || name == "none") return null;
+		if(name.match(/^url\(#.+\)$/)){
+			return d.byId(name.slice(5, -1));	// Node
+		}
+		// alternative representation of a reference
+		if(name.match(/^#dojoUnique\d+$/)){
+			// we assume here that a reference was generated by dojox.gfx
+			return d.byId(name.slice(1));	// Node
+		}
+		return null;	// Node
+	};
+
+	svg.dasharray = {
+		solid:				"none",
+		shortdash:			[4, 1],
+		shortdot:			[1, 1],
+		shortdashdot:		[4, 1, 1, 1],
+		shortdashdotdot:	[4, 1, 1, 1, 1, 1],
+		dot:				[1, 3],
+		dash:				[4, 3],
+		longdash:			[8, 3],
+		dashdot:			[4, 3, 1, 3],
+		longdashdot:		[8, 3, 1, 3],
+		longdashdotdot:		[8, 3, 1, 3, 1, 3]
+	};
+
+	d.extend(g.Shape, {
+		// summary: SVG-specific implementation of dojox.gfx.Shape methods
+
+		setFill: function(fill){
+			// summary: sets a fill object (SVG)
+			// fill: Object: a fill object
+			//	(see dojox.gfx.defaultLinearGradient,
+			//	dojox.gfx.defaultRadialGradient,
+			//	dojox.gfx.defaultPattern,
+			//	or dojo.Color)
+
+			if(!fill){
+				// don't fill
+				this.fillStyle = null;
+				this.rawNode.setAttribute("fill", "none");
+				this.rawNode.setAttribute("fill-opacity", 0);
+				return this;
+			}
+			var f;
+			// FIXME: slightly magical. We're using the outer scope's "f", but setting it later
+			var setter = function(x){
+					// we assume that we're executing in the scope of the node to mutate
+					this.setAttribute(x, f[x].toFixed(8));
+				};
+			if(typeof(fill) == "object" && "type" in fill){
+				// gradient
+				switch(fill.type){
+					case "linear":
+						f = g.makeParameters(g.defaultLinearGradient, fill);
+						var gradient = this._setFillObject(f, "linearGradient");
+						d.forEach(["x1", "y1", "x2", "y2"], setter, gradient);
+						break;
+					case "radial":
+						f = g.makeParameters(g.defaultRadialGradient, fill);
+						var gradient = this._setFillObject(f, "radialGradient");
+						d.forEach(["cx", "cy", "r"], setter, gradient);
+						break;
+					case "pattern":
+						f = g.makeParameters(g.defaultPattern, fill);
+						var pattern = this._setFillObject(f, "pattern");
+						d.forEach(["x", "y", "width", "height"], setter, pattern);
+						break;
+				}
+				this.fillStyle = f;
+				return this;
+			}
+			// color object
+			var f = g.normalizeColor(fill);
+			this.fillStyle = f;
+			this.rawNode.setAttribute("fill", f.toCss());
+			this.rawNode.setAttribute("fill-opacity", f.a);
+			this.rawNode.setAttribute("fill-rule", "evenodd");
+			return this;	// self
+		},
+
+		setStroke: function(stroke){
+			//	summary:
+			//		sets a stroke object (SVG)
+			//	stroke: Object
+			// 		a stroke object (see dojox.gfx.defaultStroke)
+
+			var rn = this.rawNode;
+			if(!stroke){
+				// don't stroke
+				this.strokeStyle = null;
+				rn.setAttribute("stroke", "none");
+				rn.setAttribute("stroke-opacity", 0);
+				return this;
+			}
+			// normalize the stroke
+			if(typeof stroke == "string" || d.isArray(stroke) || stroke instanceof d.Color){
+				stroke = { color: stroke };
+			}
+			var s = this.strokeStyle = g.makeParameters(g.defaultStroke, stroke);
+			s.color = g.normalizeColor(s.color);
+			// generate attributes
+			if(s){
+				rn.setAttribute("stroke", s.color.toCss());
+				rn.setAttribute("stroke-opacity", s.color.a);
+				rn.setAttribute("stroke-width",   s.width);
+				rn.setAttribute("stroke-linecap", s.cap);
+				if(typeof s.join == "number"){
+					rn.setAttribute("stroke-linejoin",   "miter");
+					rn.setAttribute("stroke-miterlimit", s.join);
+				}else{
+					rn.setAttribute("stroke-linejoin",   s.join);
+				}
+				var da = s.style.toLowerCase();
+				if(da in svg.dasharray){
+					da = svg.dasharray[da];
+				}
+				if(da instanceof Array){
+					da = d._toArray(da);
+					for(var i = 0; i < da.length; ++i){
+						da[i] *= s.width;
+					}
+					if(s.cap != "butt"){
+						for(var i = 0; i < da.length; i += 2){
+							da[i] -= s.width;
+							if(da[i] < 1){ da[i] = 1; }
+						}
+						for(var i = 1; i < da.length; i += 2){
+							da[i] += s.width;
+						}
+					}
+					da = da.join(",");
+				}
+				rn.setAttribute("stroke-dasharray", da);
+				rn.setAttribute("dojoGfxStrokeStyle", s.style);
+			}
+			return this;	// self
+		},
+
+		_getParentSurface: function(){
+			var surface = this.parent;
+			for(; surface && !(surface instanceof g.Surface); surface = surface.parent);
+			return surface;
+		},
+
+		_setFillObject: function(f, nodeType){
+			var svgns = svg.xmlns.svg;
+			this.fillStyle = f;
+			var surface = this._getParentSurface(),
+				defs = surface.defNode,
+				fill = this.rawNode.getAttribute("fill"),
+				ref  = svg.getRef(fill);
+			if(ref){
+				fill = ref;
+				if(fill.tagName.toLowerCase() != nodeType.toLowerCase()){
+					var id = fill.id;
+					fill.parentNode.removeChild(fill);
+					fill = _createElementNS(svgns, nodeType);
+					fill.setAttribute("id", id);
+					defs.appendChild(fill);
+				}else{
+					while(fill.childNodes.length){
+						fill.removeChild(fill.lastChild);
+					}
+				}
+			}else{
+				fill = _createElementNS(svgns, nodeType);
+				fill.setAttribute("id", g._base._getUniqueId());
+				defs.appendChild(fill);
+			}
+			if(nodeType == "pattern"){
+				fill.setAttribute("patternUnits", "userSpaceOnUse");
+				var img = _createElementNS(svgns, "image");
+				img.setAttribute("x", 0);
+				img.setAttribute("y", 0);
+				img.setAttribute("width",  f.width .toFixed(8));
+				img.setAttribute("height", f.height.toFixed(8));
+				img.setAttributeNS(svg.xmlns.xlink, "xlink:href", f.src);
+				fill.appendChild(img);
+			}else{
+				fill.setAttribute("gradientUnits", "userSpaceOnUse");
+				for(var i = 0; i < f.colors.length; ++i){
+					var c = f.colors[i], t = _createElementNS(svgns, "stop"),
+						cc = c.color = g.normalizeColor(c.color);
+					t.setAttribute("offset",       c.offset.toFixed(8));
+					t.setAttribute("stop-color",   cc.toCss());
+					t.setAttribute("stop-opacity", cc.a);
+					fill.appendChild(t);
+				}
+			}
+			this.rawNode.setAttribute("fill", "url(#" + fill.getAttribute("id") +")");
+			this.rawNode.removeAttribute("fill-opacity");
+			this.rawNode.setAttribute("fill-rule", "evenodd");
+			return fill;
+		},
+
+		_applyTransform: function() {
+			var matrix = this.matrix;
+			if(matrix){
+				var tm = this.matrix;
+				this.rawNode.setAttribute("transform", "matrix(" +
+					tm.xx.toFixed(8) + "," + tm.yx.toFixed(8) + "," +
+					tm.xy.toFixed(8) + "," + tm.yy.toFixed(8) + "," +
+					tm.dx.toFixed(8) + "," + tm.dy.toFixed(8) + ")");
+			}else{
+				this.rawNode.removeAttribute("transform");
+			}
+			return this;
+		},
+
+		setRawNode: function(rawNode){
+			// summary:
+			//	assigns and clears the underlying node that will represent this
+			//	shape. Once set, transforms, gradients, etc, can be applied.
+			//	(no fill & stroke by default)
+			var r = this.rawNode = rawNode;
+			if(this.shape.type!="image"){
+				r.setAttribute("fill", "none");
+			}
+			r.setAttribute("fill-opacity", 0);
+			r.setAttribute("stroke", "none");
+			r.setAttribute("stroke-opacity", 0);
+			r.setAttribute("stroke-width", 1);
+			r.setAttribute("stroke-linecap", "butt");
+			r.setAttribute("stroke-linejoin", "miter");
+			r.setAttribute("stroke-miterlimit", 4);
+		},
+
+		setShape: function(newShape){
+			// summary: sets a shape object (SVG)
+			// newShape: Object: a shape object
+			//	(see dojox.gfx.defaultPath,
+			//	dojox.gfx.defaultPolyline,
+			//	dojox.gfx.defaultRect,
+			//	dojox.gfx.defaultEllipse,
+			//	dojox.gfx.defaultCircle,
+			//	dojox.gfx.defaultLine,
+			//	or dojox.gfx.defaultImage)
+			this.shape = g.makeParameters(this.shape, newShape);
+			for(var i in this.shape){
+				if(i != "type"){ this.rawNode.setAttribute(i, this.shape[i]); }
+			}
+			this.bbox = null;
+			return this;	// self
+		},
+
+		// move family
+
+		_moveToFront: function(){
+			// summary: moves a shape to front of its parent's list of shapes (SVG)
+			this.rawNode.parentNode.appendChild(this.rawNode);
+			return this;	// self
+		},
+		_moveToBack: function(){
+			// summary: moves a shape to back of its parent's list of shapes (SVG)
+			this.rawNode.parentNode.insertBefore(this.rawNode, this.rawNode.parentNode.firstChild);
+			return this;	// self
+		}
+	});
+
+	dojo.declare("dojox.gfx.Group", g.Shape, {
+		// summary: a group shape (SVG), which can be used
+		//	to logically group shapes (e.g, to propagate matricies)
+		constructor: function(){
+			svg.Container._init.call(this);
+		},
+		setRawNode: function(rawNode){
+			// summary: sets a raw SVG node to be used by this shape
+			// rawNode: Node: an SVG node
+			this.rawNode = rawNode;
+		}
+	});
+	g.Group.nodeType = "g";
+
+	dojo.declare("dojox.gfx.Rect", gs.Rect, {
+		// summary: a rectangle shape (SVG)
+		setShape: function(newShape){
+			// summary: sets a rectangle shape object (SVG)
+			// newShape: Object: a rectangle shape object
+			this.shape = g.makeParameters(this.shape, newShape);
+			this.bbox = null;
+			for(var i in this.shape){
+				if(i != "type" && i != "r"){ this.rawNode.setAttribute(i, this.shape[i]); }
+			}
+			if(this.shape.r){
+				this.rawNode.setAttribute("ry", this.shape.r);
+				this.rawNode.setAttribute("rx", this.shape.r);
+			}
+			return this;	// self
+		}
+	});
+	g.Rect.nodeType = "rect";
+
+	g.Ellipse = gs.Ellipse;
+	g.Ellipse.nodeType = "ellipse";
+
+	g.Circle = gs.Circle;
+	g.Circle.nodeType = "circle";
+
+	g.Line = gs.Line;
+	g.Line.nodeType = "line";
+
+	dojo.declare("dojox.gfx.Polyline", gs.Polyline, {
+		// summary: a polyline/polygon shape (SVG)
+		setShape: function(points, closed){
+			// summary: sets a polyline/polygon shape object (SVG)
+			// points: Object: a polyline/polygon shape object
+			if(points && points instanceof Array){
+				// branch
+				// points: Array: an array of points
+				this.shape = g.makeParameters(this.shape, { points: points });
+				if(closed && this.shape.points.length){
+					this.shape.points.push(this.shape.points[0]);
+				}
+			}else{
+				this.shape = g.makeParameters(this.shape, points);
+			}
+			this.bbox = null;
+			this._normalizePoints();
+			var attr = [], p = this.shape.points;
+			for(var i = 0; i < p.length; ++i){
+				attr.push(p[i].x.toFixed(8), p[i].y.toFixed(8));
+			}
+			this.rawNode.setAttribute("points", attr.join(" "));
+			return this;	// self
+		}
+	});
+	g.Polyline.nodeType = "polyline";
+
+	dojo.declare("dojox.gfx.Image", gs.Image, {
+		// summary: an image (SVG)
+		setShape: function(newShape){
+			// summary: sets an image shape object (SVG)
+			// newShape: Object: an image shape object
+			this.shape = g.makeParameters(this.shape, newShape);
+			this.bbox = null;
+			var rawNode = this.rawNode;
+			for(var i in this.shape){
+				if(i != "type" && i != "src"){ rawNode.setAttribute(i, this.shape[i]); }
+			}
+			rawNode.setAttribute("preserveAspectRatio", "none");
+			rawNode.setAttributeNS(svg.xmlns.xlink, "xlink:href", this.shape.src);
+			return this;	// self
+		}
+	});
+	g.Image.nodeType = "image";
+
+	dojo.declare("dojox.gfx.Text", gs.Text, {
+		// summary: an anchored text (SVG)
+		setShape: function(newShape){
+			// summary: sets a text shape object (SVG)
+			// newShape: Object: a text shape object
+			this.shape = g.makeParameters(this.shape, newShape);
+			this.bbox = null;
+			var r = this.rawNode, s = this.shape;
+			r.setAttribute("x", s.x);
+			r.setAttribute("y", s.y);
+			r.setAttribute("text-anchor", s.align);
+			r.setAttribute("text-decoration", s.decoration);
+			r.setAttribute("rotate", s.rotated ? 90 : 0);
+			r.setAttribute("kerning", s.kerning ? "auto" : 0);
+			r.setAttribute("text-rendering", "optimizeLegibility");
+			
+			// update the text content
+			if(r.firstChild){
+				r.firstChild.nodeValue = s.text;
+			}else{
+				r.appendChild(_createTextNode(s.text));
+			}
+			return this;	// self
+		},
+		getTextWidth: function(){
+			// summary: get the text width in pixels
+			var rawNode = this.rawNode,
+				oldParent = rawNode.parentNode,
+				_measurementNode = rawNode.cloneNode(true);
+			_measurementNode.style.visibility = "hidden";
+
+			// solution to the "orphan issue" in FF
+			var _width = 0, _text = _measurementNode.firstChild.nodeValue;
+			oldParent.appendChild(_measurementNode);
+
+			// solution to the "orphan issue" in Opera
+			// (nodeValue == "" hangs firefox)
+			if(_text!=""){
+				while(!_width){
+//Yang: work around svgweb bug 417 -- http://code.google.com/p/svgweb/issues/detail?id=417
+if (_measurementNode.getBBox)
+					_width = parseInt(_measurementNode.getBBox().width);
+else
+	_width = 68;
+				}
+			}
+			oldParent.removeChild(_measurementNode);
+			return _width;
+		}
+	});
+	g.Text.nodeType = "text";
+
+	dojo.declare("dojox.gfx.Path", g.path.Path, {
+		// summary: a path shape (SVG)
+		_updateWithSegment: function(segment){
+			// summary: updates the bounding box of path with new segment
+			// segment: Object: a segment
+			g.Path.superclass._updateWithSegment.apply(this, arguments);
+			if(typeof(this.shape.path) == "string"){
+				this.rawNode.setAttribute("d", this.shape.path);
+			}
+		},
+		setShape: function(newShape){
+			// summary: forms a path using a shape (SVG)
+			// newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+			g.Path.superclass.setShape.apply(this, arguments);
+			this.rawNode.setAttribute("d", this.shape.path);
+			return this;	// self
+		}
+	});
+	g.Path.nodeType = "path";
+
+	dojo.declare("dojox.gfx.TextPath", g.path.TextPath, {
+		// summary: a textpath shape (SVG)
+		_updateWithSegment: function(segment){
+			// summary: updates the bounding box of path with new segment
+			// segment: Object: a segment
+			g.Path.superclass._updateWithSegment.apply(this, arguments);
+			this._setTextPath();
+		},
+		setShape: function(newShape){
+			// summary: forms a path using a shape (SVG)
+			// newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+			g.Path.superclass.setShape.apply(this, arguments);
+			this._setTextPath();
+			return this;	// self
+		},
+		_setTextPath: function(){
+			if(typeof this.shape.path != "string"){ return; }
+			var r = this.rawNode;
+			if(!r.firstChild){
+				var tp = _createElementNS(svg.xmlns.svg, "textPath"),
+					tx = _createTextNode("");
+				tp.appendChild(tx);
+				r.appendChild(tp);
+			}
+			var ref  = r.firstChild.getAttributeNS(svg.xmlns.xlink, "href"),
+				path = ref && svg.getRef(ref);
+			if(!path){
+				var surface = this._getParentSurface();
+				if(surface){
+					var defs = surface.defNode;
+					path = _createElementNS(svg.xmlns.svg, "path");
+					var id = g._base._getUniqueId();
+					path.setAttribute("id", id);
+					defs.appendChild(path);
+					r.firstChild.setAttributeNS(svg.xmlns.xlink, "xlink:href", "#" + id);
+				}
+			}
+			if(path){
+				path.setAttribute("d", this.shape.path);
+			}
+		},
+		_setText: function(){
+			var r = this.rawNode;
+			if(!r.firstChild){
+				var tp = _createElementNS(svg.xmlns.svg, "textPath"),
+					tx = _createTextNode("");
+				tp.appendChild(tx);
+				r.appendChild(tp);
+			}
+			r = r.firstChild;
+			var t = this.text;
+			r.setAttribute("alignment-baseline", "middle");
+			switch(t.align){
+				case "middle":
+					r.setAttribute("text-anchor", "middle");
+					r.setAttribute("startOffset", "50%");
+					break;
+				case "end":
+					r.setAttribute("text-anchor", "end");
+					r.setAttribute("startOffset", "100%");
+					break;
+				default:
+					r.setAttribute("text-anchor", "start");
+					r.setAttribute("startOffset", "0%");
+					break;
+			}
+			//r.parentNode.setAttribute("alignment-baseline", "central");
+			//r.setAttribute("dominant-baseline", "central");
+			r.setAttribute("baseline-shift", "0.5ex");
+			r.setAttribute("text-decoration", t.decoration);
+			r.setAttribute("rotate", t.rotated ? 90 : 0);
+			r.setAttribute("kerning", t.kerning ? "auto" : 0);
+			r.firstChild.data = t.text;
+		}
+	});
+	g.TextPath.nodeType = "text";
+
+	dojo.declare("dojox.gfx.Surface", gs.Surface, {
+		// summary: a surface object to be used for drawings (SVG)
+		constructor: function(){
+			svg.Container._init.call(this);
+		},
+		destroy: function(){
+			this.defNode = null;	// release the external reference
+			this.inherited(arguments);
+		},
+		setDimensions: function(width, height){
+			// summary: sets the width and height of the rawNode
+			// width: String: width of surface, e.g., "100px"
+			// height: String: height of surface, e.g., "100px"
+			if(!this.rawNode){ return this; }
+			this.rawNode.setAttribute("width",  width);
+			this.rawNode.setAttribute("height", height);
+			return this;	// self
+		},
+		getDimensions: function(){
+			// summary: returns an object with properties "width" and "height"
+			var t = this.rawNode ? {
+				width:  g.normalizedLength(this.rawNode.getAttribute("width")),
+				height: g.normalizedLength(this.rawNode.getAttribute("height"))} : null;
+			return t;	// Object
+		}
+	});
+
+	g.createSurface = function(parentNode, width, height){
+		// summary: creates a surface (SVG)
+		// parentNode: Node: a parent node
+		// width: String: width of surface, e.g., "100px"
+		// height: String: height of surface, e.g., "100px"
+
+		var s = new g.Surface();
+		s.rawNode = _createElementNS(svg.xmlns.svg, "svg");
+		if(width){
+			s.rawNode.setAttribute("width",  width);
+		}
+		if(height){
+			s.rawNode.setAttribute("height", height);
+		}
+
+		var defNode = _createElementNS(svg.xmlns.svg, "defs");
+		s.rawNode.appendChild(defNode);
+		s.defNode = defNode;
+
+		s._parent = d.byId(parentNode);
+		s._parent.appendChild(s.rawNode);
+
+		return s;	// dojox.gfx.Surface
+	};
+
+	// Extenders
+
+	svg.Font = {
+		_setFont: function(){
+			// summary: sets a font object (SVG)
+			var f = this.fontStyle;
+			// next line doesn't work in Firefox 2 or Opera 9
+			//this.rawNode.setAttribute("font", dojox.gfx.makeFontString(this.fontStyle));
+			this.rawNode.setAttribute("font-style", f.style);
+			this.rawNode.setAttribute("font-variant", f.variant);
+			this.rawNode.setAttribute("font-weight", f.weight);
+			this.rawNode.setAttribute("font-size", f.size);
+			this.rawNode.setAttribute("font-family", f.family);
+		}
+	};
+
+	svg.Container = {
+		_init: function(){
+			gs.Container._init.call(this);
+		},
+		openBatch: function() {
+			// summary: starts a new batch, subsequent new child shapes will be held in
+			//	the batch instead of appending to the container directly
+			this.fragment = _createFragment();
+		},
+		closeBatch: function() {
+			// summary: submits the current batch, append all pending child shapes to DOM
+			if (this.fragment) {
+				this.rawNode.appendChild(this.fragment);
+				delete this.fragment;
+			}
+		},
+		add: function(shape){
+			// summary: adds a shape to a group/surface
+			// shape: dojox.gfx.Shape: an VML shape object
+			if(this != shape.getParent()){
+				if (this.fragment) {
+					this.fragment.appendChild(shape.rawNode);
+				} else {
+					this.rawNode.appendChild(shape.rawNode);
+				}
+				//dojox.gfx.Group.superclass.add.apply(this, arguments);
+				//this.inherited(arguments);
+				gs.Container.add.apply(this, arguments);
+			}
+			return this;	// self
+		},
+		remove: function(shape, silently){
+			// summary: remove a shape from a group/surface
+			// shape: dojox.gfx.Shape: an VML shape object
+			// silently: Boolean?: if true, regenerate a picture
+			if(this == shape.getParent()){
+				if(this.rawNode == shape.rawNode.parentNode){
+					this.rawNode.removeChild(shape.rawNode);
+				}
+				if(this.fragment && this.fragment == shape.rawNode.parentNode){
+					this.fragment.removeChild(shape.rawNode);
+				}
+				//dojox.gfx.Group.superclass.remove.apply(this, arguments);
+				//this.inherited(arguments);
+				gs.Container.remove.apply(this, arguments);
+			}
+			return this;	// self
+		},
+		clear: function(){
+			// summary: removes all shapes from a group/surface
+			var r = this.rawNode;
+			while(r.lastChild){
+				r.removeChild(r.lastChild);
+			}
+			var defNode = this.defNode;
+			if(defNode){
+				while(defNode.lastChild){
+					defNode.removeChild(defNode.lastChild);
+				}
+				r.appendChild(defNode);
+			}
+			//return this.inherited(arguments);	// self
+			return gs.Container.clear.apply(this, arguments);
+		},
+		_moveChildToFront: gs.Container._moveChildToFront,
+		_moveChildToBack:  gs.Container._moveChildToBack
+	};
+
+	d.mixin(gs.Creator, {
+		// summary: SVG shape creators
+		createObject: function(shapeType, rawShape){
+			// summary: creates an instance of the passed shapeType class
+			// shapeType: Function: a class constructor to create an instance of
+			// rawShape: Object: properties to be passed in to the classes "setShape" method
+			if(!this.rawNode){ return null; }
+			var shape = new shapeType(),
+				node = _createElementNS(svg.xmlns.svg, shapeType.nodeType);
+
+			shape.setRawNode(node);
+			shape.setShape(rawShape);
+			// rawNode.appendChild() will be done inside this.add(shape) below
+			this.add(shape);
+			return shape;	// dojox.gfx.Shape
+		}
+	});
+
+	d.extend(g.Text, svg.Font);
+	d.extend(g.TextPath, svg.Font);
+
+	d.extend(g.Group, svg.Container);
+	d.extend(g.Group, gs.Creator);
+
+	d.extend(g.Surface, svg.Container);
+	d.extend(g.Surface, gs.Creator);
+
+
+	// some specific override for svgweb + flash
+	if (svg.useSvgWeb) {
+		
+		// override createSurface()
+		g.createSurface = function(parentNode, width, height) {
+			var s = new g.Surface();
+
+			// ensure width / height
+			if (!width || !height) {
+				var pos = d.position(parentNode);
+				width  = width  || pos.w;
+				height = height || pos.h;
+			}
+
+			// ensure id
+			parentNode = d.byId(parentNode);
+			var id = parentNode.id ? parentNode.id+'_svgweb' : g._base._getUniqueId();
+			
+			// create dynamic svg root
+			var mockSvg = _createElementNS(svg.xmlns.svg, 'svg');
+			mockSvg.id = id;
+			mockSvg.setAttribute('width', width);
+			mockSvg.setAttribute('height', height);
+			svgweb.appendChild(mockSvg, parentNode);
+
+			// notice: any call to the raw node before flash init will fail.
+			mockSvg.addEventListener('SVGLoad', function() {
+				// become loaded
+				s.rawNode = this;
+				s.isLoaded = true;
+				
+				// init defs
+				var defNode = _createElementNS(svg.xmlns.svg, "defs");
+				s.rawNode.appendChild(defNode);
+				s.defNode = defNode;
+				
+				// notify application
+				if (s.onLoad)
+					s.onLoad(s);
+			}, false);
+
+			// flash not loaded yet
+			s.isLoaded = false;
+			return s;
+		}
+		
+		// override Surface.destroy()
+		dojo.extend(dojox.gfx.shape.Surface, {
+			destroy: function() {
+				var mockSvg = this.rawNode;
+				svgweb.removeChild(mockSvg, mockSvg.parentNode);
+			}
+		});
+
+		// override connect() & disconnect() for Shape & Surface event processing
+		gs._eventsProcessing.connect = function(name, object, method) {
+			// connect events using the mock addEventListener() provided by svgweb
+			if (name.substring(0, 2)==='on') { name = name.substring(2); }
+			if (arguments.length == 2) {
+				method = object;
+			} else {
+				method = d.hitch(object, method);
+			}
+			this.getEventSource().addEventListener(name, method, false);
+			return [this, name, method];
+		}
+		gs._eventsProcessing.disconnect = function(token) {
+			// disconnect events using the mock removeEventListener() provided by svgweb
+			this.getEventSource().removeEventListener(token[1], token[2], false);
+			delete token[0];
+		}
+		dojo.extend(dojox.gfx.Shape, dojox.gfx.shape._eventsProcessing);
+		dojo.extend(dojox.gfx.shape.Surface, dojox.gfx.shape._eventsProcessing);
+	}
+
 })();
-}
diff --git a/dojox/gfx/svg_attach.js b/dojox/gfx/svg_attach.js
index ff0e898..a7f6c88 100644
--- a/dojox/gfx/svg_attach.js
+++ b/dojox/gfx/svg_attach.js
@@ -1,191 +1,224 @@
-/*
-	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
-*/
-
-
 dojo.require("dojox.gfx.svg");
+
 dojo.experimental("dojox.gfx.svg_attach");
+
 (function(){
-dojox.gfx.attachNode=function(_1){
-if(!_1){
-return null;
-}
-var s=null;
-switch(_1.tagName.toLowerCase()){
-case dojox.gfx.Rect.nodeType:
-s=new dojox.gfx.Rect(_1);
-_2(s);
-break;
-case dojox.gfx.Ellipse.nodeType:
-s=new dojox.gfx.Ellipse(_1);
-_3(s,dojox.gfx.defaultEllipse);
-break;
-case dojox.gfx.Polyline.nodeType:
-s=new dojox.gfx.Polyline(_1);
-_3(s,dojox.gfx.defaultPolyline);
-break;
-case dojox.gfx.Path.nodeType:
-s=new dojox.gfx.Path(_1);
-_3(s,dojox.gfx.defaultPath);
-break;
-case dojox.gfx.Circle.nodeType:
-s=new dojox.gfx.Circle(_1);
-_3(s,dojox.gfx.defaultCircle);
-break;
-case dojox.gfx.Line.nodeType:
-s=new dojox.gfx.Line(_1);
-_3(s,dojox.gfx.defaultLine);
-break;
-case dojox.gfx.Image.nodeType:
-s=new dojox.gfx.Image(_1);
-_3(s,dojox.gfx.defaultImage);
-break;
-case dojox.gfx.Text.nodeType:
-var t=_1.getElementsByTagName("textPath");
-if(t&&t.length){
-s=new dojox.gfx.TextPath(_1);
-_3(s,dojox.gfx.defaultPath);
-_4(s);
-}else{
-s=new dojox.gfx.Text(_1);
-_5(s);
-}
-_6(s);
-break;
-default:
-return null;
-}
-if(!(s instanceof dojox.gfx.Image)){
-_7(s);
-_8(s);
-}
-_9(s);
-return s;
-};
-dojox.gfx.attachSurface=function(_a){
-var s=new dojox.gfx.Surface();
-s.rawNode=_a;
-var _b=_a.getElementsByTagName("defs");
-if(_b.length==0){
-return null;
-}
-s.defNode=_b[0];
-return s;
-};
-var _7=function(_c){
-var _d=_c.rawNode.getAttribute("fill");
-if(_d=="none"){
-_c.fillStyle=null;
-return;
-}
-var _e=null,_f=dojox.gfx.svg.getRef(_d);
-if(_f){
-switch(_f.tagName.toLowerCase()){
-case "lineargradient":
-_e=_10(dojox.gfx.defaultLinearGradient,_f);
-dojo.forEach(["x1","y1","x2","y2"],function(x){
-_e[x]=_f.getAttribute(x);
-});
-break;
-case "radialgradient":
-_e=_10(dojox.gfx.defaultRadialGradient,_f);
-dojo.forEach(["cx","cy","r"],function(x){
-_e[x]=_f.getAttribute(x);
-});
-_e.cx=_f.getAttribute("cx");
-_e.cy=_f.getAttribute("cy");
-_e.r=_f.getAttribute("r");
-break;
-case "pattern":
-_e=dojo.lang.shallowCopy(dojox.gfx.defaultPattern,true);
-dojo.forEach(["x","y","width","height"],function(x){
-_e[x]=_f.getAttribute(x);
-});
-_e.src=_f.firstChild.getAttributeNS(dojox.gfx.svg.xmlns.xlink,"href");
-break;
-}
-}else{
-_e=new dojo.Color(_d);
-var _11=_c.rawNode.getAttribute("fill-opacity");
-if(_11!=null){
-_e.a=_11;
-}
-}
-_c.fillStyle=_e;
-};
-var _10=function(_12,_13){
-var _14=dojo.clone(_12);
-_14.colors=[];
-for(var i=0;i<_13.childNodes.length;++i){
-_14.colors.push({offset:_13.childNodes[i].getAttribute("offset"),color:new dojo.Color(_13.childNodes[i].getAttribute("stop-color"))});
-}
-return _14;
-};
-var _8=function(_15){
-var _16=_15.rawNode,_17=_16.getAttribute("stroke");
-if(_17==null||_17=="none"){
-_15.strokeStyle=null;
-return;
-}
-var _18=_15.strokeStyle=dojo.clone(dojox.gfx.defaultStroke);
-var _19=new dojo.Color(_17);
-if(_19){
-_18.color=_19;
-_18.color.a=_16.getAttribute("stroke-opacity");
-_18.width=_16.getAttribute("stroke-width");
-_18.cap=_16.getAttribute("stroke-linecap");
-_18.join=_16.getAttribute("stroke-linejoin");
-if(_18.join=="miter"){
-_18.join=_16.getAttribute("stroke-miterlimit");
-}
-_18.style=_16.getAttribute("dojoGfxStrokeStyle");
-}
-};
-var _9=function(_1a){
-var _1b=_1a.rawNode.getAttribute("transform");
-if(_1b.match(/^matrix\(.+\)$/)){
-var t=_1b.slice(7,-1).split(",");
-_1a.matrix=dojox.gfx.matrix.normalize({xx:parseFloat(t[0]),xy:parseFloat(t[2]),yx:parseFloat(t[1]),yy:parseFloat(t[3]),dx:parseFloat(t[4]),dy:parseFloat(t[5])});
-}else{
-_1a.matrix=null;
-}
-};
-var _6=function(_1c){
-var _1d=_1c.fontStyle=dojo.clone(dojox.gfx.defaultFont),r=_1c.rawNode;
-_1d.style=r.getAttribute("font-style");
-_1d.variant=r.getAttribute("font-variant");
-_1d.weight=r.getAttribute("font-weight");
-_1d.size=r.getAttribute("font-size");
-_1d.family=r.getAttribute("font-family");
-};
-var _3=function(_1e,def){
-var _1f=_1e.shape=dojo.clone(def),r=_1e.rawNode;
-for(var i in _1f){
-_1f[i]=r.getAttribute(i);
-}
-};
-var _2=function(_20){
-_3(_20,dojox.gfx.defaultRect);
-_20.shape.r=Math.min(_20.rawNode.getAttribute("rx"),_20.rawNode.getAttribute("ry"));
-};
-var _5=function(_21){
-var _22=_21.shape=dojo.clone(dojox.gfx.defaultText),r=_21.rawNode;
-_22.x=r.getAttribute("x");
-_22.y=r.getAttribute("y");
-_22.align=r.getAttribute("text-anchor");
-_22.decoration=r.getAttribute("text-decoration");
-_22.rotated=parseFloat(r.getAttribute("rotate"))!=0;
-_22.kerning=r.getAttribute("kerning")=="auto";
-_22.text=r.firstChild.nodeValue;
-};
-var _4=function(_23){
-var _24=_23.shape=dojo.clone(dojox.gfx.defaultTextPath),r=_23.rawNode;
-_24.align=r.getAttribute("text-anchor");
-_24.decoration=r.getAttribute("text-decoration");
-_24.rotated=parseFloat(r.getAttribute("rotate"))!=0;
-_24.kerning=r.getAttribute("kerning")=="auto";
-_24.text=r.firstChild.nodeValue;
-};
+	dojox.gfx.attachNode = function(node){
+		// summary: creates a shape from a Node
+		// node: Node: an SVG node
+		if(!node) return null;
+		var s = null;
+		switch(node.tagName.toLowerCase()){
+			case dojox.gfx.Rect.nodeType:
+				s = new dojox.gfx.Rect(node);
+				attachRect(s);
+				break;
+			case dojox.gfx.Ellipse.nodeType:
+				s = new dojox.gfx.Ellipse(node);
+				attachShape(s, dojox.gfx.defaultEllipse);
+				break;
+			case dojox.gfx.Polyline.nodeType:
+				s = new dojox.gfx.Polyline(node);
+				attachShape(s, dojox.gfx.defaultPolyline);
+				break;
+			case dojox.gfx.Path.nodeType:
+				s = new dojox.gfx.Path(node);
+				attachShape(s, dojox.gfx.defaultPath);
+				break;
+			case dojox.gfx.Circle.nodeType:
+				s = new dojox.gfx.Circle(node);
+				attachShape(s, dojox.gfx.defaultCircle);
+				break;
+			case dojox.gfx.Line.nodeType:
+				s = new dojox.gfx.Line(node);
+				attachShape(s, dojox.gfx.defaultLine);
+				break;
+			case dojox.gfx.Image.nodeType:
+				s = new dojox.gfx.Image(node);
+				attachShape(s, dojox.gfx.defaultImage);
+				break;
+			case dojox.gfx.Text.nodeType:
+				var t = node.getElementsByTagName("textPath");
+				if(t && t.length){
+					s = new dojox.gfx.TextPath(node);
+					attachShape(s, dojox.gfx.defaultPath);
+					attachTextPath(s);
+				}else{
+					s = new dojox.gfx.Text(node);
+					attachText(s);
+				}
+				attachFont(s);
+				break;
+			default:
+				//console.debug("FATAL ERROR! tagName = " + node.tagName);
+				return null;
+		}
+		if(!(s instanceof dojox.gfx.Image)){
+			attachFill(s);
+			attachStroke(s);
+		}
+		attachTransform(s);
+		return s;	// dojox.gfx.Shape
+	};
+
+	dojox.gfx.attachSurface = function(node){
+		// summary: creates a surface from a Node
+		// node: Node: an SVG node
+		var s = new dojox.gfx.Surface();
+		s.rawNode = node;
+		var def_elems = node.getElementsByTagName("defs");
+		if(def_elems.length == 0){
+			return null;	// dojox.gfx.Surface
+		}
+		s.defNode = def_elems[0];
+		return s;	// dojox.gfx.Surface
+	};
+
+	var attachFill = function(object){
+		// summary: deduces a fill style from a node.
+		// object: dojox.gfx.Shape: an SVG shape
+		var fill = object.rawNode.getAttribute("fill");
+		if(fill == "none"){
+			object.fillStyle = null;
+			return;
+		}
+		var fillStyle = null, gradient = dojox.gfx.svg.getRef(fill);
+		if(gradient){
+			switch(gradient.tagName.toLowerCase()){
+				case "lineargradient":
+					fillStyle = _getGradient(dojox.gfx.defaultLinearGradient, gradient);
+					dojo.forEach(["x1", "y1", "x2", "y2"], function(x){
+						fillStyle[x] = gradient.getAttribute(x);
+					});
+					break;
+				case "radialgradient":
+					fillStyle = _getGradient(dojox.gfx.defaultRadialGradient, gradient);
+					dojo.forEach(["cx", "cy", "r"], function(x){
+						fillStyle[x] = gradient.getAttribute(x);
+					});
+					fillStyle.cx = gradient.getAttribute("cx");
+					fillStyle.cy = gradient.getAttribute("cy");
+					fillStyle.r  = gradient.getAttribute("r");
+					break;
+				case "pattern":
+					fillStyle = dojo.lang.shallowCopy(dojox.gfx.defaultPattern, true);
+					dojo.forEach(["x", "y", "width", "height"], function(x){
+						fillStyle[x] = gradient.getAttribute(x);
+					});
+					fillStyle.src = gradient.firstChild.getAttributeNS(dojox.gfx.svg.xmlns.xlink, "href");
+					break;
+			}
+		}else{
+			fillStyle = new dojo.Color(fill);
+			var opacity = object.rawNode.getAttribute("fill-opacity");
+			if(opacity != null){ fillStyle.a = opacity; }
+		}
+		object.fillStyle = fillStyle;
+	};
+
+	var _getGradient = function(defaultGradient, gradient){
+		var fillStyle = dojo.clone(defaultGradient);
+		fillStyle.colors = [];
+		for(var i = 0; i < gradient.childNodes.length; ++i){
+			fillStyle.colors.push({
+				offset: gradient.childNodes[i].getAttribute("offset"),
+				color:  new dojo.Color(gradient.childNodes[i].getAttribute("stop-color"))
+			});
+		}
+		return fillStyle;
+	};
+
+	var attachStroke = function(object){
+		// summary: deduces a stroke style from a node.
+		// object: dojox.gfx.Shape: an SVG shape
+		var rawNode = object.rawNode, stroke = rawNode.getAttribute("stroke");
+		if(stroke == null || stroke == "none"){
+			object.strokeStyle = null;
+			return;
+		}
+		var strokeStyle = object.strokeStyle = dojo.clone(dojox.gfx.defaultStroke);
+		var color = new dojo.Color(stroke);
+		if(color){
+			strokeStyle.color = color;
+			strokeStyle.color.a = rawNode.getAttribute("stroke-opacity");
+			strokeStyle.width = rawNode.getAttribute("stroke-width");
+			strokeStyle.cap = rawNode.getAttribute("stroke-linecap");
+			strokeStyle.join = rawNode.getAttribute("stroke-linejoin");
+			if(strokeStyle.join == "miter"){
+				strokeStyle.join = rawNode.getAttribute("stroke-miterlimit");
+			}
+			strokeStyle.style = rawNode.getAttribute("dojoGfxStrokeStyle");
+		}
+	};
+
+	var attachTransform = function(object){
+		// summary: deduces a transformation matrix from a node.
+		// object: dojox.gfx.Shape: an SVG shape
+		var matrix = object.rawNode.getAttribute("transform");
+		if(matrix.match(/^matrix\(.+\)$/)){
+			var t = matrix.slice(7, -1).split(",");
+			object.matrix = dojox.gfx.matrix.normalize({
+				xx: parseFloat(t[0]), xy: parseFloat(t[2]),
+				yx: parseFloat(t[1]), yy: parseFloat(t[3]),
+				dx: parseFloat(t[4]), dy: parseFloat(t[5])
+			});
+		}else{
+			object.matrix = null;
+		}
+	};
+
+	var attachFont = function(object){
+		// summary: deduces a font style from a Node.
+		// object: dojox.gfx.Shape: an SVG shape
+		var fontStyle = object.fontStyle = dojo.clone(dojox.gfx.defaultFont),
+			r = object.rawNode;
+		fontStyle.style = r.getAttribute("font-style");
+		fontStyle.variant = r.getAttribute("font-variant");
+		fontStyle.weight = r.getAttribute("font-weight");
+		fontStyle.size = r.getAttribute("font-size");
+		fontStyle.family = r.getAttribute("font-family");
+	};
+
+	var attachShape = function(object, def){
+		// summary: builds a shape from a node.
+		// object: dojox.gfx.Shape: an SVG shape
+		// def: Object: a default shape template
+		var shape = object.shape = dojo.clone(def), r = object.rawNode;
+		for(var i in shape) {
+			shape[i] = r.getAttribute(i);
+		}
+	};
+
+	var attachRect = function(object){
+		// summary: builds a rectangle shape from a node.
+		// object: dojox.gfx.Shape: an SVG shape
+		attachShape(object, dojox.gfx.defaultRect);
+		object.shape.r = Math.min(object.rawNode.getAttribute("rx"), object.rawNode.getAttribute("ry"));
+	};
+
+	var attachText = function(object){
+		// summary: builds a text shape from a node.
+		// object: dojox.gfx.Shape: an SVG shape
+		var shape = object.shape = dojo.clone(dojox.gfx.defaultText),
+			r = object.rawNode;
+		shape.x = r.getAttribute("x");
+		shape.y = r.getAttribute("y");
+		shape.align = r.getAttribute("text-anchor");
+		shape.decoration = r.getAttribute("text-decoration");
+		shape.rotated = parseFloat(r.getAttribute("rotate")) != 0;
+		shape.kerning = r.getAttribute("kerning") == "auto";
+		shape.text = r.firstChild.nodeValue;
+	};
+
+	var attachTextPath = function(object){
+		// summary: builds a textpath shape from a node.
+		// object: dojox.gfx.Shape: an SVG shape
+		var shape = object.shape = dojo.clone(dojox.gfx.defaultTextPath),
+			r = object.rawNode;
+		shape.align = r.getAttribute("text-anchor");
+		shape.decoration = r.getAttribute("text-decoration");
+		shape.rotated = parseFloat(r.getAttribute("rotate")) != 0;
+		shape.kerning = r.getAttribute("kerning") == "auto";
+		shape.text = r.firstChild.nodeValue;
+	};
 })();
diff --git a/dojox/gfx/tests/decompose.js b/dojox/gfx/tests/decompose.js
new file mode 100644
index 0000000..f49a81b
--- /dev/null
+++ b/dojox/gfx/tests/decompose.js
@@ -0,0 +1,110 @@
+dojo.provide("dojox.gfx.tests.decompose");
+dojo.require("dojox.gfx.decompose");
+
+(function(){
+	var m = dojox.gfx.matrix;
+	var eq = function(t, a, b){ t.t(2 * Math.abs(a - b) / ((a < 1 && b < 1) ? 1 : a + b) < 1e-6); };
+	var eqM = function(t, a, b){
+		eq(t, a.xx, b.xx);
+		eq(t, a.yy, b.yy);
+		eq(t, a.xy, b.xy);
+		eq(t, a.yx, b.yx);
+		eq(t, a.dx, b.dx);
+		eq(t, a.dy, b.dy);
+	};
+	var compose = function(r){
+		return m.normalize([
+			m.translate(r.dx, r.dy), 
+			m.rotate(r.angle2), 
+			m.scale(r.sx, r.sy),
+			m.rotate(r.angle1)
+		]);
+	};
+	var reconstruct = function(a){
+		return compose(dojox.gfx.decompose(a));
+	};
+	var compare = function(t, a){
+		var A = m.normalize(a);
+		eqM(t, A, reconstruct(A));
+	};
+	tests.register("dojox.gfx.tests.decompose", [
+		function IdentityTest(t){
+			compare(t, m.identity);
+		},
+		function FlipXTest(t){
+			compare(t, m.flipX);
+		},
+		function FlipYTest(t){
+			compare(t, m.flipY);
+		},
+		function FlipXYTest(t){
+			compare(t, m.flipXY);
+		},
+		function TranslationTest(t){
+			compare(t, m.translate(45, -15));
+		},
+		function RotationTest(t){
+			compare(t, m.rotateg(35));
+		},
+		function SkewXTest(t){
+			compare(t, m.skewXg(35));
+		},
+		function SkewYTest(t){
+			compare(t, m.skewYg(35));
+		},
+		function ReflectTest(t){
+			compare(t, m.reflect(13, 27));
+		},
+		function ProjectTest(t){
+			compare(t, m.project(13, 27));
+		},
+		function ScaleTest1(t){
+			compare(t, m.scale(3));
+		},
+		function ScaleTest2(t){
+			compare(t, m.scale(3, -1));
+		},
+		function ScaleTest3(t){
+			compare(t, m.scale(-3, 1));
+		},
+		function ScaleTest4(t){
+			compare(t, m.scale(-3, -1));
+		},
+		function ScaleRotateTest1(t){
+			compare(t, [m.scale(3), m.rotateAt(35, 13, 27)]);
+		},
+		function ScaleRotateTest2(t){
+			compare(t, [m.scale(3, -1), m.rotateAt(35, 13, 27)]);
+		},
+		function ScaleRotateTest3(t){
+			compare(t, [m.scale(-3, 1), m.rotateAt(35, 13, 27)]);
+		},
+		function ScaleRotateTest4(t){
+			compare(t, [m.scale(-3, -1), m.rotateAt(35, 13, 27)]);
+		},
+		function RotateScaleTest1(t){
+			compare(t, [m.rotateAt(35, 13, 27), m.scale(3)]);
+		},
+		function RotateScaleTest2(t){
+			compare(t, [m.rotateAt(35, 13, 27), m.scale(3, -1)]);
+		},
+		function RotateScaleTest3(t){
+			compare(t, [m.rotateAt(35, 13, 27), m.scale(-3, 1)]);
+		},
+		function RotateScaleTest4(t){
+			compare(t, [m.rotateAt(35, 13, 27), m.scale(-3, -1)]);
+		},
+		function RotateScaleRotateTest1(t){
+			compare(t, [m.rotateAt(35, 13, 27), m.scale(3), m.rotateAt(-15, 163, -287)]);
+		},
+		function RotateScaleRotateTest2(t){
+			compare(t, [m.rotateAt(35, 13, 27), m.scale(3, -1), m.rotateAt(-15, 163, -287)]);
+		},
+		function RotateScaleRotateTest3(t){
+			compare(t, [m.rotateAt(35, 13, 27), m.scale(-3, 1), m.rotateAt(-15, 163, -287)]);
+		},
+		function RotateScaleRotateTest4(t){
+			compare(t, [m.rotateAt(35, 13, 27), m.scale(-3, -1), m.rotateAt(-15, 163, -287)]);
+		}
+	]);
+})();
diff --git a/dojox/gfx/tests/images/eugene-sm.gif b/dojox/gfx/tests/images/eugene-sm.gif
new file mode 100644
index 0000000..b3523d5
Binary files /dev/null and b/dojox/gfx/tests/images/eugene-sm.gif differ
diff --git a/dojox/gfx/tests/images/eugene-sm.jpg b/dojox/gfx/tests/images/eugene-sm.jpg
new file mode 100644
index 0000000..cb6194a
Binary files /dev/null and b/dojox/gfx/tests/images/eugene-sm.jpg differ
diff --git a/dojox/gfx/tests/images/eugene-sm.png b/dojox/gfx/tests/images/eugene-sm.png
new file mode 100644
index 0000000..71de06d
Binary files /dev/null and b/dojox/gfx/tests/images/eugene-sm.png differ
diff --git a/dojox/gfx/tests/matrix.js b/dojox/gfx/tests/matrix.js
new file mode 100644
index 0000000..ac7d2dd
--- /dev/null
+++ b/dojox/gfx/tests/matrix.js
@@ -0,0 +1,224 @@
+dojo.provide("dojox.gfx.tests.matrix");
+dojo.require("dojox.gfx.matrix");
+
+(function(){
+	var m = dojox.gfx.matrix;
+	var eq = function(t, a, b){ t.t(2 * Math.abs(a - b) / ((a < 1 && b < 1) ? 1 : a + b) < 1e-6); };
+	tests.register("dojox.gfx.tests.matrix", [
+		function IdentityTest(t){
+			var a = new m.Matrix2D();
+			eq(t, a.xx, 1);
+			eq(t, a.yy, 1);
+			eq(t, a.xy, 0);
+			eq(t, a.yx, 0);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+		},
+		function Rot30gTest(t){
+			var a = m.rotateg(30);
+			eq(t, a.xx, a.yy);
+			eq(t, a.xy, -a.yx);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+			eq(t, a.yx, 0.5);
+			t.t(a.xy < 0);
+			t.t(a.yx > 0);
+		},
+		function Rot45gTest(t){
+			var a = m.rotateg(45);
+			eq(t, a.xx, a.yy);
+			eq(t, a.xy, -a.yx);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+			eq(t, a.xx, a.yx);
+			eq(t, a.yy, -a.xy);
+		},
+		function Rot90gTest(t){
+			var a = m.rotateg(90);
+			eq(t, a.xx, a.yy);
+			eq(t, a.xy, -a.yx);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+			eq(t, a.xx, 0);
+			eq(t, a.yx, 1);
+		},
+		function CombineIdentitiesTest(t){
+			var a = m.normalize([new m.Matrix2D(), new m.Matrix2D(), new m.Matrix2D()]);
+			eq(t, a.xx, 1);
+			eq(t, a.yy, 1);
+			eq(t, a.xy, 0);
+			eq(t, a.yx, 0);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+		},
+		function CombineExclusiveTest(t){
+			var a = m.normalize([m.rotateg(30), m.rotateg(-30)]);
+			eq(t, a.xx, 1);
+			eq(t, a.yy, 1);
+			eq(t, a.xy, 0);
+			eq(t, a.yx, 0);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+		},
+		function CombineInvertedTest(t){
+			var a = m.normalize([m.rotateg(30), m.invert(m.rotateg(30))]);
+			eq(t, a.xx, 1);
+			eq(t, a.yy, 1);
+			eq(t, a.xy, 0);
+			eq(t, a.yx, 0);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+		},
+		function Rot90gAtTest(t){
+			var a = m.rotategAt(90, 10, 10);
+			eq(t, a.xx, a.yy);
+			eq(t, a.xy, -a.yx);
+			eq(t, a.dx, 20);
+			eq(t, a.dy, 0);
+			eq(t, a.xx, 0);
+			eq(t, a.yx, 1);
+		},
+		function MultPointTest1(t){
+			var b = m.multiplyPoint(m.rotategAt(90, 10, 10), 10, 10);
+			eq(t, b.x, 10);
+			eq(t, b.y, 10);
+		},
+		function MultPointTest2(t){
+			var b = m.multiplyPoint(m.rotategAt(90, 10, 10), {x: 10, y: 5});
+			eq(t, b.x, 15);
+			eq(t, b.y, 10);
+		},
+		function MultPointTest3(t){
+			var b = m.multiplyPoint(m.rotategAt(90, 10, 10), 10, 15);
+			eq(t, b.x, 5);
+			eq(t, b.y, 10);
+		},
+		function ScaleTest1(t){
+			var a = m.normalize([m.scale(2, 1), m.invert(m.rotateg(45))]);
+			eq(t, a.xx, 2 * a.yy);
+			eq(t, a.xy, -2 * a.yx);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+			eq(t, a.xx, a.xy);
+			eq(t, a.yy, -a.yx);
+		},
+		function ScaleTest2(t){
+			var a = m.normalize([m.scale(1, 2), m.invert(m.rotateg(45))]);
+			eq(t, 2 * a.xx, a.yy);
+			eq(t, 2 * a.xy, -a.yx);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+			eq(t, a.xx, a.xy);
+			eq(t, a.yy, -a.yx);
+		},
+		function ScaleTest3(t){
+			var a = m.normalize([m.rotateg(45), m.scale(2, 1)]);
+			eq(t, a.xx, 2 * a.yy);
+			eq(t, a.yx, -2 * a.xy);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+			eq(t, a.xx, a.yx);
+			eq(t, a.yy, -a.xy);
+		},
+		function ScaleTest4(t){
+			var a = m.normalize([m.rotateg(45), m.scale(1, 2)]);
+			eq(t, 2 * a.xx, a.yy);
+			eq(t, 2 * a.yx, -a.xy);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+			eq(t, a.xx, a.yx);
+			eq(t, a.yy, -a.xy);
+		},
+		function ScaleTest5(t){
+			var a = m.normalize([m.rotategAt(45, 100, 100), m.scale(2)]);
+			eq(t, a.xx, a.yy);
+			eq(t, a.xy, -a.yx);
+			eq(t, a.xx, a.yx);
+			eq(t, a.yy, -a.xy);
+			eq(t, a.dx, 100);
+			t.t(a.dy < 0);
+			var b = m.normalize([m.scale(2), m.rotategAt(45, 100, 100)]);
+			eq(t, b.xx, b.yy);
+			eq(t, b.xy, -b.yx);
+			eq(t, b.xx, b.yx);
+			eq(t, b.yy, -b.xy);
+			eq(t, b.dx, 200);
+			t.t(b.dy < 0);
+			eq(t, a.xx, b.xx);
+			eq(t, a.xy, b.xy);
+			eq(t, a.yx, b.yx);
+			eq(t, a.yy, b.yy);
+			eq(t, 2 * a.dx, b.dx);
+			eq(t, 2 * a.dy, b.dy);
+			var c = m.normalize([m.rotateg(45), m.scale(2)]);
+			eq(t, c.xx, c.yy);
+			eq(t, c.xy, -c.yx);
+			eq(t, c.xx, c.yx);
+			eq(t, c.yy, -c.xy);
+			eq(t, c.dx, 0);
+			eq(t, c.dy, 0);
+			var d = m.normalize([m.scale(2), m.rotateg(45)]);
+			eq(t, d.xx, d.yy);
+			eq(t, d.xy, -d.yx);
+			eq(t, d.xx, d.yx);
+			eq(t, d.yy, -d.xy);
+			eq(t, d.dx, 0);
+			eq(t, d.dy, 0);
+			eq(t, a.xx, c.xx);
+			eq(t, a.xy, c.xy);
+			eq(t, a.yx, c.yx);
+			eq(t, a.yy, c.yy);
+			eq(t, a.xx, d.xx);
+			eq(t, a.xy, d.xy);
+			eq(t, a.yx, d.yx);
+			eq(t, a.yy, d.yy);
+		},
+		function ScaleTest6(t){
+			var a = m.normalize(6);
+			eq(t, a.xx, 6);
+			eq(t, a.yy, 6);
+			eq(t, a.xy, 0);
+			eq(t, a.yx, 0);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+		},
+		function ScaleTest7(t){
+			var a = m.normalize([2, m.scale(2, 1)]);
+			eq(t, a.xx, 4);
+			eq(t, a.yy, 2);
+			eq(t, a.xy, 0);
+			eq(t, a.yx, 0);
+			eq(t, a.dx, 0);
+			eq(t, a.dy, 0);
+		},
+		function TranslateTest(t){
+			var a = m.normalize({dx: 100, dy: 200});
+			eq(t, a.xx, 1);
+			eq(t, a.yy, 1);
+			eq(t, a.xy, 0);
+			eq(t, a.yx, 0);
+			eq(t, a.dx, 100);
+			eq(t, a.dy, 200);
+		},
+		function ReflectTest1(t){
+			var b = m.multiplyPoint(m.reflect(1, 1), 1, 0);
+			eq(t, b.x, 0);
+			eq(t, b.y, 1);
+		},
+		function ReflectTest2(t){
+			var b = m.multiplyPoint(m.reflect(1, 1), 0, 1);
+			eq(t, b.x, 1);
+			eq(t, b.y, 0);
+		},
+		function ProjectTest1(t){
+			var b = m.multiplyPoint(m.project(1, 1), 1, 0);
+			eq(t, b.x, 0.5);
+			eq(t, b.y, 0.5);
+		},
+		function ProjectTest2(t){
+			var b = m.multiplyPoint(m.project(1, 1), 0, 1);
+			eq(t, b.x, 0.5);
+			eq(t, b.y, 0.5);
+		}
+	]);
+})();
diff --git a/dojox/gfx/tests/module.js b/dojox/gfx/tests/module.js
new file mode 100644
index 0000000..b049f20
--- /dev/null
+++ b/dojox/gfx/tests/module.js
@@ -0,0 +1,10 @@
+dojo.provide("dojox.gfx.tests.module");
+
+try{
+	dojo.require("dojox.gfx.tests.matrix");
+	dojo.require("dojox.gfx.tests.decompose");
+	doh.registerUrl("GFX: Utils", dojo.moduleUrl("dojox", "gfx/tests/test_utils.html"), 3600000);
+}catch(e){
+	doh.debug(e);
+}
+
diff --git a/dojox/gfx/tests/performance/gfx_fill.html b/dojox/gfx/tests/performance/gfx_fill.html
new file mode 100755
index 0000000..7cdf43e
--- /dev/null
+++ b/dojox/gfx/tests/performance/gfx_fill.html
@@ -0,0 +1,199 @@
+<html>
+<head>
+<title>Testing Fill Performance</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../../../../util/doh/runner.js"></script>
+<script type="text/javascript">
+	dojo.require("doh.runner");
+	dojo.require("dojox.gfx");
+	dojo.require("dojo.colors");
+
+	
+	var surface;
+	createSurface = function(){
+		surface = dojox.gfx.createSurface("test", 500, 500);
+	};
+	
+	destroySurface = function(){
+		if(surface){
+			surface.destroy();
+			surface = null;
+		}
+	}
+	dojo.addOnLoad(function(){
+    	doh.register("gfx.fill.performance", [
+			{
+				name: "Fill Concentric Circles",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+                    createSurface();
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+					surface.clear();
+					var path = surface.createPath("");
+					 // form concentric circles
+					var center = {x: 250, y: 250};
+					for(var r = 200; r > 0; r -= 30){
+						// make two 180 degree arcs to form a circle
+						var start = {x: center.x, y: center.y - r};
+						var end   = {x: center.x, y: center.y + r};
+						path.moveTo(start).arcTo(r, r, 0, true, true, end).arcTo(r, r, 0, true, true, start).closePath();
+					}
+					// set visual attributes
+					path.setFill("red").setStroke("black");
+                 }
+            },
+			{
+				name: "Fill Square",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+                    createSurface();
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+					surface.clear();
+                    surface.createRect({ 
+						 width:  100,
+						 height: 100,
+                         x: 100,
+                         y: 100
+					}).setFill("blue").setStroke("black");
+                 }
+            },
+			{
+				name: "Fill Rectangle",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+                    createSurface();
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+					surface.clear();
+					var path = surface.createPath("");
+                    surface.createRect({ 
+						 width:  100,
+						 height: 200,
+                         x: 100,
+                         y: 100
+					}).setFill("red").setStroke("black");
+                 }
+            },
+			{
+				name: "Fill Circle",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+                    createSurface();
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+					surface.clear();
+                    surface.createEllipse({ 
+						 cx: 150,
+						 cy: 150,
+                         rx: 100,
+                         ry: 100
+					}).setFill("green").setStroke("black");
+                 }
+            },
+			{
+				name: "Fill Rectangle Linear Gradient",
+                testType: "perf",
+                trialDuration: 50,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+                    createSurface();
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+					 surface.clear();
+					 surface.createRect({ 
+						 width:  100,
+						 height: 75,
+                         x: 100,
+                         y: 100
+					 }).setFill({
+						 colors: [
+							 { offset: 0,   color: [255, 255, 0, 0] },
+							 { offset: 0.5, color: "red" },
+							 { offset: 1,   color: [255, 255, 0, 0] }
+						 ],
+						 type: "linear",
+						 x1: 0, 
+						 y1: 0,
+						 x2: 200, 
+						 y2: 0
+					 });
+                 }
+            },
+			{
+				name: "Fill Circle Linear Gradient",
+                testType: "perf",
+                trialDuration: 50,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+                    createSurface();
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+					 surface.clear();
+					 surface.createEllipse({ 
+						  cx: 150,
+						  cy: 150,
+						  rx: 100,
+						  ry: 100
+					 }).setFill({
+						colors: [
+							{ offset: 0,   color: [255, 255, 0, 0] },
+							{ offset: 0.5, color: "red" },
+							{ offset: 1,   color: [255, 255, 0, 0] }
+						],
+						type: "linear",
+						x1: 0, 
+						y1: 0,
+						x2: 200, 
+						y2: 0
+					 }).setStroke("black");
+                 }
+            }
+    	]);
+		doh.run();
+	});
+</script>
+</head>
+<body>
+<h1>Testing Fill Performance</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+</body>
+</html>
diff --git a/dojox/gfx/tests/performance/gfx_primitives.html b/dojox/gfx/tests/performance/gfx_primitives.html
new file mode 100755
index 0000000..73a3191
--- /dev/null
+++ b/dojox/gfx/tests/performance/gfx_primitives.html
@@ -0,0 +1,347 @@
+<html>
+<head>
+<title>Testing Primitives</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../../../../util/doh/runner.js"></script>
+<script type="text/javascript">
+	dojo.require("doh.runner");
+	dojo.require("dojox.gfx");
+	
+	var surface;
+	createSurface = function(){
+		surface = dojox.gfx.createSurface("test", 500, 500);
+	};
+	
+	destroySurface = function(){
+		if(surface){
+			surface.destroy();
+			surface = null;
+		}
+	}
+
+	var imageHref;
+
+	dojo.addOnLoad(function(){
+        imageHref = dojo.moduleUrl("dojox", "gfx/tests/performance/images/testImage.jpg").toString();
+    	doh.register("gfx.primitives.performance", [
+			{
+				name: "Line",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    var path = surface.createLine({
+                        x: 100,
+                        y: 100,
+                        x1: 200,
+                        y1: 200
+					}).setStroke({color: "black"});
+				}
+			},
+			{
+				name: "PolyLine",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    var path = surface.createPolyline([{
+							x: 100,
+							y: 100
+						},{
+							x: 200,
+							y: 200
+						},{
+							x: 150,
+							y: 200
+						},{
+							x: 150,
+							y: 100
+						}
+					]).setStroke({color: "black"});
+				}
+			},
+			{
+				name: "Path (lineTo)",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    var path = surface.createPath();
+					path.moveTo(100,100);
+					path.lineTo(200, 200);
+					path.lineTo(150, 200);
+					path.lineTo(150, 100);
+					path.setStroke({color: "black"});
+				}
+			},
+			{
+				name: "Path (hLineTo)",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    var path = surface.createPath();
+					path.moveTo(100,100);
+					path.hLineTo(200);
+					path.setStroke({color: "black"});
+				}
+			},
+			{
+				name: "Path (vLineTo)",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    var path = surface.createPath();
+					path.moveTo(100,100);
+					path.vLineTo(200);
+					path.setStroke({color: "black"});
+				}
+			},
+			{
+				name: "Path (qCurveTo)",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    var path = surface.createPath();
+					path.moveTo(50,50);
+					path.qCurveTo(175,150, 200,200);
+					path.setStroke({color: "black"});
+				}
+			},
+			{
+				name: "Path (qSmoothCurveTo)",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    var path = surface.createPath();
+					path.moveTo(50,50);
+					path.qCurveTo(175,150, 200,200);
+					path.qSmoothCurveTo(100,300);
+					path.setStroke({color: "black"});
+				}
+			},
+			{
+				name: "Path (arcTo)",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    var path = surface.createPath();
+					path.moveTo(50,50);
+					path.arcTo(75, 60, -30, false, true, 200,200);
+					path.setStroke({color: "black"});
+				}
+			},
+			{
+				name: "Image",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    surface.createImage({
+						src: imageHref,
+                        x: 50,
+                        y: 50,
+                        width: 300,
+                        height: 50
+					});
+				}
+			},
+			{
+				name: "Text",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    surface.createText({
+                        x: 50,
+                        y: 50,
+                        text: "I'm a bunch of text!"
+					}).setStroke({color: "black"});;
+				}
+			},
+			{
+				name: "Textpath",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    var tp = surface.createTextPath({
+                        text: "I'm a bunch of text!"
+					});
+					tp.moveTo(50, 100);
+                    tp.arcTo(75, 60, -30, false, true, 200,200);
+					tp.setStroke({color: "black"});
+				}
+			},
+			{
+				name: "Rectangle",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    surface.createRect({
+                        x: 100,
+                        y: 100,
+                        width: 200,
+                        height: 50
+					}).setStroke({color: "black"});
+				}
+			},
+			{
+				name: "Circle",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    surface.createCircle({
+                        cx: 150,
+                        cy: 150,
+                        r: 100
+					}).setStroke({color: "black"});
+				}
+			},
+			{
+				name: "Ellipse",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 50,
+                setUp: function() {
+					createSurface();
+                },
+                tearDown: function(){
+					destroySurface();
+                },
+                runTest: function(){
+                    surface.clear();
+                    surface.createEllipse({
+                        cx: 150,
+                        cy: 150,
+                        rx: 100,
+                        ry: 50
+					}).setStroke({color: "black"});
+				}
+			}
+    	]);
+		doh.run();
+	});
+</script>
+</head>
+<body>
+<h1>Testing Primitive Shapes</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+</body>
+</html>
diff --git a/dojox/gfx/tests/performance/gfx_scenes.html b/dojox/gfx/tests/performance/gfx_scenes.html
new file mode 100755
index 0000000..552a3dc
--- /dev/null
+++ b/dojox/gfx/tests/performance/gfx_scenes.html
@@ -0,0 +1,2277 @@
+<html>
+<head>
+<title>Testing Scenes</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../../../../util/doh/runner.js"></script>
+<script type="text/javascript">
+	dojo.require("doh.runner");
+	dojo.require("dojox.gfx");
+	
+	var surface;
+	createSurface = function(){
+		surface = dojox.gfx.createSurface("test", 700, 700);
+	};
+	
+	destroySurface = function(){
+		if(surface){
+			surface.destroy();
+			surface = null;
+		}
+	};
+
+	var gfxGroup;
+	var matrix;
+	
+	var rotateTiger = function(){
+        var angle = Math.floor(Math.random()*360)/2;
+        if(angle < 180){
+            angle = angle * -1;
+		}else{
+            angle = angle - 180;
+		}
+		if(gfxGroup){ gfxGroup.setTransform([dojox.gfx.matrix.rotategAt(angle, 350, 350), matrix]); }
+	};
+
+
+	var scaleTiger = function(){
+        var scaling = Math.floor(Math.random()*101);
+        if(!scaling){
+            scaling = 1;
+		}
+        scaling = scaling/100;
+        scaling = Math.exp(Math.LN10 * (scaling - 1));
+		if(gfxGroup){ gfxGroup.setTransform([dojox.gfx.matrix.scaleAt(scaling, 350, 350), matrix]); }
+	};
+
+	var scaleAndRotateTiger = function(){
+        var scaling = Math.floor(Math.random()*101);
+        if(!scaling){
+            scaling = 1;
+		}
+        scaling = scaling/100;
+        scaling = Math.exp(Math.LN10 * (scaling - 1));
+        var angle = Math.floor(Math.random()*360)/2;
+        if(angle < 180){
+            angle = angle * -1;
+		}else{
+            angle = angle - 180;
+		}
+		if(gfxGroup){ gfxGroup.setTransform([dojox.gfx.matrix.rotategAt(angle, 350, 350), dojox.gfx.matrix.scaleAt(scaling, 350, 350), matrix]); }
+	};
+
+
+	dojo.addOnLoad(function(){
+    	doh.register("gfx.scenes.performance", [
+			{
+				name: "Draw Tiger",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 20,
+                setUp: function() {
+                    createSurface();
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+					var f, g;
+                    surface.clear();
+					var initial_matrix = dojox.gfx.matrix.translate(250, 250);
+					surface.createRect({x: 0, y: 0, width: 700, height: 700}).setFill("#eee");
+					g = surface.createGroup().setTransform(initial_matrix);
+					var s = {color: "black", width: 1};
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-118.774 81.262C-118.774 81.262 -119.323 83.078 -120.092 82.779C-120.86 82.481 -119.977 31.675 -140.043 26.801C-140.043 26.801 -120.82 25.937 -118.774 81.262z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-91.284 123.59C-91.284 123.59 -89.648 124.55 -90.118 125.227C-90.589 125.904 -139.763 113.102 -149.218 131.459C-149.218 131.459 -145.539 112.572 -91.284 123.59z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-94.093 133.801C-94.093 133.801 -92.237 134.197 -92.471 134.988C-92.704 135.779 -143.407 139.121 -146.597 159.522C-146.597 159.522 -149.055 140.437 -94.093 133.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-98.304 128.276C-98.304 128.276 -96.526 128.939 -96.872 129.687C-97.218 130.435 -147.866 126.346 -153.998 146.064C-153.998 146.064 -153.646 126.825 -98.304 128.276z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-109.009 110.072C-109.009 110.072 -107.701 111.446 -108.34 111.967C-108.979 112.488 -152.722 86.634 -166.869 101.676C-166.869 101.676 -158.128 84.533 -109.009 110.072z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-116.554 114.263C-116.554 114.263 -115.098 115.48 -115.674 116.071C-116.25 116.661 -162.638 95.922 -174.992 112.469C-174.992 112.469 -168.247 94.447 -116.554 114.263z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-119.154 118.335C-119.154 118.335 -117.546 119.343 -118.036 120.006C-118.526 120.669 -167.308 106.446 -177.291 124.522C-177.291 124.522 -173.066 105.749 -119.154 118.335z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-108.42 118.949C-108.42 118.949 -107.298 120.48 -107.999 120.915C-108.7 121.35 -148.769 90.102 -164.727 103.207C-164.727 103.207 -153.862 87.326 -108.42 118.949z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-128.2 90C-128.2 90 -127.6 91.8 -128.4 92C-129.2 92.2 -157.8 50.2 -177.001 57.8C-177.001 57.8 -161.8 46 -128.2 90z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-127.505 96.979C-127.505 96.979 -126.53 98.608 -127.269 98.975C-128.007 99.343 -164.992 64.499 -182.101 76.061C-182.101 76.061 -169.804 61.261 -127.505 96.979z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-127.62 101.349C-127.62 101.349 -126.498 102.88 -127.199 103.315C-127.9 103.749 -167.969 72.502 -183.927 85.607C-183.927 85.607 -173.062 69.726 -127.62 101.349z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = "#000000";
+					g.createPath("M-129.83 103.065C-129.327 109.113 -128.339 115.682 -126.6 118.801C-126.6 118.801 -130.2 131.201 -121.4 144.401C-121.4 144.401 -121.8 151.601 -120.2 154.801C-120.2 154.801 -116.2 163.201 -111.4 164.001C-107.516 164.648 -98.793 167.717 -88.932 169.121C-88.932 169.121 -71.8 183.201 -75 196.001C-75 196.001 -75.4 212.401 -79 214.001C-79 214.001 -67.4 202.801 -77 219.601L-81.4 238.401C-81.4 238.401 -55.8 216.801 -71.4 235.201L-81.4 261.201C-81.4 261.201 -61.8 242.801 -69 251 [...]
+					f = "#cc7226"; s = "#000000";
+					g.createPath("M299.717 80.245C300.345 80.426 302.551 81.55 303.801 83.2C303.801 83.2 310.601 94 305.401 75.6C305.401 75.6 296.201 46.8 305.001 58C305.001 58 311.001 65.2 307.801 51.6C303.936 35.173 301.401 28.8 301.401 28.8C301.401 28.8 313.001 33.6 286.201 -6L295.001 -2.4C295.001 -2.4 275.401 -42 253.801 -47.2L245.801 -53.2C245.801 -53.2 284.201 -91.2 271.401 -128C271.401 -128 264.601 -133.2 255.001 -124C255.001 -124 248.601 -119.2 242.601 -120.8C242.601 -120.8 211.801 -119.6 209.8 [...]
+					f = "#cc7226"; s = null;
+					g.createPath("M-115.6 102.6C-140.6 63.2 -126.2 119.601 -126.2 119.601C-117.4 154.001 12.2 116.401 12.2 116.401C12.2 116.401 181.001 86 192.201 82C203.401 78 298.601 84.4 298.601 84.4L293.001 67.6C228.201 21.2 209.001 44.4 195.401 40.4C181.801 36.4 184.201 46 181.001 46.8C177.801 47.6 138.601 22.8 132.201 23.6C125.801 24.4 100.459 0.649 115.401 32.4C131.401 66.4 57 71.6 40.2 60.4C23.4 49.2 47.4 78.8 47.4 78.8C65.8 98.8 31.4 82 31.4 82C-3 69.2 -27 94.8 -30.2 95.6C-33.4 96.4 -38.2 99.6 [...]
+					f = "#e87f3a";
+					g.createPath("M133.51 25.346C127.11 26.146 101.743 2.407 116.71 34.146C133.31 69.346 58.31 73.346 41.51 62.146C24.709 50.946 48.71 80.546 48.71 80.546C67.11 100.546 32.709 83.746 32.709 83.746C-1.691 70.946 -25.691 96.546 -28.891 97.346C-32.091 98.146 -36.891 101.346 -37.691 94.946C-38.491 88.546 -45.87 72.012 -77.691 98.146C-98.927 115.492 -112.418 94.037 -112.418 94.037L-115.618 104.146C-140.618 64.346 -125.546 122.655 -125.546 122.655C-116.745 157.056 13.509 118.146 13.509 118.14 [...]
+					f = "#ea8c4d";
+					g.createPath("M134.819 27.091C128.419 27.891 103.685 3.862 118.019 35.891C134.219 72.092 59.619 75.092 42.819 63.892C26.019 52.692 50.019 82.292 50.019 82.292C68.419 102.292 34.019 85.492 34.019 85.492C-0.381 72.692 -24.382 98.292 -27.582 99.092C-30.782 99.892 -35.582 103.092 -36.382 96.692C-37.182 90.292 -44.43 73.925 -76.382 99.892C-98.855 117.983 -112.036 97.074 -112.036 97.074L-115.636 105.692C-139.436 66.692 -124.891 125.71 -124.891 125.71C-116.091 160.11 14.819 119.892 14.819  [...]
+					f = "#ec9961";
+					g.createPath("M136.128 28.837C129.728 29.637 104.999 5.605 119.328 37.637C136.128 75.193 60.394 76.482 44.128 65.637C27.328 54.437 51.328 84.037 51.328 84.037C69.728 104.037 35.328 87.237 35.328 87.237C0.928 74.437 -23.072 100.037 -26.272 100.837C-29.472 101.637 -34.272 104.837 -35.072 98.437C-35.872 92.037 -42.989 75.839 -75.073 101.637C-98.782 120.474 -111.655 100.11 -111.655 100.11L-115.655 107.237C-137.455 70.437 -124.236 128.765 -124.236 128.765C-115.436 163.165 16.128 121.637  [...]
+					f = "#eea575";
+					g.createPath("M137.438 30.583C131.037 31.383 106.814 7.129 120.637 39.383C137.438 78.583 62.237 78.583 45.437 67.383C28.637 56.183 52.637 85.783 52.637 85.783C71.037 105.783 36.637 88.983 36.637 88.983C2.237 76.183 -21.763 101.783 -24.963 102.583C-28.163 103.383 -32.963 106.583 -33.763 100.183C-34.563 93.783 -41.548 77.752 -73.763 103.383C-98.709 122.965 -111.273 103.146 -111.273 103.146L-115.673 108.783C-135.473 73.982 -123.582 131.819 -123.582 131.819C-114.782 166.22 17.437 123.38 [...]
+					f = "#f1b288";
+					g.createPath("M138.747 32.328C132.347 33.128 106.383 9.677 121.947 41.128C141.147 79.928 63.546 80.328 46.746 69.128C29.946 57.928 53.946 87.528 53.946 87.528C72.346 107.528 37.946 90.728 37.946 90.728C3.546 77.928 -20.454 103.528 -23.654 104.328C-26.854 105.128 -31.654 108.328 -32.454 101.928C-33.254 95.528 -40.108 79.665 -72.454 105.128C-98.636 125.456 -110.891 106.183 -110.891 106.183L-115.691 110.328C-133.691 77.128 -122.927 134.874 -122.927 134.874C-114.127 169.274 18.746 125.1 [...]
+					f = "#f3bf9c";
+					g.createPath("M140.056 34.073C133.655 34.873 107.313 11.613 123.255 42.873C143.656 82.874 64.855 82.074 48.055 70.874C31.255 59.674 55.255 89.274 55.255 89.274C73.655 109.274 39.255 92.474 39.255 92.474C4.855 79.674 -19.145 105.274 -22.345 106.074C-25.545 106.874 -30.345 110.074 -31.145 103.674C-31.945 97.274 -38.668 81.578 -71.145 106.874C-98.564 127.947 -110.509 109.219 -110.509 109.219L-115.709 111.874C-131.709 81.674 -122.273 137.929 -122.273 137.929C-113.473 172.329 20.055 126. [...]
+					f = "#f5ccb0";
+					g.createPath("M141.365 35.819C134.965 36.619 107.523 13.944 124.565 44.619C146.565 84.219 66.164 83.819 49.364 72.619C32.564 61.419 56.564 91.019 56.564 91.019C74.964 111.019 40.564 94.219 40.564 94.219C6.164 81.419 -17.836 107.019 -21.036 107.819C-24.236 108.619 -29.036 111.819 -29.836 105.419C-30.636 99.019 -37.227 83.492 -69.836 108.619C-98.491 130.438 -110.127 112.256 -110.127 112.256L-115.727 113.419C-130.128 85.019 -121.618 140.983 -121.618 140.983C-112.818 175.384 21.364 128. [...]
+					f = "#f8d8c4";
+					g.createPath("M142.674 37.565C136.274 38.365 108.832 15.689 125.874 46.365C147.874 85.965 67.474 85.565 50.674 74.365C33.874 63.165 57.874 92.765 57.874 92.765C76.274 112.765 41.874 95.965 41.874 95.965C7.473 83.165 -16.527 108.765 -19.727 109.565C-22.927 110.365 -27.727 113.565 -28.527 107.165C-29.327 100.765 -35.786 85.405 -68.527 110.365C-98.418 132.929 -109.745 115.293 -109.745 115.293L-115.745 114.965C-129.346 88.564 -120.963 144.038 -120.963 144.038C-112.163 178.438 22.673 130 [...]
+					f = "#fae5d7";
+					g.createPath("M143.983 39.31C137.583 40.11 110.529 17.223 127.183 48.11C149.183 88.91 68.783 87.31 51.983 76.11C35.183 64.91 59.183 94.51 59.183 94.51C77.583 114.51 43.183 97.71 43.183 97.71C8.783 84.91 -15.217 110.51 -18.417 111.31C-21.618 112.11 -26.418 115.31 -27.218 108.91C-28.018 102.51 -34.346 87.318 -67.218 112.11C-98.345 135.42 -109.363 118.329 -109.363 118.329L-115.764 116.51C-128.764 92.51 -120.309 147.093 -120.309 147.093C-111.509 181.493 23.983 132.11 23.983 132.11C23.98 [...]
+					f = "#fcf2eb";
+					g.createPath("M145.292 41.055C138.892 41.855 112.917 18.411 128.492 49.855C149.692 92.656 70.092 89.056 53.292 77.856C36.492 66.656 60.492 96.256 60.492 96.256C78.892 116.256 44.492 99.456 44.492 99.456C10.092 86.656 -13.908 112.256 -17.108 113.056C-20.308 113.856 -25.108 117.056 -25.908 110.656C-26.708 104.256 -32.905 89.232 -65.908 113.856C-98.273 137.911 -108.982 121.365 -108.982 121.365L-115.782 118.056C-128.582 94.856 -119.654 150.147 -119.654 150.147C-110.854 184.547 25.292 13 [...]
+					f = "#ffffff";
+					g.createPath("M-115.8 119.601C-128.6 97.6 -119 153.201 -119 153.201C-110.2 187.601 26.6 135.601 26.6 135.601C26.6 135.601 195.401 105.2 206.601 101.2C217.801 97.2 303.401 102.8 303.401 102.8L298.601 80.4C233.801 34 223.401 63.6 209.801 59.6C196.201 55.6 198.601 65.2 195.401 66C192.201 66.8 153.001 42 146.601 42.8C140.201 43.6 114.981 19.793 129.801 51.6C152.028 99.307 69.041 89.227 54.6 79.6C37.8 68.4 61.8 98 61.8 98C80.2 118.001 45.8 101.2 45.8 101.2C11.4 88.4 -12.6 114.001 -15.8 1 [...]
+					f = "#000000";
+					g.createPath("M-74.2 149.601C-74.2 149.601 -81.4 161.201 -60.6 174.401C-60.6 174.401 -59.2 175.801 -77.2 171.601C-77.2 171.601 -83.4 169.601 -85 159.201C-85 159.201 -89.8 154.801 -94.6 149.201C-99.4 143.601 -74.2 149.601 -74.2 149.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M65.8 102C65.8 102 83.498 128.821 82.9 133.601C81.6 144.001 81.4 153.601 84.6 157.601C87.801 161.601 96.601 194.801 96.601 194.801C96.601 194.801 96.201 196.001 108.601 158.001C108.601 158.001 120.201 142.001 100.201 123.601C100.201 123.601 65 94.8 65.8 102z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-54.2 176.401C-54.2 176.401 -43 183.601 -57.4 214.801L-51 212.401C-51 212.401 -51.8 223.601 -55 226.001L-47.8 222.801C-47.8 222.801 -43 230.801 -47 235.601C-47 235.601 -30.2 243.601 -31 250.001C-31 250.001 -24.6 242.001 -28.6 235.601C-32.6 229.201 -39.8 233.201 -39 214.801L-47.8 218.001C-47.8 218.001 -42.2 209.201 -42.2 202.801L-50.2 205.201C-50.2 205.201 -34.731 178.623 -45.4 177.201C-51.4 176.401 -54.2 176.401 -54.2 176.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-21.8 193.201C-21.8 193.201 -19 188.801 -21.8 189.601C-24.6 190.401 -55.8 205.201 -61.8 214.801C-61.8 214.801 -27.4 190.401 -21.8 193.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-11.4 201.201C-11.4 201.201 -8.6 196.801 -11.4 197.601C-14.2 198.401 -45.4 213.201 -51.4 222.801C-51.4 222.801 -17 198.401 -11.4 201.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M1.8 186.001C1.8 186.001 4.6 181.601 1.8 182.401C-1 183.201 -32.2 198.001 -38.2 207.601C-38.2 207.601 -3.8 183.201 1.8 186.001z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-21.4 229.601C-21.4 229.601 -21.4 223.601 -24.2 224.401C-27 225.201 -63 242.801 -69 252.401C-69 252.401 -27 226.801 -21.4 229.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-20.2 218.801C-20.2 218.801 -19 214.001 -21.8 214.801C-23.8 214.801 -50.2 226.401 -56.2 236.001C-56.2 236.001 -26.6 214.401 -20.2 218.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-34.6 266.401L-44.6 274.001C-44.6 274.001 -34.2 266.401 -30.6 267.601C-30.6 267.601 -37.4 278.801 -38.2 284.001C-38.2 284.001 -27.8 271.201 -22.2 271.601C-22.2 271.601 -14.6 272.001 -14.6 282.801C-14.6 282.801 -9 272.401 -5.8 272.801C-5.8 272.801 -4.6 279.201 -5.8 286.001C-5.8 286.001 -1.8 278.401 2.2 280.001C2.2 280.001 8.6 278.001 7.8 289.601C7.8 289.601 7.8 300.001 7 302.801C7 302.801 12.6 276.401 15 276.001C15 276.001 23 274.801 27.8 283.601C27.8 283.601 23.8 276. [...]
+					f = "#000000";
+					g.createPath("M-29.8 173.601C-29.8 173.601 -15 167.601 25 173.601C25 173.601 32.2 174.001 39 165.201C45.8 156.401 72.6 149.201 79 151.201L88.601 157.601L89.401 158.801C89.401 158.801 101.801 169.201 102.201 176.801C102.601 184.401 87.801 232.401 78.2 248.401C68.6 264.401 59 276.801 39.8 274.401C39.8 274.401 19 270.401 -6.6 274.401C-6.6 274.401 -35.8 272.801 -38.6 264.801C-41.4 256.801 -27.4 241.601 -27.4 241.601C-27.4 241.601 -23 233.201 -24.2 218.801C-25.4 204.401 -25 176.401 -29.8 [...]
+					f = "#e5668c";
+					g.createPath("M-7.8 175.601C0.6 194.001 -29 259.201 -29 259.201C-31 260.801 -16.34 266.846 -6.2 264.401C4.746 261.763 45 266.001 45 266.001C68.6 250.401 81.4 206.001 81.4 206.001C81.4 206.001 91.801 182.001 74.2 178.801C56.6 175.601 -7.8 175.601 -7.8 175.601z").setFill(f).setStroke(s);
+					f = "#b23259";
+					g.createPath("M-9.831 206.497C-6.505 193.707 -4.921 181.906 -7.8 175.601C-7.8 175.601 54.6 182.001 65.8 161.201C70.041 153.326 84.801 184.001 84.4 193.601C84.4 193.601 21.4 208.001 6.6 196.801L-9.831 206.497z").setFill(f).setStroke(s);
+					f = "#a5264c";
+					g.createPath("M-5.4 222.801C-5.4 222.801 -3.4 230.001 -5.8 234.001C-5.8 234.001 -7.4 234.801 -8.6 235.201C-8.6 235.201 -7.4 238.801 -1.4 240.401C-1.4 240.401 0.6 244.801 3 245.201C5.4 245.601 10.2 251.201 14.2 250.001C18.2 248.801 29.4 244.801 29.4 244.801C29.4 244.801 35 241.601 43.8 245.201C43.8 245.201 46.175 244.399 46.6 240.401C47.1 235.701 50.2 232.001 52.2 230.001C54.2 228.001 63.8 215.201 62.6 214.801C61.4 214.401 -5.4 222.801 -5.4 222.801z").setFill(f).setStroke(s);
+					f = "#ff727f"; s = "#000000";
+					g.createPath("M-9.8 174.401C-9.8 174.401 -12.6 196.801 -9.4 205.201C-6.2 213.601 -7 215.601 -7.8 219.601C-8.6 223.601 -4.2 233.601 1.4 239.601L13.4 241.201C13.4 241.201 28.6 237.601 37.8 240.401C37.8 240.401 46.794 241.744 50.2 226.801C50.2 226.801 55 220.401 62.2 217.601C69.4 214.801 76.6 173.201 72.6 165.201C68.6 157.201 54.2 152.801 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-8.2 249.201C-8.2 249.201 -9 247.201 -13.4 246.801C-13.4 246.801 -35.8 243.201 -44.2 230.801C-44.2 230.801 -51 225.201 -46.6 236.801C-46.6 236.801 -36.2 257.201 -29.4 260.001C-29.4 260.001 -13 264.001 -8.2 249.201z").setFill(f).setStroke(s);
+					f = "#cc3f4c"; s = null;
+					g.createPath("M71.742 185.229C72.401 177.323 74.354 168.709 72.6 165.201C66.154 152.307 49.181 157.695 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401C-9.8 174.401 -11.545 188.364 -10.705 198.376C-10.705 198.376 26.6 186.801 27.4 192.401C27.4 192.401 29 189.201 38.2 189.201C47.4 189.201 70.142 188.029 71.742 185.229z").setFill(f).setStroke(s);
+					s = {color: "#a51926", width: 2}; f = null;
+					g.createPath("M28.6 175.201C28.6 175.201 33.4 180.001 29.8 189.601C29.8 189.601 15.4 205.601 17.4 219.601").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-19.4 260.001C-19.4 260.001 -23.8 247.201 -15 254.001C-15 254.001 -10.2 256.001 -11.4 257.601C-12.6 259.201 -18.2 263.201 -19.4 260.001z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-14.36 261.201C-14.36 261.201 -17.88 250.961 -10.84 256.401C-10.84 256.401 -6.419 258.849 -7.96 259.281C-12.52 260.561 -7.96 263.121 -14.36 261.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-9.56 261.201C-9.56 261.201 -13.08 250.961 -6.04 256.401C-6.04 256.401 -1.665 258.711 -3.16 259.281C-6.52 260.561 -3.16 263.121 -9.56 261.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-2.96 261.401C-2.96 261.401 -6.48 251.161 0.56 256.601C0.56 256.601 4.943 258.933 3.441 259.481C0.48 260.561 3.441 263.321 -2.96 261.401z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M3.52 261.321C3.52 261.321 0 251.081 7.041 256.521C7.041 256.521 10.881 258.121 9.921 259.401C8.961 260.681 9.921 263.241 3.52 261.321z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M10.2 262.001C10.2 262.001 5.4 249.601 14.6 256.001C14.6 256.001 19.4 258.001 18.2 259.601C17 261.201 18.2 264.401 10.2 262.001z").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2}; f = null;
+					g.createPath("M-18.2 244.801C-18.2 244.801 -5 242.001 1 245.201C1 245.201 7 246.401 8.2 246.001C9.4 245.601 12.6 245.201 12.6 245.201").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2};
+					g.createPath("M15.8 253.601C15.8 253.601 27.8 240.001 39.8 244.401C46.816 246.974 45.8 243.601 46.6 240.801C47.4 238.001 47.6 233.801 52.6 230.801").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M33 237.601C33 237.601 29 226.801 26.2 239.601C23.4 252.401 20.2 256.001 18.6 258.801C18.6 258.801 18.6 264.001 27 263.601C27 263.601 37.8 263.201 38.2 260.401C38.6 257.601 37 246.001 33 237.601z").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2}; f = null;
+					g.createPath("M47 244.801C47 244.801 50.6 242.401 53 243.601").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2};
+					g.createPath("M53.5 228.401C53.5 228.401 56.4 223.501 61.2 222.701").setFill(f).setStroke(s);
+					f = "#b2b2b2"; s = null;
+					g.createPath("M-25.8 265.201C-25.8 265.201 -7.8 268.401 -3.4 266.801C-3.4 266.801 5.4 266.801 -3 268.801C-3 268.801 -15.8 268.801 -23.8 267.601C-23.8 267.601 -35.4 262.001 -25.8 265.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-11.8 172.001C-11.8 172.001 5.8 172.001 7.8 172.801C7.8 172.801 15 203.601 11.4 211.201C11.4 211.201 10.2 214.001 7.4 208.401C7.4 208.401 -11 175.601 -14.2 173.601C-17.4 171.601 -13 172.001 -11.8 172.001z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-88.9 169.301C-88.9 169.301 -80 171.001 -67.4 173.601C-67.4 173.601 -62.6 196.001 -59.4 200.801C-56.2 205.601 -59.8 205.601 -63.4 202.801C-67 200.001 -81.8 186.001 -83.8 181.601C-85.8 177.201 -88.9 169.301 -88.9 169.301z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-67.039 173.818C-67.039 173.818 -61.239 175.366 -60.23 177.581C-59.222 179.795 -61.432 183.092 -61.432 183.092C-61.432 183.092 -62.432 186.397 -63.634 184.235C-64.836 182.072 -67.708 174.412 -67.039 173.818z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M-67 173.601C-67 173.601 -63.4 178.801 -59.8 178.801C-56.2 178.801 -55.818 178.388 -53 179.001C-48.4 180.001 -48.8 178.001 -42.2 179.201C-39.56 179.681 -37 178.801 -34.2 180.001C-31.4 181.201 -28.2 180.401 -27 178.401C-25.8 176.401 -21 172.201 -21 172.201C-21 172.201 -33.8 174.001 -36.6 174.801C-36.6 174.801 -59 176.001 -67 173.601z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-22.4 173.801C-22.4 173.801 -28.85 177.301 -29.25 179.701C-29.65 182.101 -24 185.801 -24 185.801C-24 185.801 -21.25 190.401 -20.65 188.001C-20.05 185.601 -21.6 174.201 -22.4 173.801z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-59.885 179.265C-59.885 179.265 -52.878 190.453 -52.661 179.242C-52.661 179.242 -52.104 177.984 -53.864 177.962C-59.939 177.886 -58.418 173.784 -59.885 179.265z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-52.707 179.514C-52.707 179.514 -44.786 190.701 -45.422 179.421C-45.422 179.421 -45.415 179.089 -47.168 178.936C-51.915 178.522 -51.57 174.004 -52.707 179.514z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-45.494 179.522C-45.494 179.522 -37.534 190.15 -38.203 180.484C-38.203 180.484 -38.084 179.251 -39.738 178.95C-43.63 178.244 -43.841 174.995 -45.494 179.522z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-38.618 179.602C-38.618 179.602 -30.718 191.163 -30.37 181.382C-30.37 181.382 -28.726 180.004 -30.472 179.782C-36.29 179.042 -35.492 174.588 -38.618 179.602z").setFill(f).setStroke(s);
+					f = "#e5e5b2"; s = null;
+					g.createPath("M-74.792 183.132L-82.45 181.601C-85.05 176.601 -87.15 170.451 -87.15 170.451C-87.15 170.451 -80.8 171.451 -68.3 174.251C-68.3 174.251 -67.424 177.569 -65.952 183.364L-74.792 183.132z").setFill(f).setStroke(s);
+					f = "#e5e5b2";
+					g.createPath("M-9.724 178.47C-11.39 175.964 -12.707 174.206 -13.357 173.8C-16.37 171.917 -12.227 172.294 -11.098 172.294C-11.098 172.294 5.473 172.294 7.356 173.047C7.356 173.047 7.88 175.289 8.564 178.68C8.564 178.68 -1.524 176.67 -9.724 178.47z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M43.88 40.321C71.601 44.281 97.121 8.641 98.881 -1.04C100.641 -10.72 90.521 -22.6 90.521 -22.6C91.841 -25.68 87.001 -39.76 81.721 -49C76.441 -58.24 60.54 -57.266 43 -58.24C27.16 -59.12 8.68 -35.8 7.36 -34.04C6.04 -32.28 12.2 6.001 13.52 11.721C14.84 17.441 12.2 43.841 12.2 43.841C46.44 34.741 16.16 36.361 43.88 40.321z").setFill(f).setStroke(s);
+					f = "#ea8e51";
+					g.createPath("M8.088 -33.392C6.792 -31.664 12.84 5.921 14.136 11.537C15.432 17.153 12.84 43.073 12.84 43.073C45.512 34.193 16.728 35.729 43.944 39.617C71.161 43.505 96.217 8.513 97.945 -0.992C99.673 -10.496 89.737 -22.16 89.737 -22.16C91.033 -25.184 86.281 -39.008 81.097 -48.08C75.913 -57.152 60.302 -56.195 43.08 -57.152C27.528 -58.016 9.384 -35.12 8.088 -33.392z").setFill(f).setStroke(s);
+					f = "#efaa7c";
+					g.createPath("M8.816 -32.744C7.544 -31.048 13.48 5.841 14.752 11.353C16.024 16.865 13.48 42.305 13.48 42.305C44.884 33.145 17.296 35.097 44.008 38.913C70.721 42.729 95.313 8.385 97.009 -0.944C98.705 -10.272 88.953 -21.72 88.953 -21.72C90.225 -24.688 85.561 -38.256 80.473 -47.16C75.385 -56.064 60.063 -55.125 43.16 -56.064C27.896 -56.912 10.088 -34.44 8.816 -32.744z").setFill(f).setStroke(s);
+					f = "#f4c6a8";
+					g.createPath("M9.544 -32.096C8.296 -30.432 14.12 5.761 15.368 11.169C16.616 16.577 14.12 41.537 14.12 41.537C43.556 32.497 17.864 34.465 44.072 38.209C70.281 41.953 94.409 8.257 96.073 -0.895C97.737 -10.048 88.169 -21.28 88.169 -21.28C89.417 -24.192 84.841 -37.504 79.849 -46.24C74.857 -54.976 59.824 -54.055 43.24 -54.976C28.264 -55.808 10.792 -33.76 9.544 -32.096z").setFill(f).setStroke(s);
+					f = "#f9e2d3";
+					g.createPath("M10.272 -31.448C9.048 -29.816 14.76 5.681 15.984 10.985C17.208 16.289 14.76 40.769 14.76 40.769C42.628 31.849 18.432 33.833 44.136 37.505C69.841 41.177 93.505 8.129 95.137 -0.848C96.769 -9.824 87.385 -20.84 87.385 -20.84C88.609 -23.696 84.121 -36.752 79.225 -45.32C74.329 -53.888 59.585 -52.985 43.32 -53.888C28.632 -54.704 11.496 -33.08 10.272 -31.448z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M44.2 36.8C69.4 40.4 92.601 8 94.201 -0.8C95.801 -9.6 86.601 -20.4 86.601 -20.4C87.801 -23.2 83.4 -36 78.6 -44.4C73.8 -52.8 59.346 -51.914 43.4 -52.8C29 -53.6 12.2 -32.4 11 -30.8C9.8 -29.2 15.4 5.6 16.6 10.8C17.8 16 15.4 40 15.4 40C40.9 31.4 19 33.2 44.2 36.8z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M90.601 2.8C90.601 2.8 62.8 10.4 51.2 8.8C51.2 8.8 35.4 2.2 26.6 24C26.6 24 23 31.2 21 33.2C19 35.2 90.601 2.8 90.601 2.8z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M94.401 0.6C94.401 0.6 65.4 12.8 55.4 12.4C55.4 12.4 39 7.8 30.6 22.4C30.6 22.4 22.2 31.6 19 33.2C19 33.2 18.6 34.8 25 30.8L35.4 36C35.4 36 50.2 45.6 59.8 29.6C59.8 29.6 63.8 18.4 63.8 16.4C63.8 14.4 85 8.8 86.601 8.4C88.201 8 94.801 3.8 94.401 0.6z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M47 36.514C40.128 36.514 31.755 32.649 31.755 26.4C31.755 20.152 40.128 13.887 47 13.887C53.874 13.887 59.446 18.952 59.446 25.2C59.446 31.449 53.874 36.514 47 36.514z").setFill(f).setStroke(s);
+					f = "#659900";
+					g.createPath("M43.377 19.83C38.531 20.552 33.442 22.055 33.514 21.839C35.054 17.22 41.415 13.887 47 13.887C51.296 13.887 55.084 15.865 57.32 18.875C57.32 18.875 52.004 18.545 43.377 19.83z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M55.4 19.6C55.4 19.6 51 16.4 51 18.6C51 18.6 54.6 23 55.4 19.6z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M45.4 27.726C42.901 27.726 40.875 25.7 40.875 23.2C40.875 20.701 42.901 18.675 45.4 18.675C47.9 18.675 49.926 20.701 49.926 23.2C49.926 25.7 47.9 27.726 45.4 27.726z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M-58.6 14.4C-58.6 14.4 -61.8 -6.8 -59.4 -11.2C-59.4 -11.2 -48.6 -21.2 -49 -24.8C-49 -24.8 -49.4 -42.8 -50.6 -43.6C-51.8 -44.4 -59.4 -50.4 -65.4 -44C-65.4 -44 -75.8 -26 -75 -19.6L-75 -17.6C-75 -17.6 -82.6 -18 -84.2 -16C-84.2 -16 -85.4 -10.8 -86.6 -10.4C-86.6 -10.4 -89.4 -8 -87.4 -5.2C-87.4 -5.2 -89.4 -2.8 -89 1.2L-81.4 5.2C-81.4 5.2 -79.4 19.6 -68.6 24.8C-63.764 27.129 -60.6 20.4 -58.6 14.4z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M-59.6 12.56C-59.6 12.56 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.48 -40.36 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.96 -59.6 12.56z").setF [...]
+					f = "#eb955c";
+					g.createPath("M-51.05 -42.61C-52.14 -43.47 -59.63 -49.24 -65.48 -43C-65.48 -43 -75.62 -25.45 -74.84 -19.21L-74.84 -17.26C-74.84 -17.26 -82.25 -17.65 -83.81 -15.7C-83.81 -15.7 -84.98 -10.63 -86.15 -10.24C-86.15 -10.24 -88.88 -7.9 -86.93 -5.17C-86.93 -5.17 -88.88 -2.83 -88.49 1.07L-81.08 4.97C-81.08 4.97 -79.13 19.01 -68.6 24.08C-63.886 26.35 -60.8 19.79 -58.85 13.94C-58.85 13.94 -61.97 -6.73 -59.63 -11.02C-59.63 -11.02 -49.1 -20.77 -49.49 -24.28C-49.49 -24.28 -49.88 -41.83 -51.05 -42 [...]
+					f = "#f2b892";
+					g.createPath("M-51.5 -41.62C-52.48 -42.54 -59.86 -48.08 -65.56 -42C-65.56 -42 -75.44 -24.9 -74.68 -18.82L-74.68 -16.92C-74.68 -16.92 -81.9 -17.3 -83.42 -15.4C-83.42 -15.4 -84.56 -10.46 -85.7 -10.08C-85.7 -10.08 -88.36 -7.8 -86.46 -5.14C-86.46 -5.14 -88.36 -2.86 -87.98 0.94L-80.76 4.74C-80.76 4.74 -78.86 18.42 -68.6 23.36C-64.006 25.572 -61 19.18 -59.1 13.48C-59.1 13.48 -62.14 -6.66 -59.86 -10.84C-59.86 -10.84 -49.6 -20.34 -49.98 -23.76C-49.98 -23.76 -50.36 -40.86 -51.5 -41.62z").set [...]
+					f = "#f8dcc8";
+					g.createPath("M-51.95 -40.63C-52.82 -41.61 -60.09 -46.92 -65.64 -41C-65.64 -41 -75.26 -24.35 -74.52 -18.43L-74.52 -16.58C-74.52 -16.58 -81.55 -16.95 -83.03 -15.1C-83.03 -15.1 -84.14 -10.29 -85.25 -9.92C-85.25 -9.92 -87.84 -7.7 -85.99 -5.11C-85.99 -5.11 -87.84 -2.89 -87.47 0.81L-80.44 4.51C-80.44 4.51 -78.59 17.83 -68.6 22.64C-64.127 24.794 -61.2 18.57 -59.35 13.02C-59.35 13.02 -62.31 -6.59 -60.09 -10.66C-60.09 -10.66 -50.1 -19.91 -50.47 -23.24C-50.47 -23.24 -50.84 -39.89 -51.95 -40. [...]
+					f = "#ffffff";
+					g.createPath("M-59.6 12.46C-59.6 12.46 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.16 -40.68 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.86 -59.6 12.46z").setF [...]
+					f = "#cccccc";
+					g.createPath("M-62.7 6.2C-62.7 6.2 -84.3 -4 -85.2 -4.8C-85.2 -4.8 -76.1 3.4 -75.3 3.4C-74.5 3.4 -62.7 6.2 -62.7 6.2z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-79.8 0C-79.8 0 -61.4 3.6 -61.4 8C-61.4 10.912 -61.643 24.331 -67 22.8C-75.4 20.4 -71.8 6 -79.8 0z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M-71.4 3.8C-71.4 3.8 -62.422 5.274 -61.4 8C-60.8 9.6 -60.137 17.908 -65.6 19C-70.152 19.911 -72.382 9.69 -71.4 3.8z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M14.595 46.349C14.098 44.607 15.409 44.738 17.2 44.2C19.2 43.6 31.4 39.8 32.2 37.2C33 34.6 46.2 39 46.2 39C48 39.8 52.4 42.4 52.4 42.4C57.2 43.6 63.8 44 63.8 44C66.2 45 69.6 47.8 69.6 47.8C84.2 58 96.601 50.8 96.601 50.8C116.601 44.2 110.601 27 110.601 27C107.601 18 110.801 14.6 110.801 14.6C111.001 10.8 118.201 17.2 118.201 17.2C120.801 21.4 121.601 26.4 121.601 26.4C129.601 37.6 126.201 19.8 126.201 19.8C126.401 18.8 123.601 15.2 123.601 14C123.601 12.8 121.801 9.4 1 [...]
+					f = "#000000";
+					g.createPath("M209.401 -120C209.401 -120 183.801 -112 181.001 -93.2C181.001 -93.2 178.601 -70.4 199.001 -52.8C199.001 -52.8 199.401 -46.4 201.401 -43.2C201.401 -43.2 199.801 -38.4 218.601 -46L245.801 -54.4C245.801 -54.4 252.201 -56.8 257.401 -65.6C262.601 -74.4 277.801 -93.2 274.201 -118.4C274.201 -118.4 275.401 -129.6 269.401 -130C269.401 -130 261.001 -131.6 253.801 -124C253.801 -124 247.001 -120.8 244.601 -121.2L209.401 -120z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M264.022 -120.99C264.022 -120.99 266.122 -129.92 261.282 -125.08C261.282 -125.08 254.242 -119.36 246.761 -119.36C246.761 -119.36 232.241 -117.16 227.841 -103.96C227.841 -103.96 223.881 -77.12 231.801 -71.4C231.801 -71.4 236.641 -63.92 243.681 -70.52C250.722 -77.12 266.222 -107.35 264.022 -120.99z").setFill(f).setStroke(s);
+					f = "#323232";
+					g.createPath("M263.648 -120.632C263.648 -120.632 265.738 -129.376 260.986 -124.624C260.986 -124.624 254.074 -119.008 246.729 -119.008C246.729 -119.008 232.473 -116.848 228.153 -103.888C228.153 -103.888 224.265 -77.536 232.041 -71.92C232.041 -71.92 236.793 -64.576 243.705 -71.056C250.618 -77.536 265.808 -107.24 263.648 -120.632z").setFill(f).setStroke(s);
+					f = "#666666";
+					g.createPath("M263.274 -120.274C263.274 -120.274 265.354 -128.832 260.69 -124.168C260.69 -124.168 253.906 -118.656 246.697 -118.656C246.697 -118.656 232.705 -116.536 228.465 -103.816C228.465 -103.816 224.649 -77.952 232.281 -72.44C232.281 -72.44 236.945 -65.232 243.729 -71.592C250.514 -77.952 265.394 -107.13 263.274 -120.274z").setFill(f).setStroke(s);
+					f = "#999999";
+					g.createPath("M262.9 -119.916C262.9 -119.916 264.97 -128.288 260.394 -123.712C260.394 -123.712 253.738 -118.304 246.665 -118.304C246.665 -118.304 232.937 -116.224 228.777 -103.744C228.777 -103.744 225.033 -78.368 232.521 -72.96C232.521 -72.96 237.097 -65.888 243.753 -72.128C250.41 -78.368 264.98 -107.02 262.9 -119.916z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M262.526 -119.558C262.526 -119.558 264.586 -127.744 260.098 -123.256C260.098 -123.256 253.569 -117.952 246.633 -117.952C246.633 -117.952 233.169 -115.912 229.089 -103.672C229.089 -103.672 225.417 -78.784 232.761 -73.48C232.761 -73.48 237.249 -66.544 243.777 -72.664C250.305 -78.784 264.566 -106.91 262.526 -119.558z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M262.151 -119.2C262.151 -119.2 264.201 -127.2 259.801 -122.8C259.801 -122.8 253.401 -117.6 246.601 -117.6C246.601 -117.6 233.401 -115.6 229.401 -103.6C229.401 -103.6 225.801 -79.2 233.001 -74C233.001 -74 237.401 -67.2 243.801 -73.2C250.201 -79.2 264.151 -106.8 262.151 -119.2z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M50.6 84C50.6 84 30.2 64.8 22.2 64C22.2 64 -12.2 60 -27 78C-27 78 -9.4 57.6 18.2 63.2C18.2 63.2 -3.4 58.8 -15.8 62C-15.8 62 -32.6 62 -42.2 76L-45 80.8C-45 80.8 -41 66 -22.6 60C-22.6 60 0.2 55.2 11 60C11 60 -10.6 53.2 -20.6 55.2C-20.6 55.2 -51 52.8 -63.8 79.2C-63.8 79.2 -59.8 64.8 -45 57.6C-45 57.6 -31.4 48.8 -11 51.6C-11 51.6 3.4 54.8 8.6 57.2C13.8 59.6 12.6 56.8 4.2 52C4.2 52 -1.4 42 -15.4 42.4C-15.4 42.4 -58.2 46 -68.6 58C-68.6 58 -55 46.8 -44.6 44C-44.6 44 -22.2 36  [...]
+					f = "#cccccc";
+					g.createPath("M189 278C189 278 173.5 241.5 161 232C161 232 187 248 190.5 266C190.5 266 190.5 276 189 278z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M236 285.5C236 285.5 209.5 230.5 191 206.5C191 206.5 234.5 244 239.5 270.5L240 276L237 273.5C237 273.5 236.5 282.5 236 285.5z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M292.5 237C292.5 237 230 177.5 228.5 175C228.5 175 289 241 292 248.5C292 248.5 290 239.5 292.5 237z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M104 280.5C104 280.5 123.5 228.5 142.5 251C142.5 251 157.5 261 157 264C157 264 153 257.5 135 258C135 258 116 255 104 280.5z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M294.5 153C294.5 153 249.5 124.5 242 123C230.193 120.639 291.5 152 296.5 162.5C296.5 162.5 298.5 160 294.5 153z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M143.801 259.601C143.801 259.601 164.201 257.601 171.001 250.801L175.401 254.401L193.001 216.001L196.601 221.201C196.601 221.201 211.001 206.401 210.201 198.401C209.401 190.401 223.001 204.401 223.001 204.401C223.001 204.401 222.201 192.801 229.401 199.601C229.401 199.601 227.001 184.001 235.401 192.001C235.401 192.001 224.864 161.844 247.401 187.601C253.001 194.001 248.601 187.201 248.601 187.201C248.601 187.201 222.601 139.201 244.201 153.601C244.201 153.601 246.201  [...]
+					f = "#000000";
+					g.createPath("M109.401 -97.2C109.401 -97.2 97.801 -105.2 93.801 -104.8C89.801 -104.4 121.401 -113.6 162.601 -86C162.601 -86 167.401 -83.2 171.001 -83.6C171.001 -83.6 174.201 -81.2 171.401 -77.6C171.401 -77.6 162.601 -68 173.801 -56.8C173.801 -56.8 192.201 -50 186.601 -58.8C186.601 -58.8 197.401 -54.8 199.801 -50.8C202.201 -46.8 201.001 -50.8 201.001 -50.8C201.001 -50.8 194.601 -58 188.601 -63.2C188.601 -63.2 183.401 -65.2 180.601 -73.6C177.801 -82 175.401 -92 179.801 -95.2C179.801 - [...]
+					f = "#cc7226";
+					g.createPath("M180.801 -106.4C180.801 -106.4 170.601 -113.8 168.601 -113.8C166.601 -113.8 154.201 -124 150.001 -123.6C145.801 -123.2 133.601 -133.2 106.201 -125C106.201 -125 105.601 -127 109.201 -127.8C109.201 -127.8 115.601 -130 116.001 -130.6C116.001 -130.6 136.201 -134.8 143.401 -131.2C143.401 -131.2 152.601 -128.6 158.801 -122.4C158.801 -122.4 170.001 -119.2 173.201 -120.2C173.201 -120.2 182.001 -118 182.401 -116.2C182.401 -116.2 188.201 -113.2 186.401 -110.6C186.401 -110.6 186. [...]
+					f = "#cc7226";
+					g.createPath("M168.33 -108.509C169.137 -107.877 170.156 -107.779 170.761 -106.97C170.995 -106.656 170.706 -106.33 170.391 -106.233C169.348 -105.916 168.292 -106.486 167.15 -105.898C166.748 -105.691 166.106 -105.873 165.553 -106.022C163.921 -106.463 162.092 -106.488 160.401 -105.8C158.416 -106.929 156.056 -106.345 153.975 -107.346C153.917 -107.373 153.695 -107.027 153.621 -107.054C150.575 -108.199 146.832 -107.916 144.401 -110.2C141.973 -110.612 139.616 -111.074 137.188 -111.754C135. [...]
+					f = "#cc7226";
+					g.createPath("M91.696 -122.739C89.178 -124.464 86.81 -125.57 84.368 -127.356C84.187 -127.489 83.827 -127.319 83.625 -127.441C82.618 -128.05 81.73 -128.631 80.748 -129.327C80.209 -129.709 79.388 -129.698 78.88 -129.956C76.336 -131.248 73.707 -131.806 71.2 -133C71.882 -133.638 73.004 -133.394 73.6 -134.2C73.795 -133.92 74.033 -133.636 74.386 -133.827C76.064 -134.731 77.914 -134.884 79.59 -134.794C81.294 -134.702 83.014 -134.397 84.789 -134.125C85.096 -134.078 85.295 -133.555 85.618 -1 [...]
+					f = "#cc7226";
+					g.createPath("M59.198 -115.391C56.044 -116.185 52.994 -116.07 49.978 -117.346C49.911 -117.374 49.688 -117.027 49.624 -117.054C48.258 -117.648 47.34 -118.614 46.264 -119.66C45.351 -120.548 43.693 -120.161 42.419 -120.648C42.095 -120.772 41.892 -121.284 41.591 -121.323C40.372 -121.48 39.445 -122.429 38.4 -123C40.736 -123.795 43.147 -123.764 45.609 -124.148C45.722 -124.166 45.867 -123.845 46 -123.845C46.136 -123.845 46.266 -124.066 46.4 -124.2C46.595 -123.92 46.897 -123.594 47.154 -123 [...]
+					f = "#cc7226";
+					g.createPath("M45.338 -71.179C43.746 -72.398 43.162 -74.429 42.034 -76.221C41.82 -76.561 42.094 -76.875 42.411 -76.964C42.971 -77.123 43.514 -76.645 43.923 -76.443C45.668 -75.581 47.203 -74.339 49.2 -74.2C51.19 -71.966 55.45 -71.581 55.457 -68.2C55.458 -67.341 54.03 -68.259 53.6 -67.4C51.149 -68.403 48.76 -68.3 46.38 -69.767C45.763 -70.148 46.093 -70.601 45.338 -71.179z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M17.8 -123.756C17.935 -123.755 24.966 -123.522 24.949 -123.408C24.904 -123.099 17.174 -122.05 16.81 -122.22C16.646 -122.296 9.134 -119.866 9 -120C9.268 -120.135 17.534 -123.756 17.8 -123.756z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M33.2 -114C33.2 -114 18.4 -112.2 14 -111C9.6 -109.8 -9 -102.2 -12 -100.2C-12 -100.2 -25.4 -94.8 -42.4 -74.8C-42.4 -74.8 -34.8 -78.2 -32.6 -81C-32.6 -81 -19 -93.6 -19.2 -91C-19.2 -91 -7 -99.6 -7.6 -97.4C-7.6 -97.4 16.8 -108.6 14.8 -105.4C14.8 -105.4 36.4 -110 35.4 -108C35.4 -108 54.2 -103.6 51.4 -103.4C51.4 -103.4 45.6 -102.2 52 -98.6C52 -98.6 48.6 -94.2 43.2 -98.2C37.8 -102.2 40.8 -100 35.8 -99C35.8 -99 33.2 -98.2 28.6 -102.2C28.6 -102.2 23 -106.8 14.2 -103.2C14.2 -103 [...]
+					s = {color: "#4c0000", width: 2}; f = null;
+					g.createPath("M51.4 85C51.4 85 36.4 68.2 28 65.6C28 65.6 14.6 58.8 -10 66.6").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M24.8 64.2C24.8 64.2 -0.4 56.2 -15.8 60.4C-15.8 60.4 -34.2 62.4 -42.6 76.2").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M21.2 63C21.2 63 4.2 55.8 -10.6 53.6C-10.6 53.6 -27.2 51 -43.8 58.2C-43.8 58.2 -56 64.2 -61.4 74.4").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M22.2 63.4C22.2 63.4 6.8 52.4 5.8 51C5.8 51 -1.2 40 -14.2 39.6C-14.2 39.6 -35.6 40.4 -52.8 48.4").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M20.895 54.407C22.437 55.87 49.4 84.8 49.4 84.8C84.6 121.401 56.6 87.2 56.6 87.2C49 82.4 39.8 63.6 39.8 63.6C38.6 60.8 53.8 70.8 53.8 70.8C57.8 71.6 71.4 90.8 71.4 90.8C64.6 88.4 69.4 95.6 69.4 95.6C72.2 97.6 92.601 113.201 92.601 113.201C96.201 117.201 100.201 118.801 100.201 118.801C114.201 113.601 107.801 126.801 107.801 126.801C110.201 133.601 115.801 122.001 115.801 122.001C127.001 105.2 110.601 107.601 110.601 107.601C80.6 110.401 73.8 94.4 73.8 94.4C71.4 92 80.2 [...]
+					f = "#4c0000";
+					g.createPath("M-3 42.8C-3 42.8 8.6 48.4 11.2 51.2C13.8 54 27.8 65.4 27.8 65.4C27.8 65.4 22.4 63.4 19.8 61.6C17.2 59.8 6.4 51.6 6.4 51.6C6.4 51.6 2.6 45.6 -3 42.8z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M-61.009 11.603C-60.672 11.455 -61.196 8.743 -61.4 8.2C-62.422 5.474 -71.4 4 -71.4 4C-71.627 5.365 -71.682 6.961 -71.576 8.599C-71.576 8.599 -66.708 14.118 -61.009 11.603z").setFill(f).setStroke(s);
+					f = "#659900";
+					g.createPath("M-61.009 11.403C-61.458 11.561 -61.024 8.669 -61.2 8.2C-62.222 5.474 -71.4 3.9 -71.4 3.9C-71.627 5.265 -71.682 6.861 -71.576 8.499C-71.576 8.499 -67.308 13.618 -61.009 11.403z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-65.4 11.546C-66.025 11.546 -66.531 10.406 -66.531 9C-66.531 7.595 -66.025 6.455 -65.4 6.455C-64.775 6.455 -64.268 7.595 -64.268 9C-64.268 10.406 -64.775 11.546 -65.4 11.546z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-65.4 9z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-111 109.601C-111 109.601 -116.6 119.601 -91.8 113.601C-91.8 113.601 -77.8 112.401 -75.4 110.001C-74.2 110.801 -65.834 113.734 -63 114.401C-56.2 116.001 -47.8 106 -47.8 106C-47.8 106 -43.2 95.5 -40.4 95.5C-37.6 95.5 -40.8 97.1 -40.8 97.1C-40.8 97.1 -47.4 107.201 -47 108.801C-47 108.801 -52.2 128.801 -68.2 129.601C-68.2 129.601 -84.35 130.551 -83 136.401C-83 136.401 -74.2 134.001 -71.8 136.401C-71.8 136.401 -61 136.001 -69 142.401L-75.8 154.001C-75.8 154.001 -75.66 157 [...]
+					f = "#e59999";
+					g.createPath("M-112.2 113.601C-112.2 113.601 -114.2 123.201 -77.4 112.801C-77.4 112.801 -73 112.801 -70.6 113.601C-68.2 114.401 -56.2 117.201 -54.2 116.001C-54.2 116.001 -61.4 129.601 -73 128.001C-73 128.001 -86.2 129.601 -85.8 134.401C-85.8 134.401 -81.8 141.601 -77 144.001C-77 144.001 -74.2 146.401 -74.6 149.601C-75 152.801 -77.8 154.401 -79.8 155.201C-81.8 156.001 -85 152.801 -86.6 152.801C-88.2 152.801 -96.6 146.401 -101 141.601C-105.4 136.801 -113.8 124.801 -113.4 122.001C-113  [...]
+					f = "#b26565";
+					g.createPath("M-109 131.051C-106.4 135.001 -103.2 139.201 -101 141.601C-96.6 146.401 -88.2 152.801 -86.6 152.801C-85 152.801 -81.8 156.001 -79.8 155.201C-77.8 154.401 -75 152.801 -74.6 149.601C-74.2 146.401 -77 144.001 -77 144.001C-80.066 142.468 -82.806 138.976 -84.385 136.653C-84.385 136.653 -84.2 139.201 -89.4 138.401C-94.6 137.601 -99.8 134.801 -101.4 131.601C-103 128.401 -105.4 126.001 -103.8 129.601C-102.2 133.201 -99.8 136.801 -98.2 137.201C-96.6 137.601 -97 138.801 -99.4 138 [...]
+					f = "#992600";
+					g.createPath("M-111.6 110.001C-111.6 110.001 -109.8 96.4 -108.6 92.4C-108.6 92.4 -109.4 85.6 -107 81.4C-104.6 77.2 -102.6 71 -99.6 65.6C-96.6 60.2 -96.4 56.2 -92.4 54.6C-88.4 53 -82.4 44.4 -79.6 43.4C-76.8 42.4 -77 43.2 -77 43.2C-77 43.2 -70.2 28.4 -56.6 32.4C-56.6 32.4 -72.8 29.6 -57 20.2C-57 20.2 -61.8 21.3 -58.5 14.3C-56.299 9.632 -56.8 16.4 -67.8 28.2C-67.8 28.2 -72.8 36.8 -78 39.8C-83.2 42.8 -95.2 49.8 -96.4 53.6C-97.6 57.4 -100.8 63.2 -102.8 64.8C-104.8 66.4 -107.6 70.6 -108 7 [...]
+					f = "#ffffff";
+					g.createPath("M-120.2 114.601C-120.2 114.601 -122.2 113.201 -126.6 119.201C-126.6 119.201 -119.3 152.201 -119.3 153.601C-119.3 153.601 -118.2 151.501 -119.5 144.301C-120.8 137.101 -121.7 124.401 -121.7 124.401L-120.2 114.601z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-98.6 54C-98.6 54 -116.2 57.2 -115.8 86.4L-116.6 111.201C-116.6 111.201 -117.8 85.6 -119 84C-120.2 82.4 -116.2 71.2 -119.4 77.2C-119.4 77.2 -133.4 91.2 -125.4 112.401C-125.4 112.401 -123.9 115.701 -126.9 111.101C-126.9 111.101 -131.5 98.5 -130.4 92.1C-130.4 92.1 -130.2 89.9 -128.3 87.1C-128.3 87.1 -119.7 75.4 -117 73.1C-117 73.1 -115.2 58.7 -99.8 53.5C-99.8 53.5 -94.1 51.2 -98.6 54z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M40.8 -12.2C41.46 -12.554 41.451 -13.524 42.031 -13.697C43.18 -14.041 43.344 -15.108 43.862 -15.892C44.735 -17.211 44.928 -18.744 45.51 -20.235C45.782 -20.935 45.809 -21.89 45.496 -22.55C44.322 -25.031 43.62 -27.48 42.178 -29.906C41.91 -30.356 41.648 -31.15 41.447 -31.748C40.984 -33.132 39.727 -34.123 38.867 -35.443C38.579 -35.884 39.104 -36.809 38.388 -36.893C37.491 -36.998 36.042 -37.578 35.809 -36.552C35.221 -33.965 36.232 -31.442 37.2 -29C36.418 -28.308 36.752 -27. [...]
+					f = "#000000";
+					g.createPath("M31.959 -16.666C32.083 -16.743 31.928 -17.166 32.037 -17.382C32.199 -17.706 32.602 -17.894 32.764 -18.218C32.873 -18.434 32.71 -18.814 32.846 -18.956C35.179 -21.403 35.436 -24.427 34.4 -27.4C35.424 -28.02 35.485 -29.282 35.06 -30.129C34.207 -31.829 34.014 -33.755 33.039 -35.298C32.237 -36.567 30.659 -37.811 29.288 -36.508C28.867 -36.108 28.546 -35.321 28.824 -34.609C28.888 -34.446 29.173 -34.3 29.146 -34.218C29.039 -33.894 28.493 -33.67 28.487 -33.398C28.457 -31.902 27 [...]
+					f = "#000000";
+					g.createPath("M94.771 -26.977C96.16 -25.185 96.45 -22.39 94.401 -21C94.951 -17.691 98.302 -19.67 100.401 -20.2C100.292 -20.588 100.519 -20.932 100.802 -20.937C101.859 -20.952 102.539 -21.984 103.601 -21.8C104.035 -23.357 105.673 -24.059 106.317 -25.439C108.043 -29.134 107.452 -33.407 104.868 -36.653C104.666 -36.907 104.883 -37.424 104.759 -37.786C104.003 -39.997 101.935 -40.312 100.001 -41C98.824 -44.875 98.163 -48.906 96.401 -52.6C94.787 -52.85 94.089 -54.589 92.752 -55.309C91.419  [...]
+					f = "#000000";
+					g.createPath("M57.611 -8.591C56.124 -6.74 52.712 -4.171 55.629 -2.243C55.823 -2.114 56.193 -2.11 56.366 -2.244C58.387 -3.809 60.39 -4.712 62.826 -5.294C62.95 -5.323 63.224 -4.856 63.593 -5.017C65.206 -5.72 67.216 -5.662 68.4 -7C72.167 -6.776 75.732 -7.892 79.123 -9.2C80.284 -9.648 81.554 -10.207 82.755 -10.709C84.131 -11.285 85.335 -12.213 86.447 -13.354C86.58 -13.49 86.934 -13.4 87.201 -13.4C87.161 -14.263 88.123 -14.39 88.37 -15.012C88.462 -15.244 88.312 -15.64 88.445 -15.742C90.5 [...]
+					f = "#000000";
+					g.createPath("M2.2 -58C2.2 -58 -7.038 -60.872 -18.2 -35.2C-18.2 -35.2 -20.6 -30 -23 -28C-25.4 -26 -36.6 -22.4 -38.6 -18.4L-49 -2.4C-49 -2.4 -34.2 -18.4 -31 -20.8C-31 -20.8 -23 -29.2 -26.2 -22.4C-26.2 -22.4 -40.2 -11.6 -39 -2.4C-39 -2.4 -44.6 12 -45.4 14C-45.4 14 -29.4 -18 -27 -19.2C-24.6 -20.4 -23.4 -20.4 -24.6 -16.8C-25.8 -13.2 -26.2 3.2 -29 5.2C-29 5.2 -21 -15.2 -21.8 -18.4C-21.8 -18.4 -18.6 -22 -16.2 -16.8L-17.4 -0.8L-13 11.2C-13 11.2 -15.4 0 -13.8 -15.6C-13.8 -15.6 -15.8 -26 -11 [...]
+					f = "#000000";
+					g.createPath("M-17.8 -41.6C-17.8 -41.6 -30.6 -41.6 -33.8 -36.4L-41 -26.8C-41 -26.8 -23.8 -36.8 -19.8 -38C-15.8 -39.2 -17.8 -41.6 -17.8 -41.6z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-57.8 -35.2C-57.8 -35.2 -59.8 -34 -60.2 -31.2C-60.6 -28.4 -63 -28 -62.2 -25.2C-61.4 -22.4 -59.4 -20 -59.4 -24C-59.4 -28 -57.8 -30 -57 -31.2C-56.2 -32.4 -54.6 -36.8 -57.8 -35.2z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-66.6 26C-66.6 26 -75 22 -78.2 18.4C-81.4 14.8 -80.948 19.966 -85.8 19.6C-91.647 19.159 -90.6 3.2 -90.6 3.2L-94.6 10.8C-94.6 10.8 -95.8 25.2 -87.8 22.8C-83.893 21.628 -82.6 23.2 -84.2 24C-85.8 24.8 -78.6 25.2 -81.4 26.8C-84.2 28.4 -69.8 23.2 -72.2 33.6L-66.6 26z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-79.2 40.4C-79.2 40.4 -94.6 44.8 -98.2 35.2C-98.2 35.2 -103 37.6 -100.8 40.6C-98.6 43.6 -97.4 44 -97.4 44C-97.4 44 -92 45.2 -92.6 46C-93.2 46.8 -95.6 50.2 -95.6 50.2C-95.6 50.2 -85.4 44.2 -79.2 40.4z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M149.201 118.601C148.774 120.735 147.103 121.536 145.201 122.201C143.284 121.243 140.686 118.137 138.801 120.201C138.327 119.721 137.548 119.661 137.204 118.999C136.739 118.101 137.011 117.055 136.669 116.257C136.124 114.985 135.415 113.619 135.601 112.201C137.407 111.489 138.002 109.583 137.528 107.82C137.459 107.563 137.03 107.366 137.23 107.017C137.416 106.694 137.734 106.467 138.001 106.2C137.866 106.335 137.721 106.568 137.61 106.548C137 106.442 137.124 105.805 13 [...]
+					f = "#ffffff";
+					g.createPath("M139.6 138.201C139.593 136.463 137.992 134.707 139.201 133.001C139.336 133.135 139.467 133.356 139.601 133.356C139.736 133.356 139.867 133.135 140.001 133.001C141.496 135.217 145.148 136.145 145.006 138.991C144.984 139.438 143.897 140.356 144.801 141.001C142.988 142.349 142.933 144.719 142.001 146.601C140.763 146.315 139.551 145.952 138.401 145.401C138.753 143.915 138.636 142.231 139.456 140.911C139.89 140.213 139.603 139.134 139.6 138.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-26.6 129.201C-26.6 129.201 -43.458 139.337 -29.4 124.001C-20.6 114.401 -10.6 108.801 -10.6 108.801C-10.6 108.801 -0.2 104.4 3.4 103.2C7 102 22.2 96.8 25.4 96.4C28.6 96 38.2 92 45 96C51.8 100 59.8 104.4 59.8 104.4C59.8 104.4 43.4 96 39.8 98.4C36.2 100.8 29 100.4 23 103.6C23 103.6 8.2 108.001 5 110.001C1.8 112.001 -8.6 123.601 -10.2 122.801C-11.8 122.001 -9.8 121.601 -8.6 118.801C-7.4 116.001 -9.4 114.401 -17.4 120.801C-25.4 127.201 -26.6 129.201 -26.6 129.201z").setFi [...]
+					f = "#000000";
+					g.createPath("M-19.195 123.234C-19.195 123.234 -17.785 110.194 -9.307 111.859C-9.307 111.859 -1.081 107.689 1.641 105.721C1.641 105.721 9.78 104.019 11.09 103.402C29.569 94.702 44.288 99.221 44.835 98.101C45.381 96.982 65.006 104.099 68.615 108.185C69.006 108.628 58.384 102.588 48.686 100.697C40.413 99.083 18.811 100.944 7.905 106.48C4.932 107.989 -4.013 113.773 -6.544 113.662C-9.075 113.55 -19.195 123.234 -19.195 123.234z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-23 148.801C-23 148.801 -38.2 146.401 -21.4 144.801C-21.4 144.801 -3.4 142.801 0.6 137.601C0.6 137.601 14.2 128.401 17 128.001C19.8 127.601 49.8 120.401 50.2 118.001C50.6 115.601 56.2 115.601 57.8 116.401C59.4 117.201 58.6 118.401 55.8 119.201C53 120.001 21.8 136.401 15.4 137.601C9 138.801 -2.6 146.401 -7.4 147.601C-12.2 148.801 -23 148.801 -23 148.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-3.48 141.403C-3.48 141.403 -12.062 140.574 -3.461 139.755C-3.461 139.755 5.355 136.331 7.403 133.668C7.403 133.668 14.367 128.957 15.8 128.753C17.234 128.548 31.194 124.861 31.399 123.633C31.604 122.404 65.67 109.823 70.09 113.013C73.001 115.114 63.1 113.437 53.466 117.847C52.111 118.467 18.258 133.054 14.981 133.668C11.704 134.283 5.765 138.174 3.307 138.788C0.85 139.403 -3.48 141.403 -3.48 141.403z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-11.4 143.601C-11.4 143.601 -6.2 143.201 -7.4 144.801C-8.6 146.401 -11 145.601 -11 145.601L-11.4 143.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-18.6 145.201C-18.6 145.201 -13.4 144.801 -14.6 146.401C-15.8 148.001 -18.2 147.201 -18.2 147.201L-18.6 145.201z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-29 146.801C-29 146.801 -23.8 146.401 -25 148.001C-26.2 149.601 -28.6 148.801 -28.6 148.801L-29 146.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-36.6 147.601C-36.6 147.601 -31.4 147.201 -32.6 148.801C-33.8 150.401 -36.2 149.601 -36.2 149.601L-36.6 147.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M1.8 108.001C1.8 108.001 6.2 108.001 5 109.601C3.8 111.201 0.6 110.801 0.6 110.801L1.8 108.001z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-8.2 113.601C-8.2 113.601 -1.694 111.46 -4.2 114.801C-5.4 116.401 -7.8 115.601 -7.8 115.601L-8.2 113.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-19.4 118.401C-19.4 118.401 -14.2 118.001 -15.4 119.601C-16.6 121.201 -19 120.401 -19 120.401L-19.4 118.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-27 124.401C-27 124.401 -21.8 124.001 -23 125.601C-24.2 127.201 -26.6 126.401 -26.6 126.401L-27 124.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-33.8 129.201C-33.8 129.201 -28.6 128.801 -29.8 130.401C-31 132.001 -33.4 131.201 -33.4 131.201L-33.8 129.201z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M5.282 135.598C5.282 135.598 12.203 135.066 10.606 137.195C9.009 139.325 5.814 138.26 5.814 138.26L5.282 135.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M15.682 130.798C15.682 130.798 22.603 130.266 21.006 132.395C19.409 134.525 16.214 133.46 16.214 133.46L15.682 130.798z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M26.482 126.398C26.482 126.398 33.403 125.866 31.806 127.995C30.209 130.125 27.014 129.06 27.014 129.06L26.482 126.398z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M36.882 121.598C36.882 121.598 43.803 121.066 42.206 123.195C40.609 125.325 37.414 124.26 37.414 124.26L36.882 121.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M9.282 103.598C9.282 103.598 16.203 103.066 14.606 105.195C13.009 107.325 9.014 107.06 9.014 107.06L9.282 103.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M19.282 100.398C19.282 100.398 26.203 99.866 24.606 101.995C23.009 104.125 18.614 103.86 18.614 103.86L19.282 100.398z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-3.4 140.401C-3.4 140.401 1.8 140.001 0.6 141.601C-0.6 143.201 -3 142.401 -3 142.401L-3.4 140.401z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-76.6 41.2C-76.6 41.2 -81 50 -81.4 53.2C-81.4 53.2 -80.6 44.4 -79.4 42.4C-78.2 40.4 -76.6 41.2 -76.6 41.2z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-95 55.2C-95 55.2 -98.2 69.6 -97.8 72.4C-97.8 72.4 -99 60.8 -98.6 59.6C-98.2 58.4 -95 55.2 -95 55.2z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-74.2 -19.4L-74.4 -16.2L-76.6 -16C-76.6 -16 -62.4 -3.4 -61.8 4.2C-61.8 4.2 -61 -4 -74.2 -19.4z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-70.216 -18.135C-70.647 -18.551 -70.428 -19.296 -70.836 -19.556C-71.645 -20.072 -69.538 -20.129 -69.766 -20.845C-70.149 -22.051 -69.962 -22.072 -70.084 -23.348C-70.141 -23.946 -69.553 -25.486 -69.168 -25.926C-67.722 -27.578 -69.046 -30.51 -67.406 -32.061C-67.102 -32.35 -66.726 -32.902 -66.441 -33.32C-65.782 -34.283 -64.598 -34.771 -63.648 -35.599C-63.33 -35.875 -63.531 -36.702 -62.962 -36.61C-62.248 -36.495 -61.007 -36.625 -61.052 -35.784C-61.165 -33.664 -62.494 -31.9 [...]
+					f = "#000000";
+					g.createPath("M-73.8 -16.4C-73.8 -16.4 -73.4 -9.6 -71 -8C-68.6 -6.4 -69.8 -7.2 -73 -8.4C-76.2 -9.6 -75 -10.4 -75 -10.4C-75 -10.4 -77.8 -10 -75.4 -8C-73 -6 -69.4 -3.6 -71 -3.6C-72.6 -3.6 -80.2 -7.6 -80.2 -10.4C-80.2 -13.2 -81.2 -17.3 -81.2 -17.3C-81.2 -17.3 -80.1 -18.1 -75.3 -18C-75.3 -18 -73.9 -17.3 -73.8 -16.4z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-74.6 2.2C-74.6 2.2 -83.12 -0.591 -101.6 2.8C-101.6 2.8 -92.569 0.722 -73.8 3C-63.5 4.25 -74.6 2.2 -74.6 2.2z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-72.502 2.129C-72.502 2.129 -80.748 -1.389 -99.453 0.392C-99.453 0.392 -90.275 -0.897 -71.774 2.995C-61.62 5.131 -72.502 2.129 -72.502 2.129z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-70.714 2.222C-70.714 2.222 -78.676 -1.899 -97.461 -1.514C-97.461 -1.514 -88.213 -2.118 -70.052 3.14C-60.086 6.025 -70.714 2.222 -70.714 2.222z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-69.444 2.445C-69.444 2.445 -76.268 -1.862 -93.142 -2.96C-93.142 -2.96 -84.803 -2.79 -68.922 3.319C-60.206 6.672 -69.444 2.445 -69.444 2.445z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M45.84 12.961C45.84 12.961 44.91 13.605 45.124 12.424C45.339 11.243 73.547 -1.927 77.161 -1.677C77.161 -1.677 46.913 11.529 45.84 12.961z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M42.446 13.6C42.446 13.6 41.57 14.315 41.691 13.121C41.812 11.927 68.899 -3.418 72.521 -3.452C72.521 -3.452 43.404 12.089 42.446 13.6z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M39.16 14.975C39.16 14.975 38.332 15.747 38.374 14.547C38.416 13.348 58.233 -2.149 68.045 -4.023C68.045 -4.023 50.015 4.104 39.16 14.975z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M36.284 16.838C36.284 16.838 35.539 17.532 35.577 16.453C35.615 15.373 53.449 1.426 62.28 -0.26C62.28 -0.26 46.054 7.054 36.284 16.838z").setFill(f).setStroke(s);
+					f = "#cccccc"; s = null;
+					g.createPath("M4.6 164.801C4.6 164.801 -10.6 162.401 6.2 160.801C6.2 160.801 24.2 158.801 28.2 153.601C28.2 153.601 41.8 144.401 44.6 144.001C47.4 143.601 63.8 140.001 64.2 137.601C64.6 135.201 70.6 132.801 72.2 133.601C73.8 134.401 73.8 143.601 71 144.401C68.2 145.201 49.4 152.401 43 153.601C36.6 154.801 25 162.401 20.2 163.601C15.4 164.801 4.6 164.801 4.6 164.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M77.6 127.401C77.6 127.401 74.6 129.001 73.4 131.601C73.4 131.601 67 142.201 52.8 145.401C52.8 145.401 29.8 154.401 22 156.401C22 156.401 8.6 161.401 1.2 160.601C1.2 160.601 -5.8 160.801 0.4 162.401C0.4 162.401 20.6 160.401 24 158.601C24 158.601 39.6 153.401 42.6 150.801C45.6 148.201 63.8 143.201 66 141.201C68.2 139.201 78 130.801 77.6 127.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M18.882 158.911C18.882 158.911 24.111 158.685 22.958 160.234C21.805 161.784 19.357 160.91 19.357 160.91L18.882 158.911z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M11.68 160.263C11.68 160.263 16.908 160.037 15.756 161.586C14.603 163.136 12.155 162.263 12.155 162.263L11.68 160.263z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M1.251 161.511C1.251 161.511 6.48 161.284 5.327 162.834C4.174 164.383 1.726 163.51 1.726 163.51L1.251 161.511z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-6.383 162.055C-6.383 162.055 -1.154 161.829 -2.307 163.378C-3.46 164.928 -5.908 164.054 -5.908 164.054L-6.383 162.055z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M35.415 151.513C35.415 151.513 42.375 151.212 40.84 153.274C39.306 155.336 36.047 154.174 36.047 154.174L35.415 151.513z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M45.73 147.088C45.73 147.088 51.689 143.787 51.155 148.849C50.885 151.405 46.362 149.749 46.362 149.749L45.73 147.088z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M54.862 144.274C54.862 144.274 62.021 140.573 60.287 146.035C59.509 148.485 55.493 146.935 55.493 146.935L54.862 144.274z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M64.376 139.449C64.376 139.449 68.735 134.548 69.801 141.21C70.207 143.748 65.008 142.11 65.008 142.11L64.376 139.449z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M26.834 155.997C26.834 155.997 32.062 155.77 30.91 157.32C29.757 158.869 27.308 157.996 27.308 157.996L26.834 155.997z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M62.434 34.603C62.434 34.603 61.708 35.268 61.707 34.197C61.707 33.127 79.191 19.863 88.034 18.479C88.034 18.479 71.935 25.208 62.434 34.603z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M65.4 98.4C65.4 98.4 87.401 120.801 96.601 124.401C96.601 124.401 105.801 135.601 101.801 161.601C101.801 161.601 98.601 169.201 95.401 148.401C95.401 148.401 98.601 123.201 87.401 139.201C87.401 139.201 79 129.301 85.4 129.601C85.4 129.601 88.601 131.601 89.001 130.001C89.401 128.401 81.4 114.801 64.2 100.4C47 86 65.4 98.4 65.4 98.4z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M7 137.201C7 137.201 6.8 135.401 8.6 136.201C10.4 137.001 104.601 143.201 136.201 167.201C136.201 167.201 91.001 144.001 7 137.201z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M17.4 132.801C17.4 132.801 17.2 131.001 19 131.801C20.8 132.601 157.401 131.601 181.001 164.001C181.001 164.001 159.001 138.801 17.4 132.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M29 128.801C29 128.801 28.8 127.001 30.6 127.801C32.4 128.601 205.801 115.601 229.401 148.001C229.401 148.001 219.801 122.401 29 128.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M39 124.001C39 124.001 38.8 122.201 40.6 123.001C42.4 123.801 164.601 85.2 188.201 117.601C188.201 117.601 174.801 93 39 124.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-19 146.801C-19 146.801 -19.2 145.001 -17.4 145.801C-15.6 146.601 2.2 148.801 4.2 187.601C4.2 187.601 -3 145.601 -19 146.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-27.8 148.401C-27.8 148.401 -28 146.601 -26.2 147.401C-24.4 148.201 -10.2 143.601 -13 182.401C-13 182.401 -11.8 147.201 -27.8 148.401z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-35.8 148.801C-35.8 148.801 -36 147.001 -34.2 147.801C-32.4 148.601 -17 149.201 -29.4 171.601C-29.4 171.601 -19.8 147.601 -35.8 148.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M11.526 104.465C11.526 104.465 11.082 106.464 12.631 105.247C28.699 92.622 61.141 33.72 116.826 28.086C116.826 28.086 78.518 15.976 11.526 104.465z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M22.726 102.665C22.726 102.665 21.363 101.472 23.231 100.847C25.099 100.222 137.541 27.72 176.826 35.686C176.826 35.686 149.719 28.176 22.726 102.665z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M1.885 108.767C1.885 108.767 1.376 110.366 3.087 109.39C12.062 104.27 15.677 47.059 59.254 45.804C59.254 45.804 26.843 31.09 1.885 108.767z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-18.038 119.793C-18.038 119.793 -19.115 121.079 -17.162 120.825C-6.916 119.493 14.489 78.222 58.928 83.301C58.928 83.301 26.962 68.955 -18.038 119.793z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-6.8 113.667C-6.8 113.667 -7.611 115.136 -5.742 114.511C4.057 111.237 17.141 66.625 61.729 63.078C61.729 63.078 27.603 55.135 -6.8 113.667z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-25.078 124.912C-25.078 124.912 -25.951 125.954 -24.369 125.748C-16.07 124.669 1.268 91.24 37.264 95.354C37.264 95.354 11.371 83.734 -25.078 124.912z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-32.677 130.821C-32.677 130.821 -33.682 131.866 -32.091 131.748C-27.923 131.439 2.715 98.36 21.183 113.862C21.183 113.862 9.168 95.139 -32.677 130.821z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M36.855 98.898C36.855 98.898 35.654 97.543 37.586 97.158C39.518 96.774 160.221 39.061 198.184 51.927C198.184 51.927 172.243 41.053 36.855 98.898z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M3.4 163.201C3.4 163.201 3.2 161.401 5 162.201C6.8 163.001 22.2 163.601 9.8 186.001C9.8 186.001 19.4 162.001 3.4 163.201z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M13.8 161.601C13.8 161.601 13.6 159.801 15.4 160.601C17.2 161.401 35 163.601 37 202.401C37 202.401 29.8 160.401 13.8 161.601z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M20.6 160.001C20.6 160.001 20.4 158.201 22.2 159.001C24 159.801 48.6 163.201 72.2 195.601C72.2 195.601 36.6 158.801 20.6 160.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M28.225 157.972C28.225 157.972 27.788 156.214 29.678 156.768C31.568 157.322 52.002 155.423 90.099 189.599C90.099 189.599 43.924 154.656 28.225 157.972z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M38.625 153.572C38.625 153.572 38.188 151.814 40.078 152.368C41.968 152.922 76.802 157.423 128.499 192.399C128.499 192.399 54.324 150.256 38.625 153.572z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-1.8 142.001C-1.8 142.001 -2 140.201 -0.2 141.001C1.6 141.801 55 144.401 85.4 171.201C85.4 171.201 50.499 146.426 -1.8 142.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-11.8 146.001C-11.8 146.001 -12 144.201 -10.2 145.001C-8.4 145.801 16.2 149.201 39.8 181.601C39.8 181.601 4.2 144.801 -11.8 146.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M49.503 148.962C49.503 148.962 48.938 147.241 50.864 147.655C52.79 148.068 87.86 150.004 141.981 181.098C141.981 181.098 64.317 146.704 49.503 148.962z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M57.903 146.562C57.903 146.562 57.338 144.841 59.264 145.255C61.19 145.668 96.26 147.604 150.381 178.698C150.381 178.698 73.317 143.904 57.903 146.562z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M67.503 141.562C67.503 141.562 66.938 139.841 68.864 140.255C70.79 140.668 113.86 145.004 203.582 179.298C203.582 179.298 82.917 138.904 67.503 141.562z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M-43.8 148.401C-43.8 148.401 -38.6 148.001 -39.8 149.601C-41 151.201 -43.4 150.401 -43.4 150.401L-43.8 148.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-13 162.401C-13 162.401 -7.8 162.001 -9 163.601C-10.2 165.201 -12.6 164.401 -12.6 164.401L-13 162.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-21.8 162.001C-21.8 162.001 -16.6 161.601 -17.8 163.201C-19 164.801 -21.4 164.001 -21.4 164.001L-21.8 162.001z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-117.169 150.182C-117.169 150.182 -112.124 151.505 -113.782 152.624C-115.439 153.744 -117.446 152.202 -117.446 152.202L-117.169 150.182z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-115.169 140.582C-115.169 140.582 -110.124 141.905 -111.782 143.024C-113.439 144.144 -115.446 142.602 -115.446 142.602L-115.169 140.582z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-122.369 136.182C-122.369 136.182 -117.324 137.505 -118.982 138.624C-120.639 139.744 -122.646 138.202 -122.646 138.202L-122.369 136.182z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-42.6 211.201C-42.6 211.201 -44.2 211.201 -48.2 213.201C-50.2 213.201 -61.4 216.801 -67 226.801C-67 226.801 -54.6 217.201 -42.6 211.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M45.116 303.847C45.257 304.105 45.312 304.525 45.604 304.542C46.262 304.582 47.495 304.883 47.37 304.247C46.522 299.941 45.648 295.004 41.515 293.197C40.876 292.918 39.434 293.331 39.36 294.215C39.233 295.739 39.116 297.088 39.425 298.554C39.725 299.975 41.883 299.985 42.8 298.601C43.736 300.273 44.168 302.116 45.116 303.847z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M34.038 308.581C34.786 309.994 34.659 311.853 36.074 312.416C36.814 312.71 38.664 311.735 38.246 310.661C37.444 308.6 37.056 306.361 35.667 304.55C35.467 304.288 35.707 303.755 35.547 303.427C34.953 302.207 33.808 301.472 32.4 301.801C31.285 304.004 32.433 306.133 33.955 307.842C34.091 307.994 33.925 308.37 34.038 308.581z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-5.564 303.391C-5.672 303.014 -5.71 302.551 -5.545 302.23C-5.014 301.197 -4.221 300.075 -4.558 299.053C-4.906 297.997 -6.022 298.179 -6.672 298.748C-7.807 299.742 -7.856 301.568 -8.547 302.927C-8.743 303.313 -8.692 303.886 -9.133 304.277C-9.607 304.698 -10.047 306.222 -9.951 306.793C-9.898 307.106 -10.081 317.014 -9.859 316.751C-9.24 316.018 -6.19 306.284 -6.121 305.392C-6.064 304.661 -5.332 304.196 -5.564 303.391z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-31.202 296.599C-28.568 294.1 -25.778 291.139 -26.22 287.427C-26.336 286.451 -28.111 286.978 -28.298 287.824C-29.1 291.449 -31.139 294.11 -33.707 296.502C-35.903 298.549 -37.765 304.893 -38 305.401C-34.303 300.145 -32.046 297.399 -31.202 296.599z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-44.776 290.635C-44.253 290.265 -44.555 289.774 -44.338 289.442C-43.385 287.984 -42.084 286.738 -42.066 285C-42.063 284.723 -42.441 284.414 -42.776 284.638C-43.053 284.822 -43.395 284.952 -43.503 285.082C-45.533 287.531 -46.933 290.202 -48.376 293.014C-48.559 293.371 -49.703 297.862 -49.39 297.973C-49.151 298.058 -47.431 293.877 -47.221 293.763C-45.958 293.077 -45.946 291.462 -44.776 290.635z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-28.043 310.179C-27.599 309.31 -26.023 308.108 -26.136 307.219C-26.254 306.291 -25.786 304.848 -26.698 305.536C-27.955 306.484 -31.404 307.833 -31.674 313.641C-31.7 314.212 -28.726 311.519 -28.043 310.179z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-13.6 293.001C-13.2 292.333 -12.492 292.806 -12.033 292.543C-11.385 292.171 -10.774 291.613 -10.482 290.964C-9.512 288.815 -7.743 286.995 -7.6 284.601C-9.091 283.196 -9.77 285.236 -10.4 286.201C-11.723 284.554 -12.722 286.428 -14.022 286.947C-14.092 286.975 -14.305 286.628 -14.38 286.655C-15.557 287.095 -16.237 288.176 -17.235 288.957C-17.406 289.091 -17.811 288.911 -17.958 289.047C-18.61 289.65 -19.583 289.975 -19.863 290.657C-20.973 293.364 -24.113 295.459 -26 303.0 [...]
+					f = "#cccccc";
+					g.createPath("M46.2 347.401C46.2 347.401 53.6 327.001 49.2 315.801C49.2 315.801 60.6 337.401 56 348.601C56 348.601 55.6 338.201 51.6 333.201C51.6 333.201 47.6 346.001 46.2 347.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M31.4 344.801C31.4 344.801 36.8 336.001 28.8 317.601C28.8 317.601 28 338.001 21.2 349.001C21.2 349.001 35.4 328.801 31.4 344.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M21.4 342.801C21.4 342.801 21.2 322.801 21.6 319.801C21.6 319.801 17.8 336.401 7.6 346.001C7.6 346.001 22 334.001 21.4 342.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M11.8 310.801C11.8 310.801 17.8 324.401 7.8 342.801C7.8 342.801 14.2 330.601 9.4 323.601C9.4 323.601 12 320.201 11.8 310.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-7.4 342.401C-7.4 342.401 -8.4 326.801 -6.6 324.601C-6.6 324.601 -6.4 318.201 -6.8 317.201C-6.8 317.201 -2.8 311.001 -2.6 318.401C-2.6 318.401 -1.2 326.201 1.6 330.801C1.6 330.801 5.2 336.201 5 342.601C5 342.601 -5 312.401 -7.4 342.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-11 314.801C-11 314.801 -17.6 325.601 -19.4 344.601C-19.4 344.601 -20.8 338.401 -17 324.001C-17 324.001 -12.8 308.601 -11 314.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-32.8 334.601C-32.8 334.601 -27.8 329.201 -26.4 324.201C-26.4 324.201 -22.8 308.401 -29.2 317.001C-29.2 317.001 -29 325.001 -37.2 332.401C-37.2 332.401 -32.4 330.001 -32.8 334.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-38.6 329.601C-38.6 329.601 -35.2 312.201 -34.4 311.401C-34.4 311.401 -32.6 308.001 -35.4 311.201C-35.4 311.201 -44.2 330.401 -48.2 337.001C-48.2 337.001 -40.2 327.801 -38.6 329.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-44.4 313.001C-44.4 313.001 -32.8 290.601 -54.6 316.401C-54.6 316.401 -43.6 306.601 -44.4 313.001z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-59.8 298.401C-59.8 298.401 -55 279.601 -52.4 279.801C-52.4 279.801 -44.2 270.801 -50.8 281.401C-50.8 281.401 -56.8 291.001 -56.2 300.801C-56.2 300.801 -56.8 291.201 -59.8 298.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M270.5 287C270.5 287 258.5 277 256 273.5C256 273.5 269.5 292 269.5 299C269.5 299 272 291.5 270.5 287z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M276 265C276 265 255 250 251.5 242.5C251.5 242.5 278 272 278 276.5C278 276.5 278.5 267.5 276 265z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M293 111C293 111 281 103 279.5 105C279.5 105 290 111.5 292.5 120C292.5 120 291 111 293 111z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M301.5 191.5L284 179.5C284 179.5 303 196.5 303.5 200.5L301.5 191.5z").setFill(f).setStroke(s);
+					s = "#000000"; f = null;
+					g.createPath("M-89.25 169L-67.25 173.75").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M-39 331C-39 331 -39.5 327.5 -48.5 338").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M-33.5 336C-33.5 336 -31.5 329.5 -38 334").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M20.5 344.5C20.5 344.5 22 333.5 10.5 346.5").setFill(f).setStroke(s);
+                }
+            },
+			{
+				name: "Draw Lion",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 20,
+                setUp: function() {
+                    createSurface();
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+					var f, g;
+                    surface.clear();
+					var m = dojox.gfx.matrix;
+					var initial_matrix = m.normalize([m.rotateg(10), m.translate(300, 100)]);
+					surface.createRect({x: 0, y: 0, width: 700, height: 700}).setFill("#eee");
+					g = surface.createGroup().setTransform(initial_matrix);
+					g.createPolyline([69,18,82,8,99,3,118,5,135,12,149,21,156,13,165,9,177,13,183,28,180,50,164,91,155,107,154,114,151,121,141,127,139,136,155,206,157,251,126,342,133,357,128,376,83,376,75,368,67,350,61,350,53,369,4,369,2,361,5,354,12,342,16,321,4,257,4,244,7,218,9,179,26,127,43,93,32,77,30,70,24,67,16,49,17,35,18,23,30,12,40,7,53,7,62,12]).setFill("#f2cc99");
+					g.createPolyline([142,79,136,74,138,82,133,78,133,84,127,78,128,85,124,80,125,87,119,82,119,90,125,99,125,96,128,100,128,94,131,98,132,93,135,97,136,93,138,97,139,94,141,98,143,94,144,85]).setFill("#e5b27f");
+					g.createPolyline([127,101,132,100,137,99,144,101,143,105,135,110]).setFill("#eb8080");
+					g.createPolyline([178,229,157,248,139,296,126,349,137,356,158,357,183,342,212,332,235,288,235,261,228,252,212,250,188,251]).setFill("#f2cc99");
+					var c = new dojo.Color("#9c826b");
+					g.createPolyline([56,229,48,241,48,250,57,281,63,325,71,338,81,315,76,321,79,311,83,301,75,308,80,298,73,303,76,296,71,298,74,292,69,293,74,284,78,278,71,278,74,274,68,273,70,268,66,267,68,261,60,266,62,259,65,253,57,258,59,251,55,254,55,248,60,237,54,240,58,234,54,236]).setFill(c);
+					g.createPolyline([74,363,79,368,81,368,85,362,89,363,92,370,96,373,101,372,108,361,110,371,113,373,116,371,120,358,122,363,123,371,126,371,129,367,132,357,135,361,130,376,127,377,94,378,84,376,76,371]).setFill(c);
+					g.createPolyline([212,250,219,251,228,258,236,270,235,287,225,304,205,332,177,343,171,352,158,357,166,352,168,346,168,339,165,333,155,327,155,323,161,320,165,316,169,316,167,312,171,313,168,308,173,309,170,306,177,306,175,308,177,311,174,311,176,316,171,315,174,319,168,320,168,323,175,327,179,332,183,326,184,332,189,323,190,328,194,320,194,325,199,316,201,320,204,313,206,316,208,310,211,305,219,298,226,288,229,279,228,266,224,259,217,253]).setFill(c);
+					g.createPolyline([151,205,151,238,149,252,141,268,128,282,121,301,130,300,126,313,118,324,116,337,120,346,133,352,133,340,137,333,145,329,156,327,153,319,153,291,157,271,170,259,178,277,193,250,174,216]).setFill(c);
+					g.createPolyline([78,127,90,142,95,155,108,164,125,167,139,175,150,206,152,191,141,140,121,148,100,136]).setFill(c);
+					g.createPolyline([21,58,35,63,38,68,32,69,42,74,40,79,47,80,54,83,45,94,34,81,32,73,24,66]).setFill(c);
+					g.createPolyline([71,34,67,34,66,27,59,24,54,17,48,17,39,22,30,26,28,31,31,39,38,46,29,45,36,54,41,61,41,70,50,69,54,71,55,58,67,52,76,43,76,39,68,44]).setFill(c);
+					g.createPolyline([139,74,141,83,143,89,144,104,148,104,155,106,154,86,157,77,155,72,150,77,144,77]).setFill(c);
+					g.createPolyline([105,44,102,53,108,58,111,62,112,55]).setFill(c);
+					g.createPolyline([141,48,141,54,144,58,139,62,137,66,136,59,137,52]).setFill(c);
+					g.createPolyline([98,135,104,130,105,134,108,132,108,135,112,134,113,137,116,136,116,139,119,139,124,141,128,140,133,138,140,133,139,140,126,146,104,144]).setFill(c);
+					g.createPolyline([97,116,103,119,103,116,111,118,116,117,122,114,127,107,135,111,142,107,141,114,145,118,149,121,145,125,140,124,127,121,113,125,100,124]).setFill(c);
+					g.createPolyline([147,33,152,35,157,34,153,31,160,31,156,28,161,28,159,24,163,25,163,21,165,22,170,23,167,17,172,21,174,18,175,23,176,22,177,28,177,33,174,37,176,39,174,44,171,49,168,53,164,57,159,68,156,70,154,60,150,51,146,43,144,35]).setFill(c);
+					g.createPolyline([85,72,89,74,93,75,100,76,105,75,102,79,94,79,88,76]).setFill(c);
+					g.createPolyline([86,214,79,221,76,232,82,225,78,239,82,234,78,245,81,243,79,255,84,250,84,267,87,254,90,271,90,257,95,271,93,256,95,249,92,252,93,243,89,253,89,241,86,250,87,236,83,245,87,231,82,231,90,219,84,221]).setFill(c);
+					c = new dojo.Color("#ffcc7f");
+					g.createPolyline([93,68,96,72,100,73,106,72,108,66,105,63,100,62]).setFill(c);
+					g.createPolyline([144,64,142,68,142,73,146,74,150,73,154,64,149,62]).setFill(c);
+					c = new dojo.Color("#9c826b");
+					g.createPolyline([57,91,42,111,52,105,41,117,53,112,46,120,53,116,50,124,57,119,55,127,61,122,60,130,67,126,66,134,71,129,72,136,77,130,76,137,80,133,82,138,86,135,96,135,94,129,86,124,83,117,77,123,79,117,73,120,75,112,68,116,71,111,65,114,69,107,63,110,68,102,61,107,66,98,61,103,63,97,57,99]).setFill(c);
+					g.createPolyline([83,79,76,79,67,82,75,83,65,88,76,87,65,92,76,91,68,96,77,95,70,99,80,98,72,104,80,102,76,108,85,103,92,101,87,98,93,96,86,94,91,93,85,91,93,89,99,89,105,93,107,85,102,82,92,80]).setFill(c);
+					g.createPolyline([109,77,111,83,109,89,113,94,117,90,117,81,114,78]).setFill(c);
+					g.createPolyline([122,128,127,126,134,127,136,129,134,130,130,128,124,129]).setFill(c);
+					g.createPolyline([78,27,82,32,80,33,82,36,78,37,82,40,78,42,81,46,76,47,78,49,74,50,82,52,87,50,83,48,91,46,86,45,91,42,88,40,92,37,86,34,90,31,86,29,89,26]).setFill(c);
+					g.createPolyline([82,17,92,20,79,21,90,25,81,25,94,28,93,26,101,30,101,26,107,33,108,28,111,40,113,34,115,45,117,39,119,54,121,46,124,58,126,47,129,59,130,49,134,58,133,44,137,48,133,37,137,40,133,32,126,20,135,26,132,19,138,23,135,17,142,18,132,11,116,6,94,6,78,11,92,12,80,14,90,16]).setFill(c);
+					g.createPolyline([142,234,132,227,124,223,115,220,110,225,118,224,127,229,135,236,122,234,115,237,113,242,121,238,139,243,121,245,111,254,95,254,102,244,104,235,110,229,100,231,104,224,113,216,122,215,132,217,141,224,145,230,149,240]).setFill(c);
+					g.createPolyline([115,252,125,248,137,249,143,258,134,255,125,254]).setFill(c);
+					g.createPolyline([114,212,130,213,140,219,147,225,144,214,137,209,128,207]).setFill(c);
+					g.createPolyline([102,263,108,258,117,257,131,258,116,260,109,265]).setFill(c);
+					g.createPolyline([51,241,35,224,40,238,23,224,31,242,19,239,28,247,17,246,25,250,37,254,39,263,44,271,47,294,48,317,51,328,60,351,60,323,53,262,47,246]).setFill(c);
+					g.createPolyline([2,364,9,367,14,366,18,355,20,364,26,366,31,357,35,364,39,364,42,357,47,363,53,360,59,357,54,369,7,373]).setFill(c);
+					g.createPolyline([7,349,19,345,25,339,18,341,23,333,28,326,23,326,27,320,23,316,25,311,20,298,15,277,12,264,9,249,10,223,3,248,5,261,15,307,17,326,11,343]).setFill(c);
+					g.createPolyline([11,226,15,231,25,236,18,227]).setFill(c);
+					g.createPolyline([13,214,19,217,32,227,23,214,16,208,15,190,24,148,31,121,24,137,14,170,8,189]).setFill(c);
+					g.createPolyline([202,254,195,258,199,260,193,263,197,263,190,268,196,268,191,273,188,282,200,272,194,272,201,266,197,265,204,262,200,258,204,256]).setFill(c);
+					c = new dojo.Color("#845433");
+					g.createPolyline([151,213,165,212,179,225,189,246,187,262,179,275,176,263,177,247,171,233,163,230,165,251,157,264,146,298,145,321,133,326,143,285,154,260,153,240]).setFill(c);
+					g.createPolyline([91,132,95,145,97,154,104,148,107,155,109,150,111,158,115,152,118,159,120,153,125,161,126,155,133,164,132,154,137,163,137,152,142,163,147,186,152,192,148,167,141,143,124,145,105,143]).setFill(c);
+					c = new dojo.Color("#9c826b");
+					g.createPolyline([31,57,23,52,26,51,20,44,23,42,21,36,22,29,25,23,24,32,30,43,26,41,30,50,26,48]).setFill(c);
+					g.createPolyline([147,21,149,28,155,21,161,16,167,14,175,15,173,11,161,9]).setFill(c);
+					g.createPolyline([181,39,175,51,169,57,171,65,165,68,165,75,160,76,162,91,171,71,180,51]).setFill(c);
+					g.createPolyline([132,346,139,348,141,346,142,341,147,342,143,355,133,350]).setFill(c);
+					g.createPolyline([146,355,151,352,155,348,157,343,160,349,151,356,147,357]).setFill(c);
+					g.createPolyline([99,266,100,281,94,305,86,322,78,332,72,346,73,331,91,291]).setFill(c);
+					g.createPolyline([20,347,32,342,45,340,54,345,45,350,42,353,38,350,31,353,29,356,23,350,19,353,15,349]).setFill(c);
+					g.createPolyline([78,344,86,344,92,349,88,358,84,352]).setFill(c);
+					g.createPolyline([93,347,104,344,117,345,124,354,121,357,116,351,112,351,108,355,102,351]).setFill(c);
+					c = new dojo.Color("black");
+					g.createPolyline([105,12,111,18,113,24,113,29,119,34,116,23,112,16]).setFill(c);
+					g.createPolyline([122,27,125,34,127,43,128,34,125,29]).setFill(c);
+					g.createPolyline([115,13,122,19,122,15,113,10]).setFill(c);
+					c = new dojo.Color("#ffe5b2");
+					g.createPolyline([116,172,107,182,98,193,98,183,90,199,89,189,84,207,88,206,87,215,95,206,93,219,91,230,98,216,97,226,104,214,112,209,104,208,113,202,126,200,139,207,132,198,142,203,134,192,142,195,134,187,140,185,130,181,136,177,126,177,125,171,116,180]).setFill(c);
+					g.createPolyline([74,220,67,230,67,221,59,235,63,233,60,248,70,232,65,249,71,243,67,256,73,250,69,262,73,259,71,267,76,262,72,271,78,270,76,275,82,274,78,290,86,279,86,289,92,274,88,275,87,264,82,270,82,258,77,257,78,247,73,246,77,233,72,236]).setFill(c);
+					g.createPolyline([133,230,147,242,148,250,145,254,138,247,129,246,142,245,138,241,128,237,137,238]).setFill(c);
+					g.createPolyline([133,261,125,261,116,263,111,267,125,265]).setFill(c);
+					g.createPolyline([121,271,109,273,103,279,99,305,92,316,85,327,83,335,89,340,97,341,94,336,101,336,96,331,103,330,97,327,108,325,99,322,109,321,100,318,110,317,105,314,110,312,107,310,113,308,105,306,114,303,105,301,115,298,107,295,115,294,108,293,117,291,109,289,117,286,109,286,118,283,112,281,118,279,114,278,119,276,115,274]).setFill(c);
+					g.createPolyline([79,364,74,359,74,353,76,347,80,351,83,356,82,360]).setFill(c);
+					g.createPolyline([91,363,93,356,97,353,103,355,105,360,103,366,99,371,94,368]).setFill(c);
+					g.createPolyline([110,355,114,353,118,357,117,363,113,369,111,362]).setFill(c);
+					g.createPolyline([126,354,123,358,124,367,126,369,129,361,129,357]).setFill(c);
+					g.createPolyline([30,154,24,166,20,182,23,194,29,208,37,218,41,210,41,223,46,214,46,227,52,216,52,227,61,216,59,225,68,213,73,219,70,207,77,212,69,200,77,202,70,194,78,197,68,187,76,182,64,182,58,175,58,185,53,177,50,186,46,171,44,182,39,167,36,172,36,162,30,166]).setFill(c);
+					g.createPolyline([44,130,41,137,45,136,43,150,48,142,48,157,53,150,52,164,60,156,61,169,64,165,66,175,70,167,74,176,77,168,80,183,85,172,90,182,93,174,98,181,99,173,104,175,105,169,114,168,102,163,95,157,94,166,90,154,87,162,82,149,75,159,72,148,68,155,67,143,62,148,62,138,58,145,56,133,52,142,52,128,49,134,47,125]).setFill(c);
+					g.createPolyline([13,216,19,219,36,231,22,223,16,222,22,227,12,224,13,220,16,220]).setFill(c);
+					g.createPolyline([10,231,14,236,25,239,27,237,19,234]).setFill(c);
+					g.createPolyline([9,245,14,242,25,245,13,245]).setFill(c);
+					g.createPolyline([33,255,26,253,18,254,25,256,18,258,27,260,18,263,27,265,19,267,29,270,21,272,29,276,21,278,30,281,22,283,31,287,24,288,32,292,23,293,34,298,26,299,37,303,32,305,39,309,33,309,39,314,34,314,40,318,34,317,40,321,34,321,41,326,33,326,40,330,33,332,39,333,33,337,42,337,54,341,49,337,52,335,47,330,50,330,45,325,49,325,45,321,48,321,45,316,46,306,45,286,43,274,36,261]).setFill(c);
+					g.createPolyline([7,358,9,351,14,351,17,359,11,364]).setFill(c);
+					g.createPolyline([44,354,49,351,52,355,49,361]).setFill(c);
+					g.createPolyline([32,357,37,353,40,358,36,361]).setFill(c);
+					g.createPolyline([139,334,145,330,154,330,158,334,154,341,152,348,145,350,149,340,147,336,141,339,139,345,136,342,136,339]).setFill(c);
+					g.createPolyline([208,259,215,259,212,255,220,259,224,263,225,274,224,283,220,292,208,300,206,308,203,304,199,315,197,309,195,318,193,313,190,322,190,316,185,325,182,318,180,325,172,321,178,320,176,313,186,312,180,307,188,307,184,303,191,302,186,299,195,294,187,290,197,288,192,286,201,283,194,280,203,277,198,275,207,271,200,269,209,265,204,265,212,262]).setFill(c);
+					g.createPolyline([106,126,106,131,109,132,111,134,115,132,115,135,119,133,118,137,123,137,128,137,133,134,136,130,136,127,132,124,118,128,112,128,106,126,106,126,106,126]).setFill(c);
+					g.createPolyline([107,114,101,110,98,102,105,97,111,98,119,102,121,108,118,112,113,115]).setFill(c);
+					g.createPolyline([148,106,145,110,146,116,150,118,152,111,151,107]).setFill(c);
+					g.createPolyline([80,55,70,52,75,58,63,57,72,61,57,61,67,66,57,67,62,69,54,71,61,73,54,77,63,78,53,85,60,84,56,90,69,84,63,82,75,76,70,75,77,72,72,71,78,69,72,66,81,67,78,64,82,63,80,60,86,62]).setFill(c);
+					g.createPolyline([87,56,91,52,96,50,102,56,98,56,92,60]).setFill(c);
+					g.createPolyline([85,68,89,73,98,76,106,74,96,73,91,70]).setFill(c);
+					g.createPolyline([115,57,114,64,111,64,115,75,122,81,122,74,126,79,126,74,131,78,130,72,133,77,131,68,126,61,119,57]).setFill(c);
+					g.createPolyline([145,48,143,53,147,59,151,59,150,55]).setFill(c);
+					g.createPolyline([26,22,34,15,43,10,52,10,59,16,47,15,32,22]).setFill(c);
+					g.createPolyline([160,19,152,26,149,34,154,33,152,30,157,30,155,26,158,27,157,23,161,23]).setFill(c);
+					c = new dojo.Color("black");
+					g.createPolyline([98,117,105,122,109,122,105,117,113,120,121,120,130,112,128,108,123,103,123,99,128,101,132,106,135,109,142,105,142,101,145,101,145,91,148,101,145,105,136,112,135,116,143,124,148,120,150,122,142,128,133,122,121,125,112,126,103,125,100,129,96,124]).setFill(c);
+					g.createPolyline([146,118,152,118,152,115,149,115]).setFill(c);
+					g.createPolyline([148,112,154,111,154,109,149,109]).setFill(c);
+					g.createPolyline([106,112,108,115,114,116,118,114]).setFill(c);
+					g.createPolyline([108,108,111,110,116,110,119,108]).setFill(c);
+					g.createPolyline([106,104,109,105,117,106,115,104]).setFill(c);
+					g.createPolyline([50,25,41,26,34,33,39,43,49,58,36,51,47,68,55,69,54,59,61,57,74,46,60,52,67,42,57,48,61,40,54,45,60,36,59,29,48,38,52,30,47,32]).setFill(c);
+					g.createPolyline([147,34,152,41,155,49,161,53,157,47,164,47,158,43,168,44,159,40,164,37,169,37,164,33,169,34,165,28,170,30,170,25,173,29,175,27,176,32,173,36,175,39,172,42,172,46,168,49,170,55,162,57,158,63,155,58,153,50,149,46]).setFill(c);
+					g.createPolyline([155,71,159,80,157,93,157,102,155,108,150,101,149,93,154,101,152,91,151,83,155,79]).setFill(c);
+					g.createPolyline([112,78,115,81,114,91,112,87,113,82]).setFill(c);
+					g.createPolyline([78,28,64,17,58,11,47,9,36,10,28,16,21,26,18,41,20,51,23,61,33,65,28,68,37,74,36,81,43,87,48,90,43,100,40,98,39,90,31,80,30,72,22,71,17,61,14,46,16,28,23,17,33,9,45,6,54,6,65,12]).setFill(c);
+					g.createPolyline([67,18,76,9,87,5,101,2,118,3,135,8,149,20,149,26,144,19,132,12,121,9,105,7,89,8,76,14,70,20]).setFill(c);
+					g.createPolyline([56,98,48,106,56,103,47,112,56,110,52,115,57,113,52,121,62,115,58,123,65,119,63,125,69,121,68,127,74,125,74,129,79,128,83,132,94,135,93,129,85,127,81,122,76,126,75,121,71,124,71,117,66,121,66,117,62,117,64,112,60,113,60,110,57,111,61,105,57,107,60,101,55,102]).setFill(c);
+					g.createPolyline([101,132,103,138,106,134,106,139,112,136,111,142,115,139,114,143,119,142,125,145,131,142,135,138,140,134,140,129,143,135,145,149,150,171,149,184,145,165,141,150,136,147,132,151,131,149,126,152,125,150,121,152,117,148,111,152,110,148,105,149,104,145,98,150,96,138,94,132,94,130,98,132]).setFill(c);
+					g.createPolyline([41,94,32,110,23,132,12,163,6,190,7,217,5,236,3,247,9,230,12,211,12,185,18,160,26,134,35,110,43,99]).setFill(c);
+					g.createPolyline([32,246,41,250,50,257,52,267,53,295,53,323,59,350,54,363,51,365,44,366,42,360,40,372,54,372,59,366,62,353,71,352,75,335,73,330,66,318,68,302,64,294,67,288,63,286,63,279,59,275,58,267,56,262,50,247,42,235,44,246,32,236,35,244]).setFill(c);
+					g.createPolyline([134,324,146,320,159,322,173,327,179,337,179,349,172,355,158,357,170,350,174,343,170,333,163,328,152,326,134,329]).setFill(c);
+					g.createPolyline([173,339,183,334,184,338,191,329,194,332,199,323,202,325,206,318,209,320,213,309,221,303,228,296,232,289,234,279,233,269,230,262,225,256,219,253,208,252,198,252,210,249,223,250,232,257,237,265,238,277,238,291,232,305,221,323,218,335,212,342,200,349,178,348]).setFill(c);
+					g.createPolyline([165,296,158,301,156,310,156,323,162,324,159,318,162,308,162,304]).setFill(c);
+					g.createPolyline([99,252,105,244,107,234,115,228,121,228,131,235,122,233,113,235,109,246,121,239,133,243,121,243,110,251]).setFill(c);
+					g.createPolyline([117,252,124,247,134,249,136,253,126,252]).setFill(c);
+					g.createPolyline([117,218,132,224,144,233,140,225,132,219,117,218,117,218,117,218]).setFill(c);
+					g.createPolyline([122,212,134,214,143,221,141,213,132,210]).setFill(c);
+					g.createPolyline([69,352,70,363,76,373,86,378,97,379,108,379,120,377,128,378,132,373,135,361,133,358,132,366,127,375,121,374,121,362,119,367,117,374,110,376,110,362,107,357,106,371,104,375,97,376,90,375,90,368,86,362,83,364,86,369,85,373,78,370,73,362,71,351]).setFill(c);
+					g.createPolyline([100,360,96,363,99,369,102,364]).setFill(c);
+					g.createPolyline([115,360,112,363,114,369,117,364]).setFill(c);
+					g.createPolyline([127,362,125,364,126,369,128,365]).setFill(c);
+					g.createPolyline([5,255,7,276,11,304,15,320,13,334,6,348,2,353,0,363,5,372,12,374,25,372,38,372,44,369,42,367,36,368,31,369,30,360,27,368,20,370,16,361,15,368,10,369,3,366,3,359,6,352,11,348,17,331,19,316,12,291,9,274]).setFill(c);
+					g.createPolyline([10,358,7,362,10,366,11,362]).setFill(c);
+					g.createPolyline([25,357,22,360,24,366,27,360]).setFill(c);
+					g.createPolyline([37,357,34,361,36,365,38,361]).setFill(c);
+					g.createPolyline([49,356,46,359,47,364,50,360]).setFill(c);
+					g.createPolyline([130,101,132,102,135,101,139,102,143,103,142,101,137,100,133,100]).setFill(c);
+					g.createPolyline([106,48,105,52,108,56,109,52]).setFill(c);
+					g.createPolyline([139,52,139,56,140,60,142,58,141,56]).setFill(c);
+					g.createPolyline([25,349,29,351,30,355,33,350,37,348,42,351,45,347,49,345,44,343,36,345]).setFill(c);
+					g.createPolyline([98,347,105,351,107,354,109,349,115,349,120,353,118,349,113,346,104,346]).setFill(c);
+					g.createPolyline([83,348,87,352,87,357,89,351,87,348]).setFill(c);
+					g.createPolyline([155,107,163,107,170,107,186,108,175,109,155,109]).setFill(c);
+					g.createPolyline([153,114,162,113,175,112,192,114,173,114,154,115]).setFill(c);
+					g.createPolyline([152,118,164,120,180,123,197,129,169,123,151,120]).setFill(c);
+					g.createPolyline([68,109,87,106,107,106,106,108,88,108]).setFill(c);
+					g.createPolyline([105,111,95,112,79,114,71,116,85,115,102,113]).setFill(c);
+					g.createPolyline([108,101,98,99,87,99,78,99,93,100,105,102]).setFill(c);
+					g.createPolyline([85,63,91,63,97,60,104,60,108,62,111,69,112,75,110,74,108,71,103,73,106,69,105,65,103,64,103,67,102,70,99,70,97,66,94,67,97,72,88,67,84,66]).setFill(c);
+					g.createPolyline([140,74,141,66,144,61,150,61,156,62,153,70,150,73,152,65,150,65,151,68,149,71,146,71,144,66,143,70,143,74]).setFill(c);
+					g.createPolyline([146,20,156,11,163,9,172,9,178,14,182,18,184,32,182,42,182,52,177,58,176,67,171,76,165,90,157,105,160,92,164,85,168,78,167,73,173,66,172,62,175,59,174,55,177,53,180,46,181,29,179,21,173,13,166,11,159,13,153,18,148,23]).setFill(c);
+					g.createPolyline([150,187,148,211,150,233,153,247,148,267,135,283,125,299,136,292,131,313,122,328,122,345,129,352,133,359,133,367,137,359,148,356,140,350,131,347,129,340,132,332,140,328,137,322,140,304,154,265,157,244,155,223,161,220,175,229,186,247,185,260,176,275,178,287,185,277,188,261,196,253,189,236,174,213]).setFill(c);
+					g.createPolyline([147,338,142,341,143,345,141,354,147,343]).setFill(c);
+					g.createPolyline([157,342,156,349,150,356,157,353,163,346,162,342]).setFill(c);
+					g.createPolyline([99,265,96,284,92,299,73,339,73,333,87,300]).setFill(c);
+                }
+            },
+			{
+				name: "Draw Butterfly",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 20,
+                setUp: function() {
+                    createSurface();
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+					var f, g;
+                    surface.clear();
+					var m = dojox.gfx.matrix;
+					var initial_matrix = m.translate(140, 180);
+					surface.createRect({x: 0, y: 0, width: 700, height: 700}).setFill("#eee");
+					g = surface.createGroup().setTransform(initial_matrix);
+					g.createPath("M204.33 139.83 C196.33 133.33 206.68 132.82 206.58 132.58 C192.33 97.08 169.35 81.41 167.58 80.58 C162.12 78.02 159.48 78.26 160.45 76.97 C161.41 75.68 167.72 79.72 168.58 80.33 C193.83 98.33 207.58 132.33 207.58 132.33 C207.58 132.33 209.33 133.33 209.58 132.58 C219.58 103.08 239.58 87.58 246.33 81.33 C253.08 75.08 256.63 74.47 247.33 81.58 C218.58 103.58 210.34 132.23 210.83 132.33 C222.33 134.83 211.33 140.33 211.83 139.83 C214.85 136.81 214.83 145.83 214.83 145.83  [...]
+					g.createPath("M203.62 139.62 C195.62 133.12 205.96 132.6 205.87 132.37 C191.62 96.87 168.64 81.2 166.87 80.37 C161.41 77.81 158.77 78.05 159.73 76.76 C160.69 75.47 167.01 79.51 167.87 80.12 C193.12 98.12 206.87 132.12 206.87 132.12 C206.87 132.12 208.62 133.12 208.87 132.37 C218.87 102.87 238.87 87.37 245.62 81.12 C252.37 74.87 255.92 74.26 246.62 81.37 C217.87 103.37 209.63 132.01 210.12 132.12 C221.62 134.62 210.62 140.12 211.12 139.62 C214.14 136.6 214.12 145.62 214.12 145.62 C21 [...]
+					g.createPath("M363.73 85.73 C359.27 86.29 355.23 86.73 354.23 81.23 C353.23 75.73 355.73 73.73 363.23 75.73 C370.73 77.73 375.73 84.23 363.73 85.73 zM327.23 89.23 C327.23 89.23 308.51 93.65 325.73 80.73 C333.73 74.73 334.23 79.73 334.73 82.73 C335.48 87.2 327.23 89.23 327.23 89.23 zM384.23 48.73 C375.88 47.06 376.23 42.23 385.23 40.23 C386.7 39.91 389.23 49.73 384.23 48.73 zM389.23 48.73 C391.73 48.23 395.73 49.23 396.23 52.73 C396.73 56.23 392.73 58.23 390.23 56.23 C387.73 54.23 38 [...]
+                }
+            },
+			{
+				name: "Rotate Tiger",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 20,
+                setUp: function() {
+                    createSurface();
+					var f, g;
+                    surface.clear();
+					var initial_matrix = dojox.gfx.matrix.translate(250, 250);
+                    matrix = initial_matrix;
+					surface.createRect({x: 0, y: 0, width: 700, height: 700}).setFill("#eee");
+					g = surface.createGroup().setTransform(initial_matrix);
+                    gfxGroup = g;
+					var s = {color: "black", width: 1};
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-118.774 81.262C-118.774 81.262 -119.323 83.078 -120.092 82.779C-120.86 82.481 -119.977 31.675 -140.043 26.801C-140.043 26.801 -120.82 25.937 -118.774 81.262z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-91.284 123.59C-91.284 123.59 -89.648 124.55 -90.118 125.227C-90.589 125.904 -139.763 113.102 -149.218 131.459C-149.218 131.459 -145.539 112.572 -91.284 123.59z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-94.093 133.801C-94.093 133.801 -92.237 134.197 -92.471 134.988C-92.704 135.779 -143.407 139.121 -146.597 159.522C-146.597 159.522 -149.055 140.437 -94.093 133.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-98.304 128.276C-98.304 128.276 -96.526 128.939 -96.872 129.687C-97.218 130.435 -147.866 126.346 -153.998 146.064C-153.998 146.064 -153.646 126.825 -98.304 128.276z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-109.009 110.072C-109.009 110.072 -107.701 111.446 -108.34 111.967C-108.979 112.488 -152.722 86.634 -166.869 101.676C-166.869 101.676 -158.128 84.533 -109.009 110.072z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-116.554 114.263C-116.554 114.263 -115.098 115.48 -115.674 116.071C-116.25 116.661 -162.638 95.922 -174.992 112.469C-174.992 112.469 -168.247 94.447 -116.554 114.263z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-119.154 118.335C-119.154 118.335 -117.546 119.343 -118.036 120.006C-118.526 120.669 -167.308 106.446 -177.291 124.522C-177.291 124.522 -173.066 105.749 -119.154 118.335z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-108.42 118.949C-108.42 118.949 -107.298 120.48 -107.999 120.915C-108.7 121.35 -148.769 90.102 -164.727 103.207C-164.727 103.207 -153.862 87.326 -108.42 118.949z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-128.2 90C-128.2 90 -127.6 91.8 -128.4 92C-129.2 92.2 -157.8 50.2 -177.001 57.8C-177.001 57.8 -161.8 46 -128.2 90z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-127.505 96.979C-127.505 96.979 -126.53 98.608 -127.269 98.975C-128.007 99.343 -164.992 64.499 -182.101 76.061C-182.101 76.061 -169.804 61.261 -127.505 96.979z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-127.62 101.349C-127.62 101.349 -126.498 102.88 -127.199 103.315C-127.9 103.749 -167.969 72.502 -183.927 85.607C-183.927 85.607 -173.062 69.726 -127.62 101.349z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = "#000000";
+					g.createPath("M-129.83 103.065C-129.327 109.113 -128.339 115.682 -126.6 118.801C-126.6 118.801 -130.2 131.201 -121.4 144.401C-121.4 144.401 -121.8 151.601 -120.2 154.801C-120.2 154.801 -116.2 163.201 -111.4 164.001C-107.516 164.648 -98.793 167.717 -88.932 169.121C-88.932 169.121 -71.8 183.201 -75 196.001C-75 196.001 -75.4 212.401 -79 214.001C-79 214.001 -67.4 202.801 -77 219.601L-81.4 238.401C-81.4 238.401 -55.8 216.801 -71.4 235.201L-81.4 261.201C-81.4 261.201 -61.8 242.801 -69 251 [...]
+					f = "#cc7226"; s = "#000000";
+					g.createPath("M299.717 80.245C300.345 80.426 302.551 81.55 303.801 83.2C303.801 83.2 310.601 94 305.401 75.6C305.401 75.6 296.201 46.8 305.001 58C305.001 58 311.001 65.2 307.801 51.6C303.936 35.173 301.401 28.8 301.401 28.8C301.401 28.8 313.001 33.6 286.201 -6L295.001 -2.4C295.001 -2.4 275.401 -42 253.801 -47.2L245.801 -53.2C245.801 -53.2 284.201 -91.2 271.401 -128C271.401 -128 264.601 -133.2 255.001 -124C255.001 -124 248.601 -119.2 242.601 -120.8C242.601 -120.8 211.801 -119.6 209.8 [...]
+					f = "#cc7226"; s = null;
+					g.createPath("M-115.6 102.6C-140.6 63.2 -126.2 119.601 -126.2 119.601C-117.4 154.001 12.2 116.401 12.2 116.401C12.2 116.401 181.001 86 192.201 82C203.401 78 298.601 84.4 298.601 84.4L293.001 67.6C228.201 21.2 209.001 44.4 195.401 40.4C181.801 36.4 184.201 46 181.001 46.8C177.801 47.6 138.601 22.8 132.201 23.6C125.801 24.4 100.459 0.649 115.401 32.4C131.401 66.4 57 71.6 40.2 60.4C23.4 49.2 47.4 78.8 47.4 78.8C65.8 98.8 31.4 82 31.4 82C-3 69.2 -27 94.8 -30.2 95.6C-33.4 96.4 -38.2 99.6 [...]
+					f = "#e87f3a";
+					g.createPath("M133.51 25.346C127.11 26.146 101.743 2.407 116.71 34.146C133.31 69.346 58.31 73.346 41.51 62.146C24.709 50.946 48.71 80.546 48.71 80.546C67.11 100.546 32.709 83.746 32.709 83.746C-1.691 70.946 -25.691 96.546 -28.891 97.346C-32.091 98.146 -36.891 101.346 -37.691 94.946C-38.491 88.546 -45.87 72.012 -77.691 98.146C-98.927 115.492 -112.418 94.037 -112.418 94.037L-115.618 104.146C-140.618 64.346 -125.546 122.655 -125.546 122.655C-116.745 157.056 13.509 118.146 13.509 118.14 [...]
+					f = "#ea8c4d";
+					g.createPath("M134.819 27.091C128.419 27.891 103.685 3.862 118.019 35.891C134.219 72.092 59.619 75.092 42.819 63.892C26.019 52.692 50.019 82.292 50.019 82.292C68.419 102.292 34.019 85.492 34.019 85.492C-0.381 72.692 -24.382 98.292 -27.582 99.092C-30.782 99.892 -35.582 103.092 -36.382 96.692C-37.182 90.292 -44.43 73.925 -76.382 99.892C-98.855 117.983 -112.036 97.074 -112.036 97.074L-115.636 105.692C-139.436 66.692 -124.891 125.71 -124.891 125.71C-116.091 160.11 14.819 119.892 14.819  [...]
+					f = "#ec9961";
+					g.createPath("M136.128 28.837C129.728 29.637 104.999 5.605 119.328 37.637C136.128 75.193 60.394 76.482 44.128 65.637C27.328 54.437 51.328 84.037 51.328 84.037C69.728 104.037 35.328 87.237 35.328 87.237C0.928 74.437 -23.072 100.037 -26.272 100.837C-29.472 101.637 -34.272 104.837 -35.072 98.437C-35.872 92.037 -42.989 75.839 -75.073 101.637C-98.782 120.474 -111.655 100.11 -111.655 100.11L-115.655 107.237C-137.455 70.437 -124.236 128.765 -124.236 128.765C-115.436 163.165 16.128 121.637  [...]
+					f = "#eea575";
+					g.createPath("M137.438 30.583C131.037 31.383 106.814 7.129 120.637 39.383C137.438 78.583 62.237 78.583 45.437 67.383C28.637 56.183 52.637 85.783 52.637 85.783C71.037 105.783 36.637 88.983 36.637 88.983C2.237 76.183 -21.763 101.783 -24.963 102.583C-28.163 103.383 -32.963 106.583 -33.763 100.183C-34.563 93.783 -41.548 77.752 -73.763 103.383C-98.709 122.965 -111.273 103.146 -111.273 103.146L-115.673 108.783C-135.473 73.982 -123.582 131.819 -123.582 131.819C-114.782 166.22 17.437 123.38 [...]
+					f = "#f1b288";
+					g.createPath("M138.747 32.328C132.347 33.128 106.383 9.677 121.947 41.128C141.147 79.928 63.546 80.328 46.746 69.128C29.946 57.928 53.946 87.528 53.946 87.528C72.346 107.528 37.946 90.728 37.946 90.728C3.546 77.928 -20.454 103.528 -23.654 104.328C-26.854 105.128 -31.654 108.328 -32.454 101.928C-33.254 95.528 -40.108 79.665 -72.454 105.128C-98.636 125.456 -110.891 106.183 -110.891 106.183L-115.691 110.328C-133.691 77.128 -122.927 134.874 -122.927 134.874C-114.127 169.274 18.746 125.1 [...]
+					f = "#f3bf9c";
+					g.createPath("M140.056 34.073C133.655 34.873 107.313 11.613 123.255 42.873C143.656 82.874 64.855 82.074 48.055 70.874C31.255 59.674 55.255 89.274 55.255 89.274C73.655 109.274 39.255 92.474 39.255 92.474C4.855 79.674 -19.145 105.274 -22.345 106.074C-25.545 106.874 -30.345 110.074 -31.145 103.674C-31.945 97.274 -38.668 81.578 -71.145 106.874C-98.564 127.947 -110.509 109.219 -110.509 109.219L-115.709 111.874C-131.709 81.674 -122.273 137.929 -122.273 137.929C-113.473 172.329 20.055 126. [...]
+					f = "#f5ccb0";
+					g.createPath("M141.365 35.819C134.965 36.619 107.523 13.944 124.565 44.619C146.565 84.219 66.164 83.819 49.364 72.619C32.564 61.419 56.564 91.019 56.564 91.019C74.964 111.019 40.564 94.219 40.564 94.219C6.164 81.419 -17.836 107.019 -21.036 107.819C-24.236 108.619 -29.036 111.819 -29.836 105.419C-30.636 99.019 -37.227 83.492 -69.836 108.619C-98.491 130.438 -110.127 112.256 -110.127 112.256L-115.727 113.419C-130.128 85.019 -121.618 140.983 -121.618 140.983C-112.818 175.384 21.364 128. [...]
+					f = "#f8d8c4";
+					g.createPath("M142.674 37.565C136.274 38.365 108.832 15.689 125.874 46.365C147.874 85.965 67.474 85.565 50.674 74.365C33.874 63.165 57.874 92.765 57.874 92.765C76.274 112.765 41.874 95.965 41.874 95.965C7.473 83.165 -16.527 108.765 -19.727 109.565C-22.927 110.365 -27.727 113.565 -28.527 107.165C-29.327 100.765 -35.786 85.405 -68.527 110.365C-98.418 132.929 -109.745 115.293 -109.745 115.293L-115.745 114.965C-129.346 88.564 -120.963 144.038 -120.963 144.038C-112.163 178.438 22.673 130 [...]
+					f = "#fae5d7";
+					g.createPath("M143.983 39.31C137.583 40.11 110.529 17.223 127.183 48.11C149.183 88.91 68.783 87.31 51.983 76.11C35.183 64.91 59.183 94.51 59.183 94.51C77.583 114.51 43.183 97.71 43.183 97.71C8.783 84.91 -15.217 110.51 -18.417 111.31C-21.618 112.11 -26.418 115.31 -27.218 108.91C-28.018 102.51 -34.346 87.318 -67.218 112.11C-98.345 135.42 -109.363 118.329 -109.363 118.329L-115.764 116.51C-128.764 92.51 -120.309 147.093 -120.309 147.093C-111.509 181.493 23.983 132.11 23.983 132.11C23.98 [...]
+					f = "#fcf2eb";
+					g.createPath("M145.292 41.055C138.892 41.855 112.917 18.411 128.492 49.855C149.692 92.656 70.092 89.056 53.292 77.856C36.492 66.656 60.492 96.256 60.492 96.256C78.892 116.256 44.492 99.456 44.492 99.456C10.092 86.656 -13.908 112.256 -17.108 113.056C-20.308 113.856 -25.108 117.056 -25.908 110.656C-26.708 104.256 -32.905 89.232 -65.908 113.856C-98.273 137.911 -108.982 121.365 -108.982 121.365L-115.782 118.056C-128.582 94.856 -119.654 150.147 -119.654 150.147C-110.854 184.547 25.292 13 [...]
+					f = "#ffffff";
+					g.createPath("M-115.8 119.601C-128.6 97.6 -119 153.201 -119 153.201C-110.2 187.601 26.6 135.601 26.6 135.601C26.6 135.601 195.401 105.2 206.601 101.2C217.801 97.2 303.401 102.8 303.401 102.8L298.601 80.4C233.801 34 223.401 63.6 209.801 59.6C196.201 55.6 198.601 65.2 195.401 66C192.201 66.8 153.001 42 146.601 42.8C140.201 43.6 114.981 19.793 129.801 51.6C152.028 99.307 69.041 89.227 54.6 79.6C37.8 68.4 61.8 98 61.8 98C80.2 118.001 45.8 101.2 45.8 101.2C11.4 88.4 -12.6 114.001 -15.8 1 [...]
+					f = "#000000";
+					g.createPath("M-74.2 149.601C-74.2 149.601 -81.4 161.201 -60.6 174.401C-60.6 174.401 -59.2 175.801 -77.2 171.601C-77.2 171.601 -83.4 169.601 -85 159.201C-85 159.201 -89.8 154.801 -94.6 149.201C-99.4 143.601 -74.2 149.601 -74.2 149.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M65.8 102C65.8 102 83.498 128.821 82.9 133.601C81.6 144.001 81.4 153.601 84.6 157.601C87.801 161.601 96.601 194.801 96.601 194.801C96.601 194.801 96.201 196.001 108.601 158.001C108.601 158.001 120.201 142.001 100.201 123.601C100.201 123.601 65 94.8 65.8 102z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-54.2 176.401C-54.2 176.401 -43 183.601 -57.4 214.801L-51 212.401C-51 212.401 -51.8 223.601 -55 226.001L-47.8 222.801C-47.8 222.801 -43 230.801 -47 235.601C-47 235.601 -30.2 243.601 -31 250.001C-31 250.001 -24.6 242.001 -28.6 235.601C-32.6 229.201 -39.8 233.201 -39 214.801L-47.8 218.001C-47.8 218.001 -42.2 209.201 -42.2 202.801L-50.2 205.201C-50.2 205.201 -34.731 178.623 -45.4 177.201C-51.4 176.401 -54.2 176.401 -54.2 176.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-21.8 193.201C-21.8 193.201 -19 188.801 -21.8 189.601C-24.6 190.401 -55.8 205.201 -61.8 214.801C-61.8 214.801 -27.4 190.401 -21.8 193.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-11.4 201.201C-11.4 201.201 -8.6 196.801 -11.4 197.601C-14.2 198.401 -45.4 213.201 -51.4 222.801C-51.4 222.801 -17 198.401 -11.4 201.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M1.8 186.001C1.8 186.001 4.6 181.601 1.8 182.401C-1 183.201 -32.2 198.001 -38.2 207.601C-38.2 207.601 -3.8 183.201 1.8 186.001z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-21.4 229.601C-21.4 229.601 -21.4 223.601 -24.2 224.401C-27 225.201 -63 242.801 -69 252.401C-69 252.401 -27 226.801 -21.4 229.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-20.2 218.801C-20.2 218.801 -19 214.001 -21.8 214.801C-23.8 214.801 -50.2 226.401 -56.2 236.001C-56.2 236.001 -26.6 214.401 -20.2 218.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-34.6 266.401L-44.6 274.001C-44.6 274.001 -34.2 266.401 -30.6 267.601C-30.6 267.601 -37.4 278.801 -38.2 284.001C-38.2 284.001 -27.8 271.201 -22.2 271.601C-22.2 271.601 -14.6 272.001 -14.6 282.801C-14.6 282.801 -9 272.401 -5.8 272.801C-5.8 272.801 -4.6 279.201 -5.8 286.001C-5.8 286.001 -1.8 278.401 2.2 280.001C2.2 280.001 8.6 278.001 7.8 289.601C7.8 289.601 7.8 300.001 7 302.801C7 302.801 12.6 276.401 15 276.001C15 276.001 23 274.801 27.8 283.601C27.8 283.601 23.8 276. [...]
+					f = "#000000";
+					g.createPath("M-29.8 173.601C-29.8 173.601 -15 167.601 25 173.601C25 173.601 32.2 174.001 39 165.201C45.8 156.401 72.6 149.201 79 151.201L88.601 157.601L89.401 158.801C89.401 158.801 101.801 169.201 102.201 176.801C102.601 184.401 87.801 232.401 78.2 248.401C68.6 264.401 59 276.801 39.8 274.401C39.8 274.401 19 270.401 -6.6 274.401C-6.6 274.401 -35.8 272.801 -38.6 264.801C-41.4 256.801 -27.4 241.601 -27.4 241.601C-27.4 241.601 -23 233.201 -24.2 218.801C-25.4 204.401 -25 176.401 -29.8 [...]
+					f = "#e5668c";
+					g.createPath("M-7.8 175.601C0.6 194.001 -29 259.201 -29 259.201C-31 260.801 -16.34 266.846 -6.2 264.401C4.746 261.763 45 266.001 45 266.001C68.6 250.401 81.4 206.001 81.4 206.001C81.4 206.001 91.801 182.001 74.2 178.801C56.6 175.601 -7.8 175.601 -7.8 175.601z").setFill(f).setStroke(s);
+					f = "#b23259";
+					g.createPath("M-9.831 206.497C-6.505 193.707 -4.921 181.906 -7.8 175.601C-7.8 175.601 54.6 182.001 65.8 161.201C70.041 153.326 84.801 184.001 84.4 193.601C84.4 193.601 21.4 208.001 6.6 196.801L-9.831 206.497z").setFill(f).setStroke(s);
+					f = "#a5264c";
+					g.createPath("M-5.4 222.801C-5.4 222.801 -3.4 230.001 -5.8 234.001C-5.8 234.001 -7.4 234.801 -8.6 235.201C-8.6 235.201 -7.4 238.801 -1.4 240.401C-1.4 240.401 0.6 244.801 3 245.201C5.4 245.601 10.2 251.201 14.2 250.001C18.2 248.801 29.4 244.801 29.4 244.801C29.4 244.801 35 241.601 43.8 245.201C43.8 245.201 46.175 244.399 46.6 240.401C47.1 235.701 50.2 232.001 52.2 230.001C54.2 228.001 63.8 215.201 62.6 214.801C61.4 214.401 -5.4 222.801 -5.4 222.801z").setFill(f).setStroke(s);
+					f = "#ff727f"; s = "#000000";
+					g.createPath("M-9.8 174.401C-9.8 174.401 -12.6 196.801 -9.4 205.201C-6.2 213.601 -7 215.601 -7.8 219.601C-8.6 223.601 -4.2 233.601 1.4 239.601L13.4 241.201C13.4 241.201 28.6 237.601 37.8 240.401C37.8 240.401 46.794 241.744 50.2 226.801C50.2 226.801 55 220.401 62.2 217.601C69.4 214.801 76.6 173.201 72.6 165.201C68.6 157.201 54.2 152.801 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-8.2 249.201C-8.2 249.201 -9 247.201 -13.4 246.801C-13.4 246.801 -35.8 243.201 -44.2 230.801C-44.2 230.801 -51 225.201 -46.6 236.801C-46.6 236.801 -36.2 257.201 -29.4 260.001C-29.4 260.001 -13 264.001 -8.2 249.201z").setFill(f).setStroke(s);
+					f = "#cc3f4c"; s = null;
+					g.createPath("M71.742 185.229C72.401 177.323 74.354 168.709 72.6 165.201C66.154 152.307 49.181 157.695 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401C-9.8 174.401 -11.545 188.364 -10.705 198.376C-10.705 198.376 26.6 186.801 27.4 192.401C27.4 192.401 29 189.201 38.2 189.201C47.4 189.201 70.142 188.029 71.742 185.229z").setFill(f).setStroke(s);
+					s = {color: "#a51926", width: 2}; f = null;
+					g.createPath("M28.6 175.201C28.6 175.201 33.4 180.001 29.8 189.601C29.8 189.601 15.4 205.601 17.4 219.601").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-19.4 260.001C-19.4 260.001 -23.8 247.201 -15 254.001C-15 254.001 -10.2 256.001 -11.4 257.601C-12.6 259.201 -18.2 263.201 -19.4 260.001z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-14.36 261.201C-14.36 261.201 -17.88 250.961 -10.84 256.401C-10.84 256.401 -6.419 258.849 -7.96 259.281C-12.52 260.561 -7.96 263.121 -14.36 261.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-9.56 261.201C-9.56 261.201 -13.08 250.961 -6.04 256.401C-6.04 256.401 -1.665 258.711 -3.16 259.281C-6.52 260.561 -3.16 263.121 -9.56 261.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-2.96 261.401C-2.96 261.401 -6.48 251.161 0.56 256.601C0.56 256.601 4.943 258.933 3.441 259.481C0.48 260.561 3.441 263.321 -2.96 261.401z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M3.52 261.321C3.52 261.321 0 251.081 7.041 256.521C7.041 256.521 10.881 258.121 9.921 259.401C8.961 260.681 9.921 263.241 3.52 261.321z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M10.2 262.001C10.2 262.001 5.4 249.601 14.6 256.001C14.6 256.001 19.4 258.001 18.2 259.601C17 261.201 18.2 264.401 10.2 262.001z").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2}; f = null;
+					g.createPath("M-18.2 244.801C-18.2 244.801 -5 242.001 1 245.201C1 245.201 7 246.401 8.2 246.001C9.4 245.601 12.6 245.201 12.6 245.201").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2};
+					g.createPath("M15.8 253.601C15.8 253.601 27.8 240.001 39.8 244.401C46.816 246.974 45.8 243.601 46.6 240.801C47.4 238.001 47.6 233.801 52.6 230.801").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M33 237.601C33 237.601 29 226.801 26.2 239.601C23.4 252.401 20.2 256.001 18.6 258.801C18.6 258.801 18.6 264.001 27 263.601C27 263.601 37.8 263.201 38.2 260.401C38.6 257.601 37 246.001 33 237.601z").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2}; f = null;
+					g.createPath("M47 244.801C47 244.801 50.6 242.401 53 243.601").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2};
+					g.createPath("M53.5 228.401C53.5 228.401 56.4 223.501 61.2 222.701").setFill(f).setStroke(s);
+					f = "#b2b2b2"; s = null;
+					g.createPath("M-25.8 265.201C-25.8 265.201 -7.8 268.401 -3.4 266.801C-3.4 266.801 5.4 266.801 -3 268.801C-3 268.801 -15.8 268.801 -23.8 267.601C-23.8 267.601 -35.4 262.001 -25.8 265.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-11.8 172.001C-11.8 172.001 5.8 172.001 7.8 172.801C7.8 172.801 15 203.601 11.4 211.201C11.4 211.201 10.2 214.001 7.4 208.401C7.4 208.401 -11 175.601 -14.2 173.601C-17.4 171.601 -13 172.001 -11.8 172.001z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-88.9 169.301C-88.9 169.301 -80 171.001 -67.4 173.601C-67.4 173.601 -62.6 196.001 -59.4 200.801C-56.2 205.601 -59.8 205.601 -63.4 202.801C-67 200.001 -81.8 186.001 -83.8 181.601C-85.8 177.201 -88.9 169.301 -88.9 169.301z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-67.039 173.818C-67.039 173.818 -61.239 175.366 -60.23 177.581C-59.222 179.795 -61.432 183.092 -61.432 183.092C-61.432 183.092 -62.432 186.397 -63.634 184.235C-64.836 182.072 -67.708 174.412 -67.039 173.818z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M-67 173.601C-67 173.601 -63.4 178.801 -59.8 178.801C-56.2 178.801 -55.818 178.388 -53 179.001C-48.4 180.001 -48.8 178.001 -42.2 179.201C-39.56 179.681 -37 178.801 -34.2 180.001C-31.4 181.201 -28.2 180.401 -27 178.401C-25.8 176.401 -21 172.201 -21 172.201C-21 172.201 -33.8 174.001 -36.6 174.801C-36.6 174.801 -59 176.001 -67 173.601z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-22.4 173.801C-22.4 173.801 -28.85 177.301 -29.25 179.701C-29.65 182.101 -24 185.801 -24 185.801C-24 185.801 -21.25 190.401 -20.65 188.001C-20.05 185.601 -21.6 174.201 -22.4 173.801z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-59.885 179.265C-59.885 179.265 -52.878 190.453 -52.661 179.242C-52.661 179.242 -52.104 177.984 -53.864 177.962C-59.939 177.886 -58.418 173.784 -59.885 179.265z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-52.707 179.514C-52.707 179.514 -44.786 190.701 -45.422 179.421C-45.422 179.421 -45.415 179.089 -47.168 178.936C-51.915 178.522 -51.57 174.004 -52.707 179.514z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-45.494 179.522C-45.494 179.522 -37.534 190.15 -38.203 180.484C-38.203 180.484 -38.084 179.251 -39.738 178.95C-43.63 178.244 -43.841 174.995 -45.494 179.522z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-38.618 179.602C-38.618 179.602 -30.718 191.163 -30.37 181.382C-30.37 181.382 -28.726 180.004 -30.472 179.782C-36.29 179.042 -35.492 174.588 -38.618 179.602z").setFill(f).setStroke(s);
+					f = "#e5e5b2"; s = null;
+					g.createPath("M-74.792 183.132L-82.45 181.601C-85.05 176.601 -87.15 170.451 -87.15 170.451C-87.15 170.451 -80.8 171.451 -68.3 174.251C-68.3 174.251 -67.424 177.569 -65.952 183.364L-74.792 183.132z").setFill(f).setStroke(s);
+					f = "#e5e5b2";
+					g.createPath("M-9.724 178.47C-11.39 175.964 -12.707 174.206 -13.357 173.8C-16.37 171.917 -12.227 172.294 -11.098 172.294C-11.098 172.294 5.473 172.294 7.356 173.047C7.356 173.047 7.88 175.289 8.564 178.68C8.564 178.68 -1.524 176.67 -9.724 178.47z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M43.88 40.321C71.601 44.281 97.121 8.641 98.881 -1.04C100.641 -10.72 90.521 -22.6 90.521 -22.6C91.841 -25.68 87.001 -39.76 81.721 -49C76.441 -58.24 60.54 -57.266 43 -58.24C27.16 -59.12 8.68 -35.8 7.36 -34.04C6.04 -32.28 12.2 6.001 13.52 11.721C14.84 17.441 12.2 43.841 12.2 43.841C46.44 34.741 16.16 36.361 43.88 40.321z").setFill(f).setStroke(s);
+					f = "#ea8e51";
+					g.createPath("M8.088 -33.392C6.792 -31.664 12.84 5.921 14.136 11.537C15.432 17.153 12.84 43.073 12.84 43.073C45.512 34.193 16.728 35.729 43.944 39.617C71.161 43.505 96.217 8.513 97.945 -0.992C99.673 -10.496 89.737 -22.16 89.737 -22.16C91.033 -25.184 86.281 -39.008 81.097 -48.08C75.913 -57.152 60.302 -56.195 43.08 -57.152C27.528 -58.016 9.384 -35.12 8.088 -33.392z").setFill(f).setStroke(s);
+					f = "#efaa7c";
+					g.createPath("M8.816 -32.744C7.544 -31.048 13.48 5.841 14.752 11.353C16.024 16.865 13.48 42.305 13.48 42.305C44.884 33.145 17.296 35.097 44.008 38.913C70.721 42.729 95.313 8.385 97.009 -0.944C98.705 -10.272 88.953 -21.72 88.953 -21.72C90.225 -24.688 85.561 -38.256 80.473 -47.16C75.385 -56.064 60.063 -55.125 43.16 -56.064C27.896 -56.912 10.088 -34.44 8.816 -32.744z").setFill(f).setStroke(s);
+					f = "#f4c6a8";
+					g.createPath("M9.544 -32.096C8.296 -30.432 14.12 5.761 15.368 11.169C16.616 16.577 14.12 41.537 14.12 41.537C43.556 32.497 17.864 34.465 44.072 38.209C70.281 41.953 94.409 8.257 96.073 -0.895C97.737 -10.048 88.169 -21.28 88.169 -21.28C89.417 -24.192 84.841 -37.504 79.849 -46.24C74.857 -54.976 59.824 -54.055 43.24 -54.976C28.264 -55.808 10.792 -33.76 9.544 -32.096z").setFill(f).setStroke(s);
+					f = "#f9e2d3";
+					g.createPath("M10.272 -31.448C9.048 -29.816 14.76 5.681 15.984 10.985C17.208 16.289 14.76 40.769 14.76 40.769C42.628 31.849 18.432 33.833 44.136 37.505C69.841 41.177 93.505 8.129 95.137 -0.848C96.769 -9.824 87.385 -20.84 87.385 -20.84C88.609 -23.696 84.121 -36.752 79.225 -45.32C74.329 -53.888 59.585 -52.985 43.32 -53.888C28.632 -54.704 11.496 -33.08 10.272 -31.448z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M44.2 36.8C69.4 40.4 92.601 8 94.201 -0.8C95.801 -9.6 86.601 -20.4 86.601 -20.4C87.801 -23.2 83.4 -36 78.6 -44.4C73.8 -52.8 59.346 -51.914 43.4 -52.8C29 -53.6 12.2 -32.4 11 -30.8C9.8 -29.2 15.4 5.6 16.6 10.8C17.8 16 15.4 40 15.4 40C40.9 31.4 19 33.2 44.2 36.8z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M90.601 2.8C90.601 2.8 62.8 10.4 51.2 8.8C51.2 8.8 35.4 2.2 26.6 24C26.6 24 23 31.2 21 33.2C19 35.2 90.601 2.8 90.601 2.8z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M94.401 0.6C94.401 0.6 65.4 12.8 55.4 12.4C55.4 12.4 39 7.8 30.6 22.4C30.6 22.4 22.2 31.6 19 33.2C19 33.2 18.6 34.8 25 30.8L35.4 36C35.4 36 50.2 45.6 59.8 29.6C59.8 29.6 63.8 18.4 63.8 16.4C63.8 14.4 85 8.8 86.601 8.4C88.201 8 94.801 3.8 94.401 0.6z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M47 36.514C40.128 36.514 31.755 32.649 31.755 26.4C31.755 20.152 40.128 13.887 47 13.887C53.874 13.887 59.446 18.952 59.446 25.2C59.446 31.449 53.874 36.514 47 36.514z").setFill(f).setStroke(s);
+					f = "#659900";
+					g.createPath("M43.377 19.83C38.531 20.552 33.442 22.055 33.514 21.839C35.054 17.22 41.415 13.887 47 13.887C51.296 13.887 55.084 15.865 57.32 18.875C57.32 18.875 52.004 18.545 43.377 19.83z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M55.4 19.6C55.4 19.6 51 16.4 51 18.6C51 18.6 54.6 23 55.4 19.6z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M45.4 27.726C42.901 27.726 40.875 25.7 40.875 23.2C40.875 20.701 42.901 18.675 45.4 18.675C47.9 18.675 49.926 20.701 49.926 23.2C49.926 25.7 47.9 27.726 45.4 27.726z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M-58.6 14.4C-58.6 14.4 -61.8 -6.8 -59.4 -11.2C-59.4 -11.2 -48.6 -21.2 -49 -24.8C-49 -24.8 -49.4 -42.8 -50.6 -43.6C-51.8 -44.4 -59.4 -50.4 -65.4 -44C-65.4 -44 -75.8 -26 -75 -19.6L-75 -17.6C-75 -17.6 -82.6 -18 -84.2 -16C-84.2 -16 -85.4 -10.8 -86.6 -10.4C-86.6 -10.4 -89.4 -8 -87.4 -5.2C-87.4 -5.2 -89.4 -2.8 -89 1.2L-81.4 5.2C-81.4 5.2 -79.4 19.6 -68.6 24.8C-63.764 27.129 -60.6 20.4 -58.6 14.4z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M-59.6 12.56C-59.6 12.56 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.48 -40.36 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.96 -59.6 12.56z").setF [...]
+					f = "#eb955c";
+					g.createPath("M-51.05 -42.61C-52.14 -43.47 -59.63 -49.24 -65.48 -43C-65.48 -43 -75.62 -25.45 -74.84 -19.21L-74.84 -17.26C-74.84 -17.26 -82.25 -17.65 -83.81 -15.7C-83.81 -15.7 -84.98 -10.63 -86.15 -10.24C-86.15 -10.24 -88.88 -7.9 -86.93 -5.17C-86.93 -5.17 -88.88 -2.83 -88.49 1.07L-81.08 4.97C-81.08 4.97 -79.13 19.01 -68.6 24.08C-63.886 26.35 -60.8 19.79 -58.85 13.94C-58.85 13.94 -61.97 -6.73 -59.63 -11.02C-59.63 -11.02 -49.1 -20.77 -49.49 -24.28C-49.49 -24.28 -49.88 -41.83 -51.05 -42 [...]
+					f = "#f2b892";
+					g.createPath("M-51.5 -41.62C-52.48 -42.54 -59.86 -48.08 -65.56 -42C-65.56 -42 -75.44 -24.9 -74.68 -18.82L-74.68 -16.92C-74.68 -16.92 -81.9 -17.3 -83.42 -15.4C-83.42 -15.4 -84.56 -10.46 -85.7 -10.08C-85.7 -10.08 -88.36 -7.8 -86.46 -5.14C-86.46 -5.14 -88.36 -2.86 -87.98 0.94L-80.76 4.74C-80.76 4.74 -78.86 18.42 -68.6 23.36C-64.006 25.572 -61 19.18 -59.1 13.48C-59.1 13.48 -62.14 -6.66 -59.86 -10.84C-59.86 -10.84 -49.6 -20.34 -49.98 -23.76C-49.98 -23.76 -50.36 -40.86 -51.5 -41.62z").set [...]
+					f = "#f8dcc8";
+					g.createPath("M-51.95 -40.63C-52.82 -41.61 -60.09 -46.92 -65.64 -41C-65.64 -41 -75.26 -24.35 -74.52 -18.43L-74.52 -16.58C-74.52 -16.58 -81.55 -16.95 -83.03 -15.1C-83.03 -15.1 -84.14 -10.29 -85.25 -9.92C-85.25 -9.92 -87.84 -7.7 -85.99 -5.11C-85.99 -5.11 -87.84 -2.89 -87.47 0.81L-80.44 4.51C-80.44 4.51 -78.59 17.83 -68.6 22.64C-64.127 24.794 -61.2 18.57 -59.35 13.02C-59.35 13.02 -62.31 -6.59 -60.09 -10.66C-60.09 -10.66 -50.1 -19.91 -50.47 -23.24C-50.47 -23.24 -50.84 -39.89 -51.95 -40. [...]
+					f = "#ffffff";
+					g.createPath("M-59.6 12.46C-59.6 12.46 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.16 -40.68 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.86 -59.6 12.46z").setF [...]
+					f = "#cccccc";
+					g.createPath("M-62.7 6.2C-62.7 6.2 -84.3 -4 -85.2 -4.8C-85.2 -4.8 -76.1 3.4 -75.3 3.4C-74.5 3.4 -62.7 6.2 -62.7 6.2z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-79.8 0C-79.8 0 -61.4 3.6 -61.4 8C-61.4 10.912 -61.643 24.331 -67 22.8C-75.4 20.4 -71.8 6 -79.8 0z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M-71.4 3.8C-71.4 3.8 -62.422 5.274 -61.4 8C-60.8 9.6 -60.137 17.908 -65.6 19C-70.152 19.911 -72.382 9.69 -71.4 3.8z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M14.595 46.349C14.098 44.607 15.409 44.738 17.2 44.2C19.2 43.6 31.4 39.8 32.2 37.2C33 34.6 46.2 39 46.2 39C48 39.8 52.4 42.4 52.4 42.4C57.2 43.6 63.8 44 63.8 44C66.2 45 69.6 47.8 69.6 47.8C84.2 58 96.601 50.8 96.601 50.8C116.601 44.2 110.601 27 110.601 27C107.601 18 110.801 14.6 110.801 14.6C111.001 10.8 118.201 17.2 118.201 17.2C120.801 21.4 121.601 26.4 121.601 26.4C129.601 37.6 126.201 19.8 126.201 19.8C126.401 18.8 123.601 15.2 123.601 14C123.601 12.8 121.801 9.4 1 [...]
+					f = "#000000";
+					g.createPath("M209.401 -120C209.401 -120 183.801 -112 181.001 -93.2C181.001 -93.2 178.601 -70.4 199.001 -52.8C199.001 -52.8 199.401 -46.4 201.401 -43.2C201.401 -43.2 199.801 -38.4 218.601 -46L245.801 -54.4C245.801 -54.4 252.201 -56.8 257.401 -65.6C262.601 -74.4 277.801 -93.2 274.201 -118.4C274.201 -118.4 275.401 -129.6 269.401 -130C269.401 -130 261.001 -131.6 253.801 -124C253.801 -124 247.001 -120.8 244.601 -121.2L209.401 -120z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M264.022 -120.99C264.022 -120.99 266.122 -129.92 261.282 -125.08C261.282 -125.08 254.242 -119.36 246.761 -119.36C246.761 -119.36 232.241 -117.16 227.841 -103.96C227.841 -103.96 223.881 -77.12 231.801 -71.4C231.801 -71.4 236.641 -63.92 243.681 -70.52C250.722 -77.12 266.222 -107.35 264.022 -120.99z").setFill(f).setStroke(s);
+					f = "#323232";
+					g.createPath("M263.648 -120.632C263.648 -120.632 265.738 -129.376 260.986 -124.624C260.986 -124.624 254.074 -119.008 246.729 -119.008C246.729 -119.008 232.473 -116.848 228.153 -103.888C228.153 -103.888 224.265 -77.536 232.041 -71.92C232.041 -71.92 236.793 -64.576 243.705 -71.056C250.618 -77.536 265.808 -107.24 263.648 -120.632z").setFill(f).setStroke(s);
+					f = "#666666";
+					g.createPath("M263.274 -120.274C263.274 -120.274 265.354 -128.832 260.69 -124.168C260.69 -124.168 253.906 -118.656 246.697 -118.656C246.697 -118.656 232.705 -116.536 228.465 -103.816C228.465 -103.816 224.649 -77.952 232.281 -72.44C232.281 -72.44 236.945 -65.232 243.729 -71.592C250.514 -77.952 265.394 -107.13 263.274 -120.274z").setFill(f).setStroke(s);
+					f = "#999999";
+					g.createPath("M262.9 -119.916C262.9 -119.916 264.97 -128.288 260.394 -123.712C260.394 -123.712 253.738 -118.304 246.665 -118.304C246.665 -118.304 232.937 -116.224 228.777 -103.744C228.777 -103.744 225.033 -78.368 232.521 -72.96C232.521 -72.96 237.097 -65.888 243.753 -72.128C250.41 -78.368 264.98 -107.02 262.9 -119.916z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M262.526 -119.558C262.526 -119.558 264.586 -127.744 260.098 -123.256C260.098 -123.256 253.569 -117.952 246.633 -117.952C246.633 -117.952 233.169 -115.912 229.089 -103.672C229.089 -103.672 225.417 -78.784 232.761 -73.48C232.761 -73.48 237.249 -66.544 243.777 -72.664C250.305 -78.784 264.566 -106.91 262.526 -119.558z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M262.151 -119.2C262.151 -119.2 264.201 -127.2 259.801 -122.8C259.801 -122.8 253.401 -117.6 246.601 -117.6C246.601 -117.6 233.401 -115.6 229.401 -103.6C229.401 -103.6 225.801 -79.2 233.001 -74C233.001 -74 237.401 -67.2 243.801 -73.2C250.201 -79.2 264.151 -106.8 262.151 -119.2z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M50.6 84C50.6 84 30.2 64.8 22.2 64C22.2 64 -12.2 60 -27 78C-27 78 -9.4 57.6 18.2 63.2C18.2 63.2 -3.4 58.8 -15.8 62C-15.8 62 -32.6 62 -42.2 76L-45 80.8C-45 80.8 -41 66 -22.6 60C-22.6 60 0.2 55.2 11 60C11 60 -10.6 53.2 -20.6 55.2C-20.6 55.2 -51 52.8 -63.8 79.2C-63.8 79.2 -59.8 64.8 -45 57.6C-45 57.6 -31.4 48.8 -11 51.6C-11 51.6 3.4 54.8 8.6 57.2C13.8 59.6 12.6 56.8 4.2 52C4.2 52 -1.4 42 -15.4 42.4C-15.4 42.4 -58.2 46 -68.6 58C-68.6 58 -55 46.8 -44.6 44C-44.6 44 -22.2 36  [...]
+					f = "#cccccc";
+					g.createPath("M189 278C189 278 173.5 241.5 161 232C161 232 187 248 190.5 266C190.5 266 190.5 276 189 278z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M236 285.5C236 285.5 209.5 230.5 191 206.5C191 206.5 234.5 244 239.5 270.5L240 276L237 273.5C237 273.5 236.5 282.5 236 285.5z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M292.5 237C292.5 237 230 177.5 228.5 175C228.5 175 289 241 292 248.5C292 248.5 290 239.5 292.5 237z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M104 280.5C104 280.5 123.5 228.5 142.5 251C142.5 251 157.5 261 157 264C157 264 153 257.5 135 258C135 258 116 255 104 280.5z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M294.5 153C294.5 153 249.5 124.5 242 123C230.193 120.639 291.5 152 296.5 162.5C296.5 162.5 298.5 160 294.5 153z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M143.801 259.601C143.801 259.601 164.201 257.601 171.001 250.801L175.401 254.401L193.001 216.001L196.601 221.201C196.601 221.201 211.001 206.401 210.201 198.401C209.401 190.401 223.001 204.401 223.001 204.401C223.001 204.401 222.201 192.801 229.401 199.601C229.401 199.601 227.001 184.001 235.401 192.001C235.401 192.001 224.864 161.844 247.401 187.601C253.001 194.001 248.601 187.201 248.601 187.201C248.601 187.201 222.601 139.201 244.201 153.601C244.201 153.601 246.201  [...]
+					f = "#000000";
+					g.createPath("M109.401 -97.2C109.401 -97.2 97.801 -105.2 93.801 -104.8C89.801 -104.4 121.401 -113.6 162.601 -86C162.601 -86 167.401 -83.2 171.001 -83.6C171.001 -83.6 174.201 -81.2 171.401 -77.6C171.401 -77.6 162.601 -68 173.801 -56.8C173.801 -56.8 192.201 -50 186.601 -58.8C186.601 -58.8 197.401 -54.8 199.801 -50.8C202.201 -46.8 201.001 -50.8 201.001 -50.8C201.001 -50.8 194.601 -58 188.601 -63.2C188.601 -63.2 183.401 -65.2 180.601 -73.6C177.801 -82 175.401 -92 179.801 -95.2C179.801 - [...]
+					f = "#cc7226";
+					g.createPath("M180.801 -106.4C180.801 -106.4 170.601 -113.8 168.601 -113.8C166.601 -113.8 154.201 -124 150.001 -123.6C145.801 -123.2 133.601 -133.2 106.201 -125C106.201 -125 105.601 -127 109.201 -127.8C109.201 -127.8 115.601 -130 116.001 -130.6C116.001 -130.6 136.201 -134.8 143.401 -131.2C143.401 -131.2 152.601 -128.6 158.801 -122.4C158.801 -122.4 170.001 -119.2 173.201 -120.2C173.201 -120.2 182.001 -118 182.401 -116.2C182.401 -116.2 188.201 -113.2 186.401 -110.6C186.401 -110.6 186. [...]
+					f = "#cc7226";
+					g.createPath("M168.33 -108.509C169.137 -107.877 170.156 -107.779 170.761 -106.97C170.995 -106.656 170.706 -106.33 170.391 -106.233C169.348 -105.916 168.292 -106.486 167.15 -105.898C166.748 -105.691 166.106 -105.873 165.553 -106.022C163.921 -106.463 162.092 -106.488 160.401 -105.8C158.416 -106.929 156.056 -106.345 153.975 -107.346C153.917 -107.373 153.695 -107.027 153.621 -107.054C150.575 -108.199 146.832 -107.916 144.401 -110.2C141.973 -110.612 139.616 -111.074 137.188 -111.754C135. [...]
+					f = "#cc7226";
+					g.createPath("M91.696 -122.739C89.178 -124.464 86.81 -125.57 84.368 -127.356C84.187 -127.489 83.827 -127.319 83.625 -127.441C82.618 -128.05 81.73 -128.631 80.748 -129.327C80.209 -129.709 79.388 -129.698 78.88 -129.956C76.336 -131.248 73.707 -131.806 71.2 -133C71.882 -133.638 73.004 -133.394 73.6 -134.2C73.795 -133.92 74.033 -133.636 74.386 -133.827C76.064 -134.731 77.914 -134.884 79.59 -134.794C81.294 -134.702 83.014 -134.397 84.789 -134.125C85.096 -134.078 85.295 -133.555 85.618 -1 [...]
+					f = "#cc7226";
+					g.createPath("M59.198 -115.391C56.044 -116.185 52.994 -116.07 49.978 -117.346C49.911 -117.374 49.688 -117.027 49.624 -117.054C48.258 -117.648 47.34 -118.614 46.264 -119.66C45.351 -120.548 43.693 -120.161 42.419 -120.648C42.095 -120.772 41.892 -121.284 41.591 -121.323C40.372 -121.48 39.445 -122.429 38.4 -123C40.736 -123.795 43.147 -123.764 45.609 -124.148C45.722 -124.166 45.867 -123.845 46 -123.845C46.136 -123.845 46.266 -124.066 46.4 -124.2C46.595 -123.92 46.897 -123.594 47.154 -123 [...]
+					f = "#cc7226";
+					g.createPath("M45.338 -71.179C43.746 -72.398 43.162 -74.429 42.034 -76.221C41.82 -76.561 42.094 -76.875 42.411 -76.964C42.971 -77.123 43.514 -76.645 43.923 -76.443C45.668 -75.581 47.203 -74.339 49.2 -74.2C51.19 -71.966 55.45 -71.581 55.457 -68.2C55.458 -67.341 54.03 -68.259 53.6 -67.4C51.149 -68.403 48.76 -68.3 46.38 -69.767C45.763 -70.148 46.093 -70.601 45.338 -71.179z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M17.8 -123.756C17.935 -123.755 24.966 -123.522 24.949 -123.408C24.904 -123.099 17.174 -122.05 16.81 -122.22C16.646 -122.296 9.134 -119.866 9 -120C9.268 -120.135 17.534 -123.756 17.8 -123.756z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M33.2 -114C33.2 -114 18.4 -112.2 14 -111C9.6 -109.8 -9 -102.2 -12 -100.2C-12 -100.2 -25.4 -94.8 -42.4 -74.8C-42.4 -74.8 -34.8 -78.2 -32.6 -81C-32.6 -81 -19 -93.6 -19.2 -91C-19.2 -91 -7 -99.6 -7.6 -97.4C-7.6 -97.4 16.8 -108.6 14.8 -105.4C14.8 -105.4 36.4 -110 35.4 -108C35.4 -108 54.2 -103.6 51.4 -103.4C51.4 -103.4 45.6 -102.2 52 -98.6C52 -98.6 48.6 -94.2 43.2 -98.2C37.8 -102.2 40.8 -100 35.8 -99C35.8 -99 33.2 -98.2 28.6 -102.2C28.6 -102.2 23 -106.8 14.2 -103.2C14.2 -103 [...]
+					s = {color: "#4c0000", width: 2}; f = null;
+					g.createPath("M51.4 85C51.4 85 36.4 68.2 28 65.6C28 65.6 14.6 58.8 -10 66.6").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M24.8 64.2C24.8 64.2 -0.4 56.2 -15.8 60.4C-15.8 60.4 -34.2 62.4 -42.6 76.2").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M21.2 63C21.2 63 4.2 55.8 -10.6 53.6C-10.6 53.6 -27.2 51 -43.8 58.2C-43.8 58.2 -56 64.2 -61.4 74.4").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M22.2 63.4C22.2 63.4 6.8 52.4 5.8 51C5.8 51 -1.2 40 -14.2 39.6C-14.2 39.6 -35.6 40.4 -52.8 48.4").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M20.895 54.407C22.437 55.87 49.4 84.8 49.4 84.8C84.6 121.401 56.6 87.2 56.6 87.2C49 82.4 39.8 63.6 39.8 63.6C38.6 60.8 53.8 70.8 53.8 70.8C57.8 71.6 71.4 90.8 71.4 90.8C64.6 88.4 69.4 95.6 69.4 95.6C72.2 97.6 92.601 113.201 92.601 113.201C96.201 117.201 100.201 118.801 100.201 118.801C114.201 113.601 107.801 126.801 107.801 126.801C110.201 133.601 115.801 122.001 115.801 122.001C127.001 105.2 110.601 107.601 110.601 107.601C80.6 110.401 73.8 94.4 73.8 94.4C71.4 92 80.2 [...]
+					f = "#4c0000";
+					g.createPath("M-3 42.8C-3 42.8 8.6 48.4 11.2 51.2C13.8 54 27.8 65.4 27.8 65.4C27.8 65.4 22.4 63.4 19.8 61.6C17.2 59.8 6.4 51.6 6.4 51.6C6.4 51.6 2.6 45.6 -3 42.8z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M-61.009 11.603C-60.672 11.455 -61.196 8.743 -61.4 8.2C-62.422 5.474 -71.4 4 -71.4 4C-71.627 5.365 -71.682 6.961 -71.576 8.599C-71.576 8.599 -66.708 14.118 -61.009 11.603z").setFill(f).setStroke(s);
+					f = "#659900";
+					g.createPath("M-61.009 11.403C-61.458 11.561 -61.024 8.669 -61.2 8.2C-62.222 5.474 -71.4 3.9 -71.4 3.9C-71.627 5.265 -71.682 6.861 -71.576 8.499C-71.576 8.499 -67.308 13.618 -61.009 11.403z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-65.4 11.546C-66.025 11.546 -66.531 10.406 -66.531 9C-66.531 7.595 -66.025 6.455 -65.4 6.455C-64.775 6.455 -64.268 7.595 -64.268 9C-64.268 10.406 -64.775 11.546 -65.4 11.546z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-65.4 9z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-111 109.601C-111 109.601 -116.6 119.601 -91.8 113.601C-91.8 113.601 -77.8 112.401 -75.4 110.001C-74.2 110.801 -65.834 113.734 -63 114.401C-56.2 116.001 -47.8 106 -47.8 106C-47.8 106 -43.2 95.5 -40.4 95.5C-37.6 95.5 -40.8 97.1 -40.8 97.1C-40.8 97.1 -47.4 107.201 -47 108.801C-47 108.801 -52.2 128.801 -68.2 129.601C-68.2 129.601 -84.35 130.551 -83 136.401C-83 136.401 -74.2 134.001 -71.8 136.401C-71.8 136.401 -61 136.001 -69 142.401L-75.8 154.001C-75.8 154.001 -75.66 157 [...]
+					f = "#e59999";
+					g.createPath("M-112.2 113.601C-112.2 113.601 -114.2 123.201 -77.4 112.801C-77.4 112.801 -73 112.801 -70.6 113.601C-68.2 114.401 -56.2 117.201 -54.2 116.001C-54.2 116.001 -61.4 129.601 -73 128.001C-73 128.001 -86.2 129.601 -85.8 134.401C-85.8 134.401 -81.8 141.601 -77 144.001C-77 144.001 -74.2 146.401 -74.6 149.601C-75 152.801 -77.8 154.401 -79.8 155.201C-81.8 156.001 -85 152.801 -86.6 152.801C-88.2 152.801 -96.6 146.401 -101 141.601C-105.4 136.801 -113.8 124.801 -113.4 122.001C-113  [...]
+					f = "#b26565";
+					g.createPath("M-109 131.051C-106.4 135.001 -103.2 139.201 -101 141.601C-96.6 146.401 -88.2 152.801 -86.6 152.801C-85 152.801 -81.8 156.001 -79.8 155.201C-77.8 154.401 -75 152.801 -74.6 149.601C-74.2 146.401 -77 144.001 -77 144.001C-80.066 142.468 -82.806 138.976 -84.385 136.653C-84.385 136.653 -84.2 139.201 -89.4 138.401C-94.6 137.601 -99.8 134.801 -101.4 131.601C-103 128.401 -105.4 126.001 -103.8 129.601C-102.2 133.201 -99.8 136.801 -98.2 137.201C-96.6 137.601 -97 138.801 -99.4 138 [...]
+					f = "#992600";
+					g.createPath("M-111.6 110.001C-111.6 110.001 -109.8 96.4 -108.6 92.4C-108.6 92.4 -109.4 85.6 -107 81.4C-104.6 77.2 -102.6 71 -99.6 65.6C-96.6 60.2 -96.4 56.2 -92.4 54.6C-88.4 53 -82.4 44.4 -79.6 43.4C-76.8 42.4 -77 43.2 -77 43.2C-77 43.2 -70.2 28.4 -56.6 32.4C-56.6 32.4 -72.8 29.6 -57 20.2C-57 20.2 -61.8 21.3 -58.5 14.3C-56.299 9.632 -56.8 16.4 -67.8 28.2C-67.8 28.2 -72.8 36.8 -78 39.8C-83.2 42.8 -95.2 49.8 -96.4 53.6C-97.6 57.4 -100.8 63.2 -102.8 64.8C-104.8 66.4 -107.6 70.6 -108 7 [...]
+					f = "#ffffff";
+					g.createPath("M-120.2 114.601C-120.2 114.601 -122.2 113.201 -126.6 119.201C-126.6 119.201 -119.3 152.201 -119.3 153.601C-119.3 153.601 -118.2 151.501 -119.5 144.301C-120.8 137.101 -121.7 124.401 -121.7 124.401L-120.2 114.601z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-98.6 54C-98.6 54 -116.2 57.2 -115.8 86.4L-116.6 111.201C-116.6 111.201 -117.8 85.6 -119 84C-120.2 82.4 -116.2 71.2 -119.4 77.2C-119.4 77.2 -133.4 91.2 -125.4 112.401C-125.4 112.401 -123.9 115.701 -126.9 111.101C-126.9 111.101 -131.5 98.5 -130.4 92.1C-130.4 92.1 -130.2 89.9 -128.3 87.1C-128.3 87.1 -119.7 75.4 -117 73.1C-117 73.1 -115.2 58.7 -99.8 53.5C-99.8 53.5 -94.1 51.2 -98.6 54z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M40.8 -12.2C41.46 -12.554 41.451 -13.524 42.031 -13.697C43.18 -14.041 43.344 -15.108 43.862 -15.892C44.735 -17.211 44.928 -18.744 45.51 -20.235C45.782 -20.935 45.809 -21.89 45.496 -22.55C44.322 -25.031 43.62 -27.48 42.178 -29.906C41.91 -30.356 41.648 -31.15 41.447 -31.748C40.984 -33.132 39.727 -34.123 38.867 -35.443C38.579 -35.884 39.104 -36.809 38.388 -36.893C37.491 -36.998 36.042 -37.578 35.809 -36.552C35.221 -33.965 36.232 -31.442 37.2 -29C36.418 -28.308 36.752 -27. [...]
+					f = "#000000";
+					g.createPath("M31.959 -16.666C32.083 -16.743 31.928 -17.166 32.037 -17.382C32.199 -17.706 32.602 -17.894 32.764 -18.218C32.873 -18.434 32.71 -18.814 32.846 -18.956C35.179 -21.403 35.436 -24.427 34.4 -27.4C35.424 -28.02 35.485 -29.282 35.06 -30.129C34.207 -31.829 34.014 -33.755 33.039 -35.298C32.237 -36.567 30.659 -37.811 29.288 -36.508C28.867 -36.108 28.546 -35.321 28.824 -34.609C28.888 -34.446 29.173 -34.3 29.146 -34.218C29.039 -33.894 28.493 -33.67 28.487 -33.398C28.457 -31.902 27 [...]
+					f = "#000000";
+					g.createPath("M94.771 -26.977C96.16 -25.185 96.45 -22.39 94.401 -21C94.951 -17.691 98.302 -19.67 100.401 -20.2C100.292 -20.588 100.519 -20.932 100.802 -20.937C101.859 -20.952 102.539 -21.984 103.601 -21.8C104.035 -23.357 105.673 -24.059 106.317 -25.439C108.043 -29.134 107.452 -33.407 104.868 -36.653C104.666 -36.907 104.883 -37.424 104.759 -37.786C104.003 -39.997 101.935 -40.312 100.001 -41C98.824 -44.875 98.163 -48.906 96.401 -52.6C94.787 -52.85 94.089 -54.589 92.752 -55.309C91.419  [...]
+					f = "#000000";
+					g.createPath("M57.611 -8.591C56.124 -6.74 52.712 -4.171 55.629 -2.243C55.823 -2.114 56.193 -2.11 56.366 -2.244C58.387 -3.809 60.39 -4.712 62.826 -5.294C62.95 -5.323 63.224 -4.856 63.593 -5.017C65.206 -5.72 67.216 -5.662 68.4 -7C72.167 -6.776 75.732 -7.892 79.123 -9.2C80.284 -9.648 81.554 -10.207 82.755 -10.709C84.131 -11.285 85.335 -12.213 86.447 -13.354C86.58 -13.49 86.934 -13.4 87.201 -13.4C87.161 -14.263 88.123 -14.39 88.37 -15.012C88.462 -15.244 88.312 -15.64 88.445 -15.742C90.5 [...]
+					f = "#000000";
+					g.createPath("M2.2 -58C2.2 -58 -7.038 -60.872 -18.2 -35.2C-18.2 -35.2 -20.6 -30 -23 -28C-25.4 -26 -36.6 -22.4 -38.6 -18.4L-49 -2.4C-49 -2.4 -34.2 -18.4 -31 -20.8C-31 -20.8 -23 -29.2 -26.2 -22.4C-26.2 -22.4 -40.2 -11.6 -39 -2.4C-39 -2.4 -44.6 12 -45.4 14C-45.4 14 -29.4 -18 -27 -19.2C-24.6 -20.4 -23.4 -20.4 -24.6 -16.8C-25.8 -13.2 -26.2 3.2 -29 5.2C-29 5.2 -21 -15.2 -21.8 -18.4C-21.8 -18.4 -18.6 -22 -16.2 -16.8L-17.4 -0.8L-13 11.2C-13 11.2 -15.4 0 -13.8 -15.6C-13.8 -15.6 -15.8 -26 -11 [...]
+					f = "#000000";
+					g.createPath("M-17.8 -41.6C-17.8 -41.6 -30.6 -41.6 -33.8 -36.4L-41 -26.8C-41 -26.8 -23.8 -36.8 -19.8 -38C-15.8 -39.2 -17.8 -41.6 -17.8 -41.6z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-57.8 -35.2C-57.8 -35.2 -59.8 -34 -60.2 -31.2C-60.6 -28.4 -63 -28 -62.2 -25.2C-61.4 -22.4 -59.4 -20 -59.4 -24C-59.4 -28 -57.8 -30 -57 -31.2C-56.2 -32.4 -54.6 -36.8 -57.8 -35.2z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-66.6 26C-66.6 26 -75 22 -78.2 18.4C-81.4 14.8 -80.948 19.966 -85.8 19.6C-91.647 19.159 -90.6 3.2 -90.6 3.2L-94.6 10.8C-94.6 10.8 -95.8 25.2 -87.8 22.8C-83.893 21.628 -82.6 23.2 -84.2 24C-85.8 24.8 -78.6 25.2 -81.4 26.8C-84.2 28.4 -69.8 23.2 -72.2 33.6L-66.6 26z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-79.2 40.4C-79.2 40.4 -94.6 44.8 -98.2 35.2C-98.2 35.2 -103 37.6 -100.8 40.6C-98.6 43.6 -97.4 44 -97.4 44C-97.4 44 -92 45.2 -92.6 46C-93.2 46.8 -95.6 50.2 -95.6 50.2C-95.6 50.2 -85.4 44.2 -79.2 40.4z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M149.201 118.601C148.774 120.735 147.103 121.536 145.201 122.201C143.284 121.243 140.686 118.137 138.801 120.201C138.327 119.721 137.548 119.661 137.204 118.999C136.739 118.101 137.011 117.055 136.669 116.257C136.124 114.985 135.415 113.619 135.601 112.201C137.407 111.489 138.002 109.583 137.528 107.82C137.459 107.563 137.03 107.366 137.23 107.017C137.416 106.694 137.734 106.467 138.001 106.2C137.866 106.335 137.721 106.568 137.61 106.548C137 106.442 137.124 105.805 13 [...]
+					f = "#ffffff";
+					g.createPath("M139.6 138.201C139.593 136.463 137.992 134.707 139.201 133.001C139.336 133.135 139.467 133.356 139.601 133.356C139.736 133.356 139.867 133.135 140.001 133.001C141.496 135.217 145.148 136.145 145.006 138.991C144.984 139.438 143.897 140.356 144.801 141.001C142.988 142.349 142.933 144.719 142.001 146.601C140.763 146.315 139.551 145.952 138.401 145.401C138.753 143.915 138.636 142.231 139.456 140.911C139.89 140.213 139.603 139.134 139.6 138.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-26.6 129.201C-26.6 129.201 -43.458 139.337 -29.4 124.001C-20.6 114.401 -10.6 108.801 -10.6 108.801C-10.6 108.801 -0.2 104.4 3.4 103.2C7 102 22.2 96.8 25.4 96.4C28.6 96 38.2 92 45 96C51.8 100 59.8 104.4 59.8 104.4C59.8 104.4 43.4 96 39.8 98.4C36.2 100.8 29 100.4 23 103.6C23 103.6 8.2 108.001 5 110.001C1.8 112.001 -8.6 123.601 -10.2 122.801C-11.8 122.001 -9.8 121.601 -8.6 118.801C-7.4 116.001 -9.4 114.401 -17.4 120.801C-25.4 127.201 -26.6 129.201 -26.6 129.201z").setFi [...]
+					f = "#000000";
+					g.createPath("M-19.195 123.234C-19.195 123.234 -17.785 110.194 -9.307 111.859C-9.307 111.859 -1.081 107.689 1.641 105.721C1.641 105.721 9.78 104.019 11.09 103.402C29.569 94.702 44.288 99.221 44.835 98.101C45.381 96.982 65.006 104.099 68.615 108.185C69.006 108.628 58.384 102.588 48.686 100.697C40.413 99.083 18.811 100.944 7.905 106.48C4.932 107.989 -4.013 113.773 -6.544 113.662C-9.075 113.55 -19.195 123.234 -19.195 123.234z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-23 148.801C-23 148.801 -38.2 146.401 -21.4 144.801C-21.4 144.801 -3.4 142.801 0.6 137.601C0.6 137.601 14.2 128.401 17 128.001C19.8 127.601 49.8 120.401 50.2 118.001C50.6 115.601 56.2 115.601 57.8 116.401C59.4 117.201 58.6 118.401 55.8 119.201C53 120.001 21.8 136.401 15.4 137.601C9 138.801 -2.6 146.401 -7.4 147.601C-12.2 148.801 -23 148.801 -23 148.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-3.48 141.403C-3.48 141.403 -12.062 140.574 -3.461 139.755C-3.461 139.755 5.355 136.331 7.403 133.668C7.403 133.668 14.367 128.957 15.8 128.753C17.234 128.548 31.194 124.861 31.399 123.633C31.604 122.404 65.67 109.823 70.09 113.013C73.001 115.114 63.1 113.437 53.466 117.847C52.111 118.467 18.258 133.054 14.981 133.668C11.704 134.283 5.765 138.174 3.307 138.788C0.85 139.403 -3.48 141.403 -3.48 141.403z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-11.4 143.601C-11.4 143.601 -6.2 143.201 -7.4 144.801C-8.6 146.401 -11 145.601 -11 145.601L-11.4 143.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-18.6 145.201C-18.6 145.201 -13.4 144.801 -14.6 146.401C-15.8 148.001 -18.2 147.201 -18.2 147.201L-18.6 145.201z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-29 146.801C-29 146.801 -23.8 146.401 -25 148.001C-26.2 149.601 -28.6 148.801 -28.6 148.801L-29 146.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-36.6 147.601C-36.6 147.601 -31.4 147.201 -32.6 148.801C-33.8 150.401 -36.2 149.601 -36.2 149.601L-36.6 147.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M1.8 108.001C1.8 108.001 6.2 108.001 5 109.601C3.8 111.201 0.6 110.801 0.6 110.801L1.8 108.001z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-8.2 113.601C-8.2 113.601 -1.694 111.46 -4.2 114.801C-5.4 116.401 -7.8 115.601 -7.8 115.601L-8.2 113.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-19.4 118.401C-19.4 118.401 -14.2 118.001 -15.4 119.601C-16.6 121.201 -19 120.401 -19 120.401L-19.4 118.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-27 124.401C-27 124.401 -21.8 124.001 -23 125.601C-24.2 127.201 -26.6 126.401 -26.6 126.401L-27 124.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-33.8 129.201C-33.8 129.201 -28.6 128.801 -29.8 130.401C-31 132.001 -33.4 131.201 -33.4 131.201L-33.8 129.201z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M5.282 135.598C5.282 135.598 12.203 135.066 10.606 137.195C9.009 139.325 5.814 138.26 5.814 138.26L5.282 135.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M15.682 130.798C15.682 130.798 22.603 130.266 21.006 132.395C19.409 134.525 16.214 133.46 16.214 133.46L15.682 130.798z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M26.482 126.398C26.482 126.398 33.403 125.866 31.806 127.995C30.209 130.125 27.014 129.06 27.014 129.06L26.482 126.398z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M36.882 121.598C36.882 121.598 43.803 121.066 42.206 123.195C40.609 125.325 37.414 124.26 37.414 124.26L36.882 121.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M9.282 103.598C9.282 103.598 16.203 103.066 14.606 105.195C13.009 107.325 9.014 107.06 9.014 107.06L9.282 103.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M19.282 100.398C19.282 100.398 26.203 99.866 24.606 101.995C23.009 104.125 18.614 103.86 18.614 103.86L19.282 100.398z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-3.4 140.401C-3.4 140.401 1.8 140.001 0.6 141.601C-0.6 143.201 -3 142.401 -3 142.401L-3.4 140.401z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-76.6 41.2C-76.6 41.2 -81 50 -81.4 53.2C-81.4 53.2 -80.6 44.4 -79.4 42.4C-78.2 40.4 -76.6 41.2 -76.6 41.2z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-95 55.2C-95 55.2 -98.2 69.6 -97.8 72.4C-97.8 72.4 -99 60.8 -98.6 59.6C-98.2 58.4 -95 55.2 -95 55.2z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-74.2 -19.4L-74.4 -16.2L-76.6 -16C-76.6 -16 -62.4 -3.4 -61.8 4.2C-61.8 4.2 -61 -4 -74.2 -19.4z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-70.216 -18.135C-70.647 -18.551 -70.428 -19.296 -70.836 -19.556C-71.645 -20.072 -69.538 -20.129 -69.766 -20.845C-70.149 -22.051 -69.962 -22.072 -70.084 -23.348C-70.141 -23.946 -69.553 -25.486 -69.168 -25.926C-67.722 -27.578 -69.046 -30.51 -67.406 -32.061C-67.102 -32.35 -66.726 -32.902 -66.441 -33.32C-65.782 -34.283 -64.598 -34.771 -63.648 -35.599C-63.33 -35.875 -63.531 -36.702 -62.962 -36.61C-62.248 -36.495 -61.007 -36.625 -61.052 -35.784C-61.165 -33.664 -62.494 -31.9 [...]
+					f = "#000000";
+					g.createPath("M-73.8 -16.4C-73.8 -16.4 -73.4 -9.6 -71 -8C-68.6 -6.4 -69.8 -7.2 -73 -8.4C-76.2 -9.6 -75 -10.4 -75 -10.4C-75 -10.4 -77.8 -10 -75.4 -8C-73 -6 -69.4 -3.6 -71 -3.6C-72.6 -3.6 -80.2 -7.6 -80.2 -10.4C-80.2 -13.2 -81.2 -17.3 -81.2 -17.3C-81.2 -17.3 -80.1 -18.1 -75.3 -18C-75.3 -18 -73.9 -17.3 -73.8 -16.4z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-74.6 2.2C-74.6 2.2 -83.12 -0.591 -101.6 2.8C-101.6 2.8 -92.569 0.722 -73.8 3C-63.5 4.25 -74.6 2.2 -74.6 2.2z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-72.502 2.129C-72.502 2.129 -80.748 -1.389 -99.453 0.392C-99.453 0.392 -90.275 -0.897 -71.774 2.995C-61.62 5.131 -72.502 2.129 -72.502 2.129z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-70.714 2.222C-70.714 2.222 -78.676 -1.899 -97.461 -1.514C-97.461 -1.514 -88.213 -2.118 -70.052 3.14C-60.086 6.025 -70.714 2.222 -70.714 2.222z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-69.444 2.445C-69.444 2.445 -76.268 -1.862 -93.142 -2.96C-93.142 -2.96 -84.803 -2.79 -68.922 3.319C-60.206 6.672 -69.444 2.445 -69.444 2.445z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M45.84 12.961C45.84 12.961 44.91 13.605 45.124 12.424C45.339 11.243 73.547 -1.927 77.161 -1.677C77.161 -1.677 46.913 11.529 45.84 12.961z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M42.446 13.6C42.446 13.6 41.57 14.315 41.691 13.121C41.812 11.927 68.899 -3.418 72.521 -3.452C72.521 -3.452 43.404 12.089 42.446 13.6z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M39.16 14.975C39.16 14.975 38.332 15.747 38.374 14.547C38.416 13.348 58.233 -2.149 68.045 -4.023C68.045 -4.023 50.015 4.104 39.16 14.975z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M36.284 16.838C36.284 16.838 35.539 17.532 35.577 16.453C35.615 15.373 53.449 1.426 62.28 -0.26C62.28 -0.26 46.054 7.054 36.284 16.838z").setFill(f).setStroke(s);
+					f = "#cccccc"; s = null;
+					g.createPath("M4.6 164.801C4.6 164.801 -10.6 162.401 6.2 160.801C6.2 160.801 24.2 158.801 28.2 153.601C28.2 153.601 41.8 144.401 44.6 144.001C47.4 143.601 63.8 140.001 64.2 137.601C64.6 135.201 70.6 132.801 72.2 133.601C73.8 134.401 73.8 143.601 71 144.401C68.2 145.201 49.4 152.401 43 153.601C36.6 154.801 25 162.401 20.2 163.601C15.4 164.801 4.6 164.801 4.6 164.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M77.6 127.401C77.6 127.401 74.6 129.001 73.4 131.601C73.4 131.601 67 142.201 52.8 145.401C52.8 145.401 29.8 154.401 22 156.401C22 156.401 8.6 161.401 1.2 160.601C1.2 160.601 -5.8 160.801 0.4 162.401C0.4 162.401 20.6 160.401 24 158.601C24 158.601 39.6 153.401 42.6 150.801C45.6 148.201 63.8 143.201 66 141.201C68.2 139.201 78 130.801 77.6 127.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M18.882 158.911C18.882 158.911 24.111 158.685 22.958 160.234C21.805 161.784 19.357 160.91 19.357 160.91L18.882 158.911z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M11.68 160.263C11.68 160.263 16.908 160.037 15.756 161.586C14.603 163.136 12.155 162.263 12.155 162.263L11.68 160.263z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M1.251 161.511C1.251 161.511 6.48 161.284 5.327 162.834C4.174 164.383 1.726 163.51 1.726 163.51L1.251 161.511z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-6.383 162.055C-6.383 162.055 -1.154 161.829 -2.307 163.378C-3.46 164.928 -5.908 164.054 -5.908 164.054L-6.383 162.055z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M35.415 151.513C35.415 151.513 42.375 151.212 40.84 153.274C39.306 155.336 36.047 154.174 36.047 154.174L35.415 151.513z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M45.73 147.088C45.73 147.088 51.689 143.787 51.155 148.849C50.885 151.405 46.362 149.749 46.362 149.749L45.73 147.088z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M54.862 144.274C54.862 144.274 62.021 140.573 60.287 146.035C59.509 148.485 55.493 146.935 55.493 146.935L54.862 144.274z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M64.376 139.449C64.376 139.449 68.735 134.548 69.801 141.21C70.207 143.748 65.008 142.11 65.008 142.11L64.376 139.449z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M26.834 155.997C26.834 155.997 32.062 155.77 30.91 157.32C29.757 158.869 27.308 157.996 27.308 157.996L26.834 155.997z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M62.434 34.603C62.434 34.603 61.708 35.268 61.707 34.197C61.707 33.127 79.191 19.863 88.034 18.479C88.034 18.479 71.935 25.208 62.434 34.603z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M65.4 98.4C65.4 98.4 87.401 120.801 96.601 124.401C96.601 124.401 105.801 135.601 101.801 161.601C101.801 161.601 98.601 169.201 95.401 148.401C95.401 148.401 98.601 123.201 87.401 139.201C87.401 139.201 79 129.301 85.4 129.601C85.4 129.601 88.601 131.601 89.001 130.001C89.401 128.401 81.4 114.801 64.2 100.4C47 86 65.4 98.4 65.4 98.4z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M7 137.201C7 137.201 6.8 135.401 8.6 136.201C10.4 137.001 104.601 143.201 136.201 167.201C136.201 167.201 91.001 144.001 7 137.201z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M17.4 132.801C17.4 132.801 17.2 131.001 19 131.801C20.8 132.601 157.401 131.601 181.001 164.001C181.001 164.001 159.001 138.801 17.4 132.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M29 128.801C29 128.801 28.8 127.001 30.6 127.801C32.4 128.601 205.801 115.601 229.401 148.001C229.401 148.001 219.801 122.401 29 128.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M39 124.001C39 124.001 38.8 122.201 40.6 123.001C42.4 123.801 164.601 85.2 188.201 117.601C188.201 117.601 174.801 93 39 124.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-19 146.801C-19 146.801 -19.2 145.001 -17.4 145.801C-15.6 146.601 2.2 148.801 4.2 187.601C4.2 187.601 -3 145.601 -19 146.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-27.8 148.401C-27.8 148.401 -28 146.601 -26.2 147.401C-24.4 148.201 -10.2 143.601 -13 182.401C-13 182.401 -11.8 147.201 -27.8 148.401z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-35.8 148.801C-35.8 148.801 -36 147.001 -34.2 147.801C-32.4 148.601 -17 149.201 -29.4 171.601C-29.4 171.601 -19.8 147.601 -35.8 148.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M11.526 104.465C11.526 104.465 11.082 106.464 12.631 105.247C28.699 92.622 61.141 33.72 116.826 28.086C116.826 28.086 78.518 15.976 11.526 104.465z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M22.726 102.665C22.726 102.665 21.363 101.472 23.231 100.847C25.099 100.222 137.541 27.72 176.826 35.686C176.826 35.686 149.719 28.176 22.726 102.665z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M1.885 108.767C1.885 108.767 1.376 110.366 3.087 109.39C12.062 104.27 15.677 47.059 59.254 45.804C59.254 45.804 26.843 31.09 1.885 108.767z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-18.038 119.793C-18.038 119.793 -19.115 121.079 -17.162 120.825C-6.916 119.493 14.489 78.222 58.928 83.301C58.928 83.301 26.962 68.955 -18.038 119.793z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-6.8 113.667C-6.8 113.667 -7.611 115.136 -5.742 114.511C4.057 111.237 17.141 66.625 61.729 63.078C61.729 63.078 27.603 55.135 -6.8 113.667z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-25.078 124.912C-25.078 124.912 -25.951 125.954 -24.369 125.748C-16.07 124.669 1.268 91.24 37.264 95.354C37.264 95.354 11.371 83.734 -25.078 124.912z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-32.677 130.821C-32.677 130.821 -33.682 131.866 -32.091 131.748C-27.923 131.439 2.715 98.36 21.183 113.862C21.183 113.862 9.168 95.139 -32.677 130.821z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M36.855 98.898C36.855 98.898 35.654 97.543 37.586 97.158C39.518 96.774 160.221 39.061 198.184 51.927C198.184 51.927 172.243 41.053 36.855 98.898z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M3.4 163.201C3.4 163.201 3.2 161.401 5 162.201C6.8 163.001 22.2 163.601 9.8 186.001C9.8 186.001 19.4 162.001 3.4 163.201z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M13.8 161.601C13.8 161.601 13.6 159.801 15.4 160.601C17.2 161.401 35 163.601 37 202.401C37 202.401 29.8 160.401 13.8 161.601z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M20.6 160.001C20.6 160.001 20.4 158.201 22.2 159.001C24 159.801 48.6 163.201 72.2 195.601C72.2 195.601 36.6 158.801 20.6 160.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M28.225 157.972C28.225 157.972 27.788 156.214 29.678 156.768C31.568 157.322 52.002 155.423 90.099 189.599C90.099 189.599 43.924 154.656 28.225 157.972z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M38.625 153.572C38.625 153.572 38.188 151.814 40.078 152.368C41.968 152.922 76.802 157.423 128.499 192.399C128.499 192.399 54.324 150.256 38.625 153.572z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-1.8 142.001C-1.8 142.001 -2 140.201 -0.2 141.001C1.6 141.801 55 144.401 85.4 171.201C85.4 171.201 50.499 146.426 -1.8 142.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-11.8 146.001C-11.8 146.001 -12 144.201 -10.2 145.001C-8.4 145.801 16.2 149.201 39.8 181.601C39.8 181.601 4.2 144.801 -11.8 146.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M49.503 148.962C49.503 148.962 48.938 147.241 50.864 147.655C52.79 148.068 87.86 150.004 141.981 181.098C141.981 181.098 64.317 146.704 49.503 148.962z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M57.903 146.562C57.903 146.562 57.338 144.841 59.264 145.255C61.19 145.668 96.26 147.604 150.381 178.698C150.381 178.698 73.317 143.904 57.903 146.562z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M67.503 141.562C67.503 141.562 66.938 139.841 68.864 140.255C70.79 140.668 113.86 145.004 203.582 179.298C203.582 179.298 82.917 138.904 67.503 141.562z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M-43.8 148.401C-43.8 148.401 -38.6 148.001 -39.8 149.601C-41 151.201 -43.4 150.401 -43.4 150.401L-43.8 148.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-13 162.401C-13 162.401 -7.8 162.001 -9 163.601C-10.2 165.201 -12.6 164.401 -12.6 164.401L-13 162.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-21.8 162.001C-21.8 162.001 -16.6 161.601 -17.8 163.201C-19 164.801 -21.4 164.001 -21.4 164.001L-21.8 162.001z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-117.169 150.182C-117.169 150.182 -112.124 151.505 -113.782 152.624C-115.439 153.744 -117.446 152.202 -117.446 152.202L-117.169 150.182z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-115.169 140.582C-115.169 140.582 -110.124 141.905 -111.782 143.024C-113.439 144.144 -115.446 142.602 -115.446 142.602L-115.169 140.582z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-122.369 136.182C-122.369 136.182 -117.324 137.505 -118.982 138.624C-120.639 139.744 -122.646 138.202 -122.646 138.202L-122.369 136.182z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-42.6 211.201C-42.6 211.201 -44.2 211.201 -48.2 213.201C-50.2 213.201 -61.4 216.801 -67 226.801C-67 226.801 -54.6 217.201 -42.6 211.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M45.116 303.847C45.257 304.105 45.312 304.525 45.604 304.542C46.262 304.582 47.495 304.883 47.37 304.247C46.522 299.941 45.648 295.004 41.515 293.197C40.876 292.918 39.434 293.331 39.36 294.215C39.233 295.739 39.116 297.088 39.425 298.554C39.725 299.975 41.883 299.985 42.8 298.601C43.736 300.273 44.168 302.116 45.116 303.847z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M34.038 308.581C34.786 309.994 34.659 311.853 36.074 312.416C36.814 312.71 38.664 311.735 38.246 310.661C37.444 308.6 37.056 306.361 35.667 304.55C35.467 304.288 35.707 303.755 35.547 303.427C34.953 302.207 33.808 301.472 32.4 301.801C31.285 304.004 32.433 306.133 33.955 307.842C34.091 307.994 33.925 308.37 34.038 308.581z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-5.564 303.391C-5.672 303.014 -5.71 302.551 -5.545 302.23C-5.014 301.197 -4.221 300.075 -4.558 299.053C-4.906 297.997 -6.022 298.179 -6.672 298.748C-7.807 299.742 -7.856 301.568 -8.547 302.927C-8.743 303.313 -8.692 303.886 -9.133 304.277C-9.607 304.698 -10.047 306.222 -9.951 306.793C-9.898 307.106 -10.081 317.014 -9.859 316.751C-9.24 316.018 -6.19 306.284 -6.121 305.392C-6.064 304.661 -5.332 304.196 -5.564 303.391z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-31.202 296.599C-28.568 294.1 -25.778 291.139 -26.22 287.427C-26.336 286.451 -28.111 286.978 -28.298 287.824C-29.1 291.449 -31.139 294.11 -33.707 296.502C-35.903 298.549 -37.765 304.893 -38 305.401C-34.303 300.145 -32.046 297.399 -31.202 296.599z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-44.776 290.635C-44.253 290.265 -44.555 289.774 -44.338 289.442C-43.385 287.984 -42.084 286.738 -42.066 285C-42.063 284.723 -42.441 284.414 -42.776 284.638C-43.053 284.822 -43.395 284.952 -43.503 285.082C-45.533 287.531 -46.933 290.202 -48.376 293.014C-48.559 293.371 -49.703 297.862 -49.39 297.973C-49.151 298.058 -47.431 293.877 -47.221 293.763C-45.958 293.077 -45.946 291.462 -44.776 290.635z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-28.043 310.179C-27.599 309.31 -26.023 308.108 -26.136 307.219C-26.254 306.291 -25.786 304.848 -26.698 305.536C-27.955 306.484 -31.404 307.833 -31.674 313.641C-31.7 314.212 -28.726 311.519 -28.043 310.179z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-13.6 293.001C-13.2 292.333 -12.492 292.806 -12.033 292.543C-11.385 292.171 -10.774 291.613 -10.482 290.964C-9.512 288.815 -7.743 286.995 -7.6 284.601C-9.091 283.196 -9.77 285.236 -10.4 286.201C-11.723 284.554 -12.722 286.428 -14.022 286.947C-14.092 286.975 -14.305 286.628 -14.38 286.655C-15.557 287.095 -16.237 288.176 -17.235 288.957C-17.406 289.091 -17.811 288.911 -17.958 289.047C-18.61 289.65 -19.583 289.975 -19.863 290.657C-20.973 293.364 -24.113 295.459 -26 303.0 [...]
+					f = "#cccccc";
+					g.createPath("M46.2 347.401C46.2 347.401 53.6 327.001 49.2 315.801C49.2 315.801 60.6 337.401 56 348.601C56 348.601 55.6 338.201 51.6 333.201C51.6 333.201 47.6 346.001 46.2 347.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M31.4 344.801C31.4 344.801 36.8 336.001 28.8 317.601C28.8 317.601 28 338.001 21.2 349.001C21.2 349.001 35.4 328.801 31.4 344.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M21.4 342.801C21.4 342.801 21.2 322.801 21.6 319.801C21.6 319.801 17.8 336.401 7.6 346.001C7.6 346.001 22 334.001 21.4 342.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M11.8 310.801C11.8 310.801 17.8 324.401 7.8 342.801C7.8 342.801 14.2 330.601 9.4 323.601C9.4 323.601 12 320.201 11.8 310.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-7.4 342.401C-7.4 342.401 -8.4 326.801 -6.6 324.601C-6.6 324.601 -6.4 318.201 -6.8 317.201C-6.8 317.201 -2.8 311.001 -2.6 318.401C-2.6 318.401 -1.2 326.201 1.6 330.801C1.6 330.801 5.2 336.201 5 342.601C5 342.601 -5 312.401 -7.4 342.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-11 314.801C-11 314.801 -17.6 325.601 -19.4 344.601C-19.4 344.601 -20.8 338.401 -17 324.001C-17 324.001 -12.8 308.601 -11 314.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-32.8 334.601C-32.8 334.601 -27.8 329.201 -26.4 324.201C-26.4 324.201 -22.8 308.401 -29.2 317.001C-29.2 317.001 -29 325.001 -37.2 332.401C-37.2 332.401 -32.4 330.001 -32.8 334.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-38.6 329.601C-38.6 329.601 -35.2 312.201 -34.4 311.401C-34.4 311.401 -32.6 308.001 -35.4 311.201C-35.4 311.201 -44.2 330.401 -48.2 337.001C-48.2 337.001 -40.2 327.801 -38.6 329.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-44.4 313.001C-44.4 313.001 -32.8 290.601 -54.6 316.401C-54.6 316.401 -43.6 306.601 -44.4 313.001z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-59.8 298.401C-59.8 298.401 -55 279.601 -52.4 279.801C-52.4 279.801 -44.2 270.801 -50.8 281.401C-50.8 281.401 -56.8 291.001 -56.2 300.801C-56.2 300.801 -56.8 291.201 -59.8 298.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M270.5 287C270.5 287 258.5 277 256 273.5C256 273.5 269.5 292 269.5 299C269.5 299 272 291.5 270.5 287z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M276 265C276 265 255 250 251.5 242.5C251.5 242.5 278 272 278 276.5C278 276.5 278.5 267.5 276 265z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M293 111C293 111 281 103 279.5 105C279.5 105 290 111.5 292.5 120C292.5 120 291 111 293 111z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M301.5 191.5L284 179.5C284 179.5 303 196.5 303.5 200.5L301.5 191.5z").setFill(f).setStroke(s);
+					s = "#000000"; f = null;
+					g.createPath("M-89.25 169L-67.25 173.75").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M-39 331C-39 331 -39.5 327.5 -48.5 338").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M-33.5 336C-33.5 336 -31.5 329.5 -38 334").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M20.5 344.5C20.5 344.5 22 333.5 10.5 346.5").setFill(f).setStroke(s);
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+	                rotateTiger();
+                }
+            },
+			{
+				name: "Scale Tiger",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 20,
+                setUp: function() {
+                    createSurface();
+					var f, g;
+                    surface.clear();
+					var initial_matrix = dojox.gfx.matrix.translate(250, 250);
+                    matrix = initial_matrix;
+					surface.createRect({x: 0, y: 0, width: 700, height: 700}).setFill("#eee");
+					g = surface.createGroup().setTransform(initial_matrix);
+                    gfxGroup = g;
+					var s = {color: "black", width: 1};
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-118.774 81.262C-118.774 81.262 -119.323 83.078 -120.092 82.779C-120.86 82.481 -119.977 31.675 -140.043 26.801C-140.043 26.801 -120.82 25.937 -118.774 81.262z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-91.284 123.59C-91.284 123.59 -89.648 124.55 -90.118 125.227C-90.589 125.904 -139.763 113.102 -149.218 131.459C-149.218 131.459 -145.539 112.572 -91.284 123.59z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-94.093 133.801C-94.093 133.801 -92.237 134.197 -92.471 134.988C-92.704 135.779 -143.407 139.121 -146.597 159.522C-146.597 159.522 -149.055 140.437 -94.093 133.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-98.304 128.276C-98.304 128.276 -96.526 128.939 -96.872 129.687C-97.218 130.435 -147.866 126.346 -153.998 146.064C-153.998 146.064 -153.646 126.825 -98.304 128.276z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-109.009 110.072C-109.009 110.072 -107.701 111.446 -108.34 111.967C-108.979 112.488 -152.722 86.634 -166.869 101.676C-166.869 101.676 -158.128 84.533 -109.009 110.072z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-116.554 114.263C-116.554 114.263 -115.098 115.48 -115.674 116.071C-116.25 116.661 -162.638 95.922 -174.992 112.469C-174.992 112.469 -168.247 94.447 -116.554 114.263z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-119.154 118.335C-119.154 118.335 -117.546 119.343 -118.036 120.006C-118.526 120.669 -167.308 106.446 -177.291 124.522C-177.291 124.522 -173.066 105.749 -119.154 118.335z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-108.42 118.949C-108.42 118.949 -107.298 120.48 -107.999 120.915C-108.7 121.35 -148.769 90.102 -164.727 103.207C-164.727 103.207 -153.862 87.326 -108.42 118.949z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-128.2 90C-128.2 90 -127.6 91.8 -128.4 92C-129.2 92.2 -157.8 50.2 -177.001 57.8C-177.001 57.8 -161.8 46 -128.2 90z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-127.505 96.979C-127.505 96.979 -126.53 98.608 -127.269 98.975C-128.007 99.343 -164.992 64.499 -182.101 76.061C-182.101 76.061 -169.804 61.261 -127.505 96.979z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-127.62 101.349C-127.62 101.349 -126.498 102.88 -127.199 103.315C-127.9 103.749 -167.969 72.502 -183.927 85.607C-183.927 85.607 -173.062 69.726 -127.62 101.349z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = "#000000";
+					g.createPath("M-129.83 103.065C-129.327 109.113 -128.339 115.682 -126.6 118.801C-126.6 118.801 -130.2 131.201 -121.4 144.401C-121.4 144.401 -121.8 151.601 -120.2 154.801C-120.2 154.801 -116.2 163.201 -111.4 164.001C-107.516 164.648 -98.793 167.717 -88.932 169.121C-88.932 169.121 -71.8 183.201 -75 196.001C-75 196.001 -75.4 212.401 -79 214.001C-79 214.001 -67.4 202.801 -77 219.601L-81.4 238.401C-81.4 238.401 -55.8 216.801 -71.4 235.201L-81.4 261.201C-81.4 261.201 -61.8 242.801 -69 251 [...]
+					f = "#cc7226"; s = "#000000";
+					g.createPath("M299.717 80.245C300.345 80.426 302.551 81.55 303.801 83.2C303.801 83.2 310.601 94 305.401 75.6C305.401 75.6 296.201 46.8 305.001 58C305.001 58 311.001 65.2 307.801 51.6C303.936 35.173 301.401 28.8 301.401 28.8C301.401 28.8 313.001 33.6 286.201 -6L295.001 -2.4C295.001 -2.4 275.401 -42 253.801 -47.2L245.801 -53.2C245.801 -53.2 284.201 -91.2 271.401 -128C271.401 -128 264.601 -133.2 255.001 -124C255.001 -124 248.601 -119.2 242.601 -120.8C242.601 -120.8 211.801 -119.6 209.8 [...]
+					f = "#cc7226"; s = null;
+					g.createPath("M-115.6 102.6C-140.6 63.2 -126.2 119.601 -126.2 119.601C-117.4 154.001 12.2 116.401 12.2 116.401C12.2 116.401 181.001 86 192.201 82C203.401 78 298.601 84.4 298.601 84.4L293.001 67.6C228.201 21.2 209.001 44.4 195.401 40.4C181.801 36.4 184.201 46 181.001 46.8C177.801 47.6 138.601 22.8 132.201 23.6C125.801 24.4 100.459 0.649 115.401 32.4C131.401 66.4 57 71.6 40.2 60.4C23.4 49.2 47.4 78.8 47.4 78.8C65.8 98.8 31.4 82 31.4 82C-3 69.2 -27 94.8 -30.2 95.6C-33.4 96.4 -38.2 99.6 [...]
+					f = "#e87f3a";
+					g.createPath("M133.51 25.346C127.11 26.146 101.743 2.407 116.71 34.146C133.31 69.346 58.31 73.346 41.51 62.146C24.709 50.946 48.71 80.546 48.71 80.546C67.11 100.546 32.709 83.746 32.709 83.746C-1.691 70.946 -25.691 96.546 -28.891 97.346C-32.091 98.146 -36.891 101.346 -37.691 94.946C-38.491 88.546 -45.87 72.012 -77.691 98.146C-98.927 115.492 -112.418 94.037 -112.418 94.037L-115.618 104.146C-140.618 64.346 -125.546 122.655 -125.546 122.655C-116.745 157.056 13.509 118.146 13.509 118.14 [...]
+					f = "#ea8c4d";
+					g.createPath("M134.819 27.091C128.419 27.891 103.685 3.862 118.019 35.891C134.219 72.092 59.619 75.092 42.819 63.892C26.019 52.692 50.019 82.292 50.019 82.292C68.419 102.292 34.019 85.492 34.019 85.492C-0.381 72.692 -24.382 98.292 -27.582 99.092C-30.782 99.892 -35.582 103.092 -36.382 96.692C-37.182 90.292 -44.43 73.925 -76.382 99.892C-98.855 117.983 -112.036 97.074 -112.036 97.074L-115.636 105.692C-139.436 66.692 -124.891 125.71 -124.891 125.71C-116.091 160.11 14.819 119.892 14.819  [...]
+					f = "#ec9961";
+					g.createPath("M136.128 28.837C129.728 29.637 104.999 5.605 119.328 37.637C136.128 75.193 60.394 76.482 44.128 65.637C27.328 54.437 51.328 84.037 51.328 84.037C69.728 104.037 35.328 87.237 35.328 87.237C0.928 74.437 -23.072 100.037 -26.272 100.837C-29.472 101.637 -34.272 104.837 -35.072 98.437C-35.872 92.037 -42.989 75.839 -75.073 101.637C-98.782 120.474 -111.655 100.11 -111.655 100.11L-115.655 107.237C-137.455 70.437 -124.236 128.765 -124.236 128.765C-115.436 163.165 16.128 121.637  [...]
+					f = "#eea575";
+					g.createPath("M137.438 30.583C131.037 31.383 106.814 7.129 120.637 39.383C137.438 78.583 62.237 78.583 45.437 67.383C28.637 56.183 52.637 85.783 52.637 85.783C71.037 105.783 36.637 88.983 36.637 88.983C2.237 76.183 -21.763 101.783 -24.963 102.583C-28.163 103.383 -32.963 106.583 -33.763 100.183C-34.563 93.783 -41.548 77.752 -73.763 103.383C-98.709 122.965 -111.273 103.146 -111.273 103.146L-115.673 108.783C-135.473 73.982 -123.582 131.819 -123.582 131.819C-114.782 166.22 17.437 123.38 [...]
+					f = "#f1b288";
+					g.createPath("M138.747 32.328C132.347 33.128 106.383 9.677 121.947 41.128C141.147 79.928 63.546 80.328 46.746 69.128C29.946 57.928 53.946 87.528 53.946 87.528C72.346 107.528 37.946 90.728 37.946 90.728C3.546 77.928 -20.454 103.528 -23.654 104.328C-26.854 105.128 -31.654 108.328 -32.454 101.928C-33.254 95.528 -40.108 79.665 -72.454 105.128C-98.636 125.456 -110.891 106.183 -110.891 106.183L-115.691 110.328C-133.691 77.128 -122.927 134.874 -122.927 134.874C-114.127 169.274 18.746 125.1 [...]
+					f = "#f3bf9c";
+					g.createPath("M140.056 34.073C133.655 34.873 107.313 11.613 123.255 42.873C143.656 82.874 64.855 82.074 48.055 70.874C31.255 59.674 55.255 89.274 55.255 89.274C73.655 109.274 39.255 92.474 39.255 92.474C4.855 79.674 -19.145 105.274 -22.345 106.074C-25.545 106.874 -30.345 110.074 -31.145 103.674C-31.945 97.274 -38.668 81.578 -71.145 106.874C-98.564 127.947 -110.509 109.219 -110.509 109.219L-115.709 111.874C-131.709 81.674 -122.273 137.929 -122.273 137.929C-113.473 172.329 20.055 126. [...]
+					f = "#f5ccb0";
+					g.createPath("M141.365 35.819C134.965 36.619 107.523 13.944 124.565 44.619C146.565 84.219 66.164 83.819 49.364 72.619C32.564 61.419 56.564 91.019 56.564 91.019C74.964 111.019 40.564 94.219 40.564 94.219C6.164 81.419 -17.836 107.019 -21.036 107.819C-24.236 108.619 -29.036 111.819 -29.836 105.419C-30.636 99.019 -37.227 83.492 -69.836 108.619C-98.491 130.438 -110.127 112.256 -110.127 112.256L-115.727 113.419C-130.128 85.019 -121.618 140.983 -121.618 140.983C-112.818 175.384 21.364 128. [...]
+					f = "#f8d8c4";
+					g.createPath("M142.674 37.565C136.274 38.365 108.832 15.689 125.874 46.365C147.874 85.965 67.474 85.565 50.674 74.365C33.874 63.165 57.874 92.765 57.874 92.765C76.274 112.765 41.874 95.965 41.874 95.965C7.473 83.165 -16.527 108.765 -19.727 109.565C-22.927 110.365 -27.727 113.565 -28.527 107.165C-29.327 100.765 -35.786 85.405 -68.527 110.365C-98.418 132.929 -109.745 115.293 -109.745 115.293L-115.745 114.965C-129.346 88.564 -120.963 144.038 -120.963 144.038C-112.163 178.438 22.673 130 [...]
+					f = "#fae5d7";
+					g.createPath("M143.983 39.31C137.583 40.11 110.529 17.223 127.183 48.11C149.183 88.91 68.783 87.31 51.983 76.11C35.183 64.91 59.183 94.51 59.183 94.51C77.583 114.51 43.183 97.71 43.183 97.71C8.783 84.91 -15.217 110.51 -18.417 111.31C-21.618 112.11 -26.418 115.31 -27.218 108.91C-28.018 102.51 -34.346 87.318 -67.218 112.11C-98.345 135.42 -109.363 118.329 -109.363 118.329L-115.764 116.51C-128.764 92.51 -120.309 147.093 -120.309 147.093C-111.509 181.493 23.983 132.11 23.983 132.11C23.98 [...]
+					f = "#fcf2eb";
+					g.createPath("M145.292 41.055C138.892 41.855 112.917 18.411 128.492 49.855C149.692 92.656 70.092 89.056 53.292 77.856C36.492 66.656 60.492 96.256 60.492 96.256C78.892 116.256 44.492 99.456 44.492 99.456C10.092 86.656 -13.908 112.256 -17.108 113.056C-20.308 113.856 -25.108 117.056 -25.908 110.656C-26.708 104.256 -32.905 89.232 -65.908 113.856C-98.273 137.911 -108.982 121.365 -108.982 121.365L-115.782 118.056C-128.582 94.856 -119.654 150.147 -119.654 150.147C-110.854 184.547 25.292 13 [...]
+					f = "#ffffff";
+					g.createPath("M-115.8 119.601C-128.6 97.6 -119 153.201 -119 153.201C-110.2 187.601 26.6 135.601 26.6 135.601C26.6 135.601 195.401 105.2 206.601 101.2C217.801 97.2 303.401 102.8 303.401 102.8L298.601 80.4C233.801 34 223.401 63.6 209.801 59.6C196.201 55.6 198.601 65.2 195.401 66C192.201 66.8 153.001 42 146.601 42.8C140.201 43.6 114.981 19.793 129.801 51.6C152.028 99.307 69.041 89.227 54.6 79.6C37.8 68.4 61.8 98 61.8 98C80.2 118.001 45.8 101.2 45.8 101.2C11.4 88.4 -12.6 114.001 -15.8 1 [...]
+					f = "#000000";
+					g.createPath("M-74.2 149.601C-74.2 149.601 -81.4 161.201 -60.6 174.401C-60.6 174.401 -59.2 175.801 -77.2 171.601C-77.2 171.601 -83.4 169.601 -85 159.201C-85 159.201 -89.8 154.801 -94.6 149.201C-99.4 143.601 -74.2 149.601 -74.2 149.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M65.8 102C65.8 102 83.498 128.821 82.9 133.601C81.6 144.001 81.4 153.601 84.6 157.601C87.801 161.601 96.601 194.801 96.601 194.801C96.601 194.801 96.201 196.001 108.601 158.001C108.601 158.001 120.201 142.001 100.201 123.601C100.201 123.601 65 94.8 65.8 102z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-54.2 176.401C-54.2 176.401 -43 183.601 -57.4 214.801L-51 212.401C-51 212.401 -51.8 223.601 -55 226.001L-47.8 222.801C-47.8 222.801 -43 230.801 -47 235.601C-47 235.601 -30.2 243.601 -31 250.001C-31 250.001 -24.6 242.001 -28.6 235.601C-32.6 229.201 -39.8 233.201 -39 214.801L-47.8 218.001C-47.8 218.001 -42.2 209.201 -42.2 202.801L-50.2 205.201C-50.2 205.201 -34.731 178.623 -45.4 177.201C-51.4 176.401 -54.2 176.401 -54.2 176.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-21.8 193.201C-21.8 193.201 -19 188.801 -21.8 189.601C-24.6 190.401 -55.8 205.201 -61.8 214.801C-61.8 214.801 -27.4 190.401 -21.8 193.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-11.4 201.201C-11.4 201.201 -8.6 196.801 -11.4 197.601C-14.2 198.401 -45.4 213.201 -51.4 222.801C-51.4 222.801 -17 198.401 -11.4 201.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M1.8 186.001C1.8 186.001 4.6 181.601 1.8 182.401C-1 183.201 -32.2 198.001 -38.2 207.601C-38.2 207.601 -3.8 183.201 1.8 186.001z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-21.4 229.601C-21.4 229.601 -21.4 223.601 -24.2 224.401C-27 225.201 -63 242.801 -69 252.401C-69 252.401 -27 226.801 -21.4 229.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-20.2 218.801C-20.2 218.801 -19 214.001 -21.8 214.801C-23.8 214.801 -50.2 226.401 -56.2 236.001C-56.2 236.001 -26.6 214.401 -20.2 218.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-34.6 266.401L-44.6 274.001C-44.6 274.001 -34.2 266.401 -30.6 267.601C-30.6 267.601 -37.4 278.801 -38.2 284.001C-38.2 284.001 -27.8 271.201 -22.2 271.601C-22.2 271.601 -14.6 272.001 -14.6 282.801C-14.6 282.801 -9 272.401 -5.8 272.801C-5.8 272.801 -4.6 279.201 -5.8 286.001C-5.8 286.001 -1.8 278.401 2.2 280.001C2.2 280.001 8.6 278.001 7.8 289.601C7.8 289.601 7.8 300.001 7 302.801C7 302.801 12.6 276.401 15 276.001C15 276.001 23 274.801 27.8 283.601C27.8 283.601 23.8 276. [...]
+					f = "#000000";
+					g.createPath("M-29.8 173.601C-29.8 173.601 -15 167.601 25 173.601C25 173.601 32.2 174.001 39 165.201C45.8 156.401 72.6 149.201 79 151.201L88.601 157.601L89.401 158.801C89.401 158.801 101.801 169.201 102.201 176.801C102.601 184.401 87.801 232.401 78.2 248.401C68.6 264.401 59 276.801 39.8 274.401C39.8 274.401 19 270.401 -6.6 274.401C-6.6 274.401 -35.8 272.801 -38.6 264.801C-41.4 256.801 -27.4 241.601 -27.4 241.601C-27.4 241.601 -23 233.201 -24.2 218.801C-25.4 204.401 -25 176.401 -29.8 [...]
+					f = "#e5668c";
+					g.createPath("M-7.8 175.601C0.6 194.001 -29 259.201 -29 259.201C-31 260.801 -16.34 266.846 -6.2 264.401C4.746 261.763 45 266.001 45 266.001C68.6 250.401 81.4 206.001 81.4 206.001C81.4 206.001 91.801 182.001 74.2 178.801C56.6 175.601 -7.8 175.601 -7.8 175.601z").setFill(f).setStroke(s);
+					f = "#b23259";
+					g.createPath("M-9.831 206.497C-6.505 193.707 -4.921 181.906 -7.8 175.601C-7.8 175.601 54.6 182.001 65.8 161.201C70.041 153.326 84.801 184.001 84.4 193.601C84.4 193.601 21.4 208.001 6.6 196.801L-9.831 206.497z").setFill(f).setStroke(s);
+					f = "#a5264c";
+					g.createPath("M-5.4 222.801C-5.4 222.801 -3.4 230.001 -5.8 234.001C-5.8 234.001 -7.4 234.801 -8.6 235.201C-8.6 235.201 -7.4 238.801 -1.4 240.401C-1.4 240.401 0.6 244.801 3 245.201C5.4 245.601 10.2 251.201 14.2 250.001C18.2 248.801 29.4 244.801 29.4 244.801C29.4 244.801 35 241.601 43.8 245.201C43.8 245.201 46.175 244.399 46.6 240.401C47.1 235.701 50.2 232.001 52.2 230.001C54.2 228.001 63.8 215.201 62.6 214.801C61.4 214.401 -5.4 222.801 -5.4 222.801z").setFill(f).setStroke(s);
+					f = "#ff727f"; s = "#000000";
+					g.createPath("M-9.8 174.401C-9.8 174.401 -12.6 196.801 -9.4 205.201C-6.2 213.601 -7 215.601 -7.8 219.601C-8.6 223.601 -4.2 233.601 1.4 239.601L13.4 241.201C13.4 241.201 28.6 237.601 37.8 240.401C37.8 240.401 46.794 241.744 50.2 226.801C50.2 226.801 55 220.401 62.2 217.601C69.4 214.801 76.6 173.201 72.6 165.201C68.6 157.201 54.2 152.801 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-8.2 249.201C-8.2 249.201 -9 247.201 -13.4 246.801C-13.4 246.801 -35.8 243.201 -44.2 230.801C-44.2 230.801 -51 225.201 -46.6 236.801C-46.6 236.801 -36.2 257.201 -29.4 260.001C-29.4 260.001 -13 264.001 -8.2 249.201z").setFill(f).setStroke(s);
+					f = "#cc3f4c"; s = null;
+					g.createPath("M71.742 185.229C72.401 177.323 74.354 168.709 72.6 165.201C66.154 152.307 49.181 157.695 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401C-9.8 174.401 -11.545 188.364 -10.705 198.376C-10.705 198.376 26.6 186.801 27.4 192.401C27.4 192.401 29 189.201 38.2 189.201C47.4 189.201 70.142 188.029 71.742 185.229z").setFill(f).setStroke(s);
+					s = {color: "#a51926", width: 2}; f = null;
+					g.createPath("M28.6 175.201C28.6 175.201 33.4 180.001 29.8 189.601C29.8 189.601 15.4 205.601 17.4 219.601").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-19.4 260.001C-19.4 260.001 -23.8 247.201 -15 254.001C-15 254.001 -10.2 256.001 -11.4 257.601C-12.6 259.201 -18.2 263.201 -19.4 260.001z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-14.36 261.201C-14.36 261.201 -17.88 250.961 -10.84 256.401C-10.84 256.401 -6.419 258.849 -7.96 259.281C-12.52 260.561 -7.96 263.121 -14.36 261.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-9.56 261.201C-9.56 261.201 -13.08 250.961 -6.04 256.401C-6.04 256.401 -1.665 258.711 -3.16 259.281C-6.52 260.561 -3.16 263.121 -9.56 261.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-2.96 261.401C-2.96 261.401 -6.48 251.161 0.56 256.601C0.56 256.601 4.943 258.933 3.441 259.481C0.48 260.561 3.441 263.321 -2.96 261.401z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M3.52 261.321C3.52 261.321 0 251.081 7.041 256.521C7.041 256.521 10.881 258.121 9.921 259.401C8.961 260.681 9.921 263.241 3.52 261.321z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M10.2 262.001C10.2 262.001 5.4 249.601 14.6 256.001C14.6 256.001 19.4 258.001 18.2 259.601C17 261.201 18.2 264.401 10.2 262.001z").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2}; f = null;
+					g.createPath("M-18.2 244.801C-18.2 244.801 -5 242.001 1 245.201C1 245.201 7 246.401 8.2 246.001C9.4 245.601 12.6 245.201 12.6 245.201").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2};
+					g.createPath("M15.8 253.601C15.8 253.601 27.8 240.001 39.8 244.401C46.816 246.974 45.8 243.601 46.6 240.801C47.4 238.001 47.6 233.801 52.6 230.801").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M33 237.601C33 237.601 29 226.801 26.2 239.601C23.4 252.401 20.2 256.001 18.6 258.801C18.6 258.801 18.6 264.001 27 263.601C27 263.601 37.8 263.201 38.2 260.401C38.6 257.601 37 246.001 33 237.601z").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2}; f = null;
+					g.createPath("M47 244.801C47 244.801 50.6 242.401 53 243.601").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2};
+					g.createPath("M53.5 228.401C53.5 228.401 56.4 223.501 61.2 222.701").setFill(f).setStroke(s);
+					f = "#b2b2b2"; s = null;
+					g.createPath("M-25.8 265.201C-25.8 265.201 -7.8 268.401 -3.4 266.801C-3.4 266.801 5.4 266.801 -3 268.801C-3 268.801 -15.8 268.801 -23.8 267.601C-23.8 267.601 -35.4 262.001 -25.8 265.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-11.8 172.001C-11.8 172.001 5.8 172.001 7.8 172.801C7.8 172.801 15 203.601 11.4 211.201C11.4 211.201 10.2 214.001 7.4 208.401C7.4 208.401 -11 175.601 -14.2 173.601C-17.4 171.601 -13 172.001 -11.8 172.001z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-88.9 169.301C-88.9 169.301 -80 171.001 -67.4 173.601C-67.4 173.601 -62.6 196.001 -59.4 200.801C-56.2 205.601 -59.8 205.601 -63.4 202.801C-67 200.001 -81.8 186.001 -83.8 181.601C-85.8 177.201 -88.9 169.301 -88.9 169.301z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-67.039 173.818C-67.039 173.818 -61.239 175.366 -60.23 177.581C-59.222 179.795 -61.432 183.092 -61.432 183.092C-61.432 183.092 -62.432 186.397 -63.634 184.235C-64.836 182.072 -67.708 174.412 -67.039 173.818z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M-67 173.601C-67 173.601 -63.4 178.801 -59.8 178.801C-56.2 178.801 -55.818 178.388 -53 179.001C-48.4 180.001 -48.8 178.001 -42.2 179.201C-39.56 179.681 -37 178.801 -34.2 180.001C-31.4 181.201 -28.2 180.401 -27 178.401C-25.8 176.401 -21 172.201 -21 172.201C-21 172.201 -33.8 174.001 -36.6 174.801C-36.6 174.801 -59 176.001 -67 173.601z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-22.4 173.801C-22.4 173.801 -28.85 177.301 -29.25 179.701C-29.65 182.101 -24 185.801 -24 185.801C-24 185.801 -21.25 190.401 -20.65 188.001C-20.05 185.601 -21.6 174.201 -22.4 173.801z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-59.885 179.265C-59.885 179.265 -52.878 190.453 -52.661 179.242C-52.661 179.242 -52.104 177.984 -53.864 177.962C-59.939 177.886 -58.418 173.784 -59.885 179.265z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-52.707 179.514C-52.707 179.514 -44.786 190.701 -45.422 179.421C-45.422 179.421 -45.415 179.089 -47.168 178.936C-51.915 178.522 -51.57 174.004 -52.707 179.514z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-45.494 179.522C-45.494 179.522 -37.534 190.15 -38.203 180.484C-38.203 180.484 -38.084 179.251 -39.738 178.95C-43.63 178.244 -43.841 174.995 -45.494 179.522z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-38.618 179.602C-38.618 179.602 -30.718 191.163 -30.37 181.382C-30.37 181.382 -28.726 180.004 -30.472 179.782C-36.29 179.042 -35.492 174.588 -38.618 179.602z").setFill(f).setStroke(s);
+					f = "#e5e5b2"; s = null;
+					g.createPath("M-74.792 183.132L-82.45 181.601C-85.05 176.601 -87.15 170.451 -87.15 170.451C-87.15 170.451 -80.8 171.451 -68.3 174.251C-68.3 174.251 -67.424 177.569 -65.952 183.364L-74.792 183.132z").setFill(f).setStroke(s);
+					f = "#e5e5b2";
+					g.createPath("M-9.724 178.47C-11.39 175.964 -12.707 174.206 -13.357 173.8C-16.37 171.917 -12.227 172.294 -11.098 172.294C-11.098 172.294 5.473 172.294 7.356 173.047C7.356 173.047 7.88 175.289 8.564 178.68C8.564 178.68 -1.524 176.67 -9.724 178.47z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M43.88 40.321C71.601 44.281 97.121 8.641 98.881 -1.04C100.641 -10.72 90.521 -22.6 90.521 -22.6C91.841 -25.68 87.001 -39.76 81.721 -49C76.441 -58.24 60.54 -57.266 43 -58.24C27.16 -59.12 8.68 -35.8 7.36 -34.04C6.04 -32.28 12.2 6.001 13.52 11.721C14.84 17.441 12.2 43.841 12.2 43.841C46.44 34.741 16.16 36.361 43.88 40.321z").setFill(f).setStroke(s);
+					f = "#ea8e51";
+					g.createPath("M8.088 -33.392C6.792 -31.664 12.84 5.921 14.136 11.537C15.432 17.153 12.84 43.073 12.84 43.073C45.512 34.193 16.728 35.729 43.944 39.617C71.161 43.505 96.217 8.513 97.945 -0.992C99.673 -10.496 89.737 -22.16 89.737 -22.16C91.033 -25.184 86.281 -39.008 81.097 -48.08C75.913 -57.152 60.302 -56.195 43.08 -57.152C27.528 -58.016 9.384 -35.12 8.088 -33.392z").setFill(f).setStroke(s);
+					f = "#efaa7c";
+					g.createPath("M8.816 -32.744C7.544 -31.048 13.48 5.841 14.752 11.353C16.024 16.865 13.48 42.305 13.48 42.305C44.884 33.145 17.296 35.097 44.008 38.913C70.721 42.729 95.313 8.385 97.009 -0.944C98.705 -10.272 88.953 -21.72 88.953 -21.72C90.225 -24.688 85.561 -38.256 80.473 -47.16C75.385 -56.064 60.063 -55.125 43.16 -56.064C27.896 -56.912 10.088 -34.44 8.816 -32.744z").setFill(f).setStroke(s);
+					f = "#f4c6a8";
+					g.createPath("M9.544 -32.096C8.296 -30.432 14.12 5.761 15.368 11.169C16.616 16.577 14.12 41.537 14.12 41.537C43.556 32.497 17.864 34.465 44.072 38.209C70.281 41.953 94.409 8.257 96.073 -0.895C97.737 -10.048 88.169 -21.28 88.169 -21.28C89.417 -24.192 84.841 -37.504 79.849 -46.24C74.857 -54.976 59.824 -54.055 43.24 -54.976C28.264 -55.808 10.792 -33.76 9.544 -32.096z").setFill(f).setStroke(s);
+					f = "#f9e2d3";
+					g.createPath("M10.272 -31.448C9.048 -29.816 14.76 5.681 15.984 10.985C17.208 16.289 14.76 40.769 14.76 40.769C42.628 31.849 18.432 33.833 44.136 37.505C69.841 41.177 93.505 8.129 95.137 -0.848C96.769 -9.824 87.385 -20.84 87.385 -20.84C88.609 -23.696 84.121 -36.752 79.225 -45.32C74.329 -53.888 59.585 -52.985 43.32 -53.888C28.632 -54.704 11.496 -33.08 10.272 -31.448z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M44.2 36.8C69.4 40.4 92.601 8 94.201 -0.8C95.801 -9.6 86.601 -20.4 86.601 -20.4C87.801 -23.2 83.4 -36 78.6 -44.4C73.8 -52.8 59.346 -51.914 43.4 -52.8C29 -53.6 12.2 -32.4 11 -30.8C9.8 -29.2 15.4 5.6 16.6 10.8C17.8 16 15.4 40 15.4 40C40.9 31.4 19 33.2 44.2 36.8z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M90.601 2.8C90.601 2.8 62.8 10.4 51.2 8.8C51.2 8.8 35.4 2.2 26.6 24C26.6 24 23 31.2 21 33.2C19 35.2 90.601 2.8 90.601 2.8z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M94.401 0.6C94.401 0.6 65.4 12.8 55.4 12.4C55.4 12.4 39 7.8 30.6 22.4C30.6 22.4 22.2 31.6 19 33.2C19 33.2 18.6 34.8 25 30.8L35.4 36C35.4 36 50.2 45.6 59.8 29.6C59.8 29.6 63.8 18.4 63.8 16.4C63.8 14.4 85 8.8 86.601 8.4C88.201 8 94.801 3.8 94.401 0.6z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M47 36.514C40.128 36.514 31.755 32.649 31.755 26.4C31.755 20.152 40.128 13.887 47 13.887C53.874 13.887 59.446 18.952 59.446 25.2C59.446 31.449 53.874 36.514 47 36.514z").setFill(f).setStroke(s);
+					f = "#659900";
+					g.createPath("M43.377 19.83C38.531 20.552 33.442 22.055 33.514 21.839C35.054 17.22 41.415 13.887 47 13.887C51.296 13.887 55.084 15.865 57.32 18.875C57.32 18.875 52.004 18.545 43.377 19.83z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M55.4 19.6C55.4 19.6 51 16.4 51 18.6C51 18.6 54.6 23 55.4 19.6z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M45.4 27.726C42.901 27.726 40.875 25.7 40.875 23.2C40.875 20.701 42.901 18.675 45.4 18.675C47.9 18.675 49.926 20.701 49.926 23.2C49.926 25.7 47.9 27.726 45.4 27.726z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M-58.6 14.4C-58.6 14.4 -61.8 -6.8 -59.4 -11.2C-59.4 -11.2 -48.6 -21.2 -49 -24.8C-49 -24.8 -49.4 -42.8 -50.6 -43.6C-51.8 -44.4 -59.4 -50.4 -65.4 -44C-65.4 -44 -75.8 -26 -75 -19.6L-75 -17.6C-75 -17.6 -82.6 -18 -84.2 -16C-84.2 -16 -85.4 -10.8 -86.6 -10.4C-86.6 -10.4 -89.4 -8 -87.4 -5.2C-87.4 -5.2 -89.4 -2.8 -89 1.2L-81.4 5.2C-81.4 5.2 -79.4 19.6 -68.6 24.8C-63.764 27.129 -60.6 20.4 -58.6 14.4z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M-59.6 12.56C-59.6 12.56 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.48 -40.36 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.96 -59.6 12.56z").setF [...]
+					f = "#eb955c";
+					g.createPath("M-51.05 -42.61C-52.14 -43.47 -59.63 -49.24 -65.48 -43C-65.48 -43 -75.62 -25.45 -74.84 -19.21L-74.84 -17.26C-74.84 -17.26 -82.25 -17.65 -83.81 -15.7C-83.81 -15.7 -84.98 -10.63 -86.15 -10.24C-86.15 -10.24 -88.88 -7.9 -86.93 -5.17C-86.93 -5.17 -88.88 -2.83 -88.49 1.07L-81.08 4.97C-81.08 4.97 -79.13 19.01 -68.6 24.08C-63.886 26.35 -60.8 19.79 -58.85 13.94C-58.85 13.94 -61.97 -6.73 -59.63 -11.02C-59.63 -11.02 -49.1 -20.77 -49.49 -24.28C-49.49 -24.28 -49.88 -41.83 -51.05 -42 [...]
+					f = "#f2b892";
+					g.createPath("M-51.5 -41.62C-52.48 -42.54 -59.86 -48.08 -65.56 -42C-65.56 -42 -75.44 -24.9 -74.68 -18.82L-74.68 -16.92C-74.68 -16.92 -81.9 -17.3 -83.42 -15.4C-83.42 -15.4 -84.56 -10.46 -85.7 -10.08C-85.7 -10.08 -88.36 -7.8 -86.46 -5.14C-86.46 -5.14 -88.36 -2.86 -87.98 0.94L-80.76 4.74C-80.76 4.74 -78.86 18.42 -68.6 23.36C-64.006 25.572 -61 19.18 -59.1 13.48C-59.1 13.48 -62.14 -6.66 -59.86 -10.84C-59.86 -10.84 -49.6 -20.34 -49.98 -23.76C-49.98 -23.76 -50.36 -40.86 -51.5 -41.62z").set [...]
+					f = "#f8dcc8";
+					g.createPath("M-51.95 -40.63C-52.82 -41.61 -60.09 -46.92 -65.64 -41C-65.64 -41 -75.26 -24.35 -74.52 -18.43L-74.52 -16.58C-74.52 -16.58 -81.55 -16.95 -83.03 -15.1C-83.03 -15.1 -84.14 -10.29 -85.25 -9.92C-85.25 -9.92 -87.84 -7.7 -85.99 -5.11C-85.99 -5.11 -87.84 -2.89 -87.47 0.81L-80.44 4.51C-80.44 4.51 -78.59 17.83 -68.6 22.64C-64.127 24.794 -61.2 18.57 -59.35 13.02C-59.35 13.02 -62.31 -6.59 -60.09 -10.66C-60.09 -10.66 -50.1 -19.91 -50.47 -23.24C-50.47 -23.24 -50.84 -39.89 -51.95 -40. [...]
+					f = "#ffffff";
+					g.createPath("M-59.6 12.46C-59.6 12.46 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.16 -40.68 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.86 -59.6 12.46z").setF [...]
+					f = "#cccccc";
+					g.createPath("M-62.7 6.2C-62.7 6.2 -84.3 -4 -85.2 -4.8C-85.2 -4.8 -76.1 3.4 -75.3 3.4C-74.5 3.4 -62.7 6.2 -62.7 6.2z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-79.8 0C-79.8 0 -61.4 3.6 -61.4 8C-61.4 10.912 -61.643 24.331 -67 22.8C-75.4 20.4 -71.8 6 -79.8 0z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M-71.4 3.8C-71.4 3.8 -62.422 5.274 -61.4 8C-60.8 9.6 -60.137 17.908 -65.6 19C-70.152 19.911 -72.382 9.69 -71.4 3.8z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M14.595 46.349C14.098 44.607 15.409 44.738 17.2 44.2C19.2 43.6 31.4 39.8 32.2 37.2C33 34.6 46.2 39 46.2 39C48 39.8 52.4 42.4 52.4 42.4C57.2 43.6 63.8 44 63.8 44C66.2 45 69.6 47.8 69.6 47.8C84.2 58 96.601 50.8 96.601 50.8C116.601 44.2 110.601 27 110.601 27C107.601 18 110.801 14.6 110.801 14.6C111.001 10.8 118.201 17.2 118.201 17.2C120.801 21.4 121.601 26.4 121.601 26.4C129.601 37.6 126.201 19.8 126.201 19.8C126.401 18.8 123.601 15.2 123.601 14C123.601 12.8 121.801 9.4 1 [...]
+					f = "#000000";
+					g.createPath("M209.401 -120C209.401 -120 183.801 -112 181.001 -93.2C181.001 -93.2 178.601 -70.4 199.001 -52.8C199.001 -52.8 199.401 -46.4 201.401 -43.2C201.401 -43.2 199.801 -38.4 218.601 -46L245.801 -54.4C245.801 -54.4 252.201 -56.8 257.401 -65.6C262.601 -74.4 277.801 -93.2 274.201 -118.4C274.201 -118.4 275.401 -129.6 269.401 -130C269.401 -130 261.001 -131.6 253.801 -124C253.801 -124 247.001 -120.8 244.601 -121.2L209.401 -120z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M264.022 -120.99C264.022 -120.99 266.122 -129.92 261.282 -125.08C261.282 -125.08 254.242 -119.36 246.761 -119.36C246.761 -119.36 232.241 -117.16 227.841 -103.96C227.841 -103.96 223.881 -77.12 231.801 -71.4C231.801 -71.4 236.641 -63.92 243.681 -70.52C250.722 -77.12 266.222 -107.35 264.022 -120.99z").setFill(f).setStroke(s);
+					f = "#323232";
+					g.createPath("M263.648 -120.632C263.648 -120.632 265.738 -129.376 260.986 -124.624C260.986 -124.624 254.074 -119.008 246.729 -119.008C246.729 -119.008 232.473 -116.848 228.153 -103.888C228.153 -103.888 224.265 -77.536 232.041 -71.92C232.041 -71.92 236.793 -64.576 243.705 -71.056C250.618 -77.536 265.808 -107.24 263.648 -120.632z").setFill(f).setStroke(s);
+					f = "#666666";
+					g.createPath("M263.274 -120.274C263.274 -120.274 265.354 -128.832 260.69 -124.168C260.69 -124.168 253.906 -118.656 246.697 -118.656C246.697 -118.656 232.705 -116.536 228.465 -103.816C228.465 -103.816 224.649 -77.952 232.281 -72.44C232.281 -72.44 236.945 -65.232 243.729 -71.592C250.514 -77.952 265.394 -107.13 263.274 -120.274z").setFill(f).setStroke(s);
+					f = "#999999";
+					g.createPath("M262.9 -119.916C262.9 -119.916 264.97 -128.288 260.394 -123.712C260.394 -123.712 253.738 -118.304 246.665 -118.304C246.665 -118.304 232.937 -116.224 228.777 -103.744C228.777 -103.744 225.033 -78.368 232.521 -72.96C232.521 -72.96 237.097 -65.888 243.753 -72.128C250.41 -78.368 264.98 -107.02 262.9 -119.916z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M262.526 -119.558C262.526 -119.558 264.586 -127.744 260.098 -123.256C260.098 -123.256 253.569 -117.952 246.633 -117.952C246.633 -117.952 233.169 -115.912 229.089 -103.672C229.089 -103.672 225.417 -78.784 232.761 -73.48C232.761 -73.48 237.249 -66.544 243.777 -72.664C250.305 -78.784 264.566 -106.91 262.526 -119.558z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M262.151 -119.2C262.151 -119.2 264.201 -127.2 259.801 -122.8C259.801 -122.8 253.401 -117.6 246.601 -117.6C246.601 -117.6 233.401 -115.6 229.401 -103.6C229.401 -103.6 225.801 -79.2 233.001 -74C233.001 -74 237.401 -67.2 243.801 -73.2C250.201 -79.2 264.151 -106.8 262.151 -119.2z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M50.6 84C50.6 84 30.2 64.8 22.2 64C22.2 64 -12.2 60 -27 78C-27 78 -9.4 57.6 18.2 63.2C18.2 63.2 -3.4 58.8 -15.8 62C-15.8 62 -32.6 62 -42.2 76L-45 80.8C-45 80.8 -41 66 -22.6 60C-22.6 60 0.2 55.2 11 60C11 60 -10.6 53.2 -20.6 55.2C-20.6 55.2 -51 52.8 -63.8 79.2C-63.8 79.2 -59.8 64.8 -45 57.6C-45 57.6 -31.4 48.8 -11 51.6C-11 51.6 3.4 54.8 8.6 57.2C13.8 59.6 12.6 56.8 4.2 52C4.2 52 -1.4 42 -15.4 42.4C-15.4 42.4 -58.2 46 -68.6 58C-68.6 58 -55 46.8 -44.6 44C-44.6 44 -22.2 36  [...]
+					f = "#cccccc";
+					g.createPath("M189 278C189 278 173.5 241.5 161 232C161 232 187 248 190.5 266C190.5 266 190.5 276 189 278z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M236 285.5C236 285.5 209.5 230.5 191 206.5C191 206.5 234.5 244 239.5 270.5L240 276L237 273.5C237 273.5 236.5 282.5 236 285.5z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M292.5 237C292.5 237 230 177.5 228.5 175C228.5 175 289 241 292 248.5C292 248.5 290 239.5 292.5 237z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M104 280.5C104 280.5 123.5 228.5 142.5 251C142.5 251 157.5 261 157 264C157 264 153 257.5 135 258C135 258 116 255 104 280.5z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M294.5 153C294.5 153 249.5 124.5 242 123C230.193 120.639 291.5 152 296.5 162.5C296.5 162.5 298.5 160 294.5 153z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M143.801 259.601C143.801 259.601 164.201 257.601 171.001 250.801L175.401 254.401L193.001 216.001L196.601 221.201C196.601 221.201 211.001 206.401 210.201 198.401C209.401 190.401 223.001 204.401 223.001 204.401C223.001 204.401 222.201 192.801 229.401 199.601C229.401 199.601 227.001 184.001 235.401 192.001C235.401 192.001 224.864 161.844 247.401 187.601C253.001 194.001 248.601 187.201 248.601 187.201C248.601 187.201 222.601 139.201 244.201 153.601C244.201 153.601 246.201  [...]
+					f = "#000000";
+					g.createPath("M109.401 -97.2C109.401 -97.2 97.801 -105.2 93.801 -104.8C89.801 -104.4 121.401 -113.6 162.601 -86C162.601 -86 167.401 -83.2 171.001 -83.6C171.001 -83.6 174.201 -81.2 171.401 -77.6C171.401 -77.6 162.601 -68 173.801 -56.8C173.801 -56.8 192.201 -50 186.601 -58.8C186.601 -58.8 197.401 -54.8 199.801 -50.8C202.201 -46.8 201.001 -50.8 201.001 -50.8C201.001 -50.8 194.601 -58 188.601 -63.2C188.601 -63.2 183.401 -65.2 180.601 -73.6C177.801 -82 175.401 -92 179.801 -95.2C179.801 - [...]
+					f = "#cc7226";
+					g.createPath("M180.801 -106.4C180.801 -106.4 170.601 -113.8 168.601 -113.8C166.601 -113.8 154.201 -124 150.001 -123.6C145.801 -123.2 133.601 -133.2 106.201 -125C106.201 -125 105.601 -127 109.201 -127.8C109.201 -127.8 115.601 -130 116.001 -130.6C116.001 -130.6 136.201 -134.8 143.401 -131.2C143.401 -131.2 152.601 -128.6 158.801 -122.4C158.801 -122.4 170.001 -119.2 173.201 -120.2C173.201 -120.2 182.001 -118 182.401 -116.2C182.401 -116.2 188.201 -113.2 186.401 -110.6C186.401 -110.6 186. [...]
+					f = "#cc7226";
+					g.createPath("M168.33 -108.509C169.137 -107.877 170.156 -107.779 170.761 -106.97C170.995 -106.656 170.706 -106.33 170.391 -106.233C169.348 -105.916 168.292 -106.486 167.15 -105.898C166.748 -105.691 166.106 -105.873 165.553 -106.022C163.921 -106.463 162.092 -106.488 160.401 -105.8C158.416 -106.929 156.056 -106.345 153.975 -107.346C153.917 -107.373 153.695 -107.027 153.621 -107.054C150.575 -108.199 146.832 -107.916 144.401 -110.2C141.973 -110.612 139.616 -111.074 137.188 -111.754C135. [...]
+					f = "#cc7226";
+					g.createPath("M91.696 -122.739C89.178 -124.464 86.81 -125.57 84.368 -127.356C84.187 -127.489 83.827 -127.319 83.625 -127.441C82.618 -128.05 81.73 -128.631 80.748 -129.327C80.209 -129.709 79.388 -129.698 78.88 -129.956C76.336 -131.248 73.707 -131.806 71.2 -133C71.882 -133.638 73.004 -133.394 73.6 -134.2C73.795 -133.92 74.033 -133.636 74.386 -133.827C76.064 -134.731 77.914 -134.884 79.59 -134.794C81.294 -134.702 83.014 -134.397 84.789 -134.125C85.096 -134.078 85.295 -133.555 85.618 -1 [...]
+					f = "#cc7226";
+					g.createPath("M59.198 -115.391C56.044 -116.185 52.994 -116.07 49.978 -117.346C49.911 -117.374 49.688 -117.027 49.624 -117.054C48.258 -117.648 47.34 -118.614 46.264 -119.66C45.351 -120.548 43.693 -120.161 42.419 -120.648C42.095 -120.772 41.892 -121.284 41.591 -121.323C40.372 -121.48 39.445 -122.429 38.4 -123C40.736 -123.795 43.147 -123.764 45.609 -124.148C45.722 -124.166 45.867 -123.845 46 -123.845C46.136 -123.845 46.266 -124.066 46.4 -124.2C46.595 -123.92 46.897 -123.594 47.154 -123 [...]
+					f = "#cc7226";
+					g.createPath("M45.338 -71.179C43.746 -72.398 43.162 -74.429 42.034 -76.221C41.82 -76.561 42.094 -76.875 42.411 -76.964C42.971 -77.123 43.514 -76.645 43.923 -76.443C45.668 -75.581 47.203 -74.339 49.2 -74.2C51.19 -71.966 55.45 -71.581 55.457 -68.2C55.458 -67.341 54.03 -68.259 53.6 -67.4C51.149 -68.403 48.76 -68.3 46.38 -69.767C45.763 -70.148 46.093 -70.601 45.338 -71.179z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M17.8 -123.756C17.935 -123.755 24.966 -123.522 24.949 -123.408C24.904 -123.099 17.174 -122.05 16.81 -122.22C16.646 -122.296 9.134 -119.866 9 -120C9.268 -120.135 17.534 -123.756 17.8 -123.756z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M33.2 -114C33.2 -114 18.4 -112.2 14 -111C9.6 -109.8 -9 -102.2 -12 -100.2C-12 -100.2 -25.4 -94.8 -42.4 -74.8C-42.4 -74.8 -34.8 -78.2 -32.6 -81C-32.6 -81 -19 -93.6 -19.2 -91C-19.2 -91 -7 -99.6 -7.6 -97.4C-7.6 -97.4 16.8 -108.6 14.8 -105.4C14.8 -105.4 36.4 -110 35.4 -108C35.4 -108 54.2 -103.6 51.4 -103.4C51.4 -103.4 45.6 -102.2 52 -98.6C52 -98.6 48.6 -94.2 43.2 -98.2C37.8 -102.2 40.8 -100 35.8 -99C35.8 -99 33.2 -98.2 28.6 -102.2C28.6 -102.2 23 -106.8 14.2 -103.2C14.2 -103 [...]
+					s = {color: "#4c0000", width: 2}; f = null;
+					g.createPath("M51.4 85C51.4 85 36.4 68.2 28 65.6C28 65.6 14.6 58.8 -10 66.6").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M24.8 64.2C24.8 64.2 -0.4 56.2 -15.8 60.4C-15.8 60.4 -34.2 62.4 -42.6 76.2").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M21.2 63C21.2 63 4.2 55.8 -10.6 53.6C-10.6 53.6 -27.2 51 -43.8 58.2C-43.8 58.2 -56 64.2 -61.4 74.4").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M22.2 63.4C22.2 63.4 6.8 52.4 5.8 51C5.8 51 -1.2 40 -14.2 39.6C-14.2 39.6 -35.6 40.4 -52.8 48.4").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M20.895 54.407C22.437 55.87 49.4 84.8 49.4 84.8C84.6 121.401 56.6 87.2 56.6 87.2C49 82.4 39.8 63.6 39.8 63.6C38.6 60.8 53.8 70.8 53.8 70.8C57.8 71.6 71.4 90.8 71.4 90.8C64.6 88.4 69.4 95.6 69.4 95.6C72.2 97.6 92.601 113.201 92.601 113.201C96.201 117.201 100.201 118.801 100.201 118.801C114.201 113.601 107.801 126.801 107.801 126.801C110.201 133.601 115.801 122.001 115.801 122.001C127.001 105.2 110.601 107.601 110.601 107.601C80.6 110.401 73.8 94.4 73.8 94.4C71.4 92 80.2 [...]
+					f = "#4c0000";
+					g.createPath("M-3 42.8C-3 42.8 8.6 48.4 11.2 51.2C13.8 54 27.8 65.4 27.8 65.4C27.8 65.4 22.4 63.4 19.8 61.6C17.2 59.8 6.4 51.6 6.4 51.6C6.4 51.6 2.6 45.6 -3 42.8z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M-61.009 11.603C-60.672 11.455 -61.196 8.743 -61.4 8.2C-62.422 5.474 -71.4 4 -71.4 4C-71.627 5.365 -71.682 6.961 -71.576 8.599C-71.576 8.599 -66.708 14.118 -61.009 11.603z").setFill(f).setStroke(s);
+					f = "#659900";
+					g.createPath("M-61.009 11.403C-61.458 11.561 -61.024 8.669 -61.2 8.2C-62.222 5.474 -71.4 3.9 -71.4 3.9C-71.627 5.265 -71.682 6.861 -71.576 8.499C-71.576 8.499 -67.308 13.618 -61.009 11.403z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-65.4 11.546C-66.025 11.546 -66.531 10.406 -66.531 9C-66.531 7.595 -66.025 6.455 -65.4 6.455C-64.775 6.455 -64.268 7.595 -64.268 9C-64.268 10.406 -64.775 11.546 -65.4 11.546z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-65.4 9z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-111 109.601C-111 109.601 -116.6 119.601 -91.8 113.601C-91.8 113.601 -77.8 112.401 -75.4 110.001C-74.2 110.801 -65.834 113.734 -63 114.401C-56.2 116.001 -47.8 106 -47.8 106C-47.8 106 -43.2 95.5 -40.4 95.5C-37.6 95.5 -40.8 97.1 -40.8 97.1C-40.8 97.1 -47.4 107.201 -47 108.801C-47 108.801 -52.2 128.801 -68.2 129.601C-68.2 129.601 -84.35 130.551 -83 136.401C-83 136.401 -74.2 134.001 -71.8 136.401C-71.8 136.401 -61 136.001 -69 142.401L-75.8 154.001C-75.8 154.001 -75.66 157 [...]
+					f = "#e59999";
+					g.createPath("M-112.2 113.601C-112.2 113.601 -114.2 123.201 -77.4 112.801C-77.4 112.801 -73 112.801 -70.6 113.601C-68.2 114.401 -56.2 117.201 -54.2 116.001C-54.2 116.001 -61.4 129.601 -73 128.001C-73 128.001 -86.2 129.601 -85.8 134.401C-85.8 134.401 -81.8 141.601 -77 144.001C-77 144.001 -74.2 146.401 -74.6 149.601C-75 152.801 -77.8 154.401 -79.8 155.201C-81.8 156.001 -85 152.801 -86.6 152.801C-88.2 152.801 -96.6 146.401 -101 141.601C-105.4 136.801 -113.8 124.801 -113.4 122.001C-113  [...]
+					f = "#b26565";
+					g.createPath("M-109 131.051C-106.4 135.001 -103.2 139.201 -101 141.601C-96.6 146.401 -88.2 152.801 -86.6 152.801C-85 152.801 -81.8 156.001 -79.8 155.201C-77.8 154.401 -75 152.801 -74.6 149.601C-74.2 146.401 -77 144.001 -77 144.001C-80.066 142.468 -82.806 138.976 -84.385 136.653C-84.385 136.653 -84.2 139.201 -89.4 138.401C-94.6 137.601 -99.8 134.801 -101.4 131.601C-103 128.401 -105.4 126.001 -103.8 129.601C-102.2 133.201 -99.8 136.801 -98.2 137.201C-96.6 137.601 -97 138.801 -99.4 138 [...]
+					f = "#992600";
+					g.createPath("M-111.6 110.001C-111.6 110.001 -109.8 96.4 -108.6 92.4C-108.6 92.4 -109.4 85.6 -107 81.4C-104.6 77.2 -102.6 71 -99.6 65.6C-96.6 60.2 -96.4 56.2 -92.4 54.6C-88.4 53 -82.4 44.4 -79.6 43.4C-76.8 42.4 -77 43.2 -77 43.2C-77 43.2 -70.2 28.4 -56.6 32.4C-56.6 32.4 -72.8 29.6 -57 20.2C-57 20.2 -61.8 21.3 -58.5 14.3C-56.299 9.632 -56.8 16.4 -67.8 28.2C-67.8 28.2 -72.8 36.8 -78 39.8C-83.2 42.8 -95.2 49.8 -96.4 53.6C-97.6 57.4 -100.8 63.2 -102.8 64.8C-104.8 66.4 -107.6 70.6 -108 7 [...]
+					f = "#ffffff";
+					g.createPath("M-120.2 114.601C-120.2 114.601 -122.2 113.201 -126.6 119.201C-126.6 119.201 -119.3 152.201 -119.3 153.601C-119.3 153.601 -118.2 151.501 -119.5 144.301C-120.8 137.101 -121.7 124.401 -121.7 124.401L-120.2 114.601z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-98.6 54C-98.6 54 -116.2 57.2 -115.8 86.4L-116.6 111.201C-116.6 111.201 -117.8 85.6 -119 84C-120.2 82.4 -116.2 71.2 -119.4 77.2C-119.4 77.2 -133.4 91.2 -125.4 112.401C-125.4 112.401 -123.9 115.701 -126.9 111.101C-126.9 111.101 -131.5 98.5 -130.4 92.1C-130.4 92.1 -130.2 89.9 -128.3 87.1C-128.3 87.1 -119.7 75.4 -117 73.1C-117 73.1 -115.2 58.7 -99.8 53.5C-99.8 53.5 -94.1 51.2 -98.6 54z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M40.8 -12.2C41.46 -12.554 41.451 -13.524 42.031 -13.697C43.18 -14.041 43.344 -15.108 43.862 -15.892C44.735 -17.211 44.928 -18.744 45.51 -20.235C45.782 -20.935 45.809 -21.89 45.496 -22.55C44.322 -25.031 43.62 -27.48 42.178 -29.906C41.91 -30.356 41.648 -31.15 41.447 -31.748C40.984 -33.132 39.727 -34.123 38.867 -35.443C38.579 -35.884 39.104 -36.809 38.388 -36.893C37.491 -36.998 36.042 -37.578 35.809 -36.552C35.221 -33.965 36.232 -31.442 37.2 -29C36.418 -28.308 36.752 -27. [...]
+					f = "#000000";
+					g.createPath("M31.959 -16.666C32.083 -16.743 31.928 -17.166 32.037 -17.382C32.199 -17.706 32.602 -17.894 32.764 -18.218C32.873 -18.434 32.71 -18.814 32.846 -18.956C35.179 -21.403 35.436 -24.427 34.4 -27.4C35.424 -28.02 35.485 -29.282 35.06 -30.129C34.207 -31.829 34.014 -33.755 33.039 -35.298C32.237 -36.567 30.659 -37.811 29.288 -36.508C28.867 -36.108 28.546 -35.321 28.824 -34.609C28.888 -34.446 29.173 -34.3 29.146 -34.218C29.039 -33.894 28.493 -33.67 28.487 -33.398C28.457 -31.902 27 [...]
+					f = "#000000";
+					g.createPath("M94.771 -26.977C96.16 -25.185 96.45 -22.39 94.401 -21C94.951 -17.691 98.302 -19.67 100.401 -20.2C100.292 -20.588 100.519 -20.932 100.802 -20.937C101.859 -20.952 102.539 -21.984 103.601 -21.8C104.035 -23.357 105.673 -24.059 106.317 -25.439C108.043 -29.134 107.452 -33.407 104.868 -36.653C104.666 -36.907 104.883 -37.424 104.759 -37.786C104.003 -39.997 101.935 -40.312 100.001 -41C98.824 -44.875 98.163 -48.906 96.401 -52.6C94.787 -52.85 94.089 -54.589 92.752 -55.309C91.419  [...]
+					f = "#000000";
+					g.createPath("M57.611 -8.591C56.124 -6.74 52.712 -4.171 55.629 -2.243C55.823 -2.114 56.193 -2.11 56.366 -2.244C58.387 -3.809 60.39 -4.712 62.826 -5.294C62.95 -5.323 63.224 -4.856 63.593 -5.017C65.206 -5.72 67.216 -5.662 68.4 -7C72.167 -6.776 75.732 -7.892 79.123 -9.2C80.284 -9.648 81.554 -10.207 82.755 -10.709C84.131 -11.285 85.335 -12.213 86.447 -13.354C86.58 -13.49 86.934 -13.4 87.201 -13.4C87.161 -14.263 88.123 -14.39 88.37 -15.012C88.462 -15.244 88.312 -15.64 88.445 -15.742C90.5 [...]
+					f = "#000000";
+					g.createPath("M2.2 -58C2.2 -58 -7.038 -60.872 -18.2 -35.2C-18.2 -35.2 -20.6 -30 -23 -28C-25.4 -26 -36.6 -22.4 -38.6 -18.4L-49 -2.4C-49 -2.4 -34.2 -18.4 -31 -20.8C-31 -20.8 -23 -29.2 -26.2 -22.4C-26.2 -22.4 -40.2 -11.6 -39 -2.4C-39 -2.4 -44.6 12 -45.4 14C-45.4 14 -29.4 -18 -27 -19.2C-24.6 -20.4 -23.4 -20.4 -24.6 -16.8C-25.8 -13.2 -26.2 3.2 -29 5.2C-29 5.2 -21 -15.2 -21.8 -18.4C-21.8 -18.4 -18.6 -22 -16.2 -16.8L-17.4 -0.8L-13 11.2C-13 11.2 -15.4 0 -13.8 -15.6C-13.8 -15.6 -15.8 -26 -11 [...]
+					f = "#000000";
+					g.createPath("M-17.8 -41.6C-17.8 -41.6 -30.6 -41.6 -33.8 -36.4L-41 -26.8C-41 -26.8 -23.8 -36.8 -19.8 -38C-15.8 -39.2 -17.8 -41.6 -17.8 -41.6z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-57.8 -35.2C-57.8 -35.2 -59.8 -34 -60.2 -31.2C-60.6 -28.4 -63 -28 -62.2 -25.2C-61.4 -22.4 -59.4 -20 -59.4 -24C-59.4 -28 -57.8 -30 -57 -31.2C-56.2 -32.4 -54.6 -36.8 -57.8 -35.2z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-66.6 26C-66.6 26 -75 22 -78.2 18.4C-81.4 14.8 -80.948 19.966 -85.8 19.6C-91.647 19.159 -90.6 3.2 -90.6 3.2L-94.6 10.8C-94.6 10.8 -95.8 25.2 -87.8 22.8C-83.893 21.628 -82.6 23.2 -84.2 24C-85.8 24.8 -78.6 25.2 -81.4 26.8C-84.2 28.4 -69.8 23.2 -72.2 33.6L-66.6 26z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-79.2 40.4C-79.2 40.4 -94.6 44.8 -98.2 35.2C-98.2 35.2 -103 37.6 -100.8 40.6C-98.6 43.6 -97.4 44 -97.4 44C-97.4 44 -92 45.2 -92.6 46C-93.2 46.8 -95.6 50.2 -95.6 50.2C-95.6 50.2 -85.4 44.2 -79.2 40.4z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M149.201 118.601C148.774 120.735 147.103 121.536 145.201 122.201C143.284 121.243 140.686 118.137 138.801 120.201C138.327 119.721 137.548 119.661 137.204 118.999C136.739 118.101 137.011 117.055 136.669 116.257C136.124 114.985 135.415 113.619 135.601 112.201C137.407 111.489 138.002 109.583 137.528 107.82C137.459 107.563 137.03 107.366 137.23 107.017C137.416 106.694 137.734 106.467 138.001 106.2C137.866 106.335 137.721 106.568 137.61 106.548C137 106.442 137.124 105.805 13 [...]
+					f = "#ffffff";
+					g.createPath("M139.6 138.201C139.593 136.463 137.992 134.707 139.201 133.001C139.336 133.135 139.467 133.356 139.601 133.356C139.736 133.356 139.867 133.135 140.001 133.001C141.496 135.217 145.148 136.145 145.006 138.991C144.984 139.438 143.897 140.356 144.801 141.001C142.988 142.349 142.933 144.719 142.001 146.601C140.763 146.315 139.551 145.952 138.401 145.401C138.753 143.915 138.636 142.231 139.456 140.911C139.89 140.213 139.603 139.134 139.6 138.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-26.6 129.201C-26.6 129.201 -43.458 139.337 -29.4 124.001C-20.6 114.401 -10.6 108.801 -10.6 108.801C-10.6 108.801 -0.2 104.4 3.4 103.2C7 102 22.2 96.8 25.4 96.4C28.6 96 38.2 92 45 96C51.8 100 59.8 104.4 59.8 104.4C59.8 104.4 43.4 96 39.8 98.4C36.2 100.8 29 100.4 23 103.6C23 103.6 8.2 108.001 5 110.001C1.8 112.001 -8.6 123.601 -10.2 122.801C-11.8 122.001 -9.8 121.601 -8.6 118.801C-7.4 116.001 -9.4 114.401 -17.4 120.801C-25.4 127.201 -26.6 129.201 -26.6 129.201z").setFi [...]
+					f = "#000000";
+					g.createPath("M-19.195 123.234C-19.195 123.234 -17.785 110.194 -9.307 111.859C-9.307 111.859 -1.081 107.689 1.641 105.721C1.641 105.721 9.78 104.019 11.09 103.402C29.569 94.702 44.288 99.221 44.835 98.101C45.381 96.982 65.006 104.099 68.615 108.185C69.006 108.628 58.384 102.588 48.686 100.697C40.413 99.083 18.811 100.944 7.905 106.48C4.932 107.989 -4.013 113.773 -6.544 113.662C-9.075 113.55 -19.195 123.234 -19.195 123.234z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-23 148.801C-23 148.801 -38.2 146.401 -21.4 144.801C-21.4 144.801 -3.4 142.801 0.6 137.601C0.6 137.601 14.2 128.401 17 128.001C19.8 127.601 49.8 120.401 50.2 118.001C50.6 115.601 56.2 115.601 57.8 116.401C59.4 117.201 58.6 118.401 55.8 119.201C53 120.001 21.8 136.401 15.4 137.601C9 138.801 -2.6 146.401 -7.4 147.601C-12.2 148.801 -23 148.801 -23 148.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-3.48 141.403C-3.48 141.403 -12.062 140.574 -3.461 139.755C-3.461 139.755 5.355 136.331 7.403 133.668C7.403 133.668 14.367 128.957 15.8 128.753C17.234 128.548 31.194 124.861 31.399 123.633C31.604 122.404 65.67 109.823 70.09 113.013C73.001 115.114 63.1 113.437 53.466 117.847C52.111 118.467 18.258 133.054 14.981 133.668C11.704 134.283 5.765 138.174 3.307 138.788C0.85 139.403 -3.48 141.403 -3.48 141.403z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-11.4 143.601C-11.4 143.601 -6.2 143.201 -7.4 144.801C-8.6 146.401 -11 145.601 -11 145.601L-11.4 143.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-18.6 145.201C-18.6 145.201 -13.4 144.801 -14.6 146.401C-15.8 148.001 -18.2 147.201 -18.2 147.201L-18.6 145.201z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-29 146.801C-29 146.801 -23.8 146.401 -25 148.001C-26.2 149.601 -28.6 148.801 -28.6 148.801L-29 146.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-36.6 147.601C-36.6 147.601 -31.4 147.201 -32.6 148.801C-33.8 150.401 -36.2 149.601 -36.2 149.601L-36.6 147.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M1.8 108.001C1.8 108.001 6.2 108.001 5 109.601C3.8 111.201 0.6 110.801 0.6 110.801L1.8 108.001z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-8.2 113.601C-8.2 113.601 -1.694 111.46 -4.2 114.801C-5.4 116.401 -7.8 115.601 -7.8 115.601L-8.2 113.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-19.4 118.401C-19.4 118.401 -14.2 118.001 -15.4 119.601C-16.6 121.201 -19 120.401 -19 120.401L-19.4 118.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-27 124.401C-27 124.401 -21.8 124.001 -23 125.601C-24.2 127.201 -26.6 126.401 -26.6 126.401L-27 124.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-33.8 129.201C-33.8 129.201 -28.6 128.801 -29.8 130.401C-31 132.001 -33.4 131.201 -33.4 131.201L-33.8 129.201z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M5.282 135.598C5.282 135.598 12.203 135.066 10.606 137.195C9.009 139.325 5.814 138.26 5.814 138.26L5.282 135.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M15.682 130.798C15.682 130.798 22.603 130.266 21.006 132.395C19.409 134.525 16.214 133.46 16.214 133.46L15.682 130.798z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M26.482 126.398C26.482 126.398 33.403 125.866 31.806 127.995C30.209 130.125 27.014 129.06 27.014 129.06L26.482 126.398z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M36.882 121.598C36.882 121.598 43.803 121.066 42.206 123.195C40.609 125.325 37.414 124.26 37.414 124.26L36.882 121.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M9.282 103.598C9.282 103.598 16.203 103.066 14.606 105.195C13.009 107.325 9.014 107.06 9.014 107.06L9.282 103.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M19.282 100.398C19.282 100.398 26.203 99.866 24.606 101.995C23.009 104.125 18.614 103.86 18.614 103.86L19.282 100.398z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-3.4 140.401C-3.4 140.401 1.8 140.001 0.6 141.601C-0.6 143.201 -3 142.401 -3 142.401L-3.4 140.401z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-76.6 41.2C-76.6 41.2 -81 50 -81.4 53.2C-81.4 53.2 -80.6 44.4 -79.4 42.4C-78.2 40.4 -76.6 41.2 -76.6 41.2z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-95 55.2C-95 55.2 -98.2 69.6 -97.8 72.4C-97.8 72.4 -99 60.8 -98.6 59.6C-98.2 58.4 -95 55.2 -95 55.2z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-74.2 -19.4L-74.4 -16.2L-76.6 -16C-76.6 -16 -62.4 -3.4 -61.8 4.2C-61.8 4.2 -61 -4 -74.2 -19.4z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-70.216 -18.135C-70.647 -18.551 -70.428 -19.296 -70.836 -19.556C-71.645 -20.072 -69.538 -20.129 -69.766 -20.845C-70.149 -22.051 -69.962 -22.072 -70.084 -23.348C-70.141 -23.946 -69.553 -25.486 -69.168 -25.926C-67.722 -27.578 -69.046 -30.51 -67.406 -32.061C-67.102 -32.35 -66.726 -32.902 -66.441 -33.32C-65.782 -34.283 -64.598 -34.771 -63.648 -35.599C-63.33 -35.875 -63.531 -36.702 -62.962 -36.61C-62.248 -36.495 -61.007 -36.625 -61.052 -35.784C-61.165 -33.664 -62.494 -31.9 [...]
+					f = "#000000";
+					g.createPath("M-73.8 -16.4C-73.8 -16.4 -73.4 -9.6 -71 -8C-68.6 -6.4 -69.8 -7.2 -73 -8.4C-76.2 -9.6 -75 -10.4 -75 -10.4C-75 -10.4 -77.8 -10 -75.4 -8C-73 -6 -69.4 -3.6 -71 -3.6C-72.6 -3.6 -80.2 -7.6 -80.2 -10.4C-80.2 -13.2 -81.2 -17.3 -81.2 -17.3C-81.2 -17.3 -80.1 -18.1 -75.3 -18C-75.3 -18 -73.9 -17.3 -73.8 -16.4z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-74.6 2.2C-74.6 2.2 -83.12 -0.591 -101.6 2.8C-101.6 2.8 -92.569 0.722 -73.8 3C-63.5 4.25 -74.6 2.2 -74.6 2.2z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-72.502 2.129C-72.502 2.129 -80.748 -1.389 -99.453 0.392C-99.453 0.392 -90.275 -0.897 -71.774 2.995C-61.62 5.131 -72.502 2.129 -72.502 2.129z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-70.714 2.222C-70.714 2.222 -78.676 -1.899 -97.461 -1.514C-97.461 -1.514 -88.213 -2.118 -70.052 3.14C-60.086 6.025 -70.714 2.222 -70.714 2.222z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-69.444 2.445C-69.444 2.445 -76.268 -1.862 -93.142 -2.96C-93.142 -2.96 -84.803 -2.79 -68.922 3.319C-60.206 6.672 -69.444 2.445 -69.444 2.445z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M45.84 12.961C45.84 12.961 44.91 13.605 45.124 12.424C45.339 11.243 73.547 -1.927 77.161 -1.677C77.161 -1.677 46.913 11.529 45.84 12.961z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M42.446 13.6C42.446 13.6 41.57 14.315 41.691 13.121C41.812 11.927 68.899 -3.418 72.521 -3.452C72.521 -3.452 43.404 12.089 42.446 13.6z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M39.16 14.975C39.16 14.975 38.332 15.747 38.374 14.547C38.416 13.348 58.233 -2.149 68.045 -4.023C68.045 -4.023 50.015 4.104 39.16 14.975z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M36.284 16.838C36.284 16.838 35.539 17.532 35.577 16.453C35.615 15.373 53.449 1.426 62.28 -0.26C62.28 -0.26 46.054 7.054 36.284 16.838z").setFill(f).setStroke(s);
+					f = "#cccccc"; s = null;
+					g.createPath("M4.6 164.801C4.6 164.801 -10.6 162.401 6.2 160.801C6.2 160.801 24.2 158.801 28.2 153.601C28.2 153.601 41.8 144.401 44.6 144.001C47.4 143.601 63.8 140.001 64.2 137.601C64.6 135.201 70.6 132.801 72.2 133.601C73.8 134.401 73.8 143.601 71 144.401C68.2 145.201 49.4 152.401 43 153.601C36.6 154.801 25 162.401 20.2 163.601C15.4 164.801 4.6 164.801 4.6 164.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M77.6 127.401C77.6 127.401 74.6 129.001 73.4 131.601C73.4 131.601 67 142.201 52.8 145.401C52.8 145.401 29.8 154.401 22 156.401C22 156.401 8.6 161.401 1.2 160.601C1.2 160.601 -5.8 160.801 0.4 162.401C0.4 162.401 20.6 160.401 24 158.601C24 158.601 39.6 153.401 42.6 150.801C45.6 148.201 63.8 143.201 66 141.201C68.2 139.201 78 130.801 77.6 127.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M18.882 158.911C18.882 158.911 24.111 158.685 22.958 160.234C21.805 161.784 19.357 160.91 19.357 160.91L18.882 158.911z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M11.68 160.263C11.68 160.263 16.908 160.037 15.756 161.586C14.603 163.136 12.155 162.263 12.155 162.263L11.68 160.263z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M1.251 161.511C1.251 161.511 6.48 161.284 5.327 162.834C4.174 164.383 1.726 163.51 1.726 163.51L1.251 161.511z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-6.383 162.055C-6.383 162.055 -1.154 161.829 -2.307 163.378C-3.46 164.928 -5.908 164.054 -5.908 164.054L-6.383 162.055z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M35.415 151.513C35.415 151.513 42.375 151.212 40.84 153.274C39.306 155.336 36.047 154.174 36.047 154.174L35.415 151.513z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M45.73 147.088C45.73 147.088 51.689 143.787 51.155 148.849C50.885 151.405 46.362 149.749 46.362 149.749L45.73 147.088z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M54.862 144.274C54.862 144.274 62.021 140.573 60.287 146.035C59.509 148.485 55.493 146.935 55.493 146.935L54.862 144.274z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M64.376 139.449C64.376 139.449 68.735 134.548 69.801 141.21C70.207 143.748 65.008 142.11 65.008 142.11L64.376 139.449z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M26.834 155.997C26.834 155.997 32.062 155.77 30.91 157.32C29.757 158.869 27.308 157.996 27.308 157.996L26.834 155.997z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M62.434 34.603C62.434 34.603 61.708 35.268 61.707 34.197C61.707 33.127 79.191 19.863 88.034 18.479C88.034 18.479 71.935 25.208 62.434 34.603z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M65.4 98.4C65.4 98.4 87.401 120.801 96.601 124.401C96.601 124.401 105.801 135.601 101.801 161.601C101.801 161.601 98.601 169.201 95.401 148.401C95.401 148.401 98.601 123.201 87.401 139.201C87.401 139.201 79 129.301 85.4 129.601C85.4 129.601 88.601 131.601 89.001 130.001C89.401 128.401 81.4 114.801 64.2 100.4C47 86 65.4 98.4 65.4 98.4z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M7 137.201C7 137.201 6.8 135.401 8.6 136.201C10.4 137.001 104.601 143.201 136.201 167.201C136.201 167.201 91.001 144.001 7 137.201z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M17.4 132.801C17.4 132.801 17.2 131.001 19 131.801C20.8 132.601 157.401 131.601 181.001 164.001C181.001 164.001 159.001 138.801 17.4 132.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M29 128.801C29 128.801 28.8 127.001 30.6 127.801C32.4 128.601 205.801 115.601 229.401 148.001C229.401 148.001 219.801 122.401 29 128.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M39 124.001C39 124.001 38.8 122.201 40.6 123.001C42.4 123.801 164.601 85.2 188.201 117.601C188.201 117.601 174.801 93 39 124.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-19 146.801C-19 146.801 -19.2 145.001 -17.4 145.801C-15.6 146.601 2.2 148.801 4.2 187.601C4.2 187.601 -3 145.601 -19 146.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-27.8 148.401C-27.8 148.401 -28 146.601 -26.2 147.401C-24.4 148.201 -10.2 143.601 -13 182.401C-13 182.401 -11.8 147.201 -27.8 148.401z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-35.8 148.801C-35.8 148.801 -36 147.001 -34.2 147.801C-32.4 148.601 -17 149.201 -29.4 171.601C-29.4 171.601 -19.8 147.601 -35.8 148.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M11.526 104.465C11.526 104.465 11.082 106.464 12.631 105.247C28.699 92.622 61.141 33.72 116.826 28.086C116.826 28.086 78.518 15.976 11.526 104.465z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M22.726 102.665C22.726 102.665 21.363 101.472 23.231 100.847C25.099 100.222 137.541 27.72 176.826 35.686C176.826 35.686 149.719 28.176 22.726 102.665z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M1.885 108.767C1.885 108.767 1.376 110.366 3.087 109.39C12.062 104.27 15.677 47.059 59.254 45.804C59.254 45.804 26.843 31.09 1.885 108.767z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-18.038 119.793C-18.038 119.793 -19.115 121.079 -17.162 120.825C-6.916 119.493 14.489 78.222 58.928 83.301C58.928 83.301 26.962 68.955 -18.038 119.793z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-6.8 113.667C-6.8 113.667 -7.611 115.136 -5.742 114.511C4.057 111.237 17.141 66.625 61.729 63.078C61.729 63.078 27.603 55.135 -6.8 113.667z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-25.078 124.912C-25.078 124.912 -25.951 125.954 -24.369 125.748C-16.07 124.669 1.268 91.24 37.264 95.354C37.264 95.354 11.371 83.734 -25.078 124.912z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-32.677 130.821C-32.677 130.821 -33.682 131.866 -32.091 131.748C-27.923 131.439 2.715 98.36 21.183 113.862C21.183 113.862 9.168 95.139 -32.677 130.821z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M36.855 98.898C36.855 98.898 35.654 97.543 37.586 97.158C39.518 96.774 160.221 39.061 198.184 51.927C198.184 51.927 172.243 41.053 36.855 98.898z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M3.4 163.201C3.4 163.201 3.2 161.401 5 162.201C6.8 163.001 22.2 163.601 9.8 186.001C9.8 186.001 19.4 162.001 3.4 163.201z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M13.8 161.601C13.8 161.601 13.6 159.801 15.4 160.601C17.2 161.401 35 163.601 37 202.401C37 202.401 29.8 160.401 13.8 161.601z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M20.6 160.001C20.6 160.001 20.4 158.201 22.2 159.001C24 159.801 48.6 163.201 72.2 195.601C72.2 195.601 36.6 158.801 20.6 160.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M28.225 157.972C28.225 157.972 27.788 156.214 29.678 156.768C31.568 157.322 52.002 155.423 90.099 189.599C90.099 189.599 43.924 154.656 28.225 157.972z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M38.625 153.572C38.625 153.572 38.188 151.814 40.078 152.368C41.968 152.922 76.802 157.423 128.499 192.399C128.499 192.399 54.324 150.256 38.625 153.572z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-1.8 142.001C-1.8 142.001 -2 140.201 -0.2 141.001C1.6 141.801 55 144.401 85.4 171.201C85.4 171.201 50.499 146.426 -1.8 142.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-11.8 146.001C-11.8 146.001 -12 144.201 -10.2 145.001C-8.4 145.801 16.2 149.201 39.8 181.601C39.8 181.601 4.2 144.801 -11.8 146.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M49.503 148.962C49.503 148.962 48.938 147.241 50.864 147.655C52.79 148.068 87.86 150.004 141.981 181.098C141.981 181.098 64.317 146.704 49.503 148.962z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M57.903 146.562C57.903 146.562 57.338 144.841 59.264 145.255C61.19 145.668 96.26 147.604 150.381 178.698C150.381 178.698 73.317 143.904 57.903 146.562z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M67.503 141.562C67.503 141.562 66.938 139.841 68.864 140.255C70.79 140.668 113.86 145.004 203.582 179.298C203.582 179.298 82.917 138.904 67.503 141.562z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M-43.8 148.401C-43.8 148.401 -38.6 148.001 -39.8 149.601C-41 151.201 -43.4 150.401 -43.4 150.401L-43.8 148.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-13 162.401C-13 162.401 -7.8 162.001 -9 163.601C-10.2 165.201 -12.6 164.401 -12.6 164.401L-13 162.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-21.8 162.001C-21.8 162.001 -16.6 161.601 -17.8 163.201C-19 164.801 -21.4 164.001 -21.4 164.001L-21.8 162.001z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-117.169 150.182C-117.169 150.182 -112.124 151.505 -113.782 152.624C-115.439 153.744 -117.446 152.202 -117.446 152.202L-117.169 150.182z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-115.169 140.582C-115.169 140.582 -110.124 141.905 -111.782 143.024C-113.439 144.144 -115.446 142.602 -115.446 142.602L-115.169 140.582z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-122.369 136.182C-122.369 136.182 -117.324 137.505 -118.982 138.624C-120.639 139.744 -122.646 138.202 -122.646 138.202L-122.369 136.182z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-42.6 211.201C-42.6 211.201 -44.2 211.201 -48.2 213.201C-50.2 213.201 -61.4 216.801 -67 226.801C-67 226.801 -54.6 217.201 -42.6 211.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M45.116 303.847C45.257 304.105 45.312 304.525 45.604 304.542C46.262 304.582 47.495 304.883 47.37 304.247C46.522 299.941 45.648 295.004 41.515 293.197C40.876 292.918 39.434 293.331 39.36 294.215C39.233 295.739 39.116 297.088 39.425 298.554C39.725 299.975 41.883 299.985 42.8 298.601C43.736 300.273 44.168 302.116 45.116 303.847z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M34.038 308.581C34.786 309.994 34.659 311.853 36.074 312.416C36.814 312.71 38.664 311.735 38.246 310.661C37.444 308.6 37.056 306.361 35.667 304.55C35.467 304.288 35.707 303.755 35.547 303.427C34.953 302.207 33.808 301.472 32.4 301.801C31.285 304.004 32.433 306.133 33.955 307.842C34.091 307.994 33.925 308.37 34.038 308.581z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-5.564 303.391C-5.672 303.014 -5.71 302.551 -5.545 302.23C-5.014 301.197 -4.221 300.075 -4.558 299.053C-4.906 297.997 -6.022 298.179 -6.672 298.748C-7.807 299.742 -7.856 301.568 -8.547 302.927C-8.743 303.313 -8.692 303.886 -9.133 304.277C-9.607 304.698 -10.047 306.222 -9.951 306.793C-9.898 307.106 -10.081 317.014 -9.859 316.751C-9.24 316.018 -6.19 306.284 -6.121 305.392C-6.064 304.661 -5.332 304.196 -5.564 303.391z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-31.202 296.599C-28.568 294.1 -25.778 291.139 -26.22 287.427C-26.336 286.451 -28.111 286.978 -28.298 287.824C-29.1 291.449 -31.139 294.11 -33.707 296.502C-35.903 298.549 -37.765 304.893 -38 305.401C-34.303 300.145 -32.046 297.399 -31.202 296.599z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-44.776 290.635C-44.253 290.265 -44.555 289.774 -44.338 289.442C-43.385 287.984 -42.084 286.738 -42.066 285C-42.063 284.723 -42.441 284.414 -42.776 284.638C-43.053 284.822 -43.395 284.952 -43.503 285.082C-45.533 287.531 -46.933 290.202 -48.376 293.014C-48.559 293.371 -49.703 297.862 -49.39 297.973C-49.151 298.058 -47.431 293.877 -47.221 293.763C-45.958 293.077 -45.946 291.462 -44.776 290.635z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-28.043 310.179C-27.599 309.31 -26.023 308.108 -26.136 307.219C-26.254 306.291 -25.786 304.848 -26.698 305.536C-27.955 306.484 -31.404 307.833 -31.674 313.641C-31.7 314.212 -28.726 311.519 -28.043 310.179z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-13.6 293.001C-13.2 292.333 -12.492 292.806 -12.033 292.543C-11.385 292.171 -10.774 291.613 -10.482 290.964C-9.512 288.815 -7.743 286.995 -7.6 284.601C-9.091 283.196 -9.77 285.236 -10.4 286.201C-11.723 284.554 -12.722 286.428 -14.022 286.947C-14.092 286.975 -14.305 286.628 -14.38 286.655C-15.557 287.095 -16.237 288.176 -17.235 288.957C-17.406 289.091 -17.811 288.911 -17.958 289.047C-18.61 289.65 -19.583 289.975 -19.863 290.657C-20.973 293.364 -24.113 295.459 -26 303.0 [...]
+					f = "#cccccc";
+					g.createPath("M46.2 347.401C46.2 347.401 53.6 327.001 49.2 315.801C49.2 315.801 60.6 337.401 56 348.601C56 348.601 55.6 338.201 51.6 333.201C51.6 333.201 47.6 346.001 46.2 347.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M31.4 344.801C31.4 344.801 36.8 336.001 28.8 317.601C28.8 317.601 28 338.001 21.2 349.001C21.2 349.001 35.4 328.801 31.4 344.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M21.4 342.801C21.4 342.801 21.2 322.801 21.6 319.801C21.6 319.801 17.8 336.401 7.6 346.001C7.6 346.001 22 334.001 21.4 342.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M11.8 310.801C11.8 310.801 17.8 324.401 7.8 342.801C7.8 342.801 14.2 330.601 9.4 323.601C9.4 323.601 12 320.201 11.8 310.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-7.4 342.401C-7.4 342.401 -8.4 326.801 -6.6 324.601C-6.6 324.601 -6.4 318.201 -6.8 317.201C-6.8 317.201 -2.8 311.001 -2.6 318.401C-2.6 318.401 -1.2 326.201 1.6 330.801C1.6 330.801 5.2 336.201 5 342.601C5 342.601 -5 312.401 -7.4 342.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-11 314.801C-11 314.801 -17.6 325.601 -19.4 344.601C-19.4 344.601 -20.8 338.401 -17 324.001C-17 324.001 -12.8 308.601 -11 314.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-32.8 334.601C-32.8 334.601 -27.8 329.201 -26.4 324.201C-26.4 324.201 -22.8 308.401 -29.2 317.001C-29.2 317.001 -29 325.001 -37.2 332.401C-37.2 332.401 -32.4 330.001 -32.8 334.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-38.6 329.601C-38.6 329.601 -35.2 312.201 -34.4 311.401C-34.4 311.401 -32.6 308.001 -35.4 311.201C-35.4 311.201 -44.2 330.401 -48.2 337.001C-48.2 337.001 -40.2 327.801 -38.6 329.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-44.4 313.001C-44.4 313.001 -32.8 290.601 -54.6 316.401C-54.6 316.401 -43.6 306.601 -44.4 313.001z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-59.8 298.401C-59.8 298.401 -55 279.601 -52.4 279.801C-52.4 279.801 -44.2 270.801 -50.8 281.401C-50.8 281.401 -56.8 291.001 -56.2 300.801C-56.2 300.801 -56.8 291.201 -59.8 298.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M270.5 287C270.5 287 258.5 277 256 273.5C256 273.5 269.5 292 269.5 299C269.5 299 272 291.5 270.5 287z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M276 265C276 265 255 250 251.5 242.5C251.5 242.5 278 272 278 276.5C278 276.5 278.5 267.5 276 265z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M293 111C293 111 281 103 279.5 105C279.5 105 290 111.5 292.5 120C292.5 120 291 111 293 111z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M301.5 191.5L284 179.5C284 179.5 303 196.5 303.5 200.5L301.5 191.5z").setFill(f).setStroke(s);
+					s = "#000000"; f = null;
+					g.createPath("M-89.25 169L-67.25 173.75").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M-39 331C-39 331 -39.5 327.5 -48.5 338").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M-33.5 336C-33.5 336 -31.5 329.5 -38 334").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M20.5 344.5C20.5 344.5 22 333.5 10.5 346.5").setFill(f).setStroke(s);
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+	                scaleTiger();
+                }
+            },
+			{
+				name: "Scale And Rotate Tiger",
+                testType: "perf",
+                trialDuration: 100,
+                trialDelay: 50,
+                trialIterations: 20,
+                setUp: function() {
+                    createSurface();
+					var f, g;
+                    surface.clear();
+					var initial_matrix = dojox.gfx.matrix.translate(250, 250);
+                    matrix = initial_matrix;
+					surface.createRect({x: 0, y: 0, width: 700, height: 700}).setFill("#eee");
+					g = surface.createGroup().setTransform(initial_matrix);
+                    gfxGroup = g;
+					var s = {color: "black", width: 1};
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-118.774 81.262C-118.774 81.262 -119.323 83.078 -120.092 82.779C-120.86 82.481 -119.977 31.675 -140.043 26.801C-140.043 26.801 -120.82 25.937 -118.774 81.262z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-91.284 123.59C-91.284 123.59 -89.648 124.55 -90.118 125.227C-90.589 125.904 -139.763 113.102 -149.218 131.459C-149.218 131.459 -145.539 112.572 -91.284 123.59z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-94.093 133.801C-94.093 133.801 -92.237 134.197 -92.471 134.988C-92.704 135.779 -143.407 139.121 -146.597 159.522C-146.597 159.522 -149.055 140.437 -94.093 133.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-98.304 128.276C-98.304 128.276 -96.526 128.939 -96.872 129.687C-97.218 130.435 -147.866 126.346 -153.998 146.064C-153.998 146.064 -153.646 126.825 -98.304 128.276z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-109.009 110.072C-109.009 110.072 -107.701 111.446 -108.34 111.967C-108.979 112.488 -152.722 86.634 -166.869 101.676C-166.869 101.676 -158.128 84.533 -109.009 110.072z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-116.554 114.263C-116.554 114.263 -115.098 115.48 -115.674 116.071C-116.25 116.661 -162.638 95.922 -174.992 112.469C-174.992 112.469 -168.247 94.447 -116.554 114.263z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-119.154 118.335C-119.154 118.335 -117.546 119.343 -118.036 120.006C-118.526 120.669 -167.308 106.446 -177.291 124.522C-177.291 124.522 -173.066 105.749 -119.154 118.335z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-108.42 118.949C-108.42 118.949 -107.298 120.48 -107.999 120.915C-108.7 121.35 -148.769 90.102 -164.727 103.207C-164.727 103.207 -153.862 87.326 -108.42 118.949z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-128.2 90C-128.2 90 -127.6 91.8 -128.4 92C-129.2 92.2 -157.8 50.2 -177.001 57.8C-177.001 57.8 -161.8 46 -128.2 90z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-127.505 96.979C-127.505 96.979 -126.53 98.608 -127.269 98.975C-128.007 99.343 -164.992 64.499 -182.101 76.061C-182.101 76.061 -169.804 61.261 -127.505 96.979z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.172};
+					g.createPath("M-127.62 101.349C-127.62 101.349 -126.498 102.88 -127.199 103.315C-127.9 103.749 -167.969 72.502 -183.927 85.607C-183.927 85.607 -173.062 69.726 -127.62 101.349z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = "#000000";
+					g.createPath("M-129.83 103.065C-129.327 109.113 -128.339 115.682 -126.6 118.801C-126.6 118.801 -130.2 131.201 -121.4 144.401C-121.4 144.401 -121.8 151.601 -120.2 154.801C-120.2 154.801 -116.2 163.201 -111.4 164.001C-107.516 164.648 -98.793 167.717 -88.932 169.121C-88.932 169.121 -71.8 183.201 -75 196.001C-75 196.001 -75.4 212.401 -79 214.001C-79 214.001 -67.4 202.801 -77 219.601L-81.4 238.401C-81.4 238.401 -55.8 216.801 -71.4 235.201L-81.4 261.201C-81.4 261.201 -61.8 242.801 -69 251 [...]
+					f = "#cc7226"; s = "#000000";
+					g.createPath("M299.717 80.245C300.345 80.426 302.551 81.55 303.801 83.2C303.801 83.2 310.601 94 305.401 75.6C305.401 75.6 296.201 46.8 305.001 58C305.001 58 311.001 65.2 307.801 51.6C303.936 35.173 301.401 28.8 301.401 28.8C301.401 28.8 313.001 33.6 286.201 -6L295.001 -2.4C295.001 -2.4 275.401 -42 253.801 -47.2L245.801 -53.2C245.801 -53.2 284.201 -91.2 271.401 -128C271.401 -128 264.601 -133.2 255.001 -124C255.001 -124 248.601 -119.2 242.601 -120.8C242.601 -120.8 211.801 -119.6 209.8 [...]
+					f = "#cc7226"; s = null;
+					g.createPath("M-115.6 102.6C-140.6 63.2 -126.2 119.601 -126.2 119.601C-117.4 154.001 12.2 116.401 12.2 116.401C12.2 116.401 181.001 86 192.201 82C203.401 78 298.601 84.4 298.601 84.4L293.001 67.6C228.201 21.2 209.001 44.4 195.401 40.4C181.801 36.4 184.201 46 181.001 46.8C177.801 47.6 138.601 22.8 132.201 23.6C125.801 24.4 100.459 0.649 115.401 32.4C131.401 66.4 57 71.6 40.2 60.4C23.4 49.2 47.4 78.8 47.4 78.8C65.8 98.8 31.4 82 31.4 82C-3 69.2 -27 94.8 -30.2 95.6C-33.4 96.4 -38.2 99.6 [...]
+					f = "#e87f3a";
+					g.createPath("M133.51 25.346C127.11 26.146 101.743 2.407 116.71 34.146C133.31 69.346 58.31 73.346 41.51 62.146C24.709 50.946 48.71 80.546 48.71 80.546C67.11 100.546 32.709 83.746 32.709 83.746C-1.691 70.946 -25.691 96.546 -28.891 97.346C-32.091 98.146 -36.891 101.346 -37.691 94.946C-38.491 88.546 -45.87 72.012 -77.691 98.146C-98.927 115.492 -112.418 94.037 -112.418 94.037L-115.618 104.146C-140.618 64.346 -125.546 122.655 -125.546 122.655C-116.745 157.056 13.509 118.146 13.509 118.14 [...]
+					f = "#ea8c4d";
+					g.createPath("M134.819 27.091C128.419 27.891 103.685 3.862 118.019 35.891C134.219 72.092 59.619 75.092 42.819 63.892C26.019 52.692 50.019 82.292 50.019 82.292C68.419 102.292 34.019 85.492 34.019 85.492C-0.381 72.692 -24.382 98.292 -27.582 99.092C-30.782 99.892 -35.582 103.092 -36.382 96.692C-37.182 90.292 -44.43 73.925 -76.382 99.892C-98.855 117.983 -112.036 97.074 -112.036 97.074L-115.636 105.692C-139.436 66.692 -124.891 125.71 -124.891 125.71C-116.091 160.11 14.819 119.892 14.819  [...]
+					f = "#ec9961";
+					g.createPath("M136.128 28.837C129.728 29.637 104.999 5.605 119.328 37.637C136.128 75.193 60.394 76.482 44.128 65.637C27.328 54.437 51.328 84.037 51.328 84.037C69.728 104.037 35.328 87.237 35.328 87.237C0.928 74.437 -23.072 100.037 -26.272 100.837C-29.472 101.637 -34.272 104.837 -35.072 98.437C-35.872 92.037 -42.989 75.839 -75.073 101.637C-98.782 120.474 -111.655 100.11 -111.655 100.11L-115.655 107.237C-137.455 70.437 -124.236 128.765 -124.236 128.765C-115.436 163.165 16.128 121.637  [...]
+					f = "#eea575";
+					g.createPath("M137.438 30.583C131.037 31.383 106.814 7.129 120.637 39.383C137.438 78.583 62.237 78.583 45.437 67.383C28.637 56.183 52.637 85.783 52.637 85.783C71.037 105.783 36.637 88.983 36.637 88.983C2.237 76.183 -21.763 101.783 -24.963 102.583C-28.163 103.383 -32.963 106.583 -33.763 100.183C-34.563 93.783 -41.548 77.752 -73.763 103.383C-98.709 122.965 -111.273 103.146 -111.273 103.146L-115.673 108.783C-135.473 73.982 -123.582 131.819 -123.582 131.819C-114.782 166.22 17.437 123.38 [...]
+					f = "#f1b288";
+					g.createPath("M138.747 32.328C132.347 33.128 106.383 9.677 121.947 41.128C141.147 79.928 63.546 80.328 46.746 69.128C29.946 57.928 53.946 87.528 53.946 87.528C72.346 107.528 37.946 90.728 37.946 90.728C3.546 77.928 -20.454 103.528 -23.654 104.328C-26.854 105.128 -31.654 108.328 -32.454 101.928C-33.254 95.528 -40.108 79.665 -72.454 105.128C-98.636 125.456 -110.891 106.183 -110.891 106.183L-115.691 110.328C-133.691 77.128 -122.927 134.874 -122.927 134.874C-114.127 169.274 18.746 125.1 [...]
+					f = "#f3bf9c";
+					g.createPath("M140.056 34.073C133.655 34.873 107.313 11.613 123.255 42.873C143.656 82.874 64.855 82.074 48.055 70.874C31.255 59.674 55.255 89.274 55.255 89.274C73.655 109.274 39.255 92.474 39.255 92.474C4.855 79.674 -19.145 105.274 -22.345 106.074C-25.545 106.874 -30.345 110.074 -31.145 103.674C-31.945 97.274 -38.668 81.578 -71.145 106.874C-98.564 127.947 -110.509 109.219 -110.509 109.219L-115.709 111.874C-131.709 81.674 -122.273 137.929 -122.273 137.929C-113.473 172.329 20.055 126. [...]
+					f = "#f5ccb0";
+					g.createPath("M141.365 35.819C134.965 36.619 107.523 13.944 124.565 44.619C146.565 84.219 66.164 83.819 49.364 72.619C32.564 61.419 56.564 91.019 56.564 91.019C74.964 111.019 40.564 94.219 40.564 94.219C6.164 81.419 -17.836 107.019 -21.036 107.819C-24.236 108.619 -29.036 111.819 -29.836 105.419C-30.636 99.019 -37.227 83.492 -69.836 108.619C-98.491 130.438 -110.127 112.256 -110.127 112.256L-115.727 113.419C-130.128 85.019 -121.618 140.983 -121.618 140.983C-112.818 175.384 21.364 128. [...]
+					f = "#f8d8c4";
+					g.createPath("M142.674 37.565C136.274 38.365 108.832 15.689 125.874 46.365C147.874 85.965 67.474 85.565 50.674 74.365C33.874 63.165 57.874 92.765 57.874 92.765C76.274 112.765 41.874 95.965 41.874 95.965C7.473 83.165 -16.527 108.765 -19.727 109.565C-22.927 110.365 -27.727 113.565 -28.527 107.165C-29.327 100.765 -35.786 85.405 -68.527 110.365C-98.418 132.929 -109.745 115.293 -109.745 115.293L-115.745 114.965C-129.346 88.564 -120.963 144.038 -120.963 144.038C-112.163 178.438 22.673 130 [...]
+					f = "#fae5d7";
+					g.createPath("M143.983 39.31C137.583 40.11 110.529 17.223 127.183 48.11C149.183 88.91 68.783 87.31 51.983 76.11C35.183 64.91 59.183 94.51 59.183 94.51C77.583 114.51 43.183 97.71 43.183 97.71C8.783 84.91 -15.217 110.51 -18.417 111.31C-21.618 112.11 -26.418 115.31 -27.218 108.91C-28.018 102.51 -34.346 87.318 -67.218 112.11C-98.345 135.42 -109.363 118.329 -109.363 118.329L-115.764 116.51C-128.764 92.51 -120.309 147.093 -120.309 147.093C-111.509 181.493 23.983 132.11 23.983 132.11C23.98 [...]
+					f = "#fcf2eb";
+					g.createPath("M145.292 41.055C138.892 41.855 112.917 18.411 128.492 49.855C149.692 92.656 70.092 89.056 53.292 77.856C36.492 66.656 60.492 96.256 60.492 96.256C78.892 116.256 44.492 99.456 44.492 99.456C10.092 86.656 -13.908 112.256 -17.108 113.056C-20.308 113.856 -25.108 117.056 -25.908 110.656C-26.708 104.256 -32.905 89.232 -65.908 113.856C-98.273 137.911 -108.982 121.365 -108.982 121.365L-115.782 118.056C-128.582 94.856 -119.654 150.147 -119.654 150.147C-110.854 184.547 25.292 13 [...]
+					f = "#ffffff";
+					g.createPath("M-115.8 119.601C-128.6 97.6 -119 153.201 -119 153.201C-110.2 187.601 26.6 135.601 26.6 135.601C26.6 135.601 195.401 105.2 206.601 101.2C217.801 97.2 303.401 102.8 303.401 102.8L298.601 80.4C233.801 34 223.401 63.6 209.801 59.6C196.201 55.6 198.601 65.2 195.401 66C192.201 66.8 153.001 42 146.601 42.8C140.201 43.6 114.981 19.793 129.801 51.6C152.028 99.307 69.041 89.227 54.6 79.6C37.8 68.4 61.8 98 61.8 98C80.2 118.001 45.8 101.2 45.8 101.2C11.4 88.4 -12.6 114.001 -15.8 1 [...]
+					f = "#000000";
+					g.createPath("M-74.2 149.601C-74.2 149.601 -81.4 161.201 -60.6 174.401C-60.6 174.401 -59.2 175.801 -77.2 171.601C-77.2 171.601 -83.4 169.601 -85 159.201C-85 159.201 -89.8 154.801 -94.6 149.201C-99.4 143.601 -74.2 149.601 -74.2 149.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M65.8 102C65.8 102 83.498 128.821 82.9 133.601C81.6 144.001 81.4 153.601 84.6 157.601C87.801 161.601 96.601 194.801 96.601 194.801C96.601 194.801 96.201 196.001 108.601 158.001C108.601 158.001 120.201 142.001 100.201 123.601C100.201 123.601 65 94.8 65.8 102z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-54.2 176.401C-54.2 176.401 -43 183.601 -57.4 214.801L-51 212.401C-51 212.401 -51.8 223.601 -55 226.001L-47.8 222.801C-47.8 222.801 -43 230.801 -47 235.601C-47 235.601 -30.2 243.601 -31 250.001C-31 250.001 -24.6 242.001 -28.6 235.601C-32.6 229.201 -39.8 233.201 -39 214.801L-47.8 218.001C-47.8 218.001 -42.2 209.201 -42.2 202.801L-50.2 205.201C-50.2 205.201 -34.731 178.623 -45.4 177.201C-51.4 176.401 -54.2 176.401 -54.2 176.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-21.8 193.201C-21.8 193.201 -19 188.801 -21.8 189.601C-24.6 190.401 -55.8 205.201 -61.8 214.801C-61.8 214.801 -27.4 190.401 -21.8 193.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-11.4 201.201C-11.4 201.201 -8.6 196.801 -11.4 197.601C-14.2 198.401 -45.4 213.201 -51.4 222.801C-51.4 222.801 -17 198.401 -11.4 201.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M1.8 186.001C1.8 186.001 4.6 181.601 1.8 182.401C-1 183.201 -32.2 198.001 -38.2 207.601C-38.2 207.601 -3.8 183.201 1.8 186.001z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-21.4 229.601C-21.4 229.601 -21.4 223.601 -24.2 224.401C-27 225.201 -63 242.801 -69 252.401C-69 252.401 -27 226.801 -21.4 229.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-20.2 218.801C-20.2 218.801 -19 214.001 -21.8 214.801C-23.8 214.801 -50.2 226.401 -56.2 236.001C-56.2 236.001 -26.6 214.401 -20.2 218.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-34.6 266.401L-44.6 274.001C-44.6 274.001 -34.2 266.401 -30.6 267.601C-30.6 267.601 -37.4 278.801 -38.2 284.001C-38.2 284.001 -27.8 271.201 -22.2 271.601C-22.2 271.601 -14.6 272.001 -14.6 282.801C-14.6 282.801 -9 272.401 -5.8 272.801C-5.8 272.801 -4.6 279.201 -5.8 286.001C-5.8 286.001 -1.8 278.401 2.2 280.001C2.2 280.001 8.6 278.001 7.8 289.601C7.8 289.601 7.8 300.001 7 302.801C7 302.801 12.6 276.401 15 276.001C15 276.001 23 274.801 27.8 283.601C27.8 283.601 23.8 276. [...]
+					f = "#000000";
+					g.createPath("M-29.8 173.601C-29.8 173.601 -15 167.601 25 173.601C25 173.601 32.2 174.001 39 165.201C45.8 156.401 72.6 149.201 79 151.201L88.601 157.601L89.401 158.801C89.401 158.801 101.801 169.201 102.201 176.801C102.601 184.401 87.801 232.401 78.2 248.401C68.6 264.401 59 276.801 39.8 274.401C39.8 274.401 19 270.401 -6.6 274.401C-6.6 274.401 -35.8 272.801 -38.6 264.801C-41.4 256.801 -27.4 241.601 -27.4 241.601C-27.4 241.601 -23 233.201 -24.2 218.801C-25.4 204.401 -25 176.401 -29.8 [...]
+					f = "#e5668c";
+					g.createPath("M-7.8 175.601C0.6 194.001 -29 259.201 -29 259.201C-31 260.801 -16.34 266.846 -6.2 264.401C4.746 261.763 45 266.001 45 266.001C68.6 250.401 81.4 206.001 81.4 206.001C81.4 206.001 91.801 182.001 74.2 178.801C56.6 175.601 -7.8 175.601 -7.8 175.601z").setFill(f).setStroke(s);
+					f = "#b23259";
+					g.createPath("M-9.831 206.497C-6.505 193.707 -4.921 181.906 -7.8 175.601C-7.8 175.601 54.6 182.001 65.8 161.201C70.041 153.326 84.801 184.001 84.4 193.601C84.4 193.601 21.4 208.001 6.6 196.801L-9.831 206.497z").setFill(f).setStroke(s);
+					f = "#a5264c";
+					g.createPath("M-5.4 222.801C-5.4 222.801 -3.4 230.001 -5.8 234.001C-5.8 234.001 -7.4 234.801 -8.6 235.201C-8.6 235.201 -7.4 238.801 -1.4 240.401C-1.4 240.401 0.6 244.801 3 245.201C5.4 245.601 10.2 251.201 14.2 250.001C18.2 248.801 29.4 244.801 29.4 244.801C29.4 244.801 35 241.601 43.8 245.201C43.8 245.201 46.175 244.399 46.6 240.401C47.1 235.701 50.2 232.001 52.2 230.001C54.2 228.001 63.8 215.201 62.6 214.801C61.4 214.401 -5.4 222.801 -5.4 222.801z").setFill(f).setStroke(s);
+					f = "#ff727f"; s = "#000000";
+					g.createPath("M-9.8 174.401C-9.8 174.401 -12.6 196.801 -9.4 205.201C-6.2 213.601 -7 215.601 -7.8 219.601C-8.6 223.601 -4.2 233.601 1.4 239.601L13.4 241.201C13.4 241.201 28.6 237.601 37.8 240.401C37.8 240.401 46.794 241.744 50.2 226.801C50.2 226.801 55 220.401 62.2 217.601C69.4 214.801 76.6 173.201 72.6 165.201C68.6 157.201 54.2 152.801 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-8.2 249.201C-8.2 249.201 -9 247.201 -13.4 246.801C-13.4 246.801 -35.8 243.201 -44.2 230.801C-44.2 230.801 -51 225.201 -46.6 236.801C-46.6 236.801 -36.2 257.201 -29.4 260.001C-29.4 260.001 -13 264.001 -8.2 249.201z").setFill(f).setStroke(s);
+					f = "#cc3f4c"; s = null;
+					g.createPath("M71.742 185.229C72.401 177.323 74.354 168.709 72.6 165.201C66.154 152.307 49.181 157.695 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401C-9.8 174.401 -11.545 188.364 -10.705 198.376C-10.705 198.376 26.6 186.801 27.4 192.401C27.4 192.401 29 189.201 38.2 189.201C47.4 189.201 70.142 188.029 71.742 185.229z").setFill(f).setStroke(s);
+					s = {color: "#a51926", width: 2}; f = null;
+					g.createPath("M28.6 175.201C28.6 175.201 33.4 180.001 29.8 189.601C29.8 189.601 15.4 205.601 17.4 219.601").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-19.4 260.001C-19.4 260.001 -23.8 247.201 -15 254.001C-15 254.001 -10.2 256.001 -11.4 257.601C-12.6 259.201 -18.2 263.201 -19.4 260.001z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-14.36 261.201C-14.36 261.201 -17.88 250.961 -10.84 256.401C-10.84 256.401 -6.419 258.849 -7.96 259.281C-12.52 260.561 -7.96 263.121 -14.36 261.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-9.56 261.201C-9.56 261.201 -13.08 250.961 -6.04 256.401C-6.04 256.401 -1.665 258.711 -3.16 259.281C-6.52 260.561 -3.16 263.121 -9.56 261.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-2.96 261.401C-2.96 261.401 -6.48 251.161 0.56 256.601C0.56 256.601 4.943 258.933 3.441 259.481C0.48 260.561 3.441 263.321 -2.96 261.401z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M3.52 261.321C3.52 261.321 0 251.081 7.041 256.521C7.041 256.521 10.881 258.121 9.921 259.401C8.961 260.681 9.921 263.241 3.52 261.321z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M10.2 262.001C10.2 262.001 5.4 249.601 14.6 256.001C14.6 256.001 19.4 258.001 18.2 259.601C17 261.201 18.2 264.401 10.2 262.001z").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2}; f = null;
+					g.createPath("M-18.2 244.801C-18.2 244.801 -5 242.001 1 245.201C1 245.201 7 246.401 8.2 246.001C9.4 245.601 12.6 245.201 12.6 245.201").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2};
+					g.createPath("M15.8 253.601C15.8 253.601 27.8 240.001 39.8 244.401C46.816 246.974 45.8 243.601 46.6 240.801C47.4 238.001 47.6 233.801 52.6 230.801").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M33 237.601C33 237.601 29 226.801 26.2 239.601C23.4 252.401 20.2 256.001 18.6 258.801C18.6 258.801 18.6 264.001 27 263.601C27 263.601 37.8 263.201 38.2 260.401C38.6 257.601 37 246.001 33 237.601z").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2}; f = null;
+					g.createPath("M47 244.801C47 244.801 50.6 242.401 53 243.601").setFill(f).setStroke(s);
+					s = {color: "#a5264c", width: 2};
+					g.createPath("M53.5 228.401C53.5 228.401 56.4 223.501 61.2 222.701").setFill(f).setStroke(s);
+					f = "#b2b2b2"; s = null;
+					g.createPath("M-25.8 265.201C-25.8 265.201 -7.8 268.401 -3.4 266.801C-3.4 266.801 5.4 266.801 -3 268.801C-3 268.801 -15.8 268.801 -23.8 267.601C-23.8 267.601 -35.4 262.001 -25.8 265.201z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-11.8 172.001C-11.8 172.001 5.8 172.001 7.8 172.801C7.8 172.801 15 203.601 11.4 211.201C11.4 211.201 10.2 214.001 7.4 208.401C7.4 208.401 -11 175.601 -14.2 173.601C-17.4 171.601 -13 172.001 -11.8 172.001z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-88.9 169.301C-88.9 169.301 -80 171.001 -67.4 173.601C-67.4 173.601 -62.6 196.001 -59.4 200.801C-56.2 205.601 -59.8 205.601 -63.4 202.801C-67 200.001 -81.8 186.001 -83.8 181.601C-85.8 177.201 -88.9 169.301 -88.9 169.301z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-67.039 173.818C-67.039 173.818 -61.239 175.366 -60.23 177.581C-59.222 179.795 -61.432 183.092 -61.432 183.092C-61.432 183.092 -62.432 186.397 -63.634 184.235C-64.836 182.072 -67.708 174.412 -67.039 173.818z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M-67 173.601C-67 173.601 -63.4 178.801 -59.8 178.801C-56.2 178.801 -55.818 178.388 -53 179.001C-48.4 180.001 -48.8 178.001 -42.2 179.201C-39.56 179.681 -37 178.801 -34.2 180.001C-31.4 181.201 -28.2 180.401 -27 178.401C-25.8 176.401 -21 172.201 -21 172.201C-21 172.201 -33.8 174.001 -36.6 174.801C-36.6 174.801 -59 176.001 -67 173.601z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-22.4 173.801C-22.4 173.801 -28.85 177.301 -29.25 179.701C-29.65 182.101 -24 185.801 -24 185.801C-24 185.801 -21.25 190.401 -20.65 188.001C-20.05 185.601 -21.6 174.201 -22.4 173.801z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-59.885 179.265C-59.885 179.265 -52.878 190.453 -52.661 179.242C-52.661 179.242 -52.104 177.984 -53.864 177.962C-59.939 177.886 -58.418 173.784 -59.885 179.265z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-52.707 179.514C-52.707 179.514 -44.786 190.701 -45.422 179.421C-45.422 179.421 -45.415 179.089 -47.168 178.936C-51.915 178.522 -51.57 174.004 -52.707 179.514z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-45.494 179.522C-45.494 179.522 -37.534 190.15 -38.203 180.484C-38.203 180.484 -38.084 179.251 -39.738 178.95C-43.63 178.244 -43.841 174.995 -45.494 179.522z").setFill(f).setStroke(s);
+					f = "#ffffcc"; s = {color: "#000000", width: 0.5};
+					g.createPath("M-38.618 179.602C-38.618 179.602 -30.718 191.163 -30.37 181.382C-30.37 181.382 -28.726 180.004 -30.472 179.782C-36.29 179.042 -35.492 174.588 -38.618 179.602z").setFill(f).setStroke(s);
+					f = "#e5e5b2"; s = null;
+					g.createPath("M-74.792 183.132L-82.45 181.601C-85.05 176.601 -87.15 170.451 -87.15 170.451C-87.15 170.451 -80.8 171.451 -68.3 174.251C-68.3 174.251 -67.424 177.569 -65.952 183.364L-74.792 183.132z").setFill(f).setStroke(s);
+					f = "#e5e5b2";
+					g.createPath("M-9.724 178.47C-11.39 175.964 -12.707 174.206 -13.357 173.8C-16.37 171.917 -12.227 172.294 -11.098 172.294C-11.098 172.294 5.473 172.294 7.356 173.047C7.356 173.047 7.88 175.289 8.564 178.68C8.564 178.68 -1.524 176.67 -9.724 178.47z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M43.88 40.321C71.601 44.281 97.121 8.641 98.881 -1.04C100.641 -10.72 90.521 -22.6 90.521 -22.6C91.841 -25.68 87.001 -39.76 81.721 -49C76.441 -58.24 60.54 -57.266 43 -58.24C27.16 -59.12 8.68 -35.8 7.36 -34.04C6.04 -32.28 12.2 6.001 13.52 11.721C14.84 17.441 12.2 43.841 12.2 43.841C46.44 34.741 16.16 36.361 43.88 40.321z").setFill(f).setStroke(s);
+					f = "#ea8e51";
+					g.createPath("M8.088 -33.392C6.792 -31.664 12.84 5.921 14.136 11.537C15.432 17.153 12.84 43.073 12.84 43.073C45.512 34.193 16.728 35.729 43.944 39.617C71.161 43.505 96.217 8.513 97.945 -0.992C99.673 -10.496 89.737 -22.16 89.737 -22.16C91.033 -25.184 86.281 -39.008 81.097 -48.08C75.913 -57.152 60.302 -56.195 43.08 -57.152C27.528 -58.016 9.384 -35.12 8.088 -33.392z").setFill(f).setStroke(s);
+					f = "#efaa7c";
+					g.createPath("M8.816 -32.744C7.544 -31.048 13.48 5.841 14.752 11.353C16.024 16.865 13.48 42.305 13.48 42.305C44.884 33.145 17.296 35.097 44.008 38.913C70.721 42.729 95.313 8.385 97.009 -0.944C98.705 -10.272 88.953 -21.72 88.953 -21.72C90.225 -24.688 85.561 -38.256 80.473 -47.16C75.385 -56.064 60.063 -55.125 43.16 -56.064C27.896 -56.912 10.088 -34.44 8.816 -32.744z").setFill(f).setStroke(s);
+					f = "#f4c6a8";
+					g.createPath("M9.544 -32.096C8.296 -30.432 14.12 5.761 15.368 11.169C16.616 16.577 14.12 41.537 14.12 41.537C43.556 32.497 17.864 34.465 44.072 38.209C70.281 41.953 94.409 8.257 96.073 -0.895C97.737 -10.048 88.169 -21.28 88.169 -21.28C89.417 -24.192 84.841 -37.504 79.849 -46.24C74.857 -54.976 59.824 -54.055 43.24 -54.976C28.264 -55.808 10.792 -33.76 9.544 -32.096z").setFill(f).setStroke(s);
+					f = "#f9e2d3";
+					g.createPath("M10.272 -31.448C9.048 -29.816 14.76 5.681 15.984 10.985C17.208 16.289 14.76 40.769 14.76 40.769C42.628 31.849 18.432 33.833 44.136 37.505C69.841 41.177 93.505 8.129 95.137 -0.848C96.769 -9.824 87.385 -20.84 87.385 -20.84C88.609 -23.696 84.121 -36.752 79.225 -45.32C74.329 -53.888 59.585 -52.985 43.32 -53.888C28.632 -54.704 11.496 -33.08 10.272 -31.448z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M44.2 36.8C69.4 40.4 92.601 8 94.201 -0.8C95.801 -9.6 86.601 -20.4 86.601 -20.4C87.801 -23.2 83.4 -36 78.6 -44.4C73.8 -52.8 59.346 -51.914 43.4 -52.8C29 -53.6 12.2 -32.4 11 -30.8C9.8 -29.2 15.4 5.6 16.6 10.8C17.8 16 15.4 40 15.4 40C40.9 31.4 19 33.2 44.2 36.8z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M90.601 2.8C90.601 2.8 62.8 10.4 51.2 8.8C51.2 8.8 35.4 2.2 26.6 24C26.6 24 23 31.2 21 33.2C19 35.2 90.601 2.8 90.601 2.8z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M94.401 0.6C94.401 0.6 65.4 12.8 55.4 12.4C55.4 12.4 39 7.8 30.6 22.4C30.6 22.4 22.2 31.6 19 33.2C19 33.2 18.6 34.8 25 30.8L35.4 36C35.4 36 50.2 45.6 59.8 29.6C59.8 29.6 63.8 18.4 63.8 16.4C63.8 14.4 85 8.8 86.601 8.4C88.201 8 94.801 3.8 94.401 0.6z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M47 36.514C40.128 36.514 31.755 32.649 31.755 26.4C31.755 20.152 40.128 13.887 47 13.887C53.874 13.887 59.446 18.952 59.446 25.2C59.446 31.449 53.874 36.514 47 36.514z").setFill(f).setStroke(s);
+					f = "#659900";
+					g.createPath("M43.377 19.83C38.531 20.552 33.442 22.055 33.514 21.839C35.054 17.22 41.415 13.887 47 13.887C51.296 13.887 55.084 15.865 57.32 18.875C57.32 18.875 52.004 18.545 43.377 19.83z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M55.4 19.6C55.4 19.6 51 16.4 51 18.6C51 18.6 54.6 23 55.4 19.6z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M45.4 27.726C42.901 27.726 40.875 25.7 40.875 23.2C40.875 20.701 42.901 18.675 45.4 18.675C47.9 18.675 49.926 20.701 49.926 23.2C49.926 25.7 47.9 27.726 45.4 27.726z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M-58.6 14.4C-58.6 14.4 -61.8 -6.8 -59.4 -11.2C-59.4 -11.2 -48.6 -21.2 -49 -24.8C-49 -24.8 -49.4 -42.8 -50.6 -43.6C-51.8 -44.4 -59.4 -50.4 -65.4 -44C-65.4 -44 -75.8 -26 -75 -19.6L-75 -17.6C-75 -17.6 -82.6 -18 -84.2 -16C-84.2 -16 -85.4 -10.8 -86.6 -10.4C-86.6 -10.4 -89.4 -8 -87.4 -5.2C-87.4 -5.2 -89.4 -2.8 -89 1.2L-81.4 5.2C-81.4 5.2 -79.4 19.6 -68.6 24.8C-63.764 27.129 -60.6 20.4 -58.6 14.4z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M-59.6 12.56C-59.6 12.56 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.48 -40.36 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.96 -59.6 12.56z").setF [...]
+					f = "#eb955c";
+					g.createPath("M-51.05 -42.61C-52.14 -43.47 -59.63 -49.24 -65.48 -43C-65.48 -43 -75.62 -25.45 -74.84 -19.21L-74.84 -17.26C-74.84 -17.26 -82.25 -17.65 -83.81 -15.7C-83.81 -15.7 -84.98 -10.63 -86.15 -10.24C-86.15 -10.24 -88.88 -7.9 -86.93 -5.17C-86.93 -5.17 -88.88 -2.83 -88.49 1.07L-81.08 4.97C-81.08 4.97 -79.13 19.01 -68.6 24.08C-63.886 26.35 -60.8 19.79 -58.85 13.94C-58.85 13.94 -61.97 -6.73 -59.63 -11.02C-59.63 -11.02 -49.1 -20.77 -49.49 -24.28C-49.49 -24.28 -49.88 -41.83 -51.05 -42 [...]
+					f = "#f2b892";
+					g.createPath("M-51.5 -41.62C-52.48 -42.54 -59.86 -48.08 -65.56 -42C-65.56 -42 -75.44 -24.9 -74.68 -18.82L-74.68 -16.92C-74.68 -16.92 -81.9 -17.3 -83.42 -15.4C-83.42 -15.4 -84.56 -10.46 -85.7 -10.08C-85.7 -10.08 -88.36 -7.8 -86.46 -5.14C-86.46 -5.14 -88.36 -2.86 -87.98 0.94L-80.76 4.74C-80.76 4.74 -78.86 18.42 -68.6 23.36C-64.006 25.572 -61 19.18 -59.1 13.48C-59.1 13.48 -62.14 -6.66 -59.86 -10.84C-59.86 -10.84 -49.6 -20.34 -49.98 -23.76C-49.98 -23.76 -50.36 -40.86 -51.5 -41.62z").set [...]
+					f = "#f8dcc8";
+					g.createPath("M-51.95 -40.63C-52.82 -41.61 -60.09 -46.92 -65.64 -41C-65.64 -41 -75.26 -24.35 -74.52 -18.43L-74.52 -16.58C-74.52 -16.58 -81.55 -16.95 -83.03 -15.1C-83.03 -15.1 -84.14 -10.29 -85.25 -9.92C-85.25 -9.92 -87.84 -7.7 -85.99 -5.11C-85.99 -5.11 -87.84 -2.89 -87.47 0.81L-80.44 4.51C-80.44 4.51 -78.59 17.83 -68.6 22.64C-64.127 24.794 -61.2 18.57 -59.35 13.02C-59.35 13.02 -62.31 -6.59 -60.09 -10.66C-60.09 -10.66 -50.1 -19.91 -50.47 -23.24C-50.47 -23.24 -50.84 -39.89 -51.95 -40. [...]
+					f = "#ffffff";
+					g.createPath("M-59.6 12.46C-59.6 12.46 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.16 -40.68 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.86 -59.6 12.46z").setF [...]
+					f = "#cccccc";
+					g.createPath("M-62.7 6.2C-62.7 6.2 -84.3 -4 -85.2 -4.8C-85.2 -4.8 -76.1 3.4 -75.3 3.4C-74.5 3.4 -62.7 6.2 -62.7 6.2z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-79.8 0C-79.8 0 -61.4 3.6 -61.4 8C-61.4 10.912 -61.643 24.331 -67 22.8C-75.4 20.4 -71.8 6 -79.8 0z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M-71.4 3.8C-71.4 3.8 -62.422 5.274 -61.4 8C-60.8 9.6 -60.137 17.908 -65.6 19C-70.152 19.911 -72.382 9.69 -71.4 3.8z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M14.595 46.349C14.098 44.607 15.409 44.738 17.2 44.2C19.2 43.6 31.4 39.8 32.2 37.2C33 34.6 46.2 39 46.2 39C48 39.8 52.4 42.4 52.4 42.4C57.2 43.6 63.8 44 63.8 44C66.2 45 69.6 47.8 69.6 47.8C84.2 58 96.601 50.8 96.601 50.8C116.601 44.2 110.601 27 110.601 27C107.601 18 110.801 14.6 110.801 14.6C111.001 10.8 118.201 17.2 118.201 17.2C120.801 21.4 121.601 26.4 121.601 26.4C129.601 37.6 126.201 19.8 126.201 19.8C126.401 18.8 123.601 15.2 123.601 14C123.601 12.8 121.801 9.4 1 [...]
+					f = "#000000";
+					g.createPath("M209.401 -120C209.401 -120 183.801 -112 181.001 -93.2C181.001 -93.2 178.601 -70.4 199.001 -52.8C199.001 -52.8 199.401 -46.4 201.401 -43.2C201.401 -43.2 199.801 -38.4 218.601 -46L245.801 -54.4C245.801 -54.4 252.201 -56.8 257.401 -65.6C262.601 -74.4 277.801 -93.2 274.201 -118.4C274.201 -118.4 275.401 -129.6 269.401 -130C269.401 -130 261.001 -131.6 253.801 -124C253.801 -124 247.001 -120.8 244.601 -121.2L209.401 -120z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M264.022 -120.99C264.022 -120.99 266.122 -129.92 261.282 -125.08C261.282 -125.08 254.242 -119.36 246.761 -119.36C246.761 -119.36 232.241 -117.16 227.841 -103.96C227.841 -103.96 223.881 -77.12 231.801 -71.4C231.801 -71.4 236.641 -63.92 243.681 -70.52C250.722 -77.12 266.222 -107.35 264.022 -120.99z").setFill(f).setStroke(s);
+					f = "#323232";
+					g.createPath("M263.648 -120.632C263.648 -120.632 265.738 -129.376 260.986 -124.624C260.986 -124.624 254.074 -119.008 246.729 -119.008C246.729 -119.008 232.473 -116.848 228.153 -103.888C228.153 -103.888 224.265 -77.536 232.041 -71.92C232.041 -71.92 236.793 -64.576 243.705 -71.056C250.618 -77.536 265.808 -107.24 263.648 -120.632z").setFill(f).setStroke(s);
+					f = "#666666";
+					g.createPath("M263.274 -120.274C263.274 -120.274 265.354 -128.832 260.69 -124.168C260.69 -124.168 253.906 -118.656 246.697 -118.656C246.697 -118.656 232.705 -116.536 228.465 -103.816C228.465 -103.816 224.649 -77.952 232.281 -72.44C232.281 -72.44 236.945 -65.232 243.729 -71.592C250.514 -77.952 265.394 -107.13 263.274 -120.274z").setFill(f).setStroke(s);
+					f = "#999999";
+					g.createPath("M262.9 -119.916C262.9 -119.916 264.97 -128.288 260.394 -123.712C260.394 -123.712 253.738 -118.304 246.665 -118.304C246.665 -118.304 232.937 -116.224 228.777 -103.744C228.777 -103.744 225.033 -78.368 232.521 -72.96C232.521 -72.96 237.097 -65.888 243.753 -72.128C250.41 -78.368 264.98 -107.02 262.9 -119.916z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M262.526 -119.558C262.526 -119.558 264.586 -127.744 260.098 -123.256C260.098 -123.256 253.569 -117.952 246.633 -117.952C246.633 -117.952 233.169 -115.912 229.089 -103.672C229.089 -103.672 225.417 -78.784 232.761 -73.48C232.761 -73.48 237.249 -66.544 243.777 -72.664C250.305 -78.784 264.566 -106.91 262.526 -119.558z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M262.151 -119.2C262.151 -119.2 264.201 -127.2 259.801 -122.8C259.801 -122.8 253.401 -117.6 246.601 -117.6C246.601 -117.6 233.401 -115.6 229.401 -103.6C229.401 -103.6 225.801 -79.2 233.001 -74C233.001 -74 237.401 -67.2 243.801 -73.2C250.201 -79.2 264.151 -106.8 262.151 -119.2z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M50.6 84C50.6 84 30.2 64.8 22.2 64C22.2 64 -12.2 60 -27 78C-27 78 -9.4 57.6 18.2 63.2C18.2 63.2 -3.4 58.8 -15.8 62C-15.8 62 -32.6 62 -42.2 76L-45 80.8C-45 80.8 -41 66 -22.6 60C-22.6 60 0.2 55.2 11 60C11 60 -10.6 53.2 -20.6 55.2C-20.6 55.2 -51 52.8 -63.8 79.2C-63.8 79.2 -59.8 64.8 -45 57.6C-45 57.6 -31.4 48.8 -11 51.6C-11 51.6 3.4 54.8 8.6 57.2C13.8 59.6 12.6 56.8 4.2 52C4.2 52 -1.4 42 -15.4 42.4C-15.4 42.4 -58.2 46 -68.6 58C-68.6 58 -55 46.8 -44.6 44C-44.6 44 -22.2 36  [...]
+					f = "#cccccc";
+					g.createPath("M189 278C189 278 173.5 241.5 161 232C161 232 187 248 190.5 266C190.5 266 190.5 276 189 278z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M236 285.5C236 285.5 209.5 230.5 191 206.5C191 206.5 234.5 244 239.5 270.5L240 276L237 273.5C237 273.5 236.5 282.5 236 285.5z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M292.5 237C292.5 237 230 177.5 228.5 175C228.5 175 289 241 292 248.5C292 248.5 290 239.5 292.5 237z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M104 280.5C104 280.5 123.5 228.5 142.5 251C142.5 251 157.5 261 157 264C157 264 153 257.5 135 258C135 258 116 255 104 280.5z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M294.5 153C294.5 153 249.5 124.5 242 123C230.193 120.639 291.5 152 296.5 162.5C296.5 162.5 298.5 160 294.5 153z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M143.801 259.601C143.801 259.601 164.201 257.601 171.001 250.801L175.401 254.401L193.001 216.001L196.601 221.201C196.601 221.201 211.001 206.401 210.201 198.401C209.401 190.401 223.001 204.401 223.001 204.401C223.001 204.401 222.201 192.801 229.401 199.601C229.401 199.601 227.001 184.001 235.401 192.001C235.401 192.001 224.864 161.844 247.401 187.601C253.001 194.001 248.601 187.201 248.601 187.201C248.601 187.201 222.601 139.201 244.201 153.601C244.201 153.601 246.201  [...]
+					f = "#000000";
+					g.createPath("M109.401 -97.2C109.401 -97.2 97.801 -105.2 93.801 -104.8C89.801 -104.4 121.401 -113.6 162.601 -86C162.601 -86 167.401 -83.2 171.001 -83.6C171.001 -83.6 174.201 -81.2 171.401 -77.6C171.401 -77.6 162.601 -68 173.801 -56.8C173.801 -56.8 192.201 -50 186.601 -58.8C186.601 -58.8 197.401 -54.8 199.801 -50.8C202.201 -46.8 201.001 -50.8 201.001 -50.8C201.001 -50.8 194.601 -58 188.601 -63.2C188.601 -63.2 183.401 -65.2 180.601 -73.6C177.801 -82 175.401 -92 179.801 -95.2C179.801 - [...]
+					f = "#cc7226";
+					g.createPath("M180.801 -106.4C180.801 -106.4 170.601 -113.8 168.601 -113.8C166.601 -113.8 154.201 -124 150.001 -123.6C145.801 -123.2 133.601 -133.2 106.201 -125C106.201 -125 105.601 -127 109.201 -127.8C109.201 -127.8 115.601 -130 116.001 -130.6C116.001 -130.6 136.201 -134.8 143.401 -131.2C143.401 -131.2 152.601 -128.6 158.801 -122.4C158.801 -122.4 170.001 -119.2 173.201 -120.2C173.201 -120.2 182.001 -118 182.401 -116.2C182.401 -116.2 188.201 -113.2 186.401 -110.6C186.401 -110.6 186. [...]
+					f = "#cc7226";
+					g.createPath("M168.33 -108.509C169.137 -107.877 170.156 -107.779 170.761 -106.97C170.995 -106.656 170.706 -106.33 170.391 -106.233C169.348 -105.916 168.292 -106.486 167.15 -105.898C166.748 -105.691 166.106 -105.873 165.553 -106.022C163.921 -106.463 162.092 -106.488 160.401 -105.8C158.416 -106.929 156.056 -106.345 153.975 -107.346C153.917 -107.373 153.695 -107.027 153.621 -107.054C150.575 -108.199 146.832 -107.916 144.401 -110.2C141.973 -110.612 139.616 -111.074 137.188 -111.754C135. [...]
+					f = "#cc7226";
+					g.createPath("M91.696 -122.739C89.178 -124.464 86.81 -125.57 84.368 -127.356C84.187 -127.489 83.827 -127.319 83.625 -127.441C82.618 -128.05 81.73 -128.631 80.748 -129.327C80.209 -129.709 79.388 -129.698 78.88 -129.956C76.336 -131.248 73.707 -131.806 71.2 -133C71.882 -133.638 73.004 -133.394 73.6 -134.2C73.795 -133.92 74.033 -133.636 74.386 -133.827C76.064 -134.731 77.914 -134.884 79.59 -134.794C81.294 -134.702 83.014 -134.397 84.789 -134.125C85.096 -134.078 85.295 -133.555 85.618 -1 [...]
+					f = "#cc7226";
+					g.createPath("M59.198 -115.391C56.044 -116.185 52.994 -116.07 49.978 -117.346C49.911 -117.374 49.688 -117.027 49.624 -117.054C48.258 -117.648 47.34 -118.614 46.264 -119.66C45.351 -120.548 43.693 -120.161 42.419 -120.648C42.095 -120.772 41.892 -121.284 41.591 -121.323C40.372 -121.48 39.445 -122.429 38.4 -123C40.736 -123.795 43.147 -123.764 45.609 -124.148C45.722 -124.166 45.867 -123.845 46 -123.845C46.136 -123.845 46.266 -124.066 46.4 -124.2C46.595 -123.92 46.897 -123.594 47.154 -123 [...]
+					f = "#cc7226";
+					g.createPath("M45.338 -71.179C43.746 -72.398 43.162 -74.429 42.034 -76.221C41.82 -76.561 42.094 -76.875 42.411 -76.964C42.971 -77.123 43.514 -76.645 43.923 -76.443C45.668 -75.581 47.203 -74.339 49.2 -74.2C51.19 -71.966 55.45 -71.581 55.457 -68.2C55.458 -67.341 54.03 -68.259 53.6 -67.4C51.149 -68.403 48.76 -68.3 46.38 -69.767C45.763 -70.148 46.093 -70.601 45.338 -71.179z").setFill(f).setStroke(s);
+					f = "#cc7226";
+					g.createPath("M17.8 -123.756C17.935 -123.755 24.966 -123.522 24.949 -123.408C24.904 -123.099 17.174 -122.05 16.81 -122.22C16.646 -122.296 9.134 -119.866 9 -120C9.268 -120.135 17.534 -123.756 17.8 -123.756z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M33.2 -114C33.2 -114 18.4 -112.2 14 -111C9.6 -109.8 -9 -102.2 -12 -100.2C-12 -100.2 -25.4 -94.8 -42.4 -74.8C-42.4 -74.8 -34.8 -78.2 -32.6 -81C-32.6 -81 -19 -93.6 -19.2 -91C-19.2 -91 -7 -99.6 -7.6 -97.4C-7.6 -97.4 16.8 -108.6 14.8 -105.4C14.8 -105.4 36.4 -110 35.4 -108C35.4 -108 54.2 -103.6 51.4 -103.4C51.4 -103.4 45.6 -102.2 52 -98.6C52 -98.6 48.6 -94.2 43.2 -98.2C37.8 -102.2 40.8 -100 35.8 -99C35.8 -99 33.2 -98.2 28.6 -102.2C28.6 -102.2 23 -106.8 14.2 -103.2C14.2 -103 [...]
+					s = {color: "#4c0000", width: 2}; f = null;
+					g.createPath("M51.4 85C51.4 85 36.4 68.2 28 65.6C28 65.6 14.6 58.8 -10 66.6").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M24.8 64.2C24.8 64.2 -0.4 56.2 -15.8 60.4C-15.8 60.4 -34.2 62.4 -42.6 76.2").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M21.2 63C21.2 63 4.2 55.8 -10.6 53.6C-10.6 53.6 -27.2 51 -43.8 58.2C-43.8 58.2 -56 64.2 -61.4 74.4").setFill(f).setStroke(s);
+					s = {color: "#4c0000", width: 2};
+					g.createPath("M22.2 63.4C22.2 63.4 6.8 52.4 5.8 51C5.8 51 -1.2 40 -14.2 39.6C-14.2 39.6 -35.6 40.4 -52.8 48.4").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M20.895 54.407C22.437 55.87 49.4 84.8 49.4 84.8C84.6 121.401 56.6 87.2 56.6 87.2C49 82.4 39.8 63.6 39.8 63.6C38.6 60.8 53.8 70.8 53.8 70.8C57.8 71.6 71.4 90.8 71.4 90.8C64.6 88.4 69.4 95.6 69.4 95.6C72.2 97.6 92.601 113.201 92.601 113.201C96.201 117.201 100.201 118.801 100.201 118.801C114.201 113.601 107.801 126.801 107.801 126.801C110.201 133.601 115.801 122.001 115.801 122.001C127.001 105.2 110.601 107.601 110.601 107.601C80.6 110.401 73.8 94.4 73.8 94.4C71.4 92 80.2 [...]
+					f = "#4c0000";
+					g.createPath("M-3 42.8C-3 42.8 8.6 48.4 11.2 51.2C13.8 54 27.8 65.4 27.8 65.4C27.8 65.4 22.4 63.4 19.8 61.6C17.2 59.8 6.4 51.6 6.4 51.6C6.4 51.6 2.6 45.6 -3 42.8z").setFill(f).setStroke(s);
+					f = "#99cc32";
+					g.createPath("M-61.009 11.603C-60.672 11.455 -61.196 8.743 -61.4 8.2C-62.422 5.474 -71.4 4 -71.4 4C-71.627 5.365 -71.682 6.961 -71.576 8.599C-71.576 8.599 -66.708 14.118 -61.009 11.603z").setFill(f).setStroke(s);
+					f = "#659900";
+					g.createPath("M-61.009 11.403C-61.458 11.561 -61.024 8.669 -61.2 8.2C-62.222 5.474 -71.4 3.9 -71.4 3.9C-71.627 5.265 -71.682 6.861 -71.576 8.499C-71.576 8.499 -67.308 13.618 -61.009 11.403z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-65.4 11.546C-66.025 11.546 -66.531 10.406 -66.531 9C-66.531 7.595 -66.025 6.455 -65.4 6.455C-64.775 6.455 -64.268 7.595 -64.268 9C-64.268 10.406 -64.775 11.546 -65.4 11.546z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-65.4 9z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-111 109.601C-111 109.601 -116.6 119.601 -91.8 113.601C-91.8 113.601 -77.8 112.401 -75.4 110.001C-74.2 110.801 -65.834 113.734 -63 114.401C-56.2 116.001 -47.8 106 -47.8 106C-47.8 106 -43.2 95.5 -40.4 95.5C-37.6 95.5 -40.8 97.1 -40.8 97.1C-40.8 97.1 -47.4 107.201 -47 108.801C-47 108.801 -52.2 128.801 -68.2 129.601C-68.2 129.601 -84.35 130.551 -83 136.401C-83 136.401 -74.2 134.001 -71.8 136.401C-71.8 136.401 -61 136.001 -69 142.401L-75.8 154.001C-75.8 154.001 -75.66 157 [...]
+					f = "#e59999";
+					g.createPath("M-112.2 113.601C-112.2 113.601 -114.2 123.201 -77.4 112.801C-77.4 112.801 -73 112.801 -70.6 113.601C-68.2 114.401 -56.2 117.201 -54.2 116.001C-54.2 116.001 -61.4 129.601 -73 128.001C-73 128.001 -86.2 129.601 -85.8 134.401C-85.8 134.401 -81.8 141.601 -77 144.001C-77 144.001 -74.2 146.401 -74.6 149.601C-75 152.801 -77.8 154.401 -79.8 155.201C-81.8 156.001 -85 152.801 -86.6 152.801C-88.2 152.801 -96.6 146.401 -101 141.601C-105.4 136.801 -113.8 124.801 -113.4 122.001C-113  [...]
+					f = "#b26565";
+					g.createPath("M-109 131.051C-106.4 135.001 -103.2 139.201 -101 141.601C-96.6 146.401 -88.2 152.801 -86.6 152.801C-85 152.801 -81.8 156.001 -79.8 155.201C-77.8 154.401 -75 152.801 -74.6 149.601C-74.2 146.401 -77 144.001 -77 144.001C-80.066 142.468 -82.806 138.976 -84.385 136.653C-84.385 136.653 -84.2 139.201 -89.4 138.401C-94.6 137.601 -99.8 134.801 -101.4 131.601C-103 128.401 -105.4 126.001 -103.8 129.601C-102.2 133.201 -99.8 136.801 -98.2 137.201C-96.6 137.601 -97 138.801 -99.4 138 [...]
+					f = "#992600";
+					g.createPath("M-111.6 110.001C-111.6 110.001 -109.8 96.4 -108.6 92.4C-108.6 92.4 -109.4 85.6 -107 81.4C-104.6 77.2 -102.6 71 -99.6 65.6C-96.6 60.2 -96.4 56.2 -92.4 54.6C-88.4 53 -82.4 44.4 -79.6 43.4C-76.8 42.4 -77 43.2 -77 43.2C-77 43.2 -70.2 28.4 -56.6 32.4C-56.6 32.4 -72.8 29.6 -57 20.2C-57 20.2 -61.8 21.3 -58.5 14.3C-56.299 9.632 -56.8 16.4 -67.8 28.2C-67.8 28.2 -72.8 36.8 -78 39.8C-83.2 42.8 -95.2 49.8 -96.4 53.6C-97.6 57.4 -100.8 63.2 -102.8 64.8C-104.8 66.4 -107.6 70.6 -108 7 [...]
+					f = "#ffffff";
+					g.createPath("M-120.2 114.601C-120.2 114.601 -122.2 113.201 -126.6 119.201C-126.6 119.201 -119.3 152.201 -119.3 153.601C-119.3 153.601 -118.2 151.501 -119.5 144.301C-120.8 137.101 -121.7 124.401 -121.7 124.401L-120.2 114.601z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-98.6 54C-98.6 54 -116.2 57.2 -115.8 86.4L-116.6 111.201C-116.6 111.201 -117.8 85.6 -119 84C-120.2 82.4 -116.2 71.2 -119.4 77.2C-119.4 77.2 -133.4 91.2 -125.4 112.401C-125.4 112.401 -123.9 115.701 -126.9 111.101C-126.9 111.101 -131.5 98.5 -130.4 92.1C-130.4 92.1 -130.2 89.9 -128.3 87.1C-128.3 87.1 -119.7 75.4 -117 73.1C-117 73.1 -115.2 58.7 -99.8 53.5C-99.8 53.5 -94.1 51.2 -98.6 54z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M40.8 -12.2C41.46 -12.554 41.451 -13.524 42.031 -13.697C43.18 -14.041 43.344 -15.108 43.862 -15.892C44.735 -17.211 44.928 -18.744 45.51 -20.235C45.782 -20.935 45.809 -21.89 45.496 -22.55C44.322 -25.031 43.62 -27.48 42.178 -29.906C41.91 -30.356 41.648 -31.15 41.447 -31.748C40.984 -33.132 39.727 -34.123 38.867 -35.443C38.579 -35.884 39.104 -36.809 38.388 -36.893C37.491 -36.998 36.042 -37.578 35.809 -36.552C35.221 -33.965 36.232 -31.442 37.2 -29C36.418 -28.308 36.752 -27. [...]
+					f = "#000000";
+					g.createPath("M31.959 -16.666C32.083 -16.743 31.928 -17.166 32.037 -17.382C32.199 -17.706 32.602 -17.894 32.764 -18.218C32.873 -18.434 32.71 -18.814 32.846 -18.956C35.179 -21.403 35.436 -24.427 34.4 -27.4C35.424 -28.02 35.485 -29.282 35.06 -30.129C34.207 -31.829 34.014 -33.755 33.039 -35.298C32.237 -36.567 30.659 -37.811 29.288 -36.508C28.867 -36.108 28.546 -35.321 28.824 -34.609C28.888 -34.446 29.173 -34.3 29.146 -34.218C29.039 -33.894 28.493 -33.67 28.487 -33.398C28.457 -31.902 27 [...]
+					f = "#000000";
+					g.createPath("M94.771 -26.977C96.16 -25.185 96.45 -22.39 94.401 -21C94.951 -17.691 98.302 -19.67 100.401 -20.2C100.292 -20.588 100.519 -20.932 100.802 -20.937C101.859 -20.952 102.539 -21.984 103.601 -21.8C104.035 -23.357 105.673 -24.059 106.317 -25.439C108.043 -29.134 107.452 -33.407 104.868 -36.653C104.666 -36.907 104.883 -37.424 104.759 -37.786C104.003 -39.997 101.935 -40.312 100.001 -41C98.824 -44.875 98.163 -48.906 96.401 -52.6C94.787 -52.85 94.089 -54.589 92.752 -55.309C91.419  [...]
+					f = "#000000";
+					g.createPath("M57.611 -8.591C56.124 -6.74 52.712 -4.171 55.629 -2.243C55.823 -2.114 56.193 -2.11 56.366 -2.244C58.387 -3.809 60.39 -4.712 62.826 -5.294C62.95 -5.323 63.224 -4.856 63.593 -5.017C65.206 -5.72 67.216 -5.662 68.4 -7C72.167 -6.776 75.732 -7.892 79.123 -9.2C80.284 -9.648 81.554 -10.207 82.755 -10.709C84.131 -11.285 85.335 -12.213 86.447 -13.354C86.58 -13.49 86.934 -13.4 87.201 -13.4C87.161 -14.263 88.123 -14.39 88.37 -15.012C88.462 -15.244 88.312 -15.64 88.445 -15.742C90.5 [...]
+					f = "#000000";
+					g.createPath("M2.2 -58C2.2 -58 -7.038 -60.872 -18.2 -35.2C-18.2 -35.2 -20.6 -30 -23 -28C-25.4 -26 -36.6 -22.4 -38.6 -18.4L-49 -2.4C-49 -2.4 -34.2 -18.4 -31 -20.8C-31 -20.8 -23 -29.2 -26.2 -22.4C-26.2 -22.4 -40.2 -11.6 -39 -2.4C-39 -2.4 -44.6 12 -45.4 14C-45.4 14 -29.4 -18 -27 -19.2C-24.6 -20.4 -23.4 -20.4 -24.6 -16.8C-25.8 -13.2 -26.2 3.2 -29 5.2C-29 5.2 -21 -15.2 -21.8 -18.4C-21.8 -18.4 -18.6 -22 -16.2 -16.8L-17.4 -0.8L-13 11.2C-13 11.2 -15.4 0 -13.8 -15.6C-13.8 -15.6 -15.8 -26 -11 [...]
+					f = "#000000";
+					g.createPath("M-17.8 -41.6C-17.8 -41.6 -30.6 -41.6 -33.8 -36.4L-41 -26.8C-41 -26.8 -23.8 -36.8 -19.8 -38C-15.8 -39.2 -17.8 -41.6 -17.8 -41.6z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-57.8 -35.2C-57.8 -35.2 -59.8 -34 -60.2 -31.2C-60.6 -28.4 -63 -28 -62.2 -25.2C-61.4 -22.4 -59.4 -20 -59.4 -24C-59.4 -28 -57.8 -30 -57 -31.2C-56.2 -32.4 -54.6 -36.8 -57.8 -35.2z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-66.6 26C-66.6 26 -75 22 -78.2 18.4C-81.4 14.8 -80.948 19.966 -85.8 19.6C-91.647 19.159 -90.6 3.2 -90.6 3.2L-94.6 10.8C-94.6 10.8 -95.8 25.2 -87.8 22.8C-83.893 21.628 -82.6 23.2 -84.2 24C-85.8 24.8 -78.6 25.2 -81.4 26.8C-84.2 28.4 -69.8 23.2 -72.2 33.6L-66.6 26z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-79.2 40.4C-79.2 40.4 -94.6 44.8 -98.2 35.2C-98.2 35.2 -103 37.6 -100.8 40.6C-98.6 43.6 -97.4 44 -97.4 44C-97.4 44 -92 45.2 -92.6 46C-93.2 46.8 -95.6 50.2 -95.6 50.2C-95.6 50.2 -85.4 44.2 -79.2 40.4z").setFill(f).setStroke(s);
+					f = "#ffffff";
+					g.createPath("M149.201 118.601C148.774 120.735 147.103 121.536 145.201 122.201C143.284 121.243 140.686 118.137 138.801 120.201C138.327 119.721 137.548 119.661 137.204 118.999C136.739 118.101 137.011 117.055 136.669 116.257C136.124 114.985 135.415 113.619 135.601 112.201C137.407 111.489 138.002 109.583 137.528 107.82C137.459 107.563 137.03 107.366 137.23 107.017C137.416 106.694 137.734 106.467 138.001 106.2C137.866 106.335 137.721 106.568 137.61 106.548C137 106.442 137.124 105.805 13 [...]
+					f = "#ffffff";
+					g.createPath("M139.6 138.201C139.593 136.463 137.992 134.707 139.201 133.001C139.336 133.135 139.467 133.356 139.601 133.356C139.736 133.356 139.867 133.135 140.001 133.001C141.496 135.217 145.148 136.145 145.006 138.991C144.984 139.438 143.897 140.356 144.801 141.001C142.988 142.349 142.933 144.719 142.001 146.601C140.763 146.315 139.551 145.952 138.401 145.401C138.753 143.915 138.636 142.231 139.456 140.911C139.89 140.213 139.603 139.134 139.6 138.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-26.6 129.201C-26.6 129.201 -43.458 139.337 -29.4 124.001C-20.6 114.401 -10.6 108.801 -10.6 108.801C-10.6 108.801 -0.2 104.4 3.4 103.2C7 102 22.2 96.8 25.4 96.4C28.6 96 38.2 92 45 96C51.8 100 59.8 104.4 59.8 104.4C59.8 104.4 43.4 96 39.8 98.4C36.2 100.8 29 100.4 23 103.6C23 103.6 8.2 108.001 5 110.001C1.8 112.001 -8.6 123.601 -10.2 122.801C-11.8 122.001 -9.8 121.601 -8.6 118.801C-7.4 116.001 -9.4 114.401 -17.4 120.801C-25.4 127.201 -26.6 129.201 -26.6 129.201z").setFi [...]
+					f = "#000000";
+					g.createPath("M-19.195 123.234C-19.195 123.234 -17.785 110.194 -9.307 111.859C-9.307 111.859 -1.081 107.689 1.641 105.721C1.641 105.721 9.78 104.019 11.09 103.402C29.569 94.702 44.288 99.221 44.835 98.101C45.381 96.982 65.006 104.099 68.615 108.185C69.006 108.628 58.384 102.588 48.686 100.697C40.413 99.083 18.811 100.944 7.905 106.48C4.932 107.989 -4.013 113.773 -6.544 113.662C-9.075 113.55 -19.195 123.234 -19.195 123.234z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-23 148.801C-23 148.801 -38.2 146.401 -21.4 144.801C-21.4 144.801 -3.4 142.801 0.6 137.601C0.6 137.601 14.2 128.401 17 128.001C19.8 127.601 49.8 120.401 50.2 118.001C50.6 115.601 56.2 115.601 57.8 116.401C59.4 117.201 58.6 118.401 55.8 119.201C53 120.001 21.8 136.401 15.4 137.601C9 138.801 -2.6 146.401 -7.4 147.601C-12.2 148.801 -23 148.801 -23 148.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-3.48 141.403C-3.48 141.403 -12.062 140.574 -3.461 139.755C-3.461 139.755 5.355 136.331 7.403 133.668C7.403 133.668 14.367 128.957 15.8 128.753C17.234 128.548 31.194 124.861 31.399 123.633C31.604 122.404 65.67 109.823 70.09 113.013C73.001 115.114 63.1 113.437 53.466 117.847C52.111 118.467 18.258 133.054 14.981 133.668C11.704 134.283 5.765 138.174 3.307 138.788C0.85 139.403 -3.48 141.403 -3.48 141.403z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-11.4 143.601C-11.4 143.601 -6.2 143.201 -7.4 144.801C-8.6 146.401 -11 145.601 -11 145.601L-11.4 143.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-18.6 145.201C-18.6 145.201 -13.4 144.801 -14.6 146.401C-15.8 148.001 -18.2 147.201 -18.2 147.201L-18.6 145.201z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-29 146.801C-29 146.801 -23.8 146.401 -25 148.001C-26.2 149.601 -28.6 148.801 -28.6 148.801L-29 146.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-36.6 147.601C-36.6 147.601 -31.4 147.201 -32.6 148.801C-33.8 150.401 -36.2 149.601 -36.2 149.601L-36.6 147.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M1.8 108.001C1.8 108.001 6.2 108.001 5 109.601C3.8 111.201 0.6 110.801 0.6 110.801L1.8 108.001z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-8.2 113.601C-8.2 113.601 -1.694 111.46 -4.2 114.801C-5.4 116.401 -7.8 115.601 -7.8 115.601L-8.2 113.601z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-19.4 118.401C-19.4 118.401 -14.2 118.001 -15.4 119.601C-16.6 121.201 -19 120.401 -19 120.401L-19.4 118.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-27 124.401C-27 124.401 -21.8 124.001 -23 125.601C-24.2 127.201 -26.6 126.401 -26.6 126.401L-27 124.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-33.8 129.201C-33.8 129.201 -28.6 128.801 -29.8 130.401C-31 132.001 -33.4 131.201 -33.4 131.201L-33.8 129.201z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M5.282 135.598C5.282 135.598 12.203 135.066 10.606 137.195C9.009 139.325 5.814 138.26 5.814 138.26L5.282 135.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M15.682 130.798C15.682 130.798 22.603 130.266 21.006 132.395C19.409 134.525 16.214 133.46 16.214 133.46L15.682 130.798z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M26.482 126.398C26.482 126.398 33.403 125.866 31.806 127.995C30.209 130.125 27.014 129.06 27.014 129.06L26.482 126.398z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M36.882 121.598C36.882 121.598 43.803 121.066 42.206 123.195C40.609 125.325 37.414 124.26 37.414 124.26L36.882 121.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M9.282 103.598C9.282 103.598 16.203 103.066 14.606 105.195C13.009 107.325 9.014 107.06 9.014 107.06L9.282 103.598z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M19.282 100.398C19.282 100.398 26.203 99.866 24.606 101.995C23.009 104.125 18.614 103.86 18.614 103.86L19.282 100.398z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-3.4 140.401C-3.4 140.401 1.8 140.001 0.6 141.601C-0.6 143.201 -3 142.401 -3 142.401L-3.4 140.401z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-76.6 41.2C-76.6 41.2 -81 50 -81.4 53.2C-81.4 53.2 -80.6 44.4 -79.4 42.4C-78.2 40.4 -76.6 41.2 -76.6 41.2z").setFill(f).setStroke(s);
+					f = "#992600";
+					g.createPath("M-95 55.2C-95 55.2 -98.2 69.6 -97.8 72.4C-97.8 72.4 -99 60.8 -98.6 59.6C-98.2 58.4 -95 55.2 -95 55.2z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-74.2 -19.4L-74.4 -16.2L-76.6 -16C-76.6 -16 -62.4 -3.4 -61.8 4.2C-61.8 4.2 -61 -4 -74.2 -19.4z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-70.216 -18.135C-70.647 -18.551 -70.428 -19.296 -70.836 -19.556C-71.645 -20.072 -69.538 -20.129 -69.766 -20.845C-70.149 -22.051 -69.962 -22.072 -70.084 -23.348C-70.141 -23.946 -69.553 -25.486 -69.168 -25.926C-67.722 -27.578 -69.046 -30.51 -67.406 -32.061C-67.102 -32.35 -66.726 -32.902 -66.441 -33.32C-65.782 -34.283 -64.598 -34.771 -63.648 -35.599C-63.33 -35.875 -63.531 -36.702 -62.962 -36.61C-62.248 -36.495 -61.007 -36.625 -61.052 -35.784C-61.165 -33.664 -62.494 -31.9 [...]
+					f = "#000000";
+					g.createPath("M-73.8 -16.4C-73.8 -16.4 -73.4 -9.6 -71 -8C-68.6 -6.4 -69.8 -7.2 -73 -8.4C-76.2 -9.6 -75 -10.4 -75 -10.4C-75 -10.4 -77.8 -10 -75.4 -8C-73 -6 -69.4 -3.6 -71 -3.6C-72.6 -3.6 -80.2 -7.6 -80.2 -10.4C-80.2 -13.2 -81.2 -17.3 -81.2 -17.3C-81.2 -17.3 -80.1 -18.1 -75.3 -18C-75.3 -18 -73.9 -17.3 -73.8 -16.4z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-74.6 2.2C-74.6 2.2 -83.12 -0.591 -101.6 2.8C-101.6 2.8 -92.569 0.722 -73.8 3C-63.5 4.25 -74.6 2.2 -74.6 2.2z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-72.502 2.129C-72.502 2.129 -80.748 -1.389 -99.453 0.392C-99.453 0.392 -90.275 -0.897 -71.774 2.995C-61.62 5.131 -72.502 2.129 -72.502 2.129z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-70.714 2.222C-70.714 2.222 -78.676 -1.899 -97.461 -1.514C-97.461 -1.514 -88.213 -2.118 -70.052 3.14C-60.086 6.025 -70.714 2.222 -70.714 2.222z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-69.444 2.445C-69.444 2.445 -76.268 -1.862 -93.142 -2.96C-93.142 -2.96 -84.803 -2.79 -68.922 3.319C-60.206 6.672 -69.444 2.445 -69.444 2.445z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M45.84 12.961C45.84 12.961 44.91 13.605 45.124 12.424C45.339 11.243 73.547 -1.927 77.161 -1.677C77.161 -1.677 46.913 11.529 45.84 12.961z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M42.446 13.6C42.446 13.6 41.57 14.315 41.691 13.121C41.812 11.927 68.899 -3.418 72.521 -3.452C72.521 -3.452 43.404 12.089 42.446 13.6z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M39.16 14.975C39.16 14.975 38.332 15.747 38.374 14.547C38.416 13.348 58.233 -2.149 68.045 -4.023C68.045 -4.023 50.015 4.104 39.16 14.975z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M36.284 16.838C36.284 16.838 35.539 17.532 35.577 16.453C35.615 15.373 53.449 1.426 62.28 -0.26C62.28 -0.26 46.054 7.054 36.284 16.838z").setFill(f).setStroke(s);
+					f = "#cccccc"; s = null;
+					g.createPath("M4.6 164.801C4.6 164.801 -10.6 162.401 6.2 160.801C6.2 160.801 24.2 158.801 28.2 153.601C28.2 153.601 41.8 144.401 44.6 144.001C47.4 143.601 63.8 140.001 64.2 137.601C64.6 135.201 70.6 132.801 72.2 133.601C73.8 134.401 73.8 143.601 71 144.401C68.2 145.201 49.4 152.401 43 153.601C36.6 154.801 25 162.401 20.2 163.601C15.4 164.801 4.6 164.801 4.6 164.801z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M77.6 127.401C77.6 127.401 74.6 129.001 73.4 131.601C73.4 131.601 67 142.201 52.8 145.401C52.8 145.401 29.8 154.401 22 156.401C22 156.401 8.6 161.401 1.2 160.601C1.2 160.601 -5.8 160.801 0.4 162.401C0.4 162.401 20.6 160.401 24 158.601C24 158.601 39.6 153.401 42.6 150.801C45.6 148.201 63.8 143.201 66 141.201C68.2 139.201 78 130.801 77.6 127.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M18.882 158.911C18.882 158.911 24.111 158.685 22.958 160.234C21.805 161.784 19.357 160.91 19.357 160.91L18.882 158.911z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M11.68 160.263C11.68 160.263 16.908 160.037 15.756 161.586C14.603 163.136 12.155 162.263 12.155 162.263L11.68 160.263z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M1.251 161.511C1.251 161.511 6.48 161.284 5.327 162.834C4.174 164.383 1.726 163.51 1.726 163.51L1.251 161.511z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-6.383 162.055C-6.383 162.055 -1.154 161.829 -2.307 163.378C-3.46 164.928 -5.908 164.054 -5.908 164.054L-6.383 162.055z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M35.415 151.513C35.415 151.513 42.375 151.212 40.84 153.274C39.306 155.336 36.047 154.174 36.047 154.174L35.415 151.513z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M45.73 147.088C45.73 147.088 51.689 143.787 51.155 148.849C50.885 151.405 46.362 149.749 46.362 149.749L45.73 147.088z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M54.862 144.274C54.862 144.274 62.021 140.573 60.287 146.035C59.509 148.485 55.493 146.935 55.493 146.935L54.862 144.274z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M64.376 139.449C64.376 139.449 68.735 134.548 69.801 141.21C70.207 143.748 65.008 142.11 65.008 142.11L64.376 139.449z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M26.834 155.997C26.834 155.997 32.062 155.77 30.91 157.32C29.757 158.869 27.308 157.996 27.308 157.996L26.834 155.997z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M62.434 34.603C62.434 34.603 61.708 35.268 61.707 34.197C61.707 33.127 79.191 19.863 88.034 18.479C88.034 18.479 71.935 25.208 62.434 34.603z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M65.4 98.4C65.4 98.4 87.401 120.801 96.601 124.401C96.601 124.401 105.801 135.601 101.801 161.601C101.801 161.601 98.601 169.201 95.401 148.401C95.401 148.401 98.601 123.201 87.401 139.201C87.401 139.201 79 129.301 85.4 129.601C85.4 129.601 88.601 131.601 89.001 130.001C89.401 128.401 81.4 114.801 64.2 100.4C47 86 65.4 98.4 65.4 98.4z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M7 137.201C7 137.201 6.8 135.401 8.6 136.201C10.4 137.001 104.601 143.201 136.201 167.201C136.201 167.201 91.001 144.001 7 137.201z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M17.4 132.801C17.4 132.801 17.2 131.001 19 131.801C20.8 132.601 157.401 131.601 181.001 164.001C181.001 164.001 159.001 138.801 17.4 132.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M29 128.801C29 128.801 28.8 127.001 30.6 127.801C32.4 128.601 205.801 115.601 229.401 148.001C229.401 148.001 219.801 122.401 29 128.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M39 124.001C39 124.001 38.8 122.201 40.6 123.001C42.4 123.801 164.601 85.2 188.201 117.601C188.201 117.601 174.801 93 39 124.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-19 146.801C-19 146.801 -19.2 145.001 -17.4 145.801C-15.6 146.601 2.2 148.801 4.2 187.601C4.2 187.601 -3 145.601 -19 146.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-27.8 148.401C-27.8 148.401 -28 146.601 -26.2 147.401C-24.4 148.201 -10.2 143.601 -13 182.401C-13 182.401 -11.8 147.201 -27.8 148.401z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-35.8 148.801C-35.8 148.801 -36 147.001 -34.2 147.801C-32.4 148.601 -17 149.201 -29.4 171.601C-29.4 171.601 -19.8 147.601 -35.8 148.801z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M11.526 104.465C11.526 104.465 11.082 106.464 12.631 105.247C28.699 92.622 61.141 33.72 116.826 28.086C116.826 28.086 78.518 15.976 11.526 104.465z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M22.726 102.665C22.726 102.665 21.363 101.472 23.231 100.847C25.099 100.222 137.541 27.72 176.826 35.686C176.826 35.686 149.719 28.176 22.726 102.665z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M1.885 108.767C1.885 108.767 1.376 110.366 3.087 109.39C12.062 104.27 15.677 47.059 59.254 45.804C59.254 45.804 26.843 31.09 1.885 108.767z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-18.038 119.793C-18.038 119.793 -19.115 121.079 -17.162 120.825C-6.916 119.493 14.489 78.222 58.928 83.301C58.928 83.301 26.962 68.955 -18.038 119.793z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-6.8 113.667C-6.8 113.667 -7.611 115.136 -5.742 114.511C4.057 111.237 17.141 66.625 61.729 63.078C61.729 63.078 27.603 55.135 -6.8 113.667z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-25.078 124.912C-25.078 124.912 -25.951 125.954 -24.369 125.748C-16.07 124.669 1.268 91.24 37.264 95.354C37.264 95.354 11.371 83.734 -25.078 124.912z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-32.677 130.821C-32.677 130.821 -33.682 131.866 -32.091 131.748C-27.923 131.439 2.715 98.36 21.183 113.862C21.183 113.862 9.168 95.139 -32.677 130.821z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M36.855 98.898C36.855 98.898 35.654 97.543 37.586 97.158C39.518 96.774 160.221 39.061 198.184 51.927C198.184 51.927 172.243 41.053 36.855 98.898z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M3.4 163.201C3.4 163.201 3.2 161.401 5 162.201C6.8 163.001 22.2 163.601 9.8 186.001C9.8 186.001 19.4 162.001 3.4 163.201z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M13.8 161.601C13.8 161.601 13.6 159.801 15.4 160.601C17.2 161.401 35 163.601 37 202.401C37 202.401 29.8 160.401 13.8 161.601z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M20.6 160.001C20.6 160.001 20.4 158.201 22.2 159.001C24 159.801 48.6 163.201 72.2 195.601C72.2 195.601 36.6 158.801 20.6 160.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M28.225 157.972C28.225 157.972 27.788 156.214 29.678 156.768C31.568 157.322 52.002 155.423 90.099 189.599C90.099 189.599 43.924 154.656 28.225 157.972z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M38.625 153.572C38.625 153.572 38.188 151.814 40.078 152.368C41.968 152.922 76.802 157.423 128.499 192.399C128.499 192.399 54.324 150.256 38.625 153.572z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-1.8 142.001C-1.8 142.001 -2 140.201 -0.2 141.001C1.6 141.801 55 144.401 85.4 171.201C85.4 171.201 50.499 146.426 -1.8 142.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M-11.8 146.001C-11.8 146.001 -12 144.201 -10.2 145.001C-8.4 145.801 16.2 149.201 39.8 181.601C39.8 181.601 4.2 144.801 -11.8 146.001z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M49.503 148.962C49.503 148.962 48.938 147.241 50.864 147.655C52.79 148.068 87.86 150.004 141.981 181.098C141.981 181.098 64.317 146.704 49.503 148.962z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M57.903 146.562C57.903 146.562 57.338 144.841 59.264 145.255C61.19 145.668 96.26 147.604 150.381 178.698C150.381 178.698 73.317 143.904 57.903 146.562z").setFill(f).setStroke(s);
+					f = "#ffffff"; s = {color: "#000000", width: 0.1};
+					g.createPath("M67.503 141.562C67.503 141.562 66.938 139.841 68.864 140.255C70.79 140.668 113.86 145.004 203.582 179.298C203.582 179.298 82.917 138.904 67.503 141.562z").setFill(f).setStroke(s);
+					f = "#000000"; s = null;
+					g.createPath("M-43.8 148.401C-43.8 148.401 -38.6 148.001 -39.8 149.601C-41 151.201 -43.4 150.401 -43.4 150.401L-43.8 148.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-13 162.401C-13 162.401 -7.8 162.001 -9 163.601C-10.2 165.201 -12.6 164.401 -12.6 164.401L-13 162.401z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-21.8 162.001C-21.8 162.001 -16.6 161.601 -17.8 163.201C-19 164.801 -21.4 164.001 -21.4 164.001L-21.8 162.001z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-117.169 150.182C-117.169 150.182 -112.124 151.505 -113.782 152.624C-115.439 153.744 -117.446 152.202 -117.446 152.202L-117.169 150.182z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-115.169 140.582C-115.169 140.582 -110.124 141.905 -111.782 143.024C-113.439 144.144 -115.446 142.602 -115.446 142.602L-115.169 140.582z").setFill(f).setStroke(s);
+					f = "#000000";
+					g.createPath("M-122.369 136.182C-122.369 136.182 -117.324 137.505 -118.982 138.624C-120.639 139.744 -122.646 138.202 -122.646 138.202L-122.369 136.182z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-42.6 211.201C-42.6 211.201 -44.2 211.201 -48.2 213.201C-50.2 213.201 -61.4 216.801 -67 226.801C-67 226.801 -54.6 217.201 -42.6 211.201z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M45.116 303.847C45.257 304.105 45.312 304.525 45.604 304.542C46.262 304.582 47.495 304.883 47.37 304.247C46.522 299.941 45.648 295.004 41.515 293.197C40.876 292.918 39.434 293.331 39.36 294.215C39.233 295.739 39.116 297.088 39.425 298.554C39.725 299.975 41.883 299.985 42.8 298.601C43.736 300.273 44.168 302.116 45.116 303.847z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M34.038 308.581C34.786 309.994 34.659 311.853 36.074 312.416C36.814 312.71 38.664 311.735 38.246 310.661C37.444 308.6 37.056 306.361 35.667 304.55C35.467 304.288 35.707 303.755 35.547 303.427C34.953 302.207 33.808 301.472 32.4 301.801C31.285 304.004 32.433 306.133 33.955 307.842C34.091 307.994 33.925 308.37 34.038 308.581z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-5.564 303.391C-5.672 303.014 -5.71 302.551 -5.545 302.23C-5.014 301.197 -4.221 300.075 -4.558 299.053C-4.906 297.997 -6.022 298.179 -6.672 298.748C-7.807 299.742 -7.856 301.568 -8.547 302.927C-8.743 303.313 -8.692 303.886 -9.133 304.277C-9.607 304.698 -10.047 306.222 -9.951 306.793C-9.898 307.106 -10.081 317.014 -9.859 316.751C-9.24 316.018 -6.19 306.284 -6.121 305.392C-6.064 304.661 -5.332 304.196 -5.564 303.391z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-31.202 296.599C-28.568 294.1 -25.778 291.139 -26.22 287.427C-26.336 286.451 -28.111 286.978 -28.298 287.824C-29.1 291.449 -31.139 294.11 -33.707 296.502C-35.903 298.549 -37.765 304.893 -38 305.401C-34.303 300.145 -32.046 297.399 -31.202 296.599z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-44.776 290.635C-44.253 290.265 -44.555 289.774 -44.338 289.442C-43.385 287.984 -42.084 286.738 -42.066 285C-42.063 284.723 -42.441 284.414 -42.776 284.638C-43.053 284.822 -43.395 284.952 -43.503 285.082C-45.533 287.531 -46.933 290.202 -48.376 293.014C-48.559 293.371 -49.703 297.862 -49.39 297.973C-49.151 298.058 -47.431 293.877 -47.221 293.763C-45.958 293.077 -45.946 291.462 -44.776 290.635z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-28.043 310.179C-27.599 309.31 -26.023 308.108 -26.136 307.219C-26.254 306.291 -25.786 304.848 -26.698 305.536C-27.955 306.484 -31.404 307.833 -31.674 313.641C-31.7 314.212 -28.726 311.519 -28.043 310.179z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-13.6 293.001C-13.2 292.333 -12.492 292.806 -12.033 292.543C-11.385 292.171 -10.774 291.613 -10.482 290.964C-9.512 288.815 -7.743 286.995 -7.6 284.601C-9.091 283.196 -9.77 285.236 -10.4 286.201C-11.723 284.554 -12.722 286.428 -14.022 286.947C-14.092 286.975 -14.305 286.628 -14.38 286.655C-15.557 287.095 -16.237 288.176 -17.235 288.957C-17.406 289.091 -17.811 288.911 -17.958 289.047C-18.61 289.65 -19.583 289.975 -19.863 290.657C-20.973 293.364 -24.113 295.459 -26 303.0 [...]
+					f = "#cccccc";
+					g.createPath("M46.2 347.401C46.2 347.401 53.6 327.001 49.2 315.801C49.2 315.801 60.6 337.401 56 348.601C56 348.601 55.6 338.201 51.6 333.201C51.6 333.201 47.6 346.001 46.2 347.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M31.4 344.801C31.4 344.801 36.8 336.001 28.8 317.601C28.8 317.601 28 338.001 21.2 349.001C21.2 349.001 35.4 328.801 31.4 344.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M21.4 342.801C21.4 342.801 21.2 322.801 21.6 319.801C21.6 319.801 17.8 336.401 7.6 346.001C7.6 346.001 22 334.001 21.4 342.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M11.8 310.801C11.8 310.801 17.8 324.401 7.8 342.801C7.8 342.801 14.2 330.601 9.4 323.601C9.4 323.601 12 320.201 11.8 310.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-7.4 342.401C-7.4 342.401 -8.4 326.801 -6.6 324.601C-6.6 324.601 -6.4 318.201 -6.8 317.201C-6.8 317.201 -2.8 311.001 -2.6 318.401C-2.6 318.401 -1.2 326.201 1.6 330.801C1.6 330.801 5.2 336.201 5 342.601C5 342.601 -5 312.401 -7.4 342.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-11 314.801C-11 314.801 -17.6 325.601 -19.4 344.601C-19.4 344.601 -20.8 338.401 -17 324.001C-17 324.001 -12.8 308.601 -11 314.801z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-32.8 334.601C-32.8 334.601 -27.8 329.201 -26.4 324.201C-26.4 324.201 -22.8 308.401 -29.2 317.001C-29.2 317.001 -29 325.001 -37.2 332.401C-37.2 332.401 -32.4 330.001 -32.8 334.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-38.6 329.601C-38.6 329.601 -35.2 312.201 -34.4 311.401C-34.4 311.401 -32.6 308.001 -35.4 311.201C-35.4 311.201 -44.2 330.401 -48.2 337.001C-48.2 337.001 -40.2 327.801 -38.6 329.601z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-44.4 313.001C-44.4 313.001 -32.8 290.601 -54.6 316.401C-54.6 316.401 -43.6 306.601 -44.4 313.001z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M-59.8 298.401C-59.8 298.401 -55 279.601 -52.4 279.801C-52.4 279.801 -44.2 270.801 -50.8 281.401C-50.8 281.401 -56.8 291.001 -56.2 300.801C-56.2 300.801 -56.8 291.201 -59.8 298.401z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M270.5 287C270.5 287 258.5 277 256 273.5C256 273.5 269.5 292 269.5 299C269.5 299 272 291.5 270.5 287z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M276 265C276 265 255 250 251.5 242.5C251.5 242.5 278 272 278 276.5C278 276.5 278.5 267.5 276 265z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M293 111C293 111 281 103 279.5 105C279.5 105 290 111.5 292.5 120C292.5 120 291 111 293 111z").setFill(f).setStroke(s);
+					f = "#cccccc";
+					g.createPath("M301.5 191.5L284 179.5C284 179.5 303 196.5 303.5 200.5L301.5 191.5z").setFill(f).setStroke(s);
+					s = "#000000"; f = null;
+					g.createPath("M-89.25 169L-67.25 173.75").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M-39 331C-39 331 -39.5 327.5 -48.5 338").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M-33.5 336C-33.5 336 -31.5 329.5 -38 334").setFill(f).setStroke(s);
+					s = "#000000";
+					g.createPath("M20.5 344.5C20.5 344.5 22 333.5 10.5 346.5").setFill(f).setStroke(s);
+                },
+                tearDown: function(){
+                    destroySurface();
+                },
+                runTest: function(){
+	                scaleAndRotateTiger();
+                }
+            }
+    	]);
+		doh.run();
+	});
+</script>
+</head>
+<body>
+<h1>Testing Scenes</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+</body>
+</html>
diff --git a/dojox/gfx/tests/performance/images/testImage.jpg b/dojox/gfx/tests/performance/images/testImage.jpg
new file mode 100755
index 0000000..6bd1338
Binary files /dev/null and b/dojox/gfx/tests/performance/images/testImage.jpg differ
diff --git a/dojox/gfx/tests/performance/module.js b/dojox/gfx/tests/performance/module.js
new file mode 100755
index 0000000..b69a8d8
--- /dev/null
+++ b/dojox/gfx/tests/performance/module.js
@@ -0,0 +1,8 @@
+dojo.provide("dojox.gfx.tests.performance.module");
+if(dojo.isBrowser){
+	doh.registerUrl("GFX: Primitives", dojo.moduleUrl("dojox", "gfx/tests/performance/gfx_primitives.html"), 3600000);
+	doh.registerUrl("GFX: Fill", dojo.moduleUrl("dojox", "gfx/tests/performance/gfx_fill.html"), 3600000);
+	doh.registerUrl("GFX: Complex Scenes", dojo.moduleUrl("dojox", "gfx/tests/performance/gfx_scenes.html"), 3600000);
+}
+
+
diff --git a/dojox/gfx/tests/performance/runTests.html b/dojox/gfx/tests/performance/runTests.html
new file mode 100755
index 0000000..ded8415
--- /dev/null
+++ b/dojox/gfx/tests/performance/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../../util/doh/runner.html?testModule=dojox.gfx.tests.performance.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/gfx/tests/runTests.html b/dojox/gfx/tests/runTests.html
new file mode 100644
index 0000000..4e13179
--- /dev/null
+++ b/dojox/gfx/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.gfx.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/gfx/tests/svgweb/README b/dojox/gfx/tests/svgweb/README
new file mode 100644
index 0000000..18224c2
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/README
@@ -0,0 +1,15 @@
+This folder contains dojox.gfx tests modified to force SVGWeb on all browsers.
+
+NOTICE of 3rd party code included
+=================================
+For ease of testing, the svgweb/ folder contains the latest svgweb trunk
+version (as of 7/4/2010 r1205) released under Apache License Version 2.0:
+http://www.apache.org/licenses/LICENSE-2.0.
+
+This is a separately licensed library, see COPYING.txt in svgweb/ (note that
+only the binary subset of files from that project are included here).
+
+Folder svgweb/ is used for testing only, and is not required for Dojo to work.
+It can be safely removed.
+
+To obtain SVGWeb files directly, please visit http://code.google.com/p/svgweb/
diff --git a/dojox/gfx/tests/svgweb/sample.html b/dojox/gfx/tests/svgweb/sample.html
new file mode 100644
index 0000000..b3350e8
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/sample.html
@@ -0,0 +1,171 @@
+<html>
+	<head>
+		<title>GFX on SVGWeb sample</title>
+
+		<!-- tell svgweb to use flash rather than native svg -->
+		<meta name="svg.render.forceflash" content="true"/>
+		<!-- include svgweb, must before dojo, notice the extra 'data-path' attribute -->
+		<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+		<!-- include dojo, notice the config: forceGfxRenderer:'svg' -->
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, forceGfxRenderer: 'svg'"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojox.gfx");
+			dojo.require("dojox.gfx.move");
+
+			dojo.addOnLoad(function() {
+				try {
+					testSurface();
+				} catch (ex) {
+					alert(ex);
+				}
+			});
+			
+			function testSurface() {
+				var node = dojo.byId("surface");
+				var surface = dojox.gfx.createSurface(node, 600, 550);
+				
+				surface.whenLoaded(
+					function() {
+						surface.openBatch();
+
+						basicShapes(surface);
+						basicTransform(surface);
+						basicGroup(surface);
+						basicMove(surface);
+						basicText(surface);
+						
+						surface.closeBatch();
+					}
+				);
+				
+				window.s = surface;
+			}
+			
+			function basicText(surface) {
+				var text = surface.createText({x: 200, y: 200, text: "I'm wrong!"});
+				text.setShape({text: "The red circle is draggable"});
+			}
+			
+			function basicMove(surface) {
+				var d = surface.createCircle({
+					r : 50,
+					cx : 200,
+					cy: 200
+				}).setFill({
+					type: "radial",
+					cx : 200,
+					cy: 200,
+					r:50,
+					colors: [
+						{color:"white",offset:0},
+						{color:"red",offset:1}
+					]
+				});
+				new dojox.gfx.Moveable(d);
+			}
+			
+			function basicGroup(surface) {
+				var _defaultStroke = {
+					color : "black",
+					style : "solid",
+					width : 1
+				};
+
+				var _arrowHeight = 5;
+				var _arrowWidth = 3;
+				
+				drawArrow(300,300, 435,435);
+				drawArrow(300,300, 165,165);
+				drawArrow(300,300, 435,165);
+				drawArrow(300,300, 165,435);
+				
+				drawArrow(300,300, 300,450);
+				drawArrow(300,300, 300,150);
+				drawArrow(300,300, 150,300);
+				drawArrow(300,300, 450,300);
+				
+				function drawArrow(x1, y1, x2, y2) {
+					var len = Math.sqrt(Math.pow(x2-x1,2) + Math.pow(y2-y1,2));
+					var group = surface.createGroup();
+					
+					group.createLine({
+						x1 : 0,
+						y1 : 0,
+						x2 : 0+len,
+						y2 : 0
+					}).setStroke(_defaultStroke);
+					
+					group.createPath()
+						.moveTo(len-_arrowHeight,0)
+						.lineTo(len-_arrowHeight,-_arrowWidth)
+						.lineTo(len,0)
+						.lineTo(len-_arrowHeight,_arrowWidth)
+						.lineTo(len-_arrowHeight,0)
+						.setStroke(_defaultStroke)
+						.setFill("black");
+
+					var _rot = Math.asin((y2-y1)/len)*180/Math.PI;
+					if (x2 <= x1) {_rot = 180-_rot;}
+					
+					group.setTransform([
+						dojox.gfx.matrix.translate(x1,y1),
+						dojox.gfx.matrix.rotategAt(_rot,0,0)
+					]);
+				}
+			}
+			
+			function basicTransform(surface) {
+				var rect1 = surface.createRect({
+					width : 200,
+					height: 200
+				})
+				.setFill("red")
+				.setTransform([
+					dojox.gfx.matrix.rotategAt(45,50,350),
+					dojox.gfx.matrix.translate(50,350)
+				]);
+			}
+			
+			function basicShapes(surface) {
+				surface.createEllipse({
+					cx : 300,
+					cy : 300,
+					rx : 50,
+					ry : 100
+				}).setFill("yellow");
+
+				surface.createRect({
+					x : 90,
+					y : 90,
+					width : 50,
+					height : 170
+				}).setFill([255,0,0,0.5]);
+				
+				surface.createCircle({
+					cx : 400,
+					cy : 200,
+					r  : 50
+				}).setFill([255,0,0,0.5]);
+				
+				surface.createCircle({
+					cx : 425,
+					cy : 225,
+					r  : 50
+				}).setFill([0,255,0,0.5]);
+
+				surface.createCircle({
+					cx : 425,
+					cy : 175,
+					r  : 50
+				}).setFill([0,0,255,0.5]);
+
+			}
+		</script>
+	</head>
+
+	<body>
+		<div id="surface" style="width:600;height:550;border:solid 1px">
+		</div>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/gfx/tests/svgweb/svgweb/COPYING.txt b/dojox/gfx/tests/svgweb/svgweb/COPYING.txt
new file mode 100644
index 0000000..4cc8ba9
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/svgweb/COPYING.txt
@@ -0,0 +1,65 @@
+Copyright 2009 by contributors:
+
+* James Hight (http://labs.zavoo.com/)
+* Rick Masters 
+* Google Inc. - (Brad Neuberg -- http://codinginparadise.org)
+
+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. 
+
+
+Third-Party Licenses, Versions, and Build Information:
+
+* tests/js-tests/balloon.jpg is in the public domain and from
+  http://flickr.com/photos/pingnews/461040378/
+  Public domain details:
+    Berlin Balloon Race from the Bain Collection, 1908 (LOC)
+    Public Domain. Suggested credit: Library of Congress via pingnews.
+
+* src/tools/lib/yuicompressor-2.4.1.jar - This is the YUI Compressor, version 2.4.1 - http://developer.yahoo.com/yui/compressor/ - BSD License (http://developer.yahoo.com/yui/license.html)
+
+* src/tools/lib/jetty-*.jar - This is Jetty 6.1.19, a small embedded Java web server - http://jetty.mortbay.org/jetty/ - released under the Apache License - bundled to make local development faster and easier
+
+* src/tools/lib/servlet-api-*.jar - This is the javax.servlet package used by Jetty - copyright Sun Microsystems, Inc and Apache Software Foundation - released under the Common Development and Distribution License (CDDL) -  https://glassfish.dev.java.net/public/CDDLv1.0.html
+
+* src/svg.js - Browser detection code at top of file adapted from Dojo 1.1 browser detection code - http://dojotoolkit.org - available under either modified 'new' BSD license or Academic Free License 2.1 (http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE)
+
+* src/svg.js - Code to embed SVG into normal HTML for browsers that natively support SVG adapted from Sam Ruby's code - http://intertwingly.net/blog/2006/12/05/HOWTO-Embed-MathML-and-SVG-into-HTML4 - currently under the MIT license - contacting author about relicensing to Apache 2
+
+* src/svg.js - DOMContentLoaded code adapted from Dean Edwards blog article (http://dean.edwards.name/weblog/2005/09/busted/)
+
+* src/svg.js - GUID generation code in guid() adapted from blog post at http://note19.com/2007/05/27/javascript-guid-generator/
+
+* src/svg.js - UTF-8 data encode adapted from http://www.webtoolkit.info/
+
+* src/svg.js - sandbox_eval code adapted from blog post by YuppY at http://dean.edwards.name/weblog/2006/11/sandbox/
+
+* src/svg.htc - Flash embedding code adapted from Dojo Flash (Dojo 1.1.0); Brad Neuberg created Dojo Flash and owns the copyright so can freely relicense it (it's under the standard Dojo license anyway)
+
+* org/svgweb/smil/SplineInterpolator.as, org/svgweb/smil/LengthItem.as - Taken from the Timing Framework https://timingframework.dev.java.net/ project with BSD-like license variant (see source file). Copyright (c) 2006, Sun Microsystems, Inc - All rights reserved. Ported from Java to ActionScript by Rick Masters.
+
+* samples/svg-files/blocks_game.svg - Alex Fritze (http://www.croczilla.com/) - Permission given by email to freely use code under any license needed.
+
+* samples/svg-files/photos.svg - Vladimir Vukićević (http://blog.vlad1.com/) - Permission given by email to freely use code under any license needed.
+
+* tests/browser-tests/issue-tests/* - These tests are based on user submitted tests; no copyright claims are made on them and they are solely for testing SVG Web.
+* samples/svg-files/Droid*.svg - Droid fonts from the Android project - http://android.git.kernel.org/?p=platform/frameworks/base.git;a=tree;f=data/fonts - made available under Apache 2 license.
+
+* tests/non-licensed - Everything in this directory are third-party web pages and web applications used for testing and ensuring the framework works well in the third world. No license or copyright is asserted on this material, and it should not be distributed in any downloads. An example of material that might be here would be a New York Times page modified as a test work with the SVG Web framework, or a test page to ensure a clip art could work on an eBay page.
+
+TODO: There are alot of third party SVG files in samples/svg-files. Document where these came from, who the copyright holder is, and ensure we have a CLA on file for them.
+
+TODO: Figure out copyright information on the *.flv and *.mp3 files that we use in our samples in samples/svg-files
+
+TODO: Review the Flash code and identify any code that was either taken from other Flash libraries, blog posts, or tutorials. Document this and ensure we have appropriate CLAs from third-party code contributors.
+
+TODO: If you borrowed any code while creating your Flash ActionScript document it here, where it came from, version, etc. This is good open source hygiene :)
diff --git a/dojox/gfx/tests/svgweb/svgweb/src/svg.htc b/dojox/gfx/tests/svgweb/svgweb/src/svg.htc
new file mode 100644
index 0000000..7d9b097
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/svgweb/src/svg.htc
@@ -0,0 +1 @@
+<component lightWeight="true"> <property name="nodeName" get="_getNodeName" /> <property name="nodeType" get="_getNodeType" /> <property name="nodeValue" get="_getNodeValue" put="_setNodeValue" /> <property name="localName" get="_getLocalName" /> <property name="prefix" get="_getPrefix" /> <property name="namespaceURI" get="_getNamespaceURI" /> <property name="childNodes" get="_getChildNodes" /> <property name="parentNode" get="_getParentNode" /> <property name="firstChild" get="_getFirs [...]
diff --git a/dojox/gfx/tests/svgweb/svgweb/src/svg.js b/dojox/gfx/tests/svgweb/svgweb/src/svg.js
new file mode 100644
index 0000000..b866ea6
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/svgweb/src/svg.js
@@ -0,0 +1 @@
+(function(){window.svgns="http://www.w3.org/2000/svg";window.xlinkns="http://www.w3.org/1999/xlink";svgnsFake="urn:__fake__internal__namespace";var isOpera=false,isSafari=false,isMoz=false,isIE=false,isAIR=false,isKhtml=false,isFF=false,isXHTML=false;function _detectBrowsers(){var n=navigator,dua=n.userAgent,dav=n.appVersion,tv=parseFloat(dav);if(dua.indexOf("Opera")>=0){isOpera=tv;}var index=Math.max(dav.indexOf("WebKit"),dav.indexOf("Safari"),0);if(index){isSafari=parseFloat(dav.split( [...]
\ No newline at end of file
diff --git a/dojox/gfx/tests/svgweb/svgweb/src/svg.swf b/dojox/gfx/tests/svgweb/svgweb/src/svg.swf
new file mode 100644
index 0000000..0a3f35e
Binary files /dev/null and b/dojox/gfx/tests/svgweb/svgweb/src/svg.swf differ
diff --git a/dojox/gfx/tests/svgweb/test.roundrect.html b/dojox/gfx/tests/svgweb/test.roundrect.html
new file mode 100644
index 0000000..7bbb809
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test.roundrect.html
@@ -0,0 +1,39 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing rounded rectangle</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug: true, forceGfxRenderer: 'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.move");
+dojo.require("dojo.colors");
+
+makeShapes = function(){
+    var g = dojox.gfx;
+	var surface = g.createSurface("test", 800, 600)
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+    var rect1 = surface.createRect({x: 100, y: 100, width: 300, height: 200, r: 50}).setFill("red").setStroke("black");
+	new g.Moveable(rect1);
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Rounded rectangle</h1>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_arc.html b/dojox/gfx/tests/svgweb/test_arc.html
new file mode 100644
index 0000000..c894aff
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_arc.html
@@ -0,0 +1,66 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing arc</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+createSurface = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	surface.whenLoaded(makeShapes);
+};
+
+makeShapes = function(surface){
+	var m = dojox.gfx.matrix;
+    var g1 = surface.createGroup();
+    var g2 = g1.createGroup();
+
+	var rx = 100, ry = 60, xRotg = -30;
+    var startPoint = m.multiplyPoint(m.rotateg(xRotg), {x: -rx, y: 0  });
+    var endPoint   = m.multiplyPoint(m.rotateg(xRotg), {x: 0,   y: -ry});
+    
+    var re1 = g1.createPath()
+		.moveTo(startPoint)
+		.arcTo(rx, ry, xRotg, true, false, endPoint)
+		.setStroke({color: "red", width: 3})
+		;
+    var ge1 = g1.createPath()
+		.moveTo(re1.getLastPosition())
+		.arcTo(rx, ry, xRotg, false, false, startPoint)
+		.setStroke({color: "black"})
+		;
+    var re2 = g2.createPath()
+		.moveTo(startPoint)
+		.arcTo(rx, ry, xRotg, false, true, endPoint)
+		.setStroke({color: "green", width: 3})
+		;
+    var ge2 = g2.createPath()
+		.moveTo(re2.getLastPosition())
+		.arcTo(rx, ry, xRotg, true, true, startPoint)
+		.setStroke({color: "black"})
+		;
+		
+	g1.setTransform({dx: 200, dy: 200});
+	g2.setTransform({dx: 10,  dy: 10});
+};
+
+dojo.addOnLoad(createSurface);
+
+</script>
+</head>
+<body>
+<h1>Testing arc</h1>
+<!--<p><button onclick="createSurface();">Go</button></p>-->
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_bezier.html b/dojox/gfx/tests/svgweb/test_bezier.html
new file mode 100644
index 0000000..690fe2e
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_bezier.html
@@ -0,0 +1,81 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Approximation of an arc with bezier</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 300);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	var g = surface.createGroup();
+	
+	// create a reference ellipse
+	var rx = 200;
+	var ry = 100;
+	var startAngle = -30;
+	var arcAngle = -90;
+	var axisAngle = -30;
+	var e = g.createEllipse({rx: rx, ry: ry}).setStroke({});
+	
+	// calculate a bezier
+	var alpha = dojox.gfx.matrix._degToRad(arcAngle) / 2; // half of our angle
+	var cosa  = Math.cos(alpha);
+	var sina  = Math.sin(alpha);
+	// start point
+	var p1 = {x: cosa, y: sina};
+	// 1st control point
+	var p2 = {x: cosa + (4 / 3) * (1 - cosa), y: sina - (4 / 3) * cosa * (1 - cosa) / sina};
+	// 2nd control point (symmetric to the 1st one)
+	var p3 = {x: p2.x, y: -p2.y};
+	// end point (symmetric to the start point)
+	var p4 = {x: p1.x, y: -p1.y};
+	
+	// rotate and scale poins as appropriate
+	var s = dojox.gfx.matrix.normalize([dojox.gfx.matrix.scale(e.shape.rx, e.shape.ry), dojox.gfx.matrix.rotateg(startAngle + arcAngle / 2)]);
+	p1 = dojox.gfx.matrix.multiplyPoint(s, p1);
+	p2 = dojox.gfx.matrix.multiplyPoint(s, p2);
+	p3 = dojox.gfx.matrix.multiplyPoint(s, p3);
+	p4 = dojox.gfx.matrix.multiplyPoint(s, p4);
+	// draw control trapezoid
+	var t = g.createPath().setStroke({color: "blue"});
+	t.moveTo(p1.x, p1.y);
+	t.lineTo(p2.x, p2.y);
+	t.lineTo(p3.x, p3.y);
+	t.lineTo(p4.x, p4.y);
+	t.lineTo(p1.x, p1.y);
+	t.moveTo((p1.x + p4.x) / 2, (p1.y + p4.y) / 2);
+	t.lineTo((p2.x + p3.x) / 2, (p2.y + p3.y) / 2);
+	t.moveTo((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
+	t.lineTo((p3.x + p4.x) / 2, (p3.y + p4.y) / 2);
+	// draw a bezier
+	var b = g.createPath().setStroke({color: "red"});
+	b.moveTo(p1.x, p1.y);
+	b.curveTo(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
+	// move everything in a middle
+	g.setTransform([dojox.gfx.matrix.translate(250, 150), dojox.gfx.matrix.rotateg(axisAngle)]);
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>Approximation of an arc with bezier</h1>
+<!--<p><button onclick="makeShapes();">Make</button></p>-->
+<div id="test" style="width: 500px; height: 300px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_destroy.html b/dojox/gfx/tests/svgweb/test_destroy.html
new file mode 100644
index 0000000..8aaffb4
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_destroy.html
@@ -0,0 +1,58 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing surface.destroy()</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+surface = null;
+
+makeShapes = function(){
+	if(surface){
+		surface.destroy();
+		surface = null;
+		var t = dojo.byId("test").innerHTML;
+		if(t){
+			console.error("Garbage detected: " + t);
+		}else{
+			console.log("The parent node was cleaned up properly.");
+		}
+	}
+	surface = dojox.gfx.createSurface("test", 500, 500);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	var path = surface.createPath("");
+	// form concentric circles
+	var center = {x: 250, y: 250};
+	for(var r = 200; r > 0; r -= 30){
+		// make two 180 degree arcs to form a circle
+		var start = {x: center.x, y: center.y - r};
+		var end   = {x: center.x, y: center.y + r};
+		path.moveTo(start).arcTo(r, r, 0, true, true, end).arcTo(r, r, 0, true, true, start).closePath();
+	}
+	// set visual attributes
+	path.setFill("red").setStroke("black");
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+</script>
+</head>
+<body>
+	<h1>Testing surface.destroy()</h1>
+	<p><button onclick="makeShapes();">Regenerate</button></p>
+	<p><em>See the firebug log for detailed reports.</em></p>
+	<div id="test" style="width: 500px; height: 500px;"></div>
+	<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_fill.html b/dojox/gfx/tests/svgweb/test_fill.html
new file mode 100644
index 0000000..2ad9c3d
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_fill.html
@@ -0,0 +1,45 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing fill rule</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	var path = surface.createPath("");
+	// form concentric circles
+	var center = {x: 250, y: 250};
+	for(var r = 200; r > 0; r -= 30){
+		// make two 180 degree arcs to form a circle
+		var start = {x: center.x, y: center.y - r};
+		var end   = {x: center.x, y: center.y + r};
+		path.moveTo(start).arcTo(r, r, 0, true, true, end).arcTo(r, r, 0, true, true, start).closePath();
+	}
+	// set visual attributes
+	path.setFill("red").setStroke("black");
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+	<h1>Testing fill rule</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_fx.html b/dojox/gfx/tests/svgweb/test_fx.html
new file mode 100644
index 0000000..82b227a
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_fx.html
@@ -0,0 +1,104 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing animation</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.fx");
+dojo.require("dojo.colors");
+
+var rect, text;
+
+var makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	rect = surface.createRect({x: 100, y: 100, width: 300, height: 300}).
+		setFill("yellow").setStroke({
+			color: "green",
+			width: 5,
+			join: "round"
+		});
+	text = surface.createText({x: 250, y: 250, text: "Hello!", align: "middle"})
+		.setFill("black").setFont({family: "serif", size: "10pt"});
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+var animateStroke = function(){
+	var anim = dojox.gfx.fx.animateStroke({
+		duration:	5000,
+		shape: 		rect,
+		color:		{start: "green", end: "red"},
+		width:		{start: 5, end: 15},
+		join:		{values: ["bevel", "round"]}
+	});
+	dojo.byId("stroke").disabled = "disabled";
+	dojo.connect(anim, "onEnd", function(){ dojo.byId("stroke").disabled = ""; });
+	anim.play();
+};
+
+var animateFill = function(){
+	var anim = dojox.gfx.fx.animateFill({
+		duration:	5000,
+		shape: 		rect,
+		color:		{start: "yellow", end: "blue"}
+	});
+	dojo.byId("fill").disabled = "disabled";
+	dojo.connect(anim, "onEnd", function(){ dojo.byId("fill").disabled = ""; });
+	anim.play();
+};
+
+var animateFont = function(){
+	var anim = dojox.gfx.fx.animateFont({
+		duration:	5000,
+		shape: 		text,
+		variant:	{values: ["normal", "small-caps"]},
+		size:		{start: 10, end: 50, units: "pt"}
+	});
+	dojo.byId("font").disabled = "disabled";
+	dojo.connect(anim, "onEnd", function(){ dojo.byId("font").disabled = ""; });
+	anim.play();
+};
+
+var animateTransform = function(){
+	var anim = dojox.gfx.fx.animateTransform({
+		duration:	5000,
+		shape: 		text,
+		transform:	[
+			{name: "rotategAt", start: [0, 250, 250], end: [360, 350, 350]},
+			{name: "translate", start: [0, 0], end: [100, 100]}
+		]
+	});
+	dojo.byId("transform").disabled = "disabled";
+	dojo.connect(anim, "onEnd", function(){ dojo.byId("transform").disabled = ""; });
+	anim.play();
+};
+</script>
+</head>
+<body>
+<h1>Testing animation</h1>
+<p>
+	<button id="stroke" onclick="animateStroke();">Stroke</button>
+	 
+	<button id="fill" onclick="animateFill();">Fill</button>
+	 
+	<button id="font" onclick="animateFont();">Font</button>
+	 
+	<button id="transform" onclick="animateTransform();">Transform</button>
+</p>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_fx_shapes.html b/dojox/gfx/tests/svgweb/test_fx_shapes.html
new file mode 100644
index 0000000..34cf4b2
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_fx_shapes.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en">
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+        <title>Animate rectangles</title>
+        <!--<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dojo/dojo.xd.js"></script>-->
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+        <script type="text/javascript" charset="utf-8">
+            dojo.require("dojox.gfx");
+            dojo.require("dojo.fx");
+            dojo.require("dojo.fx.easing");
+            dojo.require("dojox.fx.easing");
+            
+            var WIDTH = 600, HEIGHT = 400,
+                BAR_GAP = 20, BAR_WIDTH = 76,
+                BAR_FILL = "red", BAR_STROKE = "black",
+                CHAIN_DURATION = 250, COMBINE_DURATION = 1000;
+            
+            var surface, rects = [];
+            
+            var enable = function(enabled){
+                // enable/disable controls on the page
+                dojo.query("input, select, button, textarea").attr("disabled", !enabled);
+            };
+            
+            var empty = {};
+            var populateSelect = function(from, select){
+                var module = dojo.getObject(from);
+                for(var name in module){
+                    if(name in empty){ continue; }
+                    var fun = module[name];
+                    if(dojo.isFunction(fun)){
+                        dojo.create("option", {
+                            value:     from + "." + name,
+                            selected:  name == "backOut",
+                            innerHTML: from + "." + name
+                        }, select);
+                    }
+                }
+            };
+            
+            var animate = function(){
+                // disable controls
+                enable(false);
+                
+                // get old heights
+                var oldHeights = dojo.map(rects, function(rect){ return rect.getShape().height; });
+                
+                // generate new heights (can't be 0 on IE/VML!)
+                var newHeights = dojo.map(rects, function(){ return 1 + Math.random() * (HEIGHT - 1); });
+                
+                // get parameters
+                var duration = dojo.byId("chain").checked ? CHAIN_DURATION : COMBINE_DURATION,
+                    easing = dojo.getObject(dojo.byId("easing").value);
+                
+                // create animations between heights
+                var animations = dojo.map(rects, function(rect, i){
+                    // create animation
+                    var anim = new dojo._Animation({
+                        duration: duration,
+                        easing:   easing,
+                        curve:    [oldHeights[i], newHeights[i]]
+                    });
+                    // update the rectangle on every tick
+                    dojo.connect(anim, "onAnimate", function(height){
+                        var shape = rect.getShape();
+                        shape.y = HEIGHT - height;
+                        shape.height = height;
+                        rect.setShape(shape);
+                    });
+                    return anim;
+                });
+                // combine all animations
+                var masterAnimation = dojo.byId("chain").checked ?
+                        dojo.fx.chain(animations) : dojo.fx.combine(animations);
+                // enable controls when they are done
+                dojo.connect(masterAnimation, "onEnd", function(){ enable(true); });
+                // start the animation
+                masterAnimation.play();
+            }
+            
+            var init = function(){
+                // create surface
+                surface = dojox.gfx.createSurface(dojo.byId("surface"), 600, 400);
+                
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+                // create rectangles
+                for(var w = BAR_GAP; w < WIDTH - BAR_WIDTH; w += BAR_WIDTH + BAR_GAP){
+                    rects.push(surface.createRect({
+                        x: w, y: HEIGHT, width: BAR_WIDTH, height: 1
+                    }).setFill(BAR_FILL).setStroke(BAR_STROKE));
+                }
+                // IE/VML doesn't allow height to be 0!
+                
+                // prepare and enable controls
+                populateSelect("dojo.fx.easing", "easing");
+                if(dojox.fx.easing !== dojo.fx.easing){
+                    populateSelect("dojox.fx.easing", "easing");
+                }
+                dojo.attr("chain", "checked", false);
+                dojo.connect(dojo.byId("animate"), "onclick", animate);
+                enable(true);
+	});
+	/* } */
+            };
+            
+            dojo.addOnLoad(init);
+        </script>
+    </head>
+    <body>
+        <p>
+            <button id="animate" disabled="disabled">Animate!</button> 
+            <label>Easing: <select id="easing" disabled="disabled"></select></label> 
+            <label><input id="chain" type="checkbox" disabled="disabled"> Chain (otherwise Combine)</label>
+        </p>
+        <div id="surface" style="width: 600px; height: 400px; border:1px solid #000;"></div>
+    </body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_gfx.html b/dojox/gfx/tests/svgweb/test_gfx.html
new file mode 100644
index 0000000..338e3d5
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_gfx.html
@@ -0,0 +1,565 @@
+<html>
+<head>
+	<title>Dojo Unified 2D Graphics</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+	<!-- test styles -->
+	<style type="text/css">
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/tests/css/dijitTests.css";
+		td { border: 1px solid black; text-align: left; vertical-align: top; }
+		v:group { text-align: left; }
+	</style>
+
+	<!-- required: dojo.js -->
+	<!-- SVGWEB { -->
+	<meta name="svg.render.forceflash" content="true"/>
+	<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+	<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+	<!-- } -->
+
+	<script type="text/javascript">
+
+		dojo.require("dojox.gfx");
+
+		var gTestContainer = null;
+		var gTests = {};
+
+		function isEqual(foo, bar, prefix){
+		    var flag = true;
+		    if(foo != bar ){
+		        console.debug(prefix+":"+foo + "!=" + bar + " try dig into it" );
+		        if( foo instanceof Array ) {
+		            for( var i = 0; i< foo.length; i++ ) {
+		                flag = isEqual(foo[i], bar[i], prefix+"["+i+"]") && flag;
+		            }
+		            flag = false;
+		        } else {
+		            for(var x in foo) {
+		                if(bar[x] != undefined ) {
+		                    flag = isEqual(foo[x], bar[x], prefix+"."+x) && flag;
+		                } else {
+		                    console.debug(prefix+":"+ x + " is undefined in bar" );
+		                    flag = false;
+		                }
+		            }
+		        }
+		    }
+		    return flag;
+		}
+
+
+		function getTestSurface(testName, testDescription, width, height){
+		   width = width ? width : 300;
+		   height = height ? height : 300;
+
+		   // Create a DOM node for the surface
+		   var testRow = document.createElement('tr');
+		   var testCell = document.createElement('td');
+		   var testHolder = document.createElement('div');
+		   testHolder.id = testName + '_holder';
+		   testHolder.style.width  = width;
+		   testHolder.style.height = height;
+
+		   testCell.appendChild(testHolder);
+		   testRow.appendChild(testCell);
+		   gTestContainer.appendChild(testRow);
+
+		   var descRow = document.createElement('tr');
+		   var desc = document.createElement('td');
+		   desc.innerHTML = testDescription;
+		   descRow.appendChild(desc);
+		   gTestContainer.appendChild(descRow);
+
+		   return dojox.gfx.createSurface(testHolder, width, height);
+		}
+
+		function addTest(testName, fn){
+		   gTests[testName] = fn;
+		}
+
+		function runTest_nodebug(testName){
+		   try {
+		      var t = gTests[testName];
+		      if (!t) {
+		         return 'no test named ' + t;
+		      }
+		      t(testName);
+		      return null; // the success condition
+		   } catch (e) {
+		      return e.message;
+		   }
+		}
+
+		function runTest_debug(testName){
+		      var t = gTests[testName];
+		      if (!t) {
+		         return 'no test named ' + t;
+		      }
+		      t(testName);
+		      return null; // the success condition
+		}
+
+		var runTest = dojo.config.isDebug ? runTest_debug : runTest_nodebug;
+
+		dojo.addOnLoad(function(){
+			gTestContainer = dojo.byId('testcontainer');
+			var rect = { x: 0, y: 0, width: 100, height: 100 };
+
+			addTest('rect', function(testName){
+				var surface = getTestSurface(testName, 'translucent rect with rounded stroke');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				var red_rect = surface.createRect(rect);
+				red_rect.setFill([255, 0, 0, 0.5]);
+				red_rect.setStroke({color: "blue", width: 10, join: "round" });
+				red_rect.setTransform({dx: 100, dy: 100});
+				//dojo.connect(red_rect.getNode(), "onclick", function(){ alert("red"); });
+				red_rect.connect("onclick", function(){ alert("red"); });
+				});
+				/* } */
+			});
+
+			addTest('straight_rect', function(testName){
+				var surface = getTestSurface(testName, 'translucent rect with no stroke');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				var blue_rect = surface.createRect(rect).setFill([0, 255, 0, 0.5]).setTransform({ dx: 100, dy: 100 });
+				//dojo.connect( blue_rect.getNode(), "onclick", function(){ blue_rect.setShape({width: blue_rect.getShape().width + 20}); });
+				blue_rect.connect("onclick", function(){ blue_rect.setShape({width: blue_rect.getShape().width + 20}); });
+				});
+				/* } */
+			});
+
+			addTest('rotated_rect', function(testName){
+				var surface = getTestSurface(testName, '30g CCW blue translucent rounded rect');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				console.debug('rotated_rect');
+				// anonymous 30 degree CCW rotated green rectangle
+				surface.createRect({r: 20})
+					.setFill([0, 0, 255, 0.5])
+					// rotate it around its center and move to (100, 100)
+					.setTransform([dojox.gfx.matrix.translate(100, 100), dojox.gfx.matrix.rotategAt(-30, 0, 0)])
+					;
+				});
+				/* } */
+			});
+
+			addTest('skew_rect', function(testName){
+				var surface = getTestSurface(testName, 'skewed rects' );
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				// anonymous red rectangle
+				surface.createRect(rect).setFill(new dojo.Color([255, 0, 0, 0.5]))
+					// skew it around LB point -30d, rotate it around LB point 30d, and move it to (100, 100)
+					.setTransform([dojox.gfx.matrix.translate(100, 100), dojox.gfx.matrix.rotategAt(-30, 0, 100), dojox.gfx.matrix.skewXgAt(30, 0, 100)]);
+				// anonymous blue rectangle
+				surface.createRect(rect).setFill(new dojo.Color([0, 0, 255, 0.5]))
+					// skew it around LB point -30d, and move it to (100, 100)
+					.setTransform([dojox.gfx.matrix.translate(100, 100), dojox.gfx.matrix.skewXgAt(30, 0, 100)]);
+				// anonymous yellow rectangle
+				surface.createRect(rect).setFill(new dojo.Color([255, 255, 0, 0.25]))
+					// move it to (100, 100)
+					.setTransform(dojox.gfx.matrix.translate(100, 100));
+				});
+				/* } */
+			});
+
+			addTest('matrix_rect', function(testName){
+				var surface = getTestSurface(testName, 'all matrix operations, check debug output for more details');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+
+				var group = surface.createGroup();
+		
+				var blue_rect = group.createRect(rect).setFill([0, 0, 255, 0.5]).applyTransform(dojox.gfx.matrix.identity);
+				console.debug( "blue_rect: rect with identity" );
+
+				group.createRect(rect).setFill([0, 255, 0, 0.5]).applyTransform(dojox.gfx.matrix.translate(30, 40));
+				console.debug( "lime_rect: translate(30,40) " );
+		
+				group.createRect(rect).setFill([255, 0, 0, 0.5]).applyTransform(dojox.gfx.matrix.rotateg(-30));
+				console.debug( "red_rect: rotate 30 degree counterclockwise " );
+
+				group.createRect(rect).setFill([0, 255, 255, 0.5])
+					.applyTransform(dojox.gfx.matrix.scale({x:1.5, y:0.5}))
+					.applyTransform(dojox.gfx.matrix.translate(-40, 220))
+					;
+				console.debug( "lightblue_rect: scale(1.5, 0.5)" );
+
+				group.createRect(rect).setFill([0, 0, 255, 0.5]).setFill([255, 0, 255, 0.5]).applyTransform(dojox.gfx.matrix.flipX);
+				console.debug( "pink_rect: flipX" );
+
+				group.createRect(rect).setFill([0, 0, 255, 0.5]).setFill([255, 255, 0, 0.5]).applyTransform(dojox.gfx.matrix.flipY);
+				console.debug( "yellow_rect: flipY" );
+
+				group.createRect(rect).setFill([0, 0, 255, 0.5]).setFill([128, 0, 128, 0.5]).applyTransform(dojox.gfx.matrix.flipXY);
+				console.debug( "purple_rect: flipXY" );
+
+				group.createRect(rect).setFill([0, 0, 255, 0.5]).setFill([255, 128, 0, 0.5]).applyTransform(dojox.gfx.matrix.skewXg(-15));
+				console.debug( "purple_rect: skewXg 15 degree" );
+
+				group.createRect(rect).setFill([0, 0, 255, 0.5]).setFill([0, 0, 0, 0.5]).applyTransform(dojox.gfx.matrix.skewYg(-50));
+				console.debug( "black_rect: skewXg 50 degree" );
+
+				// move
+				group
+					.setTransform({ xx: 1.5, yy: 0.5, dx: 100, dy: 100 })
+					.applyTransform(dojox.gfx.matrix.rotateg(-30))
+					;
+				});
+				/* } */
+			});
+
+			addTest('attach', function(testName){
+				var surface = getTestSurface(testName, 'Attach to existed shape');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				var red_rect = surface.createRect(rect)
+					.setShape({ width: 75 })
+					.setFill([255, 0, 0, 0.5])
+					.setStroke({ color: "blue", width: 1 })
+					.setTransform({ dx: 50, dy: 50, xx: 1, xy: 0.5, yx: 0.7, yy: 1.1 })
+					;
+
+				console.debug("attaching !");
+				// now attach it!
+				var ar = dojox.gfx.attachNode(red_rect.rawNode);
+				console.assert( ar.rawNode == red_rect.rawNode );
+
+				// FIXME: more generic method to compare two dictionary?
+				console.debug("attach shape: ");
+				isEqual(ar.shape, red_rect.shape, "rect.shape");
+				console.debug("attach matrix: ");
+				isEqual(ar.matrix, red_rect.matrix, "rect.matrix");
+				console.debug("attach strokeStyle: ");
+				isEqual(ar.strokeStyle, red_rect.strokeStyle, "rect.strokeStyle");
+				console.debug("attach fillStyle: ");
+				isEqual(ar.fillStyle, red_rect.fillStyle, "rect.fillStyle");
+				});
+				/* } */
+			});
+	
+			// test circle
+			addTest('circle', function(testName){
+				var surface = getTestSurface(testName, 'translucent green circle');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				var circle = { cx: 130, cy: 130, r: 50 };
+				surface.createCircle(circle).setFill([0, 255, 0, 0.5]).setTransform({ dx: 20, dy: 20 });
+				});
+				/* } */
+			});
+
+			// test line
+			addTest('line', function(testName){
+				var surface = getTestSurface(testName, 'straight red line');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				var line = { x1: 20, y1: 20, x2: 100, y2: 120 };
+				surface.createLine(line).setFill([255, 0, 0, 0.5]).setStroke({color: "red", width: 1}).setTransform({ dx:70, dy: 100 });
+				});
+				/* } */
+			});
+
+			// test ellipse 
+			addTest('ellipse', function(testName){
+				var surface = getTestSurface(testName, 'translucent cyan ellipse');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				var ellipse = { cx: 50, cy: 80, rx: 50, ry: 80 };
+				surface.createEllipse(ellipse).setFill([0, 255, 255, 0.5]).setTransform({ dx: 30, dy: 70 });
+				});
+				/* } */
+			});
+
+			// test polyline
+			addTest('polyline', function(testName){
+				var surface = getTestSurface(testName, 'unfilled open polyline');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				var points = [ {x: 10, y: 20}, {x: 40, y: 70}, {x: 120, y: 50}, {x: 90, y: 90} ];
+				surface.createPolyline(points).setFill(null).setStroke({ color: "blue", width: 1 }).setTransform({ dx: 15, dy: 0 });
+				});
+				/* } */
+			});
+
+			// test polygon
+			addTest('polygon', function(testName){
+				var surface = getTestSurface(testName, 'filled polygon');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				var points2 = [{x: 100, y: 0}, {x: 200, y: 40}, {x: 180, y: 150}, {x: 60, y: 170}, {x: 20, y: 100}];
+				surface.createPolyline(points2).setFill([0, 128, 255, 0.6]).setTransform({dx:30, dy: 20});
+				});
+				/* } */
+			});
+
+			// test path: lineTo, moveTo, closePath
+			addTest('lineTo', function(testName){
+				var surface = getTestSurface(testName, 'lineTo, moveTo, closePath');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				surface.createPath()
+					.moveTo(10, 20).lineTo(80, 150)
+					.setAbsoluteMode(false).lineTo(40, 0)
+					.setAbsoluteMode(true).lineTo(180, 100)
+					.setAbsoluteMode(false).lineTo(0, -30).lineTo(-30, -50)
+					.closePath()
+					.setStroke({ color: "red", width: 1 })
+					.setFill(null)
+					.setTransform({ dx: 10, dy: 18 })
+					;
+				});
+				/* } */
+			});
+
+			addTest('setPath', function(testName){
+				var surface = getTestSurface(testName, 'setPath example with lineTo moveTo');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				surface.createPath()
+					.moveTo(10, 20).lineTo(80, 150)
+					.setAbsoluteMode(false).lineTo(40,0)
+					.setAbsoluteMode(true).lineTo(180, 100)
+					.setAbsoluteMode(false).lineTo(0, -30).lineTo(-30, -50)
+					.curveTo(10, -80, -150, -10, -90, -10)
+					.closePath()
+					.setStroke({ color: "red", width: 1 })
+					.setFill(null)
+					.setTransform({ dx: 10, dy: 58 })
+					;
+
+				surface.createPath({ path: "M10,20 L80,150 l40,0 L180,100 l0,-30 l-30,-50 c10,-80 -150,-10 -90,-10 z" })
+					.setFill(null)
+					.setStroke({ color: "blue", width: 1 })
+					.setTransform({ dx: 50, dy: 78 })
+					;
+				});
+				/* } */
+			});
+
+			// test arcTo 
+			addTest('arcTo', function(testName){
+				var surface = getTestSurface(testName, 'arcTo: from 0 to 360 degree, w/ 30 degree of x axis rotation, rendered with different color');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+
+				var m = dojox.gfx.matrix;
+				var g1 = surface.createGroup();
+				var g2 = g1.createGroup();
+
+				var rx = 100, ry = 60, xRotg = 30;
+				var startPoint = m.multiplyPoint(m.rotateg(xRotg), {x: -rx, y: 0  });
+				var endPoint   = m.multiplyPoint(m.rotateg(xRotg), {x: 0,   y: -ry});
+	    
+				var re1 = g1.createPath()
+					.moveTo(startPoint)
+					.arcTo(rx, ry, xRotg, true, false, endPoint)
+					.setStroke({color: "red"})
+					;
+				var ge1 = g1.createPath()
+					.moveTo(re1.getLastPosition())
+					.arcTo(rx, ry, xRotg, false, false, startPoint)
+					.setStroke({color: "blue"})
+					;
+				var re2 = g2.createPath()
+					.moveTo(startPoint)
+					.arcTo(rx, ry, xRotg, false, true, endPoint)
+					.setStroke({color: "red"})
+					;
+				var ge2 = g2.createPath()
+					.moveTo(re2.getLastPosition())
+					.arcTo(rx, ry, xRotg, true, true, startPoint)
+					.setStroke({color: "blue"})
+					;
+			
+				g1.setTransform({dx: 150, dy: 150});
+				g2.setTransform({dx: 10,  dy: 10});
+				});
+				/* } */
+			});
+
+			// test path: curveTo, smoothCurveTo
+			addTest('curveTo', function(testName) {
+				var surface = getTestSurface(testName, 'curveTo, smoothCurveTo');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				surface.createPath()
+					.moveTo(10, 20).curveTo(50, 50, 50, 100, 150, 100).smoothCurveTo(300, 300, 200, 200)
+					.setStroke({ color: "green", width: 1 }).setFill(null).setTransform({ dx: 10, dy: 30 })
+					;
+				});
+				/* } */
+			});
+
+			// test path: curveTo, smoothCurveTo with relative.
+			addTest('curveTo2', function(testName) {
+				var surface = getTestSurface(testName, 'curveTo, smoothCurveTo with relative coordination');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				surface.createPath()
+					.moveTo(10, 20).curveTo(50, 50, 50, 100, 150, 100)
+					.setAbsoluteMode(false).smoothCurveTo(150, 200, 50, 100)
+					.setAbsoluteMode(true).smoothCurveTo(50, 100, 10, 230)
+					.setStroke({ color: "green", width: 1 }).setFill(null).setTransform({ dx: 10, dy: 30 })
+					;
+				});
+				/* } */
+			});
+
+			// test path: curveTo, smoothCurveTo with relative.
+			addTest('qCurveTo', function(testName) {
+				var surface = getTestSurface(testName, 'qCurveTo, qSmoothCurveTo' );
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				surface.createPath()
+					.moveTo(10, 15).qCurveTo(50, 50, 100, 100).qSmoothCurveTo(150, 20)
+					.setStroke({ color: "green", width: 1 }).setFill(null).setTransform({ dx: 10, dy: 30 })
+					;
+				});
+				/* } */
+			});
+
+			addTest('qCurveTo2', function(testName) {
+				var surface = getTestSurface(testName, 'qCurveTo, qSmoothCurveTo with relative' );
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				surface.createPath()
+					.moveTo(10, 20).qCurveTo(50, 50, 100, 100)
+					.setAbsoluteMode(false).qSmoothCurveTo(50, -80)
+					.setAbsoluteMode(true).qSmoothCurveTo(200, 80)
+					.setStroke({ color: "green", width: 1 }).setFill(null).setTransform({ dx: 10, dy: 30 })
+					;
+				});
+				/* } */
+			});
+
+			// test defines, linearGradient
+			addTest('linearGradient', function(testName) {
+				var surface = getTestSurface(testName, 'linear gradient fill');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				// this is an example to split the linearGradient from setFill:
+				var lg = {
+					type: "linear",
+					x1: 0, y1: 0, x2: 75, y2: 50,
+					colors: [
+						{ offset: 0, color: "#F60" },
+						{ offset: 1, color: "#FF6" }
+					]
+				};
+				surface.createRect(rect).setFill(lg).setTransform({ dx: 40, dy: 100 });
+				});
+				/* } */
+			});
+
+			// TODO: test radialGradient
+			addTest('radialGradient', function(testName) {
+				var surface = getTestSurface(testName, 'radial gradient fill');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				// this is a total inline implementation compared with previous one.
+				var rg = {
+					type: "radial",
+					cx: 100, cy: 100, r: 100,
+					colors: [
+						{ offset:   0, color: "red" },
+						{ offset: 0.5, color: "green" },
+						{ offset:   1, color: "blue" }
+					]
+				};
+		
+				surface.createCircle({cx: 100, cy: 100, r: 100})
+					.setStroke({})
+					.setFill(rg)
+					.setTransform({dx: 40, dy: 30})
+					;
+		//		surface.createRect(rect)
+		//			.setShape({width: 200})
+		//			.setStroke({})
+		//			.setFill(rg)
+		//			.setTransform({dx: 40, dy: 30})
+		//			;
+				});
+				/* } */
+			});
+
+			addTest('attach_gradient', function(testName) {
+				var surface = getTestSurface(testName, 'attach gradient fill');
+				/* SVGWEB { */
+				surface.whenLoaded(function() {
+				// this is an example to split the linearGradient from setFill:
+				var lg = {
+					type: "linear",
+					x1: 0, y1: 0, x2: 75, y2: 50,
+					colors: [
+						{ offset:   0, color: "#F60" },
+						{ offset: 0.5, color: "#FAF" },
+						{ offset:   1, color: "#FF6" }
+					]
+				};
+
+				var lgr = surface.createRect(rect).setFill(lg).setTransform({ dx: 40, dy: 100 });
+
+				var ar = dojox.gfx.attachNode(lgr.rawNode);
+				// FIXME: more generic method to compare two dictionary?
+				console.debug("attach_gradient!");
+
+				console.debug("attach shape: ");
+				isEqual(lgr.shape, ar.shape, "rect.shape");
+				console.debug("attach matrix: ");
+				isEqual(lgr.matrix, ar.matrix, "rect.matrix");
+				console.debug("attach strokeStyle: ");
+				isEqual(lgr.strokeStyle, ar.strokeStyle, "rect.strokeStyle");
+				console.debug("attach fillStyle: ");
+				isEqual(lgr.fillStyle.gradient, ar.fillStyle.gradient, "rect.fillStyle.gradient");
+				//isEqual(lgr.fillStyle.id, ar.fillStyle.id, "rect.fillStyle.id");
+				});
+				/* } */
+			});
+
+			var gTestsToRun = [
+				'rect',
+				'straight_rect',
+				'rotated_rect',
+				'skew_rect',
+				'matrix_rect', 
+				//'attach',
+				//'attach_gradient',
+				'circle',
+				'arcTo',
+				'line',
+				'ellipse',
+				'polyline',
+				'polygon',
+				'lineTo',
+				'setPath',
+				'curveTo',
+				'curveTo2',
+				'qCurveTo',
+				'qCurveTo2',
+				'linearGradient',
+				'radialGradient'
+			];
+
+			for (var i = 0; i < gTestsToRun.length; ++i) {
+				var testName = gTestsToRun[i];
+				var err = runTest(testName);
+				if (err) {
+					getTestSurface(testName, testName + ' FAILED (' + err + ')');
+				}
+			}
+
+		}); // end onload
+		</script>
+</head>
+<body>
+	<h1 class="testTitle">dojox.gfx tests</h1>
+		<table>
+			<tbody id="testcontainer">
+			</tbody>
+		</table>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_gradient.html b/dojox/gfx/tests/svgweb/test_gradient.html
new file mode 100644
index 0000000..bc71e36
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_gradient.html
@@ -0,0 +1,77 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojo.colors"); // pull in CSS3 color names
+
+makeShapes = function(){
+	var SIDE = 10;
+	var fillObj = {
+		colors: [
+			{ offset: 0,   color: [255, 255, 0, 0] },
+			{ offset: 0.5, color: "orange" },
+			{ offset: 1,   color: [255, 255, 0, 0] }
+		]
+	};
+	var surface = dojox.gfx.createSurface(dojo.byId("grad"), 300, 300);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	var start = new Date().getTime();
+	var suspendId = surface.rawNode.suspendRedraw(10000);
+	
+	// create a background
+	for(var i = 0; i < 300; i += SIDE){
+		for(var j = 0; j < 300; j += SIDE){
+			surface.
+				createRect({x: j, y: i, width: 10, height: 10}).
+				setFill((Math.floor(i / SIDE) + Math.floor(j / SIDE)) % 2 ? "lightgrey" : "white");
+		}
+	}
+	// create a rect
+	surface.createRect({ 
+		width:  300,
+		height: 100
+	}).setFill(dojo.mixin({
+		type: "linear",
+		x1: 0, y1: 0,
+		x2: 300, y2: 0
+	}, fillObj));
+	// create a circle
+	surface.createEllipse({
+		cx: 150,
+		cy: 200,
+		rx: 100,
+		ry: 100
+	}).setFill(dojo.mixin({
+		type: "radial",
+		cx: 150,
+		cy: 200
+	}, fillObj));
+	
+	surface.rawNode.unsuspendRedraw(suspendId);
+	//alert(new Date().getTime() - start);
+	});
+	/* } */
+};
+dojo.addOnLoad(makeShapes);
+</script>
+<style type="text/css">
+#grad { width: 300px; height: 300px; }
+</style>
+</head>
+<body>
+<h1>dojox.gfx Alpha gradient test</h1>
+<div id="grad"></div>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_group1.html b/dojox/gfx/tests/svgweb/test_group1.html
new file mode 100644
index 0000000..faea4af
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_group1.html
@@ -0,0 +1,70 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var surface = null;
+var g1 = null;
+var g2 = null;
+var r1 = null;
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface(document.getElementById("test"), 500, 500);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	// make a checkerboard
+	for(var i = 0; i < 500; i += 100){
+		for(var j = 0; j < 500; j += 100){
+			if(i % 200 == j % 200) {
+				surface.createRect({ x: i, y: j }).setFill([255, 0, 0, 0.1]);
+			}
+		}
+	}
+	// create groups and shapes
+	g1 = surface.createGroup();
+	g2 = surface.createGroup();
+	r1 = surface.createRect({x: 200, y: 200}).setFill("green").setStroke({});
+	g1.setTransform({dy: -100});
+	//g2.setTransform(dojox.gfx.matrix.rotateAt(-45, 250, 250));
+	g2.setTransform({dx: 100, dy: -100});
+	});
+	/* } */
+};
+
+switchRect = function(){
+	var radio = document.getElementsByName("switch");
+	if(radio[0].checked){
+		surface.add(r1);
+	}else if(radio[1].checked){
+		g1.add(r1);
+	}else if(radio[2].checked){
+		g2.add(r1);
+	}
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Group tests</h1>
+<p>
+<input type="radio" name="switch" id="r1_s" checked="checked" onclick="switchRect()" /><label for="r1_s">Rectangle belongs to the surface</label><br />
+<input type="radio" name="switch" id="r1_g1" onclick="switchRect()" /><label for="r1_g1">Rectangle belongs to the group #1</label><br />
+<input type="radio" name="switch" id="r1_g2" onclick="switchRect()" /><label for="r1_g2">Rectangle belongs to the group #2</label>
+</p>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_group2.html b/dojox/gfx/tests/svgweb/test_group2.html
new file mode 100644
index 0000000..24dde60
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_group2.html
@@ -0,0 +1,54 @@
+<html>
+<head>
+<title>Testing add/remove shape</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+	@import "../../../../dijit/themes/tundra/tundra.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dijit.form.CheckBox");
+dojo.require("dojo.parser");
+
+var surface = null, shape = null;
+
+createSurface = function(){
+	surface = dojox.gfx.createSurface("test", 300, 300);
+};
+
+flip = function(){
+	if(dojo.byId("cb").checked){
+		if(!shape){
+			//shape = surface.createRect({x: 100, y: 100, width: 100, height: 100})
+			shape = surface.createCircle({cx: 150, cy : 150, r: 50})
+				.setFill("yellow").setStroke({color: "red", width: 3});
+		}else{
+			surface.add(shape);
+		}
+	}else{
+		surface.remove(shape);
+	}
+}
+
+dojo.addOnLoad(createSurface);
+</script>
+
+
+</head>
+
+<body class="tundra">
+<h1>Testing add/remove shape</h1>
+<p>
+	<input type="checkbox" dojoType="dijit.form.CheckBox" id="cb" name="cb" onClick="flip()">
+	<label for="cb">Add shape to the surface</label>
+</p>
+<div id="test" style="width: 300px; height: 300px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_image1.html b/dojox/gfx/tests/svgweb/test_image1.html
new file mode 100644
index 0000000..7edc570
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_image1.html
@@ -0,0 +1,80 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing image</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var image = null, grid_size = 500, grid_step = 50,
+	m = dojox.gfx.matrix;
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 800, 600);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+		for(var i = 0; i <= grid_size; i += grid_step){
+			surface.createLine({x1: 0, x2: grid_size, y1: i, y2: i}).setStroke("black");
+			surface.createLine({y1: 0, y2: grid_size, x1: i, x2: i}).setStroke("black");
+		}
+	    image = surface.createImage({width: 150, height: 100, src: "../images/eugene-sm.jpg"});
+	    image.connect("onclick", function(){ alert("You didn't expect a download, did you?"); });
+	});
+	/* } */
+};
+
+transformImage = function(){
+	var radio = document.getElementsByName("switch");
+	if(radio[0].checked){
+        image.setTransform({});
+	}else if(radio[1].checked){
+        image.setTransform({dx: 100, dy: 50});
+	}else if(radio[2].checked){
+        image.setTransform(m.rotateg(15));
+	}else if(radio[3].checked){
+        image.setTransform([{dx: 70, dy: 90}, {xx: 1.5, yy: 0.5}]);
+	}else if(radio[4].checked){
+        image.setTransform([m.rotateg(15), m.skewXg(30)]);
+	}
+	var shift = document.getElementsByName("shift");
+	if(shift[0].checked){
+		image.setShape({x: 0, y: 0});
+	}else if(shift[1].checked){
+		image.setShape({x: 100, y: 50});
+	}else if(shift[2].checked){
+		image.setShape({x: 0, y: 0});
+		image.applyRightTransform({dx: 100, dy: 50});
+	}
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Image tests</h1>
+<p>Note: Silverlight doesn't allow downloading images when run from a file system. This demo should be run from a server.</p>
+<p>
+<input type="radio" name="switch" id="r1_reset" checked onclick="transformImage()" /><label for="r1_reset">Reset Image</label><br />
+<input type="radio" name="switch" id="r1_move" onclick="transformImage()" /><label for="r1_move">Move Image</label><br />
+<input type="radio" name="switch" id="r1_rotate" onclick="transformImage()" /><label for="r1_rotate">Rotate Image</label><br />
+<input type="radio" name="switch" id="r1_scale" onclick="transformImage()" /><label for="r1_scale">Scale Image</label><br />
+<input type="radio" name="switch" id="r1_skew" onclick="transformImage()" /><label for="r1_skew">Skew Image</label><br />
+</p>
+<p>
+<input type="radio" name="shift" id="r2_none" checked onclick="transformImage()" /><label for="r2_none">Place image at (0, 0)</label><br />
+<input type="radio" name="shift" id="r2_origin" onclick="transformImage()" /><label for="r2_origin">Place image at (100, 50)</label><br />
+<input type="radio" name="shift" id="r2_shift" onclick="transformImage()" /><label for="r2_shift">Shift image by (100, 50)</label>
+</p>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_image2.html b/dojox/gfx/tests/svgweb/test_image2.html
new file mode 100644
index 0000000..6a3a32e
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_image2.html
@@ -0,0 +1,52 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing image</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var grid_size = 500, grid_step = 50;
+var main = null, g = null, image = null, rect = null;
+
+makeShapes = function(){
+	var s = dojox.gfx.createSurface("test", 800, 600);
+	/* SVGWEB { */
+	s.whenLoaded(function() {
+	for(var i = 0; i <= grid_size; i += grid_step){
+		s.createLine({x1: 0, x2: grid_size, y1: i, y2: i}).setStroke("black");
+		s.createLine({y1: 0, y2: grid_size, x1: i, x2: i}).setStroke("black");
+	}
+
+	main = s.createGroup();
+	rect = main.createRect({x: 0, y: 0, width: 200, height: 200}).setStroke("black").setFill(new dojo.Color([255, 0, 255, 0.5]));
+	rect.connect("onclick", function(){ alert("rect"); })
+    
+	image = s.createImage({width: 150, height: 100, src: "../images/eugene-sm.jpg"});
+	image.connect("onclick", function(){ alert("image"); })
+	
+	main.add(image);
+	});
+	/* } */
+};
+
+trans = function(){
+	var x = 1;
+	main.setTransform([dojox.gfx.matrix.rotategAt(45, 200, 200), {dx: 200, dy: 200}]);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<p>Testing image:<br /><button onclick="trans();">Trans</button></p>
+<p>Note: Silverlight doesn't allow downloading images when run from a file system. This demo should be run from a server.</p>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_image3.html b/dojox/gfx/tests/svgweb/test_image3.html
new file mode 100644
index 0000000..f0b501b
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_image3.html
@@ -0,0 +1,77 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing image 3</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var surface, image = null, grid_size = 1000, grid_step = 50, surface2, image2
+	m = dojox.gfx.matrix;
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface("test", 800, 600);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	for(var i = 0; i <= grid_size; i += grid_step){
+		surface.createLine({x1: 0, x2: grid_size, y1: i, y2: i}).setStroke("black");
+		surface.createLine({y1: 0, y2: grid_size, x1: i, x2: i}).setStroke("black");
+	}
+    image = surface.createImage({width: 150, height: 100, src: "../images/eugene-sm.jpg"});
+    image.connect("onclick", function(){ alert("You didn't expect a download, did you?"); });
+	});
+	/* } */
+
+    //create second test
+    surface2 = dojox.gfx.createSurface("test2", 600, 600);
+	/* SVGWEB { */
+	surface2.whenLoaded(function() {
+    image2 = surface2.createImage({width: 150, height: 100, src: "../images/eugene-sm.jpg"});
+	});
+	/* } */
+};
+
+transformImage = function(){
+	if(window.scaled){
+		surface.setDimensions(800,600);
+		image.setTransform({});
+                
+		surface2.setDimensions(600,600);
+		image2.setTransform({});
+	}else{
+		surface.setDimensions(1000,600);
+	    image.setTransform({xx: 6, yy: 6});
+
+            surface2.setDimensions(800,600);
+            image2.setTransform({xx: 5, yy: 5});
+	}
+	window.scaled=!window.scaled;
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Image tests</h1>
+<p>Clicking the following button should enlarge the surface and the image.<br>
+In the first Test: The image should not be cropped on the right and the background of grid should be red.<br>
+In the secondd test: the cavas should stay the same size, the image is increased and scrollbars appear
+	</p>
+<p>
+<input type="button" onclick="transformImage()" value="scale/reset"/><br />
+</p>
+<div id="test" style="background-color:red"></div>
+<p>second test with overflow=auto</p>
+<div style="overflow:auto;background-color:red;width:602px;height:602px;"><div id="test2"></div></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_image4.html b/dojox/gfx/tests/svgweb/test_image4.html
new file mode 100644
index 0000000..12f9deb
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_image4.html
@@ -0,0 +1,58 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing image 4</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojo.colors");
+
+makeShapes = function(){
+    var g = dojox.gfx, m = g.matrix;
+    
+	var grid_size = 200, grid_step = 20,
+        surface = g.createSurface("test", grid_size, grid_size)
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	for(var i = 0; i <= grid_size; i += grid_step){
+		surface.createLine({x1: 0, x2: grid_size, y1: i, y2: i}).setStroke("grey");
+		surface.createLine({y1: 0, y2: grid_size, x1: i, x2: i}).setStroke("grey");
+	}
+    
+    var rect1 = surface.createRect({x: 50, y: 50, width: 100, height: 100, r: 5}).setFill("red").setStroke("black");
+    var img1  = surface.createImage({width: 75, height: 50, src: "../images/eugene-sm.jpg"}).
+                    setTransform([m.translate(50, 0), m.rotateg(45)]);
+    var rect2 = surface.createRect({x: 75, y: 25, width: 50, height: 150, r: 5}).setFill("yellow").setStroke("black");
+    var img2  = surface.createImage({width: 75, height: 50, src: "../images/eugene-sm.jpg"}).
+                    setTransform([m.translate(50, 120), m.rotateg(-45)]);
+    var rect3 = surface.createRect({x: 25, y: 75, width: 150, height: 50, r: 5}).setFill("green").setStroke("black");
+
+    img1.connect("onclick", function(){ alert("image #1"); });
+    img2.connect("onclick", function(){ alert("image #2"); });
+    
+    rect1.connect("onclick", function(){ alert("red"); });
+    rect2.connect("onclick", function(){ alert("yellow"); });
+    rect3.connect("onclick", function(){ alert("green"); });
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Image event tests</h1>
+<p>Note: Silverlight doesn't allow downloading images when run from a file system. This demo should be run from a server.</p>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_image5.html b/dojox/gfx/tests/svgweb/test_image5.html
new file mode 100644
index 0000000..07970fa
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_image5.html
@@ -0,0 +1,67 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing image 5</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.move");
+dojo.require("dojo.colors");
+
+makeShapes = function(){
+    var g = dojox.gfx, m = g.matrix;
+    
+	var grid_size = 800, grid_step = 50,
+        surface = g.createSurface("test", 800, 600)
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	for(var i = 0; i <= grid_size; i += grid_step){
+		surface.createLine({x1: 0, x2: grid_size, y1: i, y2: i}).setStroke("grey");
+		surface.createLine({y1: 0, y2: grid_size, x1: i, x2: i}).setStroke("grey");
+	}
+    
+    var rect1 = surface.createRect({x: 0, y: 0, width: 300, height: 200, r: 5}).setFill("red").setStroke("black");
+    var img1  = surface.createImage({width: 300, height: 200, src: "../images/eugene-sm.jpg"}).setTransform({dx: 50, dy: 50});
+    var rect2 = surface.createRect({x: 100, y: 100, width: 300, height: 200, r: 5}).setFill("yellow").setStroke("black");
+    var img2  = surface.createImage({width: 300, height: 200, src: "../images/eugene-sm.gif"}).setTransform({dx: 150, dy: 150});
+    var rect3 = surface.createRect({x: 200, y: 200, width: 300, height: 200, r: 5}).setFill("green").setStroke("black");
+    var img3  = surface.createImage({width: 300, height: 200, src: "../images/eugene-sm.png"}).setTransform({dx: 250, dy: 250});
+    var rect4 = surface.createRect({x: 300, y: 300, width: 300, height: 200, r: 5}).setFill("blue").setStroke("black");
+    
+	new g.Moveable(rect1);
+	new g.Moveable(rect2);
+	new g.Moveable(rect3);
+	new g.Moveable(rect4);
+
+	new g.Moveable(img1);
+	new g.Moveable(img2);
+	new g.Moveable(img3);
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Image opacity and move tests</h1>
+<p>Note: Silverlight doesn't allow downloading images when run from a file system. This demo should be run from a server.</p>
+<div id="test"></div>
+<p>That's how images should look like (light yellow background):</p>
+<p style="background-color: #ffe; padding: 1em; border: 1px solid black;">
+    <img src="../images/eugene-sm.jpg">
+    <img src="../images/eugene-sm.gif">
+    <img src="../images/eugene-sm.png">
+</p>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_linearGradient.html b/dojox/gfx/tests/svgweb/test_linearGradient.html
new file mode 100644
index 0000000..9a5c5f3
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_linearGradient.html
@@ -0,0 +1,75 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojo.colors");
+
+makeShapes = function(){
+	var lg1 = {
+		type: "linear",
+		x1: 0, y1: 0,
+		x2: 300, y2: 0,
+		colors: [
+			{ offset: 0,   color: [0, 0, 0, 0] },
+			{ offset: 0.1, color: "#000000" },
+			{ offset: 0.2, color: "red" },
+			{ offset: 0.3, color: "rgb(0,255,0)" },
+			{ offset: 0.4, color: "blue" },
+			{ offset: 0.5, color: "#ff0" },
+			{ offset: 0.6, color: [128] },
+			{ offset: 0.7, color: [128, 128, 64] },
+			{ offset: 1,   color: [0, 255, 0, 0] }
+		]
+	};
+	var lg2 = {
+		type: "linear",
+		x1: 0, y1: 0,
+		x2: 300, y2: 0,
+		colors: [
+			{ offset: 0.2, color: "red" },
+			{ offset: 0.3, color: "yellow" }
+		]
+	};
+	var surface = dojox.gfx.createSurface(dojo.byId("grad"), 300, 300);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	var group = surface.createGroup();
+	var rect1 = surface.createRect({ 
+		width:  300,
+		height: 100
+	});
+	rect1.setFill(lg1);
+	var rect2 = surface.createRect({ 
+		y: 150,
+		width:  300,
+		height: 100
+	});
+	rect2.setFill(lg2);
+	group.add(rect1);
+	group.add(rect2);
+	});
+	/* } */
+};
+dojo.addOnLoad(makeShapes);
+</script>
+<style>
+v:group { text-align: left; }
+#grad { width: 300px; height: 300px; }
+</style>
+</head>
+<body>
+<h1>dojox.gfx Linear Gradient test</h1>
+<div id="grad"></div>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_linestyle.html b/dojox/gfx/tests/svgweb/test_linestyle.html
new file mode 100644
index 0000000..fa04db5
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_linestyle.html
@@ -0,0 +1,43 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface(document.getElementById("test"), 500, 500);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	var styles = ["none", "Solid", "ShortDash", "ShortDot", "ShortDashDot", "ShortDashDotDot", 
+		"Dot", "Dash", "LongDash", "DashDot", "LongDashDot", "LongDashDotDot"];
+	var font = "normal normal normal 10pt Arial";	// CSS font style
+	var y_offset = dojox.gfx.normalizedLength("4pt");
+	for(var i = 0; i < styles.length; ++i){
+		var y = 20 + i * 20;
+		surface.createText({x: 140, y: y + y_offset, text: styles[i], align: "end"}).setFont(font).setFill("black");
+		surface.createLine({x1: 150, y1: y, x2: 490, y2: y}).setStroke({style: styles[i], width: 3, cap: "round"});
+	}
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+	<h1>dojox.gfx: Line style test</h1>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_pattern.html b/dojox/gfx/tests/svgweb/test_pattern.html
new file mode 100644
index 0000000..584ab15
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_pattern.html
@@ -0,0 +1,43 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing pattern</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+    var pattern = {
+        type: "pattern",
+        x: 0, y: 0, width: 75, height: 50,
+        src: "../images/eugene-sm.jpg"
+    };
+	var ellipse = {cx: 400, cy: 200, rx: 350, ry: 150};
+	var surface = dojox.gfx.createSurface("test", 800, 600);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	surface.createEllipse(ellipse)
+        .setStroke({color: "blue", width: 1 })
+        .setFill(pattern);
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+	<h1>dojox.gfx Pattern test</h1>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_poly.html b/dojox/gfx/tests/svgweb/test_poly.html
new file mode 100644
index 0000000..e21321a
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_poly.html
@@ -0,0 +1,49 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing polyline and line transforms</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	var line = surface.createLine({x1: 250, y1: 50, x2: 250, y2: 250})
+		.setStroke({color: "blue"})
+		;
+	var poly = surface.createPolyline([{x: 250, y: 250}, {x: 300, y: 300}, {x: 250, y: 350}, {x: 200, y: 300}, {x: 250, y: 250}])
+		.setStroke({color: "blue"})
+		;
+	var rotate = dojox.gfx.matrix.rotategAt(5, 250, 250);
+	//var rotate = dojox.gfx.matrix.rotategAt(0.4, 250, 250);
+		
+	window.setInterval(function() {
+			line.applyTransform(rotate);
+			poly.applyTransform(rotate);
+		},
+		100
+	);
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Polyline test</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_resize.html b/dojox/gfx/tests/svgweb/test_resize.html
new file mode 100644
index 0000000..f151368
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_resize.html
@@ -0,0 +1,57 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing surface resizing</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var surface;
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface("test", 500, 500);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	surface.createRect({width: 300, height: 300}).setFill([255, 0, 0, 0.3]).setStroke("red");
+	surface.createRect({x: 200, y: 200, width: 300, height: 300}).setFill([0, 0, 255, 0.3]).setStroke("green");
+	});
+	/* } */
+};
+
+getDim = function(){
+	var t = surface.getDimensions();
+	alert("dimensions: " + t.width + " by " + t.height);
+};
+
+make500x500 = function(){ surface.setDimensions(500, 500); };
+make400x400 = function(){ surface.setDimensions(400, 400); };
+make300x300 = function(){ surface.setDimensions(300, 300); };
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>Testing surface resizing</h1>
+<!--<p><button onclick="makeShapes();">Go</button></p>-->
+<p>
+	<button onclick="getDim();">getDimensions</button>
+	 
+	<button onclick="make300x300();">Make 300x300</button>
+	 
+	<button onclick="make400x400();">Make 400x400</button>
+	 
+	<button onclick="make500x500();">Make 500x500</button>
+</p>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_setPath.html b/dojox/gfx/tests/svgweb/test_setPath.html
new file mode 100644
index 0000000..9ba8bb5
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_setPath.html
@@ -0,0 +1,86 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing setPath and curves</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+	li {font-weight: bold;}
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 400);
+	// relative path with cubic beziers
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	surface
+		.createPath("m100 100 100 0 0 100c0 50-50 50-100 0s-50-100 0-100z")
+		.setStroke({color: "black"})
+		.setFill("red")
+		.setTransform({dx: -50, dy: -50})
+		;
+	// absolute path with cubic bezier
+	surface
+		.createPath("M100 100 200 100 200 200C200 250 150 250 100 200S50 100 100 100z")
+		.setStroke({color: "black"})
+		.setFill("#f80")
+		.setTransform({dx: 100, dy: -50})
+		;
+	// relative path with horizontal and vertical lines, and cubic beziers
+	surface
+		.createPath("m100 100h100v100c0 50-50 50-100 0s-50-100 0-100z")
+		.setStroke({color: "black"})
+		.setFill("yellow")
+		.setTransform({dx: 250, dy: -50})
+		;
+	// relative path with quadratic beziers
+	surface
+		.createPath("m100 100 100 0 0 100q0 50-75-25t-25-75z")
+		.setStroke({color: "black"})
+		.setFill("green")
+		.setTransform({dx: -50, dy: 150})
+		;
+	// absolute path with quadratic bezier
+	surface
+		.createPath("M100 100 200 100 200 200Q200 250 125 175T100 100z")
+		.setStroke({color: "black"})
+		.setFill("blue")
+		.setTransform({dx: 100, dy: 150})
+		;
+	// relative path with horizontal and vertical lines, and quadratic beziers
+	surface
+		.createPath("m100 100h100v100q0 50-75-25t-25-75z")
+		.setStroke({color: "black"})
+		.setFill("#f0f")
+		.setTransform({dx: 250, dy: 150})
+		;
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx setPath and curve test</h1>
+<div id="test" style="width: 500px; height: 400px;"></div>
+<p>Legend:</p>
+<ul>
+	<li style="background: red"><span style="color: white">relative path with cubic beziers</span></li>
+	<li style="background: #f80"><span style="color: black">absolute path with cubic bezier</span></li>
+	<li style="background: yellow"><span style="color: black">relative path with horizontal and vertical lines, and cubic beziers</span></li>
+	<li style="background: green"><span style="color: white">relative path with quadratic beziers</span></li>
+	<li style="background: blue"><span style="color: white">absolute path with quadratic bezier</span></li>
+	<li style="background: #f0f"><span style="color: black">relative path with horizontal and vertical lines, and quadratic beziers</span></li>
+</ul>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_tbbox.html b/dojox/gfx/tests/svgweb/test_tbbox.html
new file mode 100644
index 0000000..8c6e010
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_tbbox.html
@@ -0,0 +1,113 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface(document.getElementById("test"), 500, 500);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	var g1 = surface.createGroup();
+	// make a checkerboard
+	for(var i = 0; i < 500; i += 100){
+		for(var j = 0; j < 500; j += 100){
+			if(i % 200 == j % 200) {
+				surface.createRect({ x: i, y: j }).setFill([255, 0, 0, 0.1]);
+			}
+		}
+	}
+	var r1 = g1.createRect({ x: 200, y: 200 })
+				.setFill("green")
+				.setStroke({})
+				//.setTransform(dojox.gfx.matrix.rotategAt(45, 250, 250))
+				;
+	var r2 = surface.createRect().setStroke({})
+				.setFill({ type: "linear", to: { x: 50, y: 100 },
+					colors: [{ offset: 0, color: "green" }, { offset: 0.5, color: "red" }, { offset: 1, color: "blue" }] })
+				.setTransform({dx: 100, dy: 100})
+				;
+	var r3 = surface.createRect().setStroke({})
+				.setFill({ type: "linear" })
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 250, 250))
+				;
+	var r4 = g1.createRect({})
+				.setFill("blue")
+				//.setStroke({})
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 350, 250))
+				.setTransform([dojox.gfx.matrix.rotategAt(-30, 350, 250), { dx: 300, dy: 200 }])
+				;
+	var p1 = g1.createPath()
+				.setStroke({})
+				.moveTo( 300, 100 )
+				.lineTo( 400, 200 )
+				.lineTo( 400, 300 )
+				.lineTo( 300, 400 )
+				.curveTo( 400, 300, 400, 200, 300, 100 )
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 250, 250))
+				.setTransform({})
+				;
+	var p2 = g1.createPath(p1.getShape())
+				.setStroke({ color: "red", width: 2 })
+				//.moveTo( 300, 100 )
+				//.lineTo( 400, 200 )
+				//.lineTo( 400, 300 )
+				//.lineTo( 300, 400 )
+				//.curveTo( 400, 300, 400, 200, 300, 100 )
+				//.setTransform(dojox.gfx.matrix.rotategAt(180, 250, 250))
+				.setTransform({ dx: 100 })
+				;
+	var p3 = g1.createPath()
+				.setStroke({ color: "blue", width: 2 })
+				.moveTo( 300, 100 )
+				.setAbsoluteMode(false)
+				.lineTo (  100,  100 )
+				.lineTo (    0,  100 )
+				.lineTo ( -100,  100 )
+				.curveTo(  100, -100, 100, -200, 0, -300 )
+				//.setTransform(dojox.gfx.matrix.rotategAt(135, 250, 250))
+				.setTransform(dojox.gfx.matrix.rotategAt(180, 250, 250))
+				;
+	//g1.setTransform({ dx: 100 });
+	g1.moveToFront();
+	g1.setTransform(dojox.gfx.matrix.rotategAt(-15, 250, 250));
+	//g1.setTransform([dojox.gfx.matrix.rotategAt(-45, 250, 250), dojox.gfx.matrix.scaleAt(0.5, 250, 250)]);
+	//g1.setTransform([dojox.gfx.matrix.scaleAt(2, 1, 250, 250), dojox.gfx.matrix.rotategAt(-45, 250, 250)]);
+	var a = p1.getTransformedBoundingBox();
+	a.push(a[0]);
+	surface.createPolyline(a).setStroke("green");
+	a = p2.getTransformedBoundingBox();
+	a.push(a[0]);
+	surface.createPolyline(a).setStroke("green");
+	a = p3.getTransformedBoundingBox();
+	a.push(a[0]);
+	surface.createPolyline(a).setStroke("green");
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+<!--
+<style>
+v:group { text-align: left; }
+</style>
+-->
+</head>
+<body>
+	<h1>dojox.gfx Transformation test</h1>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_text.html b/dojox/gfx/tests/svgweb/test_text.html
new file mode 100644
index 0000000..13e1c09
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_text.html
@@ -0,0 +1,80 @@
+<html>
+<head>
+<title>Testing text</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var ROTATION = 30;
+
+var surface = null, t1, t2, t3, t4, t5;
+
+var placeAnchor = function(surface, x, y){
+	surface.createLine({x1: x - 2, y1: y, x2: x + 2, y2: y}).setStroke("blue");
+	surface.createLine({x1: x, y1: y - 2, x2: x, y2: y + 2}).setStroke("blue");
+};
+
+var makeText = function(surface, text, font, fill, stroke){
+	var t = surface.createText(text);
+	if(font)   t.setFont(font);
+	if(fill)   t.setFill(fill);
+	if(stroke) t.setStroke(stroke);
+	placeAnchor(surface, text.x, text.y);
+	return t;
+};
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface("test", 500, 500);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	var m = dojox.gfx.matrix;
+	surface.createLine({x1: 250, y1: 0, x2: 250, y2: 500}).setStroke("green");
+	t1 = makeText(surface, {x: 250, y: 50, text: "Start", align: "start"}, 
+		{family: "Times", size: "36pt", weight: "bold"}, "black", "red")
+		.setTransform(m.rotategAt(ROTATION, 250, 50));
+	t2 = makeText(surface, {x: 250, y: 100, text: "Middle", align: "middle"}, 
+		{family: "Symbol", size: "24pt"}, "red", "black")
+		.setTransform(m.rotategAt(ROTATION, 250, 100));
+	t3 = makeText(surface, {x: 250, y: 150, text: "End", align: "end"}, 
+		{family: "Helvetica", style: "italic", size: "18pt", rotated: true}, "#FF8000")
+		.setTransform(m.rotategAt(ROTATION, 250, 150));
+	t4 = makeText(surface, {x: 250, y: 200, text: "Define Shuffle Tiff", align: "middle", kerning: true}, 
+		{family: "serif", size: "36pt"}, "black")
+		.setTransform(m.rotategAt(0, 250, 200));
+	t5 = makeText(surface, {x: 250, y: 250, text: "Define Shuffle Tiff", align: "middle", kerning: false}, 
+		{family: "serif", size: "36pt"}, "black")
+		.setTransform(m.rotategAt(0, 250, 250));
+	});
+	/* } */
+};
+
+getSizes = function(){
+	var t = [];
+	dojo.forEach(["t1", "t2", "t3", "t4", "t5"], function(name){
+		var node = eval("(" + name + ")");
+		t.push(node.getShape().text + " = " + node.getTextWidth());
+	});
+	dojo.byId("sizes").innerHTML = t.join("<br/>");
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+	<h1>dojox.gfx Text test</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<div><button onclick="surface.clear();">Clear</button> <button onclick="getSizes();">Get sizes</button></div>
+<p id="sizes"> </p>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_textpath.html b/dojox/gfx/tests/svgweb/test_textpath.html
new file mode 100644
index 0000000..1520959
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_textpath.html
@@ -0,0 +1,77 @@
+<html>
+<head>
+<title>Testing textpath</title>
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var CPD = 30;
+
+var surface = null;
+
+var makeText = function(surface, text, font, fill, stroke){
+	var t = surface.createText(text);
+	if(font)   t.setFont(font);
+	if(fill)   t.setFill(fill);
+	if(stroke) t.setStroke(stroke);
+	placeAnchor(surface, text.x, text.y);
+	return t;
+};
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface("test", 500, 500);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	var p = surface.createPath({})
+		.setStroke("green")
+		.moveTo(0, 100)
+		.setAbsoluteMode(false)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		.curveTo(CPD, 0, 100 - CPD, -300, 100, -300)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		.curveTo(CPD, 0, 100 - CPD, -300, 100, -300)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		;
+	console.debug(p);
+	var t = surface.createTextPath({
+			text: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. " + 
+					"In malesuada ultricies velit. Vestibulum tempor odio vitae diam. " + 
+					"Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam."
+			, align: "middle"
+			//, rotated: true
+		})
+		//.setShape(p.shape)
+		.moveTo(0, 100)
+		.setAbsoluteMode(false)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		.curveTo(CPD, 0, 100 - CPD, -300, 100, -300)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		.curveTo(CPD, 0, 100 - CPD, -300, 100, -300)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		.setFont({family: "times", size: "12pt"})
+		.setFill("blue")
+		;
+	console.debug(t);
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+	<h1>dojox.gfx Text on a Path test</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_transform.html b/dojox/gfx/tests/svgweb/test_transform.html
new file mode 100644
index 0000000..164c2d1
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_transform.html
@@ -0,0 +1,99 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../../dojo/resources/dojo.css";
+	@import "../../../../dijit/tests/css/dijitTests.css";
+</style>
+<!-- SVGWEB { -->
+<meta name="svg.render.forceflash" content="true"/>
+<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+<!-- } -->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface(document.getElementById("test"), 500, 500);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+	var g1 = surface.createGroup();
+	// make a checkerboard
+	for(var i = 0; i < 500; i += 100){
+		for(var j = 0; j < 500; j += 100){
+			if(i % 200 == j % 200) {
+				surface.createRect({x: i, y: j}).setFill([255, 0, 0, 0.1]);
+			}
+		}
+	}
+	var r1 = g1.createShape({type: "rect", x: 200, y: 200})
+				.setFill("green")
+				.setStroke({})
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 250, 250))
+				;
+	var r2 = surface.createShape({type: "rect"}).setStroke({})
+				.setFill({type: "linear", to: {x: 50, y: 100},
+					colors: [{offset: 0, color: "green"}, {offset: 0.5, color: "red"}, {offset: 1, color: "blue"}] })
+				.setTransform({dx: 100, dy: 100})
+				;
+	var r3 = surface.createRect().setStroke({})
+				.setFill({ type: "linear" })
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 250, 250))
+				;
+	var r4 = g1.createShape({type: "rect"})
+				.setFill("blue")
+				//.setStroke({})
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 350, 250))
+				.setTransform([dojox.gfx.matrix.rotategAt(-30, 350, 250), { dx: 300, dy: 200 }])
+				;
+	var p1 = g1.createShape({type: "path"})
+				.setStroke({})
+				.moveTo(300, 100)
+				.lineTo(400, 200)
+				.lineTo(400, 300)
+				.lineTo(300, 400)
+				.curveTo(400, 300, 400, 200, 300, 100)
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 250, 250))
+				.setTransform({})
+				;
+	var p2 = g1.createShape(p1.getShape())
+				.setStroke({color: "red", width: 2})
+				//.moveTo( 300, 100 )
+				//.lineTo( 400, 200 )
+				//.lineTo( 400, 300 )
+				//.lineTo( 300, 400 )
+				//.curveTo( 400, 300, 400, 200, 300, 100 )
+				//.setTransform(dojox.gfx.matrix.rotategAt(180, 250, 250))
+				.setTransform({dx: 100})
+				;
+	var p3 = g1.createShape({type: "path"})
+				.setStroke({color: "blue", width: 2})
+				.moveTo(300, 100)
+				.setAbsoluteMode(false)
+				.lineTo ( 100,  100)
+				.lineTo (   0,  100)
+				.lineTo (-100,  100)
+				.curveTo( 100, -100, 100, -200, 0, -300)
+				//.setTransform(dojox.gfx.matrix.rotategAt(135, 250, 250))
+				.setTransform(dojox.gfx.matrix.rotategAt(180, 250, 250))
+				;
+	//g1.setTransform({dx: 100});
+	g1.moveToFront();
+	g1.setTransform(dojox.gfx.matrix.rotategAt(-15, 250, 250));
+	//g1.setTransform([dojox.gfx.matrix.rotategAt(-45, 250, 250), dojox.gfx.matrix.scaleAt(0.5, 250, 250)]);
+	//g1.setTransform([dojox.gfx.matrix.scaleAt(2, 1, 250, 250), dojox.gfx.matrix.rotategAt(-45, 250, 250)]);
+	});
+	/* } */
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Transform test</h1>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_utils.html b/dojox/gfx/tests/svgweb/test_utils.html
new file mode 100644
index 0000000..a989e04
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_utils.html
@@ -0,0 +1,234 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>GFX Test: Test the basic utils functions</title>
+		<style type="text/css">
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../../../dijit/tests/css/dijitTests.css";
+		</style>
+		<!-- SVGWEB { -->
+		<meta name="svg.render.forceflash" content="true"/>
+		<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+		<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+		<!-- } -->
+		<script type="text/javascript" src="../../../util/doh/runner.js"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.require("dojox.gfx");
+			dojo.require("dojox.gfx.utils");
+		</script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				var drawing;
+				var ta;
+				doh.register("GFX: Utils Tests", [
+					{
+						name: "toJson",
+						timeout: 1000,
+						setUp: function(){
+							if(!drawing){
+								var dn = dojo.byId("gfxObject");
+								drawing = dojox.gfx.createSurface(dn, 300, 300);
+	/* SVGWEB { */
+	drawing.whenLoaded(function() {
+								drawing.createRect({ 
+									 width:  100,
+									 height: 100,
+									 x: 100,
+									 y: 100
+								}).setFill("blue").setStroke("black");
+	});
+	/* } */
+							}
+							if(!ta){
+								ta = dojo.byId("outputArea");
+							}
+						},
+						runTest: function(){
+	/* SVGWEB { */
+	drawing.whenLoaded(function() {
+							var d = new doh.Deferred();
+							try{
+								var json = dojox.gfx.utils.toJson(drawing);
+								doh.assertTrue(json != null, "Checking that non-null was returned.");
+								ta.value = json;
+								var obj = dojo.fromJson(json);
+								doh.assertTrue(1, obj.length, "Checking that the json is an array of one entry.");
+								doh.assertTrue(obj[0].shape != null, "Checking that a toplevel shape object is present.");
+								doh.assertEqual("rect", obj[0].shape.type, "Checking that the shape type is rect.");
+								doh.assertEqual(100, obj[0].shape.width, "Checking that the width is 100.");
+								doh.assertEqual(100, obj[0].shape.height, "Checking that the height is 100.");
+								d.callback(true);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+	});
+	/* } */
+						}
+					},
+					{
+						name: "fromJson",
+						timeout: 1000,
+						setUp: function(){
+							if(!drawing){
+								var dn = dojo.byId("gfxObject");
+								drawing = dojox.gfx.createSurface(dn, 300, 300);
+	/* SVGWEB { */
+	drawing.whenLoaded(function() {
+								drawing.createRect({ 
+									 width:  100,
+									 height: 100,
+									 x: 100,
+									 y: 100
+								}).setFill("blue").setStroke("black");
+	});
+	/* } */
+							}
+							if(!ta){
+								ta = dojo.byId("outputArea");
+							}
+						},
+						runTest: function(){
+	/* SVGWEB { */
+	drawing.whenLoaded(function() {
+							var d = new doh.Deferred();
+							try{
+								var json = dojox.gfx.utils.toJson(drawing);
+								doh.assertTrue(json != null, "Checking that non-null was returned.");
+								var targetNode = dojo.byId("scratchObject");
+								var tempSurface = dojox.gfx.createSurface(targetNode, 300, 300);
+								dojox.gfx.utils.fromJson(tempSurface, json);
+
+								var nsJson = dojox.gfx.utils.toJson(tempSurface);
+								tempSurface.destroy();
+
+								var obj = dojo.fromJson(nsJson);
+								doh.assertTrue(1, obj.length, "Checking that the json is an array of one entry.");
+								doh.assertTrue(obj[0].shape != null, "Checking that a toplevel shape object is present.");
+								doh.assertEqual("rect", obj[0].shape.type, "Checking that the shape type is rect.");
+								doh.assertEqual(100, obj[0].shape.width, "Checking that the width is 100.");
+								doh.assertEqual(100, obj[0].shape.height, "Checking that the height is 100.");
+								d.callback(true);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+	});
+	/* } */
+						}
+					},
+					{
+						name: "toSvg",
+						timeout: 10000,
+						setUp: function(){
+							if(!drawing){
+								var dn = dojo.byId("gfxObject");
+								drawing = dojox.gfx.createSurface(dn, 300, 300);
+	/* SVGWEB { */
+	drawing.whenLoaded(function() {
+								drawing.createRect({ 
+									 width:  100,
+									 height: 100,
+									 x: 100,
+									 y: 100
+								}).setFill("blue").setStroke("black");
+	});
+	/* } */
+							}
+							if(!ta){
+								ta = dojo.byId("outputArea");
+							}
+						},
+						runTest: function(){
+	/* SVGWEB { */
+	drawing.whenLoaded(function() {
+							var d = new doh.Deferred();
+							var def= dojox.gfx.utils.toSvg(drawing);
+							def.addCallback(function(svg){
+								try{
+									doh.assertTrue(svg != null, "Checking that non-null was returned.");
+									ta.value = svg;
+									doh.assertTrue(svg.length > 0, "Checking that svg length > 0");
+									doh.assertTrue(svg.toLowerCase().indexOf("<svg") === 0, "Checking that the string starts with SVG open tag.");
+									d.callback(true);
+								}catch(e){
+									d.errback(e);
+								}
+							});
+							def.addErrback(function(e){
+								d.errback(e);
+							});
+							return d;
+	});
+	/* } */
+						}
+					},
+					{
+						name: "serialize/deserialize",
+						timeout: 1000,
+						setUp: function(){
+							if(!drawing){
+								var dn = dojo.byId("gfxObject");
+								drawing = dojox.gfx.createSurface(dn, 300, 300);
+	/* SVGWEB { */
+	drawing.whenLoaded(function() {
+								drawing.createRect({ 
+									 width:  100,
+									 height: 100,
+									 x: 100,
+									 y: 100
+								}).setFill("blue").setStroke("black");
+	});
+	/* } */
+							}
+							if(!ta){
+								ta = dojo.byId("outputArea");
+							}
+						},
+						runTest: function(){
+	/* SVGWEB { */
+	drawing.whenLoaded(function() {
+							var d = new doh.Deferred();
+							try{
+								var sObj = dojox.gfx.utils.serialize(drawing);
+								doh.assertTrue(sObj != null, "Checking that non-null was returned.");
+
+								//Lets try to deserialize it!
+								var targetNode = dojo.byId("scratchObject");
+								var tempSurface = dojox.gfx.createSurface(targetNode, 300, 300);
+								dojox.gfx.utils.deserialize(tempSurface, sObj);
+								var nsJson = dojox.gfx.utils.toJson(tempSurface);
+								tempSurface.destroy();
+
+								var obj = dojo.fromJson(nsJson);
+								doh.assertTrue(1, obj.length, "Checking that the json is an array of one entry.");
+								doh.assertTrue(obj[0].shape != null, "Checking that a toplevel shape object is present.");
+								doh.assertEqual("rect", obj[0].shape.type, "Checking that the shape type is rect.");
+								doh.assertEqual(100, obj[0].shape.width, "Checking that the width is 100.");
+								doh.assertEqual(100, obj[0].shape.height, "Checking that the height is 100.");
+								d.callback(true);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+	});
+	/* } */
+						}
+					}
+				]);
+				doh.run();
+			});
+			</script>
+	</head>
+	<body class="tundra">
+		<h1>Test of GFX Utils functions</h1>
+		This page is intended for testing of the functions of the utils package, such as toJson, fromJson, and toSvg.
+		<div id="gfxObject"></div>
+		<div id="scratchObject"></div>
+		<div>
+			<textarea style="width: 100%; height: 300px" id="outputArea"></textarea>
+		</div>
+	</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_vectortext_draw.html b/dojox/gfx/tests/svgweb/test_vectortext_draw.html
new file mode 100644
index 0000000..0a63d44
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_vectortext_draw.html
@@ -0,0 +1,64 @@
+<html>
+	<head>
+		<title>DojoX GFX: Vector Text test: draw a font</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../../../dijit/tests/css/dijitTests.css";
+		</style>
+		<!-- SVGWEB { -->
+		<meta name="svg.render.forceflash" content="true"/>
+		<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+		<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+		<!-- } -->
+		<script type="text/javascript">
+			dojo.require("dojox.gfx");
+			dojo.require("dojox.gfx.fx");
+			dojo.require("dojox.gfx.VectorText");
+
+			var bg="#181818", fill="#a36e2c";
+			dojo.addOnLoad(function(){
+				var url = dojo.moduleUrl("dojox", "gfx/resources/Gillius.svg");
+				var f = new dojox.gfx.VectorFont(url);
+
+				//	draw out the glyphs for testing.
+				var surface = dojox.gfx.createSurface("test", 600, 400);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+				var rect = surface.createRect({ x: 0, y: 0, width: 600, height: 400 })
+					.setFill(bg);
+
+				//	draw it up.
+				var txtArgs = {
+					text: "Now is the time for all good men to come to a rest.  Plus, the rain in Spain falls mainly on the plain!",
+					x: 0, y: 0,
+					width: 560, height: 360,
+					align: "start", fitting: dojox.gfx.vectorFontFitting.FIT,
+					leading: 1.2
+				};
+				var fontArgs = {
+					size: "12pt", family: "Gillius"
+				};
+
+				var master = surface.createGroup();	
+				var g = f.draw(master, txtArgs, fontArgs, fill);
+
+				dojox.gfx.fx.animateTransform({
+					shape: master,
+					duration: 1000,
+					transform: [ 
+						{name: "rotategAt", start: [0, 250, 250], end: [360, 350, 350]},
+						{ name: "scale", start: [0.1, 0.1], end:[1, 1 ] } 
+					]
+				}).play();
+	});
+	/* } */
+			});
+		</script>
+	</head>
+	<body>
+		<h1>dojox.gfx Vector Text test: drawing a font</h1>
+		<p>This is a test of the new VectorText functionality; we draw a font using flow or fit.</p>
+		<div id="test" style="width: 500px; height: 560px;"></div>
+	</body>
+</html>
diff --git a/dojox/gfx/tests/svgweb/test_vectortext_load.html b/dojox/gfx/tests/svgweb/test_vectortext_load.html
new file mode 100644
index 0000000..4e12d75
--- /dev/null
+++ b/dojox/gfx/tests/svgweb/test_vectortext_load.html
@@ -0,0 +1,97 @@
+<html>
+	<head>
+		<title>DojoX GFX: Vector Text test: load and display a font</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../../../dijit/tests/css/dijitTests.css";
+		</style>
+		<!-- SVGWEB { -->
+		<meta name="svg.render.forceflash" content="true"/>
+		<script src="svgweb/src/svg.js" data-path="svgweb/src"></script>
+		<script src="../../../../dojo/dojo.js" djConfig="isDebug:true,forceGfxRenderer:'svg'" type="text/javascript"></script>
+		<!-- } -->
+		<script type="text/javascript">
+			dojo.require("dojox.gfx");
+			dojo.require("dojox.gfx.VectorText");
+
+			var bg="#181818", fill="#464b44", padding=32;
+			dojo.addOnLoad(function(){
+				var url = dojo.moduleUrl("dojox", "gfx/resources/Gillius.svg");
+				var f = new dojox.gfx.VectorFont(url);
+
+	// don't do too much, svgweb is slow~~~
+	for (var i in f.glyphs) {
+		if (i < 'a' || i > 'z') {
+			delete f.glyphs[i];
+		}
+	}
+
+				//	draw out the glyphs for testing.
+				var surface = dojox.gfx.createSurface("test", 2500, 560);
+	/* SVGWEB { */
+	surface.whenLoaded(function() {
+		var start = new Date().getTime();
+		var suspendId = surface.rawNode.suspendRedraw(10000000);
+				var rect = surface.createRect({ x: 0, y: 0, width: 2500, height: 560 })
+					.setFill(bg);
+				var g = surface.createGroup(), cx=0, count=0;
+				for(var gl in f.glyphs){
+					var glyph = f.glyphs[gl];
+					var t = g.createGroup();
+					if(glyph.path){
+						var p = t.createPath(glyph.path).setFill(fill);
+					}
+					t.setTransform([
+						dojox.gfx.matrix.flipY,
+						dojox.gfx.matrix.translate(cx, -f.viewbox.height-f.descent)
+					]);
+					cx += glyph.xAdvance, count++;
+					g.createLine({ 
+						x1: cx, x2: cx, y1: 0, y2: f.viewbox.height 
+					}).setStroke({color:"#409953", style:"Dash", width:1 });
+				}
+				cx -= glyph.xAdvance;
+				var factor = (500/f.viewbox.height)/2;
+				g.setTransform(dojox.gfx.matrix.scale(factor));
+				surface.setDimensions(cx*factor, (f.viewbox.height*factor)+padding*2);
+				rect.setShape({ x:0, y:0, width:cx*factor, height: (f.viewbox.height*factor)+padding*2 });
+				dojo.byId("test").style.height = Math.round(f.viewbox.height*factor)+padding*2+"px";
+				
+				//	try to find the baseline
+				surface.createLine({ x1: 0, x2: cx*factor, 
+						y1: factor*(f.viewbox.height+f.descent), y2:factor*(f.viewbox.height+f.descent) 
+				}).setStroke({ color: "#a36e2c" });
+
+				//	lets do some measuring lines.
+				var s = "#70657e", axis = surface.createGroup();
+				//	measurement axis
+				axis.createLine({ x1: 0, x2: cx*factor, y1: factor*f.viewbox.height+padding*2-1, y2: factor*f.viewbox.height+padding*2-1 })
+					.setStroke(s);
+
+				var major=50, minor=10, yMajor=20, yMinor=10, tick=5, steps=Math.floor(cx/minor);
+				for(var i=0; i<steps; i++){
+					//	ticks
+					var xpos = i*minor, y2 = padding*2+factor*f.viewbox.height, y1 = (xpos%major==0)?y2-yMajor:y2-yMinor;
+					axis.createLine({ x1: xpos, x2: xpos, y1: y1, y2: y2 }).setStroke(s);
+					if(xpos%major==0){
+						axis.createText({ x: xpos, y: y1-4, text: xpos.toString(), align: "middle" })
+							.setFont({ family: "sans-serif", size:"8pt"})
+							.setFill(s);
+					}
+				}
+
+		surface.rawNode.unsuspendRedraw(suspendId);
+		alert(new Date().getTime() - start);
+	});
+	/* } */
+
+			});
+		</script>
+	</head>
+	<body>
+		<h1>dojox.gfx Vector Text test: loading a font</h1>
+		<p>This is a test of the new VectorText functionality; we load up an SVG Font definition and use it to render text (as opposed to tapping into a browser's native text capability).</p>
+		<div id="test" style="width: 500px; height: 560px;"></div>
+	</body>
+</html>
diff --git a/dojox/gfx/tests/test.roundrect.html b/dojox/gfx/tests/test.roundrect.html
new file mode 100644
index 0000000..3f0ff1c
--- /dev/null
+++ b/dojox/gfx/tests/test.roundrect.html
@@ -0,0 +1,34 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing rounded rectangle</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.move");
+dojo.require("dojo.colors");
+
+makeShapes = function(){
+    var g = dojox.gfx;
+	var surface = g.createSurface("test", 800, 600)
+    var rect1 = surface.createRect({x: 100, y: 100, width: 300, height: 200, r: 50}).setFill("red").setStroke("black");
+	new g.Moveable(rect1);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Rounded rectangle</h1>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_arc.html b/dojox/gfx/tests/test_arc.html
new file mode 100644
index 0000000..3a96bf5
--- /dev/null
+++ b/dojox/gfx/tests/test_arc.html
@@ -0,0 +1,70 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing arc</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../_base.js"></script>
+<script type="text/javascript" src="../shape.js"></script>
+<script type="text/javascript" src="../path.js"></script>
+<script type="text/javascript" src="../arc.js"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../canvas.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+createSurface = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	surface.whenLoaded(makeShapes);
+};
+
+makeShapes = function(surface){
+	var m = dojox.gfx.matrix;
+    var g1 = surface.createGroup();
+    var g2 = g1.createGroup();
+
+	var rx = 100, ry = 60, xRotg = -30;
+    var startPoint = m.multiplyPoint(m.rotateg(xRotg), {x: -rx, y: 0  });
+    var endPoint   = m.multiplyPoint(m.rotateg(xRotg), {x: 0,   y: -ry});
+    
+    var re1 = g1.createPath()
+		.moveTo(startPoint)
+		.arcTo(rx, ry, xRotg, true, false, endPoint)
+		.setStroke({color: "red", width: 3})
+		;
+    var ge1 = g1.createPath()
+		.moveTo(re1.getLastPosition())
+		.arcTo(rx, ry, xRotg, false, false, startPoint)
+		.setStroke({color: "black"})
+		;
+    var re2 = g2.createPath()
+		.moveTo(startPoint)
+		.arcTo(rx, ry, xRotg, false, true, endPoint)
+		.setStroke({color: "green", width: 3})
+		;
+    var ge2 = g2.createPath()
+		.moveTo(re2.getLastPosition())
+		.arcTo(rx, ry, xRotg, true, true, startPoint)
+		.setStroke({color: "black"})
+		;
+		
+	g1.setTransform({dx: 200, dy: 200});
+	g2.setTransform({dx: 10,  dy: 10});
+};
+
+dojo.addOnLoad(createSurface);
+
+</script>
+</head>
+<body>
+<h1>Testing arc</h1>
+<!--<p><button onclick="createSurface();">Go</button></p>-->
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_bezier.html b/dojox/gfx/tests/test_bezier.html
new file mode 100644
index 0000000..0387ddb
--- /dev/null
+++ b/dojox/gfx/tests/test_bezier.html
@@ -0,0 +1,81 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Approximation of an arc with bezier</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../_base.js"></script>
+<script type="text/javascript" src="../shape.js"></script>
+<script type="text/javascript" src="../path.js"></script>
+<script type="text/javascript" src="../arc.js"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../canvas.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 300);
+	var g = surface.createGroup();
+	
+	// create a reference ellipse
+	var rx = 200;
+	var ry = 100;
+	var startAngle = -30;
+	var arcAngle = -90;
+	var axisAngle = -30;
+	var e = g.createEllipse({rx: rx, ry: ry}).setStroke({});
+	
+	// calculate a bezier
+	var alpha = dojox.gfx.matrix._degToRad(arcAngle) / 2; // half of our angle
+	var cosa  = Math.cos(alpha);
+	var sina  = Math.sin(alpha);
+	// start point
+	var p1 = {x: cosa, y: sina};
+	// 1st control point
+	var p2 = {x: cosa + (4 / 3) * (1 - cosa), y: sina - (4 / 3) * cosa * (1 - cosa) / sina};
+	// 2nd control point (symmetric to the 1st one)
+	var p3 = {x: p2.x, y: -p2.y};
+	// end point (symmetric to the start point)
+	var p4 = {x: p1.x, y: -p1.y};
+	
+	// rotate and scale poins as appropriate
+	var s = dojox.gfx.matrix.normalize([dojox.gfx.matrix.scale(e.shape.rx, e.shape.ry), dojox.gfx.matrix.rotateg(startAngle + arcAngle / 2)]);
+	p1 = dojox.gfx.matrix.multiplyPoint(s, p1);
+	p2 = dojox.gfx.matrix.multiplyPoint(s, p2);
+	p3 = dojox.gfx.matrix.multiplyPoint(s, p3);
+	p4 = dojox.gfx.matrix.multiplyPoint(s, p4);
+	// draw control trapezoid
+	var t = g.createPath().setStroke({color: "blue"});
+	t.moveTo(p1.x, p1.y);
+	t.lineTo(p2.x, p2.y);
+	t.lineTo(p3.x, p3.y);
+	t.lineTo(p4.x, p4.y);
+	t.lineTo(p1.x, p1.y);
+	t.moveTo((p1.x + p4.x) / 2, (p1.y + p4.y) / 2);
+	t.lineTo((p2.x + p3.x) / 2, (p2.y + p3.y) / 2);
+	t.moveTo((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
+	t.lineTo((p3.x + p4.x) / 2, (p3.y + p4.y) / 2);
+	// draw a bezier
+	var b = g.createPath().setStroke({color: "red"});
+	b.moveTo(p1.x, p1.y);
+	b.curveTo(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
+	// move everything in a middle
+	g.setTransform([dojox.gfx.matrix.translate(250, 150), dojox.gfx.matrix.rotateg(axisAngle)]);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>Approximation of an arc with bezier</h1>
+<!--<p><button onclick="makeShapes();">Make</button></p>-->
+<div id="test" style="width: 500px; height: 300px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_decompose.html b/dojox/gfx/tests/test_decompose.html
new file mode 100644
index 0000000..6291cc2
--- /dev/null
+++ b/dojox/gfx/tests/test_decompose.html
@@ -0,0 +1,54 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing decompose</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../matrix.js"></script>
+<script type="text/javascript" src="../decompose.js"></script>
+<script type="text/javascript">
+dojo.require("dojox.gfx.decompose");
+
+var m = dojox.gfx.matrix;
+
+var eq = function(a, b){
+	return Math.abs((a - b) / (a + b)) < 1e-6;
+};
+
+var calc = function(){
+	var matrix1 = eval("(m.normalize([" + dojo.byId("input").value + "]))");
+	dojo.byId("matrix1").value = dojo.toJson(matrix1, true);
+	var result = dojox.gfx.decompose(matrix1);
+	dojo.byId("result").innerHTML = "Result: " + dojo.toJson(result);
+	var matrix2 = m.normalize([
+		m.translate(result.dx, result.dy),
+		m.rotate(result.angle2),
+		m.scale(result.sx, result.sy),
+		m.rotate(result.angle1)
+	]);
+	dojo.byId("matrix2").value = dojo.toJson(matrix2, true);
+};
+
+</script>
+</head>
+<body>
+	<h1>Testing decompose</h1>
+	<p>
+		<span style="font-size: 8pt;">Example: m.rotategAt(30, 100, 100), m.scaleAt(2, 3, 5, 5), m.rotate(45)</span><br />
+		<input id="input" type="text" size="50" maxlength="200" /><button onclick="calc();">Calc</button>
+	</p>
+	<p id="result">Result:</p>
+	<p>
+		<span style="font-size: 8pt;">Original matrix</span><br />
+		<textarea id="matrix1" cols="50" rows="8" readonly="readonly"></textarea>
+	</p>
+	<p>
+		<span style="font-size: 8pt;">Decomposed matrix</span><br />
+		<textarea id="matrix2" cols="50" rows="8" readonly="readonly"></textarea>
+	</p>
+	<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_destroy.html b/dojox/gfx/tests/test_destroy.html
new file mode 100644
index 0000000..4122dc2
--- /dev/null
+++ b/dojox/gfx/tests/test_destroy.html
@@ -0,0 +1,56 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing surface.destroy()</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../_base.js"></script>-->
+<!--<script type="text/javascript" src="../shape.js"></script>-->
+<!--<script type="text/javascript" src="../path.js"></script>-->
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+surface = null;
+
+makeShapes = function(){
+	if(surface){
+		surface.destroy();
+		surface = null;
+		var t = dojo.byId("test").innerHTML;
+		if(t){
+			console.error("Garbage detected: " + t);
+		}else{
+			console.log("The parent node was cleaned up properly.");
+		}
+	}
+	surface = dojox.gfx.createSurface("test", 500, 500);
+	var path = surface.createPath("");
+	// form concentric circles
+	var center = {x: 250, y: 250};
+	for(var r = 200; r > 0; r -= 30){
+		// make two 180 degree arcs to form a circle
+		var start = {x: center.x, y: center.y - r};
+		var end   = {x: center.x, y: center.y + r};
+		path.moveTo(start).arcTo(r, r, 0, true, true, end).arcTo(r, r, 0, true, true, start).closePath();
+	}
+	// set visual attributes
+	path.setFill("red").setStroke("black");
+};
+
+dojo.addOnLoad(makeShapes);
+</script>
+</head>
+<body>
+	<h1>Testing surface.destroy()</h1>
+	<p><button onclick="makeShapes();">Regenerate</button></p>
+	<p><em>See the firebug log for detailed reports.</em></p>
+	<div id="test" style="width: 500px; height: 500px;"></div>
+	<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_fill.html b/dojox/gfx/tests/test_fill.html
new file mode 100644
index 0000000..54962d4
--- /dev/null
+++ b/dojox/gfx/tests/test_fill.html
@@ -0,0 +1,43 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing fill rule</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../_base.js"></script>-->
+<!--<script type="text/javascript" src="../shape.js"></script>-->
+<!--<script type="text/javascript" src="../path.js"></script>-->
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	var path = surface.createPath("");
+	// form concentric circles
+	var center = {x: 250, y: 250};
+	for(var r = 200; r > 0; r -= 30){
+		// make two 180 degree arcs to form a circle
+		var start = {x: center.x, y: center.y - r};
+		var end   = {x: center.x, y: center.y + r};
+		path.moveTo(start).arcTo(r, r, 0, true, true, end).arcTo(r, r, 0, true, true, start).closePath();
+	}
+	// set visual attributes
+	path.setFill("red").setStroke("black");
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+	<h1>Testing fill rule</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_fx.html b/dojox/gfx/tests/test_fx.html
new file mode 100644
index 0000000..800b0f5
--- /dev/null
+++ b/dojox/gfx/tests/test_fx.html
@@ -0,0 +1,108 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing animation</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--
+<script type="text/javascript" src="../_base.js"></script>
+<script type="text/javascript" src="../shape.js"></script>
+<script type="text/javascript" src="../path.js"></script>
+<script type="text/javascript" src="../arc.js"></script>
+<script type="text/javascript" src="../fx.js"></script>
+-->
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../canvas.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.fx");
+dojo.require("dojo.colors");
+
+var rect, text;
+
+var makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	rect = surface.createRect({x: 100, y: 100, width: 300, height: 300}).
+		setFill("yellow").setStroke({
+			color: "green",
+			width: 5,
+			join: "round"
+		});
+	text = surface.createText({x: 250, y: 250, text: "Hello!", align: "middle"})
+		.setFill("black").setFont({family: "serif", size: "10pt"});
+};
+
+dojo.addOnLoad(makeShapes);
+
+var animateStroke = function(){
+	var anim = dojox.gfx.fx.animateStroke({
+		duration:	5000,
+		shape: 		rect,
+		color:		{start: "green", end: "red"},
+		width:		{start: 5, end: 15},
+		join:		{values: ["bevel", "round"]}
+	});
+	dojo.byId("stroke").disabled = "disabled";
+	dojo.connect(anim, "onEnd", function(){ dojo.byId("stroke").disabled = ""; });
+	anim.play();
+};
+
+var animateFill = function(){
+	var anim = dojox.gfx.fx.animateFill({
+		duration:	5000,
+		shape: 		rect,
+		color:		{start: "yellow", end: "blue"}
+	});
+	dojo.byId("fill").disabled = "disabled";
+	dojo.connect(anim, "onEnd", function(){ dojo.byId("fill").disabled = ""; });
+	anim.play();
+};
+
+var animateFont = function(){
+	var anim = dojox.gfx.fx.animateFont({
+		duration:	5000,
+		shape: 		text,
+		variant:	{values: ["normal", "small-caps"]},
+		size:		{start: 10, end: 50, units: "pt"}
+	});
+	dojo.byId("font").disabled = "disabled";
+	dojo.connect(anim, "onEnd", function(){ dojo.byId("font").disabled = ""; });
+	anim.play();
+};
+
+var animateTransform = function(){
+	var anim = dojox.gfx.fx.animateTransform({
+		duration:	5000,
+		shape: 		text,
+		transform:	[
+			{name: "rotategAt", start: [0, 250, 250], end: [360, 350, 350]},
+			{name: "translate", start: [0, 0], end: [100, 100]}
+		]
+	});
+	dojo.byId("transform").disabled = "disabled";
+	dojo.connect(anim, "onEnd", function(){ dojo.byId("transform").disabled = ""; });
+	anim.play();
+};
+</script>
+</head>
+<body>
+<h1>Testing animation</h1>
+<p>
+	<button id="stroke" onclick="animateStroke();">Stroke</button>
+	 
+	<button id="fill" onclick="animateFill();">Fill</button>
+	 
+	<button id="font" onclick="animateFont();">Font</button>
+	 
+	<button id="transform" onclick="animateTransform();">Transform</button>
+</p>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_fx_shapes.html b/dojox/gfx/tests/test_fx_shapes.html
new file mode 100644
index 0000000..07726ff
--- /dev/null
+++ b/dojox/gfx/tests/test_fx_shapes.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en">
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+        <title>Animate rectangles</title>
+        <!--<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dojo/dojo.xd.js"></script>-->
+        <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+        <script type="text/javascript" charset="utf-8">
+            dojo.require("dojox.gfx");
+            dojo.require("dojo.fx");
+            dojo.require("dojo.fx.easing");
+            dojo.require("dojox.fx.easing");
+            
+            var WIDTH = 600, HEIGHT = 400,
+                BAR_GAP = 20, BAR_WIDTH = 76,
+                BAR_FILL = "red", BAR_STROKE = "black",
+                CHAIN_DURATION = 250, COMBINE_DURATION = 1000;
+            
+            var surface, rects = [];
+            
+            var enable = function(enabled){
+                // enable/disable controls on the page
+                dojo.query("input, select, button, textarea").attr("disabled", !enabled);
+            };
+            
+            var empty = {};
+            var populateSelect = function(from, select){
+                var module = dojo.getObject(from);
+                for(var name in module){
+                    if(name in empty){ continue; }
+                    var fun = module[name];
+                    if(dojo.isFunction(fun)){
+                        dojo.create("option", {
+                            value:     from + "." + name,
+                            selected:  name == "backOut",
+                            innerHTML: from + "." + name
+                        }, select);
+                    }
+                }
+            };
+            
+            var animate = function(){
+                // disable controls
+                enable(false);
+                
+                // get old heights
+                var oldHeights = dojo.map(rects, function(rect){ return rect.getShape().height; });
+                
+                // generate new heights (can't be 0 on IE/VML!)
+                var newHeights = dojo.map(rects, function(){ return 1 + Math.random() * (HEIGHT - 1); });
+                
+                // get parameters
+                var duration = dojo.byId("chain").checked ? CHAIN_DURATION : COMBINE_DURATION,
+                    easing = dojo.getObject(dojo.byId("easing").value);
+                
+                // create animations between heights
+                var animations = dojo.map(rects, function(rect, i){
+                    // create animation
+                    var anim = new dojo._Animation({
+                        duration: duration,
+                        easing:   easing,
+                        curve:    [oldHeights[i], newHeights[i]]
+                    });
+                    // update the rectangle on every tick
+                    dojo.connect(anim, "onAnimate", function(height){
+                        var shape = rect.getShape();
+                        shape.y = HEIGHT - height;
+                        shape.height = height;
+                        rect.setShape(shape);
+                    });
+                    return anim;
+                });
+                // combine all animations
+                var masterAnimation = dojo.byId("chain").checked ?
+                        dojo.fx.chain(animations) : dojo.fx.combine(animations);
+                // enable controls when they are done
+                dojo.connect(masterAnimation, "onEnd", function(){ enable(true); });
+                // start the animation
+                masterAnimation.play();
+            }
+            
+            var init = function(){
+                // create surface
+                surface = dojox.gfx.createSurface(dojo.byId("surface"), 600, 400);
+                
+                // create rectangles
+                for(var w = BAR_GAP; w < WIDTH - BAR_WIDTH; w += BAR_WIDTH + BAR_GAP){
+                    rects.push(surface.createRect({
+                        x: w, y: HEIGHT, width: BAR_WIDTH, height: 1
+                    }).setFill(BAR_FILL).setStroke(BAR_STROKE));
+                }
+                // IE/VML doesn't allow height to be 0!
+                
+                // prepare and enable controls
+                populateSelect("dojo.fx.easing", "easing");
+                if(dojox.fx.easing !== dojo.fx.easing){
+                    populateSelect("dojox.fx.easing", "easing");
+                }
+                dojo.attr("chain", "checked", false);
+                dojo.connect(dojo.byId("animate"), "onclick", animate);
+                enable(true);
+            };
+            
+            dojo.addOnLoad(init);
+        </script>
+    </head>
+    <body>
+        <p>
+            <button id="animate" disabled="disabled">Animate!</button> 
+            <label>Easing: <select id="easing" disabled="disabled"></select></label> 
+            <label><input id="chain" type="checkbox" disabled="disabled"> Chain (otherwise Combine)</label>
+        </p>
+        <div id="surface" style="width: 600px; height: 400px; border:1px solid #000;"></div>
+    </body>
+</html>
diff --git a/dojox/gfx/tests/test_gfx.html b/dojox/gfx/tests/test_gfx.html
new file mode 100644
index 0000000..e13d78b
--- /dev/null
+++ b/dojox/gfx/tests/test_gfx.html
@@ -0,0 +1,483 @@
+<html>
+<head>
+	<title>Dojo Unified 2D Graphics</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+	<!-- test styles -->
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		td { border: 1px solid black; text-align: left; vertical-align: top; }
+		v:group { text-align: left; }
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+
+	<!-- for debuggin: -->
+	<!--<script type="text/javascript" src="../_base.js"></script>-->
+	<!--<script type="text/javascript" src="../path.js"></script>-->
+	<!--<script type="text/javascript" src="../vml.js"></script>-->
+	<!--<script type="text/javascript" src="../svg.js"></script>-->
+	<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+	<script type="text/javascript">
+
+		dojo.require("dojox.gfx");
+
+		var gTestContainer = null;
+		var gTests = {};
+
+		function isEqual(foo, bar, prefix){
+		    var flag = true;
+		    if(foo != bar ){
+		        console.debug(prefix+":"+foo + "!=" + bar + " try dig into it" );
+		        if( foo instanceof Array ) {
+		            for( var i = 0; i< foo.length; i++ ) {
+		                flag = isEqual(foo[i], bar[i], prefix+"["+i+"]") && flag;
+		            }
+		            flag = false;
+		        } else {
+		            for(var x in foo) {
+		                if(bar[x] != undefined ) {
+		                    flag = isEqual(foo[x], bar[x], prefix+"."+x) && flag;
+		                } else {
+		                    console.debug(prefix+":"+ x + " is undefined in bar" );
+		                    flag = false;
+		                }
+		            }
+		        }
+		    }
+		    return flag;
+		}
+
+
+		function getTestSurface(testName, testDescription, width, height){
+		   width = width ? width : 300;
+		   height = height ? height : 300;
+
+		   // Create a DOM node for the surface
+		   var testRow = document.createElement('tr');
+		   var testCell = document.createElement('td');
+		   var testHolder = document.createElement('div');
+		   testHolder.id = testName + '_holder';
+		   testHolder.style.width  = width;
+		   testHolder.style.height = height;
+
+		   testCell.appendChild(testHolder);
+		   testRow.appendChild(testCell);
+		   gTestContainer.appendChild(testRow);
+
+		   var descRow = document.createElement('tr');
+		   var desc = document.createElement('td');
+		   desc.innerHTML = testDescription;
+		   descRow.appendChild(desc);
+		   gTestContainer.appendChild(descRow);
+
+		   return dojox.gfx.createSurface(testHolder, width, height);
+		}
+
+		function addTest(testName, fn){
+		   gTests[testName] = fn;
+		}
+
+		function runTest_nodebug(testName){
+		   try {
+		      var t = gTests[testName];
+		      if (!t) {
+		         return 'no test named ' + t;
+		      }
+		      t(testName);
+		      return null; // the success condition
+		   } catch (e) {
+		      return e.message;
+		   }
+		}
+
+		function runTest_debug(testName){
+		      var t = gTests[testName];
+		      if (!t) {
+		         return 'no test named ' + t;
+		      }
+		      t(testName);
+		      return null; // the success condition
+		}
+
+		var runTest = dojo.config.isDebug ? runTest_debug : runTest_nodebug;
+
+		dojo.addOnLoad(function(){
+			gTestContainer = dojo.byId('testcontainer');
+			var rect = { x: 0, y: 0, width: 100, height: 100 };
+
+			addTest('rect', function(testName){
+				var surface = getTestSurface(testName, 'translucent rect with rounded stroke');
+				var red_rect = surface.createRect(rect);
+				red_rect.setFill([255, 0, 0, 0.5]);
+				red_rect.setStroke({color: "blue", width: 10, join: "round" });
+				red_rect.setTransform({dx: 100, dy: 100});
+				//dojo.connect(red_rect.getNode(), "onclick", function(){ alert("red"); });
+				red_rect.connect("onclick", function(){ alert("red"); });
+			});
+
+			addTest('straight_rect', function(testName){
+				var surface = getTestSurface(testName, 'translucent rect with no stroke');
+				var blue_rect = surface.createRect(rect).setFill([0, 255, 0, 0.5]).setTransform({ dx: 100, dy: 100 });
+				//dojo.connect( blue_rect.getNode(), "onclick", function(){ blue_rect.setShape({width: blue_rect.getShape().width + 20}); });
+				blue_rect.connect("onclick", function(){ blue_rect.setShape({width: blue_rect.getShape().width + 20}); });
+			});
+
+			addTest('rotated_rect', function(testName){
+				var surface = getTestSurface(testName, '30g CCW blue translucent rounded rect');
+				console.debug('rotated_rect');
+				// anonymous 30 degree CCW rotated green rectangle
+				surface.createRect({r: 20})
+					.setFill([0, 0, 255, 0.5])
+					// rotate it around its center and move to (100, 100)
+					.setTransform([dojox.gfx.matrix.translate(100, 100), dojox.gfx.matrix.rotategAt(-30, 0, 0)])
+					;
+			});
+
+			addTest('skew_rect', function(testName){
+				var surface = getTestSurface(testName, 'skewed rects' );
+				// anonymous red rectangle
+				surface.createRect(rect).setFill(new dojo.Color([255, 0, 0, 0.5]))
+					// skew it around LB point -30d, rotate it around LB point 30d, and move it to (100, 100)
+					.setTransform([dojox.gfx.matrix.translate(100, 100), dojox.gfx.matrix.rotategAt(-30, 0, 100), dojox.gfx.matrix.skewXgAt(30, 0, 100)]);
+				// anonymous blue rectangle
+				surface.createRect(rect).setFill(new dojo.Color([0, 0, 255, 0.5]))
+					// skew it around LB point -30d, and move it to (100, 100)
+					.setTransform([dojox.gfx.matrix.translate(100, 100), dojox.gfx.matrix.skewXgAt(30, 0, 100)]);
+				// anonymous yellow rectangle
+				surface.createRect(rect).setFill(new dojo.Color([255, 255, 0, 0.25]))
+					// move it to (100, 100)
+					.setTransform(dojox.gfx.matrix.translate(100, 100));
+			});
+
+			addTest('matrix_rect', function(testName){
+				var surface = getTestSurface(testName, 'all matrix operations, check debug output for more details');
+
+				var group = surface.createGroup();
+		
+				var blue_rect = group.createRect(rect).setFill([0, 0, 255, 0.5]).applyTransform(dojox.gfx.matrix.identity);
+				console.debug( "blue_rect: rect with identity" );
+
+				group.createRect(rect).setFill([0, 255, 0, 0.5]).applyTransform(dojox.gfx.matrix.translate(30, 40));
+				console.debug( "lime_rect: translate(30,40) " );
+		
+				group.createRect(rect).setFill([255, 0, 0, 0.5]).applyTransform(dojox.gfx.matrix.rotateg(-30));
+				console.debug( "red_rect: rotate 30 degree counterclockwise " );
+
+				group.createRect(rect).setFill([0, 255, 255, 0.5])
+					.applyTransform(dojox.gfx.matrix.scale({x:1.5, y:0.5}))
+					.applyTransform(dojox.gfx.matrix.translate(-40, 220))
+					;
+				console.debug( "lightblue_rect: scale(1.5, 0.5)" );
+
+				group.createRect(rect).setFill([0, 0, 255, 0.5]).setFill([255, 0, 255, 0.5]).applyTransform(dojox.gfx.matrix.flipX);
+				console.debug( "pink_rect: flipX" );
+
+				group.createRect(rect).setFill([0, 0, 255, 0.5]).setFill([255, 255, 0, 0.5]).applyTransform(dojox.gfx.matrix.flipY);
+				console.debug( "yellow_rect: flipY" );
+
+				group.createRect(rect).setFill([0, 0, 255, 0.5]).setFill([128, 0, 128, 0.5]).applyTransform(dojox.gfx.matrix.flipXY);
+				console.debug( "purple_rect: flipXY" );
+
+				group.createRect(rect).setFill([0, 0, 255, 0.5]).setFill([255, 128, 0, 0.5]).applyTransform(dojox.gfx.matrix.skewXg(-15));
+				console.debug( "purple_rect: skewXg 15 degree" );
+
+				group.createRect(rect).setFill([0, 0, 255, 0.5]).setFill([0, 0, 0, 0.5]).applyTransform(dojox.gfx.matrix.skewYg(-50));
+				console.debug( "black_rect: skewXg 50 degree" );
+
+				// move
+				group
+					.setTransform({ xx: 1.5, yy: 0.5, dx: 100, dy: 100 })
+					.applyTransform(dojox.gfx.matrix.rotateg(-30))
+					;
+			});
+
+			addTest('attach', function(testName){
+				var surface = getTestSurface(testName, 'Attach to existed shape');
+				var red_rect = surface.createRect(rect)
+					.setShape({ width: 75 })
+					.setFill([255, 0, 0, 0.5])
+					.setStroke({ color: "blue", width: 1 })
+					.setTransform({ dx: 50, dy: 50, xx: 1, xy: 0.5, yx: 0.7, yy: 1.1 })
+					;
+
+				console.debug("attaching !");
+				// now attach it!
+				var ar = dojox.gfx.attachNode(red_rect.rawNode);
+				console.assert( ar.rawNode == red_rect.rawNode );
+
+				// FIXME: more generic method to compare two dictionary?
+				console.debug("attach shape: ");
+				isEqual(ar.shape, red_rect.shape, "rect.shape");
+				console.debug("attach matrix: ");
+				isEqual(ar.matrix, red_rect.matrix, "rect.matrix");
+				console.debug("attach strokeStyle: ");
+				isEqual(ar.strokeStyle, red_rect.strokeStyle, "rect.strokeStyle");
+				console.debug("attach fillStyle: ");
+				isEqual(ar.fillStyle, red_rect.fillStyle, "rect.fillStyle");
+			});
+	
+			// test circle
+			addTest('circle', function(testName){
+				var surface = getTestSurface(testName, 'translucent green circle');
+				var circle = { cx: 130, cy: 130, r: 50 };
+				surface.createCircle(circle).setFill([0, 255, 0, 0.5]).setTransform({ dx: 20, dy: 20 });
+			});
+
+			// test line
+			addTest('line', function(testName){
+				var surface = getTestSurface(testName, 'straight red line');
+				var line = { x1: 20, y1: 20, x2: 100, y2: 120 };
+				surface.createLine(line).setFill([255, 0, 0, 0.5]).setStroke({color: "red", width: 1}).setTransform({ dx:70, dy: 100 });
+			});
+
+			// test ellipse 
+			addTest('ellipse', function(testName){
+				var surface = getTestSurface(testName, 'translucent cyan ellipse');
+				var ellipse = { cx: 50, cy: 80, rx: 50, ry: 80 };
+				surface.createEllipse(ellipse).setFill([0, 255, 255, 0.5]).setTransform({ dx: 30, dy: 70 });
+			});
+
+			// test polyline
+			addTest('polyline', function(testName){
+				var surface = getTestSurface(testName, 'unfilled open polyline');
+				var points = [ {x: 10, y: 20}, {x: 40, y: 70}, {x: 120, y: 50}, {x: 90, y: 90} ];
+				surface.createPolyline(points).setFill(null).setStroke({ color: "blue", width: 1 }).setTransform({ dx: 15, dy: 0 });
+			});
+
+			// test polygon
+			addTest('polygon', function(testName){
+				var surface = getTestSurface(testName, 'filled polygon');
+				var points2 = [{x: 100, y: 0}, {x: 200, y: 40}, {x: 180, y: 150}, {x: 60, y: 170}, {x: 20, y: 100}];
+				surface.createPolyline(points2).setFill([0, 128, 255, 0.6]).setTransform({dx:30, dy: 20});
+			});
+
+			// test path: lineTo, moveTo, closePath
+			addTest('lineTo', function(testName){
+				var surface = getTestSurface(testName, 'lineTo, moveTo, closePath');
+				surface.createPath()
+					.moveTo(10, 20).lineTo(80, 150)
+					.setAbsoluteMode(false).lineTo(40, 0)
+					.setAbsoluteMode(true).lineTo(180, 100)
+					.setAbsoluteMode(false).lineTo(0, -30).lineTo(-30, -50)
+					.closePath()
+					.setStroke({ color: "red", width: 1 })
+					.setFill(null)
+					.setTransform({ dx: 10, dy: 18 })
+					;
+			});
+
+			addTest('setPath', function(testName){
+				var surface = getTestSurface(testName, 'setPath example with lineTo moveTo');
+				surface.createPath()
+					.moveTo(10, 20).lineTo(80, 150)
+					.setAbsoluteMode(false).lineTo(40,0)
+					.setAbsoluteMode(true).lineTo(180, 100)
+					.setAbsoluteMode(false).lineTo(0, -30).lineTo(-30, -50)
+					.curveTo(10, -80, -150, -10, -90, -10)
+					.closePath()
+					.setStroke({ color: "red", width: 1 })
+					.setFill(null)
+					.setTransform({ dx: 10, dy: 58 })
+					;
+
+				surface.createPath({ path: "M10,20 L80,150 l40,0 L180,100 l0,-30 l-30,-50 c10,-80 -150,-10 -90,-10 z" })
+					.setFill(null)
+					.setStroke({ color: "blue", width: 1 })
+					.setTransform({ dx: 50, dy: 78 })
+					;
+			});
+
+			// test arcTo 
+			addTest('arcTo', function(testName){
+				var surface = getTestSurface(testName, 'arcTo: from 0 to 360 degree, w/ 30 degree of x axis rotation, rendered with different color');
+
+				var m = dojox.gfx.matrix;
+				var g1 = surface.createGroup();
+				var g2 = g1.createGroup();
+
+				var rx = 100, ry = 60, xRotg = 30;
+				var startPoint = m.multiplyPoint(m.rotateg(xRotg), {x: -rx, y: 0  });
+				var endPoint   = m.multiplyPoint(m.rotateg(xRotg), {x: 0,   y: -ry});
+	    
+				var re1 = g1.createPath()
+					.moveTo(startPoint)
+					.arcTo(rx, ry, xRotg, true, false, endPoint)
+					.setStroke({color: "red"})
+					;
+				var ge1 = g1.createPath()
+					.moveTo(re1.getLastPosition())
+					.arcTo(rx, ry, xRotg, false, false, startPoint)
+					.setStroke({color: "blue"})
+					;
+				var re2 = g2.createPath()
+					.moveTo(startPoint)
+					.arcTo(rx, ry, xRotg, false, true, endPoint)
+					.setStroke({color: "red"})
+					;
+				var ge2 = g2.createPath()
+					.moveTo(re2.getLastPosition())
+					.arcTo(rx, ry, xRotg, true, true, startPoint)
+					.setStroke({color: "blue"})
+					;
+			
+				g1.setTransform({dx: 150, dy: 150});
+				g2.setTransform({dx: 10,  dy: 10});
+			});
+
+			// test path: curveTo, smoothCurveTo
+			addTest('curveTo', function(testName) {
+				var surface = getTestSurface(testName, 'curveTo, smoothCurveTo');
+				surface.createPath()
+					.moveTo(10, 20).curveTo(50, 50, 50, 100, 150, 100).smoothCurveTo(300, 300, 200, 200)
+					.setStroke({ color: "green", width: 1 }).setFill(null).setTransform({ dx: 10, dy: 30 })
+					;
+			});
+
+			// test path: curveTo, smoothCurveTo with relative.
+			addTest('curveTo2', function(testName) {
+				var surface = getTestSurface(testName, 'curveTo, smoothCurveTo with relative coordination');
+				surface.createPath()
+					.moveTo(10, 20).curveTo(50, 50, 50, 100, 150, 100)
+					.setAbsoluteMode(false).smoothCurveTo(150, 200, 50, 100)
+					.setAbsoluteMode(true).smoothCurveTo(50, 100, 10, 230)
+					.setStroke({ color: "green", width: 1 }).setFill(null).setTransform({ dx: 10, dy: 30 })
+					;
+			});
+
+			// test path: curveTo, smoothCurveTo with relative.
+			addTest('qCurveTo', function(testName) {
+				var surface = getTestSurface(testName, 'qCurveTo, qSmoothCurveTo' );
+				surface.createPath()
+					.moveTo(10, 15).qCurveTo(50, 50, 100, 100).qSmoothCurveTo(150, 20)
+					.setStroke({ color: "green", width: 1 }).setFill(null).setTransform({ dx: 10, dy: 30 })
+					;
+			});
+
+			addTest('qCurveTo2', function(testName) {
+				var surface = getTestSurface(testName, 'qCurveTo, qSmoothCurveTo with relative' );
+				surface.createPath()
+					.moveTo(10, 20).qCurveTo(50, 50, 100, 100)
+					.setAbsoluteMode(false).qSmoothCurveTo(50, -80)
+					.setAbsoluteMode(true).qSmoothCurveTo(200, 80)
+					.setStroke({ color: "green", width: 1 }).setFill(null).setTransform({ dx: 10, dy: 30 })
+					;
+			});
+
+			// test defines, linearGradient
+			addTest('linearGradient', function(testName) {
+				var surface = getTestSurface(testName, 'linear gradient fill');
+				// this is an example to split the linearGradient from setFill:
+				var lg = {
+					type: "linear",
+					x1: 0, y1: 0, x2: 75, y2: 50,
+					colors: [
+						{ offset: 0, color: "#F60" },
+						{ offset: 1, color: "#FF6" }
+					]
+				};
+				surface.createRect(rect).setFill(lg).setTransform({ dx: 40, dy: 100 });
+			});
+
+			// TODO: test radialGradient
+			addTest('radialGradient', function(testName) {
+				var surface = getTestSurface(testName, 'radial gradient fill');
+				// this is a total inline implementation compared with previous one.
+				var rg = {
+					type: "radial",
+					cx: 100, cy: 100, r: 100,
+					colors: [
+						{ offset:   0, color: "red" },
+						{ offset: 0.5, color: "green" },
+						{ offset:   1, color: "blue" }
+					]
+				};
+		
+				surface.createCircle({cx: 100, cy: 100, r: 100})
+					.setStroke({})
+					.setFill(rg)
+					.setTransform({dx: 40, dy: 30})
+					;
+		//		surface.createRect(rect)
+		//			.setShape({width: 200})
+		//			.setStroke({})
+		//			.setFill(rg)
+		//			.setTransform({dx: 40, dy: 30})
+		//			;
+			});
+
+			addTest('attach_gradient', function(testName) {
+				var surface = getTestSurface(testName, 'attach gradient fill');
+				// this is an example to split the linearGradient from setFill:
+				var lg = {
+					type: "linear",
+					x1: 0, y1: 0, x2: 75, y2: 50,
+					colors: [
+						{ offset:   0, color: "#F60" },
+						{ offset: 0.5, color: "#FAF" },
+						{ offset:   1, color: "#FF6" }
+					]
+				};
+
+				var lgr = surface.createRect(rect).setFill(lg).setTransform({ dx: 40, dy: 100 });
+
+				var ar = dojox.gfx.attachNode(lgr.rawNode);
+				// FIXME: more generic method to compare two dictionary?
+				console.debug("attach_gradient!");
+
+				console.debug("attach shape: ");
+				isEqual(lgr.shape, ar.shape, "rect.shape");
+				console.debug("attach matrix: ");
+				isEqual(lgr.matrix, ar.matrix, "rect.matrix");
+				console.debug("attach strokeStyle: ");
+				isEqual(lgr.strokeStyle, ar.strokeStyle, "rect.strokeStyle");
+				console.debug("attach fillStyle: ");
+				isEqual(lgr.fillStyle.gradient, ar.fillStyle.gradient, "rect.fillStyle.gradient");
+				//isEqual(lgr.fillStyle.id, ar.fillStyle.id, "rect.fillStyle.id");
+			});
+
+			var gTestsToRun = [
+				'rect',
+				'straight_rect',
+				'rotated_rect',
+				'skew_rect',
+				'matrix_rect', 
+				//'attach',
+				//'attach_gradient',
+				'circle',
+				'arcTo',
+				'line',
+				'ellipse',
+				'polyline',
+				'polygon',
+				'lineTo',
+				'setPath',
+				'curveTo',
+				'curveTo2',
+				'qCurveTo',
+				'qCurveTo2',
+				'linearGradient',
+				'radialGradient'
+			];
+
+			for (var i = 0; i < gTestsToRun.length; ++i) {
+				var testName = gTestsToRun[i];
+				var err = runTest(testName);
+				if (err) {
+					getTestSurface(testName, testName + ' FAILED (' + err + ')');
+				}
+			}
+
+		}); // end onload
+		</script>
+</head>
+<body>
+	<h1 class="testTitle">dojox.gfx tests</h1>
+		<table>
+			<tbody id="testcontainer">
+			</tbody>
+		</table>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_gradient.html b/dojox/gfx/tests/test_gradient.html
new file mode 100644
index 0000000..3aa6ffa
--- /dev/null
+++ b/dojox/gfx/tests/test_gradient.html
@@ -0,0 +1,66 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojo.colors"); // pull in CSS3 color names
+
+makeShapes = function(){
+	var SIDE = 10;
+	var fillObj = {
+		colors: [
+			{ offset: 0,   color: [255, 255, 0, 0] },
+			{ offset: 0.5, color: "orange" },
+			{ offset: 1,   color: [255, 255, 0, 0] }
+		]
+	};
+	var surface = dojox.gfx.createSurface(dojo.byId("grad"), 300, 300);
+	// create a background
+	for(var i = 0; i < 300; i += SIDE){
+		for(var j = 0; j < 300; j += SIDE){
+			surface.
+				createRect({x: j, y: i, width: 10, height: 10}).
+				setFill((Math.floor(i / SIDE) + Math.floor(j / SIDE)) % 2 ? "lightgrey" : "white");
+		}
+	}
+	// create a rect
+	surface.createRect({ 
+		width:  300,
+		height: 100
+	}).setFill(dojo.mixin({
+		type: "linear",
+		x1: 0, y1: 0,
+		x2: 300, y2: 0
+	}, fillObj));
+	// create a circle
+	surface.createEllipse({
+		cx: 150,
+		cy: 200,
+		rx: 100,
+		ry: 100
+	}).setFill(dojo.mixin({
+		type: "radial",
+		cx: 150,
+		cy: 200
+	}, fillObj));
+};
+dojo.addOnLoad(makeShapes);
+</script>
+<style type="text/css">
+#grad { width: 300px; height: 300px; }
+</style>
+</head>
+<body>
+<h1>dojox.gfx Alpha gradient test</h1>
+<div id="grad"></div>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_group1.html b/dojox/gfx/tests/test_group1.html
new file mode 100644
index 0000000..92f336d
--- /dev/null
+++ b/dojox/gfx/tests/test_group1.html
@@ -0,0 +1,69 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../matrix.js"></script>-->
+<!--<script type="text/javascript" src="../util.js"></script>-->
+<!--<script type="text/javascript" src="../shape.js"></script>-->
+<!--<script type="text/javascript" src="../path.js"></script>-->
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var surface = null;
+var g1 = null;
+var g2 = null;
+var r1 = null;
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface(document.getElementById("test"), 500, 500);
+	// make a checkerboard
+	for(var i = 0; i < 500; i += 100){
+		for(var j = 0; j < 500; j += 100){
+			if(i % 200 == j % 200) {
+				surface.createRect({ x: i, y: j }).setFill([255, 0, 0, 0.1]);
+			}
+		}
+	}
+	// create groups and shapes
+	g1 = surface.createGroup();
+	g2 = surface.createGroup();
+	r1 = surface.createRect({x: 200, y: 200}).setFill("green").setStroke({});
+	g1.setTransform({dy: -100});
+	//g2.setTransform(dojox.gfx.matrix.rotateAt(-45, 250, 250));
+	g2.setTransform({dx: 100, dy: -100});
+};
+
+switchRect = function(){
+	var radio = document.getElementsByName("switch");
+	if(radio[0].checked){
+		surface.add(r1);
+	}else if(radio[1].checked){
+		g1.add(r1);
+	}else if(radio[2].checked){
+		g2.add(r1);
+	}
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Group tests</h1>
+<p>
+<input type="radio" name="switch" id="r1_s" checked="checked" onclick="switchRect()" /><label for="r1_s">Rectangle belongs to the surface</label><br />
+<input type="radio" name="switch" id="r1_g1" onclick="switchRect()" /><label for="r1_g1">Rectangle belongs to the group #1</label><br />
+<input type="radio" name="switch" id="r1_g2" onclick="switchRect()" /><label for="r1_g2">Rectangle belongs to the group #2</label>
+</p>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_group2.html b/dojox/gfx/tests/test_group2.html
new file mode 100644
index 0000000..0adc7b8
--- /dev/null
+++ b/dojox/gfx/tests/test_group2.html
@@ -0,0 +1,50 @@
+<html>
+<head>
+<title>Testing add/remove shape</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dijit.form.CheckBox");
+dojo.require("dojo.parser");
+
+var surface = null, shape = null;
+
+createSurface = function(){
+	surface = dojox.gfx.createSurface("test", 300, 300);
+};
+
+flip = function(){
+	if(dijit.byId("cb").checked){
+		if(!shape){
+			//shape = surface.createRect({x: 100, y: 100, width: 100, height: 100})
+			shape = surface.createCircle({cx: 150, cy : 150, r: 50})
+				.setFill("yellow").setStroke({color: "red", width: 3});
+		}else{
+			surface.add(shape);
+		}
+	}else{
+		surface.remove(shape);
+	}
+}
+
+dojo.addOnLoad(createSurface);
+</script>
+
+
+</head>
+
+<body class="tundra">
+<h1>Testing add/remove shape</h1>
+<p>
+	<input type="checkbox" dojoType="dijit.form.CheckBox" id="cb" name="cb" onClick="flip()">
+	<label for="cb">Add shape to the surface</label>
+</p>
+<div id="test" style="width: 300px; height: 300px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_image1.html b/dojox/gfx/tests/test_image1.html
new file mode 100644
index 0000000..436da3b
--- /dev/null
+++ b/dojox/gfx/tests/test_image1.html
@@ -0,0 +1,72 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing image</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var image = null, grid_size = 500, grid_step = 50,
+	m = dojox.gfx.matrix;
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 800, 600);
+	for(var i = 0; i <= grid_size; i += grid_step){
+		surface.createLine({x1: 0, x2: grid_size, y1: i, y2: i}).setStroke("black");
+		surface.createLine({y1: 0, y2: grid_size, x1: i, x2: i}).setStroke("black");
+	}
+    image = surface.createImage({width: 150, height: 100, src: "images/eugene-sm.jpg"});
+    image.connect("onclick", function(){ alert("You didn't expect a download, did you?"); });
+};
+
+transformImage = function(){
+	var radio = document.getElementsByName("switch");
+	if(radio[0].checked){
+        image.setTransform({});
+	}else if(radio[1].checked){
+        image.setTransform({dx: 100, dy: 50});
+	}else if(radio[2].checked){
+        image.setTransform(m.rotateg(15));
+	}else if(radio[3].checked){
+        image.setTransform([{dx: 70, dy: 90}, {xx: 1.5, yy: 0.5}]);
+	}else if(radio[4].checked){
+        image.setTransform([m.rotateg(15), m.skewXg(30)]);
+	}
+	var shift = document.getElementsByName("shift");
+	if(shift[0].checked){
+		image.setShape({x: 0, y: 0});
+	}else if(shift[1].checked){
+		image.setShape({x: 100, y: 50});
+	}else if(shift[2].checked){
+		image.setShape({x: 0, y: 0});
+		image.applyRightTransform({dx: 100, dy: 50});
+	}
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Image tests</h1>
+<p>Note: Silverlight doesn't allow downloading images when run from a file system. This demo should be run from a server.</p>
+<p>
+<input type="radio" name="switch" id="r1_reset" checked onclick="transformImage()" /><label for="r1_reset">Reset Image</label><br />
+<input type="radio" name="switch" id="r1_move" onclick="transformImage()" /><label for="r1_move">Move Image</label><br />
+<input type="radio" name="switch" id="r1_rotate" onclick="transformImage()" /><label for="r1_rotate">Rotate Image</label><br />
+<input type="radio" name="switch" id="r1_scale" onclick="transformImage()" /><label for="r1_scale">Scale Image</label><br />
+<input type="radio" name="switch" id="r1_skew" onclick="transformImage()" /><label for="r1_skew">Skew Image</label><br />
+</p>
+<p>
+<input type="radio" name="shift" id="r2_none" checked onclick="transformImage()" /><label for="r2_none">Place image at (0, 0)</label><br />
+<input type="radio" name="shift" id="r2_origin" onclick="transformImage()" /><label for="r2_origin">Place image at (100, 50)</label><br />
+<input type="radio" name="shift" id="r2_shift" onclick="transformImage()" /><label for="r2_shift">Shift image by (100, 50)</label>
+</p>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_image2.html b/dojox/gfx/tests/test_image2.html
new file mode 100644
index 0000000..faecf90
--- /dev/null
+++ b/dojox/gfx/tests/test_image2.html
@@ -0,0 +1,55 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing image</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var grid_size = 500, grid_step = 50;
+var main = null, g = null, image = null, rect = null;
+
+makeShapes = function(){
+	var s = dojox.gfx.createSurface("test", 800, 600);
+	for(var i = 0; i <= grid_size; i += grid_step){
+		s.createLine({x1: 0, x2: grid_size, y1: i, y2: i}).setStroke("black");
+		s.createLine({y1: 0, y2: grid_size, x1: i, x2: i}).setStroke("black");
+	}
+
+	main = s.createGroup();
+	rect = main.createRect({x: 0, y: 0, width: 200, height: 200}).setStroke("black").setFill(new dojo.Color([255, 0, 255, 0.5]));
+	rect.connect("onclick", function(){ alert("rect"); })
+    
+	image = s.createImage({width: 150, height: 100, src: "images/eugene-sm.jpg"});
+	image.connect("onclick", function(){ alert("image"); })
+	
+	main.add(image);
+	
+	// static images to see how the size
+
+	s.createImage({x: 0,   y: 200, width: 150, height: 100, src: "images/eugene-sm.jpg"});
+	s.createImage({x: 0,   y: 300, width: 300, height: 100, src: "images/eugene-sm.jpg"});
+	s.createImage({x: 300, y: 200, width: 150, height: 200, src: "images/eugene-sm.jpg"});
+	
+	main.moveToFront();
+};
+
+trans = function(){
+	var x = 1;
+	main.setTransform([dojox.gfx.matrix.rotategAt(45, 200, 200), {dx: 200, dy: 200}]);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<p>Testing image:<br /><button onclick="trans();">Trans</button></p>
+<p>Note: Silverlight doesn't allow downloading images when run from a file system. This demo should be run from a server.</p>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_image3.html b/dojox/gfx/tests/test_image3.html
new file mode 100755
index 0000000..cb889b4
--- /dev/null
+++ b/dojox/gfx/tests/test_image3.html
@@ -0,0 +1,65 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing image 3</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var surface, image = null, grid_size = 1000, grid_step = 50, surface2, image2
+	m = dojox.gfx.matrix;
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface("test", 800, 600);
+	for(var i = 0; i <= grid_size; i += grid_step){
+		surface.createLine({x1: 0, x2: grid_size, y1: i, y2: i}).setStroke("black");
+		surface.createLine({y1: 0, y2: grid_size, x1: i, x2: i}).setStroke("black");
+	}
+    image = surface.createImage({width: 150, height: 100, src: "images/eugene-sm.jpg"});
+    image.connect("onclick", function(){ alert("You didn't expect a download, did you?"); });
+
+    //create second test
+    surface2 = dojox.gfx.createSurface("test2", 600, 600);
+    image2 = surface2.createImage({width: 150, height: 100, src: "images/eugene-sm.jpg"});
+};
+
+transformImage = function(){
+	if(window.scaled){
+		surface.setDimensions(800,600);
+		image.setTransform({});
+                
+		surface2.setDimensions(600,600);
+		image2.setTransform();
+	}else{
+		surface.setDimensions(1000,600);
+	    image.setTransform({xx: 6, yy: 6});
+
+            surface2.setDimensions(800,600);
+            image2.setTransform({xx: 5, yy: 5});
+	}
+	window.scaled=!window.scaled;
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Image tests</h1>
+<p>Clicking the following button should enlarge the surface and the image.<br>
+In the first Test: The image should not be cropped on the right and the background of grid should be red.<br>
+In the secondd test: the cavas should stay the same size, the image is increased and scrollbars appear
+	</p>
+<p>
+<input type="button" onclick="transformImage()" value="scale/reset"/><br />
+</p>
+<div id="test" style="background-color:red"></div>
+<p>second test with overflow=auto</p>
+<div style="overflow:auto;background-color:red;width:602px;height:602px;"><div id="test2"></div></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_image4.html b/dojox/gfx/tests/test_image4.html
new file mode 100644
index 0000000..8454345
--- /dev/null
+++ b/dojox/gfx/tests/test_image4.html
@@ -0,0 +1,53 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing image 4</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojo.colors");
+
+makeShapes = function(){
+    var g = dojox.gfx, m = g.matrix;
+    
+	var grid_size = 200, grid_step = 20,
+        surface = g.createSurface("test", grid_size, grid_size)
+	for(var i = 0; i <= grid_size; i += grid_step){
+		surface.createLine({x1: 0, x2: grid_size, y1: i, y2: i}).setStroke("grey");
+		surface.createLine({y1: 0, y2: grid_size, x1: i, x2: i}).setStroke("grey");
+	}
+    
+    var rect1 = surface.createRect({x: 50, y: 50, width: 100, height: 100, r: 5}).setFill("red").setStroke("black");
+    var img1  = surface.createImage({width: 75, height: 50, src: "images/eugene-sm.jpg"}).
+                    setTransform([m.translate(50, 0), m.rotateg(45)]);
+    var rect2 = surface.createRect({x: 75, y: 25, width: 50, height: 150, r: 5}).setFill("yellow").setStroke("black");
+    var img2  = surface.createImage({width: 75, height: 50, src: "images/eugene-sm.jpg"}).
+                    setTransform([m.translate(50, 120), m.rotateg(-45)]);
+    var rect3 = surface.createRect({x: 25, y: 75, width: 150, height: 50, r: 5}).setFill("green").setStroke("black");
+
+    img1.connect("onclick", function(){ alert("image #1"); });
+    img2.connect("onclick", function(){ alert("image #2"); });
+    
+    rect1.connect("onclick", function(){ alert("red"); });
+    rect2.connect("onclick", function(){ alert("yellow"); });
+    rect3.connect("onclick", function(){ alert("green"); });
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Image event tests</h1>
+<p>Note: Silverlight doesn't allow downloading images when run from a file system. This demo should be run from a server.</p>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_image5.html b/dojox/gfx/tests/test_image5.html
new file mode 100644
index 0000000..48882b0
--- /dev/null
+++ b/dojox/gfx/tests/test_image5.html
@@ -0,0 +1,62 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing image 5</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.move");
+dojo.require("dojo.colors");
+
+makeShapes = function(){
+    var g = dojox.gfx, m = g.matrix;
+    
+	var grid_size = 800, grid_step = 50,
+        surface = g.createSurface("test", 800, 600)
+	for(var i = 0; i <= grid_size; i += grid_step){
+		surface.createLine({x1: 0, x2: grid_size, y1: i, y2: i}).setStroke("grey");
+		surface.createLine({y1: 0, y2: grid_size, x1: i, x2: i}).setStroke("grey");
+	}
+    
+    var rect1 = surface.createRect({x: 0, y: 0, width: 300, height: 200, r: 5}).setFill("red").setStroke("black");
+    var img1  = surface.createImage({width: 300, height: 200, src: "images/eugene-sm.jpg"}).setTransform({dx: 50, dy: 50});
+    var rect2 = surface.createRect({x: 100, y: 100, width: 300, height: 200, r: 5}).setFill("yellow").setStroke("black");
+    var img2  = surface.createImage({width: 300, height: 200, src: "images/eugene-sm.gif"}).setTransform({dx: 150, dy: 150});
+    var rect3 = surface.createRect({x: 200, y: 200, width: 300, height: 200, r: 5}).setFill("green").setStroke("black");
+    var img3  = surface.createImage({width: 300, height: 200, src: "images/eugene-sm.png"}).setTransform({dx: 250, dy: 250});
+    var rect4 = surface.createRect({x: 300, y: 300, width: 300, height: 200, r: 5}).setFill("blue").setStroke("black");
+    
+	new g.Moveable(rect1);
+	new g.Moveable(rect2);
+	new g.Moveable(rect3);
+	new g.Moveable(rect4);
+
+	new g.Moveable(img1);
+	new g.Moveable(img2);
+	new g.Moveable(img3);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Image opacity and move tests</h1>
+<p>Note: Silverlight doesn't allow downloading images when run from a file system. This demo should be run from a server.</p>
+<div id="test"></div>
+<p>That's how images should look like (light yellow background):</p>
+<p style="background-color: #ffe; padding: 1em; border: 1px solid black;">
+    <img src="images/eugene-sm.jpg">
+    <img src="images/eugene-sm.gif">
+    <img src="images/eugene-sm.png">
+</p>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_linearGradient.html b/dojox/gfx/tests/test_linearGradient.html
new file mode 100644
index 0000000..c3513d6
--- /dev/null
+++ b/dojox/gfx/tests/test_linearGradient.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../../../dojo/_base/Color.js"></script>
+<script type="text/javascript" src="../_base.js"></script>
+<script type="text/javascript" src="../shape.js"></script>
+<script type="text/javascript" src="../path.js"></script>
+<script type="text/javascript" src="../arc.js"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../canvas.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+dojo.require("dojo.colors");
+
+makeShapes = function(){
+	var lg1 = {
+		type: "linear",
+		x1: 0, y1: 0,
+		x2: 300, y2: 0,
+		colors: [
+			{ offset: 0,   color: [0, 0, 0, 0] },
+			{ offset: 0.1, color: "#000000" },
+			{ offset: 0.2, color: "red" },
+			{ offset: 0.3, color: "rgb(0,255,0)" },
+			{ offset: 0.4, color: "blue" },
+			{ offset: 0.5, color: "#ff0" },
+			{ offset: 0.6, color: [128] },
+			{ offset: 0.7, color: [128, 128, 64] },
+			{ offset: 1,   color: [0, 255, 0, 0] }
+		]
+	};
+	var lg2 = {
+		type: "linear",
+		x1: 0, y1: 0,
+		x2: 300, y2: 0,
+		colors: [
+			{ offset: 0.2, color: "red" },
+			{ offset: 0.3, color: "yellow" }
+		]
+	};
+	var surface = dojox.gfx.createSurface(dojo.byId("grad"), 300, 300);
+	var group = surface.createGroup();
+	var rect1 = surface.createRect({ 
+		width:  300,
+		height: 100
+	});
+	rect1.setFill(lg1);
+	var rect2 = surface.createRect({ 
+		y: 150,
+		width:  300,
+		height: 100
+	});
+	rect2.setFill(lg2);
+	group.add(rect1);
+	group.add(rect2);
+};
+dojo.addOnLoad(makeShapes);
+</script>
+<style>
+v:group { text-align: left; }
+#grad { width: 300px; height: 300px; }
+</style>
+</head>
+<body>
+<h1>dojox.gfx Linear Gradient test</h1>
+<div id="grad"></div>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_linestyle.html b/dojox/gfx/tests/test_linestyle.html
new file mode 100644
index 0000000..c48ec17
--- /dev/null
+++ b/dojox/gfx/tests/test_linestyle.html
@@ -0,0 +1,41 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../_base.js"></script>-->
+<!--<script type="text/javascript" src="../shape.js"></script>-->
+<!--<script type="text/javascript" src="../path.js"></script>-->
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface(document.getElementById("test"), 500, 500);
+	var styles = ["none", "Solid", "ShortDash", "ShortDot", "ShortDashDot", "ShortDashDotDot", 
+		"Dot", "Dash", "LongDash", "DashDot", "LongDashDot", "LongDashDotDot"];
+	var font = "normal normal normal 10pt Arial";	// CSS font style
+	var y_offset = dojox.gfx.normalizedLength("4pt");
+	for(var i = 0; i < styles.length; ++i){
+		var y = 20 + i * 20;
+		surface.createText({x: 140, y: y + y_offset, text: styles[i], align: "end"}).setFont(font).setFill("black");
+		surface.createLine({x1: 150, y1: y, x2: 490, y2: y}).setStroke({style: styles[i], width: 3, cap: "round"});
+	}
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+	<h1>dojox.gfx: Line style test</h1>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_pattern.html b/dojox/gfx/tests/test_pattern.html
new file mode 100644
index 0000000..9060d0b
--- /dev/null
+++ b/dojox/gfx/tests/test_pattern.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Testing pattern</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../matrix.js"></script>-->
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<!--<script type="text/javascript" src="../canvas.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+    var pattern = {
+        type: "pattern",
+        x: 0, y: 0, width: 75, height: 50,
+        src: "images/eugene-sm.jpg"
+    };
+	var ellipse = {cx: 400, cy: 200, rx: 350, ry: 150};
+	var surface = dojox.gfx.createSurface("test", 800, 600);
+	surface.createEllipse(ellipse)
+        .setStroke({color: "blue", width: 1 })
+        .setFill(pattern);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+	<h1>dojox.gfx Pattern test</h1>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_poly.html b/dojox/gfx/tests/test_poly.html
new file mode 100644
index 0000000..26f4041
--- /dev/null
+++ b/dojox/gfx/tests/test_poly.html
@@ -0,0 +1,49 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing polyline and line transforms</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../_base.js"></script>
+<script type="text/javascript" src="../shape.js"></script>
+<script type="text/javascript" src="../path.js"></script>
+<script type="text/javascript" src="../arc.js"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../canvas.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	var line = surface.createLine({x1: 250, y1: 50, x2: 250, y2: 250})
+		.setStroke({color: "blue"})
+		;
+	var poly = surface.createPolyline([{x: 250, y: 250}, {x: 300, y: 300}, {x: 250, y: 350}, {x: 200, y: 300}, {x: 250, y: 250}])
+		.setStroke({color: "blue"})
+		;
+	var rotate = dojox.gfx.matrix.rotategAt(5, 250, 250);
+	//var rotate = dojox.gfx.matrix.rotategAt(0.4, 250, 250);
+		
+	window.setInterval(function() {
+			line.applyTransform(rotate);
+			poly.applyTransform(rotate);
+		},
+		100
+	);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Polyline test</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_refproj.html b/dojox/gfx/tests/test_refproj.html
new file mode 100644
index 0000000..13df02c
--- /dev/null
+++ b/dojox/gfx/tests/test_refproj.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <title>Test Reflection and Projection matrices</title>
+    <style>
+        @import "../../../dojo/resources/dojo.css";
+        @import "../../../dijit/themes/tundra/tundra.css";
+    </style>
+    <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+    <script>
+        dojo.require("dojox.gfx");
+        dojo.require("dojo.colors");
+        
+        dojo.require("dijit.form.HorizontalSlider");
+        dojo.require("dijit.form.HorizontalRule");
+        dojo.require("dijit.form.HorizontalRuleLabels");
+        
+        var W = 500, H = 500, MARKER_SIZE = 5;
+
+        function makeGrid(group, size, step, stroke){
+            var g = group.createGroup();
+            stroke = stroke || {color: [0, 0, 0, 0.1], width: 1};
+            for(var i = step; i < size; i += step){
+                g.createLine({x1: 0, y1: i, x2: size, y2: i}).setStroke(stroke);
+                g.createLine({x1: i, y1: 0, x2: i, y2: size}).setStroke(stroke);
+            }
+            g.createRect({x: 0, y: 0, width: size - 1, height: size -1}).setStroke("black");
+            return g;
+        }
+        
+        var surface, shape, line = {x1: 0, y1: 0, x2: W, y2: H},
+            rm, pm, pt, rpt, ppt, point, rpoint, ppoint, rline, pline;
+            
+        function updatePoints(){
+            // get all transforms
+            rm = dojox.gfx.matrix.reflect(line.x2, line.y2);
+            pm = dojox.gfx.matrix.project(line.x2, line.y2);
+            
+            // update points and lines
+            if(point){
+                rpt = dojox.gfx.matrix.multiplyPoint(rm, pt);
+                ppt = dojox.gfx.matrix.multiplyPoint(pm, pt);
+                point.setShape({cx: pt.x, cy: pt.y, r: MARKER_SIZE});
+                rpoint.setShape({cx: rpt.x, cy: rpt.y, r: MARKER_SIZE});
+                ppoint.setShape({cx: ppt.x, cy: ppt.y, r: MARKER_SIZE});
+                rline.setShape({x1: pt.x, y1: pt.y, x2: rpt.x, y2: rpt.y});
+                pline.setShape({x1: pt.x, y1: pt.y, x2: ppt.x, y2: ppt.y});
+            }
+        }
+        
+        function shiftVector(value){
+            // update the line
+            if(value < 0){
+                line.y2 = H;
+                line.x2 = W + (W / 100) * value;
+            }else{
+                line.x2 = W;
+                line.y2 = H - (H / 100) * value;
+            }
+            shape.setShape(line);
+            updatePoints();
+        }
+        
+        function setPoint(e){
+            var bbox = dojo.position("surf", true);
+            pt = {x: e.pageX - bbox.x, y: e.pageY - bbox.y};
+            if(!point){
+                point = surface.createCircle({cx: 0, cy: 0, r: MARKER_SIZE}).
+                    setStroke("black").setFill("yellow");
+                rpoint = surface.createCircle({cx: 0, cy: 0, r: MARKER_SIZE}).
+                    setStroke("black").setFill("red");
+                ppoint = surface.createCircle({cx: 0, cy: 0, r: MARKER_SIZE}).
+                    setStroke("black").setFill("green");
+                rline = surface.createLine({x1: 0, y1: 0, x2: 0, y2: 0}).
+                    setStroke("red");
+                pline = surface.createLine({x1: 0, y1: 0, x2: 0, y2: 0}).
+                    setStroke({color: "green", style: "dash"});
+            }
+            updatePoints();
+        }
+
+        run = function(){
+            dojo.attr("start", "disabled", true);
+            surface = dojox.gfx.createSurface("surf", W, H);
+            makeGrid(surface, W, 50);
+            shape = surface.createLine(line).setStroke("black");
+            dojo.connect(dijit.byId("shifter"), "onChange", shiftVector);
+            dojo.connect(dojo.byId("surf"), "onclick", setPoint);
+            shiftVector(0);
+        };
+        
+        dojo.addOnLoad(run);
+    </script>
+</head>
+<body class="tundra">
+    <h1>Test Reflection and Projection matrices</h1>
+    <p><button id="start" onclick="run();">Start!</button></p>
+    <div id="shifter" dojoType="dijit.form.HorizontalSlider" 
+            value="0" minimum="-100" maximum="100" value="0" discreteValues="21" showButtons="false" intermediateChanges="true" style="width: 500px;">
+        <div dojoType="dijit.form.HorizontalRule" container="topDecoration" count="21" style="height: 5px;"></div>
+        <div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="5" style="height: 5px;"></div>
+        <div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" labels="-100,-50,0,50,100" style="height: 1.2em; font-size: 75%; color: gray;"></div>
+    </div>
+    <div id="surf"></div>
+    <p>Legend: <span style="background: yellow;">yellow</span> is your point, <span style="color: red;">red</span> is a reflected point,
+    <span style="color: green;">green</span> is a projected point.</p>
+    <p>Click anywhere on the surface to set a point and see its reflection and projection.</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_resize.html b/dojox/gfx/tests/test_resize.html
new file mode 100644
index 0000000..8a99fbe
--- /dev/null
+++ b/dojox/gfx/tests/test_resize.html
@@ -0,0 +1,57 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing surface resizing</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../_base.js"></script>
+<script type="text/javascript" src="../shape.js"></script>
+<script type="text/javascript" src="../path.js"></script>
+<script type="text/javascript" src="../arc.js"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../canvas.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var surface;
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface("test", 500, 500);
+	surface.createRect({width: 300, height: 300}).setFill([255, 0, 0, 0.3]).setStroke("red");
+	surface.createRect({x: 200, y: 200, width: 300, height: 300}).setFill([0, 0, 255, 0.3]).setStroke("green");
+};
+
+getDim = function(){
+	var t = surface.getDimensions();
+	alert("dimensions: " + t.width + " by " + t.height);
+};
+
+make500x500 = function(){ surface.setDimensions(500, 500); };
+make400x400 = function(){ surface.setDimensions(400, 400); };
+make300x300 = function(){ surface.setDimensions(300, 300); };
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>Testing surface resizing</h1>
+<!--<p><button onclick="makeShapes();">Go</button></p>-->
+<p>
+	<button onclick="getDim();">getDimensions</button>
+	 
+	<button onclick="make300x300();">Make 300x300</button>
+	 
+	<button onclick="make400x400();">Make 400x400</button>
+	 
+	<button onclick="make500x500();">Make 500x500</button>
+</p>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_setPath.html b/dojox/gfx/tests/test_setPath.html
new file mode 100644
index 0000000..7a1f010
--- /dev/null
+++ b/dojox/gfx/tests/test_setPath.html
@@ -0,0 +1,82 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Testing setPath and curves</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	li {font-weight: bold;}
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../path.js"></script>-->
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 400);
+	// relative path with cubic beziers
+	surface
+		.createPath("m100 100 100 0 0 100c0 50-50 50-100 0s-50-100 0-100z")
+		.setStroke({color: "black"})
+		.setFill("red")
+		.setTransform({dx: -50, dy: -50})
+		;
+	// absolute path with cubic bezier
+	surface
+		.createPath("M100 100 200 100 200 200C200 250 150 250 100 200S50 100 100 100z")
+		.setStroke({color: "black"})
+		.setFill("#f80")
+		.setTransform({dx: 100, dy: -50})
+		;
+	// relative path with horizontal and vertical lines, and cubic beziers
+	surface
+		.createPath("m100 100h100v100c0 50-50 50-100 0s-50-100 0-100z")
+		.setStroke({color: "black"})
+		.setFill("yellow")
+		.setTransform({dx: 250, dy: -50})
+		;
+	// relative path with quadratic beziers
+	surface
+		.createPath("m100 100 100 0 0 100q0 50-75-25t-25-75z")
+		.setStroke({color: "black"})
+		.setFill("green")
+		.setTransform({dx: -50, dy: 150})
+		;
+	// absolute path with quadratic bezier
+	surface
+		.createPath("M100 100 200 100 200 200Q200 250 125 175T100 100z")
+		.setStroke({color: "black"})
+		.setFill("blue")
+		.setTransform({dx: 100, dy: 150})
+		;
+	// relative path with horizontal and vertical lines, and quadratic beziers
+	surface
+		.createPath("m100 100h100v100q0 50-75-25t-25-75z")
+		.setStroke({color: "black"})
+		.setFill("#f0f")
+		.setTransform({dx: 250, dy: 150})
+		;
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx setPath and curve test</h1>
+<div id="test" style="width: 500px; height: 400px;"></div>
+<p>Legend:</p>
+<ul>
+	<li style="background: red"><span style="color: white">relative path with cubic beziers</span></li>
+	<li style="background: #f80"><span style="color: black">absolute path with cubic bezier</span></li>
+	<li style="background: yellow"><span style="color: black">relative path with horizontal and vertical lines, and cubic beziers</span></li>
+	<li style="background: green"><span style="color: white">relative path with quadratic beziers</span></li>
+	<li style="background: blue"><span style="color: white">absolute path with quadratic bezier</span></li>
+	<li style="background: #f0f"><span style="color: black">relative path with horizontal and vertical lines, and quadratic beziers</span></li>
+</ul>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_tbbox.html b/dojox/gfx/tests/test_tbbox.html
new file mode 100644
index 0000000..7d64566
--- /dev/null
+++ b/dojox/gfx/tests/test_tbbox.html
@@ -0,0 +1,113 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../_base.js"></script>
+<script type="text/javascript" src="../shape.js"></script>
+<script type="text/javascript" src="../path.js"></script>
+<script type="text/javascript" src="../arc.js"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../canvas.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface(document.getElementById("test"), 500, 500);
+	var g1 = surface.createGroup();
+	// make a checkerboard
+	for(var i = 0; i < 500; i += 100){
+		for(var j = 0; j < 500; j += 100){
+			if(i % 200 == j % 200) {
+				surface.createRect({ x: i, y: j }).setFill([255, 0, 0, 0.1]);
+			}
+		}
+	}
+	var r1 = g1.createRect({ x: 200, y: 200 })
+				.setFill("green")
+				.setStroke({})
+				//.setTransform(dojox.gfx.matrix.rotategAt(45, 250, 250))
+				;
+	var r2 = surface.createRect().setStroke({})
+				.setFill({ type: "linear", to: { x: 50, y: 100 },
+					colors: [{ offset: 0, color: "green" }, { offset: 0.5, color: "red" }, { offset: 1, color: "blue" }] })
+				.setTransform({dx: 100, dy: 100})
+				;
+	var r3 = surface.createRect().setStroke({})
+				.setFill({ type: "linear" })
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 250, 250))
+				;
+	var r4 = g1.createRect({})
+				.setFill("blue")
+				//.setStroke({})
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 350, 250))
+				.setTransform([dojox.gfx.matrix.rotategAt(-30, 350, 250), { dx: 300, dy: 200 }])
+				;
+	var p1 = g1.createPath()
+				.setStroke({})
+				.moveTo( 300, 100 )
+				.lineTo( 400, 200 )
+				.lineTo( 400, 300 )
+				.lineTo( 300, 400 )
+				.curveTo( 400, 300, 400, 200, 300, 100 )
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 250, 250))
+				.setTransform({})
+				;
+	var p2 = g1.createPath(p1.getShape())
+				.setStroke({ color: "red", width: 2 })
+				//.moveTo( 300, 100 )
+				//.lineTo( 400, 200 )
+				//.lineTo( 400, 300 )
+				//.lineTo( 300, 400 )
+				//.curveTo( 400, 300, 400, 200, 300, 100 )
+				//.setTransform(dojox.gfx.matrix.rotategAt(180, 250, 250))
+				.setTransform({ dx: 100 })
+				;
+	var p3 = g1.createPath()
+				.setStroke({ color: "blue", width: 2 })
+				.moveTo( 300, 100 )
+				.setAbsoluteMode(false)
+				.lineTo (  100,  100 )
+				.lineTo (    0,  100 )
+				.lineTo ( -100,  100 )
+				.curveTo(  100, -100, 100, -200, 0, -300 )
+				//.setTransform(dojox.gfx.matrix.rotategAt(135, 250, 250))
+				.setTransform(dojox.gfx.matrix.rotategAt(180, 250, 250))
+				;
+	//g1.setTransform({ dx: 100 });
+	g1.moveToFront();
+	g1.setTransform(dojox.gfx.matrix.rotategAt(-15, 250, 250));
+	//g1.setTransform([dojox.gfx.matrix.rotategAt(-45, 250, 250), dojox.gfx.matrix.scaleAt(0.5, 250, 250)]);
+	//g1.setTransform([dojox.gfx.matrix.scaleAt(2, 1, 250, 250), dojox.gfx.matrix.rotategAt(-45, 250, 250)]);
+	var a = p1.getTransformedBoundingBox();
+	a.push(a[0]);
+	surface.createPolyline(a).setStroke("green");
+	a = p2.getTransformedBoundingBox();
+	a.push(a[0]);
+	surface.createPolyline(a).setStroke("green");
+	a = p3.getTransformedBoundingBox();
+	a.push(a[0]);
+	surface.createPolyline(a).setStroke("green");
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+<!--
+<style>
+v:group { text-align: left; }
+</style>
+-->
+</head>
+<body>
+	<h1>dojox.gfx Transformation test</h1>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_text.html b/dojox/gfx/tests/test_text.html
new file mode 100644
index 0000000..ea5b9c7
--- /dev/null
+++ b/dojox/gfx/tests/test_text.html
@@ -0,0 +1,79 @@
+<html>
+<head>
+<title>Testing text</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--
+<script type="text/javascript" src="../common.js"></script>
+<script type="text/javascript" src="../shape.js"></script>
+-->
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var ROTATION = 30;
+
+var surface = null, t1, t2, t3, t4, t5;
+
+var placeAnchor = function(surface, x, y){
+	surface.createLine({x1: x - 2, y1: y, x2: x + 2, y2: y}).setStroke("blue");
+	surface.createLine({x1: x, y1: y - 2, x2: x, y2: y + 2}).setStroke("blue");
+};
+
+var makeText = function(surface, text, font, fill, stroke){
+	var t = surface.createText(text);
+	if(font)   t.setFont(font);
+	if(fill)   t.setFill(fill);
+	if(stroke) t.setStroke(stroke);
+	placeAnchor(surface, text.x, text.y);
+	return t;
+};
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface("test", 500, 500);
+	var m = dojox.gfx.matrix;
+	surface.createLine({x1: 250, y1: 0, x2: 250, y2: 500}).setStroke("green");
+	t1 = makeText(surface, {x: 250, y: 50, text: "Start", align: "start"}, 
+		{family: "Times", size: "36pt", weight: "bold"}, "black", "red")
+		.setTransform(m.rotategAt(ROTATION, 250, 50));
+	t2 = makeText(surface, {x: 250, y: 100, text: "Middle", align: "middle"}, 
+		{family: "Symbol", size: "24pt"}, "red", "black")
+		.setTransform(m.rotategAt(ROTATION, 250, 100));
+	t3 = makeText(surface, {x: 250, y: 150, text: "End", align: "end"}, 
+		{family: "Helvetica", style: "italic", size: "18pt", rotated: true}, "#FF8000")
+		.setTransform(m.rotategAt(ROTATION, 250, 150));
+	t4 = makeText(surface, {x: 250, y: 200, text: "Define Shuffle Tiff", align: "middle", kerning: true}, 
+		{family: "serif", size: "36pt"}, "black")
+		.setTransform(m.rotategAt(0, 250, 200));
+	t5 = makeText(surface, {x: 250, y: 250, text: "Define Shuffle Tiff", align: "middle", kerning: false}, 
+		{family: "serif", size: "36pt"}, "black")
+		.setTransform(m.rotategAt(0, 250, 250));
+};
+
+getSizes = function(){
+	var t = [];
+	dojo.forEach(["t1", "t2", "t3", "t4", "t5"], function(name){
+		var node = eval("(" + name + ")");
+		t.push(node.getShape().text + " = " + node.getTextWidth());
+	});
+	dojo.byId("sizes").innerHTML = t.join("<br/>");
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+	<h1>dojox.gfx Text test</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<div><button onclick="surface.clear();">Clear</button> <button onclick="getSizes();">Get sizes</button></div>
+<p id="sizes"> </p>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_textpath.html b/dojox/gfx/tests/test_textpath.html
new file mode 100644
index 0000000..201b0b5
--- /dev/null
+++ b/dojox/gfx/tests/test_textpath.html
@@ -0,0 +1,76 @@
+<html>
+<head>
+<title>Testing textpath</title>
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--
+<script type="text/javascript" src="../common.js"></script>
+<script type="text/javascript" src="../shape.js"></script>
+<script type="text/javascript" src="../path.js"></script>
+-->
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+var CPD = 30;
+
+var surface = null;
+
+var makeText = function(surface, text, font, fill, stroke){
+	var t = surface.createText(text);
+	if(font)   t.setFont(font);
+	if(fill)   t.setFill(fill);
+	if(stroke) t.setStroke(stroke);
+	placeAnchor(surface, text.x, text.y);
+	return t;
+};
+
+makeShapes = function(){
+	surface = dojox.gfx.createSurface("test", 500, 500);
+	var p = surface.createPath({})
+		.setStroke("green")
+		.moveTo(0, 100)
+		.setAbsoluteMode(false)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		.curveTo(CPD, 0, 100 - CPD, -300, 100, -300)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		.curveTo(CPD, 0, 100 - CPD, -300, 100, -300)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		;
+	console.debug(p);
+	var t = surface.createTextPath({
+			text: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Praesent erat. " + 
+					"In malesuada ultricies velit. Vestibulum tempor odio vitae diam. " + 
+					"Morbi arcu lectus, laoreet eget, nonummy at, elementum a, quam."
+			, align: "middle"
+			//, rotated: true
+		})
+		//.setShape(p.shape)
+		.moveTo(0, 100)
+		.setAbsoluteMode(false)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		.curveTo(CPD, 0, 100 - CPD, -300, 100, -300)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		.curveTo(CPD, 0, 100 - CPD, -300, 100, -300)
+		.curveTo(CPD, 0, 100 - CPD,  300, 100,  300)
+		.setFont({family: "times", size: "12pt"})
+		.setFill("blue")
+		;
+	console.debug(t);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+	<h1>dojox.gfx Text on a Path test</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_transform.html b/dojox/gfx/tests/test_transform.html
new file mode 100644
index 0000000..00820be
--- /dev/null
+++ b/dojox/gfx/tests/test_transform.html
@@ -0,0 +1,94 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo Unified 2D Graphics</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<!--<script type="text/javascript" src="../vml.js"></script>-->
+<!--<script type="text/javascript" src="../svg.js"></script>-->
+<!--<script type="text/javascript" src="../silverlight.js"></script>-->
+<script type="text/javascript">
+dojo.require("dojox.gfx");
+
+makeShapes = function(){
+	var surface = dojox.gfx.createSurface(document.getElementById("test"), 500, 500);
+	var g1 = surface.createGroup();
+	// make a checkerboard
+	for(var i = 0; i < 500; i += 100){
+		for(var j = 0; j < 500; j += 100){
+			if(i % 200 == j % 200) {
+				surface.createRect({x: i, y: j}).setFill([255, 0, 0, 0.1]);
+			}
+		}
+	}
+	var r1 = g1.createShape({type: "rect", x: 200, y: 200})
+				.setFill("green")
+				.setStroke({})
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 250, 250))
+				;
+	var r2 = surface.createShape({type: "rect"}).setStroke({})
+				.setFill({type: "linear", to: {x: 50, y: 100},
+					colors: [{offset: 0, color: "green"}, {offset: 0.5, color: "red"}, {offset: 1, color: "blue"}] })
+				.setTransform({dx: 100, dy: 100})
+				;
+	var r3 = surface.createRect().setStroke({})
+				.setFill({ type: "linear" })
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 250, 250))
+				;
+	var r4 = g1.createShape({type: "rect"})
+				.setFill("blue")
+				//.setStroke({})
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 350, 250))
+				.setTransform([dojox.gfx.matrix.rotategAt(-30, 350, 250), { dx: 300, dy: 200 }])
+				;
+	var p1 = g1.createShape({type: "path"})
+				.setStroke({})
+				.moveTo(300, 100)
+				.lineTo(400, 200)
+				.lineTo(400, 300)
+				.lineTo(300, 400)
+				.curveTo(400, 300, 400, 200, 300, 100)
+				//.setTransform(dojox.gfx.matrix.rotategAt(-45, 250, 250))
+				.setTransform({})
+				;
+	var p2 = g1.createShape(p1.getShape())
+				.setStroke({color: "red", width: 2})
+				//.moveTo( 300, 100 )
+				//.lineTo( 400, 200 )
+				//.lineTo( 400, 300 )
+				//.lineTo( 300, 400 )
+				//.curveTo( 400, 300, 400, 200, 300, 100 )
+				//.setTransform(dojox.gfx.matrix.rotategAt(180, 250, 250))
+				.setTransform({dx: 100})
+				;
+	var p3 = g1.createShape({type: "path"})
+				.setStroke({color: "blue", width: 2})
+				.moveTo(300, 100)
+				.setAbsoluteMode(false)
+				.lineTo ( 100,  100)
+				.lineTo (   0,  100)
+				.lineTo (-100,  100)
+				.curveTo( 100, -100, 100, -200, 0, -300)
+				//.setTransform(dojox.gfx.matrix.rotategAt(135, 250, 250))
+				.setTransform(dojox.gfx.matrix.rotategAt(180, 250, 250))
+				;
+	//g1.setTransform({dx: 100});
+	g1.moveToFront();
+	g1.setTransform(dojox.gfx.matrix.rotategAt(-15, 250, 250));
+	//g1.setTransform([dojox.gfx.matrix.rotategAt(-45, 250, 250), dojox.gfx.matrix.scaleAt(0.5, 250, 250)]);
+	//g1.setTransform([dojox.gfx.matrix.scaleAt(2, 1, 250, 250), dojox.gfx.matrix.rotategAt(-45, 250, 250)]);
+};
+
+dojo.addOnLoad(makeShapes);
+
+</script>
+</head>
+<body>
+<h1>dojox.gfx Transform test</h1>
+<div id="test"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx/tests/test_utils.html b/dojox/gfx/tests/test_utils.html
new file mode 100755
index 0000000..008a495
--- /dev/null
+++ b/dojox/gfx/tests/test_utils.html
@@ -0,0 +1,198 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>GFX Test: Test the basic utils functions</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript" src="../../../util/doh/runner.js"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.require("dojox.gfx");
+			dojo.require("dojox.gfx.utils");
+		</script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				var drawing;
+				var ta;
+				doh.register("GFX: Utils Tests", [
+					{
+						name: "toJson",
+						timeout: 1000,
+						setUp: function(){
+							if(!drawing){
+								var dn = dojo.byId("gfxObject");
+								drawing = dojox.gfx.createSurface(dn, 300, 300);
+								drawing.createRect({ 
+									 width:  100,
+									 height: 100,
+									 x: 100,
+									 y: 100
+								}).setFill("blue").setStroke("black");
+							}
+							if(!ta){
+								ta = dojo.byId("outputArea");
+							}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								var json = dojox.gfx.utils.toJson(drawing);
+								doh.assertTrue(json != null, "Checking that non-null was returned.");
+								ta.value = json;
+								var obj = dojo.fromJson(json);
+								doh.assertTrue(1, obj.length, "Checking that the json is an array of one entry.");
+								doh.assertTrue(obj[0].shape != null, "Checking that a toplevel shape object is present.");
+								doh.assertEqual("rect", obj[0].shape.type, "Checking that the shape type is rect.");
+								doh.assertEqual(100, obj[0].shape.width, "Checking that the width is 100.");
+								doh.assertEqual(100, obj[0].shape.height, "Checking that the height is 100.");
+								d.callback(true);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						}
+					},
+					{
+						name: "fromJson",
+						timeout: 1000,
+						setUp: function(){
+							if(!drawing){
+								var dn = dojo.byId("gfxObject");
+								drawing = dojox.gfx.createSurface(dn, 300, 300);
+								drawing.createRect({ 
+									 width:  100,
+									 height: 100,
+									 x: 100,
+									 y: 100
+								}).setFill("blue").setStroke("black");
+							}
+							if(!ta){
+								ta = dojo.byId("outputArea");
+							}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								var json = dojox.gfx.utils.toJson(drawing);
+								doh.assertTrue(json != null, "Checking that non-null was returned.");
+								var targetNode = dojo.byId("scratchObject");
+								var tempSurface = dojox.gfx.createSurface(targetNode, 300, 300);
+								dojox.gfx.utils.fromJson(tempSurface, json);
+
+								var nsJson = dojox.gfx.utils.toJson(tempSurface);
+								tempSurface.destroy();
+
+								var obj = dojo.fromJson(nsJson);
+								doh.assertTrue(1, obj.length, "Checking that the json is an array of one entry.");
+								doh.assertTrue(obj[0].shape != null, "Checking that a toplevel shape object is present.");
+								doh.assertEqual("rect", obj[0].shape.type, "Checking that the shape type is rect.");
+								doh.assertEqual(100, obj[0].shape.width, "Checking that the width is 100.");
+								doh.assertEqual(100, obj[0].shape.height, "Checking that the height is 100.");
+								d.callback(true);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						}
+					},
+					{
+						name: "toSvg",
+						timeout: 10000,
+						setUp: function(){
+							if(!drawing){
+								var dn = dojo.byId("gfxObject");
+								drawing = dojox.gfx.createSurface(dn, 300, 300);
+								drawing.createRect({ 
+									 width:  100,
+									 height: 100,
+									 x: 100,
+									 y: 100
+								}).setFill("blue").setStroke("black");
+							}
+							if(!ta){
+								ta = dojo.byId("outputArea");
+							}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							var def= dojox.gfx.utils.toSvg(drawing);
+							def.addCallback(function(svg){
+								try{
+									doh.assertTrue(svg != null, "Checking that non-null was returned.");
+									ta.value = svg;
+									doh.assertTrue(svg.length > 0, "Checking that svg length > 0");
+									doh.assertTrue(svg.toLowerCase().indexOf("<svg") === 0, "Checking that the string starts with SVG open tag.");
+									d.callback(true);
+								}catch(e){
+									d.errback(e);
+								}
+							});
+							def.addErrback(function(e){
+								d.errback(e);
+							});
+							return d;
+						}
+					},
+					{
+						name: "serialize/deserialize",
+						timeout: 1000,
+						setUp: function(){
+							if(!drawing){
+								var dn = dojo.byId("gfxObject");
+								drawing = dojox.gfx.createSurface(dn, 300, 300);
+								drawing.createRect({ 
+									 width:  100,
+									 height: 100,
+									 x: 100,
+									 y: 100
+								}).setFill("blue").setStroke("black");
+							}
+							if(!ta){
+								ta = dojo.byId("outputArea");
+							}
+						},
+						runTest: function(){
+							var d = new doh.Deferred();
+							try{
+								var sObj = dojox.gfx.utils.serialize(drawing);
+								doh.assertTrue(sObj != null, "Checking that non-null was returned.");
+
+								//Lets try to deserialize it!
+								var targetNode = dojo.byId("scratchObject");
+								var tempSurface = dojox.gfx.createSurface(targetNode, 300, 300);
+								dojox.gfx.utils.deserialize(tempSurface, sObj);
+								var nsJson = dojox.gfx.utils.toJson(tempSurface);
+								tempSurface.destroy();
+
+								var obj = dojo.fromJson(nsJson);
+								doh.assertTrue(1, obj.length, "Checking that the json is an array of one entry.");
+								doh.assertTrue(obj[0].shape != null, "Checking that a toplevel shape object is present.");
+								doh.assertEqual("rect", obj[0].shape.type, "Checking that the shape type is rect.");
+								doh.assertEqual(100, obj[0].shape.width, "Checking that the width is 100.");
+								doh.assertEqual(100, obj[0].shape.height, "Checking that the height is 100.");
+								d.callback(true);
+							}catch(e){
+								d.errback(e);
+							}
+							return d;
+						}
+					}
+				]);
+				doh.run();
+			});
+			</script>
+	</head>
+	<body class="tundra">
+		<h1>Test of GFX Utils functions</h1>
+		This page is intended for testing of the functions of the utils package, such as toJson, fromJson, and toSvg.
+		<div id="gfxObject"></div>
+		<div id="scratchObject"></div>
+		<div>
+			<textarea style="width: 100%; height: 300px" id="outputArea"></textarea>
+		</div>
+	</body>
+</html>
diff --git a/dojox/gfx/tests/test_vectortext_draw.html b/dojox/gfx/tests/test_vectortext_draw.html
new file mode 100644
index 0000000..d71bb70
--- /dev/null
+++ b/dojox/gfx/tests/test_vectortext_draw.html
@@ -0,0 +1,57 @@
+<html>
+	<head>
+		<title>DojoX GFX: Vector Text test: draw a font</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" 
+			djConfig="isDebug: true, gfxRenderer: 'svg,vml,silverlight,canvas'"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.gfx");
+			dojo.require("dojox.gfx.fx");
+			dojo.require("dojox.gfx.VectorText");
+
+			var bg="#181818", fill="#a36e2c";
+			dojo.addOnLoad(function(){
+				var url = dojo.moduleUrl("dojox", "gfx/resources/Gillius.svg");
+				var f = new dojox.gfx.VectorFont(url);
+
+				//	draw out the glyphs for testing.
+				var surface = dojox.gfx.createSurface("test", 600, 400);
+				var rect = surface.createRect({ x: 0, y: 0, width: 600, height: 400 })
+					.setFill(bg);
+
+				//	draw it up.
+				var txtArgs = {
+					text: "Now is the time for all good men to come to a rest.  Plus, the rain in Spain falls mainly on the plain!",
+					x: 0, y: 0,
+					width: 560, height: 360,
+					align: "start", fitting: dojox.gfx.vectorFontFitting.FIT,
+					leading: 1.2
+				};
+				var fontArgs = {
+					size: "12pt", family: "Gillius"
+				};
+
+				var master = surface.createGroup();	
+				var g = f.draw(master, txtArgs, fontArgs, fill);
+
+				dojox.gfx.fx.animateTransform({
+					shape: master,
+					duration: 1000,
+					transform: [ 
+						{name: "rotategAt", start: [0, 250, 250], end: [360, 350, 350]},
+						{ name: "scale", start: [0.1, 0.1], end:[1, 1 ] } 
+					]
+				}).play();
+			});
+		</script>
+	</head>
+	<body>
+		<h1>dojox.gfx Vector Text test: drawing a font</h1>
+		<p>This is a test of the new VectorText functionality; we draw a font using flow or fit.</p>
+		<div id="test" style="width: 500px; height: 560px;"></div>
+	</body>
+</html>
diff --git a/dojox/gfx/tests/test_vectortext_load.html b/dojox/gfx/tests/test_vectortext_load.html
new file mode 100644
index 0000000..c8f03ab
--- /dev/null
+++ b/dojox/gfx/tests/test_vectortext_load.html
@@ -0,0 +1,79 @@
+<html>
+	<head>
+		<title>DojoX GFX: Vector Text test: load and display a font</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" 
+			djConfig="isDebug: false"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.gfx");
+			dojo.require("dojox.gfx.VectorText");
+
+			var bg="#181818", fill="#464b44", padding=32;
+			dojo.addOnLoad(function(){
+				var url = dojo.moduleUrl("dojox", "gfx/resources/Gillius.svg");
+				var f = new dojox.gfx.VectorFont(url);
+
+				//	draw out the glyphs for testing.
+				var surface = dojox.gfx.createSurface("test", 500, 560);
+				var rect = surface.createRect({ x: 0, y: 0, width: 500, height: 560 })
+					.setFill(bg);
+				var g = surface.createGroup(), cx=0, count=0;
+				for(var gl in f.glyphs){
+					var glyph = f.glyphs[gl];
+					var t = g.createGroup();
+					if(glyph.path){
+						var p = t.createPath(glyph.path).setFill(fill);
+					}
+					t.setTransform([
+						dojox.gfx.matrix.flipY,
+						dojox.gfx.matrix.translate(cx, -f.viewbox.height-f.descent)
+					]);
+					cx += glyph.xAdvance, count++;
+					g.createLine({ 
+						x1: cx, x2: cx, y1: 0, y2: f.viewbox.height 
+					}).setStroke({color:"#409953", style:"Dash", width:1 });
+				}
+				cx -= glyph.xAdvance;
+				var factor = (500/f.viewbox.height)/2;
+				g.setTransform(dojox.gfx.matrix.scale(factor));
+				surface.setDimensions(cx*factor, (f.viewbox.height*factor)+padding*2);
+				rect.setShape({ x:0, y:0, width:cx*factor, height: (f.viewbox.height*factor)+padding*2 });
+				dojo.byId("test").style.height = Math.round(f.viewbox.height*factor)+padding*2+"px";
+				
+				//	try to find the baseline
+				surface.createLine({ x1: 0, x2: cx*factor, 
+						y1: factor*(f.viewbox.height+f.descent), y2:factor*(f.viewbox.height+f.descent) 
+				}).setStroke({ color: "#a36e2c" });
+
+				//	lets do some measuring lines.
+				var s = "#70657e", axis = surface.createGroup();
+				//	measurement axis
+				axis.createLine({ x1: 0, x2: cx*factor, y1: factor*f.viewbox.height+padding*2-1, y2: factor*f.viewbox.height+padding*2-1 })
+					.setStroke(s);
+
+				var major=50, minor=10, yMajor=20, yMinor=10, tick=5, steps=Math.floor(cx/minor);
+				for(var i=0; i<steps; i++){
+					//	ticks
+					var xpos = i*minor, y2 = padding*2+factor*f.viewbox.height, y1 = (xpos%major==0)?y2-yMajor:y2-yMinor;
+					axis.createLine({ x1: xpos, x2: xpos, y1: y1, y2: y2 }).setStroke(s);
+					if(xpos%major==0){
+						axis.createText({ x: xpos, y: y1-4, text: xpos.toString(), align: "middle" })
+							.setFont({ family: "sans-serif", size:"8pt"})
+							.setFill(s);
+					}
+				}
+
+
+			});
+		</script>
+	</head>
+	<body>
+		<h1>dojox.gfx Vector Text test: loading a font</h1>
+		<p>This is a test of the new VectorText functionality; we load up an SVG Font definition and use it to render text (as opposed to tapping into a browser's native text capability).</p>
+		<div id="test" style="width: 500px; height: 560px;"></div>
+	</body>
+</html>
diff --git a/dojox/gfx/utils.js b/dojox/gfx/utils.js
index 8404144..f5c5fb3 100644
--- a/dojox/gfx/utils.js
+++ b/dojox/gfx/utils.js
@@ -1,198 +1,277 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.utils"]){
-dojo._hasResource["dojox.gfx.utils"]=true;
 dojo.provide("dojox.gfx.utils");
+
 dojo.require("dojox.gfx");
+
 (function(){
-var d=dojo,g=dojox.gfx,gu=g.utils;
-dojo.mixin(gu,{forEach:function(_1,f,o){
-o=o||d.global;
-f.call(o,_1);
-if(_1 instanceof g.Surface||_1 instanceof g.Group){
-d.forEach(_1.children,function(_2){
-gu.forEach(_2,f,o);
-});
-}
-},serialize:function(_3){
-var t={},v,_4=_3 instanceof g.Surface;
-if(_4||_3 instanceof g.Group){
-t.children=d.map(_3.children,gu.serialize);
-if(_4){
-return t.children;
-}
-}else{
-t.shape=_3.getShape();
-}
-if(_3.getTransform){
-v=_3.getTransform();
-if(v){
-t.transform=v;
-}
-}
-if(_3.getStroke){
-v=_3.getStroke();
-if(v){
-t.stroke=v;
-}
-}
-if(_3.getFill){
-v=_3.getFill();
-if(v){
-t.fill=v;
-}
-}
-if(_3.getFont){
-v=_3.getFont();
-if(v){
-t.font=v;
-}
-}
-return t;
-},toJson:function(_5,_6){
-return d.toJson(gu.serialize(_5),_6);
-},deserialize:function(_7,_8){
-if(_8 instanceof Array){
-return d.map(_8,d.hitch(null,gu.deserialize,_7));
-}
-var _9=("shape" in _8)?_7.createShape(_8.shape):_7.createGroup();
-if("transform" in _8){
-_9.setTransform(_8.transform);
-}
-if("stroke" in _8){
-_9.setStroke(_8.stroke);
-}
-if("fill" in _8){
-_9.setFill(_8.fill);
-}
-if("font" in _8){
-_9.setFont(_8.font);
-}
-if("children" in _8){
-d.forEach(_8.children,d.hitch(null,gu.deserialize,_9));
-}
-return _9;
-},fromJson:function(_a,_b){
-return gu.deserialize(_a,d.fromJson(_b));
-},toSvg:function(_c){
-var _d=new dojo.Deferred();
-if(dojox.gfx.renderer==="svg"){
-try{
-var _e=gu._cleanSvg(gu._innerXML(_c.rawNode));
-_d.callback(_e);
-}
-catch(e){
-_d.errback(e);
-}
-}else{
-if(!gu._initSvgSerializerDeferred){
-gu._initSvgSerializer();
-}
-var _f=dojox.gfx.utils.toJson(_c);
-var _10=function(){
-try{
-var _11=_c.getDimensions();
-var _12=_11.width;
-var _13=_11.height;
-var _14=gu._gfxSvgProxy.document.createElement("div");
-gu._gfxSvgProxy.document.body.appendChild(_14);
-dojo.withDoc(gu._gfxSvgProxy.document,function(){
-dojo.style(_14,"width",_12);
-dojo.style(_14,"height",_13);
-},this);
-var ts=gu._gfxSvgProxy[dojox._scopeName].gfx.createSurface(_14,_12,_13);
-var _15=function(_16){
-try{
-gu._gfxSvgProxy[dojox._scopeName].gfx.utils.fromJson(_16,_f);
-var svg=gu._cleanSvg(_14.innerHTML);
-_16.clear();
-_16.destroy();
-gu._gfxSvgProxy.document.body.removeChild(_14);
-_d.callback(svg);
-}
-catch(e){
-_d.errback(e);
-}
-};
-ts.whenLoaded(null,_15);
-}
-catch(ex){
-_d.errback(ex);
-}
-};
-if(gu._initSvgSerializerDeferred.fired>0){
-_10();
-}else{
-gu._initSvgSerializerDeferred.addCallback(_10);
-}
-}
-return _d;
-},_gfxSvgProxy:null,_initSvgSerializerDeferred:null,_svgSerializerInitialized:function(){
-gu._initSvgSerializerDeferred.callback(true);
-},_initSvgSerializer:function(){
-if(!gu._initSvgSerializerDeferred){
-gu._initSvgSerializerDeferred=new dojo.Deferred();
-var f=dojo.doc.createElement("iframe");
-dojo.style(f,{display:"none",position:"absolute",width:"1em",height:"1em",top:"-10000px"});
-var _17;
-if(dojo.isIE){
-f.onreadystatechange=function(){
-if(f.contentWindow.document.readyState=="complete"){
-f.onreadystatechange=function(){
-};
-_17=setInterval(function(){
-if(f.contentWindow[dojo._scopeName]&&f.contentWindow[dojox._scopeName].gfx&&f.contentWindow[dojox._scopeName].gfx.utils){
-clearInterval(_17);
-f.contentWindow.parent[dojox._scopeName].gfx.utils._gfxSvgProxy=f.contentWindow;
-f.contentWindow.parent[dojox._scopeName].gfx.utils._svgSerializerInitialized();
-}
-},50);
-}
-};
-}else{
-f.onload=function(){
-f.onload=function(){
-};
-_17=setInterval(function(){
-if(f.contentWindow[dojo._scopeName]&&f.contentWindow[dojox._scopeName].gfx&&f.contentWindow[dojox._scopeName].gfx.utils){
-clearInterval(_17);
-f.contentWindow.parent[dojox._scopeName].gfx.utils._gfxSvgProxy=f.contentWindow;
-f.contentWindow.parent[dojox._scopeName].gfx.utils._svgSerializerInitialized();
-}
-},50);
-};
-}
-var uri=(dojo.config["dojoxGfxSvgProxyFrameUrl"]||dojo.moduleUrl("dojox","gfx/resources/gfxSvgProxyFrame.html"));
-f.setAttribute("src",uri);
-dojo.body().appendChild(f);
-}
-},_innerXML:function(_18){
-if(_18.innerXML){
-return _18.innerXML;
-}else{
-if(_18.xml){
-return _18.xml;
-}else{
-if(typeof XMLSerializer!="undefined"){
-return (new XMLSerializer()).serializeToString(_18);
-}
-}
-}
-return null;
-},_cleanSvg:function(svg){
-if(svg){
-if(svg.indexOf("xmlns=\"http://www.w3.org/2000/svg\"")==-1){
-svg=svg.substring(4,svg.length);
-svg="<svg xmlns=\"http://www.w3.org/2000/svg\""+svg;
-}
-svg=svg.replace(/\bdojoGfx\w*\s*=\s*(['"])\w*\1/g,"");
-}
-return svg;
-}});
+	var d = dojo, g = dojox.gfx, gu = g.utils;
+
+	dojo.mixin(gu, {
+		forEach: function(
+			/* dojox.gfx.Surface || dojox.gfx.Shape */ object,
+			/*Function|String|Array*/ f, /*Object?*/ o
+		){
+			o = o || d.global;
+			f.call(o, object);
+			if(object instanceof g.Surface || object instanceof g.Group){
+				d.forEach(object.children, function(shape){
+					gu.forEach(shape, f, o);
+				});
+			}
+		},
+
+		serialize: function(
+			/* dojox.gfx.Surface || dojox.gfx.Shape */ object
+		){
+			var t = {}, v, isSurface = object instanceof g.Surface;
+			if(isSurface || object instanceof g.Group){
+				t.children = d.map(object.children, gu.serialize);
+				if(isSurface){
+					return t.children;	// Array
+				}
+			}else{
+				t.shape = object.getShape();
+			}
+			if(object.getTransform){
+				v = object.getTransform();
+				if(v){ t.transform = v; }
+			}
+			if(object.getStroke){
+				v = object.getStroke();
+				if(v){ t.stroke = v; }
+			}
+			if(object.getFill){
+				v = object.getFill();
+				if(v){ t.fill = v; }
+			}
+			if(object.getFont){
+				v = object.getFont();
+				if(v){ t.font = v; }
+			}
+			return t;	// Object
+		},
+
+		toJson: function(
+			/* dojox.gfx.Surface || dojox.gfx.Shape */ object,
+			/* Boolean? */ prettyPrint
+		){
+			return d.toJson(gu.serialize(object), prettyPrint);	// String
+		},
+
+		deserialize: function(
+			/* dojox.gfx.Surface || dojox.gfx.Shape */ parent,
+			/* dojox.gfx.Shape || Array */ object
+		){
+			if(object instanceof Array){
+				return d.map(object, d.hitch(null, gu.deserialize, parent));	// Array
+			}
+			var shape = ("shape" in object) ? parent.createShape(object.shape) : parent.createGroup();
+			if("transform" in object){
+				shape.setTransform(object.transform);
+			}
+			if("stroke" in object){
+				shape.setStroke(object.stroke);
+			}
+			if("fill" in object){
+				shape.setFill(object.fill);
+			}
+			if("font" in object){
+				shape.setFont(object.font);
+			}
+			if("children" in object){
+				d.forEach(object.children, d.hitch(null, gu.deserialize, shape));
+			}
+			return shape;	// dojox.gfx.Shape
+		},
+
+		fromJson: function(
+			/* dojox.gfx.Surface || dojox.gfx.Shape */ parent,
+			/* String */ json){
+			return gu.deserialize(parent, d.fromJson(json));	// Array || dojox.gfx.Shape
+		},
+
+		toSvg: function(/*GFX object*/surface){
+			// summary:
+			//		Function to serialize a GFX surface to SVG text.  
+			// description:
+			//		Function to serialize a GFX surface to SVG text.  The value of this output
+			//		is that there are numerous serverside parser libraries that can render
+			//		SVG into images in various formats.  This provides a way that GFX objects
+			//		can be captured in a known format and sent serverside for serialization
+			//		into an image.
+			// surface:
+			//		The GFX surface to serialize.
+			// returns:
+			//		Deferred object that will be called when SVG serialization is complete.
+		
+			//Since the init and even surface creation can be async, we need to
+			//return a deferred that will be called when content has serialized.
+			var deferred = new dojo.Deferred();
+		
+			if(dojox.gfx.renderer === "svg"){
+				//If we're already in SVG mode, this is easy and quick.
+				try{
+					var svg = gu._cleanSvg(gu._innerXML(surface.rawNode));
+					deferred.callback(svg);
+				}catch(e){
+					deferred.errback(e);
+				}
+			}else{
+				//Okay, now we have to get creative with hidden iframes and the like to
+				//serialize SVG.
+				if (!gu._initSvgSerializerDeferred) {
+					gu._initSvgSerializer();
+				}
+				var jsonForm = dojox.gfx.utils.toJson(surface);
+				var serializer = function(){
+					try{
+						var sDim = surface.getDimensions();
+						var width = sDim.width;
+						var	height = sDim.height;
+
+						//Create an attach point in the iframe for the contents.
+						var node = gu._gfxSvgProxy.document.createElement("div");
+						gu._gfxSvgProxy.document.body.appendChild(node);
+						//Set the node scaling.
+						dojo.withDoc(gu._gfxSvgProxy.document, function() {
+							dojo.style(node, "width", width);
+							dojo.style(node, "height", height);
+						}, this);
+
+						//Create temp surface to render object to and render.
+						var ts = gu._gfxSvgProxy[dojox._scopeName].gfx.createSurface(node, width, height);
+
+						//It's apparently possible that a suface creation is async, so we need to use 
+						//the whenLoaded function.  Probably not needed for SVG, but making it common
+						var draw = function(surface) {
+							try{
+								gu._gfxSvgProxy[dojox._scopeName].gfx.utils.fromJson(surface, jsonForm);
+
+								//Get contents and remove temp surface.
+								var svg = gu._cleanSvg(node.innerHTML);
+								surface.clear();
+								surface.destroy();
+								gu._gfxSvgProxy.document.body.removeChild(node);
+								deferred.callback(svg);
+							}catch(e){
+								deferred.errback(e);
+							}
+						};
+						ts.whenLoaded(null,draw);
+					 }catch (ex) {
+						deferred.errback(ex);
+					}
+				};
+				//See if we can call it directly or pass it to the deferred to be
+				//called on initialization.
+				if(gu._initSvgSerializerDeferred.fired > 0){
+					serializer();
+				}else{
+					gu._initSvgSerializerDeferred.addCallback(serializer);		
+				}
+			}
+			return deferred; //dojo.Deferred that will be called when serialization finishes.
+		},
+
+		//iFrame document used for handling SVG serialization.
+		_gfxSvgProxy: null,
+
+		//Serializer loaded.
+		_initSvgSerializerDeferred: null,
+
+		_svgSerializerInitialized: function() {
+			// summary:
+			//		Internal function to call when the serializer init completed.	
+			// tags:
+			//		private
+			gu._initSvgSerializerDeferred.callback(true);
+		},
+
+		_initSvgSerializer: function(){
+			// summary:
+			//		Internal function to initialize the hidden iframe where SVG rendering
+			//		will occur.
+			// tags:
+			//		private
+			if(!gu._initSvgSerializerDeferred){
+				gu._initSvgSerializerDeferred = new dojo.Deferred();
+				var f = dojo.doc.createElement("iframe");
+				dojo.style(f, {
+					display: "none",
+					position: "absolute",
+					width: "1em",
+					height: "1em",
+					top: "-10000px"
+				});
+				var intv;
+				if(dojo.isIE){
+					f.onreadystatechange = function(){
+						if(f.contentWindow.document.readyState == "complete"){
+							f.onreadystatechange = function() {};
+							intv = setInterval(function() {
+								if(f.contentWindow[dojo._scopeName] && 
+								   f.contentWindow[dojox._scopeName].gfx &&
+								   f.contentWindow[dojox._scopeName].gfx.utils){
+									clearInterval(intv);
+									f.contentWindow.parent[dojox._scopeName].gfx.utils._gfxSvgProxy = f.contentWindow;
+									f.contentWindow.parent[dojox._scopeName].gfx.utils._svgSerializerInitialized();
+								}
+							}, 50);
+						}
+					};
+				}else{
+					f.onload = function(){
+						f.onload = function() {};
+						intv = setInterval(function() {
+							if(f.contentWindow[dojo._scopeName] && 
+							   f.contentWindow[dojox._scopeName].gfx &&
+							   f.contentWindow[dojox._scopeName].gfx.utils){
+								clearInterval(intv);
+								f.contentWindow.parent[dojox._scopeName].gfx.utils._gfxSvgProxy = f.contentWindow;
+								f.contentWindow.parent[dojox._scopeName].gfx.utils._svgSerializerInitialized();
+							}
+						}, 50);
+					};
+				}
+				//We have to load the GFX SVG proxy frame.  Default is to use the one packaged in dojox.
+				var uri = (dojo.config["dojoxGfxSvgProxyFrameUrl"]||dojo.moduleUrl("dojox", "gfx/resources/gfxSvgProxyFrame.html"));
+				f.setAttribute("src", uri);
+				dojo.body().appendChild(f);
+			}
+		},
+
+		_innerXML: function(/*Node*/node){
+			// summary:
+			//		Implementation of MS's innerXML function, borrowed from dojox.xml.parser.
+			// node:
+			//		The node from which to generate the XML text representation.
+			// tags:
+			//		private
+			if(node.innerXML){
+				return node.innerXML;	//String
+			}else if(node.xml){
+				return node.xml;		//String
+			}else if(typeof XMLSerializer != "undefined"){
+				return (new XMLSerializer()).serializeToString(node);	//String
+			}
+			return null;
+		},
+
+		_cleanSvg: function(svg) {
+			// summary:
+			//		Internal function that cleans up artifacts in extracted SVG content.
+			// tags:
+			//		private
+			if(svg){
+				//Make sure the namespace is set.
+				if(svg.indexOf("xmlns=\"http://www.w3.org/2000/svg\"") == -1){
+					svg = svg.substring(4, svg.length);
+					svg = "<svg xmlns=\"http://www.w3.org/2000/svg\"" + svg;
+				}
+				//Do some other cleanup, like stripping out the 
+				//dojoGfx attributes.
+				svg = svg.replace(/\bdojoGfx\w*\s*=\s*(['"])\w*\1/g, "");
+			}
+			return svg;  //Cleaned SVG text.
+		}
+	});
 })();
-}
diff --git a/dojox/gfx/vml.js b/dojox/gfx/vml.js
index 6b6698d..e3537fa 100644
--- a/dojox/gfx/vml.js
+++ b/dojox/gfx/vml.js
@@ -1,893 +1,1187 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx.vml"]){
-dojo._hasResource["dojox.gfx.vml"]=true;
 dojo.provide("dojox.gfx.vml");
+
 dojo.require("dojox.gfx._base");
 dojo.require("dojox.gfx.shape");
 dojo.require("dojox.gfx.path");
 dojo.require("dojox.gfx.arc");
+dojo.require("dojox.gfx.gradient");
+
 (function(){
-var d=dojo,g=dojox.gfx,m=g.matrix,gs=g.shape,_1=g.vml;
-_1.xmlns="urn:schemas-microsoft-com:vml";
-_1.text_alignment={start:"left",middle:"center",end:"right"};
-_1._parseFloat=function(_2){
-return _2.match(/^\d+f$/i)?parseInt(_2)/65536:parseFloat(_2);
-};
-_1._bool={"t":1,"true":1};
-d.extend(g.Shape,{setFill:function(_3){
-if(!_3){
-this.fillStyle=null;
-this.rawNode.filled="f";
-return this;
-}
-var i,f,fo,a,s;
-if(typeof _3=="object"&&"type" in _3){
-switch(_3.type){
-case "linear":
-var _4=this._getRealMatrix();
-s=[];
-f=g.makeParameters(g.defaultLinearGradient,_3);
-a=f.colors;
-this.fillStyle=f;
-d.forEach(a,function(v,i,a){
-a[i].color=g.normalizeColor(v.color);
-});
-if(a[0].offset>0){
-s.push("0 "+a[0].color.toHex());
-}
-for(i=0;i<a.length;++i){
-s.push(a[i].offset.toFixed(8)+" "+a[i].color.toHex());
-}
-i=a.length-1;
-if(a[i].offset<1){
-s.push("1 "+a[i].color.toHex());
-}
-fo=this.rawNode.fill;
-fo.colors.value=s.join(";");
-fo.method="sigma";
-fo.type="gradient";
-var _5=_4?m.multiplyPoint(_4,f.x1,f.y1):{x:f.x1,y:f.y1},_6=_4?m.multiplyPoint(_4,f.x2,f.y2):{x:f.x2,y:f.y2};
-fo.angle=(m._radToDeg(Math.atan2(_6.x-_5.x,_6.y-_5.y))+180)%360;
-fo.on=true;
-break;
-case "radial":
-f=g.makeParameters(g.defaultRadialGradient,_3);
-this.fillStyle=f;
-var l=parseFloat(this.rawNode.style.left),t=parseFloat(this.rawNode.style.top),w=parseFloat(this.rawNode.style.width),h=parseFloat(this.rawNode.style.height),c=isNaN(w)?1:2*f.r/w;
-a=[];
-if(f.colors[0].offset>0){
-a.push({offset:1,color:g.normalizeColor(f.colors[0].color)});
-}
-d.forEach(f.colors,function(v,i){
-a.push({offset:1-v.offset*c,color:g.normalizeColor(v.color)});
-});
-i=a.length-1;
-while(i>=0&&a[i].offset<0){
---i;
-}
-if(i<a.length-1){
-var q=a[i],p=a[i+1];
-p.color=d.blendColors(q.color,p.color,q.offset/(q.offset-p.offset));
-p.offset=0;
-while(a.length-i>2){
-a.pop();
-}
-}
-i=a.length-1,s=[];
-if(a[i].offset>0){
-s.push("0 "+a[i].color.toHex());
-}
-for(;i>=0;--i){
-s.push(a[i].offset.toFixed(8)+" "+a[i].color.toHex());
-}
-fo=this.rawNode.fill;
-fo.colors.value=s.join(";");
-fo.method="sigma";
-fo.type="gradientradial";
-if(isNaN(w)||isNaN(h)||isNaN(l)||isNaN(t)){
-fo.focusposition="0.5 0.5";
-}else{
-fo.focusposition=((f.cx-l)/w).toFixed(8)+" "+((f.cy-t)/h).toFixed(8);
-}
-fo.focussize="0 0";
-fo.on=true;
-break;
-case "pattern":
-f=g.makeParameters(g.defaultPattern,_3);
-this.fillStyle=f;
-fo=this.rawNode.fill;
-fo.type="tile";
-fo.src=f.src;
-if(f.width&&f.height){
-fo.size.x=g.px2pt(f.width);
-fo.size.y=g.px2pt(f.height);
-}
-fo.alignShape="f";
-fo.position.x=0;
-fo.position.y=0;
-fo.origin.x=f.width?f.x/f.width:0;
-fo.origin.y=f.height?f.y/f.height:0;
-fo.on=true;
-break;
-}
-this.rawNode.fill.opacity=1;
-return this;
-}
-this.fillStyle=g.normalizeColor(_3);
-fo=this.rawNode.fill;
-if(!fo){
-fo=this.rawNode.ownerDocument.createElement("v:fill");
-}
-fo.method="any";
-fo.type="solid";
-fo.opacity=this.fillStyle.a;
-this.rawNode.fillcolor=this.fillStyle.toHex();
-this.rawNode.filled=true;
-return this;
-},setStroke:function(_7){
-if(!_7){
-this.strokeStyle=null;
-this.rawNode.stroked="f";
-return this;
-}
-if(typeof _7=="string"||d.isArray(_7)||_7 instanceof d.Color){
-_7={color:_7};
-}
-var s=this.strokeStyle=g.makeParameters(g.defaultStroke,_7);
-s.color=g.normalizeColor(s.color);
-var rn=this.rawNode;
-rn.stroked=true;
-rn.strokecolor=s.color.toCss();
-rn.strokeweight=s.width+"px";
-if(rn.stroke){
-rn.stroke.opacity=s.color.a;
-rn.stroke.endcap=this._translate(this._capMap,s.cap);
-if(typeof s.join=="number"){
-rn.stroke.joinstyle="miter";
-rn.stroke.miterlimit=s.join;
-}else{
-rn.stroke.joinstyle=s.join;
-}
-rn.stroke.dashstyle=s.style=="none"?"Solid":s.style;
-}
-return this;
-},_capMap:{butt:"flat"},_capMapReversed:{flat:"butt"},_translate:function(_8,_9){
-return (_9 in _8)?_8[_9]:_9;
-},_applyTransform:function(){
-if(this.fillStyle&&this.fillStyle.type=="linear"){
-this.setFill(this.fillStyle);
-}
-var _a=this._getRealMatrix();
-if(!_a){
-return this;
-}
-var _b=this.rawNode.skew;
-if(typeof _b=="undefined"){
-for(var i=0;i<this.rawNode.childNodes.length;++i){
-if(this.rawNode.childNodes[i].tagName=="skew"){
-_b=this.rawNode.childNodes[i];
-break;
-}
-}
-}
-if(_b){
-_b.on="f";
-var mt=_a.xx.toFixed(8)+" "+_a.xy.toFixed(8)+" "+_a.yx.toFixed(8)+" "+_a.yy.toFixed(8)+" 0 0",_c=Math.floor(_a.dx).toFixed()+"px "+Math.floor(_a.dy).toFixed()+"px",s=this.rawNode.style,l=parseFloat(s.left),t=parseFloat(s.top),w=parseFloat(s.width),h=parseFloat(s.height);
-if(isNaN(l)){
-l=0;
-}
-if(isNaN(t)){
-t=0;
-}
-if(isNaN(w)||!w){
-w=1;
-}
-if(isNaN(h)||!h){
-h=1;
-}
-var _d=(-l/w-0.5).toFixed(8)+" "+(-t/h-0.5).toFixed(8);
-_b.matrix=mt;
-_b.origin=_d;
-_b.offset=_c;
-_b.on=true;
-}
-return this;
-},_setDimensions:function(_e,_f){
-return this;
-},setRawNode:function(_10){
-_10.stroked="f";
-_10.filled="f";
-this.rawNode=_10;
-},_moveToFront:function(){
-this.rawNode.parentNode.appendChild(this.rawNode);
-return this;
-},_moveToBack:function(){
-var r=this.rawNode,p=r.parentNode,n=p.firstChild;
-p.insertBefore(r,n);
-if(n.tagName=="rect"){
-n.swapNode(r);
-}
-return this;
-},_getRealMatrix:function(){
-return this.parentMatrix?new g.Matrix2D([this.parentMatrix,this.matrix]):this.matrix;
-}});
-dojo.declare("dojox.gfx.Group",g.Shape,{constructor:function(){
-_1.Container._init.call(this);
-},_applyTransform:function(){
-var _11=this._getRealMatrix();
-for(var i=0;i<this.children.length;++i){
-this.children[i]._updateParentMatrix(_11);
-}
-return this;
-},_setDimensions:function(_12,_13){
-var r=this.rawNode,rs=r.style,bs=this.bgNode.style;
-rs.width=_12;
-rs.height=_13;
-r.coordsize=_12+" "+_13;
-bs.width=_12;
-bs.height=_13;
-for(var i=0;i<this.children.length;++i){
-this.children[i]._setDimensions(_12,_13);
-}
-return this;
-}});
-g.Group.nodeType="group";
-dojo.declare("dojox.gfx.Rect",gs.Rect,{setShape:function(_14){
-var _15=this.shape=g.makeParameters(this.shape,_14);
-this.bbox=null;
-var r=Math.min(1,(_15.r/Math.min(parseFloat(_15.width),parseFloat(_15.height)))).toFixed(8);
-var _16=this.rawNode.parentNode,_17=null;
-if(_16){
-if(_16.lastChild!==this.rawNode){
-for(var i=0;i<_16.childNodes.length;++i){
-if(_16.childNodes[i]===this.rawNode){
-_17=_16.childNodes[i+1];
-break;
-}
-}
-}
-_16.removeChild(this.rawNode);
-}
-if(d.isIE>7){
-var _18=this.rawNode.ownerDocument.createElement("v:roundrect");
-_18.arcsize=r;
-_18.style.display="inline-block";
-this.rawNode=_18;
-}else{
-this.rawNode.arcsize=r;
-}
-if(_16){
-if(_17){
-_16.insertBefore(this.rawNode,_17);
-}else{
-_16.appendChild(this.rawNode);
-}
-}
-var _19=this.rawNode.style;
-_19.left=_15.x.toFixed();
-_19.top=_15.y.toFixed();
-_19.width=(typeof _15.width=="string"&&_15.width.indexOf("%")>=0)?_15.width:_15.width.toFixed();
-_19.height=(typeof _15.width=="string"&&_15.height.indexOf("%")>=0)?_15.height:_15.height.toFixed();
-return this.setTransform(this.matrix).setFill(this.fillStyle).setStroke(this.strokeStyle);
-}});
-g.Rect.nodeType="roundrect";
-dojo.declare("dojox.gfx.Ellipse",gs.Ellipse,{setShape:function(_1a){
-var _1b=this.shape=g.makeParameters(this.shape,_1a);
-this.bbox=null;
-var _1c=this.rawNode.style;
-_1c.left=(_1b.cx-_1b.rx).toFixed();
-_1c.top=(_1b.cy-_1b.ry).toFixed();
-_1c.width=(_1b.rx*2).toFixed();
-_1c.height=(_1b.ry*2).toFixed();
-return this.setTransform(this.matrix);
-}});
-g.Ellipse.nodeType="oval";
-dojo.declare("dojox.gfx.Circle",gs.Circle,{setShape:function(_1d){
-var _1e=this.shape=g.makeParameters(this.shape,_1d);
-this.bbox=null;
-var _1f=this.rawNode.style;
-_1f.left=(_1e.cx-_1e.r).toFixed();
-_1f.top=(_1e.cy-_1e.r).toFixed();
-_1f.width=(_1e.r*2).toFixed();
-_1f.height=(_1e.r*2).toFixed();
-return this;
-}});
-g.Circle.nodeType="oval";
-dojo.declare("dojox.gfx.Line",gs.Line,{constructor:function(_20){
-if(_20){
-_20.setAttribute("dojoGfxType","line");
-}
-},setShape:function(_21){
-var _22=this.shape=g.makeParameters(this.shape,_21);
-this.bbox=null;
-this.rawNode.path.v="m"+_22.x1.toFixed()+" "+_22.y1.toFixed()+"l"+_22.x2.toFixed()+" "+_22.y2.toFixed()+"e";
-return this.setTransform(this.matrix);
-}});
-g.Line.nodeType="shape";
-dojo.declare("dojox.gfx.Polyline",gs.Polyline,{constructor:function(_23){
-if(_23){
-_23.setAttribute("dojoGfxType","polyline");
-}
-},setShape:function(_24,_25){
-if(_24&&_24 instanceof Array){
-this.shape=g.makeParameters(this.shape,{points:_24});
-if(_25&&this.shape.points.length){
-this.shape.points.push(this.shape.points[0]);
-}
-}else{
-this.shape=g.makeParameters(this.shape,_24);
-}
-this.bbox=null;
-this._normalizePoints();
-var _26=[],p=this.shape.points;
-if(p.length>0){
-_26.push("m");
-_26.push(p[0].x.toFixed(),p[0].y.toFixed());
-if(p.length>1){
-_26.push("l");
-for(var i=1;i<p.length;++i){
-_26.push(p[i].x.toFixed(),p[i].y.toFixed());
-}
-}
-}
-_26.push("e");
-this.rawNode.path.v=_26.join(" ");
-return this.setTransform(this.matrix);
-}});
-g.Polyline.nodeType="shape";
-dojo.declare("dojox.gfx.Image",gs.Image,{setShape:function(_27){
-var _28=this.shape=g.makeParameters(this.shape,_27);
-this.bbox=null;
-this.rawNode.firstChild.src=_28.src;
-return this.setTransform(this.matrix);
-},_applyTransform:function(){
-var _29=this._getRealMatrix(),_2a=this.rawNode,s=_2a.style,_2b=this.shape;
-if(_29){
-_29=m.multiply(_29,{dx:_2b.x,dy:_2b.y});
-}else{
-_29=m.normalize({dx:_2b.x,dy:_2b.y});
-}
-if(_29.xy==0&&_29.yx==0&&_29.xx>0&&_29.yy>0){
-s.filter="";
-s.width=Math.floor(_29.xx*_2b.width);
-s.height=Math.floor(_29.yy*_2b.height);
-s.left=Math.floor(_29.dx);
-s.top=Math.floor(_29.dy);
-}else{
-var ps=_2a.parentNode.style;
-s.left="0px";
-s.top="0px";
-s.width=ps.width;
-s.height=ps.height;
-_29=m.multiply(_29,{xx:_2b.width/parseInt(s.width),yy:_2b.height/parseInt(s.height)});
-var f=_2a.filters["DXImageTransform.Microsoft.Matrix"];
-if(f){
-f.M11=_29.xx;
-f.M12=_29.xy;
-f.M21=_29.yx;
-f.M22=_29.yy;
-f.Dx=_29.dx;
-f.Dy=_29.dy;
-}else{
-s.filter="progid:DXImageTransform.Microsoft.Matrix(M11="+_29.xx+", M12="+_29.xy+", M21="+_29.yx+", M22="+_29.yy+", Dx="+_29.dx+", Dy="+_29.dy+")";
-}
-}
-return this;
-},_setDimensions:function(_2c,_2d){
-var r=this.rawNode,f=r.filters["DXImageTransform.Microsoft.Matrix"];
-if(f){
-var s=r.style;
-s.width=_2c;
-s.height=_2d;
-return this._applyTransform();
-}
-return this;
-}});
-g.Image.nodeType="rect";
-dojo.declare("dojox.gfx.Text",gs.Text,{constructor:function(_2e){
-if(_2e){
-_2e.setAttribute("dojoGfxType","text");
-}
-this.fontStyle=null;
-},_alignment:{start:"left",middle:"center",end:"right"},setShape:function(_2f){
-this.shape=g.makeParameters(this.shape,_2f);
-this.bbox=null;
-var r=this.rawNode,s=this.shape,x=s.x,y=s.y.toFixed(),_30;
-switch(s.align){
-case "middle":
-x-=5;
-break;
-case "end":
-x-=10;
-break;
-}
-_30="m"+x.toFixed()+","+y+"l"+(x+10).toFixed()+","+y+"e";
-var p=null,t=null,c=r.childNodes;
-for(var i=0;i<c.length;++i){
-var tag=c[i].tagName;
-if(tag=="path"){
-p=c[i];
-if(t){
-break;
-}
-}else{
-if(tag=="textpath"){
-t=c[i];
-if(p){
-break;
-}
-}
-}
-}
-if(!p){
-p=r.ownerDocument.createElement("v:path");
-r.appendChild(p);
-}
-if(!t){
-t=r.ownerDocument.createElement("v:textpath");
-r.appendChild(t);
-}
-p.v=_30;
-p.textPathOk=true;
-t.on=true;
-var a=_1.text_alignment[s.align];
-t.style["v-text-align"]=a?a:"left";
-t.style["text-decoration"]=s.decoration;
-t.style["v-rotate-letters"]=s.rotated;
-t.style["v-text-kern"]=s.kerning;
-t.string=s.text;
-return this.setTransform(this.matrix);
-},_setFont:function(){
-var f=this.fontStyle,c=this.rawNode.childNodes;
-for(var i=0;i<c.length;++i){
-if(c[i].tagName=="textpath"){
-c[i].style.font=g.makeFontString(f);
-break;
-}
-}
-this.setTransform(this.matrix);
-},_getRealMatrix:function(){
-var _31=g.Shape.prototype._getRealMatrix.call(this);
-if(_31){
-_31=m.multiply(_31,{dy:-g.normalizedLength(this.fontStyle?this.fontStyle.size:"10pt")*0.35});
-}
-return _31;
-},getTextWidth:function(){
-var _32=this.rawNode,_33=_32.style.display;
-_32.style.display="inline";
-var _34=g.pt2px(parseFloat(_32.currentStyle.width));
-_32.style.display=_33;
-return _34;
-}});
-g.Text.nodeType="shape";
-g.path._calcArc=function(_35){
-var _36=Math.cos(_35),_37=Math.sin(_35),p2={x:_36+(4/3)*(1-_36),y:_37-(4/3)*_36*(1-_36)/_37};
-return {s:{x:_36,y:-_37},c1:{x:p2.x,y:-p2.y},c2:p2,e:{x:_36,y:_37}};
-};
-dojo.declare("dojox.gfx.Path",g.path.Path,{constructor:function(_38){
-if(_38&&!_38.getAttribute("dojoGfxType")){
-_38.setAttribute("dojoGfxType","path");
-}
-this.vmlPath="";
-this.lastControl={};
-},_updateWithSegment:function(_39){
-var _3a=d.clone(this.last);
-g.Path.superclass._updateWithSegment.apply(this,arguments);
-var _3b=this[this.renderers[_39.action]](_39,_3a);
-if(typeof this.vmlPath=="string"){
-this.vmlPath+=_3b.join("");
-this.rawNode.path.v=this.vmlPath+" r0,0 e";
-}else{
-Array.prototype.push.apply(this.vmlPath,_3b);
-}
-},setShape:function(_3c){
-this.vmlPath=[];
-this.lastControl.type="";
-g.Path.superclass.setShape.apply(this,arguments);
-this.vmlPath=this.vmlPath.join("");
-this.rawNode.path.v=this.vmlPath+" r0,0 e";
-return this;
-},_pathVmlToSvgMap:{m:"M",l:"L",t:"m",r:"l",c:"C",v:"c",qb:"Q",x:"z",e:""},renderers:{M:"_moveToA",m:"_moveToR",L:"_lineToA",l:"_lineToR",H:"_hLineToA",h:"_hLineToR",V:"_vLineToA",v:"_vLineToR",C:"_curveToA",c:"_curveToR",S:"_smoothCurveToA",s:"_smoothCurveToR",Q:"_qCurveToA",q:"_qCurveToR",T:"_qSmoothCurveToA",t:"_qSmoothCurveToR",A:"_arcTo",a:"_arcTo",Z:"_closePath",z:"_closePath"},_addArgs:function(_3d,_3e,_3f,_40){
-var n=_3e instanceof Array?_3e:_3e.args;
-for(var i=_3f;i<_40;++i){
-_3d.push(" ",n[i].toFixed());
-}
-},_adjustRelCrd:function(_41,_42,_43){
-var n=_42 instanceof Array?_42:_42.args,l=n.length,_44=new Array(l),i=0,x=_41.x,y=_41.y;
-if(typeof x!="number"){
-_44[0]=x=n[0];
-_44[1]=y=n[1];
-i=2;
-}
-if(typeof _43=="number"&&_43!=2){
-var j=_43;
-while(j<=l){
-for(;i<j;i+=2){
-_44[i]=x+n[i];
-_44[i+1]=y+n[i+1];
-}
-x=_44[j-2];
-y=_44[j-1];
-j+=_43;
-}
-}else{
-for(;i<l;i+=2){
-_44[i]=(x+=n[i]);
-_44[i+1]=(y+=n[i+1]);
-}
-}
-return _44;
-},_adjustRelPos:function(_45,_46){
-var n=_46 instanceof Array?_46:_46.args,l=n.length,_47=new Array(l);
-for(var i=0;i<l;++i){
-_47[i]=(_45+=n[i]);
-}
-return _47;
-},_moveToA:function(_48){
-var p=[" m"],n=_48 instanceof Array?_48:_48.args,l=n.length;
-this._addArgs(p,n,0,2);
-if(l>2){
-p.push(" l");
-this._addArgs(p,n,2,l);
-}
-this.lastControl.type="";
-return p;
-},_moveToR:function(_49,_4a){
-return this._moveToA(this._adjustRelCrd(_4a,_49));
-},_lineToA:function(_4b){
-var p=[" l"],n=_4b instanceof Array?_4b:_4b.args;
-this._addArgs(p,n,0,n.length);
-this.lastControl.type="";
-return p;
-},_lineToR:function(_4c,_4d){
-return this._lineToA(this._adjustRelCrd(_4d,_4c));
-},_hLineToA:function(_4e,_4f){
-var p=[" l"],y=" "+_4f.y.toFixed(),n=_4e instanceof Array?_4e:_4e.args,l=n.length;
-for(var i=0;i<l;++i){
-p.push(" ",n[i].toFixed(),y);
-}
-this.lastControl.type="";
-return p;
-},_hLineToR:function(_50,_51){
-return this._hLineToA(this._adjustRelPos(_51.x,_50),_51);
-},_vLineToA:function(_52,_53){
-var p=[" l"],x=" "+_53.x.toFixed(),n=_52 instanceof Array?_52:_52.args,l=n.length;
-for(var i=0;i<l;++i){
-p.push(x," ",n[i].toFixed());
-}
-this.lastControl.type="";
-return p;
-},_vLineToR:function(_54,_55){
-return this._vLineToA(this._adjustRelPos(_55.y,_54),_55);
-},_curveToA:function(_56){
-var p=[],n=_56 instanceof Array?_56:_56.args,l=n.length,lc=this.lastControl;
-for(var i=0;i<l;i+=6){
-p.push(" c");
-this._addArgs(p,n,i,i+6);
-}
-lc.x=n[l-4];
-lc.y=n[l-3];
-lc.type="C";
-return p;
-},_curveToR:function(_57,_58){
-return this._curveToA(this._adjustRelCrd(_58,_57,6));
-},_smoothCurveToA:function(_59,_5a){
-var p=[],n=_59 instanceof Array?_59:_59.args,l=n.length,lc=this.lastControl,i=0;
-if(lc.type!="C"){
-p.push(" c");
-this._addArgs(p,[_5a.x,_5a.y],0,2);
-this._addArgs(p,n,0,4);
-lc.x=n[0];
-lc.y=n[1];
-lc.type="C";
-i=4;
-}
-for(;i<l;i+=4){
-p.push(" c");
-this._addArgs(p,[2*_5a.x-lc.x,2*_5a.y-lc.y],0,2);
-this._addArgs(p,n,i,i+4);
-lc.x=n[i];
-lc.y=n[i+1];
-}
-return p;
-},_smoothCurveToR:function(_5b,_5c){
-return this._smoothCurveToA(this._adjustRelCrd(_5c,_5b,4),_5c);
-},_qCurveToA:function(_5d){
-var p=[],n=_5d instanceof Array?_5d:_5d.args,l=n.length,lc=this.lastControl;
-for(var i=0;i<l;i+=4){
-p.push(" qb");
-this._addArgs(p,n,i,i+4);
-}
-lc.x=n[l-4];
-lc.y=n[l-3];
-lc.type="Q";
-return p;
-},_qCurveToR:function(_5e,_5f){
-return this._qCurveToA(this._adjustRelCrd(_5f,_5e,4));
-},_qSmoothCurveToA:function(_60,_61){
-var p=[],n=_60 instanceof Array?_60:_60.args,l=n.length,lc=this.lastControl,i=0;
-if(lc.type!="Q"){
-p.push(" qb");
-this._addArgs(p,[lc.x=_61.x,lc.y=_61.y],0,2);
-lc.type="Q";
-this._addArgs(p,n,0,2);
-i=2;
-}
-for(;i<l;i+=2){
-p.push(" qb");
-this._addArgs(p,[lc.x=2*_61.x-lc.x,lc.y=2*_61.y-lc.y],0,2);
-this._addArgs(p,n,i,i+2);
-}
-return p;
-},_qSmoothCurveToR:function(_62,_63){
-return this._qSmoothCurveToA(this._adjustRelCrd(_63,_62,2),_63);
-},_arcTo:function(_64,_65){
-var p=[],n=_64.args,l=n.length,_66=_64.action=="a";
-for(var i=0;i<l;i+=7){
-var x1=n[i+5],y1=n[i+6];
-if(_66){
-x1+=_65.x;
-y1+=_65.y;
-}
-var _67=g.arc.arcAsBezier(_65,n[i],n[i+1],n[i+2],n[i+3]?1:0,n[i+4]?1:0,x1,y1);
-for(var j=0;j<_67.length;++j){
-p.push(" c");
-var t=_67[j];
-this._addArgs(p,t,0,t.length);
-}
-_65.x=x1;
-_65.y=y1;
-}
-this.lastControl.type="";
-return p;
-},_closePath:function(){
-this.lastControl.type="";
-return ["x"];
-}});
-g.Path.nodeType="shape";
-dojo.declare("dojox.gfx.TextPath",g.Path,{constructor:function(_68){
-if(_68){
-_68.setAttribute("dojoGfxType","textpath");
-}
-this.fontStyle=null;
-if(!("text" in this)){
-this.text=d.clone(g.defaultTextPath);
-}
-if(!("fontStyle" in this)){
-this.fontStyle=d.clone(g.defaultFont);
-}
-},setText:function(_69){
-this.text=g.makeParameters(this.text,typeof _69=="string"?{text:_69}:_69);
-this._setText();
-return this;
-},setFont:function(_6a){
-this.fontStyle=typeof _6a=="string"?g.splitFontString(_6a):g.makeParameters(g.defaultFont,_6a);
-this._setFont();
-return this;
-},_setText:function(){
-this.bbox=null;
-var r=this.rawNode,s=this.text,p=null,t=null,c=r.childNodes;
-for(var i=0;i<c.length;++i){
-var tag=c[i].tagName;
-if(tag=="path"){
-p=c[i];
-if(t){
-break;
-}
-}else{
-if(tag=="textpath"){
-t=c[i];
-if(p){
-break;
-}
-}
-}
-}
-if(!p){
-p=this.rawNode.ownerDocument.createElement("v:path");
-r.appendChild(p);
-}
-if(!t){
-t=this.rawNode.ownerDocument.createElement("v:textpath");
-r.appendChild(t);
-}
-p.textPathOk=true;
-t.on=true;
-var a=_1.text_alignment[s.align];
-t.style["v-text-align"]=a?a:"left";
-t.style["text-decoration"]=s.decoration;
-t.style["v-rotate-letters"]=s.rotated;
-t.style["v-text-kern"]=s.kerning;
-t.string=s.text;
-},_setFont:function(){
-var f=this.fontStyle,c=this.rawNode.childNodes;
-for(var i=0;i<c.length;++i){
-if(c[i].tagName=="textpath"){
-c[i].style.font=g.makeFontString(f);
-break;
-}
-}
-}});
-g.TextPath.nodeType="shape";
-dojo.declare("dojox.gfx.Surface",gs.Surface,{constructor:function(){
-_1.Container._init.call(this);
-},setDimensions:function(_6b,_6c){
-this.width=g.normalizedLength(_6b);
-this.height=g.normalizedLength(_6c);
-if(!this.rawNode){
-return this;
-}
-var cs=this.clipNode.style,r=this.rawNode,rs=r.style,bs=this.bgNode.style,ps=this._parent.style,i;
-ps.width=_6b;
-ps.height=_6c;
-cs.width=_6b;
-cs.height=_6c;
-cs.clip="rect(0px "+_6b+"px "+_6c+"px 0px)";
-rs.width=_6b;
-rs.height=_6c;
-r.coordsize=_6b+" "+_6c;
-bs.width=_6b;
-bs.height=_6c;
-for(i=0;i<this.children.length;++i){
-this.children[i]._setDimensions(_6b,_6c);
-}
-return this;
-},getDimensions:function(){
-var t=this.rawNode?{width:g.normalizedLength(this.rawNode.style.width),height:g.normalizedLength(this.rawNode.style.height)}:null;
-if(t.width<=0){
-t.width=this.width;
-}
-if(t.height<=0){
-t.height=this.height;
-}
-return t;
-}});
-g.createSurface=function(_6d,_6e,_6f){
-if(!_6e&&!_6f){
-var pos=d.position(_6d);
-_6e=_6e||pos.w;
-_6f=_6f||pos.h;
-}
-if(typeof _6e=="number"){
-_6e=_6e+"px";
-}
-if(typeof _6f=="number"){
-_6f=_6f+"px";
-}
-var s=new g.Surface(),p=d.byId(_6d),c=s.clipNode=p.ownerDocument.createElement("div"),r=s.rawNode=p.ownerDocument.createElement("v:group"),cs=c.style,rs=r.style;
-if(d.isIE>7){
-rs.display="inline-block";
-}
-s._parent=p;
-s._nodes.push(c);
-p.style.width=_6e;
-p.style.height=_6f;
-cs.position="absolute";
-cs.width=_6e;
-cs.height=_6f;
-cs.clip="rect(0px "+_6e+" "+_6f+" 0px)";
-rs.position="absolute";
-rs.width=_6e;
-rs.height=_6f;
-r.coordsize=(_6e==="100%"?_6e:parseFloat(_6e))+" "+(_6f==="100%"?_6f:parseFloat(_6f));
-r.coordorigin="0 0";
-var b=s.bgNode=r.ownerDocument.createElement("v:rect"),bs=b.style;
-bs.left=bs.top=0;
-bs.width=rs.width;
-bs.height=rs.height;
-b.filled=b.stroked="f";
-r.appendChild(b);
-c.appendChild(r);
-p.appendChild(c);
-s.width=g.normalizedLength(_6e);
-s.height=g.normalizedLength(_6f);
-return s;
-};
-_1.Container={_init:function(){
-gs.Container._init.call(this);
-},add:function(_70){
-if(this!=_70.getParent()){
-this.rawNode.appendChild(_70.rawNode);
-if(!_70.getParent()){
-_70.setFill(_70.getFill());
-_70.setStroke(_70.getStroke());
-}
-gs.Container.add.apply(this,arguments);
-}
-return this;
-},remove:function(_71,_72){
-if(this==_71.getParent()){
-if(this.rawNode==_71.rawNode.parentNode){
-this.rawNode.removeChild(_71.rawNode);
-}
-gs.Container.remove.apply(this,arguments);
-}
-return this;
-},clear:function(){
-var r=this.rawNode;
-while(r.firstChild!=r.lastChild){
-if(r.firstChild!=this.bgNode){
-r.removeChild(r.firstChild);
-}
-if(r.lastChild!=this.bgNode){
-r.removeChild(r.lastChild);
-}
-}
-return gs.Container.clear.apply(this,arguments);
-},_moveChildToFront:gs.Container._moveChildToFront,_moveChildToBack:gs.Container._moveChildToBack};
-dojo.mixin(gs.Creator,{createGroup:function(){
-var _73=this.createObject(g.Group,null);
-var r=_73.rawNode.ownerDocument.createElement("v:rect");
-r.style.left=r.style.top=0;
-r.style.width=_73.rawNode.style.width;
-r.style.height=_73.rawNode.style.height;
-r.filled=r.stroked="f";
-_73.rawNode.appendChild(r);
-_73.bgNode=r;
-return _73;
-},createImage:function(_74){
-if(!this.rawNode){
-return null;
-}
-var _75=new g.Image(),doc=this.rawNode.ownerDocument,_76=doc.createElement("v:rect");
-_76.stroked="f";
-_76.style.width=this.rawNode.style.width;
-_76.style.height=this.rawNode.style.height;
-var img=doc.createElement("v:imagedata");
-_76.appendChild(img);
-_75.setRawNode(_76);
-this.rawNode.appendChild(_76);
-_75.setShape(_74);
-this.add(_75);
-return _75;
-},createRect:function(_77){
-if(!this.rawNode){
-return null;
-}
-var _78=new g.Rect,_79=this.rawNode.ownerDocument.createElement("v:roundrect");
-if(d.isIE>7){
-_79.style.display="inline-block";
-}
-_78.setRawNode(_79);
-this.rawNode.appendChild(_79);
-_78.setShape(_77);
-this.add(_78);
-return _78;
-},createObject:function(_7a,_7b){
-if(!this.rawNode){
-return null;
-}
-var _7c=new _7a(),_7d=this.rawNode.ownerDocument.createElement("v:"+_7a.nodeType);
-_7c.setRawNode(_7d);
-this.rawNode.appendChild(_7d);
-switch(_7a){
-case g.Group:
-case g.Line:
-case g.Polyline:
-case g.Image:
-case g.Text:
-case g.Path:
-case g.TextPath:
-this._overrideSize(_7d);
-}
-_7c.setShape(_7b);
-this.add(_7c);
-return _7c;
-},_overrideSize:function(_7e){
-var s=this.rawNode.style,w=s.width,h=s.height;
-_7e.style.width=w;
-_7e.style.height=h;
-_7e.coordsize=parseInt(w)+" "+parseInt(h);
-}});
-d.extend(g.Group,_1.Container);
-d.extend(g.Group,gs.Creator);
-d.extend(g.Surface,_1.Container);
-d.extend(g.Surface,gs.Creator);
-})();
-}
+	var d = dojo, g = dojox.gfx, m = g.matrix, gs = g.shape, vml = g.vml;
+
+	// dojox.gfx.vml.xmlns: String: a VML's namespace
+	vml.xmlns = "urn:schemas-microsoft-com:vml";
+
+	// dojox.gfx.vml.text_alignment: Object: mapping from SVG alignment to VML alignment
+	vml.text_alignment = {start: "left", middle: "center", end: "right"};
+
+	vml._parseFloat = function(str) {
+		// summary: a helper function to parse VML-specific floating-point values
+		// str: String: a representation of a floating-point number
+		return str.match(/^\d+f$/i) ? parseInt(str) / 65536 : parseFloat(str);	// Number
+	};
+
+	vml._bool = {"t": 1, "true": 1};
+
+	d.extend(g.Shape, {
+		// summary: VML-specific implementation of dojox.gfx.Shape methods
+
+		setFill: function(fill){
+			// summary: sets a fill object (VML)
+			// fill: Object: a fill object
+			//	(see dojox.gfx.defaultLinearGradient,
+			//	dojox.gfx.defaultRadialGradient,
+			//	dojox.gfx.defaultPattern,
+			//	or dojo.Color)
+
+			if(!fill){
+				// don't fill
+				this.fillStyle = null;
+				this.rawNode.filled = "f";
+				return this;
+			}
+			var i, f, fo, a, s;
+			if(typeof fill == "object" && "type" in fill){
+				// gradient
+				switch(fill.type){
+					case "linear":
+						var matrix = this._getRealMatrix(), bbox = this.getBoundingBox(),
+							tbbox = this._getRealBBox ? this._getRealBBox() : this.getTransformedBoundingBox();
+						s = [];
+						if(this.fillStyle !== fill){
+							this.fillStyle = g.makeParameters(g.defaultLinearGradient, fill);
+						}
+						f = g.gradient.project(matrix, this.fillStyle,
+								{x: bbox.x, y: bbox.y},
+								{x: bbox.x + bbox.width, y: bbox.y + bbox.height},
+								tbbox[0], tbbox[2]);
+						a = f.colors;
+						if(a[0].offset.toFixed(5) != "0.00000"){
+							s.push("0 " + g.normalizeColor(a[0].color).toHex());
+						}
+						for(i = 0; i < a.length; ++i){
+							s.push(a[i].offset.toFixed(5) + " " + g.normalizeColor(a[i].color).toHex());
+						}
+						i = a.length - 1;
+						if(a[i].offset.toFixed(5) != "1.00000"){
+							s.push("1 " + g.normalizeColor(a[i].color).toHex());
+						}
+						fo = this.rawNode.fill;
+						fo.colors.value = s.join(";");
+						fo.method = "sigma";
+						fo.type = "gradient";
+						fo.angle = (270 - m._radToDeg(f.angle)) % 360;
+						fo.on = true;
+						break;
+					case "radial":
+						f = g.makeParameters(g.defaultRadialGradient, fill);
+						this.fillStyle = f;
+						var l = parseFloat(this.rawNode.style.left),
+							t = parseFloat(this.rawNode.style.top),
+							w = parseFloat(this.rawNode.style.width),
+							h = parseFloat(this.rawNode.style.height),
+							c = isNaN(w) ? 1 : 2 * f.r / w;
+						a = [];
+						// add a color at the offset 0 (1 in VML coordinates)
+						if(f.colors[0].offset > 0){
+							a.push({offset: 1, color: g.normalizeColor(f.colors[0].color)});
+						}
+						// massage colors
+						d.forEach(f.colors, function(v, i){
+							a.push({offset: 1 - v.offset * c, color: g.normalizeColor(v.color)});
+						});
+						i = a.length - 1;
+						while(i >= 0 && a[i].offset < 0){ --i; }
+						if(i < a.length - 1){
+							// correct excessive colors
+							var q = a[i], p = a[i + 1];
+							p.color = d.blendColors(q.color, p.color, q.offset / (q.offset - p.offset));
+							p.offset = 0;
+							while(a.length - i > 2) a.pop();
+						}
+						// set colors
+						i = a.length - 1, s = [];
+						if(a[i].offset > 0){
+							s.push("0 " + a[i].color.toHex());
+						}
+						for(; i >= 0; --i){
+							s.push(a[i].offset.toFixed(5) + " " + a[i].color.toHex());
+						}
+						fo = this.rawNode.fill;
+						fo.colors.value = s.join(";");
+						fo.method = "sigma";
+						fo.type = "gradientradial";
+						if(isNaN(w) || isNaN(h) || isNaN(l) || isNaN(t)){
+							fo.focusposition = "0.5 0.5";
+						}else{
+							fo.focusposition = ((f.cx - l) / w).toFixed(5) + " " + ((f.cy - t) / h).toFixed(5);
+						}
+						fo.focussize = "0 0";
+						fo.on = true;
+						break;
+					case "pattern":
+						f = g.makeParameters(g.defaultPattern, fill);
+						this.fillStyle = f;
+						fo = this.rawNode.fill;
+						fo.type = "tile";
+						fo.src = f.src;
+						if(f.width && f.height){
+							// in points
+							fo.size.x = g.px2pt(f.width);
+							fo.size.y = g.px2pt(f.height);
+						}
+						fo.alignShape = "f";
+						fo.position.x = 0;
+						fo.position.y = 0;
+						fo.origin.x = f.width  ? f.x / f.width  : 0;
+						fo.origin.y = f.height ? f.y / f.height : 0;
+						fo.on = true;
+						break;
+				}
+				this.rawNode.fill.opacity = 1;
+				return this;
+			}
+			// color object
+			this.fillStyle = g.normalizeColor(fill);
+			fo = this.rawNode.fill;
+			if(!fo){
+				fo = this.rawNode.ownerDocument.createElement("v:fill");
+			}
+			fo.method = "any";
+			fo.type = "solid";
+			fo.opacity = this.fillStyle.a;
+			this.rawNode.fillcolor = this.fillStyle.toHex();
+			this.rawNode.filled = true;
+			return this;	// self
+		},
+
+		setStroke: function(stroke){
+			// summary: sets a stroke object (VML)
+			// stroke: Object: a stroke object
+			//	(see dojox.gfx.defaultStroke)
+
+			if(!stroke){
+				// don't stroke
+				this.strokeStyle = null;
+				this.rawNode.stroked = "f";
+				return this;
+			}
+			// normalize the stroke
+			if(typeof stroke == "string" || d.isArray(stroke) || stroke instanceof d.Color){
+				stroke = {color: stroke};
+			}
+			var s = this.strokeStyle = g.makeParameters(g.defaultStroke, stroke);
+			s.color = g.normalizeColor(s.color);
+			// generate attributes
+			var rn = this.rawNode;
+			rn.stroked = true;
+			rn.strokecolor = s.color.toCss();
+			rn.strokeweight = s.width + "px";	// TODO: should we assume that the width is always in pixels?
+			if(rn.stroke) {
+				rn.stroke.opacity = s.color.a;
+				rn.stroke.endcap = this._translate(this._capMap, s.cap);
+				if(typeof s.join == "number") {
+					rn.stroke.joinstyle = "miter";
+					rn.stroke.miterlimit = s.join;
+				}else{
+					rn.stroke.joinstyle = s.join;
+					// rn.stroke.miterlimit = s.width;
+				}
+				rn.stroke.dashstyle = s.style == "none" ? "Solid" : s.style;
+			}
+			return this;	// self
+		},
+
+		_capMap: { butt: 'flat' },
+		_capMapReversed: { flat: 'butt' },
+
+		_translate: function(dict, value) {
+			return (value in dict) ? dict[value] : value;
+		},
+
+		_applyTransform: function() {
+			var matrix = this._getRealMatrix();
+			if(matrix){
+				var skew = this.rawNode.skew;
+				if(typeof skew == "undefined"){
+					for(var i = 0; i < this.rawNode.childNodes.length; ++i){
+						if(this.rawNode.childNodes[i].tagName == "skew"){
+							skew = this.rawNode.childNodes[i];
+							break;
+						}
+					}
+				}
+				if(skew){
+					skew.on = "f";
+					var mt = matrix.xx.toFixed(8) + " " + matrix.xy.toFixed(8) + " " +
+						matrix.yx.toFixed(8) + " " + matrix.yy.toFixed(8) + " 0 0",
+						offset = Math.floor(matrix.dx).toFixed() + "px " + Math.floor(matrix.dy).toFixed() + "px",
+						s = this.rawNode.style,
+						l = parseFloat(s.left),
+						t = parseFloat(s.top),
+						w = parseFloat(s.width),
+						h = parseFloat(s.height);
+					if(isNaN(l)) l = 0;
+					if(isNaN(t)) t = 0;
+					if(isNaN(w) || !w) w = 1;
+					if(isNaN(h) || !h) h = 1;
+					var origin = (-l / w - 0.5).toFixed(8) + " " + (-t / h - 0.5).toFixed(8);
+					skew.matrix =  mt;
+					skew.origin = origin;
+					skew.offset = offset;
+					skew.on = true;
+				}
+			}
+			if(this.fillStyle && this.fillStyle.type == "linear"){
+				this.setFill(this.fillStyle);
+			}
+			return this;
+		},
+
+		_setDimensions: function(width, height){
+			// summary: sets the width and height of the rawNode,
+			//	if the surface sixe has been changed
+			// width: String: width in pixels
+			// height: String: height in pixels
+
+			// default implementation does nothing
+			return this; // self
+		},
+
+		setRawNode: function(rawNode){
+			// summary:
+			//	assigns and clears the underlying node that will represent this
+			//	shape. Once set, transforms, gradients, etc, can be applied.
+			//	(no fill & stroke by default)
+			rawNode.stroked = "f";
+			rawNode.filled  = "f";
+			this.rawNode = rawNode;
+		},
+
+		// move family
+
+		_moveToFront: function(){
+			// summary: moves a shape to front of its parent's list of shapes (VML)
+			this.rawNode.parentNode.appendChild(this.rawNode);
+			return this;
+		},
+		_moveToBack: function(){
+			// summary: moves a shape to back of its parent's list of shapes (VML)
+			var r = this.rawNode, p = r.parentNode, n = p.firstChild;
+			p.insertBefore(r, n);
+			if(n.tagName == "rect"){
+				// surface has a background rectangle, which position should be preserved
+				n.swapNode(r);
+			}
+			return this;
+		},
+
+		_getRealMatrix: function(){
+			// summary: returns the cumulative ("real") transformation matrix
+			//	by combining the shape's matrix with its parent's matrix
+			return this.parentMatrix ? new g.Matrix2D([this.parentMatrix, this.matrix]) : this.matrix;	// dojox.gfx.Matrix2D
+		}
+	});
+
+	dojo.declare("dojox.gfx.Group", g.Shape, {
+		// summary: a group shape (VML), which can be used
+		//	to logically group shapes (e.g, to propagate matricies)
+		constructor: function(){
+			vml.Container._init.call(this);
+		},
+		// apply transformation
+		_applyTransform: function(){
+			// summary: applies a transformation matrix to a group
+			var matrix = this._getRealMatrix();
+			for(var i = 0; i < this.children.length; ++i){
+				this.children[i]._updateParentMatrix(matrix);
+			}
+			return this;	// self
+		},
+		_setDimensions: function(width, height){
+			// summary: sets the width and height of the rawNode,
+			//	if the surface sixe has been changed
+			// width: String: width in pixels
+			// height: String: height in pixels
+			var r = this.rawNode, rs = r.style,
+				bs = this.bgNode.style;
+			rs.width = width;
+			rs.height = height;
+			r.coordsize = width + " " + height;
+			bs.width = width;
+			bs.height = height;
+			for(var i = 0; i < this.children.length; ++i){
+				this.children[i]._setDimensions(width, height);
+			}
+			return this; // self
+		}
+	});
+	g.Group.nodeType = "group";
+
+	dojo.declare("dojox.gfx.Rect", gs.Rect, {
+		// summary: a rectangle shape (VML)
+		setShape: function(newShape){
+			// summary: sets a rectangle shape object (VML)
+			// newShape: Object: a rectangle shape object
+			var shape = this.shape = g.makeParameters(this.shape, newShape);
+			this.bbox = null;
+			var r = Math.min(1, (shape.r / Math.min(parseFloat(shape.width), parseFloat(shape.height)))).toFixed(8);
+			// a workaround for the VML's arcsize bug: cannot read arcsize of an instantiated node
+			var parent = this.rawNode.parentNode, before = null;
+			if(parent){
+				if(parent.lastChild !== this.rawNode){
+					for(var i = 0; i < parent.childNodes.length; ++i){
+						if(parent.childNodes[i] === this.rawNode){
+							before = parent.childNodes[i + 1];
+							break;
+						}
+					}
+				}
+				parent.removeChild(this.rawNode);
+			}
+			if(d.isIE > 7){
+				var node = this.rawNode.ownerDocument.createElement("v:roundrect");
+				node.arcsize = r;
+				node.style.display = "inline-block";
+				this.rawNode = node;
+			}else{
+				this.rawNode.arcsize = r;
+			}
+			if(parent){
+				if(before){
+					parent.insertBefore(this.rawNode, before);
+				}else{
+					parent.appendChild(this.rawNode);
+				}
+			}
+			var style = this.rawNode.style;
+			style.left   = shape.x.toFixed();
+			style.top    = shape.y.toFixed();
+			style.width  = (typeof shape.width == "string" && shape.width.indexOf("%") >= 0)  ? shape.width  : shape.width.toFixed();
+			style.height = (typeof shape.width == "string" && shape.height.indexOf("%") >= 0) ? shape.height : shape.height.toFixed();
+			// set all necessary styles, which are lost by VML (yes, it's a VML's bug)
+			return this.setTransform(this.matrix).setFill(this.fillStyle).setStroke(this.strokeStyle);	// self
+		}
+	});
+	g.Rect.nodeType = "roundrect"; // use a roundrect so the stroke join type is respected
+
+
+	dojo.declare("dojox.gfx.Ellipse", gs.Ellipse, {
+		// summary: an ellipse shape (VML)
+		setShape: function(newShape){
+			// summary: sets an ellipse shape object (VML)
+			// newShape: Object: an ellipse shape object
+			var shape = this.shape = g.makeParameters(this.shape, newShape);
+			this.bbox = null;
+			var style = this.rawNode.style;
+			style.left   = (shape.cx - shape.rx).toFixed();
+			style.top    = (shape.cy - shape.ry).toFixed();
+			style.width  = (shape.rx * 2).toFixed();
+			style.height = (shape.ry * 2).toFixed();
+			return this.setTransform(this.matrix);	// self
+		}
+	});
+	g.Ellipse.nodeType = "oval";
+
+	dojo.declare("dojox.gfx.Circle", gs.Circle, {
+		// summary: a circle shape (VML)
+		setShape: function(newShape){
+			// summary: sets a circle shape object (VML)
+			// newShape: Object: a circle shape object
+			var shape = this.shape = g.makeParameters(this.shape, newShape);
+			this.bbox = null;
+			var style = this.rawNode.style;
+			style.left   = (shape.cx - shape.r).toFixed();
+			style.top    = (shape.cy - shape.r).toFixed();
+			style.width  = (shape.r * 2).toFixed();
+			style.height = (shape.r * 2).toFixed();
+			return this;	// self
+		}
+	});
+	g.Circle.nodeType = "oval";
+
+	dojo.declare("dojox.gfx.Line", gs.Line, {
+		// summary: a line shape (VML)
+		constructor: function(rawNode){
+			if(rawNode) rawNode.setAttribute("dojoGfxType", "line");
+		},
+		setShape: function(newShape){
+			// summary: sets a line shape object (VML)
+			// newShape: Object: a line shape object
+			var shape = this.shape = g.makeParameters(this.shape, newShape);
+			this.bbox = null;
+			this.rawNode.path.v = "m" + shape.x1.toFixed() + " " + shape.y1.toFixed() +
+				"l" + shape.x2.toFixed() + " " + shape.y2.toFixed() + "e";
+			return this.setTransform(this.matrix);	// self
+		}
+	});
+	g.Line.nodeType = "shape";
+
+	dojo.declare("dojox.gfx.Polyline", gs.Polyline, {
+		// summary: a polyline/polygon shape (VML)
+		constructor: function(rawNode){
+			if(rawNode) rawNode.setAttribute("dojoGfxType", "polyline");
+		},
+		setShape: function(points, closed){
+			// summary: sets a polyline/polygon shape object (VML)
+			// points: Object: a polyline/polygon shape object
+			// closed: Boolean?: if true, close the polyline explicitely
+			if(points && points instanceof Array){
+				// branch
+				// points: Array: an array of points
+				this.shape = g.makeParameters(this.shape, { points: points });
+				if(closed && this.shape.points.length) this.shape.points.push(this.shape.points[0]);
+			}else{
+				this.shape = g.makeParameters(this.shape, points);
+			}
+			this.bbox = null;
+			this._normalizePoints();
+			var attr = [], p = this.shape.points;
+			if(p.length > 0){
+				attr.push("m");
+				attr.push(p[0].x.toFixed(), p[0].y.toFixed());
+				if(p.length > 1){
+					attr.push("l");
+					for(var i = 1; i < p.length; ++i){
+						attr.push(p[i].x.toFixed(), p[i].y.toFixed());
+					}
+				}
+			}
+			attr.push("e");
+			this.rawNode.path.v = attr.join(" ");
+			return this.setTransform(this.matrix);	// self
+		}
+	});
+	g.Polyline.nodeType = "shape";
+
+	dojo.declare("dojox.gfx.Image", gs.Image, {
+		// summary: an image (VML)
+		setShape: function(newShape){
+			// summary: sets an image shape object (VML)
+			// newShape: Object: an image shape object
+			var shape = this.shape = g.makeParameters(this.shape, newShape);
+			this.bbox = null;
+			this.rawNode.firstChild.src = shape.src;
+			return this.setTransform(this.matrix);	// self
+		},
+		_applyTransform: function() {
+			var matrix = this._getRealMatrix(),
+				rawNode = this.rawNode,
+				s = rawNode.style,
+				shape = this.shape;
+			if(matrix){
+				matrix = m.multiply(matrix, {dx: shape.x, dy: shape.y});
+			}else{
+				matrix = m.normalize({dx: shape.x, dy: shape.y});
+			}
+			if(matrix.xy == 0 && matrix.yx == 0 && matrix.xx > 0 && matrix.yy > 0){
+				// special case to avoid filters
+				s.filter = "";
+				s.width  = Math.floor(matrix.xx * shape.width);
+				s.height = Math.floor(matrix.yy * shape.height);
+				s.left   = Math.floor(matrix.dx);
+				s.top    = Math.floor(matrix.dy);
+			}else{
+				var ps = rawNode.parentNode.style;
+				s.left   = "0px";
+				s.top    = "0px";
+				s.width  = ps.width;
+				s.height = ps.height;
+				matrix = m.multiply(matrix,
+					{xx: shape.width / parseInt(s.width), yy: shape.height / parseInt(s.height)});
+				var f = rawNode.filters["DXImageTransform.Microsoft.Matrix"];
+				if(f){
+					f.M11 = matrix.xx;
+					f.M12 = matrix.xy;
+					f.M21 = matrix.yx;
+					f.M22 = matrix.yy;
+					f.Dx = matrix.dx;
+					f.Dy = matrix.dy;
+				}else{
+					s.filter = "progid:DXImageTransform.Microsoft.Matrix(M11=" + matrix.xx +
+						", M12=" + matrix.xy + ", M21=" + matrix.yx + ", M22=" + matrix.yy +
+						", Dx=" + matrix.dx + ", Dy=" + matrix.dy + ")";
+				}
+			}
+			return this; // self
+		},
+		_setDimensions: function(width, height){
+			// summary: sets the width and height of the rawNode,
+			//	if the surface sixe has been changed
+			// width: String: width in pixels
+			// height: String: height in pixels
+
+			var r = this.rawNode, f = r.filters["DXImageTransform.Microsoft.Matrix"];
+			if(f){
+				var s = r.style;
+				s.width  = width;
+				s.height = height;
+				return this._applyTransform(); // self
+			}
+			return this;	// self
+		}
+	});
+	g.Image.nodeType = "rect";
+
+	dojo.declare("dojox.gfx.Text", gs.Text, {
+		// summary: an anchored text (VML)
+		constructor: function(rawNode){
+			if(rawNode){rawNode.setAttribute("dojoGfxType", "text");}
+			this.fontStyle = null;
+		},
+		_alignment: {start: "left", middle: "center", end: "right"},
+		setShape: function(newShape){
+			// summary: sets a text shape object (VML)
+			// newShape: Object: a text shape object
+			this.shape = g.makeParameters(this.shape, newShape);
+			this.bbox = null;
+			var r = this.rawNode, s = this.shape, x = s.x, y = s.y.toFixed(), path;
+			switch(s.align){
+				case "middle":
+					x -= 5;
+					break;
+				case "end":
+					x -= 10;
+					break;
+			}
+			path = "m" + x.toFixed() + "," + y + "l" + (x + 10).toFixed() + "," + y + "e";
+			// find path and text path
+			var p = null, t = null, c = r.childNodes;
+			for(var i = 0; i < c.length; ++i){
+				var tag = c[i].tagName;
+				if(tag == "path"){
+					p = c[i];
+					if(t) break;
+				}else if(tag == "textpath"){
+					t = c[i];
+					if(p) break;
+				}
+			}
+			if(!p){
+				p = r.ownerDocument.createElement("v:path");
+				r.appendChild(p);
+			}
+			if(!t){
+				t = r.ownerDocument.createElement("v:textpath");
+				r.appendChild(t);
+			}
+			p.v = path;
+			p.textPathOk = true;
+			t.on = true;
+			var a = vml.text_alignment[s.align];
+			t.style["v-text-align"] = a ? a : "left";
+			t.style["text-decoration"] = s.decoration;
+			t.style["v-rotate-letters"] = s.rotated;
+			t.style["v-text-kern"] = s.kerning;
+			t.string = s.text;
+			return this.setTransform(this.matrix);	// self
+		},
+		_setFont: function(){
+			// summary: sets a font object (VML)
+			var f = this.fontStyle, c = this.rawNode.childNodes;
+			for(var i = 0; i < c.length; ++i){
+				if(c[i].tagName == "textpath"){
+					c[i].style.font = g.makeFontString(f);
+					break;
+				}
+			}
+			this.setTransform(this.matrix);
+		},
+		_getRealMatrix: function(){
+			// summary: returns the cumulative ("real") transformation matrix
+			//	by combining the shape's matrix with its parent's matrix;
+			//	it makes a correction for a font size
+			var matrix = g.Shape.prototype._getRealMatrix.call(this);
+			// It appears that text is always aligned vertically at a middle of x-height (???).
+			// It is impossible to obtain these metrics from VML => I try to approximate it with
+			// more-or-less util value of 0.7 * FontSize, which is typical for European fonts.
+			if(matrix){
+				matrix = m.multiply(matrix,
+					{dy: -g.normalizedLength(this.fontStyle ? this.fontStyle.size : "10pt") * 0.35});
+			}
+			return matrix;	// dojox.gfx.Matrix2D
+		},
+		getTextWidth: function(){
+			// summary: get the text width, in px
+			var rawNode = this.rawNode, _display = rawNode.style.display;
+			rawNode.style.display = "inline";
+			var _width = g.pt2px(parseFloat(rawNode.currentStyle.width));
+			rawNode.style.display = _display;
+			return _width;
+		}
+	});
+	g.Text.nodeType = "shape";
+
+	dojo.declare("dojox.gfx.Path", g.path.Path, {
+		// summary: a path shape (VML)
+		constructor: function(rawNode){
+			if(rawNode && !rawNode.getAttribute("dojoGfxType")){
+				rawNode.setAttribute("dojoGfxType", "path");
+			}
+			this.vmlPath = "";
+			this.lastControl = {};
+		},
+		_updateWithSegment: function(segment){
+			// summary: updates the bounding box of path with new segment
+			// segment: Object: a segment
+			var last = d.clone(this.last);
+			g.Path.superclass._updateWithSegment.apply(this, arguments);
+			if(arguments.length > 1){ return; } // skip transfomed bbox calculations
+			// add a VML path segment
+			var path = this[this.renderers[segment.action]](segment, last);
+			if(typeof this.vmlPath == "string"){
+				this.vmlPath += path.join("");
+				this.rawNode.path.v = this.vmlPath + " r0,0 e";
+			}else{
+				Array.prototype.push.apply(this.vmlPath, path);
+			}
+		},
+		setShape: function(newShape){
+			// summary: forms a path using a shape (VML)
+			// newShape: Object: an VML path string or a path object (see dojox.gfx.defaultPath)
+			this.vmlPath = [];
+			this.lastControl.type = "";	// no prior control point
+			g.Path.superclass.setShape.apply(this, arguments);
+			this.vmlPath = this.vmlPath.join("");
+			this.rawNode.path.v = this.vmlPath + " r0,0 e";
+			return this;
+		},
+		_pathVmlToSvgMap: {m: "M", l: "L", t: "m", r: "l", c: "C", v: "c", qb: "Q", x: "z", e: ""},
+		// VML-specific segment renderers
+		renderers: {
+			M: "_moveToA", m: "_moveToR",
+			L: "_lineToA", l: "_lineToR",
+			H: "_hLineToA", h: "_hLineToR",
+			V: "_vLineToA", v: "_vLineToR",
+			C: "_curveToA", c: "_curveToR",
+			S: "_smoothCurveToA", s: "_smoothCurveToR",
+			Q: "_qCurveToA", q: "_qCurveToR",
+			T: "_qSmoothCurveToA", t: "_qSmoothCurveToR",
+			A: "_arcTo", a: "_arcTo",
+			Z: "_closePath", z: "_closePath"
+		},
+		_addArgs: function(path, segment, from, upto){
+			var n = segment instanceof Array ? segment : segment.args;
+			for(var i = from; i < upto; ++i){
+				path.push(" ", n[i].toFixed());
+			}
+		},
+		_adjustRelCrd: function(last, segment, step){
+			var n = segment instanceof Array ? segment : segment.args, l = n.length,
+				result = new Array(l), i = 0, x = last.x, y = last.y;
+			if(typeof x != "number"){
+				// there is no last coordinate =>
+				// treat the first pair as an absolute coordinate
+				result[0] = x = n[0];
+				result[1] = y = n[1];
+				i = 2;
+			}
+			if(typeof step == "number" && step != 2){
+				var j = step;
+				while(j <= l){
+					for(; i < j; i += 2){
+						result[i] = x + n[i];
+						result[i + 1] = y + n[i + 1];
+					}
+					x = result[j - 2];
+					y = result[j - 1];
+					j += step;
+				}
+			}else{
+				for(; i < l; i += 2){
+					result[i] = (x += n[i]);
+					result[i + 1] = (y += n[i + 1]);
+				}
+			}
+			return result;
+		},
+		_adjustRelPos: function(last, segment){
+			var n = segment instanceof Array ? segment : segment.args, l = n.length,
+				result = new Array(l);
+			for(var i = 0; i < l; ++i){
+				result[i] = (last += n[i]);
+			}
+			return result;
+		},
+		_moveToA: function(segment){
+			var p = [" m"], n = segment instanceof Array ? segment : segment.args, l = n.length;
+			this._addArgs(p, n, 0, 2);
+			if(l > 2){
+				p.push(" l");
+				this._addArgs(p, n, 2, l);
+			}
+			this.lastControl.type = "";	// no control point after this primitive
+			return p;
+		},
+		_moveToR: function(segment, last){
+			return this._moveToA(this._adjustRelCrd(last, segment));
+		},
+		_lineToA: function(segment){
+			var p = [" l"], n = segment instanceof Array ? segment : segment.args;
+			this._addArgs(p, n, 0, n.length);
+			this.lastControl.type = "";	// no control point after this primitive
+			return p;
+		},
+		_lineToR: function(segment, last){
+			return this._lineToA(this._adjustRelCrd(last, segment));
+		},
+		_hLineToA: function(segment, last){
+			var p = [" l"], y = " " + last.y.toFixed(),
+				n = segment instanceof Array ? segment : segment.args, l = n.length;
+			for(var i = 0; i < l; ++i){
+				p.push(" ", n[i].toFixed(), y);
+			}
+			this.lastControl.type = "";	// no control point after this primitive
+			return p;
+		},
+		_hLineToR: function(segment, last){
+			return this._hLineToA(this._adjustRelPos(last.x, segment), last);
+		},
+		_vLineToA: function(segment, last){
+			var p = [" l"], x = " " + last.x.toFixed(),
+				n = segment instanceof Array ? segment : segment.args, l = n.length;
+			for(var i = 0; i < l; ++i){
+				p.push(x, " ", n[i].toFixed());
+			}
+			this.lastControl.type = "";	// no control point after this primitive
+			return p;
+		},
+		_vLineToR: function(segment, last){
+			return this._vLineToA(this._adjustRelPos(last.y, segment), last);
+		},
+		_curveToA: function(segment){
+			var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+				lc = this.lastControl;
+			for(var i = 0; i < l; i += 6){
+				p.push(" c");
+				this._addArgs(p, n, i, i + 6);
+			}
+			lc.x = n[l - 4];
+			lc.y = n[l - 3];
+			lc.type = "C";
+			return p;
+		},
+		_curveToR: function(segment, last){
+			return this._curveToA(this._adjustRelCrd(last, segment, 6));
+		},
+		_smoothCurveToA: function(segment, last){
+			var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+				lc = this.lastControl, i = 0;
+			if(lc.type != "C"){
+				p.push(" c");
+				this._addArgs(p, [last.x, last.y], 0, 2);
+				this._addArgs(p, n, 0, 4);
+				lc.x = n[0];
+				lc.y = n[1];
+				lc.type = "C";
+				i = 4;
+			}
+			for(; i < l; i += 4){
+				p.push(" c");
+				this._addArgs(p, [
+					2 * last.x - lc.x,
+					2 * last.y - lc.y
+				], 0, 2);
+				this._addArgs(p, n, i, i + 4);
+				lc.x = n[i];
+				lc.y = n[i + 1];
+			}
+			return p;
+		},
+		_smoothCurveToR: function(segment, last){
+			return this._smoothCurveToA(this._adjustRelCrd(last, segment, 4), last);
+		},
+		_qCurveToA: function(segment){
+			var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+				lc = this.lastControl;
+			for(var i = 0; i < l; i += 4){
+				p.push(" qb");
+				this._addArgs(p, n, i, i + 4);
+			}
+			lc.x = n[l - 4];
+			lc.y = n[l - 3];
+			lc.type = "Q";
+			return p;
+		},
+		_qCurveToR: function(segment, last){
+			return this._qCurveToA(this._adjustRelCrd(last, segment, 4));
+		},
+		_qSmoothCurveToA: function(segment, last){
+			var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+				lc = this.lastControl, i = 0;
+			if(lc.type != "Q"){
+				p.push(" qb");
+				this._addArgs(p, [
+					lc.x = last.x,
+					lc.y = last.y
+				], 0, 2);
+				lc.type = "Q";
+				this._addArgs(p, n, 0, 2);
+				i = 2;
+			}
+			for(; i < l; i += 2){
+				p.push(" qb");
+				this._addArgs(p, [
+					lc.x = 2 * last.x - lc.x,
+					lc.y = 2 * last.y - lc.y
+				], 0, 2);
+				this._addArgs(p, n, i, i + 2);
+			}
+			return p;
+		},
+		_qSmoothCurveToR: function(segment, last){
+			return this._qSmoothCurveToA(this._adjustRelCrd(last, segment, 2), last);
+		},
+		_arcTo: function(segment, last){
+			var p = [], n = segment.args, l = n.length, relative = segment.action == "a";
+			for(var i = 0; i < l; i += 7){
+				var x1 = n[i + 5], y1 = n[i + 6];
+				if(relative){
+					x1 += last.x;
+					y1 += last.y;
+				}
+				var result = g.arc.arcAsBezier(
+					last, n[i], n[i + 1], n[i + 2],
+					n[i + 3] ? 1 : 0, n[i + 4] ? 1 : 0,
+					x1, y1
+				);
+				for(var j = 0; j < result.length; ++j){
+					p.push(" c");
+					var t = result[j];
+					this._addArgs(p, t, 0, t.length);
+					this._updateBBox(t[0], t[1]);
+					this._updateBBox(t[2], t[3]);
+					this._updateBBox(t[4], t[5]);
+				}
+				last.x = x1;
+				last.y = y1;
+			}
+			this.lastControl.type = "";	// no control point after this primitive
+			return p;
+		},
+		_closePath: function(){
+			this.lastControl.type = "";	// no control point after this primitive
+			return ["x"];
+		}
+	});
+	g.Path.nodeType = "shape";
+
+	dojo.declare("dojox.gfx.TextPath", g.Path, {
+		// summary: a textpath shape (VML)
+		constructor: function(rawNode){
+			if(rawNode){rawNode.setAttribute("dojoGfxType", "textpath");}
+			this.fontStyle = null;
+			if(!("text" in this)){
+				this.text = d.clone(g.defaultTextPath);
+			}
+			if(!("fontStyle" in this)){
+				this.fontStyle = d.clone(g.defaultFont);
+			}
+		},
+		setText: function(newText){
+			// summary: sets a text to be drawn along the path
+			this.text = g.makeParameters(this.text,
+				typeof newText == "string" ? {text: newText} : newText);
+			this._setText();
+			return this;	// self
+		},
+		setFont: function(newFont){
+			// summary: sets a font for text
+			this.fontStyle = typeof newFont == "string" ?
+				g.splitFontString(newFont) :
+				g.makeParameters(g.defaultFont, newFont);
+			this._setFont();
+			return this;	// self
+		},
+
+		_setText: function(){
+			// summary: sets a text shape object (VML)
+			this.bbox = null;
+			var r = this.rawNode, s = this.text,
+				// find path and text path
+				p = null, t = null, c = r.childNodes;
+			for(var i = 0; i < c.length; ++i){
+				var tag = c[i].tagName;
+				if(tag == "path"){
+					p = c[i];
+					if(t) break;
+				}else if(tag == "textpath"){
+					t = c[i];
+					if(p) break;
+				}
+			}
+			if(!p){
+				p = this.rawNode.ownerDocument.createElement("v:path");
+				r.appendChild(p);
+			}
+			if(!t){
+				t = this.rawNode.ownerDocument.createElement("v:textpath");
+				r.appendChild(t);
+			}
+			p.textPathOk = true;
+			t.on = true;
+			var a = vml.text_alignment[s.align];
+			t.style["v-text-align"] = a ? a : "left";
+			t.style["text-decoration"] = s.decoration;
+			t.style["v-rotate-letters"] = s.rotated;
+			t.style["v-text-kern"] = s.kerning;
+			t.string = s.text;
+		},
+		_setFont: function(){
+			// summary: sets a font object (VML)
+			var f = this.fontStyle, c = this.rawNode.childNodes;
+			for(var i = 0; i < c.length; ++i){
+				if(c[i].tagName == "textpath"){
+					c[i].style.font = g.makeFontString(f);
+					break;
+				}
+			}
+		}
+	});
+	g.TextPath.nodeType = "shape";
+
+	dojo.declare("dojox.gfx.Surface", gs.Surface, {
+		// summary: a surface object to be used for drawings (VML)
+		constructor: function(){
+			vml.Container._init.call(this);
+		},
+		setDimensions: function(width, height){
+			// summary: sets the width and height of the rawNode
+			// width: String: width of surface, e.g., "100px"
+			// height: String: height of surface, e.g., "100px"
+			this.width  = g.normalizedLength(width);	// in pixels
+			this.height = g.normalizedLength(height);	// in pixels
+			if(!this.rawNode) return this;
+			var cs = this.clipNode.style,
+				r = this.rawNode, rs = r.style,
+				bs = this.bgNode.style,
+				ps = this._parent.style, i;
+			ps.width = width;
+			ps.height = height;
+			cs.width  = width;
+			cs.height = height;
+			cs.clip = "rect(0px " + width + "px " + height + "px 0px)";
+			rs.width = width;
+			rs.height = height;
+			r.coordsize = width + " " + height;
+			bs.width = width;
+			bs.height = height;
+			for(i = 0; i < this.children.length; ++i){
+				this.children[i]._setDimensions(width, height);
+			}
+			return this;	// self
+		},
+		getDimensions: function(){
+			// summary: returns an object with properties "width" and "height"
+			var t = this.rawNode ? {
+				width:  g.normalizedLength(this.rawNode.style.width),
+				height: g.normalizedLength(this.rawNode.style.height)} : null;
+			if(t.width  <= 0){ t.width  = this.width; }
+			if(t.height <= 0){ t.height = this.height; }
+			return t;	// Object
+		}
+	});
+
+	g.createSurface = function(parentNode, width, height){
+		// summary: creates a surface (VML)
+		// parentNode: Node: a parent node
+		// width: String: width of surface, e.g., "100px"
+		// height: String: height of surface, e.g., "100px"
+
+		if(!width && !height){
+			var pos = d.position(parentNode);
+			width  = width  || pos.w;
+			height = height || pos.h;
+		}
+		if(typeof width == "number"){
+			width = width + "px";
+		}
+		if(typeof height == "number"){
+			height = height + "px";
+		}
+
+		var s = new g.Surface(), p = d.byId(parentNode),
+			c = s.clipNode = p.ownerDocument.createElement("div"),
+			r = s.rawNode = p.ownerDocument.createElement("v:group"),
+			cs = c.style, rs = r.style;
+
+		if(d.isIE > 7){
+			rs.display = "inline-block";
+		}
+
+		s._parent = p;
+		s._nodes.push(c);	// other elements will be deleted as parts of "c"
+
+		p.style.width  = width;
+		p.style.height = height;
+
+		cs.position = "absolute";
+		cs.width  = width;
+		cs.height = height;
+		cs.clip = "rect(0px " + width + " " + height + " 0px)";
+		rs.position = "absolute";
+		rs.width  = width;
+		rs.height = height;
+		r.coordsize = (width === "100%" ? width : parseFloat(width)) + " " +
+			(height === "100%" ? height : parseFloat(height));
+		r.coordorigin = "0 0";
+
+		// create a background rectangle, which is required to show all other shapes
+		var b = s.bgNode = r.ownerDocument.createElement("v:rect"), bs = b.style;
+		bs.left = bs.top = 0;
+		bs.width  = rs.width;
+		bs.height = rs.height;
+		b.filled = b.stroked = "f";
+
+		r.appendChild(b);
+		c.appendChild(r);
+		p.appendChild(c);
+
+		s.width  = g.normalizedLength(width);	// in pixels
+		s.height = g.normalizedLength(height);	// in pixels
+
+		return s;	// dojox.gfx.Surface
+	};
+
+	// Extenders
+
+
+	vml.Container = {
+		_init: function(){
+			gs.Container._init.call(this);
+		},
+		add: function(shape){
+			// summary: adds a shape to a group/surface
+			// shape: dojox.gfx.Shape: an VML shape object
+			if(this != shape.getParent()){
+				this.rawNode.appendChild(shape.rawNode);
+				if(!shape.getParent()){
+					// reapply visual attributes
+					shape.setFill(shape.getFill());
+					shape.setStroke(shape.getStroke());
+				}
+				//dojox.gfx.Group.superclass.add.apply(this, arguments);
+				//this.inherited(arguments);
+				gs.Container.add.apply(this, arguments);
+			}
+			return this;	// self
+		},
+		remove: function(shape, silently){
+			// summary: remove a shape from a group/surface
+			// shape: dojox.gfx.Shape: an VML shape object
+			// silently: Boolean?: if true, regenerate a picture
+			if(this == shape.getParent()){
+				if(this.rawNode == shape.rawNode.parentNode){
+					this.rawNode.removeChild(shape.rawNode);
+				}
+				//dojox.gfx.Group.superclass.remove.apply(this, arguments);
+				//this.inherited(arguments);
+				gs.Container.remove.apply(this, arguments);
+			}
+			return this;	// self
+		},
+		clear: function(){
+			// summary: removes all shapes from a group/surface
+			var r = this.rawNode;
+			while(r.firstChild != r.lastChild){
+				if(r.firstChild != this.bgNode){
+					r.removeChild(r.firstChild);
+				}
+				if(r.lastChild != this.bgNode){
+					r.removeChild(r.lastChild);
+				}
+			}
+			//return this.inherited(arguments);	// self
+			return gs.Container.clear.apply(this, arguments);
+		},
+		_moveChildToFront: gs.Container._moveChildToFront,
+		_moveChildToBack:  gs.Container._moveChildToBack
+	};
+
+	dojo.mixin(gs.Creator, {
+		// summary: VML shape creators
+		createGroup: function(){
+			// summary: creates a VML group shape
+			var node = this.createObject(g.Group, null);	// dojox.gfx.Group
+			// create a background rectangle, which is required to show all other shapes
+			var r = node.rawNode.ownerDocument.createElement("v:rect");
+			r.style.left = r.style.top = 0;
+			r.style.width  = node.rawNode.style.width;
+			r.style.height = node.rawNode.style.height;
+			r.filled = r.stroked = "f";
+			node.rawNode.appendChild(r);
+			node.bgNode = r;
+			return node;	// dojox.gfx.Group
+		},
+		createImage: function(image){
+			// summary: creates a VML image shape
+			// image: Object: an image object (see dojox.gfx.defaultImage)
+			if(!this.rawNode) return null;
+			var shape = new g.Image(),
+				doc = this.rawNode.ownerDocument,
+				node = doc.createElement('v:rect');
+			node.stroked = "f";
+			node.style.width  = this.rawNode.style.width;
+			node.style.height = this.rawNode.style.height;
+			var img  = doc.createElement('v:imagedata');
+			node.appendChild(img);
+			shape.setRawNode(node);
+			this.rawNode.appendChild(node);
+			shape.setShape(image);
+			this.add(shape);
+			return shape;	// dojox.gfx.Image
+		},
+		createRect: function(rect){
+			// summary: creates a rectangle shape
+			// rect: Object: a path object (see dojox.gfx.defaultRect)
+			if(!this.rawNode) return null;
+			var shape = new g.Rect,
+				node = this.rawNode.ownerDocument.createElement("v:roundrect");
+			if(d.isIE > 7){
+				node.style.display = "inline-block";
+			}
+			shape.setRawNode(node);
+			this.rawNode.appendChild(node);
+			shape.setShape(rect);
+			this.add(shape);
+			return shape;	// dojox.gfx.Rect
+		},
+		createObject: function(shapeType, rawShape) {
+			// summary: creates an instance of the passed shapeType class
+			// shapeType: Function: a class constructor to create an instance of
+			// rawShape: Object: properties to be passed in to the classes "setShape" method
+			// overrideSize: Boolean: set the size explicitly, if true
+			if(!this.rawNode) return null;
+			var shape = new shapeType(),
+				node = this.rawNode.ownerDocument.createElement('v:' + shapeType.nodeType);
+			shape.setRawNode(node);
+			this.rawNode.appendChild(node);
+			switch(shapeType){
+				case g.Group:
+				case g.Line:
+				case g.Polyline:
+				case g.Image:
+				case g.Text:
+				case g.Path:
+				case g.TextPath:
+					this._overrideSize(node);
+			}
+			shape.setShape(rawShape);
+			this.add(shape);
+			return shape;	// dojox.gfx.Shape
+		},
+		_overrideSize: function(node){
+			var s = this.rawNode.style, w = s.width, h = s.height;
+			node.style.width  = w;
+			node.style.height = h;
+			node.coordsize = parseInt(w) + " " + parseInt(h);
+		}
+	});
+
+	d.extend(g.Group, vml.Container);
+	d.extend(g.Group, gs.Creator);
+
+	d.extend(g.Surface, vml.Container);
+	d.extend(g.Surface, gs.Creator);
+
+})();
\ No newline at end of file
diff --git a/dojox/gfx/vml_attach.js b/dojox/gfx/vml_attach.js
index 0fc8970..99008d9 100644
--- a/dojox/gfx/vml_attach.js
+++ b/dojox/gfx/vml_attach.js
@@ -1,300 +1,362 @@
-/*
-	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
-*/
-
-
 dojo.require("dojox.gfx.vml");
+
 dojo.experimental("dojox.gfx.vml_attach");
+
 (function(){
-dojox.gfx.attachNode=function(_1){
-if(!_1){
-return null;
-}
-var s=null;
-switch(_1.tagName.toLowerCase()){
-case dojox.gfx.Rect.nodeType:
-s=new dojox.gfx.Rect(_1);
-_2(s);
-break;
-case dojox.gfx.Ellipse.nodeType:
-if(_1.style.width==_1.style.height){
-s=new dojox.gfx.Circle(_1);
-_3(s);
-}else{
-s=new dojox.gfx.Ellipse(_1);
-_4(s);
-}
-break;
-case dojox.gfx.Path.nodeType:
-switch(_1.getAttribute("dojoGfxType")){
-case "line":
-s=new dojox.gfx.Line(_1);
-_5(s);
-break;
-case "polyline":
-s=new dojox.gfx.Polyline(_1);
-_6(s);
-break;
-case "path":
-s=new dojox.gfx.Path(_1);
-_7(s);
-break;
-case "text":
-s=new dojox.gfx.Text(_1);
-_8(s);
-_9(s);
-_a(s);
-break;
-case "textpath":
-s=new dojox.gfx.TextPath(_1);
-_7(s);
-_8(s);
-_9(s);
-break;
-}
-break;
-case dojox.gfx.Image.nodeType:
-switch(_1.getAttribute("dojoGfxType")){
-case "image":
-s=new dojox.gfx.Image(_1);
-_b(s);
-_c(s);
-break;
-}
-break;
-default:
-return null;
-}
-if(!(s instanceof dojox.gfx.Image)){
-_d(s);
-_e(s);
-if(!(s instanceof dojox.gfx.Text)){
-_f(s);
-}
-}
-return s;
-};
-dojox.gfx.attachSurface=function(_10){
-var s=new dojox.gfx.Surface();
-s.clipNode=_10;
-var r=s.rawNode=_10.firstChild;
-var b=r.firstChild;
-if(!b||b.tagName!="rect"){
-return null;
-}
-s.bgNode=r;
-return s;
-};
-var _d=function(_11){
-var _12=null,r=_11.rawNode,fo=r.fill;
-if(fo.on&&fo.type=="gradient"){
-var _12=dojo.clone(dojox.gfx.defaultLinearGradient),rad=dojox.gfx.matrix._degToRad(fo.angle);
-_12.x2=Math.cos(rad);
-_12.y2=Math.sin(rad);
-_12.colors=[];
-var _13=fo.colors.value.split(";");
-for(var i=0;i<_13.length;++i){
-var t=_13[i].match(/\S+/g);
-if(!t||t.length!=2){
-continue;
-}
-_12.colors.push({offset:dojox.gfx.vml._parseFloat(t[0]),color:new dojo.Color(t[1])});
-}
-}else{
-if(fo.on&&fo.type=="gradientradial"){
-var _12=dojo.clone(dojox.gfx.defaultRadialGradient),w=parseFloat(r.style.width),h=parseFloat(r.style.height);
-_12.cx=isNaN(w)?0:fo.focusposition.x*w;
-_12.cy=isNaN(h)?0:fo.focusposition.y*h;
-_12.r=isNaN(w)?1:w/2;
-_12.colors=[];
-var _13=fo.colors.value.split(";");
-for(var i=_13.length-1;i>=0;--i){
-var t=_13[i].match(/\S+/g);
-if(!t||t.length!=2){
-continue;
-}
-_12.colors.push({offset:dojox.gfx.vml._parseFloat(t[0]),color:new dojo.Color(t[1])});
-}
-}else{
-if(fo.on&&fo.type=="tile"){
-var _12=dojo.clone(dojox.gfx.defaultPattern);
-_12.width=dojox.gfx.pt2px(fo.size.x);
-_12.height=dojox.gfx.pt2px(fo.size.y);
-_12.x=fo.origin.x*_12.width;
-_12.y=fo.origin.y*_12.height;
-_12.src=fo.src;
-}else{
-if(fo.on&&r.fillcolor){
-_12=new dojo.Color(r.fillcolor+"");
-_12.a=fo.opacity;
-}
-}
-}
-}
-_11.fillStyle=_12;
-};
-var _e=function(_14){
-var r=_14.rawNode;
-if(!r.stroked){
-_14.strokeStyle=null;
-return;
-}
-var _15=_14.strokeStyle=dojo.clone(dojox.gfx.defaultStroke),rs=r.stroke;
-_15.color=new dojo.Color(r.strokecolor.value);
-_15.width=dojox.gfx.normalizedLength(r.strokeweight+"");
-_15.color.a=rs.opacity;
-_15.cap=this._translate(this._capMapReversed,rs.endcap);
-_15.join=rs.joinstyle=="miter"?rs.miterlimit:rs.joinstyle;
-_15.style=rs.dashstyle;
-};
-var _f=function(_16){
-var s=_16.rawNode.skew,sm=s.matrix,so=s.offset;
-_16.matrix=dojox.gfx.matrix.normalize({xx:sm.xtox,xy:sm.ytox,yx:sm.xtoy,yy:sm.ytoy,dx:dojox.gfx.pt2px(so.x),dy:dojox.gfx.pt2px(so.y)});
-};
-var _17=function(_18){
-_18.bgNode=_18.rawNode.firstChild;
-};
-var _2=function(_19){
-var r=_19.rawNode,_1a=r.outerHTML.match(/arcsize = \"(\d*\.?\d+[%f]?)\"/)[1],_1b=r.style,_1c=parseFloat(_1b.width),_1d=parseFloat(_1b.height);
-_1a=(_1a.indexOf("%")>=0)?parseFloat(_1a)/100:dojox.gfx.vml._parseFloat(_1a);
-_19.shape=dojox.gfx.makeParameters(dojox.gfx.defaultRect,{x:parseInt(_1b.left),y:parseInt(_1b.top),width:_1c,height:_1d,r:Math.min(_1c,_1d)*_1a});
-};
-var _4=function(_1e){
-var _1f=_1e.rawNode.style,rx=parseInt(_1f.width)/2,ry=parseInt(_1f.height)/2;
-_1e.shape=dojox.gfx.makeParameters(dojox.gfx.defaultEllipse,{cx:parseInt(_1f.left)+rx,cy:parseInt(_1f.top)+ry,rx:rx,ry:ry});
-};
-var _3=function(_20){
-var _21=_20.rawNode.style,r=parseInt(_21.width)/2;
-_20.shape=dojox.gfx.makeParameters(dojox.gfx.defaultCircle,{cx:parseInt(_21.left)+r,cy:parseInt(_21.top)+r,r:r});
-};
-var _5=function(_22){
-var _23=_22.shape=dojo.clone(dojox.gfx.defaultLine),p=_22.rawNode.path.v.match(dojox.gfx.pathVmlRegExp);
-do{
-if(p.length<7||p[0]!="m"||p[3]!="l"||p[6]!="e"){
-break;
-}
-_23.x1=parseInt(p[1]);
-_23.y1=parseInt(p[2]);
-_23.x2=parseInt(p[4]);
-_23.y2=parseInt(p[5]);
-}while(false);
-};
-var _6=function(_24){
-var _25=_24.shape=dojo.clone(dojox.gfx.defaultPolyline),p=_24.rawNode.path.v.match(dojox.gfx.pathVmlRegExp);
-do{
-if(p.length<3||p[0]!="m"){
-break;
-}
-var x=parseInt(p[0]),y=parseInt(p[1]);
-if(isNaN(x)||isNaN(y)){
-break;
-}
-_25.points.push({x:x,y:y});
-if(p.length<6||p[3]!="l"){
-break;
-}
-for(var i=4;i<p.length;i+=2){
-x=parseInt(p[i]);
-y=parseInt(p[i+1]);
-if(isNaN(x)||isNaN(y)){
-break;
-}
-_25.points.push({x:x,y:y});
-}
-}while(false);
-};
-var _b=function(_26){
-_26.shape=dojo.clone(dojox.gfx.defaultImage);
-_26.shape.src=_26.rawNode.firstChild.src;
-};
-var _c=function(_27){
-var m=_27.rawNode.filters["DXImageTransform.Microsoft.Matrix"];
-_27.matrix=dojox.gfx.matrix.normalize({xx:m.M11,xy:m.M12,yx:m.M21,yy:m.M22,dx:m.Dx,dy:m.Dy});
-};
-var _8=function(_28){
-var _29=_28.shape=dojo.clone(dojox.gfx.defaultText),r=_28.rawNode,p=r.path.v.match(dojox.gfx.pathVmlRegExp);
-do{
-if(!p||p.length!=7){
-break;
-}
-var c=r.childNodes,i=0;
-for(;i<c.length&&c[i].tagName!="textpath";++i){
-}
-if(i>=c.length){
-break;
-}
-var s=c[i].style;
-_29.text=c[i].string;
-switch(s["v-text-align"]){
-case "left":
-_29.x=parseInt(p[1]);
-_29.align="start";
-break;
-case "center":
-_29.x=(parseInt(p[1])+parseInt(p[4]))/2;
-_29.align="middle";
-break;
-case "right":
-_29.x=parseInt(p[4]);
-_29.align="end";
-break;
-}
-_29.y=parseInt(p[2]);
-_29.decoration=s["text-decoration"];
-_29.rotated=s["v-rotate-letters"].toLowerCase() in dojox.gfx.vml._bool;
-_29.kerning=s["v-text-kern"].toLowerCase() in dojox.gfx.vml._bool;
-return;
-}while(false);
-_28.shape=null;
-};
-var _9=function(_2a){
-var _2b=_2a.fontStyle=dojo.clone(dojox.gfx.defaultFont),c=_2a.rawNode.childNodes,i=0;
-for(;i<c.length&&c[i].tagName=="textpath";++i){
-}
-if(i>=c.length){
-_2a.fontStyle=null;
-return;
-}
-var s=c[i].style;
-_2b.style=s.fontstyle;
-_2b.variant=s.fontvariant;
-_2b.weight=s.fontweight;
-_2b.size=s.fontsize;
-_2b.family=s.fontfamily;
-};
-var _a=function(_2c){
-_f(_2c);
-var _2d=_2c.matrix,fs=_2c.fontStyle;
-if(_2d&&fs){
-_2c.matrix=dojox.gfx.matrix.multiply(_2d,{dy:dojox.gfx.normalizedLength(fs.size)*0.35});
-}
-};
-var _7=function(_2e){
-var _2f=_2e.shape=dojo.clone(dojox.gfx.defaultPath),p=_2e.rawNode.path.v.match(dojox.gfx.pathVmlRegExp),t=[],_30=false,map=dojox.gfx.Path._pathVmlToSvgMap;
-for(var i=0;i<p.length;++p){
-var s=p[i];
-if(s in map){
-_30=false;
-t.push(map[s]);
-}else{
-if(!_30){
-var n=parseInt(s);
-if(isNaN(n)){
-_30=true;
-}else{
-t.push(n);
-}
-}
-}
-}
-var l=t.length;
-if(l>=4&&t[l-1]==""&&t[l-2]==0&&t[l-3]==0&&t[l-4]=="l"){
-t.splice(l-4,4);
-}
-if(l){
-_2f.path=t.join(" ");
-}
-};
+	dojox.gfx.attachNode = function(node){
+		// summary: creates a shape from a Node
+		// node: Node: an VML node
+		if(!node) return null;
+		var s = null;
+		switch(node.tagName.toLowerCase()){
+			case dojox.gfx.Rect.nodeType:
+				s = new dojox.gfx.Rect(node);
+				attachRect(s);
+				break;
+			case dojox.gfx.Ellipse.nodeType:
+				if(node.style.width == node.style.height){
+					s = new dojox.gfx.Circle(node);
+					attachCircle(s);
+				}else{
+					s = new dojox.gfx.Ellipse(node);
+					attachEllipse(s);
+				}
+				break;
+			case dojox.gfx.Path.nodeType:
+				switch(node.getAttribute("dojoGfxType")){
+					case "line":
+						s = new dojox.gfx.Line(node);
+						attachLine(s);
+						break;
+					case "polyline":
+						s = new dojox.gfx.Polyline(node);
+						attachPolyline(s);
+						break;
+					case "path":
+						s = new dojox.gfx.Path(node);
+						attachPath(s);
+						break;
+					case "text":
+						s = new dojox.gfx.Text(node);
+						attachText(s);
+						attachFont(s);
+						attachTextTransform(s);
+						break;
+					case "textpath":
+						s = new dojox.gfx.TextPath(node);
+						attachPath(s);
+						attachText(s);
+						attachFont(s);
+						break;
+				}
+				break;
+			case dojox.gfx.Image.nodeType:
+				switch(node.getAttribute("dojoGfxType")){
+					case "image":
+						s = new dojox.gfx.Image(node);
+						attachImage(s);
+						attachImageTransform(s);
+						break;
+				}
+				break;
+			default:
+				//console.debug("FATAL ERROR! tagName = " + node.tagName);
+				return null;
+		}
+		if(!(s instanceof dojox.gfx.Image)){
+			attachFill(s);
+			attachStroke(s);
+			if(!(s instanceof dojox.gfx.Text)){
+				attachTransform(s);
+			}
+		}
+		return s;	// dojox.gfx.Shape
+	};
+
+	dojox.gfx.attachSurface = function(node){
+		// summary: creates a surface from a Node
+		// node: Node: an VML node
+		var s = new dojox.gfx.Surface();
+		s.clipNode = node;
+		var r = s.rawNode = node.firstChild;
+		var b = r.firstChild;
+		if(!b || b.tagName != "rect"){
+			return null;	// dojox.gfx.Surface
+		}
+		s.bgNode = r;
+		return s;	// dojox.gfx.Surface
+	};
+
+	var attachFill = function(object){
+		// summary: deduces a fill style from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		var fillStyle = null, r = object.rawNode, fo = r.fill;
+		if(fo.on && fo.type == "gradient"){
+			var fillStyle = dojo.clone(dojox.gfx.defaultLinearGradient),
+				rad = dojox.gfx.matrix._degToRad(fo.angle);
+			fillStyle.x2 = Math.cos(rad);
+			fillStyle.y2 = Math.sin(rad);
+			fillStyle.colors = [];
+			var stops = fo.colors.value.split(";");
+			for(var i = 0; i < stops.length; ++i){
+				var t = stops[i].match(/\S+/g);
+				if(!t || t.length != 2){ continue; }
+				fillStyle.colors.push({offset: dojox.gfx.vml._parseFloat(t[0]), color: new dojo.Color(t[1])});
+			}
+		}else if(fo.on && fo.type == "gradientradial"){
+			var fillStyle = dojo.clone(dojox.gfx.defaultRadialGradient),
+				w = parseFloat(r.style.width), h = parseFloat(r.style.height);
+			fillStyle.cx = isNaN(w) ? 0 : fo.focusposition.x * w;
+			fillStyle.cy = isNaN(h) ? 0 : fo.focusposition.y * h;
+			fillStyle.r  = isNaN(w) ? 1 : w / 2;
+			fillStyle.colors = [];
+			var stops = fo.colors.value.split(";");
+			for(var i = stops.length - 1; i >= 0; --i){
+				var t = stops[i].match(/\S+/g);
+				if(!t || t.length != 2){ continue; }
+				fillStyle.colors.push({offset: dojox.gfx.vml._parseFloat(t[0]), color: new dojo.Color(t[1])});
+			}
+		}else if(fo.on && fo.type == "tile"){
+			var fillStyle = dojo.clone(dojox.gfx.defaultPattern);
+			fillStyle.width  = dojox.gfx.pt2px(fo.size.x); // from pt
+			fillStyle.height = dojox.gfx.pt2px(fo.size.y); // from pt
+			fillStyle.x = fo.origin.x * fillStyle.width;
+			fillStyle.y = fo.origin.y * fillStyle.height;
+			fillStyle.src = fo.src;
+		}else if(fo.on && r.fillcolor){
+			// a color object !
+			fillStyle = new dojo.Color(r.fillcolor+"");
+			fillStyle.a = fo.opacity;
+		}
+		object.fillStyle = fillStyle;
+	};
+
+	var attachStroke = function(object) {
+		// summary: deduces a stroke style from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		var r = object.rawNode;
+		if(!r.stroked){
+			object.strokeStyle = null;
+			return;
+		}
+		var strokeStyle = object.strokeStyle = dojo.clone(dojox.gfx.defaultStroke),
+			rs = r.stroke;
+		strokeStyle.color = new dojo.Color(r.strokecolor.value);
+		strokeStyle.width = dojox.gfx.normalizedLength(r.strokeweight+"");
+		strokeStyle.color.a = rs.opacity;
+		strokeStyle.cap = this._translate(this._capMapReversed, rs.endcap);
+		strokeStyle.join = rs.joinstyle == "miter" ? rs.miterlimit : rs.joinstyle;
+		strokeStyle.style = rs.dashstyle;
+	};
+
+	var attachTransform = function(object) {
+		// summary: deduces a transformation matrix from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		var s = object.rawNode.skew, sm = s.matrix, so = s.offset;
+		object.matrix = dojox.gfx.matrix.normalize({
+			xx: sm.xtox,
+			xy: sm.ytox,
+			yx: sm.xtoy,
+			yy: sm.ytoy,
+			dx: dojox.gfx.pt2px(so.x),
+			dy: dojox.gfx.pt2px(so.y)
+		});
+	};
+
+	var attachGroup = function(object){
+		// summary: reconstructs all group shape parameters from a node (VML).
+		// object: dojox.gfx.Shape: an VML shape
+		// attach the background
+		object.bgNode = object.rawNode.firstChild;	// TODO: check it first
+	};
+
+	var attachRect = function(object){
+		// summary: builds a rectangle shape from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		// a workaround for the VML's arcsize bug: cannot read arcsize of an instantiated node
+		var r = object.rawNode, arcsize = r.outerHTML.match(/arcsize = \"(\d*\.?\d+[%f]?)\"/)[1],
+			style = r.style, width = parseFloat(style.width), height = parseFloat(style.height);
+		arcsize = (arcsize.indexOf("%") >= 0) ? parseFloat(arcsize) / 100 : dojox.gfx.vml._parseFloat(arcsize);
+		// make an object
+		object.shape = dojox.gfx.makeParameters(dojox.gfx.defaultRect, {
+			x: parseInt(style.left),
+			y: parseInt(style.top),
+			width:  width,
+			height: height,
+			r: Math.min(width, height) * arcsize
+		});
+	};
+
+	var attachEllipse = function(object){
+		// summary: builds an ellipse shape from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		var style = object.rawNode.style,
+			rx = parseInt(style.width ) / 2,
+			ry = parseInt(style.height) / 2;
+		object.shape = dojox.gfx.makeParameters(dojox.gfx.defaultEllipse, {
+			cx: parseInt(style.left) + rx,
+			cy: parseInt(style.top ) + ry,
+			rx: rx,
+			ry: ry
+		});
+	};
+
+	var attachCircle = function(object){
+		// summary: builds a circle shape from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		var style = object.rawNode.style, r = parseInt(style.width) / 2;
+		object.shape = dojox.gfx.makeParameters(dojox.gfx.defaultCircle, {
+			cx: parseInt(style.left) + r,
+			cy: parseInt(style.top)  + r,
+			r:  r
+		});
+	};
+
+	var attachLine = function(object){
+		// summary: builds a line shape from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		var shape = object.shape = dojo.clone(dojox.gfx.defaultLine),
+			p = object.rawNode.path.v.match(dojox.gfx.pathVmlRegExp);
+		do{
+			if(p.length < 7 || p[0] != "m" || p[3] != "l" || p[6] != "e"){ break; }
+			shape.x1 = parseInt(p[1]);
+			shape.y1 = parseInt(p[2]);
+			shape.x2 = parseInt(p[4]);
+			shape.y2 = parseInt(p[5]);
+		}while(false);
+	};
+
+	var attachPolyline = function(object){
+		// summary: builds a polyline/polygon shape from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		var shape = object.shape = dojo.clone(dojox.gfx.defaultPolyline),
+			p = object.rawNode.path.v.match(dojox.gfx.pathVmlRegExp);
+		do{
+			if(p.length < 3 || p[0] != "m"){ break; }
+			var x = parseInt(p[0]), y = parseInt(p[1]);
+			if(isNaN(x) || isNaN(y)){ break; }
+			shape.points.push({x: x, y: y});
+			if(p.length < 6 || p[3] != "l"){ break; }
+			for(var i = 4; i < p.length; i += 2){
+				x = parseInt(p[i]);
+				y = parseInt(p[i + 1]);
+				if(isNaN(x) || isNaN(y)){ break; }
+				shape.points.push({x: x, y: y});
+			}
+		}while(false);
+	};
+
+	var attachImage = function(object){
+		// summary: builds an image shape from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		object.shape = dojo.clone(dojox.gfx.defaultImage);
+		object.shape.src = object.rawNode.firstChild.src;
+	};
+
+	var attachImageTransform = function(object) {
+		// summary: deduces a transformation matrix from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		var m = object.rawNode.filters["DXImageTransform.Microsoft.Matrix"];
+		object.matrix = dojox.gfx.matrix.normalize({
+			xx: m.M11,
+			xy: m.M12,
+			yx: m.M21,
+			yy: m.M22,
+			dx: m.Dx,
+			dy: m.Dy
+		});
+	};
+
+	var attachText = function(object){
+		// summary: builds a text shape from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		var shape = object.shape = dojo.clone(dojox.gfx.defaultText),
+			r = object.rawNode, p = r.path.v.match(dojox.gfx.pathVmlRegExp);
+		do{
+			if(!p || p.length != 7){ break; }
+			var c = r.childNodes, i = 0;
+			for(; i < c.length && c[i].tagName != "textpath"; ++i);
+			if(i >= c.length){ break; }
+			var s = c[i].style;
+			shape.text = c[i].string;
+			switch(s["v-text-align"]){
+				case "left":
+					shape.x = parseInt(p[1]);
+					shape.align = "start";
+					break;
+				case "center":
+					shape.x = (parseInt(p[1]) + parseInt(p[4])) / 2;
+					shape.align = "middle";
+					break;
+				case "right":
+					shape.x = parseInt(p[4]);
+					shape.align = "end";
+					break;
+			}
+			shape.y = parseInt(p[2]);
+			shape.decoration = s["text-decoration"];
+			shape.rotated = s["v-rotate-letters"].toLowerCase() in dojox.gfx.vml._bool;
+			shape.kerning = s["v-text-kern"].toLowerCase() in dojox.gfx.vml._bool;
+			return;
+		}while(false);
+		object.shape = null;
+	};
+
+	var attachFont = function(object){
+		// summary: deduces a font style from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		var fontStyle = object.fontStyle = dojo.clone(dojox.gfx.defaultFont),
+			c = object.rawNode.childNodes, i = 0;
+		for(; i < c.length && c[i].tagName == "textpath"; ++i);
+		if(i >= c.length){
+			object.fontStyle = null;
+			return;
+		}
+		var s = c[i].style;
+		fontStyle.style = s.fontstyle;
+		fontStyle.variant = s.fontvariant;
+		fontStyle.weight = s.fontweight;
+		fontStyle.size = s.fontsize;
+		fontStyle.family = s.fontfamily;
+	};
+
+	var attachTextTransform = function(object) {
+		// summary: deduces a transformation matrix from a node.
+		// object: dojox.gfx.Shape: an VML shape
+		attachTransform(object);
+		var matrix = object.matrix, fs = object.fontStyle;
+		// see comments in _getRealMatrix()
+		if(matrix && fs){
+			object.matrix = dojox.gfx.matrix.multiply(matrix, {dy: dojox.gfx.normalizedLength(fs.size) * 0.35});
+		}
+	};
+
+	var attachPath = function(object){
+		// summary: builds a path shape from a Node.
+		// object: dojox.gfx.Shape: an VML shape
+		var shape = object.shape = dojo.clone(dojox.gfx.defaultPath),
+			p = object.rawNode.path.v.match(dojox.gfx.pathVmlRegExp),
+			t = [], skip = false, map = dojox.gfx.Path._pathVmlToSvgMap;
+		for(var i = 0; i < p.length; ++p){
+			var s = p[i];
+			if(s in map) {
+				skip = false;
+				t.push(map[s]);
+			} else if(!skip){
+				var n = parseInt(s);
+				if(isNaN(n)){
+					skip = true;
+				}else{
+					t.push(n);
+				}
+			}
+		}
+		var l = t.length;
+		if(l >= 4 && t[l - 1] == "" && t[l - 2] == 0 && t[l - 3] == 0 && t[l - 4] == "l"){
+			t.splice(l - 4, 4);
+		}
+		if(l){
+			shape.path = t.join(" ");
+		}
+	};
 })();
diff --git a/dojox/gfx3d.js b/dojox/gfx3d.js
index 3bab8ac..c6aee36 100644
--- a/dojox/gfx3d.js
+++ b/dojox/gfx3d.js
@@ -1,14 +1,7 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx3d"]){
-dojo._hasResource["dojox.gfx3d"]=true;
 dojo.provide("dojox.gfx3d");
+
 dojo.require("dojox.gfx3d.matrix");
 dojo.require("dojox.gfx3d._base");
 dojo.require("dojox.gfx3d.object");
-}
+
+
diff --git a/dojox/gfx3d/_base.js b/dojox/gfx3d/_base.js
index 7f1a6c3..393b0a4 100644
--- a/dojox/gfx3d/_base.js
+++ b/dojox/gfx3d/_base.js
@@ -1,12 +1,15 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx3d._base"]){
-dojo._hasResource["dojox.gfx3d._base"]=true;
 dojo.provide("dojox.gfx3d._base");
-dojo.mixin(dojox.gfx3d,{defaultEdges:{type:"edges",style:null,points:[]},defaultTriangles:{type:"triangles",style:null,points:[]},defaultQuads:{type:"quads",style:null,points:[]},defaultOrbit:{type:"orbit",center:{x:0,y:0,z:0},radius:50},defaultPath3d:{type:"path3d",path:[]},defaultPolygon:{type:"polygon",path:[]},defaultCube:{type:"cube",bottom:{x:0,y:0,z:0},top:{x:100,y:100,z:100}},defaultCylinder:{type:"cylinder",center:{x:0,y:0,z:0},height:100,radius:50}});
-}
+
+dojo.mixin(dojox.gfx3d, {
+	// summary: defines constants, prototypes, and utility functions
+	
+	// default objects, which are used to fill in missing parameters
+	defaultEdges:	  {type: "edges",     style: null, points: []},
+	defaultTriangles: {type: "triangles", style: null, points: []},
+	defaultQuads:	  {type: "quads",     style: null, points: []},
+	defaultOrbit:	  {type: "orbit",     center: {x: 0, y: 0, z: 0}, radius: 50},
+	defaultPath3d:	  {type: "path3d",    path: []},
+	defaultPolygon:	  {type: "polygon",   path: []},
+	defaultCube:	  {type: "cube",      bottom: {x: 0, y: 0, z: 0}, top: {x: 100, y: 100, z: 100}},
+	defaultCylinder:  {type: "cylinder",  center: /* center of bottom */ {x: 0, y: 0, z: 0}, height: 100, radius: 50}
+});
diff --git a/dojox/gfx3d/gradient.js b/dojox/gfx3d/gradient.js
index a6080e0..bf22861 100644
--- a/dojox/gfx3d/gradient.js
+++ b/dojox/gfx3d/gradient.js
@@ -1,28 +1,37 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx3d.gradient"]){
-dojo._hasResource["dojox.gfx3d.gradient"]=true;
 dojo.provide("dojox.gfx3d.gradient");
+
 dojo.require("dojox.gfx3d.vector");
 dojo.require("dojox.gfx3d.matrix");
+
 (function(){
-var _1=function(a,b){
-return Math.sqrt(Math.pow(b.x-a.x,2)+Math.pow(b.y-a.y,2));
-};
-var N=32;
-dojox.gfx3d.gradient=function(_2,_3,_4,_5,_6,to,_7){
-var m=dojox.gfx3d.matrix,v=dojox.gfx3d.vector,mx=m.normalize(_7),f=m.multiplyPoint(mx,_5*Math.cos(_6)+_4.x,_5*Math.sin(_6)+_4.y,_4.z),t=m.multiplyPoint(mx,_5*Math.cos(to)+_4.x,_5*Math.sin(to)+_4.y,_4.z),c=m.multiplyPoint(mx,_4.x,_4.y,_4.z),_8=(to-_6)/N,r=_1(f,t)/2,_9=_2[_3.type],_a=_3.finish,_b=_3.color,_c=[{offset:0,color:_9.call(_2,v.substract(f,c),_a,_b)}];
-for(var a=_6+_8;a<to;a+=_8){
-var p=m.multiplyPoint(mx,_5*Math.cos(a)+_4.x,_5*Math.sin(a)+_4.y,_4.z),df=_1(f,p),dt=_1(t,p);
-_c.push({offset:df/(df+dt),color:_9.call(_2,v.substract(p,c),_a,_b)});
-}
-_c.push({offset:1,color:_9.call(_2,v.substract(t,c),_a,_b)});
-return {type:"linear",x1:0,y1:-r,x2:0,y2:r,colors:_c};
-};
+	var dist = function(a, b){ return Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2)); };
+	var N = 32;
+
+	dojox.gfx3d.gradient = function(model, material, center, radius, from, to, matrix){
+		// summary: calculate a cylindrical gradient
+		// model: dojox.gfx3d.lighting.Model: color model
+		// material: Object: defines visual properties
+		// center: Object: center of the cylinder's bottom
+		// radius: Number: radius of the cylinder
+		// from: Number: from position in radians
+		// to: Number: from position in radians
+		// matrix: dojox.gfx3d.Matrix3D: the cumulative transformation matrix
+		// tolerance: Number: tolerable diffirence in colors between gradient steps
+
+		var m = dojox.gfx3d.matrix, v = dojox.gfx3d.vector, mx = m.normalize(matrix),
+			f = m.multiplyPoint(mx, radius * Math.cos(from) + center.x, radius * Math.sin(from) + center.y, center.z),
+			t = m.multiplyPoint(mx, radius * Math.cos(to)   + center.x, radius * Math.sin(to)   + center.y, center.z),
+			c = m.multiplyPoint(mx, center.x, center.y, center.z), step = (to - from) / N, r = dist(f, t) / 2,
+			mod = model[material.type], fin = material.finish, pmt = material.color,
+			colors = [{offset: 0, color: mod.call(model, v.substract(f, c), fin, pmt)}];
+
+		for(var a = from + step; a < to; a += step){
+			var p = m.multiplyPoint(mx, radius * Math.cos(a) + center.x, radius * Math.sin(a) + center.y, center.z),
+				df = dist(f, p), dt = dist(t, p);
+			colors.push({offset: df / (df + dt), color: mod.call(model, v.substract(p, c), fin, pmt)});
+		}
+		colors.push({offset: 1, color: mod.call(model, v.substract(t, c), fin, pmt)});
+
+		return {type: "linear", x1: 0, y1: -r, x2: 0, y2: r, colors: colors};
+	};
 })();
-}
diff --git a/dojox/gfx3d/lighting.js b/dojox/gfx3d/lighting.js
index dd99fbe..de4f495 100644
--- a/dojox/gfx3d/lighting.js
+++ b/dojox/gfx3d/lighting.js
@@ -1,158 +1,237 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx3d.lighting"]){
-dojo._hasResource["dojox.gfx3d.lighting"]=true;
 dojo.provide("dojox.gfx3d.lighting");
 dojo.require("dojox.gfx._base");
+
 (function(){
-var _1=dojox.gfx3d.lighting;
-dojo.mixin(dojox.gfx3d.lighting,{black:function(){
-return {r:0,g:0,b:0,a:1};
-},white:function(){
-return {r:1,g:1,b:1,a:1};
-},toStdColor:function(c){
-c=dojox.gfx.normalizeColor(c);
-return {r:c.r/255,g:c.g/255,b:c.b/255,a:c.a};
-},fromStdColor:function(c){
-return new dojo.Color([Math.round(255*c.r),Math.round(255*c.g),Math.round(255*c.b),c.a]);
-},scaleColor:function(s,c){
-return {r:s*c.r,g:s*c.g,b:s*c.b,a:s*c.a};
-},addColor:function(a,b){
-return {r:a.r+b.r,g:a.g+b.g,b:a.b+b.b,a:a.a+b.a};
-},multiplyColor:function(a,b){
-return {r:a.r*b.r,g:a.g*b.g,b:a.b*b.b,a:a.a*b.a};
-},saturateColor:function(c){
-return {r:c.r<0?0:c.r>1?1:c.r,g:c.g<0?0:c.g>1?1:c.g,b:c.b<0?0:c.b>1?1:c.b,a:c.a<0?0:c.a>1?1:c.a};
-},mixColor:function(c1,c2,s){
-return _1.addColor(_1.scaleColor(s,c1),_1.scaleColor(1-s,c2));
-},diff2Color:function(c1,c2){
-var r=c1.r-c2.r;
-var g=c1.g-c2.g;
-var b=c1.b-c2.b;
-var a=c1.a-c2.a;
-return r*r+g*g+b*b+a*a;
-},length2Color:function(c){
-return c.r*c.r+c.g*c.g+c.b*c.b+c.a*c.a;
-},dot:function(a,b){
-return a.x*b.x+a.y*b.y+a.z*b.z;
-},scale:function(s,v){
-return {x:s*v.x,y:s*v.y,z:s*v.z};
-},add:function(a,b){
-return {x:a.x+b.x,y:a.y+b.y,z:a.z+b.z};
-},saturate:function(v){
-return Math.min(Math.max(v,0),1);
-},length:function(v){
-return Math.sqrt(dojox.gfx3d.lighting.dot(v,v));
-},normalize:function(v){
-return _1.scale(1/_1.length(v),v);
-},faceforward:function(n,i){
-var p=dojox.gfx3d.lighting;
-var s=p.dot(i,n)<0?1:-1;
-return p.scale(s,n);
-},reflect:function(i,n){
-var p=dojox.gfx3d.lighting;
-return p.add(i,p.scale(-2*p.dot(i,n),n));
-},diffuse:function(_2,_3){
-var c=_1.black();
-for(var i=0;i<_3.length;++i){
-var l=_3[i],d=_1.dot(_1.normalize(l.direction),_2);
-c=_1.addColor(c,_1.scaleColor(d,l.color));
-}
-return _1.saturateColor(c);
-},specular:function(_4,v,_5,_6){
-var c=_1.black();
-for(var i=0;i<_6.length;++i){
-var l=_6[i],h=_1.normalize(_1.add(_1.normalize(l.direction),v)),s=Math.pow(Math.max(0,_1.dot(_4,h)),1/_5);
-c=_1.addColor(c,_1.scaleColor(s,l.color));
-}
-return _1.saturateColor(c);
-},phong:function(_7,v,_8,_9){
-_7=_1.normalize(_7);
-var c=_1.black();
-for(var i=0;i<_9.length;++i){
-var l=_9[i],r=_1.reflect(_1.scale(-1,_1.normalize(v)),_7),s=Math.pow(Math.max(0,_1.dot(r,_1.normalize(l.direction))),_8);
-c=_1.addColor(c,_1.scaleColor(s,l.color));
-}
-return _1.saturateColor(c);
-}});
-dojo.declare("dojox.gfx3d.lighting.Model",null,{constructor:function(_a,_b,_c,_d){
-this.incident=_1.normalize(_a);
-this.lights=[];
-for(var i=0;i<_b.length;++i){
-var l=_b[i];
-this.lights.push({direction:_1.normalize(l.direction),color:_1.toStdColor(l.color)});
-}
-this.ambient=_1.toStdColor(_c.color?_c.color:"white");
-this.ambient=_1.scaleColor(_c.intensity,this.ambient);
-this.ambient=_1.scaleColor(this.ambient.a,this.ambient);
-this.ambient.a=1;
-this.specular=_1.toStdColor(_d?_d:"white");
-this.specular=_1.scaleColor(this.specular.a,this.specular);
-this.specular.a=1;
-this.npr_cool={r:0,g:0,b:0.4,a:1};
-this.npr_warm={r:0.4,g:0.4,b:0.2,a:1};
-this.npr_alpha=0.2;
-this.npr_beta=0.6;
-this.npr_scale=0.6;
-},constant:function(_e,_f,_10){
-_10=_1.toStdColor(_10);
-var _11=_10.a,_12=_1.scaleColor(_11,_10);
-_12.a=_11;
-return _1.fromStdColor(_1.saturateColor(_12));
-},matte:function(_13,_14,_15){
-if(typeof _14=="string"){
-_14=_1.finish[_14];
-}
-_15=_1.toStdColor(_15);
-_13=_1.faceforward(_1.normalize(_13),this.incident);
-var _16=_1.scaleColor(_14.Ka,this.ambient),_17=_1.saturate(-4*_1.dot(_13,this.incident)),_18=_1.scaleColor(_17*_14.Kd,_1.diffuse(_13,this.lights)),_19=_1.scaleColor(_15.a,_1.multiplyColor(_15,_1.addColor(_16,_18)));
-_19.a=_15.a;
-return _1.fromStdColor(_1.saturateColor(_19));
-},metal:function(_1a,_1b,_1c){
-if(typeof _1b=="string"){
-_1b=_1.finish[_1b];
-}
-_1c=_1.toStdColor(_1c);
-_1a=_1.faceforward(_1.normalize(_1a),this.incident);
-var v=_1.scale(-1,this.incident),_1d,_1e,_1f=_1.scaleColor(_1b.Ka,this.ambient),_20=_1.saturate(-4*_1.dot(_1a,this.incident));
-if("phong" in _1b){
-_1d=_1.scaleColor(_20*_1b.Ks*_1b.phong,_1.phong(_1a,v,_1b.phong_size,this.lights));
-}else{
-_1d=_1.scaleColor(_20*_1b.Ks,_1.specular(_1a,v,_1b.roughness,this.lights));
-}
-_1e=_1.scaleColor(_1c.a,_1.addColor(_1.multiplyColor(_1c,_1f),_1.multiplyColor(this.specular,_1d)));
-_1e.a=_1c.a;
-return _1.fromStdColor(_1.saturateColor(_1e));
-},plastic:function(_21,_22,_23){
-if(typeof _22=="string"){
-_22=_1.finish[_22];
-}
-_23=_1.toStdColor(_23);
-_21=_1.faceforward(_1.normalize(_21),this.incident);
-var v=_1.scale(-1,this.incident),_24,_25,_26=_1.scaleColor(_22.Ka,this.ambient),_27=_1.saturate(-4*_1.dot(_21,this.incident)),_28=_1.scaleColor(_27*_22.Kd,_1.diffuse(_21,this.lights));
-if("phong" in _22){
-_24=_1.scaleColor(_27*_22.Ks*_22.phong,_1.phong(_21,v,_22.phong_size,this.lights));
-}else{
-_24=_1.scaleColor(_27*_22.Ks,_1.specular(_21,v,_22.roughness,this.lights));
-}
-_25=_1.scaleColor(_23.a,_1.addColor(_1.multiplyColor(_23,_1.addColor(_26,_28)),_1.multiplyColor(this.specular,_24)));
-_25.a=_23.a;
-return _1.fromStdColor(_1.saturateColor(_25));
-},npr:function(_29,_2a,_2b){
-if(typeof _2a=="string"){
-_2a=_1.finish[_2a];
-}
-_2b=_1.toStdColor(_2b);
-_29=_1.faceforward(_1.normalize(_29),this.incident);
-var _2c=_1.scaleColor(_2a.Ka,this.ambient),_2d=_1.saturate(-4*_1.dot(_29,this.incident)),_2e=_1.scaleColor(_2d*_2a.Kd,_1.diffuse(_29,this.lights)),_2f=_1.scaleColor(_2b.a,_1.multiplyColor(_2b,_1.addColor(_2c,_2e))),_30=_1.addColor(this.npr_cool,_1.scaleColor(this.npr_alpha,_2f)),_31=_1.addColor(this.npr_warm,_1.scaleColor(this.npr_beta,_2f)),d=(1+_1.dot(this.incident,_29))/2,_2f=_1.scaleColor(this.npr_scale,_1.addColor(_2f,_1.mixColor(_30,_31,d)));
-_2f.a=_2b.a;
-return _1.fromStdColor(_1.saturateColor(_2f));
-}});
+	var lite = dojox.gfx3d.lighting;
+
+	dojo.mixin(dojox.gfx3d.lighting, {
+		// color utilities
+		black: function(){
+			return {r: 0, g: 0, b: 0, a: 1};
+		},
+		white: function(){
+			return {r: 1, g: 1, b: 1, a: 1};
+		},
+		toStdColor: function(c){
+			c = dojox.gfx.normalizeColor(c);
+			return {r: c.r / 255, g: c.g / 255, b: c.b / 255, a: c.a};
+		},
+		fromStdColor: function(c){
+			return new dojo.Color([Math.round(255 * c.r), Math.round(255 * c.g), Math.round(255 * c.b), c.a]);
+		},
+		scaleColor: function(s, c){
+			return {r: s * c.r, g: s * c.g, b: s * c.b, a: s * c.a};
+		},
+		addColor: function(a, b){
+			return {r: a.r + b.r, g: a.g + b.g, b: a.b + b.b, a: a.a + b.a};
+		},
+		multiplyColor: function(a, b){
+			return {r: a.r * b.r, g: a.g * b.g, b: a.b * b.b, a: a.a * b.a};
+		},
+		saturateColor: function(c){
+			return {
+				r: c.r < 0 ? 0 : c.r > 1 ? 1 : c.r,
+				g: c.g < 0 ? 0 : c.g > 1 ? 1 : c.g,
+				b: c.b < 0 ? 0 : c.b > 1 ? 1 : c.b,
+				a: c.a < 0 ? 0 : c.a > 1 ? 1 : c.a
+			};
+		},
+		mixColor: function(c1, c2, s){
+			return lite.addColor(lite.scaleColor(s, c1), lite.scaleColor(1 - s, c2));
+		},
+		diff2Color: function(c1, c2){
+			var r = c1.r - c2.r;
+			var g = c1.g - c2.g;
+			var b = c1.b - c2.b;
+			var a = c1.a - c2.a;
+			return r * r + g * g + b * b + a * a;
+		},
+		length2Color: function(c){
+			return c.r * c.r + c.g * c.g + c.b * c.b + c.a * c.a;
+		},
+		
+		// vector utilities
+		//TODO: move vector utilities from this file to vector.js
+		dot: function(a, b){
+			return a.x * b.x + a.y * b.y + a.z * b.z;
+		},
+		scale: function(s, v){
+			return {x: s * v.x, y: s * v.y, z: s * v.z};
+		},
+		add: function(a, b){
+			return {x: a.x + b.x, y: a.y + b.y, z: a.z + b.z};
+		},
+		saturate: function(v){
+			return Math.min(Math.max(v, 0), 1);
+		},
+		length: function(v){
+			return Math.sqrt(dojox.gfx3d.lighting.dot(v, v));
+		},
+		normalize: function(v){
+			return lite.scale(1 / lite.length(v), v);
+		},
+		faceforward: function(n, i){
+			var p = dojox.gfx3d.lighting;
+			var s = p.dot(i, n) < 0 ? 1 : -1;
+			return p.scale(s, n);
+		},
+		reflect: function(i, n){
+			var p = dojox.gfx3d.lighting;
+			return p.add(i, p.scale(-2 * p.dot(i, n), n));
+		},
+		
+		// lighting utilities
+		diffuse: function(normal, lights){
+			var c = lite.black();
+			for(var i = 0; i < lights.length; ++i){
+				var l = lights[i],
+					d = lite.dot(lite.normalize(l.direction), normal);
+				c = lite.addColor(c, lite.scaleColor(d, l.color));
+			}
+			return lite.saturateColor(c);
+		},
+		specular: function(normal, v, roughness, lights){
+			var c = lite.black();
+			for(var i = 0; i < lights.length; ++i){
+				var l = lights[i], 
+					h = lite.normalize(lite.add(lite.normalize(l.direction), v)),
+					s = Math.pow(Math.max(0, lite.dot(normal, h)), 1 / roughness);
+				c = lite.addColor(c, lite.scaleColor(s, l.color));
+			}
+			return lite.saturateColor(c);
+		},
+		phong: function(normal, v, size, lights){
+			normal = lite.normalize(normal);
+			var c = lite.black();
+			for(var i = 0; i < lights.length; ++i){
+				var l = lights[i],
+					r = lite.reflect(lite.scale(-1, lite.normalize(v)), normal),
+					s = Math.pow(Math.max(0, lite.dot(r, lite.normalize(l.direction))), size);
+				c = lite.addColor(c, lite.scaleColor(s, l.color));
+			}
+			return lite.saturateColor(c);
+		}
+	});
+
+	// this lighting model is derived from RenderMan Interface Specification Version 3.2
+
+	dojo.declare("dojox.gfx3d.lighting.Model", null, {
+		constructor: function(incident, lights, ambient, specular){
+			this.incident = lite.normalize(incident);
+			this.lights = [];
+			for(var i = 0; i < lights.length; ++i){
+				var l = lights[i];
+				this.lights.push({direction: lite.normalize(l.direction), color: lite.toStdColor(l.color)});
+			}
+			this.ambient = lite.toStdColor(ambient.color ? ambient.color : "white");
+			this.ambient = lite.scaleColor(ambient.intensity, this.ambient);
+			this.ambient = lite.scaleColor(this.ambient.a, this.ambient);
+			this.ambient.a = 1;
+			this.specular = lite.toStdColor(specular ? specular : "white");
+			this.specular = lite.scaleColor(this.specular.a, this.specular);
+			this.specular.a = 1;
+			this.npr_cool = {r: 0,   g: 0,   b: 0.4, a: 1};
+			this.npr_warm = {r: 0.4, g: 0.4, b: 0.2, a: 1};
+			this.npr_alpha = 0.2;
+			this.npr_beta  = 0.6;
+			this.npr_scale = 0.6;
+		},
+		constant: function(normal, finish, pigment){
+			pigment   = lite.toStdColor(pigment);
+			var alpha = pigment.a, color = lite.scaleColor(alpha, pigment);
+			color.a   = alpha;
+			return lite.fromStdColor(lite.saturateColor(color));
+		},
+		matte: function(normal, finish, pigment){
+			if(typeof finish == "string"){ finish = lite.finish[finish]; }
+			pigment = lite.toStdColor(pigment);
+			normal  = lite.faceforward(lite.normalize(normal), this.incident);
+			var ambient = lite.scaleColor(finish.Ka, this.ambient),
+				shadow  = lite.saturate(-4 * lite.dot(normal, this.incident)),
+				diffuse = lite.scaleColor(shadow * finish.Kd, lite.diffuse(normal, this.lights)),
+				color   = lite.scaleColor(pigment.a, lite.multiplyColor(pigment, lite.addColor(ambient, diffuse)));
+			color.a = pigment.a;
+			return lite.fromStdColor(lite.saturateColor(color));
+		},
+		metal: function(normal, finish, pigment){
+			if(typeof finish == "string"){ finish = lite.finish[finish]; }
+			pigment = lite.toStdColor(pigment);
+			normal  = lite.faceforward(lite.normalize(normal), this.incident);
+			var v = lite.scale(-1, this.incident), specular, color,
+				ambient = lite.scaleColor(finish.Ka, this.ambient),
+				shadow  = lite.saturate(-4 * lite.dot(normal, this.incident));
+			if("phong" in finish){
+				specular = lite.scaleColor(shadow * finish.Ks * finish.phong, lite.phong(normal, v, finish.phong_size, this.lights));
+			}else{
+				specular = lite.scaleColor(shadow * finish.Ks, lite.specular(normal, v, finish.roughness, this.lights));
+			}
+			color = lite.scaleColor(pigment.a, lite.addColor(lite.multiplyColor(pigment, ambient), lite.multiplyColor(this.specular, specular)));
+			color.a = pigment.a;
+			return lite.fromStdColor(lite.saturateColor(color));
+		},
+		plastic: function(normal, finish, pigment){
+			if(typeof finish == "string"){ finish = lite.finish[finish]; }
+			pigment = lite.toStdColor(pigment);
+			normal  = lite.faceforward(lite.normalize(normal), this.incident);
+			var v = lite.scale(-1, this.incident), specular, color,
+				ambient = lite.scaleColor(finish.Ka, this.ambient),
+				shadow  = lite.saturate(-4 * lite.dot(normal, this.incident)),
+				diffuse = lite.scaleColor(shadow * finish.Kd, lite.diffuse(normal, this.lights));
+			if("phong" in finish){
+				specular = lite.scaleColor(shadow * finish.Ks * finish.phong, lite.phong(normal, v, finish.phong_size, this.lights));
+			}else{
+				specular = lite.scaleColor(shadow * finish.Ks, lite.specular(normal, v, finish.roughness, this.lights));
+			}
+			color = lite.scaleColor(pigment.a, lite.addColor(lite.multiplyColor(pigment, lite.addColor(ambient, diffuse)), lite.multiplyColor(this.specular, specular)));
+			color.a = pigment.a;
+			return lite.fromStdColor(lite.saturateColor(color));
+		},
+		npr: function(normal, finish, pigment){
+			if(typeof finish == "string"){ finish = lite.finish[finish]; }
+			pigment = lite.toStdColor(pigment);
+			normal  = lite.faceforward(lite.normalize(normal), this.incident);
+			var ambient  = lite.scaleColor(finish.Ka, this.ambient),
+				shadow   = lite.saturate(-4 * lite.dot(normal, this.incident)),
+				diffuse  = lite.scaleColor(shadow * finish.Kd, lite.diffuse(normal, this.lights)),
+				color = lite.scaleColor(pigment.a, lite.multiplyColor(pigment, lite.addColor(ambient, diffuse))),
+				cool = lite.addColor(this.npr_cool, lite.scaleColor(this.npr_alpha, color)),
+				warm = lite.addColor(this.npr_warm, lite.scaleColor(this.npr_beta,  color)),
+				d = (1 + lite.dot(this.incident, normal)) / 2,
+				color = lite.scaleColor(this.npr_scale, lite.addColor(color, lite.mixColor(cool, warm, d)));
+			color.a = pigment.a;
+			return lite.fromStdColor(lite.saturateColor(color));
+		}
+	});
 })();
-dojox.gfx3d.lighting.finish={defaults:{Ka:0.1,Kd:0.6,Ks:0,roughness:0.05},dull:{Ka:0.1,Kd:0.6,Ks:0.5,roughness:0.15},shiny:{Ka:0.1,Kd:0.6,Ks:1,roughness:0.001},glossy:{Ka:0.1,Kd:0.6,Ks:1,roughness:0.0001},phong_dull:{Ka:0.1,Kd:0.6,Ks:0.5,phong:0.5,phong_size:1},phong_shiny:{Ka:0.1,Kd:0.6,Ks:1,phong:1,phong_size:200},phong_glossy:{Ka:0.1,Kd:0.6,Ks:1,phong:1,phong_size:300},luminous:{Ka:1,Kd:0,Ks:0,roughness:0.05},metalA:{Ka:0.35,Kd:0.3,Ks:0.8,roughness:1/20},metalB:{Ka:0.3,Kd:0.4,Ks:0.7,r [...]
-}
+
+// POV-Ray basic finishes
+
+dojox.gfx3d.lighting.finish = {
+
+	// Default
+	
+	defaults: {Ka: 0.1, Kd: 0.6, Ks: 0.0, roughness: 0.05},
+	
+	dull:     {Ka: 0.1, Kd: 0.6, Ks: 0.5, roughness: 0.15},
+	shiny:    {Ka: 0.1, Kd: 0.6, Ks: 1.0, roughness: 0.001},
+	glossy:   {Ka: 0.1, Kd: 0.6, Ks: 1.0, roughness: 0.0001},
+	
+	phong_dull:   {Ka: 0.1, Kd: 0.6, Ks: 0.5, phong: 0.5, phong_size: 1},
+	phong_shiny:  {Ka: 0.1, Kd: 0.6, Ks: 1.0, phong: 1.0, phong_size: 200},
+	phong_glossy: {Ka: 0.1, Kd: 0.6, Ks: 1.0, phong: 1.0, phong_size: 300},
+
+	luminous: {Ka: 1.0, Kd: 0.0, Ks: 0.0, roughness: 0.05},
+
+	// Metals
+
+	// very soft and dull
+	metalA: {Ka: 0.35, Kd: 0.3, Ks: 0.8, roughness: 1/20},
+	// fairly soft and dull
+	metalB: {Ka: 0.30, Kd: 0.4, Ks: 0.7, roughness: 1/60},
+	// medium reflectivity, holds color well
+	metalC: {Ka: 0.25, Kd: 0.5, Ks: 0.8, roughness: 1/80},
+	// highly hard and polished, high reflectivity
+	metalD: {Ka: 0.15, Kd: 0.6, Ks: 0.8, roughness: 1/100},
+	// very highly polished and reflective
+	metalE: {Ka: 0.10, Kd: 0.7, Ks: 0.8, roughness: 1/120}
+};
diff --git a/dojox/gfx3d/matrix.js b/dojox/gfx3d/matrix.js
index 7934e61..6c1a2de 100644
--- a/dojox/gfx3d/matrix.js
+++ b/dojox/gfx3d/matrix.js
@@ -1,158 +1,335 @@
-/*
-	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
-*/
+dojo.provide("dojox.gfx3d.matrix");
 
+// candidates for dojox.math:
+dojox.gfx3d.matrix._degToRad = function(degree){ return Math.PI * degree / 180; };
+dojox.gfx3d.matrix._radToDeg = function(radian){ return radian / Math.PI * 180; };
 
-if(!dojo._hasResource["dojox.gfx3d.matrix"]){
-dojo._hasResource["dojox.gfx3d.matrix"]=true;
-dojo.provide("dojox.gfx3d.matrix");
-dojox.gfx3d.matrix._degToRad=function(_1){
-return Math.PI*_1/180;
-};
-dojox.gfx3d.matrix._radToDeg=function(_2){
-return _2/Math.PI*180;
+dojox.gfx3d.matrix.Matrix3D = function(arg){
+	// summary: a 3D matrix object
+	// description: Normalizes a 3D matrix-like object. If arrays is passed, 
+	//		all objects of the array are normalized and multiplied sequentially.
+	// arg: Object
+	//		a 3D matrix-like object, a number, or an array of such objects
+	if(arg){
+		if(typeof arg == "number"){
+			this.xx = this.yy = this.zz = arg;
+		}else if(arg instanceof Array){
+			if(arg.length > 0){
+				var m = dojox.gfx3d.matrix.normalize(arg[0]);
+				// combine matrices
+				for(var i = 1; i < arg.length; ++i){
+					var l = m;
+					var r = dojox.gfx3d.matrix.normalize(arg[i]);
+					m = new dojox.gfx3d.matrix.Matrix3D();
+					m.xx = l.xx * r.xx + l.xy * r.yx + l.xz * r.zx;
+					m.xy = l.xx * r.xy + l.xy * r.yy + l.xz * r.zy;
+					m.xz = l.xx * r.xz + l.xy * r.yz + l.xz * r.zz;
+					m.yx = l.yx * r.xx + l.yy * r.yx + l.yz * r.zx;
+					m.yy = l.yx * r.xy + l.yy * r.yy + l.yz * r.zy;
+					m.yz = l.yx * r.xz + l.yy * r.yz + l.yz * r.zz;
+					m.zx = l.zx * r.xx + l.zy * r.yx + l.zz * r.zx;
+					m.zy = l.zx * r.xy + l.zy * r.yy + l.zz * r.zy;
+					m.zz = l.zx * r.xz + l.zy * r.yz + l.zz * r.zz;
+					m.dx = l.xx * r.dx + l.xy * r.dy + l.xz * r.dz + l.dx;
+					m.dy = l.yx * r.dx + l.yy * r.dy + l.yz * r.dz + l.dy;
+					m.dz = l.zx * r.dx + l.zy * r.dy + l.zz * r.dz + l.dz;
+				}
+				dojo.mixin(this, m);
+			}
+		}else{
+			dojo.mixin(this, arg);
+		}
+	}
 };
-dojox.gfx3d.matrix.Matrix3D=function(_3){
-if(_3){
-if(typeof _3=="number"){
-this.xx=this.yy=this.zz=_3;
-}else{
-if(_3 instanceof Array){
-if(_3.length>0){
-var m=dojox.gfx3d.matrix.normalize(_3[0]);
-for(var i=1;i<_3.length;++i){
-var l=m;
-var r=dojox.gfx3d.matrix.normalize(_3[i]);
-m=new dojox.gfx3d.matrix.Matrix3D();
-m.xx=l.xx*r.xx+l.xy*r.yx+l.xz*r.zx;
-m.xy=l.xx*r.xy+l.xy*r.yy+l.xz*r.zy;
-m.xz=l.xx*r.xz+l.xy*r.yz+l.xz*r.zz;
-m.yx=l.yx*r.xx+l.yy*r.yx+l.yz*r.zx;
-m.yy=l.yx*r.xy+l.yy*r.yy+l.yz*r.zy;
-m.yz=l.yx*r.xz+l.yy*r.yz+l.yz*r.zz;
-m.zx=l.zx*r.xx+l.zy*r.yx+l.zz*r.zx;
-m.zy=l.zx*r.xy+l.zy*r.yy+l.zz*r.zy;
-m.zz=l.zx*r.xz+l.zy*r.yz+l.zz*r.zz;
-m.dx=l.xx*r.dx+l.xy*r.dy+l.xz*r.dz+l.dx;
-m.dy=l.yx*r.dx+l.yy*r.dy+l.yz*r.dz+l.dy;
-m.dz=l.zx*r.dx+l.zy*r.dy+l.zz*r.dz+l.dz;
-}
-dojo.mixin(this,m);
-}
-}else{
-dojo.mixin(this,_3);
-}
-}
-}
-};
-dojo.extend(dojox.gfx3d.matrix.Matrix3D,{xx:1,xy:0,xz:0,yx:0,yy:1,yz:0,zx:0,zy:0,zz:1,dx:0,dy:0,dz:0});
-dojo.mixin(dojox.gfx3d.matrix,{identity:new dojox.gfx3d.matrix.Matrix3D(),translate:function(a,b,c){
-if(arguments.length>1){
-return new dojox.gfx3d.matrix.Matrix3D({dx:a,dy:b,dz:c});
-}
-return new dojox.gfx3d.matrix.Matrix3D({dx:a.x,dy:a.y,dz:a.z});
-},scale:function(a,b,c){
-if(arguments.length>1){
-return new dojox.gfx3d.matrix.Matrix3D({xx:a,yy:b,zz:c});
-}
-if(typeof a=="number"){
-return new dojox.gfx3d.matrix.Matrix3D({xx:a,yy:a,zz:a});
-}
-return new dojox.gfx3d.matrix.Matrix3D({xx:a.x,yy:a.y,zz:a.z});
-},rotateX:function(_4){
-var c=Math.cos(_4);
-var s=Math.sin(_4);
-return new dojox.gfx3d.matrix.Matrix3D({yy:c,yz:-s,zy:s,zz:c});
-},rotateXg:function(_5){
-return dojox.gfx3d.matrix.rotateX(dojox.gfx3d.matrix._degToRad(_5));
-},rotateY:function(_6){
-var c=Math.cos(_6);
-var s=Math.sin(_6);
-return new dojox.gfx3d.matrix.Matrix3D({xx:c,xz:s,zx:-s,zz:c});
-},rotateYg:function(_7){
-return dojox.gfx3d.matrix.rotateY(dojox.gfx3d.matrix._degToRad(_7));
-},rotateZ:function(_8){
-var c=Math.cos(_8);
-var s=Math.sin(_8);
-return new dojox.gfx3d.matrix.Matrix3D({xx:c,xy:-s,yx:s,yy:c});
-},rotateZg:function(_9){
-return dojox.gfx3d.matrix.rotateZ(dojox.gfx3d.matrix._degToRad(_9));
-},cameraTranslate:function(a,b,c){
-if(arguments.length>1){
-return new dojox.gfx3d.matrix.Matrix3D({dx:-a,dy:-b,dz:-c});
-}
-return new dojox.gfx3d.matrix.Matrix3D({dx:-a.x,dy:-a.y,dz:-a.z});
-},cameraRotateX:function(_a){
-var c=Math.cos(-_a);
-var s=Math.sin(-_a);
-return new dojox.gfx3d.matrix.Matrix3D({yy:c,yz:-s,zy:s,zz:c});
-},cameraRotateXg:function(_b){
-return dojox.gfx3d.matrix.rotateX(dojox.gfx3d.matrix._degToRad(_b));
-},cameraRotateY:function(_c){
-var c=Math.cos(-_c);
-var s=Math.sin(-_c);
-return new dojox.gfx3d.matrix.Matrix3D({xx:c,xz:s,zx:-s,zz:c});
-},cameraRotateYg:function(_d){
-return dojox.gfx3d.matrix.rotateY(dojox.gfx3d.matrix._degToRad(_d));
-},cameraRotateZ:function(_e){
-var c=Math.cos(-_e);
-var s=Math.sin(-_e);
-return new dojox.gfx3d.matrix.Matrix3D({xx:c,xy:-s,yx:s,yy:c});
-},cameraRotateZg:function(_f){
-return dojox.gfx3d.matrix.rotateZ(dojox.gfx3d.matrix._degToRad(_f));
-},normalize:function(_10){
-return (_10 instanceof dojox.gfx3d.matrix.Matrix3D)?_10:new dojox.gfx3d.matrix.Matrix3D(_10);
-},clone:function(_11){
-var obj=new dojox.gfx3d.matrix.Matrix3D();
-for(var i in _11){
-if(typeof (_11[i])=="number"&&typeof (obj[i])=="number"&&obj[i]!=_11[i]){
-obj[i]=_11[i];
-}
-}
-return obj;
-},invert:function(_12){
-var m=dojox.gfx3d.matrix.normalize(_12);
-var D=m.xx*m.yy*m.zz+m.xy*m.yz*m.zx+m.xz*m.yx*m.zy-m.xx*m.yz*m.zy-m.xy*m.yx*m.zz-m.xz*m.yy*m.zx;
-var M=new dojox.gfx3d.matrix.Matrix3D({xx:(m.yy*m.zz-m.yz*m.zy)/D,xy:(m.xz*m.zy-m.xy*m.zz)/D,xz:(m.xy*m.yz-m.xz*m.yy)/D,yx:(m.yz*m.zx-m.yx*m.zz)/D,yy:(m.xx*m.zz-m.xz*m.zx)/D,yz:(m.xz*m.yx-m.xx*m.yz)/D,zx:(m.yx*m.zy-m.yy*m.zx)/D,zy:(m.xy*m.zx-m.xx*m.zy)/D,zz:(m.xx*m.yy-m.xy*m.yx)/D,dx:-1*(m.xy*m.yz*m.dz+m.xz*m.dy*m.zy+m.dx*m.yy*m.zz-m.xy*m.dy*m.zz-m.xz*m.yy*m.dz-m.dx*m.yz*m.zy)/D,dy:(m.xx*m.yz*m.dz+m.xz*m.dy*m.zx+m.dx*m.yx*m.zz-m.xx*m.dy*m.zz-m.xz*m.yx*m.dz-m.dx*m.yz*m.zx)/D,dz:-1*(m.xx*m [...]
-return M;
-},_multiplyPoint:function(m,x,y,z){
-return {x:m.xx*x+m.xy*y+m.xz*z+m.dx,y:m.yx*x+m.yy*y+m.yz*z+m.dy,z:m.zx*x+m.zy*y+m.zz*z+m.dz};
-},multiplyPoint:function(_13,a,b,c){
-var m=dojox.gfx3d.matrix.normalize(_13);
-if(typeof a=="number"&&typeof b=="number"&&typeof c=="number"){
-return dojox.gfx3d.matrix._multiplyPoint(m,a,b,c);
-}
-return dojox.gfx3d.matrix._multiplyPoint(m,a.x,a.y,a.z);
-},multiply:function(_14){
-var m=dojox.gfx3d.matrix.normalize(_14);
-for(var i=1;i<arguments.length;++i){
-var l=m;
-var r=dojox.gfx3d.matrix.normalize(arguments[i]);
-m=new dojox.gfx3d.matrix.Matrix3D();
-m.xx=l.xx*r.xx+l.xy*r.yx+l.xz*r.zx;
-m.xy=l.xx*r.xy+l.xy*r.yy+l.xz*r.zy;
-m.xz=l.xx*r.xz+l.xy*r.yz+l.xz*r.zz;
-m.yx=l.yx*r.xx+l.yy*r.yx+l.yz*r.zx;
-m.yy=l.yx*r.xy+l.yy*r.yy+l.yz*r.zy;
-m.yz=l.yx*r.xz+l.yy*r.yz+l.yz*r.zz;
-m.zx=l.zx*r.xx+l.zy*r.yx+l.zz*r.zx;
-m.zy=l.zx*r.xy+l.zy*r.yy+l.zz*r.zy;
-m.zz=l.zx*r.xz+l.zy*r.yz+l.zz*r.zz;
-m.dx=l.xx*r.dx+l.xy*r.dy+l.xz*r.dz+l.dx;
-m.dy=l.yx*r.dx+l.yy*r.dy+l.yz*r.dz+l.dy;
-m.dz=l.zx*r.dx+l.zy*r.dy+l.zz*r.dz+l.dz;
-}
-return m;
-},_project:function(m,x,y,z){
-return {x:m.xx*x+m.xy*y+m.xz*z+m.dx,y:m.yx*x+m.yy*y+m.yz*z+m.dy,z:m.zx*x+m.zy*y+m.zz*z+m.dz};
-},project:function(_15,a,b,c){
-var m=dojox.gfx3d.matrix.normalize(_15);
-if(typeof a=="number"&&typeof b=="number"&&typeof c=="number"){
-return dojox.gfx3d.matrix._project(m,a,b,c);
-}
-return dojox.gfx3d.matrix._project(m,a.x,a.y,a.z);
-}});
-dojox.gfx3d.Matrix3D=dojox.gfx3d.matrix.Matrix3D;
-}
+
+// the default (identity) matrix, which is used to fill in missing values
+dojo.extend(dojox.gfx3d.matrix.Matrix3D, {xx: 1, xy: 0, xz: 0, yx: 0, yy: 1, yz: 0, zx: 0, zy: 0, zz: 1, dx: 0, dy: 0, dz: 0});
+
+dojo.mixin(dojox.gfx3d.matrix, {
+	// summary: class constants, and methods of dojox.gfx3d.matrix
+	
+	// matrix constants
+	
+	// identity: dojox.gfx3d.matrix.Matrix3D
+	//		an identity matrix constant: identity * (x, y, z) == (x, y, z)
+	identity: new dojox.gfx3d.matrix.Matrix3D(),
+	
+	// matrix creators
+	
+	translate: function(a, b, c){
+		// summary: forms a translation matrix
+		// description: The resulting matrix is used to translate (move) points by specified offsets.
+		// a: Number: an x coordinate value
+		// b: Number: a y coordinate value
+		// c: Number: a z coordinate value
+		if(arguments.length > 1){
+			return new dojox.gfx3d.matrix.Matrix3D({dx: a, dy: b, dz: c}); // dojox.gfx3d.matrix.Matrix3D
+		}
+		// branch
+		// a: Object: a point-like object, which specifies offsets for 3 dimensions
+		// b: null
+		return new dojox.gfx3d.matrix.Matrix3D({dx: a.x, dy: a.y, dz: a.z}); // dojox.gfx3d.matrix.Matrix3D
+	},
+	scale: function(a, b, c){
+		// summary: forms a scaling matrix
+		// description: The resulting matrix is used to scale (magnify) points by specified offsets.
+		// a: Number: a scaling factor used for the x coordinate
+		// b: Number: a scaling factor used for the y coordinate
+		// c: Number: a scaling factor used for the z coordinate
+		if(arguments.length > 1){
+			return new dojox.gfx3d.matrix.Matrix3D({xx: a, yy: b, zz: c}); // dojox.gfx3d.matrix.Matrix3D
+		}
+		if(typeof a == "number"){
+			// branch
+			// a: Number: a uniform scaling factor used for the all coordinates
+			// b: null
+			return new dojox.gfx3d.matrix.Matrix3D({xx: a, yy: a, zz: a}); // dojox.gfx3d.matrix.Matrix3D
+		}
+		// branch
+		// a: Object: a point-like object, which specifies scale factors for 3 dimensions
+		// b: null
+		return new dojox.gfx3d.matrix.Matrix3D({xx: a.x, yy: a.y, zz: a.z}); // dojox.gfx3d.matrix.Matrix3D
+	},
+	rotateX: function(angle){
+		// summary: forms a rotating matrix (about the x axis)
+		// description: The resulting matrix is used to rotate points 
+		//		around the origin of coordinates (0, 0) by specified angle.
+		// angle: Number: an angle of rotation in radians (>0 for CW)
+		var c = Math.cos(angle);
+		var s = Math.sin(angle);
+		return new dojox.gfx3d.matrix.Matrix3D({yy: c, yz: -s, zy: s, zz: c}); // dojox.gfx3d.matrix.Matrix3D
+	},
+	rotateXg: function(degree){
+		// summary: forms a rotating matrix (about the x axis)
+		// description: The resulting matrix is used to rotate points
+		//		around the origin of coordinates (0, 0) by specified degree.
+		//		See dojox.gfx3d.matrix.rotateX() for comparison.
+		// degree: Number: an angle of rotation in degrees (>0 for CW)
+		return dojox.gfx3d.matrix.rotateX(dojox.gfx3d.matrix._degToRad(degree)); // dojox.gfx3d.matrix.Matrix3D
+	},
+	rotateY: function(angle){
+		// summary: forms a rotating matrix (about the y axis)
+		// description: The resulting matrix is used to rotate points 
+		//		around the origin of coordinates (0, 0) by specified angle.
+		// angle: Number: an angle of rotation in radians (>0 for CW)
+		var c = Math.cos(angle);
+		var s = Math.sin(angle);
+		return new dojox.gfx3d.matrix.Matrix3D({xx: c, xz: s, zx: -s, zz: c}); // dojox.gfx3d.matrix.Matrix3D
+	},
+	rotateYg: function(degree){
+		// summary: forms a rotating matrix (about the y axis)
+		// description: The resulting matrix is used to rotate points
+		//		around the origin of coordinates (0, 0) by specified degree.
+		//		See dojox.gfx3d.matrix.rotateY() for comparison.
+		// degree: Number: an angle of rotation in degrees (>0 for CW)
+		return dojox.gfx3d.matrix.rotateY(dojox.gfx3d.matrix._degToRad(degree)); // dojox.gfx3d.matrix.Matrix3D
+	},
+	rotateZ: function(angle){
+		// summary: forms a rotating matrix (about the z axis)
+		// description: The resulting matrix is used to rotate points 
+		//		around the origin of coordinates (0, 0) by specified angle.
+		// angle: Number: an angle of rotation in radians (>0 for CW)
+		var c = Math.cos(angle);
+		var s = Math.sin(angle);
+		return new dojox.gfx3d.matrix.Matrix3D({xx: c, xy: -s, yx: s, yy: c}); // dojox.gfx3d.matrix.Matrix3D
+	},
+	rotateZg: function(degree){
+		// summary: forms a rotating matrix (about the z axis)
+		// description: The resulting matrix is used to rotate points
+		//		around the origin of coordinates (0, 0) by specified degree.
+		//		See dojox.gfx3d.matrix.rotateZ() for comparison.
+		// degree: Number: an angle of rotation in degrees (>0 for CW)
+		return dojox.gfx3d.matrix.rotateZ(dojox.gfx3d.matrix._degToRad(degree)); // dojox.gfx3d.matrix.Matrix3D
+	},
+
+	// camera transformation
+	cameraTranslate: function(a, b, c){
+		// summary: forms a translation matrix
+		// description: The resulting matrix is used to translate (move) points by specified offsets.
+		// a: Number: an x coordinate value
+		// b: Number: a y coordinate value
+		// c: Number: a z coordinate value
+		if(arguments.length > 1){
+			return new dojox.gfx3d.matrix.Matrix3D({dx: -a, dy: -b, dz: -c}); // dojox.gfx3d.matrix.Matrix3D
+		}
+		// branch
+		// a: Object: a point-like object, which specifies offsets for 3 dimensions
+		// b: null
+		return new dojox.gfx3d.matrix.Matrix3D({dx: -a.x, dy: -a.y, dz: -a.z}); // dojox.gfx3d.matrix.Matrix3D
+	},
+	cameraRotateX: function(angle){
+		// summary: forms a rotating matrix (about the x axis) in cameraTransform manner
+		// description: The resulting matrix is used to rotate points 
+		//		around the origin of coordinates (0, 0) by specified angle.
+		// angle: Number: an angle of rotation in radians (>0 for CW)
+		var c = Math.cos(-angle);
+		var s = Math.sin(-angle);
+		return new dojox.gfx3d.matrix.Matrix3D({yy: c, yz: -s, zy: s, zz: c}); // dojox.gfx3d.matrix.Matrix3D
+	},
+	cameraRotateXg: function(degree){
+		// summary: forms a rotating matrix (about the x axis)in cameraTransform manner
+		// description: The resulting matrix is used to rotate points
+		//		around the origin of coordinates (0, 0) by specified degree.
+		//		See dojox.gfx3d.matrix.rotateX() for comparison.
+		// degree: Number: an angle of rotation in degrees (>0 for CW)
+		return dojox.gfx3d.matrix.rotateX(dojox.gfx3d.matrix._degToRad(degree)); // dojox.gfx3d.matrix.Matrix3D
+	},
+	cameraRotateY: function(angle){
+		// summary: forms a rotating matrix (about the y axis) in cameraTransform manner
+		// description: The resulting matrix is used to rotate points 
+		//		around the origin of coordinates (0, 0) by specified angle.
+		// angle: Number: an angle of rotation in radians (>0 for CW)
+		var c = Math.cos(-angle);
+		var s = Math.sin(-angle);
+		return new dojox.gfx3d.matrix.Matrix3D({xx: c, xz: s, zx: -s, zz: c}); // dojox.gfx3d.matrix.Matrix3D
+	},
+	cameraRotateYg: function(degree){
+		// summary: forms a rotating matrix (about the y axis) in cameraTransform manner
+		// description: The resulting matrix is used to rotate points
+		//		around the origin of coordinates (0, 0) by specified degree.
+		//		See dojox.gfx3d.matrix.rotateY() for comparison.
+		// degree: Number: an angle of rotation in degrees (>0 for CW)
+		return dojox.gfx3d.matrix.rotateY(dojox.gfx3d.matrix._degToRad(degree)); // dojox.gfx3d.matrix.Matrix3D
+	},
+	cameraRotateZ: function(angle){
+		// summary: forms a rotating matrix (about the z axis) in cameraTransform manner
+		// description: The resulting matrix is used to rotate points 
+		//		around the origin of coordinates (0, 0) by specified angle.
+		// angle: Number: an angle of rotation in radians (>0 for CW)
+		var c = Math.cos(-angle);
+		var s = Math.sin(-angle);
+		return new dojox.gfx3d.matrix.Matrix3D({xx: c, xy: -s, yx: s, yy: c}); // dojox.gfx3d.matrix.Matrix3D
+	},
+	cameraRotateZg: function(degree){
+		// summary: forms a rotating matrix (about the z axis) in cameraTransform manner
+		// description: The resulting matrix is used to rotate points
+		//		around the origin of coordinates (0, 0) by specified degree.
+		//		See dojox.gfx3d.matrix.rotateZ() for comparison.
+		// degree: Number: an angle of rotation in degrees (>0 for CW)
+		return dojox.gfx3d.matrix.rotateZ(dojox.gfx3d.matrix._degToRad(degree)); // dojox.gfx3d.matrix.Matrix3D
+	},
+
+	// ensure matrix 3D conformance
+	normalize: function(matrix){
+		// summary: converts an object to a matrix, if necessary
+		// description: Converts any 3D matrix-like object or an array of
+		//		such objects to a valid dojox.gfx3d.matrix.Matrix3D object.
+		// matrix: Object: an object, which is converted to a matrix, if necessary
+		return (matrix instanceof dojox.gfx3d.matrix.Matrix3D) ? matrix : new dojox.gfx3d.matrix.Matrix3D(matrix); // dojox.gfx3d.matrix.Matrix3D
+	},
+	
+	// common operations
+	
+	clone: function(matrix){
+		// summary: creates a copy of a 3D matrix
+		// matrix: dojox.gfx3d.matrix.Matrix3D: a 3D matrix-like object to be cloned
+		var obj = new dojox.gfx3d.matrix.Matrix3D();
+		for(var i in matrix){
+			if(typeof(matrix[i]) == "number" && typeof(obj[i]) == "number" && obj[i] != matrix[i]) obj[i] = matrix[i];
+		}
+		return obj; // dojox.gfx3d.matrix.Matrix3D
+	},
+	invert: function(matrix){
+		// summary: inverts a 2D matrix
+		// matrix: dojox.gfx.matrix.Matrix3D: a 2D matrix-like object to be inverted
+		var m = dojox.gfx3d.matrix.normalize(matrix);
+		var D = m.xx * m.yy * m.zz + m.xy * m.yz * m.zx + m.xz * m.yx * m.zy - m.xx * m.yz * m.zy - m.xy * m.yx * m.zz - m.xz * m.yy * m.zx;
+		var M = new dojox.gfx3d.matrix.Matrix3D({
+			xx: (m.yy * m.zz - m.yz * m.zy) / D,
+			xy: (m.xz * m.zy - m.xy * m.zz) / D,
+			xz: (m.xy * m.yz - m.xz * m.yy) / D,
+			yx: (m.yz * m.zx - m.yx * m.zz) / D,
+			yy: (m.xx * m.zz - m.xz * m.zx) / D,
+			yz: (m.xz * m.yx - m.xx * m.yz) / D,
+			zx: (m.yx * m.zy - m.yy * m.zx) / D,
+			zy: (m.xy * m.zx - m.xx * m.zy) / D,
+			zz: (m.xx * m.yy - m.xy * m.yx) / D,
+			dx: -1 * (m.xy * m.yz * m.dz + m.xz * m.dy * m.zy + m.dx * m.yy * m.zz - m.xy * m.dy * m.zz - m.xz * m.yy * m.dz - m.dx * m.yz * m.zy) / D,
+			dy: (m.xx * m.yz * m.dz + m.xz * m.dy * m.zx + m.dx * m.yx * m.zz - m.xx * m.dy * m.zz - m.xz * m.yx * m.dz - m.dx * m.yz * m.zx) / D,
+			dz: -1 * (m.xx * m.yy * m.dz + m.xy * m.dy * m.zx + m.dx * m.yx * m.zy - m.xx * m.dy * m.zy - m.xy * m.yx * m.dz - m.dx * m.yy * m.zx) / D
+		});
+		return M; // dojox.gfx3d.matrix.Matrix3D
+	},
+	_multiplyPoint: function(m, x, y, z){
+		// summary: applies a matrix to a point
+		// matrix: dojox.gfx3d.matrix.Matrix3D: a 3D matrix object to be applied
+		// x: Number: an x coordinate of a point
+		// y: Number: a y coordinate of a point
+		// z: Number: a z coordinate of a point
+		return {x: m.xx * x + m.xy * y + m.xz * z + m.dx, y: m.yx * x + m.yy * y + m.yz * z + m.dy, z: m.zx * x + m.zy * y + m.zz * z + m.dz}; // Object
+	},
+	multiplyPoint: function(matrix, /* Number||Point */ a, /* Number, optional */ b, /* Number, optional */ c){
+		// summary: applies a matrix to a point
+		// matrix: dojox.gfx3d.matrix.Matrix3D: a 3D matrix object to be applied
+		// a: Number: an x coordinate of a point
+		// b: Number: a y coordinate of a point
+		// c: Number: a z coordinate of a point
+		var m = dojox.gfx3d.matrix.normalize(matrix);
+		if(typeof a == "number" && typeof b == "number" && typeof c == "number"){
+			return dojox.gfx3d.matrix._multiplyPoint(m, a, b, c); // Object
+		}
+		// branch
+		// matrix: dojox.gfx3d.matrix.Matrix3D: a 3D matrix object to be applied
+		// a: Object: a point
+		// b: null
+		// c: null
+		return dojox.gfx3d.matrix._multiplyPoint(m, a.x, a.y, a.z); // Object
+	},
+	multiply: function(matrix){
+		// summary: combines matrices by multiplying them sequentially in the given order
+		// matrix: dojox.gfx3d.matrix.Matrix3D...: a 3D matrix-like object, 
+		//		all subsequent arguments are matrix-like objects too
+		var m = dojox.gfx3d.matrix.normalize(matrix);
+		// combine matrices
+		for(var i = 1; i < arguments.length; ++i){
+			var l = m;
+			var r = dojox.gfx3d.matrix.normalize(arguments[i]);
+			m = new dojox.gfx3d.matrix.Matrix3D();
+			m.xx = l.xx * r.xx + l.xy * r.yx + l.xz * r.zx;
+			m.xy = l.xx * r.xy + l.xy * r.yy + l.xz * r.zy;
+			m.xz = l.xx * r.xz + l.xy * r.yz + l.xz * r.zz;
+			m.yx = l.yx * r.xx + l.yy * r.yx + l.yz * r.zx;
+			m.yy = l.yx * r.xy + l.yy * r.yy + l.yz * r.zy;
+			m.yz = l.yx * r.xz + l.yy * r.yz + l.yz * r.zz;
+			m.zx = l.zx * r.xx + l.zy * r.yx + l.zz * r.zx;
+			m.zy = l.zx * r.xy + l.zy * r.yy + l.zz * r.zy;
+			m.zz = l.zx * r.xz + l.zy * r.yz + l.zz * r.zz;
+			m.dx = l.xx * r.dx + l.xy * r.dy + l.xz * r.dz + l.dx;
+			m.dy = l.yx * r.dx + l.yy * r.dy + l.yz * r.dz + l.dy;
+			m.dz = l.zx * r.dx + l.zy * r.dy + l.zz * r.dz + l.dz;
+		}
+		return m; // dojox.gfx3d.matrix.Matrix3D
+	},
+
+	_project: function(m, x, y, z){
+		// summary: applies a matrix to a point
+		// matrix: dojox.gfx3d.matrix.Matrix3D: a 3D matrix object to be applied
+		// x: Number: an x coordinate of a point
+		// y: Number: a y coordinate of a point
+		// z: Number: a z coordinate of a point
+		return {	// Object
+			x: m.xx * x + m.xy * y + m.xz * z + m.dx, 
+			y: m.yx * x + m.yy * y + m.yz * z + m.dy, 
+			z: m.zx * x + m.zy * y + m.zz * z + m.dz};
+	},
+	project: function(matrix, /* Number||Point */ a, /* Number, optional */ b, /* Number, optional */ c){
+		// summary: applies a matrix to a point
+		// matrix: dojox.gfx3d.matrix.Matrix3D: a 3D matrix object to be applied
+		// a: Number: an x coordinate of a point
+		// b: Number: a y coordinate of a point
+		// c: Number: a z coordinate of a point
+		var m = dojox.gfx3d.matrix.normalize(matrix);
+		if(typeof a == "number" && typeof b == "number" && typeof c == "number"){
+			return dojox.gfx3d.matrix._project(m, a, b, c); // Object
+		}
+		// branch
+		// matrix: dojox.gfx3d.matrix.Matrix3D: a 3D matrix object to be applied
+		// a: Object: a point
+		// b: null
+		// c: null
+		return dojox.gfx3d.matrix._project(m, a.x, a.y, a.z); // Object
+	}
+});
+
+// propagate matrix up
+dojox.gfx3d.Matrix3D = dojox.gfx3d.matrix.Matrix3D;
diff --git a/dojox/gfx3d/object.js b/dojox/gfx3d/object.js
index e4982d5..85038a7 100644
--- a/dojox/gfx3d/object.js
+++ b/dojox/gfx3d/object.js
@@ -1,614 +1,1093 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx3d.object"]){
-dojo._hasResource["dojox.gfx3d.object"]=true;
 dojo.provide("dojox.gfx3d.object");
+
 dojo.require("dojox.gfx");
 dojo.require("dojox.gfx3d.lighting");
 dojo.require("dojox.gfx3d.scheduler");
 dojo.require("dojox.gfx3d.vector");
 dojo.require("dojox.gfx3d.gradient");
-var out=function(o,x){
-if(arguments.length>1){
-o=x;
-}
-var e={};
-for(var i in o){
-if(i in e){
-continue;
-}
-}
+
+// FIXME: why the global "out" var here?
+var out = function(o, x){
+	if(arguments.length > 1){
+		// console.debug("debug:", o);
+		o = x;
+	}
+	var e = {};
+	for(var i in o){
+		if(i in e){ continue; }
+		// console.debug("debug:", i, typeof o[i], o[i]);
+	}
 };
-dojo.declare("dojox.gfx3d.Object",null,{constructor:function(){
-this.object=null;
-this.matrix=null;
-this.cache=null;
-this.renderer=null;
-this.parent=null;
-this.strokeStyle=null;
-this.fillStyle=null;
-this.shape=null;
-},setObject:function(_1){
-this.object=dojox.gfx.makeParameters(this.object,_1);
-return this;
-},setTransform:function(_2){
-this.matrix=dojox.gfx3d.matrix.clone(_2?dojox.gfx3d.matrix.normalize(_2):dojox.gfx3d.identity,true);
-return this;
-},applyRightTransform:function(_3){
-return _3?this.setTransform([this.matrix,_3]):this;
-},applyLeftTransform:function(_4){
-return _4?this.setTransform([_4,this.matrix]):this;
-},applyTransform:function(_5){
-return _5?this.setTransform([this.matrix,_5]):this;
-},setFill:function(_6){
-this.fillStyle=_6;
-return this;
-},setStroke:function(_7){
-this.strokeStyle=_7;
-return this;
-},toStdFill:function(_8,_9){
-return (this.fillStyle&&typeof this.fillStyle["type"]!="undefined")?_8[this.fillStyle.type](_9,this.fillStyle.finish,this.fillStyle.color):this.fillStyle;
-},invalidate:function(){
-this.renderer.addTodo(this);
-},destroy:function(){
-if(this.shape){
-var p=this.shape.getParent();
-if(p){
-p.remove(this.shape);
-}
-this.shape=null;
-}
-},render:function(_a){
-throw "Pure virtual function, not implemented";
-},draw:function(_b){
-throw "Pure virtual function, not implemented";
-},getZOrder:function(){
-return 0;
-},getOutline:function(){
-return null;
-}});
-dojo.declare("dojox.gfx3d.Scene",dojox.gfx3d.Object,{constructor:function(){
-this.objects=[];
-this.todos=[];
-this.schedule=dojox.gfx3d.scheduler.zOrder;
-this._draw=dojox.gfx3d.drawer.conservative;
-},setFill:function(_c){
-this.fillStyle=_c;
-dojo.forEach(this.objects,function(_d){
-_d.setFill(_c);
-});
-return this;
-},setStroke:function(_e){
-this.strokeStyle=_e;
-dojo.forEach(this.objects,function(_f){
-_f.setStroke(_e);
-});
-return this;
-},render:function(_10,_11){
-var m=dojox.gfx3d.matrix.multiply(_10,this.matrix);
-if(_11){
-this.todos=this.objects;
-}
-dojo.forEach(this.todos,function(_12){
-_12.render(m,_11);
-});
-},draw:function(_13){
-this.objects=this.schedule(this.objects);
-this._draw(this.todos,this.objects,this.renderer);
-},addTodo:function(_14){
-if(dojo.every(this.todos,function(_15){
-return _15!=_14;
-})){
-this.todos.push(_14);
-this.invalidate();
-}
-},invalidate:function(){
-this.parent.addTodo(this);
-},getZOrder:function(){
-var _16=0;
-dojo.forEach(this.objects,function(_17){
-_16+=_17.getZOrder();
-});
-return (this.objects.length>1)?_16/this.objects.length:0;
-}});
-dojo.declare("dojox.gfx3d.Edges",dojox.gfx3d.Object,{constructor:function(){
-this.object=dojo.clone(dojox.gfx3d.defaultEdges);
-},setObject:function(_18,_19){
-this.object=dojox.gfx.makeParameters(this.object,(_18 instanceof Array)?{points:_18,style:_19}:_18);
-return this;
-},getZOrder:function(){
-var _1a=0;
-dojo.forEach(this.cache,function(_1b){
-_1a+=_1b.z;
-});
-return (this.cache.length>1)?_1a/this.cache.length:0;
-},render:function(_1c){
-var m=dojox.gfx3d.matrix.multiply(_1c,this.matrix);
-this.cache=dojo.map(this.object.points,function(_1d){
-return dojox.gfx3d.matrix.multiplyPoint(m,_1d);
-});
-},draw:function(){
-var c=this.cache;
-if(this.shape){
-this.shape.setShape("");
-}else{
-this.shape=this.renderer.createPath();
-}
-var p=this.shape.setAbsoluteMode("absolute");
-if(this.object.style=="strip"||this.object.style=="loop"){
-p.moveTo(c[0].x,c[0].y);
-dojo.forEach(c.slice(1),function(_1e){
-p.lineTo(_1e.x,_1e.y);
-});
-if(this.object.style=="loop"){
-p.closePath();
-}
-}else{
-for(var i=0;i<this.cache.length;){
-p.moveTo(c[i].x,c[i].y);
-i++;
-p.lineTo(c[i].x,c[i].y);
-i++;
-}
-}
-p.setStroke(this.strokeStyle);
-}});
-dojo.declare("dojox.gfx3d.Orbit",dojox.gfx3d.Object,{constructor:function(){
-this.object=dojo.clone(dojox.gfx3d.defaultOrbit);
-},render:function(_1f){
-var m=dojox.gfx3d.matrix.multiply(_1f,this.matrix);
-var _20=[0,Math.PI/4,Math.PI/3];
-var _21=dojox.gfx3d.matrix.multiplyPoint(m,this.object.center);
-var _22=dojo.map(_20,function(_23){
-return {x:this.center.x+this.radius*Math.cos(_23),y:this.center.y+this.radius*Math.sin(_23),z:this.center.z};
-},this.object);
-_22=dojo.map(_22,function(_24){
-return dojox.gfx3d.matrix.multiplyPoint(m,_24);
-});
-var _25=dojox.gfx3d.vector.normalize(_22);
-_22=dojo.map(_22,function(_26){
-return dojox.gfx3d.vector.substract(_26,_21);
-});
-var A={xx:_22[0].x*_22[0].y,xy:_22[0].y*_22[0].y,xz:1,yx:_22[1].x*_22[1].y,yy:_22[1].y*_22[1].y,yz:1,zx:_22[2].x*_22[2].y,zy:_22[2].y*_22[2].y,zz:1,dx:0,dy:0,dz:0};
-var B=dojo.map(_22,function(_27){
-return -Math.pow(_27.x,2);
-});
-var X=dojox.gfx3d.matrix.multiplyPoint(dojox.gfx3d.matrix.invert(A),B[0],B[1],B[2]);
-var _28=Math.atan2(X.x,1-X.y)/2;
-var _29=dojo.map(_22,function(_2a){
-return dojox.gfx.matrix.multiplyPoint(dojox.gfx.matrix.rotate(-_28),_2a.x,_2a.y);
-});
-var a=Math.pow(_29[0].x,2);
-var b=Math.pow(_29[0].y,2);
-var c=Math.pow(_29[1].x,2);
-var d=Math.pow(_29[1].y,2);
-var rx=Math.sqrt((a*d-b*c)/(d-b));
-var ry=Math.sqrt((a*d-b*c)/(a-c));
-this.cache={cx:_21.x,cy:_21.y,rx:rx,ry:ry,theta:_28,normal:_25};
-},draw:function(_2b){
-if(this.shape){
-this.shape.setShape(this.cache);
-}else{
-this.shape=this.renderer.createEllipse(this.cache);
-}
-this.shape.applyTransform(dojox.gfx.matrix.rotateAt(this.cache.theta,this.cache.cx,this.cache.cy)).setStroke(this.strokeStyle).setFill(this.toStdFill(_2b,this.cache.normal));
-}});
-dojo.declare("dojox.gfx3d.Path3d",dojox.gfx3d.Object,{constructor:function(){
-this.object=dojo.clone(dojox.gfx3d.defaultPath3d);
-this.segments=[];
-this.absolute=true;
-this.last={};
-this.path="";
-},_collectArgs:function(_2c,_2d){
-for(var i=0;i<_2d.length;++i){
-var t=_2d[i];
-if(typeof (t)=="boolean"){
-_2c.push(t?1:0);
-}else{
-if(typeof (t)=="number"){
-_2c.push(t);
-}else{
-if(t instanceof Array){
-this._collectArgs(_2c,t);
-}else{
-if("x" in t&&"y" in t){
-_2c.push(t.x);
-_2c.push(t.y);
-}
-}
-}
-}
-}
-},_validSegments:{m:3,l:3,z:0},_pushSegment:function(_2e,_2f){
-var _30=this._validSegments[_2e.toLowerCase()],_31;
-if(typeof (_30)=="number"){
-if(_30){
-if(_2f.length>=_30){
-_31={action:_2e,args:_2f.slice(0,_2f.length-_2f.length%_30)};
-this.segments.push(_31);
-}
-}else{
-_31={action:_2e,args:[]};
-this.segments.push(_31);
-}
-}
-},moveTo:function(){
-var _32=[];
-this._collectArgs(_32,arguments);
-this._pushSegment(this.absolute?"M":"m",_32);
-return this;
-},lineTo:function(){
-var _33=[];
-this._collectArgs(_33,arguments);
-this._pushSegment(this.absolute?"L":"l",_33);
-return this;
-},closePath:function(){
-this._pushSegment("Z",[]);
-return this;
-},render:function(_34){
-var m=dojox.gfx3d.matrix.multiply(_34,this.matrix);
-var _35="";
-var _36=this._validSegments;
-dojo.forEach(this.segments,function(_37){
-_35+=_37.action;
-for(var i=0;i<_37.args.length;i+=_36[_37.action.toLowerCase()]){
-var pt=dojox.gfx3d.matrix.multiplyPoint(m,_37.args[i],_37.args[i+1],_37.args[i+2]);
-_35+=" "+pt.x+" "+pt.y;
-}
-});
-this.cache=_35;
-},_draw:function(){
-return this.parent.createPath(this.cache);
-}});
-dojo.declare("dojox.gfx3d.Triangles",dojox.gfx3d.Object,{constructor:function(){
-this.object=dojo.clone(dojox.gfx3d.defaultTriangles);
-},setObject:function(_38,_39){
-if(_38 instanceof Array){
-this.object=dojox.gfx.makeParameters(this.object,{points:_38,style:_39});
-}else{
-this.object=dojox.gfx.makeParameters(this.object,_38);
-}
-return this;
-},render:function(_3a){
-var m=dojox.gfx3d.matrix.multiply(_3a,this.matrix);
-var c=dojo.map(this.object.points,function(_3b){
-return dojox.gfx3d.matrix.multiplyPoint(m,_3b);
+
+dojo.declare("dojox.gfx3d.Object", null, {
+	constructor: function(){
+		// summary: a Object object, which knows how to map
+		// 3D objects to 2D shapes.
+
+		// object: Object: an abstract Object object
+		// (see dojox.gfx3d.defaultEdges,
+		// dojox.gfx3d.defaultTriangles,
+		// dojox.gfx3d.defaultQuads
+		// dojox.gfx3d.defaultOrbit
+		// dojox.gfx3d.defaultCube
+		// or dojox.gfx3d.defaultCylinder)
+		this.object = null;
+
+		// matrix: dojox.gfx3d.matrix: world transform
+		this.matrix = null;
+		// cache: buffer for intermediate result, used late for draw()
+		this.cache = null;
+		// renderer: a reference for the Viewport
+		this.renderer = null;
+		// parent: a reference for parent, Scene or Viewport object
+		this.parent = null;
+
+		// strokeStyle: Object: a stroke object 
+		this.strokeStyle = null;
+		// fillStyle: Object: a fill object or texture object
+		this.fillStyle = null;
+		// shape: dojox.gfx.Shape: an underlying 2D shape
+		this.shape = null;
+	},
+
+	setObject: function(newObject){
+		// summary: sets a Object object
+		// object: Object: an abstract Object object
+		// (see dojox.gfx3d.defaultEdges,
+		// dojox.gfx3d.defaultTriangles,
+		// dojox.gfx3d.defaultQuads
+		// dojox.gfx3d.defaultOrbit
+		// dojox.gfx3d.defaultCube
+		// or dojox.gfx3d.defaultCylinder)
+		this.object = dojox.gfx.makeParameters(this.object, newObject);
+		return this;
+	},
+
+	setTransform: function(matrix){
+		// summary: sets a transformation matrix
+		// matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx3d.matrix.Matrix 
+		//	constructor for a list of acceptable arguments)
+		this.matrix = dojox.gfx3d.matrix.clone(matrix ? dojox.gfx3d.matrix.normalize(matrix) : dojox.gfx3d.identity, true);
+		return this;	// self
+	},
+
+	// apply left & right transformation
+	
+	applyRightTransform: function(matrix){
+		// summary: multiplies the existing matrix with an argument on right side
+		//	(this.matrix * matrix)
+		// matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx.matrix.Matrix 
+		//	constructor for a list of acceptable arguments)
+		return matrix ? this.setTransform([this.matrix, matrix]) : this;	// self
+	},
+	applyLeftTransform: function(matrix){
+		// summary: multiplies the existing matrix with an argument on left side
+		//	(matrix * this.matrix)
+		// matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx.matrix.Matrix 
+		//	constructor for a list of acceptable arguments)
+		return matrix ? this.setTransform([matrix, this.matrix]) : this;	// self
+	},
+
+	applyTransform: function(matrix){
+		// summary: a shortcut for dojox.gfx.Shape.applyRightTransform
+		// matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx.matrix.Matrix 
+		//	constructor for a list of acceptable arguments)
+		return matrix ? this.setTransform([this.matrix, matrix]) : this;	// self
+	},
+	
+	setFill: function(fill){
+		// summary: sets a fill object
+		// (the default implementation is to delegate to 
+		// the underlying 2D shape).
+		// fill: Object: a fill object
+		//	(see dojox.gfx.defaultLinearGradient, 
+		//	dojox.gfx.defaultRadialGradient, 
+		//	dojox.gfx.defaultPattern, 
+		//	dojo.Color
+		//	or dojox.gfx.MODEL)
+		this.fillStyle = fill;
+		return this;
+	},
+
+	setStroke: function(stroke){
+		// summary: sets a stroke object
+		//	(the default implementation simply ignores it)
+		// stroke: Object: a stroke object
+		//	(see dojox.gfx.defaultStroke) 
+		this.strokeStyle = stroke;
+		return this;
+	},
+
+	toStdFill: function(lighting, normal){
+		return (this.fillStyle && typeof this.fillStyle['type'] != "undefined") ? lighting[this.fillStyle.type](normal, this.fillStyle.finish, this.fillStyle.color) : this.fillStyle;
+	},
+
+	invalidate: function(){
+		this.renderer.addTodo(this);
+	},
+	
+	destroy: function(){
+		if(this.shape){
+			var p = this.shape.getParent();
+			if(p){
+				p.remove(this.shape);
+			}
+			this.shape = null;
+		}
+	},
+
+	// All the 3D objects need to override the following virtual functions:
+	// render, getZOrder, getOutline, draw, redraw if necessary.
+
+	render: function(camera){
+		throw "Pure virtual function, not implemented";
+	},
+
+	draw: function(lighting){
+		throw "Pure virtual function, not implemented";
+	},
+
+	getZOrder: function(){
+		return 0;
+	},
+
+	getOutline: function(){
+		return null;
+	}
+
 });
-this.cache=[];
-var _3c=c.slice(0,2);
-var _3d=c[0];
-if(this.object.style=="strip"){
-dojo.forEach(c.slice(2),function(_3e){
-_3c.push(_3e);
-_3c.push(_3c[0]);
-this.cache.push(_3c);
-_3c=_3c.slice(1,3);
-},this);
-}else{
-if(this.object.style=="fan"){
-dojo.forEach(c.slice(2),function(_3f){
-_3c.push(_3f);
-_3c.push(_3d);
-this.cache.push(_3c);
-_3c=[_3d,_3f];
-},this);
-}else{
-for(var i=0;i<c.length;){
-this.cache.push([c[i],c[i+1],c[i+2],c[i]]);
-i+=3;
-}
-}
-}
-},draw:function(_40){
-this.cache=dojox.gfx3d.scheduler.bsp(this.cache,function(it){
-return it;
+
+dojo.declare("dojox.gfx3d.Scene", dojox.gfx3d.Object, {
+	// summary: the Scene is just a containter.
+	// note: we have the following assumption:
+	// all objects in the Scene are not overlapped with other objects
+	// outside of the scene.
+	constructor: function(){
+		// summary: a containter of other 3D objects
+		this.objects= [];
+		this.todos = [];
+		this.schedule = dojox.gfx3d.scheduler.zOrder;
+		this._draw = dojox.gfx3d.drawer.conservative;
+	},
+
+	setFill: function(fill){
+		this.fillStyle = fill;
+		dojo.forEach(this.objects, function(item){
+			item.setFill(fill);
+		});
+		return this;
+	},
+
+	setStroke: function(stroke){
+		this.strokeStyle = stroke;
+		dojo.forEach(this.objects, function(item){
+			item.setStroke(stroke);
+		});
+		return this;
+	},
+
+	render: function(camera, deep){
+		var m = dojox.gfx3d.matrix.multiply(camera, this.matrix);
+		if(deep){
+			this.todos = this.objects;
+		}
+		dojo.forEach(this.todos, function(item){ item.render(m, deep); });
+	},
+
+	draw: function(lighting){
+		this.objects = this.schedule(this.objects);
+		this._draw(this.todos, this.objects, this.renderer);
+	},
+
+	addTodo: function(newObject){
+		// FIXME: use indexOf?
+		if(dojo.every(this.todos, function(item){ return item != newObject; })){
+			this.todos.push(newObject);
+			this.invalidate();
+		}
+	},
+
+	invalidate: function(){
+		this.parent.addTodo(this);
+	},
+
+	getZOrder: function(){
+		var zOrder = 0;
+		dojo.forEach(this.objects, function(item){ zOrder += item.getZOrder(); });
+		return (this.objects.length > 1) ?  zOrder / this.objects.length : 0;
+	}
 });
-if(this.shape){
-this.shape.clear();
-}else{
-this.shape=this.renderer.createGroup();
-}
-dojo.forEach(this.cache,function(_41){
-this.shape.createPolyline(_41).setStroke(this.strokeStyle).setFill(this.toStdFill(_40,dojox.gfx3d.vector.normalize(_41)));
-},this);
-},getZOrder:function(){
-var _42=0;
-dojo.forEach(this.cache,function(_43){
-_42+=(_43[0].z+_43[1].z+_43[2].z)/3;
+
+
+dojo.declare("dojox.gfx3d.Edges", dojox.gfx3d.Object, {
+	constructor: function(){
+		// summary: a generic edge in 3D viewport 
+		this.object = dojo.clone(dojox.gfx3d.defaultEdges);
+	},
+
+	setObject: function(newObject, /* String, optional */ style){
+		// summary: setup the object
+		// newObject: Array of points || Object
+		// style: String, optional
+		this.object = dojox.gfx.makeParameters(this.object, (newObject instanceof Array) ? { points: newObject, style: style } : newObject);
+		return this;
+	},
+
+	getZOrder: function(){
+		var zOrder = 0;
+		dojo.forEach(this.cache, function(item){ zOrder += item.z;} );
+		return (this.cache.length > 1) ?  zOrder / this.cache.length : 0;
+	},
+
+	render: function(camera){
+		var m = dojox.gfx3d.matrix.multiply(camera, this.matrix);
+		this.cache = dojo.map(this.object.points, function(item){
+			return dojox.gfx3d.matrix.multiplyPoint(m, item);
+		});
+	},
+
+	draw: function(){
+		var c = this.cache;
+		if(this.shape){
+			this.shape.setShape("")
+		}else{
+			this.shape = this.renderer.createPath();
+		}
+		var p = this.shape.setAbsoluteMode("absolute");
+
+		if(this.object.style == "strip" || this.object.style == "loop"){
+			p.moveTo(c[0].x, c[0].y);
+			dojo.forEach(c.slice(1), function(item){
+				p.lineTo(item.x, item.y);
+			});
+			if(this.object.style == "loop"){
+				p.closePath();
+			}
+		}else{
+			for(var i = 0; i < this.cache.length; ){
+				p.moveTo(c[i].x, c[i].y);
+				i ++;
+				p.lineTo(c[i].x, c[i].y);
+				i ++;
+			}
+		}
+		// FIXME: doe setFill make sense here?
+		p.setStroke(this.strokeStyle);
+	}
 });
-return (this.cache.length>1)?_42/this.cache.length:0;
-}});
-dojo.declare("dojox.gfx3d.Quads",dojox.gfx3d.Object,{constructor:function(){
-this.object=dojo.clone(dojox.gfx3d.defaultQuads);
-},setObject:function(_44,_45){
-this.object=dojox.gfx.makeParameters(this.object,(_44 instanceof Array)?{points:_44,style:_45}:_44);
-return this;
-},render:function(_46){
-var m=dojox.gfx3d.matrix.multiply(_46,this.matrix),i;
-var c=dojo.map(this.object.points,function(_47){
-return dojox.gfx3d.matrix.multiplyPoint(m,_47);
+
+dojo.declare("dojox.gfx3d.Orbit", dojox.gfx3d.Object, {
+	constructor: function(){
+		// summary: a generic edge in 3D viewport 
+		this.object = dojo.clone(dojox.gfx3d.defaultOrbit);
+	},
+
+	render: function(camera){
+		var m = dojox.gfx3d.matrix.multiply(camera, this.matrix);
+		var angles = [0, Math.PI/4, Math.PI/3];
+		var center = dojox.gfx3d.matrix.multiplyPoint(m, this.object.center);
+		var marks = dojo.map(angles, function(item){
+			return {x: this.center.x + this.radius * Math.cos(item), 
+				y: this.center.y + this.radius * Math.sin(item), z: this.center.z};
+			}, this.object);
+
+		marks = dojo.map(marks, function(item){
+			return dojox.gfx3d.matrix.multiplyPoint(m, item);
+		});
+
+		var normal = dojox.gfx3d.vector.normalize(marks);
+
+		marks = dojo.map(marks, function(item){
+			return dojox.gfx3d.vector.substract(item, center);
+		});
+
+		// Use the algorithm here:
+		// http://www.3dsoftware.com/Math/PlaneCurves/EllipseAlgebra/
+		// After we normalize the marks, the equation is:
+		// a x^2 + 2b xy + cy^2 + f = 0: let a = 1
+		//  so the final equation is:
+		//  [ xy, y^2, 1] * [2b, c, f]' = [ -x^2 ]'
+
+		var A = {
+			xx: marks[0].x * marks[0].y, xy: marks[0].y * marks[0].y, xz: 1,
+			yx: marks[1].x * marks[1].y, yy: marks[1].y * marks[1].y, yz: 1,
+			zx: marks[2].x * marks[2].y, zy: marks[2].y * marks[2].y, zz: 1,
+			dx: 0, dy: 0, dz: 0
+		};
+		var B = dojo.map(marks, function(item){
+			return -Math.pow(item.x, 2);
+		});
+
+		// X is 2b, c, f
+		var X = dojox.gfx3d.matrix.multiplyPoint(dojox.gfx3d.matrix.invert(A),B[0], B[1], B[2]);
+		var theta = Math.atan2(X.x, 1 - X.y) / 2;
+
+		// rotate the marks back to the canonical form
+		var probes = dojo.map(marks, function(item){
+			return dojox.gfx.matrix.multiplyPoint(dojox.gfx.matrix.rotate(-theta), item.x, item.y);
+		});
+
+		// we are solving the equation: Ax = b
+		// A = [x^2, y^2] X = [1/a^2, 1/b^2]', b = [1, 1]'
+		// so rx = Math.sqrt(1/ ( inv(A)[1:] * b ) );
+		// so ry = Math.sqrt(1/ ( inv(A)[2:] * b ) );
+
+		var a = Math.pow(probes[0].x, 2);
+		var b = Math.pow(probes[0].y, 2);
+		var c = Math.pow(probes[1].x, 2);
+		var d = Math.pow(probes[1].y, 2);
+
+		// the invert matrix is 
+		// 1/(ad -bc) [ d, -b; -c, a];
+		var rx = Math.sqrt( (a*d - b*c)/ (d-b) );
+		var ry  = Math.sqrt( (a*d - b*c)/ (a-c) );
+
+		this.cache = {cx: center.x, cy: center.y, rx: rx, ry: ry, theta: theta, normal: normal};
+	},
+
+	draw: function(lighting){
+		if(this.shape){
+			this.shape.setShape(this.cache);
+		} else {
+			this.shape = this.renderer.createEllipse(this.cache);
+		}
+		this.shape.applyTransform(dojox.gfx.matrix.rotateAt(this.cache.theta, this.cache.cx, this.cache.cy))
+			.setStroke(this.strokeStyle)
+			.setFill(this.toStdFill(lighting, this.cache.normal));
+	}
 });
-this.cache=[];
-if(this.object.style=="strip"){
-var _48=c.slice(0,2);
-for(i=2;i<c.length;){
-_48=_48.concat([c[i],c[i+1],_48[0]]);
-this.cache.push(_48);
-_48=_48.slice(2,4);
-i+=2;
-}
-}else{
-for(i=0;i<c.length;){
-this.cache.push([c[i],c[i+1],c[i+2],c[i+3],c[i]]);
-i+=4;
-}
-}
-},draw:function(_49){
-this.cache=dojox.gfx3d.scheduler.bsp(this.cache,function(it){
-return it;
+
+dojo.declare("dojox.gfx3d.Path3d", dojox.gfx3d.Object, {
+	// This object is still very immature !
+	constructor: function(){
+		// summary: a generic line
+		//	(this is a helper object, which is defined for convenience)
+		this.object = dojo.clone(dojox.gfx3d.defaultPath3d);
+		this.segments = [];
+		this.absolute = true;
+		this.last = {};
+		this.path = "";
+	},
+
+	_collectArgs: function(array, args){
+		// summary: converts an array of arguments to plain numeric values
+		// array: Array: an output argument (array of numbers)
+		// args: Array: an input argument (can be values of Boolean, Number, dojox.gfx.Point, or an embedded array of them)
+		for(var i = 0; i < args.length; ++i){
+			var t = args[i];
+			if(typeof(t) == "boolean"){
+				array.push(t ? 1 : 0);
+			}else if(typeof(t) == "number"){
+				array.push(t);
+			}else if(t instanceof Array){
+				this._collectArgs(array, t);
+			}else if("x" in t && "y" in t){
+				array.push(t.x);
+				array.push(t.y);
+			}
+		}
+	},
+
+	// a dictionary, which maps segment type codes to a number of their argemnts
+	_validSegments: {m: 3, l: 3,  z: 0},
+
+	_pushSegment: function(action, args){
+		// summary: adds a segment
+		// action: String: valid SVG code for a segment's type
+		// args: Array: a list of parameters for this segment
+		var group = this._validSegments[action.toLowerCase()], segment;
+		if(typeof(group) == "number"){
+			if(group){
+				if(args.length >= group){
+					segment = {action: action, args: args.slice(0, args.length - args.length % group)};
+					this.segments.push(segment);
+				}
+			}else{
+				segment = {action: action, args: []};
+				this.segments.push(segment);
+			}
+		}
+	},
+
+	moveTo: function(){
+		// summary: formes a move segment
+		var args = [];
+		this._collectArgs(args, arguments);
+		this._pushSegment(this.absolute ? "M" : "m", args);
+		return this; // self
+	},
+	lineTo: function(){
+		// summary: formes a line segment
+		var args = [];
+		this._collectArgs(args, arguments);
+		this._pushSegment(this.absolute ? "L" : "l", args);
+		return this; // self
+	},
+
+	closePath: function(){
+		// summary: closes a path
+		this._pushSegment("Z", []);
+		return this; // self
+	},
+
+	render: function(camera){
+		// TODO: we need to get the ancestors' matrix
+		var m = dojox.gfx3d.matrix.multiply(camera, this.matrix);
+		// iterate all the segments and convert them to 2D canvas
+		// TODO consider the relative mode
+		var path = ""
+		var _validSegments = this._validSegments;
+		dojo.forEach(this.segments, function(item){
+			path += item.action;
+			for(var i = 0; i < item.args.length; i+= _validSegments[item.action.toLowerCase()] ){
+				var pt = dojox.gfx3d.matrix.multiplyPoint(m, item.args[i], item.args[i+1], item.args[i+2])
+				path += " " + pt.x + " " + pt.y; 
+			}
+		});
+
+		this.cache =  path;
+	},
+
+	_draw: function(){
+		return this.parent.createPath(this.cache);
+	}
 });
-if(this.shape){
-this.shape.clear();
-}else{
-this.shape=this.renderer.createGroup();
-}
-for(var x=0;x<this.cache.length;x++){
-this.shape.createPolyline(this.cache[x]).setStroke(this.strokeStyle).setFill(this.toStdFill(_49,dojox.gfx3d.vector.normalize(this.cache[x])));
-}
-},getZOrder:function(){
-var _4a=0;
-for(var x=0;x<this.cache.length;x++){
-var i=this.cache[x];
-_4a+=(i[0].z+i[1].z+i[2].z+i[3].z)/4;
-}
-return (this.cache.length>1)?_4a/this.cache.length:0;
-}});
-dojo.declare("dojox.gfx3d.Polygon",dojox.gfx3d.Object,{constructor:function(){
-this.object=dojo.clone(dojox.gfx3d.defaultPolygon);
-},setObject:function(_4b){
-this.object=dojox.gfx.makeParameters(this.object,(_4b instanceof Array)?{path:_4b}:_4b);
-return this;
-},render:function(_4c){
-var m=dojox.gfx3d.matrix.multiply(_4c,this.matrix);
-this.cache=dojo.map(this.object.path,function(_4d){
-return dojox.gfx3d.matrix.multiplyPoint(m,_4d);
+
+dojo.declare("dojox.gfx3d.Triangles", dojox.gfx3d.Object, {
+	constructor: function(){
+		// summary: a generic triangle 
+		//	(this is a helper object, which is defined for convenience)
+		this.object = dojo.clone(dojox.gfx3d.defaultTriangles);
+	},
+
+	setObject: function(newObject, /* String, optional */ style){
+		// summary: setup the object
+		// newObject: Array of points || Object
+		// style: String, optional
+		if(newObject instanceof Array){
+			this.object = dojox.gfx.makeParameters(this.object, { points: newObject, style: style } );
+		} else {
+			this.object = dojox.gfx.makeParameters(this.object, newObject);
+		}
+		return this;
+	},
+	render: function(camera){
+		var m = dojox.gfx3d.matrix.multiply(camera, this.matrix);
+		var c = dojo.map(this.object.points, function(item){
+			return dojox.gfx3d.matrix.multiplyPoint(m, item);
+		});
+		this.cache = [];
+		var pool = c.slice(0, 2);
+		var center = c[0];
+		if(this.object.style == "strip"){
+			dojo.forEach(c.slice(2), function(item){
+				pool.push(item);
+				pool.push(pool[0]);
+				this.cache.push(pool);
+				pool = pool.slice(1, 3);
+			}, this);
+		} else if(this.object.style == "fan"){
+			dojo.forEach(c.slice(2), function(item){
+				pool.push(item);
+				pool.push(center);
+				this.cache.push(pool);
+				pool = [center, item];
+			}, this);
+		} else {
+			for(var i = 0; i < c.length; ){
+				this.cache.push( [ c[i], c[i+1], c[i+2], c[i] ]);
+				i += 3;
+			}
+		}
+	},
+
+	draw: function(lighting){
+		// use the BSP to schedule
+		this.cache = dojox.gfx3d.scheduler.bsp(this.cache, function(it){  return it; });
+		if(this.shape){
+			this.shape.clear();
+		} else {
+			this.shape = this.renderer.createGroup();
+		}
+		dojo.forEach(this.cache, function(item){
+			this.shape.createPolyline(item)
+				.setStroke(this.strokeStyle)
+				.setFill(this.toStdFill(lighting, dojox.gfx3d.vector.normalize(item)));
+		}, this);
+	},
+
+	getZOrder: function(){
+		var zOrder = 0;
+		dojo.forEach(this.cache, function(item){ 
+				zOrder += (item[0].z + item[1].z + item[2].z) / 3; });
+		return (this.cache.length > 1) ?  zOrder / this.cache.length : 0;
+	}
 });
-this.cache.push(this.cache[0]);
-},draw:function(_4e){
-if(this.shape){
-this.shape.setShape({points:this.cache});
-}else{
-this.shape=this.renderer.createPolyline({points:this.cache});
-}
-this.shape.setStroke(this.strokeStyle).setFill(this.toStdFill(_4e,dojox.gfx3d.matrix.normalize(this.cache)));
-},getZOrder:function(){
-var _4f=0;
-for(var x=0;x<this.cache.length;x++){
-_4f+=this.cache[x].z;
-}
-return (this.cache.length>1)?_4f/this.cache.length:0;
-},getOutline:function(){
-return this.cache.slice(0,3);
-}});
-dojo.declare("dojox.gfx3d.Cube",dojox.gfx3d.Object,{constructor:function(){
-this.object=dojo.clone(dojox.gfx3d.defaultCube);
-this.polygons=[];
-},setObject:function(_50){
-this.object=dojox.gfx.makeParameters(this.object,_50);
-},render:function(_51){
-var a=this.object.top;
-var g=this.object.bottom;
-var b={x:g.x,y:a.y,z:a.z};
-var c={x:g.x,y:g.y,z:a.z};
-var d={x:a.x,y:g.y,z:a.z};
-var e={x:a.x,y:a.y,z:g.z};
-var f={x:g.x,y:a.y,z:g.z};
-var h={x:a.x,y:g.y,z:g.z};
-var _52=[a,b,c,d,e,f,g,h];
-var m=dojox.gfx3d.matrix.multiply(_51,this.matrix);
-var p=dojo.map(_52,function(_53){
-return dojox.gfx3d.matrix.multiplyPoint(m,_53);
+
+dojo.declare("dojox.gfx3d.Quads", dojox.gfx3d.Object, {
+	constructor: function(){
+		// summary: a generic triangle 
+		//	(this is a helper object, which is defined for convenience)
+		this.object = dojo.clone(dojox.gfx3d.defaultQuads);
+	},
+
+	setObject: function(newObject, /* String, optional */ style){
+		// summary: setup the object
+		// newObject: Array of points || Object
+		// style: String, optional
+		this.object = dojox.gfx.makeParameters(this.object, (newObject instanceof Array) ? { points: newObject, style: style } : newObject );
+		return this;
+	},
+	render: function(camera){
+		var m = dojox.gfx3d.matrix.multiply(camera, this.matrix), i;
+		var c = dojo.map(this.object.points, function(item){
+			return dojox.gfx3d.matrix.multiplyPoint(m, item);
+		});
+		this.cache = [];
+		if(this.object.style == "strip"){
+			var pool = c.slice(0, 2);
+			for(i = 2; i < c.length; ){
+				pool = pool.concat( [ c[i], c[i+1], pool[0] ] );
+				this.cache.push(pool);
+				pool = pool.slice(2,4);
+				i += 2;
+			}
+		}else{
+			for(i = 0; i < c.length; ){
+				this.cache.push( [c[i], c[i+1], c[i+2], c[i+3], c[i] ] );
+				i += 4;
+			}
+		}
+	},
+
+	draw: function(lighting){
+		// use the BSP to schedule
+		this.cache = dojox.gfx3d.scheduler.bsp(this.cache, function(it){  return it; });
+		if(this.shape){
+			this.shape.clear();
+		}else{
+			this.shape = this.renderer.createGroup();
+		}
+		// using naive iteration to speed things up a bit by avoiding function call overhead
+		for(var x=0; x<this.cache.length; x++){
+			this.shape.createPolyline(this.cache[x])
+				.setStroke(this.strokeStyle)
+				.setFill(this.toStdFill(lighting, dojox.gfx3d.vector.normalize(this.cache[x])));
+		}
+		/*
+		dojo.forEach(this.cache, function(item){
+			this.shape.createPolyline(item)
+				.setStroke(this.strokeStyle)
+				.setFill(this.toStdFill(lighting, dojox.gfx3d.vector.normalize(item)));
+		}, this);
+		*/
+	},
+
+	getZOrder: function(){
+		var zOrder = 0;
+		// using naive iteration to speed things up a bit by avoiding function call overhead
+		for(var x=0; x<this.cache.length; x++){
+			var i = this.cache[x];
+			zOrder += (i[0].z + i[1].z + i[2].z + i[3].z) / 4;
+		}
+		/*
+		dojo.forEach(this.cache, function(item){
+				zOrder += (item[0].z + item[1].z + item[2].z + item[3].z) / 4; });
+		*/
+		return (this.cache.length > 1) ?  zOrder / this.cache.length : 0;
+	}
 });
-a=p[0];
-b=p[1];
-c=p[2];
-d=p[3];
-e=p[4];
-f=p[5];
-g=p[6];
-h=p[7];
-this.cache=[[a,b,c,d,a],[e,f,g,h,e],[a,d,h,e,a],[d,c,g,h,d],[c,b,f,g,c],[b,a,e,f,b]];
-},draw:function(_54){
-this.cache=dojox.gfx3d.scheduler.bsp(this.cache,function(it){
-return it;
+
+dojo.declare("dojox.gfx3d.Polygon", dojox.gfx3d.Object, {
+	constructor: function(){
+		// summary: a generic triangle 
+		//	(this is a helper object, which is defined for convenience)
+		this.object = dojo.clone(dojox.gfx3d.defaultPolygon);
+	},
+
+	setObject: function(newObject){
+		// summary: setup the object
+		// newObject: Array of points || Object
+		this.object = dojox.gfx.makeParameters(this.object, (newObject instanceof Array) ? {path: newObject} : newObject)
+		return this;
+	},
+
+	render: function(camera){
+		var m = dojox.gfx3d.matrix.multiply(camera, this.matrix);
+		this.cache = dojo.map(this.object.path, function(item){
+			return dojox.gfx3d.matrix.multiplyPoint(m, item);
+		});
+		// add the first point to close the polyline
+		this.cache.push(this.cache[0]);
+	},
+
+	draw: function(lighting){
+		if(this.shape){
+			this.shape.setShape({points: this.cache});
+		}else{
+			this.shape = this.renderer.createPolyline({points: this.cache});
+		}
+
+		this.shape.setStroke(this.strokeStyle)
+			.setFill(this.toStdFill(lighting, dojox.gfx3d.matrix.normalize(this.cache)));
+	},
+
+	getZOrder: function(){
+		var zOrder = 0;
+		// using naive iteration to speed things up a bit by avoiding function call overhead
+		for(var x=0; x<this.cache.length; x++){
+			zOrder += this.cache[x].z;
+		}
+		return (this.cache.length > 1) ?  zOrder / this.cache.length : 0;
+	},
+
+	getOutline: function(){
+		return this.cache.slice(0, 3);
+	}
 });
-var _55=this.cache.slice(3);
-if(this.shape){
-this.shape.clear();
-}else{
-this.shape=this.renderer.createGroup();
-}
-for(var x=0;x<_55.length;x++){
-this.shape.createPolyline(_55[x]).setStroke(this.strokeStyle).setFill(this.toStdFill(_54,dojox.gfx3d.vector.normalize(_55[x])));
-}
-},getZOrder:function(){
-var top=this.cache[0][0];
-var _56=this.cache[1][2];
-return (top.z+_56.z)/2;
-}});
-dojo.declare("dojox.gfx3d.Cylinder",dojox.gfx3d.Object,{constructor:function(){
-this.object=dojo.clone(dojox.gfx3d.defaultCylinder);
-},render:function(_57){
-var m=dojox.gfx3d.matrix.multiply(_57,this.matrix);
-var _58=[0,Math.PI/4,Math.PI/3];
-var _59=dojox.gfx3d.matrix.multiplyPoint(m,this.object.center);
-var _5a=dojo.map(_58,function(_5b){
-return {x:this.center.x+this.radius*Math.cos(_5b),y:this.center.y+this.radius*Math.sin(_5b),z:this.center.z};
-},this.object);
-_5a=dojo.map(_5a,function(_5c){
-return dojox.gfx3d.vector.substract(dojox.gfx3d.matrix.multiplyPoint(m,_5c),_59);
+
+dojo.declare("dojox.gfx3d.Cube", dojox.gfx3d.Object, {
+	constructor: function(){
+		// summary: a generic triangle 
+		//	(this is a helper object, which is defined for convenience)
+		this.object = dojo.clone(dojox.gfx3d.defaultCube);
+		this.polygons = [];
+	},
+
+	setObject: function(newObject){
+		// summary: setup the object
+		// newObject: Array of points || Object
+		this.object = dojox.gfx.makeParameters(this.object, newObject);
+	},
+
+	render: function(camera){
+		// parse the top, bottom to get 6 polygons:
+		var a = this.object.top;
+		var g = this.object.bottom;
+		var b = {x: g.x, y: a.y, z: a.z};
+		var c = {x: g.x, y: g.y, z: a.z};
+		var d = {x: a.x, y: g.y, z: a.z};
+		var e = {x: a.x, y: a.y, z: g.z};
+		var f = {x: g.x, y: a.y, z: g.z};
+		var h = {x: a.x, y: g.y, z: g.z};
+		var polygons = [a, b, c, d, e, f, g, h];
+		var m = dojox.gfx3d.matrix.multiply(camera, this.matrix);
+		var p = dojo.map(polygons, function(item){
+			return dojox.gfx3d.matrix.multiplyPoint(m, item);
+		});
+		a = p[0]; b = p[1]; c = p[2]; d = p[3]; e = p[4]; f = p[5]; g = p[6]; h = p[7];
+		this.cache = [[a, b, c, d, a], [e, f, g, h, e], [a, d, h, e, a], [d, c, g, h, d], [c, b, f, g, c], [b, a, e, f, b]];
+	},
+
+	draw: function(lighting){
+		// use bsp to sort.
+		this.cache = dojox.gfx3d.scheduler.bsp(this.cache, function(it){ return it; });
+		// only the last 3 polys are visible.
+		var cache = this.cache.slice(3);
+
+		if(this.shape){
+			this.shape.clear();
+		}else{
+			this.shape = this.renderer.createGroup();
+		}
+		for(var x=0; x<cache.length; x++){
+			this.shape.createPolyline(cache[x])
+				.setStroke(this.strokeStyle)
+				.setFill(this.toStdFill(lighting, dojox.gfx3d.vector.normalize(cache[x])));
+		}
+		/*
+		dojo.forEach(cache, function(item){
+			this.shape.createPolyline(item)
+				.setStroke(this.strokeStyle)
+				.setFill(this.toStdFill(lighting, dojox.gfx3d.vector.normalize(item)));
+		}, this);
+		*/
+	},
+
+	getZOrder: function(){
+		var top = this.cache[0][0];
+		var bottom = this.cache[1][2];
+		return (top.z + bottom.z) / 2;
+	}
 });
-var A={xx:_5a[0].x*_5a[0].y,xy:_5a[0].y*_5a[0].y,xz:1,yx:_5a[1].x*_5a[1].y,yy:_5a[1].y*_5a[1].y,yz:1,zx:_5a[2].x*_5a[2].y,zy:_5a[2].y*_5a[2].y,zz:1,dx:0,dy:0,dz:0};
-var B=dojo.map(_5a,function(_5d){
-return -Math.pow(_5d.x,2);
+
+
+dojo.declare("dojox.gfx3d.Cylinder", dojox.gfx3d.Object, {
+	constructor: function(){
+		this.object = dojo.clone(dojox.gfx3d.defaultCylinder);
+	},
+
+	render: function(camera){
+		// get the bottom surface first 
+		var m = dojox.gfx3d.matrix.multiply(camera, this.matrix);
+		var angles = [0, Math.PI/4, Math.PI/3];
+		var center = dojox.gfx3d.matrix.multiplyPoint(m, this.object.center);
+		var marks = dojo.map(angles, function(item){
+			return {x: this.center.x + this.radius * Math.cos(item), 
+				y: this.center.y + this.radius * Math.sin(item), z: this.center.z};
+			}, this.object);
+
+		marks = dojo.map(marks, function(item){
+			return dojox.gfx3d.vector.substract(dojox.gfx3d.matrix.multiplyPoint(m, item), center);
+		});
+
+		// Use the algorithm here:
+		// http://www.3dsoftware.com/Math/PlaneCurves/EllipseAlgebra/
+		// After we normalize the marks, the equation is:
+		// a x^2 + 2b xy + cy^2 + f = 0: let a = 1
+		//  so the final equation is:
+		//  [ xy, y^2, 1] * [2b, c, f]' = [ -x^2 ]'
+
+		var A = {
+			xx: marks[0].x * marks[0].y, xy: marks[0].y * marks[0].y, xz: 1,
+			yx: marks[1].x * marks[1].y, yy: marks[1].y * marks[1].y, yz: 1,
+			zx: marks[2].x * marks[2].y, zy: marks[2].y * marks[2].y, zz: 1,
+			dx: 0, dy: 0, dz: 0
+		};
+		var B = dojo.map(marks, function(item){
+			return -Math.pow(item.x, 2);
+		});
+
+		// X is 2b, c, f
+		var X = dojox.gfx3d.matrix.multiplyPoint(dojox.gfx3d.matrix.invert(A), B[0], B[1], B[2]);
+		var theta = Math.atan2(X.x, 1 - X.y) / 2;
+
+		// rotate the marks back to the canonical form
+		var probes = dojo.map(marks, function(item){
+			return dojox.gfx.matrix.multiplyPoint(dojox.gfx.matrix.rotate(-theta), item.x, item.y);
+		});
+
+		// we are solving the equation: Ax = b
+		// A = [x^2, y^2] X = [1/a^2, 1/b^2]', b = [1, 1]'
+		// so rx = Math.sqrt(1/ ( inv(A)[1:] * b ) );
+		// so ry = Math.sqrt(1/ ( inv(A)[2:] * b ) );
+
+		var a = Math.pow(probes[0].x, 2);
+		var b = Math.pow(probes[0].y, 2);
+		var c = Math.pow(probes[1].x, 2);
+		var d = Math.pow(probes[1].y, 2);
+
+		// the invert matrix is 
+		// 1/(ad - bc) [ d, -b; -c, a];
+		var rx = Math.sqrt((a * d - b * c) / (d - b));
+		var ry = Math.sqrt((a * d - b * c) / (a - c));
+		if(rx < ry){
+			var t = rx;
+			rx = ry;
+			ry = t;
+			theta -= Math.PI/2;
+		}
+
+		var top = dojox.gfx3d.matrix.multiplyPoint(m, 
+			dojox.gfx3d.vector.sum(this.object.center, {x: 0, y:0, z: this.object.height})); 
+
+		var gradient = this.fillStyle.type == "constant" ? this.fillStyle.color
+			: dojox.gfx3d.gradient(this.renderer.lighting, this.fillStyle, this.object.center, this.object.radius, Math.PI, 2 * Math.PI, m);
+		if(isNaN(rx) || isNaN(ry) || isNaN(theta)){
+			// in case the cap is invisible (parallel to the incident vector)
+			rx = this.object.radius, ry = 0, theta = 0;
+		}
+		this.cache = {center: center, top: top, rx: rx, ry: ry, theta: theta, gradient: gradient};
+	},
+
+	draw: function(){
+		var c = this.cache, v = dojox.gfx3d.vector, m = dojox.gfx.matrix,
+			centers = [c.center, c.top], normal = v.substract(c.top, c.center);
+		if(v.dotProduct(normal, this.renderer.lighting.incident) > 0){
+			centers = [c.top, c.center];
+			normal = v.substract(c.center, c.top);
+		}
+
+		var color = this.renderer.lighting[this.fillStyle.type](normal, this.fillStyle.finish, this.fillStyle.color),
+			d = Math.sqrt( Math.pow(c.center.x - c.top.x, 2) + Math.pow(c.center.y - c.top.y, 2) );
+
+		if(this.shape){
+			this.shape.clear();
+		}else{
+			this.shape = this.renderer.createGroup();
+		}
+		
+		this.shape.createPath("")
+			.moveTo(0, -c.rx)
+			.lineTo(d, -c.rx)
+			.lineTo(d, c.rx)
+			.lineTo(0, c.rx)
+			.arcTo(c.ry, c.rx, 0, true, true, 0, -c.rx)
+			.setFill(c.gradient).setStroke(this.strokeStyle)
+			.setTransform([m.translate(centers[0]), 
+				m.rotate(Math.atan2(centers[1].y - centers[0].y, centers[1].x - centers[0].x))]);
+
+		if(c.rx > 0 && c.ry > 0){
+			this.shape.createEllipse({cx: centers[1].x, cy: centers[1].y, rx: c.rx, ry: c.ry})
+				.setFill(color).setStroke(this.strokeStyle)
+				.applyTransform(m.rotateAt(c.theta, centers[1]));
+		}
+	}
 });
-var X=dojox.gfx3d.matrix.multiplyPoint(dojox.gfx3d.matrix.invert(A),B[0],B[1],B[2]);
-var _5e=Math.atan2(X.x,1-X.y)/2;
-var _5f=dojo.map(_5a,function(_60){
-return dojox.gfx.matrix.multiplyPoint(dojox.gfx.matrix.rotate(-_5e),_60.x,_60.y);
+
+
+// the ultimate container of 3D world
+dojo.declare("dojox.gfx3d.Viewport", dojox.gfx.Group, {
+	constructor: function(){
+		// summary: a viewport/container for 3D objects, which knows
+		// the camera and lightings
+
+		// matrix: dojox.gfx3d.matrix: world transform
+		// dimension: Object: the dimension of the canvas
+		this.dimension = null;
+
+		// objects: Array: all 3d Objects
+		this.objects = [];
+		// todos: Array: all 3d Objects that needs to redraw
+		this.todos = [];
+
+		// FIXME: memory leak?
+		this.renderer = this;
+		// Using zOrder as the default scheduler
+		this.schedule = dojox.gfx3d.scheduler.zOrder;
+		this.draw = dojox.gfx3d.drawer.conservative;
+		// deep: boolean, true means the whole viewport needs to re-render, redraw
+		this.deep = false;
+
+		// lights: Array: an array of light objects
+		this.lights = [];
+		this.lighting = null;
+	},
+
+	setCameraTransform: function(matrix){
+		// summary: sets a transformation matrix
+		// matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx.matrix.Matrix 
+		//	constructor for a list of acceptable arguments)
+		this.camera = dojox.gfx3d.matrix.clone(matrix ? dojox.gfx3d.matrix.normalize(matrix) : dojox.gfx3d.identity, true);
+		this.invalidate();
+		return this;	// self
+	},
+
+	applyCameraRightTransform: function(matrix){
+		// summary: multiplies the existing matrix with an argument on right side
+		//	(this.matrix * matrix)
+		// matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx3d.matrix.Matrix 
+		//	constructor for a list of acceptable arguments)
+		return matrix ? this.setCameraTransform([this.camera, matrix]) : this;	// self
+	},
+
+	applyCameraLeftTransform: function(matrix){
+		// summary: multiplies the existing matrix with an argument on left side
+		//	(matrix * this.matrix)
+		// matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx3d.matrix.Matrix 
+		//	constructor for a list of acceptable arguments)
+		return matrix ? this.setCameraTransform([matrix, this.camera]) : this;	// self
+	},
+
+	applyCameraTransform: function(matrix){
+		// summary: a shortcut for dojox.gfx3d.Object.applyRightTransform
+		// matrix: dojox.gfx3d.matrix.Matrix: a matrix or a matrix-like object
+		//	(see an argument of dojox.gfx3d.matrix.Matrix 
+		//	constructor for a list of acceptable arguments)
+		return this.applyCameraRightTransform(matrix); // self
+	},
+
+	setLights: function(/* Array || Object */lights, /* Color, optional */ ambient, 
+		/* Color, optional */ specular){
+		// summary: set the lights
+		// lights: Array: an array of light object
+		// or lights object
+		// ambient: Color: an ambient object
+		// specular: Color: an specular object
+		this.lights = (lights instanceof Array) ? {sources: lights, ambient: ambient, specular: specular} : lights;
+		var view = {x: 0, y: 0, z: 1};
+
+		this.lighting = new dojox.gfx3d.lighting.Model(view, this.lights.sources, 
+				this.lights.ambient, this.lights.specular);
+		this.invalidate();
+		return this;
+	},
+
+	addLights: function(lights){
+		// summary: add new light/lights to the viewport.
+		// lights: Array || light object: light object(s)
+		return this.setLights(this.lights.sources.concat(lights));
+	},
+
+	addTodo: function(newObject){
+		// NOTE: Viewport implements almost the same addTodo, 
+		// except calling invalidate, since invalidate is used as
+		// any modification needs to redraw the object itself, call invalidate.
+		// then call render.
+		if(dojo.every(this.todos, 
+			function(item){
+				return item != newObject; 
+			}
+		)){
+			this.todos.push(newObject);
+		}
+	},
+
+	invalidate: function(){
+		this.deep = true;
+		this.todos = this.objects;
+	},
+
+	setDimensions: function(dim){
+		if(dim){
+			var w = dojo.isString(dim.width) ? parseInt(dim.width)  : dim.width;
+			var h = dojo.isString(dim.height) ? parseInt(dim.height) : dim.height;
+			var trs = this.rawNode.style;
+			trs.height = h;
+			trs.width = w;
+			this.dimension = {
+				width:  w,
+				height: h
+			};
+		}else{
+			this.dimension = null;
+		}
+	},
+
+	render: function(){
+		// summary: iterate all children and call their render callback function.
+		if(!this.todos.length){ return; }
+		// console.debug("Viewport::render");
+		var m = dojox.gfx3d.matrix;
+		
+		// Iterate the todos and call render to prepare the rendering:
+		for(var x=0; x<this.todos.length; x++){
+			this.todos[x].render(dojox.gfx3d.matrix.normalize([
+				m.cameraRotateXg(180),
+				m.cameraTranslate(0, this.dimension.height, 0),
+				this.camera
+			]), this.deep);
+		}
+
+		this.objects = this.schedule(this.objects);
+		this.draw(this.todos, this.objects, this);
+		this.todos = [];
+		this.deep = false;
+	}
+
 });
-var a=Math.pow(_5f[0].x,2);
-var b=Math.pow(_5f[0].y,2);
-var c=Math.pow(_5f[1].x,2);
-var d=Math.pow(_5f[1].y,2);
-var rx=Math.sqrt((a*d-b*c)/(d-b));
-var ry=Math.sqrt((a*d-b*c)/(a-c));
-if(rx<ry){
-var t=rx;
-rx=ry;
-ry=t;
-_5e-=Math.PI/2;
-}
-var top=dojox.gfx3d.matrix.multiplyPoint(m,dojox.gfx3d.vector.sum(this.object.center,{x:0,y:0,z:this.object.height}));
-var _61=this.fillStyle.type=="constant"?this.fillStyle.color:dojox.gfx3d.gradient(this.renderer.lighting,this.fillStyle,this.object.center,this.object.radius,Math.PI,2*Math.PI,m);
-if(isNaN(rx)||isNaN(ry)||isNaN(_5e)){
-rx=this.object.radius,ry=0,_5e=0;
-}
-this.cache={center:_59,top:top,rx:rx,ry:ry,theta:_5e,gradient:_61};
-},draw:function(){
-var c=this.cache,v=dojox.gfx3d.vector,m=dojox.gfx.matrix,_62=[c.center,c.top],_63=v.substract(c.top,c.center);
-if(v.dotProduct(_63,this.renderer.lighting.incident)>0){
-_62=[c.top,c.center];
-_63=v.substract(c.center,c.top);
-}
-var _64=this.renderer.lighting[this.fillStyle.type](_63,this.fillStyle.finish,this.fillStyle.color),d=Math.sqrt(Math.pow(c.center.x-c.top.x,2)+Math.pow(c.center.y-c.top.y,2));
-if(this.shape){
-this.shape.clear();
-}else{
-this.shape=this.renderer.createGroup();
-}
-this.shape.createPath("").moveTo(0,-c.rx).lineTo(d,-c.rx).lineTo(d,c.rx).lineTo(0,c.rx).arcTo(c.ry,c.rx,0,true,true,0,-c.rx).setFill(c.gradient).setStroke(this.strokeStyle).setTransform([m.translate(_62[0]),m.rotate(Math.atan2(_62[1].y-_62[0].y,_62[1].x-_62[0].x))]);
-if(c.rx>0&&c.ry>0){
-this.shape.createEllipse({cx:_62[1].x,cy:_62[1].y,rx:c.rx,ry:c.ry}).setFill(_64).setStroke(this.strokeStyle).applyTransform(m.rotateAt(c.theta,_62[1]));
-}
-}});
-dojo.declare("dojox.gfx3d.Viewport",dojox.gfx.Group,{constructor:function(){
-this.dimension=null;
-this.objects=[];
-this.todos=[];
-this.renderer=this;
-this.schedule=dojox.gfx3d.scheduler.zOrder;
-this.draw=dojox.gfx3d.drawer.conservative;
-this.deep=false;
-this.lights=[];
-this.lighting=null;
-},setCameraTransform:function(_65){
-this.camera=dojox.gfx3d.matrix.clone(_65?dojox.gfx3d.matrix.normalize(_65):dojox.gfx3d.identity,true);
-this.invalidate();
-return this;
-},applyCameraRightTransform:function(_66){
-return _66?this.setCameraTransform([this.camera,_66]):this;
-},applyCameraLeftTransform:function(_67){
-return _67?this.setCameraTransform([_67,this.camera]):this;
-},applyCameraTransform:function(_68){
-return this.applyCameraRightTransform(_68);
-},setLights:function(_69,_6a,_6b){
-this.lights=(_69 instanceof Array)?{sources:_69,ambient:_6a,specular:_6b}:_69;
-var _6c={x:0,y:0,z:1};
-this.lighting=new dojox.gfx3d.lighting.Model(_6c,this.lights.sources,this.lights.ambient,this.lights.specular);
-this.invalidate();
-return this;
-},addLights:function(_6d){
-return this.setLights(this.lights.sources.concat(_6d));
-},addTodo:function(_6e){
-if(dojo.every(this.todos,function(_6f){
-return _6f!=_6e;
-})){
-this.todos.push(_6e);
-}
-},invalidate:function(){
-this.deep=true;
-this.todos=this.objects;
-},setDimensions:function(dim){
-if(dim){
-var w=dojo.isString(dim.width)?parseInt(dim.width):dim.width;
-var h=dojo.isString(dim.height)?parseInt(dim.height):dim.height;
-var trs=this.rawNode.style;
-trs.height=h;
-trs.width=w;
-this.dimension={width:w,height:h};
-}else{
-this.dimension=null;
-}
-},render:function(){
-if(!this.todos.length){
-return;
-}
-var m=dojox.gfx3d.matrix;
-for(var x=0;x<this.todos.length;x++){
-this.todos[x].render(dojox.gfx3d.matrix.normalize([m.cameraRotateXg(180),m.cameraTranslate(0,this.dimension.height,0),this.camera]),this.deep);
-}
-this.objects=this.schedule(this.objects);
-this.draw(this.todos,this.objects,this);
-this.todos=[];
-this.deep=false;
-}});
-dojox.gfx3d.Viewport.nodeType=dojox.gfx.Group.nodeType;
-dojox.gfx3d._creators={createEdges:function(_70,_71){
-return this.create3DObject(dojox.gfx3d.Edges,_70,_71);
-},createTriangles:function(_72,_73){
-return this.create3DObject(dojox.gfx3d.Triangles,_72,_73);
-},createQuads:function(_74,_75){
-return this.create3DObject(dojox.gfx3d.Quads,_74,_75);
-},createPolygon:function(_76){
-return this.create3DObject(dojox.gfx3d.Polygon,_76);
-},createOrbit:function(_77){
-return this.create3DObject(dojox.gfx3d.Orbit,_77);
-},createCube:function(_78){
-return this.create3DObject(dojox.gfx3d.Cube,_78);
-},createCylinder:function(_79){
-return this.create3DObject(dojox.gfx3d.Cylinder,_79);
-},createPath3d:function(_7a){
-return this.create3DObject(dojox.gfx3d.Path3d,_7a);
-},createScene:function(){
-return this.create3DObject(dojox.gfx3d.Scene);
-},create3DObject:function(_7b,_7c,_7d){
-var obj=new _7b();
-this.adopt(obj);
-if(_7c){
-obj.setObject(_7c,_7d);
-}
-return obj;
-},adopt:function(obj){
-obj.renderer=this.renderer;
-obj.parent=this;
-this.objects.push(obj);
-this.addTodo(obj);
-return this;
-},abandon:function(obj,_7e){
-for(var i=0;i<this.objects.length;++i){
-if(this.objects[i]==obj){
-this.objects.splice(i,1);
-}
-}
-obj.parent=null;
-return this;
-},setScheduler:function(_7f){
-this.schedule=_7f;
-},setDrawer:function(_80){
-this.draw=_80;
-}};
-dojo.extend(dojox.gfx3d.Viewport,dojox.gfx3d._creators);
-dojo.extend(dojox.gfx3d.Scene,dojox.gfx3d._creators);
+
+//FIXME: Viewport cannot masquerade as a Group
+dojox.gfx3d.Viewport.nodeType = dojox.gfx.Group.nodeType;
+
+dojox.gfx3d._creators = {
+	// summary: object creators
+	createEdges: function(edges, style){
+		// summary: creates an edge object 
+		// line: Object: a edge object (see dojox.gfx3d.defaultPath)
+		return this.create3DObject(dojox.gfx3d.Edges, edges, style);	// dojox.gfx3d.Edge
+	},
+	createTriangles: function(tris, style){
+		// summary: creates an edge object 
+		// line: Object: a edge object (see dojox.gfx3d.defaultPath)
+		return this.create3DObject(dojox.gfx3d.Triangles, tris, style);	// dojox.gfx3d.Edge
+	},
+	createQuads: function(quads, style){
+		// summary: creates an edge object 
+		// line: Object: a edge object (see dojox.gfx3d.defaultPath)
+		return this.create3DObject(dojox.gfx3d.Quads, quads, style);	// dojox.gfx3d.Edge
+	},
+	createPolygon: function(points){
+		// summary: creates an triangle object 
+		// points: Array of points || Object 
+		return this.create3DObject(dojox.gfx3d.Polygon, points);	// dojox.gfx3d.Polygon
+	},
+
+	createOrbit: function(orbit){
+		// summary: creates an triangle object 
+		// points: Array of points || Object 
+		return this.create3DObject(dojox.gfx3d.Orbit, orbit);	// dojox.gfx3d.Cube
+	},
+
+	createCube: function(cube){
+		// summary: creates an triangle object 
+		// points: Array of points || Object 
+		return this.create3DObject(dojox.gfx3d.Cube, cube);	// dojox.gfx3d.Cube
+	},
+
+	createCylinder: function(cylinder){
+		// summary: creates an triangle object 
+		// points: Array of points || Object 
+		return this.create3DObject(dojox.gfx3d.Cylinder, cylinder);	// dojox.gfx3d.Cube
+	},
+
+	createPath3d: function(path){
+		// summary: creates an edge object 
+		// line: Object: a edge object (see dojox.gfx3d.defaultPath)
+		return this.create3DObject(dojox.gfx3d.Path3d, path);	// dojox.gfx3d.Edge
+	},
+	createScene: function(){
+		// summary: creates an triangle object 
+		// line: Object: a triangle object (see dojox.gfx3d.defaultPath)
+		return this.create3DObject(dojox.gfx3d.Scene);	// dojox.gfx3d.Scene
+	},
+
+	create3DObject: function(objectType, rawObject, style){
+		// summary: creates an instance of the passed shapeType class
+		// shapeType: Function: a class constructor to create an instance of
+		// rawShape: Object: properties to be passed in to the classes "setShape" method
+		var obj = new objectType();
+		this.adopt(obj);
+		if(rawObject){ obj.setObject(rawObject, style); }
+		return obj;	// dojox.gfx3d.Object
+	},
+	// todo : override the add/remove if necessary
+	adopt: function(obj){
+		// summary: adds a shape to the list
+		// shape: dojox.gfx.Shape: a shape
+		obj.renderer = this.renderer; // obj._setParent(this, null); more TODOs HERER?
+		obj.parent = this;
+		this.objects.push(obj);
+		this.addTodo(obj);
+		return this;
+	},
+	abandon: function(obj, silently){
+		// summary: removes a shape from the list
+		// silently: Boolean?: if true, do not redraw a picture yet
+		for(var i = 0; i < this.objects.length; ++i){
+			if(this.objects[i] == obj){
+				this.objects.splice(i, 1);
+			}
+		}
+		// if(this.rawNode == shape.rawNode.parentNode){
+		//	this.rawNode.removeChild(shape.rawNode);
+		// }
+		// obj._setParent(null, null);
+		obj.parent = null;
+		return this;	// self
+	},
+
+
+	setScheduler: function(scheduler){
+		this.schedule = scheduler;
+	},
+
+	setDrawer: function(drawer){
+		this.draw = drawer;
+	}
+};
+
+dojo.extend(dojox.gfx3d.Viewport, dojox.gfx3d._creators);
+dojo.extend(dojox.gfx3d.Scene, dojox.gfx3d._creators);
 delete dojox.gfx3d._creators;
-dojo.extend(dojox.gfx.Surface,{createViewport:function(){
-var _81=this.createObject(dojox.gfx3d.Viewport,null,true);
-_81.setDimensions(this.getDimensions());
-return _81;
-}});
-}
+
+
+//FIXME: extending dojox.gfx.Surface and masquerading Viewport as Group is hacky!
+
+// Add createViewport to dojox.gfx.Surface
+dojo.extend(dojox.gfx.Surface, {
+	createViewport: function(){
+		//FIXME: createObject is non-public method!
+		var viewport = this.createObject(dojox.gfx3d.Viewport, null, true);
+		//FIXME: this may not work with dojox.gfx.Group !!
+		viewport.setDimensions(this.getDimensions());
+		return viewport;
+	}
+});
diff --git a/dojox/gfx3d/scheduler.js b/dojox/gfx3d/scheduler.js
index 8d18a91..518d3b2 100644
--- a/dojox/gfx3d/scheduler.js
+++ b/dojox/gfx3d/scheduler.js
@@ -1,93 +1,142 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.gfx3d.scheduler"]){
-dojo._hasResource["dojox.gfx3d.scheduler"]=true;
 dojo.provide("dojox.gfx3d.scheduler");
 dojo.provide("dojox.gfx3d.drawer");
 dojo.require("dojox.gfx3d.vector");
-dojo.mixin(dojox.gfx3d.scheduler,{zOrder:function(_1,_2){
-_2=_2?_2:dojox.gfx3d.scheduler.order;
-_1.sort(function(a,b){
-return _2(b)-_2(a);
-});
-return _1;
-},bsp:function(_3,_4){
-_4=_4?_4:dojox.gfx3d.scheduler.outline;
-var p=new dojox.gfx3d.scheduler.BinarySearchTree(_3[0],_4);
-dojo.forEach(_3.slice(1),function(_5){
-p.add(_5,_4);
-});
-return p.iterate(_4);
-},order:function(it){
-return it.getZOrder();
-},outline:function(it){
-return it.getOutline();
-}});
-dojo.declare("dojox.gfx3d.scheduler.BinarySearchTree",null,{constructor:function(_6,_7){
-this.plus=null;
-this.minus=null;
-this.object=_6;
-var o=_7(_6);
-this.orient=o[0];
-this.normal=dojox.gfx3d.vector.normalize(o);
-},add:function(_8,_9){
-var _a=0.5,o=_9(_8),v=dojox.gfx3d.vector,n=this.normal,a=this.orient,_b=dojox.gfx3d.scheduler.BinarySearchTree;
-if(dojo.every(o,function(_c){
-return Math.floor(_a+v.dotProduct(n,v.substract(_c,a)))<=0;
-})){
-if(this.minus){
-this.minus.add(_8,_9);
-}else{
-this.minus=new _b(_8,_9);
-}
-}else{
-if(dojo.every(o,function(_d){
-return Math.floor(_a+v.dotProduct(n,v.substract(_d,a)))>=0;
-})){
-if(this.plus){
-this.plus.add(_8,_9);
-}else{
-this.plus=new _b(_8,_9);
-}
-}else{
-throw "The case: polygon cross siblings' plate is not implemneted yet";
-}
-}
-},iterate:function(_e){
-var _f=0.5;
-var v=dojox.gfx3d.vector;
-var _10=[];
-var _11=null;
-var _12={x:0,y:0,z:-10000};
-if(Math.floor(_f+v.dotProduct(this.normal,v.substract(_12,this.orient)))<=0){
-_11=[this.plus,this.minus];
-}else{
-_11=[this.minus,this.plus];
-}
-if(_11[0]){
-_10=_10.concat(_11[0].iterate());
-}
-_10.push(this.object);
-if(_11[1]){
-_10=_10.concat(_11[1].iterate());
-}
-return _10;
-}});
-dojo.mixin(dojox.gfx3d.drawer,{conservative:function(_13,_14,_15){
-dojo.forEach(this.objects,function(_16){
-_16.destroy();
+
+dojo.mixin(dojox.gfx3d.scheduler, {
+	zOrder: function(buffer, order){
+		order = order ? order : dojox.gfx3d.scheduler.order;
+		buffer.sort(function(a, b){
+			return order(b) - order(a);
+		});
+		return buffer;
+	},
+
+	bsp: function(buffer, outline){
+		// console.debug("BSP scheduler");
+		outline = outline ? outline : dojox.gfx3d.scheduler.outline;
+		var p = new dojox.gfx3d.scheduler.BinarySearchTree(buffer[0], outline);
+		dojo.forEach(buffer.slice(1), function(item){ p.add(item, outline); });
+		return p.iterate(outline);
+	},
+
+	// default implementation
+	order: function(it){
+		return it.getZOrder();
+	},
+
+	outline: function(it){
+		return it.getOutline();
+	}
+
 });
-dojo.forEach(_14,function(_17){
-_17.draw(_15.lighting);
+
+dojo.declare("dojox.gfx3d.scheduler.BinarySearchTree", null, {
+	constructor: function(obj, outline){
+		// summary: build the binary search tree, using binary space partition algorithm.
+		// The idea is for any polygon, for example, (a, b, c), the space is divided by 
+		// the plane into two space: plus and minus. 
+		// 
+		// for any arbitary vertex p, if(p - a) dotProduct n = 0, p is inside the plane,
+		// > 0, p is in the plus space, vice versa for minus space. 
+		// n is the normal vector that is perpendicular the plate, defined as:
+		//            n = ( b - a) crossProduct ( c - a )
+		//
+		// in this implementation, n is declared as normal, ,a is declared as orient.
+		// 
+		// obj: object: dojox.gfx3d.Object
+		this.plus = null;
+		this.minus = null;
+		this.object = obj;
+
+		var o = outline(obj);
+		this.orient = o[0];
+		this.normal = dojox.gfx3d.vector.normalize(o);
+	},
+
+	add: function(obj, outline){
+		var epsilon = 0.5,
+			o = outline(obj),
+			v = dojox.gfx3d.vector,
+			n = this.normal,
+			a = this.orient,
+			BST = dojox.gfx3d.scheduler.BinarySearchTree;
+
+		if(
+			dojo.every(o, function(item){
+				return Math.floor(epsilon + v.dotProduct(n, v.substract(item, a))) <= 0;
+			})
+		){
+			if(this.minus){
+				this.minus.add(obj, outline);
+			}else{
+				this.minus = new BST(obj, outline);
+			}
+		}else if(
+			dojo.every(o, function(item){ 
+				return Math.floor(epsilon + v.dotProduct(n, v.substract(item, a))) >= 0; 
+			})
+		){
+			if(this.plus){
+				this.plus.add(obj, outline);
+			} else {
+				this.plus = new BST(obj, outline);
+			}
+		}else{
+			/*
+			dojo.forEach(o, function(item){
+				console.debug(v.dotProduct(n, v.substract(item, a)));
+			});
+			*/
+			throw "The case: polygon cross siblings' plate is not implemneted yet";
+		}
+	},
+
+	iterate: function(outline){
+		var epsilon = 0.5;
+		var v = dojox.gfx3d.vector;
+		var sorted = [];
+		var subs = null;
+		// FIXME: using Infinity here?
+		var view = {x: 0, y: 0, z: -10000};
+		if(Math.floor( epsilon + v.dotProduct(this.normal, v.substract(view, this.orient))) <= 0){
+			subs = [this.plus, this.minus];
+		}else{
+			subs = [this.minus, this.plus];
+		}
+
+		if(subs[0]){ 
+			sorted = sorted.concat(subs[0].iterate());
+		}
+
+		sorted.push(this.object);
+
+		if(subs[1]){ 
+			sorted = sorted.concat(subs[1].iterate());
+		}
+		return sorted;
+	}
+
 });
-},chart:function(_18,_19,_1a){
-dojo.forEach(this.todos,function(_1b){
-_1b.draw(_1a.lighting);
+
+dojo.mixin(dojox.gfx3d.drawer, {
+	conservative: function(todos, objects, viewport){
+		// console.debug('conservative draw');
+		dojo.forEach(this.objects, function(item){
+			item.destroy();
+		});
+		dojo.forEach(objects, function(item){
+			item.draw(viewport.lighting);
+		});
+	},
+	chart: function(todos, objects, viewport){
+		// NOTE: ondemand may require the todos' objects to use setShape
+		// to redraw themselves to maintain the z-order.
+
+		// console.debug('chart draw');
+		dojo.forEach(this.todos, function(item){
+			item.draw(viewport.lighting);
+		});
+	}
+	// More aggrasive optimization may re-order the DOM nodes using the order 
+	// of objects, and only elements of todos call setShape.
 });
-}});
-}
diff --git a/dojox/gfx3d/tests/test_camerarotate.html b/dojox/gfx3d/tests/test_camerarotate.html
new file mode 100644
index 0000000..e1cc4ab
--- /dev/null
+++ b/dojox/gfx3d/tests/test_camerarotate.html
@@ -0,0 +1,93 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Camera rotate of dojox.gfx3d.</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: false"></script>
+<script type="text/javascript" src="../object.js"></script>
+<script type="text/javascript" src="../scheduler.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+
+var angles = {x: 30, y: 30, z: 0};
+var cube = null;
+var view = null;
+
+rotate = function() {
+	var m = dojox.gfx3d.matrix;
+
+	if(dojo.byId('rx').checked){
+		angles.x += 1;
+	}
+	if(dojo.byId('ry').checked){
+		angles.y += 1;
+	}
+	if(dojo.byId('rz').checked){
+		angles.z += 1;
+	}
+	var t = m.normalize([
+		m.cameraTranslate(-300, -200, 0),
+		m.cameraRotateXg(angles.x), 
+		m.cameraRotateYg(angles.y), 
+		m.cameraRotateZg(angles.z)
+		]);
+	console.debug(t);
+	view.setCameraTransform(t);
+	view.render();
+}
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	view = surface.createViewport();
+
+	var c = {bottom: {x: 0, y: 0, z: 0}, top :{x: 100, y: 100, z: 100}};
+	var xaxis = [{x: 0, y: 0, z: 0}, {x: 200, y: 0, z: 0}];
+	var yaxis = [{x: 0, y: 0, z: 0}, {x: 0, y: 200, z: 0}];
+	var zaxis = [{x: 0, y: 0, z: 0}, {x: 0, y: 0, z: 200}];
+
+	var m = dojox.gfx3d.matrix;
+
+	view.createEdges(xaxis).setStroke({color: "red", width: 1});
+	view.createEdges(yaxis).setStroke({color: "green", width: 1});
+	view.createEdges(zaxis).setStroke({color: "blue", width: 1});
+		
+	cube = view.createCube(c).setStroke({color: "lime", width: 1});
+
+	var camera = dojox.gfx3d.matrix.normalize([
+		m.cameraTranslate(-300, -200, 0),
+		m.cameraRotateXg(angles.x), 
+		m.cameraRotateYg(angles.y), 
+		m.cameraRotateZg(angles.z)
+	]);
+
+	view.applyCameraTransform(camera);
+	view.render();
+	window.setInterval(rotate, 50);
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body class="tundra">
+	<h1>Camera rotate</h1>
+	<p>The cube is in the center (0, 0, 0): The color of X, Y, Z axes are red, green, blue. The view renders all the objects
+	in each frame, the <em>conservative</em> drawer is used.</p>
+<form>
+	<input id="rx" type="checkbox" name="rotateX" checked="true" value="on"/> 
+	<label for="rx"> Rotate around X-axis</label> <br/>
+	<input id="ry" type="checkbox" name="rotateY" checked="false" value="off"/> 
+	<label for="ry"> Rotate around Y-axis</label> <br/>
+	<input id="rz" type="checkbox" name="rotateZ" checked="false" value="off"/> 
+	<label for="rz"> Rotate around Z-axis</label> <br/>
+</form>
+
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_camerarotate_shaded.html b/dojox/gfx3d/tests/test_camerarotate_shaded.html
new file mode 100644
index 0000000..6fa6ac4
--- /dev/null
+++ b/dojox/gfx3d/tests/test_camerarotate_shaded.html
@@ -0,0 +1,101 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+	<title>Camera rotate of dojox.gfx3d.</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: false"></script>
+	<script type="text/javascript" src="../object.js"></script>
+	<script type="text/javascript" src="../scheduler.js"></script>
+	<script type="text/javascript">
+
+		dojo.require("dojox.gfx3d");
+
+		var angles = {x: 30, y: 30, z: 0};
+		var cube = null;
+		var view = null;
+
+		rotate = function() {
+			var m = dojox.gfx3d.matrix;
+
+			if(dojo.byId('rx').checked){
+				angles.x += 1;
+			}
+			if(dojo.byId('ry').checked){
+				angles.y += 1;
+			}
+			if(dojo.byId('rz').checked){
+				angles.z += 1;
+			}
+			var t = m.normalize([
+				m.cameraTranslate(-300, -200, 0),
+				m.cameraRotateXg(angles.x), 
+				m.cameraRotateYg(angles.y), 
+				m.cameraRotateZg(angles.z)
+				]);
+			// console.debug(t);
+			view.setCameraTransform(t);
+			view.render();
+		}
+
+		makeObjects = function(){
+			var surface = dojox.gfx.createSurface("test", 500, 500);
+			view = surface.createViewport();
+
+			view.setLights([
+					{ direction: { x: -10, y: -5, z: 5 }, color: "white"}
+				], 
+				{ color:"white", intensity: 2 },
+				"white"
+			);
+
+			var c = {bottom: {x: 0, y: 0, z: 0}, top :{x: 100, y: 100, z: 100}};
+			var xaxis = [{x: 0, y: 0, z: 0}, {x: 200, y: 0, z: 0}];
+			var yaxis = [{x: 0, y: 0, z: 0}, {x: 0, y: 200, z: 0}];
+			var zaxis = [{x: 0, y: 0, z: 0}, {x: 0, y: 0, z: 200}];
+
+			var m = dojox.gfx3d.matrix;
+
+			view.createEdges(xaxis).setStroke({color: "red", width: 1});
+			view.createEdges(yaxis).setStroke({color: "green", width: 1});
+			view.createEdges(zaxis).setStroke({color: "blue", width: 1});
+				
+			// setStroke({color: "lime", width: 1}).
+			cube = view.createCube(c).setFill({ type: "plastic", finish: "dull", color: "lime" });
+
+			var camera = dojox.gfx3d.matrix.normalize([
+				m.cameraTranslate(-300, -200, 0),
+				m.cameraRotateXg(angles.x), 
+				m.cameraRotateYg(angles.y), 
+				m.cameraRotateZg(angles.z)
+			]);
+
+			view.applyCameraTransform(camera);
+			view.render();
+			setInterval(rotate, 50);
+		};
+
+		dojo.addOnLoad(makeObjects);
+
+	</script>
+</head>
+<body class="tundra">
+	<h1>Camera rotate</h1>
+	<p>The cube is in the center (0, 0, 0): The color of X, Y, Z axes are red, green, blue. The view renders all the objects
+	in each frame, the <em>conservative</em> drawer is used.</p>
+	<form>
+		<input id="rx" type="checkbox" name="rotateX" checked="true" value="on"/> 
+		<label for="rx"> Rotate around X-axis</label> <br/>
+		<input id="ry" type="checkbox" name="rotateY" checked="false" value="off"/> 
+		<label for="ry"> Rotate around Y-axis</label> <br/>
+		<input id="rz" type="checkbox" name="rotateZ" checked="false" value="off"/> 
+		<label for="rz"> Rotate around Z-axis</label> <br/>
+	</form>
+
+	<div id="test" style="width: 500px; height: 500px;"></div>
+	<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_cube.html b/dojox/gfx3d/tests/test_cube.html
new file mode 100644
index 0000000..f5f1674
--- /dev/null
+++ b/dojox/gfx3d/tests/test_cube.html
@@ -0,0 +1,50 @@
+<html>
+<head>
+<title>Cube of dojox.gfx3d.</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<!--
+The next line should include Microsoft's Silverligth.js, if you plan to use the silverlight backend
+<script type="text/javascript" src="Silverlight.js"></script>
+-->
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+dojo.require("dojox.gfx3d");
+dojo.require("dojox.gfx.utils");
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	var view = surface.createViewport();
+	view.setLights([{direction: {x: -10, y: -5, z: 5}, color: "white"}], 
+			{color:"white", intensity: 2}, "white");
+	
+	var m = dojox.gfx3d.matrix;
+	var l = view.createCube({bottom: {x: 0, y: 0, z: 0}, top: {x: 100, y: 100, z: 100}})
+		.setFill({type: "plastic", finish: "dull", color: "lime"});
+		
+	var camera = [m.cameraRotateXg(20), m.cameraRotateYg(20), m.cameraTranslate(-200, -200, 0)];
+	view.applyCameraTransform(camera);
+	view.render();
+	
+	//dojo.byId("out1").value = dojo.byId("test").innerHTML;
+	//dojo.byId("out2").value = dojox.gfx.utils.toJson(surface, true);
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Cube Test</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<!--
+<p><button onclick="makeObjects();">Go</button></p>
+<p><textarea id="out1" cols="40" rows="5"></textarea></p>
+<p><textarea id="out2" cols="40" rows="5"></textarea></p>
+-->
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_cylinder.html b/dojox/gfx3d/tests/test_cylinder.html
new file mode 100644
index 0000000..cd1d5c1
--- /dev/null
+++ b/dojox/gfx3d/tests/test_cylinder.html
@@ -0,0 +1,66 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Cylinder test of dojox.gfx3d.</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript" src="../lighting.js"></script>
+<script type="text/javascript" src="../gradient.js"></script>
+<script type="text/javascript" src="../object.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 400);
+	var view = surface.createViewport();
+	view.setLights([
+			{direction: {x: 0, y: 0, z: -10}, color: "white"},
+			{direction: {x: 10, y: 0, z: -10}, color: "#444"}
+		], {color: "white", intensity: 2}, "white");
+
+	var m = dojox.gfx3d.matrix;
+	
+	view.createCylinder({})
+		.setTransform([m.translate(150, 250, 0), m.rotateZg(60), m.rotateXg(-60)])
+		.setStroke("black")
+		.setFill({type: "plastic", finish: "glossy", color: "red"});
+	
+	view.createCylinder({})
+		.setTransform([m.translate(150, 100, 0), m.rotateZg(45), m.rotateXg(-135)])
+		.setStroke("black")
+		.setFill({type: "plastic", finish: "shiny", color: "yellow"});
+
+	view.createCylinder({})
+		.setTransform([m.translate(250, 200, 0), m.rotateZg(-30), m.rotateXg(-30)])
+		.setStroke("black")
+		.setFill({type: "plastic", finish: "dull", color: "lime"});
+
+	//var camera = m.normalize([m.cameraRotateXg(15), m.cameraRotateYg(15), m.cameraTranslate(-200, -300, 0)]);
+	//var camera = m.normalize([m.cameraRotateXg(15), m.cameraRotateYg(15)]);
+	var camera = m.normalize({});
+
+	view.applyCameraTransform(camera);
+	view.render();
+};
+
+mdebug = function(matrix){
+	var m = dojox.gfx3d.matrix.normalize(matrix);
+	console.debug("xx: " + m.xx + ", xy: " + m.xy + " | xz:" + m.xz + " | dx:" + m.dx);
+	console.debug("yx: " + m.yx + ", yy: " + m.yy + " | yz:" + m.yz + " | dy:" + m.dy);
+	console.debug("zx: " + m.zx + ", zy: " + m.zy + " | zz:" + m.zz + " | dz:" + m.dz);
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+	<h1>Cylinder Test</h1>
+<div id="test" style="width: 500px; height: 400px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_drawer.html b/dojox/gfx3d/tests/test_drawer.html
new file mode 100644
index 0000000..3a9af1f
--- /dev/null
+++ b/dojox/gfx3d/tests/test_drawer.html
@@ -0,0 +1,92 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Pilot test of dojox.gfx3d.</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+
+var angles = {x: 0, y: 0, z: 0};
+var view = null;
+var cube = null;
+
+function moveMe(){
+	var p = dojo.byId("action");
+	var m = dojox.gfx3d.matrix;
+	if(p.value == "Move to Back!"){
+		console.debug(p.value);
+		p.value = "Move to Front!";
+		cube.setTransform(m.translate(20, 0, -120))
+	}else{
+		p.value = "Move to Back!";
+		cube.setTransform(m.translate(50, 0, 150))
+	}
+	cube.invalidate();
+	view.render();
+};
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	view = surface.createViewport();
+	var c = { bottom: {x: 0, y: 0, z: 0}, top :{x: 100, y: 100, z: 100} };
+	var xaxis = [{x: 0, y: 0, z: 0}, {x: 200, y: 0, z: 0}];
+	var yaxis = [{x: 0, y: 0, z: 0}, {x: 0, y: 200, z: 0}];
+	var zaxis = [{x: 0, y: 0, z: 0}, {x: 0, y: 0, z: 200}];
+
+	var m = dojox.gfx3d.matrix;
+
+	view.createEdges(xaxis).setStroke({color: "red", width: 1});
+	view.createEdges(yaxis).setStroke({color: "green", width: 1});
+	view.createEdges(zaxis).setStroke({color: "blue", width: 1});
+
+	view.createCube(c)
+		.setFill({type: "plastic", finish: dojox.gfx3d.lighting.finish.dull, color: "blue"})
+		.setStroke({color: "black", width: 1});
+
+	cube = view.createCube(c)
+		.setTransform(m.translate(50, 50, 150))
+		.setFill({type: "plastic", finish: dojox.gfx3d.lighting.finish.dull, color: "lime"})
+		.setStroke({color: "black", width: 1});
+
+	var camera = dojox.gfx3d.matrix.normalize([
+		m.cameraRotateXg(60), 
+		m.cameraRotateYg(30),
+		m.cameraTranslate(-200, -300, 0)
+	]);
+
+	view.applyCameraTransform(camera);
+	view.setLights([{direction: {x: 10, y: 7, z: 5}, color: "white"}], 
+			{color:"white", intensity: 2}, "white");
+	view.render();
+
+	// add the click event handler
+	dojo.connect(dojo.byId("action"), "onclick", moveMe);
+};
+
+mdebug = function(matrix){
+	var m = dojox.gfx3d.matrix.normalize(matrix);
+	console.debug("xx: " + m.xx + ", xy: " + m.xy + " | xz:" + m.xz + " | dx:" + m.dx);
+	console.debug("yx: " + m.yx + ", yy: " + m.yy + " | yz:" + m.yz + " | dy:" + m.dy);
+	console.debug("zx: " + m.zx + ", zy: " + m.zy + " | zz:" + m.zz + " | dz:" + m.dz);
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body class="tundra">
+	<h1>Pilot Test</h1>
+	<p> The color of X, Y, Z axes are red, green, blue. One cube is in the center (0, 0, 0), click the button to move the other one back
+	and forth, using this to test <em>dojox.gfx3d.drawer.conservative</em></p>
+	<input id="action" type="button" value="Move to Back!"/>
+
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_edges.html b/dojox/gfx3d/tests/test_edges.html
new file mode 100644
index 0000000..07b78f0
--- /dev/null
+++ b/dojox/gfx3d/tests/test_edges.html
@@ -0,0 +1,73 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Edges test of dojox.gfx3d.</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	var view = surface.createViewport();
+	var lines = [
+		{x: 100, y: 10, z: 5},
+		{x: 80, y: 80, z: 55},
+		{x: 120, y: 80, z: 75},
+		{x: 250, y: 92, z: 15},
+		{x: 200, y: 25, z: 5},
+		{x: 156, y: 40, z: 45}
+	];
+
+	var m = dojox.gfx3d.matrix;
+	var loop = view.createEdges(lines, "loop")
+		.setStroke({color: "blue", width: 1})
+		.applyTransform(dojox.gfx3d.matrix.translate({x: 0, y: 0, z: 0}));
+
+	var strip  = view.createEdges(lines, "strip")
+		.setStroke({color: "red", width: 1})
+		.applyTransform(dojox.gfx3d.matrix.translate({x: 0, y: 100, z: 0}));
+
+	var normal = view.createEdges(lines)
+		.setStroke({color: "lime", width: 1})
+		.applyTransform(dojox.gfx3d.matrix.translate({x: 0, y: 200, z: 0}));
+
+	var camera = dojox.gfx3d.matrix.normalize([
+		m.cameraRotateZg(20), 
+		//m.cameraRotateYg(30),
+		//m.cameraRotateXg(50),
+		m.cameraTranslate(0, 0, 0)
+	]);
+
+	view.applyCameraTransform(camera);
+	view.render();
+};
+
+mdebug = function(matrix){
+	var m = dojox.gfx3d.matrix.normalize(matrix);
+	console.debug("xx: " + m.xx + ", xy: " + m.xy + " | xz:" + m.xz + " | dx:" + m.dx);
+	console.debug("yx: " + m.yx + ", yy: " + m.yy + " | yz:" + m.yz + " | dy:" + m.dy);
+	console.debug("zx: " + m.zx + ", zy: " + m.zy + " | zz:" + m.zz + " | dz:" + m.dz);
+};
+
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+	<h1>Edges Test</h1>
+	<p> Test of the Edges, there are three modes</p>
+	<ul>
+		<li>none, any two vertice pair form one edge, lime</li>
+		<li>strip, vertices are connected by edges. red</li>
+		<li>loop, the same as strip, close the path, blue</li>
+	</ul>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_matrix.html b/dojox/gfx3d/tests/test_matrix.html
new file mode 100644
index 0000000..9acf399
--- /dev/null
+++ b/dojox/gfx3d/tests/test_matrix.html
@@ -0,0 +1,89 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo 3D Matrix</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+
+mdebug = function(matrix){
+	var m = dojox.gfx3d.matrix.normalize(matrix);
+	console.debug("xx: " + m.xx + ", xy: " + m.xy + " | xz:" + m.xz + " | dx:" + m.dx);
+	console.debug("yx: " + m.yx + ", yy: " + m.yy + " | yz:" + m.yz + " | dy:" + m.dy);
+	console.debug("zx: " + m.zx + ", zy: " + m.zy + " | zz:" + m.zz + " | dz:" + m.dz);
+};
+
+pdebug = function(point){
+	console.debug("x: " + point.x + ", y: " + point.y + ", z: " + point.z);
+};
+
+dojo.addOnLoad(function(){
+	var m = dojox.gfx3d.matrix;
+	var a = new m.Matrix3D();
+	console.debug("identity");	
+	mdebug(a);
+	a = m.rotateXg(30);
+	console.debug("rotateXg(30);");	
+	mdebug(a);
+	a = m.rotateYg(45);
+	console.debug("rotateYg(45);");	
+	mdebug(a);
+	a = m.rotateZg(90);
+	console.debug("rotateZg(90);");	
+	mdebug(a);
+	a = [new m.Matrix3D(), new m.Matrix3D(), new m.Matrix3D()];
+	console.debug("identity");	
+	mdebug(a);
+	a = [m.rotateXg(30), m.rotateXg(-30)];
+	console.debug("identity");	
+	mdebug(a);
+	var b = m.multiplyPoint(a, 10, 10, 10);
+	pdebug(b);
+	b = m.multiplyPoint(a, 10, 5, 10);
+	pdebug(b);
+	b = m.multiplyPoint(a, 10, 15, 5);
+	pdebug(b);
+
+	a = [m.scale(1,1,2), m.rotateXg(45)];
+	console.debug("a = [m.scale(1,1,2), m.rotateXg(45)];");
+	mdebug(a);
+	a = [m.rotateXg(45), m.scale(1,1,2)];
+	console.debug("a = [m.rotateXg(45), m.scale(1,1,2)];");
+	mdebug(a);
+
+	a = [m.scale(2,1,2), m.rotateYg(45)];
+	console.debug("a = [m.scale(2,1,2), m.rotateYg(45)];");
+	mdebug(a);
+	a = [m.rotateYg(45), m.scale(2,1,2)];
+	console.debug("a = [m.rotateYg(45), m.scale(2,1,2)];");
+	mdebug(a);
+
+	a = [m.scale(1,2,1), m.invert(m.rotateZg(45))];
+	console.debug("[m.scale(1,2,1), m.invert(m.rotateZg(45))];");
+	mdebug(a);
+	a = [m.invert(m.rotateZg(45)), m.scale(1,2,1)];
+	console.debug("a = [m.invert(m.rotateZg(45)), m.scale(1,2,1)];");
+	mdebug(a);
+
+	a = [a, m.invert(a)];
+	console.debug("identity");	
+	mdebug(a);
+
+	a = 5;
+	mdebug(a);
+	a = [2, m.scale(2,1,3)];
+	mdebug(a);
+});
+
+</script>
+</head>
+<body>
+	<h1>dojox.gfx3d.matrix test</h1>
+	<p>Please check the debug console for test results.</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_orbit.html b/dojox/gfx3d/tests/test_orbit.html
new file mode 100644
index 0000000..cadc043
--- /dev/null
+++ b/dojox/gfx3d/tests/test_orbit.html
@@ -0,0 +1,50 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Orbit test of dojox.gfx3d.</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	var view = surface.createViewport();
+	var m = dojox.gfx3d.matrix;
+
+	view.createOrbit({center: {x: 0, y: 0, z: 0}, radius: 80})
+		.setStroke({color: "blue", width: 1});
+
+	var camera = dojox.gfx3d.matrix.normalize([
+		m.cameraRotateXg(60), 
+		m.cameraRotateYg(30),
+		m.cameraRotateZg(0),
+		m.cameraTranslate(-300, -100, 0)
+	]);
+
+	view.applyCameraTransform(camera);
+	view.render();
+};
+
+mdebug = function(matrix){
+	var m = dojox.gfx3d.matrix.normalize(matrix);
+	console.debug("xx: " + m.xx + ", xy: " + m.xy + " | xz:" + m.xz + " | dx:" + m.dx);
+	console.debug("yx: " + m.yx + ", yy: " + m.yy + " | yz:" + m.yz + " | dy:" + m.dy);
+	console.debug("zx: " + m.zx + ", zy: " + m.zy + " | zz:" + m.zz + " | dz:" + m.dz);
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+	<h1>Orbit Test</h1>
+	<p>Test how orbit looks like in 3D</p>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_overlap.html b/dojox/gfx3d/tests/test_overlap.html
new file mode 100644
index 0000000..19f63d5
--- /dev/null
+++ b/dojox/gfx3d/tests/test_overlap.html
@@ -0,0 +1,69 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Test of dojox.gfx3d.scheduler</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+var view = null;	
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	view = surface.createViewport();
+	var tas = [
+		[{x: 100, y: 0, z: 0}, {x: 100, y: 100, z: 0}, {x: 50, y: 50, z: 50}],
+		[{x: 100, y: 0, z: 0}, {x: 100, y: 100, z: 0}, {x: 0, y: 70, z: 50}]
+	];
+	var fills = ["#0cc", "#c0c"];
+
+	var m = dojox.gfx3d.matrix;
+	for(var i = 0; i < tas.length; i++){
+		console.debug(fills[i]);
+		view.createPolygon(tas[i])
+			.setStroke({color: "blue", width: 1})
+			.setFill(fills[i]);
+	}
+	var camera = dojox.gfx3d.matrix.normalize([m.cameraTranslate(0, -300, 0)]);
+
+	view.applyCameraTransform(camera);
+	
+	view.render();
+	
+	// set up the click handlers.
+	dojo.connect(dojo.byId("bsp"), "onclick", renderWithBSP);
+	dojo.connect(dojo.byId("zorder"), "onclick", renderWithZOrder);
+};
+
+render = function(title, render){
+	dojo.byId("render").innerHTML = title;
+	view.setScheduler(render);
+	view.invalidate();
+	view.render();
+};
+
+renderWithBSP = function(){
+	render("BSP", dojox.gfx3d.scheduler.bsp);
+};
+
+renderWithZOrder = function(){
+	render("ZOrder", dojox.gfx3d.scheduler.zOrder);
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Scheduler Test</h1>
+<p>There are two schedulers available in dojox.gfx3d, zOrder and BSP. zOrder is much simpler, and it performs quite well in most cases, it may fail in some rare cases, for example: two triangles share the same two vertice, and have the same Z value of the third vertex, in this case, they have the same z-order. They are rendered in arbitary order. In this case, BSP is the rescure.</p>
+<p>Current render: <strong id="render">default</strong></p>
+<p><button id="bsp">BSP</button> <button id="zorder">zOrder</button></p>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_polygon.html b/dojox/gfx3d/tests/test_polygon.html
new file mode 100644
index 0000000..ab9f174
--- /dev/null
+++ b/dojox/gfx3d/tests/test_polygon.html
@@ -0,0 +1,44 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Polygon test of dojox.gfx3d.</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	var view = surface.createViewport();
+	var poly = [{x: 0, y: 0, z: 0}, {x: 0, y: 100, z: 0}, {x: 100, y: 100, z: 0}, {x: 100, y: 0, z: 0}];
+		
+	var m = dojox.gfx3d.matrix;
+	t = view.createPolygon(poly)
+		.setStroke({color: "blue", width: 1})
+		.setFill("#cc0");
+	
+	var camera = dojox.gfx3d.matrix.normalize([
+		m.cameraRotateXg(30), 
+		m.cameraRotateYg(30),
+		//m.cameraRotateZg(15),
+		m.cameraTranslate(-0, 0, 0)
+	]);
+
+	view.applyCameraTransform(camera);
+	view.render();
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Polygon Test</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_quads.html b/dojox/gfx3d/tests/test_quads.html
new file mode 100644
index 0000000..aff3b3b
--- /dev/null
+++ b/dojox/gfx3d/tests/test_quads.html
@@ -0,0 +1,78 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Quads test of dojox.gfx3d.</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	var view = surface.createViewport();
+	var strip = [
+		{x: 50, y: 0, z: 0}, 
+		{x: 70, y: 0, z: 60},
+		{x: 0, y: 70, z: 60},
+		{x: 0, y: 50, z: 0}, 
+		{x: -50, y: 0, z: 0},
+		{x: -70, y: 0, z: 60},
+		{x: 0, y: -70, z: 60},
+		{x: 0, y: -50, z: 0}
+	];
+
+	var normal = [
+		{x: 50, y: 0, z: 0}, 
+		{x: 70, y: 0, z: 60},
+		{x: 0, y: 70, z: 60},
+		{x: 0, y: 50, z: 0}, 
+		{x: 0, y: 70, z: 60},
+		{x: 0, y: 50, z: 0}, 
+		{x: -50, y: 0, z: 0},
+		{x: -70, y: 0, z: 60}
+	];
+
+	var m = dojox.gfx3d.matrix;
+	view.createQuads(normal)
+		.setStroke({color: "blue", width: 1})
+		.setFill("#f00")
+		.applyTransform(dojox.gfx3d.matrix.translate({x: 0, y: 500, z: 10}));
+
+	view.createQuads(strip, "strip")
+		.setStroke({color: "red", width: 1})
+		.setFill("#0f0")
+		.applyTransform(dojox.gfx3d.matrix.translate({x: 0, y: 200, z: 10}));
+
+	var camera = dojox.gfx3d.matrix.normalize([
+		m.cameraRotateXg(30), 
+		m.cameraRotateYg(30),
+		m.cameraRotateXg(50),
+		m.cameraTranslate(-100, -100, 0)
+	]);
+
+	view.applyCameraTransform(camera);
+	view.render();
+};
+
+mdebug = function(matrix){
+	var m = dojox.gfx3d.matrix.normalize(matrix);
+	console.debug("xx: " + m.xx + ", xy: " + m.xy + " | xz:" + m.xz + " | dx:" + m.dx);
+	console.debug("yx: " + m.yx + ", yy: " + m.yy + " | yz:" + m.yz + " | dy:" + m.dy);
+	console.debug("zx: " + m.zx + ", zy: " + m.zy + " | zz:" + m.zz + " | dz:" + m.dz);
+};
+
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Quads Test</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_rotate.html b/dojox/gfx3d/tests/test_rotate.html
new file mode 100644
index 0000000..5997275
--- /dev/null
+++ b/dojox/gfx3d/tests/test_rotate.html
@@ -0,0 +1,123 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Rotate test of dojox.gfx3d.</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+
+var angles = {x: 0, y: 0, z: 0};
+var cube = null;
+var view = null;
+
+rotate = function(){
+	var m = dojox.gfx3d.matrix;
+
+	if(dojo.byId('rx').checked){
+		angles.x += 10;
+	}
+	if(dojo.byId('ry').checked){
+		angles.y += 10;
+	}
+	if(dojo.byId('rz').checked){
+		angles.z += 10;
+	}
+	var t = m.normalize([
+		m.cameraRotateXg(angles.x), 
+		m.cameraRotateYg(angles.y), 
+		m.cameraRotateZg(angles.z)
+	]);
+	cube.setTransform(t);
+	cube.invalidate();
+	view.render();
+}
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	view = surface.createViewport();
+	var c = {bottom: {x: 0, y: 0, z: 0}, top: {x: 100, y: 100, z: 100}};
+	var xaxis = [
+		{x: 0, y: 0, z: 0}, 
+		{x: 200, y: 0, z: 0}
+	];
+
+	var yaxis = [
+		{x: 0, y: 0, z: 0}, 
+		{x: 0, y: 200, z: 0}
+	];
+	
+	var zaxis = [
+		{x: 0, y: 0, z: 0}, 
+		{x: 0, y: 0, z: 200}
+	];
+
+	var m = dojox.gfx3d.matrix;
+
+	view.createEdges(xaxis).setStroke({color: "red",   width: 1});
+	view.createEdges(yaxis).setStroke({color: "green", width: 1});
+	view.createEdges(zaxis).setStroke({color: "blue",  width: 1});
+
+	cube = view.createCube(c).setStroke({color: "lime", width: 1});
+
+	var camera = dojox.gfx3d.matrix.normalize([
+		m.cameraRotateXg(20), 
+		m.cameraRotateYg(30),
+		m.cameraTranslate(-100, -100, 0)
+	]);
+
+	view.applyCameraTransform(camera);
+	view.render();
+	window.setInterval(rotate, 200);
+
+	// add the click event handler
+	dojo.connect(dojo.byId("conservative"), "onclick", drawWithConservative);
+	dojo.connect(dojo.byId("chart"), "onclick", drawWithChart);
+};
+
+draw = function(title, drawer){
+	dojo.byId("drawer").innerHTML = title;
+	view.setDrawer(drawer);
+};
+
+drawWithConservative = function(){
+	draw("Conservative", dojox.gfx3d.drawer.conservative);
+};
+
+drawWithChart = function(){
+	draw("Chart", dojox.gfx3d.drawer.chart);
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body class="tundra">
+	<h1>Pilot Test</h1>
+	<p>There are two drawers(well, the name is quite misleading, it means draw-er) in dojox.gfx3d, conservative and chart:</p>
+	<ul>
+		<li><em>conservative</em> drawer is a pessimist, it assumes that the movement, transformation of objects would take a big fat impact to the viewport, so it not only render the modified objects, but also reorder all the underlying 2D shapes and redraw them.</li>
+		<li> <em>chart</em> drawer is an optimist, it assumes the change of the objects does not take effect on the z-order, this is most likely true in chart application. It only render and then draw the modified objects.</li>
+	</ul>
+	<p>The cube is in the center (0, 0, 0): The color of X, Y, Z axes are red, green, blue as the reference. The cube would rotate around X, Y, Z or their combination, it is up to you.</p>
+	<p>Current Drawer: <strong id="drawer">Conservative</strong></p>
+<form>
+	<input id="conservative" type="button" value="Draw with conservative"/>
+	<input id="chart" type="button" value="Draw with chart"/><br />
+	<input id="rx" type="checkbox" name="rotateX" checked="true" value="on"/> 
+	<label for="rx"> Rotate around X-axis</label> <br/>
+	<input id="ry" type="checkbox" name="rotateY" checked="false" value="off"/> 
+	<label for="ry"> Rotate around Y-axis</label> <br/>
+	<input id="rz" type="checkbox" name="rotateZ" checked="false" value="off"/> 
+	<label for="rz"> Rotate around Z-axis</label> <br/>
+</form>
+
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_scene.html b/dojox/gfx3d/tests/test_scene.html
new file mode 100644
index 0000000..231b289
--- /dev/null
+++ b/dojox/gfx3d/tests/test_scene.html
@@ -0,0 +1,66 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Scene test of dojox.gfx3d.</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+
+var view = null;
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	view = surface.createViewport();
+	var c = {bottom: {x: 0, y: 0, z: 0}, top: {x: 100, y: 100, z: 100}};
+	var m = dojox.gfx3d.matrix;
+
+	var sc1 = view.createScene();
+	sc1.createCube(c).setStroke({color: "blue", width: 1});
+
+	var sc2 = view.createScene();
+	sc2.createCube(c).setStroke({color: "red", width: 1}).setFill("lime");
+
+	var poly = [{x: 0, y: 0, z: 0}, {x: 0, y: 100, z: 0}, {x: 100, y: 100, z: 0}, {x: 100, y: 0, z: 0}];
+	sc2.createPolygon(poly)
+		.setStroke({color: "blue", width: 1})
+		.setTransform(dojox.gfx3d.matrix.translate(50, 20, 30))
+		.setFill("yellow");
+
+	sc2.setTransform(dojox.gfx3d.matrix.translate(100, 200, 30))
+	 
+	var camera = dojox.gfx3d.matrix.normalize([
+		m.cameraRotateXg(30), 
+		m.cameraRotateYg(60),
+		m.cameraTranslate(0, 0, 0)
+	]);
+
+	view.applyCameraTransform(camera);
+	view.render();
+
+	// set up the click handlers.
+	dojo.connect(dojo.byId("rotate"), "onclick", rotate);
+};
+
+rotate = function() {
+	view.applyCameraTransform(dojox.gfx3d.matrix.rotateXg(10));
+	view.invalidate();
+	view.render();
+};
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Scene Test</h1>
+<p>Test the setTransform of the Scene. the lime cube and yellow polygon are grouped in one Scene, and they are moved in one shot.</p>
+<p>Test Viewport.invalidate with Scene. <input id="rotate" type="button" value="Rotate around Z-Axis"/></p>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_triangles.html b/dojox/gfx3d/tests/test_triangles.html
new file mode 100644
index 0000000..cc4e65b
--- /dev/null
+++ b/dojox/gfx3d/tests/test_triangles.html
@@ -0,0 +1,82 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Triangles test of dojox.gfx3d.</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d");
+
+makeObjects = function(){
+	var surface = dojox.gfx.createSurface("test", 500, 500);
+	var view = surface.createViewport();
+	var points = [
+		{x: 0, y: 0, z: 150}, 
+		{x: 50, y: 0, z: 0},
+		{x: 0, y: 50, z: 0},
+		{x: 0, y: 0, z: 150}, 
+		{x: 50, y: 0, z: 0},
+		{x: 0, y: -50, z: 0}
+	];
+	var fan = [
+		{x: 0, y: 0, z: 150}, 
+		{x: 50, y: 0, z: 0},
+		{x: 0, y: 50, z: 0},
+		{x: -50, y: 0, z: 0},
+		{x: 0, y: -50, z: 0}
+	];
+	var strip = [
+		{x: 0, y: -50, z: 0}, 
+		{x: 0, y: 0, z: 150}, 
+		{x: 50, y: 0, z: 0},
+		{x: 0, y: 50, z: 0}
+	];
+
+	var m = dojox.gfx3d.matrix;
+	var normal = view.createTriangles(points)
+		.setStroke({color: "blue", width: 1})
+		.setFill("#ccc")
+		.applyTransform(dojox.gfx3d.matrix.translate({x: 0, y: 0, z: 10}));
+
+	view.createTriangles(strip, "strip")
+		.setStroke({color: "red", width: 1})
+		.setFill("#ccc")
+		.applyTransform(dojox.gfx3d.matrix.translate({x: 150, y: 0, z: 10}));
+
+	view.createTriangles(fan, "fan")
+		.setStroke({color: "lime", width: 1})
+		.setFill("#ccc")
+		.applyTransform(dojox.gfx3d.matrix.translate({x: 300, y: 0, z: 10}));
+
+	var camera = dojox.gfx3d.matrix.normalize([
+		m.cameraRotateXg(-30), 
+		m.cameraRotateYg(-10), 
+		m.cameraTranslate(-50, -100, 0)
+	]);
+
+	view.applyCameraTransform(camera);
+	view.render();
+};
+
+mdebug = function(matrix){
+	var m = dojox.gfx3d.matrix.normalize(matrix);
+	console.debug("xx: " + m.xx + ", xy: " + m.xy + " | xz:" + m.xz + " | dx:" + m.dx);
+	console.debug("yx: " + m.yx + ", yy: " + m.yy + " | yz:" + m.yz + " | dy:" + m.dy);
+	console.debug("zx: " + m.zx + ", zy: " + m.zy + " | zz:" + m.zz + " | dz:" + m.dz);
+};
+
+
+dojo.addOnLoad(makeObjects);
+
+</script>
+</head>
+<body>
+<h1>Path3d Test</h1>
+<div id="test" style="width: 500px; height: 500px;"></div>
+<p>That's all Folks!</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/tests/test_vector.html b/dojox/gfx3d/tests/test_vector.html
new file mode 100644
index 0000000..371d57e
--- /dev/null
+++ b/dojox/gfx3d/tests/test_vector.html
@@ -0,0 +1,59 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+<title>Dojo 3D Vector</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.gfx3d.vector");
+
+pdebug = function(point){
+	console.debug("x: " + point.x + ", y: " + point.y + ", z: " + point.z);
+};
+
+dojo.addOnLoad(function(){
+	var m = dojox.gfx3d.vector;
+	console.debug("test crossProduct...");
+	c = m.crossProduct(1, 2, 3, 4, 5, 6);
+	pdebug(c);
+	a = {x: 1, y: 2, z: 3};
+	b = {x: 4, y: 5, z: 6};
+	c = m.crossProduct(a, b);
+	pdebug(c);
+
+	console.debug("test dotProduct...");
+	c = m.dotProduct(1, 2, 3, 4, 5, 6);
+	console.debug(c);
+	a = {x: 1, y: 2, z: 3};
+	b = {x: 4, y: 5, z: 6};
+	c = m.dotProduct(a, b);
+	console.debug(c);
+
+	console.debug("test sum/substract...");
+	a = {x: 10, y: 5, z: 8};
+	b = {x: 1, y: 15, z: 2};
+	console.debug(m.sum(a, b));
+	console.debug(m.substract(a, b));
+
+	console.debug("test normalize...");
+	c = {x: 0, y: 17, z: -2};
+	d = m.normalize(a, b, c);
+	e = m.normalize([a, b, c]);
+	console.debug(d);
+	console.debug( "expecting 0:", m.dotProduct(d, m.substract(b, a)));
+	console.debug(e);
+	console.debug( "expecting 0:", m.dotProduct(e, m.substract(b, a)));
+
+});
+
+</script>
+</head>
+<body>
+	<h1>dojox.gfx3d.vector test</h1>
+	<p>Please check the debug console for test results.</p>
+</body>
+</html>
diff --git a/dojox/gfx3d/vector.js b/dojox/gfx3d/vector.js
index c2444e4..f2cbcf6 100644
--- a/dojox/gfx3d/vector.js
+++ b/dojox/gfx3d/vector.js
@@ -1,61 +1,106 @@
-/*
-	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
-*/
+dojo.provide("dojox.gfx3d.vector");
 
+dojo.mixin(dojox.gfx3d.vector, {
+	sum: function(){
+		// summary: sum of the vectors
+		var v = {x: 0, y: 0, z:0};
+		dojo.forEach(arguments, function(item){ v.x += item.x; v.y += item.y; v.z += item.z; });
+		return v;
+	},
 
-if(!dojo._hasResource["dojox.gfx3d.vector"]){
-dojo._hasResource["dojox.gfx3d.vector"]=true;
-dojo.provide("dojox.gfx3d.vector");
-dojo.mixin(dojox.gfx3d.vector,{sum:function(){
-var v={x:0,y:0,z:0};
-dojo.forEach(arguments,function(_1){
-v.x+=_1.x;
-v.y+=_1.y;
-v.z+=_1.z;
+	center: function(){
+		// summary: center of the vectors
+		var l = arguments.length;
+		if(l == 0){
+			return {x: 0, y: 0, z: 0};
+		} 
+		var v = dojox.gfx3d.vector.sum(arguments);
+		return {x: v.x/l, y: v.y/l, z: v.z/l};
+	},
+
+	substract: function(/* Pointer */a, /* Pointer */b){
+		return  {x: a.x - b.x, y: a.y - b.y, z: a.z - b.z};
+	},
+
+	_crossProduct: function(x, y, z, u, v, w){
+		// summary: applies a cross product of two vectorss, (x, y, z) and (u, v, w)
+		// x: Number: an x coordinate of a point
+		// y: Number: a y coordinate of a point
+		// z: Number: a z coordinate of a point
+		// u: Number: an x coordinate of a point
+		// v: Number: a y coordinate of a point
+		// w: Number: a z coordinate of a point
+		return {x: y * w - z * v, y: z * u - x * w, z: x * v - y * u}; // Object
+	},
+
+	crossProduct: function(/* Number||Point */ a, /* Number||Point */ b, /* Number, optional */ c, /* Number, optional */ d, /* Number, optional */ e, /* Number, optional */ f){
+		// summary: applies a matrix to a point
+		// matrix: dojox.gfx3d.matrix.Matrix3D: a 3D matrix object to be applied
+		// a: Number: an x coordinate of a point
+		// b: Number: a y coordinate of a point
+		// c: Number: a z coordinate of a point
+		// d: Number: an x coordinate of a point
+		// e: Number: a y coordinate of a point
+		// f: Number: a z coordinate of a point
+		if(arguments.length == 6 && dojo.every(arguments, function(item){ return typeof item == "number"; })){
+			return dojox.gfx3d.vector._crossProduct(a, b, c, d, e, f); // Object
+		}
+		// branch
+		// a: Object: a point
+		// b: Object: a point
+		// c: null
+		// d: null
+		// e: null
+		// f: null
+		return dojox.gfx3d.vector._crossProduct(a.x, a.y, a.z, b.x, b.y, b.z); // Object
+	},
+
+	_dotProduct: function(x, y, z, u, v, w){
+		// summary: applies a cross product of two vectorss, (x, y, z) and (u, v, w)
+		// x: Number: an x coordinate of a point
+		// y: Number: a y coordinate of a point
+		// z: Number: a z coordinate of a point
+		// u: Number: an x coordinate of a point
+		// v: Number: a y coordinate of a point
+		// w: Number: a z coordinate of a point
+		return x * u + y * v + z * w; // Number
+	},
+	dotProduct: function(/* Number||Point */ a, /* Number||Point */ b, /* Number, optional */ c, /* Number, optional */ d, /* Number, optional */ e, /* Number, optional */ f){
+		// summary: applies a matrix to a point
+		// matrix: dojox.gfx3d.matrix.Matrix3D: a 3D matrix object to be applied
+		// a: Number: an x coordinate of a point
+		// b: Number: a y coordinate of a point
+		// c: Number: a z coordinate of a point
+		// d: Number: an x coordinate of a point
+		// e: Number: a y coordinate of a point
+		// f: Number: a z coordinate of a point
+		if(arguments.length == 6 && dojo.every(arguments, function(item){ return typeof item == "number"; })){
+			return dojox.gfx3d.vector._dotProduct(a, b, c, d, e, f); // Object
+		}
+		// branch
+		// a: Object: a point
+		// b: Object: a point
+		// c: null
+		// d: null
+		// e: null
+		// f: null
+		return dojox.gfx3d.vector._dotProduct(a.x, a.y, a.z, b.x, b.y, b.z); // Object
+	},
+
+	normalize: function(/* Point||Array*/ a, /* Point */ b, /* Point */ c){
+		// summary: find the normal of the implicit surface
+		// a: Object: a point
+		// b: Object: a point
+		// c: Object: a point
+		var l, m, n; 
+		if(a instanceof Array){
+			l = a[0]; m = a[1]; n = a[2];
+		}else{
+			l = a; m = b; n = c;
+		}
+
+		var u = dojox.gfx3d.vector.substract(m, l);
+		var v = dojox.gfx3d.vector.substract(n, l);
+		return dojox.gfx3d.vector.crossProduct(u, v);
+	}
 });
-return v;
-},center:function(){
-var l=arguments.length;
-if(l==0){
-return {x:0,y:0,z:0};
-}
-var v=dojox.gfx3d.vector.sum(arguments);
-return {x:v.x/l,y:v.y/l,z:v.z/l};
-},substract:function(a,b){
-return {x:a.x-b.x,y:a.y-b.y,z:a.z-b.z};
-},_crossProduct:function(x,y,z,u,v,w){
-return {x:y*w-z*v,y:z*u-x*w,z:x*v-y*u};
-},crossProduct:function(a,b,c,d,e,f){
-if(arguments.length==6&&dojo.every(arguments,function(_2){
-return typeof _2=="number";
-})){
-return dojox.gfx3d.vector._crossProduct(a,b,c,d,e,f);
-}
-return dojox.gfx3d.vector._crossProduct(a.x,a.y,a.z,b.x,b.y,b.z);
-},_dotProduct:function(x,y,z,u,v,w){
-return x*u+y*v+z*w;
-},dotProduct:function(a,b,c,d,e,f){
-if(arguments.length==6&&dojo.every(arguments,function(_3){
-return typeof _3=="number";
-})){
-return dojox.gfx3d.vector._dotProduct(a,b,c,d,e,f);
-}
-return dojox.gfx3d.vector._dotProduct(a.x,a.y,a.z,b.x,b.y,b.z);
-},normalize:function(a,b,c){
-var l,m,n;
-if(a instanceof Array){
-l=a[0];
-m=a[1];
-n=a[2];
-}else{
-l=a;
-m=b;
-n=c;
-}
-var u=dojox.gfx3d.vector.substract(m,l);
-var v=dojox.gfx3d.vector.substract(n,l);
-return dojox.gfx3d.vector.crossProduct(u,v);
-}});
-}
diff --git a/dojox/grid/DataGrid.js b/dojox/grid/DataGrid.js
index 328f445..17aeb90 100644
--- a/dojox/grid/DataGrid.js
+++ b/dojox/grid/DataGrid.js
@@ -1,16 +1,633 @@
-/*
-	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
-*/
+dojo.provide("dojox.grid.DataGrid");
 
-/*
-	This is a compiled version of Dojo, built for deployment and not for
-	development. To get an editable version, please visit:
+dojo.require("dojox.grid._Grid");
+dojo.require("dojox.grid.DataSelection");
 
-		http://dojotoolkit.org
+/*=====
+dojo.declare("dojox.grid.__DataCellDef", dojox.grid.__CellDef, {
+	constructor: function(){
+		//	field: String?
+		//		The attribute to read from the dojo.data item for the row.
+		//  fields: String[]?
+		//		An array of fields to grab the values of and pass as an array to the grid
+		//	get: Function?
+		//		function(rowIndex, item?){} rowIndex is of type Integer, item is of type
+		//		Object.  This function will be called when a cell requests data.  Returns
+		//		the unformatted data for the cell.
+	}
+});
+=====*/
 
-	for documentation and information on getting the source.
-*/
+/*=====
+dojo.declare("dojox.grid.__DataViewDef", dojox.grid.__ViewDef, {
+	constructor: function(){
+		//	cells: dojox.grid.__DataCellDef[]|Array[dojox.grid.__DataCellDef[]]?
+		//		The structure of the cells within this grid.
+		//	defaultCell: dojox.grid.__DataCellDef?
+		//		A cell definition with default values for all cells in this view.  If
+		//		a property is defined in a cell definition in the "cells" array and
+		//		this property, the cell definition's property will override this
+		//		property's property.
+	}
+});
+=====*/
 
-if(!dojo._hasResource["dijit._base.manager"]){dojo._hasResource["dijit._base.manager"]=true;dojo.provide("dijit._base.manager");dojo.declare("dijit.WidgetSet",null,{constructor:function(){this._hash={};this.length=0;},add:function(_1){if(this._hash[_1.id]){throw new Error("Tried to register widget with id=="+_1.id+" but that id is already registered");}this._hash[_1.id]=_1;this.length++;},remove:function(id){if(this._hash[id]){delete this._hash[id];this.length--;}},forEach:function(_2,_3 [...]
+dojo.declare("dojox.grid.DataGrid", dojox.grid._Grid, {
+	store: null,
+	query: null,
+	queryOptions: null,
+	fetchText: '...',
+	sortFields: null,
+	
+	// updateDelay: int
+	//		Time, in milliseconds, to delay updates automatically so that multiple
+	//		calls to onSet/onNew/onDelete don't keep rerendering the grid.  Set
+	//		to 0 to immediately cause updates.  A higher value will result in
+	//		better performance at the expense of responsiveness of the grid.
+	updateDelay: 1,
+
+/*=====
+	// structure: dojox.grid.__DataViewDef|dojox.grid.__DataViewDef[]|dojox.grid.__DataCellDef[]|Array[dojox.grid.__DataCellDef[]]
+	//		View layout defintion.
+	structure: '',
+=====*/
+
+	// You can specify items instead of a query, if you like.  They do not need
+	// to be loaded - but the must be items in the store
+	items: null,
+	
+	_store_connects: null,
+	_by_idty: null,
+	_by_idx: null,
+	_cache: null,
+	_pages: null,
+	_pending_requests: null,
+	_bop: -1,
+	_eop: -1,
+	_requests: 0,
+	rowCount: 0,
+
+	_isLoaded: false,
+	_isLoading: false,
+	
+	postCreate: function(){
+		this._pages = [];
+		this._store_connects = [];
+		this._by_idty = {};
+		this._by_idx = [];
+		this._cache = [];
+		this._pending_requests = {};
+
+		this._setStore(this.store);
+		this.inherited(arguments);
+	},
+
+	createSelection: function(){
+		this.selection = new dojox.grid.DataSelection(this);
+	},
+
+	get: function(inRowIndex, inItem){
+		// summary: Default data getter.
+		// description:
+		//		Provides data to display in a grid cell. Called in grid cell context.
+		//		So this.cell.index is the column index.
+		// inRowIndex: Integer
+		//		Row for which to provide data
+		// returns:
+		//		Data to display for a given grid cell.
+		
+		if(inItem && this.field == "_item" && !this.fields){
+			return inItem;
+		}else if(inItem && this.fields){
+			var ret = [];
+			var s = this.grid.store;
+			dojo.forEach(this.fields, function(f){
+				ret = ret.concat(s.getValues(inItem, f));
+			});
+			return ret;
+		}else if(!inItem && typeof inRowIndex === "string"){
+			return this.inherited(arguments);
+		}
+		return (!inItem ? this.defaultValue : (!this.field ? this.value : (this.field == "_item" ? inItem : this.grid.store.getValue(inItem, this.field))));
+	},
+
+	_checkUpdateStatus: function(){
+		if(this.updateDelay > 0){
+			var iStarted = false;
+			if(this._endUpdateDelay){
+				clearTimeout(this._endUpdateDelay);
+				delete this._endUpdateDelay;
+				iStarted = true;
+			}
+			if(!this.updating){
+				this.beginUpdate();
+				iStarted = true;
+			}
+			if(iStarted){
+				var _this = this;
+				this._endUpdateDelay = setTimeout(function(){
+					delete _this._endUpdateDelay;
+					_this.endUpdate();
+				}, this.updateDelay);
+			}
+		}
+	},
+	
+	_onSet: function(item, attribute, oldValue, newValue){
+		this._checkUpdateStatus();
+		var idx = this.getItemIndex(item);
+		if(idx>-1){
+			this.updateRow(idx);
+		}
+	},
+	
+	_createItem: function(item, index){
+		var idty = this._hasIdentity ? this.store.getIdentity(item) : dojo.toJson(this.query) + ":idx:" + index + ":sort:" + dojo.toJson(this.getSortProps());
+		var o = this._by_idty[idty] = { idty: idty, item: item };
+		return o;
+	},
+
+	_addItem: function(item, index, noUpdate){
+		this._by_idx[index] = this._createItem(item, index);
+		if(!noUpdate){
+			this.updateRow(index);
+		}
+	},
+
+	_onNew: function(item, parentInfo){
+		this._checkUpdateStatus();
+		var rowCount = this.get('rowCount');
+		this._addingItem = true;
+		this.updateRowCount(rowCount+1);
+		this._addingItem = false;
+		this._addItem(item, rowCount);
+		this.showMessage();
+	},
+
+	_onDelete: function(item){
+		this._checkUpdateStatus();
+		var idx = this._getItemIndex(item, true);
+
+		if(idx >= 0){
+			// When a row is deleted, all rest rows are shifted down,
+			// and migrate from page to page. If some page is not 
+			// loaded yet empty rows can migrate to initialized pages
+			// without refreshing. It causes empty rows in some pages, see:
+			// http://bugs.dojotoolkit.org/ticket/6818
+			// this code fix this problem by reseting loaded page info
+			this._pages = [];
+			this._bop = -1;
+			this._eop = -1;
+
+			var o = this._by_idx[idx];
+			this._by_idx.splice(idx, 1);
+			delete this._by_idty[o.idty];
+			this.updateRowCount(this.get('rowCount')-1);
+			if(this.get('rowCount') === 0){
+				this.showMessage(this.noDataMessage);
+			}
+		}
+	},
+
+	_onRevert: function(){
+		this._refresh();
+	},
+
+	setStore: function(store, query, queryOptions){
+		this._setQuery(query, queryOptions);
+		this._setStore(store);
+		this._refresh(true);
+	},
+	
+	setQuery: function(query, queryOptions){
+		this._setQuery(query, queryOptions);
+		this._refresh(true);
+	},
+	
+	setItems: function(items){
+		this.items = items;
+		this._setStore(this.store);
+		this._refresh(true);
+	},
+	
+	_setQuery: function(query, queryOptions){
+		this.query = query;
+		this.queryOptions = queryOptions || this.queryOptions;		
+	},
+
+	_setStore: function(store){
+		if(this.store&&this._store_connects){
+			dojo.forEach(this._store_connects,function(arr){
+				dojo.forEach(arr, dojo.disconnect);
+			});
+		}
+		this.store = store;
+
+		if(this.store){
+			var f = this.store.getFeatures();
+			var h = [];
+
+			this._canEdit = !!f["dojo.data.api.Write"] && !!f["dojo.data.api.Identity"];
+			this._hasIdentity = !!f["dojo.data.api.Identity"];
+
+			if(!!f["dojo.data.api.Notification"] && !this.items){
+				h.push(this.connect(this.store, "onSet", "_onSet"));
+				h.push(this.connect(this.store, "onNew", "_onNew"));
+				h.push(this.connect(this.store, "onDelete", "_onDelete"));
+			}
+			if(this._canEdit){
+				h.push(this.connect(this.store, "revert", "_onRevert"));
+			}
+
+			this._store_connects = h;
+		}
+	},
+
+	_onFetchBegin: function(size, req){
+		if(!this.scroller){ return; }
+		if(this.rowCount != size){
+			if(req.isRender){
+				this.scroller.init(size, this.keepRows, this.rowsPerPage);
+				this.rowCount = size;
+				this._setAutoHeightAttr(this.autoHeight, true);
+				this._skipRowRenormalize = true;
+				this.prerender();
+				this._skipRowRenormalize = false;
+			}else{
+				this.updateRowCount(size);
+			}
+		}
+		if(!size){
+			this.views.render();
+			this._resize();
+			this.showMessage(this.noDataMessage);
+			this.focus.initFocusView();
+		}else{
+			this.showMessage();
+		}
+	},
+
+	_onFetchComplete: function(items, req){
+		if(!this.scroller){ return; }
+		if(items && items.length > 0){
+			//console.log(items);
+			dojo.forEach(items, function(item, idx){
+				this._addItem(item, req.start+idx, true);
+			}, this);
+			if(this._autoHeight){
+				this._skipRowRenormalize = true;
+			}
+			this.updateRows(req.start, items.length);
+			if(this._autoHeight){
+				this._skipRowRenormalize = false;
+			}			
+			if(req.isRender){
+				this.setScrollTop(0);
+				this.postrender();
+			}else if(this._lastScrollTop){
+				this.setScrollTop(this._lastScrollTop);
+			}
+		}
+		delete this._lastScrollTop;
+		if(!this._isLoaded){
+			this._isLoading = false;
+			this._isLoaded = true;
+		}
+		this._pending_requests[req.start] = false;
+	},
+
+	_onFetchError: function(err, req){
+		console.log(err);
+		delete this._lastScrollTop;
+		if(!this._isLoaded){
+			this._isLoading = false;
+			this._isLoaded = true;
+			this.showMessage(this.errorMessage);
+		}
+		this._pending_requests[req.start] = false;
+		this.onFetchError(err, req);
+	},
+
+	onFetchError: function(err, req){
+	},
+
+	_fetch: function(start, isRender){
+		start = start || 0;
+		if(this.store && !this._pending_requests[start]){
+			if(!this._isLoaded && !this._isLoading){
+				this._isLoading = true;
+				this.showMessage(this.loadingMessage);
+			}
+			this._pending_requests[start] = true;
+			//console.log("fetch: ", start);
+			try{
+				if(this.items){
+					var items = this.items;
+					var store = this.store;
+					this.rowsPerPage = items.length;
+					var req = {
+						start: start,
+						count: this.rowsPerPage,
+						isRender: isRender
+					};
+					this._onFetchBegin(items.length, req);
+					
+					// Load them if we need to
+					var waitCount = 0;
+					dojo.forEach(items, function(i){
+						if(!store.isItemLoaded(i)){ waitCount++; }
+					});
+					if(waitCount === 0){
+						this._onFetchComplete(items, req);
+					}else{
+						var onItem = function(item){
+							waitCount--;
+							if(waitCount === 0){
+								this._onFetchComplete(items, req);
+							}
+						};
+						dojo.forEach(items, function(i){
+							if(!store.isItemLoaded(i)){
+								store.loadItem({item: i, onItem: onItem, scope: this});
+							}
+						}, this);
+					}
+				}else{
+					this.store.fetch({
+						start: start,
+						count: this.rowsPerPage,
+						query: this.query,
+						sort: this.getSortProps(),
+						queryOptions: this.queryOptions,
+						isRender: isRender,
+						onBegin: dojo.hitch(this, "_onFetchBegin"),
+						onComplete: dojo.hitch(this, "_onFetchComplete"),
+						onError: dojo.hitch(this, "_onFetchError")
+					});
+				}
+			}catch(e){
+				this._onFetchError(e, {start: start, count: this.rowsPerPage});
+			}
+		}
+	},
+
+	_clearData: function(){
+		this.updateRowCount(0);
+		this._by_idty = {};
+		this._by_idx = [];
+		this._pages = [];
+		this._bop = this._eop = -1;
+		this._isLoaded = false;
+		this._isLoading = false;
+	},
+
+	getItem: function(idx){
+		var data = this._by_idx[idx];
+		if(!data||(data&&!data.item)){
+			this._preparePage(idx);
+			return null;
+		}
+		return data.item;
+	},
+
+	getItemIndex: function(item){
+		return this._getItemIndex(item, false);
+	},
+	
+	_getItemIndex: function(item, isDeleted){
+		if(!isDeleted && !this.store.isItem(item)){
+			return -1;
+		}
+
+		var idty = this._hasIdentity ? this.store.getIdentity(item) : null;
+
+		for(var i=0, l=this._by_idx.length; i<l; i++){
+			var d = this._by_idx[i];
+			if(d && ((idty && d.idty == idty) || (d.item === item))){
+				return i;
+			}
+		}
+		return -1;
+	},
+
+	filter: function(query, reRender){
+		this.query = query;
+		if(reRender){
+			this._clearData();
+		}
+		this._fetch();
+	},
+
+	_getItemAttr: function(idx, attr){
+		var item = this.getItem(idx);
+		return (!item ? this.fetchText : this.store.getValue(item, attr));
+	},
+
+	// rendering
+	_render: function(){
+		if(this.domNode.parentNode){
+			this.scroller.init(this.get('rowCount'), this.keepRows, this.rowsPerPage);
+			this.prerender();
+			this._fetch(0, true);
+		}
+	},
+
+	// paging
+	_requestsPending: function(inRowIndex){
+		return this._pending_requests[inRowIndex];
+	},
+
+	_rowToPage: function(inRowIndex){
+		return (this.rowsPerPage ? Math.floor(inRowIndex / this.rowsPerPage) : inRowIndex);
+	},
+
+	_pageToRow: function(inPageIndex){
+		return (this.rowsPerPage ? this.rowsPerPage * inPageIndex : inPageIndex);
+	},
+
+	_preparePage: function(inRowIndex){
+		if((inRowIndex < this._bop || inRowIndex >= this._eop) && !this._addingItem){
+			var pageIndex = this._rowToPage(inRowIndex);
+			this._needPage(pageIndex);
+			this._bop = pageIndex * this.rowsPerPage;
+			this._eop = this._bop + (this.rowsPerPage || this.get('rowCount'));
+		}
+	},
+
+	_needPage: function(inPageIndex){
+		if(!this._pages[inPageIndex]){
+			this._pages[inPageIndex] = true;
+			this._requestPage(inPageIndex);
+		}
+	},
+
+	_requestPage: function(inPageIndex){
+		var row = this._pageToRow(inPageIndex);
+		var count = Math.min(this.rowsPerPage, this.get('rowCount') - row);
+		if(count > 0){
+			this._requests++;
+			if(!this._requestsPending(row)){
+				setTimeout(dojo.hitch(this, "_fetch", row, false), 1);
+				//this.requestRows(row, count);
+			}
+		}
+	},
+
+	getCellName: function(inCell){
+		return inCell.field;
+		//console.log(inCell);
+	},
+
+	_refresh: function(isRender){
+		this._clearData();
+		this._fetch(0, isRender);
+	},
+
+	sort: function(){
+		this._lastScrollTop = this.scrollTop;
+		this._refresh();
+	},
+
+	canSort: function(){
+		return (!this._isLoading);
+	},
+
+	getSortProps: function(){
+		var c = this.getCell(this.getSortIndex());
+		if(!c){
+			if(this.sortFields){
+				return this.sortFields;
+			}
+			return null;
+		}else{
+			var desc = c["sortDesc"];
+			var si = !(this.sortInfo>0);
+			if(typeof desc == "undefined"){
+				desc = si;
+			}else{
+				desc = si ? !desc : desc;
+			}
+			return [{ attribute: c.field, descending: desc }];
+		}
+	},
+
+	styleRowState: function(inRow){
+		// summary: Perform row styling
+		if(this.store && this.store.getState){
+			var states=this.store.getState(inRow.index), c='';
+			for(var i=0, ss=["inflight", "error", "inserting"], s; s=ss[i]; i++){
+				if(states[s]){
+					c = ' dojoxGridRow-' + s;
+					break;
+				}
+			}
+			inRow.customClasses += c;
+		}
+	},
+
+	onStyleRow: function(inRow){
+		this.styleRowState(inRow);
+		this.inherited(arguments);
+	},
+
+	// editing
+	canEdit: function(inCell, inRowIndex){
+		return this._canEdit;
+	},
+
+	_copyAttr: function(idx, attr){
+		var row = {};
+		var backstop = {};
+		var src = this.getItem(idx);
+		return this.store.getValue(src, attr);
+	},
+
+	doStartEdit: function(inCell, inRowIndex){
+		if(!this._cache[inRowIndex]){
+			this._cache[inRowIndex] = this._copyAttr(inRowIndex, inCell.field);
+		}
+		this.onStartEdit(inCell, inRowIndex);
+	},
+
+	doApplyCellEdit: function(inValue, inRowIndex, inAttrName){
+		this.store.fetchItemByIdentity({
+			identity: this._by_idx[inRowIndex].idty,
+			onItem: dojo.hitch(this, function(item){
+				var oldValue = this.store.getValue(item, inAttrName);
+				if(typeof oldValue == 'number'){
+					inValue = isNaN(inValue) ? inValue : parseFloat(inValue);
+				}else if(typeof oldValue == 'boolean'){
+					inValue = inValue == 'true' ? true : inValue == 'false' ? false : inValue;
+				}else if(oldValue instanceof Date){
+					var asDate = new Date(inValue);
+					inValue = isNaN(asDate.getTime()) ? inValue : asDate;
+				}
+				this.store.setValue(item, inAttrName, inValue);
+				this.onApplyCellEdit(inValue, inRowIndex, inAttrName);
+			})
+		});
+	},
+
+	doCancelEdit: function(inRowIndex){
+		var cache = this._cache[inRowIndex];
+		if(cache){
+			this.updateRow(inRowIndex);
+			delete this._cache[inRowIndex];
+		}
+		this.onCancelEdit.apply(this, arguments);
+	},
+
+	doApplyEdit: function(inRowIndex, inDataAttr){
+		var cache = this._cache[inRowIndex];
+		/*if(cache){
+			var data = this.getItem(inRowIndex);
+			if(this.store.getValue(data, inDataAttr) != cache){
+				this.update(cache, data, inRowIndex);
+			}
+			delete this._cache[inRowIndex];
+		}*/
+		this.onApplyEdit(inRowIndex);
+	},
+
+	removeSelectedRows: function(){
+		// summary:
+		//		Remove the selected rows from the grid.
+		if(this._canEdit){
+			this.edit.apply();
+			var fx = dojo.hitch(this, function(items){
+				if(items.length){
+					dojo.forEach(items, this.store.deleteItem, this.store);
+					this.selection.clear();
+				}			
+			});
+			if(this.allItemsSelected){
+				this.store.fetch({
+							query: this.query, 
+							queryOptions: this.queryOptions,
+							onComplete: fx});
+			}else{
+				fx(this.selection.getSelected());
+			}
+		}
+	}
+});
+
+dojox.grid.DataGrid.cell_markupFactory = function(cellFunc, node, cellDef){
+	var field = dojo.trim(dojo.attr(node, "field")||"");
+	if(field){
+		cellDef.field = field;
+	}
+	cellDef.field = cellDef.field||cellDef.name;
+	var fields = dojo.trim(dojo.attr(node, "fields")||"");
+	if(fields){
+		cellDef.fields = fields.split(",");
+	}
+	if(cellFunc){
+		cellFunc(node, cellDef);
+	}
+};
+
+dojox.grid.DataGrid.markupFactory = function(props, node, ctor, cellFunc){
+	return dojox.grid._Grid.markupFactory(props, node, ctor, 
+					dojo.partial(dojox.grid.DataGrid.cell_markupFactory, cellFunc));
+};
diff --git a/dojox/grid/DataGrid.js.uncompressed.js b/dojox/grid/DataGrid.js.uncompressed.js
deleted file mode 100644
index 39a1af3..0000000
--- a/dojox/grid/DataGrid.js.uncompressed.js
+++ /dev/null
@@ -1,16328 +0,0 @@
-/*
-	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["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 = {};
-		this.length = 0;
-	},
-
-	add: function(/*dijit._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;
-		this.length++;
-	},
-
-	remove: function(/*String*/ id){
-		// summary:
-		//		Remove a widget from this WidgetSet. Does not destroy the widget; simply
-		//		removes the reference.
-		if(this._hash[id]){
-			delete this._hash[id];
-			this.length--;
-		}
-	},
-
-	forEach: function(/*Function*/ func, /* Object? */thisObj){
-		// summary:
-		//		Call specified function for each widget in this set.
-		//
-		// func:
-		//		A callback function to run for each item. Is passed the widget, the index
-		//		in the iteration, and the full hash, similar to `dojo.forEach`.
-		//
-		// thisObj:
-		//		An optional scope parameter
-		//
-		// example:
-		//		Using the default `dijit.registry` instance:
-		//		|	dijit.registry.forEach(function(widget){
-		//		|		console.log(widget.declaredClass);
-		//		|	});
-		//
-		// returns:
-		//		Returns self, in order to allow for further chaining.
-
-		thisObj = thisObj || dojo.global;
-		var i = 0, id;
-		for(id in this._hash){
-			func.call(thisObj, this._hash[id], i++, this._hash);
-		}
-		return this;	// dijit.WidgetSet
-	},
-
-	filter: function(/*Function*/ filter, /* Object? */thisObj){
-		// 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. Is passed the widget
-		//		reference and the pseudo-index in the object.
-		//
-		// thisObj: Object?
-		//		Option scope to use for the filter function.
-		//
-		// example:
-		//		Arbitrary: select the odd widgets in this list
-		//		|	dijit.registry.filter(function(w, i){
-		//		|		return i % 2 == 0;
-		//		|	}).forEach(function(w){ /* odd ones */ });
-
-		thisObj = thisObj || dojo.global;
-		var res = new dijit.WidgetSet(), i = 0, id;
-		for(id in this._hash){
-			var w = this._hash[id];
-			if(filter.call(thisObj, w, i++, this._hash)){
-				res.add(w);
-			}
-		}
-		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`
-		//
-		// cls: String
-		//		The Class to scan for. Full dot-notated string.
-		//
-		// example:
-		//		Find all `dijit.TitlePane`s in a page:
-		//		|	dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); });
-
-		var res = new dijit.WidgetSet(), id, widget;
-		for(id in this._hash){
-			widget = this._hash[id];
-			if(widget.declaredClass == cls){
-				res.add(widget);
-			}
-		 }
-		 return res; // dijit.WidgetSet
-},
-
-	toArray: function(){
-		// summary:
-		//		Convert this WidgetSet into a true Array
-		//
-		// example:
-		//		Work with the widget .domNodes in a real Array
-		//		|	dojo.map(dijit.registry.toArray(), function(w){ return w.domNode; });
-
-		var ar = [];
-		for(var id in this._hash){
-			ar.push(this._hash[id]);
-		}
-		return ar;	// dijit._Widget[]
-},
-
-	map: function(/* Function */func, /* Object? */thisObj){
-		// summary:
-		//		Create a new Array from this WidgetSet, following the same rules as `dojo.map`
-		// example:
-		//		|	var nodes = dijit.registry.map(function(w){ return w.domNode; });
-		//
-		// returns:
-		//		A new array of the returned values.
-		return dojo.map(this.toArray(), func, thisObj); // Array
-	},
-
-	every: function(func, thisObj){
-		// summary:
-		// 		A synthetic clone of `dojo.every` acting explictly on this WidgetSet
-		//
-		// func: Function
-		//		A callback function run for every widget in this list. Exits loop
-		//		when the first false return is encountered.
-		//
-		// thisObj: Object?
-		//		Optional scope parameter to use for the callback
-
-		thisObj = thisObj || dojo.global;
-		var x = 0, i;
-		for(i in this._hash){
-			if(!func.call(thisObj, this._hash[i], x++, this._hash)){
-				return false; // Boolean
-			}
-		}
-		return true; // Boolean
-	},
-
-	some: function(func, thisObj){
-		// summary:
-		// 		A synthetic clone of `dojo.some` acting explictly on this WidgetSet
-		//
-		// func: Function
-		//		A callback function run for every widget in this list. Exits loop
-		//		when the first true return is encountered.
-		//
-		// thisObj: Object?
-		//		Optional scope parameter to use for the callback
-
-		thisObj = thisObj || dojo.global;
-		var x = 0, i;
-		for(i in this._hash){
-			if(func.call(thisObj, this._hash[i], x++, this._hash)){
-				return true; // Boolean
-			}
-		}
-		return false; // Boolean
-	}
-
-});
-
-/*=====
-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 dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
-};
-
-dijit.findWidgets = function(/*DomNode*/ root){
-	// summary:
-	//		Search subtree under root returning widgets found.
-	//		Doesn't search for nested widgets (ie, widgets inside other widgets).
-
-	var outAry = [];
-
-	function getChildrenHelper(root){
-		for(var node = root.firstChild; node; node = node.nextSibling){
-			if(node.nodeType == 1){
-				var widgetId = node.getAttribute("widgetId");
-				if(widgetId){
-					var widget = dijit.byId(widgetId);
-					outAry.push(widget);
-				}else{
-					getChildrenHelper(node);
-				}
-			}
-		}
-	}
-
-	getChildrenHelper(root);
-	return outAry;
-};
-
-dijit._destroyAll = function(){
-	// summary:
-	//		Code to destroy all widgets and do other cleanup on page unload
-
-	// Clean up focus manager lingering references to widgets and nodes
-	dijit._curFocus = null;
-	dijit._prevFocus = null;
-	dijit._activeStack = [];
-
-	// Destroy all the widgets, top down
-	dojo.forEach(dijit.findWidgets(dojo.body()), function(widget){
-		// Avoid double destroy of widgets like Menu that are attached to <body>
-		// even though they are logically children of other widgets.
-		if(!widget._destroyed){
-			if(widget.destroyRecursive){
-				widget.destroyRecursive();
-			}else if(widget.destroy){
-				widget.destroy();
-			}
-		}
-	});
-};
-
-if(dojo.isIE){
-	// Only run _destroyAll() 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(){
-		dijit._destroyAll();
-	});
-}
-
-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 typeof id == "string" ? dijit.registry._hash[id] : id; // dijit._Widget
-};
-
-dijit.byNode = function(/* DOMNode */ node){
-	// summary:
-	//		Returns the widget corresponding to the given DOMNode
-	return dijit.registry.byId(node.getAttribute("widgetId")); // dijit._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){
-		var id = node.getAttribute && node.getAttribute("widgetId");
-		if(id){
-			return dijit.byId(id);
-		}
-		node = node.parentNode;
-	}
-	return null;
-};
-
-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
-
-	// TODO: convert (and rename method) to return effectivite tabIndex; will save time in _getTabNavigable()
-	if(dojo.attr(elem, "disabled")){
-		return false;
-	}else if(dojo.hasAttr(elem, "tabIndex")){
-		// Explicit tab index setting
-		return dojo.attr(elem, "tabIndex") >= 0; // boolean
-	}else{
-		// No explicit tabIndex setting, need to investigate node type
-		switch(elem.nodeName.toLowerCase()){
-			case "a":
-				// An <a> w/out a tabindex is only navigable if it has an href
-				return dojo.hasAttr(elem, "href");
-			case "area":
-			case "button":
-			case "input":
-			case "object":
-			case "select":
-			case "textarea":
-				// These are navigable by default
-				return true;
-			case "iframe":
-				// If it's an editor <iframe> then it's tab navigable.
-				if(dojo.isMoz){
-					return elem.contentDocument.designMode == "on";
-				}else if(dojo.isWebKit){
-					var doc = elem.contentDocument,
-						body = doc && doc.body;
-					return body && body.contentEditable == 'true';
-				}else{
-					// contentWindow.document isn't accessible within IE7/8
-					// if the iframe.src points to a foreign url and this
-					// page contains an element, that could get focus
-					try{
-						doc = elem.contentWindow.document;
-						body = doc && doc.body;
-						return body && body.firstChild && body.firstChild.contentEditable == 'true';
-					}catch(e){
-						return false;
-					}
-				}
-			default:
-				return elem.contentEditable == 'true';
-		}
-	}
-};
-
-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["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");
-
-	// for dijit.isTabNavigable()
-
-// summary:
-//		These functions are used to query or set the focus and selection.
-//
-//		Also, they trace when widgets become activated/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
-		return dijit.getBookmark().isCollapsed;
-	},
-
-	getBookmark: function(){
-		// summary:
-		//		Retrieves a bookmark that can be used with moveToBookmark to return to the same range
-		var bm, rg, tg, sel = dojo.doc.selection, cf = dijit._curFocus;
-
-		if(dojo.global.getSelection){
-			//W3C Range API for selections.
-			sel = dojo.global.getSelection();
-			if(sel){
-				if(sel.isCollapsed){
-					tg = cf? cf.tagName : "";
-					if(tg){
-						//Create a fake rangelike item to restore selections.
-						tg = tg.toLowerCase();
-						if(tg == "textarea" ||
-								(tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
-							sel = {
-								start: cf.selectionStart,
-								end: cf.selectionEnd,
-								node: cf,
-								pRange: true
-							};
-							return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
-						}
-					}
-					bm = {isCollapsed:true};
-				}else{
-					rg = sel.getRangeAt(0);
-					bm = {isCollapsed: false, mark: rg.cloneRange()};
-				}
-			}
-		}else if(sel){
-			// If the current focus was a input of some sort and no selection, don't bother saving
-			// a native bookmark.  This is because it causes issues with dialog/page selection restore.
-			// So, we need to create psuedo bookmarks to work with.
-			tg = cf ? cf.tagName : "";
-			tg = tg.toLowerCase();
-			if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
-				if(sel.type && sel.type.toLowerCase() == "none"){
-					return {
-						isCollapsed: true,
-						mark: null
-					}
-				}else{
-					rg = sel.createRange();
-					return {
-						isCollapsed: rg.text && rg.text.length?false:true,
-						mark: {
-							range: rg,
-							pRange: true
-						}
-					};
-				}
-			}
-			bm = {};
-
-			//'IE' way for selections.
-			try{
-				// createRange() throws exception when dojo in iframe
-				//and nothing selected, see #9632
-				rg = sel.createRange();
-				bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
-			}catch(e){
-				bm.isCollapsed = true;
-				return bm;
-			}
-			if(sel.type.toUpperCase() == 'CONTROL'){
-				if(rg.length){
-					bm.mark=[];
-					var i=0,len=rg.length;
-					while(i<len){
-						bm.mark.push(rg.item(i++));
-					}
-				}else{
-					bm.isCollapsed = true;
-					bm.mark = null;
-				}
-			}else{
-				bm.mark = rg.getBookmark();
-			}
-		}else{
-			console.warn("No idea how to store the current selection for this browser!");
-		}
-		return bm; // Object
-	},
-
-	moveToBookmark: function(/*Object*/bookmark){
-		// summary:
-		//		Moves current selection to a bookmark
-		// bookmark:
-		//		This should be a returned object from dijit.getBookmark()
-
-		var _doc = dojo.doc,
-			mark = bookmark.mark;
-		if(mark){
-			if(dojo.global.getSelection){
-				//W3C Rangi API (FF, WebKit, Opera, etc)
-				var sel = dojo.global.getSelection();
-				if(sel && sel.removeAllRanges){
-					if(mark.pRange){
-						var r = mark;
-						var n = r.node;
-						n.selectionStart = r.start;
-						n.selectionEnd = r.end;
-					}else{
-						sel.removeAllRanges();
-						sel.addRange(mark);
-					}
-				}else{
-					console.warn("No idea how to restore selection for this browser!");
-				}
-			}else if(_doc.selection && mark){
-				//'IE' way.
-				var rg;
-				if(mark.pRange){
-					rg = mark.range;
-				}else if(dojo.isArray(mark)){
-					rg = _doc.body.createControlRange();
-					//rg.addElement does not have call/apply method, so can not call it directly
-					//rg is not available in "range.addElement(item)", so can't use that either
-					dojo.forEach(mark, function(n){
-						rg.addElement(n);
-					});
-				}else{
-					rg = _doc.body.createTextRange();
-					rg.moveToBookmark(mark);
-				}
-				rg.select();
-			}
-		}
-	},
-
-	getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){
-		// summary:
-		//		Called as getFocus(), this returns an Object showing the current focus
-		//		and selected text.
-		//
-		//		Called as getFocus(widget), where widget is a (widget representing) a button
-		//		that was just pressed, it returns where focus was before that button
-		//		was pressed.   (Pressing the button may have either shifted focus to the button,
-		//		or removed focus altogether.)   In this case the selected text is not returned,
-		//		since it can't be accurately determined.
-		//
-		// menu: dijit._Widget or {domNode: DomNode} structure
-		//		The button that was just pressed.  If focus has disappeared or moved
-		//		to this button, returns the previous focus.  In this case the bookmark
-		//		information is already lost, and null is returned.
-		//
-		// openedForWindow:
-		//		iframe in which menu was opened
-		//
-		// returns:
-		//		A handle to restore focus/selection, to be passed to `dijit.focus`
-		var node = !dijit._curFocus || (menu && dojo.isDescendant(dijit._curFocus, menu.domNode)) ? dijit._prevFocus : dijit._curFocus;
-		return {
-			node: node,
-			bookmark: (node == dijit._curFocus) && dojo.withGlobal(openedForWindow || dojo.global, dijit.getBookmark),
-			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,
-			collapsed = bookmark ? bookmark.isCollapsed : false;
-
-		// 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) or if previous selection was collapsed
-		// as it may cause focus shift (Esp in IE).
-		if(bookmark && dojo.withGlobal(openedForWindow || dojo.global, dijit.isCollapsed) && !collapsed){
-			if(openedForWindow){
-				openedForWindow.focus();
-			}
-			try{
-				dojo.withGlobal(openedForWindow || dojo.global, dijit.moveToBookmark, null, [bookmark]);
-			}catch(e2){
-				/*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
-			}
-		}
-	},
-
-	// _activeStack: dijit._Widget[]
-	//		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.
-		// returns:
-		//		Handle to pass to unregisterIframe()
-		return dijit.registerWin(iframe.contentWindow, iframe);
-	},
-
-	unregisterIframe: function(/*Object*/ handle){
-		// summary:
-		//		Unregisters listeners on the specified iframe created by registerIframe.
-		//		After calling be sure to delete or null out the handle itself.
-		// handle:
-		//		Handle returned by registerIframe()
-
-		dijit.unregisterWin(handle);
-	},
-
-	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.
-		// returns:
-		//		Handle to pass to unregisterWin()
-
-		// TODO: make this function private in 2.0; Editor/users should call registerIframe(),
-
-		var mousedownListener = function(evt){
-			dijit._justMouseDowned = true;
-			setTimeout(function(){ dijit._justMouseDowned = false; }, 0);
-			dijit._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse");
-		};
-		//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.
-		// Connect to <html> (rather than document) on IE to avoid memory leaks, but document on other browsers because
-		// (at least for FF) the focus event doesn't fire on <html> or <body>.
-		var doc = dojo.isIE ? targetWindow.document.documentElement : targetWindow.document;
-		if(doc){
-			if(dojo.isIE){
-				doc.attachEvent('onmousedown', mousedownListener);
-				var activateListener = function(evt){
-					// IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
-					// Should consider those more like a mouse-click than a focus....
-					if(evt.srcElement.tagName.toLowerCase() != "#document" &&
-						dijit.isTabNavigable(evt.srcElement)){
-						dijit._onFocusNode(effectiveNode || evt.srcElement);
-					}else{
-						dijit._onTouchNode(effectiveNode || evt.srcElement);
-					}
-				};
-				doc.attachEvent('onactivate', activateListener);
-				var deactivateListener =  function(evt){
-					dijit._onBlurNode(effectiveNode || evt.srcElement);
-				};
-				doc.attachEvent('ondeactivate', deactivateListener);
-
-				return function(){
-					doc.detachEvent('onmousedown', mousedownListener);
-					doc.detachEvent('onactivate', activateListener);
-					doc.detachEvent('ondeactivate', deactivateListener);
-					doc = null;	// prevent memory leak (apparent circular reference via closure)
-				};
-			}else{
-				doc.addEventListener('mousedown', mousedownListener, true);
-				var focusListener = function(evt){
-					dijit._onFocusNode(effectiveNode || evt.target);
-				};
-				doc.addEventListener('focus', focusListener, true);
-				var blurListener = function(evt){
-					dijit._onBlurNode(effectiveNode || evt.target);
-				};
-				doc.addEventListener('blur', blurListener, true);
-
-				return function(){
-					doc.removeEventListener('mousedown', mousedownListener, true);
-					doc.removeEventListener('focus', focusListener, true);
-					doc.removeEventListener('blur', blurListener, true);
-					doc = null;	// prevent memory leak (apparent circular reference via closure)
-				};
-			}
-		}
-	},
-
-	unregisterWin: function(/*Handle*/ handle){
-		// summary:
-		//		Unregisters listeners on the specified window (either the main
-		//		window or an iframe's window) according to handle returned from registerWin().
-		//		After calling be sure to delete or null out the handle itself.
-
-		// Currently our handle is actually a function
-		handle && handle();
-	},
-
-	_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, /*String*/ by){
-		// summary:
-		//		Callback when node is focused or mouse-downed
-		// node:
-		//		The node that was touched.
-		// by:
-		//		"mouse" if the focus/touch was caused by a mouse down event
-
-		// 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){
-				var popupParent = dojo.attr(node, "dijitPopupParent");
-				if(popupParent){
-					node=dijit.byId(popupParent).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, by);
-	},
-
-	_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(/*String[]*/ newStack, /*String*/ by){
-		// summary:
-		//		The stack of active widgets has changed.  Send out appropriate events and records new stack.
-		// newStack:
-		//		array of widget id's, starting from the top (outermost) widget
-		// by:
-		//		"mouse" if the focus/touch was caused by a mouse down event
-
-		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;
-			}
-		}
-
-		var widget;
-		// for all elements that have gone out of focus, send blur event
-		for(var i=oldStack.length-1; i>=nCommon; i--){
-			widget = dijit.byId(oldStack[i]);
-			if(widget){
-				widget._focused = false;
-				widget._hasBeenBlurred = true;
-				if(widget._onBlur){
-					widget._onBlur(by);
-				}
-				if(widget._setStateClass){
-					widget._setStateClass();
-				}
-				dojo.publish("widgetBlur", [widget, by]);
-			}
-		}
-
-		// 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(by);
-				}
-				if(widget._setStateClass){
-					widget._setStateClass();
-				}
-				dojo.publish("widgetFocus", [widget, by]);
-			}
-		}
-	}
-});
-
-// register top window and all the iframes it contains
-dojo.addOnLoad(function(){
-	var handle = dijit.registerWin(window);
-	if(dojo.isIE){
-		dojo.addOnWindowUnload(function(){
-			dijit.unregisterWin(handle);
-			handle = null;
-		})
-	}
-});
-
-}
-
-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 = Math.max(view.l, corner.charAt(1) == 'L' ? pos.x : (pos.x - mb.w)),
-			startY = Math.max(view.t, corner.charAt(0) == 'T' ? pos.y : (pos.y - mb.h)),
-			endX = Math.min(view.l + view.w, corner.charAt(1) == 'L' ? (startX + mb.w) : pos.x),
-			endY = Math.min(view.t + view.h, corner.charAt(0) == 'T' ? (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 aroundNodePos = dojo.position(aroundNode, true);
-	aroundNode.style.display=oldDisplay;
-
-	// place the node around the calculated rectangle
-	return dijit._placeOnScreenAroundRect(node,
-		aroundNodePos.x, aroundNodePos.y, aroundNodePos.w, aroundNodePos.h,	// 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
-
-	this.x = x;
-	this.y = y;
-	this.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);
-};
-
-dijit.getPopupAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
-	// summary:
-	//		Transforms the passed array of preferred positions into a format suitable for passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
-	//
-	// position: String[]
-	//		This variable controls the position of the drop down.
-	//		It's an array of strings with the following values:
-	//
-	//			* before: places drop down to the left of the target node/widget, or to the right in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* after: places drop down to the right of the target node/widget, or to the left in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* above: drop down goes above target node
-	//			* below: drop down goes below target node
-	//
-	//		The list is positions is tried, in order, until a position is found where the drop down fits
-	//		within the viewport.
-	//
-	// leftToRight: Boolean
-	//		Whether the popup will be displaying in leftToRight mode.
-	//
-	var align = {};
-	dojo.forEach(position, function(pos){
-		switch(pos){
-			case "after":
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
-				break;
-			case "before":
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
-				break;
-			case "below":
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "TL" : "TR";
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "TR" : "TL";
-				break;
-			case "above":
-			default:
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "TL" : "TR"] = leftToRight ? "BL" : "BR";
-				align[leftToRight ? "TR" : "TL"] = leftToRight ? "BR" : "BL";
-				break;
-		}
-	});
-	return align;
-};
-dijit.getPopupAroundAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
-	// summary:
-	//		Transforms the passed array of preferred positions into a format suitable for passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
-	//
-	// position: String[]
-	//		This variable controls the position of the drop down.
-	//		It's an array of strings with the following values:
-	//
-	//			* before: places drop down to the left of the target node/widget, or to the right in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* after: places drop down to the right of the target node/widget, or to the left in
-	//			  the case of RTL scripts like Hebrew and Arabic
-	//			* above: drop down goes above target node
-	//			* below: drop down goes below target node
-	//
-	//		The list is positions is tried, in order, until a position is found where the drop down fits
-	//		within the viewport.
-	//
-	// leftToRight: Boolean
-	//		Whether the popup will be displaying in leftToRight mode.
-	//
-	var align = {};
-	dojo.forEach(position, function(pos){
-		switch(pos){
-			case "after":
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
-				break;
-			case "before":
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
-				break;
-			case "below":
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "BL" : "BR"] = leftToRight ? "TL" : "TR";
-				align[leftToRight ? "BR" : "BL"] = leftToRight ? "TR" : "TL";
-				break;
-			case "above":
-			default:
-				// first try to align left borders, next try to align right borders (or reverse for RTL mode)
-				align[leftToRight ? "TL" : "TR"] = leftToRight ? "BL" : "BR";
-				align[leftToRight ? "TR" : "TL"] = leftToRight ? "BR" : "BL";
-				break;
-		}
-	});
-	return align;
-};
-
-}
-
-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.moveOffScreen = function(/*DomNode*/ node){
-		// summary:
-		//		Moves node offscreen without hiding it (so that all layout widgets included 
-		//		in this node can still layout properly)
-		//
-		// 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;
-}
-=====*/
-
-	// 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];
-	};
-
-	var wrappers=[];
-	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 || (
-				dojo._isBodyLtr() ?
-				{'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'} :
-				{'BR':'TR', 'BL':'TL', 'TR':'BR', '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 wrapperobj = wrappers.pop(), wrapper, iframe;
-		if(!wrapperobj){
-			wrapper = dojo.create("div",{
-				"class":"dijitPopup"
-			}, dojo.body());
-			dijit.setWaiRole(wrapper, "presentation");
-		}else{
-			// recycled a old wrapper, so that we don't need to reattach the iframe
-			// which is slow even if the iframe is empty, see #10167
-			wrapper = wrapperobj[0];
-			iframe = wrapperobj[1];
-		}
-
-		dojo.attr(wrapper,{
-			id: id,
-			style:{
-				zIndex: beginZIndex + stack.length,
-				visibility:"hidden",
-				// prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
-				top: "-9999px"
-			},
-			dijitPopupParent: args.parent ? args.parent.id : ""
-		});
-
-		var s = widget.domNode.style;
-		s.display = "";
-		s.visibility = "";
-		s.position = "";
-		s.top = "0px";
-		wrapper.appendChild(widget.domNode);
-
-		if(!iframe){
-			iframe = new dijit.BackgroundIframe(wrapper);
-		}else{
-			iframe.resize(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 = [];
-
-		// 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", args.onCancel));
-		}
-
-		handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", 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){
-			// TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here)
-			widget.onOpen(best);
-		}
-
-		return best;
-	};
-
-	this.close = function(/*dijit._Widget*/ popup){
-		// summary:
-		//		Close specified popup and any popups that it parented
-		
-		// Basically work backwards from the top of the stack closing popups
-		// until we hit the specified popup, but IIRC there was some issue where closing
-		// a popup would cause others to close too.  Thus if we are trying to close B in [A,B,C]
-		// closing C might close B indirectly and then the while() condition will run where stack==[A]...
-		// so the while condition is constructed defensively.
-		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){
-				// TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here)
-				widget.onClose();
-			}
-			dojo.forEach(top.handlers, dojo.disconnect);
-
-			// Move the widget offscreen, unless it has already been destroyed in above onClose() etc.
-			if(widget && widget.domNode){
-				this.moveOffScreen(widget.domNode);
-			}
-                        
-			// recycle the wrapper plus iframe, so we prevent reattaching iframe everytime an popup opens
-			// don't use moveOffScreen which would also reattach the wrapper to body, which causes reloading of iframe
-			wrapper.style.top = "-9999px";
-			wrapper.style.visibility = "hidden";
-			wrappers.push([wrapper,iframe]);
-
-			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";
-				dojo.style(iframe, "opacity", 0.1);
-			}
-			iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didnt work.
-		}
-		return iframe;
-	};
-
-	this.push = function(iframe){
-		iframe.style.display="none";
-		queue.push(iframe);
-	}
-}();
-
-
-dijit.BackgroundIframe = function(/* DomNode */node){
-	// summary:
-	//		For IE/FF 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 || dojo.isMoz){
-		var iframe = dijit._frames.pop();
-		node.appendChild(iframe);
-		if(dojo.isIE<7){
-			this.resize(node);
-			this._conn = dojo.connect(node, 'onresize', this, function(){
-				this.resize(node);
-			});
-		}else{
-			dojo.style(iframe, {
-				width: '100%',
-				height: '100%'
-			});
-		}
-		this.iframe = iframe;
-	}
-};
-
-dojo.extend(dijit.BackgroundIframe, {
-	resize: function(node){
-		// summary:
-		// 		resize the iframe so its the same size as node
-		// description:
-		//		this function is a no-op in all browsers except
-		//		IE6, which does not support 100% width/height 
-		//		of absolute positioned iframes
-		if(this.iframe && dojo.isIE<7){
-			dojo.style(this.iframe, {
-				width: node.offsetWidth + 'px',
-				height: node.offsetHeight + 'px'
-			});
-		}
-	},
-	destroy: function(){
-		// summary:
-		//		destroy the iframe
-		if(this._conn){
-			dojo.disconnect(this._conn);
-			this._conn = null;
-		}
-		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, /*Object?*/ pos){
-	// summary:
-	//		Scroll the passed node into view, if it is not already.
-	
-	// don't rely on that node.scrollIntoView works just because the function is there
-
-	try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
-	node = dojo.byId(node);
-	var doc = node.ownerDocument || dojo.doc,
-		body = doc.body || dojo.body(),
-		html = doc.documentElement || body.parentNode,
-		isIE = dojo.isIE, isWK = dojo.isWebKit;
-	// if an untested browser, then use the native method
-	if((!(dojo.isMoz || isIE || isWK) || node == body || node == html) && (typeof node.scrollIntoView != "undefined")){
-		node.scrollIntoView(false); // short-circuit to native if possible
-		return;
-	}
-	var backCompat = doc.compatMode == 'BackCompat',
-		clientAreaRoot = backCompat? body : html,
-		scrollRoot = isWK ? body : clientAreaRoot,
-		rootWidth = clientAreaRoot.clientWidth,
-		rootHeight = clientAreaRoot.clientHeight,
-		rtl = !dojo._isBodyLtr(),
-		nodePos = pos || dojo.position(node),
-		el = node.parentNode,
-		isFixed = function(el){
-			return ((isIE <= 6 || (isIE && backCompat))? false : (dojo.style(el, 'position').toLowerCase() == "fixed"));
-		};
-	if(isFixed(node)){ return; } // nothing to do
-	while(el){
-		if(el == body){ el = scrollRoot; }
-		var elPos = dojo.position(el),
-			fixedPos = isFixed(el);
-		with(elPos){
-			if(el == scrollRoot){
-				w = rootWidth, h = rootHeight;
-				if(scrollRoot == html && isIE && rtl){ x += scrollRoot.offsetWidth-w; } // IE workaround where scrollbar causes negative x
-				if(x < 0 || !isIE){ x = 0; } // IE can have values > 0
-				if(y < 0 || !isIE){ y = 0; }
-			}else{
-				var pb = dojo._getPadBorderExtents(el);
-				w -= pb.w; h -= pb.h; x += pb.l; y += pb.t;
-			}
-			with(el){
-				if(el != scrollRoot){ // body, html sizes already have the scrollbar removed
-					var clientSize = clientWidth,
-						scrollBarSize = w - clientSize;
-					if(clientSize > 0 && scrollBarSize > 0){
-						w = clientSize;
-						if(isIE && rtl){ x += scrollBarSize; }
-					}
-					clientSize = clientHeight;
-					scrollBarSize = h - clientSize;
-					if(clientSize > 0 && scrollBarSize > 0){
-						h = clientSize;
-					}
-				}
-				if(fixedPos){ // bounded by viewport, not parents
-					if(y < 0){
-						h += y, y = 0;
-					}
-					if(x < 0){
-						w += x, x = 0;
-					}
-					if(y + h > rootHeight){
-						h = rootHeight - y;
-					}
-					if(x + w > rootWidth){
-						w = rootWidth - x;
-					}
-				}
-				// calculate overflow in all 4 directions
-				var l = nodePos.x - x, // beyond left: < 0
-					t = nodePos.y - Math.max(y, 0), // beyond top: < 0
-					r = l + nodePos.w - w, // beyond right: > 0
-					bot = t + nodePos.h - h; // beyond bottom: > 0
-				if(r * l > 0){
-					var s = Math[l < 0? "max" : "min"](l, r);
-					nodePos.x += scrollLeft;
-					scrollLeft += (isIE >= 8 && !backCompat && rtl)? -s : s;
-					nodePos.x -= scrollLeft;
-				}
-				if(bot * t > 0){
-					nodePos.y += scrollTop;
-					scrollTop += Math[t < 0? "max" : "min"](t, bot);
-					nodePos.y -= scrollTop;
-				}
-			}
-		}
-		el = (el != scrollRoot) && !fixedPos && el.parentNode;
-	}
-	}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_ie6: maj(ie) == 6,
-			dj_ie7: maj(ie) == 7,
-			dj_ie8: maj(ie) == 8,
-			dj_iequirks: ie && d.isQuirks,
-
-			// NOTE: Opera not supported by dijit
-			dj_opera: opera,
-
-			dj_khtml: d.isKhtml,
-
-			dj_webkit: d.isWebKit,
-			dj_safari: d.isSafari,
-			dj_chrome: d.isChrome,
-
-			dj_gecko: d.isMozilla,
-			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);
-		
-		// Schedule next event, reducing the timer a little bit each iteration, bottoming-out at 10 to avoid
-		// browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup)
-		this._currentTimeout = Math.max(
-			this._currentTimeout < 0 ? this._initialDelay :
-				(this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)),
-			10);
-		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.altKey) &&
-				(keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey
-				(keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){
-					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:
-		//		Replace existing role attribute with new role.
-		//		If elem already has an XHTML role, append this role to XHTML role
-		//		and remove other ARIA roles.
-
-		var curRole = dojo.attr(elem, "role") || "";
-		if(!this._XhtmlRoles.test(curRole)){
-			dojo.attr(elem, "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 t = dojo.trim((" " + roleValue + " ").replace(" " + role + " ", " "));
-			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:
-		//		Checks for an attribute called "aria-"+state.
-		// returns:
-		//		true if elem has a value for the given state and
-		//		false if it does not.
-
-		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:
-		//		Checks 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.
-
-		return elem.getAttribute("aria-"+state) || "";
-	},
-
-	setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
-		// summary:
-		//		Sets a state on an element.
-		// description:
-		//		Sets an attribute called "aria-"+state.
-
-		elem.setAttribute("aria-"+state, value);
-	},
-
-	removeWaiState: function(/*Element*/ elem, /*String*/ state){
-		// summary:
-		//		Removes a state from an element.
-		// description:
-		//		Sets an attribute called "aria-"+state.
-
-		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["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),
-		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); //TODO: UTC defaults
-		if(match[0] < 100){
-			result.setFullYear(match[0] || 1970);
-		}
-
-		var offset = 0,
-			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 = [],
-		getter = options.zulu ? "getUTC" : "get",
-		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;
-	this._attrName = d._scopeName + "Type";
-	this._query = "[" + this._attrName + "]";
-
-	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){
-						// The user has specified some text for a function like "return x+5"
-						return new Function(value);
-					}else{
-						// The user has specified the name of a function like "myOnClick"
-						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"} }
-	};
-
-	// Widgets like BorderContainer add properties to _Widget via dojo.extend().
-	// If BorderContainer is loaded after _Widget's parameter list has been cached,
-	// we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
-	dojo.connect(dojo, "extend", function(){
-		instanceClasses = {};
-	});
-
-	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, /* Object? */args){
-		// 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.
-		// args: Object?
-		//		An object used to hold kwArgs for instantiation.
-		//		Only supports 'noStart' currently.
-		var thelist = [], dp = dojo.parser;
-		mixin = mixin||{};
-		args = args||{};
-		
-		d.forEach(nodes, function(node){
-			if(!node){ return; }
-			var type = dp._attrName in mixin?mixin[dp._attrName]:node.getAttribute(dp._attrName);
-			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 || clazz.prototype && 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
-		if(!mixin._started){
-			d.forEach(thelist, function(instance){
-				if(	!args.noStart && instance  && 
-					instance.startup &&
-					!instance._started && 
-					(!instance.getParent || !instance.getParent())
-				){
-					instance.startup();
-				}
-			});
-		}
-		return thelist;
-	};
-
-	this.parse = function(/*DomNode?*/ rootNode, /* Object? */ args){
-		// summary:
-		//		Scan the DOM for class instances, and instantiate them.
-		//
-		// description:
-		//		Search specified node (or root node) recursively for class instances,
-		//		and instantiate them Searches for
-		//		dojoType="qualified.class.name"
-		//
-		// rootNode: DomNode?
-		//		A default starting root node from which to start the parsing. Can be
-		//		omitted, defaulting to the entire document. If omitted, the `args`
-		//		object can be passed in this place. If the `args` object has a 
-		//		`rootNode` member, that is used.
-		//
-		// args:
-		//		a kwArgs object passed along to instantiate()
-		//		
-		//			* noStart: Boolean?
-		//				when set will prevent the parser from calling .startup()
-		//				when locating the nodes. 
-		//			* rootNode: DomNode?
-		//				identical to the function's `rootNode` argument, though
-		//				allowed to be passed in via this `args object. 
-		//
-		// example:
-		//		Parse all widgets on a page:
-		//	|		dojo.parser.parse();
-		//
-		// example:
-		//		Parse all classes within the node with id="foo"
-		//	|		dojo.parser.parse(dojo.byId(foo));
-		//
-		// example:
-		//		Parse all classes in a page, but do not call .startup() on any 
-		//		child
-		//	|		dojo.parser.parse({ noStart: true })
-		//
-		// example:
-		//		Parse all classes in a node, but do not call .startup()
-		//	|		dojo.parser.parse(someNode, { noStart:true });
-		//	|		// or
-		// 	|		dojo.parser.parse({ noStart:true, rootNode: someNode });
-
-		// determine the root node based on the passed arguments.
-		var root;
-		if(!args && rootNode && rootNode.rootNode){
-			args = rootNode;
-			root = args.rootNode;
-		}else{
-			root = rootNode;
-		}
-
-		var	list = d.query(this._query, root);
-			// go build the object instances
-		return this.instantiate(list, null, args); // Array
-
-	};
-}();
-
-//Register the parser callback. It should be the first callback
-//after the a11y test.
-
-(function(){
-	var parseRunner = function(){ 
-		if(dojo.config.parseOnLoad){
-			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["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" );
-
-
-// This code is to assist deferring dojo.connect() calls in widgets (connecting to events on the widgets'
-// DOM nodes) until someone actually needs to monitor that event.
-dojo.connect(dojo, "_connect",
-	function(/*dijit._Widget*/ widget, /*String*/ event){
-		if(widget && dojo.isFunction(widget._onConnect)){
-			widget._onConnect(event);
-		}
-	});
-
-dijit._connectOnUseEventHandler = function(/*Event*/ event){};
-
-// Keep track of where the last keydown event was, to help avoid generating
-// spurious ondijitclick events when:
-// 1. focus is on a <button> or <a>
-// 2. user presses then releases the ENTER key
-// 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
-// 4. onkeyup event fires, causing the ondijitclick handler to fire
-dijit._lastKeyDownNode = null;
-if(dojo.isIE){
-	(function(){
-		var keydownCallback = function(evt){
-			dijit._lastKeyDownNode = evt.srcElement;
-		};
-		dojo.doc.attachEvent('onkeydown', keydownCallback);
-		dojo.addOnWindowUnload(function(){
-			dojo.doc.detachEvent('onkeydown', keydownCallback);
-		});
-	})();
-}else{
-	dojo.doc.addEventListener('keydown', function(evt){
-		dijit._lastKeyDownNode = evt.target;
-	}, true);
-}
-
-(function(){
-
-var _attrReg = {},	// cached results from getSetterAttributes
-	getSetterAttributes = function(widget){
-		// summary:
-		//		Returns list of attributes with custom setters for specified widget
-		var dc = widget.declaredClass;
-		if(!_attrReg[dc]){
-			var r = [],
-				attrs,
-				proto = widget.constructor.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] || [];	// String[]
-	};
-
-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.
-	//
-	//		For form widgets this specifies a tooltip to display when hovering over
-	//		the widget (just like the native HTML title attribute).
-	//
-	//		For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
-	//		etc., it's used to specify the tab label, accordion pane title, etc.
-	title: "",
-
-	// tooltip: String
-	//		When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
-	//		this specifies the tooltip to appear when the mouse is hovered over that text.
-	tooltip: "",
-
-	// 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,
-
-/*=====
-	// _started: Boolean
-	//		startup() has completed.
-	_started: false,
-=====*/
-
-	// 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 innerText
-	//	|		title: { node: "titleNode", type: "innerText" }
-	//		Maps this.title to this.titleNode.innerText
-	//
-	//		- 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] String
-	//		Path to a blank 1x1 image.
-	//		Used by <img> nodes in templates that really get their image via CSS background-image.
-	_blankGif: (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")).toString(),
-
-	//////////// 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:
-		//		Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
-		//		etc.), some of which of you'll want to override. See http://docs.dojocampus.org/dijit/_Widget
-		//		for a discussion of the widget creation lifecycle.
-		//
-		//		Of course, adventurous developers could override create entirely, but this should
-		//		only be done as a last resort.
-		// 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 = [];
-
-		// For garbage collection.  An array of handles returned by Widget.subscribe()
-		// The handle returned from Widget.subscribe() is the handle returned from dojo.subscribe()
-		this._subscribes = [];
-
-		// 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]);
-			}
-		};
-
-		// Do the attributes in attributeMap
-		for(var attr in this.attributeMap){
-			condAttrApply(attr, this);
-		}
-
-		// And also any attributes with custom setters
-		dojo.forEach(getSetterAttributes(this), 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
-		// description:
-		//		Most widgets will mixin `dijit._Templated`, which implements this
-		//		method.
-		// tags:
-		//		protected
-		this.domNode = this.srcNodeRef || dojo.create('div');
-	},
-
-	postCreate: function(){
-		// summary:
-		//		Processing after the DOM fragment is created
-		// description:
-		//		Called after the DOM fragment has been created, but not necessarily
-		//		added to the document.  Do not include any operations which rely on
-		//		node dimensions or placement.
-		// tags:
-		//		protected
-	},
-
-	startup: function(){
-		// summary:
-		//		Processing after the DOM fragment is added to the document
-		// description:
-		//		Called after a widget and its children have been created and added to the page,
-		//		and all related widgets have finished their create() cycle, up through postCreate().
-		//		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 its descendants
-		// description:
-		//		This is the generic "destructor" function that all widget users
-		// 		should call to cleanly discard with a widget. Once a widget is
-		// 		destroyed, it is 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._beingDestroyed = true;
-		this.destroyDescendants(preserveDom);
-		this.destroy(preserveDom);
-	},
-
-	destroy: function(/*Boolean*/ preserveDom){
-		// summary:
-		// 		Destroy this widget, but not its descendants.
-		//		This method 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._beingDestroyed = true;
-		this.uninitialize();
-		var d = dojo,
-			dfe = d.forEach,
-			dun = d.unsubscribe;
-		dfe(this._connects, function(array){
-			dfe(array, d.disconnect);
-		});
-		dfe(this._subscribes, function(handle){
-			dun(handle);
-		});
-
-		// destroy widgets created as part of template, etc.
-		dfe(this._supportingWidgets || [], function(w){
-			if(w.destroyRecursive){
-				w.destroyRecursive();
-			}else if(w.destroy){
-				w.destroy();
-			}
-		});
-
-		this.destroyRendering(preserveDom);
-		dijit.registry.remove(this.id);
-		this._destroyed = true;
-	},
-
-	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, innerText, or attribute
-
-			switch(type){
-				case "attribute":
-					if(dojo.isFunction(value)){ // functions execute in the context of the widget
-						value = dojo.hitch(this, value);
-					}
-
-					// Get the name of the DOM node attribute; usually it's the same
-					// as the name of the attribute in the widget (attr), but can be overridden.
-					// Also maps handler names to lowercase, like onSubmit --> onsubmit
-					var attrName = command.attribute ? command.attribute :
-						(/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
-
-					dojo.attr(mapNode, attrName, value);
-					break;
-				case "innerText":
-					mapNode.innerHTML = "";
-					mapNode.appendChild(dojo.doc.createTextNode(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
-				args = dojo._toArray(arguments, 1);
-				return this[names.s].apply(this, args) || 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
-			return this[names.g] ? this[names.g]() : 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
-		// description:
-		//		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 reversible
-		//		serialization.
-		return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
-	},
-
-	getDescendants: function(){
-		// summary:
-		//		Returns all the widgets 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.
-
-		return this.containerNode ? dojo.query('[widgetId]', this.containerNode).map(dijit.byNode) : []; // dijit._Widget[]
-	},
-
-	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.
-		return this.containerNode ? dijit.findWidgets(this.containerNode) : []; // dijit._Widget[]
-	},
-
-	// 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 or enter keyup
-		// returns:
-		//		A handle that can be passed to `disconnect` in order to disconnect before
-		//		the widget is destroyed.
-		// 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(){
-		//	|		console.debug(this.toString());
-		//	|	});
-		// tags:
-		//		protected
-
-		var d = dojo,
-			dc = d._connect,
-			handles = [];
-		if(event == "ondijitclick"){
-			// add key based click activation for unsupported nodes.
-			// do all processing onkey up to prevent spurious clicks
-			// for details see comments at top of this file where _lastKeyDownNode is defined
-			if(!this.nodesWithKeyClick[obj.tagName.toLowerCase()]){
-				var m = d.hitch(this, method);
-				handles.push(
-					dc(obj, "onkeydown", this, function(e){
-						//console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
-						if((e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
-							!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
-							// needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
-							dijit._lastKeyDownNode = e.target;
-							d.stopEvent(e);		// stop event to prevent scrolling on space key in IE
-						}
-			 		}),
-					dc(obj, "onkeyup", this, function(e){
-						//console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
-						if( (e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
-							e.target === dijit._lastKeyDownNode &&
-							!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
-								//need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
-								dijit._lastKeyDownNode = null;
-								return m(e);
-						}
-					})
-				);
-			}
-			event = "onclick";
-		}
-		handles.push(dc(obj, event, this, method));
-
-		this._connects.push(handles);
-		return handles;		// _Widget.Handle
-	},
-
-	disconnect: function(/* _Widget.Handle */ handles){
-		// summary:
-		//		Disconnects handle created by `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;
-			}
-		}
-	},
-
-	subscribe: function(
-			/*String*/ topic,
-			/*String|Function*/ method){
-		// summary:
-		//		Subscribes to the specified topic and calls the specified method
-		//		of this object and registers for unsubscribe() on widget destroy.
-		// description:
-		//		Provide widget-specific analog to dojo.subscribe, except with the
-		//		implicit use of this widget as the target object.
-		// example:
-		//	|	var btn = new dijit.form.Button();
-		//	|	// when /my/topic is published, this button changes its label to
-		//	|   // be the parameter of the topic.
-		//	|	btn.subscribe("/my/topic", function(v){
-		//	|		this.attr("label", v);
-		//	|	});
-		var d = dojo,
-			handle = d.subscribe(topic, this, method);
-
-		// return handles for Any widget that may need them
-		this._subscribes.push(handle);
-		return handle;
-	},
-
-	unsubscribe: function(/*Object*/ handle){
-		// summary:
-		//		Unsubscribes handle created by this.subscribe.
-		//		Also removes handle from this widget's list of subscriptions
-		for(var i=0; i<this._subscribes.length; i++){
-			if(this._subscribes[i] == handle){
-				dojo.unsubscribe(handle);
-				this._subscribes.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){ console.log('click'); });
-		//
-		// 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;
-	},
-
-	_onShow: function(){
-		// summary:
-		//		Internal method called when this widget is made visible.
-		//		See `onShow` for details.
-		this.onShow();
-	},
-
-	onShow: function(){
-		// summary:
-		//		Called when this widget becomes the selected pane in a
-		//		`dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
-		//		`dijit.layout.AccordionContainer`, etc.
-		//
-		//		Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
-		// tags:
-		//		callback
-	},
-
-	onHide: function(){
-		// summary:
-			//		Called when another widget becomes the selected pane in a
-			//		`dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
-			//		`dijit.layout.AccordionContainer`, etc.
-			//
-			//		Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
-			// tags:
-			//		callback
-	}
-});
-
-})();
-
-}
-
-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. mylib.encodeXML
-	//	thisObject: 
-	//		where to look for optional format function; default to the global
-	//		namespace
-	//	example:
-	//		Substitutes two expressions in a string from an Array or Object
-	//	|	// returns "File 'foo.html' is not found in directory '/temp'."
-	//	|	// by providing substitution data in an Array
-	//	|	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'."
-	//	|	// but provides substitution data in an Object structure.  Dotted
-	//	|	// notation may be used to traverse the structure.
-	//	|	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 ? 
-		dojo.hitch(thisObject, transform) : function(v){ return v; };
-
-	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.cache"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.cache"] = true;
-dojo.provide("dojo.cache");
-
-/*=====
-dojo.cache = { 
-	// summary:
-	// 		A way to cache string content that is fetchable via `dojo.moduleUrl`.
-};
-=====*/
-
-(function(){
-	var cache = {};
-	dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
-		// summary:
-		// 		A getter and setter for storing the string content associated with the
-		// 		module and url arguments.
-		// description:
-		// 		module and url are used to call `dojo.moduleUrl()` to generate a module URL.
-		// 		If value is specified, the cache value for the moduleUrl will be set to
-		// 		that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
-		// 		in its internal cache and return that cached value for the URL. To clear
-		// 		a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
-		// 		the URL contents, only modules on the same domain of the page can use this capability.
-		// 		The build system can inline the cache values though, to allow for xdomain hosting.
-		// module: String||Object
-		// 		If a String, the module name to use for the base part of the URL, similar to module argument
-		// 		to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
-		// 		generates a valid path for the cache item. For example, a dojo._Url object.
-		// url: String
-		// 		The rest of the path to append to the path derived from the module argument. If
-		// 		module is an object, then this second argument should be the "value" argument instead.
-		// value: String||Object?
-		// 		If a String, the value to use in the cache for the module/url combination.
-		// 		If an Object, it can have two properties: value and sanitize. The value property
-		// 		should be the value to use in the cache, and sanitize can be set to true or false,
-		// 		to indicate if XML declarations should be removed from the value and if the HTML
-		// 		inside a body tag in the value should be extracted as the real value. The value argument
-		// 		or the value property on the value argument are usually only used by the build system
-		// 		as it inlines cache content.
-		//	example:
-		//		To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
-		// 		of call is used to avoid an issue with the build system erroneously trying to intern
-		// 		this example. To get the build system to intern your dojo.cache calls, use the
-		// 		"dojo.cache" style of call):
-		// 		|	//If template.html contains "<h1>Hello</h1>" that will be
-		// 		|	//the value for the text variable.
-		//		|	var text = dojo["cache"]("my.module", "template.html");
-		//	example:
-		//		To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
-		// 		 (the dojo["cache"] style of call is used to avoid an issue with the build system 
-		// 		erroneously trying to intern this example. To get the build system to intern your
-		// 		dojo.cache calls, use the "dojo.cache" style of call):
-		// 		|	//If template.html contains "<html><body><h1>Hello</h1></body></html>", the
-		// 		|	//text variable will contain just "<h1>Hello</h1>".
-		//		|	var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
-		//	example:
-		//		Same example as previous, but demostrates how an object can be passed in as
-		//		the first argument, then the value argument can then be the second argument.
-		// 		|	//If template.html contains "<html><body><h1>Hello</h1></body></html>", the
-		// 		|	//text variable will contain just "<h1>Hello</h1>".
-		//		|	var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
-
-		//Module could be a string, or an object that has a toString() method
-		//that will return a useful path. If it is an object, then the "url" argument
-		//will actually be the value argument.
-		if(typeof module == "string"){
-			var pathObj = dojo.moduleUrl(module, url);
-		}else{
-			pathObj = module;
-			value = url;
-		}
-		var key = pathObj.toString();
-
-		var val = value;
-		if(value !== undefined && !dojo.isString(value)){
-			val = ("value" in value ? value.value : undefined);
-		}
-
-		var sanitize = value && value.sanitize ? true : false;
-
-		if(val || val === null){
-			//We have a value, either clear or set the cache value.
-			if(val == null){
-				delete cache[key];
-			}else{
-				val = cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
-			}
-		}else{
-			//Allow cache values to be empty strings. If key property does
-			//not exist, fetch it.
-			if(!(key in cache)){
-				val = dojo._getText(key);
-				cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
-			}
-			val = cache[key];
-		}
-		return val; //String
-	};
-
-	dojo.cache._sanitize = function(/*String*/val){
-		// 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.
-		// description:
-		// 		Copied from dijit._Templated._sanitizeTemplateString.
-		if(val){
-			val = val.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
-			var matches = val.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
-			if(matches){
-				val = matches[1];
-			}
-		}else{
-			val = "";
-		}
-		return val; //String
-	};
-})();
-
-}
-
-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.
-		//
-		//		Use in conjunction with dojo.cache() to load from a file.
-		templateString: null,
-
-		// templatePath: [protected deprecated] String
-		//		Path to template (HTML file) for this widget relative to dojo.baseUrl.
-		//		Deprecated: use templateString with dojo.cache() instead.
-		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,
-
-		// _earlyTemplatedStartup: Boolean
-		//		A fallback to preserve the 1.0 - 1.3 behavior of children in
-		//		templates having their startup called before the parent widget
-		//		fires postCreate. Defaults to 'false', causing child widgets to
-		//		have their .startup() called immediately before a parent widget
-		//		.startup(), but always after the parent .postCreate(). Set to
-		//		'true' to re-enable to previous, arguably broken, behavior.
-		_earlyTemplatedStartup: false,
-
-		// _attachPoints: [private] String[]
-		//		List of widget attribute names associated with dojoAttachPoint=... in the
-		//		template, ex: ["containerNode", "labelNode"]
-/*=====
- 		_attachPoints: [],
- =====*/
-
-		constructor: function(){
-			this._attachPoints = [];
-		},
-
-		_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,"""); //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));
-				if(node.nodeType != 1){
-					// Flag common problems such as templates with multiple top level nodes (nodeType == 11)
-					throw new Error("Invalid template: " + 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){
-				// Make sure dojoType is used for parsing widgets in template.
-				// The dojo.parser.query could be changed from multiversion support.
-				var parser = dojo.parser, qry, attr;
-				if(parser._query != "[dojoType]"){
-					qry = parser._query;
-					attr = parser._attrName;
-					parser._query = "[dojoType]";
-					parser._attrName = "dojoType";
-				}
-
-				// Store widgets that we need to start at a later point in time
-				var cw = (this._startupWidgets = dojo.parser.parse(node, {
-					noStart: !this._earlyTemplatedStartup
-				}));
-
-				// Restore the query.
-				if(qry){
-					parser._query = qry;
-					parser._attrName = attr;
-				}
-
-				this._supportingWidgets = dijit.findWidgets(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;
-						}
-						this._attachPoints.push(point);
-					}
-				}
-
-				// 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]);
-						}
-					});
-				}
-			}
-		},
-
-		startup: function(){
-			dojo.forEach(this._startupWidgets, function(w){
-				if(w && !w._started && w.startup){
-					w.startup();
-				}
-			});
-			this.inherited(arguments);
-		},
-
-		destroyRendering: function(){
-			// Delete all attach points to prevent IE6 memory leaks.
-			dojo.forEach(this._attachPoints, function(point){
-				delete this[point];
-			}, this);
-			this._attachPoints = [];
-
-			this.inherited(arguments);
-		}
-	}
-);
-
-// 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||dojo.uri.Uri
-	//		The URL to get the template from.
-	// 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){
-		try{
-			// if the cached value is an innerHTML string (no ownerDocument) or a DOM tree created within the current document, then use the current cached value
-			if(!cached.ownerDocument || cached.ownerDocument == dojo.doc){
-				// string or node of the same document
-				return cached;
-			}
-		}catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded
-		dojo.destroy(cached);
-	}
-
-	// If necessary, load template string from template path
-	if(!templateString){
-		templateString = dojo.cache(templatePath, {sanitize: true});
-	}
-	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
-		var node = dojo._toDom(templateString);
-		if(node.nodeType != 1){
-			throw new Error("Invalid template: " + templateString);
-		}
-		return (tmplts[key] = node); //Node
-	}
-};
-
-if(dojo.isIE){
-	dojo.addOnWindowUnload(function(){
-		var cache = dijit._Templated._templateCache;
-		for(var key in cache){
-			var value = cache[key];
-			if(typeof value == "object"){ // value is either a string or a DOM node template
-				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._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
-		//		Indicates that this widget acts as a "parent" to the descendant widgets.
-		//		When the parent is started it will call startup() on the child widgets.
-		//		See also `isLayoutContainer`.
-		isContainer: true,
-
-		buildRendering: function(){
-			this.inherited(arguments);
-			if(!this.containerNode){
-				// all widgets with descendants must set containerNode
-	 				this.containerNode = this.domNode;
-			}
-		},
-
-		addChild: function(/*dijit._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(widget && widget.domNode){
-				var node = widget.domNode;
-				node.parentNode.removeChild(node); // detach but don't destroy
-			}
-		},
-
-		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 dojo.query("> [widgetId]", this.containerNode).length > 0;	// 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(/*dijit._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,
-				which = (dir>0 ? "nextSibling" : "previousSibling");
-			do{
-				node = node[which];
-			}while(node && (node.nodeType != 1 || !dijit.byNode(node)));
-			return node && dijit.byNode(node);	// dijit._Widget
-		},
-
-		getIndexOfChild: function(/*dijit._Widget*/ child){
-			// summary:
-			//		Gets the index of the child in this container or -1 if not found
-			return dojo.indexOf(this.getChildren(), child);	// int
-		},
-
-		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; }
-
-			// Startup all children of this widget
-			dojo.forEach(this.getChildren(), function(child){ child.startup(); });
-
-			this.inherited(arguments);
-		}
-	}
-);
-
-}
-
-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
-				//		specifies isContainer
-				var parent = dijit.getEnclosingWidget(this.domNode.parentNode);
-				return parent && parent.isContainer ? parent : null;
-			},
-
-			_getSibling: function(/*String*/ 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);
-				return node && dijit.byNode(node);	// dijit._Widget
-			},
-
-			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"); // dijit._Widget
-			},
-
-			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"); // dijit._Widget
-			},
-
-			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.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 manage placement and sizing of 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,
-		//		for example dijitTabContainer-content.
-		baseClass: "dijitLayoutContainer",
-
-		// isLayoutContainer: [protected] Boolean
-		//		Indicates that this widget is going to call resize() on its
-		//		children widgets, setting their size, when they become visible.
-		isLayoutContainer: true,
-
-		postCreate: function(){
-			dojo.addClass(this.domNode, "dijitContainer");
-			dojo.addClass(this.domNode, this.baseClass);
-
-			this.inherited(arguments);
-		},
-
-		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; }
-
-			// Need to call inherited first - so that child widgets get started
-			// up correctly
-			this.inherited(arguments);
-
-			// If I am a not being controlled by a parent layout widget...
-			var parent = this.getParent && this.getParent()
-			if(!(parent && parent.isLayoutContainer)){
-				// 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 *may be* width=height=100%
-				// or something similar (either set directly or via a CSS class),
-				// monitor when my size changes so that I can re-layout.
-				// For browsers where I can't directly monitor when my size changes,
-				// monitor when the viewport changes size, which *may* indicate a size change for me.
-				this.connect(dojo.isIE ? this.domNode : dojo.global, 'onresize', function(){
-					// Using function(){} closure to ensure no arguments to resize.
-					this.resize();
-				});
-			}
-		},
-
-		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 its 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 its 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(/*dijit._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(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
-			// Overrides _Container.addChild() to call _setupChild()
-			this.inherited(arguments);
-			if(this._started){
-				this._setupChild(child);
-			}
-		},
-
-		removeChild: function(/*dijit._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 its 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["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,
-
-	// 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",
-		id: "focusNode",
-		tabIndex: "focusNode",
-		alt: "focusNode",
-		title: "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);
-		if(this.valueNode){
-			dojo.attr(this.valueNode, '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.setAttribute('tabIndex', "-1");
-		}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){
-				if(this._onChangeHandle){
-					clearTimeout(this._onChangeHandle);
-				}
-				// setTimout allows hidden value processing to run and
-				// also the onChange handler can safely adjust focus, etc
-				this._onChangeHandle = setTimeout(dojo.hitch(this,
-					function(){
-						this._onChangeHandle = null;
-						this.onChange(newValue);
-					}), 0); // try to collapse multiple onChange's fired faster than can be processed
-			}
-		}
-	},
-
-	create: function(){
-		// Overrides _Widget.create()
-		this.inherited(arguments);
-		this._onChangeActive = true;
-		this._setStateClass();
-	},
-
-	destroy: function(){
-		if(this._onChangeHandle){ // destroy called before last onChange has fired
-			clearTimeout(this._onChangeHandle);
-			this.onChange(this._lastValueReported);
-		}
-		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');
-	}
-});
-
-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)
-
-	// 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,
-
-	attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
-		value: "",
-		readOnly: "focusNode"
-	}),
-
-	_setReadOnlyAttr: function(/*Boolean*/ value){
-		this.readOnly = value;
-		dojo.attr(this.focusNode, 'readOnly', value);
-		dijit.setWaiState(this.focusNode, "readonly", value);
-		this._setStateClass();
-	},
-
-	postCreate: function(){
-		if(dojo.isIE){ // IE won't stop the event with keypress
-			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(){
-		// 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 || e.metaKey)){
-			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);
-			}
-		}
-	},
-
-	_layoutHackIE7: function(){
-		// summary:
-		//		Work around table sizing bugs on IE7 by forcing redraw
-
-		if(dojo.isIE == 7){ // fix IE7 layout bug when the widget is scrolled out of sight
-			var domNode = this.domNode;
-			var parent = domNode.parentNode;
-			var pingNode = domNode.firstChild || domNode; // target node most unlikely to have a custom filter
-			var origFilter = pingNode.style.filter; // save custom filter, most likely nothing
-			while(parent && parent.clientHeight == 0){ // search for parents that haven't rendered yet
-				parent._disconnectHandle = this.connect(parent, "onscroll", dojo.hitch(this, function(e){
-					this.disconnect(parent._disconnectHandle); // only call once
-					parent.removeAttribute("_disconnectHandle"); // clean up DOM node
-					pingNode.style.filter = (new Date()).getMilliseconds(); // set to anything that's unique
-					setTimeout(function(){ pingNode.style.filter = origFilter }, 0); // restore custom filter, if any
-				}));
-				parent = parent.parentNode;
-			}
-		}
-	}
-});
-
-}
-
-if(!dojo._hasResource["dijit.dijit"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.dijit"] = true;
-dojo.provide("dijit.dijit");
-
-/*=====
-dijit.dijit = {
-	// summary:
-	//		A roll-up for common dijit methods
-	// description:
-	//	A rollup file for the build system including the core and common
-	//	dijit files.
-	//
-	// example:
-	// | <script type="text/javascript" src="js/dojo/dijit/dijit.js"></script>
-	//
-};
-=====*/
-
-// All the stuff in _base (these are the function that are guaranteed available without an explicit dojo.require)
-
-
-// And some other stuff that we tend to pull in all the time anyway
-
-
-
-
-
-
-
-}
-
-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(/*dijit._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
-			var child = this._getFirstFocusableChild();
-			if(child){ // edge case: Menu could be empty or hidden
-				this.focusChild(child);
-			}
-		},
-
-		focusNext: function(){
-			// summary:
-			//		Focus the next widget
-			// tags:
-			//		protected
-			var child = this._getNextFocusableChild(this.focusedChild, 1);
-			this.focusChild(child);
-		},
-
-		focusPrev: function(){
-			// summary:
-			//		Focus the last focusable node in the previous widget
-			//		(ex: go to the ComboButton icon section rather than button section)
-			// tags:
-			//		protected
-			var child = this._getNextFocusableChild(this.focusedChild, -1);
-			this.focusChild(child, true);
-		},
-
-		focusChild: function(/*dijit._Widget*/ widget, /*Boolean*/ last){
-			// summary:
-			//		Focus widget.
-			// widget:
-			//		Reference to container's child widget
-			// last:
-			//		If true and if widget has multiple focusable nodes, focus the
-			//		last one instead of the first one
-			// tags:
-			//		protected
-			
-			if(this.focusedChild && widget !== this.focusedChild){
-				this._onChildBlur(this.focusedChild);
-			}
-			widget.focus(last ? "end" : "start");
-			this.focusedChild = widget;
-		},
-
-		_startupChild: function(/*dijit._Widget*/ widget){
-			// summary:
-			//		Setup for each child widget
-			// description:
-			//		Sets tabIndex=-1 on each child, so that the tab key will 
-			//		leave the container rather than visiting each child.
-			// tags:
-			//		private
-			
-			widget.attr("tabIndex", "-1");
-			
-			this.connect(widget, "_onFocus", function(){
-				// Set valid tabIndex so tabbing away from widget goes to right place, see #10272
-				widget.attr("tabIndex", this.tabIndex);
-			});
-			this.connect(widget, "_onBlur", function(){
-				widget.attr("tabIndex", "-1");
-			});
-		},
-
-		_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 set the container's tabIndex to -1,
-			// (don't remove as that breaks Safari 4)
-			// so that tab or shift-tab will go to the fields after/before
-			// the container, rather than the container itself
-			dojo.attr(this.domNode, "tabIndex", "-1");
-		},
-
-		_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);
-			}
-			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);
-			}
-		},
-
-		_onChildBlur: function(/*dijit._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);	// dijit._Widget
-		},
-
-		_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;	// dijit._Widget
-				}
-				child = this._getSiblingOfChild(child, dir);
-			}
-			// no focusable child found
-			return null;	// dijit._Widget
-		}
-	}
-);
-
-}
-
-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: dojo.cache("dijit", "templates/MenuItem.html", "<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\" dojo [...]
-
-		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);
-			var label = this.id+"_text";
-			dojo.attr(this.containerNode, "id", label);
-			if(this.accelKeyNode){
-				dojo.attr(this.accelKeyNode, "id", this.id + "_accel");
-				label += " " + this.id + "_accel";
-			}
-			dijit.setWaiState(this.domNode, "labelledby", label);
-		},
-
-		_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{
-				if(dojo.isIE == 8){
-					// needed for IE8 which won't scroll TR tags into view on focus yet calling scrollIntoView creates flicker (#10275)
-					this.containerNode.focus();
-				}
-				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);
-			this.getParent()._onItemFocus(this);
-
-			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){
-				// Destroy the popup, unless it's already been destroyed.  This can happen because
-				// the popup is a direct child of <body> even though it's logically my child.
-				if(!this.popup._destroyed){
-					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: dojo.cache("dijit", "templates/CheckedMenuItem.html", "<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=\"dijitCheckedMen [...]
-
-		// 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: dojo.cache("dijit", "templates/MenuSeparator.html", "<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();
-			}
-		}
-	},
-
-	_onPopupHover: function(/*Event*/ evt){
-		// summary:
-		//		This handler is called when the mouse moves over the popup.
-		// tags:
-		//		private
-
-		// if the mouse hovers over a menu popup that is in pending-close state,
-		// then stop the close operation.
-		// This can't be done in onItemHover since some popup targets don't have MenuItems (e.g. ColorPicker)
-		if(this.currentPopup && this.currentPopup._pendingClose_timer){
-			var parentMenu = this.currentPopup.parentMenu;
-			// highlight the parent menu item pointing to this popup
-			if(parentMenu.focusedChild){
-				parentMenu.focusedChild._setSelected(false);
-			}
-			parentMenu.focusedChild = this.currentPopup.from_item;
-			parentMenu.focusedChild._setSelected(true);
-			// cancel the pending close
-			this._stopPendingCloseTimer(this.currentPopup);
-		}
-	},
-
-	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) 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);
-			}
-		}
-		// if the user is mixing mouse and keyboard navigation,
-		// then the menu may not be active but a menu item has focus,
-		// but it's not the item that the mouse just hovered over.
-		// To avoid both keyboard and mouse selections, use the latest.
-		if(this.focusedChild){
-			this.focusChild(item);
-		}
-		this._hoveredChild = item;
-	},
-
-	_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
-		this._stopPopupTimer();
-		item._setSelected(false);
-		// Close all popups that are open and descendants of this menu
-		var itemPopup = item.popup;
-		if(itemPopup){
-			this._stopPendingCloseTimer(itemPopup);
-			itemPopup._pendingClose_timer = setTimeout(function(){
-				itemPopup._pendingClose_timer = null;
-				if(itemPopup.parentMenu){
-					itemPopup.parentMenu.currentPopup = null;
-				}
-				dijit.popup.close(itemPopup); // this calls onClose
-			}, this.popupDelay);
-		}
-	},
-
-	onItemUnhover: function(/*MenuItem*/ item){
-		// summary:
-		//		Callback fires when mouse exits a MenuItem
-		// tags:
-		//		protected
-
-		if(this.isActive){
-			this._stopPopupTimer();
-		}
-		if(this._hoveredChild == item){ this._hoveredChild = null; }
-	},
-
-	_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;
-		}
-	},
-
-	_stopPendingCloseTimer: function(/*dijit._Widget*/ popup){
-		// summary:
-		//		Cancels the pending-close timer because the close has been preempted
-		// tags:
-		//		private
-		if(popup._pendingClose_timer){
-			clearTimeout(popup._pendingClose_timer);
-			popup._pendingClose_timer = null;
-		}
-	},
-
-	_stopFocusTimer: function(){
-		// summary:
-		//		Cancels the pending-focus timer because the menu was closed before focus occured
-		// tags:
-		//		private
-		if(this._focus_timer){
-			clearTimeout(this._focus_timer);
-			this._focus_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(/*dijit._Widget*/ item, /*Event*/ evt){
-		// summary:
-		//		Handle clicks on an item.
-		// tags:
-		//		private
-		if(item.disabled){ return false; }
-
-		// this can't be done in _onFocus since the _onFocus events occurs asynchronously
-		if(typeof this.isShowingNow == 'undefined'){ // non-popup menu
-			this._markActive();
-		}
-
-		this.focusChild(item);
-
-		if(item.popup){
-			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;
-		if(!from_item){ return; } // the focused child lost focus since the timer was started
-		var popup = from_item.popup;
-		if(popup.isShowingNow){ return; }
-		if(this.currentPopup){
-			this._stopPendingCloseTimer(this.currentPopup);
-			dijit.popup.close(this.currentPopup);
-		}
-		popup.parentMenu = this;
-		popup.from_item = from_item; // helps finding the parent item that should be focused for this popup
-		var self = this;
-		dijit.popup.open({
-			parent: this,
-			popup: popup,
-			around: from_item.domNode,
-			orient: this._orient || (this.isLeftToRight() ?
-									{'TR': 'TL', 'TL': 'TR', 'BR': 'BL', 'BL': 'BR'} :
-									{'TL': 'TR', 'TR': 'TL', 'BL': 'BR', 'BR': 'BL'}),
-			onCancel: function(){ // called when the child menu is canceled
-				// set isActive=false (_closeChild vs _cleanUp) so that subsequent hovering will NOT open child menus
-				// which seems aligned with the UX of most applications (e.g. notepad, wordpad, paint shop pro)
-				self.focusChild(from_item);	// put focus back on my node
-				self._cleanUp();			// close the submenu (be sure this is done _after_ focus is moved)
-				from_item._setSelected(true); // oops, _cleanUp() deselected the item
-				self.focusedChild = from_item;	// and unset focusedChild
-			},
-			onExecute: dojo.hitch(this, "_cleanUp")
-		});
-
-		this.currentPopup = popup;
-		// detect mouseovers to handle lazy mouse movements that temporarily focus other menu items
-		popup.connect(popup.domNode, "onmouseenter", dojo.hitch(self, "_onPopupHover")); // cleaned up when the popped-up widget is destroyed on close
-
-		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)
-			popup._focus_timer = setTimeout(dojo.hitch(popup, function(){
-				this._focus_timer = null;
-				this.focus();
-			}), 0);
-		}
-	},
-
-	_markActive: function(){
-		// summary:
-		//              Mark this menu's state as active.
-		//		Called when this Menu gets focus from:
-		//			1) clicking it (mouse or via space/arrow key)
-		//			2) being opened by a parent menu.
-		//		This is not called just from mouse hover.
-		//		Focusing a menu via TAB does NOT automatically set isActive
-		//		since TAB is a navigation operation and not a selection one.
-		//		For Windows apps, pressing the ALT key focuses the menubar
-		//		menus (similar to TAB navigation) but the menu is not active
-		//		(ie no dropdown) until an item is clicked.
-		this.isActive = true;
-		dojo.addClass(this.domNode, "dijitMenuActive");
-		dojo.removeClass(this.domNode, "dijitMenuPassive");
-	},
-
-	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;
-		this._markActive();
-	},
-
-	_markInactive: function(){
-		// summary:
-		//		Mark this menu's state as inactive.
-		this.isActive = false; // don't do this in _onBlur since the state is pending-close until we get here
-		dojo.removeClass(this.domNode, "dijitMenuActive");
-		dojo.addClass(this.domNode, "dijitMenuPassive");
-	},
-
-	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._stopFocusTimer();
-		this._markInactive();
-		this.isShowingNow = false;
-		this.parentMenu = null;
-	},
-
-	_closeChild: function(){
-		// summary:
-		//		Called when submenu is clicked or focus is lost.  Close hierarchy of menus.
-		// tags:
-		//		private
-		this._stopPopupTimer();
-		if(this.focusedChild){ // unhighlight the focused item
-			this.focusedChild._setSelected(false);
-			this.focusedChild._onUnhover();
-			this.focusedChild = null;
-		}
-		if(this.currentPopup){
-			// Close all popups that are open and descendants of this menu
-			dijit.popup.close(this.currentPopup);
-			this.currentPopup = null;
-		}
-	},
-
-	_onItemFocus: function(/*MenuItem*/ item){
-		// summary:
-		//		Called when child of 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.
-		if(this._hoveredChild && this._hoveredChild != item){
-			this._hoveredChild._onUnhover(); // any previous mouse movement is trumped by focus selection
-		}
-	},
-
-	_onBlur: function(){
-		// summary:
-		//		Called when focus is moved away from this Menu and it's submenus.
-		// tags:
-		//		protected
-		this._cleanUp();
-		this.inherited(arguments);
-	},
-
-	_cleanUp: function(){
-		// summary:
-		//		Called when the user is done with this menu.  Closes hierarchy of menus.
-		// tags:
-		//		private
-
-		this._closeChild(); // don't call this.onClose since that's incorrect for MenuBar's that never close
-		if(typeof this.isShowingNow == 'undefined'){ // non-popup menu doesn't call onClose
-			this._markInactive();
-		}
-	}
-});
-
-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: dojo.cache("dijit", "templates/Menu.html", "<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,
-
-	// refocus: Boolean
-	// 		When this menu closes, re-focus the element which had focus before it was opened.
-	refocus: true,
-
-	// _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{
-			// TODO: should have _setTargetNodeIds() method to handle initialization and a possible
-			// later attr('targetNodeIds', ...) call.   There's also a problem that targetNodeIds[]
-			// gets stale after calls to bindDomNode()/unBindDomNode() as it still is just the original list (see #9610)
-			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(this._iframeContentDocument(iframe_el)) ||
-			// Moz. TODO: is this available when defaultView isn't?
-			this._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);
-
-		var cn;	// Connect node
-
-		// Support context menus on iframes.   Rather than binding to the iframe itself we need
-		// to bind to the <body> node inside the iframe.
-		if(node.tagName.toLowerCase() == "iframe"){
-			var iframe = node,
-				win = this._iframeContentWindow(iframe);
-			cn = dojo.withGlobal(win, dojo.body);
-		}else{
-			
-			// To capture these events at the top level, attach to <html>, not <body>.
-			// Otherwise right-click context menu just doesn't work.
-			cn = (node == dojo.body() ? dojo.doc.documentElement : node);
-		}
-
-
-		// "binding" is the object to track our connection to the node (ie, the parameter to bindDomNode())
-		var binding = {
-			node: node,
-			iframe: iframe
-		};
-
-		// Save info about binding in _bindings[], and make node itself record index(+1) into
-		// _bindings[] array.   Prefix w/_dijitMenu to avoid setting an attribute that may
-		// start with a number, which fails on FF/safari.
-		dojo.attr(node, "_dijitMenu" + this.id, this._bindings.push(binding));
-
-		// Setup the connections to monitor click etc., unless we are connecting to an iframe which hasn't finished
-		// loading yet, in which case we need to wait for the onload event first, and then connect
-		var doConnects = dojo.hitch(this, function(cn){
-			return [
-				dojo.connect(cn, (this.leftClickToOpen)?"onclick":"oncontextmenu", this, function(evt){
-					this._openMyself(evt, cn, iframe);
-				}),
-				dojo.connect(cn, "onkeydown", this, "_contextKey"),
-				dojo.connect(cn, "onmousedown", this, "_contextMouse")
-			];
-		});
-		binding.connects = cn ? doConnects(cn) : [];
-
-		if(iframe){
-			// Setup handler to [re]bind to the iframe when the contents are initially loaded,
-			// and every time the contents change.
-			// Need to do this b/c we are actually binding to the iframe's <body> node.
-			// Note: can't use dojo.connect(), see #9609.
-
-			binding.onloadHandler = dojo.hitch(this, function(){
-				// want to remove old connections, but IE throws exceptions when trying to
-				// access the <body> node because it's already gone, or at least in a state of limbo
-
-				var win = this._iframeContentWindow(iframe);
-					cn = dojo.withGlobal(win, dojo.body);
-				binding.connects = doConnects(cn);
-			});
-			if(iframe.addEventListener){
-				iframe.addEventListener("load", binding.onloadHandler, false);
-			}else{
-				iframe.attachEvent("onload", binding.onloadHandler);
-			}
-		}
-	},
-
-	unBindDomNode: function(/*String|DomNode*/ nodeName){
-		// summary:
-		//		Detach menu from given node
-
-		var node;
-		try{
-			node = dojo.byId(nodeName);
-		}catch(e){
-			// On IE the dojo.byId() call will get an exception if the attach point was
-			// the <body> node of an <iframe> that has since been reloaded (and thus the
-			// <body> node is in a limbo state of destruction.
-			return;
-		}
-
-		// node["_dijitMenu" + this.id] contains index(+1) into my _bindings[] array
-		var attrName = "_dijitMenu" + this.id;
-		if(node && dojo.hasAttr(node, attrName)){
-			var bid = dojo.attr(node, attrName)-1, b = this._bindings[bid];
-			dojo.forEach(b.connects, dojo.disconnect);
-
-			// Remove listener for iframe onload events
-			var iframe = b.iframe;
-			if(iframe){
-				if(iframe.removeEventListener){
-					iframe.removeEventListener("load", b.onloadHandler, false);
-				}else{
-					iframe.detachEvent("onload", b.onloadHandler);
-				}
-			}
-
-			dojo.removeAttr(node, attrName);
-			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, /*DomNode?*/ node, /*DomNode?*/ iframe){
-		// summary:
-		//		Internal function for opening myself when the user
-		//		does a right-click or something similar.
-		// node:
-		//		The node that is being clicked
-		// iframe:
-		//		If an <iframe> is being clicked, iframe points to that iframe and node
-		//		points to the iframe's body.
-		// 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;
-
-			if(iframe){
-				// Event is on <body> node of an <iframe>, convert coordinates to match main document
-				var od = e.target.ownerDocument,
-					ifc = dojo.position(iframe, true),
-					win = this._iframeContentWindow(iframe),
-					scroll = dojo.withGlobal(win, "_docScroll", dojo);
-
-				var cs = dojo.getComputedStyle(iframe),
-					tp = dojo._toPixelValue,
-					left = (dojo.isIE && dojo.isQuirks ? 0 : tp(iframe, cs.paddingLeft)) + (dojo.isIE && dojo.isQuirks ? tp(iframe, cs.borderLeftWidth) : 0),
-					top = (dojo.isIE && dojo.isQuirks ? 0 : tp(iframe, cs.paddingTop)) + (dojo.isIE && dojo.isQuirks ? tp(iframe, cs.borderTopWidth) : 0);
-
-				x += ifc.x + left - scroll.x;
-				y += ifc.y + top - scroll.y;
-			}
-		}else{
-			// otherwise open near e.target
-			var coords = dojo.position(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
-			if(self.refocus){
-				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._bindings, function(b){ if(b){ this.unBindDomNode(b.node); } }, this);
- 		this.inherited(arguments);
-	}
-}
-);
-
-// Back-compat (TODO: remove in 2.0)
-
-
-
-
-
-
-}
-
-if(!dojo._hasResource["dojox.html.metrics"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.html.metrics"] = true;
-dojo.provide("dojox.html.metrics");
-
-(function(){
-	var dhm = dojox.html.metrics;
-
-	//	derived from Morris John's emResized measurer
-	dhm.getFontMeasurements = function(){
-		//	summary
-		//	Returns an object that has pixel equivilents of standard font size values.
-		var heights = {
-			'1em':0, '1ex':0, '100%':0, '12pt':0, '16px':0, 'xx-small':0, 'x-small':0,
-			'small':0, 'medium':0, 'large':0, 'x-large':0, 'xx-large':0
-		};
-	
-		if(dojo.isIE){
-			//	we do a font-size fix if and only if one isn't applied already.
-			//	NOTE: If someone set the fontSize on the HTML Element, this will kill it.
-			dojo.doc.documentElement.style.fontSize="100%";
-		}
-	
-		//	set up the measuring node.
-		var div=dojo.doc.createElement("div");
-		var ds = div.style;
-		ds.position="absolute";
-		ds.left="-100px";
-		ds.top="0";
-		ds.width="30px";
-		ds.height="1000em";
-		ds.border="0";
-		ds.margin="0";
-		ds.padding="0";
-		ds.outline="0";
-		ds.lineHeight="1";
-		ds.overflow="hidden";
-		dojo.body().appendChild(div);
-	
-		//	do the measurements.
-		for(var p in heights){
-			ds.fontSize = p;
-			heights[p] = Math.round(div.offsetHeight * 12/16) * 16/12 / 1000;
-		}
-		
-		dojo.body().removeChild(div);
-		div = null;
-		return heights; 	//	object
-	};
-
-	var fontMeasurements = null;
-	
-	dhm.getCachedFontMeasurements = function(recalculate){
-		if(recalculate || !fontMeasurements){
-			fontMeasurements = dhm.getFontMeasurements();
-		}
-		return fontMeasurements;
-	};
-
-	var measuringNode = null, empty = {};
-	dhm.getTextBox = function(/* String */ text, /* Object */ style, /* String? */ className){
-		var m;
-		if(!measuringNode){
-			m = measuringNode = dojo.doc.createElement("div");
-			m.style.position = "absolute";
-			m.style.left = "0px";
-			m.style.top = "-10000px";
-			dojo.body().appendChild(m);
-		}else{
-			m = measuringNode;
-		}
-		// reset styles
-		m.className = "";
-		m.style.border = "0";
-		m.style.margin = "0";
-		m.style.padding = "0";
-		m.style.outline = "0";
-		// set new style
-		if(arguments.length > 1 && style){
-			for(var i in style){
-				if(i in empty){ continue; }
-				m.style[i] = style[i];
-			}
-		}
-		// set classes
-		if(arguments.length > 2 && className){
-			m.className = className;
-		}
-		// take a measure
-		m.innerHTML = text;
-		return dojo.marginBox(m);
-	};
-
-	//	determine the scrollbar sizes on load.
-	var scroll={ w:16, h:16 };
-	dhm.getScrollbar=function(){ return { w:scroll.w, h:scroll.h }; };
-
-	dhm._fontResizeNode = null;
-
-	dhm.initOnFontResize = function(interval){
-		var f = dhm._fontResizeNode = dojo.doc.createElement("iframe");
-		var fs = f.style;
-		fs.position = "absolute";
-		fs.width = "5em";
-		fs.height = "10em";
-		fs.top = "-10000px";
-		if(dojo.isIE){
-			f.onreadystatechange = function(){
-				if(f.contentWindow.document.readyState == "complete"){
-					f.onresize = f.contentWindow.parent[dojox._scopeName].html.metrics._fontresize;
-				}
-			};
-		}else{
-			f.onload = function(){
-				f.contentWindow.onresize = f.contentWindow.parent[dojox._scopeName].html.metrics._fontresize;
-			};
-		}
-		//The script tag is to work around a known firebug race condition.  See comments in bug #9046
-		f.setAttribute("src", "javascript:'<html><head><script>if(\"loadFirebugConsole\" in window){window.loadFirebugConsole();}</script></head><body></body></html>'");
-		dojo.body().appendChild(f);
-		dhm.initOnFontResize = function(){};
-	};
-
-	dhm.onFontResize = function(){};
-	dhm._fontresize = function(){
-		dhm.onFontResize();
-	}
-
-	dojo.addOnUnload(function(){
-		// destroy our font resize iframe if we have one
-		var f = dhm._fontResizeNode;
-		if(f){
-			if(dojo.isIE && f.onresize){
-				f.onresize = null;
-			}else if(f.contentWindow && f.contentWindow.onresize){
-				f.contentWindow.onresize = null;
-			}
-			dhm._fontResizeNode = null;
-		}
-	});
-
-	dojo.addOnLoad(function(){
-		// getScrollbar metrics node
-		try{
-			var n=dojo.doc.createElement("div");
-			n.style.cssText = "top:0;left:0;width:100px;height:100px;overflow:scroll;position:absolute;visibility:hidden;";
-			dojo.body().appendChild(n);
-			scroll.w = n.offsetWidth - n.clientWidth;
-			scroll.h = n.offsetHeight - n.clientHeight;
-			dojo.body().removeChild(n);
-			//console.log("Scroll bar dimensions: ", scroll);
-			delete n;
-		}catch(e){}
-
-		// text size poll setup
-		if("fontSizeWatch" in dojo.config && !!dojo.config.fontSizeWatch){
-			dhm.initOnFontResize();
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.grid.util"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid.util"] = true;
-dojo.provide("dojox.grid.util");
-
-// summary: grid utility library
-(function(){
-	var dgu = dojox.grid.util;
-
-	dgu.na = '...';
-	dgu.rowIndexTag = "gridRowIndex";
-	dgu.gridViewTag = "gridView";
-
-
-	dgu.fire = function(ob, ev, args){
-		var fn = ob && ev && ob[ev];
-		return fn && (args ? fn.apply(ob, args) : ob[ev]());
-	};
-	
-	dgu.setStyleHeightPx = function(inElement, inHeight){
-		if(inHeight >= 0){
-			var s = inElement.style;
-			var v = inHeight + 'px';
-			if(inElement && s['height'] != v){
-				s['height'] = v;
-			}
-		}
-	};
-	
-	dgu.mouseEvents = [ 'mouseover', 'mouseout', /*'mousemove',*/ 'mousedown', 'mouseup', 'click', 'dblclick', 'contextmenu' ];
-
-	dgu.keyEvents = [ 'keyup', 'keydown', 'keypress' ];
-
-	dgu.funnelEvents = function(inNode, inObject, inMethod, inEvents){
-		var evts = (inEvents ? inEvents : dgu.mouseEvents.concat(dgu.keyEvents));
-		for (var i=0, l=evts.length; i<l; i++){
-			inObject.connect(inNode, 'on' + evts[i], inMethod);
-		}
-	};
-
-	dgu.removeNode = function(inNode){
-		inNode = dojo.byId(inNode);
-		inNode && inNode.parentNode && inNode.parentNode.removeChild(inNode);
-		return inNode;
-	};
-	
-	dgu.arrayCompare = function(inA, inB){
-		for(var i=0,l=inA.length; i<l; i++){
-			if(inA[i] != inB[i]){return false;}
-		}
-		return (inA.length == inB.length);
-	};
-	
-	dgu.arrayInsert = function(inArray, inIndex, inValue){
-		if(inArray.length <= inIndex){
-			inArray[inIndex] = inValue;
-		}else{
-			inArray.splice(inIndex, 0, inValue);
-		}
-	};
-	
-	dgu.arrayRemove = function(inArray, inIndex){
-		inArray.splice(inIndex, 1);
-	};
-	
-	dgu.arraySwap = function(inArray, inI, inJ){
-		var cache = inArray[inI];
-		inArray[inI] = inArray[inJ];
-		inArray[inJ] = cache;
-	};
-})();
-
-}
-
-if(!dojo._hasResource["dojox.grid._Scroller"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid._Scroller"] = true;
-dojo.provide("dojox.grid._Scroller");
-
-(function(){
-	var indexInParent = function(inNode){
-		var i=0, n, p=inNode.parentNode;
-		while((n = p.childNodes[i++])){
-			if(n == inNode){
-				return i - 1;
-			}
-		}
-		return -1;
-	};
-	
-	var cleanNode = function(inNode){
-		if(!inNode){
-			return;
-		}
-		var filter = function(inW){
-			return inW.domNode && dojo.isDescendant(inW.domNode, inNode, true);
-		};
-		var ws = dijit.registry.filter(filter);
-		for(var i=0, w; (w=ws[i]); i++){
-			w.destroy();
-		}
-		delete ws;
-	};
-
-	var getTagName = function(inNodeOrId){
-		var node = dojo.byId(inNodeOrId);
-		return (node && node.tagName ? node.tagName.toLowerCase() : '');
-	};
-	
-	var nodeKids = function(inNode, inTag){
-		var result = [];
-		var i=0, n;
-		while((n = inNode.childNodes[i])){
-			i++;
-			if(getTagName(n) == inTag){
-				result.push(n);
-			}
-		}
-		return result;
-	};
-	
-	var divkids = function(inNode){
-		return nodeKids(inNode, 'div');
-	};
-
-	dojo.declare("dojox.grid._Scroller", null, {
-		constructor: function(inContentNodes){
-			this.setContentNodes(inContentNodes);
-			this.pageHeights = [];
-			this.pageNodes = [];
-			this.stack = [];
-		},
-		// specified
-		rowCount: 0, // total number of rows to manage
-		defaultRowHeight: 32, // default height of a row
-		keepRows: 100, // maximum number of rows that should exist at one time
-		contentNode: null, // node to contain pages
-		scrollboxNode: null, // node that controls scrolling
-		// calculated
-		defaultPageHeight: 0, // default height of a page
-		keepPages: 10, // maximum number of pages that should exists at one time
-		pageCount: 0,
-		windowHeight: 0,
-		firstVisibleRow: 0,
-		lastVisibleRow: 0,
-		averageRowHeight: 0, // the average height of a row
-		// private
-		page: 0,
-		pageTop: 0,
-		// init
-		init: function(inRowCount, inKeepRows, inRowsPerPage){
-			switch(arguments.length){
-				case 3: this.rowsPerPage = inRowsPerPage;
-				case 2: this.keepRows = inKeepRows;
-				case 1: this.rowCount = inRowCount;
-				default: break;
-			}
-			this.defaultPageHeight = this.defaultRowHeight * this.rowsPerPage;
-			this.pageCount = this._getPageCount(this.rowCount, this.rowsPerPage);
-			this.setKeepInfo(this.keepRows);
-			this.invalidate();
-			if(this.scrollboxNode){
-				this.scrollboxNode.scrollTop = 0;
-				this.scroll(0);
-				this.scrollboxNode.onscroll = dojo.hitch(this, 'onscroll');
-			}
-		},
-		_getPageCount: function(rowCount, rowsPerPage){
-			return rowCount ? (Math.ceil(rowCount / rowsPerPage) || 1) : 0;
-		},
-		destroy: function(){
-			this.invalidateNodes();
-			delete this.contentNodes;
-			delete this.contentNode;
-			delete this.scrollboxNode;
-		},
-		setKeepInfo: function(inKeepRows){
-			this.keepRows = inKeepRows;
-			this.keepPages = !this.keepRows ? this.keepPages : Math.max(Math.ceil(this.keepRows / this.rowsPerPage), 2);
-		},
-		// nodes
-		setContentNodes: function(inNodes){
-			this.contentNodes = inNodes;
-			this.colCount = (this.contentNodes ? this.contentNodes.length : 0);
-			this.pageNodes = [];
-			for(var i=0; i<this.colCount; i++){
-				this.pageNodes[i] = [];
-			}
-		},
-		getDefaultNodes: function(){
-			return this.pageNodes[0] || [];
-		},
-		// updating
-		invalidate: function(){
-			this._invalidating = true;
-			this.invalidateNodes();
-			this.pageHeights = [];
-			this.height = (this.pageCount ? (this.pageCount - 1)* this.defaultPageHeight + this.calcLastPageHeight() : 0);
-			this.resize();
-			this._invalidating = false;
-		},
-		updateRowCount: function(inRowCount){
-			this.invalidateNodes();
-			this.rowCount = inRowCount;
-			// update page count, adjust document height
-			var oldPageCount = this.pageCount;
-			if(oldPageCount === 0){
-				//We want to have at least 1px in height to keep scroller.  Otherwise with an
-				//empty grid you can't scroll to see the header.
-				this.height = 1;
-			}
-			this.pageCount = this._getPageCount(this.rowCount, this.rowsPerPage);
-			if(this.pageCount < oldPageCount){
-				for(var i=oldPageCount-1; i>=this.pageCount; i--){
-					this.height -= this.getPageHeight(i);
-					delete this.pageHeights[i];
-				}
-			}else if(this.pageCount > oldPageCount){
-				this.height += this.defaultPageHeight * (this.pageCount - oldPageCount - 1) + this.calcLastPageHeight();
-			}
-			this.resize();
-		},
-		// implementation for page manager
-		pageExists: function(inPageIndex){
-			return Boolean(this.getDefaultPageNode(inPageIndex));
-		},
-		measurePage: function(inPageIndex){
-			if(this.grid.rowHeight){
-				var height = this.grid.rowHeight + 1;
-				return ((inPageIndex + 1) * this.rowsPerPage > this.rowCount ?
-					this.rowCount - inPageIndex * this.rowsPerPage :
-					this.rowsPerPage) * height;
-					 
-			}
-			var n = this.getDefaultPageNode(inPageIndex);
-			return (n && n.innerHTML) ? n.offsetHeight : undefined;
-		},
-		positionPage: function(inPageIndex, inPos){
-			for(var i=0; i<this.colCount; i++){
-				this.pageNodes[i][inPageIndex].style.top = inPos + 'px';
-			}
-		},
-		repositionPages: function(inPageIndex){
-			var nodes = this.getDefaultNodes();
-			var last = 0;
-
-			for(var i=0; i<this.stack.length; i++){
-				last = Math.max(this.stack[i], last);
-			}
-			//
-			var n = nodes[inPageIndex];
-			var y = (n ? this.getPageNodePosition(n) + this.getPageHeight(inPageIndex) : 0);
-			for(var p=inPageIndex+1; p<=last; p++){
-				n = nodes[p];
-				if(n){
-					if(this.getPageNodePosition(n) == y){
-						return;
-					}
-					this.positionPage(p, y);
-				}
-				y += this.getPageHeight(p);
-			}
-		},
-		installPage: function(inPageIndex){
-			for(var i=0; i<this.colCount; i++){
-				this.contentNodes[i].appendChild(this.pageNodes[i][inPageIndex]);
-			}
-		},
-		preparePage: function(inPageIndex, inReuseNode){
-			var p = (inReuseNode ? this.popPage() : null);
-			for(var i=0; i<this.colCount; i++){
-				var nodes = this.pageNodes[i];
-				var new_p = (p === null ? this.createPageNode() : this.invalidatePageNode(p, nodes));
-				new_p.pageIndex = inPageIndex;
-				nodes[inPageIndex] = new_p;
-			}
-		},
-		// rendering implementation
-		renderPage: function(inPageIndex){
-			var nodes = [];
-			var i, j;
-			for(i=0; i<this.colCount; i++){
-				nodes[i] = this.pageNodes[i][inPageIndex];
-			}
-			for(i=0, j=inPageIndex*this.rowsPerPage; (i<this.rowsPerPage)&&(j<this.rowCount); i++, j++){
-				this.renderRow(j, nodes);
-			}
-		},
-		removePage: function(inPageIndex){
-			for(var i=0, j=inPageIndex*this.rowsPerPage; i<this.rowsPerPage; i++, j++){
-				this.removeRow(j);
-			}
-		},
-		destroyPage: function(inPageIndex){
-			for(var i=0; i<this.colCount; i++){
-				var n = this.invalidatePageNode(inPageIndex, this.pageNodes[i]);
-				if(n){
-					dojo.destroy(n);
-				}
-			}
-		},
-		pacify: function(inShouldPacify){
-		},
-		// pacification
-		pacifying: false,
-		pacifyTicks: 200,
-		setPacifying: function(inPacifying){
-			if(this.pacifying != inPacifying){
-				this.pacifying = inPacifying;
-				this.pacify(this.pacifying);
-			}
-		},
-		startPacify: function(){
-			this.startPacifyTicks = new Date().getTime();
-		},
-		doPacify: function(){
-			var result = (new Date().getTime() - this.startPacifyTicks) > this.pacifyTicks;
-			this.setPacifying(true);
-			this.startPacify();
-			return result;
-		},
-		endPacify: function(){
-			this.setPacifying(false);
-		},
-		// default sizing implementation
-		resize: function(){
-			if(this.scrollboxNode){
-				this.windowHeight = this.scrollboxNode.clientHeight;
-			}
-			for(var i=0; i<this.colCount; i++){
-				//We want to have 1px in height min to keep scroller.  Otherwise can't scroll
-				//and see header in empty grid.
-				dojox.grid.util.setStyleHeightPx(this.contentNodes[i], Math.max(1,this.height));
-			}
-			
-			// Calculate the average row height and update the defaults (row and page).
-			var needPage = (!this._invalidating);
-			if(!needPage){
-				var ah = this.grid.attr("autoHeight");
-				if(typeof ah == "number" && ah <= Math.min(this.rowsPerPage, this.rowCount)){
-					needPage = true;
-				}
-			}
-			if(needPage){
-				this.needPage(this.page, this.pageTop);
-			}
-			var rowsOnPage = (this.page < this.pageCount - 1) ? this.rowsPerPage : ((this.rowCount % this.rowsPerPage) || this.rowsPerPage);
-			var pageHeight = this.getPageHeight(this.page);
-			this.averageRowHeight = (pageHeight > 0 && rowsOnPage > 0) ? (pageHeight / rowsOnPage) : 0;
-		},
-		calcLastPageHeight: function(){
-			if(!this.pageCount){
-				return 0;
-			}
-			var lastPage = this.pageCount - 1;
-			var lastPageHeight = ((this.rowCount % this.rowsPerPage)||(this.rowsPerPage)) * this.defaultRowHeight;
-			this.pageHeights[lastPage] = lastPageHeight;
-			return lastPageHeight;
-		},
-		updateContentHeight: function(inDh){
-			this.height += inDh;
-			this.resize();
-		},
-		updatePageHeight: function(inPageIndex, fromBuild){
-			if(this.pageExists(inPageIndex)){
-				var oh = this.getPageHeight(inPageIndex);
-				var h = (this.measurePage(inPageIndex));
-				if(h === undefined){
-					h = oh;
-				}
-				this.pageHeights[inPageIndex] = h;
-				if(oh != h){
-					this.updateContentHeight(h - oh);
-					var ah = this.grid.attr("autoHeight");
-					if((typeof ah == "number" && ah > this.rowCount)||(ah === true && !fromBuild)){
-						this.grid.sizeChange();
-					}else{
-						this.repositionPages(inPageIndex);
-					}
-				}
-				return h;
-			}
-			return 0;
-		},
-		rowHeightChanged: function(inRowIndex){
-			this.updatePageHeight(Math.floor(inRowIndex / this.rowsPerPage), false);
-		},
-		// scroller core
-		invalidateNodes: function(){
-			while(this.stack.length){
-				this.destroyPage(this.popPage());
-			}
-		},
-		createPageNode: function(){
-			var p = document.createElement('div');
-			dojo.attr(p,"role","presentation");
-			p.style.position = 'absolute';
-			//p.style.width = '100%';
-			p.style[dojo._isBodyLtr() ? "left" : "right"] = '0';
-			return p;
-		},
-		getPageHeight: function(inPageIndex){
-			var ph = this.pageHeights[inPageIndex];
-			return (ph !== undefined ? ph : this.defaultPageHeight);
-		},
-		// FIXME: this is not a stack, it's a FIFO list
-		pushPage: function(inPageIndex){
-			return this.stack.push(inPageIndex);
-		},
-		popPage: function(){
-			return this.stack.shift();
-		},
-		findPage: function(inTop){
-			var i = 0, h = 0;
-			for(var ph = 0; i<this.pageCount; i++, h += ph){
-				ph = this.getPageHeight(i);
-				if(h + ph >= inTop){
-					break;
-				}
-			}
-			this.page = i;
-			this.pageTop = h;
-		},
-		buildPage: function(inPageIndex, inReuseNode, inPos){
-			this.preparePage(inPageIndex, inReuseNode);
-			this.positionPage(inPageIndex, inPos);
-			// order of operations is key below
-			this.installPage(inPageIndex);
-			this.renderPage(inPageIndex);
-			// order of operations is key above
-			this.pushPage(inPageIndex);
-		},
-		needPage: function(inPageIndex, inPos){
-			var h = this.getPageHeight(inPageIndex), oh = h;
-			if(!this.pageExists(inPageIndex)){
-				this.buildPage(inPageIndex, this.keepPages&&(this.stack.length >= this.keepPages), inPos);
-				h = this.updatePageHeight(inPageIndex, true);
-			}else{
-				this.positionPage(inPageIndex, inPos);
-			}
-			return h;
-		},
-		onscroll: function(){
-			this.scroll(this.scrollboxNode.scrollTop);
-		},
-		scroll: function(inTop){
-			this.grid.scrollTop = inTop;
-			if(this.colCount){
-				this.startPacify();
-				this.findPage(inTop);
-				var h = this.height;
-				var b = this.getScrollBottom(inTop);
-				for(var p=this.page, y=this.pageTop; (p<this.pageCount)&&((b<0)||(y<b)); p++){
-					y += this.needPage(p, y);
-				}
-				this.firstVisibleRow = this.getFirstVisibleRow(this.page, this.pageTop, inTop);
-				this.lastVisibleRow = this.getLastVisibleRow(p - 1, y, b);
-				// indicates some page size has been updated
-				if(h != this.height){
-					this.repositionPages(p-1);
-				}
-				this.endPacify();
-			}
-		},
-		getScrollBottom: function(inTop){
-			return (this.windowHeight >= 0 ? inTop + this.windowHeight : -1);
-		},
-		// events
-		processNodeEvent: function(e, inNode){
-			var t = e.target;
-			while(t && (t != inNode) && t.parentNode && (t.parentNode.parentNode != inNode)){
-				t = t.parentNode;
-			}
-			if(!t || !t.parentNode || (t.parentNode.parentNode != inNode)){
-				return false;
-			}
-			var page = t.parentNode;
-			e.topRowIndex = page.pageIndex * this.rowsPerPage;
-			e.rowIndex = e.topRowIndex + indexInParent(t);
-			e.rowTarget = t;
-			return true;
-		},
-		processEvent: function(e){
-			return this.processNodeEvent(e, this.contentNode);
-		},
-		// virtual rendering interface
-		renderRow: function(inRowIndex, inPageNode){
-		},
-		removeRow: function(inRowIndex){
-		},
-		// page node operations
-		getDefaultPageNode: function(inPageIndex){
-			return this.getDefaultNodes()[inPageIndex];
-		},
-		positionPageNode: function(inNode, inPos){
-		},
-		getPageNodePosition: function(inNode){
-			return inNode.offsetTop;
-		},
-		invalidatePageNode: function(inPageIndex, inNodes){
-			var p = inNodes[inPageIndex];
-			if(p){
-				delete inNodes[inPageIndex];
-				this.removePage(inPageIndex, p);
-				cleanNode(p);
-				p.innerHTML = '';
-			}
-			return p;
-		},
-		// scroll control
-		getPageRow: function(inPage){
-			return inPage * this.rowsPerPage;
-		},
-		getLastPageRow: function(inPage){
-			return Math.min(this.rowCount, this.getPageRow(inPage + 1)) - 1;
-		},
-		getFirstVisibleRow: function(inPage, inPageTop, inScrollTop){
-			if(!this.pageExists(inPage)){
-				return 0;
-			}
-			var row = this.getPageRow(inPage);
-			var nodes = this.getDefaultNodes();
-			var rows = divkids(nodes[inPage]);
-			for(var i=0,l=rows.length; i<l && inPageTop<inScrollTop; i++, row++){
-				inPageTop += rows[i].offsetHeight;
-			}
-			return (row ? row - 1 : row);
-		},
-		getLastVisibleRow: function(inPage, inBottom, inScrollBottom){
-			if(!this.pageExists(inPage)){
-				return 0;
-			}
-			var nodes = this.getDefaultNodes();
-			var row = this.getLastPageRow(inPage);
-			var rows = divkids(nodes[inPage]);
-			for(var i=rows.length-1; i>=0 && inBottom>inScrollBottom; i--, row--){
-				inBottom -= rows[i].offsetHeight;
-			}
-			return row + 1;
-		},
-		findTopRow: function(inScrollTop){
-			var nodes = this.getDefaultNodes();
-			var rows = divkids(nodes[this.page]);
-			for(var i=0,l=rows.length,t=this.pageTop,h; i<l; i++){
-				h = rows[i].offsetHeight;
-				t += h;
-				if(t >= inScrollTop){
-					this.offset = h - (t - inScrollTop);
-					return i + this.page * this.rowsPerPage;
-				}
-			}
-			return -1;
-		},
-		findScrollTop: function(inRow){
-			var rowPage = Math.floor(inRow / this.rowsPerPage);
-			var t = 0;
-			var i, l;
-			for(i=0; i<rowPage; i++){
-				t += this.getPageHeight(i);
-			}
-			this.pageTop = t;
-			this.needPage(rowPage, this.pageTop);
-
-			var nodes = this.getDefaultNodes();
-			var rows = divkids(nodes[rowPage]);
-			var r = inRow - this.rowsPerPage * rowPage;
-			for(i=0,l=rows.length; i<l && i<r; i++){
-				t += rows[i].offsetHeight;
-			}
-			return t;
-		},
-		dummy: 0
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.grid.cells._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid.cells._base"] = true;
-dojo.provide("dojox.grid.cells._base");
-
-
-
-
-dojo.declare("dojox.grid._DeferredTextWidget", dijit._Widget, {
-	deferred: null,
-	_destroyOnRemove: true,
-	postCreate: function(){
-		if(this.deferred){
-			this.deferred.addBoth(dojo.hitch(this, function(text){
-				if(this.domNode){
-					this.domNode.innerHTML = text;
-				}
-			}));
-		}
-	}
-});
-
-(function(){
-	var focusSelectNode = function(inNode){
-		try{
-			dojox.grid.util.fire(inNode, "focus");
-			dojox.grid.util.fire(inNode, "select");
-		}catch(e){// IE sux bad
-		}
-	};
-	
-	var whenIdle = function(/*inContext, inMethod, args ...*/){
-		setTimeout(dojo.hitch.apply(dojo, arguments), 0);
-	};
-
-	var dgc = dojox.grid.cells;
-
-	dojo.declare("dojox.grid.cells._Base", null, {
-		// summary:
-		//	Respresents a grid cell and contains information about column options and methods
-		//	for retrieving cell related information.
-		//	Each column in a grid layout has a cell object and most events and many methods
-		//	provide access to these objects.
-		styles: '',
-		classes: '',
-		editable: false,
-		alwaysEditing: false,
-		formatter: null,
-		defaultValue: '...',
-		value: null,
-		hidden: false,
-		noresize: false,
-		draggable: true,
-		//private
-		_valueProp: "value",
-		_formatPending: false,
-
-		constructor: function(inProps){
-			this._props = inProps || {};
-			dojo.mixin(this, inProps);
-			if(this.draggable === undefined){
-				this.draggable = true;
-			}
-		},
-
-		_defaultFormat: function(inValue, callArgs){
-			var s = this.grid.formatterScope || this;
-			var f = this.formatter;
-			if(f && s && typeof f == "string"){
-				f = this.formatter = s[f];
-			}
-			var v = (inValue != this.defaultValue && f) ? f.apply(s, callArgs) : inValue;
-			if(typeof v == "undefined"){
-				return this.defaultValue;
-			}
-			if(v && v.addBoth){
-				// Check if it's a deferred
-				v = new dojox.grid._DeferredTextWidget({deferred: v},
-									dojo.create("span", {innerHTML: this.defaultValue}));
-			}
-			if(v && v.declaredClass && v.startup){
-				return "<div class='dojoxGridStubNode' linkWidget='" +
-						v.id +
-						"' cellIdx='" +
-						this.index +
-						"'>" +
-						this.defaultValue +
-						"</div>";
-			}
-			return v;
-		},
-		
-		// data source
-		format: function(inRowIndex, inItem){
-			// summary:
-			//	provides the html for a given grid cell.
-			// inRowIndex: int
-			// grid row index
-			// returns: html for a given grid cell
-			var f, i=this.grid.edit.info, d=this.get ? this.get(inRowIndex, inItem) : (this.value || this.defaultValue);
-			d = (d && d.replace && this.grid.escapeHTMLInData) ? d.replace(/&/g, '&').replace(/</g, '<') : d;
-			if(this.editable && (this.alwaysEditing || (i.rowIndex==inRowIndex && i.cell==this))){
-				return this.formatEditing(d, inRowIndex);
-			}else{
-				return this._defaultFormat(d, [d, inRowIndex, this]);
-			}
-		},
-		formatEditing: function(inDatum, inRowIndex){
-			// summary:
-			//	formats the cell for editing
-			// inDatum: anything
-			//	cell data to edit
-			// inRowIndex: int
-			//	grid row index
-			// returns: string of html to place in grid cell
-		},
-		// utility
-		getNode: function(inRowIndex){
-			// summary:
-			//	gets the dom node for a given grid cell.
-			// inRowIndex: int
-			// grid row index
-			// returns: dom node for a given grid cell
-			return this.view.getCellNode(inRowIndex, this.index);
-		},
-		getHeaderNode: function(){
-			return this.view.getHeaderCellNode(this.index);
-		},
-		getEditNode: function(inRowIndex){
-			return (this.getNode(inRowIndex) || 0).firstChild || 0;
-		},
-		canResize: function(){
-			var uw = this.unitWidth;
-			return uw && (uw!=='auto');
-		},
-		isFlex: function(){
-			var uw = this.unitWidth;
-			return uw && dojo.isString(uw) && (uw=='auto' || uw.slice(-1)=='%');
-		},
-		// edit support
-		applyEdit: function(inValue, inRowIndex){
-			this.grid.edit.applyCellEdit(inValue, this, inRowIndex);
-		},
-		cancelEdit: function(inRowIndex){
-			this.grid.doCancelEdit(inRowIndex);
-		},
-		_onEditBlur: function(inRowIndex){
-			if(this.grid.edit.isEditCell(inRowIndex, this.index)){
-				//console.log('editor onblur', e);
-				this.grid.edit.apply();
-			}
-		},
-		registerOnBlur: function(inNode, inRowIndex){
-			if(this.commitOnBlur){
-				dojo.connect(inNode, "onblur", function(e){
-					// hack: if editor still thinks this editor is current some ms after it blurs, assume we've focused away from grid
-					setTimeout(dojo.hitch(this, "_onEditBlur", inRowIndex), 250);
-				});
-			}
-		},
-		//protected
-		needFormatNode: function(inDatum, inRowIndex){
-			this._formatPending = true;
-			whenIdle(this, "_formatNode", inDatum, inRowIndex);
-		},
-		cancelFormatNode: function(){
-			this._formatPending = false;
-		},
-		//private
-		_formatNode: function(inDatum, inRowIndex){
-			if(this._formatPending){
-				this._formatPending = false;
-				// make cell selectable
-				dojo.setSelectable(this.grid.domNode, true);
-				this.formatNode(this.getEditNode(inRowIndex), inDatum, inRowIndex);
-			}
-		},
-		//protected
-		formatNode: function(inNode, inDatum, inRowIndex){
-			// summary:
-			//	format the editing dom node. Use when editor is a widget.
-			// inNode: dom node
-			// dom node for the editor
-			// inDatum: anything
-			//	cell data to edit
-			// inRowIndex: int
-			//	grid row index
-			if(dojo.isIE){
-				// IE sux bad
-				whenIdle(this, "focus", inRowIndex, inNode);
-			}else{
-				this.focus(inRowIndex, inNode);
-			}
-		},
-		dispatchEvent: function(m, e){
-			if(m in this){
-				return this[m](e);
-			}
-		},
-		//public
-		getValue: function(inRowIndex){
-			// summary:
-			//	returns value entered into editor
-			// inRowIndex: int
-			// grid row index
-			// returns:
-			//	value of editor
-			return this.getEditNode(inRowIndex)[this._valueProp];
-		},
-		setValue: function(inRowIndex, inValue){
-			// summary:
-			//	set the value of the grid editor
-			// inRowIndex: int
-			// grid row index
-			// inValue: anything
-			//	value of editor
-			var n = this.getEditNode(inRowIndex);
-			if(n){
-				n[this._valueProp] = inValue;
-			}
-		},
-		focus: function(inRowIndex, inNode){
-			// summary:
-			//	focus the grid editor
-			// inRowIndex: int
-			// grid row index
-			// inNode: dom node
-			//	editor node
-			focusSelectNode(inNode || this.getEditNode(inRowIndex));
-		},
-		save: function(inRowIndex){
-			// summary:
-			//	save editor state
-			// inRowIndex: int
-			// grid row index
-			this.value = this.value || this.getValue(inRowIndex);
-			//console.log("save", this.value, inCell.index, inRowIndex);
-		},
-		restore: function(inRowIndex){
-			// summary:
-			//	restore editor state
-			// inRowIndex: int
-			// grid row index
-			this.setValue(inRowIndex, this.value);
-			//console.log("restore", this.value, inCell.index, inRowIndex);
-		},
-		//protected
-		_finish: function(inRowIndex){
-			// summary:
-			//	called when editing is completed to clean up editor
-			// inRowIndex: int
-			// grid row index
-			dojo.setSelectable(this.grid.domNode, false);
-			this.cancelFormatNode();
-		},
-		//public
-		apply: function(inRowIndex){
-			// summary:
-			//	apply edit from cell editor
-			// inRowIndex: int
-			// grid row index
-			this.applyEdit(this.getValue(inRowIndex), inRowIndex);
-			this._finish(inRowIndex);
-		},
-		cancel: function(inRowIndex){
-			// summary:
-			//	cancel cell edit
-			// inRowIndex: int
-			// grid row index
-			this.cancelEdit(inRowIndex);
-			this._finish(inRowIndex);
-		}
-	});
-	dgc._Base.markupFactory = function(node, cellDef){
-		var d = dojo;
-		var formatter = d.trim(d.attr(node, "formatter")||"");
-		if(formatter){
-			cellDef.formatter = dojo.getObject(formatter)||formatter;
-		}
-		var get = d.trim(d.attr(node, "get")||"");
-		if(get){
-			cellDef.get = dojo.getObject(get);
-		}
-		var getBoolAttr = function(attr, cell, cellAttr){
-			var value = d.trim(d.attr(node, attr)||"");
-			if(value){ cell[cellAttr||attr] = !(value.toLowerCase()=="false"); }
-		};
-		getBoolAttr("sortDesc", cellDef);
-		getBoolAttr("editable", cellDef);
-		getBoolAttr("alwaysEditing", cellDef);
-		getBoolAttr("noresize", cellDef);
-		getBoolAttr("draggable", cellDef);
-
-		var value = d.trim(d.attr(node, "loadingText")||d.attr(node, "defaultValue")||"");
-		if(value){
-			cellDef.defaultValue = value;
-		}
-
-		var getStrAttr = function(attr, cell, cellAttr){
-			var value = d.trim(d.attr(node, attr)||"")||undefined;
-			if(value){ cell[cellAttr||attr] = value; }
-		};
-		getStrAttr("styles", cellDef);
-		getStrAttr("headerStyles", cellDef);
-		getStrAttr("cellStyles", cellDef);
-		getStrAttr("classes", cellDef);
-		getStrAttr("headerClasses", cellDef);
-		getStrAttr("cellClasses", cellDef);
-	};
-
-	dojo.declare("dojox.grid.cells.Cell", dgc._Base, {
-		// summary
-		// grid cell that provides a standard text input box upon editing
-		constructor: function(){
-			this.keyFilter = this.keyFilter;
-		},
-		// keyFilter: RegExp
-		//		optional regex for disallowing keypresses
-		keyFilter: null,
-		formatEditing: function(inDatum, inRowIndex){
-			this.needFormatNode(inDatum, inRowIndex);
-			return '<input class="dojoxGridInput" type="text" value="' + inDatum + '">';
-		},
-		formatNode: function(inNode, inDatum, inRowIndex){
-			this.inherited(arguments);
-			// FIXME: feels too specific for this interface
-			this.registerOnBlur(inNode, inRowIndex);
-		},
-		doKey: function(e){
-			if(this.keyFilter){
-				var key = String.fromCharCode(e.charCode);
-				if(key.search(this.keyFilter) == -1){
-					dojo.stopEvent(e);
-				}
-			}
-		},
-		_finish: function(inRowIndex){
-			this.inherited(arguments);
-			var n = this.getEditNode(inRowIndex);
-			try{
-				dojox.grid.util.fire(n, "blur");
-			}catch(e){}
-		}
-	});
-	dgc.Cell.markupFactory = function(node, cellDef){
-		dgc._Base.markupFactory(node, cellDef);
-		var d = dojo;
-		var keyFilter = d.trim(d.attr(node, "keyFilter")||"");
-		if(keyFilter){
-			cellDef.keyFilter = new RegExp(keyFilter);
-		}
-	};
-
-	dojo.declare("dojox.grid.cells.RowIndex", dgc.Cell, {
-		name: 'Row',
-
-		postscript: function(){
-			this.editable = false;
-		},
-		get: function(inRowIndex){
-			return inRowIndex + 1;
-		}
-	});
-	dgc.RowIndex.markupFactory = function(node, cellDef){
-		dgc.Cell.markupFactory(node, cellDef);
-	};
-
-	dojo.declare("dojox.grid.cells.Select", dgc.Cell, {
-		// summary:
-		// grid cell that provides a standard select for editing
-
-		// options: Array
-		// 		text of each item
-		options: null,
-
-		// values: Array
-		//		value for each item
-		values: null,
-
-		// returnIndex: Integer
-		// 		editor returns only the index of the selected option and not the value
-		returnIndex: -1,
-
-		constructor: function(inCell){
-			this.values = this.values || this.options;
-		},
-		formatEditing: function(inDatum, inRowIndex){
-			this.needFormatNode(inDatum, inRowIndex);
-			var h = [ '<select class="dojoxGridSelect">' ];
-			for (var i=0, o, v; ((o=this.options[i]) !== undefined)&&((v=this.values[i]) !== undefined); i++){
-				h.push("<option", (inDatum==v ? ' selected' : ''), ' value="' + v + '"', ">", o, "</option>");
-			}
-			h.push('</select>');
-			return h.join('');
-		},
-		getValue: function(inRowIndex){
-			var n = this.getEditNode(inRowIndex);
-			if(n){
-				var i = n.selectedIndex, o = n.options[i];
-				return this.returnIndex > -1 ? i : o.value || o.innerHTML;
-			}
-		}
-	});
-	dgc.Select.markupFactory = function(node, cell){
-		dgc.Cell.markupFactory(node, cell);
-		var d=dojo;
-		var options = d.trim(d.attr(node, "options")||"");
-		if(options){
-			var o = options.split(',');
-			if(o[0] != options){
-				cell.options = o;
-			}
-		}
-		var values = d.trim(d.attr(node, "values")||"");
-		if(values){
-			var v = values.split(',');
-			if(v[0] != values){
-				cell.values = v;
-			}
-		}
-	};
-
-	dojo.declare("dojox.grid.cells.AlwaysEdit", dgc.Cell, {
-		// summary:
-		// grid cell that is always in an editable state, regardless of grid editing state
-		alwaysEditing: true,
-		_formatNode: function(inDatum, inRowIndex){
-			this.formatNode(this.getEditNode(inRowIndex), inDatum, inRowIndex);
-		},
-		applyStaticValue: function(inRowIndex){
-			var e = this.grid.edit;
-			e.applyCellEdit(this.getValue(inRowIndex), this, inRowIndex);
-			e.start(this, inRowIndex, true);
-		}
-	});
-	dgc.AlwaysEdit.markupFactory = function(node, cell){
-		dgc.Cell.markupFactory(node, cell);
-	};
-
-	dojo.declare("dojox.grid.cells.Bool", dgc.AlwaysEdit, {
-		// summary:
-		// grid cell that provides a standard checkbox that is always on for editing
-		_valueProp: "checked",
-		formatEditing: function(inDatum, inRowIndex){
-			return '<input class="dojoxGridInput" type="checkbox"' + (inDatum ? ' checked="checked"' : '') + ' style="width: auto" />';
-		},
-		doclick: function(e){
-			if(e.target.tagName == 'INPUT'){
-				this.applyStaticValue(e.rowIndex);
-			}
-		}
-	});
-	dgc.Bool.markupFactory = function(node, cell){
-		dgc.AlwaysEdit.markupFactory(node, cell);
-	};
-})();
-
-}
-
-if(!dojo._hasResource["dojox.grid.cells"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid.cells"] = true;
-dojo.provide("dojox.grid.cells");
-
-
-}
-
-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.getCopyKeyState = dojo.isCopyKeyPressed;
-
-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
-};
-
-}
-
-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)
-
-	// TODO: remove this when getViewport() moved to dojo core, see #7028
-
-	// 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.position(n, true);
-				//console.log(b.l, b.t, t.x, t.y, n.scrollLeft, n.scrollTop);
-				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.position()
-					// 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;
-					}
-				}
-				//console.log("ry =", ry, "b.h =", b.h, "h =", h);
-				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.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.__MoveableArgs", [], {
-	// handle: Node||String
-	//		A node (or node's id), which is used as a mouse handle.
-	//		If omitted, the node itself is used as a handle.
-	handle: null,
-
-	// delay: Number
-	//		delay move by this number of pixels
-	delay: 0,
-
-	// skip: Boolean
-	//		skip move of form elements
-	skip: false,
-
-	// mover: Object
-	//		a constructor of custom Mover
-	mover: dojo.dnd.Mover
-});
-=====*/
-
-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: dojo.dnd.__MoveableArgs?
-		//		optional parameters
-		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["dojox.grid._Builder"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid._Builder"] = true;
-dojo.provide("dojox.grid._Builder");
-
-
-
-
-(function(){
-	var dg = dojox.grid;
-
-	var getTdIndex = function(td){
-		return td.cellIndex >=0 ? td.cellIndex : dojo.indexOf(td.parentNode.cells, td);
-	};
-	
-	var getTrIndex = function(tr){
-		return tr.rowIndex >=0 ? tr.rowIndex : dojo.indexOf(tr.parentNode.childNodes, tr);
-	};
-	
-	var getTr = function(rowOwner, index){
-		return rowOwner && ((rowOwner.rows||0)[index] || rowOwner.childNodes[index]);
-	};
-
-	var findTable = function(node){
-		for(var n=node; n && n.tagName!='TABLE'; n=n.parentNode){}
-		return n;
-	};
-	
-	var ascendDom = function(inNode, inWhile){
-		for(var n=inNode; n && inWhile(n); n=n.parentNode){}
-		return n;
-	};
-	
-	var makeNotTagName = function(inTagName){
-		var name = inTagName.toUpperCase();
-		return function(node){ return node.tagName != name; };
-	};
-
-	var rowIndexTag = dojox.grid.util.rowIndexTag;
-	var gridViewTag = dojox.grid.util.gridViewTag;
-
-	// base class for generating markup for the views
-	dg._Builder = dojo.extend(function(view){
-		if(view){
-			this.view = view;
-			this.grid = view.grid;
-		}
-	},{
-		view: null,
-		// boilerplate HTML
-		_table: '<table class="dojoxGridRowTable" border="0" cellspacing="0" cellpadding="0" role="presentation"',
-
-		// Returns the table variable as an array - and with the view width, if specified
-		getTableArray: function(){
-			var html = [this._table];
-			if(this.view.viewWidth){
-				html.push([' style="width:', this.view.viewWidth, ';"'].join(''));
-			}
-			html.push('>');
-			return html;
-		},
-		
-		// generate starting tags for a cell
-		generateCellMarkup: function(inCell, inMoreStyles, inMoreClasses, isHeader){
-			var result = [], html;
-			if(isHeader){
-				var sortInfo = inCell.index != inCell.grid.getSortIndex() ? "" : inCell.grid.sortInfo > 0 ? 'aria-sort="ascending"' : 'aria-sort="descending"';
-				if (!inCell.id){
-					inCell.id = this.grid.id + "Hdr" + inCell.index;
-				}
-				// column headers are not editable, mark as aria-readonly=true
-				html = ['<th tabIndex="-1" aria-readonly="true" role="columnheader"', sortInfo, 'id="', inCell.id, '"'];
-			}else{
-				// cells inherit grid aria-readonly property; default value for aria-readonly is false(grid is editable)
-				// if grid is editable (had any editable cells), mark non editable cells as aria-readonly=true
-				// if no editable cells, grid's aria-readonly value will have been set to true and cells will inherit
-				var editInfo = this.grid.editable && !inCell.editable ? 'aria-readonly="true"' : "";
-				html = ['<td tabIndex="-1" role="gridcell"', editInfo];
-			}
-			if(inCell.colSpan){
-				html.push(' colspan="', inCell.colSpan, '"');
-			}
-			if(inCell.rowSpan){
-				html.push(' rowspan="', inCell.rowSpan, '"');
-			}
-			html.push(' class="dojoxGridCell ');
-			if(inCell.classes){
-				html.push(inCell.classes, ' ');
-			}
-			if(inMoreClasses){
-				html.push(inMoreClasses, ' ');
-			}
-			// result[0] => td opener, style
-			result.push(html.join(''));
-			// SLOT: result[1] => td classes 
-			result.push('');
-			html = ['" idx="', inCell.index, '" style="'];
-			if(inMoreStyles && inMoreStyles[inMoreStyles.length-1] != ';'){
-				inMoreStyles += ';';
-			}
-			html.push(inCell.styles, inMoreStyles||'', inCell.hidden?'display:none;':'');
-			if(inCell.unitWidth){
-				html.push('width:', inCell.unitWidth, ';');
-			}
-			// result[2] => markup
-			result.push(html.join(''));
-			// SLOT: result[3] => td style 
-			result.push('');
-			html = [ '"' ];
-			if(inCell.attrs){
-				html.push(" ", inCell.attrs);
-			}
-			html.push('>');
-			// result[4] => td postfix
-			result.push(html.join(''));
-			// SLOT: result[5] => content
-			result.push('');
-			// result[6] => td closes
-			result.push(isHeader?'</th>':'</td>');
-			return result; // Array
-		},
-
-		// cell finding
-		isCellNode: function(inNode){
-			return Boolean(inNode && inNode!=dojo.doc && dojo.attr(inNode, "idx"));
-		},
-		
-		getCellNodeIndex: function(inCellNode){
-			return inCellNode ? Number(dojo.attr(inCellNode, "idx")) : -1;
-		},
-		
-		getCellNode: function(inRowNode, inCellIndex){
-			for(var i=0, row; (row=getTr(inRowNode.firstChild, i)); i++){
-				for(var j=0, cell; (cell=row.cells[j]); j++){
-					if(this.getCellNodeIndex(cell) == inCellIndex){
-						return cell;
-					}
-				}
-			}
-			return null;
-		},
-		
-		findCellTarget: function(inSourceNode, inTopNode){
-			var n = inSourceNode;
-			while(n && (!this.isCellNode(n) || (n.offsetParent && gridViewTag in n.offsetParent.parentNode && n.offsetParent.parentNode[gridViewTag] != this.view.id)) && (n!=inTopNode)){
-				n = n.parentNode;
-			}
-			return n!=inTopNode ? n : null;
-		},
-		
-		// event decoration
-		baseDecorateEvent: function(e){
-			e.dispatch = 'do' + e.type;
-			e.grid = this.grid;
-			e.sourceView = this.view;
-			e.cellNode = this.findCellTarget(e.target, e.rowNode);
-			e.cellIndex = this.getCellNodeIndex(e.cellNode);
-			e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
-		},
-		
-		// event dispatch
-		findTarget: function(inSource, inTag){
-			var n = inSource;
-			while(n && (n!=this.domNode) && (!(inTag in n) || (gridViewTag in n && n[gridViewTag] != this.view.id))){
-				n = n.parentNode;
-			}
-			return (n != this.domNode) ? n : null; 
-		},
-
-		findRowTarget: function(inSource){
-			return this.findTarget(inSource, rowIndexTag);
-		},
-
-		isIntraNodeEvent: function(e){
-			try{
-				return (e.cellNode && e.relatedTarget && dojo.isDescendant(e.relatedTarget, e.cellNode));
-			}catch(x){
-				// e.relatedTarget has permission problem in FF if it's an input: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
-				return false;
-			}
-		},
-
-		isIntraRowEvent: function(e){
-			try{
-				var row = e.relatedTarget && this.findRowTarget(e.relatedTarget);
-				return !row && (e.rowIndex==-1) || row && (e.rowIndex==row.gridRowIndex);			
-			}catch(x){
-				// e.relatedTarget on INPUT has permission problem in FF: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
-				return false;
-			}
-		},
-
-		dispatchEvent: function(e){
-			if(e.dispatch in this){
-				return this[e.dispatch](e);
-			}
-			return false;
-		},
-
-		// dispatched event handlers
-		domouseover: function(e){
-			if(e.cellNode && (e.cellNode!=this.lastOverCellNode)){
-				this.lastOverCellNode = e.cellNode;
-				this.grid.onMouseOver(e);
-			}
-			this.grid.onMouseOverRow(e);
-		},
-
-		domouseout: function(e){
-			if(e.cellNode && (e.cellNode==this.lastOverCellNode) && !this.isIntraNodeEvent(e, this.lastOverCellNode)){
-				this.lastOverCellNode = null;
-				this.grid.onMouseOut(e);
-				if(!this.isIntraRowEvent(e)){
-					this.grid.onMouseOutRow(e);
-				}
-			}
-		},
-		
-		domousedown: function(e){
-			if (e.cellNode)
-				this.grid.onMouseDown(e);
-			this.grid.onMouseDownRow(e);
-		}
-	});
-
-	// Produces html for grid data content. Owned by grid and used internally 
-	// for rendering data. Override to implement custom rendering.
-	dg._ContentBuilder = dojo.extend(function(view){
-		dg._Builder.call(this, view);
-	},dg._Builder.prototype,{
-		update: function(){
-			this.prepareHtml();
-		},
-
-		// cache html for rendering data rows
-		prepareHtml: function(){
-			var defaultGet=this.grid.get, cells=this.view.structure.cells;
-			for(var j=0, row; (row=cells[j]); j++){
-				for(var i=0, cell; (cell=row[i]); i++){
-					cell.get = cell.get || (cell.value == undefined) && defaultGet;
-					cell.markup = this.generateCellMarkup(cell, cell.cellStyles, cell.cellClasses, false);
-					if (!this.grid.editable && cell.editable){
-						this.grid.editable = true;
-					}
-				}
-			}
-		},
-
-		// time critical: generate html using cache and data source
-		generateHtml: function(inDataIndex, inRowIndex){
-			var
-				html = this.getTableArray(),
-				v = this.view,
-				cells = v.structure.cells,
-				item = this.grid.getItem(inRowIndex);
-
-			dojox.grid.util.fire(this.view, "onBeforeRow", [inRowIndex, cells]);
-			for(var j=0, row; (row=cells[j]); j++){
-				if(row.hidden || row.header){
-					continue;
-				}
-				html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGridInvisible">');
-				for(var i=0, cell, m, cc, cs; (cell=row[i]); i++){
-					m = cell.markup; cc = cell.customClasses = []; cs = cell.customStyles = [];
-					// content (format can fill in cc and cs as side-effects)
-					m[5] = cell.format(inRowIndex, item);
-					// classes
-					m[1] = cc.join(' ');
-					// styles
-					m[3] = cs.join(';');
-					// in-place concat
-					html.push.apply(html, m);
-				}
-				html.push('</tr>');
-			}
-			html.push('</table>');
-			return html.join(''); // String
-		},
-
-		decorateEvent: function(e){
-			e.rowNode = this.findRowTarget(e.target);
-			if(!e.rowNode){return false;}
-			e.rowIndex = e.rowNode[rowIndexTag];
-			this.baseDecorateEvent(e);
-			e.cell = this.grid.getCell(e.cellIndex);
-			return true; // Boolean
-		}
-	});
-
-	// Produces html for grid header content. Owned by grid and used internally 
-	// for rendering data. Override to implement custom rendering.
-	dg._HeaderBuilder = dojo.extend(function(view){
-		this.moveable = null;
-		dg._Builder.call(this, view);
-	},dg._Builder.prototype,{
-		_skipBogusClicks: false,
-		overResizeWidth: 4,
-		minColWidth: 1,
-		
-		update: function(){
-			if(this.tableMap){
-				this.tableMap.mapRows(this.view.structure.cells);
-			}else{
-				this.tableMap = new dg._TableMap(this.view.structure.cells);
-			}
-		},
-
-		generateHtml: function(inGetValue, inValue){
-			var html = this.getTableArray(), cells = this.view.structure.cells;
-			
-			dojox.grid.util.fire(this.view, "onBeforeRow", [-1, cells]);
-			for(var j=0, row; (row=cells[j]); j++){
-				if(row.hidden){
-					continue;
-				}
-				html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGridInvisible">');
-				for(var i=0, cell, markup; (cell=row[i]); i++){
-					cell.customClasses = [];
-					cell.customStyles = [];
-					if(this.view.simpleStructure){
-						if(cell.draggable){
-							if(cell.headerClasses){
-								if(cell.headerClasses.indexOf('dojoDndItem') == -1){
-									cell.headerClasses += ' dojoDndItem';
-								}
-							}else{
-								cell.headerClasses = 'dojoDndItem';
-							}
-						}
-						if(cell.attrs){
-							if(cell.attrs.indexOf("dndType='gridColumn_") == -1){
-								cell.attrs += " dndType='gridColumn_" + this.grid.id + "'";
-							}
-						}else{
-							cell.attrs = "dndType='gridColumn_" + this.grid.id + "'";
-						}
-					}
-					markup = this.generateCellMarkup(cell, cell.headerStyles, cell.headerClasses, true);
-					// content
-					markup[5] = (inValue != undefined ? inValue : inGetValue(cell));
-					// styles
-					markup[3] = cell.customStyles.join(';');
-					// classes
-					markup[1] = cell.customClasses.join(' '); //(cell.customClasses ? ' ' + cell.customClasses : '');
-					html.push(markup.join(''));
-				}
-				html.push('</tr>');
-			}
-			html.push('</table>');
-			return html.join('');
-		},
-
-		// event helpers
-		getCellX: function(e){
-			var n, x = e.layerX;
-			if(dojo.isMoz){
-				n = ascendDom(e.target, makeNotTagName("th"));
-				x -= (n && n.offsetLeft) || 0;
-				var t = e.sourceView.getScrollbarWidth();
-				if(!dojo._isBodyLtr() && e.sourceView.headerNode.scrollLeft < t)
-					x -= t;
-				//x -= getProp(ascendDom(e.target, mkNotTagName("td")), "offsetLeft") || 0;
-			}
-			n = ascendDom(e.target, function(){
-				if(!n || n == e.cellNode){
-					return false;
-				}
-				// Mozilla 1.8 (FF 1.5) has a bug that makes offsetLeft = -parent border width
-				// when parent has border, overflow: hidden, and is positioned
-				// handle this problem here ... not a general solution!
-				x += (n.offsetLeft < 0 ? 0 : n.offsetLeft);
-				return true;
-			});
-			return x;
-		},
-
-		// event decoration
-		decorateEvent: function(e){
-			this.baseDecorateEvent(e);
-			e.rowIndex = -1;
-			e.cellX = this.getCellX(e);
-			return true;
-		},
-
-		// event handlers
-		// resizing
-		prepareResize: function(e, mod){
-			do{
-				var i = getTdIndex(e.cellNode);
-				e.cellNode = (i ? e.cellNode.parentNode.cells[i+mod] : null);
-				e.cellIndex = (e.cellNode ? this.getCellNodeIndex(e.cellNode) : -1);
-			}while(e.cellNode && e.cellNode.style.display == "none");
-			return Boolean(e.cellNode);
-		},
-
-		canResize: function(e){
-			if(!e.cellNode || e.cellNode.colSpan > 1){
-				return false;
-			}
-			var cell = this.grid.getCell(e.cellIndex); 
-			return !cell.noresize && cell.canResize();
-		},
-
-		overLeftResizeArea: function(e){
-			// We are never over a resize area if we are in the process of moving
-			if(dojo.hasClass(dojo.body(), "dojoDndMove")){
-				return false;
-			}
-			//Bugfix for crazy IE problem (#8807).  IE returns position information for the icon and text arrow divs
-			//as if they were still on the left instead of returning the position they were 'float: right' to.
-			//So, the resize check ends up checking the wrong adjacent cell.  This checks to see if the hover was over 
-			//the image or text nodes, then just ignored them/treat them not in scale range.
-			if(dojo.isIE){
-				var tN = e.target;
-				if(dojo.hasClass(tN, "dojoxGridArrowButtonNode") || 
-					dojo.hasClass(tN, "dojoxGridArrowButtonChar")){
-					return false;
-				}
-			}
-
-			if(dojo._isBodyLtr()){
-				return (e.cellIndex>0) && (e.cellX < this.overResizeWidth) && this.prepareResize(e, -1);
-			}
-			var t = e.cellNode && (e.cellX < this.overResizeWidth);
-			return t;
-		},
-
-		overRightResizeArea: function(e){
-			// We are never over a resize area if we are in the process of moving
-			if(dojo.hasClass(dojo.body(), "dojoDndMove")){
-				return false;
-			}
-			//Bugfix for crazy IE problem (#8807).  IE returns position information for the icon and text arrow divs
-			//as if they were still on the left instead of returning the position they were 'float: right' to.
-			//So, the resize check ends up checking the wrong adjacent cell.  This checks to see if the hover was over 
-			//the image or text nodes, then just ignored them/treat them not in scale range.
-			if(dojo.isIE){
-				var tN = e.target;
-				if(dojo.hasClass(tN, "dojoxGridArrowButtonNode") || 
-					dojo.hasClass(tN, "dojoxGridArrowButtonChar")){
-					return false;
-				}
-			}
-
-			if(dojo._isBodyLtr()){
-				return e.cellNode && (e.cellX >= e.cellNode.offsetWidth - this.overResizeWidth);
-			}
-			return (e.cellIndex>0) && (e.cellX >= e.cellNode.offsetWidth - this.overResizeWidth) && this.prepareResize(e, -1);
-		},
-
-		domousemove: function(e){
-			//console.log(e.cellIndex, e.cellX, e.cellNode.offsetWidth);
-			if(!this.moveable){
-				var c = (this.overRightResizeArea(e) ? 'dojoxGridColResize' : (this.overLeftResizeArea(e) ? 'dojoxGridColResize' : ''));
-				if(c && !this.canResize(e)){
-					c = 'dojoxGridColNoResize';
-				}
-				dojo.toggleClass(e.sourceView.headerNode, "dojoxGridColNoResize", (c == "dojoxGridColNoResize"));
-				dojo.toggleClass(e.sourceView.headerNode, "dojoxGridColResize", (c == "dojoxGridColResize"));
-				if(dojo.isIE){
-					var t = e.sourceView.headerNode.scrollLeft;
-					e.sourceView.headerNode.scrollLeft = t;
-				}
-				if(c){
-					dojo.stopEvent(e);
-				}
-			}
-		},
-
-		domousedown: function(e){
-			if(!this.moveable){
-				if((this.overRightResizeArea(e) || this.overLeftResizeArea(e)) && this.canResize(e)){
-					this.beginColumnResize(e);
-				}else{
-					this.grid.onMouseDown(e);
-					this.grid.onMouseOverRow(e);
-				}
-				//else{
-				//	this.beginMoveColumn(e);
-				//}
-			}
-		},
-
-		doclick: function(e) {
-			if(this._skipBogusClicks){
-				dojo.stopEvent(e);
-				return true;
-			}
-			return false;
-		},
-
-		// column resizing
-		colResizeSetup: function(/*Event Object*/e, /*boolean*/ isMouse ){
-			//Set up the drag object for column resizing
-			// Called with mouse event in case of drag and drop,
-			// Also called from keyboard shift-arrow event when focus is on a header
-			var headContentBox = dojo.contentBox(e.sourceView.headerNode);
-			
-			if(isMouse){  //IE draws line even with no mouse down so separate from keyboard 
-				this.lineDiv = document.createElement('div');
-
-				// NOTE: this is for backwards compatibility with Dojo 1.3
-				var vw = (dojo.position||dojo._abs)(e.sourceView.headerNode, true);
-				var bodyContentBox = dojo.contentBox(e.sourceView.domNode);
-				dojo.style(this.lineDiv, {
-					top: vw.y + "px",
-					left: e.clientX + "px",
-					height: (bodyContentBox.h + headContentBox.h) + "px"
-				});
-				dojo.addClass(this.lineDiv, "dojoxGridResizeColLine");
-				this.lineDiv._origLeft = e.clientX;
-				dojo.body().appendChild(this.lineDiv);
-			}
-			var spanners = [], nodes = this.tableMap.findOverlappingNodes(e.cellNode);
-			for(var i=0, cell; (cell=nodes[i]); i++){
-				spanners.push({ node: cell, index: this.getCellNodeIndex(cell), width: cell.offsetWidth });
-				//console.log("spanner: " + this.getCellNodeIndex(cell));
-			}
-
-			var view = e.sourceView;
-			var adj = dojo._isBodyLtr() ? 1 : -1;
-			var views = e.grid.views.views;
-			var followers = [];
-			for(var j=view.idx+adj, cView; (cView=views[j]); j=j+adj){
-				followers.push({ node: cView.headerNode, left: window.parseInt(cView.headerNode.style.left) });
-			}
-			var table = view.headerContentNode.firstChild;
-			var drag = {
-				scrollLeft: e.sourceView.headerNode.scrollLeft,
-				view: view,
-				node: e.cellNode,
-				index: e.cellIndex,
-				w: dojo.contentBox(e.cellNode).w,
-				vw: headContentBox.w,
-				table: table,
-				tw: dojo.contentBox(table).w,
-				spanners: spanners,
-				followers: followers
-			};
-			return drag;
-		},
-		beginColumnResize: function(e){
-			this.moverDiv = document.createElement("div");
-			dojo.style(this.moverDiv,{position: "absolute", left:0}); // to make DnD work with dir=rtl
-			dojo.body().appendChild(this.moverDiv);
-			dojo.addClass(this.grid.domNode, "dojoxGridColumnResizing");
-			var m = (this.moveable = new dojo.dnd.Moveable(this.moverDiv));
-
-			var drag = this.colResizeSetup(e,true);
-
-			m.onMove = dojo.hitch(this, "doResizeColumn", drag);
-
-			dojo.connect(m, "onMoveStop", dojo.hitch(this, function(){
-				this.endResizeColumn(drag);
-				if(drag.node.releaseCapture){
-					drag.node.releaseCapture();
-				}
-				this.moveable.destroy();
-				delete this.moveable;
-				this.moveable = null;
-				dojo.removeClass(this.grid.domNode, "dojoxGridColumnResizing");
-			}));
-
-			if(e.cellNode.setCapture){
-				e.cellNode.setCapture();
-			}
-			m.onMouseDown(e);
-		},
-
-		doResizeColumn: function(inDrag, mover, leftTop){
-			var changeX = leftTop.l;
-			var data = {
-				deltaX: changeX,
-				w: inDrag.w + changeX,
-				vw: inDrag.vw + changeX,
-				tw: inDrag.tw + changeX
-			};
-			
-			this.dragRecord = {inDrag: inDrag, mover: mover, leftTop:leftTop};
-			
-			if(data.w >= this.minColWidth){
-				if (!mover) { // we are using keyboard do immediate resize
-					this.doResizeNow(inDrag, data);
-				}
-				else{
-					dojo.style(this.lineDiv, "left", (this.lineDiv._origLeft + data.deltaX) + "px");
-				}
-			}
-		},
-
-		endResizeColumn: function(inDrag){
-			if(this.dragRecord){
-				var leftTop = this.dragRecord.leftTop;
-				var changeX = dojo._isBodyLtr() ? leftTop.l : -leftTop.l;
-				// Make sure we are not under our minimum
-				// http://bugs.dojotoolkit.org/ticket/9390
-				changeX += Math.max(inDrag.w + changeX, this.minColWidth) - (inDrag.w + changeX);
-				if(dojo.isWebKit && inDrag.spanners.length){
-					// Webkit needs the pad border extents back in
-					changeX += dojo._getPadBorderExtents(inDrag.spanners[0].node).w;
-				}
-				var data = {
-					deltaX: changeX,
-					w: inDrag.w + changeX,
-					vw: inDrag.vw + changeX,
-					tw: inDrag.tw + changeX
-				};
-				// Only resize the columns when the drag has finished
-				this.doResizeNow(inDrag, data);
-			}
-			
-			dojo.destroy(this.lineDiv);
- 			dojo.destroy(this.moverDiv);
-			dojo.destroy(this.moverDiv);
-			delete this.moverDiv;
-			this._skipBogusClicks = true;
-			inDrag.view.update();
-			this._skipBogusClicks = false;
-			this.grid.onResizeColumn(inDrag.index);
-		},
-		doResizeNow: function(inDrag, data){
-			inDrag.view.convertColPctToFixed();
-			if(inDrag.view.flexCells && !inDrag.view.testFlexCells()){
-				var t = findTable(inDrag.node);
-				if(t){
-					(t.style.width = '');
-				}
-			}
-			var i, s, sw, f, fl;
-			for(i=0; (s=inDrag.spanners[i]); i++){
-				sw = s.width + data.deltaX;
-				s.node.style.width = sw + 'px';
-				inDrag.view.setColWidth(s.index, sw);
-			}
-			for(i=0; (f=inDrag.followers[i]); i++){
-				fl = f.left + data.deltaX;
-				f.node.style.left = fl + 'px';
-			}
-			inDrag.node.style.width = data.w + 'px';
-			inDrag.view.setColWidth(inDrag.index, data.w);
-			inDrag.view.headerNode.style.width = data.vw + 'px';
-			inDrag.view.setColumnsWidth(data.tw);
-			if(!dojo._isBodyLtr()){
-				inDrag.view.headerNode.scrollLeft = inDrag.scrollLeft + data.deltaX;
-			}
-		}
-	});
-
-	// Maps an html table into a structure parsable for information about cell row and col spanning.
-	// Used by HeaderBuilder.
-	dg._TableMap = dojo.extend(function(rows){
-		this.mapRows(rows);
-	},{
-		map: null,
-
-		mapRows: function(inRows){
-			// summary: Map table topography
-
-			//console.log('mapRows');
-			// # of rows
-			var rowCount = inRows.length;
-			if(!rowCount){
-				return;
-			}
-			// map which columns and rows fill which cells
-			this.map = [];
-			var row;
-			for(var k=0; (row=inRows[k]); k++){
-				this.map[k] = [];
-			}
-			for(var j=0; (row=inRows[j]); j++){
-				for(var i=0, x=0, cell, colSpan, rowSpan; (cell=row[i]); i++){
-					while(this.map[j][x]){x++;}
-					this.map[j][x] = { c: i, r: j };
-					rowSpan = cell.rowSpan || 1;
-					colSpan = cell.colSpan || 1;
-					for(var y=0; y<rowSpan; y++){
-						for(var s=0; s<colSpan; s++){
-							this.map[j+y][x+s] = this.map[j][x];
-						}
-					}
-					x += colSpan;
-				}
-			}
-			//this.dumMap();
-		},
-
-		dumpMap: function(){
-			for(var j=0, row, h=''; (row=this.map[j]); j++,h=''){
-				for(var i=0, cell; (cell=row[i]); i++){
-					h += cell.r + ',' + cell.c + '   ';
-				}
-			}
-		},
-
-		getMapCoords: function(inRow, inCol){
-			// summary: Find node's map coords by it's structure coords
-			for(var j=0, row; (row=this.map[j]); j++){
-				for(var i=0, cell; (cell=row[i]); i++){
-					if(cell.c==inCol && cell.r == inRow){
-						return { j: j, i: i };
-					}
-					//else{console.log(inRow, inCol, ' : ', i, j, " : ", cell.r, cell.c); };
-				}
-			}
-			return { j: -1, i: -1 };
-		},
-		
-		getNode: function(inTable, inRow, inCol){
-			// summary: Find a node in inNode's table with the given structure coords
-			var row = inTable && inTable.rows[inRow];
-			return row && row.cells[inCol];
-		},
-		
-		_findOverlappingNodes: function(inTable, inRow, inCol){
-			var nodes = [];
-			var m = this.getMapCoords(inRow, inCol);
-			//console.log("node j: %d, i: %d", m.j, m.i);
-			for(var j=0, row; (row=this.map[j]); j++){
-				if(j == m.j){ continue; }
-				var rw = row[m.i];
-				//console.log("overlaps: r: %d, c: %d", rw.r, rw.c);
-				var n = (rw?this.getNode(inTable, rw.r, rw.c):null);
-				if(n){ nodes.push(n); }
-			}
-			//console.log(nodes);
-			return nodes;
-		},
-		
-		findOverlappingNodes: function(inNode){
-			return this._findOverlappingNodes(findTable(inNode), getTrIndex(inNode.parentNode), getTdIndex(inNode));
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojo.dnd.Container"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.Container"] = true;
-dojo.provide("dojo.dnd.Container");
-
-
-
-
-/*
-	Container states:
-		""		- normal state
-		"Over"	- mouse over a container
-	Container item states:
-		""		- normal state
-		"Over"	- mouse over a container item
-*/
-
-/*=====
-dojo.declare("dojo.dnd.__ContainerArgs", [], {
-	creator: function(){
-		// summary:
-		//		a creator function, which takes a data item, and returns an object like that:
-		//		{node: newNode, data: usedData, type: arrayOfStrings}
-	},
-
-	// skipForm: Boolean
-	//		don't start the drag operation, if clicked on form elements
-	skipForm: false,
-
-	// dropParent: Node||String
-	//		node or node's id to use as the parent node for dropped items
-	//		(must be underneath the 'node' parameter in the DOM)
-	dropParent: null,
-
-	// _skipStartup: Boolean
-	//		skip startup(), which collects children, for deferred initialization
-	//		(this is used in the markup mode)
-	_skipStartup: false
-});
-
-dojo.dnd.Item = function(){
-	// summary:
-	//		Represents (one of) the source node(s) being dragged.
-	//		Contains (at least) the "type" and "data" attributes.
-	// type: String[]
-	//		Type(s) of this item, by default this is ["text"]
-	// data: Object
-	//		Logical representation of the object being dragged.
-	//		If the drag object's type is "text" then data is a String,
-	//		if it's another type then data could be a different Object,
-	//		perhaps a name/value hash.
-	
-	this.type = type;
-	this.data = data;
-}
-=====*/
-
-dojo.declare("dojo.dnd.Container", null, {
-	// summary:
-	//		a Container object, which knows when mouse hovers over it, 
-	//		and over which element it hovers
-	
-	// object attributes (for markup)
-	skipForm: false,
-	
-	/*=====
-	// current: DomNode
-	//		The DOM node the mouse is currently hovered over
-	current: null,
-	
-	// map: Hash<String, dojo.dnd.Item>
-	//		Map from an item's id (which is also the DOMNode's id) to
-	//		the dojo.dnd.Item itself.
-	map: {},
-	=====*/
-	
-	constructor: function(node, params){
-		// summary:
-		//		a constructor of the Container
-		// node: Node
-		//		node or node's id to build the container on
-		// params: dojo.dnd.__ContainerArgs
-		//		a dictionary of parameters
-		this.node = dojo.byId(node);
-		if(!params){ params = {}; }
-		this.creator = params.creator || null;
-		this.skipForm = params.skipForm;
-		this.parent = params.dropParent && dojo.byId(params.dropParent);
-		
-		// class-specific variables
-		this.map = {};
-		this.current = null;
-
-		// states
-		this.containerState = "";
-		dojo.addClass(this.node, "dojoDndContainer");
-		
-		// mark up children
-		if(!(params && params._skipStartup)){
-			this.startup();
-		}
-
-		// set up events
-		this.events = [
-			dojo.connect(this.node, "onmouseover", this, "onMouseOver"),
-			dojo.connect(this.node, "onmouseout",  this, "onMouseOut"),
-			// cancel text selection and text dragging
-			dojo.connect(this.node, "ondragstart",   this, "onSelectStart"),
-			dojo.connect(this.node, "onselectstart", this, "onSelectStart")
-		];
-	},
-	
-	// object attributes (for markup)
-	creator: function(){
-		// summary:
-		//		creator function, dummy at the moment
-	},
-	
-	// abstract access to the map
-	getItem: function(/*String*/ key){
-		// summary:
-		//		returns a data item by its key (id)
-		return this.map[key];	// dojo.dnd.Item
-	},
-	setItem: function(/*String*/ key, /*dojo.dnd.Item*/ data){
-		// summary:
-		//		associates a data item with its key (id)
-		this.map[key] = data;
-	},
-	delItem: function(/*String*/ key){
-		// summary:
-		//		removes a data item from the map by its key (id)
-		delete this.map[key];
-	},
-	forInItems: function(/*Function*/ f, /*Object?*/ o){
-		// summary:
-		//		iterates over a data map skipping members that 
-		//		are present in the empty object (IE and/or 3rd-party libraries).
-		o = o || dojo.global;
-		var m = this.map, e = dojo.dnd._empty;
-		for(var i in m){
-			if(i in e){ continue; }
-			f.call(o, m[i], i, this);
-		}
-		return o;	// Object
-	},
-	clearItems: function(){
-		// summary:
-		//		removes all data items from the map
-		this.map = {};
-	},
-	
-	// methods
-	getAllNodes: function(){
-		// summary:
-		//		returns a list (an array) of all valid child nodes
-		return dojo.query("> .dojoDndItem", this.parent);	// NodeList
-	},
-	sync: function(){
-		// summary:
-		//		sync up the node list with the data map
-		var map = {};
-		this.getAllNodes().forEach(function(node){
-			if(node.id){
-				var item = this.getItem(node.id);
-				if(item){
-					map[node.id] = item;
-					return;
-				}
-			}else{
-				node.id = dojo.dnd.getUniqueId();
-			}
-			var type = node.getAttribute("dndType"),
-				data = node.getAttribute("dndData");
-			map[node.id] = {
-				data: data || node.innerHTML,
-				type: type ? type.split(/\s*,\s*/) : ["text"]
-			};
-		}, this);
-		this.map = map;
-		return this;	// self
-	},
-	insertNodes: function(data, before, anchor){
-		// summary:
-		//		inserts an array of new nodes before/after an anchor node
-		// data: Array
-		//		a list of data items, which should be processed by the creator function
-		// before: Boolean
-		//		insert before the anchor, if true, and after the anchor otherwise
-		// anchor: Node
-		//		the anchor node to be used as a point of insertion
-		if(!this.parent.firstChild){
-			anchor = null;
-		}else if(before){
-			if(!anchor){
-				anchor = this.parent.firstChild;
-			}
-		}else{
-			if(anchor){
-				anchor = anchor.nextSibling;
-			}
-		}
-		if(anchor){
-			for(var i = 0; i < data.length; ++i){
-				var t = this._normalizedCreator(data[i]);
-				this.setItem(t.node.id, {data: t.data, type: t.type});
-				this.parent.insertBefore(t.node, anchor);
-			}
-		}else{
-			for(var i = 0; i < data.length; ++i){
-				var t = this._normalizedCreator(data[i]);
-				this.setItem(t.node.id, {data: t.data, type: t.type});
-				this.parent.appendChild(t.node);
-			}
-		}
-		return this;	// self
-	},
-	destroy: function(){
-		// summary:
-		//		prepares this object to be garbage-collected
-		dojo.forEach(this.events, dojo.disconnect);
-		this.clearItems();
-		this.node = this.parent = this.current = null;
-	},
-
-	// markup methods
-	markupFactory: function(params, node){
-		params._skipStartup = true;
-		return new dojo.dnd.Container(node, params);
-	},
-	startup: function(){
-		// summary:
-		//		collects valid child items and populate the map
-		
-		// set up the real parent node
-		if(!this.parent){
-			// use the standard algorithm, if not assigned
-			this.parent = this.node;
-			if(this.parent.tagName.toLowerCase() == "table"){
-				var c = this.parent.getElementsByTagName("tbody");
-				if(c && c.length){ this.parent = c[0]; }
-			}
-		}
-		this.defaultCreator = dojo.dnd._defaultCreator(this.parent);
-
-		// process specially marked children
-		this.sync();
-	},
-
-	// mouse events
-	onMouseOver: function(e){
-		// summary:
-		//		event processor for onmouseover
-		// e: Event
-		//		mouse event
-		var n = e.relatedTarget;
-		while(n){
-			if(n == this.node){ break; }
-			try{
-				n = n.parentNode;
-			}catch(x){
-				n = null;
-			}
-		}
-		if(!n){
-			this._changeState("Container", "Over");
-			this.onOverEvent();
-		}
-		n = this._getChildByEvent(e);
-		if(this.current == n){ return; }
-		if(this.current){ this._removeItemClass(this.current, "Over"); }
-		if(n){ this._addItemClass(n, "Over"); }
-		this.current = n;
-	},
-	onMouseOut: function(e){
-		// summary:
-		//		event processor for onmouseout
-		// e: Event
-		//		mouse event
-		for(var n = e.relatedTarget; n;){
-			if(n == this.node){ return; }
-			try{
-				n = n.parentNode;
-			}catch(x){
-				n = null;
-			}
-		}
-		if(this.current){
-			this._removeItemClass(this.current, "Over");
-			this.current = null;
-		}
-		this._changeState("Container", "");
-		this.onOutEvent();
-	},
-	onSelectStart: function(e){
-		// summary:
-		//		event processor for onselectevent and ondragevent
-		// e: Event
-		//		mouse event
-		if(!this.skipForm || !dojo.dnd.isFormElement(e)){
-			dojo.stopEvent(e);
-		}
-	},
-	
-	// utilities
-	onOverEvent: function(){
-		// summary:
-		//		this function is called once, when mouse is over our container
-	},
-	onOutEvent: function(){
-		// summary:
-		//		this function is called once, when mouse is out of our container
-	},
-	_changeState: function(type, newState){
-		// summary:
-		//		changes a named state to new state value
-		// type: String
-		//		a name of the state to change
-		// newState: String
-		//		new state
-		var prefix = "dojoDnd" + type;
-		var state  = type.toLowerCase() + "State";
-		//dojo.replaceClass(this.node, prefix + newState, prefix + this[state]);
-		dojo.removeClass(this.node, prefix + this[state]);
-		dojo.addClass(this.node, prefix + newState);
-		this[state] = newState;
-	},
-	_addItemClass: function(node, type){
-		// summary:
-		//		adds a class with prefix "dojoDndItem"
-		// node: Node
-		//		a node
-		// type: String
-		//		a variable suffix for a class name
-		dojo.addClass(node, "dojoDndItem" + type);
-	},
-	_removeItemClass: function(node, type){
-		// summary:
-		//		removes a class with prefix "dojoDndItem"
-		// node: Node
-		//		a node
-		// type: String
-		//		a variable suffix for a class name
-		dojo.removeClass(node, "dojoDndItem" + type);
-	},
-	_getChildByEvent: function(e){
-		// summary:
-		//		gets a child, which is under the mouse at the moment, or null
-		// e: Event
-		//		a mouse event
-		var node = e.target;
-		if(node){
-			for(var parent = node.parentNode; parent; node = parent, parent = node.parentNode){
-				if(parent == this.parent && dojo.hasClass(node, "dojoDndItem")){ return node; }
-			}
-		}
-		return null;
-	},
-	_normalizedCreator: function(/*dojo.dnd.Item*/ item, /*String*/ hint){
-		// summary:
-		//		adds all necessary data to the output of the user-supplied creator function
-		var t = (this.creator || this.defaultCreator).call(this, item, hint);
-		if(!dojo.isArray(t.type)){ t.type = ["text"]; }
-		if(!t.node.id){ t.node.id = dojo.dnd.getUniqueId(); }
-		dojo.addClass(t.node, "dojoDndItem");
-		return t;
-	}
-});
-
-dojo.dnd._createNode = function(tag){
-	// summary:
-	//		returns a function, which creates an element of given tag 
-	//		(SPAN by default) and sets its innerHTML to given text
-	// tag: String
-	//		a tag name or empty for SPAN
-	if(!tag){ return dojo.dnd._createSpan; }
-	return function(text){	// Function
-		return dojo.create(tag, {innerHTML: text});	// Node
-	};
-};
-
-dojo.dnd._createTrTd = function(text){
-	// summary:
-	//		creates a TR/TD structure with given text as an innerHTML of TD
-	// text: String
-	//		a text for TD
-	var tr = dojo.create("tr");
-	dojo.create("td", {innerHTML: text}, tr);
-	return tr;	// Node
-};
-
-dojo.dnd._createSpan = function(text){
-	// summary:
-	//		creates a SPAN element with given text as its innerHTML
-	// text: String
-	//		a text for SPAN
-	return dojo.create("span", {innerHTML: text});	// Node
-};
-
-// dojo.dnd._defaultCreatorNodes: Object
-//		a dictionary that maps container tag names to child tag names
-dojo.dnd._defaultCreatorNodes = {ul: "li", ol: "li", div: "div", p: "div"};
-
-dojo.dnd._defaultCreator = function(node){
-	// summary:
-	//		takes a parent node, and returns an appropriate creator function
-	// node: Node
-	//		a container node
-	var tag = node.tagName.toLowerCase();
-	var c = tag == "tbody" || tag == "thead" ? dojo.dnd._createTrTd :
-			dojo.dnd._createNode(dojo.dnd._defaultCreatorNodes[tag]);
-	return function(item, hint){	// Function
-		var isObj = item && dojo.isObject(item), data, type, n;
-		if(isObj && item.tagName && item.nodeType && item.getAttribute){
-			// process a DOM node
-			data = item.getAttribute("dndData") || item.innerHTML;
-			type = item.getAttribute("dndType");
-			type = type ? type.split(/\s*,\s*/) : ["text"];
-			n = item;	// this node is going to be moved rather than copied
-		}else{
-			// process a DnD item object or a string
-			data = (isObj && item.data) ? item.data : item;
-			type = (isObj && item.type) ? item.type : ["text"];
-			n = (hint == "avatar" ? dojo.dnd._createSpan : c)(String(data));
-		}
-		n.id = dojo.dnd.getUniqueId();
-		return {node: n, data: data, type: type};
-	};
-};
-
-}
-
-if(!dojo._hasResource["dojo.dnd.Selector"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.Selector"] = true;
-dojo.provide("dojo.dnd.Selector");
-
-
-
-
-/*
-	Container item states:
-		""			- an item is not selected
-		"Selected"	- an item is selected
-		"Anchor"	- an item is selected, and is an anchor for a "shift" selection
-*/
-
-/*=====
-dojo.declare("dojo.dnd.__SelectorArgs", [dojo.dnd.__ContainerArgs], {
-	//	singular: Boolean
-	//		allows selection of only one element, if true
-	singular: false,
-
-	//	autoSync: Boolean
-	//		autosynchronizes the source with its list of DnD nodes,
-	autoSync: false
-});
-=====*/
-
-dojo.declare("dojo.dnd.Selector", dojo.dnd.Container, {
-	// summary:
-	//		a Selector object, which knows how to select its children
-	
-	/*=====
-	// selection: Set<String>
-	//		The set of id's that are currently selected, such that this.selection[id] == 1
-	//		if the node w/that id is selected.  Can iterate over selected node's id's like:
-	//	|		for(var id in this.selection)
-	selection: {},
-	=====*/
-
-	constructor: function(node, params){
-		// summary:
-		//		constructor of the Selector
-		// node: Node||String
-		//		node or node's id to build the selector on
-		// params: dojo.dnd.__SelectorArgs?
-		//		a dictionary of parameters
-		if(!params){ params = {}; }
-		this.singular = params.singular;
-		this.autoSync = params.autoSync;
-		// class-specific variables
-		this.selection = {};
-		this.anchor = null;
-		this.simpleSelection = false;
-		// set up events
-		this.events.push(
-			dojo.connect(this.node, "onmousedown", this, "onMouseDown"),
-			dojo.connect(this.node, "onmouseup",   this, "onMouseUp"));
-	},
-	
-	// object attributes (for markup)
-	singular: false,	// is singular property
-	
-	// methods
-	getSelectedNodes: function(){
-		// summary:
-		//		returns a list (an array) of selected nodes
-		var t = new dojo.NodeList();
-		var e = dojo.dnd._empty;
-		for(var i in this.selection){
-			if(i in e){ continue; }
-			t.push(dojo.byId(i));
-		}
-		return t;	// NodeList
-	},
-	selectNone: function(){
-		// summary:
-		//		unselects all items
-		return this._removeSelection()._removeAnchor();	// self
-	},
-	selectAll: function(){
-		// summary:
-		//		selects all items
-		this.forInItems(function(data, id){
-			this._addItemClass(dojo.byId(id), "Selected");
-			this.selection[id] = 1;
-		}, this);
-		return this._removeAnchor();	// self
-	},
-	deleteSelectedNodes: function(){
-		// summary:
-		//		deletes all selected items
-		var e = dojo.dnd._empty;
-		for(var i in this.selection){
-			if(i in e){ continue; }
-			var n = dojo.byId(i);
-			this.delItem(i);
-			dojo.destroy(n);
-		}
-		this.anchor = null;
-		this.selection = {};
-		return this;	// self
-	},
-	forInSelectedItems: function(/*Function*/ f, /*Object?*/ o){
-		// summary:
-		//		iterates over selected items;
-		//		see `dojo.dnd.Container.forInItems()` for details
-		o = o || dojo.global;
-		var s = this.selection, e = dojo.dnd._empty;
-		for(var i in s){
-			if(i in e){ continue; }
-			f.call(o, this.getItem(i), i, this);
-		}
-	},
-	sync: function(){
-		// summary:
-		//		sync up the node list with the data map
-		
-		dojo.dnd.Selector.superclass.sync.call(this);
-		
-		// fix the anchor
-		if(this.anchor){
-			if(!this.getItem(this.anchor.id)){
-				this.anchor = null;
-			}
-		}
-		
-		// fix the selection
-		var t = [], e = dojo.dnd._empty;
-		for(var i in this.selection){
-			if(i in e){ continue; }
-			if(!this.getItem(i)){
-				t.push(i);
-			}
-		}
-		dojo.forEach(t, function(i){
-			delete this.selection[i];
-		}, this);
-		
-		return this;	// self
-	},
-	insertNodes: function(addSelected, data, before, anchor){
-		// summary:
-		//		inserts new data items (see `dojo.dnd.Container.insertNodes()` method for details)
-		// addSelected: Boolean
-		//		all new nodes will be added to selected items, if true, no selection change otherwise
-		// data: Array
-		//		a list of data items, which should be processed by the creator function
-		// before: Boolean
-		//		insert before the anchor, if true, and after the anchor otherwise
-		// anchor: Node
-		//		the anchor node to be used as a point of insertion
-		var oldCreator = this._normalizedCreator;
-		this._normalizedCreator = function(item, hint){
-			var t = oldCreator.call(this, item, hint);
-			if(addSelected){
-				if(!this.anchor){
-					this.anchor = t.node;
-					this._removeItemClass(t.node, "Selected");
-					this._addItemClass(this.anchor, "Anchor");
-				}else if(this.anchor != t.node){
-					this._removeItemClass(t.node, "Anchor");
-					this._addItemClass(t.node, "Selected");
-				}
-				this.selection[t.node.id] = 1;
-			}else{
-				this._removeItemClass(t.node, "Selected");
-				this._removeItemClass(t.node, "Anchor");
-			}
-			return t;
-		};
-		dojo.dnd.Selector.superclass.insertNodes.call(this, data, before, anchor);
-		this._normalizedCreator = oldCreator;
-		return this;	// self
-	},
-	destroy: function(){
-		// summary:
-		//		prepares the object to be garbage-collected
-		dojo.dnd.Selector.superclass.destroy.call(this);
-		this.selection = this.anchor = null;
-	},
-
-	// markup methods
-	markupFactory: function(params, node){
-		params._skipStartup = true;
-		return new dojo.dnd.Selector(node, params);
-	},
-
-	// mouse events
-	onMouseDown: function(e){
-		// summary:
-		//		event processor for onmousedown
-		// e: Event
-		//		mouse event
-		if(this.autoSync){ this.sync(); }
-		if(!this.current){ return; }
-		if(!this.singular && !dojo.isCopyKey(e) && !e.shiftKey && (this.current.id in this.selection)){
-			this.simpleSelection = true;
-			if(e.button === dojo.mouseButtons.LEFT){
-				// accept the left button and stop the event
-				// for IE we don't stop event when multiple buttons are pressed
-				dojo.stopEvent(e);
-			}
-			return;
-		}
-		if(!this.singular && e.shiftKey){
-			if(!dojo.isCopyKey(e)){
-				this._removeSelection();
-			}
-			var c = this.getAllNodes();
-			if(c.length){
-				if(!this.anchor){
-					this.anchor = c[0];
-					this._addItemClass(this.anchor, "Anchor");
-				}
-				this.selection[this.anchor.id] = 1;
-				if(this.anchor != this.current){
-					var i = 0;
-					for(; i < c.length; ++i){
-						var node = c[i];
-						if(node == this.anchor || node == this.current){ break; }
-					}
-					for(++i; i < c.length; ++i){
-						var node = c[i];
-						if(node == this.anchor || node == this.current){ break; }
-						this._addItemClass(node, "Selected");
-						this.selection[node.id] = 1;
-					}
-					this._addItemClass(this.current, "Selected");
-					this.selection[this.current.id] = 1;
-				}
-			}
-		}else{
-			if(this.singular){
-				if(this.anchor == this.current){
-					if(dojo.isCopyKey(e)){
-						this.selectNone();
-					}
-				}else{
-					this.selectNone();
-					this.anchor = this.current;
-					this._addItemClass(this.anchor, "Anchor");
-					this.selection[this.current.id] = 1;
-				}
-			}else{
-				if(dojo.isCopyKey(e)){
-					if(this.anchor == this.current){
-						delete this.selection[this.anchor.id];
-						this._removeAnchor();
-					}else{
-						if(this.current.id in this.selection){
-							this._removeItemClass(this.current, "Selected");
-							delete this.selection[this.current.id];
-						}else{
-							if(this.anchor){
-								this._removeItemClass(this.anchor, "Anchor");
-								this._addItemClass(this.anchor, "Selected");
-							}
-							this.anchor = this.current;
-							this._addItemClass(this.current, "Anchor");
-							this.selection[this.current.id] = 1;
-						}
-					}
-				}else{
-					if(!(this.current.id in this.selection)){
-						this.selectNone();
-						this.anchor = this.current;
-						this._addItemClass(this.current, "Anchor");
-						this.selection[this.current.id] = 1;
-					}
-				}
-			}
-		}
-		dojo.stopEvent(e);
-	},
-	onMouseUp: function(e){
-		// summary:
-		//		event processor for onmouseup
-		// e: Event
-		//		mouse event
-		if(!this.simpleSelection){ return; }
-		this.simpleSelection = false;
-		this.selectNone();
-		if(this.current){
-			this.anchor = this.current;
-			this._addItemClass(this.anchor, "Anchor");
-			this.selection[this.current.id] = 1;
-		}
-	},
-	onMouseMove: function(e){
-		// summary
-		//		event processor for onmousemove
-		// e: Event
-		//		mouse event
-		this.simpleSelection = false;
-	},
-	
-	// utilities
-	onOverEvent: function(){
-		// summary:
-		//		this function is called once, when mouse is over our container
-		this.onmousemoveEvent = dojo.connect(this.node, "onmousemove", this, "onMouseMove");
-	},
-	onOutEvent: function(){
-		// summary:
-		//		this function is called once, when mouse is out of our container
-		dojo.disconnect(this.onmousemoveEvent);
-		delete this.onmousemoveEvent;
-	},
-	_removeSelection: function(){
-		// summary:
-		//		unselects all items
-		var e = dojo.dnd._empty;
-		for(var i in this.selection){
-			if(i in e){ continue; }
-			var node = dojo.byId(i);
-			if(node){ this._removeItemClass(node, "Selected"); }
-		}
-		this.selection = {};
-		return this;	// self
-	},
-	_removeAnchor: function(){
-		if(this.anchor){
-			this._removeItemClass(this.anchor, "Anchor");
-			this.anchor = null;
-		}
-		return this;	// self
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojo.dnd.Avatar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.Avatar"] = true;
-dojo.provide("dojo.dnd.Avatar");
-
-
-
-dojo.declare("dojo.dnd.Avatar", null, {
-	// summary:
-	//		Object that represents transferred DnD items visually
-	// manager: Object
-	//		a DnD manager object
-
-	constructor: function(manager){
-		this.manager = manager;
-		this.construct();
-	},
-
-	// methods
-	construct: function(){
-		// summary:
-		//		constructor function;
-		//		it is separate so it can be (dynamically) overwritten in case of need
-		this.isA11y = dojo.hasClass(dojo.body(),"dijit_a11y");
-		var a = dojo.create("table", {
-				"class": "dojoDndAvatar",
-				style: {
-					position: "absolute",
-					zIndex:   "1999",
-					margin:   "0px"
-				}
-			}),
-			source = this.manager.source, node,
-			b = dojo.create("tbody", null, a),
-			tr = dojo.create("tr", null, b),
-			td = dojo.create("td", null, tr),
-			icon = this.isA11y ? dojo.create("span", {
-						id : "a11yIcon",
-						innerHTML : this.manager.copy ? '+' : "<"
-					}, td) : null,
-			span = dojo.create("span", {
-				innerHTML: source.generateText ? this._generateText() : ""
-			}, td),
-			k = Math.min(5, this.manager.nodes.length), i = 0;
-		// we have to set the opacity on IE only after the node is live
-		dojo.attr(tr, {
-			"class": "dojoDndAvatarHeader",
-			style: {opacity: 0.9}
-		});
-		for(; i < k; ++i){
-			if(source.creator){
-				// create an avatar representation of the node
-				node = source._normalizedCreator(source.getItem(this.manager.nodes[i].id).data, "avatar").node;
-			}else{
-				// or just clone the node and hope it works
-				node = this.manager.nodes[i].cloneNode(true);
-				if(node.tagName.toLowerCase() == "tr"){
-					// insert extra table nodes
-					var table = dojo.create("table"),
-						tbody = dojo.create("tbody", null, table);
-					tbody.appendChild(node);
-					node = table;
-				}
-			}
-			node.id = "";
-			tr = dojo.create("tr", null, b);
-			td = dojo.create("td", null, tr);
-			td.appendChild(node);
-			dojo.attr(tr, {
-				"class": "dojoDndAvatarItem",
-				style: {opacity: (9 - i) / 10}
-			});
-		}
-		this.node = a;
-	},
-	destroy: function(){
-		// summary:
-		//		destructor for the avatar; called to remove all references so it can be garbage-collected
-		dojo.destroy(this.node);
-		this.node = false;
-	},
-	update: function(){
-		// summary:
-		//		updates the avatar to reflect the current DnD state
-		dojo[(this.manager.canDropFlag ? "add" : "remove") + "Class"](this.node, "dojoDndAvatarCanDrop");
-		if (this.isA11y){
-			var icon = dojo.byId("a11yIcon");
-			var text = '+';   // assume canDrop && copy
-			if (this.manager.canDropFlag && !this.manager.copy) {
-				text = '< '; // canDrop && move 
-			}else if (!this.manager.canDropFlag && !this.manager.copy) {
-				text = "o"; //!canDrop && move
-			}else if(!this.manager.canDropFlag){
-				text = 'x';  // !canDrop && copy
-			}
-			icon.innerHTML=text;
-		}
-		// replace text
-		dojo.query(("tr.dojoDndAvatarHeader td span" +(this.isA11y ? " span" : "")), this.node).forEach(
-			function(node){
-				node.innerHTML = this._generateText();
-			}, this);
-	},
-	_generateText: function(){
-		// summary: generates a proper text to reflect copying or moving of items
-		return this.manager.nodes.length.toString();
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojo.dnd.Manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.Manager"] = true;
-dojo.provide("dojo.dnd.Manager");
-
-
-
-
-
-dojo.declare("dojo.dnd.Manager", null, {
-	// summary:
-	//		the manager of DnD operations (usually a singleton)
-	constructor: function(){
-		this.avatar  = null;
-		this.source = null;
-		this.nodes = [];
-		this.copy  = true;
-		this.target = null;
-		this.canDropFlag = false;
-		this.events = [];
-	},
-
-	// avatar's offset from the mouse
-	OFFSET_X: 16,
-	OFFSET_Y: 16,
-	
-	// methods
-	overSource: function(source){
-		// summary:
-		//		called when a source detected a mouse-over condition
-		// source: Object
-		//		the reporter
-		if(this.avatar){
-			this.target = (source && source.targetState != "Disabled") ? source : null;
-			this.canDropFlag = Boolean(this.target);
-			this.avatar.update();
-		}
-		dojo.publish("/dnd/source/over", [source]);
-	},
-	outSource: function(source){
-		// summary:
-		//		called when a source detected a mouse-out condition
-		// source: Object
-		//		the reporter
-		if(this.avatar){
-			if(this.target == source){
-				this.target = null;
-				this.canDropFlag = false;
-				this.avatar.update();
-				dojo.publish("/dnd/source/over", [null]);
-			}
-		}else{
-			dojo.publish("/dnd/source/over", [null]);
-		}
-	},
-	startDrag: function(source, nodes, copy){
-		// summary:
-		//		called to initiate the DnD operation
-		// source: Object
-		//		the source which provides items
-		// nodes: Array
-		//		the list of transferred items
-		// copy: Boolean
-		//		copy items, if true, move items otherwise
-		this.source = source;
-		this.nodes  = nodes;
-		this.copy   = Boolean(copy); // normalizing to true boolean
-		this.avatar = this.makeAvatar();
-		dojo.body().appendChild(this.avatar.node);
-		dojo.publish("/dnd/start", [source, nodes, this.copy]);
-		this.events = [
-			dojo.connect(dojo.doc, "onmousemove", this, "onMouseMove"),
-			dojo.connect(dojo.doc, "onmouseup",   this, "onMouseUp"),
-			dojo.connect(dojo.doc, "onkeydown",   this, "onKeyDown"),
-			dojo.connect(dojo.doc, "onkeyup",     this, "onKeyUp"),
-			// cancel text selection and text dragging
-			dojo.connect(dojo.doc, "ondragstart",   dojo.stopEvent),
-			dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent)
-		];
-		var c = "dojoDnd" + (copy ? "Copy" : "Move");
-		dojo.addClass(dojo.body(), c); 
-	},
-	canDrop: function(flag){
-		// summary:
-		//		called to notify if the current target can accept items
-		var canDropFlag = Boolean(this.target && flag);
-		if(this.canDropFlag != canDropFlag){
-			this.canDropFlag = canDropFlag;
-			this.avatar.update();
-		}
-	},
-	stopDrag: function(){
-		// summary:
-		//		stop the DnD in progress
-		dojo.removeClass(dojo.body(), "dojoDndCopy");
-		dojo.removeClass(dojo.body(), "dojoDndMove");
-		dojo.forEach(this.events, dojo.disconnect);
-		this.events = [];
-		this.avatar.destroy();
-		this.avatar = null;
-		this.source = this.target = null;
-		this.nodes = [];
-	},
-	makeAvatar: function(){
-		// summary:
-		//		makes the avatar; it is separate to be overwritten dynamically, if needed
-		return new dojo.dnd.Avatar(this);
-	},
-	updateAvatar: function(){
-		// summary:
-		//		updates the avatar; it is separate to be overwritten dynamically, if needed
-		this.avatar.update();
-	},
-	
-	// mouse event processors
-	onMouseMove: function(e){
-		// summary:
-		//		event processor for onmousemove
-		// e: Event
-		//		mouse event
-		var a = this.avatar;
-		if(a){
-			dojo.dnd.autoScrollNodes(e);
-			//dojo.dnd.autoScroll(e);
-			var s = a.node.style;
-			s.left = (e.pageX + this.OFFSET_X) + "px";
-			s.top  = (e.pageY + this.OFFSET_Y) + "px";
-			var copy = Boolean(this.source.copyState(dojo.isCopyKey(e)));
-			if(this.copy != copy){ 
-				this._setCopyStatus(copy);
-			}
-		}
-	},
-	onMouseUp: function(e){
-		// summary:
-		//		event processor for onmouseup
-		// e: Event
-		//		mouse event
-		if(this.avatar){
-			if(this.target && this.canDropFlag){
-				var copy = Boolean(this.source.copyState(dojo.isCopyKey(e))),
-				params = [this.source, this.nodes, copy, this.target];
-				dojo.publish("/dnd/drop/before", params);
-				dojo.publish("/dnd/drop", params);
-			}else{
-				dojo.publish("/dnd/cancel");
-			}
-			this.stopDrag();
-		}
-	},
-	
-	// keyboard event processors
-	onKeyDown: function(e){
-		// summary:
-		//		event processor for onkeydown:
-		//		watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag
-		// e: Event
-		//		keyboard event
-		if(this.avatar){
-			switch(e.keyCode){
-				case dojo.keys.CTRL:
-					var copy = Boolean(this.source.copyState(true));
-					if(this.copy != copy){ 
-						this._setCopyStatus(copy);
-					}
-					break;
-				case dojo.keys.ESCAPE:
-					dojo.publish("/dnd/cancel");
-					this.stopDrag();
-					break;
-			}
-		}
-	},
-	onKeyUp: function(e){
-		// summary:
-		//		event processor for onkeyup, watching for CTRL for copy/move status
-		// e: Event
-		//		keyboard event
-		if(this.avatar && e.keyCode == dojo.keys.CTRL){
-			var copy = Boolean(this.source.copyState(false));
-			if(this.copy != copy){ 
-				this._setCopyStatus(copy);
-			}
-		}
-	},
-	
-	// utilities
-	_setCopyStatus: function(copy){
-		// summary:
-		//		changes the copy status
-		// copy: Boolean
-		//		the copy status
-		this.copy = copy;
-		this.source._markDndStatus(this.copy);
-		this.updateAvatar();
-		dojo.removeClass(dojo.body(), "dojoDnd" + (this.copy ? "Move" : "Copy"));
-		dojo.addClass(dojo.body(), "dojoDnd" + (this.copy ? "Copy" : "Move"));
-	}
-});
-
-// dojo.dnd._manager:
-//		The manager singleton variable. Can be overwritten if needed.
-dojo.dnd._manager = null;
-
-dojo.dnd.manager = function(){
-	// summary:
-	//		Returns the current DnD manager.  Creates one if it is not created yet.
-	if(!dojo.dnd._manager){
-		dojo.dnd._manager = new dojo.dnd.Manager();
-	}
-	return dojo.dnd._manager;	// Object
-};
-
-}
-
-if(!dojo._hasResource["dojo.dnd.Source"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.Source"] = true;
-dojo.provide("dojo.dnd.Source");
-
-
-
-
-/*
-	Container property:
-		"Horizontal"- if this is the horizontal container
-	Source states:
-		""			- normal state
-		"Moved"		- this source is being moved
-		"Copied"	- this source is being copied
-	Target states:
-		""			- normal state
-		"Disabled"	- the target cannot accept an avatar
-	Target anchor state:
-		""			- item is not selected
-		"Before"	- insert point is before the anchor
-		"After"		- insert point is after the anchor
-*/
-
-/*=====
-dojo.dnd.__SourceArgs = function(){
-	//	summary:
-	//		a dict of parameters for DnD Source configuration. Note that any
-	//		property on Source elements may be configured, but this is the
-	//		short-list
-	//	isSource: Boolean?
-	//		can be used as a DnD source. Defaults to true.
-	//	accept: Array?
-	//		list of accepted types (text strings) for a target; defaults to
-	//		["text"]
-	//	autoSync: Boolean
-	//		if true refreshes the node list on every operation; false by default
-	//	copyOnly: Boolean?
-	//		copy items, if true, use a state of Ctrl key otherwise,
-	//		see selfCopy and selfAccept for more details
-	//	delay: Number
-	//		the move delay in pixels before detecting a drag; 0 by default
-	//	horizontal: Boolean?
-	//		a horizontal container, if true, vertical otherwise or when omitted
-	//	selfCopy: Boolean?
-	//		copy items by default when dropping on itself,
-	//		false by default, works only if copyOnly is true
-	//	selfAccept: Boolean?
-	//		accept its own items when copyOnly is true,
-	//		true by default, works only if copyOnly is true
-	//	withHandles: Boolean?
-	//		allows dragging only by handles, false by default
-	//  generateText: Boolean?
-	//		generate text node for drag and drop, true by default
-	this.isSource = isSource;
-	this.accept = accept;
-	this.autoSync = autoSync;
-	this.copyOnly = copyOnly;
-	this.delay = delay;
-	this.horizontal = horizontal;
-	this.selfCopy = selfCopy;
-	this.selfAccept = selfAccept;
-	this.withHandles = withHandles;
-	this.generateText = true;
-}
-=====*/
-
-dojo.declare("dojo.dnd.Source", dojo.dnd.Selector, {
-	// summary:
-	//		a Source object, which can be used as a DnD source, or a DnD target
-	
-	// object attributes (for markup)
-	isSource: true,
-	horizontal: false,
-	copyOnly: false,
-	selfCopy: false,
-	selfAccept: true,
-	skipForm: false,
-	withHandles: false,
-	autoSync: false,
-	delay: 0, // pixels
-	accept: ["text"],
-	generateText: true,
-	
-	constructor: function(/*DOMNode|String*/node, /*dojo.dnd.__SourceArgs?*/params){
-		// summary: 
-		//		a constructor of the Source
-		// node:
-		//		node or node's id to build the source on
-		// params: 
-		//		any property of this class may be configured via the params
-		//		object which is mixed-in to the `dojo.dnd.Source` instance
-		dojo.mixin(this, dojo.mixin({}, params));
-		var type = this.accept;
-		if(type.length){
-			this.accept = {};
-			for(var i = 0; i < type.length; ++i){
-				this.accept[type[i]] = 1;
-			}
-		}
-		// class-specific variables
-		this.isDragging = false;
-		this.mouseDown = false;
-		this.targetAnchor = null;
-		this.targetBox = null;
-		this.before = true;
-		this._lastX = 0;
-		this._lastY = 0;
-		// states
-		this.sourceState  = "";
-		if(this.isSource){
-			dojo.addClass(this.node, "dojoDndSource");
-		}
-		this.targetState  = "";
-		if(this.accept){
-			dojo.addClass(this.node, "dojoDndTarget");
-		}
-		if(this.horizontal){
-			dojo.addClass(this.node, "dojoDndHorizontal");
-		}
-		// set up events
-		this.topics = [
-			dojo.subscribe("/dnd/source/over", this, "onDndSourceOver"),
-			dojo.subscribe("/dnd/start",  this, "onDndStart"),
-			dojo.subscribe("/dnd/drop",   this, "onDndDrop"),
-			dojo.subscribe("/dnd/cancel", this, "onDndCancel")
-		];
-	},
-	
-	// methods
-	checkAcceptance: function(source, nodes){
-		// summary:
-		//		checks if the target can accept nodes from this source
-		// source: Object
-		//		the source which provides items
-		// nodes: Array
-		//		the list of transferred items
-		if(this == source){
-			return !this.copyOnly || this.selfAccept;
-		}
-		for(var i = 0; i < nodes.length; ++i){
-			var type = source.getItem(nodes[i].id).type;
-			// type instanceof Array
-			var flag = false;
-			for(var j = 0; j < type.length; ++j){
-				if(type[j] in this.accept){
-					flag = true;
-					break;
-				}
-			}
-			if(!flag){
-				return false;	// Boolean
-			}
-		}
-		return true;	// Boolean
-	},
-	copyState: function(keyPressed, self){
-		// summary:
-		//		Returns true if we need to copy items, false to move.
-		//		It is separated to be overwritten dynamically, if needed.
-		// keyPressed: Boolean
-		//		the "copy" key was pressed
-		// self: Boolean?
-		//		optional flag that means that we are about to drop on itself
-		
-		if(keyPressed){ return true; }
-		if(arguments.length < 2){
-			self = this == dojo.dnd.manager().target;
-		}
-		if(self){
-			if(this.copyOnly){
-				return this.selfCopy;
-			}
-		}else{
-			return this.copyOnly;
-		}
-		return false;	// Boolean
-	},
-	destroy: function(){
-		// summary:
-		//		prepares the object to be garbage-collected
-		dojo.dnd.Source.superclass.destroy.call(this);
-		dojo.forEach(this.topics, dojo.unsubscribe);
-		this.targetAnchor = null;
-	},
-
-	// markup methods
-	markupFactory: function(params, node){
-		params._skipStartup = true;
-		return new dojo.dnd.Source(node, params);
-	},
-
-	// mouse event processors
-	onMouseMove: function(e){
-		// summary:
-		//		event processor for onmousemove
-		// e: Event
-		//		mouse event
-		if(this.isDragging && this.targetState == "Disabled"){ return; }
-		dojo.dnd.Source.superclass.onMouseMove.call(this, e);
-		var m = dojo.dnd.manager();
-		if(this.isDragging){
-			// calculate before/after
-			var before = false;
-			if(this.current){
-				if(!this.targetBox || this.targetAnchor != this.current){
-					this.targetBox = dojo.position(this.current, true);
-				}
-				if(this.horizontal){
-					before = (e.pageX - this.targetBox.x) < (this.targetBox.w / 2);
-				}else{
-					before = (e.pageY - this.targetBox.y) < (this.targetBox.h / 2);
-				}
-			}
-			if(this.current != this.targetAnchor || before != this.before){
-				this._markTargetAnchor(before);
-				m.canDrop(!this.current || m.source != this || !(this.current.id in this.selection));
-			}
-		}else{
-			if(this.mouseDown && this.isSource &&
-					(Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay)){
-				var nodes = this.getSelectedNodes();
-				if(nodes.length){
-					m.startDrag(this, nodes, this.copyState(dojo.isCopyKey(e), true));
-				}
-			}
-		}
-	},
-	onMouseDown: function(e){
-		// summary:
-		//		event processor for onmousedown
-		// e: Event
-		//		mouse event
-		if(!this.mouseDown && this._legalMouseDown(e) && (!this.skipForm || !dojo.dnd.isFormElement(e))){
-			this.mouseDown = true;
-			this._lastX = e.pageX;
-			this._lastY = e.pageY;
-			dojo.dnd.Source.superclass.onMouseDown.call(this, e);
-		}
-	},
-	onMouseUp: function(e){
-		// summary:
-		//		event processor for onmouseup
-		// e: Event
-		//		mouse event
-		if(this.mouseDown){
-			this.mouseDown = false;
-			dojo.dnd.Source.superclass.onMouseUp.call(this, e);
-		}
-	},
-	
-	// topic event processors
-	onDndSourceOver: function(source){
-		// summary:
-		//		topic event processor for /dnd/source/over, called when detected a current source
-		// source: Object
-		//		the source which has the mouse over it
-		if(this != source){
-			this.mouseDown = false;
-			if(this.targetAnchor){
-				this._unmarkTargetAnchor();
-			}
-		}else if(this.isDragging){
-			var m = dojo.dnd.manager();
-			m.canDrop(this.targetState != "Disabled" && (!this.current || m.source != this || !(this.current.id in this.selection)));
-		}
-	},
-	onDndStart: function(source, nodes, copy){
-		// summary:
-		//		topic event processor for /dnd/start, called to initiate the DnD operation
-		// source: Object
-		//		the source which provides items
-		// nodes: Array
-		//		the list of transferred items
-		// copy: Boolean
-		//		copy items, if true, move items otherwise
-		if(this.autoSync){ this.sync(); }
-		if(this.isSource){
-			this._changeState("Source", this == source ? (copy ? "Copied" : "Moved") : "");
-		}
-		var accepted = this.accept && this.checkAcceptance(source, nodes);
-		this._changeState("Target", accepted ? "" : "Disabled");
-		if(this == source){
-			dojo.dnd.manager().overSource(this);
-		}
-		this.isDragging = true;
-	},
-	onDndDrop: function(source, nodes, copy, target){
-		// summary:
-		//		topic event processor for /dnd/drop, called to finish the DnD operation
-		// source: Object
-		//		the source which provides items
-		// nodes: Array
-		//		the list of transferred items
-		// copy: Boolean
-		//		copy items, if true, move items otherwise
-		// target: Object
-		//		the target which accepts items
-		if(this == target){
-			// this one is for us => move nodes!
-			this.onDrop(source, nodes, copy);
-		}
-		this.onDndCancel();
-	},
-	onDndCancel: function(){
-		// summary:
-		//		topic event processor for /dnd/cancel, called to cancel the DnD operation
-		if(this.targetAnchor){
-			this._unmarkTargetAnchor();
-			this.targetAnchor = null;
-		}
-		this.before = true;
-		this.isDragging = false;
-		this.mouseDown = false;
-		this._changeState("Source", "");
-		this._changeState("Target", "");
-	},
-	
-	// local events
-	onDrop: function(source, nodes, copy){
-		// summary:
-		//		called only on the current target, when drop is performed
-		// source: Object
-		//		the source which provides items
-		// nodes: Array
-		//		the list of transferred items
-		// copy: Boolean
-		//		copy items, if true, move items otherwise
-		
-		if(this != source){
-			this.onDropExternal(source, nodes, copy);
-		}else{
-			this.onDropInternal(nodes, copy);
-		}
-	},
-	onDropExternal: function(source, nodes, copy){
-		// summary:
-		//		called only on the current target, when drop is performed
-		//		from an external source
-		// source: Object
-		//		the source which provides items
-		// nodes: Array
-		//		the list of transferred items
-		// copy: Boolean
-		//		copy items, if true, move items otherwise
-		
-		var oldCreator = this._normalizedCreator;
-		// transferring nodes from the source to the target
-		if(this.creator){
-			// use defined creator
-			this._normalizedCreator = function(node, hint){
-				return oldCreator.call(this, source.getItem(node.id).data, hint);
-			};
-		}else{
-			// we have no creator defined => move/clone nodes
-			if(copy){
-				// clone nodes
-				this._normalizedCreator = function(node, hint){
-					var t = source.getItem(node.id);
-					var n = node.cloneNode(true);
-					n.id = dojo.dnd.getUniqueId();
-					return {node: n, data: t.data, type: t.type};
-				};
-			}else{
-				// move nodes
-				this._normalizedCreator = function(node, hint){
-					var t = source.getItem(node.id);
-					source.delItem(node.id);
-					return {node: node, data: t.data, type: t.type};
-				};
-			}
-		}
-		this.selectNone();
-		if(!copy && !this.creator){
-			source.selectNone();
-		}
-		this.insertNodes(true, nodes, this.before, this.current);
-		if(!copy && this.creator){
-			source.deleteSelectedNodes();
-		}
-		this._normalizedCreator = oldCreator;
-	},
-	onDropInternal: function(nodes, copy){
-		// summary:
-		//		called only on the current target, when drop is performed
-		//		from the same target/source
-		// nodes: Array
-		//		the list of transferred items
-		// copy: Boolean
-		//		copy items, if true, move items otherwise
-		
-		var oldCreator = this._normalizedCreator;
-		// transferring nodes within the single source
-		if(this.current && this.current.id in this.selection){
-			// do nothing
-			return;
-		}
-		if(copy){
-			if(this.creator){
-				// create new copies of data items
-				this._normalizedCreator = function(node, hint){
-					return oldCreator.call(this, this.getItem(node.id).data, hint);
-				};
-			}else{
-				// clone nodes
-				this._normalizedCreator = function(node, hint){
-					var t = this.getItem(node.id);
-					var n = node.cloneNode(true);
-					n.id = dojo.dnd.getUniqueId();
-					return {node: n, data: t.data, type: t.type};
-				};
-			}
-		}else{
-			// move nodes
-			if(!this.current){
-				// do nothing
-				return;
-			}
-			this._normalizedCreator = function(node, hint){
-				var t = this.getItem(node.id);
-				return {node: node, data: t.data, type: t.type};
-			};
-		}
-		this._removeSelection();
-		this.insertNodes(true, nodes, this.before, this.current);
-		this._normalizedCreator = oldCreator;
-	},
-	onDraggingOver: function(){
-		// summary:
-		//		called during the active DnD operation, when items
-		//		are dragged over this target, and it is not disabled
-	},
-	onDraggingOut: function(){
-		// summary:
-		//		called during the active DnD operation, when items
-		//		are dragged away from this target, and it is not disabled
-	},
-	
-	// utilities
-	onOverEvent: function(){
-		// summary:
-		//		this function is called once, when mouse is over our container
-		dojo.dnd.Source.superclass.onOverEvent.call(this);
-		dojo.dnd.manager().overSource(this);
-		if(this.isDragging && this.targetState != "Disabled"){
-			this.onDraggingOver();
-		}
-	},
-	onOutEvent: function(){
-		// summary:
-		//		this function is called once, when mouse is out of our container
-		dojo.dnd.Source.superclass.onOutEvent.call(this);
-		dojo.dnd.manager().outSource(this);
-		if(this.isDragging && this.targetState != "Disabled"){
-			this.onDraggingOut();
-		}
-	},
-	_markTargetAnchor: function(before){
-		// summary:
-		//		assigns a class to the current target anchor based on "before" status
-		// before: Boolean
-		//		insert before, if true, after otherwise
-		if(this.current == this.targetAnchor && this.before == before){ return; }
-		if(this.targetAnchor){
-			this._removeItemClass(this.targetAnchor, this.before ? "Before" : "After");
-		}
-		this.targetAnchor = this.current;
-		this.targetBox = null;
-		this.before = before;
-		if(this.targetAnchor){
-			this._addItemClass(this.targetAnchor, this.before ? "Before" : "After");
-		}
-	},
-	_unmarkTargetAnchor: function(){
-		// summary:
-		//		removes a class of the current target anchor based on "before" status
-		if(!this.targetAnchor){ return; }
-		this._removeItemClass(this.targetAnchor, this.before ? "Before" : "After");
-		this.targetAnchor = null;
-		this.targetBox = null;
-		this.before = true;
-	},
-	_markDndStatus: function(copy){
-		// summary:
-		//		changes source's state based on "copy" status
-		this._changeState("Source", copy ? "Copied" : "Moved");
-	},
-	_legalMouseDown: function(e){
-		// summary:
-		//		checks if user clicked on "approved" items
-		// e: Event
-		//		mouse event
-		
-		// accept only the left mouse button
-		if(!dojo.mouseButtons.isLeft(e)){ return false; }
-		
-		if(!this.withHandles){ return true; }
-		
-		// check for handles
-		for(var node = e.target; node && node !== this.node; node = node.parentNode){
-			if(dojo.hasClass(node, "dojoDndHandle")){ return true; }
-			if(dojo.hasClass(node, "dojoDndItem") || dojo.hasClass(node, "dojoDndIgnore")){ break; }
-		}
-		return false;	// Boolean
-	}
-});
-
-dojo.declare("dojo.dnd.Target", dojo.dnd.Source, {
-	// summary: a Target object, which can be used as a DnD target
-	
-	constructor: function(node, params){
-		// summary:
-		//		a constructor of the Target --- see the `dojo.dnd.Source.constructor` for details
-		this.isSource = false;
-		dojo.removeClass(this.node, "dojoDndSource");
-	},
-
-	// markup methods
-	markupFactory: function(params, node){
-		params._skipStartup = true;
-		return new dojo.dnd.Target(node, params);
-	}
-});
-
-dojo.declare("dojo.dnd.AutoSource", dojo.dnd.Source, {
-	// summary:
-	//		a source that syncs its DnD nodes by default
-	
-	constructor: function(node, params){
-		// summary:
-		//		constructor of the AutoSource --- see the Source constructor for details
-		this.autoSync = true;
-	},
-
-	// markup methods
-	markupFactory: function(params, node){
-		params._skipStartup = true;
-		return new dojo.dnd.AutoSource(node, params);
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.grid._View"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid._View"] = true;
-dojo.provide("dojox.grid._View");
-
-
-
-
-
-
-
-
-
-
-(function(){
-	// private
-	var getStyleText = function(inNode, inStyleText){
-		return inNode.style.cssText == undefined ? inNode.getAttribute("style") : inNode.style.cssText;
-	};
-
-	// public
-	dojo.declare('dojox.grid._View', [dijit._Widget, dijit._Templated], {
-		// summary:
-		//		A collection of grid columns. A grid is comprised of a set of views that stack horizontally.
-		//		Grid creates views automatically based on grid's layout structure.
-		//		Users should typically not need to access individual views directly.
-		//
-		// defaultWidth: String
-		//		Default width of the view
-		defaultWidth: "18em",
-
-		// viewWidth: String
-		// 		Width for the view, in valid css unit
-		viewWidth: "",
-
-		templateString:"<div class=\"dojoxGridView\" wairole=\"presentation\">\n\t<div class=\"dojoxGridHeader\" dojoAttachPoint=\"headerNode\" wairole=\"presentation\">\n\t\t<div dojoAttachPoint=\"headerNodeContainer\" style=\"width:9000em\" wairole=\"presentation\">\n\t\t\t<div dojoAttachPoint=\"headerContentNode\" wairole=\"row\"></div>\n\t\t</div>\n\t</div>\n\t<input type=\"checkbox\" class=\"dojoxGridHiddenFocus\" dojoAttachPoint=\"hiddenFocusNode\" wairole=\"presentation\" />\n\t<input t [...]
-		
-		themeable: false,
-		classTag: 'dojoxGrid',
-		marginBottom: 0,
-		rowPad: 2,
-
-		// _togglingColumn: int
-		//		Width of the column being toggled (-1 for none)
-		_togglingColumn: -1,
-		
-		// _headerBuilderClass: Object
-		//		The class to use for our header builder
-		_headerBuilderClass: dojox.grid._HeaderBuilder,
-		
-		// _contentBuilderClass: Object
-		//		The class to use for our content builder
-		_contentBuilderClass: dojox.grid._ContentBuilder,
-		
-		postMixInProperties: function(){
-			this.rowNodes = {};
-		},
-
-		postCreate: function(){
-			this.connect(this.scrollboxNode,"onscroll","doscroll");
-			dojox.grid.util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
-			dojox.grid.util.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
-			this.content = new this._contentBuilderClass(this);
-			this.header = new this._headerBuilderClass(this);
-			//BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
-			if(!dojo._isBodyLtr()){
-				this.headerNodeContainer.style.width = "";
-			}
-		},
-
-		destroy: function(){
-			dojo.destroy(this.headerNode);
-			delete this.headerNode;
-			for(var i in this.rowNodes){
-				dojo.destroy(this.rowNodes[i]);
-			}
-			this.rowNodes = {};
-			if(this.source){
-				this.source.destroy();
-			}
-			this.inherited(arguments);
-		},
-
-		// focus 
-		focus: function(){
-			if(dojo.isIE || dojo.isWebKit || dojo.isOpera){
-				this.hiddenFocusNode.focus();
-			}else{
-				this.scrollboxNode.focus();
-			}
-		},
-
-		setStructure: function(inStructure){
-			var vs = (this.structure = inStructure);
-			// FIXME: similar logic is duplicated in layout
-			if(vs.width && !isNaN(vs.width)){
-				this.viewWidth = vs.width + 'em';
-			}else{
-				this.viewWidth = vs.width || (vs.noscroll ? 'auto' : this.viewWidth); //|| this.defaultWidth;
-			}
-			this._onBeforeRow = vs.onBeforeRow||function(){};
-			this._onAfterRow = vs.onAfterRow||function(){};
-			this.noscroll = vs.noscroll;
-			if(this.noscroll){
-				this.scrollboxNode.style.overflow = "hidden";
-			}
-			this.simpleStructure = Boolean(vs.cells.length == 1);
-			// bookkeeping
-			this.testFlexCells();
-			// accomodate new structure
-			this.updateStructure();
-		},
-		
-		_cleanupRowWidgets: function(inRowNode){
-			// Summary:
-			//		Cleans up the widgets for the given row node so that
-			//		we can reattach them if needed
-			if(inRowNode){
-				dojo.forEach(dojo.query("[widgetId]", inRowNode).map(dijit.byNode), function(w){
-					if(w._destroyOnRemove){
-						w.destroy();
-						delete w;
-					}else if(w.domNode && w.domNode.parentNode){
-						w.domNode.parentNode.removeChild(w.domNode);
-					}
-				});
-			}
-		},
-		
-		onBeforeRow: function(inRowIndex, cells){
-			this._onBeforeRow(inRowIndex, cells);
-			if(inRowIndex >= 0){
-				this._cleanupRowWidgets(this.getRowNode(inRowIndex));
-			}
-		},
-		
-		onAfterRow: function(inRowIndex, cells, inRowNode){
-			this._onAfterRow(inRowIndex, cells, inRowNode);
-			var g = this.grid;
-			dojo.forEach(dojo.query(".dojoxGridStubNode", inRowNode), function(n){
-				if(n && n.parentNode){
-					var lw = n.getAttribute("linkWidget");
-					var cellIdx = window.parseInt(dojo.attr(n, "cellIdx"), 10);
-					var cellDef = g.getCell(cellIdx);
-					var w = dijit.byId(lw);
-					if(w){
-						n.parentNode.replaceChild(w.domNode, n);
-						if(!w._started){
-							w.startup();
-						}
-					}else{
-						n.innerHTML = "";
-					}
-				}
-			}, this);
-		},
-
-		testFlexCells: function(){
-			// FIXME: cheater, this function does double duty as initializer and tester
-			this.flexCells = false;
-			for(var j=0, row; (row=this.structure.cells[j]); j++){
-				for(var i=0, cell; (cell=row[i]); i++){
-					cell.view = this;
-					this.flexCells = this.flexCells || cell.isFlex();
-				}
-			}
-			return this.flexCells;
-		},
-
-		updateStructure: function(){
-			// header builder needs to update table map
-			this.header.update();
-			// content builder needs to update markup cache
-			this.content.update();
-		},
-
-		getScrollbarWidth: function(){
-			var hasScrollSpace = this.hasVScrollbar();
-			var overflow = dojo.style(this.scrollboxNode, "overflow");
-			if(this.noscroll || !overflow || overflow == "hidden"){
-				hasScrollSpace = false;
-			}else if(overflow == "scroll"){
-				hasScrollSpace = true;
-			}
-			return (hasScrollSpace ? dojox.html.metrics.getScrollbar().w : 0); // Integer
-		},
-
-		getColumnsWidth: function(){
-			var h = this.headerContentNode;
-			return h && h.firstChild ? h.firstChild.offsetWidth : 0; // Integer
-		},
-
-		setColumnsWidth: function(width){
-			this.headerContentNode.firstChild.style.width = width + 'px';
-			if(this.viewWidth){
-				this.viewWidth = width + 'px';
-			}
-		},
-
-		getWidth: function(){
-			return this.viewWidth || (this.getColumnsWidth()+this.getScrollbarWidth()) +'px'; // String
-		},
-
-		getContentWidth: function(){
-			return Math.max(0, dojo._getContentBox(this.domNode).w - this.getScrollbarWidth()) + 'px'; // String
-		},
-
-		render: function(){
-			this.scrollboxNode.style.height = '';
-			this.renderHeader();
-			if(this._togglingColumn >= 0){
-				this.setColumnsWidth(this.getColumnsWidth() - this._togglingColumn);
-				this._togglingColumn = -1;
-			}
-			var cells = this.grid.layout.cells;
-			var getSibling = dojo.hitch(this, function(node, before){
-				var inc = before?-1:1;
-				var idx = this.header.getCellNodeIndex(node) + inc;
-				var cell = cells[idx];
-				while(cell && cell.getHeaderNode() && cell.getHeaderNode().style.display == "none"){
-					idx += inc;
-					cell = cells[idx];
-				}
-				if(cell){
-					return cell.getHeaderNode();
-				}
-				return null;
-			});
-			if(this.grid.columnReordering && this.simpleStructure){
-				if(this.source){
-					this.source.destroy();
-				}
-				
-				// Create the top and bottom markers
-				var bottomMarkerId = "dojoxGrid_bottomMarker";
-				var topMarkerId = "dojoxGrid_topMarker";
-				if(this.bottomMarker){
-					dojo.destroy(this.bottomMarker);
-				}
-				this.bottomMarker = dojo.byId(bottomMarkerId);
-				if(this.topMarker){
-					dojo.destroy(this.topMarker);
-				}
-				this.topMarker = dojo.byId(topMarkerId);
-				if (!this.bottomMarker) {
-					this.bottomMarker = dojo.create("div", {
-						"id": bottomMarkerId,
-						"class": "dojoxGridColPlaceBottom"
-					}, dojo.body());
-					this._hide(this.bottomMarker);
-
-					
-					this.topMarker = dojo.create("div", {
-						"id": topMarkerId,
-						"class": "dojoxGridColPlaceTop"
-					}, dojo.body());
-					this._hide(this.topMarker);
-				}
-				this.arrowDim = dojo.contentBox(this.bottomMarker);
-
-				var headerHeight = dojo.contentBox(this.headerContentNode.firstChild.rows[0]).h;
-				
-				this.source = new dojo.dnd.Source(this.headerContentNode.firstChild.rows[0], {
-					horizontal: true,
-					accept: [ "gridColumn_" + this.grid.id ],
-					viewIndex: this.index,
-					generateText: false,
-					onMouseDown: dojo.hitch(this, function(e){
-						this.header.decorateEvent(e);
-						if((this.header.overRightResizeArea(e) || this.header.overLeftResizeArea(e)) &&
-							this.header.canResize(e) && !this.header.moveable){
-							this.header.beginColumnResize(e);
-						}else{
-							if(this.grid.headerMenu){
-								this.grid.headerMenu.onCancel(true);
-							}
-							// IE reports a left click as 1, where everything else reports 0
-							if(e.button === (dojo.isIE ? 1 : 0)){
-								dojo.dnd.Source.prototype.onMouseDown.call(this.source, e);
-							}
-						}
-					}),
-					onMouseOver: dojo.hitch(this, function(e){
-						var src = this.source;
-						if(src._getChildByEvent(e)){
-							dojo.dnd.Source.prototype.onMouseOver.apply(src, arguments);
-						}
-					}),
-					_markTargetAnchor: dojo.hitch(this, function(before){
-						var src = this.source;
-						if(src.current == src.targetAnchor && src.before == before){ return; }
-						if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
-							src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
-						}
-						dojo.dnd.Source.prototype._markTargetAnchor.call(src, before);
-						
-						var target = before ? src.targetAnchor : getSibling(src.targetAnchor, src.before);
-						var endAdd = 0;
-
-						if (!target) {
-							target = src.targetAnchor;
-							endAdd = dojo.contentBox(target).w + this.arrowDim.w/2 + 2;
-						}
-
-						// NOTE: this is for backwards compatibility with Dojo 1.3
-						var pos = (dojo.position||dojo._abs)(target, true);
-						var left = Math.floor(pos.x - this.arrowDim.w/2 + endAdd);
-
-						dojo.style(this.bottomMarker, "visibility", "visible");
-						dojo.style(this.topMarker, "visibility", "visible");
-						dojo.style(this.bottomMarker, {
-							"left": left + "px",
-							"top" : (headerHeight + pos.y) + "px"
-						});
-
-						dojo.style(this.topMarker, {
-							"left": left + "px",
-							"top" : (pos.y - this.arrowDim.h) + "px"
-						});
-
-						if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
-							src._addItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
-						}
-					}),
-					_unmarkTargetAnchor: dojo.hitch(this, function(){
-						var src = this.source;
-						if(!src.targetAnchor){ return; }
-						if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
-							src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
-						}
-						this._hide(this.bottomMarker);
-						this._hide(this.topMarker);
-						dojo.dnd.Source.prototype._unmarkTargetAnchor.call(src);
-					}),
-					destroy: dojo.hitch(this, function(){
-						dojo.disconnect(this._source_conn);
-						dojo.unsubscribe(this._source_sub);
-						dojo.dnd.Source.prototype.destroy.call(this.source);
-						if(this.bottomMarker){
-							dojo.destroy(this.bottomMarker);
-							delete this.bottomMarker;
-						}
-						if(this.topMarker){
-							dojo.destroy(this.topMarker);
-							delete this.topMarker;
-						}
-					}),
-					onDndCancel: dojo.hitch(this, function(){
-						dojo.dnd.Source.prototype.onDndCancel.call(this.source);
-						this._hide(this.bottomMarker);
-						this._hide(this.topMarker);
-					})
-				});
-
-				this._source_conn = dojo.connect(this.source, "onDndDrop", this, "_onDndDrop");
-				this._source_sub = dojo.subscribe("/dnd/drop/before", this, "_onDndDropBefore");
-				this.source.startup();
-			}
-		},
-		
-		_hide: function(node){
-			dojo.style(node, {
-				left: "-10000px",
-				top: "-10000px",
-				"visibility": "hidden"
-			});
-		},
-
-		_onDndDropBefore: function(source, nodes, copy){
-			if(dojo.dnd.manager().target !== this.source){
-				return;
-			}
-			this.source._targetNode = this.source.targetAnchor;
-			this.source._beforeTarget = this.source.before;
-			var views = this.grid.views.views;
-			var srcView = views[source.viewIndex];
-			var tgtView = views[this.index];
-			if(tgtView != srcView){
-				srcView.convertColPctToFixed();
-				tgtView.convertColPctToFixed();
-			}
-		},
-
-		_onDndDrop: function(source, nodes, copy){
-			if(dojo.dnd.manager().target !== this.source){
-				if(dojo.dnd.manager().source === this.source){
-					this._removingColumn = true;
-				}
-				return;
-			}
-			this._hide(this.bottomMarker);
-			this._hide(this.topMarker);
-
-			var getIdx = function(n){
-				return n ? dojo.attr(n, "idx") : null;
-			};
-			var w = dojo.marginBox(nodes[0]).w;
-			if(source.viewIndex !== this.index){
-				var views = this.grid.views.views;
-				var srcView = views[source.viewIndex];
-				var tgtView = views[this.index];
-				if(srcView.viewWidth && srcView.viewWidth != "auto"){
-					srcView.setColumnsWidth(srcView.getColumnsWidth() - w);
-				}
-				if(tgtView.viewWidth && tgtView.viewWidth != "auto"){
-					tgtView.setColumnsWidth(tgtView.getColumnsWidth());
-				}
-			}
-			var stn = this.source._targetNode;
-			var stb = this.source._beforeTarget;
-			var layout = this.grid.layout;
-			var idx = this.index;
-			delete this.source._targetNode;
-			delete this.source._beforeTarget;
-			
-			layout.moveColumn(
-				source.viewIndex,
-				idx,
-				getIdx(nodes[0]),
-				getIdx(stn),
-				stb);
-		},
-
-		renderHeader: function(){
-			this.headerContentNode.innerHTML = this.header.generateHtml(this._getHeaderContent);
-			if(this.flexCells){
-				this.contentWidth = this.getContentWidth();
-				this.headerContentNode.firstChild.style.width = this.contentWidth;
-			}
-			dojox.grid.util.fire(this, "onAfterRow", [-1, this.structure.cells, this.headerContentNode]);
-		},
-
-		// note: not called in 'view' context
-		_getHeaderContent: function(inCell){
-			var n = inCell.name || inCell.grid.getCellName(inCell);
-			var ret = [ '<div class="dojoxGridSortNode' ];
-			
-			if(inCell.index != inCell.grid.getSortIndex()){
-				ret.push('">');
-			}else{
-				ret = ret.concat([ ' ',
-							inCell.grid.sortInfo > 0 ? 'dojoxGridSortUp' : 'dojoxGridSortDown',
-							'"><div class="dojoxGridArrowButtonChar">',
-							inCell.grid.sortInfo > 0 ? '▲' : '▼',
-							'</div><div class="dojoxGridArrowButtonNode" role="presentation"></div>']);
-			}
-			ret = ret.concat([n, '</div>']);
-			return ret.join('');
-		},
-
-		resize: function(){
-			this.adaptHeight();
-			this.adaptWidth();
-		},
-
-		hasHScrollbar: function(reset){
-			var hadScroll = this._hasHScroll||false;
-			if(this._hasHScroll == undefined || reset){
-				if(this.noscroll){
-					this._hasHScroll = false;
-				}else{
-					var style = dojo.style(this.scrollboxNode, "overflow");
-					if(style == "hidden"){
-						this._hasHScroll = false;
-					}else if(style == "scroll"){
-						this._hasHScroll = true;
-					}else{
-						this._hasHScroll = (this.scrollboxNode.offsetWidth - this.getScrollbarWidth() < this.contentNode.offsetWidth );
-					}
-				}
-			}
-			if(hadScroll !== this._hasHScroll){
-				this.grid.update();
-			}
-			return this._hasHScroll; // Boolean
-		},
-
-		hasVScrollbar: function(reset){
-			var hadScroll = this._hasVScroll||false;
-			if(this._hasVScroll == undefined || reset){
-				if(this.noscroll){
-					this._hasVScroll = false;
-				}else{
-					var style = dojo.style(this.scrollboxNode, "overflow");
-					if(style == "hidden"){
-						this._hasVScroll = false;
-					}else if(style == "scroll"){
-						this._hasVScroll = true;
-					}else{
-						this._hasVScroll = (this.scrollboxNode.scrollHeight > this.scrollboxNode.clientHeight);
-					}
-				}
-			}
-			if(hadScroll !== this._hasVScroll){
-				this.grid.update();
-			}
-			return this._hasVScroll; // Boolean
-		},
-		
-		convertColPctToFixed: function(){
-			// Fix any percentage widths to be pixel values
-			var hasPct = false;
-			this.grid.initialWidth = "";
-			var cellNodes = dojo.query("th", this.headerContentNode);
-			var fixedWidths = dojo.map(cellNodes, function(c, vIdx){
-				var w = c.style.width;
-				dojo.attr(c, "vIdx", vIdx);
-				if(w && w.slice(-1) == "%"){
-					hasPct = true;
-				}else if(w && w.slice(-2) == "px"){
-					return window.parseInt(w, 10);
-				}
-				return dojo.contentBox(c).w;
-			});
-			if(hasPct){
-				dojo.forEach(this.grid.layout.cells, function(cell, idx){
-					if(cell.view == this){
-						var cellNode = cell.view.getHeaderCellNode(cell.index);
-						if(cellNode && dojo.hasAttr(cellNode, "vIdx")){
-							var vIdx = window.parseInt(dojo.attr(cellNode, "vIdx"));
-							this.setColWidth(idx, fixedWidths[vIdx]);
-							dojo.removeAttr(cellNode, "vIdx");
-						}
-					}
-				}, this);
-				return true;
-			}
-			return false;
-		},
-
-		adaptHeight: function(minusScroll){
-			if(!this.grid._autoHeight){
-				var h = (this.domNode.style.height && parseInt(this.domNode.style.height.replace(/px/,''), 10)) || this.domNode.clientHeight;
-				var self = this;
-				var checkOtherViewScrollers = function(){
-					var v;
-					for(var i in self.grid.views.views){
-						v = self.grid.views.views[i];
-						if(v !== self && v.hasHScrollbar()){
-							return true;
-						}
-					}
-					return false;
-				};
-				if(minusScroll || (this.noscroll && checkOtherViewScrollers())){
-					h -= dojox.html.metrics.getScrollbar().h;
-				}
-				dojox.grid.util.setStyleHeightPx(this.scrollboxNode, h);
-			}
-			this.hasVScrollbar(true);
-		},
-
-		adaptWidth: function(){
-			if(this.flexCells){
-				// the view content width
-				this.contentWidth = this.getContentWidth();
-				this.headerContentNode.firstChild.style.width = this.contentWidth;
-			}
-			// FIXME: it should be easier to get w from this.scrollboxNode.clientWidth, 
-			// but clientWidth seemingly does not include scrollbar width in some cases
-			var w = this.scrollboxNode.offsetWidth - this.getScrollbarWidth();
-			if(!this._removingColumn){
-				w = Math.max(w, this.getColumnsWidth()) + 'px';
-			}else{
-				w = Math.min(w, this.getColumnsWidth()) + 'px';
-				this._removingColumn = false;
-			}
-			var cn = this.contentNode;
-			cn.style.width = w;
-			this.hasHScrollbar(true);
-		},
-
-		setSize: function(w, h){
-			var ds = this.domNode.style;
-			var hs = this.headerNode.style;
-
-			if(w){
-				ds.width = w;
-				hs.width = w;
-			}
-			ds.height = (h >= 0 ? h + 'px' : '');
-		},
-
-		renderRow: function(inRowIndex){
-			var rowNode = this.createRowNode(inRowIndex);
-			this.buildRow(inRowIndex, rowNode);
-			this.grid.edit.restore(this, inRowIndex);
-			return rowNode;
-		},
-
-		createRowNode: function(inRowIndex){
-			var node = document.createElement("div");
-			node.className = this.classTag + 'Row';
-			if (this instanceof dojox.grid._RowSelector){
-				dojo.attr(node,"role","presentation");
-			}else{
-				dojo.attr(node,"role","row");
-				if (this.grid.selectionMode != "none") {
-					dojo.attr(node, "aria-selected", "false"); //rows can be selected so add aria-selected prop
-				}
-			}
-			node[dojox.grid.util.gridViewTag] = this.id;
-			node[dojox.grid.util.rowIndexTag] = inRowIndex;
-			this.rowNodes[inRowIndex] = node;
-			return node;
-		},
-
-		buildRow: function(inRowIndex, inRowNode){
-			
-			this.buildRowContent(inRowIndex, inRowNode);
-		  	
-			this.styleRow(inRowIndex, inRowNode);
-		  
-		 
-		},
-
-		buildRowContent: function(inRowIndex, inRowNode){
-			inRowNode.innerHTML = this.content.generateHtml(inRowIndex, inRowIndex); 
-			if(this.flexCells && this.contentWidth){
-				// FIXME: accessing firstChild here breaks encapsulation
-				inRowNode.firstChild.style.width = this.contentWidth;
-			}
-			dojox.grid.util.fire(this, "onAfterRow", [inRowIndex, this.structure.cells, inRowNode]);
-		},
-
-		rowRemoved:function(inRowIndex){
-			if(inRowIndex >= 0){
-				this._cleanupRowWidgets(this.getRowNode(inRowIndex));
-			}
-			this.grid.edit.save(this, inRowIndex);
-			delete this.rowNodes[inRowIndex];
-		},
-
-		getRowNode: function(inRowIndex){
-			return this.rowNodes[inRowIndex];
-		},
-
-		getCellNode: function(inRowIndex, inCellIndex){
-			var row = this.getRowNode(inRowIndex);
-			if(row){
-				return this.content.getCellNode(row, inCellIndex);
-			}
-		},
-
-		getHeaderCellNode: function(inCellIndex){
-			if(this.headerContentNode){
-				return this.header.getCellNode(this.headerContentNode, inCellIndex);
-			}
-		},
-
-		// styling
-		styleRow: function(inRowIndex, inRowNode){
-			inRowNode._style = getStyleText(inRowNode);
-			this.styleRowNode(inRowIndex, inRowNode);
-		},
-
-		styleRowNode: function(inRowIndex, inRowNode){
-			if(inRowNode){
-				this.doStyleRowNode(inRowIndex, inRowNode);
-			}
-		},
-
-		doStyleRowNode: function(inRowIndex, inRowNode){
-			this.grid.styleRowNode(inRowIndex, inRowNode);
-		},
-
-		// updating
-		updateRow: function(inRowIndex){
-			var rowNode = this.getRowNode(inRowIndex);
-			if(rowNode){
-				rowNode.style.height = '';
-				this.buildRow(inRowIndex, rowNode);
-			}
-			return rowNode;
-		},
-
-		updateRowStyles: function(inRowIndex){
-			this.styleRowNode(inRowIndex, this.getRowNode(inRowIndex));
-		},
-
-		// scrolling
-		lastTop: 0,
-		firstScroll:0,
-
-		doscroll: function(inEvent){
-			//var s = dojo.marginBox(this.headerContentNode.firstChild);
-			var isLtr = dojo._isBodyLtr();
-			if(this.firstScroll < 2){
-				if((!isLtr && this.firstScroll == 1) || (isLtr && this.firstScroll === 0)){
-					var s = dojo.marginBox(this.headerNodeContainer);
-					if(dojo.isIE){
-						this.headerNodeContainer.style.width = s.w + this.getScrollbarWidth() + 'px';
-					}else if(dojo.isMoz){
-						//TODO currently only for FF, not sure for safari and opera
-						this.headerNodeContainer.style.width = s.w - this.getScrollbarWidth() + 'px';
-						//this.headerNodeContainer.style.width = s.w + 'px';
-						//set scroll to right in FF
-						this.scrollboxNode.scrollLeft = isLtr ?
-							this.scrollboxNode.clientWidth - this.scrollboxNode.scrollWidth :
-							this.scrollboxNode.scrollWidth - this.scrollboxNode.clientWidth;
-					}
-				}
-				this.firstScroll++;
-			}
-			this.headerNode.scrollLeft = this.scrollboxNode.scrollLeft;
-			// 'lastTop' is a semaphore to prevent feedback-loop with setScrollTop below
-			var top = this.scrollboxNode.scrollTop;
-			if(top !== this.lastTop){
-				this.grid.scrollTo(top);
-			}
-		},
-
-		setScrollTop: function(inTop){
-			// 'lastTop' is a semaphore to prevent feedback-loop with doScroll above
-			this.lastTop = inTop;
-			this.scrollboxNode.scrollTop = inTop;
-			return this.scrollboxNode.scrollTop;
-		},
-
-		// event handlers (direct from DOM)
-		doContentEvent: function(e){
-			if(this.content.decorateEvent(e)){
-				this.grid.onContentEvent(e);
-			}
-		},
-
-		doHeaderEvent: function(e){
-			if(this.header.decorateEvent(e)){
-				this.grid.onHeaderEvent(e);
-			}
-		},
-
-		// event dispatch(from Grid)
-		dispatchContentEvent: function(e){
-			return this.content.dispatchEvent(e);
-		},
-
-		dispatchHeaderEvent: function(e){
-			return this.header.dispatchEvent(e);
-		},
-
-		// column resizing
-		setColWidth: function(inIndex, inWidth){
-			this.grid.setCellWidth(inIndex, inWidth + 'px');
-		},
-
-		update: function(){
-			if(!this.domNode){
-				return;
-			}
-			this.content.update();
-			this.grid.update();
-			//get scroll after update or scroll left setting goes wrong on IE.
-			//See trac: #8040
-			var left = this.scrollboxNode.scrollLeft;
-			this.scrollboxNode.scrollLeft = left;
-			this.headerNode.scrollLeft = left;
-		}
-	});
-
-	dojo.declare("dojox.grid._GridAvatar", dojo.dnd.Avatar, {
-		construct: function(){
-			var dd = dojo.doc;
-
-			var a = dd.createElement("table");
-			a.cellPadding = a.cellSpacing = "0";
-			a.className = "dojoxGridDndAvatar";
-			a.style.position = "absolute";
-			a.style.zIndex = 1999;
-			a.style.margin = "0px"; // to avoid dojo.marginBox() problems with table's margins
-			var b = dd.createElement("tbody");
-			var tr = dd.createElement("tr");
-			var td = dd.createElement("td");
-			var img = dd.createElement("td");
-			tr.className = "dojoxGridDndAvatarItem";
-			img.className = "dojoxGridDndAvatarItemImage";
-			img.style.width = "16px";
-			var source = this.manager.source, node;
-			if(source.creator){
-				// create an avatar representation of the node
-				node = source._normalizedCreator(source.getItem(this.manager.nodes[0].id).data, "avatar").node;
-			}else{
-				// or just clone the node and hope it works
-				node = this.manager.nodes[0].cloneNode(true);
-				var table, tbody;
-				if(node.tagName.toLowerCase() == "tr"){
-					// insert extra table nodes
-					table = dd.createElement("table");
-					tbody = dd.createElement("tbody");
-					tbody.appendChild(node);
-					table.appendChild(tbody);
-					node = table;
-				}else if(node.tagName.toLowerCase() == "th"){
-					// insert extra table nodes
-					table = dd.createElement("table");
-					tbody = dd.createElement("tbody");
-					var r = dd.createElement("tr");
-					table.cellPadding = table.cellSpacing = "0";
-					r.appendChild(node);
-					tbody.appendChild(r);
-					table.appendChild(tbody);
-					node = table;
-				}
-			}
-			node.id = "";
-			td.appendChild(node);
-			tr.appendChild(img);
-			tr.appendChild(td);
-			dojo.style(tr, "opacity", 0.9);
-			b.appendChild(tr);
-
-			a.appendChild(b);
-			this.node = a;
-
-			var m = dojo.dnd.manager();
-			this.oldOffsetY = m.OFFSET_Y;
-			m.OFFSET_Y = 1;
-		},
-		destroy: function(){
-			dojo.dnd.manager().OFFSET_Y = this.oldOffsetY;
-			this.inherited(arguments);
-		}
-	});
-
-	var oldMakeAvatar = dojo.dnd.manager().makeAvatar;
-	dojo.dnd.manager().makeAvatar = function(){
-		var src = this.source;
-		if(src.viewIndex !== undefined && !dojo.hasClass(dojo.body(),"dijit_a11y")){
-			return new dojox.grid._GridAvatar(this);
-		}
-		return oldMakeAvatar.call(dojo.dnd.manager());
-	};
-})();
-
-}
-
-if(!dojo._hasResource["dojox.grid._RowSelector"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid._RowSelector"] = true;
-dojo.provide("dojox.grid._RowSelector");
-
-
-dojo.declare('dojox.grid._RowSelector', dojox.grid._View, {
-	// summary:
-	//	Custom grid view. If used in a grid structure, provides a small selectable region for grid rows.
-	defaultWidth: "2em",
-	noscroll: true,
-	padBorderWidth: 2,
-	buildRendering: function(){
-		this.inherited('buildRendering', arguments);
-		this.scrollboxNode.style.overflow = "hidden";
-		this.headerNode.style.visibility = "hidden";
-	},	
-	getWidth: function(){
-		return this.viewWidth || this.defaultWidth;
-	},
-	buildRowContent: function(inRowIndex, inRowNode){
-		var w = this.contentWidth || 0;
-		inRowNode.innerHTML = '<table class="dojoxGridRowbarTable" style="width:' + w + 'px;height:1px;" border="0" cellspacing="0" cellpadding="0" role="presentation"><tr><td class="dojoxGridRowbarInner"> </td></tr></table>';
-	},
-	renderHeader: function(){
-	},
-	updateRow: function(){
-	},
-	resize: function(){
-		this.adaptHeight();
-	},
-	adaptWidth: function(){
-		// Only calculate this here - rather than every call to buildRowContent
-		if(!("contentWidth" in this) && this.contentNode){
-			this.contentWidth = this.contentNode.offsetWidth - this.padBorderWidth;
-		}
-	},
-	// styling
-	doStyleRowNode: function(inRowIndex, inRowNode){
-		var n = [ "dojoxGridRowbar dojoxGridNonNormalizedCell" ];
-		if(this.grid.rows.isOver(inRowIndex)){
-			n.push("dojoxGridRowbarOver");
-		}
-		if(this.grid.selection.isSelected(inRowIndex)){
-			n.push("dojoxGridRowbarSelected");
-		}
-		inRowNode.className = n.join(" ");
-	},
-	// event handlers
-	domouseover: function(e){
-		this.grid.onMouseOverRow(e);
-	},
-	domouseout: function(e){
-		if(!this.isIntraRowEvent(e)){
-			this.grid.onMouseOutRow(e);
-		}
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.grid._Layout"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid._Layout"] = true;
-dojo.provide("dojox.grid._Layout");
-
-
-
-dojo.declare("dojox.grid._Layout", null, {
-	// summary:
-	//	Controls grid cell layout. Owned by grid and used internally.
-	constructor: function(inGrid){
-		this.grid = inGrid;
-	},
-	// flat array of grid cells
-	cells: [],
-	// structured array of grid cells
-	structure: null,
-	// default cell width
-	defaultWidth: '6em',
-
-	// methods
-	moveColumn: function(sourceViewIndex, destViewIndex, cellIndex, targetIndex, before){
-		var source_cells = this.structure[sourceViewIndex].cells[0];
-		var dest_cells = this.structure[destViewIndex].cells[0];
-
-		var cell = null;
-		var cell_ri = 0;
-		var target_ri = 0;
-
-		for(var i=0, c; c=source_cells[i]; i++){
-			if(c.index == cellIndex){
-				cell_ri = i;
-				break;
-			}
-		}
-		cell = source_cells.splice(cell_ri, 1)[0];
-		cell.view = this.grid.views.views[destViewIndex];
-
-		for(i=0, c=null; c=dest_cells[i]; i++){
-			if(c.index == targetIndex){
-				target_ri = i;
-				break;
-			}
-		}
-		if(!before){
-			target_ri += 1;
-		}
-		dest_cells.splice(target_ri, 0, cell);
-
-		var sortedCell = this.grid.getCell(this.grid.getSortIndex());
-		if(sortedCell){
-			sortedCell._currentlySorted = this.grid.getSortAsc();
-		}
-
-		this.cells = [];
-		cellIndex = 0;
-		var v;
-		for(i=0; v=this.structure[i]; i++){
-			for(var j=0, cs; cs=v.cells[j]; j++){
-				for(var k=0; c=cs[k]; k++){
-					c.index = cellIndex;
-					this.cells.push(c);
-					if("_currentlySorted" in c){
-						var si = cellIndex + 1;
-						si *= c._currentlySorted ? 1 : -1;
-						this.grid.sortInfo = si;
-						delete c._currentlySorted;
-					}
-					cellIndex++;
-				}
-			}
-		}
-		this.grid.setupHeaderMenu();
-		//this.grid.renderOnIdle();
-	},
-
-	setColumnVisibility: function(columnIndex, visible){
-		var cell = this.cells[columnIndex];
-		if(cell.hidden == visible){
-			cell.hidden = !visible;
-			var v = cell.view, w = v.viewWidth;
-			if(w && w != "auto"){
-				v._togglingColumn = dojo.marginBox(cell.getHeaderNode()).w || 0;
-			}
-			v.update();
-			return true;
-		}else{
-			return false;
-		}
-	},
-	
-	addCellDef: function(inRowIndex, inCellIndex, inDef){
-		var self = this;
-		var getCellWidth = function(inDef){
-			var w = 0;
-			if(inDef.colSpan > 1){
-				w = 0;
-			}else{
-				w = inDef.width || self._defaultCellProps.width || self.defaultWidth;
-
-				if(!isNaN(w)){
-					w = w + "em";
-				}
-			}
-			return w;
-		};
-
-		var props = {
-			grid: this.grid,
-			subrow: inRowIndex,
-			layoutIndex: inCellIndex,
-			index: this.cells.length
-		};
-
-		if(inDef && inDef instanceof dojox.grid.cells._Base){
-			var new_cell = dojo.clone(inDef);
-			props.unitWidth = getCellWidth(new_cell._props);
-			new_cell = dojo.mixin(new_cell, this._defaultCellProps, inDef._props, props);
-			return new_cell;
-		}
-
-		var cell_type = inDef.type || this._defaultCellProps.type || dojox.grid.cells.Cell;
-
-		props.unitWidth = getCellWidth(inDef);
-		return new cell_type(dojo.mixin({}, this._defaultCellProps, inDef, props));	
-	},
-	
-	addRowDef: function(inRowIndex, inDef){
-		var result = [];
-		var relSum = 0, pctSum = 0, doRel = true;
-		for(var i=0, def, cell; (def=inDef[i]); i++){
-			cell = this.addCellDef(inRowIndex, i, def);
-			result.push(cell);
-			this.cells.push(cell);
-			// Check and calculate the sum of all relative widths
-			if(doRel && cell.relWidth){
-				relSum += cell.relWidth;
-			}else if(cell.width){
-				var w = cell.width;
-				if(typeof w == "string" && w.slice(-1) == "%"){
-					pctSum += window.parseInt(w, 10);
-				}else if(w == "auto"){
-					// relative widths doesn't play nice with auto - since we
-					// don't have a way of knowing how much space the auto is 
-					// supposed to take up.
-					doRel = false;
-				}
-			}
-		}
-		if(relSum && doRel){
-			// We have some kind of relWidths specified - so change them to %
-			dojo.forEach(result, function(cell){
-				if(cell.relWidth){
-					cell.width = cell.unitWidth = ((cell.relWidth / relSum) * (100 - pctSum)) + "%";
-				}
-			});
-		}
-		return result;
-	
-	},
-
-	addRowsDef: function(inDef){
-		var result = [];
-		if(dojo.isArray(inDef)){
-			if(dojo.isArray(inDef[0])){
-				for(var i=0, row; inDef && (row=inDef[i]); i++){
-					result.push(this.addRowDef(i, row));
-				}
-			}else{
-				result.push(this.addRowDef(0, inDef));
-			}
-		}
-		return result;	
-	},
-	
-	addViewDef: function(inDef){
-		this._defaultCellProps = inDef.defaultCell || {};
-		if(inDef.width && inDef.width == "auto"){
-			delete inDef.width;
-		}
-		return dojo.mixin({}, inDef, {cells: this.addRowsDef(inDef.rows || inDef.cells)});
-	},
-	
-	setStructure: function(inStructure){
-		this.fieldIndex = 0;
-		this.cells = [];
-		var s = this.structure = [];
-
-		if(this.grid.rowSelector){
-			var sel = { type: dojox._scopeName + ".grid._RowSelector" };
-
-			if(dojo.isString(this.grid.rowSelector)){
-				var width = this.grid.rowSelector;
-
-				if(width == "false"){
-					sel = null;
-				}else if(width != "true"){
-					sel['width'] = width;
-				}
-			}else{
-				if(!this.grid.rowSelector){
-					sel = null;
-				}
-			}
-
-			if(sel){
-				s.push(this.addViewDef(sel));
-			}
-		}
-
-		var isCell = function(def){
-			return ("name" in def || "field" in def || "get" in def);
-		};
-
-		var isRowDef = function(def){
-			if(dojo.isArray(def)){
-				if(dojo.isArray(def[0]) || isCell(def[0])){
-					return true;
-				}
-			}
-			return false;
-		};
-
-		var isView = function(def){
-			return (def !== null && dojo.isObject(def) &&
-					("cells" in def || "rows" in def || ("type" in def && !isCell(def))));
-		};
-
-		if(dojo.isArray(inStructure)){
-			var hasViews = false;
-			for(var i=0, st; (st=inStructure[i]); i++){
-				if(isView(st)){
-					hasViews = true;
-					break;
-				}
-			}
-			if(!hasViews){
-				s.push(this.addViewDef({ cells: inStructure }));
-			}else{
-				for(i=0; (st=inStructure[i]); i++){
-					if(isRowDef(st)){
-						s.push(this.addViewDef({ cells: st }));
-					}else if(isView(st)){
-						s.push(this.addViewDef(st));
-					}
-				}
-			}
-		}else if(isView(inStructure)){
-			// it's a view object
-			s.push(this.addViewDef(inStructure));
-		}
-
-		this.cellCount = this.cells.length;
-		this.grid.setupHeaderMenu();
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.grid._ViewManager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid._ViewManager"] = true;
-dojo.provide("dojox.grid._ViewManager");
-
-dojo.declare('dojox.grid._ViewManager', null, {
-	// summary:
-	//		A collection of grid views. Owned by grid and used internally for managing grid views.
-	// description:
-	//		Grid creates views automatically based on grid's layout structure.
-	//		Users should typically not need to access individual views or the views collection directly.
-	constructor: function(inGrid){
-		this.grid = inGrid;
-	},
-
-	defaultWidth: 200,
-
-	views: [],
-
-	// operations
-	resize: function(){
-		this.onEach("resize");
-	},
-
-	render: function(){
-		this.onEach("render");
-	},
-
-	// views
-	addView: function(inView){
-		inView.idx = this.views.length;
-		this.views.push(inView);
-	},
-
-	destroyViews: function(){
-		for(var i=0, v; v=this.views[i]; i++){
-			v.destroy();
-		}
-		this.views = [];
-	},
-
-	getContentNodes: function(){
-		var nodes = [];
-		for(var i=0, v; v=this.views[i]; i++){
-			nodes.push(v.contentNode);
-		}
-		return nodes;
-	},
-
-	forEach: function(inCallback){
-		for(var i=0, v; v=this.views[i]; i++){
-			inCallback(v, i);
-		}
-	},
-
-	onEach: function(inMethod, inArgs){
-		inArgs = inArgs || [];
-		for(var i=0, v; v=this.views[i]; i++){
-			if(inMethod in v){
-				v[inMethod].apply(v, inArgs);
-			}
-		}
-	},
-
-	// layout
-	normalizeHeaderNodeHeight: function(){
-		var rowNodes = [];
-		for(var i=0, v; (v=this.views[i]); i++){
-			if(v.headerContentNode.firstChild){
-				rowNodes.push(v.headerContentNode);
-			}
-		}
-		this.normalizeRowNodeHeights(rowNodes);
-	},
-
-	normalizeRowNodeHeights: function(inRowNodes){
-		var h = 0;
-		var currHeights = [];
-		if(this.grid.rowHeight){
-			h = this.grid.rowHeight;
-		}else{
-			if(inRowNodes.length <= 1){ 
-				// no need to normalize if we are the only one...
-				return; 
-			}
-			for(var i=0, n; (n=inRowNodes[i]); i++){
-				// We only care about the height - so don't use marginBox.  This
-				// depends on the container not having any margin (which it shouldn't)
-				// Also - we only look up the height if the cell doesn't have the
-				// dojoxGridNonNormalizedCell class (like for row selectors)
-				if(!dojo.hasClass(n, "dojoxGridNonNormalizedCell")){
-					currHeights[i] = n.firstChild.offsetHeight;
-					h =  Math.max(h, currHeights[i]);
-				}
-			}
-			h = (h >= 0 ? h : 0);
-	
-			//Work around odd FF3 rendering bug: #8864.
-			//A one px increase fixes FireFox 3's rounding bug for fractional font sizes.
-			if(dojo.isMoz && h){h++;}
-		}
-		for(i=0; (n=inRowNodes[i]); i++){
-			if(currHeights[i] != h){
-				n.firstChild.style.height = h + "px";
-			}
-		}
-	},
-	
-	resetHeaderNodeHeight: function(){
-		for(var i=0, v, n; (v=this.views[i]); i++){
-			n = v.headerContentNode.firstChild;
-			if(n){
-				n.style.height = "";
-			}
-		}
-	},
-
-	renormalizeRow: function(inRowIndex){
-		var rowNodes = [];
-		for(var i=0, v, n; (v=this.views[i])&&(n=v.getRowNode(inRowIndex)); i++){
-			n.firstChild.style.height = '';
-			rowNodes.push(n);
-		}
-		this.normalizeRowNodeHeights(rowNodes);
-	},
-
-	getViewWidth: function(inIndex){
-		return this.views[inIndex].getWidth() || this.defaultWidth;
-	},
-
-	// must be called after view widths are properly set or height can be miscalculated
-	// if there are flex columns
-	measureHeader: function(){
-		// need to reset view header heights so they are properly measured.
-		this.resetHeaderNodeHeight();
-		this.forEach(function(inView){
-			inView.headerContentNode.style.height = '';
-		});
-		var h = 0;
-		// calculate maximum view header height
-		this.forEach(function(inView){
-			h = Math.max(inView.headerNode.offsetHeight, h);
-		});
-		return h;
-	},
-
-	measureContent: function(){
-		var h = 0;
-		this.forEach(function(inView){
-			h = Math.max(inView.domNode.offsetHeight, h);
-		});
-		return h;
-	},
-
-	findClient: function(inAutoWidth){
-		// try to use user defined client
-		var c = this.grid.elasticView || -1;
-		// attempt to find implicit client
-		if(c < 0){
-			for(var i=1, v; (v=this.views[i]); i++){
-				if(v.viewWidth){
-					for(i=1; (v=this.views[i]); i++){
-						if(!v.viewWidth){
-							c = i;
-							break;
-						}
-					}
-					break;
-				}
-			}
-		}
-		// client is in the middle by default
-		if(c < 0){
-			c = Math.floor(this.views.length / 2);
-		}
-		return c;
-	},
-
-	arrange: function(l, w){
-		var i, v, vw, len = this.views.length;
-		// find the client
-		var c = (w <= 0 ? len : this.findClient());
-		// layout views
-		var setPosition = function(v, l){
-			var ds = v.domNode.style;
-			var hs = v.headerNode.style;
-
-			if(!dojo._isBodyLtr()){
-				ds.right = l + 'px';
-				// fixed rtl, the scrollbar is on the right side in FF
-				if (dojo.isMoz) {
-					hs.right = l + v.getScrollbarWidth() + 'px';
-					hs.width = parseInt(hs.width, 10) - v.getScrollbarWidth() + 'px';
-				}else{
-					hs.right = l + 'px';					
-				}
-			}else{
-				ds.left = l + 'px';
-				hs.left = l + 'px';
-			}
-			ds.top = 0 + 'px';
-			hs.top = 0;
-		};
-		// for views left of the client
-		//BiDi TODO: The left and right should not appear in BIDI environment. Should be replaced with 
-		//leading and tailing concept.
-		for(i=0; (v=this.views[i])&&(i<c); i++){
-			// get width
-			vw = this.getViewWidth(i);
-			// process boxes
-			v.setSize(vw, 0);
-			setPosition(v, l);
-			if(v.headerContentNode && v.headerContentNode.firstChild){
-				vw = v.getColumnsWidth()+v.getScrollbarWidth();
-			}else{
-				vw = v.domNode.offsetWidth;
-			}
-			// update position
-			l += vw;
-		}
-		// next view (is the client, i++ == c) 
-		i++;
-		// start from the right edge
-		var r = w;
-		// for views right of the client (iterated from the right)
-		for(var j=len-1; (v=this.views[j])&&(i<=j); j--){
-			// get width
-			vw = this.getViewWidth(j);
-			// set size
-			v.setSize(vw, 0);
-			// measure in pixels
-			vw = v.domNode.offsetWidth;
-			// update position
-			r -= vw;
-			// set position
-			setPosition(v, r);
-		}
-		if(c<len){
-			v = this.views[c];
-			// position the client box between left and right boxes	
-			vw = Math.max(1, r-l);
-			// set size
-			v.setSize(vw + 'px', 0);
-			setPosition(v, l);
-		}
-		return l;
-	},
-
-	// rendering
-	renderRow: function(inRowIndex, inNodes, skipRenorm){
-		var rowNodes = [];
-		for(var i=0, v, n, rowNode; (v=this.views[i])&&(n=inNodes[i]); i++){
-			rowNode = v.renderRow(inRowIndex);
-			n.appendChild(rowNode);
-			rowNodes.push(rowNode);
-		}
-		if(!skipRenorm){
-			this.normalizeRowNodeHeights(rowNodes);
-		}
-	},
-	
-	rowRemoved: function(inRowIndex){
-		this.onEach("rowRemoved", [ inRowIndex ]);
-	},
-	
-	// updating
-	updateRow: function(inRowIndex, skipRenorm){
-		for(var i=0, v; v=this.views[i]; i++){
-			v.updateRow(inRowIndex);
-		}
-		if(!skipRenorm){
-			this.renormalizeRow(inRowIndex);
-		}
-	},
-	
-	updateRowStyles: function(inRowIndex){
-		this.onEach("updateRowStyles", [ inRowIndex ]);
-	},
-	
-	// scrolling
-	setScrollTop: function(inTop){
-		var top = inTop;
-		for(var i=0, v; v=this.views[i]; i++){
-			top = v.setScrollTop(inTop);
-			// Work around IE not firing scroll events that cause header offset
-			// issues to occur.
-			if(dojo.isIE && v.headerNode && v.scrollboxNode){
-				v.headerNode.scrollLeft = v.scrollboxNode.scrollLeft;
-			}
-		}
-		return top;
-		//this.onEach("setScrollTop", [ inTop ]);
-	},
-	
-	getFirstScrollingView: function(){
-		// summary: Returns the first grid view with a scroll bar 
-		for(var i=0, v; (v=this.views[i]); i++){
-			if(v.hasHScrollbar() || v.hasVScrollbar()){
-				return v;
-			}
-		}
-		return null;
-	}
-	
-});
-
-}
-
-if(!dojo._hasResource["dojox.grid._RowManager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid._RowManager"] = true;
-dojo.provide("dojox.grid._RowManager");
-
-(function(){
-	var setStyleText = function(inNode, inStyleText){
-		if(inNode.style.cssText == undefined){
-			inNode.setAttribute("style", inStyleText);
-		}else{
-			inNode.style.cssText = inStyleText;
-		}
-	};
-
-	dojo.declare("dojox.grid._RowManager", null, {
-		//	Stores information about grid rows. Owned by grid and used internally.
-		constructor: function(inGrid){
-			this.grid = inGrid;
-		},
-		linesToEms: 2,
-		overRow: -2,
-		// styles
-		prepareStylingRow: function(inRowIndex, inRowNode){
-			return {
-				index: inRowIndex, 
-				node: inRowNode,
-				odd: Boolean(inRowIndex&1),
-				selected: !!this.grid.selection.isSelected(inRowIndex),
-				over: this.isOver(inRowIndex),
-				customStyles: "",
-				customClasses: "dojoxGridRow"
-			};
-		},
-		styleRowNode: function(inRowIndex, inRowNode){
-			var row = this.prepareStylingRow(inRowIndex, inRowNode);
-			this.grid.onStyleRow(row);
-			this.applyStyles(row);
-		},
-		applyStyles: function(inRow){
-			var i = inRow;
-
-			i.node.className = i.customClasses;
-			var h = i.node.style.height;
-			setStyleText(i.node, i.customStyles + ';' + (i.node._style||''));
-			i.node.style.height = h;
-		},
-		updateStyles: function(inRowIndex){
-			this.grid.updateRowStyles(inRowIndex);
-		},
-		// states and events
-		setOverRow: function(inRowIndex){
-			var last = this.overRow;
-			this.overRow = inRowIndex;
-			if((last!=this.overRow)&&(dojo.isString(last) || last >= 0)){
-				this.updateStyles(last);
-			}
-			this.updateStyles(this.overRow);
-		},
-		isOver: function(inRowIndex){
-			return (this.overRow == inRowIndex && !dojo.hasClass(this.grid.domNode, "dojoxGridColumnResizing"));
-		}
-	});
-})();
-
-}
-
-if(!dojo._hasResource["dojox.grid._FocusManager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid._FocusManager"] = true;
-dojo.provide("dojox.grid._FocusManager");
-
-
-
-// focus management
-dojo.declare("dojox.grid._FocusManager", null, {
-	// summary:
-	//	Controls grid cell focus. Owned by grid and used internally for focusing.
-	//	Note: grid cell actually receives keyboard input only when cell is being edited.
-	constructor: function(inGrid){
-		this.grid = inGrid;
-		this.cell = null;
-		this.rowIndex = -1;
-		this._connects = [];
-		this.headerMenu = this.grid.headerMenu;
-		this._connects.push(dojo.connect(this.grid.domNode, "onfocus", this, "doFocus"));
-		this._connects.push(dojo.connect(this.grid.domNode, "onblur", this, "doBlur"));
-		this._connects.push(dojo.connect(this.grid.domNode, "oncontextmenu", this, "doContextMenu"));
-		this._connects.push(dojo.connect(this.grid.lastFocusNode, "onfocus", this, "doLastNodeFocus"));
-		this._connects.push(dojo.connect(this.grid.lastFocusNode, "onblur", this, "doLastNodeBlur"));
-		this._connects.push(dojo.connect(this.grid,"_onFetchComplete", this, "_delayedCellFocus"));
-		this._connects.push(dojo.connect(this.grid,"postrender", this, "_delayedHeaderFocus"));
-	},
-	destroy: function(){
-		dojo.forEach(this._connects, dojo.disconnect);
-		delete this.grid;
-		delete this.cell;
-	},
-	_colHeadNode: null,
-	_colHeadFocusIdx: null,
-	_contextMenuBindNode: null,
-	tabbingOut: false,
-	focusClass: "dojoxGridCellFocus",
-	focusView: null,
-	initFocusView: function(){
-		this.focusView = this.grid.views.getFirstScrollingView() || this.focusView;
-		this._initColumnHeaders();
-	},
-	isFocusCell: function(inCell, inRowIndex){
-		// summary:
-		//	states if the given cell is focused
-		// inCell: object
-		//	grid cell object
-		// inRowIndex: int
-		//	grid row index
-		// returns:
-		//	true of the given grid cell is focused
-		return (this.cell == inCell) && (this.rowIndex == inRowIndex);
-	},
-	isLastFocusCell: function(){
-		if(this.cell){
-			return (this.rowIndex == this.grid.rowCount-1) && (this.cell.index == this.grid.layout.cellCount-1);
-		}
-		return false;
-	},
-	isFirstFocusCell: function(){
-		if(this.cell){
-			return (this.rowIndex === 0) && (this.cell.index === 0);
-		}
-		return false;
-	},
-	isNoFocusCell: function(){
-		return (this.rowIndex < 0) || !this.cell;
-	},
-	isNavHeader: function(){
-		// summary:
-		//	states whether currently navigating among column headers.
-		// returns:
-		//	true if focus is on a column header; false otherwise. 
-		return (!!this._colHeadNode);
-	},
-	getHeaderIndex: function(){
-		// summary:
-		//	if one of the column headers currently has focus, return its index.
-		// returns:
-		//	index of the focused column header, or -1 if none have focus.
-		if(this._colHeadNode){
-			return dojo.indexOf(this._findHeaderCells(), this._colHeadNode);
-		}else{
-			return -1;
-		}
-	},
-	_focusifyCellNode: function(inBork){
-		var n = this.cell && this.cell.getNode(this.rowIndex);
-		if(n){
-			dojo.toggleClass(n, this.focusClass, inBork);
-			if(inBork){
-				var sl = this.scrollIntoView();
-				try{
-					if(!this.grid.edit.isEditing()){
-						dojox.grid.util.fire(n, "focus");
-						if(sl){ this.cell.view.scrollboxNode.scrollLeft = sl; }
-					}
-				}catch(e){}
-			}
-		}
-	},
-	_delayedCellFocus: function(){
-		if(this.isNavHeader()||!this.grid._focused){
-				return;
-		}
-		var n = this.cell && this.cell.getNode(this.rowIndex);
-		if(n){ 
-			try{
-				if(!this.grid.edit.isEditing()){
-					dojo.toggleClass(n, this.focusClass, true);
-					this.blurHeader();
-					dojox.grid.util.fire(n, "focus");
-				}
-			} 
-			catch(e){}
-		}
-	},
-	_delayedHeaderFocus: function(){
-		if(this.isNavHeader()){
-			this.focusHeader();
-			this.grid.domNode.focus();
-		}
-	},
-	_initColumnHeaders: function(){
-		var headers = this._findHeaderCells();
-		for(var i = 0; i < headers.length; i++){
-			this._connects.push(dojo.connect(headers[i], "onfocus", this, "doColHeaderFocus"));
-			this._connects.push(dojo.connect(headers[i], "onblur", this, "doColHeaderBlur"));
-		}
-	},
-	_findHeaderCells: function(){
-		// This should be a one liner:
-		//	dojo.query("th[tabindex=-1]", this.grid.viewsHeaderNode);
-		// But there is a bug in dojo.query() for IE -- see trac #7037.
-		var allHeads = dojo.query("th", this.grid.viewsHeaderNode);
-		var headers = [];
-		for (var i = 0; i < allHeads.length; i++){
-			var aHead = allHeads[i];
-			var hasTabIdx = dojo.hasAttr(aHead, "tabIndex");
-			var tabindex = dojo.attr(aHead, "tabIndex");
-			if (hasTabIdx && tabindex < 0) {
-				headers.push(aHead);
-			}
-		}
-		return headers;
-	},
-	_setActiveColHeader: function(/*Node*/colHeaderNode, /*Integer*/colFocusIdx, /*Integer*/ prevColFocusIdx){
-		//console.log("setActiveColHeader() - colHeaderNode:colFocusIdx:prevColFocusIdx = " + colHeaderNode + ":" + colFocusIdx + ":" + prevColFocusIdx);
-		dojo.attr(this.grid.domNode, "aria-activedescendant",colHeaderNode.id);
-		if (prevColFocusIdx != null && prevColFocusIdx >= 0 && prevColFocusIdx != colFocusIdx){
-			dojo.toggleClass(this._findHeaderCells()[prevColFocusIdx],this.focusClass,false);
-		}
-		dojo.toggleClass(colHeaderNode,this.focusClass, true);
-		this._colHeadNode = colHeaderNode;
-		this._colHeadFocusIdx = colFocusIdx;
-		this._scrollHeader(this._colHeadFocusIdx);
-	},
-	scrollIntoView: function(){
-		var info = (this.cell ? this._scrollInfo(this.cell) : null);
-		if(!info || !info.s){
-			return null;
-		}
-		var rt = this.grid.scroller.findScrollTop(this.rowIndex);
-		// place cell within horizontal view
-		if(info.n && info.sr){
-			if(info.n.offsetLeft + info.n.offsetWidth > info.sr.l + info.sr.w){
-				info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
-			}else if(info.n.offsetLeft < info.sr.l){
-				info.s.scrollLeft = info.n.offsetLeft;
-			}
-		}
-		// place cell within vertical view
-		if(info.r && info.sr){
-			if(rt + info.r.offsetHeight > info.sr.t + info.sr.h){
-				this.grid.setScrollTop(rt + info.r.offsetHeight - info.sr.h);
-			}else if(rt < info.sr.t){
-				this.grid.setScrollTop(rt);
-			}
-		}
-
-		return info.s.scrollLeft;
-	},
-	_scrollInfo: function(cell, domNode){
-		if(cell){
-			var cl = cell,
-				sbn = cl.view.scrollboxNode,
-				sbnr = {
-					w: sbn.clientWidth,
-					l: sbn.scrollLeft,
-					t: sbn.scrollTop,
-					h: sbn.clientHeight
-				},
-				rn = cl.view.getRowNode(this.rowIndex);
-			return {
-				c: cl,
-				s: sbn,
-				sr: sbnr,
-				n: (domNode ? domNode : cell.getNode(this.rowIndex)),
-				r: rn
-			};
-		}
-		return null;
-	},
-	_scrollHeader: function(currentIdx){
-		var info = null;
-		if(this._colHeadNode){
-			var cell = this.grid.getCell(currentIdx);
-			info = this._scrollInfo(cell, cell.getNode(0));
-		}
-		if(info && info.s && info.sr && info.n){
-			// scroll horizontally as needed.
-			var scroll = info.sr.l + info.sr.w;
-			if(info.n.offsetLeft + info.n.offsetWidth > scroll){
-				info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
-			}else if(info.n.offsetLeft < info.sr.l){
-				info.s.scrollLeft = info.n.offsetLeft;
-			}else if(dojo.isIE <= 7 && cell && cell.view.headerNode){
-				// Trac 7158: scroll dojoxGridHeader for IE7 and lower
-				cell.view.headerNode.scrollLeft = info.s.scrollLeft;
-			}
-		}
-	},
-	_isHeaderHidden: function(){
-		// summary:
-		//		determine if the grid headers are hidden
-		//		relies on documented technique of setting .dojoxGridHeader { display:none; } 
-		// returns: Boolean
-		//		true if headers are hidden
-		//		false if headers are not hidden
-		
-		var curView = this.focusView;
-		if (!curView){
-			// find one so we can determine if headers are hidden
-			// there is no focusView after adding items to empty grid (test_data_grid_empty.html)
-			for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
-				if(cView.headerNode ){
-					curView=cView;
-					break;		
-				}	
-			}
-		}
-		return (curView && dojo.getComputedStyle(curView.headerNode).display == "none");
-	},
-	colSizeAdjust: function (e, colIdx, delta){ // adjust the column specified by colIdx by the specified delta px
-		var headers = this._findHeaderCells();
-		var view = this.focusView;
-		if (!view) {
-			for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
-				// find first view with a tableMap in order to work with empty grid
-				if(cView.header.tableMap.map ){
-					view=cView;
-					break;		
-				}
-			}
-		}
-		var curHeader = headers[colIdx];
-		if (!view || (colIdx == headers.length-1 && colIdx === 0)){
-			return; // can't adjust single col. grid
-		}	
-		view.content.baseDecorateEvent(e);
-		// need to adjust event with header cell info since focus is no longer on header cell
-		e.cellNode = curHeader; //this.findCellTarget(e.target, e.rowNode);
-		e.cellIndex = view.content.getCellNodeIndex(e.cellNode);
-		e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
-		if (view.header.canResize(e)){ 
-			var deltaObj = {
-				l: delta
-			};
-			var drag = view.header.colResizeSetup(e,false);
-			view.header.doResizeColumn(drag, null, deltaObj);
-			view.update();
-		}
-	},
-	styleRow: function(inRow){
-		return;
-	},
-	setFocusIndex: function(inRowIndex, inCellIndex){
-		// summary:
-		//	focuses the given grid cell
-		// inRowIndex: int
-		//	grid row index
-		// inCellIndex: int
-		//	grid cell index
-		this.setFocusCell(this.grid.getCell(inCellIndex), inRowIndex);
-	},
-	setFocusCell: function(inCell, inRowIndex){
-		// summary:
-		//	focuses the given grid cell
-		// inCell: object
-		//	grid cell object
-		// inRowIndex: int
-		//	grid row index
-		if(inCell && !this.isFocusCell(inCell, inRowIndex)){
-			this.tabbingOut = false;
-			if (this._colHeadNode){
-				this.blurHeader();
-			}
-			this._colHeadNode = this._colHeadFocusIdx = null;
-			this.focusGridView();
-			this._focusifyCellNode(false);
-			this.cell = inCell;
-			this.rowIndex = inRowIndex;
-			this._focusifyCellNode(true);
-		}
-		// even if this cell isFocusCell, the document focus may need to be rejiggered
-		// call opera on delay to prevent keypress from altering focus
-		if(dojo.isOpera){
-			setTimeout(dojo.hitch(this.grid, 'onCellFocus', this.cell, this.rowIndex), 1);
-		}else{
-			this.grid.onCellFocus(this.cell, this.rowIndex);
-		}
-	},
-	next: function(){
-		// summary:
-		//	focus next grid cell
-		if(this.cell){
-			var row=this.rowIndex, col=this.cell.index+1, cc=this.grid.layout.cellCount-1, rc=this.grid.rowCount-1;
-			if(col > cc){
-				col = 0;
-				row++;
-			}
-			if(row > rc){
-				col = cc;
-				row = rc;
-			}
-			if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
-				var nextCell = this.grid.getCell(col);
-				if (!this.isLastFocusCell() && !nextCell.editable){
-					this.cell=nextCell;
-					this.rowIndex=row;
-					this.next();
-					return;
-				}
-			}
-			this.setFocusIndex(row, col);
-		}
-	},
-	previous: function(){
-		// summary:
-		//	focus previous grid cell
-		if(this.cell){
-			var row=(this.rowIndex || 0), col=(this.cell.index || 0) - 1;
-			if(col < 0){
-				col = this.grid.layout.cellCount-1;
-				row--;
-			}
-			if(row < 0){
-				row = 0;
-				col = 0;
-			}
-			if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
-				var prevCell = this.grid.getCell(col);
-				if (!this.isFirstFocusCell() && !prevCell.editable){
-					this.cell=prevCell;
-					this.rowIndex=row;
-					this.previous();
-					return;
-				}
-			}
-			this.setFocusIndex(row, col);
-		}
-	},
-	move: function(inRowDelta, inColDelta) {
-		// summary:
-		//	focus grid cell or  simulate focus to column header based on position relative to current focus
-		// inRowDelta: int
-		// vertical distance from current focus
-		// inColDelta: int
-		// horizontal distance from current focus
-
-		var colDir = inColDelta < 0 ? -1 : 1;
-		// Handle column headers.
-		if(this.isNavHeader()){
-			var headers = this._findHeaderCells();
-			var savedIdx = currentIdx = dojo.indexOf(headers, this._colHeadNode);
-			currentIdx += inColDelta;
-			while(currentIdx >=0 && currentIdx < headers.length && headers[currentIdx].style.display == "none"){
-				// skip over hidden column headers
-				currentIdx += colDir;
-			}
-			if((currentIdx >= 0) && (currentIdx < headers.length)){
-				this._setActiveColHeader(headers[currentIdx],currentIdx, savedIdx);
-			}
-		}else{
-			if(this.cell){
-				// Handle grid proper.
-				var sc = this.grid.scroller,
-					r = this.rowIndex,
-					rc = this.grid.rowCount-1,
-					row = Math.min(rc, Math.max(0, r+inRowDelta));
-				if(inRowDelta){
-					if(inRowDelta>0){
-						if(row > sc.getLastPageRow(sc.page)){
-							//need to load additional data, let scroller do that
-							this.grid.setScrollTop(this.grid.scrollTop+sc.findScrollTop(row)-sc.findScrollTop(r));
-						}
-					}else if(inRowDelta<0){
-						if(row <= sc.getPageRow(sc.page)){
-							//need to load additional data, let scroller do that
-							this.grid.setScrollTop(this.grid.scrollTop-sc.findScrollTop(r)-sc.findScrollTop(row));
-						}
-					}
-				}
-				var cc = this.grid.layout.cellCount-1,
-				i = this.cell.index,
-				col = Math.min(cc, Math.max(0, i+inColDelta));
-				var cell = this.grid.getCell(col);
-				while(col>=0 && col < cc && cell && cell.hidden === true){
-					// skip hidden cells
-					col += colDir;
-					cell = this.grid.getCell(col);
-				}
-				if (!cell || cell.hidden === true){
-					// don't change col if would move to hidden
-					col = i;
-				}
-				this.setFocusIndex(row, col);
-				if(inRowDelta){
-					this.grid.updateRow(r);
-				}
-			}
-		}
-	},
-	previousKey: function(e){
-		if(this.grid.edit.isEditing()){
-			dojo.stopEvent(e);
-			this.previous();
-		}else if(!this.isNavHeader() && !this._isHeaderHidden()) {
-			this.grid.domNode.focus(); // will call doFocus and set focus into header.
-			dojo.stopEvent(e);
-		}else{
-			this.tabOut(this.grid.domNode);
-			if (this._colHeadFocusIdx != null) { // clear grid header focus
-				dojo.toggleClass(this._findHeaderCells()[this._colHeadFocusIdx], this.focusClass, false);
-				this._colHeadFocusIdx = null;
-			}
-			this._focusifyCellNode(false);
-		}
-	},
-	nextKey: function(e) {
-		var isEmpty = (this.grid.rowCount === 0);
-		if(e.target === this.grid.domNode && this._colHeadFocusIdx == null){
-			this.focusHeader();
-			dojo.stopEvent(e);
-		}else if(this.isNavHeader()){
-			// if tabbing from col header, then go to grid proper. 
-			this.blurHeader();
-			if(!this.findAndFocusGridCell()){
-				this.tabOut(this.grid.lastFocusNode);
-			}
-			this._colHeadNode = this._colHeadFocusIdx= null;
-		}else if(this.grid.edit.isEditing()){
-			dojo.stopEvent(e);
-			this.next();
-		}else{
-			this.tabOut(this.grid.lastFocusNode);
-		}
-	},
-	tabOut: function(inFocusNode){
-		this.tabbingOut = true;
-		inFocusNode.focus();
-	},
-	focusGridView: function(){
-		dojox.grid.util.fire(this.focusView, "focus");
-	},
-	focusGrid: function(inSkipFocusCell){
-		this.focusGridView();
-		this._focusifyCellNode(true);
-	},
-	findAndFocusGridCell: function(){
-		// summary:
-		//		find the first focusable grid cell 
-		// returns: Boolean
-		//		true if focus was set to a cell
-		//		false if no cell found to set focus onto
-		
-		var didFocus = true;
-		var isEmpty = (this.grid.rowCount === 0); // If grid is empty this.grid.rowCount == 0
-		if (this.isNoFocusCell() && !isEmpty){
-			var cellIdx = 0;
-			var cell = this.grid.getCell(cellIdx);
-			if (cell.hidden) {
-				// if first cell isn't visible, use _colHeadFocusIdx 
-				// could also use a while loop to find first visible cell - not sure that is worth it
-				cellIdx = this.isNavHeader() ? this._colHeadFocusIdx : 0;
-			}
-			this.setFocusIndex(0, cellIdx);
-		}
-		else if (this.cell && !isEmpty){
-			if (this.focusView && !this.focusView.rowNodes[this.rowIndex]){
-				// if rowNode for current index is undefined (likely as a result of a sort and because of #7304) 
-				// scroll to that row
-				this.grid.scrollToRow(this.rowIndex);
-			}
-			this.focusGrid();
-		}else {
-			didFocus = false;
-		}
-		this._colHeadNode = this._colHeadFocusIdx= null;
-		return didFocus;
-	},
-	focusHeader: function(){
-		var headerNodes = this._findHeaderCells();
-		var saveColHeadFocusIdx = this._colHeadFocusIdx;
-		if (this._isHeaderHidden()){
-			// grid header is hidden, focus a cell
-			this.findAndFocusGridCell();
-		}
-		else if (!this._colHeadFocusIdx) {
-			if (this.isNoFocusCell()) {
-				this._colHeadFocusIdx = 0;
-			}
-			else {
-				this._colHeadFocusIdx = this.cell.index;
-			}
-		}
-		this._colHeadNode = headerNodes[this._colHeadFocusIdx];
-		while(this._colHeadNode && this._colHeadFocusIdx >=0 && this._colHeadFocusIdx < headerNodes.length &&
-				this._colHeadNode.style.display == "none"){
-			// skip over hidden column headers
-			this._colHeadFocusIdx++;
-			this._colHeadNode = headerNodes[this._colHeadFocusIdx];
-		}
-		if(this._colHeadNode && this._colHeadNode.style.display != "none"){
-			// Column header cells know longer receive actual focus.  So, for keyboard invocation of
-			// contextMenu to work, the contextMenu must be bound to the grid.domNode rather than the viewsHeaderNode.
-			// unbind the contextmenu from the viewsHeaderNode and to the grid when header cells are active.  Reset
-			// the binding back to the viewsHeaderNode when header cells are no longer acive (in blurHeader) #10483
-			if (this.headerMenu && this._contextMenuBindNode != this.grid.domNode){
-				this.headerMenu.unBindDomNode(this.grid.viewsHeaderNode);
-				this.headerMenu.bindDomNode(this.grid.domNode);
-				this._contextMenuBindNode = this.grid.domNode;
-			}
-			this._setActiveColHeader(this._colHeadNode, this._colHeadFocusIdx, saveColHeadFocusIdx);
-			this._scrollHeader(this._colHeadFocusIdx);
-			this._focusifyCellNode(false);
-		}else {
-			// all col head nodes are hidden - focus the grid
-			this.findAndFocusGridCell();
-		}
-	},
-	blurHeader: function(){
-		dojo.removeClass(this._colHeadNode, this.focusClass);
-		dojo.removeAttr(this.grid.domNode,"aria-activedescendant");
-		// reset contextMenu onto viewsHeaderNode so right mouse on header will invoke (see focusHeader)
-		if (this.headerMenu && this._contextMenuBindNode == this.grid.domNode) {
-			var viewsHeader = this.grid.viewsHeaderNode;
-			this.headerMenu.unBindDomNode(this.grid.domNode);
-			this.headerMenu.bindDomNode(viewsHeader);
-			this._contextMenuBindNode = viewsHeader;
-		}
-	},
-	doFocus: function(e){
-		// trap focus only for grid dom node
-		if(e && e.target != e.currentTarget){
-			dojo.stopEvent(e);
-			return;
-		}
-		// do not focus for scrolling if grid is about to blur
-		if(!this.tabbingOut){
-			this.focusHeader();
-		}
-		this.tabbingOut = false;
-		dojo.stopEvent(e);
-	},
-	doBlur: function(e){
-		dojo.stopEvent(e);	// FF2
-	},
-	doContextMenu: function(e){
-	//stop contextMenu event if no header Menu to prevent default/browser contextMenu
-		if (!this.headerMenu){
-			dojo.stopEvent(e); 
-		}
-	},
-	doLastNodeFocus: function(e){
-		if (this.tabbingOut){
-			this._focusifyCellNode(false);
-		}else if(this.grid.rowCount >0){
-			if (this.isNoFocusCell()){
-				this.setFocusIndex(0,0);
-			}
-			this._focusifyCellNode(true);
-		}else {
-			this.focusHeader();
-		}
-		this.tabbingOut = false;
-		dojo.stopEvent(e);	 // FF2
-	},
-	doLastNodeBlur: function(e){
-		dojo.stopEvent(e);	 // FF2
-	},
-	doColHeaderFocus: function(e){
-		this._setActiveColHeader(e.target,dojo.attr(e.target, "idx"),this._colHeadFocusIdx);
-		this._scrollHeader(this.getHeaderIndex());
-		dojo.stopEvent(e);
-	},
-	doColHeaderBlur: function(e){
-		dojo.toggleClass(e.target, this.focusClass, false);
-	}		
-});
-
-}
-
-if(!dojo._hasResource["dojox.grid._EditManager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid._EditManager"] = true;
-dojo.provide("dojox.grid._EditManager");
-
-
-
-dojo.declare("dojox.grid._EditManager", null, {
-	// summary:
-	//		Controls grid cell editing process. Owned by grid and used internally for editing.
-	constructor: function(inGrid){
-		// inGrid: dojox.Grid
-		//		The dojox.Grid this editor should be attached to
-		this.grid = inGrid;
-		this.connections = [];
-		if(dojo.isIE){
-			this.connections.push(dojo.connect(document.body, "onfocus", dojo.hitch(this, "_boomerangFocus")));
-		}
-	},
-	
-	info: {},
-
-	destroy: function(){
-		dojo.forEach(this.connections,dojo.disconnect);
-	},
-
-	cellFocus: function(inCell, inRowIndex){
-		// summary:
-		//		Invoke editing when cell is focused
-		// inCell: cell object
-		//		Grid cell object
-		// inRowIndex: Integer
-		//		Grid row index
-		if(this.grid.singleClickEdit || this.isEditRow(inRowIndex)){
-			// if same row or quick editing, edit
-			this.setEditCell(inCell, inRowIndex);
-		}else{
-			// otherwise, apply any pending row edits
-			this.apply();
-		}
-		// if dynamic or static editing...
-		if(this.isEditing() || (inCell && inCell.editable && inCell.alwaysEditing)){
-			// let the editor focus itself as needed
-			this._focusEditor(inCell, inRowIndex);
-		}
-	},
-
-	rowClick: function(e){
-		if(this.isEditing() && !this.isEditRow(e.rowIndex)){
-			this.apply();
-		}
-	},
-
-	styleRow: function(inRow){
-		if(inRow.index == this.info.rowIndex){
-			inRow.customClasses += ' dojoxGridRowEditing';
-		}
-	},
-
-	dispatchEvent: function(e){
-		var c = e.cell, ed = (c && c["editable"]) ? c : 0;
-		return ed && ed.dispatchEvent(e.dispatch, e);
-	},
-
-	// Editing
-	isEditing: function(){
-		// summary:
-		//		Indicates editing state of the grid.
-		// returns: Boolean
-		//	 	True if grid is actively editing
-		return this.info.rowIndex !== undefined;
-	},
-
-	isEditCell: function(inRowIndex, inCellIndex){
-		// summary:
-		//		Indicates if the given cell is being edited.
-		// inRowIndex: Integer
-		//		Grid row index
-		// inCellIndex: Integer
-		//		Grid cell index
-		// returns: Boolean
-		//	 	True if given cell is being edited
-		return (this.info.rowIndex === inRowIndex) && (this.info.cell.index == inCellIndex);
-	},
-
-	isEditRow: function(inRowIndex){
-		// summary:
-		//		Indicates if the given row is being edited.
-		// inRowIndex: Integer
-		//		Grid row index
-		// returns: Boolean
-		//	 	True if given row is being edited
-		return this.info.rowIndex === inRowIndex;
-	},
-
-	setEditCell: function(inCell, inRowIndex){
-		// summary:
-		//		Set the given cell to be edited
-		// inRowIndex: Integer
-		//		Grid row index
-		// inCell: Object
-		//		Grid cell object
-		if(!this.isEditCell(inRowIndex, inCell.index) && this.grid.canEdit && this.grid.canEdit(inCell, inRowIndex)){
-			this.start(inCell, inRowIndex, this.isEditRow(inRowIndex) || inCell.editable);
-		}
-	},
-
-	_focusEditor: function(inCell, inRowIndex){
-		dojox.grid.util.fire(inCell, "focus", [inRowIndex]);
-	},
-
-	focusEditor: function(){
-		if(this.isEditing()){
-			this._focusEditor(this.info.cell, this.info.rowIndex);
-		}
-	},
-
-	// implement fix for focus boomerang effect on IE
-	_boomerangWindow: 500,
-	_shouldCatchBoomerang: function(){
-		return this._catchBoomerang > new Date().getTime();
-	},
-	_boomerangFocus: function(){
-		//console.log("_boomerangFocus");
-		if(this._shouldCatchBoomerang()){
-			// make sure we don't utterly lose focus
-			this.grid.focus.focusGrid();
-			// let the editor focus itself as needed
-			this.focusEditor();
-			// only catch once
-			this._catchBoomerang = 0;
-		}
-	},
-	_doCatchBoomerang: function(){
-		// give ourselves a few ms to boomerang IE focus effects
-		if(dojo.isIE){this._catchBoomerang = new Date().getTime() + this._boomerangWindow;}
-	},
-	// end boomerang fix API
-
-	start: function(inCell, inRowIndex, inEditing){
-		this.grid.beginUpdate();
-		this.editorApply();
-		if(this.isEditing() && !this.isEditRow(inRowIndex)){
-			this.applyRowEdit();
-			this.grid.updateRow(inRowIndex);
-		}
-		if(inEditing){
-			this.info = { cell: inCell, rowIndex: inRowIndex };
-			this.grid.doStartEdit(inCell, inRowIndex); 
-			this.grid.updateRow(inRowIndex);
-		}else{
-			this.info = {};
-		}
-		this.grid.endUpdate();
-		// make sure we don't utterly lose focus
-		this.grid.focus.focusGrid();
-		// let the editor focus itself as needed
-		this._focusEditor(inCell, inRowIndex);
-		// give ourselves a few ms to boomerang IE focus effects
-		this._doCatchBoomerang();
-	},
-
-	_editorDo: function(inMethod){
-		var c = this.info.cell;
-		//c && c.editor && c.editor[inMethod](c, this.info.rowIndex);
-		if(c && c.editable){
-			c[inMethod](this.info.rowIndex);
-		}
-	},
-
-	editorApply: function(){
-		this._editorDo("apply");
-	},
-
-	editorCancel: function(){
-		this._editorDo("cancel");
-	},
-
-	applyCellEdit: function(inValue, inCell, inRowIndex){
-		if(this.grid.canEdit(inCell, inRowIndex)){
-			this.grid.doApplyCellEdit(inValue, inRowIndex, inCell.field);
-		}
-	},
-
-	applyRowEdit: function(){
-		this.grid.doApplyEdit(this.info.rowIndex, this.info.cell.field);
-	},
-
-	apply: function(){
-		// summary:
-		//		Apply a grid edit
-		if(this.isEditing()){
-			this.grid.beginUpdate();
-			this.editorApply();
-			this.applyRowEdit();
-			this.info = {};
-			this.grid.endUpdate();
-			this.grid.focus.focusGrid();
-			this._doCatchBoomerang();
-		}
-	},
-
-	cancel: function(){
-		// summary:
-		//		Cancel a grid edit
-		if(this.isEditing()){
-			this.grid.beginUpdate();
-			this.editorCancel();
-			this.info = {};
-			this.grid.endUpdate();
-			this.grid.focus.focusGrid();
-			this._doCatchBoomerang();
-		}
-	},
-
-	save: function(inRowIndex, inView){
-		// summary:
-		//		Save the grid editing state
-		// inRowIndex: Integer
-		//		Grid row index
-		// inView: Object
-		//		Grid view
-		var c = this.info.cell;
-		if(this.isEditRow(inRowIndex) && (!inView || c.view==inView) && c.editable){
-			c.save(c, this.info.rowIndex);
-		}
-	},
-
-	restore: function(inView, inRowIndex){
-		// summary:
-		//		Restores the grid editing state
-		// inRowIndex: Integer
-		//		Grid row index
-		// inView: Object
-		//		Grid view
-		var c = this.info.cell;
-		if(this.isEditRow(inRowIndex) && c.view == inView && c.editable){
-			c.restore(c, this.info.rowIndex);
-		}
-	}
-});
-
-}
-
-if(!dojo._hasResource['dojox.grid.Selection']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource['dojox.grid.Selection'] = true;
-dojo.provide('dojox.grid.Selection');
-
-dojo.declare("dojox.grid.Selection", null, {
-	// summary:
-	//		Manages row selection for grid. Owned by grid and used internally
-	//		for selection. Override to implement custom selection.
-
-	constructor: function(inGrid){
-		this.grid = inGrid;
-		this.selected = [];
-
-		this.setMode(inGrid.selectionMode);
-	},
-
-	mode: 'extended',
-
-	selected: null,
-	updating: 0,
-	selectedIndex: -1,
-
-	setMode: function(mode){
-		if(this.selected.length){
-			this.deselectAll();
-		}
-		if(mode != 'extended' && mode != 'multiple' && mode != 'single' && mode != 'none'){
-			this.mode = 'extended';
-		}else{
-			this.mode = mode;
-		}
-	},
-
-	onCanSelect: function(inIndex){
-		return this.grid.onCanSelect(inIndex);
-	},
-
-	onCanDeselect: function(inIndex){
-		return this.grid.onCanDeselect(inIndex);
-	},
-
-	onSelected: function(inIndex){
-	},
-
-	onDeselected: function(inIndex){
-	},
-
-	//onSetSelected: function(inIndex, inSelect) { };
-	onChanging: function(){
-	},
-
-	onChanged: function(){
-	},
-
-	isSelected: function(inIndex){
-		if(this.mode == 'none'){
-			return false;
-		}
-		return this.selected[inIndex];
-	},
-
-	getFirstSelected: function(){
-		if(!this.selected.length||this.mode == 'none'){ return -1; }
-		for(var i=0, l=this.selected.length; i<l; i++){
-			if(this.selected[i]){
-				return i;
-			}
-		}
-		return -1;
-	},
-
-	getNextSelected: function(inPrev){
-		if(this.mode == 'none'){ return -1; }
-		for(var i=inPrev+1, l=this.selected.length; i<l; i++){
-			if(this.selected[i]){
-				return i;
-			}
-		}
-		return -1;
-	},
-
-	getSelected: function(){
-		var result = [];
-		for(var i=0, l=this.selected.length; i<l; i++){
-			if(this.selected[i]){
-				result.push(i);
-			}
-		}
-		return result;
-	},
-
-	getSelectedCount: function(){
-		var c = 0;
-		for(var i=0; i<this.selected.length; i++){
-			if(this.selected[i]){
-				c++;
-			}
-		}
-		return c;
-	},
-
-	_beginUpdate: function(){
-		if(this.updating === 0){
-			this.onChanging();
-		}
-		this.updating++;
-	},
-
-	_endUpdate: function(){
-		this.updating--;
-		if(this.updating === 0){
-			this.onChanged();
-		}
-	},
-
-	select: function(inIndex){
-		if(this.mode == 'none'){ return; }
-		if(this.mode != 'multiple'){
-			this.deselectAll(inIndex);
-			this.addToSelection(inIndex);
-		}else{
-			this.toggleSelect(inIndex);
-		}
-	},
-
-	addToSelection: function(inIndex){
-		if(this.mode == 'none'){ return; }
-		if(dojo.isArray(inIndex)){
-			dojo.forEach(inIndex, this.addToSelection, this);
-			return;
-		}
-		inIndex = Number(inIndex);
-		if(this.selected[inIndex]){
-			this.selectedIndex = inIndex;
-		}else{
-			if(this.onCanSelect(inIndex) !== false){
-				this.selectedIndex = inIndex;
-				var rowNode = this.grid.getRowNode(inIndex);
-				if(rowNode){
-					dojo.attr(rowNode,"aria-selected","true");
-				}
-				this._beginUpdate();
-				this.selected[inIndex] = true;
-				//this.grid.onSelected(inIndex);
-				this.onSelected(inIndex);
-				//this.onSetSelected(inIndex, true);
-				this._endUpdate();
-			}
-		}
-	},
-
-	deselect: function(inIndex){
-		if(this.mode == 'none'){ return; }
-		if(dojo.isArray(inIndex)){
-			dojo.forEach(inIndex, this.deselect, this);
-			return;
-		}
-		inIndex = Number(inIndex);
-		if(this.selectedIndex == inIndex){
-			this.selectedIndex = -1;
-		}
-		if(this.selected[inIndex]){
-			if(this.onCanDeselect(inIndex) === false){
-				return;
-			}
-			var rowNode = this.grid.getRowNode(inIndex);
-			if(rowNode){
-				dojo.attr(rowNode,"aria-selected","false");
-			}
-			this._beginUpdate();
-			delete this.selected[inIndex];
-			//this.grid.onDeselected(inIndex);
-			this.onDeselected(inIndex);
-			//this.onSetSelected(inIndex, false);
-			this._endUpdate();
-		}
-	},
-
-	setSelected: function(inIndex, inSelect){
-		this[(inSelect ? 'addToSelection' : 'deselect')](inIndex);
-	},
-
-	toggleSelect: function(inIndex){
-		if(dojo.isArray(inIndex)){
-			dojo.forEach(inIndex, this.toggleSelect, this);
-			return;
-		}
-		this.setSelected(inIndex, !this.selected[inIndex]);
-	},
-
-	_range: function(inFrom, inTo, func){
-		var s = (inFrom >= 0 ? inFrom : inTo), e = inTo;
-		if(s > e){
-			e = s;
-			s = inTo;
-		}
-		for(var i=s; i<=e; i++){
-			func(i);
-		}
-	},
-
-	selectRange: function(inFrom, inTo){
-		this._range(inFrom, inTo, dojo.hitch(this, "addToSelection"));
-	},
-
-	deselectRange: function(inFrom, inTo){
-		this._range(inFrom, inTo, dojo.hitch(this, "deselect"));
-	},
-
-	insert: function(inIndex){
-		this.selected.splice(inIndex, 0, false);
-		if(this.selectedIndex >= inIndex){
-			this.selectedIndex++;
-		}
-	},
-
-	remove: function(inIndex){
-		this.selected.splice(inIndex, 1);
-		if(this.selectedIndex >= inIndex){
-			this.selectedIndex--;
-		}
-	},
-
-	deselectAll: function(inExcept){
-		for(var i in this.selected){
-			if((i!=inExcept)&&(this.selected[i]===true)){
-				this.deselect(i);
-			}
-		}
-	},
-
-	clickSelect: function(inIndex, inCtrlKey, inShiftKey){
-		if(this.mode == 'none'){ return; }
-		this._beginUpdate();
-		if(this.mode != 'extended'){
-			this.select(inIndex);
-		}else{
-			var lastSelected = this.selectedIndex;
-			if(!inCtrlKey){
-				this.deselectAll(inIndex);
-			}
-			if(inShiftKey){
-				this.selectRange(lastSelected, inIndex);
-			}else if(inCtrlKey){
-				this.toggleSelect(inIndex);
-			}else{
-				this.addToSelection(inIndex);
-			}
-		}
-		this._endUpdate();
-	},
-
-	clickSelectEvent: function(e){
-		this.clickSelect(e.rowIndex, dojo.isCopyKey(e), e.shiftKey);
-	},
-
-	clear: function(){
-		this._beginUpdate();
-		this.deselectAll();
-		this._endUpdate();
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.grid._Events"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid._Events"] = true;
-dojo.provide("dojox.grid._Events");
-
-dojo.declare("dojox.grid._Events", null, {
-	// summary:
-	//		_Grid mixin that provides default implementations for grid events.
-	// description: 
-	//		Default synthetic events dispatched for _Grid. dojo.connect to events to
-	//		retain default implementation or override them for custom handling.
-	
-	// cellOverClass: String
-	// 		css class to apply to grid cells over which the cursor is placed.
-	cellOverClass: "dojoxGridCellOver",
-	
-	onKeyEvent: function(e){
-		// summary: top level handler for Key Events
-		this.dispatchKeyEvent(e);
-	},
-
-	onContentEvent: function(e){
-		// summary: Top level handler for Content events
-		this.dispatchContentEvent(e);
-	},
-
-	onHeaderEvent: function(e){
-		// summary: Top level handler for header events
-		this.dispatchHeaderEvent(e);
-	},
-
-	onStyleRow: function(inRow){
-		// summary:
-		//		Perform row styling on a given row. Called whenever row styling is updated.
-		//
-		// inRow: Object
-		// 		Object containing row state information: selected, true if the row is selcted; over:
-		// 		true of the mouse is over the row; odd: true if the row is odd. Use customClasses and
-		// 		customStyles to control row css classes and styles; both properties are strings.
-		//
-		// example: onStyleRow({ selected: true, over:true, odd:false })
-		var i = inRow;
-		i.customClasses += (i.odd?" dojoxGridRowOdd":"") + (i.selected?" dojoxGridRowSelected":"") + (i.over?" dojoxGridRowOver":"");
-		this.focus.styleRow(inRow);
-		this.edit.styleRow(inRow);
-	},
-	
-	onKeyDown: function(e){
-		// summary:
-		// 		Grid key event handler. By default enter begins editing and applies edits, escape cancels an edit,
-		// 		tab, shift-tab, and arrow keys move grid cell focus.
-		if(e.altKey || e.metaKey){
-			return;
-		}
-		var dk = dojo.keys;
-		var colIdx;
-		switch(e.keyCode){
-			case dk.ESCAPE:
-				this.edit.cancel();
-				break;
-			case dk.ENTER:
-				if(!this.edit.isEditing()){
-					colIdx = this.focus.getHeaderIndex();
-					if(colIdx >= 0) {
-						this.setSortIndex(colIdx);
-						break;
-					}else {
-						this.selection.clickSelect(this.focus.rowIndex, dojo.isCopyKey(e), e.shiftKey);
-					}
-					dojo.stopEvent(e);
-				}
-				if(!e.shiftKey){
-					var isEditing = this.edit.isEditing();
-					this.edit.apply();
-					if(!isEditing){
-						this.edit.setEditCell(this.focus.cell, this.focus.rowIndex);
-					}
-				}
-				if (!this.edit.isEditing()){
-					var curView = this.focus.focusView || this.views.views[0];  //if no focusView than only one view
-					curView.content.decorateEvent(e);
-					this.onRowClick(e);
-				}
-				break;
-			case dk.SPACE:
-				if(!this.edit.isEditing()){
-					colIdx = this.focus.getHeaderIndex();
-					if(colIdx >= 0) {
-						this.setSortIndex(colIdx);
-						break;
-					}else {
-						this.selection.clickSelect(this.focus.rowIndex, dojo.isCopyKey(e), e.shiftKey);
-					}
-					dojo.stopEvent(e);
-				}
-				break;
-			case dk.TAB:
-				this.focus[e.shiftKey ? 'previousKey' : 'nextKey'](e);
-				break;
-			case dk.LEFT_ARROW:
-			case dk.RIGHT_ARROW:
-				if(!this.edit.isEditing()){
-					var keyCode = e.keyCode;  // IE seems to lose after stopEvent when modifier keys
-					dojo.stopEvent(e);
-					colIdx = this.focus.getHeaderIndex();
-					if (colIdx >= 0 && (e.shiftKey && e.ctrlKey)){
-						this.focus.colSizeAdjust(e, colIdx, (keyCode == dk.LEFT_ARROW ? -1 : 1)*5);
-					}
-					else{
-						var offset = (keyCode == dk.LEFT_ARROW) ? 1 : -1;
-						if(dojo._isBodyLtr()){ offset *= -1; }
-						this.focus.move(0, offset);
-					}
-				}
-				break;
-			case dk.UP_ARROW:
-				if(!this.edit.isEditing() && this.focus.rowIndex !== 0){
-					dojo.stopEvent(e);
-					this.focus.move(-1, 0);
-				}
-				break;
-			case dk.DOWN_ARROW:
-				if(!this.edit.isEditing() && this.focus.rowIndex+1 != this.rowCount){
-					dojo.stopEvent(e);
-					this.focus.move(1, 0);
-				}
-				break;
-			case dk.PAGE_UP:
-				if(!this.edit.isEditing() && this.focus.rowIndex !== 0){
-					dojo.stopEvent(e);
-					if(this.focus.rowIndex != this.scroller.firstVisibleRow+1){
-						this.focus.move(this.scroller.firstVisibleRow-this.focus.rowIndex, 0);
-					}else{
-						this.setScrollTop(this.scroller.findScrollTop(this.focus.rowIndex-1));
-						this.focus.move(this.scroller.firstVisibleRow-this.scroller.lastVisibleRow+1, 0);
-					}
-				}
-				break;
-			case dk.PAGE_DOWN:
-				if(!this.edit.isEditing() && this.focus.rowIndex+1 != this.rowCount){
-					dojo.stopEvent(e);
-					if(this.focus.rowIndex != this.scroller.lastVisibleRow-1){
-						this.focus.move(this.scroller.lastVisibleRow-this.focus.rowIndex-1, 0);
-					}else{
-						this.setScrollTop(this.scroller.findScrollTop(this.focus.rowIndex+1));
-						this.focus.move(this.scroller.lastVisibleRow-this.scroller.firstVisibleRow-1, 0);
-					}
-				}
-				break;
-			default:
-				break;
-		}
-	},
-	
-	onMouseOver: function(e){
-		// summary:
-		//		Event fired when mouse is over the grid.
-		// e: Event
-		//		Decorated event object contains reference to grid, cell, and rowIndex
-		e.rowIndex == -1 ? this.onHeaderCellMouseOver(e) : this.onCellMouseOver(e);
-	},
-	
-	onMouseOut: function(e){
-		// summary:
-		//		Event fired when mouse moves out of the grid.
-		// e: Event
-		//		Decorated event object that contains reference to grid, cell, and rowIndex
-		e.rowIndex == -1 ? this.onHeaderCellMouseOut(e) : this.onCellMouseOut(e);
-	},
-	
-	onMouseDown: function(e){
-		// summary:
-		//		Event fired when mouse is down inside grid.
-		// e: Event
-		//		Decorated event object that contains reference to grid, cell, and rowIndex
-		e.rowIndex == -1 ? this.onHeaderCellMouseDown(e) : this.onCellMouseDown(e);
-	},
-	
-	onMouseOverRow: function(e){
-		// summary:
-		//		Event fired when mouse is over any row (data or header).
-		// e: Event
-		//		Decorated event object contains reference to grid, cell, and rowIndex
-		if(!this.rows.isOver(e.rowIndex)){
-			this.rows.setOverRow(e.rowIndex);
-			e.rowIndex == -1 ? this.onHeaderMouseOver(e) : this.onRowMouseOver(e);
-		}
-	},
-	onMouseOutRow: function(e){
-		// summary:
-		//		Event fired when mouse moves out of any row (data or header).
-		// e: Event
-		//		Decorated event object contains reference to grid, cell, and rowIndex
-		if(this.rows.isOver(-1)){
-			this.onHeaderMouseOut(e);
-		}else if(!this.rows.isOver(-2)){
-			this.rows.setOverRow(-2);
-			this.onRowMouseOut(e);
-		}
-	},
-	
-	onMouseDownRow: function(e){
-		// summary:
-		//		Event fired when mouse is down inside grid row
-		// e: Event
-		//		Decorated event object that contains reference to grid, cell, and rowIndex
-		if(e.rowIndex != -1)
-			this.onRowMouseDown(e);
-	},
-
-	// cell events
-	onCellMouseOver: function(e){
-		// summary:
-		//		Event fired when mouse is over a cell.
-		// e: Event
-		//		Decorated event object contains reference to grid, cell, and rowIndex
-		if(e.cellNode){
-			dojo.addClass(e.cellNode, this.cellOverClass);
-		}
-	},
-	
-	onCellMouseOut: function(e){
-		// summary:
-		//		Event fired when mouse moves out of a cell.
-		// e: Event
-		//		Decorated event object which contains reference to grid, cell, and rowIndex
-		if(e.cellNode){
-			dojo.removeClass(e.cellNode, this.cellOverClass);
-		}
-	},
-	
-	onCellMouseDown: function(e){
-		// summary:
-		//		Event fired when mouse is down in a header cell.
-		// e: Event
-		// 		Decorated event object which contains reference to grid, cell, and rowIndex
-	},
-
-	onCellClick: function(e){
-		// summary:
-		//		Event fired when a cell is clicked.
-		// e: Event
-		//		Decorated event object which contains reference to grid, cell, and rowIndex
-		this._click[0] = this._click[1];
-		this._click[1] = e;
-		if(!this.edit.isEditCell(e.rowIndex, e.cellIndex)){
-			this.focus.setFocusCell(e.cell, e.rowIndex);
-		}
-		this.onRowClick(e);
-	},
-
-	onCellDblClick: function(e){
-		// summary:
-		//		Event fired when a cell is double-clicked.
-		// e: Event
-		//		Decorated event object contains reference to grid, cell, and rowIndex
-		if(this._click.length > 1 && dojo.isIE){
-			this.edit.setEditCell(this._click[1].cell, this._click[1].rowIndex);
-		}else if(this._click.length > 1 && this._click[0].rowIndex != this._click[1].rowIndex){
-			this.edit.setEditCell(this._click[0].cell, this._click[0].rowIndex);
-		}else{
-			this.edit.setEditCell(e.cell, e.rowIndex);
-		}
-		this.onRowDblClick(e);
-	},
-
-	onCellContextMenu: function(e){
-		// summary:
-		//		Event fired when a cell context menu is accessed via mouse right click.
-		// e: Event
-		//		Decorated event object which contains reference to grid, cell, and rowIndex
-		this.onRowContextMenu(e);
-	},
-
-	onCellFocus: function(inCell, inRowIndex){
-		// summary:
-		//		Event fired when a cell receives focus.
-		// inCell: Object
-		//		Cell object containing properties of the grid column.
-		// inRowIndex: Integer
-		//		Index of the grid row
-		this.edit.cellFocus(inCell, inRowIndex);
-	},
-
-	// row events
-	onRowClick: function(e){
-		// summary:
-		//		Event fired when a row is clicked.
-		// e: Event
-		//		Decorated event object which contains reference to grid, cell, and rowIndex
-		this.edit.rowClick(e);
-		this.selection.clickSelectEvent(e);
-	},
-
-	onRowDblClick: function(e){
-		// summary:
-		//		Event fired when a row is double clicked.
-		// e: Event
-		//		decorated event object which contains reference to grid, cell, and rowIndex
-	},
-
-	onRowMouseOver: function(e){
-		// summary:
-		//		Event fired when mouse moves over a data row.
-		// e: Event
-		//		Decorated event object which contains reference to grid, cell, and rowIndex
-	},
-
-	onRowMouseOut: function(e){
-		// summary:
-		//		Event fired when mouse moves out of a data row.
-		// e: Event
-		// 		Decorated event object contains reference to grid, cell, and rowIndex
-	},
-	
-	onRowMouseDown: function(e){
-		// summary:
-		//		Event fired when mouse is down in a row.
-		// e: Event
-		// 		Decorated event object which contains reference to grid, cell, and rowIndex
-	},
-
-	onRowContextMenu: function(e){
-		// summary:
-		//		Event fired when a row context menu is accessed via mouse right click.
-		// e: Event
-		// 		Decorated event object which contains reference to grid, cell, and rowIndex
-		dojo.stopEvent(e);
-	},
-
-	// header events
-	onHeaderMouseOver: function(e){
-		// summary:
-		//		Event fired when mouse moves over the grid header.
-		// e: Event
-		// 		Decorated event object contains reference to grid, cell, and rowIndex
-	},
-
-	onHeaderMouseOut: function(e){
-		// summary:
-		//		Event fired when mouse moves out of the grid header.
-		// e: Event
-		// 		Decorated event object which contains reference to grid, cell, and rowIndex
-	},
-
-	onHeaderCellMouseOver: function(e){
-		// summary:
-		//		Event fired when mouse moves over a header cell.
-		// e: Event
-		// 		Decorated event object which contains reference to grid, cell, and rowIndex
-		if(e.cellNode){
-			dojo.addClass(e.cellNode, this.cellOverClass);
-		}
-	},
-
-	onHeaderCellMouseOut: function(e){
-		// summary:
-		//		Event fired when mouse moves out of a header cell.
-		// e: Event
-		// 		Decorated event object which contains reference to grid, cell, and rowIndex
-		if(e.cellNode){
-			dojo.removeClass(e.cellNode, this.cellOverClass);
-		}
-	},
-	
-	onHeaderCellMouseDown: function(e) {
-		// summary:
-		//		Event fired when mouse is down in a header cell.
-		// e: Event
-		// 		Decorated event object which contains reference to grid, cell, and rowIndex
-	},
-
-	onHeaderClick: function(e){
-		// summary:
-		//		Event fired when the grid header is clicked.
-		// e: Event
-		// Decorated event object which contains reference to grid, cell, and rowIndex
-	},
-
-	onHeaderCellClick: function(e){
-		// summary:
-		//		Event fired when a header cell is clicked.
-		// e: Event
-		//		Decorated event object which contains reference to grid, cell, and rowIndex
-		this.setSortIndex(e.cell.index);
-		this.onHeaderClick(e);
-	},
-
-	onHeaderDblClick: function(e){
-		// summary:
-		//		Event fired when the grid header is double clicked.
-		// e: Event
-		//		Decorated event object which contains reference to grid, cell, and rowIndex
-	},
-
-	onHeaderCellDblClick: function(e){
-		// summary:
-		//		Event fired when a header cell is double clicked.
-		// e: Event
-		//		Decorated event object which contains reference to grid, cell, and rowIndex
-		this.onHeaderDblClick(e);
-	},
-
-	onHeaderCellContextMenu: function(e){
-		// summary:
-		//		Event fired when a header cell context menu is accessed via mouse right click.
-		// e: Event
-		//		Decorated event object which contains reference to grid, cell, and rowIndex
-		this.onHeaderContextMenu(e);
-	},
-
-	onHeaderContextMenu: function(e){
-		// summary:
-		//		Event fired when the grid header context menu is accessed via mouse right click.
-		// e: Event
-		//		Decorated event object which contains reference to grid, cell, and rowIndex
-		if(!this.headerMenu){
-			dojo.stopEvent(e);
-		}
-	},
-
-	// editing
-	onStartEdit: function(inCell, inRowIndex){
-		// summary:
-		//		Event fired when editing is started for a given grid cell
-		// inCell: Object
-		//		Cell object containing properties of the grid column.
-		// inRowIndex: Integer
-		//		Index of the grid row
-	},
-
-	onApplyCellEdit: function(inValue, inRowIndex, inFieldIndex){
-		// summary:
-		//		Event fired when editing is applied for a given grid cell
-		// inValue: String
-		//		Value from cell editor
-		// inRowIndex: Integer
-		//		Index of the grid row
-		// inFieldIndex: Integer
-		//		Index in the grid's data store
-	},
-
-	onCancelEdit: function(inRowIndex){
-		// summary:
-		//		Event fired when editing is cancelled for a given grid cell
-		// inRowIndex: Integer
-		//		Index of the grid row
-	},
-
-	onApplyEdit: function(inRowIndex){
-		// summary:
-		//		Event fired when editing is applied for a given grid row
-		// inRowIndex: Integer
-		//		Index of the grid row
-	},
-
-	onCanSelect: function(inRowIndex){
-		// summary:
-		//		Event to determine if a grid row may be selected
-		// inRowIndex: Integer
-		//		Index of the grid row
-		// returns: Boolean
-		//		true if the row can be selected
-		return true;
-	},
-
-	onCanDeselect: function(inRowIndex){
-		// summary:
-		//		Event to determine if a grid row may be deselected
-		// inRowIndex: Integer
-		//		Index of the grid row
-		// returns: Boolean
-		//		true if the row can be deselected
-		return true;
-	},
-
-	onSelected: function(inRowIndex){
-		// summary:
-		//		Event fired when a grid row is selected
-		// inRowIndex: Integer
-		//		Index of the grid row
-		this.updateRowStyles(inRowIndex);
-	},
-
-	onDeselected: function(inRowIndex){
-		// summary:
-		//		Event fired when a grid row is deselected
-		// inRowIndex: Integer
-		//		Index of the grid row
-		this.updateRowStyles(inRowIndex);
-	},
-
-	onSelectionChanged: function(){
-	}
-});
-
-}
-
-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["dojox.grid._Grid"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid._Grid"] = true;
-dojo.provide("dojox.grid._Grid");
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-(function(){
-	// NOTE: this is for backwards compatibility with Dojo 1.3
-	if(!dojo.isCopyKey){
-		dojo.isCopyKey = dojo.dnd.getCopyKeyState;
-	}
-	/*=====
-	dojox.grid.__CellDef = function(){
-		//	name: String?
-		//		The text to use in the header of the grid for this cell.
-		//	get: Function?
-		//		function(rowIndex){} rowIndex is of type Integer.  This
-		//		function will be called when a cell	requests data.  Returns the
-		//		unformatted data for the cell.
-		//	value: String?
-		//		If "get" is not specified, this is used as the data for the cell.
-		//	defaultValue: String?
-		//		If "get" and "value" aren't specified or if "get" returns an undefined
-		//		value, this is used as the data for the cell.  "formatter" is not run
-		//		on this if "get" returns an undefined value.
-		//	formatter: Function?
-		//		function(data, rowIndex){} data is of type anything, rowIndex
-		//		is of type Integer.  This function will be called after the cell
-		//		has its data but before it passes it back to the grid to render.
-		//		Returns the formatted version of the cell's data.
-		//	type: dojox.grid.cells._Base|Function?
-		//		TODO
-		//	editable: Boolean?
-		//		Whether this cell should be editable or not.
-		//	hidden: Boolean?
-		//		If true, the cell will not be displayed.
-		//	noresize: Boolean?
-		//		If true, the cell will not be able to be resized.
-		//	width: Integer|String?
-		//		A CSS size.  If it's an Integer, the width will be in em's.
-		//	colSpan: Integer?
-		//		How many columns to span this cell.  Will not work in the first
-		//		sub-row of cells.
-		//	rowSpan: Integer?
-		//		How many sub-rows to span this cell.
-		//	styles: String?
-		//		A string of styles to apply to both the header cell and main
-		//		grid cells.  Must end in a ';'.
-		//	headerStyles: String?
-		//		A string of styles to apply to just the header cell.  Must end
-		//		in a ';'
-		//	cellStyles: String?
-		//		A string of styles to apply to just the main grid cells.  Must
-		//		end in a ';'
-		//	classes: String?
-		//		A space separated list of classes to apply to both the header
-		//		cell and the main grid cells.
-		//	headerClasses: String?
-		//		A space separated list of classes to apply to just the header
-		//		cell.
-		//	cellClasses: String?
-		//		A space separated list of classes to apply to just the main
-		//		grid cells.
-		//	attrs: String?
-		//		A space separated string of attribute='value' pairs to add to
-		//		the header cell element and main grid cell elements.
-		this.name = name;
-		this.value = value;
-		this.get = get;
-		this.formatter = formatter;
-		this.type = type;
-		this.editable = editable;
-		this.hidden = hidden;
-		this.width = width;
-		this.colSpan = colSpan;
-		this.rowSpan = rowSpan;
-		this.styles = styles;
-		this.headerStyles = headerStyles;
-		this.cellStyles = cellStyles;
-		this.classes = classes;
-		this.headerClasses = headerClasses;
-		this.cellClasses = cellClasses;
-		this.attrs = attrs;
-	}
-	=====*/
-
-	/*=====
-	dojox.grid.__ViewDef = function(){
-		//	noscroll: Boolean?
-		//		If true, no scrollbars will be rendered without scrollbars.
-		//	width: Integer|String?
-		//		A CSS size.  If it's an Integer, the width will be in em's. If
-		//		"noscroll" is true, this value is ignored.
-		//	cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
-		//		The structure of the cells within this grid.
-		//	type: String?
-		//		A string containing the constructor of a subclass of
-		//		dojox.grid._View.  If this is not specified, dojox.grid._View
-		//		is used.
-		//	defaultCell: dojox.grid.__CellDef?
-		//		A cell definition with default values for all cells in this view.  If
-		//		a property is defined in a cell definition in the "cells" array and
-		//		this property, the cell definition's property will override this
-		//		property's property.
-		//	onBeforeRow: Function?
-		//		function(rowIndex, cells){} rowIndex is of type Integer, cells
-		//		is of type Array[dojox.grid.__CellDef[]].  This function is called
-		//		before each row of data is rendered.  Before the header is
-		//		rendered, rowIndex will be -1.  "cells" is a reference to the
-		//		internal structure of this view's cells so any changes you make to
-		//		it will persist between calls.
-		//	onAfterRow: Function?
-		//		function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
-		//		is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
-		//		This function is called	after each row of data is rendered.  After the
-		//		header is rendered, rowIndex will be -1.  "cells" is a reference to the
-		//		internal structure of this view's cells so any changes you make to
-		//		it will persist between calls.
-		this.noscroll = noscroll;
-		this.width = width;
-		this.cells = cells;
-		this.type = type;
-		this.defaultCell = defaultCell;
-		this.onBeforeRow = onBeforeRow;
-		this.onAfterRow = onAfterRow;
-	}
-	=====*/
-
-	dojo.declare('dojox.grid._Grid',
-		[ dijit._Widget, dijit._Templated, dojox.grid._Events ],
-		{
-		// summary:
-		// 		A grid widget with virtual scrolling, cell editing, complex rows,
-		// 		sorting, fixed columns, sizeable columns, etc.
-		//
-		//	description:
-		//		_Grid provides the full set of grid features without any
-		//		direct connection to a data store.
-		//
-		//		The grid exposes a get function for the grid, or optionally
-		//		individual columns, to populate cell contents.
-		//
-		//		The grid is rendered based on its structure, an object describing
-		//		column and cell layout.
-		//
-		//	example:
-		//		A quick sample:
-		//
-		//		define a get function
-		//	|	function get(inRowIndex){ // called in cell context
-		//	|		return [this.index, inRowIndex].join(', ');
-		//	|	}
-		//
-		//		define the grid structure:
-		//	|	var structure = [ // array of view objects
-		//	|		{ cells: [// array of rows, a row is an array of cells
-		//	|			[
-		//	|				{ name: "Alpha", width: 6 },
-		//	|				{ name: "Beta" },
-		//	|				{ name: "Gamma", get: get }]
-		//	|		]}
-		//	|	];
-		//
-		//	|	<div id="grid"
-		//	|		rowCount="100" get="get"
-		//	|		structure="structure"
-		//	|		dojoType="dojox.grid._Grid"></div>
-
-		templateString:"<div class=\"dojoxGrid\" hidefocus=\"hidefocus\" wairole=\"grid\" dojoAttachEvent=\"onmouseout:_mouseOut\">\n\t<div class=\"dojoxGridMasterHeader\" dojoAttachPoint=\"viewsHeaderNode\" wairole=\"presentation\"></div>\n\t<div class=\"dojoxGridMasterView\" dojoAttachPoint=\"viewsNode\" wairole=\"presentation\"></div>\n\t<div class=\"dojoxGridMasterMessages\" style=\"display: none;\" dojoAttachPoint=\"messagesNode\"></div>\n\t<span dojoAttachPoint=\"lastFocusNode\" tabindex [...]
-
-		// classTag: String
-		// 		CSS class applied to the grid's domNode
-		classTag: 'dojoxGrid',
-
-		get: function(inRowIndex){
-			// summary: Default data getter.
-			// description:
-			//		Provides data to display in a grid cell. Called in grid cell context.
-			//		So this.cell.index is the column index.
-			// inRowIndex: Integer
-			//		Row for which to provide data
-			// returns:
-			//		Data to display for a given grid cell.
-		},
-
-		// settings
-		// rowCount: Integer
-		//		Number of rows to display.
-		rowCount: 5,
-
-		// keepRows: Integer
-		//		Number of rows to keep in the rendering cache.
-		keepRows: 75,
-
-		// rowsPerPage: Integer
-		//		Number of rows to render at a time.
-		rowsPerPage: 25,
-
-		// autoWidth: Boolean
-		//		If autoWidth is true, grid width is automatically set to fit the data.
-		autoWidth: false,
-		
-		// initialWidth: String
-		//		A css string to use to set our initial width (only used if autoWidth
-		//		is true).  The first rendering of the grid will be this width, any
-		//		resizing of columns, etc will result in the grid switching to 
-		//		autoWidth mode.  Note, this width will override any styling in a
-		//		stylesheet or directly on the node.
-		initialWidth: "",
-
-		// autoHeight: Boolean|Integer
-		//		If autoHeight is true, grid height is automatically set to fit the data.
-		//		If it is an integer, the height will be automatically set to fit the data
-		//		if there are fewer than that many rows - and the height will be set to show
-		//		that many rows if there are more
-		autoHeight: '',
-
-		// rowHeight: Integer
-		//		If rowHeight is set to a positive number, it will define the height of the rows
-		//		in pixels. This can provide a significant performance advantage, since it
-		//		eliminates the need to measure row sizes during rendering, which is one
-		// 		the primary bottlenecks in the DataGrid's performance. 
-		rowHeight: 0,
-		
-		// autoRender: Boolean
-		//		If autoRender is true, grid will render itself after initialization.
-		autoRender: true,
-
-		// defaultHeight: String
-		//		default height of the grid, measured in any valid css unit.
-		defaultHeight: '15em',
-		
-		// height: String
-		//		explicit height of the grid, measured in any valid css unit.  This will be populated (and overridden)
-		//		if the height: css attribute exists on the source node.
-		height: '',
-
-		// structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
-		//		View layout defintion.
-		structure: null,
-
-		// elasticView: Integer
-		//	Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
-		elasticView: -1,
-
-		// singleClickEdit: boolean
-		//		Single-click starts editing. Default is double-click
-		singleClickEdit: false,
-
-		// selectionMode: String
-		//		Set the selection mode of grid's Selection.  Value must be 'single', 'multiple',
-		//		or 'extended'.  Default is 'extended'.
-		selectionMode: 'extended',
-
-		// rowSelector: Boolean|String
-		// 		If set to true, will add a row selector view to this grid.  If set to a CSS width, will add
-		// 		a row selector of that width to this grid.
-		rowSelector: '',
-
-		// columnReordering: Boolean
-		// 		If set to true, will add drag and drop reordering to views with one row of columns.
-		columnReordering: false,
-
-		// headerMenu: dijit.Menu
-		// 		If set to a dijit.Menu, will use this as a context menu for the grid headers.
-		headerMenu: null,
-
-		// placeholderLabel: String
-		// 		Label of placeholders to search for in the header menu to replace with column toggling
-		// 		menu items.
-		placeholderLabel: "GridColumns",
-		
-		// selectable: Boolean
-		//		Set to true if you want to be able to select the text within the grid.
-		selectable: false,
-		
-		// Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
-		_click: null,
-		
-		// loadingMessage: String
-		//  Message that shows while the grid is loading
-		loadingMessage: "<span class='dojoxGridLoading'>${loadingState}</span>",
-
-		// errorMessage: String
-		//  Message that shows when the grid encounters an error loading
-		errorMessage: "<span class='dojoxGridError'>${errorState}</span>",
-
-		// noDataMessage: String
-		//  Message that shows if the grid has no data - wrap it in a 
-		//  span with class 'dojoxGridNoData' if you want it to be
-		//  styled similar to the loading and error messages
-		noDataMessage: "",
-		
-		// escapeHTMLInData: Boolean
-		//		This will escape HTML brackets from the data to prevent HTML from 
-		// 		user-inputted data being rendered with may contain JavaScript and result in 
-		// 		XSS attacks. This is true by default, and it is recommended that it remain 
-		// 		true. Setting this to false will allow data to be displayed in the grid without 
-		// 		filtering, and should be only used if it is known that the data won't contain 
-		// 		malicious scripts. If HTML is needed in grid cells, it is recommended that 
-		// 		you use the formatter function to generate the HTML (the output of 
-		// 		formatter functions is not filtered, even with escapeHTMLInData set to true).
-		escapeHTMLInData: true,	
-		
-		// formatterScope: Object
-		//		An object to execute format functions within.  If not set, the
-		//		format functions will execute within the scope of the cell that
-		//		has a format function.
-		formatterScope: null,
-		
-		// editable: boolean
-		// indicates if the grid contains editable cells, default is false
-		// set to true if editable cell encountered during rendering 
-		editable: false,
-		
-		// private
-		sortInfo: 0,
-		themeable: true,
-		_placeholders: null,
-
-		// _layoutClass: Object
-		//	The class to use for our layout - can be overridden by grid subclasses
-		_layoutClass: dojox.grid._Layout,
-
-		// initialization
-		buildRendering: function(){
-			this.inherited(arguments);
-			// reset get from blank function (needed for markup parsing) to null, if not changed
-			if(this.get == dojox.grid._Grid.prototype.get){
-				this.get = null;
-			}
-			if(!this.domNode.getAttribute('tabIndex')){
-				this.domNode.tabIndex = "0";
-			}
-			this.createScroller();
-			this.createLayout();
-			this.createViews();
-			this.createManagers();
-
-			this.createSelection();
-
-			this.connect(this.selection, "onSelected", "onSelected");
-			this.connect(this.selection, "onDeselected", "onDeselected");
-			this.connect(this.selection, "onChanged", "onSelectionChanged");
-
-			dojox.html.metrics.initOnFontResize();
-			this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
-			dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
-			if (this.selectionMode != "none") {
-				dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "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);
-			if(this.srcNodeRef && this.srcNodeRef.style.height){
-				this.height = this.srcNodeRef.style.height;
-			}
-			// Call this to update our autoheight to start out
-			this._setAutoHeightAttr(this.autoHeight, true);
-			this.lastScrollTop = this.scrollTop = 0;
-		},
-		
-		postCreate: function(){
-			this._placeholders = [];
-			this._setHeaderMenuAttr(this.headerMenu);
-			this._setStructureAttr(this.structure);
-			this._click = [];
-			this.inherited(arguments);
-			if(this.domNode && this.autoWidth && this.initialWidth){
-				this.domNode.style.width = this.initialWidth;
-			}
-			if (this.domNode && !this.editable){
-				// default value for aria-readonly is false, set to true if grid is not editable
-				dojo.attr(this.domNode,"aria-readonly", "true");
-			}
-		},
-
-		destroy: function(){
-			this.domNode.onReveal = null;
-			this.domNode.onSizeChange = null;
-
-			// Fixes IE domNode leak
-			delete this._click;
-
-			this.edit.destroy();
-			delete this.edit;
-
-			this.views.destroyViews();
-			if(this.scroller){
-				this.scroller.destroy();
-				delete this.scroller;
-			}
-			if(this.focus){
-				this.focus.destroy();
-				delete this.focus;
-			}
-			if(this.headerMenu&&this._placeholders.length){
-				dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
-				this.headerMenu.unBindDomNode(this.viewsHeaderNode);
-			}
-			this.inherited(arguments);
-		},
-
-		_setAutoHeightAttr: function(ah, skipRender){
-			// Calculate our autoheight - turn it into a boolean or an integer
-			if(typeof ah == "string"){
-				if(!ah || ah == "false"){
-					ah = false;
-				}else if (ah == "true"){
-					ah = true;
-				}else{
-					ah = window.parseInt(ah, 10);
-				}
-			}
-			if(typeof ah == "number"){
-				if(isNaN(ah)){
-					ah = false;
-				}
-				// Autoheight must be at least 1, if it's a number.  If it's
-				// less than 0, we'll take that to mean "all" rows (same as 
-				// autoHeight=true - if it is equal to zero, we'll take that
-				// to mean autoHeight=false
-				if(ah < 0){
-					ah = true;
-				}else if (ah === 0){
-					ah = false;
-				}
-			}
-			this.autoHeight = ah;
-			if(typeof ah == "boolean"){
-				this._autoHeight = ah;
-			}else if(typeof ah == "number"){
-				this._autoHeight = (ah >= this.attr('rowCount'));
-			}else{
-				this._autoHeight = false;
-			}
-			if(this._started && !skipRender){
-				this.render();
-			}
-		},
-
-		_getRowCountAttr: function(){
-			return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
-				this.invalidated.rowCount : this.rowCount;
-		},
-		
-		textSizeChanged: function(){
-			this.render();
-		},
-
-		sizeChange: function(){
-			this.update();
-		},
-
-		createManagers: function(){
-			// summary:
-			//		create grid managers for various tasks including rows, focus, selection, editing
-
-			// row manager
-			this.rows = new dojox.grid._RowManager(this);
-			// focus manager
-			this.focus = new dojox.grid._FocusManager(this);
-			// edit manager
-			this.edit = new dojox.grid._EditManager(this);
-		},
-
-		createSelection: function(){
-			// summary:	Creates a new Grid selection manager.
-
-			// selection manager
-			this.selection = new dojox.grid.Selection(this);
-		},
-
-		createScroller: function(){
-			// summary: Creates a new virtual scroller
-			this.scroller = new dojox.grid._Scroller();
-			this.scroller.grid = this;
-			this.scroller.renderRow = dojo.hitch(this, "renderRow");
-			this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
-		},
-
-		createLayout: function(){
-			// summary: Creates a new Grid layout
-			this.layout = new this._layoutClass(this);
-			this.connect(this.layout, "moveColumn", "onMoveColumn");
-		},
-
-		onMoveColumn: function(){
-			this.render();
-		},
-		
-		onResizeColumn: function(/*int*/ cellIdx){
-			// Called when a column is resized.
-		},
-
-		// views
-		createViews: function(){
-			this.views = new dojox.grid._ViewManager(this);
-			this.views.createView = dojo.hitch(this, "createView");
-		},
-
-		createView: function(inClass, idx){
-			var c = dojo.getObject(inClass);
-			var view = new c({ grid: this, index: idx });
-			this.viewsNode.appendChild(view.domNode);
-			this.viewsHeaderNode.appendChild(view.headerNode);
-			this.views.addView(view);
-			return view;
-		},
-
-		buildViews: function(){
-			for(var i=0, vs; (vs=this.layout.structure[i]); i++){
-				this.createView(vs.type || dojox._scopeName + ".grid._View", i).setStructure(vs);
-			}
-			this.scroller.setContentNodes(this.views.getContentNodes());
-		},
-
-		_setStructureAttr: function(structure){
-			var s = structure;
-			if(s && dojo.isString(s)){
-				dojo.deprecated("dojox.grid._Grid.attr('structure', 'objVar')", "use dojox.grid._Grid.attr('structure', objVar) instead", "2.0");
-				s=dojo.getObject(s);
-			}
-			this.structure = s;
-			if(!s){
-				if(this.layout.structure){
-					s = this.layout.structure;
-				}else{
-					return;
-				}
-			}
-			this.views.destroyViews();
-			if(s !== this.layout.structure){
-				this.layout.setStructure(s);
-			}
-			this._structureChanged();
-		},
-
-		setStructure: function(/* dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]] */ inStructure){
-			// summary:
-			//		Install a new structure and rebuild the grid.
-			dojo.deprecated("dojox.grid._Grid.setStructure(obj)", "use dojox.grid._Grid.attr('structure', obj) instead.", "2.0");
-			this._setStructureAttr(inStructure);
-		},
-		
-		getColumnTogglingItems: function(){
-			// Summary: returns an array of dijit.CheckedMenuItem widgets that can be
-			//		added to a menu for toggling columns on and off.
-			return dojo.map(this.layout.cells, function(cell){
-				if(!cell.menuItems){ cell.menuItems = []; }
-
-				var self = this;
-				var item = new dijit.CheckedMenuItem({
-					label: cell.name,
-					checked: !cell.hidden,
-					_gridCell: cell,
-					onChange: function(checked){
-						if(self.layout.setColumnVisibility(this._gridCell.index, checked)){
-							var items = this._gridCell.menuItems;
-							if(items.length > 1){
-								dojo.forEach(items, function(item){
-									if(item !== this){
-										item.setAttribute("checked", checked);
-									}
-								}, this);
-							}
-							checked = dojo.filter(self.layout.cells, function(c){
-								if(c.menuItems.length > 1){
-									dojo.forEach(c.menuItems, "item.attr('disabled', false);");
-								}else{
-									c.menuItems[0].attr('disabled', false);
-								}
-								return !c.hidden;
-							});
-							if(checked.length == 1){
-								dojo.forEach(checked[0].menuItems, "item.attr('disabled', true);");
-							}
-						}
-					},
-					destroy: function(){
-						var index = dojo.indexOf(this._gridCell.menuItems, this);
-						this._gridCell.menuItems.splice(index, 1);
-						delete this._gridCell;
-						dijit.CheckedMenuItem.prototype.destroy.apply(this, arguments);
-					}
-				});
-				cell.menuItems.push(item);
-				return item;
-			}, this); // dijit.CheckedMenuItem[]
-		},
-
-		_setHeaderMenuAttr: function(menu){
-			if(this._placeholders && this._placeholders.length){
-				dojo.forEach(this._placeholders, function(p){
-					p.unReplace(true);
-				});
-				this._placeholders = [];
-			}
-			if(this.headerMenu){
-				this.headerMenu.unBindDomNode(this.viewsHeaderNode);
-			}
-			this.headerMenu = menu;
-			if(!menu){ return; }
-
-			this.headerMenu.bindDomNode(this.viewsHeaderNode);
-			if(this.headerMenu.getPlaceholders){
-				this._placeholders = this.headerMenu.getPlaceholders(this.placeholderLabel);
-			}
-		},
-
-		setHeaderMenu: function(/* dijit.Menu */ menu){
-			dojo.deprecated("dojox.grid._Grid.setHeaderMenu(obj)", "use dojox.grid._Grid.attr('headerMenu', obj) instead.", "2.0");
-			this._setHeaderMenuAttr(menu);
-		},
-		
-		setupHeaderMenu: function(){
-			if(this._placeholders && this._placeholders.length){
-				dojo.forEach(this._placeholders, function(p){
-					if(p._replaced){
-						p.unReplace(true);
-					}
-					p.replace(this.getColumnTogglingItems());
-				}, this);
-			}
-		},
-
-		_fetch: function(start){
-			this.setScrollTop(0);
-		},
-
-		getItem: function(inRowIndex){
-			return null;
-		},
-		
-		showMessage: function(message){
-			if(message){
-				this.messagesNode.innerHTML = message;
-				this.messagesNode.style.display = "";
-			}else{
-				this.messagesNode.innerHTML = "";
-				this.messagesNode.style.display = "none";
-			}
-		},
-
-		_structureChanged: function() {
-			this.buildViews();
-			if(this.autoRender && this._started){
-				this.render();
-			}
-		},
-
-		hasLayout: function() {
-			return this.layout.cells.length;
-		},
-
-		// sizing
-		resize: function(changeSize, resultSize){
-			// summary:
-			//		Update the grid's rendering dimensions and resize it
-			
-			// Calling sizeChange calls update() which calls _resize...so let's
-			// save our input values, if any, and use them there when it gets 
-			// called.  This saves us an extra call to _resize(), which can
-			// get kind of heavy.
-			this._pendingChangeSize = changeSize;
-			this._pendingResultSize = resultSize;
-			this.sizeChange();
-		},
-
-		_getPadBorder: function() {
-			this._padBorder = this._padBorder || dojo._getPadBorderExtents(this.domNode);
-			return this._padBorder;
-		},
-
-		_getHeaderHeight: function(){
-			var vns = this.viewsHeaderNode.style, t = vns.display == "none" ? 0 : this.views.measureHeader();
-			vns.height = t + 'px';
-			// header heights are reset during measuring so must be normalized after measuring.
-			this.views.normalizeHeaderNodeHeight();
-			return t;
-		},
-		
-		_resize: function(changeSize, resultSize){
-			// Restore our pending values, if any
-			changeSize = changeSize || this._pendingChangeSize;
-			resultSize = resultSize || this._pendingResultSize;
-			delete this._pendingChangeSize;
-			delete this._pendingResultSize;
-			// if we have set up everything except the DOM, we cannot resize
-			if(!this.domNode){ return; }
-			var pn = this.domNode.parentNode;
-			if(!pn || pn.nodeType != 1 || !this.hasLayout() || pn.style.visibility == "hidden" || pn.style.display == "none"){
-				return;
-			}
-			// useful measurement
-			var padBorder = this._getPadBorder();
-			var hh = undefined;
-			var h;
-			// grid height
-			if(this._autoHeight){
-				this.domNode.style.height = 'auto';
-				this.viewsNode.style.height = '';
-			}else if(typeof this.autoHeight == "number"){
-				h = hh = this._getHeaderHeight();
-				h += (this.scroller.averageRowHeight * this.autoHeight);
-				this.domNode.style.height = h + "px";
-			}else if(this.domNode.clientHeight <= padBorder.h){
-				if(pn == document.body){
-					this.domNode.style.height = this.defaultHeight;
-				}else if(this.height){
-					this.domNode.style.height = this.height;
-				}else{
-					this.fitTo = "parent";
-				}
-			}
-			// if we are given dimensions, size the grid's domNode to those dimensions
-			if(resultSize){
-				changeSize = resultSize;
-			}
-			if(changeSize){
-				dojo.marginBox(this.domNode, changeSize);
-				this.height = this.domNode.style.height;
-				delete this.fitTo;
-			}else if(this.fitTo == "parent"){
-				h = this._parentContentBoxHeight = this._parentContentBoxHeight || dojo._getContentBox(pn).h;
-				this.domNode.style.height = Math.max(0, h) + "px";
-			}
-			
-			var hasFlex = dojo.some(this.views.views, function(v){ return v.flexCells; });
-
-			if(!this._autoHeight && (h || dojo._getContentBox(this.domNode).h) === 0){
-				// We need to hide the header, since the Grid is essentially hidden.
-				this.viewsHeaderNode.style.display = "none";
-			}else{
-				// Otherwise, show the header and give it an appropriate height.
-				this.viewsHeaderNode.style.display = "block";
-				if(!hasFlex && hh === undefined){
-					hh = this._getHeaderHeight();
-				}
-			}
-			if(hasFlex){
-				hh = undefined;
-			}
-
-			// NOTE: it is essential that width be applied before height
-			// Header height can only be calculated properly after view widths have been set.
-			// This is because flex column width is naturally 0 in Firefox.
-			// Therefore prior to width sizing flex columns with spaces are maximally wrapped
-			// and calculated to be too tall.
-			this.adaptWidth();
-			this.adaptHeight(hh);
-
-			this.postresize();
-		},
-
-		adaptWidth: function() {
-			// private: sets width and position for views and update grid width if necessary
-			var doAutoWidth = (!this.initialWidth && this.autoWidth);
-			var w = doAutoWidth ? 0 : this.domNode.clientWidth || (this.domNode.offsetWidth - this._getPadBorder().w),
-				vw = this.views.arrange(1, w);
-			this.views.onEach("adaptWidth");
-			if(doAutoWidth){
-				this.domNode.style.width = vw + "px";
-			}
-		},
-
-		adaptHeight: function(inHeaderHeight){
-			// private: measures and normalizes header height, then sets view heights, and then updates scroller
-			// content extent
-			var t = inHeaderHeight === undefined ? this._getHeaderHeight() : inHeaderHeight;
-			var h = (this._autoHeight ? -1 : Math.max(this.domNode.clientHeight - t, 0) || 0);
-			this.views.onEach('setSize', [0, h]);
-			this.views.onEach('adaptHeight');
-			if(!this._autoHeight){
-				var numScroll = 0, numNoScroll = 0;
-				var noScrolls = dojo.filter(this.views.views, function(v){
-					var has = v.hasHScrollbar();
-					if(has){ numScroll++; }else{ numNoScroll++; }
-					return (!has);
-				});
-				if(numScroll > 0 && numNoScroll > 0){
-					dojo.forEach(noScrolls, function(v){
-						v.adaptHeight(true);
-					});
-				}
-			}
-			if(this.autoHeight === true || h != -1 || (typeof this.autoHeight == "number" && this.autoHeight >= this.attr('rowCount'))){
-				this.scroller.windowHeight = h;
-			}else{
-				this.scroller.windowHeight = Math.max(this.domNode.clientHeight - t, 0);
-			}
-		},
-
-		// startup
-		startup: function(){
-			if(this._started){return;}
-			this.inherited(arguments);
-			if(this.autoRender){
-				this.render();
-			}
-		},
-
-		// render
-		render: function(){
-			// summary:
-			//	Render the grid, headers, and views. Edit and scrolling states are reset. To retain edit and
-			// scrolling states, see Update.
-
-			if(!this.domNode){return;}
-			if(!this._started){return;}
-
-			if(!this.hasLayout()) {
-				this.scroller.init(0, this.keepRows, this.rowsPerPage);
-				return;
-			}
-			//
-			this.update = this.defaultUpdate;
-			this._render();
-		},
-
-		_render: function(){
-			this.scroller.init(this.attr('rowCount'), this.keepRows, this.rowsPerPage);
-			this.prerender();
-			this.setScrollTop(0);
-			this.postrender();
-		},
-
-		prerender: function(){
-			// if autoHeight, make sure scroller knows not to virtualize; everything must be rendered.
-			this.keepRows = this._autoHeight ? 0 : this.keepRows;
-			this.scroller.setKeepInfo(this.keepRows);
-			this.views.render();
-			this._resize();
-		},
-
-		postrender: function(){
-			this.postresize();
-			this.focus.initFocusView();
-			// make rows unselectable
-			dojo.setSelectable(this.domNode, this.selectable);
-		},
-
-		postresize: function(){
-			// views are position absolute, so they do not inflate the parent
-			if(this._autoHeight){
-				var size = Math.max(this.views.measureContent()) + 'px';
-				
-				this.viewsNode.style.height = size;
-			}
-		},
-
-		renderRow: function(inRowIndex, inNodes){
-			// summary: private, used internally to render rows
-			this.views.renderRow(inRowIndex, inNodes, this._skipRowRenormalize);
-		},
-
-		rowRemoved: function(inRowIndex){
-			// summary: private, used internally to remove rows
-			this.views.rowRemoved(inRowIndex);
-		},
-
-		invalidated: null,
-
-		updating: false,
-
-		beginUpdate: function(){
-			// summary:
-			//		Use to make multiple changes to rows while queueing row updating.
-			// NOTE: not currently supporting nested begin/endUpdate calls
-			this.invalidated = [];
-			this.updating = true;
-		},
-
-		endUpdate: function(){
-			// summary:
-			//		Use after calling beginUpdate to render any changes made to rows.
-			this.updating = false;
-			var i = this.invalidated, r;
-			if(i.all){
-				this.update();
-			}else if(i.rowCount != undefined){
-				this.updateRowCount(i.rowCount);
-			}else{
-				for(r in i){
-					this.updateRow(Number(r));
-				}
-			}
-			this.invalidated = [];
-		},
-
-		// update
-		defaultUpdate: function(){
-			// note: initial update calls render and subsequently this function.
-			if(!this.domNode){return;}
-			if(this.updating){
-				this.invalidated.all = true;
-				return;
-			}
-			//this.edit.saveState(inRowIndex);
-			this.lastScrollTop = this.scrollTop;
-			this.prerender();
-			this.scroller.invalidateNodes();
-			this.setScrollTop(this.lastScrollTop);
-			this.postrender();
-			//this.edit.restoreState(inRowIndex);
-		},
-
-		update: function(){
-			// summary:
-			//		Update the grid, retaining edit and scrolling states.
-			this.render();
-		},
-
-		updateRow: function(inRowIndex){
-			// summary:
-			//		Render a single row.
-			// inRowIndex: Integer
-			//		Index of the row to render
-			inRowIndex = Number(inRowIndex);
-			if(this.updating){
-				this.invalidated[inRowIndex]=true;
-			}else{
-				this.views.updateRow(inRowIndex);
-				this.scroller.rowHeightChanged(inRowIndex);
-			}
-		},
-
-		updateRows: function(startIndex, howMany){
-			// summary:
-			//		Render consecutive rows at once.
-			// startIndex: Integer
-			//		Index of the starting row to render
-			// howMany: Integer
-			//		How many rows to update.
-			startIndex = Number(startIndex);
-			howMany = Number(howMany);
-			var i;
-			if(this.updating){
-				for(i=0; i<howMany; i++){
-					this.invalidated[i+startIndex]=true;
-				}
-			}else{
-				for(i=0; i<howMany; i++){
-					this.views.updateRow(i+startIndex, this._skipRowRenormalize);
-				}
-				this.scroller.rowHeightChanged(startIndex);
-			}
-		},
-
-		updateRowCount: function(inRowCount){
-			//summary:
-			//	Change the number of rows.
-			// inRowCount: int
-			//	Number of rows in the grid.
-			if(this.updating){
-				this.invalidated.rowCount = inRowCount;
-			}else{
-				this.rowCount = inRowCount;
-				this._setAutoHeightAttr(this.autoHeight, true);
-				if(this.layout.cells.length){
-					this.scroller.updateRowCount(inRowCount);
-				}
-				this._resize();				
-				if(this.layout.cells.length){
-					this.setScrollTop(this.scrollTop);
-				}
-			}
-		},
-
-		updateRowStyles: function(inRowIndex){
-			// summary:
-			//		Update the styles for a row after it's state has changed.
-			this.views.updateRowStyles(inRowIndex);
-		},
-		getRowNode: function(inRowIndex){
-			// summary:
-			//		find the rowNode that is not a rowSelector
-			if (this.focus.focusView && !(this.focus.focusView instanceof dojox.grid._RowSelector)){
-					return this.focus.focusView.rowNodes[inRowIndex];
-			}else{ // search through views
-				for (var i = 0, cView; (cView = this.views.views[i]); i++) {
-					if (!(cView instanceof dojox.grid._RowSelector)) {
-						return cView.rowNodes[inRowIndex];
-					}
-				}
-			}
-			return null;
-		},
-		rowHeightChanged: function(inRowIndex){
-			// summary:
-			//		Update grid when the height of a row has changed. Row height is handled automatically as rows
-			//		are rendered. Use this function only to update a row's height outside the normal rendering process.
-			// inRowIndex: Integer
-			// 		index of the row that has changed height
-
-			this.views.renormalizeRow(inRowIndex);
-			this.scroller.rowHeightChanged(inRowIndex);
-		},
-
-		// fastScroll: Boolean
-		//		flag modifies vertical scrolling behavior. Defaults to true but set to false for slower
-		//		scroll performance but more immediate scrolling feedback
-		fastScroll: true,
-
-		delayScroll: false,
-
-		// scrollRedrawThreshold: int
-		//	pixel distance a user must scroll vertically to trigger grid scrolling.
-		scrollRedrawThreshold: (dojo.isIE ? 100 : 50),
-
-		// scroll methods
-		scrollTo: function(inTop){
-			// summary:
-			//		Vertically scroll the grid to a given pixel position
-			// inTop: Integer
-			//		vertical position of the grid in pixels
-			if(!this.fastScroll){
-				this.setScrollTop(inTop);
-				return;
-			}
-			var delta = Math.abs(this.lastScrollTop - inTop);
-			this.lastScrollTop = inTop;
-			if(delta > this.scrollRedrawThreshold || this.delayScroll){
-				this.delayScroll = true;
-				this.scrollTop = inTop;
-				this.views.setScrollTop(inTop);
-				if(this._pendingScroll){
-					window.clearTimeout(this._pendingScroll);
-				}
-				var _this = this;
-				this._pendingScroll = window.setTimeout(function(){
-					delete _this._pendingScroll;
-					_this.finishScrollJob();
-				}, 200);
-			}else{
-				this.setScrollTop(inTop);
-			}
-		},
-
-		finishScrollJob: function(){
-			this.delayScroll = false;
-			this.setScrollTop(this.scrollTop);
-		},
-
-		setScrollTop: function(inTop){
-			this.scroller.scroll(this.views.setScrollTop(inTop));
-		},
-
-		scrollToRow: function(inRowIndex){
-			// summary:
-			//		Scroll the grid to a specific row.
-			// inRowIndex: Integer
-			// 		grid row index
-			this.setScrollTop(this.scroller.findScrollTop(inRowIndex) + 1);
-		},
-
-		// styling (private, used internally to style individual parts of a row)
-		styleRowNode: function(inRowIndex, inRowNode){
-			if(inRowNode){
-				this.rows.styleRowNode(inRowIndex, inRowNode);
-			}
-		},
-		
-		// called when the mouse leaves the grid so we can deselect all hover rows
-		_mouseOut: function(e){
-			this.rows.setOverRow(-2);
-		},
-	
-		// cells
-		getCell: function(inIndex){
-			// summary:
-			//		Retrieves the cell object for a given grid column.
-			// inIndex: Integer
-			// 		Grid column index of cell to retrieve
-			// returns:
-			//		a grid cell
-			return this.layout.cells[inIndex];
-		},
-
-		setCellWidth: function(inIndex, inUnitWidth){
-			this.getCell(inIndex).unitWidth = inUnitWidth;
-		},
-
-		getCellName: function(inCell){
-			// summary: Returns the cell name of a passed cell
-			return "Cell " + inCell.index; // String
-		},
-
-		// sorting
-		canSort: function(inSortInfo){
-			// summary:
-			//		Determines if the grid can be sorted
-			// inSortInfo: Integer
-			//		Sort information, 1-based index of column on which to sort, positive for an ascending sort
-			// 		and negative for a descending sort
-			// returns: Boolean
-			//		True if grid can be sorted on the given column in the given direction
-		},
-
-		sort: function(){
-		},
-
-		getSortAsc: function(inSortInfo){
-			// summary:
-			//		Returns true if grid is sorted in an ascending direction.
-			inSortInfo = inSortInfo == undefined ? this.sortInfo : inSortInfo;
-			return Boolean(inSortInfo > 0); // Boolean
-		},
-
-		getSortIndex: function(inSortInfo){
-			// summary:
-			//		Returns the index of the column on which the grid is sorted
-			inSortInfo = inSortInfo == undefined ? this.sortInfo : inSortInfo;
-			return Math.abs(inSortInfo) - 1; // Integer
-		},
-
-		setSortIndex: function(inIndex, inAsc){
-			// summary:
-			// 		Sort the grid on a column in a specified direction
-			// inIndex: Integer
-			// 		Column index on which to sort.
-			// inAsc: Boolean
-			// 		If true, sort the grid in ascending order, otherwise in descending order
-			var si = inIndex +1;
-			if(inAsc != undefined){
-				si *= (inAsc ? 1 : -1);
-			} else if(this.getSortIndex() == inIndex){
-				si = -this.sortInfo;
-			}
-			this.setSortInfo(si);
-		},
-
-		setSortInfo: function(inSortInfo){
-			if(this.canSort(inSortInfo)){
-				this.sortInfo = inSortInfo;
-				this.sort();
-				this.update();
-			}
-		},
-
-		// DOM event handler
-		doKeyEvent: function(e){
-			e.dispatch = 'do' + e.type;
-			this.onKeyEvent(e);
-		},
-
-		// event dispatch
-		//: protected
-		_dispatch: function(m, e){
-			if(m in this){
-				return this[m](e);
-			}
-			return false;
-		},
-
-		dispatchKeyEvent: function(e){
-			this._dispatch(e.dispatch, e);
-		},
-
-		dispatchContentEvent: function(e){
-			this.edit.dispatchEvent(e) || e.sourceView.dispatchContentEvent(e) || this._dispatch(e.dispatch, e);
-		},
-
-		dispatchHeaderEvent: function(e){
-			e.sourceView.dispatchHeaderEvent(e) || this._dispatch('doheader' + e.type, e);
-		},
-
-		dokeydown: function(e){
-			this.onKeyDown(e);
-		},
-
-		doclick: function(e){
-			if(e.cellNode){
-				this.onCellClick(e);
-			}else{
-				this.onRowClick(e);
-			}
-		},
-
-		dodblclick: function(e){
-			if(e.cellNode){
-				this.onCellDblClick(e);
-			}else{
-				this.onRowDblClick(e);
-			}
-		},
-
-		docontextmenu: function(e){
-			if(e.cellNode){
-				this.onCellContextMenu(e);
-			}else{
-				this.onRowContextMenu(e);
-			}
-		},
-
-		doheaderclick: function(e){
-			if(e.cellNode){
-				this.onHeaderCellClick(e);
-			}else{
-				this.onHeaderClick(e);
-			}
-		},
-
-		doheaderdblclick: function(e){
-			if(e.cellNode){
-				this.onHeaderCellDblClick(e);
-			}else{
-				this.onHeaderDblClick(e);
-			}
-		},
-
-		doheadercontextmenu: function(e){
-			if(e.cellNode){
-				this.onHeaderCellContextMenu(e);
-			}else{
-				this.onHeaderContextMenu(e);
-			}
-		},
-
-		// override to modify editing process
-		doStartEdit: function(inCell, inRowIndex){
-			this.onStartEdit(inCell, inRowIndex);
-		},
-
-		doApplyCellEdit: function(inValue, inRowIndex, inFieldIndex){
-			this.onApplyCellEdit(inValue, inRowIndex, inFieldIndex);
-		},
-
-		doCancelEdit: function(inRowIndex){
-			this.onCancelEdit(inRowIndex);
-		},
-
-		doApplyEdit: function(inRowIndex){
-			this.onApplyEdit(inRowIndex);
-		},
-
-		// row editing
-		addRow: function(){
-			// summary:
-			//		Add a row to the grid.
-			this.updateRowCount(this.attr('rowCount')+1);
-		},
-
-		removeSelectedRows: function(){
-			// summary:
-			//		Remove the selected rows from the grid.
-			if(this.allItemsSelected){
-				this.updateRowCount(0);
-			}else{
-				this.updateRowCount(Math.max(0, this.attr('rowCount') - this.selection.getSelected().length));
-			}
-			this.selection.clear();
-		}
-
-	});
-
-	dojox.grid._Grid.markupFactory = function(props, node, ctor, cellFunc){
-		var d = dojo;
-		var widthFromAttr = function(n){
-			var w = d.attr(n, "width")||"auto";
-			if((w != "auto")&&(w.slice(-2) != "em")&&(w.slice(-1) != "%")){
-				w = parseInt(w, 10)+"px";
-			}
-			return w;
-		};
-		// if(!props.store){ console.debug("no store!"); }
-		// if a structure isn't referenced, do we have enough
-		// data to try to build one automatically?
-		if(	!props.structure &&
-			node.nodeName.toLowerCase() == "table"){
-
-			// try to discover a structure
-			props.structure = d.query("> colgroup", node).map(function(cg){
-				var sv = d.attr(cg, "span");
-				var v = {
-					noscroll: (d.attr(cg, "noscroll") == "true") ? true : false,
-					__span: (!!sv ? parseInt(sv, 10) : 1),
-					cells: []
-				};
-				if(d.hasAttr(cg, "width")){
-					v.width = widthFromAttr(cg);
-				}
-				return v; // for vendetta
-			});
-			if(!props.structure.length){
-				props.structure.push({
-					__span: Infinity,
-					cells: [] // catch-all view
-				});
-			}
-			// check to see if we're gonna have more than one view
-
-			// for each tr in our th, create a row of cells
-			d.query("thead > tr", node).forEach(function(tr, tr_idx){
-				var cellCount = 0;
-				var viewIdx = 0;
-				var lastViewIdx;
-				var cView = null;
-				d.query("> th", tr).map(function(th){
-					// what view will this cell go into?
-
-					// NOTE:
-					//		to prevent extraneous iteration, we start counters over
-					//		for each row, incrementing over the surface area of the
-					//		structure that colgroup processing generates and
-					//		creating cell objects for each <th> to place into those
-					//		cell groups.  There's a lot of state-keepking logic
-					//		here, but it is what it has to be.
-					if(!cView){ // current view book keeping
-						lastViewIdx = 0;
-						cView = props.structure[0];
-					}else if(cellCount >= (lastViewIdx+cView.__span)){
-						viewIdx++;
-						// move to allocating things into the next view
-						lastViewIdx += cView.__span;
-						var lastView = cView;
-						cView = props.structure[viewIdx];
-					}
-
-					// actually define the cell from what markup hands us
-					var cell = {
-						name: d.trim(d.attr(th, "name")||th.innerHTML),
-						colSpan: parseInt(d.attr(th, "colspan")||1, 10),
-						type: d.trim(d.attr(th, "cellType")||""),
-						id: d.trim(d.attr(th,"id")||"")
-					};
-					cellCount += cell.colSpan;
-					var rowSpan = d.attr(th, "rowspan");
-					if(rowSpan){
-						cell.rowSpan = rowSpan;
-					}
-					if(d.hasAttr(th, "width")){
-						cell.width = widthFromAttr(th);
-					}
-					if(d.hasAttr(th, "relWidth")){
-						cell.relWidth = window.parseInt(dojo.attr(th, "relWidth"), 10);
-					}
-					if(d.hasAttr(th, "hidden")){
-						cell.hidden = d.attr(th, "hidden") == "true";
-					}
-
-					if(cellFunc){
-						cellFunc(th, cell);
-					}
-
-					cell.type = cell.type ? dojo.getObject(cell.type) : dojox.grid.cells.Cell;
-
-					if(cell.type && cell.type.markupFactory){
-						cell.type.markupFactory(th, cell);
-					}
-
-					if(!cView.cells[tr_idx]){
-						cView.cells[tr_idx] = [];
-					}
-					cView.cells[tr_idx].push(cell);
-				});
-			});
-		}
-
-		return new ctor(props, node);
-	};
-})();
-
-}
-
-if(!dojo._hasResource["dojox.grid.DataSelection"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid.DataSelection"] = true;
-dojo.provide("dojox.grid.DataSelection");
-
-
-dojo.declare("dojox.grid.DataSelection", dojox.grid.Selection, {
-	getFirstSelected: function(){
-		var idx = dojox.grid.Selection.prototype.getFirstSelected.call(this);
-
-		if(idx == -1){ return null; }
-		return this.grid.getItem(idx);
-	},
-
-	getNextSelected: function(inPrev){
-		var old_idx = this.grid.getItemIndex(inPrev);
-		var idx = dojox.grid.Selection.prototype.getNextSelected.call(this, old_idx);
-
-		if(idx == -1){ return null; }
-		return this.grid.getItem(idx);
-	},
-
-	getSelected: function(){
-		var result = [];
-		for(var i=0, l=this.selected.length; i<l; i++){
-			if(this.selected[i]){
-				result.push(this.grid.getItem(i));
-			}
-		}
-		return result;
-	},
-
-	addToSelection: function(inItemOrIndex){
-		if(this.mode == 'none'){ return; }
-		var idx = null;
-		if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
-			idx = inItemOrIndex;
-		}else{
-			idx = this.grid.getItemIndex(inItemOrIndex);
-		}
-		dojox.grid.Selection.prototype.addToSelection.call(this, idx);
-	},
-
-	deselect: function(inItemOrIndex){
-		if(this.mode == 'none'){ return; }
-		var idx = null;
-		if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
-			idx = inItemOrIndex;
-		}else{
-			idx = this.grid.getItemIndex(inItemOrIndex);
-		}
-		dojox.grid.Selection.prototype.deselect.call(this, idx);
-	},
-
-	deselectAll: function(inItemOrIndex){
-		var idx = null;
-		if(inItemOrIndex || typeof inItemOrIndex == "number"){
-			if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
-				idx = inItemOrIndex;
-			}else{
-				idx = this.grid.getItemIndex(inItemOrIndex);
-			}
-			dojox.grid.Selection.prototype.deselectAll.call(this, idx);
-		}else{
-			this.inherited(arguments);
-		}
-	}
-});
-
-}
-
-if(!dojo._hasResource["dojox.grid.DataGrid"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojox.grid.DataGrid"] = true;
-dojo.provide("dojox.grid.DataGrid");
-
-
-
-
-/*=====
-dojo.declare("dojox.grid.__DataCellDef", dojox.grid.__CellDef, {
-	constructor: function(){
-		//	field: String?
-		//		The attribute to read from the dojo.data item for the row.
-		//  fields: String[]?
-		//		An array of fields to grab the values of and pass as an array to the grid
-		//	get: Function?
-		//		function(rowIndex, item?){} rowIndex is of type Integer, item is of type
-		//		Object.  This function will be called when a cell requests data.  Returns
-		//		the unformatted data for the cell.
-	}
-});
-=====*/
-
-/*=====
-dojo.declare("dojox.grid.__DataViewDef", dojox.grid.__ViewDef, {
-	constructor: function(){
-		//	cells: dojox.grid.__DataCellDef[]|Array[dojox.grid.__DataCellDef[]]?
-		//		The structure of the cells within this grid.
-		//	defaultCell: dojox.grid.__DataCellDef?
-		//		A cell definition with default values for all cells in this view.  If
-		//		a property is defined in a cell definition in the "cells" array and
-		//		this property, the cell definition's property will override this
-		//		property's property.
-	}
-});
-=====*/
-
-dojo.declare("dojox.grid.DataGrid", dojox.grid._Grid, {
-	store: null,
-	query: null,
-	queryOptions: null,
-	fetchText: '...',
-	sortFields: null,
-	
-	// updateDelay: int
-	//		Time, in milliseconds, to delay updates automatically so that multiple
-	//		calls to onSet/onNew/onDelete don't keep rerendering the grid.  Set
-	//		to 0 to immediately cause updates.  A higher value will result in
-	//		better performance at the expense of responsiveness of the grid.
-	updateDelay: 1,
-
-/*=====
-	// structure: dojox.grid.__DataViewDef|dojox.grid.__DataViewDef[]|dojox.grid.__DataCellDef[]|Array[dojox.grid.__DataCellDef[]]
-	//		View layout defintion.
-	structure: '',
-=====*/
-
-	// You can specify items instead of a query, if you like.  They do not need
-	// to be loaded - but the must be items in the store
-	items: null,
-	
-	_store_connects: null,
-	_by_idty: null,
-	_by_idx: null,
-	_cache: null,
-	_pages: null,
-	_pending_requests: null,
-	_bop: -1,
-	_eop: -1,
-	_requests: 0,
-	rowCount: 0,
-
-	_isLoaded: false,
-	_isLoading: false,
-	
-	postCreate: function(){
-		this._pages = [];
-		this._store_connects = [];
-		this._by_idty = {};
-		this._by_idx = [];
-		this._cache = [];
-		this._pending_requests = {};
-
-		this._setStore(this.store);
-		this.inherited(arguments);
-	},
-
-	createSelection: function(){
-		this.selection = new dojox.grid.DataSelection(this);
-	},
-
-	get: function(inRowIndex, inItem){
-		if(inItem && this.field == "_item" && !this.fields){
-			return inItem;
-		}else if(inItem && this.fields){
-			var ret = [];
-			var s = this.grid.store;
-			dojo.forEach(this.fields, function(f){
-				ret = ret.concat(s.getValues(inItem, f));
-			});
-			return ret;
-		}
-		return (!inItem ? this.defaultValue : (!this.field ? this.value : (this.field == "_item" ? inItem : this.grid.store.getValue(inItem, this.field))));
-	},
-
-	_checkUpdateStatus: function(){
-		if(this.updateDelay > 0){
-			var iStarted = false;
-			if(this._endUpdateDelay){
-				clearTimeout(this._endUpdateDelay);
-				delete this._endUpdateDelay;
-				iStarted = true;
-			}
-			if(!this.updating){
-				this.beginUpdate();
-				iStarted = true;
-			}
-			if(iStarted){
-				var _this = this;
-				this._endUpdateDelay = setTimeout(function(){
-					delete _this._endUpdateDelay;
-					_this.endUpdate();
-				}, this.updateDelay);
-			}
-		}
-	},
-	
-	_onSet: function(item, attribute, oldValue, newValue){
-		this._checkUpdateStatus();
-		var idx = this.getItemIndex(item);
-		if(idx>-1){
-			this.updateRow(idx);
-		}
-	},
-	
-	_createItem: function(item, index){
-		var idty = this._hasIdentity ? this.store.getIdentity(item) : dojo.toJson(this.query) + ":idx:" + index + ":sort:" + dojo.toJson(this.getSortProps());
-		var o = this._by_idty[idty] = { idty: idty, item: item };
-		return o;
-	},
-
-	_addItem: function(item, index, noUpdate){
-		this._by_idx[index] = this._createItem(item, index);
-		if(!noUpdate){
-			this.updateRow(index);
-		}
-	},
-
-	_onNew: function(item, parentInfo){
-		this._checkUpdateStatus();
-		var rowCount = this.attr('rowCount');
-		this._addingItem = true;
-		this.updateRowCount(rowCount+1);
-		this._addingItem = false;
-		this._addItem(item, rowCount);
-		this.showMessage();
-	},
-
-	_onDelete: function(item){
-		this._checkUpdateStatus();
-		var idx = this._getItemIndex(item, true);
-
-		if(idx >= 0){
-			// When a row is deleted, all rest rows are shifted down,
-			// and migrate from page to page. If some page is not 
-			// loaded yet empty rows can migrate to initialized pages
-			// without refreshing. It causes empty rows in some pages, see:
-			// http://bugs.dojotoolkit.org/ticket/6818
-			// this code fix this problem by reseting loaded page info
-			this._pages = [];
-			this._bop = -1;
-			this._eop = -1;
-
-			var o = this._by_idx[idx];
-			this._by_idx.splice(idx, 1);
-			delete this._by_idty[o.idty];
-			this.updateRowCount(this.attr('rowCount')-1);
-			if(this.attr('rowCount') === 0){
-				this.showMessage(this.noDataMessage);
-			}
-		}
-	},
-
-	_onRevert: function(){
-		this._refresh();
-	},
-
-	setStore: function(store, query, queryOptions){
-		this._setQuery(query, queryOptions);
-		this._setStore(store);
-		this._refresh(true);
-	},
-	
-	setQuery: function(query, queryOptions){
-		this._setQuery(query, queryOptions);
-		this._refresh(true);
-	},
-	
-	setItems: function(items){
-		this.items = items;
-		this._setStore(this.store);
-		this._refresh(true);
-	},
-	
-	_setQuery: function(query, queryOptions){
-		this.query = query;
-		this.queryOptions = queryOptions || this.queryOptions;		
-	},
-
-	_setStore: function(store){
-		if(this.store&&this._store_connects){
-			dojo.forEach(this._store_connects,function(arr){
-				dojo.forEach(arr, dojo.disconnect);
-			});
-		}
-		this.store = store;
-
-		if(this.store){
-			var f = this.store.getFeatures();
-			var h = [];
-
-			this._canEdit = !!f["dojo.data.api.Write"] && !!f["dojo.data.api.Identity"];
-			this._hasIdentity = !!f["dojo.data.api.Identity"];
-
-			if(!!f["dojo.data.api.Notification"] && !this.items){
-				h.push(this.connect(this.store, "onSet", "_onSet"));
-				h.push(this.connect(this.store, "onNew", "_onNew"));
-				h.push(this.connect(this.store, "onDelete", "_onDelete"));
-			}
-			if(this._canEdit){
-				h.push(this.connect(this.store, "revert", "_onRevert"));
-			}
-
-			this._store_connects = h;
-		}
-	},
-
-	_onFetchBegin: function(size, req){
-		if(!this.scroller){ return; }
-		if(this.rowCount != size){
-			if(req.isRender){
-				this.scroller.init(size, this.keepRows, this.rowsPerPage);
-				this.rowCount = size;
-				this._setAutoHeightAttr(this.autoHeight, true);
-				this._skipRowRenormalize = true;
-				this.prerender();
-				this._skipRowRenormalize = false;
-			}else{
-				this.updateRowCount(size);
-			}
-		}
-		if(!size){
-			this.views.render();
-			this._resize();
-			this.showMessage(this.noDataMessage);
-			this.focus.initFocusView();
-		}else{
-			this.showMessage();
-		}
-	},
-
-	_onFetchComplete: function(items, req){
-		if(!this.scroller){ return; }
-		if(items && items.length > 0){
-			//console.log(items);
-			dojo.forEach(items, function(item, idx){
-				this._addItem(item, req.start+idx, true);
-			}, this);
-			if(this._autoHeight){
-				this._skipRowRenormalize = true;
-			}
-			this.updateRows(req.start, items.length);
-			if(this._autoHeight){
-				this._skipRowRenormalize = false;
-			}			
-			if(req.isRender){
-				this.setScrollTop(0);
-				this.postrender();
-			}else if(this._lastScrollTop){
-				this.setScrollTop(this._lastScrollTop);
-			}
-		}
-		delete this._lastScrollTop;
-		if(!this._isLoaded){
-			this._isLoading = false;
-			this._isLoaded = true;
-		}
-		this._pending_requests[req.start] = false;
-	},
-
-	_onFetchError: function(err, req){
-		console.log(err);
-		delete this._lastScrollTop;
-		if(!this._isLoaded){
-			this._isLoading = false;
-			this._isLoaded = true;
-			this.showMessage(this.errorMessage);
-		}
-		this._pending_requests[req.start] = false;
-		this.onFetchError(err, req);
-	},
-
-	onFetchError: function(err, req){
-	},
-
-	_fetch: function(start, isRender){
-		start = start || 0;
-		if(this.store && !this._pending_requests[start]){
-			if(!this._isLoaded && !this._isLoading){
-				this._isLoading = true;
-				this.showMessage(this.loadingMessage);
-			}
-			this._pending_requests[start] = true;
-			//console.log("fetch: ", start);
-			try{
-				if(this.items){
-					var items = this.items;
-					var store = this.store;
-					this.rowsPerPage = items.length;
-					var req = {
-						start: start,
-						count: this.rowsPerPage,
-						isRender: isRender
-					};
-					this._onFetchBegin(items.length, req);
-					
-					// Load them if we need to
-					var waitCount = 0;
-					dojo.forEach(items, function(i){
-						if(!store.isItemLoaded(i)){ waitCount++; }
-					});
-					if(waitCount === 0){
-						this._onFetchComplete(items, req);
-					}else{
-						var onItem = function(item){
-							waitCount--;
-							if(waitCount === 0){
-								this._onFetchComplete(items, req);
-							}
-						};
-						dojo.forEach(items, function(i){
-							if(!store.isItemLoaded(i)){
-								store.loadItem({item: i, onItem: onItem, scope: this});
-							}
-						}, this);
-					}
-				}else{
-					this.store.fetch({
-						start: start,
-						count: this.rowsPerPage,
-						query: this.query,
-						sort: this.getSortProps(),
-						queryOptions: this.queryOptions,
-						isRender: isRender,
-						onBegin: dojo.hitch(this, "_onFetchBegin"),
-						onComplete: dojo.hitch(this, "_onFetchComplete"),
-						onError: dojo.hitch(this, "_onFetchError")
-					});
-				}
-			}catch(e){
-				this._onFetchError(e, {start: start, count: this.rowsPerPage});
-			}
-		}
-	},
-
-	_clearData: function(){
-		this.updateRowCount(0);
-		this._by_idty = {};
-		this._by_idx = [];
-		this._pages = [];
-		this._bop = this._eop = -1;
-		this._isLoaded = false;
-		this._isLoading = false;
-	},
-
-	getItem: function(idx){
-		var data = this._by_idx[idx];
-		if(!data||(data&&!data.item)){
-			this._preparePage(idx);
-			return null;
-		}
-		return data.item;
-	},
-
-	getItemIndex: function(item){
-		return this._getItemIndex(item, false);
-	},
-	
-	_getItemIndex: function(item, isDeleted){
-		if(!isDeleted && !this.store.isItem(item)){
-			return -1;
-		}
-
-		var idty = this._hasIdentity ? this.store.getIdentity(item) : null;
-
-		for(var i=0, l=this._by_idx.length; i<l; i++){
-			var d = this._by_idx[i];
-			if(d && ((idty && d.idty == idty) || (d.item === item))){
-				return i;
-			}
-		}
-		return -1;
-	},
-
-	filter: function(query, reRender){
-		this.query = query;
-		if(reRender){
-			this._clearData();
-		}
-		this._fetch();
-	},
-
-	_getItemAttr: function(idx, attr){
-		var item = this.getItem(idx);
-		return (!item ? this.fetchText : this.store.getValue(item, attr));
-	},
-
-	// rendering
-	_render: function(){
-		if(this.domNode.parentNode){
-			this.scroller.init(this.attr('rowCount'), this.keepRows, this.rowsPerPage);
-			this.prerender();
-			this._fetch(0, true);
-		}
-	},
-
-	// paging
-	_requestsPending: function(inRowIndex){
-		return this._pending_requests[inRowIndex];
-	},
-
-	_rowToPage: function(inRowIndex){
-		return (this.rowsPerPage ? Math.floor(inRowIndex / this.rowsPerPage) : inRowIndex);
-	},
-
-	_pageToRow: function(inPageIndex){
-		return (this.rowsPerPage ? this.rowsPerPage * inPageIndex : inPageIndex);
-	},
-
-	_preparePage: function(inRowIndex){
-		if((inRowIndex < this._bop || inRowIndex >= this._eop) && !this._addingItem){
-			var pageIndex = this._rowToPage(inRowIndex);
-			this._needPage(pageIndex);
-			this._bop = pageIndex * this.rowsPerPage;
-			this._eop = this._bop + (this.rowsPerPage || this.attr('rowCount'));
-		}
-	},
-
-	_needPage: function(inPageIndex){
-		if(!this._pages[inPageIndex]){
-			this._pages[inPageIndex] = true;
-			this._requestPage(inPageIndex);
-		}
-	},
-
-	_requestPage: function(inPageIndex){
-		var row = this._pageToRow(inPageIndex);
-		var count = Math.min(this.rowsPerPage, this.attr('rowCount') - row);
-		if(count > 0){
-			this._requests++;
-			if(!this._requestsPending(row)){
-				setTimeout(dojo.hitch(this, "_fetch", row, false), 1);
-				//this.requestRows(row, count);
-			}
-		}
-	},
-
-	getCellName: function(inCell){
-		return inCell.field;
-		//console.log(inCell);
-	},
-
-	_refresh: function(isRender){
-		this._clearData();
-		this._fetch(0, isRender);
-	},
-
-	sort: function(){
-		this._lastScrollTop = this.scrollTop;
-		this._refresh();
-	},
-
-	canSort: function(){
-		return (!this._isLoading);
-	},
-
-	getSortProps: function(){
-		var c = this.getCell(this.getSortIndex());
-		if(!c){
-			if(this.sortFields){
-				return this.sortFields;
-			}
-			return null;
-		}else{
-			var desc = c["sortDesc"];
-			var si = !(this.sortInfo>0);
-			if(typeof desc == "undefined"){
-				desc = si;
-			}else{
-				desc = si ? !desc : desc;
-			}
-			return [{ attribute: c.field, descending: desc }];
-		}
-	},
-
-	styleRowState: function(inRow){
-		// summary: Perform row styling
-		if(this.store && this.store.getState){
-			var states=this.store.getState(inRow.index), c='';
-			for(var i=0, ss=["inflight", "error", "inserting"], s; s=ss[i]; i++){
-				if(states[s]){
-					c = ' dojoxGridRow-' + s;
-					break;
-				}
-			}
-			inRow.customClasses += c;
-		}
-	},
-
-	onStyleRow: function(inRow){
-		this.styleRowState(inRow);
-		this.inherited(arguments);
-	},
-
-	// editing
-	canEdit: function(inCell, inRowIndex){
-		return this._canEdit;
-	},
-
-	_copyAttr: function(idx, attr){
-		var row = {};
-		var backstop = {};
-		var src = this.getItem(idx);
-		return this.store.getValue(src, attr);
-	},
-
-	doStartEdit: function(inCell, inRowIndex){
-		if(!this._cache[inRowIndex]){
-			this._cache[inRowIndex] = this._copyAttr(inRowIndex, inCell.field);
-		}
-		this.onStartEdit(inCell, inRowIndex);
-	},
-
-	doApplyCellEdit: function(inValue, inRowIndex, inAttrName){
-		this.store.fetchItemByIdentity({
-			identity: this._by_idx[inRowIndex].idty,
-			onItem: dojo.hitch(this, function(item){
-				var oldValue = this.store.getValue(item, inAttrName);
-				if(typeof oldValue == 'number'){
-					inValue = isNaN(inValue) ? inValue : parseFloat(inValue);
-				}else if(typeof oldValue == 'boolean'){
-					inValue = inValue == 'true' ? true : inValue == 'false' ? false : inValue;
-				}else if(oldValue instanceof Date){
-					var asDate = new Date(inValue);
-					inValue = isNaN(asDate.getTime()) ? inValue : asDate;
-				}
-				this.store.setValue(item, inAttrName, inValue);
-				this.onApplyCellEdit(inValue, inRowIndex, inAttrName);
-			})
-		});
-	},
-
-	doCancelEdit: function(inRowIndex){
-		var cache = this._cache[inRowIndex];
-		if(cache){
-			this.updateRow(inRowIndex);
-			delete this._cache[inRowIndex];
-		}
-		this.onCancelEdit.apply(this, arguments);
-	},
-
-	doApplyEdit: function(inRowIndex, inDataAttr){
-		var cache = this._cache[inRowIndex];
-		/*if(cache){
-			var data = this.getItem(inRowIndex);
-			if(this.store.getValue(data, inDataAttr) != cache){
-				this.update(cache, data, inRowIndex);
-			}
-			delete this._cache[inRowIndex];
-		}*/
-		this.onApplyEdit(inRowIndex);
-	},
-
-	removeSelectedRows: function(){
-		// summary:
-		//		Remove the selected rows from the grid.
-		if(this._canEdit){
-			this.edit.apply();
-			var fx = dojo.hitch(this, function(items){
-				if(items.length){
-					dojo.forEach(items, this.store.deleteItem, this.store);
-					this.selection.clear();
-				}			
-			});
-			if(this.allItemsSelected){
-				this.store.fetch({
-							query: this.query, 
-							queryOptions: this.queryOptions,
-							onComplete: fx});
-			}else{
-				fx(this.selection.getSelected());
-			}
-		}
-	}
-});
-
-dojox.grid.DataGrid.cell_markupFactory = function(cellFunc, node, cellDef){
-	var field = dojo.trim(dojo.attr(node, "field")||"");
-	if(field){
-		cellDef.field = field;
-	}
-	cellDef.field = cellDef.field||cellDef.name;
-	var fields = dojo.trim(dojo.attr(node, "fields")||"");
-	if(fields){
-		cellDef.fields = fields.split(",");
-	}
-	if(cellFunc){
-		cellFunc(node, cellDef);
-	}
-};
-
-dojox.grid.DataGrid.markupFactory = function(props, node, ctor, cellFunc){
-	return dojox.grid._Grid.markupFactory(props, node, ctor, 
-					dojo.partial(dojox.grid.DataGrid.cell_markupFactory, cellFunc));
-};
-
-}
-
-
-dojo.i18n._preloadLocalizations("dojox.grid.nls.DataGrid", ["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","nb","nl","nl-nl","pl","pt","pt-br","pt-pt","ru","sk","sl","sv","th","tr","xx","zh","zh-cn","zh-tw"]);
diff --git a/dojox/grid/DataSelection.js b/dojox/grid/DataSelection.js
index 3da5913..1c65860 100644
--- a/dojox/grid/DataSelection.js
+++ b/dojox/grid/DataSelection.js
@@ -1,68 +1,65 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.DataSelection"]){
-dojo._hasResource["dojox.grid.DataSelection"]=true;
 dojo.provide("dojox.grid.DataSelection");
 dojo.require("dojox.grid.Selection");
-dojo.declare("dojox.grid.DataSelection",dojox.grid.Selection,{getFirstSelected:function(){
-var _1=dojox.grid.Selection.prototype.getFirstSelected.call(this);
-if(_1==-1){
-return null;
-}
-return this.grid.getItem(_1);
-},getNextSelected:function(_2){
-var _3=this.grid.getItemIndex(_2);
-var _4=dojox.grid.Selection.prototype.getNextSelected.call(this,_3);
-if(_4==-1){
-return null;
-}
-return this.grid.getItem(_4);
-},getSelected:function(){
-var _5=[];
-for(var i=0,l=this.selected.length;i<l;i++){
-if(this.selected[i]){
-_5.push(this.grid.getItem(i));
-}
-}
-return _5;
-},addToSelection:function(_6){
-if(this.mode=="none"){
-return;
-}
-var _7=null;
-if(typeof _6=="number"||typeof _6=="string"){
-_7=_6;
-}else{
-_7=this.grid.getItemIndex(_6);
-}
-dojox.grid.Selection.prototype.addToSelection.call(this,_7);
-},deselect:function(_8){
-if(this.mode=="none"){
-return;
-}
-var _9=null;
-if(typeof _8=="number"||typeof _8=="string"){
-_9=_8;
-}else{
-_9=this.grid.getItemIndex(_8);
-}
-dojox.grid.Selection.prototype.deselect.call(this,_9);
-},deselectAll:function(_a){
-var _b=null;
-if(_a||typeof _a=="number"){
-if(typeof _a=="number"||typeof _a=="string"){
-_b=_a;
-}else{
-_b=this.grid.getItemIndex(_a);
-}
-dojox.grid.Selection.prototype.deselectAll.call(this,_b);
-}else{
-this.inherited(arguments);
-}
-}});
-}
+
+dojo.declare("dojox.grid.DataSelection", dojox.grid.Selection, {
+	getFirstSelected: function(){
+		var idx = dojox.grid.Selection.prototype.getFirstSelected.call(this);
+
+		if(idx == -1){ return null; }
+		return this.grid.getItem(idx);
+	},
+
+	getNextSelected: function(inPrev){
+		var old_idx = this.grid.getItemIndex(inPrev);
+		var idx = dojox.grid.Selection.prototype.getNextSelected.call(this, old_idx);
+
+		if(idx == -1){ return null; }
+		return this.grid.getItem(idx);
+	},
+
+	getSelected: function(){
+		var result = [];
+		for(var i=0, l=this.selected.length; i<l; i++){
+			if(this.selected[i]){
+				result.push(this.grid.getItem(i));
+			}
+		}
+		return result;
+	},
+
+	addToSelection: function(inItemOrIndex){
+		if(this.mode == 'none'){ return; }
+		var idx = null;
+		if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
+			idx = inItemOrIndex;
+		}else{
+			idx = this.grid.getItemIndex(inItemOrIndex);
+		}
+		dojox.grid.Selection.prototype.addToSelection.call(this, idx);
+	},
+
+	deselect: function(inItemOrIndex){
+		if(this.mode == 'none'){ return; }
+		var idx = null;
+		if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
+			idx = inItemOrIndex;
+		}else{
+			idx = this.grid.getItemIndex(inItemOrIndex);
+		}
+		dojox.grid.Selection.prototype.deselect.call(this, idx);
+	},
+
+	deselectAll: function(inItemOrIndex){
+		var idx = null;
+		if(inItemOrIndex || typeof inItemOrIndex == "number"){
+			if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
+				idx = inItemOrIndex;
+			}else{
+				idx = this.grid.getItemIndex(inItemOrIndex);
+			}
+			dojox.grid.Selection.prototype.deselectAll.call(this, idx);
+		}else{
+			this.inherited(arguments);
+		}
+	}
+});
diff --git a/dojox/grid/EnhancedGrid.js b/dojox/grid/EnhancedGrid.js
index c6abfbf..b9f9dfd 100644
--- a/dojox/grid/EnhancedGrid.js
+++ b/dojox/grid/EnhancedGrid.js
@@ -1,77 +1,171 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.EnhancedGrid"]){
-dojo._hasResource["dojox.grid.EnhancedGrid"]=true;
 dojo.provide("dojox.grid.EnhancedGrid");
+
 dojo.require("dojox.grid.DataGrid");
 dojo.require("dojox.grid.enhanced._Plugin");
-dojo.requireLocalization("dojox.grid.enhanced","EnhancedGrid",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,zh,zh-tw");
+dojo.requireLocalization("dojox.grid.enhanced", "EnhancedGrid");
+
 dojo.experimental("dojox.grid.EnhancedGrid");
-dojo.declare("dojox.grid.EnhancedGrid",dojox.grid.DataGrid,{plugins:null,pluginMgr:null,doubleAffordance:false,postMixInProperties:function(){
-this._nls=dojo.i18n.getLocalization("dojox.grid.enhanced","EnhancedGrid",this.lang);
-this.inherited(arguments);
-},postCreate:function(){
-if(this.plugins){
-this.pluginMgr=new dojox.grid.enhanced._Plugin(this);
-this.pluginMgr.preInit();
-}
-this.inherited(arguments);
-this.pluginMgr&&this.pluginMgr.postInit();
-},_fillContent:function(){
-this.menuContainer=this.srcNodeRef;
-this.inherited(arguments);
-},startup:function(){
-this.menuContainer&&this._initMenus&&this._initMenus();
-this.inherited(arguments);
-if(this.doubleAffordance){
-dojo.addClass(this.domNode,"dojoxGridDoubleAffordance");
-}
-},textSizeChanged:function(){
-if(!dojo.isWebKit){
-this.inherited(arguments);
-}else{
-if(this.textSizeChanging){
-return;
-}
-this.textSizeChanging=true;
-this.inherited(arguments);
-this.textSizeChanging=false;
-}
-},removeSelectedRows:function(){
-if(this.indirectSelection&&this._canEdit){
-var _1=dojo.clone(this.selection.selected);
-this.inherited(arguments);
-dojo.forEach(_1,function(_2,_3){
-_2&&this.grid.rowSelectCell.toggleRow(_3,false);
+
+dojo.declare("dojox.grid.EnhancedGrid", dojox.grid.DataGrid, {
+	//	summary:
+	//		Provides enhanced features for DataGrid, including:
+	//		1. Nested Sorting
+	//		2. Built-in support for Indirect Selection (radio buttons and check boxes)
+	//		3. Declarative context menu
+	//		4. Selecting rows/columns via swipe
+	//		5. Drag-n-drop: columns,rows - MOVE
+	//
+	//	description:
+	//		EnhancedGrid features are implemented as plugins that could be loaded on demand.
+	//		Explicit dojo.require() is needed to use these feature plugins.
+	//
+	//	
+	//  example:
+	//		A quick sample to use all EnhancedGrid features:
+	//      
+	//	   Step 1. Load EnhancedGrid and required features
+	// |   <script type="text/javascript">
+	// |		dojo.require("dojox.grid.EnhancedGrid");
+	// |		dojo.require("dojox.grid.enhanced.plugins.DnD");
+	// |		dojo.require("dojox.grid.enhanced.plugins.Menu");
+	// |		dojo.require("dojox.grid.enhanced.plugins.NestedSorting");
+	// |		dojo.require("dojox.grid.enhanced.plugins.IndirectSelection");
+	// |	</script>
+	//
+	//		Step 2. Use EnhancedGrid
+	//		- Via HTML markup
+	// |	<div dojoType="dojox.grid.EnhancedGrid" ...
+	// |		 plugins="{nestedSorting: true, dnd: true, indirectSelection: true, 
+	// |		 menus:{headerMenu:"headerMenuId", rowMenu:"rowMenuId", cellMenu:"cellMenuId",  
+    // |         selectedRegionMenu:"selectedRegionMenuId"}}">
+	// |			...
+	// |	</div>
+	//
+	//		- Or via JavaScript
+	// |	<script type="text/javascript">
+	// |		var grid = new dojox.grid.EnhancedGrid({plugins : {nestedSorting: true, dnd: true, indirectSelection: true, 
+	// |	               menus:{headerMenu:"headerMenuId", rowMenu:"rowMenuId", cellMenu:"cellMenuId",selectedRegionMenu:"selectedRegionMenuId"}},
+	// |			       ... }, dojo.byId('gridDiv'));
+	// |		grid.startup();
+	// |	</script>
+
+	//plugins: Object
+	//		Plugin properties, e.g. {nestedSorting: true, dnd: true, ...}
+	plugins: null,
+
+	//pluginMgr: Object
+	//		Singleton plugin manager	
+	pluginMgr: null,
+	
+	//doubleAffordance: Boolean
+	//		For special cell hover style
+	doubleAffordance: false,
+	
+	//minRowHeight: Integer
+	//		Minimal row height	
+	minRowHeight: 10,	
+
+	//keepSortSelection: Boolean
+	//		Whether keep selection after sort - only applicable when client-side data store is used.	
+	keepSortSelection: false,
+	
+	//rowSelectionChangedTopic: String
+	//		Topic fired when row selection is changed 
+	rowSelectionChangedTopic: 'ROW_SELECTION_CHANGED',
+	
+	//sortRowSelectionChangedTopic: String
+	//		Topic only fired when row selection is changed by sorting.
+	sortRowSelectionChangedTopic: 'SORT_ROW_SELECTION_CHANGED',
+	
+	//rowMovedTopic: String
+	//		Topic fired when selected rows are moved.
+	rowMovedTopic: 'ROW_MOVED',		
+
+	postMixInProperties: function(){
+		//load nls bundle
+		this._nls = dojo.i18n.getLocalization("dojox.grid.enhanced", "EnhancedGrid", this.lang);
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		//create plugin manager
+		this.pluginMgr = new dojox.grid.enhanced._Plugin(this);
+		this.pluginMgr.preInit();
+		this.inherited(arguments);
+		this.pluginMgr.postInit();
+	},
+	
+	_fillContent: function(){
+		//cached for menu use(menu declared within Grid HTML markup)
+		this.menuContainer = this.srcNodeRef;
+		this.inherited(arguments);
+	},
+	
+	startup: function(){
+		this.menuContainer && this._initMenus && this._initMenus();
+		this.inherited(arguments);
+		if(this.doubleAffordance){
+			dojo.addClass(this.domNode, 'dojoxGridDoubleAffordance');
+		}
+	},
+	
+	textSizeChanged: function(){
+		// summary:
+		//		Overwritten, see _Grid.textSizeChanged()	
+		//      fix #10088 - in Webkit, this method is invoked by two parallel threads which caused #10088
+		if(!dojo.isWebKit){
+			this.inherited(arguments);
+		}else{
+			if(this.textSizeChanging){ return; }
+			this.textSizeChanging = true;
+			this.inherited(arguments);
+			this.textSizeChanging = false;
+		}
+	},
+	
+	removeSelectedRows: function(){
+		// summary:
+		//		Overwritten, see DataGrid.removeSelectedRows()
+		if(this.indirectSelection && this._canEdit){
+			//cache the selected info before cleaned by DataGrid
+			var selected = dojo.clone(this.selection.selected);
+			this.inherited(arguments);
+			dojo.forEach(selected, function(value, index){
+				value && this.grid.rowSelectCell.toggleRow(index, false);
+			});
+		}
+	},
+	
+	doApplyCellEdit: function(inValue, inRowIndex, inAttrName){
+		// summary:
+		//		Overwritten, see DataGrid.doApplyCellEdit()
+		if(!inAttrName){
+			this.invalidated[inRowIndex] = true;
+			return;
+		}
+		this.inherited(arguments);
+	},	
+	
+	mixin: function(target, source){
+		var props = {};
+		for(p in source){
+			if(p == '_inherited' || p == 'declaredClass' || p == 'constructor'){ continue; }
+			props[p] = source[p];
+		}
+		dojo.mixin(target, props);
+	},
+	
+	_copyAttr: function(idx, attr){
+		// summary:
+		//		Overwritten, see DataGrid._copyAttr()
+		//		Fix cell TAB navigation for single click editting
+		if(!attr) return;
+		return this.inherited(arguments);
+	}
 });
-}
-},doApplyCellEdit:function(_4,_5,_6){
-if(!_6){
-this.invalidated[_5]=true;
-return;
-}
-this.inherited(arguments);
-},mixin:function(_7,_8){
-var _9={};
-for(p in _8){
-if(p=="_inherited"||p=="declaredClass"||p=="constructor"){
-continue;
-}
-_9[p]=_8[p];
-}
-dojo.mixin(_7,_9);
-},_copyAttr:function(_a,_b){
-if(!_b){
-return;
-}
-return this.inherited(arguments);
-}});
-dojox.grid.EnhancedGrid.markupFactory=function(_c,_d,_e,_f){
-return dojox.grid._Grid.markupFactory(_c,_d,_e,dojo.partial(dojox.grid.DataGrid.cell_markupFactory,_f));
+
+
+dojox.grid.EnhancedGrid.markupFactory = function(props, node, ctor, cellFunc){
+	return dojox.grid._Grid.markupFactory(props, node, ctor, 
+					dojo.partial(dojox.grid.DataGrid.cell_markupFactory, cellFunc));
 };
-}
diff --git a/dojox/grid/README b/dojox/grid/README
index 7df19b5..7f34392 100644
--- a/dojox/grid/README
+++ b/dojox/grid/README
@@ -11,6 +11,7 @@ Credits
 	Scott J. Miles (sjmiles at activegrid.com)
 	Steve Orvell (sorvell at activegrid.com)
 	Bryan Forbes (bryan AT reigndropsfall.net)
+	Nathan Toone (toonetown AT dojotoolkit.org)
 -------------------------------------------------------------------------------
 Project description
 
@@ -46,3 +47,59 @@ If you wish us use the old (compat / 1.2) grid, you can untar the
 compatGrid.tar.gz archive.  This version of the grid is no longer maintained
 or updated - but should work with any newer version of the dojo library.
 -------------------------------------------------------------------------------
+
+
+
+-------------------------------------------------------------------------------
+Sub-projects:									  
+-------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------
+1. dojox.grid.EnhancedGrid
+-------------------------------------------------------------------------------
+Version 0.9
+Release date: 12/11/2009
+-------------------------------------------------------------------------------
+Project state
+
+alpha
+-------------------------------------------------------------------------------
+Credits
+	David Schwartz (drschwar at us.ibm.com)
+	Wei Huang (hwcdl at cn.ibm.com)
+	Guang Hong (hongg at cn.ibm.com)
+-------------------------------------------------------------------------------
+Project description
+
+Enhanced Grid inherits base DataGrid and provides the following enhanced features:
+
+ 1. Nested Sorting
+ 2. Built-in declarative Indirect Selection (radio buttons and check boxes)
+ 3. Declarative context menu
+ 4. Selecting rows/columns via swipe
+ 5. Drag-n-drop: columns,rows - MOVE
+
+-------------------------------------------------------------------------------
+Dependencies
+
+Dojo Core, dojox.grid.DataGrid
+-------------------------------------------------------------------------------
+Documentation
+
+http://docs.dojocampus.org/dojox/grid/EnhancedGrid
+-------------------------------------------------------------------------------
+Installation instructions
+
+Same as dojox.grid, for detail sample usages, please refer to /dojox/grid/tests/enhanced/test_enhanced_grid.html
+-------------------------------------------------------------------------------
+Known issues
+
+ - Enhanced Grid doesn't support complicated layouts (e.g. multiple rows in column header) and TreeGrid(SubGrid).
+ - Indirect Selection is not compatible with "autoHeight" mode due to a known issue in DataGrid(http://trac.dojotoolkit.org/ticket/11101)
+-------------------------------------------------------------------------------
+Possible future changes
+
+ 1. A rich set of new features to be added, e.g. Exporter, Printer, Filter, Pagination ...
+ 2. An activity of setting up a plug-in platform is in progress for future Grid versions, 
+   by then all the EnhancedGrid features will be re-cast as separate plug-ins loaded on demand.
+-------------------------------------------------------------------------------
\ No newline at end of file
diff --git a/dojox/grid/Selection.js b/dojox/grid/Selection.js
index a9f491e..98b461c 100644
--- a/dojox/grid/Selection.js
+++ b/dojox/grid/Selection.js
@@ -1,209 +1,260 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.Selection"]){
-dojo._hasResource["dojox.grid.Selection"]=true;
-dojo.provide("dojox.grid.Selection");
-dojo.declare("dojox.grid.Selection",null,{constructor:function(_1){
-this.grid=_1;
-this.selected=[];
-this.setMode(_1.selectionMode);
-},mode:"extended",selected:null,updating:0,selectedIndex:-1,setMode:function(_2){
-if(this.selected.length){
-this.deselectAll();
-}
-if(_2!="extended"&&_2!="multiple"&&_2!="single"&&_2!="none"){
-this.mode="extended";
-}else{
-this.mode=_2;
-}
-},onCanSelect:function(_3){
-return this.grid.onCanSelect(_3);
-},onCanDeselect:function(_4){
-return this.grid.onCanDeselect(_4);
-},onSelected:function(_5){
-},onDeselected:function(_6){
-},onChanging:function(){
-},onChanged:function(){
-},isSelected:function(_7){
-if(this.mode=="none"){
-return false;
-}
-return this.selected[_7];
-},getFirstSelected:function(){
-if(!this.selected.length||this.mode=="none"){
-return -1;
-}
-for(var i=0,l=this.selected.length;i<l;i++){
-if(this.selected[i]){
-return i;
-}
-}
-return -1;
-},getNextSelected:function(_8){
-if(this.mode=="none"){
-return -1;
-}
-for(var i=_8+1,l=this.selected.length;i<l;i++){
-if(this.selected[i]){
-return i;
-}
-}
-return -1;
-},getSelected:function(){
-var _9=[];
-for(var i=0,l=this.selected.length;i<l;i++){
-if(this.selected[i]){
-_9.push(i);
-}
-}
-return _9;
-},getSelectedCount:function(){
-var c=0;
-for(var i=0;i<this.selected.length;i++){
-if(this.selected[i]){
-c++;
-}
-}
-return c;
-},_beginUpdate:function(){
-if(this.updating===0){
-this.onChanging();
-}
-this.updating++;
-},_endUpdate:function(){
-this.updating--;
-if(this.updating===0){
-this.onChanged();
-}
-},select:function(_a){
-if(this.mode=="none"){
-return;
-}
-if(this.mode!="multiple"){
-this.deselectAll(_a);
-this.addToSelection(_a);
-}else{
-this.toggleSelect(_a);
-}
-},addToSelection:function(_b){
-if(this.mode=="none"){
-return;
-}
-if(dojo.isArray(_b)){
-dojo.forEach(_b,this.addToSelection,this);
-return;
-}
-_b=Number(_b);
-if(this.selected[_b]){
-this.selectedIndex=_b;
-}else{
-if(this.onCanSelect(_b)!==false){
-this.selectedIndex=_b;
-var _c=this.grid.getRowNode(_b);
-if(_c){
-dojo.attr(_c,"aria-selected","true");
-}
-this._beginUpdate();
-this.selected[_b]=true;
-this.onSelected(_b);
-this._endUpdate();
-}
-}
-},deselect:function(_d){
-if(this.mode=="none"){
-return;
-}
-if(dojo.isArray(_d)){
-dojo.forEach(_d,this.deselect,this);
-return;
-}
-_d=Number(_d);
-if(this.selectedIndex==_d){
-this.selectedIndex=-1;
-}
-if(this.selected[_d]){
-if(this.onCanDeselect(_d)===false){
-return;
-}
-var _e=this.grid.getRowNode(_d);
-if(_e){
-dojo.attr(_e,"aria-selected","false");
-}
-this._beginUpdate();
-delete this.selected[_d];
-this.onDeselected(_d);
-this._endUpdate();
-}
-},setSelected:function(_f,_10){
-this[(_10?"addToSelection":"deselect")](_f);
-},toggleSelect:function(_11){
-if(dojo.isArray(_11)){
-dojo.forEach(_11,this.toggleSelect,this);
-return;
-}
-this.setSelected(_11,!this.selected[_11]);
-},_range:function(_12,_13,_14){
-var s=(_12>=0?_12:_13),e=_13;
-if(s>e){
-e=s;
-s=_13;
-}
-for(var i=s;i<=e;i++){
-_14(i);
-}
-},selectRange:function(_15,_16){
-this._range(_15,_16,dojo.hitch(this,"addToSelection"));
-},deselectRange:function(_17,_18){
-this._range(_17,_18,dojo.hitch(this,"deselect"));
-},insert:function(_19){
-this.selected.splice(_19,0,false);
-if(this.selectedIndex>=_19){
-this.selectedIndex++;
-}
-},remove:function(_1a){
-this.selected.splice(_1a,1);
-if(this.selectedIndex>=_1a){
-this.selectedIndex--;
-}
-},deselectAll:function(_1b){
-for(var i in this.selected){
-if((i!=_1b)&&(this.selected[i]===true)){
-this.deselect(i);
-}
-}
-},clickSelect:function(_1c,_1d,_1e){
-if(this.mode=="none"){
-return;
-}
-this._beginUpdate();
-if(this.mode!="extended"){
-this.select(_1c);
-}else{
-var _1f=this.selectedIndex;
-if(!_1d){
-this.deselectAll(_1c);
-}
-if(_1e){
-this.selectRange(_1f,_1c);
-}else{
-if(_1d){
-this.toggleSelect(_1c);
-}else{
-this.addToSelection(_1c);
-}
-}
-}
-this._endUpdate();
-},clickSelectEvent:function(e){
-this.clickSelect(e.rowIndex,dojo.isCopyKey(e),e.shiftKey);
-},clear:function(){
-this._beginUpdate();
-this.deselectAll();
-this._endUpdate();
-}});
-}
+dojo.provide('dojox.grid.Selection');
+
+dojo.declare("dojox.grid.Selection", null, {
+	// summary:
+	//		Manages row selection for grid. Owned by grid and used internally
+	//		for selection. Override to implement custom selection.
+
+	constructor: function(inGrid){
+		this.grid = inGrid;
+		this.selected = [];
+
+		this.setMode(inGrid.selectionMode);
+	},
+
+	mode: 'extended',
+
+	selected: null,
+	updating: 0,
+	selectedIndex: -1,
+
+	setMode: function(mode){
+		if(this.selected.length){
+			this.deselectAll();
+		}
+		if(mode != 'extended' && mode != 'multiple' && mode != 'single' && mode != 'none'){
+			this.mode = 'extended';
+		}else{
+			this.mode = mode;
+		}
+	},
+
+	onCanSelect: function(inIndex){
+		return this.grid.onCanSelect(inIndex);
+	},
+
+	onCanDeselect: function(inIndex){
+		return this.grid.onCanDeselect(inIndex);
+	},
+
+	onSelected: function(inIndex){
+	},
+
+	onDeselected: function(inIndex){
+	},
+
+	//onSetSelected: function(inIndex, inSelect) { };
+	onChanging: function(){
+	},
+
+	onChanged: function(){
+	},
+
+	isSelected: function(inIndex){
+		if(this.mode == 'none'){
+			return false;
+		}
+		return this.selected[inIndex];
+	},
+
+	getFirstSelected: function(){
+		if(!this.selected.length||this.mode == 'none'){ return -1; }
+		for(var i=0, l=this.selected.length; i<l; i++){
+			if(this.selected[i]){
+				return i;
+			}
+		}
+		return -1;
+	},
+
+	getNextSelected: function(inPrev){
+		if(this.mode == 'none'){ return -1; }
+		for(var i=inPrev+1, l=this.selected.length; i<l; i++){
+			if(this.selected[i]){
+				return i;
+			}
+		}
+		return -1;
+	},
+
+	getSelected: function(){
+		var result = [];
+		for(var i=0, l=this.selected.length; i<l; i++){
+			if(this.selected[i]){
+				result.push(i);
+			}
+		}
+		return result;
+	},
+
+	getSelectedCount: function(){
+		var c = 0;
+		for(var i=0; i<this.selected.length; i++){
+			if(this.selected[i]){
+				c++;
+			}
+		}
+		return c;
+	},
+
+	_beginUpdate: function(){
+		if(this.updating === 0){
+			this.onChanging();
+		}
+		this.updating++;
+	},
+
+	_endUpdate: function(){
+		this.updating--;
+		if(this.updating === 0){
+			this.onChanged();
+		}
+	},
+
+	select: function(inIndex){
+		if(this.mode == 'none'){ return; }
+		if(this.mode != 'multiple'){
+			this.deselectAll(inIndex);
+			this.addToSelection(inIndex);
+		}else{
+			this.toggleSelect(inIndex);
+		}
+	},
+
+	addToSelection: function(inIndex){
+		if(this.mode == 'none'){ return; }
+		if(dojo.isArray(inIndex)){
+			dojo.forEach(inIndex, this.addToSelection, this);
+			return;
+		}
+		inIndex = Number(inIndex);
+		if(this.selected[inIndex]){
+			this.selectedIndex = inIndex;
+		}else{
+			if(this.onCanSelect(inIndex) !== false){
+				this.selectedIndex = inIndex;
+				var rowNode = this.grid.getRowNode(inIndex);
+				if(rowNode){
+					dojo.attr(rowNode,"aria-selected","true");
+				}
+				this._beginUpdate();
+				this.selected[inIndex] = true;
+				//this.grid.onSelected(inIndex);
+				this.onSelected(inIndex);
+				//this.onSetSelected(inIndex, true);
+				this._endUpdate();
+			}
+		}
+	},
+
+	deselect: function(inIndex){
+		if(this.mode == 'none'){ return; }
+		if(dojo.isArray(inIndex)){
+			dojo.forEach(inIndex, this.deselect, this);
+			return;
+		}
+		inIndex = Number(inIndex);
+		if(this.selectedIndex == inIndex){
+			this.selectedIndex = -1;
+		}
+		if(this.selected[inIndex]){
+			if(this.onCanDeselect(inIndex) === false){
+				return;
+			}
+			var rowNode = this.grid.getRowNode(inIndex);
+			if(rowNode){
+				dojo.attr(rowNode,"aria-selected","false");
+			}
+			this._beginUpdate();
+			delete this.selected[inIndex];
+			//this.grid.onDeselected(inIndex);
+			this.onDeselected(inIndex);
+			//this.onSetSelected(inIndex, false);
+			this._endUpdate();
+		}
+	},
+
+	setSelected: function(inIndex, inSelect){
+		this[(inSelect ? 'addToSelection' : 'deselect')](inIndex);
+	},
+
+	toggleSelect: function(inIndex){
+		if(dojo.isArray(inIndex)){
+			dojo.forEach(inIndex, this.toggleSelect, this);
+			return;
+		}
+		this.setSelected(inIndex, !this.selected[inIndex]);
+	},
+
+	_range: function(inFrom, inTo, func){
+		var s = (inFrom >= 0 ? inFrom : inTo), e = inTo;
+		if(s > e){
+			e = s;
+			s = inTo;
+		}
+		for(var i=s; i<=e; i++){
+			func(i);
+		}
+	},
+
+	selectRange: function(inFrom, inTo){
+		this._range(inFrom, inTo, dojo.hitch(this, "addToSelection"));
+	},
+
+	deselectRange: function(inFrom, inTo){
+		this._range(inFrom, inTo, dojo.hitch(this, "deselect"));
+	},
+
+	insert: function(inIndex){
+		this.selected.splice(inIndex, 0, false);
+		if(this.selectedIndex >= inIndex){
+			this.selectedIndex++;
+		}
+	},
+
+	remove: function(inIndex){
+		this.selected.splice(inIndex, 1);
+		if(this.selectedIndex >= inIndex){
+			this.selectedIndex--;
+		}
+	},
+
+	deselectAll: function(inExcept){
+		for(var i in this.selected){
+			if((i!=inExcept)&&(this.selected[i]===true)){
+				this.deselect(i);
+			}
+		}
+	},
+
+	clickSelect: function(inIndex, inCtrlKey, inShiftKey){
+		if(this.mode == 'none'){ return; }
+		this._beginUpdate();
+		if(this.mode != 'extended'){
+			this.select(inIndex);
+		}else{
+			var lastSelected = this.selectedIndex;
+			if(!inCtrlKey){
+				this.deselectAll(inIndex);
+			}
+			if(inShiftKey){
+				this.selectRange(lastSelected, inIndex);
+			}else if(inCtrlKey){
+				this.toggleSelect(inIndex);
+			}else{
+				this.addToSelection(inIndex);
+			}
+		}
+		this._endUpdate();
+	},
+
+	clickSelectEvent: function(e){
+		this.clickSelect(e.rowIndex, dojo.isCopyKey(e), e.shiftKey);
+	},
+
+	clear: function(){
+		this._beginUpdate();
+		this.deselectAll();
+		this._endUpdate();
+	}
+});
diff --git a/dojox/grid/TreeGrid.js b/dojox/grid/TreeGrid.js
index fb56efc..7dc14fb 100644
--- a/dojox/grid/TreeGrid.js
+++ b/dojox/grid/TreeGrid.js
@@ -1,727 +1,939 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.TreeGrid"]){
-dojo._hasResource["dojox.grid.TreeGrid"]=true;
 dojo.experimental("dojox.grid.TreeGrid");
+
 dojo.provide("dojox.grid.TreeGrid");
+
 dojo.require("dojox.grid.DataGrid");
 dojo.require("dojox.grid._TreeView");
 dojo.require("dojox.grid.cells.tree");
 dojo.require("dojox.grid.TreeSelection");
-dojo.declare("dojox.grid._TreeAggregator",null,{cells:[],grid:null,childFields:[],constructor:function(_1){
-this.cells=_1.cells||[];
-this.childFields=_1.childFields||[];
-this.grid=_1.grid;
-this.store=this.grid.store;
-},_cacheValue:function(_2,id,_3){
-_2[id]=_3;
-return _3;
-},clearSubtotalCache:function(){
-if(this.store){
-delete this.store._cachedAggregates;
-}
-},cnt:function(_4,_5,_6){
-var _7=0;
-var _8=this.store;
-var _9=this.childFields;
-if(_9[_5]){
-var _a=_8.getValues(_6,_9[_5]);
-if(_4.index<=_5+1){
-_7=_a.length;
-}else{
-dojo.forEach(_a,function(c){
-_7+=this.getForCell(_4,_5+1,c,"cnt");
-},this);
-}
-}else{
-_7=1;
-}
-return _7;
-},sum:function(_b,_c,_d){
-var _e=0;
-var _f=this.store;
-var _10=this.childFields;
-if(_10[_c]){
-dojo.forEach(_f.getValues(_d,_10[_c]),function(c){
-_e+=this.getForCell(_b,_c+1,c,"sum");
-},this);
-}else{
-_e+=_f.getValue(_d,_b.field);
-}
-return _e;
-},value:function(_11,_12,_13){
-},getForCell:function(_14,_15,_16,_17){
-var _18=this.store;
-if(!_18||!_16||!_18.isItem(_16)){
-return "";
-}
-var _19=_18._cachedAggregates=_18._cachedAggregates||{};
-var id=_18.getIdentity(_16);
-var _1a=_19[id]=_19[id]||[];
-if(!_14.getOpenState){
-_14=this.grid.getCell(_14.layoutIndex+_15+1);
-}
-var idx=_14.index;
-var _1b=_1a[idx]=_1a[idx]||{};
-_17=(_17||(_14.parentCell?_14.parentCell.aggregate:"sum"))||"sum";
-var _1c=_14.field;
-if(_1c==_18.getLabelAttributes()[0]){
-_17="cnt";
-}
-var _1d=_1b[_17]=_1b[_17]||[];
-if(_1d[_15]!=undefined){
-return _1d[_15];
-}
-var _1e=((_14.parentCell&&_14.parentCell.itemAggregates)?_14.parentCell.itemAggregates[_14.idxInParent]:"")||"";
-if(_1e&&_18.hasAttribute(_16,_1e)){
-return this._cacheValue(_1d,_15,_18.getValue(_16,_1e));
-}else{
-if(_1e){
-return this._cacheValue(_1d,_15,0);
-}
-}
-return this._cacheValue(_1d,_15,this[_17](_14,_15,_16));
-}});
-dojo.declare("dojox.grid._TreeLayout",dojox.grid._Layout,{_isCollapsable:false,_getInternalStructure:function(_1f){
-var g=this.grid;
-var s=_1f;
-var _20=s[0].cells[0];
-var _21={type:"dojox.grid._TreeView",cells:[[]]};
-var _22=[];
-var _23=0;
-var _24=function(_25,_26){
-var _27=_25.children;
-var _28=function(_29,idx){
-var k,n={};
-for(k in _29){
-n[k]=_29[k];
-}
-n=dojo.mixin(n,{level:_26,idxInParent:_26>0?idx:-1,parentCell:_26>0?_25:null});
-return n;
-};
-var ret=[];
-dojo.forEach(_27,function(c,idx){
-if("children" in c){
-_22.push(c.field);
-var _2a=ret[ret.length-1];
-_2a.isCollapsable=true;
-c.level=_26;
-ret=ret.concat(_24(c,_26+1));
-}else{
-ret.push(_28(c,idx));
-}
-});
-_23=Math.max(_23,_26);
-return ret;
-};
-var _2b={children:_20,itemAggregates:[]};
-_21.cells[0]=_24(_2b,0);
-g.aggregator=new dojox.grid._TreeAggregator({cells:_21.cells[0],grid:g,childFields:_22});
-if(g.scroller&&g.defaultOpen){
-g.scroller.defaultRowHeight=g.scroller._origDefaultRowHeight*(2*_23+1);
-}
-return [_21];
-},setStructure:function(_2c){
-var s=_2c;
-var g=this.grid;
-if(g&&g.treeModel&&!dojo.every(s,function(i){
-return ("cells" in i);
-})){
-s=arguments[0]=[{cells:[s]}];
-}
-if(s.length==1&&s[0].cells.length==1){
-if(g&&g.treeModel){
-s[0].type="dojox.grid._TreeView";
-this._isCollapsable=true;
-s[0].cells[0][(this.grid.treeModel?this.grid.expandoCell:0)].isCollapsable=true;
-}else{
-var _2d=dojo.filter(s[0].cells[0],function(c){
-return ("children" in c);
-});
-if(_2d.length===1){
-this._isCollapsable=true;
-}
-}
-}
-if(this._isCollapsable&&(!g||!g.treeModel)){
-arguments[0]=this._getInternalStructure(s);
-}
-this.inherited(arguments);
-},addCellDef:function(_2e,_2f,_30){
-var obj=this.inherited(arguments);
-return dojo.mixin(obj,dojox.grid.cells.TreeCell);
-}});
-dojo.declare("dojox.grid.TreePath",null,{level:0,_str:"",_arr:null,grid:null,store:null,cell:null,item:null,constructor:function(_31,_32){
-if(dojo.isString(_31)){
-this._str=_31;
-this._arr=dojo.map(_31.split("/"),function(_33){
-return parseInt(_33,10);
-});
-}else{
-if(dojo.isArray(_31)){
-this._str=_31.join("/");
-this._arr=_31.slice(0);
-}else{
-if(typeof _31=="number"){
-this._str=String(_31);
-this._arr=[_31];
-}else{
-this._str=_31._str;
-this._arr=_31._arr.slice(0);
-}
-}
-}
-this.level=this._arr.length-1;
-this.grid=_32;
-this.store=this.grid.store;
-if(_32.treeModel){
-this.cell=_32.layout.cells[_32.expandoCell];
-}else{
-this.cell=_32.layout.cells[this.level];
-}
-},item:function(){
-if(!this._item){
-this._item=this.grid.getItem(this._arr);
-}
-return this._item;
-},compare:function(_34){
-if(dojo.isString(_34)||dojo.isArray(_34)){
-if(this._str==_34){
-return 0;
-}
-if(_34.join&&this._str==_34.join("/")){
-return 0;
-}
-_34=new dojox.grid.TreePath(_34,this.grid);
-}else{
-if(_34 instanceof dojox.grid.TreePath){
-if(this._str==_34._str){
-return 0;
-}
-}
-}
-for(var i=0,l=(this._arr.length<_34._arr.length?this._arr.length:_34._arr.length);i<l;i++){
-if(this._arr[i]<_34._arr[i]){
-return -1;
-}
-if(this._arr[i]>_34._arr[i]){
-return 1;
-}
-}
-if(this._arr.length<_34._arr.length){
-return -1;
-}
-if(this._arr.length>_34._arr.length){
-return 1;
-}
-return 0;
-},isOpen:function(){
-return this.cell.openStates&&this.cell.getOpenState(this.item());
-},previous:function(){
-var _35=this._arr.slice(0);
-if(this._str=="0"){
-return null;
-}
-var _36=_35.length-1;
-if(_35[_36]===0){
-_35.pop();
-return new dojox.grid.TreePath(_35,this.grid);
-}
-_35[_36]--;
-var _37=new dojox.grid.TreePath(_35,this.grid);
-return _37.lastChild(true);
-},next:function(){
-var _38=this._arr.slice(0);
-if(this.isOpen()){
-_38.push(0);
-}else{
-_38[_38.length-1]++;
-for(var i=this.level;i>=0;i--){
-var _39=this.grid.getItem(_38.slice(0,i+1));
-if(i>0){
-if(!_39){
-_38.pop();
-_38[i-1]++;
-}
-}else{
-if(!_39){
-return null;
-}
-}
-}
-}
-return new dojox.grid.TreePath(_38,this.grid);
-},children:function(_3a){
-if(!this.isOpen()&&!_3a){
-return null;
-}
-var _3b=[];
-var _3c=this.grid.treeModel;
-if(_3c){
-var _3d=this.item();
-var _3e=_3c.store;
-if(!_3c.mayHaveChildren(_3d)){
-return null;
-}
-dojo.forEach(_3c.childrenAttrs,function(_3f){
-_3b=_3b.concat(_3e.getValues(_3d,_3f));
+
+dojo.declare("dojox.grid._TreeAggregator", null, {
+	cells: [],
+	grid: null,
+	childFields: [],
+	
+	constructor: function(kwArgs){
+		this.cells = kwArgs.cells || [];
+		this.childFields = kwArgs.childFields || [];
+		this.grid = kwArgs.grid;
+		this.store = this.grid.store;
+	},
+	_cacheValue: function(cache, id, value){
+		cache[id] = value;
+		return value;
+	},
+	clearSubtotalCache: function(){
+		// summary:
+		//		Clears the subtotal cache so that we are forced to recalc it
+		//		(or reread it) again.  This is needed, for example, when
+		//		column order is changed.
+		if(this.store){
+			delete this.store._cachedAggregates;
+		}
+	},
+	
+	cnt: function(cell, level, item){
+		// summary:
+		//		calculates the count of the children of item at the given level
+		var total = 0;
+		var store = this.store;
+		var childFields = this.childFields;
+		if(childFields[level]){
+			var children = store.getValues(item, childFields[level]);
+			if (cell.index <= level + 1){
+				total = children.length;
+			}else{
+				dojo.forEach(children, function(c){
+					total += this.getForCell(cell, level + 1, c, "cnt");
+				}, this);
+			}
+		}else{
+			total = 1;
+		}
+		return total;
+	},
+	sum: function(cell, level, item){
+		// summary:
+		//		calculates the sum of the children of item at the given level
+		var total = 0;
+		var store = this.store;
+		var childFields = this.childFields;
+		if(childFields[level]){
+			dojo.forEach(store.getValues(item, childFields[level]), function(c){
+				total += this.getForCell(cell, level + 1, c, "sum");
+			}, this);
+		}else{
+			total += store.getValue(item, cell.field);
+		}
+		return total;
+	},
+	value: function(cell, level, item){
+		// summary:
+		//		Empty function so that we can set "aggregate='value'" to
+		//		force loading from the data - and bypass calculating
+	},
+	getForCell: function(cell, level, item, type){
+		// summary:
+		//		Gets the value of the given cell at the given level and type.
+		//		type can be one of "sum", "cnt", or "value".  If itemAggregates
+		//		is set and can be used, it is used instead.  Values are also
+		//		cached to prevent calculating them too often.
+		var store = this.store;
+		if(!store || !item || !store.isItem(item)){ return ""; }
+		var storeCache = store._cachedAggregates = store._cachedAggregates || {};
+		var id = store.getIdentity(item);
+		var itemCache = storeCache[id] = storeCache[id] || [];
+		if(!cell.getOpenState){
+			cell = this.grid.getCell(cell.layoutIndex + level + 1);
+		}
+		var idx = cell.index;
+		var idxCache = itemCache[idx] = itemCache[idx] || {};
+		type = (type || (cell.parentCell ? cell.parentCell.aggregate : "sum"))||"sum";
+		var attr = cell.field;
+		if(attr == store.getLabelAttributes()[0]){
+			// If our attribute is one of the label attributes, we should
+			// use cnt instead (since it makes no sense to do a sum of labels)
+			type = "cnt";
+		}
+		var typeCache = idxCache[type] = idxCache[type] || [];
+
+		// See if we have it in our cache immediately for easy returning
+		if(typeCache[level] != undefined){
+			return typeCache[level];
+		}
+
+		// See if they have specified a valid field
+		var field = ((cell.parentCell && cell.parentCell.itemAggregates) ? 
+							cell.parentCell.itemAggregates[cell.idxInParent] : "")||"";
+		if(field && store.hasAttribute(item, field)){
+			return this._cacheValue(typeCache, level, store.getValue(item, field));
+		}else if(field){
+			return this._cacheValue(typeCache, level, 0);
+		}
+		
+		// Calculate it
+		return this._cacheValue(typeCache, level, this[type](cell, level, item));
+	}
 });
-}else{
-_3b=this.store.getValues(this.item(),this.grid.layout.cells[this.cell.level+1].parentCell.field);
-if(_3b.length>1&&this.grid.sortChildItems){
-var _40=this.grid.getSortProps();
-if(_40&&_40.length){
-var _41=_40[0].attribute,_42=this.grid;
-if(_41&&_3b[0][_41]){
-var _43=!!_40[0].descending;
-_3b=_3b.slice(0);
-_3b.sort(function(a,b){
-return _42._childItemSorter(a,b,_41,_43);
+
+dojo.declare("dojox.grid._TreeLayout", dojox.grid._Layout, {
+	// Whether or not we are collapsable - this is calculated when we
+	// set our structure.
+	_isCollapsable: false,
+	
+	_getInternalStructure: function(inStructure){
+		//	Create a "Tree View" with 1 row containing references for
+		//		each column (recursively)
+		var g = this.grid;
+		
+		var s = inStructure;
+		var cells = s[0].cells[0];
+		var tree = {
+			type: "dojox.grid._TreeView",
+			cells: [[]]
+		};
+		var cFields = [];
+		var maxLevels = 0;
+		var getTreeCells = function(parentCell, level){
+			var children = parentCell.children;
+			var cloneTreeCell = function(originalCell, idx){
+				var k, n = {};
+				for(k in originalCell){
+					n[k] = originalCell[k];
+				}
+				n = dojo.mixin(n, {
+					level: level,
+					idxInParent: level > 0 ? idx : -1,
+					parentCell: level > 0 ? parentCell : null
+				});
+				return n;
+			};
+			var ret = [];
+			dojo.forEach(children, function(c, idx){
+				if("children" in c){
+					cFields.push(c.field);
+					var last = ret[ret.length - 1];
+					last.isCollapsable = true;
+					c.level = level;
+					ret = ret.concat(getTreeCells(c, level + 1));
+				}else{
+					ret.push(cloneTreeCell(c, idx));
+				}
+			});
+			maxLevels = Math.max(maxLevels, level);
+			return ret;
+		};
+		var tCell = {children: cells, itemAggregates: []};
+		tree.cells[0] = getTreeCells(tCell, 0);
+		g.aggregator = new dojox.grid._TreeAggregator({cells: tree.cells[0], 
+														grid: g,
+														childFields: cFields});
+		if(g.scroller && g.defaultOpen){
+			g.scroller.defaultRowHeight = g.scroller._origDefaultRowHeight * (2 * maxLevels + 1);
+		}
+		return [ tree ];
+	},
+
+	setStructure: function(inStructure){
+		// Mangle the structure a bit and make it work as desired
+		var s = inStructure;
+		var g = this.grid;
+		// Only supporting single-view, single row or else we
+		// are not collapsable
+		if(g && g.treeModel && !dojo.every(s, function(i){
+			return ("cells" in i);
+		})){
+			s = arguments[0] = [{cells:[s]}];			
+		}
+		if(s.length == 1 && s[0].cells.length == 1){
+			if(g && g.treeModel){
+				s[0].type = "dojox.grid._TreeView";
+				this._isCollapsable = true;
+				s[0].cells[0][(this.grid.treeModel?this.grid.expandoCell:0)].isCollapsable = true;
+			}else{
+				var childCells = dojo.filter(s[0].cells[0], function(c){
+					return ("children" in c);
+				});
+				if(childCells.length === 1){
+					this._isCollapsable = true;
+				}			
+			}
+		}
+		if(this._isCollapsable && (!g || !g.treeModel)){
+			arguments[0] = this._getInternalStructure(s);
+		}
+		this.inherited(arguments);
+	},
+
+	addCellDef: function(inRowIndex, inCellIndex, inDef){
+		var obj = this.inherited(arguments);
+		return dojo.mixin(obj, dojox.grid.cells.TreeCell);
+	}
 });
-}
-}
-}
-}
-return _3b;
-},childPaths:function(){
-var _44=this.children();
-if(!_44){
-return [];
-}
-return dojo.map(_44,function(_45,_46){
-return new dojox.grid.TreePath(this._str+"/"+_46,this.grid);
-},this);
-},parent:function(){
-if(this.level===0){
-return null;
-}
-return new dojox.grid.TreePath(this._arr.slice(0,this.level),this.grid);
-},lastChild:function(_47){
-var _48=this.children();
-if(!_48||!_48.length){
-return this;
-}
-var _49=new dojox.grid.TreePath(this._str+"/"+String(_48.length-1),this.grid);
-if(!_47){
-return _49;
-}
-return _49.lastChild(true);
-},toString:function(){
-return this._str;
-}});
-dojo.declare("dojox.grid._TreeFocusManager",dojox.grid._FocusManager,{setFocusCell:function(_4a,_4b){
-if(_4a&&_4a.getNode(_4b)){
-this.inherited(arguments);
-}
-},isLastFocusCell:function(){
-if(this.cell&&this.cell.index==this.grid.layout.cellCount-1){
-var _4c=new dojox.grid.TreePath(this.grid.rowCount-1,this.grid);
-_4c=_4c.lastChild(true);
-return this.rowIndex==_4c._str;
-}
-return false;
-},next:function(){
-if(this.cell){
-var row=this.rowIndex,col=this.cell.index+1,cc=this.grid.layout.cellCount-1;
-var _4d=new dojox.grid.TreePath(this.rowIndex,this.grid);
-if(col>cc){
-var _4e=_4d.next();
-if(!_4e){
-col--;
-}else{
-col=0;
-_4d=_4e;
-}
-}
-if(this.grid.edit.isEditing()){
-var _4f=this.grid.getCell(col);
-if(!this.isLastFocusCell()&&!_4f.editable){
-this._focusifyCellNode(false);
-this.cell=_4f;
-this.rowIndex=_4d._str;
-this.next();
-return;
-}
-}
-this.setFocusIndex(_4d._str,col);
-}
-},previous:function(){
-if(this.cell){
-var row=(this.rowIndex||0),col=(this.cell.index||0)-1;
-var _50=new dojox.grid.TreePath(row,this.grid);
-if(col<0){
-var _51=_50.previous();
-if(!_51){
-col=0;
-}else{
-col=this.grid.layout.cellCount-1;
-_50=_51;
-}
-}
-if(this.grid.edit.isEditing()){
-var _52=this.grid.getCell(col);
-if(!this.isFirstFocusCell()&&!_52.editable){
-this._focusifyCellNode(false);
-this.cell=_52;
-this.rowIndex=_50._str;
-this.previous();
-return;
-}
-}
-this.setFocusIndex(_50._str,col);
-}
-},move:function(_53,_54){
-if(this.isNavHeader()){
-this.inherited(arguments);
-return;
-}
-if(!this.cell){
-return;
-}
-var sc=this.grid.scroller,r=this.rowIndex,rc=this.grid.rowCount-1,_55=new dojox.grid.TreePath(this.rowIndex,this.grid);
-if(_53){
-var row;
-if(_53>0){
-_55=_55.next();
-row=_55._arr[0];
-if(row>sc.getLastPageRow(sc.page)){
-this.grid.setScrollTop(this.grid.scrollTop+sc.findScrollTop(row)-sc.findScrollTop(r));
-}
-}else{
-if(_53<0){
-_55=_55.previous();
-row=_55._arr[0];
-if(row<=sc.getPageRow(sc.page)){
-this.grid.setScrollTop(this.grid.scrollTop-sc.findScrollTop(r)-sc.findScrollTop(row));
-}
-}
-}
-}
-var cc=this.grid.layout.cellCount-1,i=this.cell.index,col=Math.min(cc,Math.max(0,i+_54));
-var _56=this.grid.getCell(col);
-var _57=_54<0?-1:1;
-while(col>=0&&col<cc&&_56&&_56.hidden===true){
-col+=_57;
-_56=this.grid.getCell(col);
-}
-if(!_56||_56.hidden===true){
-col=i;
-}
-if(_53){
-this.grid.updateRow(r);
-}
-this.setFocusIndex(_55._str,col);
-}});
-dojo.declare("dojox.grid.TreeGrid",dojox.grid.DataGrid,{defaultOpen:true,sortChildItems:false,openAtLevels:[],treeModel:null,expandoCell:0,aggregator:null,_layoutClass:dojox.grid._TreeLayout,createSelection:function(){
-this.selection=new dojox.grid.TreeSelection(this);
-},_childItemSorter:function(a,b,_58,_59){
-var av=this.store.getValue(a,_58);
-var bv=this.store.getValue(b,_58);
-if(av!=bv){
-return av<bv==_59?1:-1;
-}
-return 0;
-},_onNew:function(_5a,_5b){
-if(!_5b||!_5b.item){
-this.inherited(arguments);
-}else{
-var idx=this.getItemIndex(_5b.item);
-if(typeof idx=="string"){
-this.updateRow(idx.split("/")[0]);
-}else{
-if(idx>-1){
-this.updateRow(idx);
-}
-}
-}
-},_onSet:function(_5c,_5d,_5e,_5f){
-this._checkUpdateStatus();
-if(this.aggregator){
-this.aggregator.clearSubtotalCache();
-}
-var idx=this.getItemIndex(_5c);
-if(typeof idx=="string"){
-this.updateRow(idx.split("/")[0]);
-}else{
-if(idx>-1){
-this.updateRow(idx);
-}
-}
-},_onDelete:function(_60){
-this._cleanupExpandoCache(this._getItemIndex(_60,true),this.store.getIdentity(_60),_60);
-this.inherited(arguments);
-},_cleanupExpandoCache:function(_61,_62,_63){
-},_addItem:function(_64,_65,_66,_67){
-if(!_67&&this.model&&dojo.indexOf(this.model.root.children,_64)==-1){
-this.model.root.children[_65]=_64;
-}
-this.inherited(arguments);
-},getItem:function(idx){
-var _68=dojo.isArray(idx);
-if(dojo.isString(idx)&&idx.indexOf("/")){
-idx=idx.split("/");
-_68=true;
-}
-if(_68&&idx.length==1){
-idx=idx[0];
-_68=false;
-}
-if(!_68){
-return dojox.grid.DataGrid.prototype.getItem.call(this,idx);
-}
-var s=this.store;
-var itm=dojox.grid.DataGrid.prototype.getItem.call(this,idx[0]);
-var cf;
-if(this.aggregator){
-cf=this.aggregator.childFields||[];
-}else{
-if(this.treeModel){
-cf=this.treeModel.childrenAttrs||[];
-}
-}
-if(cf){
-for(var i=0;i<idx.length-1&&itm;i++){
-if(cf[i]){
-itm=(s.getValues(itm,cf[i])||[])[idx[i+1]];
-}else{
-itm=null;
-}
-}
-}
-return itm||null;
-},_getItemIndex:function(_69,_6a){
-if(!_6a&&!this.store.isItem(_69)){
-return -1;
-}
-var idx=this.inherited(arguments);
-if(idx==-1){
-var _6b=this.store.getIdentity(_69);
-return this._by_idty_paths[_6b]||-1;
-}
-return idx;
-},postMixInProperties:function(){
-if(this.treeModel&&!("defaultOpen" in this.params)){
-this.defaultOpen=false;
-}
-var def=this.defaultOpen;
-this.openAtLevels=dojo.map(this.openAtLevels,function(l){
-if(typeof l=="string"){
-switch(l.toLowerCase()){
-case "true":
-return true;
-break;
-case "false":
-return false;
-break;
-default:
-var r=parseInt(l,10);
-if(isNaN(r)){
-return def;
-}
-return r;
-break;
-}
-}
-return l;
+
+dojo.declare("dojox.grid.TreePath", null, {
+	level: 0,
+	_str: "",
+	_arr: null,
+	grid: null,
+	store: null,
+	cell: null,
+	item: null,
+
+	constructor: function(/*String|Integer[]|Integer|dojox.grid.TreePath*/ path, /*dojox.grid.TreeGrid*/ grid){
+		if(dojo.isString(path)){
+			this._str = path;
+			this._arr = dojo.map(path.split('/'), function(item){ return parseInt(item, 10); });
+		}else if(dojo.isArray(path)){
+			this._str = path.join('/');
+			this._arr = path.slice(0);
+		}else if(typeof path == "number"){
+			this._str = String(path);
+			this._arr = [path];
+		}else{
+			this._str = path._str;
+			this._arr = path._arr.slice(0);
+		}
+		this.level = this._arr.length-1;
+		this.grid = grid;
+		this.store = this.grid.store;
+		if(grid.treeModel){
+			this.cell = grid.layout.cells[grid.expandoCell];
+		}else{
+			this.cell = grid.layout.cells[this.level];
+		}
+	},
+	item: function(){
+		// summary:
+		//	gets the dojo.data item associated with this path
+		if(!this._item){
+			this._item = this.grid.getItem(this._arr);
+		}
+		return this._item;
+	},
+	compare: function(path /*dojox.grid.TreePath|String|Array*/){
+		// summary:
+		//	compares two paths
+		if(dojo.isString(path) || dojo.isArray(path)){
+			if(this._str == path){ return 0; }
+			if(path.join && this._str == path.join('/')){ return 0; }
+			path = new dojox.grid.TreePath(path, this.grid);
+		}else if(path instanceof dojox.grid.TreePath){
+			if(this._str == path._str){ return 0; }
+		}
+		for(var i=0, l=(this._arr.length < path._arr.length ? this._arr.length : path._arr.length); i<l; i++){
+			if(this._arr[i]<path._arr[i]){ return -1; }
+			if(this._arr[i]>path._arr[i]){ return 1; }
+		}
+		if(this._arr.length<path._arr.length){ return -1; }
+		if(this._arr.length>path._arr.length){ return 1; }
+		return 0;
+	},
+	isOpen: function(){
+		// summary:
+		//	Returns the open state of this cell.
+		return this.cell.openStates && this.cell.getOpenState(this.item());
+	},
+	previous: function(){
+		// summary:
+		//	Returns the path that is before this path in the
+		//	grid. If no path is found, returns null.
+		var new_path = this._arr.slice(0);
+
+		if(this._str == "0"){
+			return null;
+		}
+
+		var last = new_path.length-1;
+
+		if(new_path[last] === 0){
+			new_path.pop();
+			return new dojox.grid.TreePath(new_path, this.grid);
+		}
+
+		new_path[last]--;
+		var path = new dojox.grid.TreePath(new_path, this.grid);
+		return path.lastChild(true);
+	},
+	next: function(){
+		// summary:
+		//	Returns the next path in the grid.  If no path
+		//	is found, returns null.
+		var new_path = this._arr.slice(0);
+
+		if(this.isOpen()){
+			new_path.push(0);
+		}else{
+			new_path[new_path.length-1]++;
+			for(var i=this.level; i>=0; i--){
+				var item = this.grid.getItem(new_path.slice(0, i+1));
+				if(i>0){
+					if(!item){
+						new_path.pop();
+						new_path[i-1]++;
+					}
+				}else{
+					if(!item){
+						return null;
+					}
+				}
+			}
+		}
+
+		return new dojox.grid.TreePath(new_path, this.grid);
+	},
+	children: function(alwaysReturn){
+		// summary:
+		//	Returns the child data items of this row.  If this
+		//	row isn't open and alwaysReturn is falsey, returns null.
+		if(!this.isOpen()&&!alwaysReturn){
+			return null;
+		}
+		var items = [];
+		var model = this.grid.treeModel;
+		if(model){
+			var item = this.item();
+			var store = model.store;
+			if(!model.mayHaveChildren(item)){
+				return null;
+			}
+			dojo.forEach(model.childrenAttrs, function(attr){
+				items = items.concat(store.getValues(item, attr));
+			});
+		}else{
+			items = this.store.getValues(this.item(), this.grid.layout.cells[this.cell.level+1].parentCell.field);
+			if(items.length>1&&this.grid.sortChildItems){
+				var sortProps = this.grid.getSortProps();
+				if(sortProps&&sortProps.length){
+					var attr = sortProps[0].attribute,
+						grid = this.grid;
+					if(attr&&items[0][attr]){
+						var desc = !!sortProps[0].descending;
+						items = items.slice(0); // don't touch the array in the store, make a copy
+						items.sort(function(a, b){
+							return grid._childItemSorter(a, b, attr, desc);
+						});
+					}
+				}
+			}
+		}
+		return items;
+	},
+	childPaths: function(){
+		var childItems = this.children();
+		if(!childItems){
+			return [];
+		}
+		return dojo.map(childItems, function(item, index){
+			return new dojox.grid.TreePath(this._str + '/' + index, this.grid);
+		}, this);
+	},
+	parent: function(){
+		// summary:
+		//	Returns the parent path of this path.  If this is a
+		//	top-level row, returns null.
+		if(this.level === 0){
+			return null;
+		}
+		return new dojox.grid.TreePath(this._arr.slice(0, this.level), this.grid);
+	},
+	lastChild: function(/*Boolean?*/ traverse){
+		// summary:
+		//	Returns the last child row below this path.  If traverse
+		//	is true, will traverse down to find the last child row
+		//	of this branch.  If there are no children, returns itself.
+		var children = this.children();
+		if(!children || !children.length){
+			return this;
+		}
+		var path = new dojox.grid.TreePath(this._str + "/" + String(children.length-1), this.grid);
+		if(!traverse){
+			return path;
+		}
+		return path.lastChild(true);
+	},
+	toString: function(){
+		return this._str;
+	}
 });
-this._by_idty_paths={};
-this.inherited(arguments);
-},postCreate:function(){
-this.inherited(arguments);
-if(this.treeModel){
-this._setModel(this.treeModel);
-}
-},setModel:function(_6c){
-this._setModel(_6c);
-this._refresh(true);
-},_setModel:function(_6d){
-if(_6d&&(!dijit.tree.ForestStoreModel||!(_6d instanceof dijit.tree.ForestStoreModel))){
-throw new Error("dojox.grid.TreeGrid: treeModel must be an instance of dijit.tree.ForestStoreModel");
-}
-this.treeModel=_6d;
-dojo.toggleClass(this.domNode,"dojoxGridTreeModel",this.treeModel?true:false);
-this._setQuery(_6d?_6d.query:null);
-this._setStore(_6d?_6d.store:null);
-},createScroller:function(){
-this.inherited(arguments);
-this.scroller._origDefaultRowHeight=this.scroller.defaultRowHeight;
-},createManagers:function(){
-this.rows=new dojox.grid._RowManager(this);
-this.focus=new dojox.grid._TreeFocusManager(this);
-this.edit=new dojox.grid._EditManager(this);
-},_setStore:function(_6e){
-this.inherited(arguments);
-if(this.treeModel&&!this.treeModel.root.children){
-this.treeModel.root.children=[];
-}
-if(this.aggregator){
-this.aggregator.store=_6e;
-}
-},getDefaultOpenState:function(_6f,_70){
-var cf;
-var _71=this.store;
-if(this.treeModel){
-return this.defaultOpen;
-}
-if(!_6f||!_71||!_71.isItem(_70)||!(cf=this.aggregator.childFields[_6f.level])){
-return this.defaultOpen;
-}
-if(this.openAtLevels.length>_6f.level){
-var _72=this.openAtLevels[_6f.level];
-if(typeof _72=="boolean"){
-return _72;
-}else{
-if(typeof _72=="number"){
-return (_71.getValues(_70,cf).length<=_72);
-}
-}
-}
-return this.defaultOpen;
-},onStyleRow:function(row){
-if(!this.layout._isCollapsable){
-this.inherited(arguments);
-return;
-}
-var _73=dojo.attr(row.node,"dojoxTreeGridBaseClasses");
-if(_73){
-row.customClasses=_73;
-}
-var i=row;
-var _74=i.node.tagName.toLowerCase();
-i.customClasses+=(i.odd?" dojoxGridRowOdd":"")+(i.selected&&_74=="tr"?" dojoxGridRowSelected":"")+(i.over&&_74=="tr"?" dojoxGridRowOver":"");
-this.focus.styleRow(i);
-this.edit.styleRow(i);
-},styleRowNode:function(_75,_76){
-if(_76){
-if(_76.tagName.toLowerCase()=="div"&&this.aggregator){
-dojo.query("tr[dojoxTreeGridPath]",_76).forEach(function(_77){
-this.rows.styleRowNode(dojo.attr(_77,"dojoxTreeGridPath"),_77);
-},this);
-}
-this.rows.styleRowNode(_75,_76);
-}
-},onCanSelect:function(_78){
-var _79=dojo.query("tr[dojoxTreeGridPath='"+_78+"']",this.domNode);
-if(_79.length){
-if(dojo.hasClass(_79[0],"dojoxGridSummaryRow")){
-return false;
-}
-}
-return this.inherited(arguments);
-},onKeyDown:function(e){
-if(e.altKey||e.metaKey){
-return;
-}
-var dk=dojo.keys;
-switch(e.keyCode){
-case dk.UP_ARROW:
-if(!this.edit.isEditing()&&this.focus.rowIndex!="0"){
-dojo.stopEvent(e);
-this.focus.move(-1,0);
-}
-break;
-case dk.DOWN_ARROW:
-var _7a=new dojox.grid.TreePath(this.focus.rowIndex,this);
-var _7b=new dojox.grid.TreePath(this.rowCount-1,this);
-_7b=_7b.lastChild(true);
-if(!this.edit.isEditing()&&_7a.toString()!=_7b.toString()){
-dojo.stopEvent(e);
-this.focus.move(1,0);
-}
-break;
-default:
-this.inherited(arguments);
-break;
-}
-},canEdit:function(_7c,_7d){
-var _7e=_7c.getNode(_7d);
-return _7e&&this._canEdit;
-},doApplyCellEdit:function(_7f,_80,_81){
-var _82=this.getItem(_80);
-var _83=this.store.getValue(_82,_81);
-if(typeof _83=="number"){
-_7f=isNaN(_7f)?_7f:parseFloat(_7f);
-}else{
-if(typeof _83=="boolean"){
-_7f=_7f=="true"?true:_7f=="false"?false:_7f;
-}else{
-if(_83 instanceof Date){
-var _84=new Date(_7f);
-_7f=isNaN(_84.getTime())?_7f:_84;
-}
-}
-}
-this.store.setValue(_82,_81,_7f);
-this.onApplyCellEdit(_7f,_80,_81);
-}});
-dojox.grid.TreeGrid.markupFactory=function(_85,_86,_87,_88){
-var d=dojo;
-var _89=function(n){
-var w=d.attr(n,"width")||"auto";
-if((w!="auto")&&(w.slice(-2)!="em")&&(w.slice(-1)!="%")){
-w=parseInt(w,10)+"px";
-}
-return w;
-};
-var _8a=function(_8b){
-var _8c;
-if(_8b.nodeName.toLowerCase()=="table"&&d.query("> colgroup",_8b).length===0&&(_8c=d.query("> thead > tr",_8b)).length==1){
-var tr=_8c[0];
-return d.query("> th",_8c[0]).map(function(th){
-var _8d={type:d.trim(d.attr(th,"cellType")||""),field:d.trim(d.attr(th,"field")||"")};
-if(_8d.type){
-_8d.type=d.getObject(_8d.type);
-}
-var _8e=d.query("> table",th)[0];
-if(_8e){
-_8d.name="";
-_8d.children=_8a(_8e);
-if(d.hasAttr(th,"itemAggregates")){
-_8d.itemAggregates=d.map(d.attr(th,"itemAggregates").split(","),function(v){
-return d.trim(v);
+
+dojo.declare("dojox.grid._TreeFocusManager", dojox.grid._FocusManager, {
+	setFocusCell: function(inCell, inRowIndex){
+		if(inCell && inCell.getNode(inRowIndex)){
+			this.inherited(arguments);
+		}
+	},
+	isLastFocusCell: function(){
+		if(this.cell && this.cell.index == this.grid.layout.cellCount-1){
+			var path = new dojox.grid.TreePath(this.grid.rowCount-1, this.grid);
+			path = path.lastChild(true);
+			return this.rowIndex == path._str;
+		}
+		return false;
+	},
+	next: function(){
+		// summary:
+		//	focus next grid cell
+		if(this.cell){
+			var row=this.rowIndex, col=this.cell.index+1, cc=this.grid.layout.cellCount-1;
+			var path = new dojox.grid.TreePath(this.rowIndex, this.grid);
+			if(col > cc){
+				var new_path = path.next();
+				if(!new_path){
+					col--;
+				}else{
+					col = 0;
+					path = new_path;
+				}
+			}
+			if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
+				var nextCell = this.grid.getCell(col);
+				if (!this.isLastFocusCell() && !nextCell.editable){
+					this._focusifyCellNode(false);
+					this.cell=nextCell;
+					this.rowIndex=path._str;
+					this.next();
+					return;
+				}
+			}
+			this.setFocusIndex(path._str, col);
+		}
+	},
+	previous: function(){
+		// summary:
+		//	focus previous grid cell
+		if(this.cell){
+			var row=(this.rowIndex || 0), col=(this.cell.index || 0) - 1;
+			var path = new dojox.grid.TreePath(row, this.grid);
+			if(col < 0){
+				var new_path = path.previous();
+				if(!new_path){
+					col = 0;
+				}else{
+					col = this.grid.layout.cellCount-1;
+					path = new_path;
+				}
+			}
+			if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
+				var prevCell = this.grid.getCell(col);
+				if (!this.isFirstFocusCell() && !prevCell.editable){
+					this._focusifyCellNode(false);
+					this.cell=prevCell;
+					this.rowIndex=path._str;
+					this.previous();
+					return;
+				}
+			}
+			this.setFocusIndex(path._str, col);
+		}
+	},
+	move: function(inRowDelta, inColDelta){
+		if(this.isNavHeader()){
+			this.inherited(arguments);
+			return;
+		}
+		if(!this.cell){ return; }
+		// Handle grid proper.
+		var sc = this.grid.scroller,
+			r = this.rowIndex,
+			rc = this.grid.rowCount-1,
+			path = new dojox.grid.TreePath(this.rowIndex, this.grid);
+		if(inRowDelta){
+			var row;
+			if(inRowDelta>0){
+				path = path.next();
+				row = path._arr[0];
+				if(row > sc.getLastPageRow(sc.page)){
+					//need to load additional data, let scroller do that
+					this.grid.setScrollTop(this.grid.scrollTop+sc.findScrollTop(row)-sc.findScrollTop(r));
+				}
+			}else if(inRowDelta<0){
+				path = path.previous();
+				row = path._arr[0];
+				if(row <= sc.getPageRow(sc.page)){
+					//need to load additional data, let scroller do that
+					this.grid.setScrollTop(this.grid.scrollTop-sc.findScrollTop(r)-sc.findScrollTop(row));
+				}
+			}
+		}
+		var cc = this.grid.layout.cellCount-1,
+		i = this.cell.index,
+		col = Math.min(cc, Math.max(0, i+inColDelta));
+		var cell = this.grid.getCell(col);
+		var colDir = inColDelta < 0 ? -1 : 1;
+		while(col>=0 && col < cc && cell && cell.hidden === true){
+			// skip hidden cells
+			col += colDir;
+			cell = this.grid.getCell(col);
+		}
+		if (!cell || cell.hidden === true){
+			// don't change col if would move to hidden
+			col = i;
+		}
+		if(inRowDelta){
+			this.grid.updateRow(r);
+		}
+		this.setFocusIndex(path._str, col);
+	}
 });
-}else{
-_8d.itemAggregates=[];
-}
-if(d.hasAttr(th,"aggregate")){
-_8d.aggregate=d.attr(th,"aggregate");
-}
-_8d.type=_8d.type||dojox.grid.cells.SubtableCell;
-}else{
-_8d.name=d.trim(d.attr(th,"name")||th.innerHTML);
-if(d.hasAttr(th,"width")){
-_8d.width=_89(th);
-}
-if(d.hasAttr(th,"relWidth")){
-_8d.relWidth=window.parseInt(d.attr(th,"relWidth"),10);
-}
-if(d.hasAttr(th,"hidden")){
-_8d.hidden=d.attr(th,"hidden")=="true";
-}
-_8d.field=_8d.field||_8d.name;
-dojox.grid.DataGrid.cell_markupFactory(_88,th,_8d);
-_8d.type=_8d.type||dojox.grid.cells.Cell;
-}
-if(_8d.type&&_8d.type.markupFactory){
-_8d.type.markupFactory(th,_8d);
-}
-return _8d;
+
+dojo.declare("dojox.grid.TreeGrid", dojox.grid.DataGrid, {
+	// summary:
+	//		A grid that supports nesting rows - it provides an expando function
+	//		similar to dijit.Tree.  It also provides mechanisms for aggregating
+	//		the values of subrows
+	//
+	// description:
+	//		TreeGrid currently only works on "simple" structures.  That is, 
+	//		single-view structures with a single row in them.
+	//
+	//		The TreeGrid works using the concept of "levels" - level 0 are the
+	//		top-level items.
+	
+	// defaultOpen: Boolean
+	//		Whether or not we default to open (all levels).  This defaults to
+	//		false for grids with a treeModel.
+	defaultOpen: true,
+
+	// sortChildItems: Boolean
+	// 		If true, child items will be returned sorted according to the sorting
+	// 		properties of the grid.
+	sortChildItems: false,
+
+	// openAtLevels: Array
+	//		Which levels we are open at (overrides defaultOpen for the values
+	//		that exist here).  Its values can be a boolean (true/false) or an
+	//		integer (for the # of children to be closed if there are more than
+	//		that)
+	openAtLevels: [],
+	
+	// treeModel: dijit.tree.ForestStoreModel
+	//		A dijit.Tree model that will be used instead of using aggregates.
+	//		Setting this value will make the TreeGrid behave like a columnar
+	//		tree.  When setting this value, defaultOpen will default to false,
+	//		and openAtLevels will be ignored.
+	treeModel: null,
+	
+	// expandoCell: Integer
+	//		When used in conjunction with a treeModel (see above), this is a 0-based
+	//		index of the cell in which to place the actual expando
+	expandoCell: 0,
+	
+	// private values
+	// aggregator: Object
+	//		The aggregator class - it will be populated automatically if we
+	//		are a collapsable grid
+	aggregator: null,
+
+
+	// Override this to get our "magic" layout
+	_layoutClass: dojox.grid._TreeLayout,
+
+	createSelection: function(){
+		this.selection = new dojox.grid.TreeSelection(this);
+	},
+
+	_childItemSorter: function(a, b, attribute, descending){
+		var av = this.store.getValue(a, attribute);
+		var bv = this.store.getValue(b, attribute);
+		if(av != bv){
+			return av < bv == descending ? 1 : -1;
+		}
+		return 0;
+	},
+
+	_onNew: function(item, parentInfo){
+		if(!parentInfo || !parentInfo.item){
+			this.inherited(arguments);
+		}else{
+			var idx = this.getItemIndex(parentInfo.item);
+			if(typeof idx == "string"){
+				this.updateRow(idx.split('/')[0]);
+			}else if(idx > -1){
+				this.updateRow(idx);
+			}
+		}
+	},
+
+	_onSet: function(item, attribute, oldValue, newValue){
+		this._checkUpdateStatus();
+		if(this.aggregator){
+			this.aggregator.clearSubtotalCache();
+		}
+		var idx = this.getItemIndex(item);
+		if(typeof idx == "string"){
+			this.updateRow(idx.split('/')[0]);
+		}else if(idx > -1){
+			this.updateRow(idx);
+		}
+	},
+
+	_onDelete: function(item){
+		this._cleanupExpandoCache(this._getItemIndex(item, true), this.store.getIdentity(item), item);
+		this.inherited(arguments);
+	},
+
+	_cleanupExpandoCache: function(index, identity, item){},
+
+	_addItem: function(item, index, noUpdate, dontUpdateRoot){
+		// add our root items to the root of the model's children
+		// list since we don't query the model
+		if(!dontUpdateRoot && this.model && dojo.indexOf(this.model.root.children, item) == -1){
+			this.model.root.children[index] = item;
+		}
+		this.inherited(arguments);
+	},
+
+	getItem: function(/*integer|Array|String*/ idx){
+		// summary:
+		//		overridden so that you can pass in a '/' delimited string of indexes to get the
+		//		item based off its path...that is, passing in "1/3/2" will get the
+		//		3rd (0-based) child from the 4th child of the 2nd top-level item.
+		var isArray = dojo.isArray(idx);
+		if(dojo.isString(idx) && idx.indexOf('/')){
+			idx = idx.split('/');
+			isArray = true;
+		}
+		if(isArray && idx.length == 1){
+			idx = idx[0];
+			isArray = false;
+		}
+		if(!isArray){
+			return dojox.grid.DataGrid.prototype.getItem.call(this, idx);
+		}
+		var s = this.store;
+		var itm = dojox.grid.DataGrid.prototype.getItem.call(this, idx[0]);
+		var cf;
+		if(this.aggregator){
+			cf = this.aggregator.childFields||[];
+		}else if(this.treeModel){
+			cf = this.treeModel.childrenAttrs||[];
+		}
+		if(cf){
+			for(var i = 0; i < idx.length - 1 && itm; i++){
+				if(cf[i]){
+					itm = (s.getValues(itm, cf[i])||[])[idx[i + 1]];
+				}else{
+					itm = null;
+				}
+			}
+		}
+		return itm || null;
+	},
+
+	_getItemIndex: function(item, isDeleted){
+		if(!isDeleted && !this.store.isItem(item)){
+			return -1;
+		}
+		var idx = this.inherited(arguments);
+		if(idx == -1){
+			var idty = this.store.getIdentity(item);
+			return this._by_idty_paths[idty] || -1;
+		}
+		return idx;
+	},
+	
+	postMixInProperties: function(){
+		if(this.treeModel && !("defaultOpen" in this.params)){
+			// Default open to false for tree models, true for other tree
+			// grids.
+			this.defaultOpen = false;
+		}
+		var def = this.defaultOpen;
+		this.openAtLevels = dojo.map(this.openAtLevels, function(l){
+			if(typeof l == "string"){
+				switch(l.toLowerCase()){
+					case "true":
+						return true;
+						break;
+					case "false":
+						return false;
+						break;
+					default:
+						var r = parseInt(l, 10);
+						if(isNaN(r)){
+							return def;
+						}
+						return r;
+						break;
+				}
+			}
+			return l;
+		});
+		this._by_idty_paths = {};
+		this.inherited(arguments);
+	},
+	
+    postCreate: function(){
+        this.inherited(arguments);
+		if(this.treeModel){
+			this._setModel(this.treeModel);
+		}
+    },
+
+	setModel: function(treeModel){
+		this._setModel(treeModel);
+		this._refresh(true);
+	},
+	
+	_setModel: function(treeModel){
+		if(treeModel && (!dijit.tree.ForestStoreModel || !(treeModel instanceof dijit.tree.ForestStoreModel))){
+			throw new Error("dojox.grid.TreeGrid: treeModel must be an instance of dijit.tree.ForestStoreModel");			
+		}
+		this.treeModel = treeModel;
+		dojo.toggleClass(this.domNode, "dojoxGridTreeModel", this.treeModel ? true : false);
+		this._setQuery(treeModel ? treeModel.query : null);
+		this._setStore(treeModel ? treeModel.store : null);
+	},
+
+	createScroller: function(){
+		this.inherited(arguments);
+		this.scroller._origDefaultRowHeight = this.scroller.defaultRowHeight;
+	},
+	
+	createManagers: function(){
+		// summary:
+		//		create grid managers for various tasks including rows, focus, selection, editing
+
+		// row manager
+		this.rows = new dojox.grid._RowManager(this);
+		// focus manager
+		this.focus = new dojox.grid._TreeFocusManager(this);
+		// edit manager
+		this.edit = new dojox.grid._EditManager(this);
+	},
+
+	_setStore: function(store){
+		this.inherited(arguments);
+		if(this.treeModel&&!this.treeModel.root.children){
+			this.treeModel.root.children = [];
+		}
+		if(this.aggregator){
+			this.aggregator.store = store;
+		}
+	},
+	
+	getDefaultOpenState: function(cellDef, item){
+		// summary:
+		//		Returns the default open state for the given definition and item
+		//		It reads from the openAtLevels and defaultOpen values of the
+		//		grid to calculate if the given item should default to open or
+		//		not.
+		var cf;
+		var store = this.store;
+		if(this.treeModel){ return this.defaultOpen; }
+		if(!cellDef || !store || !store.isItem(item) ||
+				!(cf = this.aggregator.childFields[cellDef.level])){
+			return this.defaultOpen;
+		}
+		if(this.openAtLevels.length > cellDef.level){
+			var dVal = this.openAtLevels[cellDef.level];
+			if(typeof dVal == "boolean"){
+				return dVal;
+			}else if(typeof dVal == "number"){
+				return (store.getValues(item, cf).length <= dVal);
+			}
+		}
+		return this.defaultOpen;
+	},
+	onStyleRow: function(row){
+		if(!this.layout._isCollapsable){
+			this.inherited(arguments);
+			return;
+		}
+		var base = dojo.attr(row.node, 'dojoxTreeGridBaseClasses');
+		if(base){
+			row.customClasses = base;
+		}
+		var i = row;
+		var tagName = i.node.tagName.toLowerCase();
+		i.customClasses += (i.odd?" dojoxGridRowOdd":"") +
+						   (i.selected&&tagName=='tr'?" dojoxGridRowSelected":"") +
+						   (i.over&&tagName=='tr'?" dojoxGridRowOver":"");
+		this.focus.styleRow(i);
+		this.edit.styleRow(i);
+	},
+	styleRowNode: function(inRowIndex, inRowNode){
+		if(inRowNode){
+			if(inRowNode.tagName.toLowerCase() == 'div' && this.aggregator){
+				dojo.query("tr[dojoxTreeGridPath]", inRowNode).forEach(function(rowNode){
+					this.rows.styleRowNode(dojo.attr(rowNode, 'dojoxTreeGridPath'), rowNode);
+				},this);
+			}
+			this.rows.styleRowNode(inRowIndex, inRowNode);
+		}
+	},
+	onCanSelect: function(inRowIndex){
+		var nodes = dojo.query("tr[dojoxTreeGridPath='" + inRowIndex + "']", this.domNode);
+		if(nodes.length){
+			if(dojo.hasClass(nodes[0], 'dojoxGridSummaryRow')){
+				return false;
+			}
+		}
+		return this.inherited(arguments);
+	},
+	onKeyDown: function(e){
+		if(e.altKey || e.metaKey){
+			return;
+		}
+		var dk = dojo.keys;
+		switch(e.keyCode){
+			case dk.UP_ARROW:
+				if(!this.edit.isEditing() && this.focus.rowIndex != "0"){
+					dojo.stopEvent(e);
+					this.focus.move(-1, 0);
+				}
+				break;
+			case dk.DOWN_ARROW:
+				var currPath = new dojox.grid.TreePath(this.focus.rowIndex, this);
+				var lastPath = new dojox.grid.TreePath(this.rowCount-1, this);
+				lastPath = lastPath.lastChild(true);
+				if(!this.edit.isEditing() && currPath.toString() != lastPath.toString()){
+					dojo.stopEvent(e);
+					this.focus.move(1, 0);
+				}
+				break;
+			default:
+				this.inherited(arguments);
+				break;
+		}
+	},
+	canEdit: function(inCell, inRowIndex){
+		var node = inCell.getNode(inRowIndex);
+		return node && this._canEdit;
+	},
+	doApplyCellEdit: function(inValue, inRowIndex, inAttrName){
+		var item = this.getItem(inRowIndex);
+		var oldValue = this.store.getValue(item, inAttrName);
+		if(typeof oldValue == 'number'){
+			inValue = isNaN(inValue) ? inValue : parseFloat(inValue);
+		}else if(typeof oldValue == 'boolean'){
+			inValue = inValue == 'true' ? true : inValue == 'false' ? false : inValue;
+		}else if(oldValue instanceof Date){
+			var asDate = new Date(inValue);
+			inValue = isNaN(asDate.getTime()) ? inValue : asDate;
+		}
+		this.store.setValue(item, inAttrName, inValue);
+		this.onApplyCellEdit(inValue, inRowIndex, inAttrName);
+	}
 });
-}
-return [];
-};
-var _8f;
-if(!_85.structure){
-var row=_8a(_86);
-if(row.length){
-_85.structure=[{__span:Infinity,cells:[row]}];
-}
-}
-return dojox.grid.DataGrid.markupFactory(_85,_86,_87,_88);
+dojox.grid.TreeGrid.markupFactory = function(props, node, ctor, cellFunc){
+	var d = dojo;
+	var widthFromAttr = function(n){
+		var w = d.attr(n, "width")||"auto";
+		if((w != "auto")&&(w.slice(-2) != "em")&&(w.slice(-1) != "%")){
+			w = parseInt(w, 10)+"px";
+		}
+		return w;
+	};
+	
+	var cellsFromMarkup = function(table){
+		var rows;
+		// Don't support colgroup on our grid - single view, single row only
+		if(table.nodeName.toLowerCase() == "table" &&
+					d.query("> colgroup", table).length === 0 &&
+					(rows = d.query("> thead > tr", table)).length == 1){
+			var tr = rows[0];
+			return d.query("> th", rows[0]).map(function(th){
+				// Grab type and field (the only ones that are shared
+				var cell = {
+					type: d.trim(d.attr(th, "cellType")||""),
+					field: d.trim(d.attr(th, "field")||"")
+				};
+				if(cell.type){ 
+					cell.type = d.getObject(cell.type);
+				}
+				
+				var subTable = d.query("> table", th)[0];
+				if(subTable){
+					// If we have a subtable, we are an aggregate and a summary cell
+					cell.name = "";
+					cell.children = cellsFromMarkup(subTable);
+					if(d.hasAttr(th, "itemAggregates")){
+						cell.itemAggregates = d.map(d.attr(th, "itemAggregates").split(","), function(v){ 
+							return d.trim(v); 
+						});
+					}else{
+						cell.itemAggregates = [];
+					}
+					if(d.hasAttr(th, "aggregate")){
+						cell.aggregate = d.attr(th, "aggregate");
+					}
+					cell.type = cell.type || dojox.grid.cells.SubtableCell;
+				}else{
+					// Grab our other stuff we need (mostly what's in the normal 
+					// Grid)
+					cell.name = d.trim(d.attr(th, "name")||th.innerHTML);
+					if(d.hasAttr(th, "width")){
+						cell.width = widthFromAttr(th);
+					}
+					if(d.hasAttr(th, "relWidth")){
+						cell.relWidth = window.parseInt(d.attr(th, "relWidth"), 10);
+					}
+					if(d.hasAttr(th, "hidden")){
+						cell.hidden = d.attr(th, "hidden") == "true";
+					}
+					cell.field = cell.field||cell.name;
+					dojox.grid.DataGrid.cell_markupFactory(cellFunc, th, cell);
+					cell.type = cell.type || dojox.grid.cells.Cell;
+				}
+				if(cell.type && cell.type.markupFactory){
+					cell.type.markupFactory(th, cell);
+				}			
+				return cell;
+			});
+		}
+		return [];
+	};
+	
+	var rows;
+	if(	!props.structure ){
+		var row = cellsFromMarkup(node);
+		if(row.length){
+			// Set our structure here - so that we don't try and set it in the
+			// markup factory
+			props.structure = [{__span: Infinity, cells:[row]}];
+		}
+	}
+	return dojox.grid.DataGrid.markupFactory(props, node, ctor, cellFunc);
 };
-}
diff --git a/dojox/grid/TreeSelection.js b/dojox/grid/TreeSelection.js
index 829a887..aa1a4fa 100644
--- a/dojox/grid/TreeSelection.js
+++ b/dojox/grid/TreeSelection.js
@@ -1,214 +1,208 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.TreeSelection"]){
-dojo._hasResource["dojox.grid.TreeSelection"]=true;
 dojo.provide("dojox.grid.TreeSelection");
+
 dojo.require("dojox.grid.DataSelection");
-dojo.declare("dojox.grid.TreeSelection",dojox.grid.DataSelection,{setMode:function(_1){
-this.selected={};
-this.sorted_sel=[];
-this.sorted_ltos={};
-this.sorted_stol={};
-dojox.grid.DataSelection.prototype.setMode.call(this,_1);
-},addToSelection:function(_2){
-if(this.mode=="none"){
-return;
-}
-var _3=null;
-if(typeof _2=="number"||typeof _2=="string"){
-_3=_2;
-}else{
-_3=this.grid.getItemIndex(_2);
-}
-if(this.selected[_3]){
-this.selectedIndex=_3;
-}else{
-if(this.onCanSelect(_3)!==false){
-this.selectedIndex=_3;
-var _4=dojo.query("tr[dojoxTreeGridPath='"+_3+"']",this.grid.domNode);
-if(_4.length){
-dojo.attr(_4[0],"aria-selected","true");
-}
-this._beginUpdate();
-this.selected[_3]=true;
-this._insertSortedSelection(_3);
-this.onSelected(_3);
-this._endUpdate();
-}
-}
-},deselect:function(_5){
-if(this.mode=="none"){
-return;
-}
-var _6=null;
-if(typeof _5=="number"||typeof _5=="string"){
-_6=_5;
-}else{
-_6=this.grid.getItemIndex(_5);
-}
-if(this.selectedIndex==_6){
-this.selectedIndex=-1;
-}
-if(this.selected[_6]){
-if(this.onCanDeselect(_6)===false){
-return;
-}
-var _7=dojo.query("tr[dojoxTreeGridPath='"+_6+"']",this.grid.domNode);
-if(_7.length){
-dojo.attr(_7[0],"aria-selected","false");
-}
-this._beginUpdate();
-delete this.selected[_6];
-this._removeSortedSelection(_6);
-this.onDeselected(_6);
-this._endUpdate();
-}
-},getSelected:function(){
-var _8=[];
-for(var i in this.selected){
-if(this.selected[i]){
-_8.push(this.grid.getItem(i));
-}
-}
-return _8;
-},getSelectedCount:function(){
-var c=0;
-for(var i in this.selected){
-if(this.selected[i]){
-c++;
-}
-}
-return c;
-},_bsearch:function(v){
-var o=this.sorted_sel;
-var h=o.length-1,l=0,m;
-while(l<=h){
-var _9=this._comparePaths(o[m=(l+h)>>1],v);
-if(_9<0){
-l=m+1;
-continue;
-}
-if(_9>0){
-h=m-1;
-continue;
-}
-return m;
-}
-return _9<0?m-_9:m;
-},_comparePaths:function(a,b){
-for(var i=0,l=(a.length<b.length?a.length:b.length);i<l;i++){
-if(a[i]<b[i]){
-return -1;
-}
-if(a[i]>b[i]){
-return 1;
-}
-}
-if(a.length<b.length){
-return -1;
-}
-if(a.length>b.length){
-return 1;
-}
-return 0;
-},_insertSortedSelection:function(_a){
-_a=String(_a);
-var s=this.sorted_sel;
-var sl=this.sorted_ltos;
-var ss=this.sorted_stol;
-var _b=_a.split("/");
-_b=dojo.map(_b,function(_c){
-return parseInt(_c,10);
+
+dojo.declare("dojox.grid.TreeSelection", dojox.grid.DataSelection, {
+	setMode: function(mode){
+		this.selected = {};
+		this.sorted_sel = [];
+		this.sorted_ltos = {};
+		this.sorted_stol = {};
+		dojox.grid.DataSelection.prototype.setMode.call(this, mode);
+	},
+	addToSelection: function(inItemOrIndex){
+		if(this.mode == 'none'){ return; }
+		var idx = null;
+		if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
+			idx = inItemOrIndex;
+		}else{
+			idx = this.grid.getItemIndex(inItemOrIndex);
+		}
+		if(this.selected[idx]){
+			this.selectedIndex = idx;
+		}else{
+			if(this.onCanSelect(idx) !== false){
+				this.selectedIndex = idx;
+				var rowNodes = dojo.query("tr[dojoxTreeGridPath='" + idx + "']", this.grid.domNode);
+				if(rowNodes.length){
+					dojo.attr(rowNodes[0],"aria-selected","true");
+				}
+				this._beginUpdate();
+				this.selected[idx] = true;
+				this._insertSortedSelection(idx);
+				//this.grid.onSelected(idx);
+				this.onSelected(idx);
+				//this.onSetSelected(idx, true);
+				this._endUpdate();
+			}
+		}
+	},
+	deselect: function(inItemOrIndex){
+		if(this.mode == 'none'){ return; }
+		var idx = null;
+		if(typeof inItemOrIndex == "number" || typeof inItemOrIndex == "string"){
+			idx = inItemOrIndex;
+		}else{
+			idx = this.grid.getItemIndex(inItemOrIndex);
+		}
+		if(this.selectedIndex == idx){
+			this.selectedIndex = -1;
+		}
+		if(this.selected[idx]){
+			if(this.onCanDeselect(idx) === false){
+				return;
+			}
+			var rowNodes = dojo.query("tr[dojoxTreeGridPath='" + idx + "']", this.grid.domNode);
+			if(rowNodes.length){
+				dojo.attr(rowNodes[0],"aria-selected","false");
+			}
+			this._beginUpdate();
+			delete this.selected[idx];
+			this._removeSortedSelection(idx);
+			//this.grid.onDeselected(idx);
+			this.onDeselected(idx);
+			//this.onSetSelected(idx, false);
+			this._endUpdate();
+		}
+	},
+	getSelected: function(){
+		var result = [];
+		for(var i in this.selected){
+			if(this.selected[i]){
+				result.push(this.grid.getItem(i));
+			}
+		}
+		return result;
+	},
+	getSelectedCount: function(){
+		var c = 0;
+		for(var i in this.selected){
+			if(this.selected[i]){
+				c++;
+			}
+		}
+		return c;
+	},
+	_bsearch: function(v){
+		var o = this.sorted_sel;
+		var h = o.length - 1, l = 0, m;
+		while(l<=h){
+			var cmp = this._comparePaths(o[m = (l + h) >> 1], v);
+			if(cmp < 0){ l = m + 1; continue; }
+			if(cmp > 0){ h = m - 1; continue; }
+			return m;
+		}
+		return cmp < 0 ? m - cmp : m;
+	},
+	_comparePaths: function(a, b){
+		for(var i=0, l=(a.length < b.length ? a.length : b.length); i<l; i++){
+			if(a[i]<b[i]){ return -1; }
+			if(a[i]>b[i]){ return 1; }
+		}
+		if(a.length<b.length){ return -1; }
+		if(a.length>b.length){ return 1; }
+		return 0;
+	},
+	_insertSortedSelection: function(index){
+		index = String(index);
+		var s = this.sorted_sel;
+		var sl = this.sorted_ltos;
+		var ss = this.sorted_stol;
+
+		var lpath = index.split('/');
+		lpath = dojo.map(lpath, function(item){ return parseInt(item, 10); });
+		sl[lpath] = index;
+		ss[index] = lpath;
+
+		if(s.length === 0){
+			s.push(lpath);
+			return;
+		}
+		if(s.length==1){
+			var cmp = this._comparePaths(s[0], lpath);
+			if(cmp==1){ s.unshift(lpath); }
+			else{ s.push(lpath); }
+			return;
+		}
+
+		var idx = this._bsearch(lpath);
+		this.sorted_sel.splice(idx, 0, lpath);
+	},
+	_removeSortedSelection: function(index){
+		index = String(index);
+		var s = this.sorted_sel;
+		var sl = this.sorted_ltos;
+		var ss = this.sorted_stol;
+
+		if(s.length === 0){
+			return;
+		}
+
+		var lpath = ss[index];
+		if(!lpath){ return; }
+
+		var idx = this._bsearch(lpath);
+		if(idx > -1){
+			delete sl[lpath];
+			delete ss[index];
+			s.splice(idx, 1);
+		}
+	},
+	getFirstSelected: function(){
+		if(!this.sorted_sel.length||this.mode == 'none'){ return -1; }
+		var fpath = this.sorted_sel[0];
+		if(!fpath){
+			return -1;
+		}
+		fpath = this.sorted_ltos[fpath];
+		if(!fpath){
+			return -1;
+		}
+		return fpath;
+	},
+	getNextSelected: function(inPrev){
+		if(!this.sorted_sel.length||this.mode == 'none'){ return -1; }
+		inPrev = String(inPrev);
+		var prevPath = this.sorted_stol[inPrev];
+		if(!prevPath){ return -1; }
+
+		var idx = this._bsearch(prevPath);
+		var lpath = this.sorted_sel[idx+1];
+		if(!lpath){
+			return -1;
+		}
+		return this.sorted_ltos[lpath];
+	},
+	_range: function(inFrom, inTo, func){
+		if(!dojo.isString(inFrom) && inFrom < 0){
+			inFrom = inTo;
+		}
+		var cells = this.grid.layout.cells,
+			store = this.grid.store,
+			grid = this.grid;
+		inFrom = new dojox.grid.TreePath(String(inFrom), grid);
+		inTo = new dojox.grid.TreePath(String(inTo), grid);
+
+		if(inFrom.compare(inTo) > 0){
+			var tmp = inFrom;
+			inFrom = inTo;
+			inTo = tmp;
+		}
+
+		var inFromStr = inFrom._str, inToStr = inTo._str;
+
+		// select/deselect the first
+		func(inFromStr);
+
+		var p = inFrom;
+		while((p = p.next())){
+			if(p._str == inToStr){
+				break;
+			}
+			func(p._str);
+		}
+
+		// select/deselect the last
+		func(inToStr);
+	}
 });
-sl[_b]=_a;
-ss[_a]=_b;
-if(s.length===0){
-s.push(_b);
-return;
-}
-if(s.length==1){
-var _d=this._comparePaths(s[0],_b);
-if(_d==1){
-s.unshift(_b);
-}else{
-s.push(_b);
-}
-return;
-}
-var _e=this._bsearch(_b);
-this.sorted_sel.splice(_e,0,_b);
-},_removeSortedSelection:function(_f){
-_f=String(_f);
-var s=this.sorted_sel;
-var sl=this.sorted_ltos;
-var ss=this.sorted_stol;
-if(s.length===0){
-return;
-}
-var _10=ss[_f];
-if(!_10){
-return;
-}
-var idx=this._bsearch(_10);
-if(idx>-1){
-delete sl[_10];
-delete ss[_f];
-s.splice(idx,1);
-}
-},getFirstSelected:function(){
-if(!this.sorted_sel.length||this.mode=="none"){
-return -1;
-}
-var _11=this.sorted_sel[0];
-if(!_11){
-return -1;
-}
-_11=this.sorted_ltos[_11];
-if(!_11){
-return -1;
-}
-return _11;
-},getNextSelected:function(_12){
-if(!this.sorted_sel.length||this.mode=="none"){
-return -1;
-}
-_12=String(_12);
-var _13=this.sorted_stol[_12];
-if(!_13){
-return -1;
-}
-var idx=this._bsearch(_13);
-var _14=this.sorted_sel[idx+1];
-if(!_14){
-return -1;
-}
-return this.sorted_ltos[_14];
-},_range:function(_15,_16,_17){
-if(!dojo.isString(_15)&&_15<0){
-_15=_16;
-}
-var _18=this.grid.layout.cells,_19=this.grid.store,_1a=this.grid;
-_15=new dojox.grid.TreePath(String(_15),_1a);
-_16=new dojox.grid.TreePath(String(_16),_1a);
-if(_15.compare(_16)>0){
-var tmp=_15;
-_15=_16;
-_16=tmp;
-}
-var _1b=_15._str,_1c=_16._str;
-_17(_1b);
-var p=_15;
-while((p=p.next())){
-if(p._str==_1c){
-break;
-}
-_17(p._str);
-}
-_17(_1c);
-}});
-}
diff --git a/dojox/grid/_Builder.js b/dojox/grid/_Builder.js
index 61f78be..499dc17 100644
--- a/dojox/grid/_Builder.js
+++ b/dojox/grid/_Builder.js
@@ -1,531 +1,741 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._Builder"]){
-dojo._hasResource["dojox.grid._Builder"]=true;
 dojo.provide("dojox.grid._Builder");
+
 dojo.require("dojox.grid.util");
 dojo.require("dojo.dnd.Moveable");
+
 (function(){
-var dg=dojox.grid;
-var _1=function(td){
-return td.cellIndex>=0?td.cellIndex:dojo.indexOf(td.parentNode.cells,td);
-};
-var _2=function(tr){
-return tr.rowIndex>=0?tr.rowIndex:dojo.indexOf(tr.parentNode.childNodes,tr);
-};
-var _3=function(_4,_5){
-return _4&&((_4.rows||0)[_5]||_4.childNodes[_5]);
-};
-var _6=function(_7){
-for(var n=_7;n&&n.tagName!="TABLE";n=n.parentNode){
-}
-return n;
-};
-var _8=function(_9,_a){
-for(var n=_9;n&&_a(n);n=n.parentNode){
-}
-return n;
-};
-var _b=function(_c){
-var _d=_c.toUpperCase();
-return function(_e){
-return _e.tagName!=_d;
-};
-};
-var _f=dojox.grid.util.rowIndexTag;
-var _10=dojox.grid.util.gridViewTag;
-dg._Builder=dojo.extend(function(_11){
-if(_11){
-this.view=_11;
-this.grid=_11.grid;
-}
-},{view:null,_table:"<table class=\"dojoxGridRowTable\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" role=\"presentation\"",getTableArray:function(){
-var _12=[this._table];
-if(this.view.viewWidth){
-_12.push([" style=\"width:",this.view.viewWidth,";\""].join(""));
-}
-_12.push(">");
-return _12;
-},generateCellMarkup:function(_13,_14,_15,_16){
-var _17=[],_18;
-if(_16){
-var _19=_13.index!=_13.grid.getSortIndex()?"":_13.grid.sortInfo>0?"aria-sort=\"ascending\"":"aria-sort=\"descending\"";
-if(!_13.id){
-_13.id=this.grid.id+"Hdr"+_13.index;
-}
-_18=["<th tabIndex=\"-1\" aria-readonly=\"true\" role=\"columnheader\"",_19,"id=\"",_13.id,"\""];
-}else{
-var _1a=this.grid.editable&&!_13.editable?"aria-readonly=\"true\"":"";
-_18=["<td tabIndex=\"-1\" role=\"gridcell\"",_1a];
-}
-if(_13.colSpan){
-_18.push(" colspan=\"",_13.colSpan,"\"");
-}
-if(_13.rowSpan){
-_18.push(" rowspan=\"",_13.rowSpan,"\"");
-}
-_18.push(" class=\"dojoxGridCell ");
-if(_13.classes){
-_18.push(_13.classes," ");
-}
-if(_15){
-_18.push(_15," ");
-}
-_17.push(_18.join(""));
-_17.push("");
-_18=["\" idx=\"",_13.index,"\" style=\""];
-if(_14&&_14[_14.length-1]!=";"){
-_14+=";";
-}
-_18.push(_13.styles,_14||"",_13.hidden?"display:none;":"");
-if(_13.unitWidth){
-_18.push("width:",_13.unitWidth,";");
-}
-_17.push(_18.join(""));
-_17.push("");
-_18=["\""];
-if(_13.attrs){
-_18.push(" ",_13.attrs);
-}
-_18.push(">");
-_17.push(_18.join(""));
-_17.push("");
-_17.push(_16?"</th>":"</td>");
-return _17;
-},isCellNode:function(_1b){
-return Boolean(_1b&&_1b!=dojo.doc&&dojo.attr(_1b,"idx"));
-},getCellNodeIndex:function(_1c){
-return _1c?Number(dojo.attr(_1c,"idx")):-1;
-},getCellNode:function(_1d,_1e){
-for(var i=0,row;(row=_3(_1d.firstChild,i));i++){
-for(var j=0,_1f;(_1f=row.cells[j]);j++){
-if(this.getCellNodeIndex(_1f)==_1e){
-return _1f;
-}
-}
-}
-return null;
-},findCellTarget:function(_20,_21){
-var n=_20;
-while(n&&(!this.isCellNode(n)||(n.offsetParent&&_10 in n.offsetParent.parentNode&&n.offsetParent.parentNode[_10]!=this.view.id))&&(n!=_21)){
-n=n.parentNode;
-}
-return n!=_21?n:null;
-},baseDecorateEvent:function(e){
-e.dispatch="do"+e.type;
-e.grid=this.grid;
-e.sourceView=this.view;
-e.cellNode=this.findCellTarget(e.target,e.rowNode);
-e.cellIndex=this.getCellNodeIndex(e.cellNode);
-e.cell=(e.cellIndex>=0?this.grid.getCell(e.cellIndex):null);
-},findTarget:function(_22,_23){
-var n=_22;
-while(n&&(n!=this.domNode)&&(!(_23 in n)||(_10 in n&&n[_10]!=this.view.id))){
-n=n.parentNode;
-}
-return (n!=this.domNode)?n:null;
-},findRowTarget:function(_24){
-return this.findTarget(_24,_f);
-},isIntraNodeEvent:function(e){
-try{
-return (e.cellNode&&e.relatedTarget&&dojo.isDescendant(e.relatedTarget,e.cellNode));
-}
-catch(x){
-return false;
-}
-},isIntraRowEvent:function(e){
-try{
-var row=e.relatedTarget&&this.findRowTarget(e.relatedTarget);
-return !row&&(e.rowIndex==-1)||row&&(e.rowIndex==row.gridRowIndex);
-}
-catch(x){
-return false;
-}
-},dispatchEvent:function(e){
-if(e.dispatch in this){
-return this[e.dispatch](e);
-}
-return false;
-},domouseover:function(e){
-if(e.cellNode&&(e.cellNode!=this.lastOverCellNode)){
-this.lastOverCellNode=e.cellNode;
-this.grid.onMouseOver(e);
-}
-this.grid.onMouseOverRow(e);
-},domouseout:function(e){
-if(e.cellNode&&(e.cellNode==this.lastOverCellNode)&&!this.isIntraNodeEvent(e,this.lastOverCellNode)){
-this.lastOverCellNode=null;
-this.grid.onMouseOut(e);
-if(!this.isIntraRowEvent(e)){
-this.grid.onMouseOutRow(e);
-}
-}
-},domousedown:function(e){
-if(e.cellNode){
-this.grid.onMouseDown(e);
-}
-this.grid.onMouseDownRow(e);
-}});
-dg._ContentBuilder=dojo.extend(function(_25){
-dg._Builder.call(this,_25);
-},dg._Builder.prototype,{update:function(){
-this.prepareHtml();
-},prepareHtml:function(){
-var _26=this.grid.get,_27=this.view.structure.cells;
-for(var j=0,row;(row=_27[j]);j++){
-for(var i=0,_28;(_28=row[i]);i++){
-_28.get=_28.get||(_28.value==undefined)&&_26;
-_28.markup=this.generateCellMarkup(_28,_28.cellStyles,_28.cellClasses,false);
-if(!this.grid.editable&&_28.editable){
-this.grid.editable=true;
-}
-}
-}
-},generateHtml:function(_29,_2a){
-var _2b=this.getTableArray(),v=this.view,_2c=v.structure.cells,_2d=this.grid.getItem(_2a);
-dojox.grid.util.fire(this.view,"onBeforeRow",[_2a,_2c]);
-for(var j=0,row;(row=_2c[j]);j++){
-if(row.hidden||row.header){
-continue;
-}
-_2b.push(!row.invisible?"<tr>":"<tr class=\"dojoxGridInvisible\">");
-for(var i=0,_2e,m,cc,cs;(_2e=row[i]);i++){
-m=_2e.markup;
-cc=_2e.customClasses=[];
-cs=_2e.customStyles=[];
-m[5]=_2e.format(_2a,_2d);
-m[1]=cc.join(" ");
-m[3]=cs.join(";");
-_2b.push.apply(_2b,m);
-}
-_2b.push("</tr>");
-}
-_2b.push("</table>");
-return _2b.join("");
-},decorateEvent:function(e){
-e.rowNode=this.findRowTarget(e.target);
-if(!e.rowNode){
-return false;
-}
-e.rowIndex=e.rowNode[_f];
-this.baseDecorateEvent(e);
-e.cell=this.grid.getCell(e.cellIndex);
-return true;
-}});
-dg._HeaderBuilder=dojo.extend(function(_2f){
-this.moveable=null;
-dg._Builder.call(this,_2f);
-},dg._Builder.prototype,{_skipBogusClicks:false,overResizeWidth:4,minColWidth:1,update:function(){
-if(this.tableMap){
-this.tableMap.mapRows(this.view.structure.cells);
-}else{
-this.tableMap=new dg._TableMap(this.view.structure.cells);
-}
-},generateHtml:function(_30,_31){
-var _32=this.getTableArray(),_33=this.view.structure.cells;
-dojox.grid.util.fire(this.view,"onBeforeRow",[-1,_33]);
-for(var j=0,row;(row=_33[j]);j++){
-if(row.hidden){
-continue;
-}
-_32.push(!row.invisible?"<tr>":"<tr class=\"dojoxGridInvisible\">");
-for(var i=0,_34,_35;(_34=row[i]);i++){
-_34.customClasses=[];
-_34.customStyles=[];
-if(this.view.simpleStructure){
-if(_34.draggable){
-if(_34.headerClasses){
-if(_34.headerClasses.indexOf("dojoDndItem")==-1){
-_34.headerClasses+=" dojoDndItem";
-}
-}else{
-_34.headerClasses="dojoDndItem";
-}
-}
-if(_34.attrs){
-if(_34.attrs.indexOf("dndType='gridColumn_")==-1){
-_34.attrs+=" dndType='gridColumn_"+this.grid.id+"'";
-}
-}else{
-_34.attrs="dndType='gridColumn_"+this.grid.id+"'";
-}
-}
-_35=this.generateCellMarkup(_34,_34.headerStyles,_34.headerClasses,true);
-_35[5]=(_31!=undefined?_31:_30(_34));
-_35[3]=_34.customStyles.join(";");
-_35[1]=_34.customClasses.join(" ");
-_32.push(_35.join(""));
-}
-_32.push("</tr>");
-}
-_32.push("</table>");
-return _32.join("");
-},getCellX:function(e){
-var n,x=e.layerX;
-if(dojo.isMoz){
-n=_8(e.target,_b("th"));
-x-=(n&&n.offsetLeft)||0;
-var t=e.sourceView.getScrollbarWidth();
-if(!dojo._isBodyLtr()&&e.sourceView.headerNode.scrollLeft<t){
-x-=t;
-}
-}
-n=_8(e.target,function(){
-if(!n||n==e.cellNode){
-return false;
-}
-x+=(n.offsetLeft<0?0:n.offsetLeft);
-return true;
-});
-return x;
-},decorateEvent:function(e){
-this.baseDecorateEvent(e);
-e.rowIndex=-1;
-e.cellX=this.getCellX(e);
-return true;
-},prepareResize:function(e,mod){
-do{
-var i=_1(e.cellNode);
-e.cellNode=(i?e.cellNode.parentNode.cells[i+mod]:null);
-e.cellIndex=(e.cellNode?this.getCellNodeIndex(e.cellNode):-1);
-}while(e.cellNode&&e.cellNode.style.display=="none");
-return Boolean(e.cellNode);
-},canResize:function(e){
-if(!e.cellNode||e.cellNode.colSpan>1){
-return false;
-}
-var _36=this.grid.getCell(e.cellIndex);
-return !_36.noresize&&_36.canResize();
-},overLeftResizeArea:function(e){
-if(dojo.hasClass(dojo.body(),"dojoDndMove")){
-return false;
-}
-if(dojo.isIE){
-var tN=e.target;
-if(dojo.hasClass(tN,"dojoxGridArrowButtonNode")||dojo.hasClass(tN,"dojoxGridArrowButtonChar")){
-return false;
-}
-}
-if(dojo._isBodyLtr()){
-return (e.cellIndex>0)&&(e.cellX<this.overResizeWidth)&&this.prepareResize(e,-1);
-}
-var t=e.cellNode&&(e.cellX<this.overResizeWidth);
-return t;
-},overRightResizeArea:function(e){
-if(dojo.hasClass(dojo.body(),"dojoDndMove")){
-return false;
-}
-if(dojo.isIE){
-var tN=e.target;
-if(dojo.hasClass(tN,"dojoxGridArrowButtonNode")||dojo.hasClass(tN,"dojoxGridArrowButtonChar")){
-return false;
-}
-}
-if(dojo._isBodyLtr()){
-return e.cellNode&&(e.cellX>=e.cellNode.offsetWidth-this.overResizeWidth);
-}
-return (e.cellIndex>0)&&(e.cellX>=e.cellNode.offsetWidth-this.overResizeWidth)&&this.prepareResize(e,-1);
-},domousemove:function(e){
-if(!this.moveable){
-var c=(this.overRightResizeArea(e)?"dojoxGridColResize":(this.overLeftResizeArea(e)?"dojoxGridColResize":""));
-if(c&&!this.canResize(e)){
-c="dojoxGridColNoResize";
-}
-dojo.toggleClass(e.sourceView.headerNode,"dojoxGridColNoResize",(c=="dojoxGridColNoResize"));
-dojo.toggleClass(e.sourceView.headerNode,"dojoxGridColResize",(c=="dojoxGridColResize"));
-if(dojo.isIE){
-var t=e.sourceView.headerNode.scrollLeft;
-e.sourceView.headerNode.scrollLeft=t;
-}
-if(c){
-dojo.stopEvent(e);
-}
-}
-},domousedown:function(e){
-if(!this.moveable){
-if((this.overRightResizeArea(e)||this.overLeftResizeArea(e))&&this.canResize(e)){
-this.beginColumnResize(e);
-}else{
-this.grid.onMouseDown(e);
-this.grid.onMouseOverRow(e);
-}
-}
-},doclick:function(e){
-if(this._skipBogusClicks){
-dojo.stopEvent(e);
-return true;
-}
-return false;
-},colResizeSetup:function(e,_37){
-var _38=dojo.contentBox(e.sourceView.headerNode);
-if(_37){
-this.lineDiv=document.createElement("div");
-var vw=(dojo.position||dojo._abs)(e.sourceView.headerNode,true);
-var _39=dojo.contentBox(e.sourceView.domNode);
-dojo.style(this.lineDiv,{top:vw.y+"px",left:e.clientX+"px",height:(_39.h+_38.h)+"px"});
-dojo.addClass(this.lineDiv,"dojoxGridResizeColLine");
-this.lineDiv._origLeft=e.clientX;
-dojo.body().appendChild(this.lineDiv);
-}
-var _3a=[],_3b=this.tableMap.findOverlappingNodes(e.cellNode);
-for(var i=0,_3c;(_3c=_3b[i]);i++){
-_3a.push({node:_3c,index:this.getCellNodeIndex(_3c),width:_3c.offsetWidth});
-}
-var _3d=e.sourceView;
-var adj=dojo._isBodyLtr()?1:-1;
-var _3e=e.grid.views.views;
-var _3f=[];
-for(var j=_3d.idx+adj,_40;(_40=_3e[j]);j=j+adj){
-_3f.push({node:_40.headerNode,left:window.parseInt(_40.headerNode.style.left)});
-}
-var _41=_3d.headerContentNode.firstChild;
-var _42={scrollLeft:e.sourceView.headerNode.scrollLeft,view:_3d,node:e.cellNode,index:e.cellIndex,w:dojo.contentBox(e.cellNode).w,vw:_38.w,table:_41,tw:dojo.contentBox(_41).w,spanners:_3a,followers:_3f};
-return _42;
-},beginColumnResize:function(e){
-this.moverDiv=document.createElement("div");
-dojo.style(this.moverDiv,{position:"absolute",left:0});
-dojo.body().appendChild(this.moverDiv);
-dojo.addClass(this.grid.domNode,"dojoxGridColumnResizing");
-var m=(this.moveable=new dojo.dnd.Moveable(this.moverDiv));
-var _43=this.colResizeSetup(e,true);
-m.onMove=dojo.hitch(this,"doResizeColumn",_43);
-dojo.connect(m,"onMoveStop",dojo.hitch(this,function(){
-this.endResizeColumn(_43);
-if(_43.node.releaseCapture){
-_43.node.releaseCapture();
-}
-this.moveable.destroy();
-delete this.moveable;
-this.moveable=null;
-dojo.removeClass(this.grid.domNode,"dojoxGridColumnResizing");
-}));
-if(e.cellNode.setCapture){
-e.cellNode.setCapture();
-}
-m.onMouseDown(e);
-},doResizeColumn:function(_44,_45,_46){
-var _47=_46.l;
-var _48={deltaX:_47,w:_44.w+_47,vw:_44.vw+_47,tw:_44.tw+_47};
-this.dragRecord={inDrag:_44,mover:_45,leftTop:_46};
-if(_48.w>=this.minColWidth){
-if(!_45){
-this.doResizeNow(_44,_48);
-}else{
-dojo.style(this.lineDiv,"left",(this.lineDiv._origLeft+_48.deltaX)+"px");
-}
-}
-},endResizeColumn:function(_49){
-if(this.dragRecord){
-var _4a=this.dragRecord.leftTop;
-var _4b=dojo._isBodyLtr()?_4a.l:-_4a.l;
-_4b+=Math.max(_49.w+_4b,this.minColWidth)-(_49.w+_4b);
-if(dojo.isWebKit&&_49.spanners.length){
-_4b+=dojo._getPadBorderExtents(_49.spanners[0].node).w;
-}
-var _4c={deltaX:_4b,w:_49.w+_4b,vw:_49.vw+_4b,tw:_49.tw+_4b};
-this.doResizeNow(_49,_4c);
-}
-dojo.destroy(this.lineDiv);
-dojo.destroy(this.moverDiv);
-dojo.destroy(this.moverDiv);
-delete this.moverDiv;
-this._skipBogusClicks=true;
-_49.view.update();
-this._skipBogusClicks=false;
-this.grid.onResizeColumn(_49.index);
-},doResizeNow:function(_4d,_4e){
-_4d.view.convertColPctToFixed();
-if(_4d.view.flexCells&&!_4d.view.testFlexCells()){
-var t=_6(_4d.node);
-if(t){
-(t.style.width="");
-}
-}
-var i,s,sw,f,fl;
-for(i=0;(s=_4d.spanners[i]);i++){
-sw=s.width+_4e.deltaX;
-s.node.style.width=sw+"px";
-_4d.view.setColWidth(s.index,sw);
-}
-for(i=0;(f=_4d.followers[i]);i++){
-fl=f.left+_4e.deltaX;
-f.node.style.left=fl+"px";
-}
-_4d.node.style.width=_4e.w+"px";
-_4d.view.setColWidth(_4d.index,_4e.w);
-_4d.view.headerNode.style.width=_4e.vw+"px";
-_4d.view.setColumnsWidth(_4e.tw);
-if(!dojo._isBodyLtr()){
-_4d.view.headerNode.scrollLeft=_4d.scrollLeft+_4e.deltaX;
-}
-}});
-dg._TableMap=dojo.extend(function(_4f){
-this.mapRows(_4f);
-},{map:null,mapRows:function(_50){
-var _51=_50.length;
-if(!_51){
-return;
-}
-this.map=[];
-var row;
-for(var k=0;(row=_50[k]);k++){
-this.map[k]=[];
-}
-for(var j=0;(row=_50[j]);j++){
-for(var i=0,x=0,_52,_53,_54;(_52=row[i]);i++){
-while(this.map[j][x]){
-x++;
-}
-this.map[j][x]={c:i,r:j};
-_54=_52.rowSpan||1;
-_53=_52.colSpan||1;
-for(var y=0;y<_54;y++){
-for(var s=0;s<_53;s++){
-this.map[j+y][x+s]=this.map[j][x];
-}
-}
-x+=_53;
-}
-}
-},dumpMap:function(){
-for(var j=0,row,h="";(row=this.map[j]);j++,h=""){
-for(var i=0,_55;(_55=row[i]);i++){
-h+=_55.r+","+_55.c+"   ";
-}
-}
-},getMapCoords:function(_56,_57){
-for(var j=0,row;(row=this.map[j]);j++){
-for(var i=0,_58;(_58=row[i]);i++){
-if(_58.c==_57&&_58.r==_56){
-return {j:j,i:i};
-}
-}
-}
-return {j:-1,i:-1};
-},getNode:function(_59,_5a,_5b){
-var row=_59&&_59.rows[_5a];
-return row&&row.cells[_5b];
-},_findOverlappingNodes:function(_5c,_5d,_5e){
-var _5f=[];
-var m=this.getMapCoords(_5d,_5e);
-for(var j=0,row;(row=this.map[j]);j++){
-if(j==m.j){
-continue;
-}
-var rw=row[m.i];
-var n=(rw?this.getNode(_5c,rw.r,rw.c):null);
-if(n){
-_5f.push(n);
-}
-}
-return _5f;
-},findOverlappingNodes:function(_60){
-return this._findOverlappingNodes(_6(_60),_2(_60.parentNode),_1(_60));
-}});
+	var dg = dojox.grid;
+
+	var getTdIndex = function(td){
+		return td.cellIndex >=0 ? td.cellIndex : dojo.indexOf(td.parentNode.cells, td);
+	};
+	
+	var getTrIndex = function(tr){
+		return tr.rowIndex >=0 ? tr.rowIndex : dojo.indexOf(tr.parentNode.childNodes, tr);
+	};
+	
+	var getTr = function(rowOwner, index){
+		return rowOwner && ((rowOwner.rows||0)[index] || rowOwner.childNodes[index]);
+	};
+
+	var findTable = function(node){
+		for(var n=node; n && n.tagName!='TABLE'; n=n.parentNode){}
+		return n;
+	};
+	
+	var ascendDom = function(inNode, inWhile){
+		for(var n=inNode; n && inWhile(n); n=n.parentNode){}
+		return n;
+	};
+	
+	var makeNotTagName = function(inTagName){
+		var name = inTagName.toUpperCase();
+		return function(node){ return node.tagName != name; };
+	};
+
+	var rowIndexTag = dojox.grid.util.rowIndexTag;
+	var gridViewTag = dojox.grid.util.gridViewTag;
+
+	// base class for generating markup for the views
+	dg._Builder = dojo.extend(function(view){
+		if(view){
+			this.view = view;
+			this.grid = view.grid;
+		}
+	},{
+		view: null,
+		// boilerplate HTML
+		_table: '<table class="dojoxGridRowTable" border="0" cellspacing="0" cellpadding="0" role="presentation"',
+
+		// Returns the table variable as an array - and with the view width, if specified
+		getTableArray: function(){
+			var html = [this._table];
+			if(this.view.viewWidth){
+				html.push([' style="width:', this.view.viewWidth, ';"'].join(''));
+			}
+			html.push('>');
+			return html;
+		},
+		
+		// generate starting tags for a cell
+		generateCellMarkup: function(inCell, inMoreStyles, inMoreClasses, isHeader){
+			var result = [], html;
+			if(isHeader){
+				var sortInfo = inCell.index != inCell.grid.getSortIndex() ? "" : inCell.grid.sortInfo > 0 ? 'aria-sort="ascending"' : 'aria-sort="descending"';
+				if (!inCell.id){
+					inCell.id = this.grid.id + "Hdr" + inCell.index;
+				}
+				// column headers are not editable, mark as aria-readonly=true
+				html = ['<th tabIndex="-1" aria-readonly="true" role="columnheader"', sortInfo, 'id="', inCell.id, '"'];
+			}else{
+				// cells inherit grid aria-readonly property; default value for aria-readonly is false(grid is editable)
+				// if grid is editable (had any editable cells), mark non editable cells as aria-readonly=true
+				// if no editable cells, grid's aria-readonly value will have been set to true and cells will inherit
+				var editInfo = this.grid.editable && !inCell.editable ? 'aria-readonly="true"' : "";
+				html = ['<td tabIndex="-1" role="gridcell"', editInfo];
+			}
+			if(inCell.colSpan){
+				html.push(' colspan="', inCell.colSpan, '"');
+			}
+			if(inCell.rowSpan){
+				html.push(' rowspan="', inCell.rowSpan, '"');
+			}
+			html.push(' class="dojoxGridCell ');
+			if(inCell.classes){
+				html.push(inCell.classes, ' ');
+			}
+			if(inMoreClasses){
+				html.push(inMoreClasses, ' ');
+			}
+			// result[0] => td opener, style
+			result.push(html.join(''));
+			// SLOT: result[1] => td classes 
+			result.push('');
+			html = ['" idx="', inCell.index, '" style="'];
+			if(inMoreStyles && inMoreStyles[inMoreStyles.length-1] != ';'){
+				inMoreStyles += ';';
+			}
+			html.push(inCell.styles, inMoreStyles||'', inCell.hidden?'display:none;':'');
+			if(inCell.unitWidth){
+				html.push('width:', inCell.unitWidth, ';');
+			}
+			// result[2] => markup
+			result.push(html.join(''));
+			// SLOT: result[3] => td style 
+			result.push('');
+			html = [ '"' ];
+			if(inCell.attrs){
+				html.push(" ", inCell.attrs);
+			}
+			html.push('>');
+			// result[4] => td postfix
+			result.push(html.join(''));
+			// SLOT: result[5] => content
+			result.push('');
+			// result[6] => td closes
+			result.push(isHeader?'</th>':'</td>');
+			return result; // Array
+		},
+
+		// cell finding
+		isCellNode: function(inNode){
+			return Boolean(inNode && inNode!=dojo.doc && dojo.attr(inNode, "idx"));
+		},
+		
+		getCellNodeIndex: function(inCellNode){
+			return inCellNode ? Number(dojo.attr(inCellNode, "idx")) : -1;
+		},
+		
+		getCellNode: function(inRowNode, inCellIndex){
+			for(var i=0, row; (row=getTr(inRowNode.firstChild, i)); i++){
+				for(var j=0, cell; (cell=row.cells[j]); j++){
+					if(this.getCellNodeIndex(cell) == inCellIndex){
+						return cell;
+					}
+				}
+			}
+			return null;
+		},
+		
+		findCellTarget: function(inSourceNode, inTopNode){
+			var n = inSourceNode;
+			while(n && (!this.isCellNode(n) || (n.offsetParent && gridViewTag in n.offsetParent.parentNode && n.offsetParent.parentNode[gridViewTag] != this.view.id)) && (n!=inTopNode)){
+				n = n.parentNode;
+			}
+			return n!=inTopNode ? n : null;
+		},
+		
+		// event decoration
+		baseDecorateEvent: function(e){
+			e.dispatch = 'do' + e.type;
+			e.grid = this.grid;
+			e.sourceView = this.view;
+			e.cellNode = this.findCellTarget(e.target, e.rowNode);
+			e.cellIndex = this.getCellNodeIndex(e.cellNode);
+			e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
+		},
+		
+		// event dispatch
+		findTarget: function(inSource, inTag){
+			var n = inSource;
+			while(n && (n!=this.domNode) && (!(inTag in n) || (gridViewTag in n && n[gridViewTag] != this.view.id))){
+				n = n.parentNode;
+			}
+			return (n != this.domNode) ? n : null; 
+		},
+
+		findRowTarget: function(inSource){
+			return this.findTarget(inSource, rowIndexTag);
+		},
+
+		isIntraNodeEvent: function(e){
+			try{
+				return (e.cellNode && e.relatedTarget && dojo.isDescendant(e.relatedTarget, e.cellNode));
+			}catch(x){
+				// e.relatedTarget has permission problem in FF if it's an input: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
+				return false;
+			}
+		},
+
+		isIntraRowEvent: function(e){
+			try{
+				var row = e.relatedTarget && this.findRowTarget(e.relatedTarget);
+				return !row && (e.rowIndex==-1) || row && (e.rowIndex==row.gridRowIndex);			
+			}catch(x){
+				// e.relatedTarget on INPUT has permission problem in FF: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
+				return false;
+			}
+		},
+
+		dispatchEvent: function(e){
+			if(e.dispatch in this){
+				return this[e.dispatch](e);
+			}
+			return false;
+		},
+
+		// dispatched event handlers
+		domouseover: function(e){
+			if(e.cellNode && (e.cellNode!=this.lastOverCellNode)){
+				this.lastOverCellNode = e.cellNode;
+				this.grid.onMouseOver(e);
+			}
+			this.grid.onMouseOverRow(e);
+		},
+
+		domouseout: function(e){
+			if(e.cellNode && (e.cellNode==this.lastOverCellNode) && !this.isIntraNodeEvent(e, this.lastOverCellNode)){
+				this.lastOverCellNode = null;
+				this.grid.onMouseOut(e);
+				if(!this.isIntraRowEvent(e)){
+					this.grid.onMouseOutRow(e);
+				}
+			}
+		},
+		
+		domousedown: function(e){
+			if (e.cellNode)
+				this.grid.onMouseDown(e);
+			this.grid.onMouseDownRow(e);
+		}
+	});
+
+	// Produces html for grid data content. Owned by grid and used internally 
+	// for rendering data. Override to implement custom rendering.
+	dg._ContentBuilder = dojo.extend(function(view){
+		dg._Builder.call(this, view);
+	},dg._Builder.prototype,{
+		update: function(){
+			this.prepareHtml();
+		},
+
+		// cache html for rendering data rows
+		prepareHtml: function(){
+			var defaultGet=this.grid.get, cells=this.view.structure.cells;
+			for(var j=0, row; (row=cells[j]); j++){
+				for(var i=0, cell; (cell=row[i]); i++){
+					cell.get = cell.get || (cell.value == undefined) && defaultGet;
+					cell.markup = this.generateCellMarkup(cell, cell.cellStyles, cell.cellClasses, false);
+					if (!this.grid.editable && cell.editable){
+						this.grid.editable = true;
+					}
+				}
+			}
+		},
+
+		// time critical: generate html using cache and data source
+		generateHtml: function(inDataIndex, inRowIndex){
+			var
+				html = this.getTableArray(),
+				v = this.view,
+				cells = v.structure.cells,
+				item = this.grid.getItem(inRowIndex);
+
+			dojox.grid.util.fire(this.view, "onBeforeRow", [inRowIndex, cells]);
+			for(var j=0, row; (row=cells[j]); j++){
+				if(row.hidden || row.header){
+					continue;
+				}
+				html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGridInvisible">');
+				for(var i=0, cell, m, cc, cs; (cell=row[i]); i++){
+					m = cell.markup; cc = cell.customClasses = []; cs = cell.customStyles = [];
+					// content (format can fill in cc and cs as side-effects)
+					m[5] = cell.format(inRowIndex, item);
+					// classes
+					m[1] = cc.join(' ');
+					// styles
+					m[3] = cs.join(';');
+					// in-place concat
+					html.push.apply(html, m);
+				}
+				html.push('</tr>');
+			}
+			html.push('</table>');
+			return html.join(''); // String
+		},
+
+		decorateEvent: function(e){
+			e.rowNode = this.findRowTarget(e.target);
+			if(!e.rowNode){return false;}
+			e.rowIndex = e.rowNode[rowIndexTag];
+			this.baseDecorateEvent(e);
+			e.cell = this.grid.getCell(e.cellIndex);
+			return true; // Boolean
+		}
+	});
+
+	// Produces html for grid header content. Owned by grid and used internally 
+	// for rendering data. Override to implement custom rendering.
+	dg._HeaderBuilder = dojo.extend(function(view){
+		this.moveable = null;
+		dg._Builder.call(this, view);
+	},dg._Builder.prototype,{
+		_skipBogusClicks: false,
+		overResizeWidth: 4,
+		minColWidth: 1,
+		
+		update: function(){
+			if(this.tableMap){
+				this.tableMap.mapRows(this.view.structure.cells);
+			}else{
+				this.tableMap = new dg._TableMap(this.view.structure.cells);
+			}
+		},
+
+		generateHtml: function(inGetValue, inValue){
+			var html = this.getTableArray(), cells = this.view.structure.cells;
+			
+			dojox.grid.util.fire(this.view, "onBeforeRow", [-1, cells]);
+			for(var j=0, row; (row=cells[j]); j++){
+				if(row.hidden){
+					continue;
+				}
+				html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGridInvisible">');
+				for(var i=0, cell, markup; (cell=row[i]); i++){
+					cell.customClasses = [];
+					cell.customStyles = [];
+					if(this.view.simpleStructure){
+						if(cell.draggable){
+							if(cell.headerClasses){
+								if(cell.headerClasses.indexOf('dojoDndItem') == -1){
+									cell.headerClasses += ' dojoDndItem';
+								}
+							}else{
+								cell.headerClasses = 'dojoDndItem';
+							}
+						}
+						if(cell.attrs){
+							if(cell.attrs.indexOf("dndType='gridColumn_") == -1){
+								cell.attrs += " dndType='gridColumn_" + this.grid.id + "'";
+							}
+						}else{
+							cell.attrs = "dndType='gridColumn_" + this.grid.id + "'";
+						}
+					}
+					markup = this.generateCellMarkup(cell, cell.headerStyles, cell.headerClasses, true);
+					// content
+					markup[5] = (inValue != undefined ? inValue : inGetValue(cell));
+					// styles
+					markup[3] = cell.customStyles.join(';');
+					// classes
+					markup[1] = cell.customClasses.join(' '); //(cell.customClasses ? ' ' + cell.customClasses : '');
+					html.push(markup.join(''));
+				}
+				html.push('</tr>');
+			}
+			html.push('</table>');
+			return html.join('');
+		},
+
+		// event helpers
+		getCellX: function(e){
+			var n, x = e.layerX;
+			if(dojo.isMoz){
+				n = ascendDom(e.target, makeNotTagName("th"));
+				x -= (n && n.offsetLeft) || 0;
+				var t = e.sourceView.getScrollbarWidth();
+				if(!dojo._isBodyLtr()/*&& e.sourceView.headerNode.scrollLeft < t*/){
+					//fix #11253
+					table = ascendDom(n,makeNotTagName("table"));
+					x -= (table && table.offsetLeft) || 0;
+				}
+				//x -= getProp(ascendDom(e.target, mkNotTagName("td")), "offsetLeft") || 0;
+			}
+			n = ascendDom(e.target, function(){
+				if(!n || n == e.cellNode){
+					return false;
+				}
+				// Mozilla 1.8 (FF 1.5) has a bug that makes offsetLeft = -parent border width
+				// when parent has border, overflow: hidden, and is positioned
+				// handle this problem here ... not a general solution!
+				x += (n.offsetLeft < 0 ? 0 : n.offsetLeft);
+				return true;
+			});
+			return x;
+		},
+
+		// event decoration
+		decorateEvent: function(e){
+			this.baseDecorateEvent(e);
+			e.rowIndex = -1;
+			e.cellX = this.getCellX(e);
+			return true;
+		},
+
+		// event handlers
+		// resizing
+		prepareResize: function(e, mod){
+			do{
+				var i = getTdIndex(e.cellNode);
+				e.cellNode = (i ? e.cellNode.parentNode.cells[i+mod] : null);
+				e.cellIndex = (e.cellNode ? this.getCellNodeIndex(e.cellNode) : -1);
+			}while(e.cellNode && e.cellNode.style.display == "none");
+			return Boolean(e.cellNode);
+		},
+
+		canResize: function(e){
+			if(!e.cellNode || e.cellNode.colSpan > 1){
+				return false;
+			}
+			var cell = this.grid.getCell(e.cellIndex); 
+			return !cell.noresize && cell.canResize();
+		},
+
+		overLeftResizeArea: function(e){
+			// We are never over a resize area if we are in the process of moving
+			if(dojo.hasClass(dojo.body(), "dojoDndMove")){
+				return false;
+			}
+			//Bugfix for crazy IE problem (#8807).  IE returns position information for the icon and text arrow divs
+			//as if they were still on the left instead of returning the position they were 'float: right' to.
+			//So, the resize check ends up checking the wrong adjacent cell.  This checks to see if the hover was over 
+			//the image or text nodes, then just ignored them/treat them not in scale range.
+			if(dojo.isIE){
+				var tN = e.target;
+				if(dojo.hasClass(tN, "dojoxGridArrowButtonNode") || 
+					dojo.hasClass(tN, "dojoxGridArrowButtonChar")){
+					return false;
+				}
+			}
+
+			if(dojo._isBodyLtr()){
+				return (e.cellIndex>0) && (e.cellX < this.overResizeWidth) && this.prepareResize(e, -1);
+			}
+			var t = e.cellNode && (e.cellX < this.overResizeWidth);
+			return t;
+		},
+
+		overRightResizeArea: function(e){
+			// We are never over a resize area if we are in the process of moving
+			if(dojo.hasClass(dojo.body(), "dojoDndMove")){
+				return false;
+			}
+			//Bugfix for crazy IE problem (#8807).  IE returns position information for the icon and text arrow divs
+			//as if they were still on the left instead of returning the position they were 'float: right' to.
+			//So, the resize check ends up checking the wrong adjacent cell.  This checks to see if the hover was over 
+			//the image or text nodes, then just ignored them/treat them not in scale range.
+			if(dojo.isIE){
+				var tN = e.target;
+				if(dojo.hasClass(tN, "dojoxGridArrowButtonNode") || 
+					dojo.hasClass(tN, "dojoxGridArrowButtonChar")){
+					return false;
+				}
+			}
+
+			if(dojo._isBodyLtr()){
+				return e.cellNode && (e.cellX >= e.cellNode.offsetWidth - this.overResizeWidth);
+			}
+			return (e.cellIndex>0) && (e.cellX >= e.cellNode.offsetWidth - this.overResizeWidth) && this.prepareResize(e, -1);
+		},
+
+		domousemove: function(e){
+			//console.log(e.cellIndex, e.cellX, e.cellNode.offsetWidth);
+			if(!this.moveable){
+				var c = (this.overRightResizeArea(e) ? 'dojoxGridColResize' : (this.overLeftResizeArea(e) ? 'dojoxGridColResize' : ''));
+				if(c && !this.canResize(e)){
+					c = 'dojoxGridColNoResize';
+				}
+				dojo.toggleClass(e.sourceView.headerNode, "dojoxGridColNoResize", (c == "dojoxGridColNoResize"));
+				dojo.toggleClass(e.sourceView.headerNode, "dojoxGridColResize", (c == "dojoxGridColResize"));
+				if(dojo.isIE){
+					var t = e.sourceView.headerNode.scrollLeft;
+					e.sourceView.headerNode.scrollLeft = t;
+				}
+				if(c){
+					dojo.stopEvent(e);
+				}
+			}
+		},
+
+		domousedown: function(e){
+			if(!this.moveable){
+				if((this.overRightResizeArea(e) || this.overLeftResizeArea(e)) && this.canResize(e)){
+					this.beginColumnResize(e);
+				}else{
+					this.grid.onMouseDown(e);
+					this.grid.onMouseOverRow(e);
+				}
+				//else{
+				//	this.beginMoveColumn(e);
+				//}
+			}
+		},
+
+		doclick: function(e) {
+			if(this._skipBogusClicks){
+				dojo.stopEvent(e);
+				return true;
+			}
+			return false;
+		},
+
+		// column resizing
+		colResizeSetup: function(/*Event Object*/e, /*boolean*/ isMouse ){
+			//Set up the drag object for column resizing
+			// Called with mouse event in case of drag and drop,
+			// Also called from keyboard shift-arrow event when focus is on a header
+			var headContentBox = dojo.contentBox(e.sourceView.headerNode);
+			
+			if(isMouse){  //IE draws line even with no mouse down so separate from keyboard 
+				this.lineDiv = document.createElement('div');
+
+				// NOTE: this is for backwards compatibility with Dojo 1.3
+				var vw = (dojo.position||dojo._abs)(e.sourceView.headerNode, true);
+				var bodyContentBox = dojo.contentBox(e.sourceView.domNode);
+				//fix #11340
+				var l = e.clientX;
+				if(!dojo._isBodyLtr() && dojo.isIE < 8){
+					l -= dojox.html.metrics.getScrollbar().w;
+				}				
+				dojo.style(this.lineDiv, {
+					top: vw.y + "px",
+					left: l + "px",
+					height: (bodyContentBox.h + headContentBox.h) + "px"
+				});
+				dojo.addClass(this.lineDiv, "dojoxGridResizeColLine");
+				this.lineDiv._origLeft = l;
+				dojo.body().appendChild(this.lineDiv);
+			}
+			var spanners = [], nodes = this.tableMap.findOverlappingNodes(e.cellNode);
+			for(var i=0, cell; (cell=nodes[i]); i++){
+				spanners.push({ node: cell, index: this.getCellNodeIndex(cell), width: cell.offsetWidth });
+				//console.log("spanner: " + this.getCellNodeIndex(cell));
+			}
+
+			var view = e.sourceView;
+			var adj = dojo._isBodyLtr() ? 1 : -1;
+			var views = e.grid.views.views;
+			var followers = [];
+			for(var j=view.idx+adj, cView; (cView=views[j]); j=j+adj){
+				followers.push({ node: cView.headerNode, left: window.parseInt(cView.headerNode.style.left) });
+			}
+			var table = view.headerContentNode.firstChild;
+			var drag = {
+				scrollLeft: e.sourceView.headerNode.scrollLeft,
+				view: view,
+				node: e.cellNode,
+				index: e.cellIndex,
+				w: dojo.contentBox(e.cellNode).w,
+				vw: headContentBox.w,
+				table: table,
+				tw: dojo.contentBox(table).w,
+				spanners: spanners,
+				followers: followers
+			};
+			return drag;
+		},
+		beginColumnResize: function(e){
+			this.moverDiv = document.createElement("div");
+			dojo.style(this.moverDiv,{position: "absolute", left:0}); // to make DnD work with dir=rtl
+			dojo.body().appendChild(this.moverDiv);
+			dojo.addClass(this.grid.domNode, "dojoxGridColumnResizing");
+			var m = (this.moveable = new dojo.dnd.Moveable(this.moverDiv));
+
+			var drag = this.colResizeSetup(e,true);
+
+			m.onMove = dojo.hitch(this, "doResizeColumn", drag);
+
+			dojo.connect(m, "onMoveStop", dojo.hitch(this, function(){
+				this.endResizeColumn(drag);
+				if(drag.node.releaseCapture){
+					drag.node.releaseCapture();
+				}
+				this.moveable.destroy();
+				delete this.moveable;
+				this.moveable = null;
+				dojo.removeClass(this.grid.domNode, "dojoxGridColumnResizing");
+			}));
+
+			if(e.cellNode.setCapture){
+				e.cellNode.setCapture();
+			}
+			m.onMouseDown(e);
+		},
+
+		doResizeColumn: function(inDrag, mover, leftTop){
+			var changeX = leftTop.l;
+			var data = {
+				deltaX: changeX,
+				w: inDrag.w + (dojo._isBodyLtr() ? changeX : -changeX),//fix #11341
+				vw: inDrag.vw + changeX,
+				tw: inDrag.tw + changeX
+			};
+			
+			this.dragRecord = {inDrag: inDrag, mover: mover, leftTop:leftTop};
+			
+			if(data.w >= this.minColWidth){
+				if (!mover) { // we are using keyboard do immediate resize
+					this.doResizeNow(inDrag, data);
+				}
+				else{
+					dojo.style(this.lineDiv, "left", (this.lineDiv._origLeft + data.deltaX) + "px");
+				}
+			}
+		},
+
+		endResizeColumn: function(inDrag){
+			if(this.dragRecord){
+				var leftTop = this.dragRecord.leftTop;
+				var changeX = dojo._isBodyLtr() ? leftTop.l : -leftTop.l;
+				// Make sure we are not under our minimum
+				// http://bugs.dojotoolkit.org/ticket/9390
+				changeX += Math.max(inDrag.w + changeX, this.minColWidth) - (inDrag.w + changeX);
+				if(dojo.isWebKit && inDrag.spanners.length){
+					// Webkit needs the pad border extents back in
+					changeX += dojo._getPadBorderExtents(inDrag.spanners[0].node).w;
+				}
+				var data = {
+					deltaX: changeX,
+					w: inDrag.w + changeX,
+					vw: inDrag.vw + changeX,
+					tw: inDrag.tw + changeX
+				};
+				// Only resize the columns when the drag has finished
+				this.doResizeNow(inDrag, data);
+			}
+			
+			dojo.destroy(this.lineDiv);
+ 			dojo.destroy(this.moverDiv);
+			dojo.destroy(this.moverDiv);
+			delete this.moverDiv;
+			this._skipBogusClicks = true;
+			inDrag.view.update();
+			this._skipBogusClicks = false;
+			this.grid.onResizeColumn(inDrag.index);
+		},
+		doResizeNow: function(inDrag, data){
+			inDrag.view.convertColPctToFixed();
+			if(inDrag.view.flexCells && !inDrag.view.testFlexCells()){
+				var t = findTable(inDrag.node);
+				if(t){
+					(t.style.width = '');
+				}
+			}
+			var i, s, sw, f, fl;
+			for(i=0; (s=inDrag.spanners[i]); i++){
+				sw = s.width + data.deltaX;
+				s.node.style.width = sw + 'px';
+				inDrag.view.setColWidth(s.index, sw);
+			}
+			if(dojo._isBodyLtr() || !dojo.isIE){//fix #11339			
+				for(i=0; (f=inDrag.followers[i]); i++){
+					fl = f.left + data.deltaX;
+					f.node.style.left = fl + 'px';
+				}
+			}
+			inDrag.node.style.width = data.w + 'px';
+			inDrag.view.setColWidth(inDrag.index, data.w);
+			inDrag.view.headerNode.style.width = data.vw + 'px';
+			inDrag.view.setColumnsWidth(data.tw);
+			if(!dojo._isBodyLtr()){
+				inDrag.view.headerNode.scrollLeft = inDrag.scrollLeft + data.deltaX;
+			}
+		}
+	});
+
+	// Maps an html table into a structure parsable for information about cell row and col spanning.
+	// Used by HeaderBuilder.
+	dg._TableMap = dojo.extend(function(rows){
+		this.mapRows(rows);
+	},{
+		map: null,
+
+		mapRows: function(inRows){
+			// summary: Map table topography
+
+			//console.log('mapRows');
+			// # of rows
+			var rowCount = inRows.length;
+			if(!rowCount){
+				return;
+			}
+			// map which columns and rows fill which cells
+			this.map = [];
+			var row;
+			for(var k=0; (row=inRows[k]); k++){
+				this.map[k] = [];
+			}
+			for(var j=0; (row=inRows[j]); j++){
+				for(var i=0, x=0, cell, colSpan, rowSpan; (cell=row[i]); i++){
+					while(this.map[j][x]){x++;}
+					this.map[j][x] = { c: i, r: j };
+					rowSpan = cell.rowSpan || 1;
+					colSpan = cell.colSpan || 1;
+					for(var y=0; y<rowSpan; y++){
+						for(var s=0; s<colSpan; s++){
+							this.map[j+y][x+s] = this.map[j][x];
+						}
+					}
+					x += colSpan;
+				}
+			}
+			//this.dumMap();
+		},
+
+		dumpMap: function(){
+			for(var j=0, row, h=''; (row=this.map[j]); j++,h=''){
+				for(var i=0, cell; (cell=row[i]); i++){
+					h += cell.r + ',' + cell.c + '   ';
+				}
+			}
+		},
+
+		getMapCoords: function(inRow, inCol){
+			// summary: Find node's map coords by it's structure coords
+			for(var j=0, row; (row=this.map[j]); j++){
+				for(var i=0, cell; (cell=row[i]); i++){
+					if(cell.c==inCol && cell.r == inRow){
+						return { j: j, i: i };
+					}
+					//else{console.log(inRow, inCol, ' : ', i, j, " : ", cell.r, cell.c); };
+				}
+			}
+			return { j: -1, i: -1 };
+		},
+		
+		getNode: function(inTable, inRow, inCol){
+			// summary: Find a node in inNode's table with the given structure coords
+			var row = inTable && inTable.rows[inRow];
+			return row && row.cells[inCol];
+		},
+		
+		_findOverlappingNodes: function(inTable, inRow, inCol){
+			var nodes = [];
+			var m = this.getMapCoords(inRow, inCol);
+			//console.log("node j: %d, i: %d", m.j, m.i);
+			for(var j=0, row; (row=this.map[j]); j++){
+				if(j == m.j){ continue; }
+				var rw = row[m.i];
+				//console.log("overlaps: r: %d, c: %d", rw.r, rw.c);
+				var n = (rw?this.getNode(inTable, rw.r, rw.c):null);
+				if(n){ nodes.push(n); }
+			}
+			//console.log(nodes);
+			return nodes;
+		},
+		
+		findOverlappingNodes: function(inNode){
+			return this._findOverlappingNodes(findTable(inNode), getTrIndex(inNode.parentNode), getTdIndex(inNode));
+		}
+	});
 })();
-}
diff --git a/dojox/grid/_CheckBoxSelector.js b/dojox/grid/_CheckBoxSelector.js
index d37e6ae..fad9313 100644
--- a/dojox/grid/_CheckBoxSelector.js
+++ b/dojox/grid/_CheckBoxSelector.js
@@ -1,12 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._CheckBoxSelector"]){
-dojo._hasResource["dojox.grid._CheckBoxSelector"]=true;
 dojo.provide("dojox.grid._CheckBoxSelector");
+
 dojo.require("dojox.grid._Selector");
-}
diff --git a/dojox/grid/_EditManager.js b/dojox/grid/_EditManager.js
index 356b2fc..850d0e8 100644
--- a/dojox/grid/_EditManager.js
+++ b/dojox/grid/_EditManager.js
@@ -1,131 +1,238 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._EditManager"]){
-dojo._hasResource["dojox.grid._EditManager"]=true;
 dojo.provide("dojox.grid._EditManager");
+
 dojo.require("dojox.grid.util");
-dojo.declare("dojox.grid._EditManager",null,{constructor:function(_1){
-this.grid=_1;
-this.connections=[];
-if(dojo.isIE){
-this.connections.push(dojo.connect(document.body,"onfocus",dojo.hitch(this,"_boomerangFocus")));
-}
-},info:{},destroy:function(){
-dojo.forEach(this.connections,dojo.disconnect);
-},cellFocus:function(_2,_3){
-if(this.grid.singleClickEdit||this.isEditRow(_3)){
-this.setEditCell(_2,_3);
-}else{
-this.apply();
-}
-if(this.isEditing()||(_2&&_2.editable&&_2.alwaysEditing)){
-this._focusEditor(_2,_3);
-}
-},rowClick:function(e){
-if(this.isEditing()&&!this.isEditRow(e.rowIndex)){
-this.apply();
-}
-},styleRow:function(_4){
-if(_4.index==this.info.rowIndex){
-_4.customClasses+=" dojoxGridRowEditing";
-}
-},dispatchEvent:function(e){
-var c=e.cell,ed=(c&&c["editable"])?c:0;
-return ed&&ed.dispatchEvent(e.dispatch,e);
-},isEditing:function(){
-return this.info.rowIndex!==undefined;
-},isEditCell:function(_5,_6){
-return (this.info.rowIndex===_5)&&(this.info.cell.index==_6);
-},isEditRow:function(_7){
-return this.info.rowIndex===_7;
-},setEditCell:function(_8,_9){
-if(!this.isEditCell(_9,_8.index)&&this.grid.canEdit&&this.grid.canEdit(_8,_9)){
-this.start(_8,_9,this.isEditRow(_9)||_8.editable);
-}
-},_focusEditor:function(_a,_b){
-dojox.grid.util.fire(_a,"focus",[_b]);
-},focusEditor:function(){
-if(this.isEditing()){
-this._focusEditor(this.info.cell,this.info.rowIndex);
-}
-},_boomerangWindow:500,_shouldCatchBoomerang:function(){
-return this._catchBoomerang>new Date().getTime();
-},_boomerangFocus:function(){
-if(this._shouldCatchBoomerang()){
-this.grid.focus.focusGrid();
-this.focusEditor();
-this._catchBoomerang=0;
-}
-},_doCatchBoomerang:function(){
-if(dojo.isIE){
-this._catchBoomerang=new Date().getTime()+this._boomerangWindow;
-}
-},start:function(_c,_d,_e){
-this.grid.beginUpdate();
-this.editorApply();
-if(this.isEditing()&&!this.isEditRow(_d)){
-this.applyRowEdit();
-this.grid.updateRow(_d);
-}
-if(_e){
-this.info={cell:_c,rowIndex:_d};
-this.grid.doStartEdit(_c,_d);
-this.grid.updateRow(_d);
-}else{
-this.info={};
-}
-this.grid.endUpdate();
-this.grid.focus.focusGrid();
-this._focusEditor(_c,_d);
-this._doCatchBoomerang();
-},_editorDo:function(_f){
-var c=this.info.cell;
-if(c&&c.editable){
-c[_f](this.info.rowIndex);
-}
-},editorApply:function(){
-this._editorDo("apply");
-},editorCancel:function(){
-this._editorDo("cancel");
-},applyCellEdit:function(_10,_11,_12){
-if(this.grid.canEdit(_11,_12)){
-this.grid.doApplyCellEdit(_10,_12,_11.field);
-}
-},applyRowEdit:function(){
-this.grid.doApplyEdit(this.info.rowIndex,this.info.cell.field);
-},apply:function(){
-if(this.isEditing()){
-this.grid.beginUpdate();
-this.editorApply();
-this.applyRowEdit();
-this.info={};
-this.grid.endUpdate();
-this.grid.focus.focusGrid();
-this._doCatchBoomerang();
-}
-},cancel:function(){
-if(this.isEditing()){
-this.grid.beginUpdate();
-this.editorCancel();
-this.info={};
-this.grid.endUpdate();
-this.grid.focus.focusGrid();
-this._doCatchBoomerang();
-}
-},save:function(_13,_14){
-var c=this.info.cell;
-if(this.isEditRow(_13)&&(!_14||c.view==_14)&&c.editable){
-c.save(c,this.info.rowIndex);
-}
-},restore:function(_15,_16){
-var c=this.info.cell;
-if(this.isEditRow(_16)&&c.view==_15&&c.editable){
-c.restore(c,this.info.rowIndex);
-}
-}});
-}
+
+dojo.declare("dojox.grid._EditManager", null, {
+	// summary:
+	//		Controls grid cell editing process. Owned by grid and used internally for editing.
+	constructor: function(inGrid){
+		// inGrid: dojox.Grid
+		//		The dojox.Grid this editor should be attached to
+		this.grid = inGrid;
+		this.connections = [];
+		if(dojo.isIE){
+			this.connections.push(dojo.connect(document.body, "onfocus", dojo.hitch(this, "_boomerangFocus")));
+		}
+	},
+	
+	info: {},
+
+	destroy: function(){
+		dojo.forEach(this.connections,dojo.disconnect);
+	},
+
+	cellFocus: function(inCell, inRowIndex){
+		// summary:
+		//		Invoke editing when cell is focused
+		// inCell: cell object
+		//		Grid cell object
+		// inRowIndex: Integer
+		//		Grid row index
+		if(this.grid.singleClickEdit || this.isEditRow(inRowIndex)){
+			// if same row or quick editing, edit
+			this.setEditCell(inCell, inRowIndex);
+		}else{
+			// otherwise, apply any pending row edits
+			this.apply();
+		}
+		// if dynamic or static editing...
+		if(this.isEditing() || (inCell && inCell.editable && inCell.alwaysEditing)){
+			// let the editor focus itself as needed
+			this._focusEditor(inCell, inRowIndex);
+		}
+	},
+
+	rowClick: function(e){
+		if(this.isEditing() && !this.isEditRow(e.rowIndex)){
+			this.apply();
+		}
+	},
+
+	styleRow: function(inRow){
+		if(inRow.index == this.info.rowIndex){
+			inRow.customClasses += ' dojoxGridRowEditing';
+		}
+	},
+
+	dispatchEvent: function(e){
+		var c = e.cell, ed = (c && c["editable"]) ? c : 0;
+		return ed && ed.dispatchEvent(e.dispatch, e);
+	},
+
+	// Editing
+	isEditing: function(){
+		// summary:
+		//		Indicates editing state of the grid.
+		// returns: Boolean
+		//	 	True if grid is actively editing
+		return this.info.rowIndex !== undefined;
+	},
+
+	isEditCell: function(inRowIndex, inCellIndex){
+		// summary:
+		//		Indicates if the given cell is being edited.
+		// inRowIndex: Integer
+		//		Grid row index
+		// inCellIndex: Integer
+		//		Grid cell index
+		// returns: Boolean
+		//	 	True if given cell is being edited
+		return (this.info.rowIndex === inRowIndex) && (this.info.cell.index == inCellIndex);
+	},
+
+	isEditRow: function(inRowIndex){
+		// summary:
+		//		Indicates if the given row is being edited.
+		// inRowIndex: Integer
+		//		Grid row index
+		// returns: Boolean
+		//	 	True if given row is being edited
+		return this.info.rowIndex === inRowIndex;
+	},
+
+	setEditCell: function(inCell, inRowIndex){
+		// summary:
+		//		Set the given cell to be edited
+		// inRowIndex: Integer
+		//		Grid row index
+		// inCell: Object
+		//		Grid cell object
+		if(!this.isEditCell(inRowIndex, inCell.index) && this.grid.canEdit && this.grid.canEdit(inCell, inRowIndex)){
+			this.start(inCell, inRowIndex, this.isEditRow(inRowIndex) || inCell.editable);
+		}
+	},
+
+	_focusEditor: function(inCell, inRowIndex){
+		dojox.grid.util.fire(inCell, "focus", [inRowIndex]);
+	},
+
+	focusEditor: function(){
+		if(this.isEditing()){
+			this._focusEditor(this.info.cell, this.info.rowIndex);
+		}
+	},
+
+	// implement fix for focus boomerang effect on IE
+	_boomerangWindow: 500,
+	_shouldCatchBoomerang: function(){
+		return this._catchBoomerang > new Date().getTime();
+	},
+	_boomerangFocus: function(){
+		//console.log("_boomerangFocus");
+		if(this._shouldCatchBoomerang()){
+			// make sure we don't utterly lose focus
+			this.grid.focus.focusGrid();
+			// let the editor focus itself as needed
+			this.focusEditor();
+			// only catch once
+			this._catchBoomerang = 0;
+		}
+	},
+	_doCatchBoomerang: function(){
+		// give ourselves a few ms to boomerang IE focus effects
+		if(dojo.isIE){this._catchBoomerang = new Date().getTime() + this._boomerangWindow;}
+	},
+	// end boomerang fix API
+
+	start: function(inCell, inRowIndex, inEditing){
+		this.grid.beginUpdate();
+		this.editorApply();
+		if(this.isEditing() && !this.isEditRow(inRowIndex)){
+			this.applyRowEdit();
+			this.grid.updateRow(inRowIndex);
+		}
+		if(inEditing){
+			this.info = { cell: inCell, rowIndex: inRowIndex };
+			this.grid.doStartEdit(inCell, inRowIndex); 
+			this.grid.updateRow(inRowIndex);
+		}else{
+			this.info = {};
+		}
+		this.grid.endUpdate();
+		// make sure we don't utterly lose focus
+		this.grid.focus.focusGrid();
+		// let the editor focus itself as needed
+		this._focusEditor(inCell, inRowIndex);
+		// give ourselves a few ms to boomerang IE focus effects
+		this._doCatchBoomerang();
+	},
+
+	_editorDo: function(inMethod){
+		var c = this.info.cell;
+		//c && c.editor && c.editor[inMethod](c, this.info.rowIndex);
+		if(c && c.editable){
+			c[inMethod](this.info.rowIndex);
+		}
+	},
+
+	editorApply: function(){
+		this._editorDo("apply");
+	},
+
+	editorCancel: function(){
+		this._editorDo("cancel");
+	},
+
+	applyCellEdit: function(inValue, inCell, inRowIndex){
+		if(this.grid.canEdit(inCell, inRowIndex)){
+			this.grid.doApplyCellEdit(inValue, inRowIndex, inCell.field);
+		}
+	},
+
+	applyRowEdit: function(){
+		this.grid.doApplyEdit(this.info.rowIndex, this.info.cell.field);
+	},
+
+	apply: function(){
+		// summary:
+		//		Apply a grid edit
+		if(this.isEditing()){
+			this.grid.beginUpdate();
+			this.editorApply();
+			this.applyRowEdit();
+			this.info = {};
+			this.grid.endUpdate();
+			this.grid.focus.focusGrid();
+			this._doCatchBoomerang();
+		}
+	},
+
+	cancel: function(){
+		// summary:
+		//		Cancel a grid edit
+		if(this.isEditing()){
+			this.grid.beginUpdate();
+			this.editorCancel();
+			this.info = {};
+			this.grid.endUpdate();
+			this.grid.focus.focusGrid();
+			this._doCatchBoomerang();
+		}
+	},
+
+	save: function(inRowIndex, inView){
+		// summary:
+		//		Save the grid editing state
+		// inRowIndex: Integer
+		//		Grid row index
+		// inView: Object
+		//		Grid view
+		var c = this.info.cell;
+		if(this.isEditRow(inRowIndex) && (!inView || c.view==inView) && c.editable){
+			c.save(c, this.info.rowIndex);
+		}
+	},
+
+	restore: function(inView, inRowIndex){
+		// summary:
+		//		Restores the grid editing state
+		// inRowIndex: Integer
+		//		Grid row index
+		// inView: Object
+		//		Grid view
+		var c = this.info.cell;
+		if(this.isEditRow(inRowIndex) && c.view == inView && c.editable){
+			c.restore(c, this.info.rowIndex);
+		}
+	}
+});
diff --git a/dojox/grid/_Events.js b/dojox/grid/_Events.js
index b6cdf4f..06d8bc4 100644
--- a/dojox/grid/_Events.js
+++ b/dojox/grid/_Events.js
@@ -1,227 +1,492 @@
-/*
-	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
-*/
+dojo.provide("dojox.grid._Events");
 
+dojo.declare("dojox.grid._Events", null, {
+	// summary:
+	//		_Grid mixin that provides default implementations for grid events.
+	// description: 
+	//		Default synthetic events dispatched for _Grid. dojo.connect to events to
+	//		retain default implementation or override them for custom handling.
+	
+	// cellOverClass: String
+	// 		css class to apply to grid cells over which the cursor is placed.
+	cellOverClass: "dojoxGridCellOver",
+	
+	onKeyEvent: function(e){
+		// summary: top level handler for Key Events
+		this.dispatchKeyEvent(e);
+	},
 
-if(!dojo._hasResource["dojox.grid._Events"]){
-dojo._hasResource["dojox.grid._Events"]=true;
-dojo.provide("dojox.grid._Events");
-dojo.declare("dojox.grid._Events",null,{cellOverClass:"dojoxGridCellOver",onKeyEvent:function(e){
-this.dispatchKeyEvent(e);
-},onContentEvent:function(e){
-this.dispatchContentEvent(e);
-},onHeaderEvent:function(e){
-this.dispatchHeaderEvent(e);
-},onStyleRow:function(_1){
-var i=_1;
-i.customClasses+=(i.odd?" dojoxGridRowOdd":"")+(i.selected?" dojoxGridRowSelected":"")+(i.over?" dojoxGridRowOver":"");
-this.focus.styleRow(_1);
-this.edit.styleRow(_1);
-},onKeyDown:function(e){
-if(e.altKey||e.metaKey){
-return;
-}
-var dk=dojo.keys;
-var _2;
-switch(e.keyCode){
-case dk.ESCAPE:
-this.edit.cancel();
-break;
-case dk.ENTER:
-if(!this.edit.isEditing()){
-_2=this.focus.getHeaderIndex();
-if(_2>=0){
-this.setSortIndex(_2);
-break;
-}else{
-this.selection.clickSelect(this.focus.rowIndex,dojo.isCopyKey(e),e.shiftKey);
-}
-dojo.stopEvent(e);
-}
-if(!e.shiftKey){
-var _3=this.edit.isEditing();
-this.edit.apply();
-if(!_3){
-this.edit.setEditCell(this.focus.cell,this.focus.rowIndex);
-}
-}
-if(!this.edit.isEditing()){
-var _4=this.focus.focusView||this.views.views[0];
-_4.content.decorateEvent(e);
-this.onRowClick(e);
-}
-break;
-case dk.SPACE:
-if(!this.edit.isEditing()){
-_2=this.focus.getHeaderIndex();
-if(_2>=0){
-this.setSortIndex(_2);
-break;
-}else{
-this.selection.clickSelect(this.focus.rowIndex,dojo.isCopyKey(e),e.shiftKey);
-}
-dojo.stopEvent(e);
-}
-break;
-case dk.TAB:
-this.focus[e.shiftKey?"previousKey":"nextKey"](e);
-break;
-case dk.LEFT_ARROW:
-case dk.RIGHT_ARROW:
-if(!this.edit.isEditing()){
-var _5=e.keyCode;
-dojo.stopEvent(e);
-_2=this.focus.getHeaderIndex();
-if(_2>=0&&(e.shiftKey&&e.ctrlKey)){
-this.focus.colSizeAdjust(e,_2,(_5==dk.LEFT_ARROW?-1:1)*5);
-}else{
-var _6=(_5==dk.LEFT_ARROW)?1:-1;
-if(dojo._isBodyLtr()){
-_6*=-1;
-}
-this.focus.move(0,_6);
-}
-}
-break;
-case dk.UP_ARROW:
-if(!this.edit.isEditing()&&this.focus.rowIndex!==0){
-dojo.stopEvent(e);
-this.focus.move(-1,0);
-}
-break;
-case dk.DOWN_ARROW:
-if(!this.edit.isEditing()&&this.focus.rowIndex+1!=this.rowCount){
-dojo.stopEvent(e);
-this.focus.move(1,0);
-}
-break;
-case dk.PAGE_UP:
-if(!this.edit.isEditing()&&this.focus.rowIndex!==0){
-dojo.stopEvent(e);
-if(this.focus.rowIndex!=this.scroller.firstVisibleRow+1){
-this.focus.move(this.scroller.firstVisibleRow-this.focus.rowIndex,0);
-}else{
-this.setScrollTop(this.scroller.findScrollTop(this.focus.rowIndex-1));
-this.focus.move(this.scroller.firstVisibleRow-this.scroller.lastVisibleRow+1,0);
-}
-}
-break;
-case dk.PAGE_DOWN:
-if(!this.edit.isEditing()&&this.focus.rowIndex+1!=this.rowCount){
-dojo.stopEvent(e);
-if(this.focus.rowIndex!=this.scroller.lastVisibleRow-1){
-this.focus.move(this.scroller.lastVisibleRow-this.focus.rowIndex-1,0);
-}else{
-this.setScrollTop(this.scroller.findScrollTop(this.focus.rowIndex+1));
-this.focus.move(this.scroller.lastVisibleRow-this.scroller.firstVisibleRow-1,0);
-}
-}
-break;
-default:
-break;
-}
-},onMouseOver:function(e){
-e.rowIndex==-1?this.onHeaderCellMouseOver(e):this.onCellMouseOver(e);
-},onMouseOut:function(e){
-e.rowIndex==-1?this.onHeaderCellMouseOut(e):this.onCellMouseOut(e);
-},onMouseDown:function(e){
-e.rowIndex==-1?this.onHeaderCellMouseDown(e):this.onCellMouseDown(e);
-},onMouseOverRow:function(e){
-if(!this.rows.isOver(e.rowIndex)){
-this.rows.setOverRow(e.rowIndex);
-e.rowIndex==-1?this.onHeaderMouseOver(e):this.onRowMouseOver(e);
-}
-},onMouseOutRow:function(e){
-if(this.rows.isOver(-1)){
-this.onHeaderMouseOut(e);
-}else{
-if(!this.rows.isOver(-2)){
-this.rows.setOverRow(-2);
-this.onRowMouseOut(e);
-}
-}
-},onMouseDownRow:function(e){
-if(e.rowIndex!=-1){
-this.onRowMouseDown(e);
-}
-},onCellMouseOver:function(e){
-if(e.cellNode){
-dojo.addClass(e.cellNode,this.cellOverClass);
-}
-},onCellMouseOut:function(e){
-if(e.cellNode){
-dojo.removeClass(e.cellNode,this.cellOverClass);
-}
-},onCellMouseDown:function(e){
-},onCellClick:function(e){
-this._click[0]=this._click[1];
-this._click[1]=e;
-if(!this.edit.isEditCell(e.rowIndex,e.cellIndex)){
-this.focus.setFocusCell(e.cell,e.rowIndex);
-}
-this.onRowClick(e);
-},onCellDblClick:function(e){
-if(this._click.length>1&&dojo.isIE){
-this.edit.setEditCell(this._click[1].cell,this._click[1].rowIndex);
-}else{
-if(this._click.length>1&&this._click[0].rowIndex!=this._click[1].rowIndex){
-this.edit.setEditCell(this._click[0].cell,this._click[0].rowIndex);
-}else{
-this.edit.setEditCell(e.cell,e.rowIndex);
-}
-}
-this.onRowDblClick(e);
-},onCellContextMenu:function(e){
-this.onRowContextMenu(e);
-},onCellFocus:function(_7,_8){
-this.edit.cellFocus(_7,_8);
-},onRowClick:function(e){
-this.edit.rowClick(e);
-this.selection.clickSelectEvent(e);
-},onRowDblClick:function(e){
-},onRowMouseOver:function(e){
-},onRowMouseOut:function(e){
-},onRowMouseDown:function(e){
-},onRowContextMenu:function(e){
-dojo.stopEvent(e);
-},onHeaderMouseOver:function(e){
-},onHeaderMouseOut:function(e){
-},onHeaderCellMouseOver:function(e){
-if(e.cellNode){
-dojo.addClass(e.cellNode,this.cellOverClass);
-}
-},onHeaderCellMouseOut:function(e){
-if(e.cellNode){
-dojo.removeClass(e.cellNode,this.cellOverClass);
-}
-},onHeaderCellMouseDown:function(e){
-},onHeaderClick:function(e){
-},onHeaderCellClick:function(e){
-this.setSortIndex(e.cell.index);
-this.onHeaderClick(e);
-},onHeaderDblClick:function(e){
-},onHeaderCellDblClick:function(e){
-this.onHeaderDblClick(e);
-},onHeaderCellContextMenu:function(e){
-this.onHeaderContextMenu(e);
-},onHeaderContextMenu:function(e){
-if(!this.headerMenu){
-dojo.stopEvent(e);
-}
-},onStartEdit:function(_9,_a){
-},onApplyCellEdit:function(_b,_c,_d){
-},onCancelEdit:function(_e){
-},onApplyEdit:function(_f){
-},onCanSelect:function(_10){
-return true;
-},onCanDeselect:function(_11){
-return true;
-},onSelected:function(_12){
-this.updateRowStyles(_12);
-},onDeselected:function(_13){
-this.updateRowStyles(_13);
-},onSelectionChanged:function(){
-}});
-}
+	onContentEvent: function(e){
+		// summary: Top level handler for Content events
+		this.dispatchContentEvent(e);
+	},
+
+	onHeaderEvent: function(e){
+		// summary: Top level handler for header events
+		this.dispatchHeaderEvent(e);
+	},
+
+	onStyleRow: function(inRow){
+		// summary:
+		//		Perform row styling on a given row. Called whenever row styling is updated.
+		//
+		// inRow: Object
+		// 		Object containing row state information: selected, true if the row is selcted; over:
+		// 		true of the mouse is over the row; odd: true if the row is odd. Use customClasses and
+		// 		customStyles to control row css classes and styles; both properties are strings.
+		//
+		// example: onStyleRow({ selected: true, over:true, odd:false })
+		var i = inRow;
+		i.customClasses += (i.odd?" dojoxGridRowOdd":"") + (i.selected?" dojoxGridRowSelected":"") + (i.over?" dojoxGridRowOver":"");
+		this.focus.styleRow(inRow);
+		this.edit.styleRow(inRow);
+	},
+	
+	onKeyDown: function(e){
+		// summary:
+		// 		Grid key event handler. By default enter begins editing and applies edits, escape cancels an edit,
+		// 		tab, shift-tab, and arrow keys move grid cell focus.
+		if(e.altKey || e.metaKey){
+			return;
+		}
+		var dk = dojo.keys;
+		var colIdx;
+		switch(e.keyCode){
+			case dk.ESCAPE:
+				this.edit.cancel();
+				break;
+			case dk.ENTER:
+				if(!this.edit.isEditing()){
+					colIdx = this.focus.getHeaderIndex();
+					if(colIdx >= 0) {
+						this.setSortIndex(colIdx);
+						break;
+					}else {
+						this.selection.clickSelect(this.focus.rowIndex, dojo.isCopyKey(e), e.shiftKey);
+					}
+					dojo.stopEvent(e);
+				}
+				if(!e.shiftKey){
+					var isEditing = this.edit.isEditing();
+					this.edit.apply();
+					if(!isEditing){
+						this.edit.setEditCell(this.focus.cell, this.focus.rowIndex);
+					}
+				}
+				if (!this.edit.isEditing()){
+					var curView = this.focus.focusView || this.views.views[0];  //if no focusView than only one view
+					curView.content.decorateEvent(e);
+					this.onRowClick(e);
+				}
+				break;
+			case dk.SPACE:
+				if(!this.edit.isEditing()){
+					colIdx = this.focus.getHeaderIndex();
+					if(colIdx >= 0) {
+						this.setSortIndex(colIdx);
+						break;
+					}else {
+						this.selection.clickSelect(this.focus.rowIndex, dojo.isCopyKey(e), e.shiftKey);
+					}
+					dojo.stopEvent(e);
+				}
+				break;
+			case dk.TAB:
+				this.focus[e.shiftKey ? 'previousKey' : 'nextKey'](e);
+				break;
+			case dk.LEFT_ARROW:
+			case dk.RIGHT_ARROW:
+				if(!this.edit.isEditing()){
+					var keyCode = e.keyCode;  // IE seems to lose after stopEvent when modifier keys
+					dojo.stopEvent(e);
+					colIdx = this.focus.getHeaderIndex();
+					if (colIdx >= 0 && (e.shiftKey && e.ctrlKey)){
+						this.focus.colSizeAdjust(e, colIdx, (keyCode == dk.LEFT_ARROW ? -1 : 1)*5);
+					}
+					else{
+						var offset = (keyCode == dk.LEFT_ARROW) ? 1 : -1;
+						if(dojo._isBodyLtr()){ offset *= -1; }
+						this.focus.move(0, offset);
+					}
+				}
+				break;
+			case dk.UP_ARROW:
+				if(!this.edit.isEditing() && this.focus.rowIndex !== 0){
+					dojo.stopEvent(e);
+					this.focus.move(-1, 0);
+				}
+				break;
+			case dk.DOWN_ARROW:
+				if(!this.edit.isEditing() && this.focus.rowIndex+1 != this.rowCount){
+					dojo.stopEvent(e);
+					this.focus.move(1, 0);
+				}
+				break;
+			case dk.PAGE_UP:
+				if(!this.edit.isEditing() && this.focus.rowIndex !== 0){
+					dojo.stopEvent(e);
+					if(this.focus.rowIndex != this.scroller.firstVisibleRow+1){
+						this.focus.move(this.scroller.firstVisibleRow-this.focus.rowIndex, 0);
+					}else{
+						this.setScrollTop(this.scroller.findScrollTop(this.focus.rowIndex-1));
+						this.focus.move(this.scroller.firstVisibleRow-this.scroller.lastVisibleRow+1, 0);
+					}
+				}
+				break;
+			case dk.PAGE_DOWN:
+				if(!this.edit.isEditing() && this.focus.rowIndex+1 != this.rowCount){
+					dojo.stopEvent(e);
+					if(this.focus.rowIndex != this.scroller.lastVisibleRow-1){
+						this.focus.move(this.scroller.lastVisibleRow-this.focus.rowIndex-1, 0);
+					}else{
+						this.setScrollTop(this.scroller.findScrollTop(this.focus.rowIndex+1));
+						this.focus.move(this.scroller.lastVisibleRow-this.scroller.firstVisibleRow-1, 0);
+					}
+				}
+				break;
+			default:
+				break;
+		}
+	},
+	
+	onMouseOver: function(e){
+		// summary:
+		//		Event fired when mouse is over the grid.
+		// e: Event
+		//		Decorated event object contains reference to grid, cell, and rowIndex
+		e.rowIndex == -1 ? this.onHeaderCellMouseOver(e) : this.onCellMouseOver(e);
+	},
+	
+	onMouseOut: function(e){
+		// summary:
+		//		Event fired when mouse moves out of the grid.
+		// e: Event
+		//		Decorated event object that contains reference to grid, cell, and rowIndex
+		e.rowIndex == -1 ? this.onHeaderCellMouseOut(e) : this.onCellMouseOut(e);
+	},
+	
+	onMouseDown: function(e){
+		// summary:
+		//		Event fired when mouse is down inside grid.
+		// e: Event
+		//		Decorated event object that contains reference to grid, cell, and rowIndex
+		e.rowIndex == -1 ? this.onHeaderCellMouseDown(e) : this.onCellMouseDown(e);
+	},
+	
+	onMouseOverRow: function(e){
+		// summary:
+		//		Event fired when mouse is over any row (data or header).
+		// e: Event
+		//		Decorated event object contains reference to grid, cell, and rowIndex
+		if(!this.rows.isOver(e.rowIndex)){
+			this.rows.setOverRow(e.rowIndex);
+			e.rowIndex == -1 ? this.onHeaderMouseOver(e) : this.onRowMouseOver(e);
+		}
+	},
+	onMouseOutRow: function(e){
+		// summary:
+		//		Event fired when mouse moves out of any row (data or header).
+		// e: Event
+		//		Decorated event object contains reference to grid, cell, and rowIndex
+		if(this.rows.isOver(-1)){
+			this.onHeaderMouseOut(e);
+		}else if(!this.rows.isOver(-2)){
+			this.rows.setOverRow(-2);
+			this.onRowMouseOut(e);
+		}
+	},
+	
+	onMouseDownRow: function(e){
+		// summary:
+		//		Event fired when mouse is down inside grid row
+		// e: Event
+		//		Decorated event object that contains reference to grid, cell, and rowIndex
+		if(e.rowIndex != -1)
+			this.onRowMouseDown(e);
+	},
+
+	// cell events
+	onCellMouseOver: function(e){
+		// summary:
+		//		Event fired when mouse is over a cell.
+		// e: Event
+		//		Decorated event object contains reference to grid, cell, and rowIndex
+		if(e.cellNode){
+			dojo.addClass(e.cellNode, this.cellOverClass);
+		}
+	},
+	
+	onCellMouseOut: function(e){
+		// summary:
+		//		Event fired when mouse moves out of a cell.
+		// e: Event
+		//		Decorated event object which contains reference to grid, cell, and rowIndex
+		if(e.cellNode){
+			dojo.removeClass(e.cellNode, this.cellOverClass);
+		}
+	},
+	
+	onCellMouseDown: function(e){
+		// summary:
+		//		Event fired when mouse is down in a header cell.
+		// e: Event
+		// 		Decorated event object which contains reference to grid, cell, and rowIndex
+	},
+
+	onCellClick: function(e){
+		// summary:
+		//		Event fired when a cell is clicked.
+		// e: Event
+		//		Decorated event object which contains reference to grid, cell, and rowIndex
+		this._click[0] = this._click[1];
+		this._click[1] = e;
+		if(!this.edit.isEditCell(e.rowIndex, e.cellIndex)){
+			this.focus.setFocusCell(e.cell, e.rowIndex);
+		}
+		this.onRowClick(e);
+	},
+
+	onCellDblClick: function(e){
+		// summary:
+		//		Event fired when a cell is double-clicked.
+		// e: Event
+		//		Decorated event object contains reference to grid, cell, and rowIndex
+		if(this._click.length > 1 && dojo.isIE){
+			this.edit.setEditCell(this._click[1].cell, this._click[1].rowIndex);
+		}else if(this._click.length > 1 && this._click[0].rowIndex != this._click[1].rowIndex){
+			this.edit.setEditCell(this._click[0].cell, this._click[0].rowIndex);
+		}else{
+			this.edit.setEditCell(e.cell, e.rowIndex);
+		}
+		this.onRowDblClick(e);
+	},
+
+	onCellContextMenu: function(e){
+		// summary:
+		//		Event fired when a cell context menu is accessed via mouse right click.
+		// e: Event
+		//		Decorated event object which contains reference to grid, cell, and rowIndex
+		this.onRowContextMenu(e);
+	},
+
+	onCellFocus: function(inCell, inRowIndex){
+		// summary:
+		//		Event fired when a cell receives focus.
+		// inCell: Object
+		//		Cell object containing properties of the grid column.
+		// inRowIndex: Integer
+		//		Index of the grid row
+		this.edit.cellFocus(inCell, inRowIndex);
+	},
+
+	// row events
+	onRowClick: function(e){
+		// summary:
+		//		Event fired when a row is clicked.
+		// e: Event
+		//		Decorated event object which contains reference to grid, cell, and rowIndex
+		this.edit.rowClick(e);
+		this.selection.clickSelectEvent(e);
+	},
+
+	onRowDblClick: function(e){
+		// summary:
+		//		Event fired when a row is double clicked.
+		// e: Event
+		//		decorated event object which contains reference to grid, cell, and rowIndex
+	},
+
+	onRowMouseOver: function(e){
+		// summary:
+		//		Event fired when mouse moves over a data row.
+		// e: Event
+		//		Decorated event object which contains reference to grid, cell, and rowIndex
+	},
+
+	onRowMouseOut: function(e){
+		// summary:
+		//		Event fired when mouse moves out of a data row.
+		// e: Event
+		// 		Decorated event object contains reference to grid, cell, and rowIndex
+	},
+	
+	onRowMouseDown: function(e){
+		// summary:
+		//		Event fired when mouse is down in a row.
+		// e: Event
+		// 		Decorated event object which contains reference to grid, cell, and rowIndex
+	},
+
+	onRowContextMenu: function(e){
+		// summary:
+		//		Event fired when a row context menu is accessed via mouse right click.
+		// e: Event
+		// 		Decorated event object which contains reference to grid, cell, and rowIndex
+		dojo.stopEvent(e);
+	},
+
+	// header events
+	onHeaderMouseOver: function(e){
+		// summary:
+		//		Event fired when mouse moves over the grid header.
+		// e: Event
+		// 		Decorated event object contains reference to grid, cell, and rowIndex
+	},
+
+	onHeaderMouseOut: function(e){
+		// summary:
+		//		Event fired when mouse moves out of the grid header.
+		// e: Event
+		// 		Decorated event object which contains reference to grid, cell, and rowIndex
+	},
+
+	onHeaderCellMouseOver: function(e){
+		// summary:
+		//		Event fired when mouse moves over a header cell.
+		// e: Event
+		// 		Decorated event object which contains reference to grid, cell, and rowIndex
+		if(e.cellNode){
+			dojo.addClass(e.cellNode, this.cellOverClass);
+		}
+	},
+
+	onHeaderCellMouseOut: function(e){
+		// summary:
+		//		Event fired when mouse moves out of a header cell.
+		// e: Event
+		// 		Decorated event object which contains reference to grid, cell, and rowIndex
+		if(e.cellNode){
+			dojo.removeClass(e.cellNode, this.cellOverClass);
+		}
+	},
+	
+	onHeaderCellMouseDown: function(e) {
+		// summary:
+		//		Event fired when mouse is down in a header cell.
+		// e: Event
+		// 		Decorated event object which contains reference to grid, cell, and rowIndex
+	},
+
+	onHeaderClick: function(e){
+		// summary:
+		//		Event fired when the grid header is clicked.
+		// e: Event
+		// Decorated event object which contains reference to grid, cell, and rowIndex
+	},
+
+	onHeaderCellClick: function(e){
+		// summary:
+		//		Event fired when a header cell is clicked.
+		// e: Event
+		//		Decorated event object which contains reference to grid, cell, and rowIndex
+		this.setSortIndex(e.cell.index);
+		this.onHeaderClick(e);
+	},
+
+	onHeaderDblClick: function(e){
+		// summary:
+		//		Event fired when the grid header is double clicked.
+		// e: Event
+		//		Decorated event object which contains reference to grid, cell, and rowIndex
+	},
+
+	onHeaderCellDblClick: function(e){
+		// summary:
+		//		Event fired when a header cell is double clicked.
+		// e: Event
+		//		Decorated event object which contains reference to grid, cell, and rowIndex
+		this.onHeaderDblClick(e);
+	},
+
+	onHeaderCellContextMenu: function(e){
+		// summary:
+		//		Event fired when a header cell context menu is accessed via mouse right click.
+		// e: Event
+		//		Decorated event object which contains reference to grid, cell, and rowIndex
+		this.onHeaderContextMenu(e);
+	},
+
+	onHeaderContextMenu: function(e){
+		// summary:
+		//		Event fired when the grid header context menu is accessed via mouse right click.
+		// e: Event
+		//		Decorated event object which contains reference to grid, cell, and rowIndex
+		if(!this.headerMenu){
+			dojo.stopEvent(e);
+		}
+	},
+
+	// editing
+	onStartEdit: function(inCell, inRowIndex){
+		// summary:
+		//		Event fired when editing is started for a given grid cell
+		// inCell: Object
+		//		Cell object containing properties of the grid column.
+		// inRowIndex: Integer
+		//		Index of the grid row
+	},
+
+	onApplyCellEdit: function(inValue, inRowIndex, inFieldIndex){
+		// summary:
+		//		Event fired when editing is applied for a given grid cell
+		// inValue: String
+		//		Value from cell editor
+		// inRowIndex: Integer
+		//		Index of the grid row
+		// inFieldIndex: Integer
+		//		Index in the grid's data store
+	},
+
+	onCancelEdit: function(inRowIndex){
+		// summary:
+		//		Event fired when editing is cancelled for a given grid cell
+		// inRowIndex: Integer
+		//		Index of the grid row
+	},
+
+	onApplyEdit: function(inRowIndex){
+		// summary:
+		//		Event fired when editing is applied for a given grid row
+		// inRowIndex: Integer
+		//		Index of the grid row
+	},
+
+	onCanSelect: function(inRowIndex){
+		// summary:
+		//		Event to determine if a grid row may be selected
+		// inRowIndex: Integer
+		//		Index of the grid row
+		// returns: Boolean
+		//		true if the row can be selected
+		return true;
+	},
+
+	onCanDeselect: function(inRowIndex){
+		// summary:
+		//		Event to determine if a grid row may be deselected
+		// inRowIndex: Integer
+		//		Index of the grid row
+		// returns: Boolean
+		//		true if the row can be deselected
+		return true;
+	},
+
+	onSelected: function(inRowIndex){
+		// summary:
+		//		Event fired when a grid row is selected
+		// inRowIndex: Integer
+		//		Index of the grid row
+		this.updateRowStyles(inRowIndex);
+	},
+
+	onDeselected: function(inRowIndex){
+		// summary:
+		//		Event fired when a grid row is deselected
+		// inRowIndex: Integer
+		//		Index of the grid row
+		this.updateRowStyles(inRowIndex);
+	},
+
+	onSelectionChanged: function(){
+	}
+});
diff --git a/dojox/grid/_FocusManager.js b/dojox/grid/_FocusManager.js
index 9a41204..42db940 100644
--- a/dojox/grid/_FocusManager.js
+++ b/dojox/grid/_FocusManager.js
@@ -1,464 +1,596 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._FocusManager"]){
-dojo._hasResource["dojox.grid._FocusManager"]=true;
 dojo.provide("dojox.grid._FocusManager");
+
 dojo.require("dojox.grid.util");
-dojo.declare("dojox.grid._FocusManager",null,{constructor:function(_1){
-this.grid=_1;
-this.cell=null;
-this.rowIndex=-1;
-this._connects=[];
-this.headerMenu=this.grid.headerMenu;
-this._connects.push(dojo.connect(this.grid.domNode,"onfocus",this,"doFocus"));
-this._connects.push(dojo.connect(this.grid.domNode,"onblur",this,"doBlur"));
-this._connects.push(dojo.connect(this.grid.domNode,"oncontextmenu",this,"doContextMenu"));
-this._connects.push(dojo.connect(this.grid.lastFocusNode,"onfocus",this,"doLastNodeFocus"));
-this._connects.push(dojo.connect(this.grid.lastFocusNode,"onblur",this,"doLastNodeBlur"));
-this._connects.push(dojo.connect(this.grid,"_onFetchComplete",this,"_delayedCellFocus"));
-this._connects.push(dojo.connect(this.grid,"postrender",this,"_delayedHeaderFocus"));
-},destroy:function(){
-dojo.forEach(this._connects,dojo.disconnect);
-delete this.grid;
-delete this.cell;
-},_colHeadNode:null,_colHeadFocusIdx:null,_contextMenuBindNode:null,tabbingOut:false,focusClass:"dojoxGridCellFocus",focusView:null,initFocusView:function(){
-this.focusView=this.grid.views.getFirstScrollingView()||this.focusView;
-this._initColumnHeaders();
-},isFocusCell:function(_2,_3){
-return (this.cell==_2)&&(this.rowIndex==_3);
-},isLastFocusCell:function(){
-if(this.cell){
-return (this.rowIndex==this.grid.rowCount-1)&&(this.cell.index==this.grid.layout.cellCount-1);
-}
-return false;
-},isFirstFocusCell:function(){
-if(this.cell){
-return (this.rowIndex===0)&&(this.cell.index===0);
-}
-return false;
-},isNoFocusCell:function(){
-return (this.rowIndex<0)||!this.cell;
-},isNavHeader:function(){
-return (!!this._colHeadNode);
-},getHeaderIndex:function(){
-if(this._colHeadNode){
-return dojo.indexOf(this._findHeaderCells(),this._colHeadNode);
-}else{
-return -1;
-}
-},_focusifyCellNode:function(_4){
-var n=this.cell&&this.cell.getNode(this.rowIndex);
-if(n){
-dojo.toggleClass(n,this.focusClass,_4);
-if(_4){
-var sl=this.scrollIntoView();
-try{
-if(!this.grid.edit.isEditing()){
-dojox.grid.util.fire(n,"focus");
-if(sl){
-this.cell.view.scrollboxNode.scrollLeft=sl;
-}
-}
-}
-catch(e){
-}
-}
-}
-},_delayedCellFocus:function(){
-if(this.isNavHeader()||!this.grid._focused){
-return;
-}
-var n=this.cell&&this.cell.getNode(this.rowIndex);
-if(n){
-try{
-if(!this.grid.edit.isEditing()){
-dojo.toggleClass(n,this.focusClass,true);
-this.blurHeader();
-dojox.grid.util.fire(n,"focus");
-}
-}
-catch(e){
-}
-}
-},_delayedHeaderFocus:function(){
-if(this.isNavHeader()){
-this.focusHeader();
-this.grid.domNode.focus();
-}
-},_initColumnHeaders:function(){
-var _5=this._findHeaderCells();
-for(var i=0;i<_5.length;i++){
-this._connects.push(dojo.connect(_5[i],"onfocus",this,"doColHeaderFocus"));
-this._connects.push(dojo.connect(_5[i],"onblur",this,"doColHeaderBlur"));
-}
-},_findHeaderCells:function(){
-var _6=dojo.query("th",this.grid.viewsHeaderNode);
-var _7=[];
-for(var i=0;i<_6.length;i++){
-var _8=_6[i];
-var _9=dojo.hasAttr(_8,"tabIndex");
-var _a=dojo.attr(_8,"tabIndex");
-if(_9&&_a<0){
-_7.push(_8);
-}
-}
-return _7;
-},_setActiveColHeader:function(_b,_c,_d){
-dojo.attr(this.grid.domNode,"aria-activedescendant",_b.id);
-if(_d!=null&&_d>=0&&_d!=_c){
-dojo.toggleClass(this._findHeaderCells()[_d],this.focusClass,false);
-}
-dojo.toggleClass(_b,this.focusClass,true);
-this._colHeadNode=_b;
-this._colHeadFocusIdx=_c;
-this._scrollHeader(this._colHeadFocusIdx);
-},scrollIntoView:function(){
-var _e=(this.cell?this._scrollInfo(this.cell):null);
-if(!_e||!_e.s){
-return null;
-}
-var rt=this.grid.scroller.findScrollTop(this.rowIndex);
-if(_e.n&&_e.sr){
-if(_e.n.offsetLeft+_e.n.offsetWidth>_e.sr.l+_e.sr.w){
-_e.s.scrollLeft=_e.n.offsetLeft+_e.n.offsetWidth-_e.sr.w;
-}else{
-if(_e.n.offsetLeft<_e.sr.l){
-_e.s.scrollLeft=_e.n.offsetLeft;
-}
-}
-}
-if(_e.r&&_e.sr){
-if(rt+_e.r.offsetHeight>_e.sr.t+_e.sr.h){
-this.grid.setScrollTop(rt+_e.r.offsetHeight-_e.sr.h);
-}else{
-if(rt<_e.sr.t){
-this.grid.setScrollTop(rt);
-}
-}
-}
-return _e.s.scrollLeft;
-},_scrollInfo:function(_f,_10){
-if(_f){
-var cl=_f,sbn=cl.view.scrollboxNode,_11={w:sbn.clientWidth,l:sbn.scrollLeft,t:sbn.scrollTop,h:sbn.clientHeight},rn=cl.view.getRowNode(this.rowIndex);
-return {c:cl,s:sbn,sr:_11,n:(_10?_10:_f.getNode(this.rowIndex)),r:rn};
-}
-return null;
-},_scrollHeader:function(_12){
-var _13=null;
-if(this._colHeadNode){
-var _14=this.grid.getCell(_12);
-_13=this._scrollInfo(_14,_14.getNode(0));
-}
-if(_13&&_13.s&&_13.sr&&_13.n){
-var _15=_13.sr.l+_13.sr.w;
-if(_13.n.offsetLeft+_13.n.offsetWidth>_15){
-_13.s.scrollLeft=_13.n.offsetLeft+_13.n.offsetWidth-_13.sr.w;
-}else{
-if(_13.n.offsetLeft<_13.sr.l){
-_13.s.scrollLeft=_13.n.offsetLeft;
-}else{
-if(dojo.isIE<=7&&_14&&_14.view.headerNode){
-_14.view.headerNode.scrollLeft=_13.s.scrollLeft;
-}
-}
-}
-}
-},_isHeaderHidden:function(){
-var _16=this.focusView;
-if(!_16){
-for(var i=0,_17;(_17=this.grid.views.views[i]);i++){
-if(_17.headerNode){
-_16=_17;
-break;
-}
-}
-}
-return (_16&&dojo.getComputedStyle(_16.headerNode).display=="none");
-},colSizeAdjust:function(e,_18,_19){
-var _1a=this._findHeaderCells();
-var _1b=this.focusView;
-if(!_1b){
-for(var i=0,_1c;(_1c=this.grid.views.views[i]);i++){
-if(_1c.header.tableMap.map){
-_1b=_1c;
-break;
-}
-}
-}
-var _1d=_1a[_18];
-if(!_1b||(_18==_1a.length-1&&_18===0)){
-return;
-}
-_1b.content.baseDecorateEvent(e);
-e.cellNode=_1d;
-e.cellIndex=_1b.content.getCellNodeIndex(e.cellNode);
-e.cell=(e.cellIndex>=0?this.grid.getCell(e.cellIndex):null);
-if(_1b.header.canResize(e)){
-var _1e={l:_19};
-var _1f=_1b.header.colResizeSetup(e,false);
-_1b.header.doResizeColumn(_1f,null,_1e);
-_1b.update();
-}
-},styleRow:function(_20){
-return;
-},setFocusIndex:function(_21,_22){
-this.setFocusCell(this.grid.getCell(_22),_21);
-},setFocusCell:function(_23,_24){
-if(_23&&!this.isFocusCell(_23,_24)){
-this.tabbingOut=false;
-if(this._colHeadNode){
-this.blurHeader();
-}
-this._colHeadNode=this._colHeadFocusIdx=null;
-this.focusGridView();
-this._focusifyCellNode(false);
-this.cell=_23;
-this.rowIndex=_24;
-this._focusifyCellNode(true);
-}
-if(dojo.isOpera){
-setTimeout(dojo.hitch(this.grid,"onCellFocus",this.cell,this.rowIndex),1);
-}else{
-this.grid.onCellFocus(this.cell,this.rowIndex);
-}
-},next:function(){
-if(this.cell){
-var row=this.rowIndex,col=this.cell.index+1,cc=this.grid.layout.cellCount-1,rc=this.grid.rowCount-1;
-if(col>cc){
-col=0;
-row++;
-}
-if(row>rc){
-col=cc;
-row=rc;
-}
-if(this.grid.edit.isEditing()){
-var _25=this.grid.getCell(col);
-if(!this.isLastFocusCell()&&!_25.editable){
-this.cell=_25;
-this.rowIndex=row;
-this.next();
-return;
-}
-}
-this.setFocusIndex(row,col);
-}
-},previous:function(){
-if(this.cell){
-var row=(this.rowIndex||0),col=(this.cell.index||0)-1;
-if(col<0){
-col=this.grid.layout.cellCount-1;
-row--;
-}
-if(row<0){
-row=0;
-col=0;
-}
-if(this.grid.edit.isEditing()){
-var _26=this.grid.getCell(col);
-if(!this.isFirstFocusCell()&&!_26.editable){
-this.cell=_26;
-this.rowIndex=row;
-this.previous();
-return;
-}
-}
-this.setFocusIndex(row,col);
-}
-},move:function(_27,_28){
-var _29=_28<0?-1:1;
-if(this.isNavHeader()){
-var _2a=this._findHeaderCells();
-var _2b=currentIdx=dojo.indexOf(_2a,this._colHeadNode);
-currentIdx+=_28;
-while(currentIdx>=0&&currentIdx<_2a.length&&_2a[currentIdx].style.display=="none"){
-currentIdx+=_29;
-}
-if((currentIdx>=0)&&(currentIdx<_2a.length)){
-this._setActiveColHeader(_2a[currentIdx],currentIdx,_2b);
-}
-}else{
-if(this.cell){
-var sc=this.grid.scroller,r=this.rowIndex,rc=this.grid.rowCount-1,row=Math.min(rc,Math.max(0,r+_27));
-if(_27){
-if(_27>0){
-if(row>sc.getLastPageRow(sc.page)){
-this.grid.setScrollTop(this.grid.scrollTop+sc.findScrollTop(row)-sc.findScrollTop(r));
-}
-}else{
-if(_27<0){
-if(row<=sc.getPageRow(sc.page)){
-this.grid.setScrollTop(this.grid.scrollTop-sc.findScrollTop(r)-sc.findScrollTop(row));
-}
-}
-}
-}
-var cc=this.grid.layout.cellCount-1,i=this.cell.index,col=Math.min(cc,Math.max(0,i+_28));
-var _2c=this.grid.getCell(col);
-while(col>=0&&col<cc&&_2c&&_2c.hidden===true){
-col+=_29;
-_2c=this.grid.getCell(col);
-}
-if(!_2c||_2c.hidden===true){
-col=i;
-}
-this.setFocusIndex(row,col);
-if(_27){
-this.grid.updateRow(r);
-}
-}
-}
-},previousKey:function(e){
-if(this.grid.edit.isEditing()){
-dojo.stopEvent(e);
-this.previous();
-}else{
-if(!this.isNavHeader()&&!this._isHeaderHidden()){
-this.grid.domNode.focus();
-dojo.stopEvent(e);
-}else{
-this.tabOut(this.grid.domNode);
-if(this._colHeadFocusIdx!=null){
-dojo.toggleClass(this._findHeaderCells()[this._colHeadFocusIdx],this.focusClass,false);
-this._colHeadFocusIdx=null;
-}
-this._focusifyCellNode(false);
-}
-}
-},nextKey:function(e){
-var _2d=(this.grid.rowCount===0);
-if(e.target===this.grid.domNode&&this._colHeadFocusIdx==null){
-this.focusHeader();
-dojo.stopEvent(e);
-}else{
-if(this.isNavHeader()){
-this.blurHeader();
-if(!this.findAndFocusGridCell()){
-this.tabOut(this.grid.lastFocusNode);
-}
-this._colHeadNode=this._colHeadFocusIdx=null;
-}else{
-if(this.grid.edit.isEditing()){
-dojo.stopEvent(e);
-this.next();
-}else{
-this.tabOut(this.grid.lastFocusNode);
-}
-}
-}
-},tabOut:function(_2e){
-this.tabbingOut=true;
-_2e.focus();
-},focusGridView:function(){
-dojox.grid.util.fire(this.focusView,"focus");
-},focusGrid:function(_2f){
-this.focusGridView();
-this._focusifyCellNode(true);
-},findAndFocusGridCell:function(){
-var _30=true;
-var _31=(this.grid.rowCount===0);
-if(this.isNoFocusCell()&&!_31){
-var _32=0;
-var _33=this.grid.getCell(_32);
-if(_33.hidden){
-_32=this.isNavHeader()?this._colHeadFocusIdx:0;
-}
-this.setFocusIndex(0,_32);
-}else{
-if(this.cell&&!_31){
-if(this.focusView&&!this.focusView.rowNodes[this.rowIndex]){
-this.grid.scrollToRow(this.rowIndex);
-}
-this.focusGrid();
-}else{
-_30=false;
-}
-}
-this._colHeadNode=this._colHeadFocusIdx=null;
-return _30;
-},focusHeader:function(){
-var _34=this._findHeaderCells();
-var _35=this._colHeadFocusIdx;
-if(this._isHeaderHidden()){
-this.findAndFocusGridCell();
-}else{
-if(!this._colHeadFocusIdx){
-if(this.isNoFocusCell()){
-this._colHeadFocusIdx=0;
-}else{
-this._colHeadFocusIdx=this.cell.index;
-}
-}
-}
-this._colHeadNode=_34[this._colHeadFocusIdx];
-while(this._colHeadNode&&this._colHeadFocusIdx>=0&&this._colHeadFocusIdx<_34.length&&this._colHeadNode.style.display=="none"){
-this._colHeadFocusIdx++;
-this._colHeadNode=_34[this._colHeadFocusIdx];
-}
-if(this._colHeadNode&&this._colHeadNode.style.display!="none"){
-if(this.headerMenu&&this._contextMenuBindNode!=this.grid.domNode){
-this.headerMenu.unBindDomNode(this.grid.viewsHeaderNode);
-this.headerMenu.bindDomNode(this.grid.domNode);
-this._contextMenuBindNode=this.grid.domNode;
-}
-this._setActiveColHeader(this._colHeadNode,this._colHeadFocusIdx,_35);
-this._scrollHeader(this._colHeadFocusIdx);
-this._focusifyCellNode(false);
-}else{
-this.findAndFocusGridCell();
-}
-},blurHeader:function(){
-dojo.removeClass(this._colHeadNode,this.focusClass);
-dojo.removeAttr(this.grid.domNode,"aria-activedescendant");
-if(this.headerMenu&&this._contextMenuBindNode==this.grid.domNode){
-var _36=this.grid.viewsHeaderNode;
-this.headerMenu.unBindDomNode(this.grid.domNode);
-this.headerMenu.bindDomNode(_36);
-this._contextMenuBindNode=_36;
-}
-},doFocus:function(e){
-if(e&&e.target!=e.currentTarget){
-dojo.stopEvent(e);
-return;
-}
-if(!this.tabbingOut){
-this.focusHeader();
-}
-this.tabbingOut=false;
-dojo.stopEvent(e);
-},doBlur:function(e){
-dojo.stopEvent(e);
-},doContextMenu:function(e){
-if(!this.headerMenu){
-dojo.stopEvent(e);
-}
-},doLastNodeFocus:function(e){
-if(this.tabbingOut){
-this._focusifyCellNode(false);
-}else{
-if(this.grid.rowCount>0){
-if(this.isNoFocusCell()){
-this.setFocusIndex(0,0);
-}
-this._focusifyCellNode(true);
-}else{
-this.focusHeader();
-}
-}
-this.tabbingOut=false;
-dojo.stopEvent(e);
-},doLastNodeBlur:function(e){
-dojo.stopEvent(e);
-},doColHeaderFocus:function(e){
-this._setActiveColHeader(e.target,dojo.attr(e.target,"idx"),this._colHeadFocusIdx);
-this._scrollHeader(this.getHeaderIndex());
-dojo.stopEvent(e);
-},doColHeaderBlur:function(e){
-dojo.toggleClass(e.target,this.focusClass,false);
-}});
-}
+
+// focus management
+dojo.declare("dojox.grid._FocusManager", null, {
+	// summary:
+	//	Controls grid cell focus. Owned by grid and used internally for focusing.
+	//	Note: grid cell actually receives keyboard input only when cell is being edited.
+	constructor: function(inGrid){
+		this.grid = inGrid;
+		this.cell = null;
+		this.rowIndex = -1;
+		this._connects = [];
+		this.headerMenu = this.grid.headerMenu;
+		this._connects.push(dojo.connect(this.grid.domNode, "onfocus", this, "doFocus"));
+		this._connects.push(dojo.connect(this.grid.domNode, "onblur", this, "doBlur"));
+		this._connects.push(dojo.connect(this.grid.domNode, "oncontextmenu", this, "doContextMenu"));
+		this._connects.push(dojo.connect(this.grid.lastFocusNode, "onfocus", this, "doLastNodeFocus"));
+		this._connects.push(dojo.connect(this.grid.lastFocusNode, "onblur", this, "doLastNodeBlur"));
+		this._connects.push(dojo.connect(this.grid,"_onFetchComplete", this, "_delayedCellFocus"));
+		this._connects.push(dojo.connect(this.grid,"postrender", this, "_delayedHeaderFocus"));
+	},
+	destroy: function(){
+		dojo.forEach(this._connects, dojo.disconnect);
+		delete this.grid;
+		delete this.cell;
+	},
+	_colHeadNode: null,
+	_colHeadFocusIdx: null,
+	_contextMenuBindNode: null,
+	tabbingOut: false,
+	focusClass: "dojoxGridCellFocus",
+	focusView: null,
+	initFocusView: function(){
+		this.focusView = this.grid.views.getFirstScrollingView() || this.focusView;
+		this._initColumnHeaders();
+	},
+	isFocusCell: function(inCell, inRowIndex){
+		// summary:
+		//	states if the given cell is focused
+		// inCell: object
+		//	grid cell object
+		// inRowIndex: int
+		//	grid row index
+		// returns:
+		//	true of the given grid cell is focused
+		return (this.cell == inCell) && (this.rowIndex == inRowIndex);
+	},
+	isLastFocusCell: function(){
+		if(this.cell){
+			return (this.rowIndex == this.grid.rowCount-1) && (this.cell.index == this.grid.layout.cellCount-1);
+		}
+		return false;
+	},
+	isFirstFocusCell: function(){
+		if(this.cell){
+			return (this.rowIndex === 0) && (this.cell.index === 0);
+		}
+		return false;
+	},
+	isNoFocusCell: function(){
+		return (this.rowIndex < 0) || !this.cell;
+	},
+	isNavHeader: function(){
+		// summary:
+		//	states whether currently navigating among column headers.
+		// returns:
+		//	true if focus is on a column header; false otherwise. 
+		return (!!this._colHeadNode);
+	},
+	getHeaderIndex: function(){
+		// summary:
+		//	if one of the column headers currently has focus, return its index.
+		// returns:
+		//	index of the focused column header, or -1 if none have focus.
+		if(this._colHeadNode){
+			return dojo.indexOf(this._findHeaderCells(), this._colHeadNode);
+		}else{
+			return -1;
+		}
+	},
+	_focusifyCellNode: function(inBork){
+		var n = this.cell && this.cell.getNode(this.rowIndex);
+		if(n){
+			dojo.toggleClass(n, this.focusClass, inBork);
+			if(inBork){
+				var sl = this.scrollIntoView();
+				try{
+					if(!this.grid.edit.isEditing()){
+						dojox.grid.util.fire(n, "focus");
+						if(sl){ this.cell.view.scrollboxNode.scrollLeft = sl; }
+					}
+				}catch(e){}
+			}
+		}
+	},
+	_delayedCellFocus: function(){
+		if(this.isNavHeader()||!this.grid._focused){
+				return;
+		}
+		var n = this.cell && this.cell.getNode(this.rowIndex);
+		if(n){ 
+			try{
+				if(!this.grid.edit.isEditing()){
+					dojo.toggleClass(n, this.focusClass, true);
+					this.blurHeader();
+					dojox.grid.util.fire(n, "focus");
+				}
+			} 
+			catch(e){}
+		}
+	},
+	_delayedHeaderFocus: function(){
+		if(this.isNavHeader()){
+			this.focusHeader();
+			this.grid.domNode.focus();
+		}
+	},
+	_initColumnHeaders: function(){
+		var headers = this._findHeaderCells();
+		for(var i = 0; i < headers.length; i++){
+			this._connects.push(dojo.connect(headers[i], "onfocus", this, "doColHeaderFocus"));
+			this._connects.push(dojo.connect(headers[i], "onblur", this, "doColHeaderBlur"));
+		}
+	},
+	_findHeaderCells: function(){
+		// This should be a one liner:
+		//	dojo.query("th[tabindex=-1]", this.grid.viewsHeaderNode);
+		// But there is a bug in dojo.query() for IE -- see trac #7037.
+		var allHeads = dojo.query("th", this.grid.viewsHeaderNode);
+		var headers = [];
+		for (var i = 0; i < allHeads.length; i++){
+			var aHead = allHeads[i];
+			var hasTabIdx = dojo.hasAttr(aHead, "tabIndex");
+			var tabindex = dojo.attr(aHead, "tabIndex");
+			if (hasTabIdx && tabindex < 0) {
+				headers.push(aHead);
+			}
+		}
+		return headers;
+	},
+	_setActiveColHeader: function(/*Node*/colHeaderNode, /*Integer*/colFocusIdx, /*Integer*/ prevColFocusIdx){
+		//console.log("setActiveColHeader() - colHeaderNode:colFocusIdx:prevColFocusIdx = " + colHeaderNode + ":" + colFocusIdx + ":" + prevColFocusIdx);
+		dojo.attr(this.grid.domNode, "aria-activedescendant",colHeaderNode.id);
+		if (prevColFocusIdx != null && prevColFocusIdx >= 0 && prevColFocusIdx != colFocusIdx){
+			dojo.toggleClass(this._findHeaderCells()[prevColFocusIdx],this.focusClass,false);
+		}
+		dojo.toggleClass(colHeaderNode,this.focusClass, true);
+		this._colHeadNode = colHeaderNode;
+		this._colHeadFocusIdx = colFocusIdx;
+		this._scrollHeader(this._colHeadFocusIdx);
+	},
+	scrollIntoView: function(){
+		var info = (this.cell ? this._scrollInfo(this.cell) : null);
+		if(!info || !info.s){
+			return null;
+		}
+		var rt = this.grid.scroller.findScrollTop(this.rowIndex);
+		// place cell within horizontal view
+		if(info.n && info.sr){
+			if(info.n.offsetLeft + info.n.offsetWidth > info.sr.l + info.sr.w){
+				info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
+			}else if(info.n.offsetLeft < info.sr.l){
+				info.s.scrollLeft = info.n.offsetLeft;
+			}
+		}
+		// place cell within vertical view
+		if(info.r && info.sr){
+			if(rt + info.r.offsetHeight > info.sr.t + info.sr.h){
+				this.grid.setScrollTop(rt + info.r.offsetHeight - info.sr.h);
+			}else if(rt < info.sr.t){
+				this.grid.setScrollTop(rt);
+			}
+		}
+
+		return info.s.scrollLeft;
+	},
+	_scrollInfo: function(cell, domNode){
+		if(cell){
+			var cl = cell,
+				sbn = cl.view.scrollboxNode,
+				sbnr = {
+					w: sbn.clientWidth,
+					l: sbn.scrollLeft,
+					t: sbn.scrollTop,
+					h: sbn.clientHeight
+				},
+				rn = cl.view.getRowNode(this.rowIndex);
+			return {
+				c: cl,
+				s: sbn,
+				sr: sbnr,
+				n: (domNode ? domNode : cell.getNode(this.rowIndex)),
+				r: rn
+			};
+		}
+		return null;
+	},
+	_scrollHeader: function(currentIdx){
+		var info = null;
+		if(this._colHeadNode){
+			var cell = this.grid.getCell(currentIdx);
+			info = this._scrollInfo(cell, cell.getNode(0));
+		}
+		if(info && info.s && info.sr && info.n){
+			// scroll horizontally as needed.
+			var scroll = info.sr.l + info.sr.w;
+			if(info.n.offsetLeft + info.n.offsetWidth > scroll){
+				info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
+			}else if(info.n.offsetLeft < info.sr.l){
+				info.s.scrollLeft = info.n.offsetLeft;
+			}else if(dojo.isIE <= 7 && cell && cell.view.headerNode){
+				// Trac 7158: scroll dojoxGridHeader for IE7 and lower
+				cell.view.headerNode.scrollLeft = info.s.scrollLeft;
+			}
+		}
+	},
+	_isHeaderHidden: function(){
+		// summary:
+		//		determine if the grid headers are hidden
+		//		relies on documented technique of setting .dojoxGridHeader { display:none; } 
+		// returns: Boolean
+		//		true if headers are hidden
+		//		false if headers are not hidden
+		
+		var curView = this.focusView;
+		if (!curView){
+			// find one so we can determine if headers are hidden
+			// there is no focusView after adding items to empty grid (test_data_grid_empty.html)
+			for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
+				if(cView.headerNode ){
+					curView=cView;
+					break;		
+				}	
+			}
+		}
+		return (curView && dojo.getComputedStyle(curView.headerNode).display == "none");
+	},
+	colSizeAdjust: function (e, colIdx, delta){ // adjust the column specified by colIdx by the specified delta px
+		var headers = this._findHeaderCells();
+		var view = this.focusView;
+		if (!view) {
+			for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
+				// find first view with a tableMap in order to work with empty grid
+				if(cView.header.tableMap.map ){
+					view=cView;
+					break;		
+				}
+			}
+		}
+		var curHeader = headers[colIdx];
+		if (!view || (colIdx == headers.length-1 && colIdx === 0)){
+			return; // can't adjust single col. grid
+		}	
+		view.content.baseDecorateEvent(e);
+		// need to adjust event with header cell info since focus is no longer on header cell
+		e.cellNode = curHeader; //this.findCellTarget(e.target, e.rowNode);
+		e.cellIndex = view.content.getCellNodeIndex(e.cellNode);
+		e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
+		if (view.header.canResize(e)){ 
+			var deltaObj = {
+				l: delta
+			};
+			var drag = view.header.colResizeSetup(e,false);
+			view.header.doResizeColumn(drag, null, deltaObj);
+			view.update();
+		}
+	},
+	styleRow: function(inRow){
+		return;
+	},
+	setFocusIndex: function(inRowIndex, inCellIndex){
+		// summary:
+		//	focuses the given grid cell
+		// inRowIndex: int
+		//	grid row index
+		// inCellIndex: int
+		//	grid cell index
+		this.setFocusCell(this.grid.getCell(inCellIndex), inRowIndex);
+	},
+	setFocusCell: function(inCell, inRowIndex){
+		// summary:
+		//	focuses the given grid cell
+		// inCell: object
+		//	grid cell object
+		// inRowIndex: int
+		//	grid row index
+		if(inCell && !this.isFocusCell(inCell, inRowIndex)){
+			this.tabbingOut = false;
+			if (this._colHeadNode){
+				this.blurHeader();
+			}
+			this._colHeadNode = this._colHeadFocusIdx = null;
+			this.focusGridView();
+			this._focusifyCellNode(false);
+			this.cell = inCell;
+			this.rowIndex = inRowIndex;
+			this._focusifyCellNode(true);
+		}
+		// even if this cell isFocusCell, the document focus may need to be rejiggered
+		// call opera on delay to prevent keypress from altering focus
+		if(dojo.isOpera){
+			setTimeout(dojo.hitch(this.grid, 'onCellFocus', this.cell, this.rowIndex), 1);
+		}else{
+			this.grid.onCellFocus(this.cell, this.rowIndex);
+		}
+	},
+	next: function(){
+		// summary:
+		//	focus next grid cell
+		if(this.cell){
+			var row=this.rowIndex, col=this.cell.index+1, cc=this.grid.layout.cellCount-1, rc=this.grid.rowCount-1;
+			if(col > cc){
+				col = 0;
+				row++;
+			}
+			if(row > rc){
+				col = cc;
+				row = rc;
+			}
+			if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
+				var nextCell = this.grid.getCell(col);
+				if (!this.isLastFocusCell() && !nextCell.editable){
+					this.cell=nextCell;
+					this.rowIndex=row;
+					this.next();
+					return;
+				}
+			}
+			this.setFocusIndex(row, col);
+		}
+	},
+	previous: function(){
+		// summary:
+		//	focus previous grid cell
+		if(this.cell){
+			var row=(this.rowIndex || 0), col=(this.cell.index || 0) - 1;
+			if(col < 0){
+				col = this.grid.layout.cellCount-1;
+				row--;
+			}
+			if(row < 0){
+				row = 0;
+				col = 0;
+			}
+			if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
+				var prevCell = this.grid.getCell(col);
+				if (!this.isFirstFocusCell() && !prevCell.editable){
+					this.cell=prevCell;
+					this.rowIndex=row;
+					this.previous();
+					return;
+				}
+			}
+			this.setFocusIndex(row, col);
+		}
+	},
+	move: function(inRowDelta, inColDelta) {
+		// summary:
+		//	focus grid cell or  simulate focus to column header based on position relative to current focus
+		// inRowDelta: int
+		// vertical distance from current focus
+		// inColDelta: int
+		// horizontal distance from current focus
+
+		var colDir = inColDelta < 0 ? -1 : 1;
+		// Handle column headers.
+		if(this.isNavHeader()){
+			var headers = this._findHeaderCells();
+			var savedIdx = currentIdx = dojo.indexOf(headers, this._colHeadNode);
+			currentIdx += inColDelta;
+			while(currentIdx >=0 && currentIdx < headers.length && headers[currentIdx].style.display == "none"){
+				// skip over hidden column headers
+				currentIdx += colDir;
+			}
+			if((currentIdx >= 0) && (currentIdx < headers.length)){
+				this._setActiveColHeader(headers[currentIdx],currentIdx, savedIdx);
+			}
+		}else{
+			if(this.cell){
+				// Handle grid proper.
+				var sc = this.grid.scroller,
+					r = this.rowIndex,
+					rc = this.grid.rowCount-1,
+					row = Math.min(rc, Math.max(0, r+inRowDelta));
+				if(inRowDelta){
+					if(inRowDelta>0){
+						if(row > sc.getLastPageRow(sc.page)){
+							//need to load additional data, let scroller do that
+							this.grid.setScrollTop(this.grid.scrollTop+sc.findScrollTop(row)-sc.findScrollTop(r));
+						}
+					}else if(inRowDelta<0){
+						if(row <= sc.getPageRow(sc.page)){
+							//need to load additional data, let scroller do that
+							this.grid.setScrollTop(this.grid.scrollTop-sc.findScrollTop(r)-sc.findScrollTop(row));
+						}
+					}
+				}
+				var cc = this.grid.layout.cellCount-1,
+				i = this.cell.index,
+				col = Math.min(cc, Math.max(0, i+inColDelta));
+				var cell = this.grid.getCell(col);
+				while(col>=0 && col < cc && cell && cell.hidden === true){
+					// skip hidden cells
+					col += colDir;
+					cell = this.grid.getCell(col);
+				}
+				if (!cell || cell.hidden === true){
+					// don't change col if would move to hidden
+					col = i;
+				}
+				this.setFocusIndex(row, col);
+				if(inRowDelta){
+					this.grid.updateRow(r);
+				}
+			}
+		}
+	},
+	previousKey: function(e){
+		if(this.grid.edit.isEditing()){
+			dojo.stopEvent(e);
+			this.previous();
+		}else if(!this.isNavHeader() && !this._isHeaderHidden()) {
+			this.grid.domNode.focus(); // will call doFocus and set focus into header.
+			dojo.stopEvent(e);
+		}else{
+			this.tabOut(this.grid.domNode);
+			if (this._colHeadFocusIdx != null) { // clear grid header focus
+				dojo.toggleClass(this._findHeaderCells()[this._colHeadFocusIdx], this.focusClass, false);
+				this._colHeadFocusIdx = null;
+			}
+			this._focusifyCellNode(false);
+		}
+	},
+	nextKey: function(e) {
+		var isEmpty = (this.grid.rowCount === 0);
+		if(e.target === this.grid.domNode && this._colHeadFocusIdx == null){
+			this.focusHeader();
+			dojo.stopEvent(e);
+		}else if(this.isNavHeader()){
+			// if tabbing from col header, then go to grid proper. 
+			this.blurHeader();
+			if(!this.findAndFocusGridCell()){
+				this.tabOut(this.grid.lastFocusNode);
+			}
+			this._colHeadNode = this._colHeadFocusIdx= null;
+		}else if(this.grid.edit.isEditing()){
+			dojo.stopEvent(e);
+			this.next();
+		}else{
+			this.tabOut(this.grid.lastFocusNode);
+		}
+	},
+	tabOut: function(inFocusNode){
+		this.tabbingOut = true;
+		inFocusNode.focus();
+	},
+	focusGridView: function(){
+		dojox.grid.util.fire(this.focusView, "focus");
+	},
+	focusGrid: function(inSkipFocusCell){
+		this.focusGridView();
+		this._focusifyCellNode(true);
+	},
+	findAndFocusGridCell: function(){
+		// summary:
+		//		find the first focusable grid cell 
+		// returns: Boolean
+		//		true if focus was set to a cell
+		//		false if no cell found to set focus onto
+		
+		var didFocus = true;
+		var isEmpty = (this.grid.rowCount === 0); // If grid is empty this.grid.rowCount == 0
+		if (this.isNoFocusCell() && !isEmpty){
+			var cellIdx = 0;
+			var cell = this.grid.getCell(cellIdx);
+			if (cell.hidden) {
+				// if first cell isn't visible, use _colHeadFocusIdx 
+				// could also use a while loop to find first visible cell - not sure that is worth it
+				cellIdx = this.isNavHeader() ? this._colHeadFocusIdx : 0;
+			}
+			this.setFocusIndex(0, cellIdx);
+		}
+		else if (this.cell && !isEmpty){
+			if (this.focusView && !this.focusView.rowNodes[this.rowIndex]){
+				// if rowNode for current index is undefined (likely as a result of a sort and because of #7304) 
+				// scroll to that row
+				this.grid.scrollToRow(this.rowIndex);
+			}
+			this.focusGrid();
+		}else {
+			didFocus = false;
+		}
+		this._colHeadNode = this._colHeadFocusIdx= null;
+		return didFocus;
+	},
+	focusHeader: function(){
+		var headerNodes = this._findHeaderCells();
+		var saveColHeadFocusIdx = this._colHeadFocusIdx;
+		if (this._isHeaderHidden()){
+			// grid header is hidden, focus a cell
+			this.findAndFocusGridCell();
+		}
+		else if (!this._colHeadFocusIdx) {
+			if (this.isNoFocusCell()) {
+				this._colHeadFocusIdx = 0;
+			}
+			else {
+				this._colHeadFocusIdx = this.cell.index;
+			}
+		}
+		this._colHeadNode = headerNodes[this._colHeadFocusIdx];
+		while(this._colHeadNode && this._colHeadFocusIdx >=0 && this._colHeadFocusIdx < headerNodes.length &&
+				this._colHeadNode.style.display == "none"){
+			// skip over hidden column headers
+			this._colHeadFocusIdx++;
+			this._colHeadNode = headerNodes[this._colHeadFocusIdx];
+		}
+		if(this._colHeadNode && this._colHeadNode.style.display != "none"){
+			// Column header cells know longer receive actual focus.  So, for keyboard invocation of
+			// contextMenu to work, the contextMenu must be bound to the grid.domNode rather than the viewsHeaderNode.
+			// unbind the contextmenu from the viewsHeaderNode and to the grid when header cells are active.  Reset
+			// the binding back to the viewsHeaderNode when header cells are no longer acive (in blurHeader) #10483
+			if (this.headerMenu && this._contextMenuBindNode != this.grid.domNode){
+				this.headerMenu.unBindDomNode(this.grid.viewsHeaderNode);
+				this.headerMenu.bindDomNode(this.grid.domNode);
+				this._contextMenuBindNode = this.grid.domNode;
+			}
+			this._setActiveColHeader(this._colHeadNode, this._colHeadFocusIdx, saveColHeadFocusIdx);
+			this._scrollHeader(this._colHeadFocusIdx);
+			this._focusifyCellNode(false);
+		}else {
+			// all col head nodes are hidden - focus the grid
+			this.findAndFocusGridCell();
+		}
+	},
+	blurHeader: function(){
+		dojo.removeClass(this._colHeadNode, this.focusClass);
+		dojo.removeAttr(this.grid.domNode,"aria-activedescendant");
+		// reset contextMenu onto viewsHeaderNode so right mouse on header will invoke (see focusHeader)
+		if (this.headerMenu && this._contextMenuBindNode == this.grid.domNode) {
+			var viewsHeader = this.grid.viewsHeaderNode;
+			this.headerMenu.unBindDomNode(this.grid.domNode);
+			this.headerMenu.bindDomNode(viewsHeader);
+			this._contextMenuBindNode = viewsHeader;
+		}
+	},
+	doFocus: function(e){
+		// trap focus only for grid dom node
+		if(e && e.target != e.currentTarget){
+			dojo.stopEvent(e);
+			return;
+		}
+		// do not focus for scrolling if grid is about to blur
+		if(!this.tabbingOut){
+			this.focusHeader();
+		}
+		this.tabbingOut = false;
+		dojo.stopEvent(e);
+	},
+	doBlur: function(e){
+		dojo.stopEvent(e);	// FF2
+	},
+	doContextMenu: function(e){
+	//stop contextMenu event if no header Menu to prevent default/browser contextMenu
+		if (!this.headerMenu){
+			dojo.stopEvent(e); 
+		}
+	},
+	doLastNodeFocus: function(e){
+		if (this.tabbingOut){
+			this._focusifyCellNode(false);
+		}else if(this.grid.rowCount >0){
+			if (this.isNoFocusCell()){
+				this.setFocusIndex(0,0);
+			}
+			this._focusifyCellNode(true);
+		}else {
+			this.focusHeader();
+		}
+		this.tabbingOut = false;
+		dojo.stopEvent(e);	 // FF2
+	},
+	doLastNodeBlur: function(e){
+		dojo.stopEvent(e);	 // FF2
+	},
+	doColHeaderFocus: function(e){
+		this._setActiveColHeader(e.target,dojo.attr(e.target, "idx"),this._colHeadFocusIdx);
+		this._scrollHeader(this.getHeaderIndex());
+		dojo.stopEvent(e);
+	},
+	doColHeaderBlur: function(e){
+		dojo.toggleClass(e.target, this.focusClass, false);
+	}		
+});
diff --git a/dojox/grid/_Grid.js b/dojox/grid/_Grid.js
index ba7cd93..ef3d9d6 100644
--- a/dojox/grid/_Grid.js
+++ b/dojox/grid/_Grid.js
@@ -1,15 +1,8 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._Grid"]){
-dojo._hasResource["dojox.grid._Grid"]=true;
 dojo.provide("dojox.grid._Grid");
+
 dojo.require("dijit.dijit");
 dojo.require("dijit.Menu");
+
 dojo.require("dojox.html.metrics");
 dojo.require("dojox.grid.util");
 dojo.require("dojox.grid._Scroller");
@@ -22,706 +15,1357 @@ dojo.require("dojox.grid._EditManager");
 dojo.require("dojox.grid.Selection");
 dojo.require("dojox.grid._RowSelector");
 dojo.require("dojox.grid._Events");
-dojo.requireLocalization("dijit","loading",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
+
+
+dojo.requireLocalization("dijit", "loading");
+
 (function(){
-if(!dojo.isCopyKey){
-dojo.isCopyKey=dojo.dnd.getCopyKeyState;
-}
-dojo.declare("dojox.grid._Grid",[dijit._Widget,dijit._Templated,dojox.grid._Events],{templateString:"<div class=\"dojoxGrid\" hidefocus=\"hidefocus\" wairole=\"grid\" dojoAttachEvent=\"onmouseout:_mouseOut\">\n\t<div class=\"dojoxGridMasterHeader\" dojoAttachPoint=\"viewsHeaderNode\" wairole=\"presentation\"></div>\n\t<div class=\"dojoxGridMasterView\" dojoAttachPoint=\"viewsNode\" wairole=\"presentation\"></div>\n\t<div class=\"dojoxGridMasterMessages\" style=\"display: none;\" dojoAtta [...]
-},rowCount:5,keepRows:75,rowsPerPage:25,autoWidth:false,initialWidth:"",autoHeight:"",rowHeight:0,autoRender:true,defaultHeight:"15em",height:"",structure:null,elasticView:-1,singleClickEdit:false,selectionMode:"extended",rowSelector:"",columnReordering:false,headerMenu:null,placeholderLabel:"GridColumns",selectable:false,_click:null,loadingMessage:"<span class='dojoxGridLoading'>${loadingState}</span>",errorMessage:"<span class='dojoxGridError'>${errorState}</span>",noDataMessage:"",esc [...]
-this.inherited(arguments);
-if(this.get==dojox.grid._Grid.prototype.get){
-this.get=null;
-}
-if(!this.domNode.getAttribute("tabIndex")){
-this.domNode.tabIndex="0";
-}
-this.createScroller();
-this.createLayout();
-this.createViews();
-this.createManagers();
-this.createSelection();
-this.connect(this.selection,"onSelected","onSelected");
-this.connect(this.selection,"onDeselected","onDeselected");
-this.connect(this.selection,"onChanged","onSelectionChanged");
-dojox.html.metrics.initOnFontResize();
-this.connect(dojox.html.metrics,"onFontResize","textSizeChanged");
-dojox.grid.util.funnelEvents(this.domNode,this,"doKeyEvent",dojox.grid.util.keyEvents);
-if(this.selectionMode!="none"){
-dojo.attr(this.domNode,"aria-multiselectable",this.selectionMode=="single"?"false":"true");
-}
-},postMixInProperties:function(){
-this.inherited(arguments);
-var _2=dojo.i18n.getLocalization("dijit","loading",this.lang);
-this.loadingMessage=dojo.string.substitute(this.loadingMessage,_2);
-this.errorMessage=dojo.string.substitute(this.errorMessage,_2);
-if(this.srcNodeRef&&this.srcNodeRef.style.height){
-this.height=this.srcNodeRef.style.height;
-}
-this._setAutoHeightAttr(this.autoHeight,true);
-this.lastScrollTop=this.scrollTop=0;
-},postCreate:function(){
-this._placeholders=[];
-this._setHeaderMenuAttr(this.headerMenu);
-this._setStructureAttr(this.structure);
-this._click=[];
-this.inherited(arguments);
-if(this.domNode&&this.autoWidth&&this.initialWidth){
-this.domNode.style.width=this.initialWidth;
-}
-if(this.domNode&&!this.editable){
-dojo.attr(this.domNode,"aria-readonly","true");
-}
-},destroy:function(){
-this.domNode.onReveal=null;
-this.domNode.onSizeChange=null;
-delete this._click;
-this.edit.destroy();
-delete this.edit;
-this.views.destroyViews();
-if(this.scroller){
-this.scroller.destroy();
-delete this.scroller;
-}
-if(this.focus){
-this.focus.destroy();
-delete this.focus;
-}
-if(this.headerMenu&&this._placeholders.length){
-dojo.forEach(this._placeholders,function(p){
-p.unReplace(true);
-});
-this.headerMenu.unBindDomNode(this.viewsHeaderNode);
-}
-this.inherited(arguments);
-},_setAutoHeightAttr:function(ah,_3){
-if(typeof ah=="string"){
-if(!ah||ah=="false"){
-ah=false;
-}else{
-if(ah=="true"){
-ah=true;
-}else{
-ah=window.parseInt(ah,10);
-}
-}
-}
-if(typeof ah=="number"){
-if(isNaN(ah)){
-ah=false;
-}
-if(ah<0){
-ah=true;
-}else{
-if(ah===0){
-ah=false;
-}
-}
-}
-this.autoHeight=ah;
-if(typeof ah=="boolean"){
-this._autoHeight=ah;
-}else{
-if(typeof ah=="number"){
-this._autoHeight=(ah>=this.attr("rowCount"));
-}else{
-this._autoHeight=false;
-}
-}
-if(this._started&&!_3){
-this.render();
-}
-},_getRowCountAttr:function(){
-return this.updating&&this.invalidated&&this.invalidated.rowCount!=undefined?this.invalidated.rowCount:this.rowCount;
-},textSizeChanged:function(){
-this.render();
-},sizeChange:function(){
-this.update();
-},createManagers:function(){
-this.rows=new dojox.grid._RowManager(this);
-this.focus=new dojox.grid._FocusManager(this);
-this.edit=new dojox.grid._EditManager(this);
-},createSelection:function(){
-this.selection=new dojox.grid.Selection(this);
-},createScroller:function(){
-this.scroller=new dojox.grid._Scroller();
-this.scroller.grid=this;
-this.scroller.renderRow=dojo.hitch(this,"renderRow");
-this.scroller.removeRow=dojo.hitch(this,"rowRemoved");
-},createLayout:function(){
-this.layout=new this._layoutClass(this);
-this.connect(this.layout,"moveColumn","onMoveColumn");
-},onMoveColumn:function(){
-this.render();
-},onResizeColumn:function(_4){
-},createViews:function(){
-this.views=new dojox.grid._ViewManager(this);
-this.views.createView=dojo.hitch(this,"createView");
-},createView:function(_5,_6){
-var c=dojo.getObject(_5);
-var _7=new c({grid:this,index:_6});
-this.viewsNode.appendChild(_7.domNode);
-this.viewsHeaderNode.appendChild(_7.headerNode);
-this.views.addView(_7);
-return _7;
-},buildViews:function(){
-for(var i=0,vs;(vs=this.layout.structure[i]);i++){
-this.createView(vs.type||dojox._scopeName+".grid._View",i).setStructure(vs);
-}
-this.scroller.setContentNodes(this.views.getContentNodes());
-},_setStructureAttr:function(_8){
-var s=_8;
-if(s&&dojo.isString(s)){
-dojo.deprecated("dojox.grid._Grid.attr('structure', 'objVar')","use dojox.grid._Grid.attr('structure', objVar) instead","2.0");
-s=dojo.getObject(s);
-}
-this.structure=s;
-if(!s){
-if(this.layout.structure){
-s=this.layout.structure;
-}else{
-return;
-}
-}
-this.views.destroyViews();
-if(s!==this.layout.structure){
-this.layout.setStructure(s);
-}
-this._structureChanged();
-},setStructure:function(_9){
-dojo.deprecated("dojox.grid._Grid.setStructure(obj)","use dojox.grid._Grid.attr('structure', obj) instead.","2.0");
-this._setStructureAttr(_9);
-},getColumnTogglingItems:function(){
-return dojo.map(this.layout.cells,function(_a){
-if(!_a.menuItems){
-_a.menuItems=[];
-}
-var _b=this;
-var _c=new dijit.CheckedMenuItem({label:_a.name,checked:!_a.hidden,_gridCell:_a,onChange:function(_d){
-if(_b.layout.setColumnVisibility(this._gridCell.index,_d)){
-var _e=this._gridCell.menuItems;
-if(_e.length>1){
-dojo.forEach(_e,function(_f){
-if(_f!==this){
-_f.setAttribute("checked",_d);
-}
-},this);
-}
-_d=dojo.filter(_b.layout.cells,function(c){
-if(c.menuItems.length>1){
-dojo.forEach(c.menuItems,"item.attr('disabled', false);");
-}else{
-c.menuItems[0].attr("disabled",false);
-}
-return !c.hidden;
-});
-if(_d.length==1){
-dojo.forEach(_d[0].menuItems,"item.attr('disabled', true);");
-}
-}
-},destroy:function(){
-var _10=dojo.indexOf(this._gridCell.menuItems,this);
-this._gridCell.menuItems.splice(_10,1);
-delete this._gridCell;
-dijit.CheckedMenuItem.prototype.destroy.apply(this,arguments);
-}});
-_a.menuItems.push(_c);
-return _c;
-},this);
-},_setHeaderMenuAttr:function(_11){
-if(this._placeholders&&this._placeholders.length){
-dojo.forEach(this._placeholders,function(p){
-p.unReplace(true);
-});
-this._placeholders=[];
-}
-if(this.headerMenu){
-this.headerMenu.unBindDomNode(this.viewsHeaderNode);
-}
-this.headerMenu=_11;
-if(!_11){
-return;
-}
-this.headerMenu.bindDomNode(this.viewsHeaderNode);
-if(this.headerMenu.getPlaceholders){
-this._placeholders=this.headerMenu.getPlaceholders(this.placeholderLabel);
-}
-},setHeaderMenu:function(_12){
-dojo.deprecated("dojox.grid._Grid.setHeaderMenu(obj)","use dojox.grid._Grid.attr('headerMenu', obj) instead.","2.0");
-this._setHeaderMenuAttr(_12);
-},setupHeaderMenu:function(){
-if(this._placeholders&&this._placeholders.length){
-dojo.forEach(this._placeholders,function(p){
-if(p._replaced){
-p.unReplace(true);
-}
-p.replace(this.getColumnTogglingItems());
-},this);
-}
-},_fetch:function(_13){
-this.setScrollTop(0);
-},getItem:function(_14){
-return null;
-},showMessage:function(_15){
-if(_15){
-this.messagesNode.innerHTML=_15;
-this.messagesNode.style.display="";
-}else{
-this.messagesNode.innerHTML="";
-this.messagesNode.style.display="none";
-}
-},_structureChanged:function(){
-this.buildViews();
-if(this.autoRender&&this._started){
-this.render();
-}
-},hasLayout:function(){
-return this.layout.cells.length;
-},resize:function(_16,_17){
-this._pendingChangeSize=_16;
-this._pendingResultSize=_17;
-this.sizeChange();
-},_getPadBorder:function(){
-this._padBorder=this._padBorder||dojo._getPadBorderExtents(this.domNode);
-return this._padBorder;
-},_getHeaderHeight:function(){
-var vns=this.viewsHeaderNode.style,t=vns.display=="none"?0:this.views.measureHeader();
-vns.height=t+"px";
-this.views.normalizeHeaderNodeHeight();
-return t;
-},_resize:function(_18,_19){
-_18=_18||this._pendingChangeSize;
-_19=_19||this._pendingResultSize;
-delete this._pendingChangeSize;
-delete this._pendingResultSize;
-if(!this.domNode){
-return;
-}
-var pn=this.domNode.parentNode;
-if(!pn||pn.nodeType!=1||!this.hasLayout()||pn.style.visibility=="hidden"||pn.style.display=="none"){
-return;
-}
-var _1a=this._getPadBorder();
-var hh=undefined;
-var h;
-if(this._autoHeight){
-this.domNode.style.height="auto";
-this.viewsNode.style.height="";
-}else{
-if(typeof this.autoHeight=="number"){
-h=hh=this._getHeaderHeight();
-h+=(this.scroller.averageRowHeight*this.autoHeight);
-this.domNode.style.height=h+"px";
-}else{
-if(this.domNode.clientHeight<=_1a.h){
-if(pn==document.body){
-this.domNode.style.height=this.defaultHeight;
-}else{
-if(this.height){
-this.domNode.style.height=this.height;
-}else{
-this.fitTo="parent";
-}
-}
-}
-}
-}
-if(_19){
-_18=_19;
-}
-if(_18){
-dojo.marginBox(this.domNode,_18);
-this.height=this.domNode.style.height;
-delete this.fitTo;
-}else{
-if(this.fitTo=="parent"){
-h=this._parentContentBoxHeight=this._parentContentBoxHeight||dojo._getContentBox(pn).h;
-this.domNode.style.height=Math.max(0,h)+"px";
-}
-}
-var _1b=dojo.some(this.views.views,function(v){
-return v.flexCells;
-});
-if(!this._autoHeight&&(h||dojo._getContentBox(this.domNode).h)===0){
-this.viewsHeaderNode.style.display="none";
-}else{
-this.viewsHeaderNode.style.display="block";
-if(!_1b&&hh===undefined){
-hh=this._getHeaderHeight();
-}
-}
-if(_1b){
-hh=undefined;
-}
-this.adaptWidth();
-this.adaptHeight(hh);
-this.postresize();
-},adaptWidth:function(){
-var _1c=(!this.initialWidth&&this.autoWidth);
-var w=_1c?0:this.domNode.clientWidth||(this.domNode.offsetWidth-this._getPadBorder().w),vw=this.views.arrange(1,w);
-this.views.onEach("adaptWidth");
-if(_1c){
-this.domNode.style.width=vw+"px";
-}
-},adaptHeight:function(_1d){
-var t=_1d===undefined?this._getHeaderHeight():_1d;
-var h=(this._autoHeight?-1:Math.max(this.domNode.clientHeight-t,0)||0);
-this.views.onEach("setSize",[0,h]);
-this.views.onEach("adaptHeight");
-if(!this._autoHeight){
-var _1e=0,_1f=0;
-var _20=dojo.filter(this.views.views,function(v){
-var has=v.hasHScrollbar();
-if(has){
-_1e++;
-}else{
-_1f++;
-}
-return (!has);
-});
-if(_1e>0&&_1f>0){
-dojo.forEach(_20,function(v){
-v.adaptHeight(true);
-});
-}
-}
-if(this.autoHeight===true||h!=-1||(typeof this.autoHeight=="number"&&this.autoHeight>=this.attr("rowCount"))){
-this.scroller.windowHeight=h;
-}else{
-this.scroller.windowHeight=Math.max(this.domNode.clientHeight-t,0);
-}
-},startup:function(){
-if(this._started){
-return;
-}
-this.inherited(arguments);
-if(this.autoRender){
-this.render();
-}
-},render:function(){
-if(!this.domNode){
-return;
-}
-if(!this._started){
-return;
-}
-if(!this.hasLayout()){
-this.scroller.init(0,this.keepRows,this.rowsPerPage);
-return;
-}
-this.update=this.defaultUpdate;
-this._render();
-},_render:function(){
-this.scroller.init(this.attr("rowCount"),this.keepRows,this.rowsPerPage);
-this.prerender();
-this.setScrollTop(0);
-this.postrender();
-},prerender:function(){
-this.keepRows=this._autoHeight?0:this.keepRows;
-this.scroller.setKeepInfo(this.keepRows);
-this.views.render();
-this._resize();
-},postrender:function(){
-this.postresize();
-this.focus.initFocusView();
-dojo.setSelectable(this.domNode,this.selectable);
-},postresize:function(){
-if(this._autoHeight){
-var _21=Math.max(this.views.measureContent())+"px";
-this.viewsNode.style.height=_21;
-}
-},renderRow:function(_22,_23){
-this.views.renderRow(_22,_23,this._skipRowRenormalize);
-},rowRemoved:function(_24){
-this.views.rowRemoved(_24);
-},invalidated:null,updating:false,beginUpdate:function(){
-this.invalidated=[];
-this.updating=true;
-},endUpdate:function(){
-this.updating=false;
-var i=this.invalidated,r;
-if(i.all){
-this.update();
-}else{
-if(i.rowCount!=undefined){
-this.updateRowCount(i.rowCount);
-}else{
-for(r in i){
-this.updateRow(Number(r));
-}
-}
-}
-this.invalidated=[];
-},defaultUpdate:function(){
-if(!this.domNode){
-return;
-}
-if(this.updating){
-this.invalidated.all=true;
-return;
-}
-this.lastScrollTop=this.scrollTop;
-this.prerender();
-this.scroller.invalidateNodes();
-this.setScrollTop(this.lastScrollTop);
-this.postrender();
-},update:function(){
-this.render();
-},updateRow:function(_25){
-_25=Number(_25);
-if(this.updating){
-this.invalidated[_25]=true;
-}else{
-this.views.updateRow(_25);
-this.scroller.rowHeightChanged(_25);
-}
-},updateRows:function(_26,_27){
-_26=Number(_26);
-_27=Number(_27);
-var i;
-if(this.updating){
-for(i=0;i<_27;i++){
-this.invalidated[i+_26]=true;
-}
-}else{
-for(i=0;i<_27;i++){
-this.views.updateRow(i+_26,this._skipRowRenormalize);
-}
-this.scroller.rowHeightChanged(_26);
-}
-},updateRowCount:function(_28){
-if(this.updating){
-this.invalidated.rowCount=_28;
-}else{
-this.rowCount=_28;
-this._setAutoHeightAttr(this.autoHeight,true);
-if(this.layout.cells.length){
-this.scroller.updateRowCount(_28);
-}
-this._resize();
-if(this.layout.cells.length){
-this.setScrollTop(this.scrollTop);
-}
-}
-},updateRowStyles:function(_29){
-this.views.updateRowStyles(_29);
-},getRowNode:function(_2a){
-if(this.focus.focusView&&!(this.focus.focusView instanceof dojox.grid._RowSelector)){
-return this.focus.focusView.rowNodes[_2a];
-}else{
-for(var i=0,_2b;(_2b=this.views.views[i]);i++){
-if(!(_2b instanceof dojox.grid._RowSelector)){
-return _2b.rowNodes[_2a];
-}
-}
-}
-return null;
-},rowHeightChanged:function(_2c){
-this.views.renormalizeRow(_2c);
-this.scroller.rowHeightChanged(_2c);
-},fastScroll:true,delayScroll:false,scrollRedrawThreshold:(dojo.isIE?100:50),scrollTo:function(_2d){
-if(!this.fastScroll){
-this.setScrollTop(_2d);
-return;
-}
-var _2e=Math.abs(this.lastScrollTop-_2d);
-this.lastScrollTop=_2d;
-if(_2e>this.scrollRedrawThreshold||this.delayScroll){
-this.delayScroll=true;
-this.scrollTop=_2d;
-this.views.setScrollTop(_2d);
-if(this._pendingScroll){
-window.clearTimeout(this._pendingScroll);
-}
-var _2f=this;
-this._pendingScroll=window.setTimeout(function(){
-delete _2f._pendingScroll;
-_2f.finishScrollJob();
-},200);
-}else{
-this.setScrollTop(_2d);
-}
-},finishScrollJob:function(){
-this.delayScroll=false;
-this.setScrollTop(this.scrollTop);
-},setScrollTop:function(_30){
-this.scroller.scroll(this.views.setScrollTop(_30));
-},scrollToRow:function(_31){
-this.setScrollTop(this.scroller.findScrollTop(_31)+1);
-},styleRowNode:function(_32,_33){
-if(_33){
-this.rows.styleRowNode(_32,_33);
-}
-},_mouseOut:function(e){
-this.rows.setOverRow(-2);
-},getCell:function(_34){
-return this.layout.cells[_34];
-},setCellWidth:function(_35,_36){
-this.getCell(_35).unitWidth=_36;
-},getCellName:function(_37){
-return "Cell "+_37.index;
-},canSort:function(_38){
-},sort:function(){
-},getSortAsc:function(_39){
-_39=_39==undefined?this.sortInfo:_39;
-return Boolean(_39>0);
-},getSortIndex:function(_3a){
-_3a=_3a==undefined?this.sortInfo:_3a;
-return Math.abs(_3a)-1;
-},setSortIndex:function(_3b,_3c){
-var si=_3b+1;
-if(_3c!=undefined){
-si*=(_3c?1:-1);
-}else{
-if(this.getSortIndex()==_3b){
-si=-this.sortInfo;
-}
-}
-this.setSortInfo(si);
-},setSortInfo:function(_3d){
-if(this.canSort(_3d)){
-this.sortInfo=_3d;
-this.sort();
-this.update();
-}
-},doKeyEvent:function(e){
-e.dispatch="do"+e.type;
-this.onKeyEvent(e);
-},_dispatch:function(m,e){
-if(m in this){
-return this[m](e);
-}
-return false;
-},dispatchKeyEvent:function(e){
-this._dispatch(e.dispatch,e);
-},dispatchContentEvent:function(e){
-this.edit.dispatchEvent(e)||e.sourceView.dispatchContentEvent(e)||this._dispatch(e.dispatch,e);
-},dispatchHeaderEvent:function(e){
-e.sourceView.dispatchHeaderEvent(e)||this._dispatch("doheader"+e.type,e);
-},dokeydown:function(e){
-this.onKeyDown(e);
-},doclick:function(e){
-if(e.cellNode){
-this.onCellClick(e);
-}else{
-this.onRowClick(e);
-}
-},dodblclick:function(e){
-if(e.cellNode){
-this.onCellDblClick(e);
-}else{
-this.onRowDblClick(e);
-}
-},docontextmenu:function(e){
-if(e.cellNode){
-this.onCellContextMenu(e);
-}else{
-this.onRowContextMenu(e);
-}
-},doheaderclick:function(e){
-if(e.cellNode){
-this.onHeaderCellClick(e);
-}else{
-this.onHeaderClick(e);
-}
-},doheaderdblclick:function(e){
-if(e.cellNode){
-this.onHeaderCellDblClick(e);
-}else{
-this.onHeaderDblClick(e);
-}
-},doheadercontextmenu:function(e){
-if(e.cellNode){
-this.onHeaderCellContextMenu(e);
-}else{
-this.onHeaderContextMenu(e);
-}
-},doStartEdit:function(_3e,_3f){
-this.onStartEdit(_3e,_3f);
-},doApplyCellEdit:function(_40,_41,_42){
-this.onApplyCellEdit(_40,_41,_42);
-},doCancelEdit:function(_43){
-this.onCancelEdit(_43);
-},doApplyEdit:function(_44){
-this.onApplyEdit(_44);
-},addRow:function(){
-this.updateRowCount(this.attr("rowCount")+1);
-},removeSelectedRows:function(){
-if(this.allItemsSelected){
-this.updateRowCount(0);
-}else{
-this.updateRowCount(Math.max(0,this.attr("rowCount")-this.selection.getSelected().length));
-}
-this.selection.clear();
-}});
-dojox.grid._Grid.markupFactory=function(_45,_46,_47,_48){
-var d=dojo;
-var _49=function(n){
-var w=d.attr(n,"width")||"auto";
-if((w!="auto")&&(w.slice(-2)!="em")&&(w.slice(-1)!="%")){
-w=parseInt(w,10)+"px";
-}
-return w;
-};
-if(!_45.structure&&_46.nodeName.toLowerCase()=="table"){
-_45.structure=d.query("> colgroup",_46).map(function(cg){
-var sv=d.attr(cg,"span");
-var v={noscroll:(d.attr(cg,"noscroll")=="true")?true:false,__span:(!!sv?parseInt(sv,10):1),cells:[]};
-if(d.hasAttr(cg,"width")){
-v.width=_49(cg);
-}
-return v;
-});
-if(!_45.structure.length){
-_45.structure.push({__span:Infinity,cells:[]});
-}
-d.query("thead > tr",_46).forEach(function(tr,_4a){
-var _4b=0;
-var _4c=0;
-var _4d;
-var _4e=null;
-d.query("> th",tr).map(function(th){
-if(!_4e){
-_4d=0;
-_4e=_45.structure[0];
-}else{
-if(_4b>=(_4d+_4e.__span)){
-_4c++;
-_4d+=_4e.__span;
-var _4f=_4e;
-_4e=_45.structure[_4c];
-}
-}
-var _50={name:d.trim(d.attr(th,"name")||th.innerHTML),colSpan:parseInt(d.attr(th,"colspan")||1,10),type:d.trim(d.attr(th,"cellType")||""),id:d.trim(d.attr(th,"id")||"")};
-_4b+=_50.colSpan;
-var _51=d.attr(th,"rowspan");
-if(_51){
-_50.rowSpan=_51;
-}
-if(d.hasAttr(th,"width")){
-_50.width=_49(th);
-}
-if(d.hasAttr(th,"relWidth")){
-_50.relWidth=window.parseInt(dojo.attr(th,"relWidth"),10);
-}
-if(d.hasAttr(th,"hidden")){
-_50.hidden=d.attr(th,"hidden")=="true";
-}
-if(_48){
-_48(th,_50);
-}
-_50.type=_50.type?dojo.getObject(_50.type):dojox.grid.cells.Cell;
-if(_50.type&&_50.type.markupFactory){
-_50.type.markupFactory(th,_50);
-}
-if(!_4e.cells[_4a]){
-_4e.cells[_4a]=[];
-}
-_4e.cells[_4a].push(_50);
-});
-});
-}
-return new _47(_45,_46);
-};
+	// NOTE: this is for backwards compatibility with Dojo 1.3
+	if(!dojo.isCopyKey){
+		dojo.isCopyKey = dojo.dnd.getCopyKeyState;
+	}
+	/*=====
+	dojox.grid.__CellDef = function(){
+		//	name: String?
+		//		The text to use in the header of the grid for this cell.
+		//	get: Function?
+		//		function(rowIndex){} rowIndex is of type Integer.  This
+		//		function will be called when a cell	requests data.  Returns the
+		//		unformatted data for the cell.
+		//	value: String?
+		//		If "get" is not specified, this is used as the data for the cell.
+		//	defaultValue: String?
+		//		If "get" and "value" aren't specified or if "get" returns an undefined
+		//		value, this is used as the data for the cell.  "formatter" is not run
+		//		on this if "get" returns an undefined value.
+		//	formatter: Function?
+		//		function(data, rowIndex){} data is of type anything, rowIndex
+		//		is of type Integer.  This function will be called after the cell
+		//		has its data but before it passes it back to the grid to render.
+		//		Returns the formatted version of the cell's data.
+		//	type: dojox.grid.cells._Base|Function?
+		//		TODO
+		//	editable: Boolean?
+		//		Whether this cell should be editable or not.
+		//	hidden: Boolean?
+		//		If true, the cell will not be displayed.
+		//	noresize: Boolean?
+		//		If true, the cell will not be able to be resized.
+		//	width: Integer|String?
+		//		A CSS size.  If it's an Integer, the width will be in em's.
+		//	colSpan: Integer?
+		//		How many columns to span this cell.  Will not work in the first
+		//		sub-row of cells.
+		//	rowSpan: Integer?
+		//		How many sub-rows to span this cell.
+		//	styles: String?
+		//		A string of styles to apply to both the header cell and main
+		//		grid cells.  Must end in a ';'.
+		//	headerStyles: String?
+		//		A string of styles to apply to just the header cell.  Must end
+		//		in a ';'
+		//	cellStyles: String?
+		//		A string of styles to apply to just the main grid cells.  Must
+		//		end in a ';'
+		//	classes: String?
+		//		A space separated list of classes to apply to both the header
+		//		cell and the main grid cells.
+		//	headerClasses: String?
+		//		A space separated list of classes to apply to just the header
+		//		cell.
+		//	cellClasses: String?
+		//		A space separated list of classes to apply to just the main
+		//		grid cells.
+		//	attrs: String?
+		//		A space separated string of attribute='value' pairs to add to
+		//		the header cell element and main grid cell elements.
+		this.name = name;
+		this.value = value;
+		this.get = get;
+		this.formatter = formatter;
+		this.type = type;
+		this.editable = editable;
+		this.hidden = hidden;
+		this.width = width;
+		this.colSpan = colSpan;
+		this.rowSpan = rowSpan;
+		this.styles = styles;
+		this.headerStyles = headerStyles;
+		this.cellStyles = cellStyles;
+		this.classes = classes;
+		this.headerClasses = headerClasses;
+		this.cellClasses = cellClasses;
+		this.attrs = attrs;
+	}
+	=====*/
+
+	/*=====
+	dojox.grid.__ViewDef = function(){
+		//	noscroll: Boolean?
+		//		If true, no scrollbars will be rendered without scrollbars.
+		//	width: Integer|String?
+		//		A CSS size.  If it's an Integer, the width will be in em's. If
+		//		"noscroll" is true, this value is ignored.
+		//	cells: dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]?
+		//		The structure of the cells within this grid.
+		//	type: String?
+		//		A string containing the constructor of a subclass of
+		//		dojox.grid._View.  If this is not specified, dojox.grid._View
+		//		is used.
+		//	defaultCell: dojox.grid.__CellDef?
+		//		A cell definition with default values for all cells in this view.  If
+		//		a property is defined in a cell definition in the "cells" array and
+		//		this property, the cell definition's property will override this
+		//		property's property.
+		//	onBeforeRow: Function?
+		//		function(rowIndex, cells){} rowIndex is of type Integer, cells
+		//		is of type Array[dojox.grid.__CellDef[]].  This function is called
+		//		before each row of data is rendered.  Before the header is
+		//		rendered, rowIndex will be -1.  "cells" is a reference to the
+		//		internal structure of this view's cells so any changes you make to
+		//		it will persist between calls.
+		//	onAfterRow: Function?
+		//		function(rowIndex, cells, rowNode){} rowIndex is of type Integer, cells
+		//		is of type Array[dojox.grid.__CellDef[]], rowNode is of type DOMNode.
+		//		This function is called	after each row of data is rendered.  After the
+		//		header is rendered, rowIndex will be -1.  "cells" is a reference to the
+		//		internal structure of this view's cells so any changes you make to
+		//		it will persist between calls.
+		this.noscroll = noscroll;
+		this.width = width;
+		this.cells = cells;
+		this.type = type;
+		this.defaultCell = defaultCell;
+		this.onBeforeRow = onBeforeRow;
+		this.onAfterRow = onAfterRow;
+	}
+	=====*/
+
+	dojo.declare('dojox.grid._Grid',
+		[ dijit._Widget, dijit._Templated, dojox.grid._Events ],
+		{
+		// summary:
+		// 		A grid widget with virtual scrolling, cell editing, complex rows,
+		// 		sorting, fixed columns, sizeable columns, etc.
+		//
+		//	description:
+		//		_Grid provides the full set of grid features without any
+		//		direct connection to a data store.
+		//
+		//		The grid exposes a get function for the grid, or optionally
+		//		individual columns, to populate cell contents.
+		//
+		//		The grid is rendered based on its structure, an object describing
+		//		column and cell layout.
+		//
+		//	example:
+		//		A quick sample:
+		//
+		//		define a get function
+		//	|	function get(inRowIndex){ // called in cell context
+		//	|		return [this.index, inRowIndex].join(', ');
+		//	|	}
+		//
+		//		define the grid structure:
+		//	|	var structure = [ // array of view objects
+		//	|		{ cells: [// array of rows, a row is an array of cells
+		//	|			[
+		//	|				{ name: "Alpha", width: 6 },
+		//	|				{ name: "Beta" },
+		//	|				{ name: "Gamma", get: get }]
+		//	|		]}
+		//	|	];
+		//
+		//	|	<div id="grid"
+		//	|		rowCount="100" get="get"
+		//	|		structure="structure"
+		//	|		dojoType="dojox.grid._Grid"></div>
+
+		templatePath: dojo.moduleUrl("dojox.grid","resources/_Grid.html"),
+
+		// classTag: String
+		// 		CSS class applied to the grid's domNode
+		classTag: 'dojoxGrid',
+
+		// settings
+		// rowCount: Integer
+		//		Number of rows to display.
+		rowCount: 5,
+
+		// keepRows: Integer
+		//		Number of rows to keep in the rendering cache.
+		keepRows: 75,
+
+		// rowsPerPage: Integer
+		//		Number of rows to render at a time.
+		rowsPerPage: 25,
+
+		// autoWidth: Boolean
+		//		If autoWidth is true, grid width is automatically set to fit the data.
+		autoWidth: false,
+		
+		// initialWidth: String
+		//		A css string to use to set our initial width (only used if autoWidth
+		//		is true).  The first rendering of the grid will be this width, any
+		//		resizing of columns, etc will result in the grid switching to 
+		//		autoWidth mode.  Note, this width will override any styling in a
+		//		stylesheet or directly on the node.
+		initialWidth: "",
+
+		// autoHeight: Boolean|Integer
+		//		If autoHeight is true, grid height is automatically set to fit the data.
+		//		If it is an integer, the height will be automatically set to fit the data
+		//		if there are fewer than that many rows - and the height will be set to show
+		//		that many rows if there are more
+		autoHeight: '',
+
+		// rowHeight: Integer
+		//		If rowHeight is set to a positive number, it will define the height of the rows
+		//		in pixels. This can provide a significant performance advantage, since it
+		//		eliminates the need to measure row sizes during rendering, which is one
+		// 		the primary bottlenecks in the DataGrid's performance. 
+		rowHeight: 0,
+		
+		// autoRender: Boolean
+		//		If autoRender is true, grid will render itself after initialization.
+		autoRender: true,
+
+		// defaultHeight: String
+		//		default height of the grid, measured in any valid css unit.
+		defaultHeight: '15em',
+		
+		// height: String
+		//		explicit height of the grid, measured in any valid css unit.  This will be populated (and overridden)
+		//		if the height: css attribute exists on the source node.
+		height: '',
+
+		// structure: dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]]
+		//		View layout defintion.
+		structure: null,
+
+		// elasticView: Integer
+		//	Override defaults and make the indexed grid view elastic, thus filling available horizontal space.
+		elasticView: -1,
+
+		// singleClickEdit: boolean
+		//		Single-click starts editing. Default is double-click
+		singleClickEdit: false,
+
+		// selectionMode: String
+		//		Set the selection mode of grid's Selection.  Value must be 'single', 'multiple',
+		//		or 'extended'.  Default is 'extended'.
+		selectionMode: 'extended',
+
+		// rowSelector: Boolean|String
+		// 		If set to true, will add a row selector view to this grid.  If set to a CSS width, will add
+		// 		a row selector of that width to this grid.
+		rowSelector: '',
+
+		// columnReordering: Boolean
+		// 		If set to true, will add drag and drop reordering to views with one row of columns.
+		columnReordering: false,
+
+		// headerMenu: dijit.Menu
+		// 		If set to a dijit.Menu, will use this as a context menu for the grid headers.
+		headerMenu: null,
+
+		// placeholderLabel: String
+		// 		Label of placeholders to search for in the header menu to replace with column toggling
+		// 		menu items.
+		placeholderLabel: "GridColumns",
+		
+		// selectable: Boolean
+		//		Set to true if you want to be able to select the text within the grid.
+		selectable: false,
+		
+		// Used to store the last two clicks, to ensure double-clicking occurs based on the intended row
+		_click: null,
+		
+		// loadingMessage: String
+		//  Message that shows while the grid is loading
+		loadingMessage: "<span class='dojoxGridLoading'>${loadingState}</span>",
+
+		// errorMessage: String
+		//  Message that shows when the grid encounters an error loading
+		errorMessage: "<span class='dojoxGridError'>${errorState}</span>",
+
+		// noDataMessage: String
+		//  Message that shows if the grid has no data - wrap it in a 
+		//  span with class 'dojoxGridNoData' if you want it to be
+		//  styled similar to the loading and error messages
+		noDataMessage: "",
+		
+		// escapeHTMLInData: Boolean
+		//		This will escape HTML brackets from the data to prevent HTML from 
+		// 		user-inputted data being rendered with may contain JavaScript and result in 
+		// 		XSS attacks. This is true by default, and it is recommended that it remain 
+		// 		true. Setting this to false will allow data to be displayed in the grid without 
+		// 		filtering, and should be only used if it is known that the data won't contain 
+		// 		malicious scripts. If HTML is needed in grid cells, it is recommended that 
+		// 		you use the formatter function to generate the HTML (the output of 
+		// 		formatter functions is not filtered, even with escapeHTMLInData set to true).
+		escapeHTMLInData: true,	
+		
+		// formatterScope: Object
+		//		An object to execute format functions within.  If not set, the
+		//		format functions will execute within the scope of the cell that
+		//		has a format function.
+		formatterScope: null,
+		
+		// editable: boolean
+		// indicates if the grid contains editable cells, default is false
+		// set to true if editable cell encountered during rendering 
+		editable: false,
+		
+		// private
+		sortInfo: 0,
+		themeable: true,
+		_placeholders: null,
+
+		// _layoutClass: Object
+		//	The class to use for our layout - can be overridden by grid subclasses
+		_layoutClass: dojox.grid._Layout,
+
+		// initialization
+		buildRendering: function(){
+			this.inherited(arguments);
+			if(!this.domNode.getAttribute('tabIndex')){
+				this.domNode.tabIndex = "0";
+			}
+			this.createScroller();
+			this.createLayout();
+			this.createViews();
+			this.createManagers();
+
+			this.createSelection();
+
+			this.connect(this.selection, "onSelected", "onSelected");
+			this.connect(this.selection, "onDeselected", "onDeselected");
+			this.connect(this.selection, "onChanged", "onSelectionChanged");
+
+			dojox.html.metrics.initOnFontResize();
+			this.connect(dojox.html.metrics, "onFontResize", "textSizeChanged");
+			dojox.grid.util.funnelEvents(this.domNode, this, 'doKeyEvent', dojox.grid.util.keyEvents);
+			if (this.selectionMode != "none") {
+				dojo.attr(this.domNode, "aria-multiselectable", this.selectionMode == "single" ? "false" : "true");
+			}
+
+			dojo.addClass(this.domNode, this.classTag);
+			if(!this.isLeftToRight()){
+				dojo.addClass(this.domNode, this.classTag+"Rtl");
+			}
+		},
+		
+		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);
+			if(this.srcNodeRef && this.srcNodeRef.style.height){
+				this.height = this.srcNodeRef.style.height;
+			}
+			// Call this to update our autoheight to start out
+			this._setAutoHeightAttr(this.autoHeight, true);
+			this.lastScrollTop = this.scrollTop = 0;
+		},
+		
+		postCreate: function(){
+			this._placeholders = [];
+			this._setHeaderMenuAttr(this.headerMenu);
+			this._setStructureAttr(this.structure);
+			this._click = [];
+			this.inherited(arguments);
+			if(this.domNode && this.autoWidth && this.initialWidth){
+				this.domNode.style.width = this.initialWidth;
+			}
+			if (this.domNode && !this.editable){
+				// default value for aria-readonly is false, set to true if grid is not editable
+				dojo.attr(this.domNode,"aria-readonly", "true");
+			}
+		},
+
+		destroy: function(){
+			this.domNode.onReveal = null;
+			this.domNode.onSizeChange = null;
+
+			// Fixes IE domNode leak
+			delete this._click;
+
+			this.edit.destroy();
+			delete this.edit;
+
+			this.views.destroyViews();
+			if(this.scroller){
+				this.scroller.destroy();
+				delete this.scroller;
+			}
+			if(this.focus){
+				this.focus.destroy();
+				delete this.focus;
+			}
+			if(this.headerMenu&&this._placeholders.length){
+				dojo.forEach(this._placeholders, function(p){ p.unReplace(true); });
+				this.headerMenu.unBindDomNode(this.viewsHeaderNode);
+			}
+			this.inherited(arguments);
+		},
+
+		_setAutoHeightAttr: function(ah, skipRender){
+			// Calculate our autoheight - turn it into a boolean or an integer
+			if(typeof ah == "string"){
+				if(!ah || ah == "false"){
+					ah = false;
+				}else if (ah == "true"){
+					ah = true;
+				}else{
+					ah = window.parseInt(ah, 10);
+				}
+			}
+			if(typeof ah == "number"){
+				if(isNaN(ah)){
+					ah = false;
+				}
+				// Autoheight must be at least 1, if it's a number.  If it's
+				// less than 0, we'll take that to mean "all" rows (same as 
+				// autoHeight=true - if it is equal to zero, we'll take that
+				// to mean autoHeight=false
+				if(ah < 0){
+					ah = true;
+				}else if (ah === 0){
+					ah = false;
+				}
+			}
+			this.autoHeight = ah;
+			if(typeof ah == "boolean"){
+				this._autoHeight = ah;
+			}else if(typeof ah == "number"){
+				this._autoHeight = (ah >= this.get('rowCount'));
+			}else{
+				this._autoHeight = false;
+			}
+			if(this._started && !skipRender){
+				this.render();
+			}
+		},
+
+		_getRowCountAttr: function(){
+			return this.updating && this.invalidated && this.invalidated.rowCount != undefined ?
+				this.invalidated.rowCount : this.rowCount;
+		},
+		
+		textSizeChanged: function(){
+			this.render();
+		},
+
+		sizeChange: function(){
+			this.update();
+		},
+
+		createManagers: function(){
+			// summary:
+			//		create grid managers for various tasks including rows, focus, selection, editing
+
+			// row manager
+			this.rows = new dojox.grid._RowManager(this);
+			// focus manager
+			this.focus = new dojox.grid._FocusManager(this);
+			// edit manager
+			this.edit = new dojox.grid._EditManager(this);
+		},
+
+		createSelection: function(){
+			// summary:	Creates a new Grid selection manager.
+
+			// selection manager
+			this.selection = new dojox.grid.Selection(this);
+		},
+
+		createScroller: function(){
+			// summary: Creates a new virtual scroller
+			this.scroller = new dojox.grid._Scroller();
+			this.scroller.grid = this;
+			this.scroller.renderRow = dojo.hitch(this, "renderRow");
+			this.scroller.removeRow = dojo.hitch(this, "rowRemoved");
+		},
+
+		createLayout: function(){
+			// summary: Creates a new Grid layout
+			this.layout = new this._layoutClass(this);
+			this.connect(this.layout, "moveColumn", "onMoveColumn");
+		},
+
+		onMoveColumn: function(){
+			this.render();
+		},
+		
+		onResizeColumn: function(/*int*/ cellIdx){
+			// Called when a column is resized.
+		},
+
+		// views
+		createViews: function(){
+			this.views = new dojox.grid._ViewManager(this);
+			this.views.createView = dojo.hitch(this, "createView");
+		},
+
+		createView: function(inClass, idx){
+			var c = dojo.getObject(inClass);
+			var view = new c({ grid: this, index: idx });
+			this.viewsNode.appendChild(view.domNode);
+			this.viewsHeaderNode.appendChild(view.headerNode);
+			this.views.addView(view);
+			return view;
+		},
+
+		buildViews: function(){
+			for(var i=0, vs; (vs=this.layout.structure[i]); i++){
+				this.createView(vs.type || dojox._scopeName + ".grid._View", i).setStructure(vs);
+			}
+			this.scroller.setContentNodes(this.views.getContentNodes());
+		},
+
+		_setStructureAttr: function(structure){
+			var s = structure;
+			if(s && dojo.isString(s)){
+				dojo.deprecated("dojox.grid._Grid.attr('structure', 'objVar')", "use dojox.grid._Grid.attr('structure', objVar) instead", "2.0");
+				s=dojo.getObject(s);
+			}
+			this.structure = s;
+			if(!s){
+				if(this.layout.structure){
+					s = this.layout.structure;
+				}else{
+					return;
+				}
+			}
+			this.views.destroyViews();
+			if(s !== this.layout.structure){
+				this.layout.setStructure(s);
+			}
+			this._structureChanged();
+		},
+
+		setStructure: function(/* dojox.grid.__ViewDef|dojox.grid.__ViewDef[]|dojox.grid.__CellDef[]|Array[dojox.grid.__CellDef[]] */ inStructure){
+			// summary:
+			//		Install a new structure and rebuild the grid.
+			dojo.deprecated("dojox.grid._Grid.setStructure(obj)", "use dojox.grid._Grid.attr('structure', obj) instead.", "2.0");
+			this._setStructureAttr(inStructure);
+		},
+		
+		getColumnTogglingItems: function(){
+			// Summary: returns an array of dijit.CheckedMenuItem widgets that can be
+			//		added to a menu for toggling columns on and off.
+			return dojo.map(this.layout.cells, function(cell){
+				if(!cell.menuItems){ cell.menuItems = []; }
+
+				var self = this;
+				var item = new dijit.CheckedMenuItem({
+					label: cell.name,
+					checked: !cell.hidden,
+					_gridCell: cell,
+					onChange: function(checked){
+						if(self.layout.setColumnVisibility(this._gridCell.index, checked)){
+							var items = this._gridCell.menuItems;
+							if(items.length > 1){
+								dojo.forEach(items, function(item){
+									if(item !== this){
+										item.setAttribute("checked", checked);
+									}
+								}, this);
+							}
+							checked = dojo.filter(self.layout.cells, function(c){
+								if(c.menuItems.length > 1){
+									dojo.forEach(c.menuItems, "item.attr('disabled', false);");
+								}else{
+									c.menuItems[0].attr('disabled', false);
+								}
+								return !c.hidden;
+							});
+							if(checked.length == 1){
+								dojo.forEach(checked[0].menuItems, "item.attr('disabled', true);");
+							}
+						}
+					},
+					destroy: function(){
+						var index = dojo.indexOf(this._gridCell.menuItems, this);
+						this._gridCell.menuItems.splice(index, 1);
+						delete this._gridCell;
+						dijit.CheckedMenuItem.prototype.destroy.apply(this, arguments);
+					}
+				});
+				cell.menuItems.push(item);
+				return item;
+			}, this); // dijit.CheckedMenuItem[]
+		},
+
+		_setHeaderMenuAttr: function(menu){
+			if(this._placeholders && this._placeholders.length){
+				dojo.forEach(this._placeholders, function(p){
+					p.unReplace(true);
+				});
+				this._placeholders = [];
+			}
+			if(this.headerMenu){
+				this.headerMenu.unBindDomNode(this.viewsHeaderNode);
+			}
+			this.headerMenu = menu;
+			if(!menu){ return; }
+
+			this.headerMenu.bindDomNode(this.viewsHeaderNode);
+			if(this.headerMenu.getPlaceholders){
+				this._placeholders = this.headerMenu.getPlaceholders(this.placeholderLabel);
+			}
+		},
+
+		setHeaderMenu: function(/* dijit.Menu */ menu){
+			dojo.deprecated("dojox.grid._Grid.setHeaderMenu(obj)", "use dojox.grid._Grid.attr('headerMenu', obj) instead.", "2.0");
+			this._setHeaderMenuAttr(menu);
+		},
+		
+		setupHeaderMenu: function(){
+			if(this._placeholders && this._placeholders.length){
+				dojo.forEach(this._placeholders, function(p){
+					if(p._replaced){
+						p.unReplace(true);
+					}
+					p.replace(this.getColumnTogglingItems());
+				}, this);
+			}
+		},
+
+		_fetch: function(start){
+			this.setScrollTop(0);
+		},
+
+		getItem: function(inRowIndex){
+			return null;
+		},
+		
+		showMessage: function(message){
+			if(message){
+				this.messagesNode.innerHTML = message;
+				this.messagesNode.style.display = "";
+			}else{
+				this.messagesNode.innerHTML = "";
+				this.messagesNode.style.display = "none";
+			}
+		},
+
+		_structureChanged: function() {
+			this.buildViews();
+			if(this.autoRender && this._started){
+				this.render();
+			}
+		},
+
+		hasLayout: function() {
+			return this.layout.cells.length;
+		},
+
+		// sizing
+		resize: function(changeSize, resultSize){
+			// summary:
+			//		Update the grid's rendering dimensions and resize it
+			
+			// Calling sizeChange calls update() which calls _resize...so let's
+			// save our input values, if any, and use them there when it gets 
+			// called.  This saves us an extra call to _resize(), which can
+			// get kind of heavy.
+			this._pendingChangeSize = changeSize;
+			this._pendingResultSize = resultSize;
+			this.sizeChange();
+		},
+
+		_getPadBorder: function() {
+			this._padBorder = this._padBorder || dojo._getPadBorderExtents(this.domNode);
+			return this._padBorder;
+		},
+
+		_getHeaderHeight: function(){
+			var vns = this.viewsHeaderNode.style, t = vns.display == "none" ? 0 : this.views.measureHeader();
+			vns.height = t + 'px';
+			// header heights are reset during measuring so must be normalized after measuring.
+			this.views.normalizeHeaderNodeHeight();
+			return t;
+		},
+		
+		_resize: function(changeSize, resultSize){
+			// Restore our pending values, if any
+			changeSize = changeSize || this._pendingChangeSize;
+			resultSize = resultSize || this._pendingResultSize;
+			delete this._pendingChangeSize;
+			delete this._pendingResultSize;
+			// if we have set up everything except the DOM, we cannot resize
+			if(!this.domNode){ return; }
+			var pn = this.domNode.parentNode;
+			if(!pn || pn.nodeType != 1 || !this.hasLayout() || pn.style.visibility == "hidden" || pn.style.display == "none"){
+				return;
+			}
+			// useful measurement
+			var padBorder = this._getPadBorder();
+			var hh = undefined;
+			var h;
+			// grid height
+			if(this._autoHeight){
+				this.domNode.style.height = 'auto';
+				this.viewsNode.style.height = '';
+			}else if(typeof this.autoHeight == "number"){
+				h = hh = this._getHeaderHeight();
+				h += (this.scroller.averageRowHeight * this.autoHeight);
+				this.domNode.style.height = h + "px";
+			}else if(this.domNode.clientHeight <= padBorder.h){
+				if(pn == document.body){
+					this.domNode.style.height = this.defaultHeight;
+				}else if(this.height){
+					this.domNode.style.height = this.height;
+				}else{
+					this.fitTo = "parent";
+				}
+			}
+			// if we are given dimensions, size the grid's domNode to those dimensions
+			if(resultSize){
+				changeSize = resultSize;
+			}
+			if(changeSize){
+				dojo.marginBox(this.domNode, changeSize);
+				this.height = this.domNode.style.height;
+				delete this.fitTo;
+			}else if(this.fitTo == "parent"){
+				h = this._parentContentBoxHeight = this._parentContentBoxHeight || dojo._getContentBox(pn).h;
+				this.domNode.style.height = Math.max(0, h) + "px";
+			}
+			
+			var hasFlex = dojo.some(this.views.views, function(v){ return v.flexCells; });
+
+			if(!this._autoHeight && (h || dojo._getContentBox(this.domNode).h) === 0){
+				// We need to hide the header, since the Grid is essentially hidden.
+				this.viewsHeaderNode.style.display = "none";
+			}else{
+				// Otherwise, show the header and give it an appropriate height.
+				this.viewsHeaderNode.style.display = "block";
+				if(!hasFlex && hh === undefined){
+					hh = this._getHeaderHeight();
+				}
+			}
+			if(hasFlex){
+				hh = undefined;
+			}
+
+			// NOTE: it is essential that width be applied before height
+			// Header height can only be calculated properly after view widths have been set.
+			// This is because flex column width is naturally 0 in Firefox.
+			// Therefore prior to width sizing flex columns with spaces are maximally wrapped
+			// and calculated to be too tall.
+			this.adaptWidth();
+			this.adaptHeight(hh);
+
+			this.postresize();
+		},
+
+		adaptWidth: function() {
+			// private: sets width and position for views and update grid width if necessary
+			var doAutoWidth = (!this.initialWidth && this.autoWidth);
+			var w = doAutoWidth ? 0 : this.domNode.clientWidth || (this.domNode.offsetWidth - this._getPadBorder().w),
+				vw = this.views.arrange(1, w);
+			this.views.onEach("adaptWidth");
+			if(doAutoWidth){
+				this.domNode.style.width = vw + "px";
+			}
+		},
+
+		adaptHeight: function(inHeaderHeight){
+			// private: measures and normalizes header height, then sets view heights, and then updates scroller
+			// content extent
+			var t = inHeaderHeight === undefined ? this._getHeaderHeight() : inHeaderHeight;
+			var h = (this._autoHeight ? -1 : Math.max(this.domNode.clientHeight - t, 0) || 0);
+			this.views.onEach('setSize', [0, h]);
+			this.views.onEach('adaptHeight');
+			if(!this._autoHeight){
+				var numScroll = 0, numNoScroll = 0;
+				var noScrolls = dojo.filter(this.views.views, function(v){
+					var has = v.hasHScrollbar();
+					if(has){ numScroll++; }else{ numNoScroll++; }
+					return (!has);
+				});
+				if(numScroll > 0 && numNoScroll > 0){
+					dojo.forEach(noScrolls, function(v){
+						v.adaptHeight(true);
+					});
+				}
+			}
+			if(this.autoHeight === true || h != -1 || (typeof this.autoHeight == "number" && this.autoHeight >= this.get('rowCount'))){
+				this.scroller.windowHeight = h;
+			}else{
+				this.scroller.windowHeight = Math.max(this.domNode.clientHeight - t, 0);
+			}
+		},
+
+		// startup
+		startup: function(){
+			if(this._started){return;}
+			this.inherited(arguments);
+			if(this.autoRender){
+				this.render();
+			}
+		},
+
+		// render
+		render: function(){
+			// summary:
+			//	Render the grid, headers, and views. Edit and scrolling states are reset. To retain edit and
+			// scrolling states, see Update.
+
+			if(!this.domNode){return;}
+			if(!this._started){return;}
+
+			if(!this.hasLayout()) {
+				this.scroller.init(0, this.keepRows, this.rowsPerPage);
+				return;
+			}
+			//
+			this.update = this.defaultUpdate;
+			this._render();
+		},
+
+		_render: function(){
+			this.scroller.init(this.get('rowCount'), this.keepRows, this.rowsPerPage);
+			this.prerender();
+			this.setScrollTop(0);
+			this.postrender();
+		},
+
+		prerender: function(){
+			// if autoHeight, make sure scroller knows not to virtualize; everything must be rendered.
+			this.keepRows = this._autoHeight ? 0 : this.keepRows;
+			this.scroller.setKeepInfo(this.keepRows);
+			this.views.render();
+			this._resize();
+		},
+
+		postrender: function(){
+			this.postresize();
+			this.focus.initFocusView();
+			// make rows unselectable
+			dojo.setSelectable(this.domNode, this.selectable);
+		},
+
+		postresize: function(){
+			// views are position absolute, so they do not inflate the parent
+			if(this._autoHeight){
+				var size = Math.max(this.views.measureContent()) + 'px';
+				
+				this.viewsNode.style.height = size;
+			}
+		},
+
+		renderRow: function(inRowIndex, inNodes){
+			// summary: private, used internally to render rows
+			this.views.renderRow(inRowIndex, inNodes, this._skipRowRenormalize);
+		},
+
+		rowRemoved: function(inRowIndex){
+			// summary: private, used internally to remove rows
+			this.views.rowRemoved(inRowIndex);
+		},
+
+		invalidated: null,
+
+		updating: false,
+
+		beginUpdate: function(){
+			// summary:
+			//		Use to make multiple changes to rows while queueing row updating.
+			// NOTE: not currently supporting nested begin/endUpdate calls
+			this.invalidated = [];
+			this.updating = true;
+		},
+
+		endUpdate: function(){
+			// summary:
+			//		Use after calling beginUpdate to render any changes made to rows.
+			this.updating = false;
+			var i = this.invalidated, r;
+			if(i.all){
+				this.update();
+			}else if(i.rowCount != undefined){
+				this.updateRowCount(i.rowCount);
+			}else{
+				for(r in i){
+					this.updateRow(Number(r));
+				}
+			}
+			this.invalidated = [];
+		},
+
+		// update
+		defaultUpdate: function(){
+			// note: initial update calls render and subsequently this function.
+			if(!this.domNode){return;}
+			if(this.updating){
+				this.invalidated.all = true;
+				return;
+			}
+			//this.edit.saveState(inRowIndex);
+			this.lastScrollTop = this.scrollTop;
+			this.prerender();
+			this.scroller.invalidateNodes();
+			this.setScrollTop(this.lastScrollTop);
+			this.postrender();
+			//this.edit.restoreState(inRowIndex);
+		},
+
+		update: function(){
+			// summary:
+			//		Update the grid, retaining edit and scrolling states.
+			this.render();
+		},
+
+		updateRow: function(inRowIndex){
+			// summary:
+			//		Render a single row.
+			// inRowIndex: Integer
+			//		Index of the row to render
+			inRowIndex = Number(inRowIndex);
+			if(this.updating){
+				this.invalidated[inRowIndex]=true;
+			}else{
+				this.views.updateRow(inRowIndex);
+				this.scroller.rowHeightChanged(inRowIndex);
+			}
+		},
+
+		updateRows: function(startIndex, howMany){
+			// summary:
+			//		Render consecutive rows at once.
+			// startIndex: Integer
+			//		Index of the starting row to render
+			// howMany: Integer
+			//		How many rows to update.
+			startIndex = Number(startIndex);
+			howMany = Number(howMany);
+			var i;
+			if(this.updating){
+				for(i=0; i<howMany; i++){
+					this.invalidated[i+startIndex]=true;
+				}
+			}else{
+				for(i=0; i<howMany; i++){
+					this.views.updateRow(i+startIndex, this._skipRowRenormalize);
+				}
+				this.scroller.rowHeightChanged(startIndex);
+			}
+		},
+
+		updateRowCount: function(inRowCount){
+			//summary:
+			//	Change the number of rows.
+			// inRowCount: int
+			//	Number of rows in the grid.
+			if(this.updating){
+				this.invalidated.rowCount = inRowCount;
+			}else{
+				this.rowCount = inRowCount;
+				this._setAutoHeightAttr(this.autoHeight, true);
+				if(this.layout.cells.length){
+					this.scroller.updateRowCount(inRowCount);
+				}
+				this._resize();				
+				if(this.layout.cells.length){
+					this.setScrollTop(this.scrollTop);
+				}
+			}
+		},
+
+		updateRowStyles: function(inRowIndex){
+			// summary:
+			//		Update the styles for a row after it's state has changed.
+			this.views.updateRowStyles(inRowIndex);
+		},
+		getRowNode: function(inRowIndex){
+			// summary:
+			//		find the rowNode that is not a rowSelector
+			if (this.focus.focusView && !(this.focus.focusView instanceof dojox.grid._RowSelector)){
+					return this.focus.focusView.rowNodes[inRowIndex];
+			}else{ // search through views
+				for (var i = 0, cView; (cView = this.views.views[i]); i++) {
+					if (!(cView instanceof dojox.grid._RowSelector)) {
+						return cView.rowNodes[inRowIndex];
+					}
+				}
+			}
+			return null;
+		},
+		rowHeightChanged: function(inRowIndex){
+			// summary:
+			//		Update grid when the height of a row has changed. Row height is handled automatically as rows
+			//		are rendered. Use this function only to update a row's height outside the normal rendering process.
+			// inRowIndex: Integer
+			// 		index of the row that has changed height
+
+			this.views.renormalizeRow(inRowIndex);
+			this.scroller.rowHeightChanged(inRowIndex);
+		},
+
+		// fastScroll: Boolean
+		//		flag modifies vertical scrolling behavior. Defaults to true but set to false for slower
+		//		scroll performance but more immediate scrolling feedback
+		fastScroll: true,
+
+		delayScroll: false,
+
+		// scrollRedrawThreshold: int
+		//	pixel distance a user must scroll vertically to trigger grid scrolling.
+		scrollRedrawThreshold: (dojo.isIE ? 100 : 50),
+
+		// scroll methods
+		scrollTo: function(inTop){
+			// summary:
+			//		Vertically scroll the grid to a given pixel position
+			// inTop: Integer
+			//		vertical position of the grid in pixels
+			if(!this.fastScroll){
+				this.setScrollTop(inTop);
+				return;
+			}
+			var delta = Math.abs(this.lastScrollTop - inTop);
+			this.lastScrollTop = inTop;
+			if(delta > this.scrollRedrawThreshold || this.delayScroll){
+				this.delayScroll = true;
+				this.scrollTop = inTop;
+				this.views.setScrollTop(inTop);
+				if(this._pendingScroll){
+					window.clearTimeout(this._pendingScroll);
+				}
+				var _this = this;
+				this._pendingScroll = window.setTimeout(function(){
+					delete _this._pendingScroll;
+					_this.finishScrollJob();
+				}, 200);
+			}else{
+				this.setScrollTop(inTop);
+			}
+		},
+
+		finishScrollJob: function(){
+			this.delayScroll = false;
+			this.setScrollTop(this.scrollTop);
+		},
+
+		setScrollTop: function(inTop){
+			this.scroller.scroll(this.views.setScrollTop(inTop));
+		},
+
+		scrollToRow: function(inRowIndex){
+			// summary:
+			//		Scroll the grid to a specific row.
+			// inRowIndex: Integer
+			// 		grid row index
+			this.setScrollTop(this.scroller.findScrollTop(inRowIndex) + 1);
+		},
+
+		// styling (private, used internally to style individual parts of a row)
+		styleRowNode: function(inRowIndex, inRowNode){
+			if(inRowNode){
+				this.rows.styleRowNode(inRowIndex, inRowNode);
+			}
+		},
+		
+		// called when the mouse leaves the grid so we can deselect all hover rows
+		_mouseOut: function(e){
+			this.rows.setOverRow(-2);
+		},
+	
+		// cells
+		getCell: function(inIndex){
+			// summary:
+			//		Retrieves the cell object for a given grid column.
+			// inIndex: Integer
+			// 		Grid column index of cell to retrieve
+			// returns:
+			//		a grid cell
+			return this.layout.cells[inIndex];
+		},
+
+		setCellWidth: function(inIndex, inUnitWidth){
+			this.getCell(inIndex).unitWidth = inUnitWidth;
+		},
+
+		getCellName: function(inCell){
+			// summary: Returns the cell name of a passed cell
+			return "Cell " + inCell.index; // String
+		},
+
+		// sorting
+		canSort: function(inSortInfo){
+			// summary:
+			//		Determines if the grid can be sorted
+			// inSortInfo: Integer
+			//		Sort information, 1-based index of column on which to sort, positive for an ascending sort
+			// 		and negative for a descending sort
+			// returns: Boolean
+			//		True if grid can be sorted on the given column in the given direction
+		},
+
+		sort: function(){
+		},
+
+		getSortAsc: function(inSortInfo){
+			// summary:
+			//		Returns true if grid is sorted in an ascending direction.
+			inSortInfo = inSortInfo == undefined ? this.sortInfo : inSortInfo;
+			return Boolean(inSortInfo > 0); // Boolean
+		},
+
+		getSortIndex: function(inSortInfo){
+			// summary:
+			//		Returns the index of the column on which the grid is sorted
+			inSortInfo = inSortInfo == undefined ? this.sortInfo : inSortInfo;
+			return Math.abs(inSortInfo) - 1; // Integer
+		},
+
+		setSortIndex: function(inIndex, inAsc){
+			// summary:
+			// 		Sort the grid on a column in a specified direction
+			// inIndex: Integer
+			// 		Column index on which to sort.
+			// inAsc: Boolean
+			// 		If true, sort the grid in ascending order, otherwise in descending order
+			var si = inIndex +1;
+			if(inAsc != undefined){
+				si *= (inAsc ? 1 : -1);
+			} else if(this.getSortIndex() == inIndex){
+				si = -this.sortInfo;
+			}
+			this.setSortInfo(si);
+		},
+
+		setSortInfo: function(inSortInfo){
+			if(this.canSort(inSortInfo)){
+				this.sortInfo = inSortInfo;
+				this.sort();
+				this.update();
+			}
+		},
+
+		// DOM event handler
+		doKeyEvent: function(e){
+			e.dispatch = 'do' + e.type;
+			this.onKeyEvent(e);
+		},
+
+		// event dispatch
+		//: protected
+		_dispatch: function(m, e){
+			if(m in this){
+				return this[m](e);
+			}
+			return false;
+		},
+
+		dispatchKeyEvent: function(e){
+			this._dispatch(e.dispatch, e);
+		},
+
+		dispatchContentEvent: function(e){
+			this.edit.dispatchEvent(e) || e.sourceView.dispatchContentEvent(e) || this._dispatch(e.dispatch, e);
+		},
+
+		dispatchHeaderEvent: function(e){
+			e.sourceView.dispatchHeaderEvent(e) || this._dispatch('doheader' + e.type, e);
+		},
+
+		dokeydown: function(e){
+			this.onKeyDown(e);
+		},
+
+		doclick: function(e){
+			if(e.cellNode){
+				this.onCellClick(e);
+			}else{
+				this.onRowClick(e);
+			}
+		},
+
+		dodblclick: function(e){
+			if(e.cellNode){
+				this.onCellDblClick(e);
+			}else{
+				this.onRowDblClick(e);
+			}
+		},
+
+		docontextmenu: function(e){
+			if(e.cellNode){
+				this.onCellContextMenu(e);
+			}else{
+				this.onRowContextMenu(e);
+			}
+		},
+
+		doheaderclick: function(e){
+			if(e.cellNode){
+				this.onHeaderCellClick(e);
+			}else{
+				this.onHeaderClick(e);
+			}
+		},
+
+		doheaderdblclick: function(e){
+			if(e.cellNode){
+				this.onHeaderCellDblClick(e);
+			}else{
+				this.onHeaderDblClick(e);
+			}
+		},
+
+		doheadercontextmenu: function(e){
+			if(e.cellNode){
+				this.onHeaderCellContextMenu(e);
+			}else{
+				this.onHeaderContextMenu(e);
+			}
+		},
+
+		// override to modify editing process
+		doStartEdit: function(inCell, inRowIndex){
+			this.onStartEdit(inCell, inRowIndex);
+		},
+
+		doApplyCellEdit: function(inValue, inRowIndex, inFieldIndex){
+			this.onApplyCellEdit(inValue, inRowIndex, inFieldIndex);
+		},
+
+		doCancelEdit: function(inRowIndex){
+			this.onCancelEdit(inRowIndex);
+		},
+
+		doApplyEdit: function(inRowIndex){
+			this.onApplyEdit(inRowIndex);
+		},
+
+		// row editing
+		addRow: function(){
+			// summary:
+			//		Add a row to the grid.
+			this.updateRowCount(this.get('rowCount')+1);
+		},
+
+		removeSelectedRows: function(){
+			// summary:
+			//		Remove the selected rows from the grid.
+			if(this.allItemsSelected){
+				this.updateRowCount(0);
+			}else{
+				this.updateRowCount(Math.max(0, this.get('rowCount') - this.selection.getSelected().length));
+			}
+			this.selection.clear();
+		}
+
+	});
+
+	dojox.grid._Grid.markupFactory = function(props, node, ctor, cellFunc){
+		var d = dojo;
+		var widthFromAttr = function(n){
+			var w = d.attr(n, "width")||"auto";
+			if((w != "auto")&&(w.slice(-2) != "em")&&(w.slice(-1) != "%")){
+				w = parseInt(w, 10)+"px";
+			}
+			return w;
+		};
+		// if(!props.store){ console.debug("no store!"); }
+		// if a structure isn't referenced, do we have enough
+		// data to try to build one automatically?
+		if(	!props.structure &&
+			node.nodeName.toLowerCase() == "table"){
+
+			// try to discover a structure
+			props.structure = d.query("> colgroup", node).map(function(cg){
+				var sv = d.attr(cg, "span");
+				var v = {
+					noscroll: (d.attr(cg, "noscroll") == "true") ? true : false,
+					__span: (!!sv ? parseInt(sv, 10) : 1),
+					cells: []
+				};
+				if(d.hasAttr(cg, "width")){
+					v.width = widthFromAttr(cg);
+				}
+				return v; // for vendetta
+			});
+			if(!props.structure.length){
+				props.structure.push({
+					__span: Infinity,
+					cells: [] // catch-all view
+				});
+			}
+			// check to see if we're gonna have more than one view
+
+			// for each tr in our th, create a row of cells
+			d.query("thead > tr", node).forEach(function(tr, tr_idx){
+				var cellCount = 0;
+				var viewIdx = 0;
+				var lastViewIdx;
+				var cView = null;
+				d.query("> th", tr).map(function(th){
+					// what view will this cell go into?
+
+					// NOTE:
+					//		to prevent extraneous iteration, we start counters over
+					//		for each row, incrementing over the surface area of the
+					//		structure that colgroup processing generates and
+					//		creating cell objects for each <th> to place into those
+					//		cell groups.  There's a lot of state-keepking logic
+					//		here, but it is what it has to be.
+					if(!cView){ // current view book keeping
+						lastViewIdx = 0;
+						cView = props.structure[0];
+					}else if(cellCount >= (lastViewIdx+cView.__span)){
+						viewIdx++;
+						// move to allocating things into the next view
+						lastViewIdx += cView.__span;
+						var lastView = cView;
+						cView = props.structure[viewIdx];
+					}
+
+					// actually define the cell from what markup hands us
+					var cell = {
+						name: d.trim(d.attr(th, "name")||th.innerHTML),
+						colSpan: parseInt(d.attr(th, "colspan")||1, 10),
+						type: d.trim(d.attr(th, "cellType")||""),
+						id: d.trim(d.attr(th,"id")||"")
+					};
+					cellCount += cell.colSpan;
+					var rowSpan = d.attr(th, "rowspan");
+					if(rowSpan){
+						cell.rowSpan = rowSpan;
+					}
+					if(d.hasAttr(th, "width")){
+						cell.width = widthFromAttr(th);
+					}
+					if(d.hasAttr(th, "relWidth")){
+						cell.relWidth = window.parseInt(dojo.attr(th, "relWidth"), 10);
+					}
+					if(d.hasAttr(th, "hidden")){
+						cell.hidden = d.attr(th, "hidden") == "true";
+					}
+
+					if(cellFunc){
+						cellFunc(th, cell);
+					}
+
+					cell.type = cell.type ? dojo.getObject(cell.type) : dojox.grid.cells.Cell;
+
+					if(cell.type && cell.type.markupFactory){
+						cell.type.markupFactory(th, cell);
+					}
+
+					if(!cView.cells[tr_idx]){
+						cView.cells[tr_idx] = [];
+					}
+					cView.cells[tr_idx].push(cell);
+				});
+			});
+		}
+
+		return new ctor(props, node);
+	};
 })();
-}
diff --git a/dojox/grid/_Layout.js b/dojox/grid/_Layout.js
index 7fc0c31..5bd2039 100644
--- a/dojox/grid/_Layout.js
+++ b/dojox/grid/_Layout.js
@@ -1,214 +1,253 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._Layout"]){
-dojo._hasResource["dojox.grid._Layout"]=true;
 dojo.provide("dojox.grid._Layout");
 dojo.require("dojox.grid.cells");
 dojo.require("dojox.grid._RowSelector");
-dojo.declare("dojox.grid._Layout",null,{constructor:function(_1){
-this.grid=_1;
-},cells:[],structure:null,defaultWidth:"6em",moveColumn:function(_2,_3,_4,_5,_6){
-var _7=this.structure[_2].cells[0];
-var _8=this.structure[_3].cells[0];
-var _9=null;
-var _a=0;
-var _b=0;
-for(var i=0,c;c=_7[i];i++){
-if(c.index==_4){
-_a=i;
-break;
-}
-}
-_9=_7.splice(_a,1)[0];
-_9.view=this.grid.views.views[_3];
-for(i=0,c=null;c=_8[i];i++){
-if(c.index==_5){
-_b=i;
-break;
-}
-}
-if(!_6){
-_b+=1;
-}
-_8.splice(_b,0,_9);
-var _c=this.grid.getCell(this.grid.getSortIndex());
-if(_c){
-_c._currentlySorted=this.grid.getSortAsc();
-}
-this.cells=[];
-_4=0;
-var v;
-for(i=0;v=this.structure[i];i++){
-for(var j=0,cs;cs=v.cells[j];j++){
-for(var k=0;c=cs[k];k++){
-c.index=_4;
-this.cells.push(c);
-if("_currentlySorted" in c){
-var si=_4+1;
-si*=c._currentlySorted?1:-1;
-this.grid.sortInfo=si;
-delete c._currentlySorted;
-}
-_4++;
-}
-}
-}
-this.grid.setupHeaderMenu();
-},setColumnVisibility:function(_d,_e){
-var _f=this.cells[_d];
-if(_f.hidden==_e){
-_f.hidden=!_e;
-var v=_f.view,w=v.viewWidth;
-if(w&&w!="auto"){
-v._togglingColumn=dojo.marginBox(_f.getHeaderNode()).w||0;
-}
-v.update();
-return true;
-}else{
-return false;
-}
-},addCellDef:function(_10,_11,_12){
-var _13=this;
-var _14=function(_15){
-var w=0;
-if(_15.colSpan>1){
-w=0;
-}else{
-w=_15.width||_13._defaultCellProps.width||_13.defaultWidth;
-if(!isNaN(w)){
-w=w+"em";
-}
-}
-return w;
-};
-var _16={grid:this.grid,subrow:_10,layoutIndex:_11,index:this.cells.length};
-if(_12&&_12 instanceof dojox.grid.cells._Base){
-var _17=dojo.clone(_12);
-_16.unitWidth=_14(_17._props);
-_17=dojo.mixin(_17,this._defaultCellProps,_12._props,_16);
-return _17;
-}
-var _18=_12.type||this._defaultCellProps.type||dojox.grid.cells.Cell;
-_16.unitWidth=_14(_12);
-return new _18(dojo.mixin({},this._defaultCellProps,_12,_16));
-},addRowDef:function(_19,_1a){
-var _1b=[];
-var _1c=0,_1d=0,_1e=true;
-for(var i=0,def,_1f;(def=_1a[i]);i++){
-_1f=this.addCellDef(_19,i,def);
-_1b.push(_1f);
-this.cells.push(_1f);
-if(_1e&&_1f.relWidth){
-_1c+=_1f.relWidth;
-}else{
-if(_1f.width){
-var w=_1f.width;
-if(typeof w=="string"&&w.slice(-1)=="%"){
-_1d+=window.parseInt(w,10);
-}else{
-if(w=="auto"){
-_1e=false;
-}
-}
-}
-}
-}
-if(_1c&&_1e){
-dojo.forEach(_1b,function(_20){
-if(_20.relWidth){
-_20.width=_20.unitWidth=((_20.relWidth/_1c)*(100-_1d))+"%";
-}
+
+dojo.declare("dojox.grid._Layout", null, {
+	// summary:
+	//	Controls grid cell layout. Owned by grid and used internally.
+	constructor: function(inGrid){
+		this.grid = inGrid;
+	},
+	// flat array of grid cells
+	cells: [],
+	// structured array of grid cells
+	structure: null,
+	// default cell width
+	defaultWidth: '6em',
+
+	// methods
+	moveColumn: function(sourceViewIndex, destViewIndex, cellIndex, targetIndex, before){
+		var source_cells = this.structure[sourceViewIndex].cells[0];
+		var dest_cells = this.structure[destViewIndex].cells[0];
+
+		var cell = null;
+		var cell_ri = 0;
+		var target_ri = 0;
+
+		for(var i=0, c; c=source_cells[i]; i++){
+			if(c.index == cellIndex){
+				cell_ri = i;
+				break;
+			}
+		}
+		cell = source_cells.splice(cell_ri, 1)[0];
+		cell.view = this.grid.views.views[destViewIndex];
+
+		for(i=0, c=null; c=dest_cells[i]; i++){
+			if(c.index == targetIndex){
+				target_ri = i;
+				break;
+			}
+		}
+		if(!before){
+			target_ri += 1;
+		}
+		dest_cells.splice(target_ri, 0, cell);
+
+		var sortedCell = this.grid.getCell(this.grid.getSortIndex());
+		if(sortedCell){
+			sortedCell._currentlySorted = this.grid.getSortAsc();
+		}
+
+		this.cells = [];
+		cellIndex = 0;
+		var v;
+		for(i=0; v=this.structure[i]; i++){
+			for(var j=0, cs; cs=v.cells[j]; j++){
+				for(var k=0; c=cs[k]; k++){
+					c.index = cellIndex;
+					this.cells.push(c);
+					if("_currentlySorted" in c){
+						var si = cellIndex + 1;
+						si *= c._currentlySorted ? 1 : -1;
+						this.grid.sortInfo = si;
+						delete c._currentlySorted;
+					}
+					cellIndex++;
+				}
+			}
+		}
+		this.grid.setupHeaderMenu();
+		//this.grid.renderOnIdle();
+	},
+
+	setColumnVisibility: function(columnIndex, visible){
+		var cell = this.cells[columnIndex];
+		if(cell.hidden == visible){
+			cell.hidden = !visible;
+			var v = cell.view, w = v.viewWidth;
+			if(w && w != "auto"){
+				v._togglingColumn = dojo.marginBox(cell.getHeaderNode()).w || 0;
+			}
+			v.update();
+			return true;
+		}else{
+			return false;
+		}
+	},
+	
+	addCellDef: function(inRowIndex, inCellIndex, inDef){
+		var self = this;
+		var getCellWidth = function(inDef){
+			var w = 0;
+			if(inDef.colSpan > 1){
+				w = 0;
+			}else{
+				w = inDef.width || self._defaultCellProps.width || self.defaultWidth;
+
+				if(!isNaN(w)){
+					w = w + "em";
+				}
+			}
+			return w;
+		};
+
+		var props = {
+			grid: this.grid,
+			subrow: inRowIndex,
+			layoutIndex: inCellIndex,
+			index: this.cells.length
+		};
+
+		if(inDef && inDef instanceof dojox.grid.cells._Base){
+			var new_cell = dojo.clone(inDef);
+			props.unitWidth = getCellWidth(new_cell._props);
+			new_cell = dojo.mixin(new_cell, this._defaultCellProps, inDef._props, props);
+			return new_cell;
+		}
+
+		var cell_type = inDef.type || this._defaultCellProps.type || dojox.grid.cells.Cell;
+
+		props.unitWidth = getCellWidth(inDef);
+		return new cell_type(dojo.mixin({}, this._defaultCellProps, inDef, props));	
+	},
+	
+	addRowDef: function(inRowIndex, inDef){
+		var result = [];
+		var relSum = 0, pctSum = 0, doRel = true;
+		for(var i=0, def, cell; (def=inDef[i]); i++){
+			cell = this.addCellDef(inRowIndex, i, def);
+			result.push(cell);
+			this.cells.push(cell);
+			// Check and calculate the sum of all relative widths
+			if(doRel && cell.relWidth){
+				relSum += cell.relWidth;
+			}else if(cell.width){
+				var w = cell.width;
+				if(typeof w == "string" && w.slice(-1) == "%"){
+					pctSum += window.parseInt(w, 10);
+				}else if(w == "auto"){
+					// relative widths doesn't play nice with auto - since we
+					// don't have a way of knowing how much space the auto is 
+					// supposed to take up.
+					doRel = false;
+				}
+			}
+		}
+		if(relSum && doRel){
+			// We have some kind of relWidths specified - so change them to %
+			dojo.forEach(result, function(cell){
+				if(cell.relWidth){
+					cell.width = cell.unitWidth = ((cell.relWidth / relSum) * (100 - pctSum)) + "%";
+				}
+			});
+		}
+		return result;
+	
+	},
+
+	addRowsDef: function(inDef){
+		var result = [];
+		if(dojo.isArray(inDef)){
+			if(dojo.isArray(inDef[0])){
+				for(var i=0, row; inDef && (row=inDef[i]); i++){
+					result.push(this.addRowDef(i, row));
+				}
+			}else{
+				result.push(this.addRowDef(0, inDef));
+			}
+		}
+		return result;	
+	},
+	
+	addViewDef: function(inDef){
+		this._defaultCellProps = inDef.defaultCell || {};
+		if(inDef.width && inDef.width == "auto"){
+			delete inDef.width;
+		}
+		return dojo.mixin({}, inDef, {cells: this.addRowsDef(inDef.rows || inDef.cells)});
+	},
+	
+	setStructure: function(inStructure){
+		this.fieldIndex = 0;
+		this.cells = [];
+		var s = this.structure = [];
+
+		if(this.grid.rowSelector){
+			var sel = { type: dojox._scopeName + ".grid._RowSelector" };
+
+			if(dojo.isString(this.grid.rowSelector)){
+				var width = this.grid.rowSelector;
+
+				if(width == "false"){
+					sel = null;
+				}else if(width != "true"){
+					sel['width'] = width;
+				}
+			}else{
+				if(!this.grid.rowSelector){
+					sel = null;
+				}
+			}
+
+			if(sel){
+				s.push(this.addViewDef(sel));
+			}
+		}
+
+		var isCell = function(def){
+			return ("name" in def || "field" in def || "get" in def);
+		};
+
+		var isRowDef = function(def){
+			if(dojo.isArray(def)){
+				if(dojo.isArray(def[0]) || isCell(def[0])){
+					return true;
+				}
+			}
+			return false;
+		};
+
+		var isView = function(def){
+			return (def !== null && dojo.isObject(def) &&
+					("cells" in def || "rows" in def || ("type" in def && !isCell(def))));
+		};
+
+		if(dojo.isArray(inStructure)){
+			var hasViews = false;
+			for(var i=0, st; (st=inStructure[i]); i++){
+				if(isView(st)){
+					hasViews = true;
+					break;
+				}
+			}
+			if(!hasViews){
+				s.push(this.addViewDef({ cells: inStructure }));
+			}else{
+				for(i=0; (st=inStructure[i]); i++){
+					if(isRowDef(st)){
+						s.push(this.addViewDef({ cells: st }));
+					}else if(isView(st)){
+						s.push(this.addViewDef(st));
+					}
+				}
+			}
+		}else if(isView(inStructure)){
+			// it's a view object
+			s.push(this.addViewDef(inStructure));
+		}
+
+		this.cellCount = this.cells.length;
+		this.grid.setupHeaderMenu();
+	}
 });
-}
-return _1b;
-},addRowsDef:function(_21){
-var _22=[];
-if(dojo.isArray(_21)){
-if(dojo.isArray(_21[0])){
-for(var i=0,row;_21&&(row=_21[i]);i++){
-_22.push(this.addRowDef(i,row));
-}
-}else{
-_22.push(this.addRowDef(0,_21));
-}
-}
-return _22;
-},addViewDef:function(_23){
-this._defaultCellProps=_23.defaultCell||{};
-if(_23.width&&_23.width=="auto"){
-delete _23.width;
-}
-return dojo.mixin({},_23,{cells:this.addRowsDef(_23.rows||_23.cells)});
-},setStructure:function(_24){
-this.fieldIndex=0;
-this.cells=[];
-var s=this.structure=[];
-if(this.grid.rowSelector){
-var sel={type:dojox._scopeName+".grid._RowSelector"};
-if(dojo.isString(this.grid.rowSelector)){
-var _25=this.grid.rowSelector;
-if(_25=="false"){
-sel=null;
-}else{
-if(_25!="true"){
-sel["width"]=_25;
-}
-}
-}else{
-if(!this.grid.rowSelector){
-sel=null;
-}
-}
-if(sel){
-s.push(this.addViewDef(sel));
-}
-}
-var _26=function(def){
-return ("name" in def||"field" in def||"get" in def);
-};
-var _27=function(def){
-if(dojo.isArray(def)){
-if(dojo.isArray(def[0])||_26(def[0])){
-return true;
-}
-}
-return false;
-};
-var _28=function(def){
-return (def!==null&&dojo.isObject(def)&&("cells" in def||"rows" in def||("type" in def&&!_26(def))));
-};
-if(dojo.isArray(_24)){
-var _29=false;
-for(var i=0,st;(st=_24[i]);i++){
-if(_28(st)){
-_29=true;
-break;
-}
-}
-if(!_29){
-s.push(this.addViewDef({cells:_24}));
-}else{
-for(i=0;(st=_24[i]);i++){
-if(_27(st)){
-s.push(this.addViewDef({cells:st}));
-}else{
-if(_28(st)){
-s.push(this.addViewDef(st));
-}
-}
-}
-}
-}else{
-if(_28(_24)){
-s.push(this.addViewDef(_24));
-}
-}
-this.cellCount=this.cells.length;
-this.grid.setupHeaderMenu();
-}});
-}
diff --git a/dojox/grid/_RadioSelector.js b/dojox/grid/_RadioSelector.js
index 235e401..055c446 100644
--- a/dojox/grid/_RadioSelector.js
+++ b/dojox/grid/_RadioSelector.js
@@ -1,12 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._RadioSelector"]){
-dojo._hasResource["dojox.grid._RadioSelector"]=true;
 dojo.provide("dojox.grid._RadioSelector");
+
 dojo.require("dojox.grid._Selector");
-}
diff --git a/dojox/grid/_RowManager.js b/dojox/grid/_RowManager.js
index 1ad2191..f82e0c0 100644
--- a/dojox/grid/_RowManager.js
+++ b/dojox/grid/_RowManager.js
@@ -1,46 +1,60 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._RowManager"]){
-dojo._hasResource["dojox.grid._RowManager"]=true;
 dojo.provide("dojox.grid._RowManager");
+
 (function(){
-var _1=function(_2,_3){
-if(_2.style.cssText==undefined){
-_2.setAttribute("style",_3);
-}else{
-_2.style.cssText=_3;
-}
-};
-dojo.declare("dojox.grid._RowManager",null,{constructor:function(_4){
-this.grid=_4;
-},linesToEms:2,overRow:-2,prepareStylingRow:function(_5,_6){
-return {index:_5,node:_6,odd:Boolean(_5&1),selected:!!this.grid.selection.isSelected(_5),over:this.isOver(_5),customStyles:"",customClasses:"dojoxGridRow"};
-},styleRowNode:function(_7,_8){
-var _9=this.prepareStylingRow(_7,_8);
-this.grid.onStyleRow(_9);
-this.applyStyles(_9);
-},applyStyles:function(_a){
-var i=_a;
-i.node.className=i.customClasses;
-var h=i.node.style.height;
-_1(i.node,i.customStyles+";"+(i.node._style||""));
-i.node.style.height=h;
-},updateStyles:function(_b){
-this.grid.updateRowStyles(_b);
-},setOverRow:function(_c){
-var _d=this.overRow;
-this.overRow=_c;
-if((_d!=this.overRow)&&(dojo.isString(_d)||_d>=0)){
-this.updateStyles(_d);
-}
-this.updateStyles(this.overRow);
-},isOver:function(_e){
-return (this.overRow==_e&&!dojo.hasClass(this.grid.domNode,"dojoxGridColumnResizing"));
-}});
+	var setStyleText = function(inNode, inStyleText){
+		if(inNode.style.cssText == undefined){
+			inNode.setAttribute("style", inStyleText);
+		}else{
+			inNode.style.cssText = inStyleText;
+		}
+	};
+
+	dojo.declare("dojox.grid._RowManager", null, {
+		//	Stores information about grid rows. Owned by grid and used internally.
+		constructor: function(inGrid){
+			this.grid = inGrid;
+		},
+		linesToEms: 2,
+		overRow: -2,
+		// styles
+		prepareStylingRow: function(inRowIndex, inRowNode){
+			return {
+				index: inRowIndex, 
+				node: inRowNode,
+				odd: Boolean(inRowIndex&1),
+				selected: !!this.grid.selection.isSelected(inRowIndex),
+				over: this.isOver(inRowIndex),
+				customStyles: "",
+				customClasses: "dojoxGridRow"
+			};
+		},
+		styleRowNode: function(inRowIndex, inRowNode){
+			var row = this.prepareStylingRow(inRowIndex, inRowNode);
+			this.grid.onStyleRow(row);
+			this.applyStyles(row);
+		},
+		applyStyles: function(inRow){
+			var i = inRow;
+
+			i.node.className = i.customClasses;
+			var h = i.node.style.height;
+			setStyleText(i.node, i.customStyles + ';' + (i.node._style||''));
+			i.node.style.height = h;
+		},
+		updateStyles: function(inRowIndex){
+			this.grid.updateRowStyles(inRowIndex);
+		},
+		// states and events
+		setOverRow: function(inRowIndex){
+			var last = this.overRow;
+			this.overRow = inRowIndex;
+			if((last!=this.overRow)&&(dojo.isString(last) || last >= 0)){
+				this.updateStyles(last);
+			}
+			this.updateStyles(this.overRow);
+		},
+		isOver: function(inRowIndex){
+			return (this.overRow == inRowIndex && !dojo.hasClass(this.grid.domNode, "dojoxGridColumnResizing"));
+		}
+	});
 })();
-}
diff --git a/dojox/grid/_RowSelector.js b/dojox/grid/_RowSelector.js
index 561d856..14a47b7 100644
--- a/dojox/grid/_RowSelector.js
+++ b/dojox/grid/_RowSelector.js
@@ -1,45 +1,55 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._RowSelector"]){
-dojo._hasResource["dojox.grid._RowSelector"]=true;
 dojo.provide("dojox.grid._RowSelector");
 dojo.require("dojox.grid._View");
-dojo.declare("dojox.grid._RowSelector",dojox.grid._View,{defaultWidth:"2em",noscroll:true,padBorderWidth:2,buildRendering:function(){
-this.inherited("buildRendering",arguments);
-this.scrollboxNode.style.overflow="hidden";
-this.headerNode.style.visibility="hidden";
-},getWidth:function(){
-return this.viewWidth||this.defaultWidth;
-},buildRowContent:function(_1,_2){
-var w=this.contentWidth||0;
-_2.innerHTML="<table class=\"dojoxGridRowbarTable\" style=\"width:"+w+"px;height:1px;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" role=\"presentation\"><tr><td class=\"dojoxGridRowbarInner\"> </td></tr></table>";
-},renderHeader:function(){
-},updateRow:function(){
-},resize:function(){
-this.adaptHeight();
-},adaptWidth:function(){
-if(!("contentWidth" in this)&&this.contentNode){
-this.contentWidth=this.contentNode.offsetWidth-this.padBorderWidth;
-}
-},doStyleRowNode:function(_3,_4){
-var n=["dojoxGridRowbar dojoxGridNonNormalizedCell"];
-if(this.grid.rows.isOver(_3)){
-n.push("dojoxGridRowbarOver");
-}
-if(this.grid.selection.isSelected(_3)){
-n.push("dojoxGridRowbarSelected");
-}
-_4.className=n.join(" ");
-},domouseover:function(e){
-this.grid.onMouseOverRow(e);
-},domouseout:function(e){
-if(!this.isIntraRowEvent(e)){
-this.grid.onMouseOutRow(e);
-}
-}});
-}
+
+dojo.declare('dojox.grid._RowSelector', dojox.grid._View, {
+	// summary:
+	//	Custom grid view. If used in a grid structure, provides a small selectable region for grid rows.
+	defaultWidth: "2em",
+	noscroll: true,
+	padBorderWidth: 2,
+	buildRendering: function(){
+		this.inherited('buildRendering', arguments);
+		this.scrollboxNode.style.overflow = "hidden";
+		this.headerNode.style.visibility = "hidden";
+	},	
+	getWidth: function(){
+		return this.viewWidth || this.defaultWidth;
+	},
+	buildRowContent: function(inRowIndex, inRowNode){
+		var w = this.contentWidth || 0;
+		inRowNode.innerHTML = '<table class="dojoxGridRowbarTable" style="width:' + w + 'px;height:1px;" border="0" cellspacing="0" cellpadding="0" role="presentation"><tr><td class="dojoxGridRowbarInner"> </td></tr></table>';
+	},
+	renderHeader: function(){
+	},
+	updateRow: function(){
+	},
+	resize: function(){
+		this.adaptHeight();
+	},
+	adaptWidth: function(){
+		// Only calculate this here - rather than every call to buildRowContent
+		if(!("contentWidth" in this) && this.contentNode){
+			this.contentWidth = this.contentNode.offsetWidth - this.padBorderWidth;
+		}
+	},
+	// styling
+	doStyleRowNode: function(inRowIndex, inRowNode){
+		var n = [ "dojoxGridRowbar dojoxGridNonNormalizedCell" ];
+		if(this.grid.rows.isOver(inRowIndex)){
+			n.push("dojoxGridRowbarOver");
+		}
+		if(this.grid.selection.isSelected(inRowIndex)){
+			n.push("dojoxGridRowbarSelected");
+		}
+		inRowNode.className = n.join(" ");
+	},
+	// event handlers
+	domouseover: function(e){
+		this.grid.onMouseOverRow(e);
+	},
+	domouseout: function(e){
+		if(!this.isIntraRowEvent(e)){
+			this.grid.onMouseOutRow(e);
+		}
+	}
+});
diff --git a/dojox/grid/_Scroller.js b/dojox/grid/_Scroller.js
index 10ffb60..35961f4 100644
--- a/dojox/grid/_Scroller.js
+++ b/dojox/grid/_Scroller.js
@@ -1,403 +1,497 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._Scroller"]){
-dojo._hasResource["dojox.grid._Scroller"]=true;
 dojo.provide("dojox.grid._Scroller");
+
 (function(){
-var _1=function(_2){
-var i=0,n,p=_2.parentNode;
-while((n=p.childNodes[i++])){
-if(n==_2){
-return i-1;
-}
-}
-return -1;
-};
-var _3=function(_4){
-if(!_4){
-return;
-}
-var _5=function(_6){
-return _6.domNode&&dojo.isDescendant(_6.domNode,_4,true);
-};
-var ws=dijit.registry.filter(_5);
-for(var i=0,w;(w=ws[i]);i++){
-w.destroy();
-}
-delete ws;
-};
-var _7=function(_8){
-var _9=dojo.byId(_8);
-return (_9&&_9.tagName?_9.tagName.toLowerCase():"");
-};
-var _a=function(_b,_c){
-var _d=[];
-var i=0,n;
-while((n=_b.childNodes[i])){
-i++;
-if(_7(n)==_c){
-_d.push(n);
-}
-}
-return _d;
-};
-var _e=function(_f){
-return _a(_f,"div");
-};
-dojo.declare("dojox.grid._Scroller",null,{constructor:function(_10){
-this.setContentNodes(_10);
-this.pageHeights=[];
-this.pageNodes=[];
-this.stack=[];
-},rowCount:0,defaultRowHeight:32,keepRows:100,contentNode:null,scrollboxNode:null,defaultPageHeight:0,keepPages:10,pageCount:0,windowHeight:0,firstVisibleRow:0,lastVisibleRow:0,averageRowHeight:0,page:0,pageTop:0,init:function(_11,_12,_13){
-switch(arguments.length){
-case 3:
-this.rowsPerPage=_13;
-case 2:
-this.keepRows=_12;
-case 1:
-this.rowCount=_11;
-default:
-break;
-}
-this.defaultPageHeight=this.defaultRowHeight*this.rowsPerPage;
-this.pageCount=this._getPageCount(this.rowCount,this.rowsPerPage);
-this.setKeepInfo(this.keepRows);
-this.invalidate();
-if(this.scrollboxNode){
-this.scrollboxNode.scrollTop=0;
-this.scroll(0);
-this.scrollboxNode.onscroll=dojo.hitch(this,"onscroll");
-}
-},_getPageCount:function(_14,_15){
-return _14?(Math.ceil(_14/_15)||1):0;
-},destroy:function(){
-this.invalidateNodes();
-delete this.contentNodes;
-delete this.contentNode;
-delete this.scrollboxNode;
-},setKeepInfo:function(_16){
-this.keepRows=_16;
-this.keepPages=!this.keepRows?this.keepPages:Math.max(Math.ceil(this.keepRows/this.rowsPerPage),2);
-},setContentNodes:function(_17){
-this.contentNodes=_17;
-this.colCount=(this.contentNodes?this.contentNodes.length:0);
-this.pageNodes=[];
-for(var i=0;i<this.colCount;i++){
-this.pageNodes[i]=[];
-}
-},getDefaultNodes:function(){
-return this.pageNodes[0]||[];
-},invalidate:function(){
-this._invalidating=true;
-this.invalidateNodes();
-this.pageHeights=[];
-this.height=(this.pageCount?(this.pageCount-1)*this.defaultPageHeight+this.calcLastPageHeight():0);
-this.resize();
-this._invalidating=false;
-},updateRowCount:function(_18){
-this.invalidateNodes();
-this.rowCount=_18;
-var _19=this.pageCount;
-if(_19===0){
-this.height=1;
-}
-this.pageCount=this._getPageCount(this.rowCount,this.rowsPerPage);
-if(this.pageCount<_19){
-for(var i=_19-1;i>=this.pageCount;i--){
-this.height-=this.getPageHeight(i);
-delete this.pageHeights[i];
-}
-}else{
-if(this.pageCount>_19){
-this.height+=this.defaultPageHeight*(this.pageCount-_19-1)+this.calcLastPageHeight();
-}
-}
-this.resize();
-},pageExists:function(_1a){
-return Boolean(this.getDefaultPageNode(_1a));
-},measurePage:function(_1b){
-if(this.grid.rowHeight){
-var _1c=this.grid.rowHeight+1;
-return ((_1b+1)*this.rowsPerPage>this.rowCount?this.rowCount-_1b*this.rowsPerPage:this.rowsPerPage)*_1c;
-}
-var n=this.getDefaultPageNode(_1b);
-return (n&&n.innerHTML)?n.offsetHeight:undefined;
-},positionPage:function(_1d,_1e){
-for(var i=0;i<this.colCount;i++){
-this.pageNodes[i][_1d].style.top=_1e+"px";
-}
-},repositionPages:function(_1f){
-var _20=this.getDefaultNodes();
-var _21=0;
-for(var i=0;i<this.stack.length;i++){
-_21=Math.max(this.stack[i],_21);
-}
-var n=_20[_1f];
-var y=(n?this.getPageNodePosition(n)+this.getPageHeight(_1f):0);
-for(var p=_1f+1;p<=_21;p++){
-n=_20[p];
-if(n){
-if(this.getPageNodePosition(n)==y){
-return;
-}
-this.positionPage(p,y);
-}
-y+=this.getPageHeight(p);
-}
-},installPage:function(_22){
-for(var i=0;i<this.colCount;i++){
-this.contentNodes[i].appendChild(this.pageNodes[i][_22]);
-}
-},preparePage:function(_23,_24){
-var p=(_24?this.popPage():null);
-for(var i=0;i<this.colCount;i++){
-var _25=this.pageNodes[i];
-var _26=(p===null?this.createPageNode():this.invalidatePageNode(p,_25));
-_26.pageIndex=_23;
-_25[_23]=_26;
-}
-},renderPage:function(_27){
-var _28=[];
-var i,j;
-for(i=0;i<this.colCount;i++){
-_28[i]=this.pageNodes[i][_27];
-}
-for(i=0,j=_27*this.rowsPerPage;(i<this.rowsPerPage)&&(j<this.rowCount);i++,j++){
-this.renderRow(j,_28);
-}
-},removePage:function(_29){
-for(var i=0,j=_29*this.rowsPerPage;i<this.rowsPerPage;i++,j++){
-this.removeRow(j);
-}
-},destroyPage:function(_2a){
-for(var i=0;i<this.colCount;i++){
-var n=this.invalidatePageNode(_2a,this.pageNodes[i]);
-if(n){
-dojo.destroy(n);
-}
-}
-},pacify:function(_2b){
-},pacifying:false,pacifyTicks:200,setPacifying:function(_2c){
-if(this.pacifying!=_2c){
-this.pacifying=_2c;
-this.pacify(this.pacifying);
-}
-},startPacify:function(){
-this.startPacifyTicks=new Date().getTime();
-},doPacify:function(){
-var _2d=(new Date().getTime()-this.startPacifyTicks)>this.pacifyTicks;
-this.setPacifying(true);
-this.startPacify();
-return _2d;
-},endPacify:function(){
-this.setPacifying(false);
-},resize:function(){
-if(this.scrollboxNode){
-this.windowHeight=this.scrollboxNode.clientHeight;
-}
-for(var i=0;i<this.colCount;i++){
-dojox.grid.util.setStyleHeightPx(this.contentNodes[i],Math.max(1,this.height));
-}
-var _2e=(!this._invalidating);
-if(!_2e){
-var ah=this.grid.attr("autoHeight");
-if(typeof ah=="number"&&ah<=Math.min(this.rowsPerPage,this.rowCount)){
-_2e=true;
-}
-}
-if(_2e){
-this.needPage(this.page,this.pageTop);
-}
-var _2f=(this.page<this.pageCount-1)?this.rowsPerPage:((this.rowCount%this.rowsPerPage)||this.rowsPerPage);
-var _30=this.getPageHeight(this.page);
-this.averageRowHeight=(_30>0&&_2f>0)?(_30/_2f):0;
-},calcLastPageHeight:function(){
-if(!this.pageCount){
-return 0;
-}
-var _31=this.pageCount-1;
-var _32=((this.rowCount%this.rowsPerPage)||(this.rowsPerPage))*this.defaultRowHeight;
-this.pageHeights[_31]=_32;
-return _32;
-},updateContentHeight:function(_33){
-this.height+=_33;
-this.resize();
-},updatePageHeight:function(_34,_35){
-if(this.pageExists(_34)){
-var oh=this.getPageHeight(_34);
-var h=(this.measurePage(_34));
-if(h===undefined){
-h=oh;
-}
-this.pageHeights[_34]=h;
-if(oh!=h){
-this.updateContentHeight(h-oh);
-var ah=this.grid.attr("autoHeight");
-if((typeof ah=="number"&&ah>this.rowCount)||(ah===true&&!_35)){
-this.grid.sizeChange();
-}else{
-this.repositionPages(_34);
-}
-}
-return h;
-}
-return 0;
-},rowHeightChanged:function(_36){
-this.updatePageHeight(Math.floor(_36/this.rowsPerPage),false);
-},invalidateNodes:function(){
-while(this.stack.length){
-this.destroyPage(this.popPage());
-}
-},createPageNode:function(){
-var p=document.createElement("div");
-dojo.attr(p,"role","presentation");
-p.style.position="absolute";
-p.style[dojo._isBodyLtr()?"left":"right"]="0";
-return p;
-},getPageHeight:function(_37){
-var ph=this.pageHeights[_37];
-return (ph!==undefined?ph:this.defaultPageHeight);
-},pushPage:function(_38){
-return this.stack.push(_38);
-},popPage:function(){
-return this.stack.shift();
-},findPage:function(_39){
-var i=0,h=0;
-for(var ph=0;i<this.pageCount;i++,h+=ph){
-ph=this.getPageHeight(i);
-if(h+ph>=_39){
-break;
-}
-}
-this.page=i;
-this.pageTop=h;
-},buildPage:function(_3a,_3b,_3c){
-this.preparePage(_3a,_3b);
-this.positionPage(_3a,_3c);
-this.installPage(_3a);
-this.renderPage(_3a);
-this.pushPage(_3a);
-},needPage:function(_3d,_3e){
-var h=this.getPageHeight(_3d),oh=h;
-if(!this.pageExists(_3d)){
-this.buildPage(_3d,this.keepPages&&(this.stack.length>=this.keepPages),_3e);
-h=this.updatePageHeight(_3d,true);
-}else{
-this.positionPage(_3d,_3e);
-}
-return h;
-},onscroll:function(){
-this.scroll(this.scrollboxNode.scrollTop);
-},scroll:function(_3f){
-this.grid.scrollTop=_3f;
-if(this.colCount){
-this.startPacify();
-this.findPage(_3f);
-var h=this.height;
-var b=this.getScrollBottom(_3f);
-for(var p=this.page,y=this.pageTop;(p<this.pageCount)&&((b<0)||(y<b));p++){
-y+=this.needPage(p,y);
-}
-this.firstVisibleRow=this.getFirstVisibleRow(this.page,this.pageTop,_3f);
-this.lastVisibleRow=this.getLastVisibleRow(p-1,y,b);
-if(h!=this.height){
-this.repositionPages(p-1);
-}
-this.endPacify();
-}
-},getScrollBottom:function(_40){
-return (this.windowHeight>=0?_40+this.windowHeight:-1);
-},processNodeEvent:function(e,_41){
-var t=e.target;
-while(t&&(t!=_41)&&t.parentNode&&(t.parentNode.parentNode!=_41)){
-t=t.parentNode;
-}
-if(!t||!t.parentNode||(t.parentNode.parentNode!=_41)){
-return false;
-}
-var _42=t.parentNode;
-e.topRowIndex=_42.pageIndex*this.rowsPerPage;
-e.rowIndex=e.topRowIndex+_1(t);
-e.rowTarget=t;
-return true;
-},processEvent:function(e){
-return this.processNodeEvent(e,this.contentNode);
-},renderRow:function(_43,_44){
-},removeRow:function(_45){
-},getDefaultPageNode:function(_46){
-return this.getDefaultNodes()[_46];
-},positionPageNode:function(_47,_48){
-},getPageNodePosition:function(_49){
-return _49.offsetTop;
-},invalidatePageNode:function(_4a,_4b){
-var p=_4b[_4a];
-if(p){
-delete _4b[_4a];
-this.removePage(_4a,p);
-_3(p);
-p.innerHTML="";
-}
-return p;
-},getPageRow:function(_4c){
-return _4c*this.rowsPerPage;
-},getLastPageRow:function(_4d){
-return Math.min(this.rowCount,this.getPageRow(_4d+1))-1;
-},getFirstVisibleRow:function(_4e,_4f,_50){
-if(!this.pageExists(_4e)){
-return 0;
-}
-var row=this.getPageRow(_4e);
-var _51=this.getDefaultNodes();
-var _52=_e(_51[_4e]);
-for(var i=0,l=_52.length;i<l&&_4f<_50;i++,row++){
-_4f+=_52[i].offsetHeight;
-}
-return (row?row-1:row);
-},getLastVisibleRow:function(_53,_54,_55){
-if(!this.pageExists(_53)){
-return 0;
-}
-var _56=this.getDefaultNodes();
-var row=this.getLastPageRow(_53);
-var _57=_e(_56[_53]);
-for(var i=_57.length-1;i>=0&&_54>_55;i--,row--){
-_54-=_57[i].offsetHeight;
-}
-return row+1;
-},findTopRow:function(_58){
-var _59=this.getDefaultNodes();
-var _5a=_e(_59[this.page]);
-for(var i=0,l=_5a.length,t=this.pageTop,h;i<l;i++){
-h=_5a[i].offsetHeight;
-t+=h;
-if(t>=_58){
-this.offset=h-(t-_58);
-return i+this.page*this.rowsPerPage;
-}
-}
-return -1;
-},findScrollTop:function(_5b){
-var _5c=Math.floor(_5b/this.rowsPerPage);
-var t=0;
-var i,l;
-for(i=0;i<_5c;i++){
-t+=this.getPageHeight(i);
-}
-this.pageTop=t;
-this.needPage(_5c,this.pageTop);
-var _5d=this.getDefaultNodes();
-var _5e=_e(_5d[_5c]);
-var r=_5b-this.rowsPerPage*_5c;
-for(i=0,l=_5e.length;i<l&&i<r;i++){
-t+=_5e[i].offsetHeight;
-}
-return t;
-},dummy:0});
+	var indexInParent = function(inNode){
+		var i=0, n, p=inNode.parentNode;
+		while((n = p.childNodes[i++])){
+			if(n == inNode){
+				return i - 1;
+			}
+		}
+		return -1;
+	};
+	
+	var cleanNode = function(inNode){
+		if(!inNode){
+			return;
+		}
+		var filter = function(inW){
+			return inW.domNode && dojo.isDescendant(inW.domNode, inNode, true);
+		};
+		var ws = dijit.registry.filter(filter);
+		for(var i=0, w; (w=ws[i]); i++){
+			w.destroy();
+		}
+		delete ws;
+	};
+
+	var getTagName = function(inNodeOrId){
+		var node = dojo.byId(inNodeOrId);
+		return (node && node.tagName ? node.tagName.toLowerCase() : '');
+	};
+	
+	var nodeKids = function(inNode, inTag){
+		var result = [];
+		var i=0, n;
+		while((n = inNode.childNodes[i])){
+			i++;
+			if(getTagName(n) == inTag){
+				result.push(n);
+			}
+		}
+		return result;
+	};
+	
+	var divkids = function(inNode){
+		return nodeKids(inNode, 'div');
+	};
+
+	dojo.declare("dojox.grid._Scroller", null, {
+		constructor: function(inContentNodes){
+			this.setContentNodes(inContentNodes);
+			this.pageHeights = [];
+			this.pageNodes = [];
+			this.stack = [];
+		},
+		// specified
+		rowCount: 0, // total number of rows to manage
+		defaultRowHeight: 32, // default height of a row
+		keepRows: 100, // maximum number of rows that should exist at one time
+		contentNode: null, // node to contain pages
+		scrollboxNode: null, // node that controls scrolling
+		// calculated
+		defaultPageHeight: 0, // default height of a page
+		keepPages: 10, // maximum number of pages that should exists at one time
+		pageCount: 0,
+		windowHeight: 0,
+		firstVisibleRow: 0,
+		lastVisibleRow: 0,
+		averageRowHeight: 0, // the average height of a row
+		// private
+		page: 0,
+		pageTop: 0,
+		// init
+		init: function(inRowCount, inKeepRows, inRowsPerPage){
+			switch(arguments.length){
+				case 3: this.rowsPerPage = inRowsPerPage;
+				case 2: this.keepRows = inKeepRows;
+				case 1: this.rowCount = inRowCount;
+				default: break;
+			}
+			this.defaultPageHeight = this.defaultRowHeight * this.rowsPerPage;
+			this.pageCount = this._getPageCount(this.rowCount, this.rowsPerPage);
+			this.setKeepInfo(this.keepRows);
+			this.invalidate();
+			if(this.scrollboxNode){
+				this.scrollboxNode.scrollTop = 0;
+				this.scroll(0);
+				this.scrollboxNode.onscroll = dojo.hitch(this, 'onscroll');
+			}
+		},
+		_getPageCount: function(rowCount, rowsPerPage){
+			return rowCount ? (Math.ceil(rowCount / rowsPerPage) || 1) : 0;
+		},
+		destroy: function(){
+			this.invalidateNodes();
+			delete this.contentNodes;
+			delete this.contentNode;
+			delete this.scrollboxNode;
+		},
+		setKeepInfo: function(inKeepRows){
+			this.keepRows = inKeepRows;
+			this.keepPages = !this.keepRows ? this.keepPages : Math.max(Math.ceil(this.keepRows / this.rowsPerPage), 2);
+		},
+		// nodes
+		setContentNodes: function(inNodes){
+			this.contentNodes = inNodes;
+			this.colCount = (this.contentNodes ? this.contentNodes.length : 0);
+			this.pageNodes = [];
+			for(var i=0; i<this.colCount; i++){
+				this.pageNodes[i] = [];
+			}
+		},
+		getDefaultNodes: function(){
+			return this.pageNodes[0] || [];
+		},
+		// updating
+		invalidate: function(){
+			this._invalidating = true;
+			this.invalidateNodes();
+			this.pageHeights = [];
+			this.height = (this.pageCount ? (this.pageCount - 1)* this.defaultPageHeight + this.calcLastPageHeight() : 0);
+			this.resize();
+			this._invalidating = false;
+		},
+		updateRowCount: function(inRowCount){
+			this.invalidateNodes();
+			this.rowCount = inRowCount;
+			// update page count, adjust document height
+			var oldPageCount = this.pageCount;
+			if(oldPageCount === 0){
+				//We want to have at least 1px in height to keep scroller.  Otherwise with an
+				//empty grid you can't scroll to see the header.
+				this.height = 1;
+			}
+			this.pageCount = this._getPageCount(this.rowCount, this.rowsPerPage);
+			if(this.pageCount < oldPageCount){
+				for(var i=oldPageCount-1; i>=this.pageCount; i--){
+					this.height -= this.getPageHeight(i);
+					delete this.pageHeights[i];
+				}
+			}else if(this.pageCount > oldPageCount){
+				this.height += this.defaultPageHeight * (this.pageCount - oldPageCount - 1) + this.calcLastPageHeight();
+			}
+			this.resize();
+		},
+		// implementation for page manager
+		pageExists: function(inPageIndex){
+			return Boolean(this.getDefaultPageNode(inPageIndex));
+		},
+		measurePage: function(inPageIndex){
+			if(this.grid.rowHeight){
+				var height = this.grid.rowHeight + 1;
+				return ((inPageIndex + 1) * this.rowsPerPage > this.rowCount ?
+					this.rowCount - inPageIndex * this.rowsPerPage :
+					this.rowsPerPage) * height;
+					 
+			}
+			var n = this.getDefaultPageNode(inPageIndex);
+			return (n && n.innerHTML) ? n.offsetHeight : undefined;
+		},
+		positionPage: function(inPageIndex, inPos){
+			for(var i=0; i<this.colCount; i++){
+				this.pageNodes[i][inPageIndex].style.top = inPos + 'px';
+			}
+		},
+		repositionPages: function(inPageIndex){
+			var nodes = this.getDefaultNodes();
+			var last = 0;
+
+			for(var i=0; i<this.stack.length; i++){
+				last = Math.max(this.stack[i], last);
+			}
+			//
+			var n = nodes[inPageIndex];
+			var y = (n ? this.getPageNodePosition(n) + this.getPageHeight(inPageIndex) : 0);
+			for(var p=inPageIndex+1; p<=last; p++){
+				n = nodes[p];
+				if(n){
+					if(this.getPageNodePosition(n) == y){
+						return;
+					}
+					this.positionPage(p, y);
+				}
+				y += this.getPageHeight(p);
+			}
+		},
+		installPage: function(inPageIndex){
+			for(var i=0; i<this.colCount; i++){
+				this.contentNodes[i].appendChild(this.pageNodes[i][inPageIndex]);
+			}
+		},
+		preparePage: function(inPageIndex, inReuseNode){
+			var p = (inReuseNode ? this.popPage() : null);
+			for(var i=0; i<this.colCount; i++){
+				var nodes = this.pageNodes[i];
+				var new_p = (p === null ? this.createPageNode() : this.invalidatePageNode(p, nodes));
+				new_p.pageIndex = inPageIndex;
+				nodes[inPageIndex] = new_p;
+			}
+		},
+		// rendering implementation
+		renderPage: function(inPageIndex){
+			var nodes = [];
+			var i, j;
+			for(i=0; i<this.colCount; i++){
+				nodes[i] = this.pageNodes[i][inPageIndex];
+			}
+			for(i=0, j=inPageIndex*this.rowsPerPage; (i<this.rowsPerPage)&&(j<this.rowCount); i++, j++){
+				this.renderRow(j, nodes);
+			}
+		},
+		removePage: function(inPageIndex){
+			for(var i=0, j=inPageIndex*this.rowsPerPage; i<this.rowsPerPage; i++, j++){
+				this.removeRow(j);
+			}
+		},
+		destroyPage: function(inPageIndex){
+			for(var i=0; i<this.colCount; i++){
+				var n = this.invalidatePageNode(inPageIndex, this.pageNodes[i]);
+				if(n){
+					dojo.destroy(n);
+				}
+			}
+		},
+		pacify: function(inShouldPacify){
+		},
+		// pacification
+		pacifying: false,
+		pacifyTicks: 200,
+		setPacifying: function(inPacifying){
+			if(this.pacifying != inPacifying){
+				this.pacifying = inPacifying;
+				this.pacify(this.pacifying);
+			}
+		},
+		startPacify: function(){
+			this.startPacifyTicks = new Date().getTime();
+		},
+		doPacify: function(){
+			var result = (new Date().getTime() - this.startPacifyTicks) > this.pacifyTicks;
+			this.setPacifying(true);
+			this.startPacify();
+			return result;
+		},
+		endPacify: function(){
+			this.setPacifying(false);
+		},
+		// default sizing implementation
+		resize: function(){
+			if(this.scrollboxNode){
+				this.windowHeight = this.scrollboxNode.clientHeight;
+			}
+			for(var i=0; i<this.colCount; i++){
+				//We want to have 1px in height min to keep scroller.  Otherwise can't scroll
+				//and see header in empty grid.
+				dojox.grid.util.setStyleHeightPx(this.contentNodes[i], Math.max(1,this.height));
+			}
+			
+			// Calculate the average row height and update the defaults (row and page).
+			var needPage = (!this._invalidating);
+			if(!needPage){
+				var ah = this.grid.attr("autoHeight");
+				if(typeof ah == "number" && ah <= Math.min(this.rowsPerPage, this.rowCount)){
+					needPage = true;
+				}
+			}
+			if(needPage){
+				this.needPage(this.page, this.pageTop);
+			}
+			var rowsOnPage = (this.page < this.pageCount - 1) ? this.rowsPerPage : ((this.rowCount % this.rowsPerPage) || this.rowsPerPage);
+			var pageHeight = this.getPageHeight(this.page);
+			this.averageRowHeight = (pageHeight > 0 && rowsOnPage > 0) ? (pageHeight / rowsOnPage) : 0;
+		},
+		calcLastPageHeight: function(){
+			if(!this.pageCount){
+				return 0;
+			}
+			var lastPage = this.pageCount - 1;
+			var lastPageHeight = ((this.rowCount % this.rowsPerPage)||(this.rowsPerPage)) * this.defaultRowHeight;
+			this.pageHeights[lastPage] = lastPageHeight;
+			return lastPageHeight;
+		},
+		updateContentHeight: function(inDh){
+			this.height += inDh;
+			this.resize();
+		},
+		updatePageHeight: function(inPageIndex, fromBuild){
+			if(this.pageExists(inPageIndex)){
+				var oh = this.getPageHeight(inPageIndex);
+				var h = (this.measurePage(inPageIndex));
+				if(h === undefined){
+					h = oh;
+				}
+				this.pageHeights[inPageIndex] = h;
+				if(oh != h){
+					this.updateContentHeight(h - oh);
+					var ah = this.grid.attr("autoHeight");
+					if((typeof ah == "number" && ah > this.rowCount)||(ah === true && !fromBuild)){
+						this.grid.sizeChange();
+					}else{
+						this.repositionPages(inPageIndex);
+					}
+				}
+				return h;
+			}
+			return 0;
+		},
+		rowHeightChanged: function(inRowIndex){
+			this.updatePageHeight(Math.floor(inRowIndex / this.rowsPerPage), false);
+		},
+		// scroller core
+		invalidateNodes: function(){
+			while(this.stack.length){
+				this.destroyPage(this.popPage());
+			}
+		},
+		createPageNode: function(){
+			var p = document.createElement('div');
+			dojo.attr(p,"role","presentation");
+			p.style.position = 'absolute';
+			//p.style.width = '100%';
+			p.style[dojo._isBodyLtr() ? "left" : "right"] = '0';
+			return p;
+		},
+		getPageHeight: function(inPageIndex){
+			var ph = this.pageHeights[inPageIndex];
+			return (ph !== undefined ? ph : this.defaultPageHeight);
+		},
+		// FIXME: this is not a stack, it's a FIFO list
+		pushPage: function(inPageIndex){
+			return this.stack.push(inPageIndex);
+		},
+		popPage: function(){
+			return this.stack.shift();
+		},
+		findPage: function(inTop){
+			var i = 0, h = 0;
+			for(var ph = 0; i<this.pageCount; i++, h += ph){
+				ph = this.getPageHeight(i);
+				if(h + ph >= inTop){
+					break;
+				}
+			}
+			this.page = i;
+			this.pageTop = h;
+		},
+		buildPage: function(inPageIndex, inReuseNode, inPos){
+			this.preparePage(inPageIndex, inReuseNode);
+			this.positionPage(inPageIndex, inPos);
+			// order of operations is key below
+			this.installPage(inPageIndex);
+			this.renderPage(inPageIndex);
+			// order of operations is key above
+			this.pushPage(inPageIndex);
+		},
+		needPage: function(inPageIndex, inPos){
+			var h = this.getPageHeight(inPageIndex), oh = h;
+			if(!this.pageExists(inPageIndex)){
+				this.buildPage(inPageIndex, this.keepPages&&(this.stack.length >= this.keepPages), inPos);
+				h = this.updatePageHeight(inPageIndex, true);
+			}else{
+				this.positionPage(inPageIndex, inPos);
+			}
+			return h;
+		},
+		onscroll: function(){
+			this.scroll(this.scrollboxNode.scrollTop);
+		},
+		scroll: function(inTop){
+			this.grid.scrollTop = inTop;
+			if(this.colCount){
+				this.startPacify();
+				this.findPage(inTop);
+				var h = this.height;
+				var b = this.getScrollBottom(inTop);
+				for(var p=this.page, y=this.pageTop; (p<this.pageCount)&&((b<0)||(y<b)); p++){
+					y += this.needPage(p, y);
+				}
+				this.firstVisibleRow = this.getFirstVisibleRow(this.page, this.pageTop, inTop);
+				this.lastVisibleRow = this.getLastVisibleRow(p - 1, y, b);
+				// indicates some page size has been updated
+				if(h != this.height){
+					this.repositionPages(p-1);
+				}
+				this.endPacify();
+			}
+		},
+		getScrollBottom: function(inTop){
+			return (this.windowHeight >= 0 ? inTop + this.windowHeight : -1);
+		},
+		// events
+		processNodeEvent: function(e, inNode){
+			var t = e.target;
+			while(t && (t != inNode) && t.parentNode && (t.parentNode.parentNode != inNode)){
+				t = t.parentNode;
+			}
+			if(!t || !t.parentNode || (t.parentNode.parentNode != inNode)){
+				return false;
+			}
+			var page = t.parentNode;
+			e.topRowIndex = page.pageIndex * this.rowsPerPage;
+			e.rowIndex = e.topRowIndex + indexInParent(t);
+			e.rowTarget = t;
+			return true;
+		},
+		processEvent: function(e){
+			return this.processNodeEvent(e, this.contentNode);
+		},
+		// virtual rendering interface
+		renderRow: function(inRowIndex, inPageNode){
+		},
+		removeRow: function(inRowIndex){
+		},
+		// page node operations
+		getDefaultPageNode: function(inPageIndex){
+			return this.getDefaultNodes()[inPageIndex];
+		},
+		positionPageNode: function(inNode, inPos){
+		},
+		getPageNodePosition: function(inNode){
+			return inNode.offsetTop;
+		},
+		invalidatePageNode: function(inPageIndex, inNodes){
+			var p = inNodes[inPageIndex];
+			if(p){
+				delete inNodes[inPageIndex];
+				this.removePage(inPageIndex, p);
+				cleanNode(p);
+				p.innerHTML = '';
+			}
+			return p;
+		},
+		// scroll control
+		getPageRow: function(inPage){
+			return inPage * this.rowsPerPage;
+		},
+		getLastPageRow: function(inPage){
+			return Math.min(this.rowCount, this.getPageRow(inPage + 1)) - 1;
+		},
+		getFirstVisibleRow: function(inPage, inPageTop, inScrollTop){
+			if(!this.pageExists(inPage)){
+				return 0;
+			}
+			var row = this.getPageRow(inPage);
+			var nodes = this.getDefaultNodes();
+			var rows = divkids(nodes[inPage]);
+			for(var i=0,l=rows.length; i<l && inPageTop<inScrollTop; i++, row++){
+				inPageTop += rows[i].offsetHeight;
+			}
+			return (row ? row - 1 : row);
+		},
+		getLastVisibleRow: function(inPage, inBottom, inScrollBottom){
+			if(!this.pageExists(inPage)){
+				return 0;
+			}
+			var nodes = this.getDefaultNodes();
+			var row = this.getLastPageRow(inPage);
+			var rows = divkids(nodes[inPage]);
+			for(var i=rows.length-1; i>=0 && inBottom>inScrollBottom; i--, row--){
+				inBottom -= rows[i].offsetHeight;
+			}
+			return row + 1;
+		},
+		findTopRow: function(inScrollTop){
+			var nodes = this.getDefaultNodes();
+			var rows = divkids(nodes[this.page]);
+			for(var i=0,l=rows.length,t=this.pageTop,h; i<l; i++){
+				h = rows[i].offsetHeight;
+				t += h;
+				if(t >= inScrollTop){
+					this.offset = h - (t - inScrollTop);
+					return i + this.page * this.rowsPerPage;
+				}
+			}
+			return -1;
+		},
+		findScrollTop: function(inRow){
+			var rowPage = Math.floor(inRow / this.rowsPerPage);
+			var t = 0;
+			var i, l;
+			for(i=0; i<rowPage; i++){
+				t += this.getPageHeight(i);
+			}
+			this.pageTop = t;
+			this.needPage(rowPage, this.pageTop);
+
+			var nodes = this.getDefaultNodes();
+			var rows = divkids(nodes[rowPage]);
+			var r = inRow - this.rowsPerPage * rowPage;
+			for(i=0,l=rows.length; i<l && i<r; i++){
+				t += rows[i].offsetHeight;
+			}
+			return t;
+		},
+		dummy: 0
+	});
 })();
-}
diff --git a/dojox/grid/_Selector.js b/dojox/grid/_Selector.js
index 24ae190..618214e 100644
--- a/dojox/grid/_Selector.js
+++ b/dojox/grid/_Selector.js
@@ -1,160 +1,216 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._Selector"]){
-dojo._hasResource["dojox.grid._Selector"]=true;
 dojo.provide("dojox.grid._Selector");
+
 dojo.require("dojox.grid.Selection");
 dojo.require("dojox.grid._View");
 dojo.require("dojox.grid._Builder");
+
 (function(){
-dojox.grid._InputSelectorHeaderBuilder=dojo.extend(function(_1){
-dojox.grid._HeaderBuilder.call(this,_1);
-},dojox.grid._HeaderBuilder.prototype,{generateHtml:function(){
-var w=this.view.contentWidth||0;
-var _2=this.view.grid.selection.getSelectedCount();
-var _3=(_2&&_2==this.view.grid.rowCount)?" dijitCheckBoxChecked dijitChecked":"";
-return "<table style=\"width:"+w+"px;\" "+"border=\"0\" cellspacing=\"0\" cellpadding=\"0\" "+"role=\"presentation\"><tr><th style=\"text-align: center;\">"+"<div class=\"dojoxGridCheckSelector dijitReset dijitInline dijitCheckBox"+_3+"\"></div></th></tr></table>";
-},doclick:function(e){
-var _4=this.view.grid.selection.getSelectedCount();
-this.view._selectionChanging=true;
-if(_4==this.view.grid.rowCount){
-this.view.grid.selection.deselectAll();
-}else{
-this.view.grid.selection.selectRange(0,this.view.grid.rowCount-1);
-}
-this.view._selectionChanging=false;
-this.view.onSelectionChanged();
-return true;
-}});
-dojox.grid._SelectorContentBuilder=dojo.extend(function(_5){
-dojox.grid._ContentBuilder.call(this,_5);
-},dojox.grid._ContentBuilder.prototype,{generateHtml:function(_6,_7){
-var w=this.view.contentWidth||0;
-return "<table class=\"dojoxGridRowbarTable\" style=\"width:"+w+"px;\" border=\"0\" "+"cellspacing=\"0\" cellpadding=\"0\" role=\"presentation\"><tr>"+"<td  style=\"text-align: center;\" class=\"dojoxGridRowbarInner\">"+this.getCellContent(_7)+"</td></tr></table>";
-},getCellContent:function(_8){
-return " ";
-},findTarget:function(){
-var t=dojox.grid._ContentBuilder.prototype.findTarget.apply(this,arguments);
-return t;
-},domouseover:function(e){
-this.view.grid.onMouseOverRow(e);
-},domouseout:function(e){
-if(!this.isIntraRowEvent(e)){
-this.view.grid.onMouseOutRow(e);
-}
-},doclick:function(e){
-var _9=e.rowIndex;
-var _a=this.view.grid.selection.isSelected(_9);
-var _b=this.view.grid.selection.mode;
-if(!_a){
-if(_b=="single"){
-this.view.grid.selection.select(_9);
-}else{
-if(_b!="none"){
-this.view.grid.selection.addToSelection(_9);
-}
-}
-}else{
-this.view.grid.selection.deselect(_9);
-}
-return true;
-}});
-dojox.grid._InputSelectorContentBuilder=dojo.extend(function(_c){
-dojox.grid._SelectorContentBuilder.call(this,_c);
-},dojox.grid._SelectorContentBuilder.prototype,{getCellContent:function(_d){
-var v=this.view;
-var _e=v.inputType=="checkbox"?"CheckBox":"Radio";
-var _f=!!v.grid.selection.isSelected(_d)?" dijit"+_e+"Checked dijitChecked":"";
-return "<div class=\"dojoxGridCheckSelector dijitReset dijitInline dijit"+_e+_f+"\"></div>";
-}});
-dojo.declare("dojox.grid._Selector",dojox.grid._View,{inputType:"",selectionMode:"",defaultWidth:"2em",noscroll:true,padBorderWidth:2,_contentBuilderClass:dojox.grid._SelectorContentBuilder,postCreate:function(){
-this.inherited(arguments);
-if(this.selectionMode){
-this.grid.selection.mode=this.selectionMode;
-}
-this.connect(this.grid.selection,"onSelected","onSelected");
-this.connect(this.grid.selection,"onDeselected","onDeselected");
-},buildRendering:function(){
-this.inherited(arguments);
-this.scrollboxNode.style.overflow="hidden";
-},getWidth:function(){
-return this.viewWidth||this.defaultWidth;
-},resize:function(){
-this.adaptHeight();
-},setStructure:function(s){
-this.inherited(arguments);
-if(s.defaultWidth){
-this.defaultWidth=s.defaultWidth;
-}
-},adaptWidth:function(){
-if(!("contentWidth" in this)&&this.contentNode){
-this.contentWidth=this.contentNode.offsetWidth-this.padBorderWidth;
-}
-},doStyleRowNode:function(_10,_11){
-var n=["dojoxGridRowbar dojoxGridNonNormalizedCell"];
-if(this.grid.rows.isOver(_10)){
-n.push("dojoxGridRowbarOver");
-}
-if(this.grid.selection.isSelected(_10)){
-n.push("dojoxGridRowbarSelected");
-}
-_11.className=n.join(" ");
-},onSelected:function(_12){
-this.grid.updateRow(_12);
-},onDeselected:function(_13){
-this.grid.updateRow(_13);
-}});
-if(!dojox.grid._View.prototype._headerBuilderClass&&!dojox.grid._View.prototype._contentBuilderClass){
-dojox.grid._Selector.prototype.postCreate=function(){
-this.connect(this.scrollboxNode,"onscroll","doscroll");
-dojox.grid.util.funnelEvents(this.contentNode,this,"doContentEvent",["mouseover","mouseout","click","dblclick","contextmenu","mousedown"]);
-dojox.grid.util.funnelEvents(this.headerNode,this,"doHeaderEvent",["dblclick","mouseover","mouseout","mousemove","mousedown","click","contextmenu"]);
-if(this._contentBuilderClass){
-this.content=new this._contentBuilderClass(this);
-}else{
-this.content=new dojox.grid._ContentBuilder(this);
-}
-if(this._headerBuilderClass){
-this.header=new this._headerBuilderClass(this);
-}else{
-this.header=new dojox.grid._HeaderBuilder(this);
-}
-if(!dojo._isBodyLtr()){
-this.headerNodeContainer.style.width="";
-}
-this.connect(this.grid.selection,"onSelected","onSelected");
-this.connect(this.grid.selection,"onDeselected","onDeselected");
-};
-}
-dojo.declare("dojox.grid._RadioSelector",dojox.grid._Selector,{inputType:"radio",selectionMode:"single",_contentBuilderClass:dojox.grid._InputSelectorContentBuilder,buildRendering:function(){
-this.inherited(arguments);
-this.headerNode.style.visibility="hidden";
-},renderHeader:function(){
-}});
-dojo.declare("dojox.grid._CheckBoxSelector",dojox.grid._Selector,{inputType:"checkbox",_headerBuilderClass:dojox.grid._InputSelectorHeaderBuilder,_contentBuilderClass:dojox.grid._InputSelectorContentBuilder,postCreate:function(){
-this.inherited(arguments);
-this.connect(this.grid,"onSelectionChanged","onSelectionChanged");
-this.connect(this.grid,"updateRowCount","_updateVisibility");
-},renderHeader:function(){
-this.inherited(arguments);
-this._updateVisibility(this.grid.rowCount);
-},_updateVisibility:function(_14){
-this.headerNode.style.visibility=_14?"":"hidden";
-},onSelectionChanged:function(){
-if(this._selectionChanging){
-return;
-}
-var _15=dojo.query(".dojoxGridCheckSelector",this.headerNode)[0];
-var g=this.grid;
-var s=(g.rowCount&&g.rowCount==g.selection.getSelectedCount());
-g.allItemsSelected=s||false;
-dojo.toggleClass(_15,"dijitChecked",g.allItemsSelected);
-dojo.toggleClass(_15,"dijitCheckBoxChecked",g.allItemsSelected);
-}});
+	dojox.grid._InputSelectorHeaderBuilder = dojo.extend(function(view){
+		dojox.grid._HeaderBuilder.call(this, view);
+	},dojox.grid._HeaderBuilder.prototype,{
+		generateHtml: function(){
+			var w = this.view.contentWidth || 0;
+			var selectedCount = this.view.grid.selection.getSelectedCount();
+			var checked = (selectedCount && selectedCount == this.view.grid.rowCount) ? ' dijitCheckBoxChecked dijitChecked' : '';
+			return '<table style="width:' + w + 'px;" ' +
+				'border="0" cellspacing="0" cellpadding="0" ' +
+				'role="presentation"><tr><th style="text-align: center;">' +
+				'<div class="dojoxGridCheckSelector dijitReset dijitInline dijitCheckBox' + checked + '"></div></th></tr></table>';
+		},
+		doclick: function(e){
+			var selectedCount = this.view.grid.selection.getSelectedCount();
+
+			this.view._selectionChanging = true;
+			if(selectedCount==this.view.grid.rowCount){
+				this.view.grid.selection.deselectAll();
+			}else{
+				this.view.grid.selection.selectRange(0, this.view.grid.rowCount-1);
+			}
+			this.view._selectionChanging = false;
+			this.view.onSelectionChanged();
+			return true;
+		}
+	});
+
+	dojox.grid._SelectorContentBuilder = dojo.extend(function(view){
+		dojox.grid._ContentBuilder.call(this, view);
+	},dojox.grid._ContentBuilder.prototype,{
+		generateHtml: function(inDataIndex, inRowIndex){
+			var w = this.view.contentWidth || 0;
+			return '<table class="dojoxGridRowbarTable" style="width:' + w + 'px;" border="0" ' + 
+				'cellspacing="0" cellpadding="0" role="presentation"><tr>' + 
+				'<td  style="text-align: center;" class="dojoxGridRowbarInner">' + this.getCellContent(inRowIndex) + '</td></tr></table>';
+		},
+		getCellContent: function(inRowIndex){
+			return ' ';
+		},
+		findTarget: function(){
+			var t = dojox.grid._ContentBuilder.prototype.findTarget.apply(this, arguments);
+			return t;
+		},
+		domouseover: function(e){
+			this.view.grid.onMouseOverRow(e);
+		},
+		domouseout: function(e){
+			if(!this.isIntraRowEvent(e)){
+				this.view.grid.onMouseOutRow(e);
+			}
+		},
+		doclick: function(e){
+			var idx = e.rowIndex;
+			var selected = this.view.grid.selection.isSelected(idx);
+			var mode = this.view.grid.selection.mode;
+
+			if(!selected){
+				if(mode == 'single'){
+					this.view.grid.selection.select(idx);
+				}else if(mode != 'none'){
+					this.view.grid.selection.addToSelection(idx);
+				}
+			}else{
+				this.view.grid.selection.deselect(idx);
+			}
+
+			return true;
+		}
+	});
+
+	dojox.grid._InputSelectorContentBuilder = dojo.extend(function(view){
+		dojox.grid._SelectorContentBuilder.call(this, view);
+	},dojox.grid._SelectorContentBuilder.prototype,{
+		getCellContent: function(rowIndex){
+			var v = this.view;
+			var type = v.inputType == "checkbox" ? "CheckBox" : "Radio";
+			var checked = !!v.grid.selection.isSelected(rowIndex) ? ' dijit' + type + 'Checked dijitChecked' : '';
+			return '<div class="dojoxGridCheckSelector dijitReset dijitInline dijit' + type + checked + '"></div>';
+		}
+	});
+
+	dojo.declare("dojox.grid._Selector", dojox.grid._View, {
+		inputType: '',
+		selectionMode: '',
+
+		// summary:
+		//	Custom grid view. If used in a grid structure, provides a small selectable region for grid rows.
+		defaultWidth: "2em",
+		noscroll: true,
+		padBorderWidth: 2,
+
+		_contentBuilderClass: dojox.grid._SelectorContentBuilder,
+
+		postCreate: function(){
+			this.inherited(arguments);
+
+			if(this.selectionMode){
+				this.grid.selection.mode = this.selectionMode;
+			}
+			this.connect(this.grid.selection, 'onSelected', 'onSelected');
+			this.connect(this.grid.selection, 'onDeselected', 'onDeselected');
+		},
+		buildRendering: function(){
+			this.inherited(arguments);
+			this.scrollboxNode.style.overflow = "hidden";
+		},	
+		getWidth: function(){
+			return this.viewWidth || this.defaultWidth;
+		},
+		resize: function(){
+			this.adaptHeight();
+		},
+		setStructure: function(s){
+			this.inherited(arguments);
+			if(s.defaultWidth){
+				this.defaultWidth = s.defaultWidth;
+			}
+		},
+		adaptWidth: function(){
+			// Only calculate this here - rather than every call to buildRowContent
+			if(!("contentWidth" in this) && this.contentNode){
+				this.contentWidth = this.contentNode.offsetWidth - this.padBorderWidth;
+			}
+		},
+		// styling
+		doStyleRowNode: function(inRowIndex, inRowNode){
+			var n = [ "dojoxGridRowbar dojoxGridNonNormalizedCell" ];
+			if(this.grid.rows.isOver(inRowIndex)){
+				n.push("dojoxGridRowbarOver");
+			}
+			if(this.grid.selection.isSelected(inRowIndex)){
+				n.push("dojoxGridRowbarSelected");
+			}
+			inRowNode.className = n.join(" ");
+		},
+		// event handlers
+		onSelected: function(inIndex){
+			this.grid.updateRow(inIndex);
+		},
+		onDeselected: function(inIndex){
+			this.grid.updateRow(inIndex);
+		}
+	});
+	if(!dojox.grid._View.prototype._headerBuilderClass &&
+		!dojox.grid._View.prototype._contentBuilderClass){
+		dojox.grid._Selector.prototype.postCreate = function(){
+			this.connect(this.scrollboxNode,"onscroll","doscroll");
+			dojox.grid.util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
+			dojox.grid.util.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
+			if(this._contentBuilderClass){
+				this.content = new this._contentBuilderClass(this);
+			}else{
+				this.content = new dojox.grid._ContentBuilder(this);
+			}
+			if(this._headerBuilderClass){
+				this.header = new this._headerBuilderClass(this);
+			}else{
+				this.header = new dojox.grid._HeaderBuilder(this);
+			}
+			//BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
+			if(!dojo._isBodyLtr()){
+				this.headerNodeContainer.style.width = "";
+			}
+			this.connect(this.grid.selection, 'onSelected', 'onSelected');
+			this.connect(this.grid.selection, 'onDeselected', 'onDeselected');
+		};
+	}
+
+	dojo.declare("dojox.grid._RadioSelector", dojox.grid._Selector, {
+		inputType: 'radio',
+		selectionMode: 'single',
+
+		_contentBuilderClass: dojox.grid._InputSelectorContentBuilder,
+
+		buildRendering: function(){
+			this.inherited(arguments);
+			this.headerNode.style.visibility = "hidden";
+		},
+		
+		renderHeader: function(){}
+	});
+
+	dojo.declare("dojox.grid._CheckBoxSelector", dojox.grid._Selector, {
+		inputType: 'checkbox',
+		_headerBuilderClass: dojox.grid._InputSelectorHeaderBuilder,
+		_contentBuilderClass: dojox.grid._InputSelectorContentBuilder,
+		postCreate: function(){
+			this.inherited(arguments);
+			this.connect(this.grid, 'onSelectionChanged', 'onSelectionChanged');
+			this.connect(this.grid, 'updateRowCount', '_updateVisibility');
+		},
+		renderHeader: function(){
+			this.inherited(arguments);
+			this._updateVisibility(this.grid.rowCount);
+		},
+		_updateVisibility: function(rowCount){
+			this.headerNode.style.visibility = rowCount ? "" : "hidden";		
+		},
+		onSelectionChanged: function(){
+			if(this._selectionChanging){ return; }
+			var inputDiv = dojo.query('.dojoxGridCheckSelector', this.headerNode)[0];
+			var g = this.grid;
+			var s = (g.rowCount && g.rowCount == g.selection.getSelectedCount());
+			g.allItemsSelected = s||false;
+			dojo.toggleClass(inputDiv, "dijitChecked", g.allItemsSelected);
+			dojo.toggleClass(inputDiv, "dijitCheckBoxChecked", g.allItemsSelected);
+		}
+	});
 })();
-}
diff --git a/dojox/grid/_TreeView.js b/dojox/grid/_TreeView.js
index 35bb571..75e764b 100644
--- a/dojox/grid/_TreeView.js
+++ b/dojox/grid/_TreeView.js
@@ -1,408 +1,443 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._TreeView"]){
-dojo._hasResource["dojox.grid._TreeView"]=true;
 dojo.provide("dojox.grid._TreeView");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dojox.grid._View");
-dojo.declare("dojox.grid._Expando",[dijit._Widget,dijit._Templated],{open:false,toggleClass:"",itemId:"",cellIdx:-1,view:null,rowNode:null,rowIdx:-1,expandoCell:null,level:0,templateString:"<div class=\"dojoxGridExpando\"\n\t><div class=\"dojoxGridExpandoNode\" dojoAttachEvent=\"onclick:onToggle\"\n\t\t><div class=\"dojoxGridExpandoNodeInner\" dojoAttachPoint=\"expandoInner\"></div\n\t></div\n></div>\n",_toggleRows:function(_1,_2){
-if(!_1||!this.rowNode){
-return;
-}
-if(dojo.query("table.dojoxGridRowTableNeedsRowUpdate").length){
-if(this._initialized){
-this.view.grid.updateRow(this.rowIdx);
-}
-return;
-}
-var _3=this;
-var g=this.view.grid;
-if(g.treeModel){
-var p=this._tableRow?dojo.attr(this._tableRow,"dojoxTreeGridPath"):"";
-if(p){
-dojo.query("tr[dojoxTreeGridPath^=\""+p+"/\"]",this.rowNode).forEach(function(n){
-var en=dojo.query(".dojoxGridExpando",n)[0];
-if(en&&en.parentNode&&en.parentNode.parentNode&&!dojo.hasClass(en.parentNode.parentNode,"dojoxGridNoChildren")){
-var ew=dijit.byNode(en);
-if(ew){
-ew._toggleRows(_1,ew.open&&_2);
-}
-}
-n.style.display=_2?"":"none";
-});
-}
-}else{
-dojo.query("tr."+_1,this.rowNode).forEach(function(n){
-if(dojo.hasClass(n,"dojoxGridExpandoRow")){
-var en=dojo.query(".dojoxGridExpando",n)[0];
-if(en){
-var ew=dijit.byNode(en);
-var _4=ew?ew.toggleClass:en.getAttribute("toggleClass");
-var _5=ew?ew.open:_3.expandoCell.getOpenState(en.getAttribute("itemId"));
-_3._toggleRows(_4,_5&&_2);
-}
-}
-n.style.display=_2?"":"none";
-});
-}
-},setOpen:function(_6){
-if(_6&&dojo.hasClass(this.domNode,"dojoxGridExpandoLoading")){
-_6=false;
-}
-var _7=this.view;
-var _8=_7.grid;
-var _9=_8.store;
-var _a=_8.treeModel;
-var d=this;
-var _b=this.rowIdx;
-var me=_8._by_idx[_b];
-if(!me){
-return;
-}
-if(_a&&!this._loadedChildren){
-if(_6){
-var _c=_8.getItem(dojo.attr(this._tableRow,"dojoxTreeGridPath"));
-if(_c){
-this.expandoInner.innerHTML="o";
-dojo.addClass(this.domNode,"dojoxGridExpandoLoading");
-_a.getChildren(_c,function(_d){
-d._loadedChildren=true;
-d._setOpen(_6);
-});
-}else{
-this._setOpen(_6);
-}
-}else{
-this._setOpen(_6);
-}
-}else{
-if(!_a&&_9){
-if(_6){
-var _e=_8._by_idx[this.rowIdx];
-if(_e&&!_9.isItemLoaded(_e.item)){
-this.expandoInner.innerHTML="o";
-dojo.addClass(this.domNode,"dojoxGridExpandoLoading");
-_9.loadItem({item:_e.item,onItem:dojo.hitch(this,function(i){
-var _f=_9.getIdentity(i);
-_8._by_idty[_f]=_8._by_idx[this.rowIdx]={idty:_f,item:i};
-this._setOpen(_6);
-})});
-}else{
-this._setOpen(_6);
-}
-}else{
-this._setOpen(_6);
-}
-}else{
-this._setOpen(_6);
-}
-}
-},_setOpen:function(_10){
-if(_10&&this._tableRow&&dojo.hasClass(this._tableRow,"dojoxGridNoChildren")){
-this._setOpen(false);
-return;
-}
-this.expandoInner.innerHTML=_10?"-":"+";
-dojo.removeClass(this.domNode,"dojoxGridExpandoLoading");
-dojo.toggleClass(this.domNode,"dojoxGridExpandoOpened",_10);
-if(this._tableRow){
-dojo.toggleClass(this._tableRow,"dojoxGridRowCollapsed",!_10);
-var _11=dojo.attr(this._tableRow,"dojoxTreeGridBaseClasses");
-var _12="";
-if(_10){
-_12=dojo.trim((" "+_11+" ").replace(" dojoxGridRowCollapsed "," "));
-}else{
-if((" "+_11+" ").indexOf(" dojoxGridRowCollapsed ")<0){
-_12=_11+(_11?" ":"")+"dojoxGridRowCollapsed";
-}else{
-_12=_11;
-}
-}
-dojo.attr(this._tableRow,"dojoxTreeGridBaseClasses",_12);
-}
-var _13=(this.open!==_10);
-this.open=_10;
-if(this.expandoCell&&this.itemId){
-this.expandoCell.openStates[this.itemId]=_10;
-}
-var v=this.view;
-var g=v.grid;
-if(this.toggleClass&&_13){
-if(!this._tableRow||!this._tableRow.style.display){
-this._toggleRows(this.toggleClass,_10);
-}
-}
-if(v&&this._initialized&&this.rowIdx>=0){
-g.rowHeightChanged(this.rowIdx);
-g.postresize();
-v.hasVScrollbar(true);
-}
-this._initialized=true;
-},onToggle:function(e){
-this.setOpen(!this.open);
-dojo.stopEvent(e);
-},setRowNode:function(_14,_15,_16){
-if(this.cellIdx<0||!this.itemId){
-return false;
-}
-this._initialized=false;
-this.view=_16;
-this.rowNode=_15;
-this.rowIdx=_14;
-this.expandoCell=_16.structure.cells[0][this.cellIdx];
-var d=this.domNode;
-if(d&&d.parentNode&&d.parentNode.parentNode){
-this._tableRow=d.parentNode.parentNode;
-}
-this.open=this.expandoCell.getOpenState(this.itemId);
-if(_16.grid.treeModel){
-dojo.style(this.domNode,"marginLeft",(this.level*18)+"px");
-if(this.domNode.parentNode){
-dojo.style(this.domNode.parentNode,"backgroundPosition",((this.level*18)+(3))+"px");
-}
-}
-this.setOpen(this.open);
-return true;
-}});
-dojo.declare("dojox.grid._TreeContentBuilder",dojox.grid._ContentBuilder,{generateHtml:function(_17,_18){
-var _19=this.getTableArray(),v=this.view,row=v.structure.cells[0],_1a=this.grid.getItem(_18),_1b=this.grid,_1c=this.grid.store;
-dojox.grid.util.fire(this.view,"onBeforeRow",[_18,[row]]);
-var _1d=function(_1e,_1f,_20,_21,_22,_23){
-if(!_23){
-if(_19[0].indexOf("dojoxGridRowTableNeedsRowUpdate")==-1){
-_19[0]=_19[0].replace("dojoxGridRowTable","dojoxGridRowTable dojoxGridRowTableNeedsRowUpdate");
-}
-return;
-}
-var _24=_19.length;
-_21=_21||[];
-var _25=_21.join("|");
-var _26=_21[_21.length-1];
-var _27=_26+(_20?" dojoxGridSummaryRow":"");
-var _28="";
-if(_1b.treeModel&&_1f&&!_1b.treeModel.mayHaveChildren(_1f)){
-_27+=" dojoxGridNoChildren";
-}
-_19.push("<tr style=\""+_28+"\" class=\""+_27+"\" dojoxTreeGridPath=\""+_22.join("/")+"\" dojoxTreeGridBaseClasses=\""+_27+"\">");
-var _29=_1e+1;
-var _2a=null;
-for(var i=0,_2b;(_2b=row[i]);i++){
-var m=_2b.markup,cc=_2b.customClasses=[],cs=_2b.customStyles=[];
-m[5]=_2b.formatAtLevel(_22,_1f,_1e,_20,_26,cc);
-m[1]=cc.join(" ");
-m[3]=cs.join(";");
-_19.push.apply(_19,m);
-if(!_2a&&_2b.level===_29&&_2b.parentCell){
-_2a=_2b.parentCell;
-}
-}
-_19.push("</tr>");
-if(_1f&&_1c&&_1c.isItem(_1f)){
-var _2c=_1c.getIdentity(_1f);
-if(typeof _1b._by_idty_paths[_2c]=="undefined"){
-_1b._by_idty_paths[_2c]=_22.join("/");
-}
-}
-var _2d;
-var _2e;
-var _2f;
-var _30;
-var _31=_22.concat([]);
-if(_1b.treeModel&&_1f){
-if(_1b.treeModel.mayHaveChildren(_1f)){
-_2d=v.structure.cells[0][_1b.expandoCell||0];
-_2e=_2d.getOpenState(_1f)&&_23;
-_2f=new dojox.grid.TreePath(_22.join("/"),_1b);
-_30=_2f.children(true)||[];
-dojo.forEach(_30,function(_32,idx){
-var _33=_25.split("|");
-_33.push(_33[_33.length-1]+"-"+idx);
-_31.push(idx);
-_1d(_29,_32,false,_33,_31,_2e);
-_31.pop();
-});
-}
-}else{
-if(_1f&&_2a&&!_20){
-_2d=v.structure.cells[0][_2a.level];
-_2e=_2d.getOpenState(_1f)&&_23;
-if(_1c.hasAttribute(_1f,_2a.field)){
-var _34=_25.split("|");
-_34.pop();
-_2f=new dojox.grid.TreePath(_22.join("/"),_1b);
-_30=_2f.children(true)||[];
-if(_30.length){
-_19[_24]="<tr class=\""+_34.join(" ")+" dojoxGridExpandoRow\" dojoxTreeGridPath=\""+_22.join("/")+"\">";
-dojo.forEach(_30,function(_35,idx){
-var _36=_25.split("|");
-_36.push(_36[_36.length-1]+"-"+idx);
-_31.push(idx);
-_1d(_29,_35,false,_36,_31,_2e);
-_31.pop();
+
+dojo.declare("dojox.grid._Expando", [ dijit._Widget, dijit._Templated ], {
+	open: false,
+	toggleClass: "",
+	itemId: "",
+	cellIdx: -1,
+	view: null,
+	rowNode: null,
+	rowIdx: -1,
+	expandoCell: null,
+	level: 0,
+	templatePath: dojo.moduleUrl("dojox.grid", "resources/Expando.html"),
+	_toggleRows: function(toggleClass, open){
+		if(!toggleClass || !this.rowNode){ return; }
+		if(dojo.query("table.dojoxGridRowTableNeedsRowUpdate").length){
+			if(this._initialized){
+				this.view.grid.updateRow(this.rowIdx);
+			}
+			return;
+		}
+		var self = this;
+		var g = this.view.grid;
+		if(g.treeModel){
+			var p = this._tableRow ? dojo.attr(this._tableRow, "dojoxTreeGridPath") : "";
+			if(p){
+				dojo.query("tr[dojoxTreeGridPath^=\"" + p + "/\"]", this.rowNode).forEach(function(n){
+					var en = dojo.query(".dojoxGridExpando", n)[0];
+					if(en && en.parentNode && en.parentNode.parentNode && 
+								!dojo.hasClass(en.parentNode.parentNode, "dojoxGridNoChildren")){
+						var ew = dijit.byNode(en);
+						if(ew){
+							ew._toggleRows(toggleClass, ew.open&&open);
+						}
+					}
+					n.style.display = open ? "" : "none";
+				});
+			}
+		}else{
+			dojo.query("tr." + toggleClass, this.rowNode).forEach(function(n){
+				if(dojo.hasClass(n, "dojoxGridExpandoRow")){
+					var en = dojo.query(".dojoxGridExpando", n)[0];
+					if(en){
+						var ew = dijit.byNode(en);
+						var toggleClass = ew ? ew.toggleClass : en.getAttribute("toggleClass");
+						var wOpen = ew ? ew.open : self.expandoCell.getOpenState(en.getAttribute("itemId"));
+						self._toggleRows(toggleClass, wOpen&&open);
+					}
+				}
+				n.style.display = open ? "" : "none";
+			});
+		}
+	},
+	setOpen: function(open){
+		if(open && dojo.hasClass(this.domNode, "dojoxGridExpandoLoading")){
+			open = false;
+		}
+		var view = this.view;
+		var grid = view.grid;
+		var store = grid.store;
+		var treeModel = grid.treeModel;
+		var d = this;
+		var idx = this.rowIdx;
+		var me = grid._by_idx[idx];
+		if(!me){ return; }
+		if(treeModel && !this._loadedChildren){
+			if(open){
+				// Do this to make sure our children are fully-loaded
+				var itm = grid.getItem(dojo.attr(this._tableRow, "dojoxTreeGridPath"));
+				if(itm){
+					this.expandoInner.innerHTML = "o";
+					dojo.addClass(this.domNode, "dojoxGridExpandoLoading");
+					treeModel.getChildren(itm, function(items){
+						d._loadedChildren = true;
+						d._setOpen(open);
+					});
+				}else{
+					this._setOpen(open);
+				}
+			}else{
+				this._setOpen(open);
+			}
+		}else if(!treeModel && store){
+			if(open){
+				var data = grid._by_idx[this.rowIdx];
+				if(data&&!store.isItemLoaded(data.item)){
+					this.expandoInner.innerHTML = "o";
+					dojo.addClass(this.domNode, "dojoxGridExpandoLoading");
+					store.loadItem({
+						item: data.item,
+						onItem: dojo.hitch(this, function(i){
+							var idty = store.getIdentity(i);
+							grid._by_idty[idty] = grid._by_idx[this.rowIdx] = { idty: idty, item: i };
+							this._setOpen(open);
+						})
+					});
+				}else{
+					this._setOpen(open);
+				}
+			}else{
+				this._setOpen(open);
+			}
+		}else{
+			this._setOpen(open);
+		}
+	},
+	_setOpen: function(open){
+		if(open && this._tableRow && dojo.hasClass(this._tableRow, "dojoxGridNoChildren")){
+			this._setOpen(false);
+			return;
+		}
+		this.expandoInner.innerHTML = open ? "-" : "+";
+		dojo.removeClass(this.domNode, "dojoxGridExpandoLoading");
+		dojo.toggleClass(this.domNode, "dojoxGridExpandoOpened", open);
+		if(this._tableRow){
+			dojo.toggleClass(this._tableRow, "dojoxGridRowCollapsed", !open);
+			var base = dojo.attr(this._tableRow, "dojoxTreeGridBaseClasses");
+			var new_base = "";
+			if(open){
+				new_base = dojo.trim((" " + base + " ").replace(" dojoxGridRowCollapsed ", " "));
+			}else{
+				if((" " + base + " ").indexOf(' dojoxGridRowCollapsed ') < 0){
+					new_base = base + (base ? ' ' : '' ) + 'dojoxGridRowCollapsed';
+				}else{
+					new_base = base;
+				}
+			}
+			dojo.attr(this._tableRow, 'dojoxTreeGridBaseClasses', new_base);
+		}
+		var changed = (this.open !== open);
+		this.open = open;
+		if(this.expandoCell && this.itemId){
+			this.expandoCell.openStates[this.itemId] = open;
+		}
+		var v = this.view;
+		var g = v.grid;
+		if(this.toggleClass && changed){
+			if(!this._tableRow || !this._tableRow.style.display){
+				this._toggleRows(this.toggleClass, open);
+			}
+		}
+		if(v && this._initialized && this.rowIdx >= 0){
+			g.rowHeightChanged(this.rowIdx);
+			g.postresize();
+			v.hasVScrollbar(true);
+		}
+		this._initialized = true;
+	},
+	onToggle: function(e){
+		this.setOpen(!this.open);
+		dojo.stopEvent(e);
+	},
+	setRowNode: function(rowIdx, rowNode, view){
+		if(this.cellIdx < 0 || !this.itemId){ return false; }
+		this._initialized = false;
+		this.view = view;
+		this.rowNode = rowNode;
+		this.rowIdx = rowIdx;
+		this.expandoCell = view.structure.cells[0][this.cellIdx];
+		var d = this.domNode;
+		if(d && d.parentNode && d.parentNode.parentNode){
+			this._tableRow = d.parentNode.parentNode;
+		}
+		this.open = this.expandoCell.getOpenState(this.itemId);
+		if(view.grid.treeModel){
+			// TODO: Rather than hard-code the 18px and 3px, we should probably
+			// calculate them based off css or something...  However, all the 
+			// themes that we support use these values.
+			dojo.style(this.domNode , "marginLeft" , (this.level * 18) + "px");
+			if(this.domNode.parentNode){
+				dojo.style(this.domNode.parentNode, "backgroundPosition", ((this.level * 18) + (3)) + "px");
+			}
+		}
+		this.setOpen(this.open);
+		return true;
+	}
 });
-_31.push(_30.length);
-_1d(_1e,_1f,true,_21,_31,_2e);
-}else{
-_19[_24]="<tr class=\""+_26+" dojoxGridNoChildren\" dojoxTreeGridPath=\""+_22.join("/")+"\">";
-}
-}else{
-if(!_1c.isItemLoaded(_1f)){
-_19[0]=_19[0].replace("dojoxGridRowTable","dojoxGridRowTable dojoxGridRowTableNeedsRowUpdate");
-}else{
-_19[_24]="<tr class=\""+_26+" dojoxGridNoChildren\" dojoxTreeGridPath=\""+_22.join("/")+"\">";
-}
-}
-}else{
-if(_1f&&!_20&&_21.length>1){
-_19[_24]="<tr class=\""+_21[_21.length-2]+"\" dojoxTreeGridPath=\""+_22.join("/")+"\">";
-}
-}
-}
-};
-_1d(0,_1a,false,["dojoxGridRowToggle-"+_18],[_18],true);
-_19.push("</table>");
-return _19.join("");
-},findTarget:function(_37,_38){
-var n=_37;
-while(n&&(n!=this.domNode)){
-if(n.tagName&&n.tagName.toLowerCase()=="tr"){
-break;
-}
-n=n.parentNode;
-}
-return (n!=this.domNode)?n:null;
-},getCellNode:function(_39,_3a){
-var _3b=dojo.query("td[idx='"+_3a+"']",_39)[0];
-if(_3b&&_3b.parentNode&&!dojo.hasClass(_3b.parentNode,"dojoxGridSummaryRow")){
-return _3b;
-}
-},decorateEvent:function(e){
-e.rowNode=this.findRowTarget(e.target);
-if(!e.rowNode){
-return false;
-}
-e.rowIndex=dojo.attr(e.rowNode,"dojoxTreeGridPath");
-this.baseDecorateEvent(e);
-e.cell=this.grid.getCell(e.cellIndex);
-return true;
-}});
-dojo.declare("dojox.grid._TreeView",[dojox.grid._View],{_contentBuilderClass:dojox.grid._TreeContentBuilder,_onDndDrop:function(_3c,_3d,_3e){
-if(this.grid&&this.grid.aggregator){
-this.grid.aggregator.clearSubtotalCache();
-}
-this.inherited(arguments);
-},postCreate:function(){
-this.inherited(arguments);
-this.connect(this.grid,"_cleanupExpandoCache","_cleanupExpandoCache");
-},_cleanupExpandoCache:function(_3f,_40,_41){
-if(_3f==-1){
-return;
-}
-dojo.forEach(this.grid.layout.cells,function(_42){
-if(typeof _42["openStates"]!="undefined"){
-if(_40 in _42.openStates){
-delete _42.openStates[_40];
-}
-}
+
+dojo.declare("dojox.grid._TreeContentBuilder", dojox.grid._ContentBuilder, {
+	generateHtml: function(inDataIndex, inRowIndex){
+		var
+			html = this.getTableArray(),
+			v = this.view,
+			row = v.structure.cells[0],
+			item = this.grid.getItem(inRowIndex),
+			grid = this.grid,
+			store = this.grid.store;
+
+		dojox.grid.util.fire(this.view, "onBeforeRow", [inRowIndex, [row]]);
+		
+		var createRow = function(level, rowItem, summaryRow, toggleClasses, rowStack, shown){
+			if(!shown){
+				if(html[0].indexOf('dojoxGridRowTableNeedsRowUpdate') == -1){
+					html[0] = html[0].replace("dojoxGridRowTable", "dojoxGridRowTable dojoxGridRowTableNeedsRowUpdate");
+				}
+				return; 
+			}
+			var rowNodeIdx = html.length;
+			toggleClasses = toggleClasses || [];
+			var tcJoin = toggleClasses.join('|');
+			var tcString = toggleClasses[toggleClasses.length - 1];
+			var clString = tcString + (summaryRow ? " dojoxGridSummaryRow" : "");
+			var sString = "";
+			if(grid.treeModel && rowItem && !grid.treeModel.mayHaveChildren(rowItem)){
+				clString += " dojoxGridNoChildren";
+			}
+			html.push('<tr style="' + sString + '" class="' + clString + '" dojoxTreeGridPath="' + rowStack.join('/') +  '" dojoxTreeGridBaseClasses="' + clString + '">');
+			var nextLevel = level + 1;
+			var parentCell = null;
+			for(var i=0, cell; (cell=row[i]); i++){
+				var m = cell.markup, cc = cell.customClasses = [], cs = cell.customStyles = [];
+				// content (format can fill in cc and cs as side-effects)
+				m[5] = cell.formatAtLevel(rowStack, rowItem, level, summaryRow, tcString, cc);
+				// classes
+				m[1] = cc.join(' ');
+				// styles
+				m[3] = cs.join(';');
+				// in-place concat
+				html.push.apply(html, m);
+				if(!parentCell && cell.level === nextLevel && cell.parentCell){
+					parentCell = cell.parentCell;
+				}
+			}
+			html.push('</tr>');
+			if(rowItem && store && store.isItem(rowItem)){
+				var idty = store.getIdentity(rowItem);
+				if(typeof grid._by_idty_paths[idty] == "undefined"){
+					grid._by_idty_paths[idty] = rowStack.join('/');
+				}
+			}
+			var expandoCell;
+			var parentOpen;
+			var path;
+			var values;
+			var iStack = rowStack.concat([]);
+			if(grid.treeModel && rowItem){
+				if(grid.treeModel.mayHaveChildren(rowItem)){
+					expandoCell = v.structure.cells[0][grid.expandoCell||0];
+					parentOpen = expandoCell.getOpenState(rowItem) && shown;
+					path = new dojox.grid.TreePath(rowStack.join('/'), grid);
+					values = path.children(true)||[];
+					dojo.forEach(values, function(cItm, idx){
+						var nToggle = tcJoin.split('|');
+						nToggle.push(nToggle[nToggle.length - 1] + "-" + idx);
+						iStack.push(idx);
+						createRow(nextLevel, cItm, false, nToggle, iStack, parentOpen);
+						iStack.pop();
+					});
+				}
+			}else if(rowItem && parentCell && !summaryRow){
+				expandoCell = v.structure.cells[0][parentCell.level];
+				parentOpen = expandoCell.getOpenState(rowItem) && shown;
+				if(store.hasAttribute(rowItem, parentCell.field)){
+					var tToggle = tcJoin.split('|');
+					tToggle.pop();
+					path = new dojox.grid.TreePath(rowStack.join('/'), grid);
+					values = path.children(true)||[];
+					if(values.length){
+						html[rowNodeIdx] = '<tr class="' + tToggle.join(' ') +' dojoxGridExpandoRow" dojoxTreeGridPath="' + rowStack.join('/') + '">';
+						dojo.forEach(values, function(cItm, idx){
+							var nToggle = tcJoin.split('|');
+							nToggle.push(nToggle[nToggle.length - 1] + "-" + idx);
+							iStack.push(idx);
+							createRow(nextLevel, cItm, false, nToggle, iStack, parentOpen);
+							iStack.pop();
+						});
+						iStack.push(values.length);
+						createRow(level, rowItem, true, toggleClasses, iStack, parentOpen);
+					}else{
+						html[rowNodeIdx] = '<tr class="' + tcString + ' dojoxGridNoChildren" dojoxTreeGridPath="' + rowStack.join('/') + '">';					
+					}
+				}else{
+					if(!store.isItemLoaded(rowItem)){
+						html[0] = html[0].replace("dojoxGridRowTable", "dojoxGridRowTable dojoxGridRowTableNeedsRowUpdate");
+					}else{
+						html[rowNodeIdx] = '<tr class="' + tcString + ' dojoxGridNoChildren" dojoxTreeGridPath="' + rowStack.join('/') + '">';
+					}
+				}
+			}else if(rowItem && !summaryRow && toggleClasses.length > 1){
+				html[rowNodeIdx] = '<tr class="' + toggleClasses[toggleClasses.length - 2] + '" dojoxTreeGridPath="' + rowStack.join('/') + '">';
+			}
+		};
+		createRow(0, item, false, ["dojoxGridRowToggle-" + inRowIndex], [inRowIndex], true);
+		html.push('</table>');
+		return html.join(''); // String
+	},
+	findTarget: function(inSource, inTag){
+		var n = inSource;
+		while(n && (n!=this.domNode)){
+			if(n.tagName && n.tagName.toLowerCase() == 'tr'){
+				break;
+			}
+			n = n.parentNode;
+		}
+		return (n != this.domNode) ? n : null; 
+	},
+	getCellNode: function(inRowNode, inCellIndex){
+		var node = dojo.query("td[idx='" + inCellIndex + "']", inRowNode)[0];
+		if(node&&node.parentNode&&!dojo.hasClass(node.parentNode, "dojoxGridSummaryRow")){
+			return node;
+		}
+	},
+	decorateEvent: function(e){
+		e.rowNode = this.findRowTarget(e.target);
+		if(!e.rowNode){return false;}
+		e.rowIndex = dojo.attr(e.rowNode, 'dojoxTreeGridPath');
+		this.baseDecorateEvent(e);
+		e.cell = this.grid.getCell(e.cellIndex);
+		return true; // Boolean
+	}
 });
-if(typeof _3f=="string"&&_3f.indexOf("/")>-1){
-var _43=new dojox.grid.TreePath(_3f,this.grid);
-var _44=_43.parent();
-while(_44){
-_43=_44;
-_44=_43.parent();
-}
-var _45=_43.item();
-if(!_45){
-return;
-}
-var _46=this.grid.store.getIdentity(_45);
-if(typeof this._expandos[_46]!="undefined"){
-for(var i in this._expandos[_46]){
-var exp=this._expandos[_46][i];
-if(exp){
-exp.destroy();
-}
-delete this._expandos[_46][i];
-}
-delete this._expandos[_46];
-}
-}else{
-for(var i in this._expandos){
-if(typeof this._expandos[i]!="undefined"){
-for(var j in this._expandos[i]){
-var exp=this._expandos[i][j];
-if(exp){
-exp.destroy();
-}
-}
-}
-}
-this._expandos={};
-}
-},postMixInProperties:function(){
-this.inherited(arguments);
-this._expandos={};
-},onBeforeRow:function(_47,_48){
-var g=this.grid;
-if(g._by_idx&&g._by_idx[_47]&&g._by_idx[_47].idty){
-var _49=g._by_idx[_47].idty;
-this._expandos[_49]=this._expandos[_49]||{};
-}
-this.inherited(arguments);
-},onAfterRow:function(_4a,_4b,_4c){
-dojo.forEach(dojo.query("span.dojoxGridExpando",_4c),function(n){
-if(n&&n.parentNode){
-var tc=n.getAttribute("toggleClass");
-var _4d;
-var _4e;
-var g=this.grid;
-if(g._by_idx&&g._by_idx[_4a]&&g._by_idx[_4a].idty){
-_4d=g._by_idx[_4a].idty;
-_4e=this._expandos[_4d][tc];
-}
-if(_4e){
-dojo.place(_4e.domNode,n,"replace");
-_4e.itemId=n.getAttribute("itemId");
-_4e.cellIdx=parseInt(n.getAttribute("cellIdx"),10);
-if(isNaN(_4e.cellIdx)){
-_4e.cellIdx=-1;
-}
-}else{
-_4e=dojo.parser.parse(n.parentNode)[0];
-if(_4d){
-this._expandos[_4d][tc]=_4e;
-}
-}
-if(!_4e.setRowNode(_4a,_4c,this)){
-_4e.domNode.parentNode.removeChild(_4e.domNode);
-}
-}
-},this);
-var alt=false;
-var _4f=this;
-dojo.query("tr[dojoxTreeGridPath]",_4c).forEach(function(n){
-dojo.toggleClass(n,"dojoxGridSubRowAlt",alt);
-dojo.attr(n,"dojoxTreeGridBaseClasses",n.className);
-alt=!alt;
-_4f.grid.rows.styleRowNode(dojo.attr(n,"dojoxTreeGridPath"),n);
+
+dojo.declare("dojox.grid._TreeView", [dojox.grid._View], {
+	_contentBuilderClass: dojox.grid._TreeContentBuilder,
+	_onDndDrop: function(source, nodes, copy){
+		if(this.grid && this.grid.aggregator){
+			this.grid.aggregator.clearSubtotalCache();
+		}
+		this.inherited(arguments);
+	},
+	postCreate: function(){
+		this.inherited(arguments);
+		this.connect(this.grid, '_cleanupExpandoCache', '_cleanupExpandoCache');
+	},
+	_cleanupExpandoCache: function(index, identity, item){
+		if(index == -1){
+			return;
+		}
+		dojo.forEach(this.grid.layout.cells, function(cell){
+			if(typeof cell['openStates'] != 'undefined'){
+				if(identity in cell.openStates){
+					delete cell.openStates[identity];
+				}
+			}
+		});
+		if(typeof index == "string" && index.indexOf('/') > -1){
+			var path = new dojox.grid.TreePath(index, this.grid);
+			var ppath = path.parent();
+			while(ppath){
+				path = ppath;
+				ppath = path.parent();
+			}
+			var pitem = path.item();
+			if(!pitem){
+				return;
+			}
+			var idty = this.grid.store.getIdentity(pitem);
+			if(typeof this._expandos[idty] != 'undefined'){
+				for(var i in this._expandos[idty]){
+					var exp = this._expandos[idty][i];
+					if(exp){
+						exp.destroy();
+					}
+					delete this._expandos[idty][i];
+				}
+				delete this._expandos[idty];
+			}
+		}else{
+			for(var i in this._expandos){
+				if(typeof this._expandos[i] != 'undefined'){
+					for(var j in this._expandos[i]){
+						var exp = this._expandos[i][j];
+						if(exp){
+							exp.destroy();
+						}
+					}
+				}
+			}
+			this._expandos = {};
+		}
+	},
+	postMixInProperties: function(){
+		this.inherited(arguments);
+		this._expandos = {};
+	},
+	onBeforeRow: function(inRowIndex, cells){
+		// Save off our expando if we have one so we don't have to create it
+		// again
+		var g = this.grid;
+		if(g._by_idx && g._by_idx[inRowIndex] && g._by_idx[inRowIndex].idty){
+			var idty = g._by_idx[inRowIndex].idty;
+			this._expandos[idty] = this._expandos[idty] || {};
+		}
+		this.inherited(arguments);
+	},
+	onAfterRow: function(inRowIndex, cells, inRowNode){
+		dojo.forEach(dojo.query("span.dojoxGridExpando", inRowNode), function(n){
+			if(n && n.parentNode){
+				// Either create our expando or put the existing expando back
+				// into place
+				var tc = n.getAttribute("toggleClass");
+				var idty;
+				var expando;
+				var g = this.grid;
+				if(g._by_idx && g._by_idx[inRowIndex] && g._by_idx[inRowIndex].idty){
+					idty = g._by_idx[inRowIndex].idty;
+					expando = this._expandos[idty][tc];
+				}
+				if(expando){
+					dojo.place(expando.domNode, n, "replace");
+					expando.itemId = n.getAttribute("itemId");
+					expando.cellIdx = parseInt(n.getAttribute("cellIdx"), 10);
+					if(isNaN(expando.cellIdx)){
+						expando.cellIdx = -1;
+					}
+				}else{
+					expando = dojo.parser.parse(n.parentNode)[0];
+					if(idty){
+						this._expandos[idty][tc] = expando;
+					}
+				}
+				if(!expando.setRowNode(inRowIndex, inRowNode, this)){
+					expando.domNode.parentNode.removeChild(expando.domNode);
+				}
+			}
+		}, this);
+		var alt = false;
+		var self = this;
+		dojo.query("tr[dojoxTreeGridPath]", inRowNode).forEach(function(n){
+			dojo.toggleClass(n, "dojoxGridSubRowAlt", alt);
+			dojo.attr(n, "dojoxTreeGridBaseClasses", n.className);
+			alt = !alt;
+			self.grid.rows.styleRowNode(dojo.attr(n, 'dojoxTreeGridPath'), n);
+		});
+		this.inherited(arguments);
+	},
+	updateRowStyles: function(inRowIndex){
+		var rowNodes = dojo.query("tr[dojoxTreeGridPath='" + inRowIndex + "']", this.domNode);
+		if(rowNodes.length){
+			this.styleRowNode(inRowIndex, rowNodes[0]);
+		}
+	},
+	getCellNode: function(inRowIndex, inCellIndex){
+		var row = dojo.query("tr[dojoxTreeGridPath='" + inRowIndex + "']", this.domNode)[0];
+		if(row){
+			return this.content.getCellNode(row, inCellIndex);
+		}
+	}
 });
-this.inherited(arguments);
-},updateRowStyles:function(_50){
-var _51=dojo.query("tr[dojoxTreeGridPath='"+_50+"']",this.domNode);
-if(_51.length){
-this.styleRowNode(_50,_51[0]);
-}
-},getCellNode:function(_52,_53){
-var row=dojo.query("tr[dojoxTreeGridPath='"+_52+"']",this.domNode)[0];
-if(row){
-return this.content.getCellNode(row,_53);
-}
-}});
-}
diff --git a/dojox/grid/_View.js b/dojox/grid/_View.js
index 83f1c81..a5a407c 100644
--- a/dojox/grid/_View.js
+++ b/dojox/grid/_View.js
@@ -1,616 +1,833 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid._View"]){
-dojo._hasResource["dojox.grid._View"]=true;
 dojo.provide("dojox.grid._View");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dojox.grid._Builder");
 dojo.require("dojox.html.metrics");
 dojo.require("dojox.grid.util");
+
 dojo.require("dojo.dnd.Source");
 dojo.require("dojo.dnd.Manager");
+
 (function(){
-var _1=function(_2,_3){
-return _2.style.cssText==undefined?_2.getAttribute("style"):_2.style.cssText;
-};
-dojo.declare("dojox.grid._View",[dijit._Widget,dijit._Templated],{defaultWidth:"18em",viewWidth:"",templateString:"<div class=\"dojoxGridView\" wairole=\"presentation\">\n\t<div class=\"dojoxGridHeader\" dojoAttachPoint=\"headerNode\" wairole=\"presentation\">\n\t\t<div dojoAttachPoint=\"headerNodeContainer\" style=\"width:9000em\" wairole=\"presentation\">\n\t\t\t<div dojoAttachPoint=\"headerContentNode\" wairole=\"row\"></div>\n\t\t</div>\n\t</div>\n\t<input type=\"checkbox\" class=\"d [...]
-this.rowNodes={};
-},postCreate:function(){
-this.connect(this.scrollboxNode,"onscroll","doscroll");
-dojox.grid.util.funnelEvents(this.contentNode,this,"doContentEvent",["mouseover","mouseout","click","dblclick","contextmenu","mousedown"]);
-dojox.grid.util.funnelEvents(this.headerNode,this,"doHeaderEvent",["dblclick","mouseover","mouseout","mousemove","mousedown","click","contextmenu"]);
-this.content=new this._contentBuilderClass(this);
-this.header=new this._headerBuilderClass(this);
-if(!dojo._isBodyLtr()){
-this.headerNodeContainer.style.width="";
-}
-},destroy:function(){
-dojo.destroy(this.headerNode);
-delete this.headerNode;
-for(var i in this.rowNodes){
-dojo.destroy(this.rowNodes[i]);
-}
-this.rowNodes={};
-if(this.source){
-this.source.destroy();
-}
-this.inherited(arguments);
-},focus:function(){
-if(dojo.isIE||dojo.isWebKit||dojo.isOpera){
-this.hiddenFocusNode.focus();
-}else{
-this.scrollboxNode.focus();
-}
-},setStructure:function(_4){
-var vs=(this.structure=_4);
-if(vs.width&&!isNaN(vs.width)){
-this.viewWidth=vs.width+"em";
-}else{
-this.viewWidth=vs.width||(vs.noscroll?"auto":this.viewWidth);
-}
-this._onBeforeRow=vs.onBeforeRow||function(){
-};
-this._onAfterRow=vs.onAfterRow||function(){
-};
-this.noscroll=vs.noscroll;
-if(this.noscroll){
-this.scrollboxNode.style.overflow="hidden";
-}
-this.simpleStructure=Boolean(vs.cells.length==1);
-this.testFlexCells();
-this.updateStructure();
-},_cleanupRowWidgets:function(_5){
-if(_5){
-dojo.forEach(dojo.query("[widgetId]",_5).map(dijit.byNode),function(w){
-if(w._destroyOnRemove){
-w.destroy();
-delete w;
-}else{
-if(w.domNode&&w.domNode.parentNode){
-w.domNode.parentNode.removeChild(w.domNode);
-}
-}
-});
-}
-},onBeforeRow:function(_6,_7){
-this._onBeforeRow(_6,_7);
-if(_6>=0){
-this._cleanupRowWidgets(this.getRowNode(_6));
-}
-},onAfterRow:function(_8,_9,_a){
-this._onAfterRow(_8,_9,_a);
-var g=this.grid;
-dojo.forEach(dojo.query(".dojoxGridStubNode",_a),function(n){
-if(n&&n.parentNode){
-var lw=n.getAttribute("linkWidget");
-var _b=window.parseInt(dojo.attr(n,"cellIdx"),10);
-var _c=g.getCell(_b);
-var w=dijit.byId(lw);
-if(w){
-n.parentNode.replaceChild(w.domNode,n);
-if(!w._started){
-w.startup();
-}
-}else{
-n.innerHTML="";
-}
-}
-},this);
-},testFlexCells:function(){
-this.flexCells=false;
-for(var j=0,_d;(_d=this.structure.cells[j]);j++){
-for(var i=0,_e;(_e=_d[i]);i++){
-_e.view=this;
-this.flexCells=this.flexCells||_e.isFlex();
-}
-}
-return this.flexCells;
-},updateStructure:function(){
-this.header.update();
-this.content.update();
-},getScrollbarWidth:function(){
-var _f=this.hasVScrollbar();
-var _10=dojo.style(this.scrollboxNode,"overflow");
-if(this.noscroll||!_10||_10=="hidden"){
-_f=false;
-}else{
-if(_10=="scroll"){
-_f=true;
-}
-}
-return (_f?dojox.html.metrics.getScrollbar().w:0);
-},getColumnsWidth:function(){
-var h=this.headerContentNode;
-return h&&h.firstChild?h.firstChild.offsetWidth:0;
-},setColumnsWidth:function(_11){
-this.headerContentNode.firstChild.style.width=_11+"px";
-if(this.viewWidth){
-this.viewWidth=_11+"px";
-}
-},getWidth:function(){
-return this.viewWidth||(this.getColumnsWidth()+this.getScrollbarWidth())+"px";
-},getContentWidth:function(){
-return Math.max(0,dojo._getContentBox(this.domNode).w-this.getScrollbarWidth())+"px";
-},render:function(){
-this.scrollboxNode.style.height="";
-this.renderHeader();
-if(this._togglingColumn>=0){
-this.setColumnsWidth(this.getColumnsWidth()-this._togglingColumn);
-this._togglingColumn=-1;
-}
-var _12=this.grid.layout.cells;
-var _13=dojo.hitch(this,function(_14,_15){
-var inc=_15?-1:1;
-var idx=this.header.getCellNodeIndex(_14)+inc;
-var _16=_12[idx];
-while(_16&&_16.getHeaderNode()&&_16.getHeaderNode().style.display=="none"){
-idx+=inc;
-_16=_12[idx];
-}
-if(_16){
-return _16.getHeaderNode();
-}
-return null;
-});
-if(this.grid.columnReordering&&this.simpleStructure){
-if(this.source){
-this.source.destroy();
-}
-var _17="dojoxGrid_bottomMarker";
-var _18="dojoxGrid_topMarker";
-if(this.bottomMarker){
-dojo.destroy(this.bottomMarker);
-}
-this.bottomMarker=dojo.byId(_17);
-if(this.topMarker){
-dojo.destroy(this.topMarker);
-}
-this.topMarker=dojo.byId(_18);
-if(!this.bottomMarker){
-this.bottomMarker=dojo.create("div",{"id":_17,"class":"dojoxGridColPlaceBottom"},dojo.body());
-this._hide(this.bottomMarker);
-this.topMarker=dojo.create("div",{"id":_18,"class":"dojoxGridColPlaceTop"},dojo.body());
-this._hide(this.topMarker);
-}
-this.arrowDim=dojo.contentBox(this.bottomMarker);
-var _19=dojo.contentBox(this.headerContentNode.firstChild.rows[0]).h;
-this.source=new dojo.dnd.Source(this.headerContentNode.firstChild.rows[0],{horizontal:true,accept:["gridColumn_"+this.grid.id],viewIndex:this.index,generateText:false,onMouseDown:dojo.hitch(this,function(e){
-this.header.decorateEvent(e);
-if((this.header.overRightResizeArea(e)||this.header.overLeftResizeArea(e))&&this.header.canResize(e)&&!this.header.moveable){
-this.header.beginColumnResize(e);
-}else{
-if(this.grid.headerMenu){
-this.grid.headerMenu.onCancel(true);
-}
-if(e.button===(dojo.isIE?1:0)){
-dojo.dnd.Source.prototype.onMouseDown.call(this.source,e);
-}
-}
-}),onMouseOver:dojo.hitch(this,function(e){
-var src=this.source;
-if(src._getChildByEvent(e)){
-dojo.dnd.Source.prototype.onMouseOver.apply(src,arguments);
-}
-}),_markTargetAnchor:dojo.hitch(this,function(_1a){
-var src=this.source;
-if(src.current==src.targetAnchor&&src.before==_1a){
-return;
-}
-if(src.targetAnchor&&_13(src.targetAnchor,src.before)){
-src._removeItemClass(_13(src.targetAnchor,src.before),src.before?"After":"Before");
-}
-dojo.dnd.Source.prototype._markTargetAnchor.call(src,_1a);
-var _1b=_1a?src.targetAnchor:_13(src.targetAnchor,src.before);
-var _1c=0;
-if(!_1b){
-_1b=src.targetAnchor;
-_1c=dojo.contentBox(_1b).w+this.arrowDim.w/2+2;
-}
-var pos=(dojo.position||dojo._abs)(_1b,true);
-var _1d=Math.floor(pos.x-this.arrowDim.w/2+_1c);
-dojo.style(this.bottomMarker,"visibility","visible");
-dojo.style(this.topMarker,"visibility","visible");
-dojo.style(this.bottomMarker,{"left":_1d+"px","top":(_19+pos.y)+"px"});
-dojo.style(this.topMarker,{"left":_1d+"px","top":(pos.y-this.arrowDim.h)+"px"});
-if(src.targetAnchor&&_13(src.targetAnchor,src.before)){
-src._addItemClass(_13(src.targetAnchor,src.before),src.before?"After":"Before");
-}
-}),_unmarkTargetAnchor:dojo.hitch(this,function(){
-var src=this.source;
-if(!src.targetAnchor){
-return;
-}
-if(src.targetAnchor&&_13(src.targetAnchor,src.before)){
-src._removeItemClass(_13(src.targetAnchor,src.before),src.before?"After":"Before");
-}
-this._hide(this.bottomMarker);
-this._hide(this.topMarker);
-dojo.dnd.Source.prototype._unmarkTargetAnchor.call(src);
-}),destroy:dojo.hitch(this,function(){
-dojo.disconnect(this._source_conn);
-dojo.unsubscribe(this._source_sub);
-dojo.dnd.Source.prototype.destroy.call(this.source);
-if(this.bottomMarker){
-dojo.destroy(this.bottomMarker);
-delete this.bottomMarker;
-}
-if(this.topMarker){
-dojo.destroy(this.topMarker);
-delete this.topMarker;
-}
-}),onDndCancel:dojo.hitch(this,function(){
-dojo.dnd.Source.prototype.onDndCancel.call(this.source);
-this._hide(this.bottomMarker);
-this._hide(this.topMarker);
-})});
-this._source_conn=dojo.connect(this.source,"onDndDrop",this,"_onDndDrop");
-this._source_sub=dojo.subscribe("/dnd/drop/before",this,"_onDndDropBefore");
-this.source.startup();
-}
-},_hide:function(_1e){
-dojo.style(_1e,{left:"-10000px",top:"-10000px","visibility":"hidden"});
-},_onDndDropBefore:function(_1f,_20,_21){
-if(dojo.dnd.manager().target!==this.source){
-return;
-}
-this.source._targetNode=this.source.targetAnchor;
-this.source._beforeTarget=this.source.before;
-var _22=this.grid.views.views;
-var _23=_22[_1f.viewIndex];
-var _24=_22[this.index];
-if(_24!=_23){
-_23.convertColPctToFixed();
-_24.convertColPctToFixed();
-}
-},_onDndDrop:function(_25,_26,_27){
-if(dojo.dnd.manager().target!==this.source){
-if(dojo.dnd.manager().source===this.source){
-this._removingColumn=true;
-}
-return;
-}
-this._hide(this.bottomMarker);
-this._hide(this.topMarker);
-var _28=function(n){
-return n?dojo.attr(n,"idx"):null;
-};
-var w=dojo.marginBox(_26[0]).w;
-if(_25.viewIndex!==this.index){
-var _29=this.grid.views.views;
-var _2a=_29[_25.viewIndex];
-var _2b=_29[this.index];
-if(_2a.viewWidth&&_2a.viewWidth!="auto"){
-_2a.setColumnsWidth(_2a.getColumnsWidth()-w);
-}
-if(_2b.viewWidth&&_2b.viewWidth!="auto"){
-_2b.setColumnsWidth(_2b.getColumnsWidth());
-}
-}
-var stn=this.source._targetNode;
-var stb=this.source._beforeTarget;
-var _2c=this.grid.layout;
-var idx=this.index;
-delete this.source._targetNode;
-delete this.source._beforeTarget;
-_2c.moveColumn(_25.viewIndex,idx,_28(_26[0]),_28(stn),stb);
-},renderHeader:function(){
-this.headerContentNode.innerHTML=this.header.generateHtml(this._getHeaderContent);
-if(this.flexCells){
-this.contentWidth=this.getContentWidth();
-this.headerContentNode.firstChild.style.width=this.contentWidth;
-}
-dojox.grid.util.fire(this,"onAfterRow",[-1,this.structure.cells,this.headerContentNode]);
-},_getHeaderContent:function(_2d){
-var n=_2d.name||_2d.grid.getCellName(_2d);
-var ret=["<div class=\"dojoxGridSortNode"];
-if(_2d.index!=_2d.grid.getSortIndex()){
-ret.push("\">");
-}else{
-ret=ret.concat([" ",_2d.grid.sortInfo>0?"dojoxGridSortUp":"dojoxGridSortDown","\"><div class=\"dojoxGridArrowButtonChar\">",_2d.grid.sortInfo>0?"▲":"▼","</div><div class=\"dojoxGridArrowButtonNode\" role=\"presentation\"></div>"]);
-}
-ret=ret.concat([n,"</div>"]);
-return ret.join("");
-},resize:function(){
-this.adaptHeight();
-this.adaptWidth();
-},hasHScrollbar:function(_2e){
-var _2f=this._hasHScroll||false;
-if(this._hasHScroll==undefined||_2e){
-if(this.noscroll){
-this._hasHScroll=false;
-}else{
-var _30=dojo.style(this.scrollboxNode,"overflow");
-if(_30=="hidden"){
-this._hasHScroll=false;
-}else{
-if(_30=="scroll"){
-this._hasHScroll=true;
-}else{
-this._hasHScroll=(this.scrollboxNode.offsetWidth-this.getScrollbarWidth()<this.contentNode.offsetWidth);
-}
-}
-}
-}
-if(_2f!==this._hasHScroll){
-this.grid.update();
-}
-return this._hasHScroll;
-},hasVScrollbar:function(_31){
-var _32=this._hasVScroll||false;
-if(this._hasVScroll==undefined||_31){
-if(this.noscroll){
-this._hasVScroll=false;
-}else{
-var _33=dojo.style(this.scrollboxNode,"overflow");
-if(_33=="hidden"){
-this._hasVScroll=false;
-}else{
-if(_33=="scroll"){
-this._hasVScroll=true;
-}else{
-this._hasVScroll=(this.scrollboxNode.scrollHeight>this.scrollboxNode.clientHeight);
-}
-}
-}
-}
-if(_32!==this._hasVScroll){
-this.grid.update();
-}
-return this._hasVScroll;
-},convertColPctToFixed:function(){
-var _34=false;
-this.grid.initialWidth="";
-var _35=dojo.query("th",this.headerContentNode);
-var _36=dojo.map(_35,function(c,_37){
-var w=c.style.width;
-dojo.attr(c,"vIdx",_37);
-if(w&&w.slice(-1)=="%"){
-_34=true;
-}else{
-if(w&&w.slice(-2)=="px"){
-return window.parseInt(w,10);
-}
-}
-return dojo.contentBox(c).w;
-});
-if(_34){
-dojo.forEach(this.grid.layout.cells,function(_38,idx){
-if(_38.view==this){
-var _39=_38.view.getHeaderCellNode(_38.index);
-if(_39&&dojo.hasAttr(_39,"vIdx")){
-var _3a=window.parseInt(dojo.attr(_39,"vIdx"));
-this.setColWidth(idx,_36[_3a]);
-dojo.removeAttr(_39,"vIdx");
-}
-}
-},this);
-return true;
-}
-return false;
-},adaptHeight:function(_3b){
-if(!this.grid._autoHeight){
-var h=(this.domNode.style.height&&parseInt(this.domNode.style.height.replace(/px/,""),10))||this.domNode.clientHeight;
-var _3c=this;
-var _3d=function(){
-var v;
-for(var i in _3c.grid.views.views){
-v=_3c.grid.views.views[i];
-if(v!==_3c&&v.hasHScrollbar()){
-return true;
-}
-}
-return false;
-};
-if(_3b||(this.noscroll&&_3d())){
-h-=dojox.html.metrics.getScrollbar().h;
-}
-dojox.grid.util.setStyleHeightPx(this.scrollboxNode,h);
-}
-this.hasVScrollbar(true);
-},adaptWidth:function(){
-if(this.flexCells){
-this.contentWidth=this.getContentWidth();
-this.headerContentNode.firstChild.style.width=this.contentWidth;
-}
-var w=this.scrollboxNode.offsetWidth-this.getScrollbarWidth();
-if(!this._removingColumn){
-w=Math.max(w,this.getColumnsWidth())+"px";
-}else{
-w=Math.min(w,this.getColumnsWidth())+"px";
-this._removingColumn=false;
-}
-var cn=this.contentNode;
-cn.style.width=w;
-this.hasHScrollbar(true);
-},setSize:function(w,h){
-var ds=this.domNode.style;
-var hs=this.headerNode.style;
-if(w){
-ds.width=w;
-hs.width=w;
-}
-ds.height=(h>=0?h+"px":"");
-},renderRow:function(_3e){
-var _3f=this.createRowNode(_3e);
-this.buildRow(_3e,_3f);
-this.grid.edit.restore(this,_3e);
-return _3f;
-},createRowNode:function(_40){
-var _41=document.createElement("div");
-_41.className=this.classTag+"Row";
-if(this instanceof dojox.grid._RowSelector){
-dojo.attr(_41,"role","presentation");
-}else{
-dojo.attr(_41,"role","row");
-if(this.grid.selectionMode!="none"){
-dojo.attr(_41,"aria-selected","false");
-}
-}
-_41[dojox.grid.util.gridViewTag]=this.id;
-_41[dojox.grid.util.rowIndexTag]=_40;
-this.rowNodes[_40]=_41;
-return _41;
-},buildRow:function(_42,_43){
-this.buildRowContent(_42,_43);
-this.styleRow(_42,_43);
-},buildRowContent:function(_44,_45){
-_45.innerHTML=this.content.generateHtml(_44,_44);
-if(this.flexCells&&this.contentWidth){
-_45.firstChild.style.width=this.contentWidth;
-}
-dojox.grid.util.fire(this,"onAfterRow",[_44,this.structure.cells,_45]);
-},rowRemoved:function(_46){
-if(_46>=0){
-this._cleanupRowWidgets(this.getRowNode(_46));
-}
-this.grid.edit.save(this,_46);
-delete this.rowNodes[_46];
-},getRowNode:function(_47){
-return this.rowNodes[_47];
-},getCellNode:function(_48,_49){
-var row=this.getRowNode(_48);
-if(row){
-return this.content.getCellNode(row,_49);
-}
-},getHeaderCellNode:function(_4a){
-if(this.headerContentNode){
-return this.header.getCellNode(this.headerContentNode,_4a);
-}
-},styleRow:function(_4b,_4c){
-_4c._style=_1(_4c);
-this.styleRowNode(_4b,_4c);
-},styleRowNode:function(_4d,_4e){
-if(_4e){
-this.doStyleRowNode(_4d,_4e);
-}
-},doStyleRowNode:function(_4f,_50){
-this.grid.styleRowNode(_4f,_50);
-},updateRow:function(_51){
-var _52=this.getRowNode(_51);
-if(_52){
-_52.style.height="";
-this.buildRow(_51,_52);
-}
-return _52;
-},updateRowStyles:function(_53){
-this.styleRowNode(_53,this.getRowNode(_53));
-},lastTop:0,firstScroll:0,doscroll:function(_54){
-var _55=dojo._isBodyLtr();
-if(this.firstScroll<2){
-if((!_55&&this.firstScroll==1)||(_55&&this.firstScroll===0)){
-var s=dojo.marginBox(this.headerNodeContainer);
-if(dojo.isIE){
-this.headerNodeContainer.style.width=s.w+this.getScrollbarWidth()+"px";
-}else{
-if(dojo.isMoz){
-this.headerNodeContainer.style.width=s.w-this.getScrollbarWidth()+"px";
-this.scrollboxNode.scrollLeft=_55?this.scrollboxNode.clientWidth-this.scrollboxNode.scrollWidth:this.scrollboxNode.scrollWidth-this.scrollboxNode.clientWidth;
-}
-}
-}
-this.firstScroll++;
-}
-this.headerNode.scrollLeft=this.scrollboxNode.scrollLeft;
-var top=this.scrollboxNode.scrollTop;
-if(top!==this.lastTop){
-this.grid.scrollTo(top);
-}
-},setScrollTop:function(_56){
-this.lastTop=_56;
-this.scrollboxNode.scrollTop=_56;
-return this.scrollboxNode.scrollTop;
-},doContentEvent:function(e){
-if(this.content.decorateEvent(e)){
-this.grid.onContentEvent(e);
-}
-},doHeaderEvent:function(e){
-if(this.header.decorateEvent(e)){
-this.grid.onHeaderEvent(e);
-}
-},dispatchContentEvent:function(e){
-return this.content.dispatchEvent(e);
-},dispatchHeaderEvent:function(e){
-return this.header.dispatchEvent(e);
-},setColWidth:function(_57,_58){
-this.grid.setCellWidth(_57,_58+"px");
-},update:function(){
-if(!this.domNode){
-return;
-}
-this.content.update();
-this.grid.update();
-var _59=this.scrollboxNode.scrollLeft;
-this.scrollboxNode.scrollLeft=_59;
-this.headerNode.scrollLeft=_59;
-}});
-dojo.declare("dojox.grid._GridAvatar",dojo.dnd.Avatar,{construct:function(){
-var dd=dojo.doc;
-var a=dd.createElement("table");
-a.cellPadding=a.cellSpacing="0";
-a.className="dojoxGridDndAvatar";
-a.style.position="absolute";
-a.style.zIndex=1999;
-a.style.margin="0px";
-var b=dd.createElement("tbody");
-var tr=dd.createElement("tr");
-var td=dd.createElement("td");
-var img=dd.createElement("td");
-tr.className="dojoxGridDndAvatarItem";
-img.className="dojoxGridDndAvatarItemImage";
-img.style.width="16px";
-var _5a=this.manager.source,_5b;
-if(_5a.creator){
-_5b=_5a._normalizedCreator(_5a.getItem(this.manager.nodes[0].id).data,"avatar").node;
-}else{
-_5b=this.manager.nodes[0].cloneNode(true);
-var _5c,_5d;
-if(_5b.tagName.toLowerCase()=="tr"){
-_5c=dd.createElement("table");
-_5d=dd.createElement("tbody");
-_5d.appendChild(_5b);
-_5c.appendChild(_5d);
-_5b=_5c;
-}else{
-if(_5b.tagName.toLowerCase()=="th"){
-_5c=dd.createElement("table");
-_5d=dd.createElement("tbody");
-var r=dd.createElement("tr");
-_5c.cellPadding=_5c.cellSpacing="0";
-r.appendChild(_5b);
-_5d.appendChild(r);
-_5c.appendChild(_5d);
-_5b=_5c;
-}
-}
-}
-_5b.id="";
-td.appendChild(_5b);
-tr.appendChild(img);
-tr.appendChild(td);
-dojo.style(tr,"opacity",0.9);
-b.appendChild(tr);
-a.appendChild(b);
-this.node=a;
-var m=dojo.dnd.manager();
-this.oldOffsetY=m.OFFSET_Y;
-m.OFFSET_Y=1;
-},destroy:function(){
-dojo.dnd.manager().OFFSET_Y=this.oldOffsetY;
-this.inherited(arguments);
-}});
-var _5e=dojo.dnd.manager().makeAvatar;
-dojo.dnd.manager().makeAvatar=function(){
-var src=this.source;
-if(src.viewIndex!==undefined&&!dojo.hasClass(dojo.body(),"dijit_a11y")){
-return new dojox.grid._GridAvatar(this);
-}
-return _5e.call(dojo.dnd.manager());
-};
+	// private
+	var getStyleText = function(inNode, inStyleText){
+		return inNode.style.cssText == undefined ? inNode.getAttribute("style") : inNode.style.cssText;
+	};
+
+	// public
+	dojo.declare('dojox.grid._View', [dijit._Widget, dijit._Templated], {
+		// summary:
+		//		A collection of grid columns. A grid is comprised of a set of views that stack horizontally.
+		//		Grid creates views automatically based on grid's layout structure.
+		//		Users should typically not need to access individual views directly.
+		//
+		// defaultWidth: String
+		//		Default width of the view
+		defaultWidth: "18em",
+
+		// viewWidth: String
+		// 		Width for the view, in valid css unit
+		viewWidth: "",
+
+		templatePath: dojo.moduleUrl("dojox.grid","resources/View.html"),
+		
+		themeable: false,
+		classTag: 'dojoxGrid',
+		marginBottom: 0,
+		rowPad: 2,
+
+		// _togglingColumn: int
+		//		Width of the column being toggled (-1 for none)
+		_togglingColumn: -1,
+		
+		// _headerBuilderClass: Object
+		//		The class to use for our header builder
+		_headerBuilderClass: dojox.grid._HeaderBuilder,
+		
+		// _contentBuilderClass: Object
+		//		The class to use for our content builder
+		_contentBuilderClass: dojox.grid._ContentBuilder,
+		
+		postMixInProperties: function(){
+			this.rowNodes = {};
+		},
+
+		postCreate: function(){
+			this.connect(this.scrollboxNode,"onscroll","doscroll");
+			dojox.grid.util.funnelEvents(this.contentNode, this, "doContentEvent", [ 'mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
+			dojox.grid.util.funnelEvents(this.headerNode, this, "doHeaderEvent", [ 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
+			this.content = new this._contentBuilderClass(this);
+			this.header = new this._headerBuilderClass(this);
+			//BiDi: in RTL case, style width='9000em' causes scrolling problem in head node
+			if(!dojo._isBodyLtr()){
+				this.headerNodeContainer.style.width = "";
+			}
+		},
+
+		destroy: function(){
+			dojo.destroy(this.headerNode);
+			delete this.headerNode;
+			for(var i in this.rowNodes){
+				dojo.destroy(this.rowNodes[i]);
+			}
+			this.rowNodes = {};
+			if(this.source){
+				this.source.destroy();
+			}
+			this.inherited(arguments);
+		},
+
+		// focus 
+		focus: function(){
+			if(dojo.isIE || dojo.isWebKit || dojo.isOpera){
+				this.hiddenFocusNode.focus();
+			}else{
+				this.scrollboxNode.focus();
+			}
+		},
+
+		setStructure: function(inStructure){
+			var vs = (this.structure = inStructure);
+			// FIXME: similar logic is duplicated in layout
+			if(vs.width && !isNaN(vs.width)){
+				this.viewWidth = vs.width + 'em';
+			}else{
+				this.viewWidth = vs.width || (vs.noscroll ? 'auto' : this.viewWidth); //|| this.defaultWidth;
+			}
+			this._onBeforeRow = vs.onBeforeRow||function(){};
+			this._onAfterRow = vs.onAfterRow||function(){};
+			this.noscroll = vs.noscroll;
+			if(this.noscroll){
+				this.scrollboxNode.style.overflow = "hidden";
+			}
+			this.simpleStructure = Boolean(vs.cells.length == 1);
+			// bookkeeping
+			this.testFlexCells();
+			// accomodate new structure
+			this.updateStructure();
+		},
+		
+		_cleanupRowWidgets: function(inRowNode){
+			// Summary:
+			//		Cleans up the widgets for the given row node so that
+			//		we can reattach them if needed
+			if(inRowNode){
+				dojo.forEach(dojo.query("[widgetId]", inRowNode).map(dijit.byNode), function(w){
+					if(w._destroyOnRemove){
+						w.destroy();
+						delete w;
+					}else if(w.domNode && w.domNode.parentNode){
+						w.domNode.parentNode.removeChild(w.domNode);
+					}
+				});
+			}
+		},
+		
+		onBeforeRow: function(inRowIndex, cells){
+			this._onBeforeRow(inRowIndex, cells);
+			if(inRowIndex >= 0){
+				this._cleanupRowWidgets(this.getRowNode(inRowIndex));
+			}
+		},
+		
+		onAfterRow: function(inRowIndex, cells, inRowNode){
+			this._onAfterRow(inRowIndex, cells, inRowNode);
+			var g = this.grid;
+			dojo.forEach(dojo.query(".dojoxGridStubNode", inRowNode), function(n){
+				if(n && n.parentNode){
+					var lw = n.getAttribute("linkWidget");
+					var cellIdx = window.parseInt(dojo.attr(n, "cellIdx"), 10);
+					var cellDef = g.getCell(cellIdx);
+					var w = dijit.byId(lw);
+					if(w){
+						n.parentNode.replaceChild(w.domNode, n);
+						if(!w._started){
+							w.startup();
+						}
+					}else{
+						n.innerHTML = "";
+					}
+				}
+			}, this);
+		},
+
+		testFlexCells: function(){
+			// FIXME: cheater, this function does double duty as initializer and tester
+			this.flexCells = false;
+			for(var j=0, row; (row=this.structure.cells[j]); j++){
+				for(var i=0, cell; (cell=row[i]); i++){
+					cell.view = this;
+					this.flexCells = this.flexCells || cell.isFlex();
+				}
+			}
+			return this.flexCells;
+		},
+
+		updateStructure: function(){
+			// header builder needs to update table map
+			this.header.update();
+			// content builder needs to update markup cache
+			this.content.update();
+		},
+
+		getScrollbarWidth: function(){
+			var hasScrollSpace = this.hasVScrollbar();
+			var overflow = dojo.style(this.scrollboxNode, "overflow");
+			if(this.noscroll || !overflow || overflow == "hidden"){
+				hasScrollSpace = false;
+			}else if(overflow == "scroll"){
+				hasScrollSpace = true;
+			}
+			return (hasScrollSpace ? dojox.html.metrics.getScrollbar().w : 0); // Integer
+		},
+
+		getColumnsWidth: function(){
+			var h = this.headerContentNode;
+			return h && h.firstChild ? h.firstChild.offsetWidth : 0; // Integer
+		},
+
+		setColumnsWidth: function(width){
+			this.headerContentNode.firstChild.style.width = width + 'px';
+			if(this.viewWidth){
+				this.viewWidth = width + 'px';
+			}
+		},
+
+		getWidth: function(){
+			return this.viewWidth || (this.getColumnsWidth()+this.getScrollbarWidth()) +'px'; // String
+		},
+
+		getContentWidth: function(){
+			return Math.max(0, dojo._getContentBox(this.domNode).w - this.getScrollbarWidth()) + 'px'; // String
+		},
+
+		render: function(){
+			this.scrollboxNode.style.height = '';
+			this.renderHeader();
+			if(this._togglingColumn >= 0){
+				this.setColumnsWidth(this.getColumnsWidth() - this._togglingColumn);
+				this._togglingColumn = -1;
+			}
+			var cells = this.grid.layout.cells;
+			var getSibling = dojo.hitch(this, function(node, before){
+				!dojo._isBodyLtr() && (before = !before);
+				var inc = before?-1:1;
+				var idx = this.header.getCellNodeIndex(node) + inc;
+				var cell = cells[idx];
+				while(cell && cell.getHeaderNode() && cell.getHeaderNode().style.display == "none"){
+					idx += inc;
+					cell = cells[idx];
+				}
+				if(cell){
+					return cell.getHeaderNode();
+				}
+				return null;
+			});
+			if(this.grid.columnReordering && this.simpleStructure){
+				if(this.source){
+					this.source.destroy();
+				}
+				
+				// Create the top and bottom markers
+				var bottomMarkerId = "dojoxGrid_bottomMarker";
+				var topMarkerId = "dojoxGrid_topMarker";
+				if(this.bottomMarker){
+					dojo.destroy(this.bottomMarker);
+				}
+				this.bottomMarker = dojo.byId(bottomMarkerId);
+				if(this.topMarker){
+					dojo.destroy(this.topMarker);
+				}
+				this.topMarker = dojo.byId(topMarkerId);
+				if (!this.bottomMarker) {
+					this.bottomMarker = dojo.create("div", {
+						"id": bottomMarkerId,
+						"class": "dojoxGridColPlaceBottom"
+					}, dojo.body());
+					this._hide(this.bottomMarker);
+
+					
+					this.topMarker = dojo.create("div", {
+						"id": topMarkerId,
+						"class": "dojoxGridColPlaceTop"
+					}, dojo.body());
+					this._hide(this.topMarker);
+				}
+				this.arrowDim = dojo.contentBox(this.bottomMarker);
+
+				var headerHeight = dojo.contentBox(this.headerContentNode.firstChild.rows[0]).h;
+				
+				this.source = new dojo.dnd.Source(this.headerContentNode.firstChild.rows[0], {
+					horizontal: true,
+					accept: [ "gridColumn_" + this.grid.id ],
+					viewIndex: this.index,
+					generateText: false,
+					onMouseDown: dojo.hitch(this, function(e){
+						this.header.decorateEvent(e);
+						if((this.header.overRightResizeArea(e) || this.header.overLeftResizeArea(e)) &&
+							this.header.canResize(e) && !this.header.moveable){
+							this.header.beginColumnResize(e);
+						}else{
+							if(this.grid.headerMenu){
+								this.grid.headerMenu.onCancel(true);
+							}
+							// IE reports a left click as 1, where everything else reports 0
+							if(e.button === (dojo.isIE ? 1 : 0)){
+								dojo.dnd.Source.prototype.onMouseDown.call(this.source, e);
+							}
+						}
+					}),
+					onMouseOver: dojo.hitch(this, function(e){
+						var src = this.source;
+						if(src._getChildByEvent(e)){
+							dojo.dnd.Source.prototype.onMouseOver.apply(src, arguments);
+						}
+					}),
+					_markTargetAnchor: dojo.hitch(this, function(before){
+						var src = this.source;
+						if(src.current == src.targetAnchor && src.before == before){ return; }
+						if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
+							src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
+						}
+						dojo.dnd.Source.prototype._markTargetAnchor.call(src, before);
+						
+						var target = before ? src.targetAnchor : getSibling(src.targetAnchor, src.before);
+						var endAdd = 0;
+
+						if (!target) {
+							target = src.targetAnchor;
+							endAdd = dojo.contentBox(target).w + this.arrowDim.w/2 + 2;
+						}
+
+						// NOTE: this is for backwards compatibility with Dojo 1.3
+						var pos = (dojo.position||dojo._abs)(target, true);
+						var left = Math.floor(pos.x - this.arrowDim.w/2 + endAdd);
+
+						dojo.style(this.bottomMarker, "visibility", "visible");
+						dojo.style(this.topMarker, "visibility", "visible");
+						dojo.style(this.bottomMarker, {
+							"left": left + "px",
+							"top" : (headerHeight + pos.y) + "px"
+						});
+
+						dojo.style(this.topMarker, {
+							"left": left + "px",
+							"top" : (pos.y - this.arrowDim.h) + "px"
+						});
+
+						if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
+							src._addItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
+						}
+					}),
+					_unmarkTargetAnchor: dojo.hitch(this, function(){
+						var src = this.source;
+						if(!src.targetAnchor){ return; }
+						if(src.targetAnchor && getSibling(src.targetAnchor, src.before)){
+							src._removeItemClass(getSibling(src.targetAnchor, src.before), src.before ? "After" : "Before");
+						}
+						this._hide(this.bottomMarker);
+						this._hide(this.topMarker);
+						dojo.dnd.Source.prototype._unmarkTargetAnchor.call(src);
+					}),
+					destroy: dojo.hitch(this, function(){
+						dojo.disconnect(this._source_conn);
+						dojo.unsubscribe(this._source_sub);
+						dojo.dnd.Source.prototype.destroy.call(this.source);
+						if(this.bottomMarker){
+							dojo.destroy(this.bottomMarker);
+							delete this.bottomMarker;
+						}
+						if(this.topMarker){
+							dojo.destroy(this.topMarker);
+							delete this.topMarker;
+						}
+					}),
+					onDndCancel: dojo.hitch(this, function(){
+						dojo.dnd.Source.prototype.onDndCancel.call(this.source);
+						this._hide(this.bottomMarker);
+						this._hide(this.topMarker);
+					})
+				});
+
+				this._source_conn = dojo.connect(this.source, "onDndDrop", this, "_onDndDrop");
+				this._source_sub = dojo.subscribe("/dnd/drop/before", this, "_onDndDropBefore");
+				this.source.startup();
+			}
+		},
+		
+		_hide: function(node){
+			dojo.style(node, {
+				left: "-10000px",
+				top: "-10000px",
+				"visibility": "hidden"
+			});
+		},
+
+		_onDndDropBefore: function(source, nodes, copy){
+			if(dojo.dnd.manager().target !== this.source){
+				return;
+			}
+			this.source._targetNode = this.source.targetAnchor;
+			this.source._beforeTarget = this.source.before;
+			var views = this.grid.views.views;
+			var srcView = views[source.viewIndex];
+			var tgtView = views[this.index];
+			if(tgtView != srcView){
+				srcView.convertColPctToFixed();
+				tgtView.convertColPctToFixed();
+			}
+		},
+
+		_onDndDrop: function(source, nodes, copy){
+			if(dojo.dnd.manager().target !== this.source){
+				if(dojo.dnd.manager().source === this.source){
+					this._removingColumn = true;
+				}
+				return;
+			}
+			this._hide(this.bottomMarker);
+			this._hide(this.topMarker);
+
+			var getIdx = function(n){
+				return n ? dojo.attr(n, "idx") : null;
+			};
+			var w = dojo.marginBox(nodes[0]).w;
+			if(source.viewIndex !== this.index){
+				var views = this.grid.views.views;
+				var srcView = views[source.viewIndex];
+				var tgtView = views[this.index];
+				if(srcView.viewWidth && srcView.viewWidth != "auto"){
+					srcView.setColumnsWidth(srcView.getColumnsWidth() - w);
+				}
+				if(tgtView.viewWidth && tgtView.viewWidth != "auto"){
+					tgtView.setColumnsWidth(tgtView.getColumnsWidth());
+				}
+			}
+			var stn = this.source._targetNode;
+			var stb = this.source._beforeTarget;
+			!dojo._isBodyLtr() && (stb = !stb);
+			var layout = this.grid.layout;
+			var idx = this.index;
+			delete this.source._targetNode;
+			delete this.source._beforeTarget;
+			
+			layout.moveColumn(
+				source.viewIndex,
+				idx,
+				getIdx(nodes[0]),
+				getIdx(stn),
+				stb);
+		},
+
+		renderHeader: function(){
+			this.headerContentNode.innerHTML = this.header.generateHtml(this._getHeaderContent);
+			if(this.flexCells){
+				this.contentWidth = this.getContentWidth();
+				this.headerContentNode.firstChild.style.width = this.contentWidth;
+			}
+			dojox.grid.util.fire(this, "onAfterRow", [-1, this.structure.cells, this.headerContentNode]);
+		},
+
+		// note: not called in 'view' context
+		_getHeaderContent: function(inCell){
+			var n = inCell.name || inCell.grid.getCellName(inCell);
+			var ret = [ '<div class="dojoxGridSortNode' ];
+			
+			if(inCell.index != inCell.grid.getSortIndex()){
+				ret.push('">');
+			}else{
+				ret = ret.concat([ ' ',
+							inCell.grid.sortInfo > 0 ? 'dojoxGridSortUp' : 'dojoxGridSortDown',
+							'"><div class="dojoxGridArrowButtonChar">',
+							inCell.grid.sortInfo > 0 ? '▲' : '▼',
+							'</div><div class="dojoxGridArrowButtonNode" role="presentation"></div>',
+							'<div class="dojoxGridColCaption">']);
+			}
+			ret = ret.concat([n, '</div></div>']);
+			return ret.join('');
+		},
+
+		resize: function(){
+			this.adaptHeight();
+			this.adaptWidth();
+		},
+
+		hasHScrollbar: function(reset){
+			var hadScroll = this._hasHScroll||false;
+			if(this._hasHScroll == undefined || reset){
+				if(this.noscroll){
+					this._hasHScroll = false;
+				}else{
+					var style = dojo.style(this.scrollboxNode, "overflow");
+					if(style == "hidden"){
+						this._hasHScroll = false;
+					}else if(style == "scroll"){
+						this._hasHScroll = true;
+					}else{
+						this._hasHScroll = (this.scrollboxNode.offsetWidth - this.getScrollbarWidth() < this.contentNode.offsetWidth );
+					}
+				}
+			}
+			if(hadScroll !== this._hasHScroll){
+				this.grid.update();
+			}
+			return this._hasHScroll; // Boolean
+		},
+
+		hasVScrollbar: function(reset){
+			var hadScroll = this._hasVScroll||false;
+			if(this._hasVScroll == undefined || reset){
+				if(this.noscroll){
+					this._hasVScroll = false;
+				}else{
+					var style = dojo.style(this.scrollboxNode, "overflow");
+					if(style == "hidden"){
+						this._hasVScroll = false;
+					}else if(style == "scroll"){
+						this._hasVScroll = true;
+					}else{
+						this._hasVScroll = (this.scrollboxNode.scrollHeight > this.scrollboxNode.clientHeight);
+					}
+				}
+			}
+			if(hadScroll !== this._hasVScroll){
+				this.grid.update();
+			}
+			return this._hasVScroll; // Boolean
+		},
+		
+		convertColPctToFixed: function(){
+			// Fix any percentage widths to be pixel values
+			var hasPct = false;
+			this.grid.initialWidth = "";
+			var cellNodes = dojo.query("th", this.headerContentNode);
+			var fixedWidths = dojo.map(cellNodes, function(c, vIdx){
+				var w = c.style.width;
+				dojo.attr(c, "vIdx", vIdx);
+				if(w && w.slice(-1) == "%"){
+					hasPct = true;
+				}else if(w && w.slice(-2) == "px"){
+					return window.parseInt(w, 10);
+				}
+				return dojo.contentBox(c).w;
+			});
+			if(hasPct){
+				dojo.forEach(this.grid.layout.cells, function(cell, idx){
+					if(cell.view == this){
+						var cellNode = cell.view.getHeaderCellNode(cell.index);
+						if(cellNode && dojo.hasAttr(cellNode, "vIdx")){
+							var vIdx = window.parseInt(dojo.attr(cellNode, "vIdx"));
+							this.setColWidth(idx, fixedWidths[vIdx]);
+							dojo.removeAttr(cellNode, "vIdx");
+						}
+					}
+				}, this);
+				return true;
+			}
+			return false;
+		},
+
+		adaptHeight: function(minusScroll){
+			if(!this.grid._autoHeight){
+				var h = (this.domNode.style.height && parseInt(this.domNode.style.height.replace(/px/,''), 10)) || this.domNode.clientHeight;
+				var self = this;
+				var checkOtherViewScrollers = function(){
+					var v;
+					for(var i in self.grid.views.views){
+						v = self.grid.views.views[i];
+						if(v !== self && v.hasHScrollbar()){
+							return true;
+						}
+					}
+					return false;
+				};
+				if(minusScroll || (this.noscroll && checkOtherViewScrollers())){
+					h -= dojox.html.metrics.getScrollbar().h;
+				}
+				dojox.grid.util.setStyleHeightPx(this.scrollboxNode, h);
+			}
+			this.hasVScrollbar(true);
+		},
+
+		adaptWidth: function(){
+			if(this.flexCells){
+				// the view content width
+				this.contentWidth = this.getContentWidth();
+				this.headerContentNode.firstChild.style.width = this.contentWidth;
+			}
+			// FIXME: it should be easier to get w from this.scrollboxNode.clientWidth, 
+			// but clientWidth seemingly does not include scrollbar width in some cases
+			var w = this.scrollboxNode.offsetWidth - this.getScrollbarWidth();
+			if(!this._removingColumn){
+				w = Math.max(w, this.getColumnsWidth()) + 'px';
+			}else{
+				w = Math.min(w, this.getColumnsWidth()) + 'px';
+				this._removingColumn = false;
+			}
+			var cn = this.contentNode;
+			cn.style.width = w;
+			this.hasHScrollbar(true);
+		},
+
+		setSize: function(w, h){
+			var ds = this.domNode.style;
+			var hs = this.headerNode.style;
+
+			if(w){
+				ds.width = w;
+				hs.width = w;
+			}
+			ds.height = (h >= 0 ? h + 'px' : '');
+		},
+
+		renderRow: function(inRowIndex){
+			var rowNode = this.createRowNode(inRowIndex);
+			this.buildRow(inRowIndex, rowNode);
+			this.grid.edit.restore(this, inRowIndex);
+			return rowNode;
+		},
+
+		createRowNode: function(inRowIndex){
+			var node = document.createElement("div");
+			node.className = this.classTag + 'Row';
+			if (this instanceof dojox.grid._RowSelector){
+				dojo.attr(node,"role","presentation");
+			}else{
+				dojo.attr(node,"role","row");
+				if (this.grid.selectionMode != "none") {
+					dojo.attr(node, "aria-selected", "false"); //rows can be selected so add aria-selected prop
+				}
+			}
+			node[dojox.grid.util.gridViewTag] = this.id;
+			node[dojox.grid.util.rowIndexTag] = inRowIndex;
+			this.rowNodes[inRowIndex] = node;
+			return node;
+		},
+
+		buildRow: function(inRowIndex, inRowNode){
+			
+			this.buildRowContent(inRowIndex, inRowNode);
+		  	
+			this.styleRow(inRowIndex, inRowNode);
+		  
+		 
+		},
+
+		buildRowContent: function(inRowIndex, inRowNode){
+			inRowNode.innerHTML = this.content.generateHtml(inRowIndex, inRowIndex); 
+			if(this.flexCells && this.contentWidth){
+				// FIXME: accessing firstChild here breaks encapsulation
+				inRowNode.firstChild.style.width = this.contentWidth;
+			}
+			dojox.grid.util.fire(this, "onAfterRow", [inRowIndex, this.structure.cells, inRowNode]);
+		},
+
+		rowRemoved:function(inRowIndex){
+			if(inRowIndex >= 0){
+				this._cleanupRowWidgets(this.getRowNode(inRowIndex));
+			}
+			this.grid.edit.save(this, inRowIndex);
+			delete this.rowNodes[inRowIndex];
+		},
+
+		getRowNode: function(inRowIndex){
+			return this.rowNodes[inRowIndex];
+		},
+
+		getCellNode: function(inRowIndex, inCellIndex){
+			var row = this.getRowNode(inRowIndex);
+			if(row){
+				return this.content.getCellNode(row, inCellIndex);
+			}
+		},
+
+		getHeaderCellNode: function(inCellIndex){
+			if(this.headerContentNode){
+				return this.header.getCellNode(this.headerContentNode, inCellIndex);
+			}
+		},
+
+		// styling
+		styleRow: function(inRowIndex, inRowNode){
+			inRowNode._style = getStyleText(inRowNode);
+			this.styleRowNode(inRowIndex, inRowNode);
+		},
+
+		styleRowNode: function(inRowIndex, inRowNode){
+			if(inRowNode){
+				this.doStyleRowNode(inRowIndex, inRowNode);
+			}
+		},
+
+		doStyleRowNode: function(inRowIndex, inRowNode){
+			this.grid.styleRowNode(inRowIndex, inRowNode);
+		},
+
+		// updating
+		updateRow: function(inRowIndex){
+			var rowNode = this.getRowNode(inRowIndex);
+			if(rowNode){
+				rowNode.style.height = '';
+				this.buildRow(inRowIndex, rowNode);
+			}
+			return rowNode;
+		},
+
+		updateRowStyles: function(inRowIndex){
+			this.styleRowNode(inRowIndex, this.getRowNode(inRowIndex));
+		},
+
+		// scrolling
+		lastTop: 0,
+		firstScroll:0,
+
+		doscroll: function(inEvent){
+			//var s = dojo.marginBox(this.headerContentNode.firstChild);
+			var isLtr = dojo._isBodyLtr();
+			if(this.firstScroll < 2){
+				if((!isLtr && this.firstScroll == 1) || (isLtr && this.firstScroll === 0)){
+					var s = dojo.marginBox(this.headerNodeContainer);
+					if(dojo.isIE){
+						this.headerNodeContainer.style.width = s.w + this.getScrollbarWidth() + 'px';
+					}else if(dojo.isMoz){
+						//TODO currently only for FF, not sure for safari and opera
+						this.headerNodeContainer.style.width = s.w - this.getScrollbarWidth() + 'px';
+						//this.headerNodeContainer.style.width = s.w + 'px';
+						//set scroll to right in FF
+						this.scrollboxNode.scrollLeft = isLtr ?
+							this.scrollboxNode.clientWidth - this.scrollboxNode.scrollWidth :
+							this.scrollboxNode.scrollWidth - this.scrollboxNode.clientWidth;
+					}
+				}
+				this.firstScroll++;
+			}
+			this.headerNode.scrollLeft = this.scrollboxNode.scrollLeft;
+			// 'lastTop' is a semaphore to prevent feedback-loop with setScrollTop below
+			var top = this.scrollboxNode.scrollTop;
+			if(top !== this.lastTop){
+				this.grid.scrollTo(top);
+			}
+		},
+
+		setScrollTop: function(inTop){
+			// 'lastTop' is a semaphore to prevent feedback-loop with doScroll above
+			this.lastTop = inTop;
+			this.scrollboxNode.scrollTop = inTop;
+			return this.scrollboxNode.scrollTop;
+		},
+
+		// event handlers (direct from DOM)
+		doContentEvent: function(e){
+			if(this.content.decorateEvent(e)){
+				this.grid.onContentEvent(e);
+			}
+		},
+
+		doHeaderEvent: function(e){
+			if(this.header.decorateEvent(e)){
+				this.grid.onHeaderEvent(e);
+			}
+		},
+
+		// event dispatch(from Grid)
+		dispatchContentEvent: function(e){
+			return this.content.dispatchEvent(e);
+		},
+
+		dispatchHeaderEvent: function(e){
+			return this.header.dispatchEvent(e);
+		},
+
+		// column resizing
+		setColWidth: function(inIndex, inWidth){
+			this.grid.setCellWidth(inIndex, inWidth + 'px');
+		},
+
+		update: function(){
+			if(!this.domNode){
+				return;
+			}
+			this.content.update();
+			this.grid.update();
+			//get scroll after update or scroll left setting goes wrong on IE.
+			//See trac: #8040
+			var left = this.scrollboxNode.scrollLeft;
+			this.scrollboxNode.scrollLeft = left;
+			this.headerNode.scrollLeft = left;
+		}
+	});
+
+	dojo.declare("dojox.grid._GridAvatar", dojo.dnd.Avatar, {
+		construct: function(){
+			var dd = dojo.doc;
+
+			var a = dd.createElement("table");
+			a.cellPadding = a.cellSpacing = "0";
+			a.className = "dojoxGridDndAvatar";
+			a.style.position = "absolute";
+			a.style.zIndex = 1999;
+			a.style.margin = "0px"; // to avoid dojo.marginBox() problems with table's margins
+			var b = dd.createElement("tbody");
+			var tr = dd.createElement("tr");
+			var td = dd.createElement("td");
+			var img = dd.createElement("td");
+			tr.className = "dojoxGridDndAvatarItem";
+			img.className = "dojoxGridDndAvatarItemImage";
+			img.style.width = "16px";
+			var source = this.manager.source, node;
+			if(source.creator){
+				// create an avatar representation of the node
+				node = source._normalizedCreator(source.getItem(this.manager.nodes[0].id).data, "avatar").node;
+			}else{
+				// or just clone the node and hope it works
+				node = this.manager.nodes[0].cloneNode(true);
+				var table, tbody;
+				if(node.tagName.toLowerCase() == "tr"){
+					// insert extra table nodes
+					table = dd.createElement("table");
+					tbody = dd.createElement("tbody");
+					tbody.appendChild(node);
+					table.appendChild(tbody);
+					node = table;
+				}else if(node.tagName.toLowerCase() == "th"){
+					// insert extra table nodes
+					table = dd.createElement("table");
+					tbody = dd.createElement("tbody");
+					var r = dd.createElement("tr");
+					table.cellPadding = table.cellSpacing = "0";
+					r.appendChild(node);
+					tbody.appendChild(r);
+					table.appendChild(tbody);
+					node = table;
+				}
+			}
+			node.id = "";
+			td.appendChild(node);
+			tr.appendChild(img);
+			tr.appendChild(td);
+			dojo.style(tr, "opacity", 0.9);
+			b.appendChild(tr);
+
+			a.appendChild(b);
+			this.node = a;
+
+			var m = dojo.dnd.manager();
+			this.oldOffsetY = m.OFFSET_Y;
+			m.OFFSET_Y = 1;
+		},
+		destroy: function(){
+			dojo.dnd.manager().OFFSET_Y = this.oldOffsetY;
+			this.inherited(arguments);
+		}
+	});
+
+	var oldMakeAvatar = dojo.dnd.manager().makeAvatar;
+	dojo.dnd.manager().makeAvatar = function(){
+		var src = this.source;
+		if(src.viewIndex !== undefined && !dojo.hasClass(dojo.body(),"dijit_a11y")){
+			return new dojox.grid._GridAvatar(this);
+		}
+		return oldMakeAvatar.call(dojo.dnd.manager());
+	};
 })();
-}
diff --git a/dojox/grid/_ViewManager.js b/dojox/grid/_ViewManager.js
index f55d7b5..348df1c 100644
--- a/dojox/grid/_ViewManager.js
+++ b/dojox/grid/_ViewManager.js
@@ -1,212 +1,302 @@
-/*
-	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
-*/
+dojo.provide("dojox.grid._ViewManager");
 
+dojo.declare('dojox.grid._ViewManager', null, {
+	// summary:
+	//		A collection of grid views. Owned by grid and used internally for managing grid views.
+	// description:
+	//		Grid creates views automatically based on grid's layout structure.
+	//		Users should typically not need to access individual views or the views collection directly.
+	constructor: function(inGrid){
+		this.grid = inGrid;
+	},
 
-if(!dojo._hasResource["dojox.grid._ViewManager"]){
-dojo._hasResource["dojox.grid._ViewManager"]=true;
-dojo.provide("dojox.grid._ViewManager");
-dojo.declare("dojox.grid._ViewManager",null,{constructor:function(_1){
-this.grid=_1;
-},defaultWidth:200,views:[],resize:function(){
-this.onEach("resize");
-},render:function(){
-this.onEach("render");
-},addView:function(_2){
-_2.idx=this.views.length;
-this.views.push(_2);
-},destroyViews:function(){
-for(var i=0,v;v=this.views[i];i++){
-v.destroy();
-}
-this.views=[];
-},getContentNodes:function(){
-var _3=[];
-for(var i=0,v;v=this.views[i];i++){
-_3.push(v.contentNode);
-}
-return _3;
-},forEach:function(_4){
-for(var i=0,v;v=this.views[i];i++){
-_4(v,i);
-}
-},onEach:function(_5,_6){
-_6=_6||[];
-for(var i=0,v;v=this.views[i];i++){
-if(_5 in v){
-v[_5].apply(v,_6);
-}
-}
-},normalizeHeaderNodeHeight:function(){
-var _7=[];
-for(var i=0,v;(v=this.views[i]);i++){
-if(v.headerContentNode.firstChild){
-_7.push(v.headerContentNode);
-}
-}
-this.normalizeRowNodeHeights(_7);
-},normalizeRowNodeHeights:function(_8){
-var h=0;
-var _9=[];
-if(this.grid.rowHeight){
-h=this.grid.rowHeight;
-}else{
-if(_8.length<=1){
-return;
-}
-for(var i=0,n;(n=_8[i]);i++){
-if(!dojo.hasClass(n,"dojoxGridNonNormalizedCell")){
-_9[i]=n.firstChild.offsetHeight;
-h=Math.max(h,_9[i]);
-}
-}
-h=(h>=0?h:0);
-if(dojo.isMoz&&h){
-h++;
-}
-}
-for(i=0;(n=_8[i]);i++){
-if(_9[i]!=h){
-n.firstChild.style.height=h+"px";
-}
-}
-},resetHeaderNodeHeight:function(){
-for(var i=0,v,n;(v=this.views[i]);i++){
-n=v.headerContentNode.firstChild;
-if(n){
-n.style.height="";
-}
-}
-},renormalizeRow:function(_a){
-var _b=[];
-for(var i=0,v,n;(v=this.views[i])&&(n=v.getRowNode(_a));i++){
-n.firstChild.style.height="";
-_b.push(n);
-}
-this.normalizeRowNodeHeights(_b);
-},getViewWidth:function(_c){
-return this.views[_c].getWidth()||this.defaultWidth;
-},measureHeader:function(){
-this.resetHeaderNodeHeight();
-this.forEach(function(_d){
-_d.headerContentNode.style.height="";
-});
-var h=0;
-this.forEach(function(_e){
-h=Math.max(_e.headerNode.offsetHeight,h);
-});
-return h;
-},measureContent:function(){
-var h=0;
-this.forEach(function(_f){
-h=Math.max(_f.domNode.offsetHeight,h);
+	defaultWidth: 200,
+
+	views: [],
+
+	// operations
+	resize: function(){
+		this.onEach("resize");
+	},
+
+	render: function(){
+		this.onEach("render");
+	},
+
+	// views
+	addView: function(inView){
+		inView.idx = this.views.length;
+		this.views.push(inView);
+	},
+
+	destroyViews: function(){
+		for(var i=0, v; v=this.views[i]; i++){
+			v.destroy();
+		}
+		this.views = [];
+	},
+
+	getContentNodes: function(){
+		var nodes = [];
+		for(var i=0, v; v=this.views[i]; i++){
+			nodes.push(v.contentNode);
+		}
+		return nodes;
+	},
+
+	forEach: function(inCallback){
+		for(var i=0, v; v=this.views[i]; i++){
+			inCallback(v, i);
+		}
+	},
+
+	onEach: function(inMethod, inArgs){
+		inArgs = inArgs || [];
+		for(var i=0, v; v=this.views[i]; i++){
+			if(inMethod in v){
+				v[inMethod].apply(v, inArgs);
+			}
+		}
+	},
+
+	// layout
+	normalizeHeaderNodeHeight: function(){
+		var rowNodes = [];
+		for(var i=0, v; (v=this.views[i]); i++){
+			if(v.headerContentNode.firstChild){
+				rowNodes.push(v.headerContentNode);
+			}
+		}
+		this.normalizeRowNodeHeights(rowNodes);
+	},
+
+	normalizeRowNodeHeights: function(inRowNodes){
+		var h = 0;
+		var currHeights = [];
+		if(this.grid.rowHeight){
+			h = this.grid.rowHeight;
+		}else{
+			if(inRowNodes.length <= 1){ 
+				// no need to normalize if we are the only one...
+				return; 
+			}
+			for(var i=0, n; (n=inRowNodes[i]); i++){
+				// We only care about the height - so don't use marginBox.  This
+				// depends on the container not having any margin (which it shouldn't)
+				// Also - we only look up the height if the cell doesn't have the
+				// dojoxGridNonNormalizedCell class (like for row selectors)
+				if(!dojo.hasClass(n, "dojoxGridNonNormalizedCell")){
+					currHeights[i] = n.firstChild.offsetHeight;
+					h =  Math.max(h, currHeights[i]);
+				}
+			}
+			h = (h >= 0 ? h : 0);
+	
+			//Work around odd FF3 rendering bug: #8864.
+			//A one px increase fixes FireFox 3's rounding bug for fractional font sizes.
+			if(dojo.isMoz && h){h++;}
+		}
+		for(i=0; (n=inRowNodes[i]); i++){
+			if(currHeights[i] != h){
+				n.firstChild.style.height = h + "px";
+			}
+		}
+	},
+	
+	resetHeaderNodeHeight: function(){
+		for(var i=0, v, n; (v=this.views[i]); i++){
+			n = v.headerContentNode.firstChild;
+			if(n){
+				n.style.height = "";
+			}
+		}
+	},
+
+	renormalizeRow: function(inRowIndex){
+		var rowNodes = [];
+		for(var i=0, v, n; (v=this.views[i])&&(n=v.getRowNode(inRowIndex)); i++){
+			n.firstChild.style.height = '';
+			rowNodes.push(n);
+		}
+		this.normalizeRowNodeHeights(rowNodes);
+	},
+
+	getViewWidth: function(inIndex){
+		return this.views[inIndex].getWidth() || this.defaultWidth;
+	},
+
+	// must be called after view widths are properly set or height can be miscalculated
+	// if there are flex columns
+	measureHeader: function(){
+		// need to reset view header heights so they are properly measured.
+		this.resetHeaderNodeHeight();
+		this.forEach(function(inView){
+			inView.headerContentNode.style.height = '';
+		});
+		var h = 0;
+		// calculate maximum view header height
+		this.forEach(function(inView){
+			h = Math.max(inView.headerNode.offsetHeight, h);
+		});
+		return h;
+	},
+
+	measureContent: function(){
+		var h = 0;
+		this.forEach(function(inView){
+			h = Math.max(inView.domNode.offsetHeight, h);
+		});
+		return h;
+	},
+
+	findClient: function(inAutoWidth){
+		// try to use user defined client
+		var c = this.grid.elasticView || -1;
+		// attempt to find implicit client
+		if(c < 0){
+			for(var i=1, v; (v=this.views[i]); i++){
+				if(v.viewWidth){
+					for(i=1; (v=this.views[i]); i++){
+						if(!v.viewWidth){
+							c = i;
+							break;
+						}
+					}
+					break;
+				}
+			}
+		}
+		// client is in the middle by default
+		if(c < 0){
+			c = Math.floor(this.views.length / 2);
+		}
+		return c;
+	},
+
+	arrange: function(l, w){
+		var i, v, vw, len = this.views.length;
+		// find the client
+		var c = (w <= 0 ? len : this.findClient());
+		// layout views
+		var setPosition = function(v, l){
+			var ds = v.domNode.style;
+			var hs = v.headerNode.style;
+
+			if(!dojo._isBodyLtr()){
+				ds.right = l + 'px';
+				// fixed rtl, the scrollbar is on the right side in FF
+				if (dojo.isMoz) {
+					hs.right = l + v.getScrollbarWidth() + 'px';
+					hs.width = parseInt(hs.width, 10) - v.getScrollbarWidth() + 'px';
+				}else{
+					hs.right = l + 'px';					
+				}
+			}else{
+				ds.left = l + 'px';
+				hs.left = l + 'px';
+			}
+			ds.top = 0 + 'px';
+			hs.top = 0;
+		};
+		// for views left of the client
+		//BiDi TODO: The left and right should not appear in BIDI environment. Should be replaced with 
+		//leading and tailing concept.
+		for(i=0; (v=this.views[i])&&(i<c); i++){
+			// get width
+			vw = this.getViewWidth(i);
+			// process boxes
+			v.setSize(vw, 0);
+			setPosition(v, l);
+			if(v.headerContentNode && v.headerContentNode.firstChild){
+				vw = v.getColumnsWidth()+v.getScrollbarWidth();
+			}else{
+				vw = v.domNode.offsetWidth;
+			}
+			// update position
+			l += vw;
+		}
+		// next view (is the client, i++ == c) 
+		i++;
+		// start from the right edge
+		var r = w;
+		// for views right of the client (iterated from the right)
+		for(var j=len-1; (v=this.views[j])&&(i<=j); j--){
+			// get width
+			vw = this.getViewWidth(j);
+			// set size
+			v.setSize(vw, 0);
+			// measure in pixels
+			vw = v.domNode.offsetWidth;
+			// update position
+			r -= vw;
+			// set position
+			setPosition(v, r);
+		}
+		if(c<len){
+			v = this.views[c];
+			// position the client box between left and right boxes	
+			vw = Math.max(1, r-l);
+			// set size
+			v.setSize(vw + 'px', 0);
+			setPosition(v, l);
+		}
+		return l;
+	},
+
+	// rendering
+	renderRow: function(inRowIndex, inNodes, skipRenorm){
+		var rowNodes = [];
+		for(var i=0, v, n, rowNode; (v=this.views[i])&&(n=inNodes[i]); i++){
+			rowNode = v.renderRow(inRowIndex);
+			n.appendChild(rowNode);
+			rowNodes.push(rowNode);
+		}
+		if(!skipRenorm){
+			this.normalizeRowNodeHeights(rowNodes);
+		}
+	},
+	
+	rowRemoved: function(inRowIndex){
+		this.onEach("rowRemoved", [ inRowIndex ]);
+	},
+	
+	// updating
+	updateRow: function(inRowIndex, skipRenorm){
+		for(var i=0, v; v=this.views[i]; i++){
+			v.updateRow(inRowIndex);
+		}
+		if(!skipRenorm){
+			this.renormalizeRow(inRowIndex);
+		}
+	},
+	
+	updateRowStyles: function(inRowIndex){
+		this.onEach("updateRowStyles", [ inRowIndex ]);
+	},
+	
+	// scrolling
+	setScrollTop: function(inTop){
+		var top = inTop;
+		for(var i=0, v; v=this.views[i]; i++){
+			top = v.setScrollTop(inTop);
+			// Work around IE not firing scroll events that cause header offset
+			// issues to occur.
+			if(dojo.isIE && v.headerNode && v.scrollboxNode){
+				v.headerNode.scrollLeft = v.scrollboxNode.scrollLeft;
+			}
+		}
+		return top;
+		//this.onEach("setScrollTop", [ inTop ]);
+	},
+	
+	getFirstScrollingView: function(){
+		// summary: Returns the first grid view with a scroll bar 
+		for(var i=0, v; (v=this.views[i]); i++){
+			if(v.hasHScrollbar() || v.hasVScrollbar()){
+				return v;
+			}
+		}
+		return null;
+	}
+	
 });
-return h;
-},findClient:function(_10){
-var c=this.grid.elasticView||-1;
-if(c<0){
-for(var i=1,v;(v=this.views[i]);i++){
-if(v.viewWidth){
-for(i=1;(v=this.views[i]);i++){
-if(!v.viewWidth){
-c=i;
-break;
-}
-}
-break;
-}
-}
-}
-if(c<0){
-c=Math.floor(this.views.length/2);
-}
-return c;
-},arrange:function(l,w){
-var i,v,vw,len=this.views.length;
-var c=(w<=0?len:this.findClient());
-var _11=function(v,l){
-var ds=v.domNode.style;
-var hs=v.headerNode.style;
-if(!dojo._isBodyLtr()){
-ds.right=l+"px";
-if(dojo.isMoz){
-hs.right=l+v.getScrollbarWidth()+"px";
-hs.width=parseInt(hs.width,10)-v.getScrollbarWidth()+"px";
-}else{
-hs.right=l+"px";
-}
-}else{
-ds.left=l+"px";
-hs.left=l+"px";
-}
-ds.top=0+"px";
-hs.top=0;
-};
-for(i=0;(v=this.views[i])&&(i<c);i++){
-vw=this.getViewWidth(i);
-v.setSize(vw,0);
-_11(v,l);
-if(v.headerContentNode&&v.headerContentNode.firstChild){
-vw=v.getColumnsWidth()+v.getScrollbarWidth();
-}else{
-vw=v.domNode.offsetWidth;
-}
-l+=vw;
-}
-i++;
-var r=w;
-for(var j=len-1;(v=this.views[j])&&(i<=j);j--){
-vw=this.getViewWidth(j);
-v.setSize(vw,0);
-vw=v.domNode.offsetWidth;
-r-=vw;
-_11(v,r);
-}
-if(c<len){
-v=this.views[c];
-vw=Math.max(1,r-l);
-v.setSize(vw+"px",0);
-_11(v,l);
-}
-return l;
-},renderRow:function(_12,_13,_14){
-var _15=[];
-for(var i=0,v,n,_16;(v=this.views[i])&&(n=_13[i]);i++){
-_16=v.renderRow(_12);
-n.appendChild(_16);
-_15.push(_16);
-}
-if(!_14){
-this.normalizeRowNodeHeights(_15);
-}
-},rowRemoved:function(_17){
-this.onEach("rowRemoved",[_17]);
-},updateRow:function(_18,_19){
-for(var i=0,v;v=this.views[i];i++){
-v.updateRow(_18);
-}
-if(!_19){
-this.renormalizeRow(_18);
-}
-},updateRowStyles:function(_1a){
-this.onEach("updateRowStyles",[_1a]);
-},setScrollTop:function(_1b){
-var top=_1b;
-for(var i=0,v;v=this.views[i];i++){
-top=v.setScrollTop(_1b);
-if(dojo.isIE&&v.headerNode&&v.scrollboxNode){
-v.headerNode.scrollLeft=v.scrollboxNode.scrollLeft;
-}
-}
-return top;
-},getFirstScrollingView:function(){
-for(var i=0,v;(v=this.views[i]);i++){
-if(v.hasHScrollbar()||v.hasVScrollbar()){
-return v;
-}
-}
-return null;
-}});
-}
diff --git a/dojox/grid/cells.js b/dojox/grid/cells.js
index 42a7cee..551af16 100644
--- a/dojox/grid/cells.js
+++ b/dojox/grid/cells.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.cells"]){
-dojo._hasResource["dojox.grid.cells"]=true;
 dojo.provide("dojox.grid.cells");
 dojo.require("dojox.grid.cells._base");
-}
diff --git a/dojox/grid/cells/_base.js b/dojox/grid/cells/_base.js
index c3b1a21..76fdc56 100644
--- a/dojox/grid/cells/_base.js
+++ b/dojox/grid/cells/_base.js
@@ -1,271 +1,453 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.cells._base"]){
-dojo._hasResource["dojox.grid.cells._base"]=true;
 dojo.provide("dojox.grid.cells._base");
+
 dojo.require("dojox.grid.util");
 dojo.require("dijit._Widget");
-dojo.declare("dojox.grid._DeferredTextWidget",dijit._Widget,{deferred:null,_destroyOnRemove:true,postCreate:function(){
-if(this.deferred){
-this.deferred.addBoth(dojo.hitch(this,function(_1){
-if(this.domNode){
-this.domNode.innerHTML=_1;
-}
-}));
-}
-}});
-(function(){
-var _2=function(_3){
-try{
-dojox.grid.util.fire(_3,"focus");
-dojox.grid.util.fire(_3,"select");
-}
-catch(e){
-}
-};
-var _4=function(){
-setTimeout(dojo.hitch.apply(dojo,arguments),0);
-};
-var _5=dojox.grid.cells;
-dojo.declare("dojox.grid.cells._Base",null,{styles:"",classes:"",editable:false,alwaysEditing:false,formatter:null,defaultValue:"...",value:null,hidden:false,noresize:false,draggable:true,_valueProp:"value",_formatPending:false,constructor:function(_6){
-this._props=_6||{};
-dojo.mixin(this,_6);
-if(this.draggable===undefined){
-this.draggable=true;
-}
-},_defaultFormat:function(_7,_8){
-var s=this.grid.formatterScope||this;
-var f=this.formatter;
-if(f&&s&&typeof f=="string"){
-f=this.formatter=s[f];
-}
-var v=(_7!=this.defaultValue&&f)?f.apply(s,_8):_7;
-if(typeof v=="undefined"){
-return this.defaultValue;
-}
-if(v&&v.addBoth){
-v=new dojox.grid._DeferredTextWidget({deferred:v},dojo.create("span",{innerHTML:this.defaultValue}));
-}
-if(v&&v.declaredClass&&v.startup){
-return "<div class='dojoxGridStubNode' linkWidget='"+v.id+"' cellIdx='"+this.index+"'>"+this.defaultValue+"</div>";
-}
-return v;
-},format:function(_9,_a){
-var f,i=this.grid.edit.info,d=this.get?this.get(_9,_a):(this.value||this.defaultValue);
-d=(d&&d.replace&&this.grid.escapeHTMLInData)?d.replace(/&/g,"&").replace(/</g,"<"):d;
-if(this.editable&&(this.alwaysEditing||(i.rowIndex==_9&&i.cell==this))){
-return this.formatEditing(d,_9);
-}else{
-return this._defaultFormat(d,[d,_9,this]);
-}
-},formatEditing:function(_b,_c){
-},getNode:function(_d){
-return this.view.getCellNode(_d,this.index);
-},getHeaderNode:function(){
-return this.view.getHeaderCellNode(this.index);
-},getEditNode:function(_e){
-return (this.getNode(_e)||0).firstChild||0;
-},canResize:function(){
-var uw=this.unitWidth;
-return uw&&(uw!=="auto");
-},isFlex:function(){
-var uw=this.unitWidth;
-return uw&&dojo.isString(uw)&&(uw=="auto"||uw.slice(-1)=="%");
-},applyEdit:function(_f,_10){
-this.grid.edit.applyCellEdit(_f,this,_10);
-},cancelEdit:function(_11){
-this.grid.doCancelEdit(_11);
-},_onEditBlur:function(_12){
-if(this.grid.edit.isEditCell(_12,this.index)){
-this.grid.edit.apply();
-}
-},registerOnBlur:function(_13,_14){
-if(this.commitOnBlur){
-dojo.connect(_13,"onblur",function(e){
-setTimeout(dojo.hitch(this,"_onEditBlur",_14),250);
+
+dojo.declare("dojox.grid._DeferredTextWidget", dijit._Widget, {
+	deferred: null,
+	_destroyOnRemove: true,
+	postCreate: function(){
+		if(this.deferred){
+			this.deferred.addBoth(dojo.hitch(this, function(text){
+				if(this.domNode){
+					this.domNode.innerHTML = text;
+				}
+			}));
+		}
+	}
 });
-}
-},needFormatNode:function(_15,_16){
-this._formatPending=true;
-_4(this,"_formatNode",_15,_16);
-},cancelFormatNode:function(){
-this._formatPending=false;
-},_formatNode:function(_17,_18){
-if(this._formatPending){
-this._formatPending=false;
-dojo.setSelectable(this.grid.domNode,true);
-this.formatNode(this.getEditNode(_18),_17,_18);
-}
-},formatNode:function(_19,_1a,_1b){
-if(dojo.isIE){
-_4(this,"focus",_1b,_19);
-}else{
-this.focus(_1b,_19);
-}
-},dispatchEvent:function(m,e){
-if(m in this){
-return this[m](e);
-}
-},getValue:function(_1c){
-return this.getEditNode(_1c)[this._valueProp];
-},setValue:function(_1d,_1e){
-var n=this.getEditNode(_1d);
-if(n){
-n[this._valueProp]=_1e;
-}
-},focus:function(_1f,_20){
-_2(_20||this.getEditNode(_1f));
-},save:function(_21){
-this.value=this.value||this.getValue(_21);
-},restore:function(_22){
-this.setValue(_22,this.value);
-},_finish:function(_23){
-dojo.setSelectable(this.grid.domNode,false);
-this.cancelFormatNode();
-},apply:function(_24){
-this.applyEdit(this.getValue(_24),_24);
-this._finish(_24);
-},cancel:function(_25){
-this.cancelEdit(_25);
-this._finish(_25);
-}});
-_5._Base.markupFactory=function(_26,_27){
-var d=dojo;
-var _28=d.trim(d.attr(_26,"formatter")||"");
-if(_28){
-_27.formatter=dojo.getObject(_28)||_28;
-}
-var get=d.trim(d.attr(_26,"get")||"");
-if(get){
-_27.get=dojo.getObject(get);
-}
-var _29=function(_2a,_2b,_2c){
-var _2d=d.trim(d.attr(_26,_2a)||"");
-if(_2d){
-_2b[_2c||_2a]=!(_2d.toLowerCase()=="false");
-}
-};
-_29("sortDesc",_27);
-_29("editable",_27);
-_29("alwaysEditing",_27);
-_29("noresize",_27);
-_29("draggable",_27);
-var _2e=d.trim(d.attr(_26,"loadingText")||d.attr(_26,"defaultValue")||"");
-if(_2e){
-_27.defaultValue=_2e;
-}
-var _2f=function(_30,_31,_32){
-var _33=d.trim(d.attr(_26,_30)||"")||undefined;
-if(_33){
-_31[_32||_30]=_33;
-}
-};
-_2f("styles",_27);
-_2f("headerStyles",_27);
-_2f("cellStyles",_27);
-_2f("classes",_27);
-_2f("headerClasses",_27);
-_2f("cellClasses",_27);
-};
-dojo.declare("dojox.grid.cells.Cell",_5._Base,{constructor:function(){
-this.keyFilter=this.keyFilter;
-},keyFilter:null,formatEditing:function(_34,_35){
-this.needFormatNode(_34,_35);
-return "<input class=\"dojoxGridInput\" type=\"text\" value=\""+_34+"\">";
-},formatNode:function(_36,_37,_38){
-this.inherited(arguments);
-this.registerOnBlur(_36,_38);
-},doKey:function(e){
-if(this.keyFilter){
-var key=String.fromCharCode(e.charCode);
-if(key.search(this.keyFilter)==-1){
-dojo.stopEvent(e);
-}
-}
-},_finish:function(_39){
-this.inherited(arguments);
-var n=this.getEditNode(_39);
-try{
-dojox.grid.util.fire(n,"blur");
-}
-catch(e){
-}
-}});
-_5.Cell.markupFactory=function(_3a,_3b){
-_5._Base.markupFactory(_3a,_3b);
-var d=dojo;
-var _3c=d.trim(d.attr(_3a,"keyFilter")||"");
-if(_3c){
-_3b.keyFilter=new RegExp(_3c);
-}
-};
-dojo.declare("dojox.grid.cells.RowIndex",_5.Cell,{name:"Row",postscript:function(){
-this.editable=false;
-},get:function(_3d){
-return _3d+1;
-}});
-_5.RowIndex.markupFactory=function(_3e,_3f){
-_5.Cell.markupFactory(_3e,_3f);
-};
-dojo.declare("dojox.grid.cells.Select",_5.Cell,{options:null,values:null,returnIndex:-1,constructor:function(_40){
-this.values=this.values||this.options;
-},formatEditing:function(_41,_42){
-this.needFormatNode(_41,_42);
-var h=["<select class=\"dojoxGridSelect\">"];
-for(var i=0,o,v;((o=this.options[i])!==undefined)&&((v=this.values[i])!==undefined);i++){
-h.push("<option",(_41==v?" selected":"")," value=\""+v+"\"",">",o,"</option>");
-}
-h.push("</select>");
-return h.join("");
-},getValue:function(_43){
-var n=this.getEditNode(_43);
-if(n){
-var i=n.selectedIndex,o=n.options[i];
-return this.returnIndex>-1?i:o.value||o.innerHTML;
-}
-}});
-_5.Select.markupFactory=function(_44,_45){
-_5.Cell.markupFactory(_44,_45);
-var d=dojo;
-var _46=d.trim(d.attr(_44,"options")||"");
-if(_46){
-var o=_46.split(",");
-if(o[0]!=_46){
-_45.options=o;
-}
-}
-var _47=d.trim(d.attr(_44,"values")||"");
-if(_47){
-var v=_47.split(",");
-if(v[0]!=_47){
-_45.values=v;
-}
-}
-};
-dojo.declare("dojox.grid.cells.AlwaysEdit",_5.Cell,{alwaysEditing:true,_formatNode:function(_48,_49){
-this.formatNode(this.getEditNode(_49),_48,_49);
-},applyStaticValue:function(_4a){
-var e=this.grid.edit;
-e.applyCellEdit(this.getValue(_4a),this,_4a);
-e.start(this,_4a,true);
-}});
-_5.AlwaysEdit.markupFactory=function(_4b,_4c){
-_5.Cell.markupFactory(_4b,_4c);
-};
-dojo.declare("dojox.grid.cells.Bool",_5.AlwaysEdit,{_valueProp:"checked",formatEditing:function(_4d,_4e){
-return "<input class=\"dojoxGridInput\" type=\"checkbox\""+(_4d?" checked=\"checked\"":"")+" style=\"width: auto\" />";
-},doclick:function(e){
-if(e.target.tagName=="INPUT"){
-this.applyStaticValue(e.rowIndex);
-}
-}});
-_5.Bool.markupFactory=function(_4f,_50){
-_5.AlwaysEdit.markupFactory(_4f,_50);
-};
+
+(function(){
+	var focusSelectNode = function(inNode){
+		try{
+			dojox.grid.util.fire(inNode, "focus");
+			dojox.grid.util.fire(inNode, "select");
+		}catch(e){// IE sux bad
+		}
+	};
+	
+	var whenIdle = function(/*inContext, inMethod, args ...*/){
+		setTimeout(dojo.hitch.apply(dojo, arguments), 0);
+	};
+
+	var dgc = dojox.grid.cells;
+
+	dojo.declare("dojox.grid.cells._Base", null, {
+		// summary:
+		//	Respresents a grid cell and contains information about column options and methods
+		//	for retrieving cell related information.
+		//	Each column in a grid layout has a cell object and most events and many methods
+		//	provide access to these objects.
+		styles: '',
+		classes: '',
+		editable: false,
+		alwaysEditing: false,
+		formatter: null,
+		defaultValue: '...',
+		value: null,
+		hidden: false,
+		noresize: false,
+		draggable: true,
+		//private
+		_valueProp: "value",
+		_formatPending: false,
+
+		constructor: function(inProps){
+			this._props = inProps || {};
+			dojo.mixin(this, inProps);
+			if(this.draggable === undefined){
+				this.draggable = true;
+			}
+		},
+
+		_defaultFormat: function(inValue, callArgs){
+			var s = this.grid.formatterScope || this;
+			var f = this.formatter;
+			if(f && s && typeof f == "string"){
+				f = this.formatter = s[f];
+			}
+			var v = (inValue != this.defaultValue && f) ? f.apply(s, callArgs) : inValue;
+			if(typeof v == "undefined"){
+				return this.defaultValue;
+			}
+			if(v && v.addBoth){
+				// Check if it's a deferred
+				v = new dojox.grid._DeferredTextWidget({deferred: v},
+									dojo.create("span", {innerHTML: this.defaultValue}));
+			}
+			if(v && v.declaredClass && v.startup){
+				return "<div class='dojoxGridStubNode' linkWidget='" +
+						v.id +
+						"' cellIdx='" +
+						this.index +
+						"'>" +
+						this.defaultValue +
+						"</div>";
+			}
+			return v;
+		},
+		
+		// data source
+		format: function(inRowIndex, inItem){
+			// summary:
+			//	provides the html for a given grid cell.
+			// inRowIndex: int
+			// grid row index
+			// returns: html for a given grid cell
+			var f, i=this.grid.edit.info, d=this.get ? this.get(inRowIndex, inItem) : (this.value || this.defaultValue);
+			d = (d && d.replace && this.grid.escapeHTMLInData) ? d.replace(/&/g, '&').replace(/</g, '<') : d;
+			if(this.editable && (this.alwaysEditing || (i.rowIndex==inRowIndex && i.cell==this))){
+				return this.formatEditing(d, inRowIndex);
+			}else{
+				return this._defaultFormat(d, [d, inRowIndex, this]);
+			}
+		},
+		formatEditing: function(inDatum, inRowIndex){
+			// summary:
+			//	formats the cell for editing
+			// inDatum: anything
+			//	cell data to edit
+			// inRowIndex: int
+			//	grid row index
+			// returns: string of html to place in grid cell
+		},
+		// utility
+		getNode: function(inRowIndex){
+			// summary:
+			//	gets the dom node for a given grid cell.
+			// inRowIndex: int
+			// grid row index
+			// returns: dom node for a given grid cell
+			return this.view.getCellNode(inRowIndex, this.index);
+		},
+		getHeaderNode: function(){
+			return this.view.getHeaderCellNode(this.index);
+		},
+		getEditNode: function(inRowIndex){
+			return (this.getNode(inRowIndex) || 0).firstChild || 0;
+		},
+		canResize: function(){
+			var uw = this.unitWidth;
+			return uw && (uw!=='auto');
+		},
+		isFlex: function(){
+			var uw = this.unitWidth;
+			return uw && dojo.isString(uw) && (uw=='auto' || uw.slice(-1)=='%');
+		},
+		// edit support
+		applyEdit: function(inValue, inRowIndex){
+			this.grid.edit.applyCellEdit(inValue, this, inRowIndex);
+		},
+		cancelEdit: function(inRowIndex){
+			this.grid.doCancelEdit(inRowIndex);
+		},
+		_onEditBlur: function(inRowIndex){
+			if(this.grid.edit.isEditCell(inRowIndex, this.index)){
+				//console.log('editor onblur', e);
+				this.grid.edit.apply();
+			}
+		},
+		registerOnBlur: function(inNode, inRowIndex){
+			if(this.commitOnBlur){
+				dojo.connect(inNode, "onblur", function(e){
+					// hack: if editor still thinks this editor is current some ms after it blurs, assume we've focused away from grid
+					setTimeout(dojo.hitch(this, "_onEditBlur", inRowIndex), 250);
+				});
+			}
+		},
+		//protected
+		needFormatNode: function(inDatum, inRowIndex){
+			this._formatPending = true;
+			whenIdle(this, "_formatNode", inDatum, inRowIndex);
+		},
+		cancelFormatNode: function(){
+			this._formatPending = false;
+		},
+		//private
+		_formatNode: function(inDatum, inRowIndex){
+			if(this._formatPending){
+				this._formatPending = false;
+				// make cell selectable
+				dojo.setSelectable(this.grid.domNode, true);
+				this.formatNode(this.getEditNode(inRowIndex), inDatum, inRowIndex);
+			}
+		},
+		//protected
+		formatNode: function(inNode, inDatum, inRowIndex){
+			// summary:
+			//	format the editing dom node. Use when editor is a widget.
+			// inNode: dom node
+			// dom node for the editor
+			// inDatum: anything
+			//	cell data to edit
+			// inRowIndex: int
+			//	grid row index
+			if(dojo.isIE){
+				// IE sux bad
+				whenIdle(this, "focus", inRowIndex, inNode);
+			}else{
+				this.focus(inRowIndex, inNode);
+			}
+		},
+		dispatchEvent: function(m, e){
+			if(m in this){
+				return this[m](e);
+			}
+		},
+		//public
+		getValue: function(inRowIndex){
+			// summary:
+			//	returns value entered into editor
+			// inRowIndex: int
+			// grid row index
+			// returns:
+			//	value of editor
+			return this.getEditNode(inRowIndex)[this._valueProp];
+		},
+		setValue: function(inRowIndex, inValue){
+			// summary:
+			//	set the value of the grid editor
+			// inRowIndex: int
+			// grid row index
+			// inValue: anything
+			//	value of editor
+			var n = this.getEditNode(inRowIndex);
+			if(n){
+				n[this._valueProp] = inValue;
+			}
+		},
+		focus: function(inRowIndex, inNode){
+			// summary:
+			//	focus the grid editor
+			// inRowIndex: int
+			// grid row index
+			// inNode: dom node
+			//	editor node
+			focusSelectNode(inNode || this.getEditNode(inRowIndex));
+		},
+		save: function(inRowIndex){
+			// summary:
+			//	save editor state
+			// inRowIndex: int
+			// grid row index
+			this.value = this.value || this.getValue(inRowIndex);
+			//console.log("save", this.value, inCell.index, inRowIndex);
+		},
+		restore: function(inRowIndex){
+			// summary:
+			//	restore editor state
+			// inRowIndex: int
+			// grid row index
+			this.setValue(inRowIndex, this.value);
+			//console.log("restore", this.value, inCell.index, inRowIndex);
+		},
+		//protected
+		_finish: function(inRowIndex){
+			// summary:
+			//	called when editing is completed to clean up editor
+			// inRowIndex: int
+			// grid row index
+			dojo.setSelectable(this.grid.domNode, false);
+			this.cancelFormatNode();
+		},
+		//public
+		apply: function(inRowIndex){
+			// summary:
+			//	apply edit from cell editor
+			// inRowIndex: int
+			// grid row index
+			this.applyEdit(this.getValue(inRowIndex), inRowIndex);
+			this._finish(inRowIndex);
+		},
+		cancel: function(inRowIndex){
+			// summary:
+			//	cancel cell edit
+			// inRowIndex: int
+			// grid row index
+			this.cancelEdit(inRowIndex);
+			this._finish(inRowIndex);
+		}
+	});
+	dgc._Base.markupFactory = function(node, cellDef){
+		var d = dojo;
+		var formatter = d.trim(d.attr(node, "formatter")||"");
+		if(formatter){
+			cellDef.formatter = dojo.getObject(formatter)||formatter;
+		}
+		var get = d.trim(d.attr(node, "get")||"");
+		if(get){
+			cellDef.get = dojo.getObject(get);
+		}
+		var getBoolAttr = function(attr, cell, cellAttr){
+			var value = d.trim(d.attr(node, attr)||"");
+			if(value){ cell[cellAttr||attr] = !(value.toLowerCase()=="false"); }
+		};
+		getBoolAttr("sortDesc", cellDef);
+		getBoolAttr("editable", cellDef);
+		getBoolAttr("alwaysEditing", cellDef);
+		getBoolAttr("noresize", cellDef);
+		getBoolAttr("draggable", cellDef);
+
+		var value = d.trim(d.attr(node, "loadingText")||d.attr(node, "defaultValue")||"");
+		if(value){
+			cellDef.defaultValue = value;
+		}
+
+		var getStrAttr = function(attr, cell, cellAttr){
+			var value = d.trim(d.attr(node, attr)||"")||undefined;
+			if(value){ cell[cellAttr||attr] = value; }
+		};
+		getStrAttr("styles", cellDef);
+		getStrAttr("headerStyles", cellDef);
+		getStrAttr("cellStyles", cellDef);
+		getStrAttr("classes", cellDef);
+		getStrAttr("headerClasses", cellDef);
+		getStrAttr("cellClasses", cellDef);
+	};
+
+	dojo.declare("dojox.grid.cells.Cell", dgc._Base, {
+		// summary
+		// grid cell that provides a standard text input box upon editing
+		constructor: function(){
+			this.keyFilter = this.keyFilter;
+		},
+		// keyFilter: RegExp
+		//		optional regex for disallowing keypresses
+		keyFilter: null,
+		formatEditing: function(inDatum, inRowIndex){
+			this.needFormatNode(inDatum, inRowIndex);
+			return '<input class="dojoxGridInput" type="text" value="' + inDatum + '">';
+		},
+		formatNode: function(inNode, inDatum, inRowIndex){
+			this.inherited(arguments);
+			// FIXME: feels too specific for this interface
+			this.registerOnBlur(inNode, inRowIndex);
+		},
+		doKey: function(e){
+			if(this.keyFilter){
+				var key = String.fromCharCode(e.charCode);
+				if(key.search(this.keyFilter) == -1){
+					dojo.stopEvent(e);
+				}
+			}
+		},
+		_finish: function(inRowIndex){
+			this.inherited(arguments);
+			var n = this.getEditNode(inRowIndex);
+			try{
+				dojox.grid.util.fire(n, "blur");
+			}catch(e){}
+		}
+	});
+	dgc.Cell.markupFactory = function(node, cellDef){
+		dgc._Base.markupFactory(node, cellDef);
+		var d = dojo;
+		var keyFilter = d.trim(d.attr(node, "keyFilter")||"");
+		if(keyFilter){
+			cellDef.keyFilter = new RegExp(keyFilter);
+		}
+	};
+
+	dojo.declare("dojox.grid.cells.RowIndex", dgc.Cell, {
+		name: 'Row',
+
+		postscript: function(){
+			this.editable = false;
+		},
+		get: function(inRowIndex){
+			return inRowIndex + 1;
+		}
+	});
+	dgc.RowIndex.markupFactory = function(node, cellDef){
+		dgc.Cell.markupFactory(node, cellDef);
+	};
+
+	dojo.declare("dojox.grid.cells.Select", dgc.Cell, {
+		// summary:
+		// grid cell that provides a standard select for editing
+
+		// options: Array
+		// 		text of each item
+		options: null,
+
+		// values: Array
+		//		value for each item
+		values: null,
+
+		// returnIndex: Integer
+		// 		editor returns only the index of the selected option and not the value
+		returnIndex: -1,
+
+		constructor: function(inCell){
+			this.values = this.values || this.options;
+		},
+		formatEditing: function(inDatum, inRowIndex){
+			this.needFormatNode(inDatum, inRowIndex);
+			var h = [ '<select class="dojoxGridSelect">' ];
+			for (var i=0, o, v; ((o=this.options[i]) !== undefined)&&((v=this.values[i]) !== undefined); i++){
+				h.push("<option", (inDatum==v ? ' selected' : ''), ' value="' + v + '"', ">", o, "</option>");
+			}
+			h.push('</select>');
+			return h.join('');
+		},
+		getValue: function(inRowIndex){
+			var n = this.getEditNode(inRowIndex);
+			if(n){
+				var i = n.selectedIndex, o = n.options[i];
+				return this.returnIndex > -1 ? i : o.value || o.innerHTML;
+			}
+		}
+	});
+	dgc.Select.markupFactory = function(node, cell){
+		dgc.Cell.markupFactory(node, cell);
+		var d=dojo;
+		var options = d.trim(d.attr(node, "options")||"");
+		if(options){
+			var o = options.split(',');
+			if(o[0] != options){
+				cell.options = o;
+			}
+		}
+		var values = d.trim(d.attr(node, "values")||"");
+		if(values){
+			var v = values.split(',');
+			if(v[0] != values){
+				cell.values = v;
+			}
+		}
+	};
+
+	dojo.declare("dojox.grid.cells.AlwaysEdit", dgc.Cell, {
+		// summary:
+		// grid cell that is always in an editable state, regardless of grid editing state
+		alwaysEditing: true,
+		_formatNode: function(inDatum, inRowIndex){
+			this.formatNode(this.getEditNode(inRowIndex), inDatum, inRowIndex);
+		},
+		applyStaticValue: function(inRowIndex){
+			var e = this.grid.edit;
+			e.applyCellEdit(this.getValue(inRowIndex), this, inRowIndex);
+			e.start(this, inRowIndex, true);
+		}
+	});
+	dgc.AlwaysEdit.markupFactory = function(node, cell){
+		dgc.Cell.markupFactory(node, cell);
+	};
+
+	dojo.declare("dojox.grid.cells.Bool", dgc.AlwaysEdit, {
+		// summary:
+		// grid cell that provides a standard checkbox that is always on for editing
+		_valueProp: "checked",
+		formatEditing: function(inDatum, inRowIndex){
+			return '<input class="dojoxGridInput" type="checkbox"' + (inDatum ? ' checked="checked"' : '') + ' style="width: auto" />';
+		},
+		doclick: function(e){
+			if(e.target.tagName == 'INPUT'){
+				this.applyStaticValue(e.rowIndex);
+			}
+		}
+	});
+	dgc.Bool.markupFactory = function(node, cell){
+		dgc.AlwaysEdit.markupFactory(node, cell);
+	};
 })();
-}
diff --git a/dojox/grid/cells/dijit.js b/dojox/grid/cells/dijit.js
index 15f18fb..43708cb 100644
--- a/dojox/grid/cells/dijit.js
+++ b/dojox/grid/cells/dijit.js
@@ -1,14 +1,10 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.cells.dijit"]){
-dojo._hasResource["dojox.grid.cells.dijit"]=true;
 dojo.provide("dojox.grid.cells.dijit");
+
 dojo.require("dojox.grid.cells");
+
+// TODO: shouldn't it be the test file's job to require these modules,
+// if it is using them?  Most of these modules aren't referenced by this file.
+
 dojo.require("dijit.form.DateTextBox");
 dojo.require("dijit.form.TimeTextBox");
 dojo.require("dijit.form.ComboBox");
@@ -20,160 +16,219 @@ dojo.require("dijit.form.NumberTextBox");
 dojo.require("dijit.form.CurrencyTextBox");
 dojo.require("dijit.form.HorizontalSlider");
 dojo.require("dijit.Editor");
+
 (function(){
-var _1=dojox.grid.cells;
-dojo.declare("dojox.grid.cells._Widget",_1._Base,{widgetClass:dijit.form.TextBox,constructor:function(_2){
-this.widget=null;
-if(typeof this.widgetClass=="string"){
-dojo.deprecated("Passing a string to widgetClass is deprecated","pass the widget class object instead","2.0");
-this.widgetClass=dojo.getObject(this.widgetClass);
-}
-},formatEditing:function(_3,_4){
-this.needFormatNode(_3,_4);
-return "<div></div>";
-},getValue:function(_5){
-return this.widget.attr("value");
-},setValue:function(_6,_7){
-if(this.widget&&this.widget.attr){
-if(this.widget.onLoadDeferred){
-var _8=this;
-this.widget.onLoadDeferred.addCallback(function(){
-_8.widget.attr("value",_7===null?"":_7);
-});
-}else{
-this.widget.attr("value",_7);
-}
-}else{
-this.inherited(arguments);
-}
-},getWidgetProps:function(_9){
-return dojo.mixin({},this.widgetProps||{},{constraints:dojo.mixin({},this.constraint)||{},value:_9});
-},createWidget:function(_a,_b,_c){
-return new this.widgetClass(this.getWidgetProps(_b),_a);
-},attachWidget:function(_d,_e,_f){
-_d.appendChild(this.widget.domNode);
-this.setValue(_f,_e);
-},formatNode:function(_10,_11,_12){
-if(!this.widgetClass){
-return _11;
-}
-if(!this.widget){
-this.widget=this.createWidget.apply(this,arguments);
-}else{
-this.attachWidget.apply(this,arguments);
-}
-this.sizeWidget.apply(this,arguments);
-this.grid.rowHeightChanged(_12);
-this.focus();
-return undefined;
-},sizeWidget:function(_13,_14,_15){
-var p=this.getNode(_15),box=dojo.contentBox(p);
-dojo.marginBox(this.widget.domNode,{w:box.w});
-},focus:function(_16,_17){
-if(this.widget){
-setTimeout(dojo.hitch(this.widget,function(){
-dojox.grid.util.fire(this,"focus");
-}),0);
-}
-},_finish:function(_18){
-this.inherited(arguments);
-dojox.grid.util.removeNode(this.widget.domNode);
-}});
-_1._Widget.markupFactory=function(_19,_1a){
-_1._Base.markupFactory(_19,_1a);
-var d=dojo;
-var _1b=d.trim(d.attr(_19,"widgetProps")||"");
-var _1c=d.trim(d.attr(_19,"constraint")||"");
-var _1d=d.trim(d.attr(_19,"widgetClass")||"");
-if(_1b){
-_1a.widgetProps=d.fromJson(_1b);
-}
-if(_1c){
-_1a.constraint=d.fromJson(_1c);
-}
-if(_1d){
-_1a.widgetClass=d.getObject(_1d);
-}
-};
-dojo.declare("dojox.grid.cells.ComboBox",_1._Widget,{widgetClass:dijit.form.ComboBox,getWidgetProps:function(_1e){
-var _1f=[];
-dojo.forEach(this.options,function(o){
-_1f.push({name:o,value:o});
-});
-var _20=new dojo.data.ItemFileReadStore({data:{identifier:"name",items:_1f}});
-return dojo.mixin({},this.widgetProps||{},{value:_1e,store:_20});
-},getValue:function(){
-var e=this.widget;
-e.attr("displayedValue",e.attr("displayedValue"));
-return e.attr("value");
-}});
-_1.ComboBox.markupFactory=function(_21,_22){
-_1._Widget.markupFactory(_21,_22);
-var d=dojo;
-var _23=d.trim(d.attr(_21,"options")||"");
-if(_23){
-var o=_23.split(",");
-if(o[0]!=_23){
-_22.options=o;
-}
-}
-};
-dojo.declare("dojox.grid.cells.DateTextBox",_1._Widget,{widgetClass:dijit.form.DateTextBox,setValue:function(_24,_25){
-if(this.widget){
-this.widget.attr("value",new Date(_25));
-}else{
-this.inherited(arguments);
-}
-},getWidgetProps:function(_26){
-return dojo.mixin(this.inherited(arguments),{value:new Date(_26)});
-}});
-_1.DateTextBox.markupFactory=function(_27,_28){
-_1._Widget.markupFactory(_27,_28);
-};
-dojo.declare("dojox.grid.cells.CheckBox",_1._Widget,{widgetClass:dijit.form.CheckBox,getValue:function(){
-return this.widget.checked;
-},setValue:function(_29,_2a){
-if(this.widget&&this.widget.attributeMap.checked){
-this.widget.attr("checked",_2a);
-}else{
-this.inherited(arguments);
-}
-},sizeWidget:function(_2b,_2c,_2d){
-return;
-}});
-_1.CheckBox.markupFactory=function(_2e,_2f){
-_1._Widget.markupFactory(_2e,_2f);
-};
-dojo.declare("dojox.grid.cells.Editor",_1._Widget,{widgetClass:dijit.Editor,getWidgetProps:function(_30){
-return dojo.mixin({},this.widgetProps||{},{height:this.widgetHeight||"100px"});
-},createWidget:function(_31,_32,_33){
-var _34=new this.widgetClass(this.getWidgetProps(_32),_31);
-dojo.connect(_34,"onLoad",dojo.hitch(this,"populateEditor"));
-return _34;
-},formatNode:function(_35,_36,_37){
-this.content=_36;
-this.inherited(arguments);
-if(dojo.isMoz){
-var e=this.widget;
-e.open();
-if(this.widgetToolbar){
-dojo.place(e.toolbar.domNode,e.editingArea,"before");
-}
-}
-},populateEditor:function(){
-this.widget.attr("value",this.content);
-this.widget.placeCursorAtEnd();
-}});
-_1.Editor.markupFactory=function(_38,_39){
-_1._Widget.markupFactory(_38,_39);
-var d=dojo;
-var h=dojo.trim(dojo.attr(_38,"widgetHeight")||"");
-if(h){
-if((h!="auto")&&(h.substr(-2)!="em")){
-h=parseInt(h,10)+"px";
-}
-_39.widgetHeight=h;
-}
-};
+	var dgc = dojox.grid.cells;
+	dojo.declare("dojox.grid.cells._Widget", dgc._Base, {
+		widgetClass: dijit.form.TextBox,
+		constructor: function(inCell){
+			this.widget = null;
+			if(typeof this.widgetClass == "string"){
+				dojo.deprecated("Passing a string to widgetClass is deprecated", "pass the widget class object instead", "2.0");
+				this.widgetClass = dojo.getObject(this.widgetClass);
+			}
+		},
+		formatEditing: function(inDatum, inRowIndex){
+			this.needFormatNode(inDatum, inRowIndex);
+			return "<div></div>";
+		},
+		getValue: function(inRowIndex){
+			return this.widget.attr('value');
+		},
+		setValue: function(inRowIndex, inValue){
+			if(this.widget&&this.widget.attr){
+				//Look for lazy-loading editor and handle it via its deferred.
+				if(this.widget.onLoadDeferred){
+					var self = this;
+					this.widget.onLoadDeferred.addCallback(function(){
+						self.widget.attr("value",inValue===null?"":inValue); 
+					});
+				}else{
+					this.widget.attr("value", inValue); 
+				}
+			}else{
+				this.inherited(arguments);
+			}
+		},
+		getWidgetProps: function(inDatum){
+			return dojo.mixin(
+				{
+					dir: this.dir,
+					lang: this.lang
+				},
+				this.widgetProps||{},
+				{
+					constraints: dojo.mixin({}, this.constraint) || {}, //TODO: really just for ValidationTextBoxes
+					value: inDatum
+				}
+			);
+		},
+		createWidget: function(inNode, inDatum, inRowIndex){
+			return new this.widgetClass(this.getWidgetProps(inDatum), inNode);
+		},
+		attachWidget: function(inNode, inDatum, inRowIndex){
+			inNode.appendChild(this.widget.domNode);
+			this.setValue(inRowIndex, inDatum);
+		},
+		formatNode: function(inNode, inDatum, inRowIndex){
+			if(!this.widgetClass){
+				return inDatum;
+			}
+			if(!this.widget){
+				this.widget = this.createWidget.apply(this, arguments);
+			}else{
+				this.attachWidget.apply(this, arguments);
+			}
+			this.sizeWidget.apply(this, arguments);
+			this.grid.rowHeightChanged(inRowIndex);
+			this.focus();
+			return undefined;
+		},
+		sizeWidget: function(inNode, inDatum, inRowIndex){
+			var
+				p = this.getNode(inRowIndex),
+				box = dojo.contentBox(p);
+			dojo.marginBox(this.widget.domNode, {w: box.w});
+		},
+		focus: function(inRowIndex, inNode){
+			if(this.widget){
+				setTimeout(dojo.hitch(this.widget, function(){
+					dojox.grid.util.fire(this, "focus");
+				}), 0);
+			}
+		},
+		_finish: function(inRowIndex){
+			this.inherited(arguments);
+			dojox.grid.util.removeNode(this.widget.domNode);
+		}
+	});
+	dgc._Widget.markupFactory = function(node, cell){
+		dgc._Base.markupFactory(node, cell);
+		var d = dojo;
+		var widgetProps = d.trim(d.attr(node, "widgetProps")||"");
+		var constraint = d.trim(d.attr(node, "constraint")||"");
+		var widgetClass = d.trim(d.attr(node, "widgetClass")||"");
+		if(widgetProps){
+			cell.widgetProps = d.fromJson(widgetProps);
+		}
+		if(constraint){
+			cell.constraint = d.fromJson(constraint);
+		}
+		if(widgetClass){
+			cell.widgetClass = d.getObject(widgetClass);
+		}
+	};
+
+	dojo.declare("dojox.grid.cells.ComboBox", dgc._Widget, {
+		widgetClass: dijit.form.ComboBox,
+		getWidgetProps: function(inDatum){
+			var items=[];
+			dojo.forEach(this.options, function(o){
+				items.push({name: o, value: o});
+			});
+			var store = new dojo.data.ItemFileReadStore({data: {identifier:"name", items: items}});
+			return dojo.mixin({}, this.widgetProps||{}, {
+				value: inDatum,
+				store: store
+			});
+		},
+		getValue: function(){
+			var e = this.widget;
+			// make sure to apply the displayed value
+			e.attr('displayedValue', e.attr('displayedValue'));
+			return e.attr('value');
+		}
+	});
+	dgc.ComboBox.markupFactory = function(node, cell){
+		dgc._Widget.markupFactory(node, cell);
+		var d=dojo;
+		var options = d.trim(d.attr(node, "options")||"");
+		if(options){
+			var o = options.split(',');
+			if(o[0] != options){
+				cell.options = o;
+			}
+		}
+	};
+
+	dojo.declare("dojox.grid.cells.DateTextBox", dgc._Widget, {
+		widgetClass: dijit.form.DateTextBox,
+		setValue: function(inRowIndex, inValue){
+			if(this.widget){
+				this.widget.attr('value', new Date(inValue));
+			}else{
+				this.inherited(arguments);
+			}
+		},
+		getWidgetProps: function(inDatum){
+			return dojo.mixin(this.inherited(arguments), {
+				value: new Date(inDatum)
+			});
+		}
+	});
+	dgc.DateTextBox.markupFactory = function(node, cell){
+		dgc._Widget.markupFactory(node, cell);
+	};
+
+	dojo.declare("dojox.grid.cells.CheckBox", dgc._Widget, {
+		widgetClass: dijit.form.CheckBox,
+		getValue: function(){
+			return this.widget.checked;
+		},
+		setValue: function(inRowIndex, inValue){
+			if(this.widget&&this.widget.attributeMap.checked){
+				this.widget.attr("checked", inValue);
+			}else{
+				this.inherited(arguments);
+			}
+		},
+		sizeWidget: function(inNode, inDatum, inRowIndex){
+			return;
+		}
+	});
+	dgc.CheckBox.markupFactory = function(node, cell){
+		dgc._Widget.markupFactory(node, cell);
+	};
+
+	dojo.declare("dojox.grid.cells.Editor", dgc._Widget, {
+		widgetClass: dijit.Editor,
+		getWidgetProps: function(inDatum){
+			return dojo.mixin({}, this.widgetProps||{}, {
+				height: this.widgetHeight || "100px"
+			});
+		},
+		createWidget: function(inNode, inDatum, inRowIndex){
+			// widget needs its value set after creation
+			var widget = new this.widgetClass(this.getWidgetProps(inDatum), inNode);
+			dojo.connect(widget, 'onLoad', dojo.hitch(this, 'populateEditor'));
+			return widget;
+		},
+		formatNode: function(inNode, inDatum, inRowIndex){
+			this.content = inDatum;
+			this.inherited(arguments);
+			if(dojo.isMoz){
+				// FIXME: seem to need to reopen the editor and display the toolbar
+				var e = this.widget;
+				e.open();
+				if(this.widgetToolbar){
+					dojo.place(e.toolbar.domNode, e.editingArea, "before");
+				}
+			}
+		},
+		populateEditor: function(){
+			this.widget.attr('value', this.content);
+			this.widget.placeCursorAtEnd();
+		}
+	});
+	dgc.Editor.markupFactory = function(node, cell){
+		dgc._Widget.markupFactory(node, cell);
+		var d = dojo;
+		var h = dojo.trim(dojo.attr(node, "widgetHeight")||"");
+		if(h){
+			if((h != "auto")&&(h.substr(-2) != "em")){
+				h = parseInt(h, 10)+"px";
+			}
+			cell.widgetHeight = h;
+		}
+	};
 })();
-}
diff --git a/dojox/grid/cells/tree.js b/dojox/grid/cells/tree.js
index c5d1f84..fd5abf3 100644
--- a/dojox/grid/cells/tree.js
+++ b/dojox/grid/cells/tree.js
@@ -1,68 +1,67 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.cells.tree"]){
-dojo._hasResource["dojox.grid.cells.tree"]=true;
 dojo.provide("dojox.grid.cells.tree");
+
 dojo.require("dojox.grid.cells");
-dojox.grid.cells.TreeCell={formatAggregate:function(_1,_2,_3){
-var f,g=this.grid,i=g.edit.info,d=g.aggregator?g.aggregator.getForCell(this,_2,_1,_2===this.level?"cnt":this.parentCell.aggregate):(this.value||this.defaultValue);
-return this._defaultFormat(d,[d,_2-this.level,_3,this]);
-},formatIndexes:function(_4,_5){
-var f,g=this.grid,i=g.edit.info,d=this.get?this.get(_4[0],_5,_4):(this.value||this.defaultValue);
-if(this.editable&&(this.alwaysEditing||(i.rowIndex==_4[0]&&i.cell==this))){
-return this.formatEditing(d,_4[0],_4);
-}else{
-return this._defaultFormat(d,[d,_4[0],_4,this]);
-}
-},getOpenState:function(_6){
-var _7=this.grid,_8=_7.store,_9=null;
-if(_8.isItem(_6)){
-_9=_6;
-_6=_8.getIdentity(_6);
-}
-if(!this.openStates){
-this.openStates={};
-}
-if(typeof _6!="string"||!(_6 in this.openStates)){
-this.openStates[_6]=_7.getDefaultOpenState(this,_9);
-}
-return this.openStates[_6];
-},formatAtLevel:function(_a,_b,_c,_d,_e,_f){
-if(!dojo.isArray(_a)){
-_a=[_a];
-}
-var _10="";
-if(_c>this.level||(_c===this.level&&_d)){
-_f.push("dojoxGridSpacerCell");
-if(_c===this.level){
-_f.push("dojoxGridTotalCell");
-}
-_10="<span></span>";
-}else{
-if(_c<this.level){
-_f.push("dojoxGridSummaryCell");
-_10="<span class=\"dojoxGridSummarySpan\">"+this.formatAggregate(_b,_c,_a)+"</span>";
-}else{
-var ret="";
-if(this.isCollapsable){
-var _11=this.grid.store,id="";
-if(_11.isItem(_b)){
-id=_11.getIdentity(_b);
-}
-_f.push("dojoxGridExpandoCell");
-ret="<span dojoType=\"dojox.grid._Expando\" level=\""+_c+"\" class=\"dojoxGridExpando\""+"\" toggleClass=\""+_e+"\" itemId=\""+id+"\" cellIdx=\""+this.index+"\"></span>";
-}
-_10=ret+this.formatIndexes(_a,_b);
-}
-}
-if(this.grid.focus.cell&&this.index==this.grid.focus.cell.index&&_a.join("/")==this.grid.focus.rowIndex){
-_f.push(this.grid.focus.focusClass);
-}
-return _10;
-}};
-}
+
+dojox.grid.cells.TreeCell = {
+	formatAggregate: function(inItem, level, inRowIndexes){
+		var f, g=this.grid, i=g.edit.info, 
+			d=g.aggregator ? g.aggregator.getForCell(this, level, inItem, level === this.level ? "cnt" : this.parentCell.aggregate) : (this.value || this.defaultValue);
+		return this._defaultFormat(d, [d, level - this.level, inRowIndexes, this]);
+	},
+	formatIndexes: function(inRowIndexes, inItem){
+		var f, g=this.grid, i=g.edit.info, 
+			d=this.get ? this.get(inRowIndexes[0], inItem, inRowIndexes) : (this.value || this.defaultValue);
+		if(this.editable && (this.alwaysEditing || (i.rowIndex==inRowIndexes[0] && i.cell==this))){
+			return this.formatEditing(d, inRowIndexes[0], inRowIndexes);
+		}else{
+			return this._defaultFormat(d, [d, inRowIndexes[0], inRowIndexes, this]);
+		}
+	},
+	getOpenState: function(itemId){
+		var grid = this.grid, store = grid.store, itm = null;
+		if(store.isItem(itemId)){
+			itm = itemId;
+			itemId = store.getIdentity(itemId);
+		}
+		if(!this.openStates){ this.openStates = {}; }
+		if(typeof itemId != "string" || !(itemId in this.openStates)){
+			this.openStates[itemId] = grid.getDefaultOpenState(this, itm);
+		}
+		return this.openStates[itemId];
+	},
+	formatAtLevel: function(inRowIndexes, inItem, level, summaryRow, toggleClass, cellClasses){
+		if(!dojo.isArray(inRowIndexes)){
+			inRowIndexes = [inRowIndexes];
+		}
+		var result = "";
+		if(level > this.level || (level === this.level && summaryRow)){
+			cellClasses.push("dojoxGridSpacerCell");
+			if(level === this.level){
+				cellClasses.push("dojoxGridTotalCell");
+			}
+			result = '<span></span>';
+		}else if(level < this.level){
+			cellClasses.push("dojoxGridSummaryCell");
+			result = '<span class="dojoxGridSummarySpan">' + this.formatAggregate(inItem, level, inRowIndexes) + '</span>';
+		}else{
+			var ret = "";
+			if(this.isCollapsable){
+				var store = this.grid.store, id = "";
+				if(store.isItem(inItem)){
+					id = store.getIdentity(inItem);
+				}
+				cellClasses.push("dojoxGridExpandoCell");
+				ret = '<span dojoType="dojox.grid._Expando" level="' + level + '" class="dojoxGridExpando"' +
+						'" toggleClass="' + toggleClass + '" itemId="' + id + '" cellIdx="' + this.index + '"></span>';
+			}
+			result = ret + this.formatIndexes(inRowIndexes, inItem);
+		}
+
+		if(this.grid.focus.cell && this.index == this.grid.focus.cell.index &&
+			inRowIndexes.join('/') == this.grid.focus.rowIndex){
+			cellClasses.push(this.grid.focus.focusClass);
+		}
+
+		return result;
+	}
+};
diff --git a/dojox/grid/enhanced/_Builder.js b/dojox/grid/enhanced/_Builder.js
index f2d6964..39c9fe3 100644
--- a/dojox/grid/enhanced/_Builder.js
+++ b/dojox/grid/enhanced/_Builder.js
@@ -1,81 +1,115 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.enhanced._Builder"]){
-dojo._hasResource["dojox.grid.enhanced._Builder"]=true;
 dojo.provide("dojox.grid.enhanced._Builder");
+
 dojo.require("dojox.grid._Builder");
-dojo.declare("dojox.grid.enhanced._BuilderMixin",null,{generateCellMarkup:function(_1,_2,_3,_4){
-var _5=this.inherited(arguments);
-if(!_4){
-_5[4]+="<div class=\"dojoxGridCellContent\">";
-_5[6]="</div></td>";
-}
-return _5;
-},domouseup:function(e){
-if(e.cellNode){
-this.grid.onMouseUp(e);
-}
-}});
-dojo.declare("dojox.grid.enhanced._HeaderBuilder",[dojox.grid._HeaderBuilder,dojox.grid.enhanced._BuilderMixin],{getCellX:function(e){
-if(this.grid.nestedSorting){
-var _6=function(_7,_8){
-for(var n=_7;n&&_8(n);n=n.parentNode){
-}
-return n;
-};
-var _9=function(_a){
-var _b=_a.toUpperCase();
-return function(_c){
-return _c.tagName!=_b;
-};
-};
-var no=_6(e.target,_9("th"));
-var x=no?e.pageX-dojo.coords(no,true).x:-1;
-if(dojo.isIE){
-var _d=dojo.body().getBoundingClientRect();
-var _e=(_d.right-_d.left)/document.body.clientWidth;
-return parseInt(x/_e);
-}
-return x;
-}
-return this.inherited(arguments);
-},decorateEvent:function(e){
-var _f=this.inherited(arguments);
-if(this.grid.nestedSorting){
-var _10=this.grid._getSortEventInfo(e);
-e.unarySortChoice=_10.unarySortChoice;
-e.nestedSortChoice=_10.nestedSortChoice;
-e.selectChoice=_10.selectChoice;
-}
-return _f;
-},doclick:function(e){
-if((this._skipBogusClicks&&!this.grid.nestedSorting)||(this.grid.nestedSorting&&this.grid.ignoreEvent(e))){
-dojo.stopEvent(e);
-return true;
-}
-},colResizeSetup:function(e,_11){
-var _12=this.minColWidth;
-if(e.sourceView.grid.nestedSorting&&!this.grid.pluginMgr.isFixedCell(e.cell)){
-this.minColWidth=this.grid.getMinColWidth();
-var _13=dojo.connect(this,"endResizeColumn",dojo.hitch(this,function(){
-this.minColWidth=_12;
-dojo.disconnect(_13);
-}));
-}
-var _14=this.inherited(arguments);
-if(!dojo._isBodyLtr()&&dojo.isIE&&_14.followers){
-dojo.forEach(_14.followers,function(_15){
-if(!_15.left){
-_15.left=dojo.position(_15.node).x;
-}
+
+dojo.declare("dojox.grid.enhanced._BuilderMixin", null, {
+	// summary:
+	//		Common methods shared between dojox.grid.enhanced._HeaderBuilder and dojox.grid.enhanced._ContentBuilder
+	generateCellMarkup: function(inCell, inMoreStyles, inMoreClasses, isHeader){
+		// summary:
+		//		Overwritten, see dojox.grid._Builder.generateCellMarkup()
+		//		Add special css classes when nested sorting is on
+		var result = this.inherited(arguments);
+		if(!isHeader){
+			result[4] += '<div class="dojoxGridCellContent">';
+			result[6] = '</div></td>';
+		}
+		return result;
+	},
+	
+	domouseup: function(e){
+	//summary:
+	//		Handler when there is a mouse up event either in header or grid content 
+	//e: Event
+	//		The mouse up event
+		if(e.cellNode)
+			this.grid.onMouseUp(e);
+	}	
+});
+
+dojo.declare("dojox.grid.enhanced._HeaderBuilder", [dojox.grid._HeaderBuilder, dojox.grid.enhanced._BuilderMixin], {
+	// summary:
+	//		Extending dojox.grid._HeaderBuilder to overwrite some default behavior
+	getCellX: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._HeaderBuilder.getCellX()		
+		if(this.grid.nestedSorting){
+			var ascendDom = function(inNode, inWhile){
+				for(var n=inNode; n && inWhile(n); n=n.parentNode);
+				return n;
+			};			
+			var makeNotTagName = function(inTagName){
+				var name = inTagName.toUpperCase();
+				return function(node){ return node.tagName != name; };
+			};
+			var no = ascendDom(e.target, makeNotTagName("th"));
+            //console.log(dojo.coords(no).x, e.clientX);
+			var x = no ? e.pageX - dojo.coords(no, true).x : -1;
+			if(dojo.isIE){
+				//fix zoom issue in IE				
+				var rect = dojo.body().getBoundingClientRect();
+				var zoomLevel = (rect.right - rect.left) / document.body.clientWidth;
+				// console.log('zoomlevel', zoomLevel);
+				return parseInt(x / zoomLevel);
+			}
+            return x;
+		}
+		return this.inherited(arguments);
+	},
+	
+	decorateEvent: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._HeaderBuilder.decorateEvent()
+		var result = this.inherited(arguments);
+		
+		//add action types for nested sorting and column selection
+		if(this.grid.nestedSorting){
+			var sortInfo = this.grid._getSortEventInfo(e);
+			e.unarySortChoice = sortInfo.unarySortChoice;
+			e.nestedSortChoice = sortInfo.nestedSortChoice;
+			e.selectChoice = sortInfo.selectChoice;				
+		}
+		return result;
+	},
+	
+	doclick: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._HeaderBuilder.doclick()
+		if((this._skipBogusClicks && !this.grid.nestedSorting)
+		   ||(this.grid.nestedSorting && this.grid.ignoreEvent(e))){
+			dojo.stopEvent(e);
+			return true;
+		}
+	},
+	
+	colResizeSetup: function(e, isMouse){
+		// summary:
+		//		Overwritten, see dojox.grid._HeaderBuilder.colResizeSetup()
+		//		Set minimal column width for unfixed cells when nested sorting is on
+		var origMinColWidthRef = this.minColWidth;
+		//if(e.sourceView.grid.nestedSorting && this.minColWidths[e.cellIndex + '']){
+		if(e.sourceView.grid.nestedSorting && !this.grid.pluginMgr.isFixedCell(e.cell)){
+			this.minColWidth =  this.grid.getMinColWidth();
+			//this.minColWidth = this.minColWidths[e.cellIndex + ''];
+			var conn = dojo.connect(this, 'endResizeColumn', dojo.hitch(this,function(){
+				this.minColWidth = origMinColWidthRef;
+				dojo.disconnect(conn);
+			}));
+		}
+		var drag = this.inherited(arguments);
+		if(!dojo._isBodyLtr() && dojo.isIE && drag.followers){
+			//fix RTL in IE - left is NaN
+			dojo.forEach(drag.followers, function(follower){
+				if(!follower.left){
+					follower.left = dojo.position(follower.node).x;
+				}
+			});
+		}
+		return drag;
+	}	
+});
+
+dojo.declare("dojox.grid.enhanced._ContentBuilder", [dojox.grid._ContentBuilder, dojox.grid.enhanced._BuilderMixin], {
+	// summary:
+	// 		Extending dojox.grid._ContentBuilder to overwrite some default behavior
 });
-}
-return _14;
-}});
-dojo.declare("dojox.grid.enhanced._ContentBuilder",[dojox.grid._ContentBuilder,dojox.grid.enhanced._BuilderMixin],{});
-}
diff --git a/dojox/grid/enhanced/_Events.js b/dojox/grid/enhanced/_Events.js
index 5cb37a5..86ff028 100644
--- a/dojox/grid/enhanced/_Events.js
+++ b/dojox/grid/enhanced/_Events.js
@@ -1,370 +1,512 @@
-/*
-	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
-*/
+dojo.provide("dojox.grid.enhanced._Events");
 
+dojo.declare("dojox.grid.enhanced._Events", null, {
+	// summary:
+	//		Overwrite some default events of DataGrid
+	//		
+	// description: 
+	//		Methods are copied or replaced for overwriting, this might be refined once 
+	//		an overall plugin architecture is set up for DataGrid.
 
-if(!dojo._hasResource["dojox.grid.enhanced._Events"]){
-dojo._hasResource["dojox.grid.enhanced._Events"]=true;
-dojo.provide("dojox.grid.enhanced._Events");
-dojo.declare("dojox.grid.enhanced._Events",null,{_events:null,headerCellActiveClass:"dojoxGridHeaderActive",cellActiveClass:"dojoxGridCellActive",rowActiveClass:"dojoxGridRowActive",selectRegionHoverClass:"dojoxGridSelectRegionHover",constructor:function(_1){
-this._events=new dojox.grid._Events();
-for(p in this._events){
-if(!this[p]){
-this.p=this._events.p;
-}
-}
-_1.mixin(_1,this);
-},onStyleRow:function(_2){
-var i=_2;
-i.customClasses+=(i.odd?" dojoxGridRowOdd":"")+(i.selected?" dojoxGridRowSelected":"")+(i.over&&!this.isDndSelectEnable?" dojoxGridRowOver":"");
-this.focus.styleRow(_2);
-this.edit.styleRow(_2);
-},dokeyup:function(e){
-this.indirectSelection&&!this.pluginMgr.inSingleSelection()&&this.indirectSelector.dokeyup(e);
-},onKeyDown:function(e){
-if(e.altKey||e.metaKey){
-return;
-}
-if(e.ctrlKey&&!e.shiftKey){
-dojo.publish("CTRL_KEY_DOWN",[this,e]);
-}
-var _3=false;
-if(this.isDndSelectEnable&&!e.ctrlKey){
-this.select.keepState=false;
-}
-if(this.isDndSelectEnable&&!e.shiftKey){
-this.select.extendSelect=false;
-}
-var dk=dojo.keys;
-switch(e.keyCode){
-case dk.ENTER:
-_3=true;
-if(!this.edit.isEditing()){
-var _4=this.focus.getHeaderIndex();
-if(_4>=0){
-this.nestedSorting&&this.focus.focusView.header.decorateEvent(e);
-var _5=e.cell&&this.pluginMgr.isFixedCell(e.cell);
-!e.selectChoice&&!_5&&this.setSortIndex(_4,null,e);
-break;
-}else{
-!this.indirectSelection&&this.selection.clickSelect(this.focus.rowIndex,dojo.isCopyKey(e),e.shiftKey);
-}
-dojo.stopEvent(e);
-}
-if(!e.shiftKey){
-var _6=this.edit.isEditing();
-this.edit.apply();
-if(!_6&&!this.pluginMgr.isFixedCell(this.focus.cell)){
-this.edit.setEditCell(this.focus.cell,this.focus.rowIndex);
-}
-}
-if(!this.edit.isEditing()){
-var _7=this.focus.focusView||this.views.views[0];
-_7.content.decorateEvent(e);
-this.onRowClick(e);
-}
-break;
-case dk.SPACE:
-_3=true;
-if(!this.edit.isEditing()){
-var _4=this.focus.getHeaderIndex();
-if(_4>=0){
-this.focus.focusView.header.decorateEvent(e);
-if(this.indirectSelection&&e.cell&&e.cell.isRowSelector){
-return;
-}
-if(this.isDndSelectEnable&&(!this.nestedSorting&&!this.canSort()||this.nestedSorting&&e.selectChoice)){
-this.inDNDKeySelectingColumnMode=true;
-this.select.keepState=e.ctrlKey;
-this.select.extendSelect=e.shiftKey;
-if(!this.select.extendSelect){
-this.select.drugSelectionStart.colIndex=_4;
-}
-this.select.drugSelectColumn(_4);
-}else{
-var _5=e.cell&&this.pluginMgr.isFixedCell(e.cell);
-!_5&&e.rowIndex==-1&&e.cell&&this.setSortIndex(_4,null,e);
-}
-break;
-}else{
-if(this.isDndSelectEnable&&this.focus.isRowBar()){
-this.inDNDKeySelectingRowMode=true;
-this.select.keepState=e.ctrlKey;
-this.select.extendSelect=e.shiftKey;
-if(!this.select.extendSelect||this.pluginMgr.inSingleSelection()){
-this.select.drugSelectionStart.rowIndex=this.focus.getFocusedRowIndex();
-}
-this.select.drugSelectRow(this.focus.getFocusedRowIndex());
-}else{
-!this.indirectSelection&&this.selection.clickSelect(this.focus.rowIndex,dojo.isCopyKey(e),e.shiftKey);
-}
-}
-dojo.stopEvent(e);
-}
-break;
-case dk.LEFT_ARROW:
-case dk.RIGHT_ARROW:
-_3=true;
-this.nestedSorting&&this.focus.focusView.header.decorateEvent(e);
-var _8=this.isDndSelectEnable&&e.shiftKey;
-var _5=e.cell&&this.pluginMgr.isFixedCell(e.cell);
-if(this.nestedSorting&&this.focus.isNavHeader()&&!_8&&!_5){
-this.focus.navHeader(e);
-return;
-}
-if(!this.edit.isEditing()){
-var _9=e.keyCode;
-dojo.stopEvent(e);
-var _a=this.focus.getHeaderIndex();
-if(_a>=0&&(e.shiftKey&&e.ctrlKey)){
-this.focus.colSizeAdjust(e,_a,(_9==dk.LEFT_ARROW?-1:1)*5);
-return;
-}
-var _b=(_9==dk.LEFT_ARROW)?1:-1;
-if(dojo._isBodyLtr()){
-_b*=-1;
-}
-if(this.nestedSorting&&this.focus.isNavHeader()&&(_8||_5)){
-this.focus.navHeaderNode(_b,true);
-}else{
-if(!(this.isDndSelectEnable&&this.focus.isRowBar())){
-this.focus.move(0,_b);
-}
-}
-if(_8){
-var _4=this.focus.getHeaderIndex();
-if(!this.select.isColSelected(_a)){
-this.inDNDKeySelectingColumnMode=true;
-this.select.drugSelectionStart.colIndex=_a;
-}else{
-if(this.select.drugSelectionStart.colIndex==-1){
-this.select.restorLastDragPoint();
-}
-}
-if(e.ctrlKey){
-this.select.drugSelectColumnToMax(e.keyCode==dk.LEFT_ARROW?"left":"right");
-}else{
-this.select.drugSelectColumn(_4);
-}
-}
-}
-break;
-case dk.UP_ARROW:
-case dk.DOWN_ARROW:
-_3=true;
-if(this.nestedSorting&&this.focus.isNavHeader()){
-return;
-}
-var _c=e.keyCode==dk.UP_ARROW?-1:1;
-if(this.isDndSelectEnable){
-var _d=this.focus.getFocusedRowIndex();
-}
-if(this.isDndSelectEnable&&this.focus.isRowBar()){
-this.focus[e.keyCode==dk.UP_ARROW?"focusPrevRowBar":"focusNextRowBar"]();
-dojo.stopEvent(e);
-}else{
-if(!this.edit.isEditing()&&this.store&&0<=(this.focus.rowIndex+_c)&&(this.focus.rowIndex+_c)<this.rowCount){
-dojo.stopEvent(e);
-this.focus.move(_c,0);
-this.indirectSelection&&this.focus.cell&&this.focus.cell.focus(this.focus.rowIndex);
-!this.indirectSelection&&this.selection.clickSelect(this.focus.rowIndex,dojo.isCopyKey(e),e.shiftKey);
-}
-}
-if(this.isDndSelectEnable&&this.focus.isRowBar()&&e.shiftKey&&!this.pluginMgr.inSingleSelection()){
-if(!this.select.isRowSelected(_d)){
-this.inDNDKeySelectingRowMode=true;
-this.select.drugSelectionStart.rowIndex=_d;
-}else{
-if(this.select.drugSelectionStart.rowIndex==-1){
-this.select.restorLastDragPoint();
-}
-}
-if(e.ctrlKey){
-this.select.drugSelectRowToMax(e.keyCode==dk.UP_ARROW?"up":"down");
-}else{
-var _e=this.focus.getFocusedRowIndex();
-this.select.drugSelectRow(_e);
-}
-}else{
-if(this.indirectSelection&&e.shiftKey&&!this.pluginMgr.inSingleSelection()&&this.focus.rowIndex>=0){
-this.focus.focusView.content.decorateEvent(e);
-if(e.cellIndex!=0||e.rowIndex==0&&_c==-1){
-return;
-}
-this.indirectSelector.swipeSelectionByKey(e,_c);
-}
-}
-break;
-case dk.ESCAPE:
-try{
-this.select.cancelDND();
-}
-catch(e){
-}
-break;
-}
-!_3&&(dojo.hitch(this,this._events.onKeyDown)(e));
-},onMouseDown:function(e){
-dojo.hitch(this,this._events.onMouseDown)(e);
-if(this.isDndSelectEnable&&!e.shiftKey){
-this.select.setDrugStartPoint(e.cellIndex,e.rowIndex);
-}
-},onMouseUp:function(e){
-e.rowIndex==-1?this.onHeaderCellMouseUp(e):this.onCellMouseUp(e);
-},onMouseOutRow:function(e){
-if(this.isDndSelectEnable){
-return;
-}
-dojo.hitch(this,this._events.onMouseOutRow)(e);
-},onMouseDownRow:function(e){
-if(this.isDndSelectEnable){
-return;
-}
-dojo.hitch(this,this._events.onMouseDownRow)(e);
-},onCellMouseOver:function(e){
-dojo.hitch(this,this._events.onCellMouseOver)(e);
-var _f=this.pluginMgr.isFixedCell(e.cell)||this.rowSelectCell&&this.rowSelectCell.inIndirectSelectionMode();
-if(this.isDndSelectEnable&&!_f){
-if(this.select.isInSelectingMode("col")){
-this.select.drugSelectColumn(e.cell.index);
-}else{
-if(this.select.isInSelectingMode("cell")){
-this.select.drugSelectCell(e.cellIndex,e.rowIndex);
-}else{
-this.select.setDrugCoverDivs(e.cellIndex,e.rowIndex);
-}
-}
-}
-},onCellMouseOut:function(e){
-dojo.hitch(this,this._events.onCellMouseOut)(e);
-this.doubleAffordance&&e.cellNode&&dojo.removeClass(e.cellNode,this.cellActiveClass);
-},onCellMouseDown:function(e){
-dojo.addClass(e.cellNode,this.cellActiveClass);
-dojo.addClass(e.rowNode,this.rowActiveClass);
-if(this.isDndSelectEnable){
-this.focus._blurRowBar();
-if(e.cellIndex>this.select.exceptColumnsTo){
-this.select.setInSelectingMode("cell",true);
-}
-}
-},onCellMouseUp:function(e){
-dojo.removeClass(e.cellNode,this.cellActiveClass);
-dojo.removeClass(e.rowNode,this.rowActiveClass);
-},onCellClick:function(e){
-if(this.isDndSelectEnable){
-this.focus._blurRowBar();
-this._click[0]=this._click[1];
-this._click[1]=e;
-this.select.cellClick(e.cellIndex,e.rowIndex);
-!this.edit.isEditCell(e.rowIndex,e.cellIndex)&&!this.edit.isEditing()&&this.select.cleanAll();
-this.focus.setFocusCell(e.cell,e.rowIndex);
-}else{
-dojo.hitch(this,this._events.onCellClick)(e);
-}
-},onCellDblClick:function(e){
-if(this.pluginMgr.isFixedCell(e.cell)){
-return;
-}
-this._click.length>1&&(!this._click[0]||!this._click[1])&&(this._click[0]=this._click[1]=e);
-dojo.hitch(this,this._events.onCellDblClick)(e);
-},onRowClick:function(e){
-this.edit.rowClick(e);
-!this.indirectSelection&&this.selection.clickSelectEvent(e);
-},onRowMouseOver:function(e){
-if(this.isDndSelectEnable&&!this.pluginMgr.inSingleSelection()){
-if(this.select.isInSelectingMode("row")){
-this.select.drugSelectRow(e.rowIndex);
-}else{
-}
-}
-if(!e.cell&&e.cellIndex<0||e.cell&&(e.cell!=this.rowSelectCell)&&this.indirectSelection){
-var _10=this.rowSelectCell;
-_10&&_10.onRowMouseOver&&_10.onRowMouseOver(e);
-}
-},onRowMouseOut:function(e){
-if(this.isDndSelectEnable){
-if(this.select.isInSelectingMode("row")){
-this.select.drugSelectRow(e.rowIndex);
-}
-}
-},onRowContextMenu:function(e){
-!this.edit.isEditing()&&this.menus&&this.showRowCellMenu(e);
-},onSelectedRegionContextMenu:function(e){
-if(this.selectedRegionMenu){
-this.selectedRegionMenu._openMyself(e);
-dojo.stopEvent(e);
-}
-},onHeaderCellMouseOver:function(e){
-if(e.cellNode){
-dojo.addClass(e.cellNode,this.cellOverClass);
-if(this.nestedSorting&&!this._inResize(e.sourceView)&&!this.pluginMgr.isFixedCell(e.cell)&&!(this.isDndSelectEnable&&this.select.isInSelectingMode("col"))){
-this.addHoverSortTip(e);
-}
-if(this.isDndSelectEnable){
-if(this.select.isInSelectingMode("col")){
-this.select.drugSelectColumn(e.cell.index);
-}else{
-this.select.clearDrugDivs();
-}
-}
-}
-},onHeaderCellMouseOut:function(e){
-if(e.cellNode){
-dojo.removeClass(e.cellNode,this.cellOverClass);
-dojo.removeClass(e.cellNode,this.headerCellActiveClass);
-if(this.nestedSorting&&!this.pluginMgr.isFixedCell(e.cell)){
-if(this.focus.headerCellInFocus(e.cellIndex)){
-this._toggleHighlight(e.sourceView,e,true);
-}else{
-this.removeHoverSortTip(e);
-}
-}
-}
-},onHeaderCellMouseDown:function(e){
-var _11=!this.nestedSorting?e.cellNode:this._getChoiceRegion(e.cellNode,e);
-_11&&dojo.addClass(_11,this.headerCellActiveClass);
-if(this.nestedSorting&&!e.selectChoice){
-return;
-}
-if(this.isDndSelectEnable){
-this.focus._blurRowBar();
-try{
-this.focus.focusHeaderNode(e.cellIndex,false,true);
-}
-catch(e){
-}
-if(e.button==2){
-return;
-}
-if(e.cellNode){
-this.select.setInSelectingMode("col",true);
-this.select.keepState=e.ctrlKey;
-this.select.extendSelect=e.shiftKey;
-if(this.select.extendSelect){
-this.select.restorLastDragPoint();
-}else{
-this.select.drugSelectionStart.colIndex=e.cellIndex;
-}
-this.select.drugSelectColumn(e.cellIndex);
-}
-}
-},onHeaderCellMouseUp:function(e){
-var _12=!this.nestedSorting?e.cellNode:this._getChoiceRegion(e.cellNode,e);
-if(_12){
-dojo.removeClass(_12,this.headerCellActiveClass);
-e.selectChoice&&dojo.addClass(_12,this.selectRegionHoverClass);
-}
-},onHeaderCellClick:function(e){
-if(this.indirectSelection&&e.cell&&e.cell.isRowSelector){
-return;
-}
-dojo.hitch(this,this._events.onHeaderCellClick)(e);
-},onHeaderContextMenu:function(e){
-if(this.nestedSorting&&this.headerMenu){
-this._toggleHighlight(e.sourceView,e,true);
-}
-dojo.hitch(this,this._events.onHeaderContextMenu)(e);
-}});
-}
+	//_events: Object
+	//		Method map cached from dojox.grid._Events().
+	_events: null,
+
+	//headerCellActiveClass: String
+	// 		css class to apply to grid header cells when activated(mouse down)
+	headerCellActiveClass: 'dojoxGridHeaderActive',
+	
+	//cellActiveClass: String
+	// 		css class to apply to grid content cells when activated(mouse down)
+	cellActiveClass: 'dojoxGridCellActive',
+	
+	//rowActiveClass: String
+	// 		css class to apply to grid rows when activated(mouse down)
+	rowActiveClass: 'dojoxGridRowActive',		
+
+	//selectRegionHoverClass: String
+	// 		css class to apply to select regions in header cells when mouse over
+	selectRegionHoverClass: 'dojoxGridSelectRegionHover',	
+
+	constructor: function(inGrid){
+		//get the default Grid events
+		this._events = new dojox.grid._Events();
+		//for methods that won't be overwritten, copy them to "this" scope
+		for(p in this._events){
+			if(!this[p]){
+				this.p = this._events.p;
+			}
+		}
+		//mixin "this" to Grid
+		inGrid.mixin(inGrid, this);
+	},
+	
+	onStyleRow: function(inRow){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onStyleRow()
+		var i = inRow;
+		i.customClasses += (i.odd?" dojoxGridRowOdd":"") + (i.selected?" dojoxGridRowSelected":"") + (i.over/*&&!this.isDndSelectEnable*/?" dojoxGridRowOver":"");
+		this.focus.styleRow(inRow);
+		this.edit.styleRow(inRow);
+	},
+	
+	dokeyup: function(e) {
+		// summary:
+		// 		Grid key up event handler.
+		// e: Event
+		//		Un-decorated event object
+		this.indirectSelection && !this.pluginMgr.inSingleSelection() && this.indirectSelector.dokeyup(e);
+	},
+	
+	onKeyDown: function(e){
+		// summary:
+		// 		Overwritten, see dojox.grid._Events.onKeyDown()
+		if(e.altKey || e.metaKey){ return; }
+		
+		if (e.ctrlKey && !e.shiftKey){
+			dojo.publish("CTRL_KEY_DOWN", [this, e]);
+		}
+		var executed = false;
+		
+		if(this.isDndSelectEnable && !e.ctrlKey){
+			this.select.keepState = false;
+		}
+		if(this.isDndSelectEnable && !e.shiftKey){
+			this.select.extendSelect = false;
+		}
+		var dk = dojo.keys;
+		switch(e.keyCode){
+			case dk.ENTER:
+				executed = true;
+				if(!this.edit.isEditing()){
+					var colIdx = this.focus.getHeaderIndex();
+					if(colIdx >= 0){
+						this.nestedSorting && this.focus.focusView.header.decorateEvent(e);
+						var isRowSelector = e.cell && this.pluginMgr.isFixedCell(e.cell);
+						!e.selectChoice && !isRowSelector && this.setSortIndex(colIdx, null, e);
+						break;
+					}else{
+						!this.indirectSelection && this.selection.clickSelect(this.focus.rowIndex, dojo.isCopyKey(e), e.shiftKey);
+					}
+					dojo.stopEvent(e);
+				}
+				if(!e.shiftKey){
+					var isEditing = this.edit.isEditing();
+					this.edit.apply();
+					if(!isEditing && !this.pluginMgr.isFixedCell(this.focus.cell)){
+						this.edit.setEditCell(this.focus.cell, this.focus.rowIndex);
+					}
+				}
+				if (!this.edit.isEditing()){
+					var curView = this.focus.focusView || this.views.views[0];  //if no focusView than only one view
+					curView.content.decorateEvent(e);
+					this.onRowClick(e);
+				}
+				break;
+			case dk.SPACE:
+				executed = true;
+				if(!this.edit.isEditing()){
+					var colIdx = this.focus.getHeaderIndex();
+					if(colIdx >= 0) {
+						//this.nestedSorting && this.focus.focusView.header.decorateEvent(e);
+						this.focus.focusView.header.decorateEvent(e);
+						if(this.indirectSelection && e.cell && e.cell.isRowSelector){
+							return;
+						}
+						if (this.isDndSelectEnable && (!this.nestedSorting && !this.canSort() || this.nestedSorting && e.selectChoice)){
+							this.inDNDKeySelectingColumnMode = true;
+							
+							this.select.keepState = e.ctrlKey;
+							this.select.extendSelect = e.shiftKey;
+							if (!this.select.extendSelect) {
+								this.select.drugSelectionStart.colIndex = colIdx;
+							}
+							this.select.drugSelectColumn(colIdx);
+						} else {
+							//this.nestedSorting && this.focus.focusView.header.decorateEvent(e);
+							var isRowSelector = e.cell && this.pluginMgr.isFixedCell(e.cell);
+							!isRowSelector && e.rowIndex == -1 && e.cell && this.setSortIndex(colIdx, null, e);
+						}
+						break;
+					}else if(this.isDndSelectEnable && this.focus.isRowBar()){
+						this.inDNDKeySelectingRowMode = true;
+						this.select.keepState = e.ctrlKey;
+						this.select.extendSelect = e.shiftKey;
+						if(!this.select.extendSelect || this.pluginMgr.inSingleSelection()){
+							this.select.drugSelectionStart.rowIndex = this.focus.getFocusedRowIndex();
+						} 
+						this.select.drugSelectRow(this.focus.getFocusedRowIndex());
+					}else {
+						!this.indirectSelection && this.selection.clickSelect(this.focus.rowIndex, dojo.isCopyKey(e), e.shiftKey);
+					}
+					dojo.stopEvent(e);
+				}
+				break;
+			case dk.LEFT_ARROW:
+			case dk.RIGHT_ARROW:
+				executed = true;
+				this.nestedSorting && this.focus.focusView.header.decorateEvent(e);
+				var needDndSelect = this.isDndSelectEnable && e.shiftKey;
+				var isRowSelector = e.cell && this.pluginMgr.isFixedCell(e.cell);
+				if(this.nestedSorting && this.focus.isNavHeader() && !needDndSelect && !isRowSelector){
+					//dojo.stopEvent(e);
+					this.focus.navHeader(e);
+					return;
+				}
+				if(!this.edit.isEditing()){
+					var keyCode = e.keyCode;  // IE seems to lose after stopEvent when modifier keys
+					dojo.stopEvent(e);
+					var origColIdx = this.focus.getHeaderIndex();
+					if (origColIdx >= 0 && (e.shiftKey && e.ctrlKey)){
+						this.focus.colSizeAdjust(e, origColIdx, (keyCode == dk.LEFT_ARROW ? -1 : 1)*5);
+						return;
+					}
+					var offset = (keyCode == dk.LEFT_ARROW) ? 1 : -1;
+					if(dojo._isBodyLtr()){ offset *= -1; }
+					//var origColSelected = this.select.isColSelected(origColIdx);
+					if(this.nestedSorting && this.focus.isNavHeader() && (needDndSelect || isRowSelector)){
+						this.focus.navHeaderNode(offset, true);
+					}else if(!(this.isDndSelectEnable && this.focus.isRowBar())){ //fix DnD, if is DnDSelectEnable, and foucus on RowBar, invaild the left & right key
+						this.focus.move(0, offset);
+					}
+					//if(this.isDndSelectEnable && e.shiftKey) {
+					if(needDndSelect) {
+						var colIdx = this.focus.getHeaderIndex();
+						if(!this.select.isColSelected(origColIdx)){
+							this.inDNDKeySelectingColumnMode = true;
+							this.select.drugSelectionStart.colIndex = origColIdx;
+						} else if(this.select.drugSelectionStart.colIndex == -1){
+							this.select.restorLastDragPoint();
+						}
+						if(e.ctrlKey){
+							this.select.drugSelectColumnToMax(e.keyCode==dk.LEFT_ARROW?"left":"right");
+						} else {
+							this.select.drugSelectColumn(colIdx);
+						}
+					}
+				}
+				break;
+			case dk.UP_ARROW:
+			case dk.DOWN_ARROW:
+				executed = true;
+				if(this.nestedSorting && this.focus.isNavHeader()){
+					return;
+				}
+				var delta = e.keyCode == dk.UP_ARROW ? -1 : 1;
+			    if(this.isDndSelectEnable){
+					var origRowIdx = this.focus.getFocusedRowIndex();
+				}
+				if(this.isDndSelectEnable && this.focus.isRowBar()){
+					this.focus[e.keyCode == dk.UP_ARROW ? 'focusPrevRowBar' : 'focusNextRowBar']();
+					dojo.stopEvent(e);
+				}else if(!this.edit.isEditing() && this.store && 0 <= (this.focus.rowIndex + delta) && (this.focus.rowIndex + delta) < this.rowCount){
+					dojo.stopEvent(e);
+					this.focus.move(delta, 0);
+					this.indirectSelection && this.focus.cell && this.focus.cell.focus(this.focus.rowIndex);			
+					!this.indirectSelection && this.selection.clickSelect(this.focus.rowIndex, dojo.isCopyKey(e), e.shiftKey);
+				}
+				if(this.isDndSelectEnable && this.focus.isRowBar() && e.shiftKey && !this.pluginMgr.inSingleSelection()) {
+					if(!this.select.isRowSelected(origRowIdx)){
+						this.inDNDKeySelectingRowMode = true;
+						this.select.drugSelectionStart.rowIndex = origRowIdx;
+					} else if(this.select.drugSelectionStart.rowIndex == -1) {
+						this.select.restorLastDragPoint();
+					}
+					if (e.ctrlKey) {
+						this.select.drugSelectRowToMax(e.keyCode == dk.UP_ARROW ? "up" : "down");
+					} else {
+						var rowIdy = this.focus.getFocusedRowIndex();
+						this.select.drugSelectRow(rowIdy);
+					}
+				} else if(this.indirectSelection && e.shiftKey && !this.pluginMgr.inSingleSelection() && this.focus.rowIndex >= 0) {
+					this.focus.focusView.content.decorateEvent(e);
+					if(e.cellIndex != 0 || e.rowIndex == 0 && delta == -1){
+						return;
+					}
+					this.indirectSelector.swipeSelectionByKey(e, delta);
+				}
+				break;
+			case dk.ESCAPE:
+				try{
+					this.select.cancelDND();
+				} catch(e) {
+					console.debug(e);
+				}
+				break;
+		}
+		//invoke dojox.grid._Events.onKeyDown()
+		!executed && (dojo.hitch(this, this._events.onKeyDown)(e));
+	},
+
+	onMouseDown: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onMouseDown()
+				
+		//invoke dojox.grid._Events.onMouseDown()
+		dojo.hitch(this, this._events.onMouseDown)(e);
+		if(this.isDndSelectEnable && !e.shiftKey){			
+			this.select.setDrugStartPoint(e.cellIndex, e.rowIndex);
+		}
+	},
+	
+	onMouseUp: function(e){
+		// summary:
+		//		New - Event fired when mouse is up inside grid.
+		// e: Event
+		//		Decorated event object that contains reference to grid, cell, and rowIndex
+		e.rowIndex == -1 ? this.onHeaderCellMouseUp(e) : this.onCellMouseUp(e);
+	},
+	
+	onMouseOutRow: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onMouseOutRow()
+		if (this.isDndSelectEnable) {
+			//waiting ...
+			return;
+		}
+		//invoke dojox.grid._Events.onMouseOutRow()
+		dojo.hitch(this, this._events.onMouseOutRow)(e);
+	},
+	
+	onMouseDownRow: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onMouseDownRow()
+		if (this.isDndSelectEnable) {
+			//waiting ...
+			return;
+		}
+		//invoke dojox.grid._Events.onMouseDownRow()
+		dojo.hitch(this, this._events.onMouseDownRow)(e);
+	},
+
+	onCellMouseOver: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onCellMouseOver()
+		
+		//invoke dojox.grid._Events.onCellMouseOver()
+		dojo.hitch(this, this._events.onCellMouseOver)(e);
+		var inIndirectSelectionMode = this.pluginMgr.isFixedCell(e.cell) || this.rowSelectCell && this.rowSelectCell.inIndirectSelectionMode();
+		if(this.isDndSelectEnable && !inIndirectSelectionMode){
+			if(this.select.isInSelectingMode("col")){
+				this.select.drugSelectColumn(e.cell.index);
+			}else if(this.select.isInSelectingMode("cell")){
+				this.select.drugSelectCell(e.cellIndex, e.rowIndex);
+			}else{
+				this.select.setDrugCoverDivs(e.cellIndex, e.rowIndex);
+			}
+		}
+	},
+	
+	onCellMouseOut: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onCellMouseOut()
+		
+		//invoke dojox.grid._Events.onCellMouseOut()
+		dojo.hitch(this, this._events.onCellMouseOut)(e);	
+		this.doubleAffordance && e.cellNode && dojo.removeClass(e.cellNode, this.cellActiveClass);
+	},
+	
+	onCellMouseDown: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onCellMouseDown()
+		dojo.addClass(e.cellNode, this.cellActiveClass);
+		dojo.addClass(e.rowNode, this.rowActiveClass);
+		if(this.isDndSelectEnable){
+			this.focus._blurRowBar();
+			if(e.cellIndex > this.select.exceptColumnsTo){
+				this.select.setInSelectingMode("cell", true);
+			}
+		}
+	},
+	
+	onCellMouseUp: function(e){
+		// summary:
+		//		New - Event fired when mouse is up inside content cell.
+		// e: Event
+		//		Decorated event object that contains reference to grid, cell, and rowIndex
+		dojo.removeClass(e.cellNode, this.cellActiveClass);
+		dojo.removeClass(e.rowNode, this.rowActiveClass);
+	},
+
+	onCellClick: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onCellClick()
+		if(this.isDndSelectEnable){
+			this.focus._blurRowBar();	//fix DnD blur
+			this._click[0] = this._click[1];
+			this._click[1] = e;
+			this.select.cellClick(e.cellIndex, e.rowIndex);
+			!this.edit.isEditCell(e.rowIndex, e.cellIndex) && !this.edit.isEditing() && this.select.cleanAll();
+			this.focus.setFocusCell(e.cell, e.rowIndex);
+		}else{
+			//invoke dojox.grid._Events.onCellClick()
+			dojo.hitch(this, this._events.onCellClick)(e);
+		} 
+	},
+
+	onCellDblClick: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onCellDblClick()
+		if(this.pluginMgr.isFixedCell(e.cell)){ return; }
+		this._click.length > 1 && (!this._click[0] || !this._click[1]) && (this._click[0] = this._click[1] = e);
+		//invoke dojox.grid._Events.onCellDblClick()
+		dojo.hitch(this, this._events.onCellDblClick)(e);
+	},
+
+	onRowClick: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onRowClick()
+		this.edit.rowClick(e);
+		!this.indirectSelection && this.selection.clickSelectEvent(e);
+	},
+
+	onRowMouseOver: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onRowMouseOver()
+		if(this.isDndSelectEnable && !this.pluginMgr.inSingleSelection()){
+			if(this.select.isInSelectingMode("row")){
+				this.select.drugSelectRow(e.rowIndex);
+			}else{
+				//this.select.setDrugCoverDivs(e.cellIndex, e.rowIndex);
+			}
+		}
+		//indirect selection
+		if(!e.cell && e.cellIndex < 0/*row selector view*/ || e.cell && (e.cell != this.rowSelectCell) && this.indirectSelection){
+			var _rowSelectCell = this.rowSelectCell;
+			_rowSelectCell && _rowSelectCell.onRowMouseOver && _rowSelectCell.onRowMouseOver(e);			
+		}
+	},
+
+	onRowMouseOut: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onRowMouseOut()
+		if(this.isDndSelectEnable){
+			if(this.select.isInSelectingMode("row")){
+				this.select.drugSelectRow(e.rowIndex);
+			}
+		}
+	},
+
+	onRowContextMenu: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onRowContextMenu()
+		!this.edit.isEditing() && this.menus && this.showRowCellMenu(e);
+		//dojo.stopEvent(e);
+	},
+	
+	onSelectedRegionContextMenu: function(e){
+		// summary:
+		//		New - Event fired when a selected region context menu is accessed via mouse right click.
+		// e: Event
+		//		Decorated event object which contains reference to grid and info of selected 
+		//		regions(selection type - row|column, selected index - [...])
+		if(this.selectedRegionMenu){
+			this.selectedRegionMenu._openMyself({
+				target: e.target,
+				coords: "pageX" in e ? {
+					x: e.pageX,
+					y: e.pageY
+				} : null
+			});
+			dojo.stopEvent(e);
+		}
+	},
+
+	onHeaderCellMouseOver: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onHeaderCellMouseOver()
+		if(e.cellNode){
+			dojo.addClass(e.cellNode, this.cellOverClass);
+			if(this.nestedSorting && !this._inResize(e.sourceView) && !this.pluginMgr.isFixedCell(e.cell) && !(this.isDndSelectEnable && this.select.isInSelectingMode("col"))){
+				this.addHoverSortTip(e);
+			}			
+			if(this.isDndSelectEnable){
+				if(this.select.isInSelectingMode("col")){
+					this.select.drugSelectColumn(e.cell.index);
+				}else{
+					this.select.clearDrugDivs();
+				}
+			}
+		}
+	},
+
+	onHeaderCellMouseOut: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onHeaderCellMouseOut()
+		if(e.cellNode){
+			dojo.removeClass(e.cellNode, this.cellOverClass);
+			dojo.removeClass(e.cellNode, this.headerCellActiveClass);
+			if(this.nestedSorting && !this.pluginMgr.isFixedCell(e.cell)){
+				if(this.focus.headerCellInFocus(e.cellIndex)){
+					this._toggleHighlight(e.sourceView, e, true);
+				}else{
+					this.removeHoverSortTip(e);					
+				}
+			}
+		}
+	},
+	
+	onHeaderCellMouseDown: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onHeaderCellMouseDown()
+		var node = !this.nestedSorting ? e.cellNode : this._getChoiceRegion(e.cellNode, e/*also contains choice info*/);
+		node && dojo.addClass(node, this.headerCellActiveClass);
+		if(this.nestedSorting && !e.selectChoice){ return; }
+		if(this.isDndSelectEnable){
+			this.focus._blurRowBar(); //fix DnD blur
+			try{
+				this.focus.focusHeaderNode(e.cellIndex, false, true);
+			}catch(e){
+				console.debug("Error fired in dojox.grid._event.js onHeaderCellMouseDown():" + e);
+			}
+			if(e.button == 2){
+				return;//always return for oncontextmenu event to only show menu
+			}
+			if(e.cellNode){
+				this.select.setInSelectingMode("col", true);
+				this.select.keepState = e.ctrlKey;
+				this.select.extendSelect = e.shiftKey;
+				if(this.select.extendSelect){
+					this.select.restorLastDragPoint();
+				} else {
+					this.select.drugSelectionStart.colIndex = e.cellIndex;
+				}
+				this.select.drugSelectColumn(e.cellIndex);
+			}
+		}
+	},
+	
+	onHeaderCellMouseUp: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onHeaderCellMouseUp()
+		var node = !this.nestedSorting ? e.cellNode : this._getChoiceRegion(e.cellNode, e/*also contains choice info*/);
+		if(node){
+			dojo.removeClass(node, this.headerCellActiveClass);
+			e.selectChoice && dojo.addClass(node, this.selectRegionHoverClass);
+		}
+	},
+
+	onHeaderCellClick: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onHeaderCellClick()
+		if(this.nestedSorting){
+			if((e.unarySortChoice || e.nestedSortChoice) && !this._inResize(e.sourceView)){
+				this.setSortIndex(e.cell.index, null, e);//nested sorting
+			}
+		}else if(!(this.indirectSelection && e.cell && e.cell.isRowSelector)){
+			this.setSortIndex(e.cell.index);//single sorting
+		}
+		//invoke dojox.grid._Events.onHeaderClick()
+		dojo.hitch(this, this._events.onHeaderClick)(e);
+	},
+	
+	onHeaderContextMenu: function(e){
+		// summary:
+		//		Overwritten, see dojox.grid._Events.onHeaderContextMenu()
+		if(this.nestedSorting && this.headerMenu){
+			this._toggleHighlight(e.sourceView, e, true);
+		}
+		//invoke dojox.grid._Events.onHeaderContextMenu()		
+		dojo.hitch(this, this._events.onHeaderContextMenu)(e);
+	}
+});
diff --git a/dojox/grid/enhanced/_Plugin.js b/dojox/grid/enhanced/_Plugin.js
index 24a7fe8..7a30cd2 100644
--- a/dojox/grid/enhanced/_Plugin.js
+++ b/dojox/grid/enhanced/_Plugin.js
@@ -1,191 +1,363 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.enhanced._Plugin"]){
-dojo._hasResource["dojox.grid.enhanced._Plugin"]=true;
 dojo.provide("dojox.grid.enhanced._Plugin");
+
 dojo.require("dojox.grid.enhanced._Builder");
 dojo.require("dojox.grid.enhanced._Events");
-dojo.declare("dojox.grid.enhanced._Plugin",null,{fixedCellNum:-1,funcMap:{},rowSelectionChangedTopic:"ROW_SELECTION_CHANGED",sortRowSelectionChangedTopic:"SORT_ROW_SELECTION_CHANGED",rowMovedTopic:"ROW_MOVED",constructor:function(_1){
-this.grid=_1;
-this._parseProps(this.grid);
-},_parseProps:function(_2){
-_2.plugins&&dojo.mixin(_2,_2.plugins);
-_2.rowSelectionChangedTopic=this.rowSelectionChangedTopic;
-_2.sortRowSelectionChangedTopic=this.sortRowSelectionChangedTopic;
-_2.rowSelectCell=null;
-_2.dnd&&(_2.nestedSorting=true);
-(_2.dnd||_2.indirectSelection)&&(_2.columnReordering=false);
-},preInit:function(){
-var _3=this.grid;
-_3.indirectSelection&&(new (this.getPluginClazz("dojox.grid.enhanced.plugins.IndirectSelection"))(_3));
-if(_3.dnd&&(!_3.rowSelector||_3.rowSelector=="false")){
-_3.rowSelector="20px";
-}
-if(_3.nestedSorting){
-dojox.grid._View.prototype._headerBuilderClass=dojox.grid.enhanced._HeaderBuilder;
-}
-dojox.grid._View.prototype._contentBuilderClass=dojox.grid.enhanced._ContentBuilder;
-},postInit:function(){
-var _4=this.grid;
-new dojox.grid.enhanced._Events(_4);
-_4.menus&&(new (this.getPluginClazz("dojox.grid.enhanced.plugins.Menu"))(_4));
-_4.nestedSorting&&(new (this.getPluginClazz("dojox.grid.enhanced.plugins.NestedSorting"))(_4));
-if(_4.dnd){
-_4.isDndSelectEnable=_4.dnd;
-_4.dndDisabledTypes=["cell"];
-new (this.getPluginClazz("dojox.grid.enhanced.plugins.DnD"))(_4);
-}
-dojo.isChrome<3&&(_4.constructor.prototype.startup=_4.startup);
-this.fixedCellNum=this.getFixedCellNumber();
-this._bindFuncs();
-},getPluginClazz:function(_5){
-var _6=dojo.getObject(_5);
-if(_6){
-return _6;
-}
-throw new Error("Please make sure class \""+_5+"\" is required.");
-},isFixedCell:function(_7){
-return _7&&(_7.isRowSelector||_7.positionFixed);
-},getFixedCellNumber:function(){
-if(this.fixedCellNum>=0){
-return this.fixedCellNum;
-}
-var i=0;
-dojo.forEach(this.grid.layout.cells,dojo.hitch(this,function(_8){
-this.isFixedCell(_8)&&(i++);
-}));
-return i;
-},inSingleSelection:function(){
-return this.grid.selectionMode&&this.grid.selectionMode=="single";
-},needUpdateRow:function(){
-return ((this.grid.indirectSelection||this.grid.isDndSelectEnable)?this.grid.edit.isEditing():true);
-},_bindFuncs:function(){
-dojo.forEach(this.grid.views.views,dojo.hitch(this,function(_9){
-dojox.grid.util.funnelEvents(_9.contentNode,_9,"doContentEvent",["mouseup","mousemove"]);
-dojox.grid.util.funnelEvents(_9.headerNode,_9,"doHeaderEvent",["mouseup"]);
-this.funcMap[_9.id+"-"+"setColumnsWidth"]=_9.setColumnsWidth;
-_9.setColumnsWidth=this.setColumnsWidth;
-this.grid.nestedSorting&&(_9._getHeaderContent=this.grid._getNestedSortHeaderContent);
-this.grid.dnd&&(_9.setScrollTop=this.setScrollTop);
-}));
-this.funcMap["nextKey"]=this.grid.focus.nextKey;
-this.grid.focus.nextKey=this.nextKey;
-this.funcMap["previousKey"]=this.grid.focus.previousKey;
-this.grid.focus.previousKey=this.previousKey;
-if(this.grid.indirectSelection){
-this.funcMap["renderPage"]=this.grid.scroller.renderPage;
-this.grid.scroller.renderPage=this.renderPage;
-}
-this.funcMap["updateRow"]=this.grid.updateRow;
-this.grid.updateRow=this.updateRow;
-if(this.grid.nestedSorting){
-dojox.grid.cells._Base.prototype.getEditNode=this.getEditNode;
-dojox.grid.cells._Widget.prototype.sizeWidget=this.sizeWidget;
-}
-dojox.grid._EditManager.prototype.styleRow=function(_a){
-};
-},setColumnsWidth:function(_b){
-if(dojo.isIE&&!dojo._isBodyLtr()){
-this.headerContentNode.style.width=_b+"px";
-this.headerContentNode.parentNode.style.width=_b+"px";
-}
-dojo.hitch(this,this.grid.pluginMgr.funcMap[this.id+"-"+"setColumnsWidth"])(_b);
-},previousKey:function(e){
-var _c=this.grid.edit.isEditing();
-if(!_c&&!this.isNavHeader()&&!this._isHeaderHidden()){
-if(!this.grid.isDndSelectEnable){
-this.focusHeader();
-}else{
-if(!this.isRowBar()){
-this.focusRowBar();
-}else{
-this._blurRowBar();
-this.focusHeader();
-}
-}
-dojo.stopEvent(e);
-return;
-}
-dojo.hitch(this,this.grid.pluginMgr.funcMap["previousKey"])(e);
-},nextKey:function(e){
-var _d=this.grid.rowCount==0;
-var _e=(e.target===this.grid.domNode);
-if(!_e&&this.grid.isDndSelectEnable&&this.isNavHeader()){
-this._colHeadNode=this._colHeadFocusIdx=null;
-this.focusRowBar();
-return;
-}else{
-if(!_e&&(!this.grid.isDndSelectEnable&&this.isNavHeader())||(this.grid.isDndSelectEnable&&this.isRowBar())){
-this._colHeadNode=this._colHeadFocusIdx=null;
-if(this.grid.isDndSelectEnable){
-this._blurRowBar();
-}
-if(this.isNoFocusCell()&&!_d){
-this.setFocusIndex(0,0);
-}else{
-if(this.cell&&!_d){
-if(this.focusView&&!this.focusView.rowNodes[this.rowIndex]){
-this.grid.scrollToRow(this.rowIndex);
-}
-this.focusGrid();
-}else{
-if(!this.findAndFocusGridCell()){
-this.tabOut(this.grid.lastFocusNode);
-}
-}
-}
-return;
-}
-}
-dojo.hitch(this,this.grid.pluginMgr.funcMap["nextKey"])(e);
-},renderPage:function(_f){
-for(var i=0,j=_f*this.rowsPerPage;(i<this.rowsPerPage)&&(j<this.rowCount);i++,j++){
-}
-this.grid.lastRenderingRowIdx=--j;
-dojo.addClass(this.grid.domNode,"dojoxGridSortInProgress");
-dojo.hitch(this,this.grid.pluginMgr.funcMap["renderPage"])(_f);
-},updateRow:function(_10){
-var _11=arguments.callee.caller;
-if(_11.nom=="move"&&!this.pluginMgr.needUpdateRow()){
-return;
-}
-dojo.hitch(this,this.pluginMgr.funcMap["updateRow"])(_10);
-},getEditNode:function(_12){
-return ((this.getNode(_12)||0).firstChild||0).firstChild||0;
-},sizeWidget:function(_13,_14,_15){
-var p=this.getNode(_15).firstChild,box=dojo.contentBox(p);
-dojo.marginBox(this.widget.domNode,{w:box.w});
-},setScrollTop:function(_16){
-this.lastTop=_16;
-this.scrollboxNode.scrollTop=_16;
-return this.scrollboxNode.scrollTop;
-},getViewByCellIdx:function(_17){
-var _18=function(_19){
-var j=0,_1a=false;
-for(;j<_19.length;j++){
-if(dojo.isArray(_19[j])){
-if(_18(_19[j])){
-return true;
-}
-}else{
-if(_19[j].index==_17){
-return true;
-}
-}
-}
-};
-var i=0,_1b=this.grid.views.views;
-for(;i<_1b.length;i++){
-cells=_1b[i].structure.cells;
-if(_18(cells)){
-return _1b[i];
-}
-}
-return null;
-}});
-}
+
+dojo.declare("dojox.grid.enhanced._Plugin", null, {
+	//	summary:
+	//		Singleton plugin manager 
+	//
+	//	description:
+	//		Plugin manager is responsible for 
+	//		1. Loading required plugins
+	//		2. Handling collaboration and dependencies among plugins
+	//		3. Overwriting some default behavior of DataGrid
+	//		
+	//		Note: Mixin and method caching are used for #3, this might be refined once 
+	//		an overall plugin architecture is set up for DataGrid.
+	//
+	//      Some plugin dependencies:
+    //	   	- DnD plugin depends on NestedSorting plugin
+	//		- RowSelector should be used for DnD plugin. 
+	//		  e.g. <div dojoType="dojox.grid.EnhancedGrid"  plugins='{dnd: true, ...}}' rowSelector="20px" .../>
+	//		- "columnReordering" attribute won't work when either DnD or Indirect Selections plugin is on.
+		
+	//fixedCellNum: Integer
+	//		Number of fixed cells(columns), e.g. cell(column) of indirect selection is fixed and can't be moved	
+	fixedCellNum: -1,
+	
+	//funcMap: Object
+	//		Map for caching default DataGrid methods.
+	funcMap:{},
+
+	constructor: function(inGrid){
+		this.grid = inGrid;
+		this._parseProps(this.grid);
+	},
+	
+	_parseProps: function(grid){
+		// summary:
+		//		Parse plugins properties
+		// grid: Grid
+		//		Grid this plugin manager belongs to
+		
+		//mixin all plugin properties into Grid
+		grid.plugins && dojo.mixin(grid, grid.plugins);
+		
+		//cell(column) of indirect selection
+		grid.rowSelectCell = null;
+		
+		//DnD plugin depends on NestedSorting plugin
+		grid.dnd && (grid.nestedSorting = true);
+		
+		//"columnReordering" attribute won't work when either DnD or Indirect Selections plugin is used.
+		(grid.dnd || grid.indirectSelection) && (grid.columnReordering = false);
+	},
+	
+	preInit: function(){
+		// summary:
+		//		Pre initialization, some plugins must be loaded before DataGrid.postCreate(). 
+		//		See EnhancedGrid.postCreate()
+		var grid = this.grid;
+		//load Indirect Selection plugin
+		grid.indirectSelection && (new (this.getPluginClazz('dojox.grid.enhanced.plugins.IndirectSelection'))(grid));
+		if(grid.dnd && (!grid.rowSelector || grid.rowSelector=="false")) {
+			//RowSelector should be used for DnD plugin.
+			grid.rowSelector = "20px";
+		}
+		//overwrite header and content builders
+		if(grid.nestedSorting){
+			dojox.grid._View.prototype._headerBuilderClass = dojox.grid.enhanced._HeaderBuilder;			
+		}
+		dojox.grid._View.prototype._contentBuilderClass = dojox.grid.enhanced._ContentBuilder;
+	},
+	
+	postInit: function(){
+		// summary:
+		//		Post initialization, by default, plugins are loaded after DataGrid.postCreate(). 
+		//		See EnhancedGrid.postCreate()
+		var grid = this.grid;
+		
+		//overwrite some default events of DataGrid
+		new dojox.grid.enhanced._Events(grid);
+		
+		//load Menu plugin
+		grid.menus && (new (this.getPluginClazz('dojox.grid.enhanced.plugins.Menu'))(grid));
+		
+		//load NestedSorting plugin
+		grid.nestedSorting && (new (this.getPluginClazz('dojox.grid.enhanced.plugins.NestedSorting'))(grid));
+		
+		//load DnD plugin
+		if(grid.dnd){
+			grid.isDndSelectEnable = grid.dnd;
+			//by default disable cell selection for EnhancedGrid M1
+			grid.dndDisabledTypes =  ["cell"];
+			//new dojox.grid.enhanced.dnd._DndMovingManager(grid);			
+			new (this.getPluginClazz('dojox.grid.enhanced.plugins.DnD'))(grid);
+		}
+		
+		//TODO - see if any better ways for this
+		//fix inherit issue for mixin, an null/undefined exception will be thrown from the "this.inherited(...)" in
+		//the following functions, like saying there is no "startup" in "this" scope
+		dojo.isChrome < 3 && (grid.constructor.prototype.startup = grid.startup);
+		//grid.constructor.prototype.onStyleRow = grid.onStyleRow;
+		
+		//get fixed cell(column) number
+		this.fixedCellNum = this.getFixedCellNumber();
+		
+		//overwrite some default methods of DataGrid by method caching
+		this.grid.plugins && this._bindFuncs();
+	},
+	
+	getPluginClazz: function(clazzStr){
+		//summary:
+		//		Load target plugin which must be already required (dojo.require(..))
+		//clazzStr: String
+		//		Plugin class name
+		var clazz = dojo.getObject(clazzStr);
+		if(clazz){
+			return clazz;
+		}
+		throw new Error('Please make sure class "' + clazzStr + '" is required.');			
+	},
+	
+	isFixedCell: function(cell) {
+		//summary:
+		//		See if target cell(column) is fixed or not.
+		//cell: Object
+		//		Target cell(column)
+		//return: Boolean
+		//		True - fixed| False - not fixed
+
+		//target cell can use Boolean attributes named "isRowSelector" or "positionFixed" to mark it's a fixed cell(column)
+		return cell && (cell.isRowSelector || cell.positionFixed);
+	},
+	
+	getFixedCellNumber: function(){
+		//summary:
+		//		See if target cell(column) is fixed or not.
+		//return: Number
+		//		True - fixed| False - not fixed
+		if(this.fixedCellNum >= 0){
+			return this.fixedCellNum;
+		}
+		var i = 0;
+		dojo.forEach(this.grid.layout.cells, dojo.hitch(this, function(cell){
+			this.isFixedCell(cell) && (i++);
+		}));
+		return i;
+	},
+	
+	inSingleSelection: function(){
+		//summary:
+		//		See if Grid is in single selection mode
+		//return: Boolean
+		//		True - in single selection mode | False - not in single selection mode
+		return this.grid.selectionMode && this.grid.selectionMode == 'single';
+	},
+	
+	needUpdateRow: function(){
+		//summary:
+		//		See if needed to update row. See this.updateRow()
+		//return: Boolean
+		//		True - need update row | False - don't update row
+		
+		//always true when either indirect selection or DnD disabled
+		return ((this.grid.indirectSelection || this.grid.isDndSelectEnable) ? this.grid.edit.isEditing() : true);		
+	},				
+	
+	_bindFuncs: function(){
+		//summary:
+		//		Overwrite some default methods of DataGrid by method caching		
+		dojo.forEach(this.grid.views.views, dojo.hitch(this, function(view){
+			//add more events handler - _View
+			dojox.grid.util.funnelEvents(view.contentNode, view, "doContentEvent", ['mouseup', 'mousemove']);
+			dojox.grid.util.funnelEvents(view.headerNode, view, "doHeaderEvent", ['mouseup']);
+			
+			//overwrite _View.setColumnsWidth()
+			this.funcMap[view.id + '-' +'setColumnsWidth'] = view.setColumnsWidth;
+			view.setColumnsWidth =  this.setColumnsWidth;
+			
+			//overwrite _View._getHeaderContent()
+			this.grid.nestedSorting && (view._getHeaderContent = this.grid._getNestedSortHeaderContent);
+			
+			//overwrite _View.setScrollTop(),
+			//#10273 fix of base DataGrid seems to bring some side effects to Enhanced Grid, 
+			//TODO - need a more close look post v.1.4 rather than simply overwrite it
+			this.grid.dnd && (view.setScrollTop = this.setScrollTop);
+		}));
+		
+		//overwrite _FocusManager.nextKey()
+		this.funcMap['nextKey'] = this.grid.focus.nextKey;
+		this.grid.focus.nextKey = this.nextKey;
+
+		//overwrite _FocusManager.previousKey()
+		this.funcMap['previousKey'] = this.grid.focus.previousKey;
+		this.grid.focus.previousKey = this.previousKey;
+
+		//overwrite _Scroller.renderPage()
+		if(this.grid.indirectSelection){
+			this.funcMap['renderPage'] = this.grid.scroller.renderPage;
+			this.grid.scroller.renderPage = this.renderPage;	
+			this.funcMap['measurePage'] = this.grid.scroller.measurePage;
+			this.grid.scroller.measurePage = this.measurePage;	
+		}
+		
+		//overwrite _Grid.updateRow()
+		this.funcMap['updateRow'] = this.grid.updateRow;		
+		this.grid.updateRow = this.updateRow;	
+		
+		if(this.grid.nestedSorting && dojox.grid.cells._Widget){			
+			 dojox.grid.cells._Widget.prototype.sizeWidget = this.sizeWidget;
+		}
+		dojox.grid.cells._Base.prototype.getEditNode = this.getEditNode;
+		dojox.grid._EditManager.prototype.styleRow = function(inRow){};		
+	},
+	
+	setColumnsWidth: function(width){
+		//summary:
+		//		Overwrite _View.setColumnsWidth(), "this" - _View scope
+		//		Fix rtl issue in IE.
+		if(dojo.isIE && !dojo._isBodyLtr()) {
+			this.headerContentNode.style.width = width + 'px';
+			this.headerContentNode.parentNode.style.width = width + 'px';			
+		}
+		//invoke _View.setColumnsWidth()
+		dojo.hitch(this, this.grid.pluginMgr.funcMap[this.id + '-' +'setColumnsWidth'])(width);
+	},
+	
+	previousKey: function(e){
+		//summary:
+		//		Overwrite _FocusManager.previousKey(), "this" - _FocusManager scope		
+		var isEditing = this.grid.edit.isEditing();
+		if(!isEditing && !this.isNavHeader() && !this._isHeaderHidden()) {
+			if(!this.grid.isDndSelectEnable){
+				this.focusHeader();
+			}else{
+				if(!this.isRowBar()){
+					this.focusRowBar();
+				} else {
+					this._blurRowBar();
+					this.focusHeader();
+				}
+			}
+			dojo.stopEvent(e);
+			return;
+		}
+		//invoke _FocusManager.previousKey()
+		dojo.hitch(this, this.grid.pluginMgr.funcMap['previousKey'])(e);
+	},
+
+	nextKey: function(e) {
+		//summary:
+		//		Overwrite _FocusManager.nextKey(), "this" - _FocusManager scope		
+		var isEmpty = this.grid.rowCount == 0;
+		var isRootEvt = (e.target === this.grid.domNode);
+		if(!isRootEvt && this.grid.isDndSelectEnable && this.isNavHeader()){
+			// if tabbing from col header, then go to grid proper. If grid is empty this.grid.rowCount == 0
+			this._colHeadNode = this._colHeadFocusIdx= null;
+			this.focusRowBar();
+			return;
+		}else if(!isRootEvt && (!this.grid.isDndSelectEnable && this.isNavHeader()) || (this.grid.isDndSelectEnable && this.isRowBar())){
+			this._colHeadNode = this._colHeadFocusIdx= null;
+			if (this.grid.isDndSelectEnable) {
+				this._blurRowBar();
+			}
+			if(this.isNoFocusCell() && !isEmpty){
+				this.setFocusIndex(0, 0);
+			}else if(this.cell && !isEmpty){
+				if(this.focusView && !this.focusView.rowNodes[this.rowIndex]){
+				// if rowNode for current index is undefined (likely as a result of a sort and because of #7304) 
+				// scroll to that row
+					this.grid.scrollToRow(this.rowIndex);
+				}
+				this.focusGrid();
+			}else if(!this.findAndFocusGridCell()){
+				this.tabOut(this.grid.lastFocusNode);
+			}
+			return;
+		}
+		//invoke _FocusManager.nextKey()
+		dojo.hitch(this, this.grid.pluginMgr.funcMap['nextKey'])(e);
+	},
+	
+	renderPage: function(inPageIndex){
+		//summary:
+		//		Overwrite _Scroller.renderPage(), "this" - _Scroller scope
+		//		To add progress cursor when rendering the indirect selection cell(column) with checkbox
+		for(var i=0, j=inPageIndex*this.rowsPerPage; (i<this.rowsPerPage)&&(j<this.rowCount); i++, j++){}
+		this.grid.lastRenderingRowIdx = --j;
+		dojo.addClass(this.grid.domNode, 'dojoxGridSortInProgress');
+		
+		//invoke _Scroller.renderPage()
+		dojo.hitch(this, this.grid.pluginMgr.funcMap['renderPage'])(inPageIndex);
+	},
+	
+	measurePage: function(inPageIndex){
+		//summary:
+		//		Overwrite _Scroller.measurePage(), "this" - _Scroller scope
+		//		Fix a regression similar as #5552
+		//		invoke _Scroller.measurePage()
+		var pageHeight = dojo.hitch(this, this.grid.pluginMgr.funcMap['measurePage'])(inPageIndex);
+		return (!dojo.isIE || this.grid.rowHeight || pageHeight > this.rowsPerPage * this.grid.minRowHeight) ? pageHeight : undefined;
+	},
+	
+	updateRow: function(inRowIndex){
+		//summary:
+		//		Overwrite _Scroller.renderPage(), "this" - _Grid scope
+		var caller = arguments.callee.caller;
+		if(caller.nom == "move" && /* caller.ctor.prototype.declaredClass == "dojox.grid._FocusManager" && */ !this.pluginMgr.needUpdateRow()){
+			//if is called from dojox.grid._FocusManager.move(), and no need to update row, then return
+			return;
+		}
+		//invoke _Grid.updateRow()
+		dojo.hitch(this, this.pluginMgr.funcMap['updateRow'])(inRowIndex);
+	},
+	
+	getEditNode: function(inRowIndex) {
+		//summary:
+		//		Overwrite dojox.grid.cells._Base.getEditNode, "this" - _Base scope
+		return ((this.getNode(inRowIndex) || 0).firstChild || 0).firstChild || 0;
+	},
+	
+	sizeWidget: function(inNode, inDatum, inRowIndex){
+		//summary:
+		//		Overwrite dojox.grid.cells._Widget.sizeWidget, "this" - _Widget scope
+		var p = this.getNode(inRowIndex).firstChild, 
+		box = dojo.contentBox(p);
+		dojo.marginBox(this.widget.domNode, {w: box.w});
+	},
+	
+	setScrollTop: function(inTop){
+		//summary:
+		//		Overwrite dojox.grid._View.setScrollTop, "this" - _View scope
+		this.lastTop = inTop;
+		this.scrollboxNode.scrollTop = inTop;
+		return this.scrollboxNode.scrollTop;
+	},
+	
+	getViewByCellIdx: function(cellIdx){
+		//summary:
+		//		Find view that contains the cell with 'cellIdx'
+		//cellIdx: Integer
+		//		Index of target cell
+		//return: Object
+		//		Matched view
+		var cellMatched = function(cells){
+			var j = 0, matched = false;
+			for(; j < cells.length; j++){
+				if(dojo.isArray(cells[j])){
+					if(cellMatched(cells[j])){ return true;}
+				}else if(cells[j].index == cellIdx){
+					return true;
+				}
+			}
+		};
+		var i = 0, views = this.grid.views.views;
+		for(; i < views.length; i++){
+			cells = views[i].structure.cells;
+			if(cellMatched(cells)){ return views[i]; }
+		}
+		return null;
+	}	
+});
diff --git a/dojox/grid/enhanced/dnd/_DndBuilder.js b/dojox/grid/enhanced/dnd/_DndBuilder.js
index 149cfb3..d3e0793 100644
--- a/dojox/grid/enhanced/dnd/_DndBuilder.js
+++ b/dojox/grid/enhanced/dnd/_DndBuilder.js
@@ -1,26 +1,36 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.enhanced.dnd._DndBuilder"]){
-dojo._hasResource["dojox.grid.enhanced.dnd._DndBuilder"]=true;
 dojo.provide("dojox.grid.enhanced.dnd._DndBuilder");
-dojo.declare("dojox.grid.enhanced.dnd._DndBuilder",null,{domouseup:function(e){
-if(this.grid.select.isInSelectingMode("col")){
-this.grid.nestedSorting?this.grid.focus.focusSelectColEndingHeader(e):this.grid.focus.focusHeaderNode(e.cellIndex);
-}
-if(e.cellNode){
-this.grid.onMouseUp(e);
-}
-this.grid.onMouseUpRow(e);
-}});
-dojo.declare("dojox.grid.enhanced.dnd._DndHeaderBuilder",null,{domouseup:function(e){
-if(this.grid.select.isInSelectingMode("col")){
-this.grid.nestedSorting?this.grid.focus.focusSelectColEndingHeader(e):this.grid.focus.focusHeaderNode(e.cellIndex);
-}
-this.grid.onMouseUp(e);
-}});
-}
+dojo.declare("dojox.grid.enhanced.dnd._DndBuilder", null, {
+	//summary:
+	//		This class declaration is used to be mixed in to dojox.grid._Builder
+	//		to enable the _Builder to handle mouse up event for DND feature
+	
+	domouseup:function(e){
+	//summary:
+	//		Handle when there is a mouse up event 
+	//e: Event
+	//		The mouse up event
+		if(this.grid.select.isInSelectingMode("col")) {
+			this.grid.nestedSorting ? this.grid.focus.focusSelectColEndingHeader(e) : this.grid.focus.focusHeaderNode(e.cellIndex);
+		}
+		if (e.cellNode)
+			this.grid.onMouseUp(e);
+		this.grid.onMouseUpRow(e)
+	}
+});
+
+dojo.declare("dojox.grid.enhanced.dnd._DndHeaderBuilder", null, {
+	//summary:
+	//		This class declaration is used to be mixed in to dojox.grid._HeadBuilder
+	//		to enable the _HeadBuilder to handle mouse up event for DND feature
+	
+	domouseup: function(e){
+		//summary:
+		//		Handle when there is a mouse up event 
+		//e: Event
+		//		The mouse up event
+		if(this.grid.select.isInSelectingMode("col")) {
+			this.grid.nestedSorting ? this.grid.focus.focusSelectColEndingHeader(e) : this.grid.focus.focusHeaderNode(e.cellIndex);
+		}
+		this.grid.onMouseUp(e);
+	}
+});
diff --git a/dojox/grid/enhanced/dnd/_DndEvents.js b/dojox/grid/enhanced/dnd/_DndEvents.js
index b66d512..8624f35 100644
--- a/dojox/grid/enhanced/dnd/_DndEvents.js
+++ b/dojox/grid/enhanced/dnd/_DndEvents.js
@@ -1,47 +1,84 @@
-/*
-	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
-*/
+dojo.provide("dojox.grid.enhanced.dnd._DndEvents");
 
+dojo.declare("dojox.grid.enhanced.dnd._DndEvents", null, {
+	//summary:
+	//		This class declaration is used to be mixed in to dojox.grid._Event
+	//		to enable the _Event to handle several events for DND feature
 
-if(!dojo._hasResource["dojox.grid.enhanced.dnd._DndEvents"]){
-dojo._hasResource["dojox.grid.enhanced.dnd._DndEvents"]=true;
-dojo.provide("dojox.grid.enhanced.dnd._DndEvents");
-dojo.declare("dojox.grid.enhanced.dnd._DndEvents",null,{onMouseUp:function(e){
-e.rowIndex==-1?this.onHeaderCellMouseUp(e):this.onCellMouseUp(e);
-this.select.resetStartPoint();
-this.select.clearInSelectingMode();
-!isNaN(e.rowIndex)&&e.cellIndex==-1&&this.focus.focusRowBarNode(e.rowIndex);
-},onMouseUpRow:function(e){
-if(this.dndSelectable){
-}else{
-if(e.rowIndex!=-1){
-this.onRowMouseUp(e);
-}
-}
-},onCellMouseUp:function(e){
-if(e.cellIndex>this.select.exceptColumnsTo){
-this.select.setInSelectingMode("cell",true);
-}
-},onRowHeaderMouseDown:function(e){
-this.focus._colHeadNode=this.focus._colHeadFocusIdx=null;
-this.focus.focusRowBarNode(e.rowIndex);
-if(e.button==2){
-return;
-}
-this.select.setInSelectingMode("row",true);
-this.select.keepState=e.ctrlKey&&!this.pluginMgr.inSingleSelection();
-this.select.extendSelect=e.shiftKey;
-this.select.setDrugStartPoint(-1,e.rowIndex);
-if(this.select.extendSelect&&!this.pluginMgr.inSingleSelection()){
-this.select.restorLastDragPoint();
-}
-this.select.drugSelectRow(e.rowIndex);
-dojo.stopEvent(e);
-},onRowHeaderMouseUp:function(e){
-this.onMouseUp(e);
-},onRowMouseUp:function(e){
-this.select.setInSelectingMode("row",false);
-}});
-}
+	//rowActiveClass: String
+	// 		css class to apply to grid rows when activated(mouse down)	
+	rowBarActiveClass: 'dojoxGridRowBarActive',
+		
+	onMouseUp: function(e){
+		// summary:
+		//		Event fired when mouse is up inside grid.
+		// e: Event
+		//		Decorated event object that contains reference to grid, cell, and rowIndex		
+		e.rowIndex == -1 ? this.onHeaderCellMouseUp(e) : this.onCellMouseUp(e);
+		this.select.resetStartPoint();
+		this.select.clearInSelectingMode();
+		!isNaN(e.rowIndex) && e.cellIndex == -1 && this.focus.focusRowBarNode(e.rowIndex);
+	},
+	
+	onMouseUpRow: function(e){
+		// summary:
+		//		Event fired when mouse is up inside grid row
+		// e: Event
+		//		Decorated event object that contains reference to grid, cell, and rowIndex
+		if (this.dndSelectable) {
+			//waiting ...
+		} else if(e.rowIndex != -1)
+			this.onRowMouseUp(e);
+	},
+	
+	onCellMouseUp: function(e){
+		// summary:
+		//		Event fired when mouse is up in a cell.
+		// e: Event
+		// 		Decorated event object which contains reference to grid, cell, and rowIndex
+		if (e.cellIndex > this.select.exceptColumnsTo) {
+			this.select.setInSelectingMode("cell", true);
+		}
+	},
+
+	onRowHeaderMouseDown: function(e) {		
+		//summary:
+		//		Handle when there is a mouse down event on row header (row bar), 
+		//		Call the dnd select to add the row to select
+		//e: Event
+		//		The mouse down event
+		//blur column header focus
+		this.focus._colHeadNode = this.focus._colHeadFocusIdx = null;
+		this.focus.focusRowBarNode(e.rowIndex);	
+		if(e.button == 2) {
+			return;//alwarys return for oncontextmenu event to only show menu
+		}
+		this.select.setInSelectingMode("row", true);
+		this.select.keepState = e.ctrlKey && !this.pluginMgr.inSingleSelection();
+		this.select.extendSelect = e.shiftKey;
+		this.select.setDrugStartPoint(-1, e.rowIndex);
+		if(this.select.extendSelect && !this.pluginMgr.inSingleSelection()){
+			this.select.restorLastDragPoint();
+		} 
+		this.select.drugSelectRow(e.rowIndex);
+		dojo.addClass(e.rowNode, this.rowBarActiveClass);
+		dojo.stopEvent(e);
+	},
+	
+	onRowHeaderMouseUp: function(e) {
+		//summary:
+		//		Handle when there is a mouse up event on row header (row bar), 
+		//e: Event
+		//		The mouse up event
+		this.onMouseUp(e);
+		dojo.removeClass(e.rowNode, this.rowBarActiveClass);
+	},
+	
+	onRowMouseUp: function(e){
+		// summary:
+		//		Event fired when mouse is up in a row.
+		// e: Event
+		// 		Decorated event object which contains reference to grid, cell, and rowIndex
+		this.select.setInSelectingMode("row", false);
+	}
+});
diff --git a/dojox/grid/enhanced/dnd/_DndFocusManager.js b/dojox/grid/enhanced/dnd/_DndFocusManager.js
index 95db2f5..53a2b29 100644
--- a/dojox/grid/enhanced/dnd/_DndFocusManager.js
+++ b/dojox/grid/enhanced/dnd/_DndFocusManager.js
@@ -1,69 +1,127 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.enhanced.dnd._DndFocusManager"]){
-dojo._hasResource["dojox.grid.enhanced.dnd._DndFocusManager"]=true;
 dojo.provide("dojox.grid.enhanced.dnd._DndFocusManager");
-dojo.declare("dojox.grid.enhanced.dnd._DndFocusManager",null,{_rowBarNode:null,_rowBarFocusIdy:null,isRowBar:function(){
-return (!!this._rowBarNode);
-},getRowBarNode:function(_1){
-return this.grid.views.views[0].getCellNode(_1,0);
-},focusRowBar:function(){
-this.focusRowBarNode(0);
-this._focusifyCellNode(false);
-},focusRowBarNode:function(_2){
-this._blurRowBar();
-this._focusifyCellNode(false);
-var _3=this.getRowBarNode(_2);
-if(!_3){
-return;
-}
-this._rowBarNode=_3;
-this._rowBarFocusIdy=_2;
-this._rowBarNode.tabIndex=-1;
-dojox.grid.util.fire(this._rowBarNode,"focus");
-dojo.toggleClass(this._rowBarNode,this.focusClass,true);
-},_blurRowBar:function(){
-if(this._rowBarNode){
-dojo.toggleClass(this._rowBarNode,this.focusClass,false);
-this._rowBarNode=this._rowBarFocusIdy=null;
-}
-},focusNextRowBar:function(){
-var sc=this.grid.scroller,r=this._rowBarFocusIdy,rc=this.grid.rowCount-1,_4=Math.min(rc,Math.max(0,r+1));
-var _5=this._rowBarFocusIdy+1;
-if(_4>sc.getLastPageRow(sc.page)){
-this.grid.setScrollTop(this.grid.scrollTop+sc.findScrollTop(_4)-sc.findScrollTop(r));
-}
-this.focusRowBarNode(_5);
-this.scrollRowBarIntoView();
-},focusPrevRowBar:function(){
-var sc=this.grid.scroller,r=this._rowBarFocusIdy,rc=this.grid.rowCount-1,_6=Math.min(rc,Math.max(0,r-1));
-var _7=this._rowBarFocusIdy-1;
-if(_7<0){
-return;
-}
-if(_7<=sc.getPageRow(sc.page)){
-this.grid.setScrollTop(this.grid.scrollTop-sc.findScrollTop(r)-sc.findScrollTop(_6));
-}
-this.focusRowBarNode(_7);
-this.scrollRowBarIntoView();
-},getFocusedRowIndex:function(){
-return this._rowBarFocusIdy;
-},scrollRowBarIntoView:function(){
-this.cell=this._rowBarNode;
-this.cell.view=this.grid.views.views[0];
-this.cell.getNode=function(_8){
-return this.cell;
-};
-this.rowIndex=this._rowBarFocusIdy;
-this.scrollIntoView();
-this.cell=null;
-},focusHeaderNode:function(_9){
-this._colHeadFocusIdx=_9;
-this.focusHeader.apply(this,arguments);
-}});
-}
+
+dojo.declare("dojox.grid.enhanced.dnd._DndFocusManager", null, {
+	//summary:
+	//		This class declaration is used to be mixed in to dojox.grid._FocusManager
+	//		to enable  DND feature by changing some focus behavior in _FocusManager
+	
+	//_rowBarNode: Object
+	//		reference to a row bar DOM node
+    _rowBarNode: null,
+	
+	//_rowBarFocusIdy: Integer
+	//		The value of the ID, which is from the row node that is focused
+    _rowBarFocusIdy: null,
+	
+    isRowBar: function(){
+		//summary:
+		//		states whether currently navigating among row bar nodes.
+		// returns:
+		//		true if focus is on a row bar node; false otherwise. 
+        return (!!this._rowBarNode);
+    },
+    
+	getRowBarNode: function(inIdx){
+		//summary:
+		//		get a reference of a row bar DOM node which has the same idx value with inIdx
+		//inIdx: Integer
+		//		The idx value of the row bar DOM node that will be got
+		return this.grid.views.views[0].getCellNode(inIdx, 0);
+	},
+	
+    focusRowBar: function(){
+		//summary:
+		//		Move the focud to the first row bar node		
+        this.focusRowBarNode(0);
+		this._focusifyCellNode(false);
+        
+    },
+    
+    focusRowBarNode: function(rowIndex){
+		//summary:
+		//		move the focus to the row bar DOM node with the row index same as rowIndex
+		//rowIndex: Integer
+		//		The row index value of the row bar node that will be focused		
+		this._blurRowBar();
+		this._focusifyCellNode(false);
+		var node = this.getRowBarNode(rowIndex);
+		if(!node) return;
+        this._rowBarNode = node;
+        this._rowBarFocusIdy = rowIndex;
+		this._rowBarNode.tabIndex = -1;
+        dojox.grid.util.fire(this._rowBarNode, "focus");
+        dojo.toggleClass(this._rowBarNode, this.focusClass, true);
+    },
+    
+    _blurRowBar: function(){
+		//summary:
+		//		blur the focus on the focused row bar node
+		if(this._rowBarNode){
+			dojo.toggleClass(this._rowBarNode, this.focusClass, false);
+        	this._rowBarNode = this._rowBarFocusIdy = null;
+		}
+       
+    },
+    
+    focusNextRowBar: function(){
+		//summary:
+		//		move the focus to the next row bar node of the the current focused node		
+        var sc = this.grid.scroller, r = this._rowBarFocusIdy, rc = this.grid.rowCount - 1, row = Math.min(rc, Math.max(0, r + 1));
+        var currentY = this._rowBarFocusIdy + 1;
+        if (row > sc.getLastPageRow(sc.page)) {
+            //need to load additional data, let scroller do that
+            this.grid.setScrollTop(this.grid.scrollTop + sc.findScrollTop(row) - sc.findScrollTop(r));
+        }
+      
+        this.focusRowBarNode(currentY);
+        this.scrollRowBarIntoView();
+    },
+    
+    focusPrevRowBar: function(){
+		//summary:
+		//		move the focus to the previous row bar node of the the current focused node		
+        var sc = this.grid.scroller, r = this._rowBarFocusIdy, rc = this.grid.rowCount - 1, row = Math.min(rc, Math.max(0, r - 1));
+        var currentY = this._rowBarFocusIdy - 1;
+        if (currentY < 0) {
+            return;
+        }
+        if (currentY <= sc.getPageRow(sc.page)) {
+            this.grid.setScrollTop(this.grid.scrollTop - sc.findScrollTop(r) - sc.findScrollTop(row));
+        }
+        
+        this.focusRowBarNode(currentY);
+        this.scrollRowBarIntoView();
+    },
+    
+    getFocusedRowIndex: function(){
+		//summary:
+		//		get the index of the node which is focused
+		//return: Integer
+		//		the index of the node which is focused
+        return this._rowBarFocusIdy;
+    },
+	
+    scrollRowBarIntoView: function(){
+    	//summary:
+		//		scroll the row bar view to make the focused row bar show in the view
+		
+        //Fake a cell object to do scroll
+        this.cell = this._rowBarNode;
+        this.cell.view = this.grid.views.views[0];
+        this.cell.getNode = function(index){
+            return this.cell;
+        };        
+        
+        this.rowIndex = this._rowBarFocusIdy;
+        this.scrollIntoView();
+		this.cell = null;
+    },
+	
+	focusHeaderNode: function(inHeaderNodeIdx){
+		//summary:
+		//		move the focus to col header
+		this._colHeadFocusIdx = inHeaderNodeIdx;
+		this.focusHeader.apply(this, arguments);
+		//this.focusHeader();
+	}
+});
diff --git a/dojox/grid/enhanced/dnd/_DndGrid.js b/dojox/grid/enhanced/dnd/_DndGrid.js
index 6d82991..f529ba0 100644
--- a/dojox/grid/enhanced/dnd/_DndGrid.js
+++ b/dojox/grid/enhanced/dnd/_DndGrid.js
@@ -1,23 +1,41 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.enhanced.dnd._DndGrid"]){
-dojo._hasResource["dojox.grid.enhanced.dnd._DndGrid"]=true;
 dojo.provide("dojox.grid.enhanced.dnd._DndGrid");
 dojo.require("dojox.grid.enhanced.dnd._DndEvents");
-dojo.declare("dojox.grid.enhanced.dnd._DndGrid",dojox.grid.enhanced.dnd._DndEvents,{select:null,dndSelectable:true,constructor:function(_1){
-this.select=_1;
-},domousedown:function(e){
-if(!e.cellNode){
-this.onRowHeaderMouseDown(e);
-}
-},domouseup:function(e){
-if(!e.cellNode){
-this.onRowHeaderMouseUp(e);
-}
-}});
-}
+dojo.declare("dojox.grid.enhanced.dnd._DndGrid", dojox.grid.enhanced.dnd._DndEvents, {
+	//summary:
+	//		This class declaration is used to be mixed in to dojox.grid._Grid
+	//		to enable DND feature in _Grid.
+	
+		//select: _DndSelectingManager
+		//		handle the DND selecting operation
+	    select: null, 
+		
+		//dndSelectable: Boolean
+		//		whether the DND feature is enabled for the grid
+		dndSelectable: true,
+		
+		constructor: function(dndManager){
+			//summary:
+			//		constructor, store the reference of the instance of_DndSelectingManager
+			this.select = dndManager;
+		},
+		
+		domousedown: function(e){
+			//summary:
+			//		handle the mouse down event
+			//e: Event
+			//		the mouse down event on grid			
+			if(!e.cellNode){
+				this.onRowHeaderMouseDown(e);
+			}
+		},
+		
+		domouseup: function(e){
+			//summary:
+			//		handle the mouse up event
+			//e: Event
+			//		the mouse up event on grid			
+			if(!e.cellNode){
+				this.onRowHeaderMouseUp(e);
+			}
+		}
+});
diff --git a/dojox/grid/enhanced/dnd/_DndMover.js b/dojox/grid/enhanced/dnd/_DndMover.js
index 77a437c..ab979d7 100644
--- a/dojox/grid/enhanced/dnd/_DndMover.js
+++ b/dojox/grid/enhanced/dnd/_DndMover.js
@@ -1,36 +1,40 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.enhanced.dnd._DndMover"]){
-dojo._hasResource["dojox.grid.enhanced.dnd._DndMover"]=true;
 dojo.provide("dojox.grid.enhanced.dnd._DndMover");
+
 dojo.require("dojo.dnd.move");
-dojo.declare("dojox.grid.enhanced.dnd._DndMover",dojo.dnd.Mover,{onMouseMove:function(e){
-dojo.dnd.autoScroll(e);
-var m=this.marginBox;
-this.host.onMove(this,{l:m.l+e.pageX,t:m.t+e.pageY},{x:e.pageX,y:e.pageY});
-dojo.stopEvent(e);
-}});
-dojo.declare("dojox.grid.enhanced.dnd._DndBoxConstrainedMoveable",dojo.dnd.move.boxConstrainedMoveable,{movingType:"row",constructor:function(_1,_2){
-if(!_2||!_2.movingType){
-return;
-}
-this.movingType=_2.movingType;
-},onFirstMove:function(_3){
-this.inherited(arguments);
-if(this.within){
-var c=this.constraintBox,mb=dojo.marginBox(_3.node);
-if(this.movingType=="row"){
-c.r+=mb.w;
-}else{
-if(this.movingType=="col"){
-c.b+=mb.h;
-}
-}
-}
-}});
-}
+
+dojo.declare("dojox.grid.enhanced.dnd._DndMover", dojo.dnd.Mover, {
+	
+	onMouseMove: function(e){
+		// summary:
+		//		Overwritten, see dojo.dnd.Mover.onMouseMove()
+		dojo.dnd.autoScroll(e);
+		var m = this.marginBox;
+		this.host.onMove(this, {l: m.l + e.pageX, t: m.t + e.pageY}, {x:e.pageX, y:e.pageY});
+		dojo.stopEvent(e);
+	}
+});
+
+dojo.declare("dojox.grid.enhanced.dnd._DndBoxConstrainedMoveable", dojo.dnd.move.boxConstrainedMoveable, {
+	//movingType: String
+	//		Row moving - 'row' or column moving - 'col'
+	movingType: 'row',
+	
+	constructor: function(node, params){
+		if(!params || !params.movingType){ return; }
+		this.movingType = params.movingType;
+	},
+	
+	onFirstMove: function(/* dojo.dnd.Mover */ mover){
+		// summary:
+		//		Overwritten, see dojo.dnd.move.constrainedMoveable.onFirstMove()
+		this.inherited(arguments);
+		if(this.within){
+			var c = this.constraintBox, mb = dojo.marginBox(mover.node);
+			if(this.movingType == 'row'){
+				c.r += mb.w;	
+			}else if(this.movingType == 'col'){
+				c.b += mb.h;
+			}
+		}
+	}
+});
diff --git a/dojox/grid/enhanced/dnd/_DndMovingManager.js b/dojox/grid/enhanced/dnd/_DndMovingManager.js
index 5b2e80f..5fccb99 100644
--- a/dojox/grid/enhanced/dnd/_DndMovingManager.js
+++ b/dojox/grid/enhanced/dnd/_DndMovingManager.js
@@ -1,691 +1,988 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.enhanced.dnd._DndMovingManager"]){
-dojo._hasResource["dojox.grid.enhanced.dnd._DndMovingManager"]=true;
 dojo.provide("dojox.grid.enhanced.dnd._DndMovingManager");
+
 dojo.require("dojox.grid.enhanced.dnd._DndSelectingManager");
 dojo.require("dojox.grid.enhanced.dnd._DndMover");
 dojo.require("dojo.dnd.move");
-dojo.declare("dojox.grid.enhanced.dnd._DndMovingManager",dojox.grid.enhanced.dnd._DndSelectingManager,{exceptRowsTo:-1,exceptColumnsTo:-1,coverDIVs:[],movers:[],constructor:function(_1){
-if(this.grid.indirectSelection){
-this.exceptColumnsTo=this.grid.pluginMgr.getFixedCellNumber()-1;
-}
-this.coverDIVs=this.movers=[];
-dojo.subscribe("CTRL_KEY_DOWN",dojo.hitch(this,function(_2,_3){
-if(_2==this.grid&&_2!=this){
-this.keyboardMove(_3);
-}
-}));
-dojo.forEach(this.grid.views.views,function(_4){
-dojo.connect(_4.scrollboxNode,"onscroll",dojo.hitch(this,function(){
-this.clearDrugDivs();
-}));
-},this);
-},getGridWidth:function(){
-return dojo.contentBox(this.grid.domNode).w-this.grid.views.views[0].getWidth().replace("px","");
-},isColSelected:function(_5){
-return this.selectedColumns[_5]&&_5>this.exceptColumnsTo;
-},getHScrollBarHeight:function(){
-this.scrollbarHeight=0;
-dojo.forEach(this.grid.views.views,function(_6,_7){
-if(_6.scrollboxNode){
-var _8=_6.scrollboxNode.offsetHeight-_6.scrollboxNode.clientHeight;
-this.scrollbarHeight=_8>this.scrollbarHeight?_8:this.scrollbarHeight;
-}
-},this);
-return this.scrollbarHeight;
-},getExceptionalColOffsetWidth:function(){
-if(!this.grid.indirectSelection||!this.grid.rowSelectCell){
-return 0;
-}
-var _9=(normalizedOffsetWidth=0),_a=this.grid.rowSelectCell.view.scrollboxNode;
-dojo.forEach(this.getHeaderNodes(),function(_b,_c){
-if(_c<=this.exceptColumnsTo){
-var _d=dojo.coords(_b);
-_9+=_d.w;
-}
-},this);
-normalizedOffsetWidth=_9-_a.scrollLeft*(dojo._isBodyLtr()?1:(dojo.isMoz?-1:1));
-return normalizedOffsetWidth>0?normalizedOffsetWidth:0;
-},getGridCoords:function(_e){
-if(!this.gridCoords||_e){
-this.gridCoords=new Object();
-if(!this.headerHeight){
-this.headerHeight=dojo.coords(this.getHeaderNodes()[0]).h;
-}
-var _f=dojo.coords(this.grid.views.views[0].domNode);
-var _10=dojo.coords(this.grid.domNode);
-var _11=dojo.contentBox(this.grid.domNode);
-this.gridCoords.h=_11.h-this.headerHeight-this.getHScrollBarHeight();
-this.gridCoords.t=_10.y;
-this.gridCoords.l=dojo._isBodyLtr()?(_10.x+_f.w):_10.x;
-this.gridCoords.w=_11.w-_f.w;
-}
-return this.gridCoords;
-},createAvatar:function(_12,_13,_14,top,_15){
-this.gridCoords=null;
-var _16=this.getGridCoords();
-var _17=dojo.doc.createElement("DIV");
-_17.className="dojoxGridSelectedDIV";
-_17.id="grid_dnd_cover_div_"+_14+"_"+top;
-_17.style.width=_12+"px";
-var _18=dojo._docScroll();
-var _19=top<_16.t+this.headerHeight?_16.t+this.headerHeight-top:0;
-var _1a=_16.t+_16.h+this.headerHeight;
-var _1b=0;
-if(top<_16.t+this.headerHeight){
-_1b=(_16.t+this.headerHeight);
-}else{
-if(top>_1a){
-_1b=10000;
-}else{
-_1b=top;
-}
-}
-_17.style.top=_1b+_18.y+"px";
-_17.style.left=(_14+_18.x)+"px";
-var _1c=_1b+_13-_19;
-if(_1c>_1a+(_15?this.scrollbarHeight:0)){
-_1c=_1a;
-}
-_17.style.height=((_1c-_1b)>=0?(_1c-_1b):0)+"px";
-dojo.doc.body.appendChild(_17);
-_17.connections=[];
-_17.connections.push(dojo.connect(_17,"onmouseout",this,function(){
-this.clearDrugDivs();
-}));
-_17.connections.push(dojo.connect(_17,"onclick",this,"avataDivClick"));
-_17.connections.push(dojo.connect(_17,"keydown",this,function(e){
-this.handleESC(e,this);
-}));
-this.coverDIVs.push(_17);
-return _17;
-},handleESC:function(e,_1d){
-var dk=dojo.keys;
-switch(e.keyCode){
-case dk.ESCAPE:
-try{
-this.cancelDND();
-}
-catch(e){
-}
-break;
-}
-},cancelDND:function(){
-this.cleanAll();
-this.clearDrugDivs();
-if(this.mover){
-this.mover.destroy();
-}
-this.cleanAll();
-},createCoverMover:function(_1e,_1f,_20,top,_21){
-var _22=this.getGridCoords(),_23=(_21=="col"?true:false);
-var _24={box:{l:(_21=="row"?_20:_22.l)+dojo._docScroll().x,t:(_21=="col"?top:_22.t+this.headerHeight)+dojo._docScroll().y,w:_21=="row"?1:_22.w,h:_21=="col"?1:_22.h},within:true,movingType:_21,mover:dojox.grid.enhanced.dnd._DndMover};
-return new dojox.grid.enhanced.dnd._DndBoxConstrainedMoveable(this.createAvatar(_1e,_1f,_20,top,_23),_24);
-},getBorderDiv:function(){
-var _25=dojo.byId("borderDIV"+this.grid.id);
-if(_25==null){
-_25=dojo.doc.createElement("DIV");
-_25.id="borderDIV"+this.grid.id;
-_25.className="dojoxGridBorderDIV";
-dojo.doc.body.appendChild(_25);
-}
-return _25;
-},setBorderDiv:function(_26,_27,_28,top){
-var _29=this.getBorderDiv();
-dojo.style(_29,{"height":_27+"px","top":top+"px","width":_26+"px","left":_28+"px"});
-return _29;
-},removeOtherMovers:function(id){
-if(!this.coverDIVs.hasRemovedOtherMovers){
-var _2a;
-dojo.forEach(this.coverDIVs,function(div){
-if(div.id!=id){
-dojo.doc.body.removeChild(div);
-}else{
-_2a=div;
-}
-},this);
-this.coverDIVs=[_2a];
-this.coverDIVs.hasRemovedOtherMovers=true;
-}
-},addColMovers:function(){
-var _2b=-1;
-dojo.forEach(this.selectedColumns,function(col,_2c){
-if(this.isColSelected(_2c)){
-if(_2b==-1){
-_2b=_2c;
-}
-if(this.selectedColumns[_2c+1]==null){
-this.addColMover(_2b,_2c);
-_2b=-1;
-}
-}
-},this);
-},addColMover:function(_2d,_2e){
-if(this.lock){
-return;
-}
-var _2f=(_30=0);
-var top=null,_31=null;
-if(dojo._isBodyLtr()){
-dojo.forEach(this.getHeaderNodes(),function(_32,_33){
-var _34=dojo.coords(_32);
-if(_33==_2d){
-_2f=_34.x;
-top=_34.y+_34.h;
-_31=_34.h;
-}
-if(_33==_2e){
-_30=_34.x+_34.w;
-}
-});
-}else{
-dojo.forEach(this.getHeaderNodes(),function(_35,_36){
-var _37=dojo.coords(_35);
-if(_36==_2d){
-_30=_37.x+_37.w;
-_31=_37.h;
-}
-if(_36==_2e){
-_2f=_37.x;
-top=_37.y+_37.h;
-}
-});
-}
-var _38=this.normalizeColMoverCoords(_2f,_30,_2d,_2e);
-var _39=_38.h,_3a=_38.w,_2f=_38.l,_30=_38.r;
-var _3b=this.createCoverMover(_3a,_39,_2f,top,"col");
-this.movers.push(_3b);
-var _3c=this.setBorderDiv(3,_39,-1000,top+dojo._docScroll().y);
-dojo.attr(_3c,"colH",_38.colH);
-dojo.connect(_3b,"onMoveStart",dojo.hitch(this,function(_3d,_3e){
-this.mover=_3d;
-this.removeOtherMovers(_3d.node.id);
-}));
-dojo.connect(_3b,"onMove",dojo.hitch(this,function(_3f,_40,_41){
-if(_3f.node==null||_3f.node.parentNode==null){
-return;
-}
-this.isMoving=true;
-this.moveColBorder(_3f,_41,_3c);
-}));
-dojo.connect(_3b,"onMoveStop",dojo.hitch(this,function(_42){
-if(this.drugDestIndex==null||this.isContinuousSelection(this.selectedColumns)&&(this.drugDestIndex==_2d||this.drugDestIndex==_2e||this.drugDestIndex==(_2e+1)&&this.drugBefore)){
-this.movingIgnored=true;
-if(this.isMoving){
-this.isMoving=false;
-this.clearDrugDivs();
-}
-return;
-}
-this.isMoving=false;
-this.mover=null;
-this.startMoveCols();
-this.drugDestIndex=null;
-}));
-},normalizeColMoverCoords:function(_43,_44,_45,_46){
-var _47=_44-_43,_48=this.grid.views.views,_49=this.grid.pluginMgr;
-var _4a={"w":_47,"h":0,"l":_43,"r":_44,"colH":0};
-var _4b=this.getGridWidth()-_48[_48.length-1].getScrollbarWidth();
-var rtl=!dojo._isBodyLtr();
-var _4c=_49.getViewByCellIdx(!rtl?_45:_46);
-var _4d=_49.getViewByCellIdx(!rtl?_46:_45);
-var _4e=(_4c==_4d);
-if(!_4c||!_4d){
-return _4a;
-}
-var _4f=dojo.coords(_4c.scrollboxNode).x+(rtl&&dojo.isIE?_4c.getScrollbarWidth():0);
-var _50=dojo.coords(_4d.scrollboxNode);
-var _51=_50.x+_50.w-((!rtl||!dojo.isIE)?_4d.getScrollbarWidth():0);
-if(_4a.l<_4f){
-_4a.w=_4a.r-_4f;
-_4a.l=_4f;
-}
-if(_4a.r>_51){
-_4a.w=_51-_4a.l;
-}
-var i,_52=this.grid.views.views[0],_53=dojo.coords(_52.contentNode).h;
-var _54=_4d,_55=_50.h;
-_4a.colH=_53;
-_55=!_4e?_55:(_55-(_54.scrollboxNode.offsetHeight-_54.scrollboxNode.clientHeight));
-_4a.h=_53<_55?_53:_55;
-return _4a;
-},moveColBorder:function(_56,_57,_58){
-var _59=dojo._docScroll(),rtl=!dojo._isBodyLtr();
-_57.x-=_59.x;
-var _5a=this.grid.views.views,_5b=this.getGridCoords();
-var _5c=_5a[!rtl?1:_5a.length-1].scrollboxNode;
-var _5d=_5a[!rtl?_5a.length-1:1].scrollboxNode;
-var _5e=(!rtl||!dojo.isIE)?_5b.l:(_5b.l+_5c.offsetWidth-_5c.clientWidth);
-var _5f=(!rtl||dojo.isMoz)?(_5b.l+_5b.w-(_5d.offsetWidth-_5d.clientWidth)):(_5b.l+_5b.w);
-dojo.forEach(this.getHeaderNodes(),dojo.hitch(this,function(_60,_61){
-if(_61>this.exceptColumnsTo){
-var x,_62=dojo.coords(_60);
-if(_57.x>=_62.x&&_57.x<=_62.x+_62.w){
-if(!this.selectedColumns[_61]||!this.selectedColumns[_61-1]){
-x=_62.x+_59.x+(rtl?_62.w:0);
-if(_57.x<_5e||_57.x>_5f||x<_5e||x>_5f){
-return;
-}
-dojo.style(_58,"left",x+"px");
-this.drugDestIndex=_61;
-this.drugBefore=true;
-!dojo.isIE&&this.normalizeColBorderHeight(_58,_61);
-}
-}else{
-if(this.getHeaderNodes()[_61+1]==null&&(!rtl?(_57.x>_62.x+_62.w):(_57.x<_62.x))){
-x=_57.x<_5e?_5e:(_57.x>_5f?_5f:(_62.x+_59.x+(rtl?0:_62.w)));
-dojo.style(_58,"left",x+"px");
-this.drugDestIndex=_61;
-this.drugBefore=false;
-!dojo.isIE&&this.normalizeColBorderHeight(_58,_61);
-}
-}
-}
-}));
-},normalizeColBorderHeight:function(_63,_64){
-var _65=this.grid.pluginMgr.getViewByCellIdx(_64);
-if(!_65){
-return;
-}
-var _66=_65.scrollboxNode,_67=dojo.attr(_63,"colH");
-var _68=dojo.coords(_66).h-(_66.offsetHeight-_66.clientHeight);
-_68=_67>0&&_67<_68?_67:_68;
-dojo.style(_63,"height",_68+"px");
-},avataDivClick:function(e){
-if(this.movingIgnored){
-this.movingIgnored=false;
-return;
-}
-this.cleanAll();
-this.clearDrugDivs();
-},startMoveCols:function(){
-this.changeCursorState("wait");
-this.srcIndexdelta=0;
-deltaColAmount=0;
-dojo.forEach(this.selectedColumns,dojo.hitch(this,function(col,_69){
-if(this.isColSelected(_69)){
-if(this.drugDestIndex>_69){
-_69-=deltaColAmount;
-}
-deltaColAmount+=1;
-var _6a=this.grid.layout.cells[_69].view.idx;
-var _6b=this.grid.layout.cells[this.drugDestIndex].view.idx;
-if(_69!=this.drugDestIndex){
-this.grid.layout.moveColumn(_6a,_6b,_69,this.drugDestIndex,this.drugBefore);
-}
-if(this.drugDestIndex<=_69&&this.drugDestIndex+1<this.grid.layout.cells.length){
-this.drugDestIndex+=1;
-}
-}
-}));
-var _6c=this.drugDestIndex+(this.drugBefore?0:1);
-this.clearDrugDivs();
-this.cleanAll();
-this.resetCellIdx();
-this.drugSelectionStart.colIndex=_6c-deltaColAmount;
-this.drugSelectColumn(this.drugSelectionStart.colIndex+deltaColAmount-1);
-},changeCursorState:function(_6d){
-dojo.forEach(this.coverDIVs,function(div){
-div.style.cursor="wait";
-});
-},addRowMovers:function(){
-var _6e=-1;
-dojo.forEach(this.grid.selection.selected,function(row,_6f){
-var _70=this.grid.views.views[0];
-if(row&&_70.rowNodes[_6f]){
-if(_6e==-1){
-_6e=_6f;
-}
-if(this.grid.selection.selected[_6f+1]==null||!_70.rowNodes[_6f+1]){
-this.addRowMover(_6e,_6f);
-_6e=-1;
-}
-}
-},this);
-},addRowMover:function(_71,to){
-var _72=0,_73=this.grid.views.views;
-dojo.forEach(_73,function(_74,_75){
-_72+=_74.getScrollbarWidth();
-});
-var _76=_73[_73.length-1].getScrollbarWidth();
-var _77=!dojo._isBodyLtr()?(dojo.isIE?_72-_76:_72):0;
-var _78=this.getGridWidth()-_76;
-var _79=this.grid.views.views[0];
-var _7a=_79.rowNodes[_71],_7b=_79.rowNodes[to];
-if(!_7a||!_7b){
-return;
-}
-var _7c=dojo.coords(_7a),_7d=dojo.coords(_7b);
-var _7e=this.getExceptionalColOffsetWidth();
-var _7f=this.createCoverMover(_78-_7e,(_7d.y-_7c.y+_7d.h),dojo._isBodyLtr()?(_7c.x+_7c.w+_7e):(_7c.x-_78-_77),_7c.y,"row");
-var _80=this.setBorderDiv(_78,3,(dojo._isBodyLtr()?(_7d.x+_7d.w):(_7d.x-_78-_77))+dojo._docScroll().x,-100);
-var _81=dojo.connect(_7f,"onMoveStart",dojo.hitch(this,function(_82,_83){
-this.mover=_82;
-this.removeOtherMovers(_82.node.id);
-}));
-var _84=dojo.connect(_7f,"onMove",dojo.hitch(this,function(_85,_86,_87){
-if(_85.node==null||_85.node.parentNode==null){
-return;
-}
-this.isMoving=true;
-this.moveRowBorder(_85,_86,_80,_87);
-}));
-var _88=dojo.connect(_7f,"onMoveStop",dojo.hitch(this,function(_89){
-if(this.avaOnRowIndex==null||this.isContinuousSelection(this.grid.selection.selected)&&(this.avaOnRowIndex==_71||this.avaOnRowIndex==(to+1))){
-this.movingIgnored=true;
-if(this.isMoving){
-this.isMoving=false;
-this.clearDrugDivs();
-}
-return;
-}
-this.isMoving=false;
-this.mover=null;
-this.grid.select.outRangeY=false;
-this.grid.select.moveOutTop=false;
-this.grid.scroller.findScrollTop(this.grid.scroller.page*this.grid.scroller.rowsPerPage);
-this.startMoveRows();
-this.avaOnRowIndex=null;
-delete _7f;
-}));
-},moveRowBorder:function(_8a,_8b,_8c,_8d){
-var _8e=this.getGridCoords(true),_8f=dojo._docScroll();
-var _90=_8e.t+this.headerHeight+_8e.h;
-_8b.t-=_8f.y,_8d.y-=_8f.y;
-if(_8d.y>=_90){
-this.grid.select.outRangeY=true;
-this.autoMoveToNextRow();
-}else{
-if(_8d.y<=_8e.t+this.headerHeight){
-this.grid.select.moveOutTop=true;
-this.autoMoveToPreRow();
-}else{
-this.grid.select.outRangeY=this.grid.select.moveOutTop=false;
-var _91=this.grid.views.views[0],_92=_91.rowNodes;
-var _93=dojo.coords(_91.contentNode).h;
-var _94=0,_95=-1;
-for(i in _92){
-++_94;
-if(i>_95){
-_95=i;
-}
-}
-var _96=dojo.coords(_92[_95]);
-if(_93<_8e.h&&_8d.y>(_96.y+_96.h)){
-this.avaOnRowIndex=_94;
-dojo.style(_8c,{"top":_96.y+_96.h+_8f.y+"px"});
-return;
-}
-var _97,_98,_99;
-for(var _9a in _92){
-_9a=parseInt(_9a);
-if(isNaN(_9a)){
-continue;
-}
-_98=_92[_9a];
-if(!_98){
-continue;
-}
-_97=dojo.coords(_98),_99=(_97.y<=_90);
-if(_99&&_8d.y>_97.y&&_8d.y<_97.y+_97.h){
-if(!this.grid.selection.selected[_9a]||!this.grid.selection.selected[_9a-1]){
-this.avaOnRowIndex=_9a;
-dojo.style(_8c,{"top":_97.y+_8f.y+"px"});
-}
-}
-}
-}
-}
-},autoMoveToPreRow:function(){
-if(this.grid.select.moveOutTop){
-if(this.grid.scroller.firstVisibleRow>0){
-this.grid.scrollToRow(this.grid.scroller.firstVisibleRow-1);
-this.autoMoveBorderDivPre();
-setTimeout(dojo.hitch(this,"autoMoveToPreRow"),this.autoScrollRate);
-}
-}
-},autoMoveBorderDivPre:function(){
-var _9b=dojo._docScroll(),_9c=this.getGridCoords();
-var _9d=_9c.t+this.headerHeight+_9b.y;
-var _9e,_9f=this.getBorderDiv();
-if(this.avaOnRowIndex-1<=0){
-this.avaOnRowIndex=0;
-_9e=_9d;
-}else{
-this.avaOnRowIndex--;
-_9e=dojo.coords(this.grid.views.views[0].rowNodes[this.avaOnRowIndex]).y+_9b.y;
-}
-_9f.style.top=(_9e<_9d?_9d:_9e)+"px";
-},autoMoveToNextRow:function(){
-if(this.grid.select.outRangeY){
-if(this.avaOnRowIndex+1<=this.grid.scroller.rowCount){
-this.grid.scrollToRow(this.grid.scroller.firstVisibleRow+1);
-this.autoMoveBorderDiv();
-setTimeout(dojo.hitch(this,"autoMoveToNextRow"),this.autoScrollRate);
-}
-}
-},autoMoveBorderDiv:function(){
-var _a0=dojo._docScroll(),_a1=this.getGridCoords();
-var _a2=_a1.t+this.headerHeight+_a1.h+_a0.y;
-var _a3,_a4=this.getBorderDiv();
-if(this.avaOnRowIndex+1>=this.grid.scroller.rowCount){
-this.avaOnRowIndex=this.grid.scroller.rowCount;
-_a3=_a2;
-}else{
-this.avaOnRowIndex++;
-_a3=dojo.coords(this.grid.views.views[0].rowNodes[this.avaOnRowIndex]).y+_a0.y;
-}
-_a4.style.top=(_a3>_a2?_a2:_a3)+"px";
-},startMoveRows:function(){
-var _a5=Math.min(this.avaOnRowIndex,this.getFirstSelected());
-var end=Math.max(this.avaOnRowIndex-1,this.getLastSelected());
-this.moveRows(_a5,end,this.getPageInfo());
-},moveRows:function(_a6,end,_a7){
-var i,_a8=false,_a9=(selectedRowsAboveBorderDIV=0),_aa=[];
-var _ab=this.grid.scroller,_ac=_ab.rowsPerPage;
-var _ad=_a7.topPage*_ac,_ae=(_a7.bottomPage+1)*_ac-1;
-var _af=dojo.hitch(this,function(_b0,to){
-for(i=_b0;i<to;i++){
-if(!this.grid.selection.selected[i]||!this.grid._by_idx[i]){
-_aa.push(this.grid._by_idx[i]);
-}
-}
-});
-_af(_a6,this.avaOnRowIndex);
-for(i=_a6;i<=end;i++){
-if(this.grid.selection.selected[i]&&this.grid._by_idx[i]){
-_aa.push(this.grid._by_idx[i]);
-_a9++;
-if(this.avaOnRowIndex>i){
-selectedRowsAboveBorderDIV++;
-}
-}
-}
-_af(this.avaOnRowIndex,end+1);
-for(i=_a6,j=0;i<=end;i++){
-this.grid._by_idx[i]=_aa[j++];
-if(i>=_ad&&i<=_ae){
-this.grid.updateRow(i);
-_a8=true;
-}
-}
-this.avaOnRowIndex+=_a9-selectedRowsAboveBorderDIV;
-try{
-this.clearDrugDivs();
-this.cleanAll();
-this.drugSelectionStart.rowIndex=this.avaOnRowIndex-_a9;
-this.drugSelectRow(this.drugSelectionStart.rowIndex+_a9-1);
-if(_a8){
-var _b1=_ab.stack;
-dojo.forEach(_a7.invalidPages,function(_b2){
-_ab.destroyPage(_b2);
-i=dojo.indexOf(_b1,_b2);
-if(i>=0){
-_b1.splice(i,1);
-}
-});
-}
-this.publishRowMove();
-}
-catch(e){
-}
-},clearDrugDivs:function(){
-if(!this.isMoving){
-var _b3=this.getBorderDiv();
-_b3.style.top=-100+"px";
-_b3.style.height="0px";
-_b3.style.left=-100+"px";
-dojo.forEach(this.coverDIVs,function(div){
-dojo.forEach(div.connections,function(_b4){
-dojo.disconnect(_b4);
-});
-dojo.doc.body.removeChild(div);
-delete div;
-},this);
-this.coverDIVs=[];
-}
-},setDrugCoverDivs:function(_b5,_b6){
-if(!this.isMoving){
-if(this.isColSelected(_b5)){
-this.addColMovers();
-}else{
-if(this.grid.selection.selected[_b6]){
-this.addRowMovers();
-}else{
-this.clearDrugDivs();
-}
-}
-}
-},getPageInfo:function(){
-var _b7=this.grid.scroller,_b8=(bottomPage=_b7.page);
-var _b9=_b7.firstVisibleRow,_ba=_b7.lastVisibleRow;
-var _bb=_b7.rowsPerPage,_bc=_b7.pageNodes[0];
-var _bd,_be,_bf=[],_c0;
-dojo.forEach(_bc,function(_c1,_c2){
-if(!_c1){
-return;
-}
-_c0=false;
-_bd=_c2*_bb;
-_be=(_c2+1)*_bb-1;
-if(_b9>=_bd&&_b9<=_be){
-_b8=_c2;
-_c0=true;
-}
-if(_ba>=_bd&&_ba<=_be){
-bottomPage=_c2;
-_c0=true;
-}
-if(!_c0&&(_bd>_ba||_be<_b9)){
-_bf.push(_c2);
-}
-});
-return {topPage:_b8,bottomPage:bottomPage,invalidPages:_bf};
-},resetCellIdx:function(){
-var _c3=0;
-var _c4=-1;
-dojo.forEach(this.grid.views.views,function(_c5,_c6){
-if(_c6==0){
-return;
-}
-if(_c5.structure.cells&&_c5.structure.cells[0]){
-dojo.forEach(_c5.structure.cells[0],function(_c7,_c8){
-var _c9=_c7.markup[2].split(" ");
-var idx=_c3+_c8;
-_c9[1]="idx=\""+idx+"\"";
-_c7.markup[2]=_c9.join(" ");
-});
-}
-for(i in _c5.rowNodes){
-if(!_c5.rowNodes[i]){
-return;
-}
-dojo.forEach(_c5.rowNodes[i].firstChild.rows[0].cells,function(_ca,_cb){
-if(_ca&&_ca.attributes){
-if(_cb+_c3>_c4){
-_c4=_cb+_c3;
-}
-var idx=document.createAttribute("idx");
-idx.value=_cb+_c3;
-_ca.attributes.setNamedItem(idx);
-}
-});
-}
-_c3=_c4+1;
+
+dojo.declare("dojox.grid.enhanced.dnd._DndMovingManager", dojox.grid.enhanced.dnd._DndSelectingManager, {
+	//summary:
+	//		_DndMovingManager is used to enable grid DND moving feature
+	
+	//exceptRowsTo: Integer
+	//		the value to which that rows, that should not be moved, with index from the -1
+	exceptRowsTo: -1,
+	
+	//exceptColumnsTo: Integer
+	//		the value to which that columns, that should not be moved, with index from the -1
+	exceptColumnsTo: -1,
+	
+	//coverDIVs: Array
+	//		the list that keep the reference to all cover DIVs for DND moving
+	coverDIVs: [],
+	
+	//movers: Array
+	//		the list that keep the reference to all dnd movers for DND moving
+	movers:[],
+	
+	constructor: function(inGrid){
+		//summary:
+		//		constructor, set the exceptColumnsTo value if the indirect selection feature is enabled 
+		if(this.grid.indirectSelection){
+			this.exceptColumnsTo = this.grid.pluginMgr.getFixedCellNumber() - 1;
+		}
+		this.coverDIVs = this.movers = [];
+			
+		dojo.subscribe("CTRL_KEY_DOWN", dojo.hitch(this,function(publisher, keyEvent){
+			if(publisher == this.grid && publisher != this){
+				this.keyboardMove(keyEvent);
+			}
+		}));
+		
+		dojo.forEach(this.grid.views.views, function(view){
+			//fix the jumping issue of cover div when scrolled
+			dojo.connect(view.scrollboxNode, 'onscroll', dojo.hitch(this, function(){
+				this.clearDrugDivs();
+			}));
+		}, this);		
+	},
+	
+	getGridWidth: function(){		
+		//summary:
+		//		get the width of the grid
+		//return: Integer
+		//		the width of the grid
+		return dojo.contentBox(this.grid.domNode).w - this.grid.views.views[0].getWidth().replace("px","");
+	},
+	
+	isColSelected: function(inColIndex){
+		//summary:
+		//		whether the specified column is selected
+		//inColIndex: Integer
+		//		the index value of the column
+		//return: Boolean
+		//		whether the specified column is selected
+		return this.selectedColumns[inColIndex] && inColIndex > this.exceptColumnsTo;
+	},
+	
+	getHScrollBarHeight: function(){
+		//summary:
+		//		get the horizontal sroll bar height
+		//return: Integer
+		//		 the horizontal sroll bar height
+		this.scrollbarHeight = 0;
+		dojo.forEach(this.grid.views.views, function(view, index){
+			if(view.scrollboxNode){
+				var thisbarHeight = view.scrollboxNode.offsetHeight - view.scrollboxNode.clientHeight;
+				this.scrollbarHeight = thisbarHeight > this.scrollbarHeight ? thisbarHeight : this.scrollbarHeight;
+			}
+		}, this);
+		return this.scrollbarHeight;
+	},
+	
+	getExceptionalColOffsetWidth: function(){
+		//summary:
+		//		get the width of all un-movable columns
+		//return: Integer
+		//		the width of all un-movable columns
+		if(!this.grid.indirectSelection || !this.grid.rowSelectCell){ return 0; }
+		var offsetWidth = (normalizedOffsetWidth = 0), viewNode = this.grid.rowSelectCell.view.scrollboxNode;
+		dojo.forEach(this.getHeaderNodes(), function(node, index){
+			if(index <= this.exceptColumnsTo){
+				var coord = dojo.coords(node);
+				offsetWidth += coord.w;
+			}
+		}, this);
+		normalizedOffsetWidth = offsetWidth - viewNode.scrollLeft * (dojo._isBodyLtr() ? 1 : (dojo.isMoz ? -1 : 1));
+		return normalizedOffsetWidth > 0 ? normalizedOffsetWidth : 0;		
+	},
+	
+	getGridCoords: function(noCache){
+		//summary:
+		//		get the coords values of the grid
+		// noCache: Boolean
+		//		force a realtime calculation
+		//return: Object
+		//		the coords values of the grid
+		if(!this.gridCoords || noCache){
+			this.gridCoords = new Object();
+			if(!this.headerHeight){
+				this.headerHeight = dojo.coords(this.getHeaderNodes()[0]).h;
+			}
+			var rowBarDomNodeCoords = dojo.coords(this.grid.views.views[0].domNode);
+			var gridDomCoords = dojo.coords(this.grid.domNode);
+			var gridDomBox = dojo.contentBox(this.grid.domNode);//use contentBox.h/w to exclude any margins
+			this.gridCoords.h = gridDomBox.h - this.headerHeight - this.getHScrollBarHeight();
+			this.gridCoords.t = gridDomCoords.y;
+			this.gridCoords.l = dojo._isBodyLtr() ? (gridDomCoords.x + rowBarDomNodeCoords.w) : gridDomCoords.x;
+			this.gridCoords.w = gridDomBox.w - rowBarDomNodeCoords.w;
+		}
+		return this.gridCoords;
+	},
+	
+	createAvatar: function(width, height, left, top, includeHScroll){
+		// Summary:
+		//		Create a avatar div to DND
+		// width: Integer
+		//		width of avatar
+		// height: Integer
+		//		height of avatar
+		// left: Integer
+		//		left position of avatar
+		// top: Integer
+		// 		top position of avatar
+		// includeHScroll: Boolean
+		// 		whether to include the H-scroll height	
+		// Return: Dom node
+		//		the avatar DIV node
+		this.gridCoords = null;
+		var getGridCoords = this.getGridCoords();
+		
+		var avatar = dojo.doc.createElement("DIV");
+		avatar.className = "dojoxGridSelectedDIV";
+		avatar.id = "grid_dnd_cover_div_" + left + "_" + top;
+
+		avatar.style.width = width + "px";
+		
+		var _docScroll = dojo._docScroll();
+		
+		var topDelta = top < getGridCoords.t + this.headerHeight
+			? getGridCoords.t + this.headerHeight - top : 0;
+		var gridBottom = getGridCoords.t + getGridCoords.h + this.headerHeight;
+		
+		var avatarTop = 0;
+		if(top < getGridCoords.t + this.headerHeight){
+			avatarTop = (getGridCoords.t + this.headerHeight);
+		}else if(top > gridBottom){
+			//avatar should not be shown
+			avatarTop = 10000;
+		}else{
+			avatarTop = top ;
+		}
+	
+		avatar.style.top = avatarTop + _docScroll.y + "px";
+		avatar.style.left = (left + _docScroll.x) + "px";
+		
+		var avatarBottom = avatarTop + height - topDelta;
+		if(avatarBottom > gridBottom + (includeHScroll ? this.scrollbarHeight : 0)){
+			avatarBottom = gridBottom;
+		}
+		
+		avatar.style.height = ((avatarBottom - avatarTop) >= 0 ? (avatarBottom - avatarTop) : 0) + "px";
+		
+		dojo.doc.body.appendChild(avatar);
+		avatar.connections = [];
+		avatar.connections.push(dojo.connect(avatar, "onmouseout", this, function(){
+			this.clearDrugDivs();
+		}));
+		
+		avatar.connections.push(dojo.connect(avatar, "onclick", this, "avataDivClick"));
+		avatar.connections.push(dojo.connect(avatar, "keydown", this, function(e){
+			this.handleESC(e, this);
+		}));
+		this.coverDIVs.push(avatar);
+		
+		return avatar;
+	},
+	
+	handleESC: function(e, select){
+		//Summary:
+		//		 handle the esc down event, stop DND operation
+		//e: Event
+		//		the keydown event
+		//select: _DndSelectingManager
+		//		the reference to the instance of _DndSelectingManager
+		var dk = dojo.keys;
+		switch(e.keyCode){
+			case dk.ESCAPE:
+				try{
+					this.cancelDND();
+				}catch(e){
+					console.debug(e);
+				}
+			break;
+		}
+	}, 
+	
+	cancelDND: function(){
+		//Summary:
+		//		Stop the DND operation
+		this.cleanAll();
+		this.clearDrugDivs();
+		if(this.mover){
+			this.mover.destroy();
+		}
+		this.cleanAll();
+	},
+	
+	createCoverMover: function(width, height, left, top, type){
+		//Summary:
+		//		Create the mover according to the avatar, 
+		//		and set the move constraint box to make it move horizontally or vertically
+		
+		var gridCoords = this.getGridCoords(), includeHScroll = (type == "col" ? true : false);
+		var params = {box: {l: (type == "row" ? left : gridCoords.l) + dojo._docScroll().x, 
+						 t: (type == "col" ? top : gridCoords.t + this.headerHeight) + dojo._docScroll().y, 
+						 w: type == "row" ? 1 : gridCoords.w,					// keep the moving horizontally
+						 h: type == "col" ? 1 : gridCoords.h // keep the moving vertically
+						 }, within:true, movingType: type,
+				   mover: dojox.grid.enhanced.dnd._DndMover};
+		return new dojox.grid.enhanced.dnd._DndBoxConstrainedMoveable(this.createAvatar(width, height, left, top, includeHScroll), 
+		params);
+	},
+	
+	getBorderDiv: function(){
+		//summary:
+		//		get the border DIV that is used identify the moving position
+		//return: Object
+		//		 the border DIV that is used identify the moving position
+		var borderDIV = dojo.byId("borderDIV" + this.grid.id);
+		if(borderDIV == null){
+			borderDIV = dojo.doc.createElement("DIV");
+			borderDIV.id = "borderDIV" + this.grid.id;
+			borderDIV.className = "dojoxGridBorderDIV";
+			dojo.doc.body.appendChild(borderDIV);
+		}
+		return borderDIV;
+	},
+	
+	setBorderDiv: function(width, height, left, top){
+		//summary:
+		//		set the position and shape of the border DIV that is used identify the moving position
+		//width: Integer
+		//height: Integer
+		//left: Integer
+		//top: Integer
+		//		the position and shape of the border DIV		
+		var borderDIV = this.getBorderDiv();
+		dojo.style(borderDIV, {"height" : height + "px", "top" : top + "px", "width" : width + "px", "left" : left + "px"});
+		return borderDIV;
+	},
+	
+	removeOtherMovers: function(id){
+		//summary:
+		//		remove other movers than the specified one
+		//id: Integer
+		//		the id of the specified mover
+		if(!this.coverDIVs.hasRemovedOtherMovers){
+			var movingDIV;
+			dojo.forEach(this.coverDIVs, function(div){
+				if(div.id != id){
+					dojo.doc.body.removeChild(div);
+				}else{
+					movingDIV = div;
+				}
+			}, this);
+			this.coverDIVs = [movingDIV];
+			this.coverDIVs.hasRemovedOtherMovers = true;
+		}
+	},
+	
+	addColMovers: function(){
+		// Summary:
+		//		Add DND movers for column DND
+		var startSetDiv = -1;
+		dojo.forEach(this.selectedColumns,function(col, index){
+			if(this.isColSelected(index)){
+				if(startSetDiv == -1){
+					startSetDiv = index;
+				}
+				if(this.selectedColumns[index + 1] == null){
+					this.addColMover(startSetDiv, index);
+					startSetDiv = -1;
+				}
+			}
+		}, this);
+	},
+	
+	addColMover: function(leadingBorderIdx, trailingBorderIdx){
+		// Summary:
+		//		Add DND mover for column DND
+		// leadingBorderIdx: Integer
+		//		the first column index for mover to cover
+		// trailingBorderIdx: Integer
+		//		the last column index for mover to cover
+		//console.debug("add mover: " + this.lock + "  l=" + leadingBorderIdx);
+		if(this.lock){
+			//console.debug("locked");
+			return;
+		}
+		var leftPosition = (rightPosition = 0);
+		var top = null, headerHeight = null;
+		if(dojo._isBodyLtr()){
+			dojo.forEach(this.getHeaderNodes(), function(node, index){
+				var coord = dojo.coords(node);
+				if(index == leadingBorderIdx){
+					leftPosition = coord.x;
+					top = coord.y + coord.h;
+					headerHeight = coord.h;
+				}
+				if(index == trailingBorderIdx){
+					rightPosition = coord.x + coord.w;
+				}
+			});
+		}else{
+			dojo.forEach(this.getHeaderNodes(), function(node, index){
+				var coord = dojo.coords(node);
+				if(index == leadingBorderIdx){
+					rightPosition = coord.x + coord.w;
+					headerHeight = coord.h;
+				}
+				if(index == trailingBorderIdx){
+					leftPosition = coord.x;
+					top = coord.y + coord.h;
+				}
+			});
+		}
+		
+		var coords = this.normalizeColMoverCoords(leftPosition, rightPosition, leadingBorderIdx, trailingBorderIdx);
+		var height = coords.h, width = coords.w;
+		leftPosition = coords.l, rightPosition = coords.r;
+		
+		var coverMover = this.createCoverMover(width, height, leftPosition, top, "col");
+		this.movers.push(coverMover);
+		var borderDIV = this.setBorderDiv(3, height, -1000, top + dojo._docScroll().y);
+		dojo.attr(borderDIV, 'colH', coords.colH);
+			
+		dojo.connect(coverMover, "onMoveStart", dojo.hitch(this, function(mover, leftTop){
+			this.mover = mover;
+			this.removeOtherMovers(mover.node.id);
+		}));
+		dojo.connect(coverMover, "onMove", dojo.hitch(this, function(mover, leftTop, mousePos){
+			if(mover.node == null || mover.node.parentNode == null){
+				return;
+			}
+			this.isMoving = true;
+			this.moveColBorder(mover, mousePos, borderDIV);
+		}));
+		dojo.connect(coverMover, "onMoveStop", dojo.hitch(this,function(mover){
+			if(this.drugDestIndex == null || this.isContinuousSelection(this.selectedColumns) 
+			   && (this.drugDestIndex == leadingBorderIdx || this.drugDestIndex == trailingBorderIdx || this.drugDestIndex == (trailingBorderIdx + 1) && this.drugBefore)){ 
+			   this.movingIgnored = true;
+			   if(this.isMoving){
+			   		this.isMoving = false;
+					this.clearDrugDivs();
+			   }
+			   return; 
+			}			
+			this.isMoving = false;
+			this.mover = null;
+			this.startMoveCols();
+			this.drugDestIndex = null;
+		}));
+	},
+	
+	normalizeColMoverCoords: function(leftPosition, rightPosition, leadingBorderIdx, trailingBorderIdx){
+		// Summary:
+		//		Normalize width/height, view column height and left/right x coordinates for column cover div
+		// leftPosition: Integer
+		//		Left side x coordinate of column mover
+		// rightPosition: Integer
+		//		Right side x coordinate of column mover
+		// leadingBorderIdx: Integer
+		//		The leftmost column index for mover to cover
+		// trailingBorderIdx: Integer
+		//		The rightmost column index for mover to cover
+		// return:Object
+		//		Normalized width and coordinates, e.g.{'w': 100, 'h': 200, 'l': 150, 'r': 250, 'colH': 50}
+		var width = rightPosition - leftPosition, views = this.grid.views.views, pluginMgr = this.grid.pluginMgr;
+		var coords = {'w': width, 'h': 0, 'l': leftPosition, 'r': rightPosition, 'colH': 0};
+		var gridWidth = this.getGridWidth() - views[views.length-1].getScrollbarWidth();
+		
+		var rtl = !dojo._isBodyLtr();
+		var leftView = pluginMgr.getViewByCellIdx(!rtl ? leadingBorderIdx : trailingBorderIdx); 
+		var rightView = pluginMgr.getViewByCellIdx(!rtl ? trailingBorderIdx : leadingBorderIdx);
+		var inSameView = (leftView == rightView);
+		
+		if(!leftView || !rightView){ return coords;}
+		
+		var leftBoundary = dojo.coords(leftView.scrollboxNode).x + (rtl && dojo.isIE ? leftView.getScrollbarWidth() : 0);
+		var rightViewCoords = dojo.coords(rightView.scrollboxNode);
+		var rightBoundary = rightViewCoords.x + rightViewCoords.w - ((!rtl || !dojo.isIE) ? rightView.getScrollbarWidth() : 0);
+		
+		if(coords.l < leftBoundary){
+			coords.w = coords.r - leftBoundary;
+			coords.l = leftBoundary;
+		}
+		if(coords.r > rightBoundary){
+			coords.w = rightBoundary - coords.l;
+		}
+
+		var i, rowBarView = this.grid.views.views[0], colHeight =  dojo.coords(rowBarView.contentNode).h;;
+		var view = rightView/*use right view as default*/, viewHeight = rightViewCoords.h;
+		coords.colH = colHeight;
+		viewHeight = !inSameView ? viewHeight : (viewHeight - (view.scrollboxNode.offsetHeight - view.scrollboxNode.clientHeight));
+		coords.h = colHeight < viewHeight ? colHeight : viewHeight;
+		return coords;
+	},	
+	
+	moveColBorder: function(mover, mousePos, borderDIV){
+		//Summary:
+		//		Column border identify the dnd dest position. move the border according to avatar move
+		//mover: Object
+		//		the reference to the dnd mover
+		//mousePos: Object
+		//		the current position of the mover - {x:.., Y:..}	
+		//borderDIV:Object
+		//		reference to the borderDIV
+		var docScroll = dojo._docScroll(), rtl = !dojo._isBodyLtr();
+		mousePos.x -= docScroll.x;		
+
+		var views = this.grid.views.views, gridCoords = this.getGridCoords();
+		var leftViewNode = views[!rtl ? 1 : views.length-1].scrollboxNode;
+		var rightViewNode = views[!rtl ? views.length-1 : 1].scrollboxNode;
+			
+		var leftX = (!rtl || !dojo.isIE) ? gridCoords.l : (gridCoords.l + leftViewNode.offsetWidth - leftViewNode.clientWidth);
+		var rightX = (!rtl || dojo.isMoz) ? (gridCoords.l + gridCoords.w - (rightViewNode.offsetWidth - rightViewNode.clientWidth)) : (gridCoords.l + gridCoords.w);
+		
+		dojo.forEach(this.getHeaderNodes(), dojo.hitch(this,function(node, index){
+			if(index > this.exceptColumnsTo){
+				var x, coord = dojo.coords(node);
+				if(mousePos.x >= coord.x && mousePos.x <= coord.x + coord.w){
+					if(!this.selectedColumns[index] || !this.selectedColumns[index - 1]){
+						x = coord.x +  docScroll.x + (rtl ? coord.w : 0);
+						if(mousePos.x < leftX || mousePos.x > rightX || x < leftX || x > rightX){ return; }
+						dojo.style(borderDIV, 'left', x + 'px');
+						this.drugDestIndex = index;
+						this.drugBefore = true;
+						!dojo.isIE && this.normalizeColBorderHeight(borderDIV, index);
+					}
+				}else if(this.getHeaderNodes()[index + 1] == null && (!rtl ? (mousePos.x > coord.x + coord.w) : (mousePos.x < coord.x))){
+						x = mousePos.x < leftX ? leftX : (mousePos.x > rightX ? rightX : (coord.x + docScroll.x + (rtl ? 0 : coord.w)));
+						dojo.style(borderDIV, 'left', x + 'px');
+						this.drugDestIndex = index;
+						this.drugBefore = false;
+						!dojo.isIE && this.normalizeColBorderHeight(borderDIV, index);
+				}
+			}
+		}));
+	},
+	
+	normalizeColBorderHeight: function(borderDiv, colIdx){
+		// Summary:
+		//		Normalize height of mover border div - for column moving
+		// borderDiv: Dom node
+		//		Mover border div dom node
+		// colIdx: Integer
+		//		Column index
+		var view = this.grid.pluginMgr.getViewByCellIdx(colIdx);
+		if(!view){ return; }
+		
+		var node = view.scrollboxNode, colHeight = dojo.attr(borderDiv, 'colH');
+		var viewHeight = dojo.coords(node).h - (node.offsetHeight - node.clientHeight);
+		viewHeight = colHeight > 0 && colHeight < viewHeight ? colHeight : viewHeight;
+		dojo.style(borderDiv, 'height', viewHeight + 'px');
+	},
+	
+	avataDivClick: function(e){
+		//Summary:
+		//		handle click on avatar, hide the avatar
+		if(this.movingIgnored){
+			this.movingIgnored = false;
+			return;
+		}
+		this.cleanAll();
+		this.clearDrugDivs();
+	},
+	
+	startMoveCols: function(){
+		// Summary:
+		//		start to move the selected columns to target position
+		this.changeCursorState("wait");
+		this.srcIndexdelta = 0;
+		deltaColAmount = 0;
+		dojo.forEach(this.selectedColumns, dojo.hitch(this, function(col, index){
+			if(this.isColSelected(index)){				
+				if(this.drugDestIndex > index){
+					index -= deltaColAmount;
+				}
+				deltaColAmount += 1;
+				var srcViewIndex = this.grid.layout.cells[index].view.idx;
+				var destViewIndex = this.grid.layout.cells[this.drugDestIndex].view.idx;
+				if(index != this.drugDestIndex){
+					this.grid.layout.moveColumn(srcViewIndex,destViewIndex,index,this.drugDestIndex,this.drugBefore);
+				}
+				if(this.drugDestIndex <= index && this.drugDestIndex + 1 < this.grid.layout.cells.length){
+					this.drugDestIndex += 1;
+				}				
+			}
+		}));
+		
+		var dest = this.drugDestIndex + (this.drugBefore? 0:1);
+		this.clearDrugDivs();
+		this.cleanAll();
+		this.resetCellIdx();
+		this.drugSelectionStart.colIndex = dest - deltaColAmount;
+		this.drugSelectColumn(this.drugSelectionStart.colIndex +  deltaColAmount - 1);		
+	},
+	
+	changeCursorState: function(state){
+		//summary:
+		//		change the cursor state
+		//state: String
+		//		the state that the cursor will be changed to
+		dojo.forEach(this.coverDIVs, function(div){
+			div.style.cursor = "wait";
+		});
+	},	
+	
+	addRowMovers: function(){
+		// Summary:
+		//		Add DND movers for row DND
+		var startSetDiv = -1;
+		dojo.forEach(this.grid.selection.selected,function(row, index){
+			var rowBarView = this.grid.views.views[0];
+			if(row && rowBarView.rowNodes[index]/*row bar node with 'index' must exist*/){
+				if(startSetDiv == -1){
+					startSetDiv = index;
+				}
+				if(this.grid.selection.selected[index + 1] == null || !rowBarView.rowNodes[index + 1]){
+					this.addRowMover(startSetDiv, index);
+					startSetDiv = -1;
+				}
+			}
+		}, this);
+	},
+	
+	addRowMover: function(from, to){
+		// Summary:
+		//		Add DND mover for row DND
+		// from: 
+		//		the first row index for mover to cover
+		// to:
+		//		the last row index for mover to cover
+
+		// scroll bar width sum, to fix the insufficient width of borderDIV/coverDIV for 2+ views
+		var scrollBarWidthSum = 0, views = this.grid.views.views;
+		dojo.forEach(views, function(view, index){
+			scrollBarWidthSum += view.getScrollbarWidth();
+		});
+		var lastScrollBarWidth = views[views.length-1].getScrollbarWidth();
+		var widthDelta = !dojo._isBodyLtr() ? (dojo.isIE ? scrollBarWidthSum - lastScrollBarWidth : scrollBarWidthSum) : 0;
+		
+		// get grid width except the scroll bar width of trailing view
+		//var gridWidth = this.getGridWidth() + scrollBarWidthSum - lastScrollBarWidth;
+		var gridWidth = this.getGridWidth() - lastScrollBarWidth;
+		
+		// use rowBar as row position identifier
+		var rowBarView = this.grid.views.views[0];
+		var startBarNode = rowBarView.rowNodes[from],
+			endBarNode = rowBarView.rowNodes[to];			
+			
+		// get the start and end postion of selected area
+		if(!startBarNode || !endBarNode){
+			return; // row not loaded
+		}
+		var	startCoord = dojo.coords(startBarNode), endCoord = dojo.coords(endBarNode);
+		var exceptionalColOffsetWidth = this.getExceptionalColOffsetWidth(); 
+		
+		var coverMover = this.createCoverMover(gridWidth - exceptionalColOffsetWidth, // width
+											   (endCoord.y - startCoord.y + endCoord.h), // height
+												dojo._isBodyLtr() ? (startCoord.x + startCoord.w + exceptionalColOffsetWidth) : (startCoord.x - gridWidth - widthDelta),
+											    startCoord.y,
+												"row"); // top
+		var borderDIV = this.setBorderDiv(gridWidth, 3,  // width & height
+									(dojo._isBodyLtr() ? (endCoord.x + endCoord.w) : (endCoord.x - gridWidth - widthDelta)) + dojo._docScroll().x, -100); // top
+			
+		var avaMoveStart = dojo.connect(coverMover, "onMoveStart", dojo.hitch(this, function(mover, leftTop){
+			this.mover = mover;
+			this.removeOtherMovers(mover.node.id);
+		}));
+		
+        var avaMove = dojo.connect(coverMover, "onMove", dojo.hitch(this, function(mover, leftTop, mousePos){
+			if(mover.node == null || mover.node.parentNode == null){
+				return;
+			}
+            this.isMoving = true;
+            this.moveRowBorder(mover, leftTop, borderDIV, mousePos);
+        }));
+		
+		var avaMoveStop = dojo.connect(coverMover, "onMoveStop", dojo.hitch(this,function(mover){
+			if(this.avaOnRowIndex == null || this.isContinuousSelection(this.grid.selection.selected) && (this.avaOnRowIndex == from || this.avaOnRowIndex == (to + 1))){
+			   	this.movingIgnored = true;
+				if(this.isMoving){
+					this.isMoving = false;
+					this.clearDrugDivs();
+				}
+				return; 
+			}			
+			this.isMoving = false;
+			this.mover = null;
+			this.grid.select.outRangeY = false;
+			this.grid.select.moveOutTop = false;
+			/*fix - blank Grid page when moving rows at bottom page, this only occurs the first time Grid get loaded*/		
+			this.grid.scroller.findScrollTop(this.grid.scroller.page * this.grid.scroller.rowsPerPage);
+			this.startMoveRows();
+			this.avaOnRowIndex = null;
+			delete coverMover;
+		}));
+		
+//		var avaKEY = dojo.connect(coverMover.node, "keydown",  dojo.hitch(this,function(e){
+//			var dk = dojo.keys;
+//			switch(e.keyCode){
+//				case dk.ESCAPE:
+//					try{
+//						this.cleanAll();
+//						this.clearDrugDivs();
+//						this.mover.destroy();
+//						this.cleanAll();
+//					}catch(e){
+//						console.debug(e);
+//					}
+//					break;
+//			}
+//		}));
+	},
+	
+	moveRowBorder: function(mover, leftTop, borderDIV, mousePos){
+		//summary:
+		//		move the border DIV to specified position when moving row
+		//mover: Object
+		//		the reference to the dnd mover
+		//leftTop: Object
+		//		the leftTop position of the mover
+		//borderDIV:Object
+		//		reference to the borderDIV
+		//mousePos: Object
+		//		the current position of the mover - {x:.., Y:..}	
+		var gridCoords = this.getGridCoords(true), docScroll = dojo._docScroll();
+		var gridBottomY = gridCoords.t + this.headerHeight + gridCoords.h
+		leftTop.t -= docScroll.y, mousePos.y -= docScroll.y;
+		if(mousePos.y >= gridBottomY){
+            this.grid.select.outRangeY = true;
+            this.autoMoveToNextRow();
+        }else if(mousePos.y <= gridCoords.t + this.headerHeight){
+        	this.grid.select.moveOutTop = true;
+            this.autoMoveToPreRow();
+		}else{
+            this.grid.select.outRangeY = this.grid.select.moveOutTop = false;
+			var rowBarView = this.grid.views.views[0], rowBarNodes = rowBarView.rowNodes;
+			var colHeight =  dojo.coords(rowBarView.contentNode).h;
+			var rowCount = 0, bottomRowIndex = -1;
+			for(i in rowBarNodes){
+				i = parseInt(i);
+				++rowCount;
+				if(i > bottomRowIndex){ bottomRowIndex = i; }
+			}
+			var bottomRowCoords = dojo.coords(rowBarNodes[bottomRowIndex]);
+			
+			if(colHeight < gridCoords.h && mousePos.y > (bottomRowCoords.y + bottomRowCoords.h)){
+				this.avaOnRowIndex = rowCount;
+				dojo.style(borderDIV, {"top" : bottomRowCoords.y + bottomRowCoords.h + docScroll.y + "px"});
+				return;
+			}
+			
+			var coord, rowBarNode, inView;
+			for(var index in rowBarNodes){
+				index = parseInt(index);
+				if(isNaN(index)){ continue; }
+				rowBarNode = rowBarNodes[index];
+				if(!rowBarNode){ continue; }
+				coord = dojo.coords(rowBarNode), inView = (coord.y <= gridBottomY);
+				if(inView && mousePos.y > coord.y && mousePos.y < coord.y + coord.h){
+					if(!this.grid.selection.selected[index] || !this.grid.selection.selected[index - 1]){
+						this.avaOnRowIndex = index;
+						dojo.style(borderDIV, {"top" : coord.y + docScroll.y + "px"});
+					}
+				}
+			}
+        }
+	},
+	
+	autoMoveToPreRow: function(){
+		//summary:
+		//		auto move the mover to the previous row of the current one
+		if(this.grid.select.moveOutTop){	
+			if(this.grid.scroller.firstVisibleRow > 0){
+				this.grid.scrollToRow(this.grid.scroller.firstVisibleRow - 1);
+				this.autoMoveBorderDivPre();
+				setTimeout(dojo.hitch(this, 'autoMoveToPreRow'), this.autoScrollRate);
+			}
+		}
+	},
+	
+	autoMoveBorderDivPre: function(){
+		//summary:
+		//		auto move the border DIV to the previous row of the current one
+		var docScroll = dojo._docScroll(), gridCoords = this.getGridCoords();
+		var viewTopY = gridCoords.t + this.headerHeight + docScroll.y;
+		var preRowY, borderDIV = this.getBorderDiv();
+		if(this.avaOnRowIndex - 1 <= 0){
+			this.avaOnRowIndex = 0;
+			preRowY = viewTopY;
+		}else{
+			this.avaOnRowIndex--;
+			preRowY = dojo.coords(this.grid.views.views[0].rowNodes[this.avaOnRowIndex]).y + docScroll.y;
+		}
+		borderDIV.style.top = (preRowY < viewTopY ? viewTopY : preRowY)+ "px";
+	},
+	
+	autoMoveToNextRow: function(){
+		//summary:
+		//		auto move the mover to the next row of the current one
+		if(this.grid.select.outRangeY){
+			if(this.avaOnRowIndex + 1 <= this.grid.scroller.rowCount){
+				this.grid.scrollToRow(this.grid.scroller.firstVisibleRow + 1);
+				this.autoMoveBorderDiv();
+				setTimeout(dojo.hitch(this, 'autoMoveToNextRow'), this.autoScrollRate);
+			}
+		}
+	},
+	
+	autoMoveBorderDiv: function(){
+		//Summary:
+		//		auto move the drop indicator to the next row when avatar is moved out of the grid bottom
+		var docScroll = dojo._docScroll(), gridCoords = this.getGridCoords();
+		var viewBottomY = gridCoords.t + this.headerHeight + gridCoords.h + docScroll.y;
+		var nextRowY, borderDIV = this.getBorderDiv();
+		if(this.avaOnRowIndex + 1 >= this.grid.scroller.rowCount){
+			this.avaOnRowIndex = this.grid.scroller.rowCount;
+			nextRowY = viewBottomY;
+		}else{
+			this.avaOnRowIndex++;
+			nextRowY = dojo.coords(this.grid.views.views[0].rowNodes[this.avaOnRowIndex]).y + docScroll.y;
+		}
+		borderDIV.style.top = (nextRowY > viewBottomY ? viewBottomY : nextRowY) + "px";
+	},
+	
+	startMoveRows: function(){
+		//summary:
+		//		start to move the selected rows to target position
+		var start = Math.min(this.avaOnRowIndex, this.getFirstSelected());
+		var end = Math.max(this.avaOnRowIndex - 1, this.getLastSelected());
+		this.moveRows(start, end, this.getPageInfo());
+	},
+	
+	moveRows: function(start, end, pageInfo){
+		//summary:
+		//		Only move visible rows to avoid performance issue especially 
+		//		when there are many disperse selected rows across not-rendered pages
+		//start:Integer
+		//		the first row of the selected area to move
+		//end:Integer
+		//		the first row of the selected area to move deltaRowAmount
+		//pageInfo:Object
+		//		{topPage: xx, bottomPage: xx, invalidPages: [xx,xx,...]}
+		var i, rowMoved = false, selectedRows = (selectedRowsAboveBorderDIV = 0), tempArray = [];//all rows to be updated
+		var scroller = this.grid.scroller, rowsPerPage = scroller.rowsPerPage;
+		var topRow = pageInfo.topPage * rowsPerPage, bottomRow = (pageInfo.bottomPage + 1) * rowsPerPage - 1;
+		
+		var pushUnselectedRows = dojo.hitch(this, function(from, to){
+			for(i = from; i < to; i++){
+				if(!this.grid.selection.selected[i] || !this.grid._by_idx[i]){
+					tempArray.push(this.grid._by_idx[i]);
+				}
+			}
+		});
+		
+		//push unselected rows above borderDIV to temp array
+		pushUnselectedRows(start, this.avaOnRowIndex);
+		
+		//push selected rows to temp array
+		for(i = start; i <= end; i++){
+			if(this.grid.selection.selected[i] && this.grid._by_idx[i]){
+				tempArray.push(this.grid._by_idx[i]);
+				selectedRows++;
+				if(this.avaOnRowIndex > i){ selectedRowsAboveBorderDIV++; } 
+			}
+		}
+		
+		//push unselected rows below borderDIV to temp array
+		pushUnselectedRows(this.avaOnRowIndex, end + 1);
+		
+		//update changed region
+		for(i = start, j = 0; i <= end; i++){
+			this.grid._by_idx[i] = tempArray[j++];
+			if(i >= topRow && i <= bottomRow){
+				this.grid.updateRow(i);
+				rowMoved = true;
+			}
+		}
+		this.avaOnRowIndex += selectedRows - selectedRowsAboveBorderDIV;
+		try{
+			this.clearDrugDivs();
+			this.cleanAll();
+			this.drugSelectionStart.rowIndex = this.avaOnRowIndex - selectedRows;
+			this.drugSelectRow(this.drugSelectionStart.rowIndex +  selectedRows - 1);
+			if(rowMoved){
+				var stack = scroller.stack;
+				dojo.forEach(pageInfo.invalidPages, function(pageIndex){
+					scroller.destroyPage(pageIndex);
+					i = dojo.indexOf(stack, pageIndex);
+					if(i >= 0){
+						stack.splice(i, 1);
+					}
+				});			
+			}
+			this.publishRowMove();
+		}catch(e){
+			console.debug(e);
+		}
+	},
+	
+	clearDrugDivs: function(){
+		//summary:
+		//		remove cover DIVs for dnd moving
+		if(!this.isMoving){ 
+			var borderDIV = this.getBorderDiv();
+	        borderDIV.style.top = -100 + "px";
+			borderDIV.style.height = "0px";
+			borderDIV.style.left = -100 + "px";
+			
+	        dojo.forEach(this.coverDIVs, function(div){
+				//console.debug("del id=" + div.id);
+				dojo.forEach(div.connections, function(connection){
+					dojo.disconnect(connection);
+				});
+	            dojo.doc.body.removeChild(div);
+				delete div;
+	        }, this);
+	        this.coverDIVs = [];
+		}
+	},	
+	
+	setDrugCoverDivs: function(inColIndex, inRowIndex){
+		// Summary:
+		//		set the cover divs for DND
+		if(!this.isMoving){
+			if(this.isColSelected(inColIndex)){
+				this.addColMovers();
+			}else if( this.grid.selection.selected[inRowIndex]){
+				this.addRowMovers();
+			}else{
+				this.clearDrugDivs();
+			}
+		}
+	},
+	
+	getPageInfo: function(){
+		//summary:
+		//		Find pages that contain visible rows
+		//return: Object
+		//		{topPage: xx, bottomPage: xx, invalidPages: [xx,xx,...]}
+		var scroller = this.grid.scroller, topPage = (bottomPage = scroller.page);
+		var firstVisibleRow = scroller.firstVisibleRow, lastVisibleRow = scroller.lastVisibleRow;
+		var rowsPerPage = scroller.rowsPerPage, renderedPages = scroller.pageNodes[0];		
+		var topRow, bottomRow, invalidPages = [], matched;
+		
+		dojo.forEach(renderedPages, function(page, pageIndex){
+			if(!page){ return; }
+			matched = false;
+			topRow = pageIndex * rowsPerPage;
+			bottomRow = (pageIndex + 1) * rowsPerPage - 1;
+			if(firstVisibleRow >= topRow && firstVisibleRow <= bottomRow){
+				topPage = pageIndex;
+				matched = true;
+			}
+			if(lastVisibleRow >= topRow && lastVisibleRow <= bottomRow){
+				bottomPage = pageIndex;
+				matched = true;
+			}
+			if(!matched && (topRow > lastVisibleRow || bottomRow < firstVisibleRow)){
+				invalidPages.push(pageIndex);				
+			}
+		});
+		return {topPage: topPage, bottomPage: bottomPage, invalidPages: invalidPages};
+	},
+	
+	resetCellIdx: function(){
+		// Summary:
+		//			reset the 'idx' attributes of cells' DOM node and structures
+		var lastMax = 0;
+		var thisMax = -1;
+		dojo.forEach(this.grid.views.views, function(view, index){
+			if(index == 0){
+				return;
+			}
+			if(view.structure.cells && view.structure.cells[0]){
+				dojo.forEach(view.structure.cells[0], function(cell, index){
+					var marks = cell.markup[2].split(" ");
+					var idx = lastMax + index;
+					marks[1] = "idx=\"" + idx + "\"";
+					cell.markup[2] = marks.join(" ");
+				});
+			}
+			for(i in view.rowNodes){
+				if(!view.rowNodes[i]){ return;/* row not loaded */}
+				dojo.forEach(view.rowNodes[i].firstChild.rows[0].cells, function(cell, cellIndex){
+					if(cell && cell.attributes ){
+						if(cellIndex + lastMax > thisMax){
+							thisMax = cellIndex + lastMax;
+						}
+						var idx = document.createAttribute("idx");
+						idx.value = cellIndex + lastMax;
+						cell.attributes.setNamedItem(idx);
+					}
+				});
+			}
+			lastMax = thisMax + 1;
+		});
+	},
+	
+	publishRowMove: function(){
+		//summary:
+		//		publish a topic to notify the row movement
+		dojo.publish(this.grid.rowMovedTopic, [this]);
+	},
+	
+	keyboardMove: function(keyEvent){
+		//summary:
+		//		handle keyboard dnd
+		var inColSelection = this.selectedColumns.length > 0;
+		var inRowSelection = dojo.hitch(this.grid.selection, dojox.grid.Selection.prototype['getFirstSelected'])() >= 0;
+		var i, colAmount, dk = dojo.keys, keyCode = keyEvent.keyCode;
+		if(!dojo._isBodyLtr()){
+			keyCode = (keyEvent.keyCode == dk.LEFT_ARROW) ? dk.RIGHT_ARROW : (keyEvent.keyCode == dk.RIGHT_ARROW ? dk.LEFT_ARROW : keyCode);
+		}
+		switch(keyCode){
+			case dk.LEFT_ARROW:
+				if(!inColSelection){return;}
+				colAmount = this.getHeaderNodes().length;
+				for(i = 0; i < colAmount; i++){
+					if(this.isColSelected(i)){
+						this.drugDestIndex = i - 1;
+						this.drugBefore = true;
+						break;
+					}
+				}
+				var minBoundary = this.grid.indirectSelection ? 1 : 0;
+				(this.drugDestIndex >= minBoundary) ? this.startMoveCols() : (this.drugDestIndex = minBoundary);
+			break;
+			case dk.RIGHT_ARROW:
+				if(!inColSelection){return;}
+				colAmount = this.getHeaderNodes().length;
+				this.drugBefore = true;
+				for(i = 0; i < colAmount; i++){
+					if(this.isColSelected(i) && !this.isColSelected(i + 1)){
+						this.drugDestIndex = i + 2;
+						if(this.drugDestIndex == colAmount){
+							this.drugDestIndex--;
+							this.drugBefore = false;
+						}
+						break;
+					}
+				}
+				if(this.drugDestIndex < colAmount){
+					this.startMoveCols();
+				}
+			break;
+			case dk.UP_ARROW:
+				if(!inRowSelection){return;}
+				this.avaOnRowIndex = dojo.hitch(this.grid.selection, dojox.grid.Selection.prototype['getFirstSelected'])() - 1;
+				if(this.avaOnRowIndex > -1){
+					this.startMoveRows();
+				}
+			break;
+			case dk.DOWN_ARROW:
+				if(!inRowSelection){return;}
+				for(i = 0; i < this.grid.rowCount; i++){
+					if(this.grid.selection.selected[i] && !this.grid.selection.selected[i + 1]){
+						this.avaOnRowIndex = i + 2;
+						break;
+					}
+				}
+				if(this.avaOnRowIndex <= this.grid.rowCount){
+					this.startMoveRows();
+				}
+		}
+	}
 });
-},publishRowMove:function(){
-dojo.publish(this.grid.rowMovedTopic,[this]);
-},keyboardMove:function(_cc){
-var _cd=this.selectedColumns.length>0;
-var _ce=dojo.hitch(this.grid.selection,dojox.grid.Selection.prototype["getFirstSelected"])()>=0;
-var i,_cf,dk=dojo.keys,_d0=_cc.keyCode;
-if(!dojo._isBodyLtr()){
-_d0=(_cc.keyCode==dk.LEFT_ARROW)?dk.RIGHT_ARROW:(_cc.keyCode==dk.RIGHT_ARROW?dk.LEFT_ARROW:_d0);
-}
-switch(_d0){
-case dk.LEFT_ARROW:
-if(!_cd){
-return;
-}
-_cf=this.getHeaderNodes().length;
-for(i=0;i<_cf;i++){
-if(this.isColSelected(i)){
-this.drugDestIndex=i-1;
-this.drugBefore=true;
-break;
-}
-}
-var _d1=this.grid.indirectSelection?1:0;
-(this.drugDestIndex>=_d1)?this.startMoveCols():(this.drugDestIndex=_d1);
-break;
-case dk.RIGHT_ARROW:
-if(!_cd){
-return;
-}
-_cf=this.getHeaderNodes().length;
-this.drugBefore=true;
-for(i=0;i<_cf;i++){
-if(this.isColSelected(i)&&!this.isColSelected(i+1)){
-this.drugDestIndex=i+2;
-if(this.drugDestIndex==_cf){
-this.drugDestIndex--;
-this.drugBefore=false;
-}
-break;
-}
-}
-if(this.drugDestIndex<_cf){
-this.startMoveCols();
-}
-break;
-case dk.UP_ARROW:
-if(!_ce){
-return;
-}
-this.avaOnRowIndex=dojo.hitch(this.grid.selection,dojox.grid.Selection.prototype["getFirstSelected"])()-1;
-if(this.avaOnRowIndex>-1){
-this.startMoveRows();
-}
-break;
-case dk.DOWN_ARROW:
-if(!_ce){
-return;
-}
-for(i=0;i<this.grid.rowCount;i++){
-if(this.grid.selection.selected[i]&&!this.grid.selection.selected[i+1]){
-this.avaOnRowIndex=i+2;
-break;
-}
-}
-if(this.avaOnRowIndex<=this.grid.rowCount){
-this.startMoveRows();
-}
-}
-}});
-}
diff --git a/dojox/grid/enhanced/dnd/_DndRowSelector.js b/dojox/grid/enhanced/dnd/_DndRowSelector.js
index 7966977..5511381 100644
--- a/dojox/grid/enhanced/dnd/_DndRowSelector.js
+++ b/dojox/grid/enhanced/dnd/_DndRowSelector.js
@@ -1,18 +1,30 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.enhanced.dnd._DndRowSelector"]){
-dojo._hasResource["dojox.grid.enhanced.dnd._DndRowSelector"]=true;
 dojo.provide("dojox.grid.enhanced.dnd._DndRowSelector");
-dojo.declare("dojox.grid.enhanced.dnd._DndRowSelector",null,{domousedown:function(e){
-this.grid.onMouseDown(e);
-},domouseup:function(e){
-this.grid.onMouseUp(e);
-},dofocus:function(e){
-e.cellNode.style.border="solid 1px";
-}});
-}
+dojo.declare("dojox.grid.enhanced.dnd._DndRowSelector", null, {
+	//summary:
+	//		This class declaration is used to be mixed in to dojox.grid._RowSelector
+	//		to enable DND feature in _RowSelector.
+
+	domousedown: function(e){
+	//summary:
+	//		Handle when there is a mouse down event 
+	//e: Event
+	//		The mouse down event
+		this.grid.onMouseDown(e);
+	},
+	
+	domouseup: function(e){
+	//summary:
+	//		Handle when there is a mouse up event 
+	//e: Event
+	//		The mouse up event
+		this.grid.onMouseUp(e);
+	},
+	
+	dofocus:function(e){
+	//summary:
+	//		Handle when there is a focus event 
+	//e: Event
+	//		The focus event
+		e.cellNode.style.border = "solid 1px";
+	}
+});
diff --git a/dojox/grid/enhanced/dnd/_DndSelectingManager.js b/dojox/grid/enhanced/dnd/_DndSelectingManager.js
index 18a72cf..b81b08d 100644
--- a/dojox/grid/enhanced/dnd/_DndSelectingManager.js
+++ b/dojox/grid/enhanced/dnd/_DndSelectingManager.js
@@ -1,371 +1,735 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.enhanced.dnd._DndSelectingManager"]){
-dojo._hasResource["dojox.grid.enhanced.dnd._DndSelectingManager"]=true;
 dojo.provide("dojox.grid.enhanced.dnd._DndSelectingManager");
+
 dojo.require("dojox.grid.util");
 dojo.require("dojox.grid._Builder");
 dojo.require("dojox.grid.enhanced.dnd._DndGrid");
 dojo.require("dojox.grid.enhanced.dnd._DndBuilder");
 dojo.require("dojox.grid.enhanced.dnd._DndRowSelector");
 dojo.require("dojox.grid.enhanced.dnd._DndFocusManager");
-dojo.declare("dojox.grid.enhanced.dnd._DndSelectingManager",null,{typeSelectingMode:[],selectingDisabledTypes:[],drugSelectionStart:null,drugCurrentPoint:null,drugMode:null,keepState:false,extendSelect:false,headerNodes:null,selectedCells:null,selectedColumns:[],selectedClass:"dojoxGridRowSelected",autoScrollRate:1000,constructor:function(_1){
-this.grid=_1;
-this.typeSelectingMode=[];
-this.selectingDisabledTypes=[];
-this.selectedColumns=[];
-this.drugSelectionStart=new Object();
-this.drugCurrentPoint=new Object();
-this.resetStartPoint();
-this.extendGridForDnd(_1);
-this.selectedCells=[];
-dojo.connect(this.grid,"_onFetchComplete",dojo.hitch(this,"refreshColumnSelection"));
-dojo.connect(this.grid.scroller,"scroll",dojo.hitch(this,"refreshColumnSelection"));
-dojo.subscribe(this.grid.rowSelectionChangedTopic,dojo.hitch(this,function(_2){
-try{
-if(_2.grid==this.grid&&_2!=this){
-this.cleanCellSelection();
-}
-}
-catch(e){
-}
-}));
-},extendGridForDnd:function(_3){
-var _4=_3.constructor;
-_3.mixin(_3,dojo.hitch(new dojox.grid.enhanced.dnd._DndGrid(this)));
-_3.constructor=_4;
-_3.mixin(_3.focus,new dojox.grid.enhanced.dnd._DndFocusManager());
-_3.mixin(_3.selection,{clickSelect:function(){
-}});
-dojo.forEach(_3.views.views,function(_5){
-_3.mixin(_5.content,new dojox.grid.enhanced.dnd._DndBuilder());
-_3.mixin(_5.header,new dojox.grid.enhanced.dnd._DndHeaderBuilder());
-if(_5.declaredClass=="dojox.grid._RowSelector"){
-_3.mixin(_5,new dojox.grid.enhanced.dnd._DndRowSelector());
-}
-dojox.grid.util.funnelEvents(_5.contentNode,_5,"doContentEvent",["mouseup"]);
-dojox.grid.util.funnelEvents(_5.headerNode,_5,"doHeaderEvent",["mouseup"]);
-});
-dojo.forEach(this.grid.dndDisabledTypes,function(_6){
-this.disableSelecting(_6);
-},this);
-this.disableFeatures();
-},disableFeatures:function(){
-if(this.selectingDisabledTypes["cell"]){
-this.cellClick=function(){
-};
-this.drugSelectCell=function(){
-};
-}
-if(this.selectingDisabledTypes["row"]){
-this.drugSelectRow=function(){
-};
-}
-if(this.selectingDisabledTypes["col"]){
-this.selectColumn=function(){
-};
-this.drugSelectColumn=function(){
-};
-}
-},disableSelecting:function(_7){
-this.selectingDisabledTypes[_7]=true;
-},isInSelectingMode:function(_8){
-return !!this.typeSelectingMode[_8];
-},setInSelectingMode:function(_9,_a){
-this.typeSelectingMode[_9]=_a;
-},getSelectedRegionInfo:function(){
-var _b=[],_c="";
-if(this.selectedColumns.length>0){
-_c="col";
-dojo.forEach(this.selectedColumns,function(_d,_e){
-!!_d&&_b.push(_e);
-});
-}else{
-if(this.grid.selection.getSelectedCount()>0){
-_c="row";
-_b=dojox.grid.Selection.prototype.getSelected.call(this.grid.selection);
-}
-}
-return {"selectionType":_c,"selectedIdx":_b};
-},clearInSelectingMode:function(){
-this.typeSelectingMode=[];
-},getHeaderNodes:function(){
-return this.headerNodes==null?dojo.query("[role*='columnheader']",this.grid.viewsHeaderNode):this.headerNode;
-},_range:function(_f,_10,_11){
-var s=(_f>=0?_f:_10),e=_10;
-if(s>e){
-e=s;
-s=_10;
-}
-for(var i=s;i<=e;i++){
-_11(i);
-}
-},cellClick:function(_12,_13){
-if(_12>this.exceptColumnsTo){
-this.grid.selection.clear();
-this.publishRowChange();
-var _14=this.getCellNode(_12,_13);
-this.cleanAll();
-this.addCellToSelection(_14);
-}
-},setDrugStartPoint:function(_15,_16){
-this.drugSelectionStart.colIndex=_15;
-this.drugSelectionStart.rowIndex=_16;
-this.drugCurrentPoint.colIndex=_15;
-this.firstOut=true;
-var _17=dojo.connect(dojo.doc,"onmousemove",dojo.hitch(this,function(e){
-this.outRangeValue=e.clientY-dojo.coords(this.grid.domNode).y-this.grid.domNode.offsetHeight;
-if(this.outRangeValue>0){
-if(this.drugSelectionStart.colIndex==-1){
-if(!this.outRangeY){
-this.autoRowScrollDrug(e);
-}
-}else{
-if(this.drugSelectionStart.rowIndex==-1){
-}else{
-this.autoCellScrollDrug(e);
-}
-}
-}else{
-this.firstOut=true;
-this.outRangeY=false;
-}
-}));
-var _18=dojo.connect(dojo.doc,"onmouseup",dojo.hitch(this,function(e){
-this.outRangeY=false;
-dojo.disconnect(_18);
-dojo.disconnect(_17);
-this.grid.onMouseUp(e);
-}));
-},autoRowScrollDrug:function(e){
-this.outRangeY=true;
-this.autoSelectNextRow();
-},autoSelectNextRow:function(){
-if(this.grid.select.outRangeY){
-this.grid.scrollToRow(this.grid.scroller.firstVisibleRow+1);
-this.drugSelectRow(this.drugCurrentPoint.rowIndex+1);
-setTimeout(dojo.hitch(this,"autoSelectNextRow",this.drugCurrentPoint.rowIndex+1),this.getAutoScrollRate());
-}
-},autoCellScrollDrug:function(e){
-var _19=null;
-dojo.forEach(this.getHeaderNodes(),function(_1a){
-var _1b=dojo.coords(_1a);
-if(e.clientX>=_1b.x&&e.clientX<=_1b.x+_1b.w){
-_19=Number(_1a.attributes.getNamedItem("idx").value);
-}
-});
-if(_19!=this.drugCurrentPoint.colIndex||this.firstOut){
-if(!this.firstOut){
-this.colChanged=true;
-this.drugCurrentPoint.colIndex=_19;
-}
-this.firstOut=false;
-this.outRangeY=true;
-dojo.hitch(this,"autoSelectCellInNextRow")();
-}
-},autoSelectCellInNextRow:function(){
-if(this.grid.select.outRangeY){
-this.grid.scrollToRow(this.grid.scroller.firstVisibleRow+1);
-this.drugSelectCell(this.drugCurrentPoint.colIndex,this.drugCurrentPoint.rowIndex+1);
-if(this.grid.select.colChanged){
-this.grid.select.colChanged=false;
-}else{
-setTimeout(dojo.hitch(this,"autoSelectCellInNextRow",this.drugCurrentPoint.rowIndex+1),this.getAutoScrollRate());
-}
-}
-},getAutoScrollRate:function(){
-return this.autoScrollRate;
-},resetStartPoint:function(){
-if(this.drugSelectionStart.colIndex==-1&&this.drugSelectionStart.rowIndex==-1){
-return;
-}
-this.lastDrugSelectionStart=dojo.clone(this.drugSelectionStart);
-this.drugSelectionStart.colIndex=-1;
-this.drugSelectionStart.rowIndex=-1;
-},restorLastDragPoint:function(){
-this.drugSelectionStart=dojo.clone(this.lastDrugSelectionStart);
-},drugSelectCell:function(_1c,_1d){
-this.cleanAll();
-this.drugCurrentPoint.columnIndex=_1c;
-this.drugCurrentPoint.rowIndex=_1d;
-var _1e,_1f,_20,_21;
-if(_1d<this.drugSelectionStart.rowIndex){
-_1e=_1d;
-_1f=this.drugSelectionStart.rowIndex;
-}else{
-_1e=this.drugSelectionStart.rowIndex;
-_1f=_1d;
-}
-if(_1c<this.drugSelectionStart.colIndex){
-_20=_1c;
-_21=this.drugSelectionStart.colIndex;
-}else{
-_20=this.drugSelectionStart.colIndex;
-_21=_1c;
-}
-for(var i=_20;i<=_21;i++){
-this.addColumnRangeToSelection(i,_1e,_1f);
-}
-},selectColumn:function(_22){
-this.addColumnToSelection(_22);
-},drugSelectColumn:function(_23){
-this.selectColumnRange(this.drugSelectionStart.colIndex,_23);
-},drugSelectColumnToMax:function(dir){
-if(dir=="left"){
-this.selectColumnRange(this.drugSelectionStart.colIndex,0);
-}else{
-this.selectColumnRange(this.drugSelectionStart.colIndex,this.getHeaderNodes().length-1);
-}
-},selectColumnRange:function(_24,_25){
-if(!this.keepState){
-this.cleanAll();
-}
-this._range(_24,_25,dojo.hitch(this,"addColumnToSelection"));
-},addColumnToSelection:function(_26){
-this.selectedColumns[_26]=true;
-dojo.toggleClass(this.getHeaderNodes()[_26],"dojoxGridHeaderSelected",true);
-this._rangCellsInColumn(_26,-1,Number.POSITIVE_INFINITY,this.addCellToSelection);
-},addColumnRangeToSelection:function(_27,_28,to){
-var _29=this.grid.views;
-var _2a=[];
-var _2b=this;
-dojo.forEach(_29.views,function(_2c){
-dojo.forEach(this.getViewRowNodes(_2c.rowNodes),function(_2d,_2e){
-if(!_2d){
-return;
-}
-if(_2e>=_28&&_2e<=to){
-dojo.forEach(_2d.firstChild.rows[0].cells,function(_2f){
-if(_2f&&_2f.attributes&&(idx=_2f.attributes.getNamedItem("idx"))&&Number(idx.value)==_27){
-_2b.addCellToSelection(_2f);
-}
-});
-}
-},this);
-},this);
-},_rangCellsInColumn:function(_30,_31,to,_32){
-var _33=this.grid.views;
-var _34=[];
-var _35=this;
-dojo.forEach(_33.views,function(_36){
-dojo.forEach(this.getViewRowNodes(_36.rowNodes),function(_37,_38){
-if(!_37){
-return;
-}
-if(_38>=_31&&_38<=to){
-dojo.forEach(_37.firstChild.rows[0].cells,function(_39){
-if(_39&&_39.attributes&&(idx=_39.attributes.getNamedItem("idx"))&&Number(idx.value)==_30){
-_32(_39,_35);
-}
+dojo.declare("dojox.grid.enhanced.dnd._DndSelectingManager", null, {
+	//summary:
+	//		_DndSelectingManager is used to enable grid DND selecting feature
+	//		
+	
+	// list, each item record whether the type is in selecting mode
+	// type: row, cell, col
+	typeSelectingMode: [],
+	
+	// list, each item record whether the type selecting is disabled
+	// type: row, cell, col
+	selectingDisabledTypes:[],
+	
+	// The start point of drag selection
+	drugSelectionStart: null,
+	
+	// The point that fire drug select
+	drugCurrentPoint : null,
+	
+	// Should be col, row or cell
+	drugMode: null,
+	
+	// If user drag select with ctrl key down
+	// selected cells should be kept state as selected
+	keepState: false,
+	
+	extendSelect: false,
+	
+	// keep the dom nodes of header in a list
+	headerNodes: null,
+	
+	// Record the selected cells
+	selectedCells : null,
+	
+	// Record the columns selected
+	selectedColumns : [],
+	
+	// Record the rows selected
+    //selectedRows : [],
+	
+	selectedClass: "dojoxGridRowSelected",
+	
+	autoScrollRate: 1000,
+	
+	constructor: function(inGrid){
+		// inGrid: dojox.Grid
+		//		The dojox.Grid this editor should be attached to
+		this.grid = inGrid;
+		this.typeSelectingMode = [];
+		this.selectingDisabledTypes = [];
+		this.selectedColumns = [];
+		
+		// Init the dnd selection start point
+		this.drugSelectionStart = new Object();
+		this.drugCurrentPoint = new Object();
+		this.resetStartPoint();
+		
+		this.extendGridForDnd(inGrid);
+		
+		this.selectedCells = [];
+		
+		dojo.connect(this.grid, "_onFetchComplete",dojo.hitch(this, "refreshColumnSelection"));
+		dojo.connect(this.grid.scroller, "scroll",dojo.hitch(this, "refreshColumnSelection"));
+		//dojo.connect(document, 'onmousedown', this.grid.focus, '_blurRowBar');
+		
+		dojo.subscribe(this.grid.rowSelectionChangedTopic, dojo.hitch(this,function(publisher){
+			try{
+				if(publisher.grid == this.grid && publisher != this){
+					this.cleanCellSelection();
+				}
+			}catch(e){
+				console.debug(e);
+			}
+		}));
+	},
+	
+	extendGridForDnd: function(inGrid){
+		//summary:
+		//       Ectend the current class to enable the DND feature
+		//		 inclucing:
+		//				dojox.Grid
+		//				dojox._FocusManager
+		//				dojox.Selection
+		//				dojox._Builder
+		//				dojox._HeaderBuilder
+		//				dojox._RowSelector
+		//		 Change the funnelEvents of views, add mouseup and mouseover event
+		
+		//extend dojox.Grid
+		var _ctr = inGrid.constructor;
+		inGrid.mixin(inGrid, dojo.hitch(new dojox.grid.enhanced.dnd._DndGrid(this)));
+		inGrid.constructor = _ctr;
+		
+		// workaround for mixin related issues
+		//inGrid.constructor.prototype.startup = inGrid.startup;
+		//inGrid.constructor.prototype.onStyleRow = inGrid.onStyleRow;
+		
+		//extend dojox._FocusManager
+		inGrid.mixin(inGrid.focus, new dojox.grid.enhanced.dnd._DndFocusManager());
+		
+		// rewrite the clickSelect function of Selection
+		inGrid.mixin(inGrid.selection, {clickSelect:function(){}});
+		
+		dojo.forEach(inGrid.views.views, function(view){
+			//extend dojox._Builder
+			inGrid.mixin(view.content, new dojox.grid.enhanced.dnd._DndBuilder());
+			//extend dojox._HeaderBuilder
+			inGrid.mixin(view.header, new dojox.grid.enhanced.dnd._DndHeaderBuilder());
+			if(view.declaredClass =="dojox.grid._RowSelector"){
+				//extend dojox._RowSelector
+				inGrid.mixin(view, new dojox.grid.enhanced.dnd._DndRowSelector());
+			}
+			// Change the funnelEvents of views, add mouseup and mouseover event
+			//dojox.grid.util.funnelEvents(view.contentNode, view, "doContentEvent", [ 'mouseup','mouseover', 'mouseout', 'click', 'dblclick', 'contextmenu', 'mousedown' ]);
+			dojox.grid.util.funnelEvents(view.contentNode, view, "doContentEvent", [ 'mouseup']);
+			//dojox.grid.util.funnelEvents(view.headerNode, view, "doHeaderEvent", [ 'dblclick','mouseup', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'click', 'contextmenu' ]);
+			dojox.grid.util.funnelEvents(view.headerNode, view, "doHeaderEvent", ['mouseup']);
+
+		});
+		dojo.forEach(this.grid.dndDisabledTypes, function(type){
+			this.disableSelecting(type);
+		}, this);
+		this.disableFeatures();
+	},
+	
+	disableFeatures: function(){
+		//summary:
+		//		disable selecting features according to the configuration
+		if(this.selectingDisabledTypes["cell"]){
+			this.cellClick = function(){/*console.debug("_DndSelectingManager.cellClick is disabled");*/};
+			this.drugSelectCell = function(){/*console.debug("_DndSelectingManager.drugSelectCell is disabled");*/};
+		}
+		if(this.selectingDisabledTypes["row"]){
+			this.drugSelectRow = function(){/*console.debug("_DndSelectingManager.drugSelectRow is disabled");*/};
+		}
+		if(this.selectingDisabledTypes["col"]){
+			this.selectColumn = function(){/*console.debug("_DndSelectingManager.selectColumn is disabled");*/};
+			this.drugSelectColumn = function(){/*console.debug("_DndSelectingManager.drugSelectColumn is disabled");*/};
+		}
+	},
+	
+	disableSelecting: function(type){
+		//summary:
+		//		set selecting feature of 'type' disabled in the disabled feature list
+		//type: Sting
+		//		the feature that will be disabled, should be 'cell', 'row', or 'col'
+		this.selectingDisabledTypes[type] = true;
+	},
+	
+	isInSelectingMode: function(type){
+		//summary:
+		//		whether the selecting manager is in 'type' selecting mode
+		//type: String
+		//		the selecting mode type
+		//return: Boolean
+		//		whether the selecting manager is in 'type' selecting mode
+		return !!this.typeSelectingMode[type];
+	},
+	
+	setInSelectingMode: function(type, isEnable){
+		//summary:
+		//		set the selecting manager to 'type' selecting mode
+		//type: String
+		//		the selecting mode will be set, should be 'cell', 'row', or 'col'
+		//isEnable: Boolean
+		//		the 'type' selecting mode is 'isEnable'ed
+		this.typeSelectingMode[type] = isEnable;
+	},
+	
+	getSelectedRegionInfo: function(){
+		//summary:
+		//		Get the selected region info
+		//return: Array
+		//		Array of selected index, might be index of rows | columns | cells
+		var selectedIdx = [], type = '';
+		if(this.selectedColumns.length > 0){
+			type = 'col';
+			dojo.forEach(this.selectedColumns, function(item, index){
+				!!item && selectedIdx.push(index);
+			});
+		}else if(this.grid.selection.getSelectedCount() > 0){
+			type = 'row';
+			selectedIdx = dojox.grid.Selection.prototype.getSelected.call(this.grid.selection);
+		}
+		return {'selectionType': type, 'selectedIdx': selectedIdx};
+		//TODO for future cells
+	},
+	
+	clearInSelectingMode: function(){
+		//summary:
+		//		clear all selecting mode
+		this.typeSelectingMode = [];
+	},
+	
+	getHeaderNodes: function(){
+		//summary:
+		//       Util function 
+		//		 Get  the header nodes list of the grid
+		// return:
+		//		 the header nodes list of the grid 
+		return this.headerNodes == null? dojo.query("[role*='columnheader']", this.grid.viewsHeaderNode) : this.headerNode;
+	},
+
+	_range: function(inFrom, inTo, func){
+		//summary:
+		// 		fire a function for each item in a range
+		var s = (inFrom >= 0 ? inFrom : inTo), e = inTo;
+		if(s > e){
+			e = s;
+			s = inTo;
+		}
+		for(var i=s; i<=e; i++){
+			func(i);
+		}
+	},
+	
+	cellClick: function(inColIndex, inRowIndex){
+		//summary:
+		// 		handle the click event on cell, select the cell call this.addCellToSelection
+		// inColIndex: Integer
+		//		the Y position  of the cell that fired the click event
+		// inRowIndex: Integer
+		//		the Y position of the cell that fired the click event
+		if(inColIndex > this.exceptColumnsTo){
+			this.grid.selection.clear();
+			this.publishRowChange();
+			var cellNode = this.getCellNode(inColIndex, inRowIndex);
+			this.cleanAll();
+			this.addCellToSelection(cellNode);
+		}
+	},
+	
+	setDrugStartPoint: function(inColIndex, inRowIndex){
+		//summary:
+		//		set drug selecting start point
+		//		also add mouse move and mouse up handler on the whole window to monitor whether the mouse move out of the grid when druging
+		// inColIndex: Integer
+		//			column index of the point
+		//inRowIndex: Integer
+		//			row index of the point
+		this.drugSelectionStart.colIndex = inColIndex;
+		this.drugSelectionStart.rowIndex = inRowIndex;
+		this.drugCurrentPoint.colIndex = inColIndex;
+		this.firstOut = true;
+		
+		// monitor mouse move
+		// when move out the grid bottom, auto scroll the grid
+		var moveHandler = dojo.connect(dojo.doc, "onmousemove", dojo.hitch(this, function(e){
+			this.outRangeValue = e.clientY - dojo.coords(this.grid.domNode).y/*this.grid.domNode.offsetTop*/ - this.grid.domNode.offsetHeight;
+			if(this.outRangeValue > 0){
+				if(this.drugSelectionStart.colIndex == -1){
+					if(!this.outRangeY){
+						this.autoRowScrollDrug(e);
+					}
+				}else if(this.drugSelectionStart.rowIndex == -1){
+					//...
+				}else {
+					this.autoCellScrollDrug(e);
+				}
+			}else {
+				this.firstOut = true;
+				this.outRangeY = false;
+			}
+		}));
+		// monitor the mouse up event
+		// when mouse up during drug selecting, stop the auto scroll and clean the handlers
+		var upHandler = dojo.connect(dojo.doc, "onmouseup", dojo.hitch(this, function(e){
+			this.outRangeY = false;
+			dojo.disconnect(upHandler);
+			dojo.disconnect(moveHandler);
+			this.grid.onMouseUp(e);
+		}));
+		
+	}, 
+	
+	autoRowScrollDrug: function(e){
+		//summary:
+		//		start auto scroll and select the next row
+		this.outRangeY = true;
+		this.autoSelectNextRow();
+	},
+	
+	autoSelectNextRow: function(){
+		//summary:
+		//		auto scroll the grid to next row and select the row
+		if(this.grid.select.outRangeY ){			
+			this.grid.scrollToRow(this.grid.scroller.firstVisibleRow + 1);
+			this.drugSelectRow(this.drugCurrentPoint.rowIndex + 1);
+			setTimeout(dojo.hitch(this, 'autoSelectNextRow', this.drugCurrentPoint.rowIndex + 1), this.getAutoScrollRate());
+		}
+	},
+	
+	autoCellScrollDrug: function(e){
+		//summary:
+		// 		start auto scroll the grid to next row
+		//		reset the selected column range when mouse move to another column
+		var mouseOnCol = null;
+		dojo.forEach(this.getHeaderNodes(), function(node){
+			var coord = dojo.coords(node);
+			if(e.clientX >= coord.x && e.clientX <=coord.x+coord.w){
+				mouseOnCol = Number(node.attributes.getNamedItem("idx").value);
+			}
+		});
+		if(mouseOnCol != this.drugCurrentPoint.colIndex || this.firstOut){
+			if(!this.firstOut){
+				this.colChanged = true;
+				this.drugCurrentPoint.colIndex = mouseOnCol;
+			}
+			this.firstOut = false;
+			this.outRangeY = true;
+			dojo.hitch(this, "autoSelectCellInNextRow")();
+		}
+	},
+	
+	autoSelectCellInNextRow: function(){
+		//summary:
+		//		auto scroll the grid to next row and select the cells
+		if(this.grid.select.outRangeY ){			
+			this.grid.scrollToRow(this.grid.scroller.firstVisibleRow + 1);
+			this.drugSelectCell(this.drugCurrentPoint.colIndex, this.drugCurrentPoint.rowIndex + 1);
+			if(this.grid.select.colChanged){
+				this.grid.select.colChanged = false;
+			}else {
+				setTimeout(dojo.hitch(this, 'autoSelectCellInNextRow', this.drugCurrentPoint.rowIndex + 1), this.getAutoScrollRate());
+			}
+		}
+	},
+	
+	getAutoScrollRate: function(){
+		//summary:
+		//		get the auto scroll time rate
+		//return: Integer:
+		//		the auto scroll time rate
+		return this.autoScrollRate;
+	},
+	
+	
+	resetStartPoint: function(){
+		//summary:
+		//		reset the DND selecting start point
+		if(this.drugSelectionStart.colIndex == -1 && this.drugSelectionStart.rowIndex == -1){
+			return;
+		}
+		this.lastDrugSelectionStart = dojo.clone(this.drugSelectionStart);
+		this.drugSelectionStart.colIndex = -1;
+		this.drugSelectionStart.rowIndex = -1;
+	},
+	
+	restorLastDragPoint: function(){
+		//summary:
+		//		restore the DND selecting start point to last one
+		this.drugSelectionStart = dojo.clone(this.lastDrugSelectionStart);
+	},
+	
+	drugSelectCell : function(inColumnIndex, inRowIndex){
+		//summary:
+		// Handle the Dnd selecting cell operation
+		// use this.grid.drugSelectionStart as the start point
+		// inRowIndex:
+		//		The end point Y position of the Dnd operation
+		// inColumnIndex:
+		//		The end point X position of the Dnd operation
+		
+		
+		// clear the pre selected cells
+		this.cleanAll();
+		
+		this.drugCurrentPoint.columnIndex = inColumnIndex;
+		this.drugCurrentPoint.rowIndex = inRowIndex;
+		
+		var fromRow, toRow, fromCol, toCol;
+		
+		// Use Min(inRowIndex, this.drugSelectionStart.rowIndex) as the Y value of top left point
+		//	   Max(inRowIndex, this.drugSelectionStart.rowIndex) as the Y value bottum right point
+		if(inRowIndex < this.drugSelectionStart.rowIndex){
+			fromRow = inRowIndex;
+			toRow = this.drugSelectionStart.rowIndex;
+		}else {
+			fromRow = this.drugSelectionStart.rowIndex;
+			toRow = inRowIndex;
+		}
+		
+		// Use Min(inColumnIndex, this.drugSelectionStart.colIndex) as the X value of top left point
+		//	   Max(inColumnIndex, this.drugSelectionStart.colIndex) as the X value bottum right point
+		if(inColumnIndex < this.drugSelectionStart.colIndex){
+			fromCol = inColumnIndex;
+			toCol = this.drugSelectionStart.colIndex;
+		}else {
+			fromCol = this.drugSelectionStart.colIndex;
+			toCol = inColumnIndex;
+		}
+		for(var i = fromCol; i <= toCol; i++){
+			this.addColumnRangeToSelection(i, fromRow, toRow);
+		}
+		
+	},
+	
+	selectColumn : function (columnIndex){
+		//summary:
+		// 		Handle the header cell click event
+		// columnIndex:
+		//		the colIndex of the header cell that fired the click event
+		this.addColumnToSelection(columnIndex);
+		
+	},
+	
+	drugSelectColumn : function(currentColumnIndex){
+		//summary:		
+		// 		Handle Dnd select operation
+		// currentColumnIndex:
+		// 		the colIndex of the col that fired mouseover event
+		this.selectColumnRange(this.drugSelectionStart.colIndex, currentColumnIndex);
+	}, 
+	
+	drugSelectColumnToMax: function(dir){
+		//summary:
+		//		select the column to the last one in the direction 'dir'
+		//dir: String
+		//		the direction to extend column selection
+		if(dir == "left"){
+			this.selectColumnRange(this.drugSelectionStart.colIndex, 0);
+		}else {
+			this.selectColumnRange(this.drugSelectionStart.colIndex, this.getHeaderNodes().length -1);
+		}
+	},
+	
+	selectColumnRange : function(startIndex, endIndex){
+		//summary:
+		// 		select a range of columns
+		// startIndex:
+		//		the start col index of the range
+		// endIndex:
+		//		the end col index of the range
+		if(!this.keepState)
+			this.cleanAll();
+		this._range(startIndex, endIndex, dojo.hitch(this, "addColumnToSelection"));
+		//this.clearDrugDivs();
+		//this.setSelectedColDivs();
+	},
+		
+	addColumnToSelection : function (columnIndex){
+		//summary:
+		// 		add all the cells in a column to selection
+		// columnIndex:
+		//		the index of the col
+		this.selectedColumns[columnIndex] = true;
+		dojo.toggleClass(this.getHeaderNodes()[columnIndex], "dojoxGridHeaderSelected", true);
+		//this.addColumnRangeToSelection(columnIndex, -1, Number.POSITIVE_INFINITY);
+		this._rangCellsInColumn(columnIndex, -1, Number.POSITIVE_INFINITY, this.addCellToSelection);
+		//this.setSelectedDiv();
+	},
+	
+	addColumnRangeToSelection : function (columnIndex, from, to){
+		//summary:
+		// Add a range of cells in the specified column to selection
+		// columnIndex:
+		//		the Column Index
+		// from:
+		//		the top cell of the range
+		// to:
+		//		the bottom cell of the range
+		
+		var viewManager = this.grid.views;
+		var columnCellNodes = [];
+		var dndManager = this;
+		
+		// As there's no reference of domNode for cell, get it manully
+		dojo.forEach(viewManager.views, function(view){
+			dojo.forEach(this.getViewRowNodes(view.rowNodes), function(rowNode, rowIndex){
+				if(!rowNode){ return; /* row not loaded */}
+				if(rowIndex >= from && rowIndex <= to){
+					dojo.forEach(rowNode.firstChild.rows[0].cells, function(cell){
+						
+						// get the cells of the row in the view by 
+						// rowNode.firstChild.rows[0].cells
+						// rowNode is the Div which is the domNode for a row, the firstChild is a table, and each row should have only one
+						// row in the table, so get rows[0] should be ok.
+						
+						if(cell && cell.attributes && (idx = cell.attributes.getNamedItem("idx")) && Number(idx.value) == columnIndex ){
+							dndManager.addCellToSelection(cell);
+						}
+					});
+				}
+			}, this);
+		}, this);		
+	},
+	
+	_rangCellsInColumn : function (columnIndex, from, to, func){
+		//summary:
+		// 		Add a range of cells in the specified column to selection
+		// 		columnIndex:
+		//		the Column Index
+		// from:
+		//		the top cell of the range
+		// to:
+		//		the bottom cell of the range
+		
+		var viewManager = this.grid.views;
+		var columnCellNodes = [];
+		var dndManager = this;
+		
+		// As there's no reference of domNode for cell, get it manully
+		dojo.forEach(viewManager.views, function(view){
+			dojo.forEach(this.getViewRowNodes(view.rowNodes), function(rowNode, rowIndex){
+				if(!rowNode){return;/* row not loaded */}
+				if(rowIndex >= from && rowIndex <= to){
+					dojo.forEach(rowNode.firstChild.rows[0].cells, function(cell){
+						// get the cells of the row in the view by 
+						// rowNode.firstChild.rows[0].cells
+						// rowNode is the Div which is the domNode for a row, the firstChild is a table, and each row should have only one
+						// row in the table, so get rows[0] should be ok.
+						if(cell && cell.attributes && (idx = cell.attributes.getNamedItem("idx")) && Number(idx.value) == columnIndex ){
+							func(cell, dndManager);
+						}
+					});
+				}
+			}, this);
+		}, this);		
+	},
+	
+	drugSelectRow : function(inRowIndex){
+		//summary:
+		// 		Handle dnd select rows
+		// 		call the dojox.grid.Selection to perform the operation
+		// inRowIndex:
+		//		the index of the row that fired mouseover event
+		
+		this.drugCurrentPoint.rowIndex = inRowIndex;
+		
+		this.cleanCellSelection();
+		this.clearDrugDivs();
+	
+		var selection = this.grid.selection;
+		selection._beginUpdate();
+		if(!this.keepState)
+			selection.deselectAll();
+		
+		selection.selectRange(this.drugSelectionStart.rowIndex, inRowIndex);
+		selection._endUpdate();
+		
+		this.publishRowChange();
+	},
+	
+	drugSelectRowToMax: function(dir){
+		//summary:
+		//		select the row to the last one in the direction 'dir'
+		//dir: String
+		//		the direction to extend row selection		
+		if(dir == "up"){
+			this.drugSelectRow(0);
+		}else {
+			this.drugSelectRow(this.grid.rowCount);
+		}
+	},
+
+	getCellNode: function(inCellIndex, inRowIndex){
+		//summary:
+		//		As there's no reference of domNode for cell, get it manully
+		//inCellIndex: Integer
+		//		Offset of the cell in the row, stands for the X index of the cell in the grid
+		//inRowIndex : Integer
+		//		Offset of the row in the grid, stands forthe Y index of the cell in the grid
+		//Description: Integer
+		//		Get the DOM node for the cell in a give position
+		//Return: Object
+		//		DOM node reference of the cell
+		var rowNodes = [], cellNode = null;
+		var viewManager = this.grid.views;
+		for(var i=0, v, n; (v=viewManager.views[i])&&(n=v.getRowNode(inRowIndex)); i++){
+			rowNodes.push(n);
+		}
+		dojo.forEach(rowNodes, dojo.hitch(function(rowNode, viewIndex){
+			if(cellNode){ return;/* get the cell from the previous view */}
+			var cells = dojo.query("[idx='" + inCellIndex + "']",rowNode);
+			if(cells && cells[0]){
+				cellNode = cells[0];
+			}
+		}));
+		return cellNode;
+	},
+	
+	addCellToSelection : function(cellNode, dndManager){
+		//summary:
+		//	 	add a cell to selection list and change it into selected state
+		//cellNode: Object
+		//		the cell node will be added to select
+		//dndManager: _DndSelectionManager
+		//		reference to the instance of _DndSelectionManager
+		if(!dndManager){
+			dndManager = this;
+		}
+		dndManager.selectedCells[dndManager.selectedCells.length] = cellNode;
+		dojo.toggleClass(cellNode, dndManager.selectedClass, true);
+	},
+	
+	isColSelected: function(inColIndex){
+		//summary:
+		//		wether the column in of index value "inColIndex" is selected
+		//inColIndex: Integer
+		//		the index value of the column
+		//return: Boolean
+		//		wether the column in of index value "inColIndex" is selected
+		return this.selectedColumns[inColIndex];
+	},
+	
+	isRowSelected: function(inRowIndex){
+		//summary:
+		//		wether the row in of index value "inRowIndex" is selected
+		//inRowIndex: Integer
+		//		the index value of the row
+		//return: Boolean
+		//		wether the row in of index value "inRowIndex" is selected
+		return this.grid.selection.selected[inRowIndex];
+	},
+	
+	isContinuousSelection: function(selected){
+		//summary:
+		//		Whether a selection is continuous
+		//selected: Array
+		//		the selection states for columns or rows
+		//return: Boolean 
+		var preSelectedIdx = -1;
+		for(var i = 0; i < selected.length; i++){
+			if(!selected[i]){ continue; }
+			if(preSelectedIdx < 0 || i - preSelectedIdx == 1 ){ preSelectedIdx = i; }
+			else if(i - preSelectedIdx >= 2 ){ return false; }
+		}
+		return preSelectedIdx >= 0 ? true : false;
+	},
+	
+	cleanCellSelection : function(){
+		//summary:
+		//		change all the selected cell to unselected and umpty the selected-cell list
+		dojo.forEach(this.selectedCells, dojo.hitch(this, "removeCellSelectedState"));
+		this.selectedCells = [];
+		dojo.forEach(this.selectedColumns, function(selected, index){
+			if(selected){
+				dojo.toggleClass(this.getHeaderNodes()[index], "dojoxGridHeaderSelected", false);
+			}
+		}, this);
+		
+		this.selectedColumns = [];
+		this.grid.edit.isEditing() && this.grid.edit.apply();
+	},
+	
+	removeCellSelectedState : function(cell){
+		//summary:
+		//		change the cell style to un-selected
+		//cell:
+		//		the cell dom-node the style to be changed
+		dojo.toggleClass(cell, this.selectedClass, false);
+	}, 
+	
+	cleanAll : function(){
+		//summary:
+		//Clear all the selected cells, columns and rows
+		// row selection is reused from dojox.grid._Selection, 
+		// so clear it by call the clear function of dojox.grid._Selection
+		
+		// clear cell and column selection effect 
+		this.cleanCellSelection();
+		// clear row selection effect
+		this.grid.selection.clear();
+		// clear Column/Row 
+		//this.selectedColumns = [];
+		//this.selectedRows = [];
+		this.publishRowChange();
+	},
+	
+	refreshColumnSelection: function(){
+		//summary:
+		//		handle grid scroll, keep column selected state
+		dojo.forEach(this.selectedColumns, dojo.hitch(this, function(selectedColumn, colIndex){
+			if(selectedColumn){
+				this.grid.select.addColumnToSelection(colIndex);
+			}
+		}));
+	},
+	
+	inSelectedArea: function(inColIndex, inRowIndex){
+		//summary:
+		//		whether the specified point is in selected area
+		//inColIndex: Integer
+		//		the col index of the point
+		//inRowIndex: Integer
+		//		the row index of the point
+		//return: Boolean
+		//		whether the specified point is in selected area
+		return this.selectedColumns[inColIndex] || this.gird.selection.selecteded[inRowIndex];
+	},
+	
+	publishRowChange: function(){
+		//summary:
+		//		publish a topic to notify that row selection changed
+		dojo.publish(this.grid.rowSelectionChangedTopic, [this]);
+	}, 
+	
+	getViewRowNodes: function(viewRowNodes){
+		//summary:
+		//		Get view row nodes in array form
+		var rowNodes = [];
+		for(i in viewRowNodes){
+			rowNodes.push(viewRowNodes[i]);
+		}
+		return rowNodes;
+	},
+	
+	getFirstSelected: function(){
+		//summary:
+		//		Get the first selected row index
+		//return: Integer
+		//		First selected row index
+		return dojo.hitch(this.grid.selection, dojox.grid.Selection.prototype.getFirstSelected)();
+	},
+	
+	getLastSelected: function(){
+		//summary:
+		//		Get the last selected row index
+		//return: Integer
+		//		Last selected row index
+		var selected = this.grid.selection.selected;
+		for(var i = selected.length - 1; i >= 0; i--){
+			if(selected[i]){ return i; }
+		}
+		return -1;
+	}
 });
-}
-},this);
-},this);
-},drugSelectRow:function(_3a){
-this.drugCurrentPoint.rowIndex=_3a;
-this.cleanCellSelection();
-this.clearDrugDivs();
-var _3b=this.grid.selection;
-_3b._beginUpdate();
-if(!this.keepState){
-_3b.deselectAll();
-}
-_3b.selectRange(this.drugSelectionStart.rowIndex,_3a);
-_3b._endUpdate();
-this.publishRowChange();
-},drugSelectRowToMax:function(dir){
-if(dir=="up"){
-this.drugSelectRow(0);
-}else{
-this.drugSelectRow(this.grid.rowCount);
-}
-},getCellNode:function(_3c,_3d){
-var _3e=[],_3f=null;
-var _40=this.grid.views;
-for(var i=0,v,n;(v=_40.views[i])&&(n=v.getRowNode(_3d));i++){
-_3e.push(n);
-}
-dojo.forEach(_3e,dojo.hitch(function(_41,_42){
-if(_3f){
-return;
-}
-var _43=dojo.query("[idx='"+_3c+"']",_41);
-if(_43&&_43[0]){
-_3f=_43[0];
-}
-}));
-return _3f;
-},addCellToSelection:function(_44,_45){
-if(!_45){
-_45=this;
-}
-_45.selectedCells[_45.selectedCells.length]=_44;
-dojo.toggleClass(_44,_45.selectedClass,true);
-},isColSelected:function(_46){
-return this.selectedColumns[_46];
-},isRowSelected:function(_47){
-return this.grid.selection.selected[_47];
-},isContinuousSelection:function(_48){
-var _49=-1;
-for(var i=0;i<_48.length;i++){
-if(!_48[i]){
-continue;
-}
-if(_49<0||i-_49==1){
-_49=i;
-}else{
-if(i-_49>=2){
-return false;
-}
-}
-}
-return _49>=0?true:false;
-},cleanCellSelection:function(){
-dojo.forEach(this.selectedCells,dojo.hitch(this,"removeCellSelectedState"));
-this.selectedCells=[];
-dojo.forEach(this.selectedColumns,function(_4a,_4b){
-if(_4a){
-dojo.toggleClass(this.getHeaderNodes()[_4b],"dojoxGridHeaderSelected",false);
-}
-},this);
-this.selectedColumns=[];
-this.grid.edit.isEditing()&&this.grid.edit.apply();
-},removeCellSelectedState:function(_4c){
-dojo.toggleClass(_4c,this.selectedClass,false);
-},cleanAll:function(){
-this.cleanCellSelection();
-this.grid.selection.clear();
-this.publishRowChange();
-},refreshColumnSelection:function(){
-dojo.forEach(this.selectedColumns,dojo.hitch(this,function(_4d,_4e){
-if(_4d){
-this.grid.select.addColumnToSelection(_4e);
-}
-}));
-},inSelectedArea:function(_4f,_50){
-return this.selectedColumns[_4f]||this.gird.selection.selecteded[_50];
-},publishRowChange:function(){
-dojo.publish(this.grid.rowSelectionChangedTopic,[this]);
-},getViewRowNodes:function(_51){
-var _52=[];
-for(i in _51){
-_52.push(_51[i]);
-}
-return _52;
-},getFirstSelected:function(){
-return dojo.hitch(this.grid.selection,dojox.grid.Selection.prototype.getFirstSelected)();
-},getLastSelected:function(){
-var _53=this.grid.selection.selected;
-for(var i=_53.length-1;i>=0;i--){
-if(_53[i]){
-return i;
-}
-}
-return -1;
-}});
-}
diff --git a/dojox/grid/enhanced/nls/EnhancedGrid.js b/dojox/grid/enhanced/nls/EnhancedGrid.js
index ddcfe7a..651ab50 100644
--- a/dojox/grid/enhanced/nls/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"Descending","sortingState":"${0} - ${1}","ascending":"Ascending","nestedSort":"Nested Sort","unsorted":"Do not sort this column","singleSort":"Single Sort"})
\ No newline at end of file
+({
+	singleSort: "Single Sort",
+	nestedSort: "Nested Sort",
+	ascending: "Ascending",
+	descending: "Descending",
+	sortingState: "${0} - ${1}",
+	unsorted: "Do not sort this column"
+})
diff --git a/dojox/grid/enhanced/nls/ar/EnhancedGrid.js b/dojox/grid/enhanced/nls/ar/EnhancedGrid.js
new file mode 100644
index 0000000..4c5bab4
--- /dev/null
+++ b/dojox/grid/enhanced/nls/ar/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "فرز منفرد",
+	nestedSort: "فرز متداخل",
+	ascending: "تصاعدي",
+	descending: "تنازلي",
+	unsorted: "عدم فرز هذا العمود"
+})
+
diff --git a/dojox/grid/enhanced/nls/ca/EnhancedGrid.js b/dojox/grid/enhanced/nls/ca/EnhancedGrid.js
new file mode 100644
index 0000000..4b72067
--- /dev/null
+++ b/dojox/grid/enhanced/nls/ca/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "Ordre únic",
+	nestedSort: "Ordre imbricat",
+	ascending: "Ascendent",
+	descending: "Descendent",
+	unsorted: "No ordenis aquesta finestra"
+})
+
diff --git a/dojox/grid/enhanced/nls/cs/EnhancedGrid.js b/dojox/grid/enhanced/nls/cs/EnhancedGrid.js
index fa66be3..d626406 100644
--- a/dojox/grid/enhanced/nls/cs/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/cs/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"Sestupně","ascending":"Vzestupně","nestedSort":"Vnořené řazení","unsorted":"Tento sloupec neřadit","singleSort":"Jednoduché řazení","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "Jednoduché řazení",
+	nestedSort: "Vnořené řazení",
+	ascending: "Vzestupně",
+	descending: "Sestupně",
+	unsorted: "Tento sloupec neřadit"
+})
+
diff --git a/dojox/grid/enhanced/nls/da/EnhancedGrid.js b/dojox/grid/enhanced/nls/da/EnhancedGrid.js
new file mode 100644
index 0000000..a9f99fd
--- /dev/null
+++ b/dojox/grid/enhanced/nls/da/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "Enkel sortering",
+	nestedSort: "Indlejret sortering",
+	ascending: "Stigende",
+	descending: "Faldende",
+	unsorted: "Sortér ikke denne kolonne"
+})
+
diff --git a/dojox/grid/enhanced/nls/de/EnhancedGrid.js b/dojox/grid/enhanced/nls/de/EnhancedGrid.js
index 48ac78f..58794db 100644
--- a/dojox/grid/enhanced/nls/de/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/de/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"Absteigend","ascending":"Aufsteigend","nestedSort":"Verschachtelte Sortierung","unsorted":"Spalte nicht sortieren","singleSort":"Einfache Sortierung","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "Einfache Sortierung",
+	nestedSort: "Verschachtelte Sortierung",
+	ascending: "Aufsteigend",
+	descending: "Absteigend",
+	unsorted: "Spalte nicht sortieren"
+})
+
diff --git a/dojox/grid/enhanced/nls/el/EnhancedGrid.js b/dojox/grid/enhanced/nls/el/EnhancedGrid.js
new file mode 100644
index 0000000..272da62
--- /dev/null
+++ b/dojox/grid/enhanced/nls/el/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "Απλή ταξινόμηση",
+	nestedSort: "Ένθετη ταξινόμηση",
+	ascending: "Αύξουσα",
+	descending: "Φθίνουσα",
+	unsorted: "Χωρίς ταξινόμηση αυτής της στήλης"
+})
+
diff --git a/dojox/grid/enhanced/nls/es/EnhancedGrid.js b/dojox/grid/enhanced/nls/es/EnhancedGrid.js
index 692ee35..5cb045f 100644
--- a/dojox/grid/enhanced/nls/es/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/es/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"Descendente","ascending":"Ascendente","nestedSort":"Orden anidado","unsorted":"No ordenar esta columna","singleSort":"Orden único","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "Orden único",
+	nestedSort: "Orden anidado",
+	ascending: "Ascendente",
+	descending: "Descendente",
+	unsorted: "No ordenar esta columna"
+})
+
diff --git a/dojox/grid/enhanced/nls/fi/EnhancedGrid.js b/dojox/grid/enhanced/nls/fi/EnhancedGrid.js
new file mode 100644
index 0000000..f88be60
--- /dev/null
+++ b/dojox/grid/enhanced/nls/fi/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "Yksinkertainen lajittelu",
+	nestedSort: "Sisäkkäinen lajittelu",
+	ascending: "Nouseva",
+	descending: "Laskeva",
+	unsorted: "Älä lajittele tätä saraketta"
+})
+
diff --git a/dojox/grid/enhanced/nls/fr/EnhancedGrid.js b/dojox/grid/enhanced/nls/fr/EnhancedGrid.js
index 49b9020..25e455f 100644
--- a/dojox/grid/enhanced/nls/fr/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/fr/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"Décroissant","ascending":"Croissant","nestedSort":"Tri imbriqué","unsorted":"Ne pas trier cette colonne","singleSort":"Tri unique","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "Tri unique",
+	nestedSort: "Tri imbriqué",
+	ascending: "Croissant",
+	descending: "Décroissant",
+	unsorted: "Ne pas trier cette colonne"
+})
+
diff --git a/dojox/grid/enhanced/nls/he/EnhancedGrid.js b/dojox/grid/enhanced/nls/he/EnhancedGrid.js
new file mode 100644
index 0000000..06b5242
--- /dev/null
+++ b/dojox/grid/enhanced/nls/he/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "מיון יחיד",
+	nestedSort: "מיון מקונן ",
+	ascending: "עולה",
+	descending: "יורד",
+	unsorted: "לא למיין עמודה זו "
+})
+
diff --git a/dojox/grid/enhanced/nls/hu/EnhancedGrid.js b/dojox/grid/enhanced/nls/hu/EnhancedGrid.js
index 8f94e10..de91f1d 100644
--- a/dojox/grid/enhanced/nls/hu/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/hu/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"Csökkenő","ascending":"Növekvő","nestedSort":"Beágyazott rendezés","unsorted":"Az oszlop nincs rendezve","singleSort":"Egyszerű rendezés","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "Egyszerű rendezés",
+	nestedSort: "Beágyazott rendezés",
+	ascending: "Növekvő",
+	descending: "Csökkenő",
+	unsorted: "Az oszlop nincs rendezve"
+})
+
diff --git a/dojox/grid/enhanced/nls/it/EnhancedGrid.js b/dojox/grid/enhanced/nls/it/EnhancedGrid.js
index 11ce57a..be73514 100644
--- a/dojox/grid/enhanced/nls/it/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/it/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"Decrescente","ascending":"Crescente","nestedSort":"Ordinamento nidificato","unsorted":"Non ordinare questa colonna","singleSort":"Ordinamento singolo","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "Ordinamento singolo",
+	nestedSort: "Ordinamento nidificato",
+	ascending: "Crescente",
+	descending: "Decrescente",
+	unsorted: "Non ordinare questa colonna"
+})
+
diff --git a/dojox/grid/enhanced/nls/ja/EnhancedGrid.js b/dojox/grid/enhanced/nls/ja/EnhancedGrid.js
index 1bfb970..2fa1310 100644
--- a/dojox/grid/enhanced/nls/ja/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/ja/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"降順","ascending":"昇順","nestedSort":"ネストされたソート","unsorted":"この列はソートしないでください","singleSort":"単一ソート","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "単一ソート",
+	nestedSort: "ネストされたソート",
+	ascending: "昇順",
+	descending: "降順",
+	unsorted: "この列はソートしないでください"
+})
+
diff --git a/dojox/grid/enhanced/nls/ko/EnhancedGrid.js b/dojox/grid/enhanced/nls/ko/EnhancedGrid.js
index 4a5a694..8096438 100644
--- a/dojox/grid/enhanced/nls/ko/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/ko/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"내림차순","ascending":"오름차순","nestedSort":"중첩 정렬","unsorted":"이 열을 정렬하지 않음","singleSort":"단일 정렬","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "단일 정렬",
+	nestedSort: "중첩 정렬",
+	ascending: "오름차순",
+	descending: "내림차순",
+	unsorted: "이 열을 정렬하지 않음"
+})
+
diff --git a/dojox/grid/enhanced/nls/nb/EnhancedGrid.js b/dojox/grid/enhanced/nls/nb/EnhancedGrid.js
new file mode 100644
index 0000000..3c84862
--- /dev/null
+++ b/dojox/grid/enhanced/nls/nb/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "Enkel sortering",
+	nestedSort: "Nestet sortering",
+	ascending: "Stigende",
+	descending: "Synkende",
+	unsorted: "Ikke sorter denne kolonnen"
+})
+
diff --git a/dojox/grid/enhanced/nls/nl/EnhancedGrid.js b/dojox/grid/enhanced/nls/nl/EnhancedGrid.js
new file mode 100644
index 0000000..848d4af
--- /dev/null
+++ b/dojox/grid/enhanced/nls/nl/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "Enkele sorteerbewerking",
+	nestedSort: "Geneste sorteerbewerking",
+	ascending: "Oplopend",
+	descending: "Aflopend",
+	unsorted: "Deze kolom niet sorteren"
+})
+
diff --git a/dojox/grid/enhanced/nls/pl/EnhancedGrid.js b/dojox/grid/enhanced/nls/pl/EnhancedGrid.js
index fd81206..85cf13f 100644
--- a/dojox/grid/enhanced/nls/pl/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/pl/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"Malejąco","ascending":"Rosnąco","nestedSort":"Sortowanie zagnieżdżone","unsorted":"Nie sortuj tej kolumny","singleSort":"Sortowanie pojedyncze","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "Sortowanie pojedyncze",
+	nestedSort: "Sortowanie zagnieżdżone",
+	ascending: "Rosnąco",
+	descending: "Malejąco",
+	unsorted: "Nie sortuj tej kolumny"
+})
+
diff --git a/dojox/grid/enhanced/nls/pt-pt/EnhancedGrid.js b/dojox/grid/enhanced/nls/pt-pt/EnhancedGrid.js
new file mode 100644
index 0000000..b845586
--- /dev/null
+++ b/dojox/grid/enhanced/nls/pt-pt/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "Ordenação única",
+	nestedSort: "Ordenação imbricada",
+	ascending: "Ascendente",
+	descending: "Descendente",
+	unsorted: "Não ordenar esta coluna"
+})
+
diff --git a/dojox/grid/enhanced/nls/pt/EnhancedGrid.js b/dojox/grid/enhanced/nls/pt/EnhancedGrid.js
index bdd7cac..6346323 100644
--- a/dojox/grid/enhanced/nls/pt/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/pt/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"Descendente","ascending":"Ascendente","nestedSort":"Classificação Aninhada","unsorted":"Não classificar esta coluna","singleSort":"Classificação Única","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "Classificação Única",
+	nestedSort: "Classificação Aninhada",
+	ascending: "Ascendente",
+	descending: "Descendente",
+	unsorted: "Não classificar esta coluna"
+})
+
diff --git a/dojox/grid/enhanced/nls/ro/EnhancedGrid.js b/dojox/grid/enhanced/nls/ro/EnhancedGrid.js
new file mode 100644
index 0000000..398a766
--- /dev/null
+++ b/dojox/grid/enhanced/nls/ro/EnhancedGrid.js
@@ -0,0 +1,9 @@
+({
+	singleSort: "Sortare singulară ",
+	nestedSort: "Sortare imbricată",
+	ascending: "Crescător",
+	descending: "Descrescător",
+	sortingState: "${0} - ${1}",
+	unsorted: "Nu sortaţi această coloană "
+})
+
diff --git a/dojox/grid/enhanced/nls/ru/EnhancedGrid.js b/dojox/grid/enhanced/nls/ru/EnhancedGrid.js
index b1560b6..d4caf2a 100644
--- a/dojox/grid/enhanced/nls/ru/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/ru/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"По убыванию","ascending":"По возрастанию","nestedSort":"Вложенная сортировка","unsorted":"Не сортировать этот столбец","singleSort":"Однократная сортировка","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "Однократная сортировка",
+	nestedSort: "Вложенная сортировка",
+	ascending: "По возрастанию",
+	descending: "По убыванию",
+	unsorted: "Не сортировать этот столбец"
+})
+
diff --git a/dojox/grid/enhanced/nls/sk/EnhancedGrid.js b/dojox/grid/enhanced/nls/sk/EnhancedGrid.js
new file mode 100644
index 0000000..711f562
--- /dev/null
+++ b/dojox/grid/enhanced/nls/sk/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "Jednoduché triedenie ",
+	nestedSort: "Vnorené triedenie ",
+	ascending: "Vzostupne ",
+	descending: "Zostupne ",
+	unsorted: "Netriediť tento stĺpec "
+})
+
diff --git a/dojox/grid/enhanced/nls/sl/EnhancedGrid.js b/dojox/grid/enhanced/nls/sl/EnhancedGrid.js
new file mode 100644
index 0000000..6726cd3
--- /dev/null
+++ b/dojox/grid/enhanced/nls/sl/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "Razvrsti po vrsti",
+	nestedSort: "Ugnezdena razvrstitev",
+	ascending: "Naraščajoče",
+	descending: "Padajoče",
+	unsorted: "Ne razvrsti tega stolpca"
+})
+
diff --git a/dojox/grid/enhanced/nls/sv/EnhancedGrid.js b/dojox/grid/enhanced/nls/sv/EnhancedGrid.js
new file mode 100644
index 0000000..8e06f85
--- /dev/null
+++ b/dojox/grid/enhanced/nls/sv/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "enkel sortering",
+	nestedSort: "nästlad sortering",
+	ascending: "stigande",
+	descending: "fallande",
+	unsorted: "Sortera inte den här kolumnen"
+})
+
diff --git a/dojox/grid/enhanced/nls/th/EnhancedGrid.js b/dojox/grid/enhanced/nls/th/EnhancedGrid.js
new file mode 100644
index 0000000..2b26c2a
--- /dev/null
+++ b/dojox/grid/enhanced/nls/th/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "เรียงลำดับแบบเดี่ยว",
+	nestedSort: "เรียงลำดับที่ซับซ้อน",
+	ascending: "จากน้อยไปหามาก",
+	descending: "จากมากไปหาน้อย",
+	unsorted: "ห้ามเรียงลำดับคอลัมน์นี้"
+})
+
diff --git a/dojox/grid/enhanced/nls/tr/EnhancedGrid.js b/dojox/grid/enhanced/nls/tr/EnhancedGrid.js
new file mode 100644
index 0000000..0c1d0a8
--- /dev/null
+++ b/dojox/grid/enhanced/nls/tr/EnhancedGrid.js
@@ -0,0 +1,8 @@
+({
+	singleSort: "Tek Sıralama",
+	nestedSort: "İç İçe Sıralama",
+	ascending: "Artan",
+	descending: "Azalan",
+	unsorted: "Bu sütunu sıralama"
+})
+
diff --git a/dojox/grid/enhanced/nls/zh-tw/EnhancedGrid.js b/dojox/grid/enhanced/nls/zh-tw/EnhancedGrid.js
index 3d42c88..48b5638 100644
--- a/dojox/grid/enhanced/nls/zh-tw/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/zh-tw/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"遞減","ascending":"遞增","nestedSort":"巢狀排序","unsorted":"不排序此直欄","singleSort":"單一排序","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "單一排序",
+	nestedSort: "巢狀排序",
+	ascending: "遞增",
+	descending: "遞減",
+	unsorted: "不排序此直欄"
+})
+
diff --git a/dojox/grid/enhanced/nls/zh/EnhancedGrid.js b/dojox/grid/enhanced/nls/zh/EnhancedGrid.js
index 06ac7a4..a0dff12 100644
--- a/dojox/grid/enhanced/nls/zh/EnhancedGrid.js
+++ b/dojox/grid/enhanced/nls/zh/EnhancedGrid.js
@@ -1 +1,8 @@
-({"descending":"降序","ascending":"升序","nestedSort":"嵌套排序","unsorted":"不要对此列排序","singleSort":"单一排序","sortingState":"${0} - ${1}"})
\ No newline at end of file
+({
+	singleSort: "单一排序",
+	nestedSort: "嵌套排序",
+	ascending: "升序",
+	descending: "降序",
+	unsorted: "不要对此列排序"
+})
+
diff --git a/dojox/grid/enhanced/plugins/DnD.js b/dojox/grid/enhanced/plugins/DnD.js
index 232b6e6..12b37c6 100644
--- a/dojox/grid/enhanced/plugins/DnD.js
+++ b/dojox/grid/enhanced/plugins/DnD.js
@@ -1,13 +1,10 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.enhanced.plugins.DnD"]){
-dojo._hasResource["dojox.grid.enhanced.plugins.DnD"]=true;
 dojo.provide("dojox.grid.enhanced.plugins.DnD");
+
 dojo.require("dojox.grid.enhanced.dnd._DndMovingManager");
-dojo.declare("dojox.grid.enhanced.plugins.DnD",dojox.grid.enhanced.dnd._DndMovingManager,{});
-}
+
+dojo.declare("dojox.grid.enhanced.plugins.DnD", dojox.grid.enhanced.dnd._DndMovingManager, {
+	//	summary:
+	//		 Provides dnd support for row(s) and column(s)
+	// example:
+	// 		 <div dojoType="dojox.grid.EnhancedGrid" plugins="{dnd: true}" ...></div>
+});
diff --git a/dojox/grid/enhanced/plugins/IndirectSelection.js b/dojox/grid/enhanced/plugins/IndirectSelection.js
index c29b753..2abba9b 100644
--- a/dojox/grid/enhanced/plugins/IndirectSelection.js
+++ b/dojox/grid/enhanced/plugins/IndirectSelection.js
@@ -1,291 +1,570 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.enhanced.plugins.IndirectSelection"]){
-dojo._hasResource["dojox.grid.enhanced.plugins.IndirectSelection"]=true;
 dojo.provide("dojox.grid.enhanced.plugins.IndirectSelection");
+
 dojo.require("dojox.grid.cells.dijit");
 dojo.require("dojox.grid.cells._base");
-dojo.declare("dojox.grid.enhanced.plugins.IndirectSelection",null,{constructor:function(_1){
-this.grid=_1;
-dojo.connect(_1.layout,"setStructure",dojo.hitch(_1.layout,this.addRowSelectCell));
-},addRowSelectCell:function(){
-if(!this.grid.indirectSelection||this.grid.selectionMode=="none"){
-return;
-}
-var _2=false,_3=["get","formatter","field","fields"],_4={type:dojox.grid.cells.DijitMultipleRowSelector,name:"",editable:true,width:"30px",styles:"text-align: center;"};
-dojo.forEach(this.structure,dojo.hitch(this,function(_5){
-var _6=_5.cells;
-if(_6&&_6.length>0&&!_2){
-var _7=_6[0];
-if(_7[0]&&_7[0]["isRowSelector"]){
-_2=true;
-return;
-}
-var _8,_9=this.grid.selectionMode=="single"?dojox.grid.cells.DijitSingleRowSelector:dojox.grid.cells.DijitMultipleRowSelector;
-if(!dojo.isObject(this.grid.indirectSelection)){
-_8=dojo.mixin(_4,{type:_9});
-}else{
-_8=dojo.mixin(_4,this.grid.indirectSelection,{type:_9,editable:true});
-dojo.forEach(_3,function(_a){
-if(_a in _8){
-delete _8[_a];
-}
+
+dojo.declare("dojox.grid.enhanced.plugins.IndirectSelection", null, {
+	//	summary:
+	//		 Provides indirect selection feature - swipe selecting row(s)
+	// example:
+	// 		 <div dojoType="dojox.grid.EnhancedGrid" plugins="{indirectSelection: true}" ...></div>
+	// 	  or <div dojoType="dojox.grid.EnhancedGrid" plugins="{indirectSelection: {name: 'xxx', width:'30px', styles:'text-align: center;'}}" ...></div>	
+
+	constructor: function(inGrid){
+		this.grid = inGrid;
+		//Hook grid.layout.setStructure(), so that indirect selection cell is included in the new structure
+		dojo.connect(inGrid.layout, 'setStructure', dojo.hitch(inGrid.layout, this.addRowSelectCell));
+	},
+	
+	addRowSelectCell: function(){
+		//summary:
+		//		Add the indirect selection cell(mapped to a column of checkboxes) to grid layout structure
+		if(!this.grid.indirectSelection || this.grid.selectionMode == 'none'){
+			return;
+		}
+		var rowSelectCellAdded = false, inValidFields = ['get', 'formatter', 'field', 'fields'],
+		defaultCellDef = {type: dojox.grid.cells.DijitMultipleRowSelector, name: '', editable: true, width:'30px', styles:'text-align: center;'};
+		dojo.forEach(this.structure, dojo.hitch(this, function(view){
+			var cells = view.cells;
+			if(cells && cells.length > 0 && !rowSelectCellAdded){
+				var firstRow = cells[0];
+				if(firstRow[0] && firstRow[0]['isRowSelector']){
+					console.debug('addRowSelectCell() - row selector cells already added, return.');
+					rowSelectCellAdded = true;
+					return;
+				}
+				var selectDef, cellType = this.grid.selectionMode == 'single' ? dojox.grid.cells.DijitSingleRowSelector : dojox.grid.cells.DijitMultipleRowSelector;
+				if(!dojo.isObject(this.grid.indirectSelection)){
+					selectDef = dojo.mixin(defaultCellDef, {type: cellType});
+				}else{
+					selectDef = dojo.mixin(defaultCellDef, this.grid.indirectSelection, {type: cellType, editable: true});
+					dojo.forEach(inValidFields, function(field){//remove invalid feilds
+						if(field in selectDef){ delete selectDef[field]; }
+					});
+				}
+				cells.length > 1 && (selectDef["rowSpan"] = cells.length);//for complicate layout
+				dojo.forEach(this.cells, function(cell, i){
+					if(cell.index >= 0){
+						cell.index += 1;
+						//console.debug('cell '+ (cell.index - 1) +  ' is updated to index ' + cell.index);
+					}else{
+						console.debug('Error:IndirectSelection.addRowSelectCell()-  cell ' + i + ' has no index!');
+					}
+				});
+				var rowSelectCell = this.addCellDef(0, 0, selectDef);
+				rowSelectCell.index = 0;
+				firstRow.unshift(rowSelectCell);
+				this.cells.unshift(rowSelectCell);
+				this.grid.rowSelectCell = rowSelectCell;
+				rowSelectCellAdded = true;
+			}			
+		}));		
+		this.cellCount = this.cells.length;
+	}
+});
+
+dojo.declare("dojox.grid.cells._SingleRowSelectorMixin", null, {
+	//	summary:
+	//		 Common attributes and functions to be mixed in for single selection	
+
+	//alwaysEditing: Boolean
+	//		Overwritten, see dojox.grid.cells._Widget
+	//		True - always show the radio or checkbox widget
+	alwaysEditing: true,
+	
+	//widgetMap: Object
+	//		Cache all the radio or checkbox widgets
+	widgetMap:{},
+	
+	//widget: Object
+	//		The currently focused widget
+	widget: null,
+	
+	//isRowSelector: Boolean
+	//		Marker of indirect selection cell(column)
+	isRowSelector: true,
+
+	//defaultValue: Boolean
+	//		Default value for radio or checkbox widget
+	defaultValue: false,
+
+	formatEditing: function(inDatum, inRowIndex){
+		// summary:
+		//		Overwritten, see dojox.grid.cells._Widget
+		this.needFormatNode(inDatum, inRowIndex);
+	},
+	
+	_formatNode: function(inDatum, inRowIndex){
+		// summary:
+		//		Overwritten, see dojox.grid.cells._Base
+		this.formatNode(inDatum, inRowIndex);
+	},
+
+	setValue: function(inRowIndex, inValue){
+		// summary:
+		//		Overwritten, see dojox.grid.cells._Widget
+		//		Simpily return, no action
+		return;
+	},
+	
+	get: function(inRowIndex){
+		// summary:
+		//		Overwritten, see dojox.grid.cells._Base
+		//		return widget value of row(inRowIndex) -  true | false
+		var widget = this.widgetMap[this.view.id] ? this.widgetMap[this.view.id][inRowIndex] : null;
+		var value = widget ? widget.attr('checked') : '';
+		return value;
+	},
+	
+	_fireSelectionChanged: function(){
+		// summary:
+		//		Publish rowSelectionChangedTopic when new row selection is made
+		dojo.publish(this.grid.rowSelectionChangedTopic,[this]);
+	},
+	
+	_selectionChanged: function(obj){
+		// summary:
+		//		Subscriber of rowSelectionChangedTopic, update row selection accordingly
+		// obj: Object
+		//		Object that fired the rowSelectionChangedTopic
+		if(obj == this || obj.grid && obj.grid != this.grid){
+			//ignore if the topic is published by self
+			return;
+		}
+		for (var i in this.widgetMap[this.view.id]){
+			var idx = new Number(i);
+			var widget = this.widgetMap[this.view.id][idx];
+			var value = !!this.grid.selection.selected[idx];
+			widget.attr('checked', value);
+		}
+		this.defaultValue = false;
+		this.grid.edit.isEditing() && this.grid.edit.apply();
+	},
+	
+	_toggleSingleRow: function(idx, value){
+		// summary:
+		//		toggle selection of a single row
+		// idx: Integer
+		//		Target row index
+		// value: Boolean
+		//		True - checked | False - unchecked
+		var widget;
+		dojo.hitch(this.grid.selection, dojox.grid.Selection.prototype[value ? 'addToSelection' : 'deselect'])(idx);
+		if(this.widgetMap[this.view.id] && (widget = this.widgetMap[this.view.id][idx])){
+			widget.attr('checked', value);			
+		}
+		this._fireSelectionChanged();
+	},	
+
+	inIndirectSelectionMode: function(){},
+	
+	toggleAllSelection: function(){}
 });
-}
-_6.length>1&&(_8["rowSpan"]=_6.length);
-dojo.forEach(this.cells,function(_b,i){
-if(_b.index>=0){
-_b.index+=1;
-}else{
-}
+
+dojo.declare("dojox.grid.cells._MultipleRowSelectorMixin", null, {
+	//	summary:
+	//		 Common attributes and functions to be mixed in for multiple selection
+
+	//swipeStartRowIndex: Integer
+	//		Start row index for swipe selection
+	swipeStartRowIndex: -1,
+
+	//swipeMinRowIndex: Integer
+	//		Min row index for swipe selection	
+	swipeMinRowIndex: -1,
+	
+	//swipeMinRowIndex: Integer
+	//		Max row index for swipe selection
+	swipeMaxRowIndex: -1,
+	
+	//toSelect: Boolean
+	//		selection new state
+	toSelect: false,
+	
+	//lastClickRowIdx: Integer
+	//		Row index for last click, used for range selection via Shift + click	
+	lastClickRowIdx: -1,
+	
+	//toggleAllTrigerred: Boolean
+	//		Whether toggle all has been triggered or not	
+	toggleAllTrigerred: false,
+
+	//_inDndSelection: Boolean
+	//		Whether in DnD row selection progress or not	
+	_inDndSelection: false,
+
+	domousedown: function(e){
+		//summay:
+		//		Event hanlder for mouse down event
+		// e: Event
+		//		Mouse down event
+		if(e.target.tagName == 'INPUT'){
+			this._startSelection(e.rowIndex);
+			//console.debug('domousedown()- set swipeStartRowIndex='+this.swipeStartRowIndex + ' toSelect='+this.toSelect);
+		}
+		dojo.stopEvent(e);
+	},
+	
+	domousemove: function(e){
+		// summay:
+		//		Event hanlder for mouse move event
+		// e: Event
+		//		Mouse move event
+		this._updateSelection(e, 0);
+	},
+		
+	onRowMouseOver: function(e){
+		// summary:
+		//		Event fired when mouse moves over a data row.
+		// e: Event
+		//		Decorated event object which contains reference to grid, cell, and rowIndex
+		this._updateSelection(e, 0);
+		if(this.grid.dnd){
+			this._inDndSelection = this.grid.select.isInSelectingMode('row');
+		}
+	},
+	
+	domouseup: function(e){
+		// summay:
+		//		Event hanlder for mouse up event
+		// e: Event
+		//		Mouse up event
+		dojo.isIE && this.view.content.decorateEvent(e);//TODO - why only e in IE hasn't been decoreated?
+		var inSwipeSelection = e.cellIndex >= 0 && (this.inIndirectSelectionMode() || this._inDndSelection) && !this.grid.edit.isEditRow(e.rowIndex);
+		inSwipeSelection && this._focusEndingCell(e.rowIndex, e.cellIndex);
+		this._finisheSelect();
+	},
+	
+	dokeyup: function(e){
+		// summay:
+		//		Event hanlder for key up event
+		// e: Event
+		//		Key up event
+		if(!e.shiftKey){
+			this._finisheSelect();
+		}
+	},
+	
+	_startSelection: function(rowIndex){
+		// summay:
+		//		Initilize parameters to start a new swipe selection
+		// rowIndex: Integer
+		//		Index of the start row
+		this.swipeStartRowIndex = this.swipeMinRowIndex = this.swipeMaxRowIndex = rowIndex;
+		this.toSelect = !this.widgetMap[this.view.id][rowIndex].attr('checked');
+	},
+	
+	_updateSelection: function(e, delta){
+		// summay:
+		//		Update row selections, fired during a swipe selection
+		// e: Event
+		//		Event of the current row,
+		// delta: Integer
+		//		Row index delta, used for swipe selection via Shift + Cursor
+		//		0: not via Shift + Cursor, -1 : Shift +  Up, 1 : Shift + Down
+		if(this.swipeStartRowIndex < 0){
+			return;
+		}
+		var byKey = delta !=0;//whether via Shift + Cursor
+		//this.defaultValue = false;
+		//index delta between the current row and starting row
+		var deltaRow = e.rowIndex - this.swipeStartRowIndex + delta;
+		deltaRow > 0 && (this.swipeMaxRowIndex < e.rowIndex + delta) && (this.swipeMaxRowIndex = e.rowIndex + delta)
+		deltaRow < 0 && (this.swipeMinRowIndex > e.rowIndex + delta) && (this.swipeMinRowIndex = e.rowIndex + delta);
+		// only when the min != max, there is a RANGE for selection
+		if (this.swipeMinRowIndex != this.swipeMaxRowIndex) {
+			for (var i in this.widgetMap[this.view.id]) {
+				var idx = new Number(i);
+				var inRange = (idx >= (deltaRow > 0 ? this.swipeStartRowIndex : e.rowIndex + delta) &&
+				idx <= (deltaRow > 0 ? e.rowIndex + delta : this.swipeStartRowIndex));
+				var outOfRange = (idx >= this.swipeMinRowIndex && idx <= this.swipeMaxRowIndex);
+				if (inRange && !(deltaRow == 0 && !this.toSelect)) {
+					(this.widgetMap[this.view.id][idx]).attr('checked', this.toSelect);
+					dojo.hitch(this.grid.selection, dojox.grid.Selection.prototype[this.toSelect ? 'addToSelection' : 'deselect'])(idx);
+				//}else if (outOfRange && (this.toSelect || !byKey)) {
+				}else if (outOfRange && !byKey) {
+					(this.widgetMap[this.view.id][idx]).attr('checked', !this.toSelect);
+					dojo.hitch(this.grid.selection, dojox.grid.Selection.prototype[!this.toSelect ? 'addToSelection' : 'deselect'])(idx);
+				}
+			}
+		}
+		this._fireSelectionChanged();
+	},
+	
+	swipeSelectionByKey: function(e, delta){
+		// summay:
+		//		Update row selections, fired when Shift + Cursor is used for swipe selection
+		//		See dojox.grid.enhanced._Events.onKeyDown
+		// e: Event
+		//		Event of the current row,
+		// delta: Integer
+		//		Row index delta, used for swipe selection via Shift + Cursor
+		//		-1 : Shift +  Up, 1 : Shift + Down
+		if(this.swipeStartRowIndex < 0) {
+			//A new swipe selection starts via Shift + Cursor			
+			this.swipeStartRowIndex = e.rowIndex;
+			if(delta > 0){//Shift + Down
+				this.swipeMaxRowIndex = e.rowIndex + delta;
+				this.swipeMinRowIndex = e.rowIndex;
+			}else{//Shift + UP
+				this.swipeMinRowIndex = e.rowIndex + delta;
+				this.swipeMaxRowIndex = e.rowIndex;	
+			}
+			this.toSelect = this.widgetMap[this.view.id][e.rowIndex].attr('checked');
+		}
+		this._updateSelection(e, delta);
+	},
+	
+	_finisheSelect: function(){
+		// summay:
+		//		Reset parameters to end a swipe selection
+		this.swipeStartRowIndex = -1;
+		this.swipeMinRowIndex = -1;
+		this.swipeMaxRowIndex = -1;
+		this.toSelect = false;
+	},
+	
+	inIndirectSelectionMode: function(){
+		// summay:
+		//		Reset parameters to end a swipe selection
+		// return: Boolean
+		//		Whether in swipe selection		
+		return this.swipeStartRowIndex >= 0;
+	},
+	
+	toggleAllSelection:function(checked){
+		// summay:
+		//		Toggle between select all and deselect all
+		// checked: Boolean
+		//		True - select all, False - deselect all
+		for (var i in this.widgetMap[this.view.id]){
+			var idx = new Number(i);
+			var widget = this.widgetMap[this.view.id][idx];
+			widget.attr('checked', checked);
+			dojo.hitch(this.grid.selection, dojox.grid.Selection.prototype[checked ? 'addToSelection' : 'deselect'])(idx);
+		}
+		!checked && this.grid.selection.deselectAll();
+		this.defaultValue = checked;
+		this.toggleAllTrigerred = true;
+		this._fireSelectionChanged();
+	}
+});
+
+dojo.declare("dojox.grid.cells.DijitSingleRowSelector", [dojox.grid.cells._Widget, dojox.grid.cells._SingleRowSelectorMixin], {
+	//	summary:
+	//		Indirect selection cell for single selection mode, using dijit.form.RadioButton
+
+	//widgetClass: Class
+	//		widget class that will be used for indirect selection cell(column)
+	widgetClass: dijit.form.RadioButton,
+	
+	constructor: function(){
+		dojo.subscribe(this.grid.rowSelectionChangedTopic, this, this._selectionChanged);
+		dojo.subscribe(this.grid.sortRowSelectionChangedTopic, this, this._selectionChanged);
+		this.grid.indirectSelector = this;
+	},
+
+	formatNode: function(inDatum, inRowIndex){
+		// summary:
+		//		Overwritten, see dojox.grid.cells._Widget
+		if(!this.widgetClass){
+			return inDatum;
+		}
+		!this.widgetMap[this.view.id] && (this.widgetMap[this.view.id] = {});
+		var currWidget = this.widgetMap[this.view.id][inRowIndex];
+		
+		var cellNode = this.getNode(inRowIndex);
+		if(!cellNode){
+			return;
+		}
+		var noAttachedWidget = !cellNode.firstChild || (currWidget && currWidget.domNode != cellNode.firstChild);
+		var inNode = noAttachedWidget && !cellNode.firstChild ? cellNode.appendChild(dojo.create('div')) : cellNode.firstChild;
+		
+		if(!currWidget || dojo.isIE){
+			!this.widgetProps && (this.widgetProps = {});
+			this.widgetProps.name = 'select_' + this.view.id;
+			var value = this.getDefaultValue(currWidget, inRowIndex);
+			this.widget = currWidget = this.createWidget(inNode, inDatum, inRowIndex);
+			this.widgetMap[this.view.id][inRowIndex] = currWidget;
+			this.widget.attr('checked', value);
+			dojo.connect(currWidget, '_onClick', dojo.hitch(this, function(e){
+				this._selectRow(e, inRowIndex);
+			}));
+			dojo.connect(currWidget.domNode, 'onkeyup', dojo.hitch(this, function(e){
+				e.keyCode == dojo.keys.SPACE && this._selectRow(e, inRowIndex, true);					
+			}));			
+			dojo.hitch(this.grid.selection, dojox.grid.Selection.prototype[value ? 'addToSelection' : 'deselect'])(inRowIndex);
+		}else{
+			this.widget = currWidget;
+			dojo.addClass(this.widget.domNode, 'dojoxGridWidgetHidden');
+			noAttachedWidget && this.attachWidget(inNode, inDatum, inRowIndex);
+		}
+		this.grid.rowHeightChanged(inRowIndex);
+		//this.focus(inRowIndex);
+		dojo.removeClass(this.widget.domNode, 'dojoxGridWidgetHidden');
+		(inRowIndex == this.grid.lastRenderingRowIdx) && dojo.removeClass(this.grid.domNode, 'dojoxGridSortInProgress');
+	},
+	
+	getDefaultValue: function(widget, inRowIndex){
+		// summary:
+		//		Get defaulst value for a widget
+		// widget: Object
+		//		Target widget
+		// inRowIndex: Integer
+		//		Row index of the widget			
+		// return: Boolean
+		//		True - checked | False - unchecked
+		var value = widget ? widget.attr('checked') : this.defaultValue;
+		if(!widget){
+			if(this.grid.nestedSorting){
+				value =  value || this.grid.getStoreSelectedValue(inRowIndex);	
+			}
+			value = this.grid.selection.isSelected(inRowIndex) ? true : value;
+		}
+		return value;
+	},
+	
+	focus: function(inRowIndex){
+		// summary:
+		//		Set focus to the widget in the target row
+		// inRowIndex: Integer
+		//		Target row			
+		var widget = this.widgetMap[this.view.id][inRowIndex];
+		if(widget){
+			setTimeout(dojo.hitch(widget, function(){
+				dojox.grid.util.fire(this, "focus");
+			}), 0);
+		}
+	},
+	
+	_focusEndingCell: function(inRowIndex, cellIndex){
+		// summary:
+		//		At the end of a swipe selection, set focus to the ending grid cell(inRowIndex,cellIndex)
+		// inRowIndex: Integer
+		//		Row index
+		// cellIndex: Integer
+		//		Column index							
+		var cell = this.grid.getCell(cellIndex);
+		this.grid.focus.setFocusCell(cell, inRowIndex);
+		this.grid.isDndSelectEnable && this.grid.focus._blurRowBar();
+	},
+
+	_selectRow: function(e, inRowIndex, preChange){
+		// summary:
+		//		Select the target row
+		// e: Event
+		//		Event fired on the target row		
+		// inRowIndex: Integer
+		//		Target row index
+		// preChange: Boolean
+		//		Whether triggered before the selection state change of the target row
+											
+		//if(preChange){ //fix seleting radio by space only works in Moz
+		if(dojo.isMoz && preChange){
+			return;
+		}
+		dojo.stopEvent(e);
+		//this.grid.selection.clickSelect(inRowIndex);
+		this._focusEndingCell(inRowIndex, 0);
+
+		var value = !this.grid.selection.selected[inRowIndex];
+		this.grid.selection.deselectAll();
+		this.grid.selection.addToSelection(inRowIndex);
+		
+		if (!dojo.isMoz) {//fix seleting radio by space only works in Moz
+			var widget = this.widgetMap[this.view.id][inRowIndex];
+			widget.attr('checked', true);
+		}
+		this._fireSelectionChanged();
+	},
+	
+	toggleRow: function(idx, value) {
+		// summary:
+		//		toggle selection of a single row
+		// idx: Integer
+		//		Target row index
+		// value: Boolean
+		//		True - checked | False - unchecked
+		var currSelectIdx = dojo.hitch(this.grid.selection, dojox.grid.Selection.prototype.getFirstSelected)();
+		if(idx != currSelectIdx && !value || idx == currSelectIdx && value){return;}
+		
+		var widget;			
+		if(idx != currSelectIdx && value && this.widgetMap[this.view.id] && (widget = this.widgetMap[this.view.id][currSelectIdx])){
+			//fix - current selected widget isn't unchecked
+			widget.attr('checked', false);			
+		}
+		this.grid.selection.deselectAll();
+		this._toggleSingleRow(idx, value);
+	},
+	
+	setDisabled: function(idx, disabled){
+		// summary:
+		//		toggle 'disabled' | 'enabled' of the selector widget in row idx
+		// idx: Integer
+		//		Row index
+		// disabled: Boolean
+		//		True - disabled | False - enabled
+		if(this.widgetMap[this.view.id]){
+			var widget = this.widgetMap[this.view.id][idx];
+			widget && widget.attr('disabled', disabled);
+		} 
+	}
+});
+
+dojo.declare("dojox.grid.cells.DijitMultipleRowSelector", [dojox.grid.cells.DijitSingleRowSelector, dojox.grid.cells._MultipleRowSelectorMixin], {
+	//summary:
+	//		Indirect selection cell for multiple or extended mode, using dijit.form.CheckBox
+
+	//widgetClass: Class
+	//		widget class that will be used for indirect selection cell(column)
+	widgetClass: dijit.form.CheckBox,
+	
+	constructor: function(){
+		dojo.connect(dojo.doc, 'onmouseup', this, 'domouseup');
+		this.grid.indirectSelector = this;
+	},
+	
+	_selectRow: function(e, inRowIndex, preChange){
+		// summary:
+		//		Select the target row or range or rows
+		// e: Event
+		//		Event fired on the target row		
+		// inRowIndex: Integer
+		//		Target row index
+		// preChange: Boolean
+		//		Whether triggered before the selection state change of the target row
+		
+		dojo.stopEvent(e);
+		this._focusEndingCell(inRowIndex, 0);
+		var delta = inRowIndex - this.lastClickRowIdx;
+		if(this.lastClickRowIdx >= 0 && !e.ctrlKey && !e.altKey && e.shiftKey){
+			var newValue = this.widgetMap[this.view.id][inRowIndex].attr('checked');
+			newValue = preChange ? !newValue : newValue;
+			for (var i in this.widgetMap[this.view.id]) {
+				var idx = new Number(i);
+				var inRange = (idx >= (delta > 0 ? this.lastClickRowIdx : inRowIndex) 
+				  			   && idx <= (delta > 0 ? inRowIndex :this.lastClickRowIdx));
+				if(inRange){
+					var widget = this.widgetMap[this.view.id][idx];
+					widget.attr('checked', newValue);
+					dojo.hitch(this.grid.selection, dojox.grid.Selection.prototype[newValue ? 'addToSelection' : 'deselect'])(idx);
+				}
+			}
+		}else{
+			//this.grid.selection.clickSelect(inRowIndex, true);	
+			var value = !this.grid.selection.selected[inRowIndex];
+			var widget = this.widgetMap[this.view.id][inRowIndex];
+			widget.attr('checked', value);
+			dojo.hitch(this.grid.selection, dojox.grid.Selection.prototype[value ? 'addToSelection' : 'deselect'])(inRowIndex);
+		}
+		//this.defaultValue = false;
+		this.lastClickRowIdx = inRowIndex;
+		this._fireSelectionChanged();
+	},
+
+	toggleRow: function(idx, value) {
+		// summary:
+		//		Overwritten
+		this._toggleSingleRow(idx, value);
+	}	
 });
-var _c=this.addCellDef(0,0,_8);
-_c.index=0;
-_7.unshift(_c);
-this.cells.unshift(_c);
-this.grid.rowSelectCell=_c;
-_2=true;
-}
-}));
-this.cellCount=this.cells.length;
-}});
-dojo.declare("dojox.grid.cells._SingleRowSelectorMixin",null,{alwaysEditing:true,widgetMap:{},widget:null,isRowSelector:true,defaultValue:false,formatEditing:function(_d,_e){
-this.needFormatNode(_d,_e);
-},_formatNode:function(_f,_10){
-this.formatNode(_f,_10);
-},setValue:function(_11,_12){
-return;
-},get:function(_13){
-var _14=this.widgetMap[this.view.id]?this.widgetMap[this.view.id][_13]:null;
-var _15=_14?_14.attr("checked"):"";
-return _15;
-},_fireSelectionChanged:function(){
-dojo.publish(this.grid.rowSelectionChangedTopic,[this]);
-},_selectionChanged:function(obj){
-if(obj==this){
-return;
-}
-for(var i in this.widgetMap[this.view.id]){
-var idx=new Number(i);
-var _16=this.widgetMap[this.view.id][idx];
-var _17=!!this.grid.selection.selected[idx];
-_16.attr("checked",_17);
-}
-this.defaultValue=false;
-this.grid.edit.isEditing()&&this.grid.edit.apply();
-},_toggleSingleRow:function(idx,_18){
-var _19;
-dojo.hitch(this.grid.selection,dojox.grid.Selection.prototype[_18?"addToSelection":"deselect"])(idx);
-if(this.widgetMap[this.view.id]&&(_19=this.widgetMap[this.view.id][idx])){
-_19.attr("checked",_18);
-}
-this._fireSelectionChanged();
-},inIndirectSelectionMode:function(){
-},toggleAllSelection:function(){
-}});
-dojo.declare("dojox.grid.cells._MultipleRowSelectorMixin",null,{swipeStartRowIndex:-1,swipeMinRowIndex:-1,swipeMaxRowIndex:-1,toSelect:false,lastClickRowIdx:-1,toggleAllTrigerred:false,_inDndSelection:false,domousedown:function(e){
-if(e.target.tagName=="INPUT"){
-this._startSelection(e.rowIndex);
-}
-dojo.stopEvent(e);
-},domousemove:function(e){
-this._updateSelection(e,0);
-},onRowMouseOver:function(e){
-this._updateSelection(e,0);
-if(this.grid.dnd){
-this._inDndSelection=this.grid.select.isInSelectingMode("row");
-}
-},domouseup:function(e){
-dojo.isIE&&this.view.content.decorateEvent(e);
-var _1a=e.cellIndex>=0&&(this.inIndirectSelectionMode()||this._inDndSelection)&&!this.grid.edit.isEditRow(e.rowIndex);
-_1a&&this._focusEndingCell(e.rowIndex,e.cellIndex);
-this._finisheSelect();
-},dokeyup:function(e){
-if(!e.shiftKey){
-this._finisheSelect();
-}
-},_startSelection:function(_1b){
-this.swipeStartRowIndex=this.swipeMinRowIndex=this.swipeMaxRowIndex=_1b;
-this.toSelect=!this.widgetMap[this.view.id][_1b].attr("checked");
-},_updateSelection:function(e,_1c){
-if(this.swipeStartRowIndex<0){
-return;
-}
-var _1d=_1c!=0;
-var _1e=e.rowIndex-this.swipeStartRowIndex+_1c;
-_1e>0&&(this.swipeMaxRowIndex<e.rowIndex+_1c)&&(this.swipeMaxRowIndex=e.rowIndex+_1c);
-_1e<0&&(this.swipeMinRowIndex>e.rowIndex+_1c)&&(this.swipeMinRowIndex=e.rowIndex+_1c);
-if(this.swipeMinRowIndex!=this.swipeMaxRowIndex){
-for(var i in this.widgetMap[this.view.id]){
-var idx=new Number(i);
-var _1f=(idx>=(_1e>0?this.swipeStartRowIndex:e.rowIndex+_1c)&&idx<=(_1e>0?e.rowIndex+_1c:this.swipeStartRowIndex));
-var _20=(idx>=this.swipeMinRowIndex&&idx<=this.swipeMaxRowIndex);
-if(_1f&&!(_1e==0&&!this.toSelect)){
-(this.widgetMap[this.view.id][idx]).attr("checked",this.toSelect);
-dojo.hitch(this.grid.selection,dojox.grid.Selection.prototype[this.toSelect?"addToSelection":"deselect"])(idx);
-}else{
-if(_20&&!_1d){
-(this.widgetMap[this.view.id][idx]).attr("checked",!this.toSelect);
-dojo.hitch(this.grid.selection,dojox.grid.Selection.prototype[!this.toSelect?"addToSelection":"deselect"])(idx);
-}
-}
-}
-}
-this._fireSelectionChanged();
-},swipeSelectionByKey:function(e,_21){
-if(this.swipeStartRowIndex<0){
-this.swipeStartRowIndex=e.rowIndex;
-if(_21>0){
-this.swipeMaxRowIndex=e.rowIndex+_21;
-this.swipeMinRowIndex=e.rowIndex;
-}else{
-this.swipeMinRowIndex=e.rowIndex+_21;
-this.swipeMaxRowIndex=e.rowIndex;
-}
-this.toSelect=this.widgetMap[this.view.id][e.rowIndex].attr("checked");
-}
-this._updateSelection(e,_21);
-},_finisheSelect:function(){
-this.swipeStartRowIndex=-1;
-this.swipeMinRowIndex=-1;
-this.swipeMaxRowIndex=-1;
-this.toSelect=false;
-},inIndirectSelectionMode:function(){
-return this.swipeStartRowIndex>=0;
-},toggleAllSelection:function(_22){
-for(var i in this.widgetMap[this.view.id]){
-var idx=new Number(i);
-var _23=this.widgetMap[this.view.id][idx];
-_23.attr("checked",_22);
-dojo.hitch(this.grid.selection,dojox.grid.Selection.prototype[_22?"addToSelection":"deselect"])(idx);
-}
-!_22&&this.grid.selection.deselectAll();
-this.defaultValue=_22;
-this.toggleAllTrigerred=true;
-this._fireSelectionChanged();
-}});
-dojo.declare("dojox.grid.cells.DijitSingleRowSelector",[dojox.grid.cells._Widget,dojox.grid.cells._SingleRowSelectorMixin],{widgetClass:dijit.form.RadioButton,constructor:function(){
-dojo.subscribe(this.grid.rowSelectionChangedTopic,this,this._selectionChanged);
-dojo.subscribe(this.grid.sortRowSelectionChangedTopic,this,this._selectionChanged);
-this.grid.indirectSelector=this;
-},formatNode:function(_24,_25){
-if(!this.widgetClass){
-return _24;
-}
-!this.widgetMap[this.view.id]&&(this.widgetMap[this.view.id]={});
-var _26=this.widgetMap[this.view.id][_25];
-var _27=this.getNode(_25);
-if(!_27){
-return;
-}
-var _28=!_27.firstChild||(_26&&_26.domNode!=_27.firstChild);
-var _29=_28&&!_27.firstChild?_27.appendChild(dojo.create("div")):_27.firstChild;
-if(!_26||dojo.isIE){
-!this.widgetProps&&(this.widgetProps={});
-this.widgetProps.name="select_"+this.view.id;
-var _2a=this.getDefaultValue(_26,_25);
-this.widget=_26=this.createWidget(_29,_24,_25);
-this.widgetMap[this.view.id][_25]=_26;
-this.widget.attr("checked",_2a);
-dojo.connect(_26,"_onClick",dojo.hitch(this,function(e){
-this._selectRow(e,_25);
-}));
-dojo.connect(_26.domNode,"onkeyup",dojo.hitch(this,function(e){
-e.keyCode==dojo.keys.SPACE&&this._selectRow(e,_25,true);
-}));
-dojo.hitch(this.grid.selection,dojox.grid.Selection.prototype[_2a?"addToSelection":"deselect"])(_25);
-}else{
-this.widget=_26;
-dojo.addClass(this.widget.domNode,"dojoxGridWidgetHidden");
-_28&&this.attachWidget(_29,_24,_25);
-}
-this.grid.rowHeightChanged(_25);
-dojo.removeClass(this.widget.domNode,"dojoxGridWidgetHidden");
-(_25==this.grid.lastRenderingRowIdx)&&dojo.removeClass(this.grid.domNode,"dojoxGridSortInProgress");
-},getDefaultValue:function(_2b,_2c){
-var _2d=_2b?_2b.attr("checked"):this.defaultValue;
-if(!_2b){
-if(this.grid.nestedSorting){
-_2d=_2d||this.grid.getStoreSelectedValue(_2c);
-}
-_2d=this.grid.selection.isSelected(_2c)?true:_2d;
-}
-return _2d;
-},focus:function(_2e){
-var _2f=this.widgetMap[this.view.id][_2e];
-if(_2f){
-setTimeout(dojo.hitch(_2f,function(){
-dojox.grid.util.fire(this,"focus");
-}),0);
-}
-},_focusEndingCell:function(_30,_31){
-var _32=this.grid.getCell(_31);
-this.grid.focus.setFocusCell(_32,_30);
-this.grid.isDndSelectEnable&&this.grid.focus._blurRowBar();
-},_selectRow:function(e,_33,_34){
-if(dojo.isMoz&&_34){
-return;
-}
-dojo.stopEvent(e);
-this._focusEndingCell(_33,0);
-var _35=!this.grid.selection.selected[_33];
-this.grid.selection.deselectAll();
-this.grid.selection.addToSelection(_33);
-if(!dojo.isMoz){
-var _36=this.widgetMap[this.view.id][_33];
-_36.attr("checked",true);
-}
-this._fireSelectionChanged();
-},toggleRow:function(idx,_37){
-var _38=dojo.hitch(this.grid.selection,dojox.grid.Selection.prototype.getFirstSelected)();
-if(idx!=_38&&!_37||idx==_38&&_37){
-return;
-}
-var _39;
-if(idx!=_38&&_37&&this.widgetMap[this.view.id]&&(_39=this.widgetMap[this.view.id][_38])){
-_39.attr("checked",false);
-}
-this.grid.selection.deselectAll();
-this._toggleSingleRow(idx,_37);
-},setDisabled:function(idx,_3a){
-if(this.widgetMap[this.view.id]){
-var _3b=this.widgetMap[this.view.id][idx];
-_3b&&_3b.attr("disabled",_3a);
-}
-}});
-dojo.declare("dojox.grid.cells.DijitMultipleRowSelector",[dojox.grid.cells.DijitSingleRowSelector,dojox.grid.cells._MultipleRowSelectorMixin],{widgetClass:dijit.form.CheckBox,constructor:function(){
-dojo.connect(dojo.doc,"onmouseup",this,"domouseup");
-this.grid.indirectSelector=this;
-},_selectRow:function(e,_3c,_3d){
-dojo.stopEvent(e);
-this._focusEndingCell(_3c,0);
-var _3e=_3c-this.lastClickRowIdx;
-if(this.lastClickRowIdx>=0&&!e.ctrlKey&&!e.altKey&&e.shiftKey){
-var _3f=this.widgetMap[this.view.id][_3c].attr("checked");
-_3f=_3d?!_3f:_3f;
-for(var i in this.widgetMap[this.view.id]){
-var idx=new Number(i);
-var _40=(idx>=(_3e>0?this.lastClickRowIdx:_3c)&&idx<=(_3e>0?_3c:this.lastClickRowIdx));
-if(_40){
-var _41=this.widgetMap[this.view.id][idx];
-_41.attr("checked",_3f);
-dojo.hitch(this.grid.selection,dojox.grid.Selection.prototype[_3f?"addToSelection":"deselect"])(idx);
-}
-}
-}else{
-var _42=!this.grid.selection.selected[_3c];
-var _41=this.widgetMap[this.view.id][_3c];
-_41.attr("checked",_42);
-dojo.hitch(this.grid.selection,dojox.grid.Selection.prototype[_42?"addToSelection":"deselect"])(_3c);
-}
-this.lastClickRowIdx=_3c;
-this._fireSelectionChanged();
-},toggleRow:function(idx,_43){
-this._toggleSingleRow(idx,_43);
-}});
-}
diff --git a/dojox/grid/enhanced/plugins/Menu.js b/dojox/grid/enhanced/plugins/Menu.js
index 4b6c903..fb9f363 100644
--- a/dojox/grid/enhanced/plugins/Menu.js
+++ b/dojox/grid/enhanced/plugins/Menu.js
@@ -1,70 +1,131 @@
-/*
-	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
-*/
+dojo.provide("dojox.grid.enhanced.plugins.Menu");
 
+dojo.declare("dojox.grid.enhanced.plugins.Menu", null, {
+	//	summary:
+	//		 Provides context menu support, including header menu, row menu, cell menu and selected region menu
+	// example:
+	// 		 <div dojoType="dojox.grid.EnhancedGrid" 
+	//			  plugins="{menus:{headerMenu:"headerMenuId", rowMenu:"rowMenuId", cellMenu:"cellMenuId", 
+	//							   selectedRegionMenu:"selectedRegionMenuId"}}" ...>
+	//		</div>
 
-if(!dojo._hasResource["dojox.grid.enhanced.plugins.Menu"]){
-dojo._hasResource["dojox.grid.enhanced.plugins.Menu"]=true;
-dojo.provide("dojox.grid.enhanced.plugins.Menu");
-dojo.declare("dojox.grid.enhanced.plugins.Menu",null,{constructor:function(_1){
-_1.mixin(_1,this);
-},_initMenus:function(){
-var _2=this.menuContainer;
-!this.headerMenu&&(this.headerMenu=this._getMenuWidget(this.menus["headerMenu"]));
-!this.rowMenu&&(this.rowMenu=this._getMenuWidget(this.menus["rowMenu"]));
-!this.cellMenu&&(this.cellMenu=this._getMenuWidget(this.menus["cellMenu"]));
-!this.selectedRegionMenu&&(this.selectedRegionMenu=this._getMenuWidget(this.menus["selectedRegionMenu"]));
-this.headerMenu&&this.attr("headerMenu",this.headerMenu)&&this.setupHeaderMenu();
-this.rowMenu&&this.attr("rowMenu",this.rowMenu);
-this.cellMenu&&this.attr("cellMenu",this.cellMenu);
-this.isDndSelectEnable&&this.selectedRegionMenu&&dojo.connect(this.select,"setDrugCoverDivs",dojo.hitch(this,this._bindDnDSelectEvent));
-},_getMenuWidget:function(_3){
-if(!_3){
-return;
-}
-var _4=dijit.byId(_3);
-if(!_4){
-throw new Error("Menu '"+_3+"' not existed");
-}
-return _4;
-},_bindDnDSelectEvent:function(){
-dojo.forEach(this.select.coverDIVs,dojo.hitch(this,function(_5){
-this.selectedRegionMenu.bindDomNode(_5);
-dojo.connect(_5,"contextmenu",dojo.hitch(this,function(e){
-dojo.mixin(e,this.select.getSelectedRegionInfo());
-this.onSelectedRegionContextMenu(e);
-}));
-}));
-},_setRowMenuAttr:function(_6){
-this._setRowCellMenuAttr(_6,"rowMenu");
-},_setCellMenuAttr:function(_7){
-this._setRowCellMenuAttr(_7,"cellMenu");
-},_setRowCellMenuAttr:function(_8,_9){
-if(!_8){
-return;
-}
-if(this[_9]){
-this[_9].unBindDomNode(this.domNode);
-}
-this[_9]=_8;
-this[_9].bindDomNode(this.domNode);
-},showRowCellMenu:function(e){
-var _a=e.sourceView.declaredClass=="dojox.grid._RowSelector";
-if(this.rowMenu&&(!e.cell||this.selection.isSelected(e.rowIndex))){
-this.rowMenu._openMyself(e);
-dojo.stopEvent(e);
-return;
-}
-if(_a||e.cell&&e.cell.isRowSelector){
-dojo.stopEvent(e);
-return;
-}
-if(this.isDndSelectEnable){
-this.select.cellClick(e.cellIndex,e.rowIndex);
-this.focus.setFocusCell(e.cell,e.rowIndex);
-}
-this.cellMenu&&this.cellMenu._openMyself(e);
-}});
-}
+	constructor: function(inGrid){
+		inGrid.mixin(inGrid, this);
+	},
+	
+	_initMenus: function(){
+		//summary:
+		//		Initilize all the required menus
+		var wrapper = this.menuContainer;
+		!this.headerMenu && (this.headerMenu = this._getMenuWidget(this.menus['headerMenu']));		
+		!this.rowMenu && (this.rowMenu = this._getMenuWidget(this.menus['rowMenu']));
+		!this.cellMenu && (this.cellMenu = this._getMenuWidget(this.menus['cellMenu']));
+		!this.selectedRegionMenu && (this.selectedRegionMenu = this._getMenuWidget(this.menus['selectedRegionMenu']));
+		this.headerMenu && this.set('headerMenu', this.headerMenu) && this.setupHeaderMenu();
+		this.rowMenu && this.set('rowMenu', this.rowMenu);
+		this.cellMenu && this.set('cellMenu', this.cellMenu);
+		this.isDndSelectEnable && this.selectedRegionMenu && dojo.connect(this.select, 'setDrugCoverDivs', dojo.hitch(this, this._bindDnDSelectEvent));
+	},
+	
+	_getMenuWidget: function(menuId){
+		//summary:
+		//		Fetch the required menu widget(should already been created)
+		//menuId: String
+		//		Id of the target menu widget
+		//return: Widget
+		//		Target menu widget
+		if(!menuId){
+			return;
+		}
+		var menu = dijit.byId(menuId);
+		if(!menu){
+			throw new Error("Menu '" + menuId +"' not existed");	
+		}
+		return menu;
+	},
+
+	_bindDnDSelectEvent: function(){
+		//summary:
+		//		Hook callback to DnD, so othat appropriate menu will be shown on selected regions	
+		dojo.forEach(this.select.coverDIVs, dojo.hitch(this, function(cover){
+			//this.selectedRegionMenu.unBindDomNode(this.domNode);
+			this.selectedRegionMenu.bindDomNode(cover);
+			dojo.connect(cover, "contextmenu", dojo.hitch(this, function(e){
+				dojo.mixin(e, this.select.getSelectedRegionInfo());
+				this.onSelectedRegionContextMenu(e);
+			}));
+		}));
+	},
+	
+	_setRowMenuAttr: function(menu){
+		//summary:
+		//		Set row menu widget
+		//menu: Widget - dijit.Menu
+		//		Row menu widget
+		this._setRowCellMenuAttr(menu, 'rowMenu');
+	},
+	
+	_setCellMenuAttr: function(menu){
+		//summary:
+		//		Set cell menu widget
+		//menu: Widget - dijit.Menu
+		//		Cell menu widget		
+		this._setRowCellMenuAttr(menu, 'cellMenu');
+	},
+	
+	_setRowCellMenuAttr: function(menu, menuType){
+		//summary:
+		//		Bind menus to Grid
+		//menu: Widget - dijit.Menu
+		//		Menu widget	
+		//menuType: String
+		//		Menu type
+		if(!menu){ return; }
+		if(this[menuType]){
+			this[menuType].unBindDomNode(this.domNode);
+		}
+		this[menuType] = menu;
+		this[menuType].bindDomNode(this.domNode);
+	},
+
+	// TODO: this code is not accessible.  Shift-F10 won't open a menu.  (I think
+	// this function never even gets called.)
+	showRowCellMenu: function(e){
+		//summary:
+		//		Show row or cell menus
+		//e: Event
+		//		Fired from dojox.grid.enhanced._Events.onRowContextMenu
+		var inRowSelectorView = e.sourceView.declaredClass == 'dojox.grid._RowSelector';
+		// !e.cell means the cell is in the rowbar.
+		// this.selection.isSelected(e.rowIndex) should remove?
+		//if(this.rowMenu && (!e.cell || this.selection.isSelected(e.rowIndex)) && (!this.focus.cell || this.focus.cell != e.cell)){
+		if(this.rowMenu && (!e.cell || this.selection.isSelected(e.rowIndex))){
+			this.rowMenu._openMyself({
+				target: e.target,
+				coords: "pageX" in e ? {
+					x: e.pageX,
+					y: e.pageY
+				} : null
+			});
+			dojo.stopEvent(e);
+			return;
+		}
+		if(inRowSelectorView || e.cell && e.cell.isRowSelector){
+			dojo.stopEvent(e);
+			return;	
+		}
+		if(this.isDndSelectEnable) {
+			this.select.cellClick(e.cellIndex, e.rowIndex);
+			this.focus.setFocusCell(e.cell, e.rowIndex);
+		}
+		if(this.cellMenu){
+			this.cellMenu._openMyself({
+				target: e.target,
+				coords: "pageX" in e ? {
+					x: e.pageX,
+					y: e.pageY
+				} : null
+			});
+		}
+	}
+});
diff --git a/dojox/grid/enhanced/plugins/NestedSorting.js b/dojox/grid/enhanced/plugins/NestedSorting.js
index 87036da..ec4e62a 100644
--- a/dojox/grid/enhanced/plugins/NestedSorting.js
+++ b/dojox/grid/enhanced/plugins/NestedSorting.js
@@ -1,730 +1,1308 @@
-/*
-	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
-*/
+dojo.provide("dojox.grid.enhanced.plugins.NestedSorting");
 
+dojo.declare("dojox.grid.enhanced.plugins.NestedSorting", null, {
+	//	summary:
+	//		 Provides nested sorting feature
+	// example:
+	// 		 <div dojoType="dojox.grid.EnhancedGrid" plugins="{nestedSorting: true}" ...></div>
 
-if(!dojo._hasResource["dojox.grid.enhanced.plugins.NestedSorting"]){
-dojo._hasResource["dojox.grid.enhanced.plugins.NestedSorting"]=true;
-dojo.provide("dojox.grid.enhanced.plugins.NestedSorting");
-dojo.declare("dojox.grid.enhanced.plugins.NestedSorting",null,{sortAttrs:[],_unarySortCell:{},_minColWidth:63,_widthDelta:23,_minColWidthUpdated:false,_sortTipMap:{},_overResizeWidth:3,storeItemSelected:"storeItemSelectedAttr",exceptionalSelectedItems:[],_a11yText:{"dojoxGridDescending":"▾","dojoxGridAscending":"▴","dojoxGridAscendingTip":"۸","dojoxGridDescendingTip":"۷","dojoxGridUnsortedTip":"x"},constructor:function(_1){
-_1.mixin(_1,this);
-dojo.forEach(_1.views.views,function(_2){
-dojo.connect(_2,"renderHeader",dojo.hitch(_2,_1._initSelectCols));
-dojo.connect(_2.header,"domousemove",_2.grid,"_sychronizeResize");
-});
-_1.getSortProps=_1._getDsSortAttrs;
-dojo.connect(_1,"_onFetchComplete",_1,"updateNewRowSelection");
-if(_1.indirectSelection&&_1.rowSelectCell.toggleAllSelection){
-dojo.connect(_1.rowSelectCell,"toggleAllSelection",_1,"allSelectionToggled");
-}
-dojo.subscribe(_1.rowSelectionChangedTopic,_1,_1._selectionChanged);
-_1.focus.destroy();
-_1.focus=new dojox.grid.enhanced.plugins._NestedSortingFocusManager(_1);
-dojo.connect(_1.views,"render",_1,"initAriaInfo");
-},setSortIndex:function(_3,_4,e){
-if(!this.nestedSorting){
-this.inherited(arguments);
-}else{
-if(this.dnd&&!this.dndRowConn){
-this.dndRowConn=dojo.connect(this.select,"startMoveRows",dojo.hitch(this,this.clearSort));
-}
-this.retainLastRowSelection();
-this.inSorting=true;
-this._toggleProgressTip(true,e);
-this._updateSortAttrs(e,_4);
-this.focus.addSortFocus(e);
-if(this.canSort()){
-this.sort();
-this.edit.info={};
-this.update();
-}
-this._toggleProgressTip(false,e);
-this.inSorting=false;
-}
-},_updateSortAttrs:function(e,_5){
-var _6=false;
-var _7=!!e.unarySortChoice;
-if(_7){
-var _8=this.getCellSortInfo(e.cell);
-var _9=(this.sortAttrs.length>0&&_8["sortPos"]!=1)?_8["unarySortAsc"]:this._getNewSortState(_8["unarySortAsc"]);
-if(_9&&_9!=0){
-this.sortAttrs=[{attr:e.cell.field,asc:_9,cell:e.cell,cellNode:e.cellNode}];
-this._unarySortCell={cell:e.cell,node:e.cellNode};
-}else{
-this.sortAttrs=[];
-this._unarySortCell=null;
-}
-}else{
-this.setCellSortInfo(e,_5);
-}
-},getCellSortInfo:function(_a){
-if(!_a){
-return false;
-}
-var _b=null;
-var _c=this.sortAttrs;
-dojo.forEach(_c,function(_d,_e,_f){
-if(_d&&_d["attr"]==_a.field&&_d["cell"]==_a){
-_b={unarySortAsc:_f[0]?_f[0]["asc"]:undefined,nestedSortAsc:_d["asc"],sortPos:_e+1};
-}
-});
-return _b?_b:{unarySortAsc:_c&&_c[0]?_c[0]["asc"]:undefined,nestedSortAsc:undefined,sortPos:-1};
-},setCellSortInfo:function(e,_10){
-var _11=e.cell;
-var _12=false;
-var _13=[];
-var _14=this.sortAttrs;
-dojo.forEach(_14,dojo.hitch(this,function(_15,_16){
-if(_15&&_15["attr"]==_11.field){
-var si=_10?_10:this._getNewSortState(_15["asc"]);
-if(si==1||si==-1){
-_15["asc"]=si;
-}else{
-if(si==0){
-_13.push(_16);
-}else{
-throw new Exception("Illegal nested sorting status - "+si);
-}
-}
-_12=true;
-}
-}));
-var _17=0;
-dojo.forEach(_13,function(_18){
-_14.splice((_18-_17++),1);
-});
-if(!_12){
-var si=_10?_10:1;
-if(si!=0){
-_14.push({attr:_11.field,asc:si,cell:e.cell,cellNode:e.cellNode});
-}
-}
-if(_13.length>0){
-this._unarySortCell={cell:_14[0]["cell"],node:_14[0]["cellNode"]};
-}
-},_getDsSortAttrs:function(){
-var _19=[];
-var si=null;
-dojo.forEach(this.sortAttrs,function(_1a){
-if(_1a&&(_1a["asc"]==1||_1a["asc"]==-1)){
-_19.push({attribute:_1a["attr"],descending:(_1a["asc"]==-1)});
-}
-});
-return _19.length>0?_19:null;
-},_getNewSortState:function(si){
-return si?(si==1?-1:(si==-1?0:1)):1;
-},sortStateInt2Str:function(si){
-if(!si){
-return "Unsorted";
-}
-switch(si){
-case 1:
-return "Ascending";
-case -1:
-return "Descending";
-default:
-return "Unsorted";
-}
-},clearSort:function(){
-dojo.query("[id*='Sort']",this.viewsHeaderNode).forEach(function(_1b){
-dojo.addClass(_1b,"dojoxGridUnsorted");
-});
-this.sortAttrs=[];
-this.focus.clearHeaderFocus();
-},_getNestedSortHeaderContent:function(_1c){
-var n=_1c.name||_1c.grid.getCellName(_1c);
-if(_1c.grid.pluginMgr.isFixedCell(_1c)){
-return ["<div class=\"dojoxGridCellContent\">",n,"</div>"].join("");
-}
-var _1d=_1c.grid.getCellSortInfo(_1c);
-var _1e=_1c.grid.sortAttrs;
-var _1f=(_1e&&_1e.length>1&&_1d["sortPos"]>=1);
-var _20=(_1e&&_1e.length==1&&_1d["sortPos"]==1);
-var _21=_1c.grid;
-var ret=["<div class=\"dojoxGridSortRoot\">","<div class=\"dojoxGridSortWrapper\">","<span id=\"selectSortSeparator"+_1c.index+"\" class=\"dojoxGridSortSeparatorOff\"></span>","<span class=\"dojoxGridNestedSortWrapper\" tabindex=\"-1\">","<span id=\""+_1c.view.id+"SortPos"+_1c.index+"\" class=\"dojoxGridSortPos "+(_1f?"":"dojoxGridSortPosOff")+"\">"+(_1f?_1d["sortPos"]:"")+"</span>","<span id=\"nestedSortCol"+_1c.index+"\" class=\"dojoxGridSort dojoxGridNestedSort "+(_1f?("dojoxGrid"+_21 [...]
-return ret.join("");
-},addHoverSortTip:function(e){
-this._sortTipMap[e.cellIndex]=true;
-var _22=this.getCellSortInfo(e.cell);
-if(!_22){
-return;
-}
-var _23=this._getCellElements(e.cellNode);
-if(!_23){
-return;
-}
-var _24=this.sortAttrs;
-var _25=!_24||_24.length<1;
-var _26=(_24&&_24.length==1&&_22["sortPos"]==1);
-dojo.addClass(_23["selectSortSeparator"],"dojoxGridSortSeparatorOn");
-if(_25||_26){
-this._addHoverUnarySortTip(_23,_22,e);
-}else{
-this._addHoverNestedSortTip(_23,_22,e);
-this.updateMinColWidth(_23["nestedSortPos"]);
-}
-var _27=_23["selectRegion"];
-this._fixSelectRegion(_27);
-if(!dijit.hasWaiRole(_27)){
-dijit.setWaiState(_27,"label","Column "+(e.cellIndex+1)+" "+e.cell.field);
-}
-this._toggleHighlight(e.sourceView,e);
-this.focus._updateFocusBorder();
-},_addHoverUnarySortTip:function(_28,_29,e){
-dojo.addClass(_28["nestedSortWrapper"],"dojoxGridUnsorted");
-var _2a=this.sortStateInt2Str(this._getNewSortState(_29["unarySortAsc"]));
-dijit.setWaiState(_28["unarySortWrapper"],"label","Column "+(e.cellIndex+1)+" "+e.cell.field+" - Choose "+_2a.toLowerCase()+" single sort");
-var _2b="dojoxGrid"+_2a+"Tip";
-dojo.addClass(_28["unarySortChoice"],_2b);
-_28["unarySortChoice"].innerHTML=this._a11yText[_2b];
-this._addTipInfo(_28["unarySortWrapper"],this._composeSortTip(_2a,"singleSort"));
-},_addHoverNestedSortTip:function(_2c,_2d,e){
-var _2e=_2c["nestedSortPos"];
-var _2f=_2c["unarySortWrapper"];
-var _30=_2c["nestedSortWrapper"];
-var _31=this.sortAttrs;
-dojo.removeClass(_30,"dojoxGridUnsorted");
-var _32=this.sortStateInt2Str(this._getNewSortState(_2d["nestedSortAsc"]));
-dijit.setWaiState(_30,"label","Column "+(e.cellIndex+1)+" "+e.cell.field+" - Choose "+_32.toLowerCase()+" nested sort");
-var _33="dojoxGrid"+_32+"Tip";
-this._addA11yInfo(_2c["nestedSortChoice"],_33);
-this._addTipInfo(_30,this._composeSortTip(_32,"nestedSort"));
-_32=this.sortStateInt2Str(_2d["unarySortAsc"]);
-dijit.setWaiState(_2f,"label","Column "+(e.cellIndex+1)+" "+e.cell.field+" - Choose "+_32.toLowerCase()+" single sort");
-_33="dojoxGrid"+_32+"Tip";
-this._addA11yInfo(_2c["unarySortChoice"],_33);
-this._addTipInfo(_2f,this._composeSortTip(_32,"singleSort"));
-dojo.addClass(_2c["sortSeparator"],"dojoxGridSortSeparatorOn");
-dojo.removeClass(_2e,"dojoxGridSortPosOff");
-if(_2d["sortPos"]<1){
-_2e.innerHTML=(_31?_31.length:0)+1;
-if(!this._unarySortInFocus()&&_31&&_31.length==1){
-var _34=this._getUnaryNode();
-_34.innerHTML="1";
-dojo.removeClass(_34,"dojoxGridSortPosOff");
-dojo.removeClass(_34.parentNode,"dojoxGridUnsorted");
-this._fixSelectRegion(this._getCellElements(_34)["selectRegion"]);
-}
-}
-},_unarySortInFocus:function(){
-return this._unarySortCell.cell&&this.focus.headerCellInFocus(this._unarySortCell.cell.index);
-},_composeSortTip:function(_35,_36){
-_35=_35.toLowerCase();
-if(_35=="unsorted"){
-return this._nls[_35];
-}else{
-var tip=dojo.string.substitute(this._nls["sortingState"],[this._nls[_36],this._nls[_35]]);
-return tip;
-}
-},_addTipInfo:function(_37,_38){
-dojo.attr(_37,"title",_38);
-dojo.query("span",_37).forEach(function(n){
-dojo.attr(n,"title",_38);
-});
-},_addA11yInfo:function(_39,_3a){
-dojo.addClass(_39,_3a);
-_39.innerHTML=this._a11yText[_3a];
-},removeHoverSortTip:function(e){
-if(!this._sortTipMap[e.cellIndex]){
-return;
-}
-var _3b=this.getCellSortInfo(e.cell);
-if(!_3b){
-return;
-}
-var _3c=this._getCellElements(e.cellNode);
-if(!_3c){
-return;
-}
-var _3d=_3c.nestedSortChoice;
-var _3e=_3c.unarySortChoice;
-var _3f=_3c.unarySortWrapper;
-var _40=_3c.nestedSortWrapper;
-this._toggleHighlight(e.sourceView,e,true);
-function _41(_42){
-dojo.forEach(_42,function(_43){
-var _44=dojo.trim((" "+_43["className"]+" ").replace(/\sdojoxGrid\w+Tip\s/g," "));
-if(_43["className"]!=_44){
-_43["className"]=_44;
-}
-});
-};
-_41([_3d,_3e]);
-_3e.innerHTML=this._a11yText["dojoxGrid"+this.sortStateInt2Str(_3b["unarySortAsc"])]||".";
-_3d.innerHTML=this._a11yText["dojoxGrid"+this.sortStateInt2Str(_3b["nestedSortAsc"])]||".";
-dojo.removeClass(_3c["selectSortSeparator"],"dojoxGridSortSeparatorOn");
-dojo.removeClass(_3c["sortSeparator"],"dojoxGridSortSeparatorOn");
-if(_3b["sortPos"]==1&&this.focus.isNavHeader()&&!this.focus.headerCellInFocus(e.cellIndex)){
-dojo.removeClass(_3c["nestedSortWrapper"],"dojoxGridUnsorted");
-}
-var _45=this.sortAttrs;
-if(!isNaN(_3b["sortPos"])&&_3b["sortPos"]<1){
-_3c["nestedSortPos"].innerHTML="";
-dojo.addClass(_40,"dojoxGridUnsorted");
-if(!this.focus._focusBorderBox&&_45&&_45.length==1){
-var _46=this._getUnaryNode();
-_46.innerHTML="";
-dojo.addClass(_46,"dojoxGridSortPosOff");
-this._fixSelectRegion(this._getCellElements(_46)["selectRegion"]);
-}
-}
-this._fixSelectRegion(_3c["selectRegion"]);
-dijit.removeWaiState(_40,"label");
-dijit.removeWaiState(_3f,"label");
-if(_3b["sortPos"]>=0){
-var _47=(_45.length==1);
-var _48=_47?_3f:_40;
-this._setSortRegionWaiState(_47,e.cellIndex,e.cell.field,_3b["sortPos"],_48);
-}
-this.focus._updateFocusBorder();
-this._sortTipMap[e.cellIndex]=false;
-},_getUnaryNode:function(){
-for(var i=0;i<this.views.views.length;i++){
-var n=dojo.byId(this.views.views[i].id+"SortPos"+this._unarySortCell.cell.index);
-if(n){
-return n;
-}
-}
-},_fixSelectRegion:function(_49){
-var _4a=_49.previousSibling;
-var _4b=dojo.contentBox(_49.parentNode);
-var _4c=dojo.marginBox(_49);
-var _4d=dojo.marginBox(_4a);
-if(dojo.isIE&&!dojo._isBodyLtr()){
-var w=0;
-dojo.forEach(_4a.childNodes,function(_4e){
-w+=dojo.marginBox(_4e).w;
-});
-_4d.w=w;
-_4d.l=(_4d.t=0);
-dojo.marginBox(_4a,_4d);
-}
-if(_4c.w!=(_4b.w-_4d.w)){
-_4c.w=_4b.w-_4d.w;
-if(!dojo.isWebKit){
-dojo.marginBox(_49,_4c);
-}else{
-_4c.h=dojo.contentBox(_4b).h;
-dojo.style(_49,"width",(_4c.w-4)+"px");
-}
-}
-},updateMinColWidth:function(_4f){
-if(this._minColWidthUpdated){
-return;
-}
-var _50=_4f.innerHTML;
-_4f.innerHTML=dojo.query(".dojoxGridSortWrapper",this.viewsHeaderNode).length;
-var _51=_4f.parentNode.parentNode;
-this._minColWidth=dojo.marginBox(_51).w+this._widthDelta;
-_4f.innerHTML=_50;
-this._minColWidthUpdated=true;
-},getMinColWidth:function(){
-return this._minColWidth;
-},_initSelectCols:function(){
-var _52=dojo.query(".dojoxGridHeaderCellSelectRegion",this.headerContentNode);
-var _53=dojo.query(".dojoxGridUnarySortWrapper",this.headerContentNode);
-var _54=dojo.query(".dojoxGridNestedSortWrapper",this.headerContentNode);
-_52.concat(_53).concat(_54).forEach(function(_55){
-dojo.connect(_55,"onmousemove",dojo.hitch(this.grid,this.grid._toggleHighlight,this));
-dojo.connect(_55,"onmouseout",dojo.hitch(this.grid,this.grid._removeActiveState));
-},this);
-this.grid._fixHeaderCellStyle(_52,this);
-if(dojo.isIE&&!dojo._isBodyLtr()){
-this.grid._fixAllSelectRegion();
-}
-},_fixHeaderCellStyle:function(_56,_57){
-dojo.forEach(_56,dojo.hitch(this,function(_58){
-var _59=dojo.marginBox(_58),_5a=this._getCellElements(_58),_5b=_5a.sortWrapper;
-_5b.style.height=_59.h+"px";
-_5b.style.lineHeight=_59.h+"px";
-var _5c=_5a["selectSortSeparator"],_5d=_5a["sortSeparator"];
-_5d.style.height=_5c.style.height=_59.h*3/5+"px";
-_5d.style.marginTop=_5c.style.marginTop=_59.h*1/5+"px";
-_57.header.overResizeWidth=this._overResizeWidth;
-}));
-},_fixAllSelectRegion:function(){
-var _5e=dojo.query(".dojoxGridHeaderCellSelectRegion",this.viewsHeaderNode);
-dojo.forEach(_5e,dojo.hitch(this,function(_5f){
-this._fixSelectRegion(_5f);
-}));
-},_toggleHighlight:function(_60,e,_61){
-if(!e.target||!e.type||!e.type.match(/mouse|contextmenu/)){
-return;
-}
-var _62=this._getCellElements(e.target);
-if(!_62){
-return;
-}
-var _63=_62["selectRegion"];
-var _64=_62["nestedSortWrapper"];
-var _65=_62["unarySortWrapper"];
-dojo.removeClass(_63,"dojoxGridSelectRegionHover");
-dojo.removeClass(_64,"dojoxGridSortHover");
-dojo.removeClass(_65,"dojoxGridSortHover");
-if(!_61&&!_60.grid._inResize(_60)){
-var _66=this._getSortEventInfo(e);
-if(_66.selectChoice){
-dojo.addClass(_63,"dojoxGridSelectRegionHover");
-}else{
-if(_66.nestedSortChoice){
-dojo.addClass(_64,"dojoxGridSortHover");
-}else{
-if(_66.unarySortChoice){
-dojo.addClass(_65,"dojoxGridSortHover");
-}
-}
-}
-}
-},_removeActiveState:function(e){
-if(!e.target||!e.type||!e.type.match(/mouse|contextmenu/)){
-return;
-}
-var _67=this._getChoiceRegion(e.target,this._getSortEventInfo(e));
-_67&&dojo.removeClass(_67,this.headerCellActiveClass);
-},_toggleProgressTip:function(on,e){
-var _68=[this.domNode,e?e.cellNode:null];
-setTimeout(function(){
-dojo.forEach(_68,function(_69){
-if(_69){
-if(on&&!dojo.hasClass(_69,"dojoxGridSortInProgress")){
-dojo.addClass(_69,"dojoxGridSortInProgress");
-}else{
-if(!on&&dojo.hasClass(_69,"dojoxGridSortInProgress")){
-dojo.removeClass(_69,"dojoxGridSortInProgress");
-}
-}
-}
+	//sortAttrs: Array
+	//		Sorting attributes, e.g.[{attr: 'col1', asc: 1|-1|0, cell: cell, cellNode: node}, {...}, ...]
+	sortAttrs: [],
+	
+	//_unarySortCell: Object
+	//		Cache for the current unary sort cell(the 1st column in sorting sequence)
+	//		will be set as {cell: cell, cellNode: node}
+	_unarySortCell:{},
+	
+	//_minColWidth: Integer
+	//		Used for calculating min cell width, will be updated dynamically
+	_minColWidth: 63,//58
+
+	//_widthDelta: Integer
+	//		Min width delta
+	_widthDelta: 23,//18
+	
+	//_minColWidthUpdated: Boolean
+	//		Flag to indicate whether the min col width has been updated
+	_minColWidthUpdated: false,
+
+	//_sortTipMap: Object
+	//		Cache the tip on/off status for each cell, e.g. {cellIndex: true|false}
+	_sortTipMap:{},
+	
+	//_overResizeWidth: Integer
+	//		Overwrite the default over resize width, 
+	//		so that the resize cursor is more obvious when leveraged with sorting hover tips
+	_overResizeWidth: 3,
+
+	//storeItemSelected: String
+	//		Attribute used in data store to mark which row(s) are selected accross sortings
+	storeItemSelected: 'storeItemSelectedAttr',
+
+	//exceptionalSelectedItems: Array
+	//		Cache data store items with exceptional selection state.
+	//		Used to retain selection states accross sortings. User may first select/deselect all rows
+	//		and then deselect/select certain rows, these later changed rows have a different state
+	//		with the global selection state, that is exceptional selection state
+	exceptionalSelectedItems: [],
+
+	//_a11yText: Object
+	//		Characters for sorting arrows, used for a11y high contrast mode
+	_a11yText: {
+		'dojoxGridDescending'   : '▾',
+		'dojoxGridAscending'    : '▴',
+		'dojoxGridAscendingTip' : '۸',	
+		'dojoxGridDescendingTip': '۷',
+		'dojoxGridUnsortedTip'  : 'x' //'✖'
+	},
+	
+	constructor: function(inGrid){
+		// summary:
+		//		Mixin in all the properties and methods into DataGrid		
+		inGrid.mixin(inGrid, this);		
+		//init views
+		dojo.forEach(inGrid.views.views, function(view){
+			//some init work for the header cells
+			dojo.connect(view, 'renderHeader', dojo.hitch(view, inGrid._initSelectCols));	
+			dojo.connect(view.header, 'domousemove', view.grid, '_sychronizeResize');					
+		});	
+		//init sorting
+		this.initSort(inGrid);	
+		//keep selection after sorting if required		
+		inGrid.keepSortSelection && dojo.connect(inGrid, '_onFetchComplete', inGrid, 'updateNewRowSelection');
+		
+		if(inGrid.indirectSelection && inGrid.rowSelectCell.toggleAllSelection){
+			dojo.connect(inGrid.rowSelectCell, 'toggleAllSelection', inGrid, 'allSelectionToggled');			
+		}
+		
+		dojo.subscribe(inGrid.rowMovedTopic, inGrid, inGrid.clearSort);		
+		dojo.subscribe(inGrid.rowSelectionChangedTopic, inGrid, inGrid._selectionChanged);
+		
+		//init focus manager for nested sorting
+		inGrid.focus.destroy();
+		inGrid.focus = new dojox.grid.enhanced.plugins._NestedSortingFocusManager(inGrid);
+		
+		//set a11y ARAI information
+		dojo.connect(inGrid.views, 'render', inGrid, 'initAriaInfo');
+	},
+	
+	initSort: function(inGrid){
+		// summary:
+		//		initiate sorting		
+		inGrid.getSortProps = inGrid._getDsSortAttrs;
+		//TODO - set default sorting order
+	},
+	
+	setSortIndex: function(inIndex, inAsc, e){
+		// summary:
+		//		Sorting entry that overwrites parent(_Grid.js) when nested sorting is enabled
+		// 		Sort the grid on multiple columns in a nested sorting sequence
+		// inIndex: Integer
+		// 		Column index on which to sort.
+		// inAsc: Integer
+		// 		1:  sort the target column in ascending order
+		//		-1: sort the target column in descending order
+		//      0:  revert the target column back to unsorted state
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.
+		if(!this.nestedSorting){
+			this.inherited(arguments);
+		}else{
+			//cache last selection status
+			this.keepSortSelection && this.retainLastRowSelection();			
+			//var desc = c["sortDesc"]; //TODO when is c["sortDesc"] used?
+			this.inSorting = true;
+			this._toggleProgressTip(true, e); //turn on progress cursor
+			this._updateSortAttrs(e, inAsc);
+			this.focus.addSortFocus(e);
+			if(this.canSort()){
+				this.sort();
+				this.edit.info = {};
+				this.update();
+			}
+			this._toggleProgressTip(false, e);//turn off progress cursor
+			this.inSorting = false;
+		}
+	},
+	
+	_updateSortAttrs: function(e, inAsc){
+		// summary:
+		//		 Update the sorting sequence
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.
+		// inAsc: Integer
+		// 		1:  sort the target column in ascending order
+		//		-1: sort the target column in descending order
+		//      0:  revert the target column back to unsorted state
+		var existing = false;
+		var unarySort = !!e.unarySortChoice;//true - unary sort | false - nested sort
+		if(unarySort){
+			//unary sort
+			var cellSortInfo = this.getCellSortInfo(e.cell);
+			var asc  = (this.sortAttrs.length > 0 && cellSortInfo["sortPos"] != 1) ? cellSortInfo["unarySortAsc"]
+					    : this._getNewSortState(cellSortInfo["unarySortAsc"]);
+			if(asc && asc != 0){
+				//update unary sorting info 
+				this.sortAttrs = [{attr: e.cell.field, asc: asc, cell: e.cell, cellNode: e.cellNode}];
+				this._unarySortCell = {cell: e.cell, node: e.cellNode};
+			}else{
+				//asc = 0, so empty sorting sequence
+				this.sortAttrs = [];
+				this._unarySortCell = null;
+			}
+		}else{
+			//nested sort
+			this.setCellSortInfo(e, inAsc);
+		}
+	},
+	
+	getCellSortInfo: function(cell){
+		// summay: 
+		//		Get sorting info of the cell
+		// cell: Cell
+		//		Target header cell
+		// return:
+		//		Sort info e.g. {unarySortAsc: 1|-1|0, nestedSortAsc: 1|-1|0, sortPos:1|2...}
+		if(!cell){return false;}
+		var cellSortInfo = null;
+		var _sortAttrs = this.sortAttrs;
+		dojo.forEach(_sortAttrs, function(attr, index, attrs){
+			if(attr && attr["attr"] == cell.field && attr["cell"] == cell){
+				cellSortInfo = {unarySortAsc: attrs[0] ? attrs[0]["asc"] : undefined,
+								nestedSortAsc:attr["asc"],
+								sortPos: index + 1
+				}
+			}
+		});
+		return cellSortInfo ? cellSortInfo : {unarySortAsc: _sortAttrs && _sortAttrs[0] ? _sortAttrs[0]["asc"] : undefined, 
+								              nestedSortAsc: undefined, sortPos:-1};
+	},
+	
+	setCellSortInfo: function(e, inAsc){
+		// summary:
+		//		Update nested sorting sequence with the new state of target cell
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.
+		// inAsc: Integer
+		// 		1:  sort the target column in ascending order
+		//		-1: sort the target column in descending order
+		//      0:  revert the target column back to unsorted state
+		var cell = e.cell;
+		var existing = false;
+		var delAttrs = [];//cells to be removed from sorting sequence
+		var _sortAttrs = this.sortAttrs;
+		dojo.forEach(_sortAttrs, dojo.hitch(this, function(attr, index){
+			if(attr && attr["attr"] == cell.field){
+				var si = inAsc ? inAsc : this._getNewSortState(attr["asc"]);
+				if(si == 1 || si == -1){
+					attr["asc"] = si;
+				}else if(si == 0){
+					delAttrs.push(index);
+				}else{
+					throw new Exception('Illegal nested sorting status - ' + si);
+				}
+				existing = true;
+			}
+		}));
+		
+		var minus = 0;
+		//remove unsorted columns from sorting sequence
+		dojo.forEach(delAttrs, function(delIndex){
+			_sortAttrs.splice((delIndex - minus++), 1);
+		});
+		//add new column to sorting sequence
+		if(!existing){
+			var si = inAsc ? inAsc : 1;
+			if(si != 0){
+				_sortAttrs.push({
+					attr: cell.field,
+					asc: si,
+					cell: e.cell,
+					cellNode: e.cellNode
+				});
+			}
+		}
+		//cache unary sort cell
+		if(delAttrs.length > 0){
+			this._unarySortCell = {cell: _sortAttrs[0]['cell'], node: _sortAttrs[0]['cellNode']};
+		}
+	},
+	
+	_getDsSortAttrs: function(){
+		// summary:
+		//		Get the sorting attributes for Data Store
+		// return: Object
+		//		Sorting attributes used by Data Store e.g. {attribute: 'xxx', descending: true|false}
+		var dsSortAttrs = [];
+		var si = null;
+		dojo.forEach(this.sortAttrs, function(attr){
+			if(attr && (attr["asc"] == 1 || attr["asc"] == -1)){
+				dsSortAttrs.push({attribute:attr["attr"], descending: (attr["asc"] == -1)});
+			}
+		});
+		return dsSortAttrs.length > 0 ? dsSortAttrs : null;
+	},
+	
+	_getNewSortState: function(si/*int 1|-1|0*/){
+		//summay:
+		//		Get the next sort sate
+		//si: Integer
+		//		Current sorting state
+		//return: Integer
+		//		Next new sorting state
+		return si ? (si == 1 ? -1 : (si == -1 ? 0 : 1)) : 1;
+	},
+	
+	sortStateInt2Str: function(si){
+		//summay: 
+		//		Map sort sate from integer to string
+		//si: Integer
+		//		Sorting state integer
+		//return: String
+		//		Sort info string
+		if(!si){
+			return 'Unsorted';
+		}
+		switch (si){
+			case 1:
+				return 'Ascending';//'SortUp';
+			case -1:
+				return 'Descending';//'SortDown';
+			default:
+				return 'Unsorted';
+		}
+	}, 
+	
+	clearSort: function(){
+		//summay: 
+		//		Clear the sorting sequence
+		dojo.query("[id*='Sort']", this.viewsHeaderNode).forEach(function(region){
+			dojo.addClass(region, 'dojoxGridUnsorted');
+		});
+		this.sortAttrs = [];
+		this.focus.clearHeaderFocus();
+	},
+	
+	_getNestedSortHeaderContent: function(inCell){
+		//summay: 
+		//		Callback to render the innHTML for a header cell, 
+		//		see _View.renderHeader() and _View.header.generateHtml()
+		//inCell: Cell
+		//		Header cell for rendering
+		//return: String
+		//		InnerHTML for the header cell
+		var n = inCell.name || inCell.grid.getCellName(inCell);
+		if(inCell.grid.pluginMgr.isFixedCell(inCell)){
+			return [
+				'<div class="dojoxGridCellContent">',
+				n,
+				'</div>'
+			].join('');
+		}
+		
+		//e.g.{unarySortAsc: 1|-1|0, nestedSortAsc: 1|-1|0, sortPos:1|2...}
+		var cellSortInfo = inCell.grid.getCellSortInfo(inCell);
+		var _sortAttrs = inCell.grid.sortAttrs;
+		var inNestedSort = (_sortAttrs && _sortAttrs.length > 1 && cellSortInfo["sortPos"] >= 1);
+		var inUnarySort =  (_sortAttrs && _sortAttrs.length == 1 && cellSortInfo["sortPos"] == 1);
+		
+		var _grid = inCell.grid;
+		var ret	= ['<div class="dojoxGridSortRoot">',
+		              '<div class="dojoxGridSortWrapper">',
+	 					   //[0] => select-sort Separator
+					   	   '<span id="selectSortSeparator' + inCell.index+ '" class="dojoxGridSortSeparatorOff"></span>', 						   
+						   '<span class="dojoxGridNestedSortWrapper" tabindex="-1">',
+							   //[1] => nested sort position
+							   '<span id="' + inCell.view.id + 'SortPos' + inCell.index + '" class="dojoxGridSortPos ' + (inNestedSort ? '' : 'dojoxGridSortPosOff') + '">' + 
+							   (inNestedSort ? cellSortInfo["sortPos"] : '') + '</span>',
+				
+							   //[2] => nested sort choice
+							   '<span id="nestedSortCol' + inCell.index  + '" class="dojoxGridSort dojoxGridNestedSort ' + 
+							   (inNestedSort ? ('dojoxGrid'+ _grid.sortStateInt2Str(cellSortInfo["nestedSortAsc"])) : 'dojoxGridUnsorted') + '">',
+							   _grid._a11yText['dojoxGrid' + _grid.sortStateInt2Str(cellSortInfo["nestedSortAsc"])] || '.',
+							   '</span>',
+						   '</span>',
+						   	
+						   //[3] => sortSeparator mark
+						   '<span id="SortSeparator' + inCell.index + '" class="dojoxGridSortSeparatorOff"></span>',
+							
+						   //[4] => unary sort choice position
+						   //only shown when this cell is the only one in sort sequence
+						   '<span class="dojoxGridUnarySortWrapper" tabindex="-1"><span id="unarySortCol' + inCell.index  + '" class="dojoxGridSort dojoxGridUnarySort ' + 
+						   (inUnarySort ? ('dojoxGrid'+ _grid.sortStateInt2Str(cellSortInfo["unarySortAsc"])) : 'dojoxGridUnsorted') + '">',
+						   _grid._a11yText['dojoxGrid' + _grid.sortStateInt2Str(cellSortInfo["unarySortAsc"])] || '.',
+						   '</span></span>',
+				   '</div>',						
+				   //[5] => select region
+					 '<div tabindex="-1" id="selectCol' + inCell.index  + '" class="dojoxGridHeaderCellSelectRegion"><span id="caption' + inCell.index + '">' + n + '<span></div>',
+				 '</div>'
+		];
+		return ret.join('');
+	},
+
+	
+	addHoverSortTip: function(e){
+		// summary:
+		//		Add sorting tip for target cell
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.
+		this._sortTipMap[e.cellIndex] = true;
+		
+		var cellSortInfo = this.getCellSortInfo(e.cell);
+		if(!cellSortInfo){return;} 
+
+		//get all related region elements 
+		var elements = this._getCellElements(e.cellNode);
+		if(!elements){return;}
+		
+		var _sortAttrs = this.sortAttrs;	
+		//Grid has not been sorted			
+		var notSorted = !_sortAttrs || _sortAttrs.length < 1;		
+		//only this cell is in sorting sequence
+		var inUnarySort = (_sortAttrs && _sortAttrs.length == 1 && cellSortInfo["sortPos"] == 1);
+		
+		dojo.addClass(elements['selectSortSeparator'], "dojoxGridSortSeparatorOn");
+
+		if(notSorted || inUnarySort){
+			this._addHoverUnarySortTip(elements, cellSortInfo, e);
+		}else{
+			//if in nested sort - "this" cell sort position > 1, then set nested sort state
+			this._addHoverNestedSortTip(elements, cellSortInfo, e);
+			//update the min cell width for column resizing
+			this.updateMinColWidth(elements['nestedSortPos']);			
+		}
+				
+		var selectRegion = elements['selectRegion'];
+		this._fixSelectRegion(selectRegion);//resize selection region
+		if(!dijit.hasWaiRole(selectRegion)){
+			dijit.setWaiState(selectRegion, 'label', 'Column ' + (e.cellIndex + 1) + ' ' +  e.cell.field);
+		}
+		
+		this._toggleHighlight(e.sourceView, e);		
+		this.focus._updateFocusBorder();
+	},
+	
+	_addHoverUnarySortTip: function(elements, cellSortInfo, e){
+		// summary:
+		//		Add hover tip for unary sorting
+		// elements: Object
+		//		Json object contains all dom nodes of sort regions
+		// cellSortInfo: Object
+		//		Json object that contains detail sorting info
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.
+				
+		//this cell would be or is already the single unary cell
+		dojo.addClass(elements['nestedSortWrapper'], "dojoxGridUnsorted");
+		var stateStr = this.sortStateInt2Str(this._getNewSortState(cellSortInfo["unarySortAsc"]));
+		dijit.setWaiState(elements['unarySortWrapper'], 'label', 'Column ' + (e.cellIndex + 1) + ' ' + e.cell.field + ' - Choose ' + stateStr.toLowerCase() + ' single sort');
+		//set unary sort state
+		var className = "dojoxGrid" + stateStr +"Tip";
+		dojo.addClass(elements['unarySortChoice'], className);
+		elements['unarySortChoice'].innerHTML = this._a11yText[className];
+		this._addTipInfo(elements['unarySortWrapper'], this._composeSortTip(stateStr, 'singleSort'));
+	},
+	
+	_addHoverNestedSortTip: function(elements, cellSortInfo, e){
+		// summary:
+		//		Add hover tip for nested sorting
+		// elements: Object
+		//		Json object contains all dom nodes of sort regions
+		// cellSortInfo: Object
+		//		Json object that contains detail sorting info
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.		
+		var nestedSortPos     = elements['nestedSortPos'];
+		var unarySortWrapper  = elements['unarySortWrapper'];
+		var nestedSortWrapper = elements['nestedSortWrapper'];
+		var _sortAttrs = this.sortAttrs;
+		
+		dojo.removeClass(nestedSortWrapper, "dojoxGridUnsorted");
+		var stateStr = this.sortStateInt2Str(this._getNewSortState(cellSortInfo["nestedSortAsc"]));
+		dijit.setWaiState(nestedSortWrapper, 'label', 'Column ' + (e.cellIndex + 1) + ' ' + e.cell.field + ' - Choose ' + stateStr.toLowerCase() + ' nested sort');				
+		var className = "dojoxGrid" + stateStr +"Tip";
+		this._addA11yInfo(elements['nestedSortChoice'], className);
+		this._addTipInfo(nestedSortWrapper, this._composeSortTip(stateStr, 'nestedSort'));
+		
+		//set unary sort state
+		stateStr = this.sortStateInt2Str(cellSortInfo["unarySortAsc"]);
+		dijit.setWaiState(unarySortWrapper, 'label', 'Column ' + (e.cellIndex + 1) + ' ' + e.cell.field + ' - Choose ' + stateStr.toLowerCase() + ' single sort');		
+		className = "dojoxGrid" + stateStr +"Tip";
+		this._addA11yInfo(elements['unarySortChoice'], className);
+		this._addTipInfo(unarySortWrapper, this._composeSortTip(stateStr, 'singleSort'));			
+		
+		//show separator
+		dojo.addClass(elements['sortSeparator'], "dojoxGridSortSeparatorOn");
+		dojo.removeClass(nestedSortPos, "dojoxGridSortPosOff");
+		
+		//set sort position info
+		if(cellSortInfo["sortPos"] < 1){
+			//this would be a new cell to sort sequence, a new sort position is needed
+			nestedSortPos.innerHTML = (_sortAttrs ? _sortAttrs.length : 0) + 1;
+			if(!this._unarySortInFocus() && _sortAttrs && _sortAttrs.length == 1){
+				//this cell will be in the 2nd sort position, sort position info should be turn on for unary sort column				
+				var unaryNode = this._getUnaryNode();
+				unaryNode.innerHTML = '1';
+				dojo.removeClass(unaryNode, "dojoxGridSortPosOff");
+				dojo.removeClass(unaryNode.parentNode, "dojoxGridUnsorted");
+				this._fixSelectRegion(this._getCellElements(unaryNode)['selectRegion']);						
+			}
+		}
+	},
+	
+	_unarySortInFocus: function(){
+		// summary:
+		//		See if the unary sort node is in keyboard focus
+		// return: Boolean
+		return this._unarySortCell.cell && this.focus.headerCellInFocus(this._unarySortCell.cell.index);
+	},
+	
+	_composeSortTip: function(state, type){
+		// summary:
+		//		Get properties from nls bundle and compose appropriate sorting tips
+		// state: String
+		//		Sorting state
+		// type: String
+		//		Sorting type
+		state = state.toLowerCase();
+		if(state == "unsorted"){
+			return this._nls[state];
+		}else{
+			var tip = dojo.string.substitute(this._nls['sortingState'], [this._nls[type], this._nls[state]]);
+			return tip;
+		}
+	},
+	
+	_addTipInfo: function(node, text){
+		// summary:
+		//		Add title tip to target node and also all the descendants
+		// node: Dom node
+		//		Target node
+		// text: String
+		//		Tip string		
+		dojo.attr(node, 'title', text);
+		dojo.query('span', node).forEach(function(n){
+			dojo.attr(n, 'title', text);
+		});
+	},
+
+	_addA11yInfo:function(node,className){
+		// summary:
+		//		Add related class and a11y sorting arrow character
+		// node: Dom node
+		//		Decorated event object which contains reference to grid, target cell etc.	
+		// className: String
+		//		CSS class name mapped to a11y sorting arrow character
+		dojo.addClass(node, className);
+		node.innerHTML = this._a11yText[className];
+	},
+	
+	removeHoverSortTip: function(e){
+		// summary:
+		//		Remove sorting tip for target cell
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.
+		if(!this._sortTipMap[e.cellIndex]){return; /*tip already removed*/}
+
+		var cellSortInfo = this.getCellSortInfo(e.cell);
+		if(!cellSortInfo){return;} 
+
+		//get all related region elements 
+		var elements = this._getCellElements(e.cellNode);
+		if(!elements){return;}
+
+		var nestedSortChoice  = elements.nestedSortChoice;
+		var unarySortChoice   = elements.unarySortChoice;
+		var unarySortWrapper  = elements.unarySortWrapper;
+		var nestedSortWrapper = elements.nestedSortWrapper;
+		
+		//remove all highlights
+		this._toggleHighlight(e.sourceView, e, true);
+		
+		//dojo.removeClass doesn't support Reg Exp?
+		function _removeTipClass(nodes){
+			dojo.forEach(nodes, function(node){
+				var newClasses = dojo.trim((" " + node["className"] + " ").replace(/\sdojoxGrid\w+Tip\s/g, " "));
+				if(node["className"] != newClasses){ node["className"] = newClasses; }
+			});
+		}
+		_removeTipClass([nestedSortChoice, unarySortChoice]);
+		
+		unarySortChoice.innerHTML = this._a11yText['dojoxGrid' + this.sortStateInt2Str(cellSortInfo["unarySortAsc"])] || '.';
+		nestedSortChoice.innerHTML = this._a11yText['dojoxGrid' + this.sortStateInt2Str(cellSortInfo["nestedSortAsc"])] || '.';
+		
+		dojo.removeClass(elements['selectSortSeparator'], "dojoxGridSortSeparatorOn");
+		dojo.removeClass(elements['sortSeparator'], "dojoxGridSortSeparatorOn");
+		
+		if(cellSortInfo["sortPos"] == 1 && this.focus.isNavHeader() && !this.focus.headerCellInFocus(e.cellIndex)){
+			dojo.removeClass(elements['nestedSortWrapper'], "dojoxGridUnsorted");
+		}
+
+		var _sortAttrs = this.sortAttrs;
+		if(!isNaN(cellSortInfo["sortPos"])/* fix sortPos missed issue*/ && cellSortInfo["sortPos"] < 1){
+			//sort position info for this cell should also be cleared
+			elements['nestedSortPos'].innerHTML = "";	
+			dojo.addClass(nestedSortWrapper, "dojoxGridUnsorted");
+			if(!this.focus._focusBorderBox && _sortAttrs && _sortAttrs.length == 1){
+				//clear the sort position info for unary sort column
+				var unaryNode = this._getUnaryNode();
+				unaryNode.innerHTML = '';
+				dojo.addClass(unaryNode, "dojoxGridSortPosOff");
+				this._fixSelectRegion(this._getCellElements(unaryNode)['selectRegion']);						
+			}
+		}
+		this._fixSelectRegion(elements['selectRegion']);		
+		
+		dijit.removeWaiState(nestedSortWrapper, 'label');
+		dijit.removeWaiState(unarySortWrapper, 'label');
+		
+		if(cellSortInfo["sortPos"] >= 0){
+			var singleSort = (_sortAttrs.length == 1);
+			var node = singleSort ? unarySortWrapper : nestedSortWrapper;
+			this._setSortRegionWaiState(singleSort, e.cellIndex, e.cell.field, cellSortInfo["sortPos"], node);
+		}
+
+		this.focus._updateFocusBorder();
+		this._sortTipMap[e.cellIndex] = false;
+	},
+
+	_getUnaryNode: function(){
+		// summary:
+		//		Get the sort position DOM node of unary column (1st in the sort sequence)
+		// return: Dom node
+		for(var i = 0; i < this.views.views.length; i++){
+			var n = dojo.byId(this.views.views[i].id + 'SortPos' + this._unarySortCell.cell.index);
+			if(n) return n;
+		}
+	},
+
+	_fixSelectRegion: function(selectRegion){
+		// summary:
+		//		Resize or recover the selection region, so that content in header cell are not messed up.
+		// selectRegion: Dom node
+		//		Dom node of selection region
+		var sortWrapper = selectRegion.previousSibling;
+		var parentBox = dojo.contentBox(selectRegion.parentNode);
+		var selectRegionBox = dojo.marginBox(selectRegion);
+		var sortWrapperBox = dojo.marginBox(sortWrapper);
+						
+		//fix rtl in IE
+		if(dojo.isIE && !dojo._isBodyLtr()){
+			var w = 0;
+			dojo.forEach(sortWrapper.childNodes, function(node){
+				w += dojo.marginBox(node).w;
+			})
+			sortWrapperBox.w = w;
+			sortWrapperBox.l = (sortWrapperBox.t = 0);
+			dojo.marginBox(sortWrapper, sortWrapperBox);
+		}				
+		if(selectRegionBox.w != (parentBox.w - sortWrapperBox.w)){
+			selectRegionBox.w = parentBox.w - sortWrapperBox.w;
+			if(!dojo.isWebKit){
+				dojo.marginBox(selectRegion,selectRegionBox);	
+			}else{//fix insufficient width of select region in Safari & Chrome when zoomed in
+				selectRegionBox.h = dojo.contentBox(parentBox).h;
+				dojo.style(selectRegion, "width", (selectRegionBox.w - 4) + "px");
+			}
+		}
+	},
+	
+	updateMinColWidth: function(nestedSortPos){
+		// summary:
+		//		Calculate and update the min cell width. So that sort tip and partial caption are visible when resized.
+		// nestedSortPos: Dom node
+		//		Dom node of nested sorting position
+		if(this._minColWidthUpdated){ return; }	
+		var oldValue = nestedSortPos.innerHTML;
+		nestedSortPos.innerHTML = dojo.query('.dojoxGridSortWrapper', this.viewsHeaderNode).length;
+		var sortWrapper = nestedSortPos.parentNode.parentNode;
+		this._minColWidth = dojo.marginBox(sortWrapper).w + this._widthDelta;
+		nestedSortPos.innerHTML = oldValue;
+		this._minColWidthUpdated = true;
+	},
+
+	getMinColWidth: function(){
+		// summary:
+		//		Fetch the min column width
+		return this._minColWidth;
+	},
+	
+	_initSelectCols: function(){
+		// summary:
+		//		Some initial works on the header cells, like event binding, resizing parameters etc.
+		var selectRegions      = dojo.query(".dojoxGridHeaderCellSelectRegion", this.headerContentNode);
+		var unarySortWrappers  = dojo.query(".dojoxGridUnarySortWrapper", this.headerContentNode);
+		var nestedSortWrappers = dojo.query(".dojoxGridNestedSortWrapper", this.headerContentNode);
+		
+		selectRegions.concat(unarySortWrappers).concat(nestedSortWrappers).forEach(function(region){
+			dojo.connect(region, 'onmousemove', dojo.hitch(this.grid, this.grid._toggleHighlight, this/*view*/));
+			dojo.connect(region, 'onmouseout', dojo.hitch(this.grid, this.grid._removeActiveState));
+		}, this);
+		
+		this.grid._fixHeaderCellStyle(selectRegions, this/*view*/);
+		
+		//fix rtl in IE
+		if(dojo.isIE && !dojo._isBodyLtr()){
+			this.grid._fixAllSelectRegion();
+		}
+	},
+	
+	_fixHeaderCellStyle: function(selectRegions, cellView){
+		// summary:
+		//		Fix some style issues when header cells are created
+		//		TBD, see if these can be fixed through CSS
+		// selectRegions: Node list
+		//		Node list of dom nodes for selection regions
+		// cellView: View
+		//		View that contains related cells
+		dojo.forEach(selectRegions, dojo.hitch(this, function(selectRegion){
+			var selectRegionBox = dojo.marginBox(selectRegion),
+				elements = this._getCellElements(selectRegion),
+				sortWrapper = elements.sortWrapper;
+			sortWrapper.style.height = selectRegionBox.h + 'px';
+			sortWrapper.style.lineHeight = selectRegionBox.h + 'px';
+			var selectSortSeparator = elements['selectSortSeparator'], sortSeparator = elements['sortSeparator'];
+			sortSeparator.style.height = selectSortSeparator.style.height = selectRegionBox.h * 3/5 + 'px';
+			sortSeparator.style.marginTop = selectSortSeparator.style.marginTop = selectRegionBox.h * 1/5 + 'px';
+			cellView.header.overResizeWidth = this._overResizeWidth;
+		}));
+	},
+
+	_fixAllSelectRegion: function (){
+		// summary:
+		//		Fix rtl in IE
+		var nodes = dojo.query('.dojoxGridHeaderCellSelectRegion', this.viewsHeaderNode);
+		dojo.forEach(nodes, dojo.hitch(this, function(node){
+			this._fixSelectRegion(node);
+		}));
+	},
+
+	_toggleHighlight: function(cellView, e, allOff){
+		// summary:
+		//		Toggle hover state for selection region, unary sort region (unarySortWrapper) 
+		//		and nested sort region (unarySortWrapper)
+		// cellView: View
+		//		View that contains related cell
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.		
+		// allOff: Boolean
+		//		True - to trun off all highlight | False - by default
+		if(!e.target || !e.type || !e.type.match(/mouse|contextmenu/)){
+			//don't highlight for key events or when in keyboard focus
+			return;
+		}
+		//console.debug("onmousemove,info.selectChoice="+info.selectChoice + ' info.nestedSortChoice='+info.nestedSortChoice+' info.unarySortChoice='+info.unarySortChoice);
+		var elements = this._getCellElements(e.target);
+		if(!elements){return;}
+		
+		var selectRegion      = elements['selectRegion'];
+		var nestedSortWrapper = elements['nestedSortWrapper'];
+		var unarySortWrapper  = elements['unarySortWrapper'];
+				
+		dojo.removeClass(selectRegion, 'dojoxGridSelectRegionHover');
+		dojo.removeClass(nestedSortWrapper, 'dojoxGridSortHover');
+		dojo.removeClass(unarySortWrapper, 'dojoxGridSortHover');	
+
+		if(!allOff && !cellView.grid._inResize(cellView)){
+			var info = this._getSortEventInfo(e);
+			if(info.selectChoice){//highlight selection region
+				dojo.addClass(selectRegion, 'dojoxGridSelectRegionHover');
+			}else if(info.nestedSortChoice){//highlight nested sort region
+				dojo.addClass(nestedSortWrapper, 'dojoxGridSortHover');
+			}else if(info.unarySortChoice){//highlight unary sort region
+				dojo.addClass(unarySortWrapper, 'dojoxGridSortHover');
+			}
+		}
+	},
+	
+	_removeActiveState: function(e){
+		// summary:
+		//		Remove active state for the event target 
+		// e: Event
+		if(!e.target || !e.type || !e.type.match(/mouse|contextmenu/)){
+			return;
+		}
+		var node = this._getChoiceRegion(e.target, this._getSortEventInfo(e));
+		node && dojo.removeClass(node, this.headerCellActiveClass);
+	},
+	
+	_toggleProgressTip: function(on, e){
+		// summary:
+		//		Change the cursor to progress or vice versa
+		// on: Boolean
+		//		True - change to progress cursor, false - recover back to original style
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.
+		var tipNodes  = [this.domNode, e ? e.cellNode : null];
+		setTimeout(function(){
+			dojo.forEach(tipNodes, function(node){
+				if(node){
+					if(on && !dojo.hasClass(node, 'dojoxGridSortInProgress')){
+						dojo.addClass(node, 'dojoxGridSortInProgress');
+					}else if(!on && dojo.hasClass(node, 'dojoxGridSortInProgress')){
+						dojo.removeClass(node, 'dojoxGridSortInProgress');									
+					}
+				}
+			});
+		}, 0.1);
+	},
+	
+	_getSortEventInfo: function(e){
+		// summary:
+		//		Get sort event type from the event 
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.
+		// return; Object
+		//      Sort event type e.g. {unarySortChoice: true|false, nestedSortChoice: true|false, selectChoice: true|false}
+		var _isRegionTypeByCSS = function (node, css){
+			return dojo.hasClass(node, css) || (node.parentNode && dojo.hasClass(node.parentNode, css));
+		};
+		return {selectChoice 	 : _isRegionTypeByCSS(e.target, 'dojoxGridHeaderCellSelectRegion'),
+				unarySortChoice  : _isRegionTypeByCSS(e.target, 'dojoxGridUnarySortWrapper'),
+				nestedSortChoice : _isRegionTypeByCSS(e.target, 'dojoxGridNestedSortWrapper')};
+	},
+	
+	ignoreEvent: function(e){
+		// summary:
+		//		See if the event should be ignored when nested sorting is enabled
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.
+		// return: Boolean
+		//		True - ignore this event, false - don't ignore
+		return !(e.nestedSortChoice || e.unarySortChoice || e.selectChoice);
+	},
+	
+	_sychronizeResize: function(e){
+		// summary:
+		//		Each time mouse moved in view.headerNode, check if need to add or remove sort tip
+		//      This is used so that when mouse moves in resize area, sort tip is turned off, when mouse
+		//		moves out of resize area, sort tip is turned on if necessary. Sort tip is also off during resizing
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.
+		if(!e.cell || e.cell.isRowSelector || this.focus.headerCellInFocus(e.cellIndex)){
+			return;
+		}
+		if(!this._inResize(e.sourceView)){
+			this.addHoverSortTip(e);
+		}else{
+			var idx = e.cellIndex;
+			if(!this._sortTipMap[e.cellIndex]){
+				e.cellIndex = this._sortTipMap[idx + 1] ? (idx + 1) : (this._sortTipMap[idx - 1] ? (idx - 1) : idx);
+				e.cellNode = e.cellNode.parentNode.childNodes[e.cellIndex];
+			}
+			this.removeHoverSortTip(e);
+		}
+	},
+	
+	_getCellElements: function(node){
+		// summary:
+		//		Fetch all dom nodes related with sorting, using dojo.query()
+		//		to search from top 'th' parent of the given node
+		// node: Dom node
+		//		Target node.
+		// return: Object
+		//		Json object contains all dom nodes related with sorting	
+		try{
+			while(node && node.nodeName.toLowerCase() != 'th'){
+				node = node.parentNode;
+			}
+			if(!node){return null;}
+			// try to get dojoxGridSortRoot
+			var ns = dojo.query(".dojoxGridSortRoot", node);
+			if(ns.length != 1){return null;}
+			var n = ns[0];
+			return {
+				'selectSortSeparator': dojo.query("[id^='selectSortSeparator']", n)[0],
+				'nestedSortPos'		 : dojo.query(".dojoxGridSortPos", n)[0],
+				'nestedSortChoice'	 : dojo.query("[id^='nestedSortCol']", n)[0],
+				'sortSeparator'		 : dojo.query("[id^='SortSeparator']", n)[0],
+				'unarySortChoice'	 : dojo.query("[id^='unarySortCol']", n)[0],
+				'selectRegion'		 : dojo.query(".dojoxGridHeaderCellSelectRegion", n)[0],
+				'sortWrapper'		 : dojo.query(".dojoxGridSortWrapper", n)[0],
+				'unarySortWrapper'	 : dojo.query(".dojoxGridUnarySortWrapper", n)[0],
+				'nestedSortWrapper'	 : dojo.query(".dojoxGridNestedSortWrapper", n)[0],
+				'sortRoot'			 : n,
+				'headCellNode'		 : node
+			}		
+		}catch(e){
+			console.debug('NestedSorting._getCellElemets() error:' + e);
+		}
+		return null;
+	},
+	
+	_getChoiceRegion: function(target, choiceInfo){
+		// summary:
+		//		Find an appropriate region node for the choice event
+		// target: Dom Node
+		//		Choice event target
+		// choiceInfo: Object
+		//		Choice info e.g. 'unarySortChoice' | 'nestedSortChoice' | 'selectChoice'
+		// return: Dom Node
+		//		Appropriate choice region node
+		var node, elements = this._getCellElements(target);
+		if(!elements){ return; }
+		choiceInfo.unarySortChoice && (node = elements['unarySortWrapper']);
+		choiceInfo.nestedSortChoice && (node = elements['nestedSortWrapper']);
+		choiceInfo.selectChoice && (node = elements['selectRegion']);
+		return node;	
+	},
+
+	_inResize: function(view){
+		// summary:
+		//		See if current view is in resizing state(including if the cursor is in resize area)
+		// view: View
+		//		Target view
+		// return: Boolean
+		//		True - in resizing state, false - not in resizing state
+		return view.header.moverDiv || dojo.hasClass(view.headerNode, "dojoxGridColResize") || dojo.hasClass(view.headerNode, "dojoxGridColNoResize");		
+	},
+	
+	retainLastRowSelection: function(){
+		// summary:
+		//		Retain selected rows before sorting
+		dojo.forEach(this._by_idx, function(o, idx){
+			if(!o || !o.item){return;}
+			var selected = !!this.selection.isSelected(idx);
+			o.item[this.storeItemSelected] = [selected];
+			if(this.indirectSelection && this.rowSelectCell.toggleAllTrigerred && selected != this.toggleAllValue){
+				this.exceptionalSelectedItems.push(o.item);
+			}
+		}, this);
+		//clear all row selections
+		this.selection.selected = [];
+		dojo.publish(this.sortRowSelectionChangedTopic,[this]);
+	},
+	
+	updateNewRowSelection: function(items, req){
+		// summary:
+		//		Fired when row selection is changed, connected from DataGrid._onFetchComplete();
+		dojo.forEach(items, function(item, idx){
+			if(this.indirectSelection && this.rowSelectCell.toggleAllTrigerred){
+				if(dojo.indexOf(this.exceptionalSelectedItems, item) < 0){
+					item[this.storeItemSelected] = [this.toggleAllValue];	
+				}				
+			}
+			if(item[this.storeItemSelected] && item[this.storeItemSelected][0]){
+				//don't invoke addToSelection to avoid any onSelected events
+				var rowIndex = req.start + idx;
+				this.selection.selectedIndex = rowIndex;
+				this.selection.selected[rowIndex] = true;
+				this.updateRowStyles(rowIndex);
+			}
+		}, this);
+		dojo.publish(this.sortRowSelectionChangedTopic,[this]);
+		if(dojo.isMoz && this._by_idx.length == 0){
+			//Fix a weird issue in FF, when there are empty rows after page loaded
+			this.update();
+		}
+	}, 
+
+	allSelectionToggled: function(checked){
+		// summary:
+		//		Fired when toggleAllSelection is triggered in indirect selection		
+		this.exceptionalSelectedItems = [];
+		this.toggleAllValue = this.rowSelectCell.defaultValue;
+	},
+	
+	_selectionChanged: function(obj){
+		// summary:
+		//		Subscriber of rowSelectionChangedTopic, update global row selection state accordingly
+		// obj: Object
+		//		Object that fired the rowSelectionChangedTopic		
+		obj == this.select && (this.toggleAllValue = false);//from DnD
+	},
+	
+	getStoreSelectedValue: function(rowIdx){
+		// summary:
+		//		Get whether a give row is selected across sortings
+		// rowIdx: Integer
+		//		Target row index
+		var data = this._by_idx[rowIdx];
+		return data && data.item && !!(data.item[this.storeItemSelected] && data.item[this.storeItemSelected][0]);
+	},
+	
+	initAriaInfo: function(){
+		// summary:
+		//		Add ARIA attributes for A11Y	
+		var _sortAttrs = this.sortAttrs;
+		dojo.forEach(_sortAttrs, dojo.hitch(this, function(attr, index){
+			if(!attr.cell || !attr.cellNode){return;}
+			var cellNode = attr.cell.getHeaderNode();
+			var elements = this._getCellElements(cellNode);
+			if(!elements){return;}
+			var selectRegion = elements['selectRegion'];
+			//dijit.setWaiRole(selectRegion, 'columnheader');
+			dijit.setWaiState(selectRegion, 'label', 'Column ' + (attr.cell.index+1) + ' ' +  attr.attr);
+			
+			var singleSort = (_sortAttrs.length == 1);
+			var sortState = this.sortStateInt2Str(attr.asc).toLowerCase();
+			var node = singleSort ? elements['unarySortWrapper'] : elements['nestedSortWrapper'];
+			dijit.setWaiState(node, 'sort', sortState);
+			this._setSortRegionWaiState(singleSort, attr.cell.index, attr.attr, index + 1, node);
+		}));
+	},
+	
+	_setSortRegionWaiState: function(singleSort, cellIdx, field, sortPos, node){
+		// summary:
+		//		Add ARIA Wai sate for sort regions
+		if(sortPos < 0) return;
+		var sortType = singleSort ? 'single sort' : 'nested sort';
+		var ariaValue = 'Column ' + (cellIdx + 1) + ' ' + field + ' ' + sortType + ' ' + (!singleSort ? (' sort position ' + sortPos) : '');
+		dijit.setWaiState(node, 'label', ariaValue);
+	},
+
+	_inPage: function(rowIndex){
+		// summary:
+		//		See if the given row is in the current page
+		// rowIndex: Integer
+		//		Target row
+		// return: Boolean
+		//		True - in the current page | False - not in the current page
+		return rowIndex < this._bop || rowIndex >= this._eop;
+	}
 });
-},0.1);
-},_getSortEventInfo:function(e){
-var _6a=function(_6b,css){
-return dojo.hasClass(_6b,css)||(_6b.parentNode&&dojo.hasClass(_6b.parentNode,css));
-};
-return {selectChoice:_6a(e.target,"dojoxGridHeaderCellSelectRegion"),unarySortChoice:_6a(e.target,"dojoxGridUnarySortWrapper"),nestedSortChoice:_6a(e.target,"dojoxGridNestedSortWrapper")};
-},ignoreEvent:function(e){
-return !(e.nestedSortChoice||e.unarySortChoice||e.selectChoice);
-},doheaderclick:function(e){
-if(this.nestedSorting){
-if(e.selectChoice){
-this.onHeaderCellSelectClick(e);
-}else{
-if((e.unarySortChoice||e.nestedSortChoice)&&!this._inResize(e.sourceView)){
-this.onHeaderCellSortClick(e);
-}
-}
-return;
-}
-this.inherited(arguments);
-},onHeaderCellSelectClick:function(e){
-},onHeaderCellSortClick:function(e){
-this.setSortIndex(e.cell.index,null,e);
-},_sychronizeResize:function(e){
-if(!e.cell||e.cell.isRowSelector||this.focus.headerCellInFocus(e.cellIndex)){
-return;
-}
-if(!this._inResize(e.sourceView)){
-this.addHoverSortTip(e);
-}else{
-var idx=e.cellIndex;
-if(!this._sortTipMap[e.cellIndex]){
-e.cellIndex=this._sortTipMap[idx+1]?(idx+1):(this._sortTipMap[idx-1]?(idx-1):idx);
-e.cellNode=e.cellNode.parentNode.childNodes[e.cellIndex];
-}
-this.removeHoverSortTip(e);
-}
-},_getCellElements:function(_6c){
-try{
-while(_6c&&_6c.nodeName.toLowerCase()!="th"){
-_6c=_6c.parentNode;
-}
-if(!_6c){
-return null;
-}
-var ns=dojo.query(".dojoxGridSortRoot",_6c);
-if(ns.length!=1){
-return null;
-}
-var n=ns[0];
-return {"selectSortSeparator":dojo.query("[id^='selectSortSeparator']",n)[0],"nestedSortPos":dojo.query(".dojoxGridSortPos",n)[0],"nestedSortChoice":dojo.query("[id^='nestedSortCol']",n)[0],"sortSeparator":dojo.query("[id^='SortSeparator']",n)[0],"unarySortChoice":dojo.query("[id^='unarySortCol']",n)[0],"selectRegion":dojo.query(".dojoxGridHeaderCellSelectRegion",n)[0],"sortWrapper":dojo.query(".dojoxGridSortWrapper",n)[0],"unarySortWrapper":dojo.query(".dojoxGridUnarySortWrapper",n)[0], [...]
-}
-catch(e){
-}
-return null;
-},_getChoiceRegion:function(_6d,_6e){
-var _6f,_70=this._getCellElements(_6d);
-if(!_70){
-return;
-}
-_6e.unarySortChoice&&(_6f=_70["unarySortWrapper"]);
-_6e.nestedSortChoice&&(_6f=_70["nestedSortWrapper"]);
-_6e.selectChoice&&(_6f=_70["selectRegion"]);
-return _6f;
-},_inResize:function(_71){
-return _71.header.moverDiv||dojo.hasClass(_71.headerNode,"dojoxGridColResize")||dojo.hasClass(_71.headerNode,"dojoxGridColNoResize");
-},retainLastRowSelection:function(){
-dojo.forEach(this._by_idx,function(o,idx){
-if(!o||!o.item){
-return;
-}
-var _72=!!this.selection.isSelected(idx);
-o.item[this.storeItemSelected]=[_72];
-if(this.indirectSelection&&this.rowSelectCell.toggleAllTrigerred&&_72!=this.toggleAllValue){
-this.exceptionalSelectedItems.push(o.item);
-}
-},this);
-this.selection.clear();
-dojo.publish(this.sortRowSelectionChangedTopic,[this]);
-},updateNewRowSelection:function(_73,req){
-dojo.forEach(_73,function(_74,idx){
-if(this.indirectSelection&&this.rowSelectCell.toggleAllTrigerred){
-if(dojo.indexOf(this.exceptionalSelectedItems,_74)<0){
-_74[this.storeItemSelected]=[this.toggleAllValue];
-}
-}
-_74[this.storeItemSelected]&&_74[this.storeItemSelected][0]&&this.selection.addToSelection(req.start+idx);
-},this);
-dojo.publish(this.sortRowSelectionChangedTopic,[this]);
-if(dojo.isMoz&&this._by_idx.length==0){
-this.update();
-}
-},allSelectionToggled:function(_75){
-this.exceptionalSelectedItems=[];
-this.toggleAllValue=this.rowSelectCell.defaultValue;
-},_selectionChanged:function(obj){
-obj==this.select&&(this.toggleAllValue=false);
-},getStoreSelectedValue:function(_76){
-var _77=this._by_idx[_76];
-return _77&&_77.item&&!!(_77.item[this.storeItemSelected]&&_77.item[this.storeItemSelected][0]);
-},initAriaInfo:function(){
-var _78=this.sortAttrs;
-dojo.forEach(_78,dojo.hitch(this,function(_79,_7a){
-var _7b=_79.cell.getHeaderNode();
-var _7c=this._getCellElements(_7b);
-if(!_7c){
-return;
-}
-var _7d=_7c["selectRegion"];
-dijit.setWaiState(_7d,"label","Column "+(_79.cell.index+1)+" "+_79.attr);
-var _7e=(_78.length==1);
-var _7f=this.sortStateInt2Str(_79.asc).toLowerCase();
-var _80=_7e?_7c["unarySortWrapper"]:_7c["nestedSortWrapper"];
-dijit.setWaiState(_80,"sort",_7f);
-this._setSortRegionWaiState(_7e,_79.cell.index,_79.attr,_7a+1,_80);
-}));
-},_setSortRegionWaiState:function(_81,_82,_83,_84,_85){
-if(_84<0){
-return;
-}
-var _86=_81?"single sort":"nested sort";
-var _87="Column "+(_82+1)+" "+_83+" "+_86+" "+(!_81?(" sort position "+_84):"");
-dijit.setWaiState(_85,"label",_87);
-},_inPage:function(_88){
-return _88<this._bop||_88>=this._eop;
-}});
-dojo.declare("dojox.grid.enhanced.plugins._NestedSortingFocusManager",dojox.grid._FocusManager,{lastHeaderFocus:{cellNode:null,regionIdx:-1},currentHeaderFocusEvt:null,cssMarkers:["dojoxGridHeaderCellSelectRegion","dojoxGridNestedSortWrapper","dojoxGridUnarySortWrapper"],_focusBorderBox:null,_initColumnHeaders:function(){
-var _89=this._findHeaderCells();
-dojo.forEach(_89,dojo.hitch(this,function(_8a){
-var _8b=dojo.query(".dojoxGridHeaderCellSelectRegion",_8a);
-var _8c=dojo.query("[class*='SortWrapper']",_8a);
-_8b=_8b.concat(_8c);
-_8b.length==0&&(_8b=[_8a]);
-dojo.forEach(_8b,dojo.hitch(this,function(_8d){
-this._connects.push(dojo.connect(_8d,"onfocus",this,"doColHeaderFocus"));
-this._connects.push(dojo.connect(_8d,"onblur",this,"doColHeaderBlur"));
-}));
-}));
-},focusHeader:function(_8e,_8f,_90){
-if(!this.isNavHeader()){
-this.inherited(arguments);
-}else{
-var _91=this._findHeaderCells();
-this._colHeadNode=_91[this._colHeadFocusIdx];
-_8f&&(this.lastHeaderFocus.cellNode=this._colHeadNode);
-}
-if(!this._colHeadNode){
-return;
-}
-if(this.grid.indirectSelection&&this._colHeadFocusIdx==0){
-this._colHeadNode=this._findHeaderCells()[++this._colHeadFocusIdx];
-}
-var _92=_90?0:(this.lastHeaderFocus.regionIdx>=0?this.lastHeaderFocus.regionIdx:(_8e?2:0));
-var _93=dojo.query("."+this.cssMarkers[_92],this._colHeadNode)[0]||this._colHeadNode;
-this.grid.addHoverSortTip(this.currentHeaderFocusEvt=this._mockEvt(_93));
-this.lastHeaderFocus.regionIdx=_92;
-_93&&dojox.grid.util.fire(_93,"focus");
-},focusSelectColEndingHeader:function(e){
-if(!e||!e.cellNode){
-return;
-}
-this._colHeadFocusIdx=e.cellIndex;
-this.focusHeader(null,false,true);
-},_delayedHeaderFocus:function(){
-this.isNavHeader()&&this.focusHeader(null,true);
-},_setActiveColHeader:function(_94,_95,_96){
-dojo.attr(this.grid.domNode,"aria-activedescendant",_94.id);
-this._colHeadNode=_94;
-this._colHeadFocusIdx=_95;
-},doColHeaderFocus:function(e){
-this.lastHeaderFocus.cellNode=this._colHeadNode;
-if(e.target==this._colHeadNode){
-this._scrollHeader(this.getHeaderIndex());
-}else{
-var _97=this.getFocusView(e);
-if(!_97){
-return;
-}
-_97.header.baseDecorateEvent(e);
-this._addFocusBorder(e.target);
-this._colHeadFocusIdx=e.cellIndex;
-this._colHeadNode=this._findHeaderCells()[this._colHeadFocusIdx];
-this._colHeadNode&&this.getHeaderIndex()!=-1&&this._scrollHeader(this._colHeadFocusIdx);
-}
-this._focusifyCellNode(false);
-this.grid.isDndSelectEnable&&this.grid.focus._blurRowBar();
-this.grid.addHoverSortTip(this.currentHeaderFocusEvt=this._mockEvt(e.target));
-if(dojo.isIE&&!dojo._isBodyLtr()){
-this.grid._fixAllSelectRegion();
-}
-},doColHeaderBlur:function(e){
-this.inherited(arguments);
-this._removeFocusBorder();
-if(!this.isNavCellRegion){
-var _98=this.getFocusView(e);
-if(!_98){
-return;
-}
-_98.header.baseDecorateEvent(e);
-this.grid.removeHoverSortTip(e);
-this.lastHeaderFocus.cellNode=this._colHeadNode;
-}
-},getFocusView:function(e){
-var _99;
-dojo.forEach(this.grid.views.views,function(_9a){
-if(!_99){
-var _9b=dojo.coords(_9a.domNode),_9c=dojo.coords(e.target);
-var _9d=_9c.x>=_9b.x&&_9c.x<=(_9b.x+_9b.w);
-_9d&&(_99=_9a);
-}
+
+dojo.declare("dojox.grid.enhanced.plugins._NestedSortingFocusManager", dojox.grid._FocusManager, {
+	// summary:
+	//		Provides keyboard focus support for nested sorting
+
+	//lastHeaderFocus: Object
+	//		Last header focus info
+	lastHeaderFocus :{cellNode:null, regionIdx:-1},
+	
+	//currentHeaderFocusEvt: Object
+	//		Dummy event for current header focus	
+	currentHeaderFocusEvt: null,
+
+	//cssMarkers: Array
+	//		CSS class markers for select region, nested sort wrapper and unary sort wrapper
+	cssMarkers : ['dojoxGridHeaderCellSelectRegion', 'dojoxGridNestedSortWrapper', 'dojoxGridUnarySortWrapper'],
+
+	//_focusBorderBox: Dom node
+	//		Root of focus border divs
+	_focusBorderBox: null,
+	
+	_initColumnHeaders: function(){
+		// summary:
+		//		Bind onfocus and onblur hanlders to regions in each header cell node
+		var headerNodes = this._findHeaderCells();
+		dojo.forEach(headerNodes, dojo.hitch(this, function(headerNode){
+			var selectRegion = dojo.query('.dojoxGridHeaderCellSelectRegion', headerNode);
+			var sortRegions = dojo.query("[class*='SortWrapper']", headerNode);
+			selectRegion = selectRegion.concat(sortRegions);
+			selectRegion.length == 0 && (selectRegion = [headerNode]);
+			dojo.forEach(selectRegion, dojo.hitch(this, function(node){
+				this._connects.push(dojo.connect(node, "onfocus", this, "doColHeaderFocus"));				
+				this._connects.push(dojo.connect(node, "onblur", this, "doColHeaderBlur"));
+			}));
+		}));
+	},
+
+	focusHeader: function(leadingDir, delayed, ignoreRegionPos){
+		// summary:
+		//		Overwritten, see _FocusManager.focusHeader()
+		//leadingDir: Boolean
+		//		If focus is switching to leading direction
+		//delayed: Boolean
+		//		If called from "this._delayedHeaderFocus()"
+		//ignoreRegionPos: Boolean
+		//		If always focus on the 1st region(select region) for each header cell node
+		if(!this.isNavHeader()){
+			//focus navigated from cells
+			this.inherited(arguments);	
+		}else{
+			var headerNodes = this._findHeaderCells();
+			this._colHeadNode = headerNodes[this._colHeadFocusIdx];
+			delayed && (this.lastHeaderFocus.cellNode = this._colHeadNode);
+		}
+		if(!this._colHeadNode){
+			return;
+		}
+		//jump over the 1st indirect selection cell(column)
+		if(this.grid.indirectSelection && this._colHeadFocusIdx == 0){
+			this._colHeadNode = this._findHeaderCells()[++this._colHeadFocusIdx];
+		}		
+		var focusRegionIdx = ignoreRegionPos ? 0 : (this.lastHeaderFocus.regionIdx >= 0 ? this.lastHeaderFocus.regionIdx : (leadingDir ? 2 : 0));
+		var focusRegion = dojo.query('.' + this.cssMarkers[focusRegionIdx], this._colHeadNode)[0] || this._colHeadNode;
+		this.grid.addHoverSortTip(this.currentHeaderFocusEvt = this._mockEvt(focusRegion));
+		this.lastHeaderFocus.regionIdx = focusRegionIdx;
+		focusRegion && dojox.grid.util.fire(focusRegion, "focus");
+	},
+	
+	focusSelectColEndingHeader: function(e){
+		// summary:
+		//		Put focus on the ending column header cell for swipe column selecting(when DnD plugin is on).
+		//		See dojox.grid.enhanced.dnd._DndBuilder.domouseup()
+		// e: Event
+		//		Decorated event object that contains reference to grid header or content
+		if(!e || !e.cellNode) return ;
+		this._colHeadFocusIdx = e.cellIndex;
+		this.focusHeader(null, false, true);
+	},
+	
+	_delayedHeaderFocus: function(){
+		// summary:
+		//		Overwritten, see _FocusManager._delayedHeaderFocus()		
+		//this.needFocusSupport() && this.isNavHeader() && this.focusHeader(null, true);
+		this.isNavHeader() && this.focusHeader(null, true);
+	},
+	
+	_setActiveColHeader: function(/*Node*/colHeaderNode, /*Integer*/colFocusIdx, /*Integer*/ prevColFocusIdx){
+		// summary:
+		//		Overwritten, see _FocusManager._setActiveColHeader()		
+		dojo.attr(this.grid.domNode, "aria-activedescendant",colHeaderNode.id);
+		this._colHeadNode = colHeaderNode;
+		this._colHeadFocusIdx = colFocusIdx;
+	},
+	
+	doColHeaderFocus: function(e){
+		// summary:
+		//		Overwritten, see _FocusManager.doColHeaderFocus()		
+        this.lastHeaderFocus.cellNode = this._colHeadNode;
+		if(e.target == this._colHeadNode){
+			this._scrollHeader(this.getHeaderIndex());
+		}else{
+			var focusView = this.getFocusView(e);
+			if(!focusView){ return; }		
+			focusView.header.baseDecorateEvent(e);
+			this._addFocusBorder(e.target);
+			this._colHeadFocusIdx = e.cellIndex;
+			this._colHeadNode = this._findHeaderCells()[this._colHeadFocusIdx];
+			// try to avoid the e.cell is undefined error.
+			this._colHeadNode && this.getHeaderIndex() != -1 && this._scrollHeader(this._colHeadFocusIdx);
+		}
+		this._focusifyCellNode(false);
+		this.grid.isDndSelectEnable && this.grid.focus._blurRowBar();
+		//fix sort position of first column is missed when 2nd column is added using keyboard.
+		this.grid.addHoverSortTip(this.currentHeaderFocusEvt = this._mockEvt(e.target));
+		
+		//fix ie rtl, focus add a border to the element, so need to change width of selection region
+		if(dojo.isIE && !dojo._isBodyLtr()){
+			this.grid._fixAllSelectRegion();
+		}
+	},
+	
+	doColHeaderBlur: function(e){
+		// summary:
+		//		Overwritten, see _FocusManager.doColHeaderBlur()		
+		this.inherited(arguments);
+		this._removeFocusBorder();
+		//if(!this.isNavHeader() || this.lastHeaderFocus.cellNode && this.lastHeaderFocus.cellNode != this._colHeadNode){
+		if(!this.isNavCellRegion){
+			var focusView = this.getFocusView(e);
+			if(!focusView){ return; }		
+			focusView.header.baseDecorateEvent(e);
+			this.grid.removeHoverSortTip(e);
+			this.lastHeaderFocus.cellNode = this._colHeadNode;
+		}
+	},
+	
+	getFocusView: function(e){
+		// summary:
+		//		Get the current focus view
+		// e: Event
+		//		Event that triggers the current focus
+		// return: Object
+		//		The current focus view
+		var focusView;
+		dojo.forEach(this.grid.views.views, function(view){
+			if(!focusView){
+				var viewBox = dojo.coords(view.domNode), targetBox = dojo.coords(e.target);
+				var inRange = targetBox.x >= viewBox.x && targetBox.x <= (viewBox.x + viewBox.w);
+				inRange && (focusView = view);
+			}
+		});
+		return (this.focusView = focusView);
+	},
+		
+	_mockEvt: function(region){
+		// summary:
+		//		Return a mocked decorated event for currently focused column header cell.
+		// region: Dom node
+		//		Target dom node			
+		// return: Object
+		//		Overwritten, see _FocusManager.doColHeaderBlur()		
+		var cell = this.grid.getCell(this._colHeadFocusIdx);
+		return {target:region, cellIndex: this._colHeadFocusIdx, cell: cell,
+				cellNode: this._colHeadNode, clientX:-1, sourceView: cell.view};
+	},
+	
+	navHeader: function(e){
+		// summary:
+		//		Navigate focus across column header cells or regions.
+		// e: Event
+		//		Un-decorated event object
+		var offset= e.ctrlKey ? 0 : (e.keyCode == dojo.keys.LEFT_ARROW) ? -1 : 1;
+		!dojo._isBodyLtr() && (offset *= -1);
+		this.focusView.header.baseDecorateEvent(e);
+		dojo.forEach(this.cssMarkers, dojo.hitch(this, function(css, index){
+			if(dojo.hasClass(e.target, css)){
+				var newPos = index + offset,region,nextRegion;
+				do{
+					region = dojo.query('.'+this.cssMarkers[newPos], e.cellNode)[0];
+					if(region && dojo.style(region.lastChild || region.firstChild, 'display') != 'none'){
+						nextRegion = region;
+						break;	
+					}
+					newPos += offset;
+				}while(newPos >=0 && newPos < this.cssMarkers.length);
+				if(nextRegion && newPos >= 0 && newPos < this.cssMarkers.length){
+					if(e.ctrlKey){return;}
+					//in IE, avoid removing hover tip during cell region navigation, see this.grid.removeHoverSortTip(e)
+					dojo.isIE && (this.grid._sortTipMap[e.cellIndex] = false);
+					this.navCellRegion(nextRegion, newPos);
+					return;
+				}
+				var delta = newPos < 0 ? -1 : (newPos >= this.cssMarkers.length ? 1 : 0);
+				this.navHeaderNode(delta);
+			}
+		}));
+	},
+	
+	navHeaderNode: function(delta, ignoreRegionPos){
+		// summary:
+		//		Navigate focus across column header cells.
+		// delta: Integer
+		//		1 | 0 | -1, navigating direction
+		// ignoreRegionPos: Boolean
+		//		If always focus on the 1st region(select region) for each header cell node		
+		var _newColHeadFocusIdx = this._colHeadFocusIdx + delta;
+		var headers = this._findHeaderCells();
+		while(_newColHeadFocusIdx >=0 && _newColHeadFocusIdx < headers.length 
+			&& headers[_newColHeadFocusIdx].style.display == "none"){
+			// skip over hidden column headers
+			_newColHeadFocusIdx += delta;
+		}
+		
+		if(this.grid.indirectSelection && _newColHeadFocusIdx == 0){
+			return;//simply ignore indirect selection column
+		}
+		if(delta != 0 && _newColHeadFocusIdx >= 0 && _newColHeadFocusIdx < this.grid.layout.cells.length){
+			this.lastHeaderFocus.cellNode = this._colHeadNode;
+			this.lastHeaderFocus.regionIdx = -1;
+			this._colHeadFocusIdx = _newColHeadFocusIdx;
+			this.focusHeader(delta < 0 ? true/*navigate towards leading direction*/ : false/*navigate towards trail direction*/, false, ignoreRegionPos);				
+		}
+	},
+	
+	navCellRegion:function(nextRegion, newPos){
+		// summary:
+		//		Navigate focus across regions within a column header cell.
+		// nextRegion: Dom node
+		//		Next region node to be focused
+		// newPos: Integer
+		//		New region index			
+		this.isNavCellRegion = true;
+		dojox.grid.util.fire(nextRegion, "focus");
+		this.currentHeaderFocusEvt.target = nextRegion;
+		this.lastHeaderFocus.regionIdx = newPos;
+		var selectRegion = newPos == 0 ? nextRegion : nextRegion.parentNode.nextSibling;
+		selectRegion && this.grid._fixSelectRegion(selectRegion);
+		this.isNavCellRegion = false;
+	},
+
+	headerCellInFocus: function(cellIndex){
+		// summary:
+		//		See if column header cell(with cellIndex) is now having focus
+		// cellIndex: Integer
+		//		Cell (column) index
+		// return: Boolean
+		//		If the column header cell(with cellIndex) is now having focus.
+		return (this._colHeadFocusIdx == cellIndex) && this._focusBorderBox;
+	},
+	
+	clearHeaderFocus: function(){
+		// summary:
+		//		Clear focus in column header cell		
+		this._colHeadNode = this._colHeadFocusIdx = null;
+		this.lastHeaderFocus = {cellNode:null, regionIdx:-1};
+	},
+
+	addSortFocus: function(e){
+		// summary:
+		//		 Add focus to sort region in column header cell by mouse click
+		//		 See NestedSorting.setSortIndex()
+		// e: Event
+		//		Decorated event object which contains reference to grid, target cell etc.
+		var cellSortInfo = this.grid.getCellSortInfo(e.cell);
+		if(!cellSortInfo) 
+			return;
+		var _sortAttrs = this.grid.sortAttrs;		
+		var notSorted = !_sortAttrs || _sortAttrs.length < 1;		
+		var inUnarySort = (_sortAttrs && _sortAttrs.length == 1 && cellSortInfo["sortPos"] == 1);
+		this._colHeadFocusIdx = e.cellIndex;
+		this._colHeadNode = e.cellNode;
+		this.currentHeaderFocusEvt = {};
+		this.lastHeaderFocus.regionIdx = (notSorted || inUnarySort) ? 2 : (e.nestedSortChoice ? 1 : 0);
+	},	
+	
+	_addFocusBorder: function(node){
+		// summary:
+		//		 Add focus borders to node, use this instead of native CSS way to fix border wobbling issue
+		// node: Dom node
+		//		Target node to add focus borders	
+		if(!node) return ;
+		this._removeFocusBorder();
+		this._focusBorderBox = dojo.create('div');
+		this._focusBorderBox.className = 'dojoxGridFocusBorderBox';
+		dojo.toggleClass(node, "dojoxGridSelectRegionFocus", true);
+		dojo.toggleClass(node, "dojoxGridSelectRegionHover", false);
+		
+		//cache the height - in IE6 the value will be doubled after 'node.insertBefore()'
+		var nodeH = node.offsetHeight;
+		if(node.hasChildNodes()){
+			node.insertBefore(this._focusBorderBox, node.firstChild);
+		}else{
+			node.appendChild(this._focusBorderBox);
+		}
+		
+		var _d = {'l': 0, 't': 0, 'r': 0, 'b': 0};		
+		for(var i in _d){
+			_d[i] = dojo.create('div');
+		}
+		
+		var pos = {
+			x: dojo.coords(node).x - dojo.coords(this._focusBorderBox).x ,
+			y: dojo.coords(node).y - dojo.coords(this._focusBorderBox).y,
+			w: node.offsetWidth,
+			h: nodeH
+		};
+		for(var i in _d){
+			var n = _d[i];
+			dojo.addClass(n, 'dojoxGridFocusBorder');
+			dojo.style(n, 'top', pos.y + 'px');
+			dojo.style(n, 'left', pos.x + 'px');
+			this._focusBorderBox.appendChild(n);
+		}
+		var normalize = function(val){
+			return val > 0 ? val : 0;
+		}
+		dojo.style(_d.r, 'left',   normalize(pos.x + pos.w - 1) + 'px');
+		dojo.style(_d.b, 'top',    normalize(pos.y + pos.h - 1) + 'px');		
+		dojo.style(_d.l, 'height', normalize(pos.h - 1) + 'px');
+		dojo.style(_d.r, 'height', normalize(pos.h - 1) + 'px');
+		dojo.style(_d.t, 'width',  normalize(pos.w - 1) + 'px');
+		dojo.style(_d.b, 'width',  normalize(pos.w - 1) + 'px');
+	},
+	
+	_updateFocusBorder: function(){
+		// summary:
+		//		 Update focus borders.
+		if(this._focusBorderBox == null){
+			return;
+		}
+		this._addFocusBorder(this._focusBorderBox.parentNode);
+	},
+
+	_removeFocusBorder: function(){
+		// summary:
+		//		 Remove focus borders.		
+		if(this._focusBorderBox && this._focusBorderBox.parentNode){
+			dojo.toggleClass(this._focusBorderBox.parentNode, "dojoxGridSelectRegionFocus", false);
+			this._focusBorderBox.parentNode.removeChild(this._focusBorderBox);
+			
+		}			
+		this._focusBorderBox = null;
+	}
 });
-return (this.focusView=_99);
-},_mockEvt:function(_9e){
-var _9f=this.grid.getCell(this._colHeadFocusIdx);
-return {target:_9e,cellIndex:this._colHeadFocusIdx,cell:_9f,cellNode:this._colHeadNode,clientX:-1,sourceView:_9f.view};
-},navHeader:function(e){
-var _a0=e.ctrlKey?0:(e.keyCode==dojo.keys.LEFT_ARROW)?-1:1;
-!dojo._isBodyLtr()&&(_a0*=-1);
-this.focusView.header.baseDecorateEvent(e);
-dojo.forEach(this.cssMarkers,dojo.hitch(this,function(css,_a1){
-if(dojo.hasClass(e.target,css)){
-var _a2=_a1+_a0,_a3,_a4;
-do{
-_a3=dojo.query("."+this.cssMarkers[_a2],e.cellNode)[0];
-if(_a3&&dojo.style(_a3.lastChild||_a3.firstChild,"display")!="none"){
-_a4=_a3;
-break;
-}
-_a2+=_a0;
-}while(_a2>=0&&_a2<this.cssMarkers.length);
-if(_a4&&_a2>=0&&_a2<this.cssMarkers.length){
-if(e.ctrlKey){
-return;
-}
-dojo.isIE&&(this.grid._sortTipMap[e.cellIndex]=false);
-this.navCellRegion(_a4,_a2);
-return;
-}
-var _a5=_a2<0?-1:(_a2>=this.cssMarkers.length?1:0);
-this.navHeaderNode(_a5);
-}
-}));
-},navHeaderNode:function(_a6,_a7){
-var _a8=this._colHeadFocusIdx+_a6;
-var _a9=this._findHeaderCells();
-while(_a8>=0&&_a8<_a9.length&&_a9[_a8].style.display=="none"){
-_a8+=_a6;
-}
-if(this.grid.indirectSelection&&_a8==0){
-return;
-}
-if(_a6!=0&&_a8>=0&&_a8<this.grid.layout.cells.length){
-this.lastHeaderFocus.cellNode=this._colHeadNode;
-this.lastHeaderFocus.regionIdx=-1;
-this._colHeadFocusIdx=_a8;
-this.focusHeader(_a6<0?true:false,false,_a7);
-}
-},navCellRegion:function(_aa,_ab){
-this.isNavCellRegion=true;
-dojox.grid.util.fire(_aa,"focus");
-this.currentHeaderFocusEvt.target=_aa;
-this.lastHeaderFocus.regionIdx=_ab;
-var _ac=_ab==0?_aa:_aa.parentNode.nextSibling;
-_ac&&this.grid._fixSelectRegion(_ac);
-this.isNavCellRegion=false;
-},headerCellInFocus:function(_ad){
-return (this._colHeadFocusIdx==_ad)&&this._focusBorderBox;
-},clearHeaderFocus:function(){
-this._colHeadNode=this._colHeadFocusIdx=null;
-this.lastHeaderFocus={cellNode:null,regionIdx:-1};
-},addSortFocus:function(e){
-var _ae=this.grid.getCellSortInfo(e.cell);
-if(!_ae){
-return;
-}
-var _af=this.grid.sortAttrs;
-var _b0=!_af||_af.length<1;
-var _b1=(_af&&_af.length==1&&_ae["sortPos"]==1);
-this._colHeadFocusIdx=e.cellIndex;
-this._colHeadNode=e.cellNode;
-this.currentHeaderFocusEvt={};
-this.lastHeaderFocus.regionIdx=(_b0||_b1)?2:(e.nestedSortChoice?1:0);
-},_addFocusBorder:function(_b2){
-if(!_b2){
-return;
-}
-this._removeFocusBorder();
-this._focusBorderBox=dojo.create("div");
-this._focusBorderBox.className="dojoxGridFocusBorderBox";
-dojo.toggleClass(_b2,"dojoxGridSelectRegionFocus",true);
-dojo.toggleClass(_b2,"dojoxGridSelectRegionHover",false);
-var _b3=_b2.offsetHeight;
-if(_b2.hasChildNodes()){
-_b2.insertBefore(this._focusBorderBox,_b2.firstChild);
-}else{
-_b2.appendChild(this._focusBorderBox);
-}
-var _b4={"l":0,"t":0,"r":0,"b":0};
-for(var i in _b4){
-_b4[i]=dojo.create("div");
-}
-var pos={x:dojo.coords(_b2).x-dojo.coords(this._focusBorderBox).x,y:dojo.coords(_b2).y-dojo.coords(this._focusBorderBox).y,w:_b2.offsetWidth,h:_b3};
-for(var i in _b4){
-var n=_b4[i];
-dojo.addClass(n,"dojoxGridFocusBorder");
-dojo.style(n,"top",pos.y+"px");
-dojo.style(n,"left",pos.x+"px");
-this._focusBorderBox.appendChild(n);
-}
-var _b5=function(val){
-return val>0?val:0;
-};
-dojo.style(_b4.r,"left",_b5(pos.x+pos.w-1)+"px");
-dojo.style(_b4.b,"top",_b5(pos.y+pos.h-1)+"px");
-dojo.style(_b4.l,"height",_b5(pos.h-1)+"px");
-dojo.style(_b4.r,"height",_b5(pos.h-1)+"px");
-dojo.style(_b4.t,"width",_b5(pos.w-1)+"px");
-dojo.style(_b4.b,"width",_b5(pos.w-1)+"px");
-},_updateFocusBorder:function(){
-if(this._focusBorderBox==null){
-return;
-}
-this._addFocusBorder(this._focusBorderBox.parentNode);
-},_removeFocusBorder:function(){
-if(this._focusBorderBox&&this._focusBorderBox.parentNode){
-dojo.toggleClass(this._focusBorderBox.parentNode,"dojoxGridSelectRegionFocus",false);
-this._focusBorderBox.parentNode.removeChild(this._focusBorderBox);
-}
-this._focusBorderBox=null;
-}});
-}
diff --git a/dojox/grid/enhanced/resources/EnhancedGrid.css b/dojox/grid/enhanced/resources/EnhancedGrid.css
index 81acd6d..26a7aec 100644
--- a/dojox/grid/enhanced/resources/EnhancedGrid.css
+++ b/dojox/grid/enhanced/resources/EnhancedGrid.css
@@ -1,52 +1,64 @@
-.dojoxGridCellContent{
+.dojoxGridCellContent {
 	padding:3px;
 }
-.dojoxGridHeader .dojoxGridCell .dojoxGridSortNode{
+
+.dojoxGridSortNode {
 	padding:3px;
 }
-.dojoxGridCell .dojoxGridSortRoot{
+
+.dojoxGridSortRoot {
 	position: relative; 
 	width: 100%;
-	text-align:left; 
+	text-align:left; /*fix the selection region jumping when hover in IE7*/
 }
-.dojoxGridCell .dojoxGridHeaderCellSelectRegion{
+
+.dojoxGridHeaderCellSelectRegion {
 	text-align: left;
 	padding:3px;
-	
+	/*position:absolute;*/
 	overflow: hidden;
 	white-space:nowrap;
 }
-.dj_ie .dojoxGridCell .dojoxGridHeaderCellSelectRegion{
+
+.dj_ie .dojoxGridHeaderCellSelectRegion {
 	padding-left:4px;
 }
-.dojoxGridSortWrapper{
-	
+
+.dojoxGridSortWrapper {
+	/*float:right;*/
 	position:absolute;
 	right:0px;
-	
+	/*left: auto;*/
 	z-index: 1;
 }
-.dojoxGridNestedSortWrapper{
+
+.dojoxGridNestedSortWrapper {
 	float:left;
 }
-.dojoxGridSortPos{
+
+.dojoxGridSortPos {
 	float:left;
 	margin-left:3px;
 }
-.dj_ff2 .dojoxGridSortPos{
+
+.dj_ff2 .dojoxGridSortPos {
 	padding: 3px 0;
 	line-height: normal;
 }
-.dojoxGridSortPosOff{
+
+.dojoxGridSortPosOff {
 	display:none;
 }
-.dojoxGridNestedSort{
+
+.dojoxGridNestedSort {
 	text-indent: -5000em;
 }
-.dojoxGridUnarySortWrapper{
+
+.dojoxGridUnarySortWrapper {
 	float:left;
 }
-.dojoxGridSort{
+
+.dojoxGridSort {
 	display: block;
 	float: left;
 	background:url("images/nestedSortArrows.png") no-repeat left center;
@@ -55,59 +67,72 @@
 	margin-left:3px;
 	text-align:center;
 }
-.dojoxGridUnarySort{
+
+.dojoxGridUnarySort {
 	text-indent: -5000em;
 	margin-left:4px;
 }
-.dojoxGridAscending{
+
+.dojoxGridAscending {
 	background-position: -9px;
 }
-.dojoxGridUnsorted{
+
+.dojoxGridUnsorted {
 	display:none;
 }
-.dojoxGridAscendingTip{
+
+.dojoxGridAscendingTip {
 	background:url("images/nestedSortArrows.png") no-repeat left center;
 	background-position: -30px;
 	display:block;
 	cursor:pointer;
 }
-.dojoxGridDescendingTip{
+
+.dojoxGridDescendingTip {
 	background:url("images/nestedSortArrows.png") no-repeat left center;
 	background-position: -20px;
 	display:block;
 	cursor:pointer;
 }
-.dojoxGridUnsortedTip{
+
+.dojoxGridUnsortedTip {
 	background:url("images/nestedSortArrows.png") no-repeat left center;
 	background-position: -39.5px;
 	display:block;
 	cursor:pointer;
 }
-.dojoxGridSortHiddenTip{
+
+.dojoxGridSortHiddenTip {
 	display:none;
 }
-.dojoxGridSortSeparatorOff{
+
+.dojoxGridSortSeparatorOff {
 	width: 0px;
 	border-right-color: #999999;
 	border-right-style:solid;
 	border-right-width:1px;
 	display: none;
 }
-.dojoxGridSortSeparatorOn{
+
+.dojoxGridSortSeparatorOn {
 	display: block;
 	float: left;
 }
-.dojoxGridSortInProgress{
+
+.dojoxGridSortInProgress {
 	cursor:progress;
 }
-.dojoxGridWidgetHidden{
+
+/* Indirect Selection */
+.dojoxGridWidgetHidden {
 	visibility:hidden;
 }
+
 .dijit_a11y .dojoxGridNestedSort, .dijit_a11y .dojoxGridUnarySort {
 	text-indent: 0;
-	font-size: 14px;
-	
+	/* background-image: none !important; - for testing*/
 }
+
 .dojoxGridFocusBorderBox {
 	position: relative;
 	top: 0;
@@ -115,6 +140,7 @@
 	width: 0;
 	height: 0;
 }
+
 .dojoxGridFocusBorder {
 	width: 0px;
 	height: 0px;
@@ -124,33 +150,41 @@
 	top: 0;
 	left: 0;
 }
-.dojoxGridSelectedDIV{
+
+/** dnd **/
+.dojoxGridSelectedDIV {
 	background-color: #3366CC;
 	position:absolute;
 	opacity:0.2;
 	cursor:move;
 	z-index:999;
 }
-.dj_ie .dojoxGridSelectedDIV{
+
+.dj_ie .dojoxGridSelectedDIV {
 	filter: alpha(opacity = 30);
 }
-.dojoxGridBorderDIV{
+
+.dojoxGridBorderDIV {
 	width:3px;
 	background-color: gray;
 	font-size:0em;
 	position:absolute;
 	z-index:9999;
 }
-.dojoxGrid{
+
+.dojoxGrid {
 	border:1px solid #DBDBDB;
 }
-.dijit_a11y .dojoxGridRowSelected{
+
+.dijit_a11y .dojoxGridRowSelected {
 	opacity:0.4 !important;
 }
-.dijit_a11y .dojoxGridSelectedDIV{
+
+.dijit_a11y .dojoxGridSelectedDIV {
 	opacity:0.4 !important;
 	border:3px solid #000 !important;
 }
-.dijit_a11y .dojoxGridBorderDIV{
+
+.dijit_a11y .dojoxGridBorderDIV {
 	border:2px solid #000 !important;
 }
diff --git a/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css b/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css
index fb28690..b191473 100644
--- a/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css
+++ b/dojox/grid/enhanced/resources/EnhancedGrid_rtl.css
@@ -1,23 +1,31 @@
-.dj_ie .dijitRtl .dojoxGridHeader table {
-	float:none;
-}
-.dijitRtl .dojoxGridCell {
-	text-align:right;
-}
-.dijitRtl .dojoxGridNestedSort, 
-.dijitRtl .dojoxGridUnarySort {
+ at import url("../../resources/Grid_rtl.css");
+
+.dojoxGridRtl .dojoxGridNestedSort, 
+.dojoxGridRtl .dojoxGridUnarySort {
 	text-align: right;
 }
-.dijitRtl .dojoxGridSortWrapper {
+
+.dojoxGridRtl .dojoxGridSortWrapper {
 	left: 0;
 	right: auto;
 }
-.dijitRtl .dojoxGridCell .dojoxGridHeaderCellSelectRegion {
+
+.dojoxGridRtl .dojoxGridCell .dojoxGridHeaderCellSelectRegion {
 	float: right;
 	text-align: right;
+	padding-right:4px;
 }
-.dijitRtl .dojoxGridSortSeparatorOn,
-.dijitRtl .dojoxGridNestedSortWrapper,
-.dijitRtl .dojoxGridUnarySortWrapper {
+
+.dojoxGridRtl .dojoxGridSortSeparatorOn,
+.dojoxGridRtl .dojoxGridNestedSortWrapper,
+.dojoxGridRtl .dojoxGridUnarySortWrapper {
 	float: right;
 }
+
+.dojoxGridRtl .dojoxGridLoading, 
+.dojoxGridRtl .dojoxGridError,
+.dojoxGridRtl .dojoxGridNoData {
+	background-position:right;
+	padding-right:25px;
+	padding-left:0px;
+}
diff --git a/dojox/grid/enhanced/resources/claroEnhancedGrid.css b/dojox/grid/enhanced/resources/claroEnhancedGrid.css
new file mode 100644
index 0000000..50390d5
--- /dev/null
+++ b/dojox/grid/enhanced/resources/claroEnhancedGrid.css
@@ -0,0 +1,104 @@
+ at import url("EnhancedGrid.css");
+ at import url("../../resources/claroGrid.css");
+
+/* overwrite claroGrid.css */
+.claro .dojoxGridRowbarInner {
+	width:20px;
+}
+/* end overwrite */
+
+/* header cell root container */
+.claro .dojoxGridSortHover {
+	border-color:#a5beda; 
+	border-bottom-color:#5c7590; 
+	color:#243C5F;
+	cursor:pointer;
+	background-color:#abd5fd;
+}
+.claro .dojoxGridSortRoot {
+	background:url("../../resources/images/header_shadow.png") repeat-x bottom;
+	color:#000;
+	text-decoration:none;
+	border:1px solid #e0eefb;
+	height:100%;
+	display:block;
+	margin-left:-1px;
+}
+.dj_ie .claro .dojoxGridSortRoot {
+	border-right:1px solid #bcbcbc;
+}
+
+/* header cell sorting wrapper & selection region (for selecting column) */
+.claro .dojoxGridHeaderCellSelectRegion {
+	padding:4px 0px 5px 6px;
+}
+.claro .dojoxGridSelectRegionHover {
+	cursor:pointer;
+	color:#243C5F;
+	text-decoration:none;
+}
+.claro .dojoxGridSelectRegionHover,
+.claro .dojoxGridCellOver .dojoxGridSortWrapper,
+.claro .dojoxGridHeaderSelected .dojoxGridHeaderCellSelectRegion {
+	background:url("../../resources/images/header.png") #abd5fd repeat-x bottom;
+}
+.claro .dojoxGridCellOver .dojoxGridSortWrapper {
+	background-color:transparent;
+}
+.claro .dojoxGridHeaderSelected .dojoxGridHeaderActive {
+	background-color:#91c9fe;
+}
+
+/* column selection */
+.claro td.dojoxGridRowSelected {
+	border-collapse:separate;
+	border:1px solid #BFD6EB;
+	border-bottom:1px solid transparent;
+	background:url("../../resources/images/row_back.png") #e3f2ff repeat-x;
+	/*border:solid 1px #A0BFDD;*/
+}
+.dj_ie6 .claro td.dojoxGridRowSelected,
+.dj_ie6 .claro .dojoxGridRowOdd td.dojoxGridRowSelected {
+	border-color:#BFD6EB;
+}
+.claro .dojoxGridRowOver td.dojoxGridRowSelected {
+	border-top:1px solid #769DC0;
+	border-bottom:1px solid #769DC0;
+}
+.claro .dojoxGridRowActive td.dojoxGridRowSelected {
+	background-image:url("../../resources/images/td_button_down.png");
+}
+
+/* focus border */
+.claro .dojoxGridFocusBorder {
+	border-top: 1px dashed darkblue;
+	border-left: 1px dashed darkblue;
+}
+
+/** dnd **/
+.claro .dojoxGridSelectedDIV {
+	background-color: #3366CC;
+}
+.dj_ie .claro .dojoxGridSelectedDIV {
+	filter: alpha(opacity = 30);
+}
+.claro .dojoxGridBorderDIV {
+	background-color:#769DC0;
+}
+
+.dj_ie6 .claro .dojoxGridSortRoot,
+.dj_ie6 .claro .dojoxGridSelectRegionHover,
+.dj_ie6 .claro .dojoxGridCellOver .dojoxGridSortWrapper,
+.dj_ie6 .claro .dojoxGridHeaderSelected .dojoxGridHeaderCellSelectRegion {
+	background-image:none;
+}
+
+/* Don't need any explicit outlines */
+.claro .dojoxGridCell,
+.claro .dojoxGridCellFocus,
+.claro .dojoxGridHeaderCellSelectRegion,
+.claro .dojoxGridUnarySortWrapper,
+.claro .dojoxGridNestedSortWrapper,
+.claro .dojoxGridSortRoot {
+	outline: none;
+}
diff --git a/dojox/grid/enhanced/resources/tundraEnhancedGrid.css b/dojox/grid/enhanced/resources/tundraEnhancedGrid.css
index 2f3fd60..09a94fc 100644
--- a/dojox/grid/enhanced/resources/tundraEnhancedGrid.css
+++ b/dojox/grid/enhanced/resources/tundraEnhancedGrid.css
@@ -1,789 +1,86 @@
-.dojoxGridCellContent{
-	padding:3px;
-}
-.dojoxGridHeader .dojoxGridCell .dojoxGridSortNode{
-	padding:3px;
-}
-.dojoxGridCell .dojoxGridSortRoot{
-	position: relative; 
-	width: 100%;
-	text-align:left; 
-}
-.dojoxGridCell .dojoxGridHeaderCellSelectRegion{
-	text-align: left;
-	padding:3px;
-	
-	overflow: hidden;
-	white-space:nowrap;
-}
-.dj_ie .dojoxGridCell .dojoxGridHeaderCellSelectRegion{
-	padding-left:4px;
-}
-.dojoxGridSortWrapper{
-	
-	position:absolute;
-	right:0px;
-	
-	z-index: 1;
-}
-.dojoxGridNestedSortWrapper{
-	float:left;
-}
-.dojoxGridSortPos{
-	float:left;
-	margin-left:3px;
-}
-.dj_ff2 .dojoxGridSortPos{
-	padding: 3px 0;
-	line-height: normal;
-}
-.dojoxGridSortPosOff{
-	display:none;
-}
-.dojoxGridNestedSort{
-	text-indent: -5000em;
-}
-.dojoxGridUnarySortWrapper{
-	float:left;
-}
-.dojoxGridSort{
-	display: block;
-	float: left;
-	background:url(images/nestedSortArrows.png) no-repeat left center;
-	width: 8px;
-	margin-right:3px;
-	margin-left:3px;
-	text-align:center;
-}
-.dojoxGridUnarySort{
-	text-indent: -5000em;
-	margin-left:4px;
-}
-.dojoxGridAscending{
-	background-position: -9px;
-}
-.dojoxGridUnsorted{
-	display:none;
-}
-.dojoxGridAscendingTip{
-	background:url(images/nestedSortArrows.png) no-repeat left center;
-	background-position: -30px;
-	display:block;
-	cursor:pointer;
-}
-.dojoxGridDescendingTip{
-	background:url(images/nestedSortArrows.png) no-repeat left center;
-	background-position: -20px;
-	display:block;
-	cursor:pointer;
-}
-.dojoxGridUnsortedTip{
-	background:url(images/nestedSortArrows.png) no-repeat left center;
-	background-position: -39.5px;
-	display:block;
-	cursor:pointer;
-}
-.dojoxGridSortHiddenTip{
-	display:none;
-}
-.dojoxGridSortSeparatorOff{
-	width: 0px;
-	border-right-color: #999999;
-	border-right-style:solid;
-	border-right-width:1px;
-	display: none;
-}
-.dojoxGridSortSeparatorOn{
-	display: block;
-	float: left;
-}
-.dojoxGridSortInProgress{
-	cursor:progress;
-}
-.dojoxGridWidgetHidden{
-	visibility:hidden;
-}
-.dijit_a11y .dojoxGridNestedSort, .dijit_a11y .dojoxGridUnarySort {
-	text-indent: 0;
-	font-size: 14px;
-	
-}
-.dojoxGridFocusBorderBox {
-	position: relative;
-	top: 0;
-	left: 0;
-	width: 0;
-	height: 0;
-}
-.dojoxGridFocusBorder {
-	width: 0px;
-	height: 0px;
-	overflow: hidden;
-	position: absolute;
-	z-index: 999;
-	top: 0;
-	left: 0;
-}
-.dojoxGridSelectedDIV{
-	background-color: #3366CC;
-	position:absolute;
-	opacity:0.2;
-	cursor:move;
-	z-index:999;
-}
-.dj_ie .dojoxGridSelectedDIV{
-	filter: alpha(opacity = 30);
-}
-.dojoxGridBorderDIV{
-	width:3px;
-	background-color: gray;
-	font-size:0em;
-	position:absolute;
-	z-index:9999;
-}
-.dojoxGrid{
-	border:1px solid #DBDBDB;
-}
-.dijit_a11y .dojoxGridRowSelected{
-	opacity:0.4 !important;
-}
-.dijit_a11y .dojoxGridSelectedDIV{
-	opacity:0.4 !important;
-	border:3px solid #000 !important;
-}
-.dijit_a11y .dojoxGridBorderDIV{
-	border:2px solid #000 !important;
-}
-.dojoxGrid {
-	position: relative;
-	background-color: #EBEADB;
-	font-family: Geneva, Arial, Helvetica, sans-serif;
-	-moz-outline-style: none;
-	outline: none;
-	overflow: hidden;
-	height: 0;
-}
-.dojoxGrid table {
-	padding: 0;
-}
-.dojoxGrid td {
-	-moz-outline: none;
-}
-.dojoxGridMasterHeader {
-	position: relative;
-}
-.dojoxGridMasterView  {
-	position: relative;
-}
-.dojoxGridMasterMessages {
-	position: relative;
-	padding: 1em;
-	text-align: center;
-	background-color: white;
-}
-.dojoxGridView {
-	position: absolute;
-	overflow: hidden;
-}
-.dojoxGridHeader {
-	position: absolute;
-	overflow: hidden;
-	cursor: default;
-}
-.dojoxGridHeader {
-	background-color: #E8E1CF;
-}
-.dojoxGridHeader table {
-	text-align: center;
-}
-.dojoxGridHeader .dojoxGridCell { 
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background: url(../../resources/images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-	padding-bottom: 2px;
-}
-.dojoxGridHeader .dojoxGridCellOver {
-	background-image: none;
-	background-color: white;
-	border-bottom-color: #FEBE47;
-	margin-bottom: 0;
-	padding-bottom: 0;
-	border-bottom-width: 3px;
-}
-.dojoxGridHeader .dojoxGridCellFocus {
-	border: 1px dashed blue;
-}
-.dojoxGridHeader.dojoxGridCellFocus.dojoxGridCellOver {
-	background-image: none;
-	background-color: white;
-	border-bottom-color: #FEBE47;
-	margin-bottom: 0;
-	padding-bottom: 0;
-	border-bottom-width: 3px;
-}
-.dojoxGridArrowButtonNode {
-	display: none;
-	padding-left: 16px;
-}
-.dojoxGridArrowButtonChar {
-	display:inline;
-}
- 
-.dojoxGridArrowButtonNode:hover {
-        cursor: default;
-}
-.dojoxGridArrowButtonChar:hover {
-        cursor: default;
-}
-.dojoxGridSortUp:hover {
-        cursor: default;
-}
-.dojoxGridSortDown:hover {
-        cursor: default;
-}
-.dijit_a11y .dojoxGridArrowButtonChar {
-	display:inline !important;
-}
-.dojoxGridScrollbox {
-	position: relative;
-	overflow: auto;
-	background-color: white;
-	width: 100%;
-}
-.dojoxGridContent {
-	position: relative;
-	overflow: hidden;
-	 -moz-outline-style: none;
-	outline: none;
-}
-.dojoxGridRowbar { 
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	border-top: none;
-	background: url(../../resources/images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-}
-.dojoxGridRowbarInner {
-	border-top: 1px solid #F6F4EB;
-}
-.dojoxGridRowbarOver {
-	background-image: none;
-	background-color: white;
-	border-top-color: #FEBE47;
-	border-bottom-color: #FEBE47;
-}
-.dojoxGridRowbarSelected {
-	background-color: #D9E8F9;
-}
-.dojoxGridRow {
-	position: relative;
-	width: 9000em;
-}
-.dojoxGridRow {
-	
-	border: 1px solid #E8E4D8;
-	border-color: #F8F7F1;
-	
-	border-left: none;
-	border-right: none;
-	background-color: white;
-	border-top: none;
-}
-.dojoxGridRowOver {
-	border-top-color: #FEBE47;
-	border-bottom-color: #FEBE47;
-	
-	
-	
-}
-.dojoxGridRowOdd {
-	background-color: #FFFDF3;
-	
-}
-.dojoxGridRowSelected {
-	background-color: #D9E8F9;
-}
-.dojoxGridRowTable {
-	table-layout: fixed;
-	width: 0;
-	empty-cells: show;
-}
-.dj_ie .dojoxGridRowTable {
-	border-collapse: collapse;
-}
-.dojoxGridInvisible {
-	visibility: hidden;
-}		
-.Xdojo-ie .dojoxGridInvisible {
-	display: none;
-}		
-.dojoxGridInvisible td, .dojoxGridHeader .dojoxGridInvisible td {
-	border-top-width: 0;
-	border-bottom-width: 0;
-	padding-top: 0;
-	padding-bottom: 0;
-	height: 0;
-	overflow: hidden;
-}
-.dojoxGridCell {
-	border: 1px solid;
-	border-color: #EBEADB;
-	border-right-color: #D5CDB5;
-	padding: 3px 3px 3px 3px;
-	text-align: left;
-	overflow: hidden;
-}
-.dojoxGridCellFocus {
-	border: 1px dashed blue;
-}
-.dojoxGridCellOver {
-	border: 1px dotted #FEBE47;
-}
-.dojoxGridCellFocus.dojoxGridCellOver {
-	border: 1px dashed green;
-}
-.dojoxGridRowEditing td {
-	background-color: #F4FFF4;
-}
-.dojoxGridRow-inserting td {
-	background-color: #F4FFF4;
-}
-.dojoxGridRow-inflight td {
-	background-color: #F2F7B7;
-}
-.dojoxGridRow-error td {
-	background-color: #F8B8B6;
-}
-.dojoxGridInput, .dojoxGridSelect, .dojoxGridTextarea {
-	margin: 0;
-	padding: 0;
-	border-style: none;
-	width: 100%;
-	font-size: 100%;
-	font-family: inherit;
-}
-.dojoxGridHiddenFocus {
-	position: absolute;
-	top: -1000px;
-	height: 0;
-	width: 0;
-}
-.dijit_a11y .dojoxGridRowbarSelected { 
-	border-top: 1px solid white;
-	border-bottom: 1px dashed black;
-	border-top: 0;
-	background: none;
-}
-.dijit_a11y .dojoxGridRowbarSelected .dojoxGridRowbarInner {
-	border: 0;
-	border-top: 1px solid white;
-}
-.dijit_a11y .dojoxGridRowSelected {
-	border: 1px solid black !important;
-}
-.dojoxGridDndAvatar {
-	font-size: 100%;
-}
-.dojoxGrid .dojoDndItemBefore {
-	border-left-color: red;
-}
-.dojoxGrid .dojoDndItemAfter {
-	border-right-color: red;
-}
-.dijit_a11y .dojoDndItemBefore {
-	border-left: double;
-}
-.dijit_a11y .dojoDndItemAfter {
-	border-right: double;
-}
-.dojoxGridDndAvatarItem	td {
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background: url(../../resources/images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-	padding: 0pt;
-	margin: 0pt;
-}
-.dojoxGridDndAvatarItem	td.dojoxGridDndAvatarItemImage {
-	border: 0;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background-color: transparent;
-	padding: 3px;
-	padding-bottom: 2px;
-	margin: 0;
-}
-.dojoDndMove .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../../dojo/resources/images/dndNoMove.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndCopy .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../../dojo/resources/images/dndNoCopy.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndMove .dojoDndAvatarCanDrop .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../../dojo/resources/images/dndMove.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndCopy .dojoDndAvatarCanDrop .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../../dojo/resources/images/dndCopy.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoxGridColPlaceBottom {
-	background: transparent url(../../resources/images/grid_sort_up.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop {
-	background: transparent url(../../resources/images/grid_sort_down.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop, .dojoxGridColPlaceBottom {
-	font-size:1px;
-	height:6px;
-	z-index:10000;
-	top:0;
-	overflow:hidden;
-	position:absolute;
-	line-height:1px;
-	width:8px;
-}
-.dojoxGridResizeColLine {
-	width: 1px;
-	background-color: #777;
-	position: absolute;
-	cursor: col-resize;
-	z-index:10000;
-}
-.dojoxGridColNoResize, 
-.dojoxGridColNoResize .dojoDndItemOver {
-	cursor: not-allowed !important;
-}
-.dojoxGridColResize, 
-.dojoxGridColResize .dojoDndItemOver,
-.dojoxGridColumnResizing,
-.dojoxGridColumnResizing .dojoDndItemOver,
-.dojoxGridColumnResizing .dojoxGridHeader {
-	cursor: col-resize !important;
-}
-.dojoxGridColPlaceBottom {
-	background: transparent url(../../resources/images/grid_sort_up.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop {
-	background: transparent url(../../resources/images/grid_sort_down.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop, .dojoxGridColPlaceBottom {
-	font-size:1px;
-	height:6px;
-	z-index:10000;
-	top:0;
-	overflow:hidden;
-	position:absolute;
-	line-height:1px;
-	width:8px;
-}
-.dojoxGridResizeColLine {
-	width: 1px;
-	background-color: #777;
-	position: absolute;
-}
-.dojoxGridExpandoCell {
-	vertical-align: top;
-}
-.dojoxGridSummarySpan {
-	visibility: hidden;
-}
-.dojoxGridSummaryRow .dojoxGridSummarySpan,
-.dojoxGridRowCollapsed .dojoxGridSummarySpan {
-	visibility: visible;
-}
-.dojoxGridNoChildren .dojoxGridExpando {
-	visibility: hidden !important;
-	width: 0px !important;
-}
-.tundra .dojoxGrid {
-	background-color: #e9e9e9;
-	font-size: 0.85em; 
-}
-.tundra .dojoxGridMasterMessages {
-	background-color: #fefefe;
-}
-.tundra .dojoxGridLoading, 
-.tundra .dojoxGridError {
-	background-position:left center;
-	background-repeat: no-repeat;
-	padding-left:25px;
-}
-.dijitRtl .tundra .dojoxGridLoading, 
-.dijitRtl .tundra .dojoxGridError,
-.dijitRtl .tundra .dojoxGridNoData {
-	background-position:right;
-	padding-right:25px;
-	padding-left:0px;
-}
-.tundra .dojoxGridLoading {
-	background-image: url(../../../../dijit/themes/tundra/images/loading.gif);
-}
-.tundra .dojoxGridError {
-	background-image: url(../../../../dijit/themes/tundra/images/warning.png);
-}
-.tundra .dojoxGridHeader {
-	background-color:  #e9e9e9;
-}
-.tundra .dojoxGridHeader .dojoxGridCell { 
-	border-width: 1px;
-	padding-bottom: 0px;
-	border-color: transparent #ACA899 #919191 transparent;
-	background: url(../../../../dijit/themes/tundra/images/tabEnabled.png) #e9e9e9 repeat-x top;
-	color: #000 !important;
-}
-.tundra .dojoxGridHeader .dojoxGridCellOver {
-	background: url(../../../../dijit/themes/tundra/images/tabHover.png) #e9e9e9 repeat-x top;
-	color: #000 !important;
-}
-.tundra .dojoxGridHeader .dojoxGridCellFocus {
-	border-color: #ACA899 #919191;
-	border-style: dashed;
-}
-.tundra .dojoxGridArrowButtonChar {
-	float: right;
-	display: none;
-}
-.tundra .dojoxGridArrowButtonNode {
-	display: block !important;
-	padding-left: 0px;
-	float: right;
-	background:url(../../../../dijit/themes/tundra/images/spriteArrows.png) no-repeat left center;
-	width: 7px;
-	height: 1em;
-	margin: 2px 4px 0px 5px;
-}
-.dj_ie6 .tundra .dojoxGridArrowButtonNode {
-	background-image:url(../../../../dijit/themes/tundra/images/spriteArrows.gif);
-	margin-left: 0px;
-}
-.tundra .dojoxGridSortUp .dojoxGridArrowButtonNode {
-	background-position: -21px;
-}
-.dijit_a11y .tundra .dojoxGridArrowButtonNode {
-	display: none !important;
-}
-.tundra .dojoxGridScrollbox {
-	background-color: #fefefe;
-}
-.tundra .dojoxGridRowbar { 
-	border: none;
-	background: url(../../resources/images/tabEnabled_rotated.png) #e9e9e9 repeat-y right;
-	border-right: 1px solid #ccc;
-	padding: 0px;
-}
-.tundra .dojoxGridRowbarInner {
-	border: none;
-	border-bottom: 1px solid #ccc;
-}
-.tundra .dojoxGridRowbarOver {
-	background: url(../../resources/images/tabHover_rotated.png) #e9e9e9 repeat-y right;
-}
-.tundra .dojoxGridRowbarSelected {
-	background: url(../../../../dijit/themes/tundra/images/tabDisabled.png) #D8E8F9 no-repeat center;
-	border-right: 1px solid #ccc;
-}
-.tundra .dojoxGridRow {
-	border: none;
-	background-color: white;
-}
-.tundra .dojoxGridRowOver {
-	border-top-color: #ccc;
-	border-bottom-color: #ccc;
-}
-.tundra .dojoxGridRowOver .dojoxGridCell {
-	background-color: #60a1ea; 
-	color:#fff;
-}
-.tundra .dojoxGridRowOver .dojoxGridCell .dijit {
-	color: #000;
-}
-.tundra .dojoxGridRowOver .dojoxGridCell .dijitDisabled {
-	color: gray;
-}
-.tundra .dojoxGridRowOdd {
-	background-color: #f2f5f9;
-}
-.tundra .dojoxGridRowSelected {
-	background-color: #aec7e3 !important;
-}
-.dijit_a11y .tundra .dojoxGridRowSelected { 
-    background-color: #aec7e3;     
-    border-style: solid;     
-}   
-.tundra .dojoxGridCell {
-	border: 1px dotted #D5CDB5;
-	border-left-color: transparent;
-	border-top-color: transparent;
-}
-.dj_ff2 .tundra .dojoxGridCell {
-	border-left-width: 0px;
-	border-top-width: 0px;
-}
-.dj_ie6 .tundra .dojoxGridCell {
-	border: 1px solid white;
-	border-right: 1px solid #D5CDB5;
-}
-.tundra .dojoxGridCellFocus {
-	border: 1px dashed darkblue !important;
-}
-.tundra .dojoxGridCellOver {
-	border: 1px dotted #a6a6a6;
-}
-.tundra .dojoxGridCellFocus .dojoxGridCellOver {
-	border: 1px dashed darkblue !important;
-}
-.tundra .dojoxGridRowEditing td {
-	
-	background-color: #60a1ea; 
-	
-}
-.tundra .dojoxGridRow-inserting td {
-	background-color: #F4FFF4;
-}
-.tundra .dojoxGridRow-inflight td {
-	background-color: #F2F7B7;
-}
-.tundra .dojoxGridRow-error td {
-	background-color: #F8B8B6;
-}
-.tundra .dojoxGrid .dojoDndItemBefore {
-	border-left-color: #3559ac;
-}
-.tundra .dojoxGrid .dojoDndItemAfter {
-	border-right-color: #3559ac;
-}
-.tundra .dojoxGridExpando {
-	float: left;
-	height: 18px;
-	width: 18px;
-	text-align: center;
-	margin-top: -3px;
-}
-.dijitRtl .tundra .dojoxGridExpando {
-	float: right;
-}
-.tundra .dojoxGridExpandoCell {
-	padding-top: 5px;
-}
-.tundra .dojoxGridExpandoNode {
-	height: 18px;
-	background-image: url(../../../../dijit/themes/tundra/images/treeExpand_plus.gif);
-}
-.tundra .dojoxGridExpandoOpened .dojoxGridExpandoNode {
-	background-image: url(../../../../dijit/themes/tundra/images/treeExpand_minus.gif);		
-}
-.tundra .dojoxGridExpandoLoading .dojoxGridExpandoNode {
-	background-image: url(../../../../dijit/themes/tundra/images/treeExpand_loading.gif);		
-}
-.tundra .dojoxGridTreeModel .dojoxGridNoChildren .dojoxGridExpando {
-	visibility: visible !important;
-	width: 18px !important;
-}
-.tundra .dojoxGridTreeModel .dojoxGridNoChildren .dojoxGridExpandoNode {
-	background-image: url(../../../../dijit/themes/tundra/images/treeExpand_leaf.gif);
-	background-position: -3px;
-}
-.tundra .dojoxGridExpandoNodeInner {
-	visibility: hidden;
-}
-.dijit_a11y .dojoxGridExpandoNodeInner {
-	visibility: visible;
-}
-		
-.tundra .dojoxGridSummaryRow .dojoxGridCell {
-	border-top-color: #999;
-	border-top-style: solid;
-}
-.tundra .dojoxGridSpacerCell,
-.tundra .dojoxGridExpandoCell,
-.tundra .dojoxGridSummaryRow .dojoxGridSpacerCell {
-	border-color: transparent;
-	border-right-color: #D5CDB5;
-}
-.tundra .dojoxGridSummaryRow .dojoxGridTotalCell,
-.tundra .dojoxGridRowCollapsed .dojoxGridExpandoCell,
-.tundra .dojoxGridTreeModel .dojoxGridExpandoCell {
-	border-bottom-color: #D5CDB5;
-}
-.tundra .dojoxGridSubRowAlt {
-	background-color: #F8F8F8;
-}
-.tundra .dojoxGridRowOdd .dojoxGridSubRowAlt {
-	background-color: #EDEFF3;
-}
+ at import url("EnhancedGrid.css");
+ at import url("../../resources/tundraGrid.css");
+
+/* overwrite */
 .tundra .dojoxGridHeader .dojoxGridCell{
 	background: #fafafa url(../../../../dijit/themes/tundra/images/titleBar.png) repeat-x bottom left;
 	border-top: 1px solid #bfbfbf;
-	
+	/*border-left-width: 0px;*/
 }
-.tundra .dojoxGridHeader .dojoxGridCell,
-.tundra .dojoxGridCell{
+
+.tundra .dojoxGridCell {
 	padding:0px;
-	
-	
-	
+	/*display:inline;*/
+	/*position:relative;*/
+	/*border-left-width: 0px;*/
 }
+
 .dj_ie6 .tundra .dojoxGridMasterView .dojoxGridCellOver{
 	border: 1px dashed #e9e9e9;
-	background:none;
 }
+
 .dj_ie6 .tundra .dojoxGridHeader .dojoxGridCellOver{
 	border-bottom: none !important;
 	border-right: 1px solid #D5CDB5 !important;
 	border-top: 1px solid #D5CDB5 !important;
 }
+
 .tundra .dojoxGridRowbarInner {
 	width:20px;
 }
-.tundra .dojoxGridHeader .dojoxGridCellOver .dojoxGridSortNode{
+
+.tundra .dojoxGridCellOver .dojoxGridSortNode{
 	cursor:pointer;
 	background: #f8fafd url("../../../../dijit/themes/tundra/images/accordionItemHover.gif") bottom repeat-x;
 }
-.tundra .dojoxGridCell .dojoxGridSelectRegionHover{
+/* end overwrite */
+
+.tundra .dojoxGridSelectRegionHover{
 	border-color:		#a5beda; 
 	border-bottom-color:#5c7590; 
 	cursor:pointer;
 	color:#243C5F;
 	background: #f8fafd url("../../../../dijit/themes/tundra/images/accordionItemHover.gif") bottom repeat-x;
 }
-.tundra .dojoxGridCell .dojoxGridSortHover{
+
+.tundra .dojoxGridSortHover{
 	border-color:		#a5beda; 
 	border-bottom-color:#5c7590; 
 	color:#243C5F;
 	background: #f8fafd url("../../../../dijit/themes/tundra/images/accordionItemHover.gif") bottom repeat-x;
 	cursor:pointer;
 }
+
 .tundra .dojoxGridSortWrapper{
 	background: #fafafa url(../../../../dijit/themes/tundra/images/titleBar.png) repeat-x bottom left;
 }
+
+
+/* fix safari focus border - overwrite */
 .dj_webkit .tundra .dojoxGridCell,
 .dj_webkit .tundra .dojoxGridCellFocus,
-.dj_webkit .tundra .dojoxGridHeader .dojoxGridCell .dojoxGridHeaderCellSelectRegion,
-.dj_webkit .tundra .dojoxGridHeader .dojoxGridCell .dojoxGridUnarySortWrapper,
-.dj_webkit .tundra .dojoxGridHeader .dojoxGridCell .dojoxGridNestedSortWrapper,
-.dj_webkit .tundra .dojoxGridHeader .dojoxGridCell .dojoxGridSortRoot{
+.dj_webkit .tundra .dojoxGridHeaderCellSelectRegion,
+.dj_webkit .tundra .dojoxGridUnarySortWrapper,
+.dj_webkit .tundra .dojoxGridNestedSortWrapper,
+.dj_webkit .tundra .dojoxGridSortRoot{
 	outline: none;
 }
-.tundra .dojoxGridHeader .dojoxGridRowTable .dojoxGridCellFocus
- {
-	border-color: darkblue !important;
-	border-style: dashed !important;
-	border-width: 1px !important;
-}
+
+/* focus border */
 .tundra .dojoxGridFocusBorder {
 	border-top: 1px dashed darkblue;
 	border-left: 1px dashed darkblue;
 }
+
+/** dnd **/
 .tundra .dojoxGridSelectedDIV{
 	background-color: #3366CC;
 }
+
 .dj_ie .tundra .dojoxGridSelectedDIV{
 	filter: alpha(opacity = 30);
 }
+
 .tundra .dojoxGridBorderDIV{
 	background-color: gray;
 }
diff --git a/dojox/grid/nls/DataGrid_ROOT.js b/dojox/grid/nls/DataGrid_ROOT.js
deleted file mode 100644
index a95f772..0000000
--- a/dojox/grid/nls/DataGrid_ROOT.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_ROOT");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"};
diff --git a/dojox/grid/nls/DataGrid_ar.js b/dojox/grid/nls/DataGrid_ar.js
deleted file mode 100644
index 6ac1ce7..0000000
--- a/dojox/grid/nls/DataGrid_ar.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_ar");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ar");dijit.nls.loading.ar={"loadingState":"جاري التحميل...","errorState":"عفوا، حدث خطأ"};
diff --git a/dojox/grid/nls/DataGrid_ca.js b/dojox/grid/nls/DataGrid_ca.js
deleted file mode 100644
index 4772c8c..0000000
--- a/dojox/grid/nls/DataGrid_ca.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_ca");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."};
diff --git a/dojox/grid/nls/DataGrid_cs.js b/dojox/grid/nls/DataGrid_cs.js
deleted file mode 100644
index 1f896c1..0000000
--- a/dojox/grid/nls/DataGrid_cs.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_cs");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ě"};
diff --git a/dojox/grid/nls/DataGrid_da.js b/dojox/grid/nls/DataGrid_da.js
deleted file mode 100644
index cd0891e..0000000
--- a/dojox/grid/nls/DataGrid_da.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_da");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"};
diff --git a/dojox/grid/nls/DataGrid_de-de.js b/dojox/grid/nls/DataGrid_de-de.js
deleted file mode 100644
index 091508c..0000000
--- a/dojox/grid/nls/DataGrid_de-de.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_de-de");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."};
diff --git a/dojox/grid/nls/DataGrid_de.js b/dojox/grid/nls/DataGrid_de.js
deleted file mode 100644
index 8c376f9..0000000
--- a/dojox/grid/nls/DataGrid_de.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_de");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."};
diff --git a/dojox/grid/nls/DataGrid_el.js b/dojox/grid/nls/DataGrid_el.js
deleted file mode 100644
index f52ad5a..0000000
--- a/dojox/grid/nls/DataGrid_el.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_el");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.el");dijit.nls.loading.el={"loadingState":"Φόρτωση...","errorState":"Σας ζητούμε συγνώμη, παρουσιάστηκε σφάλμα"};
diff --git a/dojox/grid/nls/DataGrid_en-gb.js b/dojox/grid/nls/DataGrid_en-gb.js
deleted file mode 100644
index 979fa29..0000000
--- a/dojox/grid/nls/DataGrid_en-gb.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_en-gb");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"};
diff --git a/dojox/grid/nls/DataGrid_en-us.js b/dojox/grid/nls/DataGrid_en-us.js
deleted file mode 100644
index a18e498..0000000
--- a/dojox/grid/nls/DataGrid_en-us.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_en-us");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"};
diff --git a/dojox/grid/nls/DataGrid_en.js b/dojox/grid/nls/DataGrid_en.js
deleted file mode 100644
index 2d189ff..0000000
--- a/dojox/grid/nls/DataGrid_en.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_en");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"};
diff --git a/dojox/grid/nls/DataGrid_es-es.js b/dojox/grid/nls/DataGrid_es-es.js
deleted file mode 100644
index 4d7081a..0000000
--- a/dojox/grid/nls/DataGrid_es-es.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_es-es");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"};
diff --git a/dojox/grid/nls/DataGrid_es.js b/dojox/grid/nls/DataGrid_es.js
deleted file mode 100644
index de8a105..0000000
--- a/dojox/grid/nls/DataGrid_es.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_es");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"};
diff --git a/dojox/grid/nls/DataGrid_fi-fi.js b/dojox/grid/nls/DataGrid_fi-fi.js
deleted file mode 100644
index 5300b36..0000000
--- a/dojox/grid/nls/DataGrid_fi-fi.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_fi-fi");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."};
diff --git a/dojox/grid/nls/DataGrid_fi.js b/dojox/grid/nls/DataGrid_fi.js
deleted file mode 100644
index 04f4d1a..0000000
--- a/dojox/grid/nls/DataGrid_fi.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_fi");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."};
diff --git a/dojox/grid/nls/DataGrid_fr-fr.js b/dojox/grid/nls/DataGrid_fr-fr.js
deleted file mode 100644
index 9d007ff..0000000
--- a/dojox/grid/nls/DataGrid_fr-fr.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_fr-fr");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"};
diff --git a/dojox/grid/nls/DataGrid_fr.js b/dojox/grid/nls/DataGrid_fr.js
deleted file mode 100644
index db846cc..0000000
--- a/dojox/grid/nls/DataGrid_fr.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_fr");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"};
diff --git a/dojox/grid/nls/DataGrid_he-il.js b/dojox/grid/nls/DataGrid_he-il.js
deleted file mode 100644
index cd3b2d5..0000000
--- a/dojox/grid/nls/DataGrid_he-il.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_he-il");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.he_il");dijit.nls.loading.he_il={"loadingState":"טעינה...‏","errorState":"אירעה שגיאה"};
diff --git a/dojox/grid/nls/DataGrid_he.js b/dojox/grid/nls/DataGrid_he.js
deleted file mode 100644
index dae1263..0000000
--- a/dojox/grid/nls/DataGrid_he.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_he");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.he");dijit.nls.loading.he={"loadingState":"טעינה...‏","errorState":"אירעה שגיאה"};
diff --git a/dojox/grid/nls/DataGrid_hu.js b/dojox/grid/nls/DataGrid_hu.js
deleted file mode 100644
index 1d797c2..0000000
--- a/dojox/grid/nls/DataGrid_hu.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_hu");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"};
diff --git a/dojox/grid/nls/DataGrid_it-it.js b/dojox/grid/nls/DataGrid_it-it.js
deleted file mode 100644
index 79a0800..0000000
--- a/dojox/grid/nls/DataGrid_it-it.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_it-it");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"};
diff --git a/dojox/grid/nls/DataGrid_it.js b/dojox/grid/nls/DataGrid_it.js
deleted file mode 100644
index dbe95e8..0000000
--- a/dojox/grid/nls/DataGrid_it.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_it");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"};
diff --git a/dojox/grid/nls/DataGrid_ja-jp.js b/dojox/grid/nls/DataGrid_ja-jp.js
deleted file mode 100644
index f74a69a..0000000
--- a/dojox/grid/nls/DataGrid_ja-jp.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_ja-jp");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ja_jp");dijit.nls.loading.ja_jp={"loadingState":"ロード中...","errorState":"エラーが発生しました。"};
diff --git a/dojox/grid/nls/DataGrid_ja.js b/dojox/grid/nls/DataGrid_ja.js
deleted file mode 100644
index db1f3ae..0000000
--- a/dojox/grid/nls/DataGrid_ja.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_ja");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ja");dijit.nls.loading.ja={"loadingState":"ロード中...","errorState":"エラーが発生しました。"};
diff --git a/dojox/grid/nls/DataGrid_ko-kr.js b/dojox/grid/nls/DataGrid_ko-kr.js
deleted file mode 100644
index 81e6a54..0000000
--- a/dojox/grid/nls/DataGrid_ko-kr.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_ko-kr");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ko_kr");dijit.nls.loading.ko_kr={"loadingState":"로드 중...","errorState":"죄송합니다. 오류가 발생했습니다."};
diff --git a/dojox/grid/nls/DataGrid_ko.js b/dojox/grid/nls/DataGrid_ko.js
deleted file mode 100644
index 5012b35..0000000
--- a/dojox/grid/nls/DataGrid_ko.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_ko");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ko");dijit.nls.loading.ko={"loadingState":"로드 중...","errorState":"죄송합니다. 오류가 발생했습니다."};
diff --git a/dojox/grid/nls/DataGrid_nb.js b/dojox/grid/nls/DataGrid_nb.js
deleted file mode 100644
index b838bd7..0000000
--- a/dojox/grid/nls/DataGrid_nb.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_nb");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.nb");dijit.nls.loading.nb={"loadingState":"Laster inn...","errorState":"Det oppsto en feil"};
diff --git a/dojox/grid/nls/DataGrid_nl-nl.js b/dojox/grid/nls/DataGrid_nl-nl.js
deleted file mode 100644
index 9813f74..0000000
--- a/dojox/grid/nls/DataGrid_nl-nl.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_nl-nl");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"};
diff --git a/dojox/grid/nls/DataGrid_nl.js b/dojox/grid/nls/DataGrid_nl.js
deleted file mode 100644
index dadd520..0000000
--- a/dojox/grid/nls/DataGrid_nl.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_nl");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"};
diff --git a/dojox/grid/nls/DataGrid_pl.js b/dojox/grid/nls/DataGrid_pl.js
deleted file mode 100644
index 1383697..0000000
--- a/dojox/grid/nls/DataGrid_pl.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_pl");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"};
diff --git a/dojox/grid/nls/DataGrid_pt-br.js b/dojox/grid/nls/DataGrid_pt-br.js
deleted file mode 100644
index 4548bb7..0000000
--- a/dojox/grid/nls/DataGrid_pt-br.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_pt-br");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"};
diff --git a/dojox/grid/nls/DataGrid_pt-pt.js b/dojox/grid/nls/DataGrid_pt-pt.js
deleted file mode 100644
index a713464..0000000
--- a/dojox/grid/nls/DataGrid_pt-pt.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_pt-pt");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"};
diff --git a/dojox/grid/nls/DataGrid_pt.js b/dojox/grid/nls/DataGrid_pt.js
deleted file mode 100644
index 3ba7a88..0000000
--- a/dojox/grid/nls/DataGrid_pt.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_pt");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"};
diff --git a/dojox/grid/nls/DataGrid_ru.js b/dojox/grid/nls/DataGrid_ru.js
deleted file mode 100644
index 22e6000..0000000
--- a/dojox/grid/nls/DataGrid_ru.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_ru");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.ru");dijit.nls.loading.ru={"loadingState":"Загрузка...","errorState":"Извините, возникла ошибка"};
diff --git a/dojox/grid/nls/DataGrid_sk.js b/dojox/grid/nls/DataGrid_sk.js
deleted file mode 100644
index 1df6472..0000000
--- a/dojox/grid/nls/DataGrid_sk.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_sk");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"};
diff --git a/dojox/grid/nls/DataGrid_sl.js b/dojox/grid/nls/DataGrid_sl.js
deleted file mode 100644
index 4bd6a1f..0000000
--- a/dojox/grid/nls/DataGrid_sl.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_sl");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."};
diff --git a/dojox/grid/nls/DataGrid_sv.js b/dojox/grid/nls/DataGrid_sv.js
deleted file mode 100644
index bbd3927..0000000
--- a/dojox/grid/nls/DataGrid_sv.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_sv");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."};
diff --git a/dojox/grid/nls/DataGrid_th.js b/dojox/grid/nls/DataGrid_th.js
deleted file mode 100644
index 5bf0e6e..0000000
--- a/dojox/grid/nls/DataGrid_th.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_th");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.th");dijit.nls.loading.th={"loadingState":"กำลังโหลด...","errorState":"ขออภัย เกิดข้อผิดพลาด"};
diff --git a/dojox/grid/nls/DataGrid_tr.js b/dojox/grid/nls/DataGrid_tr.js
deleted file mode 100644
index daaccd6..0000000
--- a/dojox/grid/nls/DataGrid_tr.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_tr");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"};
diff --git a/dojox/grid/nls/DataGrid_xx.js b/dojox/grid/nls/DataGrid_xx.js
deleted file mode 100644
index 2b58b5c..0000000
--- a/dojox/grid/nls/DataGrid_xx.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_xx");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"};
diff --git a/dojox/grid/nls/DataGrid_zh-cn.js b/dojox/grid/nls/DataGrid_zh-cn.js
deleted file mode 100644
index e862be9..0000000
--- a/dojox/grid/nls/DataGrid_zh-cn.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_zh-cn");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.zh_cn");dijit.nls.loading.zh_cn={"loadingState":"正在加载...","errorState":"对不起,发生了错误"};
diff --git a/dojox/grid/nls/DataGrid_zh-tw.js b/dojox/grid/nls/DataGrid_zh-tw.js
deleted file mode 100644
index 7cbfddf..0000000
--- a/dojox/grid/nls/DataGrid_zh-tw.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_zh-tw");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.zh_tw");dijit.nls.loading.zh_tw={"loadingState":"載入中...","errorState":"抱歉,發生錯誤"};
diff --git a/dojox/grid/nls/DataGrid_zh.js b/dojox/grid/nls/DataGrid_zh.js
deleted file mode 100644
index aa7d899..0000000
--- a/dojox/grid/nls/DataGrid_zh.js
+++ /dev/null
@@ -1 +0,0 @@
-dojo.provide("dojox.grid.nls.DataGrid_zh");dojo.provide("dijit.nls.loading");dijit.nls.loading._built=true;dojo.provide("dijit.nls.loading.zh");dijit.nls.loading.zh={"loadingState":"正在加载...","errorState":"对不起,发生了错误"};
diff --git a/dojox/grid/resources/Grid.css b/dojox/grid/resources/Grid.css
index d419139..05ff524 100644
--- a/dojox/grid/resources/Grid.css
+++ b/dojox/grid/resources/Grid.css
@@ -7,45 +7,66 @@
 	overflow: hidden;
 	height: 0;
 }
+
 .dojoxGrid table {
 	padding: 0;
 }
+
 .dojoxGrid td {
 	-moz-outline: none;
 }
+
+/* master header */
+
 .dojoxGridMasterHeader {
 	position: relative;
 }
+
+/* master view */
+
 .dojoxGridMasterView  {
 	position: relative;
 }
+
+/* master messages */
+
 .dojoxGridMasterMessages {
 	position: relative;
 	padding: 1em;
 	text-align: center;
 	background-color: white;
 }
+
+/* views */
+
 .dojoxGridView {
 	position: absolute;
 	overflow: hidden;
 }
+
+/* header */
+
 .dojoxGridHeader {
 	position: absolute;
 	overflow: hidden;
 	cursor: default;
 }
+
 .dojoxGridHeader {
 	background-color: #E8E1CF;
 }
+
 .dojoxGridHeader table {
 	text-align: center;
 }
+
 .dojoxGridHeader .dojoxGridCell { 
 	border: 1px solid;
 	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
 	background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
 	padding-bottom: 2px;
 }
+
 .dojoxGridHeader .dojoxGridCellOver {
 	background-image: none;
 	background-color: white;
@@ -54,9 +75,11 @@
 	padding-bottom: 0;
 	border-bottom-width: 3px;
 }
+
 .dojoxGridHeader .dojoxGridCellFocus {
 	border: 1px dashed blue;
 }
+
 .dojoxGridHeader.dojoxGridCellFocus.dojoxGridCellOver {
 	background-image: none;
 	background-color: white;
@@ -65,6 +88,10 @@
 	padding-bottom: 0;
 	border-bottom-width: 3px;
 }
+
+.dojoxGridSortNode{
+	white-space:nowrap;
+}
 .dojoxGridArrowButtonNode {
 	display: none;
 	padding-left: 16px;
@@ -72,7 +99,11 @@
 .dojoxGridArrowButtonChar {
 	display:inline;
 }
- 
+.dojoxGridColCaption {
+	overflow:hidden;
+}
+
+/* Need to explicitly define how to treat hovering over the arrow on IE */ 
 .dojoxGridArrowButtonNode:hover {
         cursor: default;
 }
@@ -85,67 +116,87 @@
 .dojoxGridSortDown:hover {
         cursor: default;
 }
+
 .dijit_a11y .dojoxGridArrowButtonChar {
 	display:inline !important;
 }
+
+/* content */
+
 .dojoxGridScrollbox {
 	position: relative;
 	overflow: auto;
 	background-color: white;
 	width: 100%;
 }
+
 .dojoxGridContent {
 	position: relative;
 	overflow: hidden;
 	 -moz-outline-style: none;
 	outline: none;
 }
+
+/* rowbar */
+
 .dojoxGridRowbar { 
 	border: 1px solid;
 	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
 	border-top: none;
 	background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
 }
+
 .dojoxGridRowbarInner {
 	border-top: 1px solid #F6F4EB;
 }
+
 .dojoxGridRowbarOver {
 	background-image: none;
 	background-color: white;
 	border-top-color: #FEBE47;
 	border-bottom-color: #FEBE47;
 }
+
 .dojoxGridRowbarSelected {
 	background-color: #D9E8F9;
 }
+
+/* rows */
+
 .dojoxGridRow {
 	position: relative;
 	width: 9000em;
 }
+
 .dojoxGridRow {
-	
+	/*border: 1px solid #E8E4D8;*/
 	border: 1px solid #E8E4D8;
 	border-color: #F8F7F1;
-	
+	/*padding: 0 0 1px 0;*/
 	border-left: none;
 	border-right: none;
 	background-color: white;
 	border-top: none;
 }
+
 .dojoxGridRowOver {
 	border-top-color: #FEBE47;
 	border-bottom-color: #FEBE47;
-	
-	
-	
+	/*border-bottom-width: 2px;
+	padding-bottom: 0;*/
+	/*background-color: #FFDD9D;*/
+	/*background-color: #FDFDFD;*/
 }
+
 .dojoxGridRowOdd {
 	background-color: #FFFDF3;
-	
+	/*background-color: #F9F7E8;*/
 }
+
 .dojoxGridRowSelected {
 	background-color: #D9E8F9;
 }
+
 .dojoxGridRowTable {
 	table-layout: fixed;
 	width: 0;
@@ -154,12 +205,15 @@
 .dj_ie .dojoxGridRowTable {
 	border-collapse: collapse;
 }
+
 .dojoxGridInvisible {
 	visibility: hidden;
 }		
+
 .Xdojo-ie .dojoxGridInvisible {
 	display: none;
 }		
+
 .dojoxGridInvisible td, .dojoxGridHeader .dojoxGridInvisible td {
 	border-top-width: 0;
 	border-bottom-width: 0;
@@ -168,6 +222,9 @@
 	height: 0;
 	overflow: hidden;
 }
+
+/* cells */
+
 .dojoxGridCell {
 	border: 1px solid;
 	border-color: #EBEADB;
@@ -176,18 +233,25 @@
 	text-align: left;
 	overflow: hidden;
 }
+
 .dojoxGridCellFocus {
 	border: 1px dashed blue;
 }
+
 .dojoxGridCellOver {
 	border: 1px dotted #FEBE47;
 }
+
 .dojoxGridCellFocus.dojoxGridCellOver {
 	border: 1px dashed green;
 }
+
+/* editing */
+
 .dojoxGridRowEditing td {
 	background-color: #F4FFF4;
 }
+
 .dojoxGridRow-inserting td {
 	background-color: #F4FFF4;
 }
@@ -197,6 +261,7 @@
 .dojoxGridRow-error td {
 	background-color: #F8B8B6;
 }
+
 .dojoxGridInput, .dojoxGridSelect, .dojoxGridTextarea {
 	margin: 0;
 	padding: 0;
@@ -205,25 +270,31 @@
 	font-size: 100%;
 	font-family: inherit;
 }
+
 .dojoxGridHiddenFocus {
 	position: absolute;
 	top: -1000px;
 	height: 0;
 	width: 0;
 }
+
 .dijit_a11y .dojoxGridRowbarSelected { 
 	border-top: 1px solid white;
 	border-bottom: 1px dashed black;
 	border-top: 0;
 	background: none;
 }
+
 .dijit_a11y .dojoxGridRowbarSelected .dojoxGridRowbarInner {
 	border: 0;
 	border-top: 1px solid white;
 }
+
 .dijit_a11y .dojoxGridRowSelected {
 	border: 1px solid black !important;
 }
+
+/* Drag and Drop */
 .dojoxGridDndAvatar {
 	font-size: 100%;
 }
@@ -274,12 +345,14 @@
 	background-repeat: no-repeat;
 	background-position: center center;
 }
+
 .dojoxGridColPlaceBottom {
 	background: transparent url(images/grid_sort_up.gif) no-repeat scroll left top;
 }
 .dojoxGridColPlaceTop {
 	background: transparent url(images/grid_sort_down.gif) no-repeat scroll left top;
 }
+
 .dojoxGridColPlaceTop, .dojoxGridColPlaceBottom {
 	font-size:1px;
 	height:6px;
@@ -308,12 +381,14 @@
 .dojoxGridColumnResizing .dojoxGridHeader {
 	cursor: col-resize !important;
 }
+
 .dojoxGridColPlaceBottom {
 	background: transparent url(images/grid_sort_up.gif) no-repeat scroll left top;
 }
 .dojoxGridColPlaceTop {
 	background: transparent url(images/grid_sort_down.gif) no-repeat scroll left top;
 }
+
 .dojoxGridColPlaceTop, .dojoxGridColPlaceBottom {
 	font-size:1px;
 	height:6px;
@@ -329,6 +404,8 @@
 	background-color: #777;
 	position: absolute;
 }
+
+/* Tree Grid */
 .dojoxGridExpandoCell {
 	vertical-align: top;
 }
@@ -342,4 +419,4 @@
 .dojoxGridNoChildren .dojoxGridExpando {
 	visibility: hidden !important;
 	width: 0px !important;
-}
+}
\ No newline at end of file
diff --git a/dojox/grid/resources/Grid_rtl.css b/dojox/grid/resources/Grid_rtl.css
index fb8cbea..77d2dd5 100644
--- a/dojox/grid/resources/Grid_rtl.css
+++ b/dojox/grid/resources/Grid_rtl.css
@@ -1,6 +1,15 @@
-.dj_ie .dijitRtl .dojoxGridHeader table {
+.dj_ie .dojoxGridRtl .dojoxGridHeader table {
 	float:none;
 }
-.dijitRtl .dojoxGridCell {
+
+.dojoxGridRtl .dojoxGridCell {
 	text-align:right;
 }
+
+.dj_ie8 .dojoxGridRtl .dojoxGridCell {
+	border-left: none;
+}
+
+.dojoxGridRtl .dojoxGridArrowButtonNode {
+	float:left;
+}
\ No newline at end of file
diff --git a/dojox/grid/resources/_Grid.html b/dojox/grid/resources/_Grid.html
index 911862b..3e0cf33 100644
--- a/dojox/grid/resources/_Grid.html
+++ b/dojox/grid/resources/_Grid.html
@@ -1,4 +1,4 @@
-<div class="dojoxGrid" hidefocus="hidefocus" wairole="grid" dojoAttachEvent="onmouseout:_mouseOut">
+<div hidefocus="hidefocus" wairole="grid" dojoAttachEvent="onmouseout:_mouseOut">
 	<div class="dojoxGridMasterHeader" dojoAttachPoint="viewsHeaderNode" wairole="presentation"></div>
 	<div class="dojoxGridMasterView" dojoAttachPoint="viewsNode" wairole="presentation"></div>
 	<div class="dojoxGridMasterMessages" style="display: none;" dojoAttachPoint="messagesNode"></div>
diff --git a/dojox/grid/resources/claroGrid.css b/dojox/grid/resources/claroGrid.css
new file mode 100644
index 0000000..f1100b5
--- /dev/null
+++ b/dojox/grid/resources/claroGrid.css
@@ -0,0 +1,216 @@
+/* Claro styles for DataGrid */
+ at import url("Grid.css");
+
+.claro .dojoxGrid {
+	margin:0px;
+	padding:0px;
+	border-collapse:collapse;	
+	background-color:#fff;	
+}
+/*  messages */
+.claro .dojoxGridMasterMessages {
+	background-color: #fefefe;
+}
+.claro .dojoxGridLoading, 
+.claro .dojoxGridError {
+	background-position:left center;
+	background-repeat: no-repeat;
+	padding-left:25px;
+}
+.claro .dojoxGridLoading {
+	background-image:url("../../../dijit/themes/claro/images/loadingAnimation.gif");
+}
+.claro .dojoxGridError {
+	background-image: url('../../../dijit/icons/images/commonIconsObjActEnabled.png'); 
+	background-position: -496px;
+	width: 16px;
+	height: 16px;
+}
+
+/* header */
+.claro .dojoxGridHeader {
+	background-color:#FFF;
+}
+.claro .dojoxGridHeader .dojoxGridCell { 
+	background:url("images/header.png") #e5edf4 repeat-x top;
+	border-style:solid;
+	border-width:1px;
+	border-color:#BCBCBC #BCBCBC #BCBCBC transparent;
+}
+.dj_ie6 .claro .dojoxGridHeader .dojoxGridCell { 
+	border-color:#BCBCBC #BCBCBC #BCBCBC #e5edf4;
+}
+
+/* header sorting arrow */
+.claro .dojoxGridSortNode {
+	background:url("images/header_shadow.png") #e5edf4 repeat-x bottom;
+	text-decoration:none;
+	display:block;
+	padding:4px 6px 5px 6px;
+	border:1px solid #e0eefb;
+}
+.dj_ie6 .claro .dojoxGridSortNode {
+	background-image:none;
+}
+.claro .dojoxGridCellOver .dojoxGridSortNode {
+	background-color:#9dcfff;
+}
+.claro .dojoxGridArrowButtonChar {
+	display:none;
+	float:right;
+}
+.claro .dojoxGridArrowButtonNode {
+	background:transparent url("../../../dijit/themes/claro/images/spriteArrows.png") no-repeat scroll left center;
+	display:block;
+	float:right;
+	height:1em;
+	margin:2px 4px 0 5px;
+	padding-left:0;
+	width:7px;
+}
+.claro .dojoxGridSortUp .dojoxGridArrowButtonNode {
+	background-position:-21px 50%;
+}
+
+/* header rows */
+.dj_ie .claro .dojoxGridHeader .dojoxGridRowTable {
+	border-collapse:separate;
+}
+
+/* Grid view content */
+.claro .dojoxGridScrollbox {
+	background-color: #fefefe;
+}
+
+/* rowbar - row headers */
+.claro .dojoxGridRowbar { 
+	background:url("images/header.png") #e5edf4 repeat-x top;
+	border:none;
+	border-right:1px solid #BCBCBC;
+}
+.claro .dojoxGridRowbarTable { 
+	background:transparent url("images/header_shadow.png") repeat-x scroll center bottom;
+}
+.dj_ie6 .claro .dojoxGridRowbar,
+.dj_ie6 .claro .dojoxGridRowbarTable { 
+	background-image:none;
+}
+.claro .dojoxGridRowbarInner {
+	border:none;
+	border-bottom:1px solid #ccc;
+}
+.claro .dojoxGridRowbarOver .dojoxGridRowbarTable {
+	background-color:#abd5fd;
+}
+.claro .dojoxGridRowBarActive .dojoxGridRowbarTable {
+	background-color:#91c9fe;
+}
+.claro .dojoxGridRowbarSelected {
+	background-color:#abd5fd;
+	border-right:1px solid #ccc;
+}
+
+/* rows */
+.claro .dojoxGridRow {
+	border:none;
+	background-color:#fff;
+}
+.dj_ie .claro .dojoxGridMasterView .dojoxGridRowTable {
+	border-collapse:separate;/*IE, separate is must to show the border of tr and td*/
+}
+.claro .dojoxGridRowTable tr {
+	background:url("images/row_back.png") #fff repeat-x;
+}
+.claro .dojoxGridRowOdd .dojoxGridRowTable tr {
+	background-color:#f4f9fd;
+}
+.claro .dojoxGridRowSelected .dojoxGridRowTable tr {
+	background-color:#d3e9fb;
+}
+
+/* cells */
+.claro .dojoxGridCell {
+	padding:0px;
+	border:1px solid transparent;
+}
+.dj_ie6 .claro .dojoxGridCell {
+	border-color:#fff
+}
+.dj_ie6 .claro .dojoxGridRowOdd .dojoxGridCell {
+	border-left-color:#f4f9fd;
+	border-right-color:#f4f9fd;
+}
+.dj_ie6 .claro .dojoxGridRowSelected .dojoxGridCell {
+	border-left-color:#d3e9fb;
+	border-right-color:#d3e9fb;
+}
+.claro .dojoxGridRowSelected .dojoxGridCell {
+	border-top:1px solid #BFD6EB;
+	border-bottom:1px solid #BFD6EB;
+}
+.claro .dojoxGridCellFocus {
+	border:1px dashed darkblue !important;
+}
+.claro .dojoxGridCellContent {
+	padding:4px 6px 4px 6px;
+}
+
+/*  Single Affordance Hover Effect */
+.claro .dojoxGridRowOver .dojoxGridCell {
+	background:url("images/row_back.png") #ABD6FF;
+	border-top:1px solid #769DC0;
+	border-bottom:1px solid #769DC0;
+}
+.dj_ie6 .claro .dojoxGridRowOver .dojoxGridCell,
+.dj_ie7 .claro .dojoxGridRowOver .dojoxGridCell {
+	border-left:1px solid #ABD6FF;
+	border-right:1px solid #ABD6FF;
+}
+.claro .dojoxGridRowActive .dojoxGridCell {
+	background:url("images/td_button_down.png") #7DBEFA repeat-x;
+}
+.dj_ie6 .claro .dojoxGridRowActive .dojoxGridCell,
+.dj_ie7 .claro .dojoxGridRowActive .dojoxGridCell {
+	border-left:1px solid #7DBEFA;
+	border-right:1px solid #7DBEFA;	
+}
+
+/*  Double Affordance Hover Effect */
+.claro .dojoxGridDoubleAffordance .dojoxGridRowOver .dojoxGridCellOver {
+	border:solid 1px #769dc0;
+	background-color:#93cafe;
+	border-collapse:separate;/*FF*/
+}
+.claro .dojoxGridDoubleAffordance .dojoxGridRowActive .dojoxGridCell{	
+	background-image:url("images/row_back.png");
+}
+.claro .dojoxGridDoubleAffordance .dojoxGridRowActive .dojoxGridCellActive {	
+	background:url("images/td_button_down.png") #93cafe repeat-x;
+}
+.dj_ie6 .claro .dojoxGridCell {
+	background-image:none !important;
+}
+
+/* editing */
+.claro .dojoxGridRowEditing td {
+	/* background-color: #F4FFF4; */
+	background-color: #60a1ea; 
+	/* padding: 0px 3px 0px 3px; */
+}
+.claro .dojoxGridRow-inserting td {
+	background-color: #F4FFF4;
+}
+.claro .dojoxGridRow-inflight td {
+	background-color: #F2F7B7;
+}
+.claro .dojoxGridRow-error td {
+	background-color: #F8B8B6;
+}
+
+/* Drag and Drop */
+.claro .dojoxGrid .dojoDndItemBefore {
+	border-left-color: #3559ac;
+}
+.claro .dojoxGrid .dojoDndItemAfter {
+	border-right-color: #3559ac;
+}
\ No newline at end of file
diff --git a/dojox/grid/resources/images/header.png b/dojox/grid/resources/images/header.png
new file mode 100644
index 0000000..aa3e5ba
Binary files /dev/null and b/dojox/grid/resources/images/header.png differ
diff --git a/dojox/grid/resources/images/header_shadow.png b/dojox/grid/resources/images/header_shadow.png
new file mode 100644
index 0000000..59b2c83
Binary files /dev/null and b/dojox/grid/resources/images/header_shadow.png differ
diff --git a/dojox/grid/resources/images/row_back.png b/dojox/grid/resources/images/row_back.png
new file mode 100644
index 0000000..643db07
Binary files /dev/null and b/dojox/grid/resources/images/row_back.png differ
diff --git a/dojox/grid/resources/images/td_button_down.png b/dojox/grid/resources/images/td_button_down.png
new file mode 100644
index 0000000..ab27e3e
Binary files /dev/null and b/dojox/grid/resources/images/td_button_down.png differ
diff --git a/dojox/grid/resources/nihiloGrid.css b/dojox/grid/resources/nihiloGrid.css
index 7b60316..4fc1bcc 100644
--- a/dojox/grid/resources/nihiloGrid.css
+++ b/dojox/grid/resources/nihiloGrid.css
@@ -1,358 +1,22 @@
-.dojoxGrid {
-	position: relative;
-	background-color: #EBEADB;
-	font-family: Geneva, Arial, Helvetica, sans-serif;
-	-moz-outline-style: none;
-	outline: none;
-	overflow: hidden;
-	height: 0;
-}
-.dojoxGrid table {
-	padding: 0;
-}
-.dojoxGrid td {
-	-moz-outline: none;
-}
-.dojoxGridMasterHeader {
-	position: relative;
-}
-.dojoxGridMasterView  {
-	position: relative;
-}
-.dojoxGridMasterMessages {
-	position: relative;
-	padding: 1em;
-	text-align: center;
-	background-color: white;
-}
-.dojoxGridView {
-	position: absolute;
-	overflow: hidden;
-}
-.dojoxGridHeader {
-	position: absolute;
-	overflow: hidden;
-	cursor: default;
-}
-.dojoxGridHeader {
-	background-color: #E8E1CF;
-}
-.dojoxGridHeader table {
-	text-align: center;
-}
-.dojoxGridHeader .dojoxGridCell { 
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-	padding-bottom: 2px;
-}
-.dojoxGridHeader .dojoxGridCellOver {
-	background-image: none;
-	background-color: white;
-	border-bottom-color: #FEBE47;
-	margin-bottom: 0;
-	padding-bottom: 0;
-	border-bottom-width: 3px;
-}
-.dojoxGridHeader .dojoxGridCellFocus {
-	border: 1px dashed blue;
-}
-.dojoxGridHeader.dojoxGridCellFocus.dojoxGridCellOver {
-	background-image: none;
-	background-color: white;
-	border-bottom-color: #FEBE47;
-	margin-bottom: 0;
-	padding-bottom: 0;
-	border-bottom-width: 3px;
-}
-.dojoxGridArrowButtonNode {
-	display: none;
-	padding-left: 16px;
-}
-.dojoxGridArrowButtonChar {
-	display:inline;
-}
- 
-.dojoxGridArrowButtonNode:hover {
-        cursor: default;
-}
-.dojoxGridArrowButtonChar:hover {
-        cursor: default;
-}
-.dojoxGridSortUp:hover {
-        cursor: default;
-}
-.dojoxGridSortDown:hover {
-        cursor: default;
-}
-.dijit_a11y .dojoxGridArrowButtonChar {
-	display:inline !important;
-}
-.dojoxGridScrollbox {
-	position: relative;
-	overflow: auto;
-	background-color: white;
-	width: 100%;
-}
-.dojoxGridContent {
-	position: relative;
-	overflow: hidden;
-	 -moz-outline-style: none;
-	outline: none;
-}
-.dojoxGridRowbar { 
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	border-top: none;
-	background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-}
-.dojoxGridRowbarInner {
-	border-top: 1px solid #F6F4EB;
-}
-.dojoxGridRowbarOver {
-	background-image: none;
-	background-color: white;
-	border-top-color: #FEBE47;
-	border-bottom-color: #FEBE47;
-}
-.dojoxGridRowbarSelected {
-	background-color: #D9E8F9;
-}
-.dojoxGridRow {
-	position: relative;
-	width: 9000em;
-}
-.dojoxGridRow {
-	
-	border: 1px solid #E8E4D8;
-	border-color: #F8F7F1;
-	
-	border-left: none;
-	border-right: none;
-	background-color: white;
-	border-top: none;
-}
-.dojoxGridRowOver {
-	border-top-color: #FEBE47;
-	border-bottom-color: #FEBE47;
-	
-	
-	
-}
-.dojoxGridRowOdd {
-	background-color: #FFFDF3;
-	
-}
-.dojoxGridRowSelected {
-	background-color: #D9E8F9;
-}
-.dojoxGridRowTable {
-	table-layout: fixed;
-	width: 0;
-	empty-cells: show;
-}
-.dj_ie .dojoxGridRowTable {
-	border-collapse: collapse;
-}
-.dojoxGridInvisible {
-	visibility: hidden;
-}		
-.Xdojo-ie .dojoxGridInvisible {
-	display: none;
-}		
-.dojoxGridInvisible td, .dojoxGridHeader .dojoxGridInvisible td {
-	border-top-width: 0;
-	border-bottom-width: 0;
-	padding-top: 0;
-	padding-bottom: 0;
-	height: 0;
-	overflow: hidden;
-}
-.dojoxGridCell {
-	border: 1px solid;
-	border-color: #EBEADB;
-	border-right-color: #D5CDB5;
-	padding: 3px 3px 3px 3px;
-	text-align: left;
-	overflow: hidden;
-}
-.dojoxGridCellFocus {
-	border: 1px dashed blue;
-}
-.dojoxGridCellOver {
-	border: 1px dotted #FEBE47;
-}
-.dojoxGridCellFocus.dojoxGridCellOver {
-	border: 1px dashed green;
-}
-.dojoxGridRowEditing td {
-	background-color: #F4FFF4;
-}
-.dojoxGridRow-inserting td {
-	background-color: #F4FFF4;
-}
-.dojoxGridRow-inflight td {
-	background-color: #F2F7B7;
-}
-.dojoxGridRow-error td {
-	background-color: #F8B8B6;
-}
-.dojoxGridInput, .dojoxGridSelect, .dojoxGridTextarea {
-	margin: 0;
-	padding: 0;
-	border-style: none;
-	width: 100%;
-	font-size: 100%;
-	font-family: inherit;
-}
-.dojoxGridHiddenFocus {
-	position: absolute;
-	top: -1000px;
-	height: 0;
-	width: 0;
-}
-.dijit_a11y .dojoxGridRowbarSelected { 
-	border-top: 1px solid white;
-	border-bottom: 1px dashed black;
-	border-top: 0;
-	background: none;
-}
-.dijit_a11y .dojoxGridRowbarSelected .dojoxGridRowbarInner {
-	border: 0;
-	border-top: 1px solid white;
-}
-.dijit_a11y .dojoxGridRowSelected {
-	border: 1px solid black !important;
-}
-.dojoxGridDndAvatar {
-	font-size: 100%;
-}
-.dojoxGrid .dojoDndItemBefore {
-	border-left-color: red;
-}
-.dojoxGrid .dojoDndItemAfter {
-	border-right-color: red;
-}
-.dijit_a11y .dojoDndItemBefore {
-	border-left: double;
-}
-.dijit_a11y .dojoDndItemAfter {
-	border-right: double;
-}
-.dojoxGridDndAvatarItem	td {
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-	padding: 0pt;
-	margin: 0pt;
-}
-.dojoxGridDndAvatarItem	td.dojoxGridDndAvatarItemImage {
-	border: 0;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background-color: transparent;
-	padding: 3px;
-	padding-bottom: 2px;
-	margin: 0;
-}
-.dojoDndMove .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndNoMove.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndCopy .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndNoCopy.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndMove .dojoDndAvatarCanDrop .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndMove.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndCopy .dojoDndAvatarCanDrop .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndCopy.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoxGridColPlaceBottom {
-	background: transparent url(images/grid_sort_up.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop {
-	background: transparent url(images/grid_sort_down.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop, .dojoxGridColPlaceBottom {
-	font-size:1px;
-	height:6px;
-	z-index:10000;
-	top:0;
-	overflow:hidden;
-	position:absolute;
-	line-height:1px;
-	width:8px;
-}
-.dojoxGridResizeColLine {
-	width: 1px;
-	background-color: #777;
-	position: absolute;
-	cursor: col-resize;
-	z-index:10000;
-}
-.dojoxGridColNoResize, 
-.dojoxGridColNoResize .dojoDndItemOver {
-	cursor: not-allowed !important;
-}
-.dojoxGridColResize, 
-.dojoxGridColResize .dojoDndItemOver,
-.dojoxGridColumnResizing,
-.dojoxGridColumnResizing .dojoDndItemOver,
-.dojoxGridColumnResizing .dojoxGridHeader {
-	cursor: col-resize !important;
-}
-.dojoxGridColPlaceBottom {
-	background: transparent url(images/grid_sort_up.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop {
-	background: transparent url(images/grid_sort_down.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop, .dojoxGridColPlaceBottom {
-	font-size:1px;
-	height:6px;
-	z-index:10000;
-	top:0;
-	overflow:hidden;
-	position:absolute;
-	line-height:1px;
-	width:8px;
-}
-.dojoxGridResizeColLine {
-	width: 1px;
-	background-color: #777;
-	position: absolute;
-}
-.dojoxGridExpandoCell {
-	vertical-align: top;
-}
-.dojoxGridSummarySpan {
-	visibility: hidden;
-}
-.dojoxGridSummaryRow .dojoxGridSummarySpan,
-.dojoxGridRowCollapsed .dojoxGridSummarySpan {
-	visibility: visible;
-}
-.dojoxGridNoChildren .dojoxGridExpando {
-	visibility: hidden !important;
-	width: 0px !important;
-}
+ at import url("Grid.css");
+
 .nihilo .dojoxGrid {
 	background-color: #e9e9e9;
-	font-size: 0.85em; 
+	font-size: 0.85em; /* inherit font-family from dojo.css */
 }
+
+/* master messages */
+
 .nihilo .dojoxGridMasterMessages {
 	background-color: #fefefe;
 }
+
+/* header */
+
 .nihilo .dojoxGridHeader {
 	background-color:  #e9e9e9;
 }
+
 .nihilo .dojoxGridHeader .dojoxGridCell { 
 	border-width: 1px;
 	padding-bottom: 0px;
@@ -360,13 +24,16 @@
 	background: url(../../../dijit/themes/nihilo/images/titleBar.png) #e9e9e9 repeat-x top;
 	color: #000 !important;
 }
+
 .nihilo .dojoxGridHeader .dojoxGridCellOver {
 	background: url(../../../dijit/themes/nihilo/images/titleBarActive.png) #e9e9e9 repeat-x top;
 }
+
 .nihilo .dojoxGridHeader .dojoxGridCellFocus {
 	border-color: #ACA899 #919191;
 	border-style: dashed;	
 }
+
 .nihilo .dojoxGridArrowButtonChar {
 	float: right;
 	display: none;
@@ -384,80 +51,111 @@
 	background-image:url("../../../dijit/themes/nihilo/images/spriteArrows.gif");
 	margin-left: 0px;
 }
+
 .nihilo .dojoxGridSortUp .dojoxGridArrowButtonNode {
 	background-position: -21px;
 }
 .dijit_a11y .nihilo .dojoxGridArrowButtonNode {
 	display: none !important;
 }
+
+/* content */
+
 .nihilo .dojoxGridScrollbox {
 	background-color: #fefefe;
 }
+
+/* rowbar */
+
 .nihilo .dojoxGridRowbar { 
 	border: none;
 	background: url(../../../dijit/themes/nihilo/images/titleBar.png) #e9e9e9 repeat-y right;
 	border-right: 1px solid #ccc;
 	padding: 0px;
 }
+
 .nihilo .dojoxGridRowbarInner {
 	border: none;
 	border-bottom: 1px solid #ccc;
 }
+
 .nihilo .dojoxGridRowbarOver {
 	background: url(../../../dijit/themes/nihilo/images/titleBarActive.png) #e9e9e9 repeat-y right;
 }
+
 .nihilo .dojoxGridRowbarSelected {
 	background: url(../../../dijit/themes/nihilo/images/titleBar.png) #D9E8F9 no-repeat center;
 	border-right: 1px solid #ccc;
 }
+
+/* rows */
+
 .nihilo .dojoxGridRow {
 	border: none;
 	background-color: white;
 }
+
 .nihilo .dojoxGridRowOver {
 	border-top-color: #ccc;
 	border-bottom-color: #ccc;
 }
+
 .nihilo .dojoxGridRowOver .dojoxGridCell {
 	background-color: #ffe284; 
 }
+
 .nihilo .dojoxGridRowOdd {
 	background-color: #f2f5f9;
 }
+
 .nihilo .dojoxGridRowSelected {
 	background-color: #aec7e3;
 }
+
 .dijit_a11y .nihilo .dojoxGridRowSelected { 
 	background-color: #aec7e3; 
 	border-style: solid; 
 } 
+
+/* cells */
+
 .nihilo .dojoxGridCell {
 	border: 1px dotted #D5CDB5;
 	border-left-color: transparent;
 	border-top-color: transparent;
 }
+
 .dj_ff2 .nihilo .dojoxGridCell {
 	border-left-width: 0px;
 	border-top-width: 0px;
 }
+
 .dj_ie6 .nihilo .dojoxGridCell {
 	border: 1px solid white;
 	border-right: 1px solid #D5CDB5;
 }
+
 .nihilo .dojoxGridCellFocus {
 	border: 1px dashed darkblue;
 }
+
 .nihilo .dojoxGridCellOver {
 	border: 1px dotted #a6a6a6;
 }
+
 .nihilo .dojoxGridCellFocus.dojoxGridCellOver {
 	border: 1px dashed darkblue;
 }
+
+/* editing */
+
+/* FIXME: these colors are off! */
 .nihilo .dojoxGridRowEditing td {
-	
+	/* background-color: #F4FFF4; */
 	background-color: #ffe284; 
-	
+	/* padding: 0px 3px 0px 3px; */
 }
+
 .nihilo .dojoxGridRow-inserting td {
 	background-color: #F4FFF4;
 }
@@ -467,12 +165,18 @@
 .nihilo .dojoxGridRow-error td {
 	background-color: #F8B8B6;
 }
+
+/* Drag and Drop */
+
 .nihilo .dojoxGrid .dojoDndItemBefore {
 	border-left-color: #ffe284;
 }
 .nihilo .dojoxGrid .dojoDndItemAfter {
 	border-right-color: #ffe284;
 }
+
+
+/* Tree Grid */
 .nihilo .dojoxGridExpando {
 	float: left;
 	height: 18px;
diff --git a/dojox/grid/resources/soriaGrid.css b/dojox/grid/resources/soriaGrid.css
index 10159c9..3a169b2 100644
--- a/dojox/grid/resources/soriaGrid.css
+++ b/dojox/grid/resources/soriaGrid.css
@@ -1,358 +1,22 @@
-.dojoxGrid {
-	position: relative;
-	background-color: #EBEADB;
-	font-family: Geneva, Arial, Helvetica, sans-serif;
-	-moz-outline-style: none;
-	outline: none;
-	overflow: hidden;
-	height: 0;
-}
-.dojoxGrid table {
-	padding: 0;
-}
-.dojoxGrid td {
-	-moz-outline: none;
-}
-.dojoxGridMasterHeader {
-	position: relative;
-}
-.dojoxGridMasterView  {
-	position: relative;
-}
-.dojoxGridMasterMessages {
-	position: relative;
-	padding: 1em;
-	text-align: center;
-	background-color: white;
-}
-.dojoxGridView {
-	position: absolute;
-	overflow: hidden;
-}
-.dojoxGridHeader {
-	position: absolute;
-	overflow: hidden;
-	cursor: default;
-}
-.dojoxGridHeader {
-	background-color: #E8E1CF;
-}
-.dojoxGridHeader table {
-	text-align: center;
-}
-.dojoxGridHeader .dojoxGridCell { 
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-	padding-bottom: 2px;
-}
-.dojoxGridHeader .dojoxGridCellOver {
-	background-image: none;
-	background-color: white;
-	border-bottom-color: #FEBE47;
-	margin-bottom: 0;
-	padding-bottom: 0;
-	border-bottom-width: 3px;
-}
-.dojoxGridHeader .dojoxGridCellFocus {
-	border: 1px dashed blue;
-}
-.dojoxGridHeader.dojoxGridCellFocus.dojoxGridCellOver {
-	background-image: none;
-	background-color: white;
-	border-bottom-color: #FEBE47;
-	margin-bottom: 0;
-	padding-bottom: 0;
-	border-bottom-width: 3px;
-}
-.dojoxGridArrowButtonNode {
-	display: none;
-	padding-left: 16px;
-}
-.dojoxGridArrowButtonChar {
-	display:inline;
-}
- 
-.dojoxGridArrowButtonNode:hover {
-        cursor: default;
-}
-.dojoxGridArrowButtonChar:hover {
-        cursor: default;
-}
-.dojoxGridSortUp:hover {
-        cursor: default;
-}
-.dojoxGridSortDown:hover {
-        cursor: default;
-}
-.dijit_a11y .dojoxGridArrowButtonChar {
-	display:inline !important;
-}
-.dojoxGridScrollbox {
-	position: relative;
-	overflow: auto;
-	background-color: white;
-	width: 100%;
-}
-.dojoxGridContent {
-	position: relative;
-	overflow: hidden;
-	 -moz-outline-style: none;
-	outline: none;
-}
-.dojoxGridRowbar { 
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	border-top: none;
-	background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-}
-.dojoxGridRowbarInner {
-	border-top: 1px solid #F6F4EB;
-}
-.dojoxGridRowbarOver {
-	background-image: none;
-	background-color: white;
-	border-top-color: #FEBE47;
-	border-bottom-color: #FEBE47;
-}
-.dojoxGridRowbarSelected {
-	background-color: #D9E8F9;
-}
-.dojoxGridRow {
-	position: relative;
-	width: 9000em;
-}
-.dojoxGridRow {
-	
-	border: 1px solid #E8E4D8;
-	border-color: #F8F7F1;
-	
-	border-left: none;
-	border-right: none;
-	background-color: white;
-	border-top: none;
-}
-.dojoxGridRowOver {
-	border-top-color: #FEBE47;
-	border-bottom-color: #FEBE47;
-	
-	
-	
-}
-.dojoxGridRowOdd {
-	background-color: #FFFDF3;
-	
-}
-.dojoxGridRowSelected {
-	background-color: #D9E8F9;
-}
-.dojoxGridRowTable {
-	table-layout: fixed;
-	width: 0;
-	empty-cells: show;
-}
-.dj_ie .dojoxGridRowTable {
-	border-collapse: collapse;
-}
-.dojoxGridInvisible {
-	visibility: hidden;
-}		
-.Xdojo-ie .dojoxGridInvisible {
-	display: none;
-}		
-.dojoxGridInvisible td, .dojoxGridHeader .dojoxGridInvisible td {
-	border-top-width: 0;
-	border-bottom-width: 0;
-	padding-top: 0;
-	padding-bottom: 0;
-	height: 0;
-	overflow: hidden;
-}
-.dojoxGridCell {
-	border: 1px solid;
-	border-color: #EBEADB;
-	border-right-color: #D5CDB5;
-	padding: 3px 3px 3px 3px;
-	text-align: left;
-	overflow: hidden;
-}
-.dojoxGridCellFocus {
-	border: 1px dashed blue;
-}
-.dojoxGridCellOver {
-	border: 1px dotted #FEBE47;
-}
-.dojoxGridCellFocus.dojoxGridCellOver {
-	border: 1px dashed green;
-}
-.dojoxGridRowEditing td {
-	background-color: #F4FFF4;
-}
-.dojoxGridRow-inserting td {
-	background-color: #F4FFF4;
-}
-.dojoxGridRow-inflight td {
-	background-color: #F2F7B7;
-}
-.dojoxGridRow-error td {
-	background-color: #F8B8B6;
-}
-.dojoxGridInput, .dojoxGridSelect, .dojoxGridTextarea {
-	margin: 0;
-	padding: 0;
-	border-style: none;
-	width: 100%;
-	font-size: 100%;
-	font-family: inherit;
-}
-.dojoxGridHiddenFocus {
-	position: absolute;
-	top: -1000px;
-	height: 0;
-	width: 0;
-}
-.dijit_a11y .dojoxGridRowbarSelected { 
-	border-top: 1px solid white;
-	border-bottom: 1px dashed black;
-	border-top: 0;
-	background: none;
-}
-.dijit_a11y .dojoxGridRowbarSelected .dojoxGridRowbarInner {
-	border: 0;
-	border-top: 1px solid white;
-}
-.dijit_a11y .dojoxGridRowSelected {
-	border: 1px solid black !important;
-}
-.dojoxGridDndAvatar {
-	font-size: 100%;
-}
-.dojoxGrid .dojoDndItemBefore {
-	border-left-color: red;
-}
-.dojoxGrid .dojoDndItemAfter {
-	border-right-color: red;
-}
-.dijit_a11y .dojoDndItemBefore {
-	border-left: double;
-}
-.dijit_a11y .dojoDndItemAfter {
-	border-right: double;
-}
-.dojoxGridDndAvatarItem	td {
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-	padding: 0pt;
-	margin: 0pt;
-}
-.dojoxGridDndAvatarItem	td.dojoxGridDndAvatarItemImage {
-	border: 0;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background-color: transparent;
-	padding: 3px;
-	padding-bottom: 2px;
-	margin: 0;
-}
-.dojoDndMove .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndNoMove.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndCopy .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndNoCopy.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndMove .dojoDndAvatarCanDrop .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndMove.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndCopy .dojoDndAvatarCanDrop .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndCopy.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoxGridColPlaceBottom {
-	background: transparent url(images/grid_sort_up.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop {
-	background: transparent url(images/grid_sort_down.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop, .dojoxGridColPlaceBottom {
-	font-size:1px;
-	height:6px;
-	z-index:10000;
-	top:0;
-	overflow:hidden;
-	position:absolute;
-	line-height:1px;
-	width:8px;
-}
-.dojoxGridResizeColLine {
-	width: 1px;
-	background-color: #777;
-	position: absolute;
-	cursor: col-resize;
-	z-index:10000;
-}
-.dojoxGridColNoResize, 
-.dojoxGridColNoResize .dojoDndItemOver {
-	cursor: not-allowed !important;
-}
-.dojoxGridColResize, 
-.dojoxGridColResize .dojoDndItemOver,
-.dojoxGridColumnResizing,
-.dojoxGridColumnResizing .dojoDndItemOver,
-.dojoxGridColumnResizing .dojoxGridHeader {
-	cursor: col-resize !important;
-}
-.dojoxGridColPlaceBottom {
-	background: transparent url(images/grid_sort_up.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop {
-	background: transparent url(images/grid_sort_down.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop, .dojoxGridColPlaceBottom {
-	font-size:1px;
-	height:6px;
-	z-index:10000;
-	top:0;
-	overflow:hidden;
-	position:absolute;
-	line-height:1px;
-	width:8px;
-}
-.dojoxGridResizeColLine {
-	width: 1px;
-	background-color: #777;
-	position: absolute;
-}
-.dojoxGridExpandoCell {
-	vertical-align: top;
-}
-.dojoxGridSummarySpan {
-	visibility: hidden;
-}
-.dojoxGridSummaryRow .dojoxGridSummarySpan,
-.dojoxGridRowCollapsed .dojoxGridSummarySpan {
-	visibility: visible;
-}
-.dojoxGridNoChildren .dojoxGridExpando {
-	visibility: hidden !important;
-	width: 0px !important;
-}
+ at import url("Grid.css");
+
 .soria .dojoxGrid {
 	background-color: #e9e9e9;
-	font-size: 0.85em; 
+	font-size: 0.85em; /* inherit font-family from dojo.css */
 }
+
+/* master messages */
+
 .soria .dojoxGridMasterMessages {
 	background-color: #fefefe;
 }
+
+/* header */
+
 .soria .dojoxGridHeader {
 	background-color:  #e9e9e9;
 }
+
 .soria .dojoxGridHeader .dojoxGridCell { 
 	border-width: 1px;
 	padding-bottom: 0px;
@@ -360,13 +24,16 @@
 	background: url(../../../dijit/themes/soria/images/titleBar.png) #e9e9e9 repeat-x top;
 	color: #000 !important;
 }
+
 .soria .dojoxGridHeader .dojoxGridCellOver {
 	background: url(../../../dijit/themes/soria/images/titleBarActive.png) #e9e9e9 repeat-x top;
 }
+
 .soria .dojoxGridHeader .dojoxGridCellFocus {
 	border-color: #ACA899 #919191;
 	border-style: dashed;	
 }
+
 .soria .dojoxGridArrowButtonChar {
 	float: right;
 	display: none;
@@ -384,81 +51,112 @@
 	background-image:url("../../../dijit/themes/soria/images/spriteArrows.gif");
 	margin-left: 0px;
 }
+
 .soria .dojoxGridSortUp .dojoxGridArrowButtonNode {
 	background-position: -21px;
 }
 .dijit_a11y .soria .dojoxGridArrowButtonNode {
 	display: none !important;
 }
+
+/* content */
+
 .soria .dojoxGridScrollbox {
 	background-color: #fefefe;
 }
+
+/* rowbar */
+
 .soria .dojoxGridRowbar { 
 	border: none;
 	background: url(../../../dijit/themes/soria/images/titleBar.png) #e9e9e9 repeat-y right;
 	border-right: 1px solid #ccc;
 	padding: 0px;
 }
+
 .soria .dojoxGridRowbarInner {
 	border: none;
 	border-bottom: 1px solid #ccc;
 }
+
 .soria .dojoxGridRowbarOver {
 	background: url(../../../dijit/themes/soria/images/titleBarActive.png) #e9e9e9 repeat-y right;
 }
+
 .soria .dojoxGridRowbarSelected {
 	background: url(../../../dijit/themes/soria/images/titleBar.png) #D9E8F9 no-repeat center;
 	border-right: 1px solid #ccc;
 }
+
+/* rows */
+
 .soria .dojoxGridRow {
 	border: none;
 	background-color: white;
 }
+
 .soria .dojoxGridRowOver {
 	border-top-color: #ccc;
 	border-bottom-color: #ccc;
 }
+
 .soria .dojoxGridRowOver .dojoxGridCell {
 	background-color: #60a1ea; 
 	color:#fff;
 }
+
 .soria .dojoxGridRowOdd {
 	background-color: #f2f5f9;
 }
+
 .soria .dojoxGridRowSelected {
 	background-color: #aec7e3;
 }
+
 .dijit_a11y .soria .dojoxGridRowSelected { 
     background-color: #aec7e3;     
     border-style: solid;     
 }   
+
+/* cells */
+
 .soria .dojoxGridCell {
 	border: 1px dotted #D5CDB5;
 	border-left-color: transparent;
 	border-top-color: transparent;
 }
+
 .dj_ff2 .soria .dojoxGridCell {
 	border-left-width: 0px;
 	border-top-width: 0px;
 }
+
 .dj_ie6 .soria .dojoxGridCell {
 	border: 1px solid white;
 	border-right: 1px solid #D5CDB5;
 }
+
 .soria .dojoxGridCellFocus {
 	border: 1px dashed darkblue;
 }
+
 .soria .dojoxGridCellOver {
 	border: 1px dotted #a6a6a6;
 }
+
 .soria .dojoxGridCellFocus.dojoxGridCellOver {
 	border: 1px dashed darkblue;
 }
+
+/* editing */
+
+/* FIXME: these colors are off! */
 .soria .dojoxGridRowEditing td {
-	
+	/* background-color: #F4FFF4; */
 	background-color: #60a1ea; 
-	
+	/* padding: 0px 3px 0px 3px; */
 }
+
 .soria .dojoxGridRow-inserting td {
 	background-color: #F4FFF4;
 }
@@ -468,12 +166,17 @@
 .soria .dojoxGridRow-error td {
 	background-color: #F8B8B6;
 }
+
+/* Drag and Drop */
+
 .soria .dojoxGrid .dojoDndItemBefore {
 	border-left-color: #4B5AAA;
 }
 .soria .dojoxGrid .dojoDndItemAfter {
 	border-right-color: #4B5AAA;
 }
+
+/* Tree Grid */
 .soria .dojoxGridExpando {
 	float: left;
 	height: 18px;
diff --git a/dojox/grid/resources/tundraGrid.css b/dojox/grid/resources/tundraGrid.css
index 0b42e69..18ba271 100644
--- a/dojox/grid/resources/tundraGrid.css
+++ b/dojox/grid/resources/tundraGrid.css
@@ -1,361 +1,23 @@
-.dojoxGrid {
-	position: relative;
-	background-color: #EBEADB;
-	font-family: Geneva, Arial, Helvetica, sans-serif;
-	-moz-outline-style: none;
-	outline: none;
-	overflow: hidden;
-	height: 0;
-}
-.dojoxGrid table {
-	padding: 0;
-}
-.dojoxGrid td {
-	-moz-outline: none;
-}
-.dojoxGridMasterHeader {
-	position: relative;
-}
-.dojoxGridMasterView  {
-	position: relative;
-}
-.dojoxGridMasterMessages {
-	position: relative;
-	padding: 1em;
-	text-align: center;
-	background-color: white;
-}
-.dojoxGridView {
-	position: absolute;
-	overflow: hidden;
-}
-.dojoxGridHeader {
-	position: absolute;
-	overflow: hidden;
-	cursor: default;
-}
-.dojoxGridHeader {
-	background-color: #E8E1CF;
-}
-.dojoxGridHeader table {
-	text-align: center;
-}
-.dojoxGridHeader .dojoxGridCell { 
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-	padding-bottom: 2px;
-}
-.dojoxGridHeader .dojoxGridCellOver {
-	background-image: none;
-	background-color: white;
-	border-bottom-color: #FEBE47;
-	margin-bottom: 0;
-	padding-bottom: 0;
-	border-bottom-width: 3px;
-}
-.dojoxGridHeader .dojoxGridCellFocus {
-	border: 1px dashed blue;
-}
-.dojoxGridHeader.dojoxGridCellFocus.dojoxGridCellOver {
-	background-image: none;
-	background-color: white;
-	border-bottom-color: #FEBE47;
-	margin-bottom: 0;
-	padding-bottom: 0;
-	border-bottom-width: 3px;
-}
-.dojoxGridArrowButtonNode {
-	display: none;
-	padding-left: 16px;
-}
-.dojoxGridArrowButtonChar {
-	display:inline;
-}
- 
-.dojoxGridArrowButtonNode:hover {
-        cursor: default;
-}
-.dojoxGridArrowButtonChar:hover {
-        cursor: default;
-}
-.dojoxGridSortUp:hover {
-        cursor: default;
-}
-.dojoxGridSortDown:hover {
-        cursor: default;
-}
-.dijit_a11y .dojoxGridArrowButtonChar {
-	display:inline !important;
-}
-.dojoxGridScrollbox {
-	position: relative;
-	overflow: auto;
-	background-color: white;
-	width: 100%;
-}
-.dojoxGridContent {
-	position: relative;
-	overflow: hidden;
-	 -moz-outline-style: none;
-	outline: none;
-}
-.dojoxGridRowbar { 
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	border-top: none;
-	background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-}
-.dojoxGridRowbarInner {
-	border-top: 1px solid #F6F4EB;
-}
-.dojoxGridRowbarOver {
-	background-image: none;
-	background-color: white;
-	border-top-color: #FEBE47;
-	border-bottom-color: #FEBE47;
-}
-.dojoxGridRowbarSelected {
-	background-color: #D9E8F9;
-}
-.dojoxGridRow {
-	position: relative;
-	width: 9000em;
-}
-.dojoxGridRow {
-	
-	border: 1px solid #E8E4D8;
-	border-color: #F8F7F1;
-	
-	border-left: none;
-	border-right: none;
-	background-color: white;
-	border-top: none;
-}
-.dojoxGridRowOver {
-	border-top-color: #FEBE47;
-	border-bottom-color: #FEBE47;
-	
-	
-	
-}
-.dojoxGridRowOdd {
-	background-color: #FFFDF3;
-	
-}
-.dojoxGridRowSelected {
-	background-color: #D9E8F9;
-}
-.dojoxGridRowTable {
-	table-layout: fixed;
-	width: 0;
-	empty-cells: show;
-}
-.dj_ie .dojoxGridRowTable {
-	border-collapse: collapse;
-}
-.dojoxGridInvisible {
-	visibility: hidden;
-}		
-.Xdojo-ie .dojoxGridInvisible {
-	display: none;
-}		
-.dojoxGridInvisible td, .dojoxGridHeader .dojoxGridInvisible td {
-	border-top-width: 0;
-	border-bottom-width: 0;
-	padding-top: 0;
-	padding-bottom: 0;
-	height: 0;
-	overflow: hidden;
-}
-.dojoxGridCell {
-	border: 1px solid;
-	border-color: #EBEADB;
-	border-right-color: #D5CDB5;
-	padding: 3px 3px 3px 3px;
-	text-align: left;
-	overflow: hidden;
-}
-.dojoxGridCellFocus {
-	border: 1px dashed blue;
-}
-.dojoxGridCellOver {
-	border: 1px dotted #FEBE47;
-}
-.dojoxGridCellFocus.dojoxGridCellOver {
-	border: 1px dashed green;
-}
-.dojoxGridRowEditing td {
-	background-color: #F4FFF4;
-}
-.dojoxGridRow-inserting td {
-	background-color: #F4FFF4;
-}
-.dojoxGridRow-inflight td {
-	background-color: #F2F7B7;
-}
-.dojoxGridRow-error td {
-	background-color: #F8B8B6;
-}
-.dojoxGridInput, .dojoxGridSelect, .dojoxGridTextarea {
-	margin: 0;
-	padding: 0;
-	border-style: none;
-	width: 100%;
-	font-size: 100%;
-	font-family: inherit;
-}
-.dojoxGridHiddenFocus {
-	position: absolute;
-	top: -1000px;
-	height: 0;
-	width: 0;
-}
-.dijit_a11y .dojoxGridRowbarSelected { 
-	border-top: 1px solid white;
-	border-bottom: 1px dashed black;
-	border-top: 0;
-	background: none;
-}
-.dijit_a11y .dojoxGridRowbarSelected .dojoxGridRowbarInner {
-	border: 0;
-	border-top: 1px solid white;
-}
-.dijit_a11y .dojoxGridRowSelected {
-	border: 1px solid black !important;
-}
-.dojoxGridDndAvatar {
-	font-size: 100%;
-}
-.dojoxGrid .dojoDndItemBefore {
-	border-left-color: red;
-}
-.dojoxGrid .dojoDndItemAfter {
-	border-right-color: red;
-}
-.dijit_a11y .dojoDndItemBefore {
-	border-left: double;
-}
-.dijit_a11y .dojoDndItemAfter {
-	border-right: double;
-}
-.dojoxGridDndAvatarItem	td {
-	border: 1px solid;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background: url(images/grid_dx_gradient.gif) #E8E1CF top repeat-x;
-	padding: 0pt;
-	margin: 0pt;
-}
-.dojoxGridDndAvatarItem	td.dojoxGridDndAvatarItemImage {
-	border: 0;
-	border-color: #F6F4EB #ACA899 #ACA899 #F6F4EB;
-	background-color: transparent;
-	padding: 3px;
-	padding-bottom: 2px;
-	margin: 0;
-}
-.dojoDndMove .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndNoMove.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndCopy .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndNoCopy.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndMove .dojoDndAvatarCanDrop .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndMove.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoDndCopy .dojoDndAvatarCanDrop .dojoxGridDndAvatarItem .dojoxGridDndAvatarItemImage {
-	background-image: url(../../../dojo/resources/images/dndCopy.png);
-	background-repeat: no-repeat;
-	background-position: center center;
-}
-.dojoxGridColPlaceBottom {
-	background: transparent url(images/grid_sort_up.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop {
-	background: transparent url(images/grid_sort_down.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop, .dojoxGridColPlaceBottom {
-	font-size:1px;
-	height:6px;
-	z-index:10000;
-	top:0;
-	overflow:hidden;
-	position:absolute;
-	line-height:1px;
-	width:8px;
-}
-.dojoxGridResizeColLine {
-	width: 1px;
-	background-color: #777;
-	position: absolute;
-	cursor: col-resize;
-	z-index:10000;
-}
-.dojoxGridColNoResize, 
-.dojoxGridColNoResize .dojoDndItemOver {
-	cursor: not-allowed !important;
-}
-.dojoxGridColResize, 
-.dojoxGridColResize .dojoDndItemOver,
-.dojoxGridColumnResizing,
-.dojoxGridColumnResizing .dojoDndItemOver,
-.dojoxGridColumnResizing .dojoxGridHeader {
-	cursor: col-resize !important;
-}
-.dojoxGridColPlaceBottom {
-	background: transparent url(images/grid_sort_up.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop {
-	background: transparent url(images/grid_sort_down.gif) no-repeat scroll left top;
-}
-.dojoxGridColPlaceTop, .dojoxGridColPlaceBottom {
-	font-size:1px;
-	height:6px;
-	z-index:10000;
-	top:0;
-	overflow:hidden;
-	position:absolute;
-	line-height:1px;
-	width:8px;
-}
-.dojoxGridResizeColLine {
-	width: 1px;
-	background-color: #777;
-	position: absolute;
-}
-.dojoxGridExpandoCell {
-	vertical-align: top;
-}
-.dojoxGridSummarySpan {
-	visibility: hidden;
-}
-.dojoxGridSummaryRow .dojoxGridSummarySpan,
-.dojoxGridRowCollapsed .dojoxGridSummarySpan {
-	visibility: visible;
-}
-.dojoxGridNoChildren .dojoxGridExpando {
-	visibility: hidden !important;
-	width: 0px !important;
-}
+ at import url("Grid.css");
+
 .tundra .dojoxGrid {
 	background-color: #e9e9e9;
-	font-size: 0.85em; 
+	font-size: 0.85em; /* inherit font-family from dojo.css */
 }
+
+/* master messages */
+
 .tundra .dojoxGridMasterMessages {
 	background-color: #fefefe;
 }
+
 .tundra .dojoxGridLoading, 
 .tundra .dojoxGridError {
 	background-position:left center;
 	background-repeat: no-repeat;
 	padding-left:25px;
 }
+
 .dijitRtl .tundra .dojoxGridLoading, 
 .dijitRtl .tundra .dojoxGridError,
 .dijitRtl .tundra .dojoxGridNoData {
@@ -363,15 +25,21 @@
 	padding-right:25px;
 	padding-left:0px;
 }
+
 .tundra .dojoxGridLoading {
 	background-image: url('../../../dijit/themes/tundra/images/loading.gif');
 }
+
 .tundra .dojoxGridError {
 	background-image: url('../../../dijit/themes/tundra/images/warning.png');
 }
+
+/* header */
+
 .tundra .dojoxGridHeader {
 	background-color:  #e9e9e9;
 }
+
 .tundra .dojoxGridHeader .dojoxGridCell { 
 	border-width: 1px;
 	padding-bottom: 0px;
@@ -379,6 +47,7 @@
 	background: url(../../../dijit/themes/tundra/images/tabEnabled.png) #e9e9e9 repeat-x top;
 	color: #000 !important;
 }
+
 .tundra .dojoxGridHeader .dojoxGridCellOver {
 	background: url(../../../dijit/themes/tundra/images/tabHover.png) #e9e9e9 repeat-x top;
 	color: #000 !important;
@@ -404,87 +73,120 @@
 	background-image:url("../../../dijit/themes/tundra/images/spriteArrows.gif");
 	margin-left: 0px;
 }
+
 .tundra .dojoxGridSortUp .dojoxGridArrowButtonNode {
 	background-position: -21px;
 }
 .dijit_a11y .tundra .dojoxGridArrowButtonNode {
 	display: none !important;
 }
+
+/* content */
+
 .tundra .dojoxGridScrollbox {
 	background-color: #fefefe;
 }
+
+/* rowbar */
+
 .tundra .dojoxGridRowbar { 
 	border: none;
 	background: url(images/tabEnabled_rotated.png) #e9e9e9 repeat-y right;
 	border-right: 1px solid #ccc;
 	padding: 0px;
 }
+
 .tundra .dojoxGridRowbarInner {
 	border: none;
 	border-bottom: 1px solid #ccc;
 }
+
 .tundra .dojoxGridRowbarOver {
 	background: url(images/tabHover_rotated.png) #e9e9e9 repeat-y right;
 }
+
 .tundra .dojoxGridRowbarSelected {
 	background: url(../../../dijit/themes/tundra/images/tabDisabled.png) #D8E8F9 no-repeat center;
 	border-right: 1px solid #ccc;
 }
+
+/* rows */
+
 .tundra .dojoxGridRow {
 	border: none;
 	background-color: white;
 }
+
 .tundra .dojoxGridRowOver {
 	border-top-color: #ccc;
 	border-bottom-color: #ccc;
 }
+
 .tundra .dojoxGridRowOver .dojoxGridCell {
 	background-color: #60a1ea; 
 	color:#fff;
 }
+
 .tundra .dojoxGridRowOver .dojoxGridCell .dijit {
 	color: #000;
 }
+
 .tundra .dojoxGridRowOver .dojoxGridCell .dijitDisabled {
 	color: gray;
 }
+
 .tundra .dojoxGridRowOdd {
 	background-color: #f2f5f9;
 }
+
 .tundra .dojoxGridRowSelected {
 	background-color: #aec7e3 !important;
 }
+
 .dijit_a11y .tundra .dojoxGridRowSelected { 
     background-color: #aec7e3;     
     border-style: solid;     
 }   
+
+/* cells */
+
 .tundra .dojoxGridCell {
 	border: 1px dotted #D5CDB5;
 	border-left-color: transparent;
 	border-top-color: transparent;
 }
+
 .dj_ff2 .tundra .dojoxGridCell {
 	border-left-width: 0px;
 	border-top-width: 0px;
 }
+
 .dj_ie6 .tundra .dojoxGridCell {
 	border: 1px solid white;
 	border-right: 1px solid #D5CDB5;
 }
+
 .tundra .dojoxGridCellFocus {
 	border: 1px dashed darkblue !important;
 }
+
 .tundra .dojoxGridCellOver {
 	border: 1px dotted #a6a6a6;
 }
+
 .tundra .dojoxGridCellFocus .dojoxGridCellOver {
 	border: 1px dashed darkblue !important;
 }
+
+/* editing */
+
+/* FIXME: these colors are off! */
 .tundra .dojoxGridRowEditing td {
-	
+	/* background-color: #F4FFF4; */
 	background-color: #60a1ea; 
-	
+	/* padding: 0px 3px 0px 3px; */
 }
+
 .tundra .dojoxGridRow-inserting td {
 	background-color: #F4FFF4;
 }
@@ -494,12 +196,17 @@
 .tundra .dojoxGridRow-error td {
 	background-color: #F8B8B6;
 }
+
+/* Drag and Drop */
+
 .tundra .dojoxGrid .dojoDndItemBefore {
 	border-left-color: #3559ac;
 }
 .tundra .dojoxGrid .dojoDndItemAfter {
 	border-right-color: #3559ac;
 }
+
+/* Tree Grid */
 .tundra .dojoxGridExpando {
 	float: left;
 	height: 18px;
diff --git a/dojox/grid/tests/databaseModel.js b/dojox/grid/tests/databaseModel.js
new file mode 100644
index 0000000..01b7a4e
--- /dev/null
+++ b/dojox/grid/tests/databaseModel.js
@@ -0,0 +1,333 @@
+dojo.provide("dojox.grid.tests.databaseModel");
+dojo.require("dojox.grid._data.model");
+
+// Provides a sparse array that is also traversable inorder 
+// with basic Array:
+//   - iterating by index is slow for large sparse arrays
+//   - for...in iteration is in order of element creation 
+// maintains a secondary index for interating
+// over sparse elements inorder
+dojo.declare("dojox.grid.Sparse", null, {
+	constructor: function() {
+		this.clear();
+	},
+	clear: function() {
+		this.indices = [];
+		this.values = [];
+	},
+	length: function() {
+		return this.indices.length;
+	},
+	set: function(inIndex, inValue) {
+		for (var i=0,l=this.indices.length; i<l; i++) {
+			if (this.indices[i] >= inIndex) 
+				break;
+		}
+		if (this.indices[i] != inIndex) 
+			this.indices.splice(i, 0, inIndex);
+		this.values[inIndex] = inValue;
+	},
+	get: function(inIndex) {
+		return this.values[inIndex];
+	},
+	remove: function(inIndex) {
+		for (var i=0,l=this.indices.length; i<l; i++) 
+			if (this.indices[i] == inIndex) {
+				this.indices.splice(i, 1);
+				break;
+			}
+		delete this.values[inIndex];
+	},
+	inorder: function(inFor) {
+		for (var i=0,l=this.indices.length, ix; i<l; i++) {
+			ix = this.indices[i];
+			if (inFor(this.values[ix], ix) === false)
+				break;
+		}
+	}
+});
+
+// sample custom model implementation that works with mysql server.
+dojo.declare("dojox.grid._data.DbTable", dojox.grid._data.Dynamic, {
+	delayedInsertCommit: true,
+	constructor: function(inFields, inData, inServer, inDatabase, inTable) {
+		this.server = inServer;
+		this.database = inDatabase;
+		this.table = inTable;
+		this.stateNames = ['inflight', 'inserting', 'removing', 'error'];
+		this.clearStates();
+		this.clearSort();
+	},
+	clearData: function() {
+		this.cache = [ ];
+		this.clearStates();
+		this.inherited(arguments);
+	},
+	clearStates: function() {
+		this.states = {};
+		for (var i=0, s; (s=this.stateNames[i]); i++) {
+			delete this.states[s];
+			this.states[s] = new dojox.grid.Sparse();
+		}
+	},
+	// row state information
+	getState: function(inRowIndex) {
+		for (var i=0, r={}, s; (s=this.stateNames[i]); i++)
+			r[s] = this.states[s].get(inRowIndex);
+		return r;
+	},
+	setState: function(inRowIndex, inState, inValue) {
+		this.states[inState].set(inRowIndex, inValue||true);
+	},
+	clearState: function(inRowIndex, inState) {
+		if (arguments.length == 1) {
+			for (var i=0, s; (s=this.stateNames[i]); i++)
+				this.states[s].remove(inRowIndex);
+		}	else {
+			for (var i=1, l=arguments.length, arg; (i<l) &&((arg=arguments[i])!=undefined); i++)
+				this.states[arg].remove(inRowIndex);
+		}
+	},
+	setStateForIndexes: function(inRowIndexes, inState, inValue) {
+		for (var i=inRowIndexes.length-1, k; (i>=0) && ((k=inRowIndexes[i])!=undefined); i--)
+			this.setState(k, inState, inValue);
+	},
+	clearStateForIndexes: function(inRowIndexes, inState) {
+		for (var i=inRowIndexes.length-1, k; (i>=0) && ((k=inRowIndexes[i])!=undefined); i--)
+			this.clearState(k, inState);
+	},
+	//$ Return boolean stating whether or not an operation is in progress that may change row indexing.
+	isAddRemoving: function() {
+		return Boolean(this.states['inserting'].length() || this.states['removing'].length());
+	},
+	isInflight: function() {
+		return Boolean(this.states['inflight'].length());
+	},
+	//$ Return boolean stating if the model is currently undergoing any type of edit.
+	isEditing: function() {
+		for (var i=0, r={}, s; (s=this.stateNames[i]); i++)
+			if (this.states[s].length())
+				return true;
+	},
+	//$ Return true if ok to modify the given row. Override as needed, using model editing state information.
+	canModify: function(inRowIndex) {
+		return !this.getState(inRowIndex).inflight && !(this.isInflight() && this.isAddRemoving());
+	},
+	// server send / receive
+	getSendParams: function(inParams) {
+		var p = {
+			database: this.database || '',
+			table: this.table || ''
+		}
+		return dojo.mixin(p, inParams || {});
+	},
+	send: function(inAsync, inParams, inCallbacks) {
+		//console.log('send', inParams.command);
+		var p = this.getSendParams(inParams);
+		var d = dojo.xhrPost({
+			url: this.server,
+			content: p,
+			handleAs: 'json-comment-filtered',
+			contentType: "application/x-www-form-urlencoded; charset=utf-8",
+			sync: !inAsync
+		});
+		d.addCallbacks(dojo.hitch(this, "receive", inCallbacks), dojo.hitch(this, "receiveError", inCallbacks));
+		return d;
+	},
+	_callback: function(cb, eb, data) {
+		try{ cb && cb(data); } 
+		catch(e){ eb && eb(data, e); }
+	},
+	receive: function(inCallbacks, inData) {
+		inCallbacks && this._callback(inCallbacks.callback, inCallbacks.errback, inData);
+	},
+	receiveError: function(inCallbacks, inErr) {
+		this._callback(inCallbacks.errback, null, inErr)
+	},
+	encodeRow: function(inParams, inRow, inPrefix) {
+		for (var i=0, l=inRow.length; i < l; i++)
+			inParams['_' + (inPrefix ? inPrefix : '') + i] = (inRow[i] ? inRow[i] : '');
+	},
+	measure: function() {
+		this.send(true, { command: 'info' }, { callback: dojo.hitch(this, this.callbacks.info) });
+	},
+	fetchRowCount: function(inCallbacks) {
+		this.send(true, { command: 'count' }, inCallbacks);
+	},
+	// server commits
+	commitEdit: function(inOldData, inNewData, inRowIndex, inCallbacks) {
+		this.setState(inRowIndex, "inflight", true);
+		var params = {command: 'update'};
+		this.encodeRow(params, inOldData, 'o');
+		this.encodeRow(params, inNewData);
+		this.send(true, params, inCallbacks);
+	},
+	commitInsert: function(inRowIndex, inNewData, inCallbacks) {
+		this.setState(inRowIndex, "inflight", true);
+		var params = {command: 'insert'};
+		this.encodeRow(params, inNewData);
+		this.send(true, params, inCallbacks);
+	},
+	// NOTE: supported only in tables with pk
+	commitDelete: function(inRows, inCallbacks) {
+		var params = { 
+			command: 'delete',
+			count: inRows.length
+		}	
+		var pk = this.getPkIndex();
+		if (pk < 0)
+			return;
+		for (var i=0; i < inRows.length; i++)	{
+			params['_' + i] = inRows[i][pk];
+		}	
+		this.send(true, params, inCallbacks);
+	},
+	getUpdateCallbacks: function(inRowIndex) {
+		return {
+			callback: dojo.hitch(this, this.callbacks.update, inRowIndex), 
+			errback: dojo.hitch(this, this.callbacks.updateError, inRowIndex)
+		};
+	},
+	// primary key from fields
+	getPkIndex: function() {
+		for (var i=0, l=this.fields.count(), f; (i<l) && (f=this.fields.get(i)); i++)
+			if (f.Key = 'PRI')
+				return i;
+		return -1;		
+	},
+	// model implementations
+	update: function(inOldData, inNewData, inRowIndex) {
+		var cbs = this.getUpdateCallbacks(inRowIndex);
+		if (this.getState(inRowIndex).inserting)
+			this.commitInsert(inRowIndex, inNewData, cbs);
+		else
+			this.commitEdit(this.cache[inRowIndex] || inOldData, inNewData, inRowIndex, cbs);
+		// set push data immediately to model	so reflectd while committing
+		this.setRow(inNewData, inRowIndex);
+	},
+	insert: function(inData, inRowIndex) {
+		this.setState(inRowIndex, 'inserting', true);
+		if (!this.delayedInsertCommit)
+			this.commitInsert(inRowIndex, inData, this.getUpdateCallbacks(inRowIndex));
+		return this.inherited(arguments);
+	},
+	remove: function(inRowIndexes) {
+		var rows = [];
+		for (var i=0, r=0, indexes=[]; (r=inRowIndexes[i]) !== undefined; i++)
+			if (!this.getState(r).inserting) {
+				rows.push(this.getRow(r));
+				indexes.push(r);
+				this.setState(r, 'removing');
+			}
+		var cbs = {
+			callback: dojo.hitch(this, this.callbacks.remove, indexes),
+			errback: dojo.hitch(this, this.callbacks.removeError, indexes)
+		};
+		this.commitDelete(rows, cbs);
+		dojox.grid._data.Dynamic.prototype.remove.apply(this, arguments);
+	},
+	cancelModifyRow: function(inRowIndex) {
+		if (this.isDelayedInsert(inRowIndex)) {
+			this.removeInsert(inRowIndex);
+		} else
+			this.finishUpdate(inRowIndex);
+	},	
+	finishUpdate: function(inRowIndex, inData) {
+		this.clearState(inRowIndex);
+		var d = (inData&&inData[0]) || this.cache[inRowIndex];
+		if (d)
+			this.setRow(d, inRowIndex);
+		delete this.cache[inRowIndex];
+	},
+	isDelayedInsert: function(inRowIndex) {
+		return (this.delayedInsertCommit && this.getState(inRowIndex).inserting);
+	},
+	removeInsert: function(inRowIndex) {
+		this.clearState(inRowIndex);
+		dojox.grid._data.Dynamic.prototype.remove.call(this, [inRowIndex]);
+	},
+	// request data 
+	requestRows: function(inRowIndex, inCount)	{
+		var params = { 
+			command: 'select',
+			orderby: this.sortField, 
+			desc: (this.sortDesc ? "true" : ''),
+			offset: inRowIndex, 
+			limit: inCount
+		}
+		this.send(true, params, {callback: dojo.hitch(this, this.callbacks.rows, inRowIndex)});
+	},
+	// sorting
+	canSort: function () { 
+		return true; 
+	},
+	setSort: function(inSortIndex) {
+		this.sortField = this.fields.get(Math.abs(inSortIndex) - 1).name || inSortIndex;
+		this.sortDesc = (inSortIndex < 0);
+	},
+	sort: function(inSortIndex) {
+		this.setSort(inSortIndex);
+		this.clearData();
+	},
+	clearSort: function(){
+		this.sortField = '';
+		this.sortDesc = false;
+	},
+	endModifyRow: function(inRowIndex){
+		var cache = this.cache[inRowIndex];
+		var m = false;
+		if(cache){
+			var data = this.getRow(inRowIndex);
+			if(!dojox.grid.util.arrayCompare(cache, data)){
+				m = true;
+				this.update(cache, data, inRowIndex);
+			}	
+		}
+		if (!m)
+			this.cancelModifyRow(inRowIndex);
+	},
+	// server callbacks (called with this == model)
+	callbacks: {
+		update: function(inRowIndex, inData) {
+			console.log('received update', arguments);
+			if (inData.error)
+				this.updateError(inData)
+			else
+				this.finishUpdate(inRowIndex, inData);
+		},
+		updateError: function(inRowIndex) {
+			this.clearState(inRowIndex, 'inflight');
+			this.setState(inRowIndex, "error", "update failed: " + inRowIndex);
+			this.rowChange(this.getRow(inRowIndex), inRowIndex);
+		},
+		remove: function(inRowIndexes) {
+			this.clearStateForIndexes(inRowIndexes);
+		},
+		removeError: function(inRowIndexes) {
+			this.clearStateForIndexes(inRowIndexes);
+			alert('Removal error. Please refresh.');
+		},
+		rows: function(inRowIndex, inData) {
+			//this.beginUpdate();
+			for (var i=0, l=inData.length; i<l; i++)
+				this.setRow(inData[i], inRowIndex + i);
+			//this.endUpdate();
+			//this.allChange();
+		},
+		count: function(inRowCount) {
+			this.count = Number(inRowCount);
+			this.clearData();
+		},
+		info: function(inInfo) {
+			this.fields.clear();
+			for (var i=0, c; (c=inInfo.columns[i]); i++) {
+				c.name = c.Field;
+				this.fields.set(i, c);
+			}
+			this.table = inInfo.table;
+			this.database = inInfo.database;
+			this.notify("MetaData", arguments);
+			this.callbacks.count.call(this, inInfo.count);
+		}
+	}
+});
diff --git a/dojox/grid/tests/enhanced/support/music-for-demo.part.csv b/dojox/grid/tests/enhanced/support/music-for-demo.part.csv
new file mode 100644
index 0000000..9109713
--- /dev/null
+++ b/dojox/grid/tests/enhanced/support/music-for-demo.part.csv
@@ -0,0 +1,309 @@
+Genre,Artist,Year,Album,Name,Length,Track,Composer
+Easy Listening,Bette Midler,2003,Bette Midler Sings the Rosemary Clooney Songbook,Hey There,3:31,4,"Ross, Jerry 1926-1956 -w Adler, Richard 1921-"
+Classic Rock,Jimi Hendrix,1993,Are You Experienced,Love Or Confusion,3:15,4,Jimi Hendrix
+Jazz,Andy Narell,1992,Down the Road,Sugar Street,7:00,8,Andy Narell
+Progressive Rock,"Emerson, Lake & Palmer",1992,The Atlantic Years,Tarkus,20:40,5,Greg Lake/Keith Emerson
+Rock,"Blood, Sweat & Tears",1968,Child Is Father To The Man,Somethin' Goin' On,8:00,9,
+Jazz,Andy Narell,1989,Little Secrets,Armchair Psychology,8:20,5,Andy Narell
+Easy Listening,Frank Sinatra,1991,Sinatra Reprise: The Very Good Years,Luck Be A Lady,5:16,4,F. Loesser
+Progressive Rock,Dixie dregs,1977,Free Fall,Sleep,1:58,6,Steve Morse
+Classic Rock,Black Sabbath,2004,Master of Reality,Sweet Leaf,5:04,1,Bill Ward/Geezer Butler/Ozzy Osbourne/Tony Iommi
+Blues,Buddy Guy,1991,"Damn Right, I've Got The Blues",Five Long Years,8:27,3,Eddie Boyd/John Lee Hooker
+Easy Listening,Frank Sinatra,1991,Sinatra Reprise: The Very Good Years,The Way You Look Tonight,3:23,5,D. Fields/J. Kern
+World,Andy Statman & David Grisman,1995,Songs Of Our Fathers,Chassidic Medley: Adir Hu / Moshe Emes,4:14,2,Shlomo Carlebach; Trad.
+Classic Rock,Jimi Hendrix,1968,Electric Ladyland,Long Hot Summer Night,3:27,6,Jimi Hendrix
+Classical,Andres Segovia,2004,The Best Of Andres Segovia,"Asturias (Suite Espanola, Op. 47)",6:25,6,Isaac Albeniz
+Jazz,Andy Narell,1989,Little Secrets,We Kinda Music,8:22,3,Andy Narell
+Pop and R&B,Joni Mitchell,2000,Both Sides Now,Comes Love,4:29,3,Charles Tobias/Sammy Stept/Lew Brown
+Pop and R&B,Joni Mitchell,1974,Court And Spark,Court And Spark,2:46,1,Joni Mitchell
+Easy Listening,Frank Sinatra,1962,Sinatra and Swinging Brass,Serenade in Blue,3:00,10,"Harry Warren, Mack Gordon"
+Classical,Julian Bream,1957,Fret Works: Dowland & Villa-Lobos,Queen Elizabeth's Galliard,1:33,1,John Dowland
+Progressive Rock,Dixie dregs,1977,Free Fall,Free Fall,4:41,1,Steve Morse
+Classic Rock,Black Sabbath,2004,Master of Reality,After Forever,5:26,2,Tony Iommi
+Classic Rock,Jimi Hendrix,1993,Are You Experienced,The Wind Cries Mary,3:23,7,Jimi Hendrix
+Rock,Dave Matthews,1998,Before These Crowded Streets,Don't Drink the Water,7:01,4,"Beauford, Carter/Matthews, David J."
+Jazz,Charlie Hunter,2004,Friends Seen and Unseen,Eleven Bars for Gandhi,6:57,7,Charlie Hunter
+World,Andy Statman & David Grisman,1995,Songs Of Our Fathers,L'Ma'an Achai V'Re'ei,5:56,8,Shlomo Carlebach
+Jazz,Bill Evans,1958,Everybody Digs Bill Evans,Minority,5:22,1,Gigi Gryce
+Classical,Julian Bream,1992,Nocturnal,Britten: Nocturnal - 1. Musingly (Meditativo),2:14,5,Benjamin Britten
+Classical,Andres Segovia,1955,The Art Of Segovia [Disc 1],Tarrega: Recuerdos de la Alhambra,5:16,1,Francisco Tarrega
+Rock,"Blood, Sweat & Tears",1968,Child Is Father To The Man,Overture,1:32,1,
+World,Andy Statman Quartet,2005,Between Heaven & Earth,Tzamah Nafshi,8:00,8,Karlin-Stolin
+Blues,B.B. King,2005,80,The Thrill Is Gone,5:03,3,
+Rock,Dave Matthews,1998,Before These Crowded Streets,Stay (Wasting Time),5:35,5,"Lessard, Stefan/Beauford, Carter/Moore, Leroi"
+Pop and R&B,Joni Mitchell,2000,Both Sides Now,Answer Me My Love,3:24,5,Carl Sigman/Gerhard Winkler/Fred Rauch
+Rock,Dave Matthews,1996,Crash,Two Step,6:29,2,Dave Matthews
+Progressive Rock,Dixie dregs,1978,What if,Little Kids,2:07,6,
+Easy Listening,Bette Midler,2003,Bette Midler Sings the Rosemary Clooney Songbook,Come On-A My House,1:50,6,"Saroyan, William 1908-1981 -w Bagdasarian, Ross 1919-1972"
+Classical,Julian Bream,1957,Fret Works: Dowland & Villa-Lobos,King of Denmark's Galliard,1:15,8,John Dowland
+Classical,Andres Segovia,2004,The Best Of Andres Segovia,Recuerdos De La Alhambra,5:12,5,Francisco Tarrega
+Classic Rock,Jimi Hendrix,1968,Electric Ladyland,Voodoo Chile,14:59,4,Jimi Hendrix
+Classical,Julian Bream,1957,Fret Works: Dowland & Villa-Lobos,Fantasia,5:02,7,John Dowland
+Blues,B.B. King,1997,Deuces Wild,There Must Be A Better World Somewhere,4:51,7,Rebennack/Pomus
+Jazz,Andy Narell,1992,Down the Road,Green Ballet: 2nd Position for Steel Orchestra,3:41,6,Vince Mendoza
+Jazz,Bill Evans,1962,Interplay,I'll Never Smile Again (Take 7),6:33,3,Ruth Lowe
+Blues,Buddy Guy,1993,Feels Like Rain,I Go Crazy,2:26,2,James Brown
+Jazz,Bill Evans,1978,Affinity,The Other Side of Midnight (Noelle's Theme),3:23,7,Michel Legrand
+Classic Rock,Jimi Hendrix,1968,Electric Ladyland,...And the Gods Made Love,1:23,1,Jimi Hendrix
+Pop and R&B,Joni Mitchell,2000,Both Sides Now,At Last,4:28,2,Mack Gordon/Harry Warren
+Easy Listening,Bette Midler,1993,Experience the Divine,Miss Ottis Regrets,2:40,8,Cole Porter
+Blues,Buddy Guy,1993,Feels Like Rain,Change in the Weather,4:38,7,John Fogerty
+Easy Listening,Bette Midler,2003,Bette Midler Sings the Rosemary Clooney Songbook,This Ole House,3:03,2,"Hamblen, Stuart 1908-1989"
+Progressive Rock,Dixie dregs,1977,Free Fall,Holiday,4:29,2,Steven J. Morse
+Rock,"Blood, Sweat & Tears",1969,"Blood, Sweat & Tears",Smiling Phases,5:11,2,"Jim Capaldi, Steve Winwood, Chris Wood"
+Jazz,Andy Narell,1992,Down the Road,Disorderly Conduct,6:40,4,Andy Narell
+Classic Rock,Jimi Hendrix,1993,Are You Experienced,Purple Haze,2:53,1,Jimi Hendrix
+Jazz,Andy Narell,1992,Down the Road,Green Ballet: 1st Position for Steel Orchestra,2:16,5,Vince Mendoza
+Rock,"Blood, Sweat & Tears",1968,Child Is Father To The Man,Just One Smile,4:38,6,
+Rock,"Blood, Sweat & Tears",1969,"Blood, Sweat & Tears",More And More,3:04,4,"Don Juan, Pea Vee"
+Classic Rock,Jimi Hendrix,1968,Electric Ladyland,Have You Ever Been (To Electric Ladyland),2:10,2,Jimi Hendrix
+Rock,"Blood, Sweat & Tears",1968,Child Is Father To The Man,I Love You More Than You'll Ever Know,5:57,2,
+Blues,B.B. King,1997,Deuces Wild,Rock Me Baby,6:38,3,B.B. King/Joe Josea
+Blues,Buddy Guy,1993,Feels Like Rain,Sufferin' Mind,3:33,6,E. Jones
+Pop and R&B,Joni Mitchell,2000,Both Sides Now,You're My Thrill,3:52,1,Jay Gorney/Sindney Clare
+Easy Listening,Bette Midler,1993,Experience the Divine,Chapel Of Love,2:54,4,Ellie Greenwich/Jeff Barry/Phil Spector
+Blues,B.B. King,2005,80,Hummingbird,4:42,6,
+Progressive Rock,"Emerson, Lake & Palmer",1996,Brain Salad Surgery [Rhino],Jerusalem,2:44,1,Charles Hubert Hastings Parry/William Blake
+Progressive Rock,"Emerson, Lake & Palmer",,The Atlantic Years,Fanfare For The Common Man,5:41,9,
+Jazz,Bill Evans,1962,Interplay,Wrap Your Troubles In Dreams (And Dream Your Troubles Away),6:21,7,Billy Moll/Harry Barris/Ted Koehler
+Classical,Andres Segovia,2004,The Best Of Andres Segovia,"Bouree (Suite In E Minor, BWV 996 - Bach)",1:32,2,Johann Sebastian Bach (1685-1750)
+Rock,Dave Matthews,1996,Crash,Crash Into Me,5:18,3,Dave Matthews
+Easy Listening,Frank Sinatra,1990,The Capitol Years [Disc 1],Someone To Watch Over Me,2:57,12,George & Ira Gershwin/George Gershwin
+Rock,Dave Matthews,1998,Before These Crowded Streets,The Last Stop,6:58,3,"Lessard, Stefan/Beauford, Carter"
+Classic Rock,Jimi Hendrix,1968,Electric Ladyland,Crosstown Traffic,2:26,3,Jimi Hendrix
+Jazz,Bill Evans,1978,Affinity,I Do It For Your Love,7:23,1,Paul Simon
+World,Andy Statman & David Grisman,1995,Songs Of Our Fathers,Dovid Melech Yisrael,2:07,6,Shlomo Carlebach
+Progressive Rock,Dixie dregs,1977,Free Fall,Dig the Ditch,3:51,9,Steven J. Morse
+Rock,Dave Matthews,1996,Crash,Too Much,4:24,4,Dave Matthews
+Classic Rock,Black Sabbath,2004,Master of Reality,Into the Void,6:12,8,Bill Ward/Geezer Butler/Ozzy Osbourne/Tony Iommi
+Easy Listening,Bette Midler,1993,Experience the Divine,From A Distance,4:39,3,Julie Gold
+Classical,Julian Bream,1957,Fret Works: Dowland & Villa-Lobos,Lachrimae Antiquae Galliard,2:59,2,John Dowland
+Rock,Dave Matthews,1996,Crash,Let You Down,4:09,8,Dave Matthews
+Jazz,Bill Evans,1958,Everybody Digs Bill Evans,Night and Day,7:35,4,Cole Porter
+Classic Rock,Black Sabbath,2004,Black Sabbath,Black Sabbath,6:18,1,Bill Ward/Geezer Butler/Ozzy Osbourne/Tony Iommi
+Blues,Buddy Guy,1993,Feels Like Rain,She's Nineteen Years Old,5:43,4,Muddy Waters
+Jazz,Bill Evans,1978,Affinity,The Days of Wine and Roses,6:43,4,"Henry Mancini, Johnny Mercer"
+Progressive Rock,"Emerson, Lake & Palmer",,The Atlantic Years,The Endless Enigma (Part 1),6:41,7,
+Easy Listening,Frank Sinatra,1991,Sinatra Reprise: The Very Good Years,It Was A Very Good Year,4:29,9,E. Drake
+Pop and R&B,Joni Mitchell,1974,Court And Spark,Help Me,3:22,2,Joni Mitchell
+Classical,Julian Bream,1965,"Julian Bream Edition, Vol. 20","Bach: Lute Suite In A Minor, BWV 997 - Praeludium",3:06,7,Johann Sebastian Bach
+Jazz,Bill Evans,1962,Interplay,You And The Night And The Music,7:05,1,Arthur Schwartz/Howard Dietz
+Classical,Julian Bream,1965,"Julian Bream Edition, Vol. 20","Bach: Lute Suite In E Minor, BWV 996 - Sarabande",4:45,4,Johann Sebastian Bach
+Jazz,Charlie Hunter,2004,Friends Seen and Unseen,One for the Kelpers,6:31,1,John Ellis
+Easy Listening,Bette Midler,2003,Bette Midler Sings the Rosemary Clooney Songbook,You'll Never Know,1:44,1,"Warren, Harry 1893-1981 -w Gordon, Mac 1904-1959"
+Progressive Rock,"Emerson, Lake & Palmer",1992,The Atlantic Years,Tank,6:47,4,Carl Palmer/Keith Emerson
+Classic Rock,Jimi Hendrix,1968,Electric Ladyland,"Come On, Pt. 1",4:10,7,Earl King
+World,Andy Statman & David Grisman,1995,Songs Of Our Fathers,Der Rebbe,3:59,9,Trad.
+Blues,B.B. King,2005,80,Early in the Morning,4:50,1,
+Classical,Julian Bream,1992,Nocturnal,Martin: Quatre Pièces Breves - 3. Plainte: Sans Lenteur,2:59,3,Frank Martin
+Jazz,Bill Evans,1958,Everybody Digs Bill Evans,What Is There to Say?,4:54,8,Duke
+Jazz,Andy Narell,1989,Little Secrets,Don't Look Back,9:39,6,Andy Narell
+Progressive Rock,Dixie dregs,1978,What if,What if,5:02,3,Steve Morse
+,,,,,,,
+,,,,,,,
+,,,,,,,
+,,,,,,,
+,,,,,,,
+,,,,,,,
+,,,,,,,
+,,,,,,,
+,,,,,,,
+,,,,,,,
+,,,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
+,,,,,
diff --git a/dojox/grid/tests/enhanced/support/test_ue.js b/dojox/grid/tests/enhanced/support/test_ue.js
new file mode 100644
index 0000000..fd5a539
--- /dev/null
+++ b/dojox/grid/tests/enhanced/support/test_ue.js
@@ -0,0 +1,29 @@
+//Customized sorters only for testing, as all testing data are not in the native format, and performance is bad if dojo.date.locale.parse is used.
+//in a real case, data should be stored as native format
+
+dojo.addOnLoad(function(){
+	if (csvStore1) {
+		csvStore1.comparatorMap = {};
+		csvStore1.comparatorMap['Length'] = function(dateStr1, dateStr2){
+			var date1 = _getDate(dateStr1);
+			var date2 = _getDate(dateStr2);
+			//console.log('in=',dateStr1, ' ', dateStr2, " | out=", date1, ' ', date2);
+			return (date1 > date2) ? 1 : (date1 < date2 ? -1 : 0);
+		};
+		
+		csvStore1.comparatorMap['Track'] = function(numStr1, numStr2){
+			var num1 = new Number(numStr1);
+			var num2 = new Number(numStr2);
+			return (num1 > num2) ? 1 : (num1 < num2 ? -1 : 0);
+		};
+	}
+	
+	_getDate = function(dateStr){
+		//item should be in HH:mm or HH:mm:ss so that dojo.date.stamp.fromISOString can parse it
+		var items = dateStr.split(':');
+		dojo.forEach(items, function(item, index, items){
+			item.length < 2 && (items[index] = '0' + item);
+		});
+		return dojo.date.stamp.fromISOString('T' + items.join(':'));
+	}
+});
diff --git a/dojox/grid/tests/enhanced/test_enhanced_grid.html b/dojox/grid/tests/enhanced/test_enhanced_grid.html
new file mode 100644
index 0000000..011b3b9
--- /dev/null
+++ b/dojox/grid/tests/enhanced/test_enhanced_grid.html
@@ -0,0 +1,181 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.EnhancedGrid</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/themes/tundra/tundra.css";
+		@import "../../enhanced/resources/tundraEnhancedGrid.css";
+		@import "../../enhanced/resources/EnhancedGrid_rtl.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+			padding: 0.5em;
+		}
+		.title {
+			text-align:center;
+		}
+		
+ 		#grid1, #grid2, #grid3 {
+			width: 85.2em;
+			height: 50em;
+		}
+
+	</style>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.EnhancedGrid");
+		dojo.require("dojox.grid.enhanced.plugins.DnD");
+		dojo.require("dojox.grid.enhanced.plugins.Menu");
+		dojo.require("dojox.grid.enhanced.plugins.NestedSorting");
+		dojo.require("dojox.grid.enhanced.plugins.IndirectSelection");
+		dojo.require("dojox.data.CsvStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript">
+		var layout = [{
+			defaultCell: { width: 8, editable: false, type: dojox.grid.cells._Widget },
+			rows:
+			[
+				{ field: "Genre", width: '6'},
+				{ field: "Artist", width: '10'},
+				{ field: "Year", width: '6'},
+				{ field: "Album", width: '12'},
+				{ field: "Name", width: '17'},
+				{ field: "Length", width: '6'},
+				{ field: "Track", width: '6'},
+				{ field: "Composer", width: '15'}				
+			]}
+		];
+
+		var csvStore1 = new dojox.data.CsvStore({id:'csvStore1', url:"support/music-for-demo.part.csv"});
+		
+		/* Un-comment this block to see more usages
+		var layout2 = [
+			[
+				{ field: "Genre", width: '10'},
+				{ field: "Artist", width: '10'},
+				{ field: "Year", width: '10'},
+				{ field: "Album", width: '15'},
+				{ field: "Name", width: '15'},
+				{ field: "Length", width: '10'},
+				{ field: "Track", width: '10'},
+				{ field: "Composer", width: '10'}				
+			]
+		];
+		dojo.addOnLoad(function(){
+			var grid = new dojox.grid.EnhancedGrid({
+				id: "grid3",
+				store: csvStore1,
+				structure: layout,
+				rowSelector: '20px',
+				plugins : {nestedSorting: true, dnd: true, indirectSelection: {name: "Selection", width:"70px", styles:"text-align: center;"}, menus:{headerMenu:"headerMenu", rowMenu:"rowMenu", cellMenu:"cellMenu", selectedRegionMenu:"selectedRegionMenu"}}
+			}, dojo.byId('gridDiv'));
+			grid.startup();
+		});
+		*/
+	</script>
+	<script type="text/javascript" src="support/test_ue.js"></script>
+</head>
+<body class="tundra">
+	<h1 class="title">Test dojox.grid.EnhancedGrid Phase 1 Features</h1>
+	<div>
+		<b>EnhancedGrid phase 1 provides the following features:</b>
+		<ol>
+			<li>Nested Sorting</li>
+			<li>Built-in support for Indirect Selection (radio buttons and check boxes)</li>
+			<li>Declarative context menu</li>
+			<li>Selecting rows/columns via swipe</li>
+			<li>Drag-n-drop: columns,rows - MOVE</li>
+		</ol>
+	</div>
+	
+	<div>
+		<b>Keyboard support:</b>
+		<ol>
+			<li>Use <b>TAB or SHIFT + TAB</b> to navigate keyboard focus among column headers, row headers and cell regions</li>
+			<li>When focus is on column header:<br>
+				<ol style="list-style: none;">
+					<li> - Use <b>LEFT/RIGHT</b> to navigate keyboard focus among column headers </li>
+					<li> - Use <b>SPACE</b> to choose a column or sorting choice</li>
+					<li> - Use <b>SHIFT + LEFT/RIGHT</b> to select multiple columns</li>
+					<li> - Use <b>CTRL + LEFT/RIGHT</b> to move columns</li>
+				</ol>
+			</li>
+			<li>When focus is on row header or column of checkbox:<br>
+				<ol style="list-style: none;">
+					<li> - Use <b>UP/DOWN</b> to navigate keyboard focus among row headers </li>
+					<li> - Use <b>SPACE</b> to choose a row</li>
+					<li> - Use <b>SHIFT + UP/DOWN</b> to select multiple rows</li>
+					<li> - Use <b>CTRL + UP/DOWN</b> to move rows</li>
+				</ol>
+			</li>
+		</ol>
+	</div>
+	
+	<div>
+		<b>Some known issues (plan to fix in phase 2):</b>
+		<ol>	
+			<li>EnhancedGrid doesn't support complicated layout(e.g. multiple rows in column header), TreeGrid(SubGrid).</li>
+		</ol>
+	</div>
+	<!--span dojoType="dojox.data.CsvStore" 
+		jsId="csvStore1" url="support/music-for-demo.part.csv">
+	</span-->
+	<div>
+		<b>
+		    Multiple selection mode:
+		</b>
+		<div id="grid1" dojoType="dojox.grid.EnhancedGrid" query="{ Track: '*' }" rowsPerPage="30" 
+			plugins='{nestedSorting: true, dnd: true, indirectSelection: true, menus:{headerMenu:"headerMenu", rowMenu:"rowMenu", cellMenu:"cellMenu", selectedRegionMenu:"selectedRegionMenu"}}'
+			store="csvStore1" structure="layout" rowSelector="20px">
+			<div dojoType="dijit.Menu" id="headerMenu"  style="display: none;">
+				<div dojoType="dijit.MenuItem">Header Menu Item 1</div>
+				<div dojoType="dijit.MenuItem">Header Menu Item 2</div>
+				<div dojoType="dijit.MenuItem">Header Menu Item 3</div>
+				<div dojoType="dijit.MenuItem">Header Menu Item 4</div>
+			</div>
+			<div dojoType="dijit.Menu" id="rowMenu"  style="display: none;">
+				<div dojoType="dijit.MenuItem">Row Menu Item 1</div>
+				<div dojoType="dijit.MenuItem">Row Menu Item 2</div>
+				<div dojoType="dijit.MenuItem">Row Menu Item 3</div>
+				<div dojoType="dijit.MenuItem">Row Menu Item 4</div>
+			</div>
+			<div dojoType="dijit.Menu" id="cellMenu"  style="display: none;">
+				<div dojoType="dijit.MenuItem">Cell Menu Item 1</div>
+				<div dojoType="dijit.MenuItem">Cell Menu Item 2</div>
+				<div dojoType="dijit.MenuItem">Cell Menu Item 3</div>
+				<div dojoType="dijit.MenuItem">Cell Menu Item 4</div>
+			</div>
+			<div dojoType="dijit.Menu" id="selectedRegionMenu"  style="display: none;">
+				<div dojoType="dijit.MenuItem">Action 1 for Selected Region</div>
+				<div dojoType="dijit.MenuItem">Action 2 for Selected Region</div>
+				<div dojoType="dijit.MenuItem">Action 3 for Selected Region</div>
+				<div dojoType="dijit.MenuItem">Action 4 for Selected Region</div>
+			</div>
+		</div>
+		<br/>
+		<input type='button' value='Select All' onclick='dijit.byId("grid1").rowSelectCell.toggleAllSelection(true)'/>
+		  
+		<input type='button' value='Deselect All' onclick='dijit.byId("grid1").rowSelectCell.toggleAllSelection(false)'/>
+	</div>
+	
+	<!-- Un-comment this block to see more usages
+	<div id="gridDiv"></div>
+	
+	<div>
+		<b>
+		    Single selection mode:
+		</b>
+		<div id="grid2" dojoType="dojox.grid.EnhancedGrid" query="{ Track: '*' }" rowsPerPage="30" selectionMode="single"
+			plugins='{nestedSorting: true, dnd: true, indirectSelection: {name: "Selection", width:"60px", styles:"text-align: center;"}, menus:{headerMenu:"headerMenu", rowMenu:"rowMenu", cellMenu:"cellMenu", selectedRegionMenu:"selectedRegionMenu"}}'
+			store="csvStore1" structure="layout" rowSelector="20px"  
+		</div>
+	</div>
+	-->
+
+</body>
+</html>
diff --git a/dojox/grid/tests/enhanced/test_enhanced_grid_claro.html b/dojox/grid/tests/enhanced/test_enhanced_grid_claro.html
new file mode 100644
index 0000000..63a5f7a
--- /dev/null
+++ b/dojox/grid/tests/enhanced/test_enhanced_grid_claro.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title></title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/themes/claro/claro.css";		
+		@import "../../enhanced/resources/claroEnhancedGrid.css";
+		body {
+			font-size: 0.9em;
+			padding: 0.5em;
+		}
+		.title {
+			padding-top: 1em;
+			padding-bottom: 0.5em;
+			font-weight:bold;
+		}
+		
+ 		#grid1,#grid2,#grid3,#grid4{
+			width: 78em;
+			height: 40em;
+		}
+
+	</style>
+	<script type="text/javascript" src="../../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.EnhancedGrid");
+		dojo.require("dojox.grid.enhanced.plugins.DnD");
+		dojo.require("dojox.grid.enhanced.plugins.Menu");
+		dojo.require("dojox.grid.enhanced.plugins.NestedSorting");
+		dojo.require("dojox.grid.enhanced.plugins.IndirectSelection");
+		dojo.require("dojox.data.CsvStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript">
+		var layout = [{
+			defaultCell: { width: 8, editable: false, type: dojox.grid.cells._Widget },
+			rows:
+			[
+				{ field: "Genre", width: '6'},
+				{ field: "Artist", width: '10'},
+				{ field: "Year", width: '6'},
+				{ field: "Album", width: '12'},
+				{ field: "Name", width: '17'},
+				{ field: "Length", width: '6'},
+				{ field: "Track", width: '6'},
+				{ field: "Composer", width: '15'}				
+			]}
+		];
+		var csvStore1 = new dojox.data.CsvStore({id:'csvStore1', url:"support/music-for-demo.part.csv"});
+	</script>
+	<script type="text/javascript" src="support/test_ue.js"></script>
+</head>
+<body class="claro">
+	<div class="title">Simple DataGrid</div>
+	<div id="grid1" dojoType="dojox.grid.EnhancedGrid" query="{ Track: '*' }" rowsPerPage="30"
+		 store="csvStore1" structure="layout" rowSelector="0px">
+	</div>
+
+	<br/>
+	<div class="title">Enhanced Grid</div>
+	<div id="grid3" dojoType="dojox.grid.EnhancedGrid" query="{ Track: '*' }" rowsPerPage="30"
+		plugins='{nestedSorting: true, dnd: true, indirectSelection: {width:"40px"}}'
+		store="csvStore1" structure="layout" rowSelector="20px">
+	</div>	
+</body>
+</html>
diff --git a/dojox/grid/tests/images/closed.gif b/dojox/grid/tests/images/closed.gif
new file mode 100644
index 0000000..7d3afa4
Binary files /dev/null and b/dojox/grid/tests/images/closed.gif differ
diff --git a/dojox/grid/tests/images/flatScreen.gif b/dojox/grid/tests/images/flatScreen.gif
new file mode 100644
index 0000000..05edd72
Binary files /dev/null and b/dojox/grid/tests/images/flatScreen.gif differ
diff --git a/dojox/grid/tests/images/open.gif b/dojox/grid/tests/images/open.gif
new file mode 100644
index 0000000..37efd2c
Binary files /dev/null and b/dojox/grid/tests/images/open.gif differ
diff --git a/dojox/grid/tests/performance/_gridPerfFramework.js b/dojox/grid/tests/performance/_gridPerfFramework.js
new file mode 100644
index 0000000..28733e6
--- /dev/null
+++ b/dojox/grid/tests/performance/_gridPerfFramework.js
@@ -0,0 +1,191 @@
+dojo.require("dojo.data.ItemFileWriteStore");
+dojo.provide("dojox.grid.tests.performance._gridPerfFramework");
+
+(function(){
+	// some sample data
+	var data_list = [ 
+		{ col1: "normal", col2: false, col3: "new", col4: 'But are not followed by two hexadecimal', col5: 29.91, col6: 10, col7: false },
+		{ col1: "important", col2: false, col3: "new", col4: 'Because a % sign always indicates', col5: 9.33, col6: -5, col7: false },
+		{ col1: "important", col2: true, col3: "read", col4: 'Signs can be selectively', col5: 19.34, col6: 0, col7: true },
+		{ col1: "note", col2: false, col3: "read", col4: 'However the reserved characters', col5: 15.63, col6: 0, col7: true },
+		{ col1: "normal", col2: true, col3: "replied", col4: 'It is therefore necessary', col5: 24.22, col6: 5.50, col7: true },
+		{ col1: "important", col2: false, col3: "replied", col4: 'To problems of corruption by', col5: 9.12, col6: -3, col7: true },
+		{ col1: "note", col2: false, col3: "replied", col4: 'Which would simply be awkward in', col5: 12.15, col6: -4, col7: false }
+	];
+	
+	// default querystring values
+	var default_obj = {rows: "100", layout: "single", rowSelector: "false", doProfiling: "false"};
+
+	// values for the performance tests
+	var iterations = 100;
+	var duration = 100;
+	var delay = 100;
+	
+	// Store functions
+	var stores = {};
+	dojo.setObject("getStore", function(numRows, force){
+		if(force){
+			delete stores[numRows];
+		}
+		if(!stores[numRows]){
+			var data = {
+				identifier: 'id',
+				label: 'id',
+				items: []
+			};
+			for(var i=0, l=data_list.length; i<numRows; i++){
+				data.items.push(dojo.mixin({ id: i }, data_list[i%l]));
+			}
+			stores[numRows] = new dojo.data.ItemFileWriteStore({data: data});
+		}
+		return stores[numRows];
+	});
+	
+	// Layout generation functions
+	dojo.setObject("getLayout", function(type){
+		switch (type.toLowerCase()){
+			case "dual":
+				return [{
+					cells: [
+						{name: 'Column 0', field: 'id',   width: '100px' },
+						{name: 'Column 1', field: 'col1', width: '100px' },
+						{name: 'Column 2', field: 'col2', width: '100px' },
+						{name: 'Column 3', field: 'col3', width: '100px' }
+					],
+					noscroll: true
+				},{
+					cells: [
+						{name: 'Column 4', field: 'col4', width: '300px' },
+						{name: 'Column 5', field: 'col5', width: '150px' },
+						{name: 'Column 6', field: 'col6', width: '150px' },
+						{name: 'Column 7', field: 'col7', width: '150px' },
+						{name: 'Column 8', field: 'col8', width: '150px' }
+					]
+				}];
+			case "single":
+			default:
+				return [
+					[
+						{ name: 'Column 0', field: 'id',   width: '10%' },
+						{ name: 'Column 1', field: 'col1', width: '10%' },
+						{ name: 'Column 2', field: 'col2', width: '10%' },
+						{ name: 'Column 3', field: 'col3', width: '10%' },
+						{ name: 'Column 4', field: 'col4', width: '20%' },
+						{ name: 'Column 5', field: 'col5', width: '10%' },
+						{ name: 'Column 6', field: 'col6', width: '10%' },
+						{ name: 'Column 7', field: 'col7', width: '10%' },
+						{ name: 'Column 8', field: 'col3', width: '10%' }
+					]
+				];
+		}
+	});
+
+	// Returns the parameters in the query string as an object
+	// It mixes in over the defaultObj you pass it - if you pass
+	// true, it will mix in over the global default obj.
+	dojo.setObject("searchParamsAsObj", function(defaultObj){
+		var s = (window.location.search||"").replace(/^\?/, "");
+		var p = s.split("&");
+		var o = {}
+		dojo.forEach(p, function(i){
+			var b = i.split("=");
+			o[b[0]] = b[1];
+		});
+		if(defaultObj === true){
+			defaultObj = default_obj;
+		}
+		return dojo.mixin(dojo.clone(defaultObj||{}), o);
+	});
+	
+	// Gets the tests for a row/layout/selector type test (the common one)
+	// This parses the object and returns a single instance and either perf
+	// tests (if run within the runner) or buttons for changing value (if
+	// run directly)
+	//
+	// getRunFunction is the core function to call.  It gets the row, layout
+	// and selector values, as well as a boolean if it's a perf function or
+	// not.
+	dojo.setObject("getRLSTests", function(getRunFunction, getSetUpFunction, getTearDownFunction){
+		var isTop = (window.top == window);
+		var obj = searchParamsAsObj(default_obj);		
+		var rows = parseInt(obj.rows, 10);
+		var layout = obj.layout;
+		var rowSelector = (obj.rowSelector.toLowerCase() == "true");
+		var doProfiling = isTop && dojo.isMoz && obj.doProfiling.toLowerCase() == "true";
+		var name = layout + " Layout" + (rowSelector ? " w/ Row Selector" : "");
+		var t = {
+			name: name,
+			runTest: getRunFunction(rows, layout, rowSelector, doProfiling, false)
+		};
+		if(getSetUpFunction){
+			t.setUp = getSetUpFunction(rows, layout, rowSelector, doProfiling, false);
+		}
+		if(getTearDownFunction){
+			t.tearDown = getTearDownFunction(rows, layout, rowSelector, doProfiling, false);
+		}
+		var tests = [ t ];
+		if(isTop && !window._buttonsAdded){
+			// Give buttons amd text boxes for changing views/rows/etc
+			var n = dojo.query(".heading")[0];
+			n = dojo.create("span", {innerHTML: "Rows: "}, n, "after");
+			n = dojo.create("input", {
+				type: "text",
+				value: rows,
+				size: 5,
+				onchange: function(){
+					v = parseInt(this.value, 10);
+					if(v && !isNaN(v)){
+						window.location.search="?rows=" + v + 
+								"&layout=" + layout + 
+								"&rowSelector=" + (rowSelector ? "true" : "false") +
+								"&doProfiling=" + (doProfiling ? "true" : "false");
+					}
+				}
+			}, n, "after");
+			n = dojo.create("button", {
+				innerHTML: layout == "single" ? "Dual Layout" : "Single Layout",
+				onclick: function(){window.location.search="?rows=" + rows + 
+								"&layout=" + (layout == "single" ? "dual" : "single") + 
+								"&rowSelector=" + (rowSelector ? "true" : "false") +
+								"&doProfiling=" + (doProfiling ? "true" : "false")}
+			}, n, "after");
+			n = dojo.create("button", {
+				innerHTML: rowSelector ? "Remove Row Selector" : "Add Row Selector",
+				onclick: function(){window.location.search="?rows=" + rows + 
+								"&layout=" + layout + 
+								"&rowSelector=" + (!rowSelector ? "true" : "false") +
+								"&doProfiling=" + (doProfiling ? "true" : "false")}
+			}, n, "after");
+			if(dojo.isMoz){
+				n = dojo.create("button", {
+					innerHTML: doProfiling ? "No Profiling" : "Do Profiling",
+					onclick: function(){window.location.search="?rows=" + rows + 
+									"&layout=" + layout + 
+									"&rowSelector=" + (rowSelector ? "true" : "false") +
+									"&doProfiling=" + (!doProfiling ? "true" : "false")}
+				}, n, "after");
+			}
+			window._buttonsAdded = true;
+		}else if (!isTop){
+			// Only run the perf tests if we are within the runner (which
+			// gives us pretty graphs and statistics...)
+			t = {
+				name: "Perf " + name,
+				testType: "perf",
+				trialDuration: duration,
+				trialIterations: iterations,
+				trialDelay: delay,
+				runTest: getRunFunction(rows, layout, rowSelector, doProfiling, true)
+			}
+			if(getSetUpFunction){
+				t.setUp = getSetUpFunction(rows, layout, rowSelector, doProfiling, true);
+			}
+			if(getTearDownFunction){
+				t.tearDown = getTearDownFunction(rows, layout, rowSelector, doProfiling, true);
+			}
+			tests.push(t);
+		}
+		return tests;
+	})
+
+})();
diff --git a/dojox/grid/tests/performance/creation.html b/dojox/grid/tests/performance/creation.html
new file mode 100644
index 0000000..fa7f807
--- /dev/null
+++ b/dojox/grid/tests/performance/creation.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Performance Test: dojox.grid.DataGrid Creation</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../resources/Grid.css";
+		@import "../../resources/tundraGrid.css";
+
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../../dojo/dojo.js"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojox.grid.tests.performance._gridPerfFramework");
+		dojo.require("dojox.grid.DataGrid");
+
+		dojo.addOnLoad(function(){
+			doh.register(searchParamsAsObj(true).rows + " rows", 
+				getRLSTests(function(rows, layout, rowSelector, doProfiling, isPerf){
+					return function(t){
+						if(doProfiling){
+							console.profile("create()");
+						}
+						var g = new dojox.grid.DataGrid({
+							store: getStore(rows),
+							structure: getLayout(layout),
+							rowSelector: rowSelector
+						}, dojo.create("div", null, dojo.body()));
+						if(doProfiling){
+							console.profileEnd();
+							console.profile("startup()");
+						}
+						g.startup();
+						if(doProfiling){
+							console.profileEnd();
+						}
+						if(isPerf){
+							g.destroy();
+						}else{
+							t.t(true);
+						}
+					};
+				}));
+			doh.run();
+		});
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">Performance Test: dojox.grid.DataGrid Creation</div>
+</body>
+</html>
diff --git a/dojox/grid/tests/performance/dataNotification.html b/dojox/grid/tests/performance/dataNotification.html
new file mode 100644
index 0000000..8a91a4b
--- /dev/null
+++ b/dojox/grid/tests/performance/dataNotification.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Performance Test: dojox.grid.DataGrid dojo.data Notification</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../resources/Grid.css";
+		@import "../../resources/tundraGrid.css";
+
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../../dojo/dojo.js"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojox.grid.tests.performance._gridPerfFramework");
+		dojo.require("dojox.grid.DataGrid");
+
+		dojo.addOnLoad(function(){
+			var p = searchParamsAsObj(true);
+			var s = getStore(p.rows);
+			var g = new dojox.grid.DataGrid({
+				store: s,
+				structure: getLayout(p.layout),
+				rowSelector: p.rowSelector
+			}, dojo.create("div", null, dojo.body()));
+			g.startup();
+			var cnt = p.rows + 1;
+			
+			var cb = function(items){
+				console.debug("HAVE ITEMS!", items.length);
+				doh.register(searchParamsAsObj(true).rows + " rows - change column", 
+					getRLSTests(function(rows, layout, rowSelector, doProfiling, isPerf){
+						return function(t){
+							if(doProfiling){
+								console.profile("changeColumn()");
+							}
+							dojo.forEach(items, function(i){
+								s.setValue(i, "col2", !s.getValue(i, "col2"));
+							});
+							if(doProfiling){
+								console.profileEnd();
+							}
+						};
+					}));
+				doh.register(searchParamsAsObj(true).rows + " rows - change row", 
+					getRLSTests(function(rows, layout, rowSelector, doProfiling, isPerf){
+						return function(t){
+							if(doProfiling){
+								console.profile("changeRow()");
+							}
+							var i = items[0];
+							s.setValue(i, "col1", s.getValue(i, "col1") == "normal" ? "important" : "normal");
+							s.setValue(i, "col2", !s.getValue(i, "col2"));
+							s.setValue(i, "col3", s.getValue(i, "col3") == "new" ? "read" : "new");
+							s.setValue(i, "col4", s.getValue(i, "col4") == "hex" ? "But are not followed by two hexadecimal" : "hex");
+							s.setValue(i, "col5", -(s.getValue(i, "col5")));
+							s.setValue(i, "col6", -(s.getValue(i, "col6")));
+							s.setValue(i, "col7", !s.getValue(i, "col7"));
+							if(doProfiling){
+								console.profileEnd();
+							}
+						};
+					}));
+				doh.register(searchParamsAsObj(true).rows + " rows - new/delete", 
+					getRLSTests(function(rows, layout, rowSelector, doProfiling, isPerf){
+						return function(t){
+							if(doProfiling){
+								console.profile("newItem()");
+							}
+							var i = s.newItem({id: cnt, 
+												col1: "normal", 
+												col2: false, 
+												col3: "new", 
+												col4: 'But are not followed by two hexadecimal', 
+												col5: 29.91, 
+												col6: 10, 
+												col7: false });
+							cnt++;
+							if(doProfiling){
+								console.profileEnd();
+								console.profile("deleteItem()");
+							}
+							s.deleteItem(i);
+							if(doProfiling){
+								console.profileEnd();
+							}
+						};
+					}));
+				doh.run();
+			};
+			s.fetch({onComplete: cb});
+		});
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">Performance Test: dojox.grid.DataGrid dojo.data Notification</div>
+</body>
+</html>
diff --git a/dojox/grid/tests/performance/module.js b/dojox/grid/tests/performance/module.js
new file mode 100644
index 0000000..3d62ce6
--- /dev/null
+++ b/dojox/grid/tests/performance/module.js
@@ -0,0 +1,26 @@
+dojo.provide("dojox.grid.tests.performance.module");
+
+doh.register("dojox.grid.tests.performance.module", []);
+
+try{
+	var numRows = [100];
+	var layouts = ["Single", "Dual"];
+	var selectors = [false, true];
+	dojo.forEach(numRows, function(r){
+		dojo.forEach(layouts, function(l){
+			dojo.forEach(selectors, function(s){
+				// 5-minute timeout on each of these - since they can take quite a while...
+				doh.registerUrl("Grid Creation - " + r + " Rows, " + l + " Layout" + (s ? "w/ selector" : ""), 
+					dojo.moduleUrl("dojox.grid.tests.performance", "creation.html") + 
+									"?rows=" + r + "&layout=" + l.toLowerCase() + "&rowSelector=" + s,
+					300000);
+				doh.registerUrl("Grid dojo.data Notification - " + r + " Rows, " + l + " Layout" + (s ? "w/ selector" : ""), 
+					dojo.moduleUrl("dojox.grid.tests.performance", "dataNotification.html") + 
+									"?rows=" + r + "&layout=" + l.toLowerCase() + "&rowSelector=" + s,
+					300000);
+			});
+		});
+	});
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/grid/tests/performance/runTests.html b/dojox/grid/tests/performance/runTests.html
new file mode 100644
index 0000000..07bb3e7
--- /dev/null
+++ b/dojox/grid/tests/performance/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>D.O.H. Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../../util/doh/runner.html?testModule=dojox.grid.tests.performance.module"></HEAD>
+    <body>
+        Redirecting to D.O.H runner.
+    </body>
+</html>
\ No newline at end of file
diff --git a/dojox/grid/tests/robot/7815.html b/dojox/grid/tests/robot/7815.html
new file mode 100755
index 0000000..645197a
--- /dev/null
+++ b/dojox/grid/tests/robot/7815.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>doh.robot #7815 regression test</title>
+
+	<style>
+		@import "../../../../util/doh/robot/robot.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../../dojo/dojo.js"
+		djConfig="isDebug: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");
+
+		dojo.addOnLoad(function(){
+
+			doh.robot.initRobot('_DataGrid.html');
+
+			doh.register("#7815",[
+				{
+					name: "editor toolbar displays",
+					timeout:60000,
+					runTest: function(){
+						// see also "edit reordered columns" test below
+						var d = new doh.Deferred();
+						var grid=dijit.byId('markup_grid_1');
+						doh.robot.sequence(function(){
+							var initialFocus = dojo.byId('initialfocus');
+							initialFocus.focus();
+						});
+						// now move focus to first ID cell of markup grid
+						var tabCount = dojo.isIE? 3:(dojo.isFF?4:6);
+						for(var i=0; i<tabCount; i++){
+							doh.robot.keyPress(dojo.keys.TAB,500);
+						}
+						// precondition: cells still arranged to id date priority mark status message amount amount
+						for(var i=0; i<5; i++){
+							doh.robot.keyPress(dojo.keys.RIGHT_ARROW,500);
+						}
+						doh.robot.keyPress(dojo.keys.ENTER,500);
+						doh.robot.sequence(d.getTestCallback(function(){
+							doh.isNot(undefined,dijit.byId('dijit_Editor_0'),"Editing the 6th field of the 1st row did not open the expected dijit.Editor.");
+							doh.t(dijit.byId('dijit_Editor_0')._focused);
+							doh.isNot(undefined,dijit.byId('dijit_Toolbar_0'),"Editor toolbar should have been created.");
+							doh.isNot(undefined,dijit.byId('dijit_Toolbar_0').domNode.parentNode,"Editor toolbar should have been attached to the DOM");
+						}),500);
+						return d;
+					}
+				}
+			]);
+			doh.run();
+		});
+	</script>
+</head>
+</html>
diff --git a/dojox/grid/tests/robot/DataGrid_a11y.html b/dojox/grid/tests/robot/DataGrid_a11y.html
new file mode 100755
index 0000000..e2e2b8c
--- /dev/null
+++ b/dojox/grid/tests/robot/DataGrid_a11y.html
@@ -0,0 +1,179 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>doh.robot DataGrid tests</title>
+
+	<style>
+		@import "../../../../util/doh/robot/robot.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../../dojo/dojo.js"
+		djConfig="isDebug: true"></script>
+		<script type="text/javascript" src="../../../../dijit/tests/helpers.js"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.robotx");
+
+		dojo.addOnLoad(function(){
+
+			doh.robot.initRobot('_DataGrid.html');
+
+			doh.register("dojo.data integration",
+			[
+				{
+					name: "user sort",
+					grid: null,
+					timeout:15000,
+					setUp: function(){
+						var params = new dojo.global.Object();
+						params.id = 'prog_grid_1';
+						params.structure = dojo.global.structure1;
+						params.store = dojo.global.structure1_store1;
+						params.query = { id: '*' };
+						this.grid = new dojo.global.dojox.grid.DataGrid(params,dojo.byId('prog_grid_1'));
+						this.grid.startup();
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						var _this=this;
+						var initialFocus = dojo.byId('initialfocus');
+						initialFocus.focus();
+						// now move focus to ID header of prog grid
+						var tabCount = dojo.isIE? 2:(dojo.isFF?3:5);
+						for(var i=0; i<tabCount; i++){
+							doh.robot.keyPress(dojo.keys.TAB,500);
+						}
+						doh.robot.keyPress(dojo.keys.SPACE,500);
+						doh.robot.keyPress(dojo.keys.SPACE,500);
+						doh.robot.sequence(d.getTestCallback(function(){
+							var item=_this.grid.getItem(0);
+							doh.is(99,item.id,"first item should have had id==99 due to reverse sort");
+						}),7000);
+						return d;
+					},
+					tearDown: function(){
+						var node = dojo.create('div',{id:this.grid.domNode.id, rowSelector:"20px"});
+						dojo.style(node,{width: "100%",height:"100px"});
+						var parent = this.grid.domNode.parentNode;
+						this.grid.destroyRecursive();
+						parent.appendChild(node);
+						this.grid = null;
+					}
+				}
+			]);
+			doh.register("UI verification",[
+				{
+					name: "edit columns",
+					timeout:60000,
+					grid: null,
+					setUp:function(){
+						this.grid = dijit.byId('markup_grid_1');
+					},
+					runTest: function(){
+						// see also "edit reordered columns" test below
+						var d = new doh.Deferred();
+						var grid=this.grid;
+						var initialFocus = dojo.byId('initialfocus');
+						initialFocus.focus();
+						// now move focus to first ID cell of markup grid
+						var tabCount = dojo.isIE? 3:(dojo.isFF?4:6);
+						for(var i=0; i<tabCount; i++){
+							doh.robot.keyPress(dojo.keys.TAB,500);
+						}
+						// precondition: cells still arranged to id date priority mark status message amount amount
+						var editorids=[null,'dijit_form_DateTextBox_0','dijit_form_ComboBox_0','dijit_form_CheckBox_0',null,'dijit_Editor_0','dijit_form_CurrencyTextBox_0','dijit_form_HorizontalSlider_0'];
+						function nextTest(i){
+							if(i==editorids.length){
+								d.callback(true);
+								return;
+							}
+							if(!editorids[i]){
+								doh.robot.keyPress(dojo.keys.RIGHT_ARROW,500);
+								doh.robot.sequence(function(){
+									nextTest(i+1);
+								},500);
+								return;
+							}
+							doh.robot.sequence(function(){
+								var cells=dojo.query("td.dojoxGridCell",grid.views.views[1].scrollboxNode);
+								doh.robot.keyPress(dojo.keys.ENTER,500);
+								doh.robot.sequence(function(){
+									try{
+										// this better have opened the expected editor or something very bad happened
+										doh.isNot(undefined,dijit.byId(editorids[i]),"Editing the "+i+" field of the 1st row did not open the expected editor.");
+										doh.t(dijit.byId(editorids[i])._focused);
+										grid.edit.cancel();
+										doh.robot.keyPress(dojo.keys.RIGHT_ARROW,500);
+										doh.robot.sequence(function(){
+											nextTest(i+1);
+										},500);
+									}catch(e){
+										d.callback(e);
+									}
+								},2000);
+							},500);
+						}
+						nextTest(0);
+						return d;
+					},
+					tearDown:function(){
+						// done editing
+						
+						this.grid.edit.cancel();
+						this.grid = null;
+					}
+				}
+			]);
+			doh.register("Context Menu",[
+				{
+					name: "invoke context menu",
+					timeout:10000,
+					grid: null,
+					setUp:function(){
+						this.grid = dijit.byId('markup_grid_1');
+					},
+					runTest: function(){
+						
+						var d = new doh.Deferred();
+						var grid=this.grid;
+						var initialFocus = dojo.byId('initialfocus');
+						initialFocus.focus();
+						// now move focus to first header cell of markup grid
+						var tabCount = dojo.isIE? 2:(dojo.isFF?3:5);
+						for(var i=0; i<tabCount; i++){
+							doh.robot.keyPress(dojo.keys.TAB,500);
+						}
+						// move to Date Column Header
+						doh.robot.keyPress(dojo.keys.RIGHT_ARROW,500);
+							// open context menu via keyboard
+							if (dojo.isMac) {
+								doh.robot.keyPress(dojo.keys.SPACE, 500, {
+									ctrl: true
+								});
+							}else {
+								doh.robot.keyPress(dojo.keys.F10, 500, {
+									shift: true
+								});
+							}
+
+						doh.robot.sequence(d.getTestCallback(function(){
+							var menu = dijit.byId("gridMenu"); 
+							doh.t(isVisible(menu), "menu is now shown");
+							doh.robot.keyPress(dojo.keys.ESCAPE,0, {}, true); // close context menu
+						}), 1500);
+						
+						return d;
+
+					},
+					tearDown:function(){
+						this.grid = null;
+					}
+				}
+			]);
+			doh.run();
+		});
+	</script>
+</head>
+</html>
diff --git a/dojox/grid/tests/robot/DataGrid_mouse.html b/dojox/grid/tests/robot/DataGrid_mouse.html
new file mode 100755
index 0000000..c5a7a85
--- /dev/null
+++ b/dojox/grid/tests/robot/DataGrid_mouse.html
@@ -0,0 +1,550 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>doh.robot DataGrid tests</title>
+
+	<style>
+		@import "../../../../util/doh/robot/robot.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../../dojo/dojo.js"
+		djConfig="isDebug: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");
+
+		dojo.addOnLoad(function(){
+
+			doh.robot.initRobot('_DataGrid.html');
+
+			doh.register("dojo.data integration",
+			[
+				{
+					name: "set the store of a new DataGrid",
+					grid: null,
+					timeout:5000,
+					setUp: function(){
+						var params = new dojo.global.Object();
+						params.id = 'prog_grid_1';
+						params.structure = dojo.global.structure1;
+						this.grid = new dojo.global.dojox.grid.DataGrid(params, dojo.byId('prog_grid_1'));
+						this.grid.startup();
+					},
+					runTest: function(){
+						// need async test or tearDown will not fire on failure (assertion failed == don't tear down)
+						var d = new doh.Deferred();
+						var _this=this;
+						doh.robot.sequence(d.getTestCallback(function(){
+							// assuming exception == doh error
+							console.log("Setting store, if there is an error then it failed.");
+							_this.grid.setStore(dojo.global.structure1_store1, {}, {});
+							console.log("Done setting store and rendering.");
+							// last row should have something
+							doh.t(_this.grid.getItem(0),"0th row should have been not null");
+						}),500);
+						return d;
+					},
+					tearDown: function(){
+						var node = dojo.create('div',{id:this.grid.domNode.id, rowSelector:"20px"});
+						dojo.style(node,{width: "100%",height:"100px"});
+						var parent = this.grid.domNode.parentNode;
+						this.grid.destroyRecursive();
+						parent.appendChild(node);
+						this.grid = null;
+					}
+				},
+				{
+					name: "set the query of a new DataGrid",
+					grid: null,
+					timeout:5000,
+					setUp: function(){
+						var params = new dojo.global.Object();
+						params.id = 'prog_grid_1';
+						params.structure = dojo.global.structure1;
+						params.store = dojo.global.structure1_store1;
+						this.grid = new dojo.global.dojox.grid.DataGrid(params, dojo.byId('prog_grid_1'));
+						this.grid.startup();
+					},
+					runTest: function(){
+						// need async test or tearDown will not fire on failure (assertion failed == don't tear down)
+						var d = new doh.Deferred();
+						var _this=this;
+						doh.robot.sequence(d.getTestCallback(function(){
+							// assuming exception == doh error
+							console.log("Setting query, if there is an error then it failed.");
+							_this.grid.setQuery({ id: '1' },{});
+							console.log("Done setting query and rendering.");
+							// 0th row should have something
+							var item = _this.grid.getItem(0);
+							doh.t(item,"0th row should have been not null");
+							// 1st row should not
+							doh.f(_this.grid.getItem(1),"1st row should have been null");
+						}),500);
+						return d;
+					},
+					tearDown: function(){
+						var node = dojo.create('div',{id:this.grid.domNode.id, rowSelector:"20px"});
+						dojo.style(node,{width: "100%",height:"100px"});
+						var parent = this.grid.domNode.parentNode;
+						this.grid.destroyRecursive();
+						parent.appendChild(node);
+						this.grid = null;
+					}
+				},
+				{
+					name: "set sortFields",
+					grid: null,
+					changedItem: null,
+					timeout:5000,
+					setUp: function(){
+						this.grid = dijit.byId('markup_grid_1');
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						var _this=this;
+						doh.robot.sequence(d.getTestCallback(function(){
+							_this.grid.attr("sortFields",[{attribute:"col3",descending:true},{attribute:"id",descending:true}]);
+							dojo.global.structure1_store1.setValue(dojo.global.structure1_store1._getItemByIdentity(1),"col3","read");
+							// must force refresh to resort
+							_this.grid.render();
+							var item=_this.grid.getItem(0);
+							doh.is("read",item.col3,"first item should have had status==read after sort");
+							doh.is(1,item.id,"first item should have had id==1");
+							item=_this.grid.getItem(1);
+							doh.is("new",item.col3,"second item should have had status==new after sort");
+							doh.is(99,item.id,"second item should have had id==99");
+						}),500);
+						return d;
+					},
+					tearDown: function(){
+						this.grid.attr("sortFields",[{attribute:"id",descending:false}]);
+						dojo.global.structure1_store1.setValue(dojo.global.structure1_store1._getItemByIdentity(1),"col3","new");
+						this.grid.render();
+						this.grid = null;
+					}
+				},
+				{
+					name: "onNew,onSet,onDelete",
+					grid: null,
+					timeout:5000,
+					connects: [],
+					onNew: null,
+					onSet: null,
+					onDelete: null,
+					setUp: function(){
+						this.grid = dijit.byId('markup_grid_2');
+						var _this=this;
+						this.connects.push(dojo.connect(this.grid,"_onNew",this,function(item){
+							_this.onNew = arguments;
+						}));
+						this.connects.push(dojo.connect(this.grid,"_onSet",this,function(item,attribute,oldvalue,newvalue){
+							_this.onSet = arguments;
+						}));
+						this.connects.push(dojo.connect(this.grid,"_onDelete",this,function(item){
+							_this.onDelete = arguments;
+						}));
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						var _this=this;
+						doh.robot.mouseMoveAt('mainTabContainer_tablist_dijit_layout_ContentPane_1',500);
+						doh.robot.mouseClick({left:true},500);
+						doh.robot.sequence(d.getTestCallback(function(){
+							// onNew
+							var item = dojo.global.structure1_store2.newItem({
+								id: 100,
+								col1: 'note',
+								col2: true,
+								col3: 'read',
+								col4: 'New text',
+								col5: 1,
+								col6: 2,
+								col7: false,
+								col8: new Date()
+							});
+							doh.isNot(null,_this.onNew,"onNew did not fire");
+							doh.is(item,_this.onNew[0],"unexpected item passed to onNew");
+							// onSet
+							var attribute = "col5";
+							var oldvalue = item[attribute];
+							var newvalue = 30;
+							dojo.global.structure1_store2.setValue(item,attribute,newvalue);
+							doh.isNot(null,_this.onSet,"onSet did not fire");
+							doh.is(attribute,_this.onSet[1],"unexpected attribute set");
+							doh.is(oldvalue,_this.onSet[2],"unexpected old value");
+							doh.is(newvalue,_this.onSet[3],"wrong new value");
+							// onDelete
+							var success = dojo.global.structure1_store2.deleteItem(item);
+							doh.isNot(null,_this.onDelete,"onDelete did not fire");
+							doh.t(success,"item not deleted");
+						}),500);
+						return d;
+					},
+					tearDown: function(){
+						dojo.forEach(this.connects, function(c){
+							dojo.disconnect(c);
+						});
+						this.onNew = null;
+						this.onSet = null;
+						this.onDelete = null;
+						this.grid = null;
+					}
+				},
+				{
+					name: "user sort",
+					grid: null,
+					timeout:15000,
+					setUp: function(){
+						var params = new dojo.global.Object();
+						params.id = 'prog_grid_1';
+						params.structure = dojo.global.structure1;
+						params.store = dojo.global.structure1_store1;
+						params.query = { id: '*' };
+						this.grid = new dojo.global.dojox.grid.DataGrid(params,dojo.byId('prog_grid_1'));
+						this.grid.startup();
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						var _this=this;
+						var columns = dojo.query('div.dojoxGridSortNode',_this.grid.domNode);
+						doh.robot.mouseMoveAt(columns[0]);
+						doh.robot.mouseClick({left:true},500);
+						doh.robot.mouseClick({left:true},500);
+						doh.robot.sequence(d.getTestCallback(function(){
+							var item=_this.grid.getItem(0);
+							doh.is(99,item.id,"first item should have had id==99 due to reverse sort");
+						}),7000);
+						return d;
+					},
+					tearDown: function(){
+						var node = dojo.create('div',{id:this.grid.domNode.id, rowSelector:"20px"});
+						dojo.style(node,{width: "100%",height:"100px"});
+						var parent = this.grid.domNode.parentNode;
+						//this.grid.destroyRecursive();
+						//parent.appendChild(node);
+						this.grid = null;
+					}
+				}
+			]);
+			doh.register("UI verification",[
+				{
+					name: "identical grids",
+					timeout:10000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						// these grids are identical except for y position, their components should have the same styles when rendered
+						var grids=[dijit.byId('markup_grid_1'),dijit.byId('markup_grid_2'),dijit.byId('markup_grid_3'),dijit.byId('markup_grid_markup_structure')];
+						// render all grids and collect widths from them
+						var gridData=[];
+						for(var i=0; i<grids.length; i++){
+							gridData.push({});
+							doh.robot.mouseMoveAt('mainTabContainer_tablist_dijit_layout_ContentPane_'+i,500);
+							doh.robot.mouseClick({left:true},500);
+							// i == gridData.length when the following sequence executes so use dojo.hitch to pass i along
+							doh.robot.sequence(dojo.hitch(this,function(i){
+								// copy style data from the now visible grid
+								gridData[i].cellBoxes=[];
+								var cells=dojo.query("td.dojoxGridCell",grids[i].views.views[1].scrollboxNode);
+								for(var j=0; j<dojo.global.structure1[0].rows.length; j++){
+									var box = dojo.marginBox(cells[j]);
+									gridData[i].cellBoxes[j]={w:box.w,h:box.h};
+								}
+								gridData[i].height = dojo.marginBox(grids[i].domNode).h;
+								gridData[i].rowSelectorWidth = dojo.marginBox(dojo.query("* td.dojoxGridRowbarInner",grids[i].domNode)[0]).w;
+								gridData[i].scrollBoxWidth = dojo.marginBox(grids[i].views.views[1].scrollboxNode).w;
+							},i),500);
+						}
+						doh.robot.sequence(d.getTestCallback(function(){
+							for(var i=1; i<grids.length; i++){
+								// compare the dimensions of each cell
+								for(var j=0; j<gridData[i].cellBoxes.length; j++){
+									doh.is(gridData[0].cellBoxes[j],gridData[i].cellBoxes[j],dojo.global.structure1[0].rows[j].name+" cell in "+grids[i].id+" should be the same as "+grids[0].id);
+								}
+								// compare the width of the initially visible (correct) grid to the grids in the other tabs
+								doh.is(gridData[0].rowSelectorWidth,gridData[i].rowSelectorWidth,grids[i].id+" row selector width should be the same as "+grids[0].id);
+								// compare the scrollBox width (determines whether the user can scroll the grid with the vertical scrollbar)
+								doh.is(gridData[0].scrollBoxWidth, gridData[i].scrollBoxWidth, grids[i].id+" scrollboxWidth should be the same as "+grids[0].id);
+								// compare heights of all of these identical grids (since they have the same amount of data, they should be the same height right?)
+								doh.is(gridData[0].height, gridData[i].height, grids[i].id+" height should be the same as "+grids[0].id);
+							}
+						}),500);
+						return d;
+					}
+				},
+				{
+					name: "update() grids",
+					timeout:20000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						var grid1=dijit.byId('markup_grid_1'); // visible
+						var grid2=dijit.byId('markup_grid_2'); // hidden in tab
+						doh.robot.mouseMoveAt('mainTabContainer_tablist_dijit_layout_ContentPane_0',500);
+						doh.robot.mouseClick({left:true},500);
+						doh.robot.sequence(function(){
+							// sizes before update
+							var boxBefore1 = dojo.marginBox(grid1.domNode);
+							var boxBefore2 = dojo.marginBox(grid2.domNode);
+							grid1.update(); // slow
+							grid2.update(); // slow
+							doh.robot.sequence(d.getTestCallback(function(){
+								// sizes after update
+								var boxAfter1 = dojo.marginBox(grid1.domNode);
+								var boxAfter2 = dojo.marginBox(grid2.domNode);
+								doh.is(boxBefore1.w,boxAfter1.w,"width of visible grid should not have changed after update()");
+								doh.is(boxBefore1.h,boxBefore1.h,"height of visible grid should not have changed after update()");
+								doh.is(boxBefore2.w,boxAfter2.w,"width of hidden grid should not have changed after update()");
+								doh.is(boxBefore2.h,boxAfter2.h,"height of hidden grid should not have changed after update()");
+							}),5000);
+						},500);
+						return d;
+					}
+				},
+				{
+					name: "column resizing",
+					timeout:20000,
+					grid: null,
+					setUp: function(){
+						this.grid = dijit.byId('markup_grid_1');
+						this.grid.sortInfo=0;
+					},
+					runTest: function(){
+						var d = new doh.Deferred();
+						var grid=this.grid;
+						doh.robot.mouseMoveAt('mainTabContainer_tablist_dijit_layout_ContentPane_0',500);
+						doh.robot.mouseClick({left:true},500);
+						doh.robot.sequence(function(){
+							grid.domNode.scrollTop = 0;
+							// try to size column headers
+							// Id width changes
+							var columns = dojo.query('div.dojoxGridSortNode',grid.domNode).map(function(e){
+								return e.parentNode;
+							});;
+							var box = dojo.position(columns[0].firstChild);
+							doh.robot.mouseMoveAt(columns[1],500,100,0,box.h/2);
+							doh.robot.mousePress({left:true},500);
+							doh.robot.mouseMoveAt(columns[1],500,100,-box.w/2,0);
+							doh.robot.mouseRelease({left:true},500); // this takes a long time
+							doh.robot.sequence(function(){
+								try{
+									columns = dojo.query('div.dojoxGridSortNode',grid.domNode);
+									var box2 = dojo.position(columns[0]);
+									doh.t(Math.abs(box.w/2-box2.w)<1, "ID column width did not shrink as expected.");
+									// Message (col4) should be unsizeable
+									box = dojo.position(columns[5]);
+									doh.robot.mouseMoveAt(columns[6],500,100,0,box.h/2);
+									doh.robot.mousePress({left:true},500);
+									doh.robot.mouseMoveAt(columns[6],500,100,-box.w/2,box.h/2);
+									doh.robot.mouseRelease({left:true},500);  // this takes a long time
+									doh.robot.sequence(d.getTestCallback(function(){
+										columns = dojo.query('div.dojoxGridSortNode',grid.domNode);
+										box2 = dojo.position(columns[5]);
+										doh.is(box.w, box2.w, "Message column width should not have changed.");
+										doh.is(0,grid.sortInfo,"Attempting to resize a non-resizable column should not set the sort order.");
+									}),5000);
+								}catch(e){
+									d.callback(e);
+								}
+							},5000);
+						},500);
+						return d;
+					},
+					tearDown: function(){
+						this.grid = null;
+					}
+				},
+				{
+					name: "edit columns",
+					timeout:60000,
+					grid: null,
+					setUp:function(){
+						this.grid = dijit.byId('markup_grid_1');
+					},
+					runTest: function(){
+						// see also "edit reordered columns" test below
+						var d = new doh.Deferred();
+						var grid=this.grid;
+						doh.robot.mouseMoveAt('mainTabContainer_tablist_dijit_layout_ContentPane_0',500);
+						doh.robot.mouseClick({left:true},500);
+						// precondition: cells still arranged to id date priority mark status message amount amount
+						var editorids=[null,'dijit_form_DateTextBox_0','dijit_form_ComboBox_0','dijit_form_CheckBox_0',null,'dijit_Editor_0','dijit_form_CurrencyTextBox_0','dijit_form_HorizontalSlider_0'];
+						function nextTest(i){
+							if(i==editorids.length){
+								d.callback(true);
+								return;
+							}
+							if(!editorids[i]){
+								nextTest(i+1);
+								return;
+							}
+							doh.robot.sequence(function(){
+								var cells=dojo.query("td.dojoxGridCell",grid.views.views[1].scrollboxNode);
+								doh.robot.mouseMoveAt(cells[i],500);
+								doh.robot.mouseClick({left:true},500);
+								doh.robot.mouseClick({left:true},1);
+								doh.robot.sequence(function(){
+									try{
+										// this better have opened the expected editor or something very bad happened
+										doh.isNot(undefined,dijit.byId(editorids[i]),"Editing the "+i+" field of the 1st row did not open the expected editor.");
+										doh.t(dijit.byId(editorids[i])._focused);
+										grid.edit.cancel();
+										nextTest(i+1);
+									}catch(e){
+										d.callback(e);
+									}
+								},2000);
+							},500);
+						}
+						nextTest(0);
+						return d;
+					},
+					tearDown:function(){
+						// done editing
+						
+						this.grid.edit.cancel();
+						this.grid = null;
+					}
+				},
+				{
+					name: "column reordering",
+					timeout:10000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						// FIXME: choose one of the other grids with filler text on the top so IE scrollIntoView doesn't freak out
+						var grid=dijit.byId('markup_grid_1');
+						doh.robot.mouseMoveAt('mainTabContainer_tablist_dijit_layout_ContentPane_0',500);
+						doh.robot.mouseClick({left:true},500);
+						// try to reorder column headers:
+						//		Id (fixed width)
+						//		Message (auto width)
+						doh.robot.sequence(function(){
+							grid.domNode.scrollTop = 0;
+							var columns = dojo.query('div.dojoxGridSortNode',grid.domNode);
+							var id=columns[0];
+							var priority=columns[2];
+							var expectedtext=[id.innerHTML,priority.innerHTML];
+							doh.robot.mouseMoveAt(id,500);
+							doh.robot.mousePress({left:true},500);
+							// position id left of priority
+							doh.robot.mouseMoveAt(priority,500,1000,0,0);
+							doh.robot.mouseRelease({left:true},500);
+							doh.robot.sequence(function(){
+								try{
+									var newColumns = dojo.query('div.dojoxGridSortNode',grid.domNode);
+									var newId = newColumns[1];
+									var newPriority = newColumns[2];
+									// the original nodes get orphaned so direct comparison is impossible
+									doh.is(expectedtext[0],newId.innerHTML,"2nd column should have been Id after dnd");
+									doh.is(expectedtext[1],newPriority.innerHTML,"3rd column should have been Priority after dnd");
+									// position message left of status
+									columns = newColumns;
+									var status=columns[4];
+									var message=columns[5];
+									expectedtext=[message.innerHTML,status.innerHTML,];
+									doh.robot.mouseMoveAt(message,500);
+									doh.robot.mousePress({left:true},500);
+									doh.robot.mouseMoveAt(status,500,1000,0,0);
+									doh.robot.mouseRelease({left:true},500);
+									doh.robot.sequence(d.getTestCallback(function(){
+										newColumns = dojo.query('div.dojoxGridSortNode',grid.domNode);
+										var newMessage = newColumns[4];
+										var newStatus = newColumns[5];
+										doh.is(expectedtext[0],newMessage.innerHTML,"5th column should have been Message after dnd");
+										doh.is(expectedtext[1],newStatus.innerHTML,"6th column should have been Status after dnd");
+									}),500);
+								}catch(e){
+									d.callback(e);
+								}
+							},500);
+						},500);
+						// also, should not be able to drag columns to other dojo.dnd targets
+						return d;
+					}
+				},
+				{
+					name: "edit reordered columns",
+					timeout:60000,
+					grid: null,
+					setUp:function(){
+						this.grid = dijit.byId('markup_grid_1');
+					},
+					runTest: function(){
+						// same test as the previous edit test, but on next row (since cell editors persist)
+						// assumes previous dnd test rearranged the cells successfully
+						var d = new doh.Deferred();
+						var grid=this.grid;
+						doh.robot.mouseMoveAt('mainTabContainer_tablist_dijit_layout_ContentPane_0',500);
+						doh.robot.mouseClick({left:true},500);
+						// precondition: cells rearranged to date id priority mark message status amount amount
+						var editorids=['dijit_form_DateTextBox_1',null,'dijit_form_ComboBox_1','dijit_form_CheckBox_1','dijit_Editor_1',null,'dijit_form_CurrencyTextBox_1','dijit_form_HorizontalSlider_1'];
+						function nextTest(i){
+							if(i==(editorids.length*2)){
+								d.callback(true);
+								return;
+							}
+							if(!editorids[i-editorids.length]){
+								nextTest(i+1);
+								return;
+							}
+							doh.robot.sequence(function(){
+								var cells=dojo.query("td.dojoxGridCell",grid.views.views[1].scrollboxNode);
+								doh.robot.mouseMoveAt(cells[i],500);
+								doh.robot.mouseClick({left:true},500);
+								doh.robot.mouseClick({left:true},1);
+								doh.robot.sequence(function(){
+									try{
+										// this better have opened the expected editor or something very bad happened
+										doh.isNot(undefined,dijit.byId(editorids[i]),"Editing the "+(i-editorids.length)+" field of the 2nd row after column drag and drop did not open the expected editor.");
+										doh.t(dijit.byId(editorids[i])._focused);
+										grid.edit.cancel();
+										nextTest(i+1);
+									}catch(e){
+										d.callback(e);
+									}
+								},2000);
+							},500);
+						}
+						nextTest(editorids.length);
+						return d;
+					},
+					tearDown:function(){
+						// done editing
+						this.grid.edit.cancel();
+						this.grid = null;
+					}
+				},
+				{
+					name: "column 1px move should not reorder",
+					timeout:10000,
+					runTest: function(){
+						var d = new doh.Deferred();
+						var grid=dijit.byId('markup_grid_1');
+						doh.robot.mouseMoveAt('mainTabContainer_tablist_dijit_layout_ContentPane_0',500,1);
+						doh.robot.mouseClick({left:true},500);
+						doh.robot.sequence(function(){
+							grid.domNode.scrollTop = 0;
+							var columns = dojo.query('div.dojoxGridSortNode',grid.domNode);
+							var prevHTML = columns[1].innerHTML;
+							var priority = columns[2];
+							doh.robot.mouseMoveAt(priority,500,500,10,5);
+							doh.robot.mousePress({left:true},100);
+							// drag priority column 1px
+							doh.robot.mouseMoveAt(priority,500,1,9,5);
+							doh.robot.mouseRelease({left:true},100);
+							doh.robot.sequence(d.getTestCallback(function(){
+								var newColumns = dojo.query('div.dojoxGridSortNode',grid.domNode);
+								var newHTML = newColumns[1].innerHTML;
+								// the original nodes get orphaned so direct comparison is impossible
+								doh.is(prevHTML,newHTML,"1st column should still be id after nop dnd " + ' old = ['+prevHTML+'] new = [' + newHTML + ']');
+							}),2000);
+						},1);
+						// also, should not be able to drag columns to other dojo.dnd targets
+						return d;
+					}
+				}
+			]);
+			doh.run();
+		});
+	</script>
+</head>
+</html>
diff --git a/dojox/grid/tests/robot/_DataGrid.html b/dojox/grid/tests/robot/_DataGrid.html
new file mode 100755
index 0000000..7693229
--- /dev/null
+++ b/dojox/grid/tests/robot/_DataGrid.html
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>TabContainer Demo</title>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../../dijit/themes/tundra/tundra.css">
+
+	<style type="text/css">
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/tests/css/dijitTests.css";
+
+		@import "../../resources/Grid.css";
+		@import "../../resources/tundraGrid.css";
+	</style>
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../../../../dijit/tests/_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.SplitContainer");
+		dojo.require("dijit.Tooltip");
+		dojo.require("dijit.Menu");
+		dojo.require("dijit.layout.LinkPane");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.dnd.Source");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+		formatCurrency = function(inDatum){
+			return isNaN(inDatum) ? '...' : dojo.currency.format(inDatum, this.constraint);
+		}
+		formatDate = function(inDatum){
+			return dojo.date.locale.format(new Date(inDatum), this.constraint);
+		}
+	</script>
+	<script type="text/javascript" src="structures.js"></script>
+	<script type="text/javascript" src="stores.js"></script>
+</head>
+<body class="tundra">
+
+	<h1 dojoType="dojo.dnd.Target" class="testTitle">dojox.grid.DataGrid tests</h1>
+	<input id="initialfocus"></input>
+		<div dojoType="dijit.Menu" jsid="gridMenu" id="gridMenu" style="display: none;">
+				<div dojoType="dijit.MenuItem" >Item One</div>
+				<div dojoType="dijit.MenuItem" >Item Two</div>
+				<div dojoType="dijit.MenuItem" >Item Three</div>
+		</div>
+	<div id="mainTabContainer" dojoType="dijit.layout.TabContainer" tabStrip="true" style="width: 100%; height: 20em;">
+
+		<div dojoType="dijit.layout.ContentPane"  title="Markup 1">
+			<h1>Editable DataGrid, markup, pane shown on init, context menu on header</h1>
+			<div id="markup_grid_1" dojoType="dojox.grid.DataGrid" columnReordering="true" store="structure1_store1" query="{ id: '*' }" structure="structure1" rowSelector="20px" headerMenu="gridMenu" style="width: 100%;height:19em;"></div>
+		</div>
+
+		<div dojoType="dijit.layout.ContentPane" title="Markup 2">
+			<h1>Editable DataGrid, markup, pane hidden on init. This grid should be identical to the first tab.</h1>
+			<div id="markup_grid_2" dojoType="dojox.grid.DataGrid" columnReordering="true" store="structure1_store2" query="{ id: '*' }" structure="structure1" rowSelector="20px" headerMenu="gridMenu" style="width: 100%;height:19em;"></div>
+		</div>
+
+		<div dojoType="dijit.layout.ContentPane" title="Markup 3">
+			<h1>Some filler text</h1>
+			<h1>More filler text</h1>
+			<h1>Even more filler text</h1>
+			<h1>Editable DataGrid, markup, pane hidden on init. This grid should be identical to the first tab.</h1>
+			<div id="markup_grid_3" dojoType="dojox.grid.DataGrid" columnReordering="true" store="structure1_store3" query="{ id: '*' }" structure="structure1" rowSelector="20px" headerMenu="gridMenu" style="width: 100%;height:19em;"></div>
+		</div>
+		<div dojoType="dijit.layout.ContentPane"  title="Markup structure"><table id="markup_grid_markup_structure" dojoType="dojox.grid.DataGrid" columnReordering="true" store="structure1_store4" query="{ id: '*' }" rowSelector="20px" headerMenu="gridMenu" style="width: 100%;">
+			<h1>Editable DataGrid, markup structure, pane hidden on init. This grid should be identical to the first tab.</h1>
+			<thead>
+					<tr>
+						<th field="id" width="8em" styles='text-align: right;'>Id</th>
+						<th cellType="dojox.grid.cells.DateTextBox" field="col8" formatter="formatDate" constraint="{formatLength: 'long', selector: 'date'}" editable="true" width="10em" styles='text-align: right;'>Date</th>
+						<th cellType="dojox.grid.cells.ComboBox" field="col1" options="normal,note,important" editable="true" width="10em" styles='text-align: center;'>Priority</th>
+						<th cellType="dojox.grid.cells.CheckBox" field="col2" editable="true" width="3em" styles='text-align: center;'>Mark</th>
+						<th cellType="dojox.grid.cells.Select" field="col3" options="new,read,replied" editable="true" width="8em" styles='text-align: center;'>Status</th>
+						<th cellType="dojox.grid.cells.Editor" field="col4" editorToolbar="true" editable="true" width="auto" styles=''>Message</th>
+						<th cellType="dojox.grid.cells._Widget" widgetClass="dijit.form.CurrencyTextBox" field="col5" formatter="formatCurrency" constraint="{currency:'EUR'}" editable="true" width="8em" styles='text-align: right;'>Amount</th>
+						<th cellType="dojox.grid.cells._Widget" widgetClass="dijit.form.HorizontalSlider" field="col6" formatter="formatCurrency" constraint="{currency:'EUR'}" editable="true" width="10em" styles='text-align: right;'>Amount</th>
+					</tr>
+				</thead>
+			</table>
+		</div>
+	</div>
+	<h1>Space for creating grids (grid should appear as part of the robot test)</h1>
+	<div id="prog_grid_1" rowSelector="20px" style="width: 100%;height:100px;"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/robot/module.js b/dojox/grid/tests/robot/module.js
new file mode 100755
index 0000000..6ce1492
--- /dev/null
+++ b/dojox/grid/tests/robot/module.js
@@ -0,0 +1,20 @@
+dojo.provide("dojox.grid.tests.robot.module");
+
+try{
+	var userArgs = window.location.search.replace(/[\?&](dojoUrl|testUrl|testModule)=[^&]*/g,"").replace(/^&/,"?");
+
+	// Safari 3 doesn't support focus on nodes like <div>, so keyboard isn't supported there...
+	// Safari 4 almost works, but has problems with shift-tab (#8987) and ESC (#9506).
+	// Enable tests when those bugs are fixed.
+	var test_a11y = dojo.isFF || dojo.isIE;
+	
+	var test_robot = true;
+
+	doh.registerUrl("dojox.grid.tests.robot.DataGrid_mouse", dojo.moduleUrl("dojox.grid", "tests/robot/DataGrid_mouse.html"), 99999999);
+	doh.registerUrl("dojox.grid.tests.robot.DataGrid_a11y", dojo.moduleUrl("dojox.grid", "tests/robot/DataGrid_a11y.html"), 99999999);
+	doh.registerUrl("dojox.grid.tests.robot.7815", dojo.moduleUrl("dojox.grid", "tests/robot/7815.html"), 99999999);
+}catch(e){
+	doh.debug(e);
+}
+
+
diff --git a/dojox/grid/tests/robot/runTests.html b/dojox/grid/tests/robot/runTests.html
new file mode 100755
index 0000000..1cbc747
--- /dev/null
+++ b/dojox/grid/tests/robot/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+	<head>
+	<title>Dojox Grid Unit Test Runner</title>
+	<meta http-equiv="REFRESH" content="0;url=../../../../util/doh/runner.html?testModule=dojox.grid.tests.robot.module"></HEAD>
+	<BODY>
+		Redirecting to D.O.H runner.
+	</BODY>
+</HTML> 
diff --git a/dojox/grid/tests/robot/stores.js b/dojox/grid/tests/robot/stores.js
new file mode 100755
index 0000000..4451ff9
--- /dev/null
+++ b/dojox/grid/tests/robot/stores.js
@@ -0,0 +1,49 @@
+(function(){
+dojo.require("dojo.data.ItemFileWriteStore");
+structure1_store1_data = [];
+structure1_store2_data = [];
+structure1_store3_data = [];
+structure1_store4_data = [];
+for(var i=0; i<100; i++){
+	var item = {
+		id: i,
+		col1: 'normal',
+		col2: false,
+		col3: 'new',
+		col4: 'Now is the time for all good men to come to the aid of their party.',
+		col5: 99.99,
+		col6: 9.99,
+		col7: false,
+		col8: new Date()
+	};
+	structure1_store1_data.push(dojo.mixin({},item));
+	structure1_store2_data.push(dojo.mixin({},item));
+	structure1_store3_data.push(dojo.mixin({},item));
+	structure1_store4_data.push(dojo.mixin({},item));
+}
+//TODO: populate data
+structure1_store1 = new dojo.data.ItemFileWriteStore({
+	data:{
+		identifier:"id",
+		items:structure1_store1_data
+	}
+});
+structure1_store2 = new dojo.data.ItemFileWriteStore({
+	data:{
+		identifier:"id",
+		items:structure1_store2_data
+	}
+});
+structure1_store3 = new dojo.data.ItemFileWriteStore({
+	data:{
+		identifier:"id",
+		items:structure1_store3_data
+	}
+});
+structure1_store4 = new dojo.data.ItemFileWriteStore({
+	data:{
+		identifier:"id",
+		items:structure1_store4_data
+	}
+});
+})();
\ No newline at end of file
diff --git a/dojox/grid/tests/robot/structures.js b/dojox/grid/tests/robot/structures.js
new file mode 100755
index 0000000..6bb27ab
--- /dev/null
+++ b/dojox/grid/tests/robot/structures.js
@@ -0,0 +1,40 @@
+(function(){
+dojo.require("dojo.date.locale");
+dojo.require("dojo.currency");
+dojo.require("dijit.form.HorizontalSlider");
+dojo.require("dijit.form.CurrencyTextBox");
+dojo.require("dojox.grid.cells.dijit");
+formatCurrency = function(inDatum){
+	return isNaN(inDatum) ? '...' : dojo.currency.format(inDatum, this.constraint);
+}
+formatDate = function(inDatum){
+	return dojo.date.locale.format(new Date(inDatum), this.constraint);
+}
+structure1 = [{
+	defaultCell: { width: 8, editable: true, type: dojox.grid.cells._Widget, styles: 'text-align: right;'  },
+	rows: [
+		{ name: 'Id', field: 'id', editable: false /* Can't edit ID's of dojo.data items */ },
+		{ name: 'Date', field: 'col8', width: 10,
+			type: dojox.grid.cells.DateTextBox,
+			formatter: formatDate, 
+			constraint: {formatLength: 'long', selector: "date"}},
+		{ name: 'Priority', styles: 'text-align: center;', field: 'col1', 
+			type: dojox.grid.cells.ComboBox, 
+			options: ["normal", "note", "important"], width: 10},
+		{ name: 'Mark', field: 'col2', width: 3, styles: 'text-align: center;', 
+			type: dojox.grid.cells.CheckBox},
+		{
+			field: 'col3', name: 'Status', 
+			styles: 'text-align: center;', 
+			type: dojox.grid.cells.Select, 
+			options: [ "new", "read", "replied" ]
+		},
+		{ name: 'Message', field: 'col4', styles: '', width: 'auto', 
+			type: dojox.grid.cells.Editor, editorToolbar: true },
+		{ name: 'Amount', field: 'col5', formatter: formatCurrency, constraint: {currency: 'EUR'}, 
+			widgetClass: dijit.form.CurrencyTextBox },
+		{ name: 'Amount', field: 'col6', formatter: formatCurrency, constraint: {currency: 'EUR'}, 
+			widgetClass: dijit.form.HorizontalSlider, width: 10}
+	]
+}];
+})();
\ No newline at end of file
diff --git a/dojox/grid/tests/support/books.xml b/dojox/grid/tests/support/books.xml
new file mode 100644
index 0000000..4c330e6
--- /dev/null
+++ b/dojox/grid/tests/support/books.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<books>
+	<book>
+		<isbn>1</isbn>
+		<title>Title of 1</title>
+		<author>Author of 1</author>
+	</book>
+	<book>
+		<isbn>2</isbn>
+		<title>Title of 2</title>
+		<author>Author of 2</author>
+	</book>
+	<book>
+		<isbn>3</isbn>
+		<title>Title of 3</title>
+		<author>Author of 3</author>
+	</book>
+	<book>
+		<isbn>4</isbn>
+		<title>Title of 4</title>
+		<author>Author of 4</author>
+	</book>
+	<book>
+		<isbn>5</isbn>
+		<title>Title of 5</title>
+		<author>Author of 5</author>
+	</book>
+	<book>
+		<isbn>6</isbn>
+		<title>Title of 6</title>
+		<author>Author of 6</author>
+	</book>
+	<book>
+		<isbn>7</isbn>
+		<title>Title of 7</title>
+		<author>Author of 7</author>
+	</book>
+	<book>
+		<isbn>8</isbn>
+		<title>Title of 8</title>
+		<author>Author of 8</author>
+	</book>
+	<book>
+		<isbn>9</isbn>
+		<title>Title of 9</title>
+		<author>Author of 9</author>
+	</book>
+	<book>
+		<isbn>10</isbn>
+		<title>Title of 10</title>
+		<author>Author of 10</author>
+	</book>
+	<book>
+		<isbn>11</isbn>
+		<title>Title of 11</title>
+		<author>Author of 11</author>
+	</book>
+	<book>
+		<isbn>12</isbn>
+		<title>Title of 12</title>
+		<author>Author of 12</author>
+	</book>
+	<book>
+		<isbn>13</isbn>
+		<title>Title of 13</title>
+		<author>Author of 13</author>
+	</book>
+	<book>
+		<isbn>14</isbn>
+		<title>Title of 14</title>
+		<author>Author of 14</author>
+	</book>
+	<book>
+		<isbn>15</isbn>
+		<title>Title of 15</title>
+		<author>Author of 15</author>
+	</book>
+	<book>
+		<isbn>16</isbn>
+		<title>Title of 16</title>
+		<author>Author of 16</author>
+	</book>
+	<book>
+		<isbn>17</isbn>
+		<title>Title of 17</title>
+		<author>Author of 17</author>
+	</book>
+	<book>
+		<isbn>18</isbn>
+		<title>Title of 18</title>
+		<author>Author of 18</author>
+	</book>
+	<book>
+		<isbn>19</isbn>
+		<title>Title of 19</title>
+		<author>Author of 19</author>
+	</book>
+	<book>
+		<isbn>20</isbn>
+		<title>Title of 20</title>
+		<author>Author of 20</author>
+	</book>
+</books>
diff --git a/dojox/grid/tests/support/countryStore.json b/dojox/grid/tests/support/countryStore.json
new file mode 100644
index 0000000..d0cd635
--- /dev/null
+++ b/dojox/grid/tests/support/countryStore.json
@@ -0,0 +1,45 @@
+{ identifier: 'name',
+  label: 'name',
+  items: [
+	{ name:'Africa', type:'continent', children:[
+		{ name:'Egypt', type:'country' }, 
+		{ name:'Kenya', type:'country', children:[
+			{ name:'Nairobi', type:'city', adults: 70400, popnum: 2940911 },
+			{ name:'Mombasa', type:'city', adults: 294091, popnum: 707400 } ]
+		},
+		{ name:'Sudan', type:'country', children:
+			{ name:'Khartoum', type:'city', adults: 480293, popnum: 1200394 } 
+		} ]
+	},
+	{ name:'Asia', type:'continent', children:[
+		{ name:'China', type:'country' },
+		{ name:'India', type:'country' },
+		{ name:'Russia', type:'country' },
+		{ name:'Mongolia', type:'country' } ]
+	},
+	{ name:'Australia', type:'continent', population:'21 million', children:
+		{ name:'Commonwealth of Australia', type:'country', population:'21 million'}
+	},
+	{ name:'Europe', type:'continent', children:[
+		{ name:'Germany', type:'country' },
+		{ name:'France', type:'country' },
+		{ name:'Spain', type:'country' },
+		{ name:'Italy', type:'country' } ]
+	},
+	{ name:'North America', type:'continent', children:[
+		{ name:'Mexico', type:'country',  population:'108 million', area:'1,972,550 sq km', children:[
+			{ name:'Mexico City', type:'city', adults: 120394, popnum: 19394839, population:'19 million', timezone:'-6 UTC'},
+			{ name:'Guadalajara', type:'city', adults: 1934839, popnum: 4830293, population:'4 million', timezone:'-6 UTC' } ]
+		},
+		{ name:'Canada', type:'country',  population:'33 million', area:'9,984,670 sq km', children:[
+			{ name:'Ottawa', type:'city', adults: 230493, popnum: 9382019, population:'0.9 million', timezone:'-5 UTC'},
+			{ name:'Toronto', type:'city', adults: 932019, popnum: 2530493, population:'2.5 million', timezone:'-5 UTC' }]
+		},
+		{ name:'United States of America', type:'country' } ]
+	},
+	{ name:'South America', type:'continent', children:[
+		{ name:'Brazil', type:'country', population:'186 million' },
+		{ name:'Argentina', type:'country', population:'40 million' } ]
+	} ]
+}
+
diff --git a/dojox/grid/tests/support/data.php b/dojox/grid/tests/support/data.php
new file mode 100644
index 0000000..1beb6f0
--- /dev/null
+++ b/dojox/grid/tests/support/data.php
@@ -0,0 +1,379 @@
+<?php
+	// db settings
+	$dbserver = 'localhost';
+	$dbuser = 'root';
+	$dbpassword = 'root';
+	
+	error_reporting(E_ALL);
+	
+	/*
+		Simple protocol:
+			- Inputs via POST variables. 
+			- Output is a string that can be evaluated into a JSON
+			  First element of the array contains return status.
+				
+		This simplified tutorial code should not be deployed without a security review.
+	*/
+	
+	@include "json.php";
+	
+	// set up response encoding 
+	header("Content-Type: text/html; charset=utf-8");
+
+	// util
+	function getPostString($inName) {
+		// make sure input strings are 'clean'
+		return mysql_real_escape_string(@$_POST[$inName]);
+	}
+		
+	// used for json encoding
+	$json = new Services_JSON();
+	
+	function echoJson($inData) {
+		global $json;
+		// delay in ms
+		$delay = getPostString('delay');
+		if (!empty($delay))
+			usleep($delay * 1000);
+		echo '/* ' . $json->encode($inData) . ' */';
+	}
+	
+	function error($inMessage) {
+		$inMessage = str_replace('"', '\\"', $inMessage);
+		error_log($inMessage);
+		//echo '/* ({error: true, message: "' . $inMessage . '"}) */';
+		echoJson(array('error' => true, 'message' => $inMessage));
+		exit;
+	}
+
+
+	function getArray($inResult, $inArray="true") {
+		$o = Array();
+		while ($row = ($inArray ? mysql_fetch_row($inResult) : mysql_fetch_object($inResult)))
+			$o[] = $row;
+		return $o;	
+	}
+	
+	// connect to DB
+	mysql_connect($dbserver, $dbuser, $dbpassword);
+
+	// select DB
+	$database = getPostString("database");
+	$database = ($database ? $database : $db);
+	if (!mysql_select_db($database))
+		error('failed to select db: ' . mysql_error());
+
+	// select table
+	$table = getPostString("table");
+	$table = ($table ? $table : $dbtable);
+
+	// cache
+	$colCache = NULL;
+	$pkCache = NULL;
+
+	// set UTF8 output (MySql > 4.0)
+	mysql_query("SET NAMES UTF8");
+	
+	// server, database, table meta data
+	function getDatabases() {
+		$result = mysql_query("SHOW DATABASES");
+		$output = Array();
+		while ($row = mysql_fetch_row($result)) {
+			$r = strtolower($row[0]);
+			if ($r != 'mysql' && $r != 'information_schema')
+				$output[] = $row[0];
+		}	
+		return $output;	
+	}
+	
+	function getTables() {
+		global $database;
+		$result = mysql_query("SHOW TABLES FROM $database");
+		$output = Array();
+		while ($row = mysql_fetch_row($result))
+			$output[] = $row[0];
+		return $output;	
+	}
+	
+	function getColumns() {
+		global $table, $colCache;
+		if (!$colCache) {
+			$result = mysql_query("SHOW COLUMNS FROM `$table`");
+			return getArray($result, false);
+			$colCache = getArray($result, false);
+		}
+		return $colCache;	
+	}
+	
+	// returns object: $this->name, $this->index
+	function getPk() {
+		global $pkCache;
+		if (!$pkCache) {
+			$k = '';
+			$columns = getColumns();
+			for ($i=0; $i < count($columns); $i++) {
+				$c = $columns[$i];
+				if ($c->Key == 'PRI') {
+					$k = $c->Field;
+					break;
+				}	
+			}
+			$pkCache->index = $i;
+			$pkCache->name = $k;
+		}	
+		return $pkCache;
+	}
+	
+	function getTableInfo() {
+		global $table, $database;
+		$c = getColumns();
+		$r = rowcount();
+		return array("count" => $r, "columns" => $c, "database" => $database, "table" => $table);
+	}
+	
+	function getOldPostPkValue() {
+		$pk = getPk();
+		return getPostString('_o' . $pk->index);
+	}
+	
+	function getNewPostPkValue() {
+		$pk = getPk();
+		return getPostString('_' . $pk->index);
+	}
+	
+	function getPostColumns() {
+		$columns = getColumns();
+		for ($i=0, $a=array(), $p; (($p=getPostString("_".$i)) != ''); $i++) {
+			$r = new stdClass();
+			$r->name = $columns[$i]->Field;
+			$r->value = $p;
+			$a[] = $r;
+		}	
+		return $a;
+	}
+	
+	function getOrderBy() {
+		$ob = getPostString("orderby");
+		if (is_numeric($ob)) {
+			$columns = getColumns();
+			$ob = $columns[intval($ob)-1]->Field;
+		}
+		return $ob;
+	}
+	
+	function getWhere() {
+		$w = getPostString("where");
+		return ($w ? " WHERE $w" : "");
+	}
+	
+	// basic operations
+	function rowcount()	{
+		global $table;
+		$query = "SELECT COUNT(*) FROM `$table`" . getWhere();
+		$result = mysql_query($query);
+		if (!$result)
+			error("failed to perform query: $query. " . mysql_error());
+		if ($row = mysql_fetch_row($result))
+			return $row[0];
+		else
+			return 0;
+	}
+	
+	function select($inQuery = '') {
+		global $table;
+		// built limit clause
+		$lim = (int)getPostString("limit");
+		$off = (int)getPostString("offset");
+		$limit = ($lim || $off ? " LIMIT $off, $lim" : "");
+		// build order by clause
+		$desc = (boolean)getPostString("desc");
+		$ob = getOrderBy();
+		$orderby = ($ob ? " ORDER BY `" . $ob . "`" . ($desc ? " DESC" : "") : "");
+		// build query
+		$query = ($inQuery ? $inQuery : "SELECT * FROM `$table`" . getWhere() . $orderby . $limit);
+		// execute query
+		if (!$result = mysql_query($query))
+			error("failed to perform query: $query. " . mysql_error());
+		// fetch each result row 
+		return getArray($result);
+	}
+
+	function reflectRow() {
+		global $table;
+		$pk = getPk();
+		$key = getNewPostPkValue();			
+		$where = "`$pk->name`=\"$key\"";
+		return select("SELECT * FROM `$table` WHERE $where LIMIT 1");
+	}
+	
+	function update() {
+		// build set clause
+		for ($i=0, $set = array(), $cols = getPostColumns(), $v; ($v=$cols[$i]); $i++)
+			$set[] = "`$v->name` = '$v->value'";
+		$set = implode(', ', $set);
+		// our table
+		global $table;
+		// build query
+		$pk = getPk();
+		$pkValue = getOldPostPkValue();
+		$query = "UPDATE `$table` SET $set WHERE `$pk->name` = '$pkValue' LIMIT 1";
+		// execute query
+		if (!mysql_query($query))
+			error("failed to perform query: [$query]. " .
+					"MySql says: [" . mysql_error() ."]");
+		else {
+			return reflectRow();
+		}	
+	}
+	
+	function insert() {
+		global $table;
+		// build values clause
+		for ($i=0, $values = array(), $cols = getPostColumns(), $v; ($v=$cols[$i]); $i++)
+			$values[] = $v->value;
+		$values = '"' . implode('", "', $values) . '"';			
+		// build query
+		$query = "INSERT INTO `$table` VALUES($values)";
+		// execute query
+		if (!mysql_query($query))
+			error("failed to perform query: [$query]. " .
+					"MySql says: [" . mysql_error() ."]");
+		else {
+			return reflectRow();
+		}
+	}
+	
+	function delete() {
+		global $table;
+		// build query
+		$n = getPostString("count");
+		$pk = getPk();
+		for ($i = 0, $deleted=array(); $i < $n; $i++) {
+			$key = getPostString("_$i");
+			array_push($deleted, $key);
+			$query = "DELETE FROM `$table` WHERE `$pk->name`=\"$key\" LIMIT 1";
+			// execute query
+			if (!mysql_query($query) || mysql_affected_rows() != 1)
+				error("failed to perform query: [$query]. " .
+					"Affected rows: " . mysql_affected_rows() .". " . 
+					"MySql says: [" . mysql_error() ."]");
+		}	
+		return $deleted;			
+	}
+	
+	// find (full text search)
+	function findData($inFindCol, $inFind, $inOrderBy, $inFullText) {
+		global $table;
+		$where = ($inFullText ? "WHERE MATCH(`$inFindCol`) AGAINST ('$inFind')" : "WHERE $inFindCol LIKE '$inFind'");
+		$query = "SELECT * FROM $table $where $inOrderBy";
+		$result = mysql_query($query);
+		// return rows
+		return getArray($result);
+	}
+	
+	// binary search through sorted data, supports start point ($inFindFrom) and direction ($inFindForward)
+	function findRow($inData, $inFindFrom=-1, $inFindForward) {
+		$b = -1;
+		$l = count($inData);
+		if (!$inData)
+			return $b;
+		if (!$inFindFrom==-1 || $l < 2)
+			$b = 0;
+		else {
+			// binary search
+			$t = $l-1;
+			$b = 0;
+			while ($b <= $t) {
+				$p = floor(($b+$t)/2);
+				$d = $inData[$p][0];
+				if ($d < $inFindFrom)
+					$b = $p + 1;
+				else if ($d > $inFindFrom)
+					$t = $p - 1;
+				else {
+					$b = $p;
+					break;
+				}	
+			}	
+			if ($inFindFrom == $inData[$b][0]) {
+				// add or subtract 1
+				$b = ($inFindForward ? ($b+1 > $l-1 ? 0 : $b+1) : ($b-1 < 0 ? $l-1 : $b-1) );
+			}	
+			else if (!$inFindForward)
+				// subtract 1
+				$b = ($b-1 < 0 ? $l-1 : $b-1);
+		}	
+		return $inData[$b][0];
+	}
+	
+	function buildFindWhere($inFindData, $inKey, $inCol) {
+		$o = Array();
+		foreach($inFindData as $row)
+			$o[] = $inCol . "='" . $row[$inKey] . "'";
+		return (count($o) ? ' WHERE ' . implode(' OR ', $o) : '');
+	}
+		
+	function find($inFindCol, $inFind='', $inOb='', $inFindFrom=0, $inFindForward=true, $inFullText=true) {
+		global $table;
+		// build order by clause
+		$desc = (boolean)getPostString("desc");
+		if (!$inOb)
+			$inOb = getOrderBy();
+		if ($inOb)
+			$inOb = "`" . $inOb . "`"	;
+		$orderby = ($inOb ? " ORDER BY $inOb " . ($desc ? " DESC" : "") : "");
+		// update inputs from post
+		if (!$inFind)
+			$inFind = getPostString('findText');
+		if (!$inFindCol)
+			$inFindCol = getPostString('findCol');	
+		if (empty($inFindFrom))
+			$inFindFrom = getPostString('findFrom');
+		$ff = getPostString('findForward');
+		if ($ff)
+			$inFindForward = (strtolower($ff) == 'true' ? true : false);
+		$ft = getPostString('findFullText');
+		if ($ft)
+			$inFullText = (strtolower($ft) == 'true' ? true : false);	
+		
+		// get find data
+		$f = findData($inFindCol, $inFind, $orderby,  $inFullText);
+		$pk = getPk();
+
+		// execute query
+		$where = buildFindWhere($f, $pk->index, 'f');
+		$query = "SELECT Row, f FROM (SELECT @row := @row + 1 AS Row, $pk->name as f FROM `$table` $orderby) AS tempTable $where";
+		mysql_query('SET @row = -1;');
+		if (!$result = mysql_query($query))
+			error("failed to perform query: $query. " . mysql_error());
+		
+		// return row number 
+		return findRow(getArray($result), $inFindFrom, $inFindForward);
+	}
+	
+	// our command list
+	$cmds = array( 
+		"count" => "rowcount", 
+		"select" => "select",
+		"update" => "update",
+		"insert" => "insert",
+		"delete" => "delete",
+		"find" => "find",
+		"databases" => "getDatabases",
+		"tables" => "getTables",
+		"columns" => "getColumns",
+		"info" => "getTableInfo"
+	);
+		
+	// process input params
+	$cmd = @$_POST["command"];
+	
+	//$cmd="select";
+	
+	// dispatch command
+	$func = @$cmds[$cmd];
+	if (function_exists($func)) 
+		echoJson(call_user_func($func));
+	else
+		error("bad command");
+?>
diff --git a/dojox/grid/tests/support/gamedata.json b/dojox/grid/tests/support/gamedata.json
new file mode 100644
index 0000000..c932b8d
--- /dev/null
+++ b/dojox/grid/tests/support/gamedata.json
@@ -0,0 +1,520 @@
+{ identifier: "id",
+  label: "label",
+  items: [
+    { 
+      id: "1",
+      label: "Player 1",
+      numSeasns: 1,
+      numGames: 1,
+      numQtrs: 1,
+      totPts: 15,
+      totReb: 8,
+      totAst: 12,
+      totTP: 9,
+      seasns: [
+        {
+          id: "2",
+          label: "Season 1",
+          numGames: 2,
+          numQtrs: 1,
+          totPts: 15,
+          totReb: 8,
+          totAst: 12,
+          totTP: 9,
+          games: [
+            {
+              id: "3",
+              label: "Game 1",
+              numQtrs: 1,
+              totPts: 15,
+              totReb: 8,
+              totAst: 12,
+              totTP: 9,
+              qtrs: [
+                {
+                  id: "4",
+                  label: "Quarter 1",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                }
+              ]
+            },
+            {
+              id: "5",
+              label: "Game 2",
+              numQtrs: 0,
+              totPts: 0,
+              totReb: 0,
+              totAst: 0,
+              totTP: 0,
+              qtrs: []
+            }
+          ]
+        }
+      ]
+    },
+	{ 
+      id: "6",
+      label: "Player 2",
+      seasns: [
+        {
+          id: "7",
+          label: "Season 1",
+		  numGames: 5,
+		  numQtrs: 20,
+		  totPts: 300,
+		  totReb: 160,
+		  totAst: 240,
+		  totTP: 180,
+          games: [
+            {
+              id: "8",
+              label: "Game 1",
+              qtrs: [
+                {
+                  id: "9",
+                  label: "Quarter 1",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "10",
+                  label: "Quarter 2",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "11",
+                  label: "Quarter 3",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "12",
+                  label: "Quarter 4",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                }
+              ],
+              numQtrs: 4,
+              totPts: 60,
+              totReb: 32,
+              totAst: 48,
+              totTP: 36
+            },
+			{
+              id: "13",
+              label: "Game 2",
+              qtrs: [
+                {
+                  id: "14",
+                  label: "Quarter 1",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "15",
+                  label: "Quarter 2",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "16",
+                  label: "Quarter 3",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "17",
+                  label: "Quarter 4",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                }
+              ],
+              numQtrs: 4,
+              totPts: 60,
+              totReb: 32,
+              totAst: 48,
+              totTP: 36
+            },
+			{
+              id: "18",
+              label: "Game 3",
+              qtrs: [
+                {
+                  id: "19",
+                  label: "Quarter 1",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "20",
+                  label: "Quarter 2",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "21",
+                  label: "Quarter 3",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "22",
+                  label: "Quarter 4",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                }
+              ],
+              numQtrs: 4,
+              totPts: 60,
+              totReb: 32,
+              totAst: 48,
+              totTP: 36
+            },
+			{
+              id: "23",
+              label: "Game 4",
+              qtrs: [
+                {
+                  id: "24",
+                  label: "Quarter 1",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "25",
+                  label: "Quarter 2",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "26",
+                  label: "Quarter 3",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "27",
+                  label: "Quarter 4",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                }
+              ],
+              numQtrs: 4,
+              totPts: 60,
+              totReb: 32,
+              totAst: 48,
+              totTP: 36
+            },
+			{
+              id: "28",
+              label: "Game 5",
+              qtrs: [
+                {
+                  id: "29",
+                  label: "Quarter 1",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "30",
+                  label: "Quarter 2",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "31",
+                  label: "Quarter 3",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "32",
+                  label: "Quarter 4",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                }
+              ],
+              numQtrs: 4,
+              totPts: 60,
+              totReb: 32,
+              totAst: 48,
+              totTP: 36
+            }
+          ]
+        },
+		{
+          id: "33",
+          label: "Season 2",
+		  numGames: 5,
+		  numQtrs: 20,
+		  totPts: 300,
+		  totReb: 160,
+		  totAst: 240,
+		  totTP: 180,
+          games: [
+            {
+              id: "34",
+              label: "Game 1",
+              qtrs: [
+                {
+                  id: "35",
+                  label: "Quarter 1",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "36",
+                  label: "Quarter 2",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "37",
+                  label: "Quarter 3",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "38",
+                  label: "Quarter 4",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                }
+              ],
+              numQtrs: 4,
+              totPts: 60,
+              totReb: 32,
+              totAst: 48,
+              totTP: 36
+            },
+			{
+              id: "39",
+              label: "Game 2",
+              qtrs: [
+                {
+                  id: "40",
+                  label: "Quarter 1",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "41",
+                  label: "Quarter 2",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "42",
+                  label: "Quarter 3",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "43",
+                  label: "Quarter 4",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                }
+              ],
+              numQtrs: 4,
+              totPts: 60,
+              totReb: 32,
+              totAst: 48,
+              totTP: 36
+            },
+			{
+              id: "44",
+              label: "Game 3",
+              qtrs: [
+                {
+                  id: "45",
+                  label: "Quarter 1",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "46",
+                  label: "Quarter 2",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "47",
+                  label: "Quarter 3",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "48",
+                  label: "Quarter 4",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                }
+              ],
+              numQtrs: 4,
+              totPts: 60,
+              totReb: 32,
+              totAst: 48,
+              totTP: 36
+            },
+			{
+              id: "49",
+              label: "Game 4",
+              qtrs: [
+                {
+                  id: "50",
+                  label: "Quarter 1",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "51",
+                  label: "Quarter 2",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "52",
+                  label: "Quarter 3",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "53",
+                  label: "Quarter 4",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                }
+              ],
+              numQtrs: 4,
+              totPts: 60,
+              totReb: 32,
+              totAst: 48,
+              totTP: 36
+            },
+			{
+              id: "54",
+              label: "Game 5",
+              qtrs: [
+                {
+                  id: "55",
+                  label: "Quarter 1",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "56",
+                  label: "Quarter 2",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "57",
+                  label: "Quarter 3",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                },
+				{
+                  id: "58",
+                  label: "Quarter 4",
+                  pts: 15,
+                  reb: 8,
+                  ast: 12,
+                  tp: 9
+                }
+              ],
+              numQtrs: 4,
+              totPts: 60,
+              totReb: 32,
+              totAst: 48,
+              totTP: 36
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/dojox/grid/tests/support/geography.xml b/dojox/grid/tests/support/geography.xml
new file mode 100644
index 0000000..070a8c1
--- /dev/null
+++ b/dojox/grid/tests/support/geography.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<opml version="1.0">
+	<head>
+		<title>geography.opml</title>
+		<dateCreated>2006-11-10</dateCreated>
+		<dateModified>2006-11-13</dateModified>
+		<ownerName>Magellan, Ferdinand</ownerName>
+	</head>
+	<body>
+		<outline text="Africa" type="continent">
+			<outline text="Egypt" type="country"/>
+			<outline text="Kenya" type="country">
+				<outline text="Nairobi" type="city"/>
+				<outline text="Mombasa" type="city"/>
+			</outline>
+			<outline text="Sudan" type="country">
+				<outline text="Khartoum" type="city"/>
+			</outline>
+		</outline>
+		<outline text="Asia" type="continent">
+			<outline text="China" type="country"/>
+			<outline text="India" type="country"/>
+			<outline text="Russia" type="country"/>
+			<outline text="Mongolia" type="country"/>
+		</outline>
+		<outline text="Australia" type="continent" population="21 million">
+			<outline text="Australia" type="country" population="21 million"/>
+		</outline>
+		<outline text="Europe" type="continent">
+			<outline text="Germany" type="country"/>
+			<outline text="France" type="country"/>
+			<outline text="Spain" type="country"/>
+			<outline text="Italy" type="country"/>
+		</outline>
+		<outline text="North America" type="continent">
+			<outline text="Mexico" type="country" population="108 million" area="1,972,550 sq km">
+				<outline text="Mexico City" type="city" population="19 million" timezone="-6 UTC"/>
+				<outline text="Guadalajara" type="city" population="4 million" timezone="-6 UTC"/>
+			</outline>
+			<outline text="Canada" type="country" population="33 million" area="9,984,670 sq km">
+				<outline text="Ottawa" type="city" population="0.9 million" timezone="-5 UTC"/>
+				<outline text="Toronto" type="city" population="2.5 million" timezone="-5 UTC"/>
+			</outline>
+			<outline text="United States of America" type="country"/>
+		</outline>
+		<outline text="South America" type="continent">
+			<outline text="Brazil" type="country" population="186 million"/>
+			<outline text="Argentina" type="country" population="40 million"/>
+		</outline>
+	</body>
+</opml>
diff --git a/dojox/grid/tests/support/json.php b/dojox/grid/tests/support/json.php
new file mode 100644
index 0000000..84e3dfa
--- /dev/null
+++ b/dojox/grid/tests/support/json.php
@@ -0,0 +1,794 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/** 
+* Converts to and from JSON format.
+* 
+* JSON (JavaScript Object Notation) is a lightweight data-interchange
+* format. It is easy for humans to read and write. It is easy for machines
+* to parse and generate. It is based on a subset of the JavaScript
+* Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+* This feature can also be found in  Python. JSON is a text format that is
+* completely language independent but uses conventions that are familiar
+* to programmers of the C-family of languages, including C, C++, C#, Java,
+* JavaScript, Perl, TCL, and many others. These properties make JSON an
+* ideal data-interchange language.
+* 
+* This package provides a simple encoder and decoder for JSON notation. It
+* is intended for use with client-side Javascript applications that make
+* use of HTTPRequest to perform server communication functions - data can
+* be encoded into JSON notation for use in a client-side javascript, or
+* decoded from incoming Javascript requests. JSON format is native to
+* Javascript, and can be directly eval()'ed with no further parsing
+* overhead
+*
+* All strings should be in ASCII or UTF-8 format!
+*
+* LICENSE: Redistribution and use in source and binary forms, with or
+* without modification, are permitted provided that the following
+* conditions are met: Redistributions of source code must retain the
+* above copyright notice, this list of conditions and the following
+* disclaimer. Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following disclaimer
+* in the documentation and/or other materials provided with the
+* distribution.
+* 
+* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+* NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+* DAMAGE.
+* 
+* @category   
+* @package     Services_JSON
+* @author      Michal Migurski <mike-json at teczno.com>
+* @author      Matt Knapp <mdknapp[at]gmail[dot]com>
+* @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+* @copyright   2005 Michal Migurski
+* @license     http://www.opensource.org/licenses/bsd-license.php
+* @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+*/
+
+/**
+* Marker constant for Services_JSON::decode(), used to flag stack state
+*/
+define('SERVICES_JSON_SLICE',   1);
+
+/**
+* Marker constant for Services_JSON::decode(), used to flag stack state
+*/
+define('SERVICES_JSON_IN_STR',  2);
+
+/**
+* Marker constant for Services_JSON::decode(), used to flag stack state
+*/
+define('SERVICES_JSON_IN_ARR',  4);
+
+/**
+* Marker constant for Services_JSON::decode(), used to flag stack state
+*/
+define('SERVICES_JSON_IN_OBJ',  8);
+
+/**
+* Marker constant for Services_JSON::decode(), used to flag stack state
+*/
+define('SERVICES_JSON_IN_CMT', 16);
+
+/**
+* Behavior switch for Services_JSON::decode()
+*/
+define('SERVICES_JSON_LOOSE_TYPE', 10);
+
+/**
+* Behavior switch for Services_JSON::decode()
+*/
+define('SERVICES_JSON_STRICT_TYPE', 11);
+
+/**
+* Encodings
+*/
+define('SERVICES_JSON_ISO_8859_1', 'iso-8859-1');
+define('SERVICES_JSON_UTF_8', 'utf-8');
+
+/** 
+* Converts to and from JSON format.
+*
+* Brief example of use:
+*
+* <code>
+* // create a new instance of Services_JSON
+* $json = new Services_JSON();
+* 
+* // convert a complexe value to JSON notation, and send it to the browser
+* $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
+* $output = $json->encode($value);
+*
+* print($output);
+* // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
+* 
+* // accept incoming POST data, assumed to be in JSON notation
+* $input = file_get_contents('php://input', 1000000);
+* $value = $json->decode($input);
+* </code>
+*/
+class Services_JSON
+{
+   /**
+    * constructs a new JSON instance
+    *
+		//>> SJM2005
+    * @param    string  $encoding 	Strings are input/output in this encoding
+    * @param    int    $encode 	Encode input is expected in this character encoding
+		//<< SJM2005
+		*
+    * @param    int     $use    object behavior: when encoding or decoding,
+    *                           be loose or strict about object/array usage
+    *
+    *                           possible values:
+    *                           - SERVICES_JSON_STRICT_TYPE: strict typing, default.
+    *                                                        "{...}" syntax creates objects in decode().
+    *                           - SERVICES_JSON_LOOSE_TYPE:  loose typing.
+    *                                                        "{...}" syntax creates associative arrays in decode().
+    */
+    function Services_JSON($encoding = SERVICES_JSON_UTF_8, $use = SERVICES_JSON_STRICT_TYPE)
+    {
+			//>> SJM2005
+			$this->encoding = $encoding;
+			//<< SJM2005
+			
+			$this->use = $use;
+    }
+
+   /**
+    * convert a string from one UTF-16 char to one UTF-8 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf16  UTF-16 character
+    * @return   string  UTF-8 character
+    * @access   private
+    */
+    function utf162utf8($utf16)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding'))
+            return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
+        
+        $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
+
+        switch(true) {
+            case ((0x7F & $bytes) == $bytes):
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x7F & $bytes);
+
+            case (0x07FF & $bytes) == $bytes:
+                // return a 2-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xC0 | (($bytes >> 6) & 0x1F))
+                     . chr(0x80 | ($bytes & 0x3F));
+
+            case (0xFFFF & $bytes) == $bytes:
+                // return a 3-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xE0 | (($bytes >> 12) & 0x0F))
+                     . chr(0x80 | (($bytes >> 6) & 0x3F))
+                     . chr(0x80 | ($bytes & 0x3F));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }        
+
+   /**
+    * convert a string from one UTF-8 char to one UTF-16 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf8   UTF-8 character
+    * @return   string  UTF-16 character
+    * @access   private
+    */
+    function utf82utf16($utf8)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding'))
+            return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+        
+        switch(strlen($utf8)) {
+            case 1:
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return $utf8;
+
+            case 2:
+                // return a UTF-16 character from a 2-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x07 & (ord($utf8{0}) >> 2))
+                     . chr((0xC0 & (ord($utf8{0}) << 6))
+                         | (0x3F & ord($utf8{1})));
+                
+            case 3:
+                // return a UTF-16 character from a 3-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr((0xF0 & (ord($utf8{0}) << 4))
+                         | (0x0F & (ord($utf8{1}) >> 2)))
+                     . chr((0xC0 & (ord($utf8{1}) << 6))
+                         | (0x7F & ord($utf8{2})));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }        
+
+   /**
+    * encodes an arbitrary variable into JSON format
+    *
+    * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
+    *                           see argument 1 to Services_JSON() above for array-parsing behavior.
+    *                           if var is a strng, note that encode() always expects it
+    *                           to be in ASCII or UTF-8 format!
+    *
+    * @return   string  JSON string representation of input var
+    * @access   public
+    */
+    function encode($var)
+    {
+        switch (gettype($var)) {
+            case 'boolean':
+                return $var ? 'true' : 'false';
+            
+            case 'NULL':
+                return 'null';
+            
+            case 'integer':
+                return (int) $var;
+                
+            case 'double':
+            case 'float':
+                return (float) $var;
+                
+            case 'string':
+								//>> SJM2005
+								if ($this->encoding == SERVICES_JSON_UTF_8)
+									;
+								else if ($this->encoding == SERVICES_JSON_ISO_8859_1)
+									$var = utf8_encode($var); 
+								else if (!function_exists('mb_convert_encoding'))
+									die('Requested encoding requires mb_strings extension.');
+								else 
+									$var = mb_convert_encoding($var, "utf-8", $this->encoding);
+								//<< SJM2005
+											
+                // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+                $ascii = '';
+                $strlen_var = strlen($var);
+
+               /*
+                * Iterate over every character in the string,
+                * escaping with a slash or encoding to UTF-8 where necessary
+                */
+                for ($c = 0; $c < $strlen_var; ++$c) {
+                    
+                    $ord_var_c = ord($var{$c});
+                    
+                    switch (true) {
+                        case $ord_var_c == 0x08:
+                            $ascii .= '\b';
+                            break;
+                        case $ord_var_c == 0x09:
+                            $ascii .= '\t';
+                            break;
+                        case $ord_var_c == 0x0A:
+                            $ascii .= '\n';
+                            break;
+                        case $ord_var_c == 0x0C:
+                            $ascii .= '\f';
+                            break;
+                        case $ord_var_c == 0x0D:
+                            $ascii .= '\r';
+                            break;
+
+                        case $ord_var_c == 0x22:
+                        case $ord_var_c == 0x2F:
+                        case $ord_var_c == 0x5C:
+                            // double quote, slash, slosh
+                            $ascii .= '\\'.$var{$c};
+                            break;
+                         
+                        case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+                            // characters U-00000000 - U-0000007F (same as ASCII)
+                            $ascii .= $var{$c};
+                            break;
+                        
+                        case (($ord_var_c & 0xE0) == 0xC0):
+                            // characters U-00000080 - U-000007FF, mask 110XXXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+                            $c += 1;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xF0) == 0xE0):
+                            // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}));
+                            $c += 2;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xF8) == 0xF0):
+                            // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}));
+                            $c += 3;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xFC) == 0xF8):
+                            // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}));
+                            $c += 4;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xFE) == 0xFC):
+                            // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}),
+                                         ord($var{$c + 5}));
+                            $c += 5;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+                    }
+                }
+                
+                return '"'.$ascii.'"';
+                
+            case 'array':
+               /*
+                * As per JSON spec if any array key is not an integer
+                * we must treat the the whole array as an object. We
+                * also try to catch a sparsely populated associative
+                * array with numeric keys here because some JS engines
+                * will create an array with empty indexes up to
+                * max_index which can cause memory issues and because
+                * the keys, which may be relevant, will be remapped
+                * otherwise.
+                * 
+                * As per the ECMA and JSON specification an object may
+                * have any string as a property. Unfortunately due to
+                * a hole in the ECMA specification if the key is a
+                * ECMA reserved word or starts with a digit the
+                * parameter is only accessible using ECMAScript's
+                * bracket notation.
+                */
+                
+                // treat as a JSON object  
+                if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+                    return '{' .
+                           join(',', array_map(array($this, 'name_value'),
+                                               array_keys($var),
+                                               array_values($var)))
+                           . '}';
+                }
+
+                // treat it like a regular array
+                return '[' . join(',', array_map(array($this, 'encode'), $var)) . ']';
+                
+            case 'object':
+                $vars = get_object_vars($var);
+                return '{' .
+                       join(',', array_map(array($this, 'name_value'),
+                                           array_keys($vars),
+                                           array_values($vars)))
+                       . '}';
+
+            default:
+                return '';
+        }
+    }
+    
+   /**
+    * array-walking function for use in generating JSON-formatted name-value pairs
+    *
+    * @param    string  $name   name of key to use
+    * @param    mixed   $value  reference to an array element to be encoded
+    *
+    * @return   string  JSON-formatted name-value pair, like '"name":value'
+    * @access   private
+    */
+    function name_value($name, $value)
+    {
+        return $this->encode(strval($name)) . ':' . $this->encode($value);
+    }        
+
+   /**
+    * reduce a string by removing leading and trailing comments and whitespace
+    *
+    * @param    $str    string      string value to strip of comments and whitespace
+    *
+    * @return   string  string value stripped of comments and whitespace
+    * @access   private
+    */
+    function reduce_string($str)
+    {
+        $str = preg_replace(array(
+        
+                // eliminate single line comments in '// ...' form
+                '#^\s*//(.+)$#m',
+    
+                // eliminate multi-line comments in '/* ... */' form, at start of string
+                '#^\s*/\*(.+)\*/#Us',
+    
+                // eliminate multi-line comments in '/* ... */' form, at end of string
+                '#/\*(.+)\*/\s*$#Us'
+    
+            ), '', $str);
+        
+        // eliminate extraneous space
+        return trim($str);
+    }
+
+   /**
+    * decodes a JSON string into appropriate variable
+    *
+    * @param    string  $str    JSON-formatted string
+    *
+    * @return   mixed   number, boolean, string, array, or object
+    *                   corresponding to given JSON input string.
+    *                   See argument 1 to Services_JSON() above for object-output behavior.
+    *                   Note that decode() always returns strings
+    *                   in ASCII or UTF-8 format!
+    * @access   public
+    */
+    function decode($str)
+    {
+				$str = $this->reduce_string($str);
+   			
+        switch (strtolower($str)) {
+            case 'true':
+                return true;
+
+            case 'false':
+                return false;
+            
+            case 'null':
+                return null;
+            
+            default:
+                if (is_numeric($str)) {
+                    // Lookie-loo, it's a number
+
+                    // This would work on its own, but I'm trying to be
+                    // good about returning integers where appropriate:
+                    // return (float)$str;
+
+                    // Return float or int, as appropriate
+                    return ((float)$str == (integer)$str)
+                        ? (integer)$str
+                        : (float)$str;
+                    
+                } elseif (preg_match('/^("|\').+(\1)$/s', $str, $m) && $m[1] == $m[2]) {
+                    // STRINGS RETURNED IN UTF-8 FORMAT
+                    $delim = substr($str, 0, 1);
+                    $chrs = substr($str, 1, -1);
+                    $utf8 = '';
+                    $strlen_chrs = strlen($chrs);
+                    
+                    for ($c = 0; $c < $strlen_chrs; ++$c) {
+                    
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                        $ord_chrs_c = ord($chrs{$c});
+                        
+                        switch (true) {
+                            case $substr_chrs_c_2 == '\b':
+                                $utf8 .= chr(0x08);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\t':
+                                $utf8 .= chr(0x09);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\n':
+                                $utf8 .= chr(0x0A);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\f':
+                                $utf8 .= chr(0x0C);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\r':
+                                $utf8 .= chr(0x0D);
+                                ++$c;
+                                break;
+
+                            case $substr_chrs_c_2 == '\\"':
+                            case $substr_chrs_c_2 == '\\\'':
+                            case $substr_chrs_c_2 == '\\\\':
+                            case $substr_chrs_c_2 == '\\/':
+                                if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
+                                   ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
+                                    $utf8 .= $chrs{++$c};
+                                }
+                                break;
+                                
+                            case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
+																//echo ' matching single escaped unicode character from ' . substr($chrs, $c, 6);
+                                // single, escaped unicode character
+                                $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
+                                       . chr(hexdec(substr($chrs, ($c + 4), 2)));
+                                $utf8 .= $this->utf162utf8($utf16);
+                                $c += 5;
+                                break;
+        
+                            case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
+                                $utf8 .= $chrs{$c};
+                                break;
+        
+                            case ($ord_chrs_c & 0xE0) == 0xC0:
+                                // characters U-00000080 - U-000007FF, mask 110XXXXX
+                                //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 2);
+                                ++$c;
+                                break;
+    
+                            case ($ord_chrs_c & 0xF0) == 0xE0:
+                                // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 3);
+                                $c += 2;
+                                break;
+    
+                            case ($ord_chrs_c & 0xF8) == 0xF0:
+                                // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 4);
+                                $c += 3;
+                                break;
+    
+                            case ($ord_chrs_c & 0xFC) == 0xF8:
+                                // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 5);
+                                $c += 4;
+                                break;
+    
+                            case ($ord_chrs_c & 0xFE) == 0xFC:
+                                // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 6);
+                                $c += 5;
+                                break;
+
+                        }
+
+                    }
+                    
+										//>> SJM2005
+										if ($this->encoding == SERVICES_JSON_UTF_8)
+	                    return $utf8;
+										if ($this->encoding == SERVICES_JSON_ISO_8859_1)
+											return utf8_decode($utf8);
+										else if (!function_exists('mb_convert_encoding'))
+											die('Requested encoding requires mb_strings extension.');
+										else 
+											return mb_convert_encoding($utf8, $this->encoding, SERVICES_JSON_UTF_8);
+										//<< SJM2005
+										
+                    return $utf8;
+                
+                } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
+                    // array, or object notation
+                    if ($str{0} == '[') {
+                        $stk = array(SERVICES_JSON_IN_ARR);
+                        $arr = array();
+                    } else {
+                        if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = array();
+                        } else {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = new stdClass();
+                        }
+                    }
+                    
+                    array_push($stk, array('what'  => SERVICES_JSON_SLICE,
+                                           'where' => 0,
+                                           'delim' => false));
+
+                    $chrs = substr($str, 1, -1);
+                    $chrs = $this->reduce_string($chrs);
+                    
+                    if ($chrs == '') {
+                        if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                            return $arr;
+
+                        } else {
+                            return $obj;
+
+                        }
+                    }
+
+                    //print("\nparsing {$chrs}\n");
+                    
+                    $strlen_chrs = strlen($chrs);
+                    for ($c = 0; $c <= $strlen_chrs; ++$c) {
+                    
+                        $top = end($stk);
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                    
+                        if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
+                            // found a comma that is not inside a string, array, etc.,
+                            // OR we've reached the end of the character list
+                            $slice = substr($chrs, $top['where'], ($c - $top['where']));
+                            array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
+                            //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                            if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                                // we are in an array, so just push an element onto the stack
+                                array_push($arr, $this->decode($slice));
+
+                            } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                                // we are in an object, so figure
+                                // out the property name and set an
+                                // element in an associative array,
+                                // for now
+                                if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // "name":value pair
+                                    $key = $this->decode($parts[1]);
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // name:value pair, where name is unquoted
+                                    $key = $parts[1];
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                }
+
+                            }
+
+                        } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
+                            // found a quote, and we are not inside a string
+                            array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
+                            //print("Found start of string at {$c}\n");
+
+												//>> SAO2006				 
+                        /*} elseif (($chrs{$c} == $top['delim']) &&
+                                 ($top['what'] == SERVICES_JSON_IN_STR) &&
+                                 (($chrs{$c - 1} != '\\')  ||
+																 ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) {*/
+												} elseif ($chrs{$c} == $top['delim'] &&
+                          		$top['what'] == SERVICES_JSON_IN_STR) {			 
+														//print("Found potential end of string at {$c}\n");
+														// verify quote is not escaped: it has no or an even number of \\ before it.
+														for ($i=0; ($chrs{$c - ($i+1)} == '\\'); $i++);
+														/*$i = 0;		
+														while (	$chrs{$c - ($i+1)} == '\\')
+															$i++;*/
+														//print("Found {$i} \ before delim\n");
+														if ($i % 2 != 0)
+														{	
+															//print("delim escaped, not end of string\n");
+															continue;	 
+														} 
+												//>> SAO2006		
+                            // found a quote, we're in a string, and it's not escaped
+                            array_pop($stk);
+                            //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '[') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-bracket, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
+                            //print("Found start of array at {$c}\n");
+
+                        } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
+                            // found a right-bracket, and we're in an array
+                            array_pop($stk);
+                            //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '{') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-brace, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
+                            //print("Found start of object at {$c}\n");
+
+                        } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
+                            // found a right-brace, and we're in an object
+                            array_pop($stk);
+                            //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($substr_chrs_c_2 == '/*') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a comment start, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
+                            $c++;
+                            //print("Found start of comment at {$c}\n");
+
+                        } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
+                            // found a comment end, and we're in one now
+                            array_pop($stk);
+                            $c++;
+                            
+                            for ($i = $top['where']; $i <= $c; ++$i)
+                                $chrs = substr_replace($chrs, ' ', $i, 1);
+                            
+                            //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        }
+                    
+                    }
+                    
+                    if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                        return $arr;
+
+                    } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                        return $obj;
+
+                    }
+                
+                }
+        }
+    }
+    
+}
+
+	/*function hex($s)
+	{
+		$l = strlen($s);
+		for ($i=0; $i < $l; $i++)
+			//echo '['.(ord($s{$i})).']';
+			echo '['.bin2hex($s{$i}).']';
+	}
+ 
+	//$d = '["hello world\\""]';
+	$d = '["\\\\\\"hello world,\\\\\\""]';
+	//$d = '["\\\\", "\\\\"]';
+	hex($d);
+	$test = new Services_JSON();
+	echo('<pre>');
+	print_r($d . "\n");
+	print_r($test->decode($d));
+	echo('</pre>');
+	*/	
+?>
\ No newline at end of file
diff --git a/dojox/grid/tests/support/movies.csv b/dojox/grid/tests/support/movies.csv
new file mode 100644
index 0000000..baf71eb
--- /dev/null
+++ b/dojox/grid/tests/support/movies.csv
@@ -0,0 +1,9 @@
+Title, Year, Producer
+City of God, 2002, Katia Lund
+Rain,, Christine Jeffs
+2001: A Space Odyssey, , Stanley Kubrick
+"This is a ""fake"" movie title", 1957, Sidney Lumet
+Alien, 1979   , Ridley Scott
+"The Sequel to ""Dances With Wolves.""", 1982, Ridley Scott
+"Caine Mutiny, The", 1954, "Dymtryk ""the King"", Edward"
+
diff --git a/dojox/grid/tests/support/numbers.json b/dojox/grid/tests/support/numbers.json
new file mode 100644
index 0000000..fe4495a
--- /dev/null
+++ b/dojox/grid/tests/support/numbers.json
@@ -0,0 +1,104 @@
+{ identifier: 'id',
+	label: 'id',
+	items: [
+		{ id: '0', label: '0'},
+		{ id: '1', label: '1'},
+		{ id: '2', label: '2'},
+		{ id: '3', label: '3'},
+		{ id: '4', label: '4'},
+		{ id: '5', label: '5'},
+		{ id: '6', label: '6'},
+		{ id: '7', label: '7'},
+		{ id: '8', label: '8'},
+		{ id: '9', label: '9'},
+		{ id: '10', label: '10'},
+		{ id: '11', label: '11'},
+		{ id: '12', label: '12'},
+		{ id: '13', label: '13'},
+		{ id: '14', label: '14'},
+		{ id: '15', label: '15'},
+		{ id: '16', label: '16'},
+		{ id: '17', label: '17'},
+		{ id: '18', label: '18'},
+		{ id: '19', label: '19'},
+		{ id: '20', label: '20'},
+		{ id: '21', label: '21'},
+		{ id: '22', label: '22'},
+		{ id: '23', label: '23'},
+		{ id: '24', label: '24'},
+		{ id: '25', label: '25'},
+		{ id: '26', label: '26'},
+		{ id: '27', label: '27'},
+		{ id: '28', label: '28'},
+		{ id: '29', label: '29'},
+		{ id: '30', label: '30'},
+		{ id: '31', label: '31'},
+		{ id: '32', label: '32'},
+		{ id: '33', label: '33'},
+		{ id: '34', label: '34'},
+		{ id: '35', label: '35'},
+		{ id: '36', label: '36'},
+		{ id: '37', label: '37'},
+		{ id: '38', label: '38'},
+		{ id: '39', label: '39'},
+		{ id: '40', label: '40'},
+		{ id: '41', label: '41'},
+		{ id: '42', label: '42'},
+		{ id: '43', label: '43'},
+		{ id: '44', label: '44'},
+		{ id: '45', label: '45'},
+		{ id: '46', label: '46'},
+		{ id: '47', label: '47'},
+		{ id: '48', label: '48'},
+		{ id: '49', label: '49'},
+		{ id: '50', label: '50'},
+		{ id: '51', label: '51'},
+		{ id: '52', label: '52'},
+		{ id: '53', label: '53'},
+		{ id: '54', label: '54'},
+		{ id: '55', label: '55'},
+		{ id: '56', label: '56'},
+		{ id: '57', label: '57'},
+		{ id: '58', label: '58'},
+		{ id: '59', label: '59'},
+		{ id: '60', label: '60'},
+		{ id: '61', label: '61'},
+		{ id: '62', label: '62'},
+		{ id: '63', label: '63'},
+		{ id: '64', label: '64'},
+		{ id: '65', label: '65'},
+		{ id: '66', label: '66'},
+		{ id: '67', label: '67'},
+		{ id: '68', label: '68'},
+		{ id: '69', label: '69'},
+		{ id: '70', label: '70'},
+		{ id: '71', label: '71'},
+		{ id: '72', label: '72'},
+		{ id: '73', label: '73'},
+		{ id: '74', label: '74'},
+		{ id: '75', label: '75'},
+		{ id: '76', label: '76'},
+		{ id: '77', label: '77'},
+		{ id: '78', label: '78'},
+		{ id: '79', label: '79'},
+		{ id: '80', label: '80'},
+		{ id: '81', label: '81'},
+		{ id: '82', label: '82'},
+		{ id: '83', label: '83'},
+		{ id: '84', label: '84'},
+		{ id: '85', label: '85'},
+		{ id: '86', label: '86'},
+		{ id: '87', label: '87'},
+		{ id: '88', label: '88'},
+		{ id: '89', label: '89'},
+		{ id: '90', label: '90'},
+		{ id: '91', label: '91'},
+		{ id: '92', label: '92'},
+		{ id: '93', label: '93'},
+		{ id: '94', label: '94'},
+		{ id: '95', label: '95'},
+		{ id: '96', label: '96'},
+		{ id: '97', label: '97'},
+		{ id: '98', label: '98'},
+		{ id: '99', label: '99'}
+]}
diff --git a/dojox/grid/tests/support/test_data.js b/dojox/grid/tests/support/test_data.js
new file mode 100644
index 0000000..8e7b4eb
--- /dev/null
+++ b/dojox/grid/tests/support/test_data.js
@@ -0,0 +1,26 @@
+// example sample data and code
+(function(){
+	// some sample data
+	// global var "data"
+	data = {
+		identifier: 'id',
+		label: 'id',
+		items: []
+	};
+	data_list = [ 
+		{ col1: "normal", col2: false, col3: "new", col4: 'But are not followed by two hexadecimal', col5: 29.91, col6: 10, col7: false },
+		{ col1: "important", col2: false, col3: "new", col4: 'Because a % sign always indicates', col5: 9.33, col6: -5, col7: false },
+		{ col1: "important", col2: false, col3: "read", col4: 'Signs can be selectively', col5: 19.34, col6: 0, col7: true },
+		{ col1: "note", col2: false, col3: "read", col4: 'However the reserved characters', col5: 15.63, col6: 0, col7: true },
+		{ col1: "normal", col2: false, col3: "replied", col4: 'It is therefore necessary', col5: 24.22, col6: 5.50, col7: true },
+		{ col1: "important", col2: false, col3: "replied", col4: 'To problems of corruption by', col5: 9.12, col6: -3, col7: true },
+		{ col1: "note", col2: false, col3: "replied", col4: 'Which would simply be awkward in', col5: 12.15, col6: -4, col7: false }
+	];
+	var rows = 100;
+	for(var i=0, l=data_list.length; i<rows; i++){
+		data.items.push(dojo.mixin({ id: i }, data_list[i%l]));
+	}
+
+	// global var "test_store"
+	test_store = new dojo.data.ItemFileWriteStore({data: data});
+})();
diff --git a/dojox/grid/tests/support/test_data_date.js b/dojox/grid/tests/support/test_data_date.js
new file mode 100644
index 0000000..0df33a6
--- /dev/null
+++ b/dojox/grid/tests/support/test_data_date.js
@@ -0,0 +1,27 @@
+// example sample data and code
+(function(){
+	// some sample data
+	// global var "data"
+	data = {
+		identifier: 'id',
+		label: 'id',
+		items: []
+	};
+	var s = (new Date()).getTime();
+	data_list = [ 
+		{ col1: "normal", col2: false, col3: "new", col4: 'But are not followed by two hexadecimal', col5: 29.91, col6: 10, col7: false, col8: new Date() },
+		{ col1: "important", col2: false, col3: "new", col4: 'Because a % sign always indicates', col5: 9.33, col6: -5, col7: false, col8: new Date() },
+		{ col1: "important", col2: false, col3: "read", col4: 'Signs can be selectively', col5: 19.34, col6: 0, col7: true, col8: new Date() },
+		{ col1: "note", col2: false, col3: "read", col4: 'However the reserved characters', col5: 15.63, col6: 0, col7: true, col8: new Date() },
+		{ col1: "normal", col2: false, col3: "replied", col4: 'It is therefore necessary', col5: 24.22, col6: 5.50, col7: true, col8: new Date() },
+		{ col1: "important", col2: false, col3: "replied", col4: 'To problems of corruption by', col5: 9.12, col6: -3, col7: true, col8: new Date() },
+		{ col1: "note", col2: false, col3: "replied", col4: 'Which would simply be awkward in', col5: 12.15, col6: -4, col7: false, col8: new Date() }
+	];
+	var rows = 100;
+	for(var i=0, l=data_list.length; i<rows; i++){
+		data.items.push(dojo.mixin({ id: i }, data_list[i%l]));
+	}
+
+	// global var "test_data"
+	test_store = new dojo.data.ItemFileWriteStore({data: data});
+})();
diff --git a/dojox/grid/tests/support/test_resize_data.json b/dojox/grid/tests/support/test_resize_data.json
new file mode 100644
index 0000000..c2a6d09
--- /dev/null
+++ b/dojox/grid/tests/support/test_resize_data.json
@@ -0,0 +1,34 @@
+{
+ "items":[
+          {
+           "r0c0":"r0c0 value1",
+           "r0c1":"r0c1 value1",
+           "r0c2":"r0c2 value1",
+           "r0c3":"r0c3 value1",
+           "r1c0":"r1c0 value1",
+           "r1c1":"r1c1 value1",
+           "r1c2":"r1c2 value1",
+           "r1c3":"r1c3 value1"
+          },
+          {
+           "r0c0":"r0c0 value2",
+           "r0c1":"r0c1 value2",
+           "r0c2":"r0c2 value2",
+           "r0c3":"r0c3 value2",
+           "r1c0":"r1c0 value2",
+           "r1c1":"r1c1 value2",
+           "r1c2":"r1c2 value2",
+           "r1c3":"r1c3 value2"
+          },
+          {
+           "r0c0":"r0c0 value3",
+           "r0c1":"r0c1 value3",
+           "r0c2":"r0c2 value3",
+           "r0c3":"r0c3 value3",
+           "r1c0":"r1c0 value3",
+           "r1c1":"r1c1 value3",
+           "r1c2":"r1c2 value3",
+           "r1c3":"r1c3 value3"
+          }
+         ]
+}          
\ No newline at end of file
diff --git a/dojox/grid/tests/support/testtbl.sql b/dojox/grid/tests/support/testtbl.sql
new file mode 100644
index 0000000..733216f
--- /dev/null
+++ b/dojox/grid/tests/support/testtbl.sql
@@ -0,0 +1,944 @@
+/*
+MySQL Data Transfer
+Source Host: localhost
+Source Database: test
+Target Host: localhost
+Target Database: test
+Date: 12/14/2006 12:13:30 PM
+*/
+
+SET FOREIGN_KEY_CHECKS=0;
+-- ----------------------------
+-- Table structure for testtbl
+-- ----------------------------
+CREATE TABLE `testtbl` (
+  `Id` int(10) unsigned NOT NULL,
+  `Name` varchar(45) NOT NULL default '',
+  `Message` varchar(255) default NULL,
+  `Date` date default '2005-01-01',
+  PRIMARY KEY  (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='InnoDB free: 4096 kB; InnoDB free: 4096 kB; InnoDB free: 409';
+
+-- ----------------------------
+-- Records 
+-- ----------------------------
+INSERT INTO `testtbl` VALUES ('363', ' Lopez, Felipe', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('364', ' Lopez, Javy', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('365', ' Lopez, L', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('366', ' Lopez, Luis', ' 0.244', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('367', ' Lopez, Mendy', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('368', ' Loretta, Mark', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('369', ' Lowell, Mike', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('370', ' Lugo, Julio', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('371', ' Lunar, Fernando', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('372', ' Mabry, John', ' 0.208', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('373', ' Machado, Robert', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('374', ' Macias, Jose', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('375', ' Mackowiak, Rob', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('376', ' Magadan, Dave', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('377', ' Magee, Wendell', ' 0.213', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('378', ' Magruder, Chris', ' 0.172', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('379', ' Marrero, Eli', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('380', ' Martin, Al', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('381', ' Martinez, Dave', ' 0.287', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('382', ' Martinez, Edgar', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('383', ' Martinez, Felix', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('384', ' Martinez, Ramon', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('385', ' Martinez, Ramone', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('386', ' Martinez, Sandy', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('387', ' Martinez, Tino', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('388', ' Mateo, Henry', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('389', ' Mateo, Ruben', ' 0.248', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('390', ' Matheny, Mike', ' 0.218', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('391', ' Matos, Luis', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('392', ' Mattess, Troy', ' 0.467', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('393', ' Matthews, Gary', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('394', ' Maurer, Dave', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('395', ' Maxwell, Jason', ' 0.191', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('396', ' Mayne, Brent', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('397', ' McCarty, David', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('398', ' McCracken, Quinton', ' 0.219', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('399', ' McDonald, Donzell', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('400', ' McDonald, John', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('401', ' McDonald, Keith', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('402', ' McEwing, Joe', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('403', ' McGriff, Fred', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('404', ' McGuire, Ryan', ' 0.185', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('405', ' McGwire, Mark', ' 0.187', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('406', ' McLemore, Mark', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('407', ' McMillon, Billy', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('408', ' McRae, Scott', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('409', ' Meares, Pat', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('410', ' Melhuse, Adam', ' 0.183', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('411', ' Mendez, Donaldo', ' 0.153', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('412', ' Menechino, Frank', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('413', ' Merced, Orlando', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('414', ' Merloni, Lou', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('415', ' Meyers, Chad', ' 0.118', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('416', ' Michaels, Jason', ' 0.167', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('417', ' Mientkiewicz, Doug', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('418', ' Millar, Kevin', ' 0.314', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('419', ' Miller, Corky', ' 0.184', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('420', ' Miller, Damian', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('421', ' Minor, Damion', ' 0.156', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('422', ' Minor, Ryan', ' 0.158', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('423', ' Mirabelli, Doug', ' 0.226', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('424', ' Moeller, Chad', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('425', ' Mohr, Dustan', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('426', ' Molina, Ben', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('427', ' Molina, Jose', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('428', ' Mondesi, Raul', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('429', ' Monroe, Craig', ' 0.212', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('430', ' Mora, Melvin', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('431', ' Mordecai, Mike', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('432', ' Morris, Warren', ' 0.204', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('433', ' Mottola, Chad', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('434', ' Mouton, James', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('435', ' Mouton, Lyle', ' 0.059', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('436', ' Mueller, Bill', ' 0.295', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('437', ' Munson, Eric', ' 0.152', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('438', ' Murray, Calvin', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('439', ' Myers, Greg', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('440', ' Nevin, Phil', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('441', ' Newhan, David', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('442', ' Nieves, Jose', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('443', ' Nixon, Trot', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('444', ' Norton, Greg', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('445', ' Nunez, Abraham', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('446', ' Ochoa, Alex', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('447', ' Offerman, Jose', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('448', ' Ojeda, Augie', ' 0.201', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('449', ' O\\\'Leary, Troy', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('450', ' Olerud, John', ' 0.302', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('451', ' Oliver, Joe', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('452', ' O\\\'Neill, Paul', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('453', ' Ordaz, Luis', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('454', ' Ordonez, Magglio', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('455', ' Ordonez, Rey', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('456', ' Ortega, Bill', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('457', ' Ortiz, David', ' 0.234', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('458', ' Ortiz, Hector', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('459', ' Ortiz, Jose', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('460', ' Osik, Keith', ' 0.208', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('461', ' Overbay, Lyle', ' 0.5', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('462', ' Owens, Eric', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('463', ' Palmeiro, Orlando', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('464', ' Palmeiro, Rafael', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('465', ' Palmer, Dean', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('466', ' Paquette, Craig', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('467', ' Patterson, Corey', ' 0.221', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('468', ' Patterson, Jarrod', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('469', ' Paul, Josh', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('470', ' Payton, Jay', ' 0.255', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('471', ' Pena, Angel', ' 0.204', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('472', ' Pena, Carlos', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('473', ' Pena, Elvis', ' 0.225', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('474', ' Perez, Eddie', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('475', ' Perez, Neifi', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('476', ' Perez, Robert', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('477', ' Perez, Santiago', ' 0.198', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('478', ' Perez, Thomas', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('479', ' Perez, Timoniel', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('480', ' Perry, Herbert', ' 0.256', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('481', ' Peters, Chris', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('482', ' Petrick, Ben', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('483', ' Phelps, Josh', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('484', ' Phillips, Jason', ' 0.143', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('485', ' Piatt, Adam', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('486', ' Piazza, Mike', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('487', ' Pickering, Calvin', ' 0.278', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('488', ' Pierre, Juan', ' 0.327', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('489', ' Pierzynski, A.J.', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('490', ' Podsednik, Scott', ' 0.167', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('491', ' Polanco, Placido', ' 0.307', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('492', ' Porter, Bo', ' 0.23', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('493', ' Posada, Jorge', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('494', ' Powell, Dante', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('495', ' Pratt, Todd', ' 0.185', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('496', ' Pride, Curtis', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('497', ' Prince, Tom', ' 0.219', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('498', ' Pujols, Albert', ' 0.329', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('499', ' Punto, Nick', ' 0.4', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('500', ' Quevado, Ruben', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('501', ' Quinn, Mark', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('502', ' Raines, Tim', ' 0.174', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('503', ' Raines, Tim', ' 0.303', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('504', ' Ramirez, Aramis', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('505', ' Ramirez, Julio', ' 0.081', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('506', ' Ramirez, Manny', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('507', ' Randa, Joe', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('508', ' Ransom, Cody', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('509', ' Reboulet, Jeff', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('510', ' Redman, Tim', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('511', ' Redmond, Mike', ' 0.312', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('512', ' Reese, Pokey', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('513', ' Relaford, Desi', ' 0.302', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('514', ' Renteria, Edgar', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('515', ' Richard, Chris', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('516', ' Riggs, Adam', ' 0.194', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('517', ' Rios, Armando', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('518', ' Ripken, Cal', ' 0.239', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('519', ' Rivas, Luis', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('520', ' Rivera, Juan', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('521', ' Rivera, Mike', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('522', ' Rivera, Ruben', ' 0.255', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('523', ' Roberts, Brian', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('524', ' Roberts, Dave', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('525', ' Robinson, Kerry', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('526', ' Rodriguez, Alex', ' 0.318', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('527', ' Rodriguez, Henry', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('528', ' Rodriguez, Ivan', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('529', ' Rolen, Scott', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('530', ' Rollins, Jimmy', ' 0.274', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('531', ' Rolls, Damian', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('532', ' Rowand, Aaron', ' 0.293', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('533', ' Ruffin, Johnny', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('534', ' Ryan, Rob', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('535', ' Sadler, Donnie', ' 0.162', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('536', ' Saenz, Olmedo', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('537', ' Salmon, Tim', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('538', ' Sanchez, Alex', ' 0.206', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('539', ' Sanchez, Rey', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('540', ' Sandberg, Jared', ' 0.206', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('541', ' Sanders, Anthony', ' 0.176', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('542', ' Sanders, Deion', ' 0.173', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('543', ' Sanders, Reggie', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('544', ' Santana, Pedro', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('545', ' Santangelo, F.P.', ' 0.197', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('546', ' Santiago, Benito', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('547', ' Santos, Angel', ' 0.125', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('548', ' Saturria, Luis', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('549', ' Schneider, Brian', ' 0.317', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('550', ' Schourek, Pete', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('551', ' Seabol, Scott', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('552', ' Sefcik, Kevin', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('553', ' Segui, David', ' 0.301', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('554', ' Seguignol, Fernando', ' 0.14', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('555', ' Selby, Bill', ' 0.228', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('556', ' Servais, Scott', ' 0.375', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('557', ' Sexson, Richie', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('558', ' Sheets, Andy', ' 0.196', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('559', ' Sheffield, Gary', ' 0.311', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('560', ' Sheldon, Scott', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('561', ' Shinjo, Tsuyoshi', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('562', ' Shumpert, Terry', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('563', ' Sierra, Ruben', ' 0.291', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('564', ' Simmons, Brian', ' 0.178', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('565', ' Simon, Randall', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('566', ' Singleton, Chris', ' 0.298', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('567', ' Smith, Bobby', ' 0.105', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('568', ' Smith, Jason', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('569', ' Smith, Mark', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('570', ' Snow, J.T.', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('571', ' Sojo, Luis', ' 0.165', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('572', ' Soriano, Alfonso', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('573', ' Sosa, Juan', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('574', ' Sosa, Sammy', ' 0.328', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('575', ' Spencer, Shane', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('576', ' Spiers, Bill', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('577', ' Spiezio, Scott', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('578', ' Spivey, Junior', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('579', ' Sprague, Ed', ' 0.298', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('580', ' Stairs, Matt', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('581', ' Stevens, Lee', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('582', ' Stewart, Shannon', ' 0.316', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('583', ' Stinnett, Kelly', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('584', ' Stynes, Chris', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('585', ' Surhoff, B.J.', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('586', ' Sutton, Larry', ' 0.119', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('587', ' Suzuki, Ichiro', ' 0.35', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('588', ' Sweeney, Mark', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('589', ' Sweeney, Mike', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('590', ' Tapani, Kevin', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('591', ' Tatis, Fernando', ' 0.255', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('592', ' Taubensee, Eddie', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('593', ' Taylor, Reggie', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('594', ' Tejada, Miguel', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('595', ' Thomas, Frank', ' 0.221', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('596', ' Thome, Jim', ' 0.291', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('597', ' Thompson, Ryan', ' 0.29', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('598', ' Toca, Jorge', ' 0.176', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('599', ' Torrealba, Steve', ' 0.5', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('600', ' Torrealba, Yorvit', ' 0.5', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('601', ' Tracy, Andy', ' 0.109', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('602', ' Trammell, Bubba', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('603', ' Truby, Chris', ' 0.206', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('604', ' Tucker, Michael', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('605', ' Tyner, Jason', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('606', ' Uribe, Juan', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('607', ' Valdez, Mario', ' 0.278', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('608', ' Valent, Eric', ' 0.098', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('609', ' Valentin, John', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('610', ' Valentin, Jose', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('611', ' VanderWal, John', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('612', ' Varitek, Jason', ' 0.293', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('613', ' Vaughn, Greg', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('614', ' Vazquez, Ramon', ' 0.229', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('615', ' Velandia, Jorge', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('616', ' Velarde, Randy', ' 0.278', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('617', ' Ventura, Robin', ' 0.237', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('618', ' Veras, Quilvio', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('619', ' Vidro, Jose', ' 0.319', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('620', ' Vina, Fernando', ' 0.303', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('621', ' Vizcaino, Jose', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('622', ' Vizquel, Omar', ' 0.255', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('623', ' Wakeland, Chris', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('624', ' Walbeck, Matt', ' 1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('625', ' Walker, Larry', ' 0.35', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('626', ' Walker, Todd', ' 0.296', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('627', ' Ward, Daryle', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('628', ' Ward, Turner', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('629', ' Wehner, John', ' 0.196', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('630', ' Wells, Vernon', ' 0.313', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('631', ' White, Devon', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('632', ' White, Rondell', ' 0.307', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('633', ' Whiteside, Matt', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('634', ' Wilkerson, Brad', ' 0.205', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('635', ' Wilkins, Rick', ' 0.182', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('636', ' Williams, Bernie', ' 0.307', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('637', ' Williams, Gerald', ' 0.201', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('638', ' Williams, Matt', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('639', ' Wilson, Craig', ' 0.31', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('640', ' Wilson, Dan', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('641', ' Wilson, Enrique', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('642', ' Wilson, Jack', ' 0.223', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('643', ' Wilson, Preston', ' 0.274', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('644', ' Wilson, Tom', ' 0.19', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('645', ' Wilson, Vance', ' 0.298', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('646', ' Winn, Randy', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('647', ' Witt, Kevin', ' 0.185', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('648', ' Womack, Tony', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('649', ' Woodward, Chris', ' 0.19', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('650', ' Wooten, Shawn', ' 0.312', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('651', ' Young, Dmitri', ' 0.302', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('652', ' Young, Eric', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('653', ' Young, Kevin', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('654', ' Young, Mike', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('655', ' Zaun, Greg', ' 0.32', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('656', ' Zeile, Todd', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('657', ' Zuleta, Julio', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('658', ' Abernathy, Brent', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('659', ' Abreu, Bob', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('660', ' Agbayani, Benny', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('661', ' Alcantara, Israel', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('662', ' Aldridge, Cory', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('663', ' Alfonzo, Edgardo', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('664', ' Alicea, Luis', ' 0.228', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('665', ' Allen, Chad', ' 0.1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('666', ' Allen, Luke', ' 0.143', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('667', ' Alomar, Roberto', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('668', ' Alomar, Sandy', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('669', ' Alou, Moises', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('670', ' Alvarez, Tony', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('671', ' Amezaga, Alfredo', ' 0.538', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('672', ' Anderson, Brady', ' 0.163', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('673', ' Anderson, Garret', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('674', ' Anderson, Marlon', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('675', ' Andrews, Shane', ' 0.077', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('676', ' Arias, Alex', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('677', ' Aurilia, Rich', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('678', ' Ausmus, Brad', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('679', ' Aven, Bruce', ' 0.118', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('680', ' Baerga, Carlos', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('681', ' Bagwell, Jeff', ' 0.291', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('682', ' Bako, Paul', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('683', ' Banks, Brian', ' 0.321', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('684', ' Barajas, Rod', ' 0.234', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('685', ' Bard, Josh', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('686', ' Barker, Kevin', ' 0.158', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('687', ' Barrett, Michael', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('688', ' Batista, Tony', ' 0.244', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('689', ' Bautista, Danny', ' 0.325', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('690', ' Bell, David', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('691', ' Bell, Jay', ' 0.163', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('692', ' Belle, Albert', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('693', ' Bellhorn, Mark', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('694', ' Belliard, Ron', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('695', ' Bellinger, Clay', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('696', ' Beltran, Carlos', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('697', ' Beltre, Adrian', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('698', ' Benard, Marvin', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('699', ' Benjamin, Mike', ' 0.15', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('700', ' Bennett, Gary', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('701', ' Berg, David', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('702', ' Berger, Brandon', ' 0.201', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('703', ' Bergeron, Peter', ' 0.187', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('704', ' Berkman, Lance', ' 0.292', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('705', ' Berroa, Angel', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('706', ' Bigbie, Larry', ' 0.176', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('707', ' Biggio, Craig', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('708', ' Blake, Casey', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('709', ' Blalock, Hank', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('710', ' Blanco, Henry', ' 0.204', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('711', ' Bloomquist, Willie', ' 0.455', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('712', ' Blum, Geoff', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('713', ' Bocachica, Hiram', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('714', ' Bonds, Barry', ' 0.37', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('715', ' Boone, Aaron', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('716', ' Boone, Bret', ' 0.278', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('717', ' Borchard, Joe', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('718', ' Borders, Pat', ' 0.5', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('719', ' Bordick, Mike', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('720', ' Bradley, Milton', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('721', ' Bragg, Darren', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('722', ' Branyan, Russell', ' 0.228', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('723', ' Brito, Juan', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('724', ' Broussard, Ben', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('725', ' Brown, Adrian', ' 0.216', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('726', ' Brown, Dermal', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('727', ' Brown, Kevin', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('728', ' Brown, Roosevelt', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('729', ' Buchanan, Brian', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('730', ' Burks, Ellis', ' 0.301', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('731', ' Burnitz, Jeromy', ' 0.215', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('732', ' Burrell, Pat', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('733', ' Burroughs, Sean', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('734', ' Bush, Homer', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('735', ' Butler, Brent', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('736', ' Byrd, Marlon', ' 0.229', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('737', ' Byrnes, Eric', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('738', ' Cabrera, Jolbert', ' 0.143', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('739', ' Cabrera, Orlando', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('740', ' Cairo, Miguel', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('741', ' Cameron, Mike', ' 0.239', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('742', ' Canizaro, Jay', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('743', ' Cardona, Javier', ' 0.103', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('744', ' Carroll, Jamey', ' 0.31', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('745', ' Caruso, Mike', ' 0.1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('746', ' Casanova, Raul', ' 0.182', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('747', ' Casey, Sean', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('748', ' Cash, Kevin', ' 0.143', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('749', ' Castilla, Vinny', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('750', ' Castillo, Alberto', ' 0.135', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('751', ' Castillo, Luis', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('752', ' Castro, Juan', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('753', ' Castro, Ramon', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('754', ' Catalanotto, Frank', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('755', ' Cedeno, Roger', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('756', ' Cepicky, Matt', ' 0.216', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('757', ' Chavez, Endy', ' 0.296', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('758', ' Chavez, Eric', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('759', ' Chavez, Raul', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('760', ' Chen, Chin-Feng', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('761', ' Choi, Hee Seop', ' 0.18', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('762', ' Christensen, McKay', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('763', ' Christenson, Ryan', ' 0.155', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('764', ' Cintron, Alex', ' 0.213', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('765', ' Cirillo, Jeff', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('766', ' Clark, Brady', ' 0.192', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('767', ' Clark, Howie', ' 0.302', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('768', ' Clark, Tony', ' 0.207', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('769', ' Clayton, Royce', ' 0.251', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('770', ' Colangelo, Mike', ' 0.174', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('771', ' Colbrunn, Greg', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('772', ' Coleman, Michael', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('773', ' Collier, Lou', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('774', ' Conine, Jeff', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('775', ' Conti, Jason', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('776', ' Coolbaugh, Mike', ' 0.083', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('777', ' Coomer, Ron', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('778', ' Cora, Alex', ' 0.291', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('779', ' Cordero, Wil', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('780', ' Cordova, Marty', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('781', ' Cota, Humberto', ' 0.294', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('782', ' Counsell, Craig', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('783', ' Cox, Steve', ' 0.254', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('784', ' Crawford, Carl', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('785', ' Crede, Joe', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('786', ' Crespo, Cesar', ' 0.172', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('787', ' Crisp, Covelli', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('788', ' Cruz, Deivi', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('789', ' Cruz, Ivan', ' 0.357', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('790', ' Cruz, Jacob', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('791', ' Cruz, Jose', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('792', ' Cuddyer, Michael', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('793', ' Cust, Jack', ' 0.169', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('794', ' Damon, Johnny', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('795', ' Daubach, Brian', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('796', ' DaVanon, Jeff', ' 0.167', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('797', ' Davis, Ben', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('798', ' Davis, J.J.', ' 0.1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('799', ' Dawkins, Travis', ' 0.125', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('800', ' DeHaan, Kory', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('801', ' Delgado, Carlos', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('802', ' Delgado, Wilson', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('803', ' Dellucci, David', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('804', ' DeRosa, Mark', ' 0.297', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('805', ' DeShields, Delino', ' 0.192', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('806', ' Diaz, Einar', ' 0.206', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('807', ' Diaz, Juan Carlos', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('808', ' DiFelice, Mike', ' 0.23', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('809', ' Donnels, Chris', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('810', ' Drew, J.D.', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('811', ' Dunn, Adam', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('812', ' Dunston, Shawon', ' 0.231', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('813', ' Dunwoody, Todd', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('814', ' Durazo, Erubiel', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('815', ' Durham, Ray', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('816', ' Dye, Jermaine', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('817', ' Easley, Damion', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('818', ' Echevarria, Angel', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('819', ' Eckstein, David', ' 0.293', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('820', ' Edmonds, Jim', ' 0.311', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('821', ' Ellis, Mark', ' 0.272', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('822', ' Encarnacion, Juan', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('823', ' Encarnacion, Mario', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('824', ' Ensberg, Morgan', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('825', ' Erstad, Darin', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('826', ' Escalona, Felix', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('827', ' Escobar, Alex', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('828', ' Estalella, Bobby', ' 0.205', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('829', ' Estrada, Johnny', ' 0.118', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('830', ' Everett, Adam', ' 0.193', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('831', ' Everett, Carl', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('832', ' Fabregas, Jorge', ' 0.181', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('833', ' Fasano, Sal', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('834', ' Febles, Carlos', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('835', ' Feliz, Pedro', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('836', ' Fick, Robert', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('837', ' Figgins, Chone', ' 0.167', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('838', ' Finley, Steve', ' 0.287', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('839', ' Flaherty, John', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('840', ' Fletcher, Darrin', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('841', ' Flores, Jose', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('842', ' Floyd, Cliff', ' 0.288', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('843', ' Fordyce, Brook', ' 0.231', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('844', ' Fox, Andy', ' 0.251', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('845', ' Franco, Julio', ' 0.284', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('846', ' Franco, Matt', ' 0.317', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('847', ' Fryman, Travis', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('848', ' Fullmer, Brad', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('849', ' Furcal, Rafael', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('850', ' Galarraga, Andres', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('851', ' Gant, Ron', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('852', ' Garcia, Jesse', ' 0.197', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('853', ' Garcia, Karim', ' 0.297', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('854', ' Garcia, Luis', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('855', ' Garciaparra, Nomar', ' 0.31', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('856', ' German, Esteban', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('857', ' Giambi, Jason', ' 0.314', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('858', ' Giambi, Jeremy', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('859', ' Gibbons, Jay', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('860', ' Gil, Benji', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('861', ' Gil, Geronimo', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('862', ' Giles, Brian', ' 0.298', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('863', ' Giles, Marcus', ' 0.23', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('864', ' Ginter, Keith', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('865', ' Gipson, Charles', ' 0.236', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('866', ' Girardi, Joe', ' 0.226', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('867', ' Glanville, Doug', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('868', ' Glaus, Troy', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('869', ' Gload, Ross', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('870', ' Gomez, Alexis', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('871', ' Gomez, Chris', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('872', ' Gonzalez, Alex', ' 0.225', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('873', ' Gonzalez, Alex', ' 0.248', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('874', ' Gonzalez, Juan', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('875', ' Gonzalez, Luis', ' 0.288', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('876', ' Gonzalez, Raul', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('877', ' Gonzalez, Wiki', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('878', ' Goodwin, Tom', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('879', ' Grabowski, Jason', ' 0.375', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('880', ' Grace, Mark', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('881', ' Graffanino, Tony', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('882', ' Green, Nick', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('883', ' Green, Shawn', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('884', ' Greene, Todd', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('885', ' Greer, Rusty', ' 0.296', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('886', ' Grieve, Ben', ' 0.251', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('887', ' Griffey, Ken', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('888', ' Grissom, Marquis', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('889', ' Grudzielanek, Mark', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('890', ' Guerrero, Vladimir', ' 0.336', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('891', ' Guerrero, Wilton', ' 0.221', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('892', ' Guiel, Aaron', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('893', ' Guillen, Carlos', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('894', ' Guillen, Jose', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('895', ' Gutierrez, Ricky', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('896', ' Guzman, Christian', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('897', ' Hafner, Travis', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('898', ' Hairston, Jerry', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('899', ' Hall, Bill', ' 0.194', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('900', ' Hall, Toby', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('901', ' Halter, Shane', ' 0.239', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('902', ' Hammonds, Jeffrey', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('903', ' Hansen, Dave', ' 0.292', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('904', ' Harris, Lenny', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('905', ' Harris, Willie', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('906', ' Hart, Jason', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('907', ' Haselman, Bill', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('908', ' Hatteberg, Scott', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('909', ' Helms, Wes', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('910', ' Helton, Todd', ' 0.329', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('911', ' Henderson, Rickey', ' 0.223', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('912', ' Henson, Drew', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('913', ' Hermansen, Chad', ' 0.207', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('914', ' Hernandez, Jose', ' 0.288', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('915', ' Hernandez, Ramon', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('916', ' Hidalgo, Richard', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('917', ' Higginson, Bobby', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('918', ' Hill, Bobby', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('919', ' Hillenbrand, Shea', ' 0.293', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('920', ' Hinch, A.J.', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('921', ' Hinske, Eric', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('922', ' Hocking, Denny', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('923', ' Hollandsworth, Todd', ' 0.284', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('924', ' Hollins, Dave', ' 0.118', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('925', ' Hoover, Paul', ' 0.176', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('926', ' Houston, Tyler', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('927', ' Hubbard, Trenidad', ' 0.209', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('928', ' Huckaby, Ken', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('929', ' Hudson, Orlando', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('930', ' Huff, Aubrey', ' 0.313', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('931', ' Hundley, Todd', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('932', ' Hunter, Brian L.', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('933', ' Hunter, Torii', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('934', ' Hyzdu, Adam', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('935', ' Ibanez, Raul', ' 0.294', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('936', ' Infante, Omar', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('937', ' Inge, Brandon', ' 0.202', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('938', ' Izturis, Cesar', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('939', ' Jackson, Damian', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('940', ' Jackson, Ryan', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('941', ' Jenkins, Geoff', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('942', ' Jensen, Marcus', ' 0.114', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('943', ' Jeter, Derek', ' 0.297', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('944', ' Jimenez, D\\\'Angelo', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('945', ' Johnson, Charles', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('946', ' Johnson, Mark', ' 0.209', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('947', ' Johnson, Mark P.', ' 0.137', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('948', ' Johnson, Nick', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('949', ' Johnson, Russ', ' 0.216', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('950', ' Jones, Andruw', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('951', ' Jones, Chipper', ' 0.327', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('952', ' Jones, Jacque', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('953', ' Jordan, Brian', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('954', ' Jose, Felix', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('955', ' Justice, David', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('956', ' Kapler, Gabe', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('957', ' Karros, Eric', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('958', ' Kearns, Austin', ' 0.315', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('959', ' Kelly, Kenny', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('960', ' Kendall, Jason', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('961', ' Kennedy, Adam', ' 0.312', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('962', ' Kent, Jeff', ' 0.313', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('963', ' Kielty, Bobby', ' 0.291', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('964', ' Kingsale, Eugene', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('965', ' Kinkade, Mike', ' 0.38', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('966', ' Klassen, Danny', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('967', ' Klesko, Ryan', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('968', ' Knoblauch, Chuck', ' 0.21', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('969', ' Konerko, Paul', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('970', ' Koskie, Corey', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('971', ' Kotsay, Mark', ' 0.292', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('972', ' Kreuter, Chad', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('973', ' Lamb, David', ' 0.1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('974', ' Lamb, Mike', ' 0.283', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('975', ' Lampkin, Tom', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('976', ' Lane, Jason', ' 0.29', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('977', ' Langerhans, Ryan', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('978', ' Lankford, Ray', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('979', ' Larkin, Barry', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('980', ' LaRocca, Greg', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('981', ' Larson, Brandon', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('982', ' LaRue, Jason', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('983', ' Lawrence, Joe', ' 0.18', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('984', ' Lawton, Matt', ' 0.236', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('985', ' LeCroy, Matt', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('986', ' Ledee, Ricky', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('987', ' Lee, Carlos', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('988', ' Lee, Derrek', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('989', ' Lee, Travis', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('990', ' Leon, Jose', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('991', ' Lesher, Brian', ' 0.132', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('992', ' Lewis, Darren', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('993', ' Lieberthal, Mike', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('994', ' Liefer, Jeff', ' 0.23', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('995', ' Little, Mark', ' 0.208', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('996', ' Lo Duca, Paul', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('997', ' Lockhart, Keith', ' 0.216', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('998', ' Lofton, Kenny', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('999', ' Lombard, George', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1000', ' Long, Terrence', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1001', ' Lopez, Felipe', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1002', ' Lopez, Javy', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1003', ' Lopez, Luis', ' 0.197', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1004', ' Lopez, Mendy', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1005', ' Loretta, Mark', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1006', ' Lowell, Mike', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1007', ' Ludwick, Ryan', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1008', ' Lugo, Julio', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1009', ' Lunar, Fernando', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1010', ' Lunsford, Trey', ' 0.667', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1011', ' Mabry, John', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1012', ' Machado, Robert', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1013', ' Macias, Jose', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1014', ' Mackowiak, Rob', ' 0.244', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1015', ' Magee, Wendell', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1016', ' Magruder, Chris', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1017', ' Mahoney, Mike', ' 0.207', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1018', ' Malloy, Marty', ' 0.12', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1019', ' Marrero, Eli', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1020', ' Martinez, Dave', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1021', ' Martinez, Edgar', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1022', ' Martinez, Ramon', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1023', ' Martinez, Tino', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1024', ' Martinez, Victor', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1025', ' Mateo, Henry', ' 0.174', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1026', ' Mateo, Ruben', ' 0.256', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1027', ' Matheny, Mike', ' 0.244', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1028', ' Matos, Julios', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1029', ' Matos, Luis', ' 0.129', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1030', ' Matthews, Gary', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1031', ' Mayne, Brent', ' 0.236', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1032', ' McCarty, David', ' 0.136', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1033', ' McCracken, Quinton', ' 0.309', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1034', ' McDonald, Donzell', ' 0.182', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1035', ' McDonald, John', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1036', ' McEwing, Joe', ' 0.199', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1037', ' McGriff, Fred', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1038', ' McGuire, Ryan', ' 0.077', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1039', ' McKay, Cody', ' 0.667', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1040', ' McKeel, Walt', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1041', ' McLemore, Mark', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1042', ' Meares, Pat', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1043', ' Meluskey, Mitch', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1044', ' Mench, Kevin', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1045', ' Menechino, Frank', ' 0.205', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1046', ' Merced, Orlando', ' 0.287', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1047', ' Merloni, Lou', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1048', ' Michaels, Jason', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1049', ' Mientkiewicz, Doug', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1050', ' Millar, Kevin', ' 0.306', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1051', ' Miller, Corky', ' 0.254', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1052', ' Miller, Damian', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1053', ' Minor, Damon', ' 0.237', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1054', ' Mirabelli, Doug', ' 0.225', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1055', ' Moeller, Chad', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1056', ' Mohr, Dustan', ' 0.269', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1057', ' Molina, Ben', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1058', ' Molina, Izzy', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1059', ' Molina, Jose', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1060', ' Mondesi, Raul', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1061', ' Monroe, Craig', ' 0.12', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1062', ' Mora, Melvin', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1063', ' Mordecai, Mike', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1064', ' Moriarty, Mike', ' 0.188', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1065', ' Morris, Warren', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1066', ' Mueller, Bill', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1067', ' Munson, Eric', ' 0.186', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1068', ' Murray, Calvin', ' 0.146', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1069', ' Myers, Greg', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1070', ' Nelson, Bryant', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1071', ' Nevin, Phil', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1072', ' Nieves, Jose', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1073', ' Nieves, Wil', ' 0.181', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1074', ' Nixon, Trot', ' 0.256', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1075', ' Norton, Greg', ' 0.22', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1076', ' Nunez, Abraham', ' 0.233', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1077', ' Nunez, Abraham', ' 0.118', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1078', ' O\\\'Leary, Troy', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1079', ' Ochoa, Alex', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1080', ' Offerman, Jose', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1081', ' Ojeda, Augie', ' 0.186', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1082', ' Olerud, John', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1083', ' Olivo, Miguel', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1084', ' Ordaz, Luis', ' 0.223', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1085', ' Ordonez, Magglio', ' 0.32', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1086', ' Ordonez, Rey', ' 0.254', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1087', ' Orie, Kevin', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1088', ' Ortiz, David', ' 0.272', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1089', ' Ortiz, Hector', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1090', ' Ortiz, Jose', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1091', ' Osik, Keith', ' 0.16', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1092', ' Overbay, Lyle', ' 0.1', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1093', ' Owens, Eric', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1094', ' Ozuna, Pablo', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1095', ' Palmeiro, Orlando', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1096', ' Palmeiro, Rafael', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1097', ' Palmer, Dean', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1098', ' Paquette, Craig', ' 0.194', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1099', ' Patterson, Corey', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1100', ' Paul, Josh', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1101', ' Payton, Jay', ' 0.303', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1102', ' Pelaez, Alex', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1103', ' Pellow, Kip', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1104', ' Pena, Carlos', ' 0.242', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1105', ' Pena, Wily Mo', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1106', ' Perez, Eddie', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1107', ' Perez, Eduardo', ' 0.201', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1108', ' Perez, Neifi', ' 0.236', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1109', ' Perez, Timoniel', ' 0.295', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1110', ' Perez, Tomas', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1111', ' Perry, Chan', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1112', ' Perry, Herbert', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1113', ' Petrick, Ben', ' 0.211', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1114', ' Phelps, Josh', ' 0.309', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1115', ' Phillips, Brandon', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1116', ' Phillips, Jason', ' 0.368', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1117', ' Piatt, Adam', ' 0.234', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1118', ' Piazza, Mike', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1119', ' Pickering, Calvin', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1120', ' Pierre, Juan', ' 0.287', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1121', ' Pierzynski, A.J.', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1122', ' Podsednik, Scott', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1123', ' Polanco, Placido', ' 0.288', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1124', ' Posada, Jorge', ' 0.268', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1125', ' Pratt, Todd', ' 0.311', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1126', ' Prince, Tom', ' 0.224', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1127', ' Pujols, Albert', ' 0.314', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1128', ' Punto, Nick', ' 0.167', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1129', ' Quinn, Mark', ' 0.237', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1130', ' Raines, Tim', ' 0.191', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1131', ' Ramirez, Aramis', ' 0.234', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1132', ' Ramirez, Julio', ' 0.281', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1133', ' Ramirez, Manny', ' 0.349', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1134', ' Randa, Joe', ' 0.282', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1135', ' Ransom, Cody', ' 0.667', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1136', ' Reboulet, Jeff', ' 0.208', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1137', ' Redmond, Mike', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1138', ' Reese, Pokey', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1139', ' Relaford, Desi', ' 0.267', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1140', ' Renteria, Edgar', ' 0.305', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1141', ' Restovich, Mike', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1142', ' Richard, Chris', ' 0.232', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1143', ' Rios, Armando', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1144', ' Rivas, Luis', ' 0.256', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1145', ' Rivera, Juan', ' 0.265', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1146', ' Rivera, Mike', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1147', ' Rivera, Ruben', ' 0.209', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1148', ' Roberts, Brian', ' 0.227', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1149', ' Roberts, Dave', ' 0.277', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1150', ' Robinson, Kerry', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1151', ' Rodriguez, Alex', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1152', ' Rodriguez, Henry', ' 0.05', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1153', ' Rodriguez, Ivan', ' 0.314', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1154', ' Rogers, Ed', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1155', ' Rolen, Scott', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1156', ' Rollins, Jimmy', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1157', ' Rolls, Damian', ' 0.292', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1158', ' Romano, Jason', ' 0.253', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1159', ' Ross, David', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1160', ' Rowand, Aaron', ' 0.258', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1161', ' Ruan, Wilken', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1162', ' Rushford, Jim', ' 0.143', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1163', ' Ryan, Mike', ' 0.091', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1164', ' Sadler, Donnie', ' 0.163', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1165', ' Saenz, Olmedo', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1166', ' Salazar, Oscar', ' 0.19', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1167', ' Salmon, Tim', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1168', ' Sanchez, Alex', ' 0.289', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1169', ' Sanchez, Freddy', ' 0.188', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1170', ' Sanchez, Rey', ' 0.286', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1171', ' Sandberg, Jared', ' 0.229', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1172', ' Sanders, Reggie', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1173', ' Santiago, Benito', ' 0.278', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1174', ' Santiago, Ramon', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1175', ' Schneider, Brian', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1176', ' Scutaro, Marcos', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1177', ' Sears, Todd', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1178', ' Segui, David', ' 0.263', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1179', ' Selby, Bill', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1180', ' Sexson, Richie', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1181', ' Sheets, Andy', ' 0.248', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1182', ' Sheffield, Gary', ' 0.307', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1183', ' Shinjo, Tsuyoshi', ' 0.238', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1184', ' Shumpert, Terry', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1185', ' Sierra, Ruben', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1186', ' Simon, Randall', ' 0.301', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1187', ' Singleton, Chris', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1188', ' Smith, Bobby', ' 0.175', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1189', ' Smith, Jason', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1190', ' Snead, Esix', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1191', ' Snelling, Chris', ' 0.148', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1192', ' Snow, J.T.', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1193', ' Snyder, Earl', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1194', ' Soriano, Alfonso', ' 0.3', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1195', ' Sosa, Sammy', ' 0.288', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1196', ' Spencer, Shane', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1197', ' Spiezio, Scott', ' 0.285', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1198', ' Spivey, Junior', ' 0.301', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1199', ' Stairs, Matt', ' 0.244', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1200', ' Stevens, Lee', ' 0.204', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1201', ' Stewart, Shannon', ' 0.303', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1202', ' Stinnett, Kelly', ' 0.226', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1203', ' Stynes, Chris', ' 0.241', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1204', ' Surhoff, B.J.', ' 0.293', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1205', ' Sutton, Larry', ' 0.105', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1206', ' Suzuki, Ichiro', ' 0.321', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1207', ' Swann, Pedro', ' 0.083', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1208', ' Sweeney, Mark', ' 0.169', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1209', ' Sweeney, Mike', ' 0.34', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1210', ' Taguchi, So', ' 0.4', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1211', ' Tarasco, Tony', ' 0.25', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1212', ' Tatis, Fernando', ' 0.228', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1213', ' Taubensee, Eddie', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1214', ' Taylor, Reggie', ' 0.254', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1215', ' Tejada, Miguel', ' 0.308', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1216', ' Thames, Marcus', ' 0.231', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1217', ' Thomas, Frank', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1218', ' Thome, Jim', ' 0.304', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1219', ' Thompson, Ryan', ' 0.248', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1220', ' Thurston, Joe', ' 0.462', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1221', ' Toca, Jorge', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1222', ' Torcato, Tony', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1223', ' Torrealba, Steve', ' 0.059', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1224', ' Torrealba, Yorvit', ' 0.279', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1225', ' Torres, Andres', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1226', ' Trammell, Bubba', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1227', ' Truby, Chris', ' 0.215', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1228', ' Tucker, Michael', ' 0.248', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1229', ' Tyner, Jason', ' 0.214', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1230', ' Ugueto, Luis', ' 0.217', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1231', ' Uribe, Juan', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1232', ' Valdez, Mario', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1233', ' Valent, Eric', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1234', ' Valentin, Javier', ' 0.5', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1235', ' Valentin, John', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1236', ' Valentin, Jose', ' 0.249', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1237', ' Vander Wal, John', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1238', ' Varitek, Jason', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1239', ' Vaughn, Greg', ' 0.163', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1240', ' Vaughn, Mo', ' 0.259', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1241', ' Vazquez, Ramon', ' 0.274', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1242', ' Velarde, Randy', ' 0.226', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1243', ' Ventura, Robin', ' 0.247', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1244', ' Vidro, Jose', ' 0.315', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1245', ' Vina, Fernando', ' 0.27', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1246', ' Vizcaino, Jose', ' 0.303', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1247', ' Vizquel, Omar', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1248', ' Walbeck, Matt', ' 0.235', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1249', ' Walker, Larry', ' 0.338', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1250', ' Walker, Todd', ' 0.299', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1251', ' Ward, Daryle', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1252', ' Wathan, Dusty', ' 0.6', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1253', ' Wells, Vernon', ' 0.275', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1254', ' Werth, Jayson', ' 0.261', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1255', ' Wesson, Barry', ' 0.2', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1256', ' White, Rondell', ' 0.24', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1257', ' Widger, Chris', ' 0.297', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1258', ' Wigginton, Ty', ' 0.302', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1259', ' Wilkerson, Brad', ' 0.266', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1260', ' Williams, Bernie', ' 0.333', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1261', ' Williams, Gerald', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1262', ' Williams, Matt', ' 0.26', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1263', ' Wilson, Craig', ' 0.264', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1264', ' Wilson, Dan', ' 0.295', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1265', ' Wilson, Enrique', ' 0.181', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1266', ' Wilson, Jack', ' 0.252', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1267', ' Wilson, Preston', ' 0.243', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1268', ' Wilson, Tom', ' 0.257', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1269', ' Wilson, Vance', ' 0.245', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1270', ' Winn, Randy', ' 0.298', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1271', ' Wise, DeWayne', ' 0.179', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1272', ' Womack, Tony', ' 0.271', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1273', ' Woodward, Chris', ' 0.276', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1274', ' Wooten, Shawn', ' 0.292', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1275', ' Wright, Ron', ' 0', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1276', ' Young, Dmitri', ' 0.284', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1277', ' Young, Eric', ' 0.28', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1278', ' Young, Kevin', ' 0.246', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1279', ' Young, Michael', ' 0.262', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1280', ' Zaun, Greg', ' 0.222', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1281', ' Zeile, Todd', ' 0.273', '2005-01-01');
+INSERT INTO `testtbl` VALUES ('1282', ' Zinter, Alan', ' 0.136', '2005-01-01');
diff --git a/dojox/grid/tests/support/yahoo_search.js b/dojox/grid/tests/support/yahoo_search.js
new file mode 100644
index 0000000..84a2429
--- /dev/null
+++ b/dojox/grid/tests/support/yahoo_search.js
@@ -0,0 +1,134 @@
+// model that works with Yahoo Search API
+(function(){
+var nop = function(){};
+dojo.declare("dojox.grid._data.yahooSearch", dojox.grid._data.dynamic, 
+	function(inFields, inData) {
+		this.rowsPerPage = 20;
+		this.fieldNames = [];
+		for (var i=0, f; (f=inFields[i]); i++)
+			this.fieldNames.push(f.name);
+	}, {
+	clearData: function() {
+		turbo.widgets.TurboGrid.data.dynamic.prototype.clearData.apply(this, arguments);
+	},
+	// server send / receive
+	encodeParam: function(inName, inValue) {
+		return turbo.printf('&%s=%s', inName, inValue);
+	},
+	getParams: function(inParams) {
+		var url = this.url;
+		url += '?appid=turboajax';
+		inParams = inParams || {};
+		inParams.output = 'json';
+		inParams.results = this.rowsPerPage;
+		inParams.query = turbo.$('searchInput').value.replace(/ /g, '+');
+		for (var i in inParams)
+			if (inParams[i] != undefined)
+				url += this.encodeParam(i, inParams[i]);
+		return url;
+	},
+	send: function(inAsync, inParams, inOnReceive, inOnError) {
+		var p = this.getParams(inParams);
+		dojo.io.bind({
+			url: "support/proxy.php",
+			method: "post",
+			content: {url: p },
+			contentType: "application/x-www-form-urlencoded; charset=utf-8",
+			mimetype: 'text/json',
+			sync: !inAsync,
+			load: turbo.bindArgs(this, "receive", inOnReceive, inOnError),
+			error: turbo.bindArgs(this, "error", inOnError) 
+		});
+		this.onSend(inParams);
+	},
+	receive: function(inOnReceive, inOnError, inEvt, inData) {
+		try {
+			inData = inData.ResultSet;
+			inOnReceive(inData);
+			this.onReceive(inData);					
+		} catch(e) {
+			if (inOnError)
+				inOnError(inData);
+		}
+	},
+	error: function(inOnError, inTyp, inErr) {
+		var m = 'io error: ' + inErr.message;
+		alert(m);
+		if (inOnError)
+			inOnError(m);
+	},
+	fetchRowCount: function(inCallback) {
+		this.send(true, inCallback );
+	},
+	// request data 
+	requestRows: function(inRowIndex, inCount)	{
+		inRowIndex = (inRowIndex == undefined ? 0 : inRowIndex);
+		var params = { 
+			start: inRowIndex + 1
+		}
+		this.send(true, params, turbo.bindArgs(this, this.processRows));
+	},
+	// server callbacks
+	processRows: function(inData) {
+		for (var i=0, l=inData.totalResultsReturned, s=inData.firstResultPosition; i<l; i++) {
+			this.setRow(inData.Result[i], s - 1 + i);
+		}
+		// yahoo says 1000 is max results to return
+		var c = Math.min(1000, inData.totalResultsAvailable);
+		if (this.count != c) {
+			this.setRowCount(c);
+			this.allChange();
+			this.onInitializeData(inData);
+		}
+	},
+	getDatum: function(inRowIndex, inColIndex) {
+		var row = this.getRow(inRowIndex);
+		var field = this.fields.get(inColIndex);
+		return (inColIndex == undefined ? row : (row ? row[field.name] : field.na));
+	},
+	// events
+	onInitializeData: nop,
+	onSend: nop,
+	onReceive: nop
+});
+
+// report
+modelChange = function() {
+	var n = turbo.$('rowCount');
+	if (n)
+		n.innerHTML = turbo.printf('about %s row(s)', model.count);
+}
+
+
+// some data formatters
+formatLink = function(inData, inRowIndex) {
+	if (!inData[0] || !inData[1])
+		return ' ';
+	return turbo.supplant('<a target="_blank" href="{href}">{text}</a>', {href: inData[0], text: inData[1] });
+};
+
+formatImage = function(inData, inRowIndex) {
+	if (!inData[0] || !inData[1])
+		return ' ';
+	var o = {
+		href: inData[0], 
+		src: inData[1].Url,
+		width: inData[1].Width,
+		height: inData[1].Height
+	}	
+	return turbo.supplant('<a href="{href}" target="_blank"><img border=0 src="{src}" width="{width}" height="{height}"></a>', o);
+};
+
+formatDate = function(inDatum, inRowIndex) {
+	if (inDatum == '')
+		return ' ';
+	var d = new Date(inDatum * 1000);
+	return turbo.printf('%s/%s/%s', d.getMonth(), d.getDate(), d.getFullYear());
+};
+
+formatDimensions = function(inData, inRowIndex) {
+	if (!inData[0] || !inData[1])
+		return ' ';
+	return inData[0] + ' x ' + inData[1];
+}
+})();
diff --git a/dojox/grid/tests/test_backwards_compatibility.html b/dojox/grid/tests/test_backwards_compatibility.html
new file mode 100644
index 0000000..ad5a318
--- /dev/null
+++ b/dojox/grid/tests/test_backwards_compatibility.html
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Backwards Compatibility</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../_grid/Grid.css";
+		@import "../_grid/tundraGrid.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid,#grid2 {
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojox.grid.Grid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		function getRow(inRowIndex){
+			return ' ' + inRowIndex;
+		}
+		var layout = [[
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6'},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+		var layoutCountries = [
+			// view 0
+			{ type: 'dojox.GridRowView', width: '20px' },
+			// view 1
+			{ cells: [[{ name: "Row", get: getRow, width: 5}]], noscroll: true},
+			// view 2
+			{ cells: [[
+				{ field: 0, width: 'auto' },
+				{ width: 8 }
+			]]}
+		];
+	</script>
+</head>
+<body>
+<div class="heading">dojox.grid.Grid Backwards Compatibility Test</div>
+	<div>A new grid</div>
+	<div jsid="grid" id="grid" dojoType="dojox.grid.DataGrid" store="test_store" query="{ id: '*' }" structure="layout" rowSelector="20px"></div>
+	<span dojoType="dojo.data.ItemFileReadStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<span dojoType="dojox.grid.data.DojoData" 
+		jsId="dataModel2" 
+		rowsPerPage="20"
+		store="jsonStore" 
+		query="{ name : '*' }">
+	</span>
+	<div>An old grid</div>
+	<div id="grid2" dojoType="dojox.Grid" elasticView="2" 
+		model="dataModel2" structure="layoutCountries">
+	</div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_change_structure.html b/dojox/grid/tests/test_change_structure.html
new file mode 100644
index 0000000..b5e5fee
--- /dev/null
+++ b/dojox/grid/tests/test_change_structure.html
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid._Grid Change Structure Example</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid { 
+			border: 1px solid #333;
+			width: 48em;
+			height: 30em;
+		}
+		
+		#grid .dojoxGridCell {
+			text-align: center;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid._Grid");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript">
+
+		// get can return data for a cell of the grid
+		function get(inRowIndex) {
+			return [this.index, inRowIndex].join(', ');
+		}
+
+		// grid structure
+		// a grid view is a group of columns
+		
+		// a view without scrollbars
+		var view0 = {
+			noscroll: true,
+			cells: [
+				{name: 'Alpha', value: '<input name="" type="checkbox" value="0">'},
+				{name: 'Beta', get: get, width: 4.5}
+		]};
+		
+		var view1 = [
+				{name: 'Apple', value: '<button>Apple</button>'},
+				{name: 'Banana', get: get},
+				{name: 'Beans', value: 'Happy to be grid!'},
+				{name: 'Kiwi', get: get},
+				{name: 'Orange', value: '<img src="images/flatScreen.gif" height="48" width="48">'},
+				{name: 'Pear', get: get},
+				{name: 'Tomato', width: 20, value: '<input name="" type="file">'}
+		];
+		
+		var view2 = {
+			noscroll: true,
+			cells: [
+				[
+					{name: 'Alpha', value: '<input name="" type="checkbox" value="0">', rowSpan: 2},
+					{name: 'Beta', get: get, width: 4.5}
+				],[
+					{name: 'Gamma', get: get}
+				],[
+					{name: 'Epsilon', value: '<button>Epsilon</button>', colSpan: 2}
+				]
+			]
+		}
+		
+		var view3 = [
+			[	
+				{name: 'Apple', value: '<button>Apple</button>', rowSpan: 3},
+				{name: 'Banana', get: get, width: 20},
+				{name: 'Kiwi', get: get, width: 20},
+				{name: 'Pear', get: get, width: 20}
+			],[
+				{name: 'Beans', value: 'Happy to be grid!'},
+				{name: 'Orange', value: '<img src="images/flatScreen.gif" height="48" width="48">'},
+				{name: 'Tomato', value: '<input name="" type="file">'}
+			],[
+				{name: 'Zuchini', value: '<span style="letter-spacing: 10em;">wide</span>', colSpan: 3}
+			]
+		];
+		
+		
+		// a grid structure is an array of views.
+		// By default the middle view will be 'elastic', sized to fit the remaining space left by other views
+		// grid.elasticView can also be manually set
+		var structure = [ view0, view1 ];
+		var structure2 = [ view2, view3 ];
+		
+		
+		var l2 = false;
+		toggleStructure = function() {
+			l2 = !l2;
+			grid.scrollToRow(0);
+			grid.attr('structure', l2 ? structure2 : structure);
+		}
+</script>
+</head>
+<body>
+<div class="heading">dojox.grid._Grid Change Structure Example</div>
+<p>
+	<button onclick="toggleStructure()">Change Structure</button>
+</p>	
+<div id="grid" jsid="grid" dojoType="dojox.grid._Grid" structure="structure" rowSelector="20px" rowCount="100000" elasticView="2"></div>
+
+</body>
+</html>
diff --git a/dojox/grid/tests/test_custom_sort.html b/dojox/grid/tests/test_custom_sort.html
new file mode 100644
index 0000000..59812ba
--- /dev/null
+++ b/dojox/grid/tests/test_custom_sort.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Custom Sort Test - dojox.grid.Grid</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid {
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		test_store.comparatorMap = {};
+		test_store.comparatorMap["col1"] = function(a, b){
+			var ret = 0;
+			// We want to map these by what the priority of these items are, not by alphabetical.
+			// So, custom comparator.
+			var enumMap = { "important": 0, "normal": 1, "note": 2 };
+			if (enumMap[a] > enumMap[b]) {
+				ret = 1;
+			}
+			if (enumMap[a] < enumMap[b]) {
+				ret = -1;
+			}
+			return ret;
+		}
+		var layout = [[
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6'},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+</script>
+</head>
+<body>
+<div class="heading">dojox.grid.Grid Custom Sort Test</div>
+<br />
+<b>Column 1</b>'s data field has a custom sorter that sorts by the status level rather than alphebetically
+<br /><br />
+<div id="grid" jsid="grid" dojoType="dojox.grid.DataGrid" store="test_store" structure="layout"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_data_grid.html b/dojox/grid/tests/test_data_grid.html
new file mode 100644
index 0000000..6760e87
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		#grid, #grid2 {
+			width: 65em;
+			height: 25em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.DataGrid Basic Test</div>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" 
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_data_grid_autoheight.html b/dojox/grid/tests/test_data_grid_autoheight.html
new file mode 100644
index 0000000..4c88a9c
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_autoheight.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Autoheight test</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+			margin-top: 1em;
+		}
+		.grid {
+			width: 65em;
+			height: 25em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<div class="heading">No autoHeight (takes height of the div)</div>
+	<table dojoType="dojox.grid.DataGrid"
+		class="grid" store="jsonStore" 
+		query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+
+	<div class="heading">autoHeight=true</div>
+	<table dojoType="dojox.grid.DataGrid"
+		class="grid" store="jsonStore" autoHeight="true"
+		query="{ type: 'city' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+
+	<div class="heading">autoHeight=5 (7 elements)</div>
+	<table dojoType="dojox.grid.DataGrid"
+		class="grid" store="jsonStore" autoHeight="5"
+		query="{ type: 'city' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+
+	<div class="heading">autoHeight=10 (7 elements)</div>
+	<table dojoType="dojox.grid.DataGrid"
+		class="grid" store="jsonStore" autoHeight="10"
+		query="{ type: 'city' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_data_grid_autowidth.html b/dojox/grid/tests/test_data_grid_autowidth.html
new file mode 100644
index 0000000..36750c0
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_autowidth.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Automatic Width</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		.grid {
+			width: 85%;
+			height: 20em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+
+		dojo.addOnLoad(function(){
+			// A quick-and-dirty resize of the grid when the window resizes to
+			// test that percentages "stick" when they are supposed to.
+			dojo.connect(window, "resize", grid2, "resize");
+		});
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.DataGrid Automatic Width Test</div>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" class="grid" autoWidth="true"
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="30em">Country/Continent Name</th>
+				<th field="type" width="10em">Type</th>
+				<th field="population" width="10em">Population</th>
+			</tr>
+		</thead>
+	</table>
+	<div class="heading">Auto Width with % column widths (and fixed initial grid width)</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid1" id="grid1" class="grid" autoWidth="true" initialWidth="50em"
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="50%">Country/Continent Name</th>
+				<th field="type" width="25%">Type</th>
+				<th field="population" width="25%">Population</th>
+			</tr>
+		</thead>
+	</table>
+	<div class="heading">Auto Width with % column widths (and % initial grid width)</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid2" id="grid2" class="grid" autoWidth="true" initialWidth="85%"
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="50%">Country/Continent Name</th>
+				<th field="type" width="25%">Type</th>
+				<th field="population" width="25%">Population</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
+
diff --git a/dojox/grid/tests/test_data_grid_edit.html b/dojox/grid/tests/test_data_grid_edit.html
new file mode 100644
index 0000000..f97b06b
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_edit.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Basic Editing</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		#grid, #grid2 {
+			width: 65em;
+			height: 25em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.DataGrid Basic Editing Test</div>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" 
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto" cellType="dojox.grid.cells.Select" options="country,city,continent" editable="true">Type</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_data_grid_edit_dijit.html b/dojox/grid/tests/test_data_grid_edit_dijit.html
new file mode 100644
index 0000000..d24f594
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_edit_dijit.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Dijit Editing</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/tundra/tundra_rtl.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		#grid, #grid2 {
+			width: 65em;
+			height: 25em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojox.grid.cells.dijit");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.DataGrid Dijit Editing Test</div>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" 
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto" cellType="dojox.grid.cells.ComboBox" options="country,city,continent" editable="true">Type</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_data_grid_edit_large_resultset.html b/dojox/grid/tests/test_data_grid_edit_large_resultset.html
new file mode 100644
index 0000000..5337a35
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_edit_large_resultset.html
@@ -0,0 +1,102 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Editing with large result set</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		body {
+			font-family: Tahoma, Arial, Helvetica, sans-serif;
+			font-size: 11px;
+		}
+		.dojoxGridRowEditing td {
+			background-color: #F4FFF4;
+		}
+		.dojoxGrid input, .dojoxGrid select, .dojoxGrid textarea {
+			margin: 0;
+			padding: 0;
+			border-style: none;
+			width: 100%;
+			font-size: 100%;
+			font-family: inherit;
+		}
+		.dojoxGrid input { }
+		.dojoxGrid select { }
+		.dojoxGrid textarea { }
+		#controls {
+			padding: 6px 0;
+		}
+		#grid, #grid2 {
+			width: 850px;
+			height: 350px;
+			border: 1px solid silver;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layoutNumbers = [
+			// view 1
+			{ cells: [ new dojox.grid.cells.RowIndex({width: 5}) ], noscroll: true},
+			// view 2
+			[
+				{ field: 'id', width: 8 },
+				{ field: 'label', editable: 'true', width: 'auto' }
+			]
+		];
+
+		removeItem = function() {
+			// Removes the first item in the store
+			// Grid should reflect removal of the first item and items should be re-indexed
+			jsonStore.deleteItem(dataStore.data[0].__dojo_data_item);
+		}
+		
+		var i = 0;
+		addItem = function() {
+			grid.addRow({name: "country"+(i++), type: "country"});
+		}
+		addItemToStore = function() {
+			// Adds a new item to the store
+			// Grid should reflect the new item.
+			jsonStore.newItem({id: "country"+(i++), label: "country"});
+		}
+	</script>
+</head>
+<body class="tundra">
+	<h2>
+		dojox.grid.DataGrid Basic Editing test
+	</h2>
+	<div id="controls">
+		<button onclick="grid.render()">Refresh</button>   
+		<button onclick="grid.edit.focusEditor()">Focus Editor</button>
+		<button onclick="grid.focus.next()">Next Focus</button>   
+		<button onclick="jsonStore.revert()">Revert (Store)</button>
+		<button onclick="removeItem()">Remove (Store)</button>
+		<button onclick="addItemToStore()">Add (Store)</button>   
+		<button onclick="grid.removeSelectedRows()">Remove</button>   
+		<button onclick="grid.edit.apply()">Apply</button>
+		<button onclick="grid.edit.cancel()">Cancel</button>   
+		<button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button> 
+	</div>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		 jsId="jsonStore" url="support/numbers.json">
+	</span>
+	<div id="grid" jsId="grid" dojoType="dojox.grid.DataGrid" elasticView="2" query="{ id: '*' }"
+		 rowsPerPage="20" store="jsonStore" structure="layoutNumbers" rowSelector="20px">
+	</div>
+	<div id="grid2" jsId="grid2" dojoType="dojox.grid.DataGrid" elasticView="2" query="{ id: '*' }"
+		 rowsPerPage="20" store="jsonStore" structure="layoutNumbers" rowSelector="20px">
+	</div>
+</body>
+</html>
+
+
+
diff --git a/dojox/grid/tests/test_data_grid_empty.html b/dojox/grid/tests/test_data_grid_empty.html
new file mode 100644
index 0000000..97204da
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_empty.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd"> 
+<html> 
+<head> 
+	<title>dojox.grid.DataGrid with an empty result set</title> 
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta> 
+	<style type="text/css"> 
+		@import "../../../dojo/resources/dojo.css"; 
+		@import "../resources/Grid.css"; 
+		#grid { 
+			width: 65em; 
+			height: 25em; 
+		}
+	</style> 
+	<script type="text/javascript" src="../../../dojo/dojo.js"  
+		djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script> 
+	<script type="text/javascript"> 
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid"); 
+		dojo.require("dojo.data.ItemFileWriteStore"); 
+		dojo.require("dojo.parser"); 
+		dojo.require("dijit.form.Button"); 
+	</script> 
+	<script type="text/javascript"> 
+		var layoutCountries = [ 
+			// view 1 
+			{ cells: [ new dojox.grid.cells.RowIndex({width: 5}) ], noscroll: true}, 
+			// view 2 
+			[ 
+				{ name: "field 0", field: 'name', width: 8 }, 
+				{ name: "field 1", field: 'type', width: 8 } 
+			]
+		];
+		
+		var emptyData = { identifier: 'name', label: 'name', items: []}; 
+		var jsonStore = new dojo.data.ItemFileWriteStore({data: emptyData}); 
+		var numItems = 0; 
+	</script> 
+</head> 
+<body class="tundra"> 
+		<h5>dojox.grid.DataGrid using initially-empty write stores and then adding an item.  Item should show up correctly (no "..."s) when added.</h5> 
+		<br>
+		<div id="grid" dojoType="dojox.grid.DataGrid" elasticView="2" query="{ name: '*' }" rowsPerPage="20"
+			store="jsonStore" structure="layoutCountries" rowSelector="20px"> 
+		</div> 
+		<button dojoType="dijit.form.Button"> 
+			<script type="dojo/method" event="onClick"> 
+				numItems++; 
+				dojo.connect(jsonStore, "fetch", function(){
+					console.error("Calling newItem should not trigger a fetch.");
+					throw new Error("Calling newItem should not trigger a fetch.");
+				});
+				jsonStore.newItem({
+					name: numItems + "-person Land", 
+					type: "city", 
+					population: numItems
+				}); 
+			</script> 
+			Add Item 
+		</button> 
+</body> 
+</html> 
diff --git a/dojox/grid/tests/test_data_grid_hideHdr.html b/dojox/grid/tests/test_data_grid_hideHdr.html
new file mode 100644
index 0000000..8508c7a
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_hideHdr.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		#grid, #grid2 {
+			width: 65em;
+			height: 25em;
+			padding: 1px;
+		}
+		.dojoxGridHeader { display:none; }
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.DataGrid Basic Test</div>
+	<p><a href="http://docs.dojocampus.org/dojox/grid">grid docs</a> (focusable element before grid)</p>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" 
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+	<p> <a href="http://docs.dojocampus.org/dojox/grid">grid docs</a> (focusable element after grid)</p>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_data_grid_large.html b/dojox/grid/tests/test_data_grid_large.html
new file mode 100644
index 0000000..c732850
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_large.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Large Data Set</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		#grid, #grid2 {
+			width: 65em;
+			height: 25em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		// a grid layout is an array of views.
+		var layout = [
+			[
+				{ name: 'Column 0', field: 'id' },
+				{ name: 'Column 1', field: 'col1' },
+				{ name: 'Column 2', field: 'col2' },
+				{ name: 'Column 3', field: 'col3', width: '150px' },
+				{ name: 'Column 4', field: 'col4' }
+			],
+			[
+				{name: 'Column 5', field: 'col5' },
+				{name: 'Column 6', field: 'col6' },
+				{name: 'Column 7', field: 'col7' },
+				{name: 'Column 8', field: 'col3', colSpan: 2}
+			]
+		];
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.DataGrid Large Data Set Test</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" 
+		store="test_store" query="{ id: '*' }" rowsPerPage="20" structure="layout" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_data_grid_large_flex_cells.html b/dojox/grid/tests/test_data_grid_large_flex_cells.html
new file mode 100644
index 0000000..ea0a20c
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_large_flex_cells.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Large Data Set with Flex cells</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		#grid {
+			width: 100%;
+			height: 25em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: false"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		// a grid layout is an array of views.
+		var layout = [
+			[
+				{ name: 'Column 0', field: 'id', width: '10%' },
+				{ name: 'Column 1', field: 'col1', width: '10%' },
+				{ name: 'Column 2', field: 'col2', width: '10%' },
+				{ name: 'Column 3', field: 'col3', width: '10%' },
+				{ name: 'Column 4', field: 'col4', width: '20%' },
+				{ name: 'Column 5', field: 'col5', width: '10%' },
+				{ name: 'Column 6', field: 'col6', width: '10%' },
+				{ name: 'Column 7', field: 'col7', width: '10%' },
+				{ name: 'Column 8', field: 'col3', width: '10%' }
+			]
+		];
+		// Set to true in order to kick off profiling startup and resizes in
+		// firebug
+		var doProfiling = false;
+		
+		dojo.addOnLoad(function(){
+			doProfiling = dojo.isMoz && doProfiling;
+			if(doProfiling){
+				console.profile("Startup/Creation");
+				window.profiling = true;
+			}
+			dojo.parser.parse();
+			grid.connect(window, "onresize", function(){
+				if(doProfiling){
+					console.profile("Resize");
+					window.profiling = true;
+				}
+				this.resize();
+				if(doProfiling){
+					window.setTimeout(function(){
+						console.profileEnd(); 
+						delete window.profiling;
+					}, 1000);
+				}
+			});
+			if(doProfiling){
+				window.setTimeout(function(){
+					console.profileEnd(); 
+					delete window.profiling;
+				}, 1000);
+			}
+		});
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.DataGrid Large Data Set Test with Flex Cells</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" columnReordering="true" 
+		store="test_store" query="{ id: '*' }" rowsPerPage="20" structure="layout">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_data_grid_multiStores.html b/dojox/grid/tests/test_data_grid_multiStores.html
new file mode 100644
index 0000000..55fc65f
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_multiStores.html
@@ -0,0 +1,238 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.DataGrid using multiple store implementations.</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		
+		#grid, #grid2, #grid3, #grid4, #grid5, #grid6{
+			width: 65em;
+			height: 25em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dojox.data.CsvStore");
+		dojo.require("dojox.data.XmlStore");
+		dojo.require("dojox.data.FlickrStore");
+		dojo.require("dojox.data.OpmlStore");
+		dojo.require("dojox.data.HtmlStore");
+		dojo.require("dojo.parser");
+	</script>
+
+	<script type="text/javascript">
+		var formatHref = function(value, rowIndex) {
+			return "<a href=\"" + value + "\" target=\"_blank\">Image Link</a>";
+		}
+
+		var rowView = { cells: [ new dojox.grid.cells.RowIndex({ width: 5 }) ], noscroll: true };
+
+		var layoutMovies = [
+			// view 1
+			rowView,
+			// view 2
+			[
+				{ field: "Title", width: 'auto' },
+				{ field: "Year", width: 5 },
+				{ field: "Producer", width: 20 }
+			]
+		];
+		
+		var layoutCountries = [
+			// view 1
+			rowView,
+			// view 2
+			[
+				{ field: 'name', width: 'auto' },
+				{ field: 'type', width: 8 }
+			]
+		];
+
+		var layoutBooks = [
+			// view 1
+			rowView,
+			// view 2
+			[
+				{ field: "title", width: 'auto' },
+				{ field: "isbn", width: '8' }
+			]
+		];
+
+		//Lay out the Flickr data so one column is a URL.  This makes use of the
+		//get function of a cell.
+		var layoutFlickrData = [
+			// view 1
+			rowView,
+			// view 2
+			[
+				{ name: "Title", field: "title", width: 'auto' },
+				{ name: "Image URL", field: "imageUrl", width: '15', formatter: formatHref}
+			]
+		];
+
+		var layoutOpmlData = [
+			// view 1
+			rowView,
+			// view 2
+			[
+				{ name: 'Name', field: 'text', width: 'auto'},
+				{ name: 'Type', field: 'type', width: '8' }
+			]
+		];
+
+		var layoutHtmlTable = [
+			// view 1
+			rowView,
+			// view 2
+			[
+				{ name: 'Column 1', field: 'Column 1', width: 'auto'},
+				{ name: 'Column 2', field: 'Column 2', width: 'auto'},
+				{ name: 'Column 3', field: 'Column 3', width: 'auto'},
+				{ name: 'Column 4', field: 'Column 4', width: 'auto'}
+			]
+		];
+	</script>
+</head>
+<body class="tundra">
+	<h1>dojox.grid.DataGrid using multiple store implementations.</h1>
+	<p>
+		This page demonstrates the Grid can display data accessed by dojo.data
+		implementing Datastores.  Each of the datastores used stores data in a
+		different format, and as this test and demonstration page shows, the
+		logic for rendering the data is virtually identical.  You define your
+		source store and then you define the layout, which maps the data
+		attribute names to columns in the grid.  You can even perform
+		cusomization of what is displayed, as demonstrated in the
+		dojox.data.FlickrStore layout.  The image url is displayed as a
+		clickable link that opens a new page.
+	</p>
+	<p>
+		The choice of stores used were ones that did not require back end
+		services to function for sake of simplicity.  There is no reason that
+		dojox.data.QueryReadStore could not be used with grid as well, it just
+		requires a back end service to send it the query results.
+	</p>
+	<p><b>Stores used:</b></p>
+	<ul>
+		<li>dojo.data.ItemFileReadStore</li>
+		<li>dojox.data.CsvStore</li>
+		<li>dojox.data.XmlStore</li>
+		<li>dojox.data.FlickrStore</li>
+		<li>dojox.data.OpmlStore</li>
+		<li>dojox.data.HtmlTableStore</li>
+	</ul>
+
+	<h2>dojo.data.ItemFileReadStore:</h2>
+	<i>Displays a list of countries through ItemFileReadStore format.</i>
+	<span dojoType="dojo.data.ItemFileReadStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<div id="grid" dojoType="dojox.grid.DataGrid" elasticView="2" query="{ name: '*' }" rowsPerPage="20"
+		store="jsonStore" structure="layoutCountries" rowSelector="20px">
+	</div>
+
+
+	<h2>dojox.data.CsvStore:</h2>
+	<i>Displays a list of movies that were stored in CSV format.</i>
+	<span dojoType="dojox.data.CsvStore" 
+		jsId="csvStore" url="support/movies.csv">
+	</span>
+	<div id="grid2" dojoType="dojox.grid.DataGrid" elasticView="2" query="{ Title: '*' }" rowsPerPage="5"
+		store="csvStore" structure="layoutMovies" rowSelector="20px">
+	</div>
+
+	<h2>dojox.data.XmlStore:</h2>
+	<i>Displays a list of books that were stored in XML format.</i>
+	<span dojoType="dojox.data.XmlStore" 
+		jsId="xmlStore" url="support/books.xml">
+	</span>
+	<div id="grid3" dojoType="dojox.grid.DataGrid" elasticView="2" query="{ title: '*' }" rowsPerPage="5"
+		store="xmlStore" structure="layoutBooks" rowSelector="20px">
+	</div>
+
+
+	<h2>dojox.data.FlickrStore:</h2>
+	<i>Displays Flickr imformation on 3DNY (Dojo Developer Days, New York) from the flickr public photo feed, accessed via the FlickrStore dojo.data implementation.</i>
+	<span dojoType="dojox.data.FlickrStore" 
+		jsId="flickrStore">
+	</span>
+	<div id="grid4" dojoType="dojox.grid.DataGrid" elasticView="2" query="{ tags: '3dny' }"
+		rowsPerPage="5"
+		store="flickrStore" structure="layoutFlickrData" rowSelector="20px">
+	</div>
+
+	<h2>dojox.data.OpmlStore:</h2>
+	<i>Scans an Opml based document for all items of type 'country'</i> 
+	<span dojoType="dojox.data.OpmlStore" 
+		jsId="opmlStore" url="support/geography.xml">
+	</span>
+	<div id="grid5" dojoType="dojox.grid.DataGrid" elasticView="2" query="{ type: 'country' }"
+		queryOptions="{ deep: true }" rowsPerPage="5"
+		store="opmlStore" structure="layoutOpmlData" rowSelector="20px">
+	</div>
+
+
+	<h2>dojox.data.HtmlStore:</h2>
+	<i>Loads the grid from an HTML Table.</i> 
+	<!-- 
+		Inline data table to be displayed bu the grid! 
+		This is accessed via the dojox.data.HtmlTableStore
+	-->
+	<table id="tableExample" style="display: none;">
+		<thead>
+			<tr>
+				<th>Column 1</th>
+				<th>Column 2</th>
+				<th>Column 3</th>
+				<th>Column 4</th>
+			</tr>
+		</thead>
+		<tbody>
+			<tr>
+				<td>This</td>
+				<td>is</td>
+				<td></td>
+				<td>empty in column 3</td>
+			</tr>
+			<tr>
+				<td>This</td>
+				<td>is</td>
+				<td>a</td>
+				<td>value</td>
+			</tr>
+			<tr>
+				<td>Who?</td>
+				<td>What?</td>
+				<td>When?</td>
+				<td>Where?</td>
+			</tr>
+			<tr>
+				<td>She</td>
+				<td>sells</td>
+				<td>sea</td>
+				<td>shells</td>
+			</tr>
+		</tbody>
+	</table>
+	<span dojoType="dojox.data.HtmlStore" 
+		jsId="htmlStore" dataId="tableExample">
+	</span>
+	<div id="grid6" dojoType="dojox.grid.DataGrid" elasticView="2" query="{}"
+		store="htmlStore" rowsPerPage="5" structure="layoutHtmlTable" rowSelector="20px">
+	</div>
+
+</body>
+</html>
+
+
diff --git a/dojox/grid/tests/test_data_grid_notification.html b/dojox/grid/tests/test_data_grid_notification.html
new file mode 100644
index 0000000..1bf2f1d
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_notification.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Notification</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		#grid, #grid2 {
+			width: 65em;
+			height: 25em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.DataGrid Notification Test</div>
+	<button onclick="updateCountryTypes();">Change country types</button>
+	<script>
+		function updateCountryTypes(){
+			// get everything starting with "A"
+			jsonStore.fetch({
+				query: { name: "A*" },
+				onComplete: function(items, result){
+					// change 'em!
+					dojo.forEach(items, function(item){
+						jsonStore.setValue(item, "type", "thinger");
+						// console.debug(item);
+					});
+				}
+			});
+		}
+	</script>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" 
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_data_grid_page_cache.html b/dojox/grid/tests/test_data_grid_page_cache.html
new file mode 100644
index 0000000..c208f6c
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_page_cache.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>DataGrid Page Cache Test</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/tundraGrid.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djconfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojox.grid.DataGrid");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		// a grid layout is an array of views.
+		var layout = [
+			[
+				{ name: 'Column 0', field: 'id' },
+				{ name: 'Column 1', field: 'col1' },
+				{ name: 'Column 2', field: 'col2' },
+				{ name: 'Column 3', field: 'col3', width: '150px' },
+				{ name: 'Column 4', field: 'col4' }
+			],
+			[
+				{name: 'Column 5', field: 'col5' },
+				{name: 'Column 6', field: 'col6' },
+				{name: 'Column 7', field: 'col7' },
+				{name: 'Column 8', field: 'col3', colSpan: 2}
+			]
+		];
+		function query(){
+			console.log("There are "+dojo.query(".dojoxGridRow",grid1.domNode).length+" rows created in the grid");
+		}
+	</script>
+</head>
+<body class="tundra">
+	Scroll trough some pages and then count the number of row nodes. We are instantiating the grid with 10 rows per page, and <b>caching at most 20 rows</b>. So if this policy works, you should never see a number bigger than 20! <br>
+	<button onclick="query()">Get number of row nodes</button>
+	<div jsid="grid1" dojoType="dojox.grid.DataGrid" store="test_store" query="{ id: '*' }" rowsPerPage="10" keepRows="20" structure="layout" style="height: 200px; width: 75%;">
+	</div>
+</body></html>
diff --git a/dojox/grid/tests/test_data_grid_pctWidth.html b/dojox/grid/tests/test_data_grid_pctWidth.html
new file mode 100644
index 0000000..11e24d3
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_pctWidth.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Percentage Width</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		#grid, #grid2 {
+			width: 85%;
+			height: 25em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+		dojo.addOnLoad(function(){
+			// A quick-and-dirty resize of the grid when the window resizes to
+			// test that percentages "stick" when they are supposed to.
+			dojo.connect(window, "resize", grid, "resize");
+		});
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.DataGrid Percentage Width Test</div>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" 
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="50%">Country/Continent Name</th>
+				<th field="type" width="20%">Type</th>
+				<th field="population" width="30%">Population</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
+
diff --git a/dojox/grid/tests/test_data_grid_processError.html b/dojox/grid/tests/test_data_grid_processError.html
new file mode 100644
index 0000000..0802d37
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_processError.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.DataGrid with trapping of data store errors.</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		
+		#grid{
+			width: 65em;
+			height: 25em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojox.data.CsvStore");
+		dojo.require("dojo.parser");
+	</script>
+
+	<script type="text/javascript">
+		var layoutMovies =[
+			{ name: "Title", field: "Title", width: 'auto' },
+			{ name: "Year", field: "Year", width: 5 },
+			{ name: "Producer", field: "Producer", width: 20 }
+		];
+	</script>
+</head>
+<body class="tundra">
+	<h1>dojox.grid.DataGrid with trapping of data store errors</h1>
+
+	<h2>dojox.data.CsvStore:</h2>.
+	<i>This grid does not load data.  The data store references a non-existent URL on purpose.  It should trigger a failure that we catch and display in an alert</i>
+	<span dojoType="dojox.data.CsvStore" 
+		jsId="csvStore" url="support/NoSuchMovieFile.csv">
+	</span>
+	<div id="grid" jsid="grid" dojoType="dojox.grid.DataGrid" elasticView="2" query="{ Title: '*' }"
+		rowsPerPage="5" store="csvStore" structure="layoutMovies" autoRender="false">
+		<script type="dojo/connect" event="onFetchError" args="error">
+			alert("Error was encountered when store was queried: " + dojo.toJson(error, true));
+		</script>
+	</div>
+</body>
+</html>
+
+
diff --git a/dojox/grid/tests/test_data_grid_relWidth.html b/dojox/grid/tests/test_data_grid_relWidth.html
new file mode 100644
index 0000000..8e6dbe0
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_relWidth.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Relative Width</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		.grid {
+			width: 85%;
+			height: 20em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+
+		dojo.addOnLoad(function(){
+			// A quick-and-dirty resize of the grid when the window resizes to
+			// test that percentages "stick" when they are supposed to.
+			dojo.connect(window, "resize", grid, "resize");
+			dojo.connect(window, "resize", grid1, "resize");
+			dojo.connect(window, "resize", grid2, "resize");
+			dojo.connect(window, "resize", grid3, "resize");
+			dojo.connect(window, "resize", grid4, "resize");
+		});
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.DataGrid Relative Width Test</div>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" class="grid"
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" relWidth="3">Country/Continent Name</th>
+				<th field="type" relWidth="1">Type</th>
+				<th field="population" relWidth="1">Population</th>
+			</tr>
+		</thead>
+	</table>
+	<div class="heading">Relwidth mixed with %</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid1" id="grid1" class="grid"
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" relWidth="3">Country/Continent Name</th>
+				<th field="type" relWidth="1">Type</th>
+				<th field="population" width="25%">Population</th>
+			</tr>
+		</thead>
+	</table>	
+	<div class="heading">Relwidth mixed with static values</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid2" id="grid2" class="grid"
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" relWidth="3">Country/Continent Name</th>
+				<th field="type" relWidth="1">Type</th>
+				<th field="population" width="20em">Population</th>
+			</tr>
+		</thead>
+	</table>	
+	<div class="heading">Relwidth mixed with auto (relwidth not used)</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid3" id="grid3" class="grid"
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="auto">Country/Continent Name</th>
+				<th field="type" relWidth="1">Type</th>
+				<th field="population" relWidth="2">Population</th>
+			</tr>
+		</thead>
+	</table>	
+	<div class="heading">Relwidth with colspans</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid4" id="grid4" class="grid"
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="type" relWidth="1">Type</th>
+				<th field="population" relWidth="2">Population</th>
+			</tr>
+			<tr>
+				<th field="name" relWidth="1" colspan="2">Country/Continent Name</th>
+			</tr>
+		</thead>
+	</table>	
+</body>
+</html>
+
diff --git a/dojox/grid/tests/test_data_grid_setStore.html b/dojox/grid/tests/test_data_grid_setStore.html
new file mode 100644
index 0000000..b58ef7b
--- /dev/null
+++ b/dojox/grid/tests/test_data_grid_setStore.html
@@ -0,0 +1,104 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test DataGrid - setStore</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		button {
+			margin: 20px;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		.grid {
+			width: 65em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+		
+		dojo.declare("dojox.grid.SlowFileWriteStore", dojo.data.ItemFileWriteStore, {
+			_fetchItems: function(	/*Object*/ keywordArgs, 
+									/*Function*/ findCallback, 
+									/*Function*/ errorCallback){
+				setTimeout(dojo.hitch(this, function(){
+					dojo.data.ItemFileWriteStore.prototype._fetchItems.call(this, keywordArgs, findCallback, errorCallback);
+				}), 10000);
+			}
+		});
+		
+		function createStore(type)
+		{
+			// Create a new datastore and use the Grid's setStore() function to change it.
+			var newStore, args = {}, grid = dijit.byId("grid");
+			if(type=="slow"){
+				// Slow Loading store
+				args.url = "../../../dijit/tests/_data/countries.json";
+				newStore = new dojox.grid.SlowFileWriteStore(args);
+				grid.setStore(newStore, { name: '*' });
+			}else if(type=="empty"){
+				// Empty result set -- set the Grid's query to something with no results
+				args.url = "../../../dijit/tests/_data/countries.json";
+				newStore = new dojo.data.ItemFileWriteStore(args);
+				grid.setStore(newStore, { name: 'nonexist' });
+			}else if(type=="error"){
+				// Error result -- set the url to a file that doesn't exist
+				args.url = "../../../dijit/tests/_data/countries-no.json";
+				newStore = new dojo.data.ItemFileWriteStore(args);
+				grid.setStore(newStore);
+			}else{//type=="standard"
+				args.url = "../../../dijit/tests/_data/countries.json";
+				newStore = new dojo.data.ItemFileWriteStore(args);
+				grid.setStore(newStore);
+			}
+		}
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<h1>dojox.grid.DataGrid using setStore() to change datastores.</h1>
+	<p>
+		This page demonstrates the ability to change datastores using the
+		DataGrid's setStore() function. Click on any of the buttons above
+		the Grid to set a new store and refresh the Grid display.
+	</p>
+	<p>
+		<button onclick="createStore('standard');">Standard Store</button>
+		<button onclick="createStore('slow');">Slow Loading Store</button>
+		<button onclick="createStore('empty');">Empty Store</button>
+		<button onclick="createStore('error');">Error Store</button>
+	</p>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<div class="heading">Grid Test</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" class="grid" autoHeight="15" noDataMessage="Sorry, there is no data available."
+		store="jsonStore" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_edit.html b/dojox/grid/tests/test_edit.html
new file mode 100644
index 0000000..537d224
--- /dev/null
+++ b/dojox/grid/tests/test_edit.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Test dojox.grid.DataGrid Editing</title>
+<style>
+	@import "../resources/Grid.css";
+	body {
+		font-family: Tahoma, Arial, Helvetica, sans-serif;
+		font-size: 11px;
+	}
+	.dojoxGridRowEditing td {
+		background-color: #F4FFF4;
+	}
+	.dojoxGrid input, .dojoxGrid select, .dojoxGrid textarea {
+		margin: 0;
+		padding: 0;
+		border-style: none;
+		width: 100%;
+		font-size: 100%;
+		font-family: inherit;
+	}
+	.dojoxGrid input {
+	}
+	.dojoxGrid select {
+	}
+	.dojoxGrid textarea {
+	}
+	#controls {
+		padding: 6px 0;
+	}
+	#grid {
+		width: 850px;
+		height: 350px;
+		border: 1px solid silver;
+	}
+</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+	// ==========================================================================
+	// Custom formatter
+	// ==========================================================================
+	formatMoney = function(inDatum) {
+		return isNaN(inDatum) ? '...' : '$' + parseFloat(inDatum).toFixed(2);
+	}
+	// ==========================================================================
+	// Grid structure
+	// ==========================================================================
+	statusCell = { field: 'col3', name: 'Status', styles: 'text-align: center;', type: dojox.grid.cells.Select, options: [ "new", "read", "replied" ] };
+	gridLayout = [{
+		defaultCell: { width: 8, editable: true, styles: 'text-align: right;'  },
+		cells: [
+			{ name: 'Id', field: 'id', width: 3 },
+			{ name: 'Priority', field: 'col1', styles: 'text-align: center;', type: dojox.grid.cells.Select, options: ["normal", "note", "important"] },
+			{ name: 'Mark', width: 3, field: 'col2', styles: 'text-align: center;', type: dojox.grid.cells.Bool },
+			statusCell,
+			{ name: 'Message', field: 'col4', styles: '', width: '100%' },
+			{ name: 'Amount', field: 'col5', formatter: formatMoney },
+			{ name: 'Amount', field: 'col6', formatter: formatMoney }
+		]
+	},{
+		defaultCell: { width: 4, editable: true, styles: 'text-align: right;' },
+		rows: [
+			{ name: 'Mark', width: 3, field: 'col2', styles: 'text-align: center;', type: dojox.grid.cells.Bool}, 
+			statusCell,
+			{ name: 'Amount', field: 'col5', formatter: formatMoney},
+			{ name: 'Detail', value: 'Detail'}
+		]
+	}];
+	// ==========================================================================
+	// UI Action
+	// ==========================================================================
+	addRow = function(){
+		test_store.newItem({
+			id: grid.rowCount,
+			col1: 'normal',
+			col2: false,
+			col3: 'new',
+			col4: 'Now is the time for all good men to come to the aid of their party.',
+			col5: 99.99,
+			col6: 9.99,
+			col7: false
+		});
+	}
+</script>
+</head>
+<body>
+<h2>
+	dojox.grid.DataGrid Basic Editing test
+</h2>
+<div id="controls">
+	<button onclick="grid.render()">Refresh</button>   
+	<button onclick="grid.edit.focusEditor()">Focus Editor</button>
+	<button onclick="grid.focus.next()">Next Focus</button>   
+	<button onclick="addRow()">Add Row</button>
+	<button onclick="grid.removeSelectedRows()">Remove</button>   
+	<button onclick="grid.edit.apply()">Apply</button>
+	<button onclick="grid.edit.cancel()">Cancel</button>   
+	<button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button> 
+</div>
+<br />
+<div id="grid" dojoType="dojox.grid.DataGrid" 
+	jsId="grid"
+	rowSelector="20px"
+	store="test_store" structure="gridLayout"></div>
+<br />
+<div id="rowCount"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_edit_canEdit.html b/dojox/grid/tests/test_edit_canEdit.html
new file mode 100644
index 0000000..299e7fd
--- /dev/null
+++ b/dojox/grid/tests/test_edit_canEdit.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+	<title>Test dojox.grid.DataGrid Editing</title>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		body {
+			font-family: Tahoma, Arial, Helvetica, sans-serif;
+			font-size: 11px;
+		}
+		.dojoxGridRowEditing td {
+			background-color: #F4FFF4;
+		}
+		.dojoxGrid input, .dojoxGrid select, .dojoxGrid textarea {
+			margin: 0;
+			padding: 0;
+			border-style: none;
+			width: 100%;
+			font-size: 100%;
+			font-family: inherit;
+		}
+		.dojoxGrid input { }
+		.dojoxGrid select { }
+		.dojoxGrid textarea { }
+		#controls {
+			padding: 6px 0;
+		}
+		#grid {
+			width: 850px;
+			height: 350px;
+			border: 1px solid silver;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		// ==========================================================================
+		// Custom formatter
+		// ==========================================================================
+		formatMoney = function(inDatum) {
+			return isNaN(inDatum) ? '...' : '$' + parseFloat(inDatum).toFixed(2);
+		}
+		// ==========================================================================
+		// Grid structure
+		// ==========================================================================
+		statusCell = { field: 'col3', name: 'Status', styles: 'text-align: center;', type: dojox.grid.cells.Select, options: [ "new", "read", "replied" ] };
+		gridLayout = [{
+			defaultCell: { width: 8, editable: true, styles: 'text-align: right;'  },
+			cells: [
+				{ name: 'Id', field: 'id', width: 3 },
+				{ name: 'Priority', field: 'col1', styles: 'text-align: center;', type: dojox.grid.cells.Select, options: ["Normal", "Note", "Important"], values: ["normal", "note", "important"]},
+				{ name: 'Mark', width: 3, field: 'col2', styles: 'text-align: center;', type: dojox.grid.cells.Bool },
+				statusCell,
+				{ name: 'Message', field: 'col4', styles: '', width: '100%' },
+				{ name: 'Amount', field: 'col5', formatter: formatMoney },
+				{ name: 'Amount', field: 'col6', formatter: formatMoney }
+			]
+		},{
+			defaultCell: { width: 4, editable: true, styles: 'text-align: right;' },
+			rows: [
+				{ name: 'Mark', width: 3, field: 'col2', styles: 'text-align: center;', type: dojox.grid.cells.Bool}, 
+				statusCell,
+				{ name: 'Amount', field: 'col5', formatter: formatMoney},
+				{ name: 'Detail', value: 'Detail'}
+			]
+		}];
+		// ==========================================================================
+		// UI Action
+		// ==========================================================================
+		addRow = function(){
+			test_store.newItem({
+				id: grid.rowCount,
+				col1: 'normal',
+				col2: false,
+				col3: 'new',
+				col4: 'Now is the time for all good men to come to the aid of their party.',
+				col5: 99.99,
+				col6: 9.99,
+				col7: false
+			});
+		}
+		
+		dojo.addOnLoad(function() {
+			// simple canEdit logic
+			grid.canEdit = function(inCell, inRowIndex){
+				return (inCell.field && 
+						inCell.field != 'id' && 
+						!(inCell.field.charAt(3) > 1 && inCell.field.charAt(3) < 5)
+				);
+			}
+		});
+	</script>
+</head>
+<body>
+	<h2>
+		dojox.grid.DataGrid Basic Editing test
+	</h2>
+	<div id="controls">
+		<button onclick="grid.render()">Refresh</button>   
+		<button onclick="grid.edit.focusEditor()">Focus Editor</button>
+		<button onclick="grid.focus.next()">Next Focus</button>   
+		<button onclick="addRow()">Add Row</button>
+		<button onclick="grid.removeSelectedRows()">Remove</button>   
+		<button onclick="grid.edit.apply()">Apply</button>
+		<button onclick="grid.edit.cancel()">Cancel</button>   
+		<button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button> 
+	</div>
+	<br />
+	<div id="grid" dojoType="dojox.grid.DataGrid" 
+		jsId="grid"
+		rowSelector="20px"
+		store="test_store" structure="gridLayout"></div>
+	<br />
+	<div id="rowCount"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_edit_dijit.html b/dojox/grid/tests/test_edit_dijit.html
new file mode 100644
index 0000000..f9cd047
--- /dev/null
+++ b/dojox/grid/tests/test_edit_dijit.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+	<title>Test dojox.grid.Grid Editing</title>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/tundra/tundra_rtl.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		#controls button {
+			margin-left: 10px;
+		}
+		#grid {
+			width: 850px;
+			height: 350px;
+			border: 1px solid silver;
+		}
+		</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojox.grid.cells.dijit");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data_date.js"></script>
+	<script type="text/javascript">
+		// ==========================================================================
+		// Custom formatters
+		// ==========================================================================
+		formatCurrency = function(inDatum){
+			return isNaN(inDatum) ? '...' : dojo.currency.format(inDatum, this.constraint);
+		}
+		formatDate = function(inDatum){
+			return dojo.date.locale.format(new Date(inDatum), this.constraint);
+		}
+		// ==========================================================================
+		// Grid structure
+		// ==========================================================================
+		statusCell = {
+			field: 'col3', name: 'Status', 
+			styles: 'text-align: center;', 
+			type: dojox.grid.cells.Select, 
+			options: [ "new", "read", "replied" ]
+		};
+
+		gridLayout = [{
+			defaultCell: { width: 8, editable: true, type: dojox.grid.cells._Widget, styles: 'text-align: right;'  },
+			rows: [
+				{ name: 'Id', field: 'id', editable: false /* Can't edit ID's of dojo.data items */ },
+				{ name: 'Date', field: 'col8', width: 10,
+					type: dojox.grid.cells.DateTextBox,
+					formatter: formatDate, 
+					constraint: {formatLength: 'long', selector: "date"}},
+				{ name: 'Priority', styles: 'text-align: center;', field: 'col1', 
+					type: dojox.grid.cells.ComboBox, 
+					options: ["normal", "note", "important"], width: 10},
+				{ name: 'Mark', field: 'col2', width: 3, styles: 'text-align: center;', 
+					type: dojox.grid.cells.CheckBox},
+				statusCell,
+				{ name: 'Message', field: 'col4', styles: '', width: 10, 
+					type: dojox.grid.cells.Editor, editorToolbar: true },
+				{ name: 'Amount', field: 'col5', formatter: formatCurrency, constraint: {currency: 'EUR'}, 
+					widgetClass: dijit.form.CurrencyTextBox },
+				{ name: 'Amount', field: 'col5', formatter: formatCurrency, constraint: {currency: 'EUR'}, 
+					widgetClass: dijit.form.HorizontalSlider, width: 10}
+			]
+		}];
+		// ==========================================================================
+		// UI Action
+		// ==========================================================================
+		addRow = function(){
+			test_store.newItem({
+				id: grid.rowCount,
+				col1: 'normal',
+				col2: false,
+				col3: 'new',
+				col4: 'Now is the time for all good men to come to the aid of their party.',
+				col5: 99.99,
+				col6: 9.99,
+				col7: false,
+				col8: new Date()
+			});
+		}
+	</script>
+</head>
+<body class="tundra">
+	<h1>dojox.grid.DataGrid Basic Editing test</h1>
+	<br />
+	<div id="controls">
+		<button onclick="grid.render()">Refresh</button>
+		<button onclick="grid.edit.focusEditor()">Focus Editor</button>
+		<button onclick="grid.focus.next()">Next Focus</button>
+		<button onclick="addRow()">Add Row</button>
+		<button onclick="grid.removeSelectedRows()">Remove</button>
+		<button onclick="grid.edit.apply()">Apply</button>
+		<button onclick="grid.edit.cancel()">Cancel</button>
+		<button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button>
+	</div>
+	<br />
+	<div id="grid" jsId="grid" dojoType="dojox.grid.DataGrid" store="test_store" rowSelector="20px" structure="gridLayout" escapeHTMLInData="false"></div>
+	<br />
+	<div id="rowCount"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_edit_keyNav.html b/dojox/grid/tests/test_edit_keyNav.html
new file mode 100644
index 0000000..ce05e0c
--- /dev/null
+++ b/dojox/grid/tests/test_edit_keyNav.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>Test dojox.grid.DataGrid Editing</title>
+<style>
+	@import "../resources/Grid.css";
+	body {
+		font-family: Tahoma, Arial, Helvetica, sans-serif;
+		font-size: 11px;
+	}
+	.dojoxGridRowEditing td {
+		background-color: #F4FFF4;
+	}
+	.dojoxGrid input, .dojoxGrid select, .dojoxGrid textarea {
+		margin: 0;
+		padding: 0;
+		border-style: none;
+		width: 100%;
+		font-size: 100%;
+		font-family: inherit;
+	}
+	.dojoxGrid input {
+	}
+	.dojoxGrid select {
+	}
+	.dojoxGrid textarea {
+	}
+	#controls {
+		padding: 6px 0;
+	}
+	#grid {
+		width: 850px;
+		height: 350px;
+		border: 1px solid silver;
+	}
+</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+	// ==========================================================================
+	// Custom formatter
+	// ==========================================================================
+	formatMoney = function(inDatum) {
+		return isNaN(inDatum) ? '...' : '$' + parseFloat(inDatum).toFixed(2);
+	}
+	// ==========================================================================
+	// Grid structure
+	// ==========================================================================
+	statusCell = { field: 'col3', name: 'Status', styles: 'text-align: center;', type: dojox.grid.cells.Select, options: [ "new", "read", "replied" ] };
+	gridLayout = [{
+		defaultCell: { width: 8, editable: true, styles: 'text-align: right;'  },
+		cells: [
+			{ name: 'Id', field: 'id', width: 3, editable: false },
+			{ name: 'Priority', field: 'col1', styles: 'text-align: center;', type: dojox.grid.cells.Select, options: ["normal", "note", "important"] },
+			{ name: 'Mark', width: 3, field: 'col2', styles: 'text-align: center;', type: dojox.grid.cells.Bool },
+			statusCell,
+			{ name: 'Message', field: 'col4', styles: '', width: '100%' },
+			{ name: 'Amount1', field: 'col5', formatter: formatMoney },
+			{ name: 'Amount2', field: 'col6', editable: false, formatter: formatMoney }
+		]
+	},{
+		defaultCell: { width: 4, editable: true, styles: 'text-align: right;' },
+		rows: [
+			{ name: 'Mark', width: 3, field: 'col2', styles: 'text-align: center;', type: dojox.grid.cells.Bool}, 
+			statusCell,
+			{ name: 'Amount3', field: 'col5', editable: false, formatter: formatMoney},
+			{ name: 'Detail', value: 'Detail', editable: false}
+		]
+	}];
+	// ==========================================================================
+	// UI Action
+	// ==========================================================================
+	addRow = function(){
+		test_store.newItem({
+			id: grid.rowCount,
+			col1: 'normal',
+			col2: false,
+			col3: 'new',
+			col4: 'Now is the time for all good men to come to the aid of their party.',
+			col5: 99.99,
+			col6: 9.99,
+			col7: false
+		});
+	}
+</script>
+</head>
+<body>
+<h2>
+	dojox.grid.DataGrid Basic Editing and Key Navigation test
+</h2>
+<div id="controls">
+	<button onclick="grid.render()">Refresh</button>   
+	<button onclick="grid.edit.focusEditor()">Focus Editor</button>
+	<button onclick="grid.focus.next()">Next Focus</button>   
+	<button onclick="addRow()">Add Row</button>
+	<button onclick="grid.removeSelectedRows()">Remove</button>   
+	<button onclick="grid.edit.apply()">Apply</button>
+	<button onclick="grid.edit.cancel()">Cancel</button>   
+	<button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button> 
+</div>
+<p>Id, Priority, Mark, Status, Message, Amount1, second Mark, second Status fields are editable, Amount2,
+Amount3, and detail field are not editable.  Once in edit mode you can tab and shift-tab between
+editable fields and remain in edit mode.  Pressing escape leaves edit mode and arrow keys will again move 
+between cells.  </p>
+<div id="grid" dojoType="dojox.grid.DataGrid" 
+	jsId="grid"
+	rowSelector="20px"
+	store="test_store" structure="gridLayout"></div>
+<br />
+<div id="rowCount"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_events.html b/dojox/grid/tests/test_events.html
new file mode 100644
index 0000000..f416954
--- /dev/null
+++ b/dojox/grid/tests/test_events.html
@@ -0,0 +1,191 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Events</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		body,td,th {
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}	
+		#grid { 
+			border: 1px solid;
+			border-top-color: #F6F4EB;
+			border-right-color: #ACA899;
+			border-bottom-color: #ACA899;
+			border-left-color: #F6F4EB;
+		}
+		#grid {
+			width: 50em;
+			height: 20em;
+			padding: 1px;
+			overflow: hidden;
+			font-size: small;
+		}
+		h3 {
+			margin: 10px 0 2px 0;
+		}
+		.fade {
+			/*background-image:url(images/fade.gif);*/
+		}
+		.no-fade {
+			/*background-image: none;*/
+		}
+		#eventGrid {
+			float: right;
+			font-size: small;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid._Grid");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript">
+		// events to track
+		var eventRows = [
+			{ name: 'onCellClick' },
+			{ name: 'onRowClick', properties: ['rowIndex'] },
+			{ name: 'onCellDblClick' },
+			{ name: 'onRowDblClick', properties: ['rowIndex'] },
+			{ name: 'onCellMouseOver' },
+			{ name: 'onCellMouseOut' },
+			{ name: 'onCellMouseDown' },
+			{ name: 'onRowMouseOver' },
+			{ name: 'onRowMouseOut' },
+			{ name: 'onRowMouseDown' },
+			{ name: 'onHeaderCellClick' },
+			{ name: 'onHeaderClick', properties: ['rowIndex'] },
+			{ name: 'onHeaderCellDblClick' },
+			{ name: 'onHeaderDblClick', properties: ['rowIndex'] },
+			{ name: 'onHeaderCellMouseOver' },
+			{ name: 'onHeaderCellMouseOut' },
+			{ name: 'onHeaderCellMouseDown' },
+			{ name: 'onHeaderMouseOver' },
+			{ name: 'onHeaderMouseOut' },
+			{ name: 'onKeyDown', properties: ['keyCode'] },
+			{ name: 'onCellContextMenu' },
+			{ name: 'onRowContextMenu', properties: ['rowIndex'] },
+			{ name: 'onHeaderCellContextMenu' },
+			{ name: 'onHeaderContextMenu', properties: ['rowIndex'] }
+		];	
+		
+		getEventName = function(inRowIndex) {
+			return eventRows[inRowIndex].name;
+		};
+		
+		getEventData = function(inRowIndex) {
+			var d = eventRows[inRowIndex].data;
+			var r = [];
+			if (d)
+				for (var i in d)
+					r.push(d[i]);
+			else
+				r.push('na')
+			return r.join(', ');
+		}
+		
+		// grid structure for event tracking grid.
+		var eventLayout = {
+			noscroll: true,
+			cells: [
+				{ name: 'Event', get: getEventName, width: 12 },
+				{ name: 'Data', get: getEventData, width: 10 }
+			]
+		}
+
+		var fade = function(inNode) {
+			if (!inNode || !inNode.style) return;
+			var c = 150, step = 5, delay = 20;
+			var animate = function() {
+				c = Math.min(c + step, 255);
+				inNode.style.backgroundColor = "rgb(" + c + ", " + c + ", 255)";
+				if (c < 255) window.setTimeout(animate, delay);
+			}
+			animate();
+		}
+		
+		// setup a fade on a row. Must do this way to avoid caching of fade gif
+		updateRowFade = function(inRowIndex) {
+			var n = eventGrid.views.views[0].getRowNode(inRowIndex);
+			fade(n);
+		}
+		
+		// store data about event. By default track event.rowIndex and event.cell.index, but eventRows can specify params, which are event properties to track.
+		setEventData = function(inIndex, inEvent) {
+			var eRow = eventRows[inIndex];
+			eRow.data = {};
+			var properties = eRow.properties;
+			if (properties)
+				for (var i=0, l=properties.length, p; (p=properties[i] || i < l); i++)
+					eRow.data[p] = inEvent[p];
+			else
+				eRow.data =  {
+					row: (inEvent.rowIndex != undefined ? Number(inEvent.rowIndex) : 'na'), 
+					cell: (inEvent.cell && inEvent.cell.index != undefined ? inEvent.cell.index : 'na')
+				}	
+			eventGrid.updateRow(inIndex);
+			updateRowFade(inIndex);
+		}
+		
+		// setup grid events for all events being tracked.
+		setGridEvents = function() {
+			var makeEvent = function(inIndex, inName) {
+				return function(e) {
+					setEventData(inIndex, e);
+					dojox.grid._Grid.prototype[inName].apply(this, arguments);
+				}
+			}
+			for (var i=0, e; (e=eventRows[i]); i++)
+				grid[e.name] = makeEvent(i, e.name);
+		}
+				
+		// Grid structure
+		var layout = [// array of view objects
+			{
+				noscroll: true,
+				cells: [[
+					{ name: "Alpha", value: '<input type="checkbox"></input>', rowSpan: 2, width: 6, styles: 'text-align:center;' },
+					{ name: "Alpha2", value: "Alpha2" }
+				],[
+					{ name: "Alpha3", value: "Alpha3" }
+				]]
+			},
+			[
+				[
+					{ name: "Beta", value: 'simple'},
+					{ name: "Beta2", value: "Beta2" },
+					{ name: "Beta3", value: "Beta3" },
+					{ name: "Beta4", value: "Beta4" },
+					{ name: "Beta5", value: "Beta5" }
+				],[
+					{ name: "Summary", colSpan: 5, value: 'Summary' }
+				]
+			],
+			{
+				noscroll: true,
+				cells: [
+					{ name: "Gamma", value: "Gamma" },
+					{ name: "Gamma2", value: "<button>Radiate</button>", styles: 'text-align:center;' }
+				]
+			}
+		];
+		
+		dojo.addOnLoad(function() {
+			setGridEvents(); 
+			eventGrid.updateRowCount(eventRows.length);
+			dojo.debug = console.log;
+		});	
+	</script>
+</head>
+<body>
+	<h3>dojox.grid.Grid Event Tracking</h3>
+	<div id="eventGrid" jsId="eventGrid" autoWidth="true" autoHeight="true" 
+		structure="eventLayout" dojoType="dojox.grid._Grid"></div>
+	<div id="grid" jsId="grid" rowCount="100" structure="layout" 
+		rowSelector="20px" dojoType="dojox.grid._Grid"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_expand.html b/dojox/grid/tests/test_expand.html
new file mode 100644
index 0000000..58a1568
--- /dev/null
+++ b/dojox/grid/tests/test_expand.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Expand Rows</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		
+		.bigHello {
+			height: 110px;
+			line-height: 110px;
+			text-align: center;
+			font-weight: bold;
+			font-size: 30px;
+		}	
+				
+		#grid { 
+			border: 1px solid #333;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript">
+		// inRow is an array of subRows. we hide the summary subRow except for every nth row
+		function onBeforeRow(inDataIndex, inRow) {
+			inRow[1].hidden = (!this.grid || !this.grid.expandedRows || !this.grid.expandedRows[inDataIndex]);
+		}
+		
+		var structure = {
+			onBeforeRow: onBeforeRow,
+			cells: [
+				[
+					{ name: 'Whatever', width: 4.5, get: getCheck, formatter: formatCheck, styles: 'text-align: center;' },
+					{name: 'Column 0'},
+					{name: 'Column 1'},
+					{name: 'Column 2'},
+					{name: 'Column 3'},
+					{name: 'Column 4'}
+				],
+				[ { name: 'Detail', colSpan: 6, get: getDetail, formatter: formatDetail } ]
+			]
+		};
+		
+		// get can return data for each cell of the grid
+		function get(inRowIndex) {
+			return [this.index, inRowIndex].join(', ');
+		}
+		
+		function getDetail(inRowIndex) {
+			if (this.grid.expandedRows[inRowIndex]) {
+				return 'Hello World!';
+			} else {
+				return '';
+			}
+		}
+		
+		function formatDetail(value, inRowIndex){
+			if(value){
+				var n = (inRowIndex % 2);
+				switch (n) {
+					case 0:
+						return value;
+					default:
+						return '<div class="bigHello">' + value + '</div>';
+				}			
+			}
+			return value;
+		}
+		
+		function toggle(inIndex, inShow) {
+			grid.expandedRows[inIndex] = inShow;
+			grid.updateRow(inIndex);
+		}
+		
+		function getCheck(inRowIndex) {
+			if (!this.grid.expandedRows)
+				this.grid.expandedRows = [ ];
+			return {image: (this.grid.expandedRows[inRowIndex] ? 'open.gif' : 'closed.gif'),
+					show: (this.grid.expandedRows[inRowIndex] ? 'false' : 'true')};
+		}
+		
+		function formatCheck(value, inRowIndex){
+			return '<img src="images/' + value.image + '" onclick="toggle(' + inRowIndex + ', ' + value.show + ')" height="11" width="11">';
+		}
+	</script>
+</head>
+<body>
+	<div class="heading">dojox.grid.Grid Expand Row Example</div>
+
+	<div id="grid" jsid="grid" dojoType="dojox.grid._Grid" get="get" 
+		structure="structure" rowCount="100000" autoWidth="true" rowSelector="20px"></div>
+
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid.html b/dojox/grid/tests/test_grid.html
new file mode 100644
index 0000000..7fa3216
--- /dev/null
+++ b/dojox/grid/tests/test_grid.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid {
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout = [[
+			new dojox.grid.cells.RowIndex({ width: 5 }),
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6', colSpan: 2},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.Grid Basic Test</div>
+	<div jsId="grid" id="grid" dojoType="dojox.grid.DataGrid" 
+		store="test_store" query="{ id: '*' }" 
+		structure="layout" rowSelector="20px"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_autorender.html b/dojox/grid/tests/test_grid_autorender.html
new file mode 100644
index 0000000..0709844
--- /dev/null
+++ b/dojox/grid/tests/test_grid_autorender.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid autoRender</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid {
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout = [[
+			new dojox.grid.cells.RowIndex({ width: 5 }),
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6', colSpan: 2},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+		var renderGrid = function(){
+			grid.render();
+		}
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.Grid autoRender Test</div>
+	<div jsId="grid" id="grid" dojoType="dojox.grid.DataGrid" 
+		store="test_store" query="{ id: '*' }" 
+		structure="layout" rowSelector="20px" autoRender="false"></div>
+	<button onclick="renderGrid()">Render the grid</button>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_colspan_resize.html b/dojox/grid/tests/test_grid_colspan_resize.html
new file mode 100644
index 0000000..7a65713
--- /dev/null
+++ b/dojox/grid/tests/test_grid_colspan_resize.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.Grid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">       
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+					   
+		#grid, #gridColspan {
+			width: 45em;
+			height: 25em;
+			border: 1px solid #333;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="debugAtAllCosts: false, isDebug: false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dojox.grid.DataGrid");
+//		dojo.require("dojox.grid._data.model");
+		dojo.require("dojo.parser");
+
+		var columnView =
+		{
+			cells: [
+				[  // column header row 1
+					{ name: 'Row 0 / Column 0',     field: "r0c0",   width: "80px" }, 
+					{ name: 'Row 0 / Column 1',     field: "r0c1",   width: "80px" }, 
+					{ name: 'Row 0 / Column 2',     field: "r0c2",   width: "80px" },
+					{ name: 'Row 0 / Column 3',     field: "r0c3",   width: "80px" }
+				],
+
+				[  // column header row 2
+					{ name: 'Row 1 / Column 0',     field: "r1c0",   width: "80px" },
+					{ name: 'Row 1 / Column 1',     field: "r1c1",   width: "80px" },
+					{ name: 'Row 1 / Column 2',     field: "r1c2",   width: "80px" },
+					{ name: 'Row 1 / Column 3',     field: "r1c3",   width: "80px" }
+				]
+			] 
+		};                
+		var layout = [ columnView ];
+		var columnViewColspan =
+		{
+			cells: [
+				[  // column header row 1
+					{ name: 'Row 0 / Column 0',     field: "r0c0",   width: "80px" }, 
+					{ name: 'Row 0 / Column 1',     field: "r0c1",   width: "80px" }, 
+					{ name: 'Row 0 / Column 2',     field: "r0c2",   width: "80px" },
+					{ name: 'Row 0 / Column 3',     field: "r0c3",   width: "80px" }
+				],
+
+				[  // column header row 2
+					{ name: 'Row 1 / Column 0/1',   field: "r1c0",   width: "80px", colSpan: "2" },
+					{ name: 'Row 1 / Column 2',     field: "r1c2",   width: "80px" },
+					{ name: 'Row 1 / Column 3',     field: "r1c3",   width: "80px" }
+				]
+			] 
+		};                
+		var layoutColspan = [ columnViewColspan ];
+	</script>
+</head>
+<body class="tundra">
+	<div dojoType="dojo.data.ItemFileReadStore"
+		jsId="jsonStore" url="support/test_resize_data.json">
+	</div>
+	<div class="heading">No Colspan</div>
+	<div id="grid" dojoType="dojox.grid.DataGrid" 
+		store="jsonStore" structure="layout"></div>
+	<div class="heading">Colspan</div>
+	<div id="gridColspan" dojoType="dojox.grid.DataGrid" 
+		store="jsonStore" structure="layoutColspan"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_column_display.html b/dojox/grid/tests/test_grid_column_display.html
new file mode 100644
index 0000000..fde0637
--- /dev/null
+++ b/dojox/grid/tests/test_grid_column_display.html
@@ -0,0 +1,179 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Column Display Toggling</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dojo/resources/dnd.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid, #grid1 {
+			border: 1px solid #333;
+			width: 60em;
+			height: 20em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dijit.ColorPalette");
+		dojo.require("dojox.widget.PlaceholderMenuItem");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout = [{
+			cells: [
+				{name: 'Column 1', field: 'col1'},
+				{name: 'Column 2', field: 'col2', hidden: true},
+				{name: 'Column 3', field: 'col3'}
+			],
+			noscroll: true,
+			width: 'auto'
+		},{
+			cells: [
+				{name: 'Column 4', field: 'col4', width: "150px"},
+				{name: 'Column 5', field: 'col5'},
+				{name: 'Column 6', field: 'col6'},
+				{name: 'Column 7', field: 'col7'},
+				{name: 'Column 8', field: 'col8'},
+				{name: 'Column 9', field: 'col9'}
+			]
+		}];
+		
+		
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.Grid Column Display Toggling Test</div>
+	<div style="margin-top:20px;">Use header menu to change display of columns</div>
+	<div dojoType="dijit.Menu" jsid="gridMenu" id="gridMenu" style="display: none;">
+		<div dojoType="dijit.MenuItem" onClick="alert('Hello world');">Enabled Item</div>
+		<div dojoType="dijit.MenuItem" disabled="true">Disabled Item</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+			onClick="alert('not actually cutting anything, just a test!')">Cut</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+			onClick="alert('not actually copying anything, just a test!')">Copy</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+			onClick="alert('not actually pasting anything, just a test!')">Paste</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dojox.widget.PlaceholderMenuItem" label="GridColumns"></div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Show Columns</span>
+			<div dojoType="dijit.Menu" id="submenu2">
+				<div dojoType="dojox.widget.PlaceholderMenuItem" label="GridColumns"></div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem" disabled="true">
+			<span>Disabled Submenu</span>
+			<div dojoType="dijit.Menu" id="submenu3" style="display: none;">
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</div>
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Different popup</span>
+			<div dojoType="dijit.ColorPalette"></div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem" jsid="popupItem1">
+			<span>Show Columns</span>
+			<div dojoType="dijit.Menu" id="submenu4">
+				<div dojoType="dojox.widget.PlaceholderMenuItem" label="GridColumns"></div>
+			</div>
+		</div>
+	</div>
+
+	<div jsid="grid" id="grid" dojoType="dojox.grid.DataGrid" 
+		columnToggling="true" store="test_store" query="{ id: '*' }" 
+		structure="layout" rowSelector="20px" headerMenu="gridMenu"></div>
+
+	<button dojoType="dijit.form.Button" onclick="popupItem1.destroyRecursive();">
+		Destroy third popup item
+	</button>
+	<div class="heading" style="margin-top:50px;">dojox.DataGrid with locked columns</div>
+	<div dojoType="dijit.Menu" jsid="gridMenu2" id="gridMenu2" style="display: none;">
+		<div dojoType="dijit.MenuItem" onClick="alert('Hello world');">Enabled Item</div>
+		<div dojoType="dijit.MenuItem" disabled="true">Disabled Item</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+			onClick="alert('not actually cutting anything, just a test!')">Cut</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+			onClick="alert('not actually copying anything, just a test!')">Copy</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+			onClick="alert('not actually pasting anything, just a test!')">Paste</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dojox.widget.PlaceholderMenuItem" label="GridColumns"></div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Show Columns</span>
+			<div dojoType="dijit.Menu" id="submenuX2">
+				<div dojoType="dojox.widget.PlaceholderMenuItem" label="GridColumns"></div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem" disabled="true">
+			<span>Disabled Submenu</span>
+			<div dojoType="dijit.Menu" id="submenuX3" style="display: none;">
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</div>
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Different popup</span>
+			<div dojoType="dijit.ColorPalette"></div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem" jsid="popupItemX1">
+			<span>Show Columns</span>
+			<div dojoType="dijit.Menu" id="submenuX4">
+				<div dojoType="dojox.widget.PlaceholderMenuItem" label="GridColumns"></div>
+			</div>
+		</div>
+	</div>
+
+		<span dojoType="dojo.data.ItemFileReadStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	
+
+	<table dojoType="dojox.grid.DataGrid"
+		store="jsonStore"
+		rowsPerPage="20"
+		query="{ name: '*' }"
+		style="width: 600px; height: 300px;"
+		rowSelector="20px"
+		headerMenu="gridMenu2">
+		<colgroup span="2" noscroll="true" width="200px"></colgroup>
+		<colgroup span="5"></colgroup>
+		<thead>
+			<tr>
+				<th field="name" width="auto">Country/Continent Name</th>
+				<th width="100px" field="population">Population</th>
+				<th width="100px" field="area">Land Mass</th>
+				<th width="100px" field="timezone">Time Zone</th>
+				<th width="5em" field="type">Type</th>
+				<th width="5em" field="hemisphere">Hemisphere</th>
+				<th width="5em" field="climate">Climate</th>
+			</tr>
+		</thead>
+	</table>
+
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_column_reorder.html b/dojox/grid/tests/test_grid_column_reorder.html
new file mode 100644
index 0000000..73fa24a
--- /dev/null
+++ b/dojox/grid/tests/test_grid_column_reorder.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Column Reordering</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dojo/resources/dnd.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid {
+			border: 1px solid #333;
+			width: 60em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout = [{
+			cells: [
+				{name: 'Column 1', field: 'col1'},
+				{name: 'Column 2', field: 'col2'},
+				{name: 'Column 3', field: 'col3'}
+			],
+			noscroll: true,
+			width: 'auto'
+		},{
+			cells: [
+				{name: 'Column 4', field: 'col4', width: "150px"},
+				{name: 'Column 5', field: 'col5'}
+			]
+		}];
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.Grid Column Reordering Test</div>
+
+	<div jsid="grid" id="grid" dojoType="dojox.grid.DataGrid" 
+		columnReordering="true" store="test_store" query="{ id: '*' }" 
+		structure="layout" rowSelector="20px"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_csv_export.html b/dojox/grid/tests/test_grid_csv_export.html
new file mode 100644
index 0000000..8dfaabd
--- /dev/null
+++ b/dojox/grid/tests/test_grid_csv_export.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid {
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var grid = null;
+		var layout = [[
+			new dojox.grid.cells.RowIndex({ name: "Index", width: 5 }),
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6', colSpan: 2},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+		var items_to_csv = function(items){
+			var csvResults = dojo.byId('csvResults');
+			var first_row = [];
+			dojo.forEach(grid.layout.cells, function(cell){
+				first_row.push(cell.name);
+			});
+			csvResults.value = first_row.join(',') + "\n";
+			dojo.forEach(items, function(item, i){
+				var result = [];
+				dojo.forEach(grid.layout.cells, function(cell){
+					result.push(cell.format(i, item));
+				});
+				csvResults.value += result.join(',') + "\n";
+			});
+		}
+		var export_all = function(){
+			var store = grid.store;
+			store.fetch({
+				query: grid.query,
+				sort: grid.getSortProps(),
+				queryOptions: grid.queryOptions,
+				onComplete: function(items){
+					items_to_csv(items);
+				}
+			});
+		}
+		var export_selected = function(){
+			items_to_csv(grid.selection.getSelected());
+		}
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.Grid Basic Test</div>
+	<button dojoType="dijit.form.Button" onClick="export_all">Export All</button>
+	<button dojoType="dijit.form.Button" onClick="export_selected">Export Selected</button>
+
+	<div jsId="grid" id="grid" dojoType="dojox.grid.DataGrid" 
+		store="test_store" query="{ id: '*' }" 
+		structure="layout" rowSelector="20px"></div>
+
+	Results:<br />
+	<textarea rows="20" cols="100" id="csvResults"></textarea>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_dlg.html b/dojox/grid/tests/test_grid_dlg.html
new file mode 100644
index 0000000..c9ea49d
--- /dev/null
+++ b/dojox/grid/tests/test_grid_dlg.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+
+    <style type="text/css">
+        @import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../resources/Grid.css";
+        @import "../../../dijit/tests/css/dijitTests.css";
+		table { border: none; }
+        
+        body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid { 
+			border: 1px solid #333;
+			width: 400px;
+			height: 500px;
+		}
+	</style>
+
+    <script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+    
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+        dojo.require("dijit.Dialog");
+        dojo.require("dijit.form.Button");
+
+
+
+		var layout = [[
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6'},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+                
+        function openDialog() {
+            var dialog = dijit.byId('dialog');
+            dialog.show();
+        }
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.Grid Basic Test</div>
+	<button onclick="openDialog()">open</button>
+	<div id="dialog" dojoType="dijit.Dialog" title="First Dialog">
+		<table>
+			<tr><td>
+				<div id="grid" dojoType="dojox.grid.DataGrid" 
+					store="test_store" structure="layout"></div>
+			</td></tr>
+			<tr><td>
+				<button dojoType="dijit.form.Button" type="submit">close</button>
+			</td></tr>
+		</table>
+	</div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_formatters.html b/dojox/grid/tests/test_grid_formatters.html
new file mode 100644
index 0000000..0d4c586
--- /dev/null
+++ b/dojox/grid/tests/test_grid_formatters.html
@@ -0,0 +1,151 @@
+<html>
+	<head>
+	<title>Test dojox.grid.DataGrid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+
+    <style type="text/css">
+        @import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+        @import "../../../dijit/tests/css/dijitTests.css";
+		table { border: none; }
+        
+        body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid { 
+			border: 1px solid #333;
+			width: 400px;
+			height: 500px;
+		}
+	</style>
+	<script type="text/javascript" 
+		src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true">
+	</script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dijit.form.TextBox");
+
+		dojo.declare("dojox.grid.formatterScopeObj", null, {
+			store: null,
+			_widgets: [],
+			constructor: function(kwArgs){
+				this.store = kwArgs.store;
+				this._widgets = [];
+			},
+			invalidateCache: function(){
+				// Called when we need to clean our cache and destroy our
+				// widgets.
+				dojo.forEach(this._widgets, function(w){
+					if(w && w.destroy){
+						w.destroy();
+					}
+				});
+				this._widgets = [];
+			},
+			fmtABBR: function(value, idx){
+				if(value == "continent"){
+					return "BIG";
+				}else if(value == "country"){
+					return "MID";
+				}else if(value == "city"){
+					return "SML";
+				}
+				return "???";
+			},
+			fmtWidget: function(value, idx){
+				if(!this._widgets[idx]){
+					this._widgets[idx] = new dijit.form.TextBox({value: value, disabled: true});
+				}
+				return this._widgets[idx];
+			},
+			fmtValue: function(value, idx){
+				return value;
+			},
+			fmtBool: function(value, idx){
+				return (value == "country");
+			},
+			fmtInt: function(value, idx){
+				return dojo.filter(["continent", "country", "city"], function(i){ return i == value; })[0]||null;
+			},
+			fmtChildren: function(value, idx){
+				return dojo.map(value, function(i){
+					return this.store.getLabel(i);
+				}, this).join(", ") || " ";
+			},
+			fmtItem: function(value, idx){
+				if(!this.store.isItem(value)){
+					return " ";
+				}
+				var d = new dojo.Deferred();
+				var fx = function(items){
+					if(items.length){
+						d.callback(this.store.getLabel(items[0]))
+					}else{
+						d.callback(" ");
+					}
+				};
+				window.setTimeout(dojo.hitch(this, function(){
+					this.store.fetch({query: {children: value}, onComplete: fx, onError: function(e){d.errback(e)}, scope: this});
+				}), 5000);
+				return d;
+			}
+		});
+			
+		dojo.addOnLoad(function(){
+			// Connect our invalidateCache function to the "important" places
+			// so we get cleaned up correctly.
+			dojo.connect(grid, "_structureChanged", myObject, "invalidateCache");
+			dojo.connect(grid, "_clearData", myObject, "invalidateCache");
+			dojo.connect(grid, "destroy", myObject, "invalidateCache");
+			
+			doh.register("tests",
+				[
+					function test_gridFormatters(t){
+						t.t(true);
+					}
+				]
+			);
+			doh.run();
+		});
+	</script>
+	<style>
+		.dijitTextBox {
+			color: gray;
+			width: 90px;
+		}
+	</style>
+	</head>	
+	<body class="tundra">
+		<h1 class="testTitle">Test: dojox.tests.grid.Grid Formatters</h1>
+		<div dojoType="dojo.data.ItemFileReadStore" jsId="readStore" url="support/countryStore.json?"></div>
+		<div dojoType="dojox.grid.formatterScopeObj" store="readStore" jsId="myObject"></div>
+		<table dojoType="dojox.grid.DataGrid" jsId="grid" formatterScope="myObject" 
+				style="width: 65em;height: 25em;" store="readStore" queryOptions="{deep:true}" rowsPerPage="100">
+			<thead>
+				<tr>
+					<th field="name" relWidth="2">Name</th>
+					<th field="type" relWidth="2">Type</th>
+					<th field="type" formatter="fmtABBR" relWidth="1">Abbr</th>
+					<th field="type" formatter="fmtValue" relWidth="2">Value</th>
+					<th field="type" formatter="fmtBool" relWidth="1">IsCountry</th>
+					<th field="type" formatter="fmtInt" relWidth="1">Int</th>
+					<th fields="children" formatter="fmtChildren" relWidth="3">Children</th>
+					<th field="_item" formatter="fmtItem" relWidth="2">Parent</th>
+					<th field="name" formatter="fmtWidget" relWidth="3">Widget</th>
+				</tr>
+			</thead>
+		</table>
+	</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_headerHeight.html b/dojox/grid/tests/test_grid_headerHeight.html
new file mode 100644
index 0000000..e4adad9
--- /dev/null
+++ b/dojox/grid/tests/test_grid_headerHeight.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid {
+			border: 1px solid #333;
+			width: 65em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout = [
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2', width: "10em"},
+			{name: 'Column 3', field: 'col3', width:"100px"},
+			{name: 'Column 4 is 25%', field: 'col4', width: "25%"},
+			{name: 'Column 5 is 75% of the remaining space', field: 'col5', width: "75%"}
+		];
+
+		var layout2 = [{
+			noscroll: true,
+			cells: [[
+				{ name: "Alpha", value: '<input type="checkbox"></input>', rowSpan: 2, width: 6, styles: 'text-align:center;' },
+				{ name: "Alpha 2", value: "Alpha2" }
+			],[
+				{ name: "Alpha 3", value: "Alpha3" }
+			]]
+		},{
+			cells: [[
+				{ name: "Beta", value: 'simple'},
+				{ name: "Beta 2", value: "Beta 2" },
+				{ name: "Beta 3", value: "Beta 3" },
+				{ name: "Beta 4", value: "Beta 4", width: "auto" },
+				{ name: "Beta 5 is good", value: "Beta 5", width: "auto" }
+			],[
+				{ name: "Summary", colSpan: 5, value: 'Summary' }
+			]]
+		},{
+			noscroll: true,
+			cells: [
+				{ name: "Gamma", value: "Gamma" },
+				{ name: "Gamma2", value: "<button>Radiate</button>", styles: 'text-align:center;' }
+			]
+		}];
+	</script>
+</head>
+<body>
+	<div class="heading">dojox.grid.Grid Basic Test</div>
+	<div jsid="grid" id="grid" dojoType="dojox.grid.DataGrid" 
+		store="test_store" structure="layout"></div>
+	<br /><br />
+	<div jsid="grid2" id="grid2" dojoType="dojox.grid._Grid" 
+		structure="layout2" rowCount="50" rowSelector="20px"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_hidden_rows.html b/dojox/grid/tests/test_grid_hidden_rows.html
new file mode 100644
index 0000000..e52afd5
--- /dev/null
+++ b/dojox/grid/tests/test_grid_hidden_rows.html
@@ -0,0 +1,211 @@
+<html>
+
+<head>
+	<title>Grid Bug</title>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+		
+		<!--<script type="text/javascript" src="dojo/dojo/grid.js"></script>--> 
+		
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	
+
+
+	<script type="text/javascript">
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dijit.form.CheckBox");
+		dojo.require("dojo.date.locale");
+
+var drc={};
+drc.gridData = {
+	identifier: 'id',
+	label: 'id',
+	items: [
+		{ id: 5301, created: 1204243230266, completed: 1204244264554, status: 'COMPLETED', completion_log: null, instructor_decision: 'YES', course: 'AGB 322', section: '02', exam_date: 1204920600000, end_time: 1204925100000 },
+		{ id: 5401, created: 1204314408874, completed: 1204834363267, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'AGB 322', section: '02', exam_date: 1205176200000, end_time: 1204314408000 },
+		{ id: 5402, created: 1204314413361, completed: 1204834364132, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'AGB 322', section: '02', exam_date: 1205176200000, end_time: 1204314413000 },
+		{ id: 5403, created: 1204315176468, completed: 1205787777855, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'AGB 322', section: '02', exam_date: 1205960400000, end_time: 1204315176000 },
+		{ id: 5404, created: 1204335924874, completed: 1205165567663, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'FRSC 415', section: '03', exam_date: 1205338200000, end_time: 1204335924000 },
+		{ id: 5405, created: 1204741820851, completed: 1204743423882, status: 'COMPLETED', completion_log: null, instructor_decision: 'somethinginvalid', course: 'FRSC 415', section: '02', exam_date: 1206731400000, end_time: 1206746700000 },
+		{ id: 5406, created: 1204744307957, completed: 1205274662191, status: 'TERMINATED', completion_log: null, instructor_decision: null, course: 'FRSC 415', section: '02', exam_date: 1206731400000, end_time: 1204744307000 },
+		{ id: 5407, created: 1204840355867, completed: 1205537683853, status: 'COMPLETED', completion_log: null, instructor_decision: 'YES', course: 'FRSC 415', section: '02', exam_date: 1206040200000, end_time: 1206055500000 },
+		{ id: 5504, created: 1205274223961, completed: 1205274408372, status: 'COMPLETED', completion_log: 'APPROVED', instructor_decision: 'YES', course: 'AGB 322', section: '01', exam_date: 1207579200000, end_time: 1207586400000 },
+		{ id: 5505, created: 1205274698075, completed: 1205274757197, status: 'TERMINATED', completion_log: null, instructor_decision: null, course: 'AGB 322', section: '01', exam_date: 1206974400000, end_time: 1205274698000 },
+		{ id: 5506, created: 1205274723562, completed: 1206628811409, status: 'COMPLETED', completion_log: 'TIMEOUT', instructor_decision: null, course: 'AGB 322', section: '01', exam_date: 1206974400000, end_time: 1205274723000 },
+		{ id: 4807, created: 1203037851016, completed: 1204045887212, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'FRSC 415', section: '03', exam_date: 1204218600000, end_time: null },
+		{ id: 4808, created: 1203037857289, completed: 1204045888187, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'FRSC 415', section: '03', exam_date: 1204218600000, end_time: null },
+		{ id: 4809, created: 1203039859756, completed: 1203970285117, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'AGB 322', section: '02', exam_date: 1204143000000, end_time: null },
+		{ id: 4810, created: 1203039862593, completed: 1203970285693, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'AGB 322', section: '02', exam_date: 1204143000000, end_time: null },
+		{ id: 4811, created: 1203039914652, completed: 1203970286217, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'FRSC 415', section: '02', exam_date: 1204143000000, end_time: null },
+		{ id: 4812, created: 1203039917115, completed: 1203970286693, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'FRSC 415', section: '02', exam_date: 1204143000000, end_time: null },
+		{ id: 4813, created: 1203718608148, completed: 1204226860378, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'WVIT 463', section: '01', exam_date: 1204330200000, end_time: null },
+		{ id: 4816, created: 1203720084402, completed: 1207077016546, status: 'COMPLETED', completion_log: null, instructor_decision: null, course: 'AGB 322', section: '02', exam_date: 1207249800000, end_time: null },
+		{ id: 5201, created: 1203725528974, completed: 1204243139125, status: 'TERMINATED', completion_log: null, instructor_decision: null, course: 'AGB 322', section: '02', exam_date: 1204747800000, end_time: null },
+		{ id: 5702, created: 1206489796519, completed: null, status: 'RUNNING', completion_log: null, instructor_decision: null, course: 'AGB 322', section: '01', exam_date: 1207320000000, end_time: 1206489796000 },
+		{ id: 5701, created: 1206462566705, completed: 1207077017340, status: 'COMPLETED', completion_log: 'TIMEOUT', instructor_decision: null, course: 'FRSC 415', section: '02', exam_date: 1207249800000, end_time: 1206462566000 },
+		{ id: 5703, created: 1206489800523, completed: null, status: 'RUNNING', completion_log: null, instructor_decision: null, course: 'AGB 322', section: '01', exam_date: 1207320000000, end_time: 1206489800000 },
+		{ id: 5704, created: 1206555988187, completed: 1207072817249, status: 'COMPLETED', completion_log: 'TIMEOUT', instructor_decision: null, course: 'FRSC 415', section: '02', exam_date: 1207245600000, end_time: 1206555988000 },
+		{ id: 5705, created: 1206556755331, completed: 1206557243510, status: 'COMPLETED', completion_log: 'APPROVED', instructor_decision: 'WITH_MODS', course: 'AGB 322', section: '01', exam_date: 1207320000000, end_time: 1207324020000 },
+		{ id: 5706, created: 1206557320052, completed: 1206557366393, status: 'COMPLETED', completion_log: 'APPROVED', instructor_decision: 'YES', course: 'FRSC 415', section: '02', exam_date: 1207336200000, end_time: 1207340220000 },
+		{ id: 5601, created: 1205522914023, completed: 1205522971080, status: 'COMPLETED', completion_log: 'REJECTED', instructor_decision: 'NO', course: 'FRSC 415', section: '02', exam_date: 1206645000000, end_time: 1205522914000 },
+		{ id: 5602, created: 1205522920401, completed: 1205523821411, status: 'COMPLETED', completion_log: 'APPROVED', instructor_decision: 'WITH_MODS', course: 'FRSC 415', section: '02', exam_date: 1206645000000, end_time: 1206660300000 },
+		{ id: 5603, created: 1205530930988, completed: 1205537697586, status: 'COMPLETED', completion_log: 'REJECTED', instructor_decision: 'NO', course: 'AGB 322', section: '02', exam_date: 1206558600000, end_time: 1205530930000 },
+		{ id: 5604, created: 1205539366682, completed: 1205881854926, status: 'COMPLETED', completion_log: 'APPROVED', instructor_decision: 'YES', course: 'WVIT 463', section: '01', exam_date: 1206745800000, end_time: 1206755700000 },
+		{ id: 5605, created: 1205539369772, completed: 1205539670553, status: 'COMPLETED', completion_log: 'APPROVED', instructor_decision: 'YES', course: 'WVIT 463', section: '01', exam_date: 1206745800000, end_time: 1206755700000 },
+		{ id: 5606, created: 1205882032439, completed: 1205967437022, status: 'COMPLETED', completion_log: 'APPROVED', instructor_decision: 'WITH_MODS', course: 'FRSC 415', section: '03', exam_date: 1206720600000, end_time: 1206725100000 },
+		{ id: 5607, created: 1206035981735, completed: 1206461410540, status: 'COMPLETED', completion_log: 'TIMEOUT', instructor_decision: null, course: 'FRSC 415', section: '03', exam_date: 1206634200000, end_time: 1206035981000 },
+		{ id: 5608, created: 1206035986106, completed: 1206461411245, status: 'COMPLETED', completion_log: 'TIMEOUT', instructor_decision: null, course: 'FRSC 415', section: '03', exam_date: 1206634200000, end_time: 120603598600 }
+	]
+};
+
+drc.filterPast = true;
+
+drc.courseFormat = function(course, rowIndex){
+	var item = this.grid.getItem(rowIndex);
+	var sec = this.grid.store.getValue(item, "section");
+	return course+"-"+sec;
+}
+
+drc.fullDateFormat = function(dateTime){
+	if(dateTime == null){
+		return null;
+	}
+	var d = new Date();
+	d.setTime(dateTime);
+	return dojo.date.locale.format(d, {datePattern:"MMM d y h:mm a",selector:'date'});
+}
+
+drc.timeFormat = function(dateTime){
+	if(dateTime == null){
+		return null;
+	}
+	var d = new Date();
+	d.setTime(dateTime);
+	return dojo.date.locale.format(d, {datePattern:"h:mm a",selector:'time'});
+}
+
+drc.filterPastChecked = function(value){
+	drc.filterPast = this.checked;
+	drc.grid.filter(null, true);
+}
+
+drc.statusFormat = function(value, rowIndex){
+	var item = this.grid.getItem(rowIndex);
+	var store = this.grid.store;
+	var state = store.getValue(item, "status");
+	var completion_log = store.getValue(item, "completion_log");
+	var instructor_decision = store.getValue(item, "instructor_decision");
+	var finishTime = store.getValue(item, "completed");
+	
+	if(state == 'RUNNING'){
+		return 'Pending Instructor Approval';
+	}
+	
+	var s = '';
+	if(state == 'TERMINATED'){
+		s += 'Canceled'
+	}
+	else if(state == 'COMPLETED'){
+		if(completion_log == 'APPROVED'){
+			s += 'Approved';
+			if(instructor_decision == 'WITH_MODS'){
+				s += ' with modifications';
+			}
+		}
+		else if(completion_log == 'REJECTED'){
+			s += 'Denied';
+		}
+		else if(completion_log == 'TIMEOUT'){
+			s += 'Expired';
+		}
+		else{
+			s += completion_log;
+		}
+	}
+	return s;
+}
+
+drc.onBeforeRow = function(inDataIndex, inRow){
+	if(inDataIndex < 0){
+		inRow[0].hidden = false;
+		return;
+	}
+	var item = this.grid.getItem(inDataIndex);
+	if(!item){ return; }
+	var store = this.grid.store;
+	if(inDataIndex >= 0) {
+		if (drc.filterPast) {
+			//If exam date is past, don't show
+			var exam_date = store.getValue(item, "exam_date");
+			if (exam_date < 1207088855078) { //use static time value so filter will always have something to filter
+				inRow[0].hidden = true;
+				return;
+			}
+		}
+	}
+	inRow[0].hidden=false;
+}
+
+drc.viewButtonFormat = function(value, rowIndex){
+	return '<a class="drc-view-button" href="'
+	+ drc.baseActionURL + '?submittedform=view&processId='+value+'"/>';
+}
+
+
+dojo.addOnLoad(function() {	
+	console.debug("initializing...");
+	
+	var check = new dijit.form.CheckBox({checked:true},"altTestingPastCheck");
+	dojo.connect(check,"onClick", drc.filterPastChecked);
+
+	var jsonStore = new dojo.data.ItemFileReadStore({ data: drc.gridData });
+	
+    var layout = [{
+		onBeforeRow: drc.onBeforeRow,
+		noscroll: true,
+		cells: [	
+			{name: 'Id',field:'id',width:3},
+			{name: 'Created',field:'created',formatter:drc.fullDateFormat,width:11},
+			{name: 'Status',field:'status',formatter:drc.statusFormat,width:13},
+			{name: 'Completed',field:'completed',formatter:drc.fullDateFormat,width:11},
+			{name: 'Course',field:'course',formatter:drc.courseFormat,width:7},
+			{name: 'Exam Date', field:'exam_date',formatter:drc.fullDateFormat,width:11},
+			{name: 'End Time', field:'end_time', formatter:drc.timeFormat,width:6},
+			{name: 'View',field:'id',width:3,formatter:drc.viewButtonFormat}			
+		]
+	}];
+	
+
+	drc.grid = new dojox.grid.DataGrid({store:jsonStore,structure:layout,query: { id: '*' },rowsPerPage:20,
+		autoHeight:true,autoWidth:true,style:"clear:both;"},"altTestingMainGrid");
+	drc.grid.startup();
+
+	console.debug("done.");
+});
+
+</script>
+		
+</head>
+
+<body class="tundra">
+		
+	
+	
+	<div id="altTestingPastCheck"></div>
+	<label for="altTestingPastCheck">Filter past exams (Exam Date before Apr 1, 2008)</label>
+	
+	<div style="background: red; padding: 10px 10px 10px 10px">
+	<div id="altTestingMainGrid"></div>
+	</div>
+	
+	
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_layout.html b/dojox/grid/tests/test_grid_layout.html
new file mode 100644
index 0000000..efb0d35
--- /dev/null
+++ b/dojox/grid/tests/test_grid_layout.html
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid in Layout Demo</title>
+	
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		html, body{	
+			width: 100%;	/* make the body expand to fill the visible window */
+			height: 100%;
+			padding: 0 0 0 0;
+			margin: 0 0 0 0;
+			overflow: hidden;
+		}
+		.dijitSplitPane{
+			margin: 5px;
+		}
+		
+		/* make grid containers overflow hidden */
+		body .dijitContentPane {
+			overflow: hidden;
+		}
+		#rightPane {
+			margin: 0;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: false"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dijit.layout.LayoutContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.LinkPane");
+		dojo.require("dijit.layout.SplitContainer");
+		dojo.require("dijit.layout.TabContainer");
+		
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout = [[
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6'},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+		var layout2 = [
+			{name: 'Alpha', field: 'col1'},
+			{name: 'Beta', field: 'col2'},
+			{name: 'Gamma', field: 'col3'},
+			{name: 'Delta', field: 'col4', width: "150px"},
+			{name: 'Epsilon', field: 'col5'},
+			{name: 'Nexilon', field: 'col6'},
+			{name: 'Zeta', field: 'col7'},
+			{name: 'Eta', field: 'col1'},
+			{name: 'Omega', field: 'col8'}
+		];
+		//
+		dojo.addOnLoad(function(){
+			dijit.byId("grid3").update();
+		});
+	</script>
+</head>
+<body class="tundra">
+	<div id="outer" dojoType="dijit.layout.LayoutContainer"
+		style="width: 100%; height: 100%;">
+		<div id="topBar" dojoType="dijit.layout.ContentPane" layoutAlign="top"
+			style="background-color: #274383; color: white;">
+			top bar
+		</div>
+		<div id="bottomBar" dojoType="dijit.layout.ContentPane" layoutAlign="bottom"
+			style="background-color: #274383; color: white;">
+			bottom bar
+		</div>
+		<div id="horizontalSplit" dojoType="dijit.layout.SplitContainer"
+			orientation="horizontal"
+			sizerWidth="5"
+			activeSizing="false"
+			layoutAlign="client"
+		>
+			<div id="leftPane" dojoType="dijit.layout.ContentPane"
+				 sizeMin="20" sizeShare="20">
+				Left side
+			</div>
+
+			<div id="rightPane"
+				dojoType="dijit.layout.SplitContainer"
+				orientation="vertical"
+				sizerWidth="5"
+				activeSizing="false"
+				sizeMin="50" sizeShare="80"
+			>
+				<div id="mainTabContainer" dojoType="dijit.layout.TabContainer" sizeMin="20" sizeShare="70">
+					<div id="grid1" dojoType="dojox.grid.DataGrid" store="test_store" structure="layout" title="Tab 1"></div>
+					<div id="grid2" dojoType="dojox.grid.DataGrid" store="test_store" structure="layout2" title="Tab 2"></div>
+				</div>
+				<div id="bottomRight" dojoType="dijit.layout.ContentPane" sizeMin="20" sizeShare="30">
+					<div id="grid3" dojoType="dojox.grid.DataGrid" store="test_store" structure="layout2"></div>
+				</div>
+			</div>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_layout_LayoutContainer.html b/dojox/grid/tests/test_grid_layout_LayoutContainer.html
new file mode 100644
index 0000000..a27f456
--- /dev/null
+++ b/dojox/grid/tests/test_grid_layout_LayoutContainer.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid in Layout Demo</title>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		html, body{	
+			width: 100%;	/* make the body expand to fill the visible window */
+			height: 100%;
+			padding: 0 0 0 0;
+			margin: 0 0 0 0;
+			overflow: hidden;
+		}
+		.dijitSplitPane{
+			margin: 5px;
+		}
+		
+		/* make grid containers overflow hidden */
+		body .dijitContentPane {
+			overflow: hidden;
+		}
+		#rightPane {
+			margin: 0;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: false"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dijit.layout.LayoutContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.LinkPane");
+		dojo.require("dijit.layout.SplitContainer");
+		dojo.require("dijit.layout.TabContainer");
+		
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout = [[
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6'},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+		var layout2 = [
+			{name: 'Alpha', field: 'col1'},
+			{name: 'Beta', field: 'col2'},
+			{name: 'Gamma', field: 'col3'},
+			{name: 'Delta', field: 'col4', width: "150px"},
+			{name: 'Epsilon', field: 'col5'},
+			{name: 'Nexilon', field: 'col6'},
+			{name: 'Zeta', field: 'col7'},
+			{name: 'Eta', field: 'col1'},
+			{name: 'Omega', field: 'col8'}
+		];
+	</script>
+</head>
+<body class="tundra">
+	<div id="outer" dojoType="dijit.layout.LayoutContainer"
+		style="width: 100%; height: 100%;">
+		
+		<div id="topBar" dojoType="dijit.layout.ContentPane" layoutAlign="top"
+			style="background-color: #274383; color: white; height:100px">
+			top bar
+		</div>
+		<div id="bottomBar" dojoType="dijit.layout.ContentPane" layoutAlign="bottom"
+			style="background-color: #274383; color: white;">
+			bottom bar
+		</div>
+
+		<div id="grid1" dojoType="dojox.grid.DataGrid" store="test_store" 
+			structure="layout" layoutAlign="client"></div>
+	</div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_layout_borderContainer.html b/dojox/grid/tests/test_grid_layout_borderContainer.html
new file mode 100644
index 0000000..dd43d5e
--- /dev/null
+++ b/dojox/grid/tests/test_grid_layout_borderContainer.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+	<head>
+		<title>Test dojox.grid.Grid layout in a BorderContainer</title>
+		<style>
+			@import "../resources/Grid.css";
+			@import "../resources/tundraGrid.css";
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+
+			html, body {
+				width: 100%;	/* make the body expand to fill the visible window */
+				height: 100%;
+				overflow: hidden;	/* erase window level scrollbars */
+				padding: 0 0 0 0;
+				margin: 0 0 0 0;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug: false, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dojox.grid.DataGrid");
+			dojo.require("dojo.data.ItemFileWriteStore");
+			dojo.require("dijit.layout.BorderContainer");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dojo.parser");
+
+
+			// ==========================================================================
+			// Grid structure
+			// ==========================================================================
+			gridLayout = {
+				defaultCell: { width: 8, editable: true, styles: 'text-align: right;'  },
+				cells: [
+					{ name: 'Id', width: 3, field: 'id' },
+					{ name: 'Priority', field: 'col1', styles: 'text-align: center;', type: dojox.grid.cells.Select, options: ["normal", "note", "important"]},
+					{ name: 'Mark', field: 'col2', width: 3, styles: 'text-align: center;', type: dojox.grid.cells.Bool },
+					{ name: 'Status', field: 'col3', styles: 'text-align: center;', type: dojox.grid.cells.Select, options: [ "new", "read", "replied" ]},
+					{ name: 'Message', field: 'col4', styles: '', width: '100%' },
+					{ name: 'Amount', field: 'col5'}
+				]
+			};
+		</script>
+		<script type="text/javascript" src="support/test_data.js"></script>
+	</head>
+	<body class="tundra">
+		<div dojoType="dijit.layout.BorderContainer" liveSplitters="false" persist="true"
+		          id="verticalSplitParam" design="headline" style="width: 100%; height: 100%;">
+
+		  <div dojoType="dijit.layout.ContentPane" id="mybuttons"
+		             region="top" splitter="false">  
+		     <button onclick="grid.render()">Refresh</button>
+		     <button onclick="grid.edit.focusEditor()">Focus Editor</button>
+		     <button onclick="grid.focus.next()">Next Focus</button>
+		     <button onclick="addRow()">Add Row</button>
+		     <button onclick="grid.removeSelectedRows()">Remove</button>
+		     <button onclick="grid.edit.apply()">Apply</button>
+		     <button onclick="grid.edit.cancel()">Cancel</button>
+		     <button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button>
+		  </div>
+		
+		  <div jsId="grid" class="myGrid" dojoType="dojox.grid.DataGrid" store="test_store" structure="gridLayout"
+		  	region="center">
+		  </div>
+
+		  <div jsId="gridBottom" class="myGrid"	dojoType="dojox.grid.DataGrid" store="test_store" structure="gridLayout"
+		  	region="bottom" splitter="true" style="height: 100px;">
+		  </div>
+		   
+		</div>
+
+	</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_messages.html b/dojox/grid/tests/test_grid_messages.html
new file mode 100644
index 0000000..2041b81
--- /dev/null
+++ b/dojox/grid/tests/test_grid_messages.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test Grid Messaging</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		.grid {
+			width: 65em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+		
+		dojo.declare("dojox.grid.SlowFileWriteStore", dojo.data.ItemFileWriteStore, {
+			_fetchItems: function(	/*Object*/ keywordArgs, 
+									/*Function*/ findCallback, 
+									/*Function*/ errorCallback){
+				setTimeout(dojo.hitch(this, function(){
+					dojo.data.ItemFileWriteStore.prototype._fetchItems.call(this, keywordArgs, findCallback, errorCallback);
+				}), 10000);
+			}
+		});
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<span dojoType="dojox.grid.SlowFileWriteStore" 
+		jsId="jsonStore1" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore2" url="../../../dijit/tests/_data/countries-no.json">
+	</span>
+	<div class="heading">Grid Messaging Test - Standard</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" class="grid" 
+		store="jsonStore" query="{ name: 'A*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table><br>
+	<div class="heading">Grid Messaging Test - Loading</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid1" id="grid1" class="grid"
+		store="jsonStore1" query="{ name: 'A*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table><br>
+	<div class="heading">Grid Messaging Test - Empty</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid2" id="grid2" class="grid"
+		store="jsonStore" query="{ name: 'nonexist' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+	<div class="heading">Grid Messaging Test - Error</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid3" id="grid3" class="grid"
+		store="jsonStore2" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_messages_autoheight.html b/dojox/grid/tests/test_grid_messages_autoheight.html
new file mode 100644
index 0000000..d1b4d12
--- /dev/null
+++ b/dojox/grid/tests/test_grid_messages_autoheight.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test Grid Messaging - autoHeight</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		.grid {
+			width: 65em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+		
+		dojo.declare("dojox.grid.SlowFileWriteStore", dojo.data.ItemFileWriteStore, {
+			_fetchItems: function(	/*Object*/ keywordArgs, 
+									/*Function*/ findCallback, 
+									/*Function*/ errorCallback){
+				setTimeout(dojo.hitch(this, function(){
+					dojo.data.ItemFileWriteStore.prototype._fetchItems.call(this, keywordArgs, findCallback, errorCallback);
+				}), 10000);
+			}
+		});
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<span dojoType="dojox.grid.SlowFileWriteStore" 
+		jsId="jsonStore1" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore2" url="../../../dijit/tests/_data/countries-no.json">
+	</span>
+	<div class="heading">Grid Messaging Test - Standard</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid" id="grid" class="grid" autoHeight="true"
+		store="jsonStore" query="{ name: 'A*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table><br>
+	<div class="heading">Grid Messaging Test - Loading</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid1" id="grid1" class="grid" autoHeight="true"
+		store="jsonStore1" query="{ name: 'A*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table><br>
+	<div class="heading">Grid Messaging Test - Empty</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid2" id="grid2" class="grid" autoHeight="true"
+		store="jsonStore" query="{ name: 'nonexist' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+	<div class="heading">Grid Messaging Test - Error</div>
+	<table dojoType="dojox.grid.DataGrid"
+		jsid="grid3" id="grid3" class="grid" autoHeight="true"
+		store="jsonStore2" query="{ name: '*' }" rowsPerPage="20" rowSelector="20px">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_performance.html b/dojox/grid/tests/test_grid_performance.html
new file mode 100644
index 0000000..35d99ec
--- /dev/null
+++ b/dojox/grid/tests/test_grid_performance.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.DataGrid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout = [[
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6'},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+	</script>
+	<script type="text/javascript">
+		var startCreationTests = function(){
+			setTimeout(function(){
+				var total_time = 0;
+				for(var i=0; i<30; i++){
+					//var mod = new dojox.grid._data.Table(null, data);
+
+					var st_time = new Date().getTime();
+					var grid = new dojox.grid.DataGrid({
+						store: test_store,
+						structure: layout
+					});
+					dojo.body().appendChild(grid.domNode);
+					grid.startup();
+					total_time += (new Date().getTime() - st_time);
+					dojo.body().removeChild(grid.domNode);
+				}
+				console.log("Average time for programmatic creation with no source node: ", total_time / 30);
+				setTimeout(function(){
+					total_time = 0;
+					for(var i=0; i<30; i++){
+						//var mod = new dojox.grid._data.Table(null, data);
+						var node = dojo.doc.createElement("div");
+						dojo.body().appendChild(node);
+						var st_time = new Date().getTime();
+						var grid = new dojox.grid.DataGrid({
+							store: test_store,
+							structure: layout
+						}, node);
+						total_time += (new Date().getTime() - st_time);
+						dojo.body().removeChild(grid.domNode);
+					}
+					console.log("Average time for programmatic creation with source node: ", total_time / 30);
+				}, 1000);
+			}, 1000);
+		}
+		var startStoreReuseTests = function(){
+			setTimeout(function(){
+				var total_time = 0;
+				for(var i=0; i<30; i++){
+
+					var st_time = new Date().getTime();
+					var mod = new dojo.data.ItemFileReadStore({data: data});
+					var grid = new dojox.grid.DataGrid({
+						store: mod,
+						structure: layout
+					});
+					dojo.body().appendChild(grid.domNode);
+					grid.startup();
+					total_time += (new Date().getTime() - st_time);
+					dojo.body().removeChild(grid.domNode);
+				}
+				console.log("Total time to create 30 grids with separate stores (including store creation time): ", total_time);
+				setTimeout(function(){
+					total_time = 0;
+					var mod = new dojo.data.ItemFileReadStore({data: data});
+					for(var i=0; i<30; i++){
+						var node = dojo.doc.createElement("div");
+						dojo.body().appendChild(node);
+						var st_time = new Date().getTime();
+						var grid = new dojox.grid.DataGrid({
+							store: mod,
+							structure: layout
+						});
+						dojo.body().appendChild(grid.domNode);
+						grid.startup();
+						total_time += (new Date().getTime() - st_time);
+						dojo.body().removeChild(grid.domNode);
+					}
+					console.log("Total time to create 30 grids with a shared store: ", total_time);
+				}, 1000);
+			}, 1000);
+		}
+	</script>
+</head>
+<body>
+	<div class="heading">dojox.grid.DataGrid Performance Test</div>
+	<button onclick="startCreationTests()">Start Creation Tests</button>
+	<button onclick="startStoreReuseTests()">Start Store Re-use Tests</button>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_programmatic.html b/dojox/grid/tests/test_grid_programmatic.html
new file mode 100644
index 0000000..8490949
--- /dev/null
+++ b/dojox/grid/tests/test_grid_programmatic.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+	<head>
+		<title>Test dojox.grid.DataGrid Programmatic Instantiation</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../resources/Grid.css";
+			@import "../resources/tundraGrid.css";
+			.heading {
+				font-weight: bold;
+				padding-bottom: 0.25em;
+			}
+					
+			#grid { 
+				border: 1px solid #333;
+				width: 50em;
+				height: 30em;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" 
+			djConfig="isDebug:false, debugAtAllCosts: false, parseOnLoad: true"></script>
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dojox.grid.DataGrid");
+			dojo.require("dojo.data.ItemFileWriteStore");
+			dojo.require("dojo.parser");
+		</script>
+		<script type="text/javascript" src="support/test_data.js"></script>
+		<script type="text/javascript">
+			var grid = null;
+			dojo.addOnLoad(function(){
+				var layout = [[
+					{name: 'Column 1', field: 'col1'},
+					{name: 'Column 2', field: 'col2'},
+					{name: 'Column 3', field: 'col3'},
+					{name: 'Column 4', field: 'col4', width: "150px"},
+					{name: 'Column 5', field: 'col5'}
+				],[
+					{name: 'Column 6', field: 'col6'},
+					{name: 'Column 7', field: 'col7'},
+					{name: 'Column 8'},
+					{name: 'Column 9', field: 'col3', colSpan: 2}
+				]];
+
+				grid = new dojox.grid.DataGrid({
+					id: "grid",
+					store: test_store,
+					structure: layout
+				}, document.createElement('div'));
+				dojo.byId("gridContainer").appendChild(grid.domNode);
+				grid.startup();
+			});
+		</script>
+	</head>
+	<body class="tundra">
+		<div class="heading">dojox.grid.DataGrid Programmatic Instantiation Test</div>
+		<div id="gridContainer"></div>
+	</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_programmatic_layout.html b/dojox/grid/tests/test_grid_programmatic_layout.html
new file mode 100644
index 0000000..693f5c2
--- /dev/null
+++ b/dojox/grid/tests/test_grid_programmatic_layout.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+	<head>
+		<title>Test dojox.grid.Grid Programmatic Instantiation</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+		<style type="text/css">
+			@import "../resources/Grid.css";
+			@import "../resources/tundraGrid.css";
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+			.heading {
+				font-weight: bold;
+				padding-bottom: 0.25em;
+			}
+					
+			#grid { 
+				width: 100%;
+				height: 100%;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" 
+			djConfig="isDebug:false, debugAtAllCosts: false, parseOnLoad: true"></script>
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dijit.layout.TabContainer");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dojox.grid.DataGrid");
+			dojo.require("dojo.data.ItemFileWriteStore");
+			dojo.require("dojo.parser");
+		</script>
+		<script type="text/javascript" src="support/test_data.js"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+
+				var tc = new dijit.layout.TabContainer({
+					style:"height: 300px; width: 100%;"
+				}, "mainTabContainer");
+				var cp = new dijit.layout.ContentPane({ title:"Tab 2" }, "cp");
+				tc.addChild(cp);
+				tc.startup();
+				
+				var layout = [[
+					{name: 'Column 1', field: 'col1'},
+					{name: 'Column 2', field: 'col2'},
+					{name: 'Column 3', field: 'col3'},
+					{name: 'Column 4', field: 'col4', width: "150px"},
+					{name: 'Column 5', field: 'col5'}
+				],[
+					{name: 'Column 6', field: 'col6'},
+					{name: 'Column 7', field: 'col7'},
+					{name: 'Column 8'},
+					{name: 'Column 9', field: 'col3', colSpan: 2}
+				]];
+
+				var grid = new dojox.grid.DataGrid({
+					title: "tab 1",
+					id: "grid",
+					store: test_store,
+					structure: layout
+				});
+				tc.addChild(grid, 0);
+			});
+		</script>
+	</head>
+	<body class="tundra">
+		<div class="heading">dojox.grid.Grid Programmatic Instantiation Test</div>
+		<div id="mainTabContainer">
+			<div id="cp">
+				... stuff ...
+			</div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_programmatic_leak_test.html b/dojox/grid/tests/test_grid_programmatic_leak_test.html
new file mode 100644
index 0000000..7b4274e
--- /dev/null
+++ b/dojox/grid/tests/test_grid_programmatic_leak_test.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+	<head>
+		<title>Test dojox.grid.DataGrid Programmatic Instantiation</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../resources/Grid.css";
+			@import "../resources/tundraGrid.css";
+
+			.heading {
+				font-weight: bold;
+				padding-bottom: 0.25em;
+			}
+					
+			#grid { 
+				border: 1px solid #333;
+				width: 50em;
+				height: 30em;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" 
+			djConfig="isDebug:false, debugAtAllCosts: false, parseOnLoad: true"></script>
+		<script type="text/javascript">
+			dojo.require("dijit.dijit"); // optimize: load dijit layer
+			dojo.require("dojox.grid.DataGrid");
+			dojo.require("dojo.data.ItemFileWriteStore");
+			dojo.require("dojo.parser");
+		</script>
+		<script type="text/javascript" src="support/test_data.js"></script>
+		<script type="text/javascript">
+			var grid = null;
+			var layout = [[
+				{name: 'Column 1', field: 'col1'},
+				{name: 'Column 2', field: 'col2'},
+				{name: 'Column 3', field: 'col3'},
+				{name: 'Column 4', field: 'col4', width: "150px"},
+				{name: 'Column 5', field: 'col5'}
+			],[
+				{name: 'Column 6', field: 'col6'},
+				{name: 'Column 7', field: 'col7'},
+				{name: 'Column 8'},
+				{name: 'Column 9', field: 'col3', colSpan: 2}
+			]];
+
+			function toggleGrid() {
+				if (grid) {
+					grid.destroy();
+					grid = null;
+					dojo.byId("toggleGridButton").innerHTML = "Create grid";
+				}
+				else {
+					grid = new dojox.grid.DataGrid({
+						id: "grid",
+						store: test_store,
+						structure: layout
+					});
+
+					dojo.byId("toggleGridButton").innerHTML = "Destroy grid";
+
+					dojo.byId("gridContainer").appendChild(grid.domNode);
+					grid.startup();
+				}
+			}
+		</script>
+	</head>
+	<body class="tundra">
+		<div class="heading">dojox.grid.DataGrid Programmatic Instantiation Test</div>
+		<button id="toggleGridButton" onClick="toggleGrid();">Create grid</button>
+		<div id="gridContainer"></div>
+	</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_rtl.html b/dojox/grid/tests/test_grid_rtl.html
new file mode 100644
index 0000000..6c218ec
--- /dev/null
+++ b/dojox/grid/tests/test_grid_rtl.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/Grid_rtl.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/tundra/tundra_rtl.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid {
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+
+		var layout = [[
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6'},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body dir="rtl" class="tundra">
+	<div class="heading">dojox.grid.Grid Basic Test</div>
+	<div id="grid" dojoType="dojox.grid.DataGrid" 
+		query="{ id: '*' }" store="test_store" structure="layout"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_selectors.html b/dojox/grid/tests/test_grid_selectors.html
new file mode 100644
index 0000000..62bf66e
--- /dev/null
+++ b/dojox/grid/tests/test_grid_selectors.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid {
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojox.grid._CheckBoxSelector");
+		dojo.require("dojox.grid._RadioSelector");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout_check = [{
+			type: "dojox.grid._CheckBoxSelector"
+		},{ cells: [[
+			new dojox.grid.cells.RowIndex({ width: 5 }),
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6', colSpan: 2},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]]}];
+		var layout_radio = [{
+			type: "dojox.grid._RadioSelector"
+		},{ cells: [[
+			new dojox.grid.cells.RowIndex({ width: 5 }),
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6', colSpan: 2},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]]}];
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.Grid CheckBox Selector</div>
+	<div jsId="grid_check" id="grid_check" dojoType="dojox.grid.DataGrid" 
+		store="test_store" query="{ id: '*' }" 
+		structure="layout_check"></div>
+	<div class="heading">dojox.grid.Grid Radio Selector</div>
+	<div jsId="grid_radio" id="grid_radio" dojoType="dojox.grid.DataGrid" 
+		store="test_store" query="{ id: '*' }" 
+		structure="layout_radio"></div>
+	<div class="heading">dojox.grid.Grid CheckBox Selector - no data</div>
+	<div jsId="grid_empty" id="grid_empty" dojoType="dojox.grid.DataGrid" 
+		store="test_store" query="{ id: 'abc' }" 
+		structure="layout_check"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_simple_structure.html b/dojox/grid/tests/test_grid_simple_structure.html
new file mode 100644
index 0000000..50a33dc
--- /dev/null
+++ b/dojox/grid/tests/test_grid_simple_structure.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Simple Structure</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid {
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+
+		var layout = [
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		];
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body>
+	<div class="heading">dojox.grid.Grid Basic Test</div>
+	<div jsid="grid" id="grid" dojoType="dojox.grid.DataGrid" 
+		store="test_store" structure="layout"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_simple_structure2.html b/dojox/grid/tests/test_grid_simple_structure2.html
new file mode 100644
index 0000000..f266fa8
--- /dev/null
+++ b/dojox/grid/tests/test_grid_simple_structure2.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Simple Structure</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid {
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+
+		var layout = [[
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6'},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body>
+	<div class="heading">dojox.grid.Grid Basic Test</div>
+	<div jsid="grid" id="grid" dojoType="dojox.grid.DataGrid" 
+		store="test_store" structure="layout"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_tab_container.html b/dojox/grid/tests/test_grid_tab_container.html
new file mode 100644
index 0000000..adb4a32
--- /dev/null
+++ b/dojox/grid/tests/test_grid_tab_container.html
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>TabContainer Demo</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../css/dijitTests.css";
+
+		body {
+			font-family : sans-serif;
+			margin:20px;
+		}
+
+		/* add padding to each contentpane inside the tab container, and scrollbar if necessary */
+		.dojoTabPane {
+			padding : 10px 10px 10px 10px;
+			overflow: auto;
+		}
+	</style>
+	
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.SplitContainer");
+		dojo.require("dijit.Tooltip");
+		dojo.require("dijit.layout.LinkPane");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	
+	
+	</script>
+	
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid {
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout = [[
+			new dojox.grid.cells.RowIndex({ width: 5 }),
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6', colSpan: 2},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+		function updateGrid() { var grid = dijit.byId('grid'); grid.update()}
+	</script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">Dijit layout.TabContainer tests</h1>
+
+	<p>These tabs are made up of local and external content. Tab 1 and Tab 2 are loading
+	files tab1.html and tab2.html. Tab 3 and Another Tab are using content that is already
+	part of this page.   Tab2 is initially selected. Attribute tabStrip is set to true
+	</p>
+
+	<div id="mainTabContainer" dojoType="dijit.layout.TabContainer" tabStrip="true" style="width: 100%; height: 20em;">
+
+		<div id="tab1" dojoType="dijit.layout.ContentPane"  title="Tab 1">
+			<h1>Test refreshing grid</h1>
+			<br/>
+			
+			
+			<div jsid="grid" id="grid" dojoType="dojox.grid.DataGrid" store="test_store" query="{ id: '*' }" structure="layout" rowSelector="20px"></div>
+		</div>
+
+		
+
+		<div dojoType="dijit.layout.ContentPane" title="Tab 2">
+			<h1>I am tab 2</h1>
+		
+			<br/>
+			<button dojoType="dijit.form.Button" onclick="updateGrid">Click here for refreshing grid on Tab 1</button>
+			<br>
+			
+			<p>
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean
+			semper sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin
+			porta rutrum lacus. Etiam consequat scelerisque quam. Nulla facilisi.
+			Maecenas luctus venenatis nulla. In sit amet dui non mi semper iaculis.
+			Sed molestie tortor at ipsum. Morbi dictum rutrum magna. Sed vitae
+			risus.
+			</p>
+			<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+			imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer lorem
+			nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in
+			massa bibendum suscipit. Integer eros. Nullam suscipit mauris. In
+			pellentesque. Mauris ipsum est, pharetra semper, pharetra in, viverra
+			quis, tellus. Etiam purus. Quisque egestas, tortor ac cursus lacinia,
+			felis leo adipiscing nisi, et rhoncus elit dolor eget eros. Fusce ut
+			quam. Suspendisse eleifend leo vitae ligula. Nulla facilisi. Nulla
+			rutrum, erat vitae lacinia dictum, pede purus imperdiet lacus, ut
+			semper velit ante id metus. Praesent massa dolor, porttitor sed,
+			pulvinar in, consequat ut, leo. Nullam nec est. Aenean id risus blandit
+			tortor pharetra congue. Suspendisse pulvinar.
+			</p>
+		</div>
+
+		
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_themes.html b/dojox/grid/tests/test_grid_themes.html
new file mode 100644
index 0000000..51d631e
--- /dev/null
+++ b/dojox/grid/tests/test_grid_themes.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid themes</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../resources/soriaGrid.css";
+		@import "../resources/nihiloGrid.css";
+		@import "../resources/claroGrid.css";
+		
+		#grid, #grid2, #grid3 {
+			width: 65em;
+			height: 25em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojox.grid.EnhancedGrid");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dojox.data.CsvStore");
+		dojo.require("dojo.parser");
+	</script>
+
+</head>
+<body>
+	<h5>dojox.grid.Grid structure from markup (tundra theme)</h5>
+	<span dojoType="dojox.data.CsvStore" 
+		jsId="csvStore" url="support/movies.csv">
+	</span>
+
+	<table class="tundra" dojoType="dojox.grid.DataGrid"
+		store="csvStore"
+		query="{ Title: '*' }"
+		style="width: 800px; height: 300px;">
+		<thead>
+			<tr>
+				<th width="300px" field="Title">Title of Movie</th>
+
+				<th width="5em" field="Year">Year</th>
+			</tr>
+			<tr>
+				<th colspan="2" field="Producer">Producer</th>
+			</tr>
+		</thead>
+	</table>
+
+	<span dojoType="dojo.data.ItemFileReadStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<h5>Locked views specified with tables and colgroups (soria theme)</h5>
+
+	<table class="soria" dojoType="dojox.grid.DataGrid"
+		store="jsonStore"
+		rowsPerPage="20"
+		query="{ name: '*' }"
+		style="width: 600px; height: 300px;">
+		<colgroup span="1" noscroll="true" width="300px"></colgroup>
+		<colgroup span="4"></colgroup>
+		<thead>
+
+			<tr>
+				<th field="name" width="auto">Country/Continent Name</th>
+				<th width="100px" field="population">Population</th>
+				<th width="100px" field="area">Land Mass</th>
+				<th width="100px" field="timezone">Time Zone</th>
+				<th width="5em" field="type">Type</th>
+
+			</tr>
+		</thead>
+	</table>
+	
+	<h5>Simple Claro DataGrid(currently an EnhancedGrid without any feature plugins)</h5>
+	<script type="text/javascript">
+		var layout = [{
+			defaultCell: { width: 8, editable: false, type: dojox.grid.cells._Widget },
+			rows:
+			[
+				{ field: "Genre", width: '6'},
+				{ field: "Artist", width: '10'},
+				{ field: "Year", width: '6'},
+				{ field: "Album", width: '12'},
+				{ field: "Name", width: '17'},
+				{ field: "Length", width: '6'},
+				{ field: "Track", width: '6'},
+				{ field: "Composer", width: '15'}				
+			]}
+		];
+		var csvStore1 = new dojox.data.CsvStore({id:'csvStore1', url:"enhanced/support/music-for-demo.part.csv"});
+	</script>
+	<div class="claro" id="grid3" dojoType="dojox.grid.EnhancedGrid" query="{ Track: '*' }" rowsPerPage="30"
+		 store="csvStore1" structure="layout" rowSelector="0px">
+	</div>
+	
+
+	<script type="text/javascript">
+		var layoutCountries = [
+			// view 1
+			{
+				noscroll: true,
+				cells: [ new dojox.grid.cells.RowIndex({width: 5}) ]
+			},
+			// view 2
+			{
+				cells: [
+					{ name: 'Country/Continent Name', field: 'name', width: 'auto' },
+					{ name: 'Type', field: 'type', width: 8 }
+				]
+			}
+		];
+	</script>
+
+	<h5>A "regular" Grid from markup (no table defintion, nihilo theme)</h5>
+	<div class="nihilo" id="grid2" dojoType="dojox.grid.DataGrid" elasticView="2" 
+		store="jsonStore" query="{ name: '*' }" rowSelector="20px" rowsPerPage="20" structure="layoutCountries">
+	</div>
+
+</body>
+</html>
diff --git a/dojox/grid/tests/test_grid_tooltip_menu.html b/dojox/grid/tests/test_grid_tooltip_menu.html
new file mode 100644
index 0000000..ba246b1
--- /dev/null
+++ b/dojox/grid/tests/test_grid_tooltip_menu.html
@@ -0,0 +1,169 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid { 
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dijit.Tooltip");
+		dojo.require("dijit.Menu");
+		dojo.require("dijit.ColorPalette");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout = [[
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6'},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+		dojo.addOnLoad(function() {
+			var 
+				showTooltip = function(e) {
+					if(gridTooltipEnabled){
+						var msg = "This is cell " + e.rowIndex + ", " + e.cellIndex;
+						dijit.showTooltip(msg, e.cellNode);
+					}
+				},
+				hideTooltip = function(e) {
+					dijit.hideTooltip(e.cellNode);
+					// FIXME: make sure that pesky tooltip doesn't reappear!
+					// would be nice if there were a way to hide tooltip without regard to aroundNode.
+					dijit._masterTT._onDeck=null;
+				}
+			
+			// cell tooltip
+			dojo.connect(grid, "onCellMouseOver", showTooltip);
+			dojo.connect(grid, "onCellMouseOut", hideTooltip);
+			// header cell tooltip
+			dojo.connect(grid, "onHeaderCellMouseOver", showTooltip);
+			dojo.connect(grid, "onHeaderCellMouseOut", hideTooltip);
+
+			// grid menu
+			window["gridMenu"] = dijit.byId("gridMenu");
+			gridMenu.bindDomNode(grid.domNode);
+			// prevent grid methods from killing the context menu event by implementing our own handler
+			grid.onCellContextMenu = function(e) {
+				cellNode = e.cellNode;
+			};
+			grid.onHeaderContextMenu = function(e) {
+				cellNode = e.cellNode;
+			};
+		});
+		
+		function reportCell() {
+			if(cellNode){
+				alert("Cell contents:  " + cellNode.innerHTML);
+				cellNode = null;
+			}
+		}
+		
+		gridTooltipEnabled = true;
+		function toggleTooltip(button){
+			gridTooltipEnabled = !gridTooltipEnabled;
+			button.value = gridTooltipEnabled ? "Disable Grid Tooltip" : "Enable Grid Tooltip";
+		}
+		
+		gridMenuEnabled = true;
+		function toggleMenu(button){
+			gridMenuEnabled = !gridMenuEnabled;
+			button.value = gridMenuEnabled ? "Disable Grid Menu" : "Enable Grid Menu";
+			gridMenu[gridMenuEnabled ? "bindDomNode" : "unBindDomNode"](grid.domNode);
+		}
+	</script>
+</head>
+<body class="tundra">
+	<div dojoType="dijit.Menu" id="gridMenu"  style="display: none;">
+		<div dojoType="dijit.MenuItem" onClick="reportCell">See cell text...</div>
+		<div dojoType="dijit.MenuItem" disabled="true">Disabled Item</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+			onClick="alert('not actually cutting anything, just a test!')">Cut</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+			onClick="alert('not actually copying anything, just a test!')">Copy</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+			onClick="alert('not actually pasting anything, just a test!')">Paste</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+	</div>
+	<div dojoType="dijit.Menu" id="submenu1" contextMenuForWindow="true" style="display: none;">
+		<div dojoType="dijit.MenuItem" onClick="alert('Hello world');">Enabled Item</div>
+		<div dojoType="dijit.MenuItem" disabled="true">Disabled Item</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+			onClick="alert('not actually cutting anything, just a test!')">Cut</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+			onClick="alert('not actually copying anything, just a test!')">Copy</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+			onClick="alert('not actually pasting anything, just a test!')">Paste</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Enabled Submenu</span>
+			<div dojoType="dijit.Menu" id="submenu2">
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</div>
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</div>
+				<div dojoType="dijit.PopupMenuItem">
+					<span>Deeper Submenu</span>
+					<div dojoType="dijit.Menu" id="submenu4">
+						<div dojoType="dijit.MenuItem" onClick="alert('Sub-submenu 1!')">Sub-sub-menu Item One</div>
+						<div dojoType="dijit.MenuItem" onClick="alert('Sub-submenu 2!')">Sub-sub-menu Item Two</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem" disabled="true">
+			<span>Disabled Submenu</span>
+			<div dojoType="dijit.Menu" id="submenu3" style="display: none;">
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</div>
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</div>
+			</div>
+		</div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Different popup</span>
+			<div dojoType="dijit.ColorPalette"></div>
+		</div>
+	</div>
+	<div class="heading">dojox.grid.Grid Basic Test</div>
+	<p>
+		<input type="button" onclick="toggleTooltip(this)" value="Disable Grid Tooltip">  
+		<input type="button" onclick="toggleMenu(this)" value="Disable Grid Menu">  <br />
+		Note: when the grid menu is disabled, the document's dijit context menu should be shown over the grid.
+	</p>
+	<div id="grid" jsid="grid" dojoType="dojox.grid.DataGrid" 
+		store="test_store" structure="layout"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_keyboard.html b/dojox/grid/tests/test_keyboard.html
new file mode 100644
index 0000000..7e0e6af
--- /dev/null
+++ b/dojox/grid/tests/test_keyboard.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Basic</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+			margin-left:5em;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid { 
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var layout = [
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'},
+			{name: 'Column 6', field: 'col6'},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3'},
+			{name: 'Column 10', field: 'col1'},
+			{name: 'Column 11', field: 'col2'},
+			{name: 'Column 12', field: 'col3'},
+			{name: 'Column 13', field: 'col4', width: "150px"},
+			{name: 'Column 14', field: 'col5'},
+			{name: 'Column 15', field: 'col6'},
+			{name: 'Column 16', field: 'col7'},
+			{name: 'Column 17'},
+			{name: 'Column 18', field: 'col3'}
+		];
+
+		function keyDown(e) {
+			switch(e.keyCode){
+				case dojo.keys.LEFT_ARROW:
+					console.log('left arrow!');
+					break;
+				case dojo.keys.RIGHT_ARROW:
+					console.log('right arrow!');
+					break;
+				case dojo.keys.ENTER:
+					console.log('enter!');
+					break;
+			}
+		}
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading" tabindex="0">dojox.grid.Grid Basic Test</div>
+	<div id="grid" jsid="grid" dojoType="dojox.grid.DataGrid" 
+		store="test_store" structure="layout">
+		<script type="dojo/connect" event="onKeyDown" args="e">
+			keyDown(e);
+		</script>
+	</div>
+	<p id="p-after-grid" tabindex="0">Tab-focusable paragraph below the grid</p>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_markup.html b/dojox/grid/tests/test_markup.html
new file mode 100644
index 0000000..a236cf1
--- /dev/null
+++ b/dojox/grid/tests/test_markup.html
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid with Dojo.Data via binding</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		
+		#grid, #grid2 {
+			width: 65em;
+			height: 25em;
+			padding: 1px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug: true, debugAtAllCosts: false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dojox.data.CsvStore");
+		dojo.require("dojo.parser");
+	</script>
+</head>
+<body class="tundra">
+	<h5>dojox.grid.Grid structure from markup</h5>
+	<span dojoType="dojox.data.CsvStore" 
+		jsId="csvStore" url="support/movies.csv">
+	</span>
+
+	<table dojoType="dojox.grid.DataGrid"
+		store="csvStore"
+		query="{ Title: '*' }"
+		clientSort="true"
+		style="width: 800px; height: 300px;">
+		<thead>
+			<tr>
+				<th width="300px" field="Title">Title of Movie</th>
+				<th width="5em">Year</th>
+			</tr>
+			<tr>
+				<th colspan="2">Producer</th>
+			</tr>
+		</thead>
+	</table>
+
+
+	<span dojoType="dojo.data.ItemFileReadStore" 
+		jsId="jsonStore" url="../../../dijit/tests/_data/countries.json">
+	</span>
+	<h5>Locked views specified with tables and colgroups</h5>
+
+	<table dojoType="dojox.grid.DataGrid"
+		store="jsonStore"
+		rowsPerPage="20"
+		query="{ name: '*' }"
+		style="width: 600px; height: 300px;"
+		rowSelector="20px">
+		<colgroup span="1" noscroll="true" width="300px"></colgroup>
+		<colgroup span="4"></colgroup>
+		<thead>
+			<tr>
+				<th field="name" width="auto">Country/Continent Name</th>
+				<th width="100px" field="population">Population</th>
+				<th width="100px" field="area">Land Mass</th>
+				<th width="100px" field="timezone">Time Zone</th>
+				<th width="5em" field="type">Type</th>
+			</tr>
+		</thead>
+	</table>
+
+	<h5>A "regular" Grid from markup (no table defintion)</h5>
+	<script type="text/javascript">
+		// helper functions and structure definitions for the old markup construction syntax
+		var layoutCountries = [
+			// view 1
+			{
+				cells: [ new dojox.grid.cells.RowIndex() ],
+				noscroll: true
+			},
+			// view 2
+			[
+				{ field: 'name', width: 'auto' },
+				{ field: 'type', width: 8 }
+			]
+		];
+	</script>
+	<div id="grid2" dojoType="dojox.grid.DataGrid" elasticView="2" query="{ name: '*' }"
+		rowsPerPage="20" store="jsonStore" structure="layoutCountries" rowSelector="20px">
+	</div>
+
+</body>
+</html>
diff --git a/dojox/grid/tests/test_mysql_edit.html b/dojox/grid/tests/test_mysql_edit.html
new file mode 100644
index 0000000..b5b02d5
--- /dev/null
+++ b/dojox/grid/tests/test_mysql_edit.html
@@ -0,0 +1,145 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html debug="true">
+<head>
+	<title>dojox.grid.Grid Test: Mysql Table Editing</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style>
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		.grid {
+			height: 30em;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojox.data.QueryReadStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript">
+		dojo.declare("DbStore", dojox.data.QueryReadStore, {
+			fetch: function(request){
+				request.serverQuery = {
+					database: this.database || '',
+					table: this.table || ''
+				}
+			}
+		});
+		var model = new dojox.grid._data.DbTable(null, null, 'support/data.php', "test", "testtbl");
+		// simple display of row info; based on model observing.
+		modelChange = function() {
+			dojo.byId('rowCount').innerHTML = model.count + ' row(s)';
+		}
+		model.observer(this);
+		
+		// yay, let's deal with MySql date types, at least a little bit...
+		// NOTE: supports only default date formatting YYYY-MM-DD HH:MM:SS or YY-MM-DD HH:MM:SS
+		mysqlDateToJsDate = function(inMysqlDateTime, inDateDelim, inTimeDelim) {
+			var dt = inMysqlDateTime.split(' '), d = dt[0], t = dt[1], r;
+			d = d&&d.split(inDateDelim||'-');
+			t = t&&t.split(inTimeDelim||':');
+			if (d && d.length == 3) {
+				r = new Date();
+				r.setYear(d[0]);
+				r.setMonth(parseInt(d[1])-1);
+				r.setDate(d[2]);
+			}
+			if (t && t.length == 3) {
+				r = r || new Date();
+				r.setHours(t[0]);
+				r.setMinutes(t[1]);
+				r.setSeconds(t[2]);
+			}
+			return r || new Date(inMysqlDateTime);
+		}
+		
+		jsDateToMySqlDate = function(inDate) {
+			var
+				d = new Date(inDate),
+				y = d.getFullYear(),
+				m = dojo.string.pad(d.getMonth() + 1),
+				dd = dojo.string.pad(d.getDate())
+			return dojo.string.substitute("${0}-${1}-${2}",[y, m, dd]);
+		};
+		
+		// custom simple MySql date formatter
+		formatMySqlDate = function(inDatum) {
+			return inDatum != dojox.grid.na ? dojo.date.locale.format(mysqlDateToJsDate(inDatum), this.constraint) : dojox.grid.na;
+		}
+		
+		// custom simple MySql date editor
+		dojo.declare("mySqlDateCell", dojox.grid.cells.DateTextBox, {
+			format: function(inDatum, inRowIndex){
+				inDatum = mysqlDateToJsDate(inDatum);
+				return this.inherited(arguments, [inDatum, inRowIndex]);
+			},
+			getValue: function(inRowIndex){
+				var v = this.editor.getValue(), fv = jsDateToMySqlDate(v);
+				return fv;
+			}
+		});
+		
+		var gridLayout = [ 
+			{ type: "dojox.grid._RowSelector", width: "20px" },
+			{
+			defaultCell: { width: 6, type: dojox.grid.cells._Widget, editable: true }, 
+			cells: [[
+				{ name: 'Id', styles: 'text-align: right;', widgetClass: dijit.form.NumberTextBox }, 
+				{ name: 'Name', width: 20},
+				{ name: 'Message', styles: 'text-align: right;'},
+				{ name: 'Date', 
+					type: mySqlDateEditor, 
+					formatter: formatMySqlDate, 
+					constraint: {selector: "date"}, 
+					width: 10, 
+					styles: 'text-align:right;'}
+			]]}
+		];
+
+		function waitMessage() {
+			alert('Edit in progress, please wait.');
+		}
+		
+		function getDefaultRow() {
+			return ['', '', '', jsDateToMySqlDate(new Date())];
+		}
+		function addRow() {
+			if(model.canModify()){
+				grid.addRow(getDefaultRow());
+			}else{
+				waitMessage();
+			}
+		}
+		
+		function removeSelected(){
+			if(model.canModify()){
+				grid.removeSelectedRows();
+			}else{
+				waitMessage();
+			}
+		}
+	</script>
+</head>
+<body class="tundra">
+	<h1>dojox.grid.Grid Test: Mysql Table Editing</h1>
+	<br>
+	<button onclick="addRow()">Add Row</button>  
+	<button onclick="removeSelected()">Remove Selected</button>  
+	<button onclick="grid.edit.apply()">Apply Edit</button>  
+	<button onclick="grid.edit.cancel()">Cancel Edit</button>  
+	<button onclick="grid.render()">Refresh</button>
+	<br><br>
+	<div jsId="grid" class="grid" structure="gridLayout" dojoType="dojox.grid.Grid" 
+		store="model" singleClickEdit="true" autoWidth="true"></div>
+	<div id="rowCount"></div>
+	<p>Note: This test requires MySql and PHP and works with the database table available in support/testtbl.sql.</p>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_selection.html b/dojox/grid/tests/test_selection.html
new file mode 100644
index 0000000..744c43f
--- /dev/null
+++ b/dojox/grid/tests/test_selection.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>Test dojox.grid.Grid Selection Models</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid1,#grid2,#grid3,#grid4 {
+			border: 1px solid #333;
+			width: 35em;
+			height: 30em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+
+		var layout = [[
+			new dojox.grid.cells.RowIndex({ width: 5 }),
+			{name: 'Column 1', field: 'col1'},
+			{name: 'Column 2', field: 'col2'},
+			{name: 'Column 3', field: 'col3'},
+			{name: 'Column 4', field: 'col4', width: "150px"},
+			{name: 'Column 5', field: 'col5'}
+		],[
+			{name: 'Column 6', field: 'col6', colSpan: 2},
+			{name: 'Column 7', field: 'col7'},
+			{name: 'Column 8'},
+			{name: 'Column 9', field: 'col3', colSpan: 2}
+		]];
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+</head>
+<body class="tundra">
+	<h2>dojox.grid.Grid Selection Models Test</h2>
+	<h3>none</h3>
+	<div jsid="grid1" id="grid1" dojoType="dojox.grid.DataGrid" selectionMode="none"
+		store="test_store" query="{ id: '*' }" structure="layout">
+	</div>
+	<h3>Single</h3>
+	<div jsid="grid2" id="grid2" dojoType="dojox.grid.DataGrid" selectionMode="single"
+		store="test_store" query="{ id: '*' }" structure="layout">
+	</div>
+	<h3>Multiple</h3>
+	<div jsid="grid3" id="grid3" dojoType="dojox.grid.DataGrid" selectionMode="multiple"
+		store="test_store" query="{ id: '*' }" structure="layout">
+	</div>
+	<h3>Extended</h3>
+	<div jsid="grid4" id="grid4" dojoType="dojox.grid.DataGrid" selectionMode="extended"
+		store="test_store" query="{ id: '*' }" structure="layout">
+	</div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_sizing.html b/dojox/grid/tests/test_sizing.html
new file mode 100644
index 0000000..930fc57
--- /dev/null
+++ b/dojox/grid/tests/test_sizing.html
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid Sizing Example</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		
+		#container {
+			width: 400px;
+			height: 200px;
+			border: 4px double #333; 
+		}
+				
+		#grid { 
+			border: 1px solid #333;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var structure = [
+			{
+				noscroll: false,
+				cells: [
+					{name: 'Column 1', field: 'col1'},
+					{name: 'Column 2', field: 'col2'}
+				]
+			},
+			[
+				{name: 'Column 3', field: 'col3'},
+				{name: 'Column 4', field: 'col4'},
+				{name: 'Column 5', field: 'col5'},
+				{name: 'Column 6', field: 'col6'},
+				{name: 'Column 7', field: 'col7'}
+			]
+		];
+		
+		// get can return data for each cell of the grid
+		function get(inRowIndex) {
+			return [this.index, inRowIndex].join(', ');
+		}
+		
+		function resizeInfo() {
+			setTimeout(function() {
+				dojo.byId('gridWidth').value = grid.domNode.clientWidth;
+				dojo.byId('gridHeight').value = grid.domNode.clientHeight;
+			}, 1);
+		}
+		
+		function resizeGrid() {
+			grid.attr('autoHeight', false);
+			grid.attr('autoWidth', false);
+			var
+				w = Number(dojo.byId('gridWidth').value),
+				h = Number(dojo.byId('gridHeight').value);
+			
+			dojo.contentBox(grid.domNode, {w: w, h: h});
+			grid.update();
+		}
+		
+		function fitWidth() {
+			grid.attr('autoHeight', false);
+			grid.attr('autoWidth', true);
+			grid.update();
+		}
+		
+		function fitHeight() {
+			grid.attr('autoHeight', true);
+			grid.attr('autoWidth', false);
+			grid.update();
+		}
+		
+		function fitBoth() {
+			grid.attr('autoHeight', true);
+			grid.attr('autoWidth', true);
+			grid.update();
+		}
+		
+		function sizeDefault() {
+			grid.attr('autoHeight', false);
+			grid.attr('autoWidth', false);
+			grid.domNode.style.width = '';
+			grid.domNode.style.height = 0;
+			grid.update();
+		}
+		
+		dojo.addOnLoad(function() {
+			dojo.byId('gridWidth').value = 500;
+			dojo.byId('gridHeight').value = 200;
+			dojo.connect(grid, 'update', resizeInfo);
+			resizeGrid();
+		});
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.Grid Sizing Test</div>
+	Grid width: <input id="gridWidth" type="text">  
+	and height: <input id="gridHeight" type="text"> 
+	<button onclick="resizeGrid()">Resize Grid</button><br><br>
+	<button onclick="fitWidth()">Fit Data Width</button> 
+	<button onclick="fitHeight()">Fit Data Height</button> 
+	<button onclick="fitBoth()">Fit Data Width & Height</button>
+	<button onclick="sizeDefault()">DefaultSize</button><br><br>
+	<div id="grid" jsid="grid" dojoType="dojox.grid.DataGrid" 
+		autoWidth="true" autoHeight="true" store="test_store" 
+		structure="structure" elasticView="2"></div>
+	
+	<p>Grid fits to a sized container by default:</p>
+	<div id="container">
+		<div id="grid1" jsid="grid1" dojoType="dojox.grid._Grid" 
+			get="get" structure="structure" rowCount="10" elasticView="2"></div>
+	</div>
+
+	<p> Grid is essentially hidden (height of zero) when parent container is unsized 
+		(nothing, including the header, should be displayed):</p>
+	<div id="unsizedContainer">
+		<div id="grid2" dojoType="dojox.grid._Grid" 
+			get="get" structure="structure" rowCount="10" elasticView="2"></div>
+	</div>
+
+	<p> Grid is autoHeight and autoWidth via markup</p>
+	<div id="grid3" dojoType="dojox.grid._Grid" 
+		autoWidth="true" autoHeight="true" get="get" 
+		structure="structure" rowCount="10" elasticView="2"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_sizing_100rows.html b/dojox/grid/tests/test_sizing_100rows.html
new file mode 100644
index 0000000..641ac5c
--- /dev/null
+++ b/dojox/grid/tests/test_sizing_100rows.html
@@ -0,0 +1,148 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid Sizing Example</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		
+		#container {
+			width: 400px;
+			height: 200px;
+			border: 4px double #333; 
+		}
+				
+		#grid { 
+			border: 1px solid #333;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var structure = [
+			{
+				noscroll: true,
+				cells: [
+					{name: 'Column 1', field: 'col1'},
+					{name: 'Column 2', field: 'col2'}
+				]
+			},
+			[
+				{name: 'Column 3', field: 'col3'},
+				{name: 'Column 4', field: 'col4'},
+				{name: 'Column 5', field: 'col5'},
+				{name: 'Column 6', field: 'col6'},
+				{name: 'Column 7', field: 'col7'}
+			]
+		];
+
+		// get can return data for each cell of the grid
+		function get(inRowIndex) {
+			return [this.index, inRowIndex].join(', ');
+		}
+		
+		function resizeInfo() {
+			setTimeout(function() {
+				dojo.byId('gridWidth').value = grid.domNode.clientWidth;
+				dojo.byId('gridHeight').value = grid.domNode.clientHeight;
+			}, 1);
+		}
+		
+		function resizeGrid() {
+			dojo.attr('autoHeight', false);
+			dojo.attr('autoWidth', false);
+			var
+				w = Number(dojo.byId('gridWidth').value),
+				h = Number(dojo.byId('gridHeight').value);
+			
+			dojo.contentBox(grid.domNode, {w: w, h: h});
+			grid.update();
+		}
+		
+		function fitWidth() {
+			dojo.attr('autoWidth', true);
+			dojo.attr('autoHeight', false);
+			grid.update();
+		}
+		
+		function fitHeight() {
+			dojo.attr('autoWidth', false);
+			dojo.attr('autoHeight', true);
+			grid.update();
+		}
+		
+		function fitBoth() {
+			dojo.attr('autoWidth', true);
+			dojo.attr('autoHeight', true);
+			grid.update();
+		}
+		
+		function sizeDefault() {
+			dojo.attr('autoWidth', false);
+			dojo.attr('autoHeight', false);
+			grid.domNode.style.width = '';
+			grid.domNode.style.height = 0;
+			grid.update();
+		}
+		
+		dojo.addOnLoad(function() {
+			dojo.byId('gridWidth').value = 500;
+			dojo.byId('gridHeight').value = 200;
+			dojo.connect(grid, 'update', resizeInfo);
+			resizeGrid();
+		});
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">dojox.grid.Grid Sizing Test</div>
+	Grid width: <input id="gridWidth" type="text">  
+	and height: <input id="gridHeight" type="text"> 
+	<button onclick="resizeGrid()">Resize Grid</button><br><br>
+	<button onclick="fitWidth()">Fit Data Width</button> 
+	<button onclick="fitHeight()">Fit Data Height</button> 
+	<button onclick="fitBoth()">Fit Data Width & Height</button>
+	<button onclick="sizeDefault()">DefaultSize</button><br><br>
+	<div id="grid" jsid="grid" dojoType="dojox.grid.DataGrid" 
+		autoWidth="true" autoHeight="true" store="test_store" 
+		structure="structure" rowSelector="20px" elasticView="2"></div>
+	
+	<p>Grid fits to a sized container by default:</p>
+	<div id="container">
+		<div id="grid1" jsid="grid1" dojoType="dojox.grid._Grid" 
+			get="get" structure="structure" rowCount="10" 
+			rowSelector="20px" elasticView="2"></div>
+	</div>
+
+	<p> Grid is essentially hidden (height of zero) when parent container is unsized 
+		(nothing, including the header, should be displayed):</p>
+	<div id="unsizedContainer">
+		<div id="grid2" dojoType="dojox.grid._Grid" 
+			get="get" structure="structure" rowCount="10" 
+			rowSelector="20px" elasticView="2"></div>
+	</div>
+
+	<p> Grid is autoHeight and autoWidth via markup</p>
+	<div id="grid3" dojoType="dojox.grid._Grid" 
+		autoWidth="true" autoHeight="true" get="get" 
+		structure="structure" rowCount="100" rowSelector="20px" elasticView="2"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_sizing_ResizeHandle.html b/dojox/grid/tests/test_sizing_ResizeHandle.html
new file mode 100644
index 0000000..74052c4
--- /dev/null
+++ b/dojox/grid/tests/test_sizing_ResizeHandle.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.DataGrid Sizing Example</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		@import "../../layout/resources/ResizeHandle.css";
+
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+		
+		#bar, #container {
+			width: 400px;
+			height: 200px;
+			border: 4px double #333; 
+		}
+				
+		#grid { 
+			border: 1px solid #333;
+		}
+		#grid .dojoxGridScrollbox,
+		#grid1 .dojoxGridScrollbox {
+			overflow: scroll;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.layout.ResizeHandle");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var structure = [
+			{
+				noscroll: false,
+				cells: [
+					{name: 'Column 1', field: 'col1'},
+					{name: 'Column 2', field: 'col2'}
+				]
+			},
+			[
+				{name: 'Column 3', field: 'col3'},
+				{name: 'Column 4', field: 'col4'},
+				{name: 'Column 5', field: 'col5'},
+				{name: 'Column 6', field: 'col6'},
+				{name: 'Column 7', field: 'col7'}
+			]
+		];
+		
+		// get can return data for each cell of the grid
+		function get(inRowIndex) {
+			return [this.index, inRowIndex].join(', ');
+		}
+
+		dojo.addOnLoad(function(){
+			var hand = new dojox.layout.ResizeHandle({
+				targetContainer: dojo.byId("bar"),
+				animateSizing: false,
+				onResize: function(e){
+					setTimeout(dojo.hitch(aGrid,"update",e),25);
+				}
+			},"hand0");
+		});
+	</script>
+</head>
+<body class="tundra">
+	<div class="heading">
+		dojox.grid.DataGrid Sizing Test w/ the experimental dojox.layout.ResizeHandle
+	</div>
+	<p>While this test should work, dojox.layout.ResizeHandle is experimental.</p>
+	
+	<div id="bar" style="position:relative">
+		<div jsId="aGrid" id="grid" dojoType="dojox.grid.DataGrid" 
+			store="test_store" rowSelector="20px" 
+			structure="structure" elasticView="2"></div>
+		<div id="hand0"></div>
+	</div>
+	
+	<p>Grid fits to a sized container by default:</p>
+	<div id="container" style="position:relative">
+		<div jsId="theGrid" id="grid1" dojoType="dojox.grid._Grid" 
+			get="get" rowSelector="20px" structure="structure" 
+			rowCount="75" elasticView="2"></div>
+		<div id="hand1" dojoType="dojox.layout.ResizeHandle" 
+			targetId="container" onResize="setTimeout(dojo.hitch(theGrid,'update'),50)" 
+			animateSizing="false"></div>
+	</div>
+	
+	<p>I am here to take up</p>
+
+	<p>space</p>
+
+	<p>as much as needed.</p>
+		
+</body>
+</html>
diff --git a/dojox/grid/tests/test_styling.html b/dojox/grid/tests/test_styling.html
new file mode 100644
index 0000000..c819a93
--- /dev/null
+++ b/dojox/grid/tests/test_styling.html
@@ -0,0 +1,127 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid Styling Test</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../resources/Grid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.heading {
+			font-weight: bold;
+			padding-bottom: 0.25em;
+		}
+				
+		#grid { 
+			border: 1px solid #333;
+			width: 45em;
+			height: 30em;
+		}
+		
+		#grid .dojoxGridRow {
+			border: none;
+		}
+		
+		#grid .dojoxGridRowTable {
+			border-collapse: collapse;
+		}
+		
+		#grid .dojoxGridCell {
+			border: none;
+			padding: 10px;
+		}
+		
+		.selectedRow .dojoxGridCell {
+			background-color: #003366;
+			color: white;
+		}
+		
+		.specialRow .dojoxGridCell {
+			background-color: dimgray;
+		}
+		
+		.selectedRow.specialRow .dojoxGridCell {
+			text-decoration: line-through;
+			/* duplicate selection background-color so has precendence over specialRow background-color */
+			background-color: #003366;
+		}
+		
+		/* in the yellow column, assign specific decoration for special rows that are selected */
+		.selectedRow.specialRow .yellowColumnData {
+			text-decoration: line-through underline;
+		}
+		
+		.yellowColumn {
+			color: #006666;
+		}
+			
+		.overRow .dojoxGridCell {
+			text-decoration: underline;
+		}
+		
+		.greenColumn {
+			color: yellow;
+			background-color: #006666;
+			font-style: italic;
+		}	
+		.yellowColumnData {
+			background-color: yellow;
+			text-decoration: underline;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="support/test_data.js"></script>
+	<script type="text/javascript">
+		var structure = [
+			{
+				// a view without scrollbars
+				noscroll: true,
+				cells: [
+					{name: 'Column 1', field: 'col1', width: 5, headerStyles: 'padding-bottom: 2px;', styles: 'border-bottom: 1px dashed #333; border-right: 1px dashed #333; padding: 6px;'},
+					{name: 'Column 2', field: 'col2', width: 5, headerStyles: 'padding-bottom: 2px;', styles: 'text-align: right; border-bottom: 1px dashed #333; border-right: 1px dashed #333; padding: 6px;'}
+				]
+			},
+			[
+				{name: 'Column 3', field: 'col3'},
+				{name: 'Column 4', field: 'col4', headerStyles: 'background-image: none; background-color: #003333;', classes: 'greenColumn'},
+				{name: 'Column 5', field: 'col5', cellClasses: 'yellowColumnData', classes: 'yellowColumn', styles: 'text-align: center;' },
+				{name: 'Column 6', field: 'col6', headerStyles: 'background-image: none; background-color: #003333;', classes: 'greenColumn'},
+				{name: 'Column 7', field: 'col7'},
+				{name: 'Column 8', field: 'col8'}
+			]
+		];
+		
+		function onStyleRow(inRow) {
+			with (inRow) {
+				var i = index % 10;
+				var special = (i > 2 && i < 6);
+				if (odd)
+					customStyles += ' color: orange;';
+				if (selected)	
+					customClasses += ' selectedRow';
+				if (special)	
+					customClasses += ' specialRow';
+				if (over)	
+					customClasses += ' overRow';
+				if (!over && !selected)
+					dojox.grid.DataGrid.prototype.onStyleRow.apply(this, arguments);
+			}	
+		}
+</script>
+</head>
+<body>
+	<div class="heading">dojox.grid.Grid Styling Example</div>
+	<div id="grid" jsid="grid" dojoType="dojox.grid.DataGrid" 
+		onStyleRow="onStyleRow" store="test_store" structure="structure"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_subgrid.html b/dojox/grid/tests/test_subgrid.html
new file mode 100644
index 0000000..08ac3d3
--- /dev/null
+++ b/dojox/grid/tests/test_subgrid.html
@@ -0,0 +1,195 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid Subgrid Test</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	</meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		
+		body { font-size: 1.0em; }
+		#grid {
+			height: 400px;
+			border: 1px solid silver;
+		}
+		.text-oneline {
+			white-space: nowrap;
+			overflow: hidden;
+			text-overflow: ellipsis;
+		}
+		.textScrolling {
+			height: 4em;
+			overflow: auto;
+		}
+		.textScrolling {
+			width: 21.5em;
+		}
+	</style>
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:true, debugAtAllCosts: false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript">
+		data = [ 
+			[ '3 stars', 'Averagia', 'Averagia', 8.99, 'An authentic experience defined by the intense layer of frothy, real facts. This combination package includes special T DISCS that work with your system to produce a perfectly serene experience. $8.99 per package. Please choose Regular (#NS1) or Decaffeinated (#NS4).' ],
+		 	[ '2 stars', 'Cheapy', 'Cheapy', 6.29, 'Power and subtlety intersect for an experience with real character. Imported from Europe just for you. 16 T DISCS per package. $6.29 per package. #NJ4.' ],
+		 	[ '4 stars', 'Luxuria', 'Luxuria', 6.49, 'A bold statement from the respected European brand Luxuria, topped with delicate zanthum. Imported exclusively for you. 18 T DISCS per package. $6.49 per package. #N42.</div>' ],
+		 	[ '5 stars', 'Ultimo', 'Ultimo', 4.59, "A rich sensation of delicious experience, brought to you by one of Europe's oldest brands. A pure indulgence. 8 T DISCS per package. $4.59 per package. #NJ0." ]
+		];		 
+
+		getDetailData = function(inRowIndex) {
+			var row = data[this.grid.dataRow % data.length];
+			switch (this.index) {
+				case 0:
+					return row[0]; //'<img src="images/sample/' + row[0] + '" width="109" height="75">';
+				case 1:
+					return (100000000 + this.grid.dataRow).toString().slice(1);
+				case 2:
+					return row[3];
+				case 3:
+					return row[1];
+				case 4:
+					return row[2];
+				case 5:
+					return row[4];
+				default: 
+					return row[this.index];
+			}
+		}		 
+		
+		getName = function(inRowIndex) {
+			var row = data[inRowIndex % data.length];
+			return row[2];
+		}		 
+		
+		// Main grid structure 
+		var gridCells = [
+			{ type: 'dojox.grid._RowSelector', width: '20px' }, 
+			{ 
+				onBeforeRow: function(inDataIndex, inSubRows) {
+					inSubRows[1].hidden = !detailRows[inDataIndex];
+				},
+				onAfterRow: function(rowIndex, subRows, rowNode) {
+					if(detailRows[rowIndex]){
+						buildSubgrid(rowIndex, subRows[1][0]);
+					}
+				},
+				cells: [[
+					{ name: '', width: 3, get: getBlank, formatter: fmtCheck, styles: 'text-align: center;' }, { name: 'Name', get: getName, width: 40 }
+				], [
+					{ name: '', get: getBlank, formatter: fmtDetail, colSpan: 2, styles: 'padding: 0; margin: 0;'}
+				]]
+			}
+		];
+		
+		function getBlank(inRowIndex){ return ""; }
+		
+		// html for the +/- cell
+		function fmtCheck(data, inRowIndex) { 
+			var image = (detailRows[inRowIndex] ? 'open.gif' : 'closed.gif');
+			var show = (detailRows[inRowIndex] ? 'false' : 'true')
+			return '<img height="11" width="11" src="images/' + image + '" onclick="toggleDetail(' + inRowIndex + ', ' + show + ')">';
+		}
+		
+		// provide html for the Detail cell in the master grid		
+		function fmtDetail(data, inRowIndex) {
+			var cell = this;
+			// look for a subgrid
+			var subGrid = dijit.byId(makeSubgridId(inRowIndex));
+			var h = (subGrid ? subGrid.cacheHeight : "120") + "px";
+			// insert a placeholder
+			return '<div style="height: ' + h + '; background-color: white;"></div>';
+		}
+		
+		// the Detail cell contains a subgrid which we set up below
+			var subGridCells = [{
+				noscroll: true,
+				cells: [
+					[{ name: "Rating", rowSpan: 2, width: 10, noresize: true, styles: 'text-align:center;' }, 
+							{ name: "Sku" }, 
+							{ name: "Price" }, 
+							{ name: "Vendor" }, 
+							{ name: "Name", width: "auto" }], 
+					[{ name: "Description", colSpan: 4 }]
+				]}];
+
+			var subGridProps = {
+				structure: subGridCells, 
+				rowCount: 1, 
+				autoHeight: true, 
+				autoRender: false,
+				"get": getDetailData
+			};
+	
+			// identify subgrids by their row indices
+			function makeSubgridId(inRowIndex) {
+				return grid.id + "_subGrid_" + inRowIndex;
+			}
+	
+			// if a subgrid exists at inRowIndex, detach it from the DOM
+			function detachSubgrid(inRowIndex) {
+				var subGrid = dijit.byId(makeSubgridId(inRowIndex));
+				if(subGrid){
+					dojox.grid.util.removeNode(subGrid.domNode);
+				}
+			}
+			
+			// render a subgrid into inCell at inRowIndex
+			function buildSubgrid(inRowIndex, inCell) {
+				var n = inCell.getNode(inRowIndex).firstChild;
+				var id = makeSubgridId(inRowIndex);
+				var subGrid = dijit.byId(id);
+				if (subGrid) {
+					n.appendChild(subGrid.domNode);
+				} else {
+					subGridProps.dataRow = inRowIndex;
+					subGridProps.id = id;
+					subGrid = new dojox.grid._Grid(subGridProps, n);
+					subGrid.startup();
+				}
+				subGrid.render();
+				if(subGrid){
+					subGrid.cacheHeight = subGrid.domNode.offsetHeight;
+					inCell.grid.rowHeightChanged(inRowIndex);
+				}	
+			}
+					
+			// destroy subgrid at inRowIndex
+			function destroySubgrid(inRowIndex) {
+				var subGrid = dijit.byId(makeSubgridId(inRowIndex));
+				if(subGrid){
+					subGrid.destroy();
+				}
+			}
+		
+		// when user clicks the +/-
+		detailRows = [];
+		function toggleDetail(inIndex, inShow) {
+			if(!inShow){
+				detachSubgrid(inIndex);
+			}
+			detailRows[inIndex] = inShow;
+			grid.updateRow(inIndex);
+		}
+		
+		dojo.addOnLoad(function() {
+			window["grid"] = dijit.byId("grid");
+			dojo.connect(grid, 'rowRemoved', destroySubgrid);
+		});
+	</script>
+</head>
+<body class="tundra">
+	<h3>dojox.grid.Grid showing sub-grid.</h3>
+	<div id="grid" dojoType="dojox.grid._Grid" 
+		structure="gridCells" 
+		rowCount="100000" 
+		autoWidth="true"></div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_treegrid.html b/dojox/grid/tests/test_treegrid.html
new file mode 100644
index 0000000..b037772
--- /dev/null
+++ b/dojox/grid/tests/test_treegrid.html
@@ -0,0 +1,250 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.TreeGrid Tests</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		.grid {
+			width: 70em;
+			height: 15em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.TreeGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+		
+		function formatTime(value, rowIdx){
+			var hrs = Math.floor(value / 60) + "";
+			var mins = (value % 60) + "";
+			while (hrs.length < 2){
+				hrs = "0" + hrs;
+			}
+			while (mins.length < 2){
+				mins = "0" + mins;
+			}
+			return hrs + ":" + mins;
+		}
+		
+		function summaryFormatter(value, rowIdx, cell, sing, plur){
+			var str;
+			if(rowIdx >= 0){
+				return value;
+			}
+			if(rowIdx == -1){
+				str = "Total (${numItems} ${displayName}):";
+			}else{
+				str = "${numItems} ${displayName}";
+			}
+			return dojo.string.substitute(str, {numItems: value, 
+						displayName: (value == 1) ? sing : plur});			
+		}
+		function quarterSummary(value, rowIdx){
+			return summaryFormatter(value, rowIdx, this, "Quarter", "Quarters");
+		}
+		function gameSummary(value, rowIdx){
+			return summaryFormatter(value, rowIdx, this, "Game", "Games");
+		}
+		function seasonSummary(value, rowIdx){
+			return summaryFormatter(value, rowIdx, this, "Season", "Seasons");
+		}
+		dojo.addOnLoad(function(){
+			var g = new dojox.grid.TreeGrid({
+				structure: [ 
+					{ cells: [
+						[ 
+							{ field: "label", name: "Game" }, 
+							{ field: "qtrs", 
+								children: [
+									{ field: "label", name: "Quarter", width: "12em", formatter: quarterSummary }, 
+									{ field: "pts", name: "Points" }, 
+									{ field: "reb", name: "Rebounds" }, 
+									{ field: "ast", name: "Assists" }, 
+									{ field: "tp", name: "Time Played" } 
+								], 
+								itemAggregates: [ "numQtrs", "totPts", "totReb", "totAst", "totTP" ], 
+								aggregate: "sum"
+							}
+						]] 
+					}					
+				],
+				store: jsonStore,
+				query: {id: "3"},
+				queryOptions: {deep: true},
+				rowSelector: true
+			}, dojo.byId("progGrid"));
+			dojo.addClass(g.domNode, "grid");
+			g.startup();
+			dojo.connect(window, "onresize", grid4, "resize");
+		});
+
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">Test: dojox.tests.grid.TreeGrid</h1>
+	<span dojoType="dojo.data.ItemFileWriteStore" 
+		jsId="jsonStore" url="support/gamedata.json">
+	</span>
+
+	<h4 class="testSubtitle">dojox.grid.TreeGrid 1-Level</h4>
+	<table dojoType="dojox.grid.TreeGrid" class="grid"
+		store="jsonStore" query="{ id: '4' }" queryOptions="{deep: true}" rowsPerPage="20" rowSelector="true">
+		<thead>
+			<tr>
+				<th field="label">Quarter</th>
+				<th field="pts">Points</th>
+				<th field="reb">Rebounds</th>
+				<th field="ast">Assists</th>
+				<th field="tp" formatter="formatTime">Time Played</th>
+			</tr>
+		</thead>
+	</table>
+
+	<h4 class="testSubtitle">dojox.grid.TreeGrid 2-Level (draggable columns)</h4>
+	<table dojoType="dojox.grid.TreeGrid" class="grid" columnReordering="true"
+		store="jsonStore" query="{ id: '3' }" queryOptions="{deep: true}" rowsPerPage="20" rowSelector="true">
+		<thead>
+			<tr>
+				<th field="label">Game</th>
+				<th field="qtrs" aggregate="sum" itemAggregates="numQtrs,totPts,totReb,totAst,totTP">
+					<table>
+						<thead>
+							<tr>
+								<th field="label" width="12em" formatter="quarterSummary">Quarter</th>
+								<th field="pts">Points</th>
+								<th field="reb">Rebounds</th>
+								<th field="ast">Assists</th>
+								<th field="tp" formatter="formatTime">Time Played</th>
+							</tr>
+						</thead>
+					</table>
+				</th>
+			</tr>
+		</thead>
+	</table>
+	
+	<h4 class="testSubtitle">dojox.grid.TreeGrid 2-Level (programmatic)</h4>
+	<div id="progGrid"></div>
+
+	<h4 class="testSubtitle">dojox.grid.TreeGrid 3-Level (initially closed, using relWidths)</h4>
+	<table dojoType="dojox.grid.TreeGrid" class="grid" defaultOpen="false"
+		store="jsonStore" query="{ id: '2' }" queryOptions="{deep: true}" rowsPerPage="20" rowSelector="true">
+		<thead>
+			<tr>
+				<th field="label" relWidth="2">Season</th>
+				<th field="games" aggregate="sum" itemAggregates="numGames">
+					<table>
+						<thead>
+							<tr>
+								<th field="label" formatter="gameSummary" relWidth="2">Game</th>
+								<th field="qtrs" aggregate="sum" itemAggregates="numQtrs,totPts,totReb,totAst,totTP">
+									<table>
+										<thead>
+											<tr>
+												<th field="label" formatter="quarterSummary" relWidth="2">Quarter</th>
+												<th field="pts" relWidth="1">Points</th>
+												<th field="reb" relWidth="1">Rebounds</th>
+												<th field="ast" relWidth="1">Assists</th>
+												<th field="tp" relWidth="1" formatter="formatTime">Time Played</th>
+											</tr>
+										</thead>
+									</table>
+								</th>
+							</tr>
+						</thead>
+					</table>
+				</th>
+			</tr>
+		</thead>
+	</table>
+
+	<h4 class="testSubtitle">dojox.grid.TreeGrid 4-Level - calculated totals, autoHeight and autoWidth</h4>
+	<table dojoType="dojox.grid.TreeGrid" class="grid" autoWidth="true" autoHeight="true"
+		store="jsonStore" query="{ id: '1' }" rowsPerPage="20" rowSelector="true">
+		<thead>
+			<tr>
+				<th field="label">Player</th>
+				<th field="seasns" aggregate="sum">
+					<table>
+						<thead>
+							<tr>
+								<th field="label" width="10em" formatter="seasonSummary">Season</th>
+								<th field="games" aggregate="sum">
+									<table>
+										<thead>
+											<tr>
+												<th field="label" width="10em" formatter="gameSummary">Game</th>
+												<th field="qtrs" aggregate="sum">
+													<table>
+														<thead>
+															<tr>
+																<th field="label" width="10em" formatter="quarterSummary">Quarter</th>
+																<th field="pts">Points</th>
+																<th field="reb">Rebounds</th>
+																<th field="ast">Assists</th>
+																<th field="tp" formatter="formatTime">Time Played</th>
+															</tr>
+														</thead>
+													</table>
+												</th>
+											</tr>
+										</thead>
+									</table>
+								</th>
+							</tr>
+						</thead>
+					</table>
+				</th>
+			</tr>
+		</thead>
+	</table>
+
+	<h4 class="testSubtitle">dojox.grid.TreeGrid Large 4-Level - calculated totals and openAtLevels</h4>
+	<table dojoType="dojox.grid.TreeGrid" class="grid" style="height: 45em;width: 100%;"
+		store="jsonStore" rowsPerPage="20" jsId="grid4" rowSelector="true" openAtLevels="false,true,3">
+		<thead>
+			<tr>
+				<th field="label" relWidth="2">Player</th>
+				<th field="seasns" aggregate="sum">
+					<table>
+						<thead>
+							<tr>
+								<th field="label" relWidth="2" formatter="seasonSummary">Season</th>
+								<th field="games" aggregate="sum">
+									<table>
+										<thead>
+											<tr>
+												<th field="label" relWidth="2" formatter="gameSummary">Game</th>
+												<th field="qtrs" aggregate="sum">
+													<table>
+														<thead>
+															<tr>
+																<th field="label" relWidth="2" formatter="quarterSummary">Quarter</th>
+																<th field="pts" relWidth="1">Points</th>
+																<th field="reb" relWidth="1">Rebounds</th>
+																<th field="ast" relWidth="1">Assists</th>
+																<th field="tp" relWidth="1" formatter="formatTime">Time Played</th>
+															</tr>
+														</thead>
+													</table>
+												</th>
+											</tr>
+										</thead>
+									</table>
+								</th>
+							</tr>
+						</thead>
+					</table>
+				</th>
+			</tr>
+		</thead>
+	</table>
+	Text After
+</body>
+</html>
+
diff --git a/dojox/grid/tests/test_treegrid_loading.html b/dojox/grid/tests/test_treegrid_loading.html
new file mode 100644
index 0000000..8339124
--- /dev/null
+++ b/dojox/grid/tests/test_treegrid_loading.html
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.TreeGrid Tests</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		.grid {
+			width: 70em;
+			height: 15em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: false"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.TreeGrid");
+		dojo.require("dojox.data.JsonRestStore");
+		dojo.require("dojo.parser");
+		
+		var data_part = {};
+		var data_full = {};
+		store = null;
+
+		var dataService = function(query, opts){
+			var d = new dojo.Deferred();
+			if(typeof query != "object"){
+				setTimeout(function(){
+					d.callback(data_full[query]);
+				}, 5000);
+				return d;
+			}else{
+				var data = [];
+				for(var i in data_part){
+					data.push(data_part[i]);
+				}
+				d.callback(data);
+				return d;
+			}
+		}
+		dataService.servicePath = "/";
+
+		dojo.addOnLoad(function(){
+			dojox.rpc._sync = false;
+			dojo.xhrGet({
+				url: "support/gamedata.json",
+				handleAs: "json",
+				sync: true
+			}).addCallback(function(res){
+				var p2 = res.items[1];
+				p2.seasns.push({
+					games: [],
+					id: 60,
+					label: "Season 3",
+					numGames: 0,
+					numQtrs: 0,
+					totAst: 0,
+					totPts: 0,
+					totReb: 0,
+					totTP: 0
+				});
+				for(var i = 0, l = p2.seasns.length; i<l; i++){
+					var item = p2.seasns[i];
+					data_full[item.id] = dojo.mixin({}, item);
+					delete item['games'];
+					item['$ref'] = item.id;
+					data_part[item.id] = dojo.mixin({}, item);
+				}
+			});
+			store = new dojox.data.JsonRestStore({
+				service: dataService,
+				cacheByDefault: true
+			});
+			dojo.parser.parse();
+			dojo.connect(window, "onresize", grid, "resize");
+		});
+
+		function formatTime(value, rowIdx){
+			var hrs = Math.floor(value / 60) + "";
+			var mins = (value % 60) + "";
+			while (hrs.length < 2){
+				hrs = "0" + hrs;
+			}
+			while (mins.length < 2){
+				mins = "0" + mins;
+			}
+			return hrs + ":" + mins;
+		}
+		
+		function summaryFormatter(value, rowIdx, cell, sing, plur){
+			var str;
+			if(rowIdx >= 0){
+				return value;
+			}
+			if(rowIdx == -1){
+				str = "Total (${numItems} ${displayName}):";
+			}else{
+				str = "${numItems} ${displayName}";
+			}
+			return dojo.string.substitute(str, {numItems: value, 
+						displayName: (value == 1) ? sing : plur});			
+		}
+		function quarterSummary(value, rowIdx){
+			return summaryFormatter(value, rowIdx, this, "Quarter", "Quarters");
+		}
+		function gameSummary(value, rowIdx){
+			return summaryFormatter(value, rowIdx, this, "Game", "Games");
+		}
+		function seasonSummary(value, rowIdx){
+			return summaryFormatter(value, rowIdx, this, "Season", "Seasons");
+		}
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">Test: dojox.tests.grid.TreeGrid</h1>
+	<h4 class="testSubtitle">dojox.grid.TreeGrid Large 4-Level - calculated totals and openAtLevels</h4>
+	<table dojoType="dojox.grid.TreeGrid" class="grid" style="height: 45em;width: 100%;"
+		store="store" rowsPerPage="20" jsId="grid" rowSelector="true" openAtLevels="false,true,3">
+			<thead>
+				<tr>
+					<th field="label" relWidth="2" formatter="seasonSummary">Players</th>
+					<th field="games" itemAggregates="numGames">
+						<table>
+							<thead>
+								<tr>
+									<th field="label" relWidth="2" formatter="gameSummary">Game</th>
+									<th field="qtrs" itemAggregates="numQtrs,totPts,totReb,totAst,totTP">
+										<table>
+											<thead>
+												<tr>
+													<th field="label" relWidth="2" formatter="quarterSummary">Quarter</th>
+													<th field="pts" relWidth="1">Points</th>
+													<th field="reb" relWidth="1">Rebounds</th>
+													<th field="ast" relWidth="1">Assists</th>
+													<th field="tp" relWidth="1" formatter="formatTime">Time Played</th>
+												</tr>
+											</thead>
+										</table>
+									</th>
+								</tr>
+							</thead>
+						</table>
+					</th>
+				</tr>
+			</thead>
+	</table>
+	Text After
+</body>
+</html>
+
diff --git a/dojox/grid/tests/test_treegrid_model.html b/dojox/grid/tests/test_treegrid_model.html
new file mode 100644
index 0000000..6777229
--- /dev/null
+++ b/dojox/grid/tests/test_treegrid_model.html
@@ -0,0 +1,207 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+    <head>
+        <title>dojox.grid.TreeGrid Model-based test</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+        <style type="text/css">
+            @import "../../../dojo/resources/dojo.css";
+            @import "../../../dijit/themes/tundra/tundra.css";
+            @import "../../../dojox/grid/resources/Grid.css";
+            @import "../../../dojox/grid/resources/tundraGrid.css";
+            .grid {
+                width: 70em;
+                height: 40em;
+            }
+        </style>
+        <script type="text/javascript" src="../../../dojo/dojo.js"  djConfig="isDebug:true, parseOnLoad: true"></script>
+        <script type="text/javascript">
+            dojo.require("dojox.grid.TreeGrid");
+            dojo.require("dijit.tree.ForestStoreModel");
+            dojo.require("dojo.data.ItemFileWriteStore");
+            dojo.require("dijit.form.Button");
+            dojo.require("dojo.parser");
+            var dataItems = {
+                identifier: 'id',
+                label: 'name',
+                items: [
+                    { id: 'AF', name:'Africa', type:'continent', population:'900 million', area: '30,221,532 sq km',
+                        timezone: '-1 UTC to +4 UTC',
+                        children:[{_reference:'EG'}, {_reference:'KE'}, {_reference:'SD'}] },
+                    { id: 'EG', name:'Egypt', type:'country' },
+                    { id: 'KE', name:'Kenya', type:'country',
+                        children:[{_reference:'Nairobi'}, {_reference:'Mombasa'}] },
+                    { id: 'Nairobi', name:'Nairobi', type:'city' },
+                    { id: 'Mombasa', name:'Mombasa', type:'city' },
+                    { id: 'SD', name:'Sudan', type:'country',
+                        children:{_reference:'Khartoum'} },
+                    { id: 'Khartoum', name:'Khartoum', type:'city' },
+                    { id: 'AS', name:'Asia', type:'continent',
+                        children:[{_reference:'CN'}, {_reference:'IN'}, {_reference:'RU'}, {_reference:'MN'}] },
+                    { id: 'CN', name:'China', type:'country' },
+                    { id: 'IN', name:'India', type:'country' },
+                    { id: 'RU', name:'Russia', type:'country' },
+                    { id: 'MN', name:'Mongolia', type:'country' },
+                    { id: 'OC', name:'Oceania', type:'continent', population:'21 million',
+                        children:{_reference:'AU'}},
+                    { id: 'AU', name:'Australia', type:'country', population:'21 million'},
+                    { id: 'EU', name:'Europe', type:'continent',
+                        children:[{_reference:'DE'}, {_reference:'FR'}, {_reference:'ES'}, {_reference:'IT'}] },
+                    { id: 'DE', name:'Germany', type:'country' },
+                    { id: 'FR', name:'France', type:'country' },
+                    { id: 'ES', name:'Spain', type:'country' },
+                    { id: 'IT', name:'Italy', type:'country' },
+                    { id: 'NA', name:'North America', type:'continent',
+                        children:[{_reference:'MX'}, {_reference:'CA'}, {_reference:'US'}] },
+                    { id: 'MX', name:'Mexico', type:'country',  population:'108 million', area:'1,972,550 sq km',
+                        children:[{_reference:'Mexico City'}, {_reference:'Guadalajara'}] },
+                    { id: 'Mexico City', name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
+                    { id: 'Guadalajara', name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' },
+                    { id: 'CA', name:'Canada', type:'country',  population:'33 million', area:'9,984,670 sq km',
+                        children:[{_reference:'Ottawa'}, {_reference:'Toronto'}] },
+                    { id: 'Ottawa', name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
+                    { id: 'Toronto', name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' },
+                    { id: 'US', name:'United States of America', type:'country' },
+                    { id: 'SA', name:'South America', type:'continent',
+                        children:[{_reference:'BR'}, {_reference:'AR'}] },
+                    { id: 'BR', name:'Brazil', type:'country', population:'186 million' },
+                    { id: 'AR', name:'Argentina', type:'country', population:'40 million' }
+                ]};
+			var dataItems2 = dojo.clone(dataItems);
+
+            function add_item(child, parentId){
+                if(child){
+                    jsonStore.fetchItemByIdentity({
+                        identity: parentId,
+                        onItem: function(item){
+                            if(item){
+                                continentModel.newItem(child, item);
+                            }
+                        }
+                    });
+                }
+            }
+
+			dojo.addOnLoad(function(){
+				var layout = [
+					{ name: "Name", field: "name", width: "auto" },
+					{ name: "Population", field: "population", width: "auto" },
+					{ name: "Timezone", field: "timezone", width: "auto" }
+				];
+				var jsonStore2 = new dojo.data.ItemFileWriteStore({ data: dataItems2 });
+				var treeModel2 = new dijit.tree.ForestStoreModel({
+					store: jsonStore2,
+					query: { type: 'continent' },
+					rootId: 'continentRoot',
+					rootLabel: 'Continents',
+					childrenAttrs: ['children']
+				});
+				var grid2 = new dojox.grid.TreeGrid({
+					treeModel: treeModel2,
+					structure: layout,
+					defaultOpen: true
+				}, 'programmatic_grid');
+				grid2.startup();
+				dojo.connect(window, "onresize", grid2, "resize");
+			});
+        </script>
+    </head>
+    <body class="tundra">
+        <h1 class="testTitle">Test: dojox.grid.TreeGrid - Model-based</h1>
+        <span dojoType="dojo.data.ItemFileWriteStore"
+              jsId="jsonStore" data="dataItems">
+        </span>
+
+        <div dojoType="dijit.tree.ForestStoreModel" jsId="continentModel"
+        store="jsonStore" query="{type:'continent'}"
+        rootId="continentRoot" rootLabel="Continents" childrenAttrs="children"></div>
+
+        <h4 class="testSubtitle">dojox.grid.TreeGrid n-Level</h4>
+        <button dojoType="dijit.form.Button">
+            Add Belgium
+            <script type="dojo/connect" event="onClick">
+                add_item({ id: 'EU_BE', name: 'Belgium', type: 'country' }, "EU");
+				this.set("disabled", true);
+            </script>
+        </button>
+        <button dojoType="dijit.form.Button">
+            Delete Italy
+            <script type="dojo/connect" event="onClick">
+				jsonStore.fetchItemByIdentity({
+					identity: 'IT',
+					onItem: function(item){
+						if(item){
+							jsonStore.deleteItem(item);
+						}
+					}
+				});
+				this.set("disabled", true);
+            </script>
+        </button>
+        <button dojoType="dijit.form.Button">
+            Add California
+            <script type="dojo/connect" event="onClick">
+                add_item({ id: 'US_CA', name: 'California', type: 'state' }, "US");
+				delCal.attr("disabled", false);
+				this.set("disabled", true);
+            </script>
+        </button>
+        <button dojoType="dijit.form.Button" disabled jsId="delCal">
+            Delete California
+            <script type="dojo/connect" event="onClick">
+				jsonStore.fetchItemByIdentity({
+					identity: 'US_CA',
+					onItem: function(item){
+						if(item){
+							jsonStore.deleteItem(item);
+						}
+					}
+				});
+				this.set("disabled", true);
+            </script>
+        </button>
+        <button dojoType="dijit.form.Button" jsId="delEU">
+            Delete Europe
+            <script type="dojo/connect" event="onClick">
+				jsonStore.fetchItemByIdentity({
+					identity: 'EU',
+					onItem: function(item){
+						if(item){
+							jsonStore.deleteItem(item);
+						}
+					}
+				});
+				this.set("disabled", true);
+            </script>
+        </button>
+        <button dojoType="dijit.form.Button" jsId="empty">
+            Empty
+            <script type="dojo/connect" event="onClick">
+				jsonStore.fetch({
+					query: { id: '*' },
+					queryOptions: { deep: true },
+					onComplete: function(items){
+						dojo.forEach(items, function(item){
+							if(item){
+								jsonStore.deleteItem(item);
+							}
+						});
+					}
+				});
+				jsonStore.save();
+				this.set("disabled", true);
+            </script>
+        </button>
+        <table jsid="grid" dojoType="dojox.grid.TreeGrid" class="grid" treeModel="continentModel">
+            <thead>
+                <tr>
+                    <th field="name" width="auto">Name</th>
+                    <th field="population" width="auto">Population</th>
+                    <th field="timezone" width="auto">Timezone</th>
+                </tr>
+            </thead>
+        </table>
+		<h4 class="testSubtitle">dojox.grid.TreeGrid Programmatic - defaultOpen true</h4>
+		<div id="programmatic_grid"></div>
+    </body>
+</html>
+
diff --git a/dojox/grid/tests/test_treegrid_model_lazy.html b/dojox/grid/tests/test_treegrid_model_lazy.html
new file mode 100644
index 0000000..f697140
--- /dev/null
+++ b/dojox/grid/tests/test_treegrid_model_lazy.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+    <head>
+        <title>dojox.grid.TreeGrid Model-based lazy loading test</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+        <style type="text/css">
+            @import "../../../dojo/resources/dojo.css";
+            @import "../../../dijit/themes/tundra/tundra.css";
+            @import "../resources/Grid.css";
+            @import "../resources/tundraGrid.css";
+            .grid {
+                width: 70em;
+                height: 40em;
+            }
+        </style>
+        <script type="text/javascript" src="../../../dojo/dojo.js"  djConfig="isDebug:true, parseOnLoad: false"></script>
+        <script type="text/javascript">
+            dojo.require("dojox.grid.TreeGrid");
+            dojo.require("dijit.tree.ForestStoreModel");
+			dojo.require("dojox.data.JsonRestStore");
+            dojo.require("dijit.form.Button");
+            dojo.require("dojo.parser");
+
+
+			jsonStore = null, childItems = null, dataItems = null, fullItems = null;
+			dojo.addOnLoad(function(){
+				childItems = {
+					'AF': [
+						{ id: 'EG', name:'Egypt', type:'country' },
+						{ id: 'KE', name:'Kenya', type:'country' },
+						{ id: 'SD', name:'Sudan', type:'country' }
+					],
+					'KE': [
+						{ id: 'Nairobi', name:'Nairobi', type:'city' },
+						{ id: 'Mombasa', name:'Mombasa', type:'city' }
+					],
+					'SD': [
+						{ id: 'Khartoum', name:'Khartoum', type:'city' }
+					],
+					'AS': [
+						{ id: 'CN', name:'China', type:'country' },
+						{ id: 'IN', name:'India', type:'country' },
+						{ id: 'RU', name:'Russia', type:'country' },
+						{ id: 'MN', name:'Mongolia', type:'country' }
+					],
+					'OC': [
+						{ id: 'AU', name:'Australia', type:'country', population:'21 million'}
+					],
+					'EU': [
+						{ id: 'DE', name:'Germany', type:'country' },
+						{ id: 'FR', name:'France', type:'country' },
+						{ id: 'ES', name:'Spain', type:'country' },
+						{ id: 'IT', name:'Italy', type:'country' }
+					]
+				};
+				dataItems = [
+					{ id: 'AF', name:'Africa', type:'continent', population:'900 million', area: '30,221,532 sq km',
+						timezone: '-1 UTC to +4 UTC', children: true, '$ref': 'AF' },
+					{ id: 'AS', name:'Asia', type:'continent', children: true, '$ref': 'AS' },
+					{ id: 'OC', name:'Oceania', type:'continent', population:'21 million', children: true, '$ref': 'OC' },
+					{ id: 'EU', name:'Europe', type:'continent', children: true, '$ref': 'EU' }
+				];
+				fullItems = {};
+				dojo.forEach(dataItems, function(item){
+					var full = fullItems[item.id] = dojo.mixin({}, item, { children: childItems[item.id] });
+					delete full['$ref'];
+				});
+				var mockService = function(query){
+					var d = new dojo.Deferred();
+					if(typeof query == 'string'){
+						setTimeout(function(){
+							d.callback(fullItems[query]);
+						}, 500);
+					}else{
+						d.fullLength = dataItems.length;
+						d.callback(dataItems);
+					}
+					return d;
+				};
+				jsonStore = new dojox.data.JsonRestStore({
+					service: mockService,
+					target: '/some/url'
+				});
+				dojo.parser.parse();
+			});
+        </script>
+    </head>
+    <body class="tundra">
+        <h1 class="testTitle">Test: dojox.grid.TreeGrid - Model-based lazy loading</h1>
+
+        <div dojoType="dijit.tree.ForestStoreModel" jsId="continentModel"
+			store="jsonStore" query="{type:'continent'}"
+			deferItemLoadingUntilExpand="true"
+			rootId="continentRoot" rootLabel="Continents" childrenAttrs="children">
+		</div>
+
+        <h4 class="testSubtitle">dojox.grid.TreeGrid n-Level</h4>
+        <table jsid="grid" dojoType="dojox.grid.TreeGrid" class="grid" treeModel="continentModel">
+            <thead>
+                <tr>
+                    <th field="name" width="auto">Name</th>
+                </tr>
+            </thead>
+        </table>
+    </body>
+</html>
+
diff --git a/dojox/grid/tests/test_treegrid_performance.html b/dojox/grid/tests/test_treegrid_performance.html
new file mode 100644
index 0000000..d6aab22
--- /dev/null
+++ b/dojox/grid/tests/test_treegrid_performance.html
@@ -0,0 +1,205 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.TreeGrid Performance Tests</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../resources/Grid.css";
+		@import "../resources/tundraGrid.css";
+		.grid {
+			width: 70em;
+			height: 15em;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: false"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojox.grid.TreeGrid");
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojo.parser");
+
+		// Set to true in order to kick off profiling startup and resizes in
+		// firebug
+		var doProfiling = false;
+		var profileTime = 100;
+
+		var resizeAndProfile = function(grid){
+			var d = new dojo.Deferred();
+			if(doProfiling){
+				console.profile("Resize " + grid.id);
+				window.profiling = true;
+				window.profid = grid.id;
+			}
+			grid.resize();
+			if(doProfiling){
+				window.setTimeout(function(){
+					console.profileEnd();
+					delete window.profiling;
+					d.callback(true);
+				}, profileTime);
+			}else{
+				d.callback(true);
+			}
+			return d;
+		}
+		
+		var parseAndProfile = function(parseContainer, idx){
+			var d = new dojo.Deferred();
+			if(doProfiling){
+				console.profile("Startup/Creation " + idx);
+				window.profiling = true;
+				window.profid = "idx_"+idx;
+			}
+			dojo.parser.parse(parseContainer);
+			if(doProfiling){
+				window.setTimeout(function(){
+					console.profileEnd();
+					delete window.profiling;
+					d.callback(true);
+				}, profileTime);
+			}else{
+				d.callback(true);
+			}
+			return d;			
+		}
+		
+		dojo.addOnLoad(function(){
+			dojo.parser.parse(dojo.query(".testTitle")[0]);
+			dijit._Templated.getCachedTemplate(dojo.moduleUrl("dojox.grid","resources/_Grid.html"));
+			dijit._Templated.getCachedTemplate(dojo.moduleUrl("dojox.grid", "resources/Expando.html"));
+			dijit._Templated.getCachedTemplate(dojo.moduleUrl("dojox.grid","resources/View.html"));
+			jsonStore.fetch({onComplete: function(){
+				doProfiling = dojo.isMoz && doProfiling;
+				dojo.connect(window, "onresize", function(){
+					var grids = dojo.filter(dojo.query(".grid").map(dijit.byNode), function(w){ return w && w.resize; });
+					var i = 0;
+					var cb = function(){
+						var g = grids[i];
+						i++;
+						if(g){
+							d = resizeAndProfile(g);
+							d.addCallback(cb);
+						}
+					};
+					cb();
+				});
+				var containers = dojo.query(".parseContainer");
+				var idx = 0;
+				var pcb = function(){
+					var cont = containers[idx];
+					idx++;
+					if(cont){
+						d = parseAndProfile(cont, idx - 1);
+						d.addCallback(pcb);
+					}
+				};
+				pcb();
+			}});
+		});
+
+		function formatTime(value, rowIdx){
+			var hrs = Math.floor(value / 60) + "";
+			var mins = (value % 60) + "";
+			while (hrs.length < 2){
+				hrs = "0" + hrs;
+			}
+			while (mins.length < 2){
+				mins = "0" + mins;
+			}
+			return hrs + ":" + mins;
+		}
+		
+		function summaryFormatter(value, rowIdx, cell, sing, plur){
+			var str;
+			if(rowIdx >= 0){
+				return value;
+			}
+			if(rowIdx == -1){
+				str = "Total (${numItems} ${displayName}):";
+			}else{
+				str = "${numItems} ${displayName}";
+			}
+			return dojo.string.substitute(str, {numItems: value, 
+						displayName: (value == 1) ? sing : plur});			
+		}
+		function quarterSummary(value, rowIdx){
+			return summaryFormatter(value, rowIdx, this, "Quarter", "Quarters");
+		}
+		function gameSummary(value, rowIdx){
+			return summaryFormatter(value, rowIdx, this, "Game", "Games");
+		}
+		function seasonSummary(value, rowIdx){
+			return summaryFormatter(value, rowIdx, this, "Season", "Seasons");
+		}
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">
+		Test: dojox.tests.grid.TreeGrid Performance
+		<span dojoType="dojo.data.ItemFileWriteStore" 
+			jsId="jsonStore" url="support/gamedata.json">
+		</span>
+	</h1>
+
+	<h4 class="testSubtitle">dojox.grid.DataGrid (For reference)</h4>
+	<div class="parseContainer">
+		<table dojoType="dojox.grid.DataGrid" class="grid" style="height: 15em;width: 100%;"
+			store="jsonStore" rowsPerPage="50" query="{label:'Quarter *'}" queryOptions="{deep: true}" rowSelector="false">
+			<thead>
+				<tr>
+					<th field="label" relWidth="2" formatter="quarterSummary">Quarter</th>
+					<th field="pts" relWidth="1">Points</th>
+					<th field="reb" relWidth="1">Rebounds</th>
+					<th field="ast" relWidth="1">Assists</th>
+					<th field="tp" relWidth="1" formatter="formatTime">Time Played</th>
+				</tr>
+			</thead>
+		</table>
+	</div>
+	<h4 class="testSubtitle">dojox.grid.TreeGrid Large 4-Level</h4>
+	<div class="parseContainer">
+		<table dojoType="dojox.grid.TreeGrid" class="grid" style="height: 15em;width: 100%;"
+			store="jsonStore" rowsPerPage="20" rowSelector="false">
+			<thead>
+				<tr>
+					<th field="label" relWidth="2">Player</th>
+					<th field="seasns" aggregate="sum" itemAggregates="numSeasons">
+						<table>
+							<thead>
+								<tr>
+									<th field="label" relWidth="2" formatter="seasonSummary">Season</th>
+									<th field="games" aggregate="sum" itemAggregates="numGames">
+										<table>
+											<thead>
+												<tr>
+													<th field="label" relWidth="2" formatter="gameSummary">Game</th>
+													<th field="qtrs" aggregate="sum" itemAggregates="numQtrs,totPts,totReb,totAst,totTP">
+														<table>
+															<thead>
+																<tr>
+																	<th field="label" relWidth="2" formatter="quarterSummary">Quarter</th>
+																	<th field="pts" relWidth="1">Points</th>
+																	<th field="reb" relWidth="1">Rebounds</th>
+																	<th field="ast" relWidth="1">Assists</th>
+																	<th field="tp" relWidth="1" formatter="formatTime">Time Played</th>
+																</tr>
+															</thead>
+														</table>
+													</th>
+												</tr>
+											</thead>
+										</table>
+									</th>
+								</tr>
+							</thead>
+						</table>
+					</th>
+				</tr>
+			</thead>
+		</table>
+	</div>
+</body>
+</html>
+
diff --git a/dojox/grid/tests/test_tundra_edit.html b/dojox/grid/tests/test_tundra_edit.html
new file mode 100644
index 0000000..51cf97f
--- /dev/null
+++ b/dojox/grid/tests/test_tundra_edit.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+	<head>
+		<title>Test dojox.grid.DataGrid Editing</title>
+		<style type="text/css">
+			@import "../resources/Grid.css";
+			@import "../resources/tundraGrid.css";
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+
+			.dojoxGridRowEditing td {
+				background-color: #F4FFF4;
+			}
+			.dojoxGrid input, .dojoxGrid select, .dojoxGrid textarea {
+				margin: 0;
+				padding: 0;
+				border-style: none;
+				width: 100%;
+				font-size: 100%;
+				font-family: inherit;
+			}
+			.dojoxGrid input { }
+			.dojoxGrid select { }
+			.dojoxGrid textarea { }
+
+			#controls {
+				padding: 6px 0;
+			}
+			#controls button {
+				margin-left: 10px;
+			}
+			.myGrid {
+				width: 850px;
+				height: 350px;
+				border: 1px solid silver;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js"
+			djConfig="isDebug:false, parseOnLoad: true"></script>
+		<script type="text/javascript">
+			dojo.require("dijit.dijit");
+			dojo.require("dojox.grid.DataGrid");
+			dojo.require("dojo.data.ItemFileWriteStore");
+			dojo.require("dojo.parser");
+		</script>
+		<script type="text/javascript" src="support/test_data.js"></script>
+		<script type="text/javascript">
+			// ==========================================================================
+			// Custom formatter
+			// ==========================================================================
+			formatMoney = function(inDatum){
+				return isNaN(inDatum) ? '...' : '$' + parseFloat(inDatum).toFixed(2);
+			}
+
+			// ==========================================================================
+			// Grid structure
+			// ==========================================================================
+			selectCell = {
+				styles: 'text-align: center;',
+				type: dojox.grid.cells.Select
+			};
+
+			gridLayout = {
+				defaultCell: { width: 8, editable: true, styles: 'text-align: right;'  },
+				rows: [
+					[
+						{ name: 'Id', width: 3, field: 'id' },
+						dojo.mixin({}, selectCell, {
+							name: 'Priority', field: 'col1', options: [ 'normal', 'note', 'important' ]
+						}),
+						{ name: 'Mark', width: 3, field: 'col2', styles: 'text-align: center;', type: dojox.grid.cells.Bool },
+						dojo.mixin({}, selectCell, {
+							name: 'Status', field: 'col3', options: [ 'new', 'read', 'replied' ]
+						}),
+						{ name: 'Message', field: 'col4', styles: '', width: '100%' },
+						{ name: 'Amount', field: 'col5', formatter: formatMoney }
+					]
+				]
+			};
+			// ==========================================================================
+			// UI Action
+			// ==========================================================================
+			addRow = function() {
+				test_store.newItem({
+					id: grid.rowCount,
+					col1: 'normal',
+					col2: false,
+					col3: 'new',
+					col4: 'Now is the time for all good men to come to the aid of their party.',
+					col5: 99.99,
+					col6: 9.99,
+					col7: false
+				});
+			}
+		</script>
+	</head>
+	<body class="tundra">
+		<h1>dojox.grid.DataGrid Basic Editing test</h1>
+		<br />
+		<div id="controls">
+			<button onclick="grid.render()">Refresh</button>
+			<button onclick="grid.edit.focusEditor()">Focus Editor</button>
+			<button onclick="grid.focus.next()">Next Focus</button>
+			<button onclick="addRow()">Add Row</button>
+			<button onclick="grid.removeSelectedRows()">Remove</button>
+			<button onclick="grid.edit.apply()">Apply</button>
+			<button onclick="grid.edit.cancel()">Cancel</button>
+			<button onclick="grid.singleClickEdit = !grid.singleClickEdit">Toggle singleClickEdit</button>
+		</div>
+		<br />
+		<div jsId="grid" class="myGrid" 
+			dojoType="dojox.grid.DataGrid" store="test_store" 
+			structure="gridLayout" rowSelector="20px"></div>
+		<br />
+		<div id="rowCount"></div>
+	</body>
+</html>
diff --git a/dojox/grid/tests/test_yahoo_images.html b/dojox/grid/tests/test_yahoo_images.html
new file mode 100644
index 0000000..3252ebc
--- /dev/null
+++ b/dojox/grid/tests/test_yahoo_images.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid - Image Search Test</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style>
+		@import "../resources/Grid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.grid {
+			height: 30em;
+			width: 51em;
+			border: 1px solid silver;
+		}
+		#info { width: 700px; }
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="debugAtAllCosts: false, isDebug:false, parseOnLoad: true">
+	</script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.io.script");
+		dojo.require("dojox.rpc.Service");
+		dojo.require("dojox.data.ServiceStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="yahooSearch.js"></script>	
+	<script type="text/javascript">
+		var service = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.SMDLibrary", "yahoo.smd"));
+		var store = new YahooStore({ service: service.imageSearch });
+
+		// Define grid structure
+		// remove the height from the header image cell / row cells have a default height so there's less adjustment when thumb comes in.
+		beforeImageRow = function(inRowIndex, inSubRows){
+			inSubRows[0].hidden = (inRowIndex == -1);
+		}
+		
+		var imageLayout = {
+			onBeforeRow: beforeImageRow,
+			width: 'auto',
+			cells: [
+				{ name: 'Image', cellStyles: "height: 100px;", styles: "text-align: center;", width: 12, get: getImage, formatter: formatImage },
+				{ name: 'Image', cellStyles: "height: 100px;", styles: "text-align: center;", width: 12, get: getImage, formatter: formatImage },
+				{ name: 'Image', cellStyles: "height: 100px;", styles: "text-align: center;", width: 12, get: getImage, formatter: formatImage },
+				{ name: 'Image', cellStyles: "height: 100px;", styles: "text-align: center;", width: 12, get: getImage, formatter: formatImage }
+			]
+		};
+		
+		// execute search
+		doSearch = function() {
+			var value = dojo.byId("searchInput").value;
+			grid.filter({ query: value }, true);
+		}
+
+		dojo.addOnLoad(function(){
+			dojo.query("#searchInput").onkeypress(function(e){
+				if(e.keyCode == dojo.keys.ENTER){ doSearch(); }
+			});
+		});
+	</script>
+</head>
+<body>
+	<h3>dojox.grid.Grid - Image Search Test</h3>
+	<input id="searchInput" type="text" value="apple">
+	<button onclick="doSearch()" style="clear: both;">Search</button>
+	<div dojoType="dojox.grid.DataGrid" 
+		id="grid" jsId="grid" class="grid" structure="imageLayout" 
+		store="store" elasticView="1" query="{ query: 'apple' }" 
+		rowSelector="20px">
+	</div>
+	<br>
+	<div id="info">
+		<div id="rowCount" style="float: left"></div>
+		<div style="float: right">
+			<div id="sendInfo" style="text-align: right"></div>
+			<div id="receiveInfo" style="text-align: right"></div>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/grid/tests/test_yahoo_search.html b/dojox/grid/tests/test_yahoo_search.html
new file mode 100644
index 0000000..bc65865
--- /dev/null
+++ b/dojox/grid/tests/test_yahoo_search.html
@@ -0,0 +1,131 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+	"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid - Yahoo Search Test</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style>
+		@import "../resources/Grid.css";
+		body {
+			font-size: 0.9em;
+			font-family: Geneva, Arial, Helvetica, sans-serif;
+		}
+		.grid {
+			height: 30em;
+		}
+		
+		#info {
+			width: 700px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" 
+		djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.io.script");
+		dojo.require("dojox.rpc.Service");
+		dojo.require("dojox.data.ServiceStore");
+		dojo.require("dojo.parser");
+	</script>
+	<script type="text/javascript" src="yahooSearch.js"></script>
+	<script type="text/javascript">
+		var service = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.SMDLibrary", "yahoo.smd"));
+		var store = new YahooStore({ service: service.webSearch });
+
+		var webLayout = [ 
+			{
+				noscroll: true,
+				cells: [
+					new dojox.grid.cells.RowIndex({ width: 3, styles: 'text-align: center;' })
+				]
+			},
+			[
+				[
+					{ name: 'Site', width: 30, field: 'ClickUrl', get: getLink, formatter: formatLink },
+					{ name: 'Date', width: 10, field: 'ModificationDate', formatter: formatDate}
+				],[
+					{ name: 'Display Url', width: 30, field: 'Url', styles: 'color: green; size: small;' },
+					{ name: 'Type', width: 10, field: 'MimeType', styles: ' font-style: italic; color: gray; size: small;'}
+				],[
+					{ name: 'Summary',  width: 40, colSpan: 2, field: 'Summary' }
+				]
+			]
+		];
+		
+		// remove the height from the header image cell / row cells have a
+		// default height so there's less adjustment when thumb comes in.
+		beforeImageRow = function(inRowIndex, inSubRow) {
+			inSubRow[0][0].cellStyles = (inRowIndex == -1 ? '' : 'height: 100px;');
+			inSubRow[1][0].cellStyles = (inRowIndex == -1 ? '' : 'vertical-align: top; height: 75px;');
+		}
+		
+		var imageLayout = [ 
+			{
+				noscroll: true,
+				cells: [
+					new dojox.grid.cells.RowIndex({ width: 3, styles: 'text-align: center;' })
+				]
+			},
+			{
+				onBeforeRow: beforeImageRow,
+				cells: [
+					[
+						{ name: 'Image', cellStyles: "height: 100px;", styles: "text-align: center;", width: 13, rowSpan: 2, field: 'Url', get: getImage },
+						{ name: 'Title', cellStyles: "height: 10px;", width: 14, field: 'Title', get: getLink }, 
+						{ name: 'Size', width: 8, field: 'FileSize', styles: "font-style: italic; text-align: center;" },
+						{ name: 'Dimensions', width: 8, styles: "text-align: center;", get: getDimensions }
+					],
+					[
+						{ name: 'Summary',  cellStyles: "vertical-align: top; height: 75px;", colSpan: 3, field: 'Summary' }
+					]
+				]
+			}
+		];
+		
+		// execute search
+		var lastLayoutType = webLayout;
+		doSearch = function(){
+			var value = dojo.byId("searchInput").value;
+			var web = dojo.byId('webRb').checked;
+			store.service = (web ? service.webSearch : service.imageSearch);
+			if(lastLayoutType != (web ? webLayout : imageLayout)){
+				grid.attr('structure', web ? webLayout : imageLayout);
+			}
+			grid.filter({ query: value }, true);
+		}
+		
+		dojo.addOnLoad(function(){
+			dojo.byId('webRb').checked = "checked";
+			dojo.query("#searchInput").onkeypress(function(e){
+				if(e.keyCode == dojo.keys.ENTER){ doSearch(); }
+			});
+		});
+
+	</script>
+</head>
+<body>
+	<div style="font-weight: bold; padding-bottom: 0.25em;">dojox.grid.Grid - Yahoo Search Test</div>
+	<div style="padding-bottom: 3px;">
+		<label><input id="webRb" type="radio" name="searchType" checked>Web</label>  
+		<label><input id="imageRb" type="radio" name="searchType">Images</label>
+	</div>	
+	<input id="searchInput" type="text" value="apple">  
+	<button onclick="doSearch()">Search</button><br><br>
+	<div dojoType="dojox.grid.DataGrid" 
+		jsId="grid" class="grid" id="grid"
+		autoWidth="true" structure="webLayout" 
+		store="store" elasticView="1" 
+		query="{ query: 'apple' }" 
+		rowSelector="20px">
+	</div>
+	<br>
+	<div id="info">
+		<div id="rowCount" style="float: left"></div>
+		<div style="float: right">
+			<div id="sendInfo" style="text-align: right"></div>
+			<div id="receiveInfo" style="text-align: right"></div>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/grid/tests/yahooSearch.js b/dojox/grid/tests/yahooSearch.js
new file mode 100644
index 0000000..3d0fc3e
--- /dev/null
+++ b/dojox/grid/tests/yahooSearch.js
@@ -0,0 +1,76 @@
+dojo.declare("YahooStore", dojox.data.ServiceStore, {
+	_processResults: function(results, def){
+		var totalCount = 0;
+		if(results.ResultSet){
+			totalCount = results.ResultSet.totalResultsAvailable;
+			results = results.ResultSet.Result;
+		}
+		var resultSet = this.inherited(arguments);
+		resultSet.totalCount = totalCount > 1000 ? 1000 : totalCount;
+		return resultSet;
+	},
+	fetch: function(request){
+		if(request.query){
+			if(request.count){
+				request.query['results'] = request.count;
+			}
+			if(typeof request.start != "undefined"){
+				request.query['start'] = request.start + 1;
+			}
+		}
+
+		return this.inherited(arguments);
+	}
+});
+
+var getCellData = function(item, field){
+	return grid.store.getValue(item, field);
+};
+
+var getLink = function(inRowIndex, inItem){
+	if(!inItem){ return ' '; }
+	return {
+		text: getCellData(inItem, 'Title'),
+		href: getCellData(inItem, 'ClickUrl')
+	};
+};
+
+var formatLink = function(result){
+	return typeof result == 'object' ? dojo.string.substitute(
+		'<a target="_blank" href="${href}">${text}</a>', 
+		result
+	) : result;
+}
+
+var formatDate = function(inDatum, inRowIndex){
+	if(!inDatum){ return ' '; }
+	var d = new Date(inDatum * 1000);
+	return dojo.string.substitute(
+		"${0}/${1}/${2}",
+		[ d.getMonth()+1, d.getDate(), d.getFullYear() ]
+	);
+};
+
+var getImage = function(inRowIndex, inItem){
+	if(!inItem){ return ' '; }
+	var thumb = getCellData(inItem, "Thumbnail");
+	return {
+		href: getCellData(inItem, "ClickUrl"),
+		src: thumb.Url,
+		width: thumb.Width,
+		height: thumb.Height
+	};
+};
+
+var formatImage = function(result){
+	return typeof result == "object" ? dojo.string.substitute(
+		'<a href="${href}" target="_blank"><img border=0 src="${src}" width="${width}" height="${height}"></a>', result) :
+		result;	
+}
+
+var getDimensions = function(inRowIndex, inItem){
+	if(!inItem){ return ' '; }
+	var w = getCellData(inItem, "Width");
+	var h = getCellData(inItem, "Height");
+	return w + ' x ' + h;
+};
diff --git a/dojox/grid/util.js b/dojox/grid/util.js
index bbf9527..cc0c227 100644
--- a/dojox/grid/util.js
+++ b/dojox/grid/util.js
@@ -1,66 +1,68 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.grid.util"]){
-dojo._hasResource["dojox.grid.util"]=true;
 dojo.provide("dojox.grid.util");
+
+// summary: grid utility library
 (function(){
-var _1=dojox.grid.util;
-_1.na="...";
-_1.rowIndexTag="gridRowIndex";
-_1.gridViewTag="gridView";
-_1.fire=function(ob,ev,_2){
-var fn=ob&&ev&&ob[ev];
-return fn&&(_2?fn.apply(ob,_2):ob[ev]());
-};
-_1.setStyleHeightPx=function(_3,_4){
-if(_4>=0){
-var s=_3.style;
-var v=_4+"px";
-if(_3&&s["height"]!=v){
-s["height"]=v;
-}
-}
-};
-_1.mouseEvents=["mouseover","mouseout","mousedown","mouseup","click","dblclick","contextmenu"];
-_1.keyEvents=["keyup","keydown","keypress"];
-_1.funnelEvents=function(_5,_6,_7,_8){
-var _9=(_8?_8:_1.mouseEvents.concat(_1.keyEvents));
-for(var i=0,l=_9.length;i<l;i++){
-_6.connect(_5,"on"+_9[i],_7);
-}
-};
-_1.removeNode=function(_a){
-_a=dojo.byId(_a);
-_a&&_a.parentNode&&_a.parentNode.removeChild(_a);
-return _a;
-};
-_1.arrayCompare=function(_b,_c){
-for(var i=0,l=_b.length;i<l;i++){
-if(_b[i]!=_c[i]){
-return false;
-}
-}
-return (_b.length==_c.length);
-};
-_1.arrayInsert=function(_d,_e,_f){
-if(_d.length<=_e){
-_d[_e]=_f;
-}else{
-_d.splice(_e,0,_f);
-}
-};
-_1.arrayRemove=function(_10,_11){
-_10.splice(_11,1);
-};
-_1.arraySwap=function(_12,inI,inJ){
-var _13=_12[inI];
-_12[inI]=_12[inJ];
-_12[inJ]=_13;
-};
+	var dgu = dojox.grid.util;
+
+	dgu.na = '...';
+	dgu.rowIndexTag = "gridRowIndex";
+	dgu.gridViewTag = "gridView";
+
+
+	dgu.fire = function(ob, ev, args){
+		var fn = ob && ev && ob[ev];
+		return fn && (args ? fn.apply(ob, args) : ob[ev]());
+	};
+	
+	dgu.setStyleHeightPx = function(inElement, inHeight){
+		if(inHeight >= 0){
+			var s = inElement.style;
+			var v = inHeight + 'px';
+			if(inElement && s['height'] != v){
+				s['height'] = v;
+			}
+		}
+	};
+	
+	dgu.mouseEvents = [ 'mouseover', 'mouseout', /*'mousemove',*/ 'mousedown', 'mouseup', 'click', 'dblclick', 'contextmenu' ];
+
+	dgu.keyEvents = [ 'keyup', 'keydown', 'keypress' ];
+
+	dgu.funnelEvents = function(inNode, inObject, inMethod, inEvents){
+		var evts = (inEvents ? inEvents : dgu.mouseEvents.concat(dgu.keyEvents));
+		for (var i=0, l=evts.length; i<l; i++){
+			inObject.connect(inNode, 'on' + evts[i], inMethod);
+		}
+	};
+
+	dgu.removeNode = function(inNode){
+		inNode = dojo.byId(inNode);
+		inNode && inNode.parentNode && inNode.parentNode.removeChild(inNode);
+		return inNode;
+	};
+	
+	dgu.arrayCompare = function(inA, inB){
+		for(var i=0,l=inA.length; i<l; i++){
+			if(inA[i] != inB[i]){return false;}
+		}
+		return (inA.length == inB.length);
+	};
+	
+	dgu.arrayInsert = function(inArray, inIndex, inValue){
+		if(inArray.length <= inIndex){
+			inArray[inIndex] = inValue;
+		}else{
+			inArray.splice(inIndex, 0, inValue);
+		}
+	};
+	
+	dgu.arrayRemove = function(inArray, inIndex){
+		inArray.splice(inIndex, 1);
+	};
+	
+	dgu.arraySwap = function(inArray, inI, inJ){
+		var cache = inArray[inI];
+		inArray[inI] = inArray[inJ];
+		inArray[inJ] = cache;
+	};
 })();
-}
diff --git a/dojox/help/_base.js b/dojox/help/_base.js
index c4a97a5..510aae2 100644
--- a/dojox/help/_base.js
+++ b/dojox/help/_base.js
@@ -1,387 +1,470 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.help._base"]){
-dojo._hasResource["dojox.help._base"]=true;
 dojo.provide("dojox.help._base");
 dojo.require("dojox.rpc.Service");
 dojo.require("dojo.io.script");
+
 dojo.experimental("dojox.help");
 console.warn("Script causes side effects (on numbers, strings, and booleans). Call dojox.help.noConflict() if you plan on executing code.");
-dojox.help={locate:function(_1,_2,_3){
-_3=_3||20;
-var _4=[];
-var _5={};
-var _6;
-if(_2){
-if(!dojo.isArray(_2)){
-_2=[_2];
-}
-for(var i=0,_7;_7=_2[i];i++){
-_6=_7;
-if(dojo.isString(_7)){
-_7=dojo.getObject(_7);
-if(!_7){
-continue;
-}
-}else{
-if(dojo.isObject(_7)){
-_6=_7.__name__;
-}else{
-continue;
-}
-}
-_4.push(_7);
-if(_6){
-_6=_6.split(".")[0];
-if(!_5[_6]&&dojo.indexOf(dojox.help._namespaces,_6)==-1){
-dojox.help.refresh(_6);
-}
-_5[_6]=true;
-}
-}
-}
-if(!_4.length){
-_4.push({__name__:"window"});
-dojo.forEach(dojox.help._namespaces,function(_8){
-_5[_8]=true;
-});
-}
-var _9=_1.toLowerCase();
-var _a=[];
-out:
-for(var i=0,_7;_7=_4[i];i++){
-var _b=_7.__name__||"";
-var _c=dojo.some(_4,function(_d){
-_d=_d.__name__||"";
-return (_b.indexOf(_d+".")==0);
-});
-if(_b&&!_c){
-_6=_b.split(".")[0];
-var _e=[];
-if(_b=="window"){
-for(_6 in dojox.help._names){
-if(dojo.isArray(dojox.help._names[_6])){
-_e=_e.concat(dojox.help._names[_6]);
-}
-}
-}else{
-_e=dojox.help._names[_6];
-}
-for(var j=0,_f;_f=_e[j];j++){
-if((_b=="window"||_f.indexOf(_b+".")==0)&&_f.toLowerCase().indexOf(_9)!=-1){
-if(_f.slice(-10)==".prototype"){
-continue;
-}
-var obj=dojo.getObject(_f);
-if(obj){
-_a.push([_f,obj]);
-if(_a.length==_3){
-break out;
-}
-}
-}
-}
-}
-}
-dojox.help._displayLocated(_a);
-if(!dojo.isMoz){
-return "";
-}
-},refresh:function(_10,_11){
-if(arguments.length<2){
-_11=true;
-}
-dojox.help._recurse(_10,_11);
-},noConflict:function(_12){
-if(arguments.length){
-return dojox.help._noConflict(_12);
-}else{
-while(dojox.help._overrides.length){
-var _13=dojox.help._overrides.pop();
-var _14=_13[0];
-var key=_13[1];
-var _15=_14[key];
-_14[key]=dojox.help._noConflict(_15);
-}
-}
-},init:function(_16,_17){
-if(_16){
-dojox.help._namespaces.concat(_16);
-}
-dojo.addOnLoad(function(){
-dojo.require=(function(_18){
-return function(){
-dojox.help.noConflict();
-_18.apply(dojo,arguments);
-if(dojox.help._timer){
-clearTimeout(dojox.help._timer);
-}
-dojox.help._timer=setTimeout(function(){
-dojo.addOnLoad(function(){
-dojox.help.refresh();
-dojox.help._timer=false;
-});
-},500);
-};
-})(dojo.require);
-dojox.help._recurse();
-});
-},_noConflict:function(_19){
-if(_19 instanceof String){
-return _19.toString();
-}else{
-if(_19 instanceof Number){
-return +_19;
-}else{
-if(_19 instanceof Boolean){
-return (_19==true);
-}else{
-if(dojo.isObject(_19)){
-delete _19.__name__;
-delete _19.help;
-}
-}
-}
-}
-return _19;
-},_namespaces:["dojo","dojox","dijit","djConfig"],_rpc:new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.SMDLibrary","dojo-api.smd")),_attributes:["summary","type","returns","parameters"],_clean:function(_1a){
-var obj={};
-for(var i=0,_1b;_1b=dojox.help._attributes[i];i++){
-var _1c=_1a["__"+_1b+"__"];
-if(_1c){
-obj[_1b]=_1c;
-}
-}
-return obj;
-},_displayLocated:function(_1d){
-throw new Error("_displayLocated should be overridden in one of the dojox.help packages");
-},_displayHelp:function(_1e,obj){
-throw new Error("_displayHelp should be overridden in one of the dojox.help packages");
-},_addVersion:function(obj){
-if(obj.name){
-obj.version=[dojo.version.major,dojo.version.minor,dojo.version.patch].join(".");
-var _1f=obj.name.split(".");
-if(_1f[0]=="dojo"||_1f[0]=="dijit"||_1f[0]=="dojox"){
-obj.project=_1f[0];
-}
-}
-return obj;
-},_stripPrototype:function(_20){
-var _21=_20.replace(/\.prototype(\.|$)/g,".");
-var _22=_21;
-if(_21.slice(-1)=="."){
-_22=_21=_21.slice(0,-1);
-}else{
-_21=_20;
-}
-return [_22,_21];
-},_help:function(){
-var _23=this.__name__;
-var _24=dojox.help._stripPrototype(_23)[0];
-var _25=[];
-for(var i=0,_26;_26=dojox.help._attributes[i];i++){
-if(!this["__"+_26+"__"]){
-_25.push(_26);
-}
-}
-dojox.help._displayHelp(true,{name:this.__name__});
-if(!_25.length||this.__searched__){
-dojox.help._displayHelp(false,dojox.help._clean(this));
-}else{
-this.__searched__=true;
-dojox.help._rpc.get(dojox.help._addVersion({name:_24,exact:true,attributes:_25})).addCallback(this,function(_27){
-if(this.toString===dojox.help._toString){
-this.toString(_27);
-}
-if(_27&&_27.length){
-_27=_27[0];
-for(var i=0,_26;_26=dojox.help._attributes[i];i++){
-if(_27[_26]){
-this["__"+_26+"__"]=_27[_26];
-}
-}
-dojox.help._displayHelp(false,dojox.help._clean(this));
-}else{
-dojox.help._displayHelp(false,false);
-}
-});
-}
-if(!dojo.isMoz){
-return "";
-}
-},_parse:function(_28){
-delete this.__searching__;
-if(_28&&_28.length){
-var _29=_28[0].parameters;
-if(_29){
-var _2a=["function ",this.__name__,"("];
-this.__parameters__=_29;
-for(var i=0,_2b;_2b=_29[i];i++){
-if(i){
-_2a.push(", ");
-}
-_2a.push(_2b.name);
-if(_2b.types){
-var _2c=[];
-for(var j=0,_2d;_2d=_2b.types[j];j++){
-_2c.push(_2d.title);
-}
-if(_2c.length){
-_2a.push(": ");
-_2a.push(_2c.join("|"));
-}
-}
-if(_2b.repeating){
-_2a.push("...");
-}
-if(_2b.optional){
-_2a.push("?");
-}
-}
-_2a.push(")");
-this.__source__=this.__source__.replace(/function[^\(]*\([^\)]*\)/,_2a.join(""));
-}
-if(this.__output__){
-delete this.__output__;
-}
-}else{
-dojox.help._displayHelp(false,false);
-}
-},_toStrings:{},_toString:function(_2e){
-if(!this.__source__){
-return this.__name__;
-}
-var _2f=(!this.__parameters__);
-this.__parameters__=[];
-if(_2e){
-dojox.help._parse.call(this,_2e);
-}else{
-if(_2f){
-this.__searching__=true;
-dojox.help._toStrings[dojox.help._stripPrototype(this.__name__)[0]]=this;
-if(dojox.help._toStringTimer){
-clearTimeout(dojox.help._toStringTimer);
-}
-dojox.help._toStringTimer=setTimeout(function(){
-dojox.help.__toString();
-},50);
-}
-}
-if(!_2f||!this.__searching__){
-return this.__source__;
-}
-var _30="function Loading info for "+this.__name__+"... (watch console for result) {}";
-if(!dojo.isMoz){
-this.__output__=true;
-return _30;
-}
-return {toString:dojo.hitch(this,function(){
-this.__output__=true;
-return _30;
-})};
-},__toString:function(){
-if(dojox.help._toStringTimer){
-clearTimeout(dojox.help._toStringTimer);
-}
-var _31=[];
-dojox.help.noConflict(dojox.help._toStrings);
-for(var _32 in dojox.help._toStrings){
-_31.push(_32);
-}
-while(_31.length){
-dojox.help._rpc.batch(dojox.help._addVersion({names:_31.splice(-50,50),exact:true,attributes:["parameters"]})).addCallback(this,function(_33){
-for(var i=0,_34;_34=_33[i];i++){
-var fn=dojox.help._toStrings[_34.name];
-if(fn){
-dojox.help._parse.call(fn,[_34]);
-delete dojox.help._toStrings[_34.name];
-}
-}
-});
-}
-},_overrides:[],_recursions:[],_names:{},_recurse:function(_35,_36){
-if(arguments.length<2){
-_36=true;
-}
-var _37=[];
-if(_35&&dojo.isString(_35)){
-dojox.help.__recurse(dojo.getObject(_35),_35,_35,_37,_36);
-}else{
-for(var i=0,ns;ns=dojox.help._namespaces[i];i++){
-if(window[ns]){
-dojox.help._recursions.push([window[ns],ns,ns]);
-window[ns].__name__=ns;
-if(!window[ns].help){
-window[ns].help=dojox.help._help;
-}
-}
-}
-}
-while(dojox.help._recursions.length){
-var _38=dojox.help._recursions.shift();
-dojox.help.__recurse(_38[0],_38[1],_38[2],_37,_36);
-}
-for(var i=0,_39;_39=_37[i];i++){
-delete _39.__seen__;
-}
-},__recurse:function(_3a,_3b,_3c,_3d,_3e){
-for(var key in _3a){
-if(key.match(/([^\w_.$]|__[\w_.$]+__)/)){
-continue;
-}
-var _3f=_3a[key];
-if(typeof _3f=="undefined"||_3f===document||_3f===window||_3f===dojox.help._toString||_3f===dojox.help._help||_3f===null||(+dojo.isIE&&_3f.tagName)||_3f.__seen__){
-continue;
-}
-var _40=dojo.isFunction(_3f);
-var _41=dojo.isObject(_3f)&&!dojo.isArray(_3f)&&!_3f.nodeType;
-var _42=(_3c)?(_3c+"."+key):key;
-if(_42=="dojo._blockAsync"){
-continue;
-}
-if(!_3f.__name__){
-var _43=null;
-if(dojo.isString(_3f)){
-_43=String;
-}else{
-if(typeof _3f=="number"){
-_43=Number;
-}else{
-if(typeof _3f=="boolean"){
-_43=Boolean;
-}
-}
-}
-if(_43){
-_3f=_3a[key]=new _43(_3f);
-}
-}
-_3f.__seen__=true;
-_3f.__name__=_42;
-(dojox.help._names[_3b]=dojox.help._names[_3b]||[]).push(_42);
-_3d.push(_3f);
-if(!_40){
-dojox.help._overrides.push([_3a,key]);
-}
-if((_40||_41)&&_3e){
-dojox.help._recursions.push([_3f,_3b,_42]);
-}
-if(_40){
-if(!_3f.__source__){
-_3f.__source__=_3f.toString().replace(/^function\b ?/,"function "+_42);
-}
-if(_3f.toString===Function.prototype.toString){
-_3f.toString=dojox.help._toString;
-}
-}
-if(!_3f.help){
-_3f.help=dojox.help._help;
-}
-}
-}};
-}
+
+dojox.help = {
+	// summary:
+	//		Adds the help function to all variables.
+	locate: function(/*String*/ searchFor, /*String|Object|String[]|Object[]*/ searchIn, /*Number*/ maxResults){
+		// summary:
+		//		Search for dojo functionality that has something to do with the given string.
+		//  description:
+		//		Search for locally available data; variable names and any cached
+		//		documentation results for matches containing our search parameter
+		// searchFor
+		//		The string to search for.
+		// searchIn:
+		//		The namespaces to search in. Defaults to dojox.help._namespaces
+		// maxResults:
+		//		The maximum number of results.
+		maxResults = maxResults || 20;
+		var namespaces = [];
+		var roots = {};
+		var root;
+		if(searchIn){
+			if(!dojo.isArray(searchIn)){
+				searchIn = [searchIn];
+			}
+			for(var i = 0, namespace; namespace = searchIn[i]; i++){
+				root = namespace;
+				if(dojo.isString(namespace)){
+					namespace = dojo.getObject(namespace);
+					if(!namespace){
+						continue;
+					}
+				}else if(dojo.isObject(namespace)){
+					root = namespace.__name__;
+				}else{
+					continue;
+				}
+				// Add to a list of namespace objects (in object form)
+				namespaces.push(namespace);
+				if(root){
+					root = root.split(".")[0];
+					if(!roots[root] && dojo.indexOf(dojox.help._namespaces, root) == -1){
+						// Refresh anything that's not part of our global namespace list
+						dojox.help.refresh(root);
+					}
+					roots[root] = true;
+				}
+			}
+		}
+		if(!namespaces.length){
+			namespaces.push({ __name__: "window" });
+			dojo.forEach(dojox.help._namespaces, function(item){ roots[item] = true; });
+		}
+
+		var searchForLower = searchFor.toLowerCase();
+		var found = [];
+		out:
+		for(var i = 0, namespace; namespace = namespaces[i]; i++){
+			var name = namespace.__name__ || "";
+			var shorter = dojo.some(namespaces, function(item){
+				// Return true if we find a namespace below
+				// the current namespace
+				item = item.__name__ || "";
+				return (name.indexOf(item + ".") == 0);
+			});
+			if(name && !shorter){
+				root = name.split(".")[0];
+				var names = [];
+				if(name == "window"){
+					for(root in dojox.help._names){
+						if(dojo.isArray(dojox.help._names[root])){
+							names = names.concat(dojox.help._names[root]);
+						}
+					}
+				}else{
+					names = dojox.help._names[root];
+				}
+				for(var j = 0, variable; variable = names[j]; j++){
+					if((name == "window" || variable.indexOf(name + ".") == 0) && variable.toLowerCase().indexOf(searchForLower) != -1){
+						if(variable.slice(-10) == ".prototype"){ continue; }
+						var obj = dojo.getObject(variable);
+						if(obj){
+							found.push([variable, obj]);
+							if(found.length == maxResults){
+								break out;
+							}
+						}
+					}
+				}
+			}
+		}
+
+		dojox.help._displayLocated(found);
+		if(!dojo.isMoz){
+			return "";
+		}
+	},
+	refresh: function(/*String?*/ namespace, /*Boolean?*/ recursive){
+		// summary:
+		//		Useful if you reset some values, and want to restore their
+		//		help function
+		// namespace:
+		//		The string-representation of a namespace.
+		// recursive:
+		//		Whether to recurse through the namespace.
+		if(arguments.length < 2){
+			recursive = true;
+		}
+		dojox.help._recurse(namespace, recursive);
+	},
+	noConflict: function(/*Object?*/ item){
+		// summary:
+		//		Use this function when you want to resolve the problems
+		//		created by including a dojox.help package.
+		// item:
+		//		If you pass an item, only that item will be cleaned
+		if(arguments.length){
+			return dojox.help._noConflict(item);
+		}else{
+			while(dojox.help._overrides.length){
+				var override = dojox.help._overrides.pop();
+				var parent = override[0];
+				var key = override[1];
+				var child = parent[key];
+				parent[key] = dojox.help._noConflict(child);
+			}
+		}
+	},
+	init: function(/*String[]*/ namespaces, /*Boolen?*/ noConflict){
+		// summary:
+		//		Should be called by one of the implementations. Runs startup code
+		// namespaces:
+		//		Any namespaces to add to the default (dojox.help._namespaces)
+		// noConflict:
+		//		Whether to start in noConflict mode
+		if(namespaces){
+			dojox.help._namespaces.concat(namespaces);
+		}
+		dojo.addOnLoad(function(){
+			dojo.require = (function(require){
+				return function(){
+					dojox.help.noConflict();
+					require.apply(dojo, arguments);
+					if(dojox.help._timer){
+						clearTimeout(dojox.help._timer);
+					}
+					dojox.help._timer = setTimeout(function(){
+						dojo.addOnLoad(function(){
+							dojox.help.refresh();
+							dojox.help._timer = false;
+						});
+					}, 500);
+				}
+			})(dojo.require);
+
+			dojox.help._recurse();
+		});
+	},
+	_noConflict: function(item){
+		if(item instanceof String){
+			return item.toString();
+		}else if(item instanceof Number){
+			return +item;
+		}else if(item instanceof Boolean){
+			return (item == true);
+		}else if(dojo.isObject(item)){
+			delete item.__name__;
+			delete item.help;
+		}
+		return item;
+	},
+	_namespaces: ["dojo", "dojox", "dijit", "djConfig"],
+	_rpc: new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.SMDLibrary", "dojo-api.smd")),
+	_attributes: ["summary", "type", "returns", "parameters"],
+	_clean: function(self){
+		var obj = {};
+		for(var i = 0, attribute; attribute = dojox.help._attributes[i]; i++){
+			var value = self["__" + attribute + "__"];
+			if(value){
+				obj[attribute] = value;
+			}
+		}
+		return obj;
+	},
+	_displayLocated: function(located){
+		// summary:
+		//		Stub function to be overridden in one of the dojox.help packages
+		throw new Error("_displayLocated should be overridden in one of the dojox.help packages");
+	},
+	_displayHelp: function(loading, obj){
+		// summary:
+		//		Stub function to be overridden in one of the dojox.help packages
+		throw new Error("_displayHelp should be overridden in one of the dojox.help packages");
+	},
+	_addVersion: function(obj){
+		if(obj.name){
+			obj.version = [dojo.version.major, dojo.version.minor, dojo.version.patch].join(".");
+			var parts = obj.name.split(".");
+			if(parts[0] == "dojo" || parts[0] == "dijit" || parts[0] == "dojox"){
+				obj.project = parts[0];
+			}
+		}
+		return obj;
+	},
+	_stripPrototype: function(original){
+		var name = original.replace(/\.prototype(\.|$)/g, ".");
+		var search = name;
+		if(name.slice(-1) == "."){
+			search = name = name.slice(0, -1);
+		}else{
+			name = original;
+		}
+		return [search, name];
+	},
+	_help: function(){
+		var name = this.__name__;
+		var search = dojox.help._stripPrototype(name)[0];
+		var attributes = [];
+		for(var i = 0, attribute; attribute = dojox.help._attributes[i]; i++){
+			if(!this["__" + attribute + "__"]){
+				attributes.push(attribute);
+			}
+		}
+
+		dojox.help._displayHelp(true, { name: this.__name__ });
+
+		if(!attributes.length || this.__searched__){
+			dojox.help._displayHelp(false, dojox.help._clean(this));
+		}else{
+			this.__searched__ = true;
+			dojox.help._rpc.get(dojox.help._addVersion({
+				name: search,
+				exact: true,
+				attributes: attributes
+			})).addCallback(this, function(data){
+				if(this.toString === dojox.help._toString){
+					this.toString(data);
+				}
+				if(data && data.length){
+					data = data[0];
+					for(var i = 0, attribute; attribute = dojox.help._attributes[i]; i++){
+						if(data[attribute]){
+							this["__" + attribute + "__"] = data[attribute];
+						}
+					}
+					dojox.help._displayHelp(false, dojox.help._clean(this));
+				}else{
+					dojox.help._displayHelp(false, false);
+				}
+			});
+		}
+		if(!dojo.isMoz){
+			return "";
+		}
+	},
+	_parse: function(data){
+		delete this.__searching__;
+		if(data && data.length){
+			var parameters = data[0].parameters;
+
+			if(parameters){
+				var signature = ["function ", this.__name__, "("];
+				this.__parameters__ = parameters;
+				for(var i = 0, parameter; parameter = parameters[i]; i++){
+					if(i){
+						signature.push(", ");
+					}
+					signature.push(parameter.name);
+					if(parameter.types){
+						var types = [];
+						for(var j = 0, type; type = parameter.types[j]; j++){
+							types.push(type.title);
+						}
+						if(types.length){
+							signature.push(": ");
+							signature.push(types.join("|"));
+						}
+					}
+					if(parameter.repeating){
+						signature.push("...");
+					}
+					if(parameter.optional){
+						signature.push("?");
+					}
+				}
+				signature.push(")");
+
+				this.__source__ = this.__source__.replace(/function[^\(]*\([^\)]*\)/, signature.join(""));
+			}
+
+			if(this.__output__){
+				delete this.__output__;
+				console.log(this);
+			}
+		}else{
+			dojox.help._displayHelp(false, false);
+		}
+	},
+	_toStrings: {},
+	_toString: function(data){
+		if(!this.__source__){
+			return this.__name__;
+		}
+
+		var first = (!this.__parameters__);
+		this.__parameters__ = [];
+
+		if(data){
+			dojox.help._parse.call(this, data);
+		}else if(first){
+			this.__searching__ = true;
+			dojox.help._toStrings[dojox.help._stripPrototype(this.__name__)[0]] = this;
+			if(dojox.help._toStringTimer){
+				clearTimeout(dojox.help._toStringTimer);
+			}
+			dojox.help._toStringTimer = setTimeout(function(){ dojox.help.__toString(); }, 50);
+		}
+
+		if(!first || !this.__searching__){
+			return this.__source__;
+		}
+
+		var message = "function Loading info for " + this.__name__ + "... (watch console for result) {}";
+
+		if(!dojo.isMoz){
+			this.__output__ = true;
+			return message;
+		}
+
+		return {
+			toString: dojo.hitch(this, function(){
+				// Detect if this was called by Firebug
+				this.__output__ = true;
+				return message;
+			})
+		};
+	},
+	__toString: function(){
+		if(dojox.help._toStringTimer){
+			clearTimeout(dojox.help._toStringTimer);
+		}
+
+		var names = [];
+		dojox.help.noConflict(dojox.help._toStrings);
+		for(var name in dojox.help._toStrings){
+			names.push(name);
+		}
+		while(names.length){
+			dojox.help._rpc.batch(dojox.help._addVersion({
+				names: names.splice(-50, 50),
+				exact: true,
+				attributes: ["parameters"]
+			})).addCallback(this, function(datas){
+				for(var i = 0, data; data = datas[i]; i++){
+					var fn = dojox.help._toStrings[data.name];
+					if(fn){
+						dojox.help._parse.call(fn, [data]);
+						delete dojox.help._toStrings[data.name];
+					}
+				}
+			});
+		}
+	},
+	_overrides: [],
+	_recursions: [],
+	_names: {},
+	_recurse: function(/*String?*/ namespace, /*Boolean?*/ recursive){
+		if(arguments.length < 2){
+			recursive = true;
+		}
+
+		var items = [];
+
+		if(namespace && dojo.isString(namespace)){
+			dojox.help.__recurse(dojo.getObject(namespace), namespace, namespace, items, recursive);
+		}else{
+			for(var i = 0, ns; ns = dojox.help._namespaces[i]; i++){
+				if(window[ns]){
+					dojox.help._recursions.push([window[ns], ns, ns]);
+					window[ns].__name__ = ns;
+					if(!window[ns].help){
+						window[ns].help = dojox.help._help;
+					}
+				}
+			}
+		}
+
+		while(dojox.help._recursions.length){
+			var recursion = dojox.help._recursions.shift();
+			dojox.help.__recurse(recursion[0], recursion[1], recursion[2], items, recursive);
+		}
+
+		for(var i = 0, item; item = items[i]; i++){
+			delete item.__seen__;
+		}
+	},
+	__recurse: function(namespace, root, name, items, recursive){
+		for(var key in namespace){
+			if(key.match(/([^\w_.$]|__[\w_.$]+__)/)){
+				continue;
+			}
+
+			var item = namespace[key];
+			if(typeof item == "undefined"
+				|| item === document
+				|| item === window
+				|| item === dojox.help._toString
+				|| item === dojox.help._help
+				|| item === null
+				|| (+dojo.isIE && item.tagName)
+				|| item.__seen__
+			) {
+				continue;
+			}
+
+			var isFunction = dojo.isFunction(item);
+			var isObject = dojo.isObject(item) && !dojo.isArray(item) && !item.nodeType;
+
+			var itemName = (name) ? (name + "." + key) : key;
+
+			if(itemName == "dojo._blockAsync"){
+				continue;
+			}
+
+			if(!item.__name__){
+				var parent = null;
+				if(dojo.isString(item)){
+					parent = String;
+				}else if(typeof item == "number"){
+					parent = Number;
+				}else if(typeof item == "boolean"){
+					parent = Boolean;
+				}
+				if(parent){
+					item = namespace[key] = new parent(item);
+				}
+			}
+
+			item.__seen__ = true;
+			item.__name__ = itemName;
+			(dojox.help._names[root] = dojox.help._names[root] || []).push(itemName);
+			items.push(item);
+			if(!isFunction){
+				dojox.help._overrides.push([namespace, key]);
+			}
+
+			if((isFunction || isObject) && recursive){
+				dojox.help._recursions.push([item, root, itemName]);
+			}
+
+			if(isFunction){
+				if(!item.__source__){
+					item.__source__ = item.toString().replace(/^function\b ?/, "function " + itemName);
+				}
+				if(item.toString === Function.prototype.toString){
+					item.toString = dojox.help._toString;
+				}
+			}
+
+			if(!item.help){
+				item.help = dojox.help._help;
+			}
+		}
+	}
+};
\ No newline at end of file
diff --git a/dojox/help/console.js b/dojox/help/console.js
index fa3dd28..360e164 100644
--- a/dojox/help/console.js
+++ b/dojox/help/console.js
@@ -1,78 +1,76 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.help.console"]){
-dojo._hasResource["dojox.help.console"]=true;
 dojo.provide("dojox.help.console");
 dojo.require("dojox.help._base");
-dojo.mixin(dojox.help,{_plainText:function(_1){
-return _1.replace(/(<[^>]*>|&[^;]{2,6};)/g,"");
-},_displayLocated:function(_2){
-var _3={};
-dojo.forEach(_2,function(_4){
-_3[_4[0]]=dojo.isMoz?{toString:function(){
-return "Click to view";
-},item:_4[1]}:_4[1];
+
+dojo.mixin(dojox.help, {
+	_plainText: function(str){
+		return str.replace(/(<[^>]*>|&[^;]{2,6};)/g, '');
+	},
+	_displayLocated: function(located){
+		var obj = {};
+		dojo.forEach(located, function(item){ obj[item[0]] = dojo.isMoz ? { toString: function(){ return "Click to view"; }, item: item[1] } : item[1]; });
+		console.dir(obj);
+	},
+	_displayHelp: function(loading, obj){
+		if(loading){
+			var message = "Help for: " + obj.name;
+			console.log(message);
+			var underline = "";
+			for(var i = 0; i < message.length; i++){
+				underline += "=";
+			}
+			console.log(underline);
+		}else if(!obj){
+			console.log("No documentation for this object");
+		}else{
+			var anything = false;
+			for(var attribute in obj){
+				var value = obj[attribute];
+				if(attribute == "returns" && obj.type != "Function" && obj.type != "Constructor"){
+					continue;
+				}
+				if(value && (!dojo.isArray(value) || value.length)){
+					anything = true;
+					console.info(attribute.toUpperCase());
+					value = dojo.isString(value) ? dojox.help._plainText(value) : value;
+					if(attribute == "returns"){
+						var returns = dojo.map(value.types || [], "return item.title;").join("|");
+						if(value.summary){
+							if(returns){
+								returns += ": ";
+							}
+							returns += dojox.help._plainText(value.summary);
+						}
+						console.log(returns || "Uknown");
+					}else if(attribute == "parameters"){
+						for(var j = 0, parameter; parameter = value[j]; j++){
+							var type = dojo.map(parameter.types, "return item.title").join("|");
+							console.log((type) ? (parameter.name + ": " + type) : parameter.name);
+							var summary = "";
+							if(parameter.optional){
+								summary += "Optional. ";
+							}
+							if(parameter.repating){
+								summary += "Repeating. ";
+							}
+							summary += dojox.help._plainText(parameter.summary);
+							if(summary){
+								summary = "  - " + summary;
+								for(var k = 0; k < parameter.name.length; k++){
+									summary = " " + summary;
+								}
+								console.log(summary);
+							}
+						}
+					}else{
+						console.log(value);
+					}
+				}
+			}
+			if(!anything){
+				console.log("No documentation for this object");
+			}
+		}
+	}
 });
-},_displayHelp:function(_5,_6){
-if(_5){
-var _7="Help for: "+_6.name;
-var _8="";
-for(var i=0;i<_7.length;i++){
-_8+="=";
-}
-}else{
-if(!_6){
-}else{
-var _9=false;
-for(var _a in _6){
-var _b=_6[_a];
-if(_a=="returns"&&_6.type!="Function"&&_6.type!="Constructor"){
-continue;
-}
-if(_b&&(!dojo.isArray(_b)||_b.length)){
-_9=true;
-_b=dojo.isString(_b)?dojox.help._plainText(_b):_b;
-if(_a=="returns"){
-var _c=dojo.map(_b.types||[],"return item.title;").join("|");
-if(_b.summary){
-if(_c){
-_c+=": ";
-}
-_c+=dojox.help._plainText(_b.summary);
-}
-}else{
-if(_a=="parameters"){
-for(var j=0,_d;_d=_b[j];j++){
-var _e=dojo.map(_d.types,"return item.title").join("|");
-var _f="";
-if(_d.optional){
-_f+="Optional. ";
-}
-if(_d.repating){
-_f+="Repeating. ";
-}
-_f+=dojox.help._plainText(_d.summary);
-if(_f){
-_f="  - "+_f;
-for(var k=0;k<_d.name.length;k++){
-_f=" "+_f;
-}
-}
-}
-}else{
-}
-}
-}
-}
-if(!_9){
-}
-}
-}
-}});
-dojox.help.init();
-}
+
+dojox.help.init();
\ No newline at end of file
diff --git a/dojox/help/demos/demo_Console.html b/dojox/help/demos/demo_Console.html
new file mode 100644
index 0000000..ce33546
--- /dev/null
+++ b/dojox/help/demos/demo_Console.html
@@ -0,0 +1,32 @@
+<html>
+	<head>
+		<title>Simple demo of dojox.help.console</title>
+		<script src="../../../dojo/dojo.js" type="text/javascript" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.addOnLoad(function(){
+				dojo.query("code").onclick(function(e){
+					var cmd = e.target.innerHTML;
+					if(cmd.slice(-1) == ";"){
+						dojo.eval(cmd);
+					}else{
+						console.log(dojo.getObject(cmd));
+					}
+				});
+			});
+		</script>
+	</head>
+	<body>
+		<p>You'll want to open up Firebug for this</p>
+		<p>Click each of the items below to run the command:</p>
+		<ul>
+			<li><code>dojo.require("dojox.help.console");</code></li>
+			<li><code>dojox.help.locate("Xhr", dojo);</code> searches variable names in the dojo namespaces for "Xhr" (no matter the case).</li>
+			<li><code>dojo.query.help();</code> displays help for dojo.byId</li>
+			<li><code>dojo.connect</code> loads and displays the function signature for dojo.connect</li>
+			<li><code>dojo.isBrowser</code> shows an example of a "conflict". It's using the Boolean object rather than the boolean generic.</li>
+			<li><code>dojox.help.noConflict();</code> fixes this conflict (click on <code>dojo.isBrowser</code> again).</li>
+			<li><code>dojox.help.refresh();</code> parses the page again!</li>
+			<li><code>dojo.isBrowser</code> and the conflict is back again!</li>
+		</ul>
+	</body>
+</html>
diff --git a/dojox/highlight.js b/dojox/highlight.js
index 514b7e3..342bf75 100644
--- a/dojox/highlight.js
+++ b/dojox/highlight.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight"]){
-dojo._hasResource["dojox.highlight"]=true;
 dojo.provide("dojox.highlight");
-dojo.require("dojox.highlight._base");
-}
+dojo.require("dojox.highlight._base"); 
diff --git a/dojox/highlight/_base.js b/dojox/highlight/_base.js
index 77db294..8786cce 100644
--- a/dojox/highlight/_base.js
+++ b/dojox/highlight/_base.js
@@ -1,327 +1,462 @@
-/*
-	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
-*/
+dojo.provide("dojox.highlight._base");
+/*=====
+	dojox.highlight = {
+		//	summary: 
+		//		Syntax highlighting with language auto-detection package
+		//
+		//	description:
+		//		
+		//		Syntax highlighting with language auto-detection package.
+		//		Released under CLA by the Dojo Toolkit, original BSD release 
+		//		available from: http://softwaremaniacs.org/soft/highlight/
+		//
+		//		
+	};
+=====*/
 
+;(function(){
+	var dh = dojox.highlight,
+		C_NUMBER_RE = '\\b(0x[A-Za-z0-9]+|\\d+(\\.\\d+)?)';
+	
+	// constants
+
+	dh.constants = {
+		IDENT_RE: '[a-zA-Z][a-zA-Z0-9_]*',
+		UNDERSCORE_IDENT_RE: '[a-zA-Z_][a-zA-Z0-9_]*',
+		NUMBER_RE: '\\b\\d+(\\.\\d+)?',
+		C_NUMBER_RE: C_NUMBER_RE,
+		// Common modes
+		APOS_STRING_MODE: {
+			className: 'string',
+			begin: '\'', end: '\'',
+			illegal: '\\n',
+			contains: ['escape'],
+			relevance: 0
+		},
+		QUOTE_STRING_MODE: {
+			className: 'string',
+			begin: '"', 
+			end: '"',
+			illegal: '\\n',
+			contains: ['escape'],
+			relevance: 0
+		},
+		BACKSLASH_ESCAPE: {
+			className: 'escape',
+			begin: '\\\\.', end: '^',
+			relevance: 0
+		},
+		C_LINE_COMMENT_MODE: {
+			className: 'comment',
+			begin: '//', end: '$',
+			relevance: 0
+		},
+		C_BLOCK_COMMENT_MODE: {
+			className: 'comment',
+			begin: '/\\*', end: '\\*/'
+		},
+		HASH_COMMENT_MODE: {
+			className: 'comment',
+			begin: '#', end: '$'
+		},
+		C_NUMBER_MODE: {
+			className: 'number',
+			begin: C_NUMBER_RE, end: '^',
+			relevance: 0
+		}
+	};
+
+	// utilities
+	
+	function esc(value){
+		return value.replace(/&/gm, '&').replace(/</gm, '<').replace(/>/gm, '>');
+	}
+	
+	function verifyText(block){
+		return dojo.every(block.childNodes, function(node){
+			return node.nodeType == 3 || String(node.nodeName).toLowerCase() == 'br';
+		});
+	}
+
+	function blockText(block){
+		var result = [];
+		dojo.forEach(block.childNodes, function(node){
+			if(node.nodeType == 3){
+				result.push(node.nodeValue);
+			}else if(String(node.nodeName).toLowerCase() == 'br'){
+				result.push("\n");
+			}else{
+				throw 'Complex markup';
+			}
+		});
+		return result.join("");
+	}
+
+	function buildKeywordGroups(mode){
+		if(!mode.keywordGroups){
+			for(var key in mode.keywords){
+				var kw = mode.keywords[key];
+    			if(kw instanceof Object){  // dojo.isObject?
+					mode.keywordGroups = mode.keywords;
+				}else{ 
+					mode.keywordGroups = {keyword: mode.keywords};
+				}
+				break;
+			}
+		}
+	}
+	
+	function buildKeywords(lang){
+		if(lang.defaultMode && lang.modes){
+			buildKeywordGroups(lang.defaultMode);
+			dojo.forEach(lang.modes, buildKeywordGroups);
+		}
+	}
+	
+	// main object
+
+	var Highlighter = function(langName, textBlock){
+		// initialize the state
+		this.langName = langName;
+		this.lang = dh.languages[langName];
+		this.modes = [this.lang.defaultMode];
+		this.relevance = 0;
+		this.keywordCount = 0;
+		this.result = [];
+		
+		// build resources lazily
+		if(!this.lang.defaultMode.illegalRe){
+			this.buildRes();
+			buildKeywords(this.lang);
+		}
+		
+		// run the algorithm
+		try{
+			this.highlight(textBlock);
+			this.result = this.result.join("");
+		}catch(e){
+			if(e == 'Illegal'){
+				this.relevance = 0;
+				this.keywordCount = 0;
+				this.partialResult = this.result.join("");
+				this.result = esc(textBlock);
+			}else{
+				throw e;
+			}
+		}
+	};
+
+	dojo.extend(Highlighter, {
+		buildRes: function(){
+			dojo.forEach(this.lang.modes, function(mode){
+				if(mode.begin){
+					mode.beginRe = this.langRe('^' + mode.begin);
+				}
+				if(mode.end){
+					mode.endRe = this.langRe('^' + mode.end);
+				}
+				if(mode.illegal){
+					mode.illegalRe = this.langRe('^(?:' + mode.illegal + ')');
+				}
+			}, this);
+			this.lang.defaultMode.illegalRe = this.langRe('^(?:' + this.lang.defaultMode.illegal + ')');
+		},
+		
+		subMode: function(lexeme){
+			var classes = this.modes[this.modes.length - 1].contains;
+			if(classes){
+				var modes = this.lang.modes;
+				for(var i = 0; i < classes.length; ++i){
+					var className = classes[i];
+					for(var j = 0; j < modes.length; ++j){
+						var mode = modes[j];
+						if(mode.className == className && mode.beginRe.test(lexeme)){ return mode; }
+					}
+				}
+			}
+			return null;
+		},
+
+		endOfMode: function(lexeme){
+			for(var i = this.modes.length - 1; i >= 0; --i){
+				var mode = this.modes[i];
+				if(mode.end && mode.endRe.test(lexeme)){ return this.modes.length - i; }
+				if(!mode.endsWithParent){ break; }
+			}
+			return 0;
+		},
+
+		isIllegal: function(lexeme){
+			var illegalRe = this.modes[this.modes.length - 1].illegalRe;
+			return illegalRe && illegalRe.test(lexeme);
+		},
+
+
+		langRe: function(value, global){
+			var mode =  'm' + (this.lang.case_insensitive ? 'i' : '') + (global ? 'g' : '');
+			return new RegExp(value, mode);
+		},
+	
+		buildTerminators: function(){
+			var mode = this.modes[this.modes.length - 1],
+				terminators = {};
+			if(mode.contains){
+				dojo.forEach(this.lang.modes, function(lmode){
+					if(dojo.indexOf(mode.contains, lmode.className) >= 0){
+						terminators[lmode.begin] = 1;
+					}
+				});
+			}
+			for(var i = this.modes.length - 1; i >= 0; --i){
+				var m = this.modes[i];
+				if(m.end){ terminators[m.end] = 1; }
+				if(!m.endsWithParent){ break; }
+			}
+			if(mode.illegal){ terminators[mode.illegal] = 1; }
+			var t = [];
+			for(i in terminators){ t.push(i); }
+			mode.terminatorsRe = this.langRe("(" + t.join("|") + ")");
+		},
+
+		eatModeChunk: function(value, index){
+			var mode = this.modes[this.modes.length - 1];
+			
+			// create terminators lazily
+			if(!mode.terminatorsRe){
+				this.buildTerminators();
+			}
+	
+			value = value.substr(index);
+			var match = mode.terminatorsRe.exec(value);
+			if(!match){
+				return {
+					buffer: value,
+					lexeme: "",
+					end:    true
+				};
+			}
+			return {
+				buffer: match.index ? value.substr(0, match.index) : "",
+				lexeme: match[0],
+				end:    false
+			};
+		},
+	
+		keywordMatch: function(mode, match){
+			var matchStr = match[0];
+			if(this.lang.case_insensitive){ matchStr = matchStr.toLowerCase(); }
+			for(var className in mode.keywordGroups){
+				if(matchStr in mode.keywordGroups[className]){ return className; }
+			}
+			return "";
+		},
+		
+		buildLexemes: function(mode){
+			var lexemes = {};
+			dojo.forEach(mode.lexems, function(lexeme){
+				lexemes[lexeme] = 1;
+			});
+			var t = [];
+			for(var i in lexemes){ t.push(i); }
+			mode.lexemsRe = this.langRe("(" + t.join("|") + ")", true);
+		},
+	
+		processKeywords: function(buffer){
+			var mode = this.modes[this.modes.length - 1];
+			if(!mode.keywords || !mode.lexems){
+				return esc(buffer);
+			}
+			
+			// create lexemes lazily
+			if(!mode.lexemsRe){
+				this.buildLexemes(mode);
+			}
+			
+			mode.lexemsRe.lastIndex = 0;
+			var result = [], lastIndex = 0,
+				match = mode.lexemsRe.exec(buffer);
+			while(match){
+				result.push(esc(buffer.substr(lastIndex, match.index - lastIndex)));
+				var keywordM = this.keywordMatch(mode, match);
+				if(keywordM){
+					++this.keywordCount;
+					result.push('<span class="'+ keywordM +'">' + esc(match[0]) + '</span>');
+				}else{
+					result.push(esc(match[0]));
+				}
+				lastIndex = mode.lexemsRe.lastIndex;
+				match = mode.lexemsRe.exec(buffer);
+			}
+			result.push(esc(buffer.substr(lastIndex, buffer.length - lastIndex)));
+			return result.join("");
+		},
+	
+		processModeInfo: function(buffer, lexeme, end) {
+			var mode = this.modes[this.modes.length - 1];
+			if(end){
+				this.result.push(this.processKeywords(mode.buffer + buffer));
+				return;
+			}
+			if(this.isIllegal(lexeme)){ throw 'Illegal'; }
+			var newMode = this.subMode(lexeme);
+			if(newMode){
+				mode.buffer += buffer;
+				this.result.push(this.processKeywords(mode.buffer));
+				if(newMode.excludeBegin){
+					this.result.push(lexeme + '<span class="' + newMode.className + '">');
+					newMode.buffer = '';
+				}else{
+					this.result.push('<span class="' + newMode.className + '">');
+					newMode.buffer = lexeme;
+				}
+				this.modes.push(newMode);
+				this.relevance += typeof newMode.relevance == "number" ? newMode.relevance : 1;
+				return;
+			}
+			var endLevel = this.endOfMode(lexeme);
+			if(endLevel){
+				mode.buffer += buffer;
+				if(mode.excludeEnd){
+					this.result.push(this.processKeywords(mode.buffer) + '</span>' + lexeme);
+				}else{
+					this.result.push(this.processKeywords(mode.buffer + lexeme) + '</span>');
+				}
+				while(endLevel > 1){
+					this.result.push('</span>');
+					--endLevel;
+					this.modes.pop();
+				}
+				this.modes.pop();
+				this.modes[this.modes.length - 1].buffer = '';
+				return;
+			}
+		},
+	
+		highlight: function(value){
+			var index = 0;
+			this.lang.defaultMode.buffer = '';
+			do{
+				var modeInfo = this.eatModeChunk(value, index);
+				this.processModeInfo(modeInfo.buffer, modeInfo.lexeme, modeInfo.end);
+				index += modeInfo.buffer.length + modeInfo.lexeme.length;
+			}while(!modeInfo.end);
+			if(this.modes.length > 1){
+				throw 'Illegal';
+			}
+		}
+	});
+	
+	// more utilities
+	
+	function replaceText(node, className, text){
+		if(String(node.tagName).toLowerCase() == "code" && String(node.parentNode.tagName).toLowerCase() == "pre"){
+			// See these 4 lines? This is IE's notion of "node.innerHTML = text". Love this browser :-/
+			var container = document.createElement('div'),
+				environment = node.parentNode.parentNode;
+			container.innerHTML = '<pre><code class="' + className + '">' + text + '</code></pre>';
+			environment.replaceChild(container.firstChild, node.parentNode);
+		}else{
+			node.className = className;
+			node.innerHTML = text;
+		}
+	}
+	function highlightStringLanguage(lang, str){
+		var highlight = new Highlighter(lang, str);
+		return {result:highlight.result, langName:lang, partialResult:highlight.partialResult};		
+	}
+
+	function highlightLanguage(block, lang){
+		var result = highlightStringLanguage(lang, blockText(block));
+		replaceText(block, block.className, result.result);
+	}
+
+	function highlightStringAuto(str){
+		var result = "", langName = "", bestRelevance = 2,
+			textBlock = str;
+		for(var key in dh.languages){
+			if(!dh.languages[key].defaultMode){ continue; }	// skip internal members
+			var highlight = new Highlighter(key, textBlock),
+				relevance = highlight.keywordCount + highlight.relevance, relevanceMax = 0;
+			if(!result || relevance > relevanceMax){
+				relevanceMax = relevance;
+				result = highlight.result;
+				langName = highlight.langName;
+			}
+		}
+		return {result:result, langName:langName};
+	}
+	
+	function highlightAuto(block){
+		var result = highlightStringAuto(blockText(block));
+		if(result.result){
+			replaceText(block, result.langName, result.result);
+		}
+	}
+	
+	// the public API
+
+	dojox.highlight.processString = function(/* String */ str, /* String? */lang){
+		// summary: highlight a string of text
+		// returns: Object containing:
+		//         result - string of html with spans to apply formatting
+		//         partialResult - if the formating failed: string of html
+		//                 up to the point of the failure, otherwise: undefined
+		//         langName - the language used to do the formatting
+		return lang ? highlightStringLanguage(lang, str) : highlightStringAuto(str);
+	};
+
+	dojox.highlight.init = function(/* String|DomNode */ node){
+		//	summary: Highlight a passed node
+		//	
+		//	description:
+		//		
+		//		Syntax highlight a passed DomNode or String ID of a DomNode
+		//
+		// 
+		//	example:
+		//	|	dojox.highlight.init("someId");
+		//		
+		node = dojo.byId(node);
+		if(dojo.hasClass(node, "no-highlight")){ return; }
+		if(!verifyText(node)){ return; }
+	
+		var classes = node.className.split(/\s+/),
+			flag = dojo.some(classes, function(className){
+				if(className.charAt(0) != "_" && dh.languages[className]){
+					highlightLanguage(node, className);
+					return true;	// stop iterations
+				}
+				return false;	// continue iterations
+			});
+		if(!flag){
+			highlightAuto(node);
+		}
+	};
+
+/*=====
+	dojox.highlight.Code = function(props, node){
+		//	summary: A Class object to allow for dojoType usage with the highlight engine. This is
+		//		NOT a Widget in the conventional sense, and does not have any member functions for
+		//		the instance. This is provided as a convenience. You likely should be calling
+		//		`dojox.highlight.init` directly.
+		//
+		//	props: Object?
+		//		Unused. Pass 'null' or {}. Positional usage to allow `dojo.parser` to instantiate 
+		//		this class as other Widgets would be.
+		// 
+		//	node: String|DomNode
+		//		A String ID or DomNode reference to use as the root node of this instance. 
+		//
+		//	example:
+		//	|	<pre><code dojoType="dojox.highlight.Code">for(var i in obj){ ... }</code></pre>
+		//
+		//	example:
+		//	|	var inst = new dojox.highlight.Code({}, "someId");
+		//
+		this.node = dojo.byId(node);
+	};
+=====*/
+
+	dh.Code = function(p, n){ dh.init(n); };
 
-if(!dojo._hasResource["dojox.highlight._base"]){
-dojo._hasResource["dojox.highlight._base"]=true;
-dojo.provide("dojox.highlight._base");
-(function(){
-var dh=dojox.highlight,_1="\\b(0x[A-Za-z0-9]+|\\d+(\\.\\d+)?)";
-dh.constants={IDENT_RE:"[a-zA-Z][a-zA-Z0-9_]*",UNDERSCORE_IDENT_RE:"[a-zA-Z_][a-zA-Z0-9_]*",NUMBER_RE:"\\b\\d+(\\.\\d+)?",C_NUMBER_RE:_1,APOS_STRING_MODE:{className:"string",begin:"'",end:"'",illegal:"\\n",contains:["escape"],relevance:0},QUOTE_STRING_MODE:{className:"string",begin:"\"",end:"\"",illegal:"\\n",contains:["escape"],relevance:0},BACKSLASH_ESCAPE:{className:"escape",begin:"\\\\.",end:"^",relevance:0},C_LINE_COMMENT_MODE:{className:"comment",begin:"//",end:"$",relevance:0},C_B [...]
-function _2(_3){
-return _3.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">");
-};
-function _4(_5){
-return dojo.every(_5.childNodes,function(_6){
-return _6.nodeType==3||String(_6.nodeName).toLowerCase()=="br";
-});
-};
-function _7(_8){
-var _9=[];
-dojo.forEach(_8.childNodes,function(_a){
-if(_a.nodeType==3){
-_9.push(_a.nodeValue);
-}else{
-if(String(_a.nodeName).toLowerCase()=="br"){
-_9.push("\n");
-}else{
-throw "Complex markup";
-}
-}
-});
-return _9.join("");
-};
-function _b(_c){
-if(!_c.keywordGroups){
-for(var _d in _c.keywords){
-var kw=_c.keywords[_d];
-if(kw instanceof Object){
-_c.keywordGroups=_c.keywords;
-}else{
-_c.keywordGroups={keyword:_c.keywords};
-}
-break;
-}
-}
-};
-function _e(_f){
-if(_f.defaultMode&&_f.modes){
-_b(_f.defaultMode);
-dojo.forEach(_f.modes,_b);
-}
-};
-var _10=function(_11,_12){
-this.langName=_11;
-this.lang=dh.languages[_11];
-this.modes=[this.lang.defaultMode];
-this.relevance=0;
-this.keywordCount=0;
-this.result=[];
-if(!this.lang.defaultMode.illegalRe){
-this.buildRes();
-_e(this.lang);
-}
-try{
-this.highlight(_12);
-this.result=this.result.join("");
-}
-catch(e){
-if(e=="Illegal"){
-this.relevance=0;
-this.keywordCount=0;
-this.partialResult=this.result.join("");
-this.result=_2(_12);
-}else{
-throw e;
-}
-}
-};
-dojo.extend(_10,{buildRes:function(){
-dojo.forEach(this.lang.modes,function(_13){
-if(_13.begin){
-_13.beginRe=this.langRe("^"+_13.begin);
-}
-if(_13.end){
-_13.endRe=this.langRe("^"+_13.end);
-}
-if(_13.illegal){
-_13.illegalRe=this.langRe("^(?:"+_13.illegal+")");
-}
-},this);
-this.lang.defaultMode.illegalRe=this.langRe("^(?:"+this.lang.defaultMode.illegal+")");
-},subMode:function(_14){
-var _15=this.modes[this.modes.length-1].contains;
-if(_15){
-var _16=this.lang.modes;
-for(var i=0;i<_15.length;++i){
-var _17=_15[i];
-for(var j=0;j<_16.length;++j){
-var _18=_16[j];
-if(_18.className==_17&&_18.beginRe.test(_14)){
-return _18;
-}
-}
-}
-}
-return null;
-},endOfMode:function(_19){
-for(var i=this.modes.length-1;i>=0;--i){
-var _1a=this.modes[i];
-if(_1a.end&&_1a.endRe.test(_19)){
-return this.modes.length-i;
-}
-if(!_1a.endsWithParent){
-break;
-}
-}
-return 0;
-},isIllegal:function(_1b){
-var _1c=this.modes[this.modes.length-1].illegalRe;
-return _1c&&_1c.test(_1b);
-},langRe:function(_1d,_1e){
-var _1f="m"+(this.lang.case_insensitive?"i":"")+(_1e?"g":"");
-return new RegExp(_1d,_1f);
-},buildTerminators:function(){
-var _20=this.modes[this.modes.length-1],_21={};
-if(_20.contains){
-dojo.forEach(this.lang.modes,function(_22){
-if(dojo.indexOf(_20.contains,_22.className)>=0){
-_21[_22.begin]=1;
-}
-});
-}
-for(var i=this.modes.length-1;i>=0;--i){
-var m=this.modes[i];
-if(m.end){
-_21[m.end]=1;
-}
-if(!m.endsWithParent){
-break;
-}
-}
-if(_20.illegal){
-_21[_20.illegal]=1;
-}
-var t=[];
-for(i in _21){
-t.push(i);
-}
-_20.terminatorsRe=this.langRe("("+t.join("|")+")");
-},eatModeChunk:function(_23,_24){
-var _25=this.modes[this.modes.length-1];
-if(!_25.terminatorsRe){
-this.buildTerminators();
-}
-_23=_23.substr(_24);
-var _26=_25.terminatorsRe.exec(_23);
-if(!_26){
-return {buffer:_23,lexeme:"",end:true};
-}
-return {buffer:_26.index?_23.substr(0,_26.index):"",lexeme:_26[0],end:false};
-},keywordMatch:function(_27,_28){
-var _29=_28[0];
-if(this.lang.case_insensitive){
-_29=_29.toLowerCase();
-}
-for(var _2a in _27.keywordGroups){
-if(_29 in _27.keywordGroups[_2a]){
-return _2a;
-}
-}
-return "";
-},buildLexemes:function(_2b){
-var _2c={};
-dojo.forEach(_2b.lexems,function(_2d){
-_2c[_2d]=1;
-});
-var t=[];
-for(var i in _2c){
-t.push(i);
-}
-_2b.lexemsRe=this.langRe("("+t.join("|")+")",true);
-},processKeywords:function(_2e){
-var _2f=this.modes[this.modes.length-1];
-if(!_2f.keywords||!_2f.lexems){
-return _2(_2e);
-}
-if(!_2f.lexemsRe){
-this.buildLexemes(_2f);
-}
-_2f.lexemsRe.lastIndex=0;
-var _30=[],_31=0,_32=_2f.lexemsRe.exec(_2e);
-while(_32){
-_30.push(_2(_2e.substr(_31,_32.index-_31)));
-var _33=this.keywordMatch(_2f,_32);
-if(_33){
-++this.keywordCount;
-_30.push("<span class=\""+_33+"\">"+_2(_32[0])+"</span>");
-}else{
-_30.push(_2(_32[0]));
-}
-_31=_2f.lexemsRe.lastIndex;
-_32=_2f.lexemsRe.exec(_2e);
-}
-_30.push(_2(_2e.substr(_31,_2e.length-_31)));
-return _30.join("");
-},processModeInfo:function(_34,_35,end){
-var _36=this.modes[this.modes.length-1];
-if(end){
-this.result.push(this.processKeywords(_36.buffer+_34));
-return;
-}
-if(this.isIllegal(_35)){
-throw "Illegal";
-}
-var _37=this.subMode(_35);
-if(_37){
-_36.buffer+=_34;
-this.result.push(this.processKeywords(_36.buffer));
-if(_37.excludeBegin){
-this.result.push(_35+"<span class=\""+_37.className+"\">");
-_37.buffer="";
-}else{
-this.result.push("<span class=\""+_37.className+"\">");
-_37.buffer=_35;
-}
-this.modes.push(_37);
-this.relevance+=typeof _37.relevance=="number"?_37.relevance:1;
-return;
-}
-var _38=this.endOfMode(_35);
-if(_38){
-_36.buffer+=_34;
-if(_36.excludeEnd){
-this.result.push(this.processKeywords(_36.buffer)+"</span>"+_35);
-}else{
-this.result.push(this.processKeywords(_36.buffer+_35)+"</span>");
-}
-while(_38>1){
-this.result.push("</span>");
---_38;
-this.modes.pop();
-}
-this.modes.pop();
-this.modes[this.modes.length-1].buffer="";
-return;
-}
-},highlight:function(_39){
-var _3a=0;
-this.lang.defaultMode.buffer="";
-do{
-var _3b=this.eatModeChunk(_39,_3a);
-this.processModeInfo(_3b.buffer,_3b.lexeme,_3b.end);
-_3a+=_3b.buffer.length+_3b.lexeme.length;
-}while(!_3b.end);
-if(this.modes.length>1){
-throw "Illegal";
-}
-}});
-function _3c(_3d,_3e,_3f){
-if(String(_3d.tagName).toLowerCase()=="code"&&String(_3d.parentNode.tagName).toLowerCase()=="pre"){
-var _40=document.createElement("div"),_41=_3d.parentNode.parentNode;
-_40.innerHTML="<pre><code class=\""+_3e+"\">"+_3f+"</code></pre>";
-_41.replaceChild(_40.firstChild,_3d.parentNode);
-}else{
-_3d.className=_3e;
-_3d.innerHTML=_3f;
-}
-};
-function _42(_43,str){
-var _44=new _10(_43,str);
-return {result:_44.result,langName:_43,partialResult:_44.partialResult};
-};
-function _45(_46,_47){
-var _48=_42(_47,_7(_46));
-_3c(_46,_46.className,_48.result);
-};
-function _49(str){
-var _4a="",_4b="",_4c=2,_4d=str;
-for(var key in dh.languages){
-if(!dh.languages[key].defaultMode){
-continue;
-}
-var _4e=new _10(key,_4d),_4f=_4e.keywordCount+_4e.relevance,_50=0;
-if(!_4a||_4f>_50){
-_50=_4f;
-_4a=_4e.result;
-_4b=_4e.langName;
-}
-}
-return {result:_4a,langName:_4b};
-};
-function _51(_52){
-var _53=_49(_7(_52));
-if(_53.result){
-_3c(_52,_53.langName,_53.result);
-}
-};
-dojox.highlight.processString=function(str,_54){
-return _54?_42(_54,str):_49(str);
-};
-dojox.highlight.init=function(_55){
-_55=dojo.byId(_55);
-if(dojo.hasClass(_55,"no-highlight")){
-return;
-}
-if(!_4(_55)){
-return;
-}
-var _56=_55.className.split(/\s+/),_57=dojo.some(_56,function(_58){
-if(_58.charAt(0)!="_"&&dh.languages[_58]){
-_45(_55,_58);
-return true;
-}
-return false;
-});
-if(!_57){
-_51(_55);
-}
-};
-dh.Code=function(p,n){
-dh.init(n);
-};
 })();
-}
diff --git a/dojox/highlight/languages/_all.js b/dojox/highlight/languages/_all.js
index 6b14093..8f748b7 100644
--- a/dojox/highlight/languages/_all.js
+++ b/dojox/highlight/languages/_all.js
@@ -1,14 +1,7 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages._all"]){
-dojo._hasResource["dojox.highlight.languages._all"]=true;
 dojo.provide("dojox.highlight.languages._all");
+
+/* groups of similar languages */
 dojo.require("dojox.highlight.languages._static");
 dojo.require("dojox.highlight.languages._dynamic");
 dojo.require("dojox.highlight.languages._www");
-}
+
diff --git a/dojox/highlight/languages/_dynamic.js b/dojox/highlight/languages/_dynamic.js
index 3dbc751..7907673 100644
--- a/dojox/highlight/languages/_dynamic.js
+++ b/dojox/highlight/languages/_dynamic.js
@@ -1,12 +1,9 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages._dynamic"]){
-dojo._hasResource["dojox.highlight.languages._dynamic"]=true;
 dojo.provide("dojox.highlight.languages._dynamic");
+
+/* common scripted languages */
 dojo.require("dojox.highlight.languages.python");
-}
+// dojo.require("dojox.highlight.languages.perl");
+// dojo.require("dojox.highlight.languages.php");
+// dojo.require("dojox.highlight.languages.ruby");
+dojo.require("dojox.highlight.languages.xquery");
+dojo.require("dojox.highlight.languages.groovy");
diff --git a/dojox/highlight/languages/_static.js b/dojox/highlight/languages/_static.js
index 7bd46c5..d94420e 100644
--- a/dojox/highlight/languages/_static.js
+++ b/dojox/highlight/languages/_static.js
@@ -1,13 +1,6 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages._static"]){
-dojo._hasResource["dojox.highlight.languages._static"]=true;
 dojo.provide("dojox.highlight.languages._static");
-dojo.require("dojox.highlight.languages.cpp");
+
+/* common static languages */
+dojo.require("dojox.highlight.languages.cpp")
+dojo.require("dojox.highlight.languages.java");
 dojo.require("dojox.highlight.languages.delphi");
-}
diff --git a/dojox/highlight/languages/_www.js b/dojox/highlight/languages/_www.js
index 50aac43..631921c 100644
--- a/dojox/highlight/languages/_www.js
+++ b/dojox/highlight/languages/_www.js
@@ -1,16 +1,8 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages._www"]){
-dojo._hasResource["dojox.highlight.languages._www"]=true;
 dojo.provide("dojox.highlight.languages._www");
+
+/* common web-centric languages */
 dojo.require("dojox.highlight.languages.xml");
 dojo.require("dojox.highlight.languages.html");
 dojo.require("dojox.highlight.languages.css");
 dojo.require("dojox.highlight.languages.django");
-dojo.require("dojox.highlight.languages.javascript");
-}
+dojo.require("dojox.highlight.languages.javascript");
\ No newline at end of file
diff --git a/dojox/highlight/languages/cpp.js b/dojox/highlight/languages/cpp.js
index e82ff57..6088f14 100644
--- a/dojox/highlight/languages/cpp.js
+++ b/dojox/highlight/languages/cpp.js
@@ -1,16 +1,49 @@
-/*
-	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
-*/
+dojo.provide("dojox.highlight.languages.cpp"); 
 
-
-if(!dojo._hasResource["dojox.highlight.languages.cpp"]){
-dojo._hasResource["dojox.highlight.languages.cpp"]=true;
-dojo.provide("dojox.highlight.languages.cpp");
 dojo.require("dojox.highlight._base");
+
 (function(){
-var dh=dojox.highlight,_1=dh.constants;
-dh.languages.cpp={defaultMode:{lexems:[_1.UNDERSCORE_IDENT_RE],illegal:"</",contains:["comment","string","number","preprocessor"],keywords:{"false":1,"int":1,"float":1,"while":1,"private":1,"char":1,"catch":1,"export":1,"virtual":1,"operator":2,"sizeof":2,"dynamic_cast":2,"typedef":2,"const_cast":2,"const":1,"struct":1,"for":1,"static_cast":2,"union":1,"namespace":1,"unsigned":1,"long":1,"throw":1,"volatile":2,"static":1,"protected":1,"bool":1,"template":1,"mutable":1,"if":1,"public":1," [...]
+	var dh = dojox.highlight, dhc = dh.constants;
+	dh.languages.cpp = {
+		// summary: C++ highlight definitions
+		defaultMode: {
+			lexems: [dhc.UNDERSCORE_IDENT_RE],
+			illegal: '</',
+			contains: ['comment', 'string', 'number', 'preprocessor'],
+			keywords: {
+				'false': 1, 'int': 1, 'float': 1, 'while': 1, 'private': 1,
+				'char': 1, 'catch': 1, 'export': 1, 'virtual': 1, 
+				'operator': 2, 'sizeof': 2, 'dynamic_cast': 2, 'typedef': 2,
+				'const_cast': 2, 'const': 1, 'struct': 1, 'for': 1,
+				'static_cast': 2, 'union': 1, 'namespace': 1, 'unsigned': 1,
+				'long': 1, 'throw': 1, 'volatile': 2, 'static': 1, 
+				'protected': 1, 'bool': 1, 'template': 1, 'mutable': 1, 
+				'if': 1, 'public': 1, 'friend': 2, 'do': 1, 'return': 1,
+				'goto': 1, 'auto': 1, 'void': 2, 'enum': 1, 'else': 1, 
+				'break': 1, 'new': 1, 'extern': 1, 'using': 1, 'true': 1,
+				'class': 1, 'asm': 1, 'case': 1, 'typeid': 1, 'short': 1,
+				'reinterpret_cast': 2, 'default': 1, 'double': 1, 
+				'register': 1, 'explicit': 1, 'signed': 1, 'typename': 1,
+				'try': 1, 'this': 1, 'switch': 1, 'continue': 1, 'wchar_t': 1,
+				'inline': 1, 'delete': 1
+			}
+		},
+		modes: [
+			dhc.C_LINE_COMMENT_MODE,
+			dhc.C_BLOCK_COMMENT_MODE,
+			dhc.C_NUMBER_MODE,
+			dhc.QUOTE_STRING_MODE,
+			dhc.BACKSLASH_ESCAPE,
+			{
+				className: 'string',
+				begin: '\'', 
+				end: '[^\\\\]\'',
+				illegal: '[^\\\\][^\']'
+			},
+			{
+				className: 'preprocessor',
+				begin: '#', end: '$'
+			}
+		]
+	};
 })();
-}
diff --git a/dojox/highlight/languages/css.js b/dojox/highlight/languages/css.js
index 7c011cd..b90ee74 100644
--- a/dojox/highlight/languages/css.js
+++ b/dojox/highlight/languages/css.js
@@ -1,17 +1,92 @@
-/*
-	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
-*/
+dojo.provide("dojox.highlight.languages.css"); 
 
-
-if(!dojo._hasResource["dojox.highlight.languages.css"]){
-dojo._hasResource["dojox.highlight.languages.css"]=true;
-dojo.provide("dojox.highlight.languages.css");
 dojo.require("dojox.highlight._base");
 dojo.require("dojox.highlight.languages.html");
+
 (function(){
-var dh=dojox.highlight,_1=dh.constants,_2=dh.languages;
-_2.css={defaultMode:{contains:["id","class","attr_selector","rules","comment"],keywords:_2.html.HTML_TAGS,lexems:[_1.IDENT_RE],illegal:"="},case_insensitive:true,modes:[{className:"id",begin:"\\#[A-Za-z0-9_-]+",end:"^"},{className:"class",begin:"\\.[A-Za-z0-9_-]+",end:"^",relevance:0},{className:"attr_selector",begin:"\\[",end:"\\]",illegal:"$"},{className:"rules",begin:"{",end:"}",lexems:["[A-Za-z-]+"],keywords:{"play-during":1,"counter-reset":1,"counter-increment":1,"min-height":1,"quo [...]
+	var dh = dojox.highlight, dhc = dh.constants, dhl = dh.languages;
+	dhl.css = {
+		defaultMode: {
+			contains: ['id', 'class', 'attr_selector', 'rules', 'comment'],
+			keywords: dhl.html.HTML_TAGS,
+			lexems: [dhc.IDENT_RE],
+			illegal: '='
+		},
+		case_insensitive: true,
+		modes: [
+			{
+				className: 'id',
+				begin: '\\#[A-Za-z0-9_-]+', end: '^'
+			},
+			{
+				className: 'class',
+				begin: '\\.[A-Za-z0-9_-]+', end: '^',
+				relevance: 0
+			},
+			{
+				className: 'attr_selector',
+				begin: '\\[', end: '\\]',
+				illegal: '$'
+			},
+			{
+				className: 'rules',
+				begin: '{', end: '}',
+				lexems: ['[A-Za-z-]+'],
+				keywords: {
+					'play-during': 1, 'counter-reset': 1, 
+					'counter-increment': 1, 'min-height': 1, 'quotes': 1,
+					'border-top': 1, 'pitch': 1, 'font': 1, 'pause': 1,
+					'list-style-image': 1, 'border-width': 1, 'cue': 1,
+					'outline-width': 1, 'border-left': 1, 'elevation': 1,
+					'richness': 1, 'speech-rate': 1, 'border-bottom': 1,
+					'border-spacing': 1, 'background': 1, 'list-style-type': 1,
+					'text-align': 1, 'page-break-inside': 1, 'orphans': 1,
+					'page-break-before': 1, 'text-transform': 1, 
+					'line-height': 1, 'padding-left': 1, 'font-size': 1,
+					'right': 1, 'word-spacing': 1, 'padding-top': 1,
+					'outline-style': 1, 'bottom': 1, 'content': 1,
+					'border-right-style': 1, 'padding-right': 1,
+					'border-left-style': 1, 'voice-family': 1,
+					'background-color': 1, 'border-bottom-color': 1,
+					'outline-color': 1, 'unicode-bidi': 1, 'max-width': 1,
+					'font-family': 1, 'caption-side': 1, 
+					'border-right-width': 1, 'pause-before': 1,
+					'border-top-style': 1, 'color': 1, 'border-collapse': 1,
+					'border-bottom-width': 1, 'float': 1, 'height': 1,
+					'max-height': 1, 'margin-right': 1, 'border-top-width': 1,
+					'speak': 1, 'speak-header': 1, 'top': 1, 'cue-before': 1,
+					'min-width': 1, 'width': 1, 'font-variant': 1,
+					'border-top-color': 1, 'background-position': 1,
+					'empty-cells': 1, 'direction': 1, 'border-right': 1,
+					'visibility': 1, 'padding': 1, 'border-style': 1,
+					'background-attachment': 1, 'overflow': 1,
+					'border-bottom-style': 1, 'cursor': 1, 'margin': 1,
+					'display': 1, 'border-left-width': 1, 'letter-spacing': 1,
+					'vertical-align': 1, 'clip': 1, 'border-color': 1,
+					'list-style': 1, 'padding-bottom': 1, 'pause-after': 1,
+					'speak-numeral': 1, 'margin-left': 1, 'widows': 1,
+					'border': 1, 'font-style': 1, 'border-left-color': 1,
+					'pitch-range': 1, 'background-repeat': 1, 
+					'table-layout': 1, 'margin-bottom': 1, 
+					'speak-punctuation': 1, 'font-weight': 1,
+					'border-right-color': 1, 'page-break-after': 1, 
+					'position': 1, 'white-space': 1, 'text-indent': 1,
+					'background-image': 1, 'volume': 1, 'stress': 1, 
+					'outline': 1, 'clear': 1, 'z-index': 1, 
+					'text-decoration': 1, 'margin-top': 1, 'azimuth': 1,
+					'cue-after': 1, 'left': 1, 'list-style-position': 1
+				},
+				contains: ['comment', 'value']
+			},
+			dhc.C_BLOCK_COMMENT_MODE,
+			{
+				className: 'value',
+				begin: ':', 
+				end: ';', 
+				endsWithParent: true, 
+				excludeBegin: true, 
+				excludeEnd: true
+			}
+		]
+	};
 })();
-}
diff --git a/dojox/highlight/languages/delphi.js b/dojox/highlight/languages/delphi.js
index 8775821..c49e556 100644
--- a/dojox/highlight/languages/delphi.js
+++ b/dojox/highlight/languages/delphi.js
@@ -1,18 +1,118 @@
-/*
-	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
-*/
+dojo.provide("dojox.highlight.languages.delphi"); 
 
-
-if(!dojo._hasResource["dojox.highlight.languages.delphi"]){
-dojo._hasResource["dojox.highlight.languages.delphi"]=true;
-dojo.provide("dojox.highlight.languages.delphi");
 dojo.require("dojox.highlight._base");
-(function(){
-var _1={"and":1,"safecall":1,"cdecl":1,"then":1,"string":1,"exports":1,"library":1,"not":1,"pascal":1,"set":1,"virtual":1,"file":1,"in":1,"array":1,"label":1,"packed":1,"end.":1,"index":1,"while":1,"const":1,"raise":1,"for":1,"to":1,"implementation":1,"with":1,"except":1,"overload":1,"destructor":1,"downto":1,"finally":1,"program":1,"exit":1,"unit":1,"inherited":1,"override":1,"if":1,"type":1,"until":1,"function":1,"do":1,"begin":1,"repeat":1,"goto":1,"nil":1,"far":1,"initialization":1," [...]
-var _2={"safecall":1,"stdcall":1,"pascal":1,"stored":1,"const":1,"implementation":1,"finalization":1,"except":1,"to":1,"finally":1,"program":1,"inherited":1,"override":1,"then":1,"exports":1,"string":1,"read":1,"not":1,"mod":1,"shr":1,"try":1,"div":1,"shl":1,"set":1,"library":1,"message":1,"packed":1,"index":1,"for":1,"near":1,"overload":1,"label":1,"downto":1,"exit":1,"public":1,"goto":1,"interface":1,"asm":1,"on":1,"of":1,"constructor":1,"or":1,"private":1,"array":1,"unit":1,"raise":1, [...]
-var dh=dojox.highlight,_3=dh.constants;
-dh.languages.delphi={defaultMode:{lexems:[_3.IDENT_RE],illegal:"(\"|\\$[G-Zg-z]|\\/\\*|</)",contains:["comment","string","number","function","class"],keywords:_1},case_insensitive:true,modes:[{className:"comment",begin:"{",end:"}"},{className:"comment",begin:"\\(\\*",end:"\\*\\)",relevance:10},_3.C_LINE_COMMENT_MODE,{className:"number",begin:_3.NUMBER_RE,end:"^",relevance:0},{className:"string",begin:"'",end:"'",contains:["quote"],relevance:0},{className:"string",begin:"(#\\d+)+",end:"^" [...]
+
+(function(){ 
+	var DELPHI_KEYWORDS = {
+		'and': 1, 'safecall': 1, 'cdecl': 1, 'then': 1, 'string': 1, 
+		'exports': 1, 'library': 1, 'not': 1, 'pascal': 1, 'set': 1, 
+		'virtual': 1, 'file': 1, 'in': 1, 'array': 1, 'label': 1, 'packed': 1,
+		'end.': 1, 'index': 1, 'while': 1, 'const': 1, 'raise': 1, 'for': 1,
+		'to': 1, 'implementation': 1, 'with': 1, 'except': 1, 'overload': 1,
+		'destructor': 1, 'downto': 1, 'finally': 1, 'program': 1, 'exit': 1,
+		'unit': 1, 'inherited': 1, 'override': 1, 'if': 1, 'type': 1, 
+		'until': 1, 'function': 1, 'do': 1, 'begin': 1, 'repeat': 1, 'goto': 1,
+		'nil': 1, 'far': 1, 'initialization': 1, 'object': 1, 'else': 1, 
+		'var': 1, 'uses': 1, 'external': 1, 'resourcestring': 1, 
+		'interface': 1, 'end': 1, 'finalization': 1, 'class': 1, 'asm': 1,
+		'mod': 1, 'case': 1, 'on': 1, 'shr': 1, 'shl': 1, 'of': 1, 
+		'register': 1, 'xorwrite': 1, 'threadvar': 1, 'try': 1, 'record': 1,
+		'near': 1, 'stored': 1, 'constructor': 1, 'stdcall': 1, 'inline': 1,
+		'div': 1, 'out': 1, 'or': 1, 'procedure': 1
+	};
+	var DELPHI_CLASS_KEYWORDS = {
+		'safecall': 1, 'stdcall': 1, 'pascal': 1, 'stored': 1, 'const': 1,
+		'implementation': 1, 'finalization': 1, 'except': 1, 'to': 1,
+		'finally': 1, 'program': 1, 'inherited': 1, 'override': 1, 'then': 1,
+		'exports': 1, 'string': 1, 'read': 1, 'not': 1, 'mod': 1, 'shr': 1,
+		'try': 1, 'div': 1, 'shl': 1, 'set': 1, 'library': 1, 'message': 1,
+		'packed': 1, 'index': 1, 'for': 1, 'near': 1, 'overload': 1, 
+		'label': 1, 'downto': 1, 'exit': 1, 'public': 1, 'goto': 1,
+		'interface': 1, 'asm': 1, 'on': 1, 'of': 1, 'constructor': 1, 'or': 1,
+		'private': 1, 'array': 1, 'unit': 1, 'raise': 1, 'destructor': 1,
+		'var': 1, 'type': 1, 'until': 1, 'function': 1, 'else': 1, 
+		'external': 1, 'with': 1, 'case': 1, 'default': 1, 'record': 1,
+		'while': 1, 'protected': 1, 'property': 1, 'procedure': 1, 
+		'published': 1, 'and': 1, 'cdecl': 1, 'do': 1, 'threadvar': 1, 
+		'file': 1, 'in': 1, 'if': 1, 'end': 1, 'virtual': 1, 'write': 1, 
+		'far': 1, 'out': 1, 'begin': 1, 'repeat': 1, 'nil': 1,
+		'initialization': 1, 'object': 1, 'uses': 1, 'resourcestring': 1,
+		'class': 1, 'register': 1, 'xorwrite': 1, 'inline': 1
+	};
+
+	var dh = dojox.highlight, dhc = dh.constants;
+	dh.languages.delphi = {
+		defaultMode: {
+			lexems: [dhc.IDENT_RE],
+			illegal: '("|\\$[G-Zg-z]|\\/\\*|</)',
+			contains: ['comment', 'string', 'number', 'function', 'class'],
+			keywords: DELPHI_KEYWORDS
+		},
+		case_insensitive: true,
+		modes: [
+			{
+				className: 'comment',
+				begin: '{', end: '}'
+			},
+			{
+				className: 'comment',
+				begin: '\\(\\*', end: '\\*\\)',
+				relevance: 10
+			},
+			dhc.C_LINE_COMMENT_MODE,
+			{
+				className: 'number',
+				begin: dhc.NUMBER_RE, end: '^',
+				relevance: 0
+			},
+			{
+				className: 'string',
+				begin: '\'', end: '\'',
+				contains: ['quote'],
+				relevance: 0
+			},
+			{
+				className: 'string',
+				begin: '(#\\d+)+', end: '^'
+			},
+			{
+				className: 'quote',
+				begin: '\'\'', end: '^'
+			},
+			{
+				className: 'function',
+				begin: 'function', end: '[:;]',
+				lexems: [dhc.IDENT_RE],
+				keywords: {'function': 1},
+				contains: ['title', 'params', 'comment'],
+				relevance: 0
+			},
+			{
+				className: 'function',
+				begin: '(procedure|constructor|destructor)', end: ';',
+				lexems: [dhc.IDENT_RE],
+				keywords: {'constructor': 1, 'destructor': 1, 'procedure': 1},
+				contains: ['title', 'params', 'comment'],
+				relevance: 10
+			},
+			{
+				className: 'title',
+				begin: dhc.IDENT_RE, end: '^'
+			},
+			{
+				className: 'params',
+				begin: '\\(', end: '\\)',
+				lexems: [dhc.IDENT_RE],
+				keywords: DELPHI_KEYWORDS,
+				contains: ['string']
+			},
+			{
+				className: 'class',
+				begin: '=\\s*class', end: 'end;',
+				lexems: [dhc.IDENT_RE],
+				keywords: DELPHI_CLASS_KEYWORDS,
+				contains: ['string', 'comment', 'function']
+			}
+		]
+	};
 })();
-}
diff --git a/dojox/highlight/languages/django.js b/dojox/highlight/languages/django.js
index 3e233ef..68d676d 100644
--- a/dojox/highlight/languages/django.js
+++ b/dojox/highlight/languages/django.js
@@ -1,18 +1,93 @@
-/*
-	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
-*/
+dojo.provide("dojox.highlight.languages.django"); 
 
-
-if(!dojo._hasResource["dojox.highlight.languages.django"]){
-dojo._hasResource["dojox.highlight.languages.django"]=true;
-dojo.provide("dojox.highlight.languages.django");
 dojo.require("dojox.highlight._base");
 dojo.require("dojox.highlight.languages.xml");
 dojo.require("dojox.highlight.languages.html");
-(function(){
-var dh=dojox.highlight,_1=dh.constants,_2=dh.languages,x=_2.xml,h=_2.html;
-_2.django={defaultMode:{contains:["tag","comment","doctype","template_comment","template_tag","variable"]},case_insensitive:true,modes:[x.XML_COMMENT,h.HTML_DOCTYPE,{className:"tag",lexems:[_1.IDENT_RE],keywords:h.HTML_TAGS,begin:"<[A-Za-z/]",end:">",contains:["attribute","template_comment","template_tag","variable"]},x.XML_ATTR,h.HTML_ATTR,{className:"value",begin:"\"",end:"\"",contains:["template_comment","template_tag","variable"]},h.HTML_VALUE,{className:"template_comment",begin:"\\{ [...]
+
+(function(){ 
+	var dh = dojox.highlight, dhc = dh.constants, dhl = dh.languages, x = dhl.xml, h = dhl.html;
+	dhl.django = {
+		defaultMode: {
+			contains: ['tag', 'comment', 'doctype', 'template_comment', 'template_tag', 'variable']
+		},
+		case_insensitive: true,
+		modes: [
+			x.XML_COMMENT,
+			h.HTML_DOCTYPE,
+			{
+				className: 'tag',
+				lexems: [dhc.IDENT_RE],
+				keywords: h.HTML_TAGS,
+				begin: '<[A-Za-z/]', end: '>',
+				contains: ['attribute', 'template_comment', 'template_tag', 'variable']
+			},
+			x.XML_ATTR,
+			h.HTML_ATTR,
+			{
+				className: 'value',
+				begin: '"', end: '"',
+				contains: ['template_comment', 'template_tag', 'variable']
+			},
+			h.HTML_VALUE,
+			{
+				className: 'template_comment',
+				begin: '\\{\\%\\s*comment\\s*\\%\\}', 
+				end: '\\{\\%\\s*endcomment\\s*\\%\\}'
+			},
+			{
+				className: 'template_comment',
+				begin: '\\{#', end: '#\\}'
+			},
+			{
+				className: 'template_tag',
+				begin: '\\{\\%', end: '\\%\\}',
+				lexems: [dhc.IDENT_RE],
+				keywords: {
+					'comment': 1, 'endcomment': 1, 'load': 1,
+					'templatetag': 1, 'ifchanged': 1, 'endifchanged': 1,
+					'if': 1, 'endif': 1, 'firstof': 1, 'for': 1, 
+					'endfor': 1, 'in': 1, 'ifnotequal': 1, 
+					'endifnotequal': 1, 'widthratio': 1, 'extends': 1,
+					'include': 1, 'spaceless': 1, 'endspaceless': 1,
+					'regroup': 1, 'by': 1, 'as': 1, 'ifequal': 1,
+					'endifequal': 1, 'ssi': 1, 'now': 1, 'with': 1,
+					'cycle': 1, 'url': 1, 'filter': 1, 'endfilter': 1,
+					'debug': 1, 'block': 1, 'endblock': 1, 'else': 1
+				},
+				contains: ['filter']
+			},
+			{
+				className: 'variable',
+				begin: '\\{\\{', end: '\\}\\}',
+				contains: ['filter']
+			},
+			{
+				className: 'filter',
+				begin: '\\|[A-Za-z]+\\:?', end: '^', excludeEnd: true,
+				lexems: [dhc.IDENT_RE],
+				keywords: {
+					'truncatewords': 1, 'removetags': 1, 'linebreaksbr': 1,
+					'yesno': 1, 'get_digit': 1, 'timesince': 1, 'random': 1,
+					'striptags': 1, 'filesizeformat': 1, 'escape': 1,
+					'linebreaks': 1, 'length_is': 1, 'ljust': 1, 'rjust': 1,
+					'cut': 1, 'urlize': 1, 'fix_ampersands': 1, 'title': 1,
+					'floatformat': 1, 'capfirst': 1, 'pprint': 1,
+					'divisibleby': 1, 'add': 1, 'make_list': 1,
+					'unordered_list': 1, 'urlencode': 1, 'timeuntil': 1,
+					'urlizetrunc': 1, 'wordcount': 1, 'stringformat': 1,
+					'linenumbers': 1, 'slice': 1, 'date': 1, 'dictsort': 1,
+					'dictsortreversed': 1, 'default_if_none': 1, 
+					'pluralize': 1, 'lower': 1, 'join': 1, 'center': 1,
+					'default': 1, 'truncatewords_html': 1, 'upper': 1,
+					'length': 1, 'phone2numeric': 1, 'wordwrap': 1, 'time': 1,
+					'addslashes': 1, 'slugify': 1, 'first': 1
+				},
+				contains: ['argument']
+			},
+			{
+				className: 'argument',
+				begin: '"', end: '"'
+			}
+		]
+	};
 })();
-}
diff --git a/dojox/highlight/languages/groovy.js b/dojox/highlight/languages/groovy.js
new file mode 100644
index 0000000..c1e2027
--- /dev/null
+++ b/dojox/highlight/languages/groovy.js
@@ -0,0 +1,67 @@
+dojo.provide("dojox.highlight.languages.groovy"); 
+
+dojo.require("dojox.highlight._base");
+
+(function(){
+	var dh = dojox.highlight, dhc = dh.constants;
+	var GROOVY_KEYWORDS = {
+				'false': 1, 'int': 1, 'float': 1, 'while': 1, 'private': 1,
+				'char': 1, 'catch': 1, 'abstract': 1, 'assert': 1, 
+				'const': 1, 'byte': 1, 'for': 1, 'final': 1,
+				'finally': 1, 'implements': 1, 'import': 1, 'extends': 1,
+				'long': 1, 'throw': 1, 'instanceof': 2, 'static': 1, 
+				'protected': 1, 'boolean': 1, 'interface': 2, 'native': 1, 
+				'if': 1, 'public': 1, 'new': 1, 'do': 1, 'return': 1,
+				'goto': 1, 'package': 2, 'void': 2, 'short': 1, 'else': 1, 
+				'break': 1, 'new': 1, 'strictfp': 1, 'super': 1, 'true': 1,
+				'class': 1, 'synchronized': 1, 'case': 1, 'this': 1, 'short': 1,
+				'throws': 1, 'transient': 1, 'double': 1, 'volatile': 1, 
+				'try': 1, 'this': 1, 'switch': 1, 'continue': 1, 'def': 2
+			}
+	dh.languages.groovy = {
+		// summary: Groovy highlight definitions
+		defaultMode: {
+			lexems: [dhc.UNDERSCORE_IDENT_RE],
+			illegal: '</',
+			contains: ['comment', 'string', 'number', 'function', 'block'],
+			keywords: GROOVY_KEYWORDS
+		},
+		modes: [
+			dhc.C_LINE_COMMENT_MODE,
+			dhc.C_BLOCK_COMMENT_MODE,
+			dhc.C_NUMBER_MODE,
+ 			{
+				className: 'string',
+				begin: '\"\"\"', end: '\"\"\"',
+				contains: ['escape'],
+				relevance: 0
+			},			
+			dhc.QUOTE_STRING_MODE,
+			dhc.BACKSLASH_ESCAPE,
+ 			{
+				className: 'string',
+				begin: '\'\'\'', end: '\'\'\'',
+				contains: ['escape'],
+				relevance: 0
+			},				
+			dhc.APOS_STRING_MODE,
+			{
+				className: 'function',
+				begin: '\\(',
+				end: '\\)',
+				contains: ['comment', 'number', 'string', 'function', 'block'],
+				keywords: GROOVY_KEYWORDS
+			},		
+			{
+				lexems: [dhc.UNDERSCORE_IDENT_RE],
+				className: 'block',
+				begin: '\\{',
+				end: '\\}',
+				contains: ['comment', 'string', 'number', 'function', 'block'],
+				keywords: GROOVY_KEYWORDS
+			}					
+		],
+		//exporting constants
+		GROOVY_KEYWORDS: GROOVY_KEYWORDS
+	};
+})();
diff --git a/dojox/highlight/languages/html.js b/dojox/highlight/languages/html.js
index d78f683..ffca78e 100644
--- a/dojox/highlight/languages/html.js
+++ b/dojox/highlight/languages/html.js
@@ -1,21 +1,66 @@
-/*
-	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
-*/
+dojo.provide("dojox.highlight.languages.html"); 
 
-
-if(!dojo._hasResource["dojox.highlight.languages.html"]){
-dojo._hasResource["dojox.highlight.languages.html"]=true;
-dojo.provide("dojox.highlight.languages.html");
 dojo.require("dojox.highlight._base");
 dojo.require("dojox.highlight.languages.xml");
+
 (function(){
-var _1={"code":1,"kbd":1,"font":1,"noscript":1,"style":1,"img":1,"title":1,"menu":1,"tt":1,"tr":1,"param":1,"li":1,"tfoot":1,"th":1,"input":1,"td":1,"dl":1,"blockquote":1,"fieldset":1,"big":1,"dd":1,"abbr":1,"optgroup":1,"dt":1,"button":1,"isindex":1,"p":1,"small":1,"div":1,"dir":1,"em":1,"frame":1,"meta":1,"sub":1,"bdo":1,"label":1,"acronym":1,"sup":1,"body":1,"xml":1,"basefont":1,"base":1,"br":1,"address":1,"strong":1,"legend":1,"ol":1,"script":1,"caption":1,"s":1,"col":1,"h2":1,"h3":1 [...]
-var _2={className:"doctype",begin:"<!DOCTYPE",end:">",relevance:10};
-var _3={className:"attribute",begin:" [a-zA-Z]+",end:"^"};
-var _4={className:"value",begin:"[a-zA-Z0-9]+",end:"^"};
-var dh=dojox.highlight,_5=dh.constants,_6=dh.languages,x=_6.xml;
-_6.html={defaultMode:{contains:["tag","comment","doctype"]},case_insensitive:true,modes:[x.XML_COMMENT,_2,{className:"tag",lexems:[_5.IDENT_RE],keywords:_1,begin:"<[A-Za-z/]",end:">",contains:["attribute"],illegal:"[\\+\\.]"},x.XML_ATTR,_3,x.XML_VALUE,_4],HTML_TAGS:_1,HTML_DOCTYPE:_2,HTML_ATTR:_3,HTML_VALUE:_4};
+	var HTML_TAGS = {
+		'code': 1, 'kbd': 1, 'font': 1, 'noscript': 1, 'style': 1, 'img': 1,
+		'title': 1, 'menu': 1, 'tt': 1, 'tr': 1, 'param': 1, 'li': 1, 'tfoot': 1,
+		'th': 1, 'input': 1, 'td': 1, 'dl': 1, 'blockquote': 1, 'fieldset': 1,
+		'big': 1, 'dd': 1, 'abbr': 1, 'optgroup': 1, 'dt': 1, 'button': 1,
+		'isindex': 1, 'p': 1, 'small': 1, 'div': 1, 'dir': 1, 'em': 1, 'frame': 1,
+		'meta': 1, 'sub': 1, 'bdo': 1, 'label': 1, 'acronym': 1, 'sup': 1, 
+		'body': 1, 'xml': 1, 'basefont': 1, 'base': 1, 'br': 1, 'address': 1,
+		'strong': 1, 'legend': 1, 'ol': 1, 'script': 1, 'caption': 1, 's': 1,
+		'col': 1, 'h2': 1, 'h3': 1, 'h1': 1, 'h6': 1, 'h4': 1, 'h5': 1, 'table': 1,
+		'select': 1, 'noframes': 1, 'span': 1, 'area': 1, 'dfn': 1, 'strike': 1,
+		'cite': 1, 'thead': 1, 'head': 1, 'option': 1, 'form': 1, 'hr': 1, 
+		'var': 1, 'link': 1, 'b': 1, 'colgroup': 1, 'ul': 1, 'applet': 1, 'del': 1,
+		'iframe': 1, 'pre': 1, 'frameset': 1, 'ins': 1, 'tbody': 1, 'html': 1,
+		'samp': 1, 'map': 1, 'object': 1, 'a': 1, 'xmlns': 1, 'center': 1,
+		'textarea': 1, 'i': 1, 'q': 1, 'u': 1
+	};
+	var HTML_DOCTYPE = {
+		className: 'doctype',
+		begin: '<!DOCTYPE', end: '>',
+		relevance: 10
+	};
+	var HTML_ATTR = {
+		className: 'attribute',
+		begin: ' [a-zA-Z]+', end: '^'
+	};
+	var HTML_VALUE = {
+		className: 'value',
+		begin: '[a-zA-Z0-9]+', end: '^'
+	};
+
+	var dh = dojox.highlight, dhc = dh.constants, dhl = dh.languages, x = dhl.xml;
+	dhl.html = {
+		defaultMode: {
+			contains: ['tag', 'comment', 'doctype']
+		},
+		case_insensitive: true,
+		modes: [
+			x.XML_COMMENT,
+			HTML_DOCTYPE,
+			{
+				className: 'tag',
+				lexems: [dhc.IDENT_RE],
+				keywords: HTML_TAGS,
+				begin: '<[A-Za-z/]', end: '>',
+				contains: ['attribute'],
+				illegal: '[\\+\\.]'
+			},
+			x.XML_ATTR,
+			HTML_ATTR,
+			x.XML_VALUE,
+			HTML_VALUE
+		],
+		// exporting constants
+		HTML_TAGS: HTML_TAGS,
+		HTML_DOCTYPE: HTML_DOCTYPE,
+		HTML_ATTR: HTML_ATTR,
+		HTML_VALUE: HTML_VALUE
+	};
 })();
-}
diff --git a/dojox/highlight/languages/java.js b/dojox/highlight/languages/java.js
new file mode 100644
index 0000000..e51f37f
--- /dev/null
+++ b/dojox/highlight/languages/java.js
@@ -0,0 +1,58 @@
+dojo.provide("dojox.highlight.languages.java"); 
+
+dojo.require("dojox.highlight._base");
+
+(function(){
+	var dh = dojox.highlight, dhc = dh.constants;
+	var javakeywords = {
+				'false': 1, 'int': 1, 'float': 1, 'while': 1, 'private': 1,
+				'char': 1, 'catch': 1, 'abstract': 1, 'assert': 1, 
+				'const': 1, 'byte': 1, 'for': 1, 'final': 1,
+				'finally': 1, 'implements': 1, 'import': 1, 'extends': 1,
+				'long': 1, 'throw': 1, 'instanceof': 2, 'static': 1, 
+				'protected': 1, 'boolean': 1, 'interface': 2, 'native': 1, 
+				'if': 1, 'public': 1, 'new': 1, 'do': 1, 'return': 1,
+				'goto': 1, 'package': 2, 'void': 2, 'short': 1, 'else': 1, 
+				'break': 1, 'new': 1, 'strictfp': 1, 'super': 1, 'true': 1,
+				'class': 1, 'synchronized': 1, 'case': 1, 'this': 1, 'short': 1,
+				'throws': 1, 'transient': 1, 'double': 1, 'volatile': 1, 
+				'try': 1, 'this': 1, 'switch': 1, 'continue': 1
+			}
+	dh.languages.java = {
+		// summary: Java highlight definitions
+		defaultMode: {
+			lexems: [dhc.UNDERSCORE_IDENT_RE],
+			illegal: '</',
+			contains: ['comment', 'string', 'number', 'function','block'],
+			keywords: javakeywords
+		},
+		modes: [
+			dhc.C_LINE_COMMENT_MODE,
+			dhc.C_BLOCK_COMMENT_MODE,
+			dhc.C_NUMBER_MODE,
+			dhc.QUOTE_STRING_MODE,
+			dhc.BACKSLASH_ESCAPE,
+			{
+				className: 'string',
+				begin: '\'', 
+				end: '[^\\\\]\'',
+				illegal: '[^\\\\][^\']'
+			},
+			{
+				className: 'function',
+				begin: '\\(',
+				end: '\\)',
+				contains: ['comment', 'number', 'string', 'function', 'block'],
+				keywords: javakeywords
+			},
+			{
+				lexems: [dhc.UNDERSCORE_IDENT_RE],
+				className: 'block',
+				begin: '\\{',
+				end: '\\}',
+				contains: ['comment', 'string', 'number', 'function','block'],
+				keywords: javakeywords
+			}					
+		]
+	};
+})();
diff --git a/dojox/highlight/languages/javascript.js b/dojox/highlight/languages/javascript.js
index 59f0f45..ead742f 100644
--- a/dojox/highlight/languages/javascript.js
+++ b/dojox/highlight/languages/javascript.js
@@ -1,16 +1,51 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages.javascript"]){
-dojo._hasResource["dojox.highlight.languages.javascript"]=true;
 dojo.provide("dojox.highlight.languages.javascript");
+
 dojo.require("dojox.highlight._base");
+
 (function(){
-var dh=dojox.highlight,_1=dh.constants;
-dh.languages.javascript={defaultMode:{lexems:[_1.UNDERSCORE_IDENT_RE],contains:["string","comment","number","regexp","function"],keywords:{"keyword":{"in":1,"if":1,"for":1,"while":1,"finally":1,"var":1,"new":1,"function":1,"do":1,"return":1,"void":1,"else":1,"break":1,"catch":1,"instanceof":1,"with":1,"throw":1,"case":1,"default":1,"try":1,"this":1,"switch":1,"continue":1,"typeof":1,"delete":1},"literal":{"true":1,"false":1,"null":1}}},modes:[_1.C_LINE_COMMENT_MODE,_1.C_BLOCK_COMMENT_MOD [...]
+	var dh = dojox.highlight, dhc = dh.constants;
+	dh.languages.javascript = {
+		defaultMode: {
+			lexems: [dhc.UNDERSCORE_IDENT_RE],
+			contains: ['string', 'comment', 'number', 'regexp', 'function'],
+			keywords: {
+				'keyword': {
+					'in': 1, 'if': 1, 'for': 1, 'while': 1, 'finally': 1, 'var': 1,
+					'new': 1, 'function': 1, 'do': 1, 'return': 1, 'void': 1,
+					'else': 1, 'break': 1, 'catch': 1, 'instanceof': 1, 'with': 1,
+					'throw': 1, 'case': 1, 'default': 1, 'try': 1, 'this': 1,
+					'switch': 1, 'continue': 1, 'typeof': 1, 'delete': 1
+				},
+				'literal': {'true': 1, 'false': 1, 'null': 1}
+			}
+		},
+		modes: [
+			dhc.C_LINE_COMMENT_MODE,
+			dhc.C_BLOCK_COMMENT_MODE,
+			dhc.C_NUMBER_MODE,
+			dhc.APOS_STRING_MODE,
+			dhc.QUOTE_STRING_MODE,
+			dhc.BACKSLASH_ESCAPE,
+			{
+				className: 'regexp',
+				begin: '/.*?[^\\\\/]/[gim]*', end: '^'
+			},
+			{
+				className: 'function',
+				begin: 'function\\b', end: '{',
+				lexems: [dhc.UNDERSCORE_IDENT_RE],
+				keywords: {'function': 1},
+				contains: ['title', 'params']
+			},
+			{
+				className: 'title',
+				begin: dhc.UNDERSCORE_IDENT_RE, end: '^'
+			},
+			{
+				className: 'params',
+				begin: '\\(', end: '\\)',
+				contains: ['string', 'comment']
+			}
+		]
+	};
 })();
-}
diff --git a/dojox/highlight/languages/pygments/_html.js b/dojox/highlight/languages/pygments/_html.js
index 896993a..4e3e1ea 100644
--- a/dojox/highlight/languages/pygments/_html.js
+++ b/dojox/highlight/languages/pygments/_html.js
@@ -1,12 +1,21 @@
-/*
-	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
-*/
+dojo.provide("dojox.highlight.languages.pygments._html");
 
+// html-related constants
 
-if(!dojo._hasResource["dojox.highlight.languages.pygments._html"]){
-dojo._hasResource["dojox.highlight.languages.pygments._html"]=true;
-dojo.provide("dojox.highlight.languages.pygments._html");
-dojox.highlight.languages.pygments._html.tags={"code":1,"kbd":1,"font":1,"noscript":1,"style":1,"img":1,"title":1,"menu":1,"tt":1,"tr":1,"param":1,"li":1,"tfoot":1,"th":1,"input":1,"td":1,"dl":1,"blockquote":1,"fieldset":1,"big":1,"dd":1,"abbr":1,"optgroup":1,"dt":1,"button":1,"isindex":1,"p":1,"small":1,"div":1,"dir":1,"em":1,"frame":1,"meta":1,"sub":1,"bdo":1,"label":1,"acronym":1,"sup":1,"body":1,"xml":1,"basefont":1,"base":1,"br":1,"address":1,"strong":1,"legend":1,"ol":1,"script":1, [...]
-}
+dojox.highlight.languages.pygments._html.tags = {
+	"code": 1, "kbd": 1, "font": 1, "noscript": 1, "style": 1, "img": 1,
+	"title": 1, "menu": 1, "tt": 1, "tr": 1, "param": 1, "li": 1, "tfoot": 1,
+	"th": 1, "input": 1, "td": 1, "dl": 1, "blockquote": 1, "fieldset": 1,
+	"big": 1, "dd": 1, "abbr": 1, "optgroup": 1, "dt": 1, "button": 1,
+	"isindex": 1, "p": 1, "small": 1, "div": 1, "dir": 1, "em": 1, "frame": 1,
+	"meta": 1, "sub": 1, "bdo": 1, "label": 1, "acronym": 1, "sup": 1, 
+	"body": 1, "xml": 1, "basefont": 1, "base": 1, "br": 1, "address": 1,
+	"strong": 1, "legend": 1, "ol": 1, "script": 1, "caption": 1, "s": 1,
+	"col": 1, "h2": 1, "h3": 1, "h1": 1, "h6": 1, "h4": 1, "h5": 1, "table": 1,
+	"select": 1, "noframes": 1, "span": 1, "area": 1, "dfn": 1, "strike": 1,
+	"cite": 1, "thead": 1, "head": 1, "option": 1, "form": 1, "hr": 1, 
+	"var": 1, "link": 1, "b": 1, "colgroup": 1, "ul": 1, "applet": 1, "del": 1,
+	"iframe": 1, "pre": 1, "frameset": 1, "ins": 1, "tbody": 1, "html": 1,
+	"samp": 1, "map": 1, "object": 1, "a": 1, "xmlns": 1, "center": 1,
+	"textarea": 1, "i": 1, "q": 1, "u": 1
+};
diff --git a/dojox/highlight/languages/pygments/_www.js b/dojox/highlight/languages/pygments/_www.js
index 29fea91..c3c4dbb 100644
--- a/dojox/highlight/languages/pygments/_www.js
+++ b/dojox/highlight/languages/pygments/_www.js
@@ -1,15 +1,8 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages.pygments._www"]){
-dojo._hasResource["dojox.highlight.languages.pygments._www"]=true;
 dojo.provide("dojox.highlight.languages.pygments._www");
+
+/* common web-centric languages */
 dojo.require("dojox.highlight.languages.pygments.xml");
 dojo.require("dojox.highlight.languages.pygments.html");
 dojo.require("dojox.highlight.languages.pygments.css");
-dojo.require("dojox.highlight.languages.pygments.javascript");
-}
+//dojo.require("dojox.highlight.languages.pygments.django");
+dojo.require("dojox.highlight.languages.pygments.javascript");
\ No newline at end of file
diff --git a/dojox/highlight/languages/pygments/css.js b/dojox/highlight/languages/pygments/css.js
index ffdd8c6..b45b447 100644
--- a/dojox/highlight/languages/pygments/css.js
+++ b/dojox/highlight/languages/pygments/css.js
@@ -1,17 +1,207 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages.pygments.css"]){
-dojo._hasResource["dojox.highlight.languages.pygments.css"]=true;
 dojo.provide("dojox.highlight.languages.pygments.css");
+
 dojo.require("dojox.highlight._base");
 dojo.require("dojox.highlight.languages.pygments._html");
+
 (function(){
-var dh=dojox.highlight,_1=dh.languages;
-_1.css={defaultMode:{lexems:["\\b[a-zA-Z0-9]+\\b","\\b at media\b"],keywords:{"keyword":{"@media":1},"name tag":_1.pygments._html.tags},contains:["comment","string single","string double","punctuation","name decorator","name class","name function","_content"]},modes:[{className:"comment",begin:"/\\*",end:"\\*/",relevance:0},{className:"comment preproc",begin:"@[a-z][a-zA-Z]*",end:"^"},{className:"comment preproc",begin:"\\!important\\b",end:"^"},{className:"number",begin:"\\#[a-fA-F0-9]{3}\ [...]
+	var dh = dojox.highlight, dhl = dh.languages;
+	dhl.css = {
+		defaultMode: {
+			lexems: ["\\b[a-zA-Z0-9]+\\b", "\\b at media\b"],
+			keywords: {
+				"keyword": {
+					"@media": 1
+				},
+				"name tag": dhl.pygments._html.tags
+			},
+			contains: [
+				"comment",
+				"string single", "string double",
+				"punctuation",
+				"name decorator", "name class", "name function",
+				"_content"
+			]
+		},
+		modes: [
+			// comments
+			{
+				className: "comment",
+				begin: "/\\*", end: "\\*/",
+				relevance: 0
+			},
+			{
+				className: "comment preproc",
+				begin: "@[a-z][a-zA-Z]*", end: "^"
+			},
+			{
+				className: "comment preproc",
+				begin: "\\!important\\b", end: "^"
+			},
+
+			// numbers
+			{
+				className: "number",
+				begin: "\\#[a-fA-F0-9]{3}\\b", end: "^",
+				relevance: 0
+			},
+			{
+				className: "number",
+				begin: "\\#[a-fA-F0-9]{6}\\b", end: "^",
+				relevance: 0
+			},
+			{
+				className: "number",
+				begin: "[\\.\\-]?[0-9]*[\\.]?[0-9]+(em|px|\\%|pt|pc|in|mm|cm|ex)", end: "^",
+				relevance: 0
+			},
+			{
+				className: "number",
+				begin: "\\-?[0-9]+", end: "^",
+				relevance: 0
+			},
+
+			// strings
+			{
+				className: "string single",
+				begin: "'", end: "'",
+				illegal: "\\n",
+				relevance: 0
+			},
+			{
+				className: "string double",
+				begin: '"', 
+				end: '"',
+				illegal: "\\n",
+				relevance: 0
+			},
+			
+			// operators
+			{
+				className: "operator",
+				begin: "[~\\^\\*!%&\\[\\]\\(\\)<>\\|+=@:;,./?-]", end: "^",
+				relevance: 0
+			},
+
+			// punctuations
+			{
+				className: "punctuation",
+				begin: "[\\[\\]();]+", end: "^",
+				relevance: 0
+			},
+			
+			// names
+			{
+				className: "name decorator",
+				begin: "\\:[a-zA-Z0-9_\\-]+\\b", end: "^"
+			},
+			{
+				className: "name class",
+				begin: "\\.[a-zA-Z0-9_\\-]+\\b", end: "^"
+			},
+			{
+				className: "name function",
+				begin: "\\#[a-zA-Z0-9_\\-]+\\b", end: "^"
+			},
+			{
+				className: "_content",
+				begin: "\\{", end: "\\}",
+				lexems: ["\\b[a-zA-Z\\-]+\\b"],
+				keywords: {
+					"keyword": {
+						"azimuth": 1, "background-attachment": 1, "background-color": 1,
+						"background-image": 1, "background-position": 1, "background-repeat": 1,
+						"background": 1, "border-bottom-color": 1, "border-bottom-style": 1,
+						"border-bottom-width": 1, "border-left-color": 1, "border-left-style": 1,
+						"border-left-width": 1, "border-right": 1, "border-right-color": 1,
+						"border-right-style": 1, "border-right-width": 1, "border-top-color": 1,
+						"border-top-style": 1, "border-top-width": 1, "border-bottom": 1,
+						"border-collapse": 1, "border-left": 1, "border-width": 1, "border-color": 1,
+						"border-spacing": 1, "border-style": 1, "border-top": 1, "border": 1, "caption-side": 1,
+						"clear": 1, "clip": 1, "color": 1, "content": 1, "counter-increment": 1, "counter-reset": 1,
+						"cue-after": 1, "cue-before": 1, "cue": 1, "cursor": 1, "direction": 1, "display": 1,
+						"elevation": 1, "empty-cells": 1, "float": 1, "font-family": 1, "font-size": 1,
+						"font-size-adjust": 1, "font-stretch": 1, "font-style": 1, "font-variant": 1,
+						"font-weight": 1, "font": 1, "height": 1, "letter-spacing": 1, "line-height": 1,
+						"list-style-type": 1, "list-style-image": 1, "list-style-position": 1,
+						"list-style": 1, "margin-bottom": 1, "margin-left": 1, "margin-right": 1,
+						"margin-top": 1, "margin": 1, "marker-offset": 1, "marks": 1, "max-height": 1, "max-width": 1,
+						"min-height": 1, "min-width": 1, "opacity": 1, "orphans": 1, "outline": 1, "outline-color": 1,
+						"outline-style": 1, "outline-width": 1, "overflow": 1, "padding-bottom": 1,
+						"padding-left": 1, "padding-right": 1, "padding-top": 1, "padding": 1, "page": 1,
+						"page-break-after": 1, "page-break-before": 1, "page-break-inside": 1,
+						"pause-after": 1, "pause-before": 1, "pause": 1, "pitch": 1, "pitch-range": 1,
+						"play-during": 1, "position": 1, "quotes": 1, "richness": 1, "right": 1, "size": 1,
+						"speak-header": 1, "speak-numeral": 1, "speak-punctuation": 1, "speak": 1,
+						"speech-rate": 1, "stress": 1, "table-layout": 1, "text-align": 1, "text-decoration": 1,
+						"text-indent": 1, "text-shadow": 1, "text-transform": 1, "top": 1, "unicode-bidi": 1,
+						"vertical-align": 1, "visibility": 1, "voice-family": 1, "volume": 1, "white-space": 1,
+						"widows": 1, "width": 1, "word-spacing": 1, "z-index": 1, "bottom": 1, "left": 1,
+						"above": 1, "absolute": 1, "always": 1, "armenian": 1, "aural": 1, "auto": 1, "avoid": 1, "baseline": 1,
+						"behind": 1, "below": 1, "bidi-override": 1, "blink": 1, "block": 1, "bold": 1, "bolder": 1, "both": 1,
+						"capitalize": 1, "center-left": 1, "center-right": 1, "center": 1, "circle": 1,
+						"cjk-ideographic": 1, "close-quote": 1, "collapse": 1, "condensed": 1, "continuous": 1,
+						"crop": 1, "crosshair": 1, "cross": 1, "cursive": 1, "dashed": 1, "decimal-leading-zero": 1,
+						"decimal": 1, "default": 1, "digits": 1, "disc": 1, "dotted": 1, "double": 1, "e-resize": 1, "embed": 1,
+						"extra-condensed": 1, "extra-expanded": 1, "expanded": 1, "fantasy": 1, "far-left": 1,
+						"far-right": 1, "faster": 1, "fast": 1, "fixed": 1, "georgian": 1, "groove": 1, "hebrew": 1, "help": 1,
+						"hidden": 1, "hide": 1, "higher": 1, "high": 1, "hiragana-iroha": 1, "hiragana": 1, "icon": 1,
+						"inherit": 1, "inline-table": 1, "inline": 1, "inset": 1, "inside": 1, "invert": 1, "italic": 1,
+						"justify": 1, "katakana-iroha": 1, "katakana": 1, "landscape": 1, "larger": 1, "large": 1,
+						"left-side": 1, "leftwards": 1, "level": 1, "lighter": 1, "line-through": 1, "list-item": 1,
+						"loud": 1, "lower-alpha": 1, "lower-greek": 1, "lower-roman": 1, "lowercase": 1, "ltr": 1,
+						"lower": 1, "low": 1, "medium": 1, "message-box": 1, "middle": 1, "mix": 1, "monospace": 1,
+						"n-resize": 1, "narrower": 1, "ne-resize": 1, "no-close-quote": 1, "no-open-quote": 1,
+						"no-repeat": 1, "none": 1, "normal": 1, "nowrap": 1, "nw-resize": 1, "oblique": 1, "once": 1,
+						"open-quote": 1, "outset": 1, "outside": 1, "overline": 1, "pointer": 1, "portrait": 1, "px": 1,
+						"relative": 1, "repeat-x": 1, "repeat-y": 1, "repeat": 1, "rgb": 1, "ridge": 1, "right-side": 1,
+						"rightwards": 1, "s-resize": 1, "sans-serif": 1, "scroll": 1, "se-resize": 1,
+						"semi-condensed": 1, "semi-expanded": 1, "separate": 1, "serif": 1, "show": 1, "silent": 1,
+						"slow": 1, "slower": 1, "small-caps": 1, "small-caption": 1, "smaller": 1, "soft": 1, "solid": 1,
+						"spell-out": 1, "square": 1, "static": 1, "status-bar": 1, "super": 1, "sw-resize": 1,
+						"table-caption": 1, "table-cell": 1, "table-column": 1, "table-column-group": 1,
+						"table-footer-group": 1, "table-header-group": 1, "table-row": 1,
+						"table-row-group": 1, "text": 1, "text-bottom": 1, "text-top": 1, "thick": 1, "thin": 1,
+						"transparent": 1, "ultra-condensed": 1, "ultra-expanded": 1, "underline": 1,
+						"upper-alpha": 1, "upper-latin": 1, "upper-roman": 1, "uppercase": 1, "url": 1,
+						"visible": 1, "w-resize": 1, "wait": 1, "wider": 1, "x-fast": 1, "x-high": 1, "x-large": 1, "x-loud": 1,
+						"x-low": 1, "x-small": 1, "x-soft": 1, "xx-large": 1, "xx-small": 1, "yes": 1
+					},
+					"name builtin": {
+						"indigo": 1, "gold": 1, "firebrick": 1, "indianred": 1, "yellow": 1, "darkolivegreen": 1,
+						"darkseagreen": 1, "mediumvioletred": 1, "mediumorchid": 1, "chartreuse": 1,
+						"mediumslateblue": 1, "black": 1, "springgreen": 1, "crimson": 1, "lightsalmon": 1, "brown": 1,
+						"turquoise": 1, "olivedrab": 1, "cyan": 1, "silver": 1, "skyblue": 1, "gray": 1, "darkturquoise": 1,
+						"goldenrod": 1, "darkgreen": 1, "darkviolet": 1, "darkgray": 1, "lightpink": 1, "teal": 1,
+						"darkmagenta": 1, "lightgoldenrodyellow": 1, "lavender": 1, "yellowgreen": 1, "thistle": 1,
+						"violet": 1, "navy": 1, "orchid": 1, "blue": 1, "ghostwhite": 1, "honeydew": 1, "cornflowerblue": 1,
+						"darkblue": 1, "darkkhaki": 1, "mediumpurple": 1, "cornsilk": 1, "red": 1, "bisque": 1, "slategray": 1,
+						"darkcyan": 1, "khaki": 1, "wheat": 1, "deepskyblue": 1, "darkred": 1, "steelblue": 1, "aliceblue": 1,
+						"gainsboro": 1, "mediumturquoise": 1, "floralwhite": 1, "coral": 1, "purple": 1, "lightgrey": 1,
+						"lightcyan": 1, "darksalmon": 1, "beige": 1, "azure": 1, "lightsteelblue": 1, "oldlace": 1,
+						"greenyellow": 1, "royalblue": 1, "lightseagreen": 1, "mistyrose": 1, "sienna": 1,
+						"lightcoral": 1, "orangered": 1, "navajowhite": 1, "lime": 1, "palegreen": 1, "burlywood": 1,
+						"seashell": 1, "mediumspringgreen": 1, "fuchsia": 1, "papayawhip": 1, "blanchedalmond": 1,
+						"peru": 1, "aquamarine": 1, "white": 1, "darkslategray": 1, "ivory": 1, "dodgerblue": 1,
+						"lemonchiffon": 1, "chocolate": 1, "orange": 1, "forestgreen": 1, "slateblue": 1, "olive": 1,
+						"mintcream": 1, "antiquewhite": 1, "darkorange": 1, "cadetblue": 1, "moccasin": 1,
+						"limegreen": 1, "saddlebrown": 1, "darkslateblue": 1, "lightskyblue": 1, "deeppink": 1,
+						"plum": 1, "aqua": 1, "darkgoldenrod": 1, "maroon": 1, "sandybrown": 1, "magenta": 1, "tan": 1,
+						"rosybrown": 1, "pink": 1, "lightblue": 1, "palevioletred": 1, "mediumseagreen": 1,
+						"dimgray": 1, "powderblue": 1, "seagreen": 1, "snow": 1, "mediumblue": 1, "midnightblue": 1,
+						"paleturquoise": 1, "palegoldenrod": 1, "whitesmoke": 1, "darkorchid": 1, "salmon": 1,
+						"lightslategray": 1, "lawngreen": 1, "lightgreen": 1, "tomato": 1, "hotpink": 1,
+						"lightyellow": 1, "lavenderblush": 1, "linen": 1, "mediumaquamarine": 1, "green": 1,
+						"blueviolet": 1, "peachpuff": 1
+					}
+				},
+				contains: [
+					"comment", "comment preproc", 
+					"number",
+					"string single", "string double",
+					"punctuation",
+					"name decorator", "name class", "name function"
+				]
+			}
+		]
+	};
 })();
-}
diff --git a/dojox/highlight/languages/pygments/html.js b/dojox/highlight/languages/pygments/html.js
index 2f86574..b818206 100644
--- a/dojox/highlight/languages/pygments/html.js
+++ b/dojox/highlight/languages/pygments/html.js
@@ -1,21 +1,97 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages.pygments.html"]){
-dojo._hasResource["dojox.highlight.languages.pygments.html"]=true;
 dojo.provide("dojox.highlight.languages.pygments.html");
+
 dojo.require("dojox.highlight._base");
 dojo.require("dojox.highlight.languages.pygments._html");
+
 (function(){
-var dh=dojox.highlight,_1=dh.languages,_2=[],ht=_1.pygments._html.tags;
-for(var _3 in ht){
-_2.push(_3);
-}
-_2="\\b("+_2.join("|")+")\\b";
-_1.html={case_insensitive:true,defaultMode:{contains:["name entity","comment","comment preproc","_script","_style","_tag"]},modes:[{className:"comment",begin:"<!--",end:"-->"},{className:"comment preproc",begin:"\\<\\!\\[CDATA\\[",end:"\\]\\]\\>"},{className:"comment preproc",begin:"\\<\\!",end:"\\>"},{className:"string",begin:"'",end:"'",illegal:"\\n",relevance:0},{className:"string",begin:"\"",end:"\"",illegal:"\\n",relevance:0},{className:"name entity",begin:"\\&[a-z]+;",end:"^"},{cla [...]
+	var dh = dojox.highlight, dhl = dh.languages, tags = [],
+		ht = dhl.pygments._html.tags;
+	
+	for(var key in ht){
+		tags.push(key);
+	}
+	tags = "\\b(" + tags.join("|") + ")\\b";
+	
+	dhl.html = {
+		case_insensitive: true,
+		defaultMode: {
+			contains: [
+				"name entity",
+				"comment", "comment preproc",
+				"_script", "_style", "_tag"
+			]
+		},
+		modes: [
+			// comments
+			{
+				className: "comment",
+				begin: "<!--", end: "-->"
+			},
+			{
+				className: "comment preproc",
+				begin: "\\<\\!\\[CDATA\\[", end: "\\]\\]\\>"
+			},
+			{
+				className: "comment preproc",
+				begin: "\\<\\!", end: "\\>"
+			},
+
+			// strings
+			{
+				className: "string",
+				begin: "'", end: "'",
+				illegal: "\\n",
+				relevance: 0
+			},
+			{
+				className: "string",
+				begin: '"', 
+				end: '"',
+				illegal: "\\n",
+				relevance: 0
+			},
+			
+			// names
+			{
+				className: "name entity",
+				begin: "\\&[a-z]+;", end: "^"
+			},
+			{
+				className: "name tag",
+				begin: tags, end: "^",
+				relevance: 5
+			},
+			{
+				className: "name attribute",
+				begin: "\\b[a-z0-9_\\:\\-]+\\s*=", end: "^",
+				relevance: 0
+			},
+			
+			{
+				className: "_script",
+				begin: "\\<script\\b", end: "\\</script\\>",
+				relevance: 5
+			},
+			{
+				className: "_style",
+				begin: "\\<style\\b", end: "\\</style\\>",
+				relevance: 5
+			},
+			
+			{
+				className: "_tag",
+				begin: "\\<(?!/)", end: "\\>",
+				contains: ["name tag", "name attribute", "string", "_value"]
+			},
+			{
+				className: "_tag",
+				begin: "\\</", end: "\\>",
+				contains: ["name tag"]
+			},
+			{
+				className: "_value",
+				begin: "[^\\s\\>]+", end: "^"
+			}
+		]
+	};
 })();
-}
diff --git a/dojox/highlight/languages/pygments/javascript.js b/dojox/highlight/languages/pygments/javascript.js
index 4db65f0..5606635 100644
--- a/dojox/highlight/languages/pygments/javascript.js
+++ b/dojox/highlight/languages/pygments/javascript.js
@@ -1,16 +1,148 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages.pygments.javascript"]){
-dojo._hasResource["dojox.highlight.languages.pygments.javascript"]=true;
 dojo.provide("dojox.highlight.languages.pygments.javascript");
+
 dojo.require("dojox.highlight._base");
+
 (function(){
-var dh=dojox.highlight,_1=dh.constants;
-dh.languages.javascript={defaultMode:{lexems:["\\b[a-zA-Z]+"],keywords:{"keyword":{"for":1,"in":1,"while":1,"do":1,"break":1,"return":1,"continue":1,"if":1,"else":1,"throw":1,"try":1,"catch":1,"var":1,"with":1,"const":1,"label":1,"function":1,"new":1,"typeof":1,"instanceof":1},"keyword constant":{"true":1,"false":1,"null":1,"NaN":1,"Infinity":1,"undefined":1},"name builtin":{"Array":1,"Boolean":1,"Date":1,"Error":1,"Function":1,"Math":1,"netscape":1,"Number":1,"Object":1,"Packages":1,"Re [...]
+	var dh = dojox.highlight, dhc = dh.constants;
+	dh.languages.javascript = {
+		defaultMode: {
+			lexems: ["\\b[a-zA-Z]+"],
+			keywords: {
+				"keyword": {
+					"for": 1, "in": 1, "while": 1, "do": 1, "break": 1, "return": 1,
+					"continue": 1, "if": 1, "else": 1, "throw": 1, "try": 1,
+		            "catch": 1, "var": 1, "with": 1, "const": 1, "label": 1,
+					"function": 1, "new": 1, "typeof": 1, "instanceof": 1
+				},
+				"keyword constant": {
+					"true": 1, "false": 1, "null": 1, "NaN": 1, "Infinity": 1, "undefined": 1
+				},
+				"name builtin": {
+					"Array": 1, "Boolean": 1, "Date": 1, "Error": 1, "Function": 1, "Math": 1,
+					"netscape": 1, "Number": 1, "Object": 1, "Packages": 1, "RegExp": 1,
+					"String": 1, "sun": 1, "decodeURI": 1, "decodeURIComponent": 1, 
+					"encodeURI": 1, "encodeURIComponent": 1, "Error": 1, "eval": 1, 
+					"isFinite": 1, "isNaN": 1, "parseFloat": 1, "parseInt": 1, "document": 1,
+					"window": 1
+				},
+				"name builtin pseudo": {
+					"this": 1
+				}
+			},
+			contains: [
+				"comment single", "comment multiline", 
+				"number integer", "number oct", "number hex", "number float",
+				"string single", "string double", "string regex",
+				"operator",
+				"punctuation",
+				//"name variable",
+				"_function"
+			]
+		},
+		modes: [
+			// comments
+			{
+				className: "comment single",
+				begin: "//", end: "$",
+				relevance: 0
+			},
+			{
+				className: "comment multiline",
+				begin: "/\\*", end: "\\*/"
+			},
+
+			// numbers
+			{
+				className: "number integer",
+				begin: "0|([1-9][0-9]*)", end: "^",
+				relevance: 0
+			},
+			{
+				className: "number oct",
+				begin: "0[0-9]+", end: "^",
+				relevance: 0
+			},
+			{
+				className: "number hex",
+				begin: "0x[0-9a-fA-F]+", end: "^",
+				relevance: 0
+			},
+			{
+				className: "number float",
+				begin: "([1-9][0-9]*\\.[0-9]*([eE][\\+-]?[0-9]+)?)|(\\.[0-9]+([eE][\\+-]?[0-9]+)?)|([0-9]+[eE][\\+-]?[0-9]+)", end: "^",
+				relevance: 0
+			},
+
+			// strings
+			{
+				className: "string single",
+				begin: "'", end: "'",
+				illegal: "\\n",
+				contains: ["string escape"],
+				relevance: 0
+			},
+			{
+				className: "string double",
+				begin: '"', 
+				end: '"',
+				illegal: "\\n",
+				contains: ["string escape"],
+				relevance: 0
+			},
+			{
+				className: "string escape",
+				begin: "\\\\.", end: "^",
+				relevance: 0
+			},
+			{
+				className: "string regex",
+				begin: "/.*?[^\\\\/]/[gim]*", end: "^"
+			},
+			
+			// operators
+			{
+				className: "operator",
+				begin: "\\|\\||&&|\\+\\+|--|-=|\\+=|/=|\\*=|==|[-\\+\\*/=\\?:~\\^]", end: "^",
+				relevance: 0
+			},
+
+			// punctuations
+			{
+				className: "punctuation",
+				begin: "[{}\\(\\)\\[\\]\\.;]", end: "^",
+				relevance: 0
+			},
+			
+			// functions
+			{
+				className: "_function",
+				begin: "function\\b", end: "{",
+				lexems: [dhc.UNDERSCORE_IDENT_RE],
+				keywords: {
+					keyword: {
+						"function": 1
+					}
+				},
+				contains: ["name function", "_params"],
+				relevance: 5
+			},
+			{
+				className: "name function",
+				begin: dhc.UNDERSCORE_IDENT_RE, end: '^'
+			},
+			{
+				className: "_params",
+				begin: "\\(", end: "\\)",
+				contains: ["comment single", "comment multiline"]
+			}
+			/*
+			// names
+			{
+				className: "name variable",
+				begin: "\\b[$a-zA-Z_][$a-zA-Z0-9_]*", end: "^",
+				relevance: 0
+			}
+			*/
+		]
+	};
 })();
-}
diff --git a/dojox/highlight/languages/pygments/xml.js b/dojox/highlight/languages/pygments/xml.js
index f1adc1d..6f59660 100644
--- a/dojox/highlight/languages/pygments/xml.js
+++ b/dojox/highlight/languages/pygments/xml.js
@@ -1,14 +1,75 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages.pygments.xml"]){
-dojo._hasResource["dojox.highlight.languages.pygments.xml"]=true;
 dojo.provide("dojox.highlight.languages.pygments.xml");
+
 dojo.require("dojox.highlight._base");
-dojox.highlight.languages.pygments.xml={a:1};
-dojox.highlight.languages.xml={defaultMode:{contains:["name entity","comment","comment preproc","_tag"]},modes:[{className:"comment",begin:"<!--",end:"-->"},{className:"comment preproc",begin:"\\<\\!\\[CDATA\\[",end:"\\]\\]\\>"},{className:"comment preproc",begin:"\\<\\!",end:"\\>"},{className:"comment preproc",begin:"\\<\\?",end:"\\?\\>",relevance:5},{className:"string",begin:"'",end:"'",illegal:"\\n",relevance:0},{className:"string",begin:"\"",end:"\"",illegal:"\\n",relevance:0},{class [...]
-}
+dojox.highlight.languages.pygments.xml = {a: 1};
+dojox.highlight.languages.xml = {
+	defaultMode: {
+		contains: [
+			"name entity",
+			"comment", "comment preproc",
+			"_tag"
+		]
+	},
+	modes: [
+		// comments
+		{
+			className: "comment",
+			begin: "<!--", end: "-->"
+		},
+		{
+			className: "comment preproc",
+			begin: "\\<\\!\\[CDATA\\[", end: "\\]\\]\\>"
+		},
+		{
+			className: "comment preproc",
+			begin: "\\<\\!", end: "\\>"
+		},
+		{
+			className: "comment preproc",
+			begin: "\\<\\?", end: "\\?\\>",
+			relevance: 5
+		},
+
+		// strings
+		{
+			className: "string",
+			begin: "'", end: "'",
+			illegal: "\\n",
+			relevance: 0
+		},
+		{
+			className: "string",
+			begin: '"', 
+			end: '"',
+			illegal: "\\n",
+			relevance: 0
+		},
+		
+		// names
+		{
+			className: "name entity",
+			begin: "\\&[a-z]+;", end: "^"
+		},
+		{
+			className: "name tag",
+			begin: "\\b[a-z0-9_\\:\\-]+\\b", end: "^"
+		},
+		{
+			className: "name attribute",
+			begin: "\\b[a-z0-9_\\:\\-]+=", end: "^",
+			relevance: 0
+		},
+		
+		
+		{
+			className: "_tag",
+			begin: "\\<", end: "\\>",
+			contains: ["name tag", "name attribute", "string"]
+		},
+		{
+			className: "_tag",
+			begin: "\\</", end: "\\>",
+			contains: ["name tag"]
+		}
+	]
+};
diff --git a/dojox/highlight/languages/python.js b/dojox/highlight/languages/python.js
index cb02ff3..3b71577 100644
--- a/dojox/highlight/languages/python.js
+++ b/dojox/highlight/languages/python.js
@@ -1,16 +1,98 @@
-/*
-	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
-*/
+dojo.provide("dojox.highlight.languages.python"); 
 
-
-if(!dojo._hasResource["dojox.highlight.languages.python"]){
-dojo._hasResource["dojox.highlight.languages.python"]=true;
-dojo.provide("dojox.highlight.languages.python");
 dojo.require("dojox.highlight._base");
+
 (function(){
-var dh=dojox.highlight,_1=dh.constants;
-dh.languages.python={defaultMode:{lexems:[_1.UNDERSCORE_IDENT_RE],illegal:"(</|->)",contains:["comment","string","function","class","number","decorator"],keywords:{"and":1,"elif":1,"is":1,"global":1,"as":1,"in":1,"if":1,"from":1,"raise":1,"for":1,"except":1,"finally":1,"print":1,"import":1,"pass":1,"None":1,"return":1,"exec":1,"else":1,"break":1,"not":1,"with":1,"class":1,"assert":1,"yield":1,"try":1,"while":1,"continue":1,"del":1,"or":1,"def":1,"lambda":1}},modes:[{className:"function", [...]
+	var dh = dojox.highlight, dhc = dh.constants;
+	dh.languages.python = {
+	    // summary: Python highlight definitions 
+        defaultMode: {
+          lexems: [dhc.UNDERSCORE_IDENT_RE],
+          illegal: '(</|->)',
+          contains: ['comment', 'string', 'function', 'class', 'number', 'decorator'],
+          keywords: {'and': 1, 'elif': 1, 'is': 1, 'global': 1, 'as': 1, 'in': 1, 'if': 1, 
+		  	'from': 1, 'raise': 1, 'for': 1, 'except': 1, 'finally': 1, 'print': 1, 
+			'import': 1, 'pass': 1, 'None': 1, 'return': 1, 'exec': 1, 'else': 1, 
+			'break': 1, 'not': 1, 'with': 1, 'class': 1, 'assert': 1, 'yield': 1, 
+			'try': 1, 'while': 1, 'continue': 1, 'del': 1, 'or': 1, 'def': 1, 'lambda': 1}
+        },
+        modes: [
+          {
+            className: 'function',
+            lexems: [dhc.UNDERSCORE_IDENT_RE],
+            begin: '\\bdef ', end: ':',
+            illegal: '$',
+            keywords: {'def': 1},
+            contains: ['title', 'params'],
+            relevance: 10
+          }, 
+          {
+            className: 'class',
+            lexems: [dhc.UNDERSCORE_IDENT_RE],
+            begin: '\\bclass ', end: ':',
+            illegal: '[${]',
+            keywords: {'class': 1},
+            contains: ['title', 'params'],
+            relevance: 10
+          },
+          {
+          className: 'title',
+          begin: dhc.UNDERSCORE_IDENT_RE, end: '^'
+        },
+        {
+          className: 'params',
+          begin: '\\(', end: '\\)',
+          contains: ['string']
+        },
+        dhc.HASH_COMMENT_MODE,
+        dhc.C_NUMBER_MODE,
+        {
+          className: 'string',
+          begin: '\'\'\'', end: '\'\'\'',
+          relevance: 10
+        },
+        {
+          className: 'string',
+          begin: '"""', end: '"""',
+          relevance: 10
+        },
+        dhc.APOS_STRING_MODE,
+        dhc.QUOTE_STRING_MODE,
+        dhc.BACKSLASH_ESCAPE,
+        {
+          className: 'string',
+          begin: 'r\'', end: '\'',
+          relevance: 10
+        },
+        {
+          className: 'string',
+          begin: 'r"', end: '"',
+          relevance: 10
+        },
+        {
+          className: 'string',
+          begin: 'u\'', end: '(^|[^\\\\])\'',
+          relevance: 10
+        },
+        {
+          className: 'string',
+          begin: 'u"', end: '(^|[^\\\\])"',
+          relevance: 10
+        },
+        {
+          className: 'string',
+          begin: 'ur\'', end: '\'',
+          relevance: 10
+        },
+        {
+          className: 'string',
+          begin: 'ur"', end: '"',
+          relevance: 10
+        },
+        {
+          className: 'decorator',
+          begin: '@', end: '$'
+        }
+      ]
+    };
 })();
-}
diff --git a/dojox/highlight/languages/sql.js b/dojox/highlight/languages/sql.js
index e9f0f6e..bb942d4 100644
--- a/dojox/highlight/languages/sql.js
+++ b/dojox/highlight/languages/sql.js
@@ -1,17 +1,97 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages.sql"]){
-dojo._hasResource["dojox.highlight.languages.sql"]=true;
 dojo.provide("dojox.highlight.languages.sql");
+
 dojo.require("dojox.highlight._base");
+
 (function(){
-var _1={"all":1,"partial":1,"global":1,"month":1,"current_timestamp":1,"using":1,"go":1,"revoke":1,"smallint":1,"indicator":1,"end-exec":1,"disconnect":1,"zone":1,"with":1,"character":1,"assertion":1,"to":1,"add":1,"current_user":1,"usage":1,"input":1,"local":1,"alter":1,"match":1,"collate":1,"real":1,"then":1,"rollback":1,"get":1,"read":1,"timestamp":1,"session_user":1,"not":1,"integer":1,"bit":1,"unique":1,"day":1,"minute":1,"desc":1,"insert":1,"execute":1,"like":1,"level":1,"decimal": [...]
-var dh=dojox.highlight,_2=dh.constants;
-dh.languages.sql={case_insensitive:true,defaultMode:{lexems:[_2.IDENT_RE],contains:["string","number","comment"],keywords:{"keyword":_1,"aggregate":{"count":1,"sum":1,"min":1,"max":1,"avg":1}}},modes:[_2.C_NUMBER_MODE,_2.C_BLOCK_COMMENT_MODE,{className:"comment",begin:"--",end:"$"},{className:"string",begin:"'",end:"'",contains:["escape","squote"],relevance:0},{className:"squote",begin:"''",end:"^"},{className:"string",begin:"\"",end:"\"",contains:["escape","dquote"],relevance:0},{classN [...]
+	var SQL_KEYWORDS = {
+		'all': 1, 'partial': 1, 'global': 1, 'month': 1, 
+		'current_timestamp': 1, 'using': 1, 'go': 1, 'revoke': 1, 
+		'smallint': 1, 'indicator': 1, 'end-exec': 1, 'disconnect': 1, 
+		'zone': 1, 'with': 1, 'character': 1, 'assertion': 1, 'to': 1, 
+		'add': 1, 'current_user': 1, 'usage': 1, 'input': 1, 'local': 1,
+		'alter': 1, 'match': 1, 'collate': 1, 'real': 1, 'then': 1, 
+		'rollback': 1, 'get': 1, 'read': 1, 'timestamp': 1,	'session_user': 1,
+		'not': 1, 'integer': 1, 'bit': 1, 'unique': 1, 'day': 1, 'minute': 1,
+		'desc': 1, 'insert': 1, 'execute': 1, 'like': 1, 'level': 1, 
+		'decimal': 1, 'drop': 1, 'continue': 1, 'isolation': 1, 'found': 1,
+		'where': 1, 'constraints': 1, 'domain': 1, 'right': 1, 'national': 1,
+		'some': 1, 'module': 1, 'transaction': 1, 'relative': 1, 'second': 1,
+		'connect': 1, 'escape': 1, 'close': 1, 'system_user': 1, 'for': 1,
+		'deferred': 1, 'section': 1, 'cast': 1, 'current': 1, 'sqlstate': 1,
+		'allocate': 1, 'intersect': 1, 'deallocate': 1, 'numeric': 1, 
+		'public': 1, 'preserve': 1, 'full': 1, 'goto': 1, 'initially': 1,
+		'asc': 1, 'no': 1, 'key': 1, 'output': 1, 'collation': 1, 'group': 1,
+		'by': 1, 'union': 1, 'session': 1, 'both': 1, 'last': 1, 'language': 1,
+		'constraint': 1, 'column': 1, 'of': 1, 'space': 1, 'foreign': 1,
+		'deferrable': 1, 'prior': 1, 'connection': 1, 'unknown': 1, 
+		'action': 1, 'commit': 1, 'view': 1, 'or': 1, 'first': 1, 'into': 1,
+		'float': 1, 'year': 1, 'primary': 1, 'cascaded': 1, 'except': 1,
+		'restrict': 1, 'set': 1, 'references': 1, 'names': 1, 'table': 1,
+		'outer': 1, 'open': 1, 'select': 1, 'size': 1, 'are': 1, 'rows': 1,
+		'from': 1, 'prepare': 1, 'distinct': 1, 'leading': 1, 'create': 1,
+		'only': 1, 'next': 1, 'inner': 1, 'authorization': 1, 'schema': 1,
+		'corresponding': 1, 'option': 1, 'declare': 1, 'precision': 1,
+		'immediate': 1, 'else': 1, 'timezone_minute': 1, 'external': 1,
+		'varying': 1, 'translation': 1, 'true': 1, 'case': 1, 'exception': 1,
+		'join': 1, 'hour': 1, 'default': 1, 'double': 1, 'scroll': 1, 
+		'value': 1, 'cursor': 1, 'descriptor': 1, 'values': 1, 'dec': 1,
+		'fetch': 1, 'procedure': 1, 'delete': 1, 'and': 1, 'false': 1, 
+		'int': 1, 'is': 1, 'describe': 1, 'char': 1, 'as': 1, 'at': 1, 'in': 1,
+		'varchar': 1, 'null': 1, 'trailing': 1, 'any': 1, 'absolute': 1,
+		'current_time': 1, 'end': 1, 'grant': 1, 'privileges': 1, 'when': 1,
+		'cross': 1, 'check': 1, 'write': 1, 'current_date': 1, 'pad': 1,
+		'begin': 1, 'temporary': 1, 'exec': 1, 'time': 1, 'update': 1,
+		'catalog': 1, 'user': 1, 'sql': 1, 'date': 1, 'on': 1, 'identity': 1,
+		'timezone_hour': 1, 'natural': 1, 'whenever': 1, 'interval': 1, 
+		'work': 1, 'order': 1, 'cascade': 1, 'diagnostics': 1, 'nchar': 1,
+		'having': 1, 'left': 1
+	};
+
+	var dh = dojox.highlight, dhc = dh.constants;
+	dh.languages.sql = {
+		// summary: SQL highlight definitions
+		case_insensitive: true,
+			defaultMode: {
+				lexems: [dhc.IDENT_RE],
+				contains: ['string', 'number', 'comment'],
+				keywords: {
+					'keyword': SQL_KEYWORDS,
+					'aggregate': {'count': 1, 'sum': 1, 'min': 1, 'max': 1, 'avg': 1}
+				}
+		},
+		modes: [
+			dhc.C_NUMBER_MODE,
+			dhc.C_BLOCK_COMMENT_MODE,
+			{
+				className: 'comment',
+				begin: '--', end: '$'
+			},
+			{
+				className: 'string',
+				begin: '\'', end: '\'',
+				contains: ['escape', 'squote'],
+				relevance: 0
+			},
+			{
+				className: 'squote',
+				begin: '\'\'', end: '^'
+			},
+			{
+				className: 'string',
+				begin: '"', end: '"',
+				contains: [ 'escape', 'dquote'],
+				relevance: 0
+			},
+			{
+				className: 'dquote',
+				begin: '""', end: '^'
+			},
+			{
+				className: 'string',
+				begin: '`', end: '`',
+				contains: ['escape']
+			},
+			dhc.BACKSLASH_ESCAPE
+		]
+	};
 })();
-}
diff --git a/dojox/highlight/languages/xml.js b/dojox/highlight/languages/xml.js
index 68ed50a..c502650 100644
--- a/dojox/highlight/languages/xml.js
+++ b/dojox/highlight/languages/xml.js
@@ -1,19 +1,65 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.highlight.languages.xml"]){
-dojo._hasResource["dojox.highlight.languages.xml"]=true;
 dojo.provide("dojox.highlight.languages.xml");
+
 dojo.require("dojox.highlight._base");
+
 (function(){
-var _1={className:"comment",begin:"<!--",end:"-->"};
-var _2={className:"attribute",begin:" [a-zA-Z-]+=",end:"^",contains:["value"]};
-var _3={className:"value",begin:"\"",end:"\""};
-var dh=dojox.highlight,_4=dh.constants;
-dh.languages.xml={defaultMode:{contains:["pi","comment","cdata","tag"]},case_insensitive:true,modes:[{className:"pi",begin:"<\\?",end:"\\?>",relevance:10},_1,{className:"cdata",begin:"<\\!\\[CDATA\\[",end:"\\]\\]>"},{className:"tag",begin:"</?",end:">",contains:["title","tag_internal"],relevance:1.5},{className:"title",begin:"[A-Za-z:_][A-Za-z0-9\\._:-]+",end:"^",relevance:0},{className:"tag_internal",begin:"^",endsWithParent:true,contains:["attribute"],relevance:0,illegal:"[\\+\\.]"},_2 [...]
+	var XML_COMMENT = {
+		className: 'comment',
+		begin: '<!--', end: '-->'
+	};
+	
+	var XML_ATTR = {
+		className: 'attribute',
+		begin: ' [a-zA-Z-]+=', end: '^',
+		contains: ['value']
+	};
+	
+	var XML_VALUE = {
+		className: 'value',
+		begin: '"', end: '"'
+	};
+	
+	var dh = dojox.highlight, dhc = dh.constants;
+	dh.languages.xml = {
+		defaultMode: {
+			contains: ['pi', 'comment', 'cdata', 'tag']
+		},
+		case_insensitive: true,
+		modes: [
+			{
+				className: 'pi',
+				begin: '<\\?', end: '\\?>',
+				relevance: 10
+			},
+			XML_COMMENT,
+			{
+				className: 'cdata',
+				begin: '<\\!\\[CDATA\\[', end: '\\]\\]>'
+			},
+			{
+				className: 'tag',
+				begin: '</?', end: '>',
+				contains: ['title', 'tag_internal'],
+				relevance: 1.5
+			},
+			{
+				className: 'title',
+				begin: '[A-Za-z:_][A-Za-z0-9\\._:-]+', end: '^',
+				relevance: 0
+			},
+			{
+				className: 'tag_internal',
+				begin: '^', endsWithParent: true,
+				contains: ['attribute'],
+				relevance: 0,
+				illegal: '[\\+\\.]'
+			},
+			XML_ATTR,
+			XML_VALUE
+		],
+		// exporting constants
+		XML_COMMENT: XML_COMMENT,
+		XML_ATTR: XML_ATTR,
+		XML_VALUE: XML_VALUE
+	};
 })();
-}
diff --git a/dojox/highlight/languages/xquery.js b/dojox/highlight/languages/xquery.js
new file mode 100644
index 0000000..d17c71d
--- /dev/null
+++ b/dojox/highlight/languages/xquery.js
@@ -0,0 +1,56 @@
+dojo.provide("dojox.highlight.languages.xquery");
+
+dojo.require("dojox.highlight._base");
+
+// Very simple XQuery language file.  Would be nice
+// to eventually handle more of the enclosed expressions
+// and direct XML element construction
+(function(){
+	var XQUERY_COMMENT = {
+		className: 'comment',
+		begin: '\\(\\:', end: '\\:\\)'
+	};
+
+	var XQUERY_KEYWORDS = {
+		// From section A2.2 of the XQuery 1.0 specification
+		'ancestor': 1, 'ancestor-or-self': 1, 'and' : 1,
+		'as': 1, 'ascending': 1, 'at': 1, 'attribute': 1,
+		'base-uri': 1, 'boundary-space': 1, 'by': 1, 'case': 1,
+		'cast': 1, 'castable': 1, 'child': 1, 'collation': 1,
+		'comment': 1, 'construction': 1, 'copy-namespaces': 1,
+		'declare': 1, 'default': 1, 'descendant': 1, 'descendant-or-self': 1,
+		'descending': 1, 'div': 1, 'document': 1, 'document-node': 1,
+		'element': 1, 'else': 1, 'empty': 1, 'empty-sequence': 1,
+		'encoding': 1, 'eq': 1, 'every': 1, 'except': 1, 'external': 1,
+		'following': 1, 'following-sibling': 1, 'for': 1, 'function': 1,
+		'ge': 1, 'greatest': 1, 'gt': 1, 'idiv': 1, 'if': 1, 'import': 1,
+		'in': 1, 'inherit': 1, 'instance': 1, 'intersect': 1, 'is': 1,
+		'item': 1, 'lax': 1, 'le': 1, 'least': 1, 'let': 1, 'lt': 1,
+		'mod': 1, 'module': 1, 'namespace': 1, 'ne': 1, 'node': 1,
+		'no-inherit': 1, 'no-preserve': 1, 'of': 1, 'option': 1, 'or': 1,
+		'order': 1, 'ordered': 1, 'ordering': 1, 'parent': 1,
+		'preceding': 1, 'preceding-sibling': 1, 'preserve': 1,
+		'processing-instruction': 1, 'return': 1, 'satisfies': 1,
+		'schema': 1, 'schema-attribute': 1, 'schema-element': 1,
+		'self': 1, 'some': 1, 'stable': 1, 'strict': 1, 'strip': 1,
+		'text': 1, 'then': 1, 'to': 1, 'treat': 1, 'typeswitch': 1,
+		'union': 1, 'unordered': 1, 'validate': 1, 'variable': 1,
+		'version': 1, 'where': 1, 'xquery': 1
+	};
+
+	var dh = dojox.highlight, dhc = dh.constants;
+	dh.languages.xquery = {
+		case_insensitive: true,
+			defaultMode: {
+				lexems: [dhc.IDENT_RE],
+				contains: ['string', 'number', 'comment'],
+				keywords: {
+					'keyword': XQUERY_KEYWORDS
+				}
+		},
+		modes: [
+				XQUERY_COMMENT
+		],
+		XQUERY_COMMENT: XQUERY_COMMENT
+	};
+})();
diff --git a/dojox/highlight/resources/highlight.css b/dojox/highlight/resources/highlight.css
index 45a61a3..eddef1f 100644
--- a/dojox/highlight/resources/highlight.css
+++ b/dojox/highlight/resources/highlight.css
@@ -1,3 +1,6 @@
+/*
+You can use this file as is or as a starting point for you own styling
+*/
 
 .string,
 .function .title,
@@ -15,11 +18,13 @@
 .smalltalk .class {
 	color: #800;
 }
+
 .comment,
 .java .annotation,
 .template_comment {
 	color: #888;
 }
+
 .number,
 .regexp,
 .javascript .literal,
@@ -27,6 +32,7 @@
 .smalltalk .char {
 	color: #080;
 }
+
 .javadoc,
 .ruby .string,
 .python .decorator,
@@ -37,6 +43,7 @@
 .xml .pi {
 	color: #88F;
 }
+
 .keyword,
 .css .id,
 .phpdoc,
diff --git a/dojox/highlight/resources/pygments/autumn.css b/dojox/highlight/resources/pygments/autumn.css
index b1846f4..3deb7c4 100644
--- a/dojox/highlight/resources/pygments/autumn.css
+++ b/dojox/highlight/resources/pygments/autumn.css
@@ -1,10 +1,14 @@
+/* Pygments autumn style */
 
 code .comment {color: #aaa; font-style: italic}
 code .comment.preproc {color: #4c8317; font-style: normal}
 code .comment.special {color: #00a}
+
 code .keyword {color: #00a}
 code .keyword.type {color: #0aa}
+
 code .operator.word {color: #00a}
+
 code .name.builtin {color: #0aa}
 code .name.function {color: #0a0}
 code .name.class {color: #0a0; text-decoration: underline}
@@ -16,7 +20,9 @@ code .name.entity {color: #800; font-weight: bold}
 code .name.attribute {color: #1e90ff}
 code .name.tag {color: #1e90ff; font-weight: bold}
 code .name.decorator {color: #888}
+
 code .string {color: #a50}
 code .string.regex {color: #099}
 code .string.symbol {color: #00a}
+
 code .number {color: #099}
diff --git a/dojox/highlight/resources/pygments/borland.css b/dojox/highlight/resources/pygments/borland.css
index 85fb11f..9fb9d19 100644
--- a/dojox/highlight/resources/pygments/borland.css
+++ b/dojox/highlight/resources/pygments/borland.css
@@ -1,11 +1,17 @@
+/* Pygments borland style */
 
 code .comment {color: #080; font-style: italic}
 code .comment.preproc {color: #008080; font-style: normal}
 code .comment.special {font-weight: bold; font-style: normal}
+
 code .keyword {color: #000080; font-weight: bold}
+
 code .operator.word {font-weight: bold}
+
 code .name.attribute {color: #f00}
 code .name.tag {color: #000080; font-weight: bold}
+
 code .string {color: #00f}
 code .string.char {color: #800080}
+
 code .number {color: #00f}
diff --git a/dojox/highlight/resources/pygments/colorful.css b/dojox/highlight/resources/pygments/colorful.css
index 06de503..d63728a 100644
--- a/dojox/highlight/resources/pygments/colorful.css
+++ b/dojox/highlight/resources/pygments/colorful.css
@@ -1,12 +1,16 @@
+/* Pygments colorful style */
 
 code .comment {color: #888}
 code .comment.preproc {color: #579}
 code .comment.special {color: #c00; font-weight: bold}
+
 code .keyword {color: #080; font-weight: bold}
 code .keyword.pseudo {color: #038}
 code .keyword.type {color: #339}
+
 code .operator {color: #333}
 code .operator.word {color: #000; font-weight: bold}
+
 code .name.builtin {color: #007020}
 code .name.function {color: #06b; font-weight: bold}
 code .name.class {color: #b06; font-weight: bold}
@@ -22,6 +26,7 @@ code .name.entity {color: #800; font-weight: bold}
 code .name.attribute {color: #00c}
 code .name.tag {color: #070}
 code .name.decorator {color: #555; font-weight: bold}
+
 code .string {background-color: #fff0f0}
 code .string.char {color: #04d; background-color: transparent}
 code .string.doc {color: #d42; background-color: transparent}
@@ -30,6 +35,7 @@ code .string.escape {color: #666; font-weight: bold}
 code .string.regex {color: #000; background-color: #fff0f0}
 code .string.symbol {color: #a60; background-color: transparent}
 code .string.other {color: #d20}
+
 code .number {color: #60e}
 code .number.integer {color: #00d}
 code .number.float {color: #60e}
diff --git a/dojox/highlight/resources/pygments/default.css b/dojox/highlight/resources/pygments/default.css
index f0b5f05..9c13e30 100644
--- a/dojox/highlight/resources/pygments/default.css
+++ b/dojox/highlight/resources/pygments/default.css
@@ -1,11 +1,16 @@
+/* Pygments default style */
 
 code {background-color: #f8f8f8}
+
 code .comment {color: #408080; font-style: italic}
 code .comment.preproc {color: #bc7a00; font-style: normal}
+
 code .keyword {color: #008000; font-weight: bold}
 code .keyword.pseudo {font-weight: normal}
+
 code .operator {color: #666}
 code .operator.word {color: #a2f}
+
 code .name.builtin {color: #008000}
 code .name.function {color: #00f}
 code .name.class {color: #00f; font-weight: bold}
@@ -18,6 +23,7 @@ code .name.entity {color: #999; font-weight: bold}
 code .name.attribute {color: #7d9029}
 code .name.tag {color: #008000; font-weight: bold}
 code .name.decorator {color: #a2f}
+
 code .string {color: #ba2121}
 code .string.doc {font-style: italic}
 code .string.interpol {color: #b68; font-weight: bold}
@@ -25,4 +31,5 @@ code .string.escape {color: #b62; font-weight: bold}
 code .string.regex {color: #b68}
 code .string.symbol {color: #19177c}
 code .string.other {color: #008000}
+
 code .number {color: #666}
diff --git a/dojox/highlight/resources/pygments/emacs.css b/dojox/highlight/resources/pygments/emacs.css
index 8c815ed..ed391e1 100644
--- a/dojox/highlight/resources/pygments/emacs.css
+++ b/dojox/highlight/resources/pygments/emacs.css
@@ -1,12 +1,17 @@
+/* Pygments emacs style */
 
 code {background-color: #f8f8f8}
+
 code .comment {color: #080; font-style: italic}
 code .comment.preproc {font-style: normal}
 code .comment.special {font-style: normal; font-weight: bold}
+
 code .keyword {color: #a2f; font-weight: bold}
 code .keyword.pseudo {font-weight: normal}
+
 code .operator {color: #666}
 code .operator.word {color: #a2f; font-weight: bold}
+
 code .name.builtin {color: #a2f}
 code .name.function {color: #00a000}
 code .name.class {color: #00f}
@@ -19,6 +24,7 @@ code .name.entity {color: #999; font-weight: bold}
 code .name.attribute {color: #b44}
 code .name.tag {color: #008000; font-weight: bold}
 code .name.decorator {color: #a2f}
+
 code .string {color: #b44}
 code .string.doc {font-style: italic}
 code .string.interpol {color: #b68; font-weight: bold}
@@ -26,4 +32,5 @@ code .string.escape {color: #b62; font-weight: bold}
 code .string.regex {color: #b68}
 code .string.symbol {color: #b8860b}
 code .string.other {color: #008000}
+
 code .number {color: #666}
diff --git a/dojox/highlight/resources/pygments/friendly.css b/dojox/highlight/resources/pygments/friendly.css
index c4d392a..7a1c36f 100644
--- a/dojox/highlight/resources/pygments/friendly.css
+++ b/dojox/highlight/resources/pygments/friendly.css
@@ -1,12 +1,17 @@
+/* Pygments friendly style */
 
 code {background-color: #f8f8f8}
+
 code .comment {color: #60a0b0; font-style: italic}
 code .comment.preproc {color: #007020; font-style: normal}
 code .comment.special {background-color: #fff0f0; font-style: normal}
+
 code .keyword {color: #007020; font-weight: bold}
 code .keyword.pseudo {font-weight: normal}
+
 code .operator {color: #666}
 code .operator.word {color: #007020; font-weight: bold}
+
 code .name.builtin {color: #007020}
 code .name.function {color: #06287e}
 code .name.class {color: #0e84b5; font-weight: bold}
@@ -19,6 +24,7 @@ code .name.entity {color: #d55537; font-weight: bold}
 code .name.attribute {color: #4070a0}
 code .name.tag {color: #062873; font-weight: bold}
 code .name.decorator {color: #555; font-weight: bold}
+
 code .string {color: #4070a0}
 code .string.doc {font-style: italic}
 code .string.interpol {color: #70a0d0; font-style: italic}
@@ -26,4 +32,5 @@ code .string.escape {color: #4070a0; font-weight: bold}
 code .string.regex {color: #235388}
 code .string.symbol {color: #517918}
 code .string.other {color: #c65d09}
+
 code .number {color: #40a070}
diff --git a/dojox/highlight/resources/pygments/fruity.css b/dojox/highlight/resources/pygments/fruity.css
index 019fa02..adf0b59 100644
--- a/dojox/highlight/resources/pygments/fruity.css
+++ b/dojox/highlight/resources/pygments/fruity.css
@@ -1,14 +1,20 @@
+/* Pygments fruity style */
 
 code {background-color: #111; color: #fff}
+
 code .comment {color: #080; background-color: #0f140f; font-style: italic}
 code .comment.preproc {color: #ff0007; font-weight: bold}
+
 code .keyword {color: #fb660a; font-weight: bold}
 code .keyword.pseudo {font-weight: normal}
 code .keyword.type {color: #cdcaa9; font-weight: bold}
+
 code .name.function {color: #ff0086; font-weight: bold}
 code .name.variable {color: #fb660a}
 code .name.constant {color: #0086d2}
 code .name.attribute {color: #ff0086; font-weight: bold}
 code .name.tag {color: #fb660a; font-weight: bold}
+
 code .string {color: #0086d2}
+
 code .number {color: #0086f7; font-weight: bold}
diff --git a/dojox/highlight/resources/pygments/manni.css b/dojox/highlight/resources/pygments/manni.css
index 0cbf7e6..d9ba41a 100644
--- a/dojox/highlight/resources/pygments/manni.css
+++ b/dojox/highlight/resources/pygments/manni.css
@@ -1,13 +1,18 @@
+/* Pygments manni style */
 
 code {background-color: #f0f3f3}
+
 code .comment {color: #09f; font-style: italic}
 code .comment.preproc {color: #099; font-style: normal}
 code .comment.special {font-weight: bold}
+
 code .keyword {color: #069; font-weight: bold}
 code .keyword.pseudo {font-weight: normal}
 code .keyword.type {color: #078}
+
 code .operator {color: #555}
 code .operator.word {color: #000; font-weight: bold}
+
 code .name.builtin {color: #366}
 code .name.function {color: #c0f}
 code .name.class {color: #0a8; font-weight: bold}
@@ -20,6 +25,7 @@ code .name.entity {color: #999; font-weight: bold}
 code .name.attribute {color: #309}
 code .name.tag {color: #309; font-weight: bold}
 code .name.decorator {color: #99f}
+
 code .string {color: #c30}
 code .string.doc {font-style: italic}
 code .string.interpol {color: #a00}
@@ -27,4 +33,5 @@ code .string.escape {color: #c30; font-weight: bold}
 code .string.regex {color: #3aa}
 code .string.symbol {color: #fc3}
 code .string.other {color: #c30}
+
 code .number {color: #f60}
diff --git a/dojox/highlight/resources/pygments/murphy.css b/dojox/highlight/resources/pygments/murphy.css
index 971b505..bea43b5 100644
--- a/dojox/highlight/resources/pygments/murphy.css
+++ b/dojox/highlight/resources/pygments/murphy.css
@@ -1,12 +1,16 @@
+/* Pygments murphy style */
 
 code .comment {color: #666; font-style: italic}
 code .comment.preproc {color: #579; font-style: normal}
 code .comment.special {color: #c00; font-weight: bold}
+
 code .keyword {color: #289; font-weight: bold}
 code .keyword.pseudo {color: #08f}
 code .keyword.type {color: #66f}
+
 code .operator {color: #333}
 code .operator.word {color: #000; font-weight: bold}
+
 code .name.builtin {color: #072}
 code .name.function {color: #5ed; font-weight: bold}
 code .name.class {color: #e9e; font-weight: bold}
@@ -22,6 +26,7 @@ code .name.entity {color: #800}
 code .name.attribute {color: #007}
 code .name.tag {color: #070}
 code .name.decorator {color: #555; font-weight: bold}
+
 code .string {background-color: #e0e0ff}
 code .string.char {color: #88f; background-color: transparent}
 code .string.doc {color: #d42; background-color: transparent}
@@ -30,6 +35,7 @@ code .string.escape {color: #666; font-weight: bold}
 code .string.regex {color: #000; background-color: #e0e0ff}
 code .string.symbol {color: #fc8; background-color: transparent}
 code .string.other {color: #f88}
+
 code .number {color: #60e; font-weight: bold}
 code .number.integer {color: #66f; font-weight: bold}
 code .number.float {color: #60e; font-weight: bold}
diff --git a/dojox/highlight/resources/pygments/native.css b/dojox/highlight/resources/pygments/native.css
index 47c361d..6d3306c 100644
--- a/dojox/highlight/resources/pygments/native.css
+++ b/dojox/highlight/resources/pygments/native.css
@@ -1,11 +1,16 @@
+/* Pygments native style */
 
 code {background-color: #202020; color: #d0d0d0}
+
 code .comment {color: #999; font-style: italic}
 code .comment.preproc {color: #cd2828; font-style: normal; font-weight: bold}
 code .comment.special {color: #e50808; font-style: normal; font-weight: bold; background-color: #520000}
+
 code .keyword {color: #6ab825; font-weight: bold}
 code .keyword.pseudo {font-weight: normal}
+
 code .operator.word {color: #6ab825; font-weight: bold}
+
 code .name.builtin {color: #24909d}
 code .name.function {color: #40ffff}
 code .name.class {color: #447fcf; text-decoration: underline}
@@ -16,6 +21,8 @@ code .name.constant {color: #40ffff}
 code .name.attribute {color: #bbb}
 code .name.tag {color: #6ab825; font-weight: bold}
 code .name.decorator {color: #ffa500}
+
 code .string {color: #ed9d13}
 code .string.other {color: #ffa500}
+
 code .number {color: #3677a9}
diff --git a/dojox/highlight/resources/pygments/pastie.css b/dojox/highlight/resources/pygments/pastie.css
index d5e20e3..5b11cae 100644
--- a/dojox/highlight/resources/pygments/pastie.css
+++ b/dojox/highlight/resources/pygments/pastie.css
@@ -1,11 +1,15 @@
+/* Pygments pastie style */
 
 code .comment {color: #888}
 code .comment.preproc {color: #c00; font-weight: bold}
 code .comment.special {color: #c00; font-weight: bold; background-color: #fff0f0}
+
 code .keyword {color: #008800; font-weight: bold}
 code .keyword.pseudo {font-weight: normal}
 code .keyword.type {color: #888}
+
 code .operator.word {color: #080}
+
 code .name.builtin {color: #038}
 code .name.function {color: #06b; font-weight: bold}
 code .name.class {color: #b06; font-weight: bold}
@@ -21,10 +25,12 @@ code .name.attribute {color: #369}
 code .name.tag {color: #b06; font-weight: bold}
 code .name.decorator {color: #555}
 code .name.property {color: #369; font-weight: bold}
+
 code .string {color: #d20; background-color: #fff0f0}
 code .string.interpol {color: #33b}
 code .string.escape {color: #04d}
 code .string.regex {color: #080; background-color: #fff0f0}
 code .string.symbol {color: #a60}
 code .string.other {color: #2b2; background-color: #f0fff0}
+
 code .number {color: #00d; font-weight: bold}
diff --git a/dojox/highlight/resources/pygments/perldoc.css b/dojox/highlight/resources/pygments/perldoc.css
index e9253e6..2a56e2f 100644
--- a/dojox/highlight/resources/pygments/perldoc.css
+++ b/dojox/highlight/resources/pygments/perldoc.css
@@ -1,11 +1,16 @@
+/* Pygments perldoc style */
 
 code {background-color: #eed}
+
 code .comment {color: #228b22}
 code .comment.preproc {color: #1e889b}
 code .comment.special {color: #8b008b; font-weight: bold}
+
 code .keyword {color: #8b008b; font-weight: bold}
 code .keyword.type {color: #a7a7a7}
+
 code .operator.word {color: #8b008b}
+
 code .name.builtin {color: #658b00}
 code .name.function {color: #008b45}
 code .name.class {color: #008b45; font-weight: bold}
@@ -16,8 +21,10 @@ code .name.constant {color: #00688b}
 code .name.attribute {color: #658b00}
 code .name.tag {color: #8b008b; font-weight: bold}
 code .name.decorator {color: #707a7c}
+
 code .string {color: #cd5555}
 code .string.regex {color: #1c7e71}
 code .string.other {color: #cb6c20}
 code .string.heredoc {color: #1c7e71; font-style: italic}
+
 code .number {color: #b452cd}
diff --git a/dojox/highlight/resources/pygments/trac.css b/dojox/highlight/resources/pygments/trac.css
index 2085719..127b1fb 100644
--- a/dojox/highlight/resources/pygments/trac.css
+++ b/dojox/highlight/resources/pygments/trac.css
@@ -1,10 +1,14 @@
+/* Pygments trac style */
 
 code .comment {color: #998; font-style: italic}
 code .comment.preproc {color: #999; font-style: normal; font-weight: bold}
 code .comment.special {color: #999; font-weight: bold}
+
 code .keyword {font-weight: bold}
 code .keyword.type {color: #458}
+
 code .operator {font-weight: bold}
+
 code .name.builtin {color: #999}
 code .name.function {color: #900; font-weight: bold}
 code .name.class {color: #458; font-weight: bold}
@@ -15,6 +19,8 @@ code .name.constant {color: #008080}
 code .name.entity {color: #800080}
 code .name.attribute {color: #008080}
 code .name.tag {color: #000080}
+
 code .string {color: #b84}
 code .string.regex {color: #808000}
+
 code .number {color: #099}
diff --git a/dojox/highlight/tests/highlight.js b/dojox/highlight/tests/highlight.js
new file mode 100644
index 0000000..1fc000f
--- /dev/null
+++ b/dojox/highlight/tests/highlight.js
@@ -0,0 +1,26 @@
+dojo.provide("dojox.highlight.tests.highlight");
+
+dojo.require("dojox.highlight");
+dojo.require("dojox.highlight.languages._all");
+
+doh.register("dojox.highlight.tests.highlight", [
+	function test_validjavascript(){
+		//summary: Test a valid javascript block is highlighted correctly
+		var unformatted = "console.debug('hello'); /*Hi*/";
+		var expected = "console.debug(<span class=\"string\">'hello'</span>); <span class=\"comment\">/*Hi*/</span>";
+		var result = dojox.highlight.processString(unformatted, "javascript");
+		doh.assertEqual(expected, result.result);
+		doh.assertTrue(!result.partialResult);
+		doh.assertEqual("javascript", result.langName);
+	},
+	function test_invalidjavascript(){
+		//summary: Test an invalid javascript block with partial result
+		var unformatted = "console.debug('hello);\n /*Hi*/";
+		//                               ^_ unmatched quote
+		var expected = "console.debug(<span class=\"string\">";
+		var result = dojox.highlight.processString(unformatted, "javascript");
+		doh.assertEqual(unformatted, result.result);
+		doh.assertEqual(expected, result.partialResult);
+		doh.assertEqual("javascript", result.langName);		
+	}
+	]);
\ No newline at end of file
diff --git a/dojox/highlight/tests/module.js b/dojox/highlight/tests/module.js
new file mode 100644
index 0000000..a55dc05
--- /dev/null
+++ b/dojox/highlight/tests/module.js
@@ -0,0 +1,9 @@
+dojo.provide("dojox.highlight.tests.module");
+//This file loads in all the test definitions.  
+
+try{
+	//Load in the highlight module test.
+	dojo.require("dojox.highlight.tests.highlight");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/highlight/tests/runTests.html b/dojox/highlight/tests/runTests.html
new file mode 100644
index 0000000..1353b48
--- /dev/null
+++ b/dojox/highlight/tests/runTests.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+  <head>
+    <title>Highlight Unit Test Runner</title>
+    <meta http-equiv="REFRESH"         
+content="0;url=../../../util/doh/runner.html?testModule=dojox.highlight.tests.module">
+  </head>
+  <body>
+      Redirecting to D.O.H runner.
+  </body>
+</html>
diff --git a/dojox/highlight/tests/test_highlight.html b/dojox/highlight/tests/test_highlight.html
new file mode 100644
index 0000000..06a03d5
--- /dev/null
+++ b/dojox/highlight/tests/test_highlight.html
@@ -0,0 +1,467 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	
+	<title>dojox.highlight - syntax highlighting | The Dojo Toolkit</title>
+
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		/* a sample set of definitions to use as a foundation to color your code */
+		@import "../resources/highlight.css";
+
+		/* additional styling for this test case */
+		pre code[class]:after {
+		  content: 'highlight: ' attr(class);
+		  display: block; text-align: right;
+		  font-size: smaller;
+		  color: #CCC; background: white;
+		  border-top: solid 1px;
+		  padding-top: 0.5em;
+		}
+		
+		pre code {
+		  display: block;
+		}
+		
+		code {
+		  background: #F0F0F0;
+		}
+		
+		pre code, 
+		.ruby .subst {
+		  color: black;
+		}
+	</style>
+
+	<script type="text/javascript" djConfig="parseOnLoad: true, isDebug: true" src="../../../dojo/dojo.js"></script>
+	<script type="text/javascript" src="../_base.js"></script>
+
+	<script type="text/javascript">
+		// initHighlightOnLoad is deprecated.
+		// if parseOnLoad==true, the onLoad init stuff is run.
+		// if parseOnLoad==false, you can call dojox.highlight.init(domNode)
+		// 
+		// utilizing the dojo build system, the dojox.highlight engine
+		// will "do it's best" based on the language maps available
+		// at the time of construction.
+		//
+		dojo.require("dojox.highlight");
+
+		// several layer-like files have been provided grouping
+		// similar langauges, and a catch all language module
+		// dojox.highlight.languages._all is available for "best results"
+
+		// we need some language definitions:		
+		dojo.require("dojox.highlight.languages._all");
+		//dojo.require("dojox.highlight.languages._static");
+		//dojo.require("dojox.highlight.languages._dynamic");
+		//dojo.require("dojox.highlight.languages._www");
+
+		var lazyCode = function(){
+			
+			dojo.query("code").forEach(dojox.highlight.init);
+			
+			dojo.xhrGet({
+				url: "../../../dojo/_base.js",
+				load: function(data){
+					var n = dojo.byId("foobar"),
+						c = document.createElement('div'),
+						e = n.parentNode.parentNode;
+					c.innerHTML = '<pre><code class="javascript">' + data.replace(/\</gi,"<") + '</code></pre>';
+					e.replaceChild(c.firstChild, n.parentNode);
+					dojo.query("pre > code", e).forEach(dojox.highlight.init);
+				}
+			});
+		};	
+		dojo.addOnLoad(lazyCode); 
+
+	</script>
+</head>
+<body>
+
+	<h1 class="testTitle">dojox.highlight</h1>
+
+	<p>client-side syntax highlighting for a number of languages.</p>
+
+	<p><em>NOTE:</em> All languages listed here have working language definitions, though
+	not all exist in the release or dojo subversion. The missing packs are not publically available.
+	<span style="display:none">based on</span>
+	</p>
+
+	<h2>Examples:</h2>
+
+	<p>Some Python code:</p>
+
+<pre><code>@requires_authorization
+def somefunc(param1, param2):
+  '''A docstring'''
+  if param1 > param2: # interesting
+    print 'Gre\'ater'
+    print ''
+  return param2 - param1 + 1
+  
+class SomeClass:<br>    pass
+</code></pre>
+
+	<p>A chunk of PHP: </p>
+
+<pre><code class="php">
+$opAr = array (    "-a|--append", // a or append toggle, nothing extra
+        "-i|--input:", // i or input with next input being needed
+        "-l|--list:",           // l with input needed
+		//"--foo",     // broken
+        "-f:",           // f with no input
+        "--wot:"      // wot with input, no short
+        );
+
+
+$op = bgetop($opAr);
+if (is_array($op)) { print_r($op); }
+
+/* here is the code: */
+
+function bgetop($opAr=array(),$unknown=true) {
+
+$argv = $_SERVER['argv'];
+$argc = $_SERVER['argc'];
+$argPos = 1; // zero is program running
+
+// foreach arg
+while ($argPos<$argc) {
+    $arg = $argv[$argPos];
+    if ($arg{0}=="-") {
+        if ($arg{1}=="-") {
+        $var = substr($arg,2,strlen($arg));
+        } else { $var = $arg{1}; }
+        foreach ($opAr as $opk => $opv) {
+            if (!isset($return[$var])) {
+            if (strpos($opv,$arg) !== FALSE) {
+                // this is where the -f -foo fix needs to be,
+                // the partial string exists in this record,
+                // but we need to determine if it's accurate
+                // somehow (i'm thinking: eregi?)
+                if ($accurate=1) {
+                    // we foudn the key
+                    if (strpos($opv,':') !== FALSE) {
+                        // next value is the one to use,
+                        // then skip it in the parser.
+                        if (isset($argv[$argPos+1])) {
+                            $return[$var] = $argv[++$argPos];
+                            } else {
+                            $return[$var] = FALSE;     
+                            }
+                        } else {
+                        // just set the toggle
+                        $return[$var] = TRUE;
+                        }
+                    // don't check this opAr value again
+                    unset($opAr[$opk]);
+                    }
+                } // if accurate
+            } // !isset already
+            } // foreach opAr    
+    } else { // we weren't expecting a non-hyphened argument, possibly just a filename, or whatnot
+        if ($unknown) { $return['unknown'][]=$arg; }
+    }
+    $argPos++;
+} // while argPos < argc
+
+if (is_array($return)) {
+return $return;
+} else { return 0; }
+
+} // end function bgetop
+
+</code></pre>
+
+	<p>A custom XML document:</p>
+
+<pre><code><?xml version="1.0"?>
+<response value="ok">
+  <text>Ok</text>
+  <comment/>
+  <ns:description><![CDATA[ 
+  CDATA is <not> magical. 
+  ]]></ns:description>
+</response>
+</code></pre>
+
+	<p>Some HTML code:</p>
+
+<pre><code><head>
+  <title>Title</title>
+<body>
+  <p class="something">Something</p>
+  <p class=something>Something</p>
+  <!-- comment -->
+  <p class>Something</p>
+  <p class="something" title="p">Something</p>
+</body>
+</code></pre>
+
+	<p>HTML with Django templates:</p>
+
+<pre><code>{% if articles|length %}
+{% for article in articles %}
+
+{# Striped table #}
+<tr class="{% cycle odd,even %}">
+  <td>{{ article|default:"Hi... "|escape }}</td>
+  <td>{{ article.date|date:"d.m.Y" }}</td>
+</tr>
+  
+{% endfor %}
+{% endif %}
+
+{% comment %}
+Comments may be long and
+multiline.
+{% endcomment %}
+</code></pre>
+
+	<p>Some CSS code:</p>
+
+<pre><code>body, 
+html {
+  font: Tahoma, Arial, san-serif;
+}
+
+#content {
+  width: 100%; /* css comment */
+  height: 100%
+}
+
+p[lang=ru] {
+  color: red;
+}
+</code></pre>
+
+	<p>Explicit Python highlight:</p>
+
+<pre><code class="python">for x in [1, 2, 3]:
+  count(x)
+</code></pre>
+
+	<p>Disabled highlighting:</p>
+
+<pre><code class="no-highlight"><div id="contents">
+  <p>Hello, World!
+</div>
+</code></pre>
+
+	<p>Normal dojo-looking code</p>
+
+<pre><code>
+dojo.provide("some.object");
+dojo.declare("some.object",null,{
+	param: "value",
+	_myMethod: function(/* Event */e){
+		this.inherited(arguments);
+	},
+	// comments
+	_another: function(){
+		dojo.addClass("foo","hovered");
+	}
+});
+dojo.addOnLoad(function(){
+	//
+	// comments with <HTML> inline
+	var d = dojo;
+	d.mixin(d,{
+		foo: function(e){
+			d.bar(e);
+		},
+		bar: function(e){
+			alert(e);
+		}
+	});
+});
+</code></pre>
+
+	<p>Lazy, xhr'd code:</p>
+
+<pre><code id="foobar"></code></pre>
+
+<hr>
+
+	<p>Text with inlined JavaScript code: <code class="javascript">dojo.forEach(a, function(x){ console.log(x); });</code> — that was the inlined sample.</p>
+
+<hr>
+
+	<p>Markuped code (python), no language was specified:</p>
+
+<pre><code dojoType="dojo.highlight.Code">@requires_authorization
+def somefunc(param1, param2):
+  '''A docstring'''
+  if param1 > param2: # interesting
+    print 'Gre\'ater'
+    print ''
+  return param2 - param1 + 1
+  
+class SomeClass:<br>    pass
+</code></pre>
+
+	<p>Markuped code, "python" was specified:</p>
+
+<pre><code dojoType="dojo.highlight.Code" class="python">
+ at requires_authorization
+def somefunc(param1, param2):
+  '''A docstring'''
+  if param1 > param2: # interesting
+    print 'Gre\'ater'
+    print ''
+  return param2 - param1 + 1
+  
+class SomeClass:<br>    pass
+</code></pre>
+
+	<p>Some XQuery code:</p>
+
+<pre><code class="xquery">
+declare variable $my:entityName as xs:string external;
+
+declare variable $databaseURI := concat('jdbc://getCreditDefaultSwapsByEntityName?cd%&', $my:entityName); 
+declare variable $creditDefaultSwaps := collection($databaseURI);
+
+(: This is a comment :)
+
+(: This is a multi-line
+comment :)
+declare function local:equityRows($root) {
+	for $equity in $root//equity
+	let $referenceEntity := $creditDefaultSwaps//fpml:referenceEntity
+	where $equity/name = $referenceEntity/fpml:entityName
+	return
+		<tr xmlns="http://www.w3.org/1999/xhtml">
+			<td>{ $equity/*:symbol/text() }</td>
+			<td>{ $equity/*:name/text() }</td>
+			<td>{ $equity/*:high/text() }</td>
+			<td>{ $equity/*:currency/text() }</td>
+		</tr>
+};
+
+<table border="1">
+<tr>
+	<th>Ticker Symbol</th>
+	<th>Company Name</th>
+	<th>High</th>
+	<th>Currency</th>
+</tr>
+{ local:equityRows(/) }
+</table>
+</code></pre>
+
+	<p>Some Java code:</p>
+
+<pre><code class="java">
+import java.io.*;
+public final class DOHRobot extends Applet{
+	// The last reported mouse x,y.
+	// If this is different from the real one, something's up.
+	private int lastMouseX;
+	private int lastMouseY;
+	JSObject dohrobot = null;
+
+	final private class onvisible extends ComponentAdapter{
+		public void componentShown(ComponentEvent evt){
+			/* sets the security manager to fix a bug *
+			 * in liveconnect in Safari on Mac        */
+			if(key != -1){ return; }
+			Thread thread = new Thread(){
+				public void run(){
+					window = (JSObject) JSObject.getWindow(applet());   
+					AccessController.doPrivileged(new PrivilegedAction(){
+						public Object run(){
+							log("> init Robot");
+							try{
+								SecurityManager oldsecurity = System.getSecurityManager();
+								boolean needsSecurityManager = applet().getParameter("needsSecurityManager").equals("true");
+								log("Socket connections managed? "+needsSecurityManager);
+								try{
+									securitymanager.checkTopLevelWindow(null);
+									// xdomain
+									if(charMap == null){
+										if(!confirm("DOH has detected that the current Web page is attempting to access DOH,\n"+
+													"but belongs to a different domain than the one you agreed to let DOH automate.")){
+											return null;
+										}
+									}
+								}catch(Exception e){
+									e.printStackTrace();
+									securitymanager = new RobotSecurityManager(needsSecurityManager,
+											oldsecurity);
+									System.setSecurityManager(securitymanager);
+								}
+								// instantiate the Robot
+								robot = new Robot();
+								robot.setAutoWaitForIdle(true);
+							}catch(Exception e){
+								key = -2;
+								e.printStackTrace();
+							}
+							return null;
+						}
+					});
+					if(key == -2){
+						// applet not trusted
+						// start the test without it
+						window.eval("doh.robot._appletDead=true;doh.run();");
+					}
+				}
+			};
+			thread.start();
+		}
+	}
+}
+</code></pre>
+
+	<p>A Groovy fragment:</p>
+
+<pre><code class="groovy">
+/*
+* A comment test block
+* 
+* ?debug
+* ?nodebug
+* 
+*/
+
+def settings = [
+	debug: false,
+	compress: true,
+	console: false,
+	ping: false,
+	testing: false,
+	profile: false
+];
+
+// function calls
+init(settings);
+render(settings);
+
+def render(settings) {
+	request.header = settings;
+	render();
+}
+
+def init(settings) {
+
+	// Default parameter handling.
+	settings.each { key, value ->
+		def onkey = "${key}";
+		def offkey = "no${key}";
+		if (foo("/request/params/${onkey}",null) != null) {
+			settings[key] = true;
+		}
+		else if (foo("/request/params/${offkey}",null) != null) {
+			settings[key] = false;
+		}
+	}
+
+	return settings;
+}
+</code></pre>
+
+</body></html>
diff --git a/dojox/highlight/tests/test_pygments.html b/dojox/highlight/tests/test_pygments.html
new file mode 100644
index 0000000..447b894
--- /dev/null
+++ b/dojox/highlight/tests/test_pygments.html
@@ -0,0 +1,146 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	
+	<title>dojox.highlight.pygments - syntax highlighting | The Dojo Toolkit</title>
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		/* CSS rules for debugging */
+		
+		pre code[class]:after {
+		  content: 'highlight: ' attr(class);
+		  display: block; text-align: right;
+		  font-size: smaller;
+		  color: #CCC; background: white;
+		  border-top: solid 1px;
+		  padding-top: 0.5em;
+		}
+		
+		pre code {
+		  display: block;
+		}
+	</style>
+	
+	<!-- a sample set of definitions to use as a foundation to color your code -->
+	<link rel="stylesheet" type="text/css" href="../resources/pygments/default.css">
+	
+	<script type="text/javascript" djConfig="parseOnLoad: true, isDebug: true" src="../../../dojo/dojo.js"></script>
+	<!--
+	<script type="text/javascript" src="../_base.js"></script>
+	<script type="text/javascript" src="../languages/pygments/xml.js"></script>
+	<script type="text/javascript" src="../languages/pygments/html.js"></script>
+	<script type="text/javascript" src="../languages/pygments/css.js"></script>
+	<script type="text/javascript" src="../languages/pygments/javascript.js"></script>
+	-->
+	
+	<script type="text/javascript">
+		dojo.require("dojox.highlight");
+		/*
+		dojo.require("dojox.highlight.languages.pygments.xml");
+		dojo.require("dojox.highlight.languages.pygments.html");
+		dojo.require("dojox.highlight.languages.pygments.css");
+		dojo.require("dojox.highlight.languages.pygments.javascript");
+		*/
+		dojo.require("dojox.highlight.languages.pygments._www");
+		dojo.require("dojo.parser");
+		
+		dojo.addOnLoad(function(){
+			var sel = dojo.byId("theme"),
+				sty = dojo.query("link[rel='stylesheet']", document.head)[0];
+			dojo.query("option[value='default']", sel)[0].selected = "selected";
+			dojo.connect(sel, "onchange", function(){
+				sty.href = "../resources/pygments/" + sel.value + ".css";
+			});
+		});
+	</script>
+</head>
+<body>
+
+	<h1>Test Pygments-based highlighting</h1>
+
+	<p>Current theme from the pygments set: 
+		<select id="theme">
+			<option value="autumn">Autumn</option>
+			<option value="borland">Borland</option>
+			<option value="colorful">Colorful</option>
+			<option value="default">Default</option>
+			<option value="emacs">Emacs</option>
+			<option value="friendly">Friendly</option>
+			<option value="fruity">Fruity</option>
+			<option value="manni">Manni</option>
+			<option value="murphy">Murphy</option>
+			<option value="native">Native</option>
+			<option value="pastie">Pastie</option>
+			<option value="perldoc">Perldoc</option>
+			<option value="trac">Trac</option>
+		</select>
+	</p>
+	
+	<p>Javascript:</p>
+
+<pre><code dojoType="dojox.highlight.Code">function initHighlight(block) {
+  if (block.className.search(/\bno\-highlight\b/) != -1)
+    return false;
+  try {
+    blockText(block);
+  } catch (e) {
+    if (e == 'Complex markup')
+      return;
+  }//try
+  var classes = block.className.split(/\s+/);
+  for (var i = 0; i < classes.length; i++) {
+    if (LANGUAGES[classes[i]]) {
+      highlightLanguage(block, classes[i]);
+      return;
+    }//if
+  }//for
+  highlightAuto(block);
+}//initHighlight
+</code></pre>
+
+	<p>Some CSS code:</p>
+
+<pre><code dojoType="dojox.highlight.Code">body, 
+html {
+  font: Tahoma, Arial, sans-serif;
+}
+
+#content {
+  width: 100%; /* test comment */
+  height: 100%
+}
+
+p[lang=ru] {
+  color: red;
+}
+</code></pre>
+
+	<p>Some HTML code:</p>
+
+<pre><code dojoType="dojox.highlight.Code"><head>
+  <title>Title</title>
+<body>
+  <p class="something">Something</p>
+  <p class=something>Something</p>
+  <!-- comment -->
+  <p class>Something</p>
+  <p class="something" title="p">Something</p>
+</body>
+</code></pre>
+
+<p>A custom XML document:</p>
+
+<pre><code dojoType="dojox.highlight.Code"><?xml version="1.0"?>
+<response value="ok">
+  <text>Ok</text>
+  <comment/>
+  <ns:description><![CDATA[ 
+  CDATA is <not> magical. 
+  ]]></ns:description>
+</response>
+</code></pre>
+
+</body>
+</html>
diff --git a/dojox/html.js b/dojox/html.js
index 0e2c7d3..ace60eb 100644
--- a/dojox/html.js
+++ b/dojox/html.js
@@ -1,12 +1,4 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.html"]){
-dojo._hasResource["dojox.html"]=true;
 dojo.provide("dojox.html");
+
 dojo.require("dojox.html._base");
-}
+
diff --git a/dojox/html/_base.js b/dojox/html/_base.js
index a7f7e6c..3b895e1 100644
--- a/dojox/html/_base.js
+++ b/dojox/html/_base.js
@@ -1,192 +1,375 @@
 /*
-	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
-*/
+	Status: dont know where this will all live exactly
+	Need to pull in the implementation of the various helper methods
+	Some can be static method, others maybe methods of the ContentSetter (?)
+	
+	Gut the ContentPane, replace its _setContent with our own call to dojox.html.set()
+	
 
+*/
 
-if(!dojo._hasResource["dojox.html._base"]){
-dojo._hasResource["dojox.html._base"]=true;
 dojo.provide("dojox.html._base");
-dojo.require("dojo.html");
-(function(){
-if(dojo.isIE){
-var _1=/(AlphaImageLoader\([^)]*?src=(['"]))(?![a-z]+:|\/)([^\r\n;}]+?)(\2[^)]*\)\s*[;}]?)/g;
-}
-var _2=/(?:(?:@import\s*(['"])(?![a-z]+:|\/)([^\r\n;{]+?)\1)|url\(\s*(['"]?)(?![a-z]+:|\/)([^\r\n;]+?)\3\s*\))([a-z, \s]*[;}]?)/g;
-var _3=dojox.html._adjustCssPaths=function(_4,_5){
-if(!_5||!_4){
-return;
-}
-if(_1){
-_5=_5.replace(_1,function(_6,_7,_8,_9,_a){
-return _7+(new dojo._Url(_4,"./"+_9).toString())+_a;
-});
-}
-return _5.replace(_2,function(_b,_c,_d,_e,_f,_10){
-if(_d){
-return "@import \""+(new dojo._Url(_4,"./"+_d).toString())+"\""+_10;
-}else{
-return "url("+(new dojo._Url(_4,"./"+_f).toString())+")"+_10;
-}
-});
-};
-var _11=/(<[a-z][a-z0-9]*\s[^>]*)(?:(href|src)=(['"]?)([^>]*?)\3|style=(['"]?)([^>]*?)\5)([^>]*>)/gi;
-var _12=dojox.html._adjustHtmlPaths=function(_13,_14){
-var url=_13||"./";
-return _14.replace(_11,function(tag,_15,_16,_17,_18,_19,_1a,end){
-return _15+(_16?(_16+"="+_17+(new dojo._Url(url,_18).toString())+_17):("style="+_19+_3(url,_1a)+_19))+end;
-});
-};
-var _1b=dojox.html._snarfStyles=function(_1c,_1d,_1e){
-_1e.attributes=[];
-return _1d.replace(/(?:<style([^>]*)>([\s\S]*?)<\/style>|<link\s+(?=[^>]*rel=['"]?stylesheet)([^>]*?href=(['"])([^>]*?)\4[^>\/]*)\/?>)/gi,function(_1f,_20,_21,_22,_23,_24){
-var i,_25=(_20||_22||"").replace(/^\s*([\s\S]*?)\s*$/i,"$1");
-if(_21){
-i=_1e.push(_1c?_3(_1c,_21):_21);
-}else{
-i=_1e.push("@import \""+_24+"\";");
-_25=_25.replace(/\s*(?:rel|href)=(['"])?[^\s]*\1\s*/gi,"");
-}
-if(_25){
-_25=_25.split(/\s+/);
-var _26={},tmp;
-for(var j=0,e=_25.length;j<e;j++){
-tmp=_25[j].split("=");
-_26[tmp[0]]=tmp[1].replace(/^\s*['"]?([\s\S]*?)['"]?\s*$/,"$1");
-}
-_1e.attributes[i-1]=_26;
-}
-return "";
-});
-};
-var _27=dojox.html._snarfScripts=function(_28,_29){
-_29.code="";
-_28=_28.replace(/<[!][-][-](.|\s){5,}?[-][-]>/g,function(_2a){
-return _2a.replace(/<(\/?)script\b/ig,"<$1Script");
-});
-function _2b(src){
-if(_29.downloadRemote){
-src=src.replace(/&([a-z0-9#]+);/g,function(m,_2c){
-switch(_2c){
-case "amp":
-return "&";
-case "gt":
-return ">";
-case "lt":
-return "<";
-default:
-return _2c.charAt(0)=="#"?String.fromCharCode(_2c.substring(1)):"&"+_2c+";";
-}
-});
-dojo.xhrGet({url:src,sync:true,load:function(_2d){
-_29.code+=_2d+";";
-},error:_29.errBack});
-}
-};
-return _28.replace(/<script\s*(?![^>]*type=['"]?(?:dojo\/|text\/html\b))(?:[^>]*?(?:src=(['"]?)([^>]*?)\1[^>]*)?)*>([\s\S]*?)<\/script>/gi,function(_2e,_2f,src,_30){
-if(src){
-_2b(src);
-}else{
-_29.code+=_30;
-}
-return "";
-});
-};
-var _31=dojox.html.evalInGlobal=function(_32,_33){
-_33=_33||dojo.doc.body;
-var n=_33.ownerDocument.createElement("script");
-n.type="text/javascript";
-_33.appendChild(n);
-n.text=_32;
-};
-dojo.declare("dojox.html._ContentSetter",[dojo.html._ContentSetter],{adjustPaths:false,referencePath:".",renderStyles:false,executeScripts:false,scriptHasHooks:false,scriptHookReplacement:null,_renderStyles:function(_34){
-this._styleNodes=[];
-var st,att,_35,doc=this.node.ownerDocument;
-var _36=doc.getElementsByTagName("head")[0];
-for(var i=0,e=_34.length;i<e;i++){
-_35=_34[i];
-att=_34.attributes[i];
-st=doc.createElement("style");
-st.setAttribute("type","text/css");
-for(var x in att){
-st.setAttribute(x,att[x]);
-}
-this._styleNodes.push(st);
-_36.appendChild(st);
-if(st.styleSheet){
-st.styleSheet.cssText=_35;
-}else{
-st.appendChild(doc.createTextNode(_35));
-}
-}
-},empty:function(){
-this.inherited("empty",arguments);
-this._styles=[];
-},onBegin:function(){
-this.inherited("onBegin",arguments);
-var _37=this.content,_38=this.node;
-var _39=this._styles;
-if(dojo.isString(_37)){
-if(this.adjustPaths&&this.referencePath){
-_37=_12(this.referencePath,_37);
-}
-if(this.renderStyles||this.cleanContent){
-_37=_1b(this.referencePath,_37,_39);
-}
-if(this.executeScripts){
-var _3a=this;
-var _3b={downloadRemote:true,errBack:function(e){
-_3a._onError.call(_3a,"Exec","Error downloading remote script in \""+_3a.id+"\"",e);
-}};
-_37=_27(_37,_3b);
-this._code=_3b.code;
-}
-}
-this.content=_37;
-},onEnd:function(){
-var _3c=this._code,_3d=this._styles;
-if(this._styleNodes&&this._styleNodes.length){
-while(this._styleNodes.length){
-dojo.destroy(this._styleNodes.pop());
-}
-}
-if(this.renderStyles&&_3d&&_3d.length){
-this._renderStyles(_3d);
-}
-if(this.executeScripts&&_3c){
-if(this.cleanContent){
-_3c=_3c.replace(/(<!--|(?:\/\/)?-->|<!\[CDATA\[|\]\]>)/g,"");
-}
-if(this.scriptHasHooks){
-_3c=_3c.replace(/_container_(?!\s*=[^=])/g,this.scriptHookReplacement);
-}
-try{
-_31(_3c,this.node);
-}
-catch(e){
-this._onError("Exec","Error eval script in "+this.id+", "+e.message,e);
-}
-}
-this.inherited("onEnd",arguments);
-},tearDown:function(){
-this.inherited(arguments);
-delete this._styles;
-if(this._styleNodes&&this._styleNodes.length){
-while(this._styleNodes.length){
-dojo.destroy(this._styleNodes.pop());
-}
-}
-delete this._styleNodes;
-dojo.mixin(this,dojo.getObject(this.declaredClass).prototype);
-}});
-dojox.html.set=function(_3e,_3f,_40){
-if(!_40){
-return dojo.html._setNodeContent(_3e,_3f,true);
-}else{
-var op=new dojox.html._ContentSetter(dojo.mixin(_40,{content:_3f,node:_3e}));
-return op.set();
-}
-};
+
+dojo.require("dojo.html"); 
+
+(function() {
+
+	if(dojo.isIE){
+		var alphaImageLoader = /(AlphaImageLoader\([^)]*?src=(['"]))(?![a-z]+:|\/)([^\r\n;}]+?)(\2[^)]*\)\s*[;}]?)/g;
+	}
+
+	// css at-rules must be set before any css declarations according to CSS spec
+	// match:
+	// @import 'http://dojotoolkit.org/dojo.css';
+	// @import 'you/never/thought/' print;
+	// @import url("it/would/work") tv, screen;
+	// @import url(/did/you/now.css);
+	// but not:
+	// @namespace dojo "http://dojotoolkit.org/dojo.css"; /* namespace URL should always be a absolute URI */
+	// @charset 'utf-8';
+	// @media print{ #menuRoot {display:none;} }
+		
+	// we adjust all paths that dont start on '/' or contains ':'
+	//(?![a-z]+:|\/)
+
+	var cssPaths = /(?:(?:@import\s*(['"])(?![a-z]+:|\/)([^\r\n;{]+?)\1)|url\(\s*(['"]?)(?![a-z]+:|\/)([^\r\n;]+?)\3\s*\))([a-z, \s]*[;}]?)/g;
+
+	var adjustCssPaths = dojox.html._adjustCssPaths = function(cssUrl, cssText){
+		//	summary:
+		//		adjusts relative paths in cssText to be relative to cssUrl
+		//		a path is considered relative if it doesn't start with '/' and not contains ':'
+		//	description:
+		//		Say we fetch a HTML page from level1/page.html
+		//		It has some inline CSS:
+		//			@import "css/page.css" tv, screen;
+		//			...
+		//			background-image: url(images/aplhaimage.png);
+		//
+		//		as we fetched this HTML and therefore this CSS
+		//		from level1/page.html, these paths needs to be adjusted to:
+		//			@import 'level1/css/page.css' tv, screen;
+		//			...
+		//			background-image: url(level1/images/alphaimage.png);
+		//		
+		//		In IE it will also adjust relative paths in AlphaImageLoader()
+		//			filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/alphaimage.png');
+		//		will be adjusted to:
+		//			filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='level1/images/alphaimage.png');
+		//
+		//		Please note that any relative paths in AlphaImageLoader in external css files wont work, as
+		//		the paths in AlphaImageLoader is MUST be declared relative to the HTML page,
+		//		not relative to the CSS file that declares it
+
+		if(!cssText || !cssUrl){ return; }
+
+		// support the ImageAlphaFilter if it exists, most people use it in IE 6 for transparent PNGs
+		// We are NOT going to kill it in IE 7 just because the PNGs work there. Somebody might have
+		// other uses for it.
+		// If user want to disable css filter in IE6  he/she should
+		// unset filter in a declaration that just IE 6 doesn't understands
+		// like * > .myselector { filter:none; }
+		if(alphaImageLoader){
+			cssText = cssText.replace(alphaImageLoader, function(ignore, pre, delim, url, post){
+				return pre + (new dojo._Url(cssUrl, './'+url).toString()) + post;
+			});
+		}
+
+		return cssText.replace(cssPaths, function(ignore, delimStr, strUrl, delimUrl, urlUrl, media){
+			if(strUrl){
+				return '@import "' + (new dojo._Url(cssUrl, './'+strUrl).toString()) + '"' + media;
+			}else{
+				return 'url(' + (new dojo._Url(cssUrl, './'+urlUrl).toString()) + ')' + media;
+			}
+		});
+	};
+
+	// attributepaths one tag can have multiple paths, example:
+	// <input src="..." style="url(..)"/> or <a style="url(..)" href="..">
+	// <img style='filter:progid...AlphaImageLoader(src="noticeTheSrcHereRunsThroughHtmlSrc")' src="img">
+	var htmlAttrPaths = /(<[a-z][a-z0-9]*\s[^>]*)(?:(href|src)=(['"]?)([^>]*?)\3|style=(['"]?)([^>]*?)\5)([^>]*>)/gi;
+
+	var adjustHtmlPaths = dojox.html._adjustHtmlPaths = function(htmlUrl, cont){
+		var url = htmlUrl || "./";
+
+		return cont.replace(htmlAttrPaths,
+			function(tag, start, name, delim, relUrl, delim2, cssText, end){
+				return start + (name ?
+							(name + '=' + delim + (new dojo._Url(url, relUrl).toString()) + delim)
+						: ('style=' + delim2 + adjustCssPaths(url, cssText) + delim2)
+				) + end;
+			}
+		);
+	};
+	
+	var snarfStyles = dojox.html._snarfStyles = function	(/*String*/cssUrl, /*String*/cont, /*Array*/styles){
+		/****************  cut out all <style> and <link rel="stylesheet" href=".."> **************/
+		// also return any attributes from this tag (might be a media attribute)
+		// if cssUrl is set it will adjust paths accordingly
+		styles.attributes = [];
+
+		return cont.replace(/(?:<style([^>]*)>([\s\S]*?)<\/style>|<link\s+(?=[^>]*rel=['"]?stylesheet)([^>]*?href=(['"])([^>]*?)\4[^>\/]*)\/?>)/gi,
+			function(ignore, styleAttr, cssText, linkAttr, delim, href){
+				// trim attribute
+				var i, attr = (styleAttr||linkAttr||"").replace(/^\s*([\s\S]*?)\s*$/i, "$1"); 
+				if(cssText){
+					i = styles.push(cssUrl ? adjustCssPaths(cssUrl, cssText) : cssText);
+				}else{
+					i = styles.push('@import "' + href + '";');
+					attr = attr.replace(/\s*(?:rel|href)=(['"])?[^\s]*\1\s*/gi, ""); // remove rel=... and href=...
+				}
+				if(attr){
+					attr = attr.split(/\s+/);// split on both "\n", "\t", " " etc
+					var atObj = {}, tmp;
+					for(var j = 0, e = attr.length; j < e; j++){
+						tmp = attr[j].split('='); // split name='value'
+						atObj[tmp[0]] = tmp[1].replace(/^\s*['"]?([\s\S]*?)['"]?\s*$/, "$1"); // trim and remove ''
+					}
+					styles.attributes[i - 1] = atObj;
+				}
+				return ""; // squelsh the <style> or <link>
+			}
+		);
+	};
+
+	var snarfScripts = dojox.html._snarfScripts = function(cont, byRef){
+		// summary
+		//		strips out script tags from cont
+		// invoke with 
+		//	byRef = {errBack:function(){/*add your download error code here*/, downloadRemote: true(default false)}}
+		//	byRef will have {code: 'jscode'} when this scope leaves
+		byRef.code = "";
+
+		//Update script tags nested in comments so that the script tag collector doesn't pick
+		//them up.
+		cont = cont.replace(/<[!][-][-](.|\s){5,}?[-][-]>/g,
+			function(comment){
+				return comment.replace(/<(\/?)script\b/ig,"<$1Script");
+			}
+		);
+
+		function download(src){
+			if(byRef.downloadRemote){
+				// console.debug('downloading',src);
+				//Fix up src, in case there were entity character encodings in it.
+				//Probably only need to worry about a subset.
+				src = src.replace(/&([a-z0-9#]+);/g, function(m, name) {
+					switch(name) {
+						case "amp"	: return "&";
+						case "gt"	: return ">";
+						case "lt"	: return "<";
+						default:
+							return name.charAt(0)=="#" ? String.fromCharCode(name.substring(1)) : "&"+name+";";
+					}
+				});
+				dojo.xhrGet({
+					url: src,
+					sync: true,
+					load: function(code){
+						byRef.code += code+";";
+					},
+					error: byRef.errBack
+				});
+			}
+		}
+		
+		// match <script>, <script type="text/..., but not <script type="dojo(/method)...
+		return cont.replace(/<script\s*(?![^>]*type=['"]?(?:dojo\/|text\/html\b))(?:[^>]*?(?:src=(['"]?)([^>]*?)\1[^>]*)?)*>([\s\S]*?)<\/script>/gi,
+			function(ignore, delim, src, code){
+				if(src){
+					download(src);
+				}else{
+					byRef.code += code;
+				}
+				return "";
+			}
+		);
+	}; 
+	
+	var evalInGlobal = dojox.html.evalInGlobal = function(code, appendNode){
+		// we do our own eval here as dojo.eval doesn't eval in global crossbrowser
+		// This work X browser but but it relies on a DOM
+		// plus it doesn't return anything, thats unrelevant here but not for dojo core
+		appendNode = appendNode || dojo.doc.body;
+		var n = appendNode.ownerDocument.createElement('script');
+		n.type = "text/javascript";
+		appendNode.appendChild(n);
+		n.text = code; // DOM 1 says this should work
+	};
+
+	dojo.declare("dojox.html._ContentSetter", [dojo.html._ContentSetter], {
+		// adjustPaths: Boolean
+		//		Adjust relative paths in html string content to point to this page
+		//		Only useful if you grab content from a another folder than the current one
+		adjustPaths: false,
+		referencePath: ".",
+		renderStyles: false, 
+
+		executeScripts: false,
+		scriptHasHooks: false,
+		scriptHookReplacement: null,
+		
+		_renderStyles: function(styles){
+			// insert css from content into document head
+			this._styleNodes = [];
+			var st, att, cssText, doc = this.node.ownerDocument;
+			var head = doc.getElementsByTagName('head')[0];
+
+			for(var i = 0, e = styles.length; i < e; i++){
+				cssText = styles[i]; att = styles.attributes[i];
+				st = doc.createElement('style');
+				st.setAttribute("type", "text/css"); // this is required in CSS spec!
+
+				for(var x in att){
+					st.setAttribute(x, att[x]);
+				}
+
+				this._styleNodes.push(st);
+				head.appendChild(st); // must insert into DOM before setting cssText
+
+				if(st.styleSheet){ // IE
+					st.styleSheet.cssText = cssText;
+				}else{ // w3c
+					st.appendChild(doc.createTextNode(cssText));
+				}
+			}
+		}, 
+
+		empty: function() {
+			this.inherited("empty", arguments);
+			
+			// empty out the styles array from any previous use
+			this._styles = [];
+		}, 
+		
+		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 implementation extends that of dojo.html._ContentSetter 
+			//		to add handling for adjustPaths, renderStyles on the html string content before it is set
+			this.inherited("onBegin", arguments);
+			
+			var cont = this.content, 
+				node = this.node; 
+				
+			var styles = this._styles;// init vars
+
+			if(dojo.isString(cont)){
+				if(this.adjustPaths && this.referencePath){
+					cont = adjustHtmlPaths(this.referencePath, cont);
+				}
+
+				if(this.renderStyles || this.cleanContent){
+					cont = snarfStyles(this.referencePath, cont, styles);
+				}
+
+				// because of a bug in IE, script tags that is first in html hierarchy doesnt make it into the DOM 
+				//	when content is innerHTML'ed, so we can't use dojo.query to retrieve scripts from DOM
+				if(this.executeScripts){
+					var _t = this; 
+					var byRef = {
+						downloadRemote: true,
+						errBack:function(e){
+							_t._onError.call(_t, 'Exec', 'Error downloading remote script in "'+_t.id+'"', e);
+						}
+					};
+					cont = snarfScripts(cont, byRef);
+					this._code = byRef.code;
+				}
+			}
+			this.content = cont;
+		},
+		
+		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 implementation extends that of dojo.html._ContentSetter
+			
+			var code = this._code, 
+				styles = this._styles;
+				
+			// clear old stylenodes from the DOM
+			// these were added by the last set call
+			// (in other words, if you dont keep and reuse the ContentSetter for a particular node
+			// .. you'll have no practical way to do this)
+			if(this._styleNodes && this._styleNodes.length){
+				while(this._styleNodes.length){
+					dojo.destroy(this._styleNodes.pop());
+				}
+			}
+			// render new style nodes
+			if(this.renderStyles && styles && styles.length){
+				this._renderStyles(styles);
+			}
+
+			if(this.executeScripts && code){
+				if(this.cleanContent){
+					// clean JS from html comments and other crap that browser
+					// parser takes care of in a normal page load
+					code = code.replace(/(<!--|(?:\/\/)?-->|<!\[CDATA\[|\]\]>)/g, '');
+				}
+				if(this.scriptHasHooks){
+					// replace _container_ with this.scriptHookReplace()
+					// the scriptHookReplacement can be a string 
+					// or a function, which when invoked returns the string you want to substitute in
+					code = code.replace(/_container_(?!\s*=[^=])/g, this.scriptHookReplacement);
+				}
+				try{
+					evalInGlobal(code, this.node);
+				}catch(e){
+					this._onError('Exec', 'Error eval script in '+this.id+', '+e.message, e);
+				}
+			}
+			this.inherited("onEnd", arguments);
+		},
+		tearDown: function() {
+			this.inherited(arguments);
+			delete this._styles;
+			// only tear down -or another set() - will explicitly throw away the
+			// references to the style nodes we added
+			if(this._styleNodes && this._styleNodes.length){
+				while(this._styleNodes.length){
+					dojo.destroy(this._styleNodes.pop());
+				}
+			}
+			delete this._styleNodes; 
+			// reset the defaults from the prototype
+			dojo.mixin(this, dojo.getObject(this.declaredClass).prototype);
+		}
+		
+	});
+	
+	dojox.html.set = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont, /* Object? */ params){
+		// TODO: add all the other options
+			// summary:
+			//		inserts (replaces) the given content into the given node
+			//	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(!params){
+			// simple and fast
+			return dojo.html._setNodeContent(node, cont, true);
+		}else{ 
+			// more options but slower
+			var op = new dojox.html._ContentSetter(dojo.mixin( 
+					params, 
+					{ content: cont, node: node } 
+			));
+			return op.set();
+		}
+	};
+	
 })();
-}
diff --git a/dojox/html/ellipsis.js b/dojox/html/ellipsis.js
index 695fc12..92fd620 100644
--- a/dojox/html/ellipsis.js
+++ b/dojox/html/ellipsis.js
@@ -1,168 +1,190 @@
-/*
-	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
-*/
+dojo.provide("dojox.html.ellipsis");
 
+/*=====
+dojox.html.ellipsis = {
+	// summary: offers cross-browser support for text-overflow: ellipsis
+	//
+	// description: Add "dojoxEllipsis" on any node that you want to ellipsis-ize. In order to function properly,
+	//	the node with the dojoxEllipsis class set on it should be a child of a node with a defined width.
+	//	It should also be a block-level element (i.e. <div>) - it will not work on td elements.
+	//	NOTE: When using the dojoxEllipsis class within tables, the table needs to have the table-layout: fixed style
+}
+=====*/
 
-if(!dojo._hasResource["dojox.html.ellipsis"]){
-dojo._hasResource["dojox.html.ellipsis"]=true;
-dojo.provide("dojox.html.ellipsis");
 (function(d){
-if(d.isMoz){
-var _1=1;
-if("dojoxFFEllipsisDelay" in d.config){
-_1=Number(d.config.dojoxFFEllipsisDelay);
-if(isNaN(_1)){
-_1=1;
-}
-}
-var _2="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-var _3=document.createElementNS(_2,"window");
-var _4=document.createElementNS(_2,"description");
-_4.setAttribute("crop","end");
-_3.appendChild(_4);
-var _5=function(n){
-var x=_3.cloneNode(true);
-x.firstChild.setAttribute("value",n.textContent);
-n.innerHTML="";
-n.appendChild(x);
-};
-var _6=d.create;
-var dd=d.doc;
-var dp=d.place;
-var _7=_6("iframe",{className:"dojoxEllipsisIFrame",src:"javascript:'<html><head><script>if(\"loadFirebugConsole\" in window){window.loadFirebugConsole();}</script></head><body></body></html>'"});
-var _8=function(r,_9){
-if(r.collapsed){
-return;
-}
-if(_9>0){
-do{
-_8(r);
-_9--;
-}while(_9);
-return;
-}
-if(r.endContainer.nodeType==3&&r.endOffset>0){
-r.setEnd(r.endContainer,r.endOffset-1);
-}else{
-if(r.endContainer.nodeType==3){
-r.setEndBefore(r.endContainer);
-_8(r);
-return;
-}else{
-if(r.endOffset&&r.endContainer.childNodes.length>=r.endOffset){
-var _a=r.endContainer.childNodes[r.endOffset-1];
-if(_a.nodeType==3){
-r.setEnd(_a,_a.length-1);
-}else{
-if(_a.childNodes.length){
-r.setEnd(_a,_a.childNodes.length);
-_8(r);
-return;
-}else{
-r.setEndBefore(_a);
-_8(r);
-return;
-}
-}
-}else{
-r.setEndBefore(r.endContainer);
-_8(r);
-return;
-}
-}
-}
-};
-var _b=function(n){
-var c=_6("div",{className:"dojoxEllipsisContainer"});
-var e=_6("div",{className:"dojoxEllipsisShown",style:{display:"none"}});
-n.parentNode.replaceChild(c,n);
-c.appendChild(n);
-c.appendChild(e);
-var i=_7.cloneNode(true);
-var ns=n.style;
-var es=e.style;
-var _c;
-var _d=function(){
-ns.display="";
-es.display="none";
-if(n.scrollWidth<=n.offsetWidth){
-return;
-}
-var r=dd.createRange();
-r.selectNodeContents(n);
-ns.display="none";
-es.display="";
-var _e=false;
-do{
-var _f=1;
-dp(r.cloneContents(),e,"only");
-var sw=e.scrollWidth,ow=e.offsetWidth;
-_e=(sw<=ow);
-var pct=(1-((ow*1)/sw));
-if(pct>0){
-_f=Math.max(Math.round(e.textContent.length*pct)-1,1);
-}
-_8(r,_f);
-}while(!r.collapsed&&!_e);
-};
-i.onload=function(){
-i.contentWindow.onresize=_d;
-_d();
-};
-c.appendChild(i);
-};
-var hc=d.hasClass;
-var doc=d.doc;
-var s,fn,opt;
-if(doc.querySelectorAll){
-s=doc;
-fn="querySelectorAll";
-opt=".dojoxEllipsis";
-}else{
-if(doc.getElementsByClassName){
-s=doc;
-fn="getElementsByClassName";
-opt="dojoxEllipsis";
-}else{
-s=d;
-fn="query";
-opt=".dojoxEllipsis";
-}
-}
-fx=function(){
-d.forEach(s[fn].apply(s,[opt]),function(n){
-if(!n||n._djx_ellipsis_done){
-return;
-}
-n._djx_ellipsis_done=true;
-if(n.textContent==n.innerHTML&&!hc(n,"dojoxEllipsisSelectable")){
-_5(n);
-}else{
-_b(n);
-}
-});
-};
-d.addOnLoad(function(){
-var t=null;
-var c=null;
-var _10=function(){
-if(c){
-d.disconnect(c);
-c=null;
-}
-if(t){
-clearTimeout(t);
-}
-t=setTimeout(function(){
-t=null;
-fx();
-c=d.connect(d.body(),"DOMSubtreeModified",_10);
-},_1);
-};
-_10();
-});
-}
+	if(d.isMoz){
+		// The delay (in ms) to wait so that we don't keep querying when many 
+		// changes happen at once - set config "dojoxFFEllipsisDelay" if you
+		// want a different value
+		var delay = 1;
+		if("dojoxFFEllipsisDelay" in d.config){
+			delay = Number(d.config.dojoxFFEllipsisDelay);
+			if(isNaN(delay)){
+				delay = 1;
+			}
+		}
+		
+		// Create our stub XUL elements for cloning later
+		var sNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
+		var xml = document.createElementNS(sNS, 'window');
+		var label = document.createElementNS(sNS, 'description');
+		label.setAttribute('crop', 'end');
+		xml.appendChild(label);
+		
+		var createXULEllipsis = function(/* Node */ n){
+			// Summary:
+			//		Given a node, it creates the XUL and sets its
+			//		content so that it will have an ellipsis
+			var x = xml.cloneNode(true);
+			x.firstChild.setAttribute('value', n.textContent);
+			n.innerHTML = '';
+			n.appendChild(x);
+		};
+		
+		// Create our iframe elements for cloning later
+		var create = d.create;
+		var dd = d.doc;
+		var dp = d.place;
+		var iFrame = create("iframe", {className: "dojoxEllipsisIFrame",
+					src: "javascript:'<html><head><script>if(\"loadFirebugConsole\" in window){window.loadFirebugConsole();}</script></head><body></body></html>'"});
+		var rollRange = function(/* W3C Range */ r, /* int? */ cnt){
+			// Summary:
+			//		Rolls the given range back one character from the end
+			//
+			//	r: W3C Range
+			//		The range to roll back
+			//	cnt: int?
+			//		An optional number of times to roll back (defaults 1)
+			if(r.collapsed){
+				// Do nothing - we are already collapsed
+				return;
+			}
+			if(cnt > 0){
+				do{
+					rollRange(r);
+					cnt--;
+				}while(cnt);
+				return;
+			}
+			if(r.endContainer.nodeType == 3 && r.endOffset > 0){
+				r.setEnd(r.endContainer, r.endOffset - 1);
+			}else if(r.endContainer.nodeType == 3){
+				r.setEndBefore(r.endContainer);
+				rollRange(r);
+				return;
+			}else if(r.endOffset && r.endContainer.childNodes.length >= r.endOffset){
+				var nCont = r.endContainer.childNodes[r.endOffset - 1];
+				if(nCont.nodeType == 3){
+					r.setEnd(nCont, nCont.length - 1);
+				}else if(nCont.childNodes.length){
+					r.setEnd(nCont, nCont.childNodes.length);
+					rollRange(r);
+					return;
+				}else{
+					r.setEndBefore(nCont);
+					rollRange(r);
+					return;
+				}
+			}else{
+				r.setEndBefore(r.endContainer);
+				rollRange(r);
+				return;
+			}
+		};
+		var createIFrameEllipsis = function(/* Node */ n){
+			// Summary:
+			//		Given a node, it creates an iframe and and ellipsis div and
+			//		sets up the connections so that they will work correctly.
+			//		This function is used when createXULEllipsis is not able
+			//		to be used (because there is markup within the node) - it's
+			//		a bit slower, but does the trick
+			var c = create("div", {className: "dojoxEllipsisContainer"});
+			var e = create("div", {className: "dojoxEllipsisShown", style: {display: "none"}});
+			n.parentNode.replaceChild(c, n);
+			c.appendChild(n);
+			c.appendChild(e);
+			var i = iFrame.cloneNode(true);
+			var ns = n.style;
+			var es = e.style;
+			var ranges;
+			var resizeNode = function(){
+				ns.display = "";
+				es.display = "none";
+				if(n.scrollWidth <= n.offsetWidth){ return; }
+				var r = dd.createRange();
+				r.selectNodeContents(n);
+				ns.display = "none";
+				es.display = "";
+				var done = false;
+				do{
+					var numRolls = 1;
+					dp(r.cloneContents(), e, "only");
+					var sw = e.scrollWidth, ow = e.offsetWidth;
+					done = (sw <= ow);
+					var pct = (1 - ((ow * 1) / sw));
+					if(pct > 0){
+						numRolls = Math.max(Math.round(e.textContent.length * pct) - 1, 1);
+					}
+					rollRange(r, numRolls);
+				}while(!r.collapsed && !done);
+			};
+			i.onload = function(){
+				i.contentWindow.onresize = resizeNode;
+				resizeNode();
+			};
+			c.appendChild(i);
+		};
+
+		// Function for updating the ellipsis
+		var hc = d.hasClass;
+		var doc = d.doc;
+		var s, fn, opt;
+		if(doc.querySelectorAll){
+			s = doc;
+			fn = "querySelectorAll";
+			opt = ".dojoxEllipsis";
+		}else if(doc.getElementsByClassName){
+			s = doc;
+			fn = "getElementsByClassName";
+			opt = "dojoxEllipsis";
+		}else{
+			s = d;
+			fn = "query";
+			opt = ".dojoxEllipsis";
+		}
+		fx = function(){
+			d.forEach(s[fn].apply(s, [opt]), function(n){
+				if(!n || n._djx_ellipsis_done){ return; }
+				n._djx_ellipsis_done = true;
+				if(n.textContent == n.innerHTML && !hc(n, "dojoxEllipsisSelectable")){
+					// We can do the faster XUL version, instead of calculating
+					createXULEllipsis(n);
+				}else{
+					createIFrameEllipsis(n);
+				}
+			});
+		};
+		
+		d.addOnLoad(function(){
+			// Apply our initial stuff
+			var t = null;
+			var c = null;
+			var connFx = function(){
+				if(c){
+					// disconnect us - so we don't fire anymore
+					d.disconnect(c);
+					c = null;
+				}
+				if(t){ clearTimeout(t); }
+				t = setTimeout(function(){
+					t = null;
+					fx();
+					// Connect to the modified function so that we can catch
+					// our next change
+					c = d.connect(d.body(), "DOMSubtreeModified", connFx);
+				}, delay);
+			};
+			connFx();
+		});
+	}
 })(dojo);
-}
diff --git a/dojox/html/entities.js b/dojox/html/entities.js
old mode 100644
new mode 100755
index ab3e8fd..1b8fdf7
--- a/dojox/html/entities.js
+++ b/dojox/html/entities.js
@@ -1,85 +1,203 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.html.entities"]){
-dojo._hasResource["dojox.html.entities"]=true;
 dojo.provide("dojox.html.entities");
 (function(){
-var _1=function(_2,_3){
-var _4,_5;
-if(_3._encCache&&_3._encCache.regexp&&_3._encCache.mapper&&_3.length==_3._encCache.length){
-_4=_3._encCache.mapper;
-_5=_3._encCache.regexp;
-}else{
-_4={};
-_5=["["];
-var i;
-for(i=0;i<_3.length;i++){
-_4[_3[i][0]]="&"+_3[i][1]+";";
-_5.push(_3[i][0]);
-}
-_5.push("]");
-_5=new RegExp(_5.join(""),"g");
-_3._encCache={mapper:_4,regexp:_5,length:_3.length};
-}
-_2=_2.replace(_5,function(c){
-return _4[c];
-});
-return _2;
-};
-var _6=function(_7,_8){
-var _9,_a;
-if(_8._decCache&&_8._decCache.regexp&&_8._decCache.mapper&&_8.length==_8._decCache.length){
-_9=_8._decCache.mapper;
-_a=_8._decCache.regexp;
-}else{
-_9={};
-_a=["("];
-var i;
-for(i=0;i<_8.length;i++){
-var e="&"+_8[i][1]+";";
-if(i){
-_a.push("|");
-}
-_9[e]=_8[i][0];
-_a.push(e);
-}
-_a.push(")");
-_a=new RegExp(_a.join(""),"g");
-_8._decCache={mapper:_9,regexp:_a,length:_8.length};
-}
-_7=_7.replace(_a,function(c){
-return _9[c];
-});
-return _7;
-};
-dojox.html.entities.html=[["&","amp"],["\"","quot"],["<","lt"],[">","gt"],[" ","nbsp"]];
-dojox.html.entities.latin=[["¡","iexcl"],["¢","cent"],["£","pound"],["€","euro"],["¤","curren"],["¥","yen"],["¦","brvbar"],["§","sect"],["¨","uml"],["©","copy"],["ª","ordf"],["«","laquo"],["¬","not"],["­","shy"],["®","reg"],["¯","macr"],["°","deg"],["±","plusmn"],["²","sup2"],["³","sup3"],["´","acute"],["µ","micro"],["¶","para"],["·","middot"],["¸","cedil"],["¹","sup1"],["º","ordm"],["»","raquo"],["¼","frac14"],["½","frac12"],["¾","frac34"],["¿","iquest"],["À","Agrave"],["Á","Aacute"],[" [...]
-dojox.html.entities.encode=function(_b,m){
-if(_b){
-if(!m){
-_b=_1(_b,dojox.html.entities.html);
-_b=_1(_b,dojox.html.entities.latin);
-}else{
-_b=_1(_b,m);
-}
-}
-return _b;
-};
-dojox.html.entities.decode=function(_c,m){
-if(_c){
-if(!m){
-_c=_6(_c,dojox.html.entities.html);
-_c=_6(_c,dojox.html.entities.latin);
-}else{
-_c=_6(_c,m);
-}
-}
-return _c;
-};
+	// dojox.html.entities.html [public] Array
+	//		Entity characters for HTML, represented as an array of 
+	//		character code, entity name (minus & and ; wrapping.
+
+	var _applyEncodingMap = function(str, map){
+		// summary:
+		//		Private internal function for performing encoding of entity characters.
+		// tags:
+		//		private
+
+		// Check to see if we have genned and cached a regexp for this map yet
+		// If we have, use it, if not, gen it, cache, then use.
+		var mapper, regexp;
+		if(map._encCache && 
+			map._encCache.regexp && 
+			map._encCache.mapper && 
+			map.length == map._encCache.length){
+			mapper = map._encCache.mapper;
+			regexp = map._encCache.regexp;
+		}else{
+			mapper = {};
+			regexp = ["["];
+			var i;
+			for(i = 0; i < map.length; i++){
+				mapper[map[i][0]] = "&" + map[i][1] + ";";
+				regexp.push(map[i][0]);
+			}
+			regexp.push("]");
+			regexp = new RegExp(regexp.join(""), "g");
+			map._encCache = {
+				mapper: mapper,
+				regexp: regexp,
+				length: map.length
+			};
+		}
+		str = str.replace(regexp, function(c){
+			return mapper[c];
+		});
+		return str;
+	};
+
+	var _applyDecodingMap = function(str, map){
+		// summary:
+		//		Private internal function for performing decoding of entity characters.
+		// tags:
+		//		private
+		var mapper, regexp;
+		if(map._decCache && 
+			map._decCache.regexp && 
+			map._decCache.mapper && 
+			map.length == map._decCache.length){
+			mapper = map._decCache.mapper;
+			regexp = map._decCache.regexp;
+		}else{
+			mapper = {};
+			regexp = ["("];
+			var i;
+			for(i = 0; i < map.length; i++){
+				var e = "&" + map[i][1] + ";";
+				if(i){regexp.push("|");}
+				mapper[e] = map[i][0];
+				regexp.push(e);
+			}
+			regexp.push(")");
+			regexp = new RegExp(regexp.join(""), "g");
+			map._decCache = {
+				mapper: mapper,
+				regexp: regexp,
+				length: map.length
+			};
+		}
+		str = str.replace(regexp, function(c){
+			return mapper[c];
+		});
+		return str;
+	};
+
+	dojox.html.entities.html = [
+		["\u0026","amp"], ["\u0022","quot"],["\u003C","lt"], ["\u003E","gt"],
+		["\u00A0","nbsp"]
+	];
+
+	// dojox.html.entities.latin [public] Array
+	//		Entity characters for Latin characters and similar, represented as an array of 
+	//		character code, entity name (minus & and ; wrapping.
+	dojox.html.entities.latin = [
+		["\u00A1","iexcl"],["\u00A2","cent"],["\u00A3","pound"],["\u20AC","euro"],
+		["\u00A4","curren"],["\u00A5","yen"],["\u00A6","brvbar"],["\u00A7","sect"],
+		["\u00A8","uml"],["\u00A9","copy"],["\u00AA","ordf"],["\u00AB","laquo"],
+		["\u00AC","not"],["\u00AD","shy"],["\u00AE","reg"],["\u00AF","macr"],
+		["\u00B0","deg"],["\u00B1","plusmn"],["\u00B2","sup2"],["\u00B3","sup3"],
+		["\u00B4","acute"],["\u00B5","micro"],["\u00B6","para"],["\u00B7","middot"],
+		["\u00B8","cedil"],["\u00B9","sup1"],["\u00BA","ordm"],["\u00BB","raquo"],
+		["\u00BC","frac14"],["\u00BD","frac12"],["\u00BE","frac34"],["\u00BF","iquest"],
+		["\u00C0","Agrave"],["\u00C1","Aacute"],["\u00C2","Acirc"],["\u00C3","Atilde"],
+		["\u00C4","Auml"],["\u00C5","Aring"],["\u00C6","AElig"],["\u00C7","Ccedil"],
+		["\u00C8","Egrave"],["\u00C9","Eacute"],["\u00CA","Ecirc"],["\u00CB","Euml"],
+		["\u00CC","Igrave"],["\u00CD","Iacute"],["\u00CE","Icirc"],["\u00CF","Iuml"],
+		["\u00D0","ETH"],["\u00D1","Ntilde"],["\u00D2","Ograve"],["\u00D3","Oacute"],
+		["\u00D4","Ocirc"],["\u00D5","Otilde"],["\u00D6","Ouml"],["\u00D7","times"],
+		["\u00D8","Oslash"],["\u00D9","Ugrave"],["\u00DA","Uacute"],["\u00DB","Ucirc"], 
+		["\u00DC","Uuml"],["\u00DD","Yacute"],["\u00DE","THORN"],["\u00DF","szlig"],
+		["\u00E0","agrave"],["\u00E1","aacute"],["\u00E2","acirc"],["\u00E3","atilde"],
+		["\u00E4","auml"],["\u00E5","aring"],["\u00E6","aelig"],["\u00E7","ccedil"],
+		["\u00E8","egrave"],["\u00E9","eacute"],["\u00EA","ecirc"],["\u00EB","euml"],
+		["\u00EC","igrave"],["\u00ED","iacute"],["\u00EE","icirc"],["\u00EF","iuml"], 
+		["\u00F0","eth"],["\u00F1","ntilde"],["\u00F2","ograve"],["\u00F3","oacute"],
+		["\u00F4","ocirc"],["\u00F5","otilde"],["\u00F6","ouml"],["\u00F7","divide"],
+		["\u00F8","oslash"],["\u00F9","ugrave"],["\u00FA","uacute"],["\u00FB","ucirc"],
+		["\u00FC","uuml"],["\u00FD","yacute"],["\u00FE","thorn"],["\u00FF","yuml"],
+		["\u0192","fnof"],["\u0391","Alpha"],["\u0392","Beta"],["\u0393","Gamma"],
+		["\u0394","Delta"],["\u0395","Epsilon"],["\u0396","Zeta"],["\u0397","Eta"],
+		["\u0398","Theta"], ["\u0399","Iota"],["\u039A","Kappa"],["\u039B","Lambda"],
+		["\u039C","Mu"],["\u039D","Nu"],["\u039E","Xi"],["\u039F","Omicron"],
+		["\u03A0","Pi"],["\u03A1","Rho"],["\u03A3","Sigma"],["\u03A4","Tau"],
+		["\u03A5","Upsilon"],["\u03A6","Phi"],["\u03A7","Chi"],["\u03A8","Psi"], 
+		["\u03A9","Omega"],["\u03B1","alpha"],["\u03B2","beta"],["\u03B3","gamma"],
+		["\u03B4","delta"],["\u03B5","epsilon"],["\u03B6","zeta"],["\u03B7","eta"],
+		["\u03B8","theta"],["\u03B9","iota"],["\u03BA","kappa"],["\u03BB","lambda"],
+		["\u03BC","mu"],["\u03BD","nu"],["\u03BE","xi"],["\u03BF","omicron"],
+		["\u03C0","pi"],["\u03C1","rho"],["\u03C2","sigmaf"],["\u03C3","sigma"], 
+		["\u03C4","tau"],["\u03C5","upsilon"],["\u03C6","phi"],["\u03C7","chi"],
+		["\u03C8","psi"],["\u03C9","omega"],["\u03D1","thetasym"],["\u03D2","upsih"],
+		["\u03D6","piv"],["\u2022","bull"],["\u2026","hellip"],["\u2032","prime"],
+		["\u2033","Prime"],["\u203E","oline"],["\u2044","frasl"],["\u2118","weierp"],
+		["\u2111","image"],["\u211C","real"],["\u2122","trade"],["\u2135","alefsym"], 
+		["\u2190","larr"],["\u2191","uarr"],["\u2192","rarr"],["\u2193","darr"],
+		["\u2194","harr"],["\u21B5","crarr"],["\u21D0","lArr"],["\u21D1","uArr"],
+		["\u21D2","rArr"],["\u21D3","dArr"],["\u21D4","hArr"],["\u2200","forall"],
+		["\u2202","part"],["\u2203","exist"],["\u2205","empty"],["\u2207","nabla"],
+		["\u2208","isin"],["\u2209","notin"],["\u220B","ni"],["\u220F","prod"], 
+		["\u2211","sum"],["\u2212","minus"],["\u2217","lowast"],["\u221A","radic"],
+		["\u221D","prop"],["\u221E","infin"],["\u2220","ang"],["\u2227","and"],
+		["\u2228","or"],["\u2229","cap"],["\u222A","cup"],["\u222B","int"],
+		["\u2234","there4"],["\u223C","sim"],["\u2245","cong"],["\u2248","asymp"],
+		["\u2260","ne"],["\u2261","equiv"],["\u2264","le"],["\u2265","ge"], 
+		["\u2282","sub"],["\u2283","sup"],["\u2284","nsub"],["\u2286","sube"],
+		["\u2287","supe"],["\u2295","oplus"],["\u2297","otimes"],["\u22A5","perp"],
+		["\u22C5","sdot"],["\u2308","lceil"],["\u2309","rceil"],["\u230A","lfloor"],
+		["\u230B","rfloor"],["\u2329","lang"],["\u232A","rang"],["\u25CA","loz"],
+		["\u2660","spades"],["\u2663","clubs"],["\u2665","hearts"],["\u2666","diams"], 
+		["\u0152","Elig"],["\u0153","oelig"],["\u0160","Scaron"],["\u0161","scaron"],
+		["\u0178","Yuml"],["\u02C6","circ"],["\u02DC","tilde"],["\u2002","ensp"],
+		["\u2003","emsp"],["\u2009","thinsp"],["\u200C","zwnj"],["\u200D","zwj"],
+		["\u200E","lrm"],["\u200F","rlm"],["\u2013","ndash"],["\u2014","mdash"],
+		["\u2018","lsquo"],["\u2019","rsquo"],["\u201A","sbquo"],["\u201C","ldquo"],
+		["\u201D","rdquo"],["\u201E","bdquo"],["\u2020","dagger"],["\u2021","Dagger"],
+		["\u2030","permil"],["\u2039","lsaquo"],["\u203A","rsaquo"]
+	];
+
+	dojox.html.entities.encode = function(str/*string*/, m /*array?*/){
+		// summary:
+		//		Function to obtain an entity encoding for a specified character
+		// str:
+		//		The string to process for possible entity encoding.
+		// m:
+		//		An optional list of character to entity name mappings (array of 
+		//		arrays).  If not provided, it uses the and Latin entities as the 
+		//		set to map and escape.
+		// tags:
+		//		public
+		if(str){
+			if(!m){
+				// Apply the basic mappings.  HTML should always come first when decoding
+				// as well.
+				str = _applyEncodingMap(str, dojox.html.entities.html);
+				str = _applyEncodingMap(str, dojox.html.entities.latin);
+
+			}else{
+				str = _applyEncodingMap(str, m);
+			}
+		}
+		return str;
+	};
+
+	dojox.html.entities.decode = function(str/*string*/, m /*array?*/){
+		// summary:
+		//		Function to obtain an entity encoding for a specified character
+		// str:
+		//		The string to process for possible entity encoding to decode.
+		// m:
+		//		An optional list of character to entity name mappings (array of 
+		//		arrays).  If not provided, it uses the HTML and Latin entities as the 
+		//		set to map and decode.
+		// tags:
+		//		public
+		if(str){
+			if(!m){
+				// Apply the basic mappings.  HTML should always come first when decoding
+				// as well.
+				str = _applyDecodingMap(str, dojox.html.entities.html);
+				str = _applyDecodingMap(str, dojox.html.entities.latin);
+
+			}else{
+				str = _applyDecodingMap(str, m);
+			}
+		}
+		return str;
+	};
 })();
-}
+
diff --git a/dojox/html/ext-dojo/style.js b/dojox/html/ext-dojo/style.js
new file mode 100644
index 0000000..8ca2d86
--- /dev/null
+++ b/dojox/html/ext-dojo/style.js
@@ -0,0 +1,460 @@
+dojo.provide("dojox.html.ext-dojo.style");
+dojo.experimental("dojox.html.ext-dojo.style");
+
+// summary: Extensions to dojo.style adding the css3 "transform" and "transform-origin" properties on IE5.5+
+// description:
+//	A Package to extend the dojo.style function
+//	Supported transformation functions:
+//  matrix, translate, translateX, translateY, scale, scaleX, scaleY, rotate, skewX, skewY, skew
+dojo.mixin(dojox.html["ext-dojo"].style, {
+	supportsTransform: true,
+	_toPx: function(measure){
+		var ds = dojo.style, _conversion = this._conversion;
+		if(typeof measure === "number"){
+			return measure + "px";
+		}else if(measure.toLowerCase().indexOf("px") != -1){
+			return measure;
+		}
+		// "native" conversion in px
+		!_conversion.parentNode && dojo.place(_conversion, dojo.body());
+		ds(_conversion, "margin", measure);
+		return ds(_conversion, "margin");
+	},
+	init: function(){
+		var ds = dojo.style, docStyle = dojo.doc.documentElement.style, extStyle = dojox.html["ext-dojo"].style;
+		dojo.style = function(	/*DomNode|String*/ node,
+								/*String?|Object?*/ style,
+								/*String?*/ value){
+			// summary:
+			//      extended dojo.style()
+			// description:
+			//      extended dojo.style() function, capable of handling the css3 "transform" and "transform-origin" properties
+			// example:
+			// | dojo.style("rotate(20deg) scaleX(1.5) scaleY(2) skew(10deg, 20deg)")
+			var n = dojo.byId(node),
+				tr = (style == "transform"),
+				to = (style == "transformOrigin"),
+				args = arguments.length
+			;
+			if(args == 3){
+				if(tr){
+					extStyle.setTransform(n, value, true);
+				}else if(to){
+					extStyle.setTransformOrigin(n, value);
+				}else{
+					ds(node, style, value);
+				}
+			}
+			if(args == 2){
+				if(tr){
+					return extStyle.getTransform(node);
+				}else if(to){
+					return extStyle.getTransformOrigin(node);
+				}else{
+					return ds(node, style);
+				}
+			}
+		};
+		// prefixes and property names
+		for(var i = 0, tPrefix = ["WebkitT", "MozT", "OT", "t"]; i < tPrefix.length; i++){
+			if(typeof docStyle[tPrefix[i] + "ransform"] !== "undefined"){
+				this.tPropertyName = tPrefix[i] + "ransform";
+			}
+			if(typeof docStyle[tPrefix[i] + "ransformOrigin"] !== "undefined"){
+				this.toPropertyName = tPrefix[i] + "ransformOrigin";
+			}
+		}
+		if(this.tPropertyName){
+			this.setTransform = function(/*DomNode*/node, /*String*/ transform){
+				return dojo.style(node, this.tPropertyName, transform);
+			};
+			this.getTransform = function(/*DomNode*/node){
+				return dojo.style(node, this.tPropertyName);
+			};
+		}else if(dojo.isIE){
+			this.setTransform = this._setTransformFilter;
+			this.getTransform = this._getTransformFilter;
+		}
+		if(this.toPropertyName){
+			this.setTransformOrigin = function(/*DomNode*/node, /*String*/ transformOrigin){
+				return dojo.style(node, this.toPropertyName, transformOrigin);
+			};
+			this.getTransformOrigin = function(/*DomNode*/node){
+				return dojo.style(node, this.toPropertyName);
+			};
+		}else if(dojo.isIE){
+			this.setTransformOrigin = this._setTransformOriginFilter;
+			this.getTransformOrigin = this._getTransformOriginFilter;
+		}else{
+			this.supportsTransform = false;
+		}
+		this._conversion = dojo.create("div", {
+			style: {
+				position: "absolute",
+				top: "-100px",
+				left: "-100px",
+				fontSize: 0,
+				width: "0",
+				backgroundPosition: "50% 50%"
+			}
+		});
+	},
+	_notSupported: function(){
+		console.warn("Sorry, this browser doesn't support transform and transform-origin");	
+	},
+	_setTransformOriginFilter: function(/*DomNode*/ node, /*String*/ transformOrigin){
+		var to = dojo.trim(transformOrigin)
+			.replace(" top", " 0")
+			.replace("left ", "0 ")
+			.replace(" center", "50%")
+			.replace("center ", "50% ")
+			.replace(" bottom", " 100%")
+			.replace("right ", "100% ")
+			.replace(/\s+/, " "),
+			toAry = to.split(" "),
+			n = dojo.byId(node),
+			t = this.getTransform(n),
+			validOrigin = true
+		;
+		for(var i = 0; i < toAry.length; i++){
+			validOrigin = validOrigin && /^0|(\d+(%|px|pt|in|pc|mm|cm))$/.test(toAry[i]);
+			if(toAry[i].indexOf("%") == -1){
+				toAry[i] = this._toPx(toAry[i]);
+			}
+		}
+		if(!validOrigin){
+			return;
+		}
+		if(!toAry.length || toAry.length > 2 ){
+			return;
+		}
+		dojo.attr(n, "dojo-transform-origin", toAry.join(" "));
+		t && this.setTransform(node, t);
+	},
+	_getTransformOriginFilter: function(/*DomNode*/ node){
+		return dojo.attr(node, "dojo-transform-origin") || "50% 50%";
+	},
+	_setTransformFilter: function(/*DomNode*/ node, /*String*/ transform){
+		// Using the Matrix Filter to implement the transform property on IE
+		var t = transform.replace(/\s/g, ""),
+			n = dojo.byId(node),
+			transforms = t.split(")"),
+			toRad = 1, toRad1 = 1,
+			mstr = "DXImageTransform.Microsoft.Matrix",
+			hasAttr = dojo.hasAttr,
+			attr = dojo.attr,
+			// Math functions
+			PI = Math.PI, cos = Math.cos, sin = Math.sin, tan = Math.tan, max = Math.max, min = Math.min, abs = Math.abs,
+			degToRad = PI/180, gradToRad = PI/200,
+
+			// current transform
+			ct = "", currentTransform = "",
+			matchingTransforms = [],
+			x0 = 0, y0 = 0, dx = 0, dy = 0, xc = 0, yc = 0, a = 0,
+
+			// default transform, identity matrix
+			m11 = 1, m12 = 0, m21 = 0, m22 = 1,
+
+			// no translation
+			tx = 0, ty = 0,
+			props = [m11, m12, m21, m22, tx, ty],
+			hasMatrix = false,
+			ds = dojo.style,
+			newPosition = ds(n, "position") == "absolute" ? "absolute" : "relative",
+			w = ds(n, "width") + ds(n, "paddingLeft") + ds(n, "paddingRight"),
+			h = ds(n, "height") + ds(n, "paddingTop") + ds(n, "paddingBottom"),
+			toPx = this._toPx
+		;
+
+		!hasAttr(n, "dojo-transform-origin") && this.setTransformOrigin(n, "50% 50%");
+
+		for(var i = 0, l = transforms.length; i < l; i++){
+			matchingTransforms = transforms[i].match(/matrix|rotate|scaleX|scaleY|scale|skewX|skewY|skew|translateX|translateY|translate/);
+			currentTransform = matchingTransforms ? matchingTransforms[0] : "";
+			switch(currentTransform){
+				case "matrix":
+					// generic transformation
+					//
+					// matrix:
+					// m11        m12
+					//
+					// m21        m22
+					//
+					ct = transforms[i].replace(/matrix\(|\)/g, "");
+					var matrix = ct.split(",");
+					m11 = props[0]*matrix[0] + props[1]*matrix[2];
+					m12 = props[0]*matrix[1] + props[1]*matrix[3];
+					m21 = props[2]*matrix[0] + props[3]*matrix[2];
+					m22 = props[2]*matrix[1] + props[3]*matrix[3];
+					tx = props[4] + matrix[4];
+					ty = props[5] + matrix[5];
+				break;
+				case "rotate":
+					// rotate
+					//
+					// rotation angle:
+					// a (rad, deg or grad)
+					//
+					// matrix:
+					// cos(a)     -sin(a)
+					//
+					// sin(a)     cos(a)
+					//
+					ct = transforms[i].replace(/rotate\(|\)/g, "");
+					toRad = ct.indexOf("deg") != -1 ? degToRad : ct.indexOf("grad") != -1 ? gradToRad : 1;
+					a = parseFloat(ct)*toRad;
+					var s = sin(a),
+						c = cos(a)
+					;
+					m11 = props[0]*c + props[1]*s;
+					m12 = -props[0]*s + props[1]*c;
+					m21 = props[2]*c + props[3]*s;
+					m22 = -props[2]*s + props[3]*c;
+				break;
+				case "skewX":
+					// skewX
+					//
+					// skew angle:
+					// a (rad, deg or grad)
+					//
+					// matrix:
+					// 1          tan(a)
+					//
+					// 0          1
+					//
+					ct = transforms[i].replace(/skewX\(|\)/g, "");
+					toRad = ct.indexOf("deg") != -1 ? degToRad : ct.indexOf("grad") != -1 ? gradToRad : 1;
+					var ta = tan(parseFloat(ct)*toRad);
+					m11 = props[0];
+					m12 = props[0]*ta + props[1];
+					m21 = props[2];
+					m22 = props[2]*ta + props[3];
+				break;
+				case "skewY":
+					// skewY
+					//
+					// skew angle:
+					// a (rad, deg or grad)
+					//
+					// matrix:
+					// 1          0
+					//
+					// tan(a)     1
+					//
+					ct = transforms[i].replace(/skewY\(|\)/g, "");
+					toRad = ct.indexOf("deg") != -1 ? degToRad : ct.indexOf("grad") != -1 ? gradToRad : 1;
+					ta = tan(parseFloat(ct)*toRad);
+					m11 = props[0] + props[1]*ta;
+					m12 = props[1];
+					m21 = props[2] + props[3]*ta;
+					m22 = props[3];
+				break;
+				case "skew":
+					// skew
+					//
+					// skew angles:
+					// a0 (rad, deg or grad)
+					// a1 (rad, deg or grad)
+					//
+					// matrix:
+					// 1          tan(a0)
+					//
+					// tan(a1)    1
+					//
+					ct = transforms[i].replace(/skew\(|\)/g, "");
+					var skewAry = ct.split(",");
+					skewAry[1] = skewAry[1] || "0";
+					toRad = skewAry[0].indexOf("deg") != -1 ? degToRad : skewAry[0].indexOf("grad") != -1 ? gradToRad : 1;
+					toRad1 = skewAry[1].indexOf("deg") != -1 ? degToRad : skewAry[1].indexOf("grad") != -1 ? gradToRad : 1;
+					var a0 = tan(parseFloat(skewAry[0])*toRad),
+						a1 = tan(parseFloat(skewAry[1])*toRad1)
+					;
+					m11 = props[0] + props[1]*a1;
+					m12 = props[0]*a0 + props[1];
+					m21 = props[2]+ props[3]*a1;
+					m22 = props[2]*a0 + props[3];
+				break;
+				case "scaleX":
+					// scaleX
+					//
+					// scale factor:
+					// sx
+					//
+					// matrix:
+					// sx         0
+					//
+					// 0          1
+					//
+					ct = parseFloat(transforms[i].replace(/scaleX\(|\)/g, "")) || 1;
+					m11 = props[0]*ct;
+					m12 = props[1];
+					m21 = props[2]*ct;
+					m22 = props[3];
+				break;
+				case "scaleY":
+					// scaleY
+					//
+					// scale factor:
+					// sy
+					//
+					// matrix:
+					// 1          0
+					//
+					// 0          sy
+					//
+					ct = parseFloat(transforms[i].replace(/scaleY\(|\)/g, "")) || 1;
+					m11 = props[0];
+					m12 = props[1]*ct;
+					m21 = props[2];
+					m22 = props[3]*ct;
+				break;
+				case "scale":
+					// scale
+					//
+					// scale factor:
+					// sx, sy
+					//
+					// matrix:
+					// sx         0
+					//
+					// 0          sy
+					//
+					ct = transforms[i].replace(/scale\(|\)/g, "");
+					var scaleAry = ct.split(",");
+					scaleAry[1] = scaleAry[1] || scaleAry[0];
+					m11 = props[0]*scaleAry[0];
+					m12 = props[1]*scaleAry[1];
+					m21 = props[2]*scaleAry[0];
+					m22 = props[3]*scaleAry[1];
+				break;
+				case "translateX":
+					ct = parseInt(transforms[i].replace(/translateX\(|\)/g, "")) || 1;
+					m11 = props[0];
+					m12 = props[1];
+					m21 = props[2];
+					m22 = props[3];
+					tx = toPx(ct);
+					tx && attr(n, "dojo-transform-matrix-tx", tx);
+				break;
+				case "translateY":
+					ct = parseInt(transforms[i].replace(/translateY\(|\)/g, "")) || 1;
+					m11 = props[0];
+					m12 = props[1];
+					m21 = props[2];
+					m22 = props[3];
+					ty = toPx(ct);
+					ty && attr(n, "dojo-transform-matrix-ty", ty);
+				break;
+				case "translate":
+					ct = transforms[i].replace(/translate\(|\)/g, "");
+					m11 = props[0];
+					m12 = props[1];
+					m21 = props[2];
+					m22 = props[3];
+					var translateAry = ct.split(",");
+					translateAry[0] = parseInt(toPx(translateAry[0])) || 0;
+					translateAry[1] = parseInt(toPx(translateAry[1])) || 0;
+					tx = translateAry[0];
+					ty = translateAry[1];
+					tx && attr(n, "dojo-transform-matrix-tx", tx);
+					ty && attr(n, "dojo-transform-matrix-ty", ty);
+				break;
+			}
+			props = [m11, m12, m21, m22, tx, ty];
+		}
+		// test
+		var Bx = min(w*m11 + h*m12, min(min(w*m11, h*m12), 0)),
+			By = min(w*m21 + h*m22, min(min(w*m21, h*m22), 0))
+		;
+		dx = -Bx;
+		dy = -By;
+		if(dojo.isIE < 8){
+			// on IE < 8 the node must have hasLayout = true
+			n.style.zoom = "1";
+			if(newPosition != "absolute"){
+				var parentWidth = ds(node.parentNode, "width"),
+					tw = abs(w*m11),
+					th = abs(h*m12),
+					wMax = max(tw + th, max(max(th, tw), 0))
+				;
+				dx -= (wMax - w) / 2 - (parentWidth > wMax ? 0 : (wMax - parentWidth) / 2);
+			}
+		}else if(dojo.isIE == 8){
+			// IE8 bug, a filter is applied to positioned descendants
+			// only if the parent has z-index
+			ds(n, "zIndex") == "auto" && (n.style.zIndex = "0");
+		}
+
+		try{
+			hasMatrix = !!n.filters.item(mstr);
+		}catch(e){
+			hasMatrix = false;
+		}
+		if(hasMatrix){
+			n.filters.item(mstr).M11 = m11;
+			n.filters.item(mstr).M12 = m12;
+			n.filters.item(mstr).M21 = m21;
+			n.filters.item(mstr).M22 = m22;
+			// use 'nearest' for a faster transform
+			n.filters.item(mstr).filterType = 'bilinear';
+			n.filters.item(mstr).Dx = 0;
+			n.filters.item(mstr).Dy = 0;
+			n.filters.item(mstr).sizingMethod = 'auto expand';
+		}else{
+			n.style.filter +=
+				" progid:" + mstr + "(M11=" + m11 +
+				",M12=" + m12 +
+				",M21=" + m21 +
+				",M22=" + m22 +
+				",FilterType='bilinear',Dx=0,Dy=0,sizingMethod='auto expand')"
+			;
+		}
+		tx = parseInt(attr(n, "dojo-transform-matrix-tx") || "0");
+		ty = parseInt(attr(n, "dojo-transform-matrix-ty") || "0");
+
+		// transform origin
+		var toAry = attr(n, "dojo-transform-origin").split(" ");
+
+		for(i = 0; i < 2; i++){
+			toAry[i] = toAry[i] || "50%";
+		}
+		xc = (toAry[0].toString().indexOf("%") != -1) ? w * parseInt(toAry[0]) * .01 : toAry[0];
+		yc = (toAry[1].toString().indexOf("%") != -1) ? h * parseInt(toAry[1]) * .01 : toAry[1];
+		if(hasAttr(n, "dojo-startX")){
+			x0 = parseInt(attr(n, "dojo-startX"));
+		}else{
+			x0 = parseInt(ds(n, "left"));
+			attr(n, "dojo-startX", newPosition == "absolute" ? x0 : "0");
+		}
+		if(hasAttr(n, "dojo-startY")){
+			y0 = parseInt(attr(n, "dojo-startY"));
+		}else{
+			y0 = parseInt(ds(n, "top"));
+			attr(n, "dojo-startY", newPosition == "absolute" ? y0 : "0");
+		}
+		ds(n, {
+			position: newPosition,
+			left: x0 - parseInt(dx) + parseInt(xc) - ((parseInt(xc) - tx)*m11 + (parseInt(yc) - ty)*m12) + "px",
+			top:  y0 - parseInt(dy) + parseInt(yc) - ((parseInt(xc) - tx)*m21 + (parseInt(yc) - ty)*m22) + "px"
+		});
+	},
+	_getTransformFilter: function(/*DomNode*/ node){
+		try{
+			var n = dojo.byId(node),
+				item = n.filters.item(0)
+			;
+			return "matrix(" + item.M11 + ", " + item.M12 + ", " + item.M21 + ", " +
+				item.M22 + ", " + (dojo.attr(node, "dojo-transform-tx") || "0") + ", " + (dojo.attr(node, "dojo-transform-ty") || "0") + ")";
+		}catch(e){
+			return "matrix(1, 0, 0, 1, 0, 0)";
+		}
+	},
+	setTransform: function(){
+		this._notSupported();
+	},
+	setTransformOrigin: function(){
+		this._notSupported();
+	}
+});
+
+dojox.html["ext-dojo"].style.init();
\ No newline at end of file
diff --git a/dojox/html/format.js b/dojox/html/format.js
old mode 100644
new mode 100755
index d766e46..cd87bb5
--- a/dojox/html/format.js
+++ b/dojox/html/format.js
@@ -1,340 +1,477 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.html.format"]){
-dojo._hasResource["dojox.html.format"]=true;
 dojo.provide("dojox.html.format");
+
 dojo.require("dojox.html.entities");
+
 (function(){
-dojox.html.format.prettyPrint=function(_1,_2,_3,_4,_5){
-var _6=[];
-var _7=0;
-var _8=[];
-var _9="\t";
-var _a="";
-var _b=[];
-var i;
-var _c=/[=]([^"']+?)(\s|>)/g;
-var _d=/style=("[^"]*"|'[^']*'|\S*)/gi;
-var _e=/\s\w+=("[^"]*"|'[^']*'|\S*)/gi;
-if(_2&&_2>0&&_2<10){
-_9="";
-for(i=0;i<_2;i++){
-_9+=" ";
-}
-}
-var _f=dojo.doc.createElement("div");
-_f.innerHTML=_1;
-var _10=dojox.html.entities.encode;
-var _11=dojox.html.entities.decode;
-var _12=function(tag){
-switch(tag){
-case "a":
-case "b":
-case "strong":
-case "s":
-case "strike":
-case "i":
-case "u":
-case "em":
-case "sup":
-case "sub":
-case "span":
-case "font":
-case "big":
-case "cite":
-case "q":
-case "small":
-return true;
-default:
-return false;
-}
-};
-var div=_f.ownerDocument.createElement("div");
-var _13=function(_14){
-var _15=_14.cloneNode(false);
-div.appendChild(_15);
-var _16=div.innerHTML;
-div.innerHTML="";
-return _16;
-};
-var _17=function(){
-var i,txt="";
-for(i=0;i<_7;i++){
-txt+=_9;
-}
-return txt.length;
-};
-var _18=function(){
-var i;
-for(i=0;i<_7;i++){
-_6.push(_9);
-}
-};
-var _19=function(){
-_6.push("\n");
-};
-var _1a=function(n){
-_a+=_10(n.nodeValue,_4);
-};
-var _1b=function(txt){
-var i;
-var _1c;
-var _1d=txt.split("\n");
-for(i=0;i<_1d.length;i++){
-_1d[i]=dojo.trim(_1d[i]);
-}
-txt=_1d.join(" ");
-txt=dojo.trim(txt);
-if(txt!==""){
-var _1e=[];
-if(_3&&_3>0){
-var _1f=_17();
-var _20=_3;
-if(_3>_1f){
-_20-=_1f;
-}
-while(txt){
-if(txt.length>_3){
-for(i=_20;(i>0&&txt.charAt(i)!==" ");i--){
-}
-if(!i){
-for(i=_20;(i<txt.length&&txt.charAt(i)!==" ");i++){
-}
-}
-var _21=txt.substring(0,i);
-_21=dojo.trim(_21);
-txt=dojo.trim(txt.substring((i==txt.length)?txt.length:i+1,txt.length));
-if(_21){
-_1c="";
-for(i=0;i<_7;i++){
-_1c+=_9;
-}
-_21=_1c+_21+"\n";
-}
-_1e.push(_21);
-}else{
-_1c="";
-for(i=0;i<_7;i++){
-_1c+=_9;
-}
-txt=_1c+txt+"\n";
-_1e.push(txt);
-txt=null;
-}
-}
-return _1e.join("");
-}else{
-_1c="";
-for(i=0;i<_7;i++){
-_1c+=_9;
-}
-txt=_1c+txt+"\n";
-return txt;
-}
-}else{
-return "";
-}
-};
-var _22=function(txt){
-if(txt){
-txt=txt.replace(/"/gi,"\"");
-txt=txt.replace(/>/gi,">");
-txt=txt.replace(/</gi,"<");
-txt=txt.replace(/&/gi,"&");
-}
-return txt;
-};
-var _23=function(txt){
-if(txt){
-txt=_22(txt);
-var i,t,c,_24;
-var _25=0;
-var _26=txt.split("\n");
-var _27=[];
-for(i=0;i<_26.length;i++){
-var _28=_26[i];
-var _29=(_28.indexOf("\n")>-1);
-_28=dojo.trim(_28);
-if(_28){
-var _2a=_25;
-for(c=0;c<_28.length;c++){
-var ch=_28.charAt(c);
-if(ch==="{"){
-_25++;
-}else{
-if(ch==="}"){
-_25--;
-_2a=_25;
-}
-}
-}
-_24="";
-for(t=0;t<_7+_2a;t++){
-_24+=_9;
-}
-_27.push(_24+_28+"\n");
-}else{
-if(_29&&i===0){
-_27.push("\n");
-}
-}
-}
-txt=_27.join("");
-}
-return txt;
-};
-var _2b=function(_2c){
-var _2d=_2c.nodeName.toLowerCase();
-var _2e=dojo.trim(_13(_2c));
-var tag=_2e.substring(0,_2e.indexOf(">")+1);
-tag=tag.replace(_c,"=\"$1\"$2");
-tag=tag.replace(_d,function(_2f){
-var sL=_2f.substring(0,6);
-var _30=_2f.substring(6,_2f.length);
-var _31=_30.charAt(0);
-_30=dojo.trim(_30.substring(1,_30.length-1));
-_30=_30.split(";");
-var _32=[];
-dojo.forEach(_30,function(s){
-s=dojo.trim(s);
-if(s){
-s=s.substring(0,s.indexOf(":")).toLowerCase()+s.substring(s.indexOf(":"),s.length);
-_32.push(s);
-}
-});
-_32=_32.sort();
-_30=_32.join("; ");
-var ts=dojo.trim(_30);
-if(!ts||ts===";"){
-return "";
-}else{
-_30+=";";
-return sL+_31+_30+_31;
-}
-});
-var _33=[];
-tag=tag.replace(_e,function(_34){
-_33.push(dojo.trim(_34));
-return "";
-});
-_33=_33.sort();
-tag="<"+_2d;
-if(_33.length){
-tag+=" "+_33.join(" ");
-}
-if(_2e.indexOf("</")!=-1){
-_8.push(_2d);
-tag+=">";
-}else{
-if(_5){
-tag+=" />";
-}else{
-tag+=">";
-}
-_8.push(false);
-}
-var _35=_12(_2d);
-_b.push(_35);
-if(_a&&!_35){
-_6.push(_1b(_a));
-_a="";
-}
-if(!_35){
-_18();
-_6.push(tag);
-_19();
-_7++;
-}else{
-_a+=tag;
-}
-};
-var _36=function(){
-var _37=_b.pop();
-if(_a&&!_37){
-_6.push(_1b(_a));
-_a="";
-}
-var ct=_8.pop();
-if(ct){
-ct="</"+ct+">";
-if(!_37){
-_7--;
-_18();
-_6.push(ct);
-_19();
-}else{
-_a+=ct;
-}
-}else{
-_7--;
-}
-};
-var _38=function(n){
-var _39=_11(n.nodeValue,_4);
-_18();
-_6.push("<!--");
-_19();
-_7++;
-_6.push(_1b(_39));
-_7--;
-_18();
-_6.push("-->");
-_19();
-};
-var _3a=function(_3b){
-var _3c=_3b.childNodes;
-if(_3c){
-var i;
-for(i=0;i<_3c.length;i++){
-var n=_3c[i];
-if(n.nodeType===1){
-var tg=dojo.trim(n.tagName.toLowerCase());
-if(dojo.isIE&&n.parentNode!=_3b){
-continue;
-}
-if(tg&&tg.charAt(0)==="/"){
-continue;
-}else{
-_2b(n);
-if(tg==="script"){
-_6.push(_23(n.innerHTML));
-}else{
-if(tg==="pre"){
-var _3d=n.innerHTML;
-if(dojo.isMoz){
-_3d=_3d.replace("<br>","\n");
-_3d=_3d.replace("<pre>","");
-_3d=_3d.replace("</pre>","");
-}
-if(_3d.charAt(_3d.length-1)!=="\n"){
-_3d+="\n";
-}
-_6.push(_3d);
-}else{
-_3a(n);
-}
-}
-_36();
-}
-}else{
-if(n.nodeType===3||n.nodeType===4){
-_1a(n);
-}else{
-if(n.nodeType===8){
-_38(n);
-}
-}
-}
-}
-}
-};
-_3a(_f);
-return _6.join("");
-};
+	dojox.html.format.prettyPrint = function(html/*String*/, indentBy /*Integer?*/, maxLineLength /*Integer?*/, map/*Array?*/, /*boolean*/ xhtml){
+		// summary:
+		//		Function for providing a 'pretty print' version of HTML content from
+		//		the provided string.  It's nor perfect by any means, but it does
+		//		a 'reasonable job'.
+		// html: String
+		//		The string of HTML to try and generate a 'pretty' formatting.
+		// indentBy:  Integer
+		//		Optional input for the number of spaces to use when indenting.  
+		//		If not defined, zero, negative, or greater than 10, will just use tab 
+		//		as the indent.
+		// maxLineLength: Integer
+		//		Optional input for the number of characters a text line should use in 
+		//		the document, including the indent if possible.
+		// map:	Array
+		//		Optional array of entity mapping characters to use when processing the 
+		//		HTML Text content.  By default it uses the default set used by the 
+		//		dojox.html.entities.encode function.
+		// xhtml: boolean
+		//		Optional parameter that declares that the returned HTML should try to be 'xhtml' compatible.
+		//		This means normally unclosed tags are terminated with /> instead of >.  Example: <hr> -> <hr />
+		var content = [];
+		var indentDepth = 0;
+		var closeTags = [];
+		var iTxt = "\t";
+		var textContent = "";
+		var inlineStyle = [];
+		var i;
+
+		// Compile regexps once for this call.
+		var rgxp_fixIEAttrs = /[=]([^"']+?)(\s|>)/g;
+		var rgxp_styleMatch = /style=("[^"]*"|'[^']*'|\S*)/gi;
+		var rgxp_attrsMatch = /\s\w+=("[^"]*"|'[^']*'|\S*)/gi;
+
+		// Check to see if we want to use spaces for indent instead
+		// of tab.
+		if(indentBy && indentBy > 0 && indentBy < 10){
+			iTxt = "";
+			for(i = 0; i < indentBy; i++){
+				iTxt += " ";
+			}
+		}
+
+		//Build the content outside of the editor so we can walk 
+		//via DOM and build a 'pretty' output.
+		var contentDiv = dojo.doc.createElement("div");
+		contentDiv.innerHTML = html;
+
+		// Use the entity encode/decode functions, they cache on the map,
+		// so it won't multiprocess a map.
+		var encode = dojox.html.entities.encode;
+		var decode = dojox.html.entities.decode;
+
+		/** Define a bunch of formatters to format the output. **/
+		var isInlineFormat = function(tag){
+			// summary:
+			//		Function to determine if the current tag is an inline
+			//		element that does formatting, as we don't want to 
+			//		break/indent around it, as it can screw up text.
+			// tag:
+			//		The tag to examine
+			switch(tag){
+				case "a":
+				case "b":
+				case "strong":
+				case "s":
+				case "strike":
+				case "i":
+				case "u":
+				case "em":
+				case "sup":
+				case "sub":
+				case "span":
+				case "font":
+				case "big":
+				case "cite":
+				case "q":
+				case "small":
+					return true;
+				default:
+					return false;
+			}
+		};
+
+		//Create less divs.
+		var div = contentDiv.ownerDocument.createElement("div");
+		var outerHTML =  function(node){
+			// summary:
+			//		Function to return the outer HTML of a node.
+			//		Yes, IE has a function like this, but using cloneNode
+			//		allows avoiding looking at any child nodes, because in this
+			//		case, we don't want them.
+			var clone = node.cloneNode(false);
+			div.appendChild(clone);
+			var html = div.innerHTML;
+			div.innerHTML = "";
+			return html;
+		};
+
+		var sizeIndent = function(){
+			var i, txt = "";
+			for(i = 0; i < indentDepth; i++){
+				txt += iTxt;
+			}
+			return txt.length;
+		}
+
+		var indent = function(){
+			// summary:
+			//		Function to handle indent depth.
+			var i;
+			for(i = 0; i < indentDepth; i++){
+				content.push(iTxt);
+			}
+		};
+		var newline = function(){
+			// summary:
+			//		Function to handle newlining.
+			content.push("\n");
+		};
+
+		var processTextNode = function(n){
+			// summary:
+			//		Function to process the text content for doc
+			//		insertion
+			// n:
+			//		The text node to process.
+			textContent += encode(n.nodeValue, map);
+		};
+
+		var formatText = function(txt){
+			// summary:
+			//		Function for processing the text content encountered up to a
+			//		point and inserting it into the formatted document output.
+			// txt:
+			//		The text to format.
+			var i;
+			var _iTxt;
+
+			// Clean up any indention organization since we're going to rework it
+			// anyway.
+			var _lines = txt.split("\n");
+			for(i = 0; i < _lines.length; i++){
+				_lines[i] = dojo.trim(_lines[i]);
+			}
+			txt = _lines.join(" ");
+			txt = dojo.trim(txt);
+			if(txt !== ""){
+				var lines = [];
+				if(maxLineLength && maxLineLength > 0){
+					var indentSize = sizeIndent();
+					var maxLine = maxLineLength;
+					if(maxLineLength > indentSize){
+						maxLine -= indentSize;
+					}
+					while(txt){
+						if(txt.length > maxLineLength){
+							for(i = maxLine; (i > 0 && txt.charAt(i) !== " "); i--){
+								// Do nothing, we're just looking for a space to split at.
+							}
+							if(!i){
+								// Couldn't find a split going back, so go forward.
+								for(i = maxLine; (i < txt.length && txt.charAt(i) !== " "); i++){
+									// Do nothing, we're just looking for a space to split at.
+								}
+							}
+							var line = txt.substring(0, i);
+							line = dojo.trim(line);
+							// Shift up the text string to the next chunk.
+							txt = dojo.trim(txt.substring((i == txt.length)?txt.length:i + 1, txt.length));
+							if(line){
+								_iTxt = "";
+								for(i = 0; i < indentDepth; i++){
+									_iTxt += iTxt;
+								}
+								line = _iTxt + line + "\n";
+							}
+							lines.push(line);
+						}else{
+							// Line is shorter than out desired length, so use it.
+							// as/is
+							_iTxt = "";
+							for(i = 0; i < indentDepth; i++){
+								_iTxt += iTxt;
+							}
+							txt = _iTxt + txt + "\n";
+							lines.push(txt);
+							txt = null;
+						}
+					}
+					return lines.join("");
+				}else{
+					_iTxt = "";
+					for(i = 0; i < indentDepth; i++){
+						_iTxt += iTxt;
+					}
+					txt = _iTxt + txt + "\n";
+					return txt;
+				}
+			}else{
+				return "";
+			}
+		};
+
+		var processScriptText = function(txt){
+			// summary:
+			//		Function to clean up potential escapes in the script code.
+			if(txt){
+				txt = txt.replace(/"/gi, "\"");
+				txt = txt.replace(/>/gi, ">");
+				txt = txt.replace(/</gi, "<");
+				txt = txt.replace(/&/gi, "&");
+			}
+			return txt;
+		};
+
+		var formatScript = function(txt){
+			// summary:
+			//		Function to rudimentary formatting of script text.
+			//		Not perfect, but it helps get some level of organization 
+			//		in there.
+			// txt:
+			//		The script text to try to format a bit.
+			if(txt){
+				txt = processScriptText(txt);
+				var i, t, c, _iTxt;
+				var indent = 0;
+				var scriptLines = txt.split("\n");
+				var newLines = [];
+				for (i = 0; i < scriptLines.length; i++){
+					var line = scriptLines[i];
+					var hasNewlines = (line.indexOf("\n") > -1);
+					line = dojo.trim(line);
+					if(line){
+						var iLevel = indent;
+						// Not all blank, so we need to process.
+						for(c = 0; c < line.length; c++){
+							var ch = line.charAt(c);
+							if(ch === "{"){
+								indent++;
+							}else if(ch === "}"){
+								indent--;
+								// We want to back up a bit before the 
+								// line is written.
+								iLevel = indent;
+							}
+						}
+						_iTxt = "";
+						for(t = 0; t < indentDepth + iLevel; t++){
+							_iTxt += iTxt;
+						}
+						newLines.push(_iTxt + line + "\n");
+					}else if(hasNewlines && i === 0){
+						// Just insert a newline for blank lines as 
+						// long as it's not the first newline (we 
+						// already inserted that in the openTag handler)
+						newLines.push("\n");
+					}
+
+				}
+				// Okay, create the script text, hopefully reasonably 
+				// formatted.
+				txt = newLines.join("");
+			}
+			return txt;
+		};
+
+		var openTag = function(node){
+			// summary:
+			//		Function to open a new tag for writing content.
+			var name = node.nodeName.toLowerCase();
+			// Generate the outer node content (tag with attrs)
+			var nText = dojo.trim(outerHTML(node));
+			var tag = nText.substring(0, nText.indexOf(">") + 1);
+
+			// Also thanks to IE, we need to check for quotes around 
+			// attributes and insert if missing.
+			tag = tag.replace(rgxp_fixIEAttrs,'="$1"$2');
+
+			// And lastly, thanks IE for changing style casing and end
+			// semi-colon and webkit adds spaces, so lets clean it up by
+			// sorting, etc, while we're at it.
+			tag = tag.replace(rgxp_styleMatch, function(match){
+				var sL = match.substring(0,6);
+				var style = match.substring(6, match.length);
+				var closure = style.charAt(0);
+				style = dojo.trim(style.substring(1,style.length -1));
+				style = style.split(";");
+				var trimmedStyles = [];
+				dojo.forEach(style, function(s){
+					s = dojo.trim(s);
+					if(s){
+						// Lower case the style name, leave the value alone.  Mainly a fixup for IE.
+						s = s.substring(0, s.indexOf(":")).toLowerCase() + s.substring(s.indexOf(":"), s.length);
+						trimmedStyles.push(s);
+					}
+				});
+				trimmedStyles = trimmedStyles.sort();
+				
+				// Reassemble and return the styles in sorted order.
+				style = trimmedStyles.join("; ");
+				var ts = dojo.trim(style);
+				if(!ts || ts === ";"){
+					// Just remove any style attrs that are empty.
+					return "";
+				}else{
+					style += ";";
+					return sL + closure + style + closure;
+				}
+			});
+
+			// Try and sort the attributes while we're at it.
+			var attrs = [];
+			tag = tag.replace(rgxp_attrsMatch, function(attr){
+				attrs.push(dojo.trim(attr));
+				return "";
+			});
+			attrs = attrs.sort();
+
+			// Reassemble the tag with sorted attributes!
+			tag = "<" + name;
+			if(attrs.length){
+				 tag += " " + attrs.join(" ");
+			}
+
+			// Determine closure status.  If xhtml, 
+			// then close the tag properly as needed.
+			if(nText.indexOf("</") != -1){
+				closeTags.push(name);
+				tag += ">";
+			}else{
+				if(xhtml){
+					tag += " />";
+				}else{
+					tag += ">";
+				}
+				closeTags.push(false);
+			}
+
+			var inline = isInlineFormat(name);
+			inlineStyle.push(inline); 
+			if(textContent && !inline){
+				// Process any text content we have that occurred 
+				// before the open tag of a non-inline.
+				content.push(formatText(textContent));
+				textContent = "";
+			}
+
+			// Determine if this has a closing tag or not!
+			if(!inline){
+				indent();
+				content.push(tag);
+				newline();
+				indentDepth++;
+			}else{
+				textContent += tag;
+			}
+			
+		};
+		
+		var closeTag = function(){
+			// summary:
+			//		Function to close out a tag if necessary.
+			var inline = inlineStyle.pop();
+			if(textContent && !inline){
+				// Process any text content we have that occurred 
+				// before the close tag.
+				content.push(formatText(textContent));
+				textContent = "";
+			}
+			var ct = closeTags.pop();
+			if(ct){
+				ct = "</" + ct + ">";
+				if(!inline){
+					indentDepth--;
+					indent();
+					content.push(ct);
+					newline();
+				}else{
+					textContent += ct;
+				}
+			}else{
+				indentDepth--;	
+			}
+		};
+
+		var processCommentNode = function(n){
+			// summary:
+			//		Function to handle processing a comment node.
+			// n:
+			//		The comment node to process.
+
+			//Make sure contents aren't double-encoded.
+			var commentText = decode(n.nodeValue, map);
+			indent();
+			content.push("<!--");
+			newline();
+			indentDepth++;
+			content.push(formatText(commentText));
+			indentDepth--;
+			indent();
+			content.push("-->");
+			newline();
+		};
+
+		var processNode = function(node) {
+			// summary:
+			//		Entrypoint for processing all the text!
+			var children = node.childNodes;
+			if(children){
+				var i;
+				for(i = 0; i < children.length; i++){
+					var n = children[i];
+					if(n.nodeType === 1){
+						var tg = dojo.trim(n.tagName.toLowerCase());
+                        if(dojo.isIE && n.parentNode != node){
+							// IE is broken.  DOMs are supposed to be a tree.  
+							// But in the case of malformed HTML, IE generates a graph
+							// meaning one node ends up with multiple references 
+							// (multiple parents).  This is totally wrong and invalid, but
+							// such is what it is.  We have to keep track and check for 
+							// this because otherwise the source output HTML will have dups.
+							continue;
+						}
+						if(tg && tg.charAt(0) === "/"){
+							// IE oddity.  Malformed HTML can put in odd tags like:
+							// </ >, </span>.  It treats a mismatched closure as a new
+							// start tag.  So, remove them.
+							continue;
+						}else{
+							//Process non-dup, seemingly wellformed elements!
+							openTag(n);
+							if(tg === "script"){
+								content.push(formatScript(n.innerHTML));
+							}else if(tg === "pre"){
+								var preTxt = n.innerHTML;
+								if(dojo.isMoz){
+									//Mozilla screws this up, so fix it up.
+									preTxt = preTxt.replace("<br>", "\n");
+									preTxt = preTxt.replace("<pre>", "");
+									preTxt = preTxt.replace("</pre>", "");
+								}
+								// Add ending newline, if needed.
+								if(preTxt.charAt(preTxt.length - 1) !== "\n"){
+									preTxt += "\n";
+								}
+								content.push(preTxt);
+							}else{
+								processNode(n);
+							}
+							closeTag();
+						}
+					}else if(n.nodeType === 3 || n.nodeType === 4){
+						processTextNode(n);
+					}else if(n.nodeType === 8){
+						processCommentNode(n);
+					}
+				}
+			}
+		};
+
+		//Okay, finally process the input string.
+		processNode(contentDiv);
+		if(textContent){
+			// Insert any trailing text.  See: #10854
+			content.push(formatText(textContent));
+			textContent = "";
+		}
+		return content.join(""); //String
+	};
 })();
-}
+
diff --git a/dojox/html/metrics.js b/dojox/html/metrics.js
index b4804f6..5b59f46 100644
--- a/dojox/html/metrics.js
+++ b/dojox/html/metrics.js
@@ -1,141 +1,176 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.html.metrics"]){
-dojo._hasResource["dojox.html.metrics"]=true;
 dojo.provide("dojox.html.metrics");
+
 (function(){
-var _1=dojox.html.metrics;
-_1.getFontMeasurements=function(){
-var _2={"1em":0,"1ex":0,"100%":0,"12pt":0,"16px":0,"xx-small":0,"x-small":0,"small":0,"medium":0,"large":0,"x-large":0,"xx-large":0};
-if(dojo.isIE){
-dojo.doc.documentElement.style.fontSize="100%";
-}
-var _3=dojo.doc.createElement("div");
-var ds=_3.style;
-ds.position="absolute";
-ds.left="-100px";
-ds.top="0";
-ds.width="30px";
-ds.height="1000em";
-ds.border="0";
-ds.margin="0";
-ds.padding="0";
-ds.outline="0";
-ds.lineHeight="1";
-ds.overflow="hidden";
-dojo.body().appendChild(_3);
-for(var p in _2){
-ds.fontSize=p;
-_2[p]=Math.round(_3.offsetHeight*12/16)*16/12/1000;
-}
-dojo.body().removeChild(_3);
-_3=null;
-return _2;
-};
-var _4=null;
-_1.getCachedFontMeasurements=function(_5){
-if(_5||!_4){
-_4=_1.getFontMeasurements();
-}
-return _4;
-};
-var _6=null,_7={};
-_1.getTextBox=function(_8,_9,_a){
-var m;
-if(!_6){
-m=_6=dojo.doc.createElement("div");
-m.style.position="absolute";
-m.style.left="0px";
-m.style.top="-10000px";
-dojo.body().appendChild(m);
-}else{
-m=_6;
-}
-m.className="";
-m.style.border="0";
-m.style.margin="0";
-m.style.padding="0";
-m.style.outline="0";
-if(arguments.length>1&&_9){
-for(var i in _9){
-if(i in _7){
-continue;
-}
-m.style[i]=_9[i];
-}
-}
-if(arguments.length>2&&_a){
-m.className=_a;
-}
-m.innerHTML=_8;
-return dojo.marginBox(m);
-};
-var _b={w:16,h:16};
-_1.getScrollbar=function(){
-return {w:_b.w,h:_b.h};
-};
-_1._fontResizeNode=null;
-_1.initOnFontResize=function(_c){
-var f=_1._fontResizeNode=dojo.doc.createElement("iframe");
-var fs=f.style;
-fs.position="absolute";
-fs.width="5em";
-fs.height="10em";
-fs.top="-10000px";
-if(dojo.isIE){
-f.onreadystatechange=function(){
-if(f.contentWindow.document.readyState=="complete"){
-f.onresize=f.contentWindow.parent[dojox._scopeName].html.metrics._fontresize;
-}
-};
-}else{
-f.onload=function(){
-f.contentWindow.onresize=f.contentWindow.parent[dojox._scopeName].html.metrics._fontresize;
-};
-}
-f.setAttribute("src","javascript:'<html><head><script>if(\"loadFirebugConsole\" in window){window.loadFirebugConsole();}</script></head><body></body></html>'");
-dojo.body().appendChild(f);
-_1.initOnFontResize=function(){
-};
-};
-_1.onFontResize=function(){
-};
-_1._fontresize=function(){
-_1.onFontResize();
-};
-dojo.addOnUnload(function(){
-var f=_1._fontResizeNode;
-if(f){
-if(dojo.isIE&&f.onresize){
-f.onresize=null;
-}else{
-if(f.contentWindow&&f.contentWindow.onresize){
-f.contentWindow.onresize=null;
-}
-}
-_1._fontResizeNode=null;
-}
-});
-dojo.addOnLoad(function(){
-try{
-var n=dojo.doc.createElement("div");
-n.style.cssText="top:0;left:0;width:100px;height:100px;overflow:scroll;position:absolute;visibility:hidden;";
-dojo.body().appendChild(n);
-_b.w=n.offsetWidth-n.clientWidth;
-_b.h=n.offsetHeight-n.clientHeight;
-dojo.body().removeChild(n);
-delete n;
-}
-catch(e){
-}
-if("fontSizeWatch" in dojo.config&&!!dojo.config.fontSizeWatch){
-_1.initOnFontResize();
-}
-});
+	var dhm = dojox.html.metrics;
+
+	//	derived from Morris John's emResized measurer
+	dhm.getFontMeasurements = function(){
+		//	summary
+		//	Returns an object that has pixel equivilents of standard font size values.
+		var heights = {
+			'1em':0, '1ex':0, '100%':0, '12pt':0, '16px':0, 'xx-small':0, 'x-small':0,
+			'small':0, 'medium':0, 'large':0, 'x-large':0, 'xx-large':0
+		};
+	
+		if(dojo.isIE){
+			//	we do a font-size fix if and only if one isn't applied already.
+			//	NOTE: If someone set the fontSize on the HTML Element, this will kill it.
+			dojo.doc.documentElement.style.fontSize="100%";
+		}
+	
+		//	set up the measuring node.
+		var div=dojo.doc.createElement("div");
+		var ds = div.style;
+		ds.position="absolute";
+		ds.left="-100px";
+		ds.top="0";
+		ds.width="30px";
+		ds.height="1000em";
+		ds.borderWidth="0";
+		ds.margin="0";
+		ds.padding="0";
+		ds.outline="0";
+		ds.lineHeight="1";
+		ds.overflow="hidden";
+		dojo.body().appendChild(div);
+	
+		//	do the measurements.
+		for(var p in heights){
+			ds.fontSize = p;
+			heights[p] = Math.round(div.offsetHeight * 12/16) * 16/12 / 1000;
+		}
+		
+		dojo.body().removeChild(div);
+		div = null;
+		return heights; 	//	object
+	};
+
+	var fontMeasurements = null;
+	
+	dhm.getCachedFontMeasurements = function(recalculate){
+		if(recalculate || !fontMeasurements){
+			fontMeasurements = dhm.getFontMeasurements();
+		}
+		return fontMeasurements;
+	};
+
+	var measuringNode = null, empty = {};
+	dhm.getTextBox = function(/* String */ text, /* Object */ style, /* String? */ className){
+		var m, s;
+		if(!measuringNode){
+			m = measuringNode = dojo.doc.createElement("div");
+			// Container that we can set contraints on so that it doesn't
+			// trigger a scrollbar.
+			var c = dojo.doc.createElement("div"); 
+			c.appendChild(m);
+			s = c.style;
+			s.overflow='scroll';
+			s.position = "absolute";
+			s.left = "0px";
+			s.top = "-10000px";
+			s.width = "1px";
+			s.height = "1px";
+			s.visibility = "hidden";
+			s.borderWidth = "0";
+			s.margin = "0";
+			s.padding = "0";
+			s.outline = "0";
+			dojo.body().appendChild(c);
+		}else{
+			m = measuringNode;
+		}
+		// reset styles
+		m.className = "";
+		s = m.style;
+		s.borderWidth = "0";
+		s.margin = "0";
+		s.padding = "0";
+		s.outline = "0";
+		// set new style
+		if(arguments.length > 1 && style){
+			for(var i in style){
+				if(i in empty){ continue; }
+				s[i] = style[i];
+			}
+		}
+		// set classes
+		if(arguments.length > 2 && className){
+			m.className = className;
+		}
+		// take a measure
+		m.innerHTML = text;
+		var box = dojo.position(m);
+		// position doesn't report right (reports 1, since parent is 1)
+		// So we have to look at the scrollWidth to get the real width
+		// Height is right.
+		box.w = m.parentNode.scrollWidth;
+		return box;
+	};
+
+	//	determine the scrollbar sizes on load.
+	var scroll={ w:16, h:16 };
+	dhm.getScrollbar=function(){ return { w:scroll.w, h:scroll.h }; };
+
+	dhm._fontResizeNode = null;
+
+	dhm.initOnFontResize = function(interval){
+		var f = dhm._fontResizeNode = dojo.doc.createElement("iframe");
+		var fs = f.style;
+		fs.position = "absolute";
+		fs.width = "5em";
+		fs.height = "10em";
+		fs.top = "-10000px";
+		if(dojo.isIE){
+			f.onreadystatechange = function(){
+				if(f.contentWindow.document.readyState == "complete"){
+					f.onresize = f.contentWindow.parent[dojox._scopeName].html.metrics._fontresize;
+				}
+			};
+		}else{
+			f.onload = function(){
+				f.contentWindow.onresize = f.contentWindow.parent[dojox._scopeName].html.metrics._fontresize;
+			};
+		}
+		//The script tag is to work around a known firebug race condition.  See comments in bug #9046
+		f.setAttribute("src", "javascript:'<html><head><script>if(\"loadFirebugConsole\" in window){window.loadFirebugConsole();}</script></head><body></body></html>'");
+		dojo.body().appendChild(f);
+		dhm.initOnFontResize = function(){};
+	};
+
+	dhm.onFontResize = function(){};
+	dhm._fontresize = function(){
+		dhm.onFontResize();
+	}
+
+	dojo.addOnUnload(function(){
+		// destroy our font resize iframe if we have one
+		var f = dhm._fontResizeNode;
+		if(f){
+			if(dojo.isIE && f.onresize){
+				f.onresize = null;
+			}else if(f.contentWindow && f.contentWindow.onresize){
+				f.contentWindow.onresize = null;
+			}
+			dhm._fontResizeNode = null;
+		}
+	});
+
+	dojo.addOnLoad(function(){
+		// getScrollbar metrics node
+		try{
+			var n=dojo.doc.createElement("div");
+			n.style.cssText = "top:0;left:0;width:100px;height:100px;overflow:scroll;position:absolute;visibility:hidden;";
+			dojo.body().appendChild(n);
+			scroll.w = n.offsetWidth - n.clientWidth;
+			scroll.h = n.offsetHeight - n.clientHeight;
+			dojo.body().removeChild(n);
+			//console.log("Scroll bar dimensions: ", scroll);
+			delete n;
+		}catch(e){}
+
+		// text size poll setup
+		if("fontSizeWatch" in dojo.config && !!dojo.config.fontSizeWatch){
+			dhm.initOnFontResize();
+		}
+	});
 })();
-}
diff --git a/dojox/html/resources/ellipsis.css b/dojox/html/resources/ellipsis.css
index 9922486..d4152e5 100644
--- a/dojox/html/resources/ellipsis.css
+++ b/dojox/html/resources/ellipsis.css
@@ -7,6 +7,7 @@
 	-o-text-overflow: ellipsis;
 	-webkit-text-overflow: ellipsis;
 }
+
 .dojoxEllipsis window {
     width:100%;
     -moz-user-focus:normal;
diff --git a/dojox/html/styles.js b/dojox/html/styles.js
old mode 100644
new mode 100755
index 4229ad9..584ff7e
--- a/dojox/html/styles.js
+++ b/dojox/html/styles.js
@@ -1,188 +1,343 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.html.styles"]){
-dojo._hasResource["dojox.html.styles"]=true;
 dojo.provide("dojox.html.styles");
+	
+	// summary:
+	//		Methods for creating and minipulating dynamic CSS Styles and Style Sheets
+	//
+	// example:
+	//		| dojox.html.createStyle("#myDiv input", "font-size:24px");
+	//			Creates Style #myDiv input, which can now be applied to myDiv, and 
+	//			the inner input will be targeted
+	//		| dojox.html.createStyle(".myStyle", "color:#FF0000");
+	//			Now the class myStyle can be assigned to a node's className
+	
 (function(){
-var _1={};
-var _2={};
-var _3=[];
-var _4=[];
-dojox.html.insertCssRule=function(_5,_6,_7){
-var ss=dojox.html.getDynamicStyleSheet(_7);
-var _8=_5+" {"+_6+"}";
-if(dojo.isIE){
-ss.cssText+=_8;
-}else{
-if(ss.sheet){
-ss.sheet.insertRule(_8,ss._indicies.length);
-}else{
-ss.appendChild(dojo.doc.createTextNode(_8));
-}
-}
-ss._indicies.push(_5+" "+_6);
-return _5;
-};
-dojox.html.removeCssRule=function(_9,_a,_b){
-var ss;
-var _c=-1;
-for(var nm in _1){
-if(_b&&_b!=nm){
-continue;
-}
-ss=_1[nm];
-for(var i=0;i<ss._indicies.length;i++){
-if(_9+" "+_a==ss._indicies[i]){
-_c=i;
-break;
-}
-}
-if(_c>-1){
-break;
-}
-}
-if(!ss){
-return false;
-}
-if(_c==-1){
-return false;
-}
-ss._indicies.splice(_c,1);
-if(dojo.isIE){
-ss.removeRule(_c);
-}else{
-if(ss.sheet){
-ss.sheet.deleteRule(_c);
-}else{
-if(document.styleSheets[0]){
-}
-}
-}
-return true;
-};
-dojox.html.getStyleSheet=function(_d){
-if(_1[_d||"default"]){
-return _1[_d||"default"];
-}
-if(!_d){
-return false;
-}
-var _e=dojox.html.getStyleSheets();
-if(_e[_d]){
-return dojox.html.getStyleSheets()[_d];
-}
-for(var nm in _e){
-if(_e[nm].href&&_e[nm].href.indexOf(_d)>-1){
-return _e[nm];
-}
-}
-return false;
-};
-dojox.html.getDynamicStyleSheet=function(_f){
-if(!_f){
-_f="default";
-}
-if(!_1[_f]){
-if(dojo.doc.createStyleSheet){
-_1[_f]=dojo.doc.createStyleSheet();
-_1[_f].title=_f;
-}else{
-_1[_f]=dojo.doc.createElement("style");
-_1[_f].setAttribute("type","text/css");
-dojo.doc.getElementsByTagName("head")[0].appendChild(_1[_f]);
-}
-_1[_f]._indicies=[];
-}
-return _1[_f];
-};
-dojox.html.enableStyleSheet=function(_10){
-var ss=dojox.html.getStyleSheet(_10);
-if(ss){
-if(ss.sheet){
-ss.sheet.disabled=false;
-}else{
-ss.disabled=false;
-}
-}
-};
-dojox.html.disableStyleSheet=function(_11){
-var ss=dojox.html.getStyleSheet(_11);
-if(ss){
-if(ss.sheet){
-ss.sheet.disabled=true;
-}else{
-ss.disabled=true;
-}
-}
-};
-dojox.html.activeStyleSheet=function(_12){
-var _13=dojox.html.getToggledStyleSheets();
-if(arguments.length==1){
-dojo.forEach(_13,function(s){
-s.disabled=(s.title==_12)?false:true;
-});
-}else{
-for(var i=0;i<_13.length;i++){
-if(_13[i].disabled==false){
-return _13[i];
-}
-}
-}
-return true;
-};
-dojox.html.getPreferredStyleSheet=function(){
-};
-dojox.html.getToggledStyleSheets=function(){
-if(!_3.length){
-var _14=dojox.html.getStyleSheets();
-for(var nm in _14){
-if(_14[nm].title){
-_3.push(_14[nm]);
-}
-}
-}
-return _3;
-};
-dojox.html.getStyleSheets=function(){
-if(_2.collected){
-return _2;
-}
-var _15=dojo.doc.styleSheets;
-dojo.forEach(_15,function(n){
-var s=(n.sheet)?n.sheet:n;
-var _16=s.title||s.href;
-if(dojo.isIE){
-if(s.cssText.indexOf("#default#VML")==-1){
-if(s.href){
-_2[_16]=s;
-}else{
-if(s.imports.length){
-dojo.forEach(s.imports,function(si){
-_2[si.title||si.href]=si;
-});
-}else{
-_2[_16]=s;
-}
-}
-}
-}else{
-_2[_16]=s;
-_2[_16].id=s.ownerNode.id;
-dojo.forEach(s.cssRules,function(r){
-if(r.href){
-_2[r.href]=r.styleSheet;
-_2[r.href].id=s.ownerNode.id;
-}
-});
-}
-});
-_2.collected=true;
-return _2;
-};
-})();
-}
+	
+	var dynamicStyleMap = {};
+	var pageStyleSheets = {};
+	var titledSheets = [];
+	var styleIndicies = [];
+	
+	dojox.html.insertCssRule = function(/*String*/selector, /*String*/declaration, /*String*/styleSheetName){
+		// summary:
+		//	Creates a style and attaches it to a dynamically created stylesheet
+		//	arguments:
+		//		selector: 	
+		//					A fully qualified class name, as it would appear in
+		//					a CSS dojo.doc. Start classes with periods, target
+		//					nodes with '#'. Large selectors can also be created
+		//					like:
+		//					| "#myDiv.myClass span input"
+		//		declaration:
+		//					A single string that would make up a style block, not
+		//					including the curly braces. Include semi-colons between
+		//					statements. Do not use JavaScript style declarations
+		//					in camel case, use as you would in a CSS dojo.doc:
+		//					| "color:#ffoooo;font-size:12px;margin-left:5px;"
+		//		styleSheetName: ( optional )
+		//					Name of the dynamic style sheet this rule should be 
+		//					inserted into. If is not found by that name, it is
+		//					created. If no name is passed, the name "default" is 
+		//					used.
+		//
+		var ss = dojox.html.getDynamicStyleSheet(styleSheetName);
+		var styleText = selector + " {" + declaration + "}";
+		console.log("insertRule:", styleText)
+		if(dojo.isIE){
+			// Note: check for if(ss.cssText) does not work
+			ss.cssText+=styleText;
+			console.log("ss.cssText:", ss.cssText)
+		}else if(ss.sheet){
+			ss.sheet.insertRule(styleText, ss._indicies.length);
+		}else{
+			ss.appendChild(dojo.doc.createTextNode(styleText));
+		}
+		ss._indicies.push(selector+" "+declaration);
+		return selector; // String 
+	
+	}
+	
+	dojox.html.removeCssRule = function(/*String*/selector, /*String*/declaration, /*String*/styleSheetName){
+		// summary:
+		//		Removes a cssRule base on the selector and declaration passed
+		//		The declaration is needed for cases of dupe selectors
+		// description: Only removes DYNAMICALLY created cssRules. If you 
+		//		created it with dojox.html.insertCssRule, it can be removed.
+		//
+		var ss;
+		var index=-1;
+		for(var nm in dynamicStyleMap){
+			if(styleSheetName && styleSheetName!=nm) {continue;}
+			ss = dynamicStyleMap[nm];
+			for(var i=0;i<ss._indicies.length;i++){
+				if(selector+" "+declaration == ss._indicies[i]){
+					index = i;
+					break;
+				}
+			}
+			if(index>-1) { break; }
+		}
+		if(!ss){
+			console.log("No dynamic style sheet has been created from which to remove a rule.");
+			return false;
+		}
+		if(index==-1){
+			console.log("The css rule was not found and could not be removed.");
+			return false;
+		}
+		
+		ss._indicies.splice(index, 1);
+		
+		
+		
+		if(dojo.isIE){ 
+			// Note: check for if(ss.removeRule) does not work
+			ss.removeRule(index);
+		}else if(ss.sheet){
+			ss.sheet.deleteRule(index);
+		}else if(document.styleSheets[0]){
+			console.log("what browser hath useth thith?")
+			//
+		}
+		return true; //Boolean
+		
+	}
+	
+	/* TODO
+	dojox.html.modifyCssRule = function(selector, declaration, styleSheetName){
+		Not implemented - it seems to have some merit for changing some complex 
+		selectors. It's not much use for changing simple ones like "span".
+		For now, simply write a new rule which will cascade over the first.
+		// summary
+		//	Modfies an existing cssRule
+	}
+	*/
+	
+	dojox.html.getStyleSheet = function(/*String*/styleSheetName){
+		// summary:
+		//		Returns a style sheet based on the argument.
+		//		Searches dynamic style sheets first. If no matches,
+		//		searches document style sheets.
+		//
+		// argument: (optional)
+		//		A title or an href to a style sheet. Title can be 
+		//		an attribute in a tag, or a dynamic style sheet 
+		//		reference. Href can be the name of the file.
+		//		If no argument, the assumed created dynamic style 
+		//		sheet is used.
+		
+		// try dynamic sheets first 
+		if(dynamicStyleMap[styleSheetName || "default"]){
+			return dynamicStyleMap[styleSheetName || "default"];
+		}
+		if(!styleSheetName){
+			// no arg is nly good for the default style sheet 
+			// and it has not been created yet.
+			return false;
+		}
+		
+		var allSheets = dojox.html.getStyleSheets();
+		
+		// now try document style sheets by name
+		if(allSheets[styleSheetName]){
+			return dojox.html.getStyleSheets()[styleSheetName];
+		}
+		
+		// check for partial matches in hrefs (so that a fully 
+		//qualified name does not have to be passed)
+		for ( var nm in allSheets){
+			if(	allSheets[nm].href && allSheets[nm].href.indexOf(styleSheetName)>-1){
+				return allSheets[nm];
+			}
+		}
+		return false; //StyleSheet or false
+	}
+	
+	dojox.html.getDynamicStyleSheet = function(/*String*/styleSheetName){
+		// summary:
+		//		Creates and returns a dynamically created style sheet
+		// 		used for dynamic styles
+		//
+		//	argument:
+		//			styleSheetName /* optional String */
+		//			The name given the style sheet so that multiple 
+		//			style sheets can be created and referenced. If 
+		//			no argument is given, the name "default" is used.
+		//
+		if(!styleSheetName){ styleSheetName="default"; }
+		
+		if(!dynamicStyleMap[styleSheetName]){
+			if(dojo.doc.createStyleSheet){ //IE
+			
+				dynamicStyleMap[styleSheetName] = dojo.doc.createStyleSheet();
+				dynamicStyleMap[styleSheetName].title = styleSheetName;
+
+			}else{
+				dynamicStyleMap[styleSheetName] = dojo.doc.createElement("style");
+				dynamicStyleMap[styleSheetName].setAttribute("type", "text/css");
+				dojo.doc.getElementsByTagName("head")[0].appendChild(dynamicStyleMap[styleSheetName]);
+				console.log(styleSheetName, " ss created: ", dynamicStyleMap[styleSheetName].sheet);
+			}
+			dynamicStyleMap[styleSheetName]._indicies = [];
+		}
+		
+		
+		return dynamicStyleMap[styleSheetName]; //StyleSheet
+	}
+
+	dojox.html.enableStyleSheet = function(/*String*/styleSheetName){
+		// summary:
+		//		Enables the style sheet with the name passed in the
+		//		argument. Deafults to the default style sheet.
+		//
+		var ss = dojox.html.getStyleSheet(styleSheetName);
+		if(ss){ 
+			if(ss.sheet){
+				ss.sheet.disabled = false; 
+			}else{
+				ss.disabled = false; 
+			}
+		}
+	}
+
+	dojox.html.disableStyleSheet = function(styleSheetName){
+		// summary:
+		//		Disables the dynamic style sheet with the name passed in the
+		//		argument. If no arg is passed, defaults to the default style sheet.
+		//
+		var ss = dojox.html.getStyleSheet(styleSheetName);
+		if(ss){ 
+			if(ss.sheet){
+				ss.sheet.disabled = true; 
+			}else{
+				ss.disabled = true; 
+			}
+		}
+	}
+	
+	dojox.html.activeStyleSheet = function(/*?String*/title){
+		// summary:
+		//		Getter/Setter
+		// description:
+		//		If passed a title, enables a that style sheet. All other
+		//		toggle-able style sheets are disabled.
+		//		If no argument is passed, returns currently enabled
+		//		style sheet.
+		//
+		var sheets = dojox.html.getToggledStyleSheets();
+		if(arguments.length == 1){
+			//console.log("sheets:", sheets);
+			dojo.forEach(sheets, function(s){
+				s.disabled = (s.title == title) ? false : true;
+				//console.log("SWITCHED:", s.title, s.disabled, s.id);
+			});
+		}else{
+			for(var i=0; i<sheets.length;i++){
+				if(sheets[i].disabled == false){
+					return sheets[i];
+				}
+			}
+		}
+		return true; //StyleSheet or Boolean - FIXME - doesn't make a lot of sense
+	}
+	
+	dojox.html.getPreferredStyleSheet = function(){
+		// summary
+		//	Returns the style sheet that was initially enabled
+		//	on document launch.
+		
+		//TODO
+	}
+	
+	
+	
+	
+	dojox.html.getToggledStyleSheets = function(){
+		// summary:
+		//		Searches HTML for style sheets that are "toggle-able" - 
+		//		can be enabled and disabled. These would include sheets
+		//		with the title attribute, as well as the REL attribute.
+		//	returns:
+		//		An array of all toggle-able style sheets
+		//	TODO: 	Sets of style sheets could be grouped according to
+		//			an ID and used in sets, much like different
+		//			groups of radio buttons. It would not however be
+		//			according to W3C spec
+		//
+		if(!titledSheets.length){
+			var sObjects = dojox.html.getStyleSheets();
+			for(var nm in sObjects){
+				
+				if(sObjects[nm].title){
+					//console.log("TITLE:", sObjects[nm].title, sObjects[nm])
+					titledSheets.push(sObjects[nm]);
+				}
+			}
+		}
+		return titledSheets; //Array
+	}
+	
+	
+	dojox.html.getStyleSheets = function(){
+		// summary:
+		//		Collects all the style sheets referenced in the HTML page,
+		//		including any incuded via @import. 
+		//
+		//	returns: 
+		//		An hash map of all the style sheets.
+		//
+		//	TODO: 	Does not recursively search for @imports, so it will
+		//			only go one level deep.
+		//
+		if(pageStyleSheets.collected) {return pageStyleSheets;}
+		
+		var sheets = dojo.doc.styleSheets;
+		//console.log("styleSheets:", sheets);
+		dojo.forEach(sheets, function(n){
+			var s = (n.sheet) ? n.sheet : n;
+			var name = s.title || s.href;
+			if(dojo.isIE){
+				// IE attaches a style sheet for VML - do not include this
+				if(s.cssText.indexOf("#default#VML")==-1){
+					
+					
+					if(s.href){
+						// linked		
+						pageStyleSheets[name] = s;
+					
+					}else if(s.imports.length){
+						// Imported via @import
+						dojo.forEach(s.imports, function(si){
+							pageStyleSheets[si.title || si.href] = si;
+						});
+						
+					}else{
+						//embedded within page
+						pageStyleSheets[name] = s;
+					}
+				}
+				
+			}else{
+				//linked or embedded
+				pageStyleSheets[name] = s;
+				pageStyleSheets[name].id = s.ownerNode.id;
+				dojo.forEach(s.cssRules, function(r){
+					if(r.href){
+						// imported
+						pageStyleSheets[r.href] = r.styleSheet;
+						pageStyleSheets[r.href].id = s.ownerNode.id;
+					}
+				});
+			
+			}
+			
+		});
+		
+		//console.log("pageStyleSheets:", pageStyleSheets);
+		
+		
+		pageStyleSheets.collected = true;
+		return pageStyleSheets; //Object
+	}
+	
+
+})();
\ No newline at end of file
diff --git a/dojox/html/tests/entities.js b/dojox/html/tests/entities.js
new file mode 100755
index 0000000..dfc1d36
--- /dev/null
+++ b/dojox/html/tests/entities.js
@@ -0,0 +1,97 @@
+dojo.provide("dojox.html.tests.entities");
+dojo.require("dojox.html.entities");
+
+doh.register("dojox.html.tests.entities", 
+	[
+		{
+			name: "Encode:  Basic HTML Entities",
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of basic encoding of characters considered HTML entities
+				//	description:
+				//		Simple test of basic encoding of characters considered HTML entities
+				var txt = "This is some \" text \" with & entities inside it that <need to be escaped>";
+				var expected = "This is some " text " with & entities inside it that <need to be escaped>";
+				var encodedTxt = dojox.html.entities.encode(txt);
+				doh.assertEqual(expected, encodedTxt);
+			}
+		},
+		{
+			name: "Decode:  Basic HTML Entities",
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of basic encoding of characters considered HTML entities
+				//	description:
+				//		Simple test of basic encoding of characters considered HTML entities
+				var txt = "This is some " text " with & entities inside it that <need to be escaped>";
+				var expected = "This is some \" text \" with & entities inside it that <need to be escaped>";
+				var decodedTxt = dojox.html.entities.decode(txt);
+				doh.assertEqual(expected, decodedTxt);
+			}
+		},
+		{
+			name: "Encode:  Basic Latin Entities",
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of basic encoding of characters considered Latin type entities
+				//	description:
+				//		Simple test of basic encoding of characters considered Latin type entities
+				var txt = "";
+				var expected = "";
+				var map = dojox.html.entities.latin;
+				var i;
+				for(i = 0; i < map.length; i++){
+					txt += map[i][0];
+					expected += "&" + map[i][1] + ";";
+				}
+				var encodedTxt = dojox.html.entities.encode(txt);
+				doh.assertEqual(expected, encodedTxt);
+			}
+		},
+		{
+			name: "Decode:  Basic Latin Entities",
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of basic decoding of characters considered Latin type entities
+				//	description:
+				//		Simple test of basic decoding of characters considered Latin type entities
+					  var txt = "";
+					  var expected = "";
+					  var map = dojox.html.entities.latin;
+					  var i;
+					  for(i = 0; i < map.length; i++){
+						  txt += "&" + map[i][1] + ";";
+						  expected += map[i][0];
+					  }
+					  var decodedTxt = dojox.html.entities.decode(txt);
+					  doh.assertEqual(expected, decodedTxt);
+			}
+		},
+		{
+			name: "Encode:  Custom entity map",
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of basic encoding using a custom map instead of the default ones.
+				//	description:
+				//		Simple test of basic encoding using a custom map instead of the default ones.
+				var txt = "This is some \" text with & entities inside it that <need to be escaped>";
+				var expected = "This is some " text with & entities inside it that <need to be escaped>";
+				var encodedTxt = dojox.html.entities.encode(txt, [["\"", "quot"]]);
+				doh.assertEqual(expected, encodedTxt);
+			}
+		},
+		{
+			name: "Decode:  Custom entity map",
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of basic decoding using a custom map instead of the default ones.
+				//	description:
+				//		Simple test of basic decoding using a custom map instead of the default ones.
+				var txt = "This is some " text with & entities inside it that <need to be escaped>";
+				var expected = "This is some \" text with & entities inside it that <need to be escaped>";
+				var decodedTxt = dojox.html.entities.decode(txt, [["\"", "quot"]]);
+				doh.assertEqual(expected, decodedTxt);
+			}
+		}
+	]
+);
diff --git a/dojox/html/tests/format.js b/dojox/html/tests/format.js
new file mode 100755
index 0000000..4c4da04
--- /dev/null
+++ b/dojox/html/tests/format.js
@@ -0,0 +1,354 @@
+dojo.provide("dojox.html.tests.format");
+dojo.require("dojox.html.format");
+
+
+doh.register("dojox.html.tests.format", 
+	[
+		{
+			name: "Format:  Basic HTML Format test",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting.
+				// description:
+				//		Simple test of basic HTML formatting.
+				var txt = "<div><b>hello</b> this is some text.</div>";
+				var expected = 	"<div>\n" +
+								"\t<b>hello</b> this is some text.\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format test with three space indent",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with spaced indenting instead of tab
+				// description:
+				//		Simple test of basic HTML formatting with spaced indenting instead of tab
+				var txt = "<div><b>hello</b> this is some text.</div>";
+				var expected = 	"<div>\n" +
+								"   <b>hello</b> this is some text.\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt, 3);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format test with three space indent and custom encoding",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with spaced indenting instead of tab
+				// description:
+				//		Simple test of basic HTML formatting with spaced indenting instead of tab
+				var txt = "<div><b>hello</b> this is \"some\" entities & text.</div>";
+				var expected = 	"<div>\n" +
+								"   <b>hello</b> this is \"some\" entities & text.\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt, 3, -1, [["&", "amp"]]);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format test with comment node",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with a comment node"
+				// description:
+				//		Simple test of basic HTML formatting with a comment node"
+				if(!dojo.isIE){
+					// Hurray for IE, it sometimes just strips comment nodes from the
+					// dom.  So we can't test this reliably.
+					var txt = "<div><!-- This is a comment! --><br></div>";
+					var expected = 	"<div>\n" +
+									"   <!--\n" +
+									"      This is a comment!\n" +
+									"   -->\n" +
+									"   <br>\n" +
+									"</div>\n";
+					var formattedTxt = dojox.html.format.prettyPrint(txt, 3);
+					doh.assertEqual(expected, formattedTxt);
+				}
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format test with inline tags",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with spaced indenting instead of tab
+				// description:
+				//		Simple test of basic HTML formatting with spaced indenting instead of tab
+				var txt = "<div><b>hello</b> <a href=\"http://example.com/\">Example.com</a> this is some text after the link.</div>";
+				var expected = 	"<div>\n" +
+								"   <b>hello</b> <a href=\"http://example.com/\">Example.com</a> this is some text after the link.\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt, 3);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format test with inline tags (2)",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with spaced indenting instead of tab
+				// description:
+				//		Simple test of basic HTML formatting with spaced indenting instead of tab
+				var txt = "<div><b>hello</b> <br> <a href=\"http://example.com/\">Example.com</a> this is some text after the link.</div>";
+				var expected = 	"<div>\n" +
+								"   <b>hello</b>\n"+
+								"   <br>\n" +
+								"   <a href=\"http://example.com/\">Example.com</a> this is some text after the link.\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt, 3);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format test with id",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with an id attr set.
+				// description:
+				//		Simple test of basic HTML formatting with an id attr set.
+				var txt = "<div id=\"myID\"><b>hello</b> this is some text.</div>";
+				var expected = 	"<div id=\"myID\">\n" +
+								"\t<b>hello</b> this is some text.\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format test with attributes (sorting attributes)",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with an id attr set.
+				// description:
+				//		Simple test of basic HTML formatting with an id attr set.
+				var txt = "<div id=\"myID\" style=\"font-weight: bold; font-style: italic;\" foo=\"bar\"><b>hello</b> this is some text.</div>";
+				var expected = 	"<div foo=\"bar\" id=\"myID\" style=\"font-style: italic; font-weight: bold;\">\n" +
+								"\t<b>hello</b> this is some text.\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format test with attributes (multiple unquoted)",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with an id attr set.
+				// description:
+				//		Simple test of basic HTML formatting with an id attr set.
+				var txt = "<p><font id=\"myID\" size=\"6\"><b>hello</b> this is some text.</font></p>";
+				var expected = 	"<p>\n\t<font id=\"myID\" size=\"6\">" +
+								"<b>hello</b> this is some text." +
+								"</font>\n</p>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format test with style",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with an id attr set.
+				// description:
+				//		Simple test of basic HTML formatting with an id attr set.
+				var txt = "<div style=\"font-weight: bold;\"><b>hello</b> this is some text.</div>";
+				var expected = 	"<div style=\"font-weight: bold;\">\n" +
+								"\t<b>hello</b> this is some text.\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format test with multi style",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with an id attr set.
+				// description:
+				//		Simple test of basic HTML formatting with an id attr set.
+				var txt = "<div style=\"font-weight: bold; color: red\"><b>hello</b> this is some text.</div>";
+				var expected = 	"<div style=\"color: red; font-weight: bold;\">\n" +
+								"\t<b>hello</b> this is some text.\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format with script test",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with an embedded script tag.
+				// description:
+				//		Simple test of basic HTML formatting with an embedded script tag.
+				var txt = "<div><div>hello</div>this is some text.<script>var foo=\"bar\";\nif(foo !== \"bar\"){\n alert(\"Should not be here!\");\n}</script></div>";
+				var expected = 	"<div>\n" +
+								"\t<div>\n" +
+								"\t\thello\n" +
+								"\t</div>\n"+
+								"\tthis is some text.\n" +
+								"\t<script>\n"+
+								"\t\tvar foo=\"bar\";\n" +
+								"\t\tif(foo !== \"bar\"){\n" +
+								"\t\t\talert(\"Should not be here!\");\n" +
+								"\t\t}\n" +
+								"\t</script>\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt);
+				doh.assertEqual(dojo.trim(expected), dojo.trim(formattedTxt));
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format with script test and three space indent",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with an embedded script tag.
+				// description:
+				//		Simple test of basic HTML formatting with an embedded script tag.
+				var txt = "<div><div>hello</div>this is some text.<script>var foo=\"bar\";\nif(foo !== \"bar\"){\n alert(\"Should not be here!\");\n}</script></div>";
+				var expected = 	"<div>\n" +
+								"   <div>\n" +
+								"      hello\n" +
+								"   </div>\n"+
+								"   this is some text.\n" +
+								"   <script>\n"+
+								"      var foo=\"bar\";\n" +
+								"      if(foo !== \"bar\"){\n" +
+								"         alert(\"Should not be here!\");\n" +
+								"      }\n" +
+								"   </script>\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt, 3);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format with script test and three space indent, XHTML",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with an embedded script tag.
+				// description:
+				//		Simple test of basic HTML formatting with an embedded script tag.
+				var txt = "<div><div>hello<br><hr></div>this is some text.<script>var foo=\"bar\";\nif(foo !== \"bar\"){\n alert(\"Should not be here!\");\n}</script></div>";
+				var expected = 	"<div>\n" +
+								"   <div>\n" +
+								"      hello\n" +
+								"      <br />\n" +
+								"      <hr />\n" +
+								"   </div>\n"+
+								"   this is some text.\n" +
+								"   <script>\n"+
+								"      var foo=\"bar\";\n" +
+								"      if(foo !== \"bar\"){\n" +
+								"         alert(\"Should not be here!\");\n" +
+								"      }\n" +
+								"   </script>\n" +
+								"</div>\n";
+				var formattedTxt = dojox.html.format.prettyPrint(txt, 3, -1, null, true);
+				doh.assertEqual(expected, formattedTxt);
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format with <pre> tag",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with an embedded pre tag.
+				// description:
+				//		Simple test of basic HTML formatting with an embedded pre tag.
+
+				if(!dojo.isIE){
+					// IE generates good pre tags, but I think the endline chars differ
+					// so direct comparison fails.  When I figure that out, I can enable
+					// this test.
+					var txt = "<div><pre>hello\nthis is    spaced\nWhee!\n</pre></div>";
+					var expected = 	"<div>\n" +
+									"\t<pre>\n" +
+									"hello\n" +
+									"this is    spaced\n" +
+									"Whee!\n" +
+									"\t</pre>\n"+
+									"</div>\n";
+					var formattedTxt = dojox.html.format.prettyPrint(txt);
+					doh.assertEqual(expected, formattedTxt);
+				}
+			}
+		},
+		{
+			name: "Format:  Basic HTML Format with <pre> tag and three space indent",
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of basic HTML formatting with an embedded pre tag.
+				// description:
+				//		Simple test of basic HTML formatting with an embedded pre tag.
+				if(!dojo.isIE){
+					// IE generates good pre tags, but I think the endline chars differ
+					// so direct comparison fails.  When I figure that out, I can enable
+					// this test.
+					var txt = "<div><pre>hello\nthis is    spaced\nWhee!\n</pre></div>";
+					var expected = 	"<div>\n" +
+									"   <pre>\n" +
+									"hello\n" +
+									"this is    spaced\n" +
+									"Whee!\n" +
+									"   </pre>\n"+
+									"</div>\n";
+					var formattedTxt = dojox.html.format.prettyPrint(txt, 3);
+					doh.assertEqual(expected, formattedTxt);
+				}
+			}
+		},
+		{
+			name: "Format:  Semi-complex HTML format",
+			timeout: 10000,
+			runTest: function(t) {
+				// summary: 
+				//		Simple test of somewhat complex HTML in an external file getting formatted.
+				// description:
+				//		Simple test of basic HTML formatting with an embedded pre tag.
+				if(!dojo.isIE){
+					// Still working out minor comparison issues on IE.  Sigh.
+					// the output is pretty accurate, just need to fix a few things.
+					// Like I think the newlines differ or somesuch.  
+					var deferred = new doh.Deferred();
+
+					var args = {
+						url: dojo.moduleUrl("dojox.html.tests", "unformatted.html").toString(),
+						handleAs: "text",
+						preventCache: true
+					}
+					var ufd = dojo.xhrGet(args);
+					ufd.addCallback(function(html){
+						html = dojox.html.format.prettyPrint(html, 3);
+						var fArgs = {
+							url: dojo.moduleUrl("dojox.html.tests", "formatted.html").toString(),
+							preventCache: true,
+							handleAs: "text"
+						}
+						var fd = dojo.xhrGet(fArgs);
+						fd.addCallback(function(fHtml){
+							try{
+								doh.assertEqual(fHtml, html);
+								deferred.callback(true);
+							}catch(e){
+								deferred.errback(e);
+							}
+						});
+						fd.addErrback(function(error){
+							deferred.errback(error);
+						});
+					});
+					ufd.addErrback(function(err){
+						console.log("Boom!");
+						deferred.errback(err);
+					});
+					return deferred;
+				}
+				return null;
+			}
+		}
+	]
+);
diff --git a/dojox/html/tests/formatted.html b/dojox/html/tests/formatted.html
new file mode 100755
index 0000000..5de0c04
--- /dev/null
+++ b/dojox/html/tests/formatted.html
@@ -0,0 +1,30 @@
+<script type="text/javascript">
+   var foo = true;
+   if(!foo){
+      alert("Should not be here.");
+   }
+</script>
+<h1>
+   This page has no formatting
+</h1>
+No kidding.  It looks horrible!  Ugh.
+<table>
+   <tbody>
+      <tr>
+         <td>
+            One cell
+         </td>
+         <td>
+            Two cell
+         </td>
+      </tr>
+   </tbody>
+</table>
+<ul>
+   <li>
+      item one
+   </li>
+   <li>
+      item two
+   </li>
+</ul>
diff --git a/dojox/html/tests/images/blank.gif b/dojox/html/tests/images/blank.gif
new file mode 100644
index 0000000..e565824
Binary files /dev/null and b/dojox/html/tests/images/blank.gif differ
diff --git a/dojox/html/tests/images/dojoLogo.png b/dojox/html/tests/images/dojoLogo.png
new file mode 100644
index 0000000..1219de7
Binary files /dev/null and b/dojox/html/tests/images/dojoLogo.png differ
diff --git a/dojox/html/tests/images/testImage.gif b/dojox/html/tests/images/testImage.gif
new file mode 100644
index 0000000..4370d68
Binary files /dev/null and b/dojox/html/tests/images/testImage.gif differ
diff --git a/dojox/html/tests/module.js b/dojox/html/tests/module.js
new file mode 100755
index 0000000..b107b00
--- /dev/null
+++ b/dojox/html/tests/module.js
@@ -0,0 +1,8 @@
+dojo.provide("dojox.html.tests.module");
+try{
+	dojo.requireIf(dojo.isBrowser, "dojox.html.tests.entities");
+	dojo.requireIf(dojo.isBrowser, "dojox.html.tests.format");
+}catch(e){
+	doh.debug(e);
+}
+
diff --git a/dojox/html/tests/performance/format.js b/dojox/html/tests/performance/format.js
new file mode 100755
index 0000000..bb40836
--- /dev/null
+++ b/dojox/html/tests/performance/format.js
@@ -0,0 +1,63 @@
+dojo.provide("dojox.html.tests.performance.format");
+
+dojo.require("dojox.html.format");
+
+
+dojox.html.tests.performance.docText = null;
+doh.register("format.prettyprint.performance", [
+	{
+		name: "smallDoc",
+		testType: "perf",
+		trialDuration: 100,
+		trialDelay: 50,
+		trialIterations: 50,
+		setUp: function() {
+			var deferred = dojo.xhrGet({
+				preventCache: true,
+				url: dojo.moduleUrl("dojox", "html/tests/performance/smalldoc.txt").toString(),
+				handleAs: "text",
+				sync: true
+			});
+			deferred.addCallback(function(txt){
+				dojox.html.tests.performance.docText = txt;
+			});
+			deferred.addErrback(function(e){
+				console.log(e);
+			});
+		},
+		tearDown: function(){
+			dojox.html.tests.performance.docText = null;
+		},
+		runTest: function(){
+			var s = dojox.html.format.prettyPrint(dojox.html.tests.performance.docText);
+		}
+	},
+	{
+		name: "largeDoc",
+		testType: "perf",
+		trialDuration: 100,
+		trialDelay: 50,
+		trialIterations: 50,
+		setUp: function() {
+			var deferred = dojo.xhrGet({
+				preventCache: true,
+				url: dojo.moduleUrl("dojox", "html/tests/performance/largedoc.txt").toString(),
+				handleAs: "text",
+				sync: true
+			});
+			deferred.addCallback(function(txt){
+				dojox.html.tests.performance.docText = txt;
+			});
+			deferred.addErrback(function(e){
+				console.log(e);
+			});
+		},
+		tearDown: function(){
+			dojox.html.tests.performance.docText = null;
+		},
+		runTest: function(){
+			var s = dojox.html.format.prettyPrint(dojox.html.tests.performance.docText);
+		}
+	}
+]);
+
diff --git a/dojox/html/tests/performance/largedoc.txt b/dojox/html/tests/performance/largedoc.txt
new file mode 100755
index 0000000..05530e5
--- /dev/null
+++ b/dojox/html/tests/performance/largedoc.txt
@@ -0,0 +1,665 @@
+<p>
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in lorem
+ante. Duis quis lectus massa. Vestibulum ligula tortor, commodo at
+facilisis vitae, interdum sed sapien. Proin imperdiet, eros sit amet
+laoreet feugiat, enim eros ornare ante, quis pulvinar magna turpis sed
+massa. Nullam rutrum vestibulum quam sit amet vulputate. Curabitur
+fermentum tellus id orci hendrerit bibendum. Mauris hendrerit nunc
+felis, ut elementum magna. Nullam dolor sapien, aliquet ac dictum ut,
+suscipit sit amet augue. In quis justo ut libero gravida consequat.
+Pellentesque scelerisque ipsum magna. Suspendisse nec dolor nec turpis
+tempor adipiscing. Vestibulum dapibus tincidunt nibh iaculis suscipit.
+Quisque a libero in nisl tempus tempor vel ac velit.
+</p>
+<p>Praesent tincidunt nunc eu nunc consectetur rhoncus. Donec nulla
+nibh, vehicula quis fringilla vel, vulputate quis erat. Curabitur
+egestas convallis lectus non tempus. Suspendisse volutpat, nunc
+scelerisque molestie aliquet, sem felis bibendum mi, eget consectetur
+odio neque mattis orci. Suspendisse urna augue, vehicula ac mattis sit
+amet, accumsan quis enim. Nam nec magna velit, a laoreet purus.
+Curabitur imperdiet condimentum tortor, quis accumsan neque eleifend
+in. Mauris iaculis enim quis tortor mattis ullamcorper consequat nunc
+eleifend. Donec laoreet laoreet metus id ornare. Donec pellentesque
+vehicula pretium. Pellentesque habitant morbi tristique senectus et
+netus et malesuada fames ac turpis egestas. Donec nec dolor non metus
+porttitor dignissim.
+</p>
+<p>Aenean tempor aliquam aliquam. Proin nec tortor sit amet risus
+dictum consequat pellentesque imperdiet libero. Donec pharetra tellus
+odio, placerat feugiat dui. Aliquam elementum mauris vitae risus
+pharetra eget tincidunt nisl interdum. Morbi enim sapien, imperdiet id
+vulputate commodo, aliquet quis felis. Duis rhoncus posuere sagittis.
+Nam at eleifend lectus. Mauris vulputate ligula nec turpis hendrerit
+egestas. Nam molestie gravida magna sed cursus. Sed ullamcorper dapibus
+sagittis. Quisque vitae nibh metus, id vehicula nulla. Vivamus in nisi
+ipsum. Nunc eget urna cursus nisi convallis euismod lobortis
+ullamcorper leo. Suspendisse eget urna magna. Pellentesque vel leo
+ante. Vestibulum ac congue nulla. Duis vehicula pellentesque ornare.
+Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
+inceptos himenaeos.
+</p>
+<p>Quisque fermentum lectus at leo hendrerit et vehicula mi interdum.
+Vivamus sit amet diam lectus, sit amet interdum nisl. Cras adipiscing
+scelerisque sollicitudin. Suspendisse magna lorem, adipiscing eget
+lobortis id, consequat a mi. Fusce vitae rhoncus urna. Donec id diam
+nisl. Donec dapibus ullamcorper auctor. Donec commodo porttitor nibh,
+eget varius mi faucibus in. In semper, enim quis tincidunt accumsan,
+nisi lectus ornare ante, sed tincidunt nunc sem a metus. Nunc sit amet
+facilisis tortor. Nulla accumsan tellus nibh, ut tempus purus. Fusce
+nisl libero, venenatis ut dignissim eget, sollicitudin placerat erat.
+Cras tristique pretium fermentum.
+</p>
+<p>Pellentesque congue posuere ante. Suspendisse metus arcu, cursus vel
+vulputate ac, tempus quis sapien. Nullam in lorem mauris, sed pretium
+felis. Pellentesque porta nulla sit amet lectus mollis at vulputate sem
+elementum. In hac habitasse platea dictumst. Vestibulum pulvinar
+vehicula lorem, sit amet molestie metus consequat non. Curabitur
+suscipit sagittis libero at dapibus. Phasellus lorem ipsum, blandit sit
+amet semper sed, aliquet eu eros. Proin rhoncus arcu ut velit fringilla
+aliquam. Nullam elit eros, mattis nec tincidunt quis, tempus id mauris.
+Aliquam in erat quis augue ultricies fringilla. Curabitur rhoncus urna
+id dolor eleifend eu malesuada dui egestas. Cras mattis dui in magna
+eleifend posuere sed id arcu. Duis ultrices rutrum turpis a adipiscing.
+Nulla facilisi.
+</p>
+<p>Quisque vel justo ut dui ullamcorper gravida et in lectus. Donec in
+ligula in lorem interdum viverra nec fringilla urna. Fusce mollis
+consectetur velit nec scelerisque. Fusce quis orci mauris, at blandit
+ante. Donec pretium vehicula augue, ac convallis metus accumsan non.
+Aliquam sit amet dui nunc. Fusce hendrerit quam purus. Praesent iaculis
+quam id orci vehicula in condimentum turpis hendrerit. Vivamus id felis
+in turpis imperdiet sollicitudin. Aliquam non cursus odio. Donec a
+laoreet metus. Ut urna erat, egestas ut feugiat quis, tincidunt vitae
+augue. Nulla consequat risus id nisl rutrum in facilisis leo sagittis.
+Morbi commodo tellus in enim eleifend varius.
+</p>
+<p>Donec euismod ligula ut felis varius quis volutpat mi tincidunt.
+Proin eget enim mi. Integer malesuada lectus at dolor rhoncus mattis.
+Ut blandit imperdiet odio at placerat. Phasellus lacinia sapien
+elementum dui tristique interdum. Curabitur tempus facilisis sem at
+egestas. Nullam eu malesuada enim. Phasellus ut elementum neque.
+Aliquam dictum nisl a eros sollicitudin viverra. Ut blandit hendrerit
+velit et iaculis. In odio nulla, mollis pharetra euismod in, pretium a
+lorem. Quisque lorem neque, congue non vehicula in, hendrerit vel nunc.
+Sed lacinia massa in ligula tempor lobortis. Donec auctor ullamcorper
+gravida. Phasellus bibendum iaculis ante nec pellentesque.
+</p>
+<p>Etiam interdum orci eu turpis facilisis tempor. Sed consequat,
+libero sed cursus aliquet, dui lorem mollis lectus, sit amet blandit
+augue lacus id metus. Etiam arcu lectus, rutrum in eleifend eget,
+suscipit at nisi. Mauris mollis arcu quis diam euismod auctor. In mi
+nunc, iaculis ac cursus at, convallis sit amet risus. Morbi sed nunc
+sit amet dolor sollicitudin ultricies vitae sit amet tellus.
+Suspendisse potenti. Praesent lobortis risus ac tortor molestie eget
+lobortis sapien dapibus. Maecenas dapibus augue eget turpis adipiscing
+vel porta sapien placerat. Aenean ut risus libero. Praesent elementum
+arcu mauris, a venenatis sapien. Mauris semper condimentum mauris,
+vitae convallis neque gravida eu. Curabitur non enim quam. Morbi
+euismod, mi a sodales volutpat, massa arcu congue augue, a vulputate
+mauris velit nec risus. Etiam placerat, elit eu suscipit aliquam,
+tortor neque auctor urna, sit amet congue turpis diam id leo.
+</p>
+<p>Integer sodales iaculis urna, sit amet eleifend elit pellentesque
+pharetra. Nulla justo sapien, aliquet vel viverra quis, laoreet in dui.
+Nam ut viverra nisi. Proin nec tortor vitae sem placerat aliquam.
+Pellentesque habitant morbi tristique senectus et netus et malesuada
+fames ac turpis egestas. Ut sodales ornare nulla, a tempus massa
+laoreet non. Nunc sed tellus augue, sit amet laoreet ante. Aliquam
+bibendum dolor id dui bibendum accumsan. Ut eu lectus vitae mi dictum
+bibendum sed vitae sem. Quisque sit amet semper erat. Vestibulum
+faucibus viverra risus, et interdum tortor fermentum quis. Sed eros
+nisl, pharetra nec sodales et, aliquet sit amet est. Vivamus et sapien
+sem.
+</p>
+<p>Suspendisse congue est laoreet nisi porttitor non lobortis ante
+cursus. Nam aliquam ipsum eu mauris venenatis hendrerit. Suspendisse
+feugiat, urna eu ultrices fringilla, nulla leo tristique urna, vel
+semper erat justo quis quam. Donec faucibus enim vel magna condimentum
+ac convallis ante adipiscing. Class aptent taciti sociosqu ad litora
+torquent per conubia nostra, per inceptos himenaeos. Cras pulvinar
+semper arcu eu euismod. Nullam lobortis, quam vel adipiscing
+condimentum, urna sem posuere purus, sed posuere sem diam vitae nibh.
+Aenean ligula odio, commodo laoreet dictum a, vestibulum nec quam.
+Morbi accumsan mollis quam, nec aliquet metus euismod id. Nulla
+consectetur nulla nec sem laoreet scelerisque. Morbi vulputate mollis
+rutrum. Pellentesque varius mattis tellus sed dictum.
+</p>
+<p>Duis ultrices ante at massa molestie gravida. Nam nisi mauris,
+consectetur ut mollis in, sollicitudin convallis purus. Morbi vitae
+augue non sem dignissim dignissim at in est. Aenean quam felis,
+condimentum quis pharetra eu, bibendum quis odio. Mauris posuere nisl
+sit amet nisl tempor accumsan. Donec feugiat tincidunt quam at
+fringilla. In urna metus, feugiat eget tempor quis, malesuada id eros.
+Mauris mattis tempus euismod. Praesent quam velit, hendrerit eu
+consectetur elementum, placerat quis purus. Nulla convallis mattis
+turpis id condimentum. Vivamus et ornare tellus. Etiam consequat,
+ligula a faucibus adipiscing, nibh leo vestibulum ante, et pellentesque
+erat turpis a libero.
+</p>
+<p>Nulla facilisi. Quisque id diam orci. Maecenas non diam purus. Ut
+aliquam nulla et sapien viverra porta. Ut et ultrices neque. In in
+interdum purus. Ut at posuere urna. Maecenas in quam eget lorem euismod
+volutpat id a turpis. Duis ac nulla lacus. Phasellus sem quam,
+porttitor et malesuada at, posuere id neque. Proin fringilla imperdiet
+nulla sed luctus. In hac habitasse platea dictumst. Integer dictum
+neque sed sem porttitor sagittis. Aliquam ornare bibendum dui, ut
+tristique diam vehicula non. Morbi sit amet dui nisl.
+</p>
+<p>Donec ac tellus leo. Proin tristique tortor ac sem condimentum
+sagittis scelerisque diam pellentesque. Proin adipiscing rhoncus ipsum
+eu rutrum. Duis velit nulla, dignissim ut facilisis non, dignissim ac
+felis. Cras vel ligula elit, nec feugiat elit. Phasellus mattis, metus
+ut fringilla porta, arcu erat tempor turpis, blandit condimentum dolor
+dolor quis ante. Pellentesque sed diam dui. Integer laoreet vestibulum
+augue eu bibendum. Nullam tristique, mauris sed aliquam rhoncus, augue
+mi ultrices enim, sit amet adipiscing ipsum tellus et nibh. Nunc eu
+ligula varius risus dignissim condimentum in eget lectus. Etiam sodales
+convallis nisl, in semper arcu commodo ut. Nulla vel eros ante. Nunc
+nulla ipsum, fermentum ut ultricies ac, consequat a purus. Maecenas nec
+est vel diam cursus feugiat. Nulla sodales ullamcorper ultricies. Nunc
+nec ante a massa semper luctus. Donec in elementum leo. Fusce nibh
+orci, luctus quis tempus vel, volutpat sit amet ligula.
+</p>
+<p>Nulla facilisi. Vestibulum et dui non lectus commodo eleifend.
+Maecenas luctus purus quis orci aliquet faucibus. Sed tempor ipsum at
+mauris scelerisque et euismod nunc aliquam. Aliquam tempus, dui eu
+molestie rutrum, lacus turpis venenatis ipsum, et ultrices ante nulla
+sollicitudin mauris. Pellentesque quam massa, lacinia auctor ornare at,
+suscipit eu dui. Donec ante augue, ultrices vitae dignissim eget,
+cursus sed turpis. Nullam eleifend nunc sit amet elit pretium ac
+hendrerit est ullamcorper. Sed pretium est et sapien blandit vel
+ultricies tellus ultricies. Donec ultrices sodales condimentum. Duis
+convallis neque quis libero cursus aliquam. Morbi aliquam justo vel
+lacus suscipit interdum. Vestibulum ante ipsum primis in faucibus orci
+luctus et ultrices posuere cubilia Curae; Duis iaculis neque ut leo
+imperdiet at tincidunt orci gravida.
+</p>
+<p>Morbi cursus, sapien ac gravida ultrices, dolor orci imperdiet est,
+eu eleifend mi mauris eu risus. Sed eros dolor, molestie at viverra
+suscipit, tincidunt at quam. Fusce cursus eros ac sem molestie
+accumsan. Suspendisse tellus felis, adipiscing vitae pulvinar ornare,
+tempus a risus. Donec gravida pulvinar dui, a pellentesque mauris
+ullamcorper a. Donec venenatis lorem nec nibh cursus gravida. Cras
+sagittis tempor aliquam. Aenean eget lacus nec ligula tincidunt
+dignissim pellentesque sit amet sem. Proin tortor libero, iaculis in
+ultricies ut, dapibus eu mi. In vel rhoncus tortor. Nunc enim enim,
+feugiat vel porta in, mattis non ante. In ut enim in sapien viverra
+accumsan at quis ante. Donec elementum, libero a fringilla tincidunt,
+elit odio rhoncus sem, vel dictum urna nunc sed dui.
+</p>
+<p>Mauris vel est justo. Sed lacinia vehicula neque vel sodales.
+Vivamus imperdiet, est vel tincidunt tempor, velit urna dapibus odio,
+quis sagittis metus lorem vel dui. Proin gravida consequat massa
+tincidunt ultrices. Sed facilisis, mi nec vestibulum congue, mi enim
+volutpat eros, sed semper est nibh in est. Vestibulum viverra magna at
+enim malesuada auctor. Nam ullamcorper varius nunc id adipiscing. Etiam
+ac sem arcu. Maecenas vestibulum, diam non commodo consequat, augue
+felis sagittis urna, eu auctor magna enim vitae libero. In eu nisi
+hendrerit dolor interdum volutpat. Quisque non tortor nibh. Maecenas
+feugiat feugiat neque, nec dapibus diam pharetra sed. Ut metus lacus,
+adipiscing non mattis sit amet, placerat at erat. Nulla lacinia
+pharetra urna, vel aliquet mauris euismod a. Pellentesque et lacus
+facilisis arcu tristique tincidunt a non nisi. Fusce a volutpat nulla.
+Aliquam in est sed ligula dictum interdum at eu magna. Sed id neque a
+est ultricies porta at in lorem.
+</p>
+<p>Aenean consectetur est justo. Suspendisse potenti. Nunc at augue
+nulla. Sed viverra massa vel velit porttitor blandit. In sollicitudin,
+lacus ac aliquet posuere, velit mauris fringilla magna, vitae eleifend
+justo dui et mi. Quisque et tellus ut mauris sodales lobortis. Nullam
+vulputate massa vel metus porta rhoncus. Cum sociis natoque penatibus
+et magnis dis parturient montes, nascetur ridiculus mus. In eu pharetra
+enim. Pellentesque habitant morbi tristique senectus et netus et
+malesuada fames ac turpis egestas. Donec eu nibh at elit rutrum
+hendrerit. Sed id quam lorem, eget posuere eros. Fusce nec sapien sit
+amet velit blandit venenatis sit amet ut libero. Morbi ut urna tortor.
+Maecenas iaculis est in elit ultricies auctor pretium velit gravida. Ut
+fermentum turpis non erat vulputate id tincidunt massa semper. Nulla
+tempor porta velit, quis viverra leo placerat a. Suspendisse potenti.
+</p>
+<p>Fusce quam leo, condimentum eget blandit eu, commodo eleifend massa.
+Maecenas libero diam, tristique vitae cursus non, tempus nec justo.
+Quisque turpis lectus, semper id pulvinar vel, mattis sed dolor.
+Phasellus luctus condimentum lacus eget interdum. Maecenas sit amet
+urna ac dolor ullamcorper pulvinar. Vestibulum nec ipsum vel massa
+venenatis egestas. Suspendisse malesuada purus a dolor vestibulum
+pretium cursus metus adipiscing. Nunc luctus, felis a consectetur
+rutrum, lacus lectus ultricies odio, sed convallis odio sapien vitae
+eros. Nam consequat rutrum justo a tristique. Praesent in blandit
+turpis.
+</p>
+<p>Vivamus lorem elit, semper vel interdum venenatis, bibendum in nisl.
+Sed volutpat venenatis lacus non aliquet. In gravida consectetur
+tortor, eget varius nisi facilisis nec. Nulla facilisi. Etiam vitae
+nunc viverra diam iaculis mollis. Pellentesque eget pharetra risus.
+Fusce eget massa tellus, ut suscipit lectus. Proin fermentum felis eu
+odio pellentesque iaculis. Morbi ornare neque ut eros pellentesque
+hendrerit. Etiam vel orci sit amet elit adipiscing tristique.
+</p>
+<p>Etiam congue nisl sit amet dolor hendrerit aliquet. Aliquam erat
+volutpat. Donec hendrerit dui in tellus imperdiet porttitor interdum
+eros elementum. Curabitur accumsan pulvinar volutpat. Proin blandit
+eros sit amet tortor pulvinar faucibus. Suspendisse diam sapien,
+blandit in faucibus a, ornare quis sapien. Nulla facilisi. Mauris ac
+leo et erat ultricies ullamcorper sit amet egestas risus. Etiam lectus
+odio, ornare eget sodales at, tempus sit amet dolor. Aenean id ante at
+magna eleifend pharetra. Vivamus dapibus condimentum risus, dignissim
+faucibus dui euismod non. Curabitur venenatis neque lectus, eget
+ullamcorper lacus. Etiam at rhoncus mi. Fusce sem diam, lacinia in
+ornare vel, pellentesque sed diam. Sed feugiat velit auctor quam
+adipiscing sodales. Donec euismod luctus velit, eget ullamcorper metus
+accumsan vel. Fusce eu turpis nunc. Donec vehicula, tellus id faucibus
+convallis, lectus erat vestibulum erat, in aliquet arcu erat at orci.
+</p>
+<p>Nam suscipit, nulla non ornare dignissim, purus purus feugiat justo,
+a lobortis ipsum enim sed quam. Suspendisse placerat tempus augue quis
+rhoncus. Sed faucibus pulvinar turpis ac facilisis. Class aptent taciti
+sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
+Sed in turpis enim. Curabitur posuere ultrices velit et lacinia. Sed et
+molestie lorem. Proin tincidunt nunc et ipsum vulputate lacinia.
+Vestibulum id augue enim. Nunc dignissim congue dui, ut commodo est
+luctus vel. Etiam auctor placerat libero, a lacinia risus fringilla
+porta. Duis pulvinar iaculis metus. Pellentesque non ligula eu lectus
+placerat dictum in sit amet sem. Aenean et mauris vel elit condimentum
+interdum. Donec ultricies, risus non fermentum congue, sapien turpis
+placerat augue, ac congue massa enim vel sem. Maecenas sagittis auctor
+est, in bibendum libero euismod adipiscing. Ut a urna ante.
+</p>
+<p>Fusce odio lorem, fringilla et interdum ac, tristique vel lorem.
+Donec aliquam vehicula felis. Lorem ipsum dolor sit amet, consectetur
+adipiscing elit. Aenean sagittis consequat nisi vitae luctus. Quisque
+venenatis, nulla et dignissim convallis, risus nisi pretium nibh, vitae
+porta erat ipsum vel dui. Nunc ligula ipsum, porta lobortis mattis ac,
+adipiscing at massa. Donec nulla velit, tempus ut scelerisque a,
+imperdiet id tortor. Pellentesque habitant morbi tristique senectus et
+netus et malesuada fames ac turpis egestas. Suspendisse in nunc quam.
+Sed facilisis sem nulla. Donec ullamcorper mollis urna sit amet
+malesuada. In hac habitasse platea dictumst. Etiam ligula sapien,
+aliquet eget eleifend nec, lacinia vel nisl. Sed porttitor dignissim
+nisl lacinia tincidunt. Cras ullamcorper odio vitae ligula scelerisque
+elementum consequat sem viverra. Etiam sit amet fringilla libero. Cras
+ultricies feugiat neque.
+</p>
+<p>Praesent in libero enim. Proin ullamcorper, lorem sed scelerisque
+sodales, felis odio iaculis eros, euismod ultrices dolor nisl eu
+tortor. Maecenas mattis fringilla eleifend. Morbi volutpat, orci ut
+ultricies pharetra, risus nunc cursus lectus, et sodales arcu turpis at
+purus. Cras dapibus, velit id cursus hendrerit, dolor nunc cursus arcu,
+sed interdum massa nibh ac felis. Sed purus lectus, mattis at pulvinar
+eu, volutpat in nulla. Class aptent taciti sociosqu ad litora torquent
+per conubia nostra, per inceptos himenaeos. Vivamus condimentum libero
+quis nisl lobortis sit amet lobortis velit pulvinar. Integer nec est
+erat. Cras adipiscing, nibh vitae fermentum mollis, elit leo consequat
+turpis, nec convallis diam orci vel massa. Nulla lectus sapien,
+volutpat vel venenatis a, feugiat nec neque. Proin dignissim justo non
+augue interdum tempus fringilla erat varius. Donec gravida laoreet
+metus a venenatis. Vivamus eu sem nec sem interdum facilisis vitae et
+neque. Nullam dapibus viverra diam, eu varius metus mollis vel. Aenean
+eu turpis aliquet dui pellentesque posuere. Pellentesque consectetur,
+dui non dignissim gravida, ligula eros sodales est, rutrum elementum
+lacus sapien ac lorem. Quisque ac posuere massa. Nulla facilisi. Class
+aptent taciti sociosqu ad litora torquent per conubia nostra, per
+inceptos himenaeos.
+</p>
+<p>Pellentesque habitant morbi tristique senectus et netus et malesuada
+fames ac turpis egestas. Ut blandit, turpis vitae luctus vestibulum,
+quam libero fermentum magna, eu ultricies eros justo pharetra lorem.
+Aenean non enim vel sem convallis porta ut in nulla. Proin placerat
+dignissim placerat. Praesent tellus leo, auctor quis placerat ut,
+posuere id nunc. Nam sed mi interdum ante auctor pellentesque nec non
+mauris. Aliquam leo dolor, pretium at auctor eu, adipiscing et magna.
+Nulla ante tortor, porta non suscipit volutpat, porta ac metus. Integer
+vitae sapien diam, in venenatis sem. Suspendisse eget odio vel dui
+tempus viverra ut vitae nulla. Quisque quis felis tellus, et eleifend
+nunc.
+</p>
+<p>Nullam dictum volutpat odio eget placerat. Sed hendrerit magna eu
+purus pulvinar commodo. Quisque et purus sed elit convallis hendrerit
+sit amet sed lorem. Pellentesque habitant morbi tristique senectus et
+netus et malesuada fames ac turpis egestas. Sed hendrerit blandit
+libero sit amet eleifend. Pellentesque habitant morbi tristique
+senectus et netus et malesuada fames ac turpis egestas. Aenean euismod,
+libero at laoreet tempus, erat neque condimentum risus, eu convallis
+ipsum nunc et tellus. Etiam accumsan semper felis in scelerisque. Cras
+euismod fermentum risus, vel gravida tellus pretium ac. Nunc nec quam
+eu neque iaculis adipiscing sit amet eu lorem. Vestibulum orci diam,
+semper eu tempus vel, iaculis ac elit. Phasellus at tellus in nunc
+condimentum consectetur. Phasellus molestie justo sit amet risus
+vestibulum adipiscing venenatis eros consectetur. Maecenas quis sapien
+nunc, ut molestie diam. Praesent nec ipsum ipsum, ut posuere nulla.
+Nulla facilisi. Vestibulum nec facilisis nisi. Suspendisse potenti.
+Suspendisse accumsan enim at quam molestie fermentum. Nullam vel risus
+mi, vitae elementum ante.
+</p>
+<p>Suspendisse libero magna, elementum vitae molestie in, tempor ut
+dolor. Nam congue laoreet adipiscing. In pharetra lectus ac justo
+porttitor in gravida dui aliquam. Sed congue leo ut nisl tristique non
+luctus ipsum sagittis. Vivamus ullamcorper mattis ligula in ultricies.
+Donec blandit, ligula vel rutrum vestibulum, massa tellus convallis
+leo, faucibus egestas tellus felis a turpis. Integer ornare aliquam
+purus at cursus. Vestibulum ante ipsum primis in faucibus orci luctus
+et ultrices posuere cubilia Curae; Ut tincidunt mauris ut nibh gravida
+tincidunt. Fusce egestas, lorem a interdum interdum, velit dui euismod
+enim, ac consequat ligula libero lacinia est. Vivamus auctor feugiat
+leo, vel porta dolor eleifend rhoncus.
+</p>
+<p>Suspendisse rutrum tortor in nulla feugiat vitae malesuada metus
+volutpat. Duis aliquet velit sed lectus lacinia porttitor. Donec in
+lorem eget est hendrerit fringilla vel nec felis. Mauris non lorem est.
+Sed sagittis augue sed tortor luctus et porttitor sapien placerat.
+Quisque eu nisl est, at porttitor lorem. Nam dictum turpis sapien.
+Fusce feugiat posuere metus eu vehicula. Phasellus est enim, dignissim
+in tempus ultricies, interdum sit amet ante. Morbi gravida sodales mi,
+a interdum purus lobortis ut. Etiam semper placerat dolor eget mollis.
+Nulla diam arcu, egestas non auctor quis, feugiat nec nulla. Nulla sit
+amet elit sit amet quam euismod sollicitudin. Etiam euismod, odio sit
+amet congue gravida, massa nulla aliquet lorem, in condimentum risus
+tellus ut augue. Etiam a turpis quam. Phasellus lacinia feugiat
+hendrerit. Integer et sapien odio, vestibulum varius augue. Phasellus
+convallis tincidunt odio lacinia ultricies. Aenean quis est vitae nibh
+molestie ultricies.
+</p>
+<p>Aenean lacus magna, porttitor eu posuere ac, varius eu felis. Morbi
+ullamcorper, metus dictum mollis eleifend, orci dolor lobortis urna,
+eget bibendum lorem ligula a ligula. Aliquam quis diam mi, vitae
+tincidunt dolor. Phasellus non libero et nulla interdum consectetur. In
+hac habitasse platea dictumst. Donec justo velit, consectetur at
+aliquet in, viverra a enim. Nam nec mi eget nibh malesuada vestibulum.
+Vivamus id quam vitae enim interdum faucibus eget sed libero. Aliquam
+ligula lacus, elementum id adipiscing eu, vulputate nec massa. Donec
+facilisis sapien ac ante faucibus eleifend.
+</p>
+<p>Pellentesque vel odio vel risus gravida auctor nec eget nisi.
+Vestibulum tincidunt bibendum purus ac lacinia. Aliquam est nisi,
+ullamcorper lacinia venenatis nec, tempor in nulla. Mauris tincidunt
+purus lobortis elit laoreet sagittis. Duis congue cursus facilisis. Sed
+ultricies nunc at purus venenatis at rutrum velit varius. Quisque quis
+velit a risus consectetur accumsan vel eget nisi. Vivamus semper est et
+velit ultricies laoreet. Aenean arcu sapien, commodo quis tempor
+lobortis, mollis vitae dolor. Duis iaculis urna in nunc pulvinar porta.
+Fusce leo arcu, tempus id interdum ultricies, scelerisque eu nunc.
+Fusce ut nibh eu velit sodales gravida. In lorem mi, mattis sed pretium
+ut, tincidunt quis nunc. Donec sed velit libero. Suspendisse potenti.
+</p>
+<p>Aenean sit amet odio elit, ut aliquet mauris. Vestibulum condimentum
+faucibus magna ac facilisis. Mauris feugiat, nunc quis condimentum
+pharetra, nibh metus aliquet tellus, vitae laoreet erat tortor et
+lorem. Morbi sit amet elit lectus, nec placerat ante. Nam commodo
+ultricies sollicitudin. Integer dictum, turpis vitae convallis mollis,
+libero nulla tincidunt magna, eu cursus risus lorem eget felis. Integer
+tempus urna eget erat accumsan sed congue augue molestie. Mauris ipsum
+velit, tempor sit amet luctus in, imperdiet in augue. Fusce id
+venenatis metus. Vivamus sodales, augue aliquam suscipit volutpat,
+mauris est ullamcorper lectus, sit amet interdum tortor enim ac magna.
+Nunc tempor, turpis id commodo imperdiet, justo massa pretium ipsum, at
+ullamcorper justo magna et ante. Curabitur at neque ac elit volutpat
+facilisis vitae non lacus.
+</p>
+<p>Aliquam sagittis, augue non feugiat consequat, erat lacus tincidunt
+orci, ac porta lacus mi sed arcu. Lorem ipsum dolor sit amet,
+consectetur adipiscing elit. Praesent ut ultrices neque. Pellentesque
+aliquet massa nunc, ut vulputate est. Suspendisse eleifend convallis
+tellus quis aliquet. Morbi non libero metus. Maecenas et leo est.
+Suspendisse pretium mollis malesuada. Proin ac nulla sit amet quam
+eleifend elementum ac fermentum neque. Etiam nisi nulla, suscipit vel
+aliquam vel, aliquam ac lacus. Class aptent taciti sociosqu ad litora
+torquent per conubia nostra, per inceptos himenaeos. Maecenas purus
+lectus, scelerisque et volutpat vel, placerat vitae quam. Proin euismod
+eleifend enim, faucibus adipiscing nibh pulvinar vitae. Lorem ipsum
+dolor sit amet, consectetur adipiscing elit. Praesent pretium, tortor
+sed congue imperdiet, sapien libero cursus dolor, at sodales orci urna
+ac diam. Maecenas eu risus vel tortor egestas volutpat id non dolor.
+</p>
+<p>Praesent pellentesque arcu eget augue pellentesque ullamcorper.
+Nulla vel ipsum in nibh congue imperdiet. Morbi non congue ante. Aenean
+pharetra vestibulum adipiscing. Cras tellus orci, sagittis ut tempor
+et, commodo eu tortor. Phasellus ullamcorper, lorem ac mollis viverra,
+enim felis euismod eros, sed molestie nisi tortor quis dolor. Donec ut
+dolor lacus. Nam quis libero metus. Etiam mi risus, pulvinar non ornare
+sit amet, auctor eu odio. Aenean quis nisi at justo ullamcorper
+euismod. Aenean sapien velit, interdum at posuere ac, tristique eu
+magna. Phasellus in nisl at massa egestas vehicula. Suspendisse at
+tincidunt quam. In lobortis hendrerit aliquet. Nullam lobortis odio
+turpis. Maecenas mattis leo ut nunc lacinia nec laoreet lacus posuere.
+</p>
+<p>Sed scelerisque molestie dignissim. Donec aliquet, massa a viverra
+vestibulum, est urna mollis nibh, vel mattis nibh tellus in magna.
+Aenean consequat fringilla risus at vulputate. Cum sociis natoque
+penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+Phasellus aliquet gravida tellus et pulvinar. Pellentesque facilisis
+pulvinar urna, nec vestibulum tellus facilisis ut. Phasellus augue
+magna, pretium in sagittis tempor, dignissim in urna. Fusce id turpis
+id magna dictum convallis sed sed ligula. Quisque pharetra, nunc id
+tincidunt adipiscing, lectus risus mattis elit, nec vulputate metus
+orci eget mi. Phasellus ac urna eget dui facilisis vehicula. Maecenas
+bibendum, metus ac tincidunt consequat, metus mauris semper odio, eu
+luctus tellus ipsum et risus.
+</p>
+<p>Nam nibh nisi, volutpat in cursus vitae, sagittis quis elit. Aliquam
+ornare, magna a gravida aliquam, felis augue sodales ligula, in
+pellentesque massa risus blandit velit. Vivamus purus felis, porttitor
+ac ultricies et, porta id mi. Phasellus sed elit eu massa molestie
+facilisis. Aliquam faucibus mauris et nisi vestibulum malesuada. Duis
+vel lacus a enim feugiat rutrum eu sit amet ligula. Aenean magna mi,
+tristique nec posuere pulvinar, pretium eu sapien. Pellentesque orci
+quam, ultricies ut placerat a, aliquet eget nisi. Phasellus neque eros,
+imperdiet nec pharetra vitae, viverra vel purus. In hac habitasse
+platea dictumst. Integer porttitor dapibus tellus, non ornare dolor
+facilisis tempor. Suspendisse pharetra sodales urna, eu congue turpis
+tristique quis. Sed sodales pulvinar urna, nec dictum arcu vestibulum
+porta.
+</p>
+<p>Vivamus in nisl in odio dapibus fermentum sit amet vitae tellus.
+Maecenas nec nisl eros, nec molestie libero. Phasellus iaculis ipsum
+eget ligula condimentum in elementum neque elementum. Nam tortor nibh,
+ultricies eu aliquam eget, faucibus sed arcu. Vestibulum laoreet
+faucibus est vel vulputate. Duis mollis mauris et lectus pretium ut
+feugiat sem bibendum. Cras erat mauris, condimentum et pharetra nec,
+egestas eu purus. Maecenas ac diam purus. Proin sed augue nibh, quis
+egestas metus. Mauris pellentesque leo lectus. Proin ornare mattis
+bibendum. Etiam aliquet rutrum lacus et iaculis. Mauris aliquam varius
+lacus eu ornare. Etiam quis nisi nisl, aliquam adipiscing est. Etiam
+egestas lacus eleifend nibh fermentum pellentesque. Sed ac lacus id mi
+posuere tempus.
+</p>
+<p>Aliquam enim orci, tempus sit amet euismod eget, sollicitudin vitae
+turpis. Integer sed metus ultricies felis consequat ullamcorper. Lorem
+ipsum dolor sit amet, consectetur adipiscing elit. Sed nec dignissim
+purus. In hac habitasse platea dictumst. Quisque eu neque velit, eget
+tincidunt purus. Integer vitae augue sed urna feugiat pharetra eget
+dapibus felis. Maecenas luctus velit a mauris venenatis tempus. Nam
+sagittis est vitae ipsum eleifend euismod. Phasellus eu massa sed neque
+sodales feugiat vel et mi. Sed eget lorem ut justo pulvinar lacinia.
+Duis adipiscing leo in mauris tincidunt condimentum.
+</p>
+<p>Donec tincidunt, ligula ac euismod ultrices, lacus lorem auctor
+mauris, sed pretium felis ipsum sed nunc. Aliquam sit amet nulla dui,
+eu adipiscing nisi. Vestibulum vulputate, nunc ac pellentesque
+accumsan, augue metus adipiscing nulla, at varius tortor quam et
+ligula. Suspendisse potenti. In consectetur neque sit amet quam
+malesuada quis congue mi vehicula. Etiam sit amet neque eget mauris
+cursus eleifend. Ut euismod ipsum in sapien sagittis venenatis. Aenean
+orci erat, tincidunt id malesuada non, consectetur aliquet justo.
+Mauris luctus enim quis ligula mattis pharetra. Proin at neque et orci
+ullamcorper auctor at vel metus. Pellentesque ultrices lacinia lacus
+tincidunt scelerisque. Pellentesque sit amet lacus in dolor lobortis
+imperdiet vitae eget risus. Sed feugiat porttitor accumsan.
+Pellentesque habitant morbi tristique senectus et netus et malesuada
+fames ac turpis egestas.
+</p>
+<p>Sed tortor dolor, euismod eu vestibulum vel, laoreet sed libero.
+Morbi a erat leo. Sed eros turpis, pretium ut placerat eu, laoreet id
+massa. Nunc quis imperdiet lacus. Vivamus in nisi at ipsum adipiscing
+fermentum. Fusce nec malesuada ipsum. In hac habitasse platea dictumst.
+Suspendisse rhoncus faucibus purus, at molestie leo porta eget. Nam
+viverra odio sed arcu tincidunt sed cursus sem lobortis. Phasellus elit
+est, auctor eu consectetur a, porttitor ac tortor. Morbi consectetur
+mauris et sem semper eget adipiscing eros faucibus. Lorem ipsum dolor
+sit amet, consectetur adipiscing elit. Cras in cursus velit. Sed vel
+purus odio. Sed ut leo nec purus luctus aliquam. Cras ullamcorper
+convallis erat eu pellentesque. Phasellus felis tellus, ullamcorper sit
+amet aliquet et, vestibulum eget tortor. Praesent id dolor et turpis
+vestibulum sagittis. Ut ligula turpis, sollicitudin vel aliquet sed,
+vulputate et mi. Aenean consequat massa a justo facilisis consectetur.
+</p>
+<p>Donec sodales mattis enim sit amet sagittis. Sed feugiat eros vitae
+justo semper cursus ac ac erat. Aliquam nec odio non mi fermentum
+rutrum. Mauris posuere, arcu ac convallis fringilla, nisi dolor
+facilisis nisl, placerat condimentum est odio ac lacus. Vestibulum ante
+ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;
+Quisque luctus risus sed arcu elementum malesuada. Aenean eu turpis
+sapien. Nam eget leo purus. Nulla accumsan condimentum mattis.
+Suspendisse volutpat risus vel neque bibendum tempor. Donec gravida,
+urna ac semper suscipit, nibh mauris blandit neque, non congue lorem mi
+ac nunc. Morbi varius sagittis elementum. Vivamus ut libero a enim
+porta mollis. Morbi quis sem id erat convallis scelerisque. Vivamus
+eleifend posuere tempus.
+</p>
+<p>Class aptent taciti sociosqu ad litora torquent per conubia nostra,
+per inceptos himenaeos. In consequat ultrices nunc quis faucibus.
+Nullam ac sagittis orci. Donec non mi tellus, ut commodo ligula.
+Suspendisse vel ante id dui consequat iaculis porta eu urna. Vestibulum
+diam sem, sollicitudin ut ultricies at, rhoncus vitae dui. Etiam erat
+elit, lobortis vitae tempor eu, feugiat sit amet enim. Mauris suscipit
+rhoncus faucibus. Integer magna sapien, imperdiet ac semper a, semper
+eget nulla. Nullam justo lacus, ullamcorper consectetur semper sed,
+mollis eget metus. Proin lobortis eros id ipsum mattis ornare. Sed
+luctus pretium justo, at rutrum odio pellentesque in. Vestibulum at
+erat arcu, in porttitor metus. Donec porta nisi eros. Curabitur sodales
+lobortis ligula, vel semper velit mollis vitae. Aliquam dignissim ante
+eu massa tempus euismod. Curabitur dictum convallis aliquam. Fusce
+ipsum libero, rhoncus ullamcorper cursus in, mattis a libero.
+</p>
+<p>Maecenas nunc tellus, condimentum ut vulputate non, varius sit amet
+elit. Ut malesuada erat ut arcu tincidunt id fermentum turpis
+consequat. Sed quam urna, placerat sit amet congue quis, rhoncus eu
+lacus. Maecenas pulvinar feugiat imperdiet. Proin feugiat dui ac sem
+mollis et sodales sapien mattis. Integer sit amet orci at arcu laoreet
+vestibulum. Fusce sit amet lectus magna, adipiscing lobortis diam.
+Donec sagittis magna sed augue placerat dignissim. Pellentesque diam
+dui, faucibus ut bibendum sit amet, posuere eu massa. Nunc feugiat elit
+eu dui pulvinar eu hendrerit ante consequat. Vestibulum nibh metus,
+congue a pretium a, consequat in arcu. Ut nibh elit, feugiat eu
+malesuada sed, sodales et dui. Nulla et quam nisl, sit amet placerat
+mi. Fusce egestas lobortis lacus, non tempus nulla volutpat quis. Sed
+quis nisi ligula, sit amet malesuada orci. Quisque et vehicula elit.
+Suspendisse vel nunc libero. Cras in ipsum lectus. Proin bibendum arcu
+rutrum augue ornare et imperdiet felis sollicitudin.
+</p>
+<p>Integer sem dui, suscipit eget convallis eu, imperdiet vitae magna.
+Nulla turpis erat, semper ac sodales at, bibendum eget mauris. Morbi
+auctor nunc ultricies arcu sagittis rhoncus. Duis viverra risus sit
+amet sapien interdum molestie. Donec ornare massa eget purus dignissim
+eu tristique velit tincidunt. Etiam ullamcorper est sodales erat mattis
+eget consequat massa hendrerit. Nunc neque est, congue in gravida
+vitae, tempor et diam. Pellentesque convallis hendrerit lectus, id
+congue augue ultricies vitae. Cras at urna eu nunc sagittis tincidunt
+eu eget dui. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+Proin ut enim dapibus dolor vestibulum condimentum. In vitae dui at
+magna porta posuere. Nunc id est turpis. Donec tempus, leo id volutpat
+vestibulum, urna sem vulputate leo, eget blandit turpis tortor
+vestibulum odio.
+</p>
+<p>Maecenas et nibh ut felis pharetra varius. Mauris porta porttitor
+neque quis consequat. Mauris sit amet erat orci. Integer nisl ligula,
+lacinia at aliquet eu, facilisis eu elit. Duis nec ligula risus.
+Vivamus vel odio non lorem interdum fringilla. Mauris massa nibh,
+ornare at tempus ut, iaculis sit amet leo. Aliquam ligula dolor,
+consectetur a hendrerit ut, pharetra mollis est. Vivamus vel ornare
+lectus. Aenean nunc metus, porttitor ut varius sit amet, blandit
+ultricies elit. Mauris et lectus sem. Vestibulum tortor felis, pharetra
+id molestie at, sollicitudin non neque. Curabitur sodales tortor vel
+mauris pulvinar vitae molestie arcu eleifend. Phasellus molestie
+fringilla dolor vel placerat. Morbi molestie fringilla pellentesque.
+Mauris tempor ornare hendrerit. Suspendisse lacinia interdum aliquet.
+Integer interdum lectus condimentum turpis rutrum dignissim et in nunc.
+</p>
+<p>Vivamus bibendum neque non quam egestas eget rhoncus erat porttitor.
+Sed vel ante sed quam auctor mollis. Duis nec aliquet sem. Phasellus at
+arcu ante. Morbi egestas hendrerit tempus. Vivamus nec interdum velit.
+Nunc ornare lacus ac metus pretium varius. Morbi lobortis mollis
+varius. Nulla quis nunc tortor. Integer tempus condimentum lacus eu
+posuere. Suspendisse potenti. Proin non elementum turpis. Integer
+tempus arcu arcu, vitae hendrerit diam. Pellentesque habitant morbi
+tristique senectus et netus et malesuada fames ac turpis egestas.
+</p>
+<p>Fusce mollis est vitae leo viverra bibendum. Nulla vitae metus
+lacus. Pellentesque habitant morbi tristique senectus et netus et
+malesuada fames ac turpis egestas. Morbi ante leo, gravida vitae mattis
+vel, sagittis commodo nibh. Etiam molestie ornare lorem sit amet
+luctus. Vivamus fermentum imperdiet elit. Quisque erat est, ullamcorper
+non porttitor vitae, elementum ut eros. Proin fermentum, leo ut lacinia
+tempor, ipsum neque porttitor risus, a fringilla nunc magna id leo.
+Proin hendrerit libero non libero imperdiet eleifend. Mauris fringilla
+diam id tellus tincidunt euismod. Donec dui turpis, hendrerit nec
+auctor vitae, sagittis vel purus. In mattis sapien eu est suscipit vel
+accumsan ipsum vulputate. Mauris sit amet eleifend elit. Donec vel est
+odio, ut fringilla urna. Quisque ac malesuada orci. Vivamus ultricies
+elit turpis, et bibendum ipsum.
+</p>
+<p>Aenean porta, nisl vel malesuada fermentum, orci eros pretium metus,
+at euismod erat augue a tellus. Suspendisse bibendum tellus sit amet
+augue sodales quis suscipit urna lobortis. Proin ullamcorper pharetra
+risus, a rhoncus orci auctor id. Pellentesque habitant morbi tristique
+senectus et netus et malesuada fames ac turpis egestas. Suspendisse
+dapibus ultrices lacus quis consectetur. Aenean ultricies convallis
+commodo. Suspendisse ligula elit, tempus id aliquet nec, ornare aliquam
+risus. Curabitur consectetur tincidunt nunc eu convallis. Pellentesque
+pulvinar, odio at molestie viverra, nibh nisi pulvinar est, nec
+fermentum massa lorem sit amet leo. Vivamus euismod turpis non lorem
+ullamcorper pretium eu tempus velit. Nullam eu augue quam, ac tincidunt
+mi. Proin id tristique sapien. Vivamus pretium nisl sed diam blandit eu
+facilisis erat ornare. In libero velit, ultricies et fringilla at,
+tincidunt ut odio. In non nisl neque, in cursus lorem. Curabitur justo
+nunc, suscipit eu congue ac, malesuada quis nisi. Aliquam in est augue.
+Cras rhoncus dolor et lacus blandit eget tempus nibh elementum.
+</p>
+<p>Cum sociis natoque penatibus et magnis dis parturient montes,
+nascetur ridiculus mus. Vestibulum elementum enim a risus commodo sit
+amet condimentum libero mattis. Ut egestas sem leo. Ut consectetur,
+sapien sed malesuada scelerisque, velit purus vulputate dolor, at
+egestas magna metus quis urna. Mauris bibendum, nisi rhoncus pharetra
+facilisis, purus purus condimentum quam, a semper est sapien lacinia
+magna. Sed pharetra, metus eu auctor accumsan, turpis nisi gravida
+orci, hendrerit bibendum diam nulla iaculis massa. Fusce a libero at
+purus pulvinar faucibus eget in arcu. Praesent nunc magna, malesuada ac
+viverra id, accumsan quis velit. Morbi ac eros quis nibh accumsan
+sagittis id vel enim. Etiam turpis nisl, sodales nec mattis non,
+sagittis non nibh. Nam eget nisl urna. Pellentesque magna leo, lobortis
+id egestas nec, gravida at odio.
+</p>
+<p>In sed ligula est, sed consectetur nunc. Sed blandit, dui ut
+imperdiet dignissim, libero lacus euismod metus, in semper mi nunc at
+odio. Etiam dapibus mattis mollis. Vivamus lobortis, nisi vestibulum
+commodo vehicula, arcu risus accumsan nulla, vel pulvinar risus libero
+eu turpis. Mauris volutpat tortor ut nunc sodales ut suscipit urna
+volutpat. Vestibulum tincidunt elementum nunc at hendrerit. Vestibulum
+purus nisi, scelerisque in ullamcorper a, euismod sit amet velit.
+Aliquam cursus ligula ligula, a gravida tellus. Nam elit tellus,
+volutpat eget bibendum a, facilisis vel eros. Aenean eu ultrices
+mauris. Morbi purus diam, tincidunt non feugiat id, accumsan ut enim.
+Vivamus tincidunt erat et felis interdum eget accumsan nunc vehicula.
+Pellentesque habitant morbi tristique senectus et netus et malesuada
+fames ac turpis egestas. Aliquam id ullamcorper dolor. Morbi quis enim
+ac neque congue gravida. Sed sodales est eget felis euismod facilisis.
+</p>
+<p>Phasellus ultrices, risus in dapibus faucibus, ligula massa
+hendrerit sapien, sit amet laoreet metus nunc at dui. Maecenas id nunc
+elit, nec viverra purus. Pellentesque semper bibendum pretium. Aliquam
+erat volutpat. Aenean non nulla odio, sed condimentum arcu. Donec vitae
+adipiscing sapien. Mauris tincidunt libero quis massa ultricies sed
+varius dolor bibendum. Integer sit amet tellus massa. Proin auctor
+eleifend consequat. Vivamus suscipit nisi vitae ante viverra et rutrum
+justo consectetur. Fusce nisi enim, vulputate ut auctor id, pretium
+vitae sem. Etiam vel orci lorem. Suspendisse eu dignissim tortor. Duis
+a turpis dolor, eu tempus velit.
+</p>
+<p>Aenean lacus felis, fermentum ut dapibus sed, ullamcorper a risus.
+Donec luctus lobortis augue non vulputate. Sed viverra sollicitudin
+porta. Sed quam lorem, commodo sed cursus at, varius vitae sem. Nunc
+quam lacus, accumsan a luctus vel, faucibus eget urna. Nullam ut quam
+arcu. Maecenas hendrerit libero non ipsum facilisis id congue quam
+sodales. Fusce sagittis luctus ligula, at sagittis justo consectetur a.
+Donec egestas risus ut ipsum feugiat sit amet congue felis egestas. Nam
+et sollicitudin quam.
+</p>
diff --git a/dojox/html/tests/performance/module.js b/dojox/html/tests/performance/module.js
new file mode 100755
index 0000000..1aa3901
--- /dev/null
+++ b/dojox/html/tests/performance/module.js
@@ -0,0 +1,6 @@
+dojo.provide("dojox.html.tests.performance.module");
+if(dojo.isBrowser){
+	dojo.require("dojox.html.tests.performance.format");
+}
+
+
diff --git a/dojox/html/tests/performance/runTests.html b/dojox/html/tests/performance/runTests.html
new file mode 100755
index 0000000..3af65dd
--- /dev/null
+++ b/dojox/html/tests/performance/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../../util/doh/runner.html?testModule=dojox.html.tests.performance.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/html/tests/performance/smalldoc.txt b/dojox/html/tests/performance/smalldoc.txt
new file mode 100755
index 0000000..48cba09
--- /dev/null
+++ b/dojox/html/tests/performance/smalldoc.txt
@@ -0,0 +1,77 @@
+<p>
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec pharetra
+cursus elit, id sagittis mauris egestas et. Vivamus elementum, quam
+vitae varius congue, mi arcu rhoncus neque, in consequat metus metus
+nec augue. Quisque tristique dignissim massa et placerat. Sed ligula
+nisi, accumsan at accumsan ac, facilisis nec urna. In nec dui non enim
+blandit luctus vel sed urna. In vel lacinia dolor. Curabitur euismod
+ullamcorper mi, vel pharetra justo mollis eget. Curabitur adipiscing,
+urna et fringilla aliquam, augue neque sodales nulla, in elementum leo
+nunc sit amet erat. Sed ultricies fringilla nisl vel dapibus. Nam eget
+odio vitae mauris laoreet sagittis. Aenean interdum nibh in justo
+convallis sagittis. Cras ornare ultricies interdum. In placerat
+dignissim blandit.
+</p>
+<p>Nunc gravida nibh vitae purus ultricies ullamcorper. Vestibulum ante
+ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae;
+Pellentesque placerat enim mi, pellentesque facilisis enim. Donec eu
+ante vitae enim lacinia tempus vel faucibus lorem. Maecenas non lacus
+est. Cras viverra enim sed erat tempus vestibulum. Vivamus nec nunc
+purus. Quisque id velit turpis. Nulla ullamcorper consectetur bibendum.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam nec
+enim odio, dapibus pellentesque purus. Proin sit amet dolor tortor.
+Phasellus semper lacus mattis dolor auctor id cursus est mollis.
+Integer nibh nulla, pretium eget euismod id, facilisis ut dui. Aliquam
+erat volutpat. Cras convallis pellentesque est eget ornare. Nunc vel
+scelerisque tellus. Pellentesque nunc elit, interdum id pretium sit
+amet, dictum quis risus.
+</p>
+<p>Etiam at nulla leo, a tincidunt lectus. Vivamus odio massa, viverra
+vel consectetur non, sagittis in nisl. Mauris malesuada arcu nec leo
+eleifend in accumsan purus molestie. In sit amet lorem magna, et
+vestibulum mauris. Praesent lacinia, diam sit amet lacinia varius,
+lorem lacus porta elit, sed pretium nulla orci vitae justo. Aliquam
+vulputate, risus nec blandit placerat, sapien tellus dictum neque, et
+elementum libero quam sit amet magna. Suspendisse auctor elit sit amet
+turpis fringilla sed vulputate est molestie. Phasellus ipsum elit,
+tempor vitae eleifend sit amet, accumsan ac nisi. Aliquam erat
+volutpat. Integer semper orci sed massa bibendum interdum. Suspendisse
+potenti. Donec consectetur, mi at fermentum egestas, ipsum ipsum
+placerat velit, eget interdum lacus neque et elit. Nulla pharetra lacus
+at nunc dignissim pharetra. Vestibulum ante ipsum primis in faucibus
+orci luctus et ultrices posuere cubilia Curae; Nulla dapibus iaculis
+magna in aliquet. Suspendisse lacinia libero id dui pharetra hendrerit
+nec nec ligula. Donec eget lacus sit amet metus mattis condimentum et
+at metus.
+</p>
+<p>Quisque consectetur ullamcorper tincidunt. Duis accumsan odio in
+velit volutpat suscipit. Integer hendrerit nunc dapibus dui blandit vel
+convallis nulla vulputate. Nam facilisis vestibulum est nec faucibus.
+Duis bibendum erat a sem scelerisque eget tincidunt diam elementum. Ut
+in sem metus, id dictum sem. Ut ac lacus sit amet risus vestibulum
+adipiscing. Cras vel lorem neque, sit amet lobortis purus. In
+consectetur interdum nunc nec scelerisque. Phasellus tempus pretium
+velit, id facilisis libero vestibulum eget. Donec tempus elementum orci
+in accumsan. Aliquam ut nulla sit amet purus ullamcorper congue non sit
+amet arcu. Proin molestie, augue a placerat aliquet, justo sem aliquam
+diam, vitae fermentum lectus velit in risus. Morbi fringilla purus
+interdum ipsum ornare congue. Proin mi leo, sodales id eleifend dictum,
+blandit a ante. Praesent varius orci vitae dolor gravida eleifend. Sed
+euismod, orci et rutrum commodo, augue nulla adipiscing nunc, porta
+mollis mauris enim sed nisi. Donec ligula eros, sagittis sit amet
+facilisis at, condimentum non sapien. Nullam sit amet magna ipsum, in
+viverra lectus.
+</p>
+<p>Praesent nisl lectus, convallis nec gravida vel, vestibulum sed
+lorem. Morbi bibendum justo ac mauris interdum fermentum. Curabitur
+hendrerit, dui rhoncus blandit suscipit, nisi nisi sodales lectus, sed
+ullamcorper nisi nisl at purus. Suspendisse nibh lorem, varius ut
+venenatis non, auctor tincidunt dui. Praesent porta augue placerat dui
+ultricies tempus. Integer non arcu sed est facilisis pharetra quis
+eleifend ligula. Integer pellentesque porttitor volutpat. Duis pulvinar
+orci ut massa tempor mattis. Vestibulum vitae enim metus, sit amet
+lobortis leo. Praesent neque justo, pretium at laoreet luctus,
+elementum non elit. Nam vulputate laoreet quam venenatis elementum.
+Vestibulum suscipit velit sed massa sodales malesuada.
+</p>
+
diff --git a/dojox/html/tests/remote/commentedScript.html b/dojox/html/tests/remote/commentedScript.html
new file mode 100755
index 0000000..cc14c73
--- /dev/null
+++ b/dojox/html/tests/remote/commentedScript.html
@@ -0,0 +1,22 @@
+<html>
+	<head>
+		<!-- Commented out as a test that the load code for content pane does NOT include it
+			 as script content.
+		<SCRIPT>
+			var div = document.createElement("div");
+			document.body.appendChild(div);
+			div.innerHTML = "<div id=\"should_not_be_here\"></div>";
+		</SCRIPT>
+		-->
+		<!-- test that entity characters are properly processed in a src url by the ContentPane code. -->
+		<script type="text/javascript" src="remote/getResponse.php?mode=entityChars&entityEscaped=true"></script>
+		<script>
+			//This sets a flag to indicate that the page has loaded and is checked
+			//in the testcase.
+			window.__remotePaneLoaded = true;
+		</script>
+	</head>
+	<body>  
+		Some simple content.
+	</body>
+</html>
diff --git a/dojox/html/tests/remote/getResponse.php b/dojox/html/tests/remote/getResponse.php
new file mode 100644
index 0000000..f991e48
--- /dev/null
+++ b/dojox/html/tests/remote/getResponse.php
@@ -0,0 +1,95 @@
+<?php
+	// this file is just a bouncer for ContentPane.html test
+	error_reporting(E_ALL ^ E_NOTICE);
+	
+	if(isset($_GET['mode'])){
+		switch($_GET['mode']){
+			case 'htmlPaths':
+				echo "<img src='../images/testImage.gif' id='imgTest'/>
+					<div id='inlineStyleTest' style='width:188px;height:125px;background-image:url(../images/testImage.gif)'></div>
+					<style>@import 'getResponse.php?mode=importCss';</style>
+					<link type='text/css' rel='stylesheet' href='getResponse.php?mode=linkCss'>
+					<div id='importCssTest'></div>
+					<div id='linkCssTest'></div>
+					<div id='importMediaTest'></div>
+					<div id='linkMediaTest'></div>
+					<!-- these may download but not render -->
+					<style media='print'>@import 'getResponse.php?mode=importMediaPrint';</style>
+					<link media='print' type='text/css' rel='stylesheet' href='getResponse.php?mode=linkMediaPrint'>
+					";
+				break;
+	
+			case 'importCss':
+				header('Content-type: text/css; charset=utf-8');
+				echo "#importMediaTest {
+					margin: 4px;
+					border: 1px dashed red;
+					width: 200px;
+					height: 200px;
+				}
+				#importCssTest {
+						margin: 4px;
+						border: 1px solid blue;
+						width: 100px;
+						height: 100px;
+					}";
+				break;
+	
+			case 'linkCss':
+				header('Content-type: text/css; charset=utf-8');
+				echo "#linkMediaTest {
+					margin: 4px;
+					border: 2px dashed red;
+					width: 200px;
+					height: 200px;
+				}
+				#linkCssTest {
+					margin: 4px;
+					border: 2px dashed red;
+					width: 100px;
+					height: 100px;
+				}";
+				break;
+
+			case 'importMediaPrint': // may download but not render
+				header('Content-type: text/css; charset=utf-8');
+				echo "#importMediaTest {
+					margin: 10px;
+					border: 5px dashed gray;
+					width: 100px;
+					height: 100px;
+				}";
+				break;
+
+			case 'linkMediaPrint': // may download but not render
+				header('Content-type: text/css; charset=utf-8');
+				echo "#linkMediaTest {
+					margin: 10px;
+					border: 5px dashed gray;
+					width: 100px;
+					height: 100px;
+				}";
+				break;
+	
+			case 'remoteJsTrue':
+				header('Content-type: text/javascript; charset=utf-8');
+				echo "unTypedVarInDocScope = true;";
+				break;
+	
+			case 'remoteJsFalse':
+				header('Content-type: text/javascript; charset=utf-8');
+				echo "unTypedVarInDocScope = false;";
+				break;
+			case 'entityChars':
+				header('Content-type: text/css; charset=utf-8');
+				if($_GET['entityEscaped'] == null){                                                                                    
+					print("var div = document.createElement(\"div\"); document.body.appendChild(div); div.innerHTML = \"<div id=\\\"should_not_be_here2\\\"></div>\"; window.__remotePaneLoaded2 = true;" );
+				}else{
+					print("window.__remotePaneLoaded2 = true;");
+				}
+				break;
+			default:
+				echo "unknown mode: ".htmlentities($_GET['mode']);
+		}
+	}
+?>
diff --git a/dojox/html/tests/runTests.html b/dojox/html/tests/runTests.html
new file mode 100755
index 0000000..11fd391
--- /dev/null
+++ b/dojox/html/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>dojo.data D.O.H. Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.html.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/html/tests/test_ellipsis.html b/dojox/html/tests/test_ellipsis.html
new file mode 100644
index 0000000..dfba203
--- /dev/null
+++ b/dojox/html/tests/test_ellipsis.html
@@ -0,0 +1,431 @@
+<html>
+<head>
+	<title>Ellipsis tests</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+	<style type="text/css">
+		@import "../resources/ellipsis.css";
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: false"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.html.ellipsis");
+		
+		dojo.addOnLoad(function(){
+			// Add in some stuff programmatically after a delay
+			setTimeout(function(){
+				var content = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. " +
+								"Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. " +
+								"Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend " +
+								"sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque " +
+								"egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula " +
+								"lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus " +
+								"fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, " +
+								"sapien ac faucibus feugiat, ligula felis laoreet justo, eu " +
+								"sollicitudin purus purus in nibh. Phasellus in nunc.";
+				dojo.create("hr", {}, dojo.body());
+				dojo.create("div", {className: "heading", innerHTML: "Programmatic and delayed"}, dojo.body());
+				dojo.create("div", {className: "subheading", innerHTML: "Within Div"}, dojo.body());
+				dojo.create("div", {className: "dojoxEllipsis", innerHTML: content},
+							dojo.create("div", {className: "divContainer", style: {width: "100px"}}, dojo.body()));
+
+				dojo.create("div", {className: "subheading", innerHTML: "Within Table (using innerHTML)"}, dojo.body());
+				dojo.create("button", {innerHTML: "Change Data", onclick: function(){
+					var n = dojo.byId("c_1_1");
+					if(n.innerHTML == "Short Text"){
+						n.innerHTML = content;
+					}else if(n.innerHTML == content){
+						n.innerHTML = "<div class='dojoxEllipsis'>" + content + "</div>";
+					}else{
+						n.innerHTML = "Short Text";
+					}
+				}}, dojo.body());
+				var tableDiv = dojo.create("div", {});
+				var tableNode = dojo.create("table", {className: "tableContainer", style: {width: "600px"}}, tableDiv);
+				var inner = "<div class='dojoxEllipsis'>" + content + "</div>";
+				for (var r = 0; r < 3; r++){
+					var tableRow = dojo.create("tr", {}, tableNode);
+					for (var c = 0; c < 3; c++){
+						dojo.create("td", {id: "c_" + r + "_" + c, innerHTML: inner, style: {width: ((c+1)*100) + "px"}}, tableRow);
+					}
+				}
+				var ihtml = tableDiv.innerHTML;
+				tableDiv.innerHTML = "";
+				dojo.body().appendChild(tableDiv);
+				tableDiv.innerHTML = ihtml;
+			}, 1000);
+		});
+	</script>
+	<style>
+		.heading {
+			font-weight: bold;
+			font-size: 1.25em;
+		}
+		.subheading {
+			font-weight: bold;
+			padding-top: 1em;
+		}
+		.divContainer,
+		.tableContainer,
+		.tableContainer td {
+			border: 1px solid #F00;
+		}
+		.tableContainer {
+			/* If using ellipsis inside a table, the 
+				table-layout needs to be set to fixed */
+			table-layout: fixed;
+		}
+	</style>
+</head>
+<body>
+	<div class="heading">Within divs</div>
+	<div class="subheading">Fixed width (px):</div>
+	<div class="divContainer" style="width: 250px; margin-bottom: 0.25em">
+		<div class="dojoxEllipsis">
+			Short data that shouldn't wrap
+		</div>
+	</div>
+	<div class="divContainer" style="width: 250px">	
+		<div class="dojoxEllipsis">
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+			Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+			Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+			sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+			egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+			lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+			fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+			sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+			sollicitudin purus purus in nibh. Phasellus in nunc.
+		</div>
+	</div>
+	<div class="subheading">Fixed width (em):</div>
+	<div class="divContainer" style="width: 20em">
+		<div class="dojoxEllipsis">
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+			Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+			Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+			sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+			egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+			lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+			fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+			sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+			sollicitudin purus purus in nibh. Phasellus in nunc.
+		</div>
+	</div>
+	<div class="subheading">Relative width (% - resize browser window):</div>
+	<div class="divContainer" style="width: 70%">
+		<div class="dojoxEllipsis">
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+			Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+			Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+			sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+			egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+			lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+			fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+			sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+			sollicitudin purus purus in nibh. Phasellus in nunc.
+		</div>
+	</div>
+	<div class="subheading">Floated and margins</div>
+	<div class="divContainer" style="width: 25%; float: right">
+		<div class="dojoxEllipsis">
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+			Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+			Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+			sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+			egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+			lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+			fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+			sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+			sollicitudin purus purus in nibh. Phasellus in nunc.
+		</div>
+	</div>
+	<div class="divContainer" style="width: 25%; float: left">
+		<div class="dojoxEllipsis">
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+			Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+			Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+			sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+			egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+			lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+			fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+			sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+			sollicitudin purus purus in nibh. Phasellus in nunc.
+		</div>
+	</div>
+	<div class="divContainer" style="width: 250px; margin-left: 30%;">
+		<div class="dojoxEllipsis">
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+			Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+			Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+			sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+			egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+			lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+			fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+			sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+			sollicitudin purus purus in nibh. Phasellus in nunc.
+		</div>
+	</div>
+	<div style="clear: both"></div>
+	<hr>
+	<div class="heading">Within tables</div>
+	<div class="subheading">Fixed table, fixed columns:</div>
+	<table class="tableContainer" style="width: 500px;">
+		<tr>
+			<td style="width: 200px;">
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+			<td style="width: 300px;">
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+			<td>
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+		</tr>
+	</table>
+	<div class="subheading">Fixed table, relative columns:</div>
+	<table class="tableContainer" style="width: 500px;">
+		<tr>
+			<td style="width: 25%;">
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+			<td style="width: 75%;">
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+			<td>
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+		</tr>
+	</table>
+	<div class="subheading">Relative table, relative columns:</div>	
+	<table class="tableContainer" style="width: 75%;">
+		<tr>
+			<td style="width: 30%;">
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+			<td style="width: 60%;">
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+			<td>
+				<div class="dojoxEllipsis">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+		</tr>
+	</table>
+	<hr>
+	<div class="heading">With Markup</div>
+	<div class="subheading">Bold/Underline</div>
+	<div class="divContainer" style="width: 25%">
+		<div class="dojoxEllipsis">
+			Some dummy text that should wrap <b><u>right about here</u></b>
+		</div>
+	</div>
+	<div class="subheading">Font Sizes</div>
+	<div class="divContainer" style="width: 250px">
+		<div class="dojoxEllipsis">
+			<font size="1">Some</font> <font size="2">more</font> <font size="3">dummy</font> <font size="4">text</font> <font size="5">getting</font> 
+			<font size="4">bigger</font> <font size="3">and</font> <font size="2">then</font> <font size="1">smaller</font>
+		</div>
+	</div>
+	<div class="subheading">Link</div>
+	<div class="divContainer" style="width: 250px">
+		<div class="dojoxEllipsis">
+			Some dummy text with a <a href="#" onclick="alert('clicked'); return false;">link that should truncate</a>
+		</div>
+	</div>
+	<hr>
+	<div class="heading">Text Selectable (in FF)</div>
+	<table class="tableContainer" style="width: 75%;">
+		<tr>
+			<td style="width: 30%;">
+				<div class="dojoxEllipsis dojoxEllipsisSelectable">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+			<td style="width: 60%;">
+				<div class="dojoxEllipsis dojoxEllipsisSelectable">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<div class="dojoxEllipsis dojoxEllipsisSelectable">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+			<td>
+				<div class="dojoxEllipsis dojoxEllipsisSelectable">
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. 
+					Etiam mattis libero nec ante. Nam porta lacus eu ligula. Cras mauris. 
+					Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+					sagittis turpis. Nullam consequat iaculis augue. Aliquam pellentesque 
+					egestas massa. Curabitur pulvinar, enim vel porta dapibus, ligula 
+					lectus vulputate purus, eu tempus ante dolor id quam. Sed luctus 
+					fermentum nulla. Donec sollicitudin imperdiet risus. Cras cursus, 
+					sapien ac faucibus feugiat, ligula felis laoreet justo, eu 
+					sollicitudin purus purus in nibh. Phasellus in nunc.
+				</div>
+			</td>
+		</tr>
+	</table>
+</body>
+</html>
diff --git a/dojox/html/tests/test_metrics.html b/dojox/html/tests/test_metrics.html
new file mode 100644
index 0000000..edb67f7
--- /dev/null
+++ b/dojox/html/tests/test_metrics.html
@@ -0,0 +1,60 @@
+<html>
+<head>
+<title>Metrics tests</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, fontSizeWatch: true"></script>
+<script type="text/javascript" src="../metrics.js"></script>
+<script type="text/javascript">
+
+dojo.require("dojox.html.metrics");
+
+var sz_to_cell = {};
+
+var updateSize = function(){
+	var sz = dojox.html.metrics.getFontMeasurements();
+	for(var p in sz_to_cell){
+		sz_to_cell[p].innerHTML = sz[p];
+	}
+}
+
+dojo.addOnLoad(function(){
+	dojo.connect(dojox.html.metrics, "onFontResize", function(){
+		console.log("Text size changed: ", dojox.html.metrics.getFontMeasurements());
+		updateSize();
+	});
+	console.log("Scrollbar measurements: ", dojox.html.metrics.getScrollbar());
+	console.log("Font measurements: ", dojox.html.metrics.getFontMeasurements());
+
+	var sz = dojox.html.metrics.getFontMeasurements();
+	for(var p in sz){
+		var row = document.createElement('tr');
+		var rel = document.createElement('td');
+		var act = sz_to_cell[p] = document.createElement('td');
+
+		rel.innerHTML = p;
+		act.innerHTML = sz[p];
+
+		row.appendChild(rel);
+		row.appendChild(act);
+
+		dojo.byId('sz_table').appendChild(row);
+	}
+});
+
+</script>
+</head>
+<body>
+	<div>Try changing the text size of your browser (make sure you're not just zooming the view).</div>
+	<table border="1">
+        <tbody id="sz_table">
+    		<tr>
+    			<th>Relative size</th><th>Actual pixel size (px)</th>
+    		</tr>
+        </tbody>
+	</table>
+</body>
+</html>
diff --git a/dojox/html/tests/test_set.html b/dojox/html/tests/test_set.html
new file mode 100644
index 0000000..a4042bf
--- /dev/null
+++ b/dojox/html/tests/test_set.html
@@ -0,0 +1,1043 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.html.set test</title>
+	<script >
+	function fixPngIE6(){
+		if(this.complete && dojo.isIE < 7){
+			var r = this.runtimeStyle;
+			if(/.png$/i.test(this.src)){
+				r.height = this.height;
+				r.width = this.width;
+				r.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.src+"');";
+				this.src = this.currentStyle.backgroundImage.replace(/url\(\s*['"]?(.+?)['"]?\s*\)/, "$1");
+			}
+			this.className = this.className.replace('run_png_fix', "");
+			r.behaviour = 'none';
+		}
+	}
+	</script>
+	<style type='text/css'>
+		.run_png_fix {
+			background-image:url(images/blank.gif);
+			behaviour: expression(fixPngIE6.call(this));
+		}
+	</style>
+	<script src='../../../dojo/dojo.js' djConfig='isDebug:true, parseOnLoad:true'></script>
+	<script src='../../../dojo/html.js'></script>
+	<script src='../../../dojox/html/_base.js'></script>
+	<script>
+		dojo.require('doh.runner');
+		dojo.require('dojox.html');
+		dojo.require('dojo.parser');
+
+		// used to test if we fire scrips to document scope
+		function documentCallback(){
+			arguments.callee.reached = true;
+			//console.debug('reached');
+		}
+		var unTypedVarInDocScope; // a closure test to make sure we can reach this from evaled scripts
+
+		var node1, setter1, setter2;
+
+		dojo.addOnLoad(function(){
+			/* 
+				These tests are largely borrowed from dojox.layout.ContentPane's testsuite
+				They provide coverage for the basic use of the:
+				 adjustPaths, renderStyles, executeScripts and referencePath properties
+				
+				We also need to test a couple other scenarios that dojox.html.set allows for: 
+				Reuse of a Setter across different node contexts
+				
+			
+			*/
+
+			node1 = dojo.byId('node1');
+			setter1 = new dojox.html._ContentSetter({
+				node: node1
+			});
+
+			function ieTrimSpaceBetweenTags(str){
+				return str.replace(/(<[a-z]*[^>]*>)\s*/ig, "$1");
+			}
+
+			doh.register("basicChecks", [
+					{
+						name: 'setContent',
+						runTest: function(t){
+							// test that setContent on a simple node does in fact set it
+							console.log("basicChecks: " + this.name);
+							var msg = "Simple Test";
+							
+							dojox.html.set(node1, msg);
+							t.assertEqual(msg, node1.innerHTML);
+							console.log("/basicChecks: " + this.name);
+						}
+					}
+				]
+			);
+
+			doh.register("pathAdjustments",
+				[
+					{
+						setUp: function() {
+							// setup text fixture for these pathAdjustments tests
+							// we use a _Setter instance rather than dojox.html.set
+							// as the tests include successive sets and depend on prior settings and results
+							setter2 = new dojox.html._ContentSetter({ node: node1 });
+							
+						},
+						name: 'cssPathAdjustments',
+						runTest: function(t){
+							// test that when you setContent, using the adjustPaths and renderStyles options
+							// the paths in the css are corrected for the current document
+							console.log("pathAdjustments: " + this.name);
+
+							// we do this test as one big string to emulate as good as possible, 
+							// but split it later to easily see where we failed
+							var cssText = ".easy{ background-image:url(images/image.png) }\n"
+							+".dontReplaceEasy{ background-image:url(images/images/image.png) }\n"
+							+".hardurl{background-image:url(\t \"../../source/~test/%20t'e(s)t.gif(\"1')?foo=bar11103&bar=baz-foo\"  \t);}body{};\n"
+							+".file{background-image: url(file:///home/nobody/image.png);}\n"
+							+".http{background-image: url(http://dojotoolkit.org/image.png);}\n"
+							+".https{background-image: url(https://dojotoolkit.org/image.png);}\n"
+							+".nonRelative{background-image:url(/toplevelfolder/image.gif);}\n"
+							+'@import "css/main.css";' + "\n at import \t'css/Newbee Url.css'\t;\n"
+							+"@import 'http://dojotoolkit.org/dojo.css';\n"
+							+"  @import 'you/never/thought/' print;\n"
+							+' @import url("it/would/work") tv, screen;'+"\n"
+							+' @import url(/did/you/now.css);'+"\n"
+							+' @import "yes.i.did";';
+							
+							var setParams = {
+								referencePath: "deep/nested/file",
+								adjustPaths: 1,
+								renderStyles: 1
+							};
+							
+							var adjustedCss;
+
+							// hijack internals to snatch the styles before they are inserted to DOM (DOM messes formating)
+							var oldFunc = setter2._renderStyles;
+							console.log("in cssPathAdjustments, returning function");
+
+							setter2._renderStyles = function(styles){
+								adjustedCss = styles.join();
+							};
+							console.log("in cssPathAdjustments, calling set");
+							setter2.set('<style>'+cssText+'</style>', setParams);
+							console.log("in cssPathAdjustments, done calling set");
+							
+							setter2._renderStyles = oldFunc;
+
+							adjustedCss = adjustedCss.split("\n");
+
+							var expectedCss = (".easy{ background-image:url(deep/nested/images/image.png) }\n"
+							+".dontReplaceEasy{ background-image:url(deep/nested/images/images/image.png) }\n"
+							+".hardurl{background-image:url(source/~test/%20t'e(s)t.gif(\"1')?foo=bar11103&bar=baz-foo);}body{};\n"
+							+".file{background-image: url(file:///home/nobody/image.png);}\n"
+							+".http{background-image: url(http://dojotoolkit.org/image.png);}\n"
+							+".https{background-image: url(https://dojotoolkit.org/image.png);}\n"
+							+".nonRelative{background-image:url(/toplevelfolder/image.gif);}\n"
+							+"@import \"deep/nested/css/main.css\";\n at import \"deep/nested/css/Newbee Url.css\"\t;\n"
+							+"@import 'http://dojotoolkit.org/dojo.css';\n"
+							+"  @import \"deep/nested/you/never/thought/\" print;\n"
+							+' @import url(deep/nested/it/would/work) tv, screen;'+"\n"
+							+' @import url(/did/you/now.css);'+"\n"
+							+' @import "deep/nested/yes.i.did";').split("\n");
+
+							// we split and loop to get a faster hint of where it failed
+							for(var i = 0; i < expectedCss.length; i++){
+								t.assertEqual(expectedCss[i], adjustedCss[i]);
+							}
+						},
+						tearDown: function(){
+							delete setter2.adjustPaths; // get back to defaults
+							delete setter2.renderStyles;
+						}
+					},
+					{
+						name: 'htmlPathAdjustments',
+						timeout: 1800,
+						runTest: function(t){
+							console.log("pathAdjustments: " + this.name);
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(
+								function(){
+									console.log("pathAdjustments: htmlPathAdjustments, in callback");
+									console.log("executeScripts: %s, cleanContent: %s, referencePath: %s, renderStyles: %s", setter2.executeScripts, setter2.cleanContent, setter2.referencePath, setter2.renderStyles);
+									// check that images and styles have been applied
+									var cb = dojo.contentBox(dojo.byId('imgTest'));
+											//dojo.getComputedStyle(dojo.byId('imgTest'));
+									t.assertEqual(188, cb.w);
+									t.assertEqual(125, cb.h);
+
+									// make sure we didn't mess up the other inline styles
+									cb = dojo.contentBox(dojo.byId('inlineStyleTest'));
+									t.assertEqual(188, cb.w);
+									t.assertEqual(125, cb.h);
+
+									// make sure it is the correct image
+									var cs = dojo.getComputedStyle(dojo.byId('inlineStyleTest'));
+									var url = cs.backgroundImage;
+									//remove url(..)
+									url = url.replace(/^\s?url\(['"]?/, "").replace(/['"]?\);?\s?$/, ""); 
+									// compare image url to full path of this document
+									imageUrl = dojo.moduleUrl('dojox', 'html/tests/images/testImage.gif');
+									console.log(new dojo._Url(document.location, imageUrl).toString(), url);
+									t.assertEqual(new dojo._Url(document.location, imageUrl).toString(), url);
+
+									// make sure we loaded the <link rel='stylesheet' correctly
+									var mb = dojo.marginBox(dojo.byId('linkCssTest'));
+									t.assertEqual(112, mb.w); // 100px  + 2px border + 4px margin = 112px
+									t.assertEqual(112, mb.h);
+
+									// make sure we loaded the <style>@import '...'; correctly
+									mb = dojo.marginBox(dojo.byId('importCssTest'));
+									t.assertEqual(110, mb.w); // 100px + 1px border + 4px margin = 110px
+									t.assertEqual(110, mb.h);
+
+									// make sure we didn't render the <link media='print' rel='stylesheet'
+									var mb = dojo.marginBox(dojo.byId('linkMediaTest'));
+									t.assertEqual(212, mb.w); // 100px  + 2px border + 4px margin = 112px
+									t.assertEqual(212, mb.h);
+
+									// make sure we didn't render the <style media='print'>@import '...';
+									mb = dojo.marginBox(dojo.byId('importMediaTest'));
+									t.assertEqual(210, mb.w); // 100px + 1px border + 4px margin = 110px
+									t.assertEqual(210, mb.h);
+									console.log("/pathAdjustments: htmlPathAdjustments, in callback");
+								}
+							), 1500);
+
+							console.log("pathAdjustments: " + this.name + ": requesting content");
+							var remoteUrl = dojo.moduleUrl("dojox", 'html/tests/remote/getResponse.php?mode=htmlPaths'); 
+							
+							dojo.xhrGet({
+								url: remoteUrl, 
+								load: function(data) {
+									console.log("pathAdjustments: htmlPathAdjustments, handling response");
+									setter2.set(data, {
+										adjustPaths: 1, 
+										referencePath: remoteUrl.toString(),
+										renderStyles: 1
+									}); 
+									console.log("/pathAdjustments: htmlPathAdjustments, handling response");
+								}
+							});
+							return d;
+						},
+						tearDown: function(){
+							delete setter2.adjustPaths; // get back to defaults
+							delete setter2.renderStyles;
+						}
+					},
+					{
+						name: 'renderStylesOfByDefaultAndOldDeleted',
+						timeout: 1800,
+						runTest: function(t){
+							var d = new t.Deferred();
+							console.log("pathAdjustments: " + this.name);
+
+							setTimeout(d.getTestCallback(
+								function(){
+									// innerHTML'ing <link tags works in some browser (IE, moz), but not all
+									// we can't test if LINK was loaded this way
+
+									// make sure we didn't load the <link rel='stylesheet'
+									//var mb = dojo.marginBox(dojo.byId('linkCssTest'));
+									//t.assertFalse(112 == mb.w);
+									//t.assertFalse(112 == mb.h);
+
+									// make sure we didn't load the <style>@import '...';
+									var mb = dojo.marginBox(dojo.byId('importCssTest'));
+									t.assertFalse(110 == mb.w);
+									t.assertFalse(110 == mb.h);
+								}
+							), 1500);
+
+							var remoteUrl = dojo.moduleUrl("dojox", 'html/tests/remote/getResponse.php?mode=htmlPaths'); 
+							dojo.xhrGet({
+								url: remoteUrl, 
+								load: function(data) {
+									console.log("pathAdjustments: renderStylesOfByDefaultAndOldDeleted, handling response");
+									setter2.set(data, {
+										adjustPaths: 1, 
+										referencePath: remoteUrl.toString()
+									}); 
+									console.log("/pathAdjustments: htmlPathAdjustments, handling response");
+								}
+							});
+							return d;
+						},
+						tearDown: function(){
+							delete setter2.adjustPaths;
+						}
+					}
+				]
+			);
+
+			doh.register("scriptTests",
+				[
+					{
+						name: 'leaveDojoMethodScriptsAsIs',
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							dojox.html.set(node1, 
+								"<"
+								+"script type='dojo/method'>unTypedVarInDocScope = 'failure';<"
+								+"/script>", 
+								{
+									executeScripts: true
+								}
+							);
+
+							var d = new t.Deferred();
+							// IE req to async this test
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('undefined', typeof unTypedVarInDocScope);
+								t.assertFalse(unTypedVarInDocScope == 'failure');
+							}), 40);
+
+							return d;
+						}
+					},
+					{
+						name: 'scripts_evals_in_global_scope',
+						timeout: 1800, // grabing remote js, wait for that
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							var remoteUrl = dojo.moduleUrl("dojox", "html/tests/remote/getResponse.php?mode=remoteJsTrue");
+							dojox.html.set(
+								node1, 
+								"<"
+								+"script>function scriptsInGlobalClicked(){ documentCallback(); }<"
+								+"/script><"+"script src='" + remoteUrl +"'></"
+								+"script>"+"<a href='javascript:scriptsInGlobalClicked()' "
+									+"onfocus='scriptsInGlobalClicked();' id='anchorTag'>test</a>", 
+								{
+									executeScripts: true
+								}
+							);
+
+							var link = dojo.byId('anchorTag');
+							dojo.isFunction(link.click) ? /*others*/ link.click() : /*moz*/ link.focus();
+							var d = new t.Deferred();
+					
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('boolean', typeof documentCallback.reached);
+								t.assertTrue(documentCallback.reached);
+								t.assertTrue(unTypedVarInDocScope);
+							}), 40);
+							return d;
+						}
+					},
+					{
+						name:'scriptsEvalsInOrder',
+						timeout: 1800,// grabing remote js, wait for that
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							var remoteUrl = dojo.moduleUrl("dojox", "html/tests/remote/getResponse.php?mode=remoteJsFalse");
+							dojox.html.set(node1, "<"
+								+"script src='"+ remoteUrl +"'><"
+								+"/script><"+"script>unTypedVarInDocScope = 1;<"
+								+"/script>", 
+								{
+									executeScripts: true
+								}); // scripts only test
+
+							// we need to make this async because of IEs strange events loops
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('number', typeof unTypedVarInDocScope);
+								t.assertEqual(1, unTypedVarInDocScope);
+							}), 40);
+							return d;
+						}
+					},
+					{
+						name: 'scriptsWithTypeTextJavascript',
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							dojox.html.set(node1, "<"
+								+"script type='text/javascript'> unTypedVarInDocScope = 'text/javascript'; <"
+								+"/script>", {
+									executeScripts: true
+								}
+							);
+
+							var d = new t.Deferred();
+							// IE needs async here
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('text/javascript', unTypedVarInDocScope);
+							}), 40);
+							return d;
+						}
+					},
+					{
+						name:'scriptsWithHtmlComments',
+						runTest: function(t){
+							dojox.html.set(node1, "<"
+								+"script><!-- unTypedVarInDocScope = 2; --><"
+								+"/script>", {
+									cleanContent: 1,
+									executeScripts: 1 
+								}
+							);
+
+							var d = new t.Deferred();
+							// IE need a async here
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('number', typeof unTypedVarInDocScope);
+								t.assertEqual(2, unTypedVarInDocScope);
+							}), 40);
+
+							return d;
+						},
+						tearDown: function(){
+							node1.innerHTML = "";
+						}
+					},
+					{
+						name:'scriptsWithCData',
+						runTest: function(t){
+							dojox.html.set(node1, "<"
+								+"script><![CDATA[ unTypedVarInDocScope = 3; ]]><"
+								+"/script>", {
+									cleanContent: 1,
+									executeScripts: 1 
+								}
+							);
+
+							var d = new t.Deferred();
+							// IE need a async here
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('number', typeof unTypedVarInDocScope);
+								t.assertEqual(3, unTypedVarInDocScope);
+							}), 40);
+
+							return d;
+						},
+						tearDown: function(){
+							node1.innerHTML = "";
+						}
+					},
+					// FIXME: what /should/ container be in this context? 
+					{
+						name: 'replace_container_',
+						runTest: function(t){
+							unTypedVarInDocScope = 'failure';
+							dojox.html.set(node1, 
+								"<"
+								+"script>function testReplace(){"
+								+	"if(typeof _container_ != 'object'){return 'not replaced 1';}\n"
+								+	"if(_container_ != setter1){ return 'not replaced 2';}\n"
+								+	"if(!_container_ == setter1){ return 'not replaced 3';}\n"
+								+	"var tmp =_container_=dojo;\n"
+								+	"if(tmp != dojo){ return 'replaced when shouldnt 1';}\n"
+								+	"var tmp = _container_  \t \t = dojo;\n"
+								+	"if(tmp != dojo){ return 'replaced when shouldnt 2';}\n"
+								+	"return 'success';\n"
+								+"};\n"
+								+"unTypedVarInDocScope = testReplace();"
+								+"</"+"script>", {
+									executeScripts: 1, 
+									scriptHasHooks: true, 
+									scriptHookReplacement: function() { return "setter1"; }
+							});
+							
+							// let IE inhale here
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('success', unTypedVarInDocScope);
+							}), 40);
+							return d;
+						},
+						tearDown: function(){
+							node1.innerHTML = "";
+							unTypedVarInDocScope = "done";
+						}
+					},
+					
+					"t.assertEqual('done', unTypedVarInDocScope)",
+					
+					{
+						name: 'evalThenParse',
+						runTest: function(t){
+							dojo.global._evalThenParseResult = "";
+							// test the executeScripts / parse sequence
+							// by declaring a class that when instantiated returns true
+							dojox.html.set(node1, 
+								"<"+"script>"
+								+"_evalThenParseResult+='a';\n"
+								+"dojo.provide('dojox.html.tests.TestThinger');"
+								+"dojo.declare('dojox.html.tests.TestThinger', null, {"
+								+"  constructor: function() {"
+								+"	 _evalThenParseResult +='b';"
+								+"  }"
+								+"});"
+								+"</"+"script>\n"
+								+""
+								+"<div dojoType='dojox.html.tests.TestThinger'>\n"
+									+"<"+"script type='dojo/method'>dojo.global._evalThenParseResult +='c';</"+"script>\n"
+								+"</div>\n"
+								, {
+									executeScripts: 1, 
+									scriptHasHooks: false,
+									parseContent: true
+							});
+							
+							t.assertEqual('abc', dojo.global._evalThenParseResult);
+						},
+						tearDown: function(){
+							delete dojo.global._evalThenParseResult;
+						}
+					}
+				]
+			);
+
+
+			doh.register('regexRegressionAndSpeedtest',[
+				{
+					name: 'cssPathAdjustments',
+					runTest: function(t){
+						// we do this test as one big string to emulate as good as possible, 
+						// but split it later to easily see where we failed
+						var cssText = ".easy{ background-image:url(images/image.png) }\n"
+						+".dontReplaceEasy{ background-image:url(images/images/image.png) }\n"
+						+".hardurl{background-image:url(\t \"../../source/~test/%20t'e(s)t.gif(\"1')?foo=bar11103&bar=baz-foo\"  \t);}body{};\n"
+						+".file{background-image: url(file:///home/nobody/image.png);}\n"
+						+".http{background-image: url(http://dojotoolkit.org/image.png);}\n"
+						+".https{background-image: url(https://dojotoolkit.org/image.png);}\n"
+						+".nonRelative{background-image:url(/toplevelfolder/image.gif);}\n"
+						+'@import "css/main.css";' + "\n at import \t'css/Newbee Url.css'\t;\n"
+						+"@import 'http://dojotoolkit.org/dojo.css';\n"
+						+"  @import 'you/never/thought/' print;\n"
+						+' @import url("it/would/work") tv, screen;'+"\n"
+						+' @import url(/did/you/now.css);'+"\n"
+						+' @import "yes.i.did";';
+
+						var expectedCss = ".easy{ background-image:url(deep/nested/images/image.png) }\n"
+						+".dontReplaceEasy{ background-image:url(deep/nested/images/images/image.png) }\n"
+						+".hardurl{background-image:url(source/~test/%20t'e(s)t.gif(\"1')?foo=bar11103&bar=baz-foo);}body{};\n"
+						+".file{background-image: url(file:///home/nobody/image.png);}\n"
+						+".http{background-image: url(http://dojotoolkit.org/image.png);}\n"
+						+".https{background-image: url(https://dojotoolkit.org/image.png);}\n"
+						+".nonRelative{background-image:url(/toplevelfolder/image.gif);}\n"
+						+"@import \"deep/nested/css/main.css\";\n at import \"deep/nested/css/Newbee Url.css\"\t;\n"
+						+"@import 'http://dojotoolkit.org/dojo.css';\n"
+						+"  @import \"deep/nested/you/never/thought/\" print;\n"
+						+' @import url(deep/nested/it/would/work) tv, screen;'+"\n"
+						+' @import url(/did/you/now.css);'+"\n"
+						+' @import "deep/nested/yes.i.did";';
+
+						for(var i = 0; i < 6; i++){
+							cssText += cssText;
+							expectedCss += expectedCss;
+						}
+
+						expectedCss = expectedCss.split("\n");
+
+						var setParams = {
+							referencePath: "deep/nested/file",
+							adjustPaths:1,
+							renderStyles:1
+						};
+						
+						var adjustedCss;
+
+						// hijack internals to snatch the styles before they are inserted to DOM (DOM messes formating)
+						var oldFunc = dojox.html._ContentSetter.prototype._renderStyles;
+						dojox.html._ContentSetter.prototype._renderStyles = function(styles){
+							adjustedCss = styles.join();
+						};
+
+						var start = new Date();
+						dojox.html.set(node1, '<style>'+cssText+'</style>', setParams);
+						var end = new Date();
+						
+						dojox.html._ContentSetter.prototype._renderStyles = oldFunc;
+
+						adjustedCss = adjustedCss.split("\n");
+						console.info('Time used to regex scan css and adjust relative paths within css:'+
+								(end - start)+' ms on '+ cssText.split('\n').length
+								+' css rows, with '+ cssText.length+' characters (roughly '
+								+Math.round(cssText.length/1024)+ 'Kb) of infile css');
+
+						// we split and loop to get a faster hint of where it failed
+						for(var i = 0; i < expectedCss.length; i++){
+							t.assertEqual(expectedCss[i], adjustedCss[i]);
+						}
+					},
+					tearDown: function(){
+					}
+				}
+				,
+				{
+					name:'htmlPathsSpeedTest',
+					runTest: function(t){
+						var htmlText = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
+							+"<title>should be removed</title>\n"
+							+"<img src=\"images/image.gif\"/>Testing\n"
+							+"<a href=\"../../topmost.html\">\n"
+							+"	<img src=\"/siteroot/top.html\">\n"
+							+"	<p style='background:url(\"images/back.png\")'>\n"
+							+"	testing link\n"
+							+"</p></a>\n"
+							+"<style \ntype='text/css'>\n"
+							+"	@import 'http://dojotoolkit.org/visible.css' tv, screen;\n"
+							+"	@import \"./audio.css\" audio;\n"
+							+"	@import url(/topsite/css/main.css);\n"
+							+"	div.mywidget, #someId {\n"
+							+"		background-color:url(../../css/main.css);"
+							+"		display:none;\n"
+							+"		background:url(../tmp/css)\n"
+							+"	}\n"
+							+"</style>\n"
+							+"<link rel=\"stylesheet\" href=\"../../css/theme.css\" media=\"all\">\n"
+							+"<link media='print' type='text/css' rel='stylesheet' href='../../css/theme2.css'>\n"
+							+"<a style='display:block; background:url(/topmost/css)' href='../above'>above</a>\n"
+							+"<sc"+"ript type=\"text/javascript\"\n src=\"..\\windows\\morons\"></scr"+"ipt>\n"
+							+"<scr"+"ipt type=\"dojo/method\" src=\"/dont/mess/with/this\"></scr"+"ipt>\n"
+							+"<scr"+"ipt src=\"/dont/mess/here/either\" type=\"dojo/method\"></scr"+"ipt>\n"
+							+"<scr"+"ipt event=\"/havent/you/listened\" type=\"dojo/method\"></scr"+"ipt>\n"
+							+"<scr"+"ipt>JS CODE</scr"+"ipt>\n"
+							+"<a href='javascript:void(0)'>void</a>";
+
+
+						var expectedHtml = "\n\n<img src=\"deep/nested/images/image.gif\"/>Testing\n"
+							+"<a href=\"topmost.html\">\n"
+							+"	<img src=\"/siteroot/top.html\">\n"
+							+"	<p style='background:url(deep/nested/images/back.png)'>\n"
+							+"	testing link\n"
+							+"</p></a>\n"
+							+"\n"
+							+"\n\n"
+							+"<a style='display:block; background:url(/topmost/css)' href='deep/above'>above</a>\n\n"
+							+"<scr"+"ipt type=\"dojo/method\" src=\"/dont/mess/with/this\"></scr"+"ipt>\n"
+							+"<scr"+"ipt src=\"/dont/mess/here/either\" type=\"dojo/method\"></scr"+"ipt>\n"
+							+"<scr"+"ipt event=\"/havent/you/listened\" type=\"dojo/method\"></scr"+"ipt>\n\n"
+							+"<a href='javascript:void(0)'>void</a>";
+
+
+						var expectedCss = [
+							"\n	@import 'http://dojotoolkit.org/visible.css' tv, screen;\n"
+							+"	@import \"deep/nested/audio.css\" audio;\n"
+							+"	@import url(/topsite/css/main.css);\n"
+							+"	div.mywidget, #someId {\n"
+							+"		background-color:url(css/main.css);"
+							+"		display:none;\n"
+							+"		background:url(deep/tmp/css)\n"
+							+"	}\n", "@import \"css/theme.css\";", "@import \"css/theme2.css\";"];
+
+						for(var i = 0; i < 6; i++){
+							htmlText += htmlText;
+							expectedHtml += expectedHtml;
+							expectedCss = expectedCss.concat(expectedCss);
+						}
+
+
+						var setParams = {
+							referencePath: "deep/nested/file",
+							executeScripts: 1,
+							adjustPaths: 1,
+							renderStyles: 1,
+							cleanContent: 1
+						};
+						
+						var adjustedCss, adjustedHtml;
+
+						// hijack internals to snatch the styles before they are inserted to DOM (DOM messes formating)
+						var oldFunc = dojox.html._ContentSetter.prototype._renderStyles;
+						dojox.html._ContentSetter.prototype._renderStyles = function(styles){
+							adjustedCss = styles;
+							this.executeScripts = 0;
+						};
+
+						var oldSetFunc = dojox.html._ContentSetter.prototype.setContent;
+						dojox.html._ContentSetter.prototype.setContent = function(html){
+							console.log("replaced setContent is called");
+							adjustedHtml = this.content;
+						};
+
+						var oldXhr = dojo.xhrGet;
+						dojo.xhrGet = function(){}; // kill script download
+
+						var start = new Date();
+
+						dojox.html.set(node1, htmlText, setParams);
+
+						console.log("/calling set to clean and adjust paths");
+						var end = new Date();
+
+						// reset back to the way it was
+						dojox.html._ContentSetter.prototype._renderStyles = oldFunc;
+						dojox.html._ContentSetter.prototype.setContent = oldSetFunc;
+						dojo.xhrGet = oldXhr;
+
+						console.info('Time used to regex scan html/css and\n adjust relative paths (adjustPaths=true),\n copy scripts (executeScripts=true) and copy css innerText (renderStyles=true) and adjust paths in there \nTime:'+
+								(end - start)+' ms on '+ htmlText.split('\n').length
+								+' html rows, with '+ htmlText.length+' characters (roughly '
+								+Math.round(htmlText.length/1024)+ 'Kb)');
+
+						// we split and loop to get a faster hint of where it failed
+						adjustedHtml = adjustedHtml.split("\n");
+						expectedHtml = expectedHtml.split("\n");
+
+						for(var i = 0; i < expectedHtml.length; i++){
+							//console.debug(expectedHtml[i], i);
+							//console.debug(adjustedHtml[i], i);
+							t.assertEqual(expectedHtml[i], adjustedHtml[i]);
+						}
+
+						var exCssBlock, adjCssBlock;
+						for(var i = 0; i < expectedCss.length; i++){
+							t.assertEqual('string', typeof adjustedCss[i]);
+
+							exCssBlock = expectedCss[i].split('\n');
+							adjCssBlock = adjustedCss[i].split('\n');
+
+							for(var j = 0; j < exCssBlock.length;j++){
+								t.assertEqual(dojo.trim(exCssBlock[j]), dojo.trim(adjCssBlock[j]));
+							}
+							
+						}
+					},
+					tearDown: function(){
+					}
+				},
+				{
+					name:'IE_AlphaImageLoader_PathAdjustments',
+					runTest: function(t){
+						if(!dojo.isIE){
+							console.info('aborting test IE_AlphaImageLoader_PathAdjustments, you dont use IE');
+							return;
+						}
+						var setParams = {
+							adjustPaths: 1,
+							renderStyles: 1,
+							referencePath: "deep/"
+						};
+
+						var html = "<div style='width:10px;height:10px;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=\"scale\", src=\"images/alpha(1).png\", nextProperty=\"useless\");'><!-- \n"
+						+" alpha png in IE 6 --></div>\n"
+						+"<style>\n"
+						+"	.ie_menu_png {"
+						+"		filter: \t progid:\n"
+						+"			DXImageTransform.Microsoft.AlphaImageLoader(\n"
+						+"			src='../midlevel/alpha(2).png')\n"
+						+"	}\n"
+						+" #my_transparent_png {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader( src='/images/alpha(3).png') }\n"
+						+" #my_transparent_png1 {filter: progid:DXImageTransform.Microsoft.AlhaImageLoader(src='http://no.se/images/alpha(4).png')}\n"
+						+"</style>\n";
+
+
+						var expectedHtml = "<div style='width:10px;height:10px;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=\"scale\", src=\"deep/images/alpha(1).png\", nextProperty=\"useless\");'><!-- \n"
+						+" alpha png in IE 6 --></div>\n\n";
+
+						var expectedCss = "\n"
+						+"	.ie_menu_png {"
+						+"		filter: \t progid:\n"
+						+"			DXImageTransform.Microsoft.AlphaImageLoader(\n"
+						+"			src='midlevel/alpha(2).png')\n"
+						+"	}\n"
+						+" #my_transparent_png {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader( src='/images/alpha(3).png') }\n"
+						+" #my_transparent_png1 {filter: progid:DXImageTransform.Microsoft.AlhaImageLoader(src='http://no.se/images/alpha(4).png')}\n";
+
+
+						for(var i = 0; i < 7; i++){
+							html += html;	
+							expectedHtml += expectedHtml;
+							expectedCss += expectedCss;
+						}
+
+						var adjustedHtml, adjustedCss;
+
+						// hijack internals to snatch the content
+						var oldRenderStyles = dojox.html._ContentSetter.prototype._renderStyles;
+						var oldSetContent = dojox.html._ContentSetter.prototype.setContent;
+						dojox.html._ContentSetter.prototype._renderStyles = function(styles){ adjustedCss = styles.join(''); };
+						dojox.html._ContentSetter.prototype.setContent = function(cont){ adjustedHtml = this.content; };
+
+						var start = new Date();
+						dojox.html.set(node1, html, setParams);
+						var end = new Date();
+
+						console.info('Time used to replace AlphaImageLoader(src="...") '
+									+(end - start) + "ms in HTML with "+html.length
+									+' characters (roughly '+(Math.round(html.length/1024))+'Kb)');
+
+						// reset hijacked
+						dojox.html._ContentSetter.prototype._renderStyles = oldRenderStyles;
+						dojox.html._ContentSetter.prototype.setContent = oldSetContent;
+
+
+						// split on newline and run a check on each row to help debugging
+						expectedHtml = expectedHtml.split("\n");
+						adjustedHtml = adjustedHtml.split("\n");
+						for(var i = 0; i < expectedHtml.length; i++){
+							t.assertEqual(expectedHtml[i], adjustedHtml[i]);
+						}
+
+						expectedCss = expectedCss.split("\n");
+						adjustedCss = adjustedCss.split("\n");
+						for(var i = 0; i < expectedCss.length; i++){
+							t.assertEqual(expectedCss[i], adjustedCss[i]);
+						}
+						
+					},
+					tearDown: function(){
+					}
+				}
+			]);
+
+			doh.register("A_AlphaImageLoader_inAction", [{
+				name:"AlphaLoaderShowHow",
+				runTest:function(t){
+					// IE filter alphaimageloader paths must be relative to the page
+					// not to the cssFile that declares it
+
+					// demo a much better way of "Fixing" alpha png in IE6 than inlining in html
+					var html = "<img src='images/dojoLogo.png' class='run_png_fix'/>";
+
+					var showHowHtml = "<pre >\nCode used in IE transparent png example\n"
+								+"code (declared in main page, not through ContentPane)\n"
+								+"<script type='text/javascript'>\n"
+								+fixPngIE6.toString().replace(/\n\t?/g, "\n")
+								+"\n</script>\n"
+								+"<style type='text/css'>\n"
+								+"	.run_png_fix {\n"
+								+"		background-image:url(images/blank.gif);\n"
+								+"		behaviour: expression(fixPngIE6.call(this));\n"
+								+"	}\n"
+								+"</style>\n\n...\n\nHtml feeded to ContentPane (or your main page):\n"
+								+"<img src='images/dojoLogo.png' class='run_png_fix'/>\n</pre>";
+
+					dojox.html.set(
+						node1, 
+						html+showHowHtml, {
+							executeScripts: 1,
+							renderStyles: 1
+						}
+					);
+				}
+			}]);
+
+			doh.register("setterReuse", [
+					{
+						// FIXME: finish this test!
+						name: 'renderStyles',
+						setUp: function() {
+							setter2 = new dojox.html._ContentSetter({
+								renderStyles: true, 
+								cleanContent: true,
+								node: dojo.byId("node2")
+							});
+							setter2.set('<style>#node2 { font-size: 18px }</style>New value');
+						},
+						runTest: function(t){
+							// test the fixture setup ok
+							var node2 = dojo.byId("node2"); 
+							t.assertEqual("New value", node2.innerHTML);
+							t.assertEqual("18px", dojo.style(node2, "fontSize"));
+							
+							// grab the styleNodes in case we need to remove them later - there should be exactly 1
+							// in the reuse scenario, this is what we have to do today
+							var node2_styleNodes = setter2._styleNodes; 
+							setter2._styleNodes = [];
+							t.assertEqual(1, node2_styleNodes.length);
+
+							// now reuse the setter on a different node
+							var node3 = setter2.node = dojo.byId("node3");
+							setter2.set('<style>#node3 { font-size: 24px }</style>Another New value');
+
+							// test the old node is still good, 
+							// and the new node got the correct value, style
+							t.assertEqual("New value", node2.innerHTML);
+							t.assertEqual("18px", dojo.style(node2, "fontSize"));
+
+							t.assertEqual("Another New value", node3.innerHTML);
+							t.assertEqual("24px", dojo.style(node3, "fontSize"));
+
+							// test the old styleNode is still around
+							t.assertEqual(1, node2_styleNodes.length);
+							// test we have just one in the new collection
+							t.assertEqual(1, setter2._styleNodes.length);
+							
+							// I guess you might want to do this...
+							// remove content and associated styles from the current and previous node
+							setter2.set("");
+							t.assertEqual(0, setter2._styleNodes.length);
+							t.assertFalse("24px" == dojo.style(node3, "fontSize"));
+							
+							setter2.node = node2;
+							setter2._styleNodes = node2_styleNodes;
+							setter2.set("");
+							t.assertEqual(0, setter2._styleNodes.length);
+							t.assertFalse("18px" == dojo.style(node2, "fontSize"));
+						}
+					}
+				]
+			);
+
+			var remoteScriptsSetter;
+			var previousContent;
+			doh.register("remoteScripts", [
+				{
+					name: 'testCommentedScriptTag',
+					setUp: function() {
+						remoteScriptsSetter = new dojox.html._ContentSetter({
+							renderStyles: true, 
+							cleanContent: true,
+							executeScripts: true,
+							node: dojo.byId("node4")
+						});
+						previousContent = dojo.byId("node4").innerHTML;
+					},
+					tearDown: function(){
+						dojo.byId("node4").innerHTML = previousContent;    
+					},
+					timeout: 10000,
+					runTest: function(t){
+						var deferred = new doh.Deferred(); 
+						var xhrDef = dojo.xhrGet({
+							url: "remote/commentedScript.html",
+							preventCache: true,
+							handleAs: "text"
+						});
+						xhrDef.addCallback(function(text){
+							remoteScriptsSetter.set(text);
+							var intv = setInterval(function(){
+								if(window.__remotePaneLoaded){
+									clearInterval(intv);
+									window.__remotePaneLoaded = null;
+									try{
+										//Test that entity characters in a src url for a script 
+										//are properly converted to correct form
+										var node = document.getElementById("should_not_be_here"); 
+										doh.assertTrue(node == null);
+										deferred.callback(true);
+									}catch(e){
+										deferred.errback(new Error(e));
+									}
+								}
+							}, 500);
+						});
+						xhrDef.addErrback(function(e){
+							deferred.errback(e);
+						});
+						return deferred;
+					}
+				},
+				{
+					name: 'testEntityChars',
+					setUp: function() {
+						remoteScriptsSetter = new dojox.html._ContentSetter({
+							renderStyles: true, 
+							cleanContent: true,
+							executeScripts: true,
+							node: dojo.byId("node4")
+						});
+						previousContent = dojo.byId("node4").innerHTML;
+					},
+					tearDown: function(){
+						dojo.byId("node4").innerHTML = previousContent;    
+					},
+					timeout: 10000,
+					runTest: function(t){
+						var deferred = new doh.Deferred(); 
+						var xhrDef = dojo.xhrGet({
+							url: "remote/commentedScript.html",
+							preventCache: true,
+							handleAs: "text"
+						});
+						xhrDef.addCallback(function(text){
+							remoteScriptsSetter.set(text);
+							var intv = setInterval(function(){
+								if(window.__remotePaneLoaded2){
+									clearInterval(intv);
+									window.__remotePaneLoaded2 = null;
+									try{
+										//Test that entity characters in a src url for a script 
+										//are properly converted to correct form
+										var node = document.getElementById("should_not_be_here2"); 
+										doh.assertTrue(node == null);
+										deferred.callback(true);
+									}catch(e){
+										deferred.errback(new Error(e));
+									}
+								}
+							}, 500);
+						});
+						xhrDef.addErrback(function(e){
+							deferred.errback(e);
+						});
+						return deferred;
+					}
+				}
+				
+			]);
+
+			doh.run();
+		});
+	</script>
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		.box {
+			border: 1px solid black;
+			height: 190px;
+			width: 80%;
+			overflow: auto;
+		}
+
+		.red {
+			color: red;
+		}
+
+		.dojoxTestWidget {
+			border: 1px dashed red;
+			background-color: #C0E209 ;
+		}
+		
+		              
+	</style>
+</head>
+<body class='tundra'>
+	<h1>dojox.layout.ContentPane</h1>
+	<h3>As dojox ContentPane is derived from dijit ContentPane, make sure that the dijit test passes before running this test</h3>
+	<h3 class='red'>Test relies on a php page as backend, so you need php installed on your server</h3>
+
+	<div class='box' id='node1'>
+		Initial value
+	</div>
+
+	<div class='box' id='node2'>
+		Initial value
+	</div>
+
+	<div class='box' id='node3'>
+		Initial value
+	</div>
+
+	<div class='box' id='node4'>
+		Initial value
+	</div>                                        
+
+	<table id='tableTest' class='box'>
+		<thead>
+			<tr>
+				<td></td>
+			</tr>
+		</thead>
+		<tbody>
+			<tr>
+				<td></td>
+			</tr>
+		<tbody>
+	</table>
+</body>
+</html>
diff --git a/dojox/html/tests/test_style-html.html b/dojox/html/tests/test_style-html.html
new file mode 100644
index 0000000..c305e8c
--- /dev/null
+++ b/dojox/html/tests/test_style-html.html
@@ -0,0 +1,310 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+		"http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title></title>
+	<style type="text/css">
+		@import "../../../dijit/themes/nihilo/nihilo.css";
+	</style>
+	<style type="text/css">
+		body, html{
+			padding:0;
+			margin:0;
+			background:#666;
+			text-align:center;
+		}
+		.box{
+			background:#fff;
+			color:#666;
+			font:11px monospace;
+			width:250px;
+			height:200px;
+			margin:40px auto;
+			padding:0;
+		}
+		.toWrapper{
+			position:relative;
+			width:100%;
+			height:100%;
+		}
+		.box .transformOrigin{
+			position:absolute;
+			font-size:0;
+			background:red;
+			width:3px;
+			height:3px;
+			margin:0;
+			border:none;
+			padding:0;
+			top:100px;
+			left:125px;	
+		}
+		.boxContainer{
+			color:white;
+			background:black;
+			height:300px;
+			width:100%;
+			text-align:center;
+			overflow:hidden;
+			position:relative;
+			padding:0;
+		}
+		div.controls{
+			background:#ddd;
+			color:#333;
+			font:bold 11px monospace;
+			margin:0 0 20px 0;
+			border-bottom:1px solid #ccc;
+		}
+		.transformName{
+			font: 18px/200px bold arial, helvetica;
+			color: #bbb;
+		}
+		.mainContainer{
+			width:800px;
+			border-right:1px solid #ccc;
+			text-align:left;
+			margin:auto;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+	dojo.require("dojo.fx");
+	dojo.require("dojox.html.ext-dojo.style");
+	dojo.require("dijit.form.HorizontalSlider");
+		var toX = 125,
+			toY = 100,
+			rotation = 0,
+			translateX = 0,
+			translateY = 0,
+			skewX = 0,
+			skewY = 0,
+			scaleX = 1,
+			scaleY = 1
+		;
+		dojo.addOnLoad(function(){
+			var rotateToX = dijit.byId("rotateToX"),
+				rotateTransformOrigin = dojo.byId("transformOriginNode"),
+				rotateToY = dijit.byId("rotateToY"),
+				rotateControl = dijit.byId("rotateControl"),
+				skewXControl = dijit.byId("skewXControl"),
+				skewYControl = dijit.byId("skewYControl"),
+				scaleXControl = dijit.byId("scaleXControl"),
+				scaleYControl = dijit.byId("scaleYControl"),
+				translateXControl = dijit.byId("translateXControl"),
+				translateYControl = dijit.byId("translateYControl"),
+				transforms = {
+					rotate: "",
+					translateX: "",
+					translateY: "",
+					skewX: "",
+					skewY: "",
+					scaleX: "",
+					scaleY: ""
+				},
+				applyTransforms = function(transforms){
+					var tString = "";
+					for(var i in transforms){
+						tString += transforms[i] + " "; 
+					}
+					dojo.style("targetDiv", "transform", tString);
+				}
+			;
+
+			// rotate
+			rotateToX.connect(rotateToX, "onChange", function(){
+				toX = parseInt(this.value);
+				dojo.style(rotateTransformOrigin, "left", toX + "px");
+				dojo.style("targetDiv", "transformOrigin", toX + "px " + toY + "px");
+			});
+			rotateToY.connect(rotateToY, "onChange", function(){
+				toY = parseInt(this.value);
+				dojo.style(rotateTransformOrigin, "top", toY + "px");
+				dojo.style("targetDiv", "transformOrigin", toX + "px " + toY + "px");
+			});
+			rotateControl.connect(rotateControl, "onChange", function(){
+				rotation = this.value;
+				transforms.rotate = "rotate(" + rotation + "deg)";
+				applyTransforms(transforms);
+			});
+
+			// skewX
+			skewXControl.connect(skewXControl, "onChange", function(){
+				skewX = this.value;
+				transforms.skewX = "skewX(" + skewX + "deg)";
+				applyTransforms(transforms);
+			});
+			
+			// skewY
+			skewYControl.connect(skewYControl, "onChange", function(){
+				skewY = this.value;
+				transforms.skewY = "skewY(" + skewY + "deg)";
+				applyTransforms(transforms);
+			});
+
+			// scaleX
+			scaleXControl.connect(scaleXControl, "onChange", function(){
+				scaleX = this.value;
+				transforms.scaleX = "scaleX(" + scaleX + ")";
+				applyTransforms(transforms);
+			});
+
+			// scaleY
+			scaleYControl.connect(scaleYControl, "onChange", function(){
+				scaleY = this.value;
+				transforms.scaleY = "scaleY(" + scaleY + ")";
+				applyTransforms(transforms);
+			});
+
+			// translateX
+			translateXControl.connect(translateXControl, "onChange", function(){
+				translateX = this.value;
+				transforms.translateX = "translateX(" + translateX + "px)";
+				applyTransforms(transforms);
+			});
+
+			// translateY
+			translateYControl.connect(translateYControl, "onChange", function(){
+				translateY = this.value;
+				transforms.translateY = "translateY(" + translateY + "px)";
+				applyTransforms(transforms);
+			});
+
+		});
+	</script>
+	</head>
+	<body class="nihilo">
+	<div class="mainContainer">
+		<div class="boxContainer">
+			<div id="targetDiv" class="box">
+				<div class="toWrapper">
+					<div class="transformName">Transform</div>
+					<div id="transformOriginNode" class="transformOrigin">
+					</div>
+				</div>
+			</div>
+		</div>
+		<div class="controls">
+			<table>
+				<tr>
+					<td>Transform Origin - x</td>
+					<td>
+						<div>
+							<div style="width:200px" dojoType="dijit.form.HorizontalSlider"
+								minimum="0"
+								maximum="250"
+								discreteValues="251"
+								value="125"
+								id="rotateToX"></div>
+						</div>
+					</td>
+				</tr>
+				<tr>
+					<td>Transform Origin - y</td>
+					<td>
+						<div>
+							<div style="width:200px" dojoType="dijit.form.HorizontalSlider"
+								minimum="0"
+								maximum="200"
+								discreteValues="361"
+								value="100"
+								id="rotateToY"></div>
+						</div>
+					</td>
+				</tr>
+				<tr>
+					<td>Rotation angle</td>
+					<td>
+						<div>
+							<div style="width:200px" dojoType="dijit.form.HorizontalSlider"
+								minimum="0"
+								maximum="360"
+								discreteValues="361"
+								value="0"
+								id="rotateControl"></div>
+						</div>
+					</td>
+				</tr>
+				<tr>
+					<td>Skew X</td>
+					<td>
+						<div>
+							<div style="width:200px" dojoType="dijit.form.HorizontalSlider"
+								minimum="0"
+								maximum="360"
+								discreteValues="361"
+								value="0"
+								id="skewXControl"></div>
+						</div>
+					</td>
+				</tr>
+				<tr>
+					<td>Skew Y</td>
+					<td>
+						<div>
+							<div style="width:200px" dojoType="dijit.form.HorizontalSlider"
+								minimum="0"
+								maximum="360"
+								discreteValues="361"
+								value="0"
+								id="skewYControl"></div>
+						</div>
+					</td>
+				</tr>
+				<tr>
+					<td>Scale X</td>
+					<td>
+						<div>
+							<div style="width:200px" dojoType="dijit.form.HorizontalSlider"
+								minimum=".1"
+								maximum="4"
+								discreteValues="41"
+								value="1"
+								id="scaleXControl"></div>
+						</div>
+					</td>
+				</tr>
+				<tr>
+					<td>Scale Y</td>
+					<td>
+						<div>
+							<div style="width:200px" dojoType="dijit.form.HorizontalSlider"
+								minimum=".1"
+								maximum="4"
+								discreteValues="41"
+								value="1"
+								id="scaleYControl"></div>
+						</div>
+					</td>
+				</tr>
+				<tr>
+					<td>Translate X</td>
+					<td>
+						<div>
+							<div style="width:200px" dojoType="dijit.form.HorizontalSlider"
+								minimum="0"
+								maximum="200"
+								discreteValues="201"
+								value="0"
+								id="translateXControl"></div>
+						</div>
+					</td>
+				</tr>
+				<tr>
+					<td>Translate Y</td>
+					<td>
+						<div>
+							<div style="width:200px" dojoType="dijit.form.HorizontalSlider"
+								minimum="0"
+								maximum="200"
+								discreteValues="201"
+								value="0"
+								id="translateYControl"></div>
+						</div>
+					</td>
+				</tr>
+			</table>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/html/tests/test_styles.html b/dojox/html/tests/test_styles.html
new file mode 100644
index 0000000..ab70f3d
--- /dev/null
+++ b/dojox/html/tests/test_styles.html
@@ -0,0 +1,167 @@
+<html>
+<head>
+<title>dojox.html.styles Test</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<style type="text/css" rel="stylesheet" title="dojoDefault">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+
+<style title="altStyle" type="text/css" rel="alternate stylesheet">
+	p{
+		font-size:9px;
+		color:#9999FF;
+	}
+</style>
+
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, fontSizeWatch: true"></script>
+<script type="text/javascript">
+	
+	dojo.require("dojox.html.styles");
+	
+	getSelectedStyleSheet = function(){
+		if(dojo.byId("ssDefault").checked) return false;
+		if(dojo.byId("ssExtra").checked) return "ssExtra";
+	}
+	
+	enableStyleSheet = function(){
+		dojox.html.enableStyleSheet(getSelectedStyleSheet());
+	}
+	
+	disableStyleSheet = function(){
+		dojox.html.disableStyleSheet(getSelectedStyleSheet());
+	}
+	dojo.addOnLoad(function(){
+		console.log(dojo.version.toString());
+		var styles = [
+			"p { font-size:24; margin:20px;}",
+			"p { font-size:12; color:#ff0000;}",
+			".woot { color:#ff0000; }",
+			".woot { color:#00ff00; }",
+			"p span {font-weight:bold;}",
+			"span {font-style:italic;}"
+		]
+		
+		var col = dojo.byId("btnCol");
+		dojo.forEach(styles, function(s){
+		
+			var sel = s.substring(0,s.indexOf("{")-1);
+			var des = s.substring(s.indexOf("{")+1, s.indexOf("}") );
+			
+			var div = dojo.doc.createElement("div");
+			col.appendChild(div);
+			
+			var d = dojo.doc.createElement("span");
+			dojo.style(d, "display", "block");
+			d.innerHTML = s;
+			div.appendChild(d);
+			
+			var b = dojo.doc.createElement("button");
+			div.appendChild(b);
+			b.innerHTML = "Insert";
+			dojo.connect(b, "click", function(){
+				console.log("Add:", s)
+				dojox.html.insertCssRule(sel, des, getSelectedStyleSheet());
+			});
+			var b = dojo.doc.createElement("button");
+			div.appendChild(b);
+			b.innerHTML = "Remove";
+			dojo.connect(b, "click", function(){
+				console.log("Rem:", s);
+				dojox.html.removeCssRule(sel, des);
+			});
+			
+		});
+		
+		
+		
+		
+		console.log("Style Sheets tests:");
+		console.log("dojox.html.getStyleSheet [is false]:", dojox.html.getStyleSheet());
+		// insert a style, which creates our dynamic style sheet:
+		var sel = styles[0].substring(0,styles[0].indexOf("{")-1);
+		var des = styles[0].substring(styles[0].indexOf("{")+1, styles[0].indexOf("}") );
+		dojox.html.insertCssRule(sel, des, getSelectedStyleSheet());
+		console.log("dojox.html.getStyleSheet [object is default]:", dojox.html.getStyleSheet());
+		console.log("dojox.html.activeStyleSheet:", dojox.html.activeStyleSheet().title);
+		dojo.forEach(dojox.html.getToggledStyleSheets(), function(s){
+			console.log("    toggled style sheet:", s.title, "enabled:", !s.disabled);
+		});
+		var ss = dojox.html.getStyleSheets(); //return object
+		for(var nm in ss){
+			//display either title or href
+			var name = (ss[nm].title)?ss[nm].title:ss[nm].href;
+			if(!name){ name = "*Persistant*"}
+			console.log("    style sheet:", name);
+		}
+		console.log("dojox.html.getStyleSheet [href:dijitTests.css, object]:", dojox.html.getStyleSheet("dijitTests.css"));
+		console.log("dojox.html.getStyleSheet [title:BadStyleName]:", dojox.html.getStyleSheet("BadStyleName"));
+	
+	});
+
+</script>
+<style>
+	#btnCol{
+		width:220px;
+	}
+	#btnCol div{
+		margin-bottom:10px;
+	}
+	body table td{
+		vertical-align:top;
+		
+	}
+	button{
+		width:70px;
+		text-align:left;
+	}
+	.label{
+		color:#666666;
+	}
+</style>
+
+</head>
+
+<body>
+<h1>dojox.html.styles Test</h1>
+<p>With the buttons on the left, insert and remove rules with a dynamically created stylesheet. Use the radio buttons
+to create a second style sheet. Toggle them on and off. See the log for more style sheet tests.</p>
+	<table width="100%" cellspacing="0" cellpadding="0">
+  <tr>
+    <td id="btnCol">
+    	<span class="label">Dynamic Stylesheets</span>
+        <div>
+        	<span style="display:block;">Use Style Sheet:</span>
+            <label for="ssDefault">Default</label>
+            <input type="radio" name="ss" id="ssDefault" checked="true"/>
+            <label for="ssExtra">Extra</label>
+            <input type="radio" name="ss" id="ssExtra" />
+            <br>
+            <button onClick="enableStyleSheet();">Enable</button>
+            <button onClick="disableStyleSheet();">Disable</button>
+        </div>
+    </td>
+    <td>
+    	<p>paragraph text</p>
+    
+    <p class="foo">paragraph class=foo text
+    	<span class="woot">span class=woot</span>
+        with a span inside it
+    </p>
+    
+    <p class="bar">paragraph class=bar text
+    	<span class="zoot">span class=zoot</span>
+    	with a span inside it
+    </p>
+     
+     <span class="xoot">external span class=xoot</span>
+    </td>
+  </tr>
+</table>
+	
+     
+     
+    	
+</body>
+</html>
diff --git a/dojox/html/tests/test_themes.html b/dojox/html/tests/test_themes.html
new file mode 100644
index 0000000..f188bf7
--- /dev/null
+++ b/dojox/html/tests/test_themes.html
@@ -0,0 +1,121 @@
+<html>
+<head>
+<title>dojox.html.style Dynamic Style Sheets Test</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+</style>
+<link id="themeStyles" title="tundra" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+<link id="themeStyles" title="nihilo" rel="alternate stylesheet" href="../../../dijit/themes/nihilo/nihilo.css">
+<link id="themeStyles" title="soria" rel="alternate stylesheet" href="../../../dijit/themes/soria/soria.css">
+<link id="themeStyles" title="claro" rel="stylesheet" href="../../../dijit/themes/claro/claro.css">
+
+
+<script type="text/javascript">
+var djConfig = {
+	isDebug: false,
+	parseOnLoad: true,
+	debugAtAllCosts:false
+	//popup:true,
+	//forceFirebugLite:true
+};
+</script>
+
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, fontSizeWatch: true"></script>
+
+<script type="text/javascript">
+
+dojo.require("dojox.html.styles");
+dojo.require("dijit.Menu");
+dojo.require("dijit.Calendar");
+dojo.require("dijit.form.Button");
+dojo.require("dijit.Calendar");
+changeStyle = function(title){
+	dojox.html.activeStyleSheet(title);
+}
+
+dojo.addOnLoad(function(){
+	console.log(dojo.version.toString());
+	var sheets = dojox.html.getToggledStyleSheets();	
+	
+	var holder = dojo.byId("sheetSwitches");
+	dojo.forEach(sheets, function(s){
+		holder.innerHTML += '<button onclick="changeStyle(\''+s.title+'\');">'+s.title+'</button>';
+	});
+	
+});
+
+</script>
+<style>
+#sheetSwitches{
+margin-bottom:15px;
+}
+
+</style>
+
+
+</head>
+
+<body class="tundra nihilo soria claro">
+<h1>dojox.html.style Dynamic Style Sheets</h1>
+<p>The Theme buttons are dymanically generated based on the the link (or style) tag's title attribute. <em>rel="stylesheet"</em> is the preferred, enabled style sheet, and all style sheets with <em>rel="alternate stylesheet"</em> are disabled. Clicking the buttons toggles which style sheet is enabled. Any style sheet without a title attribute is persistent (always enabled). This is based on the W3C spec: http://www.w3.org/TR/html401/present/styles.html#h-14.3.2</p>
+<div id="sheetSwitches"><strong>Switch me:  </strong></div>
+
+<button dojoType="dijit.form.Button" iconClass="plusIcon" onClick='console.debug("clicked simple")'>
+    Simple
+</button>
+
+<button dojoType="dijit.form.DropDownButton" iconClass="noteIcon">
+    <span>Drop Down</span>
+    <div dojoType="dijit.Menu" id="editMenu1" style="display: none;">
+        <div dojoType="dijit.MenuItem"
+            iconClass="dijitEditorIcon dijitEditorIconCut"
+            onClick="console.debug('not actually cutting anything, just a test!')">
+            Cut
+        </div>
+
+        <div dojoType="dijit.MenuItem"
+             iconClass="dijitEditorIcon dijitEditorIconCopy"
+            onClick="console.debug('not actually copying anything, just a test!')">
+            Copy
+        </div>
+
+        <div dojoType="dijit.MenuItem"
+             iconClass="dijitEditorIcon dijitEditorIconPaste"
+            onClick="console.debug('not actually pasting anything, just a test!')">
+            Paste
+        </div>
+    </div>
+</button>
+
+<button dojoType="dijit.form.ComboButton" iconClass="noteIcon"
+    optionsTitle='save options'
+    onClick='console.debug("clicked combo save")'>
+    <span>Combo</span>
+    <div dojoType="dijit.Menu" id="saveMenu1" style="display: none;">
+        <div dojoType="dijit.MenuItem"
+             iconClass="dijitEditorIcon dijitEditorIconSave"
+            onClick="console.debug('not actually saving anything, just a test!')">
+            Save
+        </div>
+        <div dojoType="dijit.MenuItem"
+            onClick="console.debug('not actually saving anything, just a test!')">
+            Save As
+        </div>
+    </div>
+</button>
+
+<button dojoType="dijit.form.ToggleButton" checked onChange="console.log('toggled button checked='+arguments[0]);" iconClass="dijitCheckBoxIcon">
+    Toggle
+</button> 
+     
+<div dojoType="dijit.Calendar"></div>
+    
+<p>
+    This form of style switching is more effective than changing an attribute in the body tag. It makes coding CSS easier, because less emphasis is placed on targeting through the body tag class, and all CSS theme's could theoretically have the exact same selector names.  
+</p>
+    	
+</body>
+</html>
diff --git a/dojox/html/tests/unformatted.html b/dojox/html/tests/unformatted.html
new file mode 100755
index 0000000..b76854c
--- /dev/null
+++ b/dojox/html/tests/unformatted.html
@@ -0,0 +1,25 @@
+<script type="text/javascript">
+var foo = true;
+if(!foo){
+alert("Should not be here.");
+}
+</script>
+<h1>This page has no formatting</h1>
+No kidding.  It looks horrible!  Ugh.
+<table>
+<tbody>
+<tr>
+<td>One cell</td>
+<td>
+Two cell
+</td>
+</tr>
+</tbody>
+</table>
+<ul>
+<li>item one</li>
+<li>
+item two
+</li>
+</ul>
+
diff --git a/dojox/image.js b/dojox/image.js
index 8d40a54..60c010f 100644
--- a/dojox/image.js
+++ b/dojox/image.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.image"]){
-dojo._hasResource["dojox.image"]=true;
 dojo.provide("dojox.image");
 dojo.require("dojox.image._base");
-}
diff --git a/dojox/image/Badge.js b/dojox/image/Badge.js
index fab89f1..7534b0f 100644
--- a/dojox/image/Badge.js
+++ b/dojox/image/Badge.js
@@ -1,102 +1,226 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.image.Badge"]){
-dojo._hasResource["dojox.image.Badge"]=true;
 dojo.provide("dojox.image.Badge");
 dojo.experimental("dojox.image.Badge");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dojo.fx.easing");
-dojo.declare("dojox.image.Badge",[dijit._Widget,dijit._Templated],{baseClass:"dojoxBadge",templateString:"<div class=\"dojoxBadge\" dojoAttachPoint=\"containerNode\"></div>",children:"div.dojoxBadgeImage",rows:4,cols:5,cellSize:50,cellMargin:1,delay:2000,threads:1,easing:"dojo.fx.easing.backOut",startup:function(){
-if(this._started){
-return;
-}
-if(dojo.isString(this.easing)){
-this.easing=dojo.getObject(this.easing);
-}
-this.inherited(arguments);
-this._init();
-},_init:function(){
-var _1=0,_2=this.cellSize;
-dojo.style(this.domNode,{width:_2*this.cols+"px",height:_2*this.rows+"px"});
-this._nl=dojo.query(this.children,this.containerNode).forEach(function(n,_3){
-var _4=_3%this.cols,t=_1*_2,l=_4*_2,m=this.cellMargin*2;
-dojo.style(n,{top:t+"px",left:l+"px",width:_2-m+"px",height:_2-m+"px"});
-if(_4==this.cols-1){
-_1++;
-}
-dojo.addClass(n,this.baseClass+"Image");
-},this);
-var l=this._nl.length;
-while(this.threads--){
-var s=Math.floor(Math.random()*l);
-setTimeout(dojo.hitch(this,"_enbiggen",{target:this._nl[s]}),this.delay*this.threads);
-}
-},_getCell:function(n){
-var _5=this._nl.indexOf(n);
-if(_5>=0){
-var _6=_5%this.cols;
-var _7=Math.floor(_5/this.cols);
-return {x:_6,y:_7,n:this._nl[_5],io:_5};
-}else{
-return undefined;
-}
-},_getImage:function(){
-return "url('')";
-},_enbiggen:function(e){
-var _8=this._getCell(e.target||e);
-if(_8){
-var m=this.cellMargin,_9=(this.cellSize*2)-(m*2),_a={height:_9,width:_9};
-var _b=function(){
-return Math.round(Math.random());
-};
-if(_8.x==this.cols-1||(_8.x>0&&_b())){
-_a.left=this.cellSize*(_8.x-m);
-}
-if(_8.y==this.rows-1||(_8.y>0&&_b())){
-_a.top=this.cellSize*(_8.y-m);
-}
-var bc=this.baseClass;
-dojo.addClass(_8.n,bc+"Top");
-dojo.addClass(_8.n,bc+"Seen");
-dojo.animateProperty({node:_8.n,properties:_a,onEnd:dojo.hitch(this,"_loadUnder",_8,_a),easing:this.easing}).play();
-}
-},_loadUnder:function(_c,_d){
-var _e=_c.io;
-var _f=[];
-var _10=(_d.left>=0);
-var _11=(_d.top>=0);
-var c=this.cols,e=_e+(_10?-1:1),f=_e+(_11?-c:c),g=(_11?(_10?e-c:f+1):(_10?f-1:e+c)),bc=this.baseClass;
-dojo.forEach([e,f,g],function(x){
-var n=this._nl[x];
-if(n){
-if(dojo.hasClass(n,bc+"Seen")){
-dojo.removeClass(n,bc+"Seen");
-}
-}
-},this);
-setTimeout(dojo.hitch(this,"_disenbiggen",_c,_d),this.delay*1.25);
-},_disenbiggen:function(_12,_13){
-if(_13.top>=0){
-_13.top+=this.cellSize;
-}
-if(_13.left>=0){
-_13.left+=this.cellSize;
-}
-var _14=this.cellSize-(this.cellMargin*2);
-dojo.animateProperty({node:_12.n,properties:dojo.mixin(_13,{width:_14,height:_14}),onEnd:dojo.hitch(this,"_cycle",_12,_13)}).play(5);
-},_cycle:function(_15,_16){
-var bc=this.baseClass;
-dojo.removeClass(_15.n,bc+"Top");
-var ns=this._nl.filter(function(n){
-return !dojo.hasClass(n,bc+"Seen");
+
+dojo.declare("dojox.image.Badge", [dijit._Widget, dijit._Templated], {
+	// summary: A simple grid of Images that loops through thumbnails
+	//
+
+	baseClass: "dojoxBadge",
+	
+	templateString:'<div class="dojoxBadge" dojoAttachPoint="containerNode"></div>',
+
+	// children: String
+	// 		A CSS3 Selector that determines the node to become a child
+	children: "div.dojoxBadgeImage",
+
+	// rows: Integer
+	//		Number of Rows to display
+	rows: 4,
+	
+	// cols: Integer
+	//		Number of Columns to display 
+	cols: 5,
+	
+	// cellSize: Integer
+	//		Size in PX of each thumbnail
+	cellSize: 50,
+	
+	// cellMargin: Integer
+	//		Size in PX to adjust for cell margins
+	cellMargin: 1,
+	
+	// delay: Integer
+	//		Time (in ms) to show the image before sizing down again
+	delay: 2000,
+	
+	// threads: Integer
+	//		how many cycles will be going "simultaneously" (>2 not reccommended)
+	threads: 1,
+	
+	// easing: Function|String
+	//		An easing function to use when showing the node (does not apply to shrinking)
+	easing: "dojo.fx.easing.backOut",
+	
+	startup: function(){
+		if(this._started){ return; }
+		if(dojo.isString(this.easing)){
+			this.easing = dojo.getObject(this.easing);
+		}
+		this.inherited(arguments);
+		this._init();
+	},
+	
+	_init: function(){
+		// summary: Setup and layout the images
+	
+		var _row = 0, 
+			_w = this.cellSize; 
+
+		dojo.style(this.domNode, {
+			width: _w * this.cols + "px",
+			height: _w * this.rows + "px"
+		});
+
+		this._nl = dojo.query(this.children, this.containerNode)
+			.forEach(function(n, _idx){
+
+				var _col = _idx % this.cols,
+					t = _row * _w,
+					l = _col * _w,
+					m = this.cellMargin * 2;
+			
+				dojo.style(n, {
+		 			top: t + "px",
+		 			left: l + "px",
+					width: _w - m + "px",
+					height: _w - m + "px"
+		 		});
+
+				if(_col == this.cols - 1){ _row++; }
+				dojo.addClass(n, this.baseClass + "Image");
+				
+			}, this)
+		;
+		
+		var l = this._nl.length;
+		while(this.threads--){
+			var s = Math.floor(Math.random() * l);
+			setTimeout(dojo.hitch(this, "_enbiggen", { 
+				target: this._nl[s]
+			}), this.delay * this.threads);
+		}
+		
+	},
+	
+	_getCell: function(/* DomNode */ n){
+		// summary: Return information about the position for a given node
+		var _pos = this._nl.indexOf(n);
+		if(_pos >= 0){
+			var _col = _pos % this.cols;
+			var _row = Math.floor(_pos / this.cols);
+			return { x: _col, y: _row, n: this._nl[_pos], io: _pos };
+		}else{
+			return undefined;
+		}
+	},
+	
+	_getImage: function(){
+		// summary: Returns the next image in the list, or the first one if not available
+		return "url('')";
+	},
+	
+	_enbiggen: function(/* Event|DomNode */ e){
+		// summary: Show the passed node in the picker
+		var _pos = this._getCell(e.target || e);
+
+		if (_pos){
+			// we have a node, and know where it is
+
+			var m = this.cellMargin,
+				_cc = (this.cellSize * 2) - (m * 2),
+				props = {
+					height: _cc,
+					width: _cc
+				}
+			;
+			
+			var _tehDecider = function(){
+				// if we have room, we'll want to decide which direction to go
+				// let "teh decider" decide.
+				return Math.round(Math.random()); 
+			};
+			
+			if(_pos.x == this.cols - 1 || (_pos.x > 0 && _tehDecider() )){
+				// we have to go left, at right edge (or we want to and not on left edge)
+				props.left = this.cellSize * (_pos.x - m);
+			}
+			
+			if(_pos.y == this.rows - 1 || (_pos.y > 0 && _tehDecider() )){
+				// we have to go up, at bottom edge (or we want to and not at top)
+				props.top = this.cellSize * (_pos.y - m);
+			}
+
+			var bc = this.baseClass;
+			dojo.addClass(_pos.n, bc + "Top");
+			dojo.addClass(_pos.n, bc + "Seen");
+
+			dojo.animateProperty({ node: _pos.n, properties: props,
+				onEnd: dojo.hitch(this, "_loadUnder", _pos, props),
+				easing: this.easing 
+			}).play();
+			
+		}
+	},
+	
+	_loadUnder: function(info, props){
+		// summary: figure out which three images are being covered, and 
+		//		determine if they need loaded or not
+
+		var idx = info.io;
+		var nodes = [];
+
+		var isLeft = (props.left >= 0);
+		var isUp = (props.top >= 0);
+		
+		var c = this.cols,
+			// the three node index's we're allegedly over:
+			e = idx + (isLeft ? -1 : 1),
+			f = idx + (isUp ? -c : c),
+			// don't ask:
+			g = (isUp ? (isLeft ? e - c : f + 1) : (isLeft ? f - 1 : e + c)),
+
+			bc = this.baseClass;
+		
+		dojo.forEach([e, f, g], function(x){
+			var n = this._nl[x];
+			if(n){
+				if(dojo.hasClass(n, bc + "Seen")){
+					// change the background image out?
+					dojo.removeClass(n, bc + "Seen");
+				}
+			}
+		},this);
+		
+		setTimeout(dojo.hitch(this, "_disenbiggen", info, props), this.delay * 1.25);
+
+	},
+	
+	_disenbiggen: function(info, props){
+		// summary: Hide the passed node (info.n), passing along properties
+		//		received.
+		
+		if(props.top >= 0){
+			props.top += this.cellSize;
+		}
+		if(props.left >= 0){
+			props.left += this.cellSize; 
+		}
+		var _cc = this.cellSize - (this.cellMargin * 2);
+		dojo.animateProperty({
+			node: info.n, 
+			properties: dojo.mixin(props, {
+				width:_cc, 
+				height:_cc
+			}),
+			onEnd: dojo.hitch(this, "_cycle", info, props)
+		}).play(5);
+	},
+	
+	_cycle: function(info, props){
+		// summary: Select an un-viewed image from the list, and show it
+
+		var bc = this.baseClass; 
+		dojo.removeClass(info.n, bc + "Top");
+		var ns = this._nl.filter(function(n){
+			return !dojo.hasClass(n, bc + "Seen")
+		});
+		var c = ns[Math.floor(Math.random() * ns.length)];
+		setTimeout(dojo.hitch(this,"_enbiggen", { target: c }), this.delay / 2)
+
+	}
+	
 });
-var c=ns[Math.floor(Math.random()*ns.length)];
-setTimeout(dojo.hitch(this,"_enbiggen",{target:c}),this.delay/2);
-}});
-}
diff --git a/dojox/image/FlickrBadge.js b/dojox/image/FlickrBadge.js
index 57775ed..d58ce70 100644
--- a/dojox/image/FlickrBadge.js
+++ b/dojox/image/FlickrBadge.js
@@ -1,60 +1,105 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.image.FlickrBadge"]){
-dojo._hasResource["dojox.image.FlickrBadge"]=true;
 dojo.provide("dojox.image.FlickrBadge");
+
 dojo.require("dojox.image.Badge");
 dojo.require("dojox.data.FlickrRestStore");
-dojo.declare("dojox.image.FlickrBadge",dojox.image.Badge,{children:"a.flickrImage",userid:"",username:"",setid:"",tags:"",searchText:"",target:"",apikey:"8c6803164dbc395fb7131c9d54843627",_store:null,postCreate:function(){
-if(this.username&&!this.userid){
-var _1=dojo.io.script.get({url:"http://www.flickr.com/services/rest/",preventCache:true,content:{format:"json",method:"flickr.people.findByUsername",api_key:this.apikey,username:this.username},callbackParamName:"jsoncallback"});
-_1.addCallback(this,function(_2){
-if(_2.user&&_2.user.nsid){
-this.userid=_2.user.nsid;
-if(!this._started){
-this.startup();
-}
-}
+
+dojo.declare("dojox.image.FlickrBadge", dojox.image.Badge, {
+	children: "a.flickrImage",
+
+	// userid: String
+	// 		If you know your Flickr userid, you can set it to prevent a call to fetch the id
+	userid: "",
+
+	// username: String
+	// 		Your Flickr username
+	username: "",
+
+	// setid: String
+	// 		The id of the set to display
+	setid: "",
+
+	// tags: String|Array
+	// 		A comma separated list of tags or an array of tags to grab from Flickr
+	tags: "",
+
+	// searchText: String
+	// 		Free text search.  Photos who's title, description, or tags contain the text will be displayed
+	searchText: "",
+
+	// target: String
+	// 		Where to display the pictures when clicked on.  Valid values are the same as the target attribute
+	// 		of the A tag.
+	target: "",
+
+	apikey: "8c6803164dbc395fb7131c9d54843627",
+	_store: null,
+
+	postCreate: function(){
+		if(this.username && !this.userid){
+			var def = dojo.io.script.get({
+				url: "http://www.flickr.com/services/rest/",
+				preventCache: true,
+				content: {
+					format: "json",
+					method: "flickr.people.findByUsername",
+					api_key: this.apikey,
+					username: this.username
+				},
+				callbackParamName: "jsoncallback"
+			});
+			def.addCallback(this, function(data){
+				if(data.user && data.user.nsid){
+					this.userid = data.user.nsid;
+					if(!this._started){
+						this.startup();
+					}
+				}
+			});
+		}
+	},
+
+	startup: function(){
+		if(this._started){ return; }
+		if(this.userid){
+			var query = {
+				userid: this.userid
+			};
+			if(this.setid){
+				query["setid"] = this.setid;
+			}
+			if(this.tags){
+				query.tags = this.tags;
+			}
+			if(this.searchText){
+				query.text = this.searchText;
+			}
+			var args = arguments;
+			this._store = new dojox.data.FlickrRestStore({ apikey: this.apikey });
+			this._store.fetch({
+				count: this.cols * this.rows,
+				query: query,
+				onComplete: dojo.hitch(this, function(items){
+					dojo.forEach(items, function(item){
+						var a = dojo.doc.createElement("a");
+						dojo.addClass(a, "flickrImage");
+						a.href = this._store.getValue(item, "link");
+						if(this.target){
+							a.target = this.target;
+						}
+
+						var img = dojo.doc.createElement("img");
+						img.src = this._store.getValue(item, "imageUrlThumb");
+						dojo.style(img, {
+							width: "100%",
+							height: "100%"
+						});
+
+						a.appendChild(img);
+						this.domNode.appendChild(a);
+					}, this);
+					dojox.image.Badge.prototype.startup.call(this, args);
+				})
+			});
+		}
+	}
 });
-}
-},startup:function(){
-if(this._started){
-return;
-}
-if(this.userid){
-var _3={userid:this.userid};
-if(this.setid){
-_3["setid"]=this.setid;
-}
-if(this.tags){
-_3.tags=this.tags;
-}
-if(this.searchText){
-_3.text=this.searchText;
-}
-var _4=arguments;
-this._store=new dojox.data.FlickrRestStore({apikey:this.apikey});
-this._store.fetch({count:this.cols*this.rows,query:_3,onComplete:dojo.hitch(this,function(_5){
-dojo.forEach(_5,function(_6){
-var a=dojo.doc.createElement("a");
-dojo.addClass(a,"flickrImage");
-a.href=this._store.getValue(_6,"link");
-if(this.target){
-a.target=this.target;
-}
-var _7=dojo.doc.createElement("img");
-_7.src=this._store.getValue(_6,"imageUrlThumb");
-dojo.style(_7,{width:"100%",height:"100%"});
-a.appendChild(_7);
-this.domNode.appendChild(a);
-},this);
-dojox.image.Badge.prototype.startup.call(this,_4);
-})});
-}
-}});
-}
diff --git a/dojox/image/Gallery.js b/dojox/image/Gallery.js
index a7c6007..5439e76 100644
--- a/dojox/image/Gallery.js
+++ b/dojox/image/Gallery.js
@@ -1,65 +1,190 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.image.Gallery"]){
-dojo._hasResource["dojox.image.Gallery"]=true;
 dojo.provide("dojox.image.Gallery");
 dojo.experimental("dojox.image.Gallery");
+//
+// dojox.image.Gallery courtesy Shane O Sullivan, licensed under a Dojo CLA 
+// @author  Copyright 2007 Shane O Sullivan (shaneosullivan1 at gmail.com)
+//
+// For a sample usage, see http://www.skynet.ie/~sos/photos.php
+//
+//	TODO: Make public, document params and privitize non-API conformant methods.
+//	document topics.
+
 dojo.require("dojo.fx");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dojox.image.ThumbnailPicker");
 dojo.require("dojox.image.SlideShow");
-dojo.declare("dojox.image.Gallery",[dijit._Widget,dijit._Templated],{imageHeight:375,imageWidth:500,pageSize:dojox.image.SlideShow.prototype.pageSize,autoLoad:true,linkAttr:"link",imageThumbAttr:"imageUrlThumb",imageLargeAttr:"imageUrl",titleAttr:"title",slideshowInterval:3,templateString:dojo.cache("dojox.image","resources/Gallery.html","<div dojoAttachPoint=\"outerNode\" class=\"imageGalleryWrapper\">\n\t<div dojoAttachPoint=\"thumbPickerNode\"></div>\n\t<div dojoAttachPoint=\"slideSho [...]
-this.widgetid=this.id;
-this.inherited(arguments);
-this.thumbPicker=new dojox.image.ThumbnailPicker({linkAttr:this.linkAttr,imageLargeAttr:this.imageLargeAttr,imageThumbAttr:this.imageThumbAttr,titleAttr:this.titleAttr,useLoadNotifier:true,size:this.imageWidth},this.thumbPickerNode);
-this.slideShow=new dojox.image.SlideShow({imageHeight:this.imageHeight,imageWidth:this.imageWidth,autoLoad:this.autoLoad,linkAttr:this.linkAttr,imageLargeAttr:this.imageLargeAttr,titleAttr:this.titleAttr,slideshowInterval:this.slideshowInterval,pageSize:this.pageSize},this.slideShowNode);
-var _1=this;
-dojo.subscribe(this.slideShow.getShowTopicName(),function(_2){
-_1.thumbPicker._showThumbs(_2.index);
-});
-dojo.subscribe(this.thumbPicker.getClickTopicName(),function(_3){
-_1.slideShow.showImage(_3.index);
-});
-dojo.subscribe(this.thumbPicker.getShowTopicName(),function(_4){
-_1.slideShow.moveImageLoadingPointer(_4.index);
-});
-dojo.subscribe(this.slideShow.getLoadTopicName(),function(_5){
-_1.thumbPicker.markImageLoaded(_5);
+
+dojo.declare("dojox.image.Gallery",
+	[dijit._Widget, dijit._Templated],
+	{
+	// summary:
+	//		Gallery widget that wraps a dojox.image.ThumbnailPicker and dojox.image.SlideShow widget
+	//
+	// imageHeight: Number
+	//		Maximum height of an image in the SlideShow widget
+	imageHeight: 375,
+	
+	// imageWidth: Number
+	//		Maximum width of an image in the SlideShow widget
+	imageWidth: 500,
+		
+	// pageSize: Number
+	//		The number of records to retrieve from the data store per request.
+	pageSize: dojox.image.SlideShow.prototype.pageSize,
+	
+	// autoLoad: Boolean
+	//		If true, images are loaded before the user views them. If false, an
+	//		image is loaded when the user displays it.
+	autoLoad: true,
+	
+	// linkAttr: String
+	//		Defines the name of the attribute to request from the store to retrieve the
+	//		URL to link to from an image, if any.
+	linkAttr: "link",
+	
+	// imageThumbAttr: String
+	//		Defines the name of the attribute to request from the store to retrieve the
+	//		URL to the thumbnail image.
+	imageThumbAttr: "imageUrlThumb",
+	
+	// imageLargeAttr: String
+	//		Defines the name of the attribute to request from the store to retrieve the
+	//		URL to the image.
+	imageLargeAttr: "imageUrl",
+	
+	// titleAttr: String
+	//		Defines the name of the attribute to request from the store to retrieve the
+	//		title of the picture, if any.
+	titleAttr: "title",
+ 
+	// slideshowInterval: Integer
+	//		Time, in seconds, between image changes in the slide show.
+	slideshowInterval: 3,
+	
+	templateString: dojo.cache("dojox.image", "resources/Gallery.html"), 
+
+	postCreate: function(){
+		// summary: 
+		//		Initializes the widget, creates the ThumbnailPicker and SlideShow widgets
+		this.widgetid = this.id;
+		this.inherited(arguments)
+		
+		this.thumbPicker = new dojox.image.ThumbnailPicker({
+			linkAttr: this.linkAttr,
+			imageLargeAttr: this.imageLargeAttr,
+			imageThumbAttr: this.imageThumbAttr,
+			titleAttr: this.titleAttr,
+			useLoadNotifier: true,
+			size: this.imageWidth
+		}, this.thumbPickerNode);
+		
+		
+		this.slideShow = new dojox.image.SlideShow({
+			imageHeight: this.imageHeight, 
+			imageWidth: this.imageWidth,
+			autoLoad: this.autoLoad,
+			linkAttr: this.linkAttr,
+			imageLargeAttr: this.imageLargeAttr,
+			titleAttr: this.titleAttr,
+			slideshowInterval: this.slideshowInterval,
+			pageSize: this.pageSize 
+		}, this.slideShowNode);
+		
+		var _this = this;
+		//When an image is shown in the Slideshow, make sure it is visible
+		//in the ThumbnailPicker
+		dojo.subscribe(this.slideShow.getShowTopicName(), function(packet){
+			_this.thumbPicker._showThumbs(packet.index);
+		});	
+		//When the user clicks a thumbnail, show that image
+		dojo.subscribe(this.thumbPicker.getClickTopicName(), function(evt){
+			_this.slideShow.showImage(evt.index);
+		});
+		//When the ThumbnailPicker moves to show a new set of pictures,
+		//make the Slideshow start loading those pictures first.
+		dojo.subscribe(this.thumbPicker.getShowTopicName(), function(evt){
+			_this.slideShow.moveImageLoadingPointer(evt.index);
+		});
+		//When an image finished loading in the slideshow, update the loading
+		//notification in the ThumbnailPicker
+		dojo.subscribe(this.slideShow.getLoadTopicName(), function(index){
+			_this.thumbPicker.markImageLoaded(index);
+		});
+		this._centerChildren();
+	},
+	  
+  	setDataStore: function(dataStore, request, /*optional*/paramNames){
+		// summary: 
+		//		Sets the data store and request objects to read data from.
+		// dataStore:
+		//		An implementation of the dojo.data.api.Read API. This accesses the image
+		//		data.
+		// request:
+		//		An implementation of the dojo.data.api.Request API. This specifies the
+		//		query and paging information to be used by the data store
+		// paramNames:
+		//		An object defining the names of the item attributes to fetch from the
+		//		data store.  The four attributes allowed are 'linkAttr', 'imageLargeAttr',
+		//		'imageThumbAttr' and 'titleAttr'
+		this.thumbPicker.setDataStore(dataStore, request, paramNames);
+		this.slideShow.setDataStore(dataStore, request, paramNames);
+  	},
+  
+  	reset: function(){
+		// summary:
+		//		Resets the widget to its initial state
+		this.slideShow.reset();
+		this.thumbPicker.reset();
+  	},
+  
+	showNextImage: function(inTimer){
+		// summary: 
+		//		Changes the image being displayed in the SlideShow to the next
+		//		image in the data store
+		// inTimer: Boolean
+		//		If true, a slideshow is active, otherwise the slideshow is inactive.
+		this.slideShow.showNextImage();
+	},
+
+	toggleSlideshow: function(){
+		dojo.deprecated("dojox.widget.Gallery.toggleSlideshow is deprecated.  Use toggleSlideShow instead.", "", "2.0");
+		this.toggleSlideShow();
+	},
+
+	toggleSlideShow: function(){
+		// summary:
+		//		Switches the slideshow mode on and off.
+		this.slideShow.toggleSlideShow();
+	},
+
+	showImage: function(index, /*optional*/callback){
+		// summary:
+		//		Shows the image at index 'idx'.
+		// idx: Number
+		//		The position of the image in the data store to display
+		// callback: Function
+		//		Optional callback function to call when the image has finished displaying.
+		this.slideShow.showImage(index, callback);
+	},
+	
+	resize: function(dim){
+		this.thumbPicker.resize(dim);
+	},
+	
+	_centerChildren: function() {
+		// summary: 
+		//		Ensures that the ThumbnailPicker and the SlideShow widgets
+		//		are centered.
+		var thumbSize = dojo.marginBox(this.thumbPicker.outerNode);
+		var slideSize = dojo.marginBox(this.slideShow.outerNode);
+		
+		var diff = (thumbSize.w - slideSize.w) / 2;
+		
+		if(diff > 0) {
+			dojo.style(this.slideShow.outerNode, "marginLeft", diff + "px");
+		} else if(diff < 0) {
+			dojo.style(this.thumbPicker.outerNode, "marginLeft", (diff * -1) + "px");
+		}
+	}
 });
-this._centerChildren();
-},setDataStore:function(_6,_7,_8){
-this.thumbPicker.setDataStore(_6,_7,_8);
-this.slideShow.setDataStore(_6,_7,_8);
-},reset:function(){
-this.slideShow.reset();
-this.thumbPicker.reset();
-},showNextImage:function(_9){
-this.slideShow.showNextImage();
-},toggleSlideshow:function(){
-dojo.deprecated("dojox.widget.Gallery.toggleSlideshow is deprecated.  Use toggleSlideShow instead.","","2.0");
-this.toggleSlideShow();
-},toggleSlideShow:function(){
-this.slideShow.toggleSlideShow();
-},showImage:function(_a,_b){
-this.slideShow.showImage(_a,_b);
-},resize:function(_c){
-this.thumbPicker.resize(_c);
-},_centerChildren:function(){
-var _d=dojo.marginBox(this.thumbPicker.outerNode);
-var _e=dojo.marginBox(this.slideShow.outerNode);
-var _f=(_d.w-_e.w)/2;
-if(_f>0){
-dojo.style(this.slideShow.outerNode,"marginLeft",_f+"px");
-}else{
-if(_f<0){
-dojo.style(this.thumbPicker.outerNode,"marginLeft",(_f*-1)+"px");
-}
-}
-}});
-}
diff --git a/dojox/image/Lightbox.js b/dojox/image/Lightbox.js
index bd03195..8dd8833 100644
--- a/dojox/image/Lightbox.js
+++ b/dojox/image/Lightbox.js
@@ -1,246 +1,580 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.image.Lightbox"]){
-dojo._hasResource["dojox.image.Lightbox"]=true;
 dojo.provide("dojox.image.Lightbox");
 dojo.experimental("dojox.image.Lightbox");
-dojo.require("dijit.Dialog");
+
+dojo.require("dojo.window");
+dojo.require("dijit.Dialog"); 
 dojo.require("dojox.fx._base");
-dojo.declare("dojox.image.Lightbox",dijit._Widget,{group:"",title:"",href:"",duration:500,modal:false,_allowPassthru:false,_attachedDialog:null,startup:function(){
-this.inherited(arguments);
-var _1=dijit.byId("dojoxLightboxDialog");
-if(_1){
-this._attachedDialog=_1;
-}else{
-this._attachedDialog=new dojox.image.LightboxDialog({id:"dojoxLightboxDialog"});
-this._attachedDialog.startup();
-}
-if(!this.store){
-this._addSelf();
-this.connect(this.domNode,"onclick","_handleClick");
-}
-},_addSelf:function(){
-this._attachedDialog.addImage({href:this.href,title:this.title},this.group||null);
-},_handleClick:function(e){
-if(!this._allowPassthru){
-e.preventDefault();
-}else{
-return;
-}
-this.show();
-},show:function(){
-this._attachedDialog.show(this);
-},hide:function(){
-this._attachedDialog.hide();
-},disable:function(){
-this._allowPassthru=true;
-},enable:function(){
-this._allowPassthru=false;
-},onClick:function(){
-}});
-dojo.declare("dojox.image.LightboxDialog",dijit.Dialog,{title:"",inGroup:null,imgUrl:dijit._Widget.prototype._blankGif,errorMessage:"Image not found.",adjust:true,modal:false,_groups:{XnoGroupX:[]},errorImg:dojo.moduleUrl("dojox.image","resources/images/warning.png"),templateString:dojo.cache("dojox.image","resources/Lightbox.html","<div class=\"dojoxLightbox\" dojoAttachPoint=\"containerNode\">\n\t<div style=\"position:relative\">\n\t\t<div dojoAttachPoint=\"imageContainer\" class=\"doj [...]
-this.inherited(arguments);
-this._animConnects=[];
-this.connect(this.nextNode,"onclick","_nextImage");
-this.connect(this.prevNode,"onclick","_prevImage");
-this.connect(this.closeNode,"onclick","hide");
-this._makeAnims();
-this._vp=dijit.getViewport();
-return this;
-},show:function(_2){
-var _3=this;
-this._lastGroup=_2;
-if(!_3.open){
-_3.inherited(arguments);
-this._modalconnects.push(dojo.connect(dojo.global,"onscroll",this,"_position"),dojo.connect(dojo.global,"onresize",this,"_position"),dojo.connect(dojo.body(),"onkeypress",this,"_handleKey"));
-if(!_2.modal){
-this._modalconnects.push(dojo.connect(dijit._underlay.domNode,"onclick",this,"onCancel"));
-}
-}
-if(this._wasStyled){
-dojo.destroy(_3.imgNode);
-_3.imgNode=dojo.create("img",null,_3.imageContainer,"first");
-_3._makeAnims();
-_3._wasStyled=false;
-}
-dojo.style(_3.imgNode,"opacity","0");
-dojo.style(_3.titleNode,"opacity","0");
-var _4=_2.href;
-if((_2.group&&_2!=="XnoGroupX")||_3.inGroup){
-if(!_3.inGroup){
-_3.inGroup=_3._groups[(_2.group)];
-dojo.forEach(_3.inGroup,function(g,i){
-if(g.href==_2.href){
-_3._index=i;
-}
-},_3);
-}
-if(!_3._index){
-_3._index=0;
-_4=_3.inGroup[_3._index].href;
-}
-_3.groupCount.innerHTML=" ("+(_3._index+1)+" of "+_3.inGroup.length+")";
-_3.prevNode.style.visibility="visible";
-_3.nextNode.style.visibility="visible";
-}else{
-_3.groupCount.innerHTML="";
-_3.prevNode.style.visibility="hidden";
-_3.nextNode.style.visibility="hidden";
-}
-if(!_2.leaveTitle){
-_3.textNode.innerHTML=_2.title;
-}
-_3._ready(_4);
-},_ready:function(_5){
-var _6=this;
-_6._imgError=dojo.connect(_6.imgNode,"error",_6,function(){
-dojo.disconnect(_6._imgError);
-_6.imgNode.src=_6.errorImg;
-_6.textNode.innerHTML=_6.errorMessage;
+
+dojo.declare("dojox.image.Lightbox",
+	dijit._Widget, {
+	// summary:
+	//		A dojo-based Lightbox implementation. 
+	//
+	// description:
+	//	An Elegant, keyboard accessible, markup and store capable Lightbox widget to show images
+	//	in a modal dialog-esque format. Can show individual images as Modal dialog, or can group
+	//	images with multiple entry points, all using a single "master" Dialog for visualization
+	//
+	//	key controls:
+	//		ESC - close
+	//		Down Arrow / Rt Arrow / N - Next Image
+	//		Up Arrow / Lf Arrow / P - Previous Image
+	// 
+	// example:
+	// |	<a href="image1.jpg" dojoType="dojox.image.Lightbox">show lightbox</a>
+	//
+	// example: 
+	// |	<a href="image2.jpg" dojoType="dojox.image.Lightbox" group="one">show group lightbox</a>
+	// |	<a href="image3.jpg" dojoType="dojox.image.Lightbox" group="one">show group lightbox</a>
+	//
+	// example:	 
+	// |	not implemented fully yet, though works with basic datastore access. need to manually call
+	// |	widget._attachedDialog.addImage(item,"fromStore") for each item in a store result set.
+	// |	<div dojoType="dojox.image.Lightbox" group="fromStore" store="storeName"></div>
+	//
+	// group: String
+	//		Grouping images in a page with similar tags will provide a 'slideshow' like grouping of images
+	group: "",
+
+	// title: String 
+	//		A string of text to be shown in the Lightbox beneath the image (empty if using a store)
+	title: "",
+
+	// href; String
+	//		Link to image to use for this Lightbox node (empty if using a store).
+	href: "",
+
+	// duration: Integer
+	//		Generic time in MS to adjust the feel of widget. could possibly add various 
+	//		durations for the various actions (dialog fadein, sizeing, img fadein ...) 
+	duration: 500,
+
+	// modal: Boolean
+	//		If true, this Dialog instance will be truly modal and prevent closing until
+	//		explicitly told to by calling hide() or clicking the (x) - Defaults to false
+	//		to preserve previous behaviors. (aka: enable click-to-click on the underlay)
+	modal: false,
+
+	// _allowPassthru: Boolean
+	//		Privately set this to disable/enable natural link of anchor tags
+	_allowPassthru: false,
+	
+	// _attachedDialg: dojox.image._LightboxDialog
+	//		The pointer to the global lightbox dialog for this widget
+	_attachedDialog: null, // try to share a single underlay per page?
+
+	startup: function(){
+		this.inherited(arguments);
+		// setup an attachment to the masterDialog (or create the masterDialog)
+		var tmp = dijit.byId('dojoxLightboxDialog');
+		if(tmp){
+			this._attachedDialog = tmp;
+		}else{
+			// this is the first instance to start, so we make the masterDialog
+			this._attachedDialog = new dojox.image.LightboxDialog({ id: "dojoxLightboxDialog" });
+			this._attachedDialog.startup();
+		}
+		if(!this.store){
+			// FIXME: full store support lacking, have to manually call this._attachedDialog.addImage(imgage,group) as it stands
+			this._addSelf();
+			this.connect(this.domNode, "onclick", "_handleClick");
+		}
+
+	},
+
+	_addSelf: function(){
+		// summary: Add this instance to the master LightBoxDialog
+		this._attachedDialog.addImage({
+			href: this.href,
+			title: this.title
+		}, this.group || null);
+	},
+
+	_handleClick: function(/* Event */e){
+		// summary: Handle the click on the link 
+		if(!this._allowPassthru){ e.preventDefault(); }
+		else{ return; }
+		this.show();
+	},
+
+	show: function(){
+		// summary: Show the Lightbox with this instance as the starting point
+		this._attachedDialog.show(this);
+	},
+	
+	hide: function(){
+		// summary: Hide the Lightbox currently showing
+		this._attachedDialog.hide();
+	},
+
+	// FIXME: switch to .attr, deprecate eventually.
+	disable: function(){
+		// summary: Disables event clobbering and dialog, and follows natural link
+		this._allowPassthru = true;
+	},
+
+	enable: function(){
+		// summary: Enables the dialog (prevents default link)
+		this._allowPassthru = false; 
+	},
+	
+	onClick: function(){
+		// summary:
+		//		Stub fired when the image in the lightbox is clicked.
+	},
+	
+	destroy: function(){
+		this._attachedDialog.removeImage(this);
+		this.inherited(arguments);
+	}
+
 });
-_6._imgConnect=dojo.connect(_6.imgNode,"load",_6,function(e){
-_6.resizeTo({w:_6.imgNode.width,h:_6.imgNode.height,duration:_6.duration});
-dojo.disconnect(_6._imgConnect);
-if(_6._imgError){
-dojo.disconnect(_6._imgError);
-}
+
+dojo.declare("dojox.image.LightboxDialog",
+	dijit.Dialog, {
+	// summary:
+	//		The "dialog" shared	 between any Lightbox instances on the page, publically available
+	//		for programatic manipulation.
+	//
+	// description:
+	//	
+	//		A widget that intercepts anchor links (typically around images)		
+	//		and displays a modal Dialog. this is the actual Dialog, which you can
+	//		create and populate manually, though should use simple Lightbox's
+	//		unless you need the direct access.
+	//
+	//		There should only be one of these on a page, so all dojox.image.Lightbox's will us it
+	//		(the first instance of a Lightbox to be show()'n will create me If i do not exist)
+	//	
+	//	example: 
+	//	|	// show a single image from a url
+	//	|	var url = "http://dojotoolkit.org/logo.png";
+	//	|	var dialog = new dojox.image.LightboxDialog().startup();
+	//	|	dialog.show({ href: url, title:"My Remote Image"});
+	//	
+	// title: String
+	//		The current title, read from object passed to show() 
+	title: "",
+
+	// FIXME: implement titleTemplate
+
+	// inGroup: Array
+	//		Array of objects. this is populated by from the JSON object _groups, and
+	//		should not be populate manually. it is a placeholder for the currently 
+	//		showing group of images in this master dialog
+	inGroup: null,
+
+	// imgUrl: String
+	//		The src="" attribute of our imageNode (can be null at statup)
+	imgUrl: dijit._Widget.prototype._blankGif,
+		
+	// errorMessage: String
+	//		The text to display when an unreachable image is linked
+	errorMessage: "Image not found.",
+
+	// adjust: Boolean
+	//		If true, ensure the image always stays within the viewport
+	//		more difficult than necessary to disable, but enabled by default
+	//		seems sane in most use cases.
+	adjust: true,
+
+	// modal: Boolean
+	//		If true, this Dialog instance will be truly modal and prevent closing until
+	//		explicitly told to by calling hide() or clicking the (x) - Defaults to false
+	//		to preserve previous behaviors. (aka: enable click-to-click on the underlay)
+	modal: false,
+	
+	// an object of arrays, each array (of objects) being a unique 'group'
+	_groups: { XnoGroupX: [] },
+
+	// errorImg: Url
+	//		Path to the image used when a 404 is encountered
+	errorImg: dojo.moduleUrl("dojox.image","resources/images/warning.png"),
+
+	templateString: dojo.cache("dojox.image","resources/Lightbox.html"),
+
+	startup: function(){
+		// summary: Add some extra event handlers, and startup our superclass.
+		//
+		// returns: dijit._Widget
+		//		Perhaps the only `dijit._Widget` that returns itself to allow
+		//		'chaining' or var referencing with .startup()
+
+		this.inherited(arguments);
+		this._animConnects = [];
+		this.connect(this.nextButtonNode, "onclick", "_nextImage");
+		this.connect(this.prevButtonNode, "onclick", "_prevImage");
+		this.connect(this.closeButtonNode, "onclick", "hide");
+		this._makeAnims();
+		this._vp = dojo.window.getBox();
+		return this;
+	},
+
+	show: function(/* Object */groupData){
+		// summary: Show the Master Dialog. Starts the chain of events to show
+		//		an image in the dialog, including showing the dialog if it is
+		//		not already visible
+		//
+		// groupData: Object
+		//		needs href and title attributes. the values for this image.
+		//
+		//
+		var _t = this; // size
+		this._lastGroup = groupData;
+		
+		// we only need to call dijit.Dialog.show() if we're not already open.
+		if(!_t.open){ 
+			_t.inherited(arguments); 
+			_t._modalconnects.push(
+				dojo.connect(dojo.global, "onscroll", this, "_position"),
+				dojo.connect(dojo.global, "onresize", this, "_position"),
+				dojo.connect(dojo.body(), "onkeypress", this, "_handleKey")
+			);
+			if(!groupData.modal){
+				_t._modalconnects.push(
+					dojo.connect(dijit._underlay.domNode, "onclick", this, "onCancel")
+				);
+			}
+		}
+		
+		if(this._wasStyled){
+			// ugly fix for IE being stupid. place the new image relative to the old
+			// image to allow for overriden templates to adjust the location of the
+			// titlebar. DOM will remain "unchanged" between views.
+			var tmpImg = dojo.create("img", null, _t.imgNode, "after");
+			dojo.destroy(_t.imgNode);
+			_t.imgNode = tmpImg;
+			_t._makeAnims();
+			_t._wasStyled = false;
+		}
+		
+		dojo.style(_t.imgNode,"opacity","0"); 
+		dojo.style(_t.titleNode,"opacity","0");
+		
+		var src = groupData.href;
+		
+		if((groupData.group && groupData !== "XnoGroupX") || _t.inGroup){ 
+			if(!_t.inGroup){ 
+				_t.inGroup = _t._groups[(groupData.group)];
+				// determine where we were or are in the show 
+				dojo.forEach(_t.inGroup, function(g, i){
+					if(g.href == groupData.href){
+						_t._index = i;
+						//return false;
+					}
+					//return true;
+				});
+			}
+			if(!_t._index){
+				_t._index = 0;
+				var sr = _t.inGroup[_t._index]; 
+				src = (sr && sr.href) || _t.errorImg;
+			}
+			// FIXME: implement titleTemplate
+			_t.groupCount.innerHTML = " (" + (_t._index + 1) + " of " + Math.max(1, _t.inGroup.length) + ")";
+			_t.prevButtonNode.style.visibility = "visible";
+			_t.nextButtonNode.style.visibility = "visible";
+		}else{
+			// single images don't have buttons, or counters:
+			_t.groupCount.innerHTML = "";
+			_t.prevButtonNode.style.visibility = "hidden";
+			_t.nextButtonNode.style.visibility = "hidden";
+		}
+		if(!groupData.leaveTitle){
+			_t.textNode.innerHTML = groupData.title;
+		}
+		_t._ready(src);
+	},
+	
+	_ready: function(src){	
+		// summary: A function to trigger all 'real' showing of some src
+		
+		var _t = this;
+		
+		// listen for 404's:
+		_t._imgError = dojo.connect(_t.imgNode, "error", _t, function(){
+			dojo.disconnect(_t._imgError);
+			// trigger the above onload with a new src:
+			_t.imgNode.src = _t.errorImg;
+			_t.textNode.innerHTML = _t.errorMessage;
+		});
+		
+		// connect to the onload of the image
+		_t._imgConnect = dojo.connect(_t.imgNode, "load", _t, function(e){
+			_t.resizeTo({
+				w: _t.imgNode.width,
+				h: _t.imgNode.height,
+				duration:_t.duration
+			});
+			// cleanup
+			dojo.disconnect(_t._imgConnect);
+			if(_t._imgError){ 
+				dojo.disconnect(_t._imgError); 
+			}
+		});
+		
+		_t.imgNode.src = src;
+	},
+
+	_nextImage: function(){
+		// summary: Load next image in group
+		if(!this.inGroup){ return; }
+		if(this._index + 1 < this.inGroup.length){
+			this._index++;
+		}else{
+			this._index = 0;
+		}
+		this._loadImage();
+	},
+
+	_prevImage: function(){
+		// summary: Load previous image in group
+		if(this.inGroup){ 
+			if(this._index == 0){
+				this._index = this.inGroup.length - 1;
+			}else{
+				this._index--;
+			}
+			this._loadImage();
+		}
+	},
+
+	_loadImage: function(){
+		// summary: Do the prep work before we can show another image 
+		this._loadingAnim.play(1);
+	},
+
+	_prepNodes: function(){
+		// summary: A localized hook to accompany _loadImage
+		this._imageReady = false; 
+		if(this.inGroup && this.inGroup[this._index]){
+			this.show({
+				href: this.inGroup[this._index].href,
+				title: this.inGroup[this._index].title
+			}); 
+		}else{
+			this.show({
+				title: this.errorMessage,
+				href: this.errorImg
+			});
+		}
+		
+	},
+
+	resizeTo: function(/* Object */size, forceTitle){
+		// summary: Resize our dialog container, and fire _showImage
+		
+		var adjustSize = dojo.boxModel == "border-box" ? 
+			dojo._getBorderExtents(this.domNode).w : 0,
+			titleSize = forceTitle || { h:30 }
+		;
+		
+		this._lastTitleSize = titleSize;
+		
+		if(this.adjust && 
+			(size.h + titleSize.h + adjustSize + 80 > this._vp.h ||
+			 size.w + adjustSize + 60 > this._vp.w
+			)
+		){
+			this._lastSize = size;
+			size = this._scaleToFit(size);
+		}
+		this._currentSize = size;
+		
+		var _sizeAnim = dojox.fx.sizeTo({ 
+			node: this.containerNode,
+			duration: size.duration||this.duration,
+			width: size.w + adjustSize,
+			height: size.h + titleSize.h + adjustSize
+		});
+		this.connect(_sizeAnim, "onEnd", "_showImage");
+		_sizeAnim.play(15);
+	},
+
+	_scaleToFit: function(/* Object */size){
+		// summary: resize an image to fit within the bounds of the viewport
+		// size: Object
+		//		The 'size' object passed around for this image
+		var ns = {};
+
+		// one of the dimensions is too big, go with the smaller viewport edge:
+		if(this._vp.h > this._vp.w){
+			// don't actually touch the edges:
+			ns.w = this._vp.w - 80;
+			ns.h = ns.w * (size.h / size.w);
+		}else{
+			// give a little room for the titlenode, too:
+			ns.h = this._vp.h - 60 - this._lastTitleSize.h;
+			ns.w = ns.h * (size.w / size.h);
+		}
+
+		// we actually have to style this image, it's too big
+		this._wasStyled = true;
+		this._setImageSize(ns);
+
+		ns.duration = size.duration;
+		return ns; // Object
+	},
+	
+	_setImageSize: function(size){
+		// summary: Reset the image size to some actual size.
+		var s = this.imgNode;
+		s.height = size.h;
+		s.width = size.w;
+	},
+
+	// clobber inherited function, it is useless.
+	_size: function(){},
+	
+	_position: function(/* Event */e){
+		// summary: we want to know the viewport size any time it changes
+		this._vp = dojo.window.getBox();
+		this.inherited(arguments);
+		
+		// determine if we need to scale up or down, if at all.
+		if(e && e.type == "resize"){
+			if(this._wasStyled){
+				this._setImageSize(this._lastSize);
+				this.resizeTo(this._lastSize);
+			}else{
+				if(this.imgNode.height + 80 > this._vp.h || this.imgNode.width + 60 > this._vp.h){
+					this.resizeTo({
+						w: this.imgNode.width, h: this.imgNode.height
+					});
+				}
+			}
+		}
+	},
+
+	_showImage: function(){
+		// summary: Fade in the image, and fire showNav
+		this._showImageAnim.play(1);
+	},
+
+	_showNav: function(){
+		// summary: Fade in the footer, and setup our connections.
+		var titleSizeNow = dojo.marginBox(this.titleNode);
+		if(titleSizeNow.h > this._lastTitleSize.h){
+			this.resizeTo(this._wasStyled ? this._lastSize : this._currentSize, titleSizeNow);
+		}else{
+			this._showNavAnim.play(1);
+		}
+	},
+
+	hide: function(){
+		// summary: Hide the Master Lightbox
+		dojo.fadeOut({
+			node: this.titleNode, 
+			duration: 200,
+			// #5112 - if you _don't_ change the .src, safari will 
+			// _never_ fire onload for this image
+			onEnd: dojo.hitch(this, function(){
+				this.imgNode.src = this._blankGif;
+			})
+		}).play(5);
+
+		this.inherited(arguments);
+
+		this.inGroup = null;
+		this._index = null;
+	},
+
+	addImage: function(child, group){
+		// summary: Add an image to this Master Lightbox
+		//
+		// child: Object
+		//		The image information to add.
+		//		href: String - link to image (required)
+		//		title: String - title to display
+		//
+		// group: String?
+		//		attach to group of similar tag or null for individual image instance
+		var g = group;
+		if(!child.href){ return; }
+		if(g){	
+			if(!this._groups[g]){
+				this._groups[g] = [];
+			}
+			this._groups[g].push(child); 
+		}else{ this._groups["XnoGroupX"].push(child); }
+	},
+
+	removeImage: function(/* Widget */child){
+		// summary: Remove an image instance from this LightboxDialog.
+		// child: Object
+		//		A reference to the Lightbox child that was added (or an object literal)
+		//		only the .href member is compared for uniqueness. The object may contain
+		//		a .group member as well.
+		
+		var g = child.group || "XnoGroupX";
+		dojo.every(this._groups[g], function(item, i, ar){
+			if(item.href == child.href){
+				ar.splice(i, 1);
+				return false;
+			}
+			return true;
+		});
+	},
+	
+	removeGroup: function(group){
+		// summary: Remove all images in a passed group
+		if(this._groups[group]){ this._groups[group] = []; }
+	},
+
+	_handleKey: function(/* Event */e){
+		// summary: Handle keyboard navigation internally
+		if(!this.open){ return; }
+
+		var dk = dojo.keys;
+		switch(e.charOrCode){
+			
+			case dk.ESCAPE: 
+				this.hide(); 
+				break;
+
+			case dk.DOWN_ARROW:
+			case dk.RIGHT_ARROW:
+			case 78: // key "n"
+				this._nextImage();
+				break;
+
+			case dk.UP_ARROW:
+			case dk.LEFT_ARROW:
+			case 80: // key "p" 
+				this._prevImage();
+				break;
+		}
+	},
+		
+	_makeAnims: function(){
+		// summary: make and cleanup animation and animation connections
+		
+		dojo.forEach(this._animConnects, dojo.disconnect);
+		this._animConnects = [];
+		this._showImageAnim = dojo.fadeIn({
+				node: this.imgNode,
+				duration: this.duration
+			});
+		this._animConnects.push(dojo.connect(this._showImageAnim, "onEnd", this, "_showNav"));
+		this._loadingAnim = dojo.fx.combine([
+				dojo.fadeOut({ node:this.imgNode, duration:175 }),
+				dojo.fadeOut({ node:this.titleNode, duration:175 })
+			]);
+		this._animConnects.push(dojo.connect(this._loadingAnim, "onEnd", this, "_prepNodes"));
+		this._showNavAnim = dojo.fadeIn({ node: this.titleNode, duration:225 });
+	},
+	
+	onClick: function(groupData){
+		// summary: a stub function, called with the currently displayed image as the only argument
+	},
+	_onImageClick: function(e){
+		if(e && e.target == this.imgNode){
+			this.onClick(this._lastGroup);
+			// also fire the onclick for the Lightbox widget which triggered, if you
+			// aren't working directly with the LBDialog
+			if(this._lastGroup.declaredClass){
+				this._lastGroup.onClick(this._lastGroup);
+			}
+		}
+	}
 });
-_6.imgNode.src=_5;
-},_nextImage:function(){
-if(!this.inGroup){
-return;
-}
-if(this._index+1<this.inGroup.length){
-this._index++;
-}else{
-this._index=0;
-}
-this._loadImage();
-},_prevImage:function(){
-if(this.inGroup){
-if(this._index==0){
-this._index=this.inGroup.length-1;
-}else{
-this._index--;
-}
-this._loadImage();
-}
-},_loadImage:function(){
-this._loadingAnim.play(1);
-},_prepNodes:function(){
-this._imageReady=false;
-this.show({href:this.inGroup[this._index].href,title:this.inGroup[this._index].title});
-},resizeTo:function(_7,_8){
-var _9=dojo.boxModel=="border-box"?dojo._getBorderExtents(this.domNode).w:0,_a=_8||{h:30};
-this._lastTitleSize=_a;
-if(this.adjust&&(_7.h+_a.h+_9+80>this._vp.h||_7.w+_9+60>this._vp.w)){
-this._lastSize=_7;
-_7=this._scaleToFit(_7);
-}
-this._currentSize=_7;
-var _b=dojox.fx.sizeTo({node:this.containerNode,duration:_7.duration||this.duration,width:_7.w+_9,height:_7.h+_a.h+_9});
-this.connect(_b,"onEnd","_showImage");
-_b.play(15);
-},_scaleToFit:function(_c){
-var ns={};
-if(this._vp.h>this._vp.w){
-ns.w=this._vp.w-80;
-ns.h=ns.w*(_c.h/_c.w);
-}else{
-ns.h=this._vp.h-60-this._lastTitleSize.h;
-ns.w=ns.h*(_c.w/_c.h);
-}
-this._wasStyled=true;
-this._setImageSize(ns);
-ns.duration=_c.duration;
-return ns;
-},_setImageSize:function(_d){
-var s=this.imgNode;
-s.height=_d.h;
-s.width=_d.w;
-},_size:function(){
-},_position:function(e){
-this._vp=dijit.getViewport();
-this.inherited(arguments);
-if(e&&e.type=="resize"){
-if(this._wasStyled){
-this._setImageSize(this._lastSize);
-this.resizeTo(this._lastSize);
-}else{
-if(this.imgNode.height+80>this._vp.h||this.imgNode.width+60>this._vp.h){
-this.resizeTo({w:this.imgNode.width,h:this.imgNode.height});
-}
-}
-}
-},_showImage:function(){
-this._showImageAnim.play(1);
-},_showNav:function(){
-var _e=dojo.marginBox(this.titleNode);
-if(_e.h>this._lastTitleSize.h){
-this.resizeTo(this._wasStyled?this._lastSize:this._currentSize,_e);
-}else{
-this._showNavAnim.play(1);
-}
-},hide:function(){
-dojo.fadeOut({node:this.titleNode,duration:200,onEnd:dojo.hitch(this,function(){
-this.imgNode.src=this._blankGif;
-})}).play(5);
-this.inherited(arguments);
-this.inGroup=null;
-this._index=null;
-},addImage:function(_f,_10){
-var g=_10;
-if(!_f.href){
-return;
-}
-if(g){
-if(!this._groups[g]){
-this._groups[g]=[];
-}
-this._groups[g].push(_f);
-}else{
-this._groups["XnoGroupX"].push(_f);
-}
-},_handleKey:function(e){
-if(!this.open){
-return;
-}
-var dk=dojo.keys;
-switch(e.charOrCode){
-case dk.ESCAPE:
-this.hide();
-break;
-case dk.DOWN_ARROW:
-case dk.RIGHT_ARROW:
-case 78:
-this._nextImage();
-break;
-case dk.UP_ARROW:
-case dk.LEFT_ARROW:
-case 80:
-this._prevImage();
-break;
-}
-},_makeAnims:function(){
-dojo.forEach(this._animConnects,dojo.disconnect);
-this._animConnects=[];
-this._showImageAnim=dojo.fadeIn({node:this.imgNode,duration:this.duration});
-this._animConnects.push(dojo.connect(this._showImageAnim,"onEnd",this,"_showNav"));
-this._loadingAnim=dojo.fx.combine([dojo.fadeOut({node:this.imgNode,duration:175}),dojo.fadeOut({node:this.titleNode,duration:175})]);
-this._animConnects.push(dojo.connect(this._loadingAnim,"onEnd",this,"_prepNodes"));
-this._showNavAnim=dojo.fadeIn({node:this.titleNode,duration:225});
-},onClick:function(_11){
-},_onImageClick:function(e){
-if(e&&e.target==this.imgNode){
-this.onClick(this._lastGroup);
-if(this._lastGroup.declaredClass){
-this._lastGroup.onClick(this._lastGroup);
-}
-}
-}});
-}
diff --git a/dojox/image/LightboxNano.js b/dojox/image/LightboxNano.js
index 67b14ac..14b28a7 100644
--- a/dojox/image/LightboxNano.js
+++ b/dojox/image/LightboxNano.js
@@ -1,122 +1,313 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.image.LightboxNano"]){
-dojo._hasResource["dojox.image.LightboxNano"]=true;
 dojo.provide("dojox.image.LightboxNano");
 dojo.require("dojo.fx");
+
 (function(d){
-var _1="absolute",_2="visibility",_3=function(){
-var _4=(d.doc.compatMode=="BackCompat")?d.body():d.doc.documentElement,_5=dojo._docScroll();
-return {w:_4.clientWidth,h:_4.clientHeight,l:_5.x,t:_5.y};
-};
-d.declare("dojox.image.LightboxNano",null,{href:"",duration:500,preloadDelay:5000,constructor:function(p,n){
-var _6=this;
-d.mixin(_6,p);
-n=_6._node=dojo.byId(n);
-if(n){
-if(!/a/i.test(n.tagName)){
-var a=d.create("a",{href:_6.href,"class":n.className},n,"after");
-n.className="";
-a.appendChild(n);
-n=a;
-}
-d.style(n,"position","relative");
-_6._createDiv("dojoxEnlarge",n);
-d.setSelectable(n,false);
-_6._onClickEvt=d.connect(n,"onclick",_6,"_load");
-}
-if(_6.href){
-setTimeout(function(){
-(new Image()).src=_6.href;
-_6._hideLoading();
-},_6.preloadDelay);
-}
-},destroy:function(){
-var a=this._connects||[];
-a.push(this._onClickEvt);
-d.forEach(a,d.disconnect);
-d.destroy(this._node);
-},_createDiv:function(_7,_8,_9){
-return d.create("div",{"class":_7,style:{position:_1,display:_9?"":"none"}},_8);
-},_load:function(e){
-var _a=this;
-e&&d.stopEvent(e);
-if(!_a._loading){
-_a._loading=true;
-_a._reset();
-var i=_a._img=d.create("img",{style:{visibility:"hidden",cursor:"pointer",position:_1,top:0,left:0,zIndex:9999999}},d.body()),ln=_a._loadingNode,n=d.query("img",_a._node)[0]||_a._node,a=d.position(n,true),c=d.contentBox(n),b=d._getBorderExtents(n);
-if(ln==null){
-_a._loadingNode=ln=_a._createDiv("dojoxLoading",_a._node,true);
-var l=d.marginBox(ln);
-d.style(ln,{left:parseInt((c.w-l.w)/2)+"px",top:parseInt((c.h-l.h)/2)+"px"});
-}
-c.x=a.x-10+b.l;
-c.y=a.y-10+b.t;
-_a._start=c;
-_a._connects=[d.connect(i,"onload",_a,"_show")];
-i.src=_a.href;
-}
-},_hideLoading:function(){
-if(this._loadingNode){
-d.style(this._loadingNode,"display","none");
-}
-this._loadingNode=false;
-},_show:function(){
-var _b=this,vp=_3(),w=_b._img.width,h=_b._img.height,_c=parseInt((vp.w-20)*0.9),_d=parseInt((vp.h-20)*0.9),dd=d.doc,bg=_b._bg=d.create("div",{style:{backgroundColor:"#000",opacity:0,position:_1,zIndex:9999998}},d.body()),ln=_b._loadingNode;
-if(_b._loadingNode){
-_b._hideLoading();
-}
-d.style(_b._img,{border:"10px solid #fff",visibility:"visible"});
-d.style(_b._node,_2,"hidden");
-_b._loading=false;
-_b._connects=_b._connects.concat([d.connect(dd,"onmousedown",_b,"_hide"),d.connect(dd,"onkeypress",_b,"_key"),d.connect(window,"onresize",_b,"_sizeBg")]);
-if(w>_c){
-h=h*_c/w;
-w=_c;
-}
-if(h>_d){
-w=w*_d/h;
-h=_d;
-}
-_b._end={x:(vp.w-20-w)/2+vp.l,y:(vp.h-20-h)/2+vp.t,w:w,h:h};
-_b._sizeBg();
-d.fx.combine([_b._anim(_b._img,_b._coords(_b._start,_b._end)),_b._anim(bg,{opacity:0.5})]).play();
-},_sizeBg:function(){
-var dd=d.doc.documentElement;
-d.style(this._bg,{top:0,left:0,width:dd.scrollWidth+"px",height:dd.scrollHeight+"px"});
-},_key:function(e){
-d.stopEvent(e);
-this._hide();
-},_coords:function(s,e){
-return {left:{start:s.x,end:e.x},top:{start:s.y,end:e.y},width:{start:s.w,end:e.w},height:{start:s.h,end:e.h}};
-},_hide:function(){
-var _e=this;
-d.forEach(_e._connects,d.disconnect);
-_e._connects=[];
-d.fx.combine([_e._anim(_e._img,_e._coords(_e._end,_e._start),"_reset"),_e._anim(_e._bg,{opacity:0})]).play();
-},_reset:function(){
-d.style(this._node,_2,"visible");
-d.forEach([this._img,this._bg],function(n){
-d.destroy(n);
-n=null;
-});
-this._node.focus();
-},_anim:function(_f,_10,_11){
-return d.animateProperty({node:_f,duration:this.duration,properties:_10,onEnd:_11?d.hitch(this,_11):null});
-},show:function(_12){
-_12=_12||{};
-this.href=_12.href||this.href;
-var n=d.byId(_12.origin),vp=_3();
-this._node=n||d.create("div",{style:{position:_1,width:0,hieght:0,left:(vp.l+(vp.w/2))+"px",top:(vp.t+(vp.h/2))+"px"}},d.body());
-this._load();
-if(!n){
-d.destroy(this._node);
-}
-}});
+
+	var abs = "absolute",
+		vis = "visibility",
+		getViewport = function(){
+			//	summary: Returns the dimensions and scroll position of the viewable area of a browser window
+			var scrollRoot = (d.doc.compatMode == "BackCompat") ? d.body() : d.doc.documentElement,
+				scroll = dojo._docScroll();
+				return { w: scrollRoot.clientWidth, h: scrollRoot.clientHeight, l: scroll.x, t: scroll.y };
+			}
+	;
+
+	d.declare("dojox.image.LightboxNano", null, {
+		//	summary:
+		//		A simple "nano" version of the lightbox. 
+		//
+		//	description:
+		//		Very lightweight lightbox which only displays a larger image.  There is
+		//		no support for a caption or description.  The lightbox can be closed by
+		//		clicking any where or pressing any key.  This widget is intended to be
+		//		used on <a> and <img> tags.  Upon creation, if the domNode is <img> tag,
+		//		then it is wrapped in an <a> tag, then a <div class="enlarge"> is placed
+		//		inside the <a> and can be styled to display an icon that the original
+		//		can be enlarged.
+		//
+		//	example:
+		//	|	<a dojoType="dojox.image.LightboxNano" href="/path/to/largeimage.jpg"><img src="/path/to/thumbnail.jpg"></a>
+		//
+		//	example:
+		//	|	<img dojoType="dojox.image.LightboxNano" src="/path/to/thumbnail.jpg" href="/path/to/largeimage.jpg">
+
+		//	href: string
+		//		URL to the large image to show in the lightbox.
+		href: "",
+
+		//	duration: int
+		//		The delay in milliseconds of the LightboxNano open and close animation.
+		duration: 500,
+
+		//	preloadDelay: int
+		//		The delay in milliseconds after the LightboxNano is created before preloading the larger image.
+		preloadDelay: 5000,
+
+		constructor: function(/*Object?*/p, /*DomNode?*/n){
+			// summary: Initializes the DOM node and connect onload event
+			var _this = this;
+
+			d.mixin(_this, p);
+			n = _this._node = dojo.byId(n);
+
+			// if we have a origin node, then prepare it to show the LightboxNano
+			if(n){
+				if(!/a/i.test(n.tagName)){
+					var a = d.create("a", { href: _this.href, "class": n.className }, n, "after");
+					n.className = "";
+					a.appendChild(n);
+					n = a;
+				}
+
+				d.style(n, "position", "relative");
+				_this._createDiv("dojoxEnlarge", n);
+				d.setSelectable(n, false);
+				_this._onClickEvt = d.connect(n, "onclick", _this, "_load");
+			}
+
+			if(_this.href){
+				setTimeout(function(){
+					(new Image()).src = _this.href;
+					_this._hideLoading();
+				}, _this.preloadDelay);
+			}
+		},
+
+		destroy: function(){
+			// summary: Destroys the LightboxNano and it's DOM node
+			var a = this._connects || [];
+			a.push(this._onClickEvt);
+			d.forEach(a, d.disconnect);
+			d.destroy(this._node);
+		},
+
+		_createDiv: function(/*String*/cssClass, /*DomNode*/refNode, /*boolean*/display){
+			// summary: Creates a div for the enlarge icon and loading indicator layers
+			return d.create("div", { // DomNode
+				"class": cssClass, 
+				style: { 
+					position: abs, 
+					display: display ? "" : "none" 
+				} 
+			}, refNode); 
+		},
+	
+		_load: function(/*Event*/e){
+			// summary: Creates the large image and begins to show it
+			var _this = this;
+
+			e && d.stopEvent(e);
+
+			if(!_this._loading){
+				_this._loading = true;
+				_this._reset();
+
+				var i = _this._img = d.create("img", {
+						style: {
+							visibility: "hidden",
+							cursor: "pointer",
+							position: abs,
+							top: 0,
+							left: 0,
+							zIndex: 9999999
+						}
+					}, d.body()),
+					ln = _this._loadingNode,
+					n = d.query("img", _this._node)[0] || _this._node,
+					a = d.position(n, true),
+					c = d.contentBox(n),
+					b = d._getBorderExtents(n)
+				;
+
+				if(ln == null){
+					_this._loadingNode = ln = _this._createDiv("dojoxLoading", _this._node, true);
+					var l = d.marginBox(ln);
+					d.style(ln, {
+						left: parseInt((c.w - l.w) / 2) + "px",
+						top: parseInt((c.h - l.h) / 2) + "px"
+					});
+				}
+
+				c.x = a.x - 10 + b.l;
+				c.y = a.y - 10 + b.t;
+				_this._start = c;
+
+				_this._connects = [d.connect(i, "onload", _this, "_show")];
+
+				i.src = _this.href;
+			}
+		},
+
+		_hideLoading: function(){
+			// summary: Hides the animated loading indicator
+			if(this._loadingNode){
+				d.style(this._loadingNode, "display", "none");
+			}
+			this._loadingNode = false;
+		},
+
+		_show: function(){
+			// summary: The image is now loaded, calculate size and display
+			var _this = this,
+				vp = getViewport(),
+				w = _this._img.width,
+				h = _this._img.height,
+				vpw = parseInt((vp.w - 20) * 0.9),
+				vph = parseInt((vp.h - 20) * 0.9),
+				dd = d.doc,
+				bg = _this._bg = d.create("div", {
+					style: {
+						backgroundColor: "#000",
+						opacity: 0.0,
+						position: abs,
+						zIndex: 9999998
+					}
+				}, d.body()),
+				ln = _this._loadingNode
+			;
+
+			if(_this._loadingNode){
+				_this._hideLoading();
+			}
+			d.style(_this._img, {
+				border: "10px solid #fff",
+				visibility: "visible"
+			});
+			d.style(_this._node, vis, "hidden");
+
+			_this._loading = false;
+
+			_this._connects = _this._connects.concat([
+				d.connect(dd, "onmousedown", _this, "_hide"),
+				d.connect(dd, "onkeypress", _this, "_key"),
+				d.connect(window, "onresize", _this, "_sizeBg")
+			]);
+
+			if(w > vpw){
+				h = h * vpw / w;
+				w = vpw;
+			}
+			if(h > vph){
+				w = w * vph / h;
+				h = vph;
+			}
+
+			_this._end = {
+				x: (vp.w - 20 - w) / 2 + vp.l,
+				y: (vp.h - 20 - h) / 2 + vp.t,
+				w: w,
+				h: h
+			};
+
+			_this._sizeBg();
+
+			d.fx.combine([
+				_this._anim(_this._img, _this._coords(_this._start, _this._end)),
+				_this._anim(bg, { opacity: 0.5 })
+			]).play();
+		},
+
+		_sizeBg: function(){
+			// summary: Resize the background to fill the page
+			var dd = d.doc.documentElement;
+			d.style(this._bg, {
+				top: 0,
+				left: 0,
+				width: dd.scrollWidth + "px",
+				height: dd.scrollHeight + "px"
+			});
+		},
+
+		_key: function(/*Event*/e){
+			// summary: A key was pressed, so hide the lightbox
+			d.stopEvent(e);
+			this._hide();
+		},
+
+		_coords: function(/*Object*/s, /*Object*/e){
+			// summary: Returns animation parameters with the start and end coords
+			return { // Object
+				left:	{ start: s.x, end: e.x },
+				top:	{ start: s.y, end: e.y },
+				width:	{ start: s.w, end: e.w },
+				height:	{ start: s.h, end: e.h }
+			}; 
+		},
+
+		_hide: function(){
+			// summary: Closes the lightbox
+			var _this = this;
+			d.forEach(_this._connects, d.disconnect);
+			_this._connects = [];
+			d.fx.combine([
+				_this._anim(_this._img, _this._coords(_this._end, _this._start), "_reset"),
+				_this._anim(_this._bg, {opacity:0})
+			]).play();
+		},
+
+		_reset: function(){
+			// summary: Destroys the lightbox
+			d.style(this._node, vis, "visible");
+			d.forEach([this._img, this._bg], function(n){
+				d.destroy(n);
+				n = null;
+			});
+			this._node.focus();
+		},
+
+		_anim: function(/*DomNode*/node, /*Object*/args, /*Function*/onEnd){
+			// summary: Creates the lightbox open/close and background fadein/out animations
+			return d.animateProperty({ // dojo.Animation
+				node: node,
+				duration: this.duration,
+				properties: args,
+				onEnd: onEnd ? d.hitch(this, onEnd) : null
+			}); 
+		},
+		
+		show: function(/*Object?*/args){
+			// summary: 
+			//		Shows this LightboxNano programatically. Allows passing a new href and 
+			//		a programatic origin.
+			//
+			// args: Object?
+			//		An object with optional members of `href` and `origin`.
+			//		`origin` can be be a String|Id of a DomNode to use when 
+			//		animating the openeing of the image (the 'box' effect starts
+			//		from this origin point. eg: { origin: e.target })
+			//		If there's no origin, it will use the center of the viewport.
+			//		The `href` member is a string URL for the image to be 
+			//		displayed. Omiting either of these members will revert to
+			//		the default href (which could be absent in some cases) and
+			//		the original srcNodeRef for the widget.
+			args = args || {}; 
+			this.href = args.href || this.href;
+
+			var n = d.byId(args.origin),
+				vp = getViewport();
+
+			// if we don't have a valid origin node, then create one as a reference
+			// that is centered in the viewport
+			this._node = n || d.create("div", {
+					style: {
+						position: abs,
+						width: 0,
+						hieght: 0,
+						left: (vp.l + (vp.w / 2)) + "px",
+						top: (vp.t + (vp.h / 2)) + "px"
+					}
+				}, d.body())
+			;
+
+			this._load();
+
+			// if we don't have a valid origin node, then destroy the centered reference
+			// node since load() has already been called and it's not needed anymore.
+			if(!n){
+				d.destroy(this._node);
+			}
+		}
+	});
+
 })(dojo);
-}
diff --git a/dojox/image/Magnifier.js b/dojox/image/Magnifier.js
index d4d8e9e..a3d2839 100644
--- a/dojox/image/Magnifier.js
+++ b/dojox/image/Magnifier.js
@@ -1,29 +1,73 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.image.Magnifier"]){
-dojo._hasResource["dojox.image.Magnifier"]=true;
 dojo.provide("dojox.image.Magnifier");
+
 dojo.require("dojox.gfx");
 dojo.require("dojox.image.MagnifierLite");
-dojo.declare("dojox.image.Magnifier",dojox.image.MagnifierLite,{_createGlass:function(){
-this.glassNode=dojo.create("div",{style:{height:this.glassSize+"px",width:this.glassSize+"px"},"className":"glassNode"},dojo.body());
-this.surfaceNode=dojo.create("div",null,this.glassNode);
-this.surface=dojox.gfx.createSurface(this.surfaceNode,this.glassSize,this.glassSize);
-this.img=this.surface.createImage({src:this.domNode.src,width:this._zoomSize.w,height:this._zoomSize.h});
-},_placeGlass:function(e){
-var x=e.pageX-2,y=e.pageY-2,_1=this.offset.x+this.offset.w+2,_2=this.offset.y+this.offset.h+2;
-if(x<this.offset.x||y<this.offset.y||x>_1||y>_2){
-this._hideGlass();
-}else{
-this.inherited(arguments);
-}
-},_setImage:function(e){
-var _3=(e.pageX-this.offset.l)/this.offset.w,_4=(e.pageY-this.offset.t)/this.offset.h,x=(this._zoomSize.w*_3*-1)+(this.glassSize*_3),y=(this._zoomSize.h*_4*-1)+(this.glassSize*_4);
-this.img.setShape({x:x,y:y});
-}});
-}
+
+dojo.declare("dojox.image.Magnifier",
+	dojox.image.MagnifierLite,{
+	// summary:
+	//		Adds magnification on a portion of an image element, using `dojox.gfx`
+	//
+	// description:
+	//		An unobtrusive way to add an unstyled overlay
+	// 		above the srcNode image element. The overlay/glass is a 
+	//		scaled version of the src image (so larger images sized down
+	//		are clearer).
+	//
+	//		over-ride the _createGlass method to create your custom surface,
+	//		being sure to create an img node on that surface.
+
+	_createGlass: function(){
+		// summary: create the glassNode, and an img on a dojox.gfx surface
+
+		// images are hard to make into workable templates, so just add outer overlay
+		// and skip using dijit._Templated
+		this.glassNode = dojo.create('div', {
+			style:{
+				height: this.glassSize + "px",
+				width: this.glassSize + "px"
+			},
+			"className":"glassNode"
+		}, dojo.body());
+		this.surfaceNode = dojo.create('div', null, this.glassNode);
+
+		this.surface = dojox.gfx.createSurface(this.surfaceNode, this.glassSize, this.glassSize);
+		this.img = this.surface.createImage({
+		   src: this.domNode.src,
+		   width: this._zoomSize.w,
+		   height: this._zoomSize.h
+		});
+
+	},
+
+	_placeGlass: function(e){
+		// summary: position the overlay centered under the cursor
+		var x = e.pageX - 2,
+			y = e.pageY - 2,
+			xMax = this.offset.x + this.offset.w + 2,
+			yMax = this.offset.y + this.offset.h + 2
+		;
+		
+		// with svg, our mouseout connection to the image surface doesn't
+		// fire, so we'r have to manually calculate offsets	
+		if(x < this.offset.x || y < this.offset.y || x > xMax || y > yMax){
+			this._hideGlass();
+		}else{
+			this.inherited(arguments);
+		}
+	},
+
+	_setImage: function(e){
+		// summary: set the image's offset in the clipping window relative to the mouse position
+
+		var xOff = (e.pageX - this.offset.l) / this.offset.w,
+			yOff = (e.pageY - this.offset.t) / this.offset.h,
+			x = (this._zoomSize.w * xOff * -1)+(this.glassSize*xOff),
+			y = (this._zoomSize.h * yOff * -1)+(this.glassSize*yOff)
+		;
+		// set the image offset
+		this.img.setShape({ x: x, y: y });	
+
+	}
+
+});
\ No newline at end of file
diff --git a/dojox/image/MagnifierLite.js b/dojox/image/MagnifierLite.js
index e866a87..1de42de 100644
--- a/dojox/image/MagnifierLite.js
+++ b/dojox/image/MagnifierLite.js
@@ -1,46 +1,130 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.image.MagnifierLite"]){
-dojo._hasResource["dojox.image.MagnifierLite"]=true;
 dojo.provide("dojox.image.MagnifierLite");
 dojo.experimental("dojox.image.MagnifierLite");
+
 dojo.require("dijit._Widget");
-dojo.declare("dojox.image.MagnifierLite",dijit._Widget,{glassSize:125,scale:6,postCreate:function(){
-this.inherited(arguments);
-this._adjustScale();
-this._createGlass();
-this.connect(this.domNode,"onmouseenter","_showGlass");
-this.connect(this.glassNode,"onmousemove","_placeGlass");
-this.connect(this.img,"onmouseout","_hideGlass");
-this.connect(window,"onresize","_adjustScale");
-},_createGlass:function(){
-var _1=this.glassNode=dojo.create("div",{style:{height:this.glassSize+"px",width:this.glassSize+"px"},className:"glassNode"},dojo.body());
-this.surfaceNode=_1.appendChild(dojo.create("div"));
-this.img=dojo.place(dojo.clone(this.domNode),_1);
-dojo.style(this.img,{position:"relative",top:0,left:0,width:this._zoomSize.w+"px",height:this._zoomSize.h+"px"});
-},_adjustScale:function(){
-this.offset=dojo.coords(this.domNode,true);
-this._imageSize={w:this.offset.w,h:this.offset.h};
-this._zoomSize={w:this._imageSize.w*this.scale,h:this._imageSize.h*this.scale};
-},_showGlass:function(e){
-this._placeGlass(e);
-dojo.style(this.glassNode,{visibility:"visible",display:""});
-},_hideGlass:function(e){
-dojo.style(this.glassNode,{visibility:"hidden",display:"none"});
-},_placeGlass:function(e){
-this._setImage(e);
-var _2=Math.floor(this.glassSize/2);
-dojo.style(this.glassNode,{top:Math.floor(e.pageY-_2)+"px",left:Math.floor(e.pageX-_2)+"px"});
-},_setImage:function(e){
-var _3=(e.pageX-this.offset.l)/this.offset.w,_4=(e.pageY-this.offset.t)/this.offset.h,x=(this._zoomSize.w*_3*-1)+(this.glassSize*_3),y=(this._zoomSize.h*_4*-1)+(this.glassSize*_4);
-dojo.style(this.img,{top:y+"px",left:x+"px"});
-},destroy:function(_5){
-dojo.destroy(this.glassNode);
-this.inherited(arguments);
-}});
-}
+
+dojo.declare("dojox.image.MagnifierLite", dijit._Widget,
+	{
+	// summary:	Adds magnification on a portion of an image element
+	//
+	// description: An unobtrusive way to add an unstyled overlay
+	// 		above the srcNode image element. The overlay/glass is a 
+	//		scaled version of the src image (so larger images sized down
+	//		are clearer).
+	//
+	//		The logic behind requiring the src image to be large is
+	//		"it's going to be downloaded, anyway" so this method avoids
+	//		having to make thumbnails and 2 http requests among other things.
+	//
+	// glassSize: Int
+	// 		the width and height of the bounding box
+	glassSize: 125,
+
+	// scale: Decimal
+	// 		the multiplier of the Mangification. 
+	scale: 6,
+
+	postCreate: function(){
+		this.inherited(arguments);
+		
+		// images are hard to make into workable templates, so just add outer overlay
+		// and skip using dijit._Templated		
+		this._adjustScale();
+		this._createGlass();
+		
+		this.connect(this.domNode,"onmouseenter","_showGlass");
+		this.connect(this.glassNode,"onmousemove","_placeGlass");
+		this.connect(this.img,"onmouseout","_hideGlass");
+
+		// when position of domNode changes, _adjustScale needs to run.
+		// window.resize isn't it always, FIXME:
+		this.connect(window,"onresize","_adjustScale");
+		
+	},
+
+	_createGlass: function(){
+		// summary: make img and glassNode elements as children of the body
+
+		var node = this.glassNode = dojo.create('div', {
+			style:{
+				height: this.glassSize + "px",
+				width: this.glassSize + "px"
+			},
+			className:"glassNode"
+		}, dojo.body());
+		
+		this.surfaceNode = node.appendChild(dojo.create('div'));
+
+		this.img = dojo.place(dojo.clone(this.domNode), node);
+		// float the image around inside the .glassNode 
+		dojo.style(this.img, {
+			position: "relative",
+			top: 0, left: 0,
+			width: this._zoomSize.w + "px",
+			height: this._zoomSize.h + "px"
+		});
+
+	},
+	
+	_adjustScale: function(){
+		// summary: update the calculations should this.scale change
+
+		this.offset = dojo.coords(this.domNode, true);
+		this._imageSize = { w: this.offset.w, h:this.offset.h };
+		this._zoomSize = {
+			w: this._imageSize.w * this.scale,
+			h: this._imageSize.h * this.scale
+		};
+	},
+	
+	_showGlass: function(e){
+		// summary: show the overlay
+		this._placeGlass(e);
+		dojo.style(this.glassNode, {
+			visibility: "visible",
+			display:""
+		});			
+		
+	},
+	
+	_hideGlass: function(e){
+		// summary: hide the overlay
+		dojo.style(this.glassNode, {
+			visibility: "hidden",
+			display:"none"
+		});
+	},
+	
+	_placeGlass: function(e){
+		// summary: position the overlay centered under the cursor
+
+		this._setImage(e);
+		var sub = Math.floor(this.glassSize / 2);
+		dojo.style(this.glassNode,{ 
+			top: Math.floor(e.pageY - sub) + "px", 
+			left:Math.floor(e.pageX - sub) + "px"
+		});
+		
+	},
+
+	_setImage: function(e){
+		// summary: set the image's offset in the clipping window relative to the mouse position
+
+		var xOff = (e.pageX - this.offset.l) / this.offset.w,
+			yOff = (e.pageY - this.offset.t) / this.offset.h,
+			x = (this._zoomSize.w * xOff * -1) + (this.glassSize * xOff),
+			y = (this._zoomSize.h * yOff * -1) + (this.glassSize * yOff);
+
+		dojo.style(this.img, {
+			top: y + "px",
+			left: x + "px"
+		});
+
+	},
+	
+	destroy: function(finalize){
+		dojo.destroy(this.glassNode);
+		this.inherited(arguments);
+	}
+
+});
\ No newline at end of file
diff --git a/dojox/image/SlideShow.js b/dojox/image/SlideShow.js
index b95b23b..cee35b9 100644
--- a/dojox/image/SlideShow.js
+++ b/dojox/image/SlideShow.js
@@ -1,367 +1,676 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.image.SlideShow"]){
-dojo._hasResource["dojox.image.SlideShow"]=true;
 dojo.provide("dojox.image.SlideShow");
+//
+// dojox.image.SlideShow courtesy Shane O Sullivan, licensed under a Dojo CLA 
+// For a sample usage, see http://www.skynet.ie/~sos/photos.php
+//
+// @author  Copyright 2007 Shane O Sullivan (shaneosullivan1 at gmail.com)
+//
+//	TODO: more cleanups
+//
 dojo.require("dojo.string");
 dojo.require("dojo.fx");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.declare("dojox.image.SlideShow",[dijit._Widget,dijit._Templated],{imageHeight:375,imageWidth:500,title:"",titleTemplate:"${title} <span class=\"slideShowCounterText\">(${current} of ${total})</span>",noLink:false,loop:true,hasNav:true,images:[],pageSize:20,autoLoad:true,autoStart:false,fixedHeight:false,imageStore:null,linkAttr:"link",imageLargeAttr:"imageUrl",titleAttr:"title",slideshowInterval:3,templateString:dojo.cache("dojox.image","resources/SlideShow.html","<div dojoAttachPoi [...]
-this.inherited(arguments);
-var _1=document.createElement("img");
-_1.setAttribute("width",this.imageWidth);
-_1.setAttribute("height",this.imageHeight);
-if(this.hasNav){
-dojo.connect(this.outerNode,"onmouseover",this,function(_2){
-try{
-this._showNav();
-}
-catch(e){
-}
-});
-dojo.connect(this.outerNode,"onmouseout",this,function(_3){
-try{
-this._hideNav(_3);
-}
-catch(e){
-}
-});
-}
-this.outerNode.style.width=this.imageWidth+"px";
-_1.setAttribute("src",this._blankGif);
-var _4=this;
-this.largeNode.appendChild(_1);
-this._tmpImage=this._currentImage=_1;
-this._fitSize(true);
-this._loadImage(0,dojo.hitch(this,"showImage",0));
-this._calcNavDimensions();
-},setDataStore:function(_5,_6,_7){
-this.reset();
-var _8=this;
-this._request={query:{},start:_6.start||0,count:_6.count||this.pageSize,onBegin:function(_9,_a){
-_8.maxPhotos=_9;
-}};
-if(_6.query){
-dojo.mixin(this._request.query,_6.query);
-}
-if(_7){
-dojo.forEach(["imageLargeAttr","linkAttr","titleAttr"],function(_b){
-if(_7[_b]){
-this[_b]=_7[_b];
-}
-},this);
-}
-var _c=function(_d){
-_8.maxPhotos=_d.length;
-_8._request.onComplete=null;
-if(_8.autoStart){
-_8.imageIndex=-1;
-_8.toggleSlideShow();
-}else{
-_8.showImage(0);
-}
-};
-this.imageStore=_5;
-this._request.onComplete=_c;
-this._request.start=0;
-this.imageStore.fetch(this._request);
-},reset:function(){
-dojo.query("> *",this.largeNode).orphan();
-this.largeNode.appendChild(this._tmpImage);
-dojo.query("> *",this.hiddenNode).orphan();
-dojo.forEach(this.images,function(_e){
-if(_e&&_e.parentNode){
-_e.parentNode.removeChild(_e);
-}
-});
-this.images=[];
-this.isInitialized=false;
-this._imageCounter=0;
-},isImageLoaded:function(_f){
-return this.images&&this.images.length>_f&&this.images[_f];
-},moveImageLoadingPointer:function(_10){
-this._imageCounter=_10;
-},destroy:function(){
-if(this._slideId){
-this._stop();
-}
-this.inherited(arguments);
-},showNextImage:function(_11,_12){
-if(_11&&this._timerCancelled){
-return false;
-}
-if(this.imageIndex+1>=this.maxPhotos){
-if(_11&&(this.loop||_12)){
-this.imageIndex=-1;
-}else{
-if(this._slideId){
-this._stop();
-}
-return false;
-}
-}
-this.showImage(this.imageIndex+1,dojo.hitch(this,function(){
-if(_11){
-this._startTimer();
-}
-}));
-return true;
-},toggleSlideShow:function(){
-if(this._slideId){
-this._stop();
-}else{
-dojo.toggleClass(this.domNode,"slideShowPaused");
-this._timerCancelled=false;
-var idx=this.imageIndex;
-if(idx<0||(this.images[idx]&&this.images[idx]._img.complete)){
-var _13=this.showNextImage(true,true);
-if(!_13){
-this._stop();
-}
-}else{
-var _14=dojo.subscribe(this.getShowTopicName(),dojo.hitch(this,function(_15){
-setTimeout(dojo.hitch(this,function(){
-if(_15.index==idx){
-var _16=this.showNextImage(true,true);
-if(!_16){
-this._stop();
-}
-dojo.unsubscribe(_14);
-}
-}),this.slideshowInterval*1000);
-}));
-dojo.publish(this.getShowTopicName(),[{index:idx,title:"",url:""}]);
-}
-}
-},getShowTopicName:function(){
-return (this.widgetId||this.id)+"/imageShow";
-},getLoadTopicName:function(){
-return (this.widgetId?this.widgetId:this.id)+"/imageLoad";
-},showImage:function(_17,_18){
-if(!_18&&this._slideId){
-this.toggleSlideShow();
-}
-var _19=this;
-var _1a=this.largeNode.getElementsByTagName("div");
-this.imageIndex=_17;
-var _1b=function(){
-if(_19.images[_17]){
-while(_19.largeNode.firstChild){
-_19.largeNode.removeChild(_19.largeNode.firstChild);
-}
-dojo.style(_19.images[_17],"opacity",0);
-_19.largeNode.appendChild(_19.images[_17]);
-_19._currentImage=_19.images[_17]._img;
-_19._fitSize();
-var _1c=function(a,b,c){
-var img=_19.images[_17].firstChild;
-if(img.tagName.toLowerCase()!="img"){
-img=img.firstChild;
-}
-var _1d=img.getAttribute("title")||"";
-if(_19._navShowing){
-_19._showNav(true);
-}
-dojo.publish(_19.getShowTopicName(),[{index:_17,title:_1d,url:img.getAttribute("src")}]);
-if(_18){
-_18(a,b,c);
-}
-_19._setTitle(_1d);
-};
-dojo.fadeIn({node:_19.images[_17],duration:300,onEnd:_1c}).play();
-}else{
-_19._loadImage(_17,function(){
-_19.showImage(_17,_18);
-});
-}
-};
-if(_1a&&_1a.length>0){
-dojo.fadeOut({node:_1a[0],duration:300,onEnd:function(){
-_19.hiddenNode.appendChild(_1a[0]);
-_1b();
-}}).play();
-}else{
-_1b();
-}
-},_fitSize:function(_1e){
-if(!this.fixedHeight||_1e){
-var _1f=(this._currentImage.height+(this.hasNav?20:0));
-dojo.style(this.innerWrapper,"height",_1f+"px");
-return;
-}
-dojo.style(this.largeNode,"paddingTop",this._getTopPadding()+"px");
-},_getTopPadding:function(){
-if(!this.fixedHeight){
-return 0;
-}
-return (this.imageHeight-this._currentImage.height)/2;
-},_loadNextImage:function(){
-if(!this.autoLoad){
-return;
-}
-while(this.images.length>=this._imageCounter&&this.images[this._imageCounter]){
-this._imageCounter++;
-}
-this._loadImage(this._imageCounter);
-},_loadImage:function(_20,_21){
-if(this.images[_20]||!this._request){
-return;
-}
-var _22=_20-(_20%(this._request.count||this.pageSize));
-this._request.start=_22;
-this._request.onComplete=function(_23){
-var _24=_20-_22;
-if(_23&&_23.length>_24){
-_25(_23[_24]);
-}else{
-}
-};
-var _26=this;
-var _27=this.imageStore;
-var _25=function(_28){
-var url=_26.imageStore.getValue(_28,_26.imageLargeAttr);
-var img=new Image();
-var div=dojo.create("div",{id:_26.id+"_imageDiv"+_20});
-div._img=img;
-var _29=_26.imageStore.getValue(_28,_26.linkAttr);
-if(!_29||_26.noLink){
-div.appendChild(img);
-}else{
-var a=dojo.create("a",{"href":_29,"target":"_blank"},div);
-a.appendChild(img);
-}
-dojo.connect(img,"onload",function(){
-if(_27!=_26.imageStore){
-return;
-}
-_26._fitImage(img);
-dojo.attr(div,{"width":_26.imageWidth,"height":_26.imageHeight});
-dojo.publish(_26.getLoadTopicName(),[_20]);
-setTimeout(function(){
-_26._loadNextImage();
-},1);
-if(_21){
-_21();
-}
+
+dojo.declare("dojox.image.SlideShow",
+	[dijit._Widget, dijit._Templated],
+	{
+	// summary: 
+	//		A Slideshow Widget
+
+	// imageHeight: Number
+	//		The maximum height of an image
+	imageHeight: 375,
+	
+	// imageWidth: Number
+	//		The maximum width of an image.
+	imageWidth: 500,
+
+	// title: String
+	//		The initial title of the SlideShow 
+	title: "",
+
+	// titleTemplate: String
+	//	a way to customize the wording in the title. supported parameters to be populated are:
+	//		${title} = the passed title of the image
+	//		${current} = the current index of the image
+	//		${total} = the total number of images in the SlideShow
+	//
+	//	should add more?
+	titleTemplate: '${title} <span class="slideShowCounterText">(${current} of ${total})</span>',
+
+	// noLink: Boolean
+	//	Prevents the slideshow from putting an anchor link around the displayed image
+	//	enables if true, though still will not link in absence of a url to link to
+	noLink: false,
+
+	// loop: Boolean
+	//	true/false - make the slideshow loop
+	loop: true,
+
+	// hasNav: Boolean
+	//	toggle to enable/disable the visual navigation controls
+	hasNav: true,
+
+	// images: Array
+	// Contains the DOM nodes that individual images are stored in when loaded or loading.
+	images: [],
+	
+	// pageSize: Number
+	//	The number of images to request each time.
+	pageSize: 20,
+		
+	// autoLoad: Boolean
+	//	If true, then images are preloaded, before the user navigates to view them.
+	//	If false, an image is not loaded until the user views it.
+	autoLoad: true,
+
+	// autoStart: Boolean
+	//	If true, the SlideShow begins playing immediately
+	autoStart: false,
+	
+	// fixedHeight: Boolean
+	// If true, the widget does not resize itself to fix the displayed image.
+	fixedHeight: false,
+
+	// imageStore: Object
+	//	Implementation of the dojo.data.api.Read API, which provides data on the images
+	//	to be displayed.
+	imageStore: null,
+		
+	// linkAttr: String
+	//	Defines the name of the attribute to request from the store to retrieve the
+	//	URL to link to from an image, if any.
+	linkAttr: "link",
+	
+	// imageLargeAttr: String
+	//	Defines the name of the attribute to request from the store to retrieve the
+	//	URL to the image.
+	imageLargeAttr: "imageUrl",
+	
+	// titleAttr: String
+	//	Defines the name of the attribute to request from the store to retrieve the
+	//	title of the picture, if any.
+	titleAttr: "title",
+
+	// slideshowInterval: Number
+	// Time, in seconds, between image transitions during a slideshow.
+	slideshowInterval: 3,
+	
+	templateString: dojo.cache("dojox.image", "resources/SlideShow.html"),
+	
+	// _imageCounter: Number
+	//	A counter to keep track of which index image is to be loaded next
+	_imageCounter: 0,
+	
+	// _tmpImage: DomNode
+	//	The temporary image to show when a picture is loading.
+	_tmpImage: null,
+	
+	// _request: Object
+	//	Implementation of the dojo.data.api.Request API, which defines the query 
+	//	parameters for accessing the store.
+	_request: null,
+
+	postCreate: function(){
+		// summary: Initilizes the widget, sets up listeners and shows the first image
+		this.inherited(arguments);
+		var img = document.createElement("img");
+
+		// FIXME: should API be to normalize an image to fit in the specified height/width?
+		img.setAttribute("width", this.imageWidth);
+		img.setAttribute("height", this.imageHeight);
+
+		if(this.hasNav){
+			dojo.connect(this.outerNode, "onmouseover", this, function(evt){
+				try{ this._showNav();}
+				catch(e){} //TODO: remove try/catch
+			});		
+			dojo.connect(this.outerNode, "onmouseout", this, function(evt){
+				try{ this._hideNav(evt);}
+				catch(e){} //TODO: remove try/catch
+			});
+		}
+		
+		this.outerNode.style.width = this.imageWidth + "px";
+
+		img.setAttribute("src", this._blankGif);
+		var _this = this;
+		
+		this.largeNode.appendChild(img);
+		this._tmpImage = this._currentImage = img;
+		this._fitSize(true);
+		
+		this._loadImage(0, dojo.hitch(this, "showImage", 0));
+		this._calcNavDimensions();
+	},
+
+	setDataStore: function(dataStore, request, /*optional*/paramNames){
+		// summary: 
+		//		Sets the data store and request objects to read data from.
+		// dataStore:
+		//		An implementation of the dojo.data.api.Read API. This accesses the image
+		//		data.
+		// request:
+		//		An implementation of the dojo.data.api.Request API. This specifies the
+		//		query and paging information to be used by the data store
+		// paramNames:
+		//		An object defining the names of the item attributes to fetch from the
+		//		data store.  The three attributes allowed are 'linkAttr', 'imageLargeAttr' and 'titleAttr'
+		this.reset();
+		var _this = this;
+
+		this._request = {
+			query: {},
+			start: request.start || 0,
+			count: request.count || this.pageSize,
+			onBegin: function(count, request){
+				// FIXME: fires too often?!?
+				_this.maxPhotos = count;
+			}
+		};
+		if(request.query){ 
+			dojo.mixin(this._request.query, request.query); 
+		}
+		if(paramNames){
+			dojo.forEach(["imageLargeAttr", "linkAttr", "titleAttr"], function(attrName){
+				if(paramNames[attrName]){ 
+					this[attrName] = paramNames[attrName]; 
+				}
+			}, this);
+		}
+	
+		var _complete = function(items){
+			// FIXME: onBegin above used to work for maxPhotos:
+			_this.maxPhotos = items.length;
+			_this._request.onComplete = null;
+			if(_this.autoStart){
+				_this.imageIndex = -1;
+				_this.toggleSlideShow(); 
+			} else {
+				_this.showImage(0);
+			}
+			
+		};
+
+		this.imageStore = dataStore;
+		this._request.onComplete = _complete;
+		this._request.start = 0;
+		this.imageStore.fetch(this._request);
+	},
+
+	reset: function(){
+		// summary: 
+		//		Resets the widget to its initial state
+		// description: 
+		//		Removes all previously loaded images, and clears all caches.
+		dojo.query("> *", this.largeNode).orphan();
+		this.largeNode.appendChild(this._tmpImage);
+		
+		dojo.query("> *", this.hiddenNode).orphan();
+		dojo.forEach(this.images, function(img){
+			if(img && img.parentNode){ img.parentNode.removeChild(img); }
+		});
+		this.images = [];
+		this.isInitialized = false;
+		this._imageCounter = 0;
+	},
+
+	isImageLoaded: function(index){
+		// summary: 
+		//		Returns true if image at the specified index is loaded, false otherwise.
+		// index:
+		//		The number index in the data store to check if it is loaded.
+		return this.images && this.images.length > index && this.images[index];
+	},
+
+	moveImageLoadingPointer: function(index){
+		// summary: 
+		//		If 'autoload' is true, this tells the widget to start loading
+		//		images from the specified pointer.
+		// index:
+		//		The number index in the data store to start loading images from.
+		this._imageCounter = index;
+	},
+	
+	destroy: function(){
+		// summary:
+		//		Cleans up the widget when it is being destroyed
+		if(this._slideId) { this._stop(); }
+		this.inherited(arguments);
+	},
+
+	showNextImage: function(inTimer, forceLoop){
+		// summary:
+		//		Changes the image being displayed to the next image in the data store
+		// inTimer: Boolean
+		//		If true, a slideshow is active, otherwise the slideshow is inactive.
+		if(inTimer && this._timerCancelled){ return false; }
+		
+		if(this.imageIndex + 1 >= this.maxPhotos){
+			if(inTimer && (this.loop || forceLoop)){ 
+				this.imageIndex = -1; 
+			}else{
+				if(this._slideId){ this._stop(); }
+				return false;
+			}
+		}
+
+		this.showImage(this.imageIndex + 1, dojo.hitch(this,function(){
+			if(inTimer){ this._startTimer(); }
+		}));
+		return true;
+	},
+
+	toggleSlideShow: function(){
+		// summary: 
+		//		Switches the slideshow mode on and off.
+		
+		// If the slideshow is already running, stop it.
+		if(this._slideId){
+			this._stop();
+		}else{
+			dojo.toggleClass(this.domNode,"slideShowPaused");
+			this._timerCancelled = false;
+			var idx = this.imageIndex;
+
+			if(idx < 0 || (this.images[idx] && this.images[idx]._img.complete)){
+				var success = this.showNextImage(true, true);
+
+				if(!success){
+					this._stop();
+				}
+			}else{
+				var handle = dojo.subscribe(this.getShowTopicName(), dojo.hitch(this, function(info){
+					setTimeout(dojo.hitch(this, function(){
+						if(info.index == idx){
+							var success = this.showNextImage(true, true);
+							if(!success){
+								this._stop();
+							}
+							dojo.unsubscribe(handle);
+						}}),
+						this.slideshowInterval * 1000);
+				}));
+				dojo.publish(this.getShowTopicName(),
+				  [{index: idx,	title: "", url: ""}]);
+			}
+		}
+	},
+
+	getShowTopicName: function(){
+		// summary: 
+		//		Returns the topic id published to when an image is shown
+		// description:
+		//		The information published is: index, title and url
+		return (this.widgetId || this.id) + "/imageShow";
+	},
+
+	getLoadTopicName: function(){
+		// summary: 
+		//		Returns the topic id published to when an image finishes loading.
+		// description:
+		//		The information published is the index position of the image loaded.
+		return (this.widgetId ? this.widgetId : this.id) + "/imageLoad";
+	},
+
+	showImage: function(index, /* Function? */callback){
+		// summary: 
+		//		Shows the image at index 'index'.
+		// index: Number
+		//		The position of the image in the data store to display
+		// callback: Function
+		//		Optional callback function to call when the image has finished displaying.
+
+		if(!callback && this._slideId){ 
+			this.toggleSlideShow(); 
+		}
+		var _this = this;
+		var current = this.largeNode.getElementsByTagName("div");
+		this.imageIndex = index;
+
+		var showOrLoadIt = function() {
+			//If the image is already loaded, then show it. 
+			if(_this.images[index]){
+				while(_this.largeNode.firstChild){
+					_this.largeNode.removeChild(_this.largeNode.firstChild);
+				}
+				dojo.style(_this.images[index],"opacity", 0);
+				_this.largeNode.appendChild(_this.images[index]);
+				_this._currentImage = _this.images[index]._img;
+				_this._fitSize();
+								
+				var onEnd = function(a,b,c){
+
+					var img = _this.images[index].firstChild;
+					if(img.tagName.toLowerCase() != "img"){ img = img.firstChild; }
+					var title = img.getAttribute("title") || "";
+					if(_this._navShowing){
+						_this._showNav(true);
+					}
+					dojo.publish(_this.getShowTopicName(), [{
+						index: index,	
+						title: title,
+						url: img.getAttribute("src")
+					}]);
+
+        				if(callback) { 
+        					callback(a,b,c);
+        				}
+					_this._setTitle(title);
+	        		};
+				
+				dojo.fadeIn({
+					node: _this.images[index],
+					duration: 300,
+					onEnd: onEnd
+				}).play();
+				
+			}else{
+				//If the image is not loaded yet, load it first, then show it.
+				_this._loadImage(index, function(){
+					_this.showImage(index, callback);	
+				});
+			}
+		};
+
+		//If an image is currently showing, fade it out, then show
+		//the new image. Otherwise, just show the new image. 	
+		if(current && current.length > 0){
+			dojo.fadeOut({
+				node: current[0],
+				duration: 300,
+				onEnd: function(){
+					_this.hiddenNode.appendChild(current[0]);
+					showOrLoadIt();
+				}
+			}).play();
+		}else{
+			showOrLoadIt();
+		}
+	},
+	
+	_fitSize: function(force){
+		// summary: 
+		//		Fits the widget size to the size of the image being shown,
+		//		or centers the image, depending on the value of 'fixedHeight'
+		// force: Boolean
+		//		If true, the widget is always resized, regardless of the value of 'fixedHeight'
+		if(!this.fixedHeight || force){
+			var height = (this._currentImage.height + (this.hasNav ? 20:0));
+			dojo.style(this.innerWrapper, "height", height + "px");
+			return;
+		}
+		dojo.style(this.largeNode, "paddingTop", this._getTopPadding() + "px");
+	},
+	
+	_getTopPadding: function(){
+		// summary: 
+		//		Returns the padding to place at the top of the image to center it vertically.
+		if(!this.fixedHeight){ return 0; }
+		return (this.imageHeight - this._currentImage.height) / 2;
+	},
+	
+	_loadNextImage: function(){
+		// summary: 
+		//		Load the next unloaded image.
+
+		if(!this.autoLoad){
+			return;
+		}
+		while(this.images.length >= this._imageCounter && this.images[this._imageCounter]){
+			this._imageCounter++;
+		}
+		this._loadImage(this._imageCounter);
+	},
+	
+	_loadImage: function(index, callbackFn){
+		// summary: 
+		//		Load image at specified index
+		// description:
+		//		This function loads the image at position 'index' into the
+		//		internal cache of images.  This does not cause the image to be displayed.
+		// index:
+		//		The position in the data store to load an image from.
+		// callbackFn:
+		//		An optional function to execute when the image has finished loading.
+
+		if(this.images[index] || !this._request) { 
+			return; 
+		}
+		
+		var pageStart = index - (index % (this._request.count || this.pageSize));
+
+		this._request.start = pageStart;
+
+		this._request.onComplete = function(items){
+			var diff = index - pageStart;
+			
+			if(items && items.length > diff){
+				loadIt(items[diff]);
+			}else{ /* Squelch - console.log("Got an empty set of items"); */ }
+		}
+
+		var _this = this;
+		var store = this.imageStore;
+		var loadIt = function(item){			
+			var url = _this.imageStore.getValue(item, _this.imageLargeAttr);
+			
+			var img = new Image();	// when creating img with "createElement" IE doesnt has width and height, so use the Image object
+			var div = dojo.create("div", {
+				id: _this.id + "_imageDiv" + index
+			});
+			div._img = img;
+
+			var link = _this.imageStore.getValue(item,_this.linkAttr);
+			if(!link || _this.noLink){ 
+				div.appendChild(img); 
+			}else{
+				var a = dojo.create("a", {
+					"href": link,
+					"target": "_blank"
+				}, div);
+				a.appendChild(img);
+			}
+
+			dojo.connect(img, "onload", function(){
+				if(store != _this.imageStore){
+					// If the store has changed, ignore this load event.
+					return;
+				}
+				_this._fitImage(img);
+				dojo.attr(div, {"width": _this.imageWidth, "height": _this.imageHeight});
+				
+				// make a short timeout to prevent IE6/7 stack overflow at line 0 ~ still occuring though for first image 
+				dojo.publish(_this.getLoadTopicName(), [index]);
+
+				setTimeout(function(){_this._loadNextImage();}, 1);	
+				if(callbackFn){ callbackFn(); }
+			});
+			_this.hiddenNode.appendChild(div);
+
+			var titleDiv = dojo.create("div", {
+				className: "slideShowTitle"
+			}, div);
+
+			_this.images[index] = div;
+			dojo.attr(img, "src", url);
+			
+			var title = _this.imageStore.getValue(item, _this.titleAttr);
+			if(title){ dojo.attr(img, "title", title); } 
+		}
+		this.imageStore.fetch(this._request);
+	},
+
+	_stop: function(){
+		// summary: 
+		//		Stops a running slide show.
+		if(this._slideId){ clearTimeout(this._slideId); }
+		this._slideId = null;
+		this._timerCancelled = true;
+		dojo.removeClass(this.domNode,"slideShowPaused");
+	},
+
+	_prev: function(){
+		// summary: 
+		//		Show the previous image.
+		// FIXME: either pull code from showNext/prev, or call it here
+		if(this.imageIndex < 1){ return; }
+		this.showImage(this.imageIndex - 1);
+	},
+
+	_next: function(){
+		// summary: 
+		//		Show the next image
+		this.showNextImage();
+	},
+
+	_startTimer: function(){
+		// summary: 
+		//		Starts a timeout to show the next image when a slide show is active
+		var id = this.id;
+		this._slideId = setTimeout(function(){
+			dijit.byId(id).showNextImage(true);
+		}, this.slideshowInterval * 1000);
+	},
+	
+	_calcNavDimensions: function() {
+		// summary:
+		//		Calculates the dimensions of the navigation controls
+		dojo.style(this.navNode, "position", "absolute");
+		
+		//Place the navigation controls far off screen
+		dojo.style(this.navNode, "top", "-10000px");
+		
+		//Make the navigation controls visible
+		dojo._setOpacity(this.navNode, 99);
+		
+		this.navPlay._size = dojo.marginBox(this.navPlay);
+		this.navPrev._size = dojo.marginBox(this.navPrev);
+		this.navNext._size = dojo.marginBox(this.navNext);
+		
+		dojo._setOpacity(this.navNode, 0);
+		
+		dojo.style(this.navNode, {"position": "", top: ""});
+	},
+
+	_setTitle: function(title){
+		// summary: 
+		//		Sets the title to the image being displayed
+		// title: String
+		//		The String title of the image
+
+		this.titleNode.innerHTML = dojo.string.substitute(this.titleTemplate,{ 
+			title: title, 
+			current: 1 + this.imageIndex, 
+			total: this.maxPhotos || ""
+		});
+	},
+	
+	_fitImage: function(img) {
+		// summary: 
+		//		Ensures that the image width and height do not exceed the maximum.
+		// img: Node
+		//		The image DOM node to optionally resize
+		var width = img.width;
+		var height = img.height;
+		
+		if(width > this.imageWidth){
+			height = Math.floor(height * (this.imageWidth / width));
+			img.height = height;
+			img.width = width = this.imageWidth;
+		}
+		if(height > this.imageHeight){
+			width = Math.floor(width * (this.imageHeight / height));
+			img.height = this.imageHeight;
+			img.width = width;
+		}
+	},
+	
+	_handleClick: function(/* Event */e){
+		// summary:
+		//		Performs navigation on the images based on users mouse clicks
+		// e:
+		//		An Event object
+		switch(e.target){
+			case this.navNext: this._next(); break;
+			case this.navPrev: this._prev(); break;
+			case this.navPlay: this.toggleSlideShow(); break;
+		}
+	},
+	
+	_showNav: function(force){
+		// summary:
+		//		Shows the navigation controls
+		// force: Boolean
+		//		If true, the navigation controls are repositioned even if they are
+		//		currently visible.
+		if(this._navShowing && !force){return;}
+		dojo.style(this.navNode, "marginTop", "0px");
+		
+		var navPlayPos = dojo.style(this.navNode, "width")/2 - this.navPlay._size.w/2 - this.navPrev._size.w;
+		
+		dojo.style(this.navPlay, "marginLeft", navPlayPos + "px");
+		var wrapperSize = dojo.marginBox(this.outerNode);
+		
+		var margin = this._currentImage.height - this.navPlay._size.h - 10 + this._getTopPadding();
+		
+		if(margin > this._currentImage.height){margin += 10;}
+		dojo[this.imageIndex < 1 ? "addClass":"removeClass"](this.navPrev, "slideShowCtrlHide");
+		dojo[this.imageIndex + 1 >= this.maxPhotos ? "addClass":"removeClass"](this.navNext, "slideShowCtrlHide");
+	
+		var _this = this;
+		if(this._navAnim) {
+			this._navAnim.stop();
+		}
+		if(this._navShowing){ return; }
+		this._navAnim = dojo.fadeIn({
+			node: this.navNode, 
+			duration: 300,
+			onEnd: function(){ _this._navAnim = null; }
+		});
+		this._navAnim.play();
+		this._navShowing = true;
+	},
+	
+	_hideNav: function(/* Event */e){
+		// summary:
+		//		Hides the navigation controls
+		// e: Event
+		//		The DOM Event that triggered this function
+		if(!e || !this._overElement(this.outerNode, e)){
+			var _this = this;
+			if(this._navAnim){
+				this._navAnim.stop();
+			}
+			this._navAnim = dojo.fadeOut({
+				node: this.navNode,
+				duration:300,
+				onEnd: function(){ _this._navAnim = null; }
+			});
+			this._navAnim.play();
+			this._navShowing = false;
+		}
+	},
+	
+	_overElement: function(/*DomNode*/element, /*Event*/e){
+		// summary:
+		//		Returns whether the mouse is over the passed element.
+		//		Element must be display:block (ie, not a <span>)
+		
+		//When the page is unloading, if this method runs it will throw an
+		//exception.
+		if(typeof(dojo) == "undefined"){ return false; }
+		element = dojo.byId(element);
+		var m = { x: e.pageX, y: e.pageY };
+		var bb = dojo._getBorderBox(element);
+		var absl = dojo.coords(element, true);
+		var left = absl.x;
+
+		return (m.x >= left
+			&& m.x <= (left + bb.w)
+			&& m.y >= absl.y
+			&& m.y <= (top + bb.h)
+		);	//	boolean
+	}
 });
-_26.hiddenNode.appendChild(div);
-var _2a=dojo.create("div",{className:"slideShowTitle"},div);
-_26.images[_20]=div;
-dojo.attr(img,"src",url);
-var _2b=_26.imageStore.getValue(_28,_26.titleAttr);
-if(_2b){
-dojo.attr(img,"title",_2b);
-}
-};
-this.imageStore.fetch(this._request);
-},_stop:function(){
-if(this._slideId){
-clearTimeout(this._slideId);
-}
-this._slideId=null;
-this._timerCancelled=true;
-dojo.removeClass(this.domNode,"slideShowPaused");
-},_prev:function(){
-if(this.imageIndex<1){
-return;
-}
-this.showImage(this.imageIndex-1);
-},_next:function(){
-this.showNextImage();
-},_startTimer:function(){
-var id=this.id;
-this._slideId=setTimeout(function(){
-dijit.byId(id).showNextImage(true);
-},this.slideshowInterval*1000);
-},_calcNavDimensions:function(){
-dojo.style(this.navNode,"position","absolute");
-dojo.style(this.navNode,"top","-10000px");
-dojo._setOpacity(this.navNode,99);
-this.navPlay._size=dojo.marginBox(this.navPlay);
-this.navPrev._size=dojo.marginBox(this.navPrev);
-this.navNext._size=dojo.marginBox(this.navNext);
-dojo._setOpacity(this.navNode,0);
-dojo.style(this.navNode,{"position":"",top:""});
-},_setTitle:function(_2c){
-this.titleNode.innerHTML=dojo.string.substitute(this.titleTemplate,{title:_2c,current:1+this.imageIndex,total:this.maxPhotos||""});
-},_fitImage:function(img){
-var _2d=img.width;
-var _2e=img.height;
-if(_2d>this.imageWidth){
-_2e=Math.floor(_2e*(this.imageWidth/_2d));
-img.height=_2e;
-img.width=_2d=this.imageWidth;
-}
-if(_2e>this.imageHeight){
-_2d=Math.floor(_2d*(this.imageHeight/_2e));
-img.height=this.imageHeight;
-img.width=_2d;
-}
-},_handleClick:function(e){
-switch(e.target){
-case this.navNext:
-this._next();
-break;
-case this.navPrev:
-this._prev();
-break;
-case this.navPlay:
-this.toggleSlideShow();
-break;
-}
-},_showNav:function(_2f){
-if(this._navShowing&&!_2f){
-return;
-}
-dojo.style(this.navNode,"marginTop","0px");
-var _30=dojo.style(this.navNode,"width")/2-this.navPlay._size.w/2-this.navPrev._size.w;
-dojo.style(this.navPlay,"marginLeft",_30+"px");
-var _31=dojo.marginBox(this.outerNode);
-var _32=this._currentImage.height-this.navPlay._size.h-10+this._getTopPadding();
-if(_32>this._currentImage.height){
-_32+=10;
-}
-dojo[this.imageIndex<1?"addClass":"removeClass"](this.navPrev,"slideShowCtrlHide");
-dojo[this.imageIndex+1>=this.maxPhotos?"addClass":"removeClass"](this.navNext,"slideShowCtrlHide");
-var _33=this;
-if(this._navAnim){
-this._navAnim.stop();
-}
-if(this._navShowing){
-return;
-}
-this._navAnim=dojo.fadeIn({node:this.navNode,duration:300,onEnd:function(){
-_33._navAnim=null;
-}});
-this._navAnim.play();
-this._navShowing=true;
-},_hideNav:function(e){
-if(!e||!this._overElement(this.outerNode,e)){
-var _34=this;
-if(this._navAnim){
-this._navAnim.stop();
-}
-this._navAnim=dojo.fadeOut({node:this.navNode,duration:300,onEnd:function(){
-_34._navAnim=null;
-}});
-this._navAnim.play();
-this._navShowing=false;
-}
-},_overElement:function(_35,e){
-if(typeof (dojo)=="undefined"){
-return false;
-}
-_35=dojo.byId(_35);
-var m={x:e.pageX,y:e.pageY};
-var bb=dojo._getBorderBox(_35);
-var _36=dojo.coords(_35,true);
-var _37=_36.x;
-return (m.x>=_37&&m.x<=(_37+bb.w)&&m.y>=_36.y&&m.y<=(top+bb.h));
-}});
-}
diff --git a/dojox/image/ThumbnailPicker.js b/dojox/image/ThumbnailPicker.js
index 949bfe7..e16b2af 100644
--- a/dojox/image/ThumbnailPicker.js
+++ b/dojox/image/ThumbnailPicker.js
@@ -1,313 +1,583 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.image.ThumbnailPicker"]){
-dojo._hasResource["dojox.image.ThumbnailPicker"]=true;
 dojo.provide("dojox.image.ThumbnailPicker");
 dojo.experimental("dojox.image.ThumbnailPicker");
-dojo.require("dojox.fx.scroll");
-dojo.require("dojo.fx.easing");
+//
+// dojox.image.ThumbnailPicker courtesy Shane O Sullivan, licensed under a Dojo CLA 
+// @author  Copyright 2007 Shane O Sullivan (shaneosullivan1 at gmail.com)
+//
+// For a sample usage, see http://www.skynet.ie/~sos/photos.php
+//
+//	document topics.
+
+dojo.require("dojox.fx.scroll"); // is optional, but don't want to dojo[require] it
+dojo.require("dojo.fx.easing"); 
+
 dojo.require("dojo.fx");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.declare("dojox.image.ThumbnailPicker",[dijit._Widget,dijit._Templated],{imageStore:null,request:null,size:500,thumbHeight:75,thumbWidth:100,useLoadNotifier:false,useHyperlink:false,hyperlinkTarget:"new",isClickable:true,isScrollable:true,isHorizontal:true,autoLoad:true,linkAttr:"link",imageThumbAttr:"imageUrlThumb",imageLargeAttr:"imageUrl",pageSize:20,titleAttr:"title",templateString:dojo.cache("dojox.image","resources/ThumbnailPicker.html","<div dojoAttachPoint=\"outerNode\" class [...]
-this.widgetid=this.id;
-this.inherited(arguments);
-this.pageSize=Number(this.pageSize);
-this._scrollerSize=this.size-(51*2);
-var _1=this._sizeProperty=this.isHorizontal?"width":"height";
-dojo.style(this.outerNode,"textAlign","center");
-dojo.style(this.outerNode,_1,this.size+"px");
-dojo.style(this.thumbScroller,_1,this._scrollerSize+"px");
-if(this.useHyperlink){
-dojo.subscribe(this.getClickTopicName(),this,function(_2){
-var _3=_2.index;
-var _4=this.imageStore.getValue(_2.data,this.linkAttr);
-if(!_4){
-return;
-}
-if(this.hyperlinkTarget=="new"){
-window.open(_4);
-}else{
-window.location=_4;
-}
-});
-}
-if(this.isClickable){
-dojo.addClass(this.thumbsNode,"thumbClickable");
-}
-this._totalSize=0;
-this.init();
-},init:function(){
-if(this.isInitialized){
-return false;
-}
-var _5=this.isHorizontal?"Horiz":"Vert";
-dojo.addClass(this.navPrev,"prev"+_5);
-dojo.addClass(this.navNext,"next"+_5);
-dojo.addClass(this.thumbsNode,"thumb"+_5);
-dojo.addClass(this.outerNode,"thumb"+_5);
-dojo.attr(this.navNextImg,"src",this._blankGif);
-dojo.attr(this.navPrevImg,"src",this._blankGif);
-this.connect(this.navPrev,"onclick","_prev");
-this.connect(this.navNext,"onclick","_next");
-this.isInitialized=true;
-if(this.isHorizontal){
-this._offsetAttr="offsetLeft";
-this._sizeAttr="offsetWidth";
-this._scrollAttr="scrollLeft";
-}else{
-this._offsetAttr="offsetTop";
-this._sizeAttr="offsetHeight";
-this._scrollAttr="scrollTop";
-}
-this._updateNavControls();
-if(this.imageStore&&this.request){
-this._loadNextPage();
-}
-return true;
-},getClickTopicName:function(){
-return (this.widgetId||this.id)+"/select";
-},getShowTopicName:function(){
-return (this.widgetId||this.id)+"/show";
-},setDataStore:function(_6,_7,_8){
-this.reset();
-this.request={query:{},start:_7.start||0,count:_7.count||10,onBegin:dojo.hitch(this,function(_9){
-this._maxPhotos=_9;
-})};
-if(_7.query){
-dojo.mixin(this.request.query,_7.query);
-}
-if(_8){
-dojo.forEach(["imageThumbAttr","imageLargeAttr","linkAttr","titleAttr"],function(_a){
-if(_8[_a]){
-this[_a]=_8[_a];
-}
-},this);
-}
-this.request.start=0;
-this.request.count=this.pageSize;
-this.imageStore=_6;
-this._loadInProgress=false;
-if(!this.init()){
-this._loadNextPage();
-}
-},reset:function(){
-this._loadedImages={};
-dojo.forEach(this._thumbs,function(_b){
-if(_b&&_b.parentNode){
-dojo.destroy(_b);
-}
-});
-this._thumbs=[];
-this.isInitialized=false;
-this._noImages=true;
-},isVisible:function(_c){
-var _d=this._thumbs[_c];
-if(!_d){
-return false;
-}
-var _e=this.isHorizontal?"offsetLeft":"offsetTop";
-var _f=this.isHorizontal?"offsetWidth":"offsetHeight";
-var _10=this.isHorizontal?"scrollLeft":"scrollTop";
-var _11=_d[_e]-this.thumbsNode[_e];
-return (_11>=this.thumbScroller[_10]&&_11+_d[_f]<=this.thumbScroller[_10]+this._scrollerSize);
-},resize:function(dim){
-var _12=this.isHorizontal?"w":"h";
-var _13=0;
-if(this._thumbs.length>0&&dojo.marginBox(this._thumbs[0]).w==0){
-return;
-}
-dojo.forEach(this._thumbs,dojo.hitch(this,function(_14){
-var mb=dojo.marginBox(_14.firstChild);
-var _15=mb[_12];
-_13+=(Number(_15)+10);
-if(this.useLoadNotifier&&mb.w>0){
-dojo.style(_14.lastChild,"width",(mb.w-4)+"px");
-}
-dojo.style(_14,"width",mb.w+"px");
-}));
-dojo.style(this.thumbsNode,this._sizeProperty,_13+"px");
-this._updateNavControls();
-},_next:function(){
-var pos=this.isHorizontal?"offsetLeft":"offsetTop";
-var _16=this.isHorizontal?"offsetWidth":"offsetHeight";
-var _17=this.thumbsNode[pos];
-var _18=this._thumbs[this._thumbIndex];
-var _19=_18[pos]-_17;
-var _1a=-1,img;
-for(var i=this._thumbIndex+1;i<this._thumbs.length;i++){
-img=this._thumbs[i];
-if(img[pos]-_17+img[_16]-_19>this._scrollerSize){
-this._showThumbs(i);
-return;
-}
-}
-},_prev:function(){
-if(this.thumbScroller[this.isHorizontal?"scrollLeft":"scrollTop"]==0){
-return;
-}
-var pos=this.isHorizontal?"offsetLeft":"offsetTop";
-var _1b=this.isHorizontal?"offsetWidth":"offsetHeight";
-var _1c=this._thumbs[this._thumbIndex];
-var _1d=_1c[pos]-this.thumbsNode[pos];
-var _1e=-1,img;
-for(var i=this._thumbIndex-1;i>-1;i--){
-img=this._thumbs[i];
-if(_1d-img[pos]>this._scrollerSize){
-this._showThumbs(i+1);
-return;
-}
-}
-this._showThumbs(0);
-},_checkLoad:function(img,_1f){
-dojo.publish(this.getShowTopicName(),[{index:_1f}]);
-this._updateNavControls();
-this._loadingImages={};
-this._thumbIndex=_1f;
-if(this.thumbsNode.offsetWidth-img.offsetLeft<(this._scrollerSize*2)){
-this._loadNextPage();
-}
-},_showThumbs:function(_20){
-_20=Math.min(Math.max(_20,0),this._maxPhotos);
-if(_20>=this._maxPhotos){
-return;
-}
-var img=this._thumbs[_20];
-if(!img){
-return;
-}
-var _21=img.offsetLeft-this.thumbsNode.offsetLeft;
-var top=img.offsetTop-this.thumbsNode.offsetTop;
-var _22=this.isHorizontal?_21:top;
-if((_22>=this.thumbScroller[this._scrollAttr])&&(_22+img[this._sizeAttr]<=this.thumbScroller[this._scrollAttr]+this._scrollerSize)){
-return;
-}
-if(this.isScrollable){
-var _23=this.isHorizontal?{x:_21,y:0}:{x:0,y:top};
-dojox.fx.smoothScroll({target:_23,win:this.thumbScroller,duration:300,easing:dojo.fx.easing.easeOut,onEnd:dojo.hitch(this,"_checkLoad",img,_20)}).play(10);
-}else{
-if(this.isHorizontal){
-this.thumbScroller.scrollLeft=_21;
-}else{
-this.thumbScroller.scrollTop=top;
-}
-this._checkLoad(img,_20);
-}
-},markImageLoaded:function(_24){
-var _25=dojo.byId("loadingDiv_"+this.widgetid+"_"+_24);
-if(_25){
-this._setThumbClass(_25,"thumbLoaded");
-}
-this._loadedImages[_24]=true;
-},_setThumbClass:function(_26,_27){
-if(!this.autoLoad){
-return;
-}
-dojo.addClass(_26,_27);
-},_loadNextPage:function(){
-if(this._loadInProgress){
-return;
-}
-this._loadInProgress=true;
-var _28=this.request.start+(this._noImages?0:this.pageSize);
-var pos=_28;
-while(pos<this._thumbs.length&&this._thumbs[pos]){
-pos++;
-}
-var _29=this.imageStore;
-var _2a=function(_2b,_2c){
-if(_29!=this.imageStore){
-return;
-}
-if(_2b&&_2b.length){
-var _2d=0;
-var _2e=dojo.hitch(this,function(){
-if(_2d>=_2b.length){
-this._loadInProgress=false;
-return;
-}
-var _2f=_2d++;
-this._loadImage(_2b[_2f],pos+_2f,_2e);
-});
-_2e();
-this._updateNavControls();
-}else{
-this._loadInProgress=false;
-}
-};
-var _30=function(){
-this._loadInProgress=false;
-};
-this.request.onComplete=dojo.hitch(this,_2a);
-this.request.onError=dojo.hitch(this,_30);
-this.request.start=_28;
-this._noImages=false;
-this.imageStore.fetch(this.request);
-},_loadImage:function(_31,_32,_33){
-var _34=this.imageStore;
-var url=_34.getValue(_31,this.imageThumbAttr);
-var _35=dojo.create("div",{id:"img_"+this.widgetid+"_"+_32});
-var img=dojo.create("img",{},_35);
-img._index=_32;
-img._data=_31;
-this._thumbs[_32]=_35;
-var _36;
-if(this.useLoadNotifier){
-_36=dojo.create("div",{id:"loadingDiv_"+this.widgetid+"_"+_32},_35);
-this._setThumbClass(_36,this._loadedImages[_32]?"thumbLoaded":"thumbNotifier");
-}
-var _37=dojo.marginBox(this.thumbsNode);
-var _38;
-var _39;
-if(this.isHorizontal){
-_38=this.thumbWidth;
-_39="w";
-}else{
-_38=this.thumbHeight;
-_39="h";
-}
-_37=_37[_39];
-var sl=this.thumbScroller.scrollLeft,st=this.thumbScroller.scrollTop;
-dojo.style(this.thumbsNode,this._sizeProperty,(_37+_38+20)+"px");
-this.thumbScroller.scrollLeft=sl;
-this.thumbScroller.scrollTop=st;
-this.thumbsNode.appendChild(_35);
-dojo.connect(img,"onload",this,dojo.hitch(this,function(){
-if(_34!=this.imageStore){
-return false;
-}
-this.resize();
-setTimeout(_33,0);
-return false;
-}));
-dojo.connect(img,"onclick",this,function(evt){
-dojo.publish(this.getClickTopicName(),[{index:evt.target._index,data:evt.target._data,url:img.getAttribute("src"),largeUrl:this.imageStore.getValue(_31,this.imageLargeAttr),title:this.imageStore.getValue(_31,this.titleAttr),link:this.imageStore.getValue(_31,this.linkAttr)}]);
-return false;
+
+dojo.declare("dojox.image.ThumbnailPicker",
+	[dijit._Widget, dijit._Templated],
+	{
+	// summary: A scrolling Thumbnail Picker widget 
+	//
+	// imageStore: Object
+	// A data store that implements the dojo.data Read API.
+	imageStore: null,
+
+	// request: Object
+	// A dojo.data Read API Request object.
+	request: null,
+
+	// size: Number
+	// Width or height in pixels, depending if horizontal or vertical.
+	size: 500, //FIXME: use CSS?
+
+	// thumbHeight: Number
+	// Default height of a thumbnail image
+	thumbHeight: 75, // FIXME: use CSS?
+
+	// thumbWidth: Number
+	// Default width of an image
+	thumbWidth: 100, // FIXME: use CSS?
+
+	// useLoadNotifier: Boolean
+	// Setting useLoadNotifier to true makes a colored DIV appear under each
+	// thumbnail image, which is used to display the loading status of each
+	// image in the data store.
+	useLoadNotifier: false,
+
+	// useHyperlink: boolean
+	// Setting useHyperlink to true causes a click on a thumbnail to open a link.
+	useHyperlink: false,
+
+	// hyperlinkTarget: String
+	// If hyperlinkTarget is set to "new", clicking on a thumb will open a new window
+	// If it is set to anything else, clicking a thumbnail will open the url in the
+	// current window.
+	hyperlinkTarget: "new",
+
+	// isClickable: Boolean
+	// When set to true, the cursor over a thumbnail changes.
+	isClickable: true,
+
+	// isScrollable: Boolean
+	// When true, uses smoothScroll to move between pages
+	isScrollable: true,
+
+	// isHorizontal: Boolean
+	// If true, the thumbnails are displayed horizontally. Otherwise they are displayed
+	// vertically
+	isHorizontal: true,
+
+	//autoLoad: Boolean
+	autoLoad: true,
+
+	// linkAttr: String
+	// The attribute name for accessing the url from the data store
+	linkAttr: "link",
+	
+	// imageThumbAttr: String
+	// The attribute name for accessing the thumbnail image url from the data store
+	imageThumbAttr: "imageUrlThumb",	
+	
+	// imageLargeAttr: String
+	// The attribute name for accessing the large image url from the data store
+	imageLargeAttr: "imageUrl",
+	
+	// pageSize: Number
+	//	The number of images to request each time.
+	pageSize: 20,
+	
+	// titleAttr: String
+	// The attribute name for accessing the title from the data store
+	titleAttr: "title",
+	
+	templateString: dojo.cache("dojox.image", "resources/ThumbnailPicker.html"), 
+	
+	// thumbs: Array
+	// Stores the image nodes for the thumbnails.
+	_thumbs: [],
+	
+	// _thumbIndex: Number
+	// The index of the first thumbnail shown
+	_thumbIndex: 0,
+	
+	// _maxPhotos: Number
+	// The total number of photos in the image store
+	_maxPhotos: 0,
+	
+	// _loadedImages: Object
+	// Stores the indices of images that have been marked as loaded using the
+	// markImageLoaded function.
+	_loadedImages: {},
+
+	postCreate: function(){
+		// summary:
+		//		Initializes styles and listeners		
+		this.widgetid = this.id;
+		this.inherited(arguments);
+		this.pageSize = Number(this.pageSize);
+
+		this._scrollerSize = this.size - (51 * 2);
+		
+		var sizeProp = this._sizeProperty = this.isHorizontal ? "width" : "height";
+	
+		// FIXME: do this via css? calculate the correct width for the widget
+		dojo.style(this.outerNode, "textAlign","center");
+		dojo.style(this.outerNode, sizeProp, this.size+"px");
+	
+		dojo.style(this.thumbScroller, sizeProp, this._scrollerSize + "px");
+	
+		//If useHyperlink is true, then listen for a click on a thumbnail, and
+		//open the link
+		if(this.useHyperlink){
+			dojo.subscribe(this.getClickTopicName(), this, function(packet){
+				var index = packet.index;
+				var url = this.imageStore.getValue(packet.data,this.linkAttr);
+				
+				//If the data item doesn't contain a URL, do nothing
+				if(!url){return;}
+				
+				if(this.hyperlinkTarget == "new"){
+					window.open(url);
+				}else{
+					window.location = url;
+				}
+			});
+		}
+	
+		if(this.isClickable){
+			dojo.addClass(this.thumbsNode, "thumbClickable");
+		}
+		this._totalSize = 0;
+		this.init();
+	},
+
+	init: function(){
+		// summary:
+		//		Creates DOM nodes for thumbnail images and initializes their listeners 
+		if(this.isInitialized) {return false;}
+	
+		var classExt = this.isHorizontal ? "Horiz" : "Vert";
+	
+		// FIXME: can we setup a listener around the whole element and determine based on e.target?	  
+		dojo.addClass(this.navPrev, "prev" + classExt);
+		dojo.addClass(this.navNext, "next" + classExt);
+		dojo.addClass(this.thumbsNode, "thumb"+classExt);
+		dojo.addClass(this.outerNode, "thumb"+classExt);
+	
+		dojo.attr(this.navNextImg, "src", this._blankGif);
+		dojo.attr(this.navPrevImg, "src", this._blankGif);
+		
+		this.connect(this.navPrev, "onclick", "_prev");
+		this.connect(this.navNext, "onclick", "_next");
+		this.isInitialized = true;
+		
+		if(this.isHorizontal){
+			this._offsetAttr = "offsetLeft";
+			this._sizeAttr = "offsetWidth";
+			this._scrollAttr = "scrollLeft";
+		}else{
+			this._offsetAttr = "offsetTop";
+			this._sizeAttr = "offsetHeight";
+			this._scrollAttr = "scrollTop";
+		}
+	
+		this._updateNavControls();
+		if(this.imageStore && this.request){this._loadNextPage();}
+		return true;
+	},
+
+	getClickTopicName: function(){
+		// summary: 
+		//		Returns the name of the dojo topic that can be
+		//		subscribed to in order to receive notifications on
+		//		which thumbnail was selected.
+		return (this.widgetId || this.id) + "/select"; // String
+	},
+
+	getShowTopicName: function(){
+		// summary:
+		//		Returns the name of the dojo topic that can be
+		//		subscribed to in order to receive notifications on
+		//		which thumbnail is now visible
+		return (this.widgetId || this.id) + "/show"; // String
+	},
+
+	setDataStore: function(dataStore, request, /*optional*/paramNames){
+		// summary:
+		//		Sets the data store and request objects to read data from.
+		// dataStore:
+		//		An implementation of the dojo.data.api.Read API. This accesses the image
+		//		data.
+		// request:
+		//		An implementation of the dojo.data.api.Request API. This specifies the
+		//		query and paging information to be used by the data store
+		// paramNames:
+		//		An object defining the names of the item attributes to fetch from the
+		//		data store.  The four attributes allowed are 'linkAttr', 'imageLargeAttr',
+		//		'imageThumbAttr' and 'titleAttr'
+		this.reset();
+	
+		this.request = {
+			query: {},
+			start: request.start || 0,
+			count: request.count || 10,
+			onBegin: dojo.hitch(this, function(total){
+				this._maxPhotos = total;
+			})
+		};
+	
+		if(request.query){ dojo.mixin(this.request.query, request.query);}
+	
+		if(paramNames){
+			dojo.forEach(["imageThumbAttr", "imageLargeAttr", "linkAttr", "titleAttr"], function(attrName){
+				if(paramNames[attrName]){ this[attrName] = paramNames[attrName]; }	
+			}, this);
+		}
+		
+		this.request.start = 0;
+		this.request.count = this.pageSize;
+		this.imageStore = dataStore;
+		this._loadInProgress = false;
+		if(!this.init()){this._loadNextPage();}
+	},
+
+	reset: function(){
+		// summary:
+		//		Resets the widget back to its original state.
+		this._loadedImages = {};
+		dojo.forEach(this._thumbs, function(img){
+			if(img && img.parentNode){
+				dojo.destroy(img);
+			}
+		});
+	
+		this._thumbs = [];
+		this.isInitialized = false;
+		this._noImages = true;
+	},
+	
+	isVisible: function(index) {
+		// summary:
+		//		Returns true if the image at the specified index is currently visible. False otherwise.
+		var img = this._thumbs[index];
+		if(!img){return false;}
+		var pos = this.isHorizontal ? "offsetLeft" : "offsetTop";
+		var size = this.isHorizontal ? "offsetWidth" : "offsetHeight";
+		var scrollAttr = this.isHorizontal ? "scrollLeft" : "scrollTop";
+		var offset = img[pos] - this.thumbsNode[pos];
+		return (offset >= this.thumbScroller[scrollAttr]
+			&& offset + img[size] <= this.thumbScroller[scrollAttr] + this._scrollerSize);	
+	},
+	
+	resize: function(dim){
+		var sizeParam = this.isHorizontal ? "w": "h";
+
+		var total = 0;
+
+		if(this._thumbs.length > 0 && dojo.marginBox(this._thumbs[0]).w == 0){
+			// Skip the resize if the widget is not visible
+			return;
+		}
+
+		// Calculate the complete size of the thumbnails
+		dojo.forEach(this._thumbs, dojo.hitch(this, function(imgContainer){
+			var mb = dojo.marginBox(imgContainer.firstChild);
+			var size = mb[sizeParam];
+			total += (Number(size) + 10);
+			
+			if(this.useLoadNotifier && mb.w > 0){
+				dojo.style(imgContainer.lastChild, "width", (mb.w - 4) + "px");
+			}
+			dojo.style(imgContainer, "width", mb.w + "px");
+		}));
+
+		dojo.style(this.thumbsNode, this._sizeProperty, total + "px");
+		this._updateNavControls();
+	},
+	
+	_next: function() {
+		// summary:
+		//		Displays the next page of images
+		var pos = this.isHorizontal ? "offsetLeft" : "offsetTop";
+		var size = this.isHorizontal ? "offsetWidth" : "offsetHeight";
+		var baseOffset = this.thumbsNode[pos];
+		var firstThumb = this._thumbs[this._thumbIndex];
+		var origOffset = firstThumb[pos] - baseOffset;
+	
+		var index = -1, img;
+	
+		for(var i = this._thumbIndex + 1; i < this._thumbs.length; i++){
+			img = this._thumbs[i];
+			if(img[pos] - baseOffset + img[size] - origOffset > this._scrollerSize){
+				this._showThumbs(i);
+				return;
+			}
+		}
+	},
+
+	_prev: function(){
+		// summary:
+		//		Displays the next page of images
+		if(this.thumbScroller[this.isHorizontal ? "scrollLeft" : "scrollTop"] == 0){return;}
+		var pos = this.isHorizontal ? "offsetLeft" : "offsetTop";
+		var size = this.isHorizontal ? "offsetWidth" : "offsetHeight";
+	
+		var firstThumb = this._thumbs[this._thumbIndex];
+		var origOffset = firstThumb[pos] - this.thumbsNode[pos];
+	
+		var index = -1, img;
+	
+		for(var i = this._thumbIndex - 1; i > -1; i--) {
+			img = this._thumbs[i];
+			if(origOffset - img[pos] > this._scrollerSize){
+				this._showThumbs(i + 1);
+				return;
+			}
+		}
+		this._showThumbs(0);
+	},
+
+	_checkLoad: function(img, index){
+		// summary:
+		//		Checks if an image is loaded.
+		dojo.publish(this.getShowTopicName(), [{index:index}]);
+		this._updateNavControls();
+		this._loadingImages = {};
+	
+		this._thumbIndex = index;
+	
+		//If we have not already requested the data from the store, do so. 
+		if(this.thumbsNode.offsetWidth - img.offsetLeft < (this._scrollerSize * 2)){
+			this._loadNextPage();
+		}
+	},
+
+	_showThumbs: function(index){
+		// summary:
+		//		Displays thumbnail images, starting at position 'index'
+		// index: Number
+		//		The index of the first thumbnail
+
+//FIXME: When is this be called with an invalid index?  Do we need this check at all?
+//		if(typeof index != "number"){ index = this._thumbIndex; }
+		index = Math.min(Math.max(index, 0), this._maxPhotos);
+		
+		if(index >= this._maxPhotos){ return; }
+		
+		var img = this._thumbs[index];
+		if(!img){ return; }
+		
+		var left = img.offsetLeft - this.thumbsNode.offsetLeft;
+		var top = img.offsetTop - this.thumbsNode.offsetTop;
+		var offset = this.isHorizontal ? left : top;
+				
+		if(	(offset >= this.thumbScroller[this._scrollAttr]) &&
+			(offset + img[this._sizeAttr] <= this.thumbScroller[this._scrollAttr] + this._scrollerSize)
+		){
+			// FIXME: WTF is this checking for?
+			return;
+		}
+		
+		
+		if(this.isScrollable){
+			var target = this.isHorizontal ? {x: left, y: 0} : { x:0, y:top};
+			dojox.fx.smoothScroll({
+				target: target,
+				win: this.thumbScroller,
+				duration:300,
+				easing:dojo.fx.easing.easeOut,
+				onEnd: dojo.hitch(this, "_checkLoad", img, index)
+			}).play(10);
+		}else{
+			if(this.isHorizontal){
+				this.thumbScroller.scrollLeft = left;
+			}else{
+				this.thumbScroller.scrollTop = top;
+			}
+			this._checkLoad(img, index);
+		}	
+	},
+	
+	markImageLoaded: function(index){
+		// summary: 
+		//		Changes a visual cue to show the image is loaded
+		// description:
+		//		If 'useLoadNotifier' is set to true, then a visual cue is
+		//		given to state whether the image is loaded or not.	Calling this function
+		//		marks an image as loaded.
+		var thumbNotifier = dojo.byId("loadingDiv_"+this.widgetid+"_"+index);
+		if(thumbNotifier){this._setThumbClass(thumbNotifier, "thumbLoaded");}
+		this._loadedImages[index] = true;
+	},
+
+	_setThumbClass: function(thumb, className){
+		// summary:
+		//		Adds a CSS class to a thumbnail, only if 'autoLoad' is true
+		// thumb: DomNode
+		//		The thumbnail DOM node to set the class on
+		// className: String
+		//		The CSS class to add to the DOM node.
+		if(!this.autoLoad){ return; }
+		dojo.addClass(thumb, className);
+	},
+                                                 
+	_loadNextPage: function(){
+		// summary:
+		//		Loads the next page of thumbnail images
+		if(this._loadInProgress){return;}
+		this._loadInProgress = true;
+		var start = this.request.start + (this._noImages ? 0 : this.pageSize);
+		
+		var pos = start;
+		while(pos < this._thumbs.length && this._thumbs[pos]){pos ++;}
+		
+		var store = this.imageStore;
+		
+		//Define the function to call when the items have been 
+		//returned from the data store.
+		var complete = function(items, request){
+			if(store != this.imageStore){
+				// If the store has been changed, ignore this callback.
+				return;
+			}
+			if(items && items.length){
+				var itemCounter = 0;
+				var loadNext = dojo.hitch(this, function(){
+					if(itemCounter >= items.length){
+						this._loadInProgress = false;
+						return;
+					}
+					var counter = itemCounter++;
+
+					this._loadImage(items[counter], pos + counter, loadNext);
+				});
+				loadNext();
+
+				//Show or hide the navigation arrows on the thumbnails, 
+				//depending on whether or not the widget is at the start,
+				//end, or middle of the list of images. 
+				this._updateNavControls();
+			}else{
+				this._loadInProgress = false;
+			}
+		};
+	
+		//Define the function to call if the store reports an error. 
+		var error = function(){
+			this._loadInProgress = false;
+			console.log("Error getting items");
+		};
+
+		this.request.onComplete = dojo.hitch(this, complete);
+		this.request.onError = dojo.hitch(this, error);
+	
+		//Increment the start parameter. This is the dojo.data API's
+		//version of paging. 
+		this.request.start = start;
+		this._noImages = false;
+		
+		//Execute the request for data. 
+		this.imageStore.fetch(this.request);
+	
+	},
+
+	_loadImage: function(data, index, callback){
+		// summary:
+		//		Loads an image.
+
+		var store = this.imageStore;
+		var url = store.getValue(data,this.imageThumbAttr);
+		
+		var imgContainer = dojo.create("div", {
+			id: "img_" + this.widgetid + "_" + index
+		});
+		var img = dojo.create("img", {}, imgContainer);
+		img._index = index;
+		img._data = data;
+	
+		this._thumbs[index] = imgContainer;
+		var loadingDiv;
+		if(this.useLoadNotifier){
+			loadingDiv = dojo.create("div", {
+				id: "loadingDiv_" + this.widgetid+"_" + index
+			}, imgContainer);
+	
+			//If this widget was previously told that the main image for this
+			//thumb has been loaded, make the loading indicator transparent.
+			this._setThumbClass(loadingDiv,
+				this._loadedImages[index] ? "thumbLoaded":"thumbNotifier");
+		}
+		var size = dojo.marginBox(this.thumbsNode);
+		var defaultSize;
+		var sizeParam;
+		if(this.isHorizontal){
+			defaultSize = this.thumbWidth;
+			sizeParam = 'w';
+		} else{
+			defaultSize = this.thumbHeight;
+			sizeParam = 'h';
+		}
+		size = size[sizeParam];
+		var sl = this.thumbScroller.scrollLeft, st = this.thumbScroller.scrollTop;
+
+		dojo.style(this.thumbsNode, this._sizeProperty, (size + defaultSize + 20) + "px");
+
+		//Remember the scroll values, as changing the size can alter them
+		this.thumbScroller.scrollLeft = sl;
+		this.thumbScroller.scrollTop = st;
+		this.thumbsNode.appendChild(imgContainer);
+	
+		dojo.connect(img, "onload", this, dojo.hitch(this, function(){
+			if(store != this.imageStore){
+				// If the store has changed, ignore this load event
+				return false;
+			}
+			this.resize();
+						
+			// Have to use a timeout here to prevent a call stack that gets
+			// so deep that IE throws stack overflow errors
+			setTimeout(callback, 0);
+			return false;
+		}));
+	
+		dojo.connect(img, "onclick", this, function(evt){
+			dojo.publish(this.getClickTopicName(),	[{
+				index: evt.target._index,
+				data: evt.target._data,
+				url: img.getAttribute("src"), 
+				largeUrl: this.imageStore.getValue(data,this.imageLargeAttr),
+				title: this.imageStore.getValue(data,this.titleAttr),
+				link: this.imageStore.getValue(data,this.linkAttr)
+			}]);
+			return false;
+		});
+		dojo.addClass(img, "imageGalleryThumb");
+		img.setAttribute("src", url);
+		var title = this.imageStore.getValue(data, this.titleAttr);
+		if(title){ img.setAttribute("title",title); }
+		this._updateNavControls();
+	
+	},
+
+	_updateNavControls: function(){
+		// summary: 
+		//		Updates the navigation controls to hide/show them when at
+		//		the first or last images.
+		var cells = [];
+		var change = function(node, add){
+			var fn = add ? "addClass" : "removeClass";
+			dojo[fn](node,"enabled");
+			dojo[fn](node,"thumbClickable");
+		};
+		
+		var pos = this.isHorizontal ? "scrollLeft" : "scrollTop";
+		var size = this.isHorizontal ? "offsetWidth" : "offsetHeight";
+		change(this.navPrev, (this.thumbScroller[pos] > 0));
+		
+		var last = this._thumbs[this._thumbs.length - 1];
+		var addClass = (this.thumbScroller[pos] + this._scrollerSize < this.thumbsNode[size]);
+		change(this.navNext, addClass);
+	}
 });
-dojo.addClass(img,"imageGalleryThumb");
-img.setAttribute("src",url);
-var _3a=this.imageStore.getValue(_31,this.titleAttr);
-if(_3a){
-img.setAttribute("title",_3a);
-}
-this._updateNavControls();
-},_updateNavControls:function(){
-var _3b=[];
-var _3c=function(_3d,add){
-var fn=add?"addClass":"removeClass";
-dojo[fn](_3d,"enabled");
-dojo[fn](_3d,"thumbClickable");
-};
-var pos=this.isHorizontal?"scrollLeft":"scrollTop";
-var _3e=this.isHorizontal?"offsetWidth":"offsetHeight";
-_3c(this.navPrev,(this.thumbScroller[pos]>0));
-var _3f=this._thumbs[this._thumbs.length-1];
-var _40=(this.thumbScroller[pos]+this._scrollerSize<this.thumbsNode[_3e]);
-_3c(this.navNext,_40);
-}});
-}
diff --git a/dojox/image/_base.js b/dojox/image/_base.js
index de20b50..12a1961 100644
--- a/dojox/image/_base.js
+++ b/dojox/image/_base.js
@@ -1,27 +1,114 @@
-/*
-	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
-*/
+dojo.provide("dojox.image._base");
 
+// summary: Core Image-related functionality 
+;(function(d){
+	
+	var cacheNode;
+	dojox.image.preload = function(/* Array */urls){
+		// summary: Preload a list of images in the dom.
+		//
+		// urls: Array
+		//		The list of urls to load. Can be any valid .src attribute.
+		//	
+		//	example:
+		//	Load two images into cache:
+		//	|	dojox.image.preload(["foo.png", "bar.gif"]);
+		//
+		//	example:
+		//	Using djConfig:
+		//	|	var djConfig = {
+		//	|		preloadImages:["bar.png", "baz.png", "http://example.com/icon.gif"]
+		//	|	};	
+		//
+		// returns: Array
+		//		An Array of DomNodes that have been cached. 
+		
+		if(!cacheNode){ 
+			cacheNode = d.create("div", {
+				style:{ position:"absolute", top:"-9999px", height:"1px", overflow:"hidden" }
+			}, d.body());
+		}
 
-if(!dojo._hasResource["dojox.image._base"]){
-dojo._hasResource["dojox.image._base"]=true;
-dojo.provide("dojox.image._base");
-(function(d){
-var _1;
-dojox.image.preload=function(_2){
-if(!_1){
-_1=d.create("div",{style:{position:"absolute",top:"-9999px",height:"1px",overflow:"hidden"}},d.body());
-}
-return d.map(_2,function(_3){
-return d.create("img",{src:_3},_1);
-});
-};
-if(d.config.preloadImages){
-d.addOnLoad(function(){
-dojox.image.preload(d.config.preloadImages);
-});
-}
-})(dojo);
-}
+		// place them in the hidden cachenode
+		return d.map(urls, function(url){
+			return d.create("img", { src: url }, cacheNode);
+		});
+	
+	};
+	
+	/*=====
+		dojo.mixin(djConfig, {
+			// preloadImages: Array?
+			//		An optional array of urls to preload immediately upon
+			//		page load. Uses `dojox.image`, and is unused if not present.
+			preloadImages: []
+		})
+	=====*/
+	if(d.config.preloadImages){
+		d.addOnLoad(function(){
+			dojox.image.preload(d.config.preloadImages);
+		});
+	}
+		
+//	dojo.declare("dojox.image.Image", dijit._Widget, {
+//		// summary: an Image widget
+//		//
+//		// example:
+//		//	| new dojox.Image({ src:"foo.png", id:"bar" });
+//		
+//		alt: "",
+//		src: dojo._blankGif,
+//		title: "",
+//		
+//		onLoad: function(e){
+//			// summary: Stub fired when this image is really ready.
+//		},
+//		
+//		_onLoad: function(e){
+//			// summary: private function to normalize `onLoad` for this
+//			//	instance.
+//			this.onLoad(e);
+//		},
+//		
+//		_setSrcAttr: function(newSrc){
+//			// summary: Function so widget.attr('src', someUrl) works
+//			
+//			var ts = this.domNode, os = td.src;
+//			if(os !== newSrc){
+//				td.src = newSrc;
+//			}
+//		},
+//		
+//		/* Sugar Functions: */
+//		
+//		crossFade: function(newSrc){
+//			// summary: Set this Image to a new src with crossfading
+//			//
+//			// example:
+//			//	dijit.byId("bar").crossFade("/images/newImage.png");
+//			//
+//			
+//			d.fadeOut({
+//				node: this.domNode,
+//				onEnd: d.hitch(this, function(){
+//					this.attr('src', newSrc);
+//					d.fadeIn({
+//						node: this.domNode,
+//						delay: 75
+//					}).play();
+//				})
+//			}).play();
+//		},
+//				
+//		/* Overrides */
+//		
+//		buildRendering: function(){
+//			// override buildrendering to create a real "img" instead of a div
+//			// when no srcNodeRef is passed. also wire up single onload.
+//			this.domNode = this.srcNodeRef || d.create('img');
+//			this.connect(this.domNode, "onload", "_onload");
+//		}
+//			
+//	});
+		
+})(dojo);
\ No newline at end of file
diff --git a/dojox/image/resources/Badge.css b/dojox/image/resources/Badge.css
index ff4fd57..482ffa2 100644
--- a/dojox/image/resources/Badge.css
+++ b/dojox/image/resources/Badge.css
@@ -1,17 +1,22 @@
+/* dojox.image.Badge definitions */
 
 .dojoxBadge {
 	position:relative;
 }
+
 .dojoxBadge .dojoxBadgeImage {
 	position:absolute;
 	top:0; left:0;
 	margin:0;
 	padding:0;
 }
+
 .dojoxBadge {
 	margin:0; padding:0;
 	border:1px solid #eee;
+/*	background:#fff; */
 }
+
 .dojoxBadge .dojoxBadgeImage {
 	overflow:hidden;
 	margin-left:1px;
@@ -19,12 +24,14 @@
 	background:#ededed;
 	z-index:90;
 }
+
 .dojoxBadge .dojoxBadgeSeen {
 	background-color:#dedede;
 }
 .dojoxBadge .dojoxBadgeOver {
 	background-color:green !important;
 }
+
 .dojoxBadge .dojoxBadgeTop {
 	z-index:99;
 }
diff --git a/dojox/image/resources/Gallery.css b/dojox/image/resources/Gallery.css
index 6ddd333..8e4fd90 100644
--- a/dojox/image/resources/Gallery.css
+++ b/dojox/image/resources/Gallery.css
@@ -1,3 +1,4 @@
+/* dojox.image.Gallery - too small to be it's own file? */
 
 .imageGalleryWrapper {
 	padding-bottom: 20px;
diff --git a/dojox/image/resources/Lightbox.css b/dojox/image/resources/Lightbox.css
index 37ecc54..d450340 100644
--- a/dojox/image/resources/Lightbox.css
+++ b/dojox/image/resources/Lightbox.css
@@ -1,8 +1,17 @@
 
+/* dojox.image.Lightbox:base */
+/* FIXME: should be be doing this? I want a black underlay, but this sets ALL dialogs to black,
+    but because it's decendant of body, i can't set this color any other way ... */
 .dijitDialogUnderlay {
 	background-color:#000; 
 }
-.dojoxLightbox {
+
+/* more specific to override .theme .dijitDialog name. might try baseClass="dojoxLightbox" 
+   but that would require additional overriden CSS on top of the original Dialog.css       */
+.claro .dojoxLightbox,
+.soria .dojoxLightbox,
+.nihilo .dojoxLightbox,
+.tundra .dojoxLightbox {
 	position:absolute;
 	z-index:999;
 	overflow:hidden;
@@ -10,16 +19,19 @@
 	height:100px; 
 	border:11px solid #fff;
 	background:#fff url('images/loading.gif') no-repeat center center;
-        
-	-webkit-box-shadow: 0px 6px 10px #636363; 
+
+	/* special safari + FF specific rounding + shadows */
+	-webkit-box-shadow: 0px 6px 10px #636363; /* #adadad; */
 	-webkit-border-radius: 3px;
 	-moz-border-radius:4px;
-        border-radius: 4px;
+	border-radius: 4px;
 }
+
 .dojoxLightboxContainer {
 	position:absolute;
 	top:0; left:0; 
 }
+
 .dojoxLightboxFooter {
 	padding-bottom:5px;
 	position:relative;
@@ -30,10 +42,12 @@
 	z-index:1000;
 	font-size:10pt;
 }
+
 .dojoxLightboxGroupText {
 	color:#666; 
 	font-size:8pt;
 }
+
 .LightboxNext,
 .LightboxPrev,
 .LightboxClose {
@@ -42,6 +56,9 @@
 	height:16px;
 	cursor:pointer;
 }
+
+/* dojox.image.Lightbox:tundra:nihilo */
+
 .nihilo .LightboxClose,
 .tundra .LightboxClose {
 	background:url('images/close.png') no-repeat center center;
@@ -66,6 +83,8 @@
 .dj_ie6 .tundra .LightboxPrev {
 	background:url('images/left.gif') no-repeat center center;
 }
+
+/* dojox.image.Lightbox:soria */
 .soria .LightboxClose,
 .soria .LightboxNext,
 .soria .LightboxPrev {
@@ -80,3 +99,7 @@
 .soria .LightboxPrev {
 	background-position:0 0;
 }
+
+.dojoxLightboxText {
+	margin:0; padding:0; 
+}
diff --git a/dojox/image/resources/Lightbox.html b/dojox/image/resources/Lightbox.html
index 32a72ef..aca14ee 100644
--- a/dojox/image/resources/Lightbox.html
+++ b/dojox/image/resources/Lightbox.html
@@ -3,9 +3,9 @@
 		<div dojoAttachPoint="imageContainer" class="dojoxLightboxContainer" dojoAttachEvent="onclick: _onImageClick">
 			<img dojoAttachPoint="imgNode" src="${imgUrl}" class="dojoxLightboxImage" alt="${title}">
 			<div class="dojoxLightboxFooter" dojoAttachPoint="titleNode">
-				<div class="dijitInline LightboxClose" dojoAttachPoint="closeNode"></div>
-				<div class="dijitInline LightboxNext" dojoAttachPoint="nextNode"></div>	
-				<div class="dijitInline LightboxPrev" dojoAttachPoint="prevNode"></div>
+				<div class="dijitInline LightboxClose" dojoAttachPoint="closeButtonNode"></div>
+				<div class="dijitInline LightboxNext" dojoAttachPoint="nextButtonNode"></div>	
+				<div class="dijitInline LightboxPrev" dojoAttachPoint="prevButtonNode"></div>
 				<div class="dojoxLightboxText" dojoAttachPoint="titleTextNode"><span dojoAttachPoint="textNode">${title}</span><span dojoAttachPoint="groupCount" class="dojoxLightboxGroupText"></span></div>
 			</div>
 		</div>
diff --git a/dojox/image/resources/SlideShow.css b/dojox/image/resources/SlideShow.css
index a9ab15d..d1d76e7 100644
--- a/dojox/image/resources/SlideShow.css
+++ b/dojox/image/resources/SlideShow.css
@@ -1,3 +1,4 @@
+/* dojox.image.SlideShow */
 
 .slideShowWrapper { 
 	position:relative; 
@@ -47,7 +48,7 @@
 	background-color: red;
 	width: 100px;
 	height: 5px;
-	font-size: 1%;
+	font-size: 1%;/*IE hack to get around the Empty-Div bug*/
 }
 .slideShowSlideShow {
 	position:absolute;
@@ -59,6 +60,10 @@
 }
 .slideShowLoading { background-color: #fad66a; }
 .slideShowLoaded { background-color: transparent; }
+/*
+.sprite-arrowbottom { background-position: 0 -30px; } 
+.sprite-arrowtop { background-position: 0 -430px; } 
+*/
 .slideShowCtrlPrev {
 	background-position: -96px 0px; 
 	float: left;
@@ -79,6 +84,7 @@
 	background-image: url("../../../dojo/resources/blank.gif");
 	cursor: auto;
 }
+
 .slideShowCtrl {
 	height: 50px;
 	width: 100%;
@@ -95,9 +101,11 @@
 .dj_ie .slideShowCtrl span {
 	background-image: url("images/buttons.gif");
 }
+
 .dj_ie6 .slideShowPager li.currentpage,
 .dj_ie6 .pagination li.disablepage{
-    
+    /*IE 6 and below. Adjust non linked LIs slightly to account for bugs*/
     margin-right: 5px;
     padding-right: 0;
 }
+
diff --git a/dojox/image/resources/ThumbnailPicker.css b/dojox/image/resources/ThumbnailPicker.css
index 4356886..54ace0b 100644
--- a/dojox/image/resources/ThumbnailPicker.css
+++ b/dojox/image/resources/ThumbnailPicker.css
@@ -1,3 +1,4 @@
+/* dojox.image.ThumbnailPicker */
 
 .thumbWrapper .thumbNav {
 	background-repeat: no-repeat;	
@@ -6,21 +7,26 @@
 	width: 30px;
 	height: 100%;
 }
+
 .thumbOuter {
 	padding-bottom: 2px;
 }
+
 .thumbOuter.thumbHoriz {
 	width: 500px;
 	height: 85px;
 }
+
 .thumbOuter.thumbVert {
 	width: 100px;
 	height: 400px;
 }
+
 .thumbOuter .enabled {
 	background: transparent url("images/buttons.png") no-repeat center center;
 }
 .dj_ie6 .thumbOuter .enabled { background-image: url("images/buttons.gif"); }
+
 .thumbOuter .thumbNav img {
 	width: 48px;
 	height: 75px;
@@ -34,11 +40,13 @@
 	float: left;
 	height: 100%;
 }
+
 .thumbOuter .nextHoriz {
 	background-position: -144px 12px;
 	position: relative;
 	float: right;
 	height: 100%;
+/*	margin-top: -85px;*/
 }
 .thumbOuter .prevVert {
 	background-position: 0px 0px;
@@ -46,47 +54,57 @@
 	width:48px;
 	margin-left:24px;
 }
+
 .thumbOuter .nextVert {
 	background-position: -48px 0px;
 	height: 48px;
 	width:48px;
 	margin-left:24px;
 }
+
 .thumbWrapper img {
 	height: 75px;
 	max-width: 100px;
-	width: expression(this.width > 100 ? 100: true);
+	width: expression(this.width > 100 ? 100: true);/*IE Hack*/
 }
+
 .thumbWrapper .thumbNav .imageGalleryThumb {
 	height: 50px;
 }
+
 .thumbWrapper .thumbNotifier {
 	background-color: red;
 	width: 0px;
 	margin-left: 2px;
 	height: 5px;
-	font-size: 1%;
+	font-size: 1%;/*IE hack to get around the Empty-Div bug*/
 }
+
 .thumbWrapper .thumbLoaded {
 	background-color: transparent;	
 }
+
 .thumbScroller {
 	overflow-x: hidden;
 	overflow-y: hidden;
 	text-align: center;
 }
+
 .thumbHoriz .thumbScroller {
 	width: 500px;
 	height: 85px;
 	float: left;
 }
+
 .thumbVert .thumbScroller {
 	height: 500px;
 	width: 100px;	
 }
+
 .thumbWrapper {
 	float: left;
 }
+
 .thumbVert .thumbWrapper {
 	width: 100px;
 	height: 10px;
@@ -95,13 +113,17 @@
 	height:85px;
 	width: 10px;
 }
+
 .thumbWrapper.thumbHoriz div {
 	float: left;
 	padding-right: 2px;
 }
+
 .thumbWrapper.thumbVert {
 	width: 100px;
 }
+
 .thumbWrapper.thumbVert div {
 	padding-bottom: 2px;
 }
+
diff --git a/dojox/image/resources/image.css b/dojox/image/resources/image.css
index 0e3411d..c4ea0a2 100644
--- a/dojox/image/resources/image.css
+++ b/dojox/image/resources/image.css
@@ -1,328 +1,16 @@
+/*
+	This is the master CSS file for the dojox.image project, and provides all
+	needed definitions for the DojoX Image Project
+
+	Before build, the files are individual. You can use image.css as a cacheable
+	single-file rollup, or link only the individual css you need (based on componenet
+	name)
+
+*/
+ at import "Lightbox.css";
+ at import "SlideShow.css";
+ at import "ThumbnailPicker.css";
+ at import "Gallery.css";
+ at import "Badge.css";
+ at import "Magnifier.css";
 
-.dijitDialogUnderlay {
-	background-color:#000; 
-}
-.dojoxLightbox {
-	position:absolute;
-	z-index:999;
-	overflow:hidden;
-	width:100px;
-	height:100px; 
-	border:11px solid #fff;
-	background:#fff url(images/loading.gif) no-repeat center center;
-        
-	-webkit-box-shadow: 0px 6px 10px #636363; 
-	-webkit-border-radius: 3px;
-	-moz-border-radius:4px;
-        border-radius: 4px;
-}
-.dojoxLightboxContainer {
-	position:absolute;
-	top:0; left:0; 
-}
-.dojoxLightboxFooter {
-	padding-bottom:5px;
-	position:relative;
-	bottom:0;
-	left:0;
-	margin-top:8px;
-	color:#333;
-	z-index:1000;
-	font-size:10pt;
-}
-.dojoxLightboxGroupText {
-	color:#666; 
-	font-size:8pt;
-}
-.LightboxNext,
-.LightboxPrev,
-.LightboxClose {
-	float:right;
-	width:16px;
-	height:16px;
-	cursor:pointer;
-}
-.nihilo .LightboxClose,
-.tundra .LightboxClose {
-	background:url(images/close.png) no-repeat center center;
-}
-.di_ie6 .nihilo .LightboxClose,
-.dj_ie6 .tundra .LightboxClose {
-	background:url(images/close.gif) no-repeat center center;
-}
-.nihilo .LightboxNext,
-.tundra .LightboxNext {
-	background:url(images/right.png) no-repeat center center;
-}
-.dj_ie6 .nihilo .LightboxNext,
-.dj_ie6 .tundra .LightboxNext {
-	background:url(images/right.gif) no-repeat center center;
-}
-.nihilo .LightboxPrev,
-.tundra .LightboxPrev {
-	background:url(images/left.png) no-repeat center center;
-}
-.dj_ie6 .nihilo .LightboxPrev,
-.dj_ie6 .tundra .LightboxPrev {
-	background:url(images/left.gif) no-repeat center center;
-}
-.soria .LightboxClose,
-.soria .LightboxNext,
-.soria .LightboxPrev {
-	width:15px;
-	height:15px;
-	background:url(../../../dijit/themes/soria/images/spriteRoundedIconsSmall.png) no-repeat center center;
-	background-position:-60px;
-}
-.soria .LightboxNext {
-	background-position:-30px 0;
-}
-.soria .LightboxPrev {
-	background-position:0 0;
-}
-.slideShowWrapper { 
-	position:relative; 
-	background:#fff;
-	padding:8px; 
-	border:1px solid #333;	
-	padding-bottom:20px;
-	overflow:hidden;
-	-moz-border-radius:3pt;
-	-webkit-border-radius:4pt;
-	-webkit-drop-shadow:#ccc 4pt; 
-}
-.slideShowNav { 
-	position:absolute;
-	bottom:-18px;	
-	left:0px;
-	padding:0px 3px 2px 0px;
-	background-color:#fff; 
-	width:100%;
-}
-.slideShowNavWrapper { float:right;  }
-.slideShowTitle {
-	float:left;
-	color:#333;
-	font-size:10pt;
-}
-.slideShowTitle .slideShowCounterText {
-	font-size:6pt; color:#666; 
-}
-.slideShowHidden {
-	position:absolute;
-	display: none;
-	height: 1px;
-	width: 1px;
-}
-.slideShowImageWrapper {
-	position:relative;
-	text-align: center;
-	margin-top: -42px;
-	float: left;
-	width: 100%;
-}
-.slideShowImageWrapper img {
-	border: 0px none;
-}
-.slideShowNotifier {
-	background-color: red;
-	width: 100px;
-	height: 5px;
-	font-size: 1%;
-}
-.slideShowSlideShow {
-	position:absolute;
-	top:30px; 
-	padding: 0 5px;
-	border: 0px;
-	text-decoration: none; 
-	color: #2e6ab1;
-}
-.slideShowLoading { background-color: #fad66a; }
-.slideShowLoaded { background-color: transparent; }
-.slideShowCtrlPrev {
-	background-position: -96px 0px; 
-	float: left;
-}
-.slideShowCtrlNext {
-	background-position: -144px 0px;
-	float: right;
-}
-.slideShowCtrlPlay {
-	background-position: -190px 0px;
-	position: absolute;
-}
-.slideShowPaused .slideShowCtrlPlay {
-	background-position: -236px 0px;
-	position: absolute;
-}
-.slideShowCtrl span.slideShowCtrlHide {
-	background-image: url(../../../dojo/resources/blank.gif);
-	cursor: auto;
-}
-.slideShowCtrl {
-	height: 50px;
-	width: 100%;
-	position: relative;
-	z-index:999;
-	float: left;
-}
-.slideShowCtrl span {
-	width: 50px;
-	height: 100%;
-	background-image: url(images/buttons.png);
-	cursor: pointer;
-}
-.dj_ie .slideShowCtrl span {
-	background-image: url(images/buttons.gif);
-}
-.dj_ie6 .slideShowPager li.currentpage,
-.dj_ie6 .pagination li.disablepage{
-    
-    margin-right: 5px;
-    padding-right: 0;
-}
-.thumbWrapper .thumbNav {
-	background-repeat: no-repeat;	
-	background-position: center;
-	padding-top: 1px;
-	width: 30px;
-	height: 100%;
-}
-.thumbOuter {
-	padding-bottom: 2px;
-}
-.thumbOuter.thumbHoriz {
-	width: 500px;
-	height: 85px;
-}
-.thumbOuter.thumbVert {
-	width: 100px;
-	height: 400px;
-}
-.thumbOuter .enabled {
-	background: transparent url(images/buttons.png) no-repeat center center;
-}
-.dj_ie6 .thumbOuter .enabled { background-image: url(images/buttons.gif); }
-.thumbOuter .thumbNav img {
-	width: 48px;
-	height: 75px;
-}
-.thumbOuter .thumbClickable div {
-	cursor: pointer;
-}
-.thumbOuter .prevHoriz {
-	background-position: -96px 12px;
-	position: relative;
-	float: left;
-	height: 100%;
-}
-.thumbOuter .nextHoriz {
-	background-position: -144px 12px;
-	position: relative;
-	float: right;
-	height: 100%;
-}
-.thumbOuter .prevVert {
-	background-position: 0px 0px;
-	height: 48px;
-	width:48px;
-	margin-left:24px;
-}
-.thumbOuter .nextVert {
-	background-position: -48px 0px;
-	height: 48px;
-	width:48px;
-	margin-left:24px;
-}
-.thumbWrapper img {
-	height: 75px;
-	max-width: 100px;
-	width: expression(this.width > 100 ? 100: true);
-}
-.thumbWrapper .thumbNav .imageGalleryThumb {
-	height: 50px;
-}
-.thumbWrapper .thumbNotifier {
-	background-color: red;
-	width: 0px;
-	margin-left: 2px;
-	height: 5px;
-	font-size: 1%;
-}
-.thumbWrapper .thumbLoaded {
-	background-color: transparent;	
-}
-.thumbScroller {
-	overflow-x: hidden;
-	overflow-y: hidden;
-	text-align: center;
-}
-.thumbHoriz .thumbScroller {
-	width: 500px;
-	height: 85px;
-	float: left;
-}
-.thumbVert .thumbScroller {
-	height: 500px;
-	width: 100px;	
-}
-.thumbWrapper {
-	float: left;
-}
-.thumbVert .thumbWrapper {
-	width: 100px;
-	height: 10px;
-}
-.thumbHoriz .thumbWapper {
-	height:85px;
-	width: 10px;
-}
-.thumbWrapper.thumbHoriz div {
-	float: left;
-	padding-right: 2px;
-}
-.thumbWrapper.thumbVert {
-	width: 100px;
-}
-.thumbWrapper.thumbVert div {
-	padding-bottom: 2px;
-}
-.imageGalleryWrapper {
-	padding-bottom: 20px;
-	text-align: center;
-}
-.dojoxBadge {
-	position:relative;
-}
-.dojoxBadge .dojoxBadgeImage {
-	position:absolute;
-	top:0; left:0;
-	margin:0;
-	padding:0;
-}
-.dojoxBadge {
-	margin:0; padding:0;
-	border:1px solid #eee;
-}
-.dojoxBadge .dojoxBadgeImage {
-	overflow:hidden;
-	margin-left:1px;
-	margin-top:1px;
-	background:#ededed;
-	z-index:90;
-}
-.dojoxBadge .dojoxBadgeSeen {
-	background-color:#dedede;
-}
-.dojoxBadge .dojoxBadgeOver {
-	background-color:green !important;
-}
-.dojoxBadge .dojoxBadgeTop {
-	z-index:99;
-}
-.glassNode {
-	overflow:hidden;
-	position:absolute;
-	visibility:hidden;
-}
diff --git a/dojox/image/resources/images/close.gif b/dojox/image/resources/images/close.gif
old mode 100644
new mode 100755
diff --git a/dojox/image/resources/images/close.png b/dojox/image/resources/images/close.png
old mode 100644
new mode 100755
diff --git a/dojox/image/resources/images/close_dark.png b/dojox/image/resources/images/close_dark.png
old mode 100644
new mode 100755
diff --git a/dojox/image/resources/images/left.gif b/dojox/image/resources/images/left.gif
old mode 100644
new mode 100755
diff --git a/dojox/image/resources/images/left.png b/dojox/image/resources/images/left.png
old mode 100644
new mode 100755
diff --git a/dojox/image/resources/images/loading.gif b/dojox/image/resources/images/loading.gif
old mode 100644
new mode 100755
diff --git a/dojox/image/resources/images/right.gif b/dojox/image/resources/images/right.gif
old mode 100644
new mode 100755
diff --git a/dojox/image/resources/images/right.png b/dojox/image/resources/images/right.png
old mode 100644
new mode 100755
diff --git a/dojox/image/tests/Lightbox.html b/dojox/image/tests/Lightbox.html
new file mode 100644
index 0000000..2b80dc3
--- /dev/null
+++ b/dojox/image/tests/Lightbox.html
@@ -0,0 +1,184 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+	
+	<title>Sample Dojo / Dijit Page</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../resources/Lightbox.css";
+		#container {
+			position:absolute;
+			left:-9999px;
+			width:9000px;
+			overflow:hidden;
+		}
+		#randomimage {
+			height:100px;
+		}
+	</style>
+	<script>var djConfig = { isDebug:true, parseOnLoad:true }</script>
+	<script src="../../../dojo/dojo.js"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojo.parser");
+		dojo.require("dojox.image.Lightbox");
+		
+		dojo.addOnLoad(function(){
+			
+			doh.register("testUi",
+				[
+					{
+						name:"basic lightbox",
+						timeout:7000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							var lb = dijit.byId("parsed");
+							t.is("dojox.image.Lightbox", lb.declaredClass);
+
+							setTimeout(function(){
+								lb.show();
+							}, 300);
+						
+							setTimeout(function(){
+								lb.hide();
+								d.callback(true);
+							}, lb.duration + 1700);
+
+							return d;
+						}
+					},
+					{
+						name:"basic onclick",
+						timeout:7000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							var lb = dijit.byId("parsed");
+							
+							t.is("basic title", lb.title);
+							var c = dojo.connect(lb, "show", function(){
+								lb.hide();
+								dojo.disconnect(c);
+								d.callback(true);
+							});
+							
+							dojo.query("a").at(0).forEach(function(n){
+								dojo._triggerEvent(n, "click");
+							});
+							
+							return d;
+						}
+					},
+					{
+						name:"basic programatic",
+						timeout:7000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							var lb = new dojox.image.Lightbox({
+								href:"images/square.png",
+								title:"A square image"
+							}).placeAt(dojo.body());
+							
+							lb.startup();
+							lb.show();
+							
+							t.is("A square image", lb.title);
+							t.is("dojox.image.LightboxDialog", dijit.byId("dojoxLightboxDialog").declaredClass);
+							
+							setTimeout(function(){
+								lb.hide();
+								d.callback(true);
+							}, lb.duration + 500);
+							
+							return d;
+						}
+					},
+					{
+						name:"show single in master",
+						timeout:5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							var lb = dijit.byId("dojoxLightboxDialog");
+							lb.show({
+								href:"images/extraWide.jpg",
+								title:"Wiiiide"
+							});
+							
+							setTimeout(function(){
+								lb.hide();
+								d.callback(true);
+							}, lb.duration + 1500);
+							
+							return d;
+						}
+					},
+					{
+						name:"basic group ui",
+						timeout:15000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							var l = dijit.byId("grouper"),
+								lb = l._attachedDialog;
+							
+							t.is("bar", l.group);
+							l.show();
+							
+							var next = lb.nextButtonNode, prev = lb.prevButtonNode, 
+								close = lb.closeButtonNode;
+							
+							var c = dojo.connect(lb, "hide", function(){
+								dojo.disconnect(c);
+								d.callback(true);
+							});
+								
+							setTimeout(function(){
+								dojo._triggerEvent(next, "click");
+								setTimeout(function(){
+									dojo._triggerEvent(prev, "click");
+									setTimeout(function(){
+										// note: calling trigger("click") on closeNode
+										// makes hide() called out of scope?
+										l.hide();
+									}, l.duration)
+								}, l.duration);
+							
+							}, l.duration + 400);
+							
+							return d;
+						}
+					}
+				]
+			);
+			
+			doh.run();		
+		
+		});
+		
+		// stolen from plugd (http://code.google.com/p/plugd/) to trigger basic events:
+		(function(d){
+			d._triggerEvent = function(node, event){
+				// summary: Helper for `dojo.trigger`, which handles the DOM cases. We should never
+				// be here without a nodeNode reference and a string eventname.
+				node = d.byId(node); 
+				event = event && event.slice(0, 2) == "on" ? event.slice(2) : event;
+				if(d.doc.createEvent){
+					var evObj = d.doc.createEvent("HTMLEvents");
+					evObj.initEvent(event, true, true);
+					node.dispatchEvent(evObj);
+				}else if(d.doc.createEventObject){
+					node.fireEvent("on" + event);
+				}
+			}
+		})(dojo);
+		
+	</script>
+
+</head>
+<body class="tundra">
+	<a href="images/square.jpg" id="parsed" title="basic title" dojoType="dojox.image.Lightbox">test</a>
+	<a href="images/square.jpg" id="grouper" group="bar" dojoType="dojox.image.Lightbox">testgroup</a>
+	<a href="images/square.jpg" group="bar" dojoType="dojox.image.Lightbox">testgroup</a>
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/image/tests/images.json b/dojox/image/tests/images.json
new file mode 100644
index 0000000..bd0cf96
--- /dev/null
+++ b/dojox/image/tests/images.json
@@ -0,0 +1,32 @@
+{ items: [
+	{
+	  "thumb":"images/extraWide.jpg",
+	  "large":"images/extraWide.jpg",
+	  "title":"I'm wide, me",
+	  "link":"http://www.flickr.com/photos/44153025@N00/748348847"
+	},
+	{
+	 "thumb":"images/imageHoriz.jpg",
+	  "large":"images/imageHoriz.jpg",
+	  "title":"I'm a horizontal picture",
+	  "link":"http://www.flickr.com/photos/44153025@N00/735656038"
+	},
+	{
+	  "thumb":"images/imageHoriz2.jpg",
+	  "large":"images/imageHoriz2.jpg",
+	  "title":"I'm another horizontal picture",
+	  "link":"http://www.flickr.com/photos/44153025@N00/714540483"
+	},
+	{
+	 "thumb":"images/imageVert.jpg",
+	  "large":"images/imageVert.jpg",
+	  "title":"I'm a vertical picture",
+	  "link":"http://www.flickr.com/photos/44153025@N00/715392758"
+	},
+	{
+	 "large":"images/square.jpg",
+	 "thumb":"images/square.jpg",
+	 "link" :"images/square.jpg",
+	 "title":"1:1 aspect ratio"
+	}
+]}
\ No newline at end of file
diff --git a/dojox/image/tests/images/chris1_lg.jpg b/dojox/image/tests/images/chris1_lg.jpg
new file mode 100644
index 0000000..8999f0a
Binary files /dev/null and b/dojox/image/tests/images/chris1_lg.jpg differ
diff --git a/dojox/image/tests/images/chris1_sm.jpg b/dojox/image/tests/images/chris1_sm.jpg
new file mode 100644
index 0000000..1ed8a5f
Binary files /dev/null and b/dojox/image/tests/images/chris1_sm.jpg differ
diff --git a/dojox/image/tests/images/chris2_lg.jpg b/dojox/image/tests/images/chris2_lg.jpg
new file mode 100644
index 0000000..fca25d3
Binary files /dev/null and b/dojox/image/tests/images/chris2_lg.jpg differ
diff --git a/dojox/image/tests/images/chris2_sm.jpg b/dojox/image/tests/images/chris2_sm.jpg
new file mode 100644
index 0000000..88e60ed
Binary files /dev/null and b/dojox/image/tests/images/chris2_sm.jpg differ
diff --git a/dojox/image/tests/images/chris3_lg.jpg b/dojox/image/tests/images/chris3_lg.jpg
new file mode 100644
index 0000000..d7ccc70
Binary files /dev/null and b/dojox/image/tests/images/chris3_lg.jpg differ
diff --git a/dojox/image/tests/images/chris3_sm.jpg b/dojox/image/tests/images/chris3_sm.jpg
new file mode 100644
index 0000000..5490ff5
Binary files /dev/null and b/dojox/image/tests/images/chris3_sm.jpg differ
diff --git a/dojox/image/tests/images/enlarge.png b/dojox/image/tests/images/enlarge.png
new file mode 100644
index 0000000..f060286
Binary files /dev/null and b/dojox/image/tests/images/enlarge.png differ
diff --git a/dojox/image/tests/images/extraWide.jpg b/dojox/image/tests/images/extraWide.jpg
new file mode 100755
index 0000000..2161825
Binary files /dev/null and b/dojox/image/tests/images/extraWide.jpg differ
diff --git a/dojox/image/tests/images/huuuge.png b/dojox/image/tests/images/huuuge.png
new file mode 100644
index 0000000..ee98a39
Binary files /dev/null and b/dojox/image/tests/images/huuuge.png differ
diff --git a/dojox/image/tests/images/imageHoriz.jpg b/dojox/image/tests/images/imageHoriz.jpg
new file mode 100755
index 0000000..3948416
Binary files /dev/null and b/dojox/image/tests/images/imageHoriz.jpg differ
diff --git a/dojox/image/tests/images/imageHoriz2.jpg b/dojox/image/tests/images/imageHoriz2.jpg
new file mode 100755
index 0000000..fbbf404
Binary files /dev/null and b/dojox/image/tests/images/imageHoriz2.jpg differ
diff --git a/dojox/image/tests/images/imageVert.jpg b/dojox/image/tests/images/imageVert.jpg
new file mode 100755
index 0000000..1652338
Binary files /dev/null and b/dojox/image/tests/images/imageVert.jpg differ
diff --git a/dojox/image/tests/images/loading-dark.gif b/dojox/image/tests/images/loading-dark.gif
new file mode 100644
index 0000000..2a76bc5
Binary files /dev/null and b/dojox/image/tests/images/loading-dark.gif differ
diff --git a/dojox/image/tests/images/spanke.jpg b/dojox/image/tests/images/spanke.jpg
new file mode 100644
index 0000000..ec95fb0
Binary files /dev/null and b/dojox/image/tests/images/spanke.jpg differ
diff --git a/dojox/image/tests/images/square.jpg b/dojox/image/tests/images/square.jpg
new file mode 100755
index 0000000..f8b6761
Binary files /dev/null and b/dojox/image/tests/images/square.jpg differ
diff --git a/dojox/image/tests/module.js b/dojox/image/tests/module.js
new file mode 100644
index 0000000..82b86cb
--- /dev/null
+++ b/dojox/image/tests/module.js
@@ -0,0 +1,13 @@
+dojo.provide("dojox.image.tests.module");
+
+try{
+
+	doh.registerUrl("dojox.image.tests._base", dojo.moduleUrl("dojox.image.tests", "test_base.html"));
+	doh.registerUrl("dojox.image.tests.Lightbox", dojo.moduleUrl("dojox.image.tests", "Lightbox.html"));
+	doh.registerUrl("dojox.image.tests.onloads", dojo.moduleUrl("dojox.image.tests", "onloads.html"));
+	
+}catch(e){
+	doh.debug(e);
+}
+
+
diff --git a/dojox/image/tests/onloads.html b/dojox/image/tests/onloads.html
new file mode 100644
index 0000000..35826e0
--- /dev/null
+++ b/dojox/image/tests/onloads.html
@@ -0,0 +1,317 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+	
+	<title>Sample Dojo / Dijit Page</title>
+	<style type="text/css">
+		#container {
+			position:absolute;
+			left:-9999px;
+			width:9000px;
+			overflow:hidden;
+		}
+		#randomimage {
+			height:100px;
+		}
+	</style>
+	<!-- load Dojo -->
+	<script>var djConfig = { isDebug:true }</script>
+	<script src="../../../dojo/dojo.js"></script>
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.addOnLoad(function(){
+			
+			doh.register("testUi",
+				[
+					{
+						name:"basic onload",
+						timeout:7000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							try{
+								var n = dojo.create("img", null, "container");
+							}catch(e){
+								d.errback(e);
+							}
+							dojo.connect(n, "onload", function(e){
+								try{
+									t.is("load", e.type);
+									t.is(359, n.height, "height mismatch");
+									t.is(359, n.width, "width mismatch");
+								}catch(e){
+									d.errback(e);
+									return;
+								}
+								d.callback(true);
+							});
+							
+							n.src = "images/square.jpg";
+							return d;
+						}
+					},
+					{
+						name:"basic onload, probably cached",
+						timeout:17000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							try{
+								var n = dojo.create("img", null, "container");
+							}catch(e){
+								d.errback(e);
+							}
+							dojo.connect(n, "onload", function(e){
+								try{
+									t.is("load", e.type);
+									t.is(359, n.height);
+									t.is(359, n.width);
+								}catch(e){
+									d.errback(e);
+									return;
+								}
+								d.callback(true);
+							});
+							n.src = "images/square.jpg";
+							
+							return d;
+						}
+					},
+					{
+						name:"set src after long delay",
+						timeout:5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							var n = dojo.place("<img id='bar'/>", "container");
+							dojo.connect(n, "onload", function(){
+								t.is(375, n.height);
+								t.is(500, n.width);
+								d.callback(true);
+							})
+							
+							setTimeout(function(){
+								n.src = "images/chris1_lg.jpg";
+							}, 2000)
+							
+							return d;
+						}
+					},
+					{
+						name:"test re-calling of onload",
+						timeout:9000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							var called = 0;
+							var n = dojo.create("img", null, "container");
+							
+							dojo.connect(n, "onload", function(e){
+								called++;
+								if(called == 2){
+									d.callback(true);
+								}
+							});
+
+							n.src = "images/chris1_sm.jpg";
+							
+							setTimeout(function(){
+								n.src = "images/chris1_sm.jpg?" + (new Date().getTime());
+							}, 1000);
+							
+							return d;
+						}
+					},
+					{
+						name:"testing the sizes, styled by js (height)",
+						timeout:9000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+								var newn = dojo.create("img", null, "container");
+								dojo.style(newn, "height", "100px");
+								
+								dojo.connect(newn, "onload", function(e){
+									try{
+										t.is(100, newn.height);
+										t.is(100, newn.width);
+										d.callback(true);
+									}catch(e){
+										d.errback(e);
+									}
+								});
+								newn.src = "images/square.jpg";
+								
+								
+							return d;
+						}
+					},
+					{
+						name:"testing the sizes, styled by js (width)",
+						timeout:9000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+								var newn = dojo.create("img", null, "container");
+								dojo.style(newn, "width", "100px");
+								
+								dojo.connect(newn, "onload", function(e){
+									try{
+										t.is(100, newn.height);
+										t.is(100, newn.width);
+										d.callback(true);
+									}catch(e){
+										d.errback(e);
+									}
+								});
+								newn.src = "images/square.jpg";
+								
+							return d;
+						}
+					},
+					{
+						name:"testing the sizes, styled by js (both)",
+						timeout:9000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+								var newn = dojo.create("img", null, "container");
+								dojo.style(newn, { "height":"100px", "width":"100px" });
+								
+								dojo.connect(newn, "onload", function(e){
+									try{
+										t.is(100, newn.height);
+										t.is(100, newn.width);
+										d.callback(true);
+									}catch(e){
+										d.errback(e);
+									}
+								});
+								newn.src = "images/square.jpg";
+								
+								
+							return d;
+						}
+					},
+//					{
+//						name:"testing the sizes, styled by css (no .src)",
+//						timeout:9000,
+//						runTest: function(t){
+//							var d = new doh.Deferred();
+//							
+//								var newn = dojo.byId("randomimage");
+//								dojo.connect(newn, "onload", function(e){
+//									try{
+//										t.is(100, newn.height);
+//										t.is(100, newn.width);
+//										d.callback(true);
+//									}catch(e){
+//										d.errback(e);
+//									}
+//								});
+//								
+//								// janky here?:
+//								setTimeout(function(){
+//									if(dojo.isOpera){
+//										d.callback("expecting opera not to fire onload?");
+//									}
+//								}, 8500)
+//								
+//							return d;
+//						}
+//					},
+//					{
+//						name:"testing the sizes, styled by css (set .src)",
+//						timeout:9000,
+//						runTest: function(t){
+//							var d = new doh.Deferred();
+//							
+//								var newn = dojo.byId("randomimage");
+//								dojo.connect(newn, "onload", function(e){
+//									try{
+//										t.is(100, newn.height);
+//										t.is(100, newn.width);
+//										d.callback(true);
+//									}catch(e){
+//										d.errback(e);
+//									}
+//								});
+//								newn.src = "images/square.jpg";
+//								
+//							return d;
+//						}
+//					},
+					{
+						name:"testing the sizes, styled by attr ",
+						timeout:9000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							var newn = dojo.byId("randomimage");
+							dojo.connect(newn, "onload", function(e){
+								try{
+									t.is(100, newn.height);
+									t.is(100, newn.width);
+									d.callback(true);
+								}catch(e){
+									d.errback(e);
+								}
+							});
+							newn.height = 100;
+							newn.src = "images/square.jpg";
+								
+							return d;
+						}
+					},
+					{
+						
+						name:"load event does not bubble",
+						timeout:4000,
+						runTest: function(t){
+
+							var d = new doh.Deferred();
+
+							var bubbles; // it doesn't bubble, btw.
+							var c = dojo.byId("container2")
+							var x = dojo.connect(c, "load", function(){
+								d.errback("Should not fire");
+								dojo.disconnect(x);
+							});
+							
+							dojo.create("img", { src:"images/square.jpg" }, "container2");
+							setTimeout(function(){
+								dojo.disconnect(x);
+								d.callback(true);
+							}, 3000);
+							
+							return d;
+						}
+						
+					}
+				]
+			);
+			
+			doh.run();	
+			
+//			
+//			var setimg = dojo.create("img", { src:"../rockstar.jpg" });
+//			setimg.width = 175;
+//			dojo.connect(setimg, "onload", function(e){
+//				console.log("attr'd onload", img.height, dojo.style(img, "height"), img.offsetHeight, img.naturalHeight);
+//			});
+//			
+			
+		});
+	</script>
+
+</head>
+<body class="tundra">
+	<h2>These tests are all expected to take a long time (image loading)</h2>
+	<p>Some of them might fail</p>
+	<div id="container">
+		<div id="container2"></div>
+	</div>
+	<img id="randomimage" src="images/square.jpg">
+	<img id="fixedimage">
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/image/tests/runTests.html b/dojox/image/tests/runTests.html
new file mode 100644
index 0000000..6e523e7
--- /dev/null
+++ b/dojox/image/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+	<head>
+	<title>Dojox Widget Unit Test Runner</title>
+	<meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.image.tests.module"></HEAD>
+	<BODY>
+		Redirecting to D.O.H runner.
+	</BODY>
+</HTML> 
diff --git a/dojox/image/tests/test_Badge.html b/dojox/image/tests/test_Badge.html
new file mode 100644
index 0000000..f550693
--- /dev/null
+++ b/dojox/image/tests/test_Badge.html
@@ -0,0 +1,234 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.image.Badge Tests | The Dojo Toolkit</title>
+
+	<!-- required: a default theme file, and project css: -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css" />
+	<link rel="stylesheet" href="../resources/image.css" />
+	
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		body, html { width:100%; height:100%; margin:0; padding:0; } 
+
+		.fixed { 
+			position:fixed;
+			font:32pt Arial,sans-serif;
+			color:#777;
+			text-align:center;
+			line-height:42px;
+		}
+		.dj_ie .fixed {
+			display:none;
+		}
+		img.thing { width:50px; height:50px; }
+		.noBorderWrapper .dojoxBadge {
+			border:none;
+		}
+		
+		.b1 { background:url('images/square.jpg') !important; }
+		.b2 { background-image:url('images/imageHoriz.jpg') !important; }
+		.b3 { background-image:url('images/imageVert.jpg') !important; }
+		.b4 { background-image:url('images/imageHoriz2.jpg') !important; }
+	</style>
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../Badge.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.image.Badge"); 
+		dojo.require("dojox.data.FlickrStore");
+	</script>
+
+	<!--script type="text/javascript">
+		// programatic flickrstore implementation [basic]
+		function onComplete(items,request){
+			if (items.length>0){
+				dojo.forEach(items,function(item){
+					var part = {
+						title: flickrStore.getValue(item,"title"),
+						href: flickrStore.getValue(item,"imageUrl")
+					};
+					// FIXME: make addImage more accessible, or do this internally
+					// _attachedDialog is dijit.byId("dojoxLightboxDialog"), and the
+					// is only one per page.
+					dijit.byId('fromStore')._attachedDialog.addImage(part,"flickrStore");
+				});
+				dojo.byId('flickrButton').disabled = false; 
+			}
+		}
+
+		function onError(error,request){
+			console.warn(error,request);
+		}
+
+		function init(){
+			var flickrRequest = {
+				query: {},
+				onComplete: onComplete,
+				onError: onError,
+				userid: "jetstreet",
+				tags: "jetstreet",
+				count: 10
+			};
+			flickrStore.fetch(flickrRequest);
+		}
+		dojo.addOnLoad(init);
+	</script-->
+
+
+</head>
+<body class="tundra">
+
+	<div style="padding:20px;">
+		
+		<h1 class="testTitle">a Dojo based Badge thingr:</h1>
+		
+			<h3>[2x2] From IMG</h3>
+			<div dojoType="dojox.image.Badge" rows="2" cols="2" children="img.thing">
+				<img src="images/square.jpg" class="thing" alt="thingr" />
+				<img src="images/square.jpg" class="thing" alt="thingr" />
+				<img src="images/square.jpg" class="thing" alt="thingr" />
+				<img src="images/square.jpg" class="thing" alt="thingr" />			
+			</div>
+		
+			<h3>[4x3]</h3>	
+			<div dojoType="dojox.image.Badge" rows="3" cols="4" cellSize="50">
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+			
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+			
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+			</div>
+
+
+		<h3>[3x4] Grid, delay:2500</h3>
+
+		<div dojoType="dojox.image.Badge" delay="4000" rows="4" cols="3" style="width:150px; height:200px">
+			<div class="dojoxBadgeImage"></div>
+			<div class="dojoxBadgeImage"></div>
+			<div class="dojoxBadgeImage"></div>
+			<div class="dojoxBadgeImage"></div>
+			
+			<div class="dojoxBadgeImage"></div>
+			<div class="dojoxBadgeImage"></div>
+			<div class="dojoxBadgeImage"></div>
+			<div class="dojoxBadgeImage"></div>
+			
+			<div class="dojoxBadgeImage"></div>
+			<div class="dojoxBadgeImage"></div>
+			<div class="dojoxBadgeImage"></div>
+			<div class="dojoxBadgeImage"></div>
+		</div>
+
+		<div style="position:absolute; top:100px; left:275px">
+			<h2>[6x2] Picker, in absolute node</h2>
+			<div dojoType="dojox.image.Badge" rows="2" cols="6">
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+			
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+			
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div>
+			</div>
+			
+			<h2>[3x2] But only 3 images</h2>
+			<div class="noBorderWrapper">
+				<div dojoType="dojox.image.Badge" cellSize="150" rows="2" cols="3">
+					<div class="dojoxBadgeImage b1"></div>
+					<div class="dojoxBadgeImage b2"></div>
+					<div class="dojoxBadgeImage b3"></div>
+				</div>
+			</div>
+			
+		</div>
+
+		<h3>position:fixed;</h3>
+		<ul>
+			<li>Does not work in IE6. At all. There are docType hacks if you choose. </li>
+		</ul>
+		<div dojoType="dojox.image.Badge" children="div" rows="6" cols="2" class="fixed" style="top:0; right:0">
+			<div>a</div>
+			<div>b</div>
+			<div>c</div>
+			<div>d</div>
+		        
+			<div>e</div>
+			<div>f</div>
+			<div>g</div>
+			<div>h</div>
+		        
+			<div>i</div>
+			<div>j</div>
+			<div>k</div>
+			<div>l</div>
+		</div>
+
+		<h2>[6x6] threads:3</h2>
+		<div class="noBorderWrapper">
+			<div dojoType="dojox.image.Badge" threads="2" rows="6" cols="6">
+				<div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div>
+				<div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div><div class="dojoxBadgeImage"></div>
+			</div>
+		</div>
+		
+		<div id="prog"></div>
+		<!--div dojoType="dojox.image.Badge">
+
+			<a href="images/imageVert.jpg" dojoType="dojox.image.Lightbox" title="More Guatemala...">tall</a>
+			<a href="images/imageHoriz.jpg" dojoType="dojox.image.Lightbox" title="Antigua, Guatemala">4:3 image</a>
+			<a href="images/broken.jpg" dojoType="dojox.image.Lightbox" title="broken href example">Broken link</a>
+
+			<a href="images/huuuge.png" dojoType="dojox.image.Lightbox" title="a large image">large than viewport?</a>
+			<a href="images/imageHoriz2.jpg" dojoType="dojox.image.Lightbox" group="group1" title="Amsterdam Train Depot">wide image</a>
+			<a href="images/square.jpg" dojoType="dojox.image.Lightbox" group="group1" title="1:1 aspect">square</a>
+
+			<a href="images/extraWide.jpg" dojoType="dojox.image.Lightbox" group="group1" title="Greeneville, TN">wide image</a>
+			<a href="images/broken.jpg" dojoType="dojox.image.Lightbox" group="group1" title="broken href example">Broken link</a>
+			<a href="images/imageHoriz2.jpg" dojoType="dojox.image.Lightbox" group="group2" title="Amsterdam Train Depot">wide image</a>
+
+			<a href="images/square.jpg" dojoType="dojox.image.Lightbox" group="group2" title="1:1 aspect">square</a>
+			<a href="images/imageHoriz.jpg" dojoType="dojox.image.Lightbox" group="group2" title="Antigua, Guatemala">4:3 image</a>
+			<a href="images/imageVert.jpg" dojoType="dojox.image.Lightbox" group="group2" title="More Guatemala...">tall</a>
+
+		</div-->
+
+		<!--h3>From dojox.data.FlickrStore:</h3>
+
+		<div dojoType="dojox.data.FlickrStore" jsId="flickrStore" label="title"></div>
+		<div id="fromStore" dojoType="dojox.image.Lightbox" store="flickrStore" group="flickrStore"></div>
+
+		<input id="flickrButton" type="button" onclick="dijit.byId('fromStore').show()" value="show flickr lightbox" disabled="disabled" -->
+	
+	</div>
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_FlickrBadge.html b/dojox/image/tests/test_FlickrBadge.html
new file mode 100644
index 0000000..2b4bb27
--- /dev/null
+++ b/dojox/image/tests/test_FlickrBadge.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.image.FlickrBadge Tests | The Dojo Toolkit</title>
+
+	<!-- required: a default theme file, and project css: -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css" />
+	<link rel="stylesheet" href="../resources/image.css" />
+	
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		body, html { width:100%; height:100%; margin:0; padding:0; } 
+
+		.fixed { 
+			position:fixed;
+			font:32pt Arial,sans-serif;
+			color:#777;
+			text-align:center;
+			line-height:42px;
+		}
+		.dj_ie .fixed {
+			display:none;
+		}
+		img.thing { width:50px; height:50px; }
+		.noBorderWrapper .dojoxBadge {
+			border:none;
+		}
+		
+		.b1 { background:url('images/square.jpg') !important; }
+		.b2 { background-image:url('images/imageHoriz.jpg') !important; }
+		.b3 { background-image:url('images/imageVert.jpg') !important; }
+		.b4 { background-image:url('images/imageHoriz2.jpg') !important; }
+	</style>
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../Badge.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.image.FlickrBadge"); 
+	</script>
+
+</head>
+<body class="tundra">
+
+	<div style="padding:20px;">
+		<h2>FlickrBadge: Dylan's photos</h2>
+		<div class="noBorderWrapper">
+			<div dojoType="dojox.image.FlickrBadge" rows="6" cols="6" username="dylans"></div>
+		</div>
+
+		<h2>FlickrBadge: Dylan's tagged photos ('dojotoolkit' and 'italy')</h2>
+		<div class="noBorderWrapper">
+			<div dojoType="dojox.image.FlickrBadge" rows="3" cols="6" username="dylans" tags="dojotoolkit,italy"></div>
+		</div>
+		
+		<h2>FlickrBadge: Dylan's Chicago set with popup</h2>
+		<div class="noBorderWrapper">
+			<div dojoType="dojox.image.FlickrBadge" rows="3" cols="6" username="dylans" setid="72157601441046380" target="_blank"></div>
+		</div>
+	</div>
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_Gallery.html b/dojox/image/tests/test_Gallery.html
new file mode 100644
index 0000000..dfea0fc
--- /dev/null
+++ b/dojox/image/tests/test_Gallery.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+	<title>Testing the Image Gallery</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/image.css">
+
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	
+	<!-- debugging includes -->
+	<script type="text/javascript" src="../ThumbnailPicker.js"></script>
+	<script type="text/javascript" src="../SlideShow.js"></script>
+	<script type="text/javascript" src="../Gallery.js"></script>
+	<script type="text/javascript" src="../../../dojo/data/util/simpleFetch.js"></script>
+	<script type="text/javascript" src="../../data/FlickrStore.js"></script>
+	<script type="text/javascript" src="../../data/FlickrRestStore.js"></script>
+	<script type="text/javascript" src="../../../dojo/data/ItemFileReadStore.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.image.Gallery");
+		dojo.require("dojox.data.FlickrRestStore");
+		dojo.require("dojo.parser");	// find widgets
+
+		dojo.addOnLoad(function(){
+			var flickrRestStore = new dojox.data.FlickrRestStore();
+			var req = {
+				query: {
+					userid: "44153025 at N00",
+					apikey: "8c6803164dbc395fb7131c9d54843627",
+					sort: [
+						   {
+							attribute: "interestingness",
+							descending: true
+							}
+						   ],
+				//	tags: ["superhorse", "redbones", "beachvolleyball"],
+					tag_mode: "any"
+				},
+				count: 20
+			};
+			setTimeout(function(){
+				dijit.byId('gallery1').setDataStore(flickrRestStore, req);				
+			},250);
+/*
+			dijit.byId('gallery2').setDataStore(imageItemStore,{ count:20 },{
+				imageThumbAttr: "thumb",
+				imageLargeAttr: "large"
+			});
+*/
+		});
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">dojox.image.Gallery</h1>
+
+	<h2>From FlickrRestStore:</h2>
+	<div id="gallery1" dojoType="dojox.image.Gallery" imageWidth="700" imageHeight="500"></div>
+
+<!--
+	<h2>From ItemFileReadStore:</h2>
+	<div id="gallery2" dojoType="dojox.image.Gallery"></div>
+-->
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_Gallery_GoogleData.html b/dojox/image/tests/test_Gallery_GoogleData.html
new file mode 100644
index 0000000..1ec2c99
--- /dev/null
+++ b/dojox/image/tests/test_Gallery_GoogleData.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+	<title>Testing the Image Gallery</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/image.css">
+	
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	
+	<!-- debugging includes -->
+	<script type="text/javascript" src="../ThumbnailPicker.js"></script>
+	<script type="text/javascript" src="../SlideShow.js"></script>
+	<script type="text/javascript" src="../Gallery.js"></script>
+	<script type="text/javascript" src="../../data/GoogleSearchStore.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.image.Gallery");
+		dojo.require("dojox.data.GoogleSearchStore");
+		dojo.require("dojox.data.FlickrRestStore");
+		dojo.require("dojo.parser");	// find widgets
+
+		dojo.addOnLoad(function(){
+			var googleImageStore = new dojox.data.GoogleImageSearchStore();
+			var req = {
+				query: {
+					text: "kinsale"
+				},
+				count: 32
+			};
+			// testCommon defers parsing by a little, so dijit's aren't ready
+			// in addOnLoad for soria/nihilo :(
+			setTimeout(function(){ 
+				dijit.byId('gallery1').setDataStore(googleImageStore, req);	
+			},250);
+		});
+		
+		function changeStore(){
+			var flickrRestStore = new dojox.data.FlickrRestStore();
+			var req = {
+				query: {
+					userid: "44153025 at N00",
+					apikey: "8c6803164dbc395fb7131c9d54843627",
+					sort: [
+						   {
+							attribute: "interestingness",
+							descending: true
+							}
+						   ],
+					tag_mode: "any"
+				},
+				count: 20
+			};
+			dijit.byId('gallery1').setDataStore(flickrRestStore, req, {
+			  imageThumbAttr: "imageUrlThumb",
+			  imageLargeAttr: "imageUrl",
+			  titleAttr: "title"
+			  
+			});				
+		}
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">dojox.image.Gallery</h1>
+
+	<h2>From GoogleImageSearchStore:</h2>
+	
+	<button onclick="changeStore()">Change Datastore</button>
+	
+	<div id="gallery1" dojoType="dojox.image.Gallery" imageWidth="700" imageHeight="500" 
+		imageThumbAttr="tbUrl" imageLargeAttr="unescapedUrl" titleAttr="titleNoFormatting"></div>
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_Gallery_in_TabContainer.html b/dojox/image/tests/test_Gallery_in_TabContainer.html
new file mode 100644
index 0000000..dc4ac52
--- /dev/null
+++ b/dojox/image/tests/test_Gallery_in_TabContainer.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+	<title>Testing the Image Gallery</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/image.css">
+
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	
+	<!-- debugging includes -->
+	<script type="text/javascript" src="../ThumbnailPicker.js"></script>
+	<script type="text/javascript" src="../SlideShow.js"></script>
+	<script type="text/javascript" src="../Gallery.js"></script>
+	<script type="text/javascript" src="../../../dojo/data/util/simpleFetch.js"></script>
+	<script type="text/javascript" src="../../data/FlickrStore.js"></script>
+	<script type="text/javascript" src="../../data/FlickrRestStore.js"></script>
+	<script type="text/javascript" src="../../../dojo/data/ItemFileReadStore.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.image.Gallery");
+		dojo.require("dojox.data.FlickrRestStore");
+		dojo.require("dijit.layout.TabContainer");;
+		dojo.require("dijit.layout.ContentPane");
+		
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">dojox.image.Gallery in a TabContainer</h1>
+	
+	<div dojoType="dojox.data.FlickrRestStore" jsId="flickrStore"></div>
+
+	<div dojoType="dijit.layout.TabContainer" style="width:800px;height:1000px;">
+		<script type="dojo/connect" event="startup">
+			// When the TabContainer has finished constructing, set the data store on each Gallery
+			dojo.forEach(["gallery1", "gallery2", "gallery3"], function(galleryId){
+				var req = {
+					query: {
+						userid: "44153025 at N00",
+						apikey: "8c6803164dbc395fb7131c9d54843627",
+						sort: [
+							   {
+								attribute: "interestingness",
+								descending: true
+								}
+							   ],
+					//	tags: ["superhorse", "redbones", "beachvolleyball"],
+						tag_mode: "any"
+					},
+					count: 20
+				};
+				
+				dijit.byId(galleryId).setDataStore(flickrStore, req);
+			});
+			
+		</script>
+		
+		<div id="gallery1" dojoType="dojox.image.Gallery" imageWidth="700" imageHeight="500"
+			  title="Gallery As Base Widget"
+		></div>
+		
+		<div dojoType="dijit.layout.ContentPane" title="Gallery In ContentPane">
+			
+			<div id="gallery2" dojoType="dojox.image.Gallery" imageWidth="700" imageHeight="500"></div>
+		
+		</div>
+		
+		
+		<div id="gallery3" dojoType="dojox.image.Gallery" imageWidth="700" imageHeight="500"
+			  title="Gallery As Base Widget"
+		></div>
+	</div>
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_Lightbox.html b/dojox/image/tests/test_Lightbox.html
new file mode 100644
index 0000000..79fe083
--- /dev/null
+++ b/dojox/image/tests/test_Lightbox.html
@@ -0,0 +1,249 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.image.Lightbox Tests | The Dojo Toolkit</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/image.css">
+	
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		body, html { width:100%; height:100%; margin:0; padding:0; } 
+		
+		#customTitleThing {
+			height:75px;
+			border:1px solid #ededed;
+			overflow:auto;
+			width:92%;
+		}
+	</style>
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../Lightbox.js"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.form.Button");
+		dojo.require("dojox.image.Lightbox"); 
+		dojo.require("dojox.data.FlickrStore");
+		dojo.ready(function(){
+			// sample with super-rich text content (no widgets or undelegated events please).
+			
+			var title = dojo.byId("customExample").innerHTML;
+			dojo.empty("customExample");
+			
+			var lb = new dojox.image.Lightbox({
+				href:"images/square.jpg",
+				title: title
+			});
+			lb.startup();
+			
+			new dijit.form.Button({
+				onClick: function(){
+					lb.show();
+				},
+				label:"Custom HTML"
+			}).placeAt("container");
+			
+			// and example that has events:
+			var elb = new dojox.image.LightboxDialog({});
+			elb.connect(elb.textNode, "onclick", function(e){
+				e.preventDefault();
+				elb.show({
+					leaveTitle:true,
+					href: dojo.attr(e.target, "href")
+				});
+			})
+			elb.startup();
+			
+			var content = "<a href='images/chris1_lg.jpg'>chris1<a/>"  
+				+ " | <a href='images/chris2_lg.jpg'>chris2</a>"
+				+ " | <a href='images/chris3_lg.jpg'>chris3</a>"
+			;
+				
+			new dijit.form.Button({
+				onClick:function(){
+					elb.show({
+						title:content,
+						href:"images/chris1_lg.jpg"
+					});
+				},
+				label:"Custom Links"
+			}).placeAt("container");
+			
+			// and example of onClick for the image (to hide the lightbox);
+			var clb = new dojox.image.Lightbox({
+				title:"fun fun fun",
+				href:"images/chris1_lg.jpg",
+				onClick: function(){
+					this.hide();
+				}
+			});
+			clb.startup();
+			
+			new dijit.form.Button({
+				label:"Custom Click",
+				onClick: function(){
+					clb.show()
+				}
+			}).placeAt("container");
+
+			// and example of onClick for the image (to toggle between large/small);
+			var clb2 = new dojox.image.Lightbox({
+				title:"fun fun fun",
+				href:"images/chris1_sm.jpg",
+				onClick: function(info){
+					
+					this.href = info.href == "images/chris1_lg.jpg" ? "images/chris1_sm.jpg" : "images/chris1_lg.jpg";
+					this.show({
+						leaveTitle:true,
+						href: this.href
+					});
+				}
+			});
+			clb2.startup();
+			
+			new dijit.form.Button({
+				label:"Zoomish Click",
+				onClick: function(){
+					clb2.show()
+				}
+			}).placeAt("container");
+			
+			dojo.query("#groupremover").onclick(function(e){
+				e.preventDefault();
+				var g = dijit.byId("targetremover");
+				console.warn(g);
+				if(g){
+					// destroying a dojox.image.Lightbox will remove itself from 
+					// the LightboxDialog
+					g.destroy();
+				}
+				
+				// test showing group 3 after removal:
+				var lbd = dijit.byId("dojoxLightboxDialog"); // the master
+				lbd.show({
+					title:"Should Only be three remaining",
+					group:"group3"
+				});
+			})
+			
+			dojo.query("#groupkiller").onclick(function(e){
+				e.preventDefault();
+				var lbd = dijit.byId("dojoxLightboxDialog");
+				lbd.removeGroup("group3");
+				
+				
+			})
+		})
+	</script>
+
+	<script type="text/javascript">
+		// programatic flickrstore implementation [basic]
+		function onComplete(items,request){
+			if (items.length>0){
+				dojo.forEach(items,function(item){
+					var part = {
+						title: flickrStore.getValue(item,"title"),
+						href: flickrStore.getValue(item,"imageUrl")
+					};
+					// FIXME: make addImage more accessible, or do this internally
+					// _attachedDialog is dijit.byId("dojoxLightboxDialog"), and the
+					// is only one per page.
+					dijit.byId('fromStore')._attachedDialog.addImage(part,"flickrStore");
+				});
+				dojo.byId('flickrButton').disabled = false; 
+			}
+		}
+
+		function onError(error,request){
+			console.warn(error,request);
+		}
+
+		function init(){
+			var flickrRequest = {
+				query: {},
+				onComplete: onComplete,
+				onError: onError,
+				userid: "jetstreet",
+				tags: "jetstreet",
+				count: 10
+			};
+			flickrStore.fetch(flickrRequest);
+		}
+		dojo.addOnLoad(init);
+	</script>
+
+
+</head>
+<body class="tundra">
+
+	<div id="container" style="padding:20px;">
+		<h1 class="testTitle">a Dojo based Lightbox implementation:</h1>
+
+		<h3>Individual</h3>
+		<p>
+			<a href="images/imageVert.jpg" dojoType="dojox.image.Lightbox" title="More Guatemala...">tall</a>
+			<a href="images/imageHoriz.jpg" dojoType="dojox.image.Lightbox" title="Antigua, Guatemala">4:3 image</a>
+			<a href="images/broken.jpg" dojoType="dojox.image.Lightbox" title="broken href example">Broken link</a>
+			<a href="images/huuuge.png" modal="true" dojoType="dojox.image.Lightbox" title="a large image">large than viewport?</a> (also modal, no click on underlay)
+			
+			<a href="images/huuuge.png" dojoType="dojox.image.Lightbox" title="a large image with a really really long multi-line-title because I can. Okay, this title has to be really really supremely long in order to occupy the full width of the viewport provided. yymv.">large than viewport, long title</a>
+		</p>
+
+		<h3>Grouped:</h3>
+		<p>
+			<a href="images/imageHoriz2.jpg" dojoType="dojox.image.Lightbox" group="group1" title="Amsterdam Train Depot but this title is going to be really really really really long just because">wide image, multiline title</a>
+			<a href="images/square.jpg" dojoType="dojox.image.Lightbox" group="group1" title="1:1 aspect">square</a>
+			<a href="images/extraWide.jpg" dojoType="dojox.image.Lightbox" group="group1" title="Greeneville, TN">wide image</a>
+			<a href="images/broken.jpg" dojoType="dojox.image.Lightbox" group="group1" title="broken href example">Broken link</a>
+		</p>	
+
+		<h3>Alternate Group:</h3>	
+		<p>
+			<a href="images/imageHoriz2.jpg" dojoType="dojox.image.Lightbox" group="group2" title="hmm <em>right</em> there is <b>rich text</b> here">Rich Text Title</a>
+			<a href="images/square.jpg" dojoType="dojox.image.Lightbox" group="group2" title="1:1 aspect">square</a>
+			<a href="images/imageHoriz.jpg" dojoType="dojox.image.Lightbox" group="group2" title="Antigua, Guatemala">4:3 image</a>
+			<a href="images/imageVert.jpg" dojoType="dojox.image.Lightbox" group="group2" title="More Guatemala...">tall</a>
+		</p>
+
+		<h3>RemoveGroup Group3:</h3>	
+		<p>
+			<a id="targetremover" href="images/imageHoriz2.jpg" dojoType="dojox.image.Lightbox" group="group3" title="hmm <em>right</em> there is <b>rich text</b> here">Rich Text Title</a>
+			<a href="images/square.jpg" dojoType="dojox.image.Lightbox" group="group3" title="1:1 aspect">square</a>
+			<a href="images/imageHoriz.jpg" dojoType="dojox.image.Lightbox" group="group3" title="Antigua, Guatemala">4:3 image</a>
+			<a href="images/imageVert.jpg" dojoType="dojox.image.Lightbox" group="group3" title="More Guatemala...">tall</a>
+		</p>
+        <p>
+                <a href='#' id="groupremover">remove one from group3, then show group</a> | <a href="#" id="groupkiller">remove group3</a>
+        </p>
+
+		<h3>From dojox.data.FlickrStore:</h3>
+
+		<div dojoType="dojox.data.FlickrStore" jsId="flickrStore" label="title"></div>
+		<div id="fromStore" dojoType="dojox.image.Lightbox" store="flickrStore" group="flickrStore"></div>
+
+		<input id="flickrButton" type="button" onclick="dijit.byId('fromStore').show()" value="show flickr lightbox" disabled="disabled">
+	
+	</div>
+
+	<div id="customExample">
+		<div id="customTitleThing">
+			<p>lorem ipsum dolor amit</p>
+			<p>lorem ipsum dolor amit</p>
+			<p>lorem ipsum dolor amit</p>
+			<p>lorem ipsum dolor amit</p>
+			<p>lorem ipsum dolor amit</p>
+			<p>lorem ipsum dolor amit</p>
+		</div>
+	</div>
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_LightboxNano.html b/dojox/image/tests/test_LightboxNano.html
new file mode 100644
index 0000000..c08dd35
--- /dev/null
+++ b/dojox/image/tests/test_LightboxNano.html
@@ -0,0 +1,166 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.image.LightboxNano Tests | The Dojo Toolkit</title>
+
+	<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+	.wrapper{width:800px;}
+	img{border:#666 solid 2px;}
+	.pic1{float:right;margin:0 0 10px 10px;}
+	.pic2{float:left;margin:0 10px 10px 0;}
+	.pic3{margin:0 auto;width:240px;}
+	a:hover .dojoxEnlarge{display:block !important;}
+	.dojoxEnlarge{background:url(images/enlarge.png) no-repeat 0 0;top:-5px;left:-5px;width:16px;height:16px;}
+	.dojoxLoading{
+		background:#333 url(images/loading-dark.gif) no-repeat center center;
+		border-radius:5px;
+		-moz-border-radius:5px;
+		-webkit-border-radius:5px;
+		border:2px solid #000;
+		height:24px;
+		filter:alpha(opacity=80);
+		opacity:0.8;
+		padding:6px;
+		width:24px;
+	}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug:true, parseOnLoad:true"></script>
+
+	<script type="text/javascript">
+	dojo.require("dojo.parser");
+	dojo.require("dojox.image.LightboxNano");
+	
+	dojo.addOnLoad(function(){
+		
+		// programmatic example
+		var w = new dojox.image.LightboxNano({
+			href: "images/chris3_lg.jpg"
+		}, "pic3");
+		
+		// a dynamic, singletonish Nano
+		var n = new dojox.image.LightboxNano();
+		dojo.query(".progButton1").onclick(function(e){
+			e.preventDefault();
+			n.show({ href:"images/chris3_lg.jpg", origin: e.target });
+		});
+		
+		dojo.query(".progButton2").onclick(function(e){
+			e.preventDefault();
+			n.show({ href:"images/chris3_lg.jpg" });
+		});
+	});
+	</script>
+</head>
+<body class="tundra">
+
+<h1>LightboxNano Test</h1>
+
+<div class="wrapper">
+
+	<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed eu orci. Phasellus luctus placerat
+	tellus. Nulla tempus tincidunt erat. Pellentesque habitant morbi tristique senectus et netus et
+	malesuada fames ac turpis egestas. Proin eros. Integer nisl orci, auctor a, facilisis ut,
+	adipiscing id, libero. Pellentesque lacus. Curabitur lobortis sapien eget est. Cras non urna ut
+	justo gravida accumsan. Vestibulum ac leo. Integer a est non risus feugiat pellentesque. Aliquam
+	neque. Fusce ligula purus, pharetra non, placerat vitae, pellentesque vitae, metus. Fusce laoreet.
+	Nullam placerat sem nec nisi aliquet volutpat.</p>
+
+	<h2>Declarative example on a <img> tag.</h2>
+
+	<p><img class="pic1" dojoType="dojox.image.LightboxNano" src="images/chris1_sm.jpg" href="images/chris1_lg.jpg">
+	In est magna, rutrum ut, consectetuer eget, iaculis sit amet, augue. Aliquam sagittis, felis sit
+	amet pharetra gravida, nunc lacus placerat sem, ac vulputate massa leo ut sapien. Nulla eget augue.
+	Nunc magna urna, vehicula eu, luctus eu, gravida at, velit. Phasellus enim. Integer placerat
+	tincidunt sapien. Nulla euismod augue quis lectus. In vehicula aliquet orci. Nulla euismod. Nam
+	feugiat elit a risus. Suspendisse cursus congue urna.</p>
+
+	<p>Aenean bibendum, orci non placerat varius, risus odio interdum lacus, a consectetuer lorem arcu
+	vitae odio. Aliquam erat volutpat. Sed quis urna ut sapien interdum dapibus. Vivamus eu nisi vel
+	justo faucibus consectetuer. Maecenas nibh. Mauris orci nibh, pharetra ut, mollis quis, congue
+	volutpat, neque. Vivamus malesuada sapien in nibh. Suspendisse orci felis, malesuada quis, dignissim
+	id, dapibus id, elit. Aliquam bibendum. Phasellus imperdiet purus sit amet enim vestibulum
+	adipiscing. Proin interdum, nunc eu euismod lacinia, mi tortor elementum arcu, ut iaculis risus
+	purus eu felis. Etiam enim nunc, vehicula in, laoreet quis, tincidunt eget, leo. Vestibulum enim
+	purus, posuere et, eleifend ac, tempus non, purus. Suspendisse rutrum elit at erat. Aenean interdum
+	risus sit amet lorem. Ut dignissim libero ac sapien. Aenean fermentum urna. Maecenas leo urna,
+	lobortis nec, ultrices at, rhoncus eget, tortor. Nunc sem. Mauris purus nisl, sodales ac, malesuada
+	at, pellentesque vel, leo.</p>
+
+	<h2>Declarative example on a <a> tag.</h2>
+
+	<p><a class="pic2" jsId="lightboxNano2" dojoType="dojox.image.LightboxNano" href="images/chris2_lg.jpg"><img src="images/chris2_sm.jpg"></a>
+	Nullam velit justo, aliquam sit amet, euismod sit amet, fermentum nec, pede. Proin sit amet
+	turpis tincidunt turpis posuere posuere. Donec ante. Donec ipsum. Morbi non lectus. Nullam rhoncus,
+	est in facilisis tincidunt, elit tortor aliquet velit, ut posuere nulla ipsum at tellus. Quisque
+	eget dolor vitae erat sollicitudin dignissim. Nulla at mi blandit lacus aliquam dignissim. Nunc
+	pretium. Nulla vitae enim vitae tortor iaculis ultrices. Vivamus suscipit urna ac ligula. Morbi
+	fringilla vestibulum sapien. Cras ante. Donec pulvinar sodales neque.</p>
+
+	<button onclick="lightboxNano2.destroy()"><-- Delete this LightboxNano</button>
+
+	<p>Nam accumsan justo ac nibh. Ut ut tortor nec magna tincidunt pulvinar. Duis at ligula ut urna
+	adipiscing dapibus. Cras dolor. Sed a lectus sit amet quam gravida lobortis. In faucibus iaculis
+	ligula. Sed scelerisque, arcu vel egestas tristique, urna odio adipiscing magna, ac lacinia urna
+	turpis eu nulla. Sed aliquet nunc ut tortor. Suspendisse ut lacus et odio lobortis molestie.
+	Suspendisse et mi sed leo cursus dictum. Nulla cursus ornare neque. Praesent pede.</p>
+
+	<p>Aliquam erat volutpat. Sed adipiscing, pede sit amet varius elementum, libero nibh molestie nunc,
+	vitae mattis odio velit et leo. Aliquam nulla diam, ultricies at, bibendum vitae, posuere ac, nisi.
+	Quisque mi odio, aliquam malesuada, congue nec, porttitor eu, tellus. Cum sociis natoque penatibus et
+	magnis dis parturient montes, nascetur ridiculus mus. Fusce a sapien. Sed at augue ut diam malesuada
+	venenatis. Fusce eu dui eget velit bibendum posuere. Pellentesque est turpis, vestibulum ut,
+	imperdiet fringilla, pretium at, neque. Integer imperdiet ullamcorper tellus. Etiam feugiat, nibh in
+	sodales molestie, nunc mauris dignissim tellus, id dapibus dui ante nec orci. Sed at mi. Aenean sed
+	erat ut nulla luctus condimentum.</p>
+
+	<h2>Programmatic example</h2>
+
+	<div class="pic3"><img id="pic3" src="images/chris3_sm.jpg"></div>
+
+	<p>Ut gravida ante vitae lectus. Donec in lacus. Vivamus fringilla quam ac pede. Aenean feugiat risus.
+	Donec tincidunt est et massa. Proin imperdiet bibendum pede. Vivamus vel dolor vitae dui posuere
+	lobortis. Aliquam erat volutpat. Sed id metus. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos himenaeos. Vestibulum porta nunc vel leo. Mauris auctor, justo eu porta
+	vulputate, lectus eros lobortis ipsum, ut eleifend est odio nec lacus. Nam vitae neque id neque
+	bibendum semper. Integer ut nunc.</p>
+
+	<h2>Singleton like example</h2>
+
+	<p>Ut gravida ante vitae lectus. Donec in lacus. Vivamus fringilla quam ac pede. Aenean feugiat risus.
+	Donec tincidunt est et massa. Proin imperdiet bibendum pede. Vivamus vel dolor vitae dui posuere
+	lobortis. Aliquam erat volutpat. Sed id metus. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos himenaeos. Vestibulum porta nunc vel leo. Mauris auctor, justo eu porta
+	vulputate, lectus eros lobortis ipsum, ut eleifend est odio nec lacus. Nam vitae neque id neque
+	bibendum semper. Integer ut nunc.</p>
+
+	<button class="progButton1">
+		Show Arbitrary Image from here
+	</button>
+
+	<p>Ut gravida ante vitae lectus. Donec in lacus. Vivamus fringilla quam ac pede. Aenean feugiat risus.
+	Donec tincidunt est et massa. Proin imperdiet bibendum pede. Vivamus vel dolor vitae dui posuere
+	lobortis. Aliquam erat volutpat. Sed id metus. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos himenaeos. Vestibulum porta nunc vel leo. Mauris auctor, justo eu porta
+	vulputate, lectus eros lobortis ipsum, ut eleifend est odio nec lacus. Nam vitae neque id neque
+	bibendum semper. Integer ut nunc.</p>
+
+	<button class="progButton2">
+		Show Arbitrary Image with no origin
+	</button>
+
+	<p>Ut gravida ante vitae lectus. Donec in lacus. Vivamus fringilla quam ac pede. Aenean feugiat risus.
+	Donec tincidunt est et massa. Proin imperdiet bibendum pede. Vivamus vel dolor vitae dui posuere
+	lobortis. Aliquam erat volutpat. Sed id metus. Class aptent taciti sociosqu ad litora torquent per
+	conubia nostra, per inceptos himenaeos. Vestibulum porta nunc vel leo. Mauris auctor, justo eu porta
+	vulputate, lectus eros lobortis ipsum, ut eleifend est odio nec lacus. Nam vitae neque id neque
+	bibendum semper. Integer ut nunc.</p>
+
+</div>
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_Magnifier.html b/dojox/image/tests/test_Magnifier.html
new file mode 100644
index 0000000..fef1ddd
--- /dev/null
+++ b/dojox/image/tests/test_Magnifier.html
@@ -0,0 +1,98 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+    <title>Testing image</title>
+    <style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		/* needed for glass overlay: */
+		@import "../resources/Magnifier.css";
+		
+		p { padding:20px; border:1px solid #ededed; }
+		#testImage { border:2px solid #000; }
+		
+    </style>
+    <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad:true"></script>
+	<!-- for debugging -->
+	<script type="text/javascript" src="../MagnifierLite.js"></script>
+	<script type="text/javascript" src="../Magnifier.js"></script>
+
+    <script type="text/javascript">
+		dojo.require("dojox.image.Magnifier");
+		dojo.require("dijit.form.Button");		
+	</script>
+
+</head>
+<body class="tundra">
+
+    <h1 class="testTitle">dojox.image.Magnifier test page</h1>
+
+		<p>They are just images. It's entirely unobtrusive to add magnification to an image, and style it accordingly.</p>
+		<p>This widget is based on <a href="test_MagnifierLite.html">dojox.image.MagnifierLite</a>, an image-only variant on this dojox.gfx
+		based Widget. The idea was/is to include addational surfaces in some kind of _Templated GFX widget, based on _Widget.</p>
+		<p>
+		Scale= 2.34, 5.67, and 8.90: <br>
+		<img id="testImage" dojoType="dojox.image.Magnifier" src="images/spanke.jpg"
+			 style="width:200px; height:130px;" scale="2.34" />
+		<img id="testImage4" dojoType="dojox.image.Magnifier" src="images/spanke.jpg"
+			 style="width:200px; height:130px;" scale="5.67" />
+
+		<img id="testImage5" dojoType="dojox.image.Magnifier" src="images/spanke.jpg"
+			 style="width:200px; height:130px;" scale="8.90" />
+		</p>
+		
+		<p>
+		<img id="testImage2" dojoType="dojox.image.Magnifier" src="images/spanke.jpg"
+			 style="width:200px; height:130px; padding-right:20px; float:left" />
+		I Am Some inline text.<br>lorem ipsum.<br style="clear:both">
+		</p>
+		
+		<p>A Transparent .png:<br>
+
+		<img  style="width:400px; height:260px" id="test3"
+			  dojoType="dojox.image.Magnifier" glassSize="215" scale="3"
+			  src="../../../util/resources/logo/positive/dojo.logo.big.png" />
+		</p>
+
+		<p>Programatic:<br>
+		
+		<button dojoType="dijit.form.Button" id="foob">
+			Make It
+			<script type="dojo/method" event="onClick">
+				this.setAttribute("disabled",true);
+				dijit.byId("foobd").setAttribute("disabled",false);
+				new dojox.image.Magnifier({ scale:4.2, glassSize:200 },"foobar");
+			</script>
+		</button>
+
+		<button dojoType="dijit.form.Button" id="foobd" disabled="disabled">
+			Destroy It
+			<script type="dojo/method" event="onClick">
+				this.setAttribute("disabled",true);
+				dijit.byId("foobar").destroy();
+				console.log('layout changed:');
+				dijit.byId("after1")._adjustScale();
+				dijit.byId("after2")._adjustScale();
+			</script>
+		</button>
+		
+		<br /><!-- srcNodeRef : -->
+		<img id="foobar" style="width:300px; height:195px;" src="images/spanke.jpg" />
+		</p>
+
+		<p>Remote file (GTA:LCS/psp map):<br>
+		<img id='after1' style="width:167px; height:240px; border:4px solid #333;"
+			 src="http://img.qj.net/uploads/articles_module/66700/stauntonhpackages_qjpreviewth.png"
+			 scale="6" glassSize="150" dojoType="dojox.image.Magnifier"
+			/>
+
+		<br>Everybody loves Zelda, right?<br>
+		<img id='after2' style="width:585px; height:201px" scale="7" glassSize="185" dojoType="dojox.image.Magnifier" src="http://www.zelda-infinite.com/games/zelda1/overworld.png" /> 
+		</p>
+		
+		<p id="programaticContainer">
+		<!-- not yet? -->	
+		</p>
+		
+</body>
+</html>
diff --git a/dojox/image/tests/test_MagnifierLite.html b/dojox/image/tests/test_MagnifierLite.html
new file mode 100644
index 0000000..a6edc56
--- /dev/null
+++ b/dojox/image/tests/test_MagnifierLite.html
@@ -0,0 +1,92 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+    <title>Testing image</title>
+    <style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../resources/Magnifier.css";
+		
+		p { padding:20px; border:1px solid #ededed; }
+		#testImage { border:2px solid #000; }
+		
+    </style>
+
+    <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad:true"></script>
+	<script type="text/javascript" src="../MagnifierLite.js"></script>
+    <script type="text/javascript">
+		dojo.require("dojox.image.MagnifierLite");
+		dojo.require("dijit.form.Button");		
+	</script>
+
+</head>
+<body class="tundra">
+
+    <h1 class="testTitle">dojox.image.MagnifierLite test page</h1>
+
+		<p>They are just images. It's entirely unobtrusive to add magnification to an image, and style it accordingly.</p>
+
+		<p>This is the base class for <a href="test_Magnifier.html">dojox.image.Magnifier</a>, a dojox.gfx-based extension
+		this portion does not require the dojox.gfx package, but is limited to CSS-based styling.
+		</p>
+
+		<p>
+		Scale= 2.34, 5.67, and 8.90: <br>
+		<img id="testImage" dojoType="dojox.image.MagnifierLite" src="images/spanke.jpg"
+			 style="width:200px; height:130px;" scale="2.34" />
+		<img id="testImage4" dojoType="dojox.image.MagnifierLite" src="images/spanke.jpg"
+			 style="width:200px; height:130px;" scale="5.67" />
+
+		<img id="testImage5" dojoType="dojox.image.MagnifierLite" src="images/spanke.jpg"
+			 style="width:200px; height:130px;" scale="8.90" />
+		</p>
+		
+		<p>
+		<img id="testImage2" dojoType="dojox.image.MagnifierLite" src="images/spanke.jpg"
+			 style="width:200px; height:130px; padding-right:20px; float:left" />
+		I Am Some inline text.<br>lorem ipsum.<br style="clear:both">
+		</p>
+		
+		<p>A Transparent .png: (url unavailable in release versions, need build-utils package, or svn)<br>
+
+		<img  style="width:400px; height:260px" id="test3"
+			  dojoType="dojox.image.MagnifierLite" glassSize="215" scale="3"
+			  src="../../../util/resources/logo/positive/dojo.logo.big.png" />
+		</p>
+
+		<p>Programatic: (destroy() removes this.domNode)<br>
+		
+		<button dojoType="dijit.form.Button" id="foob">
+			Make It
+			<script type="dojo/method" event="onClick">
+				this.setAttribute("disabled",true);
+				dijit.byId("foobd").setAttribute("disabled",false);
+				new dojox.image.MagnifierLite({ scale:4.2, glassSize:200 },"foobar");
+			</script>
+		</button>
+
+		<button dojoType="dijit.form.Button" id="foobd" disabled="disabled">
+			Destroy It
+			<script type="dojo/method" event="onClick">
+				dijit.byId("foob").setAttribute("disabled",false);
+				this.setAttribute("disabled",true);
+				dijit.byId("foobar").destroy(true);
+			</script>
+		</button>
+		
+		<br /><!-- srcNodeRef : -->
+		<img id="foobar" style="width:300px; height:195px;" src="images/spanke.jpg" />
+		</p>
+
+		<p>Remote file (GTA:LCS/psp map):<br>
+		<img style="width:167px; height:240px; border:4px solid #333;"
+			 src="http://img.qj.net/uploads/articles_module/66700/stauntonhpackages_qjpreviewth.png"
+			 scale="6" glassSize="150" dojoType="dojox.image.MagnifierLite"
+			/>
+
+		<br>Everybody loves Zelda:<br>
+		<img style="width:585px; height:201px" scale="7" glassSize="185" dojoType="dojox.image.MagnifierLite" src="http://www.zelda-infinite.com/games/zelda1/overworld.png" /> 
+		</p>
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_SlideShow.html b/dojox/image/tests/test_SlideShow.html
new file mode 100644
index 0000000..d1ac2b2
--- /dev/null
+++ b/dojox/image/tests/test_SlideShow.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+	<title>Testing dojox.image.SlideShow</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/image.css">
+
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: false"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../SlideShow.js"></script>
+	<script type="text/javascript" src="../../../dojo/data/ItemFileReadStore.js"></script>	
+	<script type="text/javascript" src="../../data/FlickrRestStore.js"></script>	
+
+	<script type="text/javascript">
+		// dojo.require("dojox.image.SlideShow");
+		// dojo.require("dojox.data.FlickrRestStore");
+		// dojo.require("dojo.data.ItemFileReadStore"); 
+		dojo.require("dojo.parser");	// find widgets		
+		
+		dojo.addOnLoad(function(){
+			//Initialize the first SlideShow with an ItemFileReadStore
+			dojo.parser.parse();
+			dijit.byId('slideshow1').setDataStore(imageItemStore,
+				{ query: {}, count:20 },
+				{
+					imageThumbAttr: "thumb",
+					imageLargeAttr: "large"
+				}
+			);
+			
+			//INitialize the second store with a FlickrRestStore
+			var flickrRestStore = new dojox.data.FlickrRestStore();
+			var req = {
+				query: {
+					userid: "44153025 at N00",
+					apikey: "8c6803164dbc395fb7131c9d54843627"
+				},
+				count: 20
+			};
+			dijit.byId('slideshow2').setDataStore(flickrRestStore, req);
+		});
+			
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">dojox.image.SlideShow</h1>
+
+	<h2>from dojo.data.ItemFileReadStore</h2>
+	<div jsId="imageItemStore" dojoType="dojo.data.ItemFileReadStore" url="images.json"></div>
+
+	This SlideShow should display five photos, and loop. It should also
+	open a URL when the image is clicked.  The widget should also resize to
+	fit the image.
+	<div id="slideshow1" dojoType="dojox.image.SlideShow"></div>
+
+	<h2>from dojox.data.FlickrRestStore</h2>
+	This SlideShow should display five photos, and not loop. It should also not
+	open a URL when the image is clicked.  AutoLoading of images is also disabled.
+	The time between images in a SlideShow is 1 second.  The widget should not resize to fit the image
+	<div id="slideshow2" dojoType="dojox.image.SlideShow" noLink="true" loop="false" autoLoad="false"
+		slideshowInterval="1" fixedHeight="true"></div>
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_SlideShow_GoogleData.html b/dojox/image/tests/test_SlideShow_GoogleData.html
new file mode 100644
index 0000000..ab60c52
--- /dev/null
+++ b/dojox/image/tests/test_SlideShow_GoogleData.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+	<title>Testing the Image Gallery</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/image.css">
+	
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../ThumbnailPicker.js"></script>
+	<script type="text/javascript" src="../SlideShow.js"></script>
+	<script type="text/javascript" src="../Gallery.js"></script>
+	<script type="text/javascript" src="../../data/GoogleSearchStore.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.data.GoogleSearchStore");
+		dojo.require("dojo.parser");	// find widgets
+
+		dojo.addOnLoad(function(){
+			var googleImageStore = new dojox.data.GoogleImageSearchStore();
+			var req = {
+				query: {
+					text: "badminton"
+				},
+				count: 32
+			};
+			dijit.byId('slideshow1').setDataStore(googleImageStore, req);
+		});
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">dojox.image.SlideShow</h1>
+
+	<h2>From GoogleImageSearchStore:</h2>
+	<div id="slideshow1" dojoType="dojox.image.SlideShow" imageWidth="700" imageHeight="500" 
+		imageThumbAttr="tbUrl" imageLargeAttr="unescapedUrl" titleAttr="titleNoFormatting"></div>
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_ThumbnailPicker.html b/dojox/image/tests/test_ThumbnailPicker.html
new file mode 100644
index 0000000..cacb624
--- /dev/null
+++ b/dojox/image/tests/test_ThumbnailPicker.html
@@ -0,0 +1,172 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+	<title>Testing the ThumbnailPicker</title>
+	
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/image.css">
+	
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: false"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../ThumbnailPicker.js"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dojox.image.ThumbnailPicker");
+		dojo.require("dojox.data.FlickrRestStore"); 
+		dojo.require("dojo.data.ItemFileReadStore"); 
+		dojo.require("dojo.parser");
+		
+		/*
+			Initializes the ThumbnailPicker with a data store that
+			reads from the Flickr REST APIs.
+		*/
+		function initFlickrGallery() {
+			var flickrRestStore = new dojox.data.FlickrRestStore();
+			var req = {
+				query: {
+					userid: "44153025 at N00",//The Flickr user id to use
+					apikey: "8c6803164dbc395fb7131c9d54843627",//An API key is required.
+					sort: [
+						   {
+							descending: true //Use descending sort order, ascending is default.
+							}
+						   ],
+					tags: ["superhorse", "redbones", "beachvolleyball","dublin","croatia"],
+					tag_mode: "any" //Match any of the tags
+				},
+				count: 20
+			};
+			
+			//Set the flickr data store on two of the dojox.image.ThumbnailPicker widgets
+			dijit.byId('thumbPicker1').setDataStore(flickrRestStore, req);
+			dijit.byId('thumbPicker3').setDataStore(flickrRestStore, req);
+		}
+		
+		/*
+			Initializes the second ThumbnailPicker widget with a data store that
+			reads information from a JSON URL.  This also tells the ThumbnailPicker
+			the name of the JSON attributes to read from each data item retrieved
+			from the JSON URL.
+		*/
+		function initItemStoreGallery(){
+			var itemRequest = {
+				query: {},
+				count: 20
+			};
+			var itemNameMap = {
+				imageThumbAttr: "thumb",
+				imageLargeAttr: "large"
+			};
+			
+			//Set the dojo.data.ItemFileReadStore on two of the dojox.image.ThumbnailPicker widgets
+			//Note the use of the 'itemNameMap', which tells the widget what attributes to
+			//read from the store.  Look in the 'images.json' file in the same folder as this
+			//file to see the data being read by the widget.
+			dijit.byId('thumbPicker2').setDataStore(imageItemStore, itemRequest, itemNameMap);
+			dijit.byId('thumbPicker4').setDataStore(imageItemStore, itemRequest, itemNameMap);
+		}
+		
+		//Subscribe to clicks on the thumbnails, and print out the information provided
+		function doSubscribe(){
+			function updateDiv(packet){
+				dojo.byId('PublishedData').innerHTML = "You selected the thumbnail:"
+						+ "<br/><b>Index:</b> " + packet.index
+						+ "<br/><b>Url:</b> " + packet.url
+						+ "<br/><b>Large Url:</b> " + packet.largeUrl
+						+ "<br/><b>Title:</b> " + packet.title
+						+ "<br/><b>Link:</b> " + packet.link
+						;
+			};
+			
+			//When an image in the ThumbnailPicker is clicked on, it publishes
+			//information on the image to a topic, whose name is found by calling
+			//the 'getTopicName' function on the widget.
+			dojo.subscribe(dijit.byId('thumbPicker1').getClickTopicName(), updateDiv);
+			dojo.subscribe(dijit.byId('thumbPicker2').getClickTopicName(), updateDiv);
+		}
+		
+		dojo.addOnLoad(function(){
+			dojo.parser.parse();
+			initFlickrGallery();
+			initItemStoreGallery();
+			doSubscribe();
+		});
+
+		function changeStore(){
+			var flickrRestStore = new dojox.data.FlickrRestStore();
+			var req = {
+				query: {
+					userid: "44153025 at N00",
+					apikey: "8c6803164dbc395fb7131c9d54843627",
+					sort: [
+						   {
+							attribute: "interestingness",
+							descending: true
+							}
+						   ],
+					tag_mode: "any"
+				},
+				count: 20
+			};
+			dijit.byId('thumbPicker2').setDataStore(flickrRestStore, req, {
+			  imageThumbAttr: "imageUrlThumb",
+			  imageLargeAttr: "imageUrl",
+			  titleAttr: "title"
+			  
+			});				
+		}
+
+	</script>
+</head>
+<body>
+	<h1 class="testTitle">dojox.image.ThumbnailPicker</h1>
+
+	<div id="PublishedData" style="background-color:light-grey">
+		When you click on a thumbnail image, it's information is placed here
+	</div>
+
+	<h2>From FlickrRestStore:</h2>
+	This ThumbnailPicker should have 8 thumbnails, with each of them linking
+	to a URL when clicked on.  The cursor should also change when over an image.
+	<div id="thumbPicker1" dojoType="dojox.image.ThumbnailPicker" size="500"
+			useHyperlink="true" ></div>
+
+    <h2>From ItemFileReadStore:</h2>
+	This ThumbnailPicker should have 5 thumbnails. Clicking on a thumbnail should NOT
+	open a URL, and the cursor should not change when over an image that is not an arrow.
+	
+	
+	<button onclick="changeStore()">Change Datastore</button>
+    <div id="thumbPicker2" dojoType="dojox.image.ThumbnailPicker" size="400"
+		isClickable="false"></div>
+	<div jsId="imageItemStore" dojoType="dojo.data.ItemFileReadStore" url="images.json"></div>
+	
+	<h2>From FlickrRestStore:</h2>
+	This ThumbnailPicker should have 6 thumbnails, with each of them linking
+	to a URL when clicked on.  The cursor should also change when over an image.
+	Unlike the ThumbnailPicker above, when these links are clicked on, this page
+	changes, instead of a popup window.
+	
+	<div id="thumbPicker3" dojoType="dojox.image.ThumbnailPicker" size="600"
+		useHyperLink="true" hyperlinkTarget="this"></div>
+
+	<h2>From ItemFileReadStore, and vertical:</h2>
+	This ThumbnailPicker should have 5 thumbnails. Clicking on a thumbnail should NOT
+	open a URL, and the cursor should not change when over an image that is not an arrow.
+	The thumbnails should also be aligned vertically.
+    <div id="thumbPicker4" dojoType="dojox.image.ThumbnailPicker" size="300"
+		isClickable="false" isHorizontal="false"></div>
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_ThumbnailPickerLightbox.html b/dojox/image/tests/test_ThumbnailPickerLightbox.html
new file mode 100644
index 0000000..261357a
--- /dev/null
+++ b/dojox/image/tests/test_ThumbnailPickerLightbox.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+	<title>Testing the ThumbnailPicker + Lightbox</title>
+	
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/image.css">
+	
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../ThumbnailPicker.js"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dojox.image.Lightbox");
+		dojo.require("dojox.image.ThumbnailPicker");
+		dojo.require("dojo.data.ItemFileReadStore"); 
+		/*
+			Initializes the second ThumbnailPicker widget with a data store that
+			reads information from a JSON URL.  This also tells the ThumbnailPicker
+			the name of the JSON attributes to read from each data item retrieved
+			from the JSON URL.
+		*/
+		function initItemStoreGallery(){
+			var itemRequest = {
+				query: {},
+				count: 20
+			};
+			var itemNameMap = {
+				imageThumbAttr: "thumb",
+				imageLargeAttr: "large"
+			};
+			
+			//Set the dojo.data.ItemFileReadStore on two of the dojox.image.ThumbnailPicker widgets
+			//Note the use of the 'itemNameMap', which tells the widget what attributes to
+			//read from the store.  Look in the 'images.json' file in the same folder as this
+			//file to see the data being read by the widget.
+			dijit.byId('thumbPicker2').setDataStore(imageItemStore, itemRequest, itemNameMap);
+
+		}
+		
+		//Subscribe to clicks on the thumbnails, and print out the information provided
+
+			function lightboxShow(packet){
+
+				// you can just "show" this image
+				lightbox.show({
+					href: packet.largeUrl,
+					title: packet.title
+				});
+				
+			};
+			
+			//When an image in the ThumbnailPicker is clicked on, it publishes
+			//information on the image to a topic, whose name is found by calling
+			//the 'getTopicName' function on the widget.
+		
+		var lightbox;
+		dojo.addOnLoad(function(){
+			dojo.parser.parse();
+
+			initItemStoreGallery();
+			// WARNING: LightboxDialog might be the _only_ widget with "return this;" coming out of .startup()
+			lightbox = new dojox.image.LightboxDialog().startup();
+			
+			dojo.subscribe(dijit.byId('thumbPicker2').getClickTopicName(), lightboxShow);
+
+		});
+
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">dojox.image.ThumbnailPicker + Lightbox</h1>
+
+	<div id="PublishedData" style="background-color:light-grey">
+	</div>
+
+    <h2>From ItemFileReadStore:</h2>
+	This ThumbnailPicker should have 5 thumbnails. Clicking on a thumbnail should NOT
+	open a URL, but rather open in a dojox.image.Lightbox. 
+	
+    <div id="thumbPicker2" dojoType="dojox.image.ThumbnailPicker" size="400"
+		isClickable="false"></div>
+	<div jsId="imageItemStore" dojoType="dojo.data.ItemFileReadStore" url="images.json"></div>
+
+</body>
+</html>
diff --git a/dojox/image/tests/test_base.html b/dojox/image/tests/test_base.html
new file mode 100644
index 0000000..9c0b61f
--- /dev/null
+++ b/dojox/image/tests/test_base.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>dojox.image.Badge Tests | The Dojo Toolkit</title>
+	
+	<!-- required: dojo.js -->
+	<script>
+		var djConfig = {
+			isDebug:true,
+			preloadImages:[
+				"images/chris2_lg.jpg"
+			]
+		}
+	</script>
+	<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+	
+	<script type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojox.image");
+		dojo.addOnLoad(function(){
+
+			doh.register("imageBase",
+				[
+					{
+						name: "test djConfig.preloadImages",
+						timeout:5000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+							
+							t.t(dojo.isArray(dojo.config.preloadImages));
+							
+							var l = dojo.query("div > img");
+							t.is(1, l.length);
+
+							l
+								.connect("onload", function(e){
+									d.callback(true);
+								})
+								.attr("src", dojo.config.preloadImages[0])
+							;
+
+							return d;
+						}
+					},
+					{
+						name: "test manual preload",
+						timeout:2000,
+						runTest: function(t){
+							var d = new doh.Deferred();
+
+							var urls = dojo.map(["chris1_lg.jpg","chris1_sm.jpg"], function(url){
+								return "images/" + url;
+							});
+							
+							var retvals = dojox.image.preload(urls);
+							t.is(2, retvals.length);
+
+							setTimeout(function(){
+								var n = dojo.query("div > img");
+								t.is(3, n.length);
+								d.callback(n.length);
+							}, 1000);
+							
+							return d;
+						}
+					}
+				]
+			);
+			
+			doh.run();
+			
+		});
+
+	</script>
+
+</head>
+<body></body>
+</html>
diff --git a/dojox/io/OAuth.js b/dojox/io/OAuth.js
index e93456a..a1e5e10 100644
--- a/dojox/io/OAuth.js
+++ b/dojox/io/OAuth.js
@@ -1,174 +1,295 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.io.OAuth"]){
-dojo._hasResource["dojox.io.OAuth"]=true;
 dojo.provide("dojox.io.OAuth");
 dojo.require("dojox.encoding.digests.SHA1");
-dojox.io.OAuth=new (function(){
-var _1=this.encode=function(s){
-if(!s){
-return "";
-}
-return encodeURIComponent(s).replace(/\!/g,"%21").replace(/\*/g,"%2A").replace(/\'/g,"%27").replace(/\(/g,"%28").replace(/\)/g,"%29");
-};
-var _2=this.decode=function(_3){
-var a=[],_4=_3.split("&");
-for(var i=0,l=_4.length;i<l;i++){
-var _5=_4[i];
-if(_4[i]==""){
-continue;
-}
-if(_4[i].indexOf("=")>-1){
-var _6=_4[i].split("=");
-a.push([decodeURIComponent(_6[0]),decodeURIComponent(_6[1])]);
-}else{
-a.push([decodeURIComponent(_4[i]),null]);
-}
-}
-return a;
-};
-function _7(_8){
-var _9=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],_a=/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,_b=_a.exec(_8),_c={},i=_9.length;
-while(i--){
-_c[_9[i]]=_b[i]||"";
-}
-var p=_c.protocol.toLowerCase(),a=_c.authority.toLowerCase(),b=(p=="http"&&_c.port==80)||(p=="https"&&_c.port==443);
-if(b){
-if(a.lastIndexOf(":")>-1){
-a=a.substring(0,a.lastIndexOf(":"));
-}
-}
-var _d=_c.path||"/";
-_c.url=p+"://"+a+_d;
-return _c;
-};
-var _e="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
-function _f(_10){
-var s="",tl=_e.length;
-for(var i=0;i<_10;i++){
-s+=_e.charAt(Math.floor(Math.random()*tl));
-}
-return s;
-};
-function _11(){
-return Math.floor(new Date().valueOf()/1000)-2;
-};
-function _12(_13,key,_14){
-if(_14&&_14!="PLAINTEXT"&&_14!="HMAC-SHA1"){
-throw new Error("dojox.io.OAuth: the only supported signature encodings are PLAINTEXT and HMAC-SHA1.");
-}
-if(_14=="PLAINTEXT"){
-return key;
-}else{
-return dojox.encoding.digests.SHA1._hmac(_13,key);
-}
-};
-function key(_15){
-return _1(_15.consumer.secret)+"&"+(_15.token&&_15.token.secret?_1(_15.token.secret):"");
-};
-function _16(_17,oaa){
-var o={oauth_consumer_key:oaa.consumer.key,oauth_nonce:_f(16),oauth_signature_method:oaa.sig_method||"HMAC-SHA1",oauth_timestamp:_11(),oauth_version:"1.0"};
-if(oaa.token){
-o.oauth_token=oaa.token.key;
-}
-_17.content=dojo.mixin(_17.content||{},o);
-};
-function _18(_19){
-var _1a=[{}],_1b;
-if(_19.form){
-if(!_19.content){
-_19.content={};
-}
-var _1c=dojo.byId(_19.form);
-var _1d=_1c.getAttributeNode("action");
-_19.url=_19.url||(_1d?_1d.value:null);
-_1b=dojo.formToObject(_1c);
-delete _19.form;
-}
-if(_1b){
-_1a.push(_1b);
-}
-if(_19.content){
-_1a.push(_19.content);
-}
-var map=_7(_19.url);
-if(map.query){
-var tmp=dojo.queryToObject(map.query);
-for(var p in tmp){
-tmp[p]=encodeURIComponent(tmp[p]);
-}
-_1a.push(tmp);
-}
-_19._url=map.url;
-var a=[];
-for(var i=0,l=_1a.length;i<l;i++){
-var _1e=_1a[i];
-for(var p in _1e){
-if(dojo.isArray(_1e[p])){
-for(var j=0,jl=_1e.length;j<jl;j++){
-a.push([p,_1e[j]]);
-}
-}else{
-a.push([p,_1e[p]]);
-}
-}
-}
-_19._parameters=a;
-return _19;
-};
-function _1f(_20,_21,oaa){
-_16(_21,oaa);
-_18(_21);
-var a=_21._parameters;
-a.sort(function(a,b){
-if(a[0]>b[0]){
-return 1;
-}
-if(a[0]<b[0]){
-return -1;
-}
-if(a[1]>b[1]){
-return 1;
-}
-if(a[1]<b[1]){
-return -1;
-}
-return 0;
-});
-var s=dojo.map(a,function(_22){
-return _1(_22[0])+"="+_1(_22[1]||"");
-}).join("&");
-var _23=_20.toUpperCase()+"&"+_1(_21._url)+"&"+_1(s);
-return _23;
-};
-function _24(_25,_26,oaa){
-var k=key(oaa),_27=_1f(_25,_26,oaa),s=_12(_27,k,oaa.sig_method||"HMAC-SHA1");
-_26.content["oauth_signature"]=s;
-return _26;
-};
-this.sign=function(_28,_29,oaa){
-return _24(_28,_29,oaa);
-};
-this.xhr=function(_2a,_2b,oaa,_2c){
-_24(_2a,_2b,oaa);
-return dojo.xhr(_2a,_2b,_2c);
-};
-this.xhrGet=function(_2d,oaa){
-return this.xhr("GET",_2d,oaa);
-};
-this.xhrPost=this.xhrRawPost=function(_2e,oaa){
-return this.xhr("POST",_2e,oaa,true);
-};
-this.xhrPut=this.xhrRawPut=function(_2f,oaa){
-return this.xhr("PUT",_2f,oaa,true);
-};
-this.xhrDelete=function(_30,oaa){
-return this.xhr("DELETE",_30,oaa);
-};
+
+dojox.io.OAuth = new (function(){
+	//	summary:
+	//		Helper singleton for signing any kind of Ajax request using the OAuth 1.0 protocol.
+	//	description:
+	//		dojox.io.OAuth is a singleton class designed to allow anyone to sign a request,
+	//		based on the OAuth 1.0 specification, made with any of the Dojo Toolkit's Ajax
+	//		methods (such as dojo.xhr[verb], dojo.io.iframe, etc.).
+	//
+	//		The main method of dojox.io.OAuth is the sign method (see documentation for .sign);
+	//		the idea is that you will "sign" the kwArgs object you'd normally pass to any of 
+	//		the Ajax methods, and then pass the signed object along.  As long as the token
+	//		object used is valid (and the client's date and time are synced with a public
+	//		time server), a signed object should be passed along correctly.
+	//
+	//		dojox.io.OAuth does not deal with the OAuth handshake process at all.
+	//
+	//		This object was developed against the Netflix API (OAuth-based service); see
+	//		http://developer.netflix.com for more details.
+	var encode = this.encode = function(s){
+		if(!s){ return ""; }
+		return encodeURIComponent(s)
+			.replace(/\!/g, "%21")
+			.replace(/\*/g, "%2A")
+			.replace(/\'/g, "%27")
+			.replace(/\(/g, "%28")
+			.replace(/\)/g, "%29");
+	};
+
+	var decode = this.decode = function(str){
+		//	summary:
+		//		Break apart the passed string and decode.
+		//		Some special cases are handled.
+		var a=[], list=str.split("&");
+		for(var i=0, l=list.length; i<l; i++){
+			var item=list[i];
+			if(list[i]==""){ continue; }	//	skip this one.
+			if(list[i].indexOf("=")>-1){
+				var tmp=list[i].split("=");
+				a.push([ decodeURIComponent(tmp[0]), decodeURIComponent(tmp[1]) ]);
+			} else {
+				a.push([ decodeURIComponent(list[i]), null ]);
+			}
+		}
+		return a;
+	};
+
+	function parseUrl(url){
+		//	summary:
+		//		Create a map out of the passed URL.  Need to pull any
+		//		query string parameters off the URL for the base signature string.
+        var keys = [
+				"source","protocol","authority","userInfo",
+				"user","password","host","port",
+				"relative","path","directory",
+				"file","query","anchor"
+			],
+			parser=/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
+			match=parser.exec(url),
+			map = {},
+			i=keys.length;
+
+		//	create the base map first.
+		while(i--){ map[keys[i]] = match[i] || ""; }
+
+		//	create the normalized version of the url and add it to the map
+		var p=map.protocol.toLowerCase(),
+			a=map.authority.toLowerCase(),
+			b=(p=="http"&&map.port==80)||(p=="https"&&map.port==443);
+		if(b){
+			if(a.lastIndexOf(":")>-1){
+				a=a.substring(0, a.lastIndexOf(":"));
+			}
+		}
+		var path=map.path||"/";
+		map.url=p+"://"+a+path;
+
+		//	return the map
+		return map;
+	}
+
+	var tab="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
+	function nonce(length){
+		var s="", tl=tab.length;
+		for(var i=0; i<length; i++){
+			s+=tab.charAt(Math.floor(Math.random()*tl));
+		}
+		return s;
+	}
+	function timestamp(){
+		return Math.floor(new Date().valueOf()/1000)-2;
+	}
+	function signature(data, key, type){
+		if(type && type!="PLAINTEXT" && type!="HMAC-SHA1"){
+			throw new Error("dojox.io.OAuth: the only supported signature encodings are PLAINTEXT and HMAC-SHA1.");
+		}
+
+		if(type=="PLAINTEXT"){
+			return key;
+		} else {
+			//	assume SHA1 HMAC
+			return dojox.encoding.digests.SHA1._hmac(data, key);
+		}
+	}
+
+	function key(args){
+		//	summary:
+		//		return the key used to sign a message based on the token object.
+		return encode(args.consumer.secret) 
+			+ "&" 
+			+ (args.token && args.token.secret ? encode(args.token.secret) : "");
+	}
+
+	function addOAuth(/* dojo.__XhrArgs */args, /* dojox.io.__OAuthArgs */oaa){
+		//	summary:
+		//		Add the OAuth parameters to the query string/content.
+		var o = {
+			oauth_consumer_key: oaa.consumer.key,
+			oauth_nonce: nonce(16),
+			oauth_signature_method: oaa.sig_method || "HMAC-SHA1",
+			oauth_timestamp: timestamp(),
+			oauth_version: "1.0"
+		}
+		if(oaa.token){
+			o.oauth_token = oaa.token.key;
+		}
+		args.content = dojo.mixin(args.content||{}, o);
+	}
+
+	function convertArgs(args){
+		//	summary:
+		//		Because of the need to create a base string, we have to do
+		//		some manual args preparation instead of relying on the internal
+		//		Dojo xhr functions.  But we'll let dojo.xhr assemble things
+		//		as it normally would.
+		var miArgs = [{}], formObject;
+
+		if(args.form){
+			if(!args.content){ args.content = {}; }
+			var form = dojo.byId(args.form);
+			var actnNode = form.getAttributeNode("action");
+			args.url = args.url || (actnNode ? actnNode.value : null);
+			formObject = dojo.formToObject(form);
+			delete args.form;
+		}
+		if(formObject){ miArgs.push(formObject); }
+		if(args.content){ miArgs.push(args.content); }
+
+		//	pull anything off the query string
+		var map = parseUrl(args.url);
+		if(map.query){ 
+			var tmp = dojo.queryToObject(map.query);
+			//	re-encode the values.  sigh
+			for(var p in tmp){ tmp[p] = encodeURIComponent(tmp[p]); }
+			miArgs.push(tmp);
+		}
+		args._url = map.url;
+
+		//	now set up all the parameters as an array of 2 element arrays.
+		var a = [];
+		for(var i=0, l=miArgs.length; i<l; i++){
+			var item=miArgs[i];
+			for(var p in item){
+				if(dojo.isArray(item[p])){
+					//	handle multiple values
+					for(var j=0, jl=item.length; j<jl; j++){
+						a.push([ p, item[j] ]);
+					}
+				} else {
+					a.push([ p, item[p] ]);
+				}
+			}
+		}
+
+		args._parameters = a;
+		return args;
+	}
+
+	function baseString(/* String */method, /* dojo.__XhrArgs */args, /* dojox.io.__OAuthArgs */oaa){
+		//	create and return the base string out of the args.
+		addOAuth(args, oaa);
+		convertArgs(args);
+
+		var a = args._parameters;
+
+		//	sort the parameters
+		a.sort(function(a,b){
+			if(a[0]>b[0]){ return 1; }
+			if(a[0]<b[0]){ return -1; }
+			if(a[1]>b[1]){ return 1; }
+			if(a[1]<b[1]){ return -1; }
+			return 0;
+		});
+
+		//	encode.
+		var s = dojo.map(a, function(item){
+			return encode(item[0]) + "=" + encode(item[1]||"");
+		}).join("&");
+
+		var baseString = method.toUpperCase()
+			+ "&" + encode(args._url) 
+			+ "&" + encode(s);
+		return baseString;
+	}
+
+	function sign(method, args, oaa){
+		//	return the oauth_signature for this message.
+		var k = key(oaa),
+			message = baseString(method, args, oaa),
+			s = signature(message, k, oaa.sig_method || "HMAC-SHA1");
+		args.content["oauth_signature"] = s;
+		return args;
+	}
+	
+	/*=====
+	 	dojox.io.OAuth.__AccessorArgs = function(key, secret){
+			//	key: String
+			//		The key or token issued to either the consumer or by the OAuth service.
+			//	secret: String
+			//		The secret (shared secret for consumers, issued secret by OAuth service).
+			this.key = key;
+			this.secret = secret;
+		};
+		dojox.io.OAuth.__OAuthArgs = function(consumer, sig_method, token){
+			//	consumer: dojox.io.OAuth.__AccessorArgs
+			//		The consumer information issued to your OpenAuth application.
+			//	sig_method: String
+			//		The method used to create the signature.  Should be PLAINTEXT or HMAC-SHA1.
+			//	token: dojox.io.OAuth.__AccessorArgs?
+			//		The request token and secret issued by the OAuth service.  If not
+			//		issued yet, this should be null.
+			this.consumer = consumer;
+			this.token = token;
+		}
+	=====*/
+
+	/*	
+	 *	Process goes something like this:
+	 *	1. prepare the base string
+	 *	2. create the key
+	 *	3. create the signature based on the base string and the key
+	 *	4. send the request using dojo.xhr[METHOD].
+	 */
+
+	this.sign = function(/* String*/method, /* dojo.__XhrArgs */args, /* dojox.io.OAuth.__OAuthArgs */oaa){
+		//	summary:
+		//		Given the OAuth access arguments, sign the kwArgs that you would pass
+		//		to any dojo Ajax method (dojo.xhr*, dojo.io.iframe, dojo.io.script).
+		//	example:
+		//		Sign the kwArgs object for use with dojo.xhrGet:
+		//	|	var oaa = {
+		//	|		consumer: {
+		//	|			key: "foobar",
+		//	|			secret: "barbaz"
+		//	|		}
+		//	|	};
+		//	|
+		//	|	var args = dojox.io.OAuth.sign("GET", myAjaxKwArgs, oaa);
+		//	|	dojo.xhrGet(args);
+		return sign(method, args, oaa);
+	};
+
+
+	//	TODO: handle redirect requests?
+	this.xhr = function(/* String */method, /* dojo.__XhrArgs */args, /* dojox.io.OAuth.__OAuthArgs */oaa, /* Boolean? */hasBody){
+		/*	summary:
+		 *		Make an XHR request that is OAuth signed.
+		 *	example:
+		 *	|	var dfd = dojox.io.OAuth.xhrGet({ 
+		 *	|		url: "http://someauthdomain.com/path?foo=bar",
+		 *	|		load: function(response, ioArgs){ } 
+		 *	|	}, 
+		 *	|	{
+		 *	|		consumer:{ key: "lasdkf9asdnfsdf", secret: "9asdnfskdfysjr" }
+		 *	|	});
+		 */
+		sign(method, args, oaa);
+		return dojo.xhr(method, args, hasBody);
+	};
+
+	this.xhrGet = function(/* dojo.__XhrArgs */args, /* dojox.io.OAuth.__OAuthArgs*/ oaa){
+		return this.xhr("GET", args, oaa);
+	};
+	this.xhrPost = this.xhrRawPost = function(/* dojo.__XhrArgs */args, /* dojox.io.OAuth.__OAuthArgs*/ oaa){
+		return this.xhr("POST", args, oaa, true);
+	};
+	this.xhrPut = this.xhrRawPut = function(/* dojo.__XhrArgs */args, /* dojox.io.OAuth.__OAuthArgs*/ oaa){
+		return this.xhr("PUT", args, oaa, true);
+	};
+	this.xhrDelete = function(/* dojo.__XhrArgs */args, /* dojox.io.OAuth.__OAuthArgs*/ oaa){
+		return this.xhr("DELETE", args, oaa);
+	};
 })();
-}
diff --git a/dojox/io/httpParse.js b/dojox/io/httpParse.js
index 37d110b..fe90113 100644
--- a/dojox/io/httpParse.js
+++ b/dojox/io/httpParse.js
@@ -1,66 +1,75 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.io.httpParse"]){
-dojo._hasResource["dojox.io.httpParse"]=true;
 dojo.provide("dojox.io.httpParse");
-dojox.io.httpParse=function(_1,_2,_3){
-var _4=[];
-var _5=_1.length;
-do{
-var _6={};
-var _7=_1.match(/(\n*[^\n]+)/);
-if(!_7){
-return null;
-}
-_1=_1.substring(_7[0].length+1);
-_7=_7[1];
-var _8=_1.match(/([^\n]+\n)*/)[0];
-_1=_1.substring(_8.length);
-var _9=_1.substring(0,1);
-_1=_1.substring(1);
-_8=(_2||"")+_8;
-var _a=_8;
-_8=_8.match(/[^:\n]+:[^\n]+\n/g);
-for(var j=0;j<_8.length;j++){
-var _b=_8[j].indexOf(":");
-_6[_8[j].substring(0,_b)]=_8[j].substring(_b+1).replace(/(^[ \r\n]*)|([ \r\n]*)$/g,"");
-}
-_7=_7.split(" ");
-var _c={status:parseInt(_7[1],10),statusText:_7[2],readyState:3,getAllResponseHeaders:function(){
-return _a;
-},getResponseHeader:function(_d){
-return _6[_d];
-}};
-var _e=_6["Content-Length"];
-var _f;
-if(_e){
-if(_e<=_1.length){
-_f=_1.substring(0,_e);
-}else{
-return _4;
-}
-}else{
-if((_f=_1.match(/(.*)HTTP\/\d\.\d \d\d\d[\w\s]*\n/))){
-_f=_f[0];
-}else{
-if(!_3||_9=="\n"){
-_f=_1;
-}else{
-return _4;
-}
-}
-}
-_4.push(_c);
-_1=_1.substring(_f.length);
-_c.responseText=_f;
-_c.readyState=4;
-_c._lastIndex=_5-_1.length;
-}while(_1);
-return _4;
-};
-}
+dojox.io.httpParse = function(/*String*/httpStream, /*String?*/topHeaders,/*Boolean?*/ partial){
+	// summary:
+	//		Parses an HTTP stream for a message.
+	// httpStream:
+	// 		HTTP stream to parse 
+	// topHeaders:
+	//		Extra header information to add to each HTTP request (kind of HTTP inheritance)
+	// partial:
+	//		A true value indicates that the stream may not be finished, it may end arbitrarily in mid stream.
+	//		The last XHR object will have a special property _lastIndex that indicates the how far along 
+	// 		the httpStream could be successfully parsed into HTTP messages.
+	// return:
+	// 		Returns an array of XHR-like object for reading the headers for each message
+	//		 
+	var xhrs=[];
+	var streamLength = httpStream.length;
+	do{
+		var headers = {};
+		var httpParts = httpStream.match(/(\n*[^\n]+)/);
+		if(!httpParts){ 
+			return null;
+		}
+		httpStream = httpStream.substring(httpParts[0].length+1);
+		httpParts = httpParts[1];
+		var headerParts = httpStream.match(/([^\n]+\n)*/)[0];
+		 
+		httpStream = httpStream.substring(headerParts.length);
+		var headerFollowingChar = httpStream.substring(0,1);
+		httpStream = httpStream.substring(1);
+		headerParts = (topHeaders || "") + headerParts;
+		var headerStr = headerParts;
+		headerParts = headerParts.match(/[^:\n]+:[^\n]+\n/g); // parse the containing and contained response headers with the contained taking precedence (by going last)
+		for(var j = 0; j < headerParts.length; j++){
+			var colonIndex = headerParts[j].indexOf(':');
+			headers[headerParts[j].substring(0,colonIndex)] = headerParts[j].substring(colonIndex+1).replace(/(^[ \r\n]*)|([ \r\n]*)$/g,''); // trim
+		}										
+	
+		httpParts = httpParts.split(' ');
+		var xhr = { // make it look like an xhr object, at least for the response part of the API
+			status : parseInt(httpParts[1],10),
+			statusText : httpParts[2],
+			readyState : 3, // leave it at 3 until we get a full body
+			getAllResponseHeaders : function(){ 
+				return headerStr;
+			},
+			getResponseHeader : function(name){
+				return headers[name];
+			}
+		}; 
+		var contentLength = headers['Content-Length'];
+		var content; 
+		if(contentLength){
+			if(contentLength <= httpStream.length){
+				content = httpStream.substring(0,contentLength);
+			}else{
+				return xhrs; // the content is not finished
+			}
+		}else if((content = httpStream.match(/(.*)HTTP\/\d\.\d \d\d\d[\w\s]*\n/))){ // assign content
+			// if we spot another HTTP message coming up, we will just assign all the in between text to the content
+			content = content[0];
+		}else if(!partial || headerFollowingChar == '\n'){
+			// if we have to finish
+			content = httpStream;
+		}else{
+			return xhrs;
+		}
+		xhrs.push(xhr); // add it to the list, since it is a full HTTP message
+		httpStream = httpStream.substring(content.length); // move along the stream
+		xhr.responseText = content;
+		xhr.readyState = 4;
+		xhr._lastIndex = streamLength - httpStream.length; // need to pick up from where we left on streaming connections 
+	}while(httpStream);
+	return xhrs;
+}
\ No newline at end of file
diff --git a/dojox/io/proxy/tests/frag.xml b/dojox/io/proxy/tests/frag.xml
new file mode 100644
index 0000000..6904bba
--- /dev/null
+++ b/dojox/io/proxy/tests/frag.xml
@@ -0,0 +1,4 @@
+<response>
+<foo>This is the foo text node value</foo>
+<bar>This is the bar text node value</bar>
+</response>
diff --git a/dojox/io/proxy/tests/xip.html b/dojox/io/proxy/tests/xip.html
new file mode 100644
index 0000000..5a5ba5f
--- /dev/null
+++ b/dojox/io/proxy/tests/xip.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>XHR IFrame Proxy Tests</title>
+	<style type="text/css">
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/themes/tundra/tundra.css";
+		@import "../../../../dijit/themes/dijit.css";
+	</style>
+
+	<script type="text/javascript" src="../../../../dojo/dojo.js"
+		djConfig="isDebug:true"></script>
+	<script type="text/javascript" src="../xip.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.io.proxy.xip");
+
+		function testXmlGet(){
+/*
+			//Normal xhrGet call.
+			dojo.xhrGet({
+				url: "frag.xml",
+				handleAs: "xml",
+				load: function(result, ioArgs){
+					var foo = result.getElementsByTagName("foo").item(0);
+
+					dojo.byId("xmlGetOut").innerHTML = "Success: First foobar value is: " + foo.firstChild.nodeValue;
+				}
+			});
+*/
+
+			//xip xhrGet call.
+			dojo.xhrGet({
+				iframeProxyUrl: "../xip_server.html",
+				url: "tests/frag.xml",
+				handleAs: "xml",
+				load: function(result, ioArgs){
+					var foo = result.getElementsByTagName("foo").item(0);
+
+					dojo.byId("xmlGetOut").innerHTML = "Success: First foobar value is: " + foo.firstChild.nodeValue;
+				}
+			});
+
+		}
+
+		dojo.addOnLoad(function(){
+
+		});
+	</script>
+</head>
+<body class="tundra">
+
+<h1>XHR IFrame Proxy Tests</h1>
+<p>Run this test from a web server, not from local disk.</p>
+
+<p>
+<button onclick="testXmlGet()">Test XML GET</button>
+</p>
+<div id="xmlGetOut"></div>
+
+</body>
+</html>
diff --git a/dojox/io/proxy/xip.js b/dojox/io/proxy/xip.js
index 79b7e3f..36af9f0 100644
--- a/dojox/io/proxy/xip.js
+++ b/dojox/io/proxy/xip.js
@@ -1,260 +1,437 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.io.proxy.xip"]){
-dojo._hasResource["dojox.io.proxy.xip"]=true;
 dojo.provide("dojox.io.proxy.xip");
+
 dojo.require("dojo.io.iframe");
 dojo.require("dojox.data.dom");
-dojox.io.proxy.xip={xipClientUrl:((dojo.config||djConfig)["xipClientUrl"])||dojo.moduleUrl("dojox.io.proxy","xip_client.html"),urlLimit:4000,_callbackName:(dojox._scopeName||"dojox")+".io.proxy.xip.fragmentReceived",_state:{},_stateIdCounter:0,_isWebKit:navigator.userAgent.indexOf("WebKit")!=-1,send:function(_1){
-var _2=this.xipClientUrl;
-if(_2.split(":")[0].match(/javascript/i)||_1._ifpServerUrl.split(":")[0].match(/javascript/i)){
-return;
-}
-var _3=_2.indexOf(":");
-var _4=_2.indexOf("/");
-if(_3==-1||_4<_3){
-var _5=window.location.href;
-if(_4==0){
-_2=_5.substring(0,_5.indexOf("/",9))+_2;
-}else{
-_2=_5.substring(0,(_5.lastIndexOf("/")+1))+_2;
-}
-}
-this.fullXipClientUrl=_2;
-if(typeof document.postMessage!="undefined"){
-document.addEventListener("message",dojo.hitch(this,this.fragmentReceivedEvent),false);
-}
-this.send=this._realSend;
-return this._realSend(_1);
-},_realSend:function(_6){
-var _7="XhrIframeProxy"+(this._stateIdCounter++);
-_6._stateId=_7;
-var _8=_6._ifpServerUrl+"#0:init:id="+_7+"&client="+encodeURIComponent(this.fullXipClientUrl)+"&callback="+encodeURIComponent(this._callbackName);
-this._state[_7]={facade:_6,stateId:_7,clientFrame:dojo.io.iframe.create(_7,"",_8),isSending:false,serverUrl:_6._ifpServerUrl,requestData:null,responseMessage:"",requestParts:[],idCounter:1,partIndex:0,serverWindow:null};
-return _7;
-},receive:function(_9,_a){
-var _b={};
-var _c=_a.split("&");
-for(var i=0;i<_c.length;i++){
-if(_c[i]){
-var _d=_c[i].split("=");
-_b[decodeURIComponent(_d[0])]=decodeURIComponent(_d[1]);
-}
-}
-var _e=this._state[_9];
-var _f=_e.facade;
-_f._setResponseHeaders(_b.responseHeaders);
-if(_b.status==0||_b.status){
-_f.status=parseInt(_b.status,10);
-}
-if(_b.statusText){
-_f.statusText=_b.statusText;
-}
-if(_b.responseText){
-_f.responseText=_b.responseText;
-var _10=_f.getResponseHeader("Content-Type");
-if(_10){
-var _11=_10.split(";")[0];
-if(_11.indexOf("application/xml")==0||_11.indexOf("text/xml")==0){
-_f.responseXML=dojox.data.dom.createDocument(_b.responseText,_10);
-}
-}
-}
-_f.readyState=4;
-this.destroyState(_9);
-},frameLoaded:function(_12){
-var _13=this._state[_12];
-var _14=_13.facade;
-var _15=[];
-for(var _16 in _14._requestHeaders){
-_15.push(_16+": "+_14._requestHeaders[_16]);
-}
-var _17={uri:_14._uri};
-if(_15.length>0){
-_17.requestHeaders=_15.join("\r\n");
-}
-if(_14._method){
-_17.method=_14._method;
-}
-if(_14._bodyData){
-_17.data=_14._bodyData;
-}
-this.sendRequest(_12,dojo.objectToQuery(_17));
-},destroyState:function(_18){
-var _19=this._state[_18];
-if(_19){
-delete this._state[_18];
-var _1a=_19.clientFrame.parentNode;
-_1a.removeChild(_19.clientFrame);
-_19.clientFrame=null;
-_19=null;
-}
-},createFacade:function(){
-if(arguments&&arguments[0]&&arguments[0].iframeProxyUrl){
-return new dojox.io.proxy.xip.XhrIframeFacade(arguments[0].iframeProxyUrl);
-}else{
-return dojox.io.proxy.xip._xhrObjOld.apply(dojo,arguments);
-}
-},sendRequest:function(_1b,_1c){
-var _1d=this._state[_1b];
-if(!_1d.isSending){
-_1d.isSending=true;
-_1d.requestData=_1c||"";
-_1d.serverWindow=frames[_1d.stateId];
-if(!_1d.serverWindow){
-_1d.serverWindow=document.getElementById(_1d.stateId).contentWindow;
-}
-if(typeof document.postMessage=="undefined"){
-if(_1d.serverWindow.contentWindow){
-_1d.serverWindow=_1d.serverWindow.contentWindow;
-}
-}
-this.sendRequestStart(_1b);
-}
-},sendRequestStart:function(_1e){
-var _1f=this._state[_1e];
-_1f.requestParts=[];
-var _20=_1f.requestData;
-var _21=_1f.serverUrl.length;
-var _22=this.urlLimit-_21;
-var _23=0;
-while((_20.length-_23)+_21>this.urlLimit){
-var _24=_20.substring(_23,_23+_22);
-var _25=_24.lastIndexOf("%");
-if(_25==_24.length-1||_25==_24.length-2){
-_24=_24.substring(0,_25);
-}
-_1f.requestParts.push(_24);
-_23+=_24.length;
-}
-_1f.requestParts.push(_20.substring(_23,_20.length));
-_1f.partIndex=0;
-this.sendRequestPart(_1e);
-},sendRequestPart:function(_26){
-var _27=this._state[_26];
-if(_27.partIndex<_27.requestParts.length){
-var _28=_27.requestParts[_27.partIndex];
-var cmd="part";
-if(_27.partIndex+1==_27.requestParts.length){
-cmd="end";
-}else{
-if(_27.partIndex==0){
-cmd="start";
-}
-}
-this.setServerUrl(_26,cmd,_28);
-_27.partIndex++;
-}
-},setServerUrl:function(_29,cmd,_2a){
-var _2b=this.makeServerUrl(_29,cmd,_2a);
-var _2c=this._state[_29];
-if(this._isWebKit){
-_2c.serverWindow.location=_2b;
-}else{
-_2c.serverWindow.location.replace(_2b);
-}
-},makeServerUrl:function(_2d,cmd,_2e){
-var _2f=this._state[_2d];
-var _30=_2f.serverUrl+"#"+(_2f.idCounter++)+":"+cmd;
-if(_2e){
-_30+=":"+_2e;
-}
-return _30;
-},fragmentReceivedEvent:function(evt){
-if(evt.uri.split("#")[0]==this.fullXipClientUrl){
-this.fragmentReceived(evt.data);
-}
-},fragmentReceived:function(_31){
-var _32=_31.indexOf("#");
-var _33=_31.substring(0,_32);
-var _34=_31.substring(_32+1,_31.length);
-var msg=this.unpackMessage(_34);
-var _35=this._state[_33];
-switch(msg.command){
-case "loaded":
-this.frameLoaded(_33);
-break;
-case "ok":
-this.sendRequestPart(_33);
-break;
-case "start":
-_35.responseMessage=""+msg.message;
-this.setServerUrl(_33,"ok");
-break;
-case "part":
-_35.responseMessage+=msg.message;
-this.setServerUrl(_33,"ok");
-break;
-case "end":
-this.setServerUrl(_33,"ok");
-_35.responseMessage+=msg.message;
-this.receive(_33,_35.responseMessage);
-break;
-}
-},unpackMessage:function(_36){
-var _37=_36.split(":");
-var _38=_37[1];
-_36=_37[2]||"";
-var _39=null;
-if(_38=="init"){
-var _3a=_36.split("&");
-_39={};
-for(var i=0;i<_3a.length;i++){
-var _3b=_3a[i].split("=");
-_39[decodeURIComponent(_3b[0])]=decodeURIComponent(_3b[1]);
-}
-}
-return {command:_38,message:_36,config:_39};
-}};
-dojox.io.proxy.xip._xhrObjOld=dojo._xhrObj;
-dojo._xhrObj=dojox.io.proxy.xip.createFacade;
-dojox.io.proxy.xip.XhrIframeFacade=function(_3c){
-this._requestHeaders={};
-this._allResponseHeaders=null;
-this._responseHeaders={};
-this._method=null;
-this._uri=null;
-this._bodyData=null;
-this.responseText=null;
-this.responseXML=null;
-this.status=null;
-this.statusText=null;
-this.readyState=0;
-this._ifpServerUrl=_3c;
-this._stateId=null;
-};
-dojo.extend(dojox.io.proxy.xip.XhrIframeFacade,{open:function(_3d,uri){
-this._method=_3d;
-this._uri=uri;
-this.readyState=1;
-},setRequestHeader:function(_3e,_3f){
-this._requestHeaders[_3e]=_3f;
-},send:function(_40){
-this._bodyData=_40;
-this._stateId=dojox.io.proxy.xip.send(this);
-this.readyState=2;
-},abort:function(){
-dojox.io.proxy.xip.destroyState(this._stateId);
-},getAllResponseHeaders:function(){
-return this._allResponseHeaders;
-},getResponseHeader:function(_41){
-return this._responseHeaders[_41];
-},_setResponseHeaders:function(_42){
-if(_42){
-this._allResponseHeaders=_42;
-_42=_42.replace(/\r/g,"");
-var _43=_42.split("\n");
-for(var i=0;i<_43.length;i++){
-if(_43[i]){
-var _44=_43[i].split(": ");
-this._responseHeaders[_44[0]]=_44[1];
-}
-}
+
+dojox.io.proxy.xip = {
+	//summary: Object that implements the iframe handling for XMLHttpRequest
+	//IFrame Proxying.
+	//description: Do not use this object directly. See the Dojo Book page
+	//on XMLHttpRequest IFrame Proxying:
+	//http://dojotoolkit.org/book/dojo-book-0-4/part-5-connecting-pieces/i-o/cross-domain-xmlhttprequest-using-iframe-proxy
+	//Usage of XHR IFrame Proxying does not work from local disk in Safari.
+
+	/*
+	This code is really focused on just sending one complete request to the server, and
+	receiving one complete response per iframe. The code does not expect to reuse iframes for multiple XHR request/response
+	sequences. This might be reworked later if performance indicates a need for it.
+	
+	xip fragment identifier/hash values have the form:
+	#id:cmd:realEncodedMessage
+
+	id: some ID that should be unique among message fragments. No inherent meaning,
+	        just something to make sure the hash value is unique so the message
+	        receiver knows a new message is available.
+	        
+	cmd: command to the receiver. Valid values are:
+	         - init: message used to init the frame. Sent as the first URL when loading
+	                 the page. Contains some config parameters.
+	         - loaded: the remote frame is loaded. Only sent from xip_client.html to this module.
+	         - ok: the message that this page sent was received OK. The next message may
+	               now be sent.
+	         - start: the start message of a block of messages (a complete message may
+	                  need to be segmented into many messages to get around the limitiations
+	                  of the size of an URL that a browser accepts.
+	         - part: indicates this is a part of a message.
+	         - end: the end message of a block of messages. The message can now be acted upon.
+	                If the message is small enough that it doesn't need to be segmented, then
+	                just one hash value message can be sent with "end" as the command.
+	
+	To reassemble a segmented message, the realEncodedMessage parts just have to be concatenated
+	together.
+	*/
+
+	xipClientUrl: ((dojo.config || djConfig)["xipClientUrl"]) || dojo.moduleUrl("dojox.io.proxy", "xip_client.html"),
+
+
+	//MSIE has the lowest limit for URLs with fragment identifiers,
+	//at around 4K. Choosing a slightly smaller number for good measure.
+	urlLimit: 4000,
+
+	_callbackName: (dojox._scopeName || "dojox") + ".io.proxy.xip.fragmentReceived",
+	_state: {},
+	_stateIdCounter: 0,
+	_isWebKit: navigator.userAgent.indexOf("WebKit") != -1,
+
+
+	send: function(/*Object*/facade){
+		//summary: starts the xdomain request using the provided facade.
+		//This method first does some init work, then delegates to _realSend.
+
+		var url = this.xipClientUrl;
+		//Make sure we are not dealing with javascript urls, just to be safe.
+		if(url.split(":")[0].match(/javascript/i) || facade._ifpServerUrl.split(":")[0].match(/javascript/i)){
+			return;
+		}
+		
+		//Make xip_client a full URL.
+		var colonIndex = url.indexOf(":");
+		var slashIndex = url.indexOf("/");
+		if(colonIndex == -1 || slashIndex < colonIndex){
+			//No colon or we are starting with a / before a colon, so we need to make a full URL.
+			var loc = window.location.href;
+			if(slashIndex == 0){
+				//Have a full path, just need the domain.
+				url = loc.substring(0, loc.indexOf("/", 9)) + url; //Using 9 to get past http(s)://
+			}else{
+				url = loc.substring(0, (loc.lastIndexOf("/") + 1)) + url;
+			}
+		}
+		this.fullXipClientUrl = url;
+
+		//Set up an HTML5 messaging listener if postMessage exists.
+		//As of this writing, this is only useful to get Opera 9.25+ to work.
+		if(typeof document.postMessage != "undefined"){
+			document.addEventListener("message", dojo.hitch(this, this.fragmentReceivedEvent), false);
+		}
+
+		//Now that we did first time init, always use the realSend method.
+		this.send = this._realSend;
+		return this._realSend(facade); //Object
+	},
+
+	_realSend: function(facade){
+		//summary: starts the actual xdomain request using the provided facade.
+		var stateId = "XhrIframeProxy" + (this._stateIdCounter++);
+		facade._stateId = stateId;
+
+		var frameUrl = facade._ifpServerUrl + "#0:init:id=" + stateId + "&client=" 
+			+ encodeURIComponent(this.fullXipClientUrl) + "&callback=" + encodeURIComponent(this._callbackName);
+
+		this._state[stateId] = {
+			facade: facade,
+			stateId: stateId,
+			clientFrame: dojo.io.iframe.create(stateId, "", frameUrl),
+			isSending: false,
+			serverUrl: facade._ifpServerUrl,
+			requestData: null,
+			responseMessage: "",
+			requestParts: [],
+			idCounter: 1,
+			partIndex: 0,
+			serverWindow: null
+		};
+
+		return stateId; //Object
+	},
+
+	receive: function(/*String*/stateId, /*String*/urlEncodedData){
+		/* urlEncodedData should have the following params:
+				- responseHeaders
+				- status
+				- statusText
+				- responseText
+		*/
+		//Decode response data.
+		var response = {};
+		var nvPairs = urlEncodedData.split("&");
+		for(var i = 0; i < nvPairs.length; i++){
+			if(nvPairs[i]){
+				var nameValue = nvPairs[i].split("=");
+				response[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]);
+			}
+		}
+
+		//Set data on facade object.
+		var state = this._state[stateId];
+		var facade = state.facade;
+
+		facade._setResponseHeaders(response.responseHeaders);
+		if(response.status == 0 || response.status){
+			facade.status = parseInt(response.status, 10);
+		}
+		if(response.statusText){
+			facade.statusText = response.statusText;
+		}
+		if(response.responseText){
+			facade.responseText = response.responseText;
+			
+			//Fix responseXML.
+			var contentType = facade.getResponseHeader("Content-Type");
+			if(contentType){
+				var mimeType = contentType.split(";")[0];
+				if(mimeType.indexOf("application/xml") == 0 || mimeType.indexOf("text/xml") == 0){
+					facade.responseXML = dojox.data.dom.createDocument(response.responseText, contentType);
+				}
+			}
+		}
+		facade.readyState = 4;
+		
+		this.destroyState(stateId);
+	},
+
+	frameLoaded: function(/*String*/stateId){
+		var state = this._state[stateId];
+		var facade = state.facade;
+
+		var reqHeaders = [];
+		for(var param in facade._requestHeaders){
+			reqHeaders.push(param + ": " + facade._requestHeaders[param]);
+		}
+
+		var requestData = {
+			uri: facade._uri
+		};
+		if(reqHeaders.length > 0){
+			requestData.requestHeaders = reqHeaders.join("\r\n");		
+		}
+		if(facade._method){
+			requestData.method = facade._method;
+		}
+		if(facade._bodyData){
+			requestData.data = facade._bodyData;
+		}
+
+		this.sendRequest(stateId, dojo.objectToQuery(requestData));
+	},
+	
+	destroyState: function(/*String*/stateId){
+		var state = this._state[stateId];
+		if(state){
+			delete this._state[stateId];
+			var parentNode = state.clientFrame.parentNode;
+			parentNode.removeChild(state.clientFrame);
+			state.clientFrame = null;
+			state = null;
+		}
+	},
+
+	createFacade: function(){
+		if(arguments && arguments[0] && arguments[0].iframeProxyUrl){
+			return new dojox.io.proxy.xip.XhrIframeFacade(arguments[0].iframeProxyUrl);
+		}else{
+			return dojox.io.proxy.xip._xhrObjOld.apply(dojo, arguments);
+		}
+	},
+	
+	//**** State-bound methods ****
+	sendRequest: function(stateId, encodedData){
+		var state = this._state[stateId];
+		if(!state.isSending){
+			state.isSending = true;
+
+			state.requestData = encodedData || "";
+
+			//Get a handle to the server iframe.
+			state.serverWindow = frames[state.stateId];
+			if (!state.serverWindow){
+				state.serverWindow = document.getElementById(state.stateId).contentWindow;
+			}
+
+			//Make sure we have contentWindow, but only do this for non-postMessage
+			//browsers (right now just opera is postMessage).
+			if(typeof document.postMessage == "undefined"){
+				if(state.serverWindow.contentWindow){
+					state.serverWindow = state.serverWindow.contentWindow;
+				}
+			}
+
+			this.sendRequestStart(stateId);
+		}
+	},
+
+	sendRequestStart: function(stateId){
+		//Break the message into parts, if necessary.
+		var state = this._state[stateId];
+		state.requestParts = [];
+		var reqData = state.requestData;
+		var urlLength = state.serverUrl.length;
+		var partLength = this.urlLimit - urlLength;
+		var reqIndex = 0;
+
+		while((reqData.length - reqIndex) + urlLength > this.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);
+			}
+			state.requestParts.push(part);
+			reqIndex += part.length;
+		}
+		state.requestParts.push(reqData.substring(reqIndex, reqData.length));
+		
+		state.partIndex = 0;
+		this.sendRequestPart(stateId);
+
+	},
+	
+	sendRequestPart: function(stateId){
+		var state = this._state[stateId];
+
+		if(state.partIndex < state.requestParts.length){
+			//Get the message part.
+			var partData = state.requestParts[state.partIndex];
+
+			//Get the command.
+			var cmd = "part";
+			if(state.partIndex + 1 == state.requestParts.length){
+				cmd = "end";
+			}else if (state.partIndex == 0){
+				cmd = "start";
+			}
+			
+			this.setServerUrl(stateId, cmd, partData);
+			state.partIndex++;
+		}
+	},
+
+	setServerUrl: function(stateId, cmd, message){
+		var serverUrl = this.makeServerUrl(stateId, cmd, message);
+		var state = this._state[stateId];
+
+		//Safari won't let us replace across domains.
+		if(this._isWebKit){
+			state.serverWindow.location = serverUrl;
+		}else{
+			state.serverWindow.location.replace(serverUrl);
+		}
+	},
+
+	makeServerUrl: function(stateId, cmd, message){
+		var state = this._state[stateId];
+		var serverUrl = state.serverUrl + "#" + (state.idCounter++) + ":" + cmd;
+		if(message){
+			serverUrl += ":" + message;
+		}
+		return serverUrl;
+	},
+
+	fragmentReceivedEvent: function(evt){
+		//summary: HTML5 document messaging endpoint. Unpack the event to see
+		//if we want to use it.
+		if(evt.uri.split("#")[0] == this.fullXipClientUrl){
+			this.fragmentReceived(evt.data);
+		}
+	},
+
+	fragmentReceived: function(frag){
+		var index = frag.indexOf("#");
+		var stateId = frag.substring(0, index);
+		var encodedData = frag.substring(index + 1, frag.length);
+
+		var msg = this.unpackMessage(encodedData);
+		var state = this._state[stateId];
+
+		switch(msg.command){
+			case "loaded":
+				this.frameLoaded(stateId);
+				break;
+			case "ok":
+				this.sendRequestPart(stateId);
+				break;
+			case "start":
+				state.responseMessage = "" + msg.message;
+				this.setServerUrl(stateId, "ok");
+				break;
+			case "part":
+				state.responseMessage += msg.message;			
+				this.setServerUrl(stateId, "ok");
+				break;
+			case "end":
+				this.setServerUrl(stateId, "ok");
+				state.responseMessage += msg.message;
+				this.receive(stateId, state.responseMessage);
+				break;
+		}
+	},
+	
+	unpackMessage: function(encodedMessage){
+		var parts = encodedMessage.split(":");
+		var command = parts[1];
+		encodedMessage = parts[2] || "";
+
+		var config = null;
+		if(command == "init"){
+			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]);
+			}
+		}
+		return {command: command, message: encodedMessage, config: config};
+	}
 }
-}});
+
+//Replace the normal XHR factory with the proxy one.
+dojox.io.proxy.xip._xhrObjOld = dojo._xhrObj;
+dojo._xhrObj = dojox.io.proxy.xip.createFacade;
+
+/**
+	Using this a reference: http://www.w3.org/TR/XMLHttpRequest/
+
+	Does not implement the onreadystate callback since dojo.xhr* does
+	not use it.
+*/
+dojox.io.proxy.xip.XhrIframeFacade = function(ifpServerUrl){
+	//summary: XMLHttpRequest facade object used by dojox.io.proxy.xip.
+	
+	//description: Do not use this object directly. See the Dojo Book page
+	//on XMLHttpRequest IFrame Proxying:
+	//http://dojotoolkit.org/book/dojo-book-0-4/part-5-connecting-pieces/i-o/cross-domain-xmlhttprequest-using-iframe-proxy
+	this._requestHeaders = {};
+	this._allResponseHeaders = null;
+	this._responseHeaders = {};
+	this._method = null;
+	this._uri = null;
+	this._bodyData = null;
+	this.responseText = null;
+	this.responseXML = null;
+	this.status = null;
+	this.statusText = null;
+	this.readyState = 0;
+	
+	this._ifpServerUrl = ifpServerUrl;
+	this._stateId = null;
 }
+
+dojo.extend(dojox.io.proxy.xip.XhrIframeFacade, {
+	//The open method does not properly reset since Dojo does not reuse XHR objects.
+	open: function(/*String*/method, /*String*/uri){
+		this._method = method;
+		this._uri = uri;
+
+		this.readyState = 1;
+	},
+	
+	setRequestHeader: function(/*String*/header, /*String*/value){
+		this._requestHeaders[header] = value;
+	},
+	
+	send: function(/*String*/stringData){
+		this._bodyData = stringData;
+		
+		this._stateId = dojox.io.proxy.xip.send(this);
+		
+		this.readyState = 2;
+	},
+	abort: function(){
+		dojox.io.proxy.xip.destroyState(this._stateId);
+	},
+	
+	getAllResponseHeaders: function(){
+		return this._allResponseHeaders; //String
+	},
+	
+	getResponseHeader: function(/*String*/header){
+		return this._responseHeaders[header]; //String
+	},
+	
+	_setResponseHeaders: function(/*String*/allHeaders){
+		if(allHeaders){
+			this._allResponseHeaders = allHeaders;
+			
+			//Make sure ther are now CR characters in the headers.
+			allHeaders = allHeaders.replace(/\r/g, "");
+			var nvPairs = allHeaders.split("\n");
+			for(var i = 0; i < nvPairs.length; i++){
+				if(nvPairs[i]){
+					var nameValue = nvPairs[i].split(": ");
+					this._responseHeaders[nameValue[0]] = nameValue[1];
+				}
+			}
+		}
+	}
+});
diff --git a/dojox/io/proxy/xip_client.html b/dojox/io/proxy/xip_client.html
index c51a839..ff4e19b 100644
--- a/dojox/io/proxy/xip_client.html
+++ b/dojox/io/proxy/xip_client.html
@@ -1,6 +1,6 @@
 <!--
 	/*
-		Copyright (c) 2004-2008, The Dojo Foundation
+		Copyright (c) 2004-2010, The Dojo Foundation
 		All Rights Reserved.
 	
 		Licensed under the Academic Free License version 2.1 or above OR the
diff --git a/dojox/io/proxy/xip_server.html b/dojox/io/proxy/xip_server.html
index 01b7274..e55149d 100644
--- a/dojox/io/proxy/xip_server.html
+++ b/dojox/io/proxy/xip_server.html
@@ -1,6 +1,6 @@
 <!--
 	/*
-		Copyright (c) 2004-2008, The Dojo Foundation
+		Copyright (c) 2004-2010, The Dojo Foundation
 		All Rights Reserved.
 	
 		Licensed under the Academic Free License version 2.1 or above OR the
diff --git a/dojox/io/scriptFrame.js b/dojox/io/scriptFrame.js
index 7281466..0d197f2 100644
--- a/dojox/io/scriptFrame.js
+++ b/dojox/io/scriptFrame.js
@@ -1,52 +1,85 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.io.scriptFrame"]){
-dojo._hasResource["dojox.io.scriptFrame"]=true;
 dojo.provide("dojox.io.scriptFrame");
+
 dojo.require("dojo.io.script");
 dojo.require("dojo.io.iframe");
+
+//This module extends dojo.io.script to use an iframe for the dojo.io.script.attach calls
+//if the frameDoc argument is passed to dojo.io.script.get(), and if frameDoc is a string (representing
+//the DOM ID of an iframe that should be used for the connection. If frameDoc is not a string, then
+//it is probably a document object, and dojox.io.scriptFrame should not get involved with the request.
+//This is useful in some long-polling comet situations in Firefox and Opera. Those browsers execute scripts
+//in DOM order, not network-receive order, so a long-polling script will block other
+//dynamically appended scripts from running until it completes. By using an iframe
+//for the dojo.io.script requests, this issue can be avoided.
+
+//WARNING: the url argument to dojo.io.script MUST BE relative to the iframe document's location,
+//NOT the parent page location. This iframe document's URL will be (dojo.moduleUrl("dojo", "resources/blank.html")
+//or djConfig.dojoBlankHtmlUrl (for xdomain loading).
+
 (function(){
-var _1=dojo.io.script;
-dojox.io.scriptFrame={_waiters:{},_loadedIds:{},_getWaiters:function(_2){
-return this._waiters[_2]||(this._waiters[_2]=[]);
-},_fixAttachUrl:function(_3){
-},_loaded:function(_4){
-var _5=this._getWaiters(_4);
-this._loadedIds[_4]=true;
-this._waiters[_4]=null;
-for(var i=0;i<_5.length;i++){
-var _6=_5[i];
-_6.frameDoc=dojo.io.iframe.doc(dojo.byId(_4));
-_1.attach(_6.id,_6.url,_6.frameDoc);
-}
-}};
-var _7=_1._canAttach;
-var _8=dojox.io.scriptFrame;
-_1._canAttach=function(_9){
-var _a=_9.args.frameDoc;
-if(_a&&dojo.isString(_a)){
-var _b=dojo.byId(_a);
-var _c=_8._getWaiters(_a);
-if(!_b){
-_c.push(_9);
-dojo.io.iframe.create(_a,dojox._scopeName+".io.scriptFrame._loaded('"+_a+"');");
-}else{
-if(_8._loadedIds[_a]){
-_9.frameDoc=dojo.io.iframe.doc(_b);
-this.attach(_9.id,_9.url,_9.frameDoc);
-}else{
-_c.push(_9);
-}
-}
-return false;
-}else{
-return _7.apply(this,arguments);
-}
-};
+	var ioScript = dojo.io.script;
+	dojox.io.scriptFrame = {
+		_waiters: {},
+		_loadedIds: {},
+
+		_getWaiters: function(/*String*/frameId){
+			return this._waiters[frameId] || (this._waiters[frameId] = []);
+		},
+
+		_fixAttachUrl: function(/*String*/url){
+			//summary: fixes the URL so that 		
+		},
+
+		_loaded: function(/*String*/frameId){
+			//summary: callback used when waiting for a frame to load (related to the usage of
+			//the frameId argument to dojo.io.script.get().
+			var waiters = this._getWaiters(frameId);
+			this._loadedIds[frameId] = true;
+			this._waiters[frameId] = null;
+
+			for(var i = 0; i < waiters.length; i++){
+				var ioArgs = waiters[i];
+				ioArgs.frameDoc = dojo.io.iframe.doc(dojo.byId(frameId));
+				ioScript.attach(ioArgs.id, ioArgs.url, ioArgs.frameDoc);
+			}
+		}
+	};
+
+	//Hold on to the old _canAttach function.
+	var oldCanAttach = ioScript._canAttach;
+	var scriptFrame = dojox.io.scriptFrame;
+
+	//Define frame-aware _canAttach method on dojo.io.script
+	ioScript._canAttach = function(/*Object*/ioArgs){
+		//summary: provides an override of dojo.io.script._canAttach to check for
+		//the existence of a the args.frameDoc property. If it is there, and it is a string,
+		//not a document, then create the iframe with an ID of frameDoc, and use that for the calls.
+		//If frameDoc is a document, then dojox.io.scriptFrame should not get involved.
+		var fId = ioArgs.args.frameDoc;
+
+		if(fId && dojo.isString(fId)){
+			var frame = dojo.byId(fId);
+			var waiters = scriptFrame._getWaiters(fId);
+			if(!frame){
+				//Need to create frame, but the frame document, which *must* be
+				//on the same domain as the page (set djConfig.dojoBlankHtmlUrl
+				//if using xdomain loading). Loading of the frame document is asynchronous,
+				//so we need to do callback stuff.
+				waiters.push(ioArgs);
+				dojo.io.iframe.create(fId, dojox._scopeName + ".io.scriptFrame._loaded('" + fId + "');");
+			}else{
+				//Frame loading could still be happening. Only call attach if the frame has loaded.
+				if(scriptFrame._loadedIds[fId]){
+					ioArgs.frameDoc = dojo.io.iframe.doc(frame);
+					this.attach(ioArgs.id, ioArgs.url, ioArgs.frameDoc);
+				}else{
+					waiters.push(ioArgs);
+				}
+			}
+			return false;
+		}else{
+			return oldCanAttach.apply(this, arguments);
+		}
+	}
 })();
-}
+
diff --git a/dojox/io/tests/attackerFrame.html b/dojox/io/tests/attackerFrame.html
new file mode 100644
index 0000000..df267bd
--- /dev/null
+++ b/dojox/io/tests/attackerFrame.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Attacker Frame Test</title>
+	<script type="text/javascript">
+	var switchedLocation;
+	var intervalId = setInterval(function(){
+		try{
+			if(!switchedLocation){
+				parent.frames[1].name='malicious data';
+				alert("changing to "+ (parent.frames[1][0][0].location = "http://127.0.0.1/dojox/io/tests/"));
+				switchedLocation = true;
+			}
+			alert("snooping for "+ parent.frames[1].name);
+			clearInterval(intervalId);
+		}
+		catch(e){}
+	},10);
+	function check(){
+		if(switchedLocation){
+			alert("other " + parent.frames[1][0][0].name);
+		}
+		alert("trying to delete"+parent['protectedFrame']);
+		(parent.frames[1].location = "http://127.0.0.1/dojox/io/tests/");
+		switchedLocation = true;
+		alert("changed ");
+		
+	}
+	</script>
+</head>
+<body class="tundra">
+<div onclick="check()">fire</div>
+</body>
+</html>
diff --git a/dojox/io/tests/crossSite.php b/dojox/io/tests/crossSite.php
new file mode 100644
index 0000000..0c48eea
--- /dev/null
+++ b/dojox/io/tests/crossSite.php
@@ -0,0 +1,12 @@
+<?php
+	header("XDomainRequestAllowed: 1");
+	header("Access-Control: allow <*>");
+	if ($_REQUEST["url"]) {
+		print "proxied";
+	}
+	if ($_REQUEST["windowname"]) {
+		print "<html><script type='text/javascript'>window.name='cross-site response'</script></html>";
+	}
+
+?>
+cross-site response
\ No newline at end of file
diff --git a/dojox/io/tests/result.txt b/dojox/io/tests/result.txt
new file mode 100644
index 0000000..f985b46
--- /dev/null
+++ b/dojox/io/tests/result.txt
@@ -0,0 +1 @@
+Success!
diff --git a/dojox/io/tests/scriptFrame.html b/dojox/io/tests/scriptFrame.html
new file mode 100644
index 0000000..a360eb5
--- /dev/null
+++ b/dojox/io/tests/scriptFrame.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Testing dojox.io.scriptFrame</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("doh.runner");
+			dojo.require("dojox.io.scriptFrame");
+
+			dojo.addOnLoad(function(){
+				doh.register("t", 
+					[
+						function ioScriptJsonp(t){
+							var d = new doh.Deferred();
+							var td = dojo.io.script.get({
+								//Note that this URL path is relative to the URL of the iframe document
+								//(dojo.moduleUrl("dojo.resources", "blank.html")
+								url: "../tests/io/scriptJsonp.js",
+								content: { foo: "bar" },
+								callbackParamName: "callback",
+								frameDoc: "testFrame"
+							});
+							td.addBoth(function(res){
+								if(!(res instanceof Error) && 
+									t.is("mammal", res.animalType)){
+									d.callback(true);
+								}else{
+									d.errback(false);
+								}
+							});
+							return d;							
+						},
+						function ioScriptJsonpTimeout(t){
+							var d = new doh.Deferred();
+							var td = dojo.io.script.get({
+								//Note that this URL path is relative to the URL of the iframe document
+								//(dojo.moduleUrl("dojo.resources", "blank.html")
+								url: "../tests/_base/timeout.php",
+								callbackParamName: "callback",
+								content: {Foo: 'Bar'},
+								timeout: 500,
+								handleAs: "json",
+								preventCache: true,
+								handle: function(response, ioArgs){
+									if(response instanceof Error && response.dojoType == "timeout"){
+										console.debug("FOO OK TEST");
+										d.callback(true);
+									}else{
+										console.debug("FOO FAIL TEST");
+										d.errback(false);
+									}
+								},
+								frameDoc: "testFrame"
+							});
+							return d;
+						}
+					]
+				);
+				doh.run();
+			});
+
+/*
+			dojo.addOnLoad(function(){
+				td = dojo.io.script.get({
+					url: "scriptSimple.js",
+					checkString: "myTasks"
+				});
+				td.addCallback(function(res){
+					alert(myTasks);
+					alert(myTasks[1]);
+					if(typeof(myTasks) != "undefined"
+						&& "Do dishes." == myTasks[1]){
+						alert("yeah");
+					}else{
+						alert("boo");
+					}
+				});
+			});
+*/
+
+		</script>
+	</head>
+	<body>
+
+	</body>
+</html>
diff --git a/dojox/io/tests/scriptFrame.js b/dojox/io/tests/scriptFrame.js
new file mode 100644
index 0000000..09a3702
--- /dev/null
+++ b/dojox/io/tests/scriptFrame.js
@@ -0,0 +1,5 @@
+dojo.provide("dojox.io.tests.scriptFrame");
+
+if(dojo.isBrowser){
+	doh.registerUrl("dojox.io.tests.scriptFrame", dojo.moduleUrl("dojox.io.tests", "scriptFrame.html"));
+}
diff --git a/dojox/io/tests/scriptFrameRepeat.html b/dojox/io/tests/scriptFrameRepeat.html
new file mode 100644
index 0000000..4be97a9
--- /dev/null
+++ b/dojox/io/tests/scriptFrameRepeat.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Testing repeat dojox.io.scriptFrame calls</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+		</style>
+		<script type="text/javascript" 
+			src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.io.scriptFrame");
+
+			function repeatCall(){
+				var td = dojo.io.script.get({
+					//Note that this URL path is relative to the URL of the iframe document
+					//(dojo.moduleUrl("dojo.resources", "blank.html")
+					url: "../tests/io/scriptJsonp.js",
+					content: { foo: "bar" },
+					callbackParamName: "callback",
+					frameDoc: "testFrame",
+					timeout: 3000
+				});
+				td.addBoth(function(res){
+					if(!(res instanceof Error) && "mammal" == res.animalType){
+						console.log("success");
+					}else{
+						console.error(res);
+					}
+					return res;
+				});
+			};
+
+			dojo.addOnLoad(function(){
+				setInterval(repeatCall, 2000);
+			});
+
+		</script>
+	</head>
+	<body>
+		<p>This page tests repeat usage of dojo.io.script.get() with the dojox.io.scriptFrame extensions.</p>
+		<p>Inspect the iframe created by dojox.io.scriptFrame to see if it is performing correctly.</p>
+	</body>
+</html>
diff --git a/dojox/io/tests/windowName.html b/dojox/io/tests/windowName.html
new file mode 100644
index 0000000..762213d
--- /dev/null
+++ b/dojox/io/tests/windowName.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Window Name Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+	<script type="text/javascript" src="../windowName.js"></script>
+	<script type="text/javascript">
+	//dojox.io.xhrWindowNamePlugin("http://localhost");
+function test(auth) {
+	var authTarget = auth && document.getElementById("authTarget");
+	var dfd = dojox.io.windowName.send("GET",{
+				url: prompt("Enter an address to retrieve data from",
+						auth ? "http://sitepen.com:80/labs/code/secure/dojox/io/tests/testResource.html" : "http://persevere.sitepen.com/Customer/37"),
+				handleAs:"text",
+				authElement: authTarget,
+				onAuthLoad: auth && function(){
+					authTarget.style.display='block';
+				}});
+	dfd.addBoth(function(result){
+		auth && (authTarget.style.display='none');
+		alert(result)
+	});
+}
+function testPost(auth) {
+	var authTarget = auth && document.getElementById("authTarget");
+	var dfd = dojox.io.windowName.send("POST",{
+				url: prompt("Enter an address to post data to",
+						"http://persevere.sitepen.com/Customer/"),
+				content:{foo:"bar"},
+				authElement: authTarget,
+				onAuthLoad: auth && function(){
+					authTarget.style.display='block';
+				}});
+	dfd.addBoth(function(result){
+		auth && (authTarget.style.display='none');
+		alert(result)
+	});
+}
+	</script>
+</head>
+<body class="tundra">
+	<h1>Window Name Test</h1>
+	<div id="authTarget" style="display:none; border: 3px solid blue; width: 300px; height:200px;"></div>
+	<p>This page allows you try getting and posting data cross-site and get the response using the window.name protocol.
+	There are two forms of the window.name protocol, the simple direct access protocol, where the resource simply
+	has to set the window.name property. There is also window.name with authorization. In this second variant,
+	the resource page must redirect to the return URL after setting the window.name property. This example page
+	lets you try out both protocols using GET or POST.</p>
+	<button onclick="test()">get data direct</button>
+	<button onclick="testPost()">post data direct</button>
+	<button onclick="test(true)">get data with authorization</button>
+	<button onclick="testPost(true)">post data with authorization</button>
+	</body>
+</html>
diff --git a/dojox/io/tests/windowName.js b/dojox/io/tests/windowName.js
new file mode 100644
index 0000000..39d3250
--- /dev/null
+++ b/dojox/io/tests/windowName.js
@@ -0,0 +1,59 @@
+dojo.provide("dojox.io.tests.xhrPlugins");
+dojo.require("dojox.io.xhrPlugins");
+
+dojox.io.xhrPlugins.addXdr("http://xdrsupportingsite.com/"); // make sure the registry is setup
+var url = dojo.moduleUrl("dojox.io.tests.crossSite");
+url = url.toString();
+url = url.substring(0,url.length-1) + ".php";
+
+doh.register("dojox.io.tests.xhrPlugins", [
+	function getLocal(t){
+		var d = new doh.Deferred();
+		var dfd = dojo.xhr("GET",{url:url});
+		dfd.addCallback(function(result){
+			d.callback(result.match(/response/));
+		});
+		return d;
+	},
+
+	function crossSiteRequest(t){
+		// Note: this isn't really testing much unless you are using IE8 (XDomainRequest) or a 
+		// browser that supports cross-site XHR (maybe FF3.1?) 
+		var d = new doh.Deferred();
+		// persevere supports both XDR and cross-site XHR so we can use it for cross-site testing for now
+		dojox.io.xhrPlugins.addXdr("http://persevere.sitepen.com/");
+		dojox.io.xhrPlugins.addCrossSiteXhr("http://persevere.sitepen.com/");
+		try {
+			var dfd = dojo.xhr("GET",{url:"http://persevere.sitepen.com/SMD"});
+		}
+		catch (e){
+			if(e.message.match(/No match/)){
+				return null; // this browser doesn't support this transport
+			}
+			throw e;
+		}
+		dfd.addCallback(function(result){
+			d.callback(result.match(/transport/)); 
+		});
+		// TODO: This should run off a fixed URL on some Dojo server.  
+		
+/*		dojox.io.xhrPlugins.addXdr("http://dojotoolkit.org/...");
+		dojox.io.xhrPlugins.addCrossSiteXhr("http://dojotoolkit.org/...");
+				
+		var dfd = dojo.xhr("GET",{url:"http://dojotoolkit.org/.../dojox/io/tests/crossSite.php"});
+		dfd.addCallback(function(result){
+			d.callback(result.match(/response/));
+		}); */
+		return d;
+	},
+	function proxiedRequest(t){
+		var d = new doh.Deferred();
+		dojox.io.xhrPlugins.addProxy(url+"?url=");
+
+		var dfd = dojo.xhr("GET",{url:"http://someforeignsite.com/SMD"});
+		dfd.addCallback(function(result){
+			d.callback(result.match(/proxied/));
+		});
+		return d;
+	}
+]);
diff --git a/dojox/io/tests/xhrMultiPart.html b/dojox/io/tests/xhrMultiPart.html
new file mode 100644
index 0000000..d377f72
--- /dev/null
+++ b/dojox/io/tests/xhrMultiPart.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>XHR MultiPart Tests</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+	<script type="text/javascript" src="../xhrMultiPart.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.io.xhrMultiPart");
+		var content = [
+			{ name: "foo", content: "FOObarbaz", filename: "foo.txt" },
+			{ name: "bar", content: "fooBARbaz", filename: "bar.txt" },
+			{ name: "baz", content: "foobarBAZ", filename: "baz.txt" }
+		];
+
+		function testXhrMulti(){
+			dojox.io.xhrMultiPart({
+				url: "result.txt",
+				file: content,
+				load: function(data){ console.log("Test with file: ", data); }
+			});
+
+			//	should be the same.
+			dojox.io.xhrMultiPart({
+				url: "result.txt",
+				content: content,
+				load: function(data){ console.log("Test with content: ", data); }
+			});
+		}
+
+		function testXhrMultiForm(){
+			dojox.io.xhrMultiPart({
+				url: "result.txt",
+				form: dojo.byId("formTest"),
+				load: function(data){ console.log("Test with form: ", data); }
+			});
+			return false;	//	stop the submission
+		}
+
+		function testXhrMultiFormWithFile(){
+			try {
+				dojox.io.xhrMultiPart({
+					url: "result.txt",
+					form: dojo.byId("formTestWithFile"),
+					load: function(data){ console.log("Test with form: ", data); }
+				});
+			} catch(e){
+				console.warn("xhrMultiPart failed because the form contains a FILE element!");
+			}
+			return false;	//	stop the submission
+		}
+	</script>
+</head>
+<body class="tundra">
+	<h1>XHR MultiParts Tests</h1>
+	<p>Run this test from a web server, not from local disk.</p>
+	<p>
+		<button onclick="testXhrMulti()">Test xhrMultiPart</button>
+	</p>
+	<div>
+		<form id="formTest" onsubmit="return testXhrMultiForm()">
+			<input type="hidden" name="foo" value="FOObarbaz" />
+			<input type="hidden" name="bar" value="fooBARbaz" />
+			<input type="hidden" name="baz" value="foobarBAZ" />
+			<input type="submit" value="Test xhrMultiPart with form values" />
+		</form>
+	</div>
+	<div>
+		<form id="formTestWithFile" onsubmit="return testXhrMultiFormWithFile()">
+			<input type="hidden" name="foo" value="FOObarbaz" />
+			<input type="hidden" name="bar" value="fooBARbaz" />
+			<input type="hidden" name="baz" value="foobarBAZ" />
+			<input type="file" name="fileTest" value="" />
+			<input type="submit" value="Test xhrMultiPart (prevent file upload)" />
+		</form>
+	</div>
+</body>
+</html>
diff --git a/dojox/io/tests/xhrPlugins.js b/dojox/io/tests/xhrPlugins.js
new file mode 100644
index 0000000..1ee086a
--- /dev/null
+++ b/dojox/io/tests/xhrPlugins.js
@@ -0,0 +1,58 @@
+dojo.provide("dojox.io.tests.xhrPlugins");
+dojo.require("dojox.io.xhrPlugins");
+
+dojox.io.xhrPlugins.addCrossSiteXhr("http://cssupportingsite.com/"); // make sure the registry is setup
+var url = dojo.moduleUrl("dojox.io.tests.crossSite");
+url = url.toString();
+url = url.substring(0,url.length-1) + ".php";
+
+doh.register("dojox.io.tests.xhrPlugins", [
+	function getLocal(t){
+		var d = new doh.Deferred();
+		var dfd = dojo.xhr("GET",{url:url});
+		dfd.addCallback(function(result){
+			d.callback(result.match(/response/));
+		});
+		return d;
+	},
+
+	function crossSiteRequest(t){
+		// Note: this isn't really testing much unless you are using IE8 (XDomainRequest) or a 
+		// browser that supports cross-site XHR (maybe FF3.1?) 
+		var d = new doh.Deferred();
+		// persevere supports cross-site XHR so we can use it for cross-site testing for now
+		dojox.io.xhrPlugins.addCrossSiteXhr("http://persevere.sitepen.com/");
+		try {
+			var dfd = dojo.xhr("GET",{url:"http://persevere.sitepen.com/SMD"});
+		}
+		catch (e){
+			if(e.message.match(/No match/)){
+				return false; // this browser doesn't support this transport
+			}
+			throw e;
+		}
+		dfd.addCallback(function(result){
+			d.callback(result.match(/transport/)); 
+		});
+		// TODO: This should run off a fixed URL on some Dojo server.  
+		
+/*		dojox.io.xhrPlugins.addXdr("http://dojotoolkit.org/...");
+		dojox.io.xhrPlugins.addCrossSiteXhr("http://dojotoolkit.org/...");
+				
+		var dfd = dojo.xhr("GET",{url:"http://dojotoolkit.org/.../dojox/io/tests/crossSite.php"});
+		dfd.addCallback(function(result){
+			d.callback(result.match(/response/));
+		}); */
+		return d;
+	},
+	function proxiedRequest(t){
+		var d = new doh.Deferred();
+		dojox.io.xhrPlugins.addProxy(url+"?url=");
+
+		var dfd = dojo.xhr("GET",{url:"http://someforeignsite.com/SMD"});
+		dfd.addCallback(function(result){
+			d.callback(result.match(/proxied/));
+		});
+		return d;
+	}
+]);
diff --git a/dojox/io/windowName.js b/dojox/io/windowName.js
index 52bb90d..5e63dbc 100644
--- a/dojox/io/windowName.js
+++ b/dojox/io/windowName.js
@@ -1,156 +1,220 @@
-/*
-	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
-*/
+dojo.provide("dojox.io.windowName");
+// Implements the window.name transport  
 
+dojox.io.windowName = {
+	send: function(/*String*/ method, /*dojo.__IoArgs*/ args){
+		// summary:
+		//		Provides secure cross-domain request capability.
+		// 		Sends a request using an iframe (POST or GET) and reads the response through the 
+		// 		frame's window.name.
+		//
+		//	method:
+		//		The method to use to send the request, GET or POST
+		//
+		//	args:
+		//		See dojo.xhr
+		//
+		//	args.authElement: DOMNode?
+		//		By providing an authElement, this indicates that windowName should use the 
+		// 		authorized window.name protocol, relying on
+		//		the loaded XD resource to return to the provided return URL on completion
+		//		of authorization/authentication. The provided authElement will be used to place
+		//		the iframe in, so the user can interact with the server resource for authentication
+		//		and/or authorization to access the resource.
+		//
+		//	args.onAuthLoad: Function?
+		//		When using authorized access to resources, this function will be called when the
+		// 		authorization page has been loaded. (When authorization is actually completed,
+		// 		the deferred callback function is called with the result). The primary use for this
+		// 		is to make the authElement visible to the user once the resource has loaded
+		// 		(this can be preferable to showing the iframe while the resource is loading
+		// 		since it may not require authorization, it may simply return the resource). 
+		//  
+		//	description:
+		//		In order to provide a windowname transport accessible resources/web services, a server
+		// 		should check for the presence of a parameter window.name=true and if a request includes
+		// 		such a parameter, it should respond to the request with an HTML 
+		// 		document that sets it's window.name to the string that is to be 
+		// 		delivered to the client. For example, if a client makes a window.name request like:
+		// 	|	http://othersite.com/greeting?windowname=true
+		// 		And server wants to respond to the client with "Hello", it should return an html page:
+		// |	<html><script type="text/javascript">
+		// |	window.name="Hello";
+		// |	</script></html>
+		// 		One can provide XML or JSON data by simply quoting the data as a string, and parsing the data
+		// 		on the client.
+		//		If you use the authorization window.name protocol, the requester should include an
+		// 		authElement element in the args, and a request will be created like:
+		// 	|	http://othersite.com/greeting?windowname=auth
+		// 		And the server can respond like this:
+		// |	<html><script type="text/javascript">
+		// |	var loc = window.name;
+		// |	authorizationButton.onclick = function(){	
+		// |		window.name="Hello";
+		// |		location = loc;
+		// |	};
+		// |	</script></html>
+		//		When using windowName from a XD Dojo build, make sure to set the 
+		// 		dojo.dojoBlankHtmlUrl property to a local URL.
+		args.url += (args.url.match(/\?/) ? '&' : '?') + "windowname=" + (args.authElement ? "auth" : true); // indicate our desire for window.name communication
+		var authElement = args.authElement;
+		var cleanup = function(result){
+			try{
+				// we have to do this to stop the wait cursor in FF 
+				var innerDoc = dfd.ioArgs.frame.contentWindow.document;
+				innerDoc.write(" ");
+				innerDoc.close();
+			}catch(e){}
+			(authElement || dojo.body()).removeChild(dfd.ioArgs.outerFrame); // clean up
+			return result;
+		}
+		var dfd = dojo._ioSetArgs(args,cleanup,cleanup,cleanup);
+		if(args.timeout){
+			setTimeout(function(){
+					if(dfd.fired == -1){
+						dfd.callback(new Error("Timeout"));
+					}
+				},
+				args.timeout
+			);
+		}
+		var self = dojox.io.windowName;
+		if(dojo.body()){
+			// the DOM is ready
+			self._send(dfd, method, authElement, args.onAuthLoad);
+		}else{
+			// we will wait for the DOM to be ready to proceed
+			dojo.addOnLoad(function(){
+				self._send(dfd, method, authElement, args.onAuthLoad);
+			});
+		}
+		return dfd;
+	},
+	_send: function(dfd, method, authTarget, onAuthLoad){
 
-if(!dojo._hasResource["dojox.io.windowName"]){
-dojo._hasResource["dojox.io.windowName"]=true;
-dojo.provide("dojox.io.windowName");
-dojox.io.windowName={send:function(_1,_2){
-_2.url+=(_2.url.match(/\?/)?"&":"?")+"windowname="+(_2.authElement?"auth":true);
-var _3=_2.authElement;
-var _4=function(_5){
-try{
-var _6=_7.ioArgs.frame.contentWindow.document;
-_6.write(" ");
-_6.close();
-}
-catch(e){
-}
-(_3||dojo.body()).removeChild(_7.ioArgs.outerFrame);
-return _5;
-};
-var _7=dojo._ioSetArgs(_2,_4,_4,_4);
-if(_2.timeout){
-setTimeout(function(){
-if(_7.fired==-1){
-_7.callback(new Error("Timeout"));
-}
-},_2.timeout);
-}
-var _8=dojox.io.windowName;
-if(dojo.body()){
-_8._send(_7,_1,_3,_2.onAuthLoad);
-}else{
-dojo.addOnLoad(function(){
-_8._send(_7,_1,_3,_2.onAuthLoad);
-});
-}
-return _7;
-},_send:function(_9,_a,_b,_c){
-var _d=_9.ioArgs;
-var _e=dojox.io.windowName._frameNum++;
-var _f=(dojo.config.dojoBlankHtmlUrl||dojo.config.dojoCallbackUrl||dojo.moduleUrl("dojo","resources/blank.html"))+"#"+_e;
-var _10=new dojo._Url(window.location,_f);
-var doc=dojo.doc;
-var _11=_b||dojo.body();
-function _12(_13){
-_13.style.width="100%";
-_13.style.height="100%";
-_13.style.border="0px";
-};
-if(dojo.isMoz&&![].reduce){
-var _14=doc.createElement("iframe");
-_12(_14);
-if(!_b){
-_14.style.display="none";
-}
-_11.appendChild(_14);
-var _15=_14.contentWindow;
-doc=_15.document;
-doc.write("<html><body margin='0px'><iframe style='width:100%;height:100%;border:0px' name='protectedFrame'></iframe></body></html>");
-doc.close();
-var _16=_15[0];
-_15.__defineGetter__(0,function(){
-});
-_15.__defineGetter__("protectedFrame",function(){
-});
-doc=_16.document;
-doc.write("<html><body margin='0px'></body></html>");
-doc.close();
-_11=doc.body;
-}
-var _17=_d.frame=_17=doc.createElement(dojo.isIE?"<iframe name=\""+_10+"\" onload=\"dojox.io.windowName["+_e+"]()\">":"iframe");
-_12(_17);
-_d.outerFrame=_14=_14||_17;
-if(!_b){
-_14.style.display="none";
-}
-var _18=0;
-function _19(){
-var _1a=_17.contentWindow.name;
-if(typeof _1a=="string"){
-if(_1a!=_10){
-_18=2;
-_9.ioArgs.hash=_17.contentWindow.location.hash;
-_9.callback(_1a);
-}
-}
-};
-dojox.io.windowName[_e]=_17.onload=function(){
-try{
-if(!dojo.isMoz&&_17.contentWindow.location=="about:blank"){
-return;
-}
-}
-catch(e){
-}
-if(!_18){
-_18=1;
-if(_b){
-if(_c){
-_c();
-}
-}else{
-_17.contentWindow.location=_f;
-}
-}
-try{
-if(_18<2){
-_19();
-}
-}
-catch(e){
-}
-};
-_17.name=_10;
-if(_a.match(/GET/i)){
-dojo._ioAddQueryToUrl(_d);
-_17.src=_d.url;
-_11.appendChild(_17);
-if(_17.contentWindow){
-_17.contentWindow.location.replace(_d.url);
-}
-}else{
-if(_a.match(/POST/i)){
-_11.appendChild(_17);
-var _1b=dojo.doc.createElement("form");
-dojo.body().appendChild(_1b);
-var _1c=dojo.queryToObject(_d.query);
-for(var i in _1c){
-var _1d=_1c[i];
-_1d=_1d instanceof Array?_1d:[_1d];
-for(var j=0;j<_1d.length;j++){
-var _1e=doc.createElement("input");
-_1e.type="hidden";
-_1e.name=i;
-_1e.value=_1d[j];
-_1b.appendChild(_1e);
-}
-}
-_1b.method="POST";
-_1b.action=_d.url;
-_1b.target=_10;
-_1b.submit();
-_1b.parentNode.removeChild(_1b);
-}else{
-throw new Error("Method "+_a+" not supported with the windowName transport");
-}
-}
-if(_17.contentWindow){
-_17.contentWindow.name=_10;
-}
-},_frameNum:0};
+		var ioArgs = dfd.ioArgs;
+		var frameNum = dojox.io.windowName._frameNum++;
+		var sameDomainUrl = (dojo.config.dojoBlankHtmlUrl||dojo.config.dojoCallbackUrl||dojo.moduleUrl("dojo", "resources/blank.html")) + "#" + frameNum;
+		var frameName = new dojo._Url(window.location, sameDomainUrl);
+		var doc = dojo.doc;
+		var frameContainer = authTarget || dojo.body();
+		function styleFrame(frame){
+			frame.style.width="100%";
+			frame.style.height="100%";
+			frame.style.border="0px";
+		}
+		if(dojo.isMoz && ![].reduce){
+			// FF2 allows unsafe sibling frame modification,
+			// the fix for this is to create nested frames with getters and setters to protect access
+			var outerFrame = doc.createElement("iframe");
+			styleFrame(outerFrame);
+			if(!authTarget){
+				outerFrame.style.display='none';
+			}
+			frameContainer.appendChild(outerFrame);
+			
+			var firstWindow = outerFrame.contentWindow;
+			doc = firstWindow.document;
+			doc.write("<html><body margin='0px'><iframe style='width:100%;height:100%;border:0px' name='protectedFrame'></iframe></body></html>");
+			doc.close();
+			var secondWindow = firstWindow[0]; 
+			firstWindow.__defineGetter__(0,function(){});
+			firstWindow.__defineGetter__("protectedFrame",function(){});
+			doc = secondWindow.document;
+			doc.write("<html><body margin='0px'></body></html>");
+			doc.close();
+			frameContainer = doc.body;
+		}
+
+		var frame = ioArgs.frame = frame = doc.createElement(dojo.isIE ? '<iframe name="' + frameName + '" onload="dojox.io.windowName['+frameNum+']()">' : 'iframe');
+		styleFrame(frame);
+		ioArgs.outerFrame = outerFrame = outerFrame || frame;
+		if(!authTarget){
+			outerFrame.style.display='none';
+		}
+		var state = 0;
+		function getData(){
+			var data = frame.contentWindow.name;
+			if(typeof data == 'string'){
+				if(data != frameName){
+					state = 2; // we are done now
+					dfd.ioArgs.hash = frame.contentWindow.location.hash;
+					dfd.callback(data);
+				}
+			}
+		}
+		dojox.io.windowName[frameNum] = frame.onload = function(){
+			try{
+				if(!dojo.isMoz && frame.contentWindow.location =='about:blank'){
+					// opera and safari will do an onload for about:blank first, we can ignore this first onload
+					return;
+				}
+			}catch(e){
+				// if we are in the target domain, frame.contentWindow.location will throw an ignorable error 
+			}
+			if(!state){
+				// we have loaded the target resource, now time to navigate back to our domain so we can read the frame name
+				state=1;
+				if(authTarget){
+					// call the callback so it can make it visible
+					if(onAuthLoad){
+						onAuthLoad();
+					}
+				}else{
+					// we are doing a synchronous capture, go directly to our same domain URL and retrieve the resource
+					frame.contentWindow.location = sameDomainUrl;
+				}
+			}
+			// back to our domain, we should be able to access the frame name now
+			try{
+				if(state<2){
+					getData();
+				}
+			}
+			catch(e){
+			}
+			
+		};
+		frame.name = frameName;
+		if(method.match(/GET/i)){
+			// if it is a GET we can just the iframe our src url
+			dojo._ioAddQueryToUrl(ioArgs);
+			frame.src = ioArgs.url;
+			frameContainer.appendChild(frame);
+			if(frame.contentWindow){
+				frame.contentWindow.location.replace(ioArgs.url);
+			}
+		}else if(method.match(/POST/i)){
+			// if it is a POST we will build a form to post it
+			frameContainer.appendChild(frame);
+			var form = dojo.doc.createElement("form");
+			dojo.body().appendChild(form);
+			var query = dojo.queryToObject(ioArgs.query);
+			for(var i in query){
+				var values = query[i];
+				values = values instanceof Array ? values : [values];
+				for(var j = 0; j < values.length; j++){
+					// create hidden inputs for all the parameters
+					var input = doc.createElement("input");
+					input.type = 'hidden';
+					input.name = i;
+					input.value = values[j];
+					form.appendChild(input);
+				}
+			}
+			form.method = 'POST';
+			form.action = ioArgs.url;
+			form.target = frameName;// connect the form to the iframe
+			
+			form.submit();
+			form.parentNode.removeChild(form);
+		}else{
+			throw new Error("Method " + method + " not supported with the windowName transport");
+		}
+		if(frame.contentWindow){
+			frame.contentWindow.name = frameName; // IE likes it afterwards
+		}
+	},
+	_frameNum: 0 
+	
 }
diff --git a/dojox/io/xhrMultiPart.js b/dojox/io/xhrMultiPart.js
index 21db1ce..b524118 100644
--- a/dojox/io/xhrMultiPart.js
+++ b/dojox/io/xhrMultiPart.js
@@ -1,70 +1,153 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.io.xhrMultiPart"]){
-dojo._hasResource["dojox.io.xhrMultiPart"]=true;
 dojo.provide("dojox.io.xhrMultiPart");
 dojo.require("dojox.uuid.generateRandomUuid");
+
 (function(){
-function _1(_2,_3){
-if(!_2["name"]&&!_2["content"]){
-throw new Error("Each part of a multi-part request requires 'name' and 'content'.");
-}
-var _4=[];
-_4.push("--"+_3,"Content-Disposition: form-data; name=\""+_2.name+"\""+(_2["filename"]?"; filename=\""+_2.filename+"\"":""));
-if(_2["contentType"]){
-var ct="Content-Type: "+_2.contentType;
-if(_2["charset"]){
-ct+="; Charset="+_2.charset;
-}
-_4.push(ct);
-}
-if(_2["contentTransferEncoding"]){
-_4.push("Content-Transfer-Encoding: "+_2.contentTransferEncoding);
-}
-_4.push("",_2.content);
-return _4;
-};
-function _5(_6,_7){
-var o=dojo.formToObject(_6),_8=[];
-for(var p in o){
-if(dojo.isArray(o[p])){
-dojo.forEach(o[p],function(_9){
-_8=_8.concat(_1({name:p,content:_9},_7));
-});
-}else{
-_8=_8.concat(_1({name:p,content:o[p]},_7));
-}
-}
-return _8;
-};
-dojox.io.xhrMultiPart=function(_a){
-if(!_a["file"]&&!_a["content"]&&!_a["form"]){
-throw new Error("content, file or form must be provided to dojox.io.xhrMultiPart's arguments");
-}
-var _b=dojox.uuid.generateRandomUuid(),_c=[],_d="";
-if(_a["file"]||_a["content"]){
-var v=_a["file"]||_a["content"];
-dojo.forEach((dojo.isArray(v)?v:[v]),function(_e){
-_c=_c.concat(_1(_e,_b));
-});
-}else{
-if(_a["form"]){
-if(dojo.query("input[type=file]",_a["form"]).length){
-throw new Error("dojox.io.xhrMultiPart cannot post files that are values of an INPUT TYPE=FILE.  Use dojo.io.iframe.send() instead.");
-}
-_c=_5(_a["form"],_b);
-}
-}
-if(_c.length){
-_c.push("--"+_b+"--","");
-_d=_c.join("\r\n");
-}
-return dojo.rawXhrPost(dojo.mixin(_a,{contentType:"multipart/form-data; boundary="+_b,postData:_d}));
-};
+	/*=====
+	dojox.io.__xhrContentArgs = function(){
+		//	name: String
+		//		Name of the form value.
+		//	content: String
+		//		The contents of the value.
+		//	filename: String?
+		//		An optional filename to pass to the server, as defined by the boundary.
+		//	contentType: String?
+		//		An optional content-type (MIME) to pass to the server, if value is being
+		//		treated as a file.
+		//	charset: String?
+		//		Optional charset to pass, for the server to interpret the file correctly.
+		//	contentTransferEncoding: String?
+		//		Optional transfer encoding header value.
+		this.name = name;
+		this.content = content;
+		this.filename = filename;
+		this.contentType = contentType;
+		this.charset = charset;
+		this.contentTransferEncoding = contentTransferEncoding;
+	}
+	=====*/
+	function _createPart(/* dojox.io.__xhrContentArgs */args, /* String */boundary){
+		//	summary
+		//		Assemble an array of boundary parts based on the passed values in args.
+		if(!args["name"] && !args["content"]){
+			throw new Error("Each part of a multi-part request requires 'name' and 'content'.");
+		}
+
+		var tmp = [];
+		tmp.push(
+			"--" + boundary,
+			 "Content-Disposition: form-data; name=\"" + args.name + "\"" + (args["filename"] ? "; filename=\"" + args.filename + "\"" : "")
+		);
+
+		if(args["contentType"]){
+			var ct = "Content-Type: " + args.contentType;
+			if(args["charset"]){
+				ct += "; Charset=" + args.charset;
+			}
+			tmp.push(ct);
+		}
+
+		if(args["contentTransferEncoding"]){
+			tmp.push("Content-Transfer-Encoding: " + args.contentTransferEncoding);
+		}
+		tmp.push("", args.content);
+		return tmp;		//	Array
+	}
+
+	function _partsFromNode(/* DOMNode */node, /* String */boundary){
+		//	summary
+		//		Assemble an array of boundary parts based on the passed FORM node.
+		var o=dojo.formToObject(node), parts=[];
+		for(var p in o){
+			if(dojo.isArray(o[p])){
+				dojo.forEach(o[p], function(item){
+					parts = parts.concat(_createPart({ name: p, content: item }, boundary));
+				});
+			} else {
+				parts = parts.concat(_createPart({ name: p, content: o[p] }, boundary));
+			}
+		}
+		return parts;	//	Array
+	}
+
+	/*=====
+	dojox.io.__xhrMultiArgs = function(){
+		//	url: String
+		//		URL to server endpoint.
+		//	content: Object?
+		//		Contains properties with string values. These
+		//		properties will be serialized using multi-part
+		//		boundaries.
+		//	file: Object?
+		//		Alias for "content".  Provided for backwards compatibility.
+		//	timeout: Integer?
+		//		Milliseconds to wait for the response. If this time
+		//		passes, the then error callbacks are called.
+		//	form: DOMNode?
+		//		DOM node for a form. Used to extract the form values
+		//		and send to the server; each form value will be serialized
+		//		using multi-part boundaries.
+		//	preventCache: Boolean?
+		//		Default is false. If true, then a
+		//		"dojo.preventCache" parameter is sent in the request
+		//		with a value that changes with each request
+		//		(timestamp). Useful only with GET-type requests.
+		//	handleAs: String?
+		//		Acceptable values depend on the type of IO
+		//		transport (see specific IO calls for more information).
+		//	load: Function?
+		//		function(response, ioArgs){}. response is an Object, ioArgs
+		//		is of type dojo.__IoCallbackArgs. The load function will be
+		//		called on a successful response.
+		//	error: Function?
+		//		function(response, ioArgs){}. response is an Object, ioArgs
+		//		is of type dojo.__IoCallbackArgs. The error function will
+		//		be called in an error case. 
+		//	handle: Function?
+		//		function(response, ioArgs){}. response is an Object, ioArgs
+		//		is of type dojo.__IoCallbackArgs. The handle function will
+		//		be called in either the successful or error case.
+		this.url = url;
+		this.content = content;
+		this.file = file;
+		this.timeout = timeout;
+		this.form = form;
+		this.preventCache = preventCache;
+		this.handleAs = handleAs;
+		this.load = load;
+		this.error = error;
+		this.handle = handle;
+	}
+	=====*/
+	dojox.io.xhrMultiPart = function(/* dojox.io.__xhrMultiArgs */args){
+		if(!args["file"] && !args["content"] && !args["form"]){
+			throw new Error("content, file or form must be provided to dojox.io.xhrMultiPart's arguments");
+		}
+
+		// unique guid as a boundary value for multipart posts
+		var boundary=dojox.uuid.generateRandomUuid(), tmp=[], out="";
+		if(args["file"] || args["content"]){
+			var v = args["file"] || args["content"];
+			dojo.forEach((dojo.isArray(v) ? v : [v]), function(item){
+				tmp = tmp.concat(_createPart(item, boundary));
+			});
+		}
+		else if(args["form"]){
+			if(dojo.query("input[type=file]", args["form"]).length){
+				throw new Error("dojox.io.xhrMultiPart cannot post files that are values of an INPUT TYPE=FILE.  Use dojo.io.iframe.send() instead.");
+			}
+			tmp = _partsFromNode(args["form"], boundary);
+		}
+
+		if(tmp.length){
+			tmp.push("--"+boundary+"--", "");
+			out = tmp.join("\r\n");
+		}
+
+		console.log(out);
+
+		return dojo.rawXhrPost(dojo.mixin(args, {
+			contentType: "multipart/form-data; boundary=" + boundary,
+			postData: out
+		}));	//	dojo.Deferred
+	}
 })();
-}
diff --git a/dojox/io/xhrPlugins.js b/dojox/io/xhrPlugins.js
index 315d907..9fb9883 100644
--- a/dojox/io/xhrPlugins.js
+++ b/dojox/io/xhrPlugins.js
@@ -1,116 +1,173 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.io.xhrPlugins"]){
-dojo._hasResource["dojox.io.xhrPlugins"]=true;
 dojo.provide("dojox.io.xhrPlugins");
 dojo.require("dojo.AdapterRegistry");
 dojo.require("dojo._base.xhr");
-(function(){
-var _1;
-var _2;
-function _3(){
-return _2=dojox.io.xhrPlugins.plainXhr=_2||dojo._defaultXhr||dojo.xhr;
-};
-dojox.io.xhrPlugins.register=function(){
-var _4=_3();
-if(!_1){
-_1=new dojo.AdapterRegistry();
-dojo[dojo._defaultXhr?"_defaultXhr":"xhr"]=function(_5,_6,_7){
-return _1.match.apply(_1,arguments);
-};
-_1.register("xhr",function(_8,_9){
-if(!_9.url.match(/^\w*:\/\//)){
-return true;
-}
-var _a=window.location.href.match(/^.*?\/\/.*?\//)[0];
-return _9.url.substring(0,_a.length)==_a;
-},_4);
-}
-return _1.register.apply(_1,arguments);
-};
-dojox.io.xhrPlugins.addProxy=function(_b){
-var _c=_3();
-dojox.io.xhrPlugins.register("proxy",function(_d,_e){
-return true;
-},function(_f,_10,_11){
-_10.url=_b+encodeURIComponent(_10.url);
-return _c.call(dojo,_f,_10,_11);
-});
-};
-var _12;
-dojox.io.xhrPlugins.addCrossSiteXhr=function(url,_13){
-var _14=_3();
-if(_12===undefined&&window.XMLHttpRequest){
-try{
-var xhr=new XMLHttpRequest();
-xhr.open("GET","http://testing-cross-domain-capability.com",true);
-_12=true;
-dojo.config.noRequestedWithHeaders=true;
-}
-catch(e){
-_12=false;
-}
-}
-dojox.io.xhrPlugins.register("cs-xhr",function(_15,_16){
-return (_12||(window.XDomainRequest&&_16.sync!==true&&(_15=="GET"||_15=="POST"||_13)))&&(_16.url.substring(0,url.length)==url);
-},_12?_14:function(){
-var _17=dojo._xhrObj;
-dojo._xhrObj=function(){
-var xdr=new XDomainRequest();
-xdr.readyState=1;
-xdr.setRequestHeader=function(){
-};
-xdr.getResponseHeader=function(_18){
-return _18=="Content-Type"?xdr.contentType:null;
-};
-function _19(_1a,_1b){
-return function(){
-xdr.readyState=_1b;
-xdr.status=_1a;
-};
-};
-xdr.onload=_19(200,4);
-xdr.onprogress=_19(200,3);
-xdr.onerror=_19(404,4);
-return xdr;
-};
-var dfd=(_13?_13(_3()):_3()).apply(dojo,arguments);
-dojo._xhrObj=_17;
-return dfd;
-});
-};
-dojox.io.xhrPlugins.fullHttpAdapter=function(_1c,_1d){
-return function(_1e,_1f,_20){
-var _21={};
-var _22={};
-if(_1e!="GET"){
-_22["http-method"]=_1e;
-if(_1f.putData&&_1d){
-_21["http-content"]=_1f.putData;
-delete _1f.putData;
-_20=false;
-}
-if(_1f.postData&&_1d){
-_21["http-content"]=_1f.postData;
-delete _1f.postData;
-_20=false;
-}
-_1e="POST";
-}
-for(var i in _1f.headers){
-var _23=i.match(/^X-/)?i.substring(2).replace(/-/g,"_").toLowerCase():("http-"+i);
-_22[_23]=_1f.headers[i];
-}
-_1f.query=dojo.objectToQuery(_22);
-dojo._ioAddQueryToUrl(_1f);
-_1f.content=dojo.mixin(_1f.content||{},_21);
-return _1c.call(dojo,_1e,_1f,_20);
-};
-};
+
+(function() {
+	var registry;
+	var plainXhr;
+	function getPlainXhr(){
+		return plainXhr = dojox.io.xhrPlugins.plainXhr = plainXhr || dojo._defaultXhr || dojo.xhr;
+	}
+	dojox.io.xhrPlugins.register = function(){
+		//	summary:
+		// 		overrides the default xhr handler to implement a registry of
+		// 		xhr handlers
+		var plainXhr = getPlainXhr();
+		if(!registry){
+			registry = new dojo.AdapterRegistry();
+			// replaces the default xhr() method. Can we just use connect() instead?
+			dojo[dojo._defaultXhr ? "_defaultXhr" : "xhr"] = function(/*String*/ method, /*dojo.__XhrArgs*/ args, /*Boolean?*/ hasBody){
+				return registry.match.apply(registry,arguments);						
+			};
+			registry.register(
+				"xhr",
+				function(method,args){ 
+					if(!args.url.match(/^\w*:\/\//)){
+						// if it is not an absolute url (or relative to the
+						// protocol) we can use this plain XHR
+						return true;
+					}
+					var root = window.location.href.match(/^.*?\/\/.*?\//)[0];
+					return args.url.substring(0, root.length) == root; // or check to see if we have the same path
+				},
+				plainXhr
+			);
+		}
+		return registry.register.apply(registry, arguments);
+	};
+	dojox.io.xhrPlugins.addProxy = function(proxyUrl){
+		//	summary:
+		//		adds a server side proxy xhr handler for cross-site URLs
+		//	proxyUrl:
+		//		This is URL to send the requests to.
+		//	example:
+		//		Define a proxy:
+		//	|	dojox.io.xhrPlugins.addProxy("/proxy?url=");
+		// 		And then when you call:
+		//	|	dojo.xhr("GET",{url:"http://othersite.com/file"});
+		// 		It would result in the request (to your origin server):
+		//	|	GET /proxy?url=http%3A%2F%2Fothersite.com%2Ffile HTTP/1.1
+		var plainXhr = getPlainXhr();
+		dojox.io.xhrPlugins.register(
+			"proxy",
+			function(method,args){
+				// this will match on URL
+
+				// really can be used for anything, but plain XHR will take
+				// precedent by order of loading 
+				return true; 
+			},
+			function(method,args,hasBody){
+				args.url = proxyUrl + encodeURIComponent(args.url);
+				return plainXhr.call(dojo, method, args, hasBody);
+			});
+	};
+	var csXhrSupport;
+	dojox.io.xhrPlugins.addCrossSiteXhr = function(url, httpAdapter){
+		//	summary:
+		// 		Adds W3C Cross site XHR or XDomainRequest handling for the given URL prefix
+		//
+		// 	url: 
+		//		Requests that start with this URL will be considered for using 
+		// 		cross-site XHR.
+		//
+		// 	httpAdapter: This allows for adapting HTTP requests that could not otherwise be 
+		// 		sent with XDR, so you can use a convention for headers and PUT/DELETE methods.
+		//
+		//	description:
+		// 		This can be used for servers that support W3C cross-site XHR. In order for 
+		// 		a server to allow a client to make cross-site XHR requests, 
+		// 		it should respond with the header like:
+		//	|	Access-Control: allow <*>
+		//		see: http://www.w3.org/TR/access-control/
+		var plainXhr = getPlainXhr();
+		if(csXhrSupport === undefined && window.XMLHttpRequest){
+			// just run this once to see if we have cross-site support
+			try{
+				var xhr = new XMLHttpRequest();
+				xhr.open("GET","http://testing-cross-domain-capability.com",true);
+				csXhrSupport = true;
+				dojo.config.noRequestedWithHeaders = true;
+			}catch(e){
+				csXhrSupport = false;
+			}
+		}
+		dojox.io.xhrPlugins.register(
+			"cs-xhr",
+			function(method,args){ 
+				return (csXhrSupport || 
+						(window.XDomainRequest && args.sync !== true && 
+							(method == "GET" || method == "POST" || httpAdapter))) &&
+					(args.url.substring(0,url.length) == url); 
+			},
+			csXhrSupport ? plainXhr : function(){
+				var normalXhrObj = dojo._xhrObj;
+				// we will just substitute this in temporarily so we can use XDomainRequest instead of XMLHttpRequest
+				dojo._xhrObj = function(){
+					
+					var xdr = new XDomainRequest();
+					xdr.readyState = 1;
+					xdr.setRequestHeader = function(){}; // just absorb them, we can't set headers :/
+					xdr.getResponseHeader = function(header){ // this is the only header we can access 
+						return header == "Content-Type" ? xdr.contentType : null;
+					}
+					// adapt the xdr handlers to xhr
+					function handler(status, readyState){
+						return function(){							
+							xdr.readyState = readyState;
+							xdr.status = status;
+						}
+					}
+					xdr.onload = handler(200, 4);
+					xdr.onprogress = handler(200, 3);
+					xdr.onerror = handler(404, 4); // an error, who knows what the real status is
+					return xdr;
+				};
+				var dfd = (httpAdapter ? httpAdapter(getPlainXhr()) : getPlainXhr()).apply(dojo,arguments);
+				dojo._xhrObj = normalXhrObj;
+				return dfd; 
+			}
+		);
+	};
+	dojox.io.xhrPlugins.fullHttpAdapter = function(plainXhr,noRawBody){
+		// summary:
+		// 		Provides a HTTP adaption.
+		// description:
+		// 		The following convention is used:
+		// 		method name -> ?http-method=PUT
+		// 		Header -> http-Header-Name=header-value
+		//		X-Header -> header_name=header-value
+		//	example:
+		//		dojox.io.xhrPlugins.addXdr("http://somesite.com", dojox.io.xhrPlugins.fullHttpAdapter);
+		return function(method,args,hasBody){
+			var content = {};
+			var parameters = {};
+			if(method != "GET"){
+				parameters["http-method"] = method;
+				if(args.putData && noRawBody){
+					content["http-content"] = args.putData;
+					delete args.putData;
+					hasBody = false;
+				}
+				if(args.postData && noRawBody){
+					content["http-content"] = args.postData;
+					delete args.postData;
+					hasBody = false;
+				}
+				method = "POST";
+			
+			}
+			for(var i in args.headers){
+				var parameterName = i.match(/^X-/) ? i.substring(2).replace(/-/g,'_').toLowerCase() : ("http-" + i);
+				parameters[parameterName] = args.headers[i];
+			}
+			args.query = dojo.objectToQuery(parameters);
+			dojo._ioAddQueryToUrl(args);
+			args.content = dojo.mixin(args.content || {},content);
+			return plainXhr.call(dojo,method,args,hasBody);
+		};
+	};
 })();
-}
+
+
+
diff --git a/dojox/io/xhrScriptPlugin.js b/dojox/io/xhrScriptPlugin.js
index 0763567..e955b26 100644
--- a/dojox/io/xhrScriptPlugin.js
+++ b/dojox/io/xhrScriptPlugin.js
@@ -1,28 +1,34 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.io.xhrScriptPlugin"]){
-dojo._hasResource["dojox.io.xhrScriptPlugin"]=true;
 dojo.provide("dojox.io.xhrScriptPlugin");
 dojo.require("dojox.io.xhrPlugins");
 dojo.require("dojo.io.script");
 dojo.require("dojox.io.scriptFrame");
-dojox.io.xhrScriptPlugin=function(_1,_2,_3){
-dojox.io.xhrPlugins.register("script",function(_4,_5){
-return _5.sync!==true&&(_4=="GET"||_3)&&(_5.url.substring(0,_1.length)==_1);
-},function(_6,_7,_8){
-var _9=function(){
-_7.callbackParamName=_2;
-if(dojo.body()){
-_7.frameDoc="frame"+Math.random();
-}
-return dojo.io.script.get(_7);
-};
-return (_3?_3(_9,true):_9)(_6,_7,_8);
-});
-};
-}
+
+dojox.io.xhrScriptPlugin = function(/*String*/url, /*String*/callbackParamName, /*Function?*/httpAdapter){
+	// summary:
+	//		Adds the script transport (JSONP) as an XHR plugin for the given site. See
+	//		dojox.io.script for more information on the transport. Note, that JSONP
+	//		is *not* a secure transport, by loading data from a third-party site using JSONP
+	//		the site has full access to your JavaScript environment.
+	//	url:
+	//		Url prefix of the site which can handle JSONP requests.
+	// 	httpAdapter: This allows for adapting HTTP requests that could not otherwise be 
+	// 		sent with JSONP, so you can use a convention for headers and PUT/DELETE methods.
+	dojox.io.xhrPlugins.register(
+		"script",
+		function(method,args){
+			 return args.sync !== true && 
+				(method == "GET" || httpAdapter) && 
+				(args.url.substring(0,url.length) == url);
+		},
+		function(method,args,hasBody){
+			var send = function(){
+				args.callbackParamName = callbackParamName;
+				if(dojo.body()){
+					args.frameDoc = "frame" + Math.random();
+				}
+				return dojo.io.script.get(args);
+			}
+			return (httpAdapter ? httpAdapter(send, true) : send)(method, args, hasBody); // use the JSONP transport
+		}
+	);
+};
\ No newline at end of file
diff --git a/dojox/io/xhrWindowNamePlugin.js b/dojox/io/xhrWindowNamePlugin.js
index 863d04f..148115f 100644
--- a/dojox/io/xhrWindowNamePlugin.js
+++ b/dojox/io/xhrWindowNamePlugin.js
@@ -1,43 +1,52 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.io.xhrWindowNamePlugin"]){
-dojo._hasResource["dojox.io.xhrWindowNamePlugin"]=true;
 dojo.provide("dojox.io.xhrWindowNamePlugin");
 dojo.require("dojox.io.xhrPlugins");
 dojo.require("dojox.io.windowName");
 dojo.require("dojox.io.httpParse");
-dojo.require("dojox.secure.capability");
-dojox.io.xhrWindowNamePlugin=function(_1,_2,_3){
-dojox.io.xhrPlugins.register("windowName",function(_4,_5){
-return _5.sync!==true&&(_4=="GET"||_4=="POST"||_2)&&(_5.url.substring(0,_1.length)==_1);
-},function(_6,_7,_8){
-var _9=dojox.io.windowName.send;
-var _a=_7.load;
-_7.load=undefined;
-var _b=(_2?_2(_9,true):_9)(_6,_7,_8);
-_b.addCallback(function(_c){
-var _d=_b.ioArgs;
-_d.xhr={getResponseHeader:function(_e){
-return dojo.queryToObject(_d.hash.match(/[^#]*$/)[0])[_e];
-}};
-if(_d.handleAs=="json"){
-if(!_3){
-dojox.secure.capability.validate(_c,["Date"],{});
-}
-return dojo.fromJson(_c);
-}
-return dojo._contentHandlers[_d.handleAs||"text"]({responseText:_c});
-});
-_7.load=_a;
-if(_a){
-_b.addCallback(_a);
-}
-return _b;
-});
-};
-}
+dojo.require("dojox.secure.capability"); // would like to have a safe JSON verifier instead (more compact)
+
+dojox.io.xhrWindowNamePlugin = function(/*String*/url, /*Function?*/httpAdapter, /*Boolean?*/trusted){
+	// summary:
+	//		Adds the windowName transport as an XHR plugin for the given site. See
+	//		dojox.io.windowName for more information on the transport.
+	//	url:
+	//		Url prefix of the site which can handle windowName requests.
+	// 	httpAdapter: This allows for adapting HTTP requests that could not otherwise be 
+	// 		sent with window.name, so you can use a convention for headers and PUT/DELETE methods.
+	dojox.io.xhrPlugins.register(
+		"windowName",
+		function(method,args){
+			 return args.sync !== true && 
+				(method == "GET" || method == "POST" || httpAdapter) && 
+				(args.url.substring(0,url.length) == url);
+		},
+		function(method,args,hasBody){
+			var send = dojox.io.windowName.send;
+			var load = args.load; 
+			args.load = undefined; //we don't want send to set this callback 
+			var dfd = (httpAdapter ? httpAdapter(send, true) : send)(method, args, hasBody); // use the windowName transport
+			dfd.addCallback(function(result){
+				var ioArgs = dfd.ioArgs;
+				ioArgs.xhr = {
+					getResponseHeader: function(name){
+						// convert the hash to an object to act like response headers
+						return dojo.queryToObject(ioArgs.hash.match(/[^#]*$/)[0])[name];
+					}
+				}
+				// use the XHR content handlers for handling
+				if(ioArgs.handleAs == 'json'){
+					// use a secure json verifier, using object capability validator for now
+					if(!trusted){
+						dojox.secure.capability.validate(result,["Date"],{});
+					}
+					return dojo.fromJson(result); 
+				}
+				return dojo._contentHandlers[ioArgs.handleAs || "text"]({responseText:result}); 
+			});
+			args.load = load; 
+			if(load){ 
+ 				dfd.addCallback(load); 
+ 			}
+			return dfd;
+		}
+	);
+};
\ No newline at end of file
diff --git a/dojox/jq.js b/dojox/jq.js
index e6e85d4..f04d303 100644
--- a/dojox/jq.js
+++ b/dojox/jq.js
@@ -1,1296 +1,1925 @@
-/*
-	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
-*/
-
+//For jQuery 1.3.2
 
-if(!dojo._hasResource["dojox.jq"]){
-dojo._hasResource["dojox.jq"]=true;
 dojo.provide("dojox.jq");
 dojo.require("dojo.NodeList-traverse");
 dojo.require("dojo.NodeList-manipulate");
 dojo.require("dojo.io.script");
+
+/*
+To get jquery tests to pass: 
+- add spaces between span>form selectors, other ones like one,two
+- .last() instead of :last
+- $("<div>").find("#foo") does not work unless the div is attached to the body.
+
+- trigger .test not work
+- No jquery.Event thing.
+
+- jQuery.ajax() modifies incoming arguments?
+- test framework not good for our io methods, async, poll.
+- Dojo ajax is async: we fire ajaxStop more than jquery.
+
+- jquery makes assumptions of a value to set for an element
+by inserting an element and checking display. Does not seem to
+account for nested styles, only captures generic tag name style off
+of body. Why can't we just set display to empty?
+
+
+
+
+
+OK for failures:
+- test("jQuery.ajax - beforeSend, cancel request (#2688)"
+  We cancel the deferred which triggers error and complete callbacks.
+
+
+Looked at jquery code for:
+- how it handled text(): did not use textContent/innerText, but use recursive look over childNodes and nodeValue,
+so it may have impact on how <br> is serialized, but it has uniform behavior across browsers.
+- Looked at trigger: how it triggered actions on dom nodes. This seemed unsafe.
+*/
+
+/*
+dojo.query differences that cause some tests to fail:
+- does not support XML queries
+- $("#sap>form") does not find a match but $("#sap > form") does. Similar issue with comma instead of > (see is() tests)
+- "$("form:last") should return the last form object, not if that particular form is that last related
+  to its siblings? Same issue with :first?
+- $("p").filter("#ap, #sndp"): filter does not work.
+- dojo.NodeList uses d.NodeList a few places in the code. Would be nice to use a ctor that can be configured.
+  That would make the filter function operate better.
+- filterQueryResult, cannot handle queries like "p, div"? See andSelf test with parents().
+- adjacent "p + p" not supported?
+= a:only-child not supported?
+- nth(1)
+- even/odd
+- eq/gt/lt
+- #form :radio:checked does not run the first :radio psuedo selector? Seems to be a general issue where only the last pseud
+  is run. For example, "#form :checked:radio" does only the radio pseudo.
+*/
+
 (function(){
-dojo.config.ioPublish=true;
-var _1="|img|meta|hr|br|input|";
-function _2(_3,_4){
-_3+="";
-_3=_3.replace(/<\s*(\w+)([^\/\>]*)\/\s*>/g,function(_5,_6,_7){
-if(_1.indexOf("|"+_6+"|")==-1){
-return "<"+_6+_7+"></"+_6+">";
-}else{
-return _5;
-}
-});
-return dojo._toDom(_3,_4);
-};
-function _8(_9){
-var _a=_9.indexOf("-");
-if(_a!=-1){
-if(_a==0){
-_9=_9.substring(1);
-}
-_9=_9.replace(/-(\w)/g,function(_b,_c){
-return _c.toUpperCase();
-});
-}
-return _9;
-};
-var _d=dojo.global.$;
-var _e=dojo.global.jQuery;
-var $=dojo.global.$=dojo.global.jQuery=function(){
-var _f=arguments[0];
-if(!_f){
-return $._wrap([],null,$);
-}else{
-if(dojo.isString(_f)){
-if(_f.charAt(0)=="<"){
-_f=_2(_f);
-if(_f.nodeType==11){
-_f=_f.childNodes;
-}else{
-return $._wrap([_f],null,$);
-}
-}else{
-var _10=dojo._NodeListCtor;
-dojo._NodeListCtor=$;
-var _11=arguments[1];
-if(_11&&_11._is$){
-_11=_11[0];
-}else{
-if(dojo.isString(_11)){
-_11=dojo.query(_11)[0];
-}
-}
-var nl=dojo.query.call(this,_f,_11);
-dojo._NodeListCtor=_10;
-return nl;
-}
-}else{
-if(dojo.isFunction(_f)){
-$.ready(_f);
-return $;
-}else{
-if(_f==document||_f==window){
-return $._wrap([_f],null,$);
-}else{
-if(dojo.isArray(_f)){
-var ary=[];
-for(var i=0;i<_f.length;i++){
-if(dojo.indexOf(ary,_f[i])==-1){
-ary.push(_f[i]);
-}
-}
-return $._wrap(_f,null,$);
-}else{
-if("nodeType" in _f){
-return $._wrap([_f],null,$);
-}
-}
-}
-}
-}
-}
-return $._wrap(dojo._toArray(_f),null,$);
-};
-var _12=dojo.NodeList.prototype;
-var f=$.fn=$.prototype=dojo.delegate(_12);
-$._wrap=dojo.NodeList._wrap;
-var _13=/^H\d/i;
-var _14=dojo.query.pseudos;
-dojo.mixin(_14,{has:function(_15,_16){
-return function(_17){
-return $(_16,_17).length;
-};
-},visible:function(_18,_19){
-return function(_1a){
-return dojo.style(_1a,"visible")!="hidden"&&dojo.style(_1a,"display")!="none";
-};
-},hidden:function(_1b,_1c){
-return function(_1d){
-return _1d.type=="hidden"||dojo.style(_1d,"visible")=="hidden"||dojo.style(_1d,"display")=="none";
-};
-},selected:function(_1e,_1f){
-return function(_20){
-return _20.selected;
-};
-},checked:function(_21,_22){
-return function(_23){
-return _23.nodeName.toUpperCase()=="INPUT"&&_23.checked;
-};
-},disabled:function(_24,_25){
-return function(_26){
-return _26.getAttribute("disabled");
-};
-},enabled:function(_27,_28){
-return function(_29){
-return !_29.getAttribute("disabled");
-};
-},input:function(_2a,_2b){
-return function(_2c){
-var n=_2c.nodeName.toUpperCase();
-return n=="INPUT"||n=="SELECT"||n=="TEXTAREA"||n=="BUTTON";
-};
-},button:function(_2d,_2e){
-return function(_2f){
-return (_2f.nodeName.toUpperCase()=="INPUT"&&_2f.type=="button")||_2f.nodeName.toUpperCase()=="BUTTON";
-};
-},header:function(_30,_31){
-return function(_32){
-return _32.nodeName.match(_13);
-};
-}});
-var _33={};
-dojo.forEach(["text","password","radio","checkbox","submit","image","reset","file"],function(_34){
-_33[_34]=function(_35,_36){
-return function(_37){
-return _37.nodeName.toUpperCase()=="INPUT"&&_37.type==_34;
-};
-};
-});
-dojo.mixin(_14,_33);
-$.browser={mozilla:dojo.isMoz,msie:dojo.isIE,opera:dojo.isOpera,safari:dojo.isSafari};
-$.browser.version=dojo.isIE||dojo.isMoz||dojo.isOpera||dojo.isSafari||dojo.isWebKit;
-$.ready=$.fn.ready=function(_38){
-dojo.addOnLoad(dojo.hitch(null,_38,$));
-return this;
-};
-f._is$=true;
-f.size=function(){
-return this.length;
-};
-$.prop=function(_39,_3a){
-if(dojo.isFunction(_3a)){
-return _3a.call(_39);
-}else{
-return _3a;
-}
-};
-$.className={add:dojo.addClass,remove:dojo.removeClass,has:dojo.hasClass};
-$.makeArray=function(_3b){
-if(typeof _3b=="undefined"){
-return [];
-}else{
-if(_3b.length&&!dojo.isString(_3b)&&!("location" in _3b)){
-return dojo._toArray(_3b);
-}else{
-return [_3b];
-}
-}
-};
-$.merge=function(_3c,_3d){
-var _3e=[_3c.length,0];
-_3e=_3e.concat(_3d);
-_3c.splice.apply(_3c,_3e);
-return _3c;
-};
-$.each=function(_3f,cb){
-if(dojo.isArrayLike(_3f)){
-for(var i=0;i<_3f.length;i++){
-if(cb.call(_3f[i],i,_3f[i])===false){
-break;
-}
-}
-}else{
-if(dojo.isObject(_3f)){
-for(var _40 in _3f){
-if(cb.call(_3f[_40],_40,_3f[_40])===false){
-break;
-}
-}
-}
-}
-return this;
-};
-f.each=function(cb){
-return $.each.call(this,this,cb);
-};
-f.eq=function(){
-var nl=$();
-dojo.forEach(arguments,function(i){
-if(this[i]){
-nl.push(this[i]);
-}
-},this);
-return nl;
-};
-f.get=function(_41){
-if(_41||_41==0){
-return this[_41];
-}
-return this;
-};
-f.index=function(arg){
-if(arg._is$){
-arg=arg[0];
-}
-return this.indexOf(arg);
-};
-var _42=[];
-var _43=0;
-var _44=dojo._scopeName+"DataId";
-var _45=function(_46){
-var id=_46.getAttribute(_44);
-if(!id){
-id=_43++;
-_46.setAttribute(_44,id);
-}
-};
-var _47=function(_48){
-var _49={};
-if(_48.nodeType==1){
-var id=_45(_48);
-_49=_42[id];
-if(!_49){
-_49=_42[id]={};
-}
-}
-return _49;
-};
-$.data=function(_4a,_4b,_4c){
-var _4d=null;
-if(_4b=="events"){
-_4d=_4e[_4a.getAttribute(_4f)];
-var _50=true;
-if(_4d){
-for(var _51 in _4d){
-_50=false;
-break;
-}
-}
-return _50?null:_4d;
-}
-var _52=_47(_4a);
-if(typeof _4c!="undefined"){
-_52[_4b]=_4c;
-}else{
-_4d=_52[_4b];
-}
-return _4c?this:_4d;
-};
-$.removeData=function(_53,_54){
-var _55=_47(_53);
-delete _55[_54];
-if(_53.nodeType==1){
-var _56=true;
-for(var _57 in _55){
-_56=false;
-break;
-}
-if(_56){
-_53.removeAttribute(_44);
-}
-}
-return this;
-};
-f.data=function(_58,_59){
-var _5a=null;
-this.forEach(function(_5b){
-_5a=$.data(_5b,_58,_59);
-});
-return _59?this:_5a;
-};
-f.removeData=function(_5c){
-this.forEach(function(_5d){
-$.removeData(_5d,_5c);
-});
-return this;
-};
-function _5e(obj,_5f){
-if(obj==_5f){
-return obj;
-}
-var _60={};
-for(var x in _5f){
-if((_60[x]===undefined||_60[x]!=_5f[x])&&_5f[x]!==undefined&&obj!=_5f[x]){
-if(dojo.isObject(obj[x])&&dojo.isObject(_5f[x])){
-if(dojo.isArray(_5f[x])){
-obj[x]=_5f[x];
-}else{
-obj[x]=_5e(obj[x],_5f[x]);
-}
-}else{
-obj[x]=_5f[x];
-}
-}
-}
-if(dojo.isIE&&_5f){
-var p=_5f.toString;
-if(typeof p=="function"&&p!=obj.toString&&p!=_60.toString&&p!="\nfunction toString() {\n    [native code]\n}\n"){
-obj.toString=_5f.toString;
-}
-}
-return obj;
-};
-f.extend=function(){
-var _61=[this];
-_61=_61.concat(arguments);
-return $.extend.apply($,_61);
-};
-$.extend=function(){
-var _62=arguments,_63;
-for(var i=0;i<_62.length;i++){
-var obj=_62[i];
-if(obj&&dojo.isObject(obj)){
-if(!_63){
-_63=obj;
-}else{
-_5e(_63,obj);
-}
-}
-}
-return _63;
-};
-$.noConflict=function(_64){
-var me=$;
-dojo.global.$=_d;
-if(_64){
-dojo.global.jQuery=_e;
-}
-return me;
-};
-f.attr=function(_65,_66){
-if(arguments.length==1&&dojo.isString(arguments[0])){
-var _67=this[0];
-if(!_67){
-return null;
-}
-var arg=arguments[0];
-var _68=dojo.attr(_67,arg);
-var _69=_67[arg];
-if((arg in _67)&&!dojo.isObject(_69)&&_65!="href"){
-return _69;
-}else{
-return _68||_69;
-}
-}else{
-if(dojo.isObject(_65)){
-for(var _6a in _65){
-this.attr(_6a,_65[_6a]);
-}
-return this;
-}else{
-var _6b=dojo.isFunction(_66);
-this.forEach(function(_6c,_6d){
-var _6e=_6c[_65];
-if((_65 in _6c)&&!dojo.isObject(_6e)&&_65!="href"){
-_6c[_65]=(_6b?_66.call(_6c,_6d):_66);
-}else{
-if(_6c.nodeType==1){
-dojo.attr(_6c,_65,(_6b?_66.call(_6c,_6d):_66));
-}
-}
-});
-return this;
-}
-}
-};
-f.removeAttr=function(_6f){
-this.forEach(function(_70,_71){
-var _72=_70[_6f];
-if((_6f in _70)&&!dojo.isObject(_72)&&_6f!="href"){
-delete _70[_6f];
-}else{
-if(_70.nodeType==1){
-if(_6f=="class"){
-_70.removeAttribute(_6f);
-}else{
-dojo.removeAttr(_70,_6f);
-}
-}
-}
-});
-return this;
-};
-f.toggleClass=function(_73,_74){
-var _75=arguments.length>1;
-this.forEach(function(_76){
-dojo.toggleClass(_76,_73,_75?_74:!dojo.hasClass(_76,_73));
-});
-return this;
-};
-f.toggle=function(){
-var _77=arguments;
-if(arguments.length>1&&dojo.isFunction(arguments[0])){
-var _78=0;
-var _79=function(){
-var _7a=_77[_78].apply(this,arguments);
-_78+=1;
-if(_78>_77.length-1){
-_78=0;
-}
-};
-return this.bind("click",_79);
-}else{
-var _7b=arguments.length==1?arguments[0]:undefined;
-this.forEach(function(_7c){
-var _7d=typeof _7b=="undefined"?dojo.style(_7c,"display")=="none":_7b;
-var _7e=(_7d?"show":"hide");
-var nl=$(_7c);
-nl[_7e].apply(nl,_77);
-});
-return this;
-}
-};
-f.hasClass=function(_7f){
-return this.some(function(_80){
-return dojo.hasClass(_80,_7f);
-});
-};
-f.html=f.innerHTML;
-dojo.forEach(["filter","slice"],function(_81){
-f[_81]=function(){
-var nl;
-if(dojo.isFunction(arguments[0])){
-var _82=arguments[0];
-arguments[0]=function(_83,_84){
-return _82.call(_83,_83,_84);
-};
-}
-if(_81=="filter"&&dojo.isString(arguments[0])){
-var nl=this._filterQueryResult(this,arguments[0]);
-}else{
-var _85=dojo._NodeListCtor;
-dojo._NodeListCtor=f;
-nl=$(_12[_81].apply(this,arguments));
-dojo._NodeListCtor=_85;
-}
-return nl._stash(this);
-};
-});
-f.map=function(_86){
-return this._buildArrayFromCallback(_86);
-};
-$.map=function(ary,_87){
-return f._buildArrayFromCallback.call(ary,_87);
-};
-$.inArray=function(_88,ary){
-return dojo.indexOf(ary,_88);
-};
-f.is=function(_89){
-return (_89?!!this.filter(_89).length:false);
-};
-f.not=function(){
-var _8a=$.apply($,arguments);
-var nl=$(_12.filter.call(this,function(_8b){
-return _8a.indexOf(_8b)==-1;
-}));
-return nl._stash(this);
-};
-f.add=function(){
-return this.concat.apply(this,arguments);
-};
-function _8c(_8d){
-var doc=_8d.contentDocument||(((_8d.name)&&(_8d.document)&&(document.getElementsByTagName("iframe")[_8d.name].contentWindow)&&(document.getElementsByTagName("iframe")[_8d.name].contentWindow.document)))||((_8d.name)&&(document.frames[_8d.name])&&(document.frames[_8d.name].document))||null;
-return doc;
-};
-f.contents=function(){
-var ary=[];
-this.forEach(function(_8e){
-if(_8e.nodeName.toUpperCase()=="IFRAME"){
-var doc=_8c(_8e);
-if(doc){
-ary.push(doc);
-}
-}else{
-var _8f=_8e.childNodes;
-for(var i=0;i<_8f.length;i++){
-ary.push(_8f[i]);
-}
-}
-});
-return this._wrap(ary)._stash(this);
-};
-f.find=function(_90){
-var ary=[];
-this.forEach(function(_91){
-if(_91.nodeType==1){
-ary=ary.concat(dojo._toArray($(_90,_91)));
-}
-});
-return this._getUniqueAsNodeList(ary)._stash(this);
-};
-f.andSelf=function(){
-return this.add(this._parent);
-};
-f.remove=function(_92){
-var nl=(_92?this._filterQueryResult(this,_92):this);
-nl.removeData();
-nl.forEach(function(_93){
-_93.parentNode.removeChild(_93);
-});
-return this;
-};
-$.css=function(_94,_95,_96){
-_95=_8(_95);
-var _97=(_96?dojo.style(_94,_95,_96):dojo.style(_94,_95));
-return _97;
-};
-f.css=function(_98,_99){
-if(dojo.isString(_98)){
-_98=_8(_98);
-if(arguments.length==2){
-if(!dojo.isString(_99)&&_98!="zIndex"){
-_99=_99+"px";
-}
-this.forEach(function(_9a){
-if(_9a.nodeType==1){
-dojo.style(_9a,_98,_99);
-}
-});
-return this;
-}else{
-_99=dojo.style(this[0],_98);
-if(!dojo.isString(_99)&&_98!="zIndex"){
-_99=_99+"px";
-}
-return _99;
-}
-}else{
-for(var _9b in _98){
-this.css(_9b,_98[_9b]);
-}
-return this;
-}
-};
-function _9c(nl,_9d,_9e,_9f){
-if(_9f){
-var mod={};
-mod[_9e]=_9f;
-nl.forEach(function(_a0){
-dojo[_9d](_a0,mod);
-});
-return nl;
-}else{
-return Math.abs(Math.round(dojo[_9d](nl[0])[_9e]));
-}
-};
-f.height=function(_a1){
-return _9c(this,"contentBox","h",_a1);
-};
-f.width=function(_a2){
-return _9c(this,"contentBox","w",_a2);
-};
-function _a3(_a4,_a5,_a6,_a7,_a8){
-var _a9=false;
-if((_a9=_a4.style.display=="none")){
-_a4.style.display="block";
-}
-var cs=dojo.getComputedStyle(_a4);
-var _aa=Math.abs(Math.round(dojo._getContentBox(_a4,cs)[_a5]));
-var pad=_a6?Math.abs(Math.round(dojo._getPadExtents(_a4,cs)[_a5])):0;
-var _ab=_a7?Math.abs(Math.round(dojo._getBorderExtents(_a4,cs)[_a5])):0;
-var _ac=_a8?Math.abs(Math.round(dojo._getMarginExtents(_a4,cs)[_a5])):0;
-if(_a9){
-_a4.style.display="none";
-}
-return pad+_aa+_ab+_ac;
-};
-f.innerHeight=function(){
-return _a3(this[0],"h",true);
-};
-f.innerWidth=function(){
-return _a3(this[0],"w",true);
-};
-f.outerHeight=function(_ad){
-return _a3(this[0],"h",true,true,_ad);
-};
-f.outerWidth=function(_ae){
-return _a3(this[0],"w",true,true,_ae);
-};
-var _4e=[];
-var _af=1;
-var _4f=dojo._scopeName+"eventid";
-var _b0;
-function _b1(_b2){
-_b2=_b2.split("$$")[0];
-var _b3=_b2.indexOf(".");
-if(_b3!=-1){
-_b2=_b2.substring(0,_b3);
-}
-return _b2;
-};
-function _b4(_b5,_b6){
-if(_b6.indexOf("ajax")==0){
-return dojo.subscribe(_b7[_b6],function(dfd,res){
-var _b8=new $.Event(_b6);
-if("ajaxComplete|ajaxSend|ajaxSuccess".indexOf(_b6)!=-1){
-_b9(_b5,[_b8,dfd.ioArgs.xhr,dfd.ioArgs.args]);
-}else{
-if(_b6=="ajaxError"){
-_b9(_b5,[_b8,dfd.ioArgs.xhr,dfd.ioArgs.args,res]);
-}else{
-_b9(_b5,[_b8]);
-}
-}
-});
-}else{
-return dojo.connect(_b5,"on"+_b6,function(e){
-_b9(_b5,arguments);
-});
-}
-};
-$.Event=function(_ba){
-if(this==$){
-return new $.Event(_ba);
-}
-if(typeof _ba=="string"){
-this.type=_ba.replace(/!/,"");
-}else{
-dojo.mixin(this,_ba);
-}
-this.timeStamp=(new Date()).getTime();
-this._isFake=true;
-this._isStrict=(this.type.indexOf("!")!=-1);
-};
-var ep=$.Event.prototype={preventDefault:function(){
-this.isDefaultPrevented=this._true;
-},stopPropagation:function(){
-this.isPropagationStopped=this._true;
-},stopImmediatePropagation:function(){
-this.isPropagationStopped=this._true;
-this.isImmediatePropagationStopped=this._true;
-},_true:function(){
-return true;
-},_false:function(){
-return false;
-}};
-dojo.mixin(ep,{isPropagationStopped:ep._false,isImmediatePropagationStopped:ep._false,isDefaultPrevented:ep._false});
-function _bb(_bc,_bd){
-_bc=_bc||[];
-_bc=[].concat(_bc);
-var evt=_bc[0];
-if(!evt||!evt.preventDefault){
-evt=_bd&&_bd.preventDefault?_bd:new $.Event(_bd);
-_bc.unshift(evt);
-}
-return _bc;
-};
-var _be=false;
-function _b9(_bf,_c0,_c1){
-_be=true;
-_c0=_c0||_b0;
-_c1=_c1;
-if(_bf.nodeType==9){
-_bf=_bf.documentElement;
-}
-var _c2=_bf.getAttribute(_4f);
-if(!_c2){
-return;
-}
-var evt=_c0[0];
-var _c3=evt.type;
-var _c4=_b1(_c3);
-var cbs=_4e[_c2][_c4];
-var _c5;
-if(_c1){
-_c5=_c1.apply(_bf,_c0);
-}
-if(_c5!==false){
-for(var _c6 in cbs){
-if(_c6!="_connectId"&&(!evt._isStrict&&(_c6.indexOf(_c3)==0)||(evt._isStrict&&_c6==_c3))){
-evt[dojo._scopeName+"callbackId"]=_c6;
-var cb=cbs[_c6];
-if(typeof cb.data!="undefined"){
-evt.data=cb.data;
-}else{
-evt.data=null;
-}
-if((_c5=cb.fn.apply(evt.target,_c0))===false&&!evt._isFake){
-dojo.stopEvent(evt);
-}
-evt.result=_c5;
-}
-}
-}
-return _c5;
-};
-f.triggerHandler=function(_c7,_c8,_c9){
-var _ca=this[0];
-if(_ca&&_ca.nodeType!=3&&_ca.nodeType!=8){
-_c8=_bb(_c8,_c7);
-return _b9(_ca,_c8,_c9);
-}else{
-return undefined;
-}
-};
-f.trigger=function(_cb,_cc,_cd){
-_cc=_bb(_cc,_cb);
-var evt=_cc[0];
-var _cb=_b1(evt.type);
-_b0=_cc;
-currentExtraFunc=_cd;
-var _ce=null;
-var _cf=!evt.target;
-this.forEach(function(_d0){
-if(_d0.nodeType!=3&&_d0.nodeType!=8){
-if(_d0.nodeType==9){
-_d0=_d0.documentElement;
-}
-if(evt._isFake){
-evt.currentTarget=_d0;
-if(_cf){
-evt.target=_d0;
-}
-}
-if(_cd){
-var _d1=_cc.slice(1);
-_ce=_cd.apply(_d0,(_ce=null?_d1:_d1.concat(_ce)));
-}
-if(_ce!==false){
-_be=false;
-if(_d0[_cb]){
-try{
-_ce=_d0[_cb]();
-}
-catch(e){
-}
-}else{
-if(_d0["on"+_cb]){
-try{
-_ce=_d0["on"+_cb]();
-}
-catch(e){
-}
-}
-}
-if(!_be){
-_ce=_b9(_d0,_cc);
-}
-var _d2=_d0.parentNode;
-if(_ce!==false&&!evt.isImmediatePropagationStopped()&&!evt.isPropagationStopped()&&_d2&&_d2.nodeType==1){
-$(_d2).trigger(_cb,_cc,_cd);
-}
-}
-}
-});
-_b0=null;
-currentExtraFunc=null;
-return this;
-};
-var _d3=0;
-f.bind=function(_d4,_d5,fn){
-_d4=_d4.split(" ");
-if(!fn){
-fn=_d5;
-_d5=null;
-}
-this.forEach(function(_d6){
-if(_d6.nodeType!=3&&_d6.nodeType!=8){
-if(_d6.nodeType==9){
-_d6=_d6.documentElement;
-}
-var _d7=_d6.getAttribute(_4f);
-if(!_d7){
-_d7=_af++;
-_d6.setAttribute(_4f,_d7);
-_4e[_d7]={};
-}
-for(var i=0;i<_d4.length;i++){
-var _d8=_d4[i];
-var _d9=_b1(_d8);
-if(_d9==_d8){
-_d8=_d9+"$$"+(_d3++);
-}
-var lls=_4e[_d7];
-if(!lls[_d9]){
-lls[_d9]={_connectId:_b4(_d6,_d9)};
-}
-lls[_d9][_d8]={fn:fn,data:_d5};
-}
-}
-});
-return this;
-};
-function _da(src,_db){
-var _dc=_db.getAttribute(_4f);
-var sls=_4e[_dc];
-if(!sls){
-return;
-}
-var _dd=_dd=_af++;
-_db.setAttribute(_4f,_dd);
-var tls=_4e[_dd]={};
-var _de={};
-for(var _df in sls){
-var _e0=tls[_df]={_connectId:_b4(_db,_df)};
-var _e1=sls[_df];
-for(var _e2 in _e1){
-_e0[_e2]={fn:_e1[_e2].fn,data:_e1[_e2].data,};
-}
-}
-};
-function _e3(lls,_e4,_e5,_e6,fn){
-var _e7=lls[_e4];
-if(_e7){
-var _e8=_e5.indexOf(".")!=-1;
-var _e9=false;
-if(_e6){
-delete _e7[_e6];
-}else{
-if(!_e8&&!fn){
-_e9=true;
-}else{
-if(_e8){
-if(_e5.charAt(0)=="."){
-for(var _ea in _e7){
-if(_ea.indexOf(_e5)==_ea.length-_e5.length){
-delete _e7[_ea];
-}
-}
-}else{
-delete _e7[_e5];
-}
-}else{
-for(var _ea in _e7){
-if(_ea.indexOf("$$")!=-1&&_e7[_ea].fn==fn){
-delete _e7[_ea];
-break;
-}
-}
-}
-}
-}
-var _eb=true;
-for(var _ea in _e7){
-if(_ea!="_connectId"){
-_eb=false;
-break;
-}
-}
-if(_e9||_eb){
-if(_e4.indexOf("ajax")!=-1){
-dojo.unsubscribe(_e7._connectId);
-}else{
-dojo.disconnect(_e7._connectId);
-}
-delete lls[_e4];
-}
-}
-};
-f.unbind=function(_ec,fn){
-var _ed=_ec?_ec[dojo._scopeName+"callbackId"]:null;
-_ec=_ec&&_ec.type?_ec.type:_ec;
-_ec=_ec?_ec.split(" "):_ec;
-this.forEach(function(_ee){
-if(_ee.nodeType!=3&&_ee.nodeType!=8){
-if(_ee.nodeType==9){
-_ee=_ee.documentElement;
-}
-var _ef=_ee.getAttribute(_4f);
-if(_ef){
-var lls=_4e[_ef];
-if(lls){
-var _f0=_ec;
-if(!_f0){
-_f0=[];
-for(var _f1 in lls){
-_f0.push(_f1);
-}
-}
-for(var i=0;i<_f0.length;i++){
-var _f2=_f0[i];
-var _f3=_b1(_f2);
-if(_f2.charAt(0)=="."){
-for(var _f1 in lls){
-_e3(lls,_f1,_f2,_ed,fn);
-}
-}else{
-_e3(lls,_f3,_f2,_ed,fn);
-}
-}
-}
-}
-}
-});
-return this;
-};
-f.one=function(_f4,_f5){
-var _f6=function(){
-$(this).unbind(_f4,arguments.callee);
-return _f5.apply(this,arguments);
-};
-return this.bind(_f4,_f6);
-};
-f._cloneNode=function(src){
-var _f7=src.cloneNode(true);
-if(src.nodeType==1){
-var _f8=dojo.query("["+_4f+"]",_f7);
-for(var i=0,_f9;_f9=_f8[i];i++){
-var _fa=dojo.query("["+_4f+"=\""+_f9.getAttribute(_4f)+"\"]",src)[0];
-if(_fa){
-_da(_fa,_f9);
-}
-}
-}
-return _f7;
-};
-dojo.getObject("$.event.global",true);
-dojo.forEach(["blur","focus","dblclick","click","error","keydown","keypress","keyup","load","mousedown","mouseenter","mouseleave","mousemove","mouseout","mouseover","mouseup","submit","ajaxStart","ajaxSend","ajaxSuccess","ajaxError","ajaxComplete","ajaxStop"],function(evt){
-f[evt]=function(_fb){
-if(_fb){
-this.bind(evt,_fb);
-}else{
-this.trigger(evt);
-}
-return this;
-};
-});
-function _fc(_fd){
-if(dojo.isString(_fd)){
-if(_fd=="slow"){
-_fd=700;
-}else{
-if(_fd="fast"){
-_fd=300;
-}else{
-_fd=500;
-}
-}
-}
-return _fd;
-};
-f.hide=function(_fe,_ff){
-_fe=_fc(_fe);
-this.forEach(function(node){
-var _100=node.style;
-var cs=dojo.getComputedStyle(node);
-if(cs.display=="none"){
-return;
-}
-_100.overflow="hidden";
-_100.display="block";
-if(_fe){
-dojo.anim(node,{width:0,height:0,opacity:0},_fe,null,function(){
-_100.width="";
-_100.height="";
-_100.display="none";
-return _ff&&_ff.call(node);
-});
-}else{
-dojo.style(node,"display","none");
-if(_ff){
-_ff.call(node);
-}
-}
-});
-return this;
-};
-f.show=function(_101,_102){
-_101=_fc(_101);
-this.forEach(function(node){
-var _103=node.style;
-var cs=dojo.getComputedStyle(node);
-if(cs.display!="none"){
-return;
-}
-if(_101){
-var _104=parseFloat(_103.width);
-var _105=parseFloat(_103.height);
-if(!_104||!_105){
-_103.display="block";
-var box=dojo.marginBox(node);
-_104=box.w;
-_105=box.h;
-}
-_103.width=0;
-_103.height=0;
-_103.overflow="hidden";
-dojo.attr(node,"opacity",0);
-_103.display="block";
-dojo.anim(node,{width:_104,height:_105,opacity:1},_101,null,_102?dojo.hitch(node,_102):undefined);
-}else{
-dojo.style(node,"display","block");
-if(_102){
-_102.call(node);
-}
-}
-});
-return this;
-};
-$.ajaxSettings={};
-$.ajaxSetup=function(args){
-dojo.mixin($.ajaxSettings,args);
-};
-var _b7={"ajaxStart":"/dojo/io/start","ajaxSend":"/dojo/io/send","ajaxSuccess":"/dojo/io/load","ajaxError":"/dojo/io/error","ajaxComplete":"/dojo/io/done","ajaxStop":"/dojo/io/stop"};
-for(var _106 in _b7){
-if(_106.indexOf("ajax")==0){
-(function(_107){
-f[_107]=function(_108){
-this.forEach(function(node){
-dojo.subscribe(_b7[_107],function(){
-var _109=new $.Event(_107);
-var _10a=arguments[0]&&arguments[0].ioArgs;
-var xhr=_10a&&_10a.xhr;
-var args=_10a&&_10a.args;
-var res=arguments[1];
-if("ajaxComplete|ajaxSend|ajaxSuccess".indexOf(_107)!=-1){
-return _108.call(node,_109,xhr,args);
-}else{
-if(_107=="ajaxError"){
-return _108.call(node,_109,xhr,args,res);
-}else{
-return _108.call(node,_109);
-}
-}
-});
-});
-return this;
-};
-})(_106);
-}
-}
-var _10b=dojo._xhrObj;
-dojo._xhrObj=function(args){
-var xhr=_10b.apply(dojo,arguments);
-if(args&&args.beforeSend){
-if(args.beforeSend(xhr)===false){
-return false;
-}
-}
-return xhr;
-};
-$.ajax=function(args){
-var temp=dojo.delegate($.ajaxSettings);
-for(var _10c in args){
-if(_10c=="data"&&dojo.isObject(args[_10c])&&dojo.isObject(temp.data)){
-for(var prop in args[_10c]){
-temp.data[prop]=args[_10c][prop];
-}
-}else{
-temp[_10c]=args[_10c];
-}
-}
-args=temp;
-var url=args.url;
-if("async" in args){
-args.sync=!args.async;
-}
-if(args.global===false){
-args.ioPublish=false;
-}
-if(args.data){
-var data=args.data;
-if(dojo.isString(data)){
-args.content=dojo.queryToObject(data);
-}else{
-for(var _10c in data){
-if(dojo.isFunction(data[_10c])){
-data[_10c]=data[_10c]();
-}
-}
-args.content=data;
-}
-}
-var _10d=args.dataType;
-if("dataType" in args){
-if(_10d=="script"){
-_10d="javascript";
-}else{
-if(_10d=="html"){
-_10d="text";
-}
-}
-args.handleAs=_10d;
-}else{
-_10d=args.handleAs="text";
-args.guessedType=true;
-}
-if("cache" in args){
-args.preventCache=!args.cache;
-}else{
-if(args.dataType=="script"||args.dataType=="jsonp"){
-args.preventCache=true;
-}
-}
-if(args.error){
-args._jqueryError=args.error;
-delete args.error;
-}
-args.handle=function(_10e,_10f){
-var _110="success";
-if(_10e instanceof Error){
-_110=(_10e.dojoType=="timeout"?"timeout":"error");
-if(args._jqueryError){
-args._jqueryError(_10f.xhr,_110,_10e);
-}
-}else{
-var xml=(_10f.args.guessedType&&_10f.xhr&&_10f.xhr.responseXML);
-if(xml){
-_10e=xml;
-}
-if(args.success){
-args.success(_10e,_110,_10f.xhr);
-}
-}
-if(args.complete){
-args.complete(_10e,_110,_10f.xhr);
-}
-return _10e;
-};
-var _111=(_10d=="jsonp");
-if(_10d=="javascript"){
-var _112=url.indexOf(":");
-var _113=url.indexOf("/");
-if(_112>0&&_112<_113){
-var _114=url.indexOf("/",_113+2);
-if(_114==-1){
-_114=url.length;
-}
-if(location.protocol!=url.substring(0,_112+1)||location.hostname!=url.substring(_113+2,_114)){
-_111=true;
-}
-}
-}
-if(_111){
-if(_10d=="jsonp"){
-var cb=args.jsonp;
-if(!cb){
-var _115=args.url.split("?")[1];
-if(_115&&(_115=dojo.queryToObject(_115))){
-cb=_116(_115);
-if(cb){
-var _117=new RegExp("([&\\?])?"+cb+"=?");
-args.url=args.url.replace(_117+"=?");
-}
-}
-if(!cb){
-cb=_116(args.content);
-if(cb){
-delete args.content[cb];
-}
-}
-}
-args.jsonp=cb||"callback";
-}
-var dfd=dojo.io.script.get(args);
-return dfd;
-}else{
-var dfd=dojo.xhr(args.type||"GET",args);
-return dfd.ioArgs.xhr===false?false:dfd.ioArgs.xhr;
-}
-};
-function _116(obj){
-for(var prop in obj){
-if(prop.indexOf("callback")==prop.length-8){
-return prop;
-}
-}
-return null;
-};
-$.getpost=function(_118,url,data,_119,_11a){
-var args={url:url,type:_118};
-if(data){
-if(dojo.isFunction(data)&&!_119){
-args.complete=data;
-}else{
-args.data=data;
-}
-}
-if(_119){
-if(dojo.isString(_119)&&!_11a){
-_11a=_119;
-}else{
-args.complete=_119;
-}
-}
-if(_11a){
-args.dataType=_11a;
-}
-return $.ajax(args);
-};
-$.get=dojo.hitch($,"getpost","GET");
-$.post=dojo.hitch($,"getpost","POST");
-$.getJSON=function(url,data,_11b){
-return $.getpost("GET",url,data,_11b,"json");
-};
-$.getScript=function(url,_11c){
-return $.ajax({url:url,success:_11c,dataType:"script"});
-};
-f.load=function(url,data,_11d){
-var node=this[0];
-if(!node||!node.nodeType||node.nodeType==9){
-dojo.addOnLoad(url);
-return this;
-}
-var _11e=url.split(/\s+/);
-url=_11e[0];
-var _11f=_11e[1];
-var _120=_11d||data;
-var cb=dojo.hitch(this,function(_121,_122,xhr){
-var _123=_121.match(/\<\s*body[^>]+>.*<\/body\s*>/i);
-if(_123){
-_121=_123;
-}
-var _124=dojo._toDom(_121);
-if(_11f){
-var temp=$(dojo.create("div"));
-temp.append(_124);
-_124=temp.find(_11f);
-}else{
-_124=$(_124.nodeType==11?_124.childNodes:_124);
-}
-this.html(_124);
-if(_120){
-setTimeout(dojo.hitch(this,function(){
-this.forEach(function(node){
-_120.call(node,_121,_122,xhr);
-});
-}),10);
-}
-});
-if(!_11d){
-data=cb;
-}else{
-_11d=cb;
-}
-var _125="GET";
-if(data&&dojo.isObject(data)){
-_125="POST";
-}
-$.getpost(_125,url,data,_11d,"html");
-return this;
-};
-var _126="file|submit|image|reset|button|";
-f.serialize=function(){
-var ret="";
-var strs=this.map(function(node){
-if(node.nodeName.toUpperCase()=="FORM"){
-return dojo.formToQuery(node);
-}else{
-var type=(node.type||"").toLowerCase();
-if(_126.indexOf(type)==-1){
-var val=dojo.fieldToObject(node);
-if(node.name&&val!=null){
-var q={};
-q[node.name]=val;
-return dojo.objectToQuery(q);
-}
-}
-}
-});
-return ret+strs.join("&");
-};
-$.param=function(obj){
-if(obj._is$&&obj.serialize){
-return obj.serialize();
-}else{
-if(dojo.isArray(obj)){
-return dojo.map(obj,function(item){
-return $.param(item);
-}).join("&");
-}else{
-return dojo.objectToQuery(obj);
-}
-}
-};
-$.isFunction=function(){
-var _127=dojo.isFunction.apply(dojo,arguments);
-if(_127){
-_127=(typeof (arguments[0])!="object");
-}
-return _127;
-};
+	//Enable io topic publishing
+	dojo.config.ioPublish = true;
+
+	//Support stuff for toDom
+	var selfClosedTags = "|img|meta|hr|br|input|";
+
+	function toDom(/*String*/html, /*Document?*/doc){
+		//summary converts HTML string into DOM nodes.
+		//Make sure html is a string.
+		html += "";
+
+		//Convert <tag/> into <tag></tag>
+		html = html.replace(/<\s*(\w+)([^\/\>]*)\/\s*>/g, function(tag, name, contents){
+			if(selfClosedTags.indexOf("|" + name + "|") == -1){
+				return "<" + name + contents + "></" + name + ">";
+			}else{
+				return tag;
+			}
+		});
+
+		return dojo._toDom(html, doc);
+	}
+
+	function cssNameToJs(name){
+		var index = name.indexOf("-");
+		if(index != -1){
+			//Strip off beginning dash
+			if(index == 0){
+				name = name.substring(1);
+			}
+			name = name.replace(/-(\w)/g, function(match, match1){
+				return match1.toUpperCase();
+			});
+		}
+		return name;
+	}
+
+	var _old$ = dojo.global.$;
+	var _oldJQuery = dojo.global.jQuery;
+
+	var $ = dojo.global.$ = dojo.global.jQuery = function(){
+		var arg = arguments[0];
+		if(!arg){
+			return $._wrap([], null, $);
+		}else if(dojo.isString(arg)){
+			if(arg.charAt(0) == "<"){
+				//String of html that needs nodes created.
+				arg = toDom(arg);
+				//If a DocumentFragment, convert to use its children
+				//since we want to treat all top level nodes as elements
+				//in the NodeList array.
+				if(arg.nodeType == 11){
+					arg = arg.childNodes;
+				}else{
+					return $._wrap([arg], null, $);
+				}
+				//Use end case of nodelist to finish work.
+			}else{
+				//Normal dojo.query selector.
+				//Switch out query's NodeList constructor to be our specialized
+				//NodeList constructor.
+				var listCtor = dojo._NodeListCtor;
+				dojo._NodeListCtor = $;
+
+				//If the second arg is one of our fake NodeLists then
+				//use the first parent for the call.
+				var arg2 = arguments[1];
+				if(arg2 && arg2._is$){
+					arg2 = arg2[0];
+				}else if(dojo.isString(arg2)){
+					arg2 = dojo.query(arg2)[0];
+				}
+
+				var nl = dojo.query.call(this, arg, arg2);
+				dojo._NodeListCtor = listCtor;
+				return nl;
+			}
+		}else if(dojo.isFunction(arg)){
+			//The addOnLoad case
+			$.ready(arg);
+			return $;
+		}else if(arg == document || arg == window){
+			//If the arg is the document or window, 
+			//then just use it directly.
+			return $._wrap([arg], null, $);
+		}else if(dojo.isArray(arg)){
+			//Input is a plain array.
+			//Filter out duplicates.
+			var ary = [];
+			for(var i = 0; i < arg.length; i++){
+				if(dojo.indexOf(ary, arg[i]) == -1){
+					ary.push(arg[i]);
+				}
+			}
+			return $._wrap(arg, null, $);
+		}else if("nodeType" in arg){
+			//A DOM Node
+			return $._wrap([arg], null, $);
+		}
+
+		//A native NodeList that does not conform to dojo.isArray().
+		//Convert it to a workable array and create new NodeList.
+		return $._wrap(dojo._toArray(arg), null, $);
+
+	};
+
+	//Set up plugin extension point.
+	var nlProto = dojo.NodeList.prototype;
+
+	//Need a delegate, because at least one method conflicts with jquery
+	//API: attr(name) in jQuery only returns a single, first value, where
+	//dojo.attr will return an array.
+	var f = $.fn = $.prototype = dojo.delegate(nlProto);
+
+	//_wrap is required for proper use in dojo.query, but the _adaptAs* methods
+	//do not have to placed on $ -- they can be used directly off dojo.NodeList.
+	$._wrap = dojo.NodeList._wrap;
+
+	//Add in some pseudos selectors
+	var headerRegExp = /^H\d/i;
+	var pseudos = dojo.query.pseudos;
+	dojo.mixin(pseudos, {
+		has: function(name, condition){
+			return function(elem){
+				return $(condition, elem).length;
+			}
+		},
+		visible: function(name, condition){
+			return function(elem){
+				return dojo.style(elem, "visible") != "hidden" && dojo.style(elem, "display") != "none";
+			}
+		},
+		hidden: function(name, condition){
+			return function(elem){
+				return elem.type == "hidden" || dojo.style(elem, "visible") == "hidden" || dojo.style(elem, "display") == "none";
+			}
+		},
+		selected: function(name, condition){
+			return function(elem){
+				return elem.selected;
+			}
+		},
+		checked: function(name, condition){
+			return function(elem){
+				return elem.nodeName.toUpperCase() == "INPUT" && elem.checked;
+			}
+		},
+		disabled: function(name, condition){
+			return function(elem){
+				return elem.getAttribute("disabled");
+			}
+		},
+		enabled: function(name, condition){
+			return function(elem){
+				return !elem.getAttribute("disabled");
+			}
+		},
+		input: function(name, condition){
+			return function(elem){
+				var n = elem.nodeName.toUpperCase();
+				return n == "INPUT" || n == "SELECT" || n == "TEXTAREA" || n == "BUTTON";
+			}
+		},
+		button: function(name, condition){
+			return function(elem){
+				return (elem.nodeName.toUpperCase() == "INPUT" && elem.type == "button") || elem.nodeName.toUpperCase() == "BUTTON";
+			}
+		},
+		header: function(name, condition){
+			return function(elem){
+				return elem.nodeName.match(headerRegExp);
+			}
+		}
+		//TODO: implement :animated
+	});
+
+
+	//Add the input type selectors to pseudos
+	var inputPseudos = {};
+	dojo.forEach([
+		"text", "password", "radio", "checkbox", "submit", "image", "reset", "file"
+	], function(type) {
+		inputPseudos[type] = function(name, condition){
+			return function(elem){
+				return elem.nodeName.toUpperCase() == "INPUT" && elem.type == type;
+			}
+		};
+	});
+	dojo.mixin(pseudos, inputPseudos);
+
+	//Set up browser sniff.
+	$.browser = {
+		mozilla: dojo.isMoz,
+		msie: dojo.isIE,
+		opera: dojo.isOpera,
+		safari: dojo.isSafari
+	};
+	$.browser.version = dojo.isIE || dojo.isMoz || dojo.isOpera || dojo.isSafari || dojo.isWebKit;
+	
+	//Map back into dojo
+	//Hmm maybe this is not so good. Dojo
+	//modules may still be holding on to old
+	//dojo (example: the d._NodeListCtor in query.js)
+	//dojo = dojo.mixin($, dojo);
+
+	// Add $.ready
+	$.ready = $.fn.ready = function(callback){
+		dojo.addOnLoad(dojo.hitch(null, callback, $));
+		return this;
+	}
+
+	//START jquery Core API methods
+	//http://docs.jquery.com/Core
+	f._is$ = true;
+	f.size = function(){return this.length; };
+
+	$.prop = function(node, propCheck){
+		//TODO: not sure about this one, could not find the docs?
+		if(dojo.isFunction(propCheck)){
+			return propCheck.call(node);
+		}else{
+			return propCheck;
+		}
+	}
+
+	$.className = {
+		add: dojo.addClass,
+		remove: dojo.removeClass,
+		has: dojo.hasClass
+	};
+
+	$.makeArray = function(thing){
+		if(typeof thing == "undefined"){
+			return [];
+		}else if(thing.length && !dojo.isString(thing) && !("location" in thing)){
+			//Location check was for excluding window objects that have a length.
+			return dojo._toArray(thing);
+		}else{
+			return [thing];
+		}
+	}
+	
+	$.merge = function(ary1, ary2){
+		//Alters first array by adding in the element.
+		var args = [ary1.length, 0];
+		args = args.concat(ary2);
+		ary1.splice.apply(ary1, args);
+		return ary1;
+	}
+
+	$.each = function(/*Array||ArrayLike*/list, /*Function*/cb){
+		//each differs from dojo.NodeList.forEach in that
+		//"this" is the current cycled node. Breaking
+		//the loop is also possible. Also, index is first arg
+		//to the callback.
+		if(dojo.isArrayLike(list)){
+			for(var i = 0; i < list.length; i++){
+				if(cb.call(list[i], i, list[i]) === false){
+					break;
+				}
+			}
+		}else if(dojo.isObject(list)){
+			for(var param in list){
+				if(cb.call(list[param], param, list[param]) === false){
+					break;
+				}
+			}		
+		}
+		return this;
+	};
+	f.each = function(/*Function*/cb){
+		return $.each.call(this, this, cb);
+	};
+	//f.length already implemented by NodeList
+	f.eq = function(){
+		//Direct copy of dojo.NodeList.at, but want
+		//to use our NodeList class.
+		var nl = $();
+		dojo.forEach(arguments, function(i) { if(this[i]) { nl.push(this[i]); } }, this);
+		return nl; // dojo.NodeList
+	};
+	f.get = function(/*Number*/index){
+		if(index || index == 0){
+			return this[index];
+		}
+		return this;
+	};
+	f.index = function(arg){
+		//Hmm, allows passing in a $ nodelist. Apparently in that
+		//case take the first item in that array and match
+		if(arg._is$){
+			arg = arg[0];
+		}
+		return this.indexOf(arg);
+	}
+
+	//.data implementation
+	var dataStore = [];
+	var dataId = 0;
+	var dataAttr = dojo._scopeName + "DataId";
+	
+	var getDataId = function(node){
+		var id = node.getAttribute(dataAttr);
+		if(!id){
+			id = dataId++;
+			node.setAttribute(dataAttr, id);
+		}
+	}
+	
+	var getData = function(node){
+		var data = {};
+		if(node.nodeType == 1){
+			var id = getDataId(node);
+			data = dataStore[id];
+			if(!data){
+				data = dataStore[id] = {};
+			}
+		}
+		return data;
+	}
+
+	$.data = function(/*DOMNode*/node, /*String*/name, /*String*/value){
+		var result = null;
+		if(name == "events"){
+			//Special case "events", since jquery tests seem to use it to
+			//get the event handler storage for jquery. So for jquery apps
+			//"events" is probably a reserved word anyway.
+			result = listeners[node.getAttribute(eventAttr)];
+			var isEmpty = true;
+			if(result){
+				for(var param in result){
+					isEmpty = false;
+					break;
+				}
+			}
+			return isEmpty ? null : result;
+		}
+
+		var data = getData(node);
+		if(typeof value != "undefined"){
+			data[name] = value;
+		}else{
+			result = data[name];
+		}
+		return value ? this : result;
+	}
+
+	$.removeData = function(/*DOMNode*/node, /*String*/name){
+		var data = getData(node);
+		delete data[name];
+		if(node.nodeType == 1){
+			var isEmpty = true;
+			for(var param in data){
+				isEmpty = false;
+				break;
+			}
+			if(isEmpty){
+				node.removeAttribute(dataAttr);
+			}
+		}
+		return this;
+	}
+
+	f.data = function(/*String*/name, /*String*/value){
+		var result = null;
+		this.forEach(function(node){
+			result = $.data(node, name, value);
+		});
+
+		return value ? this : result;
+	}
+
+	f.removeData = function(/*String*/name){
+		this.forEach(function(node){
+			$.removeData(node, name);
+		});
+		return this;
+	}
+	
+	function jqMix(obj, props){
+		//summary: an attempt at a mixin that follows
+		//jquery's .extend rules. Seems odd. Not sure how
+		//to resolve this with dojo.mixin and what the use
+		//cases are for the jquery version.
+		//Copying some code from dojo._mixin.
+		if(obj == props){
+			return obj;
+		}
+		var tobj = {};
+		for(var x in props){
+			// the "tobj" condition avoid copying properties in "props"
+			// inherited from Object.prototype.  For example, if obj has a custom
+			// toString() method, don't overwrite it with the toString() method
+			// that props inherited from Object.prototype
+			if((tobj[x] === undefined || tobj[x] != props[x]) && props[x] !== undefined && obj != props[x]){
+				if(dojo.isObject(obj[x]) && dojo.isObject(props[x])){
+					if(dojo.isArray(props[x])){
+						obj[x] = props[x];
+					}else{
+						obj[x] = jqMix(obj[x], props[x]);
+					}
+				}else{
+					obj[x] = props[x];
+				}
+			}
+		}
+		// IE doesn't recognize custom toStrings in for..in
+		if(dojo.isIE && props){
+			var p = props.toString;
+			if(typeof p == "function" && p != obj.toString && p != tobj.toString &&
+				p != "\nfunction toString() {\n    [native code]\n}\n"){
+					obj.toString = props.toString;
+			}
+		}
+		return obj; // Object
+	}
+
+	f.extend = function(){
+		var args = [this];
+		args = args.concat(arguments);
+		return $.extend.apply($, args);
+	}
+
+	$.extend = function(){
+		//Could have multiple args to mix in. Similar to dojo.mixin,
+		//but has some different rules, and the mixins all get applied
+		//to the first arg.
+		var args = arguments, finalObj;
+		for(var i = 0; i < args.length; i++){
+			var obj = args[i];
+			if(obj && dojo.isObject(obj)){
+				if(!finalObj){
+					finalObj = obj;
+				}else{
+					jqMix(finalObj, obj);
+				}
+			}
+		}
+		return finalObj;		
+	}
+
+	$.noConflict = function(/*Boolean*/extreme){
+		var me = $;
+		dojo.global.$ = _old$;
+		if(extreme){
+			dojo.global.jQuery = _oldJQuery;
+		}
+		return me;
+	}
+	//END jquery Core API methods
+	
+	//START jquery Attribute API methods
+	//http://docs.jquery.com/Attributes
+	f.attr = function(name, value){
+		//The isObject tests below are to weed out where something
+		//like a form node has an input called "action" but we really
+		//want to get the attribute "action". But in general, favor
+		//a property value over a DOM attribute value.
+		if(arguments.length == 1 && dojo.isString(arguments[0])){
+			//The get case, return first match.
+			var first = this[0];
+			
+			//Weed out empty nodes
+			if(!first){
+				return null;
+			}
+
+			var arg = arguments[0];
+			//favor properties over attributes.
+			var attr = dojo.attr(first, arg);
+			var prop = first[arg];
+			if((arg in first) && !dojo.isObject(prop) && name != "href"){
+				return prop;
+			}else{
+				return attr || prop;
+			}
+		}else if(dojo.isObject(name)){
+			//A setter, using an object.
+			for(var param in name){
+				this.attr(param, name[param]);
+			}
+			return this;
+		}else{
+			//The setter case. Figure out if value is a function.
+			var isFunc = dojo.isFunction(value);
+			this.forEach(function(node, index){
+				var prop = node[name];
+				if((name in node) && !dojo.isObject(prop) && name != "href"){
+					node[name] = (isFunc ? value.call(node, index) : value);
+				}else if(node.nodeType == 1){
+					dojo.attr(node, name, (isFunc ? value.call(node, index) : value));
+				}
+			});
+			return this;
+		}
+	}
+
+	f.removeAttr = function(name){
+		this.forEach(function(node, index){
+			var prop = node[name];
+			if((name in node) && !dojo.isObject(prop) && name != "href"){
+				delete node[name];
+			}else if(node.nodeType == 1){
+				if(name == "class"){
+					//TODO: push this fix into dojo.removeAttr
+					node.removeAttribute(name);
+				}else{
+					dojo.removeAttr(node, name);
+				}
+			}
+		});
+		return this;
+	}
+
+	//addClass, removeClass exist in dojo.NodeList. toggleClass in jQuery case
+	//just means add/remove the classname if it missing/exists. So need custom override.
+	f.toggleClass = function(/*String*/name, /*Expression?*/condition){
+		var hasCondition = arguments.length > 1;
+		this.forEach(function(node){
+			dojo.toggleClass(node, name,  hasCondition ? condition : !dojo.hasClass(node, name));
+		});
+		return this;
+	}
+
+	//Action depends on arguments: if an array of functions do one thing,
+	//If no args, do a display toggle,
+	//If an expression, something that evaluates to true or false,
+	//then toggle display accordingly.
+	//If first arg is a String/Number, then do animation. Second arg
+	//is an optional callback.
+	f.toggle = function(){
+		//If more than two args and we have a function as first arg, then
+		//probably the onclick toggle variant: takes variable args that are
+		//functions and cycles through them on click actions.
+		var args = arguments;
+		if(arguments.length > 1 && dojo.isFunction(arguments[0])){
+			var index = 0;
+			var func = function(){
+				var result = args[index].apply(this, arguments);
+				index += 1;
+				if(index > args.length - 1){
+					index = 0;
+				}
+			};
+			return this.bind("click", func);
+		}else{
+			//The display/hide/show case.
+			var condition = arguments.length == 1 ? arguments[0] : undefined;
+			this.forEach(function(node){
+				var result = typeof condition == "undefined" ? dojo.style(node, "display") == "none" : condition;
+				var action = (result ? "show" : "hide");
+				var nl = $(node);
+				nl[action].apply(nl, args);
+			});
+			return this;
+		}
+	}
+
+	//hasClass just returns true if any of the nodes has the class.
+	f.hasClass = function(/*String*/name){
+		return this.some(function(node){
+			return dojo.hasClass(node, name);
+		});
+	}
+
+	//use the html method from dojo.NodeList-manipulate.
+	f.html = f.innerHTML;
+
+	//END jquery Attribute API methods
+
+	
+	//START jquery Traversing API methods
+	//http://docs.jquery.com/Traversing
+	dojo.forEach(["filter", "slice"], function(item){
+		f[item] = function(){
+			//Convert the "this" value for functions passed in:
+			var nl;
+			if(dojo.isFunction(arguments[0])){
+				var origFunc = arguments[0];
+				arguments[0] = function(item, index){
+					return origFunc.call(item, item, index);
+				}
+			}
+			
+			if(item == "filter" && dojo.isString(arguments[0])){
+				var nl = this._filterQueryResult(this, arguments[0]);
+			}else{
+				var oldCtor = dojo._NodeListCtor;
+				dojo._NodeListCtor = f;
+				//Need to wrap in a $() call since internally some
+				//dojo.NodeList functions reference dojo.NodeList directly.
+				//Need to get a configurable constructor for dojo.NodeList.
+				nl = $(nlProto[item].apply(this, arguments));
+				dojo._NodeListCtor = oldCtor;
+			}
+
+			return nl._stash(this);
+		}
+	});
+
+	f.map = function(/*Function*/callback){
+		//Hmm, this is not like array map/dojo.map where you get one item back for
+		//each input.
+		return this._buildArrayFromCallback(callback);
+	}
+	$.map = function(/*Array*/ary, /*Function*/callback){
+		//Hmm, this is not like array map/dojo.map where you get one item back for
+		//each input.
+		return f._buildArrayFromCallback.call(ary, callback);		
+	}
+
+	$.inArray = function(value, /*Array*/ary){
+		return dojo.indexOf(ary, value);
+	}
+
+	f.is = function(query){
+		return (query ? !!this.filter(query).length : false);
+	}
+
+	//TODO: probably a better way to do this.
+	f.not = function(){
+		var notList = $.apply($, arguments);
+		//TODO: another place where if dojo.NodeList can configure a constructor,
+		//then we could avoid the $() wrapper below.
+		var nl = $(nlProto.filter.call(this, function(node){
+			return notList.indexOf(node) == -1;
+		}));
+		return nl._stash(this);
+	}
+
+	f.add = function(){
+		return this.concat.apply(this, arguments);
+	}
+
+	function iframeDoc(/*DOMNode*/iframeNode){
+		//summary: Returns the document object associated with the iframe DOM Node argument.
+		//Taken from dojo.io.iframe.doc(). Needed for contents() function below.
+		var doc = iframeNode.contentDocument || // W3
+			(
+				(
+					(iframeNode.name) && (iframeNode.document) && 
+					(document.getElementsByTagName("iframe")[iframeNode.name].contentWindow) &&
+					(document.getElementsByTagName("iframe")[iframeNode.name].contentWindow.document)
+				)
+			) ||  // IE
+			(
+				(iframeNode.name)&&(document.frames[iframeNode.name])&&
+				(document.frames[iframeNode.name].document)
+			) || null;
+		return doc;
+	}
+
+	f.contents = function(){
+		var ary = [];
+		this.forEach(function(node){
+			if(node.nodeName.toUpperCase() == "IFRAME"){
+				var doc = iframeDoc(node);
+				if(doc){
+					ary.push(doc);
+				}
+			}else{
+				//TODO: code similar to children() function. Refactor?
+				var children = node.childNodes;
+				//Using for loop for better speed.
+				for(var i = 0; i < children.length; i++){
+					ary.push(children[i]);
+				}
+			}
+		});
+		return this._wrap(ary)._stash(this);
+	}
+
+	f.find = function(/*String*/query){
+		var ary = [];
+		this.forEach(function(node){
+			if(node.nodeType == 1){
+				ary = ary.concat(dojo._toArray($(query, node)));
+			}
+		});
+		return this._getUniqueAsNodeList(ary)._stash(this);
+	}
+
+	f.andSelf = function(){
+		return this.add(this._parent);
+	}
+
+	//END jquery Traversing API methods
+
+	//START jquery Manipulation API methods
+	//http://docs.jquery.com/Manipulation
+
+	f.remove = function(/*String?*/query){
+		//Override NodeList-manipulate's remove so we can remove data.
+		var nl = (query ? this._filterQueryResult(this, query) : this);
+		
+		//Remove data
+		nl.removeData();
+		
+		//Remove event listeners.
+		//TODO! do this, once event stuff is built out.
+		
+		//Remove the items from the DOM, but keep them in this
+		//node list.
+		nl.forEach(function(node){
+			node.parentNode.removeChild(node);
+		});
+		
+		return this;
+	}
+
+	//START jquery CSS API methods
+	//http://docs.jquery.com/CSS	
+	$.css = function(/*DOMNode*/node, /*String|Object*/name, /*String|Number?*/value){
+		name = cssNameToJs(name);
+		
+		//Hmm, dojo.style does an arguments. length check.
+		var result = (value ? dojo.style(node, name, value) : dojo.style(node, name));
+		return result;
+	}
+
+	f.css = function(/*String|Object*/name, /*String|Number?*/value){
+		if(dojo.isString(name)){
+			//Convert name to JS name if needed.
+			name = cssNameToJs(name);
+			if(arguments.length == 2){
+				//set the value. Cannot directly delegate to
+				//this.style, since non-element nodes may be in the mix?
+				//this.contents() in particular will return some funky stuff.
+				
+				//Need to be sure to add "px" if appropriate.
+				if(!dojo.isString(value) && name != "zIndex"){
+					value = value + "px";
+				}
+
+				this.forEach(function(node){
+					if(node.nodeType == 1){
+						dojo.style(node, name, value);
+					}
+				});
+				return this;
+			}else{
+				//return the value
+				value = dojo.style(this[0], name);
+				//Need to be sure to add "px" if appropriate.
+				if(!dojo.isString(value) && name != "zIndex"){
+					value = value + "px";
+				}
+				return value;
+			}
+		}else{
+			for(var param in name){
+				this.css(param, name[param]);
+			}
+			return this;
+		}
+	}
+	
+	function doBox(/*NodeList*/nl, /*String*/boxType, /*String*/prop, /*String||Number*/value){;
+		if(value){
+			//Set height for all elements.
+			var mod = {};
+			mod[prop] = value;
+			nl.forEach(function(node){
+				dojo[boxType](node, mod);
+			});
+			return nl;
+		}else{
+			//Just get first node's height.
+			//Hmm. width is negative when element is display none in FF3?
+			return Math.abs(Math.round(dojo[boxType](nl[0])[prop]));
+		}	
+	}
+
+	f.height = function(value){
+		return doBox(this, "contentBox", "h", value);
+	}
+
+	f.width = function(value){
+		return doBox(this, "contentBox", "w", value);
+	}
+
+	function getDimensions(/*DOMNode*/node, /*String*/type, /*Boolean*/usePadding, /*Boolean*/useBorder, /*Boolean*/useMargin){
+		//summary: sums up the different parts of the width/height based on arguments.
+		//If hidden, temporarily show it, do measurements then close.
+		var rehide = false;
+		if((rehide = node.style.display == "none")){
+			node.style.display = "block";
+		}
+
+		var cs = dojo.getComputedStyle(node);
+		var content = Math.abs(Math.round(dojo._getContentBox(node, cs)[type]));
+		var pad = usePadding ? Math.abs(Math.round(dojo._getPadExtents(node, cs)[type])) : 0;
+		var border = useBorder ? Math.abs(Math.round(dojo._getBorderExtents(node, cs)[type])) : 0;
+		var margin = useMargin ? Math.abs(Math.round(dojo._getMarginExtents(node, cs)[type])) : 0;
+		
+		if(rehide){
+			node.style.display = "none";
+		}
+
+		return pad + content + border + margin;
+	}
+
+	f.innerHeight = function(){
+		return getDimensions(this[0], "h", true);
+	}
+
+	f.innerWidth = function(){
+		return getDimensions(this[0], "w", true);
+	}
+
+	f.outerHeight = function(useMargin){
+		return getDimensions(this[0], "h", true, true, useMargin);
+	}
+
+	f.outerWidth = function(useMargin){
+		return getDimensions(this[0], "w", true, true, useMargin);
+	}
+
+	//END jquery CSS API methods
+
+
+	//START jquery Events API methods
+	//http://docs.jquery.com/Events
+	
+	//ready() already defined above.
+
+	//Event plumbing.
+	var listeners = [];
+	var listenId = 1;
+	var eventAttr = dojo._scopeName + "eventid";
+	var currentEvtData;
+
+	function getNonNamespacedName(/*String*/evtName){
+		//summary: gets name of the event before the first ".".
+		//The $$ stuff is special ids used to create unique names
+		//for bound functions that did not have a unique namespace name.
+		evtName = evtName.split("$$")[0];
+		var dotIndex = evtName.indexOf(".");
+		if(dotIndex != -1){
+			evtName = evtName.substring(0, dotIndex);
+		}
+		return evtName;
+	}
+
+	function domConnect(/*DOMNode*/node, /*String*/evtName){
+		//summary: handles creating the connection with a real DOM event.
+		//This work should only be done one time per evName type.
+		//If the event if an ajax event, use dojo.subscribe instead.
+		if(evtName.indexOf("ajax") == 0){
+			return dojo.subscribe(topics[evtName], function(dfd, res){
+				var fakeEvt = new $.Event(evtName);
+				if("ajaxComplete|ajaxSend|ajaxSuccess".indexOf(evtName) != -1){
+					triggerHandlers(node, [fakeEvt, dfd.ioArgs.xhr, dfd.ioArgs.args]);
+				}else if(evtName == "ajaxError"){
+					triggerHandlers(node, [fakeEvt, dfd.ioArgs.xhr, dfd.ioArgs.args, res]);
+				}else{
+					//ajaxStart|ajaxStop
+					triggerHandlers(node, [fakeEvt]);
+				}
+			});
+		}else{
+			return dojo.connect(node, "on" + evtName, function(e){
+				triggerHandlers(node, arguments);
+			}); //Object
+		}
+	}
+
+	//Event object for compatibility for some tests.
+	$.Event = function(/*String*/type){
+		//Allow for calling function without "new"
+		if(this == $){
+			return new $.Event(type);
+		}
+		if(typeof type == "string"){
+			this.type = type.replace(/!/, "");
+		}else{
+			dojo.mixin(this, type);
+		}
+		this.timeStamp = (new Date()).getTime();
+		this._isFake = true;
+		this._isStrict = (this.type.indexOf("!") != -1);
+		
+	}
+	
+	var ep = $.Event.prototype = {
+		preventDefault: function(){
+			this.isDefaultPrevented = this._true;
+		},
+		stopPropagation: function(){
+			this.isPropagationStopped = this._true;
+		},
+		stopImmediatePropagation: function(){
+			this.isPropagationStopped = this._true;
+			this.isImmediatePropagationStopped = this._true;
+		},
+		_true: function(){ return true; },
+		_false: function(){ return false; }
+	}
+	dojo.mixin(ep, {
+		isPropagationStopped: ep._false,
+		isImmediatePropagationStopped: ep._false,
+		isDefaultPrevented: ep._false
+	});
+
+	function makeTriggerData(data, type){
+		//summary: makes sure that the data array is copied
+		//and has an event as the first arg. If this function generates
+		//a fake event (known by the data[0]._isFake property being true)
+		//then the data[0].target needs to be set by the consumer of this function.
+		
+		data = data || [];
+		data = [].concat(data);
+
+		//If first data item is not an event, make one up.
+		//Need to set up target: prop in the consumers of this
+		//function.
+		var evt = data[0];
+		if(!evt || !evt.preventDefault){
+			evt = type && type.preventDefault ? type : new $.Event(type);
+			data.unshift(evt);
+		}
+		return data;
+	}
+	
+	var triggerHandlersCalled = false;
+
+	function triggerHandlers(/*DOMNode*/node, /*Array*/data, /*Function?*/extraFunc){
+		//summary: handles the actual callbacks to the handlers.
+		
+		//Indicate triggerHandlers was called.
+		triggerHandlersCalled = true;
+		
+		//Uses currentEvtData if this is a simulated event.
+		data = data || currentEvtData;
+		extraFunc = extraFunc;
+
+		//Normalize on a real element if dealing with a document.
+		if(node.nodeType == 9){
+			node = node.documentElement;
+		}
+
+		var nodeId = node.getAttribute(eventAttr);
+		if(!nodeId){
+			return;		
+		}
+
+		var evt = data[0];
+		var evtFullName = evt.type;
+		var evtName = getNonNamespacedName(evtFullName);
+
+		var cbs = listeners[nodeId][evtName];
+
+		var result;
+		//Apply the extra function. What is that about? Not mentioned in the
+		//public APIs?
+		if(extraFunc){
+			result = extraFunc.apply(node, data);
+		}
+
+		if (result !== false){
+			for(var param in cbs){
+				if(param != "_connectId" && (!evt._isStrict && (param.indexOf(evtFullName) == 0) || (evt._isStrict && param == evtFullName))){
+					//Store the callback ID in case unbind is called with this event
+					//so we can only unbind that one callback.
+					evt[dojo._scopeName + "callbackId"] = param;
+
+					var cb = cbs[param];
+					if(typeof cb.data != "undefined"){
+						evt.data = cb.data;
+					}else{
+						evt.data = null;
+					}
+	
+					//Do the actual callback.
+					if ((result = cb.fn.apply(evt.target, data)) === false && !evt._isFake){
+						dojo.stopEvent(evt);
+					}
+					evt.result = result;
+				}
+			}
+		}
+
+		return result;
+	}
+
+	f.triggerHandler = function(/*String*/type, /*Array?*/data, /*Function?*/extraFunc){
+		//Only triggers handlers on the first node. Huh.
+		var node = this[0];
+		if(node && node.nodeType != 3 && node.nodeType != 8){
+			data = makeTriggerData(data, type);
+			return triggerHandlers(node, data, extraFunc);
+		}else{
+			return undefined;
+		}
+	}
+
+	f.trigger = function(/*String*/type, /*Array?*/data, /*Function?*/extraFunc){
+		//Copy data since we may need to modify by adding a 
+		data = makeTriggerData(data, type);
+		var evt = data[0];
+		var type = getNonNamespacedName(evt.type);
+		
+		//Store the current event data in case handlers need
+		//to reference it because of a simulated event.
+		currentEvtData = data;
+		currentExtraFunc = extraFunc;
+
+		var result = null;
+		var needTarget = !evt.target;
+		this.forEach(function(node){
+			//Only handle non text/comment nodes.
+			if(node.nodeType != 3 && node.nodeType != 8){
+
+				//Normalize on a real element if dealing with a document.
+				if(node.nodeType == 9){
+					node = node.documentElement;
+				}
+
+				//Set the node target appropriately for fake events.
+				if(evt._isFake){
+					evt.currentTarget = node;
+					if(needTarget){
+						evt.target = node;
+					}
+				}
+
+				//Bizarre extra function thing. Not really demonstrated in public
+				//API docs.
+				if(extraFunc){
+					var funcData = data.slice(1);
+					result = extraFunc.apply(node, (result = null ? funcData : funcData.concat(result)));
+				}
+
+				if(result !== false){
+					//Trigger DOM event. onclick is handled differently than
+					//others.
+					/*
+					if(type == 'click' && node.onclick && node.nodeName.toUpperCase() == "A"){
+						result = node.onclick.apply(node, data);
+					}
+					*/
+					
+					//Set the "global" flag that indicates if triggerHandlers was called.
+					//If the direct node.event/onevent does not trigger the handlers, do so
+					//manually at the end.
+					triggerHandlersCalled = false;
+					
+					//Trigger functions registered directly on the DOM node.
+					if(node[type]){
+						try{
+							result = node[type]();
+						}catch(e){
+							//Apparently IE throws on some hidden elements. Just eat it.
+						}
+					}else if(node["on" + type]){
+						try{
+							result = node["on" + type]();
+						}catch(e){
+							//Apparently IE throws on some hidden elements. Just eat it.
+						}
+					}
+					
+					if(!triggerHandlersCalled){
+						//Finally triggerHandlers directly if the above code did not trigger it yet.
+						result = triggerHandlers(node, data);
+					}
+
+					//Bubble the event up.
+					//TODO: optimize this path so we don't have to do forEach and NodeList work.
+					var parentNode = node.parentNode;
+					if(result !== false && !evt.isImmediatePropagationStopped() && !evt.isPropagationStopped() && parentNode && parentNode.nodeType == 1){
+						$(parentNode).trigger(type, data, extraFunc);
+					}
+				}
+			}
+		});
+
+		//Clear current event data.
+		currentEvtData = null;
+		currentExtraFunc = null;
+
+		return this;
+	}
+
+	var bindIdCounter = 0;
+
+	f.bind = function(/*String*/type, /*Array||Function?*/data, /*Function*/fn){
+		//Type can be space separated values.
+		type = type.split(" ");
+		
+		//May not have data argument.
+		if(!fn){
+			fn = data;
+			data = null;
+		}
+
+		this.forEach(function(node){
+			//Only handle non text/comment nodes.
+			if(node.nodeType != 3 && node.nodeType != 8){
+			
+				//If document, bind to documentElement
+				if(node.nodeType == 9){
+					node = node.documentElement;
+				}
+
+				//If no nodeId, then create one and attach it to the DOM node.
+				var nodeId = node.getAttribute(eventAttr);
+				if(!nodeId){
+					nodeId = listenId++;
+					node.setAttribute(eventAttr, nodeId);
+					listeners[nodeId] = {};
+				}
+	
+				//Process each event type.
+				for(var i = 0; i < type.length; i++){
+					//Get event name, if have a dot on it, it is namespaced,
+					//be sure to get the core event name.
+					var evtFullName = type[i];
+					var evtName = getNonNamespacedName(evtFullName);
+					if(evtName == evtFullName){
+						//Generate a unique ID for this function binding
+						evtFullName = evtName + "$$" + (bindIdCounter++);
+					}
+	
+					//Get the event listeners for the event name, the complete name.
+					var lls = listeners[nodeId];		
+					if(!lls[evtName]){
+						lls[evtName] = {
+							_connectId: domConnect(node, evtName)
+						};
+					}
+	
+					//Add the callback to the list of listeners.
+					lls[evtName][evtFullName] = {
+						fn: fn,
+						data: data
+					};
+				}
+			}
+		});
+		
+		return this;
+	}
+
+	function copyEventHandlers(/*DOMNode*/ src, /*DOMNode*/ target){
+		// summary:
+		// 		copies the event handlers from onne src *element* node to
+		// 		another target *element* node. Assumes that target had
+		// 		no previous events on it, and is a clone of the src node.
+
+		//Get src listeners.
+		var srcNodeId = target.getAttribute(eventAttr);
+		var sls = listeners[srcNodeId];
+		if(!sls){
+			return;
+		}
+
+		//Generate listeners area for target.
+		var nodeId = nodeId = listenId++;
+		target.setAttribute(eventAttr, nodeId);
+		var tls = listeners[nodeId] = {};
+
+		//Loope through events in source. Protect against bad
+		//code modifying Object.prototype.
+		var empty = {};
+		for (var evtName in sls){
+			var tEvtData = tls[evtName] = {
+				_connectId: domConnect(target, evtName)
+			};
+			var sEvtData = sls[evtName];
+
+			for (var evtFullName in sEvtData){
+				tEvtData[evtFullName] = {
+					fn: sEvtData[evtFullName].fn,
+					data: sEvtData[evtFullName].data
+				};
+			}
+		}
+	}
+
+	function listenerUnbind(lls, evtName, evtFullName, callbackId, fn){
+		//Handles the real remove of an event and dojo.disconnects DOM handler if necessary.
+		//This has to be broken out of the main unbind function because we have to support
+		//things like unbind(".test") that go across major event names. Yuck.
+		var handles = lls[evtName];
+		if(handles){
+			var hasDot = evtFullName.indexOf(".") != -1;
+			var forceDelete = false;
+
+			if(callbackId){
+				//Only need to unbind that one callback
+				delete handles[callbackId];
+			}else if(!hasDot && !fn){
+				forceDelete = true;
+			}else if(hasDot){
+				//A namespaced event.
+				//Problem is the namespaced event could be something like
+				//".test" which means remove all that end in .test. Yuck.
+				if(evtFullName.charAt(0) == "."){
+					for(var param in handles){
+						if(param.indexOf(evtFullName) == param.length - evtFullName.length){
+							delete handles[param];
+						}
+					}				
+				}else{
+					delete handles[evtFullName];
+				}
+			}else{
+				//Not a namespaced event. Cycle through the $$ names
+				//to find a function match.
+				for(var param in handles){
+					if(param.indexOf("$$") != -1 && handles[param].fn == fn){
+						delete handles[param];
+						break;
+					}
+				}
+			}
+
+			//Remove handles/disconnect dom if no other params.
+			var allDone = true;
+			for(var param in handles){
+				if(param != "_connectId"){
+					allDone = false;
+					break;
+				}
+			}
+			if(forceDelete || allDone){
+				if(evtName.indexOf("ajax") != -1){
+					dojo.unsubscribe(handles._connectId);
+				}else{
+					dojo.disconnect(handles._connectId);
+				}
+				delete lls[evtName];
+			}
+		}
+	}
+
+	f.unbind = function(/*String*/type, /*Function*/fn){
+		
+		//See if event has a callbackId, if so, then we only unbind
+		//that one callback.
+		var callbackId = type ? type[dojo._scopeName + "callbackId"] : null;
+
+		//Type can be space separated values.
+		type = type && type.type ? type.type : type;
+		type = type ? type.split(" ") : type;
+
+		this.forEach(function(node){
+			//Only handle non text/comment nodes.
+			if(node.nodeType != 3 && node.nodeType != 8){
+				//If document, bind to documentElement
+				if(node.nodeType == 9){
+					node = node.documentElement;
+				}
+
+				//If no nodeId, then create one and attach it to the DOM node.
+				var nodeId = node.getAttribute(eventAttr);
+				
+				if(nodeId){
+					//Get the event listeners for the event name, the complete name.
+					var lls = listeners[nodeId];
+					if(lls){
+						//If no type, then it means do all bound types. Make a list of them.
+						var etypes = type;
+						if(!etypes){
+							etypes = [];
+							for(var param in lls){
+								etypes.push(param);
+							}
+						}
+
+						//Process each event type.
+						for(var i = 0; i < etypes.length; i++){
+							//Get event name, if have a dot on it, it is namespaced,
+							//be sure to get the core event name.
+							var evtFullName = etypes[i];
+							var evtName = getNonNamespacedName(evtFullName);
+			
+							//Problem is the namespaced event could be something like
+							//".test" which means remove all that end in .test. Yuck.
+							if(evtFullName.charAt(0) == "."){
+								for(var param in lls) {
+									listenerUnbind(lls, param, evtFullName, callbackId, fn);
+								}
+							}else{
+								listenerUnbind(lls, evtName, evtFullName, callbackId, fn);
+							}
+						}
+					}
+				}
+			}
+		});
+
+		return this;
+	}
+
+	f.one = function(/*String*/evtName, /*Function*/func){
+		var oneFunc = function(){
+			$(this).unbind(evtName, arguments.callee);
+			return func.apply(this, arguments);
+		}
+
+		return this.bind(evtName, oneFunc);
+	};
+
+	f._cloneNode = function(/*DOMNode*/ src){
+		// summary:
+		// 		private utiltity to clone a node. Copies event handlers too.
+		var target = src.cloneNode(true);
+
+		if(src.nodeType == 1){
+			//Look for event handlers in target.
+			var evNodes = dojo.query("[" + eventAttr + "]", target);
+			for(var i = 0, newNode; newNode = evNodes[i]; i++){
+				var oldNode = dojo.query('[' + eventAttr + '="' + newNode.getAttribute(eventAttr) + '"]', src)[0];
+				if(oldNode){
+					copyEventHandlers(oldNode, newNode);
+				}
+			}
+		}
+		return target;
+	};
+
+	//Temporary testing shim to get past jquery test setup errors.
+	dojo.getObject("$.event.global", true);
+
+	//Set up event handlers
+	dojo.forEach([
+		"blur", "focus", "dblclick", "click", "error", "keydown", "keypress", "keyup", "load", "mousedown",
+		"mouseenter", "mouseleave", "mousemove", "mouseout", "mouseover", "mouseup", "submit",
+		"ajaxStart", "ajaxSend", "ajaxSuccess", "ajaxError", "ajaxComplete", "ajaxStop"
+		], function(evt){
+			f[evt] = function(callback){
+				if(callback){
+					this.bind(evt, callback);
+				}else{
+					this.trigger(evt);
+				}
+				return this;
+			}
+		}
+	);
+
+	//END jquery Events API methods
+
+
+	//START jquery Effects API methods
+	//http://docs.jquery.com/Effects
+	function speedInt(speed){
+		//Fix speed setting, translate string values to numbers.
+		if(dojo.isString(speed)){
+			if(speed == "slow"){
+				speed = 700;
+			}else if(speed = "fast"){
+				speed = 300;
+			}else{
+				//Everything else is considered normal speed.
+				speed = 500;
+			}
+		}
+		return speed;
+	}
+	
+	f.hide = function(/*String||Number*/speed, /*Function?*/callback){
+		//Fix speed setting, translate string values to numbers.
+		speed = speedInt(speed);
+
+		this.forEach(function(node){
+			var style = node.style;
+			
+			//Skip if already hidden
+			var cs = dojo.getComputedStyle(node);
+			if(cs.display == "none"){
+				return;
+			}
+
+			style.overflow = "hidden";
+			style.display = "block";
+			
+			if(speed){
+				//It is alive!
+				dojo.anim(
+					node,
+					{
+						width: 0,
+						height: 0,
+						opacity: 0
+					},
+					speed,
+					null,
+					function(){
+						style.width = "";
+						style.height = "";
+						style.display = "none";
+						return callback && callback.call(node);
+					}
+				);
+			}else{
+				//No need for animation, fast path it.
+				dojo.style(node, "display", "none");
+				if(callback){
+					callback.call(node);
+				}
+			}
+		});
+		return this;
+	}
+
+	f.show = function(/*String||Number*/speed, /*Function?*/callback){
+		//Fix speed setting, translate string values to numbers.
+		speed = speedInt(speed);
+
+		this.forEach(function(node){
+			var style = node.style;
+			//Skip if the node is already showing.
+			var cs = dojo.getComputedStyle(node);
+			if(cs.display != "none"){
+				return;
+			}
+
+			if(speed){
+				//Figure out size of element
+				//so we know when to stop animation.
+				//Try the easy path first.
+				var width = parseFloat(style.width);
+				var height = parseFloat(style.height);
+				if(!width || !height){
+					//temporarily show the element to get
+					//dimensions
+					style.display = "block";
+					var box = dojo.marginBox(node);
+					width = box.w;
+					height = box.h;
+				}
+
+				//Make sure values are set to hidden state.
+				style.width = 0;
+				style.height = 0;
+				style.overflow = "hidden";
+				dojo.attr(node, "opacity", 0);
+				style.display = "block";
+
+				//It is alive!
+				dojo.anim(
+					node,
+					{
+						width: width,
+						height: height,
+						opacity: 1
+					},
+					speed,
+					null,
+					callback ? dojo.hitch(node, callback) : undefined
+				);				
+			}else{
+				dojo.style(node, "display", "block");
+				if(callback){
+					callback.call(node);
+				}
+			}
+		});
+		return this;
+	}
+
+
+	//END jquery Effects API methods
+
+
+	//START jquery Ajax API methods
+	//http://docs.jquery.com/Ajax
+	
+	$.ajaxSettings = {
+	};
+
+	$.ajaxSetup = function(/*Object*/args){
+		dojo.mixin($.ajaxSettings, args);
+	}
+
+	var topics = {
+		"ajaxStart": "/dojo/io/start",
+		"ajaxSend": "/dojo/io/send",
+		"ajaxSuccess": "/dojo/io/load",
+		"ajaxError": "/dojo/io/error",
+		"ajaxComplete": "/dojo/io/done",
+		"ajaxStop": "/dojo/io/stop"
+	};
+
+	for(var fnName in topics){
+		//Make sure we are dealing with properties
+		//we care about and not something another toolkit added.
+		if(fnName.indexOf("ajax") == 0){
+			;(function(fnName){
+				f[fnName] = function(callback){
+					this.forEach(function(node){
+						dojo.subscribe(topics[fnName], function(){
+							var fakeEvt = new $.Event(fnName);
+							var ioArgs = arguments[0] && arguments[0].ioArgs;
+							var xhr = ioArgs && ioArgs.xhr;
+							var args = ioArgs && ioArgs.args;
+							var res = arguments[1];
+							if("ajaxComplete|ajaxSend|ajaxSuccess".indexOf(fnName) != -1){
+								return callback.call(node, fakeEvt, xhr, args);
+							}else if(fnName == "ajaxError"){
+								return callback.call(node, fakeEvt, xhr, args, res);
+							}else{
+								//ajaxStart|ajaxStop
+								return callback.call(node, fakeEvt);
+							}
+						});
+					});
+					return this;
+				}
+			})(fnName);
+		}
+	};
+
+	//Override dojo._xhrObj(dfd.ioArgs.args) to support beforeSend
+	//Do not understand the reason for beforeSend, particularly
+	//returning false stops the request.
+	//WARNING: even with this code, the error and complete callbacks
+	//will be fired because the deferred is cancelled. I feel this is
+	//correct behavior for dojo, and not sure why beforeSend is needed.
+	var _oldXhrObj = dojo._xhrObj;
+	dojo._xhrObj = function(args){
+		var xhr = _oldXhrObj.apply(dojo, arguments);
+		if(args && args.beforeSend){
+			if(args.beforeSend(xhr) === false){
+				return false;
+			}
+		}
+		return xhr;
+	}
+
+	$.ajax = function(/*Object*/args){
+		//Not sure if the args are considered mutable.
+		//Copy them to be safe.
+		var temp = dojo.delegate($.ajaxSettings);
+		for(var param in args){
+			//For data objects merge the data do not overwrite.
+			if(param == "data" && dojo.isObject(args[param]) && dojo.isObject(temp.data)){
+				for(var prop in args[param]){
+					temp.data[prop] = args[param][prop];
+				}
+			}else{
+				temp[param] = args[param];
+			}
+		}
+		args = temp;
+		var url = args.url;
+
+		if("async" in args){
+			args.sync = !args.async;
+		}
+
+		//Turn off topic publications
+		if(args.global === false){
+			args.ioPublish = false;
+		}
+
+		if(args.data){
+			var data = args.data;
+			if(dojo.isString(data)){
+				//convert to an object.
+				args.content = dojo.queryToObject(data);
+			}else{
+				//data property values could be a function, be sure to call them if so.
+				//Hmm, this seems to be of dubious value.
+				for(var param in data){
+					if(dojo.isFunction(data[param])){
+						data[param] = data[param]();
+					}
+				}
+				args.content = data;	
+			}
+		}
+
+		//dataType
+		var dataType = args.dataType;
+		if("dataType" in args){
+			if(dataType == "script"){
+				dataType = "javascript";
+			}else if(dataType == "html"){
+				dataType = "text";
+			}
+			args.handleAs = dataType;
+		}else{
+			//Make a guess based on the URL.
+			dataType = args.handleAs = "text";
+			args.guessedType = true;
+		}
+
+		//cache:
+		if("cache" in args){
+			args.preventCache = !args.cache;
+		}else{
+			if(args.dataType == "script" || args.dataType == "jsonp"){
+				args.preventCache = true;
+			}
+		}
+
+		//Hide error since dojo treats it different.
+		if(args.error){
+			args._jqueryError = args.error;
+			delete args.error;
+		}
+		
+		//TODO: dataFilter
+
+		//Set up callbacks.
+		args.handle = function(result, ioArgs){
+			var textStatus = "success";
+			if(result instanceof Error){
+				textStatus = (result.dojoType == "timeout" ? "timeout" : "error");
+				if(args._jqueryError){
+					args._jqueryError(ioArgs.xhr, textStatus, result);
+				}
+			}else{
+				//If we guessed the type, see if it should be XML.
+				var xml = (ioArgs.args.guessedType && ioArgs.xhr && ioArgs.xhr.responseXML);
+				if(xml){
+					result = xml;
+				}
+
+				if(args.success){
+					args.success(result, textStatus, ioArgs.xhr);
+				}
+			}
+			if(args.complete){
+				args.complete(result, textStatus, ioArgs.xhr);
+			}
+			
+			return result;
+		};
+		
+		//Use a script tag if the request is xdomain or a jsonp thing.
+		var useScript = (dataType == "jsonp");
+		if(dataType == "javascript"){
+			//Get protocol and domain.
+			var colonIndex = url.indexOf(":");
+			var slashIndex = url.indexOf("/");
+			if(colonIndex > 0 && colonIndex < slashIndex){
+				//Possibly xdomain. Peel off protocol and hostname to find out.
+				var lastSlash = url.indexOf("/", slashIndex + 2);
+				if(lastSlash == -1){
+					lastSlash = url.length;
+				}
+				if(location.protocol != url.substring(0, colonIndex + 1) ||
+					location.hostname != url.substring(slashIndex + 2, lastSlash)){
+					useScript = true;	
+				}
+			}
+		}
+
+		if(useScript){
+			if(dataType == "jsonp"){
+				//Look for callback param
+				var cb = args.jsonp;
+				if(!cb){
+					//Look in the URL
+					var params = args.url.split("?")[1];
+					if(params && (params = dojo.queryToObject(params))){
+						cb = findJsonpCallback(params);
+						if(cb){
+							//Remove the cb from the url.
+							var regex = new RegExp("([&\\?])?" + cb + "=?");
+							args.url = args.url.replace(regex + "=?");
+						}
+					}
+					//Look in the content.
+					if(!cb){
+						cb = findJsonpCallback(args.content);
+						if(cb){
+							delete args.content[cb];
+						}
+					}
+				}
+				args.jsonp = cb || "callback";
+			}
+			var dfd = dojo.io.script.get(args);
+			return dfd;
+		}else{
+			var dfd = dojo.xhr(args.type || "GET", args);
+			//If the XHR object is false, it means beforeSend canceled the request.
+			return dfd.ioArgs.xhr === false ? false : dfd.ioArgs.xhr;
+		}
+	}
+
+	function findJsonpCallback(obj){
+		for(var prop in obj){
+			if(prop.indexOf("callback") == prop.length - 8){
+				return prop;
+			}
+		}
+		return null;
+	}
+	
+	$.getpost = function(httpType, url, data, callback, dataType){
+		var args = {
+			url: url,
+			type: httpType
+		};
+
+		//Normalize data, considering it may be the real
+		//callback.
+		if(data){
+			if(dojo.isFunction(data) && !callback){
+				args.complete = data;
+			}else{
+				args.data = data;
+			}
+		}
+
+		//Normalize callback, considering it may be
+		//the datatype.
+		if(callback){
+			if(dojo.isString(callback) && !dataType){
+				dataType = callback;
+			}else{
+				args.complete = callback;
+			}
+		}
+
+		if(dataType){
+			args.dataType = dataType;
+		}
+
+		return $.ajax(args);
+	};
+
+	$.get = dojo.hitch($, "getpost", "GET");
+	$.post = dojo.hitch($, "getpost", "POST");
+	$.getJSON = function(url, data, callback){
+		return $.getpost("GET", url, data, callback, "json");
+	}
+	$.getScript = function(url, callback){
+		return $.ajax({
+			url: url,
+			success: callback,
+			dataType: "script"
+		});
+	}
+
+	f.load = function(url, data, callback){
+		
+		//See if this is a window or document. If so, then want to
+		//register onload handler.
+		var node = this[0];
+		if(!node || !node.nodeType || node.nodeType == 9){
+			dojo.addOnLoad(url);
+			return this;
+		}
+
+		//The rest of this function is the ajax HTML load case.
+		//Pull off selector if it is on the url.
+		var parts = url.split(/\s+/);
+		url = parts[0];
+		var query = parts[1];
+		
+		var finalCb = callback || data;
+
+		var cb = dojo.hitch(this, function(result, textStatus, xhr){
+			//Try to find all the body content.
+			var match = result.match(/\<\s*body[^>]+>.*<\/body\s*>/i);
+			if(match){
+				result = match;
+			}
+
+			//Convert to DOM nodes.
+			var nodes = dojo._toDom(result);
+
+			//Apply query, using a temp div to do the filtering.
+			if(query){
+				var temp = $(dojo.create("div"));
+				temp.append(nodes);
+				nodes = temp.find(query);
+			}else{
+				nodes = $(nodes.nodeType == 11 ? nodes.childNodes : nodes);
+			}
+
+			//Add the HTML to all nodes in this node list.
+			this.html(nodes);
+
+			//Call the user's callback.
+			//Use a timeout to allow any embedded scripts that
+			//were just inserted to run.
+			if(finalCb){
+				setTimeout(dojo.hitch(this, function(){
+					this.forEach(function(node){
+						finalCb.call(node, result, textStatus, xhr);
+					});
+				}), 10);
+			}
+		});
+
+		//Adjust parameters since they are variable.
+		if(!callback){
+			data = cb;
+		}else{
+			callback = cb;
+		}
+
+		//Set HTTP method. If the data is a string, use get, if it is an object,
+		//use post.
+		var method = "GET";
+		if(data && dojo.isObject(data)){
+			method = "POST";
+		}
+
+		$.getpost(method, url, data, callback, "html");
+		return this;
+	}
+
+	var serializeExclude = "file|submit|image|reset|button|";
+	f.serialize = function(){
+		var ret = "";
+		var strs = this.map(function(node){
+			if(node.nodeName.toUpperCase() == "FORM"){
+				return dojo.formToQuery(node);
+			}else{
+				var type = (node.type||"").toLowerCase();
+				if(serializeExclude.indexOf(type) == -1){
+					var val = dojo.fieldToObject(node);
+					if(node.name && val != null){
+						var q = {};
+						q[node.name] = val;
+						return dojo.objectToQuery(q);
+					}
+				}
+			}
+		});
+		return ret + strs.join("&");
+	}
+
+	$.param = function(obj){
+		if(obj._is$ && obj.serialize){
+			return obj.serialize();
+		}else if(dojo.isArray(obj)){
+			return dojo.map(obj, function(item){
+				return $.param(item);
+			}).join("&");
+		}else{
+			return dojo.objectToQuery(obj);
+		}
+	}
+	
+	//END jquery Ajax API methods
+
+	//START jquery Utilities API methods
+	//http://docs.jquery.com/Utilities
+	//TODO:
+	
+	$.isFunction = function(){
+		var result = dojo.isFunction.apply(dojo, arguments);
+		//Make sure Object does not return true
+		if(result){
+			result = (typeof(arguments[0]) != "object");
+		}
+		return result;
+	}
+
+	//END jquery Utilities API methods
+
+	
 })();
-}
+
diff --git a/dojox/json/query.js b/dojox/json/query.js
index 966a4c0..6b7ee19 100644
--- a/dojox/json/query.js
+++ b/dojox/json/query.js
@@ -1,142 +1,260 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.json.query"]){
-dojo._hasResource["dojox.json.query"]=true;
 dojo.provide("dojox.json.query");
+
 (function(){
-function s(_1,_2,_3,_4){
-var _5=_1.length,_6=[];
-_3=_3||_5;
-_2=(_2<0)?Math.max(0,_2+_5):Math.min(_5,_2);
-_3=(_3<0)?Math.max(0,_3+_5):Math.min(_5,_3);
-for(var i=_2;i<_3;i+=_4){
-_6.push(_1[i]);
-}
-return _6;
-};
-function e(_7,_8){
-var _9=[];
-function _a(_b){
-if(_8){
-if(_8===true&&!(_b instanceof Array)){
-_9.push(_b);
-}else{
-if(_b[_8]){
-_9.push(_b[_8]);
-}
-}
-}
-for(var i in _b){
-var _c=_b[i];
-if(!_8){
-_9.push(_c);
-}else{
-if(_c&&typeof _c=="object"){
-_a(_c);
-}
-}
-}
-};
-if(_8 instanceof Array){
-if(_8.length==1){
-return _7[_8[0]];
-}
-for(var i=0;i<_8.length;i++){
-_9.push(_7[_8[i]]);
-}
-}else{
-_a(_7);
-}
-return _9;
-};
-function _d(_e,_f){
-var _10=[];
-var _11={};
-for(var i=0,l=_e.length;i<l;++i){
-var _12=_e[i];
-if(_f(_12,i,_e)){
-if((typeof _12=="object")&&_12){
-if(!_12.__included){
-_12.__included=true;
-_10.push(_12);
-}
-}else{
-if(!_11[_12+typeof _12]){
-_11[_12+typeof _12]=true;
-_10.push(_12);
-}
-}
-}
-}
-for(i=0,l=_10.length;i<l;++i){
-if(_10[i]){
-delete _10[i].__included;
-}
-}
-return _10;
-};
-dojox.json.query=function(_13,obj){
-var _14=0;
-var str=[];
-_13=_13.replace(/"(\\.|[^"\\])*"|'(\\.|[^'\\])*'|[\[\]]/g,function(t){
-_14+=t=="["?1:t=="]"?-1:0;
-return (t=="]"&&_14>0)?"`]":(t.charAt(0)=="\""||t.charAt(0)=="'")?"`"+(str.push(t)-1):t;
-});
-var _15="";
-function _16(_17){
-_15=_17+"("+_15;
-};
-function _18(t,a,b,c,d,e,f,g){
-return str[g].match(/[\*\?]/)||f=="~"?"/^"+str[g].substring(1,str[g].length-1).replace(/\\([btnfr\\"'])|([^\w\*\?])/g,"\\$1$2").replace(/([\*\?])/g,"[\\w\\W]$1")+(f=="~"?"$/i":"$/")+".test("+a+")":t;
-};
-_13.replace(/(\]|\)|push|pop|shift|splice|sort|reverse)\s*\(/,function(){
-throw new Error("Unsafe function call");
-});
-_13=_13.replace(/([^=]=)([^=])/g,"$1=$2").replace(/@|(\.\s*)?[a-zA-Z\$_]+(\s*:)?/g,function(t){
-return t.charAt(0)=="."?t:t=="@"?"$obj":(t.match(/:|^(\$|Math|true|false|null)$/)?"":"$obj.")+t;
-}).replace(/\.?\.?\[(`\]|[^\]])*\]|\?.*|\.\.([\w\$_]+)|\.\*/g,function(t,a,b){
-var _19=t.match(/^\.?\.?(\[\s*\^?\?|\^?\?|\[\s*==)(.*?)\]?$/);
-if(_19){
-var _1a="";
-if(t.match(/^\./)){
-_16("e");
-_1a=",true)";
-}
-_16(_19[1].match(/\=/)?"dojo.map":_19[1].match(/\^/)?"distinctFilter":"dojo.filter");
-return _1a+",function($obj){return "+_19[2]+"})";
-}
-_19=t.match(/^\[\s*([\/\\].*)\]/);
-if(_19){
-return ".concat().sort(function(a,b){"+_19[1].replace(/\s*,?\s*([\/\\])\s*([^,\\\/]+)/g,function(t,a,b){
-return "var av= "+b.replace(/\$obj/,"a")+",bv= "+b.replace(/\$obj/,"b")+";if(av>bv||bv==null){return "+(a=="/"?1:-1)+";}\n"+"if(bv>av||av==null){return "+(a=="/"?-1:1)+";}\n";
-})+"return 0;})";
-}
-_19=t.match(/^\[(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)\]/);
-if(_19){
-_16("s");
-return ","+(_19[1]||0)+","+(_19[2]||0)+","+(_19[3]||1)+")";
-}
-if(t.match(/^\.\.|\.\*|\[\s*\*\s*\]|,/)){
-_16("e");
-return (t.charAt(1)=="."?",'"+b+"'":t.match(/,/)?","+t:"")+")";
-}
-return t;
-}).replace(/(\$obj\s*((\.\s*[\w_$]+\s*)|(\[\s*`([0-9]+)\s*`\]))*)(==|~)\s*`([0-9]+)/g,_18).replace(/`([0-9]+)\s*(==|~)\s*(\$obj\s*((\.\s*[\w_$]+)|(\[\s*`([0-9]+)\s*`\]))*)/g,function(t,a,b,c,d,e,f,g){
-return _18(t,c,d,e,f,g,b,a);
-});
-_13=_15+(_13.charAt(0)=="$"?"":"$")+_13.replace(/`([0-9]+|\])/g,function(t,a){
-return a=="]"?"]":str[a];
-});
-var _1b=eval("1&&function($,$1,$2,$3,$4,$5,$6,$7,$8,$9){var $obj=$;return "+_13+"}");
-for(var i=0;i<arguments.length-1;i++){
-arguments[i]=arguments[i+1];
-}
-return obj?_1b.apply(this,arguments):_1b;
-};
-})();
-}
+	dojox.json._slice = function(obj,start,end,step){
+		// handles slice operations: [3:6:2]
+		var len=obj.length,results = [];
+		end = end || len;
+		start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
+		end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);
+	  	for(var i=start; i<end; i+=step){
+	  		results.push(obj[i]);
+	  	}
+		return results;
+	}
+	dojox.json._find = function e(obj,name){
+		// handles ..name, .*, [*], [val1,val2], [val]
+		// name can be a property to search for, undefined for full recursive, or an array for picking by index
+		var results = [];
+		function walk(obj){
+			if(name){
+				if(name===true && !(obj instanceof Array)){
+					//recursive object search
+					results.push(obj);
+				}else if(obj[name]){
+					// found the name, add to our results
+					results.push(obj[name]);
+				}
+			}
+			for(var i in obj){
+				var val = obj[i];
+				if(!name){
+					// if we don't have a name we are just getting all the properties values (.* or [*])
+					results.push(val);
+				}else if(val && typeof val == 'object'){
+					
+					walk(val);
+				}
+			}
+		}
+		if(name instanceof Array){
+			// this is called when multiple items are in the brackets: [3,4,5]
+			if(name.length==1){
+				// this can happen as a result of the parser becoming confused about commas 
+				// in the brackets like [@.func(4,2)]. Fixing the parser would require recursive 
+				// analsys, very expensive, but this fixes the problem nicely. 
+				return obj[name[0]];
+			}
+			for(var i = 0; i < name.length; i++){
+				results.push(obj[name[i]]);
+			}
+		}else{
+			// otherwise we expanding
+			walk(obj);
+		}
+		return results;
+	}
+	
+	dojox.json._distinctFilter = function(array, callback){
+		// does the filter with removal of duplicates in O(n)
+		var outArr = [];
+		var primitives = {};
+		for(var i=0,l=array.length; i<l; ++i){
+			var value = array[i];
+			if(callback(value, i, array)){
+				if((typeof value == 'object') && value){
+					// with objects we prevent duplicates with a marker property
+					if(!value.__included){
+						value.__included = true;
+						outArr.push(value);
+					}
+				}else if(!primitives[value + typeof value]){
+					// with primitives we prevent duplicates by putting it in a map 
+					primitives[value + typeof value] = true;
+					outArr.push(value);
+				}
+			}
+		}
+		for(i=0,l=outArr.length; i<l; ++i){
+			// cleanup the marker properties
+			if(outArr[i]){
+				delete outArr[i].__included;
+			}
+		}
+		return outArr;
+	}
+	dojox.json.query = function(/*String*/query,/*Object?*/obj){
+		// summary:
+		// 		Performs a JSONQuery on the provided object and returns the results. 
+		// 		If no object is provided (just a query), it returns a "compiled" function that evaluates objects
+		// 		according to the provided query.
+		// query:
+		// 		Query string
+		// 	obj:
+		// 		Target of the JSONQuery
+		//
+		//	description:
+		//		JSONQuery provides a comprehensive set of data querying tools including filtering,
+		//		recursive search, sorting, mapping, range selection, and powerful expressions with
+		//		wildcard string comparisons and various operators. JSONQuery generally supersets
+		// 		JSONPath and provides syntax that matches and behaves like JavaScript where
+		// 		possible.
+		//
+		//		JSONQuery evaluations begin with the provided object, which can referenced with
+		// 		$. From
+		// 		the starting object, various operators can be successively applied, each operating
+		// 		on the result of the last operation. 
+		//
+		// 		Supported Operators:
+		// 		--------------------
+		//		* .property - This will return the provided property of the object, behaving exactly 
+		// 		like JavaScript. 
+		// 		* [expression] - This returns the property name/index defined by the evaluation of 
+		// 		the provided expression, behaving exactly like JavaScript.
+		//		* [?expression] - This will perform a filter operation on an array, returning all the
+		// 		items in an array that match the provided expression. This operator does not
+		//		need to be in brackets, you can simply use ?expression, but since it does not
+		//		have any containment, no operators can be used afterwards when used 
+		// 		without brackets.
+		//		* [^?expression] - This will perform a distinct filter operation on an array. This behaves
+		//		as [?expression] except that it will remove any duplicate values/objects from the 
+		//		result set.
+		// 		* [/expression], [\expression], [/expression, /expression] - This performs a sort 
+		// 		operation on an array, with sort based on the provide expression. Multiple comma delimited sort
+		// 		expressions can be provided for multiple sort orders (first being highest priority). /
+		//		indicates ascending order and \ indicates descending order
+		// 		* [=expression] - This performs a map operation on an array, creating a new array
+		//		with each item being the evaluation of the expression for each item in the source array.
+		//		* [start:end:step] - This performs an array slice/range operation, returning the elements
+		//		from the optional start index to the optional end index, stepping by the optional step number.
+		// 		* [expr,expr] - This a union operator, returning an array of all the property/index values from
+		// 		the evaluation of the comma delimited expressions. 
+		// 		* .* or [*] - This returns the values of all the properties of the current object. 
+		// 		* $ - This is the root object, If a JSONQuery expression does not being with a $, 
+		// 		it will be auto-inserted at the beginning. 
+		// 		* @ - This is the current object in filter, sort, and map expressions. This is generally
+		// 		not necessary, names are auto-converted to property references of the current object
+		// 		in expressions. 
+		// 		*	..property - Performs a recursive search for the given property name, returning
+		// 		an array of all values with such a property name in the current object and any subobjects
+		// 		* expr = expr - Performs a comparison (like JS's ==). When comparing to
+		// 		a string, the comparison string may contain wildcards * (matches any number of 
+		// 		characters) and ? (matches any single character).
+		// 		* expr ~ expr - Performs a string comparison with case insensitivity.
+		//		* ..[?expression] - This will perform a deep search filter operation on all the objects and 
+		// 		subobjects of the current data. Rather than only searching an array, this will search 
+		// 		property values, arrays, and their children.
+		//		* $1,$2,$3, etc. - These are references to extra parameters passed to the query
+		//		function or the evaluator function.
+		//		* +, -, /, *, &, |, %, (, ), <, >, <=, >=, != - These operators behave just as they do
+		// 		in JavaScript.
+		//		
+		//	
+		//	
+		// 	|	dojox.json.query(queryString,object) 
+		// 		and
+		// 	|	dojox.json.query(queryString)(object)
+		// 		always return identical results. The first one immediately evaluates, the second one returns a
+		// 		function that then evaluates the object.
+		//  
+		// 	example:
+		// 	|	dojox.json.query("foo",{foo:"bar"}) 
+		// 		This will return "bar".
+		//
+		//	example:
+		//	|	evaluator = dojox.json.query("?foo='bar'&rating>3");
+		//		This creates a function that finds all the objects in an array with a property
+		//		foo that is equals to "bar" and with a rating property with a value greater
+		//		than 3.
+		//	|	evaluator([{foo:"bar",rating:4},{foo:"baz",rating:2}])
+		// 		This returns:
+		// 	|	{foo:"bar",rating:4}
+		//
+		//	example:
+		// 	|	evaluator = dojox.json.query("$[?price<15.00][\rating][0:10]");
+		// 	 	This finds objects in array with a price less than 15.00 and sorts then
+		// 		by rating, highest rated first, and returns the first ten items in from this
+		// 		filtered and sorted list.
+		var depth = 0;	
+		var str = [];
+		query = query.replace(/"(\\.|[^"\\])*"|'(\\.|[^'\\])*'|[\[\]]/g,function(t){
+			depth += t == '[' ? 1 : t == ']' ? -1 : 0; // keep track of bracket depth
+			return (t == ']' && depth > 0) ? '`]' : // we mark all the inner brackets as skippable
+					(t.charAt(0) == '"' || t.charAt(0) == "'") ? "`" + (str.push(t) - 1) :// and replace all the strings
+						t;     
+		});
+		var prefix = '';
+		function call(name){
+			// creates a function call and puts the expression so far in a parameter for a call 
+			prefix = name + "(" + prefix;
+		}
+		function makeRegex(t,a,b,c,d,e,f,g){
+			// creates a regular expression matcher for when wildcards and ignore case is used 
+			return str[g].match(/[\*\?]/) || f == '~' ?
+					"/^" + str[g].substring(1,str[g].length-1).replace(/\\([btnfr\\"'])|([^\w\*\?])/g,"\\$1$2").replace(/([\*\?])/g,"[\\w\\W]$1") + (f == '~' ? '$/i' : '$/') + ".test(" + a + ")" :
+					t;
+		}
+		query.replace(/(\]|\)|push|pop|shift|splice|sort|reverse)\s*\(/,function(){
+			throw new Error("Unsafe function call");
+		});
+		
+		query = query.replace(/([^=]=)([^=])/g,"$1=$2"). // change the equals to comparisons
+			replace(/@|(\.\s*)?[a-zA-Z\$_]+(\s*:)?/g,function(t){
+				return t.charAt(0) == '.' ? t : // leave .prop alone 
+					t == '@' ? "$obj" :// the reference to the current object 
+					(t.match(/:|^(\$|Math|true|false|null)$/) ? "" : "$obj.") + t; // plain names should be properties of root... unless they are a label in object initializer
+			}).
+			replace(/\.?\.?\[(`\]|[^\]])*\]|\?.*|\.\.([\w\$_]+)|\.\*/g,function(t,a,b){
+				var oper = t.match(/^\.?\.?(\[\s*\^?\?|\^?\?|\[\s*==)(.*?)\]?$/); // [?expr] and ?expr and [=expr and =expr
+				if(oper){
+					var prefix = '';
+					if(t.match(/^\./)){
+						// recursive object search
+						call("dojox.json._find");
+						prefix = ",true)";
+					}
+					call(oper[1].match(/\=/) ? "dojo.map" : oper[1].match(/\^/) ? "dojox.json._distinctFilter" : "dojo.filter");
+					return prefix + ",function($obj){return " + oper[2] + "})"; 
+				}
+				oper = t.match(/^\[\s*([\/\\].*)\]/); // [/sortexpr,\sortexpr]
+				if(oper){
+					// make a copy of the array and then sort it using the sorting expression
+					return ".concat().sort(function(a,b){" + oper[1].replace(/\s*,?\s*([\/\\])\s*([^,\\\/]+)/g,function(t,a,b){
+							return "var av= " + b.replace(/\$obj/,"a") + ",bv= " + b.replace(/\$obj/,"b") + // FIXME: Should check to make sure the $obj token isn't followed by characters
+									";if(av>bv||bv==null){return " + (a== "/" ? 1 : -1) +";}\n" +
+									"if(bv>av||av==null){return " + (a== "/" ? -1 : 1) +";}\n";
+					}) + "return 0;})";
+				}
+				oper = t.match(/^\[(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)\]/); // slice [0:3]
+				if(oper){
+					call("dojox.json._slice");
+					return "," + (oper[1] || 0) + "," + (oper[2] || 0) + "," + (oper[3] || 1) + ")"; 
+				}
+				if(t.match(/^\.\.|\.\*|\[\s*\*\s*\]|,/)){ // ..prop and [*]
+					call("dojox.json._find");
+					return (t.charAt(1) == '.' ? 
+							",'" + b + "'" : // ..prop 
+								t.match(/,/) ? 
+									"," + t : // [prop1,prop2]
+									"") + ")"; // [*]
+				}
+				return t;
+			}).
+			replace(/(\$obj\s*((\.\s*[\w_$]+\s*)|(\[\s*`([0-9]+)\s*`\]))*)(==|~)\s*`([0-9]+)/g,makeRegex). // create regex matching
+			replace(/`([0-9]+)\s*(==|~)\s*(\$obj\s*((\.\s*[\w_$]+)|(\[\s*`([0-9]+)\s*`\]))*)/g,function(t,a,b,c,d,e,f,g){ // and do it for reverse =
+				return makeRegex(t,c,d,e,f,g,b,a);
+			});
+		query = prefix + (query.charAt(0) == '$' ? "" : "$") + query.replace(/`([0-9]+|\])/g,function(t,a){
+			//restore the strings
+			return a == ']' ? ']' : str[a];
+		});
+		// create a function within this scope (so it can use expand and slice)
+		
+		var executor = eval("1&&function($,$1,$2,$3,$4,$5,$6,$7,$8,$9){var $obj=$;return " + query + "}");
+		for(var i = 0;i<arguments.length-1;i++){
+			arguments[i] = arguments[i+1];
+		}
+		return obj ? executor.apply(this,arguments) : executor;
+	};
+	
+})();
\ No newline at end of file
diff --git a/dojox/json/ref.js b/dojox/json/ref.js
index 2a2d5d9..dfa53ad 100644
--- a/dojox/json/ref.js
+++ b/dojox/json/ref.js
@@ -1,249 +1,356 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.json.ref"]){
-dojo._hasResource["dojox.json.ref"]=true;
 dojo.provide("dojox.json.ref");
 dojo.require("dojo.date.stamp");
-dojox.json.ref={resolveJson:function(_1,_2){
-_2=_2||{};
-var _3=_2.idAttribute||"id";
-var _4=this.refAttribute;
-var _5=_2.idAsRef;
-var _6=_2.idPrefix||"";
-var _7=_2.assignAbsoluteIds;
-var _8=_2.index||{};
-var _9=_2.timeStamps;
-var _a,_b=[];
-var _c=/^(.*\/)?(\w+:\/\/)|[^\/\.]+\/\.\.\/|^.*\/(\/)/;
-var _d=this._addProp;
-var F=function(){
-};
-function _e(it,_f,_10,_11,_12,_13){
-var i,_14,val,id=_3 in it?it[_3]:_10;
-if(_3 in it||((id!==undefined)&&_11)){
-id=(_6+id).replace(_c,"$2$3");
-}
-var _15=_13||it;
-if(id!==undefined){
-if(_7){
-it.__id=id;
-}
-if(_2.schemas&&(!(it instanceof Array))&&(val=id.match(/^(.+\/)[^\.\[]*$/))){
-_12=_2.schemas[val[1]];
-}
-if(_8[id]&&((it instanceof Array)==(_8[id] instanceof Array))){
-_15=_8[id];
-delete _15.$ref;
-delete _15._loadObject;
-_14=true;
-}else{
-var _16=_12&&_12.prototype;
-if(_16){
-F.prototype=_16;
-_15=new F();
-}
-}
-_8[id]=_15;
-if(_9){
-_9[id]=_2.time;
-}
-}
-while(_12){
-var _17=_12.properties;
-if(_17){
-for(i in it){
-var _18=_17[i];
-if(_18&&_18.format=="date-time"&&typeof it[i]=="string"){
-it[i]=dojo.date.stamp.fromISOString(it[i]);
-}
-}
-}
-_12=_12["extends"];
-}
-var _19=it.length;
-for(i in it){
-if(i==_19){
-break;
-}
-if(it.hasOwnProperty(i)){
-val=it[i];
-if((typeof val=="object")&&val&&!(val instanceof Date)&&i!="__parent"){
-_a=val[_4]||(_5&&val[_3]);
-if(!_a||!val.__parent){
-val.__parent=it;
-}
-if(_a){
-delete it[i];
-var _1a=_a.toString().replace(/(#)([^\.\[])/,"$1.$2").match(/(^([^\[]*\/)?[^#\.\[]*)#?([\.\[].*)?/);
-if((_a=(_1a[1]=="$"||_1a[1]=="this"||_1a[1]=="")?_1:_8[(_6+_1a[1]).replace(_c,"$2$3")])){
-if(_1a[3]){
-_1a[3].replace(/(\[([^\]]+)\])|(\.?([^\.\[]+))/g,function(t,a,b,c,d){
-_a=_a&&_a[b?b.replace(/[\"\'\\]/,""):d];
-});
-}
-}
-if(_a){
-val=_a;
-}else{
-if(!_f){
-var _1b;
-if(!_1b){
-_b.push(_15);
-}
-_1b=true;
-val=_e(val,false,val[_4],true,_18);
-val._loadObject=_2.loader;
-}
-}
-}else{
-if(!_f){
-val=_e(val,_b==it,id===undefined?undefined:_d(id,i),false,_18,_15!=it&&typeof _15[i]=="object"&&_15[i]);
-}
-}
-}
-it[i]=val;
-if(_15!=it&&!_15.__isDirty){
-var old=_15[i];
-_15[i]=val;
-if(_14&&val!==old&&!_15._loadObject&&!(i.charAt(0)=="_"&&i.charAt(1)=="_")&&i!="$ref"&&!(val instanceof Date&&old instanceof Date&&val.getTime()==old.getTime())&&!(typeof val=="function"&&typeof old=="function"&&val.toString()==old.toString())&&_8.onUpdate){
-_8.onUpdate(_15,i,old,val);
-}
-}
-}
-}
-if(_14&&(_3 in it)){
-for(i in _15){
-if(!_15.__isDirty&&_15.hasOwnProperty(i)&&!it.hasOwnProperty(i)&&!(i.charAt(0)=="_"&&i.charAt(1)=="_")&&!(_15 instanceof Array&&isNaN(i))){
-if(_8.onUpdate&&i!="_loadObject"&&i!="_idAttr"){
-_8.onUpdate(_15,i,_15[i],undefined);
-}
-delete _15[i];
-while(_15 instanceof Array&&_15.length&&_15[_15.length-1]===undefined){
-_15.length--;
-}
-}
-}
-}else{
-if(_8.onLoad){
-_8.onLoad(_15);
-}
-}
-return _15;
-};
-if(_1&&typeof _1=="object"){
-_1=_e(_1,false,_2.defaultId,true);
-_e(_b,false);
-}
-return _1;
-},fromJson:function(str,_1c){
-function ref(_1d){
-var _1e={};
-_1e[this.refAttribute]=_1d;
-return _1e;
-};
-try{
-var _1f=eval("("+str+")");
-}
-catch(e){
-throw new SyntaxError("Invalid JSON string: "+e.message+" parsing: "+str);
-}
-if(_1f){
-return this.resolveJson(_1f,_1c);
-}
-return _1f;
-},toJson:function(it,_20,_21,_22){
-var _23=this._useRefs;
-var _24=this._addProp;
-var _25=this.refAttribute;
-_21=_21||"";
-var _26={};
-var _27={};
-function _28(it,_29,_2a){
-if(typeof it=="object"&&it){
-var _2b;
-if(it instanceof Date){
-return "\""+dojo.date.stamp.toISOString(it,{zulu:true})+"\"";
-}
-var id=it.__id;
-if(id){
-if(_29!="#"&&((_23&&!id.match(/#/))||_26[id])){
-var ref=id;
-if(id.charAt(0)!="#"){
-if(it.__clientId==id){
-ref="cid:"+id;
-}else{
-if(id.substring(0,_21.length)==_21){
-ref=id.substring(_21.length);
-}else{
-ref=id;
-}
-}
-}
-var _2c={};
-_2c[_25]=ref;
-return _28(_2c,"#");
-}
-_29=id;
-}else{
-it.__id=_29;
-_27[_29]=it;
-}
-_26[_29]=it;
-_2a=_2a||"";
-var _2d=_20?_2a+dojo.toJsonIndentStr:"";
-var _2e=_20?"\n":"";
-var sep=_20?" ":"";
-if(it instanceof Array){
-var res=dojo.map(it,function(obj,i){
-var val=_28(obj,_24(_29,i),_2d);
-if(typeof val!="string"){
-val="undefined";
-}
-return _2e+_2d+val;
-});
-return "["+res.join(","+sep)+_2e+_2a+"]";
-}
-var _2f=[];
-for(var i in it){
-if(it.hasOwnProperty(i)){
-var _30;
-if(typeof i=="number"){
-_30="\""+i+"\"";
-}else{
-if(typeof i=="string"&&(i.charAt(0)!="_"||i.charAt(1)!="_")){
-_30=dojo._escapeString(i);
-}else{
-continue;
-}
-}
-var val=_28(it[i],_24(_29,i),_2d);
-if(typeof val!="string"){
-continue;
-}
-_2f.push(_2e+_2d+_30+":"+sep+val);
-}
-}
-return "{"+_2f.join(","+sep)+_2e+_2a+"}";
-}else{
-if(typeof it=="function"&&dojox.json.ref.serializeFunctions){
-return it.toString();
-}
-}
-return dojo.toJson(it);
-};
-var _31=_28(it,"#","");
-if(!_22){
-for(var i in _27){
-delete _27[i].__id;
-}
-}
-return _31;
-},_addProp:function(id,_32){
-return id+(id.match(/#/)?id.length==1?"":".":"#")+_32;
-},refAttribute:"$ref",_useRefs:false,serializeFunctions:false};
+
+
+dojox.json.ref = {
+	// summary:
+	// 		Adds advanced JSON {de}serialization capabilities to the base json library.
+	// 		This enhances the capabilities of dojo.toJson and dojo.fromJson,
+	// 		adding referencing support, date handling, and other extra format handling.
+	// 		On parsing, references are resolved. When references are made to
+	// 		ids/objects that have been loaded yet, the loader function will be set to
+	// 		_loadObject to denote a lazy loading (not loaded yet) object. 
+
+
+	resolveJson: function(/*Object*/ root,/*Object?*/ args){
+		// summary:
+		// 		Indexes and resolves references in the JSON object.
+		// description:
+		// 		A JSON Schema object that can be used to advise the handling of the JSON (defining ids, date properties, urls, etc)
+		//
+		// root:
+		//		The root object of the object graph to be processed
+		// args:
+		//		Object with additional arguments:
+		//
+		// The *index* parameter.
+		//		This is the index object (map) to use to store an index of all the objects. 
+		// 		If you are using inter-message referencing, you must provide the same object for each call.
+		// The *defaultId* parameter.
+		//		This is the default id to use for the root object (if it doesn't define it's own id)
+		//	The *idPrefix* parameter.
+		//		This the prefix to use for the ids as they enter the index. This allows multiple tables 
+		// 		to use ids (that might otherwise collide) that enter the same global index. 
+		// 		idPrefix should be in the form "/Service/".  For example,
+		//		if the idPrefix is "/Table/", and object is encountered {id:"4",...}, this would go in the
+		//		index as "/Table/4".
+		//	The *idAttribute* parameter.
+		//		This indicates what property is the identity property. This defaults to "id"
+		//	The *assignAbsoluteIds* parameter.
+		//		This indicates that the resolveJson should assign absolute ids (__id) as the objects are being parsed.
+		//  
+		// The *schemas* parameter
+		//		This provides a map of schemas, from which prototypes can be retrieved
+		// The *loader* parameter
+		//		This is a function that is called added to the reference objects that can't be resolved (lazy objects)
+		// return:
+		//		An object, the result of the processing
+		args = args || {};
+		var idAttribute = args.idAttribute || 'id';
+		var refAttribute = this.refAttribute;
+		var idAsRef = args.idAsRef;
+		var prefix = args.idPrefix || ''; 
+		var assignAbsoluteIds = args.assignAbsoluteIds;
+		var index = args.index || {}; // create an index if one doesn't exist
+		var timeStamps = args.timeStamps;
+		var ref,reWalk=[];
+		var pathResolveRegex = /^(.*\/)?(\w+:\/\/)|[^\/\.]+\/\.\.\/|^.*\/(\/)/;
+		var addProp = this._addProp;
+		var F = function(){};
+		function walk(it, stop, defaultId, needsPrefix, schema, defaultObject){
+			// this walks the new graph, resolving references and making other changes
+		 	var i, update, val, id = idAttribute in it ? it[idAttribute] : defaultId;
+		 	if(idAttribute in it || ((id !== undefined) && needsPrefix)){
+		 		id = (prefix + id).replace(pathResolveRegex,'$2$3');
+		 	}
+		 	var target = defaultObject || it;
+			if(id !== undefined){ // if there is an id available...
+				if(assignAbsoluteIds){
+					it.__id = id;
+				}
+				if(args.schemas && (!(it instanceof Array)) && // won't try on arrays to do prototypes, plus it messes with queries 
+		 					(val = id.match(/^(.+\/)[^\.\[]*$/))){ // if it has a direct table id (no paths)
+		 			schema = args.schemas[val[1]];
+				} 
+				// if the id already exists in the system, we should use the existing object, and just 
+				// update it... as long as the object is compatible
+				if(index[id] && ((it instanceof Array) == (index[id] instanceof Array))){ 
+					target = index[id];
+					delete target.$ref; // remove this artifact
+					delete target._loadObject;
+					update = true;
+				}else{
+				 	var proto = schema && schema.prototype; // and if has a prototype
+					if(proto){
+						// if the schema defines a prototype, that needs to be the prototype of the object
+						F.prototype = proto;
+						target = new F();
+					}
+				}
+				index[id] = target; // add the prefix, set _id, and index it
+				if(timeStamps){
+					timeStamps[id] = args.time;
+				}
+			}
+			while(schema){
+				var properties = schema.properties;
+				if(properties){
+					for(i in it){
+						var propertyDefinition = properties[i];
+						if(propertyDefinition && propertyDefinition.format == 'date-time' && typeof it[i] == 'string'){
+							it[i] = dojo.date.stamp.fromISOString(it[i]);
+						}
+					}
+				}
+				schema = schema["extends"];
+			}
+			var length = it.length;
+			for(i in it){
+				if(i==length){
+					break;		
+				}
+				if(it.hasOwnProperty(i)){
+					val=it[i];
+					if((typeof val =='object') && val && !(val instanceof Date) && i != '__parent'){
+						ref=val[refAttribute] || (idAsRef && val[idAttribute]);
+						if(!ref || !val.__parent){
+							if(it != reWalk){
+								val.__parent = target;
+							}
+						}
+						if(ref){ // a reference was found
+							// make sure it is a safe reference
+							delete it[i];// remove the property so it doesn't resolve to itself in the case of id.propertyName lazy values
+							var path = ref.toString().replace(/(#)([^\.\[])/,'$1.$2').match(/(^([^\[]*\/)?[^#\.\[]*)#?([\.\[].*)?/); // divide along the path
+							if((ref = (path[1]=='$' || path[1]=='this' || path[1]=='') ? root : index[(prefix + path[1]).replace(pathResolveRegex,'$2$3')])){  // a $ indicates to start with the root, otherwise start with an id
+								// if there is a path, we will iterate through the path references
+								if(path[3]){
+									path[3].replace(/(\[([^\]]+)\])|(\.?([^\.\[]+))/g,function(t,a,b,c,d){
+										ref = ref && ref[b ? b.replace(/[\"\'\\]/,'') : d];
+									});
+								}
+							}
+							if(ref){
+								val = ref;
+							}else{
+								// otherwise, no starting point was found (id not found), if stop is set, it does not exist, we have
+								// unloaded reference, if stop is not set, it may be in a part of the graph not walked yet,
+								// we will wait for the second loop
+								if(!stop){
+									var rewalking;
+									if(!rewalking){
+										reWalk.push(target); // we need to rewalk it to resolve references
+									}
+									rewalking = true; // we only want to add it once
+									val = walk(val, false, val[refAttribute], true, propertyDefinition);
+									// create a lazy loaded object
+									val._loadObject = args.loader;
+								}
+							}
+						}else{
+							if(!stop){ // if we are in stop, that means we are in the second loop, and we only need to check this current one,
+								// further walking may lead down circular loops
+								val = walk(
+									val,
+									reWalk==it,
+									id === undefined ? undefined : addProp(id, i), // the default id to use
+									false,
+									propertyDefinition, 
+									// if we have an existing object child, we want to 
+									// maintain it's identity, so we pass it as the default object
+									target != it && typeof target[i] == 'object' && target[i] 
+								);
+							}
+						}
+					}
+					it[i] = val;
+					if(target!=it && !target.__isDirty){// do updates if we are updating an existing object and it's not dirty				
+						var old = target[i];
+						target[i] = val; // only update if it changed
+						if(update && val !== old && // see if it is different 
+								!target._loadObject && // no updates if we are just lazy loading
+								!(i.charAt(0) == '_' && i.charAt(1) == '_') && i != "$ref" &&  
+								!(val instanceof Date && old instanceof Date && val.getTime() == old.getTime()) && // make sure it isn't an identical date
+								!(typeof val == 'function' && typeof old == 'function' && val.toString() == old.toString()) && // make sure it isn't an indentical function
+								index.onUpdate){
+							index.onUpdate(target,i,old,val); // call the listener for each update
+						}
+					}
+				}
+			}
+	
+			if(update && (idAttribute in it || target instanceof Array)){
+				// this means we are updating with a full representation of the object, we need to remove deleted
+				for(i in target){
+					if(!target.__isDirty && target.hasOwnProperty(i) && !it.hasOwnProperty(i) && !(i.charAt(0) == '_' && i.charAt(1) == '_') && !(target instanceof Array && isNaN(i))){
+						if(index.onUpdate && i != "_loadObject" && i != "_idAttr"){
+							index.onUpdate(target,i,target[i],undefined); // call the listener for each update
+						}
+						delete target[i];
+						while(target instanceof Array && target.length && target[target.length-1] === undefined){
+							// shorten the target if necessary
+							target.length--;
+						}
+					}
+				}
+			}else{
+				if(index.onLoad){
+					index.onLoad(target);
+				}
+			}
+			return target;
+		}
+		if(root && typeof root == 'object'){
+			root = walk(root,false,args.defaultId, true); // do the main walk through
+			walk(reWalk,false); // re walk any parts that were not able to resolve references on the first round
+		}
+		return root;
+	},
+
+
+	fromJson: function(/*String*/ str,/*Object?*/ args){
+	// summary:
+	// 		evaluates the passed string-form of a JSON object.
+	//
+	// str:
+	//		a string literal of a JSON item, for instance:
+	//			'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'
+	// args: See resolveJson
+	//
+	// return:
+	//		An object, the result of the evaluation
+		function ref(target){ // support call styles references as well
+			var refObject = {};
+			refObject[this.refAttribute] = target;
+			return refObject;
+		}
+		try{
+			var root = eval('(' + str + ')'); // do the eval
+		}catch(e){
+			throw new SyntaxError("Invalid JSON string: " + e.message + " parsing: "+ str);
+		}		
+		if(root){
+			return this.resolveJson(root, args);
+		}
+		return root;
+	},
+	
+	toJson: function(/*Object*/ it, /*Boolean?*/ prettyPrint, /*Object?*/ idPrefix, /*Object?*/ indexSubObjects){
+		// summary:
+		//		Create a JSON serialization of an object.
+		//		This has support for referencing, including circular references, duplicate references, and out-of-message references
+		// 		id and path-based referencing is supported as well and is based on http://www.json.com/2007/10/19/json-referencing-proposal-and-library/.
+		//
+		// it:
+		//		an object to be serialized.
+		//
+		// prettyPrint:
+		//		if true, we indent objects and arrays to make the output prettier.
+		//		The variable dojo.toJsonIndentStr is used as the indent string
+		//		-- to use something other than the default (tab),
+		//		change that variable before calling dojo.toJson().
+		//
+		// idPrefix: The prefix that has been used for the absolute ids
+		//
+		// return:
+		//		a String representing the serialized version of the passed object.
+		var useRefs = this._useRefs;
+		var addProp = this._addProp;
+		var refAttribute = this.refAttribute;
+		idPrefix = idPrefix || ''; // the id prefix for this context
+		var paths={};
+		var generated = {};
+		function serialize(it,path,_indentStr){
+			if(typeof it == 'object' && it){
+				var value;
+				if(it instanceof Date){ // properly serialize dates
+					return '"' + dojo.date.stamp.toISOString(it,{zulu:true}) + '"';
+				}
+				var id = it.__id;
+				if(id){ // we found an identifiable object, we will just serialize a reference to it... unless it is the root
+					if(path != '#' && ((useRefs && !id.match(/#/)) || paths[id])){
+						var ref = id;	
+						if(id.charAt(0)!='#'){
+							if(it.__clientId == id){
+								ref = "cid:" + id;
+							}else if(id.substring(0, idPrefix.length) == idPrefix){ // see if the reference is in the current context
+								// a reference with a prefix matching the current context, the prefix should be removed
+								ref = id.substring(idPrefix.length);
+							}else{
+								// a reference to a different context, assume relative url based referencing
+								ref = id;
+							}
+						}
+						var refObject = {};
+						refObject[refAttribute] = ref;
+						return serialize(refObject,'#');
+					}
+					path = id;
+				}else{
+					it.__id = path; // we will create path ids for other objects in case they are circular
+					generated[path] = it;
+				}
+				paths[path] = it;// save it here so they can be deleted at the end
+				_indentStr = _indentStr || "";
+				var nextIndent = prettyPrint ? _indentStr + dojo.toJsonIndentStr : "";
+				var newLine = prettyPrint ? "\n" : "";
+				var sep = prettyPrint ? " " : "";
+	
+				if(it instanceof Array){
+					var res = dojo.map(it, function(obj,i){
+						var val = serialize(obj, addProp(path, i), nextIndent);
+						if(typeof val != "string"){
+							val = "undefined";
+						}
+						return newLine + nextIndent + val;
+					});
+					return "[" + res.join("," + sep) + newLine + _indentStr + "]";
+				}
+	
+				var output = [];
+				for(var i in it){
+					if(it.hasOwnProperty(i)){
+						var keyStr;
+						if(typeof i == "number"){
+							keyStr = '"' + i + '"';
+						}else if(typeof i == "string" && (i.charAt(0) != '_' || i.charAt(1) != '_')){
+							// we don't serialize our internal properties __id and __clientId
+							keyStr = dojo._escapeString(i);
+						}else{
+							// skip non-string or number keys
+							continue;
+						}
+						var val = serialize(it[i],addProp(path, i),nextIndent);
+						if(typeof val != "string"){
+							// skip non-serializable values
+							continue;
+						}
+						output.push(newLine + nextIndent + keyStr + ":" + sep + val);
+					}
+				}
+				return "{" + output.join("," + sep) + newLine + _indentStr + "}";
+			}else if(typeof it == "function" && dojox.json.ref.serializeFunctions){
+				return it.toString();
+			}
+	
+			return dojo.toJson(it); // use the default serializer for primitives
+		}
+		var json = serialize(it,'#','');
+		if(!indexSubObjects){
+			for(var i in generated)  {// cleanup the temporary path-generated ids
+				delete generated[i].__id;
+			}
+		}
+		return json;
+	},
+	_addProp: function(id, prop){
+		return id + (id.match(/#/) ? id.length == 1 ? '' : '.' : '#') + prop;
+	},
+	//	refAttribute: String
+	//		This indicates what property is the reference property. This acts like the idAttribute
+	// 		except that this is used to indicate the current object is a reference or only partially 
+	// 		loaded. This defaults to "$ref". 
+	refAttribute: "$ref",
+	_useRefs: false,
+	serializeFunctions: false
 }
diff --git a/dojox/json/schema.js b/dojox/json/schema.js
index 9a94f79..33dc54b 100644
--- a/dojox/json/schema.js
+++ b/dojox/json/schema.js
@@ -1,186 +1,218 @@
-/*
-	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
-*/
+dojo.provide("dojox.json.schema");
 
 
-if(!dojo._hasResource["dojox.json.schema"]){
-dojo._hasResource["dojox.json.schema"]=true;
-dojo.provide("dojox.json.schema");
-dojox.json.schema.validate=function(_1,_2){
-return this._validate(_1,_2,false);
-};
-dojox.json.schema.checkPropertyChange=function(_3,_4,_5){
-return this._validate(_3,_4,_5||"property");
-};
-dojox.json.schema.mustBeValid=function(_6){
-if(!_6.valid){
-throw new TypeError(dojo.map(_6.errors,function(_7){
-return "for property "+_7.property+": "+_7.message;
-}).join(", "));
-}
-};
-dojox.json.schema._validate=function(_8,_9,_a){
-var _b=[];
-function _c(_d,_e,_f,i){
-var l;
-_f+=_f?typeof i=="number"?"["+i+"]":typeof i=="undefined"?"":"."+i:i;
-function _10(_11){
-_b.push({property:_f,message:_11});
-};
-if((typeof _e!="object"||_e instanceof Array)&&(_f||typeof _e!="function")){
-if(typeof _e=="function"){
-if(!(Object(_d) instanceof _e)){
-_10("is not an instance of the class/constructor "+_e.name);
-}
-}else{
-if(_e){
-_10("Invalid schema/property definition "+_e);
-}
-}
-return null;
-}
-if(_a&&_e.readonly){
-_10("is a readonly field, it can not be changed");
-}
-if(_e["extends"]){
-_c(_d,_e["extends"],_f,i);
-}
-function _12(_13,_14){
-if(_13){
-if(typeof _13=="string"&&_13!="any"&&(_13=="null"?_14!==null:typeof _14!=_13)&&!(_14 instanceof Array&&_13=="array")&&!(_13=="integer"&&_14%1===0)){
-return [{property:_f,message:(typeof _14)+" value found, but a "+_13+" is required"}];
-}
-if(_13 instanceof Array){
-var _15=[];
-for(var j=0;j<_13.length;j++){
-if(!(_15=_12(_13[j],_14)).length){
-break;
-}
-}
-if(_15.length){
-return _15;
-}
-}else{
-if(typeof _13=="object"){
-var _16=_b;
-_b=[];
-_c(_14,_13,_f);
-var _17=_b;
-_b=_16;
-return _17;
-}
-}
-}
-return [];
-};
-if(_d===undefined){
-if(!_e.optional){
-_10("is missing and it is not optional");
-}
-}else{
-_b=_b.concat(_12(_e.type,_d));
-if(_e.disallow&&!_12(_e.disallow,_d).length){
-_10(" disallowed value was matched");
-}
-if(_d!==null){
-if(_d instanceof Array){
-if(_e.items){
-if(_e.items instanceof Array){
-for(i=0,l=_d.length;i<l;i++){
-_b.concat(_c(_d[i],_e.items[i],_f,i));
-}
-}else{
-for(i=0,l=_d.length;i<l;i++){
-_b.concat(_c(_d[i],_e.items,_f,i));
-}
-}
-}
-if(_e.minItems&&_d.length<_e.minItems){
-_10("There must be a minimum of "+_e.minItems+" in the array");
-}
-if(_e.maxItems&&_d.length>_e.maxItems){
-_10("There must be a maximum of "+_e.maxItems+" in the array");
-}
-}else{
-if(_e.properties){
-_b.concat(_18(_d,_e.properties,_f,_e.additionalProperties));
-}
-}
-if(_e.pattern&&typeof _d=="string"&&!_d.match(_e.pattern)){
-_10("does not match the regex pattern "+_e.pattern);
-}
-if(_e.maxLength&&typeof _d=="string"&&_d.length>_e.maxLength){
-_10("may only be "+_e.maxLength+" characters long");
-}
-if(_e.minLength&&typeof _d=="string"&&_d.length<_e.minLength){
-_10("must be at least "+_e.minLength+" characters long");
-}
-if(typeof _e.minimum!==undefined&&typeof _d==typeof _e.minimum&&_e.minimum>_d){
-_10("must have a minimum value of "+_e.minimum);
-}
-if(typeof _e.maximum!==undefined&&typeof _d==typeof _e.maximum&&_e.maximum<_d){
-_10("must have a maximum value of "+_e.maximum);
-}
-if(_e["enum"]){
-var _19=_e["enum"];
-l=_19.length;
-var _1a;
-for(var j=0;j<l;j++){
-if(_19[j]===_d){
-_1a=1;
-break;
-}
-}
-if(!_1a){
-_10("does not have a value in the enumeration "+_19.join(", "));
-}
-}
-if(typeof _e.maxDecimal=="number"&&(_d.toString().match(new RegExp("\\.[0-9]{"+(_e.maxDecimal+1)+",}")))){
-_10("may only have "+_e.maxDecimal+" digits of decimal places");
-}
-}
-}
-return null;
+dojox.json.schema.validate = function(/*Any*/instance,/*Object*/schema){
+	// summary:
+	//  	To use the validator call this with an instance object and an optional schema object.
+	// 		If a schema is provided, it will be used to validate. If the instance object refers to a schema (self-validating), 
+	// 		that schema will be used to validate and the schema parameter is not necessary (if both exist, 
+	// 		both validations will occur).
+	//	instance:
+	//		The instance value/object to validate
+	// schema:
+	//		The schema to use to validate
+	// description: 
+	// 		The validate method will return an object with two properties:
+	// 			valid: A boolean indicating if the instance is valid by the schema
+	// 			errors: An array of validation errors. If there are no errors, then an 
+	// 					empty list will be returned. A validation error will have two properties: 
+	// 						property: which indicates which property had the error
+	// 						message: which indicates what the error was
+	//
+	return this._validate(instance,schema,false);
 };
-function _18(_1b,_1c,_1d,_1e){
-if(typeof _1c=="object"){
-if(typeof _1b!="object"||_1b instanceof Array){
-_b.push({property:_1d,message:"an object is required"});
-}
-for(var i in _1c){
-if(_1c.hasOwnProperty(i)&&!(i.charAt(0)=="_"&&i.charAt(1)=="_")){
-var _1f=_1b[i];
-var _20=_1c[i];
-_c(_1f,_20,_1d,i);
-}
-}
-}
-for(i in _1b){
-if(_1b.hasOwnProperty(i)&&!(i.charAt(0)=="_"&&i.charAt(1)=="_")&&_1c&&!_1c[i]&&_1e===false){
-_b.push({property:_1d,message:(typeof _1f)+"The property "+i+" is not defined in the schema and the schema does not allow additional properties"});
-}
-var _21=_1c&&_1c[i]&&_1c[i].requires;
-if(_21&&!(_21 in _1b)){
-_b.push({property:_1d,message:"the presence of the property "+i+" requires that "+_21+" also be present"});
-}
-_1f=_1b[i];
-if(_1c&&typeof _1c=="object"&&!(i in _1c)){
-_c(_1f,_1e,_1d,i);
-}
-if(!_a&&_1f&&_1f.$schema){
-_b=_b.concat(_c(_1f,_1f.$schema,_1d,i));
-}
-}
-return _b;
+dojox.json.schema.checkPropertyChange = function(/*Any*/value,/*Object*/schema, /*String*/ property){
+	// summary:
+	// 		The checkPropertyChange method will check to see if an value can legally be in property with the given schema
+	// 		This is slightly different than the validate method in that it will fail if the schema is readonly and it will
+	// 		not check for self-validation, it is assumed that the passed in value is already internally valid.  
+	// 		The checkPropertyChange method will return the same object type as validate, see JSONSchema.validate for 
+	// 		information.
+	//	value:
+	//		The new instance value/object to check
+	// schema:
+	//		The schema to use to validate
+	// return: 
+	// 		see dojox.validate.jsonSchema.validate
+	//
+	return this._validate(value,schema, property || "property");
 };
-if(_9){
-_c(_8,_9,"",_a||"");
-}
-if(!_a&&_8&&_8.$schema){
-_c(_8,_8.$schema,"","");
-}
-return {valid:!_b.length,errors:_b};
+dojox.json.schema.mustBeValid = function(result){
+	//	summary:
+	//		This checks to ensure that the result is valid and will throw an appropriate error message if it is not
+	// result: the result returned from checkPropertyChange or validate
+	if(!result.valid){
+		throw new TypeError(dojo.map(result.errors,function(error){return "for property " + error.property + ': ' + error.message;}).join(", "));
+	}	
+}
+dojox.json.schema._validate = function(/*Any*/instance,/*Object*/schema,/*Boolean*/ _changing){
+	
+	var errors = [];
+		// validate a value against a property definition
+	function checkProp(value, schema, path,i){
+		var l;
+		path += path ? typeof i == 'number' ? '[' + i + ']' : typeof i == 'undefined' ? '' : '.' + i : i;
+		function addError(message){
+			errors.push({property:path,message:message});
+		}
+		
+		if((typeof schema != 'object' || schema instanceof Array) && (path || typeof schema != 'function')){
+			if(typeof schema == 'function'){
+				if(!(Object(value) instanceof schema)){
+					addError("is not an instance of the class/constructor " + schema.name);
+				}
+			}else if(schema){
+				addError("Invalid schema/property definition " + schema);
+			}
+			return null;
+		}			
+		if(_changing && schema.readonly){
+			addError("is a readonly field, it can not be changed");
+		}
+		if(schema['extends']){ // if it extends another schema, it must pass that schema as well
+			checkProp(value,schema['extends'],path,i);
+		}
+		// validate a value against a type definition
+		function checkType(type,value){
+			if(type){
+				if(typeof type == 'string' && type != 'any' && 
+						(type == 'null' ? value !== null : typeof value != type) && 
+						!(value instanceof Array && type == 'array') &&
+						!(type == 'integer' && value%1===0)){
+					return [{property:path,message:(typeof value) + " value found, but a " + type + " is required"}];
+				}
+				if(type instanceof Array){
+					var unionErrors=[];
+					for(var j = 0; j < type.length; j++){ // a union type 
+						if(!(unionErrors=checkType(type[j],value)).length){
+							break;
+						}
+					}
+					if(unionErrors.length){
+						return unionErrors;
+					}
+				}else if(typeof type == 'object'){
+					var priorErrors = errors;
+					errors = []; 
+					checkProp(value,type,path);
+					var theseErrors = errors;
+					errors = priorErrors;
+					return theseErrors; 
+				} 
+			}
+			return [];
+		}
+		if(value === undefined){
+			if(!schema.optional){  
+				addError("is missing and it is not optional");
+			}
+		}else{
+			errors = errors.concat(checkType(schema.type,value));
+			if(schema.disallow && !checkType(schema.disallow,value).length){
+				addError(" disallowed value was matched");
+			}
+			if(value !== null){
+				if(value instanceof Array){
+					if(schema.items){
+						if(schema.items instanceof Array){
+							for(i=0,l=value.length; i<l; i++){
+								errors.concat(checkProp(value[i],schema.items[i],path,i));
+							}
+						}else{
+							for(i=0,l=value.length; i<l; i++){
+								errors.concat(checkProp(value[i],schema.items,path,i));
+							}
+						}							
+					}
+					if(schema.minItems && value.length < schema.minItems){
+						addError("There must be a minimum of " + schema.minItems + " in the array");
+					}
+					if(schema.maxItems && value.length > schema.maxItems){
+						addError("There must be a maximum of " + schema.maxItems + " in the array");
+					}
+				}else if(schema.properties){
+					errors.concat(checkObj(value,schema.properties,path,schema.additionalProperties));
+				}
+				if(schema.pattern && typeof value == 'string' && !value.match(schema.pattern)){
+					addError("does not match the regex pattern " + schema.pattern);
+				}
+				if(schema.maxLength && typeof value == 'string' && value.length > schema.maxLength){
+					addError("may only be " + schema.maxLength + " characters long");
+				}
+				if(schema.minLength && typeof value == 'string' && value.length < schema.minLength){
+					addError("must be at least " + schema.minLength + " characters long");
+				}
+				if(typeof schema.minimum !== undefined && typeof value == typeof schema.minimum && 
+						schema.minimum > value){
+					addError("must have a minimum value of " + schema.minimum);
+				}
+				if(typeof schema.maximum !== undefined && typeof value == typeof schema.maximum && 
+						schema.maximum < value){
+					addError("must have a maximum value of " + schema.maximum);
+				}
+				if(schema['enum']){
+					var enumer = schema['enum'];
+					l = enumer.length;
+					var found;
+					for(var j = 0; j < l; j++){
+						if(enumer[j]===value){
+							found=1;
+							break;
+						}
+					}
+					if(!found){
+						addError("does not have a value in the enumeration " + enumer.join(", "));
+					}
+				}
+				if(typeof schema.maxDecimal == 'number' && 
+					(value.toString().match(new RegExp("\\.[0-9]{" + (schema.maxDecimal + 1) + ",}")))){
+					addError("may only have " + schema.maxDecimal + " digits of decimal places");
+				}
+			}
+		}
+		return null;
+	}
+	// validate an object against a schema
+	function checkObj(instance,objTypeDef,path,additionalProp){
+	
+		if(typeof objTypeDef =='object'){
+			if(typeof instance != 'object' || instance instanceof Array){
+				errors.push({property:path,message:"an object is required"});
+			}
+			
+			for(var i in objTypeDef){ 
+				if(objTypeDef.hasOwnProperty(i) && !(i.charAt(0) == '_' && i.charAt(1) == '_')){
+					var value = instance[i];
+					var propDef = objTypeDef[i];
+					checkProp(value,propDef,path,i);
+				}
+			}
+		}
+		for(i in instance){
+			if(instance.hasOwnProperty(i) && !(i.charAt(0) == '_' && i.charAt(1) == '_') && objTypeDef && !objTypeDef[i] && additionalProp===false){
+				errors.push({property:path,message:(typeof value) + "The property " + i +
+						" is not defined in the schema and the schema does not allow additional properties"});
+			}
+			var requires = objTypeDef && objTypeDef[i] && objTypeDef[i].requires;
+			if(requires && !(requires in instance)){
+				errors.push({property:path,message:"the presence of the property " + i + " requires that " + requires + " also be present"});
+			}
+			value = instance[i];
+			if(objTypeDef && typeof objTypeDef == 'object' && !(i in objTypeDef)){
+				checkProp(value,additionalProp,path,i); 
+			}
+			if(!_changing && value && value.$schema){
+				errors = errors.concat(checkProp(value,value.$schema,path,i));
+			}
+		}
+		return errors;
+	}
+	if(schema){
+		checkProp(instance,schema,'',_changing || '');
+	}
+	if(!_changing && instance && instance.$schema){
+		checkProp(instance,instance.$schema,'','');
+	}
+	return {valid:!errors.length,errors:errors};
 };
-}
+
diff --git a/dojox/json/tests/module.js b/dojox/json/tests/module.js
new file mode 100644
index 0000000..5539c63
--- /dev/null
+++ b/dojox/json/tests/module.js
@@ -0,0 +1,10 @@
+dojo.provide("dojox.json.tests.module");
+
+try{
+	dojo.require("dojox.json.tests.ref");
+	dojo.require("dojox.json.tests.schema");
+	dojo.require("dojox.json.tests.query");
+}catch(e){
+	doh.debug(e);
+}
+
diff --git a/dojox/json/tests/query.js b/dojox/json/tests/query.js
new file mode 100644
index 0000000..d5f6def
--- /dev/null
+++ b/dojox/json/tests/query.js
@@ -0,0 +1,367 @@
+dojo.provide("dojox.json.tests.query");
+dojo.require("dojox.json.query");
+
+
+dojox.json.tests.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	d.errback(errData);	
+};
+
+dojox.json.tests.testData= {
+	store: {
+		"book": [ 
+			{ 
+				"category":"reference",
+				"author":"Nigel Rees",
+				"title":"Sayings of the Century",
+				"price":8.95
+			},
+			{ 
+				"category":"fiction",
+				"author":"Evelyn Waugh",
+				"title":"Sword of Honour",
+				"price":12.99
+			},
+			{ 
+				"category":"fiction",
+				"author":"Herman Melville",
+				"title":"Moby Dick",
+				"isbn":"0-553-21311-3",
+				"price":8.99
+			},
+			{ 
+				"category":"fiction",
+				"author":"J. R. R. Tolkien",
+				"title":"The Lord of the\nRings",
+				"isbn":"0-395-19395-8",
+				"price":22.99
+			}
+		],
+		"bicycle": {
+				"color":"red",
+				"price":19.95
+		}
+	},
+	"symbols":{"@.$;":5}
+};
+
+doh.register("dojox.json.tests.query", 
+	[
+		{
+			name: "$.store.book[=author]",
+			runTest: function(t) {
+				var result = dojox.json.query(this.name,dojox.json.tests.testData);
+				console.log("result",result);
+				result = dojo.toJson(result);
+				var success =  '["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..author",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]';
+				doh.assertEqual(success,result);
+		
+			}
+		},
+		{
+			name: "$.store.*",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success = '[[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the\\nRings","isbn":"0-395-19395-8","price":22.99}],{"color":"red","price":19.95}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store..price",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success = '[8.95,12.99,8.99,22.99,19.95]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[0]?price=22.99",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the\\nRings","isbn":"0-395-19395-8","price":22.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[0][-1:]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the\\nRings","isbn":"0-395-19395-8","price":22.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[0][0,1]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[0][:2]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store.book[=category][^?true]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '["reference","fiction"]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..[^?author~'herman melville']",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,[dojox.json.tests.testData,dojox.json.tests.testData]));
+				var success =  '[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..[^?author='Herman*']",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,[dojox.json.tests.testData,dojox.json.tests.testData]));
+				var success =  '[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..[^?@['author']='Herman*']",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,[dojox.json.tests.testData,dojox.json.tests.testData]));
+				var success =  '[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[0][?(@.isbn)]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the\\nRings","isbn":"0-395-19395-8","price":22.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[0][?(@.price<10)]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[0]?author=$1&price=$2",
+			runTest: function(t) {
+				var query = dojox.json.query(this.name);
+				var result = dojo.toJson(query(dojox.json.tests.testData,"Nigel Rees",8.95));
+				var success =  '[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[0]?author=$1&price=$2",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData,"Herman Melville",8.99));
+				var success =  '[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[0][?(@['price']<10)]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..[?price<10]",
+			runTest: function(t) {
+				var query = dojox.json.query(this.name);
+				console.log("recursive object search",query.toString());
+				var result = dojo.toJson(query(dojox.json.tests.testData));
+				var success =  '[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store..[?price<10]",
+			runTest: function(t) {
+				var query = dojox.json.query(this.name);
+				console.log("recursive object search",query.toString());
+				var result = dojo.toJson(query(dojox.json.tests.testData));
+				var success =  '[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store.book[/category][/price][=price]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[8.95,8.99,12.99,22.99]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store.book[\\category,\\price][=price]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[8.95,22.99,12.99,8.99]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store.book?title='*of the*'",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the\\nRings","isbn":"0-395-19395-8","price":22.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store.book[?'?iction'=category][=price]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[12.99,8.99,22.99]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store.book[?'?ICTion'~category][=price]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[12.99,8.99,22.99]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store.book[\\price][0].price - $.store.book[/price][0].price",
+			runTest: function(t) {
+				var result = dojox.json.query(this.name,dojox.json.tests.testData);
+				var success =  14;
+				doh.assertEqual(success,Math.round(result));
+			}
+		},
+		{
+			name: "$.symbols[*]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success =  '[5]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.symbols['@.$;']",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query(this.name,dojox.json.tests.testData));
+				var success = '5';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store.book[?(@.price<15)][1:3]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query("$.store.book[?(@.price<15)][1:3]",dojox.json.tests.testData));
+				var success = '[{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store.book[?(@.price<15)][=author]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query("$.store.book[?(@.price<15)][=author]",dojox.json.tests.testData));
+				var success = '["Nigel Rees","Evelyn Waugh","Herman Melville"]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store.book[1].category",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query("$.store.book[1].category",dojox.json.tests.testData));
+				var success = '"fiction"';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "test $.store.bicycle",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query("$.store.bicycle",dojox.json.tests.testData));
+				var success = '{"color":"red","price":19.95}';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "test $.store.book[=category]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.json.query("$.store.book[=category]",dojox.json.tests.testData));
+				var success = '["reference","fiction","fiction","fiction"]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "safeEval: Illegal Eval",
+			runTest: function(t) {
+				try { 
+					var result = dojo.toJson(dojox.json.query("$.store.book[?(push(5))]",dojox.json.tests.testData));
+					console.log("Illegal eval permitted");
+					doh.e("Illegal eval was permitted");
+				} catch(e) {
+					console.log("Eval properly blocked", e);	
+				}
+			}
+		},
+		{
+			name: "safeEval: Illegal Eval 2",
+			runTest: function(t) {
+				try { 
+					var result = dojo.toJson(dojox.json.query("$.store.book[?(new Danger)]",dojox.json.tests.testData ));
+					console.log("Illegal eval permitted");
+					doh.e("Illegal eval was permitted");
+				} catch(e) {
+					console.log("Eval properly blocked", e);						
+				}
+			}
+		},
+		{
+			name: "safeEval: Illegal Eval 3",
+			runTest: function(t) {
+				try { 
+					var result = dojo.toJson(dojox.json.query("$.store.book[?(@+=2)]",dojox.json.tests.testData));
+					console.log("Illegal eval permitted");
+					doh.e("Illegal eval was permitted");
+				} catch(e) {
+					console.log("Eval properly blocked", e);	
+				}
+			}
+		}
+
+	]
+);
+function performanceTest(){
+	dojo.require("dojox.jsonPath");
+	var data = [];
+	for(var i = 0; i < 20000;i++){
+		data.push({foo:Math.random()});
+	}
+	var now = new Date().getTime();
+	var results = dojox.jsonPath.query(data,"$[?(@.foo<0.01)]");
+	alert("JSONPath" + (new Date().getTime()-now) + " " + results.length);
+	now = new Date().getTime();
+	results = dojox.json.query("$[?(@.foo<0.01)]",data);
+	alert("JSONQuery" + (new Date().getTime()-now) + " " + results.length);
+}
+
diff --git a/dojox/json/tests/ref.js b/dojox/json/tests/ref.js
new file mode 100644
index 0000000..03c6436
--- /dev/null
+++ b/dojox/json/tests/ref.js
@@ -0,0 +1,69 @@
+dojo.provide("dojox.json.tests.ref");
+dojo.require("dojox.json.ref");
+
+doh.register("dojox.json.tests.ref", [
+	function fromRefJson(t) {
+		var testStr = '{a:{$ref:"#"},id:"root",c:{d:"e",f:{$ref:"root.c"}},b:{$ref:"#.c"},"an array":["a string"],"a string":{$ref:"#an array.0"}}';
+
+		var mirrorObj = dojox.json.ref.fromJson(testStr);
+		t.assertEqual(mirrorObj, mirrorObj.a);
+		t.assertEqual(mirrorObj.c, mirrorObj.c.f);
+		t.assertEqual(mirrorObj.c, mirrorObj.b);
+		t.assertEqual(mirrorObj["a string"], "a string");
+	},
+	function toAndFromRefJson(t) {
+		var testObj = {a:{},b:{"has space":{}}};
+		testObj.a.d= testObj;
+		var arrayItem = testObj.array = [{}];
+		arrayItem[1] = arrayItem[0];
+		testObj.b.g=testObj.a;
+		testObj.b["has space"].f = testObj.b;
+		testObj.b.h=testObj.a;
+		var mirrorObj = dojox.json.ref.fromJson(dojox.json.ref.toJson(testObj));
+		t.assertEqual(mirrorObj.a.d, mirrorObj);
+		t.assertEqual(mirrorObj.b.g, mirrorObj.a);
+		t.assertEqual(mirrorObj.b["has space"].f, mirrorObj.b);
+		t.assertEqual(mirrorObj.b.h, mirrorObj.a);
+		t.assertEqual(mirrorObj.array[0], mirrorObj.array[1]);
+	},
+	function usingSchemas(t) {
+		var testStr = '{id:"/dog/1",eats:{$ref:"/cat/2"},aTime:"2008-11-07T20:26:17-07:00"}';
+		var schemas = {
+			"/dog/":{prototype:{barks:true},properties:{aTime:{format:'date-time'}}},
+			"/cat/":{prototype:{meows:true}}
+		}
+		var testObj = dojox.json.ref.fromJson(testStr,{
+			schemas:schemas
+		});
+		t.t(testObj.barks);
+		t.t(testObj.aTime instanceof Date);
+		t.t(testObj.eats.meows);
+	},
+	function secondLevelLazy(t) {
+		var testStr = '[{$ref:1,foo:"bar"},{$ref:2, me:{$ref:2},first:{$ref:1}}]';
+		var mirrorObj = dojox.json.ref.fromJson(testStr);
+		t.is(mirrorObj[0].foo,"bar");
+		t.is(mirrorObj[1],mirrorObj[1].me);
+		t.is(mirrorObj[0],mirrorObj[1].first);
+	}
+	
+	/*,
+	function performanceTest(t) {
+		var normalishJson= '[{"id":"1",	"created":"2007-10-23T14:40:18Z","address":"somewhere","phoneNumber":"555-5555","comment":"this is great",	"firstName":"Jim",	"lastName":"Jones"},{"id":"20","created":"2008-06-03T19:45:12Z",	"firstName":"Kristopher",	"lastName":"dddddd"	},{"id":"23",	"foo":"ba=sr",	"firstName":"Jennika",	"lastName":"Zyp"	}]';
+		var now = new Date().getTime();
+		for(var i=0;i<1000;i++){
+		}
+		console.log("Just Loop",new Date().getTime()-now);
+		now = new Date().getTime();
+		var result;
+		for(i=0;i<1000;i++){
+			result = dojo.fromJson(normalishJson);
+		}
+		console.log("Normal fromJson",new Date().getTime()-now, result, normalishJson.length);
+		now = new Date().getTime();
+		for(i=0;i<1000;i++){
+			result = dojox.json.ref.fromJson(normalishJson);
+		}
+		console.log("JSON Referencing toJson",new Date().getTime()-now, result);
+	}*/
+]);
diff --git a/dojox/json/tests/runTests.html b/dojox/json/tests/runTests.html
new file mode 100644
index 0000000..9690da5
--- /dev/null
+++ b/dojox/json/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.json.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML>
diff --git a/dojox/json/tests/schema.js b/dojox/json/tests/schema.js
new file mode 100644
index 0000000..5df5a42
--- /dev/null
+++ b/dojox/json/tests/schema.js
@@ -0,0 +1,276 @@
+dojo.provide("dojox.json.tests.schema");
+dojo.require("dojox.json.schema");
+dojo.require("dojox.json.ref");
+
+var simpleObj = {
+  "name" : "John Doe",
+  "age" : 30,
+  "$schema":{
+	  "type" : {
+	    "name": {"type":"string",
+	       "required":true},
+	    "age" : {"type":"number",
+	      "maximum":125}
+	  }
+  }
+};
+var biggerObj = {
+  "name" : "John Doe",
+  "born" : "1979-03-23T06:26:07Z",
+  "gender" : "male",
+  tuple:[1,"a",false],
+  "address" : {"street":"123 S Main St",
+    "city":"Springfield",
+    "state":"CA"}
+  
+};
+var invalidBiggerObj = {
+  "name" : "John Doe",
+  "born" : false,
+  "gender" : "mal",
+  "address" : {"street":"123 S Main St",
+    "city":"Springfield",
+    "state":"CA"}
+  
+};
+var biggerSchema = {
+  "readonly":true,
+  "type":"object",
+  "properties":{
+    "name": {"type":"string",
+	   length:5,
+       "optional":false},
+    "tuple":{items:[{"type":"integer"},
+    {"type":"string"},
+    {"type":"boolean"}]},
+    "born" : {"type":["number","string"], //allow for a numeric year, or a full date
+      "format":"date", //format when a string value is used
+      "minimum":1900, //min/max for when a number value is used
+      "maximum":2010
+    },
+    "gender" : {"type":"string",
+    	"enum":["male","female"],
+    	"options":[{"label":"Male",value:"male"},{"label":"Female",value:"female"}]},
+	    "address" : {"type":"object",
+	    	"properties":
+	        {"street":{"type":"string"},
+	         "city":{"type":"string"},
+	         "state":{"type":"string"}}
+	    }
+  }
+};
+var schemaForSchemas ={"description":"This is the JSON Schema for JSON Schemas.",
+ "type":["object","array"],
+ "items":{
+     "type":"object",
+     "properties":{"$ref":"$.properties"},
+     "description":"When the schema is an array, it indicates that it is enforcing tuple typing. Each item in the instance array must correspond to the item in the schema array"},
+ "properties":{
+     "type":{
+     	"type":["string","array"],
+     	"items":{"$ref":"$.properties.type"},
+	"description":"This is a type definition value. This can be a simple type, or a union type",
+	"options":[{"value":"string"},{"value":"object"},{"value":"array"},{"value":"boolean"},{"value":"number"},{"value":"integer"},{"value":"null"},{"value":"any"}],
+	"unconstrained":true,
+	"optional":true,
+	"default":"any"},
+     "optional":{
+     	"type":"boolean",
+     	"description":"This indicates that the instance property in the instance object is not required.",
+	"optional":true,
+	"default":false},
+     "properties":{
+     	"type":"object",
+     	"additionalProperties":{"$ref":"$"},
+     	"description":"This is a definition for the properties of an object value",
+     	"optional":true,
+     	"default":{}
+     },
+     "items":{
+     	"type":"object",
+     	"properties":{"$ref":"$.properties"},
+     	"description":"When the value is an array, this indicates the schema to use to validate each item in an array",
+	"optional":true,
+	"default":{}},
+     "additionalProperties":{
+     	"type":["boolean","object"],
+     	"properties":{"$ref":"$.properties"},
+     	"description":"This provides a default property definition for all properties that are not explicitly defined in an object type definition.",
+	"optional":true,
+	"default":{}},
+     "specificity":{
+        "type":"number",
+        "description":"This indicates an order of specificity of properties. If an instance defines another property with a higher specificity than this one, than this instance property is required.",
+	"optional":true,
+        "default":false},
+     "identity":{
+     	"type":"boolean",
+     	"description":"This indicates that the instance property should have unique values. No other property with the same name in the instance object tree should have the same value.",
+	"optional":true,
+	"default":false},
+     "minimum":{
+     	"type":"number",
+	"optional":true,
+     	"description":"This indicates the minimum value for the instance property when the type of the instance value is a number, or it indicates the minimum number of values in an array when an array is the instance value."},
+     "maximum":{
+     	"type":"number",
+	"optional":true,
+     	"description":"This indicates the maximum value for the instance property when the type of the instance value is a number, or it indicates the maximum number of values in an array when an array is the instance value."},
+     "pattern":{
+     	"type":"string",
+     	"format":"regex",
+     	"description":"When the instance value is a string, this provides a regular expression that a instance string value should match in order to be valid.",
+	"optional":true,
+	"default":".*"},
+     "maxLength" :{
+     	"type":"number",
+	"optional":true,
+     	"description":"When the instance value is a string, this indicates maximum length of the string."},
+     "minLength" :{
+     	"type":"number",
+	"optional":true,
+     	"description":"When the instance value is a string, this indicates minimum length of the string."},
+     "maxItems" :{
+     	"type":"number",
+	"optional":true,
+     	"description":"When the instance value is an array, this indicates maximum number of items."},
+     "minItems" :{
+     	"type":"number",
+	"optional":true,
+     	"description":"When the instance value is an array, this indicates minimum number of items."},
+     "enum" : {
+     	"type":"array",
+	"optional":true,
+     	"description":"This provides an enumeration of possible values that are valid for the instance property."},
+     "options" : {
+     	"type":"array",
+     	"items":{
+     	   "properties":{
+     	   	"label":{
+     	   	    "type":"string",
+     	   	    "description":"This is the label for this option",
+     	   	    "optional":true
+     	   	    },
+     	   	"value":{
+     	   	    "description":"This is the value for this option"
+     	   	}
+     	   },
+     	   "description":"This is an option for list of possible values"
+     	},
+	"optional":true,
+     	"description":"This provides a list of suggested options for the instance property."},
+     "readonly":{
+     	"type":"boolean",
+     	"description":"This indicates that the instance property should not be changed (this is only for interaction, it has no effect for standalone validation).",
+	"optional":true,
+	"default":false},
+     "description":{
+     	"type":"string",
+	"optional":true,
+     	"description":"This provides a description of the purpose the instance property. The value can be a string or it can be an object with properties corresponding to various different instance languages (with an optional default property indicating the default description)."},
+     "format":{
+     	"type":"string",
+	"optional":true,
+     	"description":"This indicates what format the data is among some predefined formats which may include:\n\ndate - a string following the ISO format \naddress \nschema - a schema definition object \nperson \npage \nhtml - a string representing HTML"},
+     "default":{
+     	"type":"any",
+	"optional":true,
+     	"description":"This indicates the default for the instance property."},
+     "transient":{
+     	"type":"boolean",
+	"optional":true,
+     	"description":"This indicates that the property will be used for transient/volatile values that should not be persisted.",
+	"default":false},
+     "maxDecimal":{
+     	"type":"integer",
+	"optional":true,
+     	"description":"This indicates the maximum number of decimal places in a floating point number."},
+     "hidden":{
+     	"type":"boolean",
+	"optional":true,
+     	"description":"This indicates whether the property should be hidden in user interfaces."},     	
+     "extends":{
+     	"type":"object",
+     	"properties":{"$ref":"$.properties"},
+     	"description":"This indicates the schema extends the given schema. All instances of this schema must be valid to by the extended schema also.",
+	"optional":true,
+	"default":{}},     	
+     "id":{
+     	"type":["string","number"],
+	"optional":true,
+	"format":"url",
+     	"identity":true}
+   }
+};
+ 
+ 
+schemaForSchemas = dojox.json.ref.resolveJson(schemaForSchemas);
+doh.register("dojox.validate.tests.jsonSchema",
+	[{
+		name:"isValidForSchema",
+		runTest: function(t){
+			doh.t(dojox.json.schema.validate(simpleObj).valid); //a simple self-validating test
+			doh.t(dojox.json.schema.validate(biggerObj,biggerSchema).valid); //a bigger instance and schema
+			doh.f(dojox.json.schema.validate(invalidBiggerObj,biggerSchema).valid); //should have two errors
+			doh.t(dojox.json.schema.validate(schemaForSchemas,schemaForSchemas).valid); //test the schema for schemas against it's self. Narcissitic testing
+			doh.t(dojox.json.schema.validate(biggerSchema,schemaForSchemas).valid); //Test the big schema against the schema for schemas
+		}
+	},
+	{
+		name:"isValidPropertyChange", 
+		runTest: function(t){
+			doh.f(dojox.json.schema.checkPropertyChange(biggerObj,biggerSchema).valid); //this should fail because of the 
+			doh.t(dojox.json.schema.checkPropertyChange(schemaForSchemas,schemaForSchemas).valid); //schema should be valid
+		}
+	},
+	function disallow(t){
+		var schema={
+			disallow: [{maxLength:4}]
+		}		
+		doh.t(dojox.json.schema.validate("hello", schema).valid);
+		doh.f(dojox.json.schema.validate("hi", schema).valid);
+	},
+	function maxDecimal(t){
+		var schema={
+			maxDecimal: 4
+		}		
+		doh.t(dojox.json.schema.validate(4.44, schema).valid);
+		doh.f(dojox.json.schema.validate(4.444444, schema).valid);
+		
+	},
+	function tuple(t){
+		var schema={
+			items: [{type:"string"},{type:"number"}]
+		};		
+		doh.t(dojox.json.schema.validate(["hi",33], schema).valid);
+		doh.f(dojox.json.schema.validate([22,22], schema).valid);
+		
+	},
+	function union(t){
+		var schema={
+			type: ["string", "number"]
+		};		
+		doh.t(dojox.json.schema.validate(22, schema).valid);
+		doh.t(dojox.json.schema.validate("hi", schema).valid);
+		doh.f(dojox.json.schema.validate(null, schema).valid);
+		doh.f(dojox.json.schema.validate({foo:"bar"}, schema).valid);
+	},
+	function aLittleComplex(t){
+		var schema = {type:[
+			{type:"object", properties:{name:{type:"string"}, id:{type:"integer"}}, additionalProperties:false}, 
+			{type:"object", properties:{brand:{type:"string"}, id:{type:"integer"}}, additionalProperties:false}]
+		};
+		doh.t(dojox.json.schema.validate({name:"Bill", id:3}, schema).valid);
+		doh.t(dojox.json.schema.validate({brand:"Dojo", id:3}, schema).valid);
+		doh.f(dojox.json.schema.validate({foo:"bar"}, schema).valid);
+		doh.f(dojox.json.schema.validate({foo:"bar", brand:"Dojo", id:3}, schema).valid);
+		doh.f(dojox.json.schema.validate("a string", schema).valid);
+	},
+	function invalidSchema(t){
+		var schema = {
+			properties: { foo:"string"}
+		};
+		doh.f(dojox.json.schema.validate({foo:"bar"}, schema).valid);
+	}
+]);
+
diff --git a/dojox/jsonPath.js b/dojox/jsonPath.js
index 8ee5897..e18b23d 100644
--- a/dojox/jsonPath.js
+++ b/dojox/jsonPath.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.jsonPath"]){
-dojo._hasResource["dojox.jsonPath"]=true;
 dojo.provide("dojox.jsonPath");
 dojo.require("dojox.jsonPath.query");
-}
diff --git a/dojox/jsonPath/query.js b/dojox/jsonPath/query.js
index 4b7a5fa..20a5a3e 100644
--- a/dojox/jsonPath/query.js
+++ b/dojox/jsonPath/query.js
@@ -1,204 +1,159 @@
-/*
-	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
-*/
+dojo.provide("dojox.jsonPath.query");
 
+dojox.jsonPath.query = function(/*Object*/obj, /*String*/expr, /*Object*/arg){
+	// summaRy
+	// 	Perform jsonPath query `expr` on javascript object or json string `obj`
+	//	obj - object || json string to perform query on
+	//	expr - jsonPath expression (string) to be evaluated
+	//	arg - {}special arugments.  
+	//		resultType: "VALUE"||"BOTH"||"PATH"} (defaults to value)
+	//		evalType: "RESULT"||"ITEM"} (defaults to ?)
 
-if(!dojo._hasResource["dojox.jsonPath.query"]){
-dojo._hasResource["dojox.jsonPath.query"]=true;
-dojo.provide("dojox.jsonPath.query");
-dojox.jsonPath.query=function(_1,_2,_3){
-var re=dojox.jsonPath._regularExpressions;
-if(!_3){
-_3={};
-}
-var _4=[];
-function _5(i){
-return _4[i];
-};
-var _6;
-if(_3.resultType=="PATH"&&_3.evalType=="RESULT"){
-throw Error("RESULT based evaluation not supported with PATH based results");
-}
-var P={resultType:_3.resultType||"VALUE",normalize:function(_7){
-var _8=[];
-_7=_7.replace(/'([^']|'')*'/g,function(t){
-return "_str("+(_4.push(eval(t))-1)+")";
-});
-var ll=-1;
-while(ll!=_8.length){
-ll=_8.length;
-_7=_7.replace(/(\??\([^\(\)]*\))/g,function($0){
-return "#"+(_8.push($0)-1);
-});
-}
-_7=_7.replace(/[\['](#[0-9]+)[\]']/g,"[$1]").replace(/'?\.'?|\['?/g,";").replace(/;;;|;;/g,";..;").replace(/;$|'?\]|'$/g,"");
-ll=-1;
-while(ll!=_7){
-ll=_7;
-_7=_7.replace(/#([0-9]+)/g,function($0,$1){
-return _8[$1];
-});
-}
-return _7.split(";");
-},asPaths:function(_9){
-for(var j=0;j<_9.length;j++){
-var p="$";
-var x=_9[j];
-for(var i=1,n=x.length;i<n;i++){
-p+=/^[0-9*]+$/.test(x[i])?("["+x[i]+"]"):("['"+x[i]+"']");
-}
-_9[j]=p;
-}
-return _9;
-},exec:function(_a,_b,rb){
-var _c=["$"];
-var _d=rb?_b:[_b];
-var _e=[_c];
-function _f(v,p,def){
-if(v&&v.hasOwnProperty(p)&&P.resultType!="VALUE"){
-_e.push(_c.concat([p]));
-}
-if(def){
-_d=v[p];
-}else{
-if(v&&v.hasOwnProperty(p)){
-_d.push(v[p]);
-}
-}
-};
-function _10(v){
-_d.push(v);
-_e.push(_c);
-P.walk(v,function(i){
-if(typeof v[i]==="object"){
-var _11=_c;
-_c=_c.concat(i);
-_10(v[i]);
-_c=_11;
-}
-});
-};
-function _12(loc,val){
-if(val instanceof Array){
-var len=val.length,_13=0,end=len,_14=1;
-loc.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g,function($0,$1,$2,$3){
-_13=parseInt($1||_13);
-end=parseInt($2||end);
-_14=parseInt($3||_14);
-});
-_13=(_13<0)?Math.max(0,_13+len):Math.min(len,_13);
-end=(end<0)?Math.max(0,end+len):Math.min(len,end);
-for(var i=_13;i<end;i+=_14){
-_f(val,i);
-}
-}
-};
-function _15(str){
-var i=loc.match(/^_str\(([0-9]+)\)$/);
-return i?_4[i[1]]:str;
-};
-function _16(val){
-if(/^\(.*?\)$/.test(loc)){
-_f(val,P.eval(loc,val),rb);
-}else{
-if(loc==="*"){
-P.walk(val,rb&&val instanceof Array?function(i){
-P.walk(val[i],function(j){
-_f(val[i],j);
-});
-}:function(i){
-_f(val,i);
-});
-}else{
-if(loc===".."){
-_10(val);
-}else{
-if(/,/.test(loc)){
-for(var s=loc.split(/'?,'?/),i=0,n=s.length;i<n;i++){
-_f(val,_15(s[i]));
-}
-}else{
-if(/^\?\(.*?\)$/.test(loc)){
-P.walk(val,function(i){
-if(P.eval(loc.replace(/^\?\((.*?)\)$/,"$1"),val[i])){
-_f(val,i);
-}
-});
-}else{
-if(/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)){
-_12(loc,val);
-}else{
-loc=_15(loc);
-if(rb&&val instanceof Array&&!/^[0-9*]+$/.test(loc)){
-P.walk(val,function(i){
-_f(val[i],loc);
-});
-}else{
-_f(val,loc,rb);
-}
-}
-}
-}
-}
-}
-}
-};
-while(_a.length){
-var loc=_a.shift();
-if((_b=_d)===null||_b===undefined){
-return _b;
-}
-_d=[];
-var _17=_e;
-_e=[];
-if(rb){
-_16(_b);
-}else{
-P.walk(_b,function(i){
-_c=_17[i]||_c;
-_16(_b[i]);
-});
-}
-}
-if(P.resultType=="BOTH"){
-_e=P.asPaths(_e);
-var _18=[];
-for(var i=0;i<_e.length;i++){
-_18.push({path:_e[i],value:_d[i]});
-}
-return _18;
-}
-return P.resultType=="PATH"?P.asPaths(_e):_d;
-},walk:function(val,f){
-if(val instanceof Array){
-for(var i=0,n=val.length;i<n;i++){
-if(i in val){
-f(i);
-}
-}
-}else{
-if(typeof val==="object"){
-for(var m in val){
-if(val.hasOwnProperty(m)){
-f(m);
-}
-}
-}
-}
-},eval:function(x,_19){
-try{
-return $&&_19&&eval(x.replace(/@/g,"_v"));
-}
-catch(e){
-throw new SyntaxError("jsonPath: "+e.message+": "+x.replace(/@/g,"_v").replace(/\^/g,"_a"));
-}
-}};
-var $=_1;
-if(_2&&_1){
-return P.exec(P.normalize(_2).slice(1),_1,_3.evalType=="RESULT");
-}
-return false;
-};
-}
+	var re = dojox.jsonPath._regularExpressions;
+	if (!arg){arg={};}
+
+	var strs = [];
+	function _str(i){ return strs[i];}
+	var acc;
+	if (arg.resultType == "PATH" && arg.evalType == "RESULT") throw Error("RESULT based evaluation not supported with PATH based results");
+	var P = {
+		resultType: arg.resultType || "VALUE",
+		normalize: function(expr){
+			var subx = [];
+			expr = expr.replace(/'([^']|'')*'/g, function(t){return "_str("+(strs.push(eval(t))-1)+")";});
+			var ll = -1;
+			while(ll!=subx.length){
+				ll=subx.length;//TODO: Do expression syntax checking
+				expr = expr.replace(/(\??\([^\(\)]*\))/g, function($0){return "#"+(subx.push($0)-1);});
+			}
+			expr = expr.replace(/[\['](#[0-9]+)[\]']/g,'[$1]')
+						  .replace(/'?\.'?|\['?/g, ";")
+						  .replace(/;;;|;;/g, ";..;")
+						  .replace(/;$|'?\]|'$/g, "");
+			ll = -1;
+			while(ll!=expr){
+				ll=expr;
+					 expr = expr.replace(/#([0-9]+)/g, function($0,$1){return subx[$1];});
+			}
+			return expr.split(";");
+		},
+		asPaths: function(paths){
+			for (var j=0;j<paths.length;j++){
+			var p = "$";
+			var x= paths[j];
+			for (var i=1,n=x.length; i<n; i++)
+				p += /^[0-9*]+$/.test(x[i]) ? ("["+x[i]+"]") : ("['"+x[i]+"']");
+			paths[j]=p;
+		  }
+			return paths;
+		},
+		exec: function(locs, val, rb){
+			var path = ['$'];
+			var result=rb?val:[val];
+			var paths=[path];
+			function add(v, p,def){
+			  if (v && v.hasOwnProperty(p) && P.resultType != "VALUE") paths.push(path.concat([p]));
+				if (def) 
+				  result = v[p];
+			  else if (v && v.hasOwnProperty(p))  
+					result.push(v[p]);
+			}
+			function desc(v){
+				result.push(v);
+				paths.push(path);
+				P.walk(v,function(i){
+					if (typeof v[i] ==='object')  {
+						var oldPath = path;
+						path = path.concat(i);
+						desc(v[i]);
+						path = oldPath;
+					}
+				});
+			}
+			function slice(loc, val){
+				if (val instanceof Array){
+					var len=val.length, start=0, end=len, step=1;
+					loc.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g, function($0,$1,$2,$3){start=parseInt($1||start);end=parseInt($2||end);step=parseInt($3||step);});
+					start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
+					end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);
+				  	for (var i=start; i<end; i+=step)
+						add(val,i);
+				}
+			}
+			function repStr(str){
+				var i=loc.match(/^_str\(([0-9]+)\)$/);
+				return i?strs[i[1]]:str;
+			}
+			function oper(val){
+				if (/^\(.*?\)$/.test(loc)) // [(expr)]
+					add(val, P.eval(loc, val),rb);
+				else if (loc === "*"){
+					P.walk(val, rb && val instanceof Array ? // if it is result based, there is no point to just return the same array
+					function(i){P.walk(val[i],function(j){ add(val[i],j); })} :
+					function(i){ add(val,i); });
+				}
+				else if (loc === "..") 
+					desc(val);
+				else if (/,/.test(loc)){ // [name1,name2,...]
+					for (var s=loc.split(/'?,'?/),i=0,n=s.length; i<n; i++)
+						add(val,repStr(s[i])); 
+				}
+				else if (/^\?\(.*?\)$/.test(loc)) // [?(expr)]
+					P.walk(val, function(i){ if (P.eval(loc.replace(/^\?\((.*?)\)$/,"$1"),val[i])) add(val,i); });
+				else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) // [start:end:step]  python slice syntax
+					slice(loc, val);
+				else {
+					loc=repStr(loc);
+					if (rb && val instanceof Array && !/^[0-9*]+$/.test(loc)) 
+						P.walk(val, function(i){ add(val[i], loc)});
+					else 
+						add(val,loc,rb);		
+				}
+
+			}
+			while (locs.length){
+				var loc = locs.shift();
+				if ((val = result) === null || val===undefined) return val;
+				result = [];
+				var valPaths = paths;
+				paths = [];
+				if (rb) 
+					oper(val)
+				else
+					P.walk(val,function(i){path=valPaths[i]||path;oper(val[i])});
+			}
+			if (P.resultType == "BOTH"){
+				paths = P.asPaths(paths);
+				var newResult = [];
+				for (var i =0;i <paths.length;i++)
+					newResult.push({path:paths[i],value:result[i]});
+				return newResult;
+			}
+			return P.resultType == "PATH" ? P.asPaths(paths):result;
+		},
+		walk: function(val, f){
+			if (val instanceof Array){
+				for (var i=0,n=val.length; i<n; i++)
+					if (i in val)
+						f(i);
+			}
+			else if (typeof val === "object"){
+				for (var m in val)
+					if (val.hasOwnProperty(m))
+						f(m);
+			}
+		},
+		eval: function(x, _v){
+			try { return $ && _v && eval(x.replace(/@/g,'_v')); }
+			catch(e){ throw new SyntaxError("jsonPath: " + e.message + ": " + x.replace(/@/g, "_v").replace(/\^/g, "_a")); }
+		}
+	};
+
+	var $ = obj;
+	if (expr && obj){
+		return P.exec(P.normalize(expr).slice(1), obj, arg.evalType == "RESULT");
+	}	
+
+	return false;
+
+}; 
diff --git a/dojox/jsonPath/tests/jsonPath.js b/dojox/jsonPath/tests/jsonPath.js
new file mode 100644
index 0000000..0bd60d6
--- /dev/null
+++ b/dojox/jsonPath/tests/jsonPath.js
@@ -0,0 +1,206 @@
+dojo.provide("dojox.jsonPath.tests.jsonPath");
+dojo.require("dojox.jsonPath");
+
+
+dojox.jsonPath.tests.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	d.errback(errData);	
+}
+
+dojox.jsonPath.tests.testData= {
+	store: {
+		"book": [ 
+			{ 
+				"category":"reference",
+				"author":"Nigel Rees",
+				"title":"Sayings of the Century",
+				"price":8.95
+			},
+			{ 
+				"category":"fiction",
+				"author":"Evelyn Waugh",
+				"title":"Sword of Honour",
+				"price":12.99
+			},
+			{ 
+				"category":"fiction",
+				"author":"Herman Melville",
+				"title":"Moby Dick",
+				"isbn":"0-553-21311-3",
+				"price":8.99
+			},
+			{ 
+				"category":"fiction",
+				"author":"J. R. R. Tolkien",
+				"title":"The Lord of the Rings",
+				"isbn":"0-395-19395-8",
+				"price":22.99
+			}
+		],
+		"bicycle": {
+				"color":"red",
+				"price":19.95
+		}
+	},
+	"symbols":{"@.$;":5}
+}
+
+doh.register("dojox.jsonPath.tests.jsonPath", 
+	[
+		{
+			name: "$.store.book[*].author",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success =  '["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..author",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success =  '["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]';
+				doh.assertEqual(success,result);
+		
+			}
+		},
+		{
+			name: "$.store.*",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success = '[[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],{"color":"red","price":19.95}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.store..price",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success = '[8.95,12.99,8.99,22.99,19.95]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[(@.length-1)]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success =  '[{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[-1:]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success =  '[{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[0,1]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success =  '[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[:2]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success =  '[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[?(@.isbn)]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success =  '[{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$..book[?(@.price<10)]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success =  '[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.symbols[*]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success =  '[5]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.symbols['@.$;']",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success =  '[5]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "$.symbols[(@[('@.$;')]?'@.$;':'@.$;')]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, this.name));
+				var success =  '[5]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "resultType: 'BOTH' test",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, "$..book[*]",{resultType:"BOTH"}));
+				var success =  dojo.toJson([{"path": "$['store']['book'][0]", "value": {"category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95}}, {"path": "$['store']['book'][1]", "value": {"category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99}}, {"path": "$['store']['book'][2]", "value": {"category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99}}, {"path": "$['sto [...]
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "evalType: 'RESULT' test $.store.book[?(@.price<15)][1:3]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, "$.store.book[?(@.price<15)][1:3]",{evalType:"RESULT"}));
+				var success = '[{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "evalType: 'RESULT' test $.store.book[1].category",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, "$.store.book[1].category",{evalType:"RESULT"}));
+				var success = '"fiction"';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "evalType: 'RESULT' test $.store.bicycle",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, "$.store.bicycle",{evalType:"RESULT"}));
+				var success = '{"color":"red","price":19.95}';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "evalType: 'RESULT' test $.store.book[*]",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, "$.store.book[*]",{evalType:"RESULT"}));
+				var success = '["reference","Nigel Rees","Sayings of the Century",8.95,"fiction","Evelyn Waugh","Sword of Honour",12.99,"fiction","Herman Melville","Moby Dick","0-553-21311-3",8.99,"fiction","J. R. R. Tolkien","The Lord of the Rings","0-395-19395-8",22.99]';
+				doh.assertEqual(success,result);
+			}
+		},
+		{
+			name: "evalType: 'RESULT' test $.store.book.category",
+			runTest: function(t) {
+				var result = dojo.toJson(dojox.jsonPath.query(dojox.jsonPath.tests.testData, "$.store.book.category",{evalType:"RESULT"}));
+				var success = '["reference","fiction","fiction","fiction"]';
+				doh.assertEqual(success,result);
+			}
+		}
+	]
+);
+
diff --git a/dojox/jsonPath/tests/module.js b/dojox/jsonPath/tests/module.js
new file mode 100644
index 0000000..2cb4140
--- /dev/null
+++ b/dojox/jsonPath/tests/module.js
@@ -0,0 +1,8 @@
+dojo.provide("dojox.jsonPath.tests.module");
+
+try{
+	dojo.require("dojox.jsonPath.tests.jsonPath");
+}catch(e){
+	doh.debug(e);
+}
+
diff --git a/dojox/jsonPath/tests/runTests.html b/dojox/jsonPath/tests/runTests.html
new file mode 100644
index 0000000..60a1167
--- /dev/null
+++ b/dojox/jsonPath/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.jsonPath.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/lang/README b/dojox/lang/README
index a52cd4d..1967de4 100644
--- a/dojox/lang/README
+++ b/dojox/lang/README
@@ -13,8 +13,15 @@ Credits
 -------------------------------------------------------------------------------
 Project description
 
-Implementation of common functional operations, and provisions, aspect-oriented
-helpers. Later we can add other JS language-related helpers.
+dojox.lang.functional - Provides lambda functions, and common functional
+operations.
+
+dojox.lang.aspect - Provides a framework for aspect-oriented programming.
+
+dojox.lang.oo - Provides mixers to support traits and mixins for object-oriented
+programming.
+
+dojox.lang.async - Provides helpers for event-driven programming.
 
 dojox.lang.observable - Provides construction of objects that such that 
 property access and modification can be controlled, i.e. provides a form of
@@ -40,6 +47,10 @@ For now:
 
 dojox.lang.functional:
 http://lazutkin.com/blog/2008/jan/12/functional-fun-javascript-dojo/
+http://lazutkin.com/blog/2008/jun/30/using-recursion-combinators-javascript/
+
+dojox.lang.aspect:
+http://lazutkin.com/blog/2008/may/18/aop-aspect-javascript-dojo/
 
 -------------------------------------------------------------------------------
 Installation instructions
diff --git a/dojox/lang/aspect.js b/dojox/lang/aspect.js
index 4c3f601..09dbfc4 100644
--- a/dojox/lang/aspect.js
+++ b/dojox/lang/aspect.js
@@ -1,212 +1,367 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.aspect"]){
-dojo._hasResource["dojox.lang.aspect"]=true;
 dojo.provide("dojox.lang.aspect");
+
 (function(){
-var d=dojo,_1=dojox.lang.aspect,ap=Array.prototype,_2=[],_3;
-var _4=function(){
-this.next_before=this.prev_before=this.next_around=this.prev_around=this.next_afterReturning=this.prev_afterReturning=this.next_afterThrowing=this.prev_afterThrowing=this;
-this.counter=0;
-};
-d.extend(_4,{add:function(_5){
-var _6=d.isFunction(_5),_7={advice:_5,dynamic:_6};
-this._add(_7,"before","",_6,_5);
-this._add(_7,"around","",_6,_5);
-this._add(_7,"after","Returning",_6,_5);
-this._add(_7,"after","Throwing",_6,_5);
-++this.counter;
-return _7;
-},_add:function(_8,_9,_a,_b,_c){
-var _d=_9+_a;
-if(_b||_c[_9]||(_a&&_c[_d])){
-var _e="next_"+_d,_f="prev_"+_d;
-(_8[_f]=this[_f])[_e]=_8;
-(_8[_e]=this)[_f]=_8;
-}
-},remove:function(_10){
-this._remove(_10,"before");
-this._remove(_10,"around");
-this._remove(_10,"afterReturning");
-this._remove(_10,"afterThrowing");
---this.counter;
-},_remove:function(_11,_12){
-var _13="next_"+_12,_14="prev_"+_12;
-if(_11[_13]){
-_11[_13][_14]=_11[_14];
-_11[_14][_13]=_11[_13];
-}
-},isEmpty:function(){
-return !this.counter;
-}});
-var _15=function(){
-return function(){
-var _16=arguments.callee,_17=_16.advices,ret,i,a,e,t;
-if(_3){
-_2.push(_3);
-}
-_3={instance:this,joinPoint:_16,depth:_2.length,around:_17.prev_around,dynAdvices:[],dynIndex:0};
-try{
-for(i=_17.prev_before;i!=_17;i=i.prev_before){
-if(i.dynamic){
-_3.dynAdvices.push(a=new i.advice(_3));
-if(t=a.before){
-t.apply(a,arguments);
-}
-}else{
-t=i.advice;
-t.before.apply(t,arguments);
-}
-}
-try{
-ret=(_17.prev_around==_17?_16.target:_1.proceed).apply(this,arguments);
-}
-catch(e){
-_3.dynIndex=_3.dynAdvices.length;
-for(i=_17.next_afterThrowing;i!=_17;i=i.next_afterThrowing){
-a=i.dynamic?_3.dynAdvices[--_3.dynIndex]:i.advice;
-if(t=a.afterThrowing){
-t.call(a,e);
-}
-if(t=a.after){
-t.call(a);
-}
-}
-throw e;
-}
-_3.dynIndex=_3.dynAdvices.length;
-for(i=_17.next_afterReturning;i!=_17;i=i.next_afterReturning){
-a=i.dynamic?_3.dynAdvices[--_3.dynIndex]:i.advice;
-if(t=a.afterReturning){
-t.call(a,ret);
-}
-if(t=a.after){
-t.call(a);
-}
-}
-var ls=_16._listeners;
-for(i in ls){
-if(!(i in ap)){
-ls[i].apply(this,arguments);
-}
-}
-}
-finally{
-for(i=0;i<_3.dynAdvices.length;++i){
-a=_3.dynAdvices[i];
-if(a.destroy){
-a.destroy();
-}
-}
-_3=_2.length?_2.pop():null;
-}
-return ret;
-};
-};
-_1.advise=function(obj,_18,_19){
-if(typeof obj!="object"){
-obj=obj.prototype;
-}
-var _1a=[];
-if(!(_18 instanceof Array)){
-_18=[_18];
-}
-for(var j=0;j<_18.length;++j){
-var t=_18[j];
-if(t instanceof RegExp){
-for(var i in obj){
-if(d.isFunction(obj[i])&&t.test(i)){
-_1a.push(i);
-}
-}
-}else{
-if(d.isFunction(obj[t])){
-_1a.push(t);
-}
-}
-}
-if(!d.isArray(_19)){
-_19=[_19];
-}
-return _1.adviseRaw(obj,_1a,_19);
-};
-_1.adviseRaw=function(obj,_1b,_1c){
-if(!_1b.length||!_1c.length){
-return null;
-}
-var m={},al=_1c.length;
-for(var i=_1b.length-1;i>=0;--i){
-var _1d=_1b[i],o=obj[_1d],ao=new Array(al),t=o.advices;
-if(!t){
-var x=obj[_1d]=_15();
-x.target=o.target||o;
-x.targetName=_1d;
-x._listeners=o._listeners||[];
-x.advices=new _4;
-t=x.advices;
-}
-for(var j=0;j<al;++j){
-ao[j]=t.add(_1c[j]);
-}
-m[_1d]=ao;
-}
-return [obj,m];
-};
-_1.unadvise=function(_1e){
-if(!_1e){
-return;
-}
-var obj=_1e[0],_1f=_1e[1];
-for(var _20 in _1f){
-var o=obj[_20],t=o.advices,ao=_1f[_20];
-for(var i=ao.length-1;i>=0;--i){
-t.remove(ao[i]);
-}
-if(t.isEmpty()){
-var _21=true,ls=o._listeners;
-if(ls.length){
-for(i in ls){
-if(!(i in ap)){
-_21=false;
-break;
-}
-}
-}
-if(_21){
-obj[_20]=o.target;
-}else{
-var x=obj[_20]=d._listener.getDispatcher();
-x.target=o.target;
-x._listeners=ls;
-}
-}
-}
-};
-_1.getContext=function(){
-return _3;
+	var d = dojo, aop = dojox.lang.aspect, ap = Array.prototype,
+		contextStack = [], context;
+		
+	// this class implements a topic-based double-linked list
+	var Advice = function(){
+		this.next_before = this.prev_before =
+		this.next_around = this.prev_around =
+		this.next_afterReturning = this.prev_afterReturning =
+		this.next_afterThrowing = this.prev_afterThrowing =
+			this;
+		this.counter = 0;
+	};
+	d.extend(Advice, {
+		add: function(advice){
+			var dyn = d.isFunction(advice),
+				node = {advice: advice, dynamic: dyn};
+			this._add(node, "before", "", dyn, advice);
+			this._add(node, "around", "", dyn, advice);
+			this._add(node, "after", "Returning", dyn, advice);
+			this._add(node, "after", "Throwing", dyn, advice);
+			++this.counter;
+			return node;
+		},
+		_add: function(node, topic, subtopic, dyn, advice){
+			var full = topic + subtopic;
+			if(dyn || advice[topic] || (subtopic && advice[full])){
+				var next = "next_" + full, prev = "prev_" + full;
+				(node[prev] = this[prev])[next] = node;
+				(node[next] = this)[prev] = node;
+			}
+		},
+		remove: function(node){
+			this._remove(node, "before");
+			this._remove(node, "around");
+			this._remove(node, "afterReturning");
+			this._remove(node, "afterThrowing");
+			--this.counter;
+		},
+		_remove: function(node, topic){
+			var next = "next_" + topic, prev = "prev_" + topic;
+			if(node[next]){
+				node[next][prev] = node[prev];
+				node[prev][next] = node[next];
+			}
+		},
+		isEmpty: function(){
+			return !this.counter;
+		}
+	});
+
+	var getDispatcher = function(){
+	
+		return function(){
+			
+			var self = arguments.callee,	// the join point
+				advices = self.advices,		// list of advices for this joinpoint
+				ret, i, a, e, t;
+
+			// push context
+			if(context){ contextStack.push(context); }
+			context = {
+				instance: this,					// object instance
+				joinPoint: self,				// join point
+				depth: contextStack.length,		// current level of depth starting from 0
+				around: advices.prev_around,	// pointer to the current around advice
+				dynAdvices: [],					// array of dynamic advices if any
+				dynIndex: 0						// index of a dynamic advice
+			};
+
+			try{
+				// process before events
+				for(i = advices.prev_before; i != advices; i = i.prev_before){
+					if(i.dynamic){
+						// instantiate a dynamic advice
+						context.dynAdvices.push(a = new i.advice(context));
+						if(t = a.before){ // intentional assignment
+							t.apply(a, arguments);
+						}
+					}else{
+						t = i.advice;
+						t.before.apply(t, arguments);
+					}
+				}
+
+				// process around and after events
+				try{
+					// call the around advice or the original method
+					ret = (advices.prev_around == advices ? self.target : aop.proceed).apply(this, arguments);
+				}catch(e){
+					// process after throwing and after events
+					context.dynIndex = context.dynAdvices.length;
+					for(i = advices.next_afterThrowing; i != advices; i = i.next_afterThrowing){
+						a = i.dynamic ? context.dynAdvices[--context.dynIndex] : i.advice;
+						if(t = a.afterThrowing){ // intentional assignment
+							t.call(a, e);
+						}
+						if(t = a.after){ // intentional assignment
+							t.call(a);
+						}
+					}
+					// continue the exception processing
+					throw e;
+				}
+				// process after returning and after events
+				context.dynIndex = context.dynAdvices.length;
+				for(i = advices.next_afterReturning; i != advices; i = i.next_afterReturning){
+					a = i.dynamic ? context.dynAdvices[--context.dynIndex] : i.advice;
+					if(t = a.afterReturning){ // intentional assignment
+						t.call(a, ret);
+					}
+					if(t = a.after){ // intentional assignment
+						t.call(a);
+					}
+				}
+				// process dojo.connect() listeners
+				var ls = self._listeners;
+				for(i in ls){
+					if(!(i in ap)){
+						ls[i].apply(this, arguments);
+					}
+				}
+			}finally{
+				// destroy dynamic advices
+				for(i = 0; i < context.dynAdvices.length; ++i){
+					a = context.dynAdvices[i];
+					if(a.destroy){
+						a.destroy();
+					}
+				}
+				// pop context
+				context = contextStack.length ? contextStack.pop() : null;
+			}
+			
+			return ret;
+		};
+	};
+
+	aop.advise = function(/*Object*/ obj,
+						/*String|RegExp|Array*/ method,
+						/*Object|Function|Array*/ advice
+						){
+		// summary:
+		//		Attach AOP-style advices to a method.
+		//
+		// description:
+		//		Attaches AOP-style advices to a method. Can attach several
+		//		advices at once and operate on several methods of an object.
+		//		The latter is achieved when a RegExp is specified as
+		//		a method name, or an array of strings and regular expressions
+		//		is used. In this case all functional methods that
+		//		satisfy the RegExp condition are processed. This function
+		//		returns a handle, which can be used to unadvise, or null,
+		//		if advising has failed.
+		//		
+		//		This function is a convenience wrapper for
+		//		dojox.lang.aspect.adviseRaw().
+		//
+		// obj:
+		//		A source object for the advised function. Cannot be a DOM node.
+		//		If this object is a constructor, its prototype is advised.
+		//
+		// method:
+		//		A string name of the function in obj. In case of RegExp all
+		//		methods of obj matching the regular expression are advised.
+		//
+		// advice:
+		//		An object, which defines advises, or a function, which
+		//		returns such object, or an array of previous items.
+		//		The advice object can define following member functions:
+		//		before, around, afterReturning, afterThrowing, after.
+		//		If the function is supplied, it is called with a context
+		//		object once per call to create a temporary advice object, which
+		//		is destroyed after the processing. The temporary advice object
+		//		can implement a destroy() method, if it wants to be called when
+		//		not needed.
+		
+		if(typeof obj != "object"){
+			obj = obj.prototype;
+		}
+
+		var methods = [];
+		if(!(method instanceof Array)){
+			method = [method];
+		}
+		
+		// identify advised methods
+		for(var j = 0; j < method.length; ++j){
+			var t = method[j];
+			if(t instanceof RegExp){
+				for(var i in obj){
+					if(d.isFunction(obj[i]) && t.test(i)){
+						methods.push(i);
+					}
+				}
+			}else{
+				if(d.isFunction(obj[t])){
+					methods.push(t);
+				}
+			}
+		}
+
+		if(!d.isArray(advice)){ advice = [advice]; }
+
+		return aop.adviseRaw(obj, methods, advice);	// Object
+	};
+	
+	aop.adviseRaw = function(/*Object*/ obj,
+						/*Array*/ methods,
+						/*Array*/ advices
+						){
+		// summary:
+		//		Attach AOP-style advices to methods.
+		//
+		// description:
+		//		Attaches AOP-style advices to object's methods. Can attach several
+		//		advices at once and operate on several methods of the object.
+		//		The latter is achieved when a RegExp is specified as
+		//		a method name. In this case all functional methods that
+		//		satisfy the RegExp condition are processed. This function
+		//		returns a handle, which can be used to unadvise, or null,
+		//		if advising has failed.
+		//
+		// obj:
+		//		A source object for the advised function.
+		//		Cannot be a DOM node.
+		//
+		// methods:
+		//		An array of method names (strings) to be advised.
+		//
+		// advices:
+		//		An array of advices represented by objects or functions that
+		//		return such objects on demand during the event processing.
+		//		The advice object can define following member functions:
+		//		before, around, afterReturning, afterThrowing, after.
+		//		If the function is supplied, it is called with a context
+		//		object once per call to create a temporary advice object, which
+		//		is destroyed after the processing. The temporary advice object
+		//		can implement a destroy() method, if it wants to be called when
+		//		not needed.
+
+		if(!methods.length || !advices.length){ return null; }
+		
+		// attach advices
+		var m = {}, al = advices.length;
+		for(var i = methods.length - 1; i >= 0; --i){
+			var name = methods[i], o = obj[name], ao = new Array(al), t = o.advices;
+			// create a stub, if needed
+			if(!t){
+				var x = obj[name] = getDispatcher();
+				x.target = o.target || o;
+				x.targetName = name;
+				x._listeners = o._listeners || [];
+				x.advices = new Advice;
+				t = x.advices;
+			}
+			// attach advices
+			for(var j = 0; j < al; ++j){
+				ao[j] = t.add(advices[j]);
+			}
+			m[name] = ao;
+		}
+		
+		return [obj, m];	// Object
+	};
+
+	aop.unadvise = function(/*Object*/ handle){
+		// summary:
+		//		Detach previously attached AOP-style advices.
+		//
+		// handle:
+		//		The object returned by dojox.lang.aspect.advise().
+		
+		if(!handle){ return; }
+		var obj = handle[0], methods = handle[1];
+		for(var name in methods){
+			var o = obj[name], t = o.advices, ao = methods[name];
+			for(var i = ao.length - 1; i >= 0; --i){
+				t.remove(ao[i]);
+			}
+			if(t.isEmpty()){
+				// check if we can remove all stubs
+				var empty = true, ls = o._listeners;
+				if(ls.length){
+					for(i in ls){
+						if(!(i in ap)){
+							empty = false;
+							break;
+						}
+					}
+				}
+				if(empty){
+					// revert to the original method
+					obj[name] = o.target;
+				}else{
+					// replace with the dojo.connect() stub
+					var x = obj[name] = d._listener.getDispatcher();
+					x.target = o.target;
+					x._listeners = ls;
+				}
+			}
+		}
+	};
+	
+	aop.getContext = function(){
+		// summary:
+		//		Returns the context information for the advice in effect.
+		
+		return context;	// Object
+	};
+	
+	aop.getContextStack = function(){
+		// summary:
+		//		Returns the context stack, which reflects executing advices
+		//		up to this point. The array is ordered from oldest to newest.
+		//		In order to get the active context use dojox.lang.aspect.getContext().
+		
+		return contextStack;	// Array
+	};
+	
+	aop.proceed = function(){
+		// summary:
+		//		Call the original function (or the next level around advice) in an around advice code.
+		//
+		// description:
+		//		Calls the original function (or the next level around advice).
+		//		Accepts and passes on any number of arguments, and returns a value.
+		//		This function is valid only in the content of around calls.
+		
+		var joinPoint = context.joinPoint, advices = joinPoint.advices;
+		for(var c = context.around; c != advices; c = context.around){
+			context.around = c.prev_around;	// advance the pointer
+			if(c.dynamic){
+				var a = context.dynAdvices[context.dynIndex++], t = a.around;
+				if(t){
+					return t.apply(a, arguments);
+				}
+			}else{
+				return c.advice.around.apply(c.advice, arguments);
+			}
+		}
+		return joinPoint.target.apply(context.instance, arguments);
+	};
+})();
+
+/*
+Aspect = {
+	before: function(arguments){...},
+	around: function(arguments){...returns value...},
+	afterReturning: function(ret){...},
+	afterThrowing: function(excp){...},
+	after: function(){...}
 };
-_1.getContextStack=function(){
-return _2;
+
+Context = {
+	instance:  ..., // the instance we operate on
+	joinPoint: ...,	// Object (see below)
+	depth:     ...	// current depth of the context stack
 };
-_1.proceed=function(){
-var _22=_3.joinPoint,_23=_22.advices;
-for(var c=_3.around;c!=_23;c=_3.around){
-_3.around=c.prev_around;
-if(c.dynamic){
-var a=_3.dynAdvices[_3.dynIndex++],t=a.around;
-if(t){
-return t.apply(a,arguments);
-}
-}else{
-return c.advice.around.apply(c.advice,arguments);
-}
-}
-return _22.target.apply(_3.instance,arguments);
+
+JoinPoint = {
+	target:     ...,	// the original function being wrapped
+	targetName: ...		// name of the method
 };
-})();
-}
+*/
diff --git a/dojox/lang/aspect/cflow.js b/dojox/lang/aspect/cflow.js
index 27917bd..2da0284 100644
--- a/dojox/lang/aspect/cflow.js
+++ b/dojox/lang/aspect/cflow.js
@@ -1,43 +1,43 @@
-/*
-	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
-*/
+dojo.provide("dojox.lang.aspect.cflow");
 
 
-if(!dojo._hasResource["dojox.lang.aspect.cflow"]){
-dojo._hasResource["dojox.lang.aspect.cflow"]=true;
-dojo.provide("dojox.lang.aspect.cflow");
 (function(){
-var _1=dojox.lang.aspect;
-_1.cflow=function(_2,_3){
-if(arguments.length>1&&!(_3 instanceof Array)){
-_3=[_3];
-}
-var _4=_1.getContextStack();
-for(var i=_4.length-1;i>=0;--i){
-var c=_4[i];
-if(_2&&c.instance!=_2){
-continue;
-}
-if(!_3){
-return true;
-}
-var n=c.joinPoint.targetName;
-for(var j=_3.length-1;j>=0;--j){
-var m=_3[j];
-if(m instanceof RegExp){
-if(m.test(n)){
-return true;
-}
-}else{
-if(n==m){
-return true;
-}
-}
-}
-}
-return false;
-};
-})();
-}
+	var aop = dojox.lang.aspect;
+	
+	aop.cflow = function(/*Object*/ instance, /*String|RegExp|Array?*/ method){
+		// summary:
+		//		Returns true if the context stack contains a context for a given
+		//		instance that satisfies a given method name criteria.
+		//
+		// instance:
+		//		An instance to be matched. If null, any context will be examined.
+		//		Otherwise the context should belong to this instance.
+		//
+		// method:
+		//		An optional pattern to be matched against a method name. Can be a string,
+		//		a RegExp object or an array of strings and RegExp objects.
+		//		If it is omitted, any name will satisfy the criteria.
+	
+		if(arguments.length > 1 && !(method instanceof Array)){
+			method = [method];
+		}
+	
+		var contextStack = aop.getContextStack();
+		for(var i = contextStack.length - 1; i >= 0; --i){
+			var c = contextStack[i];
+			// check if instance matches
+			if(instance && c.instance != instance){ continue; }
+			if(!method){ return true; }
+			var n = c.joinPoint.targetName;
+			for(var j = method.length - 1; j >= 0; --j){
+				var m = method[j];
+				if(m instanceof RegExp){
+					if(m.test(n)){ return true; }
+				}else{
+					if(n == m){ return true; }
+				}
+			}
+		}
+		return false;	// Boolean
+	};
+})();
\ No newline at end of file
diff --git a/dojox/lang/aspect/counter.js b/dojox/lang/aspect/counter.js
index d2e0ad9..ddc81ed 100644
--- a/dojox/lang/aspect/counter.js
+++ b/dojox/lang/aspect/counter.js
@@ -1,27 +1,27 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.aspect.counter"]){
-dojo._hasResource["dojox.lang.aspect.counter"]=true;
 dojo.provide("dojox.lang.aspect.counter");
+
 (function(){
-var _1=dojox.lang.aspect;
-var _2=function(){
-this.reset();
-};
-dojo.extend(_2,{before:function(){
-++this.calls;
-},afterThrowing:function(){
-++this.errors;
-},reset:function(){
-this.calls=this.errors=0;
-}});
-_1.counter=function(){
-return new _2;
-};
-})();
-}
+	var aop = dojox.lang.aspect;
+	
+	var Counter = function(){
+		this.reset();
+	};
+	dojo.extend(Counter, {
+		before: function(/*arguments*/){
+			++this.calls;
+		},
+		afterThrowing: function(/*excp*/){
+			++this.errors;
+		},
+		reset: function(){
+			this.calls = this.errors = 0;
+		}
+	});
+	
+	aop.counter = function(){
+		// summary:
+		//		Returns an object, which can be used to count calls to methods.
+	
+		return new Counter;	// Object
+	};
+})();
\ No newline at end of file
diff --git a/dojox/lang/aspect/memoizer.js b/dojox/lang/aspect/memoizer.js
index 3fc72c1..17bceb6 100644
--- a/dojox/lang/aspect/memoizer.js
+++ b/dojox/lang/aspect/memoizer.js
@@ -1,47 +1,45 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.aspect.memoizer"]){
-dojo._hasResource["dojox.lang.aspect.memoizer"]=true;
 dojo.provide("dojox.lang.aspect.memoizer");
+
 (function(){
-var _1=dojox.lang.aspect;
-var _2={around:function(_3){
-var _4=_1.getContext(),_5=_4.joinPoint,_6=_4.instance,t,u,_7;
-if((t=_6.__memoizerCache)&&(t=t[_5.targetName])&&(_3 in t)){
-return t[_3];
-}
-var _7=_1.proceed.apply(null,arguments);
-if(!(t=_6.__memoizerCache)){
-t=_6.__memoizerCache={};
-}
-if(!(u=t[_5.targetName])){
-u=t[_5.targetName]={};
-}
-return u[_3]=_7;
-}};
-var _8=function(_9){
-return {around:function(){
-var _a=_1.getContext(),_b=_a.joinPoint,_c=_a.instance,t,u,_d,_e=_9.apply(_c,arguments);
-if((t=_c.__memoizerCache)&&(t=t[_b.targetName])&&(_e in t)){
-return t[_e];
-}
-var _d=_1.proceed.apply(null,arguments);
-if(!(t=_c.__memoizerCache)){
-t=_c.__memoizerCache={};
-}
-if(!(u=t[_b.targetName])){
-u=t[_b.targetName]={};
-}
-return u[_e]=_d;
-}};
-};
-_1.memoizer=function(_f){
-return arguments.length==0?_2:_8(_f);
-};
-})();
-}
+	var aop = dojox.lang.aspect;
+
+	var memoize1 = {
+		around: function(key){
+			var ctx = aop.getContext(), self = ctx.joinPoint, that = ctx.instance, t, u, ret;
+			if((t = that.__memoizerCache) && (t = t[self.targetName]) && (key in t)){
+				return t[key];
+			}
+			var ret = aop.proceed.apply(null, arguments);
+			if(!(t = that.__memoizerCache)){ t = that.__memoizerCache = {}; }
+			if(!(u = t[self.targetName])){ u = t[self.targetName] = {}; }
+			return u[key] = ret;
+		}
+	};
+
+	var memoizeN = function(/*Function*/keyMaker){
+		return {
+			around: function(/*arguments*/){
+				var ctx = aop.getContext(), self = ctx.joinPoint, that = ctx.instance, t, u, ret,
+					key  = keyMaker.apply(that, arguments);
+				if((t = that.__memoizerCache) && (t = t[self.targetName]) && (key in t)){
+					return t[key];
+				}
+				var ret = aop.proceed.apply(null, arguments);
+				if(!(t = that.__memoizerCache)){ t = that.__memoizerCache = {}; }
+				if(!(u = t[self.targetName])){ u = t[self.targetName] = {}; }
+				return u[key] = ret;
+			}
+		};
+	};
+
+	aop.memoizer = function(/*Function?*/ keyMaker){
+		// summary:
+		//		Returns an object, which can be used to count calls to methods.
+		//
+		// keyMaker:
+		//		the function, which takes method's arguments and returns a key,
+		//		which can be used to index the result.
+
+		return arguments.length == 0 ? memoize1 : memoizeN(keyMaker);	// Object
+	};
+})();
\ No newline at end of file
diff --git a/dojox/lang/aspect/memoizerGuard.js b/dojox/lang/aspect/memoizerGuard.js
index 5cededc..0795583 100644
--- a/dojox/lang/aspect/memoizerGuard.js
+++ b/dojox/lang/aspect/memoizerGuard.js
@@ -1,35 +1,33 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.aspect.memoizerGuard"]){
-dojo._hasResource["dojox.lang.aspect.memoizerGuard"]=true;
 dojo.provide("dojox.lang.aspect.memoizerGuard");
+
 (function(){
-var _1=dojox.lang.aspect,_2=function(_3){
-var _4=_1.getContext().instance,t;
-if(!(t=_4.__memoizerCache)){
-return;
-}
-if(arguments.length==0){
-delete _4.__memoizerCache;
-}else{
-if(dojo.isArray(_3)){
-dojo.forEach(_3,function(m){
-delete t[m];
-});
-}else{
-delete t[_3];
-}
-}
-};
-_1.memoizerGuard=function(_5){
-return {after:function(){
-_2(_5);
-}};
-};
-})();
-}
+	var aop = dojox.lang.aspect,
+		reset = function(/*String|Array?*/ method){
+			var that = aop.getContext().instance, t;
+			if(!(t = that.__memoizerCache)){ return; }
+			if(arguments.length == 0){
+				delete that.__memoizerCache;
+			}else if(dojo.isArray(method)){
+				dojo.forEach(method, function(m){ delete t[m]; });
+			}else{
+				delete t[method];
+			}
+		};
+
+
+	aop.memoizerGuard = function(/*String|Array?*/ method){
+		// summary:
+		//		Invalidates the memoizer's cache (see dojox.lang.aspect.memoizer)
+		//		after calling certain methods.
+		//
+		// method:
+		//		Optional method's name to be guarded: only cache for
+		//		this method will be invalidated on call. Can be a string
+		//		or an array of method names. If omitted the whole cache
+		//		will be invalidated.
+
+		return {	// Object
+			after: function(){ reset(method); }
+		};
+	};
+})();
\ No newline at end of file
diff --git a/dojox/lang/aspect/profiler.js b/dojox/lang/aspect/profiler.js
index 11f68bf..28fd272 100644
--- a/dojox/lang/aspect/profiler.js
+++ b/dojox/lang/aspect/profiler.js
@@ -1,29 +1,33 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.aspect.profiler"]){
-dojo._hasResource["dojox.lang.aspect.profiler"]=true;
 dojo.provide("dojox.lang.aspect.profiler");
+
 (function(){
-var _1=dojox.lang.aspect,_2=0;
-var _3=function(_4){
-this.args=_4?[_4]:[];
-this.inCall=0;
-};
-dojo.extend(_3,{before:function(){
-if(!(this.inCall++)){
-console.profile.apply(console,this.args);
-}
-},after:function(){
-if(!--this.inCall){
-}
-}});
-_1.profiler=function(_5){
-return new _3(_5);
-};
-})();
-}
+	var aop = dojox.lang.aspect,
+		uniqueNumber = 0;
+	
+	var Profiler = function(title){
+		this.args = title ? [title] : [];
+		this.inCall = 0;
+	};
+	dojo.extend(Profiler, {
+		before: function(/*arguments*/){
+			if(!(this.inCall++)){
+				console.profile.apply(console, this.args);
+			}
+		},
+		after: function(/*excp*/){
+			if(!--this.inCall){
+				console.profileEnd();
+			}
+		}
+	});
+	
+	aop.profiler = function(/*String?*/ title){
+		// summary:
+		//		Returns an object, which can be used to time calls to methods.
+		//
+		// title:
+		//		The optional name of the profile section.
+	
+		return new Profiler(title);	// Object
+	};
+})();
\ No newline at end of file
diff --git a/dojox/lang/aspect/timer.js b/dojox/lang/aspect/timer.js
index 52e6bc3..fabb25d 100644
--- a/dojox/lang/aspect/timer.js
+++ b/dojox/lang/aspect/timer.js
@@ -1,28 +1,33 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.aspect.timer"]){
-dojo._hasResource["dojox.lang.aspect.timer"]=true;
 dojo.provide("dojox.lang.aspect.timer");
+
 (function(){
-var _1=dojox.lang.aspect,_2=0;
-var _3=function(_4){
-this.name=_4||("DojoAopTimer #"+ ++_2);
-this.inCall=0;
-};
-dojo.extend(_3,{before:function(){
-if(!(this.inCall++)){
-}
-},after:function(){
-if(!--this.inCall){
-}
-}});
-_1.timer=function(_5){
-return new _3(_5);
-};
-})();
-}
+	var aop = dojox.lang.aspect,
+		uniqueNumber = 0;
+	
+	var Timer = function(name){
+		this.name = name || ("DojoAopTimer #" + ++uniqueNumber);
+		this.inCall = 0;
+	};
+	dojo.extend(Timer, {
+		before: function(/*arguments*/){
+			if(!(this.inCall++)){
+				console.time(this.name);
+			}
+		},
+		after: function(/*excp*/){
+			if(!--this.inCall){
+				console.timeEnd(this.name);
+			}
+		}
+	});
+	
+	aop.timer = function(/*String?*/ name){
+		// summary:
+		//		Returns an object, which can be used to time calls to methods.
+		//
+		// name:
+		//		The optional unique name of the timer.
+
+		return new Timer(name);	// Object
+	};
+})();
\ No newline at end of file
diff --git a/dojox/lang/aspect/tracer.js b/dojox/lang/aspect/tracer.js
index 00e8aa6..72928a7 100644
--- a/dojox/lang/aspect/tracer.js
+++ b/dojox/lang/aspect/tracer.js
@@ -1,34 +1,44 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.aspect.tracer"]){
-dojo._hasResource["dojox.lang.aspect.tracer"]=true;
 dojo.provide("dojox.lang.aspect.tracer");
+
 (function(){
-var _1=dojox.lang.aspect;
-var _2=function(_3){
-this.method=_3?"group":"log";
-if(_3){
-this.after=this._after;
-}
-};
-dojo.extend(_2,{before:function(){
-var _4=_1.getContext(),_5=_4.joinPoint,_6=Array.prototype.join.call(arguments,", ");
-console[this.method](_4.instance,"=>",_5.targetName+"("+_6+")");
-},afterReturning:function(_7){
-var _8=_1.getContext().joinPoint;
-if(typeof _7!="undefined"){
-}else{
-}
-},afterThrowing:function(_9){
-},_after:function(_a){
-}});
-_1.tracer=function(_b){
-return new _2(_b);
-};
-})();
-}
+	var aop = dojox.lang.aspect;
+	
+	var Tracer = function(/*Boolean*/ grouping){
+		this.method   = grouping ? "group" : "log";
+		if(grouping){
+			this.after = this._after;
+		}
+	};
+	dojo.extend(Tracer, {
+		before: function(/*arguments*/){
+			var context = aop.getContext(), joinPoint = context.joinPoint,
+				args = Array.prototype.join.call(arguments, ", ");
+			console[this.method](context.instance, "=>", joinPoint.targetName + "(" + args + ")");
+		},
+		afterReturning: function(retVal){
+			var joinPoint = aop.getContext().joinPoint;
+			if(typeof retVal != "undefined"){
+				console.log(joinPoint.targetName + "() returns:", retVal);
+			}else{
+				console.log(joinPoint.targetName + "() returns");
+			}
+		},
+		afterThrowing: function(excp){
+			console.log(aop.getContext().joinPoint.targetName + "() throws:", excp);
+		},
+		_after: function(excp){
+			console.groupEnd();
+		}
+	});
+	
+	aop.tracer = function(/*Boolean*/ grouping){
+		// summary:
+		//		Returns an object, which can be used to trace calls with Firebug's console.
+		//		Prints argument, a return value, or an exception.
+		//
+		// grouping:
+		//		The flag to group output. If true, indents embedded console messages.
+	
+		return new Tracer(grouping);	// Object
+	};
+})();
\ No newline at end of file
diff --git a/dojox/lang/async.js b/dojox/lang/async.js
new file mode 100644
index 0000000..a6c3bc2
--- /dev/null
+++ b/dojox/lang/async.js
@@ -0,0 +1,199 @@
+dojo.provide("dojox.lang.async");
+
+(function(){
+	var d = dojo, Deferred = d.Deferred, each = d.forEach, some = d.some,
+		async = dojox.lang.async, aps = Array.prototype.slice,
+		opts = Object.prototype.toString;
+
+	async.seq = function(x){
+		// summary:
+		//		Executes functions sequentially. Waits if any of them returns Deferred.
+		var fs = opts.call(x) == "[object Array]" ? x : arguments;
+		return function(init){
+			var x = new Deferred();
+			each(fs, function(f){ x.addCallback(f); });
+			x.callback(init);
+			return x;
+		};
+	};
+
+	async.par = function(x){
+		// summary:
+		//		Executes functions in parallel. Waits for all of them to finish.
+		var fs = opts.call(x) == "[object Array]" ? x : arguments;
+		return function(init){
+			var results = new Array(fs.length),
+				cancel = function(){
+					each(results, function(v){
+						if(v instanceof Deferred && v.fired < 0){
+							v.cancel();
+						}
+					});
+				},
+				x = new Deferred(cancel),
+				ready = fs.length;
+			each(fs, function(f, i){
+				var x;
+				try {
+					x = f(init);
+				}catch(e){
+					x = e;
+				}
+				results[i] = x;
+			});
+			var failed = some(results, function(v){
+				if(v instanceof Error){
+					cancel();
+					x.errback(v);
+					return true;
+				}
+				return false;
+			});
+			if(!failed){
+				each(results, function(v, i){
+					if(v instanceof Deferred){
+						v.addCallbacks(
+							function(v){
+								results[i] = v;
+								if(!--ready){
+									x.callback(results);
+								}
+							},
+							function(v){
+								cancel();
+								x.errback(v);
+							}
+						);
+					}else{
+						--ready;
+					}
+				});
+			}
+			if(!ready){
+				x.callback(results);
+			}
+			return x;
+		};
+	};
+
+	async.any = function(x){
+		// summary:
+		//		Executes functions in parallel. As soon as one of them finishes
+		//		cancels the rest.
+		var fs = opts.call(x) == "[object Array]" ? x : arguments;
+		return function(init){
+			var results = new Array(fs.length), noResult = true;
+				cancel = function(index){
+					each(results, function(v, i){
+						if(i != index && v instanceof Deferred && v.fired < 0){
+							v.cancel();
+						}
+					});
+				},
+				x = new Deferred(cancel);
+			each(fs, function(f, i){
+				var x;
+				try {
+					x = f(init);
+				}catch(e){
+					x = e;
+				}
+				results[i] = x;
+			});
+			var done = some(results, function(v, i){
+				if(!(v instanceof Deferred)){
+					cancel(i);
+					x.callback(v);
+					return true;
+				}
+				return false;
+			});
+			if(!done){
+				each(results, function(v, i){
+					v.addBoth(
+						function(v){
+							if(noResult){
+								noResult = false;
+								cancel(i);
+								x.callback(v);
+							}
+						}
+					);
+				});
+			}
+			return x;
+		};
+	};
+
+	async.select = function(cond, x){
+		// summary:
+		//		Executes a condition, waits for it if necessary, and executes
+		//		Nth function from list.
+		var fs = opts.call(x) == "[object Array]" ? x : aps.call(arguments, 1);
+		return function(init){
+			return new Deferred().addCallback(cond).addCallback(function(v){
+				if(typeof v == "number" && v >= 0 && v < fs.length){
+					return fs[v](init);
+				}else{
+					return new Error("async.select: out of range");
+				}
+			}).callback(init);
+		};
+	};
+
+	async.ifThen = function(cond, ifTrue, ifFalse){
+		// summary:
+		//		Executes a condition, waits for it if necessary, and executes
+		//		one of two functions.
+		return function(init){
+			return new Deferred().addCallback(cond).addCallback(function(v){
+				return (v ? ifTrue : ifFalse)(init);
+			}).callback(init);
+		};
+	};
+
+	async.loop = function(cond, body){
+		// summary:
+		//		Executes a condition, waits for it if necessary, and executes
+		//		the body, if truthy value was returned.
+		//		Then it repeats the cycle until the condition function returns
+		//		a falsy value.
+		return function(init){
+			var x, y = new Deferred(function(){ x.cancel(); });
+			function ifErr(v){ y.errback(v); }
+			function loop(v){
+				if(v){
+					x.addCallback(body).addCallback(setUp);
+				}else{
+					y.callback(v);
+				}
+				return v;
+			}
+			function setUp(init){
+				x = new Deferred().
+					addCallback(cond).
+					addCallback(loop).
+					addErrback(ifErr);
+				x.callback(init);
+			}
+			setUp(init);
+			return y;
+		};
+	};
+})();
+
+/*
+Design decisions:
+
+seq() - behaves like the normal Deferred callback chain.
+
+par() - if error, all pending Deferreds are cancelled and the error is signaled,
+otherwise return an array of all results.
+
+any() - just like par() but only one result is returned.
+
+select() - any error is returned, otherwise the selected result is returned.
+
+loop() - any error is returned, otherwise the last result is returned.
+
+*/
diff --git a/dojox/lang/async/event.js b/dojox/lang/async/event.js
new file mode 100644
index 0000000..d099e30
--- /dev/null
+++ b/dojox/lang/async/event.js
@@ -0,0 +1,41 @@
+dojo.provide("dojox.lang.async.event");
+
+// Source of Deferred for events
+
+(function(){
+	var d = dojo, event = dojox.lang.async.event;
+
+	event.from = function(src, name){
+		return function(){
+			var h, cancel = function(){
+					if(h){
+						d.disconnect(h);
+						h = null;
+					}
+				},
+				x = new d.Deferred(cancel);
+			h = d.connect(src, name, function(evt){
+				cancel();
+				x.callback(evt);
+			});
+			return x;
+		};
+	};
+
+	event.failOn = function(src, name){
+		return function(){
+			var h, cancel = function(){
+					if(h){
+						d.disconnect(h);
+						h = null;
+					}
+				},
+				x = new d.Deferred(cancel);
+			h = d.connect(src, name, function(evt){
+				cancel();
+				x.errback(new Error(evt));
+			});
+			return x;
+		};
+	};
+})();
diff --git a/dojox/lang/async/timeout.js b/dojox/lang/async/timeout.js
new file mode 100644
index 0000000..13c4870
--- /dev/null
+++ b/dojox/lang/async/timeout.js
@@ -0,0 +1,41 @@
+dojo.provide("dojox.lang.async.timeout");
+
+// Source of Deferred for timeouts
+
+(function(){
+	var d = dojo, timeout = dojox.lang.async.timeout;
+
+	timeout.from = function(ms){
+		return function(){
+			var h, cancel = function(){
+					if(h){
+						clearTimeout(h);
+						h = null;
+					}
+				},
+				x = new d.Deferred(cancel);
+			h = setTimeout(function(){
+				cancel();
+				x.callback(ms);
+			}, ms);
+			return x;
+		};
+	};
+
+	timeout.failOn = function(ms){
+		return function(){
+			var h, cancel = function(){
+					if(h){
+						clearTimeout(h);
+						h = null;
+					}
+				},
+				x = new d.Deferred(cancel);
+			h = setTimeout(function(){
+				cancel();
+				x.errback(ms);
+			}, ms);
+			return x;
+		};
+	};
+})();
\ No newline at end of file
diff --git a/dojox/lang/async/topic.js b/dojox/lang/async/topic.js
new file mode 100644
index 0000000..71db3dd
--- /dev/null
+++ b/dojox/lang/async/topic.js
@@ -0,0 +1,41 @@
+dojo.provide("dojox.lang.async.topic");
+
+// Source of Deferred for topics
+
+(function(){
+	var d = dojo, topic = dojox.lang.async.topic;
+
+	topic.from = function(topic){
+		return function(){
+			var h, cancel = function(){
+					if(h){
+						d.unsubscribe(h);
+						h = null;
+					}
+				},
+				x = new d.Deferred(cancel);
+			h = d.subscribe(topic, function(){
+				cancel();
+				x.callback(arguments);
+			});
+			return x;
+		};
+	};
+
+	topic.failOn = function(topic){
+		return function(){
+			var h, cancel = function(){
+					if(h){
+						d.unsubscribe(h);
+						h = null;
+					}
+				},
+				x = new d.Deferred(cancel);
+			h = d.subscribe(topic, function(evt){
+				cancel();
+				x.errback(new Error(arguments));
+			});
+			return x;
+		};
+	};
+})();
\ No newline at end of file
diff --git a/dojox/lang/docs.js b/dojox/lang/docs.js
index 3229e5c..fb6a089 100644
--- a/dojox/lang/docs.js
+++ b/dojox/lang/docs.js
@@ -1,192 +1,214 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.docs"]){
-dojo._hasResource["dojox.lang.docs"]=true;
 dojo.provide("dojox.lang.docs");
+
+// Extracts information from the API docs to apply a schema representation to dojo classes.
+// This can be utilized for runtime metadata retrieval and type checking
 (function(){
-function _1(_2){
-};
-var _3={};
-var _4=[];
-var _5=dojox.lang.docs._loadedDocs={};
-var _6=function(_7,_8){
-_3[_8]=_7;
-};
-var _9=function(_a){
-var _b=_a.type||"";
-var _c,_d=false,_e=false,_f;
-_b=_b.replace(/\?/,function(){
-_d=true;
-return "";
-});
-_b=_b.replace(/\[\]/,function(){
-_e=true;
-return "";
-});
-if(_b.match(/HTML/)){
-_b="string";
-}else{
-if(_b=="String"||_b=="Number"||_b=="Boolean"||_b=="Object"||_b=="Array"||_b=="Integer"||_b=="Function"){
-_b=_b.toLowerCase();
-}else{
-if(_b=="bool"){
-_b="boolean";
-}else{
-if(_b){
-_c=dojo.getObject(_b)||{};
-_f=true;
-}else{
-_c={};
-}
-}
-}
-}
-_c=_c||{type:_b};
-if(_e){
-_c={items:_c,type:"array"};
-_f=false;
-}
-if(!_f){
-if(_d){
-_c.optional=true;
-}
-if(/const/.test(_a.tags)){
-_c.readonly=true;
-}
-}
-return _c;
-};
-var _10=function(_11,_12){
-var _13=_5[_12];
-if(_13){
-_11.description=_13.description;
-_11.properties={};
-_11.methods={};
-if(_13.properties){
-var _14=_13.properties;
-for(var i=0,l=_14.length;i<l;i++){
-if(_14[i].scope=="prototype"){
-var _15=_11.properties[_14[i].name]=_9(_14[i]);
-_15.description=_14[i].summary;
-}
-}
-}
-if(_13.methods){
-var _16=_13.methods;
-for(i=0,l=_16.length;i<l;i++){
-_12=_16[i].name;
-if(_12&&_16[i].scope=="prototype"){
-var _17=_11.methods[_12]={};
-_17.description=_16[i].summary;
-var _18=_16[i].parameters;
-if(_18){
-_17.parameters=[];
-for(var j=0,k=_18.length;j<k;j++){
-var _19=_18[j];
-var _1a=_17.parameters[j]=_9(_19);
-_1a.name=_19.name;
-_1a.optional="optional"==_19.usage;
-}
-}
-var ret=_16[i]["return-types"];
-if(ret&&ret[0]){
-var _1b=_9(ret[0]);
-if(_1b.type){
-_17.returns=_1b;
-}
-}
-}
-}
-}
-var _1c=_13.superclass;
-if(_1c){
-_11["extends"]=dojo.getObject(_1c);
-}
-}
-};
-var _1d=function(_1e){
-_4.push(_1e);
-};
-var _1f=dojo.declare;
-dojo.declare=function(_20){
-var _21=_1f.apply(this,arguments);
-_6(_21,_20);
-return _21;
-};
-dojo.mixin(dojo.declare,_1f);
-var _22;
-var _23=dojo.require;
-dojo.require=function(_24){
-_1d(_24);
-var _25=_23.apply(this,arguments);
-return _25;
-};
-dojox.lang.docs.init=function(_26){
-function _27(){
-dojo.require=_23;
-_4=null;
-try{
-dojo.xhrGet({sync:!_26,url:dojo.baseUrl+"../util/docscripts/api.json",handleAs:"text"}).addCallbacks(function(obj){
-_5=(new Function("return "+obj))();
-obj=null;
-_6=_10;
-for(var i in _3){
-_6(_3[i],i);
-}
-_3=null;
-},_1);
-}
-catch(e){
-_1(e);
-}
-};
-if(_22){
-return null;
-}
-_22=true;
-var _28=function(_29,_2a){
-return dojo.xhrGet({sync:_2a||!_26,url:dojo.baseUrl+"../util/docscripts/api/"+_29+".json",handleAs:"text"}).addCallback(function(obj){
-obj=(new Function("return "+obj))();
-for(var _2b in obj){
-if(!_5[_2b]){
-_5[_2b]=obj[_2b];
-}
-}
-});
-};
-try{
-var _2c=_4.shift();
-_28(_2c,true).addCallbacks(function(){
-_1d=function(_2d){
-if(!_5[_2d]){
-try{
-_28(_2d);
-}
-catch(e){
-_5[_2d]={};
-}
-}
-};
-dojo.forEach(_4,function(mod){
-_1d(mod);
-});
-_4=null;
-_6=_10;
-for(i in _3){
-_6(_3[i],i);
-}
-_3=null;
-},_27);
-}
-catch(e){
-_27();
-}
-return null;
-};
+	function error(error){
+		console.log("Warning, the API docs must be available at ../util/docscripts/api.json "+ 
+		"or ../util/docscripts/api/*.json "+
+		"in order for dojox.lang.docs to supply schema information, but it could not be loaded: " + error);
+	}
+
+	var declaredClasses = {};
+	var requiredModules = [];
+	var _docs = dojox.lang.docs._loadedDocs = {};
+
+	var schemifyClass = function(clazz, name){
+		// initial implementation records classes until they are ready
+		declaredClasses[name] = clazz;
+	};
+	var getType = function(typeDef){
+		var type = typeDef.type || '';		
+		var typeObj, optional = false, array = false, dontModify;
+		type = type.replace(/\?/, function(){
+			optional = true;
+			return '';
+		});
+		type = type.replace(/\[\]/, function(){
+			array = true;
+			return '';
+		});
+		if(type.match(/HTML/)){
+			// HTML String and other "types" of strings are really just strings
+			type = "string";
+		}else if(type == 'String' || type == 'Number' ||
+				type == 'Boolean' || type == 'Object' ||
+				type == 'Array' || type == 'Integer' || type == "Function"){
+			type = type.toLowerCase();
+		}else if(type == "bool"){
+			type = "boolean";
+		}else if(type){
+			typeObj = dojo.getObject(type) || {};
+			dontModify = true;
+		}else{
+			typeObj = {};
+		}
+		typeObj = typeObj || {type:type};
+		if(array){
+			typeObj = {items:typeObj, type:"array"};
+			dontModify = false;
+		}
+		if(!dontModify){
+			if(optional){
+				typeObj.optional = true;
+			}
+			if(/const/.test(typeDef.tags)){
+				typeObj.readonly = true;
+			}
+		}
+		return typeObj;
+	};
+	var actualSchemifyClass = function(clazz, name){
+		var docForClass = _docs[name];
+		if(docForClass){
+			clazz.description = docForClass.description;
+			clazz.properties = {};
+			clazz.methods = {};
+
+			if(docForClass.properties){
+				var props = docForClass.properties;
+				for(var i=0, l=props.length; i<l; i++){
+					if(props[i].scope == "prototype"){
+						var propDef = clazz.properties[props[i].name] = getType(props[i]);
+						propDef.description = props[i].summary;
+					}
+				}
+			}
+
+			// translate the methods to JSON Schema
+			if(docForClass.methods){
+				var methods = docForClass.methods;
+				for(i=0, l=methods.length; i<l; i++){
+					name = methods[i].name;
+					if(name && methods[i].scope == "prototype"){
+						var methodDef = clazz.methods[name] = {};
+						methodDef.description = methods[i].summary;
+						var parameters = methods[i].parameters;
+						if(parameters){
+							methodDef.parameters = [];
+							for(var j=0, k=parameters.length; j<k; j++){
+								var param = parameters[j];
+								var paramDef = methodDef.parameters[j] = getType(param);
+								paramDef.name = param.name;
+								paramDef.optional = "optional" == param.usage;
+							}
+						}
+						var ret = methods[i]['return-types'];
+						if(ret && ret[0]){
+							var returns = getType(ret[0]);
+							if(returns.type){
+								methodDef.returns = returns;
+							}
+						}
+					}
+				}
+			}
+
+			var superclass = docForClass.superclass;
+			if(superclass){
+				clazz["extends"] = dojo.getObject(superclass);
+			}
+		}
+	};
+	var requireDocs = function(moduleName){
+		requiredModules.push(moduleName);
+	};
+
+	// hook into all declared classes
+	var defaultDeclare = dojo.declare;
+	dojo.declare = function(name){
+		var clazz = defaultDeclare.apply(this, arguments);
+		schemifyClass(clazz, name);
+		return clazz;
+	};
+	dojo.mixin(dojo.declare, defaultDeclare);
+	var initialized;
+
+	// hook into dojo.require
+	var defaultRequire = dojo.require;
+	dojo.require = function(moduleName){
+		requireDocs(moduleName);
+		var module = defaultRequire.apply(this, arguments);
+		return module;
+	};
+
+	dojox.lang.docs.init = function(/*Boolean*/async){
+		// summary:
+		//		Loads the documentation and applies it to the previously defined classes 
+		// 		and any future defined classes
+		// 
+		// async:
+		// 		 If true, the documentation will be loaded asynchronously
+		function loadFullDocs(){
+			dojo.require = defaultRequire;
+			requiredModules = null;
+			try{
+				dojo.xhrGet({
+					sync:!async,
+					url: dojo.baseUrl + '../util/docscripts/api.json',
+					handleAs: 'text'
+				}).addCallbacks(function(obj){
+					_docs = (new Function("return " + obj))();
+					obj = null;
+					schemifyClass = actualSchemifyClass;
+
+					for(var i in declaredClasses){
+						schemifyClass(declaredClasses[i], i);
+					}
+					declaredClasses = null;
+				}, error);
+			}catch(e){
+				error(e);
+			}
+		}
+		
+		if(initialized){
+			return null;
+		}
+		initialized = true;
+
+		var getSplitDocs = function(moduleName, sync){
+			return dojo.xhrGet({
+				sync: sync||!async,
+				url: dojo.baseUrl + '../util/docscripts/api/' + moduleName + '.json',
+				handleAs: 'text'
+			}).addCallback(function(obj){
+				obj = (new Function("return " + obj))();
+				for(var clazz in obj){
+					if(!_docs[clazz]){
+						_docs[clazz] = obj[clazz];
+					}
+				}
+			});
+		};
+		try{
+			var firstMod = requiredModules.shift();
+			getSplitDocs(firstMod, true).addCallbacks(function(){
+				requireDocs = function(moduleName){
+					if(!_docs[moduleName]){
+						try{
+							getSplitDocs(moduleName);
+						}catch(e){
+							_docs[moduleName] = {};
+						}
+					}
+				};
+				//console.log(requiredModules);
+				dojo.forEach(requiredModules, function(mod){
+					requireDocs(mod);
+				});
+				requiredModules = null;
+
+				schemifyClass = actualSchemifyClass;
+
+				for(i in declaredClasses){
+					schemifyClass(declaredClasses[i], i);
+				}
+				declaredClasses = null;
+			},loadFullDocs);
+		}catch(e){
+			loadFullDocs();
+		}
+		return null;
+	}
 })();
-}
diff --git a/dojox/lang/functional.js b/dojox/lang/functional.js
index 364aed0..9d8411e 100644
--- a/dojox/lang/functional.js
+++ b/dojox/lang/functional.js
@@ -1,14 +1,5 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional"]){
-dojo._hasResource["dojox.lang.functional"]=true;
 dojo.provide("dojox.lang.functional");
+
 dojo.require("dojox.lang.functional.lambda");
 dojo.require("dojox.lang.functional.array");
 dojo.require("dojox.lang.functional.object");
-}
diff --git a/dojox/lang/functional/array.js b/dojox/lang/functional/array.js
old mode 100644
new mode 100755
index 36fdadd..5f2c71d
--- a/dojox/lang/functional/array.js
+++ b/dojox/lang/functional/array.js
@@ -1,161 +1,164 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.array"]){
-dojo._hasResource["dojox.lang.functional.array"]=true;
 dojo.provide("dojox.lang.functional.array");
+
 dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+//	- array-processing functions similar to standard JS functions
+
+// Notes:
+//	- this module provides JS standard methods similar to high-level functions in dojo/_base/array.js: 
+//		forEach, map, filter, every, some
+
+// Defined methods:
+//	- take any valid lambda argument as the functional argument
+//	- operate on dense arrays
+//	- take a string as the array argument
+//	- take an iterator objects as the array argument
+
 (function(){
-var d=dojo,df=dojox.lang.functional,_1={};
-d.mixin(df,{filter:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var t=[],v,i,n;
-if(d.isArray(a)){
-for(i=0,n=a.length;i<n;++i){
-v=a[i];
-if(f.call(o,v,i,a)){
-t.push(v);
-}
-}
-}else{
-if(typeof a.hasNext=="function"&&typeof a.next=="function"){
-for(i=0;a.hasNext();){
-v=a.next();
-if(f.call(o,v,i++,a)){
-t.push(v);
-}
-}
-}else{
-for(i in a){
-if(!(i in _1)){
-v=a[i];
-if(f.call(o,v,i,a)){
-t.push(v);
-}
-}
-}
-}
-}
-return t;
-},forEach:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var i,n;
-if(d.isArray(a)){
-for(i=0,n=a.length;i<n;f.call(o,a[i],i,a),++i){
-}
-}else{
-if(typeof a.hasNext=="function"&&typeof a.next=="function"){
-for(i=0;a.hasNext();f.call(o,a.next(),i++,a)){
-}
-}else{
-for(i in a){
-if(!(i in _1)){
-f.call(o,a[i],i,a);
-}
-}
-}
-}
-return o;
-},map:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var t,n,i;
-if(d.isArray(a)){
-t=new Array(n=a.length);
-for(i=0;i<n;t[i]=f.call(o,a[i],i,a),++i){
-}
-}else{
-if(typeof a.hasNext=="function"&&typeof a.next=="function"){
-t=[];
-for(i=0;a.hasNext();t.push(f.call(o,a.next(),i++,a))){
-}
-}else{
-t=[];
-for(i in a){
-if(!(i in _1)){
-t.push(f.call(o,a[i],i,a));
-}
-}
-}
-}
-return t;
-},every:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var i,n;
-if(d.isArray(a)){
-for(i=0,n=a.length;i<n;++i){
-if(!f.call(o,a[i],i,a)){
-return false;
-}
-}
-}else{
-if(typeof a.hasNext=="function"&&typeof a.next=="function"){
-for(i=0;a.hasNext();){
-if(!f.call(o,a.next(),i++,a)){
-return false;
-}
-}
-}else{
-for(i in a){
-if(!(i in _1)){
-if(!f.call(o,a[i],i,a)){
-return false;
-}
-}
-}
-}
-}
-return true;
-},some:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var i,n;
-if(d.isArray(a)){
-for(i=0,n=a.length;i<n;++i){
-if(f.call(o,a[i],i,a)){
-return true;
-}
-}
-}else{
-if(typeof a.hasNext=="function"&&typeof a.next=="function"){
-for(i=0;a.hasNext();){
-if(f.call(o,a.next(),i++,a)){
-return true;
-}
-}
-}else{
-for(i in a){
-if(!(i in _1)){
-if(f.call(o,a[i],i,a)){
-return true;
-}
-}
-}
-}
-}
-return false;
-}});
+	var d = dojo, df = dojox.lang.functional, empty = {};
+
+	d.mixin(df, {
+		// JS 1.6 standard array functions, which can take a lambda as a parameter.
+		// Consider using dojo._base.array functions, if you don't need the lambda support.
+		filter: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: creates a new array with all elements that pass the test 
+			//	implemented by the provided function.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var t = [], v, i, n;
+			if(d.isArray(a)){
+				// array
+				for(i = 0, n = a.length; i < n; ++i){
+					v = a[i];
+					if(f.call(o, v, i, a)){ t.push(v); }
+				}
+			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
+				// iterator
+				for(i = 0; a.hasNext();){
+					v = a.next();
+					if(f.call(o, v, i++, a)){ t.push(v); }
+				}
+			}else{
+				// object/dictionary
+				for(i in a){
+					if(!(i in empty)){
+						v = a[i];
+						if(f.call(o, v, i, a)){ t.push(v); }
+					}
+				}
+			}
+			return t;	// Array
+		},
+		forEach: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: executes a provided function once per array element.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var i, n;
+			if(d.isArray(a)){
+				// array
+				for(i = 0, n = a.length; i < n; f.call(o, a[i], i, a), ++i);
+			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
+				// iterator
+				for(i = 0; a.hasNext(); f.call(o, a.next(), i++, a));
+			}else{
+				// object/dictionary
+				for(i in a){
+					if(!(i in empty)){
+						f.call(o, a[i], i, a);
+					}
+				}
+			}
+			return o;	// Object
+		},
+		map: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: creates a new array with the results of calling 
+			//	a provided function on every element in this array.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var t, n, i;
+			if(d.isArray(a)){
+				// array
+				t = new Array(n = a.length);
+				for(i = 0; i < n; t[i] = f.call(o, a[i], i, a), ++i);
+			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
+				// iterator
+				t = [];
+				for(i = 0; a.hasNext(); t.push(f.call(o, a.next(), i++, a)));
+			}else{
+				// object/dictionary
+				t = [];
+				for(i in a){
+					if(!(i in empty)){
+						t.push(f.call(o, a[i], i, a));
+					}
+				}
+			}
+			return t;	// Array
+		},
+		every: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: tests whether all elements in the array pass the test 
+			//	implemented by the provided function.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var i, n;
+			if(d.isArray(a)){
+				// array
+				for(i = 0, n = a.length; i < n; ++i){
+					if(!f.call(o, a[i], i, a)){
+						return false;	// Boolean
+					}
+				}
+			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
+				// iterator
+				for(i = 0; a.hasNext();){
+					if(!f.call(o, a.next(), i++, a)){
+						return false;	// Boolean
+					}
+				}
+			}else{
+				// object/dictionary
+				for(i in a){
+					if(!(i in empty)){
+						if(!f.call(o, a[i], i, a)){
+							return false;	// Boolean
+						}
+					}
+				}
+			}
+			return true;	// Boolean
+		},
+		some: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: tests whether some element in the array passes the test 
+			//	implemented by the provided function.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var i, n;
+			if(d.isArray(a)){
+				// array
+				for(i = 0, n = a.length; i < n; ++i){
+					if(f.call(o, a[i], i, a)){
+						return true;	// Boolean
+					}
+				}
+			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
+				// iterator
+				for(i = 0; a.hasNext();){
+					if(f.call(o, a.next(), i++, a)){
+						return true;	// Boolean
+					}
+				}
+			}else{
+				// object/dictionary
+				for(i in a){
+					if(!(i in empty)){
+						if(f.call(o, a[i], i, a)){
+							return true;	// Boolean
+						}
+					}
+				}
+			}
+			return false;	// Boolean
+		}
+	});
 })();
-}
diff --git a/dojox/lang/functional/binrec.js b/dojox/lang/functional/binrec.js
index 49ca84e..e679c1f 100644
--- a/dojox/lang/functional/binrec.js
+++ b/dojox/lang/functional/binrec.js
@@ -1,62 +1,173 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.binrec"]){
-dojo._hasResource["dojox.lang.functional.binrec"]=true;
 dojo.provide("dojox.lang.functional.binrec");
+
 dojo.require("dojox.lang.functional.lambda");
 dojo.require("dojox.lang.functional.util");
+
+// This module provides recursion combinators:
+//	- a binary recursion combinator.
+
+// Acknoledgements:
+//	- recursion combinators are inspired by Manfred von Thun's article
+//		"Recursion Theory and Joy"
+//		(http://www.latrobe.edu.au/philosophy/phimvt/joy/j05cmp.html)
+
+// Notes:
+//	- recursion combinators produce a function, which implements
+//	their respective recusion patterns. String lambdas are inlined, if possible.
+
 (function(){
-var df=dojox.lang.functional,_1=df.inlineLambda,_2="_x",_3=["_z.r","_r","_z.a"];
-df.binrec=function(_4,_5,_6,_7){
-var c,t,b,a,cs,ts,bs,as,_8={},_9={},_a=function(x){
-_8[x]=1;
+	var df = dojox.lang.functional, inline = df.inlineLambda,
+		_x ="_x", _z_r_r_z_a = ["_z.r", "_r", "_z.a"];
+
+	df.binrec = function(
+					/*Function|String|Array*/ cond,
+					/*Function|String|Array*/ then,
+					/*Function|String|Array*/ before,
+					/*Function|String|Array*/ after){
+		// summary:
+		//		Generates a function for the binary recursion pattern.
+		//		All parameter functions are called in the context of "this" object.
+		// cond:
+		//		The lambda expression, which is used to detect the termination of recursion.
+		//		It accepts the same parameter as the generated recursive function itself.
+		//		This function should return "true", if the recursion should be stopped,
+		//		and the "then" part should be executed. Otherwise the recursion will proceed.
+		// then:
+		//		The lambda expression, which is called upon termination of the recursion.
+		//		It accepts the same parameters as the generated recursive function itself.
+		//		The returned value will be returned as the value of the generated function.
+		// before:
+		//		The lambda expression, which is called before the recursive step.
+		//		It accepts the same parameter as the generated recursive function itself.
+		//		The returned value should be an array of two variable, which are used to call
+		//		the generated function recursively twice in row starting from the first item.
+		// above:
+		//		The lambda expression, which is called after the recursive step.
+		//		It accepts three parameters: two returned values from recursive steps, and
+		//		the original array of parameters used with all other functions.
+		//		The returned value will be returned as the value of the generated function.
+
+		var c, t, b, a, cs, ts, bs, as, dict1 = {}, dict2 = {},
+			add2dict = function(x){ dict1[x] = 1; };
+		if(typeof cond == "string"){
+			cs = inline(cond, _x, add2dict);
+		}else{
+			c = df.lambda(cond);
+			cs = "_c.apply(this, _x)";
+			dict2["_c=_t.c"] = 1;
+		}
+		if(typeof then == "string"){
+			ts = inline(then, _x, add2dict);
+		}else{
+			t = df.lambda(then);
+			ts = "_t.apply(this, _x)";
+		}
+		if(typeof before == "string"){
+			bs = inline(before, _x, add2dict);
+		}else{
+			b = df.lambda(before);
+			bs = "_b.apply(this, _x)";
+			dict2["_b=_t.b"] = 1;
+		}
+		if(typeof after == "string"){
+			as = inline(after, _z_r_r_z_a, add2dict);
+		}else{
+			a = df.lambda(after);
+			as = "_a.call(this, _z.r, _r, _z.a)";
+			dict2["_a=_t.a"] = 1;
+		}
+		var locals1 = df.keys(dict1), locals2 = df.keys(dict2),
+			f = new Function([], "var _x=arguments,_y,_z,_r".concat(	// Function
+				locals1.length ? "," + locals1.join(",") : "",
+				locals2.length ? ",_t=_x.callee," + locals2.join(",") : "",
+				t ? (locals2.length ? ",_t=_t.t" : "_t=_x.callee.t") : "",
+				";while(!",
+				cs,
+				"){_r=",
+				bs,
+				";_y={p:_y,a:_r[1]};_z={p:_z,a:_x};_x=_r[0]}for(;;){do{_r=",
+				ts,
+				";if(!_z)return _r;while(\"r\" in _z){_r=",
+				as,
+				";if(!(_z=_z.p))return _r}_z.r=_r;_x=_y.a;_y=_y.p}while(",
+				cs,
+				");do{_r=",
+				bs,
+				";_y={p:_y,a:_r[1]};_z={p:_z,a:_x};_x=_r[0]}while(!",
+				cs,
+				")}"
+			));
+		if(c){ f.c = c; }
+		if(t){ f.t = t; }
+		if(b){ f.b = b; }
+		if(a){ f.a = a; }
+		return f;
+	};
+})();
+
+/*
+For documentation only:
+
+1) The original recursive version:
+
+var binrec1 = function(cond, then, before, after){
+	var cond   = df.lambda(cond),
+		then   = df.lambda(then),
+		before = df.lambda(before),
+		after  = df.lambda(after);
+	return function(){
+		if(cond.apply(this, arguments)){
+			return then.apply(this, arguments);
+		}
+		var args = before.apply(this, arguments);
+		var ret1 = arguments.callee.apply(this, args[0]);
+		var ret2 = arguments.callee.apply(this, args[1]);
+		return after.call(this, ret1, ret2, arguments);
+	};
 };
-if(typeof _4=="string"){
-cs=_1(_4,_2,_a);
-}else{
-c=df.lambda(_4);
-cs="_c.apply(this, _x)";
-_9["_c=_t.c"]=1;
-}
-if(typeof _5=="string"){
-ts=_1(_5,_2,_a);
-}else{
-t=df.lambda(_5);
-ts="_t.apply(this, _x)";
-}
-if(typeof _6=="string"){
-bs=_1(_6,_2,_a);
-}else{
-b=df.lambda(_6);
-bs="_b.apply(this, _x)";
-_9["_b=_t.b"]=1;
-}
-if(typeof _7=="string"){
-as=_1(_7,_3,_a);
-}else{
-a=df.lambda(_7);
-as="_a.call(this, _z.r, _r, _z.a)";
-_9["_a=_t.a"]=1;
-}
-var _b=df.keys(_8),_c=df.keys(_9),f=new Function([],"var _x=arguments,_y,_z,_r".concat(_b.length?","+_b.join(","):"",_c.length?",_t=_x.callee,"+_c.join(","):"",t?(_c.length?",_t=_t.t":"_t=_x.callee.t"):"",";while(!",cs,"){_r=",bs,";_y={p:_y,a:_r[1]};_z={p:_z,a:_x};_x=_r[0]}for(;;){do{_r=",ts,";if(!_z)return _r;while(\"r\" in _z){_r=",as,";if(!(_z=_z.p))return _r}_z.r=_r;_x=_y.a;_y=_y.p}while(",cs,");do{_r=",bs,";_y={p:_y,a:_r[1]};_z={p:_z,a:_x};_x=_r[0]}while(!",cs,")}"));
-if(c){
-f.c=c;
-}
-if(t){
-f.t=t;
-}
-if(b){
-f.b=b;
-}
-if(a){
-f.a=a;
-}
-return f;
+
+2) The original iterative version (before minification and inlining):
+
+var binrec2 = function(cond, then, before, after){
+	var cond   = df.lambda(cond),
+		then   = df.lambda(then),
+		before = df.lambda(before),
+		after  = df.lambda(after);
+	return function(){
+		var top1, top2, ret, args = arguments;
+		// first part: start the pump
+		while(!cond.apply(this, args)){
+			ret = before.apply(this, args);
+			top1 = {prev: top1, args: ret[1]};
+			top2 = {prev: top2, args: args};
+			args = ret[0];
+		}
+		for(;;){
+			// second part: mop up
+			do{
+				ret = then.apply(this, args);
+				if(!top2){
+					return ret;
+				}
+				while("ret" in top2){
+					ret = after.call(this, top2.ret, ret, top2.args);
+					if(!(top2 = top2.prev)){
+						return ret;
+					}
+				}
+				top2.ret = ret;
+				args = top1.args;
+				top1 = top1.prev;
+			}while(cond.apply(this, args));
+			// first part (encore)
+			do{
+				ret = before.apply(this, args);
+				top1 = {prev: top1, args: ret[1]};
+				top2 = {prev: top2, args: args};
+				args = ret[0];
+			}while(!cond.apply(this, args));
+		}
+	};
 };
-})();
-}
+
+*/
\ No newline at end of file
diff --git a/dojox/lang/functional/curry.js b/dojox/lang/functional/curry.js
old mode 100644
new mode 100755
index 8ba5326..115912e
--- a/dojox/lang/functional/curry.js
+++ b/dojox/lang/functional/curry.js
@@ -1,64 +1,93 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.curry"]){
-dojo._hasResource["dojox.lang.functional.curry"]=true;
 dojo.provide("dojox.lang.functional.curry");
+
 dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+//	- currying and partial functions
+//	- argument pre-processing: mixer and flip
+
+// Acknoledgements:
+//	- partial() is based on work by Oliver Steele 
+//		(http://osteele.com/sources/javascript/functional/functional.js)
+//		which was published under MIT License
+
+// Defined methods:
+//	- take any valid lambda argument as the functional argument
+
 (function(){
-var df=dojox.lang.functional,ap=Array.prototype;
-var _1=function(_2){
-return function(){
-var _3=_2.args.concat(ap.slice.call(arguments,0));
-if(arguments.length+_2.args.length<_2.arity){
-return _1({func:_2.func,arity:_2.arity,args:_3});
-}
-return _2.func.apply(this,_3);
-};
-};
-dojo.mixin(df,{curry:function(f,_4){
-f=df.lambda(f);
-_4=typeof _4=="number"?_4:f.length;
-return _1({func:f,arity:_4,args:[]});
-},arg:{},partial:function(f){
-var a=arguments,l=a.length,_5=new Array(l-1),p=[],i=1,t;
-f=df.lambda(f);
-for(;i<l;++i){
-t=a[i];
-_5[i-1]=t;
-if(t===df.arg){
-p.push(i-1);
-}
-}
-return function(){
-var t=ap.slice.call(_5,0),i=0,l=p.length;
-for(;i<l;++i){
-t[p[i]]=arguments[i];
-}
-return f.apply(this,t);
-};
-},mixer:function(f,_6){
-f=df.lambda(f);
-return function(){
-var t=new Array(_6.length),i=0,l=_6.length;
-for(;i<l;++i){
-t[i]=arguments[_6[i]];
-}
-return f.apply(this,t);
-};
-},flip:function(f){
-f=df.lambda(f);
-return function(){
-var a=arguments,l=a.length-1,t=new Array(l+1),i=0;
-for(;i<=l;++i){
-t[l-i]=a[i];
-}
-return f.apply(this,t);
-};
-}});
+	var df = dojox.lang.functional, ap = Array.prototype;
+
+	var currying = function(/*Object*/ info){
+		return function(){	// Function
+			var args = info.args.concat(ap.slice.call(arguments, 0));
+			if(arguments.length + info.args.length < info.arity){
+				return currying({func: info.func, arity: info.arity, args: args});
+			}
+			return info.func.apply(this, args);
+		};
+	};
+
+	dojo.mixin(df, {
+		// currying and partial functions
+		curry: function(/*Function|String|Array*/ f, /*Number?*/ arity){
+			// summary: curries a function until the arity is satisfied, at 
+			//	which point it returns the calculated value.
+			f = df.lambda(f);
+			arity = typeof arity == "number" ? arity : f.length;
+			return currying({func: f, arity: arity, args: []});	// Function
+		},
+		arg: {},	// marker for missing arguments
+		partial: function(/*Function|String|Array*/ f){
+			// summary: creates a function where some arguments are bound, and
+			//	some arguments (marked as dojox.lang.functional.arg) are will be 
+			//	accepted by the final function in the order they are encountered.
+			// description: This method is used to produce partially bound 
+			//	functions. If you want to change the order of arguments, use
+			//	dojox.lang.functional.mixer() or dojox.lang.functional.flip().
+			var a = arguments, l = a.length, args = new Array(l - 1), p = [], i = 1, t;
+			f = df.lambda(f);
+			for(; i < l; ++i){
+				t = a[i];
+				args[i - 1] = t;
+				if(t === df.arg){
+					p.push(i - 1);
+				}
+			}
+			return function(){	// Function
+				var t = ap.slice.call(args, 0), // clone the array
+					i = 0, l = p.length;
+				for(; i < l; ++i){
+					t[p[i]] = arguments[i];
+				}
+				return f.apply(this, t);
+			};
+		},
+		// argument pre-processing
+		mixer: function(/*Function|String|Array*/ f, /*Array*/ mix){
+			// summary: changes the order of arguments using an array of
+			//	numbers mix --- i-th argument comes from mix[i]-th place
+			//	of supplied arguments.
+			f = df.lambda(f);
+			return function(){	// Function
+				var t = new Array(mix.length), i = 0, l = mix.length;
+				for(; i < l; ++i){
+					t[i] = arguments[mix[i]];
+				}
+				return f.apply(this, t);
+			};
+		},
+		flip: function(/*Function|String|Array*/ f){
+			// summary: changes the order of arguments by reversing their
+			//	order.
+			f = df.lambda(f);
+			return function(){	// Function
+				// reverse arguments
+				var a = arguments, l = a.length - 1, t = new Array(l + 1), i = 0;
+				for(; i <= l; ++i){
+					t[l - i] = a[i];
+				}
+				return f.apply(this, t);
+			};
+		}
+	});
 })();
-}
diff --git a/dojox/lang/functional/fold.js b/dojox/lang/functional/fold.js
old mode 100644
new mode 100755
index 628cd30..a1b5377
--- a/dojox/lang/functional/fold.js
+++ b/dojox/lang/functional/fold.js
@@ -1,104 +1,120 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.fold"]){
-dojo._hasResource["dojox.lang.functional.fold"]=true;
 dojo.provide("dojox.lang.functional.fold");
+
 dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+//	- "fold" family of functions
+
+// Notes:
+//	- missing high-level functions are provided with the compatible API: 
+//		foldl, foldl1, foldr, foldr1
+//	- missing JS standard functions are provided with the compatible API: 
+//		reduce, reduceRight
+//	- the fold's counterpart: unfold
+
+// Defined methods:
+//	- take any valid lambda argument as the functional argument
+//	- operate on dense arrays
+//	- take a string as the array argument
+//	- take an iterator objects as the array argument (only foldl, foldl1, and reduce)
+
 (function(){
-var d=dojo,df=dojox.lang.functional,_1={};
-d.mixin(df,{foldl:function(a,f,z,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var i,n;
-if(d.isArray(a)){
-for(i=0,n=a.length;i<n;z=f.call(o,z,a[i],i,a),++i){
-}
-}else{
-if(typeof a.hasNext=="function"&&typeof a.next=="function"){
-for(i=0;a.hasNext();z=f.call(o,z,a.next(),i++,a)){
-}
-}else{
-for(i in a){
-if(!(i in _1)){
-z=f.call(o,z,a[i],i,a);
-}
-}
-}
-}
-return z;
-},foldl1:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var z,i,n;
-if(d.isArray(a)){
-z=a[0];
-for(i=1,n=a.length;i<n;z=f.call(o,z,a[i],i,a),++i){
-}
-}else{
-if(typeof a.hasNext=="function"&&typeof a.next=="function"){
-if(a.hasNext()){
-z=a.next();
-for(i=1;a.hasNext();z=f.call(o,z,a.next(),i++,a)){
-}
-}
-}else{
-var _2=true;
-for(i in a){
-if(!(i in _1)){
-if(_2){
-z=a[i];
-_2=false;
-}else{
-z=f.call(o,z,a[i],i,a);
-}
-}
-}
-}
-}
-return z;
-},foldr:function(a,f,z,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-for(var i=a.length;i>0;--i,z=f.call(o,z,a[i],i,a)){
-}
-return z;
-},foldr1:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var n=a.length,z=a[n-1],i=n-1;
-for(;i>0;--i,z=f.call(o,z,a[i],i,a)){
-}
-return z;
-},reduce:function(a,f,z){
-return arguments.length<3?df.foldl1(a,f):df.foldl(a,f,z);
-},reduceRight:function(a,f,z){
-return arguments.length<3?df.foldr1(a,f):df.foldr(a,f,z);
-},unfold:function(pr,f,g,z,o){
-o=o||d.global;
-f=df.lambda(f);
-g=df.lambda(g);
-pr=df.lambda(pr);
-var t=[];
-for(;!pr.call(o,z);t.push(f.call(o,z)),z=g.call(o,z)){
-}
-return t;
-}});
+	var d = dojo, df = dojox.lang.functional, empty = {};
+
+	d.mixin(df, {
+		// classic reduce-class functions
+		foldl: function(/*Array|String|Object*/ a, /*Function*/ f, /*Object*/ z, /*Object?*/ o){
+			// summary: repeatedly applies a binary function to an array from left
+			//	to right using a seed value as a starting point; returns the final
+			//	value.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var i, n;
+			if(d.isArray(a)){
+				// array
+				for(i = 0, n = a.length; i < n; z = f.call(o, z, a[i], i, a), ++i);
+			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
+				// iterator
+				for(i = 0; a.hasNext(); z = f.call(o, z, a.next(), i++, a));
+			}else{
+				// object/dictionary
+				for(i in a){
+					if(!(i in empty)){
+						z = f.call(o, z, a[i], i, a);
+					}
+				}
+			}
+			return z;	// Object
+		},
+		foldl1: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: repeatedly applies a binary function to an array from left
+			//	to right; returns the final value.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var z, i, n;
+			if(d.isArray(a)){
+				// array
+				z = a[0];
+				for(i = 1, n = a.length; i < n; z = f.call(o, z, a[i], i, a), ++i);
+			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
+				// iterator
+				if(a.hasNext()){
+					z = a.next();
+					for(i = 1; a.hasNext(); z = f.call(o, z, a.next(), i++, a));
+				}
+			}else{
+				// object/dictionary
+				var first = true;
+				for(i in a){
+					if(!(i in empty)){
+						if(first){
+							z = a[i];
+							first = false;
+						}else{
+							z = f.call(o, z, a[i], i, a);
+						}
+					}
+				}
+			}
+			return z;	// Object
+		},
+		foldr: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
+			// summary: repeatedly applies a binary function to an array from right
+			//	to left using a seed value as a starting point; returns the final 
+			//	value.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			for(var i = a.length; i > 0; --i, z = f.call(o, z, a[i], i, a));
+			return z;	// Object
+		},
+		foldr1: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: repeatedly applies a binary function to an array from right
+			//	to left; returns the final value.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var n = a.length, z = a[n - 1], i = n - 1;
+			for(; i > 0; --i, z = f.call(o, z, a[i], i, a));
+			return z;	// Object
+		},
+		// JS 1.8 standard array functions, which can take a lambda as a parameter.
+		reduce: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ z){
+			// summary: apply a function simultaneously against two values of the array
+			//	(from left-to-right) as to reduce it to a single value.
+			return arguments.length < 3 ? df.foldl1(a, f) : df.foldl(a, f, z);	// Object
+		},
+		reduceRight: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ z){
+			// summary: apply a function simultaneously against two values of the array
+			//	(from right-to-left) as to reduce it to a single value.
+			return arguments.length < 3 ? df.foldr1(a, f) : df.foldr(a, f, z);	// Object
+		},
+		// the fold's counterpart: unfold
+		unfold: function(/*Function|String|Array*/ pr, /*Function|String|Array*/ f,
+						/*Function|String|Array*/ g, /*Object*/ z, /*Object?*/ o){
+			// summary: builds an array by unfolding a value
+			o = o || d.global; f = df.lambda(f); g = df.lambda(g); pr = df.lambda(pr);
+			var t = [];
+			for(; !pr.call(o, z); t.push(f.call(o, z)), z = g.call(o, z));
+			return t;	// Array
+		}
+	});
 })();
-}
diff --git a/dojox/lang/functional/lambda.js b/dojox/lang/functional/lambda.js
old mode 100644
new mode 100755
index 9234e1c..c88afae
--- a/dojox/lang/functional/lambda.js
+++ b/dojox/lang/functional/lambda.js
@@ -1,89 +1,130 @@
-/*
-	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
-*/
+dojo.provide("dojox.lang.functional.lambda");
 
+// This module adds high-level functions and related constructs:
+//	- anonymous functions built from the string
+
+// Acknoledgements:
+//	- lambda() is based on work by Oliver Steele 
+//		(http://osteele.com/sources/javascript/functional/functional.js)
+//		which was published under MIT License
+
+// Notes:
+//	- lambda() produces functions, which after the compilation step are 
+//		as fast as regular JS functions (at least theoretically).
+
+// Lambda input values:
+//	- returns functions unchanged
+//	- converts strings to functions
+//	- converts arrays to a functional composition
 
-if(!dojo._hasResource["dojox.lang.functional.lambda"]){
-dojo._hasResource["dojox.lang.functional.lambda"]=true;
-dojo.provide("dojox.lang.functional.lambda");
 (function(){
-var df=dojox.lang.functional,_1={};
-var _2="ab".split(/a*/).length>1?String.prototype.split:function(_3){
-var r=this.split.call(this,_3),m=_3.exec(this);
-if(m&&m.index==0){
-r.unshift("");
-}
-return r;
-};
-var _4=function(s){
-var _5=[],_6=_2.call(s,/\s*->\s*/m);
-if(_6.length>1){
-while(_6.length){
-s=_6.pop();
-_5=_6.pop().split(/\s*,\s*|\s+/m);
-if(_6.length){
-_6.push("(function("+_5+"){return ("+s+")})");
-}
-}
-}else{
-if(s.match(/\b_\b/)){
-_5=["_"];
-}else{
-var l=s.match(/^\s*(?:[+*\/%&|\^\.=<>]|!=)/m),r=s.match(/[+\-*\/%&|\^\.=<>!]\s*$/m);
-if(l||r){
-if(l){
-_5.push("$1");
-s="$1"+s;
-}
-if(r){
-_5.push("$2");
-s=s+"$2";
-}
-}else{
-var _7=s.replace(/(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_$\d]*:|this|true|false|null|undefined|typeof|instanceof|in|delete|new|void|arguments|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|isFinite|isNaN|parseFloat|parseInt|unescape|dojo|dijit|dojox|window|document|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g,"").match(/([a-z_$][a-z_$\d]*)/gi)||[],t={};
-dojo.forEach(_7,function(v){
-if(!(v in t)){
-_5.push(v);
-t[v]=1;
-}
-});
-}
-}
-}
-return {args:_5,body:s};
-};
-var _8=function(a){
-return a.length?function(){
-var i=a.length-1,x=df.lambda(a[i]).apply(this,arguments);
-for(--i;i>=0;--i){
-x=df.lambda(a[i]).call(this,x);
-}
-return x;
-}:function(x){
-return x;
-};
-};
-dojo.mixin(df,{rawLambda:function(s){
-return _4(s);
-},buildLambda:function(s){
-s=_4(s);
-return "function("+s.args.join(",")+"){return ("+s.body+");}";
-},lambda:function(s){
-if(typeof s=="function"){
-return s;
-}
-if(s instanceof Array){
-return _8(s);
-}
-if(s in _1){
-return _1[s];
-}
-s=_4(s);
-return _1[s]=new Function(s.args,"return ("+s.body+");");
-},clearLambdaCache:function(){
-_1={};
-}});
+	var df = dojox.lang.functional, lcache = {};
+
+	// split() is augmented on IE6 to ensure the uniform behavior
+	var split = "ab".split(/a*/).length > 1 ? String.prototype.split :
+			function(sep){
+				 var r = this.split.call(this, sep),
+					 m = sep.exec(this);
+				 if(m && m.index == 0){ r.unshift(""); }
+				 return r;
+			};
+			
+	var lambda = function(/*String*/ s){
+		var args = [], sects = split.call(s, /\s*->\s*/m);
+		if(sects.length > 1){
+			while(sects.length){
+				s = sects.pop();
+				args = sects.pop().split(/\s*,\s*|\s+/m);
+				if(sects.length){ sects.push("(function(" + args + "){return (" + s + ")})"); }
+			}
+		}else if(s.match(/\b_\b/)){
+			args = ["_"];
+		}else{
+			var l = s.match(/^\s*(?:[+*\/%&|\^\.=<>]|!=)/m),
+				r = s.match(/[+\-*\/%&|\^\.=<>!]\s*$/m);
+			if(l || r){
+				if(l){
+					args.push("$1");
+					s = "$1" + s;
+				}
+				if(r){
+					args.push("$2");
+					s = s + "$2";
+				}
+			}else{
+				// the point of the long regex below is to exclude all well-known 
+				// lower-case words from the list of potential arguments
+				var vars = s.
+					replace(/(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_$\d]*:|this|true|false|null|undefined|typeof|instanceof|in|delete|new|void|arguments|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|isFinite|isNaN|parseFloat|parseInt|unescape|dojo|dijit|dojox|window|document|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g, "").
+					match(/([a-z_$][a-z_$\d]*)/gi) || [], t = {};
+				dojo.forEach(vars, function(v){
+					if(!(v in t)){
+						args.push(v);
+						t[v] = 1;
+					}
+				});
+			}
+		}
+		return {args: args, body: s};	// Object
+	};
+
+	var compose = function(/*Array*/ a){
+		return a.length ? 
+					function(){
+						var i = a.length - 1, x = df.lambda(a[i]).apply(this, arguments);
+						for(--i; i >= 0; --i){ x = df.lambda(a[i]).call(this, x); }
+						return x;
+					}
+				: 
+					// identity
+					function(x){ return x; };
+	};
+
+	dojo.mixin(df, {
+		// lambda
+		rawLambda: function(/*String*/ s){
+			// summary:
+			//		builds a function from a snippet, or array (composing),
+			//		returns an object describing the function; functions are
+			//		passed through unmodified.
+			// description:
+			//		This method is to normalize a functional representation (a
+			//		text snippet) to an object that contains an array of
+			//		arguments, and a body , which is used to calculate the
+			//		returning value.
+			return lambda(s);	// Object
+		},
+		buildLambda: function(/*String*/ s){
+			// summary:
+			//		builds a function from a snippet, returns a string, which
+			//		represents the function.
+			// description:
+			//		This method returns a textual representation of a function
+			//		built from the snippet. It is meant to be evaled in the
+			//		proper context, so local variables can be pulled from the
+			//		environment.
+			s = lambda(s);
+			return "function(" + s.args.join(",") + "){return (" + s.body + ");}";	// String
+		},
+		lambda: function(/*Function|String|Array*/ s){
+			// summary:
+			//		builds a function from a snippet, or array (composing),
+			//		returns a function object; functions are passed through
+			//		unmodified.
+			// description:
+			//		This method is used to normalize a functional
+			//		representation (a text snippet, an array, or a function) to
+			//		a function object.
+			if(typeof s == "function"){ return s; }
+			if(s instanceof Array){ return compose(s); }
+			if(s in lcache){ return lcache[s]; }
+			s = lambda(s);
+			return lcache[s] = new Function(s.args, "return (" + s.body + ");");	// Function
+		},
+		clearLambdaCache: function(){
+			// summary:
+			//		clears internal cache of lambdas
+			lcache = {};
+		}
+	});
 })();
-}
diff --git a/dojox/lang/functional/linrec.js b/dojox/lang/functional/linrec.js
index cb9e855..410184a 100644
--- a/dojox/lang/functional/linrec.js
+++ b/dojox/lang/functional/linrec.js
@@ -1,62 +1,143 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.linrec"]){
-dojo._hasResource["dojox.lang.functional.linrec"]=true;
 dojo.provide("dojox.lang.functional.linrec");
+
 dojo.require("dojox.lang.functional.lambda");
 dojo.require("dojox.lang.functional.util");
+
+// This module provides recursion combinators:
+//	- a linear recursion combinator.
+
+// Acknoledgements:
+//	- recursion combinators are inspired by Manfred von Thun's article
+//		"Recursion Theory and Joy"
+//		(http://www.latrobe.edu.au/philosophy/phimvt/joy/j05cmp.html)
+
+// Notes:
+//	- recursion combinators produce a function, which implements
+//	their respective recusion patterns. String lambdas are inlined, if possible.
+
 (function(){
-var df=dojox.lang.functional,_1=df.inlineLambda,_2="_x",_3=["_r","_y.a"];
-df.linrec=function(_4,_5,_6,_7){
-var c,t,b,a,cs,ts,bs,as,_8={},_9={},_a=function(x){
-_8[x]=1;
+	var df = dojox.lang.functional, inline = df.inlineLambda,
+		_x ="_x", _r_y_a = ["_r", "_y.a"];
+
+	df.linrec = function(
+					/*Function|String|Array*/ cond,
+					/*Function|String|Array*/ then,
+					/*Function|String|Array*/ before,
+					/*Function|String|Array*/ after){
+		// summary:
+		//		Generates a function for the linear recursion pattern.
+		//		All parameter functions are called in the context of "this" object.
+		// cond:
+		//		The lambda expression, which is used to detect the termination of recursion.
+		//		It accepts the same parameter as the generated recursive function itself.
+		//		This function should return "true", if the recursion should be stopped,
+		//		and the "then" part should be executed. Otherwise the recursion will proceed.
+		// then:
+		//		The lambda expression, which is called upon termination of the recursion.
+		//		It accepts the same parameters as the generated recursive function itself.
+		//		The returned value will be returned as the value of the generated function.
+		// before:
+		//		The lambda expression, which is called before the recursive step.
+		//		It accepts the same parameter as the generated recursive function itself.
+		//		The returned value should be an array, which is used to call
+		//		the generated function recursively.
+		// above:
+		//		The lambda expression, which is called after the recursive step.
+		//		It accepts two parameters: the returned value from the recursive step, and
+		//		the original array of parameters used with all other functions.
+		//		The returned value will be returned as the value of the generated function.
+
+		var c, t, b, a, cs, ts, bs, as, dict1 = {}, dict2 = {},
+			add2dict = function(x){ dict1[x] = 1; };
+		if(typeof cond == "string"){
+			cs = inline(cond, _x, add2dict);
+		}else{
+			c = df.lambda(cond);
+			cs = "_c.apply(this, _x)";
+			dict2["_c=_t.c"] = 1;
+		}
+		if(typeof then == "string"){
+			ts = inline(then, _x, add2dict);
+		}else{
+			t = df.lambda(then);
+			ts = "_t.t.apply(this, _x)";
+		}
+		if(typeof before == "string"){
+			bs = inline(before, _x, add2dict);
+		}else{
+			b = df.lambda(before);
+			bs = "_b.apply(this, _x)";
+			dict2["_b=_t.b"] = 1;
+		}
+		if(typeof after == "string"){
+			as = inline(after, _r_y_a, add2dict);
+		}else{
+			a = df.lambda(after);
+			as = "_a.call(this, _r, _y.a)";
+			dict2["_a=_t.a"] = 1;
+		}
+		var locals1 = df.keys(dict1), locals2 = df.keys(dict2),
+			f = new Function([], "var _x=arguments,_y,_r".concat(	// Function
+				locals1.length ? "," + locals1.join(",") : "",
+				locals2.length ? ",_t=_x.callee," + locals2.join(",") : t ? ",_t=_x.callee" : "",
+				";for(;!",
+				cs,
+				";_x=",
+				bs,
+				"){_y={p:_y,a:_x}}_r=",
+				ts,
+				";for(;_y;_y=_y.p){_r=",
+				as,
+				"}return _r"
+			));
+		if(c){ f.c = c; }
+		if(t){ f.t = t; }
+		if(b){ f.b = b; }
+		if(a){ f.a = a; }
+		return f;
+	};
+})();
+
+/*
+For documentation only:
+
+1) The original recursive version:
+
+var linrec1 = function(cond, then, before, after){
+	var cond   = df.lambda(cond),
+		then   = df.lambda(then),
+		before = df.lambda(before),
+		after  = df.lambda(after);
+	return function(){
+		if(cond.apply(this, arguments)){
+			return then.apply(this, arguments);
+		}
+		var args = before.apply(this, arguments);
+		var ret  = arguments.callee.apply(this, args);
+		return after.call(this, ret, arguments);
+	};
 };
-if(typeof _4=="string"){
-cs=_1(_4,_2,_a);
-}else{
-c=df.lambda(_4);
-cs="_c.apply(this, _x)";
-_9["_c=_t.c"]=1;
-}
-if(typeof _5=="string"){
-ts=_1(_5,_2,_a);
-}else{
-t=df.lambda(_5);
-ts="_t.t.apply(this, _x)";
-}
-if(typeof _6=="string"){
-bs=_1(_6,_2,_a);
-}else{
-b=df.lambda(_6);
-bs="_b.apply(this, _x)";
-_9["_b=_t.b"]=1;
-}
-if(typeof _7=="string"){
-as=_1(_7,_3,_a);
-}else{
-a=df.lambda(_7);
-as="_a.call(this, _r, _y.a)";
-_9["_a=_t.a"]=1;
-}
-var _b=df.keys(_8),_c=df.keys(_9),f=new Function([],"var _x=arguments,_y,_r".concat(_b.length?","+_b.join(","):"",_c.length?",_t=_x.callee,"+_c.join(","):t?",_t=_x.callee":"",";for(;!",cs,";_x=",bs,"){_y={p:_y,a:_x}}_r=",ts,";for(;_y;_y=_y.p){_r=",as,"}return _r"));
-if(c){
-f.c=c;
-}
-if(t){
-f.t=t;
-}
-if(b){
-f.b=b;
-}
-if(a){
-f.a=a;
-}
-return f;
+
+2) The original iterative version (before minification and inlining):
+
+var linrec2 = function(cond, then, before, after){
+	var cond   = df.lambda(cond),
+		then   = df.lambda(then),
+		before = df.lambda(before),
+		after  = df.lambda(after);
+	return function(){
+		var args = arguments, top, ret;
+		// 1st part
+		for(; !cond.apply(this, args); args = before.apply(this, args)){
+			top = {prev: top, args: args};
+		}
+		ret = then.apply(this, args);
+		//2nd part
+		for(; top; top = top.prev){
+			ret = after.call(this, ret, top.args);
+		}
+		return ret;
+	};
 };
-})();
-}
+
+*/
\ No newline at end of file
diff --git a/dojox/lang/functional/listcomp.js b/dojox/lang/functional/listcomp.js
old mode 100644
new mode 100755
index 112032b..12c804c
--- a/dojox/lang/functional/listcomp.js
+++ b/dojox/lang/functional/listcomp.js
@@ -1,33 +1,50 @@
-/*
-	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
-*/
+dojo.provide("dojox.lang.functional.listcomp");
 
+// This module adds high-level functions and related constructs:
+//	- list comprehensions similar to JavaScript 1.7
+
+// Notes:
+//	- listcomp() produces functions, which after the compilation step are 
+//		as fast as regular JS functions (at least theoretically).
 
-if(!dojo._hasResource["dojox.lang.functional.listcomp"]){
-dojo._hasResource["dojox.lang.functional.listcomp"]=true;
-dojo.provide("dojox.lang.functional.listcomp");
 (function(){
-var _1=/\bfor\b|\bif\b/gm;
-var _2=function(s){
-var _3=s.split(_1),_4=s.match(_1),_5=["var r = [];"],_6=[],i=0,l=_4.length;
-while(i<l){
-var a=_4[i],f=_3[++i];
-if(a=="for"&&!/^\s*\(\s*(;|var)/.test(f)){
-f=f.replace(/^\s*\(/,"(var ");
-}
-_5.push(a,f,"{");
-_6.push("}");
-}
-return _5.join("")+"r.push("+_3[0]+");"+_6.join("")+"return r;";
-};
-dojo.mixin(dojox.lang.functional,{buildListcomp:function(s){
-return "function(){"+_2(s)+"}";
-},compileListcomp:function(s){
-return new Function([],_2(s));
-},listcomp:function(s){
-return (new Function([],_2(s)))();
-}});
+	var g_re = /\bfor\b|\bif\b/gm;
+
+	var listcomp = function(/*String*/ s){
+		var frag = s.split(g_re), act = s.match(g_re),
+			head = ["var r = [];"], tail = [], i = 0, l = act.length;
+		while(i < l){
+			var a = act[i], f = frag[++i];
+			if(a == "for" && !/^\s*\(\s*(;|var)/.test(f)){
+				f = f.replace(/^\s*\(/, "(var ");
+			}
+			head.push(a, f, "{");
+			tail.push("}");
+		}
+		return head.join("") + "r.push(" + frag[0] + ");" + tail.join("") + "return r;";	// String
+	};
+
+	dojo.mixin(dojox.lang.functional, {
+		buildListcomp: function(/*String*/ s){
+			// summary: builds a function from a text snippet, which represents a valid
+			//	JS 1.7 list comprehension, returns a string, which represents the function.
+			// description: This method returns a textual representation of a function 
+			//	built from the list comprehension text snippet (conformant to JS 1.7). 
+			//	It is meant to be evaled in the proper context, so local variable can be 
+			//	pulled from the environment.
+			return "function(){" + listcomp(s) + "}";	// String
+		},
+		compileListcomp: function(/*String*/ s){
+			// summary: builds a function from a text snippet, which represents a valid
+			//	JS 1.7 list comprehension, returns a function object.
+			// description: This method returns a function built from the list 
+			//	comprehension text snippet (conformant to JS 1.7). It is meant to be 
+			//	reused several times.
+			return new Function([], listcomp(s));	// Function
+		},
+		listcomp: function(/*String*/ s){
+			// summary: executes the list comprehension building an array.
+			return (new Function([], listcomp(s)))();	// Array
+		}
+	});
 })();
-}
diff --git a/dojox/lang/functional/multirec.js b/dojox/lang/functional/multirec.js
index f28a807..e3f2566 100644
--- a/dojox/lang/functional/multirec.js
+++ b/dojox/lang/functional/multirec.js
@@ -1,62 +1,164 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.multirec"]){
-dojo._hasResource["dojox.lang.functional.multirec"]=true;
 dojo.provide("dojox.lang.functional.multirec");
+
 dojo.require("dojox.lang.functional.lambda");
 dojo.require("dojox.lang.functional.util");
+
+// This module provides recursion combinators:
+//	- a multi-way recursion combinator.
+
+// Acknoledgements:
+//	- recursion combinators are inspired by Manfred von Thun's article
+//		"Recursion Theory and Joy"
+//		(http://www.latrobe.edu.au/philosophy/phimvt/joy/j05cmp.html)
+
+// Notes:
+//	- recursion combinators produce a function, which implements
+//	their respective recusion patterns. String lambdas are inlined, if possible.
+
 (function(){
-var df=dojox.lang.functional,_1=df.inlineLambda,_2="_x",_3=["_y.r","_y.o"];
-df.multirec=function(_4,_5,_6,_7){
-var c,t,b,a,cs,ts,bs,as,_8={},_9={},_a=function(x){
-_8[x]=1;
+	var df = dojox.lang.functional, inline = df.inlineLambda,
+		_x ="_x", _y_r_y_o = ["_y.r", "_y.o"];
+
+	df.multirec = function(
+					/*Function|String|Array*/ cond,
+					/*Function|String|Array*/ then,
+					/*Function|String|Array*/ before,
+					/*Function|String|Array*/ after){
+		// summary:
+		//		Generates a function for the multi-way recursion pattern.
+		//		All parameter functions are called in the context of "this" object.
+		// cond:
+		//		The lambda expression, which is used to detect the termination of recursion.
+		//		It accepts the same parameter as the generated recursive function itself.
+		//		This function should return "true", if the recursion should be stopped,
+		//		and the "then" part should be executed. Otherwise the recursion will proceed.
+		// then:
+		//		The lambda expression, which is called upon termination of the recursion.
+		//		It accepts the same parameters as the generated recursive function itself.
+		//		The returned value will be returned as the value of the generated function.
+		// before:
+		//		The lambda expression, which is called before the recursive step.
+		//		It accepts the same parameter as the generated recursive function itself.
+		//		The returned value should be an array, which is used to call
+		//		the generated function recursively. Each member of the array should be
+		//		an array of parameters. The length of it defines how many times
+		//		the generated function is called recursively.
+		// above:
+		//		The lambda expression, which is called after the recursive step.
+		//		It accepts two parameters: the array of returned values from recursive steps,
+		//		and the original array of parameters used with all other functions.
+		//		The returned value will be returned as the value of the generated function.
+
+		var c, t, b, a, cs, ts, bs, as, dict1 = {}, dict2 = {},
+			add2dict = function(x){ dict1[x] = 1; };
+		if(typeof cond == "string"){
+			cs = inline(cond, _x, add2dict);
+		}else{
+			c = df.lambda(cond);
+			cs = "_c.apply(this, _x)";
+			dict2["_c=_t.c"] = 1;
+		}
+		if(typeof then == "string"){
+			ts = inline(then, _x, add2dict);
+		}else{
+			t = df.lambda(then);
+			ts = "_t.apply(this, _x)";
+		}
+		if(typeof before == "string"){
+			bs = inline(before, _x, add2dict);
+		}else{
+			b = df.lambda(before);
+			bs = "_b.apply(this, _x)";
+			dict2["_b=_t.b"] = 1;
+		}
+		if(typeof after == "string"){
+			as = inline(after, _y_r_y_o, add2dict);
+		}else{
+			a = df.lambda(after);
+			as = "_a.call(this, _y.r, _y.o)";
+			dict2["_a=_t.a"] = 1;
+		}
+		var locals1 = df.keys(dict1), locals2 = df.keys(dict2),
+			f = new Function([], "var _y={a:arguments},_x,_r,_z,_i".concat(	// Function
+				locals1.length ? "," + locals1.join(",") : "",
+				locals2.length ? ",_t=arguments.callee," + locals2.join(",") : "",
+				t ? (locals2.length ? ",_t=_t.t" : "_t=arguments.callee.t") : "",
+				";for(;;){for(;;){if(_y.o){_r=",
+				as,
+				";break}_x=_y.a;if(",
+				cs,
+				"){_r=",
+				ts,
+				";break}_y.o=_x;_x=",
+				bs,
+				";_y.r=[];_z=_y;for(_i=_x.length-1;_i>=0;--_i){_y={p:_y,a:_x[_i],z:_z}}}if(!(_z=_y.z)){return _r}_z.r.push(_r);_y=_y.p}"
+			));
+		if(c){ f.c = c; }
+		if(t){ f.t = t; }
+		if(b){ f.b = b; }
+		if(a){ f.a = a; }
+		return f;
+	};
+})();
+
+/*
+For documentation only:
+
+1) The original recursive version:
+
+var multirec1 = function(cond, then, before, after){
+	var cond   = df.lambda(cond),
+		then   = df.lambda(then),
+		before = df.lambda(before),
+		after  = df.lambda(after);
+	return function(){
+		if(cond.apply(this, arguments)){
+			return then.apply(this, arguments);
+		}
+		var args = before.apply(this, arguments),
+			ret  = new Array(args.length);
+		for(var i = 0; i < args.length; ++i){
+			ret[i] = arguments.callee.apply(this, args[i]);
+		}
+		return after.call(this, ret, arguments);
+	};
 };
-if(typeof _4=="string"){
-cs=_1(_4,_2,_a);
-}else{
-c=df.lambda(_4);
-cs="_c.apply(this, _x)";
-_9["_c=_t.c"]=1;
-}
-if(typeof _5=="string"){
-ts=_1(_5,_2,_a);
-}else{
-t=df.lambda(_5);
-ts="_t.apply(this, _x)";
-}
-if(typeof _6=="string"){
-bs=_1(_6,_2,_a);
-}else{
-b=df.lambda(_6);
-bs="_b.apply(this, _x)";
-_9["_b=_t.b"]=1;
-}
-if(typeof _7=="string"){
-as=_1(_7,_3,_a);
-}else{
-a=df.lambda(_7);
-as="_a.call(this, _y.r, _y.o)";
-_9["_a=_t.a"]=1;
-}
-var _b=df.keys(_8),_c=df.keys(_9),f=new Function([],"var _y={a:arguments},_x,_r,_z,_i".concat(_b.length?","+_b.join(","):"",_c.length?",_t=arguments.callee,"+_c.join(","):"",t?(_c.length?",_t=_t.t":"_t=arguments.callee.t"):"",";for(;;){for(;;){if(_y.o){_r=",as,";break}_x=_y.a;if(",cs,"){_r=",ts,";break}_y.o=_x;_x=",bs,";_y.r=[];_z=_y;for(_i=_x.length-1;_i>=0;--_i){_y={p:_y,a:_x[_i],z:_z}}}if(!(_z=_y.z)){return _r}_z.r.push(_r);_y=_y.p}"));
-if(c){
-f.c=c;
-}
-if(t){
-f.t=t;
-}
-if(b){
-f.b=b;
-}
-if(a){
-f.a=a;
-}
-return f;
+
+2) The original iterative version (before minification and inlining):
+
+var multirec2 = function(cond, then, before, after){
+	var cond   = df.lambda(cond),
+		then   = df.lambda(then),
+		before = df.lambda(before),
+		after  = df.lambda(after);
+	return function(){
+		var top = {args: arguments}, args, ret, parent, i;
+		for(;;){
+			for(;;){
+				if(top.old){
+					ret = after.call(this, top.ret, top.old);
+					break;
+				}
+				args = top.args;
+				if(cond.apply(this, args)){
+					ret = then.apply(this, args);
+					break;
+				}
+				top.old = args;
+				args = before.apply(this, args);
+				top.ret = [];
+				parent = top;
+				for(i = args.length - 1; i >= 0; --i){
+					top = {prev: top, args: args[i], parent: parent};
+				}
+			}
+			if(!(parent = top.parent)){
+				return ret;
+			}
+			parent.ret.push(ret);
+			top = top.prev;
+		}
+	};
 };
-})();
-}
+
+*/
diff --git a/dojox/lang/functional/numrec.js b/dojox/lang/functional/numrec.js
index 434caf8..a0092ba 100644
--- a/dojox/lang/functional/numrec.js
+++ b/dojox/lang/functional/numrec.js
@@ -1,33 +1,91 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.numrec"]){
-dojo._hasResource["dojox.lang.functional.numrec"]=true;
 dojo.provide("dojox.lang.functional.numrec");
+
 dojo.require("dojox.lang.functional.lambda");
 dojo.require("dojox.lang.functional.util");
+
+// This module provides recursion combinators:
+//	- a simplified numeric linear recursion combinator.
+
+// Acknoledgements:
+//	- recursion combinators are inspired by Manfred von Thun's article
+//		"Recursion Theory and Joy"
+//		(http://www.latrobe.edu.au/philosophy/phimvt/joy/j05cmp.html)
+
+// Notes:
+//	- recursion combinators produce a function, which implements
+//	their respective recusion patterns. String lambdas are inlined, if possible.
+
 (function(){
-var df=dojox.lang.functional,_1=df.inlineLambda,_2=["_r","_i"];
-df.numrec=function(_3,_4){
-var a,as,_5={},_6=function(x){
-_5[x]=1;
+	var df = dojox.lang.functional, inline = df.inlineLambda,
+		_r_i = ["_r", "_i"];
+
+	df.numrec = function(/*Object*/ then, /*Function|String|Array*/ after){
+		// summary:
+		//		Generates a function for the simplified numeric linear recursion pattern.
+		//		All parameter functions are called in the context of "this" object.
+		// description:
+		//		This is a simplification of the linear recursion combinator:
+		//		- the generated function takes one numeric parameter "x",
+		//		- the "cond" is fixed and checks for 0.
+		//		- the "before" is fixed and the generated function is called with "x - 1".
+		//		- the "above is called with two parameters: the return from the generated
+		//		function, and with "x".
+		//		- as you can see the recursion is done by decreasing the parameter,
+		//		and calling itself until it reaches 0.
+		// then:
+		//		The value, which is used upon termination of the recursion.
+		//		It will be returned as the value of the generated function.
+		// above:
+		//		The lambda expression, which is called after the recursive step.
+		//		It accepts two parameters: the returned value from the recursive step, and
+		//		the original parameter. The returned value will be returned as the value of
+		//		the generated function.
+
+		var a, as, dict = {},
+			add2dict = function(x){ dict[x] = 1; };
+		if(typeof after == "string"){
+			as = inline(after, _r_i, add2dict);
+		}else{
+			a = df.lambda(after);
+			as = "_a.call(this, _r, _i)";
+		}
+		var locals = df.keys(dict),
+			f = new Function(["_x"], "var _t=arguments.callee,_r=_t.t,_i".concat(	// Function
+				locals.length ? "," + locals.join(",") : "",
+				a ? ",_a=_t.a" : "",
+				";for(_i=1;_i<=_x;++_i){_r=",
+				as,
+				"}return _r"
+			));
+		f.t = then;
+		if(a){ f.a = a; }
+		return f;
+	};
+})();
+
+/*
+For documentation only:
+
+1) The original recursive version:
+
+var numrec1 = function(then, after){
+	var after = df.lambda(after);
+	return function(x){
+		return x ? after.call(this, arguments.callee.call(this, x - 1), x) : then;
+	};
 };
-if(typeof _4=="string"){
-as=_1(_4,_2,_6);
-}else{
-a=df.lambda(_4);
-as="_a.call(this, _r, _i)";
-}
-var _7=df.keys(_5),f=new Function(["_x"],"var _t=arguments.callee,_r=_t.t,_i".concat(_7.length?","+_7.join(","):"",a?",_a=_t.a":"",";for(_i=1;_i<=_x;++_i){_r=",as,"}return _r"));
-f.t=_3;
-if(a){
-f.a=a;
-}
-return f;
+
+2) The original iterative version (before minification and inlining):
+
+var numrec2 = function(then, after){
+	var after = df.lambda(after);
+	return function(x){
+		var ret = then, i;
+		for(i = 1; i <= x; ++i){
+			ret = after.call(this, ret, i);
+		}
+		return ret;
+	};
 };
-})();
-}
+
+*/
\ No newline at end of file
diff --git a/dojox/lang/functional/object.js b/dojox/lang/functional/object.js
old mode 100644
new mode 100755
index 0146e79..63227c7
--- a/dojox/lang/functional/object.js
+++ b/dojox/lang/functional/object.js
@@ -1,64 +1,74 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.object"]){
-dojo._hasResource["dojox.lang.functional.object"]=true;
 dojo.provide("dojox.lang.functional.object");
+
 dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+//	- object/dictionary helpers
+
+// Defined methods:
+//	- take any valid lambda argument as the functional argument
+//	- skip all attributes that are present in the empty object 
+//		(IE and/or 3rd-party libraries).
+
 (function(){
-var d=dojo,df=dojox.lang.functional,_1={};
-d.mixin(df,{keys:function(_2){
-var t=[];
-for(var i in _2){
-if(!(i in _1)){
-t.push(i);
-}
-}
-return t;
-},values:function(_3){
-var t=[];
-for(var i in _3){
-if(!(i in _1)){
-t.push(_3[i]);
-}
-}
-return t;
-},filterIn:function(_4,f,o){
-o=o||d.global;
-f=df.lambda(f);
-var t={},v,i;
-for(i in _4){
-if(!(i in _1)){
-v=_4[i];
-if(f.call(o,v,i,_4)){
-t[i]=v;
-}
-}
-}
-return t;
-},forIn:function(_5,f,o){
-o=o||d.global;
-f=df.lambda(f);
-for(var i in _5){
-if(!(i in _1)){
-f.call(o,_5[i],i,_5);
-}
-}
-return o;
-},mapIn:function(_6,f,o){
-o=o||d.global;
-f=df.lambda(f);
-var t={},i;
-for(i in _6){
-if(!(i in _1)){
-t[i]=f.call(o,_6[i],i,_6);
-}
-}
-return t;
-}});
+	var d = dojo, df = dojox.lang.functional, empty = {};
+
+	d.mixin(df, {
+		// object helpers
+		keys: function(/*Object*/ obj){
+			// summary: returns an array of all keys in the object
+			var t = [];
+			for(var i in obj){
+				if(!(i in empty)){
+					t.push(i);
+				}
+			}
+			return	t; // Array
+		},
+		values: function(/*Object*/ obj){
+			// summary: returns an array of all values in the object
+			var t = [];
+			for(var i in obj){
+				if(!(i in empty)){
+					t.push(obj[i]);
+				}
+			}
+			return	t; // Array
+		},
+		filterIn: function(/*Object*/ obj, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: creates new object with all attributes that pass the test 
+			//	implemented by the provided function.
+			o = o || d.global; f = df.lambda(f);
+			var t = {}, v, i;
+			for(i in obj){
+				if(!(i in empty)){
+					v = obj[i];
+					if(f.call(o, v, i, obj)){ t[i] = v; }
+				}
+			}
+			return t;	// Object
+		},
+		forIn: function(/*Object*/ obj, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: iterates over all object attributes.
+			o = o || d.global; f = df.lambda(f);
+			for(var i in obj){
+				if(!(i in empty)){
+					f.call(o, obj[i], i, obj);
+				}
+			}
+			return o;	// Object
+		},
+		mapIn: function(/*Object*/ obj, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: creates new object with the results of calling 
+			//	a provided function on every attribute in this object.
+			o = o || d.global; f = df.lambda(f);
+			var t = {}, i;
+			for(i in obj){
+				if(!(i in empty)){
+					t[i] = f.call(o, obj[i], i, obj);
+				}
+			}
+			return t;	// Object
+		}
+	});
 })();
-}
diff --git a/dojox/lang/functional/reversed.js b/dojox/lang/functional/reversed.js
old mode 100644
new mode 100755
index 4baea00..575a0a5
--- a/dojox/lang/functional/reversed.js
+++ b/dojox/lang/functional/reversed.js
@@ -1,72 +1,75 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.reversed"]){
-dojo._hasResource["dojox.lang.functional.reversed"]=true;
 dojo.provide("dojox.lang.functional.reversed");
+
 dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+//	- reversed versions of array-processing functions similar to standard JS functions
+
+// Notes:
+//	- this module provides reversed versions of standard array-processing functions: 
+//		forEachRev, mapRev, filterRev
+
+// Defined methods:
+//	- take any valid lambda argument as the functional argument
+//	- operate on dense arrays
+//	- take a string as the array argument
+
 (function(){
-var d=dojo,df=dojox.lang.functional;
-d.mixin(df,{filterRev:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var t=[],v,i=a.length-1;
-for(;i>=0;--i){
-v=a[i];
-if(f.call(o,v,i,a)){
-t.push(v);
-}
-}
-return t;
-},forEachRev:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-for(var i=a.length-1;i>=0;f.call(o,a[i],i,a),--i){
-}
-},mapRev:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var n=a.length,t=new Array(n),i=n-1,j=0;
-for(;i>=0;t[j++]=f.call(o,a[i],i,a),--i){
-}
-return t;
-},everyRev:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-for(var i=a.length-1;i>=0;--i){
-if(!f.call(o,a[i],i,a)){
-return false;
-}
-}
-return true;
-},someRev:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-for(var i=a.length-1;i>=0;--i){
-if(f.call(o,a[i],i,a)){
-return true;
-}
-}
-return false;
-}});
+	var d = dojo, df = dojox.lang.functional;
+
+	d.mixin(df, {
+		// JS 1.6 standard array functions, which can take a lambda as a parameter.
+		// Consider using dojo._base.array functions, if you don't need the lambda support.
+		filterRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: creates a new array with all elements that pass the test 
+			//	implemented by the provided function.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var t = [], v, i = a.length - 1;
+			for(; i >= 0; --i){
+				v = a[i];
+				if(f.call(o, v, i, a)){ t.push(v); }
+			}
+			return t;	// Array
+		},
+		forEachRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: executes a provided function once per array element.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			for(var i = a.length - 1; i >= 0; f.call(o, a[i], i, a), --i);
+		},
+		mapRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: creates a new array with the results of calling 
+			//	a provided function on every element in this array.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var n = a.length, t = new Array(n), i = n - 1, j = 0;
+			for(; i >= 0; t[j++] = f.call(o, a[i], i, a), --i);
+			return t;	// Array
+		},
+		everyRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: tests whether all elements in the array pass the test 
+			//	implemented by the provided function.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			for(var i = a.length - 1; i >= 0; --i){
+				if(!f.call(o, a[i], i, a)){
+					return false;	// Boolean
+				}
+			}
+			return true;	// Boolean
+		},
+		someRev: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: tests whether some element in the array passes the test 
+			//	implemented by the provided function.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			for(var i = a.length - 1; i >= 0; --i){
+				if(f.call(o, a[i], i, a)){
+					return true;	// Boolean
+				}
+			}
+			return false;	// Boolean
+		}
+	});
 })();
-}
diff --git a/dojox/lang/functional/scan.js b/dojox/lang/functional/scan.js
old mode 100644
new mode 100755
index c46eec2..25864a2
--- a/dojox/lang/functional/scan.js
+++ b/dojox/lang/functional/scan.js
@@ -1,98 +1,106 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.scan"]){
-dojo._hasResource["dojox.lang.functional.scan"]=true;
 dojo.provide("dojox.lang.functional.scan");
+
 dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+//	- "scan" family of functions
+
+// Notes:
+//	- missing high-level functions are provided with the compatible API: 
+//		scanl, scanl1, scanr, scanr1
+
+// Defined methods:
+//	- take any valid lambda argument as the functional argument
+//	- operate on dense arrays
+//	- take a string as the array argument
+//	- take an iterator objects as the array argument (only scanl, and scanl1)
+
 (function(){
-var d=dojo,df=dojox.lang.functional,_1={};
-d.mixin(df,{scanl:function(a,f,z,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var t,n,i;
-if(d.isArray(a)){
-t=new Array((n=a.length)+1);
-t[0]=z;
-for(i=0;i<n;z=f.call(o,z,a[i],i,a),t[++i]=z){
-}
-}else{
-if(typeof a.hasNext=="function"&&typeof a.next=="function"){
-t=[z];
-for(i=0;a.hasNext();t.push(z=f.call(o,z,a.next(),i++,a))){
-}
-}else{
-t=[z];
-for(i in a){
-if(!(i in _1)){
-t.push(z=f.call(o,z,a[i],i,a));
-}
-}
-}
-}
-return t;
-},scanl1:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var t,n,z,_2=true;
-if(d.isArray(a)){
-t=new Array(n=a.length);
-t[0]=z=a[0];
-for(var i=1;i<n;t[i]=z=f.call(o,z,a[i],i,a),++i){
-}
-}else{
-if(typeof a.hasNext=="function"&&typeof a.next=="function"){
-if(a.hasNext()){
-t=[z=a.next()];
-for(var i=1;a.hasNext();t.push(z=f.call(o,z,a.next(),i++,a))){
-}
-}
-}else{
-for(var i in a){
-if(!(i in _1)){
-if(_2){
-t=[z=a[i]];
-_2=false;
-}else{
-t.push(z=f.call(o,z,a[i],i,a));
-}
-}
-}
-}
-}
-return t;
-},scanr:function(a,f,z,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var n=a.length,t=new Array(n+1),i=n;
-t[n]=z;
-for(;i>0;--i,z=f.call(o,z,a[i],i,a),t[i]=z){
-}
-return t;
-},scanr1:function(a,f,o){
-if(typeof a=="string"){
-a=a.split("");
-}
-o=o||d.global;
-f=df.lambda(f);
-var n=a.length,t=new Array(n),z=a[n-1],i=n-1;
-t[i]=z;
-for(;i>0;--i,z=f.call(o,z,a[i],i,a),t[i]=z){
-}
-return t;
-}});
+	var d = dojo, df = dojox.lang.functional, empty = {};
+
+	d.mixin(df, {
+		// classic reduce-class functions
+		scanl: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
+			// summary: repeatedly applies a binary function to an array from left 
+			//	to right using a seed value as a starting point; returns an array
+			//	of values produced by foldl() at that point.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var t, n, i;
+			if(d.isArray(a)){
+				// array
+				t = new Array((n = a.length) + 1);
+				t[0] = z;
+				for(i = 0; i < n; z = f.call(o, z, a[i], i, a), t[++i] = z);
+			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
+				// iterator
+				t = [z];
+				for(i = 0; a.hasNext(); t.push(z = f.call(o, z, a.next(), i++, a)));
+			}else{
+				// object/dictionary
+				t = [z];
+				for(i in a){
+					if(!(i in empty)){
+						t.push(z = f.call(o, z, a[i], i, a));
+					}
+				}
+			}
+			return t;	// Array
+		},
+		scanl1: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: repeatedly applies a binary function to an array from left 
+			//	to right; returns an array of values produced by foldl1() at that 
+			//	point.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var t, n, z, first = true;
+			if(d.isArray(a)){
+				// array
+				t = new Array(n = a.length);
+				t[0] = z = a[0];
+				for(var i = 1; i < n; t[i] = z = f.call(o, z, a[i], i, a), ++i);
+			}else if(typeof a.hasNext == "function" && typeof a.next == "function"){
+				// iterator
+				if(a.hasNext()){
+					t = [z = a.next()];
+					for(var i = 1; a.hasNext(); t.push(z = f.call(o, z, a.next(), i++, a)));
+				}
+			}else{
+				// object/dictionary
+				for(var i in a){
+					if(!(i in empty)){
+						if(first){
+							t = [z = a[i]];
+							first = false;
+						}else{
+							t.push(z = f.call(o, z, a[i], i, a));
+						}
+					}
+				}
+			}
+			return t;	// Array
+		},
+		scanr: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
+			// summary: repeatedly applies a binary function to an array from right
+			//	to left using a seed value as a starting point; returns an array
+			//	of values produced by foldr() at that point.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var n = a.length, t = new Array(n + 1), i = n;
+			t[n] = z;
+			for(; i > 0; --i, z = f.call(o, z, a[i], i, a), t[i] = z);
+			return t;	// Array
+		},
+		scanr1: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
+			// summary: repeatedly applies a binary function to an array from right
+			//	to left; returns an array of values produced by foldr1() at that 
+			//	point.
+			if(typeof a == "string"){ a = a.split(""); }
+			o = o || d.global; f = df.lambda(f);
+			var n = a.length, t = new Array(n), z = a[n - 1], i = n - 1;
+			t[i] = z;
+			for(; i > 0; --i, z = f.call(o, z, a[i], i, a), t[i] = z);
+			return t;	// Array
+		}
+	});
 })();
-}
diff --git a/dojox/lang/functional/sequence.js b/dojox/lang/functional/sequence.js
old mode 100644
new mode 100755
index 210e222..7e03054
--- a/dojox/lang/functional/sequence.js
+++ b/dojox/lang/functional/sequence.js
@@ -1,32 +1,37 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.sequence"]){
-dojo._hasResource["dojox.lang.functional.sequence"]=true;
 dojo.provide("dojox.lang.functional.sequence");
+
 dojo.require("dojox.lang.functional.lambda");
+
+// This module adds high-level functions and related constructs:
+//	- sequence generators
+
+// If you want more general sequence builders check out listcomp.js and
+// unfold() (in fold.js).
+
+// Defined methods:
+//	- take any valid lambda argument as the functional argument
+
 (function(){
-var d=dojo,df=dojox.lang.functional;
-d.mixin(df,{repeat:function(n,f,z,o){
-o=o||d.global;
-f=df.lambda(f);
-var t=new Array(n),i=1;
-t[0]=z;
-for(;i<n;t[i]=z=f.call(o,z),++i){
-}
-return t;
-},until:function(pr,f,z,o){
-o=o||d.global;
-f=df.lambda(f);
-pr=df.lambda(pr);
-var t=[];
-for(;!pr.call(o,z);t.push(z),z=f.call(o,z)){
-}
-return t;
-}});
+	var d = dojo, df = dojox.lang.functional;
+
+	d.mixin(df, {
+		// sequence generators
+		repeat: function(/*Number*/ n, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
+			// summary: builds an array by repeatedly applying a unary function N times
+			//	with a seed value Z. N should be greater than 0.
+			o = o || d.global; f = df.lambda(f);
+			var t = new Array(n), i = 1;
+			t[0] = z;
+			for(; i < n; t[i] = z = f.call(o, z), ++i);
+			return t;	// Array
+		},
+		until: function(/*Function|String|Array*/ pr, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
+			// summary: builds an array by repeatedly applying a unary function with
+			//	a seed value Z until the predicate is satisfied.
+			o = o || d.global; f = df.lambda(f); pr = df.lambda(pr);
+			var t = [];
+			for(; !pr.call(o, z); t.push(z), z = f.call(o, z));
+			return t;	// Array
+		}
+	});
 })();
-}
diff --git a/dojox/lang/functional/tailrec.js b/dojox/lang/functional/tailrec.js
index 7d064e1..c6e7f5d 100644
--- a/dojox/lang/functional/tailrec.js
+++ b/dojox/lang/functional/tailrec.js
@@ -1,52 +1,116 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.tailrec"]){
-dojo._hasResource["dojox.lang.functional.tailrec"]=true;
 dojo.provide("dojox.lang.functional.tailrec");
+
 dojo.require("dojox.lang.functional.lambda");
 dojo.require("dojox.lang.functional.util");
+
+// This module provides recursion combinators:
+//	- a tail recursion combinator.
+
+// Acknoledgements:
+//	- recursion combinators are inspired by Manfred von Thun's article
+//		"Recursion Theory and Joy"
+//		(http://www.latrobe.edu.au/philosophy/phimvt/joy/j05cmp.html)
+
+// Notes:
+//	- recursion combinators produce a function, which implements
+//	their respective recusion patterns. String lambdas are inlined, if possible.
+
 (function(){
-var df=dojox.lang.functional,_1=df.inlineLambda,_2="_x";
-df.tailrec=function(_3,_4,_5){
-var c,t,b,cs,ts,bs,_6={},_7={},_8=function(x){
-_6[x]=1;
+	var df = dojox.lang.functional, inline = df.inlineLambda, _x ="_x";
+
+	df.tailrec = function(
+					/*Function|String|Array*/ cond,
+					/*Function|String|Array*/ then,
+					/*Function|String|Array*/ before){
+		// summary:
+		//		Generates a function for the tail recursion pattern. This is the simplified
+		//		version of the linear recursive combinator without the "after" function,
+		//		and with the modified "before" function. All parameter functions are called
+		//		in the context of "this" object.
+		// cond:
+		//		The lambda expression, which is used to detect the termination of recursion.
+		//		It accepts the same parameter as the generated recursive function itself.
+		//		This function should return "true", if the recursion should be stopped,
+		//		and the "then" part should be executed. Otherwise the recursion will proceed.
+		// then:
+		//		The lambda expression, which is called upon termination of the recursion.
+		//		It accepts the same parameters as the generated recursive function itself.
+		//		The returned value will be returned as the value of the generated function.
+		// before:
+		//		The lambda expression, which is called before the recursive step.
+		//		It accepts the same parameter as the generated recursive function itself,
+		//		and returns an array of arguments for the next recursive call of
+		//		the generated function.
+
+		var c, t, b, cs, ts, bs, dict1 = {}, dict2 = {},
+			add2dict = function(x){ dict1[x] = 1; };
+		if(typeof cond == "string"){
+			cs = inline(cond, _x, add2dict);
+		}else{
+			c = df.lambda(cond);
+			cs = "_c.apply(this, _x)";
+			dict2["_c=_t.c"] = 1;
+		}
+		if(typeof then == "string"){
+			ts = inline(then, _x, add2dict);
+		}else{
+			t = df.lambda(then);
+			ts = "_t.t.apply(this, _x)";
+		}
+		if(typeof before == "string"){
+			bs = inline(before, _x, add2dict);
+		}else{
+			b = df.lambda(before);
+			bs = "_b.apply(this, _x)";
+			dict2["_b=_t.b"] = 1;
+		}
+		var locals1 = df.keys(dict1), locals2 = df.keys(dict2),
+			f = new Function([], "var _x=arguments,_t=_x.callee,_c=_t.c,_b=_t.b".concat(	// Function
+				locals1.length ? "," + locals1.join(",") : "",
+				locals2.length ? ",_t=_x.callee," + locals2.join(",") : t ? ",_t=_x.callee" : "",
+				";for(;!",
+				cs,
+				";_x=",
+				bs,
+				");return ",
+				ts
+			));
+		if(c){ f.c = c; }
+		if(t){ f.t = t; }
+		if(b){ f.b = b; }
+		return f;
+	};
+})();
+
+/*
+For documentation only:
+
+1) The original recursive version:
+
+var tailrec1 = function(cond, then, before){
+	var cond   = df.lambda(cond),
+		then   = df.lambda(then),
+		before = df.lambda(before);
+	return function(){
+		if(cond.apply(this, arguments)){
+			return then.apply(this, arguments);
+		}
+		var args = before.apply(this, arguments);
+		return arguments.callee.apply(this, args);
+	};
 };
-if(typeof _3=="string"){
-cs=_1(_3,_2,_8);
-}else{
-c=df.lambda(_3);
-cs="_c.apply(this, _x)";
-_7["_c=_t.c"]=1;
-}
-if(typeof _4=="string"){
-ts=_1(_4,_2,_8);
-}else{
-t=df.lambda(_4);
-ts="_t.t.apply(this, _x)";
-}
-if(typeof _5=="string"){
-bs=_1(_5,_2,_8);
-}else{
-b=df.lambda(_5);
-bs="_b.apply(this, _x)";
-_7["_b=_t.b"]=1;
-}
-var _9=df.keys(_6),_a=df.keys(_7),f=new Function([],"var _x=arguments,_t=_x.callee,_c=_t.c,_b=_t.b".concat(_9.length?","+_9.join(","):"",_a.length?",_t=_x.callee,"+_a.join(","):t?",_t=_x.callee":"",";for(;!",cs,";_x=",bs,");return ",ts));
-if(c){
-f.c=c;
-}
-if(t){
-f.t=t;
-}
-if(b){
-f.b=b;
-}
-return f;
+
+2) The original iterative version (before minification and inlining):
+
+var tailrec2 = function(cond, then, before){
+	var cond   = df.lambda(cond),
+		then   = df.lambda(then),
+		before = df.lambda(before);
+	return function(){
+		var args = arguments;
+		for(; !cond.apply(this, args); args = before.apply(this, args));
+		return then.apply(this, args);
+	};
 };
-})();
-}
+
+*/
\ No newline at end of file
diff --git a/dojox/lang/functional/util.js b/dojox/lang/functional/util.js
index 4002040..ba95367 100644
--- a/dojox/lang/functional/util.js
+++ b/dojox/lang/functional/util.js
@@ -1,33 +1,46 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.functional.util"]){
-dojo._hasResource["dojox.lang.functional.util"]=true;
 dojo.provide("dojox.lang.functional.util");
+
 dojo.require("dojox.lang.functional.lambda");
+
+// This module provides helpers:
+//	- inlining string lambda functions.
+
 (function(){
-var df=dojox.lang.functional;
-dojo.mixin(df,{inlineLambda:function(_1,_2,_3){
-var s=df.rawLambda(_1);
-if(_3){
-df.forEach(s.args,_3);
-}
-var ap=typeof _2=="string",n=ap?s.args.length:Math.min(s.args.length,_2.length),a=new Array(4*n+4),i,j=1;
-for(i=0;i<n;++i){
-a[j++]=s.args[i];
-a[j++]="=";
-a[j++]=ap?_2+"["+i+"]":_2[i];
-a[j++]=",";
-}
-a[0]="(";
-a[j++]="(";
-a[j++]=s.body;
-a[j]="))";
-return a.join("");
-}});
+	var df = dojox.lang.functional;
+
+	dojo.mixin(df, {
+		inlineLambda: function(/*String*/ lambda, /*String|Array*/ init, /*Function?*/ add2dict){
+			// summary:
+			//		Creates the inlined version of a string lambda.
+			// lambda:
+			//		The String variable representing the lambda function.
+			// init:
+			//		Conveys how to initialize parameters. If it is a String, then the apply() method
+			//		would be emulated treating "init" as a list of input parameters.
+			//		It it is an Array, then the call() method is emulated treating array members
+			//		as input parameters.
+			// add2dict:
+			//		The optional function, which is used to record names of lambda parameters.
+			//		If supplied, this function is called with a name of every parameter.
+
+			var s = df.rawLambda(lambda);
+			if(add2dict){
+				df.forEach(s.args, add2dict);
+			}
+			var ap = typeof init == "string",	// apply or call?
+				n = ap ? s.args.length : Math.min(s.args.length, init.length),
+				a = new Array(4 * n + 4), i, j = 1;
+			for(i = 0; i < n; ++i){
+				a[j++] = s.args[i];
+				a[j++] = "=";
+				a[j++] = ap ? init + "[" + i + "]": init[i];
+				a[j++] = ",";
+			}
+			a[0] = "(";
+			a[j++] = "(";
+			a[j++] = s.body;
+			a[j] = "))";
+			return a.join("");	// String
+		}
+	});
 })();
-}
diff --git a/dojox/lang/functional/zip.js b/dojox/lang/functional/zip.js
old mode 100644
new mode 100755
index 0c13aa8..627b779
--- a/dojox/lang/functional/zip.js
+++ b/dojox/lang/functional/zip.js
@@ -1,28 +1,40 @@
-/*
-	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
-*/
+dojo.provide("dojox.lang.functional.zip");
 
+// This module adds high-level functions and related constructs:
+//	- zip combiners
+
+// Defined methods:
+//	- operate on dense arrays
 
-if(!dojo._hasResource["dojox.lang.functional.zip"]){
-dojo._hasResource["dojox.lang.functional.zip"]=true;
-dojo.provide("dojox.lang.functional.zip");
 (function(){
-var df=dojox.lang.functional;
-dojo.mixin(df,{zip:function(){
-var n=arguments[0].length,m=arguments.length,i=1,t=new Array(n),j,p;
-for(;i<m;n=Math.min(n,arguments[i++].length)){
-}
-for(i=0;i<n;++i){
-p=new Array(m);
-for(j=0;j<m;p[j]=arguments[j][i],++j){
-}
-t[i]=p;
-}
-return t;
-},unzip:function(a){
-return df.zip.apply(null,a);
-}});
+	var df = dojox.lang.functional;
+
+	dojo.mixin(df, {
+		// combiners
+		zip: function(){
+			// summary: returns an array of arrays, where the i-th array 
+			//	contains the i-th element from each of the argument arrays.
+			// description: This is the venerable zip combiner (for example,
+			//	see Python documentation for general details). The returned
+			//	array is truncated to match the length of the shortest input
+			//	array.
+			var n = arguments[0].length, m = arguments.length, i = 1, t = new Array(n), j, p;
+			for(; i < m; n = Math.min(n, arguments[i++].length));
+			for(i = 0; i < n; ++i){
+				p = new Array(m);
+				for(j = 0; j < m; p[j] = arguments[j][i], ++j);
+				t[i] = p;
+			}
+			return t;	// Array
+		},
+		unzip: function(/*Array*/ a){
+			// summary: similar to dojox.lang.functional.zip(), but takes 
+			//	a single array of arrays as the input.
+			// description: This function is similar to dojox.lang.functional.zip() 
+			//	and can be used to unzip objects packed by 
+			//	dojox.lang.functional.zip(). It is here mostly to provide 
+			//	a short-cut for the different method signature.
+			return df.zip.apply(null, a);	// Array
+		}
+	});
 })();
-}
diff --git a/dojox/lang/observable.js b/dojox/lang/observable.js
index db75804..636edf0 100644
--- a/dojox/lang/observable.js
+++ b/dojox/lang/observable.js
@@ -1,150 +1,264 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.observable"]){
-dojo._hasResource["dojox.lang.observable"]=true;
 dojo.provide("dojox.lang.observable");
+// Used to create a wrapper object with monitored reads and writes
+// 
 dojo.experimental("dojox.lang.observable");
-dojox.lang.observable=function(_1,_2,_3,_4){
-return dojox.lang.makeObservable(_2,_3,_4)(_1);
-};
-dojox.lang.makeObservable=function(_5,_6,_7,_8){
-_8=_8||{};
-_7=_7||function(_9,_a,_b,_c){
-return _a[_b].apply(_9,_c);
-};
-function _d(_e,_f,i){
-return function(){
-return _7(_e,_f,i,arguments);
-};
-};
-if(dojox.lang.lettableWin){
-var _10=dojox.lang.makeObservable;
-_10.inc=(_10.inc||0)+1;
-var _11="gettable_"+_10.inc;
-dojox.lang.lettableWin[_11]=_5;
-var _12="settable_"+_10.inc;
-dojox.lang.lettableWin[_12]=_6;
-var _13={};
-return function(_14){
-if(_14.__observable){
-return _14.__observable;
-}
-if(_14.data__){
-throw new Error("Can wrap an object that is already wrapped");
-}
-var _15=[],i,l;
-for(i in _8){
-_15.push(i);
-}
-var _16={type:1,event:1};
-for(i in _14){
-if(i.match(/^[a-zA-Z][\w\$_]*$/)&&!(i in _8)&&!(i in _16)){
-_15.push(i);
-}
-}
-var _17=_15.join(",");
-var _18,_19=_13[_17];
-if(!_19){
-var _1a="dj_lettable_"+(_10.inc++);
-var _1b=_1a+"_dj_getter";
-var _1c=["Class "+_1a,"\tPublic data__"];
-for(i=0,l=_15.length;i<l;i++){
-_18=_15[i];
-var _1d=typeof _14[_18];
-if(_1d=="function"||_8[_18]){
-_1c.push("  Public "+_18);
-}else{
-if(_1d!="object"){
-_1c.push("\tPublic Property Let "+_18+"(val)","\t\tCall "+_12+"(me.data__,\""+_18+"\",val)","\tEnd Property","\tPublic Property Get "+_18,"\t\t"+_18+" = "+_11+"(me.data__,\""+_18+"\")","\tEnd Property");
-}
-}
-}
-_1c.push("End Class");
-_1c.push("Function "+_1b+"()","\tDim tmp","\tSet tmp = New "+_1a,"\tSet "+_1b+" = tmp","End Function");
-dojox.lang.lettableWin.vbEval(_1c.join("\n"));
-_13[_17]=_19=function(){
-return dojox.lang.lettableWin.construct(_1b);
-};
-}
-var _1e=_19();
-_1e.data__=_14;
-try{
-_14.__observable=_1e;
-}
-catch(e){
-}
-for(i=0,l=_15.length;i<l;i++){
-_18=_15[i];
-try{
-var val=_14[_18];
-}
-catch(e){
-}
-if(typeof val=="function"||_8[_18]){
-_1e[_18]=_d(_1e,_14,_18);
-}
-}
-return _1e;
-};
-}else{
-return function(_1f){
-if(_1f.__observable){
-return _1f.__observable;
-}
-var _20=_1f instanceof Array?[]:{};
-_20.data__=_1f;
-for(var i in _1f){
-if(i.charAt(0)!="_"){
-if(typeof _1f[i]=="function"){
-_20[i]=_d(_20,_1f,i);
-}else{
-if(typeof _1f[i]!="object"){
-(function(i){
-_20.__defineGetter__(i,function(){
-return _5(_1f,i);
-});
-_20.__defineSetter__(i,function(_21){
-return _6(_1f,i,_21);
-});
-})(i);
-}
-}
-}
-}
-for(i in _8){
-_20[i]=_d(_20,_1f,i);
-}
-_1f.__observable=_20;
-return _20;
-};
+// IMPORTANT DISCLAIMER: 
+// This is experimental and based on hideous hacks. 
+// There are severe limitations on the ability of wrapper objects:
+// Only properties that have vbscript-legal names are accessible (similar to JavaScript, but they can't start with an underscore).
+// The wrapper objects are not expando in IE, because they are built
+// from VBScript objects. This means you can't add new properties after an object is created.
+// The wrapper objects can not be used a prototype for other objects.
+// Only properties with primitive values can be wrapped.
+// This has performance implications as well.
+dojox.lang.observable = function(/*Object*/wrapped,/*function*/onRead,/*function*/onWrite,/*function*/onInvoke){
+	// 	summary:
+	// 		Creates a wrapper object, which can be observed. The wrapper object 
+	// 		is a proxy to the wrapped object. If you will be making multiple wrapper
+	// 		objects with the same set of listeners, it is recommended that you
+	// 		use makeObservable, as it is more memory efficient.	
+	// 
+	// 	wrapped:
+	// 		The object to be wrapped and monitored for property access and modification
+	//	
+	// onRead:
+	//		See dojox.lang.makeObservable.onRead
+	// onWrite:
+	//		See dojox.lang.makeObservable.onWrite
+	// onInvoke:
+	//		See dojox.lang.makeObservable.onInvoke
+	
+	return dojox.lang.makeObservable(onRead,onWrite,onInvoke)(wrapped);
 }
+dojox.lang.makeObservable = function(/*function*/onRead,/*function*/onWrite,/*function*/onInvoke,/*Object*/hiddenFunctions){
+		
+	// 	summary:
+	// 		Creates and returns an observable creator function. All the objects that 
+	// 		are created with the returned constructor will use the provided onRead and
+	// 		onWrite listeners.
+	// 		The created constructor should be called with a single argument,
+	// 		the object that will be wrapped to be observed. The constructor will 
+	// 		return the wrapper object.
+	//
+	// onRead:
+	// 		This is called whenever one of the wrapper objects created 
+	// 		from the constructor has a property that is accessed. onRead
+	// 		will be called with two arguments, the first being the wrapped object,
+	// 		and the second is the name of property that is being accessed.
+	// 		The value that onRead returns will be used as the value returned 
+	// 		by the property access
+	//  
+	// onWrite:
+	// 		This is called whenever one of the wrapper objects created 
+	// 		from the constructor has a property that is modified. onWrite
+	// 		will be called with three arguments, the first being the wrapped object,
+	// 		the second is the name of property that is being modified, and the
+	// 		third is the value that is being set on the property.
+	// 
+	// 	onInvoke: 
+	// 		This is called when a method on the object is invoked. The first 
+	// 		argument is the wrapper object, the second is the original wrapped object, 
+	// 		the third is the method name, and the fourth is the arguments.
+	//
+	// hiddenFunctions: 
+	// 		allows you to define functions that should be delegated 
+	// 		but may not be enumerable on the wrapped objects, so they must be 
+	// 		explicitly included
+	//
+	// example:
+	// 		The following could be used to create a wrapper that would
+	// 		prevent functions from being accessed on an object:
+	// 	|	function onRead(obj,prop){
+	//	|		return typeof obj[prop] == 'function' ? null : obj[prop];
+	//	|	} 
+	//	|	var observable = dojox.lang.makeObservable(onRead,onWrite);
+	//	|	var obj = {foo:1,bar:function(){}};
+	//	|	obj = observable(obj);
+	//	|	obj.foo -> 1
+	//	|	obj.bar -> null
+	//
+	hiddenFunctions = hiddenFunctions || {};
+	onInvoke = onInvoke || function(scope,obj,method,args){
+		// default implementation for onInvoke, just passes the call through
+		return obj[method].apply(scope,args);
+	};
+	function makeInvoker(scope,wrapped,i){
+		return function(){
+			// this is function used for all methods in the wrapper object
+			return onInvoke(scope,wrapped,i,arguments);
+		};
+	}
+	
+	if(dojox.lang.lettableWin){ // create the vb class
+		var factory = dojox.lang.makeObservable;
+		factory.inc = (factory.inc || 0) + 1;
+		// create globals for the getters and setters so they can be accessed from the vbscript
+		var getName = "gettable_"+factory.inc;
+		dojox.lang.lettableWin[getName] = onRead;
+		var setName = "settable_"+factory.inc;
+		dojox.lang.lettableWin[setName] = onWrite;
+		var cache = {};
+		return function(wrapped){
+			if(wrapped.__observable){ // if it already has an observable, use that
+				return wrapped.__observable;
+			}
+			if(wrapped.data__){
+				throw new Error("Can wrap an object that is already wrapped");
+			}			
+			// create the class
+			var props = [], i, l;
+			for(i in hiddenFunctions){
+				props.push(i);
+			}
+			var vbReservedWords = {type:1,event:1};
+			// find the unique signature for the class so we can reuse it if possible
+			for(i in wrapped){ 
+				if(i.match(/^[a-zA-Z][\w\$_]*$/) && !(i in hiddenFunctions) && !(i in vbReservedWords)){ //can only do properties with valid vb names/tokens and primitive values
+					props.push(i);
+				}
+			}
+			var signature = props.join(",");
+			var prop,clazz = cache[signature]; 
+			if(!clazz){ 
+				var tname = "dj_lettable_"+(factory.inc++);
+				var gtname = tname+"_dj_getter";
+				var cParts = [
+					"Class "+tname,
+					"	Public data__" // this our reference to the original object
+				];
+				for(i=0, l=props.length; i<l; i++){
+					prop = props[i];
+					var type = typeof wrapped[prop];
+					if(type == 'function' || hiddenFunctions[prop]){ // functions must go in regular properties for delegation:/
+						cParts.push("  Public " + prop);
+					}else if(type != 'object'){ // the getters/setters can only be applied to primitives
+						cParts.push(
+							"	Public Property Let "+prop+"(val)",
+							"		Call "+setName+"(me.data__,\""+prop+"\",val)",
+							"	End Property",
+							"	Public Property Get "+prop,
+							"		"+prop+" = "+getName+"(me.data__,\""+prop+"\")",
+							"	End Property");
+					}
+				}
+				cParts.push("End Class");
+				cParts.push(
+					"Function "+gtname+"()",
+					"	Dim tmp",
+					"	Set tmp = New "+tname,
+					"	Set "+gtname+" = tmp",
+					"End Function");
+				dojox.lang.lettableWin.vbEval(cParts.join("\n"));
+					
+				// Put the new class in the cache
+				cache[signature] = clazz = function(){
+					return dojox.lang.lettableWin.construct(gtname); // the class can't be accessed, only called, so we have to wrap it with a function
+				};
+			}
+			console.log("starting5");
+			var newObj = clazz();
+			newObj.data__ = wrapped;
+			console.log("starting6");
+			try {
+				wrapped.__observable = newObj;
+			} catch(e){ // some objects are not expando
+			}
+			for(i = 0,  l = props.length; i < l; i++){
+				prop = props[i];
+				try {
+				var val = wrapped[prop];
+				}
+				catch(e){
+					console.log("error ",prop,e);
+				}
+				if(typeof val == 'function' || hiddenFunctions[prop]){ // we can make a delegate function here
+					newObj[prop] = makeInvoker(newObj,wrapped,prop);
+				}
+			}
+			return newObj;
+		};
+	}else{
+		return function(wrapped){ // do it with getters and setters
+			if(wrapped.__observable){ // if it already has an observable, use that
+				return wrapped.__observable;
+			}
+			var newObj = wrapped instanceof Array ? [] : {};
+			newObj.data__ = wrapped;
+			for(var i in wrapped){
+				if(i.charAt(0) != '_'){
+					if(typeof wrapped[i] == 'function'){
+						newObj[i] = makeInvoker(newObj,wrapped,i); // TODO: setup getters and setters so we can detect when this changes
+					}else if(typeof wrapped[i] != 'object'){
+						(function(i){
+							newObj.__defineGetter__(i,function(){
+								return onRead(wrapped,i);
+							});
+							newObj.__defineSetter__(i,function(value){
+								return onWrite(wrapped,i,value);
+							});
+						})(i);
+					}
+				}
+			}
+			for(i in hiddenFunctions){
+				newObj[i] = makeInvoker(newObj,wrapped,i);
+			}
+			wrapped.__observable = newObj;
+			return newObj;
+		};
+	}
 };
 if(!{}.__defineGetter__){
-if(dojo.isIE){
-var frame;
-if(document.body){
-frame=document.createElement("iframe");
-document.body.appendChild(frame);
-}else{
-document.write("<iframe id='dj_vb_eval_frame'></iframe>");
-frame=document.getElementById("dj_vb_eval_frame");
+	if(dojo.isIE){
+		// to setup the crazy lettable hack we need to
+		// introduce vb script eval
+		// the only way that seems to work for adding a VBScript to the page is with a document.write
+		// document.write is not always available, so we use an iframe to do the document.write
+		// the iframe also provides a good hiding place for all the global variables that we must
+		// create in order for JScript and VBScript to interact.
+		var frame;
+		if(document.body){ // if the DOM is ready we can add it
+			frame = document.createElement("iframe");
+			document.body.appendChild(frame);
+		}else{ // other we have to write it out
+			document.write("<iframe id='dj_vb_eval_frame'></iframe>");
+			frame = document.getElementById("dj_vb_eval_frame");
+		}
+		frame.style.display="none";
+		var doc = frame.contentWindow.document;
+		dojox.lang.lettableWin = frame.contentWindow;
+		doc.write('<html><head><script language="VBScript" type="text/VBScript">' + 
+			'Function vb_global_eval(code)' +
+				'ExecuteGlobal(code)' +
+			'End Function' +
+			'</script>' +
+			'<script type="text/javascript">' + 
+			'function vbEval(code){ \n' + // this has to be here to call it from another frame
+				'return vb_global_eval(code);' +
+			'}' +
+			'function construct(name){ \n' + // and this too 
+				'return window[name]();' +
+			'}' +
+			'</script>' +
+			'</head><body>vb-eval</body></html>');
+		doc.close();
+	}else{
+		throw new Error("This browser does not support getters and setters");
+	}
 }
-frame.style.display="none";
-var doc=frame.contentWindow.document;
-dojox.lang.lettableWin=frame.contentWindow;
-doc.write("<html><head><script language=\"VBScript\" type=\"text/VBScript\">"+"Function vb_global_eval(code)"+"ExecuteGlobal(code)"+"End Function"+"</script>"+"<script type=\"text/javascript\">"+"function vbEval(code){ \n"+"return vb_global_eval(code);"+"}"+"function construct(name){ \n"+"return window[name]();"+"}"+"</script>"+"</head><body>vb-eval</body></html>");
-doc.close();
-}else{
-throw new Error("This browser does not support getters and setters");
-}
-}
-dojox.lang.ReadOnlyProxy=dojox.lang.makeObservable(function(obj,i){
-return obj[i];
-},function(obj,i,_22){
+
+dojox.lang.ReadOnlyProxy =
+// summary: 
+// 		Provides a read only proxy to another object, this can be 
+// 		very useful in object-capability systems
+// example:
+// 	|	var obj = {foo:"bar"};
+// 	|	var readonlyObj = dojox.lang.ReadOnlyProxy(obj);
+// 	|	readonlyObj.foo = "test" // throws an error
+// 	|	obj.foo = "new bar";
+// 	|	readonlyObj.foo -> returns "new bar", always reflects the current value of the original (it is not just a copy) 
+dojox.lang.makeObservable(function(obj,i){
+		return obj[i];
+	},function(obj,i,value){
+		// just ignore, exceptions don't seem to propagate through the VB stack.
 });
-}
diff --git a/dojox/lang/oo/Decorator.js b/dojox/lang/oo/Decorator.js
index 332057f..8188fda 100644
--- a/dojox/lang/oo/Decorator.js
+++ b/dojox/lang/oo/Decorator.js
@@ -1,24 +1,36 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.oo.Decorator"]){
-dojo._hasResource["dojox.lang.oo.Decorator"]=true;
 dojo.provide("dojox.lang.oo.Decorator");
+
 (function(){
-var oo=dojox.lang.oo,D=oo.Decorator=function(_1,_2){
-this.value=_1;
-this.decorator=typeof _2=="object"?function(){
-return _2.exec.apply(_2,arguments);
-}:_2;
-};
-oo.makeDecorator=function(_3){
-return function(_4){
-return new D(_4,_3);
-};
-};
+	var oo = dojox.lang.oo,
+
+	D = oo.Decorator = function(value, decorator){
+		//	summary:
+		//		The base class for all decorators.
+		//	description:
+		//		This object holds an original function or another decorator
+		//		object, and implements a special mixin algorithm to be used
+		//		by dojox.lang.oo.mixin.
+		//	value: Object:
+		//		a payload to be processed by the decorator.
+		//	decorator: Function|Object:
+		//		a function to handle the custom assignment, or an object with exec()
+		//		method. The signature is:
+		//		decorator(/*String*/ name, /*Function*/ newValue, /*Function*/ oldValue).
+		this.value  = value;
+		this.decorator = typeof decorator == "object" ?
+			function(){ return decorator.exec.apply(decorator, arguments); } : decorator;
+	};
+
+	oo.makeDecorator = function(decorator){
+		//	summary:
+		//		creates new custom decorator creator
+		//	decorator: Function|Object:
+		//		a function to handle the custom assignment,
+		//		or an object with exec() method
+		//	returns: Function:
+		//		new decorator constructor
+		return function(value){
+			return new D(value, decorator);
+		};
+	};
 })();
-}
diff --git a/dojox/lang/oo/Filter.js b/dojox/lang/oo/Filter.js
index 5e20e1f..bea528f 100644
--- a/dojox/lang/oo/Filter.js
+++ b/dojox/lang/oo/Filter.js
@@ -1,27 +1,44 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.oo.Filter"]){
-dojo._hasResource["dojox.lang.oo.Filter"]=true;
 dojo.provide("dojox.lang.oo.Filter");
+
 (function(){
-var oo=dojox.lang.oo,F=oo.Filter=function(_1,_2){
-this.bag=_1;
-this.filter=typeof _2=="object"?function(){
-return _2.exec.apply(_2,arguments);
-}:_2;
-},_3=function(_4){
-this.map=_4;
-};
-_3.prototype.exec=function(_5){
-return this.map.hasOwnProperty(_5)?this.map[_5]:_5;
-};
-oo.filter=function(_6,_7){
-return new F(_6,new _3(_7));
-};
+	var oo = dojox.lang.oo,
+
+	F = oo.Filter = function(bag, filter){
+		//	summary:
+		//		Filter to control mixing in objects by skipping
+		//		properties and renaming them.
+		//	description:
+		//		This object is used as a holder of an original object
+		//		(whose properites are to be copied), and a filter
+		//		function used while copying by dojox.lang.oo.mixin.
+		//	bag: Object:
+		//		object to be filtered
+		//	filter: Function|Object:
+		//		a function to handle the name filtering,
+		//		or an object with exec() method
+		this.bag = bag;
+		this.filter = typeof filter == "object" ?
+			function(){ return filter.exec.apply(filter, arguments); } : filter;
+	},
+
+	// the default map-based filter object
+	MapFilter = function(map){
+		this.map = map;
+	};
+
+	MapFilter.prototype.exec = function(name){
+		return this.map.hasOwnProperty(name) ? this.map[name] : name;
+	};
+
+	oo.filter = function(bag, map){
+		//	summary:
+		//		creates a simple filter object
+		//	bag: Object:
+		//		object to be filtered
+		//	map: Object:
+		//		the dictionary for renaming/removing while copying
+		//	returns:
+		//		new dojox.lang.oo.Filter object
+		return new F(bag, new MapFilter(map));
+	};
 })();
-}
diff --git a/dojox/lang/oo/aop.js b/dojox/lang/oo/aop.js
index c1f8f9b..e31c0aa 100644
--- a/dojox/lang/oo/aop.js
+++ b/dojox/lang/oo/aop.js
@@ -1,54 +1,74 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.oo.aop"]){
-dojo._hasResource["dojox.lang.oo.aop"]=true;
 dojo.provide("dojox.lang.oo.aop");
+
 dojo.require("dojox.lang.oo.Decorator");
 dojo.require("dojox.lang.oo.general");
+
 (function(){
-var oo=dojox.lang.oo,md=oo.makeDecorator,_1=oo.general,_2=oo.aop,_3=dojo.isFunction;
-_2.before=_1.before;
-_2.around=_1.wrap;
-_2.afterReturning=md(function(_4,_5,_6){
-return _3(_6)?function(){
-var _7=_6.apply(this,arguments);
-_5.call(this,_7);
-return _7;
-}:function(){
-_5.call(this);
-};
-});
-_2.afterThrowing=md(function(_8,_9,_a){
-return _3(_a)?function(){
-var _b;
-try{
-_b=_a.apply(this,arguments);
-}
-catch(e){
-_9.call(this,e);
-throw e;
-}
-return _b;
-}:_a;
-});
-_2.after=md(function(_c,_d,_e){
-return _3(_e)?function(){
-var _f;
-try{
-_f=_e.apply(this,arguments);
-}
-finally{
-_d.call(this);
-}
-return _f;
-}:function(){
-_d.call(this);
-};
-});
+	var oo = dojox.lang.oo, md = oo.makeDecorator, oog = oo.general, ooa = oo.aop,
+		isF = dojo.isFunction;
+
+	// five decorators implementing light-weight AOP weaving
+
+	/*=====
+	ooa.before = md(function(name, newValue, oldValue){
+		// summary: creates a "before" advise, by calling new function
+		// before the old one
+
+		// dummy body
+	});
+
+	ooa.around = md(function(name, newValue, oldValue){
+		// summary: creates an "around" advise,
+		// the previous value is passed as a first argument and can be null,
+		// arguments are passed as a second argument
+
+		// dummy body
+	});
+	=====*/
+
+	// reuse existing decorators
+	ooa.before = oog.before;
+	ooa.around = oog.wrap;
+
+	ooa.afterReturning = md(function(name, newValue, oldValue){
+		// summary: creates an "afterReturning" advise,
+		// the returned value is passed as the only argument
+		return isF(oldValue) ?
+			function(){
+				var ret = oldValue.apply(this, arguments);
+				newValue.call(this, ret);
+				return ret;
+			} : function(){ newValue.call(this); };
+	});
+
+	ooa.afterThrowing = md(function(name, newValue, oldValue){
+		// summary: creates an "afterThrowing" advise,
+		// the exception is passed as the only argument
+		return isF(oldValue) ?
+			function(){
+				var ret;
+				try{
+					ret = oldValue.apply(this, arguments);
+				}catch(e){
+					newValue.call(this, e);
+					throw e;
+				}
+				return ret;
+			} : oldValue;
+	});
+
+	ooa.after = md(function(name, newValue, oldValue){
+		// summary: creates an "after" advise,
+		// it takes no arguments
+		return isF(oldValue) ?
+			function(){
+				var ret;
+				try{
+					ret = oldValue.apply(this, arguments);
+				}finally{
+					newValue.call(this);
+				}
+				return ret;
+			} : function(){ newValue.call(this); }
+	});
 })();
-}
diff --git a/dojox/lang/oo/general.js b/dojox/lang/oo/general.js
index 7ed8cfa..cd024ae 100644
--- a/dojox/lang/oo/general.js
+++ b/dojox/lang/oo/general.js
@@ -1,49 +1,60 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.oo.general"]){
-dojo._hasResource["dojox.lang.oo.general"]=true;
 dojo.provide("dojox.lang.oo.general");
+
 dojo.require("dojox.lang.oo.Decorator");
+
 (function(){
-var oo=dojox.lang.oo,md=oo.makeDecorator,_1=oo.general,_2=dojo.isFunction;
-_1.augment=md(function(_3,_4,_5){
-return typeof _5=="undefined"?_4:_5;
-});
-_1.override=md(function(_6,_7,_8){
-return typeof _8!="undefined"?_7:_8;
-});
-_1.shuffle=md(function(_9,_a,_b){
-return _2(_b)?function(){
-return _b.apply(this,_a.apply(this,arguments));
-}:_b;
-});
-_1.wrap=md(function(_c,_d,_e){
-return function(){
-return _d.call(this,_e,arguments);
-};
-});
-_1.tap=md(function(_f,_10,_11){
-return function(){
-_10.apply(this,arguments);
-return this;
-};
-});
-_1.before=md(function(_12,_13,_14){
-return _2(_14)?function(){
-_13.apply(this,arguments);
-return _14.apply(this,arguments);
-}:_13;
-});
-_1.after=md(function(_15,_16,_17){
-return _2(_17)?function(){
-_17.apply(this,arguments);
-return _16.apply(this,arguments);
-}:_16;
-});
+	var oo = dojox.lang.oo, md = oo.makeDecorator, oog = oo.general,
+		isF = dojo.isFunction;
+
+	// generally useful decorators
+
+	oog.augment = md(function(name, newValue, oldValue){
+		// summary: add property, if it was not defined before
+		return typeof oldValue == "undefined" ? newValue : oldValue;
+	});
+
+	oog.override = md(function(name, newValue, oldValue){
+		// summary: override property only if it was already present
+		return typeof oldValue != "undefined" ? newValue : oldValue;
+	});
+
+	oog.shuffle = md(function(name, newValue, oldValue){
+		// summary: replaces arguments for an old method
+		return isF(oldValue) ?
+			function(){
+				return oldValue.apply(this, newValue.apply(this, arguments));
+			} : oldValue;
+	});
+
+	oog.wrap = md(function(name, newValue, oldValue){
+		// summary: wraps the old values with a supplied function
+		return function(){ return newValue.call(this, oldValue, arguments); };
+	});
+
+	oog.tap = md(function(name, newValue, oldValue){
+		// summary: always returns "this" ignoring the actual return
+		return function(){ newValue.apply(this, arguments); return this; };
+	});
+
+	oog.before = md(function(name, newValue, oldValue){
+		//	summary:
+		//		creates a chain of calls where the new method is called
+		//		before the old method
+		return isF(oldValue) ?
+			function(){
+				newValue.apply(this, arguments);
+				return oldValue.apply(this, arguments);
+			} : newValue;
+	});
+
+	oog.after = md(function(name, newValue, oldValue){
+		//	summary:
+		//		creates a chain of calls where the new method is called
+		//		after the old method
+		return isF(oldValue) ?
+			function(){
+				oldValue.apply(this, arguments);
+				return newValue.apply(this, arguments);
+			} : newValue;
+	});
 })();
-}
diff --git a/dojox/lang/oo/mixin.js b/dojox/lang/oo/mixin.js
index 3f99f41..74d4e8a 100644
--- a/dojox/lang/oo/mixin.js
+++ b/dojox/lang/oo/mixin.js
@@ -1,83 +1,134 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.oo.mixin"]){
-dojo._hasResource["dojox.lang.oo.mixin"]=true;
 dojo.provide("dojox.lang.oo.mixin");
+
 dojo.experimental("dojox.lang.oo.mixin");
+
 dojo.require("dojox.lang.oo.Filter");
 dojo.require("dojox.lang.oo.Decorator");
+
 (function(){
-var oo=dojox.lang.oo,_1=oo.Filter,_2=oo.Decorator,_3={},_4=function(_5){
-return _5;
-},_6=function(_7,_8,_9){
-return _8;
-},_a=function(_b,_c,_d,_e){
-_b[_c]=_d;
-},_f={},_10=dojo._extraNames,_11=_10.length,_12=oo.applyDecorator=function(_13,_14,_15,_16){
-if(_15 instanceof _2){
-var d=_15.decorator;
-_15=_12(_13,_14,_15.value,_16);
-return d(_14,_15,_16);
-}
-return _13(_14,_15,_16);
-};
-oo.__mixin=function(_17,_18,_19,_1a,_1b){
-var _1c,_1d,_1e,_1f,_20,i;
-for(_1c in _18){
-_1e=_18[_1c];
-if(!(_1c in _3)||_3[_1c]!==_1e){
-_1d=_1a(_1c,_17,_18,_1e);
-if(_1d&&(!(_1d in _17)||!(_1d in _3)||_3[_1d]!==_1e)){
-_20=_17[_1d];
-_1f=_12(_19,_1d,_1e,_20);
-if(_20!==_1f){
-_1b(_17,_1d,_1f,_20);
-}
-}
-}
-}
-if(_11){
-for(i=0;i<_11;++i){
-_1c=_10[i];
-_1e=_18[_1c];
-if(!(_1c in _3)||_3[_1c]!==_1e){
-_1d=_1a(_1c,_17,_18,_1e);
-if(_1d&&(!(_1d in _17)||!(_1d in _3)||_3[_1d]!==_1e)){
-_20=_17[_1d];
-_1f=_12(_19,_1d,_1e,_20);
-if(_20!==_1f){
-_1b(_17,_1d,_1f,_20);
-}
-}
-}
-}
-}
-return _17;
-};
-oo.mixin=function(_21,_22){
-var _23,_24,i=1,l=arguments.length;
-for(;i<l;++i){
-_22=arguments[i];
-if(_22 instanceof _1){
-_24=_22.filter;
-_22=_22.bag;
-}else{
-_24=_4;
-}
-if(_22 instanceof _2){
-_23=_22.decorator;
-_22=_22.value;
-}else{
-_23=_6;
-}
-oo.__mixin(_21,_22,_23,_24,_a);
-}
-return _21;
-};
+	var oo = dojox.lang.oo, Filter = oo.Filter, Decorator = oo.Decorator, empty = {},
+		defaultFilter = function(name){ return name; },
+		defaultDecorator = function(name, newValue, oldValue){ return newValue; },
+		defaultMixer = function(target, name, newValue, oldValue){ target[name] = newValue; },
+		defaults = {},	// for the internal use in the mixin()
+		extraNames = dojo._extraNames, extraLen = extraNames.length,
+
+		applyDecorator = oo.applyDecorator = function(decorator, name, newValue, oldValue){
+			//	summary:
+			//		applies a decorator unraveling all embedded decorators
+			//	decorator: Function:
+			//		top-level decorator to apply
+			//	name: String:
+			//		name of the property
+			//	newValue: Object:
+			//		new value of the property
+			//	oldValue: Object:
+			//		old value of the property
+			//	returns: Object:
+			//		returns the final value of the property
+			if(newValue instanceof Decorator){
+				var d = newValue.decorator;
+				newValue = applyDecorator(decorator, name, newValue.value, oldValue);
+				return d(name, newValue, oldValue);
+			}
+			return decorator(name, newValue, oldValue);
+		};
+
+	/*=====
+	dojox.lang.oo.__MixinDefaults = function(){
+		//	summary:
+		//		a dict of default parameters for dojox.lang.oo._mixin
+		//	decorator: Function:
+		//		a decorator function to be used in absence of other decorators
+		//	filter: Function:
+		//		a filter function to be used in absence of other filters
+		//	mixer: Function:
+		//		a mixer function to be used to mix in new properties
+		this.decorator = decorator;
+		this.filter = filter;
+		this.mixer = mixer;
+	};
+	=====*/
+
+	oo.__mixin = function(target, source, decorator, filter, mixer){
+		//	summary:
+		//		mixes in two objects processing decorators and filters
+		//	target: Object:
+		//		target to receive new/updated properties
+		//	source: Object:
+		//		source of properties
+		//	defaults: dojox.lang.oo.__MixinDefaults?:
+		//		default functions for various aspects of mixing
+		//	returns: Object:
+		//		target
+
+		var name, targetName, prop, newValue, oldValue, i;
+
+		// start mixing in properties
+		for(name in source){
+			prop = source[name];
+			if(!(name in empty) || empty[name] !== prop){
+				targetName = filter(name, target, source, prop);
+				if(targetName && (!(targetName in target) || !(targetName in empty) || empty[targetName] !== prop)){
+					// name is accepted
+					oldValue = target[targetName];
+					newValue = applyDecorator(decorator, targetName, prop, oldValue);
+					if(oldValue !== newValue){
+						mixer(target, targetName, newValue, oldValue);
+					}
+				}
+			}
+		}
+		if(extraLen){
+			for(i = 0; i < extraLen; ++i){
+				name = extraNames[i];
+				// repeating the body above
+				prop = source[name];
+				if(!(name in empty) || empty[name] !== prop){
+					targetName = filter(name, target, source, prop);
+					if(targetName && (!(targetName in target) || !(targetName in empty) || empty[targetName] !== prop)){
+						// name is accepted
+						oldValue = target[targetName];
+						newValue = applyDecorator(decorator, targetName, prop, oldValue);
+						if(oldValue !== newValue){
+							mixer(target, targetName, newValue, oldValue);
+						}
+					}
+				}
+			}
+		}
+
+		return target;	// Object
+	};
+
+	oo.mixin = function(target, source){
+		// summary:
+		//		mixes in two or more objects processing decorators and filters
+		//		using defaults as a fallback
+		// target: Object:
+		//		target to receive new/updated properties
+		// source: Object...:
+		//		source of properties, more than one source is allowed
+		// returns: Object:
+		//		target
+
+		var decorator, filter, i = 1, l = arguments.length;
+		for(; i < l; ++i){
+			source = arguments[i];
+			if(source instanceof Filter){
+				filter = source.filter;
+				source = source.bag;
+			}else{
+				filter = defaultFilter;
+			}
+			if(source instanceof Decorator){
+				decorator = source.decorator;
+				source = source.value;
+			}else{
+				decorator = defaultDecorator;
+			}
+			oo.__mixin(target, source, decorator, filter, defaultMixer);
+		}
+		return target;	// Object
+	};
 })();
-}
diff --git a/dojox/lang/oo/rearrange.js b/dojox/lang/oo/rearrange.js
index 3dcf1ed..e7433cb 100644
--- a/dojox/lang/oo/rearrange.js
+++ b/dojox/lang/oo/rearrange.js
@@ -1,49 +1,64 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.oo.rearrange"]){
-dojo._hasResource["dojox.lang.oo.rearrange"]=true;
 dojo.provide("dojox.lang.oo.rearrange");
+
 (function(){
-var _1=dojo._extraNames,_2=_1.length,_3=Object.prototype.toString;
-dojox.lang.oo.rearrange=function(_4,_5){
-var _6,_7,_8,i,t;
-for(_6 in _5){
-_7=_5[_6];
-if(!_7||_3.call(_7)=="[object String]"){
-_8=_4[_6];
-if(!(_6 in empty)||empty[_6]!==_8){
-if(!(delete _4[_6])){
-_4[_6]=undefined;
-}
-if(_7){
-_4[_7]=_8;
-}
-}
-}
-}
-if(_2){
-for(i=0;i<_2;++i){
-_6=_1[i];
-_7=_5[_6];
-if(!_7||_3.call(_7)=="[object String]"){
-_8=_4[_6];
-if(!(_6 in empty)||empty[_6]!==_8){
-if(!(delete _4[_6])){
-_4[_6]=undefined;
-}
-if(_7){
-_4[_7]=_8;
-}
-}
-}
-}
-}
-return _4;
-};
+	var extraNames = dojo._extraNames, extraLen = extraNames.length,
+		opts = Object.prototype.toString, empty = {};
+
+	dojox.lang.oo.rearrange = function(bag, map){
+		//	summary:
+		//		Process properties in place by removing and renaming them.
+		//	description:
+		//		Properties of an object are to be renamed or removed specified
+		//		by "map" argument. Only own properties of "map" are processed.
+		//	example:
+		//	|	oo.rearrange(bag, {
+		//	|		abc: "def",	// rename "abc" attribute to "def"
+		//	|		ghi: null	// remove/hide "ghi" attribute
+		//	|	});
+		//	bag: Object:
+		//		the object to be processed
+		//	map: Object:
+		//		the dictionary for renaming (false value indicates removal of the named property)
+		//	returns: Object:
+		//		the original object
+
+	var name, newName, prop, i, t;
+
+		for(name in map){
+			newName = map[name];
+			if(!newName || opts.call(newName) == "[object String]"){
+				prop = bag[name];
+				if(!(name in empty) || empty[name] !== prop){
+					if(!(delete bag[name])){
+						// can't delete => hide it
+						bag[name] = undefined;
+					}
+					if(newName){
+						bag[newName] = prop;
+					}
+				}
+			}
+		}
+		if(extraLen){
+			for(i = 0; i < extraLen; ++i){
+				name = extraNames[i];
+				// repeating the body above
+				newName = map[name];
+				if(!newName || opts.call(newName) == "[object String]"){
+					prop = bag[name];
+					if(!(name in empty) || empty[name] !== prop){
+						if(!(delete bag[name])){
+							// can't delete => hide it
+							bag[name] = undefined;
+						}
+						if(newName){
+							bag[newName] = prop;
+						}
+					}
+				}
+			}
+		}
+
+		return bag;	// Object
+	};
 })();
-}
diff --git a/dojox/lang/tests/array.js b/dojox/lang/tests/array.js
new file mode 100644
index 0000000..d8164d9
--- /dev/null
+++ b/dojox/lang/tests/array.js
@@ -0,0 +1,82 @@
+dojo.provide("dojox.lang.tests.array");
+
+dojo.require("dojox.lang.functional");
+dojo.require("dojox.lang.functional.fold");
+dojo.require("dojox.lang.functional.reversed");
+
+(function(){
+	var df = dojox.lang.functional, v, isOdd = "%2", x = {a: 1, b: 2, c: 3};
+	
+	var revArrayIter = function(array){
+		this.array    = array;
+		this.position = array.length - 1;
+	};
+	dojo.extend(revArrayIter, {
+		hasNext:	df.lambda("this.position >= 0"),
+		next:		df.lambda("this.array[this.position--]")
+	});
+	
+	tests.register("dojox.lang.tests.array", [
+		function testFilter1(t){ t.assertEqual(df.filter([1, 2, 3], isOdd), [1, 3]); },
+		function testFilter2(t){ t.assertEqual(df.filter([1, 2, 3], "%2==0"), [2]); },
+		function testFilterIter(t){
+			var iter = new revArrayIter([1, 2, 3]);
+			t.assertEqual(df.filter(iter, isOdd), [3, 1]);
+		},
+		function testFilterRev(t){
+			var iter = new revArrayIter([1, 2, 3]);
+			t.assertEqual(df.filter(iter, isOdd), df.filterRev([1, 2, 3], isOdd));
+		},
+		
+		function testForEach(t){
+			t.assertEqual((v = [], df.forEach([1, 2, 3], function(x){ v.push(x); }), v), [1, 2, 3]);
+		},
+		function testForEachIter(t){
+			var iter = new revArrayIter([1, 2, 3]);
+			t.assertEqual((v = [], df.forEach(iter, function(x){ v.push(x); }), v), [3, 2, 1]);
+		},
+		function testForEachRev(t){
+			t.assertEqual((v = [], df.forEachRev([1, 2, 3], function(x){ v.push(x); }), v), [3, 2, 1]);
+		},
+		
+		function testMap(t){ t.assertEqual(df.map([1, 2, 3], "+3"), [4, 5, 6]); },
+		function testMapIter(t){
+			var iter = new revArrayIter([1, 2, 3]);
+			t.assertEqual(df.map(iter, "+3"), [6, 5, 4]);
+		},
+		function testMapRev(t){
+			var iter = new revArrayIter([1, 2, 3]);
+			t.assertEqual(df.map(iter, "+3"), df.mapRev([1, 2, 3], "+3"));
+		},
+		
+		function testEvery1(t){ t.assertFalse(df.every([1, 2, 3], isOdd)); },
+		function testEvery2(t){ t.assertTrue(df.every([1, 3, 5], isOdd)); },
+		function testEveryIter(t){
+			var iter = new revArrayIter([1, 3, 5]);
+			t.assertTrue(df.every(iter, isOdd));
+		},
+		function testEveryObj(t){ t.assertFalse(df.every(x, "%2")); },
+		function testEveryRev1(t){ t.assertFalse(df.everyRev([1, 2, 3], isOdd)); },
+		function testEveryRev2(t){ t.assertTrue(df.everyRev([1, 3, 5], isOdd)); },
+
+		function testSome1(t){ t.assertFalse(df.some([2, 4, 6], isOdd)); },
+		function testSome2(t){ t.assertTrue(df.some([1, 2, 3], isOdd)); },
+		function testSomeIter(t){
+			var iter = new revArrayIter([1, 2, 3]);
+			t.assertTrue(df.some(iter, isOdd));
+		},
+		function testSomeObj(t){ t.assertTrue(df.some(x, "%2")); },
+		function testSomeRev1(t){ t.assertFalse(df.someRev([2, 4, 6], isOdd)); },
+		function testSomeRev2(t){ t.assertTrue(df.someRev([1, 2, 3], isOdd)); },
+
+		function testReduce1(t){ t.assertEqual(df.reduce([4, 2, 1], "x-y"), 1); },
+		function testReduce2(t){ t.assertEqual(df.reduce([4, 2, 1], "x-y", 8), 1); },
+		function testReduceIter(t){
+			var iter = new revArrayIter([1, 2, 4]);
+			t.assertEqual(df.reduce(iter, "x-y"), 1);
+		},
+		
+		function testReduceRight1(t){ t.assertEqual(df.reduceRight([4, 2, 1], "x-y"), -5); },
+		function testReduceRight2(t){ t.assertEqual(df.reduceRight([4, 2, 1], "x-y", 8), 1); }
+	]);
+})();
diff --git a/dojox/lang/tests/async.js b/dojox/lang/tests/async.js
new file mode 100644
index 0000000..42adde8
--- /dev/null
+++ b/dojox/lang/tests/async.js
@@ -0,0 +1,216 @@
+dojo.provide("dojox.lang.tests.async");
+
+dojo.require("dojox.lang.async");
+dojo.require("dojox.lang.async.timeout");
+dojo.require("dojox.lang.async.topic");
+
+(function(){
+	var async = dojox.lang.async,
+		wait = async.timeout.from,
+		QUANT     = 50, // ms
+		MAX_TICKS = 5;
+
+	function randomTimes(n){
+		var a = [];
+		for(var i = 0; i < n; ++i){
+			a.push((Math.floor(Math.random() * MAX_TICKS) + 1) * QUANT);
+		}
+		return a;
+	}
+
+	function getMin(a){
+		return Math.min.apply(Math, a);
+	}
+
+	function getMax(a){
+		return Math.max.apply(Math, a);
+	}
+
+	function waitAndExpect(expected, ms){
+		return function(value){
+			console.log("waitAndExpect: ", value, ", expected: ", expected);
+			if(expected !== value){
+				console.log("ERROR: unexpected value");
+				throw new Error("Unexpected value");
+			}
+			return wait(ms)();
+		}
+	}
+
+	function identity(x){
+		return x;
+	}
+
+	function is(a, b, visited){
+		if(a === b){
+			return true;
+		}
+		if(typeof a != typeof b){
+			return false;
+		}
+		if(Object.prototype.toString.call(a) != Object.prototype.toString.call(b)){
+			return false;
+		}
+		if(Object.prototype.toString.call(a) == "[object Function]"){
+			return false;
+		}
+		if(Object.prototype.toString.call(a) == "[object Array]"){
+			if(a.length !== b.length){
+				return false;
+			}
+			for(var i = 0; i < a.length; ++i){
+				if(!is(a[i], b[i], visited)){
+					return false;
+				}
+				return true;
+			}
+		}
+		if(typeof a == "object"){
+			if(visited){
+				for(var i = 0; i < visited.length; ++i){
+					if(visited[i] === a || visited[i] === b){
+						return true;
+					}
+				}
+				visited.push(a, b);
+			}else{
+				visited = [a, b];
+}
+			var akeys = [];
+			for(var i in a){
+				akeys.push(i);
+			}
+			var bkeys = [];
+			for(var i in b){
+				bkeys.push(i);
+			}
+			akeys.sort();
+			bkeys.sort();
+			if(!is(akeys, bkeys)){
+				return false;
+			}
+			for(var i = 0; i < akeys.length; ++i){
+				if(!is(a[akeys[i]], b[bkeys[i]])){
+					return false;
+				}
+			}
+			return true;
+		}
+		return false;
+	}
+
+	var waitFor0 = waitAndExpect(0, 20),
+		waitFor1 = waitAndExpect(1, 20),
+		waitFor2 = waitAndExpect(2, 20);
+
+	tests.register("dojox.lang.tests.async", [
+		function smokeTest(){
+			var a = randomTimes(1),
+				r = new dojo.Deferred();
+			wait(a[0])().addCallback(function(x){
+				if(r == a[0]){
+					console.log("ERROR: smokeTest: wrong result");
+					throw new Error("smokeTest: wrong result");
+				}
+				r.callback();
+			});
+			return r;
+		},
+		function testSeq(){
+			var a = randomTimes(5),
+				fs = dojo.map(a, function(ms, i){
+					return waitAndExpect(i && a[i - 1], ms);
+				});
+			return async.seq(fs)(0).addCallback(function(value){
+				if(a[a.length - 1] !== value){
+					console.log("ERROR: testSeq: wrong time");
+					throw new Error("testSeq: wrong time");
+				}
+			});
+		},
+		function testPar(){
+			var a = randomTimes(5),
+				fs = dojo.map(a, function(ms){
+					return waitAndExpect(0, ms);
+				});
+			return async.par(fs)(0).addCallback(function(value){
+				console.log(a, " - ", value);
+				if(!is(a, value)){
+					console.log("ERROR: testPar: wrong time");
+					throw new Error("testPar: wrong time");
+				}
+			});
+		},
+		function testAny(){
+			var a = randomTimes(5),
+				min = getMin(a),
+				fs = dojo.map(a, function(ms){
+					return waitAndExpect(0, ms);
+				});
+			return async.any(fs)(0).addCallback(function(value){
+				console.log(min, " - ", value);
+				if(min !== value){
+					console.log("ERROR: testAny: wrong time");
+					throw new Error("testAny: wrong time");
+				}
+			});
+		},
+		function testSelect0(){
+			return async.select(
+				identity,
+				waitFor0,
+				waitFor1,
+				waitFor2
+			)(0);
+		},
+		function testSelect1(){
+			return async.select(
+				identity,
+				waitFor0,
+				waitFor1,
+				waitFor2
+			)(1);
+		},
+		function testSelect2(){
+			return async.select(
+				identity,
+				waitFor0,
+				waitFor1,
+				waitFor2
+			)(2);
+		},
+		function testIfThenT(){
+			return async.ifThen(
+				identity,
+				waitFor1,
+				waitFor0
+			)(1);
+		},
+		function testIfThenF(){
+			return async.ifThen(
+				identity,
+				waitFor1,
+				waitFor0
+			)(0);
+		},
+		function testLoop(){
+			var counter = 0;
+			return async.seq(
+				async.loop(
+					identity,
+					function(ms){
+						++counter;
+						return wait(ms - 10)();
+					}
+				),
+				function(){
+					console.log(counter, " - ", 3);
+					if(counter !== 3){
+						console.log("ERROR: testLoop: wrong number of iterations");
+						throw new Error("testLoop: wrong number of iterations");
+					}
+				}
+			)(30);
+		}
+	]);
+})();
diff --git a/dojox/lang/tests/bench_decl.html b/dojox/lang/tests/bench_decl.html
new file mode 100644
index 0000000..c08cf8e
--- /dev/null
+++ b/dojox/lang/tests/bench_decl.html
@@ -0,0 +1,480 @@
+<html>
+	<head>
+		<title>OO/decl benchmark</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+
+            .stats th, .stats td { padding: 3pt; }
+            .stats th, .name { font-weight: bold; }
+            table.stats, .stats th, .stats td { border: 1px solid lightgray; }
+            .median { color: navy; font-weight: bold; }
+            .fastest { background-color: #ccf; }
+            .stablest { background-color: #ffc; }
+            .fastest.stablest { background-color: #cfc; }
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.lang.tests.declare-old");
+
+			var d = dojo, oo = dojox.lang.oo, nothing = function(){};
+
+            // test harness
+
+            var DELAY = 20,     // pause in ms between tests
+                LIMIT = 50,     // the lower limit of a test
+                COUNT = 50;     // how many times to repeat the test
+
+            // the basic unit to run a test with timing
+            var runTest = function(f, n){
+                var start = new Date();
+                for(var i = 0; i < n; ++i){
+                    f();
+                }
+                var end = new Date();
+                return end.getTime() - start.getTime();
+            };
+
+            // find the threshold number of tests just exceeding the limit
+            var findThreshold = function(f, limit){
+                // very simplistic search probing only powers of two
+                var n = 1;
+                while(runTest(f, n) + runTest(nothing, n) < limit) n <<= 1;
+                return n;
+            };
+
+            var _runUnitTest = function(a, f, n, k, m, next){
+                a[k++] = runTest(f, n) - runTest(nothing, n);
+                if(k < m){
+                    setTimeout(d.hitch(null, _runUnitTest, a, f, n, k, m, next), DELAY);
+                }else{
+                    next(a);
+                }
+            };
+
+            var runTests = function(f, n, m, next){
+                var a = new Array(m);
+                _runUnitTest(a, f, n, 0, m, next);
+            };
+
+            // statistics
+
+            var statNames = ["minimum", "firstDecile", "lowerQuartile", "median", "upperQuartile", "lastDecile", "maximum", "average"];
+
+            var statAbbr = {
+                minimum:        "min",
+                maximum:        "max",
+                median:         "med",
+                lowerQuartile:  "25%",
+                upperQuartile:  "75%",
+                firstDecile:    "10%",
+                lastDecile:     "90%",
+                average:        "avg"
+            };
+
+            var getWeightedValue = function(a, pos){
+                var p = pos * (a.length - 1), t = Math.ceil(p), f = t - 1;
+                if(f <= 0){ return a[0]; }
+                if(t >= a.length){ return a[a.length - 1]; }
+                return a[f] * (t - p) + a[t] * (p - f);
+            };
+
+            var getStats = function(a, n){
+                var t = a.slice(0);
+                t.sort(function(a, b){ return a - b; });
+                var result = {
+                    // the five-number summary
+                    minimum:        t[0],
+                    maximum:        t[t.length - 1],
+                    median:         getWeightedValue(t, 0.5),
+                    lowerQuartile:  getWeightedValue(t, 0.25),
+                    upperQuartile:  getWeightedValue(t, 0.75),
+                    // extended to the Bowley's seven-figure summary
+                    firstDecile:    getWeightedValue(t, 0.1),
+                    lastDecile:     getWeightedValue(t, 0.9)
+                };
+                // add the average
+                for(var i = 0, sum = 0; i < t.length; sum += t[i++]);
+                result.average = sum / t.length;
+                d.forEach(statNames, function(name){
+                    if(result.hasOwnProperty(name) && typeof result[name] == "number"){
+                        result[name] /= n;
+                    }
+                });
+                return result;
+            };
+			
+			var testGroups = [];
+
+            // run a group of tests, prepare statistics and show results
+
+            var registerGroup = function(fs, bi, m, node, title){
+                var n = findThreshold(fs[bi].fun, LIMIT),
+                    x = {
+                        functions:  fs,
+                        stats:      [],
+                        process: function(a){
+                            if(a){
+                                this.stats.push(getStats(a, n));
+                                console.log("test #" + this.stats.length + " is completed: " + this.functions[this.stats.length - 1].name);
+                            }
+                            if(this.stats.length < this.functions.length){
+                                //setTimeout(d.hitch(null, runTests, this.functions[this.stats.length].fun, n, m, d.hitch(this, "process")), DELAY);
+                                var f = d.hitch(null, runTests, this.functions[this.stats.length].fun, n, m, d.hitch(this, "process"));
+                                f();
+                                return;
+                            }
+                            var diff = Math.max.apply(Math, d.map(this.stats, function(s){ return s.upperQuartile - s.lowerQuartile; })),
+                                prec = 1 - Math.floor(Math.log(diff) / Math.LN10), fastest = 0, stablest = 0;
+                            d.forEach(this.stats, function(s, i){
+                                if(i){
+                                    if(s.median < this.stats[fastest].median){
+                                        fastest = i;
+                                    }
+                                    if(s.upperQuartile - s.lowerQuartile < this.stats[i].upperQuartile - this.stats[i].lowerQuartile){
+                                        stablest = i;
+                                    }
+                                }
+                            }, this);
+                            // add the table
+                            var tab = ["<table class='stats'><thead><tr><th>Test</th>"];
+							tab.push(d.map(this.functions, function(f, i){
+								return "<th class='" + (i == fastest ? "fastest" : "") + " " + (i == stablest ? "stablest" : "") + "'>" + f.name + "</th>";
+							}).join(""));
+                            tab.push("</tr></thead><tbody>");
+							d.forEach(statNames, function(n){
+								tab.push("<tr class='name " + n + "'><td>" + n + "</td>");
+								d.forEach(this.stats, function(s, i){
+									tab.push("<td class='" + (i == fastest ? "fastest" : "") + " " + (i == stablest ? "stablest" : "") + "'>" + s[n].toFixed(prec) + "</td>");
+								}, this);
+								tab.push("</tr>");
+							}, this);
+                            tab.push("</tbody></table>");
+                            d.place(tab.join(""), node);
+							// next
+							run();
+                        }
+                    };
+				testGroups.push(function(){
+					console.log("all tests will be repeated " + n + " times in " + m + " series");
+					d.place("<h1>" + title + "</h1>", node);
+					x.process();
+				});
+            };
+			
+			function run(){
+				if(testGroups.length){
+					testGroups.shift()();
+				}else{
+					setTimeout(function(){
+						console.log("Done!");
+						alert("Done!");
+					}, DELAY);
+				}
+			}
+
+            // actual benchmarks
+
+            var decl0 = dojox.lang.tests.declareOld, declx = d.declare;
+
+            var benchmarkClassCreation = function(){
+                var a0 = decl0("temp.A0", null, {m1: function(){}, m2: function(){}, m3: function(){}}),
+                    b0 = decl0("temp.B0", a0, {m1: function(){}, m2: function(){}, m3: function(){}}),
+                    c0 = decl0("temp.C0", b0, {m1: function(){}, m2: function(){}, m3: function(){}}),
+
+                    ax = declx("temp.Ax", null, {m1: function(){}, m2: function(){}, m3: function(){}}),
+                    bx = declx("temp.Bx", ax, {m1: function(){}, m2: function(){}, m3: function(){}}),
+                    cx = declx("temp.Cx", bx, {m1: function(){}, m2: function(){}, m3: function(){}}),
+
+                    group = [
+                        {
+                            name: "old/A",
+                            fun:  function(){ decl0("temp.test.A", null, {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "new/A",
+                            fun:  function(){ declx("temp.test.A", null, {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "old/B",
+                            fun:  function(){ decl0("temp.test.B", temp.A0, {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "new/B",
+                            fun:  function(){ declx("temp.test.B", temp.Ax, {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "old/C",
+                            fun:  function(){ decl0("temp.test.C", temp.B0, {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "new/C",
+                            fun:  function(){ declx("temp.test.C", temp.Bx, {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "old/D",
+                            fun:  function(){ decl0("temp.test.D", temp.C0, {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "new/D",
+                            fun:  function(){ declx("temp.test.D", temp.Cx, {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        }
+                    ];
+                registerGroup(group, 0, COUNT, "result", "Create a class (single inheritance)");
+            };
+
+            var benchmarkClassMixing = function(){
+                var a0 = decl0("temp.A0", null, {m1: function(){}, m2: function(){}, m3: function(){}}),
+                    b0 = decl0("temp.B0", null, {m1: function(){}, m2: function(){}, m3: function(){}}),
+                    c0 = decl0("temp.C0", null, {m1: function(){}, m2: function(){}, m3: function(){}}),
+
+                    ax = declx("temp.Ax", null, {m1: function(){}, m2: function(){}, m3: function(){}}),
+                    bx = declx("temp.Bx", null, {m1: function(){}, m2: function(){}, m3: function(){}}),
+                    cx = declx("temp.Cx", null, {m1: function(){}, m2: function(){}, m3: function(){}}),
+
+                    group = [
+                        {
+                            name: "old/A",
+                            fun:  function(){ decl0("temp.test.A", temp.A0, {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "new/A",
+                            fun:  function(){ declx("temp.test.A", temp.Ax, {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "old/A,B",
+                            fun:  function(){ decl0("temp.test.B", [temp.A0, temp.B0], {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "new/A,B",
+                            fun:  function(){ declx("temp.test.B", [temp.Ax, temp.Bx], {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "old/A,B,C",
+                            fun:  function(){ decl0("temp.test.C", [temp.A0, temp.B0, temp.C0], {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        },
+                        {
+                            name: "new/A,B,C",
+                            fun:  function(){ declx("temp.test.C", [temp.Ax, temp.Bx, temp.Cx], {m1: function(){}, m2: function(){}, m3: function(){}}); }
+                        }
+                    ];
+                registerGroup(group, 0, COUNT, "result", "Create a class with mixins");
+            };
+
+            var benchmarkConstructor = function(){
+                var A0 = decl0("temp.A0", null, {constructor: function(a){ this.a = a; }}),
+                    B0 = decl0("temp.B0", A0, {constructor: function(a, b){ this.b = b; }}),
+                    C0 = decl0("temp.C0", B0, {constructor: function(a, b, c){ this.c = c; }}),
+                    D0 = decl0("temp.D0", C0, {constructor: function(a, b, c, d){ this.d = d; }}),
+
+                    Ax = declx("temp.Ax", null, {constructor: function(a){ this.a = a; }}),
+                    Bx = declx("temp.Bx", Ax, {constructor: function(a, b){ this.b = b; }}),
+                    Cx = declx("temp.Cx", Bx, {constructor: function(a, b, c){ this.c = c; }}),
+                    Dx = declx("temp.Dx", Cx, {constructor: function(a, b, c, d){ this.d = d; }}),
+
+                    group = [
+                        {
+                            name: "old/A",
+                            fun:  function(){ var t = new A0("a"); }
+                        },
+                        {
+                            name: "new/A",
+                            fun:  function(){ var t = new Ax("a"); }
+                        },
+                        {
+                            name: "old/B",
+                            fun:  function(){ var t = new B0("a", "b"); }
+                        },
+                        {
+                            name: "new/B",
+                            fun:  function(){ var t = new Bx("a", "b"); }
+                        },
+                        {
+                            name: "old/C",
+                            fun:  function(){ var t = new C0("a", "b", "c"); }
+                        },
+                        {
+                            name: "new/C",
+                            fun:  function(){ var t = new Cx("a", "b", "c"); }
+                        },
+                        {
+                            name: "old/D",
+                            fun:  function(){ var t = new D0("a", "b", "c", "d"); }
+                        },
+                        {
+                            name: "new/D",
+                            fun:  function(){ var t = new Dx("a", "b", "c", "d"); }
+                        }
+                    ];
+                registerGroup(group, 0, COUNT, "result", "Create an instance");
+            };
+
+            var benchmarkRegularCalls = function(){
+                var A0 = decl0("temp.A0", null, {ma: function(a){ return this.a = a; }}),
+                    B0 = decl0("temp.B0", A0, {mb: function(b){ return this.b = b; }}),
+                    C0 = decl0("temp.C0", B0, {mc: function(c){ return this.c = c; }}),
+                    D0 = decl0("temp.D0", C0, {md: function(d){ return this.d = d; }}),
+
+                    Ax = declx("temp.Ax", null, {ma: function(a){ return this.a = a; }}),
+                    Bx = declx("temp.Bx", Ax, {mb: function(b){ return this.b = b; }}),
+                    Cx = declx("temp.Cx", Bx, {mc: function(c){ return this.c = c; }}),
+                    Dx = declx("temp.Dx", Cx, {md: function(d){ return this.d = d; }}),
+
+                    d0 = new D0,
+					dx = new Dx,
+
+                    group = [
+                        {
+                            name: "old/A",
+                            fun:  function(){ d0.ma("x"); }
+                        },
+                        {
+                            name: "new/A",
+                            fun:  function(){ dx.ma("x"); }
+                        },
+                        {
+                            name: "old/B",
+                            fun:  function(){ d0.mb("x"); }
+                        },
+                        {
+                            name: "new/B",
+                            fun:  function(){ dx.mb("x"); }
+                        },
+                        {
+                            name: "old/C",
+                            fun:  function(){ d0.mc("x"); }
+                        },
+                        {
+                            name: "new/C",
+                            fun:  function(){ dx.mc("x"); }
+                        },
+                        {
+                            name: "old/D",
+                            fun:  function(){ d0.md("x"); }
+                        },
+                        {
+                            name: "new/D",
+                            fun:  function(){ dx.md("x"); }
+                        }
+                    ];
+                registerGroup(group, 0, COUNT, "result", "Call a method");
+            };
+
+            var benchmarkInheritedCalls = function(){
+                var A0 = decl0("temp.A0", null, {m: function(a){ return this.a = a; }}),
+                    B0 = decl0("temp.B0", A0, {m: function(b){ return this.b = this.inherited(arguments); }}),
+                    C0 = decl0("temp.C0", B0, {m: function(c){ return this.c = this.inherited(arguments); }}),
+                    D0 = decl0("temp.D0", C0, {m: function(d){ return this.d = this.inherited(arguments); }}),
+
+                    Ax = declx("temp.Ax", null, {m: function(a){ return this.a = a; }}),
+                    Bx = declx("temp.Bx", Ax, {m: function(b){ return this.b = this.inherited(arguments); }}),
+                    Cx = declx("temp.Cx", Bx, {m: function(c){ return this.c = this.inherited(arguments); }}),
+                    Dx = declx("temp.Dx", Cx, {m: function(d){ return this.d = this.inherited(arguments); }}),
+
+                    b0 = new B0,
+                    bx = new Bx,
+
+                    c0 = new C0,
+                    cx = new Cx,
+
+                    d0 = new D0,
+                    dx = new Dx,
+
+                    group = [
+                        {
+                            name: "old/B",
+                            fun:  function(){ b0.m("x"); }
+                        },
+                        {
+                            name: "new/B",
+                            fun:  function(){ bx.m("x"); }
+                        },
+                        {
+                            name: "old/C",
+                            fun:  function(){ c0.m("x"); }
+                        },
+                        {
+                            name: "new/C",
+                            fun:  function(){ cx.m("x"); }
+                        },
+                        {
+                            name: "old/D",
+                            fun:  function(){ d0.m("x"); }
+                        },
+                        {
+                            name: "new/D",
+                            fun:  function(){ dx.m("x"); }
+                        }
+                    ];
+                registerGroup(group, 0, COUNT, "result", "Call an inherited method");
+            };
+
+            var benchmarkChains = function(){
+                var	A0 = decl0("temp.A0", null, {m: function(a){ this.a = a; }}),
+                    B0 = decl0("temp.B0", A0, {m: function(b){ this.inherited(arguments); this.b = b; }}),
+                    C0 = decl0("temp.C0", B0, {m: function(c){ this.inherited(arguments); this.c = c; }}),
+                    D0 = decl0("temp.D0", C0, {m: function(d){ this.inherited(arguments); this.d = d; }}),
+
+                    Ax = declx("temp.Ax", null, {m: function(a){ this.a = a; }, "-chains-": {m: "after"}}),
+                    Bx = declx("temp.Bx", Ax, {m: function(b){ this.b = b; }}),
+                    Cx = declx("temp.Cx", Bx, {m: function(c){ this.c = c; }}),
+                    Dx = declx("temp.Dx", Cx, {m: function(d){ this.d = d; }}),
+
+                    b0 = new B0,
+                    bx = new Bx,
+
+                    c0 = new C0,
+                    cx = new Cx,
+
+                    d0 = new D0,
+                    dx = new Dx,
+
+                    group = [
+                        {
+                            name: "old/B",
+                            fun:  function(){ b0.m("x"); }
+                        },
+                        {
+                            name: "new/B",
+                            fun:  function(){ bx.m("x"); }
+                        },
+                        {
+                            name: "old/C",
+                            fun:  function(){ c0.m("x"); }
+                        },
+                        {
+                            name: "new/C",
+                            fun:  function(){ cx.m("x"); }
+                        },
+                        {
+                            name: "old/D",
+                            fun:  function(){ d0.m("x"); }
+                        },
+                        {
+                            name: "new/D",
+                            fun:  function(){ dx.m("x"); }
+                        }
+                    ];
+                registerGroup(group, 0, COUNT, "result", "Call a chain");
+            };
+
+            var startBenchmarks = function(){
+                console.log("Used parameters: count=" + COUNT + " limit=" + LIMIT + "ms delay=" + DELAY + "ms");
+                benchmarkClassCreation();
+                benchmarkClassMixing();
+                benchmarkConstructor();
+                //benchmarkRegularCalls();
+                benchmarkInheritedCalls();
+                benchmarkChains();
+				run();
+            };
+
+			//dojo.addOnLoad(startBenchmarks);
+		</script>
+	</head>
+	<body>
+		<p>Warning: the benchmark takes several minutes, wait for a dialog box.</p>
+		<p>Color legend: <span class="fastest">the fastest</span>, <span class="stablest">the most stable</span>, <span class="fastest stablest">the fastest and the most stable</span></p>
+		<p><button onclick="startBenchmarks()">Start</button></p>
+        <div id="result"></div>
+	</body>
+</html>
diff --git a/dojox/lang/tests/curry.js b/dojox/lang/tests/curry.js
new file mode 100644
index 0000000..5dc4805
--- /dev/null
+++ b/dojox/lang/tests/curry.js
@@ -0,0 +1,27 @@
+dojo.provide("dojox.lang.tests.curry");
+
+dojo.require("dojox.lang.functional.curry");
+
+(function(){
+	var df = dojox.lang.functional, add5 = df.curry("+")(5), sub3 = df.curry("_-3"), fun = df.lambda("100*a + 10*b + c");
+	tests.register("dojox.lang.tests.curry", [
+		function testCurry1(t){ t.assertEqual(df.curry("+")(1, 2), 3); },
+		function testCurry2(t){ t.assertEqual(df.curry("+")(1)(2), 3); },
+		function testCurry3(t){ t.assertEqual(df.curry("+")(1, 2, 3), 3); },
+		function testCurry4(t){ t.assertEqual(add5(1), 6); },
+		function testCurry5(t){ t.assertEqual(add5(3), 8); },
+		function testCurry6(t){ t.assertEqual(add5(5), 10); },
+		function testCurry7(t){ t.assertEqual(sub3(1), -2); },
+		function testCurry8(t){ t.assertEqual(sub3(3), 0); },
+		function testCurry9(t){ t.assertEqual(sub3(5), 2); },
+		
+		function testPartial1(t){ t.assertEqual(df.partial(fun, 1, 2, 3)(), 123); },
+		function testPartial2(t){ t.assertEqual(df.partial(fun, 1, 2, df.arg)(3), 123); },
+		function testPartial3(t){ t.assertEqual(df.partial(fun, 1, df.arg, 3)(2), 123); },
+		function testPartial4(t){ t.assertEqual(df.partial(fun, 1, df.arg, df.arg)(2, 3), 123); },
+		function testPartial5(t){ t.assertEqual(df.partial(fun, df.arg, 2, 3)(1), 123); },
+		function testPartial6(t){ t.assertEqual(df.partial(fun, df.arg, 2, df.arg)(1, 3), 123); },
+		function testPartial7(t){ t.assertEqual(df.partial(fun, df.arg, df.arg, 3)(1, 2), 123); },
+		function testPartial8(t){ t.assertEqual(df.partial(fun, df.arg, df.arg, df.arg)(1, 2, 3), 123); }
+	]);
+})();
diff --git a/dojox/lang/tests/declare-old.js b/dojox/lang/tests/declare-old.js
new file mode 100644
index 0000000..5bf168f
--- /dev/null
+++ b/dojox/lang/tests/declare-old.js
@@ -0,0 +1,244 @@
+dojo.provide("dojox.lang.tests.declare-old");
+
+// the old file copied and modified here for testing
+
+// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
+
+dojox.lang.tests.declareOld = function(/*String*/ className, /*Function|Function[]*/ superclass, /*Object*/ props){
+	//	summary: 
+	//		Create a feature-rich constructor from compact notation
+	//
+	//	description:
+	//		Create a feature-rich constructor from compact notation
+	//
+	//	className:
+	//		The name of the constructor (loosely, a "class")
+	//		stored in the "declaredClass" property in the created prototype
+	//	superclass:
+	//		May be null, a Function, or an Array of Functions. If an array, 
+	//		the first element is used as the prototypical ancestor and
+	//		any following Functions become mixin ancestors.
+	//	props:
+	//		An object whose properties are copied to the
+	//		created prototype.
+	//		Add an instance-initialization function by making it a property 
+	//		named "constructor".
+	//	description:
+	//		Create a constructor using a compact notation for inheritance and
+	//		prototype extension. 
+	//
+	//		All superclasses (including mixins) must be Functions (not simple Objects).
+	//
+	//		Mixin ancestors provide a type of multiple inheritance. Prototypes of mixin 
+	//		ancestors are copied to the new class: changes to mixin prototypes will
+	//		not affect classes to which they have been mixed in.
+	//
+	//		"className" is cached in "declaredClass" property of the new class.
+	//
+	//	example:
+	//		Declare a class with no ancestors.
+	//	|	dojo.declare("my.ClassyThing", null, {
+	//	|		aProperty:"string",
+	//	|		constructor: function(args){
+	//	|			dojo.mixin(this, args);	
+	//	|		}
+	//	|	});
+	//
+	//	example:
+	//		Declare a class inheriting from my.classed.Foo
+	//	|	dojo.declare("my.classes.Bar", my.classes.Foo, {
+	//	|		// properties to be added to the class prototype
+	//	|		someValue: 2,
+	//	|		// initialization function
+	//	|		constructor: function(){
+	//	|			this.myComplicatedObject = new ReallyComplicatedObject(); 
+	//	|		},
+	//	|		// other functions
+	//	|		someMethod: function(){ 
+	//	|			doStuff(); 
+	//	|		}
+	//	|	);
+	//
+	//	example:
+	//		Declare a class inherting from two mixins, handling multiple constructor args
+	//	|	dojo.declare("my.ComplexMix", [my.BaseClass, my.MixedClass],{
+	//	|		constructor: function(a, b){
+	//	|			// someone called `new my.ComplexMix("something", "maybesomething");`
+	//	|		}
+	//	|	});
+
+	// process superclass argument
+	var dd = arguments.callee, mixins;
+	if(dojo.isArray(superclass)){
+		mixins = superclass;
+		superclass = mixins.shift();
+	}
+	// construct intermediate classes for mixins
+	if(mixins){
+		dojo.forEach(mixins, function(m, i){
+			if(!m){ throw(className + ": mixin #" + i + " is null"); } // It's likely a required module is not loaded
+			superclass = dd._delegate(superclass, m);
+		});
+	}
+	// create constructor
+	var ctor = dd._delegate(superclass);
+	// extend with "props"
+	props = props || {};
+	ctor.extend(props);
+	// more prototype decoration
+	dojo.extend(ctor, { declaredClass: className, _constructor: props.constructor/*, preamble: null*/ });
+	// special help for IE
+	ctor.prototype.constructor = ctor;
+	// create named reference
+	return dojo.setObject(className, ctor); // Function
+};
+
+dojo.mixin(dojox.lang.tests.declareOld, {
+	_delegate: function(base, mixin){
+		var bp = (base || 0).prototype, mp = (mixin || 0).prototype, dd = dojox.lang.tests.declareOld;
+		// fresh constructor, fresh prototype
+		var ctor = dd._makeCtor();
+		// cache ancestry
+		dojo.mixin(ctor, { superclass: bp, mixin: mp, extend: dd._extend });
+		// chain prototypes
+		if(base){ ctor.prototype = dojo._delegate(bp); }
+		// add mixin and core
+		dojo.extend(ctor, dd._core, mp || 0, { _constructor: null, preamble: null });
+		// special help for IE
+		ctor.prototype.constructor = ctor;
+		// name this class for debugging
+		ctor.prototype.declaredClass = (bp || 0).declaredClass + '_' + (mp || 0).declaredClass;
+		return ctor;
+	},
+	_extend: function(props){
+		var i, fn;
+		for(i in props){ if(dojo.isFunction(fn=props[i]) && !0[i]){fn.nom=i;fn.ctor=this;} }
+		dojo.extend(this, props);
+	},
+	_makeCtor: function(){
+		// we have to make a function, but don't want to close over anything
+		return function(){ this._construct(arguments); };
+	},
+	_core: { 
+		_construct: function(args){
+			var c = args.callee, s = c.superclass, ct = s && s.constructor, 
+				m = c.mixin, mct = m && m.constructor, a = args, ii, fn;
+			// side-effect of = used on purpose here, lint may complain, don't try this at home
+			if(a[0]){ 
+				// FIXME: preambles for each mixin should be allowed
+				// FIXME: 
+				//		should we allow the preamble here NOT to modify the
+				//		default args, but instead to act on each mixin
+				//		independently of the class instance being constructed
+				//		(for impedence matching)?
+
+				// allow any first argument w/ a "preamble" property to act as a
+				// class preamble (not exclusive of the prototype preamble)
+				if(/*dojo.isFunction*/((fn = a[0].preamble))){ 
+					a = fn.apply(this, a) || a; 
+				}
+			} 
+			// prototype preamble
+			if((fn = c.prototype.preamble)){ a = fn.apply(this, a) || a; }
+			// FIXME: 
+			//		need to provide an optional prototype-settable
+			//		"_explicitSuper" property which disables this
+			// initialize superclass
+			if(ct && ct.apply){ ct.apply(this, a); }
+			// initialize mixin
+			if(mct && mct.apply){ mct.apply(this, a); }
+			// initialize self
+			if((ii = c.prototype._constructor)){ ii.apply(this, args); }
+			// post construction
+			if(this.constructor.prototype == c.prototype && (ct = this.postscript)){ ct.apply(this, args); }
+		},
+		_findMixin: function(mixin){
+			var c = this.constructor, p, m;
+			while(c){
+				p = c.superclass;
+				m = c.mixin;
+				if(m == mixin || (m instanceof mixin.constructor)){ return p; }
+				if(m && m._findMixin && (m = m._findMixin(mixin))){ return m; }
+				c = p && p.constructor;
+			}
+		},
+		_findMethod: function(name, method, ptype, has){
+			// consciously trading readability for bytes and speed in this low-level method
+			var p=ptype, c, m, f;
+			do{
+				c = p.constructor;
+				m = c.mixin;
+				// find method by name in our mixin ancestor
+				if(m && (m = this._findMethod(name, method, m, has))){ return m; }
+				// if we found a named method that either exactly-is or exactly-is-not 'method'
+				if((f = p[name]) && (has == (f == method))){ return p; }
+				// ascend chain
+				p = c.superclass;
+			}while(p);
+			// if we couldn't find an ancestor in our primary chain, try a mixin chain
+			return !has && (p = this._findMixin(ptype)) && this._findMethod(name, method, p, has);
+		},
+		inherited: function(name, args, newArgs){
+			// summary: 
+			//		Call an inherited member function of this declared class.
+			//
+			// description:
+			//		Call an inherited member function of this declared class, allowing advanced
+			//		manipulation of passed arguments to inherited functions.
+			//		Explicitly cannot handle the case of intending to pass no `newArgs`, though
+			//		hoping the use in conjuction with `dojo.hitch`. Calling an inherited 
+			//		function directly via hitch() is not supported.
+			//
+			// name: String? 
+			//		The name of the method to call. If omitted, the special `arguments` passed is
+			//		used to determine the inherited function. All subsequent positional arguments
+			//		are shifted left if `name` has been omitted. (eg: args becomes name)
+			//
+			// args: Object
+			//		An `arguments` object to pass along to the inherited function. Can be in the
+			//		`name` position if `name` has been omitted. This is a literal JavaScript `arguments`
+			//		object, and must be passed.
+			//
+			// newArgs: Array?
+			//		An Array of argument values to pass to the inherited function. If omitted, 
+			//		the original arguments are passed (determined from the `args` variable)
+			// 
+			// example:
+			//		Simply call an inherited function with the same signature.
+			//	|	this.inherited(arguments);
+			// example:
+			//		Call an inherited method, replacing the arguments passed with "replacement" and "args"
+			//	|	this.inherited(arguments, [replacement, args]);
+			// example:
+			//		Call an inherited method, passing an explicit name.
+			//	|	this.inherited("method", arguments);
+			// example:
+			//		Call an inherited method by name, replacing the arguments:
+			//	|	this.inherited("method", arguments, [replacement, args]);
+
+			var a = arguments;
+			// some magic crap that alters `arguments` to shift in the case of missing `name`
+			if(typeof a[0] != "string"){ // inline'd type check
+				newArgs = args;
+				args = name;
+				name = args.callee.nom;
+			}
+			a = newArgs || args; // WARNING: hitch()ed functions may pass a newArgs you aren't expecting.
+			var c = args.callee, p = this.constructor.prototype, fn, mp;
+			// if not an instance override
+			if(this[name] != c || p[name] == c){
+				// start from memoized prototype, or
+				// find a prototype that has property 'name' == 'c'
+				mp = (c.ctor || 0).superclass || this._findMethod(name, c, p, true);
+				if(!mp){ throw(this.declaredClass + ': inherited method "' + name + '" mismatch'); }
+				// find a prototype that has property 'name' != 'c'
+				p = this._findMethod(name, c, mp, false);
+			}
+			// we expect 'name' to be in prototype 'p'
+			fn = p && p[name];
+			if(!fn){ throw( mp.declaredClass + ': inherited method "' + name + '" not found'); }
+			// if the function exists, invoke it in our scope
+			return fn.apply(this, a);
+		}
+	}
+});
diff --git a/dojox/lang/tests/docs.js b/dojox/lang/tests/docs.js
new file mode 100644
index 0000000..c2fae6e
--- /dev/null
+++ b/dojox/lang/tests/docs.js
@@ -0,0 +1,29 @@
+dojo.provide("dojox.lang.tests.docs");
+
+dojo.require("dojox.lang.docs");
+dojo.require("dijit.ColorPalette");
+
+tests.register("dojox.lang.tests.docs", [
+	function notReady(t){
+		t.is(!dijit.ColorPalette.description, true);
+	},
+	function pastClassHasSchema(t){
+		dojox.lang.docs.init();
+		t.is(!!dijit.ColorPalette.description, true);
+		dojox.lang.docs.init(); // make sure it can be called twice without any problems
+		t.is(!!dijit.ColorPalette.properties.defaultTimeout.description, true);
+		t.is(dijit.ColorPalette.properties.defaultTimeout.type, "number");	
+		t.is(dijit.ColorPalette.methods.onChange.parameters[0].type, "string");	
+		t.is(dijit.ColorPalette.methods.onChange.parameters[0].name, "color");
+		t.is(dijit.ColorPalette["extends"], dijit._Widget);		
+	},
+	function futureClassHasSchema(t){
+		dojo.require("dijit.Dialog");
+		t.is(!!dijit.Dialog.description, true);
+		t.is(!!dijit.Dialog.properties.autofocus.description, true);
+		t.is(dijit.Dialog.properties.autofocus.type, "boolean");	
+	},
+	function testSchema(t){
+		
+	}
+]);
diff --git a/dojox/lang/tests/fold.js b/dojox/lang/tests/fold.js
new file mode 100644
index 0000000..b471704
--- /dev/null
+++ b/dojox/lang/tests/fold.js
@@ -0,0 +1,84 @@
+dojo.provide("dojox.lang.tests.fold");
+
+dojo.require("dojox.lang.functional.fold");
+dojo.require("dojox.lang.functional.scan");
+dojo.require("dojox.lang.functional.curry");
+dojo.require("dojox.lang.functional.sequence");
+dojo.require("dojox.lang.functional.listcomp");
+dojo.require("dojox.lang.functional.object");
+
+(function(){
+	var df = dojox.lang.functional, a = df.arg, x = {a: 1, b: 2, c: 3};
+
+	var revArrayIter = function(array){
+		this.array    = array;
+		this.position = array.length - 1;
+	};
+	dojo.extend(revArrayIter, {
+		hasNext:	df.lambda("this.position >= 0"),
+		next:		df.lambda("this.array[this.position--]")
+	});
+
+	tests.register("dojox.lang.tests.fold", [
+		function testFoldl1(t){ t.assertEqual(df.foldl([1, 2, 3], "+", 0), 6); },
+		function testFoldl2(t){ t.assertEqual(df.foldl1([1, 2, 3], "*"), 6); },
+		function testFoldl3(t){ t.assertEqual(df.foldl1([1, 2, 3], "/"), 1/6); },
+		function testFoldl4(t){ t.assertEqual(df.foldl1([1, 2, 3], df.partial(Math.max, a, a)), 3); },
+		function testFoldl5(t){ t.assertEqual(df.foldl1([1, 2, 3], df.partial(Math.min, a, a)), 1); },
+		
+		function testFoldlIter(t){
+			var iter = new revArrayIter([1, 2, 3]);
+			t.assertEqual(df.foldl(iter, "+", 0), 6);
+		},
+		function testFoldl1Iter(t){
+			var iter = new revArrayIter([1, 2, 3]);
+			t.assertEqual(df.foldl1(iter, "/"), 3/2);
+		},
+
+		function testFoldlObj(t){ t.assertEqual(df.foldl(x, "*", 2), 12); },
+		function testFoldl1Obj(t){ t.assertEqual(df.foldl1(x, "+"), 6); },
+		
+		function testFoldr1(t){ t.assertEqual(df.foldr([1, 2, 3], "+", 0), 6); },
+		function testFoldr2(t){ t.assertEqual(df.foldr1([1, 2, 3], "*"), 6); },
+		function testFoldr3(t){ t.assertEqual(df.foldr1([1, 2, 3], "/"), 3/2); },
+		function testFoldr4(t){ t.assertEqual(df.foldr1([1, 2, 3], df.partial(Math.max, a, a)), 3); },
+		function testFoldr5(t){ t.assertEqual(df.foldr1([1, 2, 3], df.partial(Math.min, a, a)), 1); },
+		
+		function testUnfold1(t){
+			// simulate df.repeat()
+			t.assertEqual(
+				df.repeat(10, "2*", 1),
+				df.unfold("x[0] >= 10", "x[1]", "[x[0] + 1, 2 * x[1]]", [0, 1])
+			);
+		},
+		function testUnfold2(t){
+			// simulate df.until()
+			t.assertEqual(
+				df.until(">1024", "2*", 1),
+				df.unfold(">1024", "x", "2*", 1)
+			);
+		},
+		
+		function testScanl1(t){ t.assertEqual(df.scanl([1, 2, 3], "+", 0), [0, 1, 3, 6]); },
+		function testScanl2(t){ t.assertEqual(df.scanl1([1, 2, 3], "*"), [1, 2, 6]); },
+		function testScanl3(t){ t.assertEqual(df.scanl1([1, 2, 3], df.partial(Math.max, a, a)), [1, 2, 3]); },
+		function testScanl4(t){ t.assertEqual(df.scanl1([1, 2, 3], df.partial(Math.min, a, a)), [1, 1, 1]); },
+
+		function testScanlIter(t){
+			var iter = new revArrayIter([1, 2, 3]);
+			t.assertEqual(df.scanl(iter, "+", 0), [0, 3, 5, 6]);
+		},
+		function testScanl1Iter(t){
+			var iter = new revArrayIter([1, 2, 3]);
+			t.assertEqual(df.scanl1(iter, "*"), [3, 6, 6]);
+		},
+		
+		function testScanlObj(t){ t.assertEqual(df.scanl(x, "+", 0), df.scanl(df.values(x), "+", 0)); },
+		function testScanl1Obj(t){ t.assertEqual(df.scanl1(x, "*"), df.scanl1(df.values(x), "*")); },
+
+		function testScanr1(t){ t.assertEqual(df.scanr([1, 2, 3], "+", 0), [6, 5, 3, 0]); },
+		function testScanr2(t){ t.assertEqual(df.scanr1([1, 2, 3], "*"), [6, 6, 3]); },
+		function testScanr3(t){ t.assertEqual(df.scanr1([1, 2, 3], df.partial(Math.max, a, a)), [3, 3, 3]); },
+		function testScanr4(t){ t.assertEqual(df.scanr1([1, 2, 3], df.partial(Math.min, a, a)), [1, 2, 3]); }
+	]);
+})();
diff --git a/dojox/lang/tests/fun_perf.html b/dojox/lang/tests/fun_perf.html
new file mode 100644
index 0000000..9e1da30
--- /dev/null
+++ b/dojox/lang/tests/fun_perf.html
@@ -0,0 +1,178 @@
+<html>
+	<head>
+		<title>Clocking fun</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+		<script type="text/javascript" src="../functional.js"></script>
+		<script type="text/javascript" src="../functional/sequence.js"></script>
+		<script type="text/javascript" src="../functional/fold.js"></script>
+		<script type="text/javascript">
+			var clock = function(body){
+				var b = new Date();
+				body();
+				var e = new Date();
+				return e.getTime() - b.getTime();	// in ms
+			};
+			
+			var log = function(name, body){
+				var ms = clock(body);
+				console.log(name + ":", ms);
+			};
+
+			var LEN = 2000, ITER = 200, tests = {},
+				df = dojox.lang.functional,
+				sample = df.repeat(LEN, "+1", 0),
+				add = df.lambda("+"),
+				isOdd = df.lambda("%2");
+				
+			// filter
+			tests["raw filter"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					var t = [];
+					for(var j = 0; j < sample.length; ++j){
+						if(isOdd(sample[j])){ t.push(sample[j]); }
+					}
+				}
+			};
+			tests["dojo.filter"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					dojo.filter(sample, isOdd);
+				}
+			};
+			tests["df.filter"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.filter(sample, isOdd);
+				}
+			};
+			if(sample.filter){
+				tests["Array.prototype.filter"] = function(){
+					for(var i = 0; i < ITER; ++i){
+						sample.filter(isOdd);
+					}
+				};
+			}
+
+			// map
+			tests["raw map"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					var t = [];
+					for(var j = 0; j < sample.length; ++j){
+						t.push(isOdd(sample[j]));
+					}
+				}
+			};
+			tests["dojo.map"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					dojo.map(sample, isOdd);
+				}
+			};
+			tests["df.map"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.map(sample, isOdd);
+				}
+			};
+			if(sample.map){
+				tests["Array.prototype.map"] = function(){
+					for(var i = 0; i < ITER; ++i){
+						sample.map(isOdd);
+					}
+				};
+			}
+
+			// forEach
+			tests["raw forEach"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					for(var j = 0; j < sample.length; ++j){
+						isOdd(sample[j]);
+					}
+				}
+			};
+			tests["dojo.forEach"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					dojo.forEach(sample, isOdd);
+				}
+			};
+			tests["df.forEach"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample, isOdd);
+				}
+			};
+			if(sample.forEach){
+				tests["Array.prototype.forEach"] = function(){
+					for(var i = 0; i < ITER; ++i){
+						sample.forEach(isOdd);
+					}
+				};
+			}
+
+			// reduce
+			tests["raw reduce"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					var z = 0;
+					for(var j = 0; j < sample.length; ++j){
+						z = add(z, sample[j]);
+					}
+				}
+			};
+			tests["df.reduce"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.reduce(sample, add, 0);
+				}
+			};
+			if(sample.reduce){
+				tests["Array.prototype.reduce"] = function(){
+					for(var i = 0; i < ITER; ++i){
+						sample.reduce(add, 0);
+					}
+				};
+			}
+
+			// reduceRight
+			tests["raw reduceRight"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					var z = 0;
+					for(var j = sample.length - 1; j >= 0; --j){
+						z = add(z, sample[j]);
+					}
+				}
+			};
+			tests["df.reduceRight"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.reduceRight(sample, add, 0);
+				}
+			};
+			if(sample.reduceRight){
+				tests["Array.prototype.reduceRight"] = function(){
+					for(var i = 0; i < ITER; ++i){
+						sample.reduceRight(add, 0);
+					}
+				};
+			}
+			
+			var keys = df.keys(tests), i = 0;
+			
+			var doTest = function(){
+				log(keys[i], tests[keys[i]]);
+				++i;
+				if(i < keys.length){
+					setTimeout(doTest, 20);
+				}else{
+					console.log("that's all");
+				}
+			};
+			
+			var test = function(){
+				i = 0;
+				setTimeout(doTest, 20);
+			};
+				
+			//dojo.addOnLoad(test);
+		</script>
+	</head>
+	<body>
+		<p>This test is meant to run with Firebug. Open the console to see the output.</p>
+		<p><button onclick="test()">Start</button></p>
+	</body>
+</html>
diff --git a/dojox/lang/tests/lambda.js b/dojox/lang/tests/lambda.js
new file mode 100644
index 0000000..04d44a7
--- /dev/null
+++ b/dojox/lang/tests/lambda.js
@@ -0,0 +1,20 @@
+dojo.provide("dojox.lang.tests.lambda");
+
+dojo.require("dojox.lang.functional");
+dojo.require("dojox.lang.functional.sequence");
+
+(function(){
+	var df = dojox.lang.functional;
+	tests.register("dojox.lang.tests.lambda", [
+		function testLambda1(t){ t.assertEqual(df.repeat(3, "3*", 1), [1, 3, 9]); },
+		function testLambda2(t){ t.assertEqual(df.repeat(3, "*3", 1), [1, 3, 9]); },
+		function testLambda3(t){ t.assertEqual(df.repeat(3, "_*3", 1), [1, 3, 9]); },
+		function testLambda4(t){ t.assertEqual(df.repeat(3, "3*_", 1), [1, 3, 9]); },
+		function testLambda5(t){ t.assertEqual(df.repeat(3, "n->n*3", 1), [1, 3, 9]); },
+		function testLambda6(t){ t.assertEqual(df.repeat(3, "n*3", 1), [1, 3, 9]); },
+		function testLambda7(t){ t.assertEqual(df.repeat(3, "3*m", 1), [1, 3, 9]); },
+		function testLambda8(t){ t.assertEqual(df.repeat(3, "->1", 1), [1, 1, 1]); },
+		function testLambda9(t){ t.assertEqual(df.repeat(3, function(n){ return n * 3; }, 1), [1, 3, 9]); },
+		function testLambda10(t){ t.assertEqual(df.repeat(3, ["_-1", ["*3"]], 1), [1, 2, 5]); }
+	]);
+})();
diff --git a/dojox/lang/tests/listcomp.js b/dojox/lang/tests/listcomp.js
new file mode 100644
index 0000000..a6c0ff0
--- /dev/null
+++ b/dojox/lang/tests/listcomp.js
@@ -0,0 +1,24 @@
+dojo.provide("dojox.lang.tests.listcomp");
+
+dojo.require("dojox.lang.functional.listcomp");
+dojo.require("dojox.lang.functional.sequence");
+
+(function(){
+	var df = dojox.lang.functional;
+	tests.register("dojox.lang.tests.listcomp", [
+		function testIterator1(t){ t.assertEqual(df.repeat(3, function(n){ return n + 1; }, 0), [0, 1, 2]); },
+		function testIterator2(t){ t.assertEqual(df.repeat(3, function(n){ return n * 3; }, 1), [1, 3, 9]); },
+		function testIterator3(t){ t.assertEqual(df.until(function(n){ return n > 10; }, function(n){ return n * 3; }, 1), [1, 3, 9]); },
+		
+		function testListcomp1(t){ t.assertEqual(df.listcomp("i for(var i=0; i<3; ++i)"), [0, 1, 2]); },
+		function testListcomp2(t){ t.assertEqual(df.listcomp("i*j for(var i=0; i<3; ++i) for(var j=0; j<3; ++j)"), [0, 0, 0, 0, 1, 2, 0, 2, 4]); },
+		function testListcomp3(t){ t.assertEqual(df.listcomp("i*j for(var i=0; i<3; ++i) if(i%2==1) for(var j=0; j<3; ++j)"), [0, 1, 2]); },
+		function testListcomp4(t){ t.assertEqual(df.listcomp("i+j for(var i=0; i<3; ++i) for(var j=0; j<3; ++j)"), [0, 1, 2, 1, 2, 3, 2, 3, 4]); },
+		function testListcomp5(t){ t.assertEqual(df.listcomp("i+j for(var i=0; i<3; ++i) if(i%2==1) for(var j=0; j<3; ++j)"), [1, 2, 3]); },
+		function testListcomp6(t){ t.assertEqual(df.listcomp("i for(i=0; i<3; ++i)"), [0, 1, 2]); },
+		function testListcomp7(t){ t.assertEqual(df.listcomp("i*j for(i=0; i<3; ++i) for(j=0; j<3; ++j)"), [0, 0, 0, 0, 1, 2, 0, 2, 4]); },
+		function testListcomp8(t){ t.assertEqual(df.listcomp("i*j for(i=0; i<3; ++i) if(i%2==1) for(j=0; j<3; ++j)"), [0, 1, 2]); },
+		function testListcomp9(t){ t.assertEqual(df.listcomp("i+j for(i=0; i<3; ++i) for(j=0; j<3; ++j)"), [0, 1, 2, 1, 2, 3, 2, 3, 4]); },
+		function testListcomp10(t){ t.assertEqual(df.listcomp("i+j for(i=0; i<3; ++i) if(i%2==1) for(j=0; j<3; ++j)"), [1, 2, 3]); }
+	]);
+})();
diff --git a/dojox/lang/tests/main.js b/dojox/lang/tests/main.js
new file mode 100644
index 0000000..71565aa
--- /dev/null
+++ b/dojox/lang/tests/main.js
@@ -0,0 +1,19 @@
+dojo.provide("dojox.lang.tests.main");
+
+try{
+	dojo.require("dojox.lang.tests.listcomp");
+	dojo.require("dojox.lang.tests.lambda");
+	dojo.require("dojox.lang.tests.fold");
+	dojo.require("dojox.lang.tests.curry");
+	dojo.require("dojox.lang.tests.misc");
+	dojo.require("dojox.lang.tests.array");
+	dojo.require("dojox.lang.tests.object");
+	dojo.require("dojox.lang.tests.oo_mixin");
+	dojo.require("dojox.lang.tests.async");
+	dojo.require("dojox.lang.tests.recomb");
+	dojo.require("dojox.lang.tests.observable");
+	dojo.require("dojox.lang.tests.docs");
+	dojo.require("dojox.lang.tests.typed");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/lang/tests/misc.js b/dojox/lang/tests/misc.js
new file mode 100644
index 0000000..dfe2f58
--- /dev/null
+++ b/dojox/lang/tests/misc.js
@@ -0,0 +1,21 @@
+dojo.provide("dojox.lang.tests.misc");
+
+dojo.require("dojox.lang.functional.zip");
+
+(function(){
+	var df = dojox.lang.functional, fun = df.lambda("100*a + 10*b + c");
+	
+	tests.register("dojox.lang.tests.misc", [
+		function testZip1(t){ t.assertEqual(df.zip([1, 2, 3], [4, 5, 6]), [[1, 4], [2, 5], [3, 6]]); },
+		function testZip2(t){ t.assertEqual(df.zip([1, 2], [3, 4], [5, 6]), [[1, 3, 5], [2, 4, 6]]); },
+		
+		function testUnzip1(t){ t.assertEqual(df.unzip([[1, 4], [2, 5], [3, 6]]), [[1, 2, 3], [4, 5, 6]]); },
+		function testUnzip2(t){ t.assertEqual(df.unzip([[1, 3, 5], [2, 4, 6]]), [[1, 2], [3, 4], [5, 6]]); },
+		
+		function testMixer(t){ t.assertEqual(df.mixer(fun, [1, 2, 0])(3, 1, 2), 123); },
+		function testFlip(t){ t.assertEqual(df.flip(fun)(3, 2, 1), 123); },
+		
+		function testCompose1(t){ t.assertEqual(df.lambda(["+5", "*3"])(8), 8 * 3 + 5); },
+		function testCompose2(t){ t.assertEqual(df.lambda(["+5", "*3"].reverse())(8), (8 + 5) * 3); }
+	]);
+})();
diff --git a/dojox/lang/tests/object.js b/dojox/lang/tests/object.js
new file mode 100644
index 0000000..ad03331
--- /dev/null
+++ b/dojox/lang/tests/object.js
@@ -0,0 +1,18 @@
+dojo.provide("dojox.lang.tests.object");
+
+dojo.require("dojox.lang.functional.object");
+
+(function(){
+	var df = dojox.lang.functional, x = {a: 1, b: 2, c: 3},
+		print = function(v, i){ this.push("[" + i + "] = " + v); },
+		show = function(o){ return df.forIn(o, print, []).sort().join(", "); };
+	
+	tests.register("dojox.lang.tests.object", [
+		function testKeys(t){ t.assertEqual(df.keys(x).sort(), ["a", "b", "c"]); },
+		function testValues(t){ t.assertEqual(df.values(x).sort(), [1, 2, 3]); },
+		
+		function testForIn(t){ t.assertEqual(show(x), "[a] = 1, [b] = 2, [c] = 3"); },
+		function testFilterIn(t){ t.assertEqual(show(df.filterIn(x, "%2")), "[a] = 1, [c] = 3"); },
+		function testMapIn(t){ t.assertEqual(show(df.mapIn(x, "+3")), "[a] = 4, [b] = 5, [c] = 6"); }
+	]);
+})();
diff --git a/dojox/lang/tests/observable.js b/dojox/lang/tests/observable.js
new file mode 100644
index 0000000..3091d43
--- /dev/null
+++ b/dojox/lang/tests/observable.js
@@ -0,0 +1,126 @@
+dojo.provide("dojox.lang.tests.observable");
+dojo.require("dojox.lang.observable");
+
+(function(){
+	tests.register("dojox.lang.tests.observable", [
+		function propertyAccessMakeObservable(t){
+			console.log("start");
+			var testStrs = []; 
+			var observable = new dojox.lang.makeObservable(
+				function(obj,i){
+					testStrs.push("onRead " + i);
+					return obj[i];
+				},
+				function(obj,i,value){
+					testStrs.push("onWrite " + i);
+					obj[i] = value;
+				},
+				function(scope,obj,i,args){
+					testStrs.push("onInvoke " + i);
+					return obj[i].apply(scope,args);
+				}
+			);
+			var obj = {foo:"bar",test:function(){
+					return this.foo;
+				}
+			};
+			var newObj = observable(obj);
+			testStrs.push("returned " + newObj.test());
+			newObj.foo = "new";
+			testStrs.push(newObj.foo);
+			t.assertEqual("onInvoke test,onRead foo,returned bar,onWrite foo,onRead foo,new",testStrs.join(','));
+		},
+		function propertyAccessObservable(t){
+			var testStrs = []; 
+			var obj = {foo:"bar",test:function(){
+				return this.foo;
+			}};
+			var newObj = dojox.lang.observable(obj,function(obj,i){
+					testStrs.push("onRead " + i);
+					return obj[i];
+				},function(obj,i,value){
+					testStrs.push("onWrite " + i);
+					obj[i] = value;
+				},function(scope,obj,i,args){
+					testStrs.push("onInvoke " + i);
+					return obj[i].apply(scope,args);
+				}
+			);
+			testStrs.push("returned " + newObj.test());
+			newObj.foo = "new";
+			testStrs.push(newObj.foo);
+			t.assertEqual("onInvoke test,onRead foo,returned bar,onWrite foo,onRead foo,new",testStrs.join(','));
+		},
+		function readonlyProxy(t){
+			console.log("start");
+			var testStrs = []; 
+			var obj = {foo:"bar"};
+			var newObj = dojox.lang.ReadOnlyProxy(obj);
+			testStrs.push(newObj.foo);
+			newObj.foo = "illegal";
+
+			testStrs.push(newObj.foo);
+			obj.foo = "new";
+			testStrs.push(newObj.foo);
+			t.assertEqual("bar,bar,new",testStrs.join(','));
+		},
+		function perf(t){
+			var getter = function(obj,i){
+				return obj[i];
+			};
+			var observable = new dojox.lang.makeObservable(
+				function(obj,i){
+					return obj[i];
+				},
+				function(obj,i,value){
+					obj[i] = value;
+				},
+				function(scope,obj,i,args){
+					return obj[i].apply(scope,args);
+				}
+			);
+			var obj = {foo:"bar",bar:'foo'};
+			var newObj = observable(obj);
+			var start = new Date().getTime();
+			for(var i = 0; i < 100000;i++){ // normal access
+				var a = obj.foo;
+				a = obj.bar;
+			}
+			var store = {
+				getValue:function(item, property,lazyCallback){
+					// summary:
+					//	Gets the value of an item's 'property'
+					//
+					//	item: /* object */
+					//	property: /* string */
+					//		property to look up value for	
+					// lazyCallback: /* function*/ 
+					// 		not part of the API, but if you are using lazy loading properties, you may provide a callback to resume, in order to have asynchronous loading
+					var value = item[property]; 
+					if(value instanceof dojo.Deferred){
+						dojox.rpc._sync = !lazyCallback; // tell the service to operate synchronously (I have some concerns about the "thread" safety with FF3, as I think it does event stacking on sync calls)
+						value.addCallback(function(returned){
+								value = returned;
+								if(lazyCallback){lazyCallback(value);}
+								return value;
+							}
+						);
+						delete dojox.rpc._sync; // revert to normal async behavior
+					}else if(lazyCallback){lazyCallback(value);}
+					return value;
+				}
+			};
+			console.log(new Date().getTime() - start);
+			start = new Date().getTime();
+			for(i = 0; i < 100000;i++){// observed access
+				a = store.getValue(obj,"foo");
+				a = store.getValue(obj,"bar");
+			}
+			console.log(new Date().getTime() - start);
+			start = new Date().getTime();
+			for(i = 0; i < 1000000;i++){ // measure the loop time itself
+			}
+			console.log(new Date().getTime() - start);
+		}
+	]);
+})();
diff --git a/dojox/lang/tests/oo_mixin.js b/dojox/lang/tests/oo_mixin.js
new file mode 100644
index 0000000..6278357
--- /dev/null
+++ b/dojox/lang/tests/oo_mixin.js
@@ -0,0 +1,26 @@
+dojo.provide("dojox.lang.tests.oo_mixin");
+
+dojo.require("dojox.lang.functional.object");
+dojo.require("dojox.lang.oo.mixin");
+dojo.require("dojox.lang.oo.rearrange");
+
+(function(){
+	var df = dojox.lang.functional, oo = dojox.lang.oo,
+		x = {a: 1, b: 2, c: 3},
+		y = {c: 1, d: 2, e: 3, f: 4},
+		z = oo.mixin({}, oo.filter(y, {d: "a", e: "b", f: ""})),
+		q = dojo.clone(x),
+		p = dojo.clone(y),
+		print = function(v, i){ this.push("[" + i + "] = " + v); },
+		show = function(o){ return df.forIn(o, print, []).sort().join(", "); };
+
+	oo.mixin(q, y);
+	oo.mixin(p, x);
+	oo.rearrange(y, {d: "a", e: "b", f: ""});
+
+	tests.register("dojox.lang.tests.oo_mixin", [
+		function testMixin1(t){ t.assertEqual(df.keys(q).sort(), df.keys(p).sort()); },
+		function testMixin2(t){ t.assertEqual(df.keys(x).sort(), df.keys(z).sort()); },
+		function testRearrange(t){ t.assertEqual(df.keys(y).sort(), df.keys(z).sort()); }
+	]);
+})();
diff --git a/dojox/lang/tests/rec_perf.html b/dojox/lang/tests/rec_perf.html
new file mode 100644
index 0000000..3eab63d
--- /dev/null
+++ b/dojox/lang/tests/rec_perf.html
@@ -0,0 +1,484 @@
+<html>
+	<head>
+		<title>Clocking recursion combinators</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+		<script type="text/javascript" src="../functional.js"></script>
+		<script type="text/javascript" src="../functional/linrec.js"></script>
+		<script type="text/javascript" src="../functional/tailrec.js"></script>
+		<script type="text/javascript" src="../functional/numrec.js"></script>
+		<script type="text/javascript" src="../functional/binrec.js"></script>
+		<script type="text/javascript" src="../functional/multirec.js"></script>
+		<script type="text/javascript" src="../functional/sequence.js"></script>
+		<script type="text/javascript">
+			// reference implementations
+			
+			var linrec1 = function(cond, then, before, after){
+				var cond   = df.lambda(cond),
+					then   = df.lambda(then),
+					before = df.lambda(before),
+					after  = df.lambda(after);
+				return function(){
+					if(cond.apply(this, arguments)){
+						return then.apply(this, arguments);
+					}
+					var args = before.apply(this, arguments);
+					var ret  = arguments.callee.apply(this, args);
+					return after.call(this, ret, arguments);
+				};
+			};
+			
+			var linrec2 = function(cond, then, before, after){
+				var cond   = df.lambda(cond),
+					then   = df.lambda(then),
+					before = df.lambda(before),
+					after  = df.lambda(after);
+				return function(){
+					var args = arguments, top, ret;
+					// 1st part
+					for(; !cond.apply(this, args); args = before.apply(this, args)){
+						top = {prev: top, args: args};
+					}
+					ret = then.apply(this, args);
+					//2nd part
+					for(; top; top = top.prev){
+						ret = after.call(this, ret, top.args);
+					}
+					return ret;
+				};
+			};
+
+			var tailrec1 = function(cond, then, before){
+				var cond   = df.lambda(cond),
+					then   = df.lambda(then),
+					before = df.lambda(before);
+				return function(){
+					if(cond.apply(this, arguments)){
+						return then.apply(this, arguments);
+					}
+					var args = before.apply(this, arguments);
+					return arguments.callee.apply(this, args);
+				};
+			};
+			
+			var tailrec2 = function(cond, then, before){
+				var cond   = df.lambda(cond),
+					then   = df.lambda(then),
+					before = df.lambda(before);
+				return function(){
+					var args = arguments;
+					for(; !cond.apply(this, args); args = before.apply(this, args));
+					return then.apply(this, args);
+				};
+			};
+			
+			var numrec1 = function(then, after){
+				var after = df.lambda(after);
+				return function(x){
+					return x ? after.call(this, arguments.callee.call(this, x - 1), x) : then;
+				};
+			};
+			
+			var numrec2 = function(then, after){
+				var after = df.lambda(after);
+				return function(x){
+					var ret = then, i;
+					for(i = 1; i <= x; ++i){
+						ret = after.call(this, ret, i);
+					}
+					return ret;
+				};
+			};
+			
+			var binrec1 = function(cond, then, before, after){
+				var cond   = df.lambda(cond),
+					then   = df.lambda(then),
+					before = df.lambda(before),
+					after  = df.lambda(after);
+				return function(){
+					if(cond.apply(this, arguments)){
+						return then.apply(this, arguments);
+					}
+					var args = before.apply(this, arguments);
+					var ret1 = arguments.callee.apply(this, args[0]);
+					var ret2 = arguments.callee.apply(this, args[1]);
+					return after.call(this, ret1, ret2, arguments);
+				};
+			};
+			
+			var binrec2 = function(cond, then, before, after){
+				var cond   = df.lambda(cond),
+					then   = df.lambda(then),
+					before = df.lambda(before),
+					after  = df.lambda(after);
+				return function(){
+					var top1, top2, ret, args = arguments;
+					// first part: start the pump
+					while(!cond.apply(this, args)){
+						ret = before.apply(this, args);
+						top1 = {prev: top1, args: ret[1]};
+						top2 = {prev: top2, args: args};
+						args = ret[0];
+					}
+					for(;;){
+						// second part: mop up
+						do{
+							ret = then.apply(this, args);
+							if(!top2){
+								return ret;
+							}
+							while("ret" in top2){
+								ret = after.call(this, top2.ret, ret, top2.args);
+								if(!(top2 = top2.prev)){
+									return ret;
+								}
+							}
+							top2.ret = ret;
+							args = top1.args;
+							top1 = top1.prev;
+						}while(cond.apply(this, args));
+						// first part (encore)
+						do{
+							ret = before.apply(this, args);
+							top1 = {prev: top1, args: ret[1]};
+							top2 = {prev: top2, args: args};
+							args = ret[0];
+						}while(!cond.apply(this, args));
+					}
+				};
+			};
+
+			var multirec1 = function(cond, then, before, after){
+				var cond   = df.lambda(cond),
+					then   = df.lambda(then),
+					before = df.lambda(before),
+					after  = df.lambda(after);
+				return function(){
+					if(cond.apply(this, arguments)){
+						return then.apply(this, arguments);
+					}
+					var args = before.apply(this, arguments),
+						ret  = new Array(args.length);
+					for(var i = 0; i < args.length; ++i){
+						ret[i] = arguments.callee.apply(this, args[i]);
+					}
+					return after.call(this, ret, arguments);
+				};
+			};
+			
+			var multirec2 = function(cond, then, before, after){
+				var cond   = df.lambda(cond),
+					then   = df.lambda(then),
+					before = df.lambda(before),
+					after  = df.lambda(after);
+				return function(){
+					var top = {args: arguments}, args, ret, parent, i;
+					for(;;){
+						for(;;){
+							if(top.old){
+								ret = after.call(this, top.ret, top.old);
+								break;
+							}
+							args = top.args;
+							if(cond.apply(this, args)){
+								ret = then.apply(this, args);
+								break;
+							}
+							top.old = args;
+							args = before.apply(this, args);
+							top.ret = [];
+							parent = top;
+							for(i = args.length - 1; i >= 0; --i){
+								top = {prev: top, args: args[i], parent: parent};
+							}
+						}
+						if(!(parent = top.parent)){
+							return ret;
+						}
+						parent.ret.push(ret);
+						top = top.prev;
+					}
+				};
+			};
+
+			// tests
+
+			var clock = function(body){
+				var b = new Date();
+				body();
+				var e = new Date();
+				return e.getTime() - b.getTime();	// in ms
+			};
+			
+			var log = function(name, body){
+				var ms = clock(body);
+				console.log(name + ":", ms);
+			};
+
+			var LEN1 = 15, LEN2 = 10, ITER = 1000, tests = {},
+				df = dojox.lang.functional,
+				sample1 = df.repeat(LEN1, "+1", 0),
+				sample2 = df.repeat(LEN2, "+1", 0);
+				
+			var fact1 = function(n){
+				var ret = 1;
+				for(var i = 2; i <= n; ++i){
+					ret *= i;
+				}
+				return ret;
+			};
+			tests["factorial: raw iterative"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact1);
+				}
+			};
+			
+			var fact2 = function(n){ return n ? n * arguments.callee.call(this, n - 1) : 1; };
+			tests["factorial: raw recursion"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact2);
+				}
+			};
+			
+			var fact3_1 = linrec1("<= 1", "1", "[n - 1]", "a * b[0]");
+			tests["factorial: linrec1 (recursive reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact3_1);
+				}
+			};
+			
+			var fact3_2 = linrec2("<= 1", "1", "[n - 1]", "a * b[0]");
+			tests["factorial: linrec2 (iterative reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact3_2);
+				}
+			};
+			
+			var fact3 = df.linrec("<= 1", "1", "[n - 1]", "a * b[0]");
+			tests["factorial: linrec"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact3);
+				}
+			};
+			
+			var fact4_1 = numrec1(1, "*");
+			tests["factorial: numrec1 (recursive reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact4_1);
+				}
+			};
+			
+			var fact4_2 = numrec2(1, "*");
+			tests["factorial: numrec2 (iterative reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact4_2);
+				}
+			};
+			
+			var fact4 = df.numrec(1, "*");
+			tests["factorial: numrec"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact4);
+				}
+			};
+			
+			var fact5_1a = tailrec1("<= 1", "a, b -> b", "[n - 1, n * acc]");
+			var fact5_1 = function(n){ return fact5_1a(n, 1); };
+			tests["factorial: tailrec1 (recursive reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact5_1);
+				}
+			};
+
+			var fact5_2a = tailrec2("<= 1", "a, b -> b", "[n - 1, n * acc]");
+			var fact5_2 = function(n){ return fact5_2a(n, 1); };
+			tests["factorial: tailrec2 (iterative reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact5_2);
+				}
+			};
+
+			var fact5a = df.tailrec("<= 1", "a, b -> b", "[n - 1, n * acc]");
+			var fact5 = function(n){ return fact5a(n, 1); };
+			tests["factorial: tailrec"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact5);
+				}
+			};
+			
+			var fact6_1 = multirec1("<= 0", "1", "[[n - 1]]", "a[0] * b[0]");
+			tests["factorial: multirec1 (recursive reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact6_1);
+				}
+			};
+			
+			var fact6_2 = multirec2("<= 0", "1", "[[n - 1]]", "a[0] * b[0]");
+			tests["factorial: multirec2 (iterative reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact6_2);
+				}
+			};
+			
+			var fact6 = df.multirec("<= 0", "1", "[[n - 1]]", "a[0] * b[0]");
+			tests["factorial: multirec"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample1, fact6);
+				}
+			};
+			
+			var fib1 = function(n){
+				var a = 1, b = 1;
+				for(var i = 2; i <= n; ++i){
+					var c = a + b;
+					b = a;
+					a = c;
+				}
+				return a;
+			};
+			tests["fibonacci: raw iterative"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib1);
+				}
+			};
+			
+			var fib2 = function(n){ return n <= 1 ? 1 : arguments.callee.call(this, n - 1) + arguments.callee.call(this, n - 2); };
+			tests["fibonacci: raw recursion"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib2);
+				}
+			};
+			
+			var fib3a = function(n, next, result){ return n <= 0 ? result : arguments.callee.call(this, n - 1, next + result, next); };
+			var fib3  = function(n){ return fib3a(n, 1, 1); };
+			tests["fibonacci: raw tail recursion"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib3);
+				}
+			};
+
+			var fib4_1 = binrec1("<= 1", "1", "[[n - 1], [n - 2]]", "+");
+			tests["fibonacci: binrec1 (recursive reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib4_1);
+				}
+			};
+
+			var fib4_2 = binrec2("<= 1", "1", "[[n - 1], [n - 2]]", "+");
+			tests["fibonacci: binrec2 (iterative reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib4_2);
+				}
+			};
+
+			var fib4 = df.binrec("<= 1", "1", "[[n - 1], [n - 2]]", "+");
+			tests["fibonacci: binrec"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib4);
+				}
+			};
+			
+			var fib5_1a = tailrec1("<= 0", "a, b, c -> c", "[n - 1, next + result, next]");
+			var fib5_1  = function(n){ return fib5_1a(n, 1, 1); };
+			tests["fibonacci: tailrec1 (recursive reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib5_1);
+				}
+			};
+
+			var fib5_2a = tailrec2("<= 0", "a, b, c -> c", "[n - 1, next + result, next]");
+			var fib5_2  = function(n){ return fib5_2a(n, 1, 1); };
+			tests["fibonacci: tailrec2 (iterative reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib5_2);
+				}
+			};
+
+			var fib5a = df.tailrec("<= 0", "a, b, c -> c", "[n - 1, next + result, next]");
+			var fib5  = function(n){ return fib5a(n, 1, 1); };
+			tests["fibonacci: tailrec"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib5);
+				}
+			};
+			
+			var fib6_1 = multirec1("<= 1", "1", "[[n - 1], [n - 2]]", "a[0] + a[1]");
+			tests["fibonacci: multirec1 (recursive reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib6_1);
+				}
+			};
+			
+			var fib6_2 = multirec2("<= 1", "1", "[[n - 1], [n - 2]]", "a[0] + a[1]");
+			tests["fibonacci: multirec2 (iterative reference)"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib6_2);
+				}
+			};
+			
+			var fib6 = df.multirec("<= 1", "1", "[[n - 1], [n - 2]]", "a[0] + a[1]");
+			tests["fibonacci: multirec"] = function(){
+				for(var i = 0; i < ITER; ++i){
+					df.forEach(sample2, fib6);
+				}
+			};
+			
+			var keys = df.keys(tests), i = 0;
+			
+			var doTest = function(){
+				log(keys[i], tests[keys[i]]);
+				++i;
+				if(i < keys.length){
+					setTimeout(doTest, 20);
+				}else{
+					console.log("that's all");
+				}
+			};
+			
+			var test = function(){
+				i = 0;
+				setTimeout(doTest, 20);
+			};
+				
+			dojo.addOnLoad(function(){
+				// sanity check
+
+				console.assert(fact1(5)   == 120, "fact1");
+				console.assert(fact2(5)   == 120, "fact2");
+				console.assert(fact3_1(5) == 120, "fact3_1");
+				console.assert(fact3_2(5) == 120, "fact3_2");
+				console.assert(fact3(5)   == 120, "fact3");
+				console.assert(fact4_1(5) == 120, "fact4_1");
+				console.assert(fact4_2(5) == 120, "fact4_2");
+				console.assert(fact4(5)   == 120, "fact4");
+				console.assert(fact5_1(5) == 120, "fact5_1");
+				console.assert(fact5_2(5) == 120, "fact5_2");
+				console.assert(fact5(5)   == 120, "fact5");
+				console.assert(fact6_1(5) == 120, "fact6_1");
+				console.assert(fact6_2(5) == 120, "fact6_2");
+				console.assert(fact6(5)   == 120, "fact6");
+
+				console.assert(fib1(5)   == 8, "fib1");
+				console.assert(fib2(5)   == 8, "fib2");
+				console.assert(fib3(5)   == 8, "fib3");
+				console.assert(fib4_1(5) == 8, "fib4_1");
+				console.assert(fib4_2(5) == 8, "fib4_2");
+				console.assert(fib4(5)   == 8, "fib4");
+				console.assert(fib5_1(5) == 8, "fib5_1");
+				console.assert(fib5_2(5) == 8, "fib5_2");
+				console.assert(fib5(5)   == 8, "fib5");
+				console.assert(fib6_1(5) == 8, "fib6_1");
+				console.assert(fib6_2(5) == 8, "fib6_2");
+				console.assert(fib6(5)   == 8, "fib6");
+				
+				console.log("sanity check finished");
+			});
+		</script>
+	</head>
+	<body>
+		<p>This test is meant to run with Firebug. Open the console to see the output.</p>
+		<p><button onclick="test()">Start</button></p>
+	</body>
+</html>
diff --git a/dojox/lang/tests/recomb.js b/dojox/lang/tests/recomb.js
new file mode 100644
index 0000000..241eba8
--- /dev/null
+++ b/dojox/lang/tests/recomb.js
@@ -0,0 +1,92 @@
+dojo.provide("dojox.lang.tests.recomb");
+
+dojo.require("dojox.lang.functional");
+dojo.require("dojox.lang.functional.listcomp");
+
+dojo.require("dojox.lang.functional.linrec");
+dojo.require("dojox.lang.functional.numrec");
+dojo.require("dojox.lang.functional.tailrec");
+dojo.require("dojox.lang.functional.binrec");
+dojo.require("dojox.lang.functional.multirec");
+
+(function(){
+	var df = dojox.lang.functional,
+		
+		// define the standard factorial function to compare with
+		fact = function(n){ return n <= 1 ? 1 : n * fact(n - 1); },
+
+		// define the standard fibonacci function to compare with
+		fib  = function(n){ return n <= 1 ? 1 : fib(n - 1) + fib(n - 2); },
+		
+		// prepare the sequence of arguments for comparison
+		seq = df.listcomp("i for(i = 0; i < 15; ++i)"),
+		
+		// build a set of results for our argument list using the standard factorial function
+		factTable = df.map(seq, fact),
+
+		// build a set of results for our argument list using the standard fibonacci function
+		fibTable  = df.map(seq, fib);
+	
+	tests.register("dojox.lang.tests.recomb", [
+		function testFactLinrec1(t){
+			var fact = df.linrec("<= 1", "1", "[n - 1]", "a * b[0]");
+			t.assertEqual(df.map(seq, fact), factTable);
+		},
+		function testFactLinrec2(t){
+			var fact = df.linrec(df.lambda("<= 1"), df.lambda("1"), df.lambda("[n - 1]"), df.lambda("a * b[0]"));
+			t.assertEqual(df.map(seq, fact), factTable);
+		},
+		function testFactNumrec1(t){
+			var fact = df.numrec(1, "*");
+			t.assertEqual(df.map(seq, fact), factTable);
+		},
+		function testFactNumrec2(t){
+			var fact = df.numrec(1, df.lambda("*"));
+			t.assertEqual(df.map(seq, fact), factTable);
+		},
+		function testFactMultirec1(t){
+			var fact = df.multirec("<= 1", "1", "[[n - 1]]", "a[0] * b[0]");
+			t.assertEqual(df.map(seq, fact), factTable);
+		},
+		function testFactMultirec2(t){
+			var fact = df.multirec(df.lambda("<= 1"), df.lambda("1"), df.lambda("[[n - 1]]"), df.lambda("a[0] * b[0]"));
+			t.assertEqual(df.map(seq, fact), factTable);
+		},
+		function testFactTailrec1(t){
+			var fact2 = df.tailrec("<= 1", "n, acc -> acc", "[n - 1, n * acc]"),
+				fact  = function(n){ return fact2(n, 1); };
+			t.assertEqual(df.map(seq, fact), factTable);
+		},
+		function testFactTailrec2(t){
+			var fact2 = df.tailrec(df.lambda("<= 1"), df.lambda("n, acc -> acc"), df.lambda("[n - 1, n * acc]")),
+				fact  = function(n){ return fact2(n, 1); };
+			t.assertEqual(df.map(seq, fact), factTable);
+		},
+		function testFibBinrec1(t){
+			var fib = df.binrec("<= 1", "1", "[[n - 1], [n - 2]]", "+");
+			t.assertEqual(df.map(seq, fib), fibTable);
+		},
+		function testFibBinrec2(t){
+			var fib = df.binrec(df.lambda("<= 1"), df.lambda("1"), df.lambda("[[n - 1], [n - 2]]"), df.lambda("+"));
+			t.assertEqual(df.map(seq, fib), fibTable);
+		},
+		function testFibTailrec1(t){
+			var fib2 = df.tailrec("<= 0", "n, next, result -> result", "[n - 1, next + result, next]"),
+				fib  = function(n){ return fib2(n, 1, 1); };
+			t.assertEqual(df.map(seq, fib), fibTable);
+		},
+		function testFibTailrec2(t){
+			var fib2 = df.tailrec(df.lambda("<= 0"), df.lambda("n, next, result -> result"), df.lambda("[n - 1, next + result, next]")),
+				fib  = function(n){ return fib2(n, 1, 1); };
+			t.assertEqual(df.map(seq, fib), fibTable);
+		},
+		function testFibMultirec1(t){
+			var fib = df.multirec("<= 1", "1", "[[n - 1], [n - 2]]", "a[0] + a[1]");
+			t.assertEqual(df.map(seq, fib), fibTable);
+		},
+		function testFibMultirec2(t){
+			var fib = df.multirec(df.lambda("<= 1"), df.lambda("1"), df.lambda("[[n - 1], [n - 2]]"), df.lambda("a[0] + a[1]"));
+			t.assertEqual(df.map(seq, fib), fibTable);
+		}
+	]);
+})();
diff --git a/dojox/lang/tests/runTests.html b/dojox/lang/tests/runTests.html
new file mode 100644
index 0000000..9dab1ec
--- /dev/null
+++ b/dojox/lang/tests/runTests.html
@@ -0,0 +1,9 @@
+<html>
+	<head>
+		<title>DojoX Functional Unit Test Runner</title>
+		<meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.lang.tests.main" />
+	</head>
+	<body>
+		<p>Redirecting to D.O.H runner.</p>
+	</body>
+</html>
diff --git a/dojox/lang/tests/test_aspect.html b/dojox/lang/tests/test_aspect.html
new file mode 100644
index 0000000..912fc76
--- /dev/null
+++ b/dojox/lang/tests/test_aspect.html
@@ -0,0 +1,478 @@
+<html>
+	<head>
+		<title>aspects</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+		<script type="text/javascript" src="../aspect.js"></script>
+		<script type="text/javascript" src="../aspect/cflow.js"></script>
+		<script type="text/javascript" src="../aspect/tracer.js"></script>
+		<script type="text/javascript" src="../aspect/timer.js"></script>
+		<script type="text/javascript" src="../aspect/profiler.js"></script>
+		<script type="text/javascript" src="../aspect/counter.js"></script>
+		<script type="text/javascript" src="../aspect/memoizer.js"></script>
+		<script type="text/javascript" src="../aspect/memoizerGuard.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.lang.aspect");
+			dojo.require("dojox.lang.aspect.cflow");
+			dojo.require("dojox.lang.aspect.tracer");
+			dojo.require("dojox.lang.aspect.timer");
+			dojo.require("dojox.lang.aspect.profiler");
+			dojo.require("dojox.lang.aspect.counter");
+			dojo.require("dojox.lang.aspect.memoizer");
+			dojo.require("dojox.lang.aspect.memoizerGuard");
+			dojo.require("dojo.string");
+			dojo.require("dojox.lang.functional.listcomp");
+			
+			var test = function(){
+				// This is a test class, don't program like this!
+				var Rect = function(){
+					this.x = this.y = this.width = this.height = 0;
+				};
+				dojo.extend(Rect, {
+					// getters
+					getX: function(){ return this.x; },
+					getY: function(){ return this.y; },
+					getWidth: function(){ return this.width; },
+					getHeight: function(){ return this.height; },
+					// setters
+					setX: function(val){ this.x = val; },
+					setY: function(val){ this.y = val; },
+					setWidth: function(val){ this.width = val; },
+					setHeight: function(val){ this.height = val; },
+					// special methods
+					getPerimeter: function(){ return 2 * (this.width + this.height); },
+					getArea: function(){ return this.width * this.height; },
+					getCorner: function(){ return {x: this.x + this.width, y: this.y + this.height}; },
+					move: function(x, y){ this.x = x; this.y = y; },
+					makeSquare: function(l){ this.width = this.height = l; },
+					scale: function(s){ this.width *= s; this.height *= s; },
+					pointInside: function(x, y){
+						return	this.x <= x && x < (this.x + this.width) &&
+								this.y <= y && y < (this.y + this.height);
+					},
+					assertSquare: function(){
+						if(this.getHeight() != this.getWidth()){
+							throw new Error("NOT A SQUARE!");
+						}
+					}
+				});
+				
+				var aop = dojox.lang.aspect, df = dojox.lang.functional;
+				
+				// our simple advices
+				var TraceArguments = {
+					before: function(/*arguments*/){
+						var joinPoint = aop.getContext().joinPoint,
+							args = Array.prototype.join.call(arguments, ", ");
+						console.log("=> " + joinPoint.targetName + "(" + args + ")");
+					}
+				};
+				var TraceReturns = {
+					afterReturning: function(retVal){
+						var joinPoint = aop.getContext().joinPoint;
+						console.log("<= " + joinPoint.targetName + " returns " + retVal);
+					},
+					afterThrowing: function(excp){
+						var joinPoint = aop.getContext().joinPoint;
+						console.log("<= " + joinPoint.targetName + " throws: " + excp);
+					}
+				};
+				
+				console.log("create rect1 and call its methods without aspects.");
+				var rect1 = new Rect;
+				rect1.move(100, 100);
+				rect1.makeSquare(200);
+				rect1.pointInside(150, 250);
+				console.log("perimeter: " + rect1.getPerimeter());
+				console.log("area: " + rect1.getArea());
+				console.log("=================================");
+				
+				console.log("create rect2, attach advices to the instance, and repeat...");
+				var rect2 = new Rect;
+				aop.advise(rect2, /^get/, TraceReturns);
+				aop.advise(rect2, [/^set/, "move", "makeSquare"], TraceArguments);
+				aop.advise(rect2, "pointInside", [TraceReturns, TraceArguments]);
+				rect2.move(100, 100);
+				rect2.makeSquare(200);
+				rect2.pointInside(150, 250);
+				console.log("perimeter: " + rect2.getPerimeter());
+				console.log("area: " + rect2.getArea());
+				console.log("=================================");
+
+				console.log("attach advices to the Rect class, and repeat with rect1...");
+				var h1 = aop.advise(Rect, /^get/, TraceReturns);
+				var h2 = aop.advise(Rect, [/^set/, "move", "makeSquare"], TraceArguments);
+				var h3 = aop.advise(Rect, "pointInside", [TraceReturns, TraceArguments]);
+				rect1.move(100, 100);
+				rect1.makeSquare(200);
+				rect1.pointInside(150, 250);
+				console.log("perimeter: " + rect1.getPerimeter());
+				console.log("area: " + rect1.getArea());
+				console.log("=================================");
+				
+				console.log("remove advices for getters and setters from the class, and repeat with rect1...");
+				aop.unadvise(h1);
+				aop.unadvise(h2);
+				rect1.move(100, 100);
+				rect1.makeSquare(200);
+				rect1.pointInside(150, 250);
+				console.log("perimeter: " + rect1.getPerimeter());
+				console.log("area: " + rect1.getArea());
+				console.log("=================================");
+
+				console.log("repeat with rect2...");
+				rect2.move(100, 100);
+				rect2.makeSquare(200);
+				rect2.pointInside(150, 250);
+				console.log("perimeter: " + rect2.getPerimeter());
+				console.log("area: " + rect2.getArea());
+				console.log("=================================");
+
+				console.log("test rect2 with throwing an exception...");
+				aop.advise(rect2, /^assert/, TraceReturns);
+				try{
+					rect2.assertSquare();
+					rect2.width = 300; // triggering exception
+					rect2.assertSquare();
+				}catch(e){
+					// squelch
+				}
+				console.log("=================================");
+				
+				// more complex dynamic tracing advice
+				var Trace = function(context){
+					this.name = context.joinPoint.targetName;
+				};
+				dojo.extend(Trace, {
+					before: function(/*arguments*/){
+						this.args = Array.prototype.join.call(arguments, ", ");
+					},
+					afterReturning: function(retVal){
+						var buf = "-- " + this.name + "(" + this.args + ")";
+						if(typeof retVal == "undefined"){
+							// procedure without a return value
+							console.log(buf);
+						}else{
+							// function with returned value
+							console.log(buf + " returns: " + retVal);
+						}
+					},
+					afterThrowing: function(excp){
+						console.log("-- " + this.name + "(" + this.args + ") throws: " + excp);
+					}
+				});
+				
+				// remove tracing for pointInside
+				aop.unadvise(h3);
+				
+				console.log("create rect3, and trace all its methods...");
+				var rect3 = new Rect;
+				aop.advise(rect3, /^\S/, Trace);
+				rect3.move(100, 100);
+				rect3.makeSquare(200);
+				rect3.pointInside(150, 250);
+				console.log("perimeter: " + rect3.getPerimeter());
+				console.log("area: " + rect3.getArea());
+				rect3.assertSquare();
+				console.log("=================================");
+				
+				var TraceAll = function(context, id){
+					this.name = context.joinPoint.targetName;
+					this.prefix = dojo.string.pad("", context.depth * 2, "--", true) + "-- #" + (id || 1);
+				};
+				dojo.extend(TraceAll, {
+					before: function(/*arguments*/){
+						var args = Array.prototype.join.call(arguments, ", ");
+						console.log(this.prefix + " => before " + this.name + "(" + args + ")");
+					},
+					around: function(/*arguments*/){
+						var args = Array.prototype.join.call(arguments, ", ");
+						console.log(this.prefix + " => around " + this.name + "(" + args + ")");
+						var retVal = aop.proceed.apply(null, arguments);
+						console.log(this.prefix + " <= around " + this.name + " returns " + retVal);
+						return retVal;	// should return a value, if the target returns a value
+					},
+					afterReturning: function(retVal){
+						console.log(this.prefix + " <= afterR " + this.name + " returns " + retVal);
+					},
+					afterThrowing: function(excp){
+						console.log(this.prefix + " <= afterT " + this.name + " throws: " + excp);
+					},
+					after: function(){
+						console.log(this.prefix + " <= after  " + this.name);
+					}
+				});
+				
+				console.log("create rect4, and attach two tracer to all its methods...");
+				var rect4 = new Rect;
+				aop.advise(rect4, /^\S/, [
+					function(context){ return new TraceAll(context, 1); },
+					function(context){ return new TraceAll(context, 2); }
+				]);
+				rect4.move(100, 100);
+				rect4.makeSquare(200);
+				rect4.pointInside(150, 250);
+				console.log("perimeter: " + rect4.getPerimeter());
+				console.log("area: " + rect4.getArea());
+				try{
+					rect4.assertSquare();
+					rect4.width = 300; // triggering exception
+					rect4.assertSquare();
+				}catch(e){
+					// squelch
+				}
+				console.log("=================================");
+
+				var TraceTopLevel = function(context){
+					this.name = context.joinPoint.targetName;
+				};
+				dojo.extend(TraceTopLevel, {
+					before: function(/*arguments*/){
+						var args = Array.prototype.join.call(arguments, ", ");
+						console.log("=> " + this.name + "(" + args + ")");
+					},
+					afterReturning: function(retVal){
+						console.log("<= " + this.name + " returns: " + retVal);
+					},
+					afterThrowing: function(excp){
+						console.log("<= " + this.name + " throws: " + excp);
+					}
+				});
+
+				console.log("create rect5, and track only top-level calls...");
+				var rect5 = new Rect;
+				aop.advise(rect5, /^\S/,
+					function(context){
+						return aop.cflow(context.instance) ? 	// the advised object
+							{} :								// do nothing
+							new TraceTopLevel(context);			// log top level
+					}
+				);
+				rect5.move(100, 100);
+				rect5.makeSquare(200);
+				rect5.pointInside(150, 250);
+				console.log("perimeter: " + rect5.getPerimeter());
+				console.log("area: " + rect5.getArea());
+				try{
+					rect5.assertSquare();
+					rect5.width = 300; // triggering exception
+					rect5.assertSquare();
+				}catch(e){
+					// squelch
+				}
+				console.log("=================================");
+				
+				var log = function(){
+					// log the rect1pointInside state
+					var dispatcher = "native";
+					if(rect1.pointInside.target){
+						if(rect1.pointInside.advices){
+							dispatcher = "dojox.lang.aspect";
+						}else if(rect1.pointInside._listeners){
+							dispatcher = "dojo.connect";
+						}
+					}
+					console.log("Dispatcher: " + dispatcher);
+				};
+				
+				console.log("use dojo.connect() on rect1 to trace...");
+				console.log("Running native method.");
+				log();
+				rect1.pointInside(150, 250);
+				console.log("Connecting an event processor.");
+				h1 = dojo.connect(rect1, "pointInside", function(){
+					var args = Array.prototype.join.call(arguments, ", ");
+					console.log("from dojo.connect(): " + args);
+				});
+				log();
+				rect1.pointInside(150, 250);
+				console.log("Connecting the TraceAll advice.");
+				h2 = aop.advise(rect1, "pointInside", TraceAll);
+				log();
+				rect1.pointInside(150, 250);
+				console.log("Disconnecting the event processor.");
+				dojo.disconnect(h1);
+				log();
+				rect1.pointInside(150, 250);
+				console.log("Disconnecting the advise.");
+				aop.unadvise(h2);
+				log();
+				rect1.pointInside(150, 250);
+				console.log("Connecting the TraceAll advice.");
+				h2 = aop.advise(rect1, "pointInside", TraceAll);
+				log();
+				rect1.pointInside(150, 250);
+				console.log("Connecting an event processor.");
+				h1 = dojo.connect(rect1, "pointInside", function(){
+					var args = Array.prototype.join.call(arguments, ", ");
+					console.log("from dojo.connect(): " + args);
+				});
+				log();
+				rect1.pointInside(150, 250);
+				console.log("Disconnecting the advise.");
+				aop.unadvise(h2);
+				log();
+				rect1.pointInside(150, 250);
+				console.log("Disconnecting the event processor.");
+				dojo.disconnect(h1);
+				log();
+				rect1.pointInside(150, 250);
+				console.log("=================================");
+				
+				console.log("trace all methods of rect1...");
+				h1 = aop.advise(rect1, /^\S/, aop.tracer(true));
+				rect1.move(100, 100);
+				rect1.makeSquare(200);
+				rect1.pointInside(150, 250);
+				console.log("perimeter: " + rect1.getPerimeter());
+				console.log("area: " + rect1.getArea());
+				try{
+					rect1.assertSquare();
+					rect1.width = 300; // triggering exception
+					rect1.assertSquare();
+				}catch(e){
+					// squelch
+				}
+				aop.unadvise(h1);
+				console.log("=================================");
+				
+				console.log("count all get* methods of rect1...");
+				var counter = aop.counter();
+				h1 = aop.advise(rect1, /^get/, counter);
+				rect1.move(100, 100);
+				rect1.makeSquare(200);
+				rect1.pointInside(150, 250);
+				console.log("perimeter: " + rect1.getPerimeter());
+				console.log("area: " + rect1.getArea());
+				try{
+					rect1.assertSquare();
+					rect1.width = 300; // triggering exception
+					rect1.assertSquare();
+				}catch(e){
+					// squelch
+				}
+				aop.unadvise(h1);
+				console.log("get* methods were called", counter.calls, "times, with", counter.errors, "errors.");
+				console.log("=================================");
+
+				console.log("time all methods of rect1...");
+				h1 = aop.advise(rect1, /^\S/, aop.timer());
+				rect1.move(100, 100);
+				rect1.makeSquare(200);
+				rect1.pointInside(150, 250);
+				console.log("perimeter: " + rect1.getPerimeter());
+				console.log("area: " + rect1.getArea());
+				try{
+					rect1.assertSquare();
+					rect1.width = 300; // triggering exception
+					rect1.assertSquare();
+				}catch(e){
+					// squelch
+				}
+				aop.unadvise(h1);
+				console.log("=================================");
+
+				/*
+				console.log("profile all methods of rect1...");
+				h1 = aop.advise(rect1, /^\S/, aop.profiler("Profile1"));
+				rect1.move(100, 100);
+				rect1.makeSquare(200);
+				rect1.pointInside(150, 250);
+				console.log("perimeter: " + rect1.getPerimeter());
+				console.log("area: " + rect1.getArea());
+				try{
+					rect1.assertSquare();
+					rect1.width = 300; // triggering exception
+					rect1.assertSquare();
+				}catch(e){
+					// squelch
+				}
+				aop.unadvise(h1);
+				console.log("=================================");
+				*/
+				
+				var Fibonacci = function(order){
+					if(arguments.length == 1){
+						this.setOrder(order);
+					}else{
+						this.offset = 2;
+					}
+				}
+				dojo.extend(Fibonacci, {
+					setOrder: function(order){
+						this.offset = order + 1;
+					},
+					getOrder: function(){
+						return this.offset - 1;
+					},
+					calculate: function(n){
+						if(n < 0){ return 0; }
+						if(n == 0){ return 1; }
+						return this.calculate(n - 1) + this.calculate(n - this.offset);
+					},
+					calculateN: function(n, o){
+						if(n < 0){ return 0; }
+						if(n == 0){ return 1; }
+						return this.calculateN(n - 1, o) + this.calculateN(n - 1 - o, o);
+					}
+				});
+				var args = df.listcomp("i for(i = 0; i < 15; ++i)");
+
+				console.log("calculate Fibonacci numbers...");
+				var fib = new Fibonacci;
+				h1 = aop.advise(fib, /^calculate/, aop.timer("fib"));
+				
+				console.log("before memoization");
+				fib.setOrder(0);
+				console.log("0-order:", dojo.map(args, dojo.hitch(fib, "calculate")));
+				fib.setOrder(1);
+				console.log("1-order:", dojo.map(args, dojo.hitch(fib, "calculate")));
+				fib.setOrder(2);
+				console.log("2-order:", dojo.map(args, dojo.hitch(fib, "calculate")));
+				fib.setOrder(3);
+				console.log("3-order:", dojo.map(args, dojo.hitch(fib, "calculate")));
+				
+				console.log("after memoization");
+				h2 = aop.advise(fib, "calculate", aop.memoizer());
+				h3 = aop.advise(fib, /^set/, aop.memoizerGuard("calculate"));
+				fib.setOrder(0);
+				console.log("0-order:", dojo.map(args, dojo.hitch(fib, "calculate")));
+				fib.setOrder(1);
+				console.log("1-order:", dojo.map(args, dojo.hitch(fib, "calculate")));
+				fib.setOrder(2);
+				console.log("2-order:", dojo.map(args, dojo.hitch(fib, "calculate")));
+				fib.setOrder(3);
+				console.log("3-order:", dojo.map(args, dojo.hitch(fib, "calculate")));
+				aop.unadvise(h3);
+				aop.unadvise(h2);
+				
+				console.log("before memoization");
+				console.log(fib.calculateN(15, 0));
+				console.log(fib.calculateN(15, 1));
+				console.log(fib.calculateN(15, 2));
+				console.log(fib.calculateN(15, 3));
+				
+				console.log("after memoization");
+				h2 = aop.advise(fib, "calculateN", aop.memoizer(function(a, b){ return a + "/" + b; }));
+				h3 = aop.advise(fib, /^set/, aop.memoizerGuard("calculate"));
+				console.log(fib.calculateN(15, 0));
+				console.log(fib.calculateN(15, 1));
+				console.log(fib.calculateN(15, 2));
+				console.log(fib.calculateN(15, 3));
+				aop.unadvise(h3);
+				aop.unadvise(h2);
+
+				aop.unadvise(h1);
+				
+				console.log("=================================");
+			};
+			//dojo.addOnLoad(test);
+		</script>
+	</head>
+	<body>
+		<p>This test is meant to run with Firebug. Open the console to see the output.</p>
+		<p><button onclick="test()">Start</button></p>
+	</body>
+</html>
diff --git a/dojox/lang/tests/test_oo_decl.html b/dojox/lang/tests/test_oo_decl.html
new file mode 100644
index 0000000..0dbdc25
--- /dev/null
+++ b/dojox/lang/tests/test_oo_decl.html
@@ -0,0 +1,492 @@
+<html>
+	<head>
+		<title>OO/decl</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+		<!--<script type="text/javascript" src="../oo/declare.js"></script>-->
+		<script type="text/javascript">
+			//dojo.require("dojox.lang.oo.declare");
+			dojo.require("dojox.lang.tests.declare-old");
+
+			var decl = dojo.declare, t, chains = true,
+				oldDecl = dojox.lang.tests.declareOld;
+
+			var test1 = function(){
+				var A = decl("A", null, {
+					constructor: function(){
+						console.log("A.constructor:", arguments);
+					},
+					m1: function(){
+						console.log("A.m1:", arguments);
+					}
+				});
+				var a = new A(1);
+				a.m1(2);
+				var B = decl("B", A, {
+					constructor: function(){
+						console.log("B.constructor:", arguments);
+					},
+					m2: function(){
+						console.log("B.m2:", arguments);
+					}
+				});
+				var b = new B(1);
+				b.m1(2);
+				b.m2(3);
+				var C = decl("C", B, {
+					constructor: function(){
+						console.log("C.constructor:", arguments);
+					},
+					m2: function(){
+						this.inherited(arguments);
+						console.log("C.m2:", arguments);
+						this.inherited(arguments);
+					}
+				});
+				var c = new C(1);
+				c.m1(2);
+				c.m2(3);
+				if(chains){
+					var D = decl("D", C, {
+						constructor: function(){
+							console.log("D.constructor:", arguments);
+						},
+						"-chains-": {m1: "after"},
+						m1: function(){
+							console.log("D.m1:", arguments);
+						},
+						m2: function(){
+							console.log("D.m2:", arguments);
+							this.inherited(arguments);
+						},
+						m3: function(){
+							console.log("D.m3:", arguments);
+							this.m2.apply(this, arguments);
+						}
+					});
+					var d = new D(1);
+					d.m1(2);
+					d.m2(3);
+					d.m3(4);
+					var E = decl("E", C, {
+						constructor: function(){
+							console.log("E.constructor:", arguments);
+						},
+						"-chains-": {m1: "before"},
+						m1: function(){
+							console.log("E.m1:", arguments);
+						},
+						m2: function(){
+							console.log("E.m2:", arguments);
+							this.inherited(arguments);
+						},
+						m3: function(){
+							console.log("E.m3:", arguments);
+							B.prototype.m2.apply(this, arguments);
+							this.m2.apply(this, arguments);
+						}
+					});
+					var e = new E(1);
+					e.m1(2);
+					e.m2(3);
+					e.m3(4);
+				}
+				var F = function(){
+					console.log("F.constructor:", arguments);
+				};
+				dojo.extend(F, {
+					m1: function(){
+						console.log("F.m1:", arguments);
+					},
+					m2: function(){
+						console.log("F.m2:", arguments);
+					},
+					m3: function(){
+						console.log("F.m3:", arguments);
+					}
+				});
+				var G = decl("G", null, {
+					constructor: function(){
+						console.log("G.constructor:", arguments);
+					},
+					m1: function(){
+						console.log("G.m1:", arguments);
+						this.inherited(arguments);
+					},
+					m2: function(){
+						console.log("G.m2:", arguments);
+					},
+					m3: function(){
+						console.log("G.m3:", arguments);
+					}
+				});
+				var H = decl("H", null, {
+					constructor: function(){
+						console.log("H.constructor:", arguments);
+					},
+					m1: function(){
+						console.log("H.m1:", arguments);
+					},
+					m2: function(){
+						console.log("H.m2:", arguments);
+					},
+					m3: function(){
+						console.log("H.m3:", arguments);
+					}
+				});
+				if(chains){
+					var I = decl("I", [H, F, G], {
+						constructor: function(){
+							console.log("I.constructor:", arguments);
+						},
+						"-chains-": {m3: "before", m2: "after"},
+						m1: function(){
+							console.log("I.m1:", arguments);
+							this.inherited(arguments);
+						},
+						m2: function(){
+							console.log("I.m2:", arguments);
+						},
+						m3: function(){
+							console.log("I.m3:", arguments);
+						}
+					});
+					var i = new I(1);
+					i.m1(2);
+					i.m2(3);
+					i.m3(4);
+				}
+				var J = decl("J", C, {
+					m2: function(){
+						console.log("J.m2:", arguments);
+						this.inherited(arguments);
+					}
+				});
+				var j = new J(1);
+				j.m1(2);
+				j.m2(3);
+				console.log("the classic diamond test");
+				if(chains){
+					var DA = decl(null, {
+						constructor: function(){
+							console.log("DA.constructor");
+						},
+						m1: function(){
+							this.inherited(arguments);
+							console.log("DA.m1");
+						},
+						m2: function(){
+							console.log("DA.m2");
+							this.inherited(arguments);
+						},
+						toLocaleString: function(){
+							return this.inherited(arguments) + " -DA";
+						}
+					});
+					var DB = decl(DA, {
+						constructor: function(){
+							console.log("DB.constructor");
+						},
+						m1: function(){
+							this.inherited(arguments);
+							console.log("DB.m1");
+						},
+						m2: function(){
+							console.log("DB.m2");
+							this.inherited(arguments);
+						},
+						toLocaleString: function(){
+							return this.inherited(arguments) + " -DB";
+						}
+					});
+					var DC = decl(DA, {
+						constructor: function(){
+							console.log("DC.constructor");
+						},
+						m1: function(){
+							this.inherited(arguments);
+							console.log("DC.m1");
+						},
+						m2: function(){
+							console.log("DC.m2");
+							this.inherited(arguments);
+						},
+						toLocaleString: function(){
+							return this.inherited(arguments) + " -DC";
+						}
+					});
+					var DD = decl([DB, DC], {
+						constructor: function(){
+							console.log("DD.constructor");
+						},
+						m1: function(){
+							this.inherited(arguments);
+							console.log("DD.m1");
+						},
+						m2: function(){
+							console.log("DD.m2");
+							this.inherited(arguments);
+						},
+						toLocaleString: function(){
+							return this.inherited(arguments) + " -DD";
+						}
+					});
+					var dd = new DD;
+					dd.m1();
+					dd.m2();
+					console.log(dd.toLocaleString());
+				}
+				console.log("chained constructor (but no preamble)");
+				if(chains){
+					var A = decl(null, {
+							constructor: function(){
+								console.log("A.constructor");
+							},
+							"-chains-": {constructor: "after", destroy: "before"},
+							destroy: function(){
+								console.log("A.destroy");
+							}
+						}),
+						B = decl(A, {
+							constructor: function(){
+								console.log("B.constructor");
+							},
+							destroy: function(){
+								console.log("B.destroy");
+							}
+						}),
+						C = decl(B, {
+							constructor: function(){
+								console.log("C.constructor");
+							},
+							destroy: function(){
+								console.log("C.destroy");
+							}
+						});
+					new A().destroy();
+					new B().destroy();
+					new C().destroy();
+				}
+				console.log("constructor is not chained");
+				if(chains){
+					var A = decl(null, {
+							constructor: function(){
+								console.log("A.constructor");
+							},
+							"-chains-": {constructor: "manual"}
+						}),
+						B = decl(A, {
+							constructor: function(){
+								console.log("B.constructor");
+								this.inherited(arguments);
+							}
+						}),
+						C = decl(B, {
+							constructor: function(){
+								console.log("C.constructor");
+								this.inherited(arguments);
+							}
+						});
+					new A();
+					new B();
+					new C();
+				}
+				console.log("preamble() test #1");
+				var A = decl(null, {
+						constructor: function(){
+							console.log("A.constructor: ", arguments);
+						}
+					}),
+					B = decl(A, {
+						constructor: function(){
+							console.log("B.constructor: ", arguments);
+						},
+						preamble: function(a, b){
+							return [2 * a, 2 * b];
+						}
+					}),
+					C = decl(B, {
+						constructor: function(){
+							console.log("C.constructor: ", arguments);
+						},
+						preamble: function(a, b){
+							var dict = {a: 1, b: 2};
+							return [dict[a], dict[b]];
+						}
+					});
+				new C("a", "b");
+				console.log("preamble() test #2");
+				var A = decl(null, {
+						constructor: function(){
+							console.log("A.constructor: ", arguments);
+						}
+					}),
+					B = decl(A, {
+						constructor: function(){
+							console.log("B.constructor: ", arguments);
+						}
+					}),
+					C = decl(B, {
+						constructor: function(){
+							console.log("C.constructor: ", arguments);
+						}
+					}),
+					P = decl(null, {
+						preamble: function(x, a, b){
+							return [x, 2 * a, 2 * b];
+						}
+					});
+				new C(new P, 1, 2);
+			};
+
+			var superclassRef = function(){
+				decl("tests._base.declare.tmp10", null, {
+					foo: "thonk"
+				});
+				decl("tests._base.declare.tmp11", tests._base.declare.tmp10, {
+					constructor: function(){
+						this.foo = "blah";
+					}
+				});
+				var tmp = new tests._base.declare.tmp11();
+				console.log("blah", tmp.foo);
+				console.log("thonk", tests._base.declare.tmp11.superclass.foo);
+			}
+
+			var inheritedExplicitCall = function(){
+				var foo = "xyzzy";
+				decl("tests._base.declare.tmp14", null, {
+					foo: "thonk",
+					bar: function(arg1, arg2){
+						if(arg1){
+							this.foo = arg1;
+						}
+						if(arg2){
+							foo = arg2;
+						}
+					}
+				});
+				decl("tests._base.declare.tmp15", tests._base.declare.tmp14, {
+					constructor: function(){
+						this.foo = "blah";
+					},
+					bar: function(arg1, arg2){
+						this.inherited("bar", arguments, [arg2, arg1]);
+					},
+					baz: function(arg1, arg2){
+						tests._base.declare.tmp15.superclass.bar.apply(this, arguments);
+					}
+				});
+				var tmp = new tests._base.declare.tmp15();
+				console.log("blah", tmp.foo);
+				console.log("xyzzy", foo);
+				tmp.baz("zot");
+				console.log("zot", tmp.foo);
+				console.log("xyzzy", foo);
+				tmp.bar("trousers", "squiggle");
+				console.log("squiggle", tmp.foo);
+				console.log("trousers", foo);
+			}
+
+			var feature9795 = function(){
+				//var decl = dojo.declare;
+				decl("ClassA", [], {});
+				decl("ClassB", [ClassA],
+				{
+					preamble: function()
+					{
+						console.log("ClassB preamble invoked on " + this.declaredClass);
+						return [new ClassC()];
+					}
+				});
+				decl("ClassC", null,
+				{
+					preamble: function()
+					{
+						console.log("ClassC preamble invoked on " + this.declaredClass);
+					}
+				});
+				new ClassB;
+			};
+
+			var duplicatedBases = function(){
+				console.log("duplicated bases");
+				var A = decl(null, {
+					constructor: function(){
+						console.log("A.constructor");
+					}
+				});
+				var B = decl([A, A, A], {
+					constructor: function(){
+						console.log("B.constructor");
+					}
+				});
+				new B;
+			};
+
+			var preambleTest = function(){
+				console.log("preamble tests");
+				var newA = decl(null, {
+						constructor: function(arg){
+							console.log("newA: expects 1 - " + arg);
+						}
+					}),
+					newB = decl(newA, {
+						constructor: function(arg){
+							console.log("newB expects A - " + arg);
+						},
+						preamble: function(arg){
+							console.log("newB/preamble expects A - " + arg);
+							return [1];
+						}
+					}),
+					newX = decl(null, {
+						constructor: function(arg){
+							console.log("newX expects object - " + (typeof arg));
+							this.obj = arg;
+						}
+					}),
+					newBi = new newB("A"), newXi = new newX(newBi);
+				oldDecl("oldA", null, {
+					constructor: function(arg){
+						console.log("oldA: expects 1 - " + arg);
+					}
+				});
+				oldDecl("oldB", oldA, {
+					constructor: function(arg){
+						console.log("oldB expects A - " + arg);
+					},
+					preamble: function(arg){
+						console.log("oldB/preamble expects A - " + arg);
+						return [1];
+					}
+				});
+				oldDecl("oldX", null, {
+					constructor: function(arg){
+						console.log("oldX expects object - " + (typeof arg));
+						this.obj = arg;
+					}
+				});
+				var oldBi = new oldB("A"), oldXi = new oldX(oldBi);
+			};
+
+			var test = function(){
+				test1();
+				console.log("testing for individual bugs");
+				superclassRef();
+				inheritedExplicitCall();
+				feature9795();
+				duplicatedBases();
+				preambleTest();
+			};
+
+			//dojo.addOnLoad(test1);
+		</script>
+	</head>
+	<body>
+		<p>This test is meant to run with Firebug. Open the console to see the output.</p>
+		<p><button onclick="test()">Start</button></p>
+	</body>
+</html>
diff --git a/dojox/lang/tests/test_oo_mixin.html b/dojox/lang/tests/test_oo_mixin.html
new file mode 100644
index 0000000..38a95bf
--- /dev/null
+++ b/dojox/lang/tests/test_oo_mixin.html
@@ -0,0 +1,162 @@
+<html>
+	<head>
+		<title>OO/mixin</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+		<script type="text/javascript">
+			dojo.require("dojox.lang.oo.mixin");
+			dojo.require("dojox.lang.oo.general");
+			dojo.require("dojox.lang.oo.aop");
+
+			var oo = dojox.lang.oo, oog = oo.general, ooa = oo.aop;
+
+			var test = function(){
+				// test chaining of constructor() and destroy()
+
+				var a = {
+					init: function(){ console.log("init #1"); },
+					abc: function(){ console.log("abc #1: args = ", arguments); return 1; },
+					destroy: function(){ console.log("destroy #1"); }
+				},
+				b = {
+					init: function(){ console.log("init #2"); },
+					abc: function(){ console.log("abc #2: args = ", arguments); return 2; },
+					destroy: function(){ console.log("destroy #2"); }
+				},
+				c = {
+					init: function(){ console.log("init #3"); },
+					abc: function(){ console.log("abc #3: args = ", arguments); return 3; },
+					destroy: function(){ console.log("destroy #3"); }
+				};
+
+				console.log("=== test default mixin: a");
+				var t = oo.mixin({}, a);
+				t.init();
+				t.abc(42);
+				t.destroy();
+
+				console.log("=== test default mixin: a + b");
+				var t = oo.mixin({}, a, b);
+				t.init();
+				t.abc(42);
+				t.destroy();
+
+				console.log("=== test default mixin: a + b + c");
+				var t = oo.mixin({}, a, b, c);
+				t.init();
+				t.abc(42);
+				t.destroy();
+
+				console.log("=== test default mixin: a + (b - 'abc')");
+				var t = oo.mixin({}, a, oo.filter(b, {abc: ""}));
+				t.init();
+				t.abc(42);
+				t.destroy();
+
+				console.log("=== test default mixin: a + (b - 'destroy' * 'abc'/'def')");
+				var t = oo.mixin({}, a, oo.filter(b, {abc: "def", destroy: ""}));
+				t.init();
+				t.abc(42);
+				console.log("the next line shoud print 'abc #2'");
+				t.def(42);
+				t.destroy();
+
+				console.log("=== test default mixin: a + 'abc2'/after + 'abc3'/before");
+				var t = oo.mixin({}, a,
+							oo.filter(oog.after(b),  {init: "", destroy: ""}),
+							oo.filter(oog.before(c), {init: "", destroy: ""})
+						);
+				t.init();
+				t.abc(42);
+				t.destroy();
+
+				console.log("=== test augment and override (negative case)");
+				var t = oo.mixin({}, a, {
+					abc: oog.augment(function(){ console.log("augmented"); }),	// can't override
+					def: oog.override(function(){ console.log("overidden"); })	// nothing to override
+				});
+				t.init();
+				t.abc(42);
+				console.log("should be 'undefined': ", t.def);
+				t.destroy();
+
+				console.log("=== test augment and override (positive case)");
+				var t = oo.mixin({}, a, {
+					def: oog.augment(function(){ console.log("augmented"); }),	// can't override
+					abc: oog.override(function(){ console.log("overidden"); })	// nothing to override
+				});
+				t.init();
+				t.abc(42);
+				t.def(42);
+				t.destroy();
+
+				console.log("=== test augment and general.after (no chaining for existing functions)");
+				var t = oo.mixin({}, a, {
+					abc: oog.augment(oog.after(
+							function(){ console.log("overidden"); }
+					))
+				});
+				t.init();
+				t.abc(42);
+				t.destroy();
+
+				console.log("=== test override and general.after (chaining only for existing functions)");
+				var t = oo.mixin({}, a, {
+					abc: oog.override(oog.after(
+							function(){ console.log("overidden? not really"); }
+					))
+				});
+				t.init();
+				t.abc(42);
+				t.destroy();
+
+				console.log("=== test decorated objects");
+				var t = oo.mixin({}, a, oog.after({
+					abc: function(){ console.log("added after abc"); },
+					def: function(){ console.log("added after def"); }
+				}));
+				t.init();
+				t.abc(42);
+				t.def(42);
+				t.destroy();
+
+				console.log("=== test aop-like decorators");
+				var t = oo.mixin({}, a,
+					{
+						abc: ooa.around(function(f, args){
+							console.log("aop.around: args = ", args);
+							var ret = f.apply(this, args);
+							console.log("aop.around: ret = ", ret);
+							return ret;
+						})
+					},
+					{
+						abc: ooa.before(function(){
+							console.log("aop.before: args = ", arguments);
+						})
+					},
+					{
+						abc: ooa.afterReturning(function(ret){
+							console.log("aop.afterReturning: ret = ", ret);
+						})
+					},
+					{
+						abc: ooa.after(function(){
+							console.log("aop.after");
+						})
+					}
+				);
+				t.init();
+				t.abc(42);
+				t.destroy();
+			};
+			//dojo.addOnLoad(test);
+		</script>
+	</head>
+	<body>
+		<p>This test is meant to run with Firebug. Open the console to see the output.</p>
+		<p><button onclick="test()">Start</button></p>
+	</body>
+</html>
diff --git a/dojox/lang/tests/typed.js b/dojox/lang/tests/typed.js
new file mode 100644
index 0000000..4db1aa0
--- /dev/null
+++ b/dojox/lang/tests/typed.js
@@ -0,0 +1,144 @@
+dojo.provide("dojox.lang.tests.typed");
+dojo.config.typeCheckAllClasses = true;
+dojo.require("dojox.lang.typed");
+(function(){
+	
+	dojox.lang.typed(
+		dojo.declare("dojox.lang.tests.TypedClass", null, {
+			constructor: function(makeDefaults){
+				if(makeDefaults){
+					this.aString = "start";
+					this.self = this;
+				}
+			},
+			add: function(a, b){
+				return a + b;
+			},
+			withCallback: function(callback, param){
+				callback(param);
+			}
+	}));
+	var TypedClass = dojox.lang.tests.TypedClass;
+	TypedClass.properties = {
+		aString:String, 
+		self: TypedClass, 
+		anInt: {type:"integer", maximum: 100, optional: true}
+	};
+	TypedClass.methods = {
+		add: {
+			parameters:[
+				{type:"number"},
+				{type:"number"}
+			],
+			returns: {type:"string"}
+		},
+		withCallback:{
+			parameters:[
+				{type:"function", parameters:[Number]}
+			]
+		}
+	}
+	var hasGetters = {}.__defineGetter__;
+	if(!hasGetters){
+		console.warn("This platform does not support getters, property type checking will not be tested");
+	}
+	function mustThrow(testFunc){
+		try{
+			testFunc();
+		}catch(e){
+			return;
+		}
+		throw new Error("No exception was thrown where an exception was required");
+	}
+	tests.register("dojox.lang.tests.typed", [
+		function typedConstructor(){
+			mustThrow(function(){
+				typedInstance = new TypedClass();
+			});
+		},
+		function typedProperties(t){
+			typedInstance = new TypedClass(true);
+			t.is(typedInstance.aString, "start");
+			typedInstance.aString = "hi";
+			if(hasGetters){
+				mustThrow(function(){
+					typedInstance.aString = 44;
+				});
+			}
+			typedInstance.anInt = 22;
+			if(hasGetters){
+				mustThrow(function(){
+					typedInstance.anInt = "hello";
+				});
+			}
+			if(hasGetters){
+				mustThrow(function(){
+					typedInstance.anInt = 44.33;
+				});
+			}
+			if(hasGetters){
+				mustThrow(function(){
+					typedInstance.anInt = 144;
+				});
+			}
+			typedInstance.self = typedInstance;
+			if(hasGetters){
+				mustThrow(function(){
+					typedInstance.self = {};
+				});
+			}
+		},
+		function typedMethods(){
+			typedInstance = new TypedClass(true);
+			mustThrow(function(){
+				typedInstance.add("hi",33);
+			});
+			mustThrow(function(){
+				typedInstance.add(22,33);
+			});
+			mustThrow(function(){
+				typedInstance.withCallback(22,33);
+			});
+			mustThrow(function(){
+				typedInstance.withCallback(function(){},"hi");
+			});
+			TypedClass.methods.add.returns.type = "number";
+			typedInstance.add(22,33);
+			typedInstance.withCallback(function(){},44);
+			
+		},
+		function typedDeclares(){
+			dojo.declare("dojox.lang.tests.AutoTypedClass", null, {
+				constructor: function(){
+					this.foo = "bar";
+				},
+				subtract: function(a, b){
+					return a - b;
+				}
+			});
+			var AutoTypedClass = dojox.lang.tests.AutoTypedClass;
+			AutoTypedClass.properties = {
+				foo:{type:"string"} 
+			};
+			AutoTypedClass.methods = {
+				subtract: {
+					parameters:[
+						{type:"number"},
+						{type:"number"}
+					]
+				}
+			};
+			typedInstance = new AutoTypedClass(true);
+			if(hasGetters){
+				mustThrow(function(){
+					typedInstance.foo = 33;
+				});
+			}
+			typedInstance.foo = "baz";
+			mustThrow(function(){
+				typedInstance.subtract("hi",33);
+			});
+			typedInstance.subtract(22,33);
+		}
+	]);
+})();
diff --git a/dojox/lang/typed.js b/dojox/lang/typed.js
index 7c95480..bb15851 100644
--- a/dojox/lang/typed.js
+++ b/dojox/lang/typed.js
@@ -1,146 +1,148 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.typed"]){
-dojo._hasResource["dojox.lang.typed"]=true;
 (function(){
-var _1,_2=typeof dojo!="undefined";
-if(_2){
-dojo.provide("dojox.lang.typed");
-dojo.require("dojox.json.schema");
-_1=dojox.json.schema;
-}else{
-if(typeof JSONSchema=="undefined"){
-throw new Error("Dojo or JSON Schema library must be present");
-}
-_1=JSONSchema;
-}
-function _3(_4,_5){
-var _6=function(){
-var _7=_5();
-if(_7&&_7.parameters){
-var _8=_7.parameters;
-for(var j=0;j<_8.length;j++){
-arguments[j]=_9(arguments[j],_8[j],j.toString());
-}
-if(_7.additionalParameters){
-for(;j<arguments.length;j++){
-arguments[j]=_9(arguments[j],_7.additionalParameters,j.toString());
-}
-}
-}
-var _a=_4.apply(this,arguments);
-if(_7.returns){
-_9(_a,_7.returns);
-}
-return _a;
-};
-_6.__typedFunction__=true;
-for(var i in _4){
-_6[i]=_4[i];
-}
-return _6;
-};
-function _b(_c){
-return function(){
-return _c;
-};
-};
-function _9(_d,_e,_f){
-if(typeof _d=="function"&&_e&&!_d.__typedFunction__){
-_d=_3(_d,_b(_e));
-}
-var _10=_1._validate(_d,_e,_f);
-if(!_10.valid){
-var _11="";
-var _12=_10.errors;
-for(var i=0;i<_12.length;i++){
-_11+=_12[i].property+" "+_12[i].message+"\n";
-}
-throw new TypeError(_11);
-}
-return _d;
-};
-var _13=_1.__defineGetter__;
-var _14=function(_15){
-if(_15.__typedClass__){
-return _15;
-}
-var _16=function(){
-var i,_17,_18=_16.properties;
-var _19=_16.methods;
-_15.apply(this,arguments);
-this.__props__={};
-for(i in _19){
-_17=this[i];
-if(_17){
-if(!_17.__typedFunction__){
-var _1a=this;
-while(!_1a.hasOwnProperty(i)&&_1a.__proto__){
-_1a=_1a.__proto__;
-}
-(function(i){
-_1a[i]=_3(_17,function(){
-return _19[i];
-});
-})(i);
-}
-}else{
-(function(i){
-this[i]=function(){
-throw new TypeError("The method "+i+" is defined but not implemented");
-};
-})(i);
-}
-}
-if(_13){
-var _1b=this;
-for(i in _18){
-_17=this[i];
-if(this.hasOwnProperty(i)){
-this.__props__[i]=_17;
-}
-(function(i){
-delete _1b[i];
-_1b.__defineGetter__(i,function(){
-return i in this.__props__?this.__props__[i]:this.__proto__[i];
-});
-_1b.__defineSetter__(i,function(_1c){
-_9(_1c,_18[i],i);
-return this.__props__[i]=_1c;
-});
-})(i);
-}
-}
-_9(this,_16);
-};
-_16.prototype=_15.prototype;
-for(var i in _15){
-_16[i]=_15[i];
-}
-if(_15.prototype.declaredClass&&_2){
-dojo.setObject(_15.prototype.declaredClass,_16);
-}
-_16.__typedClass__=true;
-return _16;
-};
-if(_2){
-dojox.lang.typed=_14;
-if(dojo.config.typeCheckAllClasses){
-var _1d=dojo.declare;
-dojo.declare=function(_1e){
-var _1f=_1d.apply(this,arguments);
-_1f=_14(_1f);
-return _1f;
-};
-dojo.mixin(dojo.declare,_1d);
-}
-}else{
-typed=_14;
-}
+	var jsonSchema, inDojo = typeof dojo != "undefined";
+	if(inDojo){
+		dojo.provide("dojox.lang.typed");
+		dojo.require("dojox.json.schema");
+		jsonSchema = dojox.json.schema;
+	}else{
+		if(typeof JSONSchema == "undefined"){
+			throw new Error("Dojo or JSON Schema library must be present");
+		}
+		jsonSchema = JSONSchema;
+	}
+	function validatingFunction(func, getMethodDef){
+		var validatingFunc = function(){
+			var methodDef = getMethodDef();
+			if(methodDef && methodDef.parameters){
+				var params = methodDef.parameters;
+				for(var j = 0; j < params.length; j++){
+					arguments[j] = validate(arguments[j], params[j], j.toString());
+				}
+				if(methodDef.additionalParameters){
+					for(;j < arguments.length; j++){
+						arguments[j] = validate(arguments[j], methodDef.additionalParameters, j.toString());
+					}
+				}
+			}
+			var returns = func.apply(this, arguments);
+			if(methodDef.returns){
+				validate(returns, methodDef.returns);
+			}
+			return returns;
+		};
+		validatingFunc.__typedFunction__ = true;
+		for(var i in func){
+			validatingFunc[i] = func[i];
+		}
+		return validatingFunc;
+	}
+	function identityFunc(obj){
+		return function(){
+			return obj;
+		}
+	}
+	function validate(instance, schema, property){
+		//	summary:
+		//		This checks to ensure that the result is valid and will throw an appropriate error message if it is not
+		// result: the result returned from checkPropertyChange or validate
+		if(typeof instance == "function" && schema && !instance.__typedFunction__){
+			instance = validatingFunction(instance, identityFunc(schema));
+		}
+		var result = jsonSchema._validate(instance, schema, property);
+		if(!result.valid){
+			var errorMessage = ""
+			var errors = result.errors;
+			for(var i = 0; i < errors.length; i++){
+				errorMessage += errors[i].property + ' ' + errors[i].message + '\n';
+			}
+			throw new TypeError(errorMessage);
+		}
+		return instance;
+	}
+	var hasGetters = jsonSchema.__defineGetter__;
+	var typedFunction = function(Class){
+		// summary:
+		//		Adds type checking to a class, returning a new class with typing enabled
+		if(Class.__typedClass__){
+			// type checking has already been added
+			return Class;
+		}
+		var Wrapper = function(){
+			var i, value, properties = Wrapper.properties;
+			var methods = Wrapper.methods;
+			Class.apply(this,arguments);
+			this.__props__ = {};
+			for(i in methods){
+				value = this[i];
+				if(value){
+					if(!value.__typedFunction__){
+						// add typing checking to the method, going up the proto chain to find the right one
+						var proto = this;
+						while(!proto.hasOwnProperty(i) && proto.__proto__){
+							proto = proto.__proto__;
+						}
+						(function(i){
+							proto[i] = validatingFunction(value, function(){
+								return methods[i];
+							});
+						})(i);
+					}
+				}else{
+					(function(i){
+						this[i] = function(){
+							throw new TypeError("The method " + i + " is defined but not implemented");
+						};
+					})(i);
+				}
+			}
+			if(hasGetters){
+				var self = this;
+				for(i in properties){
+					// add type checking to each property
+					value = this[i];
+					if(this.hasOwnProperty(i)){
+						this.__props__[i] = value;
+					}
+					(function(i){
+						delete self[i];
+						self.__defineGetter__(i, function(){
+							return i in this.__props__ ? this.__props__[i] : this.__proto__[i];
+						});
+						self.__defineSetter__(i, function(value){
+							validate(value, properties[i], i);
+							return this.__props__[i] = value;
+						});
+					})(i);
+				}
+			}
+			validate(this, Wrapper);
+		};
+		Wrapper.prototype = Class.prototype;
+		for(var i in Class){
+			Wrapper[i] = Class[i];
+		}
+		if(Class.prototype.declaredClass && inDojo){
+			dojo.setObject(Class.prototype.declaredClass, Wrapper);
+		}
+		Wrapper.__typedClass__ = true;
+		return Wrapper;
+	};
+	if(inDojo){
+		dojox.lang.typed = typedFunction;
+		if(dojo.config.typeCheckAllClasses){
+			//	This will add type checking to all classes that will be declared via dojo.declare
+			//	(only ones to be declared in the future)
+
+			// hook into all declared classes
+			var defaultDeclare = dojo.declare;
+			dojo.declare = function(name){
+				var clazz = defaultDeclare.apply(this, arguments);
+				clazz = typedFunction(clazz);
+				return clazz;
+			};
+			dojo.mixin(dojo.declare, defaultDeclare);
+		}
+	}else{
+		typed = typedFunction;
+	}
 })();
-}
diff --git a/dojox/lang/utils.js b/dojox/lang/utils.js
index 3d76c3e..a28b743 100644
--- a/dojox/lang/utils.js
+++ b/dojox/lang/utils.js
@@ -1,59 +1,103 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.lang.utils"]){
-dojo._hasResource["dojox.lang.utils"]=true;
 dojo.provide("dojox.lang.utils");
+
 (function(){
-var _1={},du=dojox.lang.utils;
-var _2=function(o){
-if(dojo.isArray(o)){
-return dojo._toArray(o);
-}
-if(!dojo.isObject(o)||dojo.isFunction(o)){
-return o;
-}
-return dojo.delegate(o);
-};
-dojo.mixin(du,{coerceType:function(_3,_4){
-switch(typeof _3){
-case "number":
-return Number(eval("("+_4+")"));
-case "string":
-return String(_4);
-case "boolean":
-return Boolean(eval("("+_4+")"));
-}
-return eval("("+_4+")");
-},updateWithObject:function(_5,_6,_7){
-if(!_6){
-return _5;
-}
-for(var x in _5){
-if(x in _6&&!(x in _1)){
-var t=_5[x];
-if(t&&typeof t=="object"){
-du.updateWithObject(t,_6[x],_7);
-}else{
-_5[x]=_7?du.coerceType(t,_6[x]):_2(_6[x]);
-}
-}
-}
-return _5;
-},updateWithPattern:function(_8,_9,_a,_b){
-if(!_9||!_a){
-return _8;
-}
-for(var x in _a){
-if(x in _9&&!(x in _1)){
-_8[x]=_b?du.coerceType(_a[x],_9[x]):_2(_9[x]);
-}
-}
-return _8;
-}});
+	var empty = {}, du = dojox.lang.utils, opts = Object.prototype.toString;
+
+	var clone = function(o){
+		if(o){
+			switch(opts.call(o)){
+				case "[object Array]":
+					return o.slice(0);
+				case "[object Object]":
+					return dojo.delegate(o);
+			}
+		}
+		return o;
+	}
+	
+	dojo.mixin(du, {
+		coerceType: function(target, source){
+			// summary: Coerces one object to the type of another.
+			// target: Object: object, which typeof result is used to coerce "source" object.
+			// source: Object: object, which will be forced to change type.
+			switch(typeof target){
+				case "number":	return Number(eval("(" + source + ")"));
+				case "string":	return String(source);
+				case "boolean":	return Boolean(eval("(" + source + ")"));
+			}
+			return eval("(" + source + ")");
+		},
+		
+		updateWithObject: function(target, source, conv){
+			// summary: Updates an existing object in place with properties from an "source" object.
+			// target: Object: the "target" object to be updated
+			// source: Object: the "source" object, whose properties will be used to source the existed object.
+			// conv: Boolean?: force conversion to the original type
+			if(!source){ return target; }
+			for(var x in target){
+				if(x in source && !(x in empty)){
+					var t = target[x];
+					if(t && typeof t == "object"){
+						du.updateWithObject(t, source[x], conv);
+					}else{
+						target[x] = conv ? du.coerceType(t, source[x]) : clone(source[x]);
+					}
+				}
+			}
+			return target;	// Object
+		},
+	
+		updateWithPattern: function(target, source, pattern, conv){
+			// summary: Updates an existing object in place with properties from an "source" object.
+			// target: Object: the "target" object to be updated
+			// source: Object: the "source" object, whose properties will be used to source the existed object.
+			// pattern: Array: an array of properties to be copied
+			// conv: Boolean?: force conversion to the original type
+			if(!source || !pattern){ return target; }
+			for(var x in pattern){
+				if(x in source && !(x in empty)){
+					target[x] = conv ? du.coerceType(pattern[x], source[x]) : clone(source[x]);
+				}
+			}
+			return target;	// Object
+		},
+		
+		merge: function(object, mixin){
+			// summary: Merge two objects structurally, mixin properties will override object's properties.
+			// object: Object: original object.
+			// mixin: Object: additional object, which properties will override object's properties.
+			if(mixin){
+				var otype = opts.call(object), mtype = opts.call(mixin), t, i, l, m;
+				switch(mtype){
+					case "[object Array]":
+						if(mtype == otype){
+							t = new Array(Math.max(object.length, mixin.length));
+							for(i = 0, l = t.length; i < l; ++i){
+								t[i] = du.merge(object[i], mixin[i]);
+							}
+							return t;
+						}
+						return mixin.slice(0);
+					case "[object Object]":
+						if(mtype == otype && object){
+							t = dojo.delegate(object);
+							for(i in mixin){
+								if(i in object){
+									l = object[i];
+									m = mixin[i];
+									if(m !== l){
+										t[i] = du.merge(l, m);
+									}
+								}else{
+									t[i] = dojo.clone(mixin[i]);
+								}
+							}
+							return t;
+						}
+						return dojo.clone(mixin);
+				}
+			}
+			return mixin;
+		}
+	});
 })();
-}
diff --git a/dojox/layout/BorderContainer.js b/dojox/layout/BorderContainer.js
index d6b67c4..9f1a6a3 100644
--- a/dojox/layout/BorderContainer.js
+++ b/dojox/layout/BorderContainer.js
@@ -1,12 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.BorderContainer"]){
-dojo._hasResource["dojox.layout.BorderContainer"]=true;
 dojo.provide("dojox.layout.BorderContainer");
-console.error("dojox.layout.BorderContainer moved to dijit.layout.BorderContainer");
-}
+
+console.error("dojox.layout.BorderContainer moved to dijit.layout.BorderContainer");
\ No newline at end of file
diff --git a/dojox/layout/ContentPane.js b/dojox/layout/ContentPane.js
old mode 100644
new mode 100755
index 59a4d3c..6fd1fcd
--- a/dojox/layout/ContentPane.js
+++ b/dojox/layout/ContentPane.js
@@ -1,33 +1,104 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.ContentPane"]){
-dojo._hasResource["dojox.layout.ContentPane"]=true;
 dojo.provide("dojox.layout.ContentPane");
+
 dojo.require("dijit.layout.ContentPane");
-dojo.require("dojox.html._base");
-dojo.declare("dojox.layout.ContentPane",dijit.layout.ContentPane,{adjustPaths:false,cleanContent:false,renderStyles:false,executeScripts:true,scriptHasHooks:false,constructor:function(){
-this.ioArgs={};
-this.ioMethod=dojo.xhrGet;
-},onExecError:function(e){
-},_setContent:function(_1){
-var _2=this._contentSetter;
-if(!(_2&&_2 instanceof dojox.html._ContentSetter)){
-_2=this._contentSetter=new dojox.html._ContentSetter({node:this.containerNode,_onError:dojo.hitch(this,this._onError),onContentError:dojo.hitch(this,function(e){
-var _3=this.onContentError(e);
-try{
-this.containerNode.innerHTML=_3;
-}
-catch(e){
-console.error("Fatal "+this.id+" could not change content due to "+e.message,e);
-}
-})});
-}
-this._contentSetterParams={adjustPaths:Boolean(this.adjustPaths&&(this.href||this.referencePath)),referencePath:this.href||this.referencePath,renderStyles:this.renderStyles,executeScripts:this.executeScripts,scriptHasHooks:this.scriptHasHooks,scriptHookReplacement:"dijit.byId('"+this.id+"')"};
-this.inherited("_setContent",arguments);
-}});
-}
+dojo.require("dojox.html._base"); 
+
+dojo.declare("dojox.layout.ContentPane", dijit.layout.ContentPane, {
+	// summary:
+	//		An extended version of dijit.layout.ContentPane.
+	//		Supports infile scripts and external ones declared by <script src=''
+	//		relative path adjustments (content fetched from a different folder)
+	//		<style> and <link rel='stylesheet' href='..'> tags,
+	//		css paths inside cssText is adjusted (if you set adjustPaths = true)
+	//
+	//		NOTE that dojo.require in script in the fetched file isn't recommended
+	//		Many widgets need to be required at page load to work properly
+
+	// adjustPaths: Boolean
+	//		Adjust relative paths in html string content to point to this page.
+	//		Only useful if you grab content from a another folder then the current one
+	adjustPaths: false,
+
+	// cleanContent: Boolean
+	//	summary:
+	//		cleans content to make it less likely to generate DOM/JS errors.
+	//	description:
+	//		useful if you send ContentPane a complete page, instead of a html fragment
+	//		scans for 
+	//
+	//			* title Node, remove
+	//			* DOCTYPE tag, remove
+	cleanContent: false,
+
+	// renderStyles: Boolean
+	//		trigger/load styles in the content
+	renderStyles: false,
+
+	// executeScripts: Boolean
+	//		Execute (eval) scripts that is found in the content
+	executeScripts: true,
+
+	// scriptHasHooks: Boolean
+	//		replace keyword '_container_' in scripts with 'dijit.byId(this.id)'
+	// NOTE this name might change in the near future
+	scriptHasHooks: false,
+
+	/*======
+	// ioMethod: dojo.xhrGet|dojo.xhrPost
+	//		reference to the method that should grab the content
+	ioMethod: dojo.xhrGet,
+	
+	// ioArgs: Object
+	//		makes it possible to add custom args to xhrGet, like ioArgs.headers['X-myHeader'] = 'true'
+	ioArgs: {},
+	======*/
+
+	constructor: function(){
+		// init per instance properties, initializer doesn't work here because how things is hooked up in dijit._Widget
+		this.ioArgs = {};
+		this.ioMethod = dojo.xhrGet;
+	},
+
+	onExecError: function(e){
+		// summary:
+		//		event callback, called on script error or on java handler error
+		//		overide and return your own html string if you want a some text 
+		//		displayed within the ContentPane
+	},
+
+	_setContent: function(cont){
+		// override dijit.layout.ContentPane._setContent, to enable path adjustments
+		
+		var setter = this._contentSetter; 
+		if(! (setter && setter instanceof dojox.html._ContentSetter)) {
+			setter = this._contentSetter = new dojox.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 */
+			});
+		};
+
+		// stash the params for the contentSetter to allow inheritance to work for _setContent
+		this._contentSetterParams = {
+			adjustPaths: Boolean(this.adjustPaths && (this.href||this.referencePath)),
+			referencePath: this.href || this.referencePath,
+			renderStyles: this.renderStyles,
+			executeScripts: this.executeScripts,
+			scriptHasHooks: this.scriptHasHooks,
+			scriptHookReplacement: "dijit.byId('"+this.id+"')"
+		};
+
+		this.inherited("_setContent", arguments);
+	}
+	// could put back _renderStyles by wrapping/aliasing dojox.html._ContentSetter.prototype._renderStyles
+});
diff --git a/dojox/layout/DragPane.js b/dojox/layout/DragPane.js
index d210bd5..ed4bc20 100644
--- a/dojox/layout/DragPane.js
+++ b/dojox/layout/DragPane.js
@@ -1,36 +1,61 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.DragPane"]){
-dojo._hasResource["dojox.layout.DragPane"]=true;
 dojo.provide("dojox.layout.DragPane");
+
 dojo.require("dijit._Widget");
-dojo.declare("dojox.layout.DragPane",dijit._Widget,{invert:true,postCreate:function(){
-this.inherited(arguments);
-this.connect(this.domNode,"onmousedown","_down");
-this.connect(this.domNode,"onmouseup","_up");
-},_down:function(e){
-var t=this.domNode;
-dojo.style(t,"cursor","move");
-this._x=e.pageX;
-this._y=e.pageY;
-if((this._x<t.offsetLeft+t.clientWidth)&&(this._y<t.offsetTop+t.clientHeight)){
-dojo.setSelectable(t,false);
-this._mover=this.connect(t,"onmousemove","_move");
-}
-},_up:function(e){
-dojo.setSelectable(this.domNode,true);
-dojo.style(this.domNode,"cursor","pointer");
-this.disconnect(this._mover);
-},_move:function(e){
-var _1=this.invert?1:-1;
-this.domNode.scrollTop+=(this._y-e.pageY)*_1;
-this.domNode.scrollLeft+=(this._x-e.pageX)*_1;
-this._x=e.pageX;
-this._y=e.pageY;
-}});
-}
+
+dojo.declare("dojox.layout.DragPane",
+	dijit._Widget, {
+	//
+	// summary: Makes a pane's content dragable by/within it's surface
+	//
+	// description:
+	//		A small widget which takes a node with overflow:auto and
+	//		allows dragging to position the content. Useful with images,
+	//		or for just adding "something" to a overflow-able div.
+	//
+	// invert: Boolean
+	//		Naturally, the behavior is to invert the axis of the drag.
+	//		Setting invert:false will make the pane drag in the same
+	//		direction as the mouse.
+	invert:true,
+	
+	postCreate: function(){
+
+		this.inherited(arguments);
+		this.connect(this.domNode,"onmousedown","_down");
+		this.connect(this.domNode,"onmouseup","_up");
+	},
+	
+	_down: function(e){
+		// summary: mousedown handler, start the dragging
+		var t = this.domNode;
+		dojo.style(t,"cursor","move");
+		this._x = e.pageX;
+		this._y = e.pageY;
+		if ((this._x < t.offsetLeft + t.clientWidth) &&
+			(this._y < t.offsetTop + t.clientHeight)) {
+			dojo.setSelectable(t,false);
+			this._mover = this.connect(t,"onmousemove","_move");
+		}
+	},
+	
+	_up: function(e){
+		// summary: mouseup handler, stop the dragging
+		
+		dojo.setSelectable(this.domNode,true);
+		dojo.style(this.domNode,"cursor","pointer");
+		this.disconnect(this._mover);
+	},
+	
+	_move: function(e){
+		// summary: mousemove listener, offset the scroll amount by the delta
+		//		since our last call.
+		
+		var mod = this.invert ? 1 : -1;
+		this.domNode.scrollTop += (this._y - e.pageY) * mod;
+		this.domNode.scrollLeft += (this._x - e.pageX) * mod;
+		this._x = e.pageX;
+		this._y = e.pageY;
+		
+	}
+	
+});
diff --git a/dojox/layout/ExpandoPane.js b/dojox/layout/ExpandoPane.js
index fca923e..dfa8029 100644
--- a/dojox/layout/ExpandoPane.js
+++ b/dojox/layout/ExpandoPane.js
@@ -1,126 +1,281 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.ExpandoPane"]){
-dojo._hasResource["dojox.layout.ExpandoPane"]=true;
 dojo.provide("dojox.layout.ExpandoPane");
-dojo.experimental("dojox.layout.ExpandoPane");
+dojo.experimental("dojox.layout.ExpandoPane"); // just to show it can be done?
+
 dojo.require("dijit.layout.ContentPane");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Contained");
-dojo.declare("dojox.layout.ExpandoPane",[dijit.layout.ContentPane,dijit._Templated,dijit._Contained],{maxHeight:"",maxWidth:"",splitter:false,templateString:dojo.cache("dojox.layout","resources/ExpandoPane.html","<div class=\"dojoxExpandoPane\" dojoAttachEvent=\"ondblclick:toggle\" >\n\t<div dojoAttachPoint=\"titleWrapper\" class=\"dojoxExpandoTitle\">\n\t\t<div class=\"dojoxExpandoIcon\" dojoAttachPoint=\"iconNode\" dojoAttachEvent=\"onclick:toggle\"><span class=\"a11yNode\">X</span></d [...]
-this.inherited(arguments);
-this._animConnects=[];
-this._isHorizontal=true;
-if(dojo.isString(this.easeOut)){
-this.easeOut=dojo.getObject(this.easeOut);
-}
-if(dojo.isString(this.easeIn)){
-this.easeIn=dojo.getObject(this.easeIn);
-}
-var _1="",_2=!this.isLeftToRight();
-if(this.region){
-switch(this.region){
-case "trailing":
-case "right":
-_1=_2?"Left":"Right";
-break;
-case "leading":
-case "left":
-_1=_2?"Right":"Left";
-break;
-case "top":
-_1="Top";
-break;
-case "bottom":
-_1="Bottom";
-break;
-}
-dojo.addClass(this.domNode,"dojoxExpando"+_1);
-dojo.addClass(this.iconNode,"dojoxExpandoIcon"+_1);
-this._isHorizontal=/top|bottom/.test(this.region);
-}
-dojo.style(this.domNode,{overflow:"hidden",padding:0});
-},_startupSizes:function(){
-this._container=this.getParent();
-this._closedSize=this._titleHeight=dojo.marginBox(this.titleWrapper).h;
-if(this.splitter){
-var _3=this.id;
-dijit.registry.filter(function(w){
-return w&&w.child&&w.child.id==_3;
-}).forEach(dojo.hitch(this,function(w){
-this.connect(w,"_stopDrag","_afterResize");
-}));
-}
-this._currentSize=dojo.contentBox(this.domNode);
-this._showSize=this._currentSize[(this._isHorizontal?"h":"w")];
-this._setupAnims();
-if(this.startExpanded){
-this._showing=true;
-}else{
-this._showing=false;
-this._hideWrapper();
-this._hideAnim.gotoPercent(99,true);
-}
-this._hasSizes=true;
-},_afterResize:function(e){
-var _4=this._currentSize;
-this._currentSize=dojo.marginBox(this.domNode);
-var n=this._currentSize[(this._isHorizontal?"h":"w")];
-if(n>this._titleHeight){
-if(!this._showing){
-this._showing=!this._showing;
-this._showEnd();
-}
-this._showSize=n;
-this._setupAnims();
-}else{
-this._showSize=_4[(this._isHorizontal?"h":"w")];
-this._showing=false;
-this._hideWrapper();
-this._hideAnim.gotoPercent(89,true);
-}
-},_setupAnims:function(){
-dojo.forEach(this._animConnects,dojo.disconnect);
-var _5={node:this.domNode,duration:this.duration},_6=this._isHorizontal,_7={},_8={},_9=_6?"height":"width";
-_7[_9]={end:this._showSize};
-_8[_9]={end:this._closedSize};
-this._showAnim=dojo.animateProperty(dojo.mixin(_5,{easing:this.easeIn,properties:_7}));
-this._hideAnim=dojo.animateProperty(dojo.mixin(_5,{easing:this.easeOut,properties:_8}));
-this._animConnects=[dojo.connect(this._showAnim,"onEnd",this,"_showEnd"),dojo.connect(this._hideAnim,"onEnd",this,"_hideEnd")];
-},toggle:function(){
-if(this._showing){
-this._hideWrapper();
-this._showAnim&&this._showAnim.stop();
-this._hideAnim.play();
-}else{
-this._hideAnim&&this._hideAnim.stop();
-this._showAnim.play();
-}
-this._showing=!this._showing;
-},_hideWrapper:function(){
-dojo.addClass(this.domNode,"dojoxExpandoClosed");
-dojo.style(this.cwrapper,{visibility:"hidden",opacity:"0",overflow:"hidden"});
-},_showEnd:function(){
-dojo.style(this.cwrapper,{opacity:0,visibility:"visible"});
-dojo.fadeIn({node:this.cwrapper,duration:227}).play(1);
-dojo.removeClass(this.domNode,"dojoxExpandoClosed");
-setTimeout(dojo.hitch(this._container,"layout"),15);
-},_hideEnd:function(){
-setTimeout(dojo.hitch(this._container,"layout"),15);
-},resize:function(_a){
-if(!this._hasSizes){
-this._startupSizes(_a);
-}
-var _b=(_a&&_a.h)?_a:dojo.marginBox(this.domNode);
-this._contentBox={w:_b.w||dojo.marginBox(this.domNode).w,h:_b.h-this._titleHeight};
-dojo.style(this.containerNode,"height",this._contentBox.h+"px");
-this._layoutChildren();
-},_trap:function(e){
-dojo.stopEvent(e);
-}});
-}
+
+dojo.declare("dojox.layout.ExpandoPane",
+	[dijit.layout.ContentPane, dijit._Templated, dijit._Contained, dijit._Container],
+	{
+	// summary: An experimental collapsing-pane for dijit.layout.BorderContainer
+	//
+	// description:
+	//		Works just like a ContentPane inside of a borderContainer. Will expand/collapse on
+	//		command, and supports having Layout Children as direct descendants
+	//	
+
+	//maxHeight: "",
+	//maxWidth: "",
+	//splitter: false,
+	
+	templateString: dojo.cache("dojox.layout","resources/ExpandoPane.html"),
+
+	// easeOut: String|Function
+	//		easing function used to hide pane
+	easeOut: "dojo._DefaultEasing",
+	
+	// easeIn: String|Function
+	//		easing function use to show pane
+	easeIn: "dojo._DefaultEasing",
+	
+	// duration: Integer
+	//		duration to run show/hide animations
+	duration: 420,
+
+	// startExpanded: Boolean
+	//		Does this widget start in an open (true) or closed (false) state
+	startExpanded: true, 
+
+	// previewOpacity: Float
+	//		A value from 0 .. 1 indicating the opacity to use on the container
+	//		when only showing a preview
+	previewOpacity: 0.75,
+	
+	// previewOnDblClick: Boolean
+	//		If true, will override the default behavior of a double-click calling a full toggle.
+	//		If false, a double-click will cause the preview to popup
+	previewOnDblClick: false,
+
+	baseClass: "dijitExpandoPane",
+
+	postCreate: function(){
+		this.inherited(arguments);
+		this._animConnects = [];
+
+		this._isHorizontal = true;
+		
+		if(dojo.isString(this.easeOut)){
+			this.easeOut = dojo.getObject(this.easeOut);
+		}
+		if(dojo.isString(this.easeIn)){
+			this.easeIn = dojo.getObject(this.easeIn); 
+		}
+	
+		var thisClass = "", rtl = !this.isLeftToRight();
+		if(this.region){
+			switch(this.region){
+				case "trailing" : 
+				case "right" :
+					thisClass = rtl ? "Left" : "Right";
+					break;
+				case "leading" : 
+				case "left" :
+					thisClass = rtl ? "Right" : "Left";
+					break;
+				case "top" :
+					thisClass = "Top";
+					break;
+				case "bottom" :
+					thisClass = "Bottom"; 
+					break;
+			}
+			dojo.addClass(this.domNode, "dojoxExpando" + thisClass);
+			dojo.addClass(this.iconNode, "dojoxExpandoIcon" + thisClass);
+			this._isHorizontal = /top|bottom/.test(this.region);
+		}
+		dojo.style(this.domNode, {
+			overflow: "hidden",
+			padding:0
+		});
+		
+		this.connect(this.domNode, "ondblclick", this.previewOnDblClick ? "preview" : "toggle");
+		
+		if(this.previewOnDblClick){
+			this.connect(this.getParent(), "_layoutChildren", dojo.hitch(this, function(){
+				this._isonlypreview = false;
+			}));
+		}
+		
+	},
+	
+	_startupSizes: function(){
+		
+		this._container = this.getParent();
+		this._closedSize = this._titleHeight = dojo.marginBox(this.titleWrapper).h;
+		
+		if(this.splitter){
+			// find our splitter and tie into it's drag logic
+			var myid = this.id;
+			dijit.registry.filter(function(w){
+				return w && w.child && w.child.id == myid;
+			}).forEach(dojo.hitch(this,function(w){
+				this.connect(w,"_stopDrag","_afterResize");
+			}));
+		}
+		
+		this._currentSize = dojo.contentBox(this.domNode);	// TODO: can compute this from passed in value to resize(), see _LayoutWidget for example
+		this._showSize = this._currentSize[(this._isHorizontal ? "h" : "w")];
+		this._setupAnims();
+
+		if(this.startExpanded){
+			this._showing = true;
+		}else{
+			this._showing = false;
+			this._hideWrapper();
+			this._hideAnim.gotoPercent(99,true);
+		}
+		
+		this._hasSizes = true;
+	},
+	
+	_afterResize: function(e){
+		var tmp = this._currentSize;						// the old size
+		this._currentSize = dojo.marginBox(this.domNode);	// the new size
+		var n = this._currentSize[(this._isHorizontal ? "h" : "w")] 
+		if(n > this._titleHeight){
+			if(!this._showing){	
+				this._showing = !this._showing; 
+				this._showEnd();
+			}
+			this._showSize = n;
+			this._setupAnims();
+		}else{
+			this._showSize = tmp[(this._isHorizontal ? "h" : "w")];
+			this._showing = false;
+			this._hideWrapper();
+			this._hideAnim.gotoPercent(89,true);
+		}
+		
+	},
+	
+	_setupAnims: function(){
+		// summary: Create the show and hide animations
+		dojo.forEach(this._animConnects, dojo.disconnect);
+		
+		var _common = {
+				node:this.domNode,
+				duration:this.duration
+			},
+			isHorizontal = this._isHorizontal,
+			showProps = {},
+			hideProps = {},
+			dimension = isHorizontal ? "height" : "width"
+		;
+
+		showProps[dimension] = { 
+			end: this._showSize
+		};
+		hideProps[dimension] = { 
+			end: this._closedSize
+		};
+		
+		this._showAnim = dojo.animateProperty(dojo.mixin(_common,{
+			easing:this.easeIn,
+			properties: showProps 
+		}));
+		this._hideAnim = dojo.animateProperty(dojo.mixin(_common,{
+			easing:this.easeOut,
+			properties: hideProps
+		}));
+
+		this._animConnects = [
+			dojo.connect(this._showAnim, "onEnd", this, "_showEnd"),
+			dojo.connect(this._hideAnim, "onEnd", this, "_hideEnd")
+		];
+	},
+	
+	preview: function(){
+		// summary: Expand this pane in preview mode (does not affect surrounding layout)
+
+		if(!this._showing){
+			this._isonlypreview = !this._isonlypreview;
+		}
+		this.toggle();
+	},
+
+	toggle: function(){
+		// summary: Toggle this pane's visibility
+		if(this._showing){
+			this._hideWrapper();
+			this._showAnim && this._showAnim.stop();
+			this._hideAnim.play();
+		}else{
+			this._hideAnim && this._hideAnim.stop();
+			this._showAnim.play();
+		}
+		this._showing = !this._showing;
+	},
+	
+	_hideWrapper: function(){
+		// summary: Set the Expando state to "closed"
+		dojo.addClass(this.domNode, "dojoxExpandoClosed");
+		
+		dojo.style(this.cwrapper,{
+			visibility: "hidden",
+			opacity: "0",
+			overflow: "hidden"
+		});
+	},
+	
+	_showEnd: function(){
+		// summary: Common animation onEnd code - "unclose"
+		dojo.style(this.cwrapper, { 
+			opacity: 0,
+			visibility:"visible" 
+		});
+		dojo.anim(this.cwrapper, {
+			opacity: this._isonlypreview ? this.previewOpacity : 1
+		}, 227);
+		dojo.removeClass(this.domNode, "dojoxExpandoClosed");
+		if(!this._isonlypreview){
+			setTimeout(dojo.hitch(this._container, "layout"), 15);
+		}else{
+			this._previewShowing = true;
+			this.resize();
+		}
+	},
+	
+	_hideEnd: function(){
+		// summary: Callback for the hide animation - "close"
+
+		// every time we hide, reset the "only preview" state
+		if(!this._isonlypreview){
+			setTimeout(dojo.hitch(this._container, "layout"), 25);
+		}else{
+			this._previewShowing = false;
+		}
+		this._isonlypreview = false;
+		
+	},
+	
+	resize: function(/* Object? */newSize, /*Object?*/ currentSize){
+		// summary:
+		//		we aren't a layout widget, but need to act like one:
+		// newSize: Object
+		//		The size object to resize to
+		// currentSize: Object
+		//		The size of my domNode that has already been set (by BorderContainer)
+
+		if(!this._hasSizes){ this._startupSizes(newSize); }
+		
+		// compute size of container (ie, size left over after title bar)
+		this._contentBox = {
+			w: newSize && "w" in newSize ? newSize.w : currentSize.w,
+			h: (newSize && "h" in newSize ? newSize.h : currentSize.h) - this._titleHeight
+		};	
+		dojo.style(this.containerNode, "height", this._contentBox.h + "px");
+
+		if(newSize){
+			dojo.marginBox(this.domNode, newSize);
+		}
+
+		this._layoutChildren();
+	},
+	
+	_trap: function(e){
+		// summary: Trap stray events
+		dojo.stopEvent(e);
+	}
+
+});
diff --git a/dojox/layout/FloatingPane.js b/dojox/layout/FloatingPane.js
index 501631d..c2f87de 100644
--- a/dojox/layout/FloatingPane.js
+++ b/dojox/layout/FloatingPane.js
@@ -1,221 +1,403 @@
-/*
-	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
-*/
+dojo.provide("dojox.layout.FloatingPane");
+dojo.experimental("dojox.layout.FloatingPane"); 
 
+dojo.require("dojo.window");
 
-if(!dojo._hasResource["dojox.layout.FloatingPane"]){
-dojo._hasResource["dojox.layout.FloatingPane"]=true;
-dojo.provide("dojox.layout.FloatingPane");
-dojo.experimental("dojox.layout.FloatingPane");
-dojo.require("dojox.layout.ContentPane");
-dojo.require("dijit._Templated");
-dojo.require("dijit._Widget");
+dojo.require("dijit._Templated"); 
+dojo.require("dijit._Widget"); 
 dojo.require("dojo.dnd.Moveable");
-dojo.require("dojox.layout.ResizeHandle");
-dojo.declare("dojox.layout.FloatingPane",[dojox.layout.ContentPane,dijit._Templated],{closable:true,dockable:true,resizable:false,maxable:false,resizeAxis:"xy",title:"",dockTo:"",duration:400,contentClass:"dojoxFloatingPaneContent",_showAnim:null,_hideAnim:null,_dockNode:null,_restoreState:{},_allFPs:[],_startZ:100,templateString:dojo.cache("dojox.layout","resources/FloatingPane.html","<div class=\"dojoxFloatingPane\" id=\"${id}\">\n\t<div tabindex=\"0\" waiRole=\"button\" class=\"dojoxF [...]
-this.inherited(arguments);
-new dojo.dnd.Moveable(this.domNode,{handle:this.focusNode});
-if(!this.dockable){
-this.dockNode.style.display="none";
-}
-if(!this.closable){
-this.closeNode.style.display="none";
-}
-if(!this.maxable){
-this.maxNode.style.display="none";
-this.restoreNode.style.display="none";
-}
-if(!this.resizable){
-this.resizeHandle.style.display="none";
-}else{
-this.domNode.style.width=dojo.marginBox(this.domNode).w+"px";
-}
-this._allFPs.push(this);
-this.domNode.style.position="absolute";
-this.bgIframe=new dijit.BackgroundIframe(this.domNode);
-this._naturalState=dojo.coords(this.domNode);
-},startup:function(){
-if(this._started){
-return;
-}
-this.inherited(arguments);
-if(this.resizable){
-if(dojo.isIE){
-this.canvas.style.overflow="auto";
-}else{
-this.containerNode.style.overflow="auto";
-}
-this._resizeHandle=new dojox.layout.ResizeHandle({targetId:this.id,resizeAxis:this.resizeAxis},this.resizeHandle);
-}
-if(this.dockable){
-var _1=this.dockTo;
-if(this.dockTo){
-this.dockTo=dijit.byId(this.dockTo);
-}else{
-this.dockTo=dijit.byId("dojoxGlobalFloatingDock");
-}
-if(!this.dockTo){
-var _2,_3;
-if(_1){
-_2=_1;
-_3=dojo.byId(_1);
-}else{
-_3=dojo.create("div",null,dojo.body());
-dojo.addClass(_3,"dojoxFloatingDockDefault");
-_2="dojoxGlobalFloatingDock";
-}
-this.dockTo=new dojox.layout.Dock({id:_2,autoPosition:"south"},_3);
-this.dockTo.startup();
-}
-if((this.domNode.style.display=="none")||(this.domNode.style.visibility=="hidden")){
-this.minimize();
-}
-}
-this.connect(this.focusNode,"onmousedown","bringToTop");
-this.connect(this.domNode,"onmousedown","bringToTop");
-this.resize(dojo.coords(this.domNode));
-this._started=true;
-},setTitle:function(_4){
-dojo.deprecated("pane.setTitle","Use pane.attr('title', someTitle)","2.0");
-this.attr("title",_4);
-},close:function(){
-if(!this.closable){
-return;
-}
-dojo.unsubscribe(this._listener);
-this.hide(dojo.hitch(this,function(){
-this.destroyRecursive();
-}));
-},hide:function(_5){
-dojo.fadeOut({node:this.domNode,duration:this.duration,onEnd:dojo.hitch(this,function(){
-this.domNode.style.display="none";
-this.domNode.style.visibility="hidden";
-if(this.dockTo&&this.dockable){
-this.dockTo._positionDock(null);
-}
-if(_5){
-_5();
-}
-})}).play();
-},show:function(_6){
-var _7=dojo.fadeIn({node:this.domNode,duration:this.duration,beforeBegin:dojo.hitch(this,function(){
-this.domNode.style.display="";
-this.domNode.style.visibility="visible";
-if(this.dockTo&&this.dockable){
-this.dockTo._positionDock(null);
-}
-if(typeof _6=="function"){
-_6();
-}
-this._isDocked=false;
-if(this._dockNode){
-this._dockNode.destroy();
-this._dockNode=null;
-}
-})}).play();
-this.resize(dojo.coords(this.domNode));
-},minimize:function(){
-if(!this._isDocked){
-this.hide(dojo.hitch(this,"_dock"));
-}
-},maximize:function(){
-if(this._maximized){
-return;
-}
-this._naturalState=dojo.position(this.domNode);
-if(this._isDocked){
-this.show();
-setTimeout(dojo.hitch(this,"maximize"),this.duration);
-}
-dojo.addClass(this.focusNode,"floatingPaneMaximized");
-this.resize(dijit.getViewport());
-this._maximized=true;
-},_restore:function(){
-if(this._maximized){
-this.resize(this._naturalState);
-dojo.removeClass(this.focusNode,"floatingPaneMaximized");
-this._maximized=false;
-}
-},_dock:function(){
-if(!this._isDocked&&this.dockable){
-this._dockNode=this.dockTo.addNode(this);
-this._isDocked=true;
-}
-},resize:function(_8){
-_8=_8||this._naturalState;
-this._currentState=_8;
-var _9=this.domNode.style;
-if("t" in _8){
-_9.top=_8.t+"px";
-}
-if("l" in _8){
-_9.left=_8.l+"px";
-}
-_9.width=_8.w+"px";
-_9.height=_8.h+"px";
-var _a={l:0,t:0,w:_8.w,h:(_8.h-this.focusNode.offsetHeight)};
-dojo.marginBox(this.canvas,_a);
-this._checkIfSingleChild();
-if(this._singleChild&&this._singleChild.resize){
-this._singleChild.resize(_a);
-}
-},bringToTop:function(){
-var _b=dojo.filter(this._allFPs,function(i){
-return i!==this;
-},this);
-_b.sort(function(a,b){
-return a.domNode.style.zIndex-b.domNode.style.zIndex;
+
+dojo.require("dojox.layout.ContentPane");
+dojo.require("dojox.layout.ResizeHandle"); 
+
+dojo.declare("dojox.layout.FloatingPane", 
+	[ dojox.layout.ContentPane, dijit._Templated ],
+	{
+	// summary:
+	//		A non-modal Floating window.
+	//
+	// description:
+	// 		Makes a `dojox.layout.ContentPane` float and draggable by it's title [similar to TitlePane]
+	// 		and over-rides onClick to onDblClick for wipeIn/Out of containerNode
+	// 		provides minimize(dock) / show() and hide() methods, and resize [almost] 
+	//
+	// closable: Boolean
+	//		Allow closure of this Node
+	closable: true,
+
+	// dockable: Boolean
+	//		Allow minimizing of pane if true
+	dockable: true,
+
+	// resizable: Boolean
+	//		Allow resizing of pane true if true
+	resizable: false,
+
+	// maxable: Boolean
+	//		Horrible param name for "Can you maximize this floating pane?"
+	maxable: false,
+
+	// resizeAxis: String
+	//		One of: x | xy | y to limit pane's sizing direction
+	resizeAxis: "xy",
+
+	// title: String
+	//		Title to use in the header
+	title: "",
+
+	// dockTo: DomNode?
+	//		if empty, will create private layout.Dock that scrolls with viewport
+	//		on bottom span of viewport.	
+	dockTo: "",
+
+	// duration: Integer
+	//		Time is MS to spend toggling in/out node
+	duration: 400,
+
+	/*=====
+	// iconSrc: String
+	//		[not implemented yet] will be either icon in titlepane to left
+	//		of Title, and/or icon show when docked in a fisheye-like dock
+	//		or maybe dockIcon would be better?
+	iconSrc: null,
+	=====*/
+
+	// contentClass: String
+	// 		The className to give to the inner node which has the content
+	contentClass: "dojoxFloatingPaneContent",
+
+	// animation holders for toggle
+	_showAnim: null,
+	_hideAnim: null, 
+	// node in the dock (if docked)
+	_dockNode: null,
+
+	// privates:
+	_restoreState: {},
+	_allFPs: [],
+	_startZ: 100,
+
+	templateString: dojo.cache("dojox.layout","resources/FloatingPane.html"),
+	
+	attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
+		title: { type:"innerHTML", node:"titleNode" }
+	}),
+	
+	postCreate: function(){
+		this.inherited(arguments);
+		new dojo.dnd.Moveable(this.domNode,{ handle: this.focusNode });
+		//this._listener = dojo.subscribe("/dnd/move/start",this,"bringToTop"); 
+
+		if(!this.dockable){ this.dockNode.style.display = "none"; } 
+		if(!this.closable){ this.closeNode.style.display = "none"; } 
+		if(!this.maxable){
+			this.maxNode.style.display = "none";
+			this.restoreNode.style.display = "none";
+		}
+		if(!this.resizable){
+			this.resizeHandle.style.display = "none"; 	
+		}else{
+			this.domNode.style.width = dojo.marginBox(this.domNode).w + "px"; 
+		}
+		this._allFPs.push(this);
+		this.domNode.style.position = "absolute";
+		
+		this.bgIframe = new dijit.BackgroundIframe(this.domNode);
+		this._naturalState = dojo.coords(this.domNode);
+	},
+	
+	startup: function(){
+		if(this._started){ return; }
+		
+		this.inherited(arguments);
+
+		if(this.resizable){
+			if(dojo.isIE){
+				this.canvas.style.overflow = "auto";
+			}else{
+				this.containerNode.style.overflow = "auto";
+			}
+			
+			this._resizeHandle = new dojox.layout.ResizeHandle({ 
+				targetId: this.id, 
+				resizeAxis: this.resizeAxis 
+			},this.resizeHandle);
+
+		}
+
+		if(this.dockable){ 
+			// FIXME: argh.
+			var tmpName = this.dockTo; 
+
+			if(this.dockTo){
+				this.dockTo = dijit.byId(this.dockTo); 
+			}else{
+				this.dockTo = dijit.byId('dojoxGlobalFloatingDock');
+			}
+
+			if(!this.dockTo){
+				var tmpId, tmpNode;
+				// we need to make our dock node, and position it against
+				// .dojoxDockDefault .. this is a lot. either dockto="node"
+				// and fail if node doesn't exist or make the global one
+				// once, and use it on empty OR invalid dockTo="" node?
+				if(tmpName){ 
+					tmpId = tmpName;
+					tmpNode = dojo.byId(tmpName); 
+				}else{
+					tmpNode = dojo.create('div', null, dojo.body());
+					dojo.addClass(tmpNode,"dojoxFloatingDockDefault");
+					tmpId = 'dojoxGlobalFloatingDock';
+				}
+				this.dockTo = new dojox.layout.Dock({ id: tmpId, autoPosition: "south" }, tmpNode);
+				this.dockTo.startup(); 
+			}
+			
+			if((this.domNode.style.display == "none")||(this.domNode.style.visibility == "hidden")){
+				// If the FP is created dockable and non-visible, start up docked.
+				this.minimize();
+			} 
+		} 		
+		this.connect(this.focusNode,"onmousedown","bringToTop");
+		this.connect(this.domNode,	"onmousedown","bringToTop");
+
+		// Initial resize to give child the opportunity to lay itself out
+		this.resize(dojo.coords(this.domNode));
+		
+		this._started = true;
+	},
+
+	setTitle: function(/* String */ title){
+		// summary: Update the Title bar with a new string
+		dojo.deprecated("pane.setTitle", "Use pane.attr('title', someTitle)", "2.0");
+		this.set("title", title);
+		// this.setTitle = dojo.hitch(this, "setTitle") ?? 
+	},
+		
+	close: function(){
+		// summary: Close and destroy this widget
+		if(!this.closable){ return; }
+		dojo.unsubscribe(this._listener);
+		this.hide(dojo.hitch(this,function(){
+			this.destroyRecursive();
+		})); 
+	},
+
+	hide: function(/* Function? */ callback){
+		// summary: Close, but do not destroy this FloatingPane
+		dojo.fadeOut({
+			node:this.domNode,
+			duration:this.duration,
+			onEnd: dojo.hitch(this,function() { 
+				this.domNode.style.display = "none";
+				this.domNode.style.visibility = "hidden"; 
+				if(this.dockTo && this.dockable){
+					this.dockTo._positionDock(null);
+				}
+				if(callback){
+					callback();
+				}
+			})
+		}).play();
+	},
+
+	show: function(/* Function? */callback){
+		// summary: Show the FloatingPane
+		var anim = dojo.fadeIn({node:this.domNode, duration:this.duration,
+			beforeBegin: dojo.hitch(this,function(){
+				this.domNode.style.display = ""; 
+				this.domNode.style.visibility = "visible";
+				if (this.dockTo && this.dockable) { this.dockTo._positionDock(null); }
+				if (typeof callback == "function") { callback(); }
+				this._isDocked = false;
+				if (this._dockNode) { 
+					this._dockNode.destroy();
+					this._dockNode = null;
+				}
+			})
+		}).play();
+		this.resize(dojo.coords(this.domNode));
+	},
+
+	minimize: function(){
+		// summary: Hide and dock the FloatingPane
+		if(!this._isDocked){ this.hide(dojo.hitch(this,"_dock")); } 
+	},
+
+	maximize: function(){
+		// summary: Make this FloatingPane full-screen (viewport)	
+		if(this._maximized){ return; }
+		this._naturalState = dojo.position(this.domNode);
+		if(this._isDocked){
+			this.show();
+			setTimeout(dojo.hitch(this,"maximize"),this.duration);
+		}
+		dojo.addClass(this.focusNode,"floatingPaneMaximized");
+		this.resize(dojo.window.getBox());
+		this._maximized = true;
+	},
+
+	_restore: function(){
+		if(this._maximized){
+			this.resize(this._naturalState);
+			dojo.removeClass(this.focusNode,"floatingPaneMaximized");
+			this._maximized = false;
+		}	
+	},
+
+	_dock: function(){
+		if(!this._isDocked && this.dockable){
+			this._dockNode = this.dockTo.addNode(this);
+			this._isDocked = true;
+		}
+	},
+	
+	resize: function(/* Object */dim){
+		// summary: Size the FloatingPane and place accordingly
+		dim = dim || this._naturalState;
+		this._currentState = dim;
+
+		// From the ResizeHandle we only get width and height information
+		var dns = this.domNode.style;
+		if("t" in dim){ dns.top = dim.t + "px"; }
+		if("l" in dim){ dns.left = dim.l + "px"; }
+		dns.width = dim.w + "px"; 
+		dns.height = dim.h + "px";
+
+		// Now resize canvas
+		var mbCanvas = { l: 0, t: 0, w: dim.w, h: (dim.h - this.focusNode.offsetHeight) };
+		dojo.marginBox(this.canvas, mbCanvas);
+
+		// If the single child can resize, forward resize event to it so it can
+		// fit itself properly into the content area
+		this._checkIfSingleChild();
+		if(this._singleChild && this._singleChild.resize){
+			this._singleChild.resize(mbCanvas);
+		}
+	},
+	
+	bringToTop: function(){
+		// summary: bring this FloatingPane above all other panes
+		var windows = dojo.filter(
+			this._allFPs,
+			function(i){
+				return i !== this;
+			}, 
+		this);
+		windows.sort(function(a, b){
+			return a.domNode.style.zIndex - b.domNode.style.zIndex;
+		});
+		windows.push(this);
+		
+		dojo.forEach(windows, function(w, x){
+			w.domNode.style.zIndex = this._startZ + (x * 2);
+			dojo.removeClass(w.domNode, "dojoxFloatingPaneFg");
+		}, this);
+		dojo.addClass(this.domNode, "dojoxFloatingPaneFg");
+	},
+	
+	destroy: function(){
+		// summary: Destroy this FloatingPane completely
+		this._allFPs.splice(dojo.indexOf(this._allFPs, this), 1);
+		if(this._resizeHandle){
+			this._resizeHandle.destroy();
+		}
+		this.inherited(arguments);
+	}
+});
+
+
+dojo.declare("dojox.layout.Dock",
+	[dijit._Widget,dijit._Templated],
+	{
+	// summary:
+	//		A widget that attaches to a node and keeps track of incoming / outgoing FloatingPanes
+	// 		and handles layout
+
+	templateString: '<div class="dojoxDock"><ul dojoAttachPoint="containerNode" class="dojoxDockList"></ul></div>',
+
+	// private _docked: array of panes currently in our dock
+	_docked: [],
+	
+	_inPositioning: false,
+	
+	autoPosition: false,
+	
+	addNode: function(refNode){
+		// summary: Instert a dockNode refernce into the dock
+		
+		var div = dojo.create('li', null, this.containerNode),
+			node = new dojox.layout._DockNode({ 
+				title: refNode.title,
+				paneRef: refNode 
+			}, div)
+		;
+		node.startup();
+		return node;
+	},
+
+	startup: function(){
+				
+		if (this.id == "dojoxGlobalFloatingDock" || this.isFixedDock) {
+			// attach window.onScroll, and a position like in presentation/dialog
+			this.connect(window, 'onresize', "_positionDock");
+			this.connect(window, 'onscroll', "_positionDock");
+			if(dojo.isIE){
+				this.connect(this.domNode, "onresize", "_positionDock");
+			}
+		}
+		this._positionDock(null);
+		this.inherited(arguments);
+
+	},
+	
+	_positionDock: function(/* Event? */e){
+		if(!this._inPositioning){	
+			if(this.autoPosition == "south"){
+				// Give some time for scrollbars to appear/disappear
+				setTimeout(dojo.hitch(this, function() {
+					this._inPositiononing = true;
+					var viewport = dojo.window.getBox();
+					var s = this.domNode.style;
+					s.left = viewport.l + "px";
+					s.width = (viewport.w-2) + "px";
+					s.top = (viewport.h + viewport.t) - this.domNode.offsetHeight + "px";
+					this._inPositioning = false;
+				}), 125);
+			}
+		}
+	}
+
+
+});
+
+dojo.declare("dojox.layout._DockNode",
+	[dijit._Widget,dijit._Templated],
+	{
+	// summary:
+	//		dojox.layout._DockNode is a private widget used to keep track of
+	//		which pane is docked.
+	//
+	// title: String
+	// 		Shown in dock icon. should read parent iconSrc?	
+	title: "",
+
+	// paneRef: Widget
+	//		reference to the FloatingPane we reprasent in any given dock
+	paneRef: null,
+
+	templateString:
+		'<li dojoAttachEvent="onclick: restore" class="dojoxDockNode">'+
+			'<span dojoAttachPoint="restoreNode" class="dojoxDockRestoreButton" dojoAttachEvent="onclick: restore"></span>'+
+			'<span class="dojoxDockTitleNode" dojoAttachPoint="titleNode">${title}</span>'+
+		'</li>',
+
+	restore: function(){
+		// summary: remove this dock item from parent dock, and call show() on reffed floatingpane
+		this.paneRef.show();
+		this.paneRef.bringToTop();
+		if(!this.paneRef.isLoaded){ this.paneRef.refresh(); }
+		this.destroy();
+	}
+
 });
-_b.push(this);
-dojo.forEach(_b,function(w,x){
-w.domNode.style.zIndex=this._startZ+(x*2);
-dojo.removeClass(w.domNode,"dojoxFloatingPaneFg");
-},this);
-dojo.addClass(this.domNode,"dojoxFloatingPaneFg");
-},destroy:function(){
-this._allFPs.splice(dojo.indexOf(this._allFPs,this),1);
-if(this._resizeHandle){
-this._resizeHandle.destroy();
-}
-this.inherited(arguments);
-}});
-dojo.declare("dojox.layout.Dock",[dijit._Widget,dijit._Templated],{templateString:"<div class=\"dojoxDock\"><ul dojoAttachPoint=\"containerNode\" class=\"dojoxDockList\"></ul></div>",_docked:[],_inPositioning:false,autoPosition:false,addNode:function(_c){
-var _d=dojo.create("li",null,this.containerNode),_e=new dojox.layout._DockNode({title:_c.title,paneRef:_c},_d);
-_e.startup();
-return _e;
-},startup:function(){
-if(this.id=="dojoxGlobalFloatingDock"||this.isFixedDock){
-this.connect(window,"onresize","_positionDock");
-this.connect(window,"onscroll","_positionDock");
-if(dojo.isIE){
-this.connect(this.domNode,"onresize","_positionDock");
-}
-}
-this._positionDock(null);
-this.inherited(arguments);
-},_positionDock:function(e){
-if(!this._inPositioning){
-if(this.autoPosition=="south"){
-setTimeout(dojo.hitch(this,function(){
-this._inPositiononing=true;
-var _f=dijit.getViewport();
-var s=this.domNode.style;
-s.left=_f.l+"px";
-s.width=(_f.w-2)+"px";
-s.top=(_f.h+_f.t)-this.domNode.offsetHeight+"px";
-this._inPositioning=false;
-}),125);
-}
-}
-}});
-dojo.declare("dojox.layout._DockNode",[dijit._Widget,dijit._Templated],{title:"",paneRef:null,templateString:"<li dojoAttachEvent=\"onclick: restore\" class=\"dojoxDockNode\">"+"<span dojoAttachPoint=\"restoreNode\" class=\"dojoxDockRestoreButton\" dojoAttachEvent=\"onclick: restore\"></span>"+"<span class=\"dojoxDockTitleNode\" dojoAttachPoint=\"titleNode\">${title}</span>"+"</li>",restore:function(){
-this.paneRef.show();
-this.paneRef.bringToTop();
-if(!this.paneRef.isLoaded){
-this.paneRef.refresh();
-}
-this.destroy();
-}});
-}
diff --git a/dojox/layout/GridContainer.js b/dojox/layout/GridContainer.js
index 27a28c2..130b3d1 100644
--- a/dojox/layout/GridContainer.js
+++ b/dojox/layout/GridContainer.js
@@ -1,826 +1,621 @@
-/*
-	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
-*/
+dojo.provide("dojox.layout.GridContainer");
 
+dojo.require("dojox.layout.GridContainerLite");
 
-if(!dojo._hasResource["dojox.layout.GridContainer"]){
-dojo._hasResource["dojox.layout.GridContainer"]=true;
-dojo.provide("dojox.layout.GridContainer");
-dojo.experimental("dojox.layout.GridContainer");
-dojo.require("dijit._base.focus");
-dojo.require("dijit._Templated");
-dojo.require("dijit._Container");
-dojo.require("dijit._Contained");
-dojo.require("dojo.dnd.move");
-dojo.require("dojox.layout.dnd.PlottedDnd");
-dojo.declare("dojox.layout.GridContainer",[dijit._Widget,dijit._Templated,dijit._Container,dijit._Contained],{templateString:dojo.cache("dojox.layout","resources/GridContainer.html","<div id=\"${id}\" class=\"gridContainer\" dojoAttachPoint=\"containerNode\" tabIndex=\"0\" dojoAttachEvent=\"onkeypress:_selectFocus\">\n\t<table class=\"gridContainerTable\" dojoAttachPoint=\"gridContainerTable\" cellspacing=\"0\" cellpadding=\"0\">\n\t\t<tbody class=\"gridContainerBody\">\n\t\t\t<tr class= [...]
-_1=_1||{};
-this.acceptTypes=_1.acceptTypes||["dijit.layout.ContentPane"];
-this.offsetDrag=_1.offsetDrag||_1.dragOffset||{x:0,y:0};
-},postCreate:function(){
-this.inherited(arguments);
-if(this.nbZones===0){
-this.nbZones=1;
-}
-if(dojo.isIE&&dojo.marginBox(this.gridNode).height){
-var _3=document.createTextNode(" ");
-this.gridNode.appendChild(_3);
-}
-for(var i=0;i<this.nbZones;i++){
-var _4=dojo.create("td",{id:this.id+"_dz"+i,className:"gridContainerZone",style:{width:this._getColWidth(i)+"%"}},this.gridNode);
-}
-},startup:function(){
-this.grid=this._createGrid();
-this.connect(dojo.global,"onresize","onResized");
-this.connect(this,"onDndDrop","_placeGrips");
-this.dropHandler=dojo.subscribe("/dnd/drop",this,"_placeGrips");
-this._oldwidth=this.domNode.offsetWidth;
-if(this.hasResizableColumns){
-this._initPlaceGrips();
-this._placeGrips();
-}
-if(this.usepref!==true){
-this[(this.isAutoOrganized?"_organizeServices":"_organizeServicesManually")]();
-}
-for(var j=0;j<this.grid.length;j++){
-var dz=this.grid[j];
-dojo.forEach(dz.node.childNodes,function(_5){
-dz.setItem(_5.id,{data:_5,type:[_5.getAttribute("dndType")]});
-});
-}
-this.inherited(arguments);
-},destroy:function(){
-for(var i=0;i<this.handleDndStart;i++){
-dojo.disconnect(this.handleDndStart[i]);
-}
-dojo.unsubscribe(this.dropHandler);
-this.inherited(arguments);
-},resize:function(){
-dojo.forEach(this.getChildren(),function(_6){
-_6.resize&&_6.resize();
-});
-},getZones:function(){
-return dojo.query(".gridContainerZone",this.containerNode);
-},getNewChildren:function(){
-return dojo.query("> [widgetId]",this.containerNode).map(dijit.byNode);
-},getChildren:function(){
-var _7=dojo.query(".gridContainerZone > [widgetId]",this.containerNode).map(dijit.byNode);
-return _7;
-},onResized:function(){
-if(this.hasResizableColumns){
-this._placeGrips();
-}
-},_organizeServices:function(){
-var _8=this.nbZones,_9=this.getNewChildren(),_a=_9.length,_b=Math.floor(_a/_8),_c=_a%_8,i=0;
-for(var z=0;z<_8;z++){
-for(var r=0;r<_b;r++){
-this._insertService(z,i,_9[i],true);
-i++;
-}
-if(_c>0){
-try{
-this._insertService(z,i,_9[i],true);
-i++;
-}
-catch(e){
-console.error("Unable to insert service in grid container",e,_9);
-}
-_c--;
-}else{
-if(_b===0){
-break;
-}
-}
-}
-},_organizeServicesManually:function(){
-var _d=this.getNewChildren();
-for(var i=0;i<_d.length;i++){
-try{
-this._insertService(_d[i].column-1,i,_d[i],true);
-}
-catch(e){
-console.error("Unable to insert service in grid container",e,_d[i]);
-}
-}
-},_insertService:function(z,p,_e,_f){
-if(_e===undefined){
-return;
-}
-var _10=this.getZones()[z];
-var _11=_10.childNodes.length;
-if(p===undefined||p>_11){
-p=_11;
-}
-var _12=dojo.place(_e.domNode,_10,p);
-_e.domNode.setAttribute("tabIndex",0);
-if(!_e.dragRestriction){
-dojo.addClass(_e.domNode,"dojoDndItem");
-}
-if(!_e.domNode.getAttribute("dndType")){
-_e.domNode.setAttribute("dndType",_e.declaredClass);
-}
-dojox.layout.dnd._setGcDndHandle(_e,this.withHandles,this.handleClasses,_f);
-if(this.hasResizableColumns){
-if(_e.onLoad){
-this.connect(_e,"onLoad","_placeGrips");
-}
-if(_e.onExecError){
-this.connect(_e,"onExecError","_placeGrips");
-}
-if(_e.onUnLoad){
-this.connect(_e,"onUnLoad","_placeGrips");
-}
-}
-this._placeGrips();
-return _e.id;
-},addService:function(_13,z,p){
-return this.addChild(_13,z,p);
-},addChild:function(_14,z,p){
-_14.domNode.id=_14.id;
-if(z<=0){
-z=0;
-}
-var _15=z||0;
-if(p<=0){
-p=0;
-}
-var row=p||0;
-var _16=this._insertService(_15,row,_14);
-if(this._started&&!_14._started){
-this.grid[z].setItem(_14.id,{data:_14.domNode,type:[_14.domNode.getAttribute("dndType")]});
-_14.startup();
-}
-return _16;
-},_createGrid:function(){
-var _17=[];
-var i=0;
-while(i<this.nbZones){
-var _18=this._createZone(this.getZones()[i]);
-if(this.hasResizableColumns&&i!=(this.nbZones-1)){
-this._createGrip(_18);
-}
-_17.push(_18);
-i++;
-}
-if(this.hasResizableColumns){
-this.handleDndStart=[];
-for(var j=0;j<_17.length;j++){
-var dz=_17[j];
-var _19=this;
-this.handleDndStart.push(dojo.connect(dz,"onDndStart",dz,function(_1a){
-if(_1a==this){
-_19.handleDndInsertNodes=[];
-for(i=0;i<_19.grid.length;i++){
-_19.handleDndInsertNodes.push(dojo.connect(_19.grid[i],"insertNodes",_19,function(){
-_19._disconnectDnd();
-}));
-}
-_19.handleDndInsertNodes.push(dojo.connect(dz,"onDndCancel",_19,_19._disconnectDnd));
-_19.onResized();
-}
-}));
-}
-}
-return _17;
-},_disconnectDnd:function(){
-dojo.forEach(this.handleDndInsertNodes,dojo.disconnect);
-setTimeout(dojo.hitch(this,"onResized"),0);
-},_createZone:function(_1b){
-var dz=new dojox.layout.dnd.PlottedDnd(_1b.id,{accept:this.acceptTypes,withHandles:this.withHandles,handleClasses:this.handleClasses,singular:true,hideSource:true,opacity:this.opacity,dom:this.domNode,allowAutoScroll:this.allowAutoScroll,isOffset:this.isOffset,offsetDrag:this.offsetDrag});
-this.connect(dz,"insertDashedZone","_placeGrips");
-this.connect(dz,"deleteDashedZone","_placeGrips");
-return dz;
-},_createGrip:function(dz){
-var _1c=document.createElement("div");
-_1c.className="gridContainerGrip";
-_1c.setAttribute("tabIndex","0");
-var _1d=this;
-this.onMouseOver=this.connect(_1c,"onmouseover",function(e){
-var _1e=false;
-for(var i=0;i<_1d.grid.length-1;i++){
-if(dojo.hasClass(_1d.grid[i].grip,"gridContainerGripShow")){
-_1e=true;
-break;
-}
-}
-if(!_1e){
-dojo.removeClass(e.target,"gridContainerGrip");
-dojo.addClass(e.target,"gridContainerGripShow");
-}
-});
-this.connect(_1c,"onmouseout",function(e){
-if(!_1d._isResized){
-dojo.removeClass(e.target,"gridContainerGripShow");
-dojo.addClass(e.target,"gridContainerGrip");
-}
-});
-this.connect(_1c,"onmousedown",function(e){
-_1d._a11yOn=false;
-_1d._activeGrip=e.target;
-_1d.resizeColumnOn(e);
-});
-this.domNode.appendChild(_1c);
-dz.grip=_1c;
-},_initPlaceGrips:function(){
-var dcs=dojo.getComputedStyle(this.domNode);
-this._x=parseInt(dcs.paddingLeft);
-var _1f=parseInt(dcs.paddingTop);
-if(dojo.isIE||dojo.getComputedStyle(this.gridContainerTable).borderCollapse!="collapse"){
-var ex=dojo._getBorderExtents(this.gridContainerTable);
-this._x+=ex.l;
-_1f+=ex.t;
-}
-_1f+="px";
-for(var z=0;z<this.grid.length;z++){
-var _20=this.grid[z];
-if(_20.grip){
-var _21=_20.grip;
-if(!dojo.isIE){
-_20.pad=dojo._getPadBorderExtents(_20.node).w;
-}
-_21.style.top=_1f;
-}
-}
-},_placeGrips:function(){
-var _22;
-var _23=this._x;
-dojo.forEach(this.grid,function(_24){
-if(_24.grip){
-if(_22===undefined){
-if(this.allowAutoScroll){
-_22=this.gridNode.scrollHeight;
-}else{
-_22=dojo.contentBox(this.gridNode).h;
-}
-}
-var _25=_24.grip;
-_23+=dojo[(dojo.isIE?"marginBox":"contentBox")](_24.node).w+(dojo.isIE?0:_24.pad);
-dojo.style(_25,{left:_23+"px",height:_22+"px"});
-}
-},this);
-},_getZoneByIndex:function(n){
-return this.grid[(n>=0&&n<this.grid.length?n:0)];
-},getIndexZone:function(_26){
-for(var z=0;z<this.grid.length;z++){
-if(this.grid[z].node.id==_26.id){
-return z;
-}
-}
-return -1;
-},resizeColumnOn:function(e){
-var k=dojo.keys;
-var i;
-if(!(this._a11yOn&&e.keyCode!=k.LEFT_ARROW&&e.keyCode!=k.RIGHT_ARROW)){
-e.preventDefault();
-dojo.body().style.cursor="ew-resize";
-this._isResized=true;
-this.initX=e.pageX;
-var _27=[];
-for(i=0;i<this.grid.length;i++){
-_27[i]=dojo.contentBox(this.grid[i].node).w;
-}
-this.oldTabSize=_27;
-for(i=0;i<this.grid.length;i++){
-if(this._activeGrip==this.grid[i].grip){
-this.currentColumn=this.grid[i].node;
-this.currentColumnWidth=_27[i];
-this.nextColumn=this.currentColumn.nextSibling;
-this.nextColumnWidth=_27[i+1];
-}
-this.grid[i].node.style.width=_27[i]+"px";
-}
-var _28=function(_29,_2a){
-var _2b=0;
-var _2c=0;
-dojo.forEach(_29,function(_2d){
-if(_2d.nodeType==1){
-var _2e=dojo.getComputedStyle(_2d);
-var _2f=(dojo.isIE?_2a:parseInt(_2e.minWidth));
-_2c=_2f+parseInt(_2e.marginLeft)+parseInt(_2e.marginRight);
-if(_2b<_2c){
-_2b=_2c;
-}
-}
-});
-return _2b;
-};
-var _30=_28(this.currentColumn.childNodes,this.minChildWidth);
-var _31=_28(this.nextColumn.childNodes,this.minChildWidth);
-var _32=Math.round((dojo.marginBox(this.gridContainerTable).w*this.minColWidth)/100);
-this.currentMinCol=_30;
-this.nextMinCol=_31;
-if(_32>this.currentMinCol){
-this.currentMinCol=_32;
-}
-if(_32>this.nextMinCol){
-this.nextMinCol=_32;
-}
-if(this._a11yOn){
-this.connectResizeColumnMove=this.connect(dojo.doc,"onkeypress","resizeColumnMove");
-}else{
-this.connectResizeColumnMove=this.connect(dojo.doc,"onmousemove","resizeColumnMove");
-this.connectResizeColumnOff=this.connect(document,"onmouseup","resizeColumnOff");
-}
-}
-},resizeColumnMove:function(e){
-var d=0;
-if(this._a11yOn){
-var k=dojo.keys;
-switch(e.keyCode){
-case k.LEFT_ARROW:
-d=-10;
-break;
-case k.RIGHT_ARROW:
-d=10;
-break;
-}
-}else{
-e.preventDefault();
-d=e.pageX-this.initX;
-}
-if(d==0){
-return;
-}
-if(!(this.currentColumnWidth+d<this.currentMinCol||this.nextColumnWidth-d<this.nextMinCol)){
-this.currentColumnWidth+=d;
-this.nextColumnWidth-=d;
-this.initX=e.pageX;
-this.currentColumn.style["width"]=this.currentColumnWidth+"px";
-this.nextColumn.style["width"]=this.nextColumnWidth+"px";
-this._activeGrip.style.left=parseInt(this._activeGrip.style.left)+d+"px";
-this._placeGrips();
-}
-if(this._a11yOn){
-this.resizeColumnOff(e);
-}
-},resizeColumnOff:function(e){
-dojo.body().style.cursor="default";
-if(this._a11yOn){
-this.disconnect(this.connectResizeColumnMove);
-this._a11yOn=false;
-}else{
-this.disconnect(this.connectResizeColumnMove);
-this.disconnect(this.connectResizeColumnOff);
-}
-var _33=[];
-var _34=[];
-var _35=this.gridContainerTable.clientWidth;
-var i;
-for(i=0;i<this.grid.length;i++){
-var _36=dojo.contentBox(this.grid[i].node);
-if(dojo.isIE){
-_33[i]=dojo.marginBox(this.grid[i].node).w;
-_34[i]=_36.w;
-}else{
-_33[i]=_36.w;
-_34=_33;
-}
-}
-var _37=false;
-for(i=0;i<_34.length;i++){
-if(_34[i]!=this.oldTabSize[i]){
-_37=true;
-break;
-}
-}
-if(_37){
-var mul=dojo.isIE?100:10000;
-for(i=0;i<this.grid.length;i++){
-this.grid[i].node.style.width=Math.round((100*mul*_33[i])/_35)/mul+"%";
-}
-this._placeGrips();
-}
-if(this._activeGrip){
-dojo.removeClass(this._activeGrip,"gridContainerGripShow");
-dojo.addClass(this._activeGrip,"gridContainerGrip");
-}
-this._isResized=false;
-},setColumns:function(_38){
-var _39;
-if(_38>0){
-var _3a=this.grid.length-_38;
-if(_3a>0){
-var _3b=[];
-var _3c,end,z,_3d,j;
-if(this.mode=="right"){
-end=(this.isLeftFixed&&this.grid.length>0)?1:0;
-_3c=this.grid.length-(this.isRightFixed?2:1);
-for(z=_3c;z>=end;z--){
-_3d=0;
-_39=this.grid[z].node;
-for(j=0;j<_39.childNodes.length;j++){
-if(_39.childNodes[j].nodeType==1&&!(_39.childNodes[j].id=="")){
-_3d++;
-break;
-}
-}
-if(_3d==0){
-_3b[_3b.length]=z;
-}
-if(_3b.length>=_3a){
-this._deleteColumn(_3b);
-break;
-}
-}
-if(_3b.length<_3a){
-console.error("Move boxes in first columns, in all tabs before changing the organization of the page");
-}
-}else{
-_3c=(this.isLeftFixed&&this.grid.length>0)?1:0;
-end=this.grid.length;
-if(this.isRightFixed){
-end--;
-}
-for(z=_3c;z<end;z++){
-_3d=0;
-_39=this.grid[z].node;
-for(j=0;j<_39.childNodes.length;j++){
-if(_39.childNodes[j].nodeType==1&&!(_39.childNodes[j].id=="")){
-_3d++;
-break;
-}
-}
-if(_3d==0){
-_3b[_3b.length]=z;
-}
-if(_3b.length>=_3a){
-this._deleteColumn(_3b);
-break;
-}
-}
-if(_3b.length<_3a){
-console.warn("Move boxes in last columns, in all tabs before changing the organization of the page");
-}
-}
-}else{
-if(_3a<0){
-this._addColumn(Math.abs(_3a));
-}
-}
-this._initPlaceGrips();
-this._placeGrips();
-}
-},_addColumn:function(_3e){
-var _3f;
-if(this.hasResizableColumns&&!this.isRightFixed&&this.mode=="right"){
-_3f=this.grid[this.grid.length-1];
-this._createGrip(_3f);
-}
-for(var i=0;i<_3e;i++){
-_3f=dojo.doc.createElement("td");
-dojo.addClass(_3f,"gridContainerZone");
-_3f.id=this.id+"_dz"+this.nbZones;
-var dz;
-if(this.mode=="right"){
-if(this.isRightFixed){
-this.grid[this.grid.length-1].node.parentNode.insertBefore(_3f,this.grid[this.grid.length-1].node);
-dz=this._createZone(_3f);
-this.grid.splice(this.grid.length-1,0,dz);
-}else{
-var _40=this.gridNode.appendChild(_3f);
-dz=this._createZone(_3f);
-this.grid.push(dz);
-}
-}else{
-if(this.isLeftFixed){
-(this.grid.length==1)?this.grid[0].node.parentNode.appendChild(_3f,this.grid[0].node):this.grid[1].node.parentNode.insertBefore(_3f,this.grid[1].node);
-dz=this._createZone(_3f);
-this.grid.splice(1,0,dz);
-}else{
-this.grid[this.grid.length-this.nbZones].node.parentNode.insertBefore(_3f,this.grid[this.grid.length-this.nbZones].node);
-dz=this._createZone(_3f);
-this.grid.splice(this.grid.length-this.nbZones,0,dz);
-}
-}
-if(this.hasResizableColumns){
-var _41=this;
-var _42=dojo.connect(dz,"onDndStart",dz,function(_43){
-if(_43==this){
-_41.handleDndInsertNodes=[];
-for(var o=0;o<_41.grid.length;o++){
-_41.handleDndInsertNodes.push(dojo.connect(_41.grid[o],"insertNodes",_41,function(){
-_41._disconnectDnd();
-}));
-}
-_41.handleDndInsertNodes.push(dojo.connect(dz,"onDndCancel",_41,_41._disconnectDnd));
-_41.onResized();
-}
-});
-if(this.mode=="right"){
-if(this.isRightFixed){
-this.handleDndStart.splice(this.handleDndStart.length-1,0,_42);
-}else{
-this.handleDndStart.push(_42);
-}
-}else{
-if(this.isLeftFixed){
-this.handleDndStart.splice(1,0,_42);
-}else{
-this.handleDndStart.splice(this.handleDndStart.length-this.nbZones,0,_42);
-}
-}
-this._createGrip(dz);
-}
-this.nbZones++;
-}
-this._updateColumnsWidth();
-},_deleteColumn:function(_44){
-var _45,_46,_47;
-_47=0;
-for(var i=0;i<_44.length;i++){
-var idx=_44[i];
-if(this.mode=="right"){
-_45=this.grid[idx];
-}else{
-_45=this.grid[idx-_47];
-}
-for(var j=0;j<_45.node.childNodes.length;j++){
-if(_45.node.childNodes[j].nodeType!=1){
-continue;
-}
-_46=dijit.byId(_45.node.childNodes[j].id);
-for(var x=0;x<this.getChildren().length;x++){
-if(this.getChildren()[x]===_46){
-this.getChildren().splice(x,1);
-break;
-}
-}
-}
-_45.node.parentNode.removeChild(_45.node);
-if(this.mode=="right"){
-if(this.hasResizableColumns){
-dojo.disconnect(this.handleDndStart[idx]);
-}
-this.grid.splice(idx,1);
-}else{
-if(this.hasResizableColumns){
-dojo.disconnect(this.handleDndStart[idx-_47]);
-}
-this.grid.splice(idx-_47,1);
-}
-this.nbZones--;
-_47++;
-if(_45.grip){
-this.domNode.removeChild(_45.grip);
-}
-}
-this._updateColumnsWidth();
-},_getColWidth:function(idx){
-if(idx<this.colWidths.length){
-return this.colWidths[idx];
-}
-var _48=100;
-dojo.forEach(this.colWidths,function(_49){
-_48-=_49;
-});
-return _48/(this.nbZones-this.colWidths.length);
-},_updateColumnsWidth:function(){
-var _4a;
-for(var z=0;z<this.grid.length;z++){
-this.grid[z].node.style.width=this._getColWidth(z)+"%";
-}
-},_selectFocus:function(_4b){
-var e=_4b.keyCode;
-var _4c=null;
-var _4d=dijit.getFocus();
-var _4e=_4d.node;
-var k=dojo.keys;
-var i,_4f,_50,r,z,_51;
-var _52=(e==k.UP_ARROW||e==k.LEFT_ARROW)?"lastChild":"firstChild";
-var pos=(e==k.UP_ARROW||e==k.LEFT_ARROW)?"previousSibling":"nextSibling";
-if(_4e==this.containerNode){
-switch(e){
-case k.DOWN_ARROW:
-case k.RIGHT_ARROW:
-for(i=0;i<this.gridNode.childNodes.length;i++){
-_4c=this.gridNode.childNodes[i].firstChild;
-_4f=false;
-while(!_4f){
-if(_4c!=null){
-if(_4c.style.display!=="none"){
-dijit.focus(_4c);
-dojo.stopEvent(_4b);
-_4f=true;
-}else{
-_4c=_4c[pos];
-}
-}else{
-break;
-}
-}
-if(_4f){
-break;
-}
-}
-break;
-case k.UP_ARROW:
-case k.LEFT_ARROW:
-for(i=this.gridNode.childNodes.length-1;i>=0;i--){
-_4c=this.gridNode.childNodes[i].lastChild;
-_4f=false;
-while(!_4f){
-if(_4c!=null){
-if(_4c.style.display!=="none"){
-dijit.focus(_4c);
-dojo.stopEvent(_4b);
-_4f=true;
-}else{
-_4c=_4c[pos];
-}
-}else{
-break;
-}
-}
-if(_4f){
-break;
-}
-}
-break;
-}
-}else{
-if(_4e.parentNode.parentNode==this.gridNode){
-switch(e){
-case k.UP_ARROW:
-case k.DOWN_ARROW:
-dojo.stopEvent(_4b);
-var _53=0;
-dojo.forEach(_4e.parentNode.childNodes,function(_54){
-if(_54.style.display!=="none"){
-_53++;
-}
-});
-if(_53==1){
-return;
-}
-_4f=false;
-_4c=_4e[pos];
-while(!_4f){
-if(_4c==null){
-_4c=_4e.parentNode[_52];
-if(_4c.style.display!=="none"){
-_4f=true;
-}else{
-_4c=_4c[pos];
-}
-}else{
-if(_4c.style.display!=="none"){
-_4f=true;
-}else{
-_4c=_4c[pos];
-}
-}
-}
-if(_4b.shiftKey){
-if(dijit.byNode(_4e).dragRestriction){
-return;
-}
-_51=_4e.getAttribute("dndtype");
-_50=false;
-for(i=0;i<this.acceptTypes.length;i++){
-if(_51==this.acceptTypes[i]){
-_50=true;
-break;
-}
-}
-if(_50){
-var _55=_4e.parentNode;
-var _56=_55.firstChild;
-var _57=_55.lastChild;
-while(_56.style.display=="none"||_57.style.display=="none"){
-if(_56.style.display=="none"){
-_56=_56.nextSibling;
-}
-if(_57.style.display=="none"){
-_57=_57.previousSibling;
-}
-}
-if(e==k.UP_ARROW){
-r=_55.removeChild(_4e);
-if(r==_56){
-_55.appendChild(r);
-}else{
-_55.insertBefore(r,_4c);
-}
-r.setAttribute("tabIndex","0");
-dijit.focus(r);
-}else{
-if(_4e==_57){
-r=_55.removeChild(_4e);
-_55.insertBefore(r,_4c);
-r.setAttribute("tabIndex","0");
-dijit.focus(r);
-}else{
-r=_55.removeChild(_4c);
-_55.insertBefore(r,_4e);
-_4e.setAttribute("tabIndex","0");
-dijit.focus(_4e);
-}
-}
-}else{
-this._displayPopup();
-}
-}else{
-dijit.focus(_4c);
-}
-break;
-case k.RIGHT_ARROW:
-case k.LEFT_ARROW:
-dojo.stopEvent(_4b);
-if(_4b.shiftKey){
-if(dijit.byNode(_4e).dragRestriction){
-return;
-}
-z=0;
-if(_4e.parentNode[pos]==null){
-if(e==k.LEFT_ARROW){
-z=this.gridNode.childNodes.length-1;
-}
-}else{
-if(_4e.parentNode[pos].nodeType==3){
-z=this.gridNode.childNodes.length-2;
-}else{
-for(i=0;i<this.gridNode.childNodes.length;i++){
-if(_4e.parentNode[pos]==this.gridNode.childNodes[i]){
-break;
-}
-z++;
-}
-}
-}
-_51=_4e.getAttribute("dndtype");
-_50=false;
-for(i=0;i<this.acceptTypes.length;i++){
-if(_51==this.acceptTypes[i]){
-_50=true;
-break;
-}
-}
-if(_50){
-var _58=_4e.parentNode;
-var _59=dijit.byNode(_4e);
-r=_58.removeChild(_4e);
-var _5a=(e==k.RIGHT_ARROW?0:this.gridNode.childNodes[z].length);
-this.addService(_59,z,_5a);
-r.setAttribute("tabIndex","0");
-dijit.focus(r);
-this._placeGrips();
-}else{
-this._displayPopup();
-}
-}else{
-var _5b=_4e.parentNode;
-while(_4c===null){
-if(_5b[pos]!==null&&_5b[pos].nodeType!==3){
-_5b=_5b[pos];
-}else{
-if(pos==="previousSibling"){
-_5b=_5b.parentNode.childNodes[_5b.parentNode.childNodes.length-1];
-}else{
-_5b=_5b.parentNode.childNodes[0];
-}
-}
-_4f=false;
-var _5c=_5b[_52];
-while(!_4f){
-if(_5c!=null){
-if(_5c.style.display!=="none"){
-_4c=_5c;
-_4f=true;
-}else{
-_5c=_5c[pos];
-}
-}else{
-break;
-}
-}
-}
-dijit.focus(_4c);
-}
-break;
-}
-}else{
-if(dojo.hasClass(_4e,"gridContainerGrip")||dojo.hasClass(_4e,"gridContainerGripShow")){
-this._activeGrip=_4b.target;
-this._a11yOn=true;
-this.resizeColumnOn(_4b);
-}
-}
-}
-},_displayPopup:function(){
-if(this._canDisplayPopup){
-var _5d=dojo.doc.createElement("div");
-dojo.addClass(_5d,"gridContainerPopup");
-_5d.innerHTML="this widget type is not accepted to be moved!";
-var _5e=this.containerNode.appendChild(_5d);
-this._canDisplayPopup=false;
-setTimeout(dojo.hitch(this,function(){
-this.containerNode.removeChild(_5e);
-dojo.destroy(_5e);
-this._canDisplayPopup=true;
-}),this.timeDisplayPopup);
-}
-}});
-dojo.extend(dijit._Widget,{dragRestriction:false,column:"1",group:""});
-}
+dojo.declare(
+	"dojox.layout.GridContainer",
+	dojox.layout.GridContainerLite,
+{
+	// summary:
+	//		A grid containing any kind of objects and acting like web portals.
+	//
+	// description:
+	//		This component inherits of all features of gridContainerLite plus :
+	//			- Resize colums
+	//			- Add / remove columns
+	//			- Fix columns at left or at right.
+	// example:
+	// 	|	<div dojoType="dojox.layout.GridContainer" nbZones="3" isAutoOrganized="true">
+	// 	|		<div dojoType="dijit.layout.ContentPane">Content Pane 1 : Drag Me !</div>
+	// 	|		<div dojoType="dijit.layout.ContentPane">Content Pane 2 : Drag Me !</div>
+	// 	|		<div dojoType="dijit.layout.ContentPane">Content Pane 3 : Drag Me !</div>
+	// 	|	</div>
+	//
+	// example:
+	// 	|	dojo.ready(function(){
+	// 	|		var cpane1 = new dijit.layout.ContentPane({ title:"cpane1", content: "Content Pane 1 : Drag Me !" }),
+	// 	|			cpane2 = new dijit.layout.ContentPane({ title:"cpane2", content: "Content Pane 2 : Drag Me !" }),
+	// 	|			cpane3 = new dijit.layout.ContentPane({ title:"cpane3", content: "Content Pane 3 : Drag Me !" });
+	// 	|
+	// 	|		var widget = new dojox.layout.GridContainer({
+	// 	|			nbZones: 3,
+	// 	|			isAutoOrganized: true
+	// 	|		}, dojo.byId("idNode"));
+	// 	|		widget.addChild(cpane1, 0, 0);
+	// 	|		widget.addChild(cpane2, 1, 0);
+	// 	|		widget.addChild(cpane3, 2, 1);
+	// 	|		widget.startup();
+	// 	|	});
+
+	// hasResizableColumns: Boolean
+	//		Allow or not resizing of columns by a grip handle.
+	hasResizableColumns: true,
+
+	// liveResizeColumns: Boolean
+	//		Specifies whether columns resize as you drag (true) or only upon mouseup (false)
+	liveResizeColumns : false,
+
+	// minColWidth: Integer
+	//		Minimum column width in percentage.
+	minColWidth: 20,
+
+	// minChildWidth: Integer
+	// 		Minimum children width in pixel (only used for IE6 which doesn't handle min-width css property)
+	minChildWidth: 150,
+
+	// mode: String
+	//		Location to add/remove columns, must be set to 'left' or 'right' (default).
+	mode: "right",
+
+	// isRightFixed: Boolean
+	//		Define if the last right column is fixed.
+	//		Used when you add or remove columns by calling setColumns method.
+	isRightFixed: false,
+
+	// isLeftFixed: Boolean
+	//		Define if the last left column is fixed.
+	//		Used when you add or remove columns by calling setColumns method.
+	isLeftFixed: false,
+
+	startup: function(){
+		// summary:
+		//		Call the startup of GridContainerLite and place grips
+		//		if user has chosen the hasResizableColumns attribute to true.
+
+		//console.log("dojox.layout.GridContainer ::: startup");
+		this.inherited(arguments);
+		if(this.hasResizableColumns){
+			for(var i = 0; i < this._grid.length - 1; i++){
+				this._createGrip(i);
+			}
+			// If widget has a container parent, grips will be placed
+			// by method onShow.
+			if(!this.getParent()){
+				// Fix IE7 :
+				//		The CSS property height:100% for the grip
+				//		doesn't work anytime. It's necessary to wait
+				//		the end of loading before to place grips.
+				dojo.ready(dojo.hitch(this, "_placeGrips"));
+			}
+		}
+	},
+
+	resizeChildAfterDrop : function(/*Node*/node, /*Object*/targetArea, /*Integer*/indexChild){
+		// summary:
+		//		Call when a child is dropped.
+		// description:
+		//		Allow to resize and put grips
+		// node:
+		//		domNode of dropped widget.
+		// targetArea:
+		//		AreaManager Object containing information of targetArea
+		// indexChild:
+		// 		Index where the dropped widget has been placed
+
+		if(this.inherited(arguments)){
+			this._placeGrips();
+		}
+	},
+
+	onShow: function(){
+		// summary:
+		//		Place grips in the right place when the GridContainer becomes visible.
+
+		//console.log("dojox.layout.GridContainer ::: onShow");
+		this.inherited(arguments);
+		this._placeGrips();
+	},
+
+	resize: function(){
+		// summary:
+		//		Resize the GridContainer widget and columns.
+		//		Replace grips if it's necessary.
+		// tags:
+		//		callback
+
+		//console.log("dojox.layout.GridContainer ::: resize");
+		this.inherited(arguments);
+		// Fix IE6 :
+		//		IE6 calls method resize itself.
+		//		If the GridContainer is not visible at this time,
+		//		the method _placeGrips can return a negative value with
+		// 		contentBox method. (see method _placeGrip() with Fix Ie6 for the height)
+		if(this._isShown() && this.hasResizableColumns){
+			this._placeGrips();
+		}
+	},
+
+	_createGrip: function(/*Integer*/ index){
+		// summary:
+		//		Create a grip for a specific zone.
+		// index:
+		//		index where the grip has to be created.
+		// tags:
+		//		protected
+
+		//console.log("dojox.layout.GridContainer ::: _createGrip");
+		var dropZone = this._grid[index],
+			grip = dojo.create("div", { 'class': "gridContainerGrip" }, this.domNode);
+		dropZone.grip = grip;
+		dropZone.gripHandler = [
+			this.connect(grip, "onmouseover", function(e){
+				var gridContainerGripShow = false;
+				for(var i = 0; i < this._grid.length - 1; i++){
+					if(dojo.hasClass(this._grid[i].grip, "gridContainerGripShow")){
+						gridContainerGripShow = true;
+						break;
+					}
+				}
+				if(!gridContainerGripShow){
+					dojo.removeClass(e.target, "gridContainerGrip");
+					dojo.addClass(e.target, "gridContainerGripShow");
+				}
+			})[0],
+			this.connect(grip, "onmouseout", function(e){
+				if(!this._isResized){
+					dojo.removeClass(e.target, "gridContainerGripShow");
+					dojo.addClass(e.target, "gridContainerGrip");
+				}
+			})[0],
+			this.connect(grip, "onmousedown", "_resizeColumnOn")[0],
+			this.connect(grip, "ondblclick", "_onGripDbClick")[0]
+		];
+	},
+
+	_placeGrips: function(){
+		// summary:
+		//		Define the position of a grip and place it on page.
+		// tags:
+		//		protected
+
+		//console.log("dojox.layout.GridContainer ::: _placeGrips");
+		var gripWidth, height, left = 0, grip;
+		var scroll = this.domNode.style.overflowY;
+
+		dojo.forEach(this._grid, function(dropZone){
+			if(dropZone.grip){
+				grip = dropZone.grip;
+				if(!gripWidth){
+					gripWidth = grip.offsetWidth / 2;
+				}
+
+				left += dojo.marginBox(dropZone.node).w;
+
+				dojo.style(grip, "left", (left - gripWidth) + "px");
+				//if(dojo.isIE == 6){ do it fot all navigators
+				if(!height){
+					height = dojo.contentBox(this.gridNode).h;
+				}
+				if(height > 0){
+					dojo.style(grip, "height", height + "px");
+				}
+				//}
+			}
+		}, this);
+	},
+
+	_onGripDbClick: function(){
+		// summary:
+		//		Called when a double click is catch. Resize all columns with the same width.
+		//		The method resize of children have to be called.
+		// tags:
+		//		callback protected
+
+		//console.log("dojox.layout.GridContainer ::: _onGripDbClick");
+		this._updateColumnsWidth(this._dragManager);
+		this.resize();
+	},
+
+	_resizeColumnOn: function(/*Event*/e){
+		// summary:
+		//		Connect events to listen the resize action.
+		//		Change the type of width columns (% to px).
+		//		Calculate the minwidth according to the children.
+		// tags:
+		//		callback
+
+		//console.log("dojox.layout.GridContainer ::: _resizeColumnOn", e);
+		this._activeGrip = e.target;
+		this._initX = e.pageX;
+		e.preventDefault();
+
+		dojo.body().style.cursor = "ew-resize";
+
+		this._isResized = true;
+
+		var tabSize = [];
+		var grid;
+		var i;
+
+		for(i = 0; i < this._grid.length; i++){
+			tabSize[i] = dojo.contentBox(this._grid[i].node).w;
+		}
+
+		this._oldTabSize = tabSize;
+
+		for(i = 0; i < this._grid.length; i++){
+			grid = this._grid[i];
+			if(this._activeGrip == grid.grip){
+				this._currentColumn = grid.node;
+				this._currentColumnWidth = tabSize[i];
+				this._nextColumn = this._grid[i + 1].node;
+				this._nextColumnWidth = tabSize[i + 1];
+			}
+			grid.node.style.width = tabSize[i] + "px";
+		}
+
+		// calculate the minWidh of all children for current and next column
+		var calculateChildMinWidth = function(childNodes, minChild){
+			var width = 0;
+			var childMinWidth = 0;
+
+			dojo.forEach(childNodes, function(child){
+				if(child.nodeType == 1){
+					var objectStyle = dojo.getComputedStyle(child);
+					var minWidth = (dojo.isIE) ? minChild : parseInt(objectStyle.minWidth);
+
+					childMinWidth = minWidth +
+								parseInt(objectStyle.marginLeft) +
+								parseInt(objectStyle.marginRight);
+
+					if(width < childMinWidth){
+						width = childMinWidth;
+					}
+				}
+			});
+			return width;
+		}
+		var currentColumnMinWidth = calculateChildMinWidth(this._currentColumn.childNodes, this.minChildWidth);
+
+		var nextColumnMinWidth = calculateChildMinWidth(this._nextColumn.childNodes, this.minChildWidth);
+
+		var minPix = Math.round((dojo.marginBox(this.gridContainerTable).w * this.minColWidth) / 100);
+
+		this._currentMinCol = currentColumnMinWidth;
+		this._nextMinCol = nextColumnMinWidth;
+
+		if(minPix > this._currentMinCol){
+			this._currentMinCol = minPix;
+		}
+		if(minPix > this._nextMinCol){
+			this._nextMinCol = minPix;
+		}
+		this._connectResizeColumnMove = dojo.connect(dojo.doc, "onmousemove", this, "_resizeColumnMove");
+		this._connectOnGripMouseUp = dojo.connect(dojo.doc, "onmouseup", this, "_onGripMouseUp");
+	},
+
+	_onGripMouseUp: function(){
+		// summary:
+		//		Call on the onMouseUp only if the reiszeColumnMove was not called.
+		// tags:
+		//		callback
+
+		//console.log(dojox.layout.GridContainer ::: _onGripMouseUp");
+		dojo.body().style.cursor = "default";
+
+		dojo.disconnect(this._connectResizeColumnMove);
+		dojo.disconnect(this._connectOnGripMouseUp);
+
+		this._connectOnGripMouseUp = this._connectResizeColumnMove = null;
+
+		if(this._activeGrip){
+			dojo.removeClass(this._activeGrip, "gridContainerGripShow");
+			dojo.addClass(this._activeGrip, "gridContainerGrip");
+		}
+
+		this._isResized = false;
+	},
+
+	_resizeColumnMove: function(/*Event*/e){
+		// summary:
+		//		Change columns size.
+		// tags:
+		//		callback
+
+		//console.log("dojox.layout.GridContainer ::: _resizeColumnMove");
+		e.preventDefault();
+		if(!this._connectResizeColumnOff){
+			dojo.disconnect(this._connectOnGripMouseUp);
+			this._connectOnGripMouseUp = null;
+			this._connectResizeColumnOff = dojo.connect(dojo.doc, "onmouseup", this, "_resizeColumnOff");
+		}
+
+		var d = e.pageX - this._initX;
+		if(d == 0){ return; }
+
+		if(!(this._currentColumnWidth + d < this._currentMinCol || 
+				this._nextColumnWidth - d < this._nextMinCol)){
+
+			this._currentColumnWidth += d;
+			this._nextColumnWidth -= d;
+			this._initX = e.pageX;
+			this._activeGrip.style.left = parseInt(this._activeGrip.style.left) + d + "px";
+
+			if(this.liveResizeColumns){
+				this._currentColumn.style["width"] = this._currentColumnWidth + "px";
+				this._nextColumn.style["width"] = this._nextColumnWidth + "px";
+				this.resize();
+			}
+		}
+	},
+
+	_resizeColumnOff: function(/*Event*/e){
+		// summary:
+		//		Disconnect resize events.
+		//		Change the type of width columns (px to %).
+		// tags:
+		//		callback
+
+		//console.log("dojox.layout.GridContainer ::: _resizeColumnOff");
+		dojo.body().style.cursor = "default";
+
+		dojo.disconnect(this._connectResizeColumnMove);
+		dojo.disconnect(this._connectResizeColumnOff);
+
+		this._connectResizeColumnOff = this._connectResizeColumnMove = null;
+
+		if(!this.liveResizeColumns){
+			this._currentColumn.style["width"] = this._currentColumnWidth + "px";
+			this._nextColumn.style["width"] = this._nextColumnWidth + "px";
+			//this.resize();
+		}
+
+		var tabSize = [],
+			testSize = [],
+			tabWidth = this.gridContainerTable.clientWidth,
+			node,
+			update = false,
+			i;
+
+		for(i = 0; i < this._grid.length; i++){
+			node = this._grid[i].node;
+			if(dojo.isIE){
+				tabSize[i] = dojo.marginBox(node).w;
+				testSize[i] = dojo.contentBox(node).w;
+			}
+			else{
+				tabSize[i] = dojo.contentBox(node).w;
+				testSize = tabSize;
+			}
+		}
+
+		for(i = 0; i < testSize.length; i++){
+			if(testSize[i] != this._oldTabSize[i]){
+				update = true;
+				break;
+			}
+		}
+
+		if(update){
+			var mul = dojo.isIE ? 100 : 10000;
+			for(i = 0; i < this._grid.length; i++){
+				this._grid[i].node.style.width = Math.round((100 * mul * tabSize[i]) / tabWidth) / mul + "%";
+			}
+			this.resize();
+		}
+
+		if(this._activeGrip){
+			dojo.removeClass(this._activeGrip, "gridContainerGripShow");
+			dojo.addClass(this._activeGrip, "gridContainerGrip");
+		}
+
+		this._isResized = false;
+	},
+
+	setColumns: function(/*Integer*/nbColumns){
+		// summary:
+		//		Set the number of columns.
+		// nbColumns:
+		//		Number of columns
+
+		//console.log("dojox.layout.GridContainer ::: setColumns");
+		var z, j;
+		if(nbColumns > 0){
+			var length = this._grid.length,
+				delta = length - nbColumns;
+			if(delta > 0){
+				var count = [], zone, start, end, nbChildren;
+				// Check if right or left columns are fixed
+				// Columns are not taken in account and can't be deleted
+				if(this.mode == "right"){
+					end = (this.isLeftFixed && length > 0) ? 1 : 0;
+					start = (this.isRightFixed) ? length - 2 : length - 1
+					for(z = start; z >= end; z--){
+						nbChildren = 0;
+						zone = this._grid[z].node;
+						for(j = 0; j < zone.childNodes.length; j++){
+							if(zone.childNodes[j].nodeType == 1 && !(zone.childNodes[j].id == "")){
+								nbChildren++;
+								break;
+							}
+						}
+						if(nbChildren == 0){ count[count.length] = z; }
+						if(count.length >= delta){
+							this._deleteColumn(count);
+							break;
+						}
+					}
+					if(count.length < delta){
+						dojo.publish("/dojox/layout/gridContainer/noEmptyColumn", [this]);
+					}
+				}
+				else{ // mode = "left"
+					start = (this.isLeftFixed && length > 0) ? 1 : 0;
+					end = (this.isRightFixed) ? length - 1 : length;
+					for(z = start; z < end; z++){
+						nbChildren = 0;
+						zone = this._grid[z].node;
+						for(j = 0; j < zone.childNodes.length; j++){
+							if(zone.childNodes[j].nodeType == 1 && !(zone.childNodes[j].id == "")){
+								nbChildren++;
+								break;
+							}
+						}
+						if(nbChildren == 0){ count[count.length] = z; }
+						if(count.length >= delta){
+							this._deleteColumn(count);
+							break;
+						}
+					}
+					if(count.length < delta){
+						//Not enough empty columns
+						dojo.publish("/dojox/layout/gridContainer/noEmptyColumn", [this]);
+					}
+				}
+			}
+			else{
+				if(delta < 0){ this._addColumn(Math.abs(delta)); }
+			}
+			if(this.hasResizableColumns){ this._placeGrips(); }
+		}
+	},
+
+	_addColumn: function(/*Integer*/nbColumns){
+		// summary:
+		//		Add some columns.
+		// nbColumns:
+		//		Number of column to added
+		// tags:
+		//		private
+
+		//console.log("dojox.layout.GridContainer ::: _addColumn");
+		var grid = this._grid,
+			dropZone,
+			node,
+			index,
+			length,
+			isRightMode = (this.mode == "right"),
+			accept = this.acceptTypes.join(","),
+			m = this._dragManager;
+
+		//Add a grip to the last column
+		if(this.hasResizableColumns && ((!this.isRightFixed && isRightMode)
+			|| (this.isLeftFixed && !isRightMode && this.nbZones == 1) )){
+			this._createGrip(grid.length - 1);
+		}
+
+		for(var i = 0; i < nbColumns; i++){
+			// Fix CODEX defect #53025 :
+			//		Apply acceptType attribute on each new column.
+			node = dojo.create("td", {
+				'class': "gridContainerZone dojoxDndArea" ,
+				'accept': accept,
+				'id': this.id + "_dz" + this.nbZones
+			});
+
+			length = grid.length;
+
+			if(isRightMode){
+				if(this.isRightFixed){
+					index = length - 1;
+					grid.splice(index, 0, {
+						'node': grid[index].node.parentNode.insertBefore(node, grid[index].node) 
+					});
+				}
+				else{
+					index = length;
+					grid.push({ 'node': this.gridNode.appendChild(node) });
+				}
+			}
+			else{
+				if(this.isLeftFixed){
+					index = (length == 1) ? 0 : 1;
+					this._grid.splice(1, 0, {
+						'node': this._grid[index].node.parentNode.appendChild(node, this._grid[index].node)
+					});
+					index = 1;
+				}
+				else{
+					index = length - this.nbZones;
+					this._grid.splice(index, 0, {
+						'node': grid[index].node.parentNode.insertBefore(node, grid[index].node)
+					});
+				}
+			}
+			if(this.hasResizableColumns){
+				//Add a grip to resize columns
+				if((!isRightMode && this.nbZones != 1) ||
+						(!isRightMode && this.nbZones == 1 && !this.isLeftFixed) ||
+							(isRightMode && i < nbColumns-1) ||
+								(isRightMode && i == nbColumns-1 && this.isRightFixed)){
+					this._createGrip(index);
+				}
+			}
+			// register tnbZoneshe new area into the areaManager
+			m.registerByNode(grid[index].node);
+			this.nbZones++;
+		}
+		this._updateColumnsWidth(m);
+	},
+
+	_deleteColumn: function(/*Array*/indices){
+		// summary:
+		//		Remove some columns with indices passed as an array.
+		// indices:
+		//		Column index array
+		// tags:
+		//		private
+
+		//console.log("dojox.layout.GridContainer ::: _deleteColumn");
+		var child, grid, index,
+			nbDelZones = 0,
+			length = indices.length,
+			m = this._dragManager;
+		for(var i = 0; i < length; i++){
+			index = (this.mode == "right") ? indices[i] : indices[i] - nbDelZones;
+			grid = this._grid[index];
+
+			if(this.hasResizableColumns && grid.grip){
+				dojo.forEach(grid.gripHandler, function(handler){
+					dojo.disconnect(handler);
+				});
+				dojo.destroy(this.domNode.removeChild(grid.grip));
+				grid.grip = null;
+			}
+
+			m.unregister(grid.node);
+			dojo.destroy(this.gridNode.removeChild(grid.node));
+			this._grid.splice(index, 1);
+			this.nbZones--;
+			nbDelZones++;
+		}
+
+		// last grip
+		var lastGrid = this._grid[this.nbZones-1];
+		if(lastGrid.grip){
+			dojo.forEach(lastGrid.gripHandler, dojo.disconnect);
+			dojo.destroy(this.domNode.removeChild(lastGrid.grip));
+			lastGrid.grip = null;
+		}
+
+		this._updateColumnsWidth(m);
+	},
+
+	_updateColumnsWidth: function(/*Object*/ manager){
+		// summary:
+		//		Update the columns width.
+		// manager:
+		//		dojox.mdnd.AreaManager singleton
+		// tags:
+		//		private
+
+		//console.log("dojox.layout.GridContainer ::: _updateColumnsWidth");
+	 	this.inherited(arguments);
+		manager._dropMode.updateAreas(manager._areaList);
+	},
+
+	destroy: function(){
+		dojo.unsubscribe(this._dropHandler);
+		this.inherited(arguments);
+	}
+});
\ No newline at end of file
diff --git a/dojox/layout/GridContainerLite.js b/dojox/layout/GridContainerLite.js
new file mode 100644
index 0000000..d783878
--- /dev/null
+++ b/dojox/layout/GridContainerLite.js
@@ -0,0 +1,811 @@
+dojo.provide("dojox.layout.GridContainerLite");
+
+dojo.require("dijit._Templated");
+dojo.require("dijit.layout._LayoutWidget");
+
+dojo.require("dojox.mdnd.AreaManager");
+dojo.require("dojox.mdnd.DropIndicator");
+dojo.require("dojox.mdnd.dropMode.OverDropMode");
+dojo.require("dojox.mdnd.AutoScroll");
+
+dojo.declare(
+	"dojox.layout.GridContainerLite",
+	[dijit.layout._LayoutWidget, dijit._Templated],
+{
+	// summary:
+	// 		The GridContainerLite is a container of child elements that are placed in a kind of grid.
+	//
+	// description:
+	//		GridContainerLite displays the child elements by column
+	//		(ie: the children widths are fixed by the column width of the grid but
+	//              the children heights are free).
+	//		Each child is movable by drag and drop inside the GridContainer.
+	//		The position of other children is automatically calculated when a child is moved.
+	//
+	// example:
+	// 	|	<div dojoType="dojox.layout.GridContainerLite" nbZones="3" isAutoOrganized="true">
+	// 	|		<div dojoType="dijit.layout.ContentPane">Content Pane 1 : Drag Me !</div>
+	// 	|		<div dojoType="dijit.layout.ContentPane">Content Pane 2 : Drag Me !</div>
+	// 	|		<div dojoType="dijit.layout.ContentPane">Content Pane 3 : Drag Me !</div>
+	// 	|	</div>
+	//
+	// example:
+	// 	|	dojo.ready(function(){
+	// 	|		var cpane1 = new dijit.layout.ContentPane({
+	//	|			title:"cpane1", content: "Content Pane 1 : Drag Me !"
+	//	|		}),
+	// 	|		cpane2 = new dijit.layout.ContentPane({
+	//	|			title:"cpane2",
+	//	|			content: "Content Pane 2 : Drag Me !"
+	//	|		}),
+	// 	|		cpane3 = new dijit.layout.ContentPane({
+	//	|			title:"cpane3",
+	//	|			content: "Content Pane 3 : Drag Me !"
+	//	|		});
+	// 	|
+	// 	|		var widget = new dojox.layout.GridContainerLite({
+	// 	|			nbZones: 3,
+	// 	|			isAutoOrganized: true
+	// 	|		}, dojo.byId("idNode"));
+	// 	|		widget.addChild(cpane1, 0, 0);
+	// 	|		widget.addChild(cpane2, 1, 0);
+	// 	|		widget.addChild(cpane3, 2, 1);
+	// 	|		widget.startup();
+	// 	|	});
+	
+	//	autoRefresh: Boolean
+	//		Enable the refresh of registered areas on drag start. 
+	autoRefresh: true,
+
+
+	// templateString: String
+	//		template of gridContainer.
+	templateString: dojo.cache("dojox.layout", "resources/GridContainer.html"),
+
+	// dragHandleClass: Array :
+	//		CSS class enabling a drag handle on a child.
+	dragHandleClass: "dojoxDragHandle",
+
+	// nbZones: Integer
+	//		The number of dropped zones, by default 1.
+	nbZones: 1,
+
+	// doLayout: Boolean
+	//		If true, change the size of my currently displayed child to match my size.
+	doLayout: true,
+
+	// isAutoOrganized: Boolean
+	//		If true, widgets are organized automatically,
+	//		else the attribute colum of child will define the right column.
+	isAutoOrganized: true,
+
+	// acceptTypes: Array
+	//		The GridContainer will only accept the children that fit to the types.
+	acceptTypes: [],
+	
+	// colWidths: String
+	//		A comma separated list of column widths. If the column widths do not add up
+	//		to 100, the remaining columns split the rest of the width evenly
+	//		between them.
+	colWidths: "",
+
+	constructor: function(/*Object*/props, /*DOMNode*/node){
+		this.acceptTypes = (props || {}).acceptTypes || ["text"];
+		this._disabled = true;
+	},
+
+	postCreate: function(){
+		//console.log("dojox.layout.GridContainerLite ::: postCreate");
+		this.inherited(arguments);
+		this._grid = [];
+
+		this._createCells();
+
+		// need to resize dragged child when it's dropped.
+		this.subscribe("/dojox/mdnd/drop", "resizeChildAfterDrop");
+		this.subscribe("/dojox/mdnd/drag/start", "resizeChildAfterDragStart");
+
+		this._dragManager = dojox.mdnd.areaManager();
+		// console.info("autorefresh ::: ", this.autoRefresh);
+		this._dragManager.autoRefresh = this.autoRefresh;
+
+		//	Add specific dragHandleClass to the manager.
+		this._dragManager.dragHandleClass = this.dragHandleClass;
+
+		if(this.doLayout){
+			this._border = {
+				'h':(dojo.isIE) ? dojo._getBorderExtents(this.gridContainerTable).h : 0,
+				'w': (dojo.isIE == 6) ? 1 : 0
+			}
+		}
+		else{
+			dojo.style(this.domNode, "overflowY", "hidden");
+			dojo.style(this.gridContainerTable, "height", "auto");
+		}
+		// Call postCreate of dijit.layout._LayoutWidget.
+		this.inherited(arguments);
+
+	},
+
+	startup: function(){
+		//console.log("dojox.layout.GridContainerLite ::: startup");
+		if(this._started){ return; }
+
+		if(this.isAutoOrganized){
+			this._organizeChildren();
+		}
+		else{
+			this._organizeChildrenManually();
+		}
+
+		// Need to call getChildren because getChildren return null
+		// The children are not direct children because of _organizeChildren method
+		dojo.forEach(this.getChildren(), function(child){ child.startup(); });
+
+		// Need to enable the Drag And Drop only if the GridContainer is visible.
+		if(this._isShown()){
+			this.enableDnd();
+		}
+		this.inherited(arguments);
+	},
+
+	resizeChildAfterDrop: function(/*Node*/node, /*Object*/targetArea, /*Integer*/indexChild){
+		// summary:
+		//		Resize the GridContainerLite inner table and the dropped widget.
+		// description:
+		//		These components are resized only if the targetArea.node is a
+		//		child of this instance of gridContainerLite.
+		//		To be resized, the dropped node must have also a method resize.
+		// node:
+		//		domNode of dropped widget.
+		// targetArea:
+		//		AreaManager Object containing information of targetArea
+		// indexChild:
+		// 		Index where the dropped widget has been placed
+		// returns:
+		//		True if resized.
+
+		//console.log("dojox.layout.GridContainerLite ::: resizeChildAfterDrop");
+		if(this._disabled){
+			return false;
+		}
+		if(dijit.getEnclosingWidget(targetArea.node) == this){
+			var widget = dijit.byNode(node);
+			if(widget.resize && dojo.isFunction(widget.resize)){
+				widget.resize();
+			}
+			if(this.doLayout){
+				var domNodeHeight = this._contentBox.h,
+					divHeight = dojo.contentBox(this.gridContainerDiv).h;
+				if(divHeight >= domNodeHeight){
+					dojo.style(this.gridContainerTable, "height",
+							(domNodeHeight - this._border.h) + "px");
+				}
+			}
+			return true;
+		}
+		return false;
+	},
+
+	resizeChildAfterDragStart: function(/*Node*/node, /*Object*/sourceArea, /*Integer*/indexChild){
+		// summary:
+		//		Resize the GridContainerLite inner table only if the drag source
+		//		is a child of this gridContainer.
+		// node:
+		//		domNode of dragged widget.
+		// sourceArea:
+		//		AreaManager Object containing information of sourceArea
+		// indexChild:
+		// 		Index where the dragged widget has been placed
+
+		//console.log("dojox.layout.GridContainerLite ::: resizeChildAfterDragStart");
+		if(this._disabled){
+			return false;
+		}
+		if(dijit.getEnclosingWidget(sourceArea.node) == this){
+			this._draggedNode = node;
+			if(this.doLayout){
+				dojo.marginBox(this.gridContainerTable, {
+					'h': dojo.contentBox(this.gridContainerDiv).h - this._border.h
+				});
+			}
+			return true;
+		}
+		return false;
+	},
+
+	getChildren: function(){
+		// summary:
+		//		A specific method which returns children after they were placed in zones.
+		// returns:
+		//		An array containing all children (widgets).
+		// tags:
+		//		protected
+
+		//console.log("dojox.layout.GridContainerLite ::: _getChildren");
+		var children = [];
+		dojo.forEach(this._grid, function(dropZone){
+			children = children.concat(dojo.query("> [widgetId]", dropZone.node).map(dijit.byNode));
+		});
+		return children;	// Array
+	},
+
+	_isShown: function(){
+		// summary:
+		//		Check if the domNode is visible or not.
+		// returns:
+		//		true if the content is currently shown
+		// tags:
+		//		protected
+
+		//console.log("dojox.layout.GridContainerLite ::: _isShown");
+		if("open" in this){		// for TitlePane, etc.
+			return this.open;		// Boolean
+		}
+		else{
+			var node = this.domNode;
+			return (node.style.display != 'none') && (node.style.visibility != 'hidden') && !dojo.hasClass(node, "dijitHidden"); // Boolean
+		}
+	},
+
+	layout: function(){
+		// summary:
+		//		Resize of each child
+
+		//console.log("dojox.layout.GridContainerLite ::: layout");
+		if(this.doLayout){
+			var contentBox = this._contentBox;
+			dojo.marginBox(this.gridContainerTable, {
+				'h': contentBox.h - this._border.h
+			});
+			dojo.contentBox(this.domNode, {
+				'w': contentBox.w - this._border.w
+			});
+		}
+		dojo.forEach(this.getChildren(), function(widget){
+			if(widget.resize && dojo.isFunction(widget.resize)){
+				widget.resize();
+			}
+		});
+	},
+
+	onShow: function(){
+		// summary:
+		//		Enabled the Drag And Drop if it's necessary.
+
+		//console.log("dojox.layout.GridContainerLite ::: onShow");
+		if(this._disabled){
+			this.enableDnd();
+		}
+	},
+
+	onHide: function(){
+		// summary:
+		//		Disabled the Drag And Drop if it's necessary.
+
+		//console.log("dojox.layout.GridContainerLite ::: onHide");
+		if(!this._disabled){
+			this.disableDnd();
+		}
+	},
+
+	_createCells: function(){
+		// summary:
+		//		Create the columns of the GridContainer.
+		// tags:
+		//		protected
+
+		//console.log("dojox.layout.GridContainerLite ::: _createCells");
+		if(this.nbZones === 0){ this.nbZones = 1; }
+		var accept = this.acceptTypes.join(","),
+			i = 0;
+			
+		var origWidths = this.colWidths || [];
+		var widths = [];
+		var colWidth;
+		var widthSum = 0;
+		
+		// Calculate the widths of each column.
+		for(i = 0; i < this.nbZones; i++){
+			if(widths.length < origWidths.length){
+				widthSum += origWidths[i];
+				widths.push(origWidths[i]);
+			}else{
+				if(!colWidth){
+					colWidth = (100 - widthSum)/(this.nbZones - i);
+				}
+				widths.push(colWidth);
+			}
+		}
+
+		i = 0;
+		while(i < this.nbZones){
+			// Add the parameter accept in each zone used by AreaManager
+			// (see method dojox.mdnd.AreaManager:registerByNode)			
+			this._grid.push({
+				'node': dojo.create("td", {
+					'class': "gridContainerZone",
+					'accept': accept,
+					'id': this.id + "_dz" + i,
+					'style': {
+						'width': widths[i] + "%"
+					}
+				}, this.gridNode)
+			});
+			i++;
+		}
+	},
+
+	enableDnd: function(){
+		// summary:
+		//		Enable the Drag And Drop for children of GridContainer.
+
+		//console.log("dojox.layout.GridContainerLite ::: enableDnd");
+		var m = this._dragManager;
+		dojo.forEach(this._grid, function(dropZone){
+			m.registerByNode(dropZone.node);
+		});
+		m._dropMode.updateAreas(m._areaList);
+		this._disabled = false;
+	},
+
+	disableDnd: function(){
+		// summary:
+		//		Disable the Drag And Drop for children of GridContainer.
+
+		//console.log("dojox.layout.GridContainerLite ::: disableDnd");
+		var m = this._dragManager;
+		dojo.forEach(this._grid, function(dropZone){
+			m.unregister(dropZone.node);
+		});
+		m._dropMode.updateAreas(m._areaList);
+		this._disabled = true;
+	},
+
+	_organizeChildren: function(){
+		// summary:
+		//		List all zones and insert child into columns.
+
+		//console.log("dojox.layout.GridContainerLite ::: _organizeChildren");
+		var children = dojox.layout.GridContainerLite.superclass.getChildren.call(this);
+		var numZones = this.nbZones,
+			numPerZone = Math.floor(children.length / numZones),
+			mod = children.length % numZones,
+			i = 0;
+//		console.log('numPerZone', numPerZone, ':: mod', mod);
+		for(var z = 0; z < numZones; z++){
+			for(var r = 0; r < numPerZone; r++){
+				this._insertChild(children[i], z);
+				i++;
+			}
+			if(mod > 0){
+				try{
+					this._insertChild(children[i], z);
+					i++;
+				}
+				catch(e){
+					console.error("Unable to insert child in GridContainer", e);
+				}
+				mod--;
+			}
+			else if(numPerZone === 0){
+				break;	// Optimization
+			}
+		}
+	},
+
+	_organizeChildrenManually: function (){
+		// summary:
+		//		Organize children by column property of widget.
+
+		//console.log("dojox.layout.GridContainerLite ::: _organizeChildrenManually");
+		var children = dojox.layout.GridContainerLite.superclass.getChildren.call(this),
+			length = children.length,
+			child;
+		for(var i = 0; i < length; i++){
+			child = children[i];
+			try{
+				this._insertChild(child, child.column - 1);
+			}
+			catch(e){
+				console.error("Unable to insert child in GridContainer", e);
+			}
+		}
+	},
+
+	_insertChild: function(/*Widget*/child, /*Integer*/column, /*Integer?*/p){
+		// summary:
+		//		Insert a child in a specific column of the GridContainer widget.
+		// column:
+		//		Column number
+		// p:
+		//		Place in the zone (0 - first)
+		// returns:
+		//		The widget inserted
+
+		//console.log("dojox.layout.GridContainerLite ::: _insertChild", child, column, p);
+		var zone = this._grid[column].node,
+			length = zone.childNodes.length;
+		if(typeof(p) == undefined || p > length){
+			p = length;
+		}
+		if(this._disabled){
+			dojo.place(child.domNode, zone, p);
+			dojo.attr(child.domNode, "tabIndex", "0");
+		}
+		else{
+			if(!child.dragRestriction){
+				this._dragManager.addDragItem(zone, child.domNode, p, true);
+			}
+			else{
+				dojo.place(child.domNode, zone, p);
+				dojo.attr(child.domNode, "tabIndex", "0");
+			}
+		}
+		return child; // Widget
+	},
+
+	removeChild: function(/*Widget*/ widget){
+		//console.log("dojox.layout.GridContainerLite ::: removeChild");
+		if(this._disabled){
+			this.inherited(arguments);
+		}
+		else{
+			this._dragManager.removeDragItem(widget.domNode.parentNode, widget.domNode);
+		}
+	},
+
+	addService: function(/*Object*/child, /*Integer?*/column, /*Integer?*/p){
+		//console.log("dojox.layout.GridContainerLite ::: addService");
+		dojo.deprecated("addService is deprecated.", "Please use  instead.", "Future");
+		this.addChild(child, column, p);
+	},
+
+	addChild: function(/*Object*/child, /*Integer?*/column, /*Integer?*/p){
+		// summary:
+		//		Add a child in a specific column of the GridContainer widget.
+		// child:
+		//		widget to insert
+		// column:
+		//		column number
+		// p:
+		//		place in the zone (first = 0)
+		// returns:
+		//		The widget inserted
+
+		//console.log("dojox.layout.GridContainerLite ::: addChild");
+		child.domNode.id = child.id;
+		dojox.layout.GridContainerLite.superclass.addChild.call(this, child, 0);
+		if(column < 0 || column == undefined){ column = 0; }
+		if(p <= 0){ p = 0; }
+		try{
+			return this._insertChild(child, column, p);
+		}
+		catch(e){
+			console.error("Unable to insert child in GridContainer", e);
+		}
+		return null; 	// Widget
+	},
+	
+	_setColWidthsAttr: function(value){
+		this.colWidths = dojo.isString(value) ? value.split(",") : (dojo.isArray(value) ? value : [value]);
+		
+		if(this._started){ 
+			this._updateColumnsWidth();
+		}
+	},
+	
+	_updateColumnsWidth: function(/*Object*/ manager){
+		// summary:
+		//		Update the columns width.
+		// manager:
+		//		dojox.mdnd.AreaManager singleton
+		// tags:
+		//		private
+
+		//console.log("dojox.layout.GridContainer ::: _updateColumnsWidth");
+		var length = this._grid.length;
+
+		var origWidths = this.colWidths || [];
+		var widths = [];
+		var colWidth;
+		var widthSum = 0;
+		var i;
+
+		// Calculate the widths of each column.
+		for(i = 0; i < length; i++){
+			if(widths.length < origWidths.length){
+				widthSum += origWidths[i] * 1;
+				widths.push(origWidths[i]);
+			}else{
+				if(!colWidth){
+					colWidth = (100 - widthSum)/(this.nbZones - i);
+					
+					// If the numbers don't work out, make the remaining columns
+					// an even width and let the code below average
+					// out the differences.
+					if(colWidth < 0){
+						colWidth = 100 / this.nbZones;
+					}
+				}
+				widths.push(colWidth);
+				widthSum += colWidth * 1;
+			}
+		}
+
+		// If the numbers are wrong, divide them all so they add up to 100
+		if(widthSum > 100){
+			var divisor = 100 / widthSum;
+			for(i = 0; i < widths.length; i++){
+				widths[i] *= divisor;
+			}
+		}
+
+		// Set the widths of each node
+		for(i = 0; i < length; i++){
+			this._grid[i].node.style.width = widths[i] + "%";
+		}
+	},
+
+	_selectFocus: function(/*Event*/event){
+		// summary:
+		//		Enable keyboard accessibility into the GridContainer.
+		// description:
+		//		Possibility to move focus into the GridContainer (TAB, LEFT ARROW, RIGHT ARROW, UP ARROW, DOWN ARROW).
+		//		Possibility to move GridContainer's children (Drag and Drop) with keyboard. (SHIFT +  ARROW).
+		//		If the type of widget is not draggable, a popup is displayed.
+
+		//console.log("dojox.layout.GridContainerLite ::: _selectFocus");
+		if(this._disabled){ return; }
+		var key = event.keyCode,
+			k = dojo.keys,
+			zone = null,
+			focus = dijit.getFocus(),
+			focusNode = focus.node,
+			m = this._dragManager,
+			found,
+			i,
+			j,
+			r,
+			children,
+			area,
+			widget;
+		if(focusNode == this.containerNode){
+			area = this.gridNode.childNodes;
+			switch(key){
+				case k.DOWN_ARROW:
+				case k.RIGHT_ARROW:
+					found = false;
+					for(i = 0; i < area.length; i++){
+						children = area[i].childNodes;
+						for(j = 0; j < children.length; j++){
+							zone = children[j];
+							if(zone != null && zone.style.display != "none"){
+								dijit.focus(zone);
+								dojo.stopEvent(event);
+								found = true;
+								break;
+							}
+						}
+						if(found){ break };
+					}
+				break;
+				case k.UP_ARROW:
+				case k.LEFT_ARROW:
+					area = this.gridNode.childNodes;
+					found = false;
+					for(i = area.length-1; i >= 0 ; i--){
+						children = area[i].childNodes;
+						for(j = children.length; j >= 0; j--){
+							zone = children[j];
+							if(zone != null && zone.style.display != "none"){
+								dijit.focus(zone);
+								dojo.stopEvent(event);
+								found = true;
+								break;
+							}
+						}
+						if(found){ break };
+					}
+				break;
+			}
+		}
+		else{
+			if(focusNode.parentNode.parentNode == this.gridNode){
+				var child = (key == k.UP_ARROW || key == k.LEFT_ARROW) ? "lastChild" : "firstChild";
+				var pos = (key == k.UP_ARROW || key == k.LEFT_ARROW) ? "previousSibling" : "nextSibling";
+				switch(key){
+					case k.UP_ARROW:
+					case k.DOWN_ARROW:
+						dojo.stopEvent(event);
+						found = false;
+						var focusTemp = focusNode;
+						while(!found){
+							children = focusTemp.parentNode.childNodes;
+							var num = 0;
+							for(i = 0; i < children.length; i++){
+								if(children[i].style.display != "none"){ num++ };
+								if(num > 1){ break; }
+							}
+							if(num == 1){ return; }
+							if(focusTemp[pos] == null){
+								zone = focusTemp.parentNode[child];
+							}
+							else{
+								zone = focusTemp[pos];
+							}
+							if(zone.style.display === "none"){
+								focusTemp = zone;
+							}
+							else{
+								found = true;
+							}
+						}
+						if(event.shiftKey){
+							var parent = focusNode.parentNode;
+							for(i = 0; i < this.gridNode.childNodes.length; i++){
+								if(parent == this.gridNode.childNodes[i]){
+									break;
+								}
+							}
+							children = this.gridNode.childNodes[i].childNodes;
+							for(j = 0; j < children.length; j++){
+								if(zone == children[j]){
+									break;
+								}
+							}
+							if(dojo.isMoz || dojo.isWebKit){ i-- };
+
+							widget = dijit.byNode(focusNode);
+							if(!widget.dragRestriction){
+								r = m.removeDragItem(parent, focusNode);
+								this.addChild(widget, i, j);
+								dojo.attr(focusNode, "tabIndex", "0");
+								dijit.focus(focusNode);
+							}
+							else{
+								dojo.publish("/dojox/layout/gridContainer/moveRestriction", [this]);
+							}
+						}
+						else{
+							dijit.focus(zone);
+						}
+					break;
+					case k.RIGHT_ARROW:
+					case k.LEFT_ARROW:
+						dojo.stopEvent(event);
+						if(event.shiftKey){
+							var z = 0;
+							if(focusNode.parentNode[pos] == null){
+								if(dojo.isIE && key == k.LEFT_ARROW){
+									z = this.gridNode.childNodes.length-1;
+								}
+							}
+							else if(focusNode.parentNode[pos].nodeType == 3){
+								z = this.gridNode.childNodes.length - 2;
+							}
+							else{
+								for(i = 0; i < this.gridNode.childNodes.length; i++){
+									if(focusNode.parentNode[pos] == this.gridNode.childNodes[i]){
+										break;
+									}
+									z++;
+								}
+								if(dojo.isMoz || dojo.isWebKit){ z-- };
+							}
+							widget = dijit.byNode(focusNode);
+							var _dndType = focusNode.getAttribute("dndtype");
+							if(_dndType == null){
+								//check if it's a dijit object
+								if(widget && widget.dndType){
+									_dndType = widget.dndType.split(/\s*,\s*/);
+								}
+								else{
+									_dndType = ["text"];
+								}
+							}
+							else{
+								_dndType = _dndType.split(/\s*,\s*/);
+							}
+							var accept = false;
+							for(i = 0; i < this.acceptTypes.length; i++){
+								for(j = 0; j < _dndType.length; j++){
+									if(_dndType[j] == this.acceptTypes[i]){
+										accept = true;
+										break;
+									}
+								}
+							}
+							if(accept && !widget.dragRestriction){
+								var parentSource = focusNode.parentNode,
+									place = 0;
+								if(k.LEFT_ARROW == key){
+									var t = z;
+									if(dojo.isMoz || dojo.isWebKit){ t = z + 1 };
+									place = this.gridNode.childNodes[t].childNodes.length;
+								}
+								// delete of manager :
+								r = m.removeDragItem(parentSource, focusNode);
+								this.addChild(widget, z, place);
+								dojo.attr(r, "tabIndex", "0");
+								dijit.focus(r);
+							}
+							else{
+								dojo.publish("/dojox/layout/gridContainer/moveRestriction", [this]);
+							}
+						}
+						else{
+							var node = focusNode.parentNode;
+							while(zone === null){
+								if(node[pos] !== null && node[pos].nodeType !== 3){
+									node = node[pos];
+								}
+								else{
+									if(pos === "previousSibling"){
+										node = node.parentNode.childNodes[node.parentNode.childNodes.length-1];
+									}
+									else{
+										node = (dojo.isIE)? node.parentNode.childNodes[0]: node.parentNode.childNodes[1];
+									}
+								}
+								zone = node[child];
+								if(zone && zone.style.display == "none"){
+									// check that all elements are not hidden
+									children = zone.parentNode.childNodes;
+									var childToSelect = null;
+									if(pos == "previousSibling"){
+										for(i = children.length-1; i >= 0; i--){
+											if(children[i].style.display != "none"){
+												childToSelect = children[i];
+												break;
+											}
+										}
+									}
+									else{
+										for(i = 0; i < children.length; i++){
+											if(children[i].style.display != "none"){
+												childToSelect = children[i];
+												break;
+											}
+										}
+									}
+									if(!childToSelect){
+										focusNode = zone;
+										node = focusNode.parentNode;
+										zone = null;
+									}
+									else{
+										zone = childToSelect;
+									}
+								}
+							}
+							dijit.focus(zone);
+						}
+					break;
+				}
+			}
+		}
+	},
+
+	destroy: function(){
+		//console.log("dojox.layout.GridContainerLite ::: destroy");
+		var m = this._dragManager;
+		dojo.forEach(this._grid, function(dropZone){
+			m.unregister(dropZone.node);
+		});
+		this.inherited(arguments);
+	}
+});
+
+dojo.extend(dijit._Widget, {
+
+	// column: String
+	//		Column of the grid to place the widget.
+	//		Defined only if dojo.require("dojox.layout.GridContainerLite") is done.
+	column : "1",
+
+	// dragRestriction: Boolean
+	//		If true, the widget can not be draggable.
+	//		Defined only if dojo.require("dojox.layout.GridContainerLite") is done.
+	dragRestriction : false
+});
\ No newline at end of file
diff --git a/dojox/layout/README b/dojox/layout/README
index 14d3211..225dce1 100644
--- a/dojox/layout/README
+++ b/dojox/layout/README
@@ -27,7 +27,7 @@ Credits
 [DragPane]	Peter Higgins (dante)
 [ExpandoPane] Peter Higgins (dante)
 [FloatingPane] Peter Higgins (dante)
-[GridContainer] Juff Cunat (jfcunat), Peter Higgins (dante)
+[GridContainer/GridContainerLite] Erwan Morvillez (emorvillez), Jeff Cunat (jfcunat), Guillaume Mouricou (gmouricou), Peter Higgins (dante)
 [RadioGroup/Fade/Slide] Peter Higgins (dante) 
 [ResizeHandle] Peter Higgins (dante)
 [RotatorContainer] Chris Barber (cb1)
diff --git a/dojox/layout/RadioGroup.js b/dojox/layout/RadioGroup.js
index ab05ae5..28bb986 100644
--- a/dojox/layout/RadioGroup.js
+++ b/dojox/layout/RadioGroup.js
@@ -1,139 +1,297 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.RadioGroup"]){
-dojo._hasResource["dojox.layout.RadioGroup"]=true;
 dojo.provide("dojox.layout.RadioGroup");
 dojo.experimental("dojox.layout.RadioGroup");
+//
+//	dojox.layout.RadioGroup - an experimental (probably poorly named) Layout widget extending StackContainer
+//	that accepts ContentPanes as children, and applies aesthetically pleasing responsive transition animations
+//	attached to :hover of the Buttons created.
+//
+//	FIXME: take the Buttons out of the root template, and allow layoutAlign or similar attrib to use a different
+//	template, or build the template dynamically? 
+//
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Contained");
 dojo.require("dijit.layout.StackContainer");
-dojo.require("dojo.fx.easing");
-dojo.declare("dojox.layout.RadioGroup",[dijit.layout.StackContainer,dijit._Templated],{duration:750,hasButtons:false,buttonClass:"dojox.layout._RadioButton",templateString:"<div class=\"dojoxRadioGroup\">"+" \t<div dojoAttachPoint=\"buttonHolder\" style=\"display:none;\">"+"\t\t<table class=\"dojoxRadioButtons\"><tbody><tr class=\"dojoxRadioButtonRow\" dojoAttachPoint=\"buttonNode\"></tr></tbody></table>"+"\t</div>"+"\t<div class=\"dojoxRadioView\" dojoAttachPoint=\"containerNode\"></div [...]
-this.inherited(arguments);
-this._children=this.getChildren();
-this._buttons=this._children.length;
-this._size=dojo.coords(this.containerNode);
-if(this.hasButtons){
-dojo.style(this.buttonHolder,"display","block");
-}
-},_setupChild:function(_1){
-if(this.hasButtons){
-dojo.style(_1.domNode,"position","absolute");
-var _2=this.buttonNode.appendChild(dojo.create("td"));
-var n=dojo.create("div",null,_2),_3=dojo.getObject(this.buttonClass),_4=new _3({label:_1.title,page:_1},n);
-dojo.mixin(_1,{_radioButton:_4});
-_4.startup();
-}
-_1.domNode.style.display="none";
-},removeChild:function(_5){
-if(this.hasButtons&&_5._radioButton){
-_5._radioButton.destroy();
-delete _5._radioButton;
-}
-this.inherited(arguments);
-},_transition:function(_6,_7){
-this._showChild(_6);
-if(_7){
-this._hideChild(_7);
-}
-if(this.doLayout&&_6.resize){
-_6.resize(this._containerContentBox||this._contentBox);
-}
-},_showChild:function(_8){
-var _9=this.getChildren();
-_8.isFirstChild=(_8==_9[0]);
-_8.isLastChild=(_8==_9[_9.length-1]);
-_8.selected=true;
-_8.domNode.style.display="";
-if(_8._onShow){
-_8._onShow();
-}else{
-if(_8.onShow){
-_8.onShow();
-}
-}
-},_hideChild:function(_a){
-_a.selected=false;
-_a.domNode.style.display="none";
-if(_a.onHide){
-_a.onHide();
-}
-}});
-dojo.declare("dojox.layout.RadioGroupFade",dojox.layout.RadioGroup,{_hideChild:function(_b){
-dojo.fadeOut({node:_b.domNode,duration:this.duration,onEnd:dojo.hitch(this,"inherited",arguments,arguments)}).play();
-},_showChild:function(_c){
-this.inherited(arguments);
-dojo.style(_c.domNode,"opacity",0);
-dojo.fadeIn({node:_c.domNode,duration:this.duration}).play();
-}});
-dojo.declare("dojox.layout.RadioGroupSlide",dojox.layout.RadioGroup,{easing:"dojo.fx.easing.backOut",zTop:99,constructor:function(){
-if(dojo.isString(this.easing)){
-this.easing=dojo.getObject(this.easing);
-}
-},_positionChild:function(_d){
-if(!this._size){
-return;
-}
-var rA=true,rB=true;
-switch(_d.slideFrom){
-case "bottom":
-rB=!rB;
-break;
-case "right":
-rA=!rA;
-rB=!rB;
-break;
-case "top":
-break;
-case "left":
-rA=!rA;
-break;
-default:
-rA=Math.round(Math.random());
-rB=Math.round(Math.random());
-break;
-}
-var _e=rA?"top":"left",_f=(rB?"-":"")+(this._size[rA?"h":"w"]+20)+"px";
-dojo.style(_d.domNode,_e,_f);
-},_showChild:function(_10){
-var _11=this.getChildren();
-_10.isFirstChild=(_10==_11[0]);
-_10.isLastChild=(_10==_11[_11.length-1]);
-_10.selected=true;
-dojo.style(_10.domNode,{zIndex:this.zTop,display:""});
-if(this._anim&&this._anim.status()=="playing"){
-this._anim.gotoPercent(100,true);
-}
-this._anim=dojo.animateProperty({node:_10.domNode,properties:{left:0,top:0},duration:this.duration,easing:this.easing,onEnd:dojo.hitch(_10,function(){
-if(this.onShow){
-this.onShow();
-}
-if(this._onShow){
-this._onShow();
-}
-}),beforeBegin:dojo.hitch(this,"_positionChild",_10)});
-this._anim.play();
-},_hideChild:function(_12){
-_12.selected=false;
-_12.domNode.style.zIndex=this.zTop-1;
-if(_12.onHide){
-_12.onHide();
-}
-}});
-dojo.declare("dojox.layout._RadioButton",[dijit._Widget,dijit._Templated,dijit._Contained],{label:"",page:null,templateString:"<div dojoAttachPoint=\"focusNode\" class=\"dojoxRadioButton\"><span dojoAttachPoint=\"titleNode\" class=\"dojoxRadioButtonLabel\">${label}</span></div>",startup:function(){
-this.connect(this.domNode,"onmouseenter","_onMouse");
-},_onMouse:function(e){
-this.getParent().selectChild(this.page);
-this._clearSelected();
-dojo.addClass(this.domNode,"dojoxRadioButtonSelected");
-},_clearSelected:function(){
-dojo.query(".dojoxRadioButtonSelected",this.domNode.parentNode.parentNode).removeClass("dojoxRadioButtonSelected");
-}});
-dojo.extend(dijit._Widget,{slideFrom:"random"});
-}
+dojo.require("dojo.fx.easing"); 
+
+dojo.declare("dojox.layout.RadioGroup",
+	[dijit.layout.StackContainer,dijit._Templated],
+	{
+	// summary: A Container that turns its Layout Children into a single Pane and transitions between states
+	//	onHover of the button
+	//
+
+	// duration: Integer
+	//	used for Fade and Slide RadioGroup's, the duration to run the transition animation. does not affect anything
+	//	in default RadioGroup
+	duration: 750,
+
+	// hasButtons: Boolean
+	//	toggles internal button making on or off
+	hasButtons: false,
+
+	// buttonClass: String
+	//		The full declared className of the Button widget to use for hasButtons
+	buttonClass: "dojox.layout._RadioButton",
+	
+	// templateString: String
+	//	the template for our container
+	templateString: '<div class="dojoxRadioGroup">'
+			+' 	<div dojoAttachPoint="buttonHolder" style="display:none;">'
+			+'		<table class="dojoxRadioButtons"><tbody><tr class="dojoxRadioButtonRow" dojoAttachPoint="buttonNode"></tr></tbody></table>'
+			+'	</div>'
+			+'	<div class="dojoxRadioView" dojoAttachPoint="containerNode"></div>'
+			+'</div>',
+
+	startup: function(){
+		// summary: scan the container for children, and make "tab buttons" for them
+		this.inherited(arguments);
+		this._children = this.getChildren();
+		this._buttons = this._children.length;
+		this._size = dojo.coords(this.containerNode);
+		if(this.hasButtons){
+			dojo.style(this.buttonHolder,"display","block");
+		}
+	},
+
+	_setupChild: function(/* dijit._Widget */child){
+		// summary: Creates a hover button for a child node of the RadioGroup
+		if(this.hasButtons){
+			
+			dojo.style(child.domNode,"position","absolute");
+			
+			var tmp = this.buttonNode.appendChild(dojo.create('td'));
+			var n = dojo.create("div", null, tmp),
+				_Button = dojo.getObject(this.buttonClass),
+				tmpw = new _Button({
+					label: child.title,
+					page: child
+				}, n)
+			;
+			
+			dojo.mixin(child, { _radioButton: tmpw });
+			tmpw.startup();
+		}
+		child.domNode.style.display = "none";
+	},
+	
+	removeChild: function(child){
+		if(this.hasButtons && child._radioButton){
+			child._radioButton.destroy();
+			delete child._radioButton;
+		}
+		this.inherited(arguments);
+	},
+	
+	// FIXME: shouldn't have to rewriting these, need to take styling out of _showChild and _hideChild
+	//		and use classes on the domNode in _transition or something similar (in StackContainer)
+	_transition: function(/*dijit._Widget*/ newWidget, /*dijit._Widget*/ oldWidget){
+		// summary: called when StackContainer receives a selectChild call, used to transition the panes.
+		this._showChild(newWidget);
+		if(oldWidget){
+			this._hideChild(oldWidget);
+		}
+		// Size the new widget, in case this is the first time it's being shown,
+		// or I have been resized since the last time it was shown.
+		// page must be visible for resizing to work
+		if(this.doLayout && newWidget.resize){
+			newWidget.resize(this._containerContentBox || this._contentBox);
+		}
+	},
+
+	_showChild: function(/*dijit._Widget*/ page){
+		// summary: show the selected child widget
+		var children = this.getChildren();
+		page.isFirstChild = (page == children[0]);
+		page.isLastChild = (page == children[children.length-1]);
+		page.selected = true;
+
+		page.domNode.style.display="";
+
+		if(page._onShow){
+			page._onShow(); // trigger load in ContentPane
+		}else if(page.onShow){
+			page.onShow();
+		}
+	},
+
+	_hideChild: function(/*dijit._Widget*/ page){
+		// summary: hide the specified child widget
+		page.selected = false;
+		page.domNode.style.display="none";
+		if(page.onHide){
+			page.onHide();
+		}
+	}
+
+});
+
+dojo.declare("dojox.layout.RadioGroupFade",
+	dojox.layout.RadioGroup,
+	{
+	// summary: An extension on a stock RadioGroup, that fades the panes.
+
+	_hideChild: function(page){
+		// summary: hide the specified child widget
+		dojo.fadeOut({
+			node:page.domNode,
+			duration:this.duration,
+			onEnd: dojo.hitch(this,"inherited", arguments, arguments)
+		}).play();
+	},
+
+	_showChild: function(page){
+		// summary: show the specified child widget
+		this.inherited(arguments);
+		dojo.style(page.domNode, "opacity", 0);
+		dojo.fadeIn({
+			node:page.domNode,
+			duration:this.duration
+		}).play();
+	}
+});
+
+dojo.declare("dojox.layout.RadioGroupSlide",
+	dojox.layout.RadioGroup,
+	{
+	// summary: A Sliding Radio Group
+	// description: 
+	//		An extension on a stock RadioGroup widget, sliding the pane
+	//		into view from being hidden. The entry direction is randomized 
+	//		on each view
+	//		
+
+	// easing: Function
+	//	A hook to override the default easing of the pane slides.
+	easing: "dojo.fx.easing.backOut",
+
+	// zTop: Integer
+	//		A z-index to apply to the incoming pane
+	zTop: 99,
+	
+	constructor: function(){
+		if(dojo.isString(this.easing)){
+			this.easing = dojo.getObject(this.easing);
+		}
+	},
+	
+	_positionChild: function(page){
+		// summary: set the child out of view immediately after being hidden
+		
+		if(!this._size){ return; } // FIXME: is there a real "size" floating around always?
+		
+		// there should be a contest: obfuscate this function as best you can. 
+		var rA = true, rB = true;
+		switch(page.slideFrom){
+			case "bottom" : rB = !rB; break;
+			case "right" : 	rA = !rA; rB = !rB; break;
+			case "top" : 	break;
+			case "left" : 	rA = !rA; break;
+			default:
+				rA = Math.round(Math.random());
+				rB = Math.round(Math.random());
+				break;
+		}
+		var prop = rA ? "top" : "left",
+			val = (rB ? "-" : "") + (this._size[rA ? "h" : "w" ] + 20) + "px";	
+			
+		dojo.style(page.domNode, prop, val);
+
+	},
+
+	_showChild: function(page){
+		// summary: Slide in the selected child widget
+		
+		var children = this.getChildren();
+		page.isFirstChild = (page == children[0]);
+		page.isLastChild = (page == children[children.length-1]);
+		page.selected = true;
+
+		dojo.style(page.domNode,{
+			zIndex: this.zTop, display:"" 
+		})
+
+		if(this._anim && this._anim.status()=="playing"){
+			this._anim.gotoPercent(100,true);
+		}
+		
+		this._anim = dojo.animateProperty({
+			node:page.domNode,
+			properties: {
+				left: 0,
+				top: 0
+			},
+			duration: this.duration,
+			easing: this.easing,
+			onEnd: dojo.hitch(page, function(){
+				if(this.onShow){ this.onShow(); }
+				if(this._onShow){ this._onShow(); }
+			}),
+			beforeBegin: dojo.hitch(this, "_positionChild", page)
+		});
+		this._anim.play();
+	},
+
+	_hideChild: function(page){
+		// summary: reset the position of the hidden pane out of sight
+
+		page.selected = false;
+		page.domNode.style.zIndex = this.zTop - 1;
+		if(page.onHide){
+			page.onHide();
+		}
+
+	}
+	
+});
+
+dojo.declare("dojox.layout._RadioButton",
+	[dijit._Widget,dijit._Templated,dijit._Contained],
+	{
+	// summary: The Buttons for a RadioGroup
+	//
+	// description: A private widget used to manipulate the StackContainer (RadioGroup*). Don't create directly. 
+	//	
+	
+	// label: String
+	//	the Text Label of the button
+	label: "",
+
+	// domNode to tell parent to select
+	page: null,
+
+	templateString: '<div dojoAttachPoint="focusNode" class="dojoxRadioButton"><span dojoAttachPoint="titleNode" class="dojoxRadioButtonLabel">${label}</span></div>',
+	
+	startup: function(){
+		// summary: start listening to mouseOver
+		this.connect(this.domNode, "onmouseenter", "_onMouse");
+	},
+	
+	_onMouse: function(/* Event */e){
+		// summary: set the selected child on hover, and set our hover state class
+		this.getParent().selectChild(this.page);
+		this._clearSelected();
+		dojo.addClass(this.domNode,"dojoxRadioButtonSelected");
+
+	},
+
+	_clearSelected: function(){
+		// summary: remove hover state class from sibling Buttons. This is easier (and more reliable)
+		//	than setting up an additional connection to onMouseOut
+		
+		// FIXME: this relies on the template being [div][span]node[/span][/div]
+		dojo.query(".dojoxRadioButtonSelected", this.domNode.parentNode.parentNode)
+			.removeClass("dojoxRadioButtonSelected")
+		;
+	}
+	
+});
+
+dojo.extend(dijit._Widget,{
+	// slideFrom: String
+	//		A parameter needed by RadioGroupSlide only. An optional paramter to force
+	//		the ContentPane to slide in from a set direction. Defaults
+	//		to "random", or specify one of "top", "left", "right", "bottom"
+	//		to slideFrom top, left, right, or bottom.
+	slideFrom: "random"	
+})
diff --git a/dojox/layout/ResizeHandle.js b/dojox/layout/ResizeHandle.js
index 091d879..03b76bd 100644
--- a/dojox/layout/ResizeHandle.js
+++ b/dojox/layout/ResizeHandle.js
@@ -1,182 +1,355 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.ResizeHandle"]){
-dojo._hasResource["dojox.layout.ResizeHandle"]=true;
 dojo.provide("dojox.layout.ResizeHandle");
-dojo.experimental("dojox.layout.ResizeHandle");
+dojo.experimental("dojox.layout.ResizeHandle"); 
+
 dojo.require("dijit._Widget");
-dojo.require("dijit._Templated");
-dojo.require("dojo.fx");
-dojo.declare("dojox.layout.ResizeHandle",[dijit._Widget,dijit._Templated],{targetId:"",targetContainer:null,resizeAxis:"xy",activeResize:false,activeResizeClass:"dojoxResizeHandleClone",animateSizing:true,animateMethod:"chain",animateDuration:225,minHeight:100,minWidth:100,constrainMax:false,maxHeight:0,maxWidth:0,fixedAspect:false,intermediateChanges:false,startTopic:"/dojo/resize/start",endTopic:"/dojo/resize/stop",templateString:"<div dojoAttachPoint=\"resizeHandle\" class=\"dojoxResi [...]
-this.connect(this.resizeHandle,"onmousedown","_beginSizing");
-if(!this.activeResize){
-this._resizeHelper=dijit.byId("dojoxGlobalResizeHelper");
-if(!this._resizeHelper){
-this._resizeHelper=new dojox.layout._ResizeHelper({id:"dojoxGlobalResizeHelper"}).placeAt(dojo.body());
-dojo.addClass(this._resizeHelper.domNode,this.activeResizeClass);
-}
-}else{
-this.animateSizing=false;
-}
-if(!this.minSize){
-this.minSize={w:this.minWidth,h:this.minHeight};
-}
-if(this.constrainMax){
-this.maxSize={w:this.maxWidth,h:this.maxHeight};
-}
-this._resizeX=this._resizeY=false;
-var _1=dojo.partial(dojo.addClass,this.resizeHandle);
-switch(this.resizeAxis.toLowerCase()){
-case "xy":
-this._resizeX=this._resizeY=true;
-_1("dojoxResizeNW");
-break;
-case "x":
-this._resizeX=true;
-_1("dojoxResizeW");
-break;
-case "y":
-this._resizeY=true;
-_1("dojoxResizeN");
-break;
-}
-},_beginSizing:function(e){
-if(this._isSizing){
-return false;
-}
-dojo.publish(this.startTopic,[this]);
-this.targetWidget=dijit.byId(this.targetId);
-this.targetDomNode=this.targetWidget?this.targetWidget.domNode:dojo.byId(this.targetId);
-if(this.targetContainer){
-this.targetDomNode=this.targetContainer;
-}
-if(!this.targetDomNode){
-return false;
-}
-if(!this.activeResize){
-var c=dojo.coords(this.targetDomNode,true);
-this._resizeHelper.resize({l:c.x,t:c.y,w:c.w,h:c.h});
-this._resizeHelper.show();
-}
-this._isSizing=true;
-this.startPoint={x:e.clientX,y:e.clientY};
-var mb=this.targetWidget?dojo.marginBox(this.targetDomNode):dojo.contentBox(this.targetDomNode);
-this.startSize={w:mb.w,h:mb.h};
-if(this.fixedAspect){
-var _2,_3;
-if(mb.w>mb.h){
-_2="w";
-_3=mb.w/mb.h;
-}else{
-_2="h";
-_3=mb.h/mb.w;
-}
-this._aspect={prop:_2};
-this._aspect[_2]=_3;
-}
-this._pconnects=[];
-this._pconnects.push(dojo.connect(dojo.doc,"onmousemove",this,"_updateSizing"));
-this._pconnects.push(dojo.connect(dojo.doc,"onmouseup",this,"_endSizing"));
-dojo.stopEvent(e);
-},_updateSizing:function(e){
-if(this.activeResize){
-this._changeSizing(e);
-}else{
-var _4=this._getNewCoords(e);
-if(_4===false){
-return;
-}
-this._resizeHelper.resize(_4);
-}
-e.preventDefault();
-},_getNewCoords:function(e){
-try{
-if(!e.clientX||!e.clientY){
-return false;
-}
-}
-catch(e){
-return false;
-}
-this._activeResizeLastEvent=e;
-var dx=this.startPoint.x-e.clientX,dy=this.startPoint.y-e.clientY,_5=this.startSize.w-(this._resizeX?dx:0),_6=this.startSize.h-(this._resizeY?dy:0);
-return this._checkConstraints(_5,_6);
-},_checkConstraints:function(_7,_8){
-if(this.minSize){
-var tm=this.minSize;
-if(_7<tm.w){
-_7=tm.w;
-}
-if(_8<tm.h){
-_8=tm.h;
-}
-}
-if(this.constrainMax&&this.maxSize){
-var ms=this.maxSize;
-if(_7>ms.w){
-_7=ms.w;
-}
-if(_8>ms.h){
-_8=ms.h;
-}
-}
-if(this.fixedAspect){
-var ta=this._aspect[this._aspect.prop];
-if(_7<_8){
-_8=_7*ta;
-}else{
-if(_8<_7){
-_7=_8*ta;
-}
-}
-}
-return {w:_7,h:_8};
-},_changeSizing:function(e){
-var _9=this._getNewCoords(e);
-if(_9===false){
-return;
-}
-if(this.targetWidget&&dojo.isFunction(this.targetWidget.resize)){
-this.targetWidget.resize(_9);
-}else{
-if(this.animateSizing){
-var _a=dojo.fx[this.animateMethod]([dojo.animateProperty({node:this.targetDomNode,properties:{width:{start:this.startSize.w,end:_9.w}},duration:this.animateDuration}),dojo.animateProperty({node:this.targetDomNode,properties:{height:{start:this.startSize.h,end:_9.h}},duration:this.animateDuration})]);
-_a.play();
-}else{
-dojo.style(this.targetDomNode,{width:_9.w+"px",height:_9.h+"px"});
-}
-}
-if(this.intermediateChanges){
-this.onResize(e);
-}
-},_endSizing:function(e){
-dojo.forEach(this._pconnects,dojo.disconnect);
-var _b=dojo.partial(dojo.publish,this.endTopic,[this]);
-if(!this.activeResize){
-this._resizeHelper.hide();
-this._changeSizing(e);
-setTimeout(_b,this.animateDuration+15);
-}else{
-_b();
-}
-this._isSizing=false;
-this.onResize(e);
-},onResize:function(e){
-}});
-dojo.declare("dojox.layout._ResizeHelper",dijit._Widget,{show:function(){
-dojo.fadeIn({node:this.domNode,duration:120,beforeBegin:function(n){
-dojo.style(n,"display","");
-}}).play();
-},hide:function(){
-dojo.fadeOut({node:this.domNode,duration:250,onEnd:function(n){
-dojo.style(n,"display","none");
-}}).play();
-},resize:function(_c){
-dojo.marginBox(this.domNode,_c);
-}});
-}
+dojo.require("dijit._Templated"); 
+dojo.require("dojo.fx"); 
+dojo.require("dojo.window");
+
+dojo.declare("dojox.layout.ResizeHandle",
+	[dijit._Widget, dijit._Templated],
+	{
+	// summary: A dragable handle used to resize an attached node.
+	//
+	// description:
+	//	The handle on the bottom-right corner of FloatingPane or other widgets that allows
+	//	the widget to be resized.
+	//	Typically not used directly.
+	//
+	// targetId: String
+	//	id of the Widget OR DomNode that I will size
+	targetId: "",
+	
+	// targetContainer: DomNode
+	//	over-ride targetId and attch this handle directly to a reference of a DomNode
+	targetContainer: null, 
+	
+	// resizeAxis: String
+	//	one of: x|y|xy limit resizing to a single axis, default to xy ... 
+	resizeAxis: "xy",
+	
+	// activeResize: Boolean
+	// 	if true, node will size realtime with mouse movement, 
+	//	if false, node will create virtual node, and only resize target on mouseUp
+	activeResize: false,
+	
+	// activeResizeClass: String
+	//	css class applied to virtual resize node. 
+	activeResizeClass: "dojoxResizeHandleClone",
+	
+	// animateSizing: Boolean
+	//	only applicable if activeResize = false. onMouseup, animate the node to the
+	//	new size
+	animateSizing: true,
+	
+	// animateMethod: String
+	// 	one of "chain" or "combine" ... visual effect only. combine will "scale" 
+	// 	node to size, "chain" will alter width, then height
+	animateMethod: "chain",
+
+	// animateDuration: Integer
+	//	time in MS to run sizing animation. if animateMethod="chain", total animation 
+	//	playtime is 2*animateDuration
+	animateDuration: 225,
+
+	// minHeight: Integer
+	//	smallest height in px resized node can be
+	minHeight: 100,
+
+	// minWidth: Integer
+	//	smallest width in px resize node can be
+	minWidth: 100,
+
+	// constrainMax: Boolean
+	//	Toggle if this widget cares about the maxHeight and maxWidth 
+	//	parameters. 
+	constrainMax: false,
+
+	// maxHeight: Integer
+	//	Largest height size in px the resize node can become. 
+	maxHeight:0, 
+	
+	// maxWidth: Integer
+	//	Largest width size in px the reize node can become.
+	maxWidth:0,
+
+	// fixedAspect: Boolean
+	//		Toggle to enable this widget to maintain the aspect 
+	//		ratio of the attached node. 
+	fixedAspect: false,
+
+	// intermediateChanges: Boolean
+	//		Toggle to enable/disable this widget from firing onResize
+	//		events at every step of a resize. If `activeResize` is true,
+	//		and this is false, onResize only fires _after_ the drop 
+	//		operation. Animated resizing is not affected by this setting.
+	intermediateChanges: false,
+
+	// startTopic: String
+	//		The name of the topic this resizehandle publishes when resize is starting
+	startTopic: "/dojo/resize/start",
+	
+	// endTopic: String
+	//		The name of the topic this resizehandle publishes when resize is complete
+	endTopic:"/dojo/resize/stop",
+
+	templateString: '<div dojoAttachPoint="resizeHandle" class="dojoxResizeHandle"><div></div></div>',
+
+	postCreate: function(){
+		// summary: setup our one major listener upon creation
+		this.connect(this.resizeHandle, "onmousedown", "_beginSizing");
+		if(!this.activeResize){ 
+			// there shall be only a single resize rubberbox that at the top
+			// level so that we can overlay it on anything whenever the user
+			// resizes something. Since there is only one mouse pointer he
+			// can't at once resize multiple things interactively.
+			this._resizeHelper = dijit.byId('dojoxGlobalResizeHelper');
+			if(!this._resizeHelper){
+				this._resizeHelper = new dojox.layout._ResizeHelper({ 
+						id: 'dojoxGlobalResizeHelper'
+				}).placeAt(dojo.body());
+				dojo.addClass(this._resizeHelper.domNode, this.activeResizeClass);
+			}
+		}else{ this.animateSizing = false; } 	
+
+		if(!this.minSize){ 
+			this.minSize = { w: this.minWidth, h: this.minHeight };
+		}
+		
+		if(this.constrainMax){
+			this.maxSize = { w: this.maxWidth, h: this.maxHeight }
+		}
+		
+		// should we modify the css for the cursor hover to n-resize nw-resize and w-resize?
+		this._resizeX = this._resizeY = false;
+		var addClass = dojo.partial(dojo.addClass, this.resizeHandle); 
+		switch(this.resizeAxis.toLowerCase()){
+			case "xy" : 
+				this._resizeX = this._resizeY = true; 
+				// FIXME: need logic to determine NW or NE class to see
+				// based on which [todo] corner is clicked
+				addClass("dojoxResizeNW"); 
+				break; 
+			case "x" : 
+				this._resizeX = true; 
+				addClass("dojoxResizeW");
+				break;
+			case "y" : 
+				this._resizeY = true; 
+				addClass("dojoxResizeN");
+				break;
+		}
+	},
+
+	_beginSizing: function(/*Event*/ e){
+		// summary: setup movement listeners and calculate initial size
+		
+		if(this._isSizing){ return false; }
+
+		dojo.publish(this.startTopic, [ this ]);
+		this.targetWidget = dijit.byId(this.targetId);
+
+		this.targetDomNode = this.targetWidget ? this.targetWidget.domNode : dojo.byId(this.targetId);
+		if(this.targetContainer){ this.targetDomNode = this.targetContainer; }
+		if(!this.targetDomNode){ return false; }
+
+		if(!this.activeResize){
+			var c = dojo.position(this.targetDomNode, true);
+			console.log(c);
+			console.log(dojo.window.getBox());
+			this._resizeHelper.resize({l: c.x, t: c.y, w: c.w, h: c.h});
+			this._resizeHelper.show();
+		}
+
+		this._isSizing = true;
+		this.startPoint  = { x:e.clientX, y:e.clientY};
+
+		// FIXME: this is funky: marginBox adds height, contentBox ignores padding (expected, but foo!)
+		var mb = this.targetWidget ? dojo.marginBox(this.targetDomNode) : dojo.contentBox(this.targetDomNode);  
+		this.startSize  = { w:mb.w, h:mb.h };
+		
+		if(this.fixedAspect){
+			var max, val;
+			if(mb.w > mb.h){
+				max = "w";
+				val = mb.w / mb.h
+			}else{
+				max = "h";
+				val = mb.h / mb.w
+			}
+			this._aspect = { prop: max };
+			this._aspect[max] = val;
+		}
+
+		this._pconnects = []; 
+		this._pconnects.push(dojo.connect(dojo.doc,"onmousemove",this,"_updateSizing")); 
+		this._pconnects.push(dojo.connect(dojo.doc,"onmouseup", this, "_endSizing"));
+		
+		dojo.stopEvent(e); 
+	},
+
+	_updateSizing: function(/*Event*/ e){
+		// summary: called when moving the ResizeHandle ... determines 
+		//	new size based on settings/position and sets styles.
+
+		if(this.activeResize){
+			this._changeSizing(e);
+		}else{
+			var tmp = this._getNewCoords(e);
+			if(tmp === false){ return; }
+			this._resizeHelper.resize(tmp);
+		}
+		e.preventDefault();
+	},
+
+	_getNewCoords: function(/* Event */ e){
+		
+		// On IE, if you move the mouse above/to the left of the object being resized,
+		// sometimes clientX/Y aren't set, apparently.  Just ignore the event.
+		try{
+			if(!e.clientX  || !e.clientY){ return false; }
+		}catch(e){
+			// sometimes you get an exception accessing above fields...
+			return false;
+		}
+		this._activeResizeLastEvent = e; 
+
+		var dx = (this.isLeftToRight()? this.startPoint.x - e.clientX: e.clientX - this.startPoint.x),
+			dy = this.startPoint.y - e.clientY,
+			newW = this.startSize.w - (this._resizeX ? dx : 0),
+			newH = this.startSize.h - (this._resizeY ? dy : 0)
+		;
+			
+		return this._checkConstraints(newW, newH); // Object
+	},
+	
+	_checkConstraints: function(newW, newH){
+		// summary: filter through the various possible constaint possibilities.
+				
+		// minimum size check
+		if(this.minSize){
+			var tm = this.minSize;
+			if(newW < tm.w){
+				newW = tm.w;
+			}
+			if(newH < tm.h){
+				newH = tm.h;
+			}
+		}
+		
+		// maximum size check:
+		if(this.constrainMax && this.maxSize){
+			var ms = this.maxSize;
+			if(newW > ms.w){
+				newW = ms.w;
+			}
+			if(newH > ms.h){
+				newH = ms.h;
+			}
+		}
+		
+		if(this.fixedAspect){
+			var ta = this._aspect[this._aspect.prop];
+			if(newW < newH){
+				newH = newW * ta;
+			}else if(newH < newW){
+				newW = newH * ta;
+			}
+		}
+		
+		return { w: newW, h: newH }; // Object
+	},
+		
+	_changeSizing: function(/*Event*/ e){
+		// summary: apply sizing information based on information in (e) to attached node
+		var tmp = this._getNewCoords(e);
+		if(tmp === false){ return; }
+
+		if(this.targetWidget && dojo.isFunction(this.targetWidget.resize)){ 
+			this.targetWidget.resize(tmp);
+		}else{
+			if(this.animateSizing){
+				var anim = dojo.fx[this.animateMethod]([
+					dojo.animateProperty({
+						node: this.targetDomNode,
+						properties: { 
+							width: { start: this.startSize.w, end: tmp.w } 
+						},	
+						duration: this.animateDuration
+					}),
+					dojo.animateProperty({
+						node: this.targetDomNode,
+						properties: { 
+							height: { start: this.startSize.h, end: tmp.h }
+						},
+						duration: this.animateDuration
+					})
+				]);
+				anim.play();
+			}else{
+				dojo.style(this.targetDomNode,{
+					width: tmp.w + "px",
+					height: tmp.h + "px"
+				});
+			}
+		}
+		if(this.intermediateChanges){
+			this.onResize(e);
+		}	
+	},
+
+	_endSizing: function(/*Event*/ e){
+		// summary: disconnect listenrs and cleanup sizing
+		dojo.forEach(this._pconnects, dojo.disconnect);
+		var pub = dojo.partial(dojo.publish, this.endTopic, [ this ]);
+		if(!this.activeResize){
+			this._resizeHelper.hide();
+			this._changeSizing(e);
+			setTimeout(pub, this.animateDuration + 15);
+		}else{
+			pub();
+		}
+		this._isSizing = false;
+		this.onResize(e);
+	},
+	
+	onResize: function(e){
+		// summary: Stub fired when sizing is done. Fired once 
+		//	after resize, or often when `intermediateChanges` is 
+		//	set to true. 
+	}
+	
+});
+
+dojo.declare("dojox.layout._ResizeHelper",
+	dijit._Widget,
+	{
+	// summary: A global private resize helper shared between any 
+	//		`dojox.layout.ResizeHandle` with activeSizing off.
+	
+	show: function(){
+		// summary: show helper to start resizing
+		dojo.fadeIn({ 
+			node: this.domNode, 
+			duration: 120, 
+			beforeBegin: function(n){ dojo.style(n, "display", "") }
+		}).play();
+	},
+	
+	hide: function(){
+		// summary: hide helper after resizing is complete
+		dojo.fadeOut({ 
+			node: this.domNode, 
+			duration: 250,
+			onEnd: function(n){ dojo.style(n, "display", "none") }
+		}).play();
+	},
+	
+	resize: function(/* Object */dim){
+		// summary: size the widget and place accordingly
+
+		// FIXME: this is off when padding present
+		dojo.marginBox(this.domNode, dim);
+	}
+	
+});
diff --git a/dojox/layout/RotatorContainer.js b/dojox/layout/RotatorContainer.js
old mode 100644
new mode 100755
index ee5737f..8462edc
--- a/dojox/layout/RotatorContainer.js
+++ b/dojox/layout/RotatorContainer.js
@@ -1,191 +1,450 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.RotatorContainer"]){
-dojo._hasResource["dojox.layout.RotatorContainer"]=true;
 dojo.provide("dojox.layout.RotatorContainer");
+
 dojo.require("dojo.fx");
 dojo.require("dijit.layout.StackContainer");
 dojo.require("dijit.layout.StackController");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Contained");
-dojo.declare("dojox.layout.RotatorContainer",[dijit.layout.StackContainer,dijit._Templated],{templateString:"<div class=\"dojoxRotatorContainer\"><div dojoAttachPoint=\"tabNode\"></div><div class=\"dojoxRotatorPager\" dojoAttachPoint=\"pagerNode\"></div><div class=\"dojoxRotatorContent\" dojoAttachPoint=\"containerNode\"></div></div>",showTabs:true,transitionDelay:5000,transition:"fade",transitionDuration:1000,autoStart:true,suspendOnHover:false,pauseOnManualChange:null,reverse:false,pag [...]
-this.inherited(arguments);
-dojo.style(this.domNode,"position","relative");
-if(this.cycles-0==this.cycles&&this.cycles!=-1){
-this.cycles++;
-}else{
-this.cycles=-1;
-}
-if(this.pauseOnManualChange===null){
-this.pauseOnManualChange=!this.suspendOnHover;
-}
-var id=this.id||"rotator"+(new Date()).getTime(),sc=new dijit.layout.StackController({containerId:id},this.tabNode);
-this.tabNode=sc.domNode;
-this._stackController=sc;
-dojo.style(this.tabNode,"display",this.showTabs?"":"none");
-this.connect(sc,"onButtonClick","_manualChange");
-this._subscriptions=[dojo.subscribe(this.id+"-cycle",this,"_cycle"),dojo.subscribe(this.id+"-state",this,"_state")];
-var d=Math.round(this.transitionDelay*0.75);
-if(d<this.transitionDuration){
-this.transitionDuration=d;
-}
-if(this.suspendOnHover){
-this.connect(this.domNode,"onmouseover","_onMouseOver");
-this.connect(this.domNode,"onmouseout","_onMouseOut");
-}
-},startup:function(){
-if(this._started){
-return;
-}
-var c=this.getChildren();
-for(var i=0,_1=c.length;i<_1;i++){
-if(c[i].declaredClass==this.pagerClass){
-this.pagerNode.appendChild(c[i].domNode);
-break;
-}
-}
-this.inherited(arguments);
-if(this.autoStart){
-setTimeout(dojo.hitch(this,"_play"),10);
-}else{
-this._updatePager();
-}
-},destroy:function(){
-dojo.forEach(this._subscriptions,dojo.unsubscribe);
-this.inherited(arguments);
-},_setShowTabsAttr:function(_2){
-this.showTabs=_2;
-dojo.style(this.tabNode,"display",_2?"":"none");
-},_updatePager:function(){
-var c=this.getChildren();
-dojo.publish(this.id+"-update",[this._playing,dojo.indexOf(c,this.selectedChildWidget)+1,c.length]);
-},_onMouseOver:function(){
-this._resetTimer();
-this._over=true;
-},_onMouseOut:function(){
-this._over=false;
-if(this._playing){
-clearTimeout(this._timer);
-this._timer=setTimeout(dojo.hitch(this,"_play",true),200);
-}
-},_resetTimer:function(){
-clearTimeout(this._timer);
-this._timer=null;
-},_cycle:function(_3){
-if(_3 instanceof Boolean||typeof _3=="boolean"){
-this._manualChange();
-}
-var c=this.getChildren(),_4=c.length,i=dojo.indexOf(c,this.selectedChildWidget)+(_3===false||(_3!==true&&this.reverse)?-1:1);
-this.selectChild(c[(i<_4?(i<0?_4-1:i):0)]);
-this._updatePager();
-},_manualChange:function(){
-if(this.pauseOnManualChange){
-this._playing=false;
-}
-this.cycles=-1;
-},_play:function(_5){
-this._playing=true;
-this._resetTimer();
-if(_5!==true&&this.cycles>0){
-this.cycles--;
-}
-if(this.cycles==0){
-this._pause();
-}else{
-if((!this.suspendOnHover||!this._over)&&this.transitionDelay){
-this._timer=setTimeout(dojo.hitch(this,"_cycle"),this.selectedChildWidget.domNode.getAttribute("transitionDelay")||this.transitionDelay);
-}
-}
-this._updatePager();
-},_pause:function(){
-this._playing=false;
-this._resetTimer();
-},_state:function(_6){
-if(_6){
-this.cycles=-1;
-this._play();
-}else{
-this._pause();
-}
-},_transition:function(_7,_8){
-this._resetTimer();
-if(_8&&this.transitionDuration){
-switch(this.transition){
-case "fade":
-this._fade(_7,_8);
-return;
-}
-}
-this._transitionEnd();
-this.inherited(arguments);
-},_transitionEnd:function(){
-if(this._playing){
-this._play();
-}else{
-this._updatePager();
-}
-},_fade:function(_9,_a){
-this._styleNode(_a.domNode,1,1);
-this._styleNode(_9.domNode,0,2);
-this._showChild(_9);
-if(this.doLayout&&_9.resize){
-_9.resize(this._containerContentBox||this._contentBox);
-}
-var _b={duration:this.transitionDuration},_c=dojo.fx.combine([dojo["fadeOut"](dojo.mixin({node:_a.domNode},_b)),dojo["fadeIn"](dojo.mixin({node:_9.domNode},_b))]);
-this.connect(_c,"onEnd",dojo.hitch(this,function(){
-this._hideChild(_a);
-this._transitionEnd();
-}));
-_c.play();
-},_styleNode:function(_d,_e,_f){
-dojo.style(_d,"opacity",_e);
-dojo.style(_d,"zIndex",_f);
-dojo.style(_d,"position","absolute");
-}});
-dojo.declare("dojox.layout.RotatorPager",[dijit._Widget,dijit._Templated,dijit._Contained],{widgetsInTemplate:true,rotatorId:"",postMixInProperties:function(){
-this.templateString="<div>"+this.srcNodeRef.innerHTML+"</div>";
-},postCreate:function(){
-var p=dijit.byId(this.rotatorId)||this.getParent();
-if(p&&p.declaredClass=="dojox.layout.RotatorContainer"){
-if(this.previous){
-dojo.connect(this.previous,"onClick",function(){
-dojo.publish(p.id+"-cycle",[false]);
-});
-}
-if(this.next){
-dojo.connect(this.next,"onClick",function(){
-dojo.publish(p.id+"-cycle",[true]);
+
+dojo.declare("dojox.layout.RotatorContainer", 
+	[dijit.layout.StackContainer, dijit._Templated], {
+	// summary:
+	//		Extends a StackContainer to automatically transition between children
+	//		and display navigation in the form of tabs or a pager.
+	//
+	// description:
+	// 		The RotatorContainer cycles through the children with a transition.
+	//
+	// published topics:
+	// 		[widgetId]-update - Notifies pager(s) that a child has changed.
+	//			Parameters:
+	//				/*boolean*/ playing - true if playing, false if paused
+	//				/*int*/ current     - current selected child
+	//				/*int*/ total       - total number of children
+	//
+	// example:
+	// |	<div dojoType="dojox.layout.RotatorContainer" id="myRotator" showTabs="true" autoStart="true" transitionDelay="5000">
+	// |		<div id="pane1" dojoType="dijit.layout.ContentPane" title="1">
+	// |			Pane 1!
+	// |		</div>
+	// |		<div id="pane2" dojoType="dijit.layout.ContentPane" title="2">
+	// |			Pane 2!
+	// |		</div>
+	// |		<div id="pane3" dojoType="dijit.layout.ContentPane" title="3" transitionDelay="10000">
+	// |			Pane 3 with overrided transitionDelay!
+	// |		</div>
+	// |	</div>
+
+	templateString: '<div class="dojoxRotatorContainer"><div dojoAttachPoint="tabNode"></div><div class="dojoxRotatorPager" dojoAttachPoint="pagerNode"></div><div class="dojoxRotatorContent" dojoAttachPoint="containerNode"></div></div>',
+
+	// showTabs: Boolean
+	//		Sets the display of the tabs.  The tabs are actually a StackController.
+	//		The child's title is used for the tab's label. 
+	showTabs: true,
+
+	// transitionDelay: int
+	//		The delay in milliseconds before transitioning to the next child.
+	transitionDelay: 5000,
+
+	// transition: String
+	//		The type of transition to perform when switching children.
+	//		A null transition will transition instantly.
+	transition: "fade",
+
+	// transitionDuration: int
+	//		The duration of the transition in milliseconds.
+	transitionDuration: 1000,
+
+	// autoStart: Boolean
+	//		Starts the timer to transition children upon creation.
+	autoStart: true,
+
+	// suspendOnHover: Boolean
+	//		Pause the rotator when the mouse hovers over it.
+	suspendOnHover: false,
+
+	// pauseOnManualChange: Boolean
+	//		Pause the rotator when the tab is changed or the pager's next/previous
+	//		buttons are clicked.
+	pauseOnManualChange: null,
+
+	// reverse: Boolean
+	//		Causes the rotator to rotate in reverse order.
+	reverse: false,
+
+	// pagerId: String
+	//		ID the pager widget.
+	pagerId: "",
+
+	// cycles: int
+	//		Number of cycles before pausing.
+	cycles: -1,
+
+	// pagerClass: String
+	//		The declared Class of the Pager used for this Widget
+ 	pagerClass: "dojox.layout.RotatorPager",
+
+	postCreate: function(){
+		// summary: Initializes the DOM nodes, tabs, and transition stuff.
+		this.inherited(arguments);
+
+		// force this DOM node to a relative position and make sure the children are absolute positioned
+		dojo.style(this.domNode, "position", "relative");
+
+		// validate the cycles counter
+		if(this.cycles-0 == this.cycles && this.cycles != -1){
+			// we need to add 1 because we decrement cycles before the animation starts
+			this.cycles++;
+		}else{
+			this.cycles = -1;
+		}
+
+		// if they didn't specify the pauseOnManualChange, then we want it to be the opposite of
+		// the suspendOnHover since it doesn't make sense to do both, unless you really want to
+		if(this.pauseOnManualChange === null){
+			this.pauseOnManualChange = !this.suspendOnHover;
+		}
+
+		// create the stack controller if we are using tabs
+		var id = this.id || "rotator"+(new Date()).getTime(),
+			sc = new dijit.layout.StackController({ containerId:id }, this.tabNode);
+		this.tabNode = sc.domNode;
+		this._stackController = sc;
+		dojo.style(this.tabNode, "display", this.showTabs ? "" : "none");
+
+		// if the controller's tabs are clicked, check if we should pause and reset the cycle counter
+		this.connect(sc, "onButtonClick","_manualChange");
+
+		// set up our topic listeners
+		this._subscriptions = [
+			dojo.subscribe(this.id+"-cycle", this, "_cycle"),
+			dojo.subscribe(this.id+"-state", this, "_state")
+		];
+
+		// make sure the transition duration isn't less than the transition delay
+		var d = Math.round(this.transitionDelay * 0.75);
+		if(d < this.transitionDuration){
+			this.transitionDuration = d;
+		}
+
+		// wire up the mouse hover events
+		if(this.suspendOnHover){
+			this.connect(this.domNode, "onmouseover", "_onMouseOver");
+			this.connect(this.domNode, "onmouseout", "_onMouseOut");
+		}
+	},
+
+	startup: function(){
+		// summary: Initializes the pagers.
+		if(this._started){ return; }
+
+		// check if the pager is defined within the rotator container
+		var c = this.getChildren();
+		for(var i=0, len=c.length; i<len; i++){
+			if(c[i].declaredClass == this.pagerClass){
+				this.pagerNode.appendChild(c[i].domNode);
+				break;
+			}
+		}
+
+		// process the child widgets
+		this.inherited(arguments);
+
+		// check if we should start automatically
+		if(this.autoStart){
+			// start playing
+			setTimeout(dojo.hitch(this, "_play"), 10);
+		}else{
+			// update the pagers with the initial state
+			this._updatePager();
+		}
+	},
+
+	destroy: function(){
+		// summary: Unsubscribe to all of our topics
+		dojo.forEach(this._subscriptions, dojo.unsubscribe);
+		this.inherited(arguments);
+	},
+
+	_setShowTabsAttr: function(/*anything*/value){
+		this.showTabs = value;
+		dojo.style(this.tabNode, "display", value ? "" : "none");
+	},
+
+	_updatePager: function(){
+		// summary: Notify the pager's current and total numbers.
+		var c = this.getChildren();
+		dojo.publish(this.id+"-update", [this._playing, dojo.indexOf(c, this.selectedChildWidget)+1, c.length]);
+	},
+
+	_onMouseOver: function(){
+		// summary: Triggered when the mouse is moved over the rotator container.
+
+		// temporarily suspend the cycling, but don't officially pause it
+		this._resetTimer();
+		this._over = true;
+	},
+
+	_onMouseOut: function(){
+		// summary: Triggered when the mouse is moved off the rotator container.
+		this._over = false;
+
+		// if we were playing, resume playback in 200ms
+		// we need to wait because we may be moused over again right away
+		if(this._playing){
+			clearTimeout(this._timer);
+			this._timer = setTimeout(dojo.hitch(this, "_play", true), 200);
+		}
+	},
+
+	_resetTimer: function(){
+		// summary: Resets the timer used to start the next transition.
+		clearTimeout(this._timer);
+		this._timer = null;
+	},
+
+	_cycle: function(/*boolean or int*/next){
+		// summary: Cycles to the next/previous child.
+
+		// if next is an int, then _cycle() was called via a timer
+		// if next is a boolean, then _cycle() was called via the next/prev buttons, stop playing and reset cycles
+		if(next instanceof Boolean || typeof next == "boolean"){
+			this._manualChange();
+		}
+
+		var c = this.getChildren(),
+			len = c.length,
+			i = dojo.indexOf(c, this.selectedChildWidget) + (next === false || (next !== true && this.reverse) ? -1 : 1);
+		this.selectChild(c[(i < len ? (i < 0 ? len-1 : i) : 0)]);
+		this._updatePager();
+	},
+
+	_manualChange: function(){
+		// summary: This function is only called when a manual change occurs in which
+		//   case we may need to stop playing and we need to reset the cycle counter
+		if(this.pauseOnManualChange){
+			this._playing = false;
+		}
+		this.cycles = -1;
+	},
+
+	_play: function(skip){
+		// summary: Schedules the next transition.
+		this._playing = true;
+		this._resetTimer();
+		if(skip !== true && this.cycles>0){
+			this.cycles--;
+		}
+		if(this.cycles==0){
+			this._pause();
+		}else if((!this.suspendOnHover || !this._over) && this.transitionDelay){
+			// check if current pane has a delay
+			this._timer = setTimeout(dojo.hitch(this, "_cycle"), this.selectedChildWidget.domNode.getAttribute("transitionDelay") || this.transitionDelay);
+		}
+		this._updatePager();
+	},
+
+	_pause: function(){
+		// summary: Clears the transition timer and pauses the rotator.
+		this._playing = false;
+		this._resetTimer();
+	},
+
+	_state: function(playing){
+		// summary: Fired when the play/pause pager button is toggled.
+		if(playing){
+			// since we were manually changed, disable the cycle counter
+			this.cycles = -1;
+			this._play();
+		}else{
+			this._pause();
+		}
+	},
+
+	_transition: function(/*dijit._Widget*/ next, /*dijit._Widget*/ prev){
+		// summary: Dispatches the appropriate transition.
+		this._resetTimer();
+
+		// check if we have anything to transition
+		if(prev && this.transitionDuration){
+			switch(this.transition){
+				case "fade": this._fade(next, prev); return;
+			}
+		}
+
+		this._transitionEnd();
+		this.inherited(arguments);
+	},
+
+	_transitionEnd: function(){
+		if(this._playing){
+			this._play();
+		}else{
+			this._updatePager();
+		}
+	},
+
+	_fade: function(/*dijit._Widget*/ next, /*dijit._Widget*/ prev){
+		// summary: Crossfades two children.
+		this._styleNode(prev.domNode, 1, 1);
+		this._styleNode(next.domNode, 0, 2);
+
+		// show the next child and make sure it's sized properly
+		this._showChild(next);
+		if(this.doLayout && next.resize){
+			next.resize(this._containerContentBox || this._contentBox);
+		}
+
+		// create the crossfade animation
+		var args = { duration:this.transitionDuration },
+			anim = dojo.fx.combine([
+				dojo["fadeOut"](dojo.mixin({node:prev.domNode}, args)),
+				dojo["fadeIn"](dojo.mixin({node:next.domNode}, args))
+			]);
+
+		this.connect(anim, "onEnd", dojo.hitch(this,function(){
+			this._hideChild(prev);
+			this._transitionEnd();
+		}));
+
+		anim.play();
+	},
+
+	_styleNode: function(/*DOMnode*/node, /*number*/opacity, /*int*/zIndex){
+		// summary: Helper function to style the children.
+		dojo.style(node, "opacity", opacity);
+		dojo.style(node, "zIndex", zIndex);
+		dojo.style(node, "position", "absolute");
+	}
 });
-}
-if(this.playPause){
-dojo.connect(this.playPause,"onClick",function(){
-this.attr("label",this.checked?"Pause":"Play");
-dojo.publish(p.id+"-state",[this.checked]);
+
+dojo.declare("dojox.layout.RotatorPager", [dijit._Widget, dijit._Templated, dijit._Contained], {
+	// summary:
+	//		Defines controls used to manipulate a RotatorContainer
+	//
+	// description:
+	//		A pager can be defined one of two ways:
+	//			* Externally of the RotatorContainer's template and tell the
+	//			RotatorPager the rotatorId of the RotatorContainer
+	//			* As a direct descendant of the RotatorContainer (i.e. inside the
+	//			RotatorContainer's template)
+	//
+	//		The pager can contain the following components:
+	//			* Previous button
+	//				- Must be a dijit.form.Button
+	//				- dojoAttachPoint must be named "previous"
+	//			* Next button
+	//				- Must be a dijit.form.Button
+	//				- dojoAttachPoint must be named "next"
+	//			* Play/Pause toggle button
+	//				- Must be a dijit.form.ToggleButton
+	//				- dojoAttachPoint must be named "playPause"
+	//				- Use iconClass to specify toggled state
+	//			* Current child #
+	//				- dojoAttachPoint must be named "current"
+	//			* Total # of children
+	//				- dojoAttachPoint must be named "total"
+	//
+	//		You can choose to exclude specific controls as well as add elements
+	//		for styling.
+	//
+	//		Should you need a pager, but don't want to use Dijit buttons, you can
+	//		write your own pager widget and just wire it into the topics.  The
+	//		topic names are prefixed with the widget ID of the RotatorContainer.
+	//		Notifications are received from and sent to the RotatorContainer as
+	//		well as other RotatorPagers.
+	//
+	// published topics:
+	//		[widgetId]-cycle - Notify that the next or previous button was pressed.
+	//			Parameters:
+	//				/*boolean*/ next - true if next, false if previous
+	//		[widgetId]-state - Notify that the play/pause button was toggled.
+	//			Parameters:
+	//				/*boolean*/ playing - true if playing, false if paused
+	//
+	// example:
+	//		A pager with the current/total children and previous/next buttons.
+	// |	<div dojoType="dojox.layout.RotatorPager" rotatorId="myRotator">
+	// |		<button dojoType="dijit.form.Button" dojoAttachPoint="previous">Prev</button>
+	// |		<span dojoAttachPoint="current"></span> / <span dojoAttachPoint="total"></span>
+	// |		<button dojoType="dijit.form.Button" dojoAttachPoint="next">Next</button>
+	// |	</div>
+	//
+	// example:
+	//		A pager with only a play/pause toggle button.
+	// |	<div dojoType="dojox.layout.RotatorPager" rotatorId="myRotator">
+	// |		<button dojoType="dijit.form.ToggleButton" dojoAttachPoint="playPause"></button>
+	// |	</div>
+	//
+	// example:
+	//		A pager styled with iconClass.
+	// |	<div dojoType="dojox.layout.RotatorPager" class="rotatorIcons" rotatorId="myRotator">
+	// |		<button dojoType="dijit.form.Button" iconClass="previous" dojoAttachPoint="previous">Prev</button>
+	// |		<button dojoType="dijit.form.ToggleButton" iconClass="playPause" dojoAttachPoint="playPause"></button>
+	// |		<button dojoType="dijit.form.Button" iconClass="next" dojoAttachPoint="next">Next</button>
+	// |		<span dojoAttachPoint="current"></span> / <span dojoAttachPoint="total"></span>
+	// |	</div>
+
+	widgetsInTemplate: true,
+
+	// rotatorId: int
+	//		The ID of the rotator this pager is tied to.
+	//		Only required if defined outside of the RotatorContainer's container.
+	rotatorId: "",
+
+	postMixInProperties: function(){
+		this.templateString = "<div>" + this.srcNodeRef.innerHTML + "</div>";
+	},
+
+	postCreate: function(){
+		var p = dijit.byId(this.rotatorId) || this.getParent();
+		if(p && p.declaredClass == "dojox.layout.RotatorContainer"){
+			if(this.previous){
+				dojo.connect(this.previous, "onClick", function(){
+					dojo.publish(p.id+"-cycle", [false]);
+				});
+			}
+			if(this.next){
+				dojo.connect(this.next, "onClick", function(){
+					dojo.publish(p.id+"-cycle", [true]);
+				});
+			}
+			if(this.playPause){
+				dojo.connect(this.playPause, "onClick", function(){
+					this.set('label', this.checked ? "Pause" : "Play");
+					dojo.publish(p.id+"-state", [this.checked]);
+				});
+			}
+			this._subscriptions = [
+				dojo.subscribe(p.id+"-state", this, "_state"),
+				dojo.subscribe(p.id+"-update", this, "_update")
+			];
+		}
+	},
+
+	destroy: function(){
+		// summary: Unsubscribe to all of our topics
+		dojo.forEach(this._subscriptions, dojo.unsubscribe);
+		this.inherited(arguments);
+	},
+
+	_state: function(/*boolean*/playing){
+		// summary: Updates the display of the play/pause button
+		if(this.playPause && this.playPause.checked != playing){
+			this.playPause.attr("label", playing ? "Pause" : "Play");
+			this.playPause.attr("checked", playing);
+		}
+	},
+
+	_update: function(/*boolean*/playing, /*int*/current, /*int*/total){
+		// summary: Updates the pager's play/pause button, current child, and total number of children.
+		this._state(playing);
+		if(this.current && current){
+			this.current.innerHTML = current;
+		}
+		if(this.total && total){
+			this.total.innerHTML = total;
+		}
+	}
 });
-}
-this._subscriptions=[dojo.subscribe(p.id+"-state",this,"_state"),dojo.subscribe(p.id+"-update",this,"_update")];
-}
-},destroy:function(){
-dojo.forEach(this._subscriptions,dojo.unsubscribe);
-this.inherited(arguments);
-},_state:function(_10){
-if(this.playPause&&this.playPause.checked!=_10){
-this.playPause.attr("label",_10?"Pause":"Play");
-this.playPause.attr("checked",_10);
-}
-},_update:function(_11,_12,_13){
-this._state(_11);
-if(this.current&&_12){
-this.current.innerHTML=_12;
-}
-if(this.total&&_13){
-this.total.innerHTML=_13;
-}
-}});
-}
diff --git a/dojox/layout/ScrollPane.js b/dojox/layout/ScrollPane.js
index b212ecc..e9c2c80 100644
--- a/dojox/layout/ScrollPane.js
+++ b/dojox/layout/ScrollPane.js
@@ -1,82 +1,147 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.ScrollPane"]){
-dojo._hasResource["dojox.layout.ScrollPane"]=true;
 dojo.provide("dojox.layout.ScrollPane");
 dojo.experimental("dojox.layout.ScrollPane");
+
 dojo.require("dijit.layout.ContentPane");
 dojo.require("dijit._Templated");
-dojo.declare("dojox.layout.ScrollPane",[dijit.layout.ContentPane,dijit._Templated],{_line:null,_lo:null,_offset:15,orientation:"vertical",autoHide:true,templateString:dojo.cache("dojox.layout","resources/ScrollPane.html","<div class=\"dojoxScrollWindow\" dojoAttachEvent=\"onmouseenter: _enter, onmouseleave: _leave\">\n    <div class=\"dojoxScrollWrapper\" style=\"${style}\" dojoAttachPoint=\"wrapper\" dojoAttachEvent=\"onmousemove: _calc\">\n\t<div class=\"dojoxScrollPane\" dojoAttachPoi [...]
-if(_1){
-if(_1.h){
-dojo.style(this.domNode,"height",_1.h+"px");
-}
-if(_1.w){
-dojo.style(this.domNode,"width",_1.w+"px");
-}
-}
-var _2=this._dir,_3=this._vertical,_4=this.containerNode[(_3?"scrollHeight":"scrollWidth")];
-dojo.style(this.wrapper,this._dir,this.domNode.style[this._dir]);
-this._lo=dojo.coords(this.wrapper,true);
-this._size=Math.max(0,_4-this._lo[(_3?"h":"w")]);
-if(!this._size){
-this.helper.style.display="none";
-this.wrapper[this._scroll]=0;
-return;
-}else{
-this.helper.style.display="";
-}
-this._line=new dojo._Line(0-this._offset,this._size+(this._offset*2));
-var u=this._lo[(_3?"h":"w")],r=Math.min(1,u/_4),s=u*r,c=Math.floor(u-(u*r));
-this._helpLine=new dojo._Line(0,c);
-dojo.style(this.helper,_2,Math.floor(s)+"px");
-},postCreate:function(){
-this.inherited(arguments);
-if(this.autoHide){
-this._showAnim=dojo._fade({node:this.helper,end:0.5,duration:350});
-this._hideAnim=dojo.fadeOut({node:this.helper,duration:750});
-}
-this._vertical=(this.orientation=="vertical");
-if(!this._vertical){
-dojo.addClass(this.containerNode,"dijitInline");
-this._dir="width";
-this._edge="left";
-this._scroll="scrollLeft";
-}else{
-this._dir="height";
-this._edge="top";
-this._scroll="scrollTop";
-}
-if(this._hideAnim){
-this._hideAnim.play();
-}
-dojo.style(this.wrapper,"overflow","hidden");
-},_set:function(n){
-if(!this._size){
-return;
-}
-this.wrapper[this._scroll]=Math.floor(this._line.getValue(n));
-dojo.style(this.helper,this._edge,Math.floor(this._helpLine.getValue(n))+"px");
-},_calc:function(e){
-if(!this._lo){
-this.resize();
-}
-this._set(this._vertical?((e.pageY-this._lo.y)/this._lo.h):((e.pageX-this._lo.x)/this._lo.w));
-},_enter:function(e){
-if(this._hideAnim){
-if(this._hideAnim.status()=="playing"){
-this._hideAnim.stop();
-}
-this._showAnim.play();
-}
-},_leave:function(e){
-if(this._hideAnim){
-this._hideAnim.play();
-}
-}});
-}
+
+dojo.declare("dojox.layout.ScrollPane",
+	[dijit.layout.ContentPane, dijit._Templated],
+	{
+	// summary: A pane that "scrolls" its content based on the mouse poisition inside
+	//
+	// description:
+	//		A sizable container that takes it's content's natural size and creates
+	//		a scroll effect based on the relative mouse position. It is an interesting
+	//		way to display lists of data, or blocks of content, within a confined
+	//		space.
+	//
+	// 		Horizontal scrolling is supported. Combination scrolling is not.
+	//
+	//		FIXME: need to adust the _line somehow, it stops scrolling
+	//		
+	// example:
+	// |	<div dojoType="dojox.layout.ScrollPane" style="width:150px height:300px;">
+	// |		<!-- any height content -->
+	// |	</div>
+	//
+	// _line: dojo._Line
+	// 		storage for our top and bottom most scrollpoints
+	_line: null,
+	
+	// _lo: the height of the visible pane
+	_lo: null,
+	
+	_offset: 15,
+	
+	// orientation: String
+	//		either "horizontal" or "vertical" for scroll orientation. 
+	orientation: "vertical",
+	
+	// alwaysShow: Boolean
+	//		whether the scroll helper should hide when mouseleave
+	autoHide: true,
+	templateString: dojo.cache("dojox.layout","resources/ScrollPane.html"),
+	
+	resize: function(size){
+		// summary: calculates required sizes. Call this if you add/remove content manually, or reload the content.
+		
+		// if size is passed, it means we need to take care of sizing ourself (this is for IE<8)
+		if(size){
+			if(size.h){
+				dojo.style(this.domNode,'height',size.h+'px');
+			}
+			if(size.w){
+				dojo.style(this.domNode,'width',size.w+'px');
+			}
+		}
+		var dir = this._dir,
+			vert = this._vertical,
+			val = this.containerNode[(vert ? "scrollHeight" : "scrollWidth")];
+
+		dojo.style(this.wrapper, this._dir, this.domNode.style[this._dir]);
+		this._lo = dojo.coords(this.wrapper, true);
+		
+		this._size = Math.max(0, val - this._lo[(vert ? "h" : "w")]);
+		if(!this._size){
+			this.helper.style.display="none";
+			//make sure we reset scroll position, otherwise the content may be hidden
+			this.wrapper[this._scroll]=0;
+			return;
+		}else{
+			this.helper.style.display="";
+		}
+		this._line = new dojo._Line(0 - this._offset, this._size + (this._offset * 2));
+	
+		// share a relative position w the scroll offset via a line
+		var u = this._lo[(vert ? "h" : "w")],
+			r = Math.min(1, u / val), // ratio
+			s = u * r, // size
+			c = Math.floor(u - (u * r)); // center
+			  
+		this._helpLine = new dojo._Line(0, c);
+	
+		// size the helper
+		dojo.style(this.helper, dir, Math.floor(s) + "px");
+		
+	},
+	
+	postCreate: function(){
+		this.inherited(arguments);
+		// for the helper
+		if(this.autoHide){
+			this._showAnim = dojo._fade({ node:this.helper, end:0.5, duration:350 });
+			this._hideAnim = dojo.fadeOut({ node:this.helper, duration: 750 });
+		}
+	
+		// orientation helper
+		this._vertical = (this.orientation == "vertical");
+		if(!this._vertical){
+			dojo.addClass(this.containerNode,"dijitInline");
+			this._dir = "width";
+			this._edge = "left";
+			this._scroll = "scrollLeft";
+		}else{
+			this._dir = "height";
+			this._edge = "top";
+			this._scroll = "scrollTop";
+		}
+
+		if(this._hideAnim){
+			this._hideAnim.play();
+		}
+		dojo.style(this.wrapper,"overflow","hidden");
+	
+	},	
+	
+	_set: function(/* Float */n){
+		if(!this._size){ return; }
+		// summary: set the pane's scroll offset, and position the virtual scroll helper 
+		this.wrapper[this._scroll] = Math.floor(this._line.getValue(n));
+		dojo.style(this.helper, this._edge, Math.floor(this._helpLine.getValue(n)) + "px");    
+	},
+	
+	_calc: function(/* Event */e){
+		// summary: calculate the relative offset of the cursor over the node, and call _set
+		if(!this._lo){ this.resize(); }
+		this._set(this._vertical ? 
+			((e.pageY - this._lo.y) / this._lo.h) :
+			((e.pageX - this._lo.x) / this._lo.w)
+		);
+	},
+	
+	_enter: function(e){
+		if(this._hideAnim){
+			if(this._hideAnim.status() == "playing"){ 
+				this._hideAnim.stop(); 
+			}
+			this._showAnim.play();
+		}
+	},
+	
+	_leave: function(e){
+		if(this._hideAnim){
+			this._hideAnim.play();
+		}
+	}
+    
+});
diff --git a/dojox/layout/TableContainer.js b/dojox/layout/TableContainer.js
index 600fbe8..e6b9ebd 100644
--- a/dojox/layout/TableContainer.js
+++ b/dojox/layout/TableContainer.js
@@ -1,136 +1,279 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.TableContainer"]){
-dojo._hasResource["dojox.layout.TableContainer"]=true;
 dojo.experimental("dojox.layout.TableContainer");
 dojo.provide("dojox.layout.TableContainer");
 dojo.require("dijit.layout._LayoutWidget");
-dojo.declare("dojox.layout.TableContainer",dijit.layout._LayoutWidget,{cols:1,labelWidth:"100",showLabels:true,orientation:"horiz",spacing:1,customClass:"",postCreate:function(){
-this.inherited(arguments);
-this._children=[];
-dojo.connect(this,"attr",dojo.hitch(this,function(_1,_2){
-if(_2&&(_1=="orientation"||_1=="customClass"||_1=="cols")){
-this.layout();
-}
-}));
-},startup:function(){
-if(this._started){
-return;
-}
-this.inherited(arguments);
-if(this._initialized){
-return;
-}
-var _3=this.getChildren();
-if(_3.length<1){
-return;
-}
-this._initialized=true;
-dojo.addClass(this.domNode,"dijitTableLayout");
-dojo.forEach(_3,function(_4){
-if(!_4.started&&!_4._started){
-_4.startup();
-}
-});
-this.resize();
-this.layout();
-},resize:function(){
-dojo.forEach(this.getChildren(),function(_5){
-if(typeof _5.resize=="function"){
-_5.resize();
-}
+
+dojo.declare("dojox.layout.TableContainer",
+	dijit.layout._LayoutWidget,
+	{
+	// summary: 
+	//		A container that lays out its child widgets in a table layout.
+	//
+	// description:
+	//		The TableContainer lays out child widgets in a Table layout.
+	//		Each widget can specify a "label" or a "title" parameter.
+	//		This label is displayed either above or to the left of
+	//		a widget depending on whether the "orientation" attribute
+	//		is "horiz" or "vert", for horizontal and vertical respectively.
+	//		The number of columns is configured using the "cols" attribute.
+	//		The width of labels can be configured using the "labelWidth" parameter.
+	//
+	// example:
+	// |	<div dojoType="dojox.layout.TableContainer" orientation="vert" cols="3>
+	// |		<div dojoType="dijit.form.TextInput" value="John" label="First Name:"></div>
+	// |		<div dojoType="dijit.form.CheckBox" label="Is Student?:"></div>
+	// |		<div dojoType="dojox.form.DateTextBox" label="Date Of Birth:"></div>
+	// |	</div>
+	//
+
+	cols: 1,
+	
+	// labelWidth: Number|String
+	//		Defines the width of a label.  If the value is a number, it is
+	//		treated as a pixel value.  The other valid value is a percentage, 
+	//		e.g. "50%"
+	labelWidth: "100",
+
+	// showLabels: Boolean
+	//		True if labels should be displayed, false otherwise.
+	showLabels: true,
+
+	// orientation: String
+	//		Either "horiz" or "vert" for label orientation. 
+	orientation: "horiz", 
+	
+	// spacing: Number
+	//		The cell spacing to apply to the table.
+	spacing: 1,
+
+	// customClass: String
+	//		A CSS class that will be applied to child elements.  For example, if
+	//		the class is "myClass", the table will have "myClass-table" applied to it,
+	//		each label TD will have "myClass-labelCell" applied, and each 
+	//		widget TD will have "myClass-valueCell" applied.
+	customClass: "",
+
+	postCreate: function(){
+		this.inherited(arguments);
+		this._children = [];
+		
+		// If the orientation, customClass or cols attributes are changed, 
+		// layout the widgets again.
+		dojo.connect(this, "attr", dojo.hitch(this, function(name, value){
+			if(value && (name == "orientation" || name == "customClass" || name == "cols")) {
+				this.layout();
+			}
+		}))
+	},
+
+	startup: function() {
+		if(this._started) {
+			return;
+		}
+		this.inherited(arguments);
+		if(this._initialized) {
+			return;
+		}
+		var children = this.getChildren();
+		if(children.length < 1) {
+			return;
+		}
+		this._initialized = true;
+
+		dojo.addClass(this.domNode, "dijitTableLayout");
+
+		// Call startup on all child widgets
+		dojo.forEach(children, function(child){
+			if(!child.started && !child._started) {
+				child.startup();
+			}
+		});
+		this.resize();
+		this.layout();
+	},
+
+	resize: function(){
+		// summary: 
+		//		Resizes all children.  This widget itself
+		//		does not resize, as it takes up 100% of the
+		//		available width.
+		dojo.forEach(this.getChildren(), function(child){
+			if(typeof child.resize == "function") {
+				child.resize();
+			}
+		});
+	},
+
+	layout: function(){
+		// summary: 
+		//		Lays out the child widgets.
+		if(!this._initialized){
+			return;
+		}
+
+		var children = this.getChildren();
+
+		var childIds = {};
+		var _this = this;
+
+		function addCustomClass(node, type, count) {
+			if(_this.customClass != "") {
+				var clazz = _this.customClass+ "-" + (type || node.tagName.toLowerCase());
+				dojo.addClass(node, clazz);
+
+				if(arguments.length > 2) {
+					dojo.addClass(node, clazz + "-" + count);
+				}
+			}
+		}
+
+		// Find any new children that have been added since the last layout() call
+		dojo.forEach(this._children, dojo.hitch(this, function(child){
+			childIds[child.id] = child;
+		}));
+
+		dojo.forEach(children, dojo.hitch(this, function(child, index){
+			if(!childIds[child.id]) {
+				// Add pre-existing children to the start of the array
+				this._children.push(child);
+			}
+		}));
+
+		// Create the table.  It fills the width of it's container.
+		var table = dojo.create("table", {
+			"width": "100%",
+			 "class": "tableContainer-table tableContainer-table-" + this.orientation,
+			 "cellspacing" : this.spacing
+			},
+			this.domNode);
+
+		var tbody = dojo.create("tbody");
+		table.appendChild(tbody);
+
+		addCustomClass(table, "table", this.orientation);
+
+		var width = Math.floor(100 / this.cols) + "%";
+
+		var labelRow = dojo.create("tr", {}, tbody);
+		var childRow = (!this.showLabels || this.orientation == "horiz")
+											? labelRow : dojo.create("tr", {}, tbody);
+		var maxCols = this.cols * (this.showLabels ? 2 : 1);
+		var numCols = 0;
+
+		// Iterate over the children, adding them to the table.
+		dojo.forEach(this._children, dojo.hitch(this, function(child, index){
+			
+			var colspan = child.colspan || 1;
+			
+			if(colspan > 1) {
+				colspan = this.showLabels ? 
+					Math.min(maxCols - 1, colspan * 2 -1): Math.min(maxCols, colspan);
+			}
+
+			// Create a new row if we need one
+			if(numCols + colspan - 1 + (this.showLabels ? 1 : 0)>= maxCols) {
+				numCols = 0;
+				labelRow = dojo.create("tr", {}, tbody);
+				childRow = this.orientation == "horiz" ? labelRow : dojo.create("tr", {}, tbody);
+			}
+			var labelCell;
+			
+			// If labels should be visible, add them
+			if(this.showLabels) {
+				labelCell = dojo.create("td", {"class": "tableContainer-labelCell"}, labelRow);
+
+				// If the widget should take up both the label and value,
+				// then just set the class on it.
+				if(child.spanLabel) {
+					dojo.attr(labelCell, this.orientation == "vert" ? "rowspan" : "colspan", 2);
+				}
+				else {
+					// Add the custom label class to the label cell
+					addCustomClass(labelCell, "labelCell");
+					var labelProps = {"for": child.attr("id")};
+					var label = dojo.create("label", labelProps, labelCell);
+
+					if(Number(this.labelWidth) > -1 ||
+						String(this.labelWidth).indexOf("%") > -1) {
+							
+						// Set the width of the label cell with either a pixel or percentage value
+						dojo.style(labelCell, "width", 
+							String(this.labelWidth).indexOf("%") < 0 
+								? this.labelWidth + "px" : this.labelWidth);
+					}
+
+					label.innerHTML = child.attr("label") || child.attr("title");
+				}
+			}
+			var childCell;
+
+			if(child.spanLabel && labelCell) {
+				childCell = labelCell;
+			} else {
+				 childCell = dojo.create("td", {
+				 	"class" : "tableContainer-valueCell"
+				}, childRow);
+			}
+			if(colspan > 1) {
+				dojo.attr(childCell, "colspan", colspan);
+			}
+			
+			// Add the widget cell's custom class, if one exists.
+			addCustomClass(childCell, "valueCell", index);
+
+			childCell.appendChild(child.domNode);
+			numCols += colspan + (this.showLabels ? 1 : 0);
+		}));
+
+		if(this.table)	 {
+			this.table.parentNode.removeChild(this.table);
+		}
+		// Refresh the layout of any child widgets, allowing them to resize
+		// to their new parent.
+		dojo.forEach(children, function(child){
+			if(typeof child.layout == "function") {
+				child.layout();
+			}
+		});
+		this.table = table;
+		this.resize();
+	},
+	
+	destroyDescendants: function(/*Boolean*/ preserveDom){
+		// summary:
+		//      Destroys all the widgets inside this.containerNode,
+		//      but not this widget itself
+		dojo.forEach(this._children, function(child){ child.destroyRecursive(preserveDom); });
+	},
+	
+	_setSpacingAttr: function(value) {
+		// summary: 
+		//		Sets the spacing attribute.
+		this.spacing = value;
+		if(this.table) {
+			this.table.cellspacing = Number(value);
+		}
+	}
 });
-},layout:function(){
-if(!this._initialized){
-return;
-}
-var _6=this.getChildren();
-var _7={};
-var _8=this;
-function _9(_a,_b,_c){
-if(_8.customClass!=""){
-var _d=_8.customClass+"-"+(_b||_a.tagName.toLowerCase());
-dojo.addClass(_a,_d);
-if(arguments.length>2){
-dojo.addClass(_a,_d+"-"+_c);
-}
-}
-};
-dojo.forEach(this._children,dojo.hitch(this,function(_e){
-_7[_e.id]=_e;
-}));
-dojo.forEach(_6,dojo.hitch(this,function(_f,_10){
-if(!_7[_f.id]){
-this._children.push(_f);
-}
-}));
-var _11=dojo.create("table",{"width":"100%","class":"tableContainer-table tableContainer-table-"+this.orientation,"cellspacing":this.spacing},this.domNode);
-var _12=dojo.create("tbody");
-_11.appendChild(_12);
-_9(_11,"table",this.orientation);
-var _13=Math.floor(100/this.cols)+"%";
-var _14=dojo.create("tr",{},_12);
-var _15=(!this.showLabels||this.orientation=="horiz")?_14:dojo.create("tr",{},_12);
-var _16=this.cols*(this.showLabels?2:1);
-var _17=0;
-dojo.forEach(this._children,dojo.hitch(this,function(_18,_19){
-var _1a=_18.colspan||1;
-if(_1a>1){
-_1a=this.showLabels?Math.min(_16-1,_1a*2-1):Math.min(_16,_1a);
-}
-if(_17+_1a-1+(this.showLabels?1:0)>=_16){
-_17=0;
-_14=dojo.create("tr",{},_12);
-_15=this.orientation=="horiz"?_14:dojo.create("tr",{},_12);
-}
-var _1b;
-if(this.showLabels){
-_1b=dojo.create("td",{"class":"tableContainer-labelCell"},_14);
-if(_18.spanLabel){
-dojo.attr(_1b,this.orientation=="vert"?"rowspan":"colspan",2);
-}else{
-_9(_1b,"labelCell");
-var _1c={"for":_18.attr("id")};
-var _1d=dojo.create("label",_1c,_1b);
-if(Number(this.labelWidth)>-1||String(this.labelWidth).indexOf("%")>-1){
-dojo.style(_1b,"width",String(this.labelWidth).indexOf("%")<0?this.labelWidth+"px":this.labelWidth);
-}
-_1d.innerHTML=_18.attr("label")||_18.attr("title");
-}
-}
-var _1e;
-if(_18.spanLabel&&_1b){
-_1e=_1b;
-}else{
-_1e=dojo.create("td",{"class":"tableContainer-valueCell"},_15);
-}
-if(_1a>1){
-dojo.attr(_1e,"colspan",_1a);
-}
-_9(_1e,"valueCell",_19);
-_1e.appendChild(_18.domNode);
-_17+=_1a+(this.showLabels?1:0);
-}));
-if(this.table){
-this.table.parentNode.removeChild(this.table);
-}
-dojo.forEach(_6,function(_1f){
-if(typeof _1f.layout=="function"){
-_1f.layout();
-}
+
+// Extend the default widget with both label and title elements, as
+// well as a "spanLabel" attribute.  If a widget
+dojo.extend(dijit._Widget, {
+	// label: String
+	//		The label to display for a given widget
+	label: "",
+	
+	// title: String
+	//		The label to display for a given widget.  This is interchangeable
+	//		with the 'label' parameter, as some widgets already have a use
+	//		for the 'label', and this can be used instead to avoid conflicts.
+	title: "",
+	
+	// spanLabel: Boolean
+	//		Setting spanLabel to true makes the widget take up both the
+	//		label and value cells. Defaults to false.
+	spanLabel: false,
+	
+	// colspan: Number
+	//		The number of columns this widget should span.
+	colspan: 1
 });
-this.table=_11;
-this.resize();
-},_setSpacingAttr:function(_20){
-this.spacing=_20;
-if(this.table){
-this.table.cellspacing=Number(_20);
-}
-}});
-dojo.extend(dijit._Widget,{label:"",title:"",spanLabel:false,colspan:1});
-}
diff --git a/dojox/layout/ToggleSplitter.js b/dojox/layout/ToggleSplitter.js
index c11535d..0a9337c 100644
--- a/dojox/layout/ToggleSplitter.js
+++ b/dojox/layout/ToggleSplitter.js
@@ -1,131 +1,261 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.ToggleSplitter"]){
-dojo._hasResource["dojox.layout.ToggleSplitter"]=true;
 dojo.provide("dojox.layout.ToggleSplitter");
-dojo.experimental("dojox.layout.ToggleSplitter");
+dojo.experimental("dojox.layout.ToggleSplitter"); 
+
 dojo.require("dijit.layout.BorderContainer");
-dojo.declare("dojox.layout.ToggleSplitter",[dijit.layout._Splitter],{open:true,closedThreshold:5,openSize:"",_closedSize:"0",templateString:"<div class=\"dijitSplitter dojoxToggleSplitter\" dojoAttachEvent=\"onkeypress:_onKeyPress,onmousedown:_onMouseDown\" tabIndex=\"0\" waiRole=\"separator\"><div dojoAttachPoint=\"toggleNode\" class=\"dijitSplitterThumb dojoxToggleSplitterIcon\"></div></div>",postCreate:function(){
-this._started=false;
-this.inherited(arguments);
-var _1=this.region;
-dojo.addClass(this.domNode,"dojoxToggleSplitter"+_1.charAt(0).toUpperCase()+_1.substring(1));
-this.connect(this,"onDblClick","_toggleMe");
-},startup:function(){
-this.inherited(arguments);
-var _2=this.child.domNode,_3=dojo.style(_2,(this.horizontal?"height":"width"));
-dojo.forEach(["toggleSplitterOpen","toggleSplitterClosedThreshold","toggleSplitterOpenSize"],function(_4){
-var _5=_4.substring("toggleSplitter".length);
-_5=_5.charAt(0).toLowerCase()+_5.substring(1);
-if(_4 in this.child){
-this[_5]=this.child[_4];
-}
-},this);
-if(!this.openSize){
-this.openSize=(this.open)?_3+"px":"75px";
-}
-this._openStyleProps=this._getStyleProps(_2,true);
-this._started=true;
-this.attr("open",this.open);
-return this;
-},_onMouseUp:function(_6){
-dojo.disconnect(this._onMoveHandle);
-dojo.disconnect(this._onUpHandle);
-delete this._onMoveHandle;
-delete this._onUpHandle;
-delete this._startPosn;
-},_onPrelimMouseMove:function(_7){
-var _8=this._startPosn||0;
-var _9=3;
-var _a=Math.abs(_8-(this.horizontal?_7.clientY:_7.clientX));
-if(_a>=_9){
-dojo.disconnect(this._onMoveHandle);
-this._startDrag(_7);
-}
-},_onMouseDown:function(_b){
-if(!this.open){
-return;
-}
-if(!this._onUpHandle){
-this._onUpHandle=dojo.connect(dojo.body(),"onmouseup",this,"_onMouseUp");
-}
-if(!this._onMoveHandle){
-this._startPosn=this.horizontal?_b.clientY:_b.clientX;
-this._onMoveHandle=dojo.connect(dojo.body(),"onmousemove",this,"_onPrelimMouseMove");
-}
-},_handleOnChange:function(){
-var _c=this.child.domNode,_d,_e=this.horizontal?"height":"width";
-if(this.open){
-var _f=dojo.mixin({display:"block",overflow:"auto",visibility:"visible"},this._openStyleProps);
-_f[_e]=(this._openStyleProps&&this._openStyleProps[_e])?this._openStyleProps[_e]:this.openSize;
-dojo.style(_c,_f);
-this.connect(this.domNode,"onmousedown","_onMouseDown");
-}else{
-var _10=dojo.getComputedStyle(_c);
-_d=this._getStyleProps(_c,true,_10);
-var _11=this._getStyleProps(_c,false,_10);
-this._openStyleProps=_d;
-dojo.style(_c,_11);
-}
-this._setStateClass();
-if(this.container._started){
-this.container._layoutChildren(this.region);
-}
-},_getStyleProps:function(_12,_13,_14){
-if(!_14){
-_14=dojo.getComputedStyle(_12);
-}
-var _15={},dim=this.horizontal?"height":"width";
-_15["overflow"]=(_13)?_14["overflow"]:"hidden";
-_15["visibility"]=(_13)?_14["visibility"]:"hidden";
-_15[dim]=(_13)?_12.style[dim]||_14[dim]:this._closedSize;
-var _16=["Top","Right","Bottom","Left"];
-dojo.forEach(["padding","margin","border"],function(_17){
-for(var i=0;i<_16.length;i++){
-var _18=_17+_16[i];
-if(_17=="border"){
-_17+="Width";
-}
-if(undefined!==_14[_18]){
-_15[_18]=(_13)?_14[_18]:0;
-}
-}
+
+dojo.declare("dojox.layout.ToggleSplitter", [ dijit.layout._Splitter ],
+{
+	// summary: 
+	//		A draggable and toggle-to-close/open spacer between two items in a BorderContainer
+	//
+	// description:
+	// 		Extends the dijit.layout._Splitter to add a toggling behavior
+	// 		on double-click
+	//
+
+/*=====
+	container: null,
+	child: null,
+	region: null,
+=====*/
+
+	// open: Boolean
+	//	the initial and current state of the splitter (and its attached pane)
+	open: true, 
+
+	// closedThreshold: Integer
+	//	how small the attached pane can be before its considered closed
+	closedThreshold: 5,
+
+	// openSize: String
+	//	the css height/width value to apply by default when the attached pane is open
+	openSize: "",
+
+	// _closedSize: String
+	//	the css height/width value to apply by default when the attached pane is closed
+	_closedSize: "0",
+	
+	templateString: '<div class="dijitSplitter dojoxToggleSplitter" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onMouseDown" tabIndex="0" waiRole="separator"><div dojoAttachPoint="toggleNode" class="dijitSplitterThumb dojoxToggleSplitterIcon"></div></div>',
+
+	postCreate: function(){
+		this._started = false; 
+
+		this.inherited(arguments);
+		
+		// add a region css hook
+		var region = this.region; 
+		dojo.addClass(this.domNode, "dojoxToggleSplitter"+region.charAt(0).toUpperCase() + region.substring(1));
+
+		// hook up double-clicks to toggle the splitter - 
+		this.connect(this, "onDblClick", "_toggleMe");
+
+	}, 
+	startup: function(){
+		this.inherited(arguments);
+
+		// we have to wait until startup to be sure the child exists in the dom
+		// and has non-zero size (if its supposed to be showing)
+		var paneNode = this.child.domNode, 
+			intPaneSize = dojo.style(paneNode, (this.horizontal ? "height" : "width"));
+		
+		// creation of splitters is an opaque process in BorderContainer, 
+		// so if we want to get init params, we have to retrieve them from the attached BC child
+		// NOTE: for this to work we have to extend the prototype of dijit._Widget (some more)
+		dojo.forEach(["toggleSplitterOpen", "toggleSplitterClosedThreshold", "toggleSplitterOpenSize"], function(name){
+			var pname = name.substring("toggleSplitter".length);
+			pname = pname.charAt(0).toLowerCase() + pname.substring(1);
+			if(name in this.child){
+				this[pname] = this.child[name];
+			}
+		}, this);
+
+		if(!this.openSize){
+			// store the current size as the openSize if none was provided
+
+			// dojo.style always returns a integer (pixel) value for height/width
+			// use an arbirary default if a pane was initalized closed and no openSize provided
+			this.openSize = (this.open) ? intPaneSize + "px" : "75px";
+		}
+		this._openStyleProps = this._getStyleProps(paneNode, true);
+
+		// update state
+		this._started = true; 
+		this.set("open", this.open);
+
+		return this;
+	},
+	_onMouseUp: function(evt){
+		dojo.disconnect(this._onMoveHandle);
+		dojo.disconnect(this._onUpHandle);
+		delete this._onMoveHandle; 
+		delete this._onUpHandle;
+		delete this._startPosn; 
+	},
+	_onPrelimMouseMove: function(evt){
+		// only start dragging when a mouse down AND a significant mousemove occurs
+		var startPosn = this._startPosn || 0;
+		// allow a little fudging in a click before we consider a drag started
+		var dragThreshold = 3; 
+		var offset = Math.abs( startPosn - (this.horizontal ? evt.clientY : evt.clientX) );
+		if(offset >= dragThreshold){
+			// treat as a drag and dismantle this preliminary handlers
+			dojo.disconnect(this._onMoveHandle);
+			this._startDrag(evt);
+		}
+	},
+	_onMouseDown: function(evt){
+		// summary: 
+		// 	handle mousedown events from the domNode
+		if(!this.open){
+			// ignore mousedown while closed 
+			// - this has the effect of preventing dragging while closed, which is the prefered behavior (for now)
+			return; 
+		}
+		// Mousedown can fire more than once (!)
+		// ..so check before connecting
+		if(!this._onUpHandle){
+			this._onUpHandle = dojo.connect(dojo.body(), "onmouseup", this, "_onMouseUp");
+		}
+		if(!this._onMoveHandle){
+			this._startPosn = this.horizontal ? evt.clientY : evt.clientX; 
+			// start listening for mousemove
+			this._onMoveHandle = dojo.connect(dojo.body(), "onmousemove", this, "_onPrelimMouseMove");
+		}
+	}, 
+	_handleOnChange: function(){
+		// summary
+		// 	effect the state change with the new value of this.open
+
+		// TODO: animate the open/close
+		
+		var paneNode = this.child.domNode, 
+			openProps,
+			dim = this.horizontal ? "height" : "width"; 
+
+		if(this.open){
+			// change to open state
+			var styleProps = dojo.mixin({
+				display: "block", 
+				overflow: "auto",
+				visibility: "visible"
+			}, this._openStyleProps);
+
+			styleProps[dim] = (this._openStyleProps && this._openStyleProps[dim]) ? this._openStyleProps[dim] : this.openSize;
+			dojo.style(paneNode, styleProps);
+			
+			// and re-hook up the mouse event handler
+			this.connect(this.domNode, "onmousedown", "_onMouseDown");
+
+		} else {
+			// change to closed state
+			// FIXME: this wont work in a drag-to-closed scenario
+			var paneStyle  = dojo.getComputedStyle(paneNode); 
+			
+			openProps = this._getStyleProps(paneNode, true, paneStyle);
+			var closedProps = this._getStyleProps(paneNode, false, paneStyle);
+
+			this._openStyleProps = openProps;
+			dojo.style(paneNode, closedProps);
+		}
+		this._setStateClass();
+		if(this.container._started){
+			this.container._layoutChildren(this.region);
+		}
+	},
+	
+	_getStyleProps: function(paneNode, open, paneStyle){
+		// summary: 
+		//	create an object with the style property name: values 
+		// 	that will need to be applied to the child pane render the given state
+		if(!paneStyle){
+			paneStyle  = dojo.getComputedStyle(paneNode);
+		}
+		var styleProps = {}, 
+			dim = this.horizontal ? "height" : "width";
+			
+		styleProps["overflow"] = (open) ? paneStyle["overflow"] : "hidden";
+		styleProps["visibility"] = (open) ? paneStyle["visibility"] : "hidden";
+
+		// use the inline width/height style value, in preference to the computedStyle
+		// for the open width/height
+		styleProps[dim] = (open) ? paneNode.style[dim] || paneStyle[dim] : this._closedSize;
+
+		// We include the padding,border,margin width values for restoring on open
+		var edgeNames = ["Top", "Right", "Bottom", "Left"];
+		dojo.forEach(["padding","margin","border"], function(pname){
+			for(var i=0; i<edgeNames.length; i++){
+				var fullname = pname+edgeNames[i]; 
+				if(pname=="border"){
+					pname+="Width";
+				}
+				if(undefined !== paneStyle[fullname]){
+					styleProps[fullname] = (open) ? 
+						paneStyle[fullname] : 0;
+				}
+			}
+		});
+		return styleProps;
+	},
+	
+	_setStateClass: function(){
+		// sumamry: 
+		//	apply the appropriate classes for the current open state
+		if(this.open){
+			dojo.removeClass(this.domNode, "dojoxToggleSplitterClosed");
+			dojo.addClass(this.domNode, "dojoxToggleSplitterOpen");
+			dojo.removeClass(this.toggleNode, "dojoxToggleSplitterIconClosed");
+			dojo.addClass(this.toggleNode, "dojoxToggleSplitterIconOpen");
+		} else {
+			dojo.addClass(this.domNode, "dojoxToggleSplitterClosed");
+			dojo.removeClass(this.domNode, "dojoxToggleSplitterOpen");
+			dojo.addClass(this.toggleNode, "dojoxToggleSplitterIconClosed");
+			dojo.removeClass(this.toggleNode, "dojoxToggleSplitterIconOpen");
+		}
+	},
+	_setOpenAttr: function(/*Boolean*/ value){
+		// summary: 
+		// 	setter for the open property
+		if(!this._started) {
+			return; 
+		}
+		this.open = value;
+		this._handleOnChange(value, true);
+		var evt = this.open ? "onOpen" : "onClose";
+		this[evt](this.child);
+	},
+	onOpen: function(){
+		// stub
+	},
+	onClose: function(){
+		// stub
+	},
+
+	_toggleMe: function(evt){
+		// summary: 
+		// 	event handle, toggle the open state
+		if(evt){
+			dojo.stopEvent(evt);
+		}
+		this.set("open", !this.open);
+	},
+
+	_onKeyPress: function(/*Event*/ e){
+		this.inherited(arguments); 
+		// TODO: add support for space, enter to cause toggle
+	}
+
 });
-return _15;
-},_setStateClass:function(){
-if(this.open){
-dojo.removeClass(this.domNode,"dojoxToggleSplitterClosed");
-dojo.addClass(this.domNode,"dojoxToggleSplitterOpen");
-dojo.removeClass(this.toggleNode,"dojoxToggleSplitterIconClosed");
-dojo.addClass(this.toggleNode,"dojoxToggleSplitterIconOpen");
-}else{
-dojo.addClass(this.domNode,"dojoxToggleSplitterClosed");
-dojo.removeClass(this.domNode,"dojoxToggleSplitterOpen");
-dojo.addClass(this.toggleNode,"dojoxToggleSplitterIconClosed");
-dojo.removeClass(this.toggleNode,"dojoxToggleSplitterIconOpen");
-}
-},_setOpenAttr:function(_19){
-if(!this._started){
-return;
-}
-this.open=_19;
-this._handleOnChange(_19,true);
-var evt=this.open?"onOpen":"onClose";
-this[evt](this.child);
-},onOpen:function(){
-},onClose:function(){
-},_toggleMe:function(evt){
-if(evt){
-dojo.stopEvent(evt);
-}
-this.attr("open",!this.open);
-},_onKeyPress:function(e){
-this.inherited(arguments);
-}});
-dojo.extend(dijit._Widget,{toggleSplitterOpen:true,toggleSplitterClosedThreshold:5,toggleSplitterOpenSize:""});
-}
+
+// As BC places no constraints on what kind of widgets can be children
+// we have to extend the base class to ensure the properties we need can be set (both in markup and programatically)
+dojo.extend(dijit._Widget, {
+	// toggleSplitterOpen: Boolean
+	toggleSplitterOpen: true, 
+	
+	// toggleSplitterClosedThreshold: Integer
+	toggleSplitterClosedThreshold: 5, 
+
+	// toggleSplitterClosedThreshold: String
+	// 		a css size value (e.g. "100px")
+	toggleSplitterOpenSize: ""
+});
\ No newline at end of file
diff --git a/dojox/layout/dnd/Avatar.js b/dojox/layout/dnd/Avatar.js
index 43bcca9..be57902 100644
--- a/dojox/layout/dnd/Avatar.js
+++ b/dojox/layout/dnd/Avatar.js
@@ -1,29 +1,46 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.dnd.Avatar"]){
-dojo._hasResource["dojox.layout.dnd.Avatar"]=true;
 dojo.provide("dojox.layout.dnd.Avatar");
+
 dojo.require("dojo.dnd.Avatar");
 dojo.require("dojo.dnd.common");
-dojo.declare("dojox.layout.dnd.Avatar",dojo.dnd.Avatar,{constructor:function(_1,_2){
-this.opacity=_2||0.9;
-},construct:function(){
-var _3=this.manager.source,_4=_3.creator?_3._normalizedCreator(_3.getItem(this.manager.nodes[0].id).data,"avatar").node:this.manager.nodes[0].cloneNode(true);
-dojo.addClass(_4,"dojoDndAvatar");
-_4.id=dojo.dnd.getUniqueId();
-_4.style.position="absolute";
-_4.style.zIndex=1999;
-_4.style.margin="0px";
-_4.style.width=dojo.marginBox(_3.node).w+"px";
-dojo.style(_4,"opacity",this.opacity);
-this.node=_4;
-},update:function(){
-dojo.toggleClass(this.node,"dojoDndAvatarCanDrop",this.manager.canDropFlag);
-},_generateText:function(){
-}});
-}
+
+dojo.declare("dojox.layout.dnd.Avatar", dojo.dnd.Avatar, {
+	// summary:
+	//      An Object, which represents the object being moved in a GridContainer
+	constructor: function(manager, opacity){
+		this.opacity = opacity || 0.9;
+	},
+
+	construct: function(){
+		// summary:
+		//		A constructor function. it is separate so it can be (dynamically)
+		//		overwritten in case of need.
+		
+		var source = this.manager.source,
+			node = source.creator ?
+				// create an avatar representation of the node
+				source._normalizedCreator(source.getItem(this.manager.nodes[0].id).data, "avatar").node :
+				// or just clone the node and hope it works
+				this.manager.nodes[0].cloneNode(true)
+		;
+
+		dojo.addClass(node, "dojoDndAvatar");
+		
+		node.id = dojo.dnd.getUniqueId();
+		node.style.position = "absolute";
+		node.style.zIndex = 1999;
+		node.style.margin = "0px"
+		node.style.width = dojo.marginBox(source.node).w + "px"
+		
+		// add contructor object params to define it
+		dojo.style(node, "opacity", this.opacity);
+		this.node = node;
+	},
+
+	update: function(){
+		// summary: Updates the avatar to reflect the current DnD state.
+		dojo.toggleClass(this.node, "dojoDndAvatarCanDrop", this.manager.canDropFlag);
+	},
+
+	_generateText: function(){ /* nada. */ }
+
+});
diff --git a/dojox/layout/dnd/PlottedDnd.js b/dojox/layout/dnd/PlottedDnd.js
index 091da4a..3438f7b 100644
--- a/dojox/layout/dnd/PlottedDnd.js
+++ b/dojox/layout/dnd/PlottedDnd.js
@@ -1,401 +1,515 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.dnd.PlottedDnd"]){
-dojo._hasResource["dojox.layout.dnd.PlottedDnd"]=true;
 dojo.provide("dojox.layout.dnd.PlottedDnd");
+
 dojo.require("dojo.dnd.Source");
 dojo.require("dojo.dnd.Manager");
 dojo.require("dojox.layout.dnd.Avatar");
-dojo.declare("dojox.layout.dnd.PlottedDnd",[dojo.dnd.Source],{GC_OFFSET_X:dojo.dnd.manager().OFFSET_X,GC_OFFSET_Y:dojo.dnd.manager().OFFSET_Y,constructor:function(_1,_2){
-this.childBoxes=null;
-this.dropIndicator=new dojox.layout.dnd.DropIndicator("dndDropIndicator","div");
-this.withHandles=_2.withHandles;
-this.handleClasses=_2.handleClasses;
-this.opacity=_2.opacity;
-this.allowAutoScroll=_2.allowAutoScroll;
-this.dom=_2.dom;
-this.singular=true;
-this.skipForm=true;
-this._over=false;
-this.defaultHandleClass="GcDndHandle";
-this.isDropped=false;
-this._timer=null;
-this.isOffset=(_2.isOffset)?true:false;
-this.offsetDrag=(_2.offsetDrag)?_2.offsetDrag:{x:0,y:0};
-this.hideSource=_2.hideSource?_2.hideSource:true;
-this._drop=this.dropIndicator.create();
-},_calculateCoords:function(_3){
-dojo.forEach(this.node.childNodes,function(_4){
-var c=dojo.coords(_4,true);
-_4.coords={xy:c,w:_4.offsetWidth/2,h:_4.offsetHeight/2,mw:c.w};
-if(_3){
-_4.coords.mh=c.h;
-}
-},this);
-},_legalMouseDown:function(e){
-if(!this.withHandles){
-return true;
-}
-for(var _5=(e.target);_5&&_5!=this.node;_5=_5.parentNode){
-if(dojo.hasClass(_5,this.defaultHandleClass)){
-return true;
-}
-}
-return false;
-},setDndItemSelectable:function(_6,_7){
-for(var _8=_6;_8&&_6!=this.node;_8=_8.parentNode){
-if(dojo.hasClass(_8,"dojoDndItem")){
-dojo.setSelectable(_8,_7);
-return;
-}
-}
-},getDraggedWidget:function(_9){
-var _a=_9;
-while(_a&&_a.nodeName.toLowerCase()!="body"&&!dojo.hasClass(_a,"dojoDndItem")){
-_a=_a.parentNode;
-}
-return (_a)?dijit.byNode(_a):null;
-},isAccepted:function(_b){
-var _c=(_b)?_b.getAttribute("dndtype"):null;
-return (_c&&_c in this.accept);
-},onDndStart:function(_d,_e,_f){
-this.firstIndicator=(_d==this);
-this._calculateCoords(true);
-var m=dojo.dnd.manager();
-if(_e[0].coords){
-this._drop.style.height=_e[0].coords.mh+"px";
-dojo.style(m.avatar.node,"width",_e[0].coords.mw+"px");
-}else{
-this._drop.style.height=m.avatar.node.clientHeight+"px";
-}
-this.dndNodes=_e;
-dojox.layout.dnd.PlottedDnd.superclass.onDndStart.call(this,_d,_e,_f);
-if(_d==this&&this.hideSource){
-dojo.forEach(_e,function(n){
-dojo.style(n,"display","none");
-});
-}
-},onDndCancel:function(){
-var m=dojo.dnd.manager();
-if(m.source==this&&this.hideSource){
-var _10=this.getSelectedNodes();
-dojo.forEach(_10,function(n){
-dojo.style(n,"display","");
+
+dojo.declare("dojox.layout.dnd.PlottedDnd", [dojo.dnd.Source], {
+	// summary:
+	//		dnd source handling plotted zone to show the dropping area
+	GC_OFFSET_X: dojo.dnd.manager().OFFSET_X,
+	GC_OFFSET_Y: dojo.dnd.manager().OFFSET_Y,
+	
+	constructor: function(/*Node*/node, /*Object*/params){
+		
+		this.childBoxes 		= null;
+		this.dropIndicator		= new dojox.layout.dnd.DropIndicator("dndDropIndicator", "div");
+		this.withHandles 		= params.withHandles;
+		this.handleClasses	 	= params.handleClasses;
+		this.opacity 			= params.opacity;
+		this.allowAutoScroll	= params.allowAutoScroll;//MODIF MYS
+		this.dom                = params.dom;
+		this.singular			= true;
+		this.skipForm 			= true;
+		this._over 				= false;
+		this.defaultHandleClass = "GcDndHandle";
+		this.isDropped			= false;
+		this._timer				= null;
+		//Initialize the params to calculate offset
+  		this.isOffset = (params.isOffset)?true:false;
+  		this.offsetDrag = (params.offsetDrag) ? params.offsetDrag : {x:0,y:0};
+		this.hideSource = params.hideSource ? params.hideSource : true;  
+		this._drop = this.dropIndicator.create();
+		
+	},
+	
+	_calculateCoords : function(/*Boolean*/height){
+		// summary: Calculate each position of children
+		dojo.forEach(this.node.childNodes, function(child){
+			var c = dojo.coords(child, true);
+			child.coords = {
+				xy: c,
+				w: child.offsetWidth / 2,
+				h: child.offsetHeight / 2,
+				mw: c.w
+			};
+			if(height){
+				child.coords.mh = c.h;
+			}
+		}, this);
+	},
+	
+	_legalMouseDown: function(/*Event*/e){
+		// summary: Checks if user clicked on "approved" items.
+		if(!this.withHandles){ return true; }
+		for(var node = (e.target); node && node != this.node; node = node.parentNode){
+			if(dojo.hasClass(node, this.defaultHandleClass)){
+				return true;	
+			}
+		}
+		return false;	// Boolean
+	},
+	
+	setDndItemSelectable: function(/*Node*/node, /*Boolean*/isSelectable) {
+		// summary: set an item as selectable	
+		for(var _node = node; _node && node != this.node; _node = _node.parentNode) {
+			if (dojo.hasClass(_node,"dojoDndItem")) {
+				dojo.setSelectable(_node, isSelectable);
+				return;
+			}
+		}	
+	},
+	
+	getDraggedWidget: function(/*Node*/node) {
+		// summary: Return one or more widget selected during the drag.
+		var _node = node;
+		while (_node && _node.nodeName.toLowerCase()!="body" && !dojo.hasClass(_node,"dojoDndItem")) {
+			_node = _node.parentNode;
+		}
+		return (_node) ? dijit.byNode(_node) : null;
+	},
+	
+	isAccepted: function(/*Node*/ node) {
+		// summary: test if this node can be accepted	
+		var _dndType = (node) ? node.getAttribute("dndtype") : null;
+		return (_dndType && _dndType in this.accept);
+	},
+	
+	onDndStart:function(/*Object*/source, /*Array*/nodes, /*Object*/copy){
+		// summary: Called to initiate the DnD operation.
+
+		this.firstIndicator = (source == this);
+		this._calculateCoords(true);
+		//this.isDropped = true;
+		var m = dojo.dnd.manager();
+		if(nodes[0].coords){
+			this._drop.style.height = nodes[0].coords.mh + "px";
+			dojo.style(m.avatar.node, "width", nodes[0].coords.mw + "px");
+		}else{
+			this._drop.style.height = m.avatar.node.clientHeight+"px";
+		}
+		this.dndNodes = nodes;
+		dojox.layout.dnd.PlottedDnd.superclass.onDndStart.call(this,source, nodes, copy);
+		if(source == this && this.hideSource){
+			dojo.forEach(nodes, function(n){
+				dojo.style(n, "display","none");
+			});
+		}
+			
+	},
+
+	onDndCancel:function(){
+		// summary: Called to cancel the DnD operation.	
+		var m = dojo.dnd.manager();
+		if(m.source == this && this.hideSource){
+			var nodes = this.getSelectedNodes();
+			dojo.forEach(nodes, function(n){
+				dojo.style(n, "display","");
+			});
+		}
+		dojox.layout.dnd.PlottedDnd.superclass.onDndCancel.call(this);
+		this.deleteDashedZone();
+	},
+	
+	onDndDrop: function(source,nodes,copy,target) {
+		// summary: Called to finish the DnD operation	
+		try{
+			if(!this.isAccepted(nodes[0])){ 
+				this.onDndCancel();
+			}else{
+				if(source == this && this._over && this.dropObject){ 
+					this.current = this.dropObject.c;
+				}
+				dojox.layout.dnd.PlottedDnd.superclass.onDndDrop.call(this, source, nodes, copy, target);
+				this._calculateCoords(true);
+			}
+		}catch(e){
+			console.warn(e);
+		}
+	},
+			
+	onMouseDown: function(/*Event*/e) {
+		// summary: Event processor for onmousedown.	
+		if(this.current == null){
+			this.selection = {};
+		}else{
+			if(this.current == this.anchor){
+				this.anchor = null;
+			}
+		}
+		if(this.current !== null){
+			var c = dojo.coords(this.current, true);
+			this.current.coords = {
+				xy: c,
+				w: this.current.offsetWidth / 2,
+				h: this.current.offsetHeight / 2,
+				mh: c.h,
+				mw: c.w
+			};
+			this._drop.style.height = this.current.coords.mh + "px";
+			
+			if(this.isOffset){
+				if(this.offsetDrag.x == 0 && this.offsetDrag.y == 0){
+					var NoOffsetDrag = true;
+					var coords = dojo.coords(this._getChildByEvent(e));
+					this.offsetDrag.x = coords.x - e.pageX;
+					this.offsetDrag.y = coords.y - e.clientY;
+				}
+				if(this.offsetDrag.y < 16 && this.current != null){ 
+					this.offsetDrag.y = this.GC_OFFSET_Y;
+				}
+
+				var m = dojo.dnd.manager();
+				m.OFFSET_X = this.offsetDrag.x;
+				m.OFFSET_Y = this.offsetDrag.y;
+				if (NoOffsetDrag) {
+					this.offsetDrag.x = 0;
+					this.offsetDrag.y = 0;
+				}
+			}
+		}
+		
+		if(dojo.dnd.isFormElement(e)){ 
+			this.setDndItemSelectable(e.target,true);
+		}else{
+			this.containerSource = true;
+			var _draggedWidget = this.getDraggedWidget(e.target);
+			if(_draggedWidget && _draggedWidget.dragRestriction){
+			// FIXME: not clear what this was supposed to mean ... this code needs more cleanups. 
+			//	dragRestriction = true;
+			}else{
+				dojox.layout.dnd.PlottedDnd.superclass.onMouseDown.call(this,e);
+			}
+		}
+	},
+
+	onMouseUp: function(/*Event*/e) {
+		// summary: Event processor for onmouseup.	
+		dojox.layout.dnd.PlottedDnd.superclass.onMouseUp.call(this,e);
+		this.containerSource = false;
+		if (!dojo.isIE && this.mouseDown){
+			this.setDndItemSelectable(e.target,true);
+		}
+		var m = dojo.dnd.manager();
+		m.OFFSET_X = this.GC_OFFSET_X;
+		m.OFFSET_Y = this.GC_OFFSET_Y;
+	},
+	
+	onMouseMove: function(e) {
+		// summary: Event processor for onmousemove	
+		var m = dojo.dnd.manager();
+		if(this.isDragging) {
+			var before = false;
+			if(this.current != null || (this.current == null && !this.dropObject)){
+				if(this.isAccepted(m.nodes[0]) || this.containerSource){
+					before = this.setIndicatorPosition(e);
+				}
+			}
+			if(this.current != this.targetAnchor || before != this.before){
+				this._markTargetAnchor(before);
+				m.canDrop(!this.current || m.source != this || !(this.current.id in this.selection));
+			}
+
+			if(this.allowAutoScroll){
+				this._checkAutoScroll(e);
+			}
+		}else{
+			if(this.mouseDown && this.isSource){
+				var nodes = this.getSelectedNodes();
+				if(nodes.length){
+					m.startDrag(this, nodes, this.copyState(dojo.isCopyKey(e)));
+				}
+			}
+
+			if(this.allowAutoScroll){ 
+				this._stopAutoScroll();
+			}
+		}		
+	},
+	
+	_markTargetAnchor: function(/*Boolean*/before){
+		// summary: Assigns a class to the current target anchor based on "before" status	
+		if(this.current == this.targetAnchor && this.before == before){ return; }
+		this.targetAnchor = this.current;
+		this.targetBox = null;
+		this.before = before;
+	},
+	
+	_unmarkTargetAnchor: function(){
+		// summary: Removes a class of the current target anchor based on "before" status.	
+		if(!this.targetAnchor){ return; }
+		this.targetAnchor = null;
+		this.targetBox = null;
+		this.before = true;
+	},
+	
+	setIndicatorPosition: function(/*Event*/e) {
+		// summary: set the position of the drop indicator
+		var before = false;
+		if(this.current){
+			if (!this.current.coords || this.allowAutoScroll) {
+				this.current.coords = {
+					xy: dojo.coords(this.current, true),
+					w: this.current.offsetWidth / 2,
+					h: this.current.offsetHeight / 2
+				};
+			}
+			before = this.horizontal ? 
+				(e.pageX - this.current.coords.xy.x) < this.current.coords.w :
+				(e.pageY - this.current.coords.xy.y) < this.current.coords.h
+			this.insertDashedZone(before);	
+		}else{
+			if(!this.dropObject /*|| dojo.isIE*/){ this.insertDashedZone(false); }
+		}
+		return before;
+	},
+	
+
+	onOverEvent:function(){
+		this._over = true;
+		dojox.layout.dnd.PlottedDnd.superclass.onOverEvent.call(this);
+		if (this.isDragging) {
+			var m = dojo.dnd.manager();
+			if (!this.current && !this.dropObject && this.getSelectedNodes()[0] && this.isAccepted(m.nodes[0]))
+				this.insertDashedZone(false);
+		}
+	},
+	
+	onOutEvent: function() {
+		this._over = false;
+		this.containerSource = false;
+		dojox.layout.dnd.PlottedDnd.superclass.onOutEvent.call(this);
+		if (this.dropObject) this.deleteDashedZone();
+	},
+	
+	deleteDashedZone: function() {
+		// summary: hide the dashed zone
+		this._drop.style.display = "none";
+			var next = this._drop.nextSibling;
+			while (next != null) {
+				next.coords.xy.y -= parseInt(this._drop.style.height);
+				next = next.nextSibling;
+			}
+		delete this.dropObject;
+	},
+	
+	insertDashedZone: function(/*Boolean*/before) {
+		// summary: Insert the dashed zone at the right place 
+		if(this.dropObject){
+			if( before == this.dropObject.b && 
+				((this.current && this.dropObject.c == this.current.id) || 
+				(!this.current && !this.dropObject.c))
+			){
+				return;
+			}else{
+				this.deleteDashedZone();
+			}
+		}
+		this.dropObject = { n: this._drop, c: this.current ? this.current.id : null, b: before};
+		if(this.current){
+			dojo.place(this._drop, this.current, before ? "before" : "after");
+			if(!this.firstIndicator){
+				var next = this._drop.nextSibling;
+				while(next != null){
+					next.coords.xy.y += parseInt(this._drop.style.height);
+					next = next.nextSibling;
+				}
+			}else{
+				this.firstIndicator = false;
+			}
+		}else{ 
+			this.node.appendChild(this._drop);
+		}
+		this._drop.style.display = "";
+	},
+	
+	insertNodes: function(/*Boolean*/addSelected, /*Array*/data, /*Boolean*/before, /*Node*/anchor){
+		// summary: Inserts new data items (see Dojo Container's insertNodes method for details).	
+		if(this.dropObject){
+			dojo.style(this.dropObject.n,"display","none");
+			dojox.layout.dnd.PlottedDnd.superclass.insertNodes.call(this,true,data,true,this.dropObject.n);
+			this.deleteDashedZone();
+		}else{
+			 return dojox.layout.dnd.PlottedDnd.superclass.insertNodes.call(this,addSelected,data,before,anchor);
+		}
+		var _widget = dijit.byId(data[0].getAttribute("widgetId"));
+		if (_widget) {
+			dojox.layout.dnd._setGcDndHandle(_widget, this.withHandles, this.handleClasses);
+			if(this.hideSource)
+				dojo.style(_widget.domNode, "display", "");
+		}
+	},
+	
+	_checkAutoScroll: function(e){
+		if(this._timer){
+			clearTimeout(this._timer);
+		}
+		this._stopAutoScroll();
+		var node = this.dom, 
+			y = this._sumAncestorProperties(node,"offsetTop")
+		;
+		//Down
+		if( (e.pageY - node.offsetTop +30 ) > node.clientHeight ){
+			this.autoScrollActive = true;
+			this._autoScrollDown(node);
+		} else if ( (node.scrollTop > 0) && (e.pageY - y) < 30){
+			//Up
+			this.autoScrollActive = true;
+			this._autoScrollUp(node);
+		}
+	},
+
+	_autoScrollUp: function(node){
+		if( this.autoScrollActive && node.scrollTop > 0) {
+			node.scrollTop -= 30;
+			this._timer = setTimeout(dojo.hitch(this,"_autoScrollUp",node), 100);
+		}
+	},
+
+	_autoScrollDown: function(node){
+		if( this.autoScrollActive && (node.scrollTop < (node.scrollHeight-node.clientHeight))){
+			node.scrollTop += 30;
+			this._timer = setTimeout(dojo.hitch(this, "_autoScrollDown",node), 100);
+		}
+	},
+
+	_stopAutoScroll: function(){
+		this.autoScrollActive = false;
+	},
+
+	_sumAncestorProperties: function(node, prop){
+		//	summary
+		//	Returns the sum of the passed property on all ancestors of node.
+		node = dojo.byId(node);
+		if(!node){ return 0; }
+		
+		var retVal = 0;
+		while(node){
+			var val = node[prop];
+			if(val){
+				retVal += val - 0;
+				if(node == dojo.body()){ break; }// opera and khtml #body & #html has the same values, we only need one value
+			}
+			node = node.parentNode;
+		}
+		return retVal;	//	integer
+	}
+	
 });
-}
-dojox.layout.dnd.PlottedDnd.superclass.onDndCancel.call(this);
-this.deleteDashedZone();
-},onDndDrop:function(_11,_12,_13,_14){
-try{
-if(!this.isAccepted(_12[0])){
-this.onDndCancel();
-}else{
-if(_11==this&&this._over&&this.dropObject){
-this.current=this.dropObject.c;
-}
-dojox.layout.dnd.PlottedDnd.superclass.onDndDrop.call(this,_11,_12,_13,_14);
-this._calculateCoords(true);
-}
-}
-catch(e){
-console.warn(e);
-}
-},onMouseDown:function(e){
-if(this.current==null){
-this.selection={};
-}else{
-if(this.current==this.anchor){
-this.anchor=null;
-}
-}
-if(this.current!==null){
-var c=dojo.coords(this.current,true);
-this.current.coords={xy:c,w:this.current.offsetWidth/2,h:this.current.offsetHeight/2,mh:c.h,mw:c.w};
-this._drop.style.height=this.current.coords.mh+"px";
-if(this.isOffset){
-if(this.offsetDrag.x==0&&this.offsetDrag.y==0){
-var _15=true;
-var _16=dojo.coords(this._getChildByEvent(e));
-this.offsetDrag.x=_16.x-e.pageX;
-this.offsetDrag.y=_16.y-e.clientY;
-}
-if(this.offsetDrag.y<16&&this.current!=null){
-this.offsetDrag.y=this.GC_OFFSET_Y;
-}
-var m=dojo.dnd.manager();
-m.OFFSET_X=this.offsetDrag.x;
-m.OFFSET_Y=this.offsetDrag.y;
-if(_15){
-this.offsetDrag.x=0;
-this.offsetDrag.y=0;
-}
-}
-}
-if(dojo.dnd.isFormElement(e)){
-this.setDndItemSelectable(e.target,true);
-}else{
-this.containerSource=true;
-var _17=this.getDraggedWidget(e.target);
-if(_17&&_17.dragRestriction){
-}else{
-dojox.layout.dnd.PlottedDnd.superclass.onMouseDown.call(this,e);
-}
-}
-},onMouseUp:function(e){
-dojox.layout.dnd.PlottedDnd.superclass.onMouseUp.call(this,e);
-this.containerSource=false;
-if(!dojo.isIE&&this.mouseDown){
-this.setDndItemSelectable(e.target,true);
-}
-var m=dojo.dnd.manager();
-m.OFFSET_X=this.GC_OFFSET_X;
-m.OFFSET_Y=this.GC_OFFSET_Y;
-},onMouseMove:function(e){
-var m=dojo.dnd.manager();
-if(this.isDragging){
-var _18=false;
-if(this.current!=null||(this.current==null&&!this.dropObject)){
-if(this.isAccepted(m.nodes[0])||this.containerSource){
-_18=this.setIndicatorPosition(e);
-}
-}
-if(this.current!=this.targetAnchor||_18!=this.before){
-this._markTargetAnchor(_18);
-m.canDrop(!this.current||m.source!=this||!(this.current.id in this.selection));
-}
-if(this.allowAutoScroll){
-this._checkAutoScroll(e);
-}
-}else{
-if(this.mouseDown&&this.isSource){
-var _19=this.getSelectedNodes();
-if(_19.length){
-m.startDrag(this,_19,this.copyState(dojo.isCopyKey(e)));
-}
-}
-if(this.allowAutoScroll){
-this._stopAutoScroll();
-}
-}
-},_markTargetAnchor:function(_1a){
-if(this.current==this.targetAnchor&&this.before==_1a){
-return;
-}
-this.targetAnchor=this.current;
-this.targetBox=null;
-this.before=_1a;
-},_unmarkTargetAnchor:function(){
-if(!this.targetAnchor){
-return;
-}
-this.targetAnchor=null;
-this.targetBox=null;
-this.before=true;
-},setIndicatorPosition:function(e){
-var _1b=false;
-if(this.current){
-if(!this.current.coords||this.allowAutoScroll){
-this.current.coords={xy:dojo.coords(this.current,true),w:this.current.offsetWidth/2,h:this.current.offsetHeight/2};
-}
-_1b=this.horizontal?(e.pageX-this.current.coords.xy.x)<this.current.coords.w:(e.pageY-this.current.coords.xy.y)<this.current.coords.h;
-this.insertDashedZone(_1b);
-}else{
-if(!this.dropObject){
-this.insertDashedZone(false);
-}
-}
-return _1b;
-},onOverEvent:function(){
-this._over=true;
-dojox.layout.dnd.PlottedDnd.superclass.onOverEvent.call(this);
-if(this.isDragging){
-var m=dojo.dnd.manager();
-if(!this.current&&!this.dropObject&&this.getSelectedNodes()[0]&&this.isAccepted(m.nodes[0])){
-this.insertDashedZone(false);
-}
-}
-},onOutEvent:function(){
-this._over=false;
-this.containerSource=false;
-dojox.layout.dnd.PlottedDnd.superclass.onOutEvent.call(this);
-if(this.dropObject){
-this.deleteDashedZone();
-}
-},deleteDashedZone:function(){
-this._drop.style.display="none";
-var _1c=this._drop.nextSibling;
-while(_1c!=null){
-_1c.coords.xy.y-=parseInt(this._drop.style.height);
-_1c=_1c.nextSibling;
-}
-delete this.dropObject;
-},insertDashedZone:function(_1d){
-if(this.dropObject){
-if(_1d==this.dropObject.b&&((this.current&&this.dropObject.c==this.current.id)||(!this.current&&!this.dropObject.c))){
-return;
-}else{
-this.deleteDashedZone();
-}
-}
-this.dropObject={n:this._drop,c:this.current?this.current.id:null,b:_1d};
-if(this.current){
-dojo.place(this._drop,this.current,_1d?"before":"after");
-if(!this.firstIndicator){
-var _1e=this._drop.nextSibling;
-while(_1e!=null){
-_1e.coords.xy.y+=parseInt(this._drop.style.height);
-_1e=_1e.nextSibling;
-}
-}else{
-this.firstIndicator=false;
-}
-}else{
-this.node.appendChild(this._drop);
-}
-this._drop.style.display="";
-},insertNodes:function(_1f,_20,_21,_22){
-if(this.dropObject){
-dojo.style(this.dropObject.n,"display","none");
-dojox.layout.dnd.PlottedDnd.superclass.insertNodes.call(this,true,_20,true,this.dropObject.n);
-this.deleteDashedZone();
-}else{
-return dojox.layout.dnd.PlottedDnd.superclass.insertNodes.call(this,_1f,_20,_21,_22);
-}
-var _23=dijit.byId(_20[0].getAttribute("widgetId"));
-if(_23){
-dojox.layout.dnd._setGcDndHandle(_23,this.withHandles,this.handleClasses);
-if(this.hideSource){
-dojo.style(_23.domNode,"display","");
-}
-}
-},_checkAutoScroll:function(e){
-if(this._timer){
-clearTimeout(this._timer);
-}
-this._stopAutoScroll();
-var _24=this.dom,y=this._sumAncestorProperties(_24,"offsetTop");
-if((e.pageY-_24.offsetTop+30)>_24.clientHeight){
-this.autoScrollActive=true;
-this._autoScrollDown(_24);
-}else{
-if((_24.scrollTop>0)&&(e.pageY-y)<30){
-this.autoScrollActive=true;
-this._autoScrollUp(_24);
-}
-}
-},_autoScrollUp:function(_25){
-if(this.autoScrollActive&&_25.scrollTop>0){
-_25.scrollTop-=30;
-this._timer=setTimeout(dojo.hitch(this,"_autoScrollUp",_25),100);
-}
-},_autoScrollDown:function(_26){
-if(this.autoScrollActive&&(_26.scrollTop<(_26.scrollHeight-_26.clientHeight))){
-_26.scrollTop+=30;
-this._timer=setTimeout(dojo.hitch(this,"_autoScrollDown",_26),100);
-}
-},_stopAutoScroll:function(){
-this.autoScrollActive=false;
-},_sumAncestorProperties:function(_27,_28){
-_27=dojo.byId(_27);
-if(!_27){
-return 0;
-}
-var _29=0;
-while(_27){
-var val=_27[_28];
-if(val){
-_29+=val-0;
-if(_27==dojo.body()){
-break;
-}
-}
-_27=_27.parentNode;
-}
-return _29;
-}});
-dojox.layout.dnd._setGcDndHandle=function(_2a,_2b,_2c,_2d){
-var cls="GcDndHandle";
-if(!_2d){
-dojo.query(".GcDndHandle",_2a.domNode).removeClass(cls);
-}
-if(!_2b){
-dojo.addClass(_2a.domNode,cls);
-}else{
-var _2e=false;
-for(var i=_2c.length-1;i>=0;i--){
-var _2f=dojo.query("."+_2c[i],_2a.domNode)[0];
-if(_2f){
-_2e=true;
-if(_2c[i]!=cls){
-var _30=dojo.query("."+cls,_2a.domNode);
-if(_30.length==0){
-dojo.removeClass(_2a.domNode,cls);
-}else{
-_30.removeClass(cls);
-}
-dojo.addClass(_2f,cls);
-}
-}
-}
-if(!_2e){
-dojo.addClass(_2a.domNode,cls);
-}
-}
-};
-dojo.declare("dojox.layout.dnd.DropIndicator",null,{constructor:function(cn,tag){
-this.tag=tag||"div";
-this.style=cn||null;
-},isInserted:function(){
-return (this.node.parentNode&&this.node.parentNode.nodeType==1);
-},create:function(){
-if(this.node&&this.isInserted()){
-return this.node;
-}
-var h="90px",el=dojo.doc.createElement(this.tag);
-if(this.style){
-el.className=this.style;
-el.style.height=h;
-}else{
-dojo.style(el,{position:"relative",border:"1px dashed #F60",margin:"2px",height:h});
-}
-this.node=el;
-return el;
-},destroy:function(){
-if(!this.node||!this.isInserted()){
-return;
-}
-this.node.parentNode.removeChild(this.node);
-this.node=null;
-}});
-dojo.extend(dojo.dnd.Manager,{canDrop:function(_31){
-var _32=this.target&&_31;
-if(this.canDropFlag!=_32){
-this.canDropFlag=_32;
-if(this.avatar){
-this.avatar.update();
-}
-}
-},makeAvatar:function(){
-return (this.source.declaredClass=="dojox.layout.dnd.PlottedDnd")?new dojox.layout.dnd.Avatar(this,this.source.opacity):new dojo.dnd.Avatar(this);
-}});
-if(dojo.isIE){
-dojox.layout.dnd.handdleIE=[dojo.subscribe("/dnd/start",null,function(){
-IEonselectstart=document.body.onselectstart;
-document.body.onselectstart=function(){
-return false;
+
+dojox.layout.dnd._setGcDndHandle = function(service,withHandles,handleClasses, first) {
+	var cls = "GcDndHandle";
+	if(!first){
+		dojo.query(".GcDndHandle", service.domNode).removeClass(cls);
+	}
+	if(!withHandles){
+		dojo.addClass(service.domNode, cls);
+	}else{
+		var _hasHandle = false;
+		for(var i = handleClasses.length - 1; i >= 0; i--){
+			var _node = dojo.query("." + handleClasses[i], service.domNode)[0];
+			if(_node){
+				_hasHandle = true;
+				if(handleClasses[i] != cls){
+					var _gripNode = dojo.query("." + cls, service.domNode);
+					if(_gripNode.length == 0){ 
+						dojo.removeClass(service.domNode, cls);
+					}else{				
+						_gripNode.removeClass(cls);
+					}
+					dojo.addClass(_node, cls);
+				}
+			}
+		}
+		if(!_hasHandle){ 
+			dojo.addClass(service.domNode, cls);
+		}
+	}
 };
-}),dojo.subscribe("/dnd/cancel",null,function(){
-document.body.onselectstart=IEonselectstart;
-}),dojo.subscribe("/dnd/drop",null,function(){
-document.body.onselectstart=IEonselectstart;
-})];
-dojo.addOnWindowUnload(function(){
-dojo.forEach(dojox.layout.dnd.handdleIE,dojo.unsubscribe);
+
+dojo.declare("dojox.layout.dnd.DropIndicator", null, {
+	// summary: An empty widget to show at the user the drop zone of the widget.
+	constructor: function(/*String*/cn, /*String*/tag) {
+		this.tag = tag || "div";
+		this.style = cn || null;
+	},
+
+	isInserted : function(){
+		return (this.node.parentNode && this.node.parentNode.nodeType==1);
+	},
+
+	create : function(/*Node*//*nodeRef*/){
+		if(this.node && this.isInserted()){ return this.node; }
+		var h = "90px",
+			el = dojo.doc.createElement(this.tag);
+			
+		if(this.style){
+			el.className = this.style;
+			el.style.height = h;
+		}else{
+			// FIXME: allow this to be done mostly in CSS?
+			dojo.style(el, {
+				position:"relative",
+				border:"1px dashed #F60",
+				margin:"2px",
+				height: h
+			})
+		}
+		this.node = el;
+		return el;
+	},
+	
+	destroy : function(){
+		if(!this.node || !this.isInserted()){ return; }
+		this.node.parentNode.removeChild(this.node);
+		this.node = null;
+	}
+});
+
+dojo.extend(dojo.dnd.Manager, {
+	
+	canDrop: function(flag){
+		var canDropFlag = this.target && flag;
+		if(this.canDropFlag != canDropFlag){
+			this.canDropFlag = canDropFlag;
+			if(this.avatar){ this.avatar.update(); }
+		}
+		
+	},
+	
+	makeAvatar: function(){
+		//summary: Makes the avatar, it is separate to be overwritten dynamically, if needed.
+		return (this.source.declaredClass == "dojox.layout.dnd.PlottedDnd") ?
+			new dojox.layout.dnd.Avatar(this, this.source.opacity) :
+			new dojo.dnd.Avatar(this)
+		;
+	}
 });
-}
-}
+
+if(dojo.isIE){
+	dojox.layout.dnd.handdleIE = [
+		dojo.subscribe("/dnd/start", null, function(){
+			IEonselectstart = document.body.onselectstart;
+			document.body.onselectstart = function(){ return false; };
+		}),
+		dojo.subscribe("/dnd/cancel", null, function(){
+			document.body.onselectstart = IEonselectstart;
+		}),
+		dojo.subscribe("/dnd/drop", null, function(){
+			document.body.onselectstart = IEonselectstart;
+		})
+	];
+	dojo.addOnWindowUnload(function(){
+		dojo.forEach(dojox.layout.dnd.handdleIE, dojo.unsubscribe);
+	});
+}
\ No newline at end of file
diff --git a/dojox/layout/ext-dijit/layout/StackContainer-touch.js b/dojox/layout/ext-dijit/layout/StackContainer-touch.js
index a1c1f3b..3d67ade 100644
--- a/dojox/layout/ext-dijit/layout/StackContainer-touch.js
+++ b/dojox/layout/ext-dijit/layout/StackContainer-touch.js
@@ -1,47 +1,44 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.layout.ext-dijit.layout.StackContainer-touch"]){
-dojo._hasResource["dojox.layout.ext-dijit.layout.StackContainer-touch"]=true;
 dojo.provide("dojox.layout.ext-dijit.layout.StackContainer-touch");
 dojo.experimental("dojox.layout.ext-dijit.layout.StackContainer-touch");
 dojo.require("dijit.layout.StackContainer");
-dojo.connect(dijit.layout.StackContainer.prototype,"postCreate",function(){
-this.axis=(this.baseClass=="dijitAccordionContainer")?"Y":"X";
-dojo.forEach(["touchstart","touchmove","touchend","touchcancel"],function(p){
-this.connect(this.domNode,p,function(e){
-switch(e.type){
-case "touchmove":
-e.preventDefault();
-if(this.touchPosition){
-var _1=e.touches[0]["page"+this.axis]-this.touchPosition;
-if(Math.abs(_1)>100){
-if(this.axis=="Y"){
-_1*=-1;
-}
-delete this.touchPosition;
-if(_1>0){
-!this.selectedChildWidget.isLastChild&&this.forward();
-}else{
-!this.selectedChildWidget.isFirstChild&&this.back();
-}
-}
-}
-break;
-case "touchstart":
-if(e.touches.length==1){
-this.touchPosition=e.touches[0]["page"+this.axis];
-break;
-}
-case "touchend":
-case "touchcancel":
-delete this.touchPosition;
-}
-});
-},this);
+
+// To support "flick" actions on iPhone, iPod Touch, etc.
+// Implemented as a mixin to work with StackContainer (horizontal) and AccordionContainer (vertical)
+// TODO: use native CSS animations for fx, provide live tracking of touch and perhaps a 'bounce' effect.
+
+dojo.connect(dijit.layout.StackContainer.prototype, "postCreate", function(){
+	this.axis = (this.baseClass == "dijitAccordionContainer") ? "Y" : "X";
+	dojo.forEach(
+		["touchstart", "touchmove", "touchend", "touchcancel"],
+		function(p){
+			this.connect(this.domNode, p, function(e){
+				switch(e.type){
+					case "touchmove":
+						e.preventDefault();
+						if(this.touchPosition){
+							var delta = e.touches[0]["page" + this.axis] - this.touchPosition;
+							if(Math.abs(delta) > 100){
+								if(this.axis == "Y"){ delta *= -1;}
+								delete this.touchPosition;
+								if(delta > 0){
+									!this.selectedChildWidget.isLastChild && this.forward();
+								}else{
+									!this.selectedChildWidget.isFirstChild && this.back();
+								}
+							}
+						}
+						break;
+					case "touchstart":
+						if(e.touches.length == 1){
+							this.touchPosition = e.touches[0]["page" + this.axis];
+							break;
+						}
+					// else fallthrough
+					case "touchend":
+					case "touchcancel":
+						delete this.touchPosition;
+				}
+			});
+		},
+		this);
 });
-}
diff --git a/dojox/layout/resources/DndGridContainer.css b/dojox/layout/resources/DndGridContainer.css
index 46d8126..1d42d20 100644
--- a/dojox/layout/resources/DndGridContainer.css
+++ b/dojox/layout/resources/DndGridContainer.css
@@ -1,4 +1,5 @@
-
+/**********************************dojox.layout.dnd************************************/
+/* item-specific settings */
 .dojoDndItemOver		{background-color: #feb !important;}
 .dojoDndItemSelected	{background: #ccf; color: #444;}
 .dojoDndItemBefore		{border-top:    3px solid red;}
@@ -6,5 +7,7 @@
 .dojoDndItemAnchor		{background: #ccf; color: black;}
 .dojoDndItemOver.dojoDndItemSelected	{background: #ec8;}
 .dojoDndItemOver.dojoDndItemAnchor		{background: #feb !important;}
+/* avatar-specific settings */
+/*.dojoDndAvatarHeader	{display:none;} move to gridContainer */
 .dojoDndAvatarItem		{background: #eee;}
-.dndDropIndicator 		{border: 1px dashed #FF6600;cursor: default;}
+.dndDropIndicator 		{border: 1px dashed #FF6600;cursor: default;}
\ No newline at end of file
diff --git a/dojox/layout/resources/ExpandoPane.css b/dojox/layout/resources/ExpandoPane.css
index fbd38e2..47001a3 100644
--- a/dojox/layout/resources/ExpandoPane.css
+++ b/dojox/layout/resources/ExpandoPane.css
@@ -1,4 +1,5 @@
-	
+	/* dojox.layout.ExpandoPane */
+
 	.dojoxExpandoPane {
 		overflow:hidden;
 		z-index:440 !important;
@@ -7,31 +8,38 @@
 	.dojoxExpandoPane .dojoxExpandoWrapper {
 		overflow:hidden;
 	}
+
 	.dojoxExpandoClosed .dojoxExpandoTitleNode {
 		display:none;
 	}
-	
+
+	/* hide all layout children scrollbars when closed */
 	.dojoxExpandoClosed .dojoxExpandoWrapper * {
 		overflow:hidden !important;
 	}
+
 	.dojoxExpandoTitleNode {
 		padding-right:6px; 
 		padding-left:6px;
 	}
+
 	.dojoxExpandoIcon .a11yNode {
 		display:none;
 		visibility:hidden;
 	}
+
 	.dojoxExpandoBottom .dojoxExpandoIcon,
 	.dojoxExpandoTop .dojoxExpandoIcon,
 	.dojoxExpandoLeft .dojoxExpandoIcon {
 		float:right;
 		margin-right:2px;
 	}
+
 	.dojoxExpandoRight .dojoxExpandoIcon {
 		float:left;
 		margin-left:2px;
 	}
+
 	.dojoxExpandoIcon {
 		width:14px;
 		cursor:pointer;
@@ -39,6 +47,7 @@
 		background-repeat: no-repeat;
 		height:14px;
 	}
+
 	.dojoxExpandoClosed .dojoxExpandoIcon {
 		background-position: 0px 0px;
 		margin:0 auto;
@@ -47,7 +56,9 @@
 	.dijitBorderContainer-dijitExpandoPane {
 		border: none !important; 
 	}
-	
+
+	/* soria definitions */
+
 	.soria .dojoxExpandoTitle {
 		height:16px;
 		font-size:0.9em;
@@ -80,7 +91,7 @@
 		background-image: url('../../../dijit/themes/soria/images/spriteRoundedIconsSmall.gif');
 	}
 		
-	
+	/* tundra styles */
 	.tundra .dojoxExpandoTitle {
 		font-weight: bold;
 		padding: 5px;
@@ -104,6 +115,7 @@
 		background-color: #fafafa;
 		border: 1px solid #ccc !important;
 	}
+
 	.tundra .dojoxExpandoRight .dojoxExpandoTitle,
 	.tundra .dojoxExpandoLeft .dojoxExpandoTitle,
 	.tundra .dojoxExpandoClosed .dojoxExpandoTitle,
@@ -122,7 +134,59 @@
 		margin-top: 3px;
 	}
 	
+	/* claro styles */
+	.claro .dojoxExpandoTitle {
+		font-weight: bold;
+		border:1px solid #769DC0;
+		border-bottom:none;
+        background-color:#cde8ff;
+		background-image: url("../../../dijit/themes/claro/layout/images/accordion.png");
+        background-position:0px 0px;
+        background-repeat:repeat-x;
+		padding: 5px 7px 2px 7px;
+        min-height:17px;
+        color:#4a4a4a;
+	}
+		
+	.claro .dojoxExpandoClosed .dojoxExpandoTitle {
+		background: none;
+		background-color: #E6E6E7;
+		border: none;
+		padding:3px;
+	}
 	
+	.claro .dojoxExpandoClosed {
+		background: none;
+		background-color: #E6E6E7;
+		border: 1px solid #769DC0 !important;
+	}
+
+	.claro .dojoxExpandoRight .dojoxExpandoTitle,
+	.claro .dojoxExpandoLeft .dojoxExpandoTitle,
+	.claro .dojoxExpandoClosed .dojoxExpandoTitle{
+		background-color: #E6E6E7;
+	}
+	.claro .dojoxExpandoClosed .dojoxExpandoTitle{
+		background-image: url("../../../dijit/themes/claro/layout/images/accordion.png");
+		background-position:0 0;
+	}
+	
+	/* FIXME: use tundra spriteRoundedIconsSmall for now,
+	because there is no compatible image files in claro (15x15
+	icon, and icons are arranged in the same order as in 
+	spriteRoundedIconsSmall.gif */
+	.claro .dojoxExpandoIcon {
+		background-image: url('../../../dijit/themes/tundra/images/spriteRoundedIconsSmall.gif');
+	}
+	
+	.claro .dojoxExpandoClosed .dojoxExpandoIconLeft,
+	.claro .dojoxExpandoClosed .dojoxExpandoIconRight,
+	.claro .dojoxExpandoClosed .dojoxExpandoIconTop,
+	.claro .dojoxExpandoClosed .dojoxExpandoIconBottom {
+		margin-top: 3px;
+	}
+	
+	/* nihilo theme styles */
 	.nihilo .dojoxExpandoPane {
 		background: #fafafa;
 	}
@@ -165,7 +229,7 @@
 		border-right:1px solid #ccc; 
 	}
 	
-	
+	/* open/closed states */
 	
 	.dojoxExpandoClosed .dojoxExpandoIcon {
 		margin-right:4px;
diff --git a/dojox/layout/resources/ExpandoPane.html b/dojox/layout/resources/ExpandoPane.html
index d28222e..a2e646f 100644
--- a/dojox/layout/resources/ExpandoPane.html
+++ b/dojox/layout/resources/ExpandoPane.html
@@ -1,4 +1,4 @@
-<div class="dojoxExpandoPane" dojoAttachEvent="ondblclick:toggle" >
+<div class="dojoxExpandoPane">
 	<div dojoAttachPoint="titleWrapper" class="dojoxExpandoTitle">
 		<div class="dojoxExpandoIcon" dojoAttachPoint="iconNode" dojoAttachEvent="onclick:toggle"><span class="a11yNode">X</span></div>			
 		<span class="dojoxExpandoTitleNode" dojoAttachPoint="titleNode">${title}</span>
@@ -6,4 +6,4 @@
 	<div class="dojoxExpandoWrapper" dojoAttachPoint="cwrapper" dojoAttachEvent="ondblclick:_trap">
 		<div class="dojoxExpandoContent" dojoAttachPoint="containerNode"></div>
 	</div>
-</div>
\ No newline at end of file
+</div>
diff --git a/dojox/layout/resources/FloatingPane.css b/dojox/layout/resources/FloatingPane.css
index 18ef1f7..579f604 100644
--- a/dojox/layout/resources/FloatingPane.css
+++ b/dojox/layout/resources/FloatingPane.css
@@ -5,9 +5,12 @@
 	overflow: hidden;
 	-webkit-box-shadow: 0px 5px 10px #adadad;
 }
+
 .dojoxFloatingPaneFg {
 	-webkit-box-shadow: 0px 8px 20px #525252;
 }
+
+/* titleNode */
 .dojoxFloatingPaneTitle {
 	background: #cccccc;
 	background:#fafafa repeat-x bottom left;
@@ -16,6 +19,7 @@
 	cursor: pointer;
 	white-space: nowrap;
 }
+
 .soria .dojoxFloatingPaneTitle {
 	background:#fff url("../../../dijit/themes/soria/images/titleBar.png") repeat-x top left;
 	border:1px solid #b1badf;
@@ -23,11 +27,16 @@
 	font-weight: bold;
 	line-height:1.2em;
 }
+
+
 .tundra .dojoxFloatingPaneTitle {
 	background:#fafafa url("../../../dijit/themes/tundra/images/titleBarBg.gif") repeat-x bottom left;
 	border:1px solid #bfbfbf;
 	color:#000; 	
 }
+
+
+/* Icons */
 .dojoxFloatingCloseIcon {
 	background:url('../../../dijit/themes/tundra/images/tabClose.png') no-repeat center center; 
 	width:16px;
@@ -35,6 +44,7 @@
 	overflow:hidden;
 	float:right; 
 }
+
 .dojoxFloatingMinimizeIcon {
 	background:url('../../../dijit/themes/tundra/images/spriteArrows.png') no-repeat 0px center; 
 	width:7px;
@@ -47,6 +57,7 @@
 	width: 14px;
 	margin: 0px 2px;
 }
+
 .floatingPaneMaximized .dojoxFloatingMaximizeIcon { display:none; }
 .dojoxFloatingMaximizeIcon {
 	background:url('../../../dijit/themes/tundra/images/spriteArrows.png') no-repeat -21px center;
@@ -58,6 +69,7 @@
 .soria .dojoxFloatingMaximizeIcon {
 	background:url("../../../dijit/themes/soria/images/spriteRoundedIconsSmallBl.png") no-repeat -45px top;
 }
+
 .floatingPaneMaximized .dojoxFloatingRestoreIcon { display:inline; }
 .dojoxFloatingRestoreIcon {
 	background:url('../../../dijit/themes/tundra/images/spriteArrows.png') no-repeat 0px center; 
@@ -66,6 +78,7 @@
 	float:right;
 	display:none;
 }
+
 .dojoxFloatingResizeHandle {
 	background:url('icons/resize.png') no-repeat bottom right;
 	position:absolute; 
@@ -75,6 +88,7 @@
 	height:16px; 
 	cursor:nw-resize;
 }
+
 .dojoxFloatingCloseIcon {
 	width:15px;
 	height:15px; 
@@ -82,12 +96,16 @@
 	float:right; 
 	cursor:pointer;
 }
+
 .soria .dojoxFloatingCloseIcon {
 	background:url("../../../dijit/themes/soria/images/spriteRoundedIconsSmallBl.png") no-repeat -60px top;
 }
+
 .tundra .dojoxFloatingCloseIcon {
 	background:url('../../../dijit/themes/tundra/images/tabClose.png') no-repeat center center; 	
 }
+
+/* our un-used dock styles for now */
 .dojoxFloatingDockDefault {
 	position:absolute;
 	bottom:0px;
@@ -97,14 +115,19 @@
 	margin-bottom:3px; 
 	padding:0px; 
 	width:100%;
-	z-index:99; 
+	z-index:99; /* position the dock _just_ below the lowest pane */
+
 	background:transparent;
-	
+	/* background-color:#fff; 
+	border-top:1px solid #ccc; 
+	*/
 }
+
 .dojoxDockList {
 	padding: 0px;
 	margin: 0px;
 }
+
 .dojoxDockRestoreButton {
 	background:url('../../../dijit/themes/tundra/images/arrowUp.png') no-repeat center center;
 	width:16px; height:16px;
@@ -115,9 +138,13 @@
 .soria .dojoxDockRestoreButton {
 	background:url("../../../dijit/themes/soria/images/spriteRoundedIconsSmallBl.png") no-repeat -45px top;
 }
+
 .dojoxDockTitleNode {
 	overflow:hidden;
 }
+
+/* Modifications */
+
 .dojoxDock {
 	display: block;
 	border: 1px solid black;
@@ -126,6 +153,7 @@
 	margin:0;
 	background:#fcfcfc;
 }
+
 .dojoxDockNode {
 	border: 1px solid #adadad;
 	border-radius: 2px;
@@ -143,12 +171,14 @@
 .soria .dojoxDockNode {
 	background:#b7cdee url("../../../dijit/themes/soria/images/titleBar.png") repeat-x;
 }
+
 .dojoxFloatingPaneContent {
 	overflow: auto;
 	background-color: #fff; 
 	height: 100%; 
 	width:	100%; 
 }
+
 .dojoxFloatingPaneCanvas {
 	background-color:#fff;
 }
diff --git a/dojox/layout/resources/GridContainer.css b/dojox/layout/resources/GridContainer.css
index d656665..8146fbd 100644
--- a/dojox/layout/resources/GridContainer.css
+++ b/dojox/layout/resources/GridContainer.css
@@ -1,76 +1,74 @@
-.oafDndHandle {
-	cursor: move;
+ at import url("../../mdnd/resources/dnd.css");
+.dj_ie6 .gridContainer *{
+	zoom:1;
 }
-.gridContainer {
+
+.gridContainer{
 	display:block;	
-	position: relative;
+	position:relative;
 	background:#FFF;	
-	margin:0px;
+	margin:0;	
+	width:100%;
+	/*height:1%;*/ /*Bug focus with IE6/7)*/
+	height:auto;
+	overflow-y:auto;
+	overflow-x:hidden !important;
 }
 	
-.gridContainer .dojoDndAvatarHeader	{
-	display:none;
-}
-.gridContainerTable {
+.gridContainerTable{
 	width:100%;
-	height: 100%;
+	border:1px solid #BFBFBF;
 }
-.gridContainerPopup {
-	position: absolute;
-	top:40%;
-	left:40%;
-	width: 200px;
-	height: auto;	
-	border: 1px solid #F60;
-	background-color: #FFF;
-	text-align: center;
-	padding: 10px;
+
+.gridContainerTable tbody, .gridContainerTable tr{
+	height:100%;
 }
-.gridContainerTable tbody.gridContainerBody, .gridContainerTable tr.gridContainerRow {
-	height: 100%;
+
+.gridContainerZone{
+	vertical-align:top;	
+	background-color:#FDFDFD;	
+	height:100%;
 }
-.gridContainerZone {
-	vertical-align: top;	
-	padding:12px;	
-	background-color: #FDFDFD;	 
-	height: 100%;
+
+.gridContainerZone .serviceWidgetTitleText h2{
+	position:relative;
 }
-.gridContainerZone .serviceWidgetTitleText h2 {
-	position: relative;
-}
-.gridContainerGrip {
+
+.gridContainerGrip{
 	cursor:default;
-	position:absolute;	
-	width:5px;	
-	padding: 0px;	
-	margin:0px;
-	background-image: url(images/pixel.gif);
-	background-color: #ededed;
-}
-.tundra .gridContainerGrip {
-	border-left:1px solid #a7a7a7;
-	border-right:1px solid #a7a7a7;
+	position:absolute;
+	top:0;	
+	width:10px;	
+	padding:0;	
+	margin:0;
+	background-image:url(icons/pixel.gif);
+	height:100%;
 }
 	
-.gridContainerGripShow, .gridContainerGrip:focus {
+.gridContainerGripShow{
 	cursor:e-resize;	
 	position:absolute;	
-	width:5px;	
-	padding:0px;	
-	margin:0px;
-	background-color: #a7a7a7;	
-	background-image: url(images/grip_bg.gif);
+	top:0;
+	width:10px;	
+	padding:0;	
+	margin:0;	
+	background-image:url(icons/gridcontainer_grip.gif);
+	height:100%;
 }
-.tundra .gridContainerGripShow, .tundra .gridContainerGrid:focus {
-	border-left:1px solid #aeaeae;
-	border-right:1px solid #aeaeae;
+
+.dropIndicator{
+	border:2px dashed #BFBFBF;
 }
-.tundra .gridContainer .dndDropIndicator,
-.nihilo .gridContainer .dndDropIndicator{
-	border: 2px dashed #CCCCCC;
-	cursor:default;
+
+.dropIndicator > div{
+	background-color:#FFF;
 }
-.soria .gridContainer .dndDropIndicator {
-	border: 2px dashed #99BBE8;
-	cursor:default;
+
+.dj_ie6 .dropIndicator,
+.dj_ie6 .dijitContentPane,
+.dj_ie6 .dojoxPortlet, .dj_ie6 .dijitTitlePane{
+	margin: 10px;
+}
+.gridContainerZone > *{
+	margin: 10px !important;
 }
diff --git a/dojox/layout/resources/GridContainer.html b/dojox/layout/resources/GridContainer.html
index f8a53e8..c92a917 100644
--- a/dojox/layout/resources/GridContainer.html
+++ b/dojox/layout/resources/GridContainer.html
@@ -1,7 +1,11 @@
 <div id="${id}" class="gridContainer" dojoAttachPoint="containerNode" tabIndex="0" dojoAttachEvent="onkeypress:_selectFocus">
-	<table class="gridContainerTable" dojoAttachPoint="gridContainerTable" cellspacing="0" cellpadding="0">
-		<tbody class="gridContainerBody">
-			<tr class="gridContainerRow" dojoAttachPoint="gridNode"></tr>
-		</tbody>
-	</table>
+	<div dojoAttachPoint="gridContainerDiv">
+		<table class="gridContainerTable" dojoAttachPoint="gridContainerTable" cellspacing="0" cellpadding="0">
+			<tbody>
+				<tr dojoAttachPoint="gridNode" >
+					
+				</tr>
+			</tbody>
+		</table>
+	</div>
 </div>
\ No newline at end of file
diff --git a/dojox/layout/resources/RadioGroup.css b/dojox/layout/resources/RadioGroup.css
index 684fa36..d4d67d2 100644
--- a/dojox/layout/resources/RadioGroup.css
+++ b/dojox/layout/resources/RadioGroup.css
@@ -1,18 +1,21 @@
-
+/* RadioGroup base Button styling: */
 .dojoxRadioButtons {
 	margin:0; padding:4px;
 	width:100%;
 	outline:0;
 }
+
 .dojoxRadioButtons tbody  {
 	margin:0; padding:0;
 	width:100%;
 }
+
 .dojoxRadioButton {
 	text-align:center;
 	cursor:pointer;
 	margin:0;
 }
+
 .dojoxRadioButtonSelected {
 	border:1px solid #ededed;
 }
@@ -23,11 +26,13 @@
 .soria .dojoxRadioButtonSelected {
 	background:#b7cdee url('../../../dijit/themes/soria/images/gradientTopBg.png') repeat-x top center;
 }
+
 .dojoxRadioButtonLabel {
 	padding:8px;
 	text-align:center;
 	display:block;
 }
+
 .dojoxRadioGroup {
 	overflow:hidden;
 	border:0;
@@ -37,4 +42,4 @@
 	position:relative;
 	overflow:hidden;
 	height:100%;
-}
+}
\ No newline at end of file
diff --git a/dojox/layout/resources/ResizeHandle.css b/dojox/layout/resources/ResizeHandle.css
index b68f2d4..533d250 100644
--- a/dojox/layout/resources/ResizeHandle.css
+++ b/dojox/layout/resources/ResizeHandle.css
@@ -9,20 +9,44 @@
 	background-image: url('icons/resize.png');
 	line-height: 0px;
 }
+
+.dijitRtl .dojoxResizeHandle {
+        float: right;
+        left: 0px;
+        right: auto;
+	background-image: url('icons/resizeRtl.png');
+}
+
 .dojoxResizeNW {
 	cursor: nw-resize;
 }
+
+.dijitRtl .dojoxResizeNW {
+        cursor: ne-resize;
+}
+
 .dojoxResizeNE {
 	cursor: ne-resize; 
 }
+
+.dijitRtl .dojoxResizeNE {
+        cursor: nw-resize;
+}
+
 .dojoxResizeW {
 	cursor: w-resize; 
 }
+
+
 .dojoxResizeN { 
 	cursor: n-resize; 
 }
+
 .dojoxResizeHandleClone {
 	position:absolute; top:0; left:0; 
 	border:1px dashed #666; 
 	z-index:999; 
 }
+
+
+
diff --git a/dojox/layout/resources/RotatorContainer.css b/dojox/layout/resources/RotatorContainer.css
index ef0afcc..0c87a8a 100644
--- a/dojox/layout/resources/RotatorContainer.css
+++ b/dojox/layout/resources/RotatorContainer.css
@@ -3,23 +3,29 @@
 	position:absolute;
 	z-index:3;
 }
+
 .dojoxRotatorContent {
 	position:absolute;
 	z-index:1;
 }
+
 .dojoxRotatorContainer {
 	border:1px solid #9b9b9b;
 }
+
 .dojoxRotatorContainer .dijitStackController {
 	right:5px;
 	top:5px;
 }
+
 .dojoxRotatorContainer .dijitStackController .dijitToggleButtonChecked .dijitButtonNode {
 	background-color:#000;
 	background-image:none;
 	color:#fff;
 }
+
 .dojoxRotatorContainer .dojoxRotatorPager{bottom:5px;right:5px;}
+
 .rotatorIcons .dijitButton{margin:0;}
 .rotatorIcons .dijitButtonNode{background:none !important;border:0 !important;padding:0 !important;}
 .rotatorIcons .dijitButtonText{display:none;}
diff --git a/dojox/layout/resources/ScrollPane.css b/dojox/layout/resources/ScrollPane.css
index 6aaa36a..3dc7386 100644
--- a/dojox/layout/resources/ScrollPane.css
+++ b/dojox/layout/resources/ScrollPane.css
@@ -2,9 +2,11 @@
 	position:relative;
 	overflow:hidden;
 }
+
 .dojoxScrollHelper .helperInner {
 	visibility: hidden;
 }
+
 .dojoxScrollHelper {
 	border:1px solid #b7b7b7;
 	width:4px;
@@ -17,5 +19,6 @@
 	-moz-border-radius: 3px;
 	-webkit-border-radius: 3px;
 }
+
 .dojoxScrollWrapper {
 }
diff --git a/dojox/layout/resources/ToggleSplitter.css b/dojox/layout/resources/ToggleSplitter.css
index 5a1f32d..a00d546 100644
--- a/dojox/layout/resources/ToggleSplitter.css
+++ b/dojox/layout/resources/ToggleSplitter.css
@@ -6,6 +6,7 @@
 .dijitBorderContainer .dojoxToggleSplitterRight {
 	width:16px;
 }
+
 .dijitBorderContainer .dijitSplitterH .dojoxToggleSplitterIcon {
 	width:16px;
 	height:16px;
@@ -18,6 +19,7 @@
 	left: 0;
 	cursor: pointer;
 }
+
 .tundra .dojoxToggleSplitterTop .dojoxToggleSplitterIconOpen, 
 .tundra .dojoxToggleSplitterBottom .dojoxToggleSplitterIconClosed 
  {
@@ -28,6 +30,7 @@
  {
 	background: transparent url('../../../dijit/themes/tundra/images/spriteRoundedIconsSmall.png') no-repeat -15px 50%;
 }
+
 .tundra .dojoxToggleSplitterLeft .dojoxToggleSplitterIconOpen, 
 .tundra .dojoxToggleSplitterRight .dojoxToggleSplitterIconClosed 
  {
@@ -38,6 +41,7 @@
  {
 	background: transparent url('../../../dijit/themes/tundra/images/spriteRoundedIconsSmall.png') no-repeat -30px 50%;
 }
+
 .soria .dojoxToggleSplitterTop .dojoxToggleSplitterIconOpen, 
 .soria .dojoxToggleSplitterBottom .dojoxToggleSplitterIconClosed 
  {
@@ -48,6 +52,7 @@
  {
 	background: transparent url('../../../dijit/themes/soria/images/spriteRoundedIconsSmall.png') no-repeat -15px 50%;
 }
+
 .soria .dojoxToggleSplitterLeft .dojoxToggleSplitterIconOpen, 
 .soria .dojoxToggleSplitterRight .dojoxToggleSplitterIconClosed 
  {
@@ -58,6 +63,7 @@
  {
 	background: transparent url('../../../dijit/themes/soria/images/spriteRoundedIconsSmall.png') no-repeat -30px 50%;
 }
+
 .nihilo .dojoxToggleSplitterTop .dojoxToggleSplitterIconOpen, 
 .nihilo .dojoxToggleSplitterBottom .dojoxToggleSplitterIconClosed 
  {
@@ -68,6 +74,7 @@
  {
 	background: transparent url('../../../dijit/themes/nihilo/images/spriteRoundedIconsSmall.png') no-repeat -15px 50%;
 }
+
 .nihilo .dojoxToggleSplitterLeft .dojoxToggleSplitterIconOpen, 
 .nihilo .dojoxToggleSplitterRight .dojoxToggleSplitterIconClosed 
  {
diff --git a/dojox/layout/resources/icons/gridcontainer_grip.gif b/dojox/layout/resources/icons/gridcontainer_grip.gif
new file mode 100644
index 0000000..2eb05e8
Binary files /dev/null and b/dojox/layout/resources/icons/gridcontainer_grip.gif differ
diff --git a/dojox/layout/resources/icons/grip_bg.gif b/dojox/layout/resources/icons/grip_bg.gif
old mode 100644
new mode 100755
diff --git a/dojox/layout/resources/icons/pixel.gif b/dojox/layout/resources/icons/pixel.gif
old mode 100644
new mode 100755
diff --git a/dojox/layout/resources/icons/resize.png b/dojox/layout/resources/icons/resize.png
old mode 100644
new mode 100755
diff --git a/dojox/layout/resources/icons/resizeRtl.png b/dojox/layout/resources/icons/resizeRtl.png
new file mode 100644
index 0000000..c3f97c6
Binary files /dev/null and b/dojox/layout/resources/icons/resizeRtl.png differ
diff --git a/dojox/layout/resources/icons/rotator.png b/dojox/layout/resources/icons/rotator.png
old mode 100644
new mode 100755
diff --git a/dojox/layout/tests/ContentPane.html b/dojox/layout/tests/ContentPane.html
new file mode 100644
index 0000000..77e1d38
--- /dev/null
+++ b/dojox/layout/tests/ContentPane.html
@@ -0,0 +1,1050 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.layout.ContentPane test</title>
+	<script >
+	function fixPngIE6(){
+		if(this.complete && dojo.isIE < 7){
+			var r = this.runtimeStyle;
+			if(/.png$/i.test(this.src)){
+				r.height = this.height;
+				r.width = this.width;
+				r.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.src+"');";
+				this.src = this.currentStyle.backgroundImage.replace(/url\(\s*['"]?(.+?)['"]?\s*\)/, "$1");
+			}
+			this.className = this.className.replace('run_png_fix', "");
+			r.behaviour = 'none';
+		}
+	}
+	</script>
+	<style type='text/css'>
+		.run_png_fix {
+			background-image:url(images/blank.gif);
+			behaviour: expression(fixPngIE6.call(this));
+		}
+	</style>
+	<script src='../../../dojo/dojo.js' djConfig='isDebug:true, parseOnLoad:true'></script>
+	<script src='../../../dojo/html.js'></script>
+	<script src='../../../dojox/html/_base.js'></script>
+	<script src='../../../dojox/layout/ContentPane.js'></script>
+	<script>
+		dojo.require('doh.runner');
+		dojo.require('dojox.layout.ContentPane');
+		dojo.require('dojo.parser');
+		dojo.require('dijit._Container');
+		dojo.require('dijit._Templated');
+
+
+		// create a do nothing, only for test widget
+		dojo.declare("dojox.TestWidget",
+			[dijit._Widget, dijit._Templated], {
+			templateString: "<span class='dojoxTestWidget'></span>"
+		});
+
+		// used to test if we fire scrips to document scope
+		function documentCallback(){
+			arguments.callee.reached = true;
+			//console.debug('reached');
+		}
+		var unTypedVarInDocScope; // a closure test to make sure we can reach this from evaled scripts
+
+
+		var pane1, pane2;
+
+		dojo.addOnLoad(function(){
+
+			pane1 = dijit.byId('parsedPane');
+
+			function ieTrimSpaceBetweenTags(str){
+				return str.replace(/(<[a-z]*[^>]*>)\s*/ig, "$1");
+			}
+
+			doh.register("basicChecks", [
+					{
+						name: 'setContent',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var msg = "Simple Test";
+							pane1.attr('content', msg);
+							t.assertEqual(msg, pane1.domNode.innerHTML);
+						}
+					},
+					{
+						name: 'setHref',
+						timeout: 1800,
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var msg = "simple remote Test"
+							pane1.attr('href', dojo.moduleUrl('dijit', 'tests/layout/getResponse.php?message='+encodeURI(msg)));
+
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual(msg, pane1.domNode.innerHTML)
+							}), 1500);
+							return d;
+						}
+					},
+					{
+						name: 'setContent_with_Widgets',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var cont = "<div dojoType='dojox.TestWidget'>Test</div>";
+							pane1.attr('content', cont);
+							t.assertFalse(cont.toLowerCase() == pane1.domNode.innerHTML.toLowerCase());
+							t.assertEqual(1, dijit._Container.prototype.getChildren.call(pane1).length);
+						}
+					},
+					{
+						name: 'changeContentTRHead',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var trHead = dojo.query('table#tableTest > thead > tr')[0];
+							pane2 = new dojox.layout.ContentPane({} , trHead);
+							var html = "<td><div>This</div>Should<u>Work</u></td>";
+							pane2.attr('content', html);
+							var res = ieTrimSpaceBetweenTags(pane2.domNode.innerHTML.toLowerCase());
+							t.assertEqual(html.toLowerCase(), res);
+						},
+						tearDown: function(){
+							pane2.destroy();
+						}
+					},
+					{
+						name: 'changeContentTHead',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var tHead = dojo.query('table#tableTest > thead')[0];
+							pane2 = new dojox.layout.ContentPane({}, tHead);
+							var html = "<tr><td><div>This</div>Should<u>Work</u></td></tr>";
+							pane2.attr('content', html);
+							var res = ieTrimSpaceBetweenTags(pane2.domNode.innerHTML.toLowerCase());
+							t.assertEqual(html.toLowerCase(), res);
+						},
+						tearDown: function(){
+							pane2.destroy();
+						}
+					},
+					{
+						name: 'changeContentTRBody',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var trBody = dojo.query('table#tableTest > tbody > tr')[0];
+							pane2 = new dojox.layout.ContentPane({}, trBody);
+							var html = "<td><div>This</div>Should<u>Work</u></td>";
+							pane2.attr('content', html);
+							var res = ieTrimSpaceBetweenTags(pane2.domNode.innerHTML.toLowerCase());
+							t.assertEqual(html.toLowerCase(), res);
+						},
+						tearDown: function(){
+							pane2.destroy();
+						}
+					},
+					{
+						name: 'changeContentTBody',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var tBody = dojo.query('table#tableTest > tbody')[0];
+							pane2 = new dojox.layout.ContentPane({}, tBody);
+							var html = "<tr><td><div>This</div>Should<u>Work</u></td></tr>";
+							pane2.attr('content', html);
+							var res = ieTrimSpaceBetweenTags(pane2.domNode.innerHTML.toLowerCase());
+							t.assertEqual(html.toLowerCase(), res);
+						},
+						tearDown: function(){
+							pane2.destroy();
+						}
+					},
+					{
+						name: 'changeContentTable',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var table = dojo.query('table#tableTest')[0];
+							pane2 = new dojox.layout.ContentPane({}, table);
+							var html = "<tbody><tr><td><div>This</div>Should<u>Work</u></td></tr></tbody>";
+							pane2.attr('content', html);
+							var res = ieTrimSpaceBetweenTags(pane2.domNode.innerHTML.toLowerCase());
+							t.assertEqual(html.toLowerCase(), res);
+						},
+						tearDown: function(){
+							pane2.destroy();
+						}
+					},
+					{
+						name: 'ioArgsSetSyncLoad',
+						timeout: 1500,
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							pane1.ioArgs.sync = true;
+							pane1.attr('href', dojo.moduleUrl('dijit', 'tests/layout/getResponse.php?delay=100&message=sync'));
+
+							// since it was a sync fetch it should be loaded here
+							t.assertEqual('sync', pane1.domNode.innerHTML);
+						},
+						tearDown: function(){
+							pane1.ioArgs = {}; // back to defaults
+						}
+					},
+					{
+						name: 'ioArgsSetsHeader',
+						timeout: 1800,
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							// test if we can set a custom header on every request
+							pane1.ioArgs.headers = {'X-TestHeader': 'Testing'};
+							pane1.attr('href', 'remote/getResponse.php?mode=bounceHeaders');
+
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(function(){
+								var cont = pane1.domNode.innerHTML;
+								t.assertTrue(/X-TestHeader/i.test(cont));
+								t.assertTrue(/Testing/i.test(cont));
+							}), 1500);
+
+							return d;
+						},
+						tearDown: function(){
+							pane1.ioArgs = {}; // back to defaults
+						}
+					},
+					{
+						name: 'ioMethodPost',
+						timeout: 1800,
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							// test to post some content on each request
+							pane1.ioMethod = dojo.xhrPost;
+							pane1.ioArgs.content = {test:'it should work'};
+							pane1.attr('href', 'remote/getResponse.php?mode=bounceInput');
+
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('test=it%20should%20work', pane1.domNode.innerHTML);
+							}), 1500);
+							return d;
+						},
+						tearDown: function(){
+							// back to defaults
+							pane1.ioMethod = dojo.xhrGet;
+							pane1.ioArgs = {};
+						}
+					},
+					{
+						name: 'handleFrom_setContent',
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var unLoadCalled, loadCalled;
+							var handle = pane1.attr('content', "test 'var handle = attr('content', '')'");
+
+							handle.addCallback(function(){
+								loadCalled = true;
+							});
+
+							t.assertTrue(loadCalled);
+						}
+					},
+					{
+						name: 'handleFrom_setHref_and_refresh_and_cancelWorking',
+						timeout: 3400,
+						runTest: function(t){
+							console.log("basicChecks: " + this.name);
+							var loadCalled;
+							var r_loadCalled;
+							var r_handle, href = dojo.moduleUrl('dijit', 'tests/layout/getResponse.php?delay=100&message=test');
+
+							var handle = pane1.attr('href', href);
+							t.assertTrue(handle);
+							handle.addCallback(function(){
+								console.log("handleFrom_setHref_and_refresh_and_cancelWorking: handle onLoad");
+								loadCalled = 'loadCalled';
+							});
+
+							// Since we cancel immediately the deferred should never fire
+							handle.cancel();
+
+							setTimeout(function(){
+								console.log("handleFrom_setHref_and_refresh_and_cancelWorking: setting href: " + href);
+								pane1.href = href;
+								handle = pane1.refresh();
+								t.assertTrue(handle);
+								r_handle = 'refreshHandle ok';
+								handle.addCallback(function(){
+									console.log("handleFrom_setHref_and_refresh_and_cancelWorking: 2ary handle onload");
+									r_loadCalled = 'refresh loadCalled';
+									pane1.attr('content', ''); // trigger unload
+								});
+							}, 1500); // wait for page load in case cancel didn't work
+
+							var d = new t.Deferred();
+
+							setTimeout(d.getTestCallback(function(){
+								// load from the href (was canceled)
+								t.assertEqual(undefined, loadCalled);
+
+								// load from the refresh
+								t.assertEqual('refreshHandle ok', r_handle);
+								t.assertEqual('refresh loadCalled', r_loadCalled);
+							}), 3200);
+
+							return d;
+						}
+					}
+				]
+			);
+
+
+			doh.register("pathAdjustments",
+				[
+					{
+						setUp: function() {
+							// setup text fixture for these pathAdjustments tests
+							if(!pane1._contentSetter) {
+								// make sure the contentSetter is created, by doing a simple setContent 
+								pane1.attr("content", "");
+							}
+						},
+						name: 'cssPathAdjustments',
+						runTest: function(t){
+							// test that when you setContent, using the adjustPaths and renderStyles options
+							// the paths in the css are corrected for the current document
+							console.log("pathAdjustments: " + this.name);
+
+							// we do this test as one big string to emulate as good as possible, 
+							// but split it later to easily see where we failed
+							var cssText = ".easy{ background-image:url(images/image.png) }\n"
+							+".dontReplaceEasy{ background-image:url(images/images/image.png) }\n"
+							+".hardurl{background-image:url(\t \"../../source/~test/%20t'e(s)t.gif(\"1')?foo=bar11103&bar=baz-foo\"	 \t);}body{};\n"
+							+".file{background-image: url(file:///home/nobody/image.png);}\n"
+							+".http{background-image: url(http://dojotoolkit.org/image.png);}\n"
+							+".https{background-image: url(https://dojotoolkit.org/image.png);}\n"
+							+".nonRelative{background-image:url(/toplevelfolder/image.gif);}\n"
+							+'@import "css/main.css";' + "\n at import \t'css/Newbee Url.css'\t;\n"
+							+"@import 'http://dojotoolkit.org/dojo.css';\n"
+							+"	@import 'you/never/thought/' print;\n"
+							+' @import url("it/would/work") tv, screen;'+"\n"
+							+' @import url(/did/you/now.css);'+"\n"
+							+' @import "yes.i.did";';
+
+							pane1.referencePath = "deep/nested/file";	// hook for testing to trigger path adjustment on an attr('content', ...)
+							pane1.adjustPaths = true;
+							pane1.renderStyles = true;
+							var adjustedCss;
+
+							// hijack internals to snatch the styles before they are inserted to DOM (DOM messes formating)
+							var oldFunc = pane1._contentSetter._renderStyles;
+							console.log("in cssPathAdjustments, returning function");
+
+							pane1._contentSetter._renderStyles = function(styles){
+								console.log("in replaced _renderStyles");
+								adjustedCss = styles.join();
+							}
+							console.log("in cssPathAdjustments, calling set");
+							pane1.attr('content', '<style>'+cssText+'</style>');
+							console.log("in cssPathAdjustments, done calling set");
+							pane1._contentSetter._renderStyles = oldFunc;
+
+							adjustedCss = adjustedCss.split("\n");
+
+							var expectedCss = (".easy{ background-image:url(deep/nested/images/image.png) }\n"
+							+".dontReplaceEasy{ background-image:url(deep/nested/images/images/image.png) }\n"
+							+".hardurl{background-image:url(source/~test/%20t'e(s)t.gif(\"1')?foo=bar11103&bar=baz-foo);}body{};\n"
+							+".file{background-image: url(file:///home/nobody/image.png);}\n"
+							+".http{background-image: url(http://dojotoolkit.org/image.png);}\n"
+							+".https{background-image: url(https://dojotoolkit.org/image.png);}\n"
+							+".nonRelative{background-image:url(/toplevelfolder/image.gif);}\n"
+							+"@import \"deep/nested/css/main.css\";\n at import \"deep/nested/css/Newbee Url.css\"\t;\n"
+							+"@import 'http://dojotoolkit.org/dojo.css';\n"
+							+"	@import \"deep/nested/you/never/thought/\" print;\n"
+							+' @import url(deep/nested/it/would/work) tv, screen;'+"\n"
+							+' @import url(/did/you/now.css);'+"\n"
+							+' @import "deep/nested/yes.i.did";').split("\n");
+
+							// we split and loop to get a faster hint of where it failed
+							for(var i = 0; i < expectedCss.length; i++){
+								t.assertEqual(expectedCss[i], adjustedCss[i]);
+							}
+						},
+						tearDown: function(){
+							delete pane1.adjustPaths; // get back to defaults
+							delete pane1.renderStyles;
+							delete pane1.referencePath;
+						}
+					},
+					{
+						name: 'htmlPathAdjustments',
+						timeout: 1800,
+						runTest: function(t){
+							console.log("pathAdjustments: " + this.name);
+
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(
+								function(){
+									console.log("pathAdjustments: htmlPathAdjustments, in callback");
+									
+									// check that images and styles have been applied
+									var cb = dojo.contentBox(dojo.byId('imgTest'));
+											//dojo.getComputedStyle(dojo.byId('imgTest'));
+									t.assertEqual(188, cb.w);
+									t.assertEqual(125, cb.h);
+
+									// make sure we didn't mess up the other inline styles
+									cb = dojo.contentBox(dojo.byId('inlineStyleTest'));
+									t.assertEqual(188, cb.w);
+									t.assertEqual(125, cb.h);
+
+									// make sure it is the correct image
+									var cs = dojo.getComputedStyle(dojo.byId('inlineStyleTest'));
+									var url = cs.backgroundImage;
+									//remove url(..)
+									url = url.replace(/^\s?url\(['"]?/, "").replace(/['"]?\);?\s?$/, ""); 
+									// compare image url to full path of this document
+									imageUrl = dojo.moduleUrl('dojox', 'layout/tests/images/testImage.gif');
+									t.assertEqual(new dojo._Url(document.location, imageUrl).toString(), url);
+
+									// make sure we loaded the <link rel='stylesheet' correctly
+									var mb = dojo.marginBox(dojo.byId('linkCssTest'));
+									t.assertEqual(112, mb.w); // 100px	+ 2px border + 4px margin = 112px
+									t.assertEqual(112, mb.h);
+
+									// make sure we loaded the <style>@import '...'; correctly
+									mb = dojo.marginBox(dojo.byId('importCssTest'));
+									t.assertEqual(110, mb.w); // 100px + 1px border + 4px margin = 110px
+									t.assertEqual(110, mb.h);
+
+									// make sure we didn't render the <link media='print' rel='stylesheet'
+									var mb = dojo.marginBox(dojo.byId('linkMediaTest'));
+									t.assertEqual(212, mb.w); // 100px	+ 2px border + 4px margin = 112px
+									t.assertEqual(212, mb.h);
+
+									// make sure we didn't render the <style media='print'>@import '...';
+									mb = dojo.marginBox(dojo.byId('importMediaTest'));
+									t.assertEqual(210, mb.w); // 100px + 1px border + 4px margin = 110px
+									t.assertEqual(210, mb.h);
+								}
+							), 1500);
+
+							pane1.adjustPaths=true; pane1.renderStyles=true;
+							pane1.attr('href', 'remote/getResponse.php?mode=htmlPaths');
+							return d;
+						},
+						tearDown: function(){
+							delete pane1.adjustPaths; // get back to defaults
+							delete pane1.renderStyles;
+						}
+					},
+					{
+						name: 'renderStylesOfByDefaultAndOldDeleted',
+						timeout: 1800,
+						runTest: function(t){
+							console.log("pathAdjustments: " + this.name);
+							var d = new t.Deferred();
+
+							setTimeout(d.getTestCallback(
+								function(){
+									// innerHTML'ing <link tags works in some browser (IE, moz), but not all
+									// we can't test if LINK was loaded this way
+
+									// make sure we didn't load the <link rel='stylesheet'
+									//var mb = dojo.marginBox(dojo.byId('linkCssTest'));
+									//t.assertFalse(112 == mb.w);
+									//t.assertFalse(112 == mb.h);
+									// make sure we didn't load the <style>@import '...';
+
+									var mb = dojo.marginBox(dojo.byId('importCssTest'));
+									t.assertFalse(110 == mb.w);
+									t.assertFalse(110 == mb.h);
+								}
+							), 1500);
+							pane1.adjustPaths=true;
+							pane1.attr('href', 'remote/getResponse.php?mode=htmlPaths');
+							return d;
+						},
+						tearDown: function(){
+							delete pane1.adjustPaths;
+						}
+					}
+				]
+			);
+
+			doh.register("scriptTests",
+				[
+					"t.assertTrue(pane1.executeScripts);",
+					{
+						name: 'leaveDojoMethodScriptsAsIs',
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							pane1.attr('content', "<"
+								+"script type='dojo/method'>unTypedVarInDocScope = 'failure';<"
+								+"/script>");
+
+							var d = new t.Deferred();
+							// IE req to async this test
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('undefined', typeof unTypedVarInDocScope);
+								t.assertFalse(unTypedVarInDocScope == 'failure');
+							}), 40);
+
+							return d;
+						}
+					},
+					{
+						name: 'scripts_evals_in_global_scope',
+						timeout: 1800, // grabing remote js, wait for that
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							pane1.attr('content', "<"
+								+"script>function scriptsInGlobalClicked(){ documentCallback(); }<"
+								+"/script><"+"script src='remote/getResponse.php?mode=remoteJsTrue'></"
+								+"script>"+"<a href='javascript:scriptsInGlobalClicked()' "
+									+"onfocus='scriptsInGlobalClicked();' id='anchorTag'>test</a>");
+
+							var link = dojo.byId('anchorTag');
+							dojo.isFunction(link.click) ? /*others*/ link.click() : /*moz*/ link.focus();
+							var d = new t.Deferred();
+					
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('boolean', typeof documentCallback.reached);
+								t.assertTrue(documentCallback.reached);
+								t.assertTrue(unTypedVarInDocScope);
+							}), 40);
+							return d;
+						}
+					},
+					{
+						name:'scriptsEvalsInOrder',
+						timeout: 1800,// grabing remote js, wait for that
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							pane1.attr('content', "<"
+								+"script src='remote/getResponse.php?mode=remoteJsFalse'><"
+								+"/script><"+"script>unTypedVarInDocScope = 1;<"
+								+"/script>"); // scripts only test
+
+							// we need to make this async because of IEs strange events loops
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('number', typeof unTypedVarInDocScope);
+								t.assertEqual(1, unTypedVarInDocScope);
+							}), 40);
+							return d;
+						}
+					},
+					{
+						name: 'scriptsWithTypeTextJavascript',
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							pane1.attr('content', "<"
+								+"script type='text/javascript'> unTypedVarInDocScope = 'text/javascript'; <"
+								+"/script>");
+
+							var d = new t.Deferred();
+							// IE needs async here
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('text/javascript', unTypedVarInDocScope);
+							}), 40);
+							return d;
+						}
+					},
+					{
+						name:'scriptsWithHtmlComments',
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							pane1.cleanContent = true;
+							pane1.attr('content', "<"
+								+"script><!-- unTypedVarInDocScope = 2; --><"
+								+"/script>");
+
+							var d = new t.Deferred();
+							// IE need a async here
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('number', typeof unTypedVarInDocScope);
+								t.assertEqual(2, unTypedVarInDocScope);
+							}), 40);
+
+							return d;
+						},
+						tearDown: function(){
+							delete pane1.cleanContent; // go back to default
+						}
+					},
+					{
+						name:'scriptsWithCData',
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							pane1.cleanContent = true;
+							pane1.attr('content', "<"
+								+"script><![CDATA[ unTypedVarInDocScope = 3; ]]><"
+								+"/script>");
+
+							var d = new t.Deferred();
+							// IE need a async here
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('number', typeof unTypedVarInDocScope);
+								t.assertEqual(3, unTypedVarInDocScope);
+							}), 40);
+
+							return d;
+						},
+						tearDown: function(){
+							delete pane1.cleanContent; // go back to default
+						}
+					},
+					{
+						name: 'replace_container_with_dijit.byId()',
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							unTypedVarInDocScope = 'failure';
+							pane1.scriptHasHooks = true;
+							pane1.attr('content', "<"
+							+"script>function testReplace(){"
+							+	"if(typeof _container_ != 'object'){return 'not replaced 1';}\n"
+							+	"if(_container_ != pane1){ return 'not replaced 2';}\n"
+							+	"if(!_container_ == pane1){ return 'not replaced 3';}\n"
+							+	"var tmp =_container_=dojo;\n"
+							+	"if(tmp != dojo){ return 'replaced when shouldnt 1';}\n"
+							+	"var tmp = _container_	\t \t = dojo;\n"
+							+	"if(tmp != dojo){ return 'replaced when shouldnt 2';}\n"
+							+	"return 'success';\n"
+							+"};\n"
+							+"unTypedVarInDocScope = testReplace();"
+							+"</"+"script>");
+
+							// let IE inhale here
+							var d = new t.Deferred();
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('success', unTypedVarInDocScope);
+							}), 40);
+							return d;
+						},
+						tearDown: function(){
+							delete pane1.scriptHasHooks; // get back to default
+						}
+					}/*,
+					{
+						name:'_container_onLoadDeferred|onUnloadDeferred',
+						runTest: function(t){
+							console.log("scriptTests: " + this.name);
+							pane1.scriptHasHooks = true;
+							pane1.attr('content', "<"
+								+"script>"
+								+"var testConn;"
+								+"_container_.onLoadDeferred.addCallback(function(){"
+								+	"testConn = dojo.connect(dojo.byId('testForm'), 'onsubmit', null, function(){"
+								+		"unTypedVarInDocScope = dojo.byId('testInput').value;"
+								+	"});"
+								+	"dojo.byId('testButton').click();"
+								+"});"
+								+"_container_.onUnloadDeferred.addCallback(function(){"
+								+		"unTypedVarInDocScope = 'unloaded';"
+								+	"dojo.disconnect(testConn);"
+								+"});"
+								+"<"+"/script><form onsubmit='return false;' id='testForm'>"
+								+	"<input id='testInput' value='loaded'/>"
+								+	"<input type='submit' id='testButton'/>"
+								+"</form>");
+
+							var d = new t.Deferred();
+							// IE must breathe here
+							setTimeout(d.getTestCallback(function(){
+								t.assertEqual('loaded', unTypedVarInDocScope);
+							}), 40);
+							return d;
+						},
+						tearDown: function(){
+							delete pane1.scriptHasHooks; // get back to default
+							pane1.attr('content', '');
+						}
+					},
+					"t.assertEqual('unloaded', unTypedVarInDocScope)"
+					*/
+				]
+			);
+
+
+			doh.register('regexRegressionAndSpeedtest',[
+				{
+					name: 'cssPathAdjustments',
+					runTest: function(t){
+						console.log("regexRegressionAndSpeedtest: " + this.name);
+						// we do this test as one big string to emulate as good as possible, 
+						// but split it later to easily see where we failed
+						var cssText = ".easy{ background-image:url(images/image.png) }\n"
+						+".dontReplaceEasy{ background-image:url(images/images/image.png) }\n"
+						+".hardurl{background-image:url(\t \"../../source/~test/%20t'e(s)t.gif(\"1')?foo=bar11103&bar=baz-foo\"	 \t);}body{};\n"
+						+".file{background-image: url(file:///home/nobody/image.png);}\n"
+						+".http{background-image: url(http://dojotoolkit.org/image.png);}\n"
+						+".https{background-image: url(https://dojotoolkit.org/image.png);}\n"
+						+".nonRelative{background-image:url(/toplevelfolder/image.gif);}\n"
+						+'@import "css/main.css";' + "\n at import \t'css/Newbee Url.css'\t;\n"
+						+"@import 'http://dojotoolkit.org/dojo.css';\n"
+						+"	@import 'you/never/thought/' print;\n"
+						+' @import url("it/would/work") tv, screen;'+"\n"
+						+' @import url(/did/you/now.css);'+"\n"
+						+' @import "yes.i.did";';
+
+						var expectedCss = ".easy{ background-image:url(deep/nested/images/image.png) }\n"
+						+".dontReplaceEasy{ background-image:url(deep/nested/images/images/image.png) }\n"
+						+".hardurl{background-image:url(source/~test/%20t'e(s)t.gif(\"1')?foo=bar11103&bar=baz-foo);}body{};\n"
+						+".file{background-image: url(file:///home/nobody/image.png);}\n"
+						+".http{background-image: url(http://dojotoolkit.org/image.png);}\n"
+						+".https{background-image: url(https://dojotoolkit.org/image.png);}\n"
+						+".nonRelative{background-image:url(/toplevelfolder/image.gif);}\n"
+						+"@import \"deep/nested/css/main.css\";\n at import \"deep/nested/css/Newbee Url.css\"\t;\n"
+						+"@import 'http://dojotoolkit.org/dojo.css';\n"
+						+"	@import \"deep/nested/you/never/thought/\" print;\n"
+						+' @import url(deep/nested/it/would/work) tv, screen;'+"\n"
+						+' @import url(/did/you/now.css);'+"\n"
+						+' @import "deep/nested/yes.i.did";';
+
+						for(var i = 0; i < 6; i++){
+							cssText += cssText;
+							expectedCss += expectedCss;
+						}
+
+						expectedCss = expectedCss.split("\n");
+
+						pane1.referencePath = "deep/nested/file";	// hook for testing to trigger path adjustment on an attr('content', ...)
+						pane1.adjustPaths = true;
+						pane1.renderStyles = true;
+						var adjustedCss;
+
+						// hijack internals to snatch the styles before they are inserted to DOM (DOM messes formating)
+						var oldFunc = pane1._contentSetter._renderStyles;
+						console.log("in cssPathAdjustments, returning function");
+
+						pane1._contentSetter._renderStyles = function(styles){
+							console.log("in replaced _renderStyles");
+							adjustedCss = styles.join();
+						}
+
+						var start = new Date();
+						pane1.attr('content', '<style>'+cssText+'</style>');
+						var end = new Date();
+						pane1._contentSetter._renderStyles = oldFunc;
+
+						adjustedCss = adjustedCss.split("\n");
+
+
+						console.info('Time used to regex scan css and adjust relative paths within css:'+
+								(end - start)+' ms on '+ cssText.split('\n').length
+								+' css rows, with '+ cssText.length+' characters (roughly '
+								+Math.round(cssText.length/1024)+ 'Kb) of infile css')
+
+						// we split and loop to get a faster hint of where it failed
+						for(var i = 0; i < expectedCss.length; i++){
+							t.assertEqual(expectedCss[i], adjustedCss[i]);
+						}
+					},
+					tearDown: function(){
+						delete pane1.adjustPaths; // get back to defaults
+						delete pane1.renderStyles;
+						delete pane1.referencePath;
+					}
+				}
+				,
+				{
+					name:'htmlPathsSpeedTest',
+					runTest: function(t){
+						console.log("regexRegressionAndSpeedtest: " + this.name);
+						var htmlText = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
+							+"<title>should be removed</title>\n"
+							+"<img src=\"images/image.gif\"/>Testing\n"
+							+"<a href=\"../../topmost.html\">\n"
+							+"	<img src=\"/siteroot/top.html\">\n"
+							+"	<p style='background:url(\"images/back.png\")'>\n"
+							+"	testing link\n"
+							+"</p></a>\n"
+							+"<style \ntype='text/css'>\n"
+							+"	@import 'http://dojotoolkit.org/visible.css' tv, screen;\n"
+							+"	@import \"./audio.css\" audio;\n"
+							+"	@import url(/topsite/css/main.css);\n"
+							+"	div.mywidget, #someId {\n"
+							+"		background-color:url(../../css/main.css);"
+							+"		display:none;\n"
+							+"		background:url(../tmp/css)\n"
+							+"	}\n"
+							+"</style>\n"
+							+"<link rel=\"stylesheet\" href=\"../../css/theme.css\" media=\"all\">\n"
+							+"<link media='print' type='text/css' rel='stylesheet' href='../../css/theme2.css'>\n"
+							+"<a style='display:block; background:url(/topmost/css)' href='../above'>above</a>\n"
+							+"<sc"+"ript type=\"text/javascript\"\n src=\"..\\windows\\morons\"></scr"+"ipt>\n"
+							+"<scr"+"ipt type=\"dojo/method\" src=\"/dont/mess/with/this\"></scr"+"ipt>\n"
+							+"<scr"+"ipt src=\"/dont/mess/here/either\" type=\"dojo/method\"></scr"+"ipt>\n"
+							+"<scr"+"ipt event=\"/havent/you/listened\" type=\"dojo/method\"></scr"+"ipt>\n"
+							+"<scr"+"ipt>JS CODE</scr"+"ipt>\n"
+							+"<a href='javascript:void(0)'>void</a>";
+
+
+						var expectedHtml = "\n\n<img src=\"deep/nested/images/image.gif\"/>Testing\n"
+							+"<a href=\"topmost.html\">\n"
+							+"	<img src=\"/siteroot/top.html\">\n"
+							+"	<p style='background:url(deep/nested/images/back.png)'>\n"
+							+"	testing link\n"
+							+"</p></a>\n"
+							+"\n"
+							+"\n\n"
+							+"<a style='display:block; background:url(/topmost/css)' href='deep/above'>above</a>\n\n"
+							+"<scr"+"ipt type=\"dojo/method\" src=\"/dont/mess/with/this\"></scr"+"ipt>\n"
+							+"<scr"+"ipt src=\"/dont/mess/here/either\" type=\"dojo/method\"></scr"+"ipt>\n"
+							+"<scr"+"ipt event=\"/havent/you/listened\" type=\"dojo/method\"></scr"+"ipt>\n\n"
+							+"<a href='javascript:void(0)'>void</a>";
+
+
+						var expectedCss = [
+							"\n @import 'http://dojotoolkit.org/visible.css' tv, screen;\n"
+							+"	@import \"deep/nested/audio.css\" audio;\n"
+							+"	@import url(/topsite/css/main.css);\n"
+							+"	div.mywidget, #someId {\n"
+							+"		background-color:url(css/main.css);"
+							+"		display:none;\n"
+							+"		background:url(deep/tmp/css)\n"
+							+"	}\n", "@import \"css/theme.css\";", "@import \"css/theme2.css\";"];
+
+						for(var i = 0; i < 6; i++){
+							htmlText += htmlText;
+							expectedHtml += expectedHtml;
+							expectedCss = expectedCss.concat(expectedCss);
+						}
+
+
+						pane1.referencePath = "deep/nested/file";	// hook for testing to trigger path adjustment on an attr('content', ...)
+						pane1.adjustPaths = true;
+						pane1.renderStyles = true;
+						pane1.cleanContent = true;
+						var adjustedCss, adjustedHtml;
+
+
+						// hijack internals to snatch the styles before they are inserted to DOM (DOM messes formating)
+						var oldFunc = pane1._contentSetter._renderStyles;
+
+						pane1._contentSetter._renderStyles = function(styles){
+							adjustedCss = styles;
+							pane1._contentSetter.executeScripts = false;
+						}
+
+						// we want to inspect the string without actually inserting it into the DOM 
+						// to make exact markup-string matching easier
+						var oldSetFunc = pane1._contentSetter.setContent;
+						pane1._contentSetter.setContent = function(){
+							adjustedHtml = this.content;
+						}
+
+						var oldXhr = dojo.xhrGet;
+						dojo.xhrGet = function(){}; // kill script download
+
+						var start = new Date();
+						pane1.attr('content', htmlText);
+						var end = new Date();
+
+						// reset back to the way it was
+						pane1._contentSetter._renderStyles = oldFunc;
+						pane1._contentSetter.setContent = oldSetFunc;
+						dojo.xhrGet = oldXhr;
+
+						console.info('Time used to regex scan html/css and\n adjust relative paths (adjustPaths=true),\n copy scripts (executeScripts=true) and copy css innerText (renderStyles=true) and adjust paths in there \nTime:'+
+								(end - start)+' ms on '+ htmlText.split('\n').length
+								+' html rows, with '+ htmlText.length+' characters (roughly '
+								+Math.round(htmlText.length/1024)+ 'Kb)');
+
+						// we split and loop to get a faster hint of where it failed
+						adjustedHtml = adjustedHtml.split("\n");
+						expectedHtml = expectedHtml.split("\n");
+
+						for(var i = 0; i < expectedHtml.length; i++){
+							//console.debug(expectedHtml[i], i);
+							//console.debug(adjustedHtml[i], i);
+							t.assertEqual(expectedHtml[i], adjustedHtml[i]);
+						}
+
+						var exCssBlock, adjCssBlock;
+						for(var i = 0; i < expectedCss.length; i++){
+							t.assertEqual('string', typeof adjustedCss[i]);
+
+							exCssBlock = expectedCss[i].split('\n');
+							adjCssBlock = adjustedCss[i].split('\n');
+
+							for(var j = 0; j < exCssBlock.length;j++){
+								t.assertEqual(dojo.trim(exCssBlock[j]), dojo.trim(adjCssBlock[j]));
+							}
+							
+						}
+					},
+					tearDown: function(){
+						delete pane1.cleanContent;
+						delete pane1.adjustPaths;
+						delete pane1.referencePath;
+						delete pane1.renderStyles;
+						delete pane1.executeScripts;
+					}
+				},
+				{
+					name:'IE_AlphaImageLoader_PathAdjustments',
+					runTest: function(t){
+						console.log("regexRegressionAndSpeedtest: " + this.name);
+						if(!dojo.isIE){
+							console.info('aborting test IE_AlphaImageLoader_PathAdjustments, you dont use IE');
+							return;
+						}
+
+						pane1.adjustPaths = true;
+						pane1.renderStyles = true;
+
+						pane1.href = "deep/";
+						pane1.referencePath = "deep/";	// hook for testing to trigger path adjustment on an attr('content', ...)
+
+						var html = "<div style='width:10px;height:10px;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=\"scale\", src=\"images/alpha(1).png\", nextProperty=\"useless\");'><!-- \n"
+						+" alpha png in IE 6 --></div>\n"
+						+"<style>\n"
+						+"	.ie_menu_png {"
+						+"		filter: \t progid:\n"
+						+"			DXImageTransform.Microsoft.AlphaImageLoader(\n"
+						+"			src='../midlevel/alpha(2).png')\n"
+						+"	}\n"
+						+" #my_transparent_png {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader( src='/images/alpha(3).png') }\n"
+						+" #my_transparent_png1 {filter: progid:DXImageTransform.Microsoft.AlhaImageLoader(src='http://no.se/images/alpha(4).png')}\n"
+						+"</style>\n";
+
+
+						var expectedHtml = "<div style='width:10px;height:10px;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=\"scale\", src=\"deep/images/alpha(1).png\", nextProperty=\"useless\");'><!-- \n"
+						+" alpha png in IE 6 --></div>\n\n";
+
+						var expectedCss = "\n"
+						+"	.ie_menu_png {"
+						+"		filter: \t progid:\n"
+						+"			DXImageTransform.Microsoft.AlphaImageLoader(\n"
+						+"			src='midlevel/alpha(2).png')\n"
+						+"	}\n"
+						+" #my_transparent_png {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader( src='/images/alpha(3).png') }\n"
+						+" #my_transparent_png1 {filter: progid:DXImageTransform.Microsoft.AlhaImageLoader(src='http://no.se/images/alpha(4).png')}\n";
+
+
+						for(var i = 0; i < 7; i++){
+							html += html;	
+							expectedHtml += expectedHtml;
+							expectedCss += expectedCss;
+						}
+
+						var adjustedHtml, adjustedCss;
+
+						// hijack internals to snatch the content
+						var oldRenderStyles = pane1._contentSetter._renderStyles;
+						var oldSetFunc = pane1._contentSetter.setContent;
+
+						pane1._contentSetter._renderStyles = function(styles){ adjustedCss = styles.join(''); };
+						pane1._contentSetter.setContent = function(){
+							adjustedHtml = this.content;
+						}
+
+						var start = new Date();
+						pane1.attr('content', html);
+						var end = new Date();
+
+						console.info('Time used to replace AlphaImageLoader(src="...") '
+									+(end - start) + "ms in HTML with "+html.length
+									+' characters (roughly '+(Math.round(html.length/1024))+'Kb)');
+
+						// reset hijacked
+						pane1._contentSetter._renderStyles = oldRenderStyles;
+						pane1._contentSetter.setContent = oldSetFunc;
+
+
+						// split on newline and run a check on each row to help debugging
+						expectedHtml = expectedHtml.split("\n");
+						adjustedHtml = adjustedHtml.split("\n");
+						for(var i = 0; i < expectedHtml.length; i++){
+							t.assertEqual(expectedHtml[i], adjustedHtml[i]);
+						}
+
+						expectedCss = expectedCss.split("\n");
+						adjustedCss = adjustedCss.split("\n");
+						for(var i = 0; i < expectedCss.length; i++){
+							t.assertEqual(expectedCss[i], adjustedCss[i]);
+						}
+						
+					},
+					tearDown: function(){
+						delete pane1.renderStyles;
+						delete pane1.adjustPaths;
+						delete pane1.referencePath;
+					}
+				}
+			]);
+
+			doh.register("A_AlphaImageLoader_inAction", [{
+				name:"AlphaLoaderShowHow",
+				runTest:function(t){
+				// IE filter alphaimageloader paths must be relative to the page
+				// not to the cssFile that declares it
+
+				// demo a much better way of "Fixing" alpha png in IE6 than inlining in html
+				var html = "<img src='images/dojoLogo.png' class='run_png_fix'/>"
+
+				var showHowHtml = "<pre >\nCode used in IE transparent png example\n"
+							+"code (declared in main page, not through ContentPane)\n"
+							+"<script type='text/javascript'>\n"
+							+fixPngIE6.toString().replace(/\n\t?/g, "\n")
+							+"\n</script>\n"
+							+"<style type='text/css'>\n"
+							+"	.run_png_fix {\n"
+							+"		background-image:url(images/blank.gif);\n"
+							+"		behaviour: expression(fixPngIE6.call(this));\n"
+							+"	}\n"
+							+"</style>\n\n...\n\nHtml feeded to ContentPane (or your main page):\n"
+							+"<img src='images/dojoLogo.png' class='run_png_fix'/>\n</pre>";
+
+				pane1.executeScripts = true;
+				pane1.renderStyles = true;
+				pane1.attr('content', html+showHowHtml);
+				
+
+				}
+			}]);
+
+			doh.run();
+		});
+	</script>
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		.box {
+			border: 1px solid black;
+			height: 190px;
+			width: 80%;
+			overflow: auto;
+		}
+
+		.red {
+			color: red;
+		}
+
+		.dojoxTestWidget {
+			border: 1px dashed red;
+			background-color: #C0E209 ;
+		}
+	</style>
+</head>
+<body class='tundra'>
+	<h1>dojox.layout.ContentPane</h1>
+	<h3>As dojox ContentPane is derived from dijit ContentPane, make sure that the dijit test passes before running this test</h3>
+	<h3 class='red'>Test relies on a php page as backend, so you need php installed on your server</h3>
+
+	<div class='box' dojoType="dojox.layout.ContentPane" id='parsedPane'>
+		Initial value
+	</div>
+
+	<table id='tableTest' class='box'>
+		<thead>
+			<tr>
+				<td></td>
+			</tr>
+		</thead>
+		<tbody>
+			<tr>
+				<td></td>
+			</tr>
+		<tbody>
+	</table>
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/layout/tests/_bottomPane.html b/dojox/layout/tests/_bottomPane.html
new file mode 100644
index 0000000..8f5090a
--- /dev/null
+++ b/dojox/layout/tests/_bottomPane.html
@@ -0,0 +1,53 @@
+<div class="wrap">
+	Bottom Pane Content:
+	<button dojoType="dijit.form.Button">
+		Setup Toggler
+		<script type="dojo/method" event="onClick">
+			// only do this once:
+			this.setAttribute('disabled',true);
+			var pane = dijit.getEnclosingWidget(this.domNode.parentNode);
+			
+			dijit.registry
+				.filter(function(n){
+					// there is probably an easier way to get all the Splitters
+					return n.declaredClass == "dijit.layout._Splitter";
+				})
+				.forEach(function(n){
+					// add some stuff to this instance:
+					dojo.mixin(n,{
+						// toggle additions:
+						_hackSize:null,
+						_hackShowing:true,
+						/*_setHack:function(e){
+							this._hackShowing = true;
+						},*/
+						_tgl: function(e){
+							if(this._hackShowing){
+								this._hackSize = dojo.marginBox(this.child.domNode);
+								this.child.domNode.style.height = "1px";
+							}else{
+								this.child.domNode.style.height = this._hackSize.h + "px";
+							}
+							// toggle state, and call layout() on parent
+							this._hackShowing = !this._hackShowing;
+							dijit.getEnclosingWidget(this.domNode.parentNode).layout();
+						}
+					});
+					// using it's internal connect method, setup the toggler
+					n.connect(n.domNode,"ondblclick","_tgl");
+					//n.connect(n,"_cleanupHandlers","_setHack");
+				});
+		</script>
+	</button>
+
+	<button dojoType="dijit.form.Button">
+		Minimize
+		<script type="dojo/method" event="onClick">
+			// simplified version of above:
+			var pane = dijit.getEnclosingWidget(this.domNode.parentNode);
+			pane.domNode.style.height = "1px";
+			dijit.byId("bc").layout();
+		</script>
+	</button>
+
+</div>
\ No newline at end of file
diff --git a/dojox/layout/tests/_expando.css b/dojox/layout/tests/_expando.css
new file mode 100644
index 0000000..93178f3
--- /dev/null
+++ b/dojox/layout/tests/_expando.css
@@ -0,0 +1,64 @@
+ at import "../../../dojo/resources/dojo.css";
+ at import "../../../dijit/tests/css/dijitTests.css";
+
+ at import "../resources/FloatingPane.css";
+ at import "../resources/ExpandoPane.css";
+
+body, html {
+	margin:0;
+	padding:0;
+	width:100%;
+	height:100%;
+	background: #fafafa;
+	overflow: hidden;
+}  
+.wrap {
+	margin: 0;
+	padding: 15px;
+}
+.wrap h3 {
+	margin-top: 5px;
+}
+#header {
+	height:32px;
+}
+.searchBar {
+	position: absolute;
+	top: 0;
+	left: 0;
+	right: 0;
+	height: 25px;
+	border-bottom: 1px solid #ccc;
+	background: #fafafa;
+}
+.searchBar p {
+	margin: 0;
+	padding: 2px; 
+}
+.searchStuff {
+	position: absolute;
+	top: 25px;
+	margin: 0 auto;
+}
+.searchStuff ul {
+	width: auto;
+	margin: 0 auto;
+	padding: 0;
+}
+div.itty {
+	font-weight: normal;
+	font: 8pt Arial,sans-serif;
+	color:#666;
+	padding:5px;
+	padding-left:10px;
+}
+div.itty:hover {
+	color:#333;
+}
+.itemType {
+	font-style:italic;
+	font-size:12pt;
+}
+#runSearchIcon {
+	border:1px solid #000;
+}
diff --git a/dojox/layout/tests/_floating.html b/dojox/layout/tests/_floating.html
new file mode 100644
index 0000000..5fe8f2d
--- /dev/null
+++ b/dojox/layout/tests/_floating.html
@@ -0,0 +1,48 @@
+<div class="wrap">
+	<h3>I am FloatingPane</h3>
+	<p>Windows in the Browser is weird UI, but sometimes useful. Even more useful:<br>
+	<br>
+	<button dojoType="dijit.form.Button">
+		Dock To Tab
+		<script type="dojo/method" event="onClick">
+			this.setAttribute("disabled",true);
+			var c = dijit.getEnclosingWidget(this.domNode.parentNode);
+			dojo.style(c.focusNode,"display","none");
+			dojo.style(c.domNode,{
+				position:"relative",
+				top:"0",
+				left:"0"
+			})
+			var tab = dijit.byId("centerPane");
+			tab.addChild(c);
+			tab.selectChild(c);
+		</script>
+	</button>
+	<br>
+	<button dojoType="dijit.form.Button">
+		Dock To Accordion
+		<script type="dojo/method" event="onClick">
+			this.setAttribute("disabled",true);
+			var n = dijit.getEnclosingWidget(this.domNode.parentNode);
+			dojo.style(n.focusNode,"display","none");
+			dojo.style(n.domNode,{
+				position:"relative",
+				top:"0",
+				left:"0"
+			})
+			var c = new dijit.layout.ContentPane({
+				title:n.title,
+				closable:n.closable
+			});
+			c.startup();
+			c.setContent(n.containerNode);
+			var accordion = dijit.byId("rightAccordion");
+			accordion.addChild(c);
+			accordion.selectChild(c);
+		</script>
+	</button>
+	<br><br>
+	(both technically unsupported)
+	</p>
+
+</div>
\ No newline at end of file
diff --git a/dojox/layout/tests/_lorem.html b/dojox/layout/tests/_lorem.html
new file mode 100644
index 0000000..9e7aaef
--- /dev/null
+++ b/dojox/layout/tests/_lorem.html
@@ -0,0 +1,11 @@
+<p>
+	Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam facilisis enim.
+    Pellentesque in elit et lacus euismod dignissim. Aliquam dolor pede, convallis eget,
+    dictum a, blandit ac, urna. Pellentesque sed nunc ut justo volutpat egestas. Class
+    aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos.
+    In erat. Suspendisse potenti. Fusce faucibus nibh sed nisi. Phasellus faucibus, dui
+    a cursus dapibus, mauris nulla euismod velit, a lobortis turpis arcu vel dui. Pellentesque
+    fermentum ultrices pede. Donec auctor lectus eu arcu. Curabitur non orci eget est porta gravida.
+    Aliquam pretium orci id nisi. Duis faucibus, mi non adipiscing venenatis, erat urna aliquet elit,
+    eu fringilla lacus tellus quis erat. Nam tempus ornare lorem. Nullam feugiat.
+</p>
diff --git a/dojox/layout/tests/_script.html b/dojox/layout/tests/_script.html
new file mode 100644
index 0000000..64bcd0e
--- /dev/null
+++ b/dojox/layout/tests/_script.html
@@ -0,0 +1,9 @@
+<script type="text/javascript">
+	console.log('foo - whenever');
+	dojo.addOnLoad(function(){
+		console.warn('foo - onload');
+	});
+</script>
+<p>
+ bar baz
+</p>
diff --git a/dojox/layout/tests/doc0.html b/dojox/layout/tests/doc0.html
new file mode 100644
index 0000000..10fd03a
--- /dev/null
+++ b/dojox/layout/tests/doc0.html
@@ -0,0 +1,14 @@
+<h1>Document 0</h1>
+This document has <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+(to check we're copying children around properly).<br />
+Also it's got a widget, a combo box:<br>
+<select dojoType="dijit.form.ComboBox">
+	<option value="1">foo</option>
+	<option value="2">bar</option>
+	<option value="3">baz</option>
+</select>
+And a button too:
+<button dojoType="dijit.form.Button" onclick="dijit.byId('remotePane').setHref('doc0.html');">Reload Me!</button>
+Here's some text that comes AFTER the button.
+Okay textbox:
+<input dojoType="dijit.form.TextBox" value="dndTest" />
diff --git a/dojox/layout/tests/images/blank.gif b/dojox/layout/tests/images/blank.gif
new file mode 100644
index 0000000..e565824
Binary files /dev/null and b/dojox/layout/tests/images/blank.gif differ
diff --git a/dojox/layout/tests/images/dojoLogo.png b/dojox/layout/tests/images/dojoLogo.png
new file mode 100755
index 0000000..1219de7
Binary files /dev/null and b/dojox/layout/tests/images/dojoLogo.png differ
diff --git a/dojox/layout/tests/images/gridUnderlay.png b/dojox/layout/tests/images/gridUnderlay.png
new file mode 100755
index 0000000..016f129
Binary files /dev/null and b/dojox/layout/tests/images/gridUnderlay.png differ
diff --git a/dojox/layout/tests/images/testImage.gif b/dojox/layout/tests/images/testImage.gif
new file mode 100644
index 0000000..4370d68
Binary files /dev/null and b/dojox/layout/tests/images/testImage.gif differ
diff --git a/dojox/layout/tests/remote/getResponse.php b/dojox/layout/tests/remote/getResponse.php
new file mode 100644
index 0000000..ac3b94b
--- /dev/null
+++ b/dojox/layout/tests/remote/getResponse.php
@@ -0,0 +1,108 @@
+<?php
+	// this file is just a bouncer for ContentPane.html test
+	error_reporting(E_ALL ^ E_NOTICE);
+	
+	if(isset($_GET['mode'])){
+		switch($_GET['mode']){
+			case 'htmlPaths':
+				echo "<img src='../images/testImage.gif' id='imgTest'/>
+					<div id='inlineStyleTest' style='width:188px;height:125px;background-image:url(../images/testImage.gif)'></div>
+					<style>@import 'getResponse.php?mode=importCss';</style>
+					<link type='text/css' rel='stylesheet' href='getResponse.php?mode=linkCss'>
+					<div id='importCssTest'></div>
+					<div id='linkCssTest'></div>
+					<div id='importMediaTest'></div>
+					<div id='linkMediaTest'></div>
+					<!-- these may download but not render -->
+					<style media='print'>@import 'getResponse.php?mode=importMediaPrint';</style>
+					<link media='print' type='text/css' rel='stylesheet' href='getResponse.php?mode=linkMediaPrint'>
+					";
+				break;
+	
+			case 'importCss':
+				header('Content-type: text/css; charset=utf-8');
+				echo "#importMediaTest {
+					margin: 4px;
+					border: 1px dashed red;
+					width: 200px;
+					height: 200px;
+				}
+				#importCssTest {
+						margin: 4px;
+						border: 1px solid blue;
+						width: 100px;
+						height: 100px;
+					}";
+				break;
+	
+			case 'linkCss':
+				header('Content-type: text/css; charset=utf-8');
+				echo "#linkMediaTest {
+					margin: 4px;
+					border: 2px dashed red;
+					width: 200px;
+					height: 200px;
+				}
+				#linkCssTest {
+					margin: 4px;
+					border: 2px dashed red;
+					width: 100px;
+					height: 100px;
+				}";
+				break;
+
+			case 'importMediaPrint': // may download but not render
+				header('Content-type: text/css; charset=utf-8');
+				echo "#importMediaTest {
+					margin: 10px;
+					border: 5px dashed gray;
+					width: 100px;
+					height: 100px;
+				}";
+				break;
+
+			case 'linkMediaPrint': // may download but not render
+				header('Content-type: text/css; charset=utf-8');
+				echo "#linkMediaTest {
+					margin: 10px;
+					border: 5px dashed gray;
+					width: 100px;
+					height: 100px;
+				}";
+				break;
+	
+			case 'remoteJsTrue':
+				header('Content-type: text/javascript; charset=utf-8');
+				echo "unTypedVarInDocScope = true;";
+				break;
+	
+			case 'remoteJsFalse':
+				header('Content-type: text/javascript; charset=utf-8');
+				echo "unTypedVarInDocScope = false;";
+				break;
+	
+			case 'bounceInput':
+				echo file_get_contents("php://input");
+				break;
+	
+			case 'bounceHeaders';
+				if(function_exists("apache_request_headers")){
+					$headers = apache_request_headers();
+					foreach($headers as $header => $vlu){
+						echo "$header=$vlu\n<br/>";
+					}
+				}else{
+					// IIS, php as CGI etc gets here, messes formating, suboptimal
+					$headers = preg_grep('/HTTP_/i', array_keys($_SERVER));
+					foreach($headers as $header){
+						$vlu = preg_replace(array('/^HTTP_/', '/_/'), array('', '-'), $header);
+						echo "$vlu={$_SERVER[$header]}\n<br/>";
+					}
+				}
+				break;
+	
+			default:
+				echo "unkown mode {$_GET['mode']}";
+		}
+	}
+?>
\ No newline at end of file
diff --git a/dojox/layout/tests/resources/script_dnd.js b/dojox/layout/tests/resources/script_dnd.js
new file mode 100644
index 0000000..6972ad8
--- /dev/null
+++ b/dojox/layout/tests/resources/script_dnd.js
@@ -0,0 +1,158 @@
+dojo.addOnLoad(init);
+var tabContainer, gridContainer;
+function init(){
+	tabContainer = dijit.byId("tb1");
+	dojo.subscribe("/dnd/drop/after", "createNode");
+	var adapter = dojox.mdnd.adapter.dndToDojo();
+	// register tabs of tabContainer.
+	var dojoNode = dojo.query('.dijitTab', tabContainer.tablist.containerNode).forEach(function(node){
+		adapter.register(node, tabContainer.declaredClass);
+	});
+	adapter.register(c2.node, "targetDojo", true, "Drag Me !");
+	
+	adapter.isAccepted = function(draggedNode, target){
+		//console.log("isAccepted ::: ", draggedNode, target);
+		var dndType = dijit.byNode(draggedNode).get("dndType");
+		switch(target.type){
+			case "dijit.layout.TabContainer" :
+				var tabButton = dijit.byNode(target.node);
+				var panes = tabContainer.getChildren();
+				for (var i = 0, l = panes.length; i < l; i++) {	
+					var gc = panes[i];
+					if (gc.controlButton == tabButton) {
+						for (var j=0; j < gc.acceptTypes.length; j++){
+							if (dndType == gc.acceptTypes[j]){
+								gridContainer = gc;
+								return true;
+							}
+						}
+						if (j == gc.acceptTypes.length){
+							return false;
+						}
+					}
+				}
+				break;
+			default:
+				return true;
+				break;
+			
+		};
+	};
+	
+	dojo.subscribe("/dojox/mdnd/adapter/dndToDojo/over", null, "onOver");
+	dojo.subscribe("/dojox/mdnd/adapter/dndToDojo/out", null, "onOut");
+	dojo.subscribe("/dojox/mdnd/adapter/dndToDojo/drop", null, "onDrop");
+	
+	dojo.subscribe("/dojox/mdnd/drop", null, function(){
+		dojo.forEach(dojoNode, function(node){
+			dojo.removeClass(node, "dndOver");
+			dojo.removeClass(node, "dndOverNotAccepted");
+		});
+	});
+	
+	dojo.subscribe(tabContainer.domNode.id+"-removeChild", null, "refresh");	
+};
+
+/**
+ * DojoDndAdapter functions :
+ * 	source/target dojo to D&D OAF Area
+ */
+
+/*Function: createNode
+ * 	Create a widget with a dojo draggedNode and drop this into a D&D OAF Area. 
+ */
+function createNode(source, nodes, copy, target, dropIndex){
+	//console.log("createNode ::: ", source, nodes, copy, target, dropIndex);
+	if(target){
+		var widget = _createWidget(nodes);
+		dojox.mdnd.areaManager().addDragItem(target, widget.domNode, dropIndex);
+	}
+};
+/*
+ * Widget Factory : Create a Dijit Widget with the type of draggedNode.
+ */
+function _createWidget(/*Array*/nodes){
+	var type = nodes[0].getAttribute("dndType");
+	var widget;
+	switch (type) {
+		case "ContentPane":
+			widget = new dijit.layout.ContentPane();
+			dojo.addClass(widget.domNode, 'cpane');
+			widget.set('dndType','ContentPane');
+			break;
+		case "Portlet":
+			widget = new dojox.widget.Portlet({
+				title: "portlet",
+				closable : true,
+				dndType:"Portlet"
+			});
+			break;
+		case "TitlePane":
+			widget = new dijit.TitlePane({
+				title: "TitlePane",
+				dndType:"TitlePane"
+			});
+			break;
+		default:
+			widget = new dijit.layout.ContentPane();
+			dojo.addClass(widget.domNode, 'cpane');
+			widget.set('dndType','ContentPane');
+			break;
+	}
+	widget.set('content','Lorem ipsum dolor sit amet, consectetuer adipiscing elit.');
+	widget.startup();
+	return widget;
+};
+
+/**
+ * Adapter functions
+ */
+
+/*Function: onOver
+ * Call when the OAF draggedNode enters in a dojo target registered by the oafDndAdapter
+ */
+function onOver(target, type, draggedNode, accept){
+	//console.info("onOver ::: ", target, type, draggedNode);
+	// add the dropIndicator style for the tab of tabContainer.
+	switch(type){
+		case "dijit.layout.TabContainer" :
+			if (accept){
+				dojo.addClass(target, "dndOver");
+			}
+			else{
+				dojo.addClass(target, "dndOverNotAccepted");
+			}
+		break;
+	}
+};
+
+/*Function: onOut
+ * Call when the OAF draggedNode exits of a dojo target registered by the oafDndAdapter
+ */
+function onOut(target, type, draggedNode, accept){
+	//console.info("onOut ::: ", target, type, draggedNode);
+	// remove the dropIndicator style for the tab of tabContainer.
+	switch(type){
+		case "dijit.layout.TabContainer" :
+			dojo.removeClass(target, "dndOver");
+			dojo.removeClass(target, "dndOverNotAccepted");
+		break;
+	}
+};
+
+function onDrop(node, target, type){
+	//console.log("onDrop ::: ", node, target, type);
+	switch(type){
+		case "dijit.layout.TabContainer" :
+			gridContainer.addChild(dijit.byNode(node), 0, 0); // add in first column / first element
+			dojo.removeClass(target, "dndOver");
+			dojo.removeClass(target, "dndOverNotAccepted");
+		break;
+	}
+};
+
+function refresh(){
+	//console.info("refresh");
+	dojox.mdnd.adapter.dndToDojo().refresh();
+};
+
diff --git a/dojox/layout/tests/resources/set_complete_dnd.css b/dojox/layout/tests/resources/set_complete_dnd.css
new file mode 100644
index 0000000..a0d5fe1
--- /dev/null
+++ b/dojox/layout/tests/resources/set_complete_dnd.css
@@ -0,0 +1,61 @@
+html,body{
+	margin:0;
+	padding:0;
+}
+
+.cpane{
+	border:1px solid #666;
+	font:bold 12px Arial;
+	color:#000;
+	background:#FFF;
+	padding:10px;
+	height:100px;
+}	
+
+.gridContainerZone > *{
+	margin: 10px;
+}
+
+.dj_ie6 .dropIndicator, .dj_ie6 .cpane, .dj_ie6 .dojoxPortlet, .dj_ie6 .cpane, .dj_ie6 .dijitTitlePane{
+	margin: 10px;
+}
+
+.container {
+	border:3px solid #ccc;
+	padding: 1em 3em; 
+	cursor: default;
+	radius:8pt;
+	background:#fff;
+	-moz-border-radius:8pt 8pt;
+}
+
+.dojoDndItem { 
+	padding:3px; 
+}
+
+.dojoDndItemOver {
+	background: #ededed;
+	cursor:pointer;
+}
+
+.dojoDndAvatarItem .dojoDndItemOver {
+	background: transparent;
+}
+
+.dragNode{
+	opacity:0.6; 
+	filter:alpha(opacity=60); 
+	-khtml-opacity:0.6; 
+	-moz-opacity:0.6;
+}
+
+.dndOver{
+	color:green;
+	font-weight:bold;
+}
+
+.dndOverNotAccepted{
+	color:red;
+	font-weight:bold;
+	cursor:not-allowed;
+}
diff --git a/dojox/layout/tests/test_DragPane.html b/dojox/layout/tests/test_DragPane.html
new file mode 100644
index 0000000..fee1e8b
--- /dev/null
+++ b/dojox/layout/tests/test_DragPane.html
@@ -0,0 +1,202 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>DragPane layout widget Test</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../DragPane.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.layout.DragPane");
+		dojo.require("dojo.parser");
+	</script>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		.fbox { float:left; width:200px; height:200px; margin:0; padding:0; }
+		.hasHand { cursor:pointer !important; }
+		.box { width:25px; height:25px; background:#000; position:absolute; }
+		#br { bottom:5px; right:5px; }
+		#bl { left:5px; bottom:5px; }
+		#tl { top:5px; left:5px; }
+		#tr { top:5px; right:5px; }
+		.hugetext {
+			font:22pt Arial,sans-serif;
+			font-weight:bold;
+		}
+		#container0,
+		#container {
+			overflow:auto;
+			width:600px;
+			height:300px;
+			border:4px solid #ededed;
+			background:#ededed;
+		}
+		#innerThing {
+			width:400px; height:400px;
+		}
+	</style>
+
+</head>
+<body class="tundra">
+	
+	<h1 class="testTitle">dojox.layout.DragPane</h1>
+	<p>A simple widget to drag contents around within a sized div</p>
+	
+	<h2>Inverted dragging</h2>
+	<div class="hugetext" id="container" dojoType="dojox.layout.DragPane">
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>	
+	</div>
+
+	<h2>Not inverted</h2>
+	<div class="hugetext" id="container0" invert="false" dojoType="dojox.layout.DragPane">
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>	
+	</div>
+	
+	<!--h2>An Image:</h2>
+	
+	<div dojoType="dojox.layout.DragPane" id="imagePane" style="width:200px; height:200px; overflow:hidden;">
+		<div id="innerThing">
+		<div class="fbox">
+			<p style="color:#666; padding:8px; margin:0;">
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+			porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+			sagittis turpis. purus purus in nibh. Phasellus in nunc.
+			</p>					
+		</div>
+		<div class="fbox">
+			<p style="color:#666; padding:8px; margin:0;">
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+			porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+			sagittis turpis. purus purus in nibh. Phasellus in nunc.
+			</p>					
+		</div>
+		<div class="fbox">
+			<p style="color:#666; padding:8px; margin:0;">
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+			porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+			sagittis turpis. purus purus in nibh. Phasellus in nunc.
+			</p>					
+		</div>
+		<div class="fbox">
+			<p style="color:#666; padding:8px; margin:0;">
+			Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+			porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+			sagittis turpis. purus purus in nibh. Phasellus in nunc.
+			</p>					
+		</div>
+		</div>
+	</div-->
+	
+</body>
+</html>
diff --git a/dojox/layout/tests/test_ExpandoPane.html b/dojox/layout/tests/test_ExpandoPane.html
new file mode 100644
index 0000000..e4be70f
--- /dev/null
+++ b/dojox/layout/tests/test_ExpandoPane.html
@@ -0,0 +1,327 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.layout.ExpandoPane</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<!-- test file style rollup, you need resources/ExpandoPane.css exclusively -->
+	<link rel="stylesheet" href="_expando.css">	
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true, popup:true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script src="../ExpandoPane.js" type="text/javascript"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.layout.ExpandoPane");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dojox.layout.FloatingPane");
+		dojo.require("dojo.fx.easing");
+		dojo.require("dojox.rpc.Service");
+		dojo.require("dojo.io.script");
+	</script>
+
+	<script type="text/javascript">
+		dojo.declare("demo.DemoPane",dijit.layout.ContentPane,{
+
+			startup: function(){
+				this.inherited(arguments);
+				this.rpc.get({ name: this.title, 
+					attributes:["summary","type","source","description","examples"]			 
+				}).addCallback(dojo.hitch(this,"_setSelf"));
+			},
+			_setSelf:function(data){
+				var out = "";
+				dojo.forEach(data,function(d){
+					console.log(d);
+					if(d.name){
+						out += "<h2>" + d.name + " <span class='itemType'>" + d.type +"</span></h2>";
+					}
+					if(d.summary){
+						out += "<div class='summary'>" + d.summary + "</div>";
+					}
+				});
+				this.setContent(out);
+
+			}
+			
+		});
+		
+		var togglePane = function(e){
+			
+				var lp = dijit.byId("leftPane");
+				var sel = dojo.byId("easingSelect");
+				var o = dojo.getObject("dojo.fx.easing."+sel.value);
+			
+				lp.easeIn = o;
+				lp.easeOut = o;
+				lp.duration = parseInt(dojo.byId("durationBox").value) || 1000;
+				lp._setupAnims();
+				lp.toggle();
+		};
+		
+		var easeSelectionCode = function(){
+			var sel = dojo.byId("easingSelect");
+			dojo.connect(sel,"onchange",togglePane);
+			dojo.connect(dojo.byId("durationBox"),"onchange",togglePane);
+			var opt = dojo.query("#easingSelect option")[0];
+			for(var i in dojo.fx.easing){
+				var n = dojo.clone(opt);
+				n.value = i;
+				n.innerHTML = i;
+				sel.appendChild(n);
+			}
+		};
+
+		var _clearSearch = function(){
+			dojo.query("li","searchResults").forEach(dojo.destroy);
+		};
+		
+		var shifter = function(input){
+			// convert an array to a object, just that deep
+			var last, output;
+			last = output = {};
+			for(var i = 0; i < input.length; i++){
+			  if(i == input.length - 2){
+			   last[input[i]] = input[i + 1];
+			   break;
+			 }
+			 last = last[input[i]] = {};
+			}
+			return output;
+		};
+		
+		var makeTree = function(data){
+			var undata = {
+				dojo:{}, dijit:{}, dojox:{}
+			};
+			var items = [];
+			dojo.forEach(data,function(item){
+				var foo = item.name.split(".");
+				foo.push("_meta");
+				foo.push(item);
+				//var ns = foo.shift();
+				var obj = shifter(foo);
+				items.push(obj);
+			});
+			return items;
+		};
+		
+		var runSearch = function(e){
+			dijit.byId("centerPane").selectChild(dijit.byId("resultsPane"));
+			var val = dojo.byId("searchBox").value;
+			var li = dojo.doc.createElement('li');
+			_clearSearch();
+			li.appendChild(dojo.clone(dojo.query(".cloneNode")[0]));
+			dojo.byId("searchResults").appendChild(li);
+			searchHistory.push(val);
+			api.get({ name:val }).addCallback(function(data){
+				var tree = makeTree(data);
+		
+				_clearSearch();
+				
+				dojo.forEach(data,function(item){
+					console.log(item);
+					var list = dojo.byId("")
+					var nli = dojo.doc.createElement('li');
+					nli.innerHTML = "<div class='inner'>"
+						+"<a"+" hre"+"f='#"+ item.name +"'>"+item.name +"</a>"
+						+"- <span class='itemType'>"+ item.type +"</span>"
+						+"<div class='itty'>"+item.summary+"</div></div>";
+					dojo.byId("searchResults").appendChild(nli);
+				});
+			})
+		};
+
+		var searchInteract = function(e){
+			e.preventDefault();
+			var v;
+			if((v = dojo.attr(e.target,"href"))){
+				var tabs = dijit.byId("centerPane");
+				v = v.replace(/#/g,"");
+				var cp = dijit.byId(v);
+				if(!cp){
+					var cp = new demo.DemoPane({
+						title:v,
+						closable:true,
+						id:v,
+						rpc:api
+					});
+					cp.startup();
+					tabs.addChild(cp);
+				}
+				tabs.selectChild(cp);
+			}
+		};
+
+		var searchHistory = [];
+		var rpc = null;
+		var apiData = {};
+		var _clone = null;
+		var searchCode = function(){
+			_clone = dojo.query(".cloneLoading")[0];
+			api = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc", "SMDLibrary/dojo-api.smd"));
+			dojo.connect(dojo.byId("searchBox"),"onchange",runSearch);
+			dojo.connect(dojo.byId("runSearchIcon"),"onclick",runSearch);
+			dojo.connect(dojo.byId("searchResults"),"onclick",searchInteract);
+		}
+
+		dojo.addOnLoad(easeSelectionCode);
+		dojo.addOnLoad(searchCode);
+
+	</script>
+</head>
+<body class="tundra">
+		<div id="bc" style="width:100%; height:100%; padding: 5px;" dojoType="dijit.layout.BorderContainer">
+			<div id="header" dojoType="dijit.layout.ContentPane" region="top" splitter="true">Dojo Expando Pane Test</div>
+			<div dojoType="dojox.layout.ExpandoPane" 
+				splitter="true" 
+				duration="125" 
+				region="left" 
+				title="Left Section" 
+				previewOnDblClick="true"
+				id="leftPane" 
+				maxWidth="275" 
+				style="width: 275px;">
+				<div dojoType="dijit.layout.TabContainer" attachParent="true" tabPosition="bottom" tabStrip="true">
+					<div dojoType="dijit.layout.ContentPane" title="Search">
+						<div class="searchBar">
+							<p>
+								<span style="float: left;">Search:</span>
+								<input id="searchBox" name="searchBox" style="float: left;">
+								<span id="runSearchIcon" style="border: none; floast: left; padding: 3px;">
+									<img src="../../presentation/resources/icons/next.png" style="height:12px; width:12px;">
+								</span>
+							</p>
+						</div>
+						
+					</div>
+					<div dojoType="dijit.layout.AccordionContainer" title="Panes" style="width:275px;" attachParent="true">
+						<div dojoType="dijit.layout.ContentPane" title="Dojo">
+							<ul id="dojoList"></ul>
+						</div>
+						<div dojoType="dijit.layout.ContentPane" title="Dijit">
+							<ul id="dijitList"></ul>
+						</div>
+						<div dojoType="dijit.layout.ContentPane" title="DojoX">
+							<ul id="dojoxList"></ul>
+						</div>
+					</div>
+					<div dojoType="dijit.layout.ContentPane" title="Tree View">
+						<div dojoType="dojo.data.ItemFileReadStore" jsId="continentStore"
+							url="../../../dijit/tests/_data/countries.json"></div>
+						<div dojoType="dijit.Tree" store="continentStore" query="{type:'continent'}"
+							labelAttr="name" typeAttr="type" label="Toolkit API"></div>
+					</div>
+				</div>
+			</div>
+			<div dojoType="dijit.layout.TabContainer" region="center" id="centerPane" tabStrip="true">
+				<div dojoType="dijit.layout.ContentPane" title="tab 1">a</div>
+				<div dojoType="dijit.layout.ContentPane" title="tab 2">
+					<button dojoType="dijit.form.Button">Preview left
+						<script type="dojo/method" event="onClick">
+							dijit.byId("leftPane").preview();
+						</script>
+				</div>
+				<div dojoType="dijit.layout.ContentPane" title="Results" id="resultsPane">
+					<div class="wrap">
+						<div class="searchStuff">
+							<ul id="searchResults"></ul>
+						</div>
+					</div>
+				</div>
+			</div>
+			<div dojoType="dojox.layout.ExpandoPane" 
+				splitter="true" 
+				title="Right Section" 
+				region="right" 
+				id="rightPane" 
+				maxWidth="275" 
+				style="width:275px" 
+				easeIn="dojo.fx.easing.backOut" 
+				easeOut="dojo.fx.easing.backInOut">
+
+				<div dojoType="dijit.layout.AccordionContainer" id="rightAccordion" style="width:275px;" attachParent="true">
+					<div dojoType="dijit.layout.ContentPane" title="Easing Selection">
+						<div class="wrap">
+							<p>This select modifies the left Expando's easing function. An Expando can have an easeIn and an easeOut parameter. This sets both.</p> 
+							<select id="easingSelect" name="easingSelect">
+								<option value="dojo._DefaultEasing">Default</option>
+							</select>
+							<p><label for="durationBox">Duration: </label> <input id="durationBox" name="durationBox" value="1000" /></p>
+							<p>Some easing functions break when used with width: (negative width? but how?). <em>Be warned.</em></p>
+						</div>
+					</div>
+					<div dojoType="dijit.layout.ContentPane" title="Children">
+						<div class="wrap">
+							<p>This is a BorderContainer (the window). Each of the panes is set to one of
+							"left", "right", or "center". The left and right panes are ExpandoPanes (they collapse).
+							</p>
+							<p>What does a FloatingPane look like here?</p>
+							<p>
+							<button dojoType="dijit.form.Button">
+								Make Floater
+								<script type="dojo/connect" event="onClick">
+									var div = dojo.doc.createElement('div');
+									dojo.body().appendChild(div);
+									var fp = new dojox.layout.FloatingPane({
+										title:"A Winder.",
+										closeable:true, dockable:false,
+										href:"_floating.html"
+									},div);
+									dojo.style(fp.domNode,{
+										width:"350px",
+										height:"255px",
+										top:"75px", left:"75px",
+										position:"absolute",
+										zIndex:"980"
+									});
+									fp.startup();
+									fp.show();
+								</script>
+							</button>
+							</p>
+							<p>the end</p>
+						</div>
+					</div>
+					<div dojoType="dijit.layout.ContentPane" title="Acc 3">c</div>
+				</div>
+			</div>
+			<div dojoType="dojox.layout.ExpandoPane" 
+				splitter="true" 
+				duration="125" 
+				region="bottom" 
+				title="Bottom Section" 
+				id="bottomPane" 
+				maxWidth="275" 
+				style="height: 100px;">
+				<div dojoType="dijit.layout.TabContainer" attachParent="true" tabPosition="bottom" tabStrip="true">
+					<div dojoType="dijit.layout.ContentPane" title="Search">
+												
+					</div>
+					<div dojoType="dijit.layout.AccordionContainer" title="Panes" style="width:275px;" attachParent="true">
+						
+					</div>
+					<div dojoType="dijit.layout.ContentPane" title="Tree View">
+						
+					</div>
+				</div>
+			</div>
+		</div>
+
+		<div class="cloneNode">Loading <img style="width:17px; height:17px" src="../../image/resources/images/loading.gif" alt="progress" /></div>
+
+</body>
+</html>
diff --git a/dojox/layout/tests/test_ExpandoPane_code.html b/dojox/layout/tests/test_ExpandoPane_code.html
new file mode 100644
index 0000000..6455bb9
--- /dev/null
+++ b/dojox/layout/tests/test_ExpandoPane_code.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.layout.ExpandoPane</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<!-- test file style rollup, you need resources/ExpandoPane.css exclusively -->
+	<link rel="stylesheet" href="_expando.css">	
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.layout.ExpandoPane");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.BorderContainer");
+		
+		var _clearPane = function(){
+			var ch = dijit.byId("bc").getChildren();
+			dojo.forEach(["pane0","pane1","pane2","pane3"],function(p){
+
+				dojo.byId("hidden").appendChild(dojo.byId(p));
+				var dij = dijit.getEnclosingWidget(p.parentNode);
+				if(dij){
+					console.log(dij);
+					dijit.byId("bc").removeChild(dij);
+					dij.destroy();
+				}
+
+			});
+		};
+
+	</script>
+	<style type="text/css">
+		#hidden {
+			position:absolute;
+			top:-999px;
+			left:-999px;
+			overflow:hidden;
+			width:500px;
+			height:500px;
+			visibility:hidden;
+		}
+		#pane0, #pane1, #pane2, #pane3 {
+			width:100%;
+			height:100%;
+		}
+		#pane1 { background:red; }
+		#pane2 { background:green; }
+		#pane3 { background:blue; }
+		#pane0 { background:yellow; }
+	</style>
+</head>
+<body class="tundra">
+		<div id="bc" style="width:100%; height:100%;" dojoType="dijit.layout.BorderContainer">
+			<div region="center" style="height:65px; border-bottom:1px solid #666">
+				<button dojoType="dijit.form.Button">
+					Set 3-pane
+					<script type="dojo/method" event="onClick">
+						_clearPane();
+						var bc = dijit.byId("bc");
+						
+						var cp = new dijit.layout.ContentPane({
+							region:"left",
+							style:"width:125px; height:100%",
+							splitter:true
+						});
+						cp.domNode.appendChild(dojo.byId("pane1"));
+						cp.startup();
+						bc.addChild(cp);
+						
+						var cp2 = new dijit.layout.ContentPane({
+							region:"right",
+							style:"width:125px; height:100%",
+							splitter:true
+						});
+						cp2.domNode.appendChild(dojo.byId("pane2"));
+						cp2.startup();
+						bc.addChild(cp2);
+						
+						var cp3 = new dijit.layout.ContentPane({
+							region:"center"
+							
+						});
+						cp3.domNode.appendChild(dojo.byId("pane0"));
+						cp3.startup();
+						bc.addChild(cp3);
+						
+						bc.layout();
+					</script>
+				</button>
+			</div>
+			
+		</div>
+		<div id="hidden">
+			<div id="pane0">pane 0 content</div>
+			<div id="pane1">pane 1 content</div>
+			<div id="pane2">pane 2 content</div>
+			<div id="pane3">pane 3 content</div>
+		</div>
+</body>
+</html>
diff --git a/dojox/layout/tests/test_ExpandoPane_more.html b/dojox/layout/tests/test_ExpandoPane_more.html
new file mode 100644
index 0000000..4656543
--- /dev/null
+++ b/dojox/layout/tests/test_ExpandoPane_more.html
@@ -0,0 +1,149 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.layout.ExpandoPane</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<!-- test file style rollup, you need resources/ExpandoPane.css exclusively -->
+	<link rel="stylesheet" href="../resources/ExpandoPane.css">
+	<link rel="stylesheet" href="../../../dijit/tests/css/dijitTests.css">
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<style type="text/css">
+		body, html {
+			height:100%;
+		}
+	</style>
+
+	<!-- for debugging -->
+	<script src="../ExpandoPane.js" type="text/javascript"></script>
+	<script type="text/javascript">
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dojo.fx.easing");
+	</script>
+</head>
+<body class="tundra">
+
+	<h1>Basic ExpandoPane tests</h1>
+
+	<h2>Left:</h2>
+	<div dojoType="dijit.layout.BorderContainer" style="height:275px; border: solid #ccc 1px;">
+		<div dojoType="dojox.layout.ExpandoPane" title="leftTest" region="left" maxWidth="175" style="width:175px; background:red">
+			foo
+		</div>
+		<div dojoType="dijit.layout.TabContainer" region="center" tabStrip="true">
+			<div dojoType="dijit.layout.ContentPane" title="tab 1" href="_lorem.html"></div>
+			<div dojoType="dijit.layout.ContentPane" title="tab 2" href="_lorem.html"></div>
+		</div>
+	</div>
+
+	<h2>Right:</h2>
+	<div dojoType="dijit.layout.BorderContainer" style="height:275px; border: solid #ccc 1px;">
+		<div dojoType="dojox.layout.ExpandoPane" title="rightTest" region="right" maxWidth="175" style="width:175px; background:red">
+			<div dojoType="dijit.layout.TabContainer" tabPosition="bottom" attachParent="true" tabStrip="true">
+				<div dojoType="dijit.layout.ContentPane" attachParent="true" title="tab 1" href="_lorem.html"></div>
+				<div dojoType="dijit.layout.ContentPane" title="tab 2" href="_lorem.html"></div>
+			</div>
+		</div>
+		<div dojoType="dijit.layout.TabContainer" region="center" tabStrip="true">
+			<div dojoType="dijit.layout.ContentPane" title="tab 1" href="_lorem.html"></div>
+			<div dojoType="dijit.layout.ContentPane" title="tab 2" href="_lorem.html"></div>
+		</div>
+	</div>
+
+	<h2>Top (easeIn="dojo.fx.easing.bounceOut" duration="1200"):</h2>
+	<div dojoType="dijit.layout.BorderContainer" style="height:275px; border: solid #ccc 1px;">
+		<div easeIn="dojo.fx.easing.bounceOut" duration="1200" dojoType="dojox.layout.ExpandoPane" title="topTest" region="top" maxHeight="75" style="height:75px; background:red">
+			foo
+		</div>
+		<div region="center" dojoType="dijit.layout.ContentPane" href="_lorem.html"></div>
+	</div>
+
+	<h2>Bottom:</h2>
+	<div dojoType="dijit.layout.BorderContainer" style="height:375px; border:8px solid #333;">
+		<div dojoType="dojox.layout.ExpandoPane" title="bottomTest" region="bottom" maxHeight="75" style="height:75px;">
+			foo
+		</div>
+		<div region="center" dojoType="dijit.layout.ContentPane" href="_lorem.html"></div>
+	</div>
+
+	<h2>Bottom/Left:</h2>
+	<div dojoType="dijit.layout.BorderContainer" style="height:375px; border:8px solid #333;">
+		<div dojoType="dojox.layout.ExpandoPane" title="leftTest" region="left" maxWidth="175" style="width:175px; background:red;">
+			foo
+		</div>
+		<div dojoType="dojox.layout.ExpandoPane" title="bottomTest" region="bottom" maxHeight="75" style="height:75px;">
+			foo
+		</div>
+		<div region="center" dojoType="dijit.layout.ContentPane" href="_lorem.html"></div>
+	</div>
+
+	<h2>Top/Left/Right</h2>	
+	<div dojoType="dijit.layout.BorderContainer" style="height:375px; border:8px solid #333;">
+		<div dojoType="dojox.layout.ExpandoPane" title="leftTest" region="left" maxWidth="175" style="width:175px; background:red;">
+			foo
+		</div>
+		<div dojoType="dojox.layout.ExpandoPane" title="leftTest" region="right" maxWidth="175" style="width:175px; background:red;">
+			foo
+		</div>
+		<div dojoType="dojox.layout.ExpandoPane" title="bottomTest" region="bottom" maxHeight="75" style="height:75px;">
+			foo
+		</div>
+		<div region="center" dojoType="dijit.layout.ContentPane" href="_lorem.html"></div>
+	</div>	
+
+	<h2>Bottom/Left/Right + splitters</h2>	
+	<div dojoType="dijit.layout.BorderContainer" style="height:375px; border:8px solid #333;">
+		<div splitter="true" dojoType="dojox.layout.ExpandoPane" title="leftTest" region="left" maxWidth="175" style="width:175px; background:red;">
+			foo
+		</div>
+		<div splitter="true" dojoType="dojox.layout.ExpandoPane" title="leftTest" region="right" maxWidth="175" style="width:175px; background:red;">
+			foo
+		</div>
+		<div splitter="true" dojoType="dojox.layout.ExpandoPane" title="bottomTest" region="bottom" maxHeight="75" style="height:75px;">
+			foo
+		</div>
+		<div region="center" dojoType="dijit.layout.ContentPane" href="_lorem.html"></div>
+	</div>	
+
+	<h2>Same, all closed</h2>
+	<div dojoType="dijit.layout.BorderContainer" style="height:375px; border:8px solid #333;">
+		<div splitter="true" startExpanded="false" dojoType="dojox.layout.ExpandoPane" title="leftTest" region="left" maxWidth="175" style="width:175px; background:yellow;">
+			foo
+		</div>
+		<div splitter="true" startExpanded="false" dojoType="dojox.layout.ExpandoPane" title="leftTest" region="right" maxWidth="175" style="width:175px; background:yellow;">
+			foo
+		</div>
+		<div splitter="true" startExpanded="false" dojoType="dojox.layout.ExpandoPane" title="bottomTest" region="bottom" maxHeight="75" style="height:75px; background:yellow;">
+			foo
+		</div>
+		<div region="center" startExpanded="false" dojoType="dijit.layout.ContentPane" href="_lorem.html"></div>
+	</div>	
+
+	<h2>Same, Leading / Trailing</h2>
+	<div dojoType="dijit.layout.BorderContainer" style="height:375px; border:8px solid #333;" design="sidebar">
+		<div splitter="true" startExpanded="false" dojoType="dojox.layout.ExpandoPane" title="leftTest" region="leading" maxWidth="175" style="width:175px; background:yellow;">
+			foo
+		</div>
+		<div splitter="true" startExpanded="false" dojoType="dojox.layout.ExpandoPane" title="rightTest" region="trailing" maxWidth="175" style="width:175px; background:yellow;">
+			foo
+		</div>
+		<div splitter="true" startExpanded="false" dojoType="dojox.layout.ExpandoPane" title="topTest" region="top" maxHeight="75" style="height:75px; background:yellow;">
+			foo
+		</div>
+		<div region="center" startExpanded="false" dojoType="dijit.layout.ContentPane" href="_lorem.html"></div>
+	</div>	
+
+
+</body>
+</html>
diff --git a/dojox/layout/tests/test_ExpandoPane_prog.html b/dojox/layout/tests/test_ExpandoPane_prog.html
new file mode 100644
index 0000000..79f73d8
--- /dev/null
+++ b/dojox/layout/tests/test_ExpandoPane_prog.html
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.layout.ExpandoPane</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css" />
+	<!-- required: supplemental styles for this widget -->
+	<link rel="stylesheet" href="../resources/ExpandoPane.css" />
+	
+	<!-- used for test design only: -->
+	<link rel="stylesheet" href="../../../dijit/tests/css/dijitTests.css" />
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<style type="text/css">
+		body, html {
+			height:100%;
+		}
+	</style>
+
+	<!-- for debugging -->
+	<script src="../ExpandoPane.js" type="text/javascript"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.layout.ExpandoPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dojo.fx.easing");
+
+		var constructTabContainerTest = function(){
+			
+			var parent = dojo.byId("container0");
+			console.log("Parent id is: ", parent.id);
+			
+			var tabContainer = new dijit.layout.TabContainer({
+				id: "0",
+				tabPosition: "top",
+				style:"height:400px; width: 100%;"
+			}).placeAt(parent);
+			
+			var cp2 = new dijit.layout.ContentPane({
+				id: "0.2",
+				title: "Tab 1"
+			}).placeAt(tabContainer);
+			
+			tabContainer.startup();
+			constructBorderContainerExpandoPaneTest(tabContainer, "0.1");
+			// FIXME: if cp2 isn't visible, Expando's collapse to 0px? TitleHeight calc'd at 0?!
+			//constructBorderContainerExpandoPaneTest(cp2, "0.2");
+			
+		}
+		
+		var constructBorderContainerExpandoPaneTest = function(parent, cid){
+			console.log ("Parent id is: " + parent.id);
+			
+			var borderContainer = new dijit.layout.BorderContainer({
+				id: cid + "." + 0,
+				title:"Tab 2",
+				design: "horizontal",
+				style: "height:350px;",
+				selected:true
+			}).placeAt(parent);
+			parent.selectChild(borderContainer);
+			
+			// add a center region:
+			var cr = new dijit.layout.ContentPane({
+				id: cid + "center",
+				region: "center"
+			}).placeAt(borderContainer);
+			
+			var ep = new dojox.layout.ExpandoPane({
+				id: cid + "." + 1,
+				title: "Left Section Test",
+				region: "left",
+				style: "width: 33%; height: 98%; background-color:#FFDEAD"
+			}).placeAt(borderContainer);
+
+			var ep1 = new dojox.layout.ExpandoPane({
+				id: cid + "." + 2,
+				title: "Right Section Test",
+				region: "right",
+				style: "width: 33%; height: 98%; background-color:#FFDEAD"
+			}).placeAt(borderContainer);
+			
+			borderContainer.startup();
+			
+		}
+		
+		// build the UI immediately onload:
+		dojo.addOnLoad(constructTabContainerTest);
+
+	</script>
+</head>
+<body class="tundra">
+	<h1 class="testTitle">Programatic ExpandoPane Test</h1>
+	<div id="container0"></div>
+</body>
+</html>
diff --git a/dojox/layout/tests/test_ExpandoPane_splitters.html b/dojox/layout/tests/test_ExpandoPane_splitters.html
new file mode 100644
index 0000000..e9ae23c
--- /dev/null
+++ b/dojox/layout/tests/test_ExpandoPane_splitters.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.layout.ExpandoPane</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<!-- test file style rollup, you need resources/ExpandoPane.css exclusively -->
+	<link rel="stylesheet" href="../resources/ExpandoPane.css">
+	<link rel="stylesheet" href="../../../dijit/tests/css/dijitTests.css">
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dojox.layout.ExpandoPane");
+	</script>
+</head>
+<body class="tundra">
+
+	<h1>Testing splitters on ExpandoPanes</h1>
+
+	<h2>splitter="true":</h2>
+	<div dojoType="dijit.layout.BorderContainer" style="height:275px; border: solid #ccc 1px;">
+		<div dojoType="dojox.layout.ExpandoPane" splitter="true" title="leftTest" region="left" maxWidth="175" style="width:175px; background:red">
+			foo
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="center" href="_lorem.html"></div>
+	</div>
+
+	<h2>splitter="false":</h2>
+	<div dojoType="dijit.layout.BorderContainer" style="height:275px; border: solid #ccc 1px;">
+		<div dojoType="dojox.layout.ExpandoPane" splitter="false" title="leftTest" region="left" maxWidth="175" style="width:175px; background:red">
+			foo
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="center" href="_lorem.html"></div>
+	</div>
+
+	<h2>Splitter not specified:</h2>
+	<div dojoType="dijit.layout.BorderContainer" style="height:275px; border: solid #ccc 1px;">
+		<div dojoType="dojox.layout.ExpandoPane" title="leftTest" region="left" maxWidth="175" style="width:175px; background:red">
+			foo
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="center" href="_lorem.html"></div>
+	</div>
+
+</body>
+</html>
+
diff --git a/dojox/layout/tests/test_FloatingPane.html b/dojox/layout/tests/test_FloatingPane.html
new file mode 100644
index 0000000..f334ffe
--- /dev/null
+++ b/dojox/layout/tests/test_FloatingPane.html
@@ -0,0 +1,186 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.layout.FloatPane - a crude non-modal Floating Window</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/FloatingPane.css">	
+	<link rel="stylesheet" href="../resources/ResizeHandle.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../FloatingPane.js"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dojox.layout.FloatingPane"); 
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.form.ComboBox"); 
+		dojo.require("dijit.form.Button"); 
+		dojo.require("dojo.parser"); // scan page for widgets
+	</script>
+	
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+	/* body { background:url('gridUnderlay.png') top left; }  */
+
+		.alternateDock {
+			position:absolute; 
+			background-color:#ededed; 
+			right:0px; top:0px; 
+			border-left:1px solid #ccc; 
+			height:100%; 
+		
+		}
+		#alternateDock ul.dojoxDockList { display:block; }
+		.testFixedSize {
+			width:300px;
+			height:200px;
+			padding:7px;			
+		}
+	</style>
+	<script type="text/javascript">
+
+		function makeFloater() {
+			// programatically created FloatingPane with srcNode ref
+			var tmp = new dojox.layout.FloatingPane({  
+				title: "dynamically created ...",
+				id:"floater3",
+				closeable:true,
+				resizable:true,
+				dockable: false
+			},"nonFloater");
+			tmp.startup(); 
+		}
+
+		var mi = 1;
+		function brandNewFloater(){
+			var node = document.createElement('div');
+			node.innerHTML = dojo.byId('contentHolder').innerHTML;
+			dojo.body().appendChild(node);
+			dojo.addClass(node,"testFixedSize");
+			var tmp = new dojox.layout.FloatingPane({
+				title:" New Floater #"+(mi++),
+				dockable: false,
+				maxable: true,
+				closable: true,
+				resizable: false
+			},node);
+			tmp.startup();
+			tmp.resize({ w:300, h:125 });
+		}
+
+		var vpx, vpy = null;
+		dojo.addOnLoad(makeFloater);
+
+	</script>
+
+</head>
+<body class="tundra">
+
+		<a href="javascript:dijit.byId('floater1').hide()">hide first pane</a> |
+		<a href="javascript:dijit.byId('floater1').show()">show first pane</a> |
+		<a href="javascript:dijit.byId('floater1').minimize()">minimize 'uncloseable, dockable' pane pane</a> |
+		<a href="javascript:brandNewFloater()">new floater</a>
+
+		<div dojoType="dojox.layout.FloatingPane" title="Floater test ... " resizable="true" id="floater1" style="position:absolute; width:100px; height:100px; top:100px; left:0px; " duration="300">
+		<p style="margin:0; padding:10px;">I am the content to be floated around</p>
+		</div>
+
+		<div dojoType="dojox.layout.FloatingPane" title="un-closable, dockable" style="width:200px; position:absolute; top:100px; left:100px;" closable="false" id="floater2">
+		<p style="padding:8px; margin:0;">
+		I am dockable, though I have no dockTo="" attribute. I will create or use an existing dock 
+		on the bottom of the screen.
+		<br><br>
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc 
+		eleifend sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		</div> 
+		
+		<div id="nonFloater" style="width:100px; height:100px; top:100px; left:300px;" duration="750" >
+		<p style="padding:8x; margin:2px;">
+		I am made into a FloatingPane in dojo.addOnLoad();<br><br>
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		</div>
+
+		<div title="Alt Dock 1" style="width:100px; height:100px; position:absolute; top:200px; left:0; position:absolute; " 
+			dojoType="dojox.layout.FloatingPane" duration="350" resizable="true" 
+			dockTo="alternateDock" executeScripts="true" href="_script.html">
+		</div>
+		<div title="Alt Dock 2" dojoType="dojox.layout.FloatingPane" resizable="true" style="width:100px; height:100px; position:absolute; top:200px; left:100px;" duration="350" dockTo="alternateDock">
+		<p style="color:#666; padding:8px; margin:0;">
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In porta. Etiam mattis libero nec ante. Nam 
+		porta lacus eu ligula. Cras mauris. Suspendisse vel augue. Vivamus aliquam orci ut eros. Nunc eleifend 
+		sagittis turpis. purus purus in nibh. Phasellus in nunc.
+		</p>
+		</div>
+
+		
+		<div dojoType="dojox.layout.FloatingPane" 
+			resizeable="false" style="width:100px; 100px; top:200px; left:200px; position:absolute; " title="foobar" 
+			closable="false" dockable="false">
+			
+			<p style="padding:12px;">
+				This is just a pane. You cannot close me, you cannot resize me, you cannot minimize me. I have a 
+				select to test bleed:
+			</p>
+			
+			<select name="foo">
+				<option value="bleeeeed">bleed?<option>
+				<option value="bleeeeed1">bleed?<option>
+				<option value="bleeeeed2">bleed?<option>
+				<option value="bleeeeed3">bleed?<option>
+			</select>
+			
+		</div> 
+
+		<div dojoType="dojox.layout.FloatingPane"  id="remotePane"
+			title="Remote Pane" href="doc0.html" resizable="true"
+			style="width:250px; height:250px; background:#fff; position:absolute; top:300px; left:0px;"
+		></div>    
+
+		<div dojoType="dojox.layout.Dock" id="alternateDock" class="alternateDock"></div>
+
+    <div style="display:none;" id="contentHolder"><p style="padding:13px; margin:0;">
+		I am content. I am hidden right now.  This content is used to populate the newly created
+		node being attached to the DOM to insert a new FloatingPane without a srcNodeRef. This
+		node is not being manipulated, just having it's innerHTML read. For demonstration purposes.
+		</p>
+		</div>
+		
+		<div dojotype="dojox.layout.FloatingPane" title="Child layout test" 
+			style="width:400px; height:300px;" resizable="true">
+			<div dojotype="dijit.layout.TabContainer">
+				<div dojotype="dijit.layout.ContentPane" title="Tab 1">
+					First Page
+				</div>
+				<div dojotype="dijit.layout.ContentPane" title="Tab 2">
+					<div dojotype="dijit.layout.TabContainer">
+						<div dojotype="dijit.layout.ContentPane" title="Sub-tab 1">
+							Story of Paul.
+						</div>
+						<div dojotype="dijit.layout.ContentPane" title="Sub-tab 2">
+							Story about Paul.
+						</div>
+						<div dojotype="dijit.layout.ContentPane" title="Sub-tab 3">
+							Story about... guess who.
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>	
+			
+</body>
+</html>
diff --git a/dojox/layout/tests/test_GridContainer.html b/dojox/layout/tests/test_GridContainer.html
new file mode 100644
index 0000000..8a0dfe7
--- /dev/null
+++ b/dojox/layout/tests/test_GridContainer.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+		<title>Demo GridContainer</title>
+
+		<link rel="stylesheet" href="../resources/GridContainer.css">
+
+		<style type="text/css" title="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			
+			html, body{
+				margin:0;
+				padding:1%;
+			}
+
+			.cpane{
+				border:1px solid #666;
+				font:bold 12px Arial;
+				color:#666;
+				background:#FFF;
+				padding:10px;
+				height:50px
+			}
+			
+			#GC1 .gridContainerZone {
+				border-collapse:collapse;
+				border : 1px solid #ededed;
+			}
+			
+			.dj_ie6 .dropIndicator, .dj_ie6 .dijitContentpane, .dj_ie6 .dijitCalendar{
+				margin: 10px;
+			}
+			.gridContainerZone > *{
+				margin: 10px !important;
+			}
+			
+		</style>
+		
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript" src="../../../dojox/layout/GridContainerLite.js"></script>
+		<script type="text/javascript" src="../../../dojox/layout/GridContainer.js"></script>
+		
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("dijit.TitlePane");
+			dojo.require("dijit.ColorPalette");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dojox.layout.GridContainer");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.Calendar");
+			var GC1;
+			function setColumns(){
+				GC1 = dijit.byId("GC1");
+				var nb = dojo.byId("nbCol").value;
+				if(nb > 0){
+					GC1.setColumns(nb);
+				}
+			}
+		</script>
+
+	</head>
+
+	<body class="tundra">
+		
+		<h1 class="testTitle">Grid Container</h1>
+		
+		<h2>GridContainer (acceptTypes="ContentPane, TitlePane, ColorPalette, Calendar", hasResizableColumns="false", doLayout="false")</h2>
+			
+			<h5>Add / remove dynamically columns :</h5>
+			<input value="5" name="col" id="nbCol"/>
+			<button id="bt2" dojoType="dijit.form.Button" onclick="setColumns();">set Number of Columns</button>
+		
+			<div id="GC1" dojoType="dojox.layout.GridContainer" 
+				nbZones="3"
+				hasResizableColumns="false"
+				doLayout="false" 
+				acceptTypes="ContentPane, TitlePane, ColorPalette, Calendar">
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane" >Content Pane n°1 !</div>
+					<div dojoType="dijit.TitlePane" title="Ergo" dndType="TitlePane" >
+						Non ergo erunt homines deliciis diffluentes audiendi, si quando de amicitia, quam nec usu nec ratione habent cognitam, disputabunt. Nam quis est, pro deorum fidem atque hominum! qui velit, ut neque diligat quemquam nec ipse ab ullo diligatur, circumfluere omnibus copiis atque in omnium rerum abundantia vivere? Haec enim est tyrannorum vita nimirum, in qua nulla fides, nulla caritas, nulla stabilis benevolentiae potest esse fiducia, omnia semper suspecta atque sollicita, nullus locu [...]
+					</div>
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°2 !</div>
+			  		<div dojoType="dijit.layout.ContentPane" title="Intellectum" dndType="ContentPane">
+			  			Intellectum est enim mihi quidem in multis, et maxime in me ipso, sed paulo ante in omnibus, cum M. Marcellum senatui reique publicae concessisti, commemoratis praesertim offensionibus, te auctoritatem huius ordinis dignitatemque rei publicae tuis vel doloribus vel suspicionibus anteferre. Ille quidem fructum omnis ante actae vitae hodierno die maximum cepit, cum summo consensu senatus, tum iudicio tuo gravissimo et maximo. Ex quo profecto intellegis quanta in dato beneficio sit  [...]
+			  		</div>
+			  		
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°3 !</div>
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°4 !</div>
+					<div dojoType="dijit.Calendar" dndType="Calendar"></div>
+			</div>
+		
+	</body>
+</html>
diff --git a/dojox/layout/tests/test_GridContainerColWidths.html b/dojox/layout/tests/test_GridContainerColWidths.html
new file mode 100644
index 0000000..2721e3c
--- /dev/null
+++ b/dojox/layout/tests/test_GridContainerColWidths.html
@@ -0,0 +1,164 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+		<title>Testing GridContainer Column Widths</title>
+
+		<style type="text/css" title="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			
+			html, body{
+				margin:0;
+				padding:1%;
+			}
+			.dijitTitlePane .gripNode {
+			 	cursor: move;
+			}
+			
+			.dijitTitlePane .gripNode span {
+			 	cursor: pointer;
+			}
+			.cpane{
+				border:1px solid #666;
+				font:bold 12px Arial;
+				color:#666;
+				background:#FFF;
+				padding:10px;
+				margin:2px;
+			}
+			
+			#GC1{
+				height:300px;
+				margin:10px;
+				padding:2px;
+				border:1px solid #ededed;
+				overflow-x:hidden;
+				overflow-y:auto;
+			}
+			
+			#GC1 .gridContainerTable {
+				border-collapse:collapse;
+			}
+			
+			#GC1 .gridContainerZone {
+				border-collapse:collapse;
+				border : 1px solid #ededed;
+			}
+			#GC2 {
+				border:1px solid #333;
+			}
+		</style>
+		
+		<link rel="stylesheet" href="../resources/GridContainer.css">
+		<link rel="stylesheet" href="../resources/DndGridContainer.css">
+		
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+		<script type="text/javascript" src="../GridContainerLite.js"></script>
+		<script type="text/javascript" src="../GridContainer.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("dijit.TitlePane");
+			dojo.require("dijit.ColorPalette");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dojox.layout.GridContainer");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.Calendar");
+			
+			
+			var GC1;
+			
+			// Sets the number of columns on the first GridContainer
+			function setColumns(){
+				GC1 = dijit.byId("GC1");
+				var nb = dojo.byId("nbCol").value;
+				if(nb > 0){
+					GC1.setColumns(nb);
+				}
+			}
+			
+			function setColumnWidths(){
+				GC1 = dijit.byId("GC1");
+				var widths = dojo.byId("colWidth").value;
+				GC1.set("colWidths", widths);
+			}
+		</script>
+
+	</head>
+
+	<body class="tundra">
+		
+		<h1 class="testTitle">Grid Container</h1>
+		
+		<div>
+			This pages tests setting the widths of GridContainer columns using the "colWidths" parameter.
+		</div>
+		
+		<h2>Grid Container (allowAutoScroll="true", hasResizableColumns="false")</h2>
+			
+		<h5>Add / remove dynamically columns :</h5>
+		<input value="5" name="col" id="nbCol"/>
+		<button id="bt2" dojoType="dijit.form.Button" onclick="setColumns();">set Number of Columns</button>
+
+		<h5>Set the width of columns :</h5>
+		<input value="25,30,40" name="col" id="colWidth"/>
+		<button id="bt3" dojoType="dijit.form.Button" onclick="setColumnWidths();">Set Column Widths</button>
+		
+		<div>
+			<h4>Testing column width where the first column has a width fixed to 40%.  All other columns take up the remiaining space</h4>
+			
+			<div id="GC1" dojoType="dojox.layout.GridContainer" 
+				nbZones="3"
+				opacity="0.7" 
+				allowAutoScroll="true" 
+				hasResizableColumns="false"
+				withHandles="true"
+				acceptTypes="ContentPane, TitlePane, ColorPalette, Calendar"
+
+				colWidths="40"
+				>
+					<div dojoType="dijit.layout.ContentPane" dndType="ContentPane" class="cpane" label="Content Pane">Content Pane n°1 !</div>
+					<div dojoType="dijit.TitlePane" dndType="TitlePane" title="Ergo">
+						Non ergo erunt homines deliciis diffluentes audiendi, si quando de amicitia, quam nec usu nec ratione habent cognitam, disputabunt. Nam quis est, pro deorum fidem atque hominum! qui velit, ut neque diligat quemquam nec ipse ab ullo diligatur, circumfluere omnibus copiis atque in omnium rerum abundantia vivere? Haec enim est tyrannorum vita nimirum, in qua nulla fides, nulla caritas, nulla stabilis benevolentiae potest esse fiducia, omnia semper suspecta atque sollicita, nullus locu [...]
+					</div>
+					<div dojoType="dijit.layout.ContentPane" dndType="ContentPane" class="cpane" label="Content Pane">Content Pane n°2 !</div>
+			  		<div dojoType="dijit.layout.ContentPane" dndType="ContentPane" title="Intellectum">
+			  			Intellectum est enim mihi quidem in multis, et maxime in me ipso, sed paulo ante in omnibus, cum M. Marcellum senatui reique publicae concessisti, commemoratis praesertim offensionibus, te auctoritatem huius ordinis dignitatemque rei publicae tuis vel doloribus vel suspicionibus anteferre. Ille quidem fructum omnis ante actae vitae hodierno die maximum cepit, cum summo consensu senatus, tum iudicio tuo gravissimo et maximo. Ex quo profecto intellegis quanta in dato beneficio sit  [...]
+			  		</div>
+			  		
+					<div dojoType="dijit.layout.ContentPane" dndType="ContentPane" class="cpane" label="Content Pane">Content Pane n°3 !</div>
+					<div dojoType="dijit.layout.ContentPane" dndType="ContentPane" class="cpane" label="Content Pane">Content Pane n°4 !</div>
+					<div dojoType="dijit.Calendar" dndType="Calendar"></div>
+			</div>
+			
+			
+			<h4>Testing column width with all column widths defined, to use 40%, 40% and 20%.</h4>
+			<div id="GC2" dojoType="dojox.layout.GridContainer" 
+							nbZones="3"
+							opacity="0.7" 
+							allowAutoScroll="true" 
+							hasResizableColumns="false"
+							withHandles="true"
+							acceptTypes="ContentPane,TitlePane,ColorPalette,Calendar"
+							colWidths="40,40,20"
+							>
+								<div dojoType="dijit.layout.ContentPane" dndType="ContentPane" class="cpane" label="Content Pane">Content Pane n°1 !</div>
+								<div dojoType="dijit.TitlePane" dndType="TitlePane" title="Ergo">
+									Non ergo erunt homines deliciis diffluentes audiendi, si quando de amicitia, quam nec usu nec ratione habent cognitam, disputabunt. Nam quis est, pro deorum fidem atque hominum! qui velit, ut neque diligat quemquam nec ipse ab ullo diligatur, circumfluere omnibus copiis atque in omnium rerum abundantia vivere? Haec enim est tyrannorum vita nimirum, in qua nulla fides, nulla caritas, nulla stabilis benevolentiae potest esse fiducia, omnia semper suspecta atque sollicita, nullus l [...]
+								</div>
+								<div dojoType="dijit.layout.ContentPane" dndType="ContentPane" class="cpane" label="Content Pane">Content Pane n°2 !</div>
+						  		<div dojoType="dijit.layout.ContentPane" dndType="ContentPane" title="Intellectum">
+						  			Intellectum est enim mihi quidem in multis, et maxime in me ipso, sed paulo ante in omnibus, cum M. Marcellum senatui reique publicae concessisti, commemoratis praesertim offensionibus, te auctoritatem huius ordinis dignitatemque rei publicae tuis vel doloribus vel suspicionibus anteferre. Ille quidem fructum omnis ante actae vitae hodierno die maximum cepit, cum summo consensu senatus, tum iudicio tuo gravissimo et maximo. Ex quo profecto intellegis quanta in dato beneficio s [...]
+						  		</div>
+						  		
+								<div dojoType="dijit.layout.ContentPane" dndType="ContentPane" class="cpane" label="Content Pane">Content Pane n°3 !</div>
+								<div dojoType="dijit.layout.ContentPane" dndType="ContentPane" class="cpane" label="Content Pane">Content Pane n°4 !</div>
+								<div dojoType="dijit.Calendar" dndType="Calendar"></div>
+			</div>
+		</div>
+		
+	</body>
+</html>
diff --git a/dojox/layout/tests/test_GridContainerLite.html b/dojox/layout/tests/test_GridContainerLite.html
new file mode 100644
index 0000000..e51fe36
--- /dev/null
+++ b/dojox/layout/tests/test_GridContainerLite.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+		<title>Demo GridContainer</title>
+
+		<style type="text/css" title="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			
+			html, body{
+				margin:0;
+				padding:1%;
+			}
+
+			.cpane{
+				border:1px solid #666;
+				font:bold 12px Arial;
+				color:#666;
+				background:#FFF;
+				padding:10px;
+			}
+			
+			.gridContainerPopup{
+				position:absolute;
+				top:40%;
+				left:40%;
+				width:200px;
+				height:auto;	
+				border:1px solid #BFBFBF;
+				background-color:#FFF;
+				text-align:center;
+				padding:10px;
+			}
+			
+			.dj_ie6 .orange .gridContainerPopup{
+				top:10%;
+			}
+			
+			.dj_ie6 .dropIndicator, .dj_ie6 .dijitContentpane, .dj_ie6 .dijitCalendar{
+				margin: 10px;
+			}
+			.gridContainerZone > *{
+				margin: 10px !important;
+			}
+		</style>
+		
+		<link rel="stylesheet" href="../resources/GridContainer.css">
+		
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+		
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("dijit.TitlePane");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dojox.layout.GridContainerLite");
+			dojo.require("dijit.Calendar");
+
+			var canDisplayPopup = true;
+			
+			function displayPopup(gridContainer) {
+				//	summary:
+				//		Display a popup when a widget can not be moved (not accepted type)
+
+				if(canDisplayPopup){
+					canDisplayPopup = false;
+					var popup = dojo.doc.createElement("div");
+					dojo.addClass(popup, "gridContainerPopup");
+					popup.innerHTML = "Impossible to move this widget ! ";
+					var attachPopup = dijit.byId("GC1").containerNode.appendChild(popup);
+					setTimeout(dojo.hitch(this, function(){
+						dijit.byId("GC1").containerNode.removeChild(attachPopup);
+						dojo.destroy(attachPopup);
+						canDisplayPopup = true;
+					}), 1500);
+				}
+			};
+
+			dojo.addOnLoad(function(){
+				dojo.subscribe("/dojox/layout/gridContainer/moveRestriction",displayPopup);
+			});
+	
+				
+
+		</script>
+
+	</head>
+
+	<body class="tundra">
+		
+		<h1 class="testTitle">Grid Container Lite</h1>
+		<h2>Accessibility</h2>
+			<ul>
+				<li>Possibility to move focus into the GridContainer (TAB, LEFT ARROW, RIGHT ARROW, UP ARROW, DOWN ARROW).</li>
+				<li>Possibility to move GridContainer's children (Drag and Drop) with keyboard. (SHIFT + LEFT ARROW or RIGHT ARROW or UP ARROW or DOWN ARROW). To test dnd restriction, try to move a TitlePane widget...</li>
+			</ul>
+		<h2>Grid Container (acceptTypes="ContentPane, Calendar", nbZones="3", isAutoOrganized="true", doLayout="false")</h2>
+			
+			<div id="GC1" dojoType="dojox.layout.GridContainerLite" 
+				nbZones="3"
+				hasResizableColumns="false" 
+				doLayout="false" 
+				acceptTypes="ContentPane, Calendar">
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane" >Content Pane n°1 !</div>
+					<div dojoType="dijit.TitlePane" title="Ergo" dndType="TitlePane" >
+						Non ergo erunt homines deliciis diffluentes audiendi, si quando de amicitia, quam nec usu nec ratione habent cognitam, disputabunt. Nam quis est, pro deorum fidem atque hominum! qui velit, ut neque diligat quemquam nec ipse ab ullo diligatur, circumfluere omnibus copiis atque in omnium rerum abundantia vivere? Haec enim est tyrannorum vita nimirum, in qua nulla fides, nulla caritas, nulla stabilis benevolentiae potest esse fiducia, omnia semper suspecta atque sollicita, nullus locu [...]
+					</div>
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°2 !</div>
+			  		<div dojoType="dijit.layout.ContentPane" title="Intellectum" dndType="ContentPane">
+			  			Intellectum est enim mihi quidem in multis, et maxime in me ipso, sed paulo ante in omnibus, cum M. Marcellum senatui reique publicae concessisti, commemoratis praesertim offensionibus, te auctoritatem huius ordinis dignitatemque rei publicae tuis vel doloribus vel suspicionibus anteferre. Ille quidem fructum omnis ante actae vitae hodierno die maximum cepit, cum summo consensu senatus, tum iudicio tuo gravissimo et maximo. Ex quo profecto intellegis quanta in dato beneficio sit  [...]
+			  		</div>
+			  		
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°3 !</div>
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°4 !</div>
+					<div dojoType="dijit.Calendar" dndType="Calendar"></div>
+			</div>
+		
+	</body>
+</html>
diff --git a/dojox/layout/tests/test_GridContainerLite_doLayout.html b/dojox/layout/tests/test_GridContainerLite_doLayout.html
new file mode 100644
index 0000000..d6c45a2
--- /dev/null
+++ b/dojox/layout/tests/test_GridContainerLite_doLayout.html
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+	<title>GridContainerLite - doLayout</title>
+
+	<!-- Specific CSS -->
+	<style type="text/css" title="text/css">
+		/* <![CDATA[ */
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+
+			body{
+				padding-left:10px;
+			}
+			.cpane{
+				border:1px solid #666;
+				font:bold 12px Arial;
+				color:#666;
+				background:#FFF;
+				padding:5px;
+				height:100px;
+			}
+			
+			.gridContainerZone > div{
+				margin: 5px;
+			}
+			
+			.dj_ie6 .dropIndicator, .dj_ie6 .cpane{
+				margin: 10px;
+			}
+		/* ]]> */
+	</style>
+	
+	<link rel="stylesheet" href="../resources/GridContainer.css">
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<script type="text/javascript" language="javascript">
+		dojo.require("dojox.layout.GridContainerLite");
+		dojo.require("dijit.layout.ContentPane");
+	</script>
+</head>
+
+<body class="orange">
+	<h1>GridContainerLite - doLayout</h1>
+		
+		<div style="position:absolute;top:50px;left:50px;width:400px;">
+			<h3>doLayout = false</h3>
+			<p>GridContainer has a fixed no fixed height.</p>
+			<div id="GC1" 
+				dojoType="dojox.layout.GridContainerLite" 
+				nbZones="3" 
+				isAutoOrganized="true"
+				doLayout="false">
+				<div dojoType="dijit.layout.ContentPane" class="cpane">
+		   			Content Pane 1
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane"class="cpane" >
+			   		Content Pane 2
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+			   		Content Pane 3
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+			   		Content Pane 4
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+		   			Content Pane 5
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+			   		Content Pane 6
+			  	</div>
+			  	
+			</div>
+		</div>
+		<div style="position:absolute;top:50px;left:500px;width:600px;">
+			<h3>doLayout = true (default)</h3>
+			<p>GridContainer has a fixed height.</p>
+			<div id="GC2" 
+				dojoType="dojox.layout.GridContainerLite" 
+				nbZones="4" 
+				isAutoOrganized="true"
+				style="height:400px">
+				<div dojoType="dijit.layout.ContentPane" class="cpane">
+		   			Content Pane 7
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+			   		Content Pane 8
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+			   		Content Pane 9
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+		   			Content Pane 10
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+			   		Content Pane 11
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+			   		Content Pane 12
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+			   		Content Pane 13
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+			   		Content Pane 14
+			  	</div>
+			</div>
+		</div>
+</body>
+</html>
diff --git a/dojox/layout/tests/test_GridContainerLite_dragRestriction.html b/dojox/layout/tests/test_GridContainerLite_dragRestriction.html
new file mode 100644
index 0000000..ba637df
--- /dev/null
+++ b/dojox/layout/tests/test_GridContainerLite_dragRestriction.html
@@ -0,0 +1,148 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+	<title>GridContainerLite [acceptTypes, dragRestriction]</title>
+
+	<!-- Specific CSS -->
+	<style type="text/css" title="text/css">
+		/* <![CDATA[ */
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+
+			body{
+				padding-left:10px;
+			}
+			.cpane{
+				border:1px solid #666;
+				font:bold 12px Arial;
+				color:#F60;
+				background:#FFF;
+				padding:5px;
+				height:100px;
+			}
+			
+			.gridContainerZone > div{
+				margin: 5px;
+			}
+			
+			.dj_ie6 .dropIndicator, .dj_ie6 .cpane{
+				margin: 10px;
+			}
+		/* ]]> */
+	</style>
+	
+	<link rel="stylesheet" href="../resources/GridContainer.css">
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<script type="text/javascript" language="javascript">
+		dojo.require("dojox.layout.GridContainerLite");
+		dojo.require("dijit.layout.ContentPane");
+
+		var canDisplayPopup = true;
+		
+		function displayPopup(grid) {
+			//	summary:
+			//		Display a popup when a widget can not be moved (not accepted type)
+
+			if(canDisplayPopup){
+				canDisplayPopup = false;
+				var popup = dojo.doc.createElement("div");
+				dojo.addClass(popup, "gridContainerPopup");
+				popup.innerHTML = "Impossible to move this widget ! ";
+				var attachPopup = dijit.byId("GC1").containerNode.appendChild(popup);
+				setTimeout(dojo.hitch(this, function(){
+					dijit.byId("GC1").containerNode.removeChild(attachPopup);
+					dojo.destroy(attachPopup);
+					canDisplayPopup = true;
+				}), 1500);
+			}
+		};
+
+		dojo.addOnLoad(function(){
+			dojo.subscribe("/dojox/layout/gridContainer/moveRestriction",displayPopup);
+		});
+	</script>
+</head>
+
+<body class="orange">
+	<h1>GridContainerLite with acceptTypes</h1>
+		<ul>
+			<li>Try to drag and Drop Widget !</li>
+			<li>Try to drag and Drop Widget with keyBoard (no drag and drop between GridContainer)</li>
+			<ul>
+				<li>Use Tab to place focus on the GridContainer.</li>
+				<li>Use Arrows to place focus on children</li>
+				<li>Use Shift + Arrows to drag and drop a child</li>
+			</ul>
+			<li>Try to drag widgets which have an attribute dragRestriction="true". It's imposible !</li>
+		</ul>
+		
+		<div style="position:absolute;top:150px;left:50px;width:400px;">
+			<h3>AcceptTypes :</h3>
+			<p>text (equal to any dndType), color, animal</p>
+			<div id="GC1" 
+				dojoType="dojox.layout.GridContainerLite" 
+				nbZones="3" 
+				isAutoOrganized="true"
+				doLayout="false"
+				acceptTypes="text, color, animal">
+				<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="animal">
+		   			I am a Tiger : drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane">
+			   		I have no type (text) : Drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="color" style="background-color:blue">
+			   		I am a color : Drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane" dragRestriction="true">
+			   		I have a dragRestriction : Try to Drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="animal">
+		   			I am a Snake : Drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="motor">
+			   		I am a car : Drag Me !
+			  	</div>
+			  	
+			</div>
+		</div>
+		<div style="position:absolute;top:150px;left:500px;width:600px;">
+			<h3>AcceptTypes :</h3>
+			<p>color, motor</p>
+			<div id="GC2" 
+				dojoType="dojox.layout.GridContainerLite" 
+				nbZones="4" 
+				isAutoOrganized="true"
+				doLayout="false"
+				acceptTypes="color, motor">
+				<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="color" style="background-color:yellow">
+		   			I am a color : drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="motor">
+			   		I am a plane : drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="animal">
+			   		I am a horse : Drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="motor">
+		   			I am a bus : Drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="color" style="background-color:pink">
+			   		I am a color: Drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="animal">
+			   		I am a rabbit : Drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane" dragRestriction="true">
+			   		I have a dragRestriction : Try to Drag Me !
+			  	</div>
+			  	<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="color" style="background-color:red">
+			   		I am a color : Drag Me !
+			  	</div>
+			</div>
+		</div>
+</body>
+</html>
diff --git a/dojox/layout/tests/test_GridContainer_ResizableCol.html b/dojox/layout/tests/test_GridContainer_ResizableCol.html
new file mode 100644
index 0000000..ebbc0c5
--- /dev/null
+++ b/dojox/layout/tests/test_GridContainer_ResizableCol.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+		<title>GridContainer - Resize Columns</title>
+
+		<style type="text/css" title="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			
+			html, body{
+				margin:0;
+				padding:1%;
+			}
+
+			.cpane{
+				border:1px solid #666;
+				font:bold 12px Arial;
+				color:#666;
+				background:#FFF;
+				padding:10px;
+				height:100px;
+			}
+			
+			.gridContainerZone > *{
+				margin: 10px !important;
+			}
+			
+			.dj_ie6 .dropIndicator, .dj_ie6 .dijitContentpane, .dj_ie6 .dijitCalendar{
+				margin: 10px;
+			}
+			
+			
+		</style>
+		
+		<link rel="stylesheet" href="../resources/GridContainer.css">
+		
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+		
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("dijit.TitlePane");
+			dojo.require("dijit.ColorPalette");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dojox.layout.GridContainer");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.Calendar");
+			var GC1;
+			function setColumns(){
+				GC1 = dijit.byId("GC1");
+				var nb = dojo.byId("nbCol").value;
+				if(nb > 0){
+					GC1.setColumns(nb);
+				}
+			}
+		</script>
+
+	</head>
+
+	<body class="tundra">
+		
+		<h1 class="testTitle">Grid Container</h1>
+		
+		<h2>Grid Container (acceptTypes="ContentPane, TitlePane, ColorPalette, Calendar", hasResizableColumns="true")</h2>
+			
+			<h5>Add / remove dynamically columns :</h5>
+			<input value="5" name="col" id="nbCol"/>
+			<button id="bt2" dojoType="dijit.form.Button" onclick="setColumns();">set Number of Columns</button>
+		
+			<div id="GC1" dojoType="dojox.layout.GridContainer" 
+				nbZones="3"
+				hasResizableColumns="true"
+				doLayout="false"
+				acceptTypes="ContentPane, TitlePane, ColorPalette, Calendar">
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane" >Content Pane n°1 !</div>
+					<div dojoType="dijit.TitlePane" title="Ergo" dndType="TitlePane" >
+						Non ergo erunt homines deliciis diffluentes audiendi, si quando de amicitia, quam nec usu nec ratione habent cognitam, disputabunt. Nam quis est, pro deorum fidem atque hominum! qui velit, ut neque diligat quemquam nec ipse ab ullo diligatur, circumfluere omnibus copiis atque in omnium rerum abundantia vivere? Haec enim est tyrannorum vita nimirum, in qua nulla fides, nulla caritas, nulla stabilis benevolentiae potest esse fiducia, omnia semper suspecta atque sollicita, nullus locu [...]
+					</div>
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°2 !</div>
+			  		<div dojoType="dijit.layout.ContentPane" title="Intellectum" dndType="ContentPane">
+			  			Intellectum est enim mihi quidem in multis, et maxime in me ipso, sed paulo ante in omnibus, cum M. Marcellum senatui reique publicae concessisti, commemoratis praesertim offensionibus, te auctoritatem huius ordinis dignitatemque rei publicae tuis vel doloribus vel suspicionibus anteferre. Ille quidem fructum omnis ante actae vitae hodierno die maximum cepit, cum summo consensu senatus, tum iudicio tuo gravissimo et maximo. Ex quo profecto intellegis quanta in dato beneficio sit  [...]
+			  		</div>
+			  		
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°3 !</div>
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°4 !</div>
+					<div dojoType="dijit.Calendar" dndType="Calendar"></div>
+			</div>
+		
+	</body>
+</html>
diff --git a/dojox/layout/tests/test_GridContainer_TitlePanes.html b/dojox/layout/tests/test_GridContainer_TitlePanes.html
new file mode 100644
index 0000000..f5fb0cf
--- /dev/null
+++ b/dojox/layout/tests/test_GridContainer_TitlePanes.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+		<title>Demo GridContainer</title>
+
+		<style type="text/css" title="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			
+			html, body{
+				margin:0;
+				padding:1%;
+			}
+			.dijitTitlePane .gripNode {
+			 	cursor: move;
+			}
+			
+			.dijitTitlePane .gripNode span {
+			 	cursor: pointer;
+			}
+			.cpane{
+				border:1px solid #666;
+				font:bold 12px Arial;
+				color:#666;
+				background:#FFF;
+				padding:10px;
+				margin:2px;
+			}
+			
+			#GC1{
+				height:600px;
+				margin:10px;
+				padding:2px;
+				border:1px solid #ededed;
+				overflow-x:hidden;
+				overflow-y:auto;
+				border-collapse:collapse;
+				border : 1px solid #ededed;
+			}
+			
+			#GC1 .gridContainerTable {
+				border-collapse:collapse;
+			}
+		</style>
+		
+		<link rel="stylesheet" href="../resources/GridContainer.css">
+		<link rel="stylesheet" href="../resources/DndGridContainer.css">
+		
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+		<script type="text/javascript" src="../GridContainer.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("dijit.TitlePane");
+			dojo.require("dojox.layout.GridContainer");
+
+		</script>
+
+	</head>
+
+	<body class="tundra">
+		
+		<h1 class="testTitle">Grid Container With Title Panes</h1>
+		
+		<div>
+			<div id="GC1" dojoType="dojox.layout.GridContainer" 
+				nbZones="3"
+				opacity="0.7" 
+				allowAutoScroll="true" 
+				hasResizableColumns="false"
+				withHandles="true"
+				acceptTypes="TitlePane">
+					<div dojoType="dijit.TitlePane" dndType="TitlePane" title="Title Pane 1">Title Pane 1<br><br><br><br><br>Some more content</div>
+					<div dojoType="dijit.TitlePane" dndType="TitlePane" title="Title Pane 2">Title Pane 2<br><br><br><br><br>Some more content</div>
+					<div dojoType="dijit.TitlePane" dndType="TitlePane" title="Title Pane 3">Title Pane 3<br><br><br><br><br>Some more content</div>
+					<div dojoType="dijit.TitlePane" dndType="TitlePane" title="Title Pane 4">Title Pane 4<br><br><br><br><br>Some more content</div>
+					<div dojoType="dijit.TitlePane" dndType="TitlePane" title="Ergo">
+						Non ergo erunt homines deliciis diffluentes audiendi, si quando de amicitia, quam nec usu nec ratione habent cognitam, disputabunt. Nam quis est, pro deorum fidem atque hominum! qui velit, ut neque diligat quemquam nec ipse ab ullo diligatur, circumfluere omnibus copiis atque in omnium rerum abundantia vivere? Haec enim est tyrannorum vita nimirum, in qua nulla fides, nulla caritas, nulla stabilis benevolentiae potest esse fiducia, omnia semper suspecta atque sollicita, nullus locu [...]
+					</div>
+			</div>
+	</body>
+</html>
diff --git a/dojox/layout/tests/test_GridContainer_complete_solution.html b/dojox/layout/tests/test_GridContainer_complete_solution.html
new file mode 100644
index 0000000..a28b6f8
--- /dev/null
+++ b/dojox/layout/tests/test_GridContainer_complete_solution.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="pragma" content="no-cache" />
+	<meta http-equiv="expires" content="-1" />
+	
+	<title>Drag and Drop - Complete Solution</title>
+	
+	<link rel="stylesheet" href="resources/set_complete_dnd.css" type="text/css" />	
+	<link rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css" type="text/css" />	
+	<link rel="stylesheet" href="../../../dojo/resources/dojo.css" type="text/css" />
+	
+	<link rel="stylesheet" href="../../../dojox/mdnd/resources/dnd.css" type="text/css" />
+	
+	<link rel="stylesheet" href="../resources/GridContainer.css" type="text/css" />
+	<link rel="stylesheet" href="../../../dijit/tests/css/dijitTests.css" type="text/css"/>
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true,  parseOnLoad: true"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dojox.layout.GridContainerLite");
+		dojo.require("dojox.widget.Portlet");
+		dojo.require("dijit.TitlePane");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojox.mdnd.PureSource");
+		dojo.require("dojox.mdnd.adapter.DndFromDojo");
+		dojo.require("dojox.mdnd.adapter.DndToDojo");
+		dojo.require("dojo.dnd.Source");
+		dojo.require("dijit.layout.TabContainer");
+	</script>
+	
+	<script type="text/javascript" src="resources/script_dnd.js"></script>
+</head>
+<body class="tundra">
+	<div style="position:absolute;width:200px;left:5px;top:50px;">
+		<H2>Pure Source Dojo</H2>
+		<div dojoType="dojox.mdnd.PureSource" jsId="c1" class="container" >
+			<div class="dojoDndItem" dndType="ContentPane"><strong>ContentPane</strong></div>
+			<div class="dojoDndItem" dndType="Portlet"><strong>Portlet</strong></div>
+			<div class="dojoDndItem" dndType="TitlePane"><strong>TitlePane</strong></div>
+		</div>
+	</div>
+	<div style="position:absolute;width:200px;left:5px;top:220px;">
+		<H2>Source/Target Dojo</H2>
+		<div dojoType="dojo.dnd.Source" accept="rss, TitlePane, News" jsId="c2" class="container">
+			<div class="dojoDndItem" dndType="rss">RSS <strong>1</strong></div>
+			<div class="dojoDndItem" dndType="TitlePane"><strong>TitlePane</strong></div>
+			<div class="dojoDndItem" dndType="ContentPane"><strong>ContentPane</strong></div>
+		</div>
+		<p><b>accept :</b><br><i>Rss, TitlePane, News</i></p>
+	</div>
+	<div id="tb1" dojoType="dijit.layout.TabContainer" style="position:absolute;left:250px;top:50px;margin:10px; width:800px;height:500px">
+    	<div id="GC1" 
+			dojoType="dojox.layout.GridContainerLite" 
+			nbZones="3" 
+			isAutoOrganized="true" 
+			acceptTypes="Portlet, text, ContentPane, News"
+			title="onglet 1"
+			>
+			<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="ContentPane">
+		   		Content Pane 1!!!
+		  	</div>
+		  	<div dojoType="dijit.layout.ContentPane" class="cpane" dndType="ContentPane">
+		   		Content Pane 2!!!
+		  	</div>
+			<div dojoType="dojox.widget.Portlet" 
+				id="ptl"
+				title = "News Draggable"
+				style="height:150px;"
+				dndType="Portlet" >
+				<b>Source/Target OAF (drop only rss)</b><br>
+				<div dojoType="dojo.dnd.Source" jsId="cp1" accept="rss">
+					<div class="dojoDndItem" dndType="News">News <strong>1</strong></div>
+					<div class="dojoDndItem" dndType="News">News <strong>2</strong></div>
+					<div class="dojoDndItem" dndType="News">News <strong>3</strong></div>
+					<div class="dojoDndItem" dndType="rss">RSS <strong>2</strong></div>
+				</div>
+			</div>
+			<div dojoType="dijit.TitlePane" title="titlePane1" dndType="TitlePane">
+		   		Title Pane 1!!!
+		  	</div>
+		</div>			
+        <div id="GC2" 
+			dojoType="dojox.layout.GridContainerLite" 
+			nbZones="3" 
+			isAutoOrganized="true" 
+			acceptTypes="text, Portlet, ContentPane, TitlePane"
+			style="min-height:350px"
+			title="onglet 2" 
+			closable="true"
+			>
+			<div dojoType="dijit.layout.ContentPane" dndType="ContentPane" class="cpane">
+		   		Content Pane 3!!!
+		  	</div>
+		  	<div dojoType="dijit.TitlePane" dndType="TitlePane" title="titlePane 2">
+		   		Title Pane 2!!!
+		  	</div>
+		</div>  
+	</div>
+	
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/layout/tests/test_GridContainer_dragHandle.html b/dojox/layout/tests/test_GridContainer_dragHandle.html
new file mode 100644
index 0000000..c67605f
--- /dev/null
+++ b/dojox/layout/tests/test_GridContainer_dragHandle.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+		<title>GridContainer - dragHandleClass</title>
+
+		<link rel="stylesheet" href="../resources/GridContainer.css">
+
+		<style type="text/css" title="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			
+			html, body{
+				margin:0;
+				padding:1%;
+			}
+
+			.cpane{
+				border:1px solid #666;
+				font:bold 12px Arial;
+				color:#666;
+				background:#FFF;
+				padding:10px;
+				height:50px
+			}
+			
+			#GC1 .gridContainerZone {
+				border-collapse:collapse;
+				border : 1px solid #ededed;
+			}
+			
+			.dj_ie6 .dropIndicator, .dj_ie6 .dijitContentpane, .dj_ie6 .dijitCalendar{
+				margin: 10px;
+			}
+			.gridContainerZone > *{
+				margin: 10px !important;
+			}
+			
+		</style>
+		
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+		
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("dijit.TitlePane");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dojox.widget.Portlet");
+			dojo.require("dojox.layout.GridContainer");
+			dojo.require("dijit.form.CheckBox");
+		</script>
+
+	</head>
+
+	<body class="tundra">
+		
+		<h1 class="testTitle">Grid Container</h1>
+		
+		<h2>Specify dragHandle CSS class</h2>
+		<h3>dragHandleClass="dijitTitlePaneTitle"</h3>
+		<div>
+		  Rather than dragging by clicking anywhere on a widget, it is also possible to specify
+		  particular parts of the widget that are draggable, for example a title bar.
+		  To do this, set the 'dragHandleClass' to the CSS class on that draggable node.
+		  Note that below, you can only drag the title panes by dragging their title bar, not the body
+		  of the widget.
+		</div>
+		
+		<div id="GC1" dojoType="dojox.layout.GridContainer" 
+			nbZones="3"
+			hasResizableColumns="false"
+			doLayout="false" 
+			dragHandleClass="dijitTitlePaneTitle">
+				<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane" >Content Pane n°1 !</div>
+				<div dojoType="dijit.TitlePane" title="Ergo" >
+					Non ergo erunt homines deliciis diffluentes audiendi, si quando de amicitia, quam nec usu nec ratione habent cognitam, disputabunt. Nam quis est, pro deorum fidem atque hominum! qui velit, ut neque diligat quemquam nec ipse ab ullo diligatur, circumfluere omnibus copiis atque in omnium rerum abundantia vivere? Haec enim est tyrannorum vita nimirum, in qua nulla fides, nulla caritas, nulla stabilis benevolentiae potest esse fiducia, omnia semper suspecta atque sollicita, nullus locus [...]
+				</div>
+				<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane">Content Pane n°2 !</div>
+				<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane">Content Pane n°3 !</div>
+				<div dojoType="dojox.widget.Portlet" title="Portlet with Dialog Settings" id="portlet2">
+				<div dojoType="dojox.widget.PortletDialogSettings" title="Settings in a Dialog">
+					Use Bold Text: <div dojoType="dijit.form.CheckBox">
+						<script type="dojo/connect" event="onClick">
+						  dojo.style(dijit.byId('portlet2').containerNode, "fontWeight", this.checked ? "bold" : "normal");
+						</script>
+					</div>
+				</div>
+				<div>
+					Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
+					Nam facilisis enim. Pellentesque in elit et lacus euismod dignissim.
+					Aliquam dolor pede, convallis eget, dictum a, blandit ac, urna. 
+					Pellentesque sed nunc ut justo volutpat egestas. Class aptent taciti
+					sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. 
+					In erat. Suspendisse potenti. Fusce faucibus nibh sed nisi. Phasellus 
+					faucibus, dui a cursus dapibus, mauris nulla euismod velit, a lobortis turpis 
+					arcu vel dui. Pellentesque fermentum ultrices pede. Donec auctor lectus eu arcu. 
+					Curabitur non orci eget est porta gravida. Aliquam pretium orci id nisi. Duis faucibus,
+					mi non adipiscing venenatis, erat urna aliquet elit, eu fringilla lacus tellus quis erat. 
+					Nam tempus ornare lorem. Nullam feugiat.
+				</div>
+			</div>
+				<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane">Content Pane n°4 !</div>
+		</div>
+		
+	</body>
+</html>
diff --git a/dojox/layout/tests/test_GridContainer_in_BorderContainer.html b/dojox/layout/tests/test_GridContainer_in_BorderContainer.html
new file mode 100644
index 0000000..36b7c84
--- /dev/null
+++ b/dojox/layout/tests/test_GridContainer_in_BorderContainer.html
@@ -0,0 +1,150 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<title>Demo GridContainer</title>
+		<style type="text/css" title="text/css">
+			/* <![CDATA[ */
+				@import "../../../dojo/resources/dojo.css";
+				@import "../../../dijit/themes/soria/soria.css";
+				
+				html,body{
+					overflow:hidden;
+					margin:0; padding:0; 
+					width:100%; height:100%;
+				}
+				.cpane{
+					border:1px solid #666;
+					font:bold 12px Arial;
+					color:#999;
+					background:#FFF;
+					padding:10px;
+					height:50px;
+				}
+				
+				#GC1{
+					margin:0;
+					padding:5px;
+					overflow-x:hidden;
+					overflow-y:scroll;
+				}
+				#lGC,
+				#GC1 .gridContainerTable {
+					border-collapse:collapse;
+				}
+
+				#lGC,
+				#GC1 .gridContainerZone {
+					border-collapse:collapse;
+					border : 2px solid #ededed
+				}
+				
+				.dj_ie6 .dropIndicator, .dj_ie6 .dijitContentpane, .dj_ie6 .dijitCalendar{
+					margin: 5px;
+				}
+				.gridContainerZone > *{
+					margin: 5px !important;
+				}
+			/* ]]> */
+		</style>
+		
+		<link rel="stylesheet" href="../resources/GridContainer.css">
+		<link rel="stylesheet" href="../resources/ExpandoPane.css">
+		
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("dijit.TitlePane");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dojox.layout.GridContainer");
+			dojo.require("dojox.layout.ExpandoPane");
+			dojo.require("dijit.layout.BorderContainer");
+			dojo.require("dijit.layout.AccordionContainer");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.Calendar");
+			dojo.require("dojo.fx.easing");
+			var GC1;
+			function setColumns(){
+				GC1 = dijit.byId("GC1");
+				nb = dojo.byId("nbCol").value;
+				if(nb > 0){
+					GC1.setColumns(nb);
+				}
+			}
+		</script>
+
+	</head>
+
+	<body class="soria">
+		<div id="layout" dojoType="dijit.layout.BorderContainer" liveSplitters="false" style="height:100%; width:100%">
+			
+			<div id="expandoL" dojoType="dojox.layout.ExpandoPane" 
+				title="Left Side" splitter="true" 
+				style="width:200px" 
+				region="left" 
+				easeIn="dojo.fx.easing.backOut" duration="600"
+			>
+				<div id="lGC" dojoType="dojox.layout.GridContainer"
+					acceptTypes="TitlePane, AccordionContainer, Calendar"
+					hasResizableColumns="false"
+					nbZones="1"
+					style="height:100%"
+				>
+					<div dojoType="dijit.TitlePane" attachParent="true" title="Panel 1" dndType="TitlePane">
+						lorem ipsum
+					</div>	
+					<div dojoType="dijit.TitlePane" title="Panel 2" dndType="TitlePane">
+						lorem ipsum
+					</div>	
+					<div dojoType="dijit.TitlePane" title="Panel 3" dndType="TitlePane">
+						lorem ipsum
+					</div>	
+
+				</div>
+			</div>
+			
+			<div id="GC1" dojoType="dojox.layout.GridContainer" 
+				region="center"
+				nbZones="3"
+				hasResizableColumns="false"				
+				acceptTypes="ContentPane, TitlePane">
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°1 !</div>
+					<div dojoType="dijit.TitlePane" title="Ergo" dndType="TitlePane">
+						Non ergo erunt homines deliciis diffluentes audiendi, si quando de amicitia, quam nec usu nec ratione habent cognitam, disputabunt. Nam quis est, pro deorum fidem atque hominum! qui velit, ut neque diligat quemquam nec ipse ab ullo diligatur, circumfluere omnibus copiis atque in omnium rerum abundantia vivere? Haec enim est tyrannorum vita nimirum, in qua nulla fides, nulla caritas, nulla stabilis benevolentiae potest esse fiducia, omnia semper suspecta atque sollicita, nullus locu [...]
+					</div>
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°2 !</div>
+			  		<div dojoType="dijit.layout.ContentPane" title="Intellectum" dndType="ContentPane">
+			  			Intellectum est enim mihi quidem in multis, et maxime in me ipso, sed paulo ante in omnibus, cum M. Marcellum senatui reique publicae concessisti, commemoratis praesertim offensionibus, te auctoritatem huius ordinis dignitatemque rei publicae tuis vel doloribus vel suspicionibus anteferre. Ille quidem fructum omnis ante actae vitae hodierno die maximum cepit, cum summo consensu senatus, tum iudicio tuo gravissimo et maximo. Ex quo profecto intellegis quanta in dato beneficio sit  [...]
+			  		</div>
+			  		
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°3 !</div>
+					<div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane" dndType="ContentPane">Content Pane n°4 !</div>
+					<div dojoType="dijit.Calendar" dndType="Calendar"></div>
+
+			</div>
+			
+			<div id="rGC" dojoType="dojox.layout.GridContainer"
+				acceptTypes="TitlePane"
+				hasResizableColumns="false"
+				nbZones="1"
+				region="right"
+				style="width:200px"
+				splitter="true"
+			>
+				<div dojoType="dijit.TitlePane" attachParent="true" title="Panel 1" dndType="TitlePane">
+					lorem ipsum
+				</div>	
+				<div dojoType="dijit.TitlePane" title="Panel 2" dndType="TitlePane">
+					lorem ipsum
+				</div>	
+				<div dojoType="dijit.TitlePane" title="Panel 3" dndType="TitlePane">
+					lorem ipsum
+				</div>	
+			</div>
+			
+		</div>
+
+	</body>
+</html>
diff --git a/dojox/layout/tests/test_GridContainer_in_BorderContainer_prog.html b/dojox/layout/tests/test_GridContainer_in_BorderContainer_prog.html
new file mode 100644
index 0000000..24197d7
--- /dev/null
+++ b/dojox/layout/tests/test_GridContainer_in_BorderContainer_prog.html
@@ -0,0 +1,231 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<title>Demo GridContainer</title>
+		<style type="text/css" title="text/css">
+			/* <![CDATA[ */
+				@import "../../../dojo/resources/dojo.css";
+				@import "../../../dijit/themes/soria/soria.css";
+				
+				html,body{
+					overflow:hidden;
+					margin:0; padding:0; 
+					width:100%; height:100%;
+				}
+
+				.cpane{
+					border:1px solid #666;
+					font:bold 12px Arial;
+					color:#999;
+					background:#FFF;
+					padding:10px;
+					height:50px;
+				}
+				
+				#GC1{
+					margin:0;
+					padding:5px;
+					overflow-x:hidden;
+					overflow-y:scroll;
+				}
+				#GC1 .gridContainerTable {
+					border-collapse:collapse;
+				}
+
+				#GC1 .gridContainerZone {
+					border : 2px solid #ededed
+				}
+				
+				.dj_ie6 .dropIndicator, .dj_ie6 .dijitContentPane, .dj_ie6 .dijitCalendar{
+					margin: 5px;
+				}
+				.gridContainerZone > *{
+					margin: 5px !important;
+				}
+				
+			/* ]]> */
+		</style>
+		
+		<link rel="stylesheet" href="../resources/GridContainer.css">
+		<link rel="stylesheet" href="../resources/ExpandoPane.css">
+		
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("dijit.TitlePane");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dojox.layout.GridContainer");
+			dojo.require("dojox.layout.ExpandoPane");
+			dojo.require("dijit.layout.BorderContainer");
+			dojo.require("dijit.layout.AccordionContainer");
+			dojo.require("dijit.form.Button");
+			dojo.require("dijit.Calendar");
+			dojo.require("dojo.fx.easing");
+
+			dojo.addOnLoad(init);
+			function init(){
+				// Create the border container
+				bc = new dijit.layout.BorderContainer({liveSplitters:false, style:{height: '100%', width: '100%'}});
+				document.body.appendChild(bc.domNode);
+				
+				// Create the ExpandoPane to be placed on the left hand side
+				ep = new dojox.layout.ExpandoPane({
+					title: 'Left Side', 
+					splitter:true, 
+					style:{
+						width:'200px'
+					}, 
+					region: 'left', 
+					easing: dojo.fx.easing.backOut, 
+					duration: 600
+				});
+				bc.addChild(ep);
+				
+				// Create the GridContainer to be placed on the left hand side.
+				// You cna drag TitlePanes, AccordionContainers and Calendar widgets into it
+				gc1 = new dojox.layout.GridContainer({
+					acceptTypes: ['TitlePane', 'AccordionContainer', 'Calendar'], 
+					hasResizableColumns:false,  
+					nbZones:1, 
+					style:{
+						height: '100%'
+					}
+				});
+				ep.containerNode.appendChild(gc1.domNode);
+				
+				// Add three TitlePane widgets. Note that the 'dndType' attributes are the same
+				// as those in the 'acceptTypes' attribute of the GridContainer.
+				// These do NOT have to match to the widget type name
+				tp1 = new dijit.TitlePane({
+					attachParent:true, 
+					title:'Panel 1', 
+					dndType:'TitlePane'
+				});
+				tp1.attr('content', 'lorem ipsum');
+				gc1.addChild(tp1);
+
+				tp2 = new dijit.TitlePane({
+					title:'Panel 2', 
+					dndType:'TitlePane'
+				});
+				tp2.attr('content', 'lorem ipsum');
+				gc1.addChild(tp2);
+
+				tp3 = new dijit.TitlePane({
+					title:'Panel 3', 
+					dndType:'TitlePane'
+				});
+				tp3.attr('content', 'lorem ipsum');
+				gc1.addChild(tp3,0,2);
+				
+				// Create the central GridContainer
+				gc2 = new dojox.layout.GridContainer({
+					id:'GC1', 
+					region: 'center', 
+					nbZones:3, 
+					hasResizableColumns:false, 
+					acceptTypes:['ContentPane', 'TitlePane', 'Calendar', 'AccordionPane']
+				});
+				bc.addChild(gc2);
+				
+				cp1 = new dijit.layout.ContentPane({
+					"class":'cpane', 
+					label:'Content Pane', 
+					dndType:'ContentPane'
+				});
+				cp1.attr('content', 'ContentPane n*1 !');
+				gc2.addChild(cp1);
+
+				tp4 = new dijit.TitlePane({
+					title:'Ergo', 
+					dndType:'TitlePane'
+				});
+				tp4.attr('content', 'Non ergo erunt homines deliciis diffluentes audiendi, si quando de amicitia, quam nec usu nec ratione habent cognitam, disputabunt. Nam quis est, pro deorum fidem atque hominum! qui velit, ut neque diligat quemquam nec ipse ab ullo diligatur, circumfluere omnibus copiis atque in omnium rerum abundantia vivere? Haec enim est tyrannorum vita nimirum, in qua nulla fides, nulla caritas, nulla stabilis benevolentiae potest esse fiducia, omnia semper suspecta atque sol [...]
+				gc2.addChild(tp4,0,1);
+
+				cp2 = new dijit.layout.ContentPane({
+					"class":'cpane', 
+					label:"Content Pane", 
+					dndType:'ContentPane'
+				});
+				cp2.attr('content', 'Content Pane n*2 !');
+				gc2.addChild(cp2,1,0);
+
+				cp3 = new dijit.layout.ContentPane({
+					title:"Itellectum", 
+					dndType:'ContentPane'
+				});
+				cp3.attr('content', 'Intellectum est enim mihi quidem in multis, et maxime in me ipso, sed paulo ante in omnibus, cum M. Marcellum senatui reique publicae concessisti, commemoratis praesertim offensionibus, te auctoritatem huius ordinis dignitatemque rei publicae tuis vel doloribus vel suspicionibus anteferre. Ille quidem fructum omnis ante actae vitae hodierno die maximum cepit, cum summo consensu senatus, tum iudicio tuo gravissimo et maximo. Ex quo profecto intellegis quanta in da [...]
+				gc2.addChild(cp3,1,1);
+
+				cp4 = new dijit.layout.ContentPane({
+					"class":'cpane', 
+					label:'Content Pane', 
+					dndType:'ContentPane'
+				});
+				cp4.attr('content', 'Content Pane n*3 !');
+				gc2.addChild(cp4,1,2);
+
+				cp5 = new dijit.layout.ContentPane({
+					"class":'cpane', 
+					label:'Content Pane', 
+					dndType:'ContentPane'
+				});
+				cp5.attr('content', 'Content Pane n*4 !');
+				gc2.addChild(cp5,2,0);
+
+				dp = new dijit.Calendar({dndType:'Calendar'});
+				gc2.addChild(dp,2,1);
+
+				// Add the grid container on the right hand side.  Only TitlePanes can be dragged into it.
+				gc3 = new dojox.layout.GridContainer({
+					region: 'right', 
+					nbZones:1, 
+					hasResizableColumns:false, 
+					acceptTypes:['TitlePane'], 
+					style: {width:'200px'}, 
+					splitter:true});
+				bc.addChild(gc3);
+
+				tp4 = new dijit.TitlePane({
+					attachParent:true, 
+					title:'Panel 1', 
+					dndType:'TitlePane'
+				});
+				tp4.attr('content', 'lorem ipsum');
+				gc3.addChild(tp4,0,0);
+
+				tp5 = new dijit.TitlePane({
+					title:'Panel 2', 
+					dndType:'TitlePane'
+				});
+				tp5.attr('content', 'lorem ipsum');
+				gc3.addChild(tp5,0,1);
+
+				tp6 = new dijit.TitlePane({
+					title:'Panel 3', 
+					dndType:'TitlePane'
+				});
+				tp6.attr('content', 'lorem ipsum');
+				gc3.addChild(tp6,0,2);
+
+				gc1.startup();
+				bc.startup();
+			}
+
+		</script>
+
+	</head>
+
+	<body class="soria">
+		<div style="width:200px;height:200px;background-color: #aaa;cursor:pointer;" 
+				id="deleteThis" 
+				onclick="dojo.destroy(dojo.byId('deleteThis'))">
+			Test dragging elements in the GridContainer. 
+			Then click To Delete Me Then try to drag elements in the GridContainer again
+		</div>
+	</body>
+</html>
diff --git a/dojox/layout/tests/test_RadioGroup.html b/dojox/layout/tests/test_RadioGroup.html
new file mode 100644
index 0000000..8d0632d
--- /dev/null
+++ b/dojox/layout/tests/test_RadioGroup.html
@@ -0,0 +1,150 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>RadioGroup (Animated StackContainer) Widget Test</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/RadioGroup.css">	
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../RadioGroup.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dojox.layout.RadioGroup");
+		dojo.require("dojo.parser"); 
+		dojo.require("dijit.layout.ContentPane"); 
+		dojo.require("dijit.form.Button");
+	</script>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		body { background:#a0a0a0 !important; }
+
+		.dojoPane {
+			background:#eee url('../../../util/resources/logo/positive/dojo.logo.png') no-repeat center center !important;
+		}
+		.dojoxPane {
+			background:#ededed url('../../../util/resources/logo/positive/dojox.logo.png') no-repeat center center !important;
+		}
+		.dijitPane {
+			background:#fefefe url('../../../util/resources/logo/positive/dijit.logo.png') no-repeat center center !important;
+		}
+
+		#newestone .dijitContentPane {
+			background:#fff;
+		}
+		#newestone .dijitContentPane p {
+			padding:20px;
+			font-size:200%;
+		}
+	</style>
+
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">dojox.layout.RadioGroup test</h1>
+
+	<div style="width:915px; margin:0 auto; height:300px;">
+		<div id="firstGroup" dojoType="dojox.layout.RadioGroup" style="width:300px; height:300px; float:left;" hasButtons="true">
+			<div dojoType="dijit.layout.ContentPane" title="Dojo" class="dojoPane" style="width:300px; height:300px; "></div>
+			<div dojoType="dijit.layout.ContentPane" title="Dijit" class="dijitPane" style="width:300px; height:300px; "></div>
+			<div dojoType="dijit.layout.ContentPane" title="Dojox" class="dojoxPane" style="width:300px; height:300px; "></div>
+		</div>
+	
+		<div id="firstFade" dojoType="dojox.layout.RadioGroupFade" style="width:300px; height:300px; float:left" hasButtons="true">
+			<div dojoType="dijit.layout.ContentPane" title="Dojo" class="dojoPane" style="width:300px; height:300px; "></div>
+			<div dojoType="dijit.layout.ContentPane" title="Dijit" class="dijitPane" style="width:300px; height:300px; "></div>
+			<div dojoType="dijit.layout.ContentPane" title="Dojox" class="dojoxPane" style="width:300px; height:300px; "></div>
+		</div>
+	
+		<div id="firstSlide" dojoType="dojox.layout.RadioGroupSlide" style="width:300px; height:300px;" hasButtons="true">
+			<div dojoType="dijit.layout.ContentPane" title="Dojo" class="dojoPane" style="width:300px; height:300px; "></div>
+			<div dojoType="dijit.layout.ContentPane" title="Dijit" class="dijitPane" style="width:300px; height:300px; "></div>
+			<div dojoType="dijit.layout.ContentPane" title="Dojox" class="dojoxPane" style="width:300px; height:300px; "></div>
+		</div>
+	</div>
+
+	<br style="clear:both">
+	<br style="clear:both">
+	<div>
+		<button dojoType="dijit.form.Button">add children
+			<script type="dojo/method" event="onClick">
+				dojo.forEach(["firstGroup","firstFade","firstSlide"], function(id){
+					var w = dijit.byId(id);
+					w.addChild(
+						new dijit.layout.ContentPane({
+							title:"Added", href:"_lorem.html",
+							style:"padding:8px; background-color:#fff"
+						})
+					);
+				})
+			</script>
+		</button>
+		
+		<button dojoType="dijit.form.Button">remove one from each
+			<script type="dojo/method" event="onClick">
+				dijit.registry.filter(function(w){
+					return w.declaredClass.match(/dojox\.layout\.RadioGroup/);
+				}).forEach(function(w){
+					var child = w.selectedChildWidget;
+					if(child){
+						w.removeChild(child);
+					}
+				});
+			</script>
+		</button>
+	</div>
+
+	<div id="proggy" style="width:915px; margin:0 auto; height:300px;">
+		<div dojoType="dojox.layout.RadioGroupSlide" style="width:300px; height:300px; float:left" hasButtons="true">
+			<div dojoType="dijit.layout.ContentPane" slideFrom="top" title="Dojo" class="dojoPane" style="width:300px; height:300px; "><p>1</p></div>
+			<div dojoType="dijit.layout.ContentPane" slideFrom="top" title="Dijit" class="dijitPane" style="width:300px; height:300px; "><p>2</p></div>
+			<div dojoType="dijit.layout.ContentPane" slideFrom="top" title="Dojox" class="dojoxPane" style="width:300px; height:300px; "><p>3</p></div>
+		</div>
+	
+		<div dojoType="dojox.layout.RadioGroupSlide" style="width:300px; height:300px;" hasButtons="true">
+			<div dojoType="dijit.layout.ContentPane" slideFrom="left" title="Dojo" class="dojoPane" style="width:300px; height:300px; "><p>1</p></div>
+			<div dojoType="dijit.layout.ContentPane" slideFrom="bottom" title="Dijit" class="dijitPane" style="width:300px; height:300px; "><p>2</p></div>
+			<div dojoType="dijit.layout.ContentPane" slideFrom="right" title="Dojox" class="dojoxPane" style="width:300px; height:300px; "><p>3</p></div>
+		</div>
+	</div>
+	
+	<script>
+		dojo.addOnLoad(function(){
+			
+			var x = 0, lorem = function(){ 
+				return "<p>Pane" + (++x) + " Content!</p>";
+			};
+			
+			// basic programatic instantiation
+			var g = new dojox.layout.RadioGroupSlide({
+				style:"width:300px; height:300px; float:left",
+				hasButtons:true,
+				id:"newestone"
+			}).placeAt("proggy");
+			
+			new dijit.layout.ContentPane({ title:"one", content:lorem() }).placeAt(g);
+			new dijit.layout.ContentPane({ title:"two", content:lorem() }).placeAt(g);
+			
+			g.startup();
+			
+			// testing addchild after startup
+			new dijit.layout.ContentPane({ title:"after", content:lorem() }).placeAt(g);
+			
+		})
+	</script>
+	
+
+
+</body>
+</html>
diff --git a/dojox/layout/tests/test_ResizeHandle.html b/dojox/layout/tests/test_ResizeHandle.html
new file mode 100644
index 0000000..16fb7ee
--- /dev/null
+++ b/dojox/layout/tests/test_ResizeHandle.html
@@ -0,0 +1,196 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Resize Widget Test</title>
+
+	<script type="text/javascript">var djConfig = {isDebug: true, parseOnLoad: true };</script>
+	<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+	<script type="text/javascript" src="../ResizeHandle.js"></script>
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dojo.parser"); 
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.form.Button");
+		// dojo.require("dojox.layout.ResizeHandle");
+	
+		function makeNewSizer(){
+			var handle = document.createElement('div');
+			dojo.byId("programatic").appendChild(handle);
+			var resizer = new dojox.layout.ResizeHandle({
+				targetId: "programatic",
+				activeResize: true
+			},handle);
+			resizer.startup();
+		}
+		dojo.addOnLoad(makeNewSizer);
+		
+		// HOWTO use the resize topics
+		dojo.subscribe("/dojo/resize/start", function(inst){
+			// inst is the resizehandle instance. Lookup any members about 
+			// which node/widget/etc that way.
+			dojo.byId("status").innerHTML = "Resizing: " + inst;
+		});
+		var timer;
+		dojo.subscribe("/dojo/resize/stop", function(inst){
+			dojo.byId("status").innerHTML = "Finished: " + inst;
+			timer && clearTimeout(timer);
+			timer = setTimeout(function(){
+				dojo.fadeOut({
+					node: "status",
+					onEnd: function(n){
+						n.innerHTML = "Waiting.";
+						dojo.anim(n, { opacity: 1});
+					}
+				}).play();
+			}, 300);
+		});
+
+	</script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../resources/ResizeHandle.css"; 
+		#programatic {
+			width:100px;
+			height:100px;
+			border:2px solid #333; 
+			position:relative;
+		}
+		
+		#handler, #handler2, #minMax {
+			position:relative; float:left;
+		}
+	</style>
+
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">dojox.layout.ResizeHandle test</h1>
+
+	<div id="status">Status Node</div>
+	
+	<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam facilisis enim. 
+	Pellentesque in elit et lacus euismod dignissim. Aliquam dolor pede, convallis eget, 
+	dictum a, blandit ac, urna. Pellentesque sed nunc ut justo volutpat egestas. Class 
+	aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos.
+	In erat. Suspendisse potenti. Fusce faucibus nibh sed nisi. Phasellus faucibus, dui 
+	a cursus dapibus, mauris nulla euismod velit, a lobortis turpis arcu vel dui. Pellentesque 
+	fermentum ultrices pede. Donec auctor lectus eu arcu. Curabitur non orci eget est porta gravida.
+	Aliquam pretium orci id nisi. Duis faucibus, mi non adipiscing venenatis, erat urna aliquet elit,
+	eu fringilla lacus tellus quis erat. Nam tempus ornare lorem. Nullam feugiat.</p>
+
+	<p>Sed congue. Aenean blandit sollicitudin mi. Maecenas pellentesque. Vivamus ac urna. Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin suscipit porta magna. Duis accumsan nunc in velit. Nam et nibh. Nulla facilisi. Cras venenatis urna et magna. Aenean magna mauris, bibendum sit amet, semper quis, aliquet nec, sapien. Aliquam aliquam odio quis erat. Etiam est nisi, condimentum non, lacinia ac, vehicula laoreet, elit. Sed interdum augue sit amet quam dapibus semper. Nulla faci [...]
+
+	<!-- TODO: figure out a way to attach to non-containers, or make ResizeContainter
+	<div style="position:relative; height:188px; width:125px; margin:0; padding:0; " id="logo"><img src="images/dojoLogo.png" style="width:100%; height:100%">
+	<div dojoType="dojox.layout.ResizeHandle" activeSizing="true" targetId="logo"></div>
+	</div>
+	-->
+
+	<div id="programatic"> This is text!</div>
+	<br><br>
+	<div dojoType="dijit.layout.ContentPane"
+		title="Test window"
+		style="width: 300px; height: 200px; padding:10px; border: 1px solid #dedede; position: relative; background: white;"
+		id="testWindow"
+	>
+		
+		<button dojoType='dijit.form.Button'>
+			kill handle
+			<script type="dojo/method" event="onClick">
+				dijit.byId("hand1").destroy();
+			</script>
+		</button>
+		Content Pane w/a resize handle. activeResize'ing only on layout Widgets? FIXME: :)
+		<div id="hand1" dojoType="dojox.layout.ResizeHandle" targetId="testWindow"></div>
+	</div>
+
+	<br>
+
+	<div id="plainDiv"
+		style="width: 300px; padding:3px; height: 200px; border:1px solid #666; position: relative; background: white;"
+	>
+		<button dojoType='dijit.form.Button'>
+			kill handle
+			<script type="dojo/method" event="onClick">
+				dijit.byId("hand2").destroy();
+			</script>
+		</button>
+		Plain div w/a resize handle. All Default settings.
+		<div id="hand2" dojoType="dojox.layout.ResizeHandle" targetId="plainDiv"></div>
+	</div>
+
+	<br><br>	
+
+	<div id="plainDiv3" 
+		style="margin:8px; float:left; width: 300px; height: 200px; border: solid red 5px; position: relative; background: white;"
+	>
+		Plain div w/a resize handle but resizeAxis="y", and activeResize="true"
+		<div dojoType="dojox.layout.ResizeHandle" resizeAxis="y" activeResize="true" targetId="plainDiv3" style="bottom: 0; right: 0; position: absolute;"></div>
+	</div>
+
+
+	<div id="plainDiv2" 
+		style="margin:8px; float:left; width: 300px; height: 200px; border: solid red 5px; position: relative; background: white;"
+	>
+		Plain div w/a resize handle but resizeAxis="x" with animated sizing.
+		<div dojoType="dojox.layout.ResizeHandle" resizeAxis="x" targetId="plainDiv2" style="bottom: 2px; right: 2px; position: absolute;"></div>
+	</div>
+
+	<br><br>
+	
+	<div id="plainDiv22" 
+		style="margin:8px; padding:15px; float:left; width: 300px; height: 200px; border: solid red 5px; position: relative; background: white;"
+	>
+		Plain div w/a resize handle but resizeAxis="xy" with animated sizing (combine).
+		<div dojoType="dojox.layout.ResizeHandle" resizeAxis="xy" animateMethod="combine" targetId="plainDiv22" style="bottom: 2px; right: 2px; position: absolute;"></div>
+	</div>
+
+	<br><br>
+
+	<p>Sed arcu magna, molestie at, fringilla in, sodales eu, elit. Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus ut elit convallis eleifend. Fusce tincidunt, justo quis tempus euismod, magna nulla viverra libero, sit amet lacinia odio diam id risus. Ut varius viverra turpis. M [...]
+
+	<p>Fusce rutrum pede eget quam. Praesent purus. Aenean at elit in sem volutpat facilisis. Nunc est augue, commodo at, pretium a, fermentum at, quam. Nam sit amet enim. Suspendisse potenti. Cras hendrerit rhoncus justo. Integer libero. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam erat volutpat. Sed adipiscing mi vel ipsum.</p>
+
+	<br style="clear:both;">
+	
+	<h2>Experimental Settings:</h2>
+
+	<div id="handler" style="height:200px; width:200px; border:2px solid #ededed">
+		<p>Plain div with fixed aspect and 1:1</p>
+		<div dojoType="dojox.layout.ResizeHandle" targetId="handler" fixedAspect="true" style="bottom: 2px; right: 2px; position: absolute;"></div>
+	</div>
+
+	<p>known issue: fixed aspect only works with 1:1 aspect ratio</p>
+	<div id="handler2" style="height:100px; width:300px; border:red">
+		<p>Plain div with fixed aspect and 4:3</p>
+		<div dojoType="dojox.layout.ResizeHandle" targetId="handler2" fixedAspect="true" style="bottom: 2px; right: 2px; position: absolute;"></div>
+	</div>
+
+	<div id="minMax" style="width:150px; height:150px; border:1px solid #000">
+		<p>Min/Max set to 25x25 and 200x200, constrainMax = true</p>
+		<div dojoType="dojox.layout.ResizeHandle" targetId="minMax"
+			constrainMax="true" maxWidth="200" maxHeight="200"
+			minWidth="25" minHeight="25" style="bottom: 2px; right: 2px; position: absolute;"
+		></div>
+	</div>
+
+	<div id="minMax2" style="width:150px; float:left; position:relative; height:150px; border:1px solid #000">
+		<p>Min/Max set to 25x25 and 200x200, constrainMax = true, fixed 1:1 aspect</p>
+		<div dojoType="dojox.layout.ResizeHandle" targetId="minMax2"
+			constrainMax="true" maxWidth="200" maxHeight="200" fixedAspect="true"
+			minWidth="25" minHeight="25" style="bottom: 2px; right: 2px; position: absolute;"
+		></div>
+	</div>
+
+	<br style="clear:both;">
+
+	<p>Sed aliquam, quam consectetuer condimentum bibendum, neque libero commodo metus, non consectetuer magna risus vitae eros. Pellentesque mollis augue id libero. Morbi nonummy hendrerit dui. Morbi nisi felis, fringilla ac, euismod vitae, dictum mollis, pede. Integer suscipit, est sed posuere ullamcorper, ipsum lectus interdum nunc, quis blandit erat eros hendrerit pede. Vestibulum varius, elit id mattis mattis, nulla est feugiat ante, eget vestibulum augue eros ut odio. Maecenas euismod [...]
+
+	<p>Sed aliquam, quam consectetuer condimentum bibendum, neque libero commodo metus, non consectetuer magna risus vitae eros. Pellentesque mollis augue id libero. Morbi nonummy hendrerit dui. Morbi nisi felis, fringilla ac, euismod vitae, dictum mollis, pede. Integer suscipit, est sed posuere ullamcorper, ipsum lectus interdum nunc, quis blandit erat eros hendrerit pede. Vestibulum varius, elit id mattis mattis, nulla est feugiat ante, eget vestibulum augue eros ut odio. Maecenas euismod [...]
+
+
+</body>
+</html>
diff --git a/dojox/layout/tests/test_RotatorContainer.html b/dojox/layout/tests/test_RotatorContainer.html
new file mode 100644
index 0000000..f21a4ec
--- /dev/null
+++ b/dojox/layout/tests/test_RotatorContainer.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>RotatorContainer layout widget Test</title>
+	<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+	@import "../resources/RotatorContainer.css";
+
+	#pane4 {
+		background:url(../../image/tests/images/imageHoriz2.jpg) no-repeat 0 0;
+		color:#FFF;
+	}
+
+	#pane4 h1, #pane4 p {
+		background-color:#000;
+		opacity:0.8;
+	}
+	
+	#myRotator {
+		width:350px; height:275px;
+	}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad:true, isDebug:true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojox.layout.RotatorContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.form.ComboBox");
+	</script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">dojox.layout.RotatorContainer</h1>
+
+	<p>This RotatorContainer will auto-start and cycle every 2.5 seconds through each pane and stop when it gets back to the first pane.
+	You can suspend the animation by hovering over the rotator, but as soon as you mouse off, it will resume.</p>
+
+	<div style="float:left;padding:0 20px 20px 0;">
+
+		<div dojoType="dojox.layout.RotatorContainer" id="myRotator" showTabs="true" cycles="4" suspendOnHover="true" autoStart="true" transitionDelay="2500" transition="fade">
+
+			<div dojoType="dojox.layout.RotatorPager">
+				<button dojoType="dijit.form.Button" dojoAttachPoint="previous">Prev</button>
+				<span dojoAttachPoint="current"></span> / <span dojoAttachPoint="total"></span>
+				<button dojoType="dijit.form.Button" dojoAttachPoint="next">Next</button>
+				<button dojoType="dijit.form.ToggleButton" dojoAttachPoint="playPause"></button>
+			</div>
+
+			<div id="pane1" dojoType="dijit.layout.ContentPane" title="1">
+				<h1>Welcome!</h1>
+				<p>It cycles through ContentPanes and even has transitions!</p>
+			</div>
+
+			<div id="pane2" dojoType="dijit.layout.ContentPane" title="2" transitionDelay="5000">
+				<h1>This is the 2nd pane</h1>
+				<p>Then next pane will be lazy loaded in 5 seconds!</p>
+			</div>
+
+			<div id="pane3" dojoType="dijit.layout.ContentPane" href="doc0.html" title="3"></div>
+
+			<div id="pane4" dojoType="dijit.layout.ContentPane" title="4">
+				<h1>Background pictures!</h1>
+				<p>You can put virtually anything here.</p>
+			</div>
+
+		</div>
+
+	</div>
+
+	<div>
+
+		<h3>Remote pager without a play/pause button</h3>
+
+		<div dojoType="dojox.layout.RotatorPager" rotatorId="myRotator">
+			<button dojoType="dijit.form.Button" dojoAttachPoint="previous">Prev</button>
+			<button dojoType="dijit.form.Button" dojoAttachPoint="next">Next</button>
+			<span dojoAttachPoint="current"></span> / <span dojoAttachPoint="total"></span>
+		</div>
+
+		<h3>Remote pager with styled buttons</h3>
+
+		<div dojoType="dojox.layout.RotatorPager" class="rotatorIcons" rotatorId="myRotator">
+			<button dojoType="dijit.form.Button" iconClass="previous" dojoAttachPoint="previous">Prev</button>
+			<button dojoType="dijit.form.ToggleButton" iconClass="playPause" dojoAttachPoint="playPause"></button>
+			<button dojoType="dijit.form.Button" iconClass="next" dojoAttachPoint="next">Next</button>
+			<span dojoAttachPoint="current"></span> / <span dojoAttachPoint="total"></span>
+		</div>
+
+	</div>
+
+	<div style="clear:both;"></div>
+
+</body>
+</html>
diff --git a/dojox/layout/tests/test_ScrollPane.html b/dojox/layout/tests/test_ScrollPane.html
new file mode 100644
index 0000000..1b5a12f
--- /dev/null
+++ b/dojox/layout/tests/test_ScrollPane.html
@@ -0,0 +1,194 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>ScrollPane layout widget Test</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/ScrollPane.css">	
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../ScrollPane.js"></script>
+	
+	<script language="JavaScript" type="text/javascript">
+		
+		dojo.require("dojox.layout.ScrollPane");
+		dojo.require("dojo.parser");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.addOnLoad(function(){
+			var i; 
+			var node = dojo.byId("cloneMe");
+			dojo.query(".list").forEach(function(n){
+				for(i = 0; i<42; i++){
+					var b = n.appendChild(dojo.clone(node));
+				}
+			});
+
+			dojo.parser.parse();
+			
+			// programatic example:
+			var widget = new dojox.layout.ScrollPane({
+				orientation: "vertical",
+				style:"width:125px; height:300px; border:2px solid #ededed"
+			},"progExample");
+						
+		});
+	</script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		#altStyle .dojoxScrollHelper {
+			-moz-border-radius:3pt;
+			background:#b7cdee;
+			border:2px solid #333;
+			width:3px;
+		}
+		table.fooBar td {
+			width:50px;
+			border-right:2px solid #000; 
+			padding:20px;
+		}
+
+		#vertList li {
+			cursor:pointer;
+		}
+		.foo { float:left; }
+		p.special { width:800px; }
+	</style>
+
+</head>
+<body class="tundra">
+
+	<h1 class='testTitle'>dojox.layout.ScrollPane</h1>
+
+	<p>An intuitive UI for lists of data in a confined space. supports horizontal or vertical "scrolling", but not both</p>
+	
+	<h2>vertical:</h2>
+	<div style="float:left; padding-right:12px;">
+
+		<div dojoType="dojox.layout.ScrollPane" style="width:100px; height:300px; border:1px solid #b7b7b7">
+			<ol class="list" id="vertList">
+				<li id="cloneMe"><a href="#"><span>testItem</span></a></li>
+			</ol>
+		</div>
+		
+	</div>
+	<div id="altStyle" style="float:left; padding-right:12px;">
+
+		<div dojoType="dojox.layout.ScrollPane" style="width:100px; height:300px; border:1px solid #b7b7b7">
+			<ol class="list" id="vertList2"></ol>
+		</div>
+	
+	</div>
+
+	<br style="clear:both;">	
+
+	<h2>horizontal</h2>
+	<div dojoType="dojox.layout.ScrollPane" orientation="horizontal"  style="width:600px; height:125px; border:1px solid #b7b7b7" id="horiz">
+	<table class="fooBar">
+		<tr>
+			<td style="padding-left:20px;">LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+			<td>LOREM IPSUM</td>
+		</tr>
+	</table>
+	</div>
+
+	<h2>In a BorderContainer:</h2>
+
+	<div dojoType="dijit.layout.BorderContainer" style="width:401px; height:400px; border:1px solid #b7b7b7;">
+		<div dojoType="dojox.layout.ScrollPane" region="left" style="width:100px;">
+			<ol class="list"></ol>
+		</div>
+		<div dojoType="dijit._Widget" region="top" style="height:15px" splitter="true">boo</div>
+		<div region="center" dojoType="dijit.layout.ContentPane">
+			<p>Foo! Seems you need explicit height on ScrollPane's in a BorderContainer. 100% seems to suffice.</p>
+		</div>
+		<!--div region="top" dojoType="dojox.layout.ScrollPane" orientation="horiztonal" style="height:75px;">
+			<table class="fooBar">
+				<tr>
+					<td style="padding-left:20px;">LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+					<td>LOREM IPSUM</td>
+				</tr>
+			</table>
+		</div-->
+		<div dojoType="dojox.layout.ScrollPane" region="right" splitter="true" style="width:100px;">
+			<ol class="list"></ol>
+		</div>
+	</div>
+
+	<h2>Programatically:<h2>
+	
+	<div id="progExample">
+		<ol class="list"></ol>
+	</div>
+
+	<h2>Tabs:</h2>
+	
+	<div id="tabber" dojoType="dijit.layout.TabContainer" style="height:6em; width:200px">
+		<div dojoType="dojox.layout.ScrollPane" title="tab1" orientation="horizontal">
+			<p class='special'>Lorem, ipsum Dolor
+				Lorem, ipsum Dolor
+				Lorem, ipsum Dolor
+				Lorem, ipsum Dolor
+				Lorem, ipsum Dolor	
+			</p>
+		</div>
+		<div dojoType="dojox.layout.ScrollPane" title="tab2" orientation="horizontal">
+			<p class='special'>Lorem, ipsum Dolor
+				Lorem, ipsum Dolor
+				Lorem, ipsum Dolor
+				Lorem, ipsum Dolor
+				Lorem, ipsum Dolor
+				Lorem, ipsum Dolor
+			</p>
+		</div>
+	</div>
+	<div dojoType="dojox.layout.ScrollPane" style="width:600px; height:125px; border:1px solid #b7b7b7" id="noscroll">
+		not enough content to make it scroll
+	</div>
+</body>
+</html>
diff --git a/dojox/layout/tests/test_ScrollPaneSingle.html b/dojox/layout/tests/test_ScrollPaneSingle.html
new file mode 100644
index 0000000..d003556
--- /dev/null
+++ b/dojox/layout/tests/test_ScrollPaneSingle.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>ScrollPane layout widget Test</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/ScrollPane.css">	
+
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: false"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../ScrollPane.js"></script>
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.addOnLoad(function(){
+			var i;
+			var n = dojo.byId("hold");
+			var c = dojo.query(".clone")[0];
+			for(i=0; i<12; i++){
+				var b = dojo.clone(c);
+				n.appendChild(b); // dojo.clone(dojo.byId("clone")));
+			}
+			dojo.parser.parse();
+			dijit.byId("horiz").layout(); 
+		});
+	</script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		.dojoxScrollWindow {
+			position:relative;
+		}
+		.dojoxScrollHelper .helperInner {
+			visibility:hidden;
+		}
+		.dojoxScrollHelper {
+			border:1px solid #b7b7b7;
+			width:4px;
+			background:#ededed;
+			height:3px;
+			position:absolute;
+			bottom:2px;
+			left:4px; 
+		}
+		#altStyle .dojoxScrollHelper {
+			-moz-border-radius:3pt;
+			background:#b7cdee;
+			border:2px solid #333;
+			width:3px;
+		}
+		
+		.container { width:602px; margin:0 auto; }
+		.example { padding:20px; margin:5px; border:1px dotted #b7b7b7; } 
+	</style>
+
+</head>
+<body class="tundra">
+
+<div class="container">
+	<h1 class='testTitle'>dojox.layout.ScrollPane</h1>
+	<h2>horizontal</h2>
+	<div dojoType="dojox.layout.ScrollPane" orientation="horizontal"  style="width:600px; height:125px" id="horiz">
+		<div class="dijitInline" id="hold">
+			<div class="dijitInline clone example">
+				<h2>Foo!</h2><div>text <ul><li>bar</li><li>bar</li></ul></div>
+			</div>
+		</div>
+	</div>
+</div>
+</body>
+</html>
diff --git a/dojox/layout/tests/test_TableContainer.html b/dojox/layout/tests/test_TableContainer.html
new file mode 100644
index 0000000..4ea02a1
--- /dev/null
+++ b/dojox/layout/tests/test_TableContainer.html
@@ -0,0 +1,321 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>TableContainer layout widget Test</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../resources/ScrollPane.css">	
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script language="JavaScript" type="text/javascript" src="../TableContainer.js"></script>
+	
+	<script language="JavaScript" type="text/javascript">
+		
+		dojo.require("dijit.dijit");
+		dojo.require("dojox.layout.TableContainer");
+		dojo.require("dojo.parser");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.NumberTextBox");
+		dojo.require("dijit.form.NumberSpinner");
+		dojo.require("dijit.form.CheckBox");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojox.form.DateTextBox");
+		
+		dojo.addOnLoad(function(){
+			dojo.parser.parse();
+			
+			var programmatic = new dojox.layout.TableContainer(
+				{
+					cols: 2, 
+					customClass:"greyLNF", 
+					"labelWidth": "150"
+				}, dojo.byId("programmatic"));
+			var text1 = new dijit.form.TextBox({label: "ProgText 1"});
+			var text2 = new dijit.form.TextBox({label: "ProgText 2"});
+			var text3 = new dijit.form.TextBox({label: "ProgText 3"});
+			var text4 = new dijit.form.TextBox({label: "ProgText 4"});
+			
+			programmatic.addChild(text1);
+			programmatic.addChild(text2);
+			programmatic.addChild(text3);
+			programmatic.addChild(text4);
+			programmatic.startup();
+		});
+	</script>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../widget/Calendar/Calendar.css";
+
+		#altStyle .dojoxScrollHelper {
+			-moz-border-radius:3pt;
+			background:#b7cdee;
+			border:2px solid #333;
+			width:3px;
+		}
+		table.fooBar td {
+			width:50px;
+			border-right:2px solid #000; 
+			padding:20px;
+		}
+
+		#vertList li {
+			cursor:pointer;
+		}
+		.foo { float:left; }
+		p.special { width:800px; }
+		
+		.dijitTableLayout label {
+			font-weight: bold;
+		}
+		
+		.greyLNF-labelCell {
+			background-color: lightgrey;
+			padding-left: 5px;
+		}
+		.greyLNF-table-horiz .greyLNF-labelCell {
+			text-align: right;
+		}
+		.greyLNF-valueCell {
+			padding-left: 5px;
+		}
+		.innerLNF-table {
+			background-color: lightblue;
+		}
+		.innerLNF-labelCell {
+			padding-bottom: 2px;
+			text-align: center;
+		}
+		.innerLNF-table-vert .innerLNF-labelCell {
+			border-bottom: 1px solid black;
+		}
+		.innerLNF-valueCell {
+			padding-top: 2px;
+			text-align: center;
+		}
+		.greenLNF-labelCell {
+			background-color: green;
+			color: white;
+			text-align: center;
+		}
+		.greenLNF-valueCell {
+			color: blue;
+			padding: 5px;
+			text-align: center;
+		}
+		.greenLNF-valueCell-0 {
+			width: 50%;
+		}
+		.greenLNF-valueCell-2 {
+			width: 25%;
+		}
+		.greyBlueLNF-labelCell {
+			background-color: lightgrey;
+			padding-left: 5px;
+		}
+		.greyBlueLNF-table-horiz .greyBlueLNF-labelCell {
+			text-align: right;
+		}
+		.greyBlueLNF-valueCell {
+			padding-left: 5px;
+			background-color: #D6E9F8;
+		}
+	</style>
+
+</head>
+<body class="tundra">
+
+	<h1 class='testTitle'>dojox.layout.TableContainer</h1>
+
+	<p>
+		A container that lays out child widgets in a set number of columns.
+	  Each widget can have a 'label' or 'title' attribute which can
+		be configured to be displayed beside or above each widget.
+	</p>
+	<p>
+		The TableContainer has no default styling, as the base implementation
+		is designed to be a simple layout mechanism.  However you can style the
+		labels and value cells and rows very easily.  This page shows how four
+		different styling schemes, greyLNF, greyBlueLNF, greenLNF and innerLNF
+		can be applied to TableContainers.
+	</p>
+	
+	<h2>A simple single column layout, with labels in the default horizontal alignment:</h2>
+	
+	<div style="width: 500px; border: 1px solid black;">
+
+		<div dojoType="dojox.layout.TableContainer" cols="1" id="tc1">
+			<div dojoType="dijit.form.TextBox" title="First Name:"></div>
+			<div dojoType="dijit.form.TextBox" title="Last Name:"></div>
+			<div dojoType="dijit.form.CheckBox" title="Employed"></div>
+			<div dojoType="dijit.form.NumberSpinner" title="Age" value="30"></div>
+		</div>
+		
+	</div>
+	<h2>A two column layout, with labels in the default horizontal alignment, with custom styling:</h2>
+
+	<span dojoType="dojox.layout.TableContainer" cols="2" id="tc2" 
+			customClass="greyLNF" style="border: 1px solid black;width: 500px;">
+		<div dojoType="dijit.form.CheckBox" title="Married:"></div>
+		<div dojoType="dojox.form.DateTextBox" title="Date Of Birth:" value="1978-06-29"></div>
+		<div dojoType="dijit.form.CheckBox" title="Is Student:" checked="true"></div>
+		<div dojoType="dijit.form.TextBox" title="School Name:" value="University Of Limerick"></div>
+	</span>
+		
+
+	<h2>A three column nested layout with custom styles, that you can configure using the drop down controls below:</h2>
+	<div>
+		Notice the two nested TableContainers, highlighted in blue.  
+		One has the 'spanLabel' attribute set to "true"
+	  so that it takes up both the value cell and the label cell.
+		The other has the label "Nested TableContainer" set.
+	</div>
+	<div>
+		This table also automatically changes the number of columns based on its width,
+		in order to maintain a minimum cell width.  Try resizing the screen to 
+		see this in action.
+	</div>
+	Set the number of columns: 
+	<select onchange="dijit.byId('tc3').attr('cols', this.value)">
+		<option value="1">1</option>
+		<option value="2">2</option>
+		<option value="3" selected>3</option>
+		<option value="4">4</option>
+	</select>
+	Set the label layout: 
+	<select onchange="dijit.byId('tc3').attr('orientation', this.value)">
+		<option value="vert">Vertical</option>
+		<option value="horiz">Horizontal</option>
+	</select>
+	Set the custom CSS: 
+	<select onchange="dijit.byId('tc3').attr('customClass', this.value)">
+		<option value="greyLNF">greyLNF</option>
+		<option value="greenLNF">greenLNF</option>
+	</select>
+	<br>
+	<br>
+	<div style="border: 1px solid black;" >
+
+		<div dojoType="dojox.layout.TableContainer" cols="3" id="tc3" orientation="vert" customClass="greyLNF">
+			<script type="dojo/connect">
+				// This code runs after the widget has been constructed.
+				// It sets the number of columns used by the table based on the width
+				// of the table.
+				
+				var _this = this;
+				function resizeContainer(){
+				  var width = dojo.style(_this.domNode, "width");
+					var numCols = 3;
+
+					if (width < 500) {
+					  numCols = 1;
+					} else if (width < 800) {
+					  numCols = 2;
+					}
+					if (_this.get("cols") != numCols) {
+					  _this.set("cols", numCols);
+					}
+				}
+				var timer;
+				dojo.connect(window, "onresize", dojo.hitch(this, function(){
+				  if (timer) {
+					  clearTimeout(timer);
+					}
+				  timer = setTimeout(resizeContainer, 100);  
+				}));
+			</script>
+			
+			<div dojoType="dijit.form.CheckBox" title="Option 1" id="check1"></div>
+			<div dojoType="dijit.form.CheckBox" title="Option 2" id="check2"></div>
+			<div dojoType="dijit.form.TextBox" title="Text1" id="text1"></div>
+			<div dojoType="dijit.form.NumberTextBox" title="Number" value="120"></div>
+
+			<div dojoType="dijit.form.NumberSpinner" title="Number Spinner" value="100"></div>
+			<div dojoType="dijit.layout.ContentPane" title="Content Pane">
+				This is a ContentPane with a label
+			</div>
+			<div dojoType="dijit.layout.ContentPane" spanLabel="true">
+				This is just some text that fills a couple of cells,
+				look at it wrap around!!!!
+			</div>
+			<div dojoType="dojox.layout.TableContainer" cols="3" id="tc4" 
+					orientation="vert" 
+					spanLabel="true" 
+					customClass="innerLNF"
+					spacing="0"
+					>
+						
+				<div dojoType="dijit.form.CheckBox" title="Nested 1"></div>
+				<div dojoType="dijit.form.CheckBox" title="Nested 2"></div>
+				<div dojoType="dijit.form.CheckBox" title="Nested 3"></div>
+			</div>
+			
+			<div 	dojoType="dojox.layout.TableContainer" 
+						cols="3"  
+						orientation="horiz" 
+						customClass="innerLNF"
+						label="Nested TableContainer"
+						>
+				<div dojoType="dijit.form.CheckBox" title="Horiz Label1"></div>
+				<div dojoType="dijit.form.CheckBox" title="Horiz Label2"></div>
+			</div>
+		</div>
+	</div>
+	
+	<div id="colspanTest">
+		<h2>This table tests the use of the 'colspan' attribute with labels enabled</h2>
+		<div dojoType="dojox.layout.TableContainer" cols="3" customClass="greyBlueLNF" labelWidth="-1">
+			<script type="dojo/connect" event="startup">
+				// Show the actual colspan in each cell
+				dojo.query(".greyBlueLNF-valueCell", this.domNode).forEach(function(cell){
+				  cell.firstChild.innerHTML += " - <i>actual colspan = " + dojo.attr(cell, "colspan") + "</i>";
+				});
+			</script>
+			
+			<div dojoType="dijit.layout.ContentPane" label="Label 1">colspan = 1</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 1">colspan = 1</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 1">colspan = 1</div>			<div dojoType="dijit.layout.ContentPane" label="Label 2" colspan="2">colspan = 2</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 3" colspan="2">colspan = 2</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 4">colspan = 1</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 5">colspan = 1</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 6">colspan = 1</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 7" colspan="3">colspan = 3</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 8" colspan="4">colspan = 4 (just takes up 3)</div>
+		</div>
+		
+		<h2>This table tests the use of the 'colspan' attribute with labels disabled</h2>
+		<div dojoType="dojox.layout.TableContainer" cols="3" customClass="greyBlueLNF" labelWidth="-1" showLabels="false">
+			<script type="dojo/connect" event="startup">
+				// Show the actual colspan in each cell
+				dojo.query(".greyBlueLNF-valueCell", this.domNode).forEach(function(cell){
+				  cell.firstChild.innerHTML += " - <i>actual colspan = " + dojo.attr(cell, "colspan") + "</i>";
+				});
+			</script>
+			
+			<div dojoType="dijit.layout.ContentPane" label="Label 1">colspan = 1</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 1">colspan = 1</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 1">colspan = 1</div>			<div dojoType="dijit.layout.ContentPane" label="Label 2" colspan="2">colspan = 2</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 3" colspan="2">colspan = 2</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 4">colspan = 1</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 5">colspan = 1</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 6">colspan = 1</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 7" colspan="3">colspan = 3</div>
+			<div dojoType="dijit.layout.ContentPane" label="Label 8" colspan="4">colspan = 4 (just takes up 3)</div>
+		</div>
+	</div>
+	
+	<h2>This is a programmatically created TableContainer</h2>
+	<br><br>
+	<div id="programmatic" style="width: 800px;">
+		
+	</div>
+</body>
+</html>
diff --git a/dojox/layout/tests/test_ToggleSplitter.html b/dojox/layout/tests/test_ToggleSplitter.html
new file mode 100644
index 0000000..3cfb1f9
--- /dev/null
+++ b/dojox/layout/tests/test_ToggleSplitter.html
@@ -0,0 +1,132 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.layout.ToggleSplitter Test</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../ToggleSplitter.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.layout.ToggleSplitter");
+		dojo.require("dojo.parser");
+	</script>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../resources/ToggleSplitter.css";
+		
+	</style>
+	
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojox.layout.ToggleSplitter");
+
+		function watchSplitters(bc) {
+
+			var out = dojo.byId("watchedOutput");
+			var moveConnects = {};
+			dojo.forEach(["top", "left"], function(region) {
+				var spl = bc.getSplitter(region); 
+
+				dojo.connect(spl, "_startDrag", function() {
+
+					dojo.style(spl.child.domNode, "opacity", "0.4");
+					moveConnects[spl.widgetId] = dojo.connect(spl.domNode, "onmousemove", function(evt) {
+
+						out.innerHTML = spl.region + ": " + dojo.toJson({
+							x: !spl.horizontal ? spl.domNode.style[spl.region] : 0,
+							y: spl.horizontal ? spl.domNode.style[spl.region] : 0
+						});
+					})
+					
+				});
+				dojo.connect(spl, "_stopDrag", function(evt) {
+					dojo.style(spl.child.domNode, "opacity", 1);
+					dojo.disconnect(moveConnects[spl.widgetId]); 
+					delete moveConnects[spl.widgetId];
+				});
+				dojo.connect(spl, "onOpen", function() {
+					out.innerHTML = spl.region + ": open";
+				});
+				dojo.connect(spl, "onClose", function() {
+					out.innerHTML = spl.region + ": closed";
+				});
+			})
+		}
+		dojo.addOnLoad(function() {
+			watchSplitters( dijit.byId("watchedBC") );
+		})
+	</script>
+</head>
+<body class="tundra" id="testpage">
+
+	<h2 class="testTitle">dojox.layout.ToggleSplitter tests</h2>
+	<p>Double click the splitters to toggle them open/closed</p>
+
+	<div id="border1" dojoType="dijit.layout.BorderContainer"
+		style="width: 90%; height: 300px; border: 2px solid blue; ">
+		<script type="dojo/method">
+			this._splitterClass="dojox.layout.ToggleSplitter";
+		</script>
+
+		<div dojoType="dijit.layout.ContentPane" region="top" style="background-color: #b39b86; border: 1px black solid; height: 50px;" splitter="true">
+			top bar (resizable)
+		</div>
+		<div dojoType="dijit.layout.AccordionContainer"
+			minSize="20" style="width: 300px;" id="leftAccordion" region="leading" splitter="true">
+
+			<div dojoType="dijit.layout.ContentPane" title="Popups and Alerts">
+			</div>
+
+			<div dojoType="dijit.layout.ContentPane" title="Dojo Tree from Store">
+			</div>
+
+			<div dojoType="dijit.layout.ContentPane" title="Calendar" selected="true">
+			</div>
+
+			<div dojoType="dijit.layout.ContentPane" title="Color Picker">
+			</div>
+
+		</div><!-- end AccordionContainer -->
+		<div dojoType="dijit.layout.ContentPane" region="center" style="background-color: #f5ffbf; padding: 3px;">
+			main panel with <a href="http://www.dojotoolkit.org/">a link</a>.<br />
+			(to check we're copying children around properly).<br />
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="right" toggleSplitterOpen="false" style="background-color: #acb386; width: 100px;" splitter="true">
+			initialized closed
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="bottom" style="background-color: #b39b86; height: 50px;" splitter="true">
+			bottom bar (resizable)
+		</div>
+	</div>
+	
+	<br />
+	<p>Watching the splitter events</p>
+	<div dojoType="dijit.layout.BorderContainer" id="watchedBC" persist="false" style="height: 200px; width: 100%">
+		<script type="dojo/method">
+			this._splitterClass="dojox.layout.ToggleSplitter";
+		</script>
+		<div dojoType="dijit.layout.ContentPane" region="top" splitter="true" style="background-color: #ccffcc; height: 50px;">Top:</div>
+		<div dojoType="dijit.layout.ContentPane" region="left" style="background-color: #ccccff; width: 40px" splitter="true"><span>Bottom</span></div>
+		<div dojoType="dijit.layout.ContentPane" region="center" style="background-color: #ffffcc"><span>Center</span></div>
+	</div>
+	
+	<p>Splitter coords output:</p>
+	<div id="watchedOutput" style="border: 1px solid #999">nothing moving</div>
+
+
+</body>
+</html>
diff --git a/dojox/layout/tests/test_TouchStackContainer.html b/dojox/layout/tests/test_TouchStackContainer.html
new file mode 100644
index 0000000..85647a4
--- /dev/null
+++ b/dojox/layout/tests/test_TouchStackContainer.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Touch StackContainer Demo (EXPERIMENTAL)</title>
+
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		.dijitStackController .dijitToggleButtonChecked button {
+			background-color: white;
+			background-image: none;
+		}
+		.dijit_a11y .dijitStackController .dijitToggleButtonChecked button {
+			border-style: dashed !important;
+		}
+	</style>
+	
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: do NOT use in your code! -->
+	<script type="text/javascript" src="../_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojox.layout.ext-dijit.layout.StackContainer-touch");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		function selected(page){
+			console.debug("page selected " + page.id);
+			var widget=dijit.byId("myStackContainer");
+			dijit.byId("previous").attr("disabled", page.isFirstChild);
+			dijit.byId("next").attr("disabled", page.isLastChild);
+			dijit.byId("previous2").attr("disabled", page.isFirstChild);
+			dijit.byId("next2").attr("disabled", page.isLastChild);
+		}
+		dojo.subscribe("myStackContainer-selectChild", selected);
+	</script>
+</head>
+
+<body class="tundra">
+	<h1 class="testTitle">A Tale Of Two Cities</h1>
+
+	<button dojoType="dijit.form.Button" id="previous"
+		onClick="dijit.byId('myStackContainer').back()"><</button>
+	<span dojoType="dijit.layout.StackController" containerId="myStackContainer"></span>
+	<button dojoType="dijit.form.Button" id="next"
+		onClick="dijit.byId('myStackContainer').forward()">></button>
+
+	<div id="myStackContainer" dojoType="dijit.layout.StackContainer"
+		style="width: 90%; border: 1px solid #9b9b9b; height: 20em; margin: 0.5em 0 0.5em 0; padding: 0.5em;">
+		<p id="page1" dojoType="dijit.layout.ContentPane" title="page 1">IT WAS the best of times, it <input value="was the worst" /> of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the  [...]
+		<p id="page2" dojoType="dijit.layout.ContentPane" title="page 2">There were a king with a large jaw and a queen with a plain face, on the throne of England; there were a king with a large jaw and a queen with a fair face, on the throne of <a href="http://www.france.com">France</a>. In both countries it was clearer than crystal to the lords of the State preserves of loaves and fishes, that things in general were settled for ever.</p>
+		<p id="page3" dojoType="dijit.layout.ContentPane" title="page 3">It was the year of Our Lord one thousand seven hundred and seventy- five. Spiritual revelations were conceded to England at that favoured period, as at this. Mrs. Southcott had recently attained her five-and- twentieth blessed birthday, of whom a prophetic private in the Life Guards had heralded the sublime appearance by announcing that arrangements were made for the swallowing up of London and Westminster. Even the Cock- [...]
+	</div>
+
+	<button dojoType="dijit.form.Button" id="previous2" onClick="dijit.byId('myStackContainer').back()"><</button>
+	<span dojoType="dijit.layout.StackController" containerId="myStackContainer"></span>
+	<button dojoType="dijit.form.Button" id="next2" onClick="dijit.byId('myStackContainer').forward()">></button>
+
+</body>
+</html>
diff --git a/dojox/math.js b/dojox/math.js
index 8bdd2dd..9d64cc2 100644
--- a/dojox/math.js
+++ b/dojox/math.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.math"]){
-dojo._hasResource["dojox.math"]=true;
 dojo.provide("dojox.math");
 dojo.require("dojox.math._base");
-}
diff --git a/dojox/math/BigInteger-ext.js b/dojox/math/BigInteger-ext.js
index 729c0d1..449352d 100644
--- a/dojox/math/BigInteger-ext.js
+++ b/dojox/math/BigInteger-ext.js
@@ -1,796 +1,658 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.math.BigInteger-ext"]){
-dojo._hasResource["dojox.math.BigInteger-ext"]=true;
 dojo.provide("dojox.math.BigInteger-ext");
 dojo.experimental("dojox.math.BigInteger-ext");
+
 dojo.require("dojox.math.BigInteger");
+
+// Contributed under CLA by Tom Wu
+
+// Extended JavaScript BN functions, required for RSA private ops.
+
 (function(){
-var _1=dojox.math.BigInteger,_2=_1._nbi,_3=_1._nbv,_4=_1._nbits,_5=_1._Montgomery;
-function _6(){
-var r=_2();
-this._copyTo(r);
-return r;
-};
-function _7(){
-if(this.s<0){
-if(this.t==1){
-return this[0]-this._DV;
-}else{
-if(this.t==0){
-return -1;
-}
-}
-}else{
-if(this.t==1){
-return this[0];
-}else{
-if(this.t==0){
-return 0;
-}
-}
-}
-return ((this[1]&((1<<(32-this._DB))-1))<<this._DB)|this[0];
-};
-function _8(){
-return (this.t==0)?this.s:(this[0]<<24)>>24;
-};
-function _9(){
-return (this.t==0)?this.s:(this[0]<<16)>>16;
-};
-function _a(r){
-return Math.floor(Math.LN2*this._DB/Math.log(r));
-};
-function _b(){
-if(this.s<0){
-return -1;
-}else{
-if(this.t<=0||(this.t==1&&this[0]<=0)){
-return 0;
-}else{
-return 1;
-}
-}
-};
-function _c(b){
-if(b==null){
-b=10;
-}
-if(this.signum()==0||b<2||b>36){
-return "0";
-}
-var cs=this._chunkSize(b);
-var a=Math.pow(b,cs);
-var d=_3(a),y=_2(),z=_2(),r="";
-this._divRemTo(d,y,z);
-while(y.signum()>0){
-r=(a+z.intValue()).toString(b).substr(1)+r;
-y._divRemTo(d,y,z);
-}
-return z.intValue().toString(b)+r;
-};
-function _d(s,b){
-this._fromInt(0);
-if(b==null){
-b=10;
-}
-var cs=this._chunkSize(b);
-var d=Math.pow(b,cs),mi=false,j=0,w=0;
-for(var i=0;i<s.length;++i){
-var x=intAt(s,i);
-if(x<0){
-if(s.charAt(i)=="-"&&this.signum()==0){
-mi=true;
-}
-continue;
-}
-w=b*w+x;
-if(++j>=cs){
-this._dMultiply(d);
-this._dAddOffset(w,0);
-j=0;
-w=0;
-}
-}
-if(j>0){
-this._dMultiply(Math.pow(b,j));
-this._dAddOffset(w,0);
-}
-if(mi){
-_1.ZERO._subTo(this,this);
-}
-};
-function _e(a,b,c){
-if("number"==typeof b){
-if(a<2){
-this._fromInt(1);
-}else{
-this._fromNumber(a,c);
-if(!this.testBit(a-1)){
-this._bitwiseTo(_1.ONE.shiftLeft(a-1),_f,this);
-}
-if(this._isEven()){
-this._dAddOffset(1,0);
-}
-while(!this.isProbablePrime(b)){
-this._dAddOffset(2,0);
-if(this.bitLength()>a){
-this._subTo(_1.ONE.shiftLeft(a-1),this);
-}
-}
-}
-}else{
-var x=[],t=a&7;
-x.length=(a>>3)+1;
-b.nextBytes(x);
-if(t>0){
-x[0]&=((1<<t)-1);
-}else{
-x[0]=0;
-}
-this._fromString(x,256);
-}
-};
-function _10(){
-var i=this.t,r=[];
-r[0]=this.s;
-var p=this._DB-(i*this._DB)%8,d,k=0;
-if(i-->0){
-if(p<this._DB&&(d=this[i]>>p)!=(this.s&this._DM)>>p){
-r[k++]=d|(this.s<<(this._DB-p));
-}
-while(i>=0){
-if(p<8){
-d=(this[i]&((1<<p)-1))<<(8-p);
-d|=this[--i]>>(p+=this._DB-8);
-}else{
-d=(this[i]>>(p-=8))&255;
-if(p<=0){
-p+=this._DB;
---i;
-}
-}
-if((d&128)!=0){
-d|=-256;
-}
-if(k==0&&(this.s&128)!=(d&128)){
-++k;
-}
-if(k>0||d!=this.s){
-r[k++]=d;
-}
-}
-}
-return r;
-};
-function _11(a){
-return (this.compareTo(a)==0);
-};
-function _12(a){
-return (this.compareTo(a)<0)?this:a;
-};
-function _13(a){
-return (this.compareTo(a)>0)?this:a;
-};
-function _14(a,op,r){
-var i,f,m=Math.min(a.t,this.t);
-for(i=0;i<m;++i){
-r[i]=op(this[i],a[i]);
-}
-if(a.t<this.t){
-f=a.s&this._DM;
-for(i=m;i<this.t;++i){
-r[i]=op(this[i],f);
-}
-r.t=this.t;
-}else{
-f=this.s&this._DM;
-for(i=m;i<a.t;++i){
-r[i]=op(f,a[i]);
-}
-r.t=a.t;
-}
-r.s=op(this.s,a.s);
-r._clamp();
-};
-function _15(x,y){
-return x&y;
-};
-function _16(a){
-var r=_2();
-this._bitwiseTo(a,_15,r);
-return r;
-};
-function _f(x,y){
-return x|y;
-};
-function _17(a){
-var r=_2();
-this._bitwiseTo(a,_f,r);
-return r;
-};
-function _18(x,y){
-return x^y;
-};
-function _19(a){
-var r=_2();
-this._bitwiseTo(a,_18,r);
-return r;
-};
-function _1a(x,y){
-return x&~y;
-};
-function _1b(a){
-var r=_2();
-this._bitwiseTo(a,_1a,r);
-return r;
-};
-function _1c(){
-var r=_2();
-for(var i=0;i<this.t;++i){
-r[i]=this._DM&~this[i];
-}
-r.t=this.t;
-r.s=~this.s;
-return r;
-};
-function _1d(n){
-var r=_2();
-if(n<0){
-this._rShiftTo(-n,r);
-}else{
-this._lShiftTo(n,r);
-}
-return r;
-};
-function _1e(n){
-var r=_2();
-if(n<0){
-this._lShiftTo(-n,r);
-}else{
-this._rShiftTo(n,r);
-}
-return r;
-};
-function _1f(x){
-if(x==0){
-return -1;
-}
-var r=0;
-if((x&65535)==0){
-x>>=16;
-r+=16;
-}
-if((x&255)==0){
-x>>=8;
-r+=8;
-}
-if((x&15)==0){
-x>>=4;
-r+=4;
-}
-if((x&3)==0){
-x>>=2;
-r+=2;
-}
-if((x&1)==0){
-++r;
-}
-return r;
-};
-function _20(){
-for(var i=0;i<this.t;++i){
-if(this[i]!=0){
-return i*this._DB+_1f(this[i]);
-}
-}
-if(this.s<0){
-return this.t*this._DB;
-}
-return -1;
-};
-function _21(x){
-var r=0;
-while(x!=0){
-x&=x-1;
-++r;
-}
-return r;
-};
-function _22(){
-var r=0,x=this.s&this._DM;
-for(var i=0;i<this.t;++i){
-r+=_21(this[i]^x);
-}
-return r;
-};
-function _23(n){
-var j=Math.floor(n/this._DB);
-if(j>=this.t){
-return (this.s!=0);
-}
-return ((this[j]&(1<<(n%this._DB)))!=0);
-};
-function _24(n,op){
-var r=_1.ONE.shiftLeft(n);
-this._bitwiseTo(r,op,r);
-return r;
-};
-function _25(n){
-return this._changeBit(n,_f);
-};
-function _26(n){
-return this._changeBit(n,_1a);
-};
-function _27(n){
-return this._changeBit(n,_18);
-};
-function _28(a,r){
-var i=0,c=0,m=Math.min(a.t,this.t);
-while(i<m){
-c+=this[i]+a[i];
-r[i++]=c&this._DM;
-c>>=this._DB;
-}
-if(a.t<this.t){
-c+=a.s;
-while(i<this.t){
-c+=this[i];
-r[i++]=c&this._DM;
-c>>=this._DB;
-}
-c+=this.s;
-}else{
-c+=this.s;
-while(i<a.t){
-c+=a[i];
-r[i++]=c&this._DM;
-c>>=this._DB;
-}
-c+=a.s;
-}
-r.s=(c<0)?-1:0;
-if(c>0){
-r[i++]=c;
-}else{
-if(c<-1){
-r[i++]=this._DV+c;
-}
-}
-r.t=i;
-r._clamp();
-};
-function _29(a){
-var r=_2();
-this._addTo(a,r);
-return r;
-};
-function _2a(a){
-var r=_2();
-this._subTo(a,r);
-return r;
-};
-function _2b(a){
-var r=_2();
-this._multiplyTo(a,r);
-return r;
-};
-function _2c(a){
-var r=_2();
-this._divRemTo(a,r,null);
-return r;
-};
-function _2d(a){
-var r=_2();
-this._divRemTo(a,null,r);
-return r;
-};
-function _2e(a){
-var q=_2(),r=_2();
-this._divRemTo(a,q,r);
-return [q,r];
-};
-function _2f(n){
-this[this.t]=this.am(0,n-1,this,0,0,this.t);
-++this.t;
-this._clamp();
-};
-function _30(n,w){
-while(this.t<=w){
-this[this.t++]=0;
-}
-this[w]+=n;
-while(this[w]>=this._DV){
-this[w]-=this._DV;
-if(++w>=this.t){
-this[this.t++]=0;
-}
-++this[w];
-}
-};
-function _31(){
-};
-function _32(x){
-return x;
-};
-function _33(x,y,r){
-x._multiplyTo(y,r);
-};
-function _34(x,r){
-x._squareTo(r);
-};
-_31.prototype.convert=_32;
-_31.prototype.revert=_32;
-_31.prototype.mulTo=_33;
-_31.prototype.sqrTo=_34;
-function _35(e){
-return this._exp(e,new _31());
-};
-function _36(a,n,r){
-var i=Math.min(this.t+a.t,n);
-r.s=0;
-r.t=i;
-while(i>0){
-r[--i]=0;
-}
-var j;
-for(j=r.t-this.t;i<j;++i){
-r[i+this.t]=this.am(0,a[i],r,i,0,this.t);
-}
-for(j=Math.min(a.t,n);i<j;++i){
-this.am(0,a[i],r,i,0,n-i);
-}
-r._clamp();
-};
-function _37(a,n,r){
---n;
-var i=r.t=this.t+a.t-n;
-r.s=0;
-while(--i>=0){
-r[i]=0;
-}
-for(i=Math.max(n-this.t,0);i<a.t;++i){
-r[this.t+i-n]=this.am(n-i,a[i],r,0,0,this.t+i-n);
-}
-r._clamp();
-r._drShiftTo(1,r);
-};
-function _38(m){
-this.r2=_2();
-this.q3=_2();
-_1.ONE._dlShiftTo(2*m.t,this.r2);
-this.mu=this.r2.divide(m);
-this.m=m;
-};
-function _39(x){
-if(x.s<0||x.t>2*this.m.t){
-return x.mod(this.m);
-}else{
-if(x.compareTo(this.m)<0){
-return x;
-}else{
-var r=_2();
-x._copyTo(r);
-this.reduce(r);
-return r;
-}
-}
-};
-function _3a(x){
-return x;
-};
-function _3b(x){
-x._drShiftTo(this.m.t-1,this.r2);
-if(x.t>this.m.t+1){
-x.t=this.m.t+1;
-x._clamp();
-}
-this.mu._multiplyUpperTo(this.r2,this.m.t+1,this.q3);
-this.m._multiplyLowerTo(this.q3,this.m.t+1,this.r2);
-while(x.compareTo(this.r2)<0){
-x._dAddOffset(1,this.m.t+1);
-}
-x._subTo(this.r2,x);
-while(x.compareTo(this.m)>=0){
-x._subTo(this.m,x);
-}
-};
-function _3c(x,r){
-x._squareTo(r);
-this.reduce(r);
-};
-function _3d(x,y,r){
-x._multiplyTo(y,r);
-this.reduce(r);
-};
-_38.prototype.convert=_39;
-_38.prototype.revert=_3a;
-_38.prototype.reduce=_3b;
-_38.prototype.mulTo=_3d;
-_38.prototype.sqrTo=_3c;
-function _3e(e,m){
-var i=e.bitLength(),k,r=_3(1),z;
-if(i<=0){
-return r;
-}else{
-if(i<18){
-k=1;
-}else{
-if(i<48){
-k=3;
-}else{
-if(i<144){
-k=4;
-}else{
-if(i<768){
-k=5;
-}else{
-k=6;
-}
-}
-}
-}
-}
-if(i<8){
-z=new Classic(m);
-}else{
-if(m._isEven()){
-z=new _38(m);
-}else{
-z=new _5(m);
-}
-}
-var g=[],n=3,k1=k-1,km=(1<<k)-1;
-g[1]=z.convert(this);
-if(k>1){
-var g2=_2();
-z.sqrTo(g[1],g2);
-while(n<=km){
-g[n]=_2();
-z.mulTo(g2,g[n-2],g[n]);
-n+=2;
-}
-}
-var j=e.t-1,w,is1=true,r2=_2(),t;
-i=_4(e[j])-1;
-while(j>=0){
-if(i>=k1){
-w=(e[j]>>(i-k1))&km;
-}else{
-w=(e[j]&((1<<(i+1))-1))<<(k1-i);
-if(j>0){
-w|=e[j-1]>>(this._DB+i-k1);
-}
-}
-n=k;
-while((w&1)==0){
-w>>=1;
---n;
-}
-if((i-=n)<0){
-i+=this._DB;
---j;
-}
-if(is1){
-g[w]._copyTo(r);
-is1=false;
-}else{
-while(n>1){
-z.sqrTo(r,r2);
-z.sqrTo(r2,r);
-n-=2;
-}
-if(n>0){
-z.sqrTo(r,r2);
-}else{
-t=r;
-r=r2;
-r2=t;
-}
-z.mulTo(r2,g[w],r);
-}
-while(j>=0&&(e[j]&(1<<i))==0){
-z.sqrTo(r,r2);
-t=r;
-r=r2;
-r2=t;
-if(--i<0){
-i=this._DB-1;
---j;
-}
-}
-}
-return z.revert(r);
-};
-function _3f(a){
-var x=(this.s<0)?this.negate():this.clone();
-var y=(a.s<0)?a.negate():a.clone();
-if(x.compareTo(y)<0){
-var t=x;
-x=y;
-y=t;
-}
-var i=x.getLowestSetBit(),g=y.getLowestSetBit();
-if(g<0){
-return x;
-}
-if(i<g){
-g=i;
-}
-if(g>0){
-x._rShiftTo(g,x);
-y._rShiftTo(g,y);
-}
-while(x.signum()>0){
-if((i=x.getLowestSetBit())>0){
-x._rShiftTo(i,x);
-}
-if((i=y.getLowestSetBit())>0){
-y._rShiftTo(i,y);
-}
-if(x.compareTo(y)>=0){
-x._subTo(y,x);
-x._rShiftTo(1,x);
-}else{
-y._subTo(x,y);
-y._rShiftTo(1,y);
-}
-}
-if(g>0){
-y._lShiftTo(g,y);
-}
-return y;
-};
-function _40(n){
-if(n<=0){
-return 0;
-}
-var d=this._DV%n,r=(this.s<0)?n-1:0;
-if(this.t>0){
-if(d==0){
-r=this[0]%n;
-}else{
-for(var i=this.t-1;i>=0;--i){
-r=(d*r+this[i])%n;
-}
-}
-}
-return r;
-};
-function _41(m){
-var ac=m._isEven();
-if((this._isEven()&&ac)||m.signum()==0){
-return _1.ZERO;
-}
-var u=m.clone(),v=this.clone();
-var a=_3(1),b=_3(0),c=_3(0),d=_3(1);
-while(u.signum()!=0){
-while(u._isEven()){
-u._rShiftTo(1,u);
-if(ac){
-if(!a._isEven()||!b._isEven()){
-a._addTo(this,a);
-b._subTo(m,b);
-}
-a._rShiftTo(1,a);
-}else{
-if(!b._isEven()){
-b._subTo(m,b);
-}
-}
-b._rShiftTo(1,b);
-}
-while(v._isEven()){
-v._rShiftTo(1,v);
-if(ac){
-if(!c._isEven()||!d._isEven()){
-c._addTo(this,c);
-d._subTo(m,d);
-}
-c._rShiftTo(1,c);
-}else{
-if(!d._isEven()){
-d._subTo(m,d);
-}
-}
-d._rShiftTo(1,d);
-}
-if(u.compareTo(v)>=0){
-u._subTo(v,u);
-if(ac){
-a._subTo(c,a);
-}
-b._subTo(d,b);
-}else{
-v._subTo(u,v);
-if(ac){
-c._subTo(a,c);
-}
-d._subTo(b,d);
-}
-}
-if(v.compareTo(_1.ONE)!=0){
-return _1.ZERO;
-}
-if(d.compareTo(m)>=0){
-return d.subtract(m);
-}
-if(d.signum()<0){
-d._addTo(m,d);
-}else{
-return d;
-}
-if(d.signum()<0){
-return d.add(m);
-}else{
-return d;
-}
-};
-var _42=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509];
-var _43=(1<<26)/_42[_42.length-1];
-function _44(t){
-var i,x=this.abs();
-if(x.t==1&&x[0]<=_42[_42.length-1]){
-for(i=0;i<_42.length;++i){
-if(x[0]==_42[i]){
-return true;
-}
-}
-return false;
-}
-if(x._isEven()){
-return false;
-}
-i=1;
-while(i<_42.length){
-var m=_42[i],j=i+1;
-while(j<_42.length&&m<_43){
-m*=_42[j++];
-}
-m=x._modInt(m);
-while(i<j){
-if(m%_42[i++]==0){
-return false;
-}
-}
-}
-return x._millerRabin(t);
-};
-function _45(t){
-var n1=this.subtract(_1.ONE);
-var k=n1.getLowestSetBit();
-if(k<=0){
-return false;
-}
-var r=n1.shiftRight(k);
-t=(t+1)>>1;
-if(t>_42.length){
-t=_42.length;
-}
-var a=_2();
-for(var i=0;i<t;++i){
-a._fromInt(_42[i]);
-var y=a.modPow(r,this);
-if(y.compareTo(_1.ONE)!=0&&y.compareTo(n1)!=0){
-var j=1;
-while(j++<k&&y.compareTo(n1)!=0){
-y=y.modPowInt(2,this);
-if(y.compareTo(_1.ONE)==0){
-return false;
-}
-}
-if(y.compareTo(n1)!=0){
-return false;
-}
-}
-}
-return true;
-};
-dojo.extend(_1,{_chunkSize:_a,_toRadix:_c,_fromRadix:_d,_fromNumber:_e,_bitwiseTo:_14,_changeBit:_24,_addTo:_28,_dMultiply:_2f,_dAddOffset:_30,_multiplyLowerTo:_36,_multiplyUpperTo:_37,_modInt:_40,_millerRabin:_45,clone:_6,intValue:_7,byteValue:_8,shortValue:_9,signum:_b,toByteArray:_10,equals:_11,min:_12,max:_13,and:_16,or:_17,xor:_19,andNot:_1b,not:_1c,shiftLeft:_1d,shiftRight:_1e,getLowestSetBit:_20,bitCount:_22,testBit:_23,setBit:_25,clearBit:_26,flipBit:_27,add:_29,subtract:_2a,mult [...]
+	var BigInteger = dojox.math.BigInteger,
+		nbi = BigInteger._nbi, nbv = BigInteger._nbv,
+		nbits = BigInteger._nbits,
+		Montgomery = BigInteger._Montgomery;
+	
+	// (public)
+	function bnClone() { var r = nbi(); this._copyTo(r); return r; }
+
+	// (public) return value as integer
+	function bnIntValue() {
+	  if(this.s < 0) {
+		if(this.t == 1) return this[0]-this._DV;
+		else if(this.t == 0) return -1;
+	  }
+	  else if(this.t == 1) return this[0];
+	  else if(this.t == 0) return 0;
+	  // assumes 16 < DB < 32
+	  return ((this[1]&((1<<(32-this._DB))-1))<<this._DB)|this[0];
+	}
+
+	// (public) return value as byte
+	function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
+
+	// (public) return value as short (assumes DB>=16)
+	function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
+
+	// (protected) return x s.t. r^x < DV
+	function bnpChunkSize(r) { return Math.floor(Math.LN2*this._DB/Math.log(r)); }
+
+	// (public) 0 if this == 0, 1 if this > 0
+	function bnSigNum() {
+	  if(this.s < 0) return -1;
+	  else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
+	  else return 1;
+	}
+
+	// (protected) convert to radix string
+	function bnpToRadix(b) {
+	  if(b == null) b = 10;
+	  if(this.signum() == 0 || b < 2 || b > 36) return "0";
+	  var cs = this._chunkSize(b);
+	  var a = Math.pow(b,cs);
+	  var d = nbv(a), y = nbi(), z = nbi(), r = "";
+	  this._divRemTo(d,y,z);
+	  while(y.signum() > 0) {
+		r = (a+z.intValue()).toString(b).substr(1) + r;
+		y._divRemTo(d,y,z);
+	  }
+	  return z.intValue().toString(b) + r;
+	}
+
+	// (protected) convert from radix string
+	function bnpFromRadix(s,b) {
+	  this._fromInt(0);
+	  if(b == null) b = 10;
+	  var cs = this._chunkSize(b);
+	  var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
+	  for(var i = 0; i < s.length; ++i) {
+		var x = intAt(s,i);
+		if(x < 0) {
+		  if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
+		  continue;
+		}
+		w = b*w+x;
+		if(++j >= cs) {
+		  this._dMultiply(d);
+		  this._dAddOffset(w,0);
+		  j = 0;
+		  w = 0;
+		}
+	  }
+	  if(j > 0) {
+		this._dMultiply(Math.pow(b,j));
+		this._dAddOffset(w,0);
+	  }
+	  if(mi) BigInteger.ZERO._subTo(this,this);
+	}
+
+	// (protected) alternate constructor
+	function bnpFromNumber(a,b,c) {
+	  if("number" == typeof b) {
+		// new BigInteger(int,int,RNG)
+		if(a < 2) this._fromInt(1);
+		else {
+		  this._fromNumber(a,c);
+		  if(!this.testBit(a-1))	// force MSB set
+			this._bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
+		  if(this._isEven()) this._dAddOffset(1,0); // force odd
+		  while(!this.isProbablePrime(b)) {
+			this._dAddOffset(2,0);
+			if(this.bitLength() > a) this._subTo(BigInteger.ONE.shiftLeft(a-1),this);
+		  }
+		}
+	  }
+	  else {
+		// new BigInteger(int,RNG)
+		var x = [], t = a&7;
+		x.length = (a>>3)+1;
+		b.nextBytes(x);
+		if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
+		this._fromString(x,256);
+	  }
+	}
+
+	// (public) convert to bigendian byte array
+	function bnToByteArray() {
+	  var i = this.t, r = [];
+	  r[0] = this.s;
+	  var p = this._DB-(i*this._DB)%8, d, k = 0;
+	  if(i-- > 0) {
+		if(p < this._DB && (d = this[i]>>p) != (this.s&this._DM)>>p)
+		  r[k++] = d|(this.s<<(this._DB-p));
+		while(i >= 0) {
+		  if(p < 8) {
+			d = (this[i]&((1<<p)-1))<<(8-p);
+			d |= this[--i]>>(p+=this._DB-8);
+		  }
+		  else {
+			d = (this[i]>>(p-=8))&0xff;
+			if(p <= 0) { p += this._DB; --i; }
+		  }
+		  if((d&0x80) != 0) d |= -256;
+		  if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
+		  if(k > 0 || d != this.s) r[k++] = d;
+		}
+	  }
+	  return r;
+	}
+
+	function bnEquals(a) { return(this.compareTo(a)==0); }
+	function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
+	function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
+
+	// (protected) r = this op a (bitwise)
+	function bnpBitwiseTo(a,op,r) {
+	  var i, f, m = Math.min(a.t,this.t);
+	  for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
+	  if(a.t < this.t) {
+		f = a.s&this._DM;
+		for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
+		r.t = this.t;
+	  }
+	  else {
+		f = this.s&this._DM;
+		for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
+		r.t = a.t;
+	  }
+	  r.s = op(this.s,a.s);
+	  r._clamp();
+	}
+
+	// (public) this & a
+	function op_and(x,y) { return x&y; }
+	function bnAnd(a) { var r = nbi(); this._bitwiseTo(a,op_and,r); return r; }
+
+	// (public) this | a
+	function op_or(x,y) { return x|y; }
+	function bnOr(a) { var r = nbi(); this._bitwiseTo(a,op_or,r); return r; }
+
+	// (public) this ^ a
+	function op_xor(x,y) { return x^y; }
+	function bnXor(a) { var r = nbi(); this._bitwiseTo(a,op_xor,r); return r; }
+
+	// (public) this & ~a
+	function op_andnot(x,y) { return x&~y; }
+	function bnAndNot(a) { var r = nbi(); this._bitwiseTo(a,op_andnot,r); return r; }
+
+	// (public) ~this
+	function bnNot() {
+	  var r = nbi();
+	  for(var i = 0; i < this.t; ++i) r[i] = this._DM&~this[i];
+	  r.t = this.t;
+	  r.s = ~this.s;
+	  return r;
+	}
+
+	// (public) this << n
+	function bnShiftLeft(n) {
+	  var r = nbi();
+	  if(n < 0) this._rShiftTo(-n,r); else this._lShiftTo(n,r);
+	  return r;
+	}
+
+	// (public) this >> n
+	function bnShiftRight(n) {
+	  var r = nbi();
+	  if(n < 0) this._lShiftTo(-n,r); else this._rShiftTo(n,r);
+	  return r;
+	}
+
+	// return index of lowest 1-bit in x, x < 2^31
+	function lbit(x) {
+	  if(x == 0) return -1;
+	  var r = 0;
+	  if((x&0xffff) == 0) { x >>= 16; r += 16; }
+	  if((x&0xff) == 0) { x >>= 8; r += 8; }
+	  if((x&0xf) == 0) { x >>= 4; r += 4; }
+	  if((x&3) == 0) { x >>= 2; r += 2; }
+	  if((x&1) == 0) ++r;
+	  return r;
+	}
+
+	// (public) returns index of lowest 1-bit (or -1 if none)
+	function bnGetLowestSetBit() {
+	  for(var i = 0; i < this.t; ++i)
+		if(this[i] != 0) return i*this._DB+lbit(this[i]);
+	  if(this.s < 0) return this.t*this._DB;
+	  return -1;
+	}
+
+	// return number of 1 bits in x
+	function cbit(x) {
+	  var r = 0;
+	  while(x != 0) { x &= x-1; ++r; }
+	  return r;
+	}
+
+	// (public) return number of set bits
+	function bnBitCount() {
+	  var r = 0, x = this.s&this._DM;
+	  for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
+	  return r;
+	}
+
+	// (public) true iff nth bit is set
+	function bnTestBit(n) {
+	  var j = Math.floor(n/this._DB);
+	  if(j >= this.t) return(this.s!=0);
+	  return((this[j]&(1<<(n%this._DB)))!=0);
+	}
+
+	// (protected) this op (1<<n)
+	function bnpChangeBit(n,op) {
+	  var r = BigInteger.ONE.shiftLeft(n);
+	  this._bitwiseTo(r,op,r);
+	  return r;
+	}
+
+	// (public) this | (1<<n)
+	function bnSetBit(n) { return this._changeBit(n,op_or); }
+
+	// (public) this & ~(1<<n)
+	function bnClearBit(n) { return this._changeBit(n,op_andnot); }
+
+	// (public) this ^ (1<<n)
+	function bnFlipBit(n) { return this._changeBit(n,op_xor); }
+
+	// (protected) r = this + a
+	function bnpAddTo(a,r) {
+	  var i = 0, c = 0, m = Math.min(a.t,this.t);
+	  while(i < m) {
+		c += this[i]+a[i];
+		r[i++] = c&this._DM;
+		c >>= this._DB;
+	  }
+	  if(a.t < this.t) {
+		c += a.s;
+		while(i < this.t) {
+		  c += this[i];
+		  r[i++] = c&this._DM;
+		  c >>= this._DB;
+		}
+		c += this.s;
+	  }
+	  else {
+		c += this.s;
+		while(i < a.t) {
+		  c += a[i];
+		  r[i++] = c&this._DM;
+		  c >>= this._DB;
+		}
+		c += a.s;
+	  }
+	  r.s = (c<0)?-1:0;
+	  if(c > 0) r[i++] = c;
+	  else if(c < -1) r[i++] = this._DV+c;
+	  r.t = i;
+	  r._clamp();
+	}
+
+	// (public) this + a
+	function bnAdd(a) { var r = nbi(); this._addTo(a,r); return r; }
+
+	// (public) this - a
+	function bnSubtract(a) { var r = nbi(); this._subTo(a,r); return r; }
+
+	// (public) this * a
+	function bnMultiply(a) { var r = nbi(); this._multiplyTo(a,r); return r; }
+
+	// (public) this / a
+	function bnDivide(a) { var r = nbi(); this._divRemTo(a,r,null); return r; }
+
+	// (public) this % a
+	function bnRemainder(a) { var r = nbi(); this._divRemTo(a,null,r); return r; }
+
+	// (public) [this/a,this%a]
+	function bnDivideAndRemainder(a) {
+	  var q = nbi(), r = nbi();
+	  this._divRemTo(a,q,r);
+	  return [q, r];
+	}
+
+	// (protected) this *= n, this >= 0, 1 < n < DV
+	function bnpDMultiply(n) {
+	  this[this.t] = this.am(0,n-1,this,0,0,this.t);
+	  ++this.t;
+	  this._clamp();
+	}
+
+	// (protected) this += n << w words, this >= 0
+	function bnpDAddOffset(n,w) {
+	  while(this.t <= w) this[this.t++] = 0;
+	  this[w] += n;
+	  while(this[w] >= this._DV) {
+		this[w] -= this._DV;
+		if(++w >= this.t) this[this.t++] = 0;
+		++this[w];
+	  }
+	}
+
+	// A "null" reducer
+	function NullExp() {}
+	function nNop(x) { return x; }
+	function nMulTo(x,y,r) { x._multiplyTo(y,r); }
+	function nSqrTo(x,r) { x._squareTo(r); }
+
+	NullExp.prototype.convert = nNop;
+	NullExp.prototype.revert = nNop;
+	NullExp.prototype.mulTo = nMulTo;
+	NullExp.prototype.sqrTo = nSqrTo;
+
+	// (public) this^e
+	function bnPow(e) { return this._exp(e,new NullExp()); }
+
+	// (protected) r = lower n words of "this * a", a.t <= n
+	// "this" should be the larger one if appropriate.
+	function bnpMultiplyLowerTo(a,n,r) {
+	  var i = Math.min(this.t+a.t,n);
+	  r.s = 0; // assumes a,this >= 0
+	  r.t = i;
+	  while(i > 0) r[--i] = 0;
+	  var j;
+	  for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
+	  for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
+	  r._clamp();
+	}
+
+	// (protected) r = "this * a" without lower n words, n > 0
+	// "this" should be the larger one if appropriate.
+	function bnpMultiplyUpperTo(a,n,r) {
+	  --n;
+	  var i = r.t = this.t+a.t-n;
+	  r.s = 0; // assumes a,this >= 0
+	  while(--i >= 0) r[i] = 0;
+	  for(i = Math.max(n-this.t,0); i < a.t; ++i)
+		r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
+	  r._clamp();
+	  r._drShiftTo(1,r);
+	}
+
+	// Barrett modular reduction
+	function Barrett(m) {
+	  // setup Barrett
+	  this.r2 = nbi();
+	  this.q3 = nbi();
+	  BigInteger.ONE._dlShiftTo(2*m.t,this.r2);
+	  this.mu = this.r2.divide(m);
+	  this.m = m;
+	}
+
+	function barrettConvert(x) {
+	  if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
+	  else if(x.compareTo(this.m) < 0) return x;
+	  else { var r = nbi(); x._copyTo(r); this.reduce(r); return r; }
+	}
+
+	function barrettRevert(x) { return x; }
+
+	// x = x mod m (HAC 14.42)
+	function barrettReduce(x) {
+	  x._drShiftTo(this.m.t-1,this.r2);
+	  if(x.t > this.m.t+1) { x.t = this.m.t+1; x._clamp(); }
+	  this.mu._multiplyUpperTo(this.r2,this.m.t+1,this.q3);
+	  this.m._multiplyLowerTo(this.q3,this.m.t+1,this.r2);
+	  while(x.compareTo(this.r2) < 0) x._dAddOffset(1,this.m.t+1);
+	  x._subTo(this.r2,x);
+	  while(x.compareTo(this.m) >= 0) x._subTo(this.m,x);
+	}
+
+	// r = x^2 mod m; x != r
+	function barrettSqrTo(x,r) { x._squareTo(r); this.reduce(r); }
+
+	// r = x*y mod m; x,y != r
+	function barrettMulTo(x,y,r) { x._multiplyTo(y,r); this.reduce(r); }
+
+	Barrett.prototype.convert = barrettConvert;
+	Barrett.prototype.revert = barrettRevert;
+	Barrett.prototype.reduce = barrettReduce;
+	Barrett.prototype.mulTo = barrettMulTo;
+	Barrett.prototype.sqrTo = barrettSqrTo;
+
+	// (public) this^e % m (HAC 14.85)
+	function bnModPow(e,m) {
+	  var i = e.bitLength(), k, r = nbv(1), z;
+	  if(i <= 0) return r;
+	  else if(i < 18) k = 1;
+	  else if(i < 48) k = 3;
+	  else if(i < 144) k = 4;
+	  else if(i < 768) k = 5;
+	  else k = 6;
+	  if(i < 8)
+		z = new Classic(m);
+	  else if(m._isEven())
+		z = new Barrett(m);
+	  else
+		z = new Montgomery(m);
+
+	  // precomputation
+	  var g = [], n = 3, k1 = k-1, km = (1<<k)-1;
+	  g[1] = z.convert(this);
+	  if(k > 1) {
+		var g2 = nbi();
+		z.sqrTo(g[1],g2);
+		while(n <= km) {
+		  g[n] = nbi();
+		  z.mulTo(g2,g[n-2],g[n]);
+		  n += 2;
+		}
+	  }
+
+	  var j = e.t-1, w, is1 = true, r2 = nbi(), t;
+	  i = nbits(e[j])-1;
+	  while(j >= 0) {
+		if(i >= k1) w = (e[j]>>(i-k1))&km;
+		else {
+		  w = (e[j]&((1<<(i+1))-1))<<(k1-i);
+		  if(j > 0) w |= e[j-1]>>(this._DB+i-k1);
+		}
+
+		n = k;
+		while((w&1) == 0) { w >>= 1; --n; }
+		if((i -= n) < 0) { i += this._DB; --j; }
+		if(is1) {	// ret == 1, don't bother squaring or multiplying it
+		  g[w]._copyTo(r);
+		  is1 = false;
+		}
+		else {
+		  while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
+		  if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
+		  z.mulTo(r2,g[w],r);
+		}
+
+		while(j >= 0 && (e[j]&(1<<i)) == 0) {
+		  z.sqrTo(r,r2); t = r; r = r2; r2 = t;
+		  if(--i < 0) { i = this._DB-1; --j; }
+		}
+	  }
+	  return z.revert(r);
+	}
+
+	// (public) gcd(this,a) (HAC 14.54)
+	function bnGCD(a) {
+	  var x = (this.s<0)?this.negate():this.clone();
+	  var y = (a.s<0)?a.negate():a.clone();
+	  if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
+	  var i = x.getLowestSetBit(), g = y.getLowestSetBit();
+	  if(g < 0) return x;
+	  if(i < g) g = i;
+	  if(g > 0) {
+		x._rShiftTo(g,x);
+		y._rShiftTo(g,y);
+	  }
+	  while(x.signum() > 0) {
+		if((i = x.getLowestSetBit()) > 0) x._rShiftTo(i,x);
+		if((i = y.getLowestSetBit()) > 0) y._rShiftTo(i,y);
+		if(x.compareTo(y) >= 0) {
+		  x._subTo(y,x);
+		  x._rShiftTo(1,x);
+		}
+		else {
+		  y._subTo(x,y);
+		  y._rShiftTo(1,y);
+		}
+	  }
+	  if(g > 0) y._lShiftTo(g,y);
+	  return y;
+	}
+
+	// (protected) this % n, n < 2^26
+	function bnpModInt(n) {
+	  if(n <= 0) return 0;
+	  var d = this._DV%n, r = (this.s<0)?n-1:0;
+	  if(this.t > 0)
+		if(d == 0) r = this[0]%n;
+		else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
+	  return r;
+	}
+
+	// (public) 1/this % m (HAC 14.61)
+	function bnModInverse(m) {
+	  var ac = m._isEven();
+	  if((this._isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
+	  var u = m.clone(), v = this.clone();
+	  var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
+	  while(u.signum() != 0) {
+		while(u._isEven()) {
+		  u._rShiftTo(1,u);
+		  if(ac) {
+			if(!a._isEven() || !b._isEven()) { a._addTo(this,a); b._subTo(m,b); }
+			a._rShiftTo(1,a);
+		  }
+		  else if(!b._isEven()) b._subTo(m,b);
+		  b._rShiftTo(1,b);
+		}
+		while(v._isEven()) {
+		  v._rShiftTo(1,v);
+		  if(ac) {
+			if(!c._isEven() || !d._isEven()) { c._addTo(this,c); d._subTo(m,d); }
+			c._rShiftTo(1,c);
+		  }
+		  else if(!d._isEven()) d._subTo(m,d);
+		  d._rShiftTo(1,d);
+		}
+		if(u.compareTo(v) >= 0) {
+		  u._subTo(v,u);
+		  if(ac) a._subTo(c,a);
+		  b._subTo(d,b);
+		}
+		else {
+		  v._subTo(u,v);
+		  if(ac) c._subTo(a,c);
+		  d._subTo(b,d);
+		}
+	  }
+	  if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
+	  if(d.compareTo(m) >= 0) return d.subtract(m);
+	  if(d.signum() < 0) d._addTo(m,d); else return d;
+	  if(d.signum() < 0) return d.add(m); else return d;
+	}
+
+	var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509];
+	var lplim = (1<<26)/lowprimes[lowprimes.length-1];
+
+	// (public) test primality with certainty >= 1-.5^t
+	function bnIsProbablePrime(t) {
+	  var i, x = this.abs();
+	  if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
+		for(i = 0; i < lowprimes.length; ++i)
+		  if(x[0] == lowprimes[i]) return true;
+		return false;
+	  }
+	  if(x._isEven()) return false;
+	  i = 1;
+	  while(i < lowprimes.length) {
+		var m = lowprimes[i], j = i+1;
+		while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
+		m = x._modInt(m);
+		while(i < j) if(m%lowprimes[i++] == 0) return false;
+	  }
+	  return x._millerRabin(t);
+	}
+
+	// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
+	function bnpMillerRabin(t) {
+	  var n1 = this.subtract(BigInteger.ONE);
+	  var k = n1.getLowestSetBit();
+	  if(k <= 0) return false;
+	  var r = n1.shiftRight(k);
+	  t = (t+1)>>1;
+	  if(t > lowprimes.length) t = lowprimes.length;
+	  var a = nbi();
+	  for(var i = 0; i < t; ++i) {
+		a._fromInt(lowprimes[i]);
+		var y = a.modPow(r,this);
+		if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
+		  var j = 1;
+		  while(j++ < k && y.compareTo(n1) != 0) {
+			y = y.modPowInt(2,this);
+			if(y.compareTo(BigInteger.ONE) == 0) return false;
+		  }
+		  if(y.compareTo(n1) != 0) return false;
+		}
+	  }
+	  return true;
+	}
+
+	dojo.extend(BigInteger, {
+		// protected
+		_chunkSize:			bnpChunkSize,
+		_toRadix:			bnpToRadix,
+		_fromRadix:			bnpFromRadix,
+		_fromNumber:		bnpFromNumber,
+		_bitwiseTo:			bnpBitwiseTo,
+		_changeBit:			bnpChangeBit,
+		_addTo:				bnpAddTo,
+		_dMultiply:			bnpDMultiply,
+		_dAddOffset:		bnpDAddOffset,
+		_multiplyLowerTo:	bnpMultiplyLowerTo,
+		_multiplyUpperTo:	bnpMultiplyUpperTo,
+		_modInt:			bnpModInt,
+		_millerRabin:		bnpMillerRabin,
+
+		// public
+		clone:				bnClone,
+		intValue:			bnIntValue,
+		byteValue:			bnByteValue,
+		shortValue:			bnShortValue,
+		signum:				bnSigNum,
+		toByteArray:		bnToByteArray,
+		equals:				bnEquals,
+		min:				bnMin,
+		max:				bnMax,
+		and:				bnAnd,
+		or:					bnOr,
+		xor:				bnXor,
+		andNot:				bnAndNot,
+		not:				bnNot,
+		shiftLeft:			bnShiftLeft,
+		shiftRight:			bnShiftRight,
+		getLowestSetBit:	bnGetLowestSetBit,
+		bitCount:			bnBitCount,
+		testBit:			bnTestBit,
+		setBit:				bnSetBit,
+		clearBit:			bnClearBit,
+		flipBit:			bnFlipBit,
+		add:				bnAdd,
+		subtract:			bnSubtract,
+		multiply:			bnMultiply,
+		divide:				bnDivide,
+		remainder:			bnRemainder,
+		divideAndRemainder:	bnDivideAndRemainder,
+		modPow:				bnModPow,
+		modInverse:			bnModInverse,
+		pow:				bnPow,
+		gcd:				bnGCD,
+		isProbablePrime:	bnIsProbablePrime
+	});
+
+	// BigInteger interfaces not implemented in jsbn:
+
+	// BigInteger(int signum, byte[] magnitude)
+	// double doubleValue()
+	// float floatValue()
+	// int hashCode()
+	// long longValue()
+	// static BigInteger valueOf(long val)
+
 })();
-}
diff --git a/dojox/math/BigInteger.js b/dojox/math/BigInteger.js
index 824ba80..5067c65 100644
--- a/dojox/math/BigInteger.js
+++ b/dojox/math/BigInteger.js
@@ -1,635 +1,586 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.math.BigInteger"]){
-dojo._hasResource["dojox.math.BigInteger"]=true;
 dojo.provide("dojox.math.BigInteger");
 dojo.experimental("dojox.math.BigInteger");
+
+// Contributed under CLA by Tom Wu <tjw at cs.Stanford.EDU>
+// See http://www-cs-students.stanford.edu/~tjw/jsbn/ for details.
+
+// Basic JavaScript BN library - subset useful for RSA encryption.
+// The API for dojox.math.BigInteger closely resembles that of the java.math.BigInteger class in Java.
+
 (function(){
-var _1;
-var _2=244837814094590;
-var _3=((_2&16777215)==15715070);
-function _4(a,b,c){
-if(a!=null){
-if("number"==typeof a){
-this._fromNumber(a,b,c);
-}else{
-if(!b&&"string"!=typeof a){
-this._fromString(a,256);
-}else{
-this._fromString(a,b);
-}
-}
-}
-};
-function _5(){
-return new _4(null);
-};
-function _6(i,x,w,j,c,n){
-while(--n>=0){
-var v=x*this[i++]+w[j]+c;
-c=Math.floor(v/67108864);
-w[j++]=v&67108863;
-}
-return c;
-};
-function _7(i,x,w,j,c,n){
-var xl=x&32767,xh=x>>15;
-while(--n>=0){
-var l=this[i]&32767;
-var h=this[i++]>>15;
-var m=xh*l+h*xl;
-l=xl*l+((m&32767)<<15)+w[j]+(c&1073741823);
-c=(l>>>30)+(m>>>15)+xh*h+(c>>>30);
-w[j++]=l&1073741823;
-}
-return c;
-};
-function _8(i,x,w,j,c,n){
-var xl=x&16383,xh=x>>14;
-while(--n>=0){
-var l=this[i]&16383;
-var h=this[i++]>>14;
-var m=xh*l+h*xl;
-l=xl*l+((m&16383)<<14)+w[j]+c;
-c=(l>>28)+(m>>14)+xh*h;
-w[j++]=l&268435455;
-}
-return c;
-};
-if(_3&&(navigator.appName=="Microsoft Internet Explorer")){
-_4.prototype.am=_7;
-_1=30;
-}else{
-if(_3&&(navigator.appName!="Netscape")){
-_4.prototype.am=_6;
-_1=26;
-}else{
-_4.prototype.am=_8;
-_1=28;
-}
-}
-var _9=52;
-var _a="0123456789abcdefghijklmnopqrstuvwxyz";
-var _b=[];
-var rr,vv;
-rr="0".charCodeAt(0);
-for(vv=0;vv<=9;++vv){
-_b[rr++]=vv;
-}
-rr="a".charCodeAt(0);
-for(vv=10;vv<36;++vv){
-_b[rr++]=vv;
-}
-rr="A".charCodeAt(0);
-for(vv=10;vv<36;++vv){
-_b[rr++]=vv;
-}
-function _c(n){
-return _a.charAt(n);
-};
-function _d(s,i){
-var c=_b[s.charCodeAt(i)];
-return (c==null)?-1:c;
-};
-function _e(r){
-for(var i=this.t-1;i>=0;--i){
-r[i]=this[i];
-}
-r.t=this.t;
-r.s=this.s;
-};
-function _f(x){
-this.t=1;
-this.s=(x<0)?-1:0;
-if(x>0){
-this[0]=x;
-}else{
-if(x<-1){
-this[0]=x+_DV;
-}else{
-this.t=0;
-}
-}
-};
-function nbv(i){
-var r=_5();
-r._fromInt(i);
-return r;
-};
-function _10(s,b){
-var k;
-if(b==16){
-k=4;
-}else{
-if(b==8){
-k=3;
-}else{
-if(b==256){
-k=8;
-}else{
-if(b==2){
-k=1;
-}else{
-if(b==32){
-k=5;
-}else{
-if(b==4){
-k=2;
-}else{
-this.fromRadix(s,b);
-return;
-}
-}
-}
-}
-}
-}
-this.t=0;
-this.s=0;
-var i=s.length,mi=false,sh=0;
-while(--i>=0){
-var x=(k==8)?s[i]&255:_d(s,i);
-if(x<0){
-if(s.charAt(i)=="-"){
-mi=true;
-}
-continue;
-}
-mi=false;
-if(sh==0){
-this[this.t++]=x;
-}else{
-if(sh+k>this._DB){
-this[this.t-1]|=(x&((1<<(this._DB-sh))-1))<<sh;
-this[this.t++]=(x>>(this._DB-sh));
-}else{
-this[this.t-1]|=x<<sh;
-}
-}
-sh+=k;
-if(sh>=this._DB){
-sh-=this._DB;
-}
-}
-if(k==8&&(s[0]&128)!=0){
-this.s=-1;
-if(sh>0){
-this[this.t-1]|=((1<<(this._DB-sh))-1)<<sh;
-}
-}
-this._clamp();
-if(mi){
-_4.ZERO._subTo(this,this);
-}
-};
-function _11(){
-var c=this.s&this._DM;
-while(this.t>0&&this[this.t-1]==c){
---this.t;
-}
-};
-function _12(b){
-if(this.s<0){
-return "-"+this.negate().toString(b);
-}
-var k;
-if(b==16){
-k=4;
-}else{
-if(b==8){
-k=3;
-}else{
-if(b==2){
-k=1;
-}else{
-if(b==32){
-k=5;
-}else{
-if(b==4){
-k=2;
-}else{
-return this._toRadix(b);
-}
-}
-}
-}
-}
-var km=(1<<k)-1,d,m=false,r="",i=this.t;
-var p=this._DB-(i*this._DB)%k;
-if(i-->0){
-if(p<this._DB&&(d=this[i]>>p)>0){
-m=true;
-r=_c(d);
-}
-while(i>=0){
-if(p<k){
-d=(this[i]&((1<<p)-1))<<(k-p);
-d|=this[--i]>>(p+=this._DB-k);
-}else{
-d=(this[i]>>(p-=k))&km;
-if(p<=0){
-p+=this._DB;
---i;
-}
-}
-if(d>0){
-m=true;
-}
-if(m){
-r+=_c(d);
-}
-}
-}
-return m?r:"0";
-};
-function _13(){
-var r=_5();
-_4.ZERO._subTo(this,r);
-return r;
-};
-function _14(){
-return (this.s<0)?this.negate():this;
-};
-function _15(a){
-var r=this.s-a.s;
-if(r){
-return r;
-}
-var i=this.t;
-r=i-a.t;
-if(r){
-return r;
-}
-while(--i>=0){
-if((r=this[i]-a[i])){
-return r;
-}
-}
-return 0;
-};
-function _16(x){
-var r=1,t;
-if((t=x>>>16)){
-x=t;
-r+=16;
-}
-if((t=x>>8)){
-x=t;
-r+=8;
-}
-if((t=x>>4)){
-x=t;
-r+=4;
-}
-if((t=x>>2)){
-x=t;
-r+=2;
-}
-if((t=x>>1)){
-x=t;
-r+=1;
-}
-return r;
-};
-function _17(){
-if(this.t<=0){
-return 0;
-}
-return this._DB*(this.t-1)+_16(this[this.t-1]^(this.s&this._DM));
-};
-function _18(n,r){
-var i;
-for(i=this.t-1;i>=0;--i){
-r[i+n]=this[i];
-}
-for(i=n-1;i>=0;--i){
-r[i]=0;
-}
-r.t=this.t+n;
-r.s=this.s;
-};
-function _19(n,r){
-for(var i=n;i<this.t;++i){
-r[i-n]=this[i];
-}
-r.t=Math.max(this.t-n,0);
-r.s=this.s;
-};
-function _1a(n,r){
-var bs=n%this._DB;
-var cbs=this._DB-bs;
-var bm=(1<<cbs)-1;
-var ds=Math.floor(n/this._DB),c=(this.s<<bs)&this._DM,i;
-for(i=this.t-1;i>=0;--i){
-r[i+ds+1]=(this[i]>>cbs)|c;
-c=(this[i]&bm)<<bs;
-}
-for(i=ds-1;i>=0;--i){
-r[i]=0;
-}
-r[ds]=c;
-r.t=this.t+ds+1;
-r.s=this.s;
-r._clamp();
-};
-function _1b(n,r){
-r.s=this.s;
-var ds=Math.floor(n/this._DB);
-if(ds>=this.t){
-r.t=0;
-return;
-}
-var bs=n%this._DB;
-var cbs=this._DB-bs;
-var bm=(1<<bs)-1;
-r[0]=this[ds]>>bs;
-for(var i=ds+1;i<this.t;++i){
-r[i-ds-1]|=(this[i]&bm)<<cbs;
-r[i-ds]=this[i]>>bs;
-}
-if(bs>0){
-r[this.t-ds-1]|=(this.s&bm)<<cbs;
-}
-r.t=this.t-ds;
-r._clamp();
-};
-function _1c(a,r){
-var i=0,c=0,m=Math.min(a.t,this.t);
-while(i<m){
-c+=this[i]-a[i];
-r[i++]=c&this._DM;
-c>>=this._DB;
-}
-if(a.t<this.t){
-c-=a.s;
-while(i<this.t){
-c+=this[i];
-r[i++]=c&this._DM;
-c>>=this._DB;
-}
-c+=this.s;
-}else{
-c+=this.s;
-while(i<a.t){
-c-=a[i];
-r[i++]=c&this._DM;
-c>>=this._DB;
-}
-c-=a.s;
-}
-r.s=(c<0)?-1:0;
-if(c<-1){
-r[i++]=this._DV+c;
-}else{
-if(c>0){
-r[i++]=c;
-}
-}
-r.t=i;
-r._clamp();
-};
-function _1d(a,r){
-var x=this.abs(),y=a.abs();
-var i=x.t;
-r.t=i+y.t;
-while(--i>=0){
-r[i]=0;
-}
-for(i=0;i<y.t;++i){
-r[i+x.t]=x.am(0,y[i],r,i,0,x.t);
-}
-r.s=0;
-r._clamp();
-if(this.s!=a.s){
-_4.ZERO._subTo(r,r);
-}
-};
-function _1e(r){
-var x=this.abs();
-var i=r.t=2*x.t;
-while(--i>=0){
-r[i]=0;
-}
-for(i=0;i<x.t-1;++i){
-var c=x.am(i,x[i],r,2*i,0,1);
-if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1))>=x._DV){
-r[i+x.t]-=x._DV;
-r[i+x.t+1]=1;
-}
-}
-if(r.t>0){
-r[r.t-1]+=x.am(i,x[i],r,2*i,0,1);
-}
-r.s=0;
-r._clamp();
-};
-function _1f(m,q,r){
-var pm=m.abs();
-if(pm.t<=0){
-return;
-}
-var pt=this.abs();
-if(pt.t<pm.t){
-if(q!=null){
-q._fromInt(0);
-}
-if(r!=null){
-this._copyTo(r);
-}
-return;
-}
-if(r==null){
-r=_5();
-}
-var y=_5(),ts=this.s,ms=m.s;
-var nsh=this._DB-_16(pm[pm.t-1]);
-if(nsh>0){
-pm._lShiftTo(nsh,y);
-pt._lShiftTo(nsh,r);
-}else{
-pm._copyTo(y);
-pt._copyTo(r);
-}
-var ys=y.t;
-var y0=y[ys-1];
-if(y0==0){
-return;
-}
-var yt=y0*(1<<this._F1)+((ys>1)?y[ys-2]>>this._F2:0);
-var d1=this._FV/yt,d2=(1<<this._F1)/yt,e=1<<this._F2;
-var i=r.t,j=i-ys,t=(q==null)?_5():q;
-y._dlShiftTo(j,t);
-if(r.compareTo(t)>=0){
-r[r.t++]=1;
-r._subTo(t,r);
-}
-_4.ONE._dlShiftTo(ys,t);
-t._subTo(y,y);
-while(y.t<ys){
-y[y.t++]=0;
-}
-while(--j>=0){
-var qd=(r[--i]==y0)?this._DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
-if((r[i]+=y.am(0,qd,r,j,0,ys))<qd){
-y._dlShiftTo(j,t);
-r._subTo(t,r);
-while(r[i]<--qd){
-r._subTo(t,r);
-}
-}
-}
-if(q!=null){
-r._drShiftTo(ys,q);
-if(ts!=ms){
-_4.ZERO._subTo(q,q);
-}
-}
-r.t=ys;
-r._clamp();
-if(nsh>0){
-r._rShiftTo(nsh,r);
-}
-if(ts<0){
-_4.ZERO._subTo(r,r);
-}
-};
-function _20(a){
-var r=_5();
-this.abs()._divRemTo(a,null,r);
-if(this.s<0&&r.compareTo(_4.ZERO)>0){
-a._subTo(r,r);
-}
-return r;
-};
-function _21(m){
-this.m=m;
-};
-function _22(x){
-if(x.s<0||x.compareTo(this.m)>=0){
-return x.mod(this.m);
-}else{
-return x;
-}
-};
-function _23(x){
-return x;
-};
-function _24(x){
-x._divRemTo(this.m,null,x);
-};
-function _25(x,y,r){
-x._multiplyTo(y,r);
-this.reduce(r);
-};
-function _26(x,r){
-x._squareTo(r);
-this.reduce(r);
-};
-dojo.extend(_21,{convert:_22,revert:_23,reduce:_24,mulTo:_25,sqrTo:_26});
-function _27(){
-if(this.t<1){
-return 0;
-}
-var x=this[0];
-if((x&1)==0){
-return 0;
-}
-var y=x&3;
-y=(y*(2-(x&15)*y))&15;
-y=(y*(2-(x&255)*y))&255;
-y=(y*(2-(((x&65535)*y)&65535)))&65535;
-y=(y*(2-x*y%this._DV))%this._DV;
-return (y>0)?this._DV-y:-y;
-};
-function _28(m){
-this.m=m;
-this.mp=m._invDigit();
-this.mpl=this.mp&32767;
-this.mph=this.mp>>15;
-this.um=(1<<(m._DB-15))-1;
-this.mt2=2*m.t;
-};
-function _29(x){
-var r=_5();
-x.abs()._dlShiftTo(this.m.t,r);
-r._divRemTo(this.m,null,r);
-if(x.s<0&&r.compareTo(_4.ZERO)>0){
-this.m._subTo(r,r);
-}
-return r;
-};
-function _2a(x){
-var r=_5();
-x._copyTo(r);
-this.reduce(r);
-return r;
-};
-function _2b(x){
-while(x.t<=this.mt2){
-x[x.t++]=0;
-}
-for(var i=0;i<this.m.t;++i){
-var j=x[i]&32767;
-var u0=(j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x._DM;
-j=i+this.m.t;
-x[j]+=this.m.am(0,u0,x,i,0,this.m.t);
-while(x[j]>=x._DV){
-x[j]-=x._DV;
-x[++j]++;
-}
-}
-x._clamp();
-x._drShiftTo(this.m.t,x);
-if(x.compareTo(this.m)>=0){
-x._subTo(this.m,x);
-}
-};
-function _2c(x,r){
-x._squareTo(r);
-this.reduce(r);
-};
-function _2d(x,y,r){
-x._multiplyTo(y,r);
-this.reduce(r);
-};
-dojo.extend(_28,{convert:_29,revert:_2a,reduce:_2b,mulTo:_2d,sqrTo:_2c});
-function _2e(){
-return ((this.t>0)?(this[0]&1):this.s)==0;
-};
-function _2f(e,z){
-if(e>4294967295||e<1){
-return _4.ONE;
-}
-var r=_5(),r2=_5(),g=z.convert(this),i=_16(e)-1;
-g._copyTo(r);
-while(--i>=0){
-z.sqrTo(r,r2);
-if((e&(1<<i))>0){
-z.mulTo(r2,g,r);
-}else{
-var t=r;
-r=r2;
-r2=t;
-}
-}
-return z.revert(r);
-};
-function _30(e,m){
-var z;
-if(e<256||m._isEven()){
-z=new _21(m);
-}else{
-z=new _28(m);
-}
-return this._exp(e,z);
-};
-dojo.extend(_4,{_DB:_1,_DM:(1<<_1)-1,_DV:1<<_1,_FV:Math.pow(2,_9),_F1:_9-_1,_F2:2*_1-_9,_copyTo:_e,_fromInt:_f,_fromString:_10,_clamp:_11,_dlShiftTo:_18,_drShiftTo:_19,_lShiftTo:_1a,_rShiftTo:_1b,_subTo:_1c,_multiplyTo:_1d,_squareTo:_1e,_divRemTo:_1f,_invDigit:_27,_isEven:_2e,_exp:_2f,toString:_12,negate:_13,abs:_14,compareTo:_15,bitLength:_17,mod:_20,modPowInt:_30});
-dojo._mixin(_4,{ZERO:nbv(0),ONE:nbv(1),_nbi:_5,_nbv:nbv,_nbits:_16,_Montgomery:_28});
-dojox.math.BigInteger=_4;
+
+	// Bits per digit
+	var dbits;
+
+	// JavaScript engine analysis
+	var canary = 0xdeadbeefcafe;
+	var j_lm = ((canary&0xffffff)==0xefcafe);
+
+	// (public) Constructor
+	function BigInteger(a,b,c) {
+	  if(a != null)
+		if("number" == typeof a) this._fromNumber(a,b,c);
+		else if(!b && "string" != typeof a) this._fromString(a,256);
+		else this._fromString(a,b);
+	}
+
+	// return new, unset BigInteger
+	function nbi() { return new BigInteger(null); }
+
+	// am: Compute w_j += (x*this_i), propagate carries,
+	// c is initial carry, returns final carry.
+	// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
+	// We need to select the fastest one that works in this environment.
+
+	// am1: use a single mult and divide to get the high bits,
+	// max digit bits should be 26 because
+	// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
+	function am1(i,x,w,j,c,n) {
+	  while(--n >= 0) {
+		var v = x*this[i++]+w[j]+c;
+		c = Math.floor(v/0x4000000);
+		w[j++] = v&0x3ffffff;
+	  }
+	  return c;
+	}
+	// am2 avoids a big mult-and-extract completely.
+	// Max digit bits should be <= 30 because we do bitwise ops
+	// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
+	function am2(i,x,w,j,c,n) {
+	  var xl = x&0x7fff, xh = x>>15;
+	  while(--n >= 0) {
+		var l = this[i]&0x7fff;
+		var h = this[i++]>>15;
+		var m = xh*l+h*xl;
+		l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
+		c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
+		w[j++] = l&0x3fffffff;
+	  }
+	  return c;
+	}
+	// Alternately, set max digit bits to 28 since some
+	// browsers slow down when dealing with 32-bit numbers.
+	function am3(i,x,w,j,c,n) {
+	  var xl = x&0x3fff, xh = x>>14;
+	  while(--n >= 0) {
+		var l = this[i]&0x3fff;
+		var h = this[i++]>>14;
+		var m = xh*l+h*xl;
+		l = xl*l+((m&0x3fff)<<14)+w[j]+c;
+		c = (l>>28)+(m>>14)+xh*h;
+		w[j++] = l&0xfffffff;
+	  }
+	  return c;
+	}
+	if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
+	  BigInteger.prototype.am = am2;
+	  dbits = 30;
+	}
+	else if(j_lm && (navigator.appName != "Netscape")) {
+	  BigInteger.prototype.am = am1;
+	  dbits = 26;
+	}
+	else { // Mozilla/Netscape seems to prefer am3
+	  BigInteger.prototype.am = am3;
+	  dbits = 28;
+	}
+
+	var BI_FP = 52;
+
+	// Digit conversions
+	var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
+	var BI_RC = [];
+	var rr,vv;
+	rr = "0".charCodeAt(0);
+	for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
+	rr = "a".charCodeAt(0);
+	for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+	rr = "A".charCodeAt(0);
+	for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+
+	function int2char(n) { return BI_RM.charAt(n); }
+	function intAt(s,i) {
+	  var c = BI_RC[s.charCodeAt(i)];
+	  return (c==null)?-1:c;
+	}
+
+	// (protected) copy this to r
+	function bnpCopyTo(r) {
+	  for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
+	  r.t = this.t;
+	  r.s = this.s;
+	}
+
+	// (protected) set from integer value x, -DV <= x < DV
+	function bnpFromInt(x) {
+	  this.t = 1;
+	  this.s = (x<0)?-1:0;
+	  if(x > 0) this[0] = x;
+	  else if(x < -1) this[0] = x+_DV;
+	  else this.t = 0;
+	}
+
+	// return bigint initialized to value
+	function nbv(i) { var r = nbi(); r._fromInt(i); return r; }
+
+	// (protected) set from string and radix
+	function bnpFromString(s,b) {
+	  var k;
+	  if(b == 16) k = 4;
+	  else if(b == 8) k = 3;
+	  else if(b == 256) k = 8; // byte array
+	  else if(b == 2) k = 1;
+	  else if(b == 32) k = 5;
+	  else if(b == 4) k = 2;
+	  else { this.fromRadix(s,b); return; }
+	  this.t = 0;
+	  this.s = 0;
+	  var i = s.length, mi = false, sh = 0;
+	  while(--i >= 0) {
+		var x = (k==8)?s[i]&0xff:intAt(s,i);
+		if(x < 0) {
+		  if(s.charAt(i) == "-") mi = true;
+		  continue;
+		}
+		mi = false;
+		if(sh == 0)
+		  this[this.t++] = x;
+		else if(sh+k > this._DB) {
+		  this[this.t-1] |= (x&((1<<(this._DB-sh))-1))<<sh;
+		  this[this.t++] = (x>>(this._DB-sh));
+		}
+		else
+		  this[this.t-1] |= x<<sh;
+		sh += k;
+		if(sh >= this._DB) sh -= this._DB;
+	  }
+	  if(k == 8 && (s[0]&0x80) != 0) {
+		this.s = -1;
+		if(sh > 0) this[this.t-1] |= ((1<<(this._DB-sh))-1)<<sh;
+	  }
+	  this._clamp();
+	  if(mi) BigInteger.ZERO._subTo(this,this);
+	}
+
+	// (protected) clamp off excess high words
+	function bnpClamp() {
+	  var c = this.s&this._DM;
+	  while(this.t > 0 && this[this.t-1] == c) --this.t;
+	}
+
+	// (public) return string representation in given radix
+	function bnToString(b) {
+	  if(this.s < 0) return "-"+this.negate().toString(b);
+	  var k;
+	  if(b == 16) k = 4;
+	  else if(b == 8) k = 3;
+	  else if(b == 2) k = 1;
+	  else if(b == 32) k = 5;
+	  else if(b == 4) k = 2;
+	  else return this._toRadix(b);
+	  var km = (1<<k)-1, d, m = false, r = "", i = this.t;
+	  var p = this._DB-(i*this._DB)%k;
+	  if(i-- > 0) {
+		if(p < this._DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
+		while(i >= 0) {
+		  if(p < k) {
+			d = (this[i]&((1<<p)-1))<<(k-p);
+			d |= this[--i]>>(p+=this._DB-k);
+		  }
+		  else {
+			d = (this[i]>>(p-=k))&km;
+			if(p <= 0) { p += this._DB; --i; }
+		  }
+		  if(d > 0) m = true;
+		  if(m) r += int2char(d);
+		}
+	  }
+	  return m?r:"0";
+	}
+
+	// (public) -this
+	function bnNegate() { var r = nbi(); BigInteger.ZERO._subTo(this,r); return r; }
+
+	// (public) |this|
+	function bnAbs() { return (this.s<0)?this.negate():this; }
+
+	// (public) return + if this > a, - if this < a, 0 if equal
+	function bnCompareTo(a) {
+	  var r = this.s-a.s;
+	  if(r) return r;
+	  var i = this.t;
+	  r = i-a.t;
+	  if(r) return r;
+	  while(--i >= 0) if((r = this[i] - a[i])) return r;
+	  return 0;
+	}
+
+	// returns bit length of the integer x
+	function nbits(x) {
+	  var r = 1, t;
+	  if((t=x>>>16)) { x = t; r += 16; }
+	  if((t=x>>8)) { x = t; r += 8; }
+	  if((t=x>>4)) { x = t; r += 4; }
+	  if((t=x>>2)) { x = t; r += 2; }
+	  if((t=x>>1)) { x = t; r += 1; }
+	  return r;
+	}
+
+	// (public) return the number of bits in "this"
+	function bnBitLength() {
+	  if(this.t <= 0) return 0;
+	  return this._DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this._DM));
+	}
+
+	// (protected) r = this << n*DB
+	function bnpDLShiftTo(n,r) {
+	  var i;
+	  for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
+	  for(i = n-1; i >= 0; --i) r[i] = 0;
+	  r.t = this.t+n;
+	  r.s = this.s;
+	}
+
+	// (protected) r = this >> n*DB
+	function bnpDRShiftTo(n,r) {
+	  for(var i = n; i < this.t; ++i) r[i-n] = this[i];
+	  r.t = Math.max(this.t-n,0);
+	  r.s = this.s;
+	}
+
+	// (protected) r = this << n
+	function bnpLShiftTo(n,r) {
+	  var bs = n%this._DB;
+	  var cbs = this._DB-bs;
+	  var bm = (1<<cbs)-1;
+	  var ds = Math.floor(n/this._DB), c = (this.s<<bs)&this._DM, i;
+	  for(i = this.t-1; i >= 0; --i) {
+		r[i+ds+1] = (this[i]>>cbs)|c;
+		c = (this[i]&bm)<<bs;
+	  }
+	  for(i = ds-1; i >= 0; --i) r[i] = 0;
+	  r[ds] = c;
+	  r.t = this.t+ds+1;
+	  r.s = this.s;
+	  r._clamp();
+	}
+
+	// (protected) r = this >> n
+	function bnpRShiftTo(n,r) {
+	  r.s = this.s;
+	  var ds = Math.floor(n/this._DB);
+	  if(ds >= this.t) { r.t = 0; return; }
+	  var bs = n%this._DB;
+	  var cbs = this._DB-bs;
+	  var bm = (1<<bs)-1;
+	  r[0] = this[ds]>>bs;
+	  for(var i = ds+1; i < this.t; ++i) {
+		r[i-ds-1] |= (this[i]&bm)<<cbs;
+		r[i-ds] = this[i]>>bs;
+	  }
+	  if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
+	  r.t = this.t-ds;
+	  r._clamp();
+	}
+
+	// (protected) r = this - a
+	function bnpSubTo(a,r) {
+	  var i = 0, c = 0, m = Math.min(a.t,this.t);
+	  while(i < m) {
+		c += this[i]-a[i];
+		r[i++] = c&this._DM;
+		c >>= this._DB;
+	  }
+	  if(a.t < this.t) {
+		c -= a.s;
+		while(i < this.t) {
+		  c += this[i];
+		  r[i++] = c&this._DM;
+		  c >>= this._DB;
+		}
+		c += this.s;
+	  }
+	  else {
+		c += this.s;
+		while(i < a.t) {
+		  c -= a[i];
+		  r[i++] = c&this._DM;
+		  c >>= this._DB;
+		}
+		c -= a.s;
+	  }
+	  r.s = (c<0)?-1:0;
+	  if(c < -1) r[i++] = this._DV+c;
+	  else if(c > 0) r[i++] = c;
+	  r.t = i;
+	  r._clamp();
+	}
+
+	// (protected) r = this * a, r != this,a (HAC 14.12)
+	// "this" should be the larger one if appropriate.
+	function bnpMultiplyTo(a,r) {
+	  var x = this.abs(), y = a.abs();
+	  var i = x.t;
+	  r.t = i+y.t;
+	  while(--i >= 0) r[i] = 0;
+	  for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
+	  r.s = 0;
+	  r._clamp();
+	  if(this.s != a.s) BigInteger.ZERO._subTo(r,r);
+	}
+
+	// (protected) r = this^2, r != this (HAC 14.16)
+	function bnpSquareTo(r) {
+	  var x = this.abs();
+	  var i = r.t = 2*x.t;
+	  while(--i >= 0) r[i] = 0;
+	  for(i = 0; i < x.t-1; ++i) {
+		var c = x.am(i,x[i],r,2*i,0,1);
+		if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x._DV) {
+		  r[i+x.t] -= x._DV;
+		  r[i+x.t+1] = 1;
+		}
+	  }
+	  if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
+	  r.s = 0;
+	  r._clamp();
+	}
+
+	// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
+	// r != q, this != m.  q or r may be null.
+	function bnpDivRemTo(m,q,r) {
+	  var pm = m.abs();
+	  if(pm.t <= 0) return;
+	  var pt = this.abs();
+	  if(pt.t < pm.t) {
+		if(q != null) q._fromInt(0);
+		if(r != null) this._copyTo(r);
+		return;
+	  }
+	  if(r == null) r = nbi();
+	  var y = nbi(), ts = this.s, ms = m.s;
+	  var nsh = this._DB-nbits(pm[pm.t-1]);	// normalize modulus
+	  if(nsh > 0) { pm._lShiftTo(nsh,y); pt._lShiftTo(nsh,r); }
+	  else { pm._copyTo(y); pt._copyTo(r); }
+	  var ys = y.t;
+	  var y0 = y[ys-1];
+	  if(y0 == 0) return;
+	  var yt = y0*(1<<this._F1)+((ys>1)?y[ys-2]>>this._F2:0);
+	  var d1 = this._FV/yt, d2 = (1<<this._F1)/yt, e = 1<<this._F2;
+	  var i = r.t, j = i-ys, t = (q==null)?nbi():q;
+	  y._dlShiftTo(j,t);
+	  if(r.compareTo(t) >= 0) {
+		r[r.t++] = 1;
+		r._subTo(t,r);
+	  }
+	  BigInteger.ONE._dlShiftTo(ys,t);
+	  t._subTo(y,y);	// "negative" y so we can replace sub with am later
+	  while(y.t < ys) y[y.t++] = 0;
+	  while(--j >= 0) {
+		// Estimate quotient digit
+		var qd = (r[--i]==y0)?this._DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
+		if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {	// Try it out
+		  y._dlShiftTo(j,t);
+		  r._subTo(t,r);
+		  while(r[i] < --qd) r._subTo(t,r);
+		}
+	  }
+	  if(q != null) {
+		r._drShiftTo(ys,q);
+		if(ts != ms) BigInteger.ZERO._subTo(q,q);
+	  }
+	  r.t = ys;
+	  r._clamp();
+	  if(nsh > 0) r._rShiftTo(nsh,r);	// Denormalize remainder
+	  if(ts < 0) BigInteger.ZERO._subTo(r,r);
+	}
+
+	// (public) this mod a
+	function bnMod(a) {
+	  var r = nbi();
+	  this.abs()._divRemTo(a,null,r);
+	  if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a._subTo(r,r);
+	  return r;
+	}
+
+	// Modular reduction using "classic" algorithm
+	function Classic(m) { this.m = m; }
+	function cConvert(x) {
+	  if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
+	  else return x;
+	}
+	function cRevert(x) { return x; }
+	function cReduce(x) { x._divRemTo(this.m,null,x); }
+	function cMulTo(x,y,r) { x._multiplyTo(y,r); this.reduce(r); }
+	function cSqrTo(x,r) { x._squareTo(r); this.reduce(r); }
+
+	dojo.extend(Classic, {
+		convert:	cConvert,
+		revert:		cRevert,
+		reduce:		cReduce,
+		mulTo:		cMulTo,
+		sqrTo:		cSqrTo
+	});
+
+	// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
+	// justification:
+	//         xy == 1 (mod m)
+	//         xy =  1+km
+	//   xy(2-xy) = (1+km)(1-km)
+	// x[y(2-xy)] = 1-k^2m^2
+	// x[y(2-xy)] == 1 (mod m^2)
+	// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
+	// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
+	// JS multiply "overflows" differently from C/C++, so care is needed here.
+	function bnpInvDigit() {
+	  if(this.t < 1) return 0;
+	  var x = this[0];
+	  if((x&1) == 0) return 0;
+	  var y = x&3;		// y == 1/x mod 2^2
+	  y = (y*(2-(x&0xf)*y))&0xf;	// y == 1/x mod 2^4
+	  y = (y*(2-(x&0xff)*y))&0xff;	// y == 1/x mod 2^8
+	  y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;	// y == 1/x mod 2^16
+	  // last step - calculate inverse mod DV directly;
+	  // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
+	  y = (y*(2-x*y%this._DV))%this._DV;		// y == 1/x mod 2^dbits
+	  // we really want the negative inverse, and -DV < y < DV
+	  return (y>0)?this._DV-y:-y;
+	}
+
+	// Montgomery reduction
+	function Montgomery(m) {
+	  this.m = m;
+	  this.mp = m._invDigit();
+	  this.mpl = this.mp&0x7fff;
+	  this.mph = this.mp>>15;
+	  this.um = (1<<(m._DB-15))-1;
+	  this.mt2 = 2*m.t;
+	}
+
+	// xR mod m
+	function montConvert(x) {
+	  var r = nbi();
+	  x.abs()._dlShiftTo(this.m.t,r);
+	  r._divRemTo(this.m,null,r);
+	  if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m._subTo(r,r);
+	  return r;
+	}
+
+	// x/R mod m
+	function montRevert(x) {
+	  var r = nbi();
+	  x._copyTo(r);
+	  this.reduce(r);
+	  return r;
+	}
+
+	// x = x/R mod m (HAC 14.32)
+	function montReduce(x) {
+	  while(x.t <= this.mt2)	// pad x so am has enough room later
+		x[x.t++] = 0;
+	  for(var i = 0; i < this.m.t; ++i) {
+		// faster way of calculating u0 = x[i]*mp mod DV
+		var j = x[i]&0x7fff;
+		var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x._DM;
+		// use am to combine the multiply-shift-add into one call
+		j = i+this.m.t;
+		x[j] += this.m.am(0,u0,x,i,0,this.m.t);
+		// propagate carry
+		while(x[j] >= x._DV) { x[j] -= x._DV; x[++j]++; }
+	  }
+	  x._clamp();
+	  x._drShiftTo(this.m.t,x);
+	  if(x.compareTo(this.m) >= 0) x._subTo(this.m,x);
+	}
+
+	// r = "x^2/R mod m"; x != r
+	function montSqrTo(x,r) { x._squareTo(r); this.reduce(r); }
+
+	// r = "xy/R mod m"; x,y != r
+	function montMulTo(x,y,r) { x._multiplyTo(y,r); this.reduce(r); }
+
+	dojo.extend(Montgomery, {
+		convert:	montConvert,
+		revert:		montRevert,
+		reduce:		montReduce,
+		mulTo:		montMulTo,
+		sqrTo:		montSqrTo
+	});
+
+	// (protected) true iff this is even
+	function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
+
+	// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
+	function bnpExp(e,z) {
+	  if(e > 0xffffffff || e < 1) return BigInteger.ONE;
+	  var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
+	  g._copyTo(r);
+	  while(--i >= 0) {
+		z.sqrTo(r,r2);
+		if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
+		else { var t = r; r = r2; r2 = t; }
+	  }
+	  return z.revert(r);
+	}
+
+	// (public) this^e % m, 0 <= e < 2^32
+	function bnModPowInt(e,m) {
+	  var z;
+	  if(e < 256 || m._isEven()) z = new Classic(m); else z = new Montgomery(m);
+	  return this._exp(e,z);
+	}
+
+	dojo.extend(BigInteger, {
+		// protected, not part of the official API
+		_DB:	dbits,
+		_DM:	(1 << dbits) - 1,
+		_DV:	1 << dbits,
+
+		_FV:	Math.pow(2, BI_FP),
+		_F1:	BI_FP - dbits,
+		_F2:	2 * dbits-BI_FP,
+
+		// protected
+		_copyTo:		bnpCopyTo,
+		_fromInt:		bnpFromInt,
+		_fromString:	bnpFromString,
+		_clamp:			bnpClamp,
+		_dlShiftTo:		bnpDLShiftTo,
+		_drShiftTo:		bnpDRShiftTo,
+		_lShiftTo:		bnpLShiftTo,
+		_rShiftTo:		bnpRShiftTo,
+		_subTo:			bnpSubTo,
+		_multiplyTo:	bnpMultiplyTo,
+		_squareTo:		bnpSquareTo,
+		_divRemTo:		bnpDivRemTo,
+		_invDigit:		bnpInvDigit,
+		_isEven:		bnpIsEven,
+		_exp:			bnpExp,
+
+		// public
+		toString:		bnToString,
+		negate:			bnNegate,
+		abs:			bnAbs,
+		compareTo:		bnCompareTo,
+		bitLength:		bnBitLength,
+		mod:			bnMod,
+		modPowInt:		bnModPowInt
+	});
+
+	dojo._mixin(BigInteger, {
+		// "constants"
+		ZERO:	nbv(0),
+		ONE:	nbv(1),
+		
+		// internal functions
+		_nbi: nbi,
+		_nbv: nbv,
+		_nbits: nbits,
+		
+		// internal classes
+		_Montgomery: Montgomery
+	});
+
+	// export to DojoX
+	dojox.math.BigInteger = BigInteger;
 })();
-}
diff --git a/dojox/math/LICENSE-BigInteger b/dojox/math/LICENSE-BigInteger
deleted file mode 100644
index 7ccbf50..0000000
--- a/dojox/math/LICENSE-BigInteger
+++ /dev/null
@@ -1,40 +0,0 @@
-Licensing
----------
-
-This software is covered under the following copyright:
-
-/*
- * Copyright (c) 2003-2005  Tom Wu
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
- * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * In addition, the following condition applies:
- *
- * All redistributions must retain an intact copy of this copyright notice
- * and disclaimer.
- */
-
-Address all questions regarding this license to:
-
-  Tom Wu
-  tjw at cs.Stanford.EDU
\ No newline at end of file
diff --git a/dojox/math/README b/dojox/math/README
index 03f7506..27d29ff 100644
--- a/dojox/math/README
+++ b/dojox/math/README
@@ -18,9 +18,6 @@ Project description
 A port of the main functionality of dojo.math 0.4.  Includes advanced math
 functions, abstract curve definitions, and some point calculations.
 
-Port of Tom Wu's port of java.math.BigInteger released in 2005 under the BSD
-license (CLA on file). See http://www-cs-students.stanford.edu/~tjw/jsbn/
-for details.
 -------------------------------------------------------------------------------
 Dependencies:
 
diff --git a/dojox/math/_base.js b/dojox/math/_base.js
index a1b6d04..51c873f 100644
--- a/dojox/math/_base.js
+++ b/dojox/math/_base.js
@@ -1,86 +1,159 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.math._base"]){
-dojo._hasResource["dojox.math._base"]=true;
 dojo.provide("dojox.math._base");
+
 (function(){
-var m=dojox.math;
-dojo.mixin(dojox.math,{toRadians:function(n){
-return (n*Math.PI)/180;
-},toDegrees:function(n){
-return (n*180)/Math.PI;
-},degreesToRadians:function(n){
-return m.toRadians(n);
-},radiansToDegrees:function(n){
-return m.toDegrees(n);
-},factorial:function(n){
-if(n===0){
-return 1;
-}else{
-if(n<0||Math.floor(n)!=n){
-return NaN;
-}
-}
-var _1=1;
-for(var i=1;i<=n;i++){
-_1*=i;
-}
-return _1;
-},permutations:function(n,k){
-if(n==0||k==0){
-return 1;
-}
-return this.factorial(n)/this.factorial(n-k);
-},combinations:function(n,r){
-if(n==0||r==0){
-return 1;
-}
-return this.factorial(n)/(this.factorial(n-r)*this.factorial(r));
-},bernstein:function(t,n,i){
-return this.combinations(n,i)*Math.pow(t,i)*Math.pow(1-t,n-i);
-},gaussian:function(){
-var k=2;
-do{
-var i=2*Math.random()-1;
-var j=2*Math.random()-1;
-k=i*i+j*j;
-}while(k>=1);
-return i*Math.sqrt((-2*Math.log(k))/k);
-},range:function(a,b,_2){
-if(arguments.length<2){
-b=a,a=0;
-}
-var _3=[],s=_2||1,i;
-if(s>0){
-for(i=a;i<b;i+=s){
-_3.push(i);
-}
-}else{
-if(s<0){
-for(i=a;i>b;i+=s){
-_3.push(i);
-}
-}else{
-throw new Error("dojox.math.range: step must not be zero.");
-}
-}
-return _3;
-},distance:function(a,b){
-return Math.sqrt(Math.pow(b[0]-a[0],2)+Math.pow(b[1]-a[1],2));
-},midpoint:function(a,b){
-if(a.length!=b.length){
-console.error("dojox.math.midpoint: Points A and B are not the same dimensionally.",a,b);
-}
-var m=[];
-for(var i=0;i<a.length;i++){
-m[i]=(a[i]+b[i])/2;
-}
-return m;
-}});
+	var m = dojox.math;
+	dojo.mixin(dojox.math, {
+		toRadians: function(/* Number */n){
+			//	summary:
+			//		Convert the passed number to radians.
+			return (n*Math.PI)/180;	// Number
+		},
+		toDegrees: function(/* Number */n){
+			//	summary:
+			//		Convert the passed number to degrees.
+			return (n*180)/Math.PI;	//	Number
+		},
+		degreesToRadians: function(/* Number */n){
+			//	summary:
+			//		Deprecated.  Use dojox.math.toRadians.
+			return m.toRadians(n);	// Number
+		},
+		radiansToDegrees: function(/* Number */n){
+			//	summary:
+			//		Deprecated.  Use dojox.math.toDegrees.
+			return m.toDegrees(n);	//	Number
+		},
+
+		_gamma: function(z){
+			//	summary:
+			//		Compute the gamma function for the passed number.
+			//		Approximately 14 dijits of precision with non-integers.
+			var answer = 1; // 0!
+			// gamma(n+1) = n * gamma(n)
+			while (--z >= 1){
+				answer *= z;
+			}
+			if(z == 0){ return answer; } // normal integer quick return
+			if(Math.floor(z) == z){ return NaN; } // undefined at nonpositive integers since sin() below will return 0
+			// assert: z < 1, remember this z is really z-1
+			if(z == -0.5){ return Math.sqrt(Math.PI); } // popular gamma(1/2)
+			if(z < -0.5){ // remember this z is really z-1
+				return Math.PI / (Math.sin(Math.PI * (z + 1)) * this._gamma(-z)); // reflection
+			}
+			// assert: -0.5 < z < 1
+			// Spouge approximation algorithm
+			var a = 13;
+			// c[0] = sqrt(2*PI) / exp(a)
+			// var kfact = 1
+			// for (var k=1; k < a; k++){
+			//      c[k] = pow(-k + a, k - 0.5) * exp(-k) / kfact
+			//      kfact *= -k  // (-1)^(k-1) * (k-1)!
+			// }
+			var c = [ // precomputed from the above algorithm
+					 5.6658056015186327e-6,
+					 1.2743717663379679,
+					-4.9374199093155115,
+					 7.8720267032485961,
+					-6.6760503749436087,
+					 3.2525298444485167,
+					-9.1852521441026269e-1,
+					 1.4474022977730785e-1,
+					-1.1627561382389853e-2,
+					 4.0117980757066622e-4,
+					-4.2652458386405744e-6,
+					 6.6651913290336086e-9,
+					-1.5392547381874824e-13
+				];
+			var sum = c[0];
+			for (var k=1; k < a; k++){
+				sum += c[k] / (z + k);
+			}
+			return answer * Math.pow(z + a, z + 0.5) / Math.exp(z) * sum;
+		},
+
+		factorial: function(/* Number */n){
+			//	summary:
+			//		Return the factorial of n
+			return this._gamma(n+1);	// Number
+		},
+
+		permutations: function(/* Number */n, /* Number */k){
+			//	summary:
+			//	TODO
+			if(n==0 || k==0){ 
+				return 1; 	// Number
+			}
+			return this.factorial(n) / this.factorial(n-k);
+		},
+
+		combinations: function(/* Number */n, /* Number */r){
+			//	summary:
+			//	TODO
+			if(n==0 || r==0){ 
+				return 1; 	//	Number
+			}
+			return this.factorial(n) / (this.factorial(n-r) * this.factorial(r));	// Number
+		},
+
+		bernstein: function(/* Number */t, /* Number */n, /* Number */ i){
+			//	summary:
+			//	TODO
+			return this.combinations(n, i) * Math.pow(t, i) * Math.pow(1-t, n-i);	//	Number
+		},
+
+		gaussian: function(){
+			//	summary:
+			//		Return a random number based on the Gaussian algo.
+			var k=2;
+			do{
+				var i=2*Math.random()-1;
+				var j=2*Math.random()-1;
+				k = i*i+j*j;
+			}while(k>=1);
+			return i * Math.sqrt((-2*Math.log(k))/k);	//	Number
+		},
+
+		//	create a range of numbers
+		range: function(/* Number */a, /* Number? */b, /* Number? */step){
+			//	summary:
+			//		Create a range of numbers based on the parameters.
+			if(arguments.length<2){
+				b=a,a=0;
+			}
+			var range=[], s=step||1, i;
+			if(s>0){
+				for(i=a; i<b; i+=s){
+					range.push(i);
+				}
+			}else{
+				if(s<0){
+					for(i=a; i>b; i+=s){
+						range.push(i);
+					}
+				}else{
+					throw new Error("dojox.math.range: step must not be zero.");
+				}
+			}
+			return range; 	// Array
+		},
+
+		distance: function(/* Array */a, /* Array */b){
+			//	summary:
+			//		Calculate the distance between point A and point B
+			return Math.sqrt(Math.pow(b[0]-a[0],2)+Math.pow(b[1]-a[1],2));	//	Number
+		},
+
+		midpoint: function(/* Array */a, /* Array */b){
+			//	summary:
+			//		Calculate the midpoint between points A and B.  A and B may be multidimensional.
+			if(a.length!=b.length){
+				console.error("dojox.math.midpoint: Points A and B are not the same dimensionally.", a, b);
+			}
+			var m=[];
+			for(var i=0; i<a.length; i++){
+				m[i]=(a[i]+b[i])/2;
+			}
+			return m;	//	Array
+		}
+	});
 })();
-}
diff --git a/dojox/math/curves.js b/dojox/math/curves.js
index 840879a..f57abad 100644
--- a/dojox/math/curves.js
+++ b/dojox/math/curves.js
@@ -1,194 +1,189 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.math.curves"]){
-dojo._hasResource["dojox.math.curves"]=true;
 dojo.provide("dojox.math.curves");
-dojo.mixin(dojox.math.curves,{Line:function(_1,_2){
-this.start=_1;
-this.end=_2;
-this.dimensions=_1.length;
-for(var i=0;i<_1.length;i++){
-_1[i]=Number(_1[i]);
-}
-for(var i=0;i<_2.length;i++){
-_2[i]=Number(_2[i]);
-}
-this.getValue=function(n){
-var _3=new Array(this.dimensions);
-for(var i=0;i<this.dimensions;i++){
-_3[i]=((this.end[i]-this.start[i])*n)+this.start[i];
-}
-return _3;
-};
-return this;
-},Bezier:function(_4){
-this.getValue=function(_5){
-if(_5>=1){
-return this.p[this.p.length-1];
-}
-if(_5<=0){
-return this.p[0];
-}
-var _6=new Array(this.p[0].length);
-for(var k=0;j<this.p[0].length;k++){
-_6[k]=0;
-}
-for(var j=0;j<this.p[0].length;j++){
-var C=0;
-var D=0;
-for(var i=0;i<this.p.length;i++){
-C+=this.p[i][j]*this.p[this.p.length-1][0]*dojox.math.bernstein(_5,this.p.length,i);
-}
-for(var l=0;l<this.p.length;l++){
-D+=this.p[this.p.length-1][0]*dojox.math.bernstein(_5,this.p.length,l);
-}
-_6[j]=C/D;
-}
-return _6;
-};
-this.p=_4;
-return this;
-},CatmullRom:function(_7,c){
-this.getValue=function(_8){
-var _9=_8*(this.p.length-1);
-var _a=Math.floor(_9);
-var _b=_9-_a;
-var i0=_a-1;
-if(i0<0){
-i0=0;
-}
-var i=_a;
-var i1=_a+1;
-if(i1>=this.p.length){
-i1=this.p.length-1;
-}
-var i2=_a+2;
-if(i2>=this.p.length){
-i2=this.p.length-1;
-}
-var u=_b;
-var u2=_b*_b;
-var u3=_b*_b*_b;
-var _c=new Array(this.p[0].length);
-for(var k=0;k<this.p[0].length;k++){
-var x1=(-this.c*this.p[i0][k])+((2-this.c)*this.p[i][k])+((this.c-2)*this.p[i1][k])+(this.c*this.p[i2][k]);
-var x2=(2*this.c*this.p[i0][k])+((this.c-3)*this.p[i][k])+((3-2*this.c)*this.p[i1][k])+(-this.c*this.p[i2][k]);
-var x3=(-this.c*this.p[i0][k])+(this.c*this.p[i1][k]);
-var x4=this.p[i][k];
-_c[k]=x1*u3+x2*u2+x3*u+x4;
-}
-return _c;
-};
-if(!c){
-this.c=0.7;
-}else{
-this.c=c;
-}
-this.p=_7;
-return this;
-},Arc:function(_d,_e,_f){
-function _10(a,b){
-var c=new Array(a.length);
-for(var i=0;i<a.length;i++){
-c[i]=a[i]+b[i];
-}
-return c;
-};
-function _11(a){
-var b=new Array(a.length);
-for(var i=0;i<a.length;i++){
-b[i]=-a[i];
-}
-return b;
-};
-var _12=dojox.math.midpoint(_d,_e);
-var _13=_10(_11(_12),_d);
-var rad=Math.sqrt(Math.pow(_13[0],2)+Math.pow(_13[1],2));
-var _14=dojox.math.radiansToDegrees(Math.atan(_13[1]/_13[0]));
-if(_13[0]<0){
-_14-=90;
-}else{
-_14+=90;
-}
-dojox.math.curves.CenteredArc.call(this,_12,rad,_14,_14+(_f?-180:180));
-},CenteredArc:function(_15,_16,_17,end){
-this.center=_15;
-this.radius=_16;
-this.start=_17||0;
-this.end=end;
-this.getValue=function(n){
-var _18=new Array(2);
-var _19=dojox.math.degreesToRadians(this.start+((this.end-this.start)*n));
-_18[0]=this.center[0]+this.radius*Math.sin(_19);
-_18[1]=this.center[1]-this.radius*Math.cos(_19);
-return _18;
-};
-return this;
-},Circle:function(_1a,_1b){
-dojox.math.curves.CenteredArc.call(this,_1a,_1b,0,360);
-return this;
-},Path:function(){
-var _1c=[];
-var _1d=[];
-var _1e=[];
-var _1f=0;
-this.add=function(_20,_21){
-if(_21<0){
-console.error("dojox.math.curves.Path.add: weight cannot be less than 0");
-}
-_1c.push(_20);
-_1d.push(_21);
-_1f+=_21;
-_22();
-};
-this.remove=function(_23){
-for(var i=0;i<_1c.length;i++){
-if(_1c[i]==_23){
-_1c.splice(i,1);
-_1f-=_1d.splice(i,1)[0];
-break;
-}
-}
-_22();
-};
-this.removeAll=function(){
-_1c=[];
-_1d=[];
-_1f=0;
-};
-this.getValue=function(n){
-var _24=false,_25=0;
-for(var i=0;i<_1e.length;i++){
-var r=_1e[i];
-if(n>=r[0]&&n<r[1]){
-var _26=(n-r[0])/r[2];
-_25=_1c[i].getValue(_26);
-_24=true;
-break;
-}
-}
-if(!_24){
-_25=_1c[_1c.length-1].getValue(1);
-}
-for(var j=0;j<i;j++){
-_25=dojox.math.points.translate(_25,_1c[j].getValue(1));
-}
-return _25;
-};
-function _22(){
-var _27=0;
-for(var i=0;i<_1d.length;i++){
-var end=_27+_1d[i]/_1f;
-var len=end-_27;
-_1e[i]=[_27,end,len];
-_27=end;
-}
-};
-return this;
-}});
-}
+
+dojo.mixin(dojox.math.curves, {
+	Line:function (start, end) {
+		this.start = start;
+		this.end = end;
+		this.dimensions = start.length;
+		for (var i = 0; i < start.length; i++) {
+			start[i] = Number(start[i]);
+		}
+		for (var i = 0; i < end.length; i++) {
+			end[i] = Number(end[i]);
+		}
+		this.getValue = function (n) {
+			var retVal = new Array(this.dimensions);
+			for (var i = 0; i < this.dimensions; i++) {
+				retVal[i] = ((this.end[i] - this.start[i]) * n) + this.start[i];
+			}
+			return retVal;
+		};
+		return this;
+	}, 
+	Bezier:function(pnts) {
+		this.getValue = function (step) {
+			if (step >= 1) {
+				return this.p[this.p.length - 1];
+			}
+			if (step <= 0) {
+				return this.p[0];
+			}
+			var retVal = new Array(this.p[0].length);
+			for (var k = 0; j < this.p[0].length; k++) {
+				retVal[k] = 0;
+			}
+			for (var j = 0; j < this.p[0].length; j++) {
+				var C = 0;
+				var D = 0;
+				for (var i = 0; i < this.p.length; i++) {
+					C += this.p[i][j] * this.p[this.p.length - 1][0] * dojox.math.bernstein(step, this.p.length, i);
+				}
+				for (var l = 0; l < this.p.length; l++) {
+					D += this.p[this.p.length - 1][0] * dojox.math.bernstein(step, this.p.length, l);
+				}
+				retVal[j] = C / D;
+			}
+			return retVal;
+		};
+		this.p = pnts;
+		return this;
+	}, 
+	CatmullRom:function (pnts, c) {
+		this.getValue = function (step) {
+			var percent = step * (this.p.length - 1);
+			var node = Math.floor(percent);
+			var progress = percent - node;
+			var i0 = node - 1;
+			if (i0 < 0) {
+				i0 = 0;
+			}
+			var i = node;
+			var i1 = node + 1;
+			if (i1 >= this.p.length) {
+				i1 = this.p.length - 1;
+			}
+			var i2 = node + 2;
+			if (i2 >= this.p.length) {
+				i2 = this.p.length - 1;
+			}
+			var u = progress;
+			var u2 = progress * progress;
+			var u3 = progress * progress * progress;
+			var retVal = new Array(this.p[0].length);
+			for (var k = 0; k < this.p[0].length; k++) {
+				var x1 = (-this.c * this.p[i0][k]) + ((2 - this.c) * this.p[i][k]) + ((this.c - 2) * this.p[i1][k]) + (this.c * this.p[i2][k]);
+				var x2 = (2 * this.c * this.p[i0][k]) + ((this.c - 3) * this.p[i][k]) + ((3 - 2 * this.c) * this.p[i1][k]) + (-this.c * this.p[i2][k]);
+				var x3 = (-this.c * this.p[i0][k]) + (this.c * this.p[i1][k]);
+				var x4 = this.p[i][k];
+				retVal[k] = x1 * u3 + x2 * u2 + x3 * u + x4;
+			}
+			return retVal;
+		};
+		if (!c) {
+			this.c = 0.7;
+		} else {
+			this.c = c;
+		}
+		this.p = pnts;
+		return this;
+	}, 
+	Arc:function (start, end, ccw){
+		function translate(a,b){
+			var c=new Array(a.length);
+			for(var i=0; i<a.length; i++){ c[i]=a[i]+b[i]; }
+			return c;
+		}
+		function invert(a){
+			var b = new Array(a.length);
+			for(var i=0; i<a.length; i++){ b[i]=-a[i]; }
+			return b;
+		}
+		var center = dojox.math.midpoint(start, end);
+		var sides = translate(invert(center), start);
+		var rad = Math.sqrt(Math.pow(sides[0], 2) + Math.pow(sides[1], 2));
+		var theta = dojox.math.radiansToDegrees(Math.atan(sides[1] / sides[0]));
+		if (sides[0] < 0){
+			theta -= 90;
+		} else {
+			theta += 90;
+		}
+		dojox.math.curves.CenteredArc.call(this, center, rad, theta, theta + (ccw ? -180 : 180));
+	}, 
+	CenteredArc:function (center, radius, start, end) {
+		this.center = center;
+		this.radius = radius;
+		this.start = start || 0;
+		this.end = end;
+		this.getValue = function (n) {
+			var retVal = new Array(2);
+			var theta = dojox.math.degreesToRadians(this.start + ((this.end - this.start) * n));
+			retVal[0] = this.center[0] + this.radius * Math.sin(theta);
+			retVal[1] = this.center[1] - this.radius * Math.cos(theta);
+			return retVal;
+		};
+		return this;
+	}, 
+	Circle:function(center, radius){
+		dojox.math.curves.CenteredArc.call(this, center, radius, 0, 360);
+		return this;
+	}, 
+	Path:function () {
+		var curves = [];
+		var weights = [];
+		var ranges = [];
+		var totalWeight = 0;
+		this.add = function (curve, weight) {
+			if (weight < 0) {
+				console.error("dojox.math.curves.Path.add: weight cannot be less than 0");
+			}
+			curves.push(curve);
+			weights.push(weight);
+			totalWeight += weight;
+			computeRanges();
+		};
+		this.remove = function (curve) {
+			for (var i = 0; i < curves.length; i++) {
+				if (curves[i] == curve) {
+					curves.splice(i, 1);
+					totalWeight -= weights.splice(i, 1)[0];
+					break;
+				}
+			}
+			computeRanges();
+		};
+		this.removeAll = function () {
+			curves = [];
+			weights = [];
+			totalWeight = 0;
+		};
+		this.getValue = function (n) {
+			var found = false, value = 0;
+			for (var i = 0; i < ranges.length; i++) {
+				var r = ranges[i];
+				if (n >= r[0] && n < r[1]) {
+					var subN = (n - r[0]) / r[2];
+					value = curves[i].getValue(subN);
+					found = true;
+					break;
+				}
+			}
+			if (!found) {
+				value = curves[curves.length - 1].getValue(1);
+			}
+			for (var j = 0; j < i; j++) {
+				value = dojox.math.points.translate(value, curves[j].getValue(1));
+			}
+			return value;
+		};
+		function computeRanges() {
+			var start = 0;
+			for (var i = 0; i < weights.length; i++) {
+				var end = start + weights[i] / totalWeight;
+				var len = end - start;
+				ranges[i] = [start, end, len];
+				start = end;
+			}
+		}
+		return this;
+	}
+});
diff --git a/dojox/math/matrix.js b/dojox/math/matrix.js
index 18c6d9a..77f5f4b 100644
--- a/dojox/math/matrix.js
+++ b/dojox/math/matrix.js
@@ -1,251 +1,290 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.math.matrix"]){
-dojo._hasResource["dojox.math.matrix"]=true;
 dojo.provide("dojox.math.matrix");
-dojo.mixin(dojox.math.matrix,{iDF:0,ALMOST_ZERO:1e-10,multiply:function(a,b){
-var ay=a.length,ax=a[0].length,by=b.length,bx=b[0].length;
-if(ax!=by){
-console.warn("Can't multiply matricies of sizes "+ax+","+ay+" and "+bx+","+by);
-return [[0]];
-}
-var c=[];
-for(var k=0;k<ay;k++){
-c[k]=[];
-for(var i=0;i<bx;i++){
-c[k][i]=0;
-for(var m=0;m<ax;m++){
-c[k][i]+=a[k][m]*b[m][i];
-}
-}
-}
-return c;
-},product:function(){
-if(arguments.length==0){
-console.warn("can't multiply 0 matrices!");
-return 1;
-}
-var m=arguments[0];
-for(var i=1;i<arguments.length;i++){
-m=this.multiply(m,arguments[i]);
-}
-return m;
-},sum:function(){
-if(arguments.length==0){
-console.warn("can't sum 0 matrices!");
-return 0;
-}
-var m=this.copy(arguments[0]);
-var _1=m.length;
-if(_1==0){
-console.warn("can't deal with matrices of 0 rows!");
-return 0;
-}
-var _2=m[0].length;
-if(_2==0){
-console.warn("can't deal with matrices of 0 cols!");
-return 0;
-}
-for(var i=1;i<arguments.length;++i){
-var _3=arguments[i];
-if(_3.length!=_1||_3[0].length!=_2){
-console.warn("can't add matrices of different dimensions: first dimensions were "+_1+"x"+_2+", current dimensions are "+_3.length+"x"+_3[0].length);
-return 0;
-}
-for(var r=0;r<_1;r++){
-for(var c=0;c<_2;c++){
-m[r][c]+=_3[r][c];
-}
-}
-}
-return m;
-},inverse:function(a){
-if(a.length==1&&a[0].length==1){
-return [[1/a[0][0]]];
-}
-var _4=a.length,m=this.create(_4,_4),mm=this.adjoint(a),_5=this.determinant(a),dd=0;
-if(_5==0){
-console.warn("Determinant Equals 0, Not Invertible.");
-return [[0]];
-}else{
-dd=1/_5;
-}
-for(var i=0;i<_4;i++){
-for(var j=0;j<_4;j++){
-m[i][j]=dd*mm[i][j];
-}
-}
-return m;
-},determinant:function(a){
-if(a.length!=a[0].length){
-console.warn("Can't calculate the determinant of a non-squre matrix!");
-return 0;
-}
-var _6=a.length,_7=1,b=this.upperTriangle(a);
-for(var i=0;i<_6;i++){
-var _8=b[i][i];
-if(Math.abs(_8)<this.ALMOST_ZERO){
-return 0;
-}
-_7*=_8;
-}
-_7*=this.iDF;
-return _7;
-},upperTriangle:function(m){
-m=this.copy(m);
-var f1=0,_9=0,_a=m.length,v=1;
-this.iDF=1;
-for(var _b=0;_b<_a-1;_b++){
-if(typeof m[_b][_b]!="number"){
-console.warn("non-numeric entry found in a numeric matrix: m["+_b+"]["+_b+"]="+m[_b][_b]);
-}
-v=1;
-var _c=0;
-while((m[_b][_b]==0)&&!_c){
-if(_b+v>=_a){
-this.iDF=0;
-_c=1;
-}else{
-for(var r=0;r<_a;r++){
-_9=m[_b][r];
-m[_b][r]=m[_b+v][r];
-m[_b+v][r]=_9;
-}
-v++;
-this.iDF*=-1;
-}
-}
-for(var _d=_b+1;_d<_a;_d++){
-if(typeof m[_d][_b]!="number"){
-console.warn("non-numeric entry found in a numeric matrix: m["+_d+"]["+_b+"]="+m[_d][_b]);
-}
-if(typeof m[_b][_d]!="number"){
-console.warn("non-numeric entry found in a numeric matrix: m["+_b+"]["+_d+"]="+m[_b][_d]);
-}
-if(m[_b][_b]!=0){
-var f1=(-1)*m[_d][_b]/m[_b][_b];
-for(var i=_b;i<_a;i++){
-m[_d][i]=f1*m[_b][i]+m[_d][i];
-}
-}
-}
-}
-return m;
-},create:function(a,b,_e){
-_e=_e||0;
-var m=[];
-for(var i=0;i<b;i++){
-m[i]=[];
-for(var j=0;j<a;j++){
-m[i][j]=_e;
-}
-}
-return m;
-},ones:function(a,b){
-return this.create(a,b,1);
-},zeros:function(a,b){
-return this.create(a,b);
-},identity:function(_f,_10){
-_10=_10||1;
-var m=[];
-for(var i=0;i<_f;i++){
-m[i]=[];
-for(var j=0;j<_f;j++){
-m[i][j]=(i==j?_10:0);
-}
-}
-return m;
-},adjoint:function(a){
-var tms=a.length;
-if(tms<=1){
-console.warn("Can't find the adjoint of a matrix with a dimension less than 2");
-return [[0]];
-}
-if(a.length!=a[0].length){
-console.warn("Can't find the adjoint of a non-square matrix");
-return [[0]];
-}
-var m=this.create(tms,tms),ap=this.create(tms-1,tms-1);
-var ii=0,jj=0,ia=0,ja=0,det=0;
-for(var i=0;i<tms;i++){
-for(var j=0;j<tms;j++){
-ia=0;
-for(ii=0;ii<tms;ii++){
-if(ii==i){
-continue;
-}
-ja=0;
-for(jj=0;jj<tms;jj++){
-if(jj==j){
-continue;
-}
-ap[ia][ja]=a[ii][jj];
-ja++;
-}
-ia++;
-}
-det=this.determinant(ap);
-m[i][j]=Math.pow(-1,(i+j))*det;
-}
-}
-return this.transpose(m);
-},transpose:function(a){
-var m=this.create(a.length,a[0].length);
-for(var i=0;i<a.length;i++){
-for(var j=0;j<a[i].length;j++){
-m[j][i]=a[i][j];
-}
-}
-return m;
-},format:function(a,_11){
-_11=_11||5;
-function _12(x,dp){
-var fac=Math.pow(10,dp);
-var a=Math.round(x*fac)/fac;
-var b=a.toString();
-if(b.charAt(0)!="-"){
-b=" "+b;
-}
-if(b.indexOf(".")>-1){
-b+=".";
-}
-while(b.length<dp+3){
-b+="0";
-}
-return b;
-};
-var ya=a.length;
-var xa=ya>0?a[0].length:0;
-var _13="";
-for(var y=0;y<ya;y++){
-_13+="| ";
-for(var x=0;x<xa;x++){
-_13+=_12(a[y][x],_11)+" ";
-}
-_13+="|\n";
-}
-return _13;
-},copy:function(a){
-var ya=a.length,xa=a[0].length,m=this.create(xa,ya);
-for(var y=0;y<ya;y++){
-for(var x=0;x<xa;x++){
-m[y][x]=a[y][x];
-}
-}
-return m;
-},scale:function(a,_14){
-a=this.copy(a);
-var ya=a.length,xa=a[0].length;
-for(var y=0;y<ya;y++){
-for(var x=0;x<xa;x++){
-a[y][x]*=_14;
-}
-}
-return a;
-}});
-}
+
+dojo.mixin(dojox.math.matrix, {
+	iDF:0,
+	ALMOST_ZERO: 1e-10,
+	multiply: function(/* Array */a, /* Array */b){
+		//	summary
+		//	Multiply matrix a by matrix b.
+		var ay=a.length, ax=a[0].length, by=b.length, bx=b[0].length;
+		if(ax!=by){
+			console.warn("Can't multiply matricies of sizes " + ax + "," + ay + " and " + bx + "," + by);
+			return [[0]];
+		}
+		var c=[];
+		for (var k=0; k<ay; k++) {
+			c[k]=[];
+			for(var i=0; i<bx; i++){
+				c[k][i]=0;
+				for(var m=0; m<ax; m++){
+					c[k][i]+=a[k][m]*b[m][i];
+				}
+			}
+		}
+		return c;	//	Array
+	},
+	product: function(/* Array... */){
+		//	summary
+		//	Return the product of N matrices
+		if (arguments.length==0){
+			console.warn("can't multiply 0 matrices!");
+			return 1;
+		}
+		var m=arguments[0];
+		for(var i=1; i<arguments.length; i++){
+			m=this.multiply(m, arguments[i]);
+		}
+		return m;	//	Array
+	},
+	sum: function(/* Array... */){
+		//	summary
+		//	Return the sum of N matrices
+		if(arguments.length==0){
+			console.warn("can't sum 0 matrices!");
+			return 0;	//	Number
+		}
+		var m=this.copy(arguments[0]);
+		var rows=m.length;
+		if(rows==0){
+			console.warn("can't deal with matrices of 0 rows!");
+			return 0;
+		}
+		var cols=m[0].length;
+		if(cols==0){
+			console.warn("can't deal with matrices of 0 cols!");
+			return 0;
+		}
+		for(var i=1; i<arguments.length; ++i){
+			var arg=arguments[i];
+			if(arg.length!=rows || arg[0].length!=cols){
+				console.warn("can't add matrices of different dimensions: first dimensions were " + rows + "x" + cols + ", current dimensions are " + arg.length + "x" + arg[0].length);
+				return 0;
+			}
+			for(var r=0; r<rows; r++) {
+				for(var c=0; c<cols; c++) {
+					m[r][c]+=arg[r][c];
+				}
+			}
+		}
+		return m;	//	Array
+	},
+	inverse: function(/* Array */a){
+		//	summary
+		//	Return the inversion of the passed matrix
+		if(a.length==1 && a[0].length==1){
+			return [[1/a[0][0]]];	//	Array
+		}
+		var tms=a.length, m=this.create(tms, tms), mm=this.adjoint(a), det=this.determinant(a), dd=0;
+		if(det==0){
+			console.warn("Determinant Equals 0, Not Invertible.");
+			return [[0]];
+		}else{
+			dd=1/det;
+		}
+		for(var i=0; i<tms; i++) {
+			for (var j=0; j<tms; j++) {
+				m[i][j]=dd*mm[i][j];
+			}
+		}
+		return m;	//	Array
+	},
+	determinant: function(/* Array */a){
+		//	summary
+		//	Calculate the determinant of the passed square matrix.
+		if(a.length!=a[0].length){
+			console.warn("Can't calculate the determinant of a non-squre matrix!");
+			return 0;
+		}
+		var tms=a.length, det=1, b=this.upperTriangle(a);
+		for (var i=0; i<tms; i++){
+			var bii=b[i][i];
+			if (Math.abs(bii)<this.ALMOST_ZERO) {
+				return 0;	//	Number
+			}
+			det*=bii;
+		}
+		det*=this.iDF;
+		return det;	//	Number
+	},
+	upperTriangle: function(/* Array */m){
+		//	Summary
+		//	Find the upper triangle of the passed matrix and return it.
+		m=this.copy(m);
+		var f1=0, temp=0, tms=m.length, v=1;
+		this.iDF=1;
+		for(var col=0; col<tms-1; col++){
+			if(typeof m[col][col]!="number") {
+				console.warn("non-numeric entry found in a numeric matrix: m[" + col + "][" + col + "]=" + m[col][col]);
+			}
+			v=1;
+			var stop_loop=0;
+			while((m[col][col] == 0) && !stop_loop){
+				if (col+v>=tms){
+					this.iDF=0;
+					stop_loop=1;
+				}else{
+					for(var r=0; r<tms; r++){
+						temp=m[col][r];
+						m[col][r]=m[col+v][r];
+						m[col+v][r]=temp;
+					}
+					v++;
+					this.iDF*=-1;
+				}
+			}
+			for(var row=col+1; row<tms; row++){
+				if(typeof m[row][col]!="number"){
+					console.warn("non-numeric entry found in a numeric matrix: m[" + row + "][" + col + "]=" + m[row][col]);
+				}
+				if(typeof m[col][row]!="number"){
+					console.warn("non-numeric entry found in a numeric matrix: m[" + col + "][" + row + "]=" + m[col][row]);
+				}
+				if(m[col][col]!=0){
+					var f1=(-1)* m[row][col]/m[col][col];
+					for (var i=col; i<tms; i++){
+						m[row][i]=f1*m[col][i]+m[row][i];
+					}
+				}
+			}
+		}
+		return m;	//	Array
+	},
+	create: function(/* Number */a, /* Number */b, /* Number? */value){
+		//	summary
+		//	Create a new matrix with rows a and cols b, and pre-populate with value.
+		value=value||0;
+		var m=[];
+		for (var i=0; i<b; i++){
+			m[i]=[];
+			for(var j=0; j<a; j++) {
+				m[i][j]=value;
+			}
+		}
+		return m;	//	Array
+	},
+	ones: function(/* Number */a, /* Number */b){
+		//	summary
+		//	Create a matrix pre-populated with ones
+		return this.create(a, b, 1);	//	Array
+	},
+	zeros: function(/* Number */a, /* Number */b){
+		//	summary
+		//	Create a matrix pre-populated with zeros
+		return this.create(a, b);	// Array
+	},
+	identity: function(/* Number */size, /* Number? */scale){
+		//	summary
+		//	Create an identity matrix based on the size and scale.
+		scale=scale||1;
+		var m=[];
+		for(var i=0; i<size; i++){
+			m[i]=[];
+			for(var j=0; j<size; j++){
+				m[i][j]=(i==j?scale:0);
+			}
+		}
+		return m;	//	Array
+	},
+	adjoint: function(/* Array */a){
+		//	summary
+		//	Find the adjoint of the passed matrix
+		var tms=a.length;
+		if(tms<=1){
+			console.warn("Can't find the adjoint of a matrix with a dimension less than 2");
+			return [[0]];
+		}
+		if(a.length!=a[0].length){
+			console.warn("Can't find the adjoint of a non-square matrix");
+			return [[0]];
+		}
+		var m=this.create(tms, tms), ap=this.create(tms-1, tms-1);
+		var ii=0, jj=0, ia=0, ja=0, det=0;
+		for(var i=0; i<tms; i++){
+			for (var j=0; j<tms; j++){
+				ia=0;
+				for(ii=0; ii<tms; ii++){
+					if(ii==i){
+						continue;
+					}
+					ja = 0;
+					for(jj=0; jj<tms; jj++){
+						if(jj==j){
+							continue;
+						}
+						ap[ia][ja] = a[ii][jj];
+						ja++;
+					}
+					ia++;
+				}
+				det=this.determinant(ap);
+				m[i][j]=Math.pow(-1, (i+j))*det;
+			}
+		}
+		return this.transpose(m);	//	Array
+	},
+	transpose: function(/* Array */a){
+		//	summary
+		//	Transpose the passed matrix (i.e. rows to columns)
+		var m=this.create(a.length, a[0].length);
+		for(var i=0; i<a.length; i++){
+			for(var j=0; j<a[i].length; j++){
+				m[j][i]=a[i][j];
+			}
+		}
+		return m;	//	Array
+	},
+	format: function(/* Array */a, /* Number? */points){
+		//	summary
+		//	Return a string representation of the matrix, rounded to points (if needed)
+		points=points||5;
+		function format_int(x, dp){
+			var fac=Math.pow(10, dp);
+			var a=Math.round(x*fac)/fac;
+			var b=a.toString();
+			if(b.charAt(0)!="-"){
+				b=" "+b;
+			}
+			if(b.indexOf(".")>-1){
+				b+=".";
+			}
+			while(b.length<dp+3){
+				b+="0";
+			}
+			return b;
+		}
+		var ya=a.length;
+		var xa=ya>0?a[0].length:0;
+		var buffer="";
+		for(var y=0; y<ya; y++){
+			buffer+="| ";
+			for(var x=0; x<xa; x++){
+				buffer+=format_int(a[y][x], points)+" ";
+			}
+			buffer+="|\n";
+		}
+		return buffer;	//	string
+	},
+	copy: function(/* Array */a){
+		//	summary
+		//	Create a copy of the passed matrix
+		var ya=a.length, xa=a[0].length, m=this.create(xa, ya);
+		for(var y=0; y<ya; y++){
+			for(var x=0; x<xa; x++){
+				m[y][x]=a[y][x];
+			}
+		}
+		return m;	// Array
+	},
+	scale: function(/* Array */a, /* Number */factor){
+		//	summary
+		//	Create a copy of passed matrix and scale each member by factor.
+		a=this.copy(a);
+		var ya=a.length, xa=a[0].length;
+		for(var y=0; y<ya; y++){
+			for(var x=0; x<xa; x++){
+				a[y][x]*=factor;
+			}
+		}
+		return a;
+	}
+});
diff --git a/dojox/math/random/Secure.js b/dojox/math/random/Secure.js
index 92c2356..c4ac2e4 100644
--- a/dojox/math/random/Secure.js
+++ b/dojox/math/random/Secure.js
@@ -1,54 +1,94 @@
-/*
-	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
-*/
+dojo.provide("dojox.math.random.Secure");
 
+// Copyright (c) 2005  Tom Wu
+// All Rights Reserved.
+// See "LICENSE-BigInteger" for details.
 
-if(!dojo._hasResource["dojox.math.random.Secure"]){
-dojo._hasResource["dojox.math.random.Secure"]=true;
-dojo.provide("dojox.math.random.Secure");
-dojo.declare("dojox.math.random.Secure",null,{constructor:function(_1,_2){
-this.prng=_1;
-var p=this.pool=new Array(_1.size);
-this.pptr=0;
-for(var i=0,_3=_1.size;i<_3;){
-var t=Math.floor(65536*Math.random());
-p[i++]=t>>>8;
-p[i++]=t&255;
-}
-this.seedTime();
-if(!_2){
-this.h=[dojo.connect(dojo.body(),"onclick",this,"seedTime"),dojo.connect(dojo.body(),"onkeypress",this,"seedTime")];
-}
-},destroy:function(){
-if(this.h){
-dojo.forEach(this.h,dojo.disconnect);
-}
-},nextBytes:function(_4){
-var _5=this.state;
-if(!_5){
-this.seedTime();
-_5=this.state=this.prng();
-_5.init(this.pool);
-for(var p=this.pool,i=0,_6=p.length;i<_6;p[i++]=0){
-}
-this.pptr=0;
-}
-for(var i=0,_6=_4.length;i<_6;++i){
-_4[i]=_5.next();
-}
-},seedTime:function(){
-this._seed_int(new Date().getTime());
-},_seed_int:function(x){
-var p=this.pool,i=this.pptr;
-p[i++]^=x&255;
-p[i++]^=(x>>8)&255;
-p[i++]^=(x>>16)&255;
-p[i++]^=(x>>24)&255;
-if(i>=this.prng.size){
-i-=this.prng.size;
-}
-this.pptr=i;
-}});
-}
+// Random number generator - requires a PRNG backend, e.g. prng4.js
+
+dojo.declare("dojox.math.random.Secure", null, {
+	// summary:
+	//	Super simple implementation of a random number generator,
+	//	which relies on Math.random().
+
+	constructor: function(prng, noEvents){
+		// summary:
+		//	Intializes an instance of a secure random generator.
+		// prng: Function:
+		//	function that returns an instance of PRNG (pseudorandom number generator)
+		//  with two methods: init(array) and next(). It should have a property "size"
+		//	to indicate the required pool size.
+		// noEvents: Boolean?:
+		//	if false or absent, onclick and onkeypress event will be used to add
+		//	"randomness", otherwise events will not be used.
+		this.prng = prng;
+
+		// Initialize the pool with junk if needed.
+		var p = this.pool = new Array(prng.size);
+		this.pptr = 0;
+		for(var i = 0, len = prng.size; i < len;) {  // extract some randomness from Math.random()
+			var t = Math.floor(65536 * Math.random());
+			p[i++] = t >>> 8;
+			p[i++] = t & 255;
+		}
+		this.seedTime();
+
+		if(!noEvents){
+			this.h = [
+				dojo.connect(dojo.body(), "onclick",    this, "seedTime"),
+				dojo.connect(dojo.body(), "onkeypress", this, "seedTime")
+			];
+		}
+	},
+	
+	destroy: function(){
+		// summary:
+		//	Disconnects events, if any, preparing the object for GC.
+		if(this.h){
+			dojo.forEach(this.h, dojo.disconnect);
+		}
+	},
+
+	nextBytes: function(/* Array */ byteArray){
+		// summary:
+		//	Fills in an array of bytes with random numbers
+		// byteArray: Array:
+		//	array to be filled in with random numbers, only existing
+		//	elements will be filled.
+
+		var state = this.state;
+
+		if(!state){
+			this.seedTime();
+			state = this.state = this.prng();
+			state.init(this.pool);
+			for(var p = this.pool, i = 0, len = p.length; i < len; p[i++] = 0);
+			this.pptr = 0;
+			//this.pool = null;
+		}
+
+		for(var i = 0, len = byteArray.length; i < len; ++i){
+			byteArray[i] = state.next();
+		}
+	},
+
+	seedTime: function() {
+		// summary:
+		//	Mix in the current time (w/milliseconds) into the pool
+		this._seed_int(new Date().getTime());
+	},
+
+	_seed_int: function(x) {
+		// summary:
+		//	Mix in a 32-bit integer into the pool
+		var p = this.pool, i = this.pptr;
+		p[i++] ^= x & 255;
+		p[i++] ^= (x >> 8) & 255;
+		p[i++] ^= (x >> 16) & 255;
+		p[i++] ^= (x >> 24) & 255;
+		if(i >= this.prng.size){
+			i -= this.prng.size;
+		}
+		this.pptr = i;
+	}
+});
diff --git a/dojox/math/random/Simple.js b/dojox/math/random/Simple.js
index f5a8833..e33c2e4 100644
--- a/dojox/math/random/Simple.js
+++ b/dojox/math/random/Simple.js
@@ -1,17 +1,23 @@
-/*
-	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
-*/
+dojo.provide("dojox.math.random.Simple");
 
+dojo.declare("dojox.math.random.Simple", null, {
+	// summary:
+	//	Super simple implementation of a random number generator,
+	//	which relies on Math.random().
 
-if(!dojo._hasResource["dojox.math.random.Simple"]){
-dojo._hasResource["dojox.math.random.Simple"]=true;
-dojo.provide("dojox.math.random.Simple");
-dojo.declare("dojox.math.random.Simple",null,{destroy:function(){
-},nextBytes:function(_1){
-for(var i=0,l=_1.length;i<l;++i){
-_1[i]=Math.floor(256*Math.random());
-}
-}});
-}
+	destroy: function(){
+		// summary:
+		//	Prepares the object for GC. (empty in this case)
+	},
+
+	nextBytes: function(/* Array */ byteArray){
+		// summary:
+		//	Fills in an array of bytes with random numbers
+		// byteArray: Array:
+		//	array to be filled in with random numbers, only existing
+		//	elements will be filled.
+		for(var i = 0, l = byteArray.length; i < l; ++i){
+			byteArray[i] = Math.floor(256 * Math.random());
+		}
+	}
+});
diff --git a/dojox/math/random/prng4.js b/dojox/math/random/prng4.js
index fdd0704..9defedc 100644
--- a/dojox/math/random/prng4.js
+++ b/dojox/math/random/prng4.js
@@ -1,45 +1,55 @@
-/*
-	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
-*/
+dojo.provide("dojox.math.random.prng4");
 
+// Copyright (c) 2005  Tom Wu
+// All Rights Reserved.
+// See "LICENSE-BigInteger" for details.
 
-if(!dojo._hasResource["dojox.math.random.prng4"]){
-dojo._hasResource["dojox.math.random.prng4"]=true;
-dojo.provide("dojox.math.random.prng4");
 (function(){
-function _1(){
-this.i=0;
-this.j=0;
-this.S=new Array(256);
-};
-dojo.extend(_1,{init:function(_2){
-var i,j,t,S=this.S,_3=_2.length;
-for(i=0;i<256;++i){
-S[i]=i;
-}
-j=0;
-for(i=0;i<256;++i){
-j=(j+S[i]+_2[i%_3])&255;
-t=S[i];
-S[i]=S[j];
-S[j]=t;
-}
-this.i=0;
-this.j=0;
-},next:function(){
-var t,i,j,S=this.S;
-this.i=i=(this.i+1)&255;
-this.j=j=(this.j+S[i])&255;
-t=S[i];
-S[i]=S[j];
-S[j]=t;
-return S[(t+S[i])&255];
-}});
-dojox.math.random.prng4=function(){
-return new _1();
-};
-dojox.math.random.prng4.size=256;
+	// prng4.js - uses Arcfour as a PRNG
+
+	function Arcfour() {
+		this.i = 0;
+		this.j = 0;
+		this.S = new Array(256);
+	}
+
+	dojo.extend(Arcfour, {
+		init: function(key){
+			// summary:
+			//	Initialize arcfour context
+			// key: Array:
+			//	an array of ints, each from [0..255]
+			var i, j, t, S = this.S, len = key.length;
+			for(i = 0; i < 256; ++i){
+				S[i] = i;
+			}
+			j = 0;
+			for(i = 0; i < 256; ++i){
+				j = (j + S[i] + key[i % len]) & 255;
+				t = S[i];
+				S[i] = S[j];
+				S[j] = t;
+			}
+			this.i = 0;
+			this.j = 0;
+		},
+
+		next: function(){
+			var t, i, j, S = this.S;
+			this.i = i = (this.i + 1) & 255;
+			this.j = j = (this.j + S[i]) & 255;
+			t = S[i];
+			S[i] = S[j];
+			S[j] = t;
+			return S[(t + S[i]) & 255];
+		}
+	});
+
+	dojox.math.random.prng4 = function(){
+		return new Arcfour();
+	};
+
+	// Pool size must be a multiple of 4 and greater than 32.
+	// An array of bytes the size of the pool will be passed to init()
+	dojox.math.random.prng4.size = 256;
 })();
-}
diff --git a/dojox/math/round.js b/dojox/math/round.js
index e28ddfb..94bd4b3 100644
--- a/dojox/math/round.js
+++ b/dojox/math/round.js
@@ -1,30 +1,61 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.math.round"]){
-dojo._hasResource["dojox.math.round"]=true;
 dojo.provide("dojox.math.round");
 dojo.experimental("dojox.math.round");
-dojox.math.round=function(_1,_2,_3){
-var _4=Math.log(Math.abs(_1))/Math.log(10);
-var _5=10/(_3||10);
-var _6=Math.pow(10,-15+_4);
-return (_5*(+_1+(_1>0?_6:-_6))).toFixed(_2)/_5;
-};
-if((0.9).toFixed()==0){
-(function(){
-var _7=dojox.math.round;
-dojox.math.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 _7(v,p,m)+(v>0?d:-d);
-};
-})();
+
+dojox.math.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){
+	//	summary:
+	//		Similar to dojo.number.round, but compensates for binary floating point artifacts
+	//	description:
+	//		Rounds to the nearest value with the given number of decimal places, away from zero if equal,
+	//		similar to Number.toFixed().  Rounding can be done by fractional increments also.
+	//		Makes minor adjustments to accommodate for precision errors due to binary floating point representation
+	//		of Javascript Numbers.  See http://speleotrove.com/decimal/decifaq.html for more information.
+	//		Because of this adjustment, the rounding may not be mathematically correct for full precision
+	//		floating point values.  The calculations assume 14 significant figures, so the accuracy will
+	//		be limited to a certain number of decimal places preserved will vary with the magnitude of
+	//		the input.  This is not a substitute for decimal arithmetic.
+	//	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:
+	//		>>> 4.8-(1.1+2.2)
+	//		1.4999999999999996
+	//		>>> Math.round(4.8-(1.1+2.2))
+	//		1
+	//		>>> dojox.math.round(4.8-(1.1+2.2))
+	//		2
+	//		>>> ((4.8-(1.1+2.2))/100)
+	//		0.014999999999999996
+	//		>>> ((4.8-(1.1+2.2))/100).toFixed(2)
+	//		"0.01"
+	//		>>> dojox.math.round((4.8-(1.1+2.2))/100,2)
+	//		0.02
+	//		>>> dojox.math.round(10.71, 0, 2.5)
+	//		10.75
+	//		>>> dojo.number.round(162.295, 2)
+	//		162.29
+	//		>>> dojox.math.round(162.295, 2)
+	//		162.3
+	var wholeFigs = Math.log(Math.abs(value))/Math.log(10);
+	var factor = 10 / (increment || 10);
+	var delta = Math.pow(10, -15 + wholeFigs);
+	return (factor * (+value + (value > 0 ? delta : -delta))).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 = dojox.math.round;
+		dojox.math.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);
+		}
+	})();
 }
diff --git a/dojox/math/stats.js b/dojox/math/stats.js
index 220a57f..75a609c 100644
--- a/dojox/math/stats.js
+++ b/dojox/math/stats.js
@@ -1,108 +1,190 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.math.stats"]){
-dojo._hasResource["dojox.math.stats"]=true;
 dojo.provide("dojox.math.stats");
+
 (function(){
-var st=dojox.math.stats;
-dojo.mixin(st,{sd:function(a){
-return Math.sqrt(st.variance(a));
-},variance:function(a){
-var _1=0,_2=0;
-dojo.forEach(a,function(_3){
-_1+=_3;
-_2+=Math.pow(_3,2);
-});
-return (_2/a.length)-Math.pow(_1/a.length,2);
-},bestFit:function(a,_4,_5){
-_4=_4||"x",_5=_5||"y";
-if(a[0]!==undefined&&typeof (a[0])=="number"){
-a=dojo.map(a,function(_6,_7){
-return {x:_7,y:_6};
-});
-}
-var sx=0,sy=0,_8=0,_9=0,_a=0,_b=0,_c=0,n=a.length,t;
-for(var i=0;i<n;i++){
-sx+=a[i][_4];
-sy+=a[i][_5];
-_8+=Math.pow(a[i][_4],2);
-_9+=Math.pow(a[i][_5],2);
-_a+=a[i][_4]*a[i][_5];
-}
-for(i=0;i<n;i++){
-t=a[i][_4]-sx/n;
-_b+=t*t;
-_c+=t*a[i][_5];
-}
-var _d=_c/(_b||1);
-var d=Math.sqrt((_8-Math.pow(sx,2)/n)*(_9-Math.pow(sy,2)/n));
-if(d===0){
-throw new Error("dojox.math.stats.bestFit: the denominator for Pearson's R is 0.");
-}
-var r=(_a-(sx*sy/n))/d;
-var r2=Math.pow(r,2);
-if(_d<0){
-r=-r;
-}
-return {slope:_d,intercept:(sy-sx*_d)/(n||1),r:r,r2:r2};
-},forecast:function(a,x,_e,_f){
-var fit=st.bestFit(a,_e,_f);
-return (fit.slope*x)+fit.intercept;
-},mean:function(a){
-var t=0;
-dojo.forEach(a,function(v){
-t+=v;
-});
-return t/Math.max(a.length,1);
-},min:function(a){
-return Math.min.apply(null,a);
-},max:function(a){
-return Math.max.apply(null,a);
-},median:function(a){
-var t=a.slice(0).sort(function(a,b){
-return a-b;
-});
-return (t[Math.floor(a.length/2)]+t[Math.ceil(a.length/2)])/2;
-},mode:function(a){
-var o={},r=0,m=Number.MIN_VALUE;
-dojo.forEach(a,function(v){
-(o[v]!==undefined)?o[v]++:o[v]=1;
-});
-for(var p in o){
-if(m<o[p]){
-m=o[p],r=p;
-}
-}
-return r;
-},sum:function(a){
-var sum=0;
-dojo.forEach(a,function(n){
-sum+=n;
-});
-return sum;
-},approxLin:function(a,pos){
-var p=pos*(a.length-1),t=Math.ceil(p),f=t-1;
-if(f<0){
-return a[0];
-}
-if(t>=a.length){
-return a[a.length-1];
-}
-return a[f]*(t-p)+a[t]*(p-f);
-},summary:function(a,_10){
-if(!_10){
-a=a.slice(0);
-a.sort(function(a,b){
-return a-b;
-});
-}
-var l=st.approxLin,_11={min:a[0],p25:l(a,0.25),med:l(a,0.5),p75:l(a,0.75),max:a[a.length-1],p10:l(a,0.1),p90:l(a,0.9)};
-return _11;
-}});
+	var st = dojox.math.stats;
+	dojo.mixin(st, {
+		sd: function(/* Number[] */a){
+			//	summary:
+			//		Returns the standard deviation of the passed arguments.
+			return Math.sqrt(st.variance(a));	//	Number
+		},
+
+		variance: function(/* Number[] */a){
+			//	summary:
+			//		Find the variance in the passed array of numbers.
+			var mean=0, squares=0;
+			dojo.forEach(a, function(item){
+				mean+=item;
+				squares+=Math.pow(item,2);
+			});
+			return (squares/a.length)-Math.pow(mean/a.length, 2);	//	Number
+		},
+
+		bestFit: function(/* Object[] || Number[] */a, /* String? */xProp, /* String? */yProp){
+			//	summary:
+			//		Calculate the slope and intercept in a linear fashion.  An array
+			//		of objects is expected; optionally you can pass in the property
+			//		names for "x" and "y", else x/y is used as the default.  If you
+			//		pass an array of numbers, it will be mapped to a set of {x,y} objects
+			//		where x = the array index.
+			xProp = xProp || "x", yProp = yProp || "y";
+			if(a[0] !== undefined && typeof(a[0]) == "number"){
+				//	this is an array of numbers, so use the index as x.
+				a = dojo.map(a, function(item, idx){
+					return { x: idx, y: item };
+				});
+			}
+
+			var sx = 0, sy = 0, sxx = 0, syy = 0, sxy = 0, stt = 0, sts = 0, n = a.length, t;
+			for(var i=0; i<n; i++){
+				sx += a[i][xProp];
+				sy += a[i][yProp];
+				sxx += Math.pow(a[i][xProp], 2);
+				syy += Math.pow(a[i][yProp], 2);
+				sxy += a[i][xProp] * a[i][yProp];
+			}
+
+			//	we use the following because it's more efficient and accurate for determining the slope.
+			for(i=0; i<n; i++){
+				t = a[i][xProp] - sx/n;
+				stt += t*t;
+				sts += t*a[i][yProp];
+			}
+			var slope = sts/(stt||1);	//	prevent divide by zero.
+
+			//	get Pearson's R
+			var d = Math.sqrt((sxx - Math.pow(sx,2)/n) * (syy - Math.pow(sy,2)/n));
+			if(d === 0){
+				throw new Error("dojox.math.stats.bestFit: the denominator for Pearson's R is 0.");
+			}
+
+			var r = (sxy-(sx*sy/n)) / d;
+			var r2 = Math.pow(r, 2);
+			if(slope < 0){
+				r = -r;
+			}
+
+			//	to use:  y = slope*x + intercept;
+			return {	//	Object
+				slope: slope,
+				intercept: (sy - sx*slope)/(n||1),
+				r: r,
+				r2: r2
+			};
+		},
+
+		forecast: function(/* Object[] || Number[] */a, /* Number */x, /* String? */xProp, /* String? */yProp){
+			//	summary:
+			//		Using the bestFit algorithm above, find y for the given x.
+			var fit = st.bestFit(a, xProp, yProp);
+			return (fit.slope * x) + fit.intercept;	//	Number
+		},
+
+		mean: function(/* Number[] */a){
+			//	summary:
+			//		Returns the mean value in the passed array.
+			var t=0;
+			dojo.forEach(a, function(v){
+				t += v;
+			});
+			return t / Math.max(a.length, 1);	//	Number
+		},
+
+		min: function(/* Number[] */a){
+			//	summary:
+			//		Returns the min value in the passed array.
+			return Math.min.apply(null, a);		//	Number
+		},
+
+		max: function(/* Number[] */a){
+			//	summary:
+			//		Returns the max value in the passed array.
+			return Math.max.apply(null, a);		//	Number
+		},
+
+		median: function(/* Number[] */a){
+			//	summary:
+			//		Returns the value closest to the middle from a sorted version of the passed array.
+			var t = a.slice(0).sort(function(a, b){ return a - b; });
+			return (t[Math.floor(a.length/2)] + t[Math.ceil(a.length/2)])/2; // Number
+		},
+
+		mode: function(/* Number[] */a){
+			//	summary:
+			//		Returns the mode from the passed array (number that appears the most often).
+			//		This is not the most efficient method, since it requires a double scan, but
+			//		is ensures accuracy.
+			var o = {}, r = 0, m = Number.MIN_VALUE;
+			dojo.forEach(a, function(v){
+				(o[v]!==undefined)?o[v]++:o[v]=1;
+			});
+
+			//	we did the lookup map because we need the number that appears the most.
+			for(var p in o){
+				if(m < o[p]){
+					m = o[p], r = p;
+				}
+			}
+			return r;	//	Number
+		},
+
+		sum: function(/* Number[] */a){
+			//	summary:
+			//		Return the sum of all the numbers in the passed array.  Does
+			//		not check to make sure values within a are NaN (should simply
+			//		return NaN).
+			var sum = 0;
+			dojo.forEach(a, function(n){
+				sum += n;
+			});
+			return sum;	//	Number
+		},
+
+		approxLin: function(a, pos){
+			//	summary:
+			//		Returns a linearly approximated value from an array using
+			//		a normalized float position value.
+			//	a: Number[]:
+			//		a sorted numeric array to be used for the approximation.
+			//	pos: Number:
+			//		a position number from 0 to 1. If outside of this range it
+			//		will be clamped.
+			//	returns: Number
+			var p = pos * (a.length - 1), t = Math.ceil(p), f = t - 1;
+			if(f < 0){ return a[0]; }
+			if(t >= a.length){ return a[a.length - 1]; }
+			return a[f] * (t - p) + a[t] * (p - f);	// Number
+		},
+
+		summary: function(a, alreadySorted){
+			//	summary:
+			//		Returns a non-parametric collection of summary statistics:
+			//		the classic five-number summary extended to the Bowley's
+			//		seven-figure summary.
+			//	a: Number[]:
+			//		a numeric array to be appraised.
+			//	alreadySorted: Boolean?:
+			//		a Boolean flag to indicated that the array is already sorted.
+			//		This is an optional flag purely to improve the performance.
+			//		If skipped, the array will be assumed unsorted.
+			//	returns: Object
+			if(!alreadySorted){
+				a = a.slice(0);								// copy the array
+				a.sort(function(a, b){ return a - b; });	// sort it properly
+			}
+			var	l = st.approxLin,
+				result = {
+					// the five-number summary
+					min:	a[0],				// minimum
+					p25:	l(a, 0.25),			// lower quartile
+					med:	l(a, 0.5),			// median
+					p75:	l(a, 0.75),			// upper quartile
+					max:	a[a.length - 1],	// maximum
+					// extended to the Bowley's seven-figure summary
+					p10:	l(a, 0.1),			// first decile
+					p90:	l(a, 0.9)			// last decile
+				};
+			return result;	// Object
+		}
+	});
 })();
-}
diff --git a/dojox/math/tests/BigInteger.js b/dojox/math/tests/BigInteger.js
new file mode 100644
index 0000000..29c61f3
--- /dev/null
+++ b/dojox/math/tests/BigInteger.js
@@ -0,0 +1,14 @@
+dojo.provide("dojox.math.tests.BigInteger");
+
+dojo.require("dojox.math.BigInteger");
+
+tests.register("dojox.math.tests.BigInteger",
+	[
+		function sanity_check(t){
+			var x = new dojox.math.BigInteger("abcd1234", 16),
+				y = new dojox.math.BigInteger("beef", 16),
+				z = x.mod(y);
+			t.is("b60c", z.toString(16));
+		}
+	]
+);
\ No newline at end of file
diff --git a/dojox/math/tests/main.js b/dojox/math/tests/main.js
new file mode 100644
index 0000000..a353e03
--- /dev/null
+++ b/dojox/math/tests/main.js
@@ -0,0 +1,12 @@
+dojo.provide("dojox.math.tests.main");
+
+try{
+	// functional block
+	dojo.require("dojox.math.tests.math");
+	dojo.require("dojox.math.tests.stats");
+	dojo.require("dojox.math.tests.round");
+	dojo.require("dojox.math.tests.BigInteger");
+	dojo.require("dojox.math.tests.random");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/math/tests/math.js b/dojox/math/tests/math.js
new file mode 100644
index 0000000..53c95dd
--- /dev/null
+++ b/dojox/math/tests/math.js
@@ -0,0 +1,29 @@
+dojo.provide("dojox.math.tests.math");
+
+dojo.require("dojox.math");
+
+(function(){
+	function approx(r){
+		return Math.floor(r * (1 << 30)) / (1 << 30);
+	}
+	tests.register("dojox.math.tests.factorial", [
+		// standard integer values
+		function fact0(t){ t.assertEqual(1, dojox.math.factorial(0)); },
+		function fact1(t){ t.assertEqual(1, dojox.math.factorial(1)); },
+		function fact2(t){ t.assertEqual(2, dojox.math.factorial(2)); },
+		function fact5(t){ t.assertEqual(120, dojox.math.factorial(5)); },
+		// almost integer
+		function fact5minus(t){ t.assertEqual(approx(119.999804750496600), approx(dojox.math.factorial(5-1/1048576))); },
+		function fact5plus(t){ t.assertEqual(approx(120.000195249840876), approx(dojox.math.factorial(5+1/1048576))); },
+		// geometric values
+		function factNeg1half(t){ t.assertEqual(Math.sqrt(Math.PI), dojox.math.factorial(-0.5)); },
+		function factPos1half(t){ t.assertEqual(approx(Math.sqrt(Math.PI)/2), approx(dojox.math.factorial(0.5))); },
+		function factNeg3halves(t){ t.assertEqual(approx(-Math.sqrt(Math.PI)*2), approx(dojox.math.factorial(-1.5))); },
+		function factNeg5halves(t){ t.assertEqual(approx(Math.sqrt(Math.PI)*4/3), approx(dojox.math.factorial(-2.5))); },
+		function factPos5halves(t){ t.assertEqual(approx(Math.sqrt(Math.PI)*15/8), approx(dojox.math.factorial(2.5))); },
+		// invalid values
+		function factNeg1(t){ t.assertEqual(NaN, dojox.math.factorial(-1)); },
+		function factNeg2(t){ t.assertEqual(NaN, dojox.math.factorial(-2)); }
+	]);
+	
+})();
diff --git a/dojox/math/tests/random.js b/dojox/math/tests/random.js
new file mode 100644
index 0000000..23f104c
--- /dev/null
+++ b/dojox/math/tests/random.js
@@ -0,0 +1,24 @@
+dojo.provide("dojox.math.tests.random");
+
+dojo.require("dojox.math.random.Simple");
+dojo.require("dojox.math.random.Secure");
+dojo.require("dojox.math.random.prng4");
+
+tests.register("dojox.math.tests.random",
+	[
+		function sanity_check_Simple(t){
+			var r = new dojox.math.random.Simple(),
+				a = new Array(256);
+			r.nextBytes(a);
+			t.f(dojo.every(a, function(x){ return x === a[0]; }));
+			r.destroy();
+		},
+		function sanity_check_Secure(t){
+			var r = new dojox.math.random.Secure(dojox.math.random.prng4),
+				a = new Array(256);
+			r.nextBytes(a);
+			t.f(dojo.every(a, function(x){ return x === a[0]; }));
+			r.destroy();
+		}
+	]
+);
diff --git a/dojox/math/tests/round.js b/dojox/math/tests/round.js
new file mode 100644
index 0000000..0c1c44b
--- /dev/null
+++ b/dojox/math/tests/round.js
@@ -0,0 +1,142 @@
+dojo.provide("dojox.math.tests.round");
+dojo.require("dojox.math.round");
+
+tests.register("dojox.math.tests.round", 
+	[
+		{
+			name: "round",
+			runTest: function(t){
+				t.is(0, dojox.math.round(0));
+				t.is(1, dojox.math.round(0.5));
+				t.is(-1, dojox.math.round(-0.5));
+				t.is(0.1, dojox.math.round(0.05, 1));
+				t.is(-0.1, dojox.math.round(-0.05, 1));
+				t.is(1.1, dojox.math.round(1.05, 1));
+				t.is(-1.1, dojox.math.round(-1.05, 1));
+				t.is(-162.3, dojox.math.round(-162.295, 2));
+				t.is(162.3, dojox.math.round(162.295, 2));
+			}
+		},
+		{
+			name: "round_multiple",
+			runTest: function(t){
+				t.is("123.455", dojox.math.round(123.4525, 2, 5));
+				t.is("123.45", dojox.math.round(123.452, 2, 5));
+				t.is("123.455", dojox.math.round(123.454, 2, 5));
+				t.is("123.455", dojox.math.round(123.456, 2, 5));
+				t.is("-123.45", dojox.math.round(-123.452, 2, 5));
+				t.is("-123.455", dojox.math.round(-123.4525, 2, 5));
+				t.is("-123.455", dojox.math.round(-123.454, 2, 5));
+				t.is("-123.455", dojox.math.round(-123.456, 2, 5));
+			}
+		},
+		{
+			name: "round_speleotrove",
+			runTest: function(t){
+				// submitted Mike Cowlishaw (IBM, CCLA), see http://speleotrove.com/decimal/#testcases
+				t.is(12345, dojox.math.round(12345 + -0.1), "radx200");
+				t.is(12345, dojox.math.round(12345 + -0.01), "radx201");
+				t.is(12345, dojox.math.round(12345 + -0.001), "radx202");
+				t.is(12345, dojox.math.round(12345 + -0.00001), "radx203");
+				t.is(12345, dojox.math.round(12345 + -0.000001), "radx204");
+				t.is(12345, dojox.math.round(12345 + -0.0000001), "radx205");
+				t.is(12345, dojox.math.round(12345 +  0), "radx206");
+				t.is(12345, dojox.math.round(12345 +  0.0000001), "radx207");
+				t.is(12345, dojox.math.round(12345 +  0.000001), "radx208");
+				t.is(12345, dojox.math.round(12345 +  0.00001), "radx209");
+				t.is(12345, dojox.math.round(12345 +  0.0001), "radx210");
+				t.is(12345, dojox.math.round(12345 +  0.001), "radx211");
+				t.is(12345, dojox.math.round(12345 +  0.01), "radx212");
+				t.is(12345, dojox.math.round(12345 +  0.1), "radx213");
+
+				t.is(12346, dojox.math.round(12346 +  0.49999), "radx215");
+				t.is(12347, dojox.math.round(12346 +  0.5), "radx216");
+				t.is(12347, dojox.math.round(12346 +  0.50001), "radx217");
+				
+				t.is(12345, dojox.math.round(12345 +  0.4), "radx220");
+				t.is(12345, dojox.math.round(12345 +  0.49), "radx221");
+				t.is(12345, dojox.math.round(12345 +  0.499), "radx222");
+				t.is(12345, dojox.math.round(12345 +  0.49999), "radx223");
+				t.is(12346, dojox.math.round(12345 +  0.5), "radx224");
+				t.is(12346, dojox.math.round(12345 +  0.50001), "radx225");
+				t.is(12346, dojox.math.round(12345 +  0.5001), "radx226");
+				t.is(12346, dojox.math.round(12345 +  0.501), "radx227");
+				t.is(12346, dojox.math.round(12345 +  0.51), "radx228");
+				t.is(12346, dojox.math.round(12345 +  0.6), "radx229");
+				
+				//negatives
+				t.is(-12345, dojox.math.round(-12345 + -0.1), "rsux200");
+				t.is(-12345, dojox.math.round(-12345 + -0.01), "rsux201");
+				t.is(-12345, dojox.math.round(-12345 + -0.001), "rsux202");
+				t.is(-12345, dojox.math.round(-12345 + -0.00001), "rsux203");
+				t.is(-12345, dojox.math.round(-12345 + -0.000001), "rsux204");
+				t.is(-12345, dojox.math.round(-12345 + -0.0000001), "rsux205");
+				t.is(-12345, dojox.math.round(-12345 +  0), "rsux206");
+				t.is(-12345, dojox.math.round(-12345 +  0.0000001), "rsux207");
+				t.is(-12345, dojox.math.round(-12345 +  0.000001), "rsux208");
+				t.is(-12345, dojox.math.round(-12345 +  0.00001), "rsux209");
+				t.is(-12345, dojox.math.round(-12345 +  0.0001), "rsux210");
+				t.is(-12345, dojox.math.round(-12345 +  0.001), "rsux211");
+				t.is(-12345, dojox.math.round(-12345 +  0.01), "rsux212");
+				t.is(-12345, dojox.math.round(-12345 +  0.1), "rsux213");
+				
+				t.is(-12346, dojox.math.round(-12346 +  0.49999), "rsux215");
+				t.is(-12346, dojox.math.round(-12346 +  0.5), "rsux216");
+				t.is(-12345, dojox.math.round(-12346 +  0.50001   ), "rsux217");
+				
+				t.is(-12345, dojox.math.round(-12345 +  0.4), "rsux220");
+				t.is(-12345, dojox.math.round(-12345 +  0.49), "rsux221");
+				t.is(-12345, dojox.math.round(-12345 +  0.499), "rsux222");
+				t.is(-12345, dojox.math.round(-12345 +  0.49999), "rsux223");
+				t.is(-12345, dojox.math.round(-12345 +  0.5), "rsux224");
+				t.is(-12344, dojox.math.round(-12345 +  0.50001), "rsux225");
+				t.is(-12344, dojox.math.round(-12345 +  0.5001), "rsux226");
+				t.is(-12344, dojox.math.round(-12345 +  0.501), "rsux227");
+				t.is(-12344, dojox.math.round(-12345 +  0.51), "rsux228");
+				t.is(-12344, dojox.math.round(-12345 +  0.6), "rsux229");
+				
+				t.is(12345, dojox.math.round(  12345 /  1), "rdvx401");
+				t.is(12344, dojox.math.round(  12345 /  1.0001), "rdvx402");
+				t.is(12333, dojox.math.round(  12345 /  1.001), "rdvx403");
+				t.is(12223, dojox.math.round(  12345 /  1.01), "rdvx404");
+				t.is(11223, dojox.math.round(  12345 /  1.1), "rdvx405");
+
+				t.is(3088.8, dojox.math.round( 12355 /  4, 1), "rdvx406");
+				t.is(3086.3, dojox.math.round( 12345 /  4, 1), "rdvx407");
+				t.is(3088.7, dojox.math.round( 12355 /  4.0001, 1), "rdvx408");
+				t.is(3086.2, dojox.math.round( 12345 /  4.0001, 1), "rdvx409");
+				t.is(2519.4, dojox.math.round( 12345 /  4.9, 1), "rdvx410");
+				t.is(2473.9, dojox.math.round( 12345 /  4.99, 1), "rdvx411");
+				t.is(2469.5, dojox.math.round( 12345 /  4.999, 1), "rdvx412");
+				t.is(2469.0, dojox.math.round( 12345 /  4.9999, 1), "rdvx413");
+				t.is(2469, dojox.math.round( 12345 /  5, 1), "rdvx414");
+				t.is(2469.0, dojox.math.round( 12345 /  5.0001, 1), "rdvx415");
+				t.is(2468.5, dojox.math.round( 12345 /  5.001, 1), "rdvx416");
+				t.is(2464.1, dojox.math.round( 12345 /  5.01, 1), "rdvx417");
+				t.is(2420.6, dojox.math.round( 12345 /  5.1, 1), "rdvx418");
+
+				t.is(12345, dojox.math.round(  12345 *  1), "rmux401");
+				t.is(12346, dojox.math.round(  12345 *  1.0001), "rmux402");
+				t.is(12357, dojox.math.round(  12345 *  1.001), "rmux403");
+				t.is(12468, dojox.math.round(  12345 *  1.01), "rmux404");
+				t.is(13580, dojox.math.round(  12345 *  1.1), "rmux405");
+				t.is(49380, dojox.math.round(  12345 *  4), "rmux406");
+				t.is(49381, dojox.math.round(  12345 *  4.0001), "rmux407");
+				t.is(60491, dojox.math.round(  12345 *  4.9), "rmux408");
+				t.is(61602, dojox.math.round(  12345 *  4.99), "rmux409");
+				t.is(61713, dojox.math.round(  12345 *  4.999), "rmux410");
+				t.is(61724, dojox.math.round(  12345 *  4.9999), "rmux411");
+				t.is(61725, dojox.math.round(  12345 *  5), "rmux412");
+				t.is(61726, dojox.math.round(  12345 *  5.0001), "rmux413");
+				t.is(61737, dojox.math.round(  12345 *  5.001), "rmux414");
+				t.is(61848, dojox.math.round(  12345 *  5.01), "rmux415");
+/*
+				t.is(1.4814E+5, dojox.math.round(  12345 *  12), "rmux416");
+				t.is(1.6049E+5, dojox.math.round(  12345 *  13), "rmux417");
+				t.is(1.4826E+5, dojox.math.round(  12355 *  12), "rmux418");
+				t.is(1.6062E+5, dojox.math.round(  12355 *  13), "rmux419");
+*/
+			}
+		}
+	]
+);
diff --git a/dojox/math/tests/runTests.html b/dojox/math/tests/runTests.html
new file mode 100644
index 0000000..cb69942
--- /dev/null
+++ b/dojox/math/tests/runTests.html
@@ -0,0 +1,9 @@
+<html>
+	<head>
+		<title>DojoX Functional Unit Test Runner</title>
+		<meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.math.tests.main" />
+	</head>
+	<body>
+		<p>Redirecting to D.O.H runner.</p>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/math/tests/stats.js b/dojox/math/tests/stats.js
new file mode 100644
index 0000000..06cf500
--- /dev/null
+++ b/dojox/math/tests/stats.js
@@ -0,0 +1,102 @@
+dojo.provide("dojox.math.tests.stats");
+dojo.require("dojox.math.stats");
+
+(function(){
+	var epsilon = 1e-6;
+		eq = function(t, a, b){
+			t.t(!isNaN(a) && ! isNaN(b));
+			var delta = Math.abs((a - b) / (a + b));
+			t.t(isNaN(delta) || delta < epsilon);
+		},
+		a1 = [1, 2, 1],
+		a2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
+		a3 = [0, 5, 4, 5, 8, 20, 21, 20, 20, 8, 9, 15, 12, 11, 18, 7, 19, 13, 13, 4];
+	tests.register("dojox.math.stats.tests", [
+		function sd(t){
+			t.assertEqual(6.335613624582861, dojox.math.stats.sd(a3));
+		},
+		function variance(t){
+			t.assertEqual(40.139999999999986, dojox.math.stats.variance(a3));
+		},
+		function mean(t){
+			t.assertEqual(11.6, dojox.math.stats.mean(a3));
+		},
+		function min(t){
+			t.assertEqual(0, dojox.math.stats.min(a3));
+		},
+		function max(t){
+			t.assertEqual(21, dojox.math.stats.max(a3));
+		},
+		function median(t){
+			t.assertEqual(12, dojox.math.stats.median(a3));
+		},
+		function mode(t){
+			t.assertEqual(20, dojox.math.stats.mode(a3));
+		},
+		function sum(t){
+			t.assertEqual(232, dojox.math.stats.sum(a3));
+		}
+	]);
+
+	var points = [
+		{x:1, y:42}, {x:1, y:7}, {x:2, y:17}, {x:4, y:41},
+		{x:5, y:60}, {x:7, y:19}, {x:7, y:16}, {x:8, y:15},
+		{x:10, y:29}, {x:11, y:1}, {x:12, y:10}, {x:13, y:22},
+		{x:13, y:16}, {x:14, y:29}, {x:20, y:37}, {x:21, y:10},
+		{x:21, y:60}, {x:22, y:4}, {x:22, y:33}, {x:25, y:52},
+		{x:25, y:32}, {x:25, y:18}, {x:27, y:46}, {x:28, y:2},
+		{x:28, y:56}, {x:29, y:12}, {x:32, y:53}, {x:32, y:14},
+		{x:36, y:18}, {x:37, y:23}, {x:38, y:18}, {x:45, y:37},
+		{x:48, y:43}, {x:50, y:9}, {x:53, y:48}, {x:55, y:60},
+		{x:55, y:28}, {x:57, y:19}, {x:58, y:48}, {x:58, y:29}
+	];
+	tests.register("dojox.math.stats.tests.bestFit", [
+		function bf(t){
+			var result = dojox.math.stats.bestFit(points);
+			console.log(result);
+			t.assertEqual(0.208, Math.round(result.slope*1000)/1000);
+			t.assertEqual(22.829, Math.round(result.intercept*1000)/1000);
+			t.assertEqual(0.045, Math.round(result.r2*1000)/1000);
+			t.assertEqual(0.212, Math.round(result.r*1000)/1000);
+		}
+	]);
+	tests.register("dojox.math.stats.tests.forecast", [
+		function _42(t){
+			t.assertEqual(31.580951899655346, dojox.math.stats.forecast(points, 42));
+		},
+		function _54(t){
+			t.assertEqual(34.08152295859065, dojox.math.stats.forecast(points, 54));
+		},
+		function _201(t){
+			t.assertEqual(64.71351843054812, dojox.math.stats.forecast(points, 201));
+		}
+	]);
+	tests.register("dojox.math.stats.tests.approx", [
+		function approx1(t){ eq(t, dojox.math.stats.approxLin(a1, 0), 1); },
+		function approx2(t){ eq(t, dojox.math.stats.approxLin(a1, 0.5), 2); },
+		function approx3(t){ eq(t, dojox.math.stats.approxLin(a1, 1), 1); },
+		function approx4(t){ eq(t, dojox.math.stats.approxLin(a1, 0.25), 1.5); },
+		function approx5(t){ eq(t, dojox.math.stats.approxLin(a1, 0.75), 1.5); },
+		function approx6(t){ eq(t, dojox.math.stats.approxLin(a1, 0.1), 1.2); },
+		function summary1(t){
+			var s = dojox.math.stats.summary(a1);
+			eq(t, s.min, 1);
+			eq(t, s.p10, 1);
+			eq(t, s.p25, 1);
+			eq(t, s.med, 1);
+			eq(t, s.p75, 1.5);
+			eq(t, s.p90, 1.8);
+			eq(t, s.max, 2);
+		},
+		function summary2(t){
+			var s = dojox.math.stats.summary(a2, true);
+			eq(t, s.min, 0);
+			eq(t, s.p10, 2);
+			eq(t, s.p25, 5);
+			eq(t, s.med, 10);
+			eq(t, s.p75, 15);
+			eq(t, s.p90, 18);
+			eq(t, s.max, 20);
+		}
+	]); 
+})();
diff --git a/dojox/mdnd/AreaManager.js b/dojox/mdnd/AreaManager.js
new file mode 100644
index 0000000..c10034a
--- /dev/null
+++ b/dojox/mdnd/AreaManager.js
@@ -0,0 +1,707 @@
+dojo.provide("dojox.mdnd.AreaManager");
+dojo.require("dojox.mdnd.Moveable");
+
+dojo.declare(
+	"dojox.mdnd.AreaManager",
+	null,
+{
+	// summary:
+	//		Drag And Drop manager
+
+	// autoRefresh: Boolean
+	//		Enable the refresh of registered areas on drag start.
+	autoRefresh: true,
+
+
+	// areaClass: String
+	//		CSS class enabled an area if areaClass is defined
+	areaClass: "dojoxDndArea",
+
+	// dragHandleClass: String
+	//		CSS class enabled a drag handle.
+	dragHandleClass: "dojoxDragHandle",
+
+	constructor: function(){
+		// summary:
+		//		Constructor of AreaManager class.
+		//		Initialize arrays, connects and subscribes.
+
+		//console.log("dojox.mdnd.AreaManager ::: constructor");
+		this._areaList = [];
+		this.resizeHandler = dojo.connect(dojo.global,"onresize", this, function(){
+			this._dropMode.updateAreas(this._areaList);
+		});
+
+		this._oldIndexArea = this._currentIndexArea = this._oldDropIndex = this._currentDropIndex = this._sourceIndexArea = this._sourceDropIndex = -1;
+	},
+
+	init: function(){
+		// summary:
+		//		Initialize the manager by calling the registerByClass method
+
+		//console.log("dojox.mdnd.AreaManager ::: init");
+		this.registerByClass();
+	},
+
+	registerByNode: function(/*DOMNode*/area, /*Boolean*/notInitAreas){
+		// summary:
+		//		To register Dnd Area : insert the DndArea using the specific sort of dropMode.
+		// area:
+		//		a DOM node corresponding to the Dnd Area
+		// notInitAreas:
+		//		if false or undefined, init the areas.
+
+		//console.log("dojox.mdnd.AreaManager ::: registerByNode", area);
+		var index = this._getIndexArea(area);
+		if(area && index == -1){
+			var acceptType = area.getAttribute("accept");
+			var accept = (acceptType) ? acceptType.split(/\s*,\s*/) : ["text"];
+			var obj = {
+				'node': area,
+				'items': [],
+				'coords': {},
+				'margin': null,
+				'accept': accept,
+				'initItems': false
+			};
+			dojo.forEach(this._getChildren(area), function(item){
+				this._setMarginArea(obj, item);
+				obj.items.push(this._addMoveableItem(item));
+			}, this);
+			this._areaList = this._dropMode.addArea(this._areaList, obj);
+			if(!notInitAreas){
+				this._dropMode.updateAreas(this._areaList);
+			}
+			dojo.publish("/dojox/mdnd/manager/register",[area]);
+		}
+	},
+
+	registerByClass: function(){
+		// summary:
+		//		Register all Dnd Areas identified by the attribute areaClass :
+		//		insert Dnd Areas using the specific sort of dropMode.
+
+		//console.log("dojox.mdnd.AreaManager ::: registerByClass");
+		dojo.query('.'+this.areaClass).forEach(function(area){
+			this.registerByNode(area, true);
+		}, this);
+		this._dropMode.updateAreas(this._areaList);
+	},
+
+	unregister: function(/*DOMNode*/area){
+		// summary:
+		//		Unregister a D&D Area and its children into the AreaManager.
+		// area:
+		//		A node corresponding to the D&D Area.
+		// returns:
+		//		True if the area is found and unregistered.
+
+		//console.log("dojox.mdnd.AreaManager ::: unregister");
+		var index = this._getIndexArea(area);
+		if(index != -1){
+			dojo.forEach(this._areaList[index].items, function(item){
+				this._deleteMoveableItem(item);
+			}, this);
+			this._areaList.splice(index,1);
+			// refresh target area
+			this._dropMode.updateAreas(this._areaList);
+			return true; // Boolean
+		}
+		return false; // Boolean
+	},
+
+	_addMoveableItem: function(/*DOMNode*/node){
+		// summary:
+		//		Create a draggable item with a DOM node.
+		// node:
+		//		A child of the D&D Area.
+		// returns:
+		//		The draggable item.
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.AreaManager ::: _addMoveableItem");
+		node.setAttribute("tabIndex", "0");
+		var handle = this._searchDragHandle(node);
+		var moveable = new dojox.mdnd.Moveable({ 'handle': handle, 'skip': true }, node);
+		// add a css style :
+		dojo.addClass(handle || node, "dragHandle");
+		var type = node.getAttribute("dndType");
+		var item = {
+			'item': moveable,
+			'type': type ? type.split(/\s*,\s*/) : ["text"],
+			'handlers': [dojo.connect(moveable, "onDragStart", this, "onDragStart")]
+		}
+		// connect to the uninitialize method of dijit._Widget to delete a moveable before a destruct
+		if(dijit && dijit.byNode){
+			var widget = dijit.byNode(node);
+			if(widget){
+				item.type = widget.dndType ? widget.dndType.split(/\s*,\s*/) : ["text"];
+				item.handlers.push(
+					dojo.connect(widget, "uninitialize", this, function(){
+						this.removeDragItem(node.parentNode, moveable.node);
+					})
+				);
+			}
+		}
+		return item; // Object
+	},
+
+	_deleteMoveableItem: function(/*Object*/ objItem){
+		// summary:
+		//		Delete the Moveable object associated with a node.
+		// item:
+		//		A moveable Object.
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.AreaManager ::: _deleteMoveableItem", objItem);
+		// disconnect the handle
+		dojo.forEach(objItem.handlers, function(handler){
+			dojo.disconnect(handler);
+		});
+		// delete css style :
+		var node = objItem.item.node,
+			handle = this._searchDragHandle(node);
+		dojo.removeClass(handle || node, "dragHandle");
+		// call destroy of Moveable class
+		objItem.item.destroy();
+	},
+
+	_getIndexArea: function(/*DOMNode*/area){
+		// summary:
+		//		Get the index of an area.
+	 	// area:
+	 	//		A moveable Object.
+	 	// returns:
+	 	//		area index or -1
+	 	// tags:
+	 	//		protected
+
+		//console.log("dojox.mdnd.AreaManager ::: _getIndexArea");
+		if(area){
+			for(var i = 0; i < this._areaList.length; i++){
+				if(this._areaList[i].node === area){
+					return i;	// Integer
+				}
+			}
+		}
+		return -1;	// Integer
+	},
+
+	_searchDragHandle: function(/*DOMNode*/node){
+		// summary:
+		//		Return the node which contains the first specific CSS class handle.
+		// node:
+		//		A child of the D&D Area.
+		// returns:
+		//		The drag handle node.
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.AreaManager ::: _searchDragHandle");
+		if(node){
+			var cssArray = this.dragHandleClass.split(' '),
+				length = cssArray.length,
+				queryCss = "";
+			dojo.forEach(cssArray, function(css, i){
+				queryCss += "." + css;
+				if(i != length - 1){
+					queryCss += ", ";
+				}
+			});
+			return dojo.query(queryCss, node)[0]; // DomNode
+		}
+	},
+
+	addDragItem: function(/*DOMNode*/area, /*DOMNode*/node, /*Integer*/index, /*Boolean*/notCheckParent){
+		// summary:
+		//		To add an item programmatically.
+		// area:
+		//		a node corresponding to the D&D Area
+		// node:
+		//		the node which has to be treated.
+		// index:
+		//		the place in the area
+		// noCheckParent:
+		//		if true, doesn't check if node has a parent.
+		// returns:
+		//		True if the node has been inserted else false.
+
+		//console.log("dojox.mdnd.AreaManager ::: addDragItem");
+		var add = true;
+		if(!notCheckParent){
+			add = area && node && (node.parentNode === null || (node.parentNode && node.parentNode.nodeType !== 1));
+		}
+		if(add){
+			var indexArea = this._getIndexArea(area);
+			if(indexArea !== -1){
+				var item = this._addMoveableItem(node),
+					items = this._areaList[indexArea].items;
+				if(0 <= index && index < items.length){
+					var firstListChild = items.slice(0, index),
+						lastListChild = items.slice(index, items.length);
+					firstListChild[firstListChild.length] = item;
+					this._areaList[indexArea].items = firstListChild.concat(lastListChild);
+					area.insertBefore(node, items[index].item.node);
+				}
+				else{
+					this._areaList[indexArea].items.push(item);
+					area.appendChild(node);
+				}
+				this._setMarginArea(this._areaList[indexArea], node);
+				this._areaList[indexArea].initItems = false;
+				return true;	// Boolean
+			}
+		}
+		return false;	// Boolean
+	},
+
+	removeDragItem: function(/*DOMNode*/area, /*DOMNode*/node){
+		// summary:
+		//		Delete a moveable item programmatically. The node is removed from the area.
+		// area:
+		//		A node corresponding to the DndArea.
+		// node:
+		//		The node which has to be treated.
+		// returns:
+		//		the removed node
+
+		//console.log("dojox.mdnd.AreaManager ::: removeDragItem");
+		var index = this._getIndexArea(area);
+		if(area && index !== -1){
+			var items = this._areaList[index].items;
+			for(var j = 0; j < items.length; j++){
+				if(items[j].item.node === node){
+					this._deleteMoveableItem(items[j]);
+					// delete item of the array
+					items.splice(j, 1);
+					return area.removeChild(node); // Object
+				}
+			}
+		}
+		return null;
+	},
+
+	_getChildren: function(/*DOMNode*/area){
+		// summary:
+		//		Get the children of a D&D area.
+		// area:
+		//		A DnD area.
+		// returns:
+		//		The children of a DnD area
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.AreaManager ::: _getChildren");
+		var children = [];
+		dojo.forEach(area.childNodes, function(child){
+			// delete \n
+			if(child.nodeType == 1){
+				if(dijit && dijit.byNode){
+					var widget = dijit.byNode(child);
+					if(widget){
+						if(!widget.dragRestriction){
+							children.push(child);
+						}
+					}
+					else{
+						children.push(child);
+					}
+				}
+				else{
+					children.push(child);
+				}
+			}
+		});
+		return children;	//Array
+	},
+
+	_setMarginArea: function(/*Object*/area,/*DOMNode*/node){
+		// summary:
+		//		Set the value of margin in the data type of areaManager
+		//		only when the margin has never been computed.
+		// area:
+		//		The object of a D&D Area.
+		// node:
+		//		The node which contains margins
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.AreaManager ::: _setMarginArea");
+		if(area && area.margin === null && node){
+			area.margin = dojo._getMarginExtents(node);
+		}
+	},
+
+	findCurrentIndexArea: function(/*Object*/coords, /*Object*/size){
+		// summary:
+		//		find the nearest target area according to coordinates.
+		//		Coordinates are representing by an object : for example, {'x':10,'y':10}
+		// coords:
+		//		an object encapsulating X and Y position
+		// size:
+		//		an object encapsulating the area size
+		// returns:
+		//		an index of area
+
+		//console.log("dojox.mdnd.AreaManager ::: findCurrentIndexArea");
+		this._oldIndexArea = this._currentIndexArea;
+		this._currentIndexArea = this._dropMode.getTargetArea(this._areaList, coords, this._currentIndexArea);
+		if(this._currentIndexArea != this._oldIndexArea){
+			if(this._oldIndexArea != -1){
+				this.onDragExit(coords, size);
+			}
+			if(this._currentIndexArea != -1){
+				this.onDragEnter(coords, size);
+			}
+		}
+		return this._currentIndexArea;	//Integer
+	},
+
+	_isAccepted: function(/*Array*/ type, /*Array*/ accept){
+		// summary:
+		//		True if user can drop widget on this node.
+		// type:
+		//		Array containing item type
+		// accept:
+		//		Array containing types
+		this._accept = false;
+		for(var i = 0; i < accept.length; ++i){
+			for(var j = 0; j < type.length;++j){
+				if(type[j] == accept[i]){
+					this._accept = true;
+					break;
+				}
+			}
+		}
+	},
+
+	onDragStart: function(/*DOMNode*/node, /*Object*/coords, /*Object*/size){
+		// summary:
+		//		Initialize the drag (see dojox.mdnd.Moveable.initOffsetDrag())
+		// node:
+		//		The node which is about to be dragged
+		// coords:
+		//		an object encapsulating X and Y position
+		// size:
+		//		an object encapsulating width and height values
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.AreaManager ::: onDragStart");
+		if(this.autoRefresh){
+			this._dropMode.updateAreas(this._areaList);
+		}
+
+		// Create the cover :
+		var _html = (dojo.isWebKit) ? dojo.body() : dojo.body().parentNode;
+		if(!this._cover){
+			this._cover = dojo.create('div', {
+				'class': "dndCover"
+			});
+			this._cover2 = dojo.clone(this._cover);
+			dojo.addClass(this._cover2, "dndCover2");
+		}
+		var h = _html.scrollHeight+"px";
+		this._cover.style.height = this._cover2.style.height = h;
+		dojo.body().appendChild(this._cover);
+		dojo.body().appendChild(this._cover2);
+
+		this._dragStartHandler = dojo.connect(node.ownerDocument, "ondragstart", dojo, "stopEvent");
+		// to know the source
+		this._sourceIndexArea = this._lastValidIndexArea = this._currentIndexArea = this._getIndexArea(node.parentNode);
+		// delete the dragItem into the source area
+		var sourceArea = this._areaList[this._sourceIndexArea];
+		var children = sourceArea.items;
+		for(var i = 0; i < children.length; i++){
+			if(children[i].item.node == node){
+				this._dragItem = children[i];
+				this._dragItem.handlers.push(dojo.connect(this._dragItem.item, "onDrag", this, "onDrag"));
+				this._dragItem.handlers.push(dojo.connect(this._dragItem.item, "onDragEnd", this, "onDrop"));
+				children.splice(i,1);
+				this._currentDropIndex = this._sourceDropIndex = i;
+				break;
+			}
+		}
+		var nodeRef = null;
+		if(this._sourceDropIndex !== sourceArea.items.length){
+			nodeRef = sourceArea.items[this._sourceDropIndex].item.node;
+		}
+		// IE7 OPTIMIZATION
+		if(dojo.isIE > 7){
+			// connect these events on the cover
+			this._eventsIE7 = [
+				dojo.connect(this._cover, "onmouseover", dojo, "stopEvent"),
+				dojo.connect(this._cover, "onmouseout", dojo, "stopEvent"),
+				dojo.connect(this._cover, "onmouseenter", dojo, "stopEvent"),
+				dojo.connect(this._cover, "onmouseleave", dojo, "stopEvent")
+			];
+		}
+
+		var s = node.style;
+		s.left = coords.x+"px";
+		s.top = coords.y+"px";
+		// attach the node to the cover
+		if(s.position == "relative" || s.position == ""){
+			s.position = "absolute"; // enforcing the absolute mode
+		}
+		this._cover.appendChild(node);
+
+		this._dropIndicator.place(sourceArea.node, nodeRef, size);
+		// add a style to place the _dragNode in foreground
+		dojo.addClass(node, "dragNode");
+		// A dragged node is always draggable in this source area.
+		this._accept = true;
+		dojo.publish("/dojox/mdnd/drag/start",[node, sourceArea, this._sourceDropIndex]);
+	},
+
+	onDragEnter: function(/*Object*/coords, /*Object*/size){
+		// summary:
+		//		Optionally called by the getTargetArea method of TargetFinder class.
+		// coords:
+		//		coordinates of the dragged Node.
+		// size:
+		//		size of the dragged Node.
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.AreaManager ::: onDragEnter", coords, size);
+		if(this._currentIndexArea === this._sourceIndexArea){
+			this._accept = true;
+		}
+		else{
+			this._isAccepted(this._dragItem.type, this._areaList[this._currentIndexArea].accept);
+		}
+	},
+
+	onDragExit: function(/*Object*/coords, /*Object*/size){
+		// summary:
+		//		Optionally called by the getTargetArea method of TargetFinder class.
+		// coords:
+		//		coordinates of the dragged Node.
+		// size:
+		//		size of the dragged Node.
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.AreaManager ::: onDragExit");
+		this._accept = false;
+	},
+
+	onDrag: function(/*DOMNode*/node, /*Object*/coords, /*Object*/size, /*Object*/mousePosition){
+		// summary:
+		//		Occurs when the dojo.dnd.Moveable.onDrag is fired.
+		//		Search the nearest target area and called the placeDropIndicator
+		// node:
+		//		The node which is dragged
+		// coords:
+		//		an object encapsulating X and Y position
+		// size:
+		//		an object encapsulating width and height values
+		// mousePosition:
+		//		coordinates of mouse
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.AreaManager ::: onDrag", node, ",", coords,size);
+		var coordinates = this._dropMode.getDragPoint(coords, size, mousePosition);
+		this.findCurrentIndexArea(coordinates, size);
+		if(this._currentIndexArea !== -1 && this._accept){
+			this.placeDropIndicator(coordinates, size);
+		}
+	},
+
+	placeDropIndicator: function(/*Object*/coords, /*Object*/size){
+		// summary:
+		//		Search the right place to insert the dropIndicator and display the dropIndicator.
+		// coords:
+		//		an object encapsulating X and Y position
+		// size:
+		//		an object encapsulating width and height values
+		// returns:
+		//		the current drop index
+
+		//console.log("dojox.mdnd.AreaManager ::: placeDropIndicator");
+		//keep old drop Index
+		this._oldDropIndex = this._currentDropIndex;
+		// calculate all children marker (see VerticalDropMode.initItems())
+		var area = this._areaList[this._currentIndexArea];
+		if(!area.initItems){
+			this._dropMode.initItems(area);
+		}
+		//get the index where the drop has to be placed.
+		this._currentDropIndex = this._dropMode.getDropIndex(area, coords);
+		if(!(this._currentIndexArea === this._oldIndexArea && this._oldDropIndex === this._currentDropIndex)){
+			this._placeDropIndicator(size);
+		}
+		return this._currentDropIndex;	//Integer
+	},
+
+	_placeDropIndicator: function(/*Object*/size){
+		// summary:
+		//		place the dropIndicator
+		// size:
+		//		an object encapsulating width and height values
+		// tags:
+		//		protected
+
+		var oldArea = this._areaList[this._lastValidIndexArea];
+		var currentArea = this._areaList[this._currentIndexArea];
+		//refresh the previous area after moving out the drop indicator
+		this._dropMode.refreshItems(oldArea, this._oldDropIndex, size, false);
+		// place dropIndicator
+		var node = null;
+		if(this._currentDropIndex != -1){
+			node = currentArea.items[this._currentDropIndex].item.node;
+		}
+		this._dropIndicator.place(currentArea.node, node);
+		this._lastValidIndexArea = this._currentIndexArea;
+		//refresh the current area after placing the drop indicator
+		this._dropMode.refreshItems(currentArea, this._currentDropIndex, size, true);
+	},
+
+	onDropCancel: function(){
+		// summary:
+		//		Cancel the drop.
+		//		The dragNode returns into the source.
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.AreaManager ::: onDropCancel");
+		if(!this._accept){
+			var index = this._getIndexArea(this._dropIndicator.node.parentNode);
+			if(index != -1){
+				this._currentIndexArea = index;
+			}
+			else{
+				// case if the dropIndicator is in the area which has been unregistered during the drag.
+				// chose by default the first area.
+				this._currentIndexArea = 0;
+			}
+		}
+	},
+
+	onDrop: function(/*DOMNode*/node){
+		// summary:
+		//		Drop the dragged item where the dropIndicator is displayed.
+		// node:
+		//		The node which is about to be dropped
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.AreaManager ::: onDrop");
+		//dropCancel
+		this.onDropCancel();
+		var targetArea = this._areaList[this._currentIndexArea];
+		dojo.removeClass(node, "dragNode");
+		var style = node.style;
+		style.position = "relative";
+		style.left = "0";
+		style.top = "0";
+		style.width = "auto";
+		if(targetArea.node == this._dropIndicator.node.parentNode){
+			targetArea.node.insertBefore(node, this._dropIndicator.node);
+		}
+		else{
+			// case if the dropIndicator is in the area which has been unregistered during the drag.
+			targetArea.node.appendChild(node);
+			this._currentDropIndex = targetArea.items.length;
+		}
+		// add child into the new target area.
+		var indexChild = this._currentDropIndex;
+		if(indexChild == -1){
+			indexChild = targetArea.items.length;
+		}
+		var children = targetArea.items;
+		var firstListArea = children.slice(0, indexChild);
+		var lastListArea = children.slice(indexChild, children.length);
+		firstListArea[firstListArea.length] = this._dragItem;
+		targetArea.items = firstListArea.concat(lastListArea);
+
+		this._setMarginArea(targetArea, node);
+		dojo.forEach(this._areaList, function(obj){
+			obj.initItems = false;
+		});
+		// disconnect onDrop handler
+		dojo.disconnect(this._dragItem.handlers.pop());
+		dojo.disconnect(this._dragItem.handlers.pop());
+		this._resetAfterDrop();
+		// remove the cover
+		if(this._cover){
+			dojo.body().removeChild(this._cover);
+			dojo.body().removeChild(this._cover2);
+		}
+		dojo.publish("/dojox/mdnd/drop",[node, targetArea, indexChild]);
+	},
+
+	_resetAfterDrop: function(){
+		// summary:
+		//		reset manager properties after dropping an item
+		// tags:
+		//		protected
+
+		this._accept = false;
+		this._dragItem = null;
+		this._currentDropIndex = -1;
+		this._currentIndexArea = -1;
+		this._oldDropIndex = -1;
+		this._sourceIndexArea = -1;
+		this._sourceDropIndex = -1;
+		this._dropIndicator.remove();
+		if(this._dragStartHandler){
+			dojo.disconnect(this._dragStartHandler);
+		}
+		if(dojo.isIE > 7){
+			dojo.forEach(this._eventsIE7, dojo.disconnect);
+		}
+	},
+
+	destroy: function(){
+		// summary:
+		//		Destroy the component.
+
+		//console.log("dojox.mdnd.AreaManager ::: destroy");
+		//see implementation of unregister()
+		while(this._areaList.length > 0){
+			if(!this.unregister(this._areaList[0].node)){
+				throw new Error("Error while destroying AreaManager");
+			}
+		}
+		dojo.disconnect(this.resizeHandler);
+		this._dropIndicator.destroy();
+		this._dropMode.destroy();
+		if(dojox.mdnd.autoScroll){
+			dojox.mdnd.autoScroll.destroy();
+		}
+		if(this.refreshListener){
+			dojo.unsubscribe(this.refreshListener);
+		}
+		// destroy the cover
+		if(this._cover){
+			dojo._destroyElement(this._cover);
+			dojo._destroyElement(this._cover2);
+			delete this._cover;
+			delete this._cover2;
+		}
+	}
+});
+
+if(dijit && dijit._Widget){
+	//	Add a new property to widget
+	dojo.extend(dijit._Widget, {
+		// dndType: String
+		//		Defines a type of widget.
+		dndType : "text"
+	});
+}
+
+dojox.mdnd._areaManager = null;
+dojox.mdnd.areaManager = function(){
+	// summary:
+	//		Returns the current areaManager, creates one if it is not created yet.
+	if(!dojox.mdnd._areaManager){
+		dojox.mdnd._areaManager = new dojox.mdnd.AreaManager();
+	}
+	return dojox.mdnd._areaManager;	// Object
+};
diff --git a/dojox/mdnd/AutoScroll.js b/dojox/mdnd/AutoScroll.js
new file mode 100644
index 0000000..241ac74
--- /dev/null
+++ b/dojox/mdnd/AutoScroll.js
@@ -0,0 +1,195 @@
+dojo.provide("dojox.mdnd.AutoScroll");
+
+dojo.declare(
+	"dojox.mdnd.AutoScroll", 
+	null, 
+{
+	// summary:
+	//		Activate scrolling while dragging a widget.
+
+	// interval: Integer
+	//		default mouse move offset
+	interval: 3,
+
+	// recursiveTimer: Integer
+	recursiveTimer: 10,
+
+	// marginMouse: Integer
+	//		Default mouse margin
+	marginMouse: 50,
+
+	constructor: function(){
+		//console.log("dojox.mdnd.AutoScroll ::: constructor ");
+		this.resizeHandler = dojo.connect(dojo.global,"onresize", this, function(){
+			this.getViewport();
+		});
+		dojo.ready(dojo.hitch(this, "init"));
+	},
+
+	init: function(){
+		//console.log("dojox.mdnd.AutoScroll ::: init ");
+		this._html = (dojo.isWebKit) ? dojo.body() : dojo.body().parentNode;
+		this.getViewport();	
+	},
+
+	getViewport:function(){
+		// summary:
+		//		Set the visible part of the window. Varies accordion to Navigator.
+
+		//console.log("dojox.mdnd.AutoScroll ::: getViewport ");
+		var d = dojo.doc, dd = d.documentElement, w = window, b = dojo.body();
+		if(dojo.isMozilla){
+			this._v = { 'w': dd.clientWidth, 'h': w.innerHeight };	// Object
+		}
+		else if(!dojo.isOpera && w.innerWidth){
+			this._v = { 'w': w.innerWidth, 'h': w.innerHeight };		// Object
+		}
+		else if(!dojo.isOpera && dd && dd.clientWidth){
+			this._v = { 'w': dd.clientWidth, 'h': dd.clientHeight };	// Object
+		}
+		else if(b.clientWidth){
+			this._v = { 'w': b.clientWidth, 'h': b.clientHeight };	// Object
+		}
+	},
+
+	setAutoScrollNode: function(/*Node*/node){
+		// summary:
+		//		set the node which is dragged
+		// node:
+		//		node to scroll
+
+		//console.log("dojox.mdnd.AutoScroll ::: setAutoScrollNode ");
+		this._node = node;
+	},
+
+	setAutoScrollMaxPage: function(){
+		// summary:
+		//		Set the hightest heigh and width authorized scroll.
+
+		//console.log("dojox.mdnd.AutoScroll ::: setAutoScrollMaxPage ");
+		this._yMax = this._html.scrollHeight;
+		this._xMax = this._html.scrollWidth;
+	},
+
+	checkAutoScroll: function(/*Event*/e){
+		// summary:
+		//		Check if an autoScroll have to be launched.
+
+		//console.log("dojox.mdnd.AutoScroll ::: checkAutoScroll");
+		if(this._autoScrollActive){
+			this.stopAutoScroll();
+		}
+		this._y = e.pageY;
+		this._x = e.pageX;
+		if(e.clientX < this.marginMouse){
+			this._autoScrollActive = true;
+			this._autoScrollLeft(e);
+		}
+		else if(e.clientX > this._v.w - this.marginMouse){
+			this._autoScrollActive = true;
+			this._autoScrollRight(e);
+		}
+		if(e.clientY < this.marginMouse){
+			this._autoScrollActive = true;
+			this._autoScrollUp(e);
+			
+		}
+		else if(e.clientY > this._v.h - this.marginMouse){
+			this._autoScrollActive = true;
+			this._autoScrollDown();
+		}
+	},
+
+	_autoScrollDown: function(){
+		// summary:
+		//		Manage the down autoscroll.
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.AutoScroll ::: _autoScrollDown ");
+		if(this._timer){
+			clearTimeout(this._timer);
+		}
+		if(this._autoScrollActive && this._y + this.marginMouse < this._yMax){
+			this._html.scrollTop += this.interval;
+			this._node.style.top = (parseInt(this._node.style.top) + this.interval) + "px";
+			this._y += this.interval;
+			this._timer = setTimeout(dojo.hitch(this, "_autoScrollDown"), this.recursiveTimer);
+		}
+	},
+
+	_autoScrollUp: function(){
+		// summary:
+		//		Manage the up autoscroll.
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.AutoScroll ::: _autoScrollUp ");
+		if(this._timer){
+			clearTimeout(this._timer);
+		}
+		if(this._autoScrollActive && this._y - this.marginMouse > 0){
+			this._html.scrollTop -= this.interval;
+			this._node.style.top = (parseInt(this._node.style.top) - this.interval) + "px";
+			this._y -= this.interval;
+			this._timer = setTimeout(dojo.hitch(this, "_autoScrollUp"),this.recursiveTimer);
+		}
+	},
+
+	_autoScrollRight: function(){
+		// summary:
+		//		Manage the right autoscroll.
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.AutoScroll ::: _autoScrollRight ");
+		if(this._timer){
+			clearTimeout(this._timer);
+		}
+		if(this._autoScrollActive && this._x + this.marginMouse < this._xMax){
+			this._html.scrollLeft += this.interval;
+			this._node.style.left = (parseInt(this._node.style.left) + this.interval) + "px";
+			this._x += this.interval;
+			this._timer = setTimeout(dojo.hitch(this, "_autoScrollRight"), this.recursiveTimer);
+		}
+	},
+
+	_autoScrollLeft: function(/*Event*/e){
+		// summary:
+		//		Manage the left autoscroll.
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.AutoScroll ::: _autoScrollLeft ");
+		if(this._timer){
+			clearTimeout(this._timer);
+		}
+		if(this._autoScrollActive && this._x - this.marginMouse > 0){
+			this._html.scrollLeft -= this.interval;
+			this._node.style.left = (parseInt(this._node.style.left) - this.interval) + "px";
+			this._x -= this.interval;
+			this._timer = setTimeout(dojo.hitch(this, "_autoScrollLeft"),this.recursiveTimer);
+		}
+	},
+
+	stopAutoScroll: function(){
+		// summary:
+		//		Stop the autoscroll.
+		
+		//console.log("dojox.mdnd.AutoScroll ::: stopAutoScroll ");
+		if(this._timer){
+			clearTimeout(this._timer);
+		}
+		this._autoScrollActive = false;
+	},
+
+	destroy: function(){
+		//console.log("dojox.mdnd.AutoScroll ::: destroy ");
+		dojo.disconnect(this.resizeHandler);
+	}
+});
+
+dojox.mdnd.autoScroll = null;
+(function(){
+	dojox.mdnd.autoScroll = new dojox.mdnd.AutoScroll();
+}());
diff --git a/dojox/mdnd/DropIndicator.js b/dojox/mdnd/DropIndicator.js
new file mode 100644
index 0000000..cc38b3d
--- /dev/null
+++ b/dojox/mdnd/DropIndicator.js
@@ -0,0 +1,86 @@
+dojo.provide("dojox.mdnd.DropIndicator");
+
+dojo.require("dojox.mdnd.AreaManager");
+
+dojo.declare(
+	"dojox.mdnd.DropIndicator", 
+	null, 
+{
+	// summary:
+	//		DropIndicator managment for DnD.
+
+	// node: DOMNode
+	//		the drop indicator node	
+	node : null,
+		
+	constructor: function(){
+		//console.log("dojox.mdnd.DropIndicator ::: constructor");
+		var dropIndicator = document.createElement("div");
+		var subDropIndicator = document.createElement("div");
+		dropIndicator.appendChild(subDropIndicator);
+		dojo.addClass(dropIndicator, "dropIndicator");
+		this.node = dropIndicator;
+	},
+	
+	place: function(/*Node*/area, /*Node*/nodeRef, /*Object*/size){
+		// summary:
+		//		Place the DropIndicator in the right place
+		// area:
+		//		the dnd targer area node
+		// nodeRef:
+		//		node where the dropIndicator have to be placed into the area
+		// dragNode:
+		//		the node which is dragged
+		// returns:
+		//		the node inserted or null if it crashes
+
+		//console.log("dojox.mdnd.DropIndicator ::: place");
+		if(size){
+			this.node.style.height = size.h + "px";
+		}
+		try{
+			if(nodeRef){
+				area.insertBefore(this.node, nodeRef);
+			}
+			else{
+				// empty target area or last node => appendChild
+				area.appendChild(this.node);
+			}
+			return this.node;	// DOMNode
+		}catch(e){
+			return null;
+		}
+	},
+	
+	remove: function(){
+		// summary:
+		//		remove the DropIndicator (not destroy)
+
+		//console.log("dojox.mdnd.DropIndicator ::: remove");
+		if(this.node){
+			//FIX : IE6 problem
+			this.node.style.height = "";
+			if(this.node.parentNode){
+				this.node.parentNode.removeChild(this.node);
+			}
+		}	
+	},
+	 
+	destroy: function(){
+		// summary:
+		//		destroy the dropIndicator
+
+		//console.log("dojox.mdnd.DropIndicator ::: destroy");
+		if(this.node){
+			if(this.node.parentNode){
+				this.node.parentNode.removeChild(this.node);
+			}
+			dojo._destroyElement(this.node);
+			delete this.node;
+		}
+	}
+});
+
+(function(){
+	dojox.mdnd.areaManager()._dropIndicator = new dojox.mdnd.DropIndicator();
+}());
diff --git a/dojox/mdnd/LazyManager.js b/dojox/mdnd/LazyManager.js
new file mode 100644
index 0000000..3f24f1f
--- /dev/null
+++ b/dojox/mdnd/LazyManager.js
@@ -0,0 +1,68 @@
+dojo.provide("dojox.mdnd.LazyManager");
+
+dojo.require("dojo.dnd.Manager");
+dojo.require("dojox.mdnd.PureSource");
+
+dojo.declare(
+	"dojox.mdnd.LazyManager",
+	null,
+{
+	// summary:
+	//		This class allows to launch a drag and drop dojo on the fly.
+	
+	constructor: function(){
+		//console.log("dojox.mdnd.LazyManager ::: constructor");
+		this._registry = {};
+		// initialization of the _fakeSource to enabled DragAndDrop :
+		this._fakeSource = new dojox.mdnd.PureSource(dojo.create("div"), {
+			'copyOnly': false
+		});
+		this._fakeSource.startup();
+		dojo.addOnUnload(dojo.hitch(this, "destroy"));
+		this.manager = dojo.dnd.manager();
+	},
+	
+	getItem: function(/*DOMNode*/draggedNode){
+		//console.log("dojox.mdnd.LazyManager ::: getItem");
+		var type = draggedNode.getAttribute("dndType");
+		return {
+			'data' : draggedNode.getAttribute("dndData") || draggedNode.innerHTML,
+			'type' : type ? type.split(/\s*,\s*/) : ["text"]
+		}
+	},
+	
+	startDrag: function(/*Event*/e, /*DOMNode?*/draggedNode){
+		// summary:
+		//		launch a dojo drag and drop on the fly.
+
+		//console.log("dojox.mdnd.LazyManager ::: startDrag");
+		draggedNode = draggedNode || e.target;
+		if(draggedNode){
+			var m = this.manager,
+				object = this.getItem(draggedNode);
+			if(draggedNode.id == ""){
+				dojo.attr(draggedNode, "id", dojo.dnd.getUniqueId());
+			}
+			dojo.addClass(draggedNode, "dojoDndItem");
+			this._fakeSource.setItem(draggedNode.id, object);
+			m.startDrag(this._fakeSource, [draggedNode], false);
+			m.onMouseMove(e);
+		}
+	},
+	
+	cancelDrag: function(){
+		// summary:
+		//		cancel a drag and drop dojo on the fly.
+
+		//console.log("dojox.mdnd.LazyManager ::: cancelDrag");
+		var m = this.manager;
+		m.target = null;
+		m.onMouseUp();
+	},
+	
+	
+	destroy: function(){
+		//console.log("dojox.mdnd.LazyManager ::: destroy");
+		this._fakeSource.destroy();
+	}
+});
diff --git a/dojox/mdnd/Moveable.js b/dojox/mdnd/Moveable.js
new file mode 100644
index 0000000..c90cf5b
--- /dev/null
+++ b/dojox/mdnd/Moveable.js
@@ -0,0 +1,251 @@
+dojo.provide("dojox.mdnd.Moveable");
+
+dojo.declare(
+	"dojox.mdnd.Moveable", 
+	null, 
+{
+	// summary:
+	//		Allow end-users to track a DOM node into the web page
+
+	// handle: DOMNode
+	//		The node on which the user clicks to drag the main node.
+	handle: null,
+	
+	// skip: Boolean
+	// 		A flag to control a drag action if a form element has been focused.
+	//		If true, the drag action is not executed.
+	skip: true,
+
+	// dragDistance: Integer
+	//		The user clicks on the handle, but the drag action will really begin
+	//		if he tracks the main node to more than 3 pixels.
+	dragDistance: 3,
+	
+	constructor: function(/*Object*/params, /*DOMNode*/node){
+		// summary:
+		// 		Configure parameters and listen to mousedown events from handle 
+		//		node.
+		// params:
+		//		Hash of parameters
+		// node:
+		//		The draggable node
+
+		//console.log("dojox.mdnd.Moveable ::: constructor"); 
+		this.node = dojo.byId(node);
+		
+		this.d = this.node.ownerDocument;
+		
+		if(!params){ params = {}; }
+		this.handle = params.handle ? dojo.byId(params.handle) : null;
+		if(!this.handle){ this.handle = this.node; }
+		this.skip = params.skip;
+		this.events = [
+			dojo.connect(this.handle, "onmousedown", this, "onMouseDown")
+		];
+		if(dojox.mdnd.autoScroll){
+			this.autoScroll = dojox.mdnd.autoScroll;
+		}
+		
+	},
+	
+	isFormElement: function(/*DOMEvent*/ e){
+		// summary:
+		//		identify the type of target node associated with a DOM event.
+		// e:
+		//		a DOM event
+		// returns:
+		//		if true, the target is one of those specific nodes.
+
+		//console.log("dojox.mdnd.Moveable ::: isFormElement");
+		var t = e.target;
+		if(t.nodeType == 3 /*TEXT_NODE*/){
+			t = t.parentNode;
+		}
+		return " a button textarea input select option ".indexOf(" " + t.tagName.toLowerCase() + " ") >= 0;	// Boolean
+	},
+	
+	onMouseDown: function(/*DOMEvent*/e){
+		// summary:
+		//		Occurs when the user clicks on the handle node.
+		//		Skip the drag action if a specific node is targeted.
+		//		Listens to mouseup and mousemove events on to the HTML document.
+		// e:
+		//		a DOM event
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.Moveable ::: onMouseDown");
+		if(this._isDragging){ return;}
+		var isLeftButton = dojo.isIE ? (e.button == 1) : (e.which == 1);
+		if(!isLeftButton){
+			return;
+		}
+		if(this.skip && this.isFormElement(e)){ return; }
+		if(this.autoScroll){
+			this.autoScroll.setAutoScrollNode(this.node);
+			this.autoScroll.setAutoScrollMaxPage();
+		}
+		this.events.push(dojo.connect(this.d, "onmouseup", this, "onMouseUp"));
+		this.events.push(dojo.connect(this.d, "onmousemove", this, "onFirstMove"));
+		this._selectStart = dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent);
+		this._firstX = e.clientX;
+		this._firstY = e.clientY;	
+		dojo.stopEvent(e);
+	},
+	
+	onFirstMove: function(/*DOMEvent*/e){
+		// summary:
+		//		Occurs when the user moves the mouse after clicking on the 
+		//		handle.
+		//		Determinate when the drag action will have to begin (see 
+		//		dragDistance).
+		// e:
+		//		A DOM event
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.Moveable ::: onFirstMove"); 
+		dojo.stopEvent(e);
+		var d = (this._firstX - e.clientX) * (this._firstX - e.clientX) 
+				+ (this._firstY - e.clientY) * (this._firstY - e.clientY);
+		if(d > this.dragDistance * this.dragDistance){
+			this._isDragging = true;
+			dojo.disconnect(this.events.pop());
+			dojo.style(this.node, "width", dojo.contentBox(this.node).w + "px");
+			this.initOffsetDrag(e);
+			this.events.push(dojo.connect(this.d, "onmousemove", this, "onMove"));
+		}
+	},
+	
+	initOffsetDrag: function(/*DOMEvent*/e){
+		// summary:
+		//		Initialize the gap between main node coordinates and the clicked point.
+		//		Call the onDragStart method.
+		// e:
+		//		A DOM event
+
+		//console.log("dojox.mdnd.Moveable ::: initOffsetDrag");
+		this.offsetDrag = { 'l': e.pageX, 't': e.pageY };
+		var s = this.node.style;
+		var position = dojo.position(this.node, true);
+		/*if(s.position == "relative" || s.position == ""){
+			s.position = "absolute"; // enforcing the absolute mode
+		}*/
+		this.offsetDrag.l = position.x - this.offsetDrag.l;
+		this.offsetDrag.t = position.y - this.offsetDrag.t;
+		var coords = {
+			'x': position.x,
+			'y': position.y
+		};
+		this.size = {
+			'w': position.w,
+			'h': position.h
+		};
+		// method to catch
+		this.onDragStart(this.node, coords, this.size);
+	},
+	
+	onMove: function(/*DOMEvent*/e){
+		// summary:
+		//		Occurs when the user moves the mouse.
+		//		Calls the onDrag method.
+		// e:
+		//		a DOM event
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.Moveable ::: onMove");
+		dojo.stopEvent(e);
+		// hack to avoid too many calls to onMove in IE8 causing sometimes slowness
+		if(dojo.isIE == 8 && new Date() - this.date < 20){
+			return;		
+		}
+		if(this.autoScroll){
+			this.autoScroll.checkAutoScroll(e);
+		}
+		var coords = {
+			'x': this.offsetDrag.l + e.pageX,
+			'y': this.offsetDrag.t + e.pageY
+		};
+		var s = this.node.style;
+		s.left = coords.x + "px";
+		s.top = coords.y + "px";
+		
+		// method to catch
+		this.onDrag(this.node, coords, this.size, {'x':e.pageX, 'y':e.pageY});
+		if(dojo.isIE == 8){
+			this.date = new Date();
+		}
+	},
+	
+	onMouseUp: function(/*DOMEvent*/e){
+		// summary:
+		//		Occurs when the user releases the mouse
+		//		Calls the onDragEnd method.
+		// e: 
+		//		a DOM event
+
+		dojo.stopEvent(e);
+		this._isDragging = false;
+		if(this.autoScroll){
+			this.autoScroll.stopAutoScroll();
+		}
+		dojo.disconnect(this.events.pop());
+		dojo.disconnect(this.events.pop());
+		delete this.onMove;
+		this.onDragEnd(this.node);
+		this.node.focus();
+	},
+	
+	onDragStart: function(/*DOMNode*/node, /*Object*/coords, /*Object*/size){
+		// summary:
+		//		Stub function.
+		//		Notes : border box model
+		// node:
+		//		a DOM node
+		//	coords:
+		//		absolute position of the main node
+		// size:
+		//		an object encapsulating width an height values
+		// tags:
+		//		callback
+
+	},
+	
+	onDragEnd: function(/*DOMNode*/node){
+		// summary:
+		//		Stub function
+		//		Notes : Coordinates don't contain margins
+		// node:
+		//		a DOM node
+		// tags:
+		//		callback
+
+	},
+	
+	onDrag: function(/*DOMNode*/node, /*Object*/coords, /*Object*/size, /*Object*/mousePosition){
+		// summary:
+		//		Stub function.
+		//		Notes : border box model for size value, margin box model for coordinates
+		// node:
+		//		a DOM node
+		// coords:
+		//		position of the main node (equals to css left/top properties)
+		// size:
+		//		an object encapsulating width and height values
+		// mousePosition:
+		//		coordiantes of mouse
+		// tags:
+		//		callback
+
+	},
+
+	destroy: function(){
+		// summary:
+		//		Delecte associated events
+
+		// console.log("dojox.mdnd.Moveable ::: destroy");
+		dojo.forEach(this.events, dojo.disconnect);
+		this.events = this.node = null;
+	}
+});
diff --git a/dojox/mdnd/PureSource.js b/dojox/mdnd/PureSource.js
new file mode 100644
index 0000000..2cabe11
--- /dev/null
+++ b/dojox/mdnd/PureSource.js
@@ -0,0 +1,208 @@
+dojo.provide("dojox.mdnd.PureSource");
+
+dojo.require("dojo.dnd.Selector");
+dojo.require("dojo.dnd.Manager");
+
+dojo.declare(
+	"dojox.mdnd.PureSource", 
+	dojo.dnd.Selector,
+{
+	// summary:
+	//		A Source Object, which can be used only as a DnD source.
+	//		A Source can contained several dnd items.
+	//		A dnd item is not a source.
+	
+	horizontal: false,
+	copyOnly: true,
+	skipForm: false,
+	withHandles: false,
+	isSource: true,	
+	targetState: "Disabled",
+	generateText: true,
+	
+	constructor: function(/*DOMNode|String*/node, /*dojo.dnd.__SourceArgs?*/params){
+		// summary:
+		//		Initialize a new PureSource.
+		// node:
+		//		Node or node's id to build the source on.
+		// params:
+		//		Any property of this class may be configured via the params
+		//		object which is mixed-in to the 'dojo.dnd.Source' instance.
+
+		//console.log('dojox.mdnd.PureSource ::: constructor');
+		dojo.mixin(this, dojo.mixin({}, params));
+		var type = this.accept;
+		
+		// class-specific variables
+		this.isDragging = false;
+		this.mouseDown = false;
+
+		// states
+		this.sourceState = "";
+		dojo.addClass(this.node, "dojoDndSource");
+		if(this.horizontal){
+			dojo.addClass(this.node, "dojoDndHorizontal");
+		}
+		// set up events
+		this.topics = [
+			dojo.subscribe("/dnd/cancel", this, "onDndCancel"),
+			dojo.subscribe("/dnd/drop", this, "onDndCancel")
+		];
+	},
+	
+	onDndCancel: function(){
+		// summary:
+		//		Topic event processor for /dnd/cancel, called to cancel the Dnd
+		//		operation.
+		// tags:
+		//		callback
+
+		//console.log('dojox.mdnd.PureSource ::: onDndCancel');
+		this.isDragging = false;
+		this.mouseDown = false;
+		delete this.mouseButton;
+	},
+	
+	copyState: function(/*Boolean*/keyPressed){
+		// summary:
+		//		Returns true, if we need to copy items, false to move.
+		//		It is separated to be overwritten dynamically, if needed.
+		// keyPressed:
+		//		The "copy" was pressed.
+		// returns:
+		//		True, if we need to copy items, false to move.
+
+		//console.log('dojox.mdnd.PureSource ::: copyState');
+		return this.copyOnly || keyPressed;	// Boolean
+	},
+	
+	destroy: function(){
+		// summary:
+		//		Prepares the object to be garbage-collected.
+
+		//console.log('dojox.mdnd.PureSource ::: destroy');
+		dojox.mdnd.PureSource.superclass.destroy.call(this);
+		dojo.forEach(this.topics, dojo.unsubscribe);
+		this.targetAnchor = null;
+	},
+
+	markupFactory: function(/*Object*/params, /*DomNode*/node){
+		// summary:
+		//		Markup methods.
+		// params:
+		//		???
+		// node:
+		//		???
+		// returns:
+		//		New dojox.mdnd.PureSource instance.
+
+		//console.log('dojox.mdnd.PureSource ::: markupFactory');
+		params._skipStartup = true;
+		return new dojox.mdnd.PureSource(node, params);
+	},
+
+	onMouseMove: function(/*Event*/e){
+		// summary:
+		//		Event processor for onmousemove.
+		// e:
+		//		Mouse event.	
+
+		//console.log('dojox.mdnd.PureSource ::: onMouseMove');
+		if(this.isDragging){
+			return;
+		}
+		dojox.mdnd.PureSource.superclass.onMouseMove.call(this, e);
+		var m = dojo.dnd.manager();		
+		if(this.mouseDown && !this.isDragging && this.isSource){
+			var nodes = this.getSelectedNodes();			
+			if(nodes.length){				
+				m.startDrag(this, nodes, this.copyState(dojo.isCopyKey(e)));
+				this.isDragging = true;
+			}
+		}
+		
+	},
+	
+	onMouseDown: function(/*Event*/e){
+		// summary:
+		//		Event processor for onmousedown.
+		// e:
+		//		Mouse event.
+		// tags:
+		//		callback
+
+		//console.log('dojox.mdnd.PureSource ::: onMouseDown');
+		if(this._legalMouseDown(e) && (!this.skipForm || !dojo.dnd.isFormElement(e))){
+			this.mouseDown = true;
+			this.mouseButton = e.button;
+			dojox.mdnd.PureSource.superclass.onMouseDown.call(this, e);
+		}
+	},
+	
+	onMouseUp: function(/*Event*/e){
+		// summary:
+		//		Event processor for onmouseup.
+		// e:
+		//		Mouse event
+		// tags:
+		//		callback
+
+		//console.log('.dnd.PureSource ::: onMouseUp');
+		if(this.mouseDown){
+			this.mouseDown = false;
+			dojox.mdnd.PureSource.superclass.onMouseUp.call(this, e);
+		}
+	},
+
+	onOverEvent: function(){
+		// summary:
+		//		Called once, when mouse is over our container.
+		// tags:
+		//		callback
+
+		//console.log('dojox.mdnd.PureSource ::: onOverEvent');
+		dojox.mdnd.PureSource.superclass.onOverEvent.call(this);
+		dojo.dnd.manager().overSource(this);
+	},
+	
+	onOutEvent: function(){
+		// summary:
+		//		Called once, when mouse is out our container.
+		// tags:
+		//		callback
+
+		//console.log('dojox.mdnd.PureSource ::: onOutEvent');
+		dojox.mdnd.PureSource.superclass.onOutEvent.call(this);
+		dojo.dnd.manager().outSource(this);
+	},
+	
+	_markDndStatus: function(/*Boolean*/copy){
+		// summary:
+		//		Changes source's state based on "copy" status.
+		// copy:
+		//		Copy status.
+		// tags:
+		//		protected
+
+		//console.log('dojox.mdnd.PureSource ::: _markDndStatus');
+		this._changeState("Source", copy ? "Copied" : "Moved");
+	},
+
+	_legalMouseDown: function(/*Event*/e){
+		// summary:
+		//		Checks if user clicked on "approved" items.
+		// e:
+		//		Mouse event.
+		// returns:
+		//		True if user clicked on "approved" items.
+		// tags:
+		// 		protected
+
+		//console.log('dojox.mdnd.PureSource ::: _legalMouseDown');
+		if(!this.withHandles){ return true; }
+		for(var node = e.target; node && !dojo.hasClass(node, "dojoDndItem"); node = node.parentNode){
+			if(dojo.hasClass(node, "dojoDndHandle")){ return true; }
+		}
+		return false;	// Boolean
+	}
+});
diff --git a/dojox/mdnd/README b/dojox/mdnd/README
new file mode 100644
index 0000000..69d99f8
--- /dev/null
+++ b/dojox/mdnd/README
@@ -0,0 +1,94 @@
+-------------------------------------------------------------------------------
+dojox.mdnd Experimental coordinates based moveable drag and drop.
+-------------------------------------------------------------------------------
+Version 1.1
+Release date: 09/04/2009
+-------------------------------------------------------------------------------
+Project state:
+
+[AreaManager]	beta
+[AutoScroll]	beta
+[DropIndicator]	beta
+[Movable]	beta
+[PureSource]	beta
+[adapter/DndFromDojo] experimental
+[adapter/DndToDojo] experimental
+[dropMode/DefaultDropMode] beta
+[dropMode/OverDropMode] experimental
+
+-------------------------------------------------------------------------------
+Credits
+
+Erwan Morvillez (emorvillez), 
+Jean-Jacques Patard (jjpatard), 
+Jeff Cunat (jfcunat)
+
+
+-------------------------------------------------------------------------------
+Project description
+
+Alternative Drag and Drop solution based on coordinates of drag element and
+targets instead of mouseover. It allows dragging directly the nodes (like
+dojo.dnd.Moveable) instead of an avatar (as in dojo.dnd). dojo.dnd and
+dojox.mdnd are compatible by using adapters.
+
+PureSource is just a rewrite of dojo.dnd.Source to only allow drag start and no
+drop without testing acceptance.
+
+-------------------------------------------------------------------------------
+Dependencies
+
+	require Dojo Core
+
+-------------------------------------------------------------------------------
+Installation:
+
+	checkout:
+
+	http://svn.dojotoolkit.org/src/dojox/trunk/mdnd/
+
+	and require via:
+		dojo.require("dojox.mdnd.AreaManager");
+
+-------------------------------------------------------------------------------
+Basic Usage:
+
+	dojo.require("dojox.mdnd.AreaManager");
+	dojo.require("dojox.mdnd.DropIndicator");
+	dojo.require("dojox.mdnd.dropMode.DefaultDropMode");
+			
+	var init = function(){
+		var m = dojox.mdnd.areaManager();
+		m.areaClass = "dndArea";
+		m.dragHandleClass = "dragHandle";
+		m.registerByClass();
+	};
+	
+	dojo.addOnLoad(init);
+	
+	...
+	
+	<div style="position:absolute; top:80px; left:50px;">
+	<h2>Accepts Type1 items</h2>
+	<div class="dndArea container" accept="type1">
+		<div class="dndItem" dndType="type1">
+			<div class="dragHandle">Item Type 1</div>
+			<div>
+				<p>Proin aliquet accumsan nunc. Duis nec tortor.</p>
+
+			</div>
+		</div>
+		<div class="dndItem simpleBlock" dndType="type2">
+			<div class="dragHandle">Item Type2</div>
+			<div>
+				<p>Proin aliquet accumsan nunc. Duis nec tortor.</p>
+			</div>
+		</div>
+
+	</div>
+
+	<div style="position:absolute; top:80px; left:350px;">
+		<h2>Accepts Type2 items</h2>
+		<div class="dndArea container" accept="type2">
+		</div>
+	</div>
diff --git a/dojox/mdnd/adapter/DndFromDojo.js b/dojox/mdnd/adapter/DndFromDojo.js
new file mode 100644
index 0000000..a65420f
--- /dev/null
+++ b/dojox/mdnd/adapter/DndFromDojo.js
@@ -0,0 +1,366 @@
+dojo.provide("dojox.mdnd.adapter.DndFromDojo");
+dojo.require("dojox.mdnd.AreaManager");
+dojo.require("dojo.dnd.Manager");
+
+dojo.declare(
+	"dojox.mdnd.adapter.DndFromDojo",
+	null,
+{
+	// summary
+	//		Allow communication between Dojo dnd items and DojoX D&D areas
+
+	// dropIndicatorSize: Object
+	//		size by default of dropIndicator (display only into a D&D Area)
+	dropIndicatorSize : {'w':0,'h':50},
+
+	// dropIndicatorSize: Object
+	//		size by default of dropIndicator (display only into a D&D Area)
+	dropIndicatorSize: {'w':0,'h':50},
+
+	// _areaManager: Object
+	//		Reference to the current DojoX Dnd Manager
+	_areaManager: null,
+
+	// _dojoManager
+	//		Reference to the current Dojo Manager
+	_dojoManager: null,
+
+	// _currentArea: Object
+	//		The current Area on mouse over
+	_currentArea: null,
+
+	// _oldArea: Object
+	//		The old area the mouse has passed over
+	_oldArea: null,
+
+	// _moveHandler: Object
+	//		The handler of mouse connection
+	_moveHandler: null,
+
+	// _subscribeHandler: Array
+	//		The list of dojo dnd topics
+	_subscribeHandler: null,
+
+	constructor: function(){
+		this._areaManager = dojox.mdnd.areaManager();
+		this._dojoManager = dojo.dnd.manager();
+		this._currentArea = null;
+		this._moveHandler = null;
+		this.subscribeDnd();
+	},
+
+	subscribeDnd: function(){
+		// summary:
+		//		Subscribe to somes topics of dojo drag and drop.
+
+		//console.log(("dojox.mdnd.adapter.DndFromDojo ::: subscribeDnd");
+		this._subscribeHandler = [
+			dojo.subscribe("/dnd/start",this,"onDragStart"),
+			dojo.subscribe("/dnd/drop/before", this, "onDrop"),
+			dojo.subscribe("/dnd/cancel",this,"onDropCancel"),
+			dojo.subscribe("/dnd/source/over",this,"onDndSource")
+		]
+	},
+
+	unsubscribeDnd: function(){
+		// summary:
+		//		Unsubscribe to some topics of dojo drag and drop.
+
+		//console.log(("dojox.mdnd.adapter.DndFromDojo ::: unsubscribeDnd");
+		dojo.forEach(this._subscribeHandler, dojo.unsubscribe);
+	},
+
+	_getHoverArea: function(/*Object*/ coords){
+		// summary:
+		//		Get a D&D dojoX area as a DOM node positioned under a specific point.
+		// coords:
+		//		Object containing the coordinates x and y (mouse position)
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.adapter.DndFromDojo ::: _getHoverArea");
+		var x = coords.x;
+		var y = coords.y;
+		this._oldArea = this._currentArea;
+		this._currentArea = null;
+		var areas = this._areaManager._areaList;
+		for(var i = 0; i < areas.length; i++){
+			var area = areas[i];
+			var startX = area.coords.x;
+			var endX = startX + area.node.offsetWidth;
+			var startY = area.coords.y;
+			var endY = startY + area.node.offsetHeight;
+			// check if the coordinates mouse is in a D&D Area
+			if(startX <= x && x <= endX && startY <= y && y <= endY){
+				this._areaManager._oldIndexArea = this._areaManager._currentIndexArea;
+				this._areaManager._currentIndexArea = i;
+				this._currentArea = area.node;
+				break;
+			}
+		}
+		if(this._currentArea != this._oldArea){
+			if(this._currentArea == null){
+				// case when the dragNode was in a D&D area but it's out now.
+				this.onDragExit();
+			}
+			else if(this._oldArea == null){
+				// case when the dragNode was out a D&D area but it's in now.
+				this.onDragEnter();
+			}
+			else{
+				// case when the dragNode was in a D&D area and enter in an other D&D area directly.
+				this.onDragExit();
+				this.onDragEnter();
+			}
+		}
+
+		//console.log("dojox.mdnd.adapter.DndFromDojo ::: _getHoverArea",this._dojoManager.avatar.node,this._currentArea,this._oldArea);
+	},
+
+	onDragStart: function(/*Object*/source, /*Array*/nodes, /*Boolean*/copy){
+		// summary:
+		//		Occurs when the "/dnd/start" topic is published.
+		// source:
+		//		the source which provides items
+		// nodes:
+		//		the list of transferred items
+		// copy:
+		//		copy items, if true, move items otherwise
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDragStart");
+		// catch the dragNode to get the type when it's necessary.
+		this._dragNode = nodes[0];
+		this._copy = copy; this._source = source;
+		// Connect the onMouseMove :
+		// It's usefull to activate the detection of a D&D area and the dropIndicator place only if
+		// the dragNode is out of a the source dojo. The classic behaviour of the dojo source is kept.
+		this._outSourceHandler = dojo.connect(this._dojoManager, "outSource", this, function(){
+			//dojo.disconnect(this._outSourceHandler);
+			if(this._moveHandler == null){
+				this._moveHandler = dojo.connect(dojo.doc, "mousemove", this, "onMouseMove");
+			}
+		});
+	},
+
+	onMouseMove: function(/*DOMEvent*/e){
+		// summary:
+		//		Occurs when the user moves the mouse.
+		// e:
+		//		the DOM event
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.adapter.DndFromDojo ::: onMouseMove");
+		// calculate the coordonates of the mouse.
+		var coords = {
+			'x': e.pageX,
+			'y': e.pageY
+		};
+		this._getHoverArea(coords);
+		// if a D&D area has been found and if it's accepted to drop this type of dragged node
+		if(this._currentArea && this._areaManager._accept){
+			// specific case : a dropIndicator can be hidden (see onDndSource method)
+			if(this._areaManager._dropIndicator.node.style.visibility == "hidden"){
+				this._areaManager._dropIndicator.node.style.visibility = "";
+				dojo.addClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
+			}
+			// place the dropIndicator in D&D Area with a default size.
+			this._areaManager.placeDropIndicator(coords, this.dropIndicatorSize);
+		}
+	},
+
+	onDragEnter: function(){
+		// summary:
+		//		Occurs when the user drages an DOJO dnd item inside a D&D dojoX area.
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDragEnter");
+		// Check if the type of dragged node is accepted in the selected D&D dojoX Area.
+		var _dndType = this._dragNode.getAttribute("dndType");
+		// need to have an array as type
+		var type = (_dndType) ? _dndType.split(/\s*,\s*/) : ["text"];
+		this._areaManager._isAccepted(type, this._areaManager._areaList[this._areaManager._currentIndexArea].accept);
+		// if the D&D dojoX Area accepts the drop, change the color of Avatar.
+		if(this._dojoManager.avatar){
+			if(this._areaManager._accept){
+				dojo.addClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
+			}
+			else{
+				dojo.removeClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
+			}
+		}
+	},
+
+	onDragExit: function(){
+		// summary:
+		//		Occurs when the user leaves a D&D dojoX area after dragging an DOJO dnd item over it.
+
+		//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDragExit");
+		// if the dragged node exits of a D&D dojoX Area :
+		this._areaManager._accept = false;
+		// change color of avatar
+		if(this._dojoManager.avatar){
+			dojo.removeClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
+		}
+		// reset all variables and remove the dropIndicator.
+		if(this._currentArea == null){
+			this._areaManager._dropMode.refreshItems(this._areaManager._areaList[this._areaManager._oldIndexArea], this._areaManager._oldDropIndex, this.dropIndicatorSize, false);
+			this._areaManager._resetAfterDrop();
+		}
+		else{
+			this._areaManager._dropIndicator.remove();
+		}
+	},
+
+	isAccepted: function(/*Node*/node, /*Object*/accept){
+		// summary:
+		//		Check if a dragNode is accepted into a dojo target.
+		// node:
+		//		The dragged node.
+		// accept:
+		//		Object containing the type accepted for a target dojo.
+		// returns:
+		//		true if the dragged node is accepted in the target dojo.
+
+		//console.log("dojox.mdnd.adapter.DndFromDojo ::: isAccepted");
+		var type = (node.getAttribute("dndType")) ? node.getAttribute("dndType") : "text";
+		if(type && type in accept)
+			return true;	// Boolean
+		else
+			return false;	// Boolean
+	},
+
+	onDndSource: function(/*Object*/ source){
+		// summary:
+		//		Called when the mouse enters or exits of a source dojo.
+		// source:
+		//		the dojo source/target
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDndSource",source);
+		// Only the case : "source dojo into a D&D dojoX Area" is treated.
+		if(this._currentArea == null){
+			return;
+		}
+		if(source){
+			// Enter in a source/target dojo.
+			// test if the type of draggedNode is accepted :
+			var accept = false;
+			if(this._dojoManager.target == source){
+				accept = true;
+			}
+			else{
+				accept = this.isAccepted(this._dragNode, source.accept);
+			}
+			if(accept){
+				// disconnect the onMouseMove to disabled the search of a drop zone in the D&D dojoX Area.
+				dojo.disconnect(this._moveHandler);
+				this._currentArea = this._moveHandler = null;
+				// hidden the visibility of dojoX dropIndicator to prevent an offset when the dropIndicator disappears.
+				// test if drop indicator is visible before applaying hidden style.
+				var dropIndicator = this._areaManager._dropIndicator.node;
+				if(dropIndicator && dropIndicator.parentNode !== null && dropIndicator.parentNode.nodeType == 1)
+					dropIndicator.style.visibility = "hidden";
+			}
+			else{
+				// if the type of dragged node is not accepted in the target dojo, the color of avatar
+				// have to be the same that the color of D&D dojoX Area acceptance.
+				this._resetAvatar();
+			}
+		}
+		else{
+			// Exit of a source/target dojo.
+			// reconnect the onMouseMove to enabled the search of a drop zone in the D&D dojox Area.
+			if(!this._moveHandler)
+				this._moveHandler = dojo.connect(dojo.doc, "mousemove", this, "onMouseMove");
+
+			this._resetAvatar();
+		}
+	},
+
+	_resetAvatar: function(){
+		// summary:
+		//		Function executed in onDndSource function to set the avatar
+		//		acceptance according to the dojox DnD AreaManager Acceptance.
+	 	//		It is used when The mouse exit a source/target dojo or if the
+		//		dragged node is not accepted in dojo source / target.
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.adapter.DndFromDojo ::: _resetAvatar");
+		if(this._dojoManager.avatar){
+			if(this._areaManager._accept){
+				dojo.addClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
+			}
+			else{
+				dojo.removeClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
+			}
+		}
+	},
+
+	onDropCancel: function(){
+		// summary:
+		//		Occurs when the "/dnd/cancel" topic is published.
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDropCancel");
+		if(this._currentArea == null){
+			// the dragged node is not in the D&D dojox Area => Cancel
+			this._areaManager._resetAfterDrop();
+			dojo.disconnect(this._moveHandler);
+			dojo.disconnect(this._outSourceHandler);
+			this._currentArea = this._moveHandler = this._outSourceHandler = null;
+		}
+		else{
+			// the dragged node is in the D&D dojox Area
+			//		(catch when dragged node exits of a source/target dojo and stays in the same D&D dojox Area)
+			// dojo cancel the drop but it's authorized in the D&D Area
+			if(this._areaManager._accept){
+				this.onDrop(this._source, [this._dragNode], this._copy, this._currentArea);
+			}
+			else{
+				this._currentArea = null;
+				dojo.disconnect(this._outSourceHandler);
+				dojo.disconnect(this._moveHandler);
+				this._moveHandler = this._outSourceHandler = null;
+			}
+		}
+	},
+
+	onDrop: function(/*Object*/source, /*Array*/nodes, /*Boolean*/copy){
+		// summary:
+		//		Occurs when the user leaves a D&D dojox area after dragging an DOJO dnd item over it.
+		// source:
+		//		the source which provides items
+		// nodes:
+		//		the list of transferred items
+		// copy:
+		//		copy items, if true, move items otherwise
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDrop", this._currentArea);
+		dojo.disconnect(this._moveHandler);
+		dojo.disconnect(this._outSourceHandler);
+		this._moveHandler = this._outSourceHandler = null;
+		if(this._currentArea){
+			var dropIndex = this._areaManager._currentDropIndex;
+			dojo.publish("/dnd/drop/after", [source, nodes, copy, this._currentArea, dropIndex]);
+			this._currentArea = null;
+		}
+		if(this._areaManager._dropIndicator.node.style.visibility == "hidden"){
+			this._areaManager._dropIndicator.node.style.visibility = "";
+		}
+		this._areaManager._resetAfterDrop();
+	}
+});
+
+dojox.mdnd.adapter._dndFromDojo = null;
+(function(){
+	dojox.mdnd.adapter._dndFromDojo = new dojox.mdnd.adapter.DndFromDojo();
+}());
diff --git a/dojox/mdnd/adapter/DndToDojo.js b/dojox/mdnd/adapter/DndToDojo.js
new file mode 100644
index 0000000..e9d0d93
--- /dev/null
+++ b/dojox/mdnd/adapter/DndToDojo.js
@@ -0,0 +1,484 @@
+dojo.provide("dojox.mdnd.adapter.DndToDojo");
+
+dojo.require("dojox.mdnd.PureSource");
+dojo.require("dojox.mdnd.LazyManager");
+
+dojo.declare(
+	"dojox.mdnd.adapter.DndToDojo",
+	null,
+{
+	// summary:
+	//		Allow communication between an item of dojox D&D area to a target dojo.
+
+	// _dojoList: Array
+	//		Array containing object references the dojo Target list
+	_dojoList: null,
+
+	// _currentDojoArea: DOMNode
+	//		Representing the current dojo area
+	_currentDojoArea: null,
+
+	// _dojoxManager: dojox.mdnd.AreaManager
+	//		The reference to the dojox AreaManager
+	_dojoxManager: null,
+
+	// _dragStartHandler: Object
+	//		Handle to keep start subscribe
+	_dragStartHandler: null,
+
+	// _dropHandler: Object
+	//		Handle to keep drop subscribe
+	_dropHandler: null,
+
+	// _moveHandler: Object
+	//		Handle to keep move subscribe
+	_moveHandler: null,
+
+	// _moveUpHandler: Object
+	//		Handle to kee move up subscribe
+	_moveUpHandler: null,
+
+	// _draggedNode: DOMNode
+	// 		The current dragged node
+	_draggedNode: null,
+
+	constructor: function(){
+		this._dojoList = [];
+		this._currentDojoArea = null;
+		this._dojoxManager = dojox.mdnd.areaManager();
+		this._dragStartHandler = dojo.subscribe("/dojox/mdnd/drag/start", this, function(node, sourceArea, sourceDropIndex){
+			this._draggedNode = node;
+			this._moveHandler = dojo.connect(dojo.doc, "onmousemove", this, "onMouseMove");
+		});
+		this._dropHandler = dojo.subscribe("/dojox/mdnd/drop", this, function(node, targetArea, indexChild){
+			if(this._currentDojoArea){
+				dojo.publish("/dojox/mdnd/adapter/dndToDojo/cancel", [this._currentDojoArea.node, this._currentDojoArea.type, this._draggedNode, this.accept]);
+			}
+			this._draggedNode = null;
+			this._currentDojoArea = null;
+			dojo.disconnect(this._moveHandler);
+		});
+	},
+
+	_getIndexDojoArea: function(/*node*/area){
+		// summary:
+		//		Check if a dojo area is registered.
+		// area: DOMNode
+		//		A node corresponding to the target dojo.
+		// returns:
+		//		The index of area if it's registered else -1.
+		// tags:
+		//		protected
+
+		//console.log('dojox.mdnd.adapter.DndToDojo ::: _getIndexDojoArea');
+		if(area){
+			for(var i = 0, l = this._dojoList.length; i < l; i++){
+				if(this._dojoList[i].node === area){
+					return i;
+				}
+			}
+		}
+		return -1;
+	},
+
+	_initCoordinates: function(/*DOMNode*/area){
+		// summary:
+		//		Initialize the coordinates of the target dojo.
+		// area:
+		//		A registered DOM node.
+		// returns:
+		//		An object which contains coordinates : *{x:0,y:,x1:0,y1:0}*
+		// tags:
+		//		protected
+
+ 		//console.log('dojox.mdnd.adapter.DndToDojo ::: _initCoordinates');
+		if(area){
+			var position = dojo.position(area, true),
+				coords = {};
+			coords.x = position.x
+			coords.y = position.y
+			coords.x1 = position.x + position.w;
+			coords.y1 = position.y + position.h;
+			return coords;	// 	Object
+		}
+		return null;
+	},
+
+	register: function(/*DOMNode*/area, /*String*/ type,/*Boolean*/ dojoTarget){
+		// summary:
+		//		Register a target dojo.
+		//		The target is represented by an object containing :
+		// 			- the dojo area node
+		// 			- the type reference to identify a group node
+		// 			- the coords of the area to enable refresh position
+		// area:
+		//		The DOM node which has to be registered.
+		// type:
+		//		A String to identify the node.
+		// dojoTarger:
+		//		True if the dojo D&D have to be enable when mouse is hover the registered target dojo.
+
+		//console.log("dojox.mdnd.adapter.DndToDojo ::: registerDojoArea", area, type, dojoTarget);
+		if(this._getIndexDojoArea(area) == -1){
+			var coords = this._initCoordinates(area),
+				object = {
+					'node': area,
+					'type': type,
+					'dojo': (dojoTarget)?dojoTarget:false,
+					'coords': coords
+				};
+			this._dojoList.push(object);
+			// initialization of the _fakeSource to allow Dnd switching
+			if(dojoTarget && !this._lazyManager){
+				this._lazyManager = new dojox.mdnd.LazyManager();
+			}
+		}
+	},
+
+	unregisterByNode: function(/*DOMNode*/area){
+		// summary:
+		//		Unregister a target dojo.
+		// area:
+		//		The DOM node of target dojo.
+
+		//console.log("dojox.mdnd.adapter.DndToDojo ::: unregisterByNode", area);
+		var index = this._getIndexDojoArea(area);
+		// if area is registered
+		if(index != -1){
+			this._dojoList.splice(index, 1);
+		}
+	},
+
+	unregisterByType: function(/*String*/type){
+		// summary:
+		//		Unregister several targets dojo having the same type passing in parameter.
+		// type:
+		//		A String to identify dojo targets.
+
+		//console.log("dojox.mdnd.adapter.DndToDojo ::: unregisterByType", type);
+		if(type){
+			var tempList = [];
+			dojo.forEach(this._dojoList, function(item, i){
+				if(item.type != type){
+					tempList.push(item);
+				}
+			});
+			this._dojoList = tempList;
+		}
+	},
+
+	unregister: function(){
+		// summary:
+		//		Unregister all targets dojo.
+
+		//console.log("dojox.mdnd.adapter.DndToDojo ::: unregister");
+		this._dojoList = [];
+	},
+
+	refresh: function(){
+		// summary:
+		//		Refresh the coordinates of all registered dojo target.
+
+		//console.log("dojox.mdnd.adapter.DndToDojo ::: refresh");
+		var dojoList = this._dojoList;
+		this.unregister();
+		dojo.forEach(dojoList, function(dojo){
+			dojo.coords = this._initCoordinates(dojo.node);
+		}, this);
+		this._dojoList = dojoList;
+	},
+
+	refreshByType: function(/*String*/ type){
+		// summary:
+		//		Refresh the coordinates of registered dojo target with a specific type.
+		// type:
+		//		A String to identify dojo targets.
+
+		//console.log("dojox.mdnd.adapter.DndToDojo ::: refresh");
+		var dojoList = this._dojoList;
+		this.unregister();
+		dojo.forEach(dojoList, function(dojo){
+			if(dojo.type == type){
+				dojo.coords = this._initCoordinates(dojo.node);
+			}
+		}, this);
+		this._dojoList = dojoList;
+	},
+
+	_getHoverDojoArea: function(/*Object*/coords){
+		// summary:
+		//		Check if the coordinates of the mouse is in a dojo target.
+		// coords:
+		//		Coordinates of the mouse.
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.adapter.DndToDojo ::: _getHoverDojoArea");
+		this._oldDojoArea = this._currentDojoArea;
+		this._currentDojoArea = null;
+		var x = coords.x;
+		var y = coords.y;
+		var length = this._dojoList.length;
+		for(var i = 0; i < length; i++){
+			var dojoArea = this._dojoList[i];
+			var coordinates = dojoArea.coords;
+			if(coordinates.x <= x && x <= coordinates.x1 && coordinates.y <= y && y <= coordinates.y1){
+				this._currentDojoArea = dojoArea;
+				break;
+			}
+		}
+	},
+
+	onMouseMove: function(/*DOMEvent*/e){
+		// summary:
+		//		Call when the mouse moving after an onStartDrag of AreaManger.
+		//		Check if the coordinates of the mouse is in a dojo target.
+		// e:
+		//		Event object.
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.adapter.DndToDojo ::: onMouseMove");
+		var coords = {
+			'x': e.pageX,
+			'y': e.pageY
+		};
+		this._getHoverDojoArea(coords);
+		if(this._currentDojoArea != this._oldDojoArea){
+			if(this._currentDojoArea == null){
+				this.onDragExit(e);
+			}
+			else if(this._oldDojoArea == null){
+				this.onDragEnter(e);
+			}
+			else{
+				this.onDragExit(e);
+				this.onDragEnter(e);
+			}
+		}
+	},
+
+	isAccepted: function(/*DOMNode*/draggedNode, /*Object*/ target){
+		// summary:
+		//		Return true if the dragged node is accepted.
+		//		This method has to be overwritten according to registered target.
+
+		//console.log("dojox.mdnd.adapter.DndToDojo ::: isAccepted");
+		return true;
+	},
+
+
+	onDragEnter: function(/*DOMEvent*/e){
+		// summary:
+		//		Call when the mouse enters in a registered dojo target.
+		// e:
+		//		The current Javascript Event.
+		// tags:
+		//		callback
+
+		//console.log("dojox.mdnd.adapter.DndToDojo ::: onDragEnter");
+		// specific for drag and drop switch
+		if(this._currentDojoArea.dojo){
+			// disconnect
+			dojo.disconnect(this._dojoxManager._dragItem.handlers.pop());
+			dojo.disconnect(this._dojoxManager._dragItem.handlers.pop());
+			//disconnect onmousemove of moveable item
+			//console.info("before",this._dojoxManager._dragItem.item.events.pop());
+			dojo.disconnect(this._dojoxManager._dragItem.item.events.pop());
+			dojo.body().removeChild(this._dojoxManager._cover);
+			dojo.body().removeChild(this._dojoxManager._cover2);
+			var node = this._dojoxManager._dragItem.item.node;
+			// hide dragNode :
+			// disconnect the dojoDndAdapter if it's initialize
+			if(dojox.mdnd.adapter._dndFromDojo){
+				dojox.mdnd.adapter._dndFromDojo.unsubscribeDnd();
+			}
+			dojo.style(node, {
+				'position': "relative",
+				'top': '0',
+				'left': '0'
+			});
+			// launch the drag and drop Dojo.
+			this._lazyManager.startDrag(e, node);
+			var handle = dojo.connect(this._lazyManager.manager, "overSource", this, function(){
+				dojo.disconnect(handle);
+				if(this._lazyManager.manager.canDropFlag){
+					// remove dropIndicator
+					this._dojoxManager._dropIndicator.node.style.display = "none";
+				}
+			});
+
+			this.cancelHandler = dojo.subscribe("/dnd/cancel", this, function(){
+				var moveableItem = this._dojoxManager._dragItem.item;
+				// connect onmousemove of moveable item
+				// need to reconnect the onmousedown of movable class.
+				moveableItem.events = [
+					dojo.connect(moveableItem.handle, "onmousedown", moveableItem, "onMouseDown")
+				];
+				// replace the cover and the dragNode in the cover.
+				dojo.body().appendChild(this._dojoxManager._cover);
+				dojo.body().appendChild(this._dojoxManager._cover2);
+				this._dojoxManager._cover.appendChild(moveableItem.node);
+
+				var objectArea = this._dojoxManager._areaList[this._dojoxManager._sourceIndexArea];
+				var dropIndex = this._dojoxManager._sourceDropIndex;
+				var nodeRef = null;
+				if(dropIndex != objectArea.items.length
+						&& dropIndex != -1){
+					nodeRef = objectArea.items[this._dojoxManager._sourceDropIndex].item.node;
+				}
+				if(this._dojoxManager._dropIndicator.node.style.display == "none"){
+					this._dojoxManager._dropIndicator.node.style.display == "";
+				}
+				this._dojoxManager._dragItem.handlers.push(dojo.connect(this._dojoxManager._dragItem.item, "onDrag", this._dojoxManager, "onDrag"));
+				this._dojoxManager._dragItem.handlers.push(dojo.connect(this._dojoxManager._dragItem.item, "onDragEnd", this._dojoxManager, "onDrop"));
+				this._draggedNode.style.display = "";
+				this._dojoxManager.onDrop(this._draggedNode);
+				dojo.unsubscribe(this.cancelHandler);
+				dojo.unsubscribe(this.dropHandler);
+				if(dojox.mdnd.adapter._dndFromDojo){
+					dojox.mdnd.adapter._dndFromDojo.subscribeDnd();
+				}
+			});
+			this.dropHandler = dojo.subscribe("/dnd/drop/before", this, function(params){
+				dojo.unsubscribe(this.cancelHandler);
+				dojo.unsubscribe(this.dropHandler);
+				this.onDrop();
+			});
+		}
+		else{
+			this.accept = this.isAccepted(this._dojoxManager._dragItem.item.node, this._currentDojoArea);
+			if(this.accept){
+				// disconnect
+				dojo.disconnect(this._dojoxManager._dragItem.handlers.pop());
+				dojo.disconnect(this._dojoxManager._dragItem.handlers.pop());
+				// remove dropIndicator
+				this._dojoxManager._dropIndicator.node.style.display = "none";
+				if(!this._moveUpHandler){
+					this._moveUpHandler = dojo.connect(dojo.doc, "onmouseup", this, "onDrop");
+				}
+			}
+		}
+		// publish a topic
+		dojo.publish("/dojox/mdnd/adapter/dndToDojo/over",[this._currentDojoArea.node, this._currentDojoArea.type, this._draggedNode, this.accept]);
+	},
+
+	onDragExit: function(/*DOMEvent*/e){
+		// summary:
+		//		Call when the mouse exit of a registered dojo target.
+		// e:
+		//		current javscript event
+
+		//console.log("dojox.mdnd.adapter.DndToDojo ::: onDragExit",e, this._dojoxManager._dragItem.item);
+		// set the old height of dropIndicator.
+		if(this._oldDojoArea.dojo){
+			// unsubscribe the topic /dnd/cancel and /dnd/drop/before
+			dojo.unsubscribe(this.cancelHandler);
+			dojo.unsubscribe(this.dropHandler);
+			// launch Drag and Drop
+			var moveableItem = this._dojoxManager._dragItem.item;
+			// connect onmousemove of moveable item
+			this._dojoxManager._dragItem.item.events.push(dojo.connect(
+				moveableItem.node.ownerDocument,
+				"onmousemove",
+				moveableItem,
+				"onMove"
+			));
+			// replace the cover and the dragNode in the cover.
+			dojo.body().appendChild(this._dojoxManager._cover);
+			dojo.body().appendChild(this._dojoxManager._cover2);
+			this._dojoxManager._cover.appendChild(moveableItem.node);
+			// fix style :
+			var style = moveableItem.node.style;
+			style.position = "absolute";
+			style.left = (moveableItem.offsetDrag.l + e.pageX)+"px";
+			style.top = (moveableItem.offsetDrag.t + e.pageX)+"px";
+			style.display = "";
+			// stop dojoDrag
+			this._lazyManager.cancelDrag();
+			// reconnect the dndFromDojo
+			if(dojox.mdnd.adapter._dndFromDojo){
+				dojox.mdnd.adapter._dndFromDojo.subscribeDnd();
+			}
+			if(this._dojoxManager._dropIndicator.node.style.display == "none"){
+				this._dojoxManager._dropIndicator.node.style.display = "";
+			}
+			// reconnect the areaManager.
+			this._dojoxManager._dragItem.handlers.push(dojo.connect(this._dojoxManager._dragItem.item, "onDrag", this._dojoxManager, "onDrag"));
+			this._dojoxManager._dragItem.handlers.push(dojo.connect(this._dojoxManager._dragItem.item, "onDragEnd", this._dojoxManager, "onDrop"));
+			this._dojoxManager._dragItem.item.onMove(e);
+		}
+		else{
+			if(this.accept){
+				// disconnect the mouseUp event.
+				if(this._moveUpHandler){
+					dojo.disconnect(this._moveUpHandler);
+					this._moveUpHandler = null;
+				}
+				// redisplay dropIndicator
+				if(this._dojoxManager._dropIndicator.node.style.display == "none"){
+					this._dojoxManager._dropIndicator.node.style.display = "";
+				}
+				// reconnect the areaManager.
+				this._dojoxManager._dragItem.handlers.push(dojo.connect(this._dojoxManager._dragItem.item, "onDrag", this._dojoxManager, "onDrag"));
+				this._dojoxManager._dragItem.handlers.push(dojo.connect(this._dojoxManager._dragItem.item, "onDragEnd", this._dojoxManager, "onDrop"));
+				this._dojoxManager._dragItem.item.onMove(e);
+			}
+		}
+		// publish a topic
+		dojo.publish("/dojox/mdnd/adapter/dndToDojo/out",[this._oldDojoArea.node, this._oldDojoArea.type, this._draggedNode, this.accept]);
+	},
+
+	onDrop: function(/*DOMEvent*/e){
+		// summary:
+		//		Called when an onmouseup event is loaded on a registered target dojo.
+		// e:
+		//		Event object.
+
+//		console.log("dojox.mdnd.adapter.DndToDojo ::: onDrop", this._currentDojoArea);
+		if(this._currentDojoArea.dojo){
+			// reconnect the dojoDndAdapter
+			if(dojox.mdnd.adapter._dndFromDojo){
+				dojox.mdnd.adapter._dndFromDojo.subscribeDnd();
+			}
+		}
+		if(this._dojoxManager._dropIndicator.node.style.display == "none"){
+			this._dojoxManager._dropIndicator.node.style.display = "";
+		}
+		// remove the cover
+		if(this._dojoxManager._cover.parentNode && this._dojoxManager._cover.parentNode.nodeType == 1){
+			dojo.body().removeChild(this._dojoxManager._cover);
+			dojo.body().removeChild(this._dojoxManager._cover2);
+		}
+		// remove draggedNode of target :
+		if(this._draggedNode.parentNode == this._dojoxManager._cover){
+			this._dojoxManager._cover.removeChild(this._draggedNode);
+		}
+		dojo.disconnect(this._moveHandler);
+		dojo.disconnect(this._moveUpHandler);
+		this._moveHandler = this._moveUpHandler = null;
+		dojo.publish("/dojox/mdnd/adapter/dndToDojo/drop", [this._draggedNode, this._currentDojoArea.node, this._currentDojoArea.type]);
+		dojo.removeClass(this._draggedNode, "dragNode");
+		var style = this._draggedNode.style;
+		style.position = "relative";
+		style.left = "0";
+		style.top = "0";
+		style.width = "auto";
+		dojo.forEach(this._dojoxManager._dragItem.handlers, dojo.disconnect);
+		this._dojoxManager._deleteMoveableItem(this._dojoxManager._dragItem);
+		this._draggedNode = null;
+		this._currentDojoArea = null;
+		// reset of area manager.
+		this._dojoxManager._resetAfterDrop();
+	}
+});
+
+dojox.mdnd.adapter._dndToDojo = null;
+dojox.mdnd.adapter.dndToDojo = function(){
+	// summary:
+	// 		returns the current areaManager, creates one if it is not created yet
+	if(!dojox.mdnd.adapter._dndToDojo){
+		dojox.mdnd.adapter._dndToDojo = new dojox.mdnd.adapter.DndToDojo();
+	}
+	return dojox.mdnd.adapter._dndToDojo;	// Object
+};
diff --git a/dojox/mdnd/dropMode/DefaultDropMode.js b/dojox/mdnd/dropMode/DefaultDropMode.js
new file mode 100644
index 0000000..7c89481
--- /dev/null
+++ b/dojox/mdnd/dropMode/DefaultDropMode.js
@@ -0,0 +1,333 @@
+dojo.provide("dojox.mdnd.dropMode.DefaultDropMode");
+dojo.require("dojox.mdnd.AreaManager");
+
+dojo.declare("dojox.mdnd.dropMode.DefaultDropMode", null, {
+	// summary:
+	//		Enabled a type of calcul for Dnd.
+	//		Default class to find the nearest target.
+
+	// _oldXPoint: Integer
+	//		used to save a X position 
+	_oldXPoint: null,
+
+	// _oldYPoint: Integer
+	//		used to save a Y position
+	_oldYPoint: null,
+
+	// _oldBehaviour: String
+	// 		see <getDragPoint>
+	_oldBehaviour: "up",
+
+	addArea: function(/*Array*/areas, /*Object*/object){
+		// summary:
+		//		Add a DnD Area into an array sorting by the x position.
+		// areas:
+		//		array of areas
+		// object:
+		//		data type of a DndArea
+		// returns:
+		//		a sorted area
+
+		//console.log("dojox.mdnd.dropMode.DefaultDropMode ::: addArea");
+		var length =  areas.length;
+		var position = dojo.position(object.node, true);
+		object.coords = {'x':position.x, 'y':position.y};
+		if (length == 0) {
+			areas.push(object);
+		}else{
+			var x =  object.coords.x;
+			for (var i = 0; i < length; i++) {
+				if (x < areas[i].coords.x) {
+					for (var j = length-1; j >= i; j--) 
+						areas[j + 1] = areas[j];
+					areas[i] = object;
+					break;
+				}
+			}
+			if (i == length) 
+				areas.push(object);
+		}
+		return areas;	// Array
+	},
+
+	updateAreas: function(/*Array*/areaList){
+		// summary:
+		//		Refresh intervals between areas to determinate the nearest area to drop an item.
+		//		Algorithm :
+		//		the marker should be the vertical line passing by the
+		//		central point between two contiguous areas.
+		//		Note:
+		//		If the page has only one targetArea, it's not necessary to calculate coords.
+		// areaList:
+		//		array of areas
+
+		//console.log("dojox.mdnd.dropMode.DefaultDropMode ::: initAreas");
+		var length = areaList.length;
+		if (length > 1){
+			var currentRight, nextLeft;
+			for (var i = 0; i < length; i++) {
+				var area = areaList[i];
+				var nextArea;
+				area.coords.x1 = -1;
+				area.coords.x2 = -1;
+				if (i == 0) {
+					nextArea = areaList[i+1];
+					this._updateArea(area);
+					this._updateArea(nextArea);
+					currentRight = area.coords.x + area.node.offsetWidth;
+					nextLeft =  nextArea.coords.x;	
+					area.coords.x2 = currentRight + (nextLeft-currentRight)/2;
+				}
+				else if (i == length-1) {
+					area.coords.x1 = areaList[i-1].coords.x2;
+				}else{
+					nextArea = areaList[i+1];
+					this._updateArea(nextArea);
+					currentRight = area.coords.x + area.node.offsetWidth;
+					nextLeft =  nextArea.coords.x;
+					area.coords.x1 = areaList[i-1].coords.x2;
+					area.coords.x2 = currentRight + (nextLeft-currentRight)/2;
+				}
+			}
+		}
+	},
+
+	_updateArea : function(/*Object*/area){
+		// summary:
+		//		update the DnD area object (i.e. update coordinates of its DOM node)
+		// area:
+		//		the DnD area
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.dropMode.DefaultDropMode  ::: _updateArea");
+		var position = dojo.position(area.node, true);
+		area.coords.x = position.x;
+		area.coords.y = position.y;
+	},
+
+	initItems: function(/*Object*/area){
+		// summary:
+		//		initialize the horizontal line in order to determinate the drop zone.
+		// area:
+		//		the DnD area
+
+		//console.log("dojox.mdnd.dropMode.DefaultDropMode ::: initItems");
+		dojo.forEach(area.items, function(obj){
+			//get the vertical middle of the item
+			var node = obj.item.node;
+			var position = dojo.position(node, true);
+			var y = position.y + position.h/2;
+			obj.y = y;
+		});
+		area.initItems = true;
+	},
+
+	refreshItems: function(/*Object*/area, /*Integer*/indexItem, /*Object*/size, /*Boolean*/added){
+		// summary:
+		//		take into account the drop indicator DOM element in order to compute horizontal lines
+		// area:
+		//		a DnD area object
+		// indexItem:
+		// 		index of a draggable item
+		// size:
+		//		dropIndicator size
+		// added:
+		//		boolean to know if a dropIndicator has been added or deleted
+
+		//console.log("dojox.mdnd.dropMode.DefaultDropMode ::: refreshItems");
+		if (indexItem == -1) {
+			return;
+		}else if(area && size && size.h){
+			var height = size.h;
+			if (area.margin){
+				height += area.margin.t;
+			}
+			var length = area.items.length;
+			for (var i=indexItem; i<length; i++){
+				var item = area.items[i];
+				if (added) {
+					item.y += height;
+				}else{
+					item.y -= height;
+				}
+			}
+		}
+	},
+
+	getDragPoint: function(/*Object*/coords, /*Object*/size, /*Object*/mousePosition){
+		// summary:
+		//		return coordinates of the draggable item
+		// description:
+		//		return for: 
+		// 			- X point : the middle 
+		//	  		- Y point : search if the user goes up or goes down with his mouse.
+		//	  		- Up : top of the draggable item
+		//	  		- Down : bottom of the draggable item
+		// coords:
+		//		an object encapsulating X and Y position
+		// size:
+		//		an object encapsulating width and height values
+		// mousePosition:
+		//		coordinates of mouse
+		// returns:
+		//		an object of coordinates
+		// 		example : {'x':10,'y':10}
+
+		//console.log("dojox.mdnd.dropMode.DefaultDropMode ::: getDragPoint");
+		var y = coords.y;
+		if (this._oldYPoint){
+			if (y > this._oldYPoint) {
+				this._oldBehaviour = "down";
+				y += size.h;
+			}
+			else 
+				if (y <= this._oldYPoint) {
+					this._oldBehaviour = "up";
+				}
+		}
+		this._oldYPoint = y;
+		return { 
+			'x': coords.x + (size.w / 2), 
+			'y': y
+			};	// Object
+	},
+
+	getTargetArea: function(/*Array*/areaList, /*Object*/ coords, /*integer*/currentIndexArea ){
+		// summary:
+		//		get the nearest DnD area.
+		//		Coordinates are basically provided by the <getDragPoint> method.
+		// areaList:
+		//		a list of DnD areas objects
+		// coords:
+		//		coordinates [x,y] of the dragItem
+		// currentIndexArea:
+		//		an index representing the active DnD area
+		// returns:
+		//		the index of the DnD area
+
+		//console.log("dojox.mdnd.dropMode.DefaultDropMode ::: getTargetArea");
+		var index = 0;
+		var x = coords.x;
+		var end = areaList.length;
+		if (end > 1) {
+			var start = 0, direction = "right", compute = false;
+			if (currentIndexArea == -1 || arguments.length<3) {
+				// first time : Need to search the nearest area in all areas.
+				compute = true;
+			}
+			else {
+				// check if it's always the same area
+				if (this._checkInterval(areaList, currentIndexArea, x)){
+					index = currentIndexArea;
+				}else{
+					if (this._oldXPoint < x){
+						start = currentIndexArea + 1;
+					}else{
+						start = currentIndexArea - 1;
+						end = 0;
+						direction = "left";
+					}
+					compute = true;
+				}
+			}
+			if (compute) {
+				if (direction === "right") {
+					for (var i = start; i < end; i++) {
+						if (this._checkInterval(areaList, i, x)) {
+							index = i;
+							break;
+						}
+					}
+				}else{
+					for (var i = start; i >= end; i--) {
+						if (this._checkInterval(areaList, i, x)) {
+							index = i;
+							break;
+						}
+					}
+				}
+			}
+		}
+		this._oldXPoint = x;
+		return index;	// Integer
+	},
+
+	_checkInterval: function(/*Array*/areaList, /*Integer*/index, /*Coord*/x){
+		// summary:
+		//		check if the dragNode is in the interval.
+		//		The x coordinate is basically provided by the <getDragPoint> method.
+		// areaList:
+		//		a list of DnD areas objects 	
+		// index:
+		//		index of a DnD area (to get the interval)
+		// x:
+		//		coordinate x, of the dragNode
+		// returns:
+		//		true if the dragNode is in intervall
+		// tags:
+		//		protected
+
+		var coords = areaList[index].coords;
+		if (coords.x1 == -1) {
+			if (x <= coords.x2) {
+				return true;
+			}
+		}
+		else 
+			if (coords.x2 == -1) {
+				if (x > coords.x1) {
+					return true;
+				}
+			}
+			else {
+				if (coords.x1 < x && x <= coords.x2) {
+					return true;
+				}
+			}
+		return false;	// Boolean
+	},
+
+	getDropIndex: function(/*Object*/ targetArea, /*Object*/ coords){
+		// summary:
+		//		Return the index where the drop has to be placed.
+		// targetArea:
+		//		a DnD area object
+		// coords:
+		//		coordinates [x,y] of the draggable item
+		// returns:
+		// 		a number
+		//		or -1 if the area has no children or the drop index represents the last position in to the area
+
+		//console.log("dojox.mdnd.dropMode.DefaultDropMode ::: getDropIndex");
+		var length = targetArea.items.length;
+		var coordinates = targetArea.coords;
+		var y = coords.y;
+		if (length > 0) {
+			// course all children in the target area.
+			for (var i = 0; i < length; i++) {
+				// compare y value with y value of children
+				if (y < targetArea.items[i].y) {
+					return i;	// Integer
+				}
+				else {
+					if (i == length-1) {
+						return -1;
+					}
+				}
+			}
+		}
+		return -1;
+	},
+
+	destroy: function(){
+		//	can be overwritten.
+	}
+});
+
+//------------
+//Singleton	
+//------------
+(function(){
+	dojox.mdnd.areaManager()._dropMode = new dojox.mdnd.dropMode.DefaultDropMode();
+}());
\ No newline at end of file
diff --git a/dojox/mdnd/dropMode/OverDropMode.js b/dojox/mdnd/dropMode/OverDropMode.js
new file mode 100644
index 0000000..9c4b158
--- /dev/null
+++ b/dojox/mdnd/dropMode/OverDropMode.js
@@ -0,0 +1,308 @@
+dojo.provide("dojox.mdnd.dropMode.OverDropMode");
+
+dojo.require("dojox.mdnd.AreaManager");
+
+dojo.declare(
+	"dojox.mdnd.dropMode.OverDropMode",
+	null,
+{
+	// summary:
+	//		Default class to find the nearest target only if the mouse is over an area.
+
+	// _oldXPoint: Integer
+	//		used to save a X position
+	_oldXPoint: null,
+
+	// _oldYPoint: Integer
+	//		used to save a Y position
+	_oldYPoint: null,
+
+	// _oldBehaviour: Integer
+	//		see getDragpoint()
+	_oldBehaviour: "up",
+
+	constructor: function(){
+		//console.log("dojox.mdnd.dropMode.OverDropMode ::: constructor");
+		this._dragHandler = [
+			dojo.connect(dojox.mdnd.areaManager(), "onDragEnter", function(coords, size){
+				var m = dojox.mdnd.areaManager();
+				if(m._oldIndexArea == -1){
+					m._oldIndexArea = m._lastValidIndexArea;
+				}
+			})
+		];
+
+	},
+
+	addArea: function(/*Array*/areas, /*Object*/object){
+		// summary:
+		//		Add a D&D Area into an array sorting by the x position.
+		// areas:
+		//		array of areas
+		// object:
+		//		data type of a DndArea
+		// returns:
+		//		a sorted area
+
+		//console.log("dojox.mdnd.dropMode.OverDropMode ::: addArea");
+		var length = areas.length,
+			position = dojo.position(object.node, true);
+		object.coords = {'x':position.x, 'y':position.y};
+		if(length == 0){
+			areas.push(object);
+		}
+		else{
+			var x = object.coords.x;
+			for(var i = 0; i < length; i++){
+				if(x < areas[i].coords.x){
+					for(var j = length-1; j >= i; j--)
+						areas[j + 1] = areas[j];
+					areas[i] = object;
+					break;
+				}
+			}
+			if(i == length){
+				areas.push(object);
+			}
+		}
+		return areas;	// Array
+	},
+
+	updateAreas: function(/*Array*/areaList){
+		// summary:
+		//		refresh areas position and size to determinate the nearest area to drop an item
+		// description:
+		//		the area position (and size) is equal to the postion of the domNode associated.
+		// areaList:
+		//		array of areas
+
+		//console.log("dojox.mdnd.dropMode.OverDropMode ::: updateAreas");
+		var length = areaList.length;
+		for(var i = 0; i < length; i++){
+			this._updateArea(areaList[i]);
+		}
+	},
+
+	_updateArea : function(/*Object*/area){
+		// summary:
+		//		update the D&D area object (i.e. update coordinates of its DOM node)
+		// area:
+		// 		the D&D area.
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.dropMode.OverDropMode ::: addArea");
+		var position = dojo.position(area.node, true);
+		area.coords.x = position.x;
+		area.coords.x2 = position.x + position.w;
+		area.coords.y = position.y;
+	},
+
+	initItems: function(/*Object*/area){
+		// summary:
+		//		initialize the horizontal line in order to determinate the drop zone.
+		// area:
+		//		the D&D area.
+
+		//console.log("dojox.mdnd.dropMode.OverDropMode ::: initItems");
+		dojo.forEach(area.items, function(obj){
+			//get the vertical middle of the item
+			var node = obj.item.node;
+			var position = dojo.position(node, true);
+			var y = position.y + position.h/2;
+			obj.y = y;
+		});
+		area.initItems = true;
+	},
+
+	refreshItems: function(/*Object*/area, /*Integer*/indexItem, /*Object*/size, /*Boolean*/added){
+		// summary:
+		//		take into account the drop indicator DOM element in order to compute horizontal lines
+		// area:
+		//		a D&D area object
+		// indexItem:
+		//		index of a draggable item
+		// size:
+		//		dropIndicator size
+		// added:
+		//		boolean to know if a dropIndicator has been added or deleted
+
+		//console.log("dojox.mdnd.dropMode.OverDropMode ::: refreshItems", area, indexItem, size, added);
+		if(indexItem == -1){
+			return;
+		}
+		else if(area && size && size.h){
+			var height = size.h;
+			if(area.margin){
+				height += area.margin.t;
+			}
+			var length = area.items.length;
+			for(var i = indexItem; i < length; i++){
+				var item = area.items[i];
+				if(added){
+					item.y += height;
+				}
+				else{
+					item.y -= height;
+				}
+			}
+		}
+	},
+
+	getDragPoint: function(/*Object*/coords, /*Object*/size, /*Object*/mousePosition){
+		// summary:
+		//		return coordinates of the draggable item.
+		//		- For X point : the x position of mouse
+		//		- For Y point : the y position of mouse
+		// returns:
+		//		an object of coordinates
+		// 		examples:{'x':10,'y':10}
+		// coords:
+		//		an object encapsulating X and Y position
+		// size:
+		// 		an object encapsulating width and height values
+		// mousePosition:
+		// 		coordinates of mouse
+
+		//console.log("dojox.mdnd.OverDropMode ::: getDragPoint");
+		return {			// Object
+			'x': mousePosition.x,
+			'y': mousePosition.y
+			}
+	},
+
+
+	getTargetArea: function(/*Array*/areaList, /*Object*/ coords, /*integer*/currentIndexArea ){
+		// summary:
+		//		get the nearest D&D area.
+		// areaList:
+		// 		a list of D&D areas objects
+		// coords:
+		//		coordinates [x,y] of the dragItem (see getDragPoint())
+		// currentIndexArea:
+		//		an index representing the active D&D area
+		//returns:
+		//		the index of the D&D area
+
+		//console.log("dojox.mdnd.dropMode.OverDropMode ::: getTargetArea");
+		var index = 0;
+		var x = coords.x;
+		var y = coords.y;
+		var end = areaList.length;
+		var start = 0, direction = "right", compute = false;
+		if(currentIndexArea == -1 || arguments.length < 3){
+			// first time : Need to search the nearest area in all areas.
+			compute = true;
+		}
+		else{
+			// check if it's always the same area
+			if(this._checkInterval(areaList, currentIndexArea, x, y)){
+				index = currentIndexArea;
+			}
+			else{
+				if(this._oldXPoint < x){
+					start = currentIndexArea + 1;
+				}
+				else{
+					start = currentIndexArea - 1;
+					end = 0;
+					direction = "left";
+				}
+				compute = true;
+			}
+		}
+		if(compute){
+			if(direction === "right"){
+				for(var i = start; i < end; i++){
+					if(this._checkInterval(areaList, i, x, y)){
+						index = i;
+						break;
+					}
+				}
+				if(i == end){
+					index = -1;
+				}
+			}
+			else{
+				for(var i = start; i >= end; i--){
+					if(this._checkInterval(areaList, i, x, y)){
+						index = i;
+						break;
+					}
+				}
+				if(i == end-1){
+					index = -1;
+				}
+			}
+		}
+		this._oldXPoint = x;
+		return index; // Integer
+	},
+
+	_checkInterval: function(/*Array*/areaList, /*Integer*/index, /*Coord*/x, /*Coord*/y){
+		// summary:
+		//		check if the dragNode is in the interval.
+		// returns:
+		//		true if the dragNode is in intervall
+		// areaList:
+		//		a list of D&D areas objects
+		// index:
+		//		index of a D&D area (to get the interval)
+		// x:
+		//		coordinate x, of the dragNode (see getDragPoint())
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.dropMode.OverDropMode ::: _checkInterval");
+		var area = areaList[index];
+		var node = area.node;
+		var coords = area.coords;
+		var startX = coords.x;
+		var endX = coords.x2;
+		var startY = coords.y;
+		var endY = startY + node.offsetHeight;
+		if(startX <= x && x <= endX && startY <= y && y <= endY){
+			return true;
+		}
+		return false; // Boolean
+	},
+
+	getDropIndex: function(/*Object*/ targetArea, /*Object*/ coords){
+		// summary:
+		//		Return the index where the drop has to be placed.
+		// targetArea:
+		//		a D&D area object.
+		// coords:
+		//		coordinates [x,y] of the draggable item.
+		// returns:
+		//		a number or -1 if the area has no children or the drop index represents the last position in to the area
+
+		//console.log("dojox.mdnd.dropMode.OverDropMode ::: getDropIndex");
+		var length = targetArea.items.length;
+		var coordinates = targetArea.coords;
+		var y = coords.y;
+		if(length > 0){
+			// course all children in the target area.
+			for(var i = 0; i < length; i++){
+				// compare y value with y value of children
+				if(y < targetArea.items[i].y){
+					return i;	// integer
+				}
+				else{
+					if(i == length-1){
+						return -1; // integer
+					}
+				}
+			}
+		}
+		return -1;	//integer
+	},
+
+	destroy: function(){
+		dojo.forEach(this._dragHandler, dojo.disconnect);
+	}
+});
+
+(function(){
+	dojox.mdnd.areaManager()._dropMode = new dojox.mdnd.dropMode.OverDropMode();
+}());
diff --git a/dojox/mdnd/dropMode/VerticalDropMode.js b/dojox/mdnd/dropMode/VerticalDropMode.js
new file mode 100644
index 0000000..3bcf3e0
--- /dev/null
+++ b/dojox/mdnd/dropMode/VerticalDropMode.js
@@ -0,0 +1,343 @@
+dojo.provide("dojox.mdnd.dropMode.VerticalDropMode");
+dojo.require("dojox.mdnd.AreaManager");
+
+dojo.declare(
+	"dojox.mdnd.dropMode.VerticalDropMode",
+	null,
+{
+	// summary:
+	//		Enabled a type of calcul for Dnd.
+	//		Default class to find the nearest target.
+
+	// _oldXPoint: Integer
+	//		used to save a X position
+	_oldXPoint: null,
+
+	// _oldYPoint: Integer
+	//		used to save a Y position
+	_oldYPoint: null,
+
+	// _oldBehaviour: String
+	// 		see <getDragPoint>
+	_oldBehaviour: "up",
+
+	addArea: function(/*Array*/areas, /*Object*/object){
+		// summary:
+		//		Add a DnD Area into an array sorting by the x position.
+		// areas:
+		//		array of areas
+		// object:
+		//		data type of a DndArea
+		// returns:
+		//		a sorted area
+
+		//console.log("dojox.mdnd.dropMode.VerticalDropMode ::: addArea");
+		var length = areas.length;
+		var position = dojo.position(object.node, true);
+		object.coords = {'x':position.x, 'y':position.y};
+		if(length == 0){
+			areas.push(object);
+		}
+		else{
+			var x = object.coords.x;
+			for(var i = 0; i < length; i++){
+				if(x < areas[i].coords.x){
+					for(var j = length-1; j >= i; j--)
+						areas[j + 1] = areas[j];
+					areas[i] = object;
+					break;
+				}
+			}
+			if(i == length){
+				areas.push(object);
+			}
+		}
+		return areas;	// Array
+	},
+
+	updateAreas: function(/*Array*/areaList){
+		// summary:
+		//		Refresh intervals between areas to determinate the nearest area to drop an item.
+		//		Algorithm :
+		//		the marker should be the vertical line passing by the
+		//		central point between two contiguous areas.
+		//		Note:
+		//		If the page has only one targetArea, it's not necessary to calculate coords.
+		// areaList:
+		//		array of areas
+
+		//console.log("dojox.mdnd.dropMode.VerticalDropMode ::: initAreas");
+		var length = areaList.length;
+		if(length > 1){
+			var currentRight, nextLeft;
+			for(var i = 0; i < length; i++){
+				var area = areaList[i];
+				var nextArea;
+				area.coords.x1 = -1;
+				area.coords.x2 = -1;
+				if(i == 0){
+					nextArea = areaList[i+1];
+					this._updateArea(area);
+					this._updateArea(nextArea);
+					currentRight = area.coords.x + area.node.offsetWidth;
+					nextLeft = nextArea.coords.x;
+					area.coords.x2 = currentRight + (nextLeft-currentRight)/2;
+				}
+				else if(i == length-1){
+					area.coords.x1 = areaList[i-1].coords.x2;
+				}
+				else{
+					nextArea = areaList[i+1];
+					this._updateArea(nextArea);
+					currentRight = area.coords.x + area.node.offsetWidth;
+					nextLeft = nextArea.coords.x;
+					area.coords.x1 = areaList[i-1].coords.x2;
+					area.coords.x2 = currentRight + (nextLeft-currentRight)/2;
+				}
+			}
+		}
+	},
+
+	_updateArea : function(/*Object*/area){
+		// summary:
+		//		update the DnD area object (i.e. update coordinates of its DOM node)
+		// area:
+		//		the DnD area
+		// tags:
+		//		protected
+
+		//console.log("dojox.mdnd.dropMode.VerticalDropMode  ::: _updateArea");
+		var position = dojo.position(area.node, true);
+		area.coords.x = position.x;
+		area.coords.y = position.y;
+	},
+
+	initItems: function(/*Object*/area){
+		// summary:
+		//		initialize the horizontal line in order to determinate the drop zone.
+		// area:
+		//		the DnD area
+
+		//console.log("dojox.mdnd.dropMode.VerticalDropMode ::: initItems");
+		dojo.forEach(area.items, function(obj){
+			//get the vertical middle of the item
+			var node = obj.item.node;
+			var position = dojo.position(node, true);
+			var y = position.y + position.h/2;
+			obj.y = y;
+		});
+		area.initItems = true;
+	},
+
+	refreshItems: function(/*Object*/area, /*Integer*/indexItem, /*Object*/size, /*Boolean*/added){
+		// summary:
+		//		take into account the drop indicator DOM element in order to compute horizontal lines
+		// area:
+		//		a DnD area object
+		// indexItem:
+		// 		index of a draggable item
+		// size:
+		//		dropIndicator size
+		// added:
+		//		boolean to know if a dropIndicator has been added or deleted
+
+		//console.log("dojox.mdnd.dropMode.VerticalDropMode ::: refreshItems");
+		if(indexItem == -1){
+			return;
+		}
+		else if(area && size && size.h){
+			var height = size.h;
+			if(area.margin){
+				height += area.margin.t;
+			}
+			var length = area.items.length;
+			for(var i = indexItem; i < length; i++){
+				var item = area.items[i];
+				if(added){
+					item.y += height;
+				}
+				else{
+					item.y -= height;
+				}
+			}
+		}
+	},
+
+	getDragPoint: function(/*Object*/coords, /*Object*/size, /*Object*/mousePosition){
+		// summary:
+		//		return coordinates of the draggable item
+		// description:
+		//		return for:
+		// 			- X point : the middle
+		//	  		- Y point : search if the user goes up or goes down with his mouse.
+		//	  		- Up : top of the draggable item
+		//	  		- Down : bottom of the draggable item
+		// coords:
+		//		an object encapsulating X and Y position
+		// size:
+		//		an object encapsulating width and height values
+		// mousePosition:
+		//		coordinates of mouse
+		// returns:
+		//		an object of coordinates
+		// 		example : {'x':10,'y':10}
+
+		//console.log("dojox.mdnd.dropMode.VerticalDropMode ::: getDragPoint");
+		var y = coords.y;
+		if(this._oldYPoint){
+			if(y > this._oldYPoint){
+				this._oldBehaviour = "down";
+				y += size.h;
+			}
+			else
+				if(y <= this._oldYPoint){
+					this._oldBehaviour = "up";
+				}
+		}
+		this._oldYPoint = y;
+		return {
+			'x': coords.x + (size.w / 2),
+			'y': y
+			};	// Object
+	},
+
+	getTargetArea: function(/*Array*/areaList, /*Object*/ coords, /*integer*/currentIndexArea ){
+		// summary:
+		//		get the nearest DnD area.
+		//		Coordinates are basically provided by the <getDragPoint> method.
+		// areaList:
+		//		a list of DnD areas objects
+		// coords:
+		//		coordinates [x,y] of the dragItem
+		// currentIndexArea:
+		//		an index representing the active DnD area
+		// returns:
+		//		the index of the DnD area
+
+		//console.log("dojox.mdnd.dropMode.VerticalDropMode ::: getTargetArea");
+		var index = 0;
+		var x = coords.x;
+		var end = areaList.length;
+		if(end > 1){
+			var start = 0, direction = "right", compute = false;
+			if(currentIndexArea == -1 || arguments.length < 3){
+				// first time : Need to search the nearest area in all areas.
+				compute = true;
+			}
+			else{
+				// check if it's always the same area
+				if(this._checkInterval(areaList, currentIndexArea, x)){
+					index = currentIndexArea;
+				}
+				else{
+					if(this._oldXPoint < x){
+						start = currentIndexArea + 1;
+					}
+					else{
+						start = currentIndexArea - 1;
+						end = 0;
+						direction = "left";
+					}
+					compute = true;
+				}
+			}
+			if(compute){
+				if(direction === "right"){
+					for(var i = start; i < end; i++){
+						if(this._checkInterval(areaList, i, x)){
+							index = i;
+							break;
+						}
+					}
+				}
+				else{
+					for(var i = start; i >= end; i--){
+						if(this._checkInterval(areaList, i, x)){
+							index = i;
+							break;
+						}
+					}
+				}
+			}
+		}
+		this._oldXPoint = x;
+		return index;	// Integer
+	},
+
+	_checkInterval: function(/*Array*/areaList, /*Integer*/index, /*Coord*/x){
+		// summary:
+		//		check if the dragNode is in the interval.
+		//		The x coordinate is basically provided by the <getDragPoint> method.
+		// areaList:
+		//		a list of DnD areas objects
+		// index:
+		//		index of a DnD area (to get the interval)
+		// x:
+		//		coordinate x, of the dragNode
+		// returns:
+		//		true if the dragNode is in intervall
+		// tags:
+		//		protected
+		var coords = areaList[index].coords;
+		if(coords.x1 == -1){
+			if(x <= coords.x2){
+				return true;
+			}
+		}
+		else
+			if(coords.x2 == -1){
+				if(x > coords.x1){
+					return true;
+				}
+			}
+			else{
+				if(coords.x1 < x && x <= coords.x2){
+					return true;
+				}
+			}
+		return false;	// Boolean
+	},
+
+	getDropIndex: function(/*Object*/ targetArea, /*Object*/ coords){
+		// summary:
+		//		Return the index where the drop has to be placed.
+		// targetArea:
+		//		a DnD area object
+		// coords:
+		//		coordinates [x,y] of the draggable item
+		// returns:
+		// 		a number
+		//		or -1 if the area has no children or the drop index represents the last position in to the area
+
+		//console.log("dojox.mdnd.dropMode.VerticalDropMode ::: getDropIndex");
+		var length = targetArea.items.length;
+		var coordinates = targetArea.coords;
+		var y = coords.y;
+		if(length > 0){
+			// course all children in the target area.
+			for(var i = 0; i < length; i++){
+				// compare y value with y value of children
+				if(y < targetArea.items[i].y){
+					return i;	// Integer
+				}
+				else{
+					if(i == length-1){
+						return -1;
+					}
+				}
+			}
+		}
+		return -1;
+	},
+
+	destroy: function(){
+		//	can be overwritten.
+	}
+});
+
+//------------
+//Singleton
+//------------
+(function(){
+	dojox.mdnd.areaManager()._dropMode = new dojox.mdnd.dropMode.VerticalDropMode();
+}());
\ No newline at end of file
diff --git a/dojox/mdnd/resources/dnd.css b/dojox/mdnd/resources/dnd.css
new file mode 100644
index 0000000..f7f0469
--- /dev/null
+++ b/dojox/mdnd/resources/dnd.css
@@ -0,0 +1,93 @@
+/**********************************oaf.base.dnd************************************/
+.dragNode{
+	z-index:10000;
+	cursor:move;
+}
+.dragHandle{
+	cursor:move;
+}
+.dropIndicator{
+	position:relative;
+	height:50px;
+	border:1px dashed #FFF;
+}
+.dropIndicator > div{
+	position:absolute;
+	left:0;top:0;right:0;bottom:0;	
+	background-color:#000;
+	opacity:0.17; 
+	filter:alpha(opacity=17); 
+	-khtml-opacity:0.17; 
+	-moz-opacity:0.17;
+}
+.dj_ie6 .dropIndicator div{
+	position:relative;
+	height:100%;
+	background-color:#000;
+	filter:alpha(opacity=17); 
+}
+.dj_ie6 .dropIndicator{
+	_margin:10px;
+}
+.dndCover{
+	background-image:url(../../layout/resources/icons/pixel.gif);
+	position:absolute;
+	left:0;
+	top:0;
+	width:100%;
+	height:1000px;
+	z-index:9999;
+	cursor:move;
+}
+
+.dndCover2{
+	z-index: 10001;
+}
+.dragNode{
+	z-index:10000;
+	cursor:move;
+}
+.dragHandle{
+	cursor:move;
+}
+.dropIndicator{
+	position:relative;
+	height:50px;
+	border:1px dashed #FFF;
+}
+.dropIndicator > div{
+	position:absolute;
+	left:0;top:0;right:0;bottom:0;	
+	background-color:#000;
+	opacity:0.17; 
+	filter:alpha(opacity=17); 
+	-khtml-opacity:0.17; 
+	-moz-opacity:0.17;
+}
+.dj_ie6 .dropIndicator div{
+	position:relative;
+	height:100%;
+	background-color:#000;
+	filter:alpha(opacity=17); 
+}
+.dj_ie6 .dropIndicator{
+	_margin:10px;
+}
+.dndCover{
+	background-image:url(data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw%3D%3D);
+	position:absolute;
+	left:0;
+	top:0;
+	width:100%;
+	height:1000px;
+	z-index:9999;
+	cursor:move;
+}
+
+.dj_ie6 .orange .dndCover, .dj_ie7 .orange .dndCover{
+	background-image:url(../../images/oaf/pixel.gif);
+}
+
+.orange .dndCover2{
+	z-index: 10001;
+}
\ No newline at end of file
diff --git a/dojox/mdnd/tests/functionalTests/test_dnd_acceptance.html b/dojox/mdnd/tests/functionalTests/test_dnd_acceptance.html
new file mode 100644
index 0000000..b93a0da
--- /dev/null
+++ b/dojox/mdnd/tests/functionalTests/test_dnd_acceptance.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+		<title>Dnd Acceptance Test</title>
+		
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/resources/dojo.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/tests/dnd/dndDefault.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/themes/tundra/tundra.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/tests/css/dijitTests.css" />
+		
+		<link rel="stylesheet" type="text/css" href="../../resources/dnd.css" />
+		<link rel="stylesheet" type="text/css" href="../resources/test_dnd.css" />
+		
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="parseOnLoad:true, isDebug:false"></script>
+	
+		<script type="text/javascript">
+			dojo.require("dojox.mdnd.AreaManager");
+			dojo.require("dojox.mdnd.DropIndicator");
+			dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+			
+			var init = function(){
+				var m = dojox.mdnd.areaManager();
+				m.areaClass = "dndArea";
+				m.dragHandleClass = "dragHandle";
+				m.registerByClass();
+			};
+			
+			dojo.addOnLoad(init);
+		</script>
+	</head>
+	<body class="tundra">
+		<div id="main">
+			<h1>Drag and Drop</h1>
+			<div style="position:absolute; top:80px; left:50px;">
+				<h2>Accepts Type1 items</h2>
+				<div class="dndArea container" accept="type1">
+					<div class="dndItem" dndType="type1">
+						<div class="title dragHandle">Item Type 1</div>
+						<div>
+							<p>Proin aliquet accumsan nunc. Duis nec tortor.</p>
+						</div>
+					</div>
+					<div class="dndItem simpleBlock" dndType="type2">
+						<div class="title dragHandle">Item Type2</div>
+						<div>
+							<p>Proin aliquet accumsan nunc. Duis nec tortor.</p>
+						</div>
+					</div>
+				</div>
+			</div>
+			
+			<div style="position:absolute; top:80px; left:350px;">
+				<h2>Accepts Type2 items</h2>
+				<div class="dndArea container" accept="type2">
+				</div>
+			</div>
+			
+			<div style="position:absolute; top:80px; left:650px;">
+				<h2>Accepts both Type1 & Type2 items</h2>
+				<div class="dndArea container" accept="type1, type2">
+					<div class="dndItem" dndType="type2, type1">
+						<div class="title dragHandle">Item Type 1 and Type 2</div>
+						<p>Proin aliquet accumsan nunc. Duis nec tortor.</p>
+					</div>
+				</div>
+			</div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/functionalTests/test_dnd_autoScroll.html b/dojox/mdnd/tests/functionalTests/test_dnd_autoScroll.html
new file mode 100644
index 0000000..520337b
--- /dev/null
+++ b/dojox/mdnd/tests/functionalTests/test_dnd_autoScroll.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Drag And Drop - AutoScroll</title>
+
+	<link rel="stylesheet" type="text/css" href="../../../../dojo/resources/dojo.css" />
+	<link rel="stylesheet" type="text/css" href="../../../../dijit/themes/tundra/tundra.css" />
+	<link rel="stylesheet" type="text/css" href="../../../../dijit/tests/css/dijitTests.css" />
+	
+	<link rel="stylesheet" type="text/css" href="../../resources/dnd.css" />
+	<link rel="stylesheet" type="text/css" href="../resources/test_dnd.css" />
+
+	<style type="text/css">
+		
+		.draggedNode{
+			position:absolute;
+			width:120px;
+			height:120px;
+			background-color:#FFF;
+			border:1px solid #000;
+			padding:5px;
+		}
+		
+		.bigDiv{
+			top:0px;
+			left:0px;
+			width:1600px;
+			height:1600px;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dojox.mdnd.AutoScroll");
+		dojo.require("dojox.mdnd.Moveable");
+		
+		dojo.addOnLoad(function(){
+			var mov = new dojox.mdnd.Moveable({},dojo.byId("dragNode"));
+		});
+	</script>
+	
+	</head>
+	<body class="tundra">
+		<div class="bigDiv">
+			<h1>Drag and Drop</h1>
+			<div id="dragNode" class="draggedNode" style="left:150px;top:150px;">Drag me ! to see autoscroll working go out of the screen</div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/functionalTests/test_dnd_defaultDropMode.html b/dojox/mdnd/tests/functionalTests/test_dnd_defaultDropMode.html
new file mode 100644
index 0000000..9961e9b
--- /dev/null
+++ b/dojox/mdnd/tests/functionalTests/test_dnd_defaultDropMode.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+		<title>Dnd DefaultDropMode Test</title>
+		
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/resources/dojo.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/tests/dnd/dndDefault.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/themes/tundra/tundra.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/tests/css/dijitTests.css" />
+		
+		<link rel="stylesheet" type="text/css" href="../../resources/dnd.css" />
+		<link rel="stylesheet" type="text/css" href="../resources/test_dnd.css" />
+		
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="parseOnLoad:true, isDebug:false"></script>
+	
+		<script type="text/javascript">
+			dojo.require("dojox.mdnd.AreaManager");
+			dojo.require("dojox.mdnd.DropIndicator");
+			dojo.require("dojox.mdnd.dropMode.DefaultDropMode");
+			
+			var init = function(){
+				var m = dojox.mdnd.areaManager();
+				m.areaClass = "dndArea";
+				m.dragHandleClass = "dragHandle";
+				m.registerByClass();
+			};
+			
+			dojo.addOnLoad(init);
+		</script>
+	</head>
+	<body class="tundra">
+		<div id="main">
+			<h1>Drag and Drop</h1>
+			<div id="leftArea" class="dndArea container" style="top:80px; left: 50px;">
+				<div id="itemA" class="dndItem">
+					<div class="dragHandle">title</div>
+					<div>
+						<p>Proin aliquet accumsan nunc. Duis nec tortor. Aliquam erat volutpat. Fusce erat velit, fringilla vel, varius nec, rhoncus sed, quam. Morbi orci. In arcu dolor, tempor sit amet, mattis ac, dignissim sed, purus. Cras malesuada, massa et bibendum facilisis, metus eros tristique pede, ac ullamcorper urna pede at nulla. Morbi a nulla gravida tellus pellentesque commodo. In hac habitasse platea dictumst. Nunc sit amet nisl nec mauris venenatis pharetra. Nam tristique consequat justo.  [...]
+					</div>
+				</div>
+			</div>
+			<div id="middleArea" class="dndArea container" style="top:80px; left: 350px;"></div>
+			<div id="rightArea" class="dndArea container" style="top:80px; left: 650px;">
+				<div id="itemB" class="dndItem">
+					<div class="dragHandle">title</div>
+					<div class="fixedHeight">
+						<p>Proin aliquet accumsan nunc. Duis nec tortor. Aliquam erat volutpat. Fusce erat velit, fringilla vel, varius nec, rhoncus sed, quam. Morbi orci. In arcu dolor, tempor sit amet, mattis ac, dignissim sed, purus. Cras malesuada, massa et bibendum facilisis, metus eros tristique pede, ac ullamcorper urna pede at nulla. Morbi a nulla gravida tellus pellentesque commodo. In hac habitasse platea dictumst. Nunc sit amet nisl nec mauris venenatis pharetra. Nam tristique consequat justo.  [...]
+					</div>
+				</div>
+			</div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/functionalTests/test_dnd_dndFromDojo.html b/dojox/mdnd/tests/functionalTests/test_dnd_dndFromDojo.html
new file mode 100644
index 0000000..1e9b8be
--- /dev/null
+++ b/dojox/mdnd/tests/functionalTests/test_dnd_dndFromDojo.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+		<title>Dnd - Dojo Adapter (From dojo)</title>
+	
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/resources/dojo.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/tests/dnd/dndDefault.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/themes/tundra/tundra.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/tests/css/dijitTests.css" />
+		
+		<link rel="stylesheet" type="text/css" href="../../resources/dnd.css" />
+		<link rel="stylesheet" type="text/css" href="../resources/test_dnd.css" />
+		
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="parseOnLoad:true, isDebug:true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojox.mdnd.AreaManager");
+			dojo.require("dojox.mdnd.DropIndicator");
+			dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+			dojo.require("dojox.mdnd.AutoScroll");
+			dojo.require("dojox.mdnd.PureSource");
+			dojo.require("dojo.dnd.Source");
+			dojo.require("dojox.mdnd.adapter.DndFromDojo");
+			dojo.require("dijit._base.sniff");
+			var init = function(){
+				var m = dojox.mdnd.areaManager();
+				m.areaClass = "dndArea";
+				m.dragHandleClass = "dragHandle";
+				m.init();
+
+				dojo.subscribe("/dnd/drop/after","createNode");					
+			};
+			
+			dojo.addOnLoad(init);
+			
+			function createNode(source, nodes, copy, target, dropIndex){
+				var node = dojo.byId("item").cloneNode(true);
+				if(target){
+					dojox.mdnd.areaManager().addDragItem(target, node, dropIndex);
+				}
+			}
+		</script>
+	</head>
+	<body class="tundra">
+		<h1>Drag and Drop : dojo Dnd to Dojox Dnd</h1>
+		<div style="position:absolute;width:200px;left:350px;top:50px;">
+			<H2>Pure Source</H2>
+			<div id="dojoPureSource" dojoType="dojox.mdnd.PureSource" class="container">
+				<div class="dojoDndItem" dndType="type1">item Type1</div>
+				<div class="dojoDndItem" dndType="type2">item Type2</div>
+			</div>
+		</div>
+		<div style="position:absolute;width:200px;left:350px;top:200px;">
+			<H2>Source/Target Dojo</H2>
+			<p>Accepts Type1 & Type2 dojo's items</p>
+			<div id="dojoSource" dojoType="dojo.dnd.Source" accept="type1, type2, text" class="container">
+				<div class="dojoDndItem" dndType="type1">item Type1</div>
+				<div class="dojoDndItem" dndType="type2">item Type2</div>
+			</div>
+		</div>
+		<div style="position:absolute;width:200px;left:50 px;top:50px;">
+			<H2>Source/Target dojox </H2>
+			<p>Accepts only Type1 items</p>
+			<div class="dndArea container" accept="type1, text">
+				<div id="item" class="dndItem">
+					<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
+				</div>
+			</div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/functionalTests/test_dnd_dndToDojo.html b/dojox/mdnd/tests/functionalTests/test_dnd_dndToDojo.html
new file mode 100644
index 0000000..477dc0e
--- /dev/null
+++ b/dojox/mdnd/tests/functionalTests/test_dnd_dndToDojo.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+		<title>Dnd - Dojo Adapter (To Dojo)</title>
+	
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/resources/dojo.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/tests/dnd/dndDefault.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/themes/tundra/tundra.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/tests/css/dijitTests.css" />
+		
+		<link rel="stylesheet" type="text/css" href="../../resources/dnd.css" />
+		<link rel="stylesheet" type="text/css" href="../resources/test_dnd.css" />
+		
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="parseOnLoad:true, isDebug:true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojox.mdnd.AreaManager");
+			dojo.require("dojox.mdnd.DropIndicator");
+			dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+			dojo.require("dojox.mdnd.AutoScroll");
+			dojo.require("dojo.dnd.Source");
+			dojo.require("dojox.mdnd.adapter.DndToDojo");
+			dojo.ready(function(){
+				var m = dojox.mdnd.areaManager();
+				m.areaClass = "dndArea";
+				m.dragHandleClass = "dragHandle";
+				var adapter = dojox.mdnd.adapter.dndToDojo();
+				adapter.register(dojo.byId("dojoSource"), "", true);
+				adapter.register(dojo.byId("domTarget"), "domTarget");
+				m.init();
+				
+				// when we register just a DOMNode, integration step is needed :
+				// --------------------------------------------------------------
+				// Rewrite isAccepted method (only for registered dom);
+				adapter.isAccepted = function(draggedNode, target){
+					if(target.type == "domTarget"){
+						var dndType = dojo.attr(draggedNode, "dndType");
+						return (dndType == "type2") ? true : false;
+					}
+				};
+				dojo.subscribe("/dojox/mdnd/adapter/dndToDojo/over", null,  "onOver");
+				dojo.subscribe("/dojox/mdnd/adapter/dndToDojo/out", null, "onOut");
+				dojo.subscribe("/dojox/mdnd/adapter/dndToDojo/drop", null, "onDrop");
+				dojo.subscribe("/dojox/mdnd/adapter/dndToDojo/cancel", null, "onOut");
+			});
+			
+			function onOver(target, type, draggedNode, accept){
+				if(type == "domTarget"){
+					dojo.addClass(draggedNode, (accept) ? "dndOver" : "dndOverNotAccepted");
+				}
+			};
+			function onOut(target, type, draggedNode, accept){
+				dojo.removeClass(draggedNode, "dndOver dndOverNotAccepted");
+			};
+			function onDrop(draggedNode, target, type){
+				onOut(target, type, draggedNode);
+				target.appendChild(draggedNode);
+			}
+		</script>
+	</head>
+	<body class="tundra">
+		<h1>Drag and Drop : Dojox Dnd to Dojo Dnd</h1>
+		<div style="position:absolute;width:200px;left:50px;top:50px;">
+			<H2>Source/Target Dojox</H2>
+			<div class="dndArea container" accept="type1, type2, type3, text">
+				<div class="dndItem" dndType="type1">
+					<div class="title dragHandle" id="handle1">Item Type1</div>
+					<div>
+						<p>Proin aliquet accumsan nunc. Duis nec tortor.</p>
+					</div>
+				</div>
+				<div class="dndItem" dndType="type2">
+					<div class="title dragHandle" id="handle1">Item Type2</div>
+					<div>
+						<p>Proin aliquet accumsan nunc. Duis nec tortor.</p>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div style="position:absolute;width:200px;left:350px;top:50px;">
+			<H2>Source/Target Dojo</H2>
+			<h3>Accepts only Type1 items</h3>
+			<div id="dojoSource" dojoType="dojo.dnd.Source" accept="type1, text" class="container" style="width:200px;height:200px;"></div>
+		</div>
+		<div style="position:absolute;width:200px;left:700px;top:50px;">
+			<H2>Target DOM </H2>
+			<h3>Accepts only Type2 items</h3>
+			<div id="domTarget" class="container" style="width:200px;height:200px;"></div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/functionalTests/test_dnd_dndToDojo_dndFromDojo.html b/dojox/mdnd/tests/functionalTests/test_dnd_dndToDojo_dndFromDojo.html
new file mode 100644
index 0000000..07d7c09
--- /dev/null
+++ b/dojox/mdnd/tests/functionalTests/test_dnd_dndToDojo_dndFromDojo.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+		<title>Dnd - Dojo Adapter (To Dojo & From Dojo)</title>
+	
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/resources/dojo.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/tests/dnd/dndDefault.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/themes/tundra/tundra.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/tests/css/dijitTests.css" />
+		
+		<link rel="stylesheet" type="text/css" href="../../resources/dnd.css" />
+		<link rel="stylesheet" type="text/css" href="../resources/test_dnd.css" />
+		
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="parseOnLoad:true, isDebug:true"></script>
+
+		<script type="text/javascript">
+			dojo.require("dojox.mdnd.AreaManager");
+			dojo.require("dojox.mdnd.DropIndicator");
+			dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+			dojo.require("dojox.mdnd.AutoScroll");
+			dojo.require("dojo.dnd.Source");
+			dojo.require("dojox.mdnd.adapter.DndToDojo");
+			dojo.require("dojox.mdnd.adapter.DndFromDojo");
+			
+			dojo.ready(function(){
+				var m = dojox.mdnd.areaManager();
+				m.areaClass = "dndArea";
+				m.dragHandleClass = "dragHandle";
+				dojox.mdnd.adapter.dndToDojo().register(dojo.byId("dojoSource"), "", true);
+				m.init();
+				
+				// integration dndFromDojo :
+				dojo.subscribe("/dnd/drop/after", "dropInDojox");
+			});
+			
+			function dropInDojox(source, nodes, copy, target, dropIndex){
+				if(target){
+					dojox.mdnd.areaManager().addDragItem(target, nodes[0], dropIndex, true);
+				}
+			}
+		</script>
+	</head>
+	<body class="tundra">
+		<h1>Drag and Drop</h1>
+		<div style="position:absolute;width:200px;left:50px;top:50px;">
+			<H2>Source/Target Dojox</H2>
+			<div class="dndArea container" accept="type1, type2, type3, text">
+				<div class="dndItem" dndType="type1">
+					<div class="title dragHandle" id="handle1">Item Type1</div>
+					<div>
+						<p>Proin aliquet accumsan nunc. Duis nec tortor.</p>
+					</div>
+				</div>
+				<div class="dndItem" dndType="type2">
+					<div class="title dragHandle" id="handle1">Item Type2</div>
+					<div>
+						<p>Proin aliquet accumsan nunc. Duis nec tortor.</p>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div style="position:absolute;width:200px;left:350px;top:50px;">
+			<H2>Source/Target Dojo</H2>
+			<h3>Accepts only Type1 items</h3>
+			<div id="dojoSource" dojoType="dojo.dnd.Source" accept="type1, text" class="container" style="width:200px;height:200px;"></div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/functionalTests/test_dnd_overDropMode.html b/dojox/mdnd/tests/functionalTests/test_dnd_overDropMode.html
new file mode 100644
index 0000000..62163ae
--- /dev/null
+++ b/dojox/mdnd/tests/functionalTests/test_dnd_overDropMode.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+		<title>Dnd OverDropMode Test</title>
+		
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/resources/dojo.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/tests/dnd/dndDefault.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/themes/tundra/tundra.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/tests/css/dijitTests.css" />
+		
+		<link rel="stylesheet" type="text/css" href="../../resources/dnd.css" />
+		<link rel="stylesheet" type="text/css" href="../resources/test_dnd.css" />
+
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="parseOnLoad:true, isDebug:false"></script>
+	
+		<script type="text/javascript">
+			dojo.require("dojox.mdnd.AreaManager");
+			dojo.require("dojox.mdnd.DropIndicator");
+			dojo.require("dojox.mdnd.dropMode.OverDropMode");
+			
+			var init = function(){
+				var m = dojox.mdnd.areaManager();
+				m.areaClass = "dndArea";
+				m.dragHandleClass = "dragHandle";
+				m.registerByClass();
+			};
+			
+			dojo.addOnLoad(init);
+		</script>
+	</head>
+	<body class="tundra">
+		<div id="main">
+			<h1>Drag and Drop : OverDropMode</h1>
+			<div id="topLeftArea" class="dndArea container" style="top:100px; left:50px;">
+				<div id="itemA" class="dndItem">
+					<div class="title dragHandle">title</div>
+						<div>
+							<p>Proin aliquet accumsan nunc.</p>
+						</div>
+					</div>
+				</div>
+			</div>
+			<div id="topRightArea" class="dndArea container" style="top:100px; left:350px;"></div>
+			<div id="bottomLeftArea" class="dndArea container" style="top:350px; left:50px;">
+				<div id="itemB" class="dndItem">
+					<div class="title dragHandle">title</div>
+					<div>
+						<p>Proin aliquet accumsan nunc.</p>
+					</div>
+				</div>
+			</div>
+			<div id="bottomRightArea" class="dndArea container" style="top:350px; left:350px;"></div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/functionalTests/test_dnd_stress.html b/dojox/mdnd/tests/functionalTests/test_dnd_stress.html
new file mode 100644
index 0000000..7258258
--- /dev/null
+++ b/dojox/mdnd/tests/functionalTests/test_dnd_stress.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+		<title>Drag And Drop - stress test</title>
+		
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/resources/dojo.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/tests/dnd/dndDefault.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/themes/tundra/tundra.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/tests/css/dijitTests.css" />
+		
+		<link rel="stylesheet" type="text/css" href="../../resources/dnd.css" />
+		<link rel="stylesheet" type="text/css" href="../resources/test_dnd.css" />
+
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="parseOnLoad:true, isDebug:false"></script>
+	
+		<script type="text/javascript">
+			dojo.require("dojox.mdnd.AreaManager");
+			dojo.require("dojox.mdnd.DropIndicator");
+			dojo.require("dojox.mdnd.AutoScroll");
+			dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+			dojo.require("dijit._base.manager");
+
+			var queryCount = location.search.match(/count=(\d*)/);
+			var count = (queryCount ? parseInt(queryCount[1]) : 10);
+
+			var init = function(){
+				//console.log("init");
+				var item = dojo.query(".item")[0];
+				clone(item, dojo.byId("area1"));
+				clone(item, dojo.byId("area2"));
+				clone(item, dojo.byId("area3"));
+				clone(item, dojo.byId("area4"));
+				var m = dojox.mdnd.areaManager();
+				m.areaClass = "dndArea";
+				m.dragHandleClass = "dragHandle";
+				m.init();	
+			};
+
+			dojo.addOnLoad(init);
+
+			function clone(item, parentNode){
+				for(var i=1;i<=count;i++){
+					var clone = item.cloneNode(true);
+					clone.className = (i%2) ? "item" : "item2";
+					clone.id=dijit.getUniqueId("item");
+					var divHandle= clone.getElementsByTagName("div")[0];
+					divHandle.id = clone.id + "_" + dijit.getUniqueId("handle");
+					divHandle.innerHTML = divHandle.id;
+					parentNode.appendChild(clone);
+				}
+			}
+		</script>
+		<style type="text/css">
+			.item {
+				margin:10px;
+				background-color:#FFF;
+				border:solid 2px #BBB;
+			}
+			.item2 {
+				margin:10px;
+				background-color:#FFF;
+				
+				border:solid 2px #FFF;
+			}
+		</style>
+	</head>
+	<body class="tundra">
+		Pass <code>?count=<i><b>10</b></i></code> in the query string to change the number of div for each column.<br><br>
+		<div id="area1" class="area dndArea container" style="left:0px; width:250px; min-height:400px;">
+			<div class="item">
+				<div class="title dragHandle">title</div>
+				<div>
+					<p>Proin aliquet accumsan nunc. Duis nec tortor. Aliquam erat volutpat. Fusce erat velit, fringilla vel, varius nec, rhoncus sed, quam. Morbi orci. In arcu dolor, tempor sit amet, mattis ac, dignissim sed, purus.</p>
+				</div>
+			</div>
+		</div>
+		<div id="area2" class="area dndArea container" style="left:270px; width:250px; min-height:400px;"></div>
+		<div id="area3" class="area dndArea container" style="left:540px; width:250px; min-height:400px;"></div>
+		<div id="area4" class="area dndArea container" style="left:810px; width:250px; min-height:400px;"></div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/functionalTests/test_dnd_verticalDropMode.html b/dojox/mdnd/tests/functionalTests/test_dnd_verticalDropMode.html
new file mode 100644
index 0000000..dba6495
--- /dev/null
+++ b/dojox/mdnd/tests/functionalTests/test_dnd_verticalDropMode.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+		<title>Dnd VerticalDropMode Test</title>
+		
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/resources/dojo.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dojo/tests/dnd/dndDefault.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/themes/tundra/tundra.css" />
+		<link rel="stylesheet" type="text/css" href="../../../../dijit/tests/css/dijitTests.css" />
+		
+		<link rel="stylesheet" type="text/css" href="../../resources/dnd.css" />
+		<link rel="stylesheet" type="text/css" href="../resources/test_dnd.css" />
+		
+		<script type="text/javascript" src="../../../../dojo/dojo.js"
+			djConfig="parseOnLoad:true, isDebug:false"></script>
+	
+		<script type="text/javascript">
+			dojo.require("dojox.mdnd.AreaManager");
+			dojo.require("dojox.mdnd.DropIndicator");
+			dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+			
+			var init = function(){
+				var m = dojox.mdnd.areaManager();
+				m.areaClass = "dndArea";
+				m.dragHandleClass = "dragHandle";
+				m.registerByClass();
+			};
+			
+			dojo.addOnLoad(init);
+		</script>
+	</head>
+	<body class="tundra">
+		<div id="main">
+			<h1>Drag and Drop : VerticalDropMode</h1>
+			<div id="leftArea" class="dndArea container" style="top:80px; left: 50px;">
+				<div id="itemA" class="dndItem">
+					<div class="title dragHandle">title</div>
+					<div>
+						<p>Proin aliquet accumsan nunc. Duis nec tortor. Aliquam erat volutpat. Fusce erat velit, fringilla vel, varius nec, rhoncus sed, quam. Morbi orci. In arcu dolor, tempor sit amet, mattis ac, dignissim sed, purus. Cras malesuada, massa et bibendum facilisis, metus eros tristique pede, ac ullamcorper urna pede at nulla. Morbi a nulla gravida tellus pellentesque commodo. In hac habitasse platea dictumst. Nunc sit amet nisl nec mauris venenatis pharetra. Nam tristique consequat justo.  [...]
+					</div>
+				</div>
+			</div>
+			<div id="middleArea" class="dndArea container" style="top:80px; left: 350px;"></div>
+			<div id="rightArea" class="dndArea container" style="top:80px; left: 650px;">
+				<div id="itemB" class="dndItem">
+					<div class="title dragHandle">title</div>
+					<div class="fixedHeight">
+						<p>Proin aliquet accumsan nunc. Duis nec tortor. Aliquam erat volutpat. Fusce erat velit, fringilla vel, varius nec, rhoncus sed, quam. Morbi orci. In arcu dolor, tempor sit amet, mattis ac, dignissim sed, purus. Cras malesuada, massa et bibendum facilisis, metus eros tristique pede, ac ullamcorper urna pede at nulla. Morbi a nulla gravida tellus pellentesque commodo. In hac habitasse platea dictumst. Nunc sit amet nisl nec mauris venenatis pharetra. Nam tristique consequat justo.  [...]
+					</div>
+				</div>
+			</div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/module.js b/dojox/mdnd/tests/module.js
new file mode 100644
index 0000000..5bf31db
--- /dev/null
+++ b/dojox/mdnd/tests/module.js
@@ -0,0 +1,16 @@
+dojo.provide("dojox.mdnd.tests.module");
+
+try{
+	dojo.require("dojox.mdnd.tests.unitTests.module");
+	dojo.require("dojox.mdnd.tests.robot.module");
+}catch(e){
+	doh.debug(e);
+}
+dojo.provide("dojox.mdnd.tests.module");
+
+try{
+	dojo.require("dojox.mdnd.tests.unitTests.module");
+	dojo.require("dojox.mdnd.tests.robot.module");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/mdnd/tests/resources/test_dnd.css b/dojox/mdnd/tests/resources/test_dnd.css
new file mode 100644
index 0000000..711918f
--- /dev/null
+++ b/dojox/mdnd/tests/resources/test_dnd.css
@@ -0,0 +1,68 @@
+ at CHARSET "UTF-8";
+
+.dndArea{
+	position:absolute;
+	background-color:#E1EBFB;
+	border:2px solid #BBB;
+	min-height:200px;
+	margin:0px;
+	padding:0px;
+	width:250px;
+}
+
+.dndItem{
+	position:relative;
+	height:auto;
+	background-color:#FFF;
+	border:1px solid #000;
+	padding:5px;
+}
+
+.title{
+	background-color:#CCC;
+	padding:5px;
+	cursor: move;
+}
+
+.dndItem, .dropIndicator{
+	margin:10px;
+}
+
+.dndOver{
+	opacity: 0.6;
+	filter: alpha(opacity=60);
+}
+			
+.dndOverNotAccepted{
+	opacity: 1;
+	filter: alpha(opacity=100);
+}
+ at CHARSET "UTF-8";
+
+.dndArea{
+	position:absolute;
+	background-color:#E1EBFB;
+	border:2px solid #BBB;
+	min-height:200px;
+	margin:0px;
+	padding:0px;
+	width:250px;
+}
+
+.dndItem{
+	position:relative;
+	height:auto;
+	background-color:#FFF;
+	border:1px solid #000;
+	padding:5px;
+}
+
+.dragHandle{
+	background-color:#CCC;
+	padding:5px;
+	cursor: move;
+}
+
+.dndItem, .dropIndicator{
+	margin:10px;
+}
diff --git a/dojox/mdnd/tests/robot/module.js b/dojox/mdnd/tests/robot/module.js
new file mode 100644
index 0000000..28a6bed
--- /dev/null
+++ b/dojox/mdnd/tests/robot/module.js
@@ -0,0 +1,16 @@
+dojo.provide("dojox.mdnd.tests.robot.module");
+
+try{
+	doh.registerUrl("dojox.mdnd.tests.robot.Acceptance",
+			dojo.moduleUrl("dojox.mdnd","tests/robot/test_dnd_acceptance.html"),60000);
+	doh.registerUrl("dojox.mdnd.tests.robot.VerticalDropMode",
+			dojo.moduleUrl("dojox.mdnd","tests/robot/test_dnd_verticalDropMode.html"),60000);
+	doh.registerUrl("dojox.mdnd.tests.robot.OverDropMode",
+			dojo.moduleUrl("dojox.mdnd","tests/robot/test_dnd_overDropMode.html"),60000);
+	doh.registerUrl("dojox.mdnd.tests.robot.DndToDojo",
+			dojo.moduleUrl("dojox.mdnd","tests/robot/test_dnd_dndToDojo.html"),60000);
+	doh.registerUrl("dojox.mdnd.tests.robot.DndFromDojo", 
+			dojo.moduleUrl("dojox.mdnd","tests/robot/test_dnd_dndFromDojo.html"),60000);
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/mdnd/tests/robot/test_dnd_acceptance.html b/dojox/mdnd/tests/robot/test_dnd_acceptance.html
new file mode 100644
index 0000000..24b6a31
--- /dev/null
+++ b/dojox/mdnd/tests/robot/test_dnd_acceptance.html
@@ -0,0 +1,284 @@
+<html>
+	<head>
+		<title>Robot - Acceptance</title>
+		
+		<script type="text/javascript" 
+			src="../../../../dojo/dojo.js" 
+			djConfig="isDebug: true, parseOnLoad: true">
+		</script>
+		
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");	
+			dojo.require("dojo.parser");
+			
+			dojo.addOnLoad(function(){			
+				
+				doh.robot.initRobot('../functionalTests/test_dnd_acceptance.html');
+				doh.register("test_dnd_acceptance", 
+					[
+						{
+							name: "dropAccepted",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between two dnd 
+								// area :
+								// 		- Item's type : 1
+								//		- Drop area accept types : 1 & 2
+								// -> In this case, drop is accepted
+
+								var d = new doh.Deferred();
+
+								var areaType1 = dojo.query('.dndArea[accept=type1]')[0];
+								var areaTypeAll = dojo.query('.dndArea[accept*=type1][accept*=type2]')[0];
+
+								var itemType1 =	dojo.query('.dndItem[dndType=type1] > .dragHandle')[0];
+								var itemTypeAll = dojo.query('.dndItem[dndType*=type1][dndType*=type2] > .dragHandle')[0];
+								
+								var sizeA = areaType1.childNodes.length;
+	                			var sizeB = areaTypeAll.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemType1,200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(areaTypeAll,200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+	                					doh.assertEqual(areaTypeAll.childNodes.length, sizeB + 1, "An item should be drop on third area.");
+	                					doh.assertEqual(areaType1.childNodes.length, sizeA - 1, "An item should be remove from first area");
+	                					d.callback(true);
+	                				}
+	                				catch(e){
+	                					d.errback(e);
+	                				}
+	               				}, 200);
+	               				return d;
+							}
+						},
+						{
+							name: "dropAccepted2",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between two dnd area.
+								// 		- Item's type : 1 & 2
+								//		- Drop area accept type : 2
+								// -> In this case, drop is accepted
+
+								var d = new doh.Deferred();
+
+								var areaType2 = dojo.query('.dndArea[accept=type2]')[0];
+								var areaTypeAll = dojo.query('.dndArea[accept*=type1][accept*=type2]')[0];
+
+								var itemTypeAll = dojo.query('.dndItem[dndType*=type1][dndType*=type2] > .dragHandle')[0];
+
+	                			var sizeA = areaTypeAll.childNodes.length;
+								var sizeB = areaType2.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemTypeAll, 200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(areaType2, 200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+		                				doh.assertEqual(areaType2.childNodes.length, sizeB + 1, "An item should be drop on second area.");
+		                				doh.assertEqual(areaTypeAll.childNodes.length, sizeA - 1, "An item should be remove from third area.");
+		                      			d.callback(true);
+		                      		}catch(e){
+		                      			d.errback(e);
+		                      		}
+	               				}, 200);
+	               				return d;
+							}
+						},
+						{
+							name: "refused",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between two dnd area.
+								// 		- Item's type : 1
+								//		- Drop area accept type : 2
+								// -> In this case, drop is refused
+
+								var d = new doh.Deferred();
+
+								var areaType2 = dojo.query('.dndArea[accept=type2]')[0];
+								var areaTypeAll = dojo.query('.dndArea[accept*=type1][accept*=type2]')[0];
+
+								var itemType1 = dojo.query('.dndItem[dndType=type1] > .dragHandle')[0];
+								
+								var sizeA = areaType2.childNodes.length;
+	                			var sizeB = areaTypeAll.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemType1, 200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(areaType2, 200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+		                				doh.assertEqual(areaType2.childNodes.length, sizeA, "No change !");
+		                				doh.assertEqual(areaTypeAll.childNodes.length, sizeB, "No change !");
+		                      			d.callback(true);
+		                      		}catch(e){
+		                      			d.errback(e);
+		                      		}
+	               				 }, 200);
+	               				 return d;
+							}
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css"></style>
+	</head>
+	<body class="tundra">
+	</body>
+</html>
+<html>
+	<head>
+		<title>Robot - Acceptance</title>
+		
+		<script type="text/javascript" 
+			src="../../../../dojo/dojo.js" 
+			djConfig="isDebug: true, parseOnLoad: true">
+		</script>
+		
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");	
+			dojo.require("dojo.parser");
+			
+			dojo.addOnLoad(function(){			
+				
+				doh.robot.initRobot('../functionalTests/test_dnd_acceptance.html');
+				doh.register("test_dnd_acceptance", 
+					[
+						{
+							name: "dropAccepted",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between two dnd 
+								// area :
+								// 		- Item's type : 1
+								//		- Drop area accept types : 1 & 2
+								// -> In this case, drop is accepted
+
+								var d = new doh.Deferred();
+
+								var areaType1 = dojo.query('.dndArea[accept=type1]')[0];
+								var areaTypeAll = dojo.query('.dndArea[accept*=type1][accept*=type2]')[0];
+
+								var itemType1 =	dojo.query('.dndItem[dndType=type1] > .dragHandle')[0];
+								var itemTypeAll = dojo.query('.dndItem[dndType*=type1][dndType*=type2] > .dragHandle')[0];
+								
+								var sizeA = areaType1.childNodes.length;
+	                			var sizeB = areaTypeAll.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemType1,200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(areaTypeAll,200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+	                					doh.assertEqual(areaTypeAll.childNodes.length, sizeB + 1, "An item should be drop on third area.");
+	                					doh.assertEqual(areaType1.childNodes.length, sizeA - 1, "An item should be remove from first area");
+	                					d.callback(true);
+	                				}
+	                				catch(e){
+	                					d.errback(e);
+	                				}
+	               				}, 200);
+	               				return d;
+							}
+						},
+						{
+							name: "dropAccepted2",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between two dnd area.
+								// 		- Item's type : 1 & 2
+								//		- Drop area accept type : 2
+								// -> In this case, drop is accepted
+
+								var d = new doh.Deferred();
+
+								var areaType2 = dojo.query('.dndArea[accept=type2]')[0];
+								var areaTypeAll = dojo.query('.dndArea[accept*=type1][accept*=type2]')[0];
+
+								var itemTypeAll = dojo.query('.dndItem[dndType*=type1][dndType*=type2] > .dragHandle')[0];
+
+	                			var sizeA = areaTypeAll.childNodes.length;
+								var sizeB = areaType2.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemTypeAll, 200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(areaType2, 200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+		                				doh.assertEqual(areaType2.childNodes.length, sizeB + 1, "An item should be drop on second area.");
+		                				doh.assertEqual(areaTypeAll.childNodes.length, sizeA - 1, "An item should be remove from third area.");
+		                      			d.callback(true);
+		                      		}catch(e){
+		                      			d.errback(e);
+		                      		}
+	               				}, 200);
+	               				return d;
+							}
+						},
+						{
+							name: "refused",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between two dnd area.
+								// 		- Item's type : 1
+								//		- Drop area accept type : 2
+								// -> In this case, drop is refused
+
+								var d = new doh.Deferred();
+
+								var areaType2 = dojo.query('.dndArea[accept=type2]')[0];
+								var areaTypeAll = dojo.query('.dndArea[accept*=type1][accept*=type2]')[0];
+
+								var itemType1 = dojo.query('.dndItem[dndType=type1] > .dragHandle')[0];
+								
+								var sizeA = areaType2.childNodes.length;
+	                			var sizeB = areaTypeAll.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemType1, 200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(areaType2, 200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+		                				doh.assertEqual(areaType2.childNodes.length, sizeA, "No change !");
+		                				doh.assertEqual(areaTypeAll.childNodes.length, sizeB, "No change !");
+		                      			d.callback(true);
+		                      		}catch(e){
+		                      			d.errback(e);
+		                      		}
+	               				 }, 200);
+	               				 return d;
+							}
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css"></style>
+	</head>
+	<body class="tundra">
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mdnd/tests/robot/test_dnd_defaultDropMode.html b/dojox/mdnd/tests/robot/test_dnd_defaultDropMode.html
new file mode 100644
index 0000000..b122eb2
--- /dev/null
+++ b/dojox/mdnd/tests/robot/test_dnd_defaultDropMode.html
@@ -0,0 +1,101 @@
+<html>
+	<head>
+		<title>DefaultDropMode</title>
+		
+		<script type="text/javascript" 
+			src="../../../../dojo/dojo.js" 
+			djConfig="isDebug: true, parseOnLoad: true">
+		</script>
+		
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");	
+			dojo.require("dojo.parser");
+			dojo.require("dojox.mdnd.dropMode.DefaultDropMode");
+			
+			dojo.addOnLoad(function(){			
+				
+				doh.robot.initRobot('../functionalTests/test_dnd_defaultDropMode.html');
+				
+				doh.register("test_dnd_defaultDropMode", 
+					[
+						{
+							name: "moveClassic",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between Dnd 
+								// areas.
+								
+								var d = new doh.Deferred();
+
+								var leftArea = dojo.byId('leftArea');
+								var rightArea = dojo.byId('rightArea');
+
+								var itemA =	dojo.query('#itemA > .dragHandle')[0];
+								
+								var sizeA = leftArea.childNodes.length;
+	                			var sizeB = rightArea.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemA, 200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(rightArea,200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+	                					doh.assertEqual(rightArea.childNodes.length, sizeB + 1, "An item should be drop on the right area.");
+	                					doh.assertEqual(leftArea.childNodes.length, sizeA - 1, "An item should be remove from left area");
+	                					d.callback(true);
+	                				}
+	                				catch(e){
+	                					d.errback(e);
+	                				}
+	               				}, 200);
+	               				return d;
+							}
+						},
+						{
+							name: "dropIndicator",
+							timeout:1000,
+							runTest: function(){
+								var d = new doh.Deferred();
+
+								// Checks if the the dropIndicator is displayed.
+								
+								var leftArea = dojo.byId('leftArea');
+								var rightArea = dojo.byId('rightArea');
+
+								var itemA =	dojo.query('#itemA > .dragHandle')[0];
+								
+								var sizeA = rightArea.childNodes.length;
+	                			var sizeB = leftArea.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemA,200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(leftArea,200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+	                					doh.assertEqual(rightArea.childNodes.length, sizeA - 1, "Item should be remove from the right area.");
+	                					doh.assertEqual(leftArea.childNodes.length, sizeB + 1, "An item should be add to the left area.");
+	                					doh.assertEqual(dojo.query('.dropIndicator').length, 1, "Item in left area should be the dropIndicator.");
+	                					d.callback(true);
+	                				}
+	                				catch(e){
+	                					d.errback(e);
+	                				}
+	               				}, 200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	               				return d;
+							}
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css"></style>
+	</head>
+	<body class="tundra">
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mdnd/tests/robot/test_dnd_dndFromDojo.html b/dojox/mdnd/tests/robot/test_dnd_dndFromDojo.html
new file mode 100644
index 0000000..1afa12e
--- /dev/null
+++ b/dojox/mdnd/tests/robot/test_dnd_dndFromDojo.html
@@ -0,0 +1,322 @@
+<html>
+	<head>
+		<title>Robot - Adapter - DndFromDojo</title>
+		
+		<script type="text/javascript" 
+			src="../../../../dojo/dojo.js" 
+			djConfig="isDebug: true, parseOnLoad: true">
+		</script>
+		
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");	
+			dojo.require("dojo.parser");
+			
+			dojo.addOnLoad(function(){			
+				
+				doh.robot.initRobot('../functionalTests/test_dnd_dndFromDojo.html');
+				
+				doh.register("test_dnd_dndFromDojo", 
+				[
+					{
+						name: "dndFromPureSource",
+						timeout:6000,
+						runTest: function(){
+
+							// Moves an item from a dojo source to a dojox 
+							// target.
+
+							var d = new doh.Deferred();
+
+							var itemType1 = dojo.query("#dojoPureSource > [dndType*=type1]")[0];
+							var area = dojo.query(".dndArea")[0];
+
+							var sizeArea = area.childNodes.length
+							doh.robot.mouseMoveAt(itemType1, 100);
+                			doh.robot.mousePress({left:true}, 100);
+                			doh.robot.mouseMoveAt(area, 100);
+                			doh.robot.mouseRelease({left:true}, 100);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(area.childNodes.length ,sizeArea + 1, "A child should be drop in the dojox area.");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 100);
+               				return d;
+						}
+					},
+					{
+						name: "dndFromDojoSource",
+						timeout:10000,
+						runTest: function(){
+
+							// Moves an item from a dojo source/target to a 
+							// dojox target.
+
+							var d = new doh.Deferred();
+
+							var itemType1 = dojo.query("#dojoSource > [dndType*=type1]")[0];
+							var area = dojo.query(".dndArea")[0];
+
+							var sizeArea = area.childNodes.length
+							doh.robot.mouseMoveAt(itemType1, 200);
+                			doh.robot.mousePress({left:true}, 200);
+                			doh.robot.mouseMoveAt(area, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(area.childNodes.length ,sizeArea + 1, "A child should be drop in the dojox area.");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 200);
+               				return d;
+						}
+					},
+					{
+						name: "dndAcceptanceFromPureSource",
+						timeout:10000,
+						runTest: function(){
+
+							// Tries to move an item from  a dojo source to a 
+							// dojox areas :
+							// 		- Item's type : 2
+							//		- Drop area accept types : 1
+							// -> In this case, drop is refused
+
+							var d = new doh.Deferred();
+
+							var itemType2 = dojo.query("#dojoPureSource > [dndType*=type2]")[0];
+							var area = dojo.query(".dndArea")[0];
+
+							var sizeArea = area.childNodes.length
+							doh.robot.mouseMoveAt(itemType2, 200);
+                			doh.robot.mousePress({left:true}, 200);
+                			doh.robot.mouseMoveAt(area, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(area.childNodes.length ,sizeArea, "A type 2 item should not be drop in the dojox area.");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 200);
+               				return d;
+						}
+					},
+					{
+						name: "dndAcceptanceFromDojoSource",
+						timeout:10000,
+						runTest: function(){
+
+							// Tries to move an item from  a dojo source/target
+							// to a dojox area :
+							// 		- Item's type : 2
+							//		- Drop area accept types : 1
+							// -> In this case, drop is refused
+
+							var d = new doh.Deferred();
+
+							var itemType2 = dojo.query("#dojoSource > [dndType*=type2]")[0];
+							var area = dojo.query(".dndArea")[0];
+
+							var sizeArea = area.childNodes.length
+							
+							doh.robot.mouseMoveAt(itemType2, 200);
+                			doh.robot.mousePress({left:true}, 200);
+                			doh.robot.mouseMoveAt(area, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(area.childNodes.length ,sizeArea, "A type 2 item should not be drop in the dojox area.");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+               				return d;
+						}
+					}
+				]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css"></style>
+	</head>
+	<body class="tundra">
+	</body>
+</html>
+<html>
+	<head>
+		<title>Robot - Adapter - DndFromDojo</title>
+		
+		<script type="text/javascript" 
+			src="../../../../dojo/dojo.js" 
+			djConfig="isDebug: true, parseOnLoad: true">
+		</script>
+		
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");	
+			dojo.require("dojo.parser");
+			
+			dojo.addOnLoad(function(){			
+				
+				doh.robot.initRobot('../functionalTests/test_dnd_dndFromDojo.html');
+				
+				doh.register("test_dnd_dndFromDojo", 
+				[
+					{
+						name: "dndFromPureSource",
+						timeout:6000,
+						runTest: function(){
+
+							// Moves an item from a dojo source to a dojox 
+							// target.
+
+							var d = new doh.Deferred();
+
+							var itemType1 = dojo.query("#dojoPureSource > [dndType*=type1]")[0];
+							var area = dojo.query(".dndArea")[0];
+
+							var sizeArea = area.childNodes.length
+							doh.robot.mouseMoveAt(itemType1, 100);
+                			doh.robot.mousePress({left:true}, 100);
+                			doh.robot.mouseMoveAt(area, 100);
+                			doh.robot.mouseRelease({left:true}, 100);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(area.childNodes.length ,sizeArea + 1, "A child should be drop in the dojox area.");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 100);
+               				return d;
+						}
+					},
+					{
+						name: "dndFromDojoSource",
+						timeout:10000,
+						runTest: function(){
+
+							// Moves an item from a dojo source/target to a 
+							// dojox target.
+
+							var d = new doh.Deferred();
+
+							var itemType1 = dojo.query("#dojoSource > [dndType*=type1]")[0];
+							var area = dojo.query(".dndArea")[0];
+
+							var sizeArea = area.childNodes.length
+							doh.robot.mouseMoveAt(itemType1, 200);
+                			doh.robot.mousePress({left:true}, 200);
+                			doh.robot.mouseMoveAt(area, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(area.childNodes.length ,sizeArea + 1, "A child should be drop in the dojox area.");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 200);
+               				return d;
+						}
+					},
+					{
+						name: "dndAcceptanceFromPureSource",
+						timeout:10000,
+						runTest: function(){
+
+							// Tries to move an item from  a dojo source to a 
+							// dojox areas :
+							// 		- Item's type : 2
+							//		- Drop area accept types : 1
+							// -> In this case, drop is refused
+
+							var d = new doh.Deferred();
+
+							var itemType2 = dojo.query("#dojoPureSource > [dndType*=type2]")[0];
+							var area = dojo.query(".dndArea")[0];
+
+							var sizeArea = area.childNodes.length
+							doh.robot.mouseMoveAt(itemType2, 200);
+                			doh.robot.mousePress({left:true}, 200);
+                			doh.robot.mouseMoveAt(area, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(area.childNodes.length ,sizeArea, "A type 2 item should not be drop in the dojox area.");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 200);
+               				return d;
+						}
+					},
+					{
+						name: "dndAcceptanceFromDojoSource",
+						timeout:10000,
+						runTest: function(){
+
+							// Tries to move an item from  a dojo source/target
+							// to a dojox area :
+							// 		- Item's type : 2
+							//		- Drop area accept types : 1
+							// -> In this case, drop is refused
+
+							var d = new doh.Deferred();
+
+							var itemType2 = dojo.query("#dojoSource > [dndType*=type2]")[0];
+							var area = dojo.query(".dndArea")[0];
+
+							var sizeArea = area.childNodes.length
+							
+							doh.robot.mouseMoveAt(itemType2, 200);
+                			doh.robot.mousePress({left:true}, 200);
+                			doh.robot.mouseMoveAt(area, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(area.childNodes.length ,sizeArea, "A type 2 item should not be drop in the dojox area.");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+               				return d;
+						}
+					}
+				]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css"></style>
+	</head>
+	<body class="tundra">
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mdnd/tests/robot/test_dnd_dndToDojo.html b/dojox/mdnd/tests/robot/test_dnd_dndToDojo.html
new file mode 100644
index 0000000..ccdeeb7
--- /dev/null
+++ b/dojox/mdnd/tests/robot/test_dnd_dndToDojo.html
@@ -0,0 +1,198 @@
+<html>
+	<head>
+		<title>Robot - Adapter - DndFromDojo</title>
+		
+		<script type="text/javascript" 
+			src="../../../../dojo/dojo.js" 
+			djConfig="isDebug: true, parseOnLoad: true">
+		</script>
+		
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");	
+			dojo.require("dojo.parser");
+			
+			dojo.addOnLoad(function(){			
+				
+				doh.robot.initRobot('../functionalTests/test_dnd_dndToDojo.html');
+				
+				doh.register("test_dnd_dndToDojo", 
+				[
+					{
+						name: "dndToDojoSource",
+						timeout:10000,
+						runTest: function(){
+
+							// Moves an item from a dojox source to a dojo
+							// target.
+
+							var d = new doh.Deferred();
+
+							var itemType1 = dojo.query(".dndItem[dndType=type1] > .dragHandle")[0];
+							var source = dojo.query(".dndArea")[0];
+							var dojoTarget = dojo.query(".dojoDndTarget")[0];
+
+							var sizeArea = source.childNodes.length
+							
+							doh.robot.mouseMoveAt(itemType1, 200);
+                			doh.robot.mousePress({left:true}, 200);
+                			doh.robot.mouseMoveAt(dojoTarget, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(source.childNodes.length , sizeArea-1, "A child should be delete from dojox dnd area.");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 200);
+               				return d;
+						}
+					},
+					{
+						name: "dndToDojoAcceptance",
+						timeout:10000,
+						runTest: function(){
+
+							// Tries to move an item from a dojox source to
+							// a dojo area :
+							// 		- Item's type : 2
+							//		- Drop area accept types : 1
+							// -> In this case, drop is refused
+
+							var d = new doh.Deferred();
+							
+							var itemType2 = dojo.query(".dndItem[dndType=type2] > .dragHandle")[0];
+							var source = dojo.query(".dndArea")[0];
+							var dojoTarget = dojo.query(".dojoDndTarget")[0];
+
+							var sizeArea = source.childNodes.length
+							
+							doh.robot.mouseMoveAt(itemType2, 200);
+                			doh.robot.mousePress({left:true}, 200);
+                			doh.robot.mouseMoveAt(dojoTarget, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(source.childNodes.length ,sizeArea, "DnD restriction. No change !");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 200);
+               				
+               				return d;
+						}
+					}
+				]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css"></style>
+	</head>
+	<body class="tundra">
+	</body>
+</html>
+<html>
+	<head>
+		<title>Robot - Adapter - DndFromDojo</title>
+		
+		<script type="text/javascript" 
+			src="../../../../dojo/dojo.js" 
+			djConfig="isDebug: true, parseOnLoad: true">
+		</script>
+		
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");	
+			dojo.require("dojo.parser");
+			
+			dojo.addOnLoad(function(){			
+				
+				doh.robot.initRobot('../functionalTests/test_dnd_dndToDojo.html');
+				
+				doh.register("test_dnd_dndToDojo", 
+				[
+					{
+						name: "dndToDojoSource",
+						timeout:10000,
+						runTest: function(){
+
+							// Moves an item from a dojox source to a dojo
+							// target.
+
+							var d = new doh.Deferred();
+
+							var itemType1 = dojo.query(".dndItem[dndType=type1] > .dragHandle")[0];
+							var source = dojo.query(".dndArea")[0];
+							var dojoTarget = dojo.query(".dojoDndTarget")[0];
+
+							var sizeArea = source.childNodes.length
+							
+							doh.robot.mouseMoveAt(itemType1, 200);
+                			doh.robot.mousePress({left:true}, 200);
+                			doh.robot.mouseMoveAt(dojoTarget, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(source.childNodes.length , sizeArea-1, "A child should be delete from dojox dnd area.");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 200);
+               				return d;
+						}
+					},
+					{
+						name: "dndToDojoAcceptance",
+						timeout:10000,
+						runTest: function(){
+
+							// Tries to move an item from a dojox source to
+							// a dojo area :
+							// 		- Item's type : 2
+							//		- Drop area accept types : 1
+							// -> In this case, drop is refused
+
+							var d = new doh.Deferred();
+							
+							var itemType2 = dojo.query(".dndItem[dndType=type2] > .dragHandle")[0];
+							var source = dojo.query(".dndArea")[0];
+							var dojoTarget = dojo.query(".dojoDndTarget")[0];
+
+							var sizeArea = source.childNodes.length
+							
+							doh.robot.mouseMoveAt(itemType2, 200);
+                			doh.robot.mousePress({left:true}, 200);
+                			doh.robot.mouseMoveAt(dojoTarget, 200);
+                			doh.robot.mouseRelease({left:true}, 200);
+                			
+                			doh.robot.sequence(function(){
+                				try{
+                					doh.assertEqual(source.childNodes.length ,sizeArea, "DnD restriction. No change !");
+                					d.callback(true);
+                				}
+                				catch(e){
+                					d.errback(e);
+                				}
+               				}, 200);
+               				
+               				return d;
+						}
+					}
+				]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css"></style>
+	</head>
+	<body class="tundra">
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mdnd/tests/robot/test_dnd_overDropMode.html b/dojox/mdnd/tests/robot/test_dnd_overDropMode.html
new file mode 100644
index 0000000..c6c4bd6
--- /dev/null
+++ b/dojox/mdnd/tests/robot/test_dnd_overDropMode.html
@@ -0,0 +1,272 @@
+<html>	
+	<head>
+		<title>OverDropMode</title>
+		
+		<script type="text/javascript" 
+			src="../../../../dojo/dojo.js" 
+			djConfig="isDebug: true, parseOnLoad: true">
+		</script>
+		
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");	
+			
+			dojo.addOnLoad(function(){			
+				
+				doh.robot.initRobot('../functionalTests/test_dnd_overDropMode.html');
+				
+				doh.register("test_dnd_overDropMode", 
+					[
+						{
+							name: "horizontalMovement",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between 
+								// horizontal Dnd areas.
+
+								var d = new doh.Deferred();
+
+								var topLefArea = dojo.byId('topLeftArea');
+								var topRightArea = dojo.byId('topRightArea');
+
+								var itemA = dojo.query('#itemA > .dragHandle')[0];
+								
+								var sizeA = topLefArea.childNodes.length;
+	                			var sizeB = topRightArea.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemA,200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(topRightArea,200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+	                					doh.assertEqual(topRightArea.childNodes.length, sizeB + 1, 'Item should be drop on top right area.');
+	                					doh.assertEqual(topLefArea.childNodes.length, sizeA - 1, 'Item should be remove from top left area.');
+	                					d.callback(true);
+	                				}
+	                				catch(e){
+	                					d.errback(e);
+	                				}
+	               				}, 200);
+	               				return d;
+							}
+						},
+						{
+							name: "verticalMovement",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between 
+								// vertical Dnd areas.
+
+								var d = new doh.Deferred();
+
+								var topLefArea = dojo.byId('topLeftArea');
+								var bottomLeftArea = dojo.byId('bottomLeftArea');
+
+								var itemB = dojo.query('#itemB > .dragHandle')[0];
+								
+								var sizeA = bottomLeftArea.childNodes.length;
+	                			var sizeB = topLefArea.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemB,200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(topLefArea,200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+	                					doh.assertEqual(topLefArea.childNodes.length, sizeB + 1, "Item should be drop on top left area.");
+	                					doh.assertEqual(bottomLeftArea.childNodes.length, sizeA - 1, "Item should be remove from botton left area.");
+	                					d.callback(true);
+	                				}
+	                				catch(e){
+	                					d.errback(e);
+	                				}
+	               				}, 200);
+	               				return d;
+							}
+						},
+						{
+							name: "dropIndicator",
+							timeout:10000,
+							runTest: function(){
+							
+								// Checks if the the dropIndicator is displayed.
+							
+								var d = new doh.Deferred();
+
+								var topLefArea = dojo.byId('topLeftArea');
+								var topRightArea = dojo.byId('topRightArea');
+
+								var itemB = dojo.query('#itemB > .dragHandle')[0];
+								
+	                			var sizeA = topLefArea.childNodes.length;
+	                			var sizeB = topRightArea.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemB, 200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(topRightArea, 200);
+	                			
+	    			 			doh.robot.sequence(function(){
+	    			 				try{
+	    			 					doh.assertEqual(topLefArea.childNodes.length, sizeA - 1, "Item should be remove from top left area.");
+	    								doh.assertEqual(topRightArea.childNodes.length, sizeB + 1, "An item should be add to top right area.");
+	    								doh.assertEqual(dojo.query('.dropIndicator').length, 1, "Item added should be a drop indicator.");
+	    								d.callback(true);
+	    							}
+	    							catch(e){
+	    								d.errback(e);
+	    							}
+	   								}, 
+	   							200);
+	    			 			doh.robot.mouseRelease({left:true}, 200);
+	               				return d;
+							}
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body class="tundra">
+	</body>
+</html>
+<html>	
+	<head>
+		<title>OverDropMode</title>
+		
+		<script type="text/javascript" 
+			src="../../../../dojo/dojo.js" 
+			djConfig="isDebug: true, parseOnLoad: true">
+		</script>
+		
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");	
+			
+			dojo.addOnLoad(function(){			
+				
+				doh.robot.initRobot('../functionalTests/test_dnd_overDropMode.html');
+				
+				doh.register("test_dnd_overDropMode", 
+					[
+						{
+							name: "horizontalMovement",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between 
+								// horizontal Dnd areas.
+
+								var d = new doh.Deferred();
+
+								var topLefArea = dojo.byId('topLeftArea');
+								var topRightArea = dojo.byId('topRightArea');
+
+								var itemA = dojo.query('#itemA > .dragHandle')[0];
+								
+								var sizeA = topLefArea.childNodes.length;
+	                			var sizeB = topRightArea.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemA,200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(topRightArea,200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+	                					doh.assertEqual(topRightArea.childNodes.length, sizeB + 1, 'Item should be drop on top right area.');
+	                					doh.assertEqual(topLefArea.childNodes.length, sizeA - 1, 'Item should be remove from top left area.');
+	                					d.callback(true);
+	                				}
+	                				catch(e){
+	                					d.errback(e);
+	                				}
+	               				}, 200);
+	               				return d;
+							}
+						},
+						{
+							name: "verticalMovement",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between 
+								// vertical Dnd areas.
+
+								var d = new doh.Deferred();
+
+								var topLefArea = dojo.byId('topLeftArea');
+								var bottomLeftArea = dojo.byId('bottomLeftArea');
+
+								var itemB = dojo.query('#itemB > .dragHandle')[0];
+								
+								var sizeA = bottomLeftArea.childNodes.length;
+	                			var sizeB = topLefArea.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemB,200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(topLefArea,200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+	                					doh.assertEqual(topLefArea.childNodes.length, sizeB + 1, "Item should be drop on top left area.");
+	                					doh.assertEqual(bottomLeftArea.childNodes.length, sizeA - 1, "Item should be remove from botton left area.");
+	                					d.callback(true);
+	                				}
+	                				catch(e){
+	                					d.errback(e);
+	                				}
+	               				}, 200);
+	               				return d;
+							}
+						},
+						{
+							name: "dropIndicator",
+							timeout:10000,
+							runTest: function(){
+							
+								// Checks if the the dropIndicator is displayed.
+							
+								var d = new doh.Deferred();
+
+								var topLefArea = dojo.byId('topLeftArea');
+								var topRightArea = dojo.byId('topRightArea');
+
+								var itemB = dojo.query('#itemB > .dragHandle')[0];
+								
+	                			var sizeA = topLefArea.childNodes.length;
+	                			var sizeB = topRightArea.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemB, 200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(topRightArea, 200);
+	                			
+	    			 			doh.robot.sequence(function(){
+	    			 				try{
+	    			 					doh.assertEqual(topLefArea.childNodes.length, sizeA - 1, "Item should be remove from top left area.");
+	    								doh.assertEqual(topRightArea.childNodes.length, sizeB + 1, "An item should be add to top right area.");
+	    								doh.assertEqual(dojo.query('.dropIndicator').length, 1, "Item added should be a drop indicator.");
+	    								d.callback(true);
+	    							}
+	    							catch(e){
+	    								d.errback(e);
+	    							}
+	   								}, 
+	   							200);
+	    			 			doh.robot.mouseRelease({left:true}, 200);
+	               				return d;
+							}
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+	</head>
+	<body class="tundra">
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mdnd/tests/robot/test_dnd_verticalDropMode.html b/dojox/mdnd/tests/robot/test_dnd_verticalDropMode.html
new file mode 100644
index 0000000..b9e131f
--- /dev/null
+++ b/dojox/mdnd/tests/robot/test_dnd_verticalDropMode.html
@@ -0,0 +1,101 @@
+<html>
+	<head>
+		<title>VerticalDropMode</title>
+		
+		<script type="text/javascript" 
+			src="../../../../dojo/dojo.js" 
+			djConfig="isDebug: true, parseOnLoad: true">
+		</script>
+		
+		<script type="text/javascript">
+			dojo.require("dijit.robotx");	
+			dojo.require("dojo.parser");
+			dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+			
+			dojo.addOnLoad(function(){			
+				
+				doh.robot.initRobot('../functionalTests/test_dnd_verticalDropMode.html');
+				
+				doh.register("test_dnd_verticalDropMode", 
+					[
+						{
+							name: "moveClassic",
+							timeout:10000,
+							runTest: function(){
+
+								// Tries to drag and drop an item between Dnd 
+								// areas.
+								
+								var d = new doh.Deferred();
+
+								var leftArea = dojo.byId('leftArea');
+								var rightArea = dojo.byId('rightArea');
+
+								var itemA =	dojo.query('#itemA > .dragHandle')[0];
+								
+								var sizeA = leftArea.childNodes.length;
+	                			var sizeB = rightArea.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemA, 200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(rightArea,200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+	                					doh.assertEqual(rightArea.childNodes.length, sizeB + 1, "An item should be drop on the right area.");
+	                					doh.assertEqual(leftArea.childNodes.length, sizeA - 1, "An item should be remove from left area");
+	                					d.callback(true);
+	                				}
+	                				catch(e){
+	                					d.errback(e);
+	                				}
+	               				}, 200);
+	               				return d;
+							}
+						},
+						{
+							name: "dropIndicator",
+							timeout:1000,
+							runTest: function(){
+								var d = new doh.Deferred();
+
+								// Checks if the the dropIndicator is displayed.
+								
+								var leftArea = dojo.byId('leftArea');
+								var rightArea = dojo.byId('rightArea');
+
+								var itemA =	dojo.query('#itemA > .dragHandle')[0];
+								
+								var sizeA = rightArea.childNodes.length;
+	                			var sizeB = leftArea.childNodes.length;
+	                			
+	                			doh.robot.mouseMoveAt(itemA,200);
+	                			doh.robot.mousePress({left:true}, 200);
+	                			doh.robot.mouseMoveAt(leftArea,200);
+	                			
+	                			doh.robot.sequence(function(){
+	                				try{
+	                					doh.assertEqual(rightArea.childNodes.length, sizeA - 1, "Item should be remove from the right area.");
+	                					doh.assertEqual(leftArea.childNodes.length, sizeB + 1, "An item should be add to the left area.");
+	                					doh.assertEqual(dojo.query('.dropIndicator').length, 1, "Item in left area should be the dropIndicator.");
+	                					d.callback(true);
+	                				}
+	                				catch(e){
+	                					d.errback(e);
+	                				}
+	               				}, 200);
+	                			doh.robot.mouseRelease({left:true}, 200);
+	               				return d;
+							}
+						}
+					]
+				);
+				doh.run();
+			});
+		</script>
+		<style type="text/css"></style>
+	</head>
+	<body class="tundra">
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mdnd/tests/runTests.html b/dojox/mdnd/tests/runTests.html
new file mode 100644
index 0000000..f37d15f
--- /dev/null
+++ b/dojox/mdnd/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.mdnd.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/mdnd/tests/unitTests/areaManager/AreaManagerCoverPresence.html b/dojox/mdnd/tests/unitTests/areaManager/AreaManagerCoverPresence.html
new file mode 100644
index 0000000..72a945e
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/areaManager/AreaManagerCoverPresence.html
@@ -0,0 +1,110 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Area Manager - Unit Tests</title>
+	
+	<style type="text/css">
+			.item{
+				border:1px solid black;
+				background-color:#fff;
+				margin:5px 2px;
+			}
+			
+			.area{
+				position:absolute;
+				top:10px;
+				border:5px solid #AAA;
+				background-color:#DDD;
+				margin-left:0;
+				padding:0px;
+			}
+			#area1{
+				left:130px;
+				width : 300px;
+				height: 1250px;
+			}
+			#area2{
+				left:10px;
+				width : 100px;
+				height: 1250px;
+			}
+			#area3{
+				left:450px;
+				width : 200px;
+				height: 1250px;
+			}
+	
+	</style>
+	<script type="text/javascript" src="../../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	
+	
+	<script type="text/javascript">
+	
+		dojo.require("doh.runner");
+		dojo.require("dojox.mdnd.AreaManager");
+		dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+		dojo.require("dojox.mdnd.DropIndicator");
+		dojo.require("dojox.mdnd.AutoScroll");
+		dojo.require("dojo.parser");
+		
+	
+		
+		
+		dojo.addOnLoad(function(){
+			// initialize the singleton areaManager
+			var mgr = dojox.mdnd.areaManager();
+			mgr.init();
+			
+			var area1,area2,area3;
+			area1 =  dojo.byId("area1");
+			area2 =  dojo.byId("area2");
+			area3 =  dojo.byId("area3");
+			
+			
+			doh.register("AreaManagerCoverPresence",
+				[
+					{
+						// move the item 2_1 to verify cover presence
+						name : "testCoverPresence",
+						runTest : function(t){
+							// get Coords of item_2_1
+							var item = dojo.byId("item_2_1");
+							var coord ={x:item.offsetLeft,y:item.offsetTop};
+							var size ={h:item.offsetHeight, w:item.offsetWidth};
+							mgr.onDragStart(item,coord,size);
+							
+							// Check 2 covers presence into body
+							var listCover = dojo.query(".dndCover");
+							doh.assertEqual(2,listCover.length);
+							// Check cover2 presence
+							doh.assertEqual(1,dojo.query(".dndCover2").length);
+							// check covers height
+							var dndCover =  listCover[0];
+							var dndCover2 = listCover[1];
+							
+							
+							//var height = (dojo.isWebKit)? document.body.scrollHeight : document.body.parentNode.scrollHeight;
+							
+							doh.assertFalse(0,dndCover.offsetHeight);
+							doh.assertFalse(0,dndCover2.offsetHeight);
+							
+							// drop the item to his initial position
+							mgr.onDrop(item);
+						}
+					}
+					
+				]
+			);
+			doh.run();
+		});
+
+	</script>
+</head>
+<body class="tundra">
+	<div id="area2" class="dojoxDndArea area">
+		<div id="item_2_1" class="item">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec ante eros, dignissim quis, facilisis nec, euismod vitae, metus. Nunc dolor sapien, euismod eget, consectetuer id, egestas ut, neque.</div>
+	</div>
+	<div id="area1" class="dojoxDndArea area"></div>
+	<div id="area3" class="dojoxDndArea area"></div>
+</body>
+</html>
diff --git a/dojox/mdnd/tests/unitTests/areaManager/AreaManagerManagingDragItems.html b/dojox/mdnd/tests/unitTests/areaManager/AreaManagerManagingDragItems.html
new file mode 100644
index 0000000..132e469
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/areaManager/AreaManagerManagingDragItems.html
@@ -0,0 +1,149 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>AreaManager</title>
+	<script type="text/javascript" src="../../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	
+	<link rel="stylesheet" type="text/css" href="../../../../../dojo/resources/dojo.css" />
+	<link rel="stylesheet" type="text/css" href="../../../../../dijit/themes/tundra/tundra.css" />
+	
+	<script type="text/javascript"><!--
+	dojo.require("doh.runner");		
+		dojo.require("dojox.mdnd.AreaManager");
+		dojo.require("dojox.mdnd.DropIndicator");
+		dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+
+		dojo.declare("AreaManagerTestFixture", null, {
+			constructor:function(testName, test) {
+				this.name = testName;
+				this.runTest = test;
+			},
+			setUp:function() {
+				this.mgr = dojox.mdnd.areaManager();
+				
+				this.areaA = dojo.byId("areaA");
+				this.areaB = dojo.byId("areaB");
+				this.areaC = dojo.byId("areaC");
+
+				this.itemA = createItem("itemA");
+				this.itemB = createItem("itemB");
+				this.itemC = createItem("itemC");
+
+			},
+			tearDown:function() {
+				//reinit DOM
+				var areas = [this.areaA,this.areaB,this.areaC];
+				for (var i = 0; i < areas.length; i++) {
+					while (areas[i].firstChild) {
+						dojo.destroy(areas[i].removeChild(areas[i].lastChild));
+					}
+					this.mgr.unregister(areas[i]);
+				}
+				delete this.areaA;
+				delete this.areaB;
+				delete this.areaC;
+				delete this.itemA;
+				delete this.itemB;
+				delete this.itemC;
+				
+			}
+		});
+
+		function createItem(id){
+			return dojo.create('div',{'class':'item', 'id': id});
+		};
+		
+		//--------------------------------------
+		dojo.addOnLoad(function(){
+			
+			doh.register("AreaManagerManagingDragItems",
+				[
+					/*
+					 * Default test of adding an item
+					 */
+					new AreaManagerTestFixture("addDragItem",function(){
+						
+						this.mgr.registerByNode(this.areaA);
+						this.mgr.addDragItem(this.areaA, this.itemA);
+						
+						doh.assertEqual(1, this.mgr._areaList.length, "One area should be register!");
+						var areaItem = this.mgr._areaList[0];
+						doh.assertEqual(areaItem.items.length, 1, "The register area should contain one item!");
+					}),
+					
+					new AreaManagerTestFixture("unregisteredArea",function(){
+						this.mgr.addDragItem(this.areaB, this.itemA);
+						doh.assertEqual(0, this.mgr._areaList.length, "An item shouldn't add to an unregitered area");
+					}),
+					
+					new AreaManagerTestFixture("addDragItemWithDomAppendedNode",function(){
+						this.mgr.registerByNode(this.areaB);
+						this.areaC.appendChild(this.itemA);
+						this.mgr.addDragItem(this.areaB, this.itemA);
+						doh.assertEqual(0, this.mgr._areaList[0].items.length, "Item shouldn't append to a node before add");						
+					}),
+					
+					new AreaManagerTestFixture("addDragItemWithInsideAreaNode",function(){
+						this.mgr.registerByNode(this.areaC);
+						this.areaC.appendChild(this.itemA);
+						this.mgr.addDragItem(this.areaC, this.itemA);
+						var areaItem = this.mgr._areaList[0];
+						doh.assertTrue(1, areaItem.items.length);
+					}),
+					
+					new AreaManagerTestFixture("addDragItemWithNegativeIndex",function(){
+						this.mgr.registerByNode(this.areaA);
+						this.mgr.addDragItem(this.areaA, this.itemA, -1);
+						var areaItem = this.mgr._areaList[0];
+						doh.assertEqual(1, areaItem.items.length);
+					}),
+					
+					new AreaManagerTestFixture("addDragItemWithOutsideIndex",function(){
+						this.mgr.registerByNode(this.areaB);
+						this.mgr.addDragItem(this.areaB, this.itemA);
+						this.mgr.addDragItem(this.areaB, this.itemB, 100);
+						
+						var areaItem = this.mgr._areaList[0];
+						doh.assertEqual(2, areaItem.items.length);
+					}),
+					
+					/*
+					 * Default test of removing an item
+					 */
+					new AreaManagerTestFixture("removeDragItem",function(){
+						this.mgr.registerByNode(this.areaA);
+						this.mgr.addDragItem(this.areaA, this.itemA);
+						
+						doh.assertEqual(1, this.mgr._areaList[0].items.length);
+						
+						this.mgr.removeDragItem(this.areaA, this.itemA);
+						var areaItem = this.mgr._areaList[0];
+						
+						doh.assertEqual(0, this.mgr._areaList[0].items.length);
+					}),
+					
+					new AreaManagerTestFixture("removeWrongDragItem",function(){
+						this.mgr.registerByNode(this.areaA);
+						this.mgr.registerByNode(this.areaB);
+						this.mgr.addDragItem(this.areaA, this.itemA);
+						this.mgr.removeDragItem(this.areaB, this.itemA);
+						
+						doh.assertEqual(1, this.mgr._areaList[0].items.length);
+						doh.assertEqual(0, this.mgr._areaList[1].items.length);
+					})
+				]
+			);
+			doh.run();
+		});
+		//--------------------------------------
+	--></script>
+
+	</head>
+	<body class="tundra">
+		<div class="area" id="areaA"></div>
+		<div class="area" id="areaB"></div>
+		<div class="area" id="areaC"></div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/unitTests/areaManager/AreaManagerRegistering.html b/dojox/mdnd/tests/unitTests/areaManager/AreaManagerRegistering.html
new file mode 100644
index 0000000..8de1242
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/areaManager/AreaManagerRegistering.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>AreaManager</title>
+	<script type="text/javascript" src="../../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("doh.runner");		
+		dojo.require("dojo.parser");
+		dojo.require("dojox.mdnd.AreaManager");
+		dojo.require("dojox.mdnd.DropIndicator");
+		dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+
+		dojo.declare("AreaManagerTestFixture", null, {
+			constructor:function(testName, test) {
+				this.name = testName;
+				this.runTest = test;
+			},
+			setUp:function() {
+				
+				this.mgr = new dojox.mdnd.AreaManager();
+				this.mgr._dropMode = new dojox.mdnd.dropMode.VerticalDropMode(this.mgr);
+				this.mgr._dropIndicator = new dojox.mdnd.DropIndicator();
+				
+				this.area1 = dojo.byId("area1");
+				this.area2 = dojo.byId("area2");
+				this.area3 = dojo.byId("area3");
+			},
+			tearDown:function() {
+				delete this.mgr;
+				delete this.area1;
+				delete this.area2;
+				delete this.area3;
+			}
+		});
+		//--------------------------------------
+		dojo.addOnLoad(function(){
+			doh.register("AreaManagerRegistering",
+				[
+					new AreaManagerTestFixture("registerByNodeNull",function(){
+						this.mgr.registerByNode(null);
+						doh.assertEqual(0, this.mgr._areaList.length, 'No area should be register.');
+					}),
+
+					new AreaManagerTestFixture("registerByNodeArea",function(){
+						this.mgr.registerByNode(this.area2);
+						this.mgr.registerByNode(this.area1);
+						doh.assertEqual(2, this.mgr._areaList.length, 'Two areas should be register.');
+						doh.assertEqual(this.area1, this.mgr._areaList[0].node);
+						doh.assertEqual(this.area2, this.mgr._areaList[1].node);
+					}),
+
+					new AreaManagerTestFixture("unregisterArea",function(){
+						this.mgr.registerByNode(this.area1);
+						this.mgr.unregister(this.area1);
+						doh.assertEqual(0, this.mgr._areaList.length, 'Area1 should be unregister.');
+					}),
+					
+					new AreaManagerTestFixture("registerByNodeRegisteredArea",function(){
+						this.mgr.registerByNode(this.area2);
+						this.mgr.registerByNode(this.area2);
+						doh.assertEqual(1, this.mgr._areaList.length, 'One area should be register.');
+						doh.assertEqual(this.area2, this.mgr._areaList[0].node, 'Area1 should be register once.');
+					}),
+					
+					new AreaManagerTestFixture("registerByNodeAreaWithChildren",function(){
+						this.mgr.registerByNode(this.area3);
+						doh.assertEqual(this.area3, this.mgr._areaList[0].node, 'Area3 should be register.');
+						var areaItem = this.mgr._areaList[0];
+						doh.assertEqual(1, areaItem.items.length, 'One item should be register.');
+					}),
+
+					new AreaManagerTestFixture("registerByClassArea",function(){
+						this.mgr.registerByClass();
+						doh.assertEqual(2, this.mgr._areaList.length, '2 area should be register.');
+					}),
+					
+					new AreaManagerTestFixture("registerByClassRegisteredArea",function(){
+						this.mgr.registerByClass();
+						this.mgr.registerByNode(this.area1);
+						doh.assertEqual(2, this.mgr._areaList.length);
+					})
+				]
+			);
+			doh.run();
+		});
+		//--------------------------------------
+	</script>
+		<style type="text/css">
+			.area{
+				position:absolute;
+				top:10px;
+				border:5px solid #AAA;
+				background-color:#DDD;
+				margin-left:0;
+				padding:0px;
+				height: 400px;
+			}
+			#area1{
+				left:10px;
+				width : 300px;
+			}
+			#area2{
+				left:330px;
+				width : 100px;
+			}
+			#area3{
+				left:450px;
+				width : 200px;
+			}
+		</style>
+	</head>
+	<body class="tundra">
+		<div id="area2" class="dojoxDndArea area"></div>
+		<div id="area1" class="dojoxDndArea area"></div>
+		<div id="area3" class="area">
+			<div class="item">
+				Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec ante eros, dignissim quis, facilisis nec, euismod vitae, metus. Nunc dolor sapien, euismod eget, consectetuer id, egestas ut, neque.
+			</div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/unitTests/areaManager/module.js b/dojox/mdnd/tests/unitTests/areaManager/module.js
new file mode 100644
index 0000000..76b7946
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/areaManager/module.js
@@ -0,0 +1,12 @@
+dojo.provide("dojox.mdnd.tests.unitTests.areaManager.module");
+
+try{
+	doh.registerUrl("dojox.mdnd.tests.unitTests.AreaManagerCoverPresence",
+			dojo.moduleUrl("dojox.mdnd","tests/unitTests/areaManager/AreaManagerCoverPresence.html"), 60000);
+	doh.registerUrl("dojox.mdnd.tests.unitTests.AreaManagerManagingDragItems",
+			dojo.moduleUrl("dojox.mdnd","tests/unitTests/areaManager/AreaManagerManagingDragItems.html"), 60000);
+	doh.registerUrl("dojox.mdnd.tests.unitTests.AreaManagerRegistering",
+			dojo.moduleUrl("dojox.mdnd","tests/unitTests/areaManager/AreaManagerRegistering.html"), 60000);
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/mdnd/tests/unitTests/dropIndicator/DropIndicatorTest.html b/dojox/mdnd/tests/unitTests/dropIndicator/DropIndicatorTest.html
new file mode 100644
index 0000000..9f5feb7
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/dropIndicator/DropIndicatorTest.html
@@ -0,0 +1,187 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Drop Indicator place test</title>
+	
+	<script type="text/javascript" src="../../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	
+	<script type="text/javascript">
+
+		dojo.require("doh.runner");		
+		dojo.require("dojo.parser");
+		dojo.require("dojox.mdnd.AreaManager");
+		dojo.require("dojox.mdnd.DropIndicator");
+		dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+		
+		dojo.addOnLoad(function(){
+			var size = {'w':100,'h':100};
+			
+			var mgr = dojox.mdnd.areaManager();
+			var dropIndicator = mgr._dropIndicator;
+			
+			mgr.areaClass = "dndArea";
+			mgr.dragHandleClass="dragHandle";
+			mgr.registerByClass();
+			
+			var area1, area2, area3,item;
+			area1 = dojo.byId("area1");
+			area2 = dojo.byId("area2");
+			item = dojo.byId("item1");
+			
+			
+			doh.register("DropIndicatorPlace",
+				[
+				{
+				 	// Test to place drop indicator into area 1
+				 	// with no node references. In this case the drop
+				 	// indicator is displayed at the end of the area
+					 name:"TestPlaceDropIndicatorNoPlace",
+					 runTest: function(t){
+					 	var diNode = dropIndicator.place(area1,null,size);
+					 	// retrieve drop indicator which must be at the end
+					 	var node = area1.getElementsByTagName("div")[4];
+					 	
+					 	//check that DropIndicator is at good position
+					 	doh.assertEqual(diNode,node);
+					 	doh.assertEqual("dropIndicator",node.className);
+					 	//check content node size
+					 	doh.assertEqual(100,dojo.contentBox(node).h);
+					 }
+				},
+				{	/**
+				 	 * Test to place drop indicator into area 1
+				 	 * with place0 node reference. In this case the drop
+				 	 * indicator is displayed at the begenning
+				 	 * 
+					 */
+					 name:"TestPlaceDropIndicatorPlace0",
+					 runTest: function(t){
+					 	var place0 = dojo.byId("place0");
+					 	var diNode = dropIndicator.place(area1,place0,size);
+					 	// retrieve drop indicator which must be at the first position
+					 	var node = area1.getElementsByTagName("div")[0];
+					 	//check that DropIndicator is present
+					 	doh.assertEqual(diNode,node);
+					 	doh.assertEqual("dropIndicator",node.className);
+					 	//check node size
+					 	doh.assertEqual(100,dojo.contentBox(node).h);
+					 }
+				},
+				{	/**
+				 	 * Test to place drop indicator into area 1
+				 	 * with place2 node reference. In this case the drop
+				 	 * indicator is displayed at the begenning
+				 	 * 
+					 */
+					 name:"TestPlaceDropIndicatorPlace2",
+					 runTest: function(t){
+					 	var place0 = dojo.byId("place2");
+					 	var diNode = dropIndicator.place(area1,place0,size);
+					 	// retrieve drop indicator which must be at the first position
+					 	var node = area1.getElementsByTagName("div")[2];
+					 	//check that DropIndicator is present
+					 	doh.assertEqual(diNode,node);
+					 	doh.assertEqual("dropIndicator",node.className);
+					 	//check node size
+					 	doh.assertEqual(100,dojo.contentBox(node).h);
+					 }
+				},
+				{	/**
+				 	 * Test to place drop indicator into area 1
+				 	 * with bad node reference (using item). In this case the drop
+				 	 * indicator is displayed at the begenning
+				 	 * 
+					 */
+					 name:"TestPlaceDropIndicatorNoPlace",
+					 runTest: function(t){
+					 	var a1BeginSize = area1.getElementsByTagName("div").length;
+					 	var a2BeginSize = area2.getElementsByTagName("div").length;
+					 	
+					 	var diNode = dropIndicator.place(area1,item,size);
+					 	// get elements number after placement
+					 	
+					 	var a1EndSize = area1.getElementsByTagName("div").length;
+					 	var a2EndSize = area2.getElementsByTagName("div").length;
+					 	//check that none child added to the 2 areas and diNode is null
+					 	doh.assertEqual(null,diNode);
+					 	doh.assertEqual(a1BeginSize, a1EndSize);
+					 	doh.assertEqual(a2BeginSize, a2EndSize);
+					 }
+				},
+				{	/**
+				 	 * Test removing dropIndicator
+					 */
+					 name:"TestRemoveDropIndicator",
+					 runTest: function(t){
+					 	var listDropIndicator = dojo.query(".dropIndicator");
+					 	// check that there's only one dromIndicator
+					 	doh.assertEqual(1,listDropIndicator.length);
+					 	// remove the drop indicator
+					 	dropIndicator.remove();
+					 	// check that there's none drop indicator
+					 	listDropIndicator = dojo.query(".dropIndicator");
+					 	doh.assertEqual(0,listDropIndicator.length);
+					 }
+				},
+				{	/**
+				 	 * Test removing dropIndicator that is not present in the document
+					 */
+					 name:"TestRemoveDropIndicatorNonExisting",
+					 runTest: function(t){
+					 	var listDropIndicator = dojo.query(".dropIndicator");
+					 	// check that there's no drop indicator present
+					 	doh.assertEqual(0,listDropIndicator.length);
+					 	// remove the drop indicator
+					 	dropIndicator.remove();
+					 	// check that there's none drop indicator present
+					 	listDropIndicator = dojo.query(".dropIndicator");
+					 	doh.assertEqual(0,listDropIndicator.length);
+					 }
+				}
+				]
+			);
+			doh.run();
+		});
+		
+		
+		//--------------------------------------
+	</script>
+	<style type="text/css">
+		.area{
+			position:absolute;
+			top:10px;
+			border:5px solid #AAA;
+			background-color:#DDD;
+			margin:0;
+			padding:0;
+		}
+		#area1{
+			left:10px;
+			width : 300px;
+		}
+		#area2{
+			left:330px;
+			width : 100px;
+			height:300px;
+		}
+		.placeNode{
+			width:100%;
+			height:75px;
+			
+		}
+	</style>
+	</head>
+	<body class="orange">
+		<div id="area2" class="dndArea area">
+			<div style="background-color:white" id="item1">tested item</div>
+		</div>
+		<div id="area1" class="dndArea area">
+			<div id="place0" class="placeNode"></div>
+			<div id="place1" class="placeNode"></div>
+			<div id="place2" class="placeNode"></div>
+			<div id="place3" class="placeNode"></div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mdnd/tests/unitTests/dropIndicator/module.js b/dojox/mdnd/tests/unitTests/dropIndicator/module.js
new file mode 100644
index 0000000..0d54632
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/dropIndicator/module.js
@@ -0,0 +1,8 @@
+dojo.provide('dojox.mdnd.tests.unitTests.dropIndicator.module');
+
+try{
+	doh.registerUrl("dojox.mdnd.tests.unitTests.dropIndicator.DropIndicatorTest",
+			dojo.moduleUrl("dojox.mdnd","tests/unitTests/dropIndicator/DropIndicatorTest.html"), 60000);
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/mdnd/tests/unitTests/dropMode/DefaultDropModeTest.html b/dojox/mdnd/tests/unitTests/dropMode/DefaultDropModeTest.html
new file mode 100644
index 0000000..551824a
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/dropMode/DefaultDropModeTest.html
@@ -0,0 +1,241 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>DefaultDropMode</title>
+	
+	<script type="text/javascript" 
+		src="../../../../../dojo/dojo.js" 
+		djConfig="isDebug: true, parseOnLoad: true">
+	</script>
+	
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");	
+		dojo.require("dojo.parser");
+		dojo.require("dojox.mdnd.tests.unitTests.dropMode.FixtureLib");
+		dojo.require("dojox.mdnd.dropMode.DefaultDropMode");
+		
+		dojo.addOnLoad(function(){			
+			
+			doh.robot.initRobot('resources/domElement.html');
+			
+			doh.register("getDragPoint",
+			    [
+					// summary:
+					//		getDragPoint get the reference point used to
+					//		represent the drag item.
+					//
+					//		For the defaultDropMode, this point varies with the
+					//		direction of moving (up or down).
+
+					 new getDragPointFixture("firstCall",function(){
+						// On the first call, this point is :
+						// X = (X position + width/2)
+						// Y = Y position
+						var point = this.dropMode.getDragPoint(this.coords, this.size, this.mousePosition);						
+						doh.assertTrue(point.x === 75);
+						doh.assertTrue(point.y === 50);
+					}),
+
+					new getDragPointFixture("moveHorizontal",function(){
+						// The drag item move from (25,50) to (125,50).
+						// X = (X position + width/2)
+						// Y = Y position
+
+						//1st call
+						this.dropMode.getDragPoint(this.coords, this.size, this.mousePosition);
+						//2nd call
+						var point = this.dropMode.getDragPoint(
+								{'x':125,'y':50},
+								this.size);
+						doh.assertTrue(point.x === 175);
+						doh.assertTrue(point.y === 50);
+					}),
+
+					new getDragPointFixture("moveUp",function(){
+						// The drag item move from (25,50) to (25,0).
+						// X = (X position + width/2)
+						// Y = Y position
+						
+						//1st call
+						this.dropMode.getDragPoint(this.coords, this.size, this.mousePosition);
+						//2nd  call
+						var point = this.dropMode.getDragPoint(
+									{'x':25,'y':0}, 
+									this.size);
+						doh.assertTrue(point.x === 75);
+						doh.assertTrue(point.y === 0);
+					}),
+
+					new getDragPointFixture("moveDown",function(){
+					 	// The drag item move from (25,50) to (25,0).
+						// X = (X position + width/2)
+						// Y = Y position + Y size
+
+						//1st call
+						this.dropMode.getDragPoint(this.coords, this.size, this.mousePosition);
+						//2nd call
+						var point = this.dropMode.getDragPoint(
+									{'x':25,'y':75}, 
+									this.size);
+						doh.assertTrue(point.x === 75);
+						doh.assertTrue(point.y === 175);
+					})					
+			    ]
+			);
+			
+			doh.register("addArea",
+				[
+					// summary:
+					//		addArea allows to add a DnD area. They are sorted
+					//		by their x position.
+
+					new AreaFixture("addAnArea", function(){
+						this.dropMode.addArea(this.array, this.objectA);
+						doh.assertTrue(this.array.length === 1);
+						doh.assertTrue(this.objectA.coords.x === 50 && this.objectA.coords.y === 50);	
+					}),
+
+					new AreaFixture("addAtStart", function(){
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectA);
+						doh.assertTrue(this.array.length === 2);
+						doh.assertTrue(this.array[0]=== this.objectA);	
+					}),
+
+					new AreaFixture("addAtEnd", function(){
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectC);
+						doh.assertTrue(this.array.length === 2);
+						doh.assertTrue(this.array[1] === this.objectC);
+					}),
+
+					new AreaFixture("addAtMiddle", function(){
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectD);
+						console.dir(this.array);
+						this.dropMode.addArea(this.array, this.objectC);
+						doh.assertTrue(this.array.length === 3);
+						doh.assertTrue(this.array[1] === this.objectC);
+					})					
+				]			
+			);
+			
+			doh.register("updateAreas",
+				[
+					// summary:
+					//		Refresh intervals between areas to determinate the 
+					//		nearest area to drop an item.
+
+					new AreaFixture("areaDropZone", function(){
+						this.dropMode.addArea(this.array, this.objectA);
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectC);
+						this.dropMode.addArea(this.array, this.objectD);
+						this.dropMode.updateAreas(this.array); 
+
+						doh.assertTrue(this.objectA.coords.x1 === -1 && this.objectA.coords.x2 === 176);
+						doh.assertTrue(this.objectB.coords.x1 === 176 && this.objectB.coords.x2 === 326);
+						doh.assertTrue(this.objectD.coords.x1 === 601 && this.objectD.coords.x2 === -1);
+					}),
+					
+					new AreaFixture("updateDOMCoord", function(){
+						this.dropMode.addArea(this.array, this.objectA);
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectC);
+						this.dropMode.addArea(this.array, this.objectD);
+						this.dropMode.updateAreas(this.array); 
+
+						doh.assertTrue(this.objectC.coords.x === 350 && this.objectC.coords.y === 50);
+						doh.assertTrue(this.objectC.coords.x1 === 326 && this.objectC.coords.x2 === 601);
+						var domNode = this.objectC.node;
+						dojo.style(domNode,{'left': '400px','top':'25px'});
+						this.dropMode.updateAreas(this.array); 
+						doh.assertTrue(this.objectC.coords.x === 400 && this.objectC.coords.y === 25);
+						doh.assertTrue(this.objectC.coords.x1 === 351 && this.objectC.coords.x2 === 626);
+					})
+				]
+			);
+			
+			doh.register("initItems",
+				[
+					// summary:
+					// 		iniItems allows to initialize the horizontal line 
+					//		in order to determinate the drop zone.
+
+					new ItemFixture("initItems", function(){
+
+						this.object = {
+							'items':[this.itemA]
+						}
+						this.dropMode.initItems(this.object);
+
+						doh.assertTrue(this.itemA.y === 551);
+					}),
+					
+					new ItemFixture("initItems2", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+
+						doh.assertTrue(this.itemA.y === 551);
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemC.y === 851);
+						doh.assertTrue(this.itemD.y === 1051);
+					})
+				]
+			);
+			
+			doh.register("refreshItems",
+				[
+					new ItemFixture("addAtStart", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+						this.dropMode.refreshItems(this.object, 0, {h:50,w:50}, true);
+
+						doh.assertTrue(this.itemA.y === 601);
+					}),
+
+					new ItemFixture("addDropIndicator", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+						this.dropMode.refreshItems(this.object, 2, {h:50,w:50}, true);
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemD.y === 1101);
+					}),
+
+					new ItemFixture("removeDropIndicator", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+						this.dropMode.refreshItems(this.object, 2, {h:50,w:50}, true);
+						
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemD.y === 1101);
+
+						this.dropMode.refreshItems(this.object, 2, {h:50,w:50}, false);
+
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemD.y === 1051);
+					})
+				]
+			);
+			
+			doh.run();
+		});
+	</script>
+	<style type="text/css"></style>
+	</head>
+	<body></body>
+</html>
\ No newline at end of file
diff --git a/dojox/mdnd/tests/unitTests/dropMode/FixtureLib.js b/dojox/mdnd/tests/unitTests/dropMode/FixtureLib.js
new file mode 100644
index 0000000..49086e2
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/dropMode/FixtureLib.js
@@ -0,0 +1,87 @@
+dojo.provide("dojox.mdnd.tests.unitTests.dropMode.FixtureLib");
+
+dojo.declare("getDragPointFixture", null, {
+
+	constructor:function(testName, test) {
+		this.name = testName;
+		this.runTest = test;
+	},
+
+	setUp:function() {
+		this.coords = {'x':25,'y':50};
+		this.size = {'w':100,'h':100};
+		this.mousePosition = {'x':50, 'y':75};
+		this.dropMode = dojox.mdnd.areaManager()._dropMode;
+	},
+
+	tearDown:function() {
+		delete this.coords;
+		delete this.size;
+		delete this.dropMode;
+	}
+});
+
+		
+dojo.declare("AreaFixture", null, {
+
+	constructor:function(testName, test) {
+		this.name = testName;
+		this.runTest = test;
+	},
+
+	setUp:function() {
+		this.dropMode = dojox.mdnd.areaManager()._dropMode;
+		this.array = [];
+		
+		//fake area object
+		this.objectA = {'node': dojo.byId('areaA')};
+		this.objectB = {'node': dojo.byId('areaB')};
+		this.objectC = {'node': dojo.byId('areaC')};
+		this.objectD = {'node': dojo.byId('areaD')};
+	},
+
+	tearDown:function() {
+		delete this.dropMode;
+		delete this.array;
+		delete this.objectA;
+		delete this.objectB;
+		delete this.objectC;
+		delete this.objectD;
+	}
+});
+
+dojo.declare("ItemFixture", null, {
+
+	constructor:function(testName, test) {
+		this.name = testName;
+		this.runTest = test;
+	},
+						
+	setUp:function() {
+		this.dropMode = dojox.mdnd.areaManager()._dropMode;
+		this.objet = {};
+		// fake moveable object
+		this.moveableA = {'node': dojo.byId("itemA")};
+		this.moveableB = {'node': dojo.byId("itemB")};
+		this.moveableC = {'node': dojo.byId("itemC")};
+		this.moveableD = {'node': dojo.byId("itemD")};
+		// fake item object
+		this.itemA = {'item': this.moveableA};
+		this.itemB = {'item': this.moveableB};
+		this.itemC = {'item': this.moveableC};
+		this.itemD = {'item': this.moveableD};
+	},
+	
+	tearDown: function(){
+		delete this.dropMode;
+		delete this.array;
+		delete this.moveableA;
+		delete this.moveableB;
+		delete this.moveableC; 
+		delete this.moveableD;
+		delete this.itemA;
+		delete this.itemB;
+		delete this.itemC;
+		delete this.itemD;
+	}
+});
diff --git a/dojox/mdnd/tests/unitTests/dropMode/OverDropModeTest.html b/dojox/mdnd/tests/unitTests/dropMode/OverDropModeTest.html
new file mode 100644
index 0000000..17dbea0
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/dropMode/OverDropModeTest.html
@@ -0,0 +1,195 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>OverDropMode</title>
+	
+	<script type="text/javascript" 
+		src="../../../../../dojo/dojo.js" 
+		djConfig="isDebug: true, parseOnLoad: true">
+	</script>
+	
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");	
+		dojo.require("dojo.parser");
+		dojo.require("dojox.mdnd.tests.unitTests.dropMode.FixtureLib");
+		dojo.require("dojox.mdnd.dropMode.OverDropMode");
+
+		dojo.addOnLoad(function(){			
+			
+			doh.robot.initRobot('resources/domElement.html');
+			
+			doh.register("getDragPoint",
+			    [
+					// summary:
+					//		getDragPoint get the reference point used to
+					//		represent the drag item.
+					//
+					//		For the overDropMode, this point is equal to
+					//		the mouse position.
+
+					 new getDragPointFixture("firstCall",function(){
+			
+						var point = this.dropMode.getDragPoint(this.coords, this.size, this.mousePosition);						
+						doh.assertTrue(point.x === this.mousePosition.x);
+						doh.assertTrue(point.y === this.mousePosition.y);
+					})	
+			    ]
+			);
+			
+			doh.register("addArea",
+				[
+					// summary:
+					//		addArea allows to add a DnD area. They are sorted
+					//		by their x position.
+
+					new AreaFixture("addAnArea", function(){
+						this.dropMode.addArea(this.array, this.objectA);
+						doh.assertTrue(this.array.length === 1);
+						doh.assertTrue(this.objectA.coords.x === 50 && this.objectA.coords.y === 50);	
+					}),
+
+					new AreaFixture("addAtStart", function(){
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectA);
+						doh.assertTrue(this.array.length === 2);
+						doh.assertTrue(this.array[0]=== this.objectA);	
+					}),
+
+					new AreaFixture("addAtEnd", function(){
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectC);
+						doh.assertTrue(this.array.length === 2);
+						doh.assertTrue(this.array[1] === this.objectC);
+					}),
+
+					new AreaFixture("addAtMiddle", function(){
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectD);
+						console.dir(this.array);
+						this.dropMode.addArea(this.array, this.objectC);
+						doh.assertTrue(this.array.length === 3);
+						doh.assertTrue(this.array[1] === this.objectC);
+					})					
+				]			
+			);
+			
+			doh.register("updateAreas",
+				[
+					// summary:
+					//		Refresh intervals between areas to determinate the 
+					//		nearest area to drop an item.
+
+					new AreaFixture("update", function(){
+						
+						this.dropMode.addArea(this.array, this.objectA);
+						this.dropMode.updateAreas(this.array); 
+
+						
+						doh.assertEqual(this.objectA.coords.x, 50);
+						doh.assertEqual(this.objectA.coords.x2, 152);
+						doh.assertEqual(this.objectA.coords.y, 50);
+					}),
+					
+					new AreaFixture("updateDOMCoord", function(){
+						
+						this.dropMode.addArea(this.array, this.objectC);
+						this.dropMode.updateAreas(this.array); 
+
+						doh.assertEqual(this.objectC.coords.x, 350);
+						doh.assertEqual(this.objectC.coords.x2, 452);
+						doh.assertEqual(this.objectC.coords.y, 50);
+
+						dojo.style(this.objectC.node,{'left': '400px','top':'25px'});
+						
+						this.dropMode.updateAreas(this.array); 
+						
+						doh.assertEqual(this.objectC.coords.x, 400);
+						doh.assertEqual(this.objectC.coords.x2, 502);
+						doh.assertEqual(this.objectC.coords.y, 25);
+					})
+				]
+			);
+			
+			doh.register("initItems",
+				[
+					// summary:
+					// 		iniItems allows to initialize the horizontal line 
+					//		in order to determinate the drop zone.
+
+					new ItemFixture("initItems", function(){
+
+						this.object = {
+							'items':[this.itemA]
+						}
+						this.dropMode.initItems(this.object);
+
+						doh.assertTrue(this.itemA.y === 551);
+					}),
+					
+					new ItemFixture("initItems2", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+
+						doh.assertTrue(this.itemA.y === 551);
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemC.y === 851);
+						doh.assertTrue(this.itemD.y === 1051);
+					})
+				]
+			);
+			
+			doh.register("refreshItems",
+				[
+					new ItemFixture("addAtStart", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+						this.dropMode.refreshItems(this.object, 0, {h:50,w:50}, true);
+
+						doh.assertTrue(this.itemA.y === 601);
+					}),
+
+					new ItemFixture("addDropIndicator", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+						this.dropMode.refreshItems(this.object, 2, {h:50,w:50}, true);
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemD.y === 1101);
+					}),
+
+					new ItemFixture("removeDropIndicator", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+						this.dropMode.refreshItems(this.object, 2, {h:50,w:50}, true);
+						
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemD.y === 1101);
+
+						this.dropMode.refreshItems(this.object, 2, {h:50,w:50}, false);
+
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemD.y === 1051);
+					})
+				]
+			);
+			
+			doh.run();
+		});
+	</script>
+	<style type="text/css"></style>
+	</head>
+	<body></body>
+</html>
diff --git a/dojox/mdnd/tests/unitTests/dropMode/VerticalDropModeTest.html b/dojox/mdnd/tests/unitTests/dropMode/VerticalDropModeTest.html
new file mode 100644
index 0000000..e1dbf9b
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/dropMode/VerticalDropModeTest.html
@@ -0,0 +1,241 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>VerticalDropMode</title>
+	
+	<script type="text/javascript" 
+		src="../../../../../dojo/dojo.js" 
+		djConfig="isDebug: true, parseOnLoad: true">
+	</script>
+	
+	<script type="text/javascript">
+		dojo.require("dijit.robotx");	
+		dojo.require("dojo.parser");
+		dojo.require("dojox.mdnd.tests.unitTests.dropMode.FixtureLib");
+		dojo.require("dojox.mdnd.dropMode.VerticalDropMode");
+		
+		dojo.addOnLoad(function(){			
+			
+			doh.robot.initRobot('resources/domElement.html');
+			
+			doh.register("getDragPoint",
+			    [
+					// summary:
+					//		getDragPoint get the reference point used to
+					//		represent the drag item.
+					//
+					//		For the VerticalDropMode this point varies with the
+					//		direction of moving (up or down).
+
+					 new getDragPointFixture("firstCall",function(){
+						// On the first call, this point is :
+						// X = (X position + width/2)
+						// Y = Y position
+						var point = this.dropMode.getDragPoint(this.coords, this.size, this.mousePosition);						
+						doh.assertTrue(point.x === 75);
+						doh.assertTrue(point.y === 50);
+					}),
+
+					new getDragPointFixture("moveHorizontal",function(){
+						// The drag item move from (25,50) to (125,50).
+						// X = (X position + width/2)
+						// Y = Y position
+
+						//1st call
+						this.dropMode.getDragPoint(this.coords, this.size, this.mousePosition);
+						//2nd call
+						var point = this.dropMode.getDragPoint(
+								{'x':125,'y':50},
+								this.size);
+						doh.assertTrue(point.x === 175);
+						doh.assertTrue(point.y === 50);
+					}),
+
+					new getDragPointFixture("moveUp",function(){
+						// The drag item move from (25,50) to (25,0).
+						// X = (X position + width/2)
+						// Y = Y position
+						
+						//1st call
+						this.dropMode.getDragPoint(this.coords, this.size, this.mousePosition);
+						//2nd  call
+						var point = this.dropMode.getDragPoint(
+									{'x':25,'y':0}, 
+									this.size);
+						doh.assertTrue(point.x === 75);
+						doh.assertTrue(point.y === 0);
+					}),
+
+					new getDragPointFixture("moveDown",function(){
+					 	// The drag item move from (25,50) to (25,0).
+						// X = (X position + width/2)
+						// Y = Y position + Y size
+
+						//1st call
+						this.dropMode.getDragPoint(this.coords, this.size, this.mousePosition);
+						//2nd call
+						var point = this.dropMode.getDragPoint(
+									{'x':25,'y':75}, 
+									this.size);
+						doh.assertTrue(point.x === 75);
+						doh.assertTrue(point.y === 175);
+					})					
+			    ]
+			);
+			
+			doh.register("addArea",
+				[
+					// summary:
+					//		addArea allows to add a DnD area. They are sorted
+					//		by their x position.
+
+					new AreaFixture("addAnArea", function(){
+						this.dropMode.addArea(this.array, this.objectA);
+						doh.assertTrue(this.array.length === 1);
+						doh.assertTrue(this.objectA.coords.x === 50 && this.objectA.coords.y === 50);	
+					}),
+
+					new AreaFixture("addAtStart", function(){
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectA);
+						doh.assertTrue(this.array.length === 2);
+						doh.assertTrue(this.array[0]=== this.objectA);	
+					}),
+
+					new AreaFixture("addAtEnd", function(){
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectC);
+						doh.assertTrue(this.array.length === 2);
+						doh.assertTrue(this.array[1] === this.objectC);
+					}),
+
+					new AreaFixture("addAtMiddle", function(){
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectD);
+						console.dir(this.array);
+						this.dropMode.addArea(this.array, this.objectC);
+						doh.assertTrue(this.array.length === 3);
+						doh.assertTrue(this.array[1] === this.objectC);
+					})					
+				]			
+			);
+			
+			doh.register("updateAreas",
+				[
+					// summary:
+					//		Refresh intervals between areas to determinate the 
+					//		nearest area to drop an item.
+
+					new AreaFixture("areaDropZone", function(){
+						this.dropMode.addArea(this.array, this.objectA);
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectC);
+						this.dropMode.addArea(this.array, this.objectD);
+						this.dropMode.updateAreas(this.array); 
+
+						doh.assertTrue(this.objectA.coords.x1 === -1 && this.objectA.coords.x2 === 176);
+						doh.assertTrue(this.objectB.coords.x1 === 176 && this.objectB.coords.x2 === 326);
+						doh.assertTrue(this.objectD.coords.x1 === 601 && this.objectD.coords.x2 === -1);
+					}),
+					
+					new AreaFixture("updateDOMCoord", function(){
+						this.dropMode.addArea(this.array, this.objectA);
+						this.dropMode.addArea(this.array, this.objectB);
+						this.dropMode.addArea(this.array, this.objectC);
+						this.dropMode.addArea(this.array, this.objectD);
+						this.dropMode.updateAreas(this.array); 
+
+						doh.assertTrue(this.objectC.coords.x === 350 && this.objectC.coords.y === 50);
+						doh.assertTrue(this.objectC.coords.x1 === 326 && this.objectC.coords.x2 === 601);
+						var domNode = this.objectC.node;
+						dojo.style(domNode,{'left': '400px','top':'25px'});
+						this.dropMode.updateAreas(this.array); 
+						doh.assertTrue(this.objectC.coords.x === 400 && this.objectC.coords.y === 25);
+						doh.assertTrue(this.objectC.coords.x1 === 351 && this.objectC.coords.x2 === 626);
+					})
+				]
+			);
+			
+			doh.register("initItems",
+				[
+					// summary:
+					// 		iniItems allows to initialize the horizontal line 
+					//		in order to determinate the drop zone.
+
+					new ItemFixture("initItems", function(){
+
+						this.object = {
+							'items':[this.itemA]
+						}
+						this.dropMode.initItems(this.object);
+
+						doh.assertTrue(this.itemA.y === 551);
+					}),
+					
+					new ItemFixture("initItems2", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+
+						doh.assertTrue(this.itemA.y === 551);
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemC.y === 851);
+						doh.assertTrue(this.itemD.y === 1051);
+					})
+				]
+			);
+			
+			doh.register("refreshItems",
+				[
+					new ItemFixture("addAtStart", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+						this.dropMode.refreshItems(this.object, 0, {h:50,w:50}, true);
+
+						doh.assertTrue(this.itemA.y === 601);
+					}),
+
+					new ItemFixture("addDropIndicator", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+						this.dropMode.refreshItems(this.object, 2, {h:50,w:50}, true);
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemD.y === 1101);
+					}),
+
+					new ItemFixture("removeDropIndicator", function(){
+
+						this.object = {
+							'items':[this.itemA, this.itemB, this.itemC, this.itemD]
+						}
+						this.dropMode.initItems(this.object);
+						this.dropMode.refreshItems(this.object, 2, {h:50,w:50}, true);
+						
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemD.y === 1101);
+
+						this.dropMode.refreshItems(this.object, 2, {h:50,w:50}, false);
+
+						doh.assertTrue(this.itemB.y === 701);
+						doh.assertTrue(this.itemD.y === 1051);
+					})
+				]
+			);
+			
+			doh.run();
+		});
+	</script>
+	<style type="text/css"></style>
+	</head>
+	<body></body>
+</html>
\ No newline at end of file
diff --git a/dojox/mdnd/tests/unitTests/dropMode/module.js b/dojox/mdnd/tests/unitTests/dropMode/module.js
new file mode 100644
index 0000000..bd4d953
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/dropMode/module.js
@@ -0,0 +1,10 @@
+dojo.provide('dojox.mdnd.tests.unitTests.dropMode.module');
+
+try{
+	doh.registerUrl("dojox.mdnd.tests.unitTests.dropMode.VerticalDropModeTest",
+			dojo.moduleUrl("dojox.mdnd","tests/unitTests/dropMode/VerticalDropModeTest.html"), 60000);
+	doh.registerUrl("dojox.mdnd.tests.unitTests.dropMode.OverDropModeTest",
+			dojo.moduleUrl("dojox.mdnd","tests/unitTests/dropMode/OverDropModeTest.html"), 60000);
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/mdnd/tests/unitTests/dropMode/resources/domElement.html b/dojox/mdnd/tests/unitTests/dropMode/resources/domElement.html
new file mode 100644
index 0000000..154fb4b
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/dropMode/resources/domElement.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<style>
+	.area{
+		position:absolute;
+		border:1px solid orange;
+		height:200px;
+		width:100px;
+	}
+	.item{
+		position:absolute;
+		border:1px solid pink;
+		height:100px;
+		width:100px;
+	}
+	#areaA{
+		top:50px;
+		left:50px;
+	}
+	#areaB{
+		top:150px;
+		left:200px;
+	}
+	#areaC{
+		top:50px;
+		left:350px;
+	}
+	#areaD{
+		top:10px;
+		left:750px;
+	}
+	
+	#itemA{
+		top:500px;
+		left:50px;
+	}
+	#itemB{
+		top:650px;
+		left:10px;
+	}
+	#itemC{
+		top:800px;
+		left:10px;
+	}
+	#itemD{
+		top:1000px;
+		left:100px;
+	}
+</style>
+</head>
+<body>
+	<div class="area" id="areaA">Area A <br/>{50, 50}</div>
+	<div class="area" id="areaB">Area B <br/>{150, 200}</div>
+	<div class="area" id="areaC">Area C <br/>{50, 350}</div>
+	<div class="area" id="areaD">Area D <br/>{10, 750}</div>
+	
+	<div class="item" id="itemA">Item A <br/>{500, 50}</div>
+	<div class="item" id="itemB">Item B <br/>{650, 10}</div>
+	<div class="item" id="itemC">Item C <br/>{800, 10}</div>
+	<div class="item" id="itemD">Item D <br/>{1000, 100}</div>
+
+</body>
+</html>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<style>
+	.area{
+		position:absolute;
+		border:1px solid orange;
+		height:200px;
+		width:100px;
+	}
+	.item{
+		position:absolute;
+		border:1px solid pink;
+		height:100px;
+		width:100px;
+	}
+	#areaA{
+		top:50px;
+		left:50px;
+	}
+	#areaB{
+		top:150px;
+		left:200px;
+	}
+	#areaC{
+		top:50px;
+		left:350px;
+	}
+	#areaD{
+		top:10px;
+		left:750px;
+	}
+	
+	#itemA{
+		top:500px;
+		left:50px;
+	}
+	#itemB{
+		top:650px;
+		left:10px;
+	}
+	#itemC{
+		top:800px;
+		left:10px;
+	}
+	#itemD{
+		top:1000px;
+		left:100px;
+	}
+</style>
+</head>
+<body>
+	<div class="area" id="areaA">Area A <br/>{50, 50}</div>
+	<div class="area" id="areaB">Area B <br/>{150, 200}</div>
+	<div class="area" id="areaC">Area C <br/>{50, 350}</div>
+	<div class="area" id="areaD">Area D <br/>{10, 750}</div>
+	
+	<div class="item" id="itemA">Item A <br/>{500, 50}</div>
+	<div class="item" id="itemB">Item B <br/>{650, 10}</div>
+	<div class="item" id="itemC">Item C <br/>{800, 10}</div>
+	<div class="item" id="itemD">Item D <br/>{1000, 100}</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mdnd/tests/unitTests/module.js b/dojox/mdnd/tests/unitTests/module.js
new file mode 100644
index 0000000..02ddf0b
--- /dev/null
+++ b/dojox/mdnd/tests/unitTests/module.js
@@ -0,0 +1,9 @@
+dojo.provide("dojox.mdnd.tests.unitTests.module");
+
+try{
+	dojo.require('dojox.mdnd.tests.unitTests.areaManager.module');
+	dojo.require('dojox.mdnd.tests.unitTests.dropMode.module');
+	dojo.require('dojox.mdnd.tests.unitTests.dropIndicator.module');
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/mobile.js b/dojox/mobile.js
new file mode 100755
index 0000000..439f6f7
--- /dev/null
+++ b/dojox/mobile.js
@@ -0,0 +1,4 @@
+dojo.provide("dojox.mobile");
+dojo.require("dojox.mobile._base");
+dojo.experimental("dojox.mobile");
+
diff --git a/dojox/mobile/README b/dojox/mobile/README
new file mode 100755
index 0000000..3bbbf27
--- /dev/null
+++ b/dojox/mobile/README
@@ -0,0 +1,55 @@
+-------------------------------------------------------------------------------
+Project Name:  dojox.mobile
+-------------------------------------------------------------------------------
+Version 0.01
+Release date: 03/23/2010
+-------------------------------------------------------------------------------
+Project state:
+        experimental
+-------------------------------------------------------------------------------
+[ NO ]	l18n support?
+[ NO ]	a11y support?
+-------------------------------------------------------------------------------
+Credits:
+       Jared Jurkiewicz (jared.jurkiewicz at gmail.com)
+       Yoshiroh Kamiyama (Contributor to Jared of base code).
+
+-------------------------------------------------------------------------------
+Project description
+
+This project tries to solve an area lacking in dojo, namely better 
+support for mobile devices.  This project provides through CSS3 and
+custom styles, interfaces that display and work well on mobile devices 
+such as the Android and iPhone Smart Phones.
+
+The code is deliberately kept as lightweight as possible, using CSS3 animations
+and the like to perform the effects.  There is a compat.js, which will simulate
+most of the effects using dojo.animateProperty and dojox.gfx where possible on
+browsers such as FireFox and IE.  It will not load by default, it has to be
+required in separately.
+-------------------------------------------------------------------------------
+Dependencies:
+        dojo base
+        dijit/_Widget.js
+-------------------------------------------------------------------------------
+Documentation
+        Documentatation will reside at:
+        http://docs.dojocampus.org/dojox/mobile
+
+-------------------------------------------------------------------------------
+Installation instructions
+
+Grab the following from the Dojo SVN Repository:
+http://svn.dojotoolkit.org/src/dojox/trunk/mobile/*
+http://svn.dojotoolkit.org/src/dojox/trunk/mobile.js
+
+Install into the following directory structure:
+/dojox/mobile.js
+/dojox/mobile/*
+
+...which should be at the same level as your Dojo checkout.
+
+then dojo.require("dojox.mobile") in your application to load it.
+
+-------------------------------------------------------------------------------
+
diff --git a/dojox/mobile/_base.js b/dojox/mobile/_base.js
new file mode 100644
index 0000000..79e32e3
--- /dev/null
+++ b/dojox/mobile/_base.js
@@ -0,0 +1,1451 @@
+dojo.provide("dojox.mobile._base");
+
+dojo.require("dijit._Widget");
+
+// summary:
+//		Mobile Widgets
+// description:
+//		This module provides a number of widgets that can be used to build
+//		web-based applications for mobile devices such as iPhone or Android.
+//		These widgets work best with webkit-based browsers, such as Safari or
+//		Chrome, since webkit-specific CSS3 features are used.
+//		However, the widgets should work in a "graceful degradation" manner
+//		even on non-CSS3 browsers, such as IE or Firefox. In that case,
+//		fancy effects, such as animation, gradient color, or round corner
+//		rectangle, may not work, but you can still operate your application.
+//
+//		Furthermore, as a separate file, a compatibility module,
+//		dojox.mobile.compat, is available that simulates some of CSS3 features
+//		used in this module. If you use the compatibility module, fancy visual
+//		effects work better even on non-CSS3 browsers.
+//
+//		Note that use of dijit._Container, dijit._Contained, dijit._Templated,
+//		and dojo.query is intentionally avoided to reduce download code size.
+
+dojo.declare(
+	"dojox.mobile.View",
+	dijit._Widget,
+{
+	// summary:
+	//		A widget that represents a view that occupies the full screen
+	// description:
+	//		View acts as a container for any HTML and/or widgets. An entire HTML page
+	//		can have multiple View widgets and the user can navigate through
+	//		the views back and forth without page transitions.
+
+	// selected: Boolean
+	//		If true, the view is displayed at startup time.
+	selected: false,
+
+	// keepScrollPos: Boolean
+	//		If true, the scroll position is kept between views.
+	keepScrollPos: true,
+
+	_started: false,
+
+	constructor: function(params, node){
+		if(node){
+			dojo.byId(node).style.visibility = "hidden";
+		}
+	},
+
+	buildRendering: function(){
+		this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("DIV");
+		this.domNode.className = "mblView";
+//		dojox.mobile.View._pillar = dojo.create("DIV", {className:"mblPillar"});
+		this.connect(this.domNode, "webkitAnimationEnd", "onAnimationEnd");
+		this.connect(this.domNode, "webkitAnimationStart", "onAnimationStart");
+		var id = location.href.match(/#(\w+)([^\w=]|$)/) ? RegExp.$1 : null;
+
+		this._visible = this.selected && !id || this.id == id;
+
+		if(this.selected){
+			dojox.mobile._defaultView = this;
+		}
+	},
+
+	startup: function(){
+		if(this._started){ return; }
+		var _this = this;
+		setTimeout(function(){
+			if(!_this._visible){
+				_this.domNode.style.display = "none";
+			}else{
+				dojox.mobile._currentView = _this;
+				_this.onStartView();
+			}
+			_this.domNode.style.visibility = "visible";
+		}, dojo.isIE?100:0); // give IE a little time to complete drawing
+		this._started = true;
+	},
+
+	onStartView: function(){
+		// Stub function to connect to from your application.
+		// Called only when this view is shown at startup time.
+	},
+
+	onBeforeTransitionIn: function(moveTo, dir, transition, context, method){
+		// Stub function to connect to from your application.
+	},
+
+	onAfterTransitionIn: function(moveTo, dir, transition, context, method){
+		// Stub function to connect to from your application.
+	},
+
+	onBeforeTransitionOut: function(moveTo, dir, transition, context, method){
+		// Stub function to connect to from your application.
+	},
+
+	onAfterTransitionOut: function(moveTo, dir, transition, context, method){
+		// Stub function to connect to from your application.
+	},
+
+	_saveState: function(moveTo, dir, transition, context, method){
+		this._context = context;
+		this._method = method;
+		if(transition == "none" || !dojo.isWebKit){
+			transition = null;
+		}
+		this._moveTo = moveTo;
+		this._dir = dir;
+		this._transition = transition;
+		this._arguments = [];
+		var i;
+		for(i = 0; i < arguments.length; i++){
+			this._arguments.push(arguments[i]);
+		}
+		this._args = [];
+		if(context || method){
+			for(i = 5; i < arguments.length; i++){
+				this._args.push(arguments[i]);
+			}
+		}
+	},
+
+	performTransition: function(/*String*/moveTo, /*Number*/dir, /*String*/transition,
+								/*Object|null*/context, /*String|Function*/method /*optional args*/){
+		// summary:
+		//		Function to perform the various types of view transitions, such as fade, slide, and flip.
+		// moveTo: String
+		//		The destination view id to transition the current view to.
+		//		If null, transitions to a blank view.
+		// dir: Number
+		//		The transition direction. If 1, transition forward. If -1, transition backward.
+		//		For example, the slide transition slides the view from right to left when dir == 1,
+		//		and from left to right when dir == -1.
+		// transision: String
+		//		The type of transition to perform. "slide", "fade", or "flip"
+		// context: Object
+		//		The object that the callback function will receive as "this".
+		// method: String|Function
+		//		A callback function that is called when the transition has been finished.
+		//		A function reference, or name of a function in context.
+		// tags:
+		//		public
+		// example:
+		//		Transitions to the blank view, and then opens another page.
+		//	|	performTransition(null, 1, "slide", null, function(){location.href = href;});
+		if(dojo.hash){
+			if(typeof(moveTo) == "string" && moveTo.charAt(0) == '#' && !dojox.mobile._params){
+				dojox.mobile._params = [];
+				for(var i = 0; i < arguments.length; i++){
+					dojox.mobile._params.push(arguments[i]);
+				}
+				dojo.hash(moveTo);
+				return;
+			}
+		}
+		this._saveState.apply(this, arguments);
+		var toNode;
+		if(moveTo){
+			if(typeof(moveTo) == "string"){
+				moveTo.match(/(\w+)/);
+				toNode = RegExp.$1;
+			}else{
+				toNode = moveTo;
+			}
+		}else{
+			if(!this._dummyNode){
+				this._dummyNode = dojo.doc.createElement("DIV");
+				dojo.body().appendChild(this._dummyNode);
+			}
+			toNode = this._dummyNode;
+		}
+		var fromNode = this.domNode;
+		toNode = this.toNode = dojo.byId(toNode);
+		if(!toNode){ alert("dojox.mobile.View#performTransition: destination view not found: "+toNode); }
+		toNode.style.visibility = "hidden";
+		toNode.style.display = "";
+		this.onBeforeTransitionOut.apply(this, arguments);
+		var toWidget = dijit.byNode(toNode);
+		if(toWidget && toWidget.onBeforeTransitionIn){
+			// perform view transition keeping the scroll position
+			if(this.keepScrollPos && !dijit.getEnclosingWidget(this.domNode.parentNode)){
+				var scrollTop = dojo.body().scrollTop || dojo.doc.documentElement.scrollTop || window.pageYOffset || 0;
+				if(dir == 1){
+					toNode.style.top = "0px";
+					if(scrollTop > 1){
+						fromNode.style.top = -scrollTop + "px";
+						if(dojo.config["mblHideAddressBar"] !== false){
+							setTimeout(function(){ // iPhone needs setTimeout
+								window.scrollTo(0, 1);
+							}, 0);
+						}
+					}
+				}else{
+					if(scrollTop > 1 || toNode.offsetTop !== 0){
+						var toTop = -toNode.offsetTop;
+						toNode.style.top = "0px";
+						fromNode.style.top = toTop - scrollTop + "px";
+						if(dojo.config["mblHideAddressBar"] !== false && toTop > 0){
+							setTimeout(function(){ // iPhone needs setTimeout
+								window.scrollTo(0, toTop + 1);
+							}, 0);
+						}
+					}
+				}
+			}else{
+				toNode.style.top = "0px";
+			}
+			toWidget.onBeforeTransitionIn.apply(this, arguments);
+		}
+		toNode.style.display = "none";
+		toNode.style.visibility = "visible";
+		this._doTransition(fromNode, toNode, transition, dir);
+	},
+
+	_doTransition: function(fromNode, toNode, transition, dir){
+		var rev = (dir == -1) ? " reverse" : "";
+		toNode.style.display = "";
+		if(transition){
+//			var pillar = dojox.mobile.View._pillar;
+//			pillar.style.height = fromNode.offsetHeight+"px";
+//			fromNode.parentNode.appendChild(pillar);
+			dojo.addClass(fromNode, transition + " out" + rev);
+			dojo.addClass(toNode, transition + " in" + rev);
+		}else{
+			this.domNode.style.display = "none";
+			this.invokeCallback();
+		}
+	},
+
+	onAnimationStart: function(e){
+	},
+
+	onAnimationEnd: function(e){
+		var isOut = false;
+		if(dojo.hasClass(this.domNode, "out")){
+			isOut = true;
+			this.domNode.style.display = "none";
+			dojo.forEach([this._transition,"in","out","reverse"], function(s){
+				dojo.removeClass(this.domNode, s);
+			}, this);
+		}
+		if(e.animationName.indexOf("shrink") === 0){
+			var li = e.target;
+			li.style.display = "none";
+			dojo.removeClass(li, "mblCloseContent");
+		}
+		if(isOut){
+//			dojox.mobile.View._pillar.parentNode.removeChild(dojox.mobile.View._pillar);
+			this.invokeCallback();
+		}
+		// this.domNode may be destroyed as a result of invoking the callback,
+		// so check for that before accessing it.
+		this.domNode && (this.domNode.className = "mblView");
+	},
+
+	invokeCallback: function(){
+		this.onAfterTransitionOut.apply(this, this._arguments);
+		var toWidget = dijit.byNode(this.toNode);
+		if(toWidget && toWidget.onAfterTransitionIn){
+			toWidget.onAfterTransitionIn.apply(this, this._arguments);
+		}
+
+		if(dojo.hash){
+			dojox.mobile._currentView = toWidget;
+		}
+
+		var c = this._context, m = this._method;
+		if(!c && !m){ return; }
+		if(!m){
+			m = c;
+			c = null;
+		}
+		c = c || dojo.global;
+		if(typeof(m) == "string"){
+			c[m].apply(c, this._args);
+		}else{
+			m.apply(c, this._args);
+		}
+	},
+
+	addChild: function(widget){
+		this.containerNode.appendChild(widget.domNode);
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.Heading",
+	dijit._Widget,
+{
+	back: "",
+	href: "",
+	moveTo: "",
+	transition: "slide",
+	label: "",
+
+	buildRendering: function(){
+		this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("H1");
+		this.domNode.className = "mblHeading";
+		this._view = this.domNode.parentNode && dijit.byNode(this.domNode.parentNode); // parentNode is null if created programmatically
+		if(this.label){
+			this.domNode.innerHTML = this.label;
+		}else{
+			this.label = this.domNode.innerHTML;
+		}
+		if(this.back){
+			var head = dojo.doc.createElement("DIV");
+			head.className = "mblArrowButtonHead";
+			var body = this._body = dojo.doc.createElement("DIV");
+			body.className = "mblArrowButtonBody mblArrowButtonText";
+			body.innerHTML = this.back;
+			this.connect(body, "onclick", "onClick");
+			var neck = dojo.doc.createElement("DIV");
+			neck.className = "mblArrowButtonNeck";
+
+			this.domNode.appendChild(head);
+			this.domNode.appendChild(body);
+			this.domNode.appendChild(neck);
+
+			this.setLabel(this.label);
+		}
+	},
+
+	onClick: function(e){
+		var h1 = this.domNode;
+		dojo.addClass(h1, "mblArrowButtonSelected");
+		setTimeout(function(){
+			dojo.removeClass(h1, "mblArrowButtonSelected");
+		}, 1000);
+		this.goTo(this.moveTo, this.href);
+	},
+
+	setLabel: function(label){
+		if(label != this.label){
+			this.label = label;
+			this.domNode.firstChild.nodeValue = label;
+		}
+		var s = this.domNode.style;
+		if(this.label.length > 12){
+			// create a clone to calculate the arrow button width correctly
+			// even when the heading is in the invisible state.
+			var h = this.domNode.cloneNode(true);
+			h.style.visibility = "hidden";
+			dojo.body().appendChild(h);
+			var b = h.childNodes[2];
+			s.paddingLeft = b.offsetWidth + 30 + "px";
+			s.textAlign = "left";
+			dojo.body().removeChild(h);
+			h = null;
+		}else{
+			s.paddingLeft = "";
+			s.textAlign = "";
+		}
+	},
+
+	goTo: function(moveTo, href){
+		if(!this._view){
+			this._view = dijit.byNode(this.domNode.parentNode);
+		}
+		if(href){
+			this._view.performTransition(null, -1, this.transition, this, function(){location.href = href;});
+		}else{
+			if(dojox.mobile.app){
+				// If in a full mobile app, then use its mechanisms to move back a scene
+				dojo.publish("/dojox/mobile/app/goback");
+			}
+			else{
+				this._view.performTransition(moveTo, -1, this.transition);
+			}
+
+		}
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.RoundRect",
+	dijit._Widget,
+{
+	shadow: false,
+
+	buildRendering: function(){
+		this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("DIV");
+		this.domNode.className = this.shadow ? "mblRoundRect mblShadow" : "mblRoundRect";
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.RoundRectCategory",
+	dijit._Widget,
+{
+	label: "",
+
+	buildRendering: function(){
+		this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("H2");
+		this.domNode.className = "mblRoundRectCategory";
+		if(this.label){
+			this.domNode.innerHTML = this.label;
+		}else{
+			this.label = this.domNode.innerHTML;
+		}
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.EdgeToEdgeCategory",
+	dojox.mobile.RoundRectCategory,
+{
+	buildRendering: function(){
+		this.inherited(arguments);
+		this.domNode.className = "mblEdgeToEdgeCategory";
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.RoundRectList",
+	dijit._Widget,
+{
+	transition: "slide",
+	iconBase: "",
+	iconPos: "",
+
+	buildRendering: function(){
+		this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("UL");
+		this.domNode.className = "mblRoundRectList";
+	},
+
+	addChild: function(widget){
+		this.containerNode.appendChild(widget.domNode);
+		widget.inheritParams();
+		widget.setIcon();
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.EdgeToEdgeList",
+	dojox.mobile.RoundRectList,
+{
+	buildRendering: function(){
+		this.inherited(arguments);
+		this.domNode.className = "mblEdgeToEdgeList";
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.AbstractItem",
+	dijit._Widget,
+{
+	icon: "",
+	iconPos: "", // top,left,width,height (ex. "0,0,29,29")
+	href: "",
+	moveTo: "",
+	clickable: false,
+	url: "",
+	transition: "",
+	callback: null,
+	sync: true,
+	label: "",
+
+	inheritParams: function(){
+		var parent = this.getParentWidget();
+		if(parent){
+			if(!this.transition){ this.transition = parent.transition; }
+			if(!this.icon){ this.icon = parent.iconBase; }
+			if(!this.iconPos){ this.iconPos = parent.iconPos; }
+		}
+	},
+
+	transitionTo: function(moveTo, href, url){
+		var n = this.domNode.parentNode;
+		var w; // the current view widget
+		while(true){
+			w = dijit.getEnclosingWidget(n);
+			if(!w){ return; }
+			if(w.performTransition){ break; }
+			n = w.domNode.parentNode;
+		}
+		if(href){
+			w.performTransition(null, 1, this.transition, this, function(){location.href = href;});
+			return;
+		}
+		if(url){
+			var id;
+			if(dojox.mobile._viewMap && dojox.mobile._viewMap[url]){
+				// external view has already been loaded
+				id = dojox.mobile._viewMap[url];
+			}else{
+				// get the specified external view and append it to the <body>
+				var text = this._text;
+				if(!text){
+					if(this.sync){
+						text = dojo.trim(dojo._getText(url));
+					}else{
+						var prog = dojox.mobile.ProgressIndicator.getInstance();
+						dojo.body().appendChild(prog.domNode);
+						prog.start();
+						var xhr = dojo.xhrGet({
+							url: url,
+							handleAs: "text"
+						});
+						xhr.addCallback(dojo.hitch(this, function(response, ioArgs){
+							prog.stop();
+							if(response){
+								this._text = response;
+								this.transitionTo(moveTo, href, url);
+							}
+						}));
+						xhr.addErrback(function(error){
+							prog.stop();
+							alert("Failed to load "+url+"\n"+(error.description||error));
+						});
+						return;
+					}
+				}
+				this._text = null;
+				id = this._parse(text);
+				if(!dojox.mobile._viewMap){
+					dojox.mobile._viewMap = [];
+				}
+				dojox.mobile._viewMap[url] = id;
+			}
+			moveTo = id;
+		}
+		w.performTransition(moveTo, 1, this.transition, this.callback && this, this.callback);
+	},
+
+	_parse: function(text){
+		var container = dojo.create("DIV");
+		var view;
+		if(text.charAt(0) == "<"){ // html markup
+			container.innerHTML = text;
+			view = container.firstChild; // <div dojoType="dojox.mobile.View">
+			if(!view && view.nodeType != 1){
+				alert("dojox.mobile.AbstractItem#transitionTo: invalid view content");
+				return;
+			}
+			view.setAttribute("_started", "true"); // to avoid startup() is called
+			view.style.visibility = "hidden";
+			dojo.body().appendChild(container);
+			(dojox.mobile.parser || dojo.parser).parse(container);
+		}else if(text.charAt(0) == "{"){ // json
+			dojo.body().appendChild(container);
+			this._ws = [];
+			view = this._instantiate(eval('('+text+')'), container);
+			for(var i = 0; i < this._ws.length; i++){
+				var w = this._ws[i];
+				w.startup && !w._started && (!w.getParent || !w.getParent()) && w.startup();
+			}
+			this._ws = null;
+		}
+		view.style.display = "none";
+		view.style.visibility = "visible";
+		var id = view.id;
+		return dojo.hash ? "#" + id : id;
+	},
+
+	_instantiate: function(/*Object*/obj, /*DomNode*/node, /*Widget*/parent){
+		var widget;
+		for(var key in obj){
+			if(key.charAt(0) == "@"){ continue; }
+			var cls = dojo.getObject(key);
+			if(!cls){ continue; }
+			var params = {};
+			var proto = cls.prototype;
+			var objs = dojo.isArray(obj[key]) ? obj[key] : [obj[key]];
+			for(var i = 0; i < objs.length; i++){
+				for(var prop in objs[i]){
+					if(prop.charAt(0) == "@"){
+						var val = objs[i][prop];
+						prop = prop.substring(1);
+						if(typeof proto[prop] == "string"){
+							params[prop] = val;
+						}else if(typeof proto[prop] == "number"){
+							params[prop] = val - 0;
+						}else if(typeof proto[prop] == "boolean"){
+							params[prop] = (val != "false");
+						}else if(typeof proto[prop] == "object"){
+							params[prop] = eval("(" + val + ")");
+						}
+					}
+				}
+				widget = new cls(params, node);
+				if(!node){ // not to call View's startup()
+					this._ws.push(widget);
+				}
+				if(parent && parent.addChild){
+					parent.addChild(widget);
+				}
+				this._instantiate(objs[i], null, widget);
+			}
+		}
+		return widget && widget.domNode;
+	},
+
+	getParentWidget: function(){
+		var ref = this.srcNodeRef || this.domNode;
+		return ref && ref.parentNode ? dijit.getEnclosingWidget(ref.parentNode) : null;
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.ListItem",
+	dojox.mobile.AbstractItem,
+{
+	rightText: "",
+	btnClass: "",
+	anchorLabel: false,
+
+	buildRendering: function(){
+		this.inheritParams();
+		var a = this.anchorNode = dojo.create("A");
+		a.className = "mblListItemAnchor";
+		var box = dojo.create("DIV");
+		box.className = "mblListItemTextBox";
+		if(this.anchorLabel){
+			box.style.cursor = "pointer";
+		}
+		var r = this.srcNodeRef;
+		if(r){
+			for(var i = 0, len = r.childNodes.length; i < len; i++){
+				box.appendChild(r.removeChild(r.firstChild));
+			}
+		}
+		if(this.label){
+			box.appendChild(dojo.doc.createTextNode(this.label));
+		}
+		a.appendChild(box);
+		if(this.rightText){
+			var txt = dojo.create("DIV");
+			txt.className = "mblRightText";
+			txt.innerHTML = this.rightText;
+			a.appendChild(txt);
+		}
+
+		if(this.moveTo || this.href || this.url || this.clickable){
+			var arrow = dojo.create("DIV");
+			arrow.className = "mblArrow";
+			a.appendChild(arrow);
+			this.connect(a, "onclick", "onClick");
+		}else if(this.btnClass){
+			var div = this.btnNode = dojo.create("DIV");
+			div.className = this.btnClass+" mblRightButton";
+			div.appendChild(dojo.create("DIV"));
+			div.appendChild(dojo.create("P"));
+
+			var dummyDiv = dojo.create("DIV");
+			dummyDiv.className = "mblRightButtonContainer";
+			dummyDiv.appendChild(div);
+			a.appendChild(dummyDiv);
+			dojo.addClass(a, "mblListItemAnchorHasRightButton");
+			setTimeout(function(){
+				dummyDiv.style.width = div.offsetWidth + "px";
+				dummyDiv.style.height = div.offsetHeight + "px";
+				if(dojo.isIE){
+					// IE seems to ignore the height of LI without this..
+					a.parentNode.style.height = a.parentNode.offsetHeight + "px";
+				}
+			});
+		}
+		if(this.anchorLabel){
+			box.style.display = "inline"; // to narrow the text region
+		}
+		var li = this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("LI");
+		li.className = "mblListItem";
+		li.appendChild(a);
+		this.setIcon();
+	},
+
+	setIcon: function(){
+		if(this.iconNode){ return; }
+		var a = this.anchorNode;
+		if(this.icon && this.icon != "none"){
+			var img = this.iconNode = dojo.create("IMG");
+			img.className = "mblListItemIcon";
+			img.src = this.icon;
+			this.domNode.insertBefore(img, a);
+			dojox.mobile.setupIcon(this.iconNode, this.iconPos);
+			dojo.removeClass(a, "mblListItemAnchorNoIcon");
+		}else{
+			dojo.addClass(a, "mblListItemAnchorNoIcon");
+		}
+	},
+
+	onClick: function(e){
+		if(this.anchorLabel){
+			for(var p = e.target; p.tagName != "LI"; p = p.parentNode){
+				if(p.className == "mblListItemTextBox"){
+					dojo.addClass(p, "mblListItemTextBoxSelected");
+					setTimeout(function(){
+						dojo.removeClass(p, "mblListItemTextBoxSelected");
+					}, 1000);
+					this.onAnchorLabelClicked(e);
+					return;
+				}
+			}
+		}
+		var a = e.currentTarget;
+		var li = a.parentNode;
+		dojo.addClass(li, "mblItemSelected");
+		setTimeout(function(){
+			dojo.removeClass(li, "mblItemSelected");
+		}, 1000);
+		this.transitionTo(this.moveTo, this.href, this.url);
+	},
+
+	onAnchorLabelClicked: function(e){
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.Switch",
+	dijit._Widget,
+{
+	value: "on",
+	leftLabel: "ON",
+	rightLabel: "OFF",
+	_width: 53,
+
+	buildRendering: function(){
+		this.domNode = this.srcNodeRef || dojo.doc.createElement("DIV");
+		this.domNode.className = "mblSwitch";
+		this.domNode.innerHTML =
+			  '<div class="mblSwitchInner">'
+			+	'<div class="mblSwitchBg mblSwitchBgLeft">'
+			+		'<div class="mblSwitchText mblSwitchTextLeft">'+this.leftLabel+'</div>'
+			+	'</div>'
+			+	'<div class="mblSwitchBg mblSwitchBgRight">'
+			+		'<div class="mblSwitchText mblSwitchTextRight">'+this.rightLabel+'</div>'
+			+	'</div>'
+			+	'<div class="mblSwitchKnob"></div>'
+			+ '</div>';
+		var n = this.inner = this.domNode.firstChild;
+		this.left = n.childNodes[0];
+		this.right = n.childNodes[1];
+		this.knob = n.childNodes[2];
+
+		dojo.addClass(this.domNode, (this.value == "on") ? "mblSwitchOn" : "mblSwitchOff");
+		this[this.value == "off" ? "left" : "right"].style.display = "none";
+	},
+
+	postCreate: function(){
+		this.connect(this.knob, "onclick", "onClick");
+		this.connect(this.knob, "touchstart", "onTouchStart");
+		this.connect(this.knob, "mousedown", "onTouchStart");
+	},
+
+	_changeState: function(/*String*/state){
+		this.inner.style.left = "";
+		dojo.addClass(this.domNode, "mblSwitchAnimation");
+		dojo.removeClass(this.domNode, (state == "on") ? "mblSwitchOff" : "mblSwitchOn");
+		dojo.addClass(this.domNode, (state == "on") ? "mblSwitchOn" : "mblSwitchOff");
+
+		var _this = this;
+		setTimeout(function(){
+			_this[state == "off" ? "left" : "right"].style.display = "none";
+			dojo.removeClass(_this.domNode, "mblSwitchAnimation");
+		}, 300);
+	},
+
+	onClick: function(e){
+		if(this._moved){ return; }
+		this.value = (this.value == "on") ? "off" : "on";
+		this._changeState(this.value);
+		this.onStateChanged(this.value);
+	},
+
+	onTouchStart: function(e){
+		this._moved = false;
+		this.innerStartX = this.inner.offsetLeft;
+		if(e.targetTouches){
+			this.touchStartX = e.targetTouches[0].clientX;
+			this._conn1 = dojo.connect(this.inner, "touchmove", this, "onTouchMove");
+			this._conn2 = dojo.connect(this.inner, "touchend", this, "onTouchEnd");
+		}
+		this.left.style.display = "block";
+		this.right.style.display = "block";
+		return false;
+	},
+
+	onTouchMove: function(e){
+		e.preventDefault();
+		var dx;
+		if(e.targetTouches){
+			if(e.targetTouches.length != 1){ return false; }
+			dx = e.targetTouches[0].clientX - this.touchStartX;
+		}else{
+			dx = e.clientX - this.touchStartX;
+		}
+		var pos = this.innerStartX + dx;
+		var d = 10;
+		if(pos <= -(this._width-d)){ pos = -this._width; }
+		if(pos >= -d){ pos = 0; }
+		this.inner.style.left = pos + "px";
+		this._moved = true;
+		return true;
+	},
+
+	onTouchEnd: function(e){
+		dojo.disconnect(this._conn1);
+		dojo.disconnect(this._conn2);
+		if(this.innerStartX == this.inner.offsetLeft){ return; }
+		var newState = (this.inner.offsetLeft < -(this._width/2)) ? "off" : "on";
+		this._changeState(newState);
+		if(newState != this.value){
+			this.value = newState;
+			this.onStateChanged(this.value);
+		}
+	},
+
+	onStateChanged: function(/*String*/newState){
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.IconContainer",
+	dijit._Widget,
+{
+	defaultIcon: "",
+	transition: "below", // slide, flip, or below
+	pressedIconOpacity: 0.4,
+	iconBase: "",
+	iconPos: "",
+	back: "Home",
+	label: "My Application",
+	single: false,
+
+	buildRendering: function(){
+		this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("UL");
+		this.domNode.className = "mblIconContainer";
+		var t = this._terminator = dojo.create("LI");
+		t.className = "mblIconItemTerminator";
+		t.innerHTML = " ";
+		this.domNode.appendChild(t);
+	},
+
+	_setupSubNodes: function(ul){
+		var len = this.domNode.childNodes.length - 1; // -1 for terminator
+		for(i = 0; i < len; i++){
+			child = this.domNode.childNodes[i];
+			if(child.nodeType != 1){ continue; }
+			w = dijit.byNode(child);
+			if(this.single){
+				w.subNode.firstChild.style.display = "none";
+			}
+			ul.appendChild(w.subNode);
+		}
+	},
+
+	startup: function(){
+		var ul, i, len, child, w;
+		if(this.transition == "below"){
+			this._setupSubNodes(this.domNode);
+		}else{
+			var view = new dojox.mobile.View({id:this.id+"_mblApplView"});
+			var _this = this;
+			view.onAfterTransitionIn = function(moveTo, dir, transition, context, method){
+				_this._opening._open_1();
+			};
+			view.domNode.style.visibility = "hidden";
+			var heading = view._heading = new dojox.mobile.Heading({back:this.back, label:this.label, moveTo:this.domNode.parentNode.id, transition:this.transition});
+			view.addChild(heading);
+			ul = dojo.doc.createElement("UL");
+			ul.className = "mblIconContainer";
+			ul.style.marginTop = "0px";
+			this._setupSubNodes(ul);
+			view.domNode.appendChild(ul);
+			dojo.doc.body.appendChild(view.domNode);
+		}
+	},
+
+	closeAll: function(){
+		var len = this.domNode.childNodes.length;
+		for(var i = 0; i < len; i++){
+			child = this.domNode.childNodes[i];
+			if(child.nodeType != 1){ continue; }
+			if(child == this._terminator){ break; }
+			w = dijit.byNode(child);
+			w.containerNode.parentNode.style.display = "none";
+			w.setOpacity(w.iconNode, 1);
+		}
+	},
+
+	addChild: function(widget){
+		this.domNode.insertBefore(widget.domNode, this._terminator);
+		widget.transition = this.transition;
+		if(this.transition == "below"){
+			this.domNode.appendChild(widget.subNode);
+		}
+		widget.inheritParams();
+		widget.setIcon();
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.IconItem",
+	dojox.mobile.AbstractItem,
+{
+	// description:
+	//		Dynamic creation is not supported.
+	lazy: false,
+	requires: "",
+	timeout: 10,
+
+	templateString: '<li class="mblIconItem">'+
+						'<div class="mblIconArea" dojoAttachPoint="iconDivNode">'+
+							'<div><img src="${icon}" dojoAttachPoint="iconNode"></div>${label}'+
+						'</div>'+
+					'</li>',
+	templateStringSub: '<li class="mblIconItemSub" lazy="${lazy}" style="display:none;" dojoAttachPoint="contentNode">'+
+						'<h2 class="mblIconContentHeading" dojoAttachPoint="closeNode">'+
+							'<div class="mblBlueMinusButton" style="position:absolute;left:4px;top:2px;" dojoAttachPoint="closeIconNode"><div></div></div>${label}'+
+						'</h2>'+
+						'<div class="mblContent" dojoAttachPoint="containerNode"></div>'+
+					'</li>',
+
+	createTemplate: function(s){
+		dojo.forEach(["lazy","icon","label"], function(v){
+			while(s.indexOf("${"+v+"}") != -1){
+				s = s.replace("${"+v+"}", this[v]);
+			}
+		}, this);
+		var div = dojo.doc.createElement("DIV");
+		div.innerHTML = s;
+
+		/*
+		dojo.forEach(dojo.query("[dojoAttachPoint]", domNode), function(node){
+			this[node.getAttribute("dojoAttachPoint")] = node;
+		}, this);
+		*/
+
+		var nodes = div.getElementsByTagName("*");
+		var i, len, s1;
+		len = nodes.length;
+		for(i = 0; i < len; i++){
+			s1 = nodes[i].getAttribute("dojoAttachPoint");
+			if(s1){
+				this[s1] = nodes[i];
+			}
+		}
+		var domNode = div.removeChild(div.firstChild);
+		div = null;
+		return domNode;
+	},
+
+	buildRendering: function(){
+		this.inheritParams();
+		this.domNode = this.createTemplate(this.templateString);
+		this.subNode = this.createTemplate(this.templateStringSub);
+		this.subNode._parentNode = this.domNode; // [custom property]
+
+		if(this.srcNodeRef){
+			// reparent
+			for(var i = 0, len = this.srcNodeRef.childNodes.length; i < len; i++){
+				this.containerNode.appendChild(this.srcNodeRef.removeChild(this.srcNodeRef.firstChild));
+			}
+			this.srcNodeRef.parentNode.replaceChild(this.domNode, this.srcNodeRef);
+			this.srcNodeRef = null;
+		}
+		this.setIcon();
+	},
+
+	setIcon: function(){
+		this.iconNode.src = this.icon;
+		dojox.mobile.setupIcon(this.iconNode, this.iconPos);
+	},
+
+	postCreate: function(){
+		this.connect(this.iconNode, "onmousedown", "onMouseDownIcon");
+		this.connect(this.iconNode, "onclick", "iconClicked");
+		this.connect(this.closeIconNode, "onclick", "closeIconClicked");
+		this.connect(this.iconNode, "onerror", "onError");
+	},
+
+	highlight: function(){
+		dojo.addClass(this.iconDivNode, "mblVibrate");
+		if(this.timeout > 0){
+			var _this = this;
+			setTimeout(function(){
+				_this.unhighlight();
+			}, this.timeout*1000);
+		}
+	},
+
+	unhighlight: function(){
+		dojo.removeClass(this.iconDivNode, "mblVibrate");
+	},
+
+	setOpacity: function(node, val){
+		node.style.opacity = val;
+		node.style.mozOpacity = val;
+		node.style.khtmlOpacity = val;
+		node.style.webkitOpacity = val;
+	},
+
+	instantiateWidget: function(e){
+		// avoid use of dojo.query
+		/*
+		var list = dojo.query('[dojoType]', this.containerNode);
+		for(var i = 0, len = list.length; i < len; i++){
+			dojo["require"](list[i].getAttribute("dojoType"));
+		}
+		*/
+
+		var nodes = this.containerNode.getElementsByTagName("*");
+		var len = nodes.length;
+		var s;
+		for(var i = 0; i < len; i++){
+			s = nodes[i].getAttribute("dojoType");
+			if(s){
+				dojo["require"](s);
+			}
+		}
+
+		if(len > 0){
+			(dojox.mobile.parser || dojo.parser).parse(this.containerNode);
+		}
+		this.lazy = false;
+	},
+
+	isOpen: function(e){
+		return this.containerNode.style.display != "none";
+	},
+
+	onMouseDownIcon: function (e){
+		this.setOpacity(this.iconNode, this.getParentWidget().pressedIconOpacity);
+	},
+
+	iconClicked: function(e){
+		if(e){
+			setTimeout(dojo.hitch(this, function(d){ this.iconClicked(); }), 0);
+			return;
+		}
+		if(this.moveTo || this.href || this.url){
+			this.transitionTo(this.moveTo, this.href, this.url);
+			setTimeout(dojo.hitch(this, function(d){
+				this.setOpacity(this.iconNode, 1);
+			}), 1500);
+		}else{
+			this.open();
+		}
+	},
+
+	closeIconClicked: function(e){
+		if(e){
+			setTimeout(dojo.hitch(this, function(d){ this.closeIconClicked(); }), 0);
+			return;
+		}
+		this.close();
+	},
+
+	open: function(){
+		var parent = this.getParentWidget(); // IconContainer
+		if(this.transition == "below"){
+			if(parent.single){
+				parent.closeAll();
+				this.setOpacity(this.iconNode, this.getParentWidget().pressedIconOpacity);
+			}
+			this._open_1();
+		}else{
+			parent._opening = this;
+			if(parent.single){
+				parent.closeAll();
+				var view = dijit.byId(parent.id+"_mblApplView");
+				view._heading.setLabel(this.label);
+			}
+			this.transitionTo(parent.id+"_mblApplView");
+		}
+	},
+
+	_open_1: function(){
+		this.contentNode.style.display = "";
+		this.unhighlight();
+		if(this.lazy){
+			if(this.requires){
+				dojo.forEach(this.requires.split(/,/), function(c){
+					dojo["require"](c);
+				});
+			}
+			this.instantiateWidget();
+		}
+		this.contentNode.scrollIntoView();
+		this.onOpen();
+	},
+
+	close: function(){
+		if(dojo.isWebKit){
+			var t = this.domNode.parentNode.offsetWidth/8;
+			var y = this.iconNode.offsetLeft;
+			var pos = 0;
+			for(var i = 1; i <= 3; i++){
+				if(t*(2*i-1) < y && y <= t*(2*(i+1)-1)){
+					pos = i;
+					break;
+				}
+			}
+			dojo.addClass(this.containerNode.parentNode, "mblCloseContent mblShrink"+pos);
+		}else{
+			this.containerNode.parentNode.style.display = "none";
+		}
+		this.setOpacity(this.iconNode, 1);
+		this.onClose();
+	},
+
+	onOpen: function(){
+		// stub method to allow the application to connect to.
+	},
+
+	onClose: function(){
+		// stub method to allow the application to connect to.
+	},
+
+	onError: function(){
+		this.iconNode.src = this.getParentWidget().defaultIcon;
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.Button",
+	dijit._Widget,
+{
+	btnClass: "mblBlueButton",
+	duration: 1000, // duration of selection, milliseconds
+
+	label: null,
+
+	buildRendering: function(){
+		this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("BUTTON");
+		this.domNode.className = "mblButton "+this.btnClass;
+
+		if(this.label){
+			this.domNode.innerHTML = this.label;
+		}
+
+		this.connect(this.domNode, "onclick", "onClick");
+	},
+
+	onClick: function(e){
+		var button = this.domNode;
+		var c = "mblButtonSelected "+this.btnClass+"Selected";
+		dojo.addClass(button, c);
+		setTimeout(function(){
+			dojo.removeClass(button, c);
+		}, this.duration);
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.TabContainer",
+	dijit._Widget,
+{
+	iconBase: "",
+	iconPos: "",
+
+	buildRendering: function(){
+		var node = this.domNode = this.srcNodeRef;
+		node.className = "mblTabContainer";
+		var headerNode = this.tabHeaderNode = dojo.doc.createElement("DIV");
+		var paneNode = this.containerNode = dojo.doc.createElement("DIV");
+
+		// reparent
+		for(var i = 0, len = node.childNodes.length; i < len; i++){
+			paneNode.appendChild(node.removeChild(node.firstChild));
+		}
+
+		headerNode.className = "mblTabPanelHeader";
+		headerNode.align = "center";
+		node.appendChild(headerNode);
+		paneNode.className = "mblTabPanelPane";
+		node.appendChild(paneNode);
+	},
+
+	startup: function(){
+		this.createTabButtons();
+		this.inherited(arguments);
+	},
+
+	createTabButtons: function(){
+		var div = dojo.doc.createElement("DIV");
+		div.align = "center";
+		var tbl = dojo.doc.createElement("TABLE");
+		var cell = tbl.insertRow(-1).insertCell(-1);
+		var children = this.containerNode.childNodes;
+		for(var i = 0; i < children.length; i++){
+			var pane = children[i];
+			if(pane.nodeType != 1){ continue; }
+			var widget = dijit.byNode(pane);
+			if(widget.selected || !this._selectedPane){
+				this._selectedPane = widget;
+			}
+			pane.style.display = "none";
+			var tab = dojo.doc.createElement("DIV");
+			tab.className = "mblTabButton";
+			if(widget.icon){
+				var imgDiv = dojo.create("DIV");
+				var img = dojo.create("IMG");
+				imgDiv.className = "mblTabButtonImgDiv";
+				img.src = widget.icon;
+				dojox.mobile.setupIcon(img, widget.iconPos);
+				imgDiv.appendChild(img);
+				tab.appendChild(imgDiv);
+			}
+			tab.appendChild(dojo.doc.createTextNode(widget.label));
+			tab.pane = widget;
+			widget.tab = tab;
+			this.connect(tab, "onclick", "onTabClick");
+			cell.appendChild(tab);
+		}
+		div.appendChild(tbl);
+		this.tabHeaderNode.appendChild(div);
+		this.selectTab(this._selectedPane.tab);
+	},
+
+	selectTab: function(/*DomNode*/tab){
+		this._selectedPane.domNode.style.display = "none";
+		dojo.removeClass(this._selectedPane.tab, "mblTabButtonSelected");
+		this._selectedPane = tab.pane;
+		this._selectedPane.domNode.style.display = "";
+		dojo.addClass(tab, "mblTabButtonSelected");
+	},
+
+	onTabClick: function(e){
+		var tab = e.currentTarget;
+		dojo.addClass(tab, "mblTabButtonHighlighted");
+		setTimeout(function(){
+			dojo.removeClass(tab, "mblTabButtonHighlighted");
+		}, 200);
+		this.selectTab(tab);
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.TabPane",
+	dijit._Widget,
+{
+	label: "",
+	icon: "",
+	iconPos: "",
+	selected: false,
+
+	inheritParams: function(){
+		var parent = this.getParentWidget();
+		if(parent){
+			if(!this.icon){ this.icon = parent.iconBase; }
+			if(!this.iconPos){ this.iconPos = parent.iconPos; }
+		}
+	},
+
+	buildRendering: function(){
+		this.inheritParams();
+		this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("DIV");
+		this.domNode.className = "mblTabPane";
+	},
+
+	getParentWidget: function(){
+		var ref = this.srcNodeRef || this.domNode;
+		return ref && ref.parentNode ? dijit.getEnclosingWidget(ref.parentNode) : null;
+	}
+});
+
+dojo.declare(
+	"dojox.mobile.ProgressIndicator",
+	null,
+{
+	interval: 100, // milliseconds
+	colors: [
+		"#C0C0C0", "#C0C0C0", "#C0C0C0", "#C0C0C0",
+		"#C0C0C0", "#C0C0C0", "#B8B9B8", "#AEAFAE",
+		"#A4A5A4", "#9A9A9A", "#8E8E8E", "#838383"
+	],
+
+	_bars: [],
+
+	constructor: function(){
+		this.domNode = dojo.create("DIV");
+		this.domNode.className = "mblProgContainer";
+		for(var i = 0; i < 12; i++){
+			var div = dojo.create("DIV");
+			div.className = "mblProg mblProg"+i;
+			this.domNode.appendChild(div);
+			this._bars.push(div);
+		}
+	},
+
+	start: function(){
+		var cntr = 0;
+		var _this = this;
+		this.timer = setInterval(function(){
+			cntr--;
+			cntr = cntr < 0 ? 11 : cntr;
+			var c = _this.colors;
+			for(var i = 0; i < 12; i++){
+				var idx = (cntr + i) % 12;
+				_this._bars[i].style.backgroundColor = c[idx];
+			}
+		}, this.interval);
+	},
+
+	stop: function(){
+		if(this.timer){
+			clearInterval(this.timer);
+		}
+		this.timer = null;
+		if(this.domNode.parentNode){
+			this.domNode.parentNode.removeChild(this.domNode);
+		}
+	}
+});
+dojox.mobile.ProgressIndicator._instance = null;
+dojox.mobile.ProgressIndicator.getInstance = function(){
+	if(!dojox.mobile.ProgressIndicator._instance){
+		dojox.mobile.ProgressIndicator._instance = new dojox.mobile.ProgressIndicator();
+	}
+	return dojox.mobile.ProgressIndicator._instance;
+};
+
+dojox.mobile.addClass = function(){
+	// summary:
+	//		Adds a theme class name to <body>.
+	// description:
+	//		Finds the currently applied theme name, such as 'iphone' or 'android'
+	//		from link elements, and adds it as a class name for the body element.
+	var elems = document.getElementsByTagName("link");
+	for(var i = 0, len = elems.length; i < len; i++){
+		if(elems[i].href.match(/dojox\/mobile\/themes\/(\w+)\//)){
+			dojox.mobile.theme = RegExp.$1;
+			dojo.addClass(dojo.body(), dojox.mobile.theme);
+			break;
+		}
+	}
+};
+
+dojox.mobile.setupIcon = function(/*DomNode*/iconNode, /*String*/iconPos){
+	if(iconNode && iconPos){
+		var arr = dojo.map(iconPos.split(/[ ,]/),
+								function(item){ return item - 0; });
+		var t = arr[0]; // top
+		var r = arr[1] + arr[2]; // right
+		var b = arr[0] + arr[3]; // bottom
+		var l = arr[1]; // left
+		iconNode.style.clip = "rect("+t+"px "+r+"px "+b+"px "+l+"px)";
+		iconNode.style.top = -t + "px";
+		iconNode.style.left = -l + "px";
+	}
+};
+
+dojo._loaders.unshift(function(){
+	// avoid use of dojo.query
+	/*
+	var list = dojo.query('[lazy=true] [dojoType]', null);
+	list.forEach(function(node, index, nodeList){
+		node.setAttribute("__dojoType", node.getAttribute("dojoType"));
+		node.removeAttribute("dojoType");
+	});
+	*/
+
+	var nodes = dojo.body().getElementsByTagName("*");
+	var i, len, s;
+	len = nodes.length;
+	for(i = 0; i < len; i++){
+		s = nodes[i].getAttribute("dojoType");
+		if(s){
+			if(nodes[i].parentNode.getAttribute("lazy") == "true"){
+				nodes[i].setAttribute("__dojoType", s);
+				nodes[i].removeAttribute("dojoType");
+			}
+		}
+	}
+});
+
+dojo.addOnLoad(function(){
+	dojox.mobile.addClass();
+	if(dojo.config["mblApplyPageStyles"] !== false){
+		dojo.addClass(dojo.doc.documentElement, "mobile");
+	}
+
+	//	You can disable hiding the address bar with the following djConfig.
+	//	var djConfig = { mblHideAddressBar: false };
+	if(dojo.config["mblHideAddressBar"] !== false){
+		var hideAddressBar = function(){
+			setTimeout(function(){ scrollTo(0, 1); }, 100);
+		};
+		hideAddressBar();
+		//dojo.connect(dojo.body(), "onorientationchange", hideAddressBar);
+	}
+
+	// avoid use of dojo.query
+	/*
+	var list = dojo.query('[__dojoType]', null);
+	list.forEach(function(node, index, nodeList){
+		node.setAttribute("dojoType", node.getAttribute("__dojoType"));
+		node.removeAttribute("__dojoType");
+	});
+	*/
+
+	var nodes = dojo.body().getElementsByTagName("*");
+	var i, len = nodes.length, s;
+	for(i = 0; i < len; i++){
+		s = nodes[i].getAttribute("__dojoType");
+		if(s){
+			nodes[i].setAttribute("dojoType", s);
+			nodes[i].removeAttribute("__dojoType");
+		}
+	}
+
+	if(dojo.hash){
+		// find widgets under root recursively
+		var findWidgets = function(root){
+			var arr;
+			arr = dijit.findWidgets(root);
+			var widgets = arr;
+			for(var i = 0; i < widgets.length; i++){
+				arr = arr.concat(findWidgets(widgets[i].containerNode));
+			}
+			return arr;
+		};
+		dojo.subscribe("/dojo/hashchange", null, function(value){
+			var view = dojox.mobile._currentView;
+			if(!view){ return; }
+			var params = dojox.mobile._params;
+			if(!params){ // browser back/forward button was pressed
+				var moveTo = value ? value : dojox.mobile._defaultView.id;
+				var widgets = findWidgets(view.domNode);
+				var dir = 1, transition = "slide";
+				for(i = 0; i < widgets.length; i++){
+					var w = widgets[i];
+					if("#"+moveTo == w.moveTo){
+						// found a widget that has the given moveTo
+						transition = w.transition;
+						dir = (w instanceof dojox.mobile.Heading) ? -1 : 1;
+						break;
+					}
+				}
+				params = [ moveTo, dir, transition ];
+			}
+			view.performTransition.apply(view, params);
+			dojox.mobile._params = null;
+		});
+	}
+
+	dojo.body().style.visibility = "visible";
+});
+
+dijit.getEnclosingWidget = function(node){
+	while(node && node.tagName !== "BODY"){
+		if(node.getAttribute && node.getAttribute("widgetId")){
+			return dijit.registry.byId(node.getAttribute("widgetId"));
+		}
+		node = node._parentNode || node.parentNode;
+	}
+	return null;
+};
diff --git a/dojox/mobile/app.js b/dojox/mobile/app.js
new file mode 100755
index 0000000..1d5b8eb
--- /dev/null
+++ b/dojox/mobile/app.js
@@ -0,0 +1,3 @@
+dojo.provide("dojox.mobileApp");
+
+dojo.require("dojox.mobile.app._base");
\ No newline at end of file
diff --git a/dojox/mobile/app/AlertDialog.js b/dojox/mobile/app/AlertDialog.js
new file mode 100644
index 0000000..8c7537d
--- /dev/null
+++ b/dojox/mobile/app/AlertDialog.js
@@ -0,0 +1,182 @@
+dojo.provide("dojox.mobile.app.AlertDialog");
+dojo.experimental("dojox.mobile.app.AlertDialog");
+dojo.require("dijit._Widget");
+
+dojo.declare("dojox.mobile.app.AlertDialog", dijit._Widget, {
+
+	// title: String
+	//		The title of the AlertDialog
+	title: "",
+
+	// text: String
+	//		The text message displayed in the AlertDialog
+	text: "",
+
+	// controller: Object
+	//		The SceneController for the currently active scene
+	controller: null,
+
+	// buttons: Array
+	buttons: null,
+
+	defaultButtonLabel: "OK",
+
+	// onChoose: Function
+	//		The callback function that is invoked when a button is tapped.
+	//		If the dialog is cancelled, no parameter is passed to this function.
+	onChoose: null,
+
+	constructor: function(){
+		this.onClick = dojo.hitch(this, this.onClick);
+		this._handleSelect = dojo.hitch(this, this._handleSelect);
+	},
+
+	buildRendering: function(){
+		this.domNode = dojo.create("div",{
+			"class": "alertDialog"
+		});
+
+		// Create the outer dialog body
+		var dlgBody = dojo.create("div", {"class": "alertDialogBody"}, this.domNode);
+
+		// Create the title
+		dojo.create("div", {"class": "alertTitle", innerHTML: this.title || ""}, dlgBody);
+
+		// Create the text
+		dojo.create("div", {"class": "alertText", innerHTML: this.text || ""}, dlgBody);
+
+		// Create the node that encapsulates all the buttons
+		var btnContainer = dojo.create("div", {"class": "alertBtns"}, dlgBody);
+
+		// If no buttons have been defined, default to a single button saying OK
+		if(!this.buttons || this.buttons.length == 0){
+			this.buttons = [{
+				label: this.defaultButtonLabel,
+				value: "ok",
+				"class": "affirmative"
+			}];
+		}
+
+		var _this = this;
+
+		// Create each of the buttons
+		dojo.forEach(this.buttons, function(btnInfo){
+			var btn = new dojox.mobile.Button({
+				btnClass: btnInfo["class"] || "",
+				label: btnInfo.label
+			});
+			btn._dialogValue = btnInfo.value;
+			dojo.place(btn.domNode, btnContainer);
+			_this.connect(btn, "onClick", _this._handleSelect);
+		});
+
+		var viewportSize = this.controller.getWindowSize();
+
+		// Create the mask that blocks out the rest of the screen
+		this.mask = dojo.create("div", {"class": "dialogUnderlayWrapper",
+			innerHTML: "<div class=\"dialogUnderlay\"></div>",
+			style: {
+				width: viewportSize.w + "px",
+				height: viewportSize.h + "px"
+			}
+		}, this.controller.assistant.domNode);
+
+		this.connect(this.mask, "onclick", function(){
+			_this.onChoose && _this.onChoose();
+			_this.hide();
+		});
+	},
+
+	postCreate: function(){
+		this.subscribe("/dojox/mobile/app/goback", this._handleSelect);
+	},
+
+	_handleSelect: function(event){
+		// summary:
+		//		Handle the selection of a value
+		var node;
+		console.log("handleSelect");
+		if(event && event.target){
+			node = event.target;
+
+			// Find the widget that was tapped.
+			while(!dijit.byNode(node)){
+				node - node.parentNode;
+			}
+		}
+
+		// If an onChoose function was provided, tell it what button
+		// value was chosen
+		if(this.onChoose){
+			this.onChoose(node ? dijit.byNode(node)._dialogValue: undefined);
+		}
+		// Hide the dialog
+		this.hide();
+	},
+
+	show: function(){
+		// summary:
+		//		Show the dialog
+		this._doTransition(1);
+	},
+
+	hide: function(){
+		// summary:
+		//		Hide the dialog
+		this._doTransition(-1);
+	},
+
+	_doTransition: function(dir){
+		// summary:
+		//		Either shows or hides the dialog.
+		// dir:
+		//		An integer.  If positive, the dialog is shown. If negative,
+		//		the dialog is hidden.
+
+		// TODO: replace this with CSS transitions
+
+		var anim;
+		var h = dojo.marginBox(this.domNode.firstChild).h;
+
+
+		var bodyHeight = this.controller.getWindowSize().h;
+		console.log("dialog height = " + h, " body height = " + bodyHeight);
+
+		var high = bodyHeight - h;
+		var low = bodyHeight;
+
+		var anim1 = dojo.fx.slideTo({
+			node: this.domNode,
+			duration: 400,
+			top: {start: dir < 0 ? high : low, end: dir < 0 ? low: high}
+		});
+
+		var anim2 = dojo[dir < 0 ? "fadeOut" : "fadeIn"]({
+			node: this.mask,
+			duration: 400
+		});
+
+		var anim = dojo.fx.combine([anim1, anim2]);
+
+		var _this = this;
+
+		dojo.connect(anim, "onEnd", this, function(){
+			if(dir < 0){
+				_this.domNode.style.display = "none";
+				dojo.destroy(_this.domNode);
+				dojo.destroy(_this.mask);
+			}
+		});
+		anim.play();
+	},
+
+	destroy: function(){
+		this.inherited(arguments);
+		dojo.destroy(this.mask);
+	},
+
+
+	onClick: function(){
+
+	}
+});
\ No newline at end of file
diff --git a/dojox/mobile/app/ImageThumbView.js b/dojox/mobile/app/ImageThumbView.js
new file mode 100644
index 0000000..56175d0
--- /dev/null
+++ b/dojox/mobile/app/ImageThumbView.js
@@ -0,0 +1,254 @@
+dojo.provide("dojox.mobile.app.ImageThumbView");
+dojo.experimental("dojox.mobile.app.ImageThumbView");
+
+dojo.require("dijit._Widget");
+dojo.require("dojo.string");
+
+dojo.declare("dojox.mobile.app.ImageThumbView", dijit._Widget, {
+	// summary:
+	//		An image thumbnail gallery
+
+	// items: Array
+	//		The data items from which the image urls are retrieved.
+	//		If an item is a string, it is expected to be a URL. Otherwise
+	//		by default it is expected to have a 'url' member.  This can
+	//		be configured using the 'urlParam' attribute on this widget.
+	items: null,
+
+	// urlParam: String
+	//		The paramter name used to retrieve an image url from a JSON object
+	urlParam: "url",
+
+	itemTemplate: '<div class="mblThumbInner">' +
+				'<div class="mblThumbOverlay"></div>' +
+				'<div class="mblThumbMask">' +
+					'<div class="mblThumbSrc" style="background-image:url(${url})"></div>' +
+				'</div>' +
+			'</div>',
+
+	minPadding: 5,
+
+	maxPerRow: 3,
+
+	baseClass: "mblImageThumbView",
+
+	selectedIndex: -1,
+
+	cache: null,
+
+	postCreate: function(){
+		this.inherited(arguments);
+		var _this = this;
+
+		var hoverCls = "mblThumbHover";
+
+		this.addThumb = dojo.hitch(this, this.addThumb);
+		this.handleImgLoad = dojo.hitch(this, this.handleImgLoad);
+
+		this._onLoadImages = {};
+
+		this.cache = [];
+		this.visibleImages = [];
+
+		this.connect(this.domNode, "onclick", function(event){
+			var itemNode = _this._getItemNodeFromEvent(event);
+
+			if(itemNode){
+				_this.onSelect(itemNode._item, itemNode._index, _this.items);
+				dojo.query(".selected", this.domNode).removeClass("selected");
+				dojo.addClass(itemNode, "selected");
+			}
+		});
+
+		this.resize();
+		this.render();
+	},
+
+	onSelect: function(item, index, items){
+		// summary:
+		//		Dummy function that is triggered when an image is selected.
+	},
+
+	_setItemsAttr: function(items){
+		this.items = items || [];
+
+		this.render();
+	},
+
+	_getItemNode: function(node){
+		while(node && !dojo.hasClass(node, "mblThumb") && node != this.domNode){
+			node = node.parentNode;
+		}
+
+		return (node == this.domNode) ? null : node;
+	},
+
+	_getItemNodeFromEvent: function(event){
+		if(event.touches && event.touches.length > 0){
+			event = event.touches[0];
+		}
+		return this._getItemNode(event.target);
+	},
+
+	resize: function(){
+		this._thumbSize = null;
+
+		this._size = dojo.marginBox(this.domNode);
+
+		this.render();
+	},
+
+	render: function(){
+		var i;
+		var url;
+		var item;
+
+		var thumb;
+		while(this.visibleImages.length > 0){
+			thumb = this.visibleImages.pop();
+			this.cache.push(thumb);
+
+			dojo.addClass(thumb, "hidden");
+			thumb._cached = true;
+		}
+		if(!this.items || this.items.length == 0){
+			//dojo.empty(this.domNode);
+			return;
+		}
+
+
+		for(i = 0; i < this.items.length; i++){
+			item = this.items[i];
+			url = (dojo.isString(item) ? item : item[this.urlParam]);
+
+			this.addThumb(item, url, i);
+		}
+
+		if(!this._thumbSize){
+			return;
+		}
+
+		var column = 0;
+		var row = -1;
+
+		var totalThumbWidth = this._thumbSize.w + (this.padding * 2);
+		var totalThumbHeight = this._thumbSize.h + (this.padding * 2);
+
+		var nodes = this.thumbNodes =
+			dojo.query(".mblThumb", this.domNode);
+
+		var pos = 0;
+		for(i = 0; i < nodes.length; i++){
+			if(nodes[i]._cached){
+				continue;
+			}
+
+			if(pos % this.maxPerRow == 0){
+				row ++;
+			}
+			column = pos % this.maxPerRow;
+
+			this.place(
+				nodes[i],
+				(column * totalThumbWidth) + this.padding,	// x position
+				(row * totalThumbHeight) + this.padding		// y position
+			);
+
+			if(!nodes[i]._loading){
+				dojo.removeClass(nodes[i], "hidden");
+			}
+
+			if(pos == this.selectedIndex){
+				dojo[pos == this.selectedIndex ? "addClass" : "removeClass"]
+					(nodes[i], "selected");
+			}
+			pos++;
+		}
+
+		var numRows = Math.ceil(pos / this.maxPerRow);
+		
+		if(this._numRows != numRows){
+			this._numRows = numRows;
+			dojo.style(this.domNode, "height",
+					(numRows * (this._thumbSize.h + this.padding * 2)) + "px");
+		}
+
+	},
+
+	addThumb: function(item, url, index){
+
+		var thumbDiv;
+		if(this.cache.length > 0){
+			// Reuse a previously created node if possible
+			thumbDiv = this.cache.pop();
+		}else{
+			// Create a new thumb
+			thumbDiv = dojo.create("div", {
+				"class": "mblThumb hidden",
+				innerHTML: dojo.string.substitute(this.itemTemplate, {
+					url: url
+				}, null, this)
+			}, this.domNode);
+		}
+		dojo.addClass(thumbDiv, "hidden");
+		var loader = dojo.create("img",{});
+		loader._thumbDiv = thumbDiv;
+		loader._conn = dojo.connect(loader, "onload", this.handleImgLoad);
+		loader._url = url;
+		thumbDiv._loading = true;
+
+		this._onLoadImages[url] = loader;
+		loader.src = url;
+
+		this.visibleImages.push(thumbDiv);
+
+		thumbDiv._index = index;
+		thumbDiv._item = item;
+		thumbDiv._url = url;
+		thumbDiv._cached = false;
+
+		if(!this._thumbSize){
+			this._thumbSize = dojo.marginBox(thumbDiv);
+			this.calcPadding();
+		}
+	},
+
+	handleImgLoad: function(event){
+		var img = event.target;
+		dojo.disconnect(img._conn);
+		dojo.removeClass(img._thumbDiv, "hidden");
+		img._thumbDiv._loading = false;
+
+		dojo.query(".mblThumbSrc", img._thumbDiv)
+				.style("backgroundImage", "url(" + img._url + ")");
+
+		delete this._onLoadImages[img._url];
+	},
+
+	calcPadding: function(){
+		var width = this._size.w;
+
+		var thumbWidth = this._thumbSize.w;
+
+		var imgBounds = thumbWidth + this.minPadding;
+
+		this.maxPerRow = Math.floor(width / imgBounds);
+
+		this.padding = (width - (thumbWidth * this.maxPerRow)) / (this.maxPerRow * 2);
+	},
+
+	place: function(node, x, y){
+		// TODO: replace this with webkit transforms
+		
+		
+		dojo.style(node, {
+			"-webkit-transform" :"translate(" + x + "px," + y + "px)"
+		});
+//		dojo.style(node, {
+//			top: y + "px",
+//			left: x + "px",
+//			visibility: "visible"
+//		});
+	}
+
+});
\ No newline at end of file
diff --git a/dojox/mobile/app/ImageView.js b/dojox/mobile/app/ImageView.js
new file mode 100644
index 0000000..a9ce3fe
--- /dev/null
+++ b/dojox/mobile/app/ImageView.js
@@ -0,0 +1,716 @@
+dojo.provide("dojox.mobile.app.ImageView");
+dojo.experimental("dojox.mobile.app.ImageView");
+dojo.require("dojox.mobile.app._Widget");
+
+dojo.require("dojo.fx.easing");
+
+dojo.declare("dojox.mobile.app.ImageView", dojox.mobile.app._Widget, {
+
+	// zoom: Number
+	//		The current level of zoom.  This should not be set manually.
+	zoom: 1,
+
+	// zoomCenterX: Number
+	//		The X coordinate in the image where the zoom is focused
+	zoomCenterX: 0,
+
+	// zoomCenterY: Number
+	//		The Y coordinate in the image where the zoom is focused
+	zoomCenterY: 0,
+
+	// maxZoom: Number
+	//		The highest degree to which an image can be zoomed.  For example,
+	//		a maxZoom of 5 means that the image will be 5 times larger than normal
+	maxZoom: 5,
+
+	// autoZoomLevel: Number
+	//		The degree to which the image is zoomed when auto zoom is invoked.
+	//		The higher the number, the more the image is zoomed in.
+	autoZoomLevel: 3,
+
+	// disableAutoZoom: Boolean
+	//		Disables auto zoom
+	disableAutoZoom: false,
+
+	// disableSwipe: Boolean
+	//		Disables the users ability to swipe from one image to the next.
+	disableSwipe: false,
+
+	// autoZoomEvent: String
+	//		Overrides the default event listened to which invokes auto zoom
+	autoZoomEvent: null,
+
+	// _leftImg: Node
+	//		The full sized image to the left
+	_leftImg: null,
+
+	// _centerImg: Node
+	//		The full sized image in the center
+	_centerImg: null,
+
+	// _rightImg: Node
+	//		The full sized image to the right
+	_rightImg: null,
+
+	// _leftImg: Node
+	//		The small sized image to the left
+	_leftSmallImg: null,
+
+	// _centerImg: Node
+	//		The small sized image in the center
+	_centerSmallImg: null,
+
+	// _rightImg: Node
+	//		The small sized image to the right
+	_rightSmallImg: null,
+
+	constructor: function(){
+
+		this.panX = 0;
+		this.panY = 0;
+
+		this.handleLoad = dojo.hitch(this, this.handleLoad);
+		this._updateAnimatedZoom = dojo.hitch(this, this._updateAnimatedZoom);
+		this._updateAnimatedPan = dojo.hitch(this, this._updateAnimatedPan);
+		this._onAnimPanEnd = dojo.hitch(this, this._onAnimPanEnd);
+	},
+
+	buildRendering: function(){
+		this.inherited(arguments);
+
+		this.canvas = dojo.create("canvas", {}, this.domNode);
+
+		dojo.addClass(this.domNode, "mblImageView");
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+
+		this.size = dojo.marginBox(this.domNode);
+
+		dojo.style(this.canvas, {
+			width: this.size.w + "px",
+			height: this.size.h + "px"
+		});
+		this.canvas.height = this.size.h;
+		this.canvas.width = this.size.w;
+
+		var _this = this;
+
+		// Listen to the mousedown/touchstart event.  Record the position
+		// so we can use it to pan the image.
+		this.connect(this.domNode, "onmousedown", function(event){
+			if(_this.isAnimating()){
+				return;
+			}
+			if(_this.panX){
+				_this.handleDragEnd();
+			}
+
+			_this.downX = event.targetTouches ? event.targetTouches[0].clientX : event.clientX;
+			_this.downY = event.targetTouches ? event.targetTouches[0].clientY : event.clientY;
+		});
+
+		// record the movement of the mouse.
+		this.connect(this.domNode, "onmousemove", function(event){
+			if(_this.isAnimating()){
+				return;
+			}
+			if((!_this.downX && _this.downX !== 0) || (!_this.downY && _this.downY !== 0)){
+				// If the touch didn't begin on this widget, ignore the movement
+				return;
+			}
+
+			if((!_this.disableSwipe && _this.zoom == 1)
+				|| (!_this.disableAutoZoom && _this.zoom != 1)){
+				var x = event.targetTouches ?
+							event.targetTouches[0].clientX : event.pageX;
+				var y = event.targetTouches ?
+							event.targetTouches[0].clientY : event.pageY;
+
+				_this.panX = x - _this.downX;
+				_this.panY = y - _this.downY;
+
+				if(_this.zoom == 1){
+					// If not zoomed in, then try to move to the next or prev image
+					// but only if the mouse has moved more than 10 pixels
+					// in the X direction
+					if(Math.abs(_this.panX) > 10){
+						_this.render();
+					}
+				}else{
+					// If zoomed in, pan the image if the mouse has moved more
+					// than 10 pixels in either direction.
+					if(Math.abs(_this.panX) > 10 || Math.abs(_this.panY) > 10){
+						_this.render();
+					}
+				}
+			}
+		});
+
+		this.connect(this.domNode, "onmouseout", function(event){
+			if(!_this.isAnimating() && _this.panX){
+				_this.handleDragEnd();
+			}
+		});
+
+		this.connect(this.domNode, "onmouseover", function(event){
+			_this.downX = _this.downY = null;
+		});
+
+		// Set up AutoZoom, which zooms in a fixed amount when the user taps
+		// a part of the canvas
+		this.connect(this.domNode, "onclick", function(event){
+			if(_this.isAnimating()){
+				return;
+			}
+			if(_this.downX == null || _this.downY == null){
+				return;
+			}
+
+			var x = (event.targetTouches ?
+						event.targetTouches[0].clientX : event.pageX);
+			var y = (event.targetTouches ?
+						event.targetTouches[0].clientY : event.pageY);
+
+			// If the mouse/finger has moved more than 14 pixels from where it
+			// started, do not treat it as a click.  It is a drag.
+			if(Math.abs(_this.panX) > 14 || Math.abs(_this.panY) > 14){
+				_this.downX = _this.downY = null;
+				_this.handleDragEnd();
+				return;
+			}
+			_this.downX = _this.downY = null;
+
+			if(!_this.disableAutoZoom){
+
+				if(!_this._centerImg || !_this._centerImg._loaded){
+					// Do nothing until the image is loaded
+					return;
+				}
+				if(_this.zoom != 1){
+					_this.set("animatedZoom", 1);
+					return;
+				}
+
+				var pos = dojo._abs(_this.domNode);
+
+				// Translate the clicked point to a point on the source image
+				var xRatio = _this.size.w / _this._centerImg.width;
+				var yRatio = _this.size.h / _this._centerImg.height;
+
+				// Do an animated zoom to the point which was clicked.
+				_this.zoomTo(
+					((x - pos.x) / xRatio) - _this.panX,
+					((y - pos.y) / yRatio) - _this.panY,
+					_this.autoZoomLevel);
+			}
+		});
+
+		// Listen for Flick events
+		dojo.connect(this.domNode, "flick", this, "handleFlick");
+	},
+
+	isAnimating: function(){
+		// summary:
+		//		Returns true if an animation is in progress, false otherwise.
+		return this._anim && this._anim.status() == "playing";
+	},
+
+	handleDragEnd: function(){
+		// summary:
+		//		Handles the end of a dragging event. If not zoomed in, it
+		//		determines if the next or previous image should be transitioned
+		//		to.
+		this.downX = this.downY = null;
+		console.log("handleDragEnd");
+
+		if(this.zoom == 1){
+			if(!this.panX){
+				return;
+			}
+
+			var leftLoaded = (this._leftImg && this._leftImg._loaded)
+							|| (this._leftSmallImg && this._leftSmallImg._loaded);
+			var rightLoaded = (this._rightImg && this._rightImg._loaded)
+							|| (this._rightSmallImg && this._rightSmallImg._loaded);
+
+			// Check if the drag has moved the image more than half its length.
+			// If so, move to either the previous or next image.
+			var doMove =
+				!(Math.abs(this.panX) < this._centerImg._baseWidth / 2) &&
+				(
+					(this.panX > 0 && leftLoaded ? 1 : 0) ||
+					(this.panX < 0 && rightLoaded ? 1 : 0)
+				);
+
+
+			if(!doMove){
+				// If not moving to another image, animate the sliding of the
+				// image back into place.
+				this._animPanTo(0, dojo.fx.easing.expoOut, 700);
+			}else{
+				// Move to another image.
+				this.moveTo(this.panX);
+			}
+		}else{
+			if(!this.panX && !this.panY){
+				return;
+			}
+			// Recenter the zoomed image based on where it was panned to
+			// previously
+			this.zoomCenterX -= (this.panX / this.zoom);
+			this.zoomCenterY -= (this.panY / this.zoom);
+
+			this.panX = this.panY = 0;
+		}
+
+	},
+
+	handleFlick: function(event){
+		// summary:
+		//		Handle a flick event.
+		if(this.zoom == 1 && event.duration < 500){
+			// Only handle quick flicks here, less than 0.5 seconds
+
+			// If not zoomed in, then check if we should move to the next photo
+			// or not
+			if(event.direction == "ltr"){
+				this.moveTo(1);
+			}else if(event.direction == "rtl"){
+				this.moveTo(-1);
+			}
+			// If an up or down flick occurs, it means nothing so ignore it
+			this.downX = this.downY = null;
+		}
+	},
+
+	moveTo: function(direction){
+		direction = direction > 0 ? 1 : -1;
+		var toImg;
+
+		if(direction < 1){
+			if(this._rightImg && this._rightImg._loaded){
+				toImg = this._rightImg;
+			}else if(this._rightSmallImg && this._rightSmallImg._loaded){
+				toImg = this._rightSmallImg;
+			}
+		}else{
+			if(this._leftImg && this._leftImg._loaded){
+				toImg = this._leftImg;
+			}else if(this._leftSmallImg && this._leftSmallImg._loaded){
+				toImg = this._leftSmallImg;
+			}
+		}
+
+		this._moveDir = direction;
+		var _this = this;
+
+		if(toImg && toImg._loaded){
+			// If the image is loaded, make a linear animation to show it
+			this._animPanTo(this.size.w * direction, null, 500, function(){
+				_this.panX = 0;
+				_this.panY = 0;
+
+				if(direction < 0){
+					// Moving to show the right image
+					_this._switchImage("left", "right");
+				}else{
+					// Moving to show the left image
+					_this._switchImage("right", "left");
+				}
+
+				_this.render();
+				_this.onChange(direction * -1);
+			});
+
+		}else{
+			// If the next image is not loaded, make an animation to
+			// move the center image to half the width of the widget and back
+			// again
+
+			console.log("moveTo image not loaded!", toImg);
+
+			this._animPanTo(0, dojo.fx.easing.expoOut, 700);
+		}
+	},
+
+	_switchImage: function(toImg, fromImg){
+		var toSmallImgName = "_" + toImg + "SmallImg";
+		var toImgName = "_" + toImg + "Img";
+
+		var fromSmallImgName = "_" + fromImg + "SmallImg";
+		var fromImgName = "_" + fromImg + "Img";
+
+		this[toImgName] = this._centerImg;
+		this[toSmallImgName] = this._centerSmallImg;
+
+		this[toImgName]._type = toImg;
+
+		if(this[toSmallImgName]){
+			this[toSmallImgName]._type = toImg;
+		}
+
+		this._centerImg = this[fromImgName];
+		this._centerSmallImg = this[fromSmallImgName];
+		this._centerImg._type = "center";
+
+		if(this._centerSmallImg){
+			this._centerSmallImg._type = "center";
+		}
+		this[fromImgName] = this[fromSmallImgName] = null;
+	},
+
+	_animPanTo: function(to, easing, duration, callback){
+		this._animCallback = callback;
+		this._anim = new dojo.Animation({
+			curve: [this.panX, to],
+			onAnimate: this._updateAnimatedPan,
+			duration: duration || 500,
+			easing: easing,
+			onEnd: this._onAnimPanEnd
+		});
+
+		this._anim.play();
+		return this._anim;
+	},
+
+	onChange: function(direction){
+		// summary:
+		//		Stub function that can be listened to in order to provide
+		//		new images when the displayed image changes
+	},
+
+	_updateAnimatedPan: function(amount){
+		this.panX = amount;
+		this.render();
+	},
+
+	_onAnimPanEnd: function(){
+		this.panX = this.panY = 0;
+
+		if(this._animCallback){
+			this._animCallback();
+		}
+	},
+
+	zoomTo: function(centerX, centerY, zoom){
+		this.set("zoomCenterX", centerX);
+		this.set("zoomCenterY", centerY);
+
+		this.set("animatedZoom", zoom);
+	},
+
+	render: function(){
+		var cxt = this.canvas.getContext('2d');
+
+		cxt.clearRect(0, 0, this.canvas.width, this.canvas.height);
+
+		// Render the center image
+		this._renderImg(
+			this._centerSmallImg,
+			this._centerImg,
+			this.zoom == 1 ? (this.panX < 0 ? 1 : this.panX > 0 ? -1 : 0) : 0);
+
+		if(this.zoom == 1 && this.panX != 0){
+			if(this.panX > 0){
+				// Render the left image, showing the right side of it
+				this._renderImg(this._leftSmallImg, this._leftImg, 1);
+			}else{
+				// Render the right image, showing the left side of it
+				this._renderImg(this._rightSmallImg, this._rightImg, -1);
+			}
+		}
+	},
+
+	_renderImg: function(smallImg, largeImg, panDir){
+		// summary:
+		//		Renders a single image
+
+
+		// If zoomed, we just display the center img
+		var img = (largeImg && largeImg._loaded) ? largeImg : smallImg;
+
+		if(!img || !img._loaded){
+			// If neither the large or small image is loaded, display nothing
+			return;
+		}
+		var cxt = this.canvas.getContext('2d');
+
+		var baseWidth = img._baseWidth;
+		var baseHeight = img._baseHeight;
+
+		// Calculate the size the image would be if there were no bounds
+		var desiredWidth = baseWidth * this.zoom;
+		var desiredHeight = baseHeight * this.zoom;
+
+		// Calculate the actual size of the viewable image
+		var destWidth = Math.min(this.size.w, desiredWidth);
+		var destHeight = Math.min(this.size.h, desiredHeight);
+
+
+		// Calculate the size of the window on the original image to use
+		var sourceWidth = this.dispWidth = img.width * (destWidth / desiredWidth);
+		var sourceHeight = this.dispHeight = img.height * (destHeight / desiredHeight);
+
+		var zoomCenterX = this.zoomCenterX - (this.panX / this.zoom);
+		var zoomCenterY = this.zoomCenterY - (this.panY / this.zoom);
+
+		// Calculate where the center of the view should be
+		var centerX = Math.floor(Math.max(sourceWidth / 2,
+				Math.min(img.width - sourceWidth / 2, zoomCenterX)));
+		var centerY = Math.floor(Math.max(sourceHeight / 2,
+				Math.min(img.height - sourceHeight / 2, zoomCenterY)));
+
+
+		var sourceX = Math.max(0,
+			Math.round((img.width - sourceWidth)/2 + (centerX - img._centerX)) );
+		var sourceY = Math.max(0,
+			Math.round((img.height - sourceHeight) / 2 + (centerY - img._centerY))
+						);
+
+		var destX = Math.round(Math.max(0, this.canvas.width - destWidth)/2);
+		var destY = Math.round(Math.max(0, this.canvas.height - destHeight)/2);
+
+		var oldDestWidth = destWidth;
+		var oldSourceWidth = sourceWidth;
+
+		if(this.zoom == 1 && panDir && this.panX){
+
+			if(this.panX < 0){
+				if(panDir > 0){
+					// If the touch is moving left, and the right side of the
+					// image should be shown, then reduce the destination width
+					// by the absolute value of panX
+					destWidth -= Math.abs(this.panX);
+					destX = 0;
+				}else if(panDir < 0){
+					// If the touch is moving left, and the left side of the
+					// image should be shown, then set the displayed width
+					// to the absolute value of panX, less some pixels for
+					// a padding between images
+					destWidth = Math.max(1, Math.abs(this.panX) - 5);
+					destX = this.size.w - destWidth;
+				}
+			}else{
+				if(panDir > 0){
+					// If the touch is moving right, and the right side of the
+					// image should be shown, then set the destination width
+					// to the absolute value of the pan, less some pixels for
+					// padding
+					destWidth = Math.max(1, Math.abs(this.panX) - 5);
+					destX = 0;
+				}else if(panDir < 0){
+					// If the touch is moving right, and the left side of the
+					// image should be shown, then reduce the destination width
+					// by the widget width minus the absolute value of panX
+					destWidth -= Math.abs(this.panX);
+					destX = this.size.w - destWidth;
+				}
+			}
+
+			sourceWidth = Math.max(1,
+						Math.floor(sourceWidth * (destWidth / oldDestWidth)));
+
+			if(panDir > 0){
+				// If the right side of the image should be displayed, move
+				// the sourceX to be the width of the image minus the difference
+				// between the original sourceWidth and the new sourceWidth
+				sourceX = (sourceX + oldSourceWidth) - (sourceWidth);
+			}
+			sourceX = Math.floor(sourceX);
+		}
+
+		try{
+
+			// See https://developer.mozilla.org/en/Canvas_tutorial/Using_images
+			cxt.drawImage(
+				img,
+				Math.max(0, sourceX),
+				sourceY,
+				Math.min(oldSourceWidth, sourceWidth),
+				sourceHeight,
+				destX, 	// Xpos
+				destY, // Ypos
+				Math.min(oldDestWidth, destWidth),
+				destHeight
+			);
+		}catch(e){
+			console.log("Caught Error",e,
+
+					"type=", img._type,
+					"oldDestWidth = ", oldDestWidth,
+					"destWidth", destWidth,
+					"destX", destX
+					, "oldSourceWidth=",oldSourceWidth,
+					"sourceWidth=", sourceWidth,
+					"sourceX = " + sourceX
+			);
+		}
+	},
+
+	_setZoomAttr: function(amount){
+		this.zoom = Math.min(this.maxZoom, Math.max(1, amount));
+
+		if(this.zoom == 1
+				&& this._centerImg
+				&& this._centerImg._loaded){
+
+			if(!this.isAnimating()){
+				this.zoomCenterX = this._centerImg.width / 2;
+				this.zoomCenterY = this._centerImg.height / 2;
+			}
+			this.panX = this.panY = 0;
+		}
+
+		this.render();
+	},
+
+	_setZoomCenterXAttr: function(value){
+		if(value != this.zoomCenterX){
+			if(this._centerImg && this._centerImg._loaded){
+				value = Math.min(this._centerImg.width, value);
+			}
+			this.zoomCenterX = Math.max(0, Math.round(value));
+		}
+	},
+
+	_setZoomCenterYAttr: function(value){
+		if(value != this.zoomCenterY){
+			if(this._centerImg && this._centerImg._loaded){
+				value = Math.min(this._centerImg.height, value);
+			}
+			this.zoomCenterY = Math.max(0, Math.round(value));
+		}
+	},
+
+	_setZoomCenterAttr: function(value){
+		if(value.x != this.zoomCenterX || value.y != this.zoomCenterY){
+			this.set("zoomCenterX", value.x);
+			this.set("zoomCenterY", value.y);
+			this.render();
+		}
+	},
+
+	_setAnimatedZoomAttr: function(amount){
+		if(this._anim && this._anim.status() == "playing"){
+			return;
+		}
+
+		this._anim = new dojo.Animation({
+			curve: [this.zoom, amount],
+			onAnimate: this._updateAnimatedZoom,
+			onEnd: this._onAnimEnd
+		});
+
+		this._anim.play();
+	},
+
+	_updateAnimatedZoom: function(amount){
+		this._setZoomAttr(amount);
+	},
+
+	_setCenterUrlAttr: function(urlOrObj){
+		this._setImage("center", urlOrObj);
+	},
+	_setLeftUrlAttr: function(urlOrObj){
+		this._setImage("left", urlOrObj);
+	},
+	_setRightUrlAttr: function(urlOrObj){
+		this._setImage("right", urlOrObj);
+	},
+
+	_setImage: function(name, urlOrObj){
+		var smallUrl = null;
+
+		var largeUrl = null;
+
+		if(dojo.isString(urlOrObj)){
+			// If the argument is a string, then just load the large url
+			largeUrl = urlOrObj;
+		}else{
+			largeUrl = urlOrObj.large;
+			smallUrl = urlOrObj.small;
+		}
+
+		if(this["_" + name + "Img"] && this["_" + name + "Img"]._src == largeUrl){
+			// Identical URL, ignore it
+			return;
+		}
+
+		// Just do the large image for now
+		var largeImg = this["_" + name + "Img"] = new Image();
+		largeImg._type = name;
+		largeImg._loaded = false;
+		largeImg._src = largeUrl;
+		largeImg._conn = dojo.connect(largeImg, "onload", this.handleLoad);
+
+		if(smallUrl){
+			// If a url to a small version of the image has been provided,
+			// load that image first.
+			var smallImg = this["_" + name + "SmallImg"] = new Image();
+			smallImg._type = name;
+			smallImg._loaded = false;
+			smallImg._conn = dojo.connect(smallImg, "onload", this.handleLoad);
+			smallImg._isSmall = true;
+			smallImg._src = smallUrl;
+			smallImg.src = smallUrl;
+		}
+
+		// It's important that the large url's src is set after the small image
+		// to ensure it's loaded second.
+		largeImg.src = largeUrl;
+	},
+
+	handleLoad: function(evt){
+		// summary:
+		//		Handles the loading of an image, both the large and small
+		//		versions.  A render is triggered as a result of each image load.
+
+		var img = evt.target;
+		img._loaded = true;
+
+		dojo.disconnect(img._conn);
+
+		var type = img._type;
+
+		switch(type){
+			case "center":
+				this.zoomCenterX = img.width / 2;
+				this.zoomCenterY = img.height / 2;
+				break;
+		}
+
+		var height = img.height;
+		var width = img.width;
+
+		if(width / this.size.w < height / this.size.h){
+			// Fit the height to the height of the canvas
+			img._baseHeight = this.canvas.height;
+			img._baseWidth = width / (height / this.size.h);
+		}else{
+			// Fix the width to the width of the canvas
+			img._baseWidth = this.canvas.width;
+			img._baseHeight = height / (width / this.size.w);
+		}
+		img._centerX = width / 2;
+		img._centerY = height / 2;
+
+		this.render();
+
+		this.onLoad(img._type, img._src, img._isSmall);
+	},
+
+	onLoad: function(type, url, isSmall){
+		// summary:
+		//		Dummy function that is called whenever an image loads.
+		// type: String
+		//		The position of the image that has loaded, either
+		//		"center", "left" or "right"
+		// url: String
+		//		The src of the image
+		// isSmall: Boolean
+		//		True if it is a small version of the image that has loaded,
+		//		false otherwise.
+	}
+});
diff --git a/dojox/mobile/app/List.js b/dojox/mobile/app/List.js
new file mode 100644
index 0000000..0ee45de
--- /dev/null
+++ b/dojox/mobile/app/List.js
@@ -0,0 +1,577 @@
+dojo.provide("dojox.mobile.app.List");
+dojo.experimental("dojox.mobile.app.List");
+
+dojo.require("dojo.string");
+dojo.require("dijit._Widget");
+
+(function(){
+
+	var templateCache = {};
+
+	dojo.declare("dojox.mobile.app.List", dijit._Widget, {
+		// summary:
+		//		A templated list widget. Given a simple array of data objects
+		//		and a HTML template, it renders a list of elements, with
+		//		support for a swipe delete action.  An optional template
+		//		can be provided for when the list is empty.
+
+		// items: Array
+		//    The array of data items that will be rendered.
+		items: null,
+	
+		// itemTemplate: String
+		//		The URL to the HTML file containing the markup for each individual
+		//		data item.
+		itemTemplate: "",
+
+		// emptyTemplate: String
+		//		The URL to the HTML file containing the HTML to display if there
+		//		are no data items. This is optional.
+		emptyTemplate: "",
+
+		// labelDelete: String
+		//		The label to display for the Delete button
+		labelDelete: "Delete",
+
+		// labelCancel: String
+		//		The label to display for the Cancel button
+		labelCancel: "Cancel",
+	
+		// controller: Object
+		//		
+		controller: null,
+	
+		// autoDelete: Boolean
+		autoDelete: true,
+
+		// enableDelete: Boolean
+		enableDelete: true,
+
+		// _templateLoadCount: Number
+		//		The number of templates remaining to load before the list renders.
+		_templateLoadCount: 0,
+	
+		// _mouseDownPos: Object
+		//    The coordinates of where a mouseDown event was detected
+		_mouseDownPos: null,
+	
+		constructor: function(){
+			this._checkLoadComplete = dojo.hitch(this, this._checkLoadComplete);
+			this._replaceToken = dojo.hitch(this, this._replaceToken);
+			this._postDeleteAnim = dojo.hitch(this, this._postDeleteAnim);
+		},
+	
+		postCreate: function(){
+	
+			var _this = this;
+	
+			if(this.emptyTemplate){
+				this._templateLoadCount++;
+			}
+			if(this.itemTemplate){
+				this._templateLoadCount++;
+			}
+	
+			dojo.addClass(this.domNode, "list");
+			var msg;
+	
+			this.connect(this.domNode, "onmousedown", function(event){
+				var touch = event;
+				if(event.targetTouches && event.targetTouches.length > 0){
+					touch = event.targetTouches[0];
+				}
+
+				// Find the node that was tapped/clicked
+				var rowNode = _this._getRowNode(event.target);
+		
+				if(rowNode){
+					// Add the rows data to the event so it can be picked up
+					// by any listeners
+					_this._setDataInfo(rowNode, event);
+					
+					// Select and highlight the row
+					_this._selectRow(rowNode);
+					
+					// Record the position that was tapped
+					_this._mouseDownPos = {
+						x: touch.pageX,
+						y: touch.pageY
+					};
+					_this._dragThreshold = null;
+				}else{
+					console.log("didnt get a node");
+				}
+			});
+	
+			this.connect(this.domNode, "onmouseup", function(event){
+				// When the mouse/finger comes off the list, 
+				// call the onSelect function and deselect the row.
+				if(event.targetTouches && event.targetTouches.length > 0){
+					event = event.targetTouches[0];
+				}
+				var rowNode = _this._getRowNode(event.target);
+		
+				if(rowNode){
+		
+					_this._setDataInfo(rowNode, event);
+		
+					if(_this._selectedRow){
+						_this.onSelect(rowNode._data, rowNode._idx, rowNode);
+					}
+		
+					this._deselectRow();
+				}
+			});
+	
+			// If swipe-to-delete is enabled, listen for the mouse moving
+			if(this.enableDelete){
+				this.connect(this.domNode, "mousemove", function(event){
+					dojo.stopEvent(event);
+					if(!_this._selectedRow){
+						return;
+					}
+					var rowNode = _this._getRowNode(event.target);
+					
+					// Still check for enableDelete in case it's changed after
+					// this listener is added.
+					if(_this.enableDelete && rowNode && !_this._deleting){
+						_this.handleDrag(event);
+					}
+				});
+			}
+
+			// Put the data and index onto each onclick event.
+			this.connect(this.domNode, "onclick", function(event){
+				if(event.touches && event.touches.length > 0){
+					event = event.touches[0];
+				}
+				var rowNode = _this._getRowNode(event.target, true);
+		
+				if(rowNode){
+					_this._setDataInfo(rowNode, event);
+				}
+			});
+
+			// If the mouse or finger moves off the selected row,
+			// deselect it.
+			this.connect(this.domNode, "mouseout", function(event){
+				if(event.touches && event.touches.length > 0){
+					event = event.touches[0];
+				}
+				if(event.target == _this._selectedRow){
+					_this._deselectRow();
+				}
+			});
+	
+			// If no item template has been provided, it is an error.
+			if(!this.itemTemplate){
+				throw Error("An item template must be provided to " + this.declaredClass);
+			}
+			
+			// Load the item template
+			this._loadTemplate(this.itemTemplate, "itemTemplate", this._checkLoadComplete);
+	
+			if(this.emptyTemplate){
+				// If the optional empty template has been provided, load it.
+				this._loadTemplate(this.emptyTemplate, "emptyTemplate", this._checkLoadComplete);
+			}
+		},
+	
+		handleDrag: function(event){
+			// summary:
+			//		Handles rows being swiped for deletion.
+			var touch = event;
+			if(event.targetTouches && event.targetTouches.length > 0){
+				touch = event.targetTouches[0];
+			}
+			
+			// Get the distance that the mouse or finger has moved since
+			// beginning the swipe action.
+			var diff = touch.pageX - this._mouseDownPos.x;
+	
+			var absDiff = Math.abs(diff);
+			if(absDiff > 10 && !this._dragThreshold){
+				// Make the user drag the row 60% of the width to remove it
+				this._dragThreshold = dojo.marginBox(this._selectedRow).w * 0.6;
+				if(!this.autoDelete){
+					this.createDeleteButtons(this._selectedRow);
+				}
+			}
+	
+			this._selectedRow.style.left = (absDiff > 10 ? diff : 0) + "px";
+	
+			// If the user has dragged the row more than the threshold, slide
+			// it off the screen in preparation for deletion.
+			if(this._dragThreshold && this._dragThreshold < absDiff){
+				this.preDelete(diff);
+			}
+		},
+	
+		handleDragCancel: function(){
+			// summary:
+			//		Handle a drag action being cancelled, for whatever reason.
+			//		Reset handles, remove CSS classes etc.
+			if(this._deleting){
+				return;
+			}
+	
+			dojo.removeClass(this._selectedRow, "hold");
+			this._selectedRow.style.left = 0;
+			this._mouseDownPos = null;
+			this._dragThreshold = null;
+	
+			this._deleteBtns && dojo.style(this._deleteBtns, "display", "none");
+		},
+	
+		preDelete: function(currentLeftPos){
+			// summary:
+			//    Slides the row offscreen before it is deleted
+	
+			// TODO: do this with CSS3!
+			var self = this;
+	
+			this._deleting = true;
+	
+			dojo.animateProperty({
+				node: this._selectedRow,
+				duration: 400,
+				properties: {
+					left: {
+					end: currentLeftPos +
+						((currentLeftPos > 0 ? 1 : -1) * this._dragThreshold * 0.8)
+					}
+				},
+				onEnd: dojo.hitch(this, function(){
+					if(this.autoDelete){
+						this.deleteRow(this._selectedRow);
+					}
+				})
+			}).play();
+		},
+	
+		deleteRow: function(row){
+	
+			// First make the row invisible
+			// Put it back where it came from
+			dojo.style(row, {
+				visibility: "hidden",
+				minHeight: "0px"
+			});
+			dojo.removeClass(row, "hold");
+	
+			this._deleteAnimConn =
+				this.connect(row, "webkitAnimationEnd", this._postDeleteAnim);
+	
+			dojo.addClass(row, "collapsed");
+	
+		},
+	
+		_postDeleteAnim: function(event){
+			// summary:
+			//		Completes the deletion of a row.
+	
+			if(this._deleteAnimConn){
+				this.disconnect(this._deleteAnimConn);
+				this._deleteAnimConn = null;
+			}
+	
+			var row = this._selectedRow;
+			var sibling = row.nextSibling;
+	
+			row.parentNode.removeChild(row);
+			this.onDelete(row._data, row._idx, this.items);
+	
+			// Decrement the index of each following row
+			while(sibling){
+				if(sibling._idx){
+					sibling._idx--;
+				}
+				sibling = sibling.nextSibling;
+			}
+	
+			dojo.destroy(row);
+
+			// Fix up the 'first' and 'last' CSS classes on the rows
+			dojo.query("> *:not(.buttons)", this.domNode).forEach(this.applyClass);
+	
+			this._deleting = false;
+			this._deselectRow();
+		},
+	
+		createDeleteButtons: function(aroundNode){
+			// summary:
+			//		Creates the two buttons displayed when confirmation is
+			//		required before deletion of a row.
+			// aroundNode:
+			//		The DOM node of the row about to be deleted.
+			var mb = dojo.marginBox(aroundNode);
+			var pos = dojo._abs(aroundNode, true);
+	
+			if(!this._deleteBtns){
+			// Create the delete buttons.
+				this._deleteBtns = dojo.create("div",{
+					"class": "buttons"
+				}, this.domNode);
+		
+				this.buttons = [];
+		
+				this.buttons.push(new dojox.mobile.Button({
+					btnClass: "mblRedButton",
+					label: this.labelDelete
+				}));
+				this.buttons.push(new dojox.mobile.Button({
+					btnClass: "mblBlueButton",
+					label: this.labelCancel
+				}));
+		
+				dojo.place(this.buttons[0].domNode, this._deleteBtns);
+				dojo.place(this.buttons[1].domNode, this._deleteBtns);
+		
+				dojo.addClass(this.buttons[0].domNode, "deleteBtn");
+				dojo.addClass(this.buttons[1].domNode, "cancelBtn");
+		
+				this._handleButtonClick = dojo.hitch(this._handleButtonClick);
+					this.connect(this._deleteBtns, "onclick", 
+									this._handleButtonClick);
+			}
+			dojo.removeClass(this._deleteBtns, "fade out fast");
+			dojo.style(this._deleteBtns, {
+				display: "",
+				width: mb.w + "px",
+				height: mb.h + "px",
+				top: (aroundNode.offsetTop) + "px",
+				left: "0px"
+			});
+		},
+	
+		onDelete: function(data, index, array){
+			// summary:
+			//    Called when a row is deleted
+			// data:
+			//		The data related to the row being deleted
+			// index:
+			//		The index of the data in the total array
+			// array:
+			//		The array of data used.
+	
+			array.splice(index, 1);
+
+			// If the data is empty, rerender in case an emptyTemplate has
+			// been provided
+			if(array.length < 1){
+				this.render();
+			}
+		},
+	
+		cancelDelete: function(){
+			// summary:
+			//		Cancels the deletion of a row.
+			this._deleting = false;
+			this.handleDragCancel();
+		},
+	
+		_handleButtonClick: function(event){
+			// summary:
+			//		Handles the click of one of the deletion buttons, either to
+			//		delete the row or to cancel the deletion.
+			if(event.touches && event.touches.length > 0){
+			event = event.touches[0];
+			}
+			var node = event.target;
+			if(dojo.hasClass(node, "deleteBtn")){
+				this.deleteRow(this._selectedRow);
+			}else if(dojo.hasClass(node, "cancelBtn")){
+				this.cancelDelete();
+			}else{
+				return;
+			}
+			dojo.addClass(this._deleteBtns, "fade out");
+		},
+	
+		applyClass: function(node, idx, array){
+			// summary:
+			//		Applies the 'first' and 'last' CSS classes to the relevant
+			//		rows.
+	
+			dojo.removeClass(node, "first last");
+			if(idx == 0){
+				dojo.addClass(node, "first");
+			}
+			if(idx == array.length - 1){
+				dojo.addClass(node, "last");
+			}
+		},
+
+		_setDataInfo: function(rowNode, event){
+			// summary:
+			//    Attaches the data item and index for each row to any event
+			//    that occurs on that row.
+			event.item = rowNode._data;
+			event.index = rowNode._idx;
+		},
+	
+		onSelect: function(data, index, rowNode){
+			// summary:
+			//		Dummy function that is called when a row is tapped
+		},
+	
+		_selectRow: function(row){
+			// summary:
+			//		Selects a row, applies the relevant CSS classes.
+			if(this._deleting && this._selectedRow && row != this._selectedRow){
+				this.cancelDelete();
+			}
+	
+			if(!dojo.hasClass(row, "row")){
+				return;
+			}
+	
+			dojo.addClass(row, "hold");
+			this._selectedRow = row;
+		},
+	
+		_deselectRow: function(){
+			// summary:
+			//		Deselects a row, and cancels any drag actions that were
+			//		occurring.
+			if(!this._selectedRow || this._deleting){
+				return;
+			}
+			this.handleDragCancel();
+			dojo.removeClass(this._selectedRow, "hold");
+			this._selectedRow = null;
+		},
+	
+		_getRowNode: function(fromNode, ignoreNoClick){
+			// summary:
+			//		Gets the DOM node of the row that is equal to or the parent
+			//		of the node passed to this function.
+			while(fromNode && !fromNode._data && fromNode != this.domNode){
+				if(!ignoreNoClick && dojo.hasClass(fromNode, "noclick")){
+					return null;
+				}
+				fromNode = fromNode.parentNode;
+			}
+			return fromNode;
+		},
+	
+		render: function(){
+			// summary:
+			//		Renders the list.
+
+			// Delete all existing nodes, except the deletion buttons.
+			dojo.query("> *:not(.buttons)", this.domNode).forEach(dojo.destroy);
+	
+			var rows = [];
+			var row, i;
+	
+			dojo.addClass(this.domNode, "list");
+			
+			for(i = 0; i < this.items.length; i++){
+				// Create a document fragment containing the templated row
+				row = dojo._toDom(dojo.string.substitute(
+					this.itemTemplate, this.items[i], this._replaceToken, this));
+	
+				rows.push(row);
+			}
+			for(i = 0; i < this.items.length; i++){
+				rows[i]._data = this.items[i];
+				rows[i]._idx = i;
+				this.domNode.appendChild(rows[i]);
+			}
+	
+			// If there is no data, and an empty template has been provided,
+			// render it.
+			if(this.items.length < 1 && this.emptyTemplate){
+				dojo.place(dojo._toDom(this.emptyTemplate), this.domNode, "first");
+			}
+	
+			if(dojo.hasClass(this.domNode.parentNode, "mblRoundRect")){
+				dojo.addClass(this.domNode.parentNode, "mblRoundRectList")
+			}
+	
+			var divs = dojo.query("> div:not(.buttons)", this.domNode);
+			divs.addClass("row");
+			if(divs.length > 0){
+				dojo.addClass(divs[0], "first");
+				dojo.addClass(divs[divs.length - 1], "last");
+			}
+		},
+	
+		_replaceToken: function(value, key){
+				if(key.charAt(0) == '!'){ value = dojo.getObject(key.substr(1), false, _this); }
+				if(typeof value == "undefined"){ return ""; } // 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,"""); //TODO: add &amp? use encodeXML method?
+	
+		},
+	
+		_checkLoadComplete: function(){
+			// summary:
+			//		Checks if all templates have loaded
+			this._templateLoadCount--;
+	
+			if(this._templateLoadCount < 1 && this.get("items")){
+				this.render();
+			}
+		},
+	
+		_loadTemplate: function(url, thisAttr, callback){
+			// summary:
+			//		Loads a template
+			if(!url){
+				callback();
+				return;
+			}
+	
+			if(templateCache[url]){
+				this.set(thisAttr, templateCache[url]);
+				callback();
+			}else{
+				var _this = this;
+		
+				dojo.xhrGet({
+					url: url,
+					sync: false,
+					handleAs: "text",
+					load: function(text){
+						templateCache[url] = dojo.trim(text);
+						_this.set(thisAttr, templateCache[url]);
+						callback();
+					}
+				});
+			}
+		},
+	
+	
+		_setItemsAttr: function(items){
+			// summary:
+			//    Sets the data items, and causes a rerender of the list
+	
+			this.items = items || [];
+	
+			if(this._templateLoadCount < 1 && items){
+				this.render();
+			}
+		},
+	
+		destroy: function(){
+			if(this.buttons){
+				dojo.forEach(this.buttons, function(button){
+					button.destroy();
+				});
+				this.buttons = null;
+			}
+	
+			this.inherited(arguments);
+		}
+
+	});
+
+})();
\ No newline at end of file
diff --git a/dojox/mobile/app/ListSelector.js b/dojox/mobile/app/ListSelector.js
new file mode 100644
index 0000000..9f55455
--- /dev/null
+++ b/dojox/mobile/app/ListSelector.js
@@ -0,0 +1,218 @@
+dojo.provide("dojox.mobile.app.ListSelector");
+dojo.experimental("dojox.mobile.app.ListSelector");
+
+dojo.require("dojox.mobile.app._Widget");
+dojo.require("dojo.fx");
+
+dojo.declare("dojox.mobile.app.ListSelector", dojox.mobile.app._Widget, {
+
+	// data: Array
+	//    The array of items to display.  Each element in the array
+	//    should have both a label and value attribute, e.g.
+	//    [{label: "Open", value: 1} , {label: "Delete", value: 2}]
+	data: null,
+
+	// controller: Object
+	//    The current SceneController widget.
+	controller: null,
+
+	// onChoose: Function
+	//    The callback function for when an item is selected
+	onChoose: null,
+
+	destroyOnHide: false,
+
+	_setDataAttr: function(data){
+		this.data = data;
+	
+		if(this.data){
+			this.render();
+		}
+	},
+
+	postCreate: function(){
+		dojo.addClass(this.domNode, "listSelector");
+	
+		var _this = this;
+	
+		this.connect(this.domNode, "onclick", function(event){
+			if(!dojo.hasClass(event.target, "listSelectorRow")){
+				return;
+			}
+	
+			if(_this.onChoose){
+				_this.onChoose(_this.data[event.target._idx].value);
+			}
+			_this.hide();
+		});
+
+		this.connect(this.domNode, "onmousedown", function(event){
+			if(!dojo.hasClass(event.target, "listSelectorRow")){
+				return;
+			}
+			dojo.addClass(event.target, "listSelectorRow-selected");
+		});
+
+		this.connect(this.domNode, "onmouseup", function(event){
+			if(!dojo.hasClass(event.target, "listSelectorRow")){
+				return;
+			}
+			dojo.removeClass(event.target, "listSelectorRow-selected");
+		});
+
+		this.connect(this.domNode, "onmouseout", function(event){
+			if(!dojo.hasClass(event.target, "listSelectorRow")){
+				return;
+			}
+			dojo.removeClass(event.target, "listSelectorRow-selected");
+		});
+	
+		var viewportSize = this.controller.getWindowSize();
+	
+		this.mask = dojo.create("div", {"class": "dialogUnderlayWrapper",
+			innerHTML: "<div class=\"dialogUnderlay\"></div>"
+		}, this.controller.assistant.domNode);
+	
+		this.connect(this.mask, "onclick", function(){
+			_this.onChoose && _this.onChoose();
+			_this.hide();
+		});
+	},
+
+	show: function(fromNode){
+
+		// Using dojo.fx here. Must figure out how to do this with CSS animations!!
+		var startPos;
+	
+		var windowSize = this.controller.getWindowSize();
+		var fromNodePos;
+		if(fromNode){
+			fromNodePos = dojo._abs(fromNode);
+			startPos = fromNodePos;
+		}else{
+			startPos.x = windowSize.w / 2;
+			startPos.y = 200;
+		}
+		console.log("startPos = ", startPos);
+	
+		dojo.style(this.domNode, {
+			opacity: 0,
+			display: "",
+			width: Math.floor(windowSize.w * 0.8) + "px"
+		});
+	
+		var maxWidth = 0;
+		dojo.query(">", this.domNode).forEach(function(node){
+			dojo.style(node, {
+				"float": "left"
+			});
+			maxWidth = Math.max(maxWidth, dojo.marginBox(node).w);
+			dojo.style(node, {
+				"float": "none"
+			});
+		});
+		maxWidth = Math.min(maxWidth, Math.round(windowSize.w * 0.8))
+					+ dojo.style(this.domNode, "paddingLeft")
+					+ dojo.style(this.domNode, "paddingRight")
+					+ 1;
+	
+		dojo.style(this.domNode, "width", maxWidth + "px");
+		var targetHeight = dojo.marginBox(this.domNode).h;
+	
+		var _this = this;
+	
+	
+		var targetY = fromNodePos ?
+				Math.max(30, fromNodePos.y - targetHeight - 10) :
+				this.getScroll().y + 30;
+	
+		console.log("fromNodePos = ", fromNodePos, " targetHeight = ", targetHeight,
+				" targetY = " + targetY, " startPos ", startPos);
+	
+	
+		var anim1 = dojo.animateProperty({
+			node: this.domNode,
+			duration: 400,
+			properties: {
+				width: {start: 1, end: maxWidth},
+				height: {start: 1, end: targetHeight},
+				top: {start: startPos.y, end: targetY},
+				left: {start: startPos.x, end: (windowSize.w/2 - maxWidth/2)},
+				opacity: {start: 0, end: 1},
+				fontSize: {start: 1}
+			},
+			onEnd: function(){
+				dojo.style(_this.domNode, "width", "inherit");
+			}
+		});
+		var anim2 = dojo.fadeIn({
+			node: this.mask,
+			duration: 400
+		});
+		dojo.fx.combine([anim1, anim2]).play();
+
+	},
+
+	hide: function(){
+		// Using dojo.fx here. Must figure out how to do this with CSS animations!!
+	
+		var _this = this;
+	
+		var anim1 = dojo.animateProperty({
+			node: this.domNode,
+			duration: 500,
+			properties: {
+				width: {end: 1},
+				height: {end: 1},
+				opacity: {end: 0},
+				fontSize: {end: 1}
+			},
+			onEnd: function(){
+				if(_this.get("destroyOnHide")){
+					_this.destroy();
+				}
+			}
+		});
+	
+		var anim2 = dojo.fadeOut({
+			node: this.mask,
+			duration: 400
+		});
+		dojo.fx.combine([anim1, anim2]).play();
+	},
+
+	render: function(){
+		// summary:
+		//    Renders
+	
+		dojo.empty(this.domNode);
+		dojo.style(this.domNode, "opacity", 0);
+	
+		var row;
+	
+		for(var i = 0; i < this.data.length; i++){
+			// Create each row and add any custom classes. Also set the _idx property.
+			row = dojo.create("div", {
+				"class": "listSelectorRow " + (this.data[i].className || ""),
+				innerHTML: this.data[i].label
+			}, this.domNode);
+	
+			row._idx = i;
+	
+			if(i == 0){
+				dojo.addClass(row, "first");
+			}
+			if(i == this.data.length - 1){
+				dojo.addClass(row, "last");
+			}
+	
+		}
+	},
+
+
+	destroy: function(){
+		this.inherited(arguments);
+		dojo.destroy(this.mask);
+	}
+
+});
diff --git a/dojox/mobile/app/SceneAssistant.js b/dojox/mobile/app/SceneAssistant.js
new file mode 100644
index 0000000..22a6e11
--- /dev/null
+++ b/dojox/mobile/app/SceneAssistant.js
@@ -0,0 +1,56 @@
+dojo.provide("dojox.mobile.app.SceneAssistant");
+dojo.experimental("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("dojox.mobile.app.SceneAssistant", null, {
+	// summary:
+	//    The base class for all scene assistants.
+
+	constructor: function(){
+
+	},
+
+	setup: function(){
+		// summary:
+		//    Called to set up the widget.  The UI is not visible at this time
+
+	},
+
+	activate: function(params){
+		// summary:
+		//    Called each time the scene becomes visible.  This can be as a result
+		//    of a new scene being created, or a subsequent scene being destroyed
+		//    and control transferring back to this scene assistant.
+		// params:
+		//    Optional paramters, only passed when a subsequent scene pops itself
+		//    off the stack and passes back data.
+	},
+
+	deactivate: function(){
+		// summary:
+		//    Called each time the scene becomes invisible.  This can be as a result
+		//    of it being popped off the stack and destroyed,
+		//    or another scene being created and pushed on top of it on the stack
+	},
+
+	destroy: function(){
+	
+		var children =
+			dojo.query("> [widgetId]", this.containerNode).map(dijit.byNode);
+		dojo.forEach(children, function(child){ child.destroyRecursive(); });
+	
+		this.disconnect();
+	},
+
+	connect: function(obj, method, callback){
+		if(!this._connects){
+			this._connects = [];
+		}
+		this._connects.push(dojo.connect(obj, method, callback));
+	},
+
+	disconnect: function(){
+		dojo.forEach(this._connects, dojo.disconnect);
+		this._connects = [];
+	}
+});
+
diff --git a/dojox/mobile/app/SceneController.js b/dojox/mobile/app/SceneController.js
new file mode 100644
index 0000000..35a6477
--- /dev/null
+++ b/dojox/mobile/app/SceneController.js
@@ -0,0 +1,157 @@
+dojo.provide("dojox.mobile.app.SceneController");
+dojo.experimental("dojox.mobile.app.SceneController");
+dojo.require("dojox.mobile._base");
+
+(function(){
+
+	var app = dojox.mobile.app;
+
+	var templates = {};
+
+	dojo.declare("dojox.mobile.app.SceneController", dojox.mobile.View, {
+
+		stageController: null,
+	
+		init: function(sceneName, params){
+			// summary:
+			//    Initializes the scene by loading the HTML template and code, if it has
+			//    not already been loaded
+	
+			this.sceneName = sceneName;
+			this.params = params;
+			var templateUrl = app.resolveTemplate(sceneName);
+	
+			this._deferredInit = new dojo.Deferred();
+	
+			dojo.xhrGet({
+				url: templateUrl,
+				handleAs: "text"
+			}).addCallback(dojo.hitch(this, this._setContents));
+	
+			return this._deferredInit;
+		},
+	
+		_setContents: function(templateHtml){
+			// summary:
+			//    Sets the content of the View, and invokes either the loading or
+			//    initialization of the scene assistant.
+			templates[this.sceneName] = templateHtml;
+	
+			this.domNode.innerHTML = "<div>" + templateHtml + "</div>";
+	
+			var sceneAssistantName = "";
+										
+			var nameParts = this.sceneName.split("-");
+			
+			for(var i = 0; i < nameParts.length; i++){
+				sceneAssistantName += nameParts[i].substring(0, 1).toUpperCase()
+							+ nameParts[i].substring(1);
+			}
+			sceneAssistantName += "Assistant";
+			this.sceneAssistantName = sceneAssistantName;
+			
+			var _this = this;
+			
+			dojox.mobile.app.loadResourcesForScene(this.sceneName, function(){
+				
+				console.log("All resources for ",_this.sceneName," loaded");
+				
+				var assistant;
+				if(typeof(window[sceneAssistantName]) != "undefined"){
+					_this._initAssistant();
+				}else{
+					var assistantUrl = app.resolveAssistant(_this.sceneName);
+			
+					dojo.xhrGet({
+						url: assistantUrl,
+						handleAs: "text"
+					}).addCallback(function(text){
+						dojo.eval(text);
+			
+						_this._initAssistant();
+					});
+				}
+			});
+			
+		},
+	
+		_initAssistant: function(){
+			// summary:
+			//    Initializes the scene assistant. At this point, the View is
+			//    populated with the HTML template, and the scene assistant type
+			//    is declared.
+	
+			console.log("Instantiating the scene assistant " + this.sceneAssistantName);
+	
+			var cls = dojo.getObject(this.sceneAssistantName);
+			
+			if(!cls){
+				throw Error("Unable to resolve scene assistant "
+							+ this.sceneAssistantName);
+			}
+			
+			this.assistant = new cls(this.params);
+	
+			this.assistant.controller = this;
+			this.assistant.domNode = this.domNode.firstChild;
+	
+			this.assistant.setup();
+	
+			this._deferredInit.callback();
+		},
+	
+		query: function(selector, node){
+			// summary:
+			//    Queries for DOM nodes within either the node passed in as an argument
+			//    or within this view.
+	
+			return dojo.query(selector, node || this.domNode)
+		},
+	
+		parse: function(node){
+			var widgets = this._widgets =
+				dojox.mobile.parser.parse(node || this.domNode, {
+					controller: this
+				});
+	
+			// Tell all widgets what their controller is.
+			for(var i = 0; i < widgets.length; i++){
+				widgets[i].attr("controller", this);
+			}
+		},
+	
+		getWindowSize: function(){
+			// TODO, this needs cross browser testing
+	
+			return {
+				w: window.innerWidth,
+				h: window.innerHeight
+			}
+		},
+	
+		showAlertDialog: function(props){
+	
+			var size = dojo.marginBox(this.assistant.domNode);
+			var dialog = new dojox.mobile.app.AlertDialog(
+					dojo.mixin(props, {controller: this}));
+			this.assistant.domNode.appendChild(dialog.domNode);
+	
+			console.log("Appended " , dialog.domNode, " to ", this.assistant.domNode);
+			dialog.show();
+		},
+	
+		popupSubMenu: function(info){
+			var widget = new dojox.mobile.app.ListSelector({
+				controller: this,
+				destroyOnHide: true,
+				onChoose: info.onChoose
+			});
+	
+			this.assistant.domNode.appendChild(widget.domNode);
+	
+			widget.set("data", info.choices);
+			widget.show(info.fromNode);
+		}
+	});
+
+})();
\ No newline at end of file
diff --git a/dojox/mobile/app/StageController.js b/dojox/mobile/app/StageController.js
new file mode 100644
index 0000000..749a701
--- /dev/null
+++ b/dojox/mobile/app/StageController.js
@@ -0,0 +1,137 @@
+dojo.provide("dojox.mobile.app.StageController");
+dojo.experimental("dojox.mobile.app.StageController");
+
+dojo.require("dojox.mobile.app.SceneController");
+
+dojo.declare("dojox.mobile.app.StageController", null,{
+
+	// scenes: Array
+	//    The list of scenes currently in existance in the app.
+	scenes: null,
+
+	effect: "fade",
+
+	constructor: function(node){
+		this.domNode = node;
+		this.scenes = [];
+	
+		if(dojo.config.mobileAnim){
+			this.effect = dojo.config.mobileAnim;
+		}
+	},
+
+	getActiveSceneController: function(){
+		return this.scenes[this.scenes.length - 1];
+	},
+
+	pushScene: function(sceneName, params){
+		console.log("pushScene", sceneName);
+		if(this._opInProgress){
+			return;
+		}
+		this._opInProgress = true;
+	
+		// Push new scenes as the first element on the page.
+		var node = dojo.create("div", {
+			"class": "scene-wrapper",
+			style: {
+				visibility: "hidden"
+			}
+		}, this.domNode);
+	
+		var controller = new dojox.mobile.app.SceneController({}, node);
+	
+		if(this.scenes.length > 0){
+			this.scenes[0].assistant.deactivate();
+		}
+
+		this.scenes.push(controller);
+	
+		var _this = this;
+	
+		dojo.forEach(this.scenes, this.setZIndex);
+	
+		controller.stageController = this;
+	
+		controller.init(sceneName, params).addCallback(function(){
+	
+			console.log("In callback after controller.init");
+	
+			if(_this.scenes.length == 1){
+				controller.domNode.style.visibility = "visible";
+				_this.scenes[_this.scenes.length - 1].assistant.activate(params);
+				_this._opInProgress = false;
+			}else{
+				_this.scenes[_this.scenes.length - 2]
+					.performTransition(
+						_this.scenes[_this.scenes.length - 1].domNode, 
+						1, 
+						_this.effect, 
+						null, 
+						function(){
+							// When the scene is ready, activate it.
+							_this.scenes[_this.scenes.length - 1].assistant.activate(params);
+							_this._opInProgress = false;
+						});
+			}
+			console.log("at end of callback after controller.init");
+			
+		});
+	},
+
+	setZIndex: function(controller, idx){
+		dojo.style(controller.domNode, "zIndex", idx + 1);
+	},
+
+	popScene: function(data){
+		//	performTransition: function(/*String*/moveTo, /*Number*/dir, /*String*/transition,
+			//						/*Object|null*/context, /*String|Function*/method /*optional args*/){
+		if(this._opInProgress){
+			return;
+		}
+	
+		var _this = this;
+		if(this.scenes.length > 1){
+	
+			this._opInProgress = true;
+			this.scenes[_this.scenes.length - 2].assistant.activate(data);
+			this.scenes[_this.scenes.length - 1]
+				.performTransition(
+					_this.scenes[this.scenes.length - 2].domNode, 
+					-1, 
+					this.effect, 
+					null,
+					function(){
+						// When the scene is no longer visible, destroy it
+						_this._destroyScene(_this.scenes[_this.scenes.length - 1]);
+						_this.scenes.splice(_this.scenes.length - 1, 1);
+						_this._opInProgress = false;
+					});
+		}else{
+			console.log("cannot pop the scene if there is just one");
+		}
+	},
+
+	popScenesTo: function(sceneName, data){
+		if(this._opInProgress){
+			return;
+		}
+	
+		while(this.scenes.length > 2 &&
+				this.scenes[this.scenes.length - 2].sceneName != sceneName){
+			this._destroyScene(this.scenes[this.scenes.length - 2]);
+			this.scenes.splice(this.scenes.length - 2, 1);
+		}
+	
+		this.popScene(data);
+	},
+	
+	_destroyScene: function(scene){
+		scene.assistant.deactivate();
+		scene.assistant.destroy();
+		scene.destroyRecursive();
+	}
+
+
+});
+
diff --git a/dojox/mobile/app/TextBox.js b/dojox/mobile/app/TextBox.js
new file mode 100644
index 0000000..9c208cd
--- /dev/null
+++ b/dojox/mobile/app/TextBox.js
@@ -0,0 +1,321 @@
+dojo.provide("dojox.mobile.app.TextBox");
+dojo.experimental("dojox.mobile.app.TextBox");
+
+dojo.require("dojox.mobile.app._Widget");
+dojo.require("dojox.mobile.app._FormWidget");
+
+dojo.declare(
+	"dojox.mobile.app.TextBox", 
+	dojox.mobile.app._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: "",
+
+		//	selectOnClick: [const] Boolean
+		//		If true, all text will be selected when focused with mouse
+		selectOnClick: false,
+
+		//	placeHolder: String
+		//		Defines a hint to help users fill out the input field (as defined in HTML 5).
+		//		This should only contain plain text (no html markup).
+		placeHolder: "",
+		
+		baseClass: "mblTextBox",
+
+		attributeMap: dojo.delegate(dojox.mobile.app._FormValueWidget.prototype.attributeMap, {
+			maxLength: "focusNode"
+		}),
+		
+		buildRendering: function(){
+			var node = this.srcNodeRef;
+	
+			// If an input is used as the source node, wrap it in a div
+			if(!node || node.tagName != "INPUT"){
+				node = dojo.create("input", {});
+			}
+			
+			dojo.attr(node, {
+				type: "text",
+				value: dojo.attr(this.srcNodeRef, "value") || "",
+				placeholder: this.placeHolder || null
+			});
+			
+			this.domNode = this.textbox = this.focusNode = node;
+		},
+
+		_setPlaceHolderAttr: function(v){
+			this.placeHolder = v;
+			if(this.textbox){
+				dojo.attr(this.textbox, "placeholder", v);
+			}
+		},
+		
+
+		_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.get('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.  Otherwise '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: "",
+
+		_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);
+		},
+
+		_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.get('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.get('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
+
+			console.log("postCreate of textinput");
+
+			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);
+			}
+		},
+
+		_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.get('value'), true);
+		},
+
+		_onBlur: function(e){
+			if(this.disabled){ return; }
+			this._setBlurValue();
+			this.inherited(arguments);
+
+			if(this._selectOnClickHandle){
+				this.disconnect(this._selectOnClickHandle);
+			}
+			if(this.selectOnClick && dojo.isMoz){
+				this.textbox.selectionStart = this.textbox.selectionEnd = undefined; // clear selection so that the next mouse click doesn't reselect
+			}
+			
+		},
+
+		_onFocus: function(/*String*/ by){
+			if(this.disabled || this.readOnly){ return; }
+
+			// Select all text on focus via click if nothing already selected.
+			// Since mouse-up will clear the selection need to defer selection until after mouse-up.
+			// Don't do anything on focus by tabbing into the widget since there's no associated mouse-up event.
+			if(this.selectOnClick && by == "mouse"){
+				this._selectOnClickHandle = this.connect(this.domNode, "onmouseup", function(){
+					// Only select all text on first click; otherwise users would have no way to clear
+					// the selection.
+					this.disconnect(this._selectOnClickHandle);
+
+					// Check if the user selected some text manually (mouse-down, mouse-move, mouse-up)
+					// and if not, then select all the text
+					var textIsNotSelected;
+					textIsNotSelected = this.textbox.selectionStart == this.textbox.selectionEnd;
+					if(textIsNotSelected){
+						this.selectInputText(this.textbox);
+					}
+				});
+			}
+			
+			this._refreshState();
+			this.inherited(arguments);
+		},
+
+		reset: function(){
+			// Overrides dijit._FormWidget.reset().
+			// Additionally resets the displayed textbox value to ''
+			this.textbox.value = '';
+			this.inherited(arguments);
+		}
+	}
+);
\ No newline at end of file
diff --git a/dojox/mobile/app/_FormWidget.js b/dojox/mobile/app/_FormWidget.js
new file mode 100644
index 0000000..777112c
--- /dev/null
+++ b/dojox/mobile/app/_FormWidget.js
@@ -0,0 +1,294 @@
+dojo.provide("dojox.mobile.app._FormWidget");
+dojo.experimental("dojox.mobile.app._FormWidget");
+
+dojo.require("dojo.window");
+
+dojo.require("dijit._Widget");
+
+dojo.declare("dojox.mobile.app._FormWidget", dijit._Widget, {
+	// 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 `dojox.mobile.app.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.
+
+	// 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",
+
+	// disabled: Boolean
+	//		Should this widget respond to user input?
+	//		In markup, this is specified as "disabled='disabled'", or just "disabled".
+	disabled: 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: false,
+
+	// 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",
+		id: "focusNode",
+		alt: "focusNode",
+		title: "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
+		// Regarding escaping, see heading "Attribute values" in
+		// http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
+		this.nameAttrSetting = this.name ? ('name="' + this.name.replace(/'/g, """) + '"') : '';
+		this.inherited(arguments);
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+		this.connect(this.domNode, "onmousedown", "_onMouseDown");
+	},
+
+	_setDisabledAttr: function(/*Boolean*/ value){
+		this.disabled = value;
+		dojo.attr(this.focusNode, 'disabled', value);
+		if(this.valueNode){
+			dojo.attr(this.valueNode, 'disabled', value);
+		}
+
+		if(value){
+			// reset these, because after the domNode is disabled, we can no longer receive
+			// mouse related events, see #4200
+			this._hovering = false;
+			this._active = false;
+		}
+	},
+
+	_onFocus: function(e){
+		if(this.scrollOnFocus){
+			dojo.window.scrollIntoView(this.domNode);
+		}
+		this.inherited(arguments);
+	},
+
+	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
+		this.focusNode.focus();
+	},
+
+	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){
+				if(this._onChangeHandle){
+					clearTimeout(this._onChangeHandle);
+				}
+				// setTimout allows hidden value processing to run and
+				// also the onChange handler can safely adjust focus, etc
+				this._onChangeHandle = setTimeout(dojo.hitch(this,
+					function(){
+						this._onChangeHandle = null;
+						this.onChange(newValue);
+					}), 0); // try to collapse multiple onChange's fired faster than can be processed
+			}
+		}
+	},
+
+	create: function(){
+		// Overrides _Widget.create()
+		this.inherited(arguments);
+		this._onChangeActive = true;
+	},
+
+	destroy: function(){
+		if(this._onChangeHandle){ // destroy called before last onChange has fired
+			clearTimeout(this._onChangeHandle);
+			this.onChange(this._lastValueReported);
+		}
+		this.inherited(arguments);
+	},
+
+	_onMouseDown: function(e){
+		// If user clicks on the button, even if the mouse is released outside of it,
+		// this button should get focus (to mimics native browser buttons).
+		// This is also needed on chrome because otherwise buttons won't get focus at all,
+		// which leads to bizarre focus restore on Dialog close etc.
+		if(this.isFocusable()){
+			// Set a global event to handle mouseup, so it fires properly
+			// even if the cursor leaves this.domNode before the mouse up event.
+			var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
+				if(this.isFocusable()){
+					this.focus();
+				}
+				this.disconnect(mouseUpConnector);
+			});
+		}
+	},
+
+	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; }
+		dijit.focus(element);
+
+		if(_window["getSelection"] && element.setSelectionRange){
+			element.setSelectionRange(start, stop);
+		}
+	}
+});
+
+dojo.declare("dojox.mobile.app._FormValueWidget", dojox.mobile.app._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)
+
+	// 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,
+
+	attributeMap: dojo.delegate(dojox.mobile.app._FormWidget.prototype.attributeMap, {
+		value: "",
+		readOnly: "focusNode"
+	}),
+
+	_setReadOnlyAttr: function(/*Boolean*/ value){
+		this.readOnly = value;
+		dojo.attr(this.focusNode, 'readOnly', value);
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+
+		// Update our reset value if it hasn't yet been set (because this.set()
+		// 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(){
+		// 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);
+	}
+});
diff --git a/dojox/mobile/app/_Widget.js b/dojox/mobile/app/_Widget.js
new file mode 100644
index 0000000..c7ebf41
--- /dev/null
+++ b/dojox/mobile/app/_Widget.js
@@ -0,0 +1,30 @@
+dojo.provide("dojox.mobile.app._Widget");
+dojo.experimental("dojox.mobile.app._Widget");
+
+dojo.require("dijit._Widget");
+
+dojo.declare("dojox.mobile.app._Widget", dijit._Widget, {
+	// summary:
+	//		The base mobile app widget.
+
+	getScroll: function(){
+		// summary:
+		//		Returns the scroll position.
+		return {
+			x: window.scrollX,
+			y: window.scrollY
+		};
+	},
+
+	connect: function(target, event, fn){
+		if(event.toLowerCase() == "dblclick"
+			|| event.toLowerCase() == "ondblclick"){
+
+			if(window["Mojo"]){
+				// Handle webOS tap event
+				return this.connect(target, Mojo.Event.tap, fn);
+			}
+		}
+		return this.inherited(arguments);
+	}
+});
\ No newline at end of file
diff --git a/dojox/mobile/app/_base.js b/dojox/mobile/app/_base.js
new file mode 100755
index 0000000..6844b60
--- /dev/null
+++ b/dojox/mobile/app/_base.js
@@ -0,0 +1,226 @@
+dojo.provide("dojox.mobile.app._base");
+dojo.experimental("dojox.mobile.app._base");
+
+dojo.require("dijit._base");
+dojo.require("dijit._Widget");
+dojo.require("dojox.mobile");
+dojo.require("dojox.mobile.parser");
+
+dojo.require("dojox.mobile.app._event");
+dojo.require("dojox.mobile.app._Widget");
+dojo.require("dojox.mobile.app.StageController");
+dojo.require("dojox.mobile.app.SceneController");
+dojo.require("dojox.mobile.app.SceneAssistant");
+dojo.require("dojox.mobile.app.AlertDialog");
+dojo.require("dojox.mobile.app.List");
+dojo.require("dojox.mobile.app.ListSelector");
+dojo.require("dojox.mobile.app.TextBox");
+dojo.require("dojox.mobile.app.ImageView");
+dojo.require("dojox.mobile.app.ImageThumbView");
+
+(function(){
+
+	var stageController;
+	var appInfo;
+
+	var jsDependencies = [
+		"dojox.mobile",
+		"dojox.mobile.parser"
+	];
+	
+	var loadedResources = {};
+	var loadingDependencies;
+
+	var rootNode;
+	
+	var sceneResources = [];
+
+	// Load the required resources asynchronously, since not all mobile OSes
+	// support dojo.require and sync XHR
+	function loadResources(resources, callback){
+		// summary:
+		//		Loads one or more JavaScript files asynchronously. When complete,
+		//		the first scene is pushed onto the stack.
+		// resources:
+		//		An array of module names, e.g. 'dojox.mobile.AlertDialog'
+		
+		var resource;
+		var url;
+		
+		do {
+			resource = resources.pop();
+			if (resource.source) {
+				url = resource.source;
+			}else if (resource.module) {
+				url = dojo.baseUrl + dojo._getModuleSymbols(resource.module).join("/") + '.js';
+			}else {
+				alert("Error: invalid JavaScript resource " + dojo.toJson(resource));
+				return;
+			}
+		}while (resources.length > 0 && loadedResources[url]);
+		
+		if(resources.length < 1 && loadedResources[url]){
+			console.log("All resources already loaded");
+			// All resources have already been loaded
+			callback();
+			return;
+		}
+		
+		console.log("loading url " + url);
+	
+		dojo.xhrGet({
+			url: url,
+			sync: false
+		}).addCallbacks(function(text){
+			dojo["eval"](text);
+	
+			if(resources.length > 0){
+				loadResources(resources, callback);
+			}else{
+				callback();
+			}
+		},
+		function(){
+			alert("Failed to load resource " + url);
+		});
+	}
+	
+	var pushFirstScene = function(){
+		// summary:
+		//		Pushes the first scene onto the stack.
+
+		stageController = new dojox.mobile.app.StageController(rootNode);
+		var defaultInfo = {
+			id: "com.test.app",
+			version: "1.0.0",
+			initialScene: "main"
+		};
+
+		// If the application info has been defined, as it should be,
+		// use it.
+		if(window["appInfo"]){
+			dojo.mixin(defaultInfo, window["appInfo"]);
+		}
+		appInfo = dojox.mobile.app.info = defaultInfo;
+
+		// Set the document title from the app info title if it exists
+		if(appInfo.title){
+			var titleNode = dojo.query("head title")[0] ||
+							dojo.create("title", {},dojo.query("head")[0]);
+			document.title = appInfo.title;
+		}
+
+		stageController.pushScene(appInfo.initialScene);
+	}
+
+	dojo.mixin(dojox.mobile.app, {
+		init: function(node){
+			// summary:
+			//    Initializes the mobile app. Creates the
+	
+			rootNode = node || dojo.body();
+	
+//			loadingDependencies = dojo.clone(jsDependencies);
+//			loadResources(loadingDependencies, function(){dojox.mobile.app._pushFirstScene()});
+	
+			dojo.subscribe("/dojox/mobile/app/goback", function(){
+				stageController.popScene();
+			});
+	
+			dojo.subscribe("/dojox/mobile/app/alert", function(params){
+				dojox.mobile.app.getActiveSceneController().showAlertDialog(params);
+			});
+			
+			// Get the list of files to load per scene/view
+			dojo.xhrGet({
+				url: "view-resources.json",
+				load: function(data){
+					var resources = [];
+					
+					if(data){
+						// Should be an array
+						sceneResources = data = dojo.fromJson(data);
+						
+						console.log("Got scene resources", sceneResources);
+						
+						// Get the list of files to load that have no scene
+						// specified, and therefore should be loaded on
+						// startup
+						for(var i = 0; i < data.length; i++){
+							if(!data[i].scene){
+								resources.push(data[i]);
+							}
+						}
+					}
+					if(resources.length > 0){
+						console.log("Loading initial resources");
+						loadResources(resources, pushFirstScene);
+					}else{
+						console.log("No initial resources");
+						pushFirstScene();
+					}
+				},
+				error: pushFirstScene
+			});
+//			pushFirstScene();
+		},
+		
+		getActiveSceneController: function(){
+			// summary:
+			//		Gets the controller for the active scene.
+
+			return stageController.getActiveSceneController();
+		},
+	
+		getStageController: function(){
+			// summary:
+			//		Gets the stage controller.
+			return stageController;
+		},
+		
+		loadResources: function(resources, callback){
+			loadResources(resources, callback);
+		},
+		
+		loadResourcesForScene: function(sceneName, callback){
+			var resources = [];
+			
+			// Get the list of files to load that have no scene
+			// specified, and therefore should be loaded on
+			// startup
+			for(var i = 0; i < sceneResources.length; i++){
+				if(sceneResources[i].scene == sceneName){
+					resources.push(sceneResources[i]);
+				}
+			}
+			
+			if(resources.length > 0){
+				console.log("Loading " + resources.length + " resources for" +
+								sceneName);
+				loadResources(resources, callback);
+			}else{
+				callback();
+			}
+		},
+	
+		resolveTemplate: function(sceneName){
+			// summary:
+			//		Given the name of a scene, returns the path to it's template
+			//		file.  For example, for a scene named 'main', the file
+			//		returned is 'app/views/main/main-scene.html'
+			//		This function can be overridden if it is desired to have
+			//		a different name to file mapping.
+			return "app/views/" + sceneName + "/" + sceneName + "-scene.html";
+		},
+	
+		resolveAssistant: function(sceneName){
+			// summary:
+			//		Given the name of a scene, returns the path to it's assistant
+			//		file.  For example, for a scene named 'main', the file
+			//		returned is 'app/assistants/main-assistant.js'
+			//		This function can be overridden if it is desired to have
+			//		a different name to file mapping.
+			return "app/assistants/" + sceneName + "-assistant.js";
+		}
+	});
+})();
\ No newline at end of file
diff --git a/dojox/mobile/app/_event.js b/dojox/mobile/app/_event.js
new file mode 100644
index 0000000..5eedb2c
--- /dev/null
+++ b/dojox/mobile/app/_event.js
@@ -0,0 +1,119 @@
+dojo.provide("dojox.mobile.app._event");
+dojo.experimental("dojox.mobile.app._event.js");
+
+dojo.mixin(dojox.mobile.app, {
+	eventMap: {},
+
+	connectFlick: function(target, context, method){
+		// summary:
+		//		Listens for a flick event on a DOM node.  If the mouse/touch
+		//		moves more than 15 pixels in any given direction it is a flick.
+		//		The synthetic event fired specifies the direction as
+		//		<ul>
+		//			<li><b>'ltr'</b> Left To Right</li>
+		//			<li><b>'rtl'</b> Right To Left</li>
+		//			<li><b>'ttb'</b> Top To Bottom</li>
+		//			<li><b>'btt'</b> Bottom To Top</li>
+		//		</ul>
+		// target: Node
+		//		The DOM node to connect to
+
+		var startX;
+		var startY;
+		var isFlick = false;
+
+		var currentX;
+		var currentY;
+
+		var connMove;
+		var connUp;
+
+		var direction;
+
+		var time;
+
+		// Listen to to the mousedown/touchstart event
+		var connDown = dojo.connect("onmousedown", target, function(event){
+			isFlick = false;
+			startX = event.targetTouches ? event.targetTouches[0].clientX : event.clientX;
+			startY = event.targetTouches ? event.targetTouches[0].clientY : event.clientY;
+
+			time = (new Date()).getTime();
+
+			connMove = dojo.connect(target, "onmousemove", onMove);
+			connUp = dojo.connect(target, "onmouseup", onUp);
+		});
+
+		// The function that handles the mousemove/touchmove event
+		var onMove = function(event){
+			dojo.stopEvent(event);
+
+			currentX = event.targetTouches ? event.targetTouches[0].clientX : event.clientX;
+			currentY = event.targetTouches ? event.targetTouches[0].clientY : event.clientY;
+			if(Math.abs(Math.abs(currentX) - Math.abs(startX)) > 15){
+				isFlick = true;
+
+				direction = (currentX > startX) ? "ltr" : "rtl";
+			}else if(Math.abs(Math.abs(currentY) - Math.abs(startY)) > 15){
+				isFlick = true;
+
+				direction = (currentY > startY) ? "ttb" : "btt";
+			}
+		};
+
+		var onUp = function(event){
+			dojo.stopEvent(event);
+
+			connMove && dojo.disconnect(connMove);
+			connUp && dojo.disconnect(connUp);
+
+			if(isFlick){
+				var flickEvt = {
+					target: target,
+					direction: direction,
+					duration: (new Date()).getTime() - time
+				};
+				if(context && method){
+					context[method](flickEvt);
+				}else{
+					method(flickEvt);
+				}
+			}
+		};
+
+	}
+});
+
+dojox.mobile.app.isIPhone = (dojo.isSafari
+	&& (navigator.userAgent.indexOf("iPhone") > -1 ||
+		navigator.userAgent.indexOf("iPod") > -1
+	));
+dojox.mobile.app.isWebOS = (navigator.userAgent.indexOf("webOS") > -1);
+
+if(dojox.mobile.app.isIPhone){
+	// We are touchable.
+	// Override the dojo._connect function to replace mouse events with touch events
+
+	dojox.mobile.app.eventMap = {
+		onmousedown: "ontouchstart",
+		mousedown: "ontouchstart",
+		onmouseup: "ontouchend",
+		mouseup: "ontouchend",
+		onmousemove: "ontouchmove",
+		mousemove: "ontouchmove"
+	};
+
+}
+dojo._oldConnect = dojo._connect;
+dojo._connect = function(obj, event, context, method, dontFix){
+	event = dojox.mobile.app.eventMap[event] || event;
+	if(event == "flick" || event == "onflick"){
+		if(window["Mojo"]){
+			event = Mojo.Event.flick;
+		}else{
+			return dojox.mobile.app.connectFlick(obj, context, method);
+		}
+	}
+
+	return dojo._oldConnect(obj, event, context, method, dontFix);
+}
\ No newline at end of file
diff --git a/dojox/mobile/app/compat.js b/dojox/mobile/app/compat.js
new file mode 100644
index 0000000..b7dbcc7
--- /dev/null
+++ b/dojox/mobile/app/compat.js
@@ -0,0 +1,109 @@
+dojo.provide("dojox.mobile.app.compat");
+dojo.require("dojox.mobile.compat");
+
+// summary:
+//		CSS3 compatibility module for apps
+// description:
+//		This module provides support for some of the CSS3 features to djMobile
+//		for non-CSS3 browsers, such as IE or Firefox.
+//		If you load this module, it directly replaces some of the methods of
+//		djMobile instead of subclassing. This way, html pages remains the same
+//		regardless of whether this compatibility module is used or not.
+//		Recommended usage is as follows. the code below loads dojox.mobile.compat
+//		only when isWebKit is true.
+//
+//		dojo.require("dojox.mobile");
+//		dojo.requireIf(!dojo.isWebKit, "dojox.mobile.appCompat");
+
+dojo.extend(dojox.mobile.app.AlertDialog, {
+	_doTransition: function(dir){
+		console.log("in _doTransition and this = ", this);
+
+		var h = dojo.marginBox(this.domNode.firstChild).h;
+
+		var bodyHeight = this.controller.getWindowSize().h;
+	
+		var high = bodyHeight - h;
+		var low = bodyHeight;
+
+		var anim1 = dojo.fx.slideTo({
+			node: this.domNode,
+			duration: 400,
+			top: {start: dir < 0 ? high : low, end: dir < 0 ? low: high}
+		});
+
+		var anim2 = dojo[dir < 0 ? "fadeOut" : "fadeIn"]({
+			node: this.mask,
+			duration: 400
+		});
+	
+		var anim = dojo.fx.combine([anim1, anim2]);
+	
+		var _this = this;
+
+		dojo.connect(anim, "onEnd", this, function(){
+			if(dir < 0){
+				_this.domNode.style.display = "none";
+				dojo.destroy(_this.domNode);
+				dojo.destroy(_this.mask);
+			}
+		});
+		anim.play();
+	}
+});
+
+dojo.extend(dojox.mobile.app.List, {
+	deleteRow: function(){
+		console.log("deleteRow in compat mode", row);
+	
+		var row = this._selectedRow;
+		// First make the row invisible
+		// Put it back where it came from
+		dojo.style(row, {
+			visibility: "hidden",
+			minHeight: "0px"
+		});
+		dojo.removeClass(row, "hold");
+	
+	
+		// Animate reducing it's height to zero, then delete the data from the
+		// array
+		var height = dojo.contentBox(row).h;
+		dojo.animateProperty({
+				node: row,
+				duration: 800,
+				properties: {
+				height: {start: height, end: 1},
+				paddingTop: {end: 0},
+				paddingBottom: {end: 0}
+			},
+			onEnd: this._postDeleteAnim
+		}).play();
+	}
+});
+
+if(dojox.mobile.app.ImageView && !dojo.create("canvas").getContext){
+	dojo.extend(dojox.mobile.app.ImageView, {
+		buildRendering: function(){
+			this.domNode.innerHTML = 
+				"ImageView widget is not supported on this browser."
+				+ "Please try again with a modern browser, e.g. "
+				+ "Safari, Chrome or Firefox";
+			this.canvas = {};
+		},
+		
+		postCreate: function(){}
+	});
+}
+
+if(dojox.mobile.app.ImageThumbView){
+	dojo.extend(dojox.mobile.app.ImageThumbView, {
+		place: function(node, x, y){
+			dojo.style(node, {
+				top: y + "px",
+				left: x + "px",
+				visibility: "visible"
+			});
+		}
+	})
+}
diff --git a/dojox/mobile/build/build.bat b/dojox/mobile/build/build.bat
new file mode 100755
index 0000000..1e5d094
--- /dev/null
+++ b/dojox/mobile/build/build.bat
@@ -0,0 +1,47 @@
+ at echo off
+
+rem Build script for dojox.mobile
+rem 
+rem Note:
+rem You may need to manually apply the following patch to your build script
+rem in order to completely remove all the unused modules from your build.
+rem The patch disables finding the dojo base modules being used from the
+rem dependent modules with a simple pattern matching, which sometimes
+rem unexpectedly picks up unused modules.
+rem For example, if you see query.js and NodeList.js baked into your build,
+rem while you are not using them, then it is worth trying the patch.
+rem The file to be patched is util/buildscripts/jslib/buildUtil.js.
+rem 
+rem --- buildUtil.js-orig
+rem +++ buildUtil.js
+rem @@ -1506,7 +1506,7 @@
+rem    var addedResources = {};
+rem -  while((matches = buildUtil.baseMappingRegExp.exec(tempContents))){
+rem +  while(false&&(matches = buildUtil.baseMappingRegExp.exec(tempContents))){
+rem        var baseResource = buildUtil.baseMappings[matches[1]];
+rem        //Make sure we do not add the dependency to its source resource.
+
+if "%1"=="separate" goto ok
+if "%1"=="single" goto ok
+echo Usage: build separate^|single [webkit]
+echo   separate  Create mobile.js that includes only dojox.mobile
+echo   single    Create a single dojo.js layer that includes dojox.mobile
+echo   webkit    Enable webkitMobile=true option (Loses PC browser support)
+goto end
+:ok
+
+set optimize=shrinksafe
+set profile=mobile.profile.js
+set dir=release-mobile-separate
+set webkit=
+if "%1"=="single" set profile=mobile-all.profile.js
+if "%1"=="single" set dir=release-mobile-single
+if "%2"=="webkit" set webkit=webkitMobile=true
+
+cd ..\..\..\util\buildscripts
+
+call build profileFile=../../dojox/mobile/build/profiles/%profile% action=release customDijitBase=true optimize=%optimize% layerOptimize=%optimize% cssOptimize=comments releaseDir=../../%dir%/ %webkit%
+
+cd ..\..\dojox\mobile\build
+
+:end
diff --git a/dojox/mobile/build/build.sh b/dojox/mobile/build/build.sh
new file mode 100755
index 0000000..ab1f456
--- /dev/null
+++ b/dojox/mobile/build/build.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+# Build script for dojox.mobile
+# 
+# Note:
+# You may need to manually apply the following patch to your build script
+# in order to completely remove all the unused modules from your build.
+# The patch disables finding the dojo base modules being used from the
+# dependent modules with a simple pattern matching, which sometimes
+# unexpectedly picks up unused modules.
+# For example, if you see query.js and NodeList.js baked into your build,
+# while you are not using them, then it is worth trying the patch.
+# The file to be patched is util/buildscripts/jslib/buildUtil.js.
+# 
+# --- buildUtil.js-orig
+# +++ buildUtil.js
+# @@ -1506,7 +1506,7 @@
+#    var addedResources = {};
+# -  while((matches = buildUtil.baseMappingRegExp.exec(tempContents))){
+# +  while(false&&(matches = buildUtil.baseMappingRegExp.exec(tempContents))){
+#        var baseResource = buildUtil.baseMappings[matches[1]];
+#        //Make sure we do not add the dependency to its source resource.
+
+if [ $# -eq 0 ]; then
+  echo 'Usage: build separate|single [webkit]'
+  echo '  separate  Create mobile.js that includes only dojox.mobile'
+  echo '  single    Create a single dojo.js layer that includes dojox.mobile'
+  echo '  webkit    Enable webkitMobile=true option (Loses PC browser support)'
+  exit 1
+fi
+
+optimize=shrinksafe
+profile=mobile.profile.js
+dir=release-mobile-separate
+webkit=
+if [ "$1" == "single" ]; then
+  profile=mobile-all.profile.js
+fi
+if [ "$1" == "single" ]; then
+  dir=release-mobile-single
+fi
+if [ "$2" == "webkit" ]; then
+  webkit=webkitMobile=true
+fi
+
+cd ../../../util/buildscripts
+
+./build.sh profileFile=../../dojox/mobile/build/profiles/$profile action=release customDijitBase=true optimize=$optimize layerOptimize=$optimize cssOptimize=comments releaseDir=../../$dir/ $webkit
+
+cd ../../dojox/mobile/build
diff --git a/dojox/mobile/build/profiles/mobile-all.profile.js b/dojox/mobile/build/profiles/mobile-all.profile.js
new file mode 100755
index 0000000..6a177de
--- /dev/null
+++ b/dojox/mobile/build/profiles/mobile-all.profile.js
@@ -0,0 +1,36 @@
+dependencies = {
+	stripConsole: "normal",
+
+	layers: [
+		{
+			name: "dojo.js",
+			customBase: true,
+			dependencies: [
+				"dojo._base.declare",
+				"dojo._base.lang",
+				"dojo._base.array",
+				"dojo._base.window",
+				"dojo._base.event",
+				"dojo._base.connect",
+				"dojo._base.html",
+				"dijit._Widget",
+				"dijit._base.manager",
+				"dijit._base.sniff",
+				"dojox.mobile.parser",
+				"dojox.mobile"
+			]
+		},
+		{
+			name: "../dojox/mobile/compat.js",
+			dependencies: [
+				"dojo._base.fx",
+				"dojox.mobile.compat"
+			]
+		}
+	],
+
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ]
+	]
+}
diff --git a/dojox/mobile/build/profiles/mobile.profile.js b/dojox/mobile/build/profiles/mobile.profile.js
new file mode 100755
index 0000000..a0c7437
--- /dev/null
+++ b/dojox/mobile/build/profiles/mobile.profile.js
@@ -0,0 +1,40 @@
+dependencies = {
+	stripConsole: "normal",
+	layers: [
+		{
+			name: "dojo.js",
+			dependencies: [
+				"dijit._Widget",
+			]
+		},
+		{
+			name: "../dojox/mobile.js",
+			dependencies: [
+				"dojox.mobile"
+			]
+		},
+		{
+			name: "../dojox/mobile/app.js",
+			dependencies: [
+				"dojox.mobile.app"
+			]
+		},
+		{
+			name: "../dojox/mobile/compat.js",
+			dependencies: [
+				"dojox.mobile.compat"
+			]
+		},
+		{
+			name: "../dojox/mobile/app/compat.js",
+			dependencies: [
+				"dojox.mobile.app.compat"
+			]
+		}
+	],
+
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ]
+	]
+}
diff --git a/dojox/mobile/compat.js b/dojox/mobile/compat.js
new file mode 100644
index 0000000..40ba11c
--- /dev/null
+++ b/dojox/mobile/compat.js
@@ -0,0 +1,399 @@
+dojo.provide("dojox.mobile.compat");
+dojo.require("dojo._base.fx");
+dojo.require("dojo.fx");
+dojo.require("dojox.fx.flip");
+
+// summary:
+//		CSS3 compatibility module
+// description:
+//		This module provides support for some of the CSS3 features to dojox.mobile
+//		for non-CSS3 browsers, such as IE or Firefox.
+//		If you load this module, it directly replaces some of the methods of
+//		dojox.mobile instead of subclassing. This way, html pages remains the same
+//		regardless of whether this compatibility module is used or not.
+//		Recommended usage is as follows. the code below loads dojox.mobile.compat
+//		only when isWebKit is true.
+//
+//		dojo.require("dojox.mobile");
+//		dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+//
+//		This module also loads compatibility CSS files, which has -compat.css
+//		suffix. You should use the <link> tag instead of @import to load theme
+//		CSS files. Then, this module searches for the <link> tags and loads
+//		compatibility CSS files. For example, if you load iphone.css with a
+//		link tag, this module automatically loads iphone-compat.css.
+//		Of course, you can explicitly load iphone.css and iphone-compat.css
+//		with the @import rule if you would like.
+
+dojo.extend(dojox.mobile.View, {
+	_doTransition: function(fromNode, toNode, transition, dir){
+		var anim;
+		this.wakeUp(toNode);
+		if(!transition || transition == "none"){
+			toNode.style.display = "";
+			fromNode.style.display = "none";
+			toNode.style.left = "0px";
+			this.invokeCallback();
+		}else if(transition == "slide"){
+			var w = fromNode.offsetWidth;
+			var s1 = dojo.fx.slideTo({
+				node: fromNode,
+				duration: 400,
+				left: -w*dir,
+				top: fromNode.offsetTop
+			});
+			var s2 = dojo.fx.slideTo({
+				node: toNode,
+				duration: 400,
+				left: 0
+			});
+			toNode.style.position = "absolute";
+			toNode.style.left = w*dir + "px";
+			toNode.style.display = "";
+			anim = dojo.fx.combine([s1,s2]);
+			dojo.connect(anim, "onEnd", this, function(){
+				fromNode.style.display = "none";
+				toNode.style.position = "relative";
+				this.invokeCallback();
+			});
+			anim.play();
+		}else if(transition == "flip"){
+			anim = dojox.fx.flip({
+				node: fromNode,
+				dir: "right",
+				depth: 0.5,
+				duration: 400
+			});
+			toNode.style.position = "absolute";
+			toNode.style.left = "0px";
+			dojo.connect(anim, "onEnd", this, function(){
+				fromNode.style.display = "none";
+				toNode.style.position = "relative";
+				toNode.style.display = "";
+				this.invokeCallback();
+			});
+			anim.play();
+		}else if(transition == "fade"){
+			anim = dojo.fx.chain([
+				dojo.fadeOut({
+					node: fromNode,
+					duration: 600
+				}),
+				dojo.fadeIn({
+					node: toNode,
+					duration: 600
+				})
+			]);
+			toNode.style.position = "absolute";
+			toNode.style.left = "0px";
+			toNode.style.display = "";
+			dojo.style(toNode, "opacity", 0);
+			dojo.connect(anim, "onEnd", this, function(){
+				fromNode.style.display = "none";
+				toNode.style.position = "relative";
+				dojo.style(fromNode, "opacity", 1);
+				this.invokeCallback();
+			});
+			anim.play();
+		}
+	},
+
+	wakeUp: function(node){
+		// summary:
+		//		Function to force IE to redraw a node since its layout code tends to misrender
+		//		in partial draws.
+		//	node:
+		//		The node to forcibly redraw.
+		// tags:
+		//		public
+		if(dojo.isIE && !node._wokeup){
+			node._wokeup = true;
+			var disp = node.style.display;
+			node.style.display = "";
+			var nodes = node.getElementsByTagName("*");
+			for(var i = 0, len = nodes.length; i < len; i++){
+				var val = nodes[i].style.display;
+				nodes[i].style.display = "none";
+				nodes[i].style.display = "";
+				nodes[i].style.display = val;
+			}
+			node.style.display = disp;
+		}
+	}
+});
+
+dojo.extend(dojox.mobile.Switch, {
+	buildRendering: function(){
+		// summary:
+		//		Function to simulate the mobile device style switches on
+		//		browsers such as IE and FireFox.
+		// tags:
+		//		protected
+		this.domNode = this.srcNodeRef || dojo.doc.createElement("DIV");
+		this.domNode.className = "mblSwitch";
+		this.domNode.innerHTML =
+			  '<div class="mblSwitchInner">'
+			+	'<div class="mblSwitchBg mblSwitchBgLeft">'
+			+		'<div class="mblSwitchCorner mblSwitchCorner1T"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner2T"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner3T"></div>'
+			+		'<div class="mblSwitchText mblSwitchTextLeft">'+this.leftLabel+'</div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner1B"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner2B"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner3B"></div>'
+			+	'</div>'
+			+	'<div class="mblSwitchBg mblSwitchBgRight">'
+			+		'<div class="mblSwitchCorner mblSwitchCorner1T"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner2T"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner3T"></div>'
+			+		'<div class="mblSwitchText mblSwitchTextRight">'+this.rightLabel+'</div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner1B"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner2B"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner3B"></div>'
+			+	'</div>'
+			+	'<div class="mblSwitchKnobContainer">'
+			+		'<div class="mblSwitchCorner mblSwitchCorner1T"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner2T"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner3T"></div>'
+			+		'<div class="mblSwitchKnob"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner1B"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner2B"></div>'
+			+		'<div class="mblSwitchCorner mblSwitchCorner3B"></div>'
+			+	'</div>'
+			+ '</div>';
+		var n = this.inner = this.domNode.firstChild;
+		this.left = n.childNodes[0];
+		this.right = n.childNodes[1];
+		this.knob = n.childNodes[2];
+
+		dojo.addClass(this.domNode, (this.value == "on") ? "mblSwitchOn" : "mblSwitchOff");
+		this[this.value == "off" ? "left" : "right"].style.display = "none";
+	},
+
+	_changeState: function(/*String*/state){
+		// summary:
+		//		Function to toggle the switch state on the switch
+		// state:
+		//		Thhe state to toggle, switch 'on' or 'off'
+		// tags:
+		//		private
+		if(!this.inner.parentNode || !this.inner.parentNode.tagName){
+			dojo.addClass(this.domNode, (state == "on") ? "mblSwitchOn" : "mblSwitchOff");
+			return;
+		}
+		var pos;
+		if(this.inner.offsetLeft == 0){ // currently ON
+			if(state == "on"){ return; }
+			pos = -53;
+		}else{ // currently OFF
+			if(state == "off"){ return; }
+			pos = 0;
+		}
+
+		var a = dojo.fx.slideTo({
+			node: this.inner,
+			duration: 500,
+			left: pos
+		});
+		var _this = this;
+		dojo.connect(a, "onEnd", function(){
+			_this[state == "off" ? "left" : "right"].style.display = "none";
+		});
+		a.play();
+	}
+});
+
+if(dojo.isIE){
+
+dojo.extend(dojox.mobile.RoundRect, {
+	buildRendering: function(){
+		// summary:
+		//		Function to simulate the borderRadius appearance on IE, since
+		//		IE does not support this CSS style.
+		// tags:
+		//		protected
+		dojox.mobile.createRoundRect(this);
+		this.domNode.className = "mblRoundRect";
+	}
+});
+
+dojox.mobile.RoundRectList._addChild = dojox.mobile.RoundRectList.prototype.addChild;
+dojo.extend(dojox.mobile.RoundRectList, {
+	buildRendering: function(){
+		// summary:
+		//		Function to simulate the borderRadius appearance on IE, since
+		//		IE does not support this CSS style.
+		// tags:
+		//		protected
+		dojox.mobile.createRoundRect(this, true);
+		this.domNode.className = "mblRoundRectList";
+	},
+
+	postCreate: function(){
+		this.redrawBorders();
+	},
+
+	addChild: function(widget){
+		dojox.mobile.RoundRectList._addChild.apply(this, arguments);
+		this.redrawBorders();
+		if(dojox.mobile.applyPngFilter){
+			dojox.mobile.applyPngFilter(widget.domNode);
+		}
+	},
+
+	redrawBorders: function(){
+		// summary:
+		//		Function to adjust the creation of RoundRectLists on IE.
+		//		Removed undesired styles.
+		// tags:
+		//		public
+
+		// Remove a border of the last ListItem.
+		// This is for browsers that do not support the last-child CSS pseudo-class.
+
+		var lastChildFound = false;
+		for(var i = this.containerNode.childNodes.length - 1; i >= 0; i--){
+			var c = this.containerNode.childNodes[i];
+			if(c.tagName == "LI"){
+				c.style.borderBottomStyle = lastChildFound ? "solid" : "none";
+				lastChildFound = true;
+			}
+		}
+	}
+});
+
+dojo.extend(dojox.mobile.EdgeToEdgeList, {
+	buildRendering: function(){
+		this.domNode = this.containerNode = this.srcNodeRef || dojo.doc.createElement("UL");
+		this.domNode.className = "mblEdgeToEdgeList";
+	}
+});
+
+dojox.mobile.IconContainer._addChild = dojox.mobile.IconContainer.prototype.addChild;
+dojo.extend(dojox.mobile.IconContainer, {
+	addChild: function(widget){
+		dojox.mobile.IconContainer._addChild.apply(this, arguments);
+		if(dojox.mobile.applyPngFilter){
+			dojox.mobile.applyPngFilter(widget.domNode);
+		}
+	}
+});
+
+dojo.mixin(dojox.mobile, {
+	createRoundRect: function(_this, isList){
+		// summary:
+		//		Function to adjust the creation of rounded rectangles on IE.
+		//		Deals with IE's lack of borderRadius support
+		// tags:
+		//		public
+		var i;
+		_this.domNode = dojo.doc.createElement("DIV");
+		_this.domNode.style.padding = "0px";
+		_this.domNode.style.backgroundColor = "transparent";
+		_this.domNode.style.borderStyle = "none";
+		_this.containerNode = dojo.doc.createElement(isList?"UL":"DIV");
+		_this.containerNode.className = "mblRoundRectContainer";
+		if(_this.srcNodeRef){
+			_this.srcNodeRef.parentNode.replaceChild(_this.domNode, _this.srcNodeRef);
+			for(i = 0, len = _this.srcNodeRef.childNodes.length; i < len; i++){
+				_this.containerNode.appendChild(_this.srcNodeRef.removeChild(_this.srcNodeRef.firstChild));
+			}
+			_this.srcNodeRef = null;
+		}
+		_this.domNode.appendChild(_this.containerNode);
+
+		for(i = 0; i <= 5; i++){
+			var top = dojo.create("DIV");
+			top.className = "mblRoundCorner mblRoundCorner"+i+"T";
+			_this.domNode.insertBefore(top, _this.containerNode);
+
+			var bottom = dojo.create("DIV");
+			bottom.className = "mblRoundCorner mblRoundCorner"+i+"B";
+			_this.domNode.appendChild(bottom);
+		}
+	}
+});
+
+} // if(dojo.isIE)
+
+if(dojo.isIE <= 6){
+	dojox.mobile.applyPngFilter = function(root){
+		root = root || dojo.body();
+		var nodes = root.getElementsByTagName("IMG");
+		var blank = dojo.moduleUrl("dojo", "resources/blank.gif");
+		for(var i = 0, len = nodes.length; i < len; i++){
+			var img = nodes[i];
+			var w = img.offsetWidth;
+			var h = img.offsetHeight;
+			if(w === 0 || h === 0){ return; }
+			var src = img.src;
+			if(src.indexOf("resources/blank.gif") != -1){ continue; }
+			img.src = blank;
+			img.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src+"')";
+			img.style.width = w + "px";
+			img.style.height = h + "px";
+		}
+	};
+} // if(dojo.isIE <= 6)
+
+dojox.mobile.loadCss = function(/*String|Array*/files){
+	// summary:
+	//		Function to load and register CSS files with the page
+	//	files: String|Array
+	//		The CSS files to load and register with the page.
+	// tags:
+	//		private
+	if(!dojo.global._loadedCss){
+		var obj = {};
+		dojo.forEach(dojo.doc.getElementsByTagName("link"), function(item){
+			obj[item.href] = true;
+		});
+		dojo.global._loadedCss = obj;
+	}
+	if(!dojo.isArray(files)){ files = [files]; }
+	for(var i = 0; i < files.length; i++){
+		var file = files[i];
+		if(!dojo.global._loadedCss[file]){
+			dojo.global._loadedCss[file] = true;
+			if(dojo.doc.createStyleSheet){
+				// for some reason, IE hangs when you try to load
+				// multiple css files almost at once.
+				setTimeout(function(file){
+					return function(){
+						dojo.doc.createStyleSheet(file);
+					};
+				}(file), 0);
+			}else{
+				var link = dojo.doc.createElement("link");
+				link.href = file;
+				link.type = "text/css";
+				link.rel = "stylesheet";
+				var head = dojo.doc.getElementsByTagName('head')[0];
+				head.appendChild(link);
+			}
+		}
+	}
+};
+
+dojox.mobile.loadCompatCssFiles = function(){
+	// summary:
+	//		Function to perform page-level adjustments on browsers such as
+	//		IE and firefox.  It loads compat specific css files into the
+	//		page header.
+	var elems = dojo.doc.getElementsByTagName("link");
+	for(var i = 0, len = elems.length; i < len; i++){
+		var href = elems[i].href;
+		if((href.indexOf("/mobile/themes/") != -1 || location.href.indexOf("/mobile/tests/") != -1)
+			 && href.substring(href.length - 4) == ".css"){
+			var compatCss = href.substring(0, href.length-4)+"-compat.css";
+			dojox.mobile.loadCss(compatCss);
+		}
+	}
+};
+
+dojo.addOnLoad(function(){
+	dojox.mobile.loadCompatCssFiles();
+	if(dojox.mobile.applyPngFilter){
+		dojox.mobile.applyPngFilter();
+	}
+});
diff --git a/dojox/mobile/parser.js b/dojox/mobile/parser.js
new file mode 100644
index 0000000..cd697d7
--- /dev/null
+++ b/dojox/mobile/parser.js
@@ -0,0 +1,80 @@
+dojo.provide("dojox.mobile.parser");
+dojo.provide("dojo.parser"); // not to load dojo.parser unexpectedly
+
+dojox.mobile.parser = new function(){
+	this.instantiate = function(list, defaultParams){
+		// summary:
+		//		Function for instantiating a list of widget nodes.
+		// list:
+		//		The list of DOMNodes to walk and instantiate widgets on.
+		var ws = [];
+		if(list){
+			var i, len;
+			len = list.length
+			for(i = 0; i < len; i++){
+				var node = list[i];
+				var cls = dojo.getObject(dojo.attr(node, "dojoType"));
+				var proto = cls.prototype;
+				var params = {};
+
+				if(defaultParams){
+					for(var name in defaultParams){
+						params[name] = defaultParams[name];
+					}
+				}
+				for(var prop in proto){
+					var val = dojo.attr(node, prop);
+					if(!val){ continue; }
+					if(typeof proto[prop] == "string"){
+						params[prop] = val;
+					}else if(typeof proto[prop] == "number"){
+						params[prop] = val - 0;
+					}else if(typeof proto[prop] == "boolean"){
+						params[prop] = (val != "false");
+					}else if(typeof proto[prop] == "object"){
+						params[prop] = eval("(" + val + ")");
+					}
+				}
+				params["class"] = node.className;
+				params["style"] = node.style && node.style.cssText;
+				ws.push(new cls(params, node));
+			}
+			len = ws.length
+			for(i = 0; i < len; i++){
+				var w = ws[i]
+				w.startup && !w._started && (!w.getParent || !w.getParent()) && w.startup();
+			}
+		}
+		return ws;
+	};
+
+	this.parse = function(rootNode, defaultParams){
+		// summary:
+		//		Function to handle parsing for widgets in the current document.
+		//		It is not as powerful as the full dojo parser, but it will handle basic
+		//		use cases fine.
+		// rootNode:
+		//		The root node in the document to parse from
+		if(!rootNode){
+			rootNode = dojo.body();
+		}else if(!defaultParams && rootNode.rootNode){
+			// Case where 'rootNode' is really a params object.
+			rootNode = rootNode.rootNode;
+ 		}
+
+		var nodes = rootNode.getElementsByTagName("*");
+		var list = [];
+		for(var i = 0, len = nodes.length; i < len; i++){
+			if(nodes[i].getAttribute("dojoType")){
+				list.push(nodes[i]);
+			}
+		}
+		return this.instantiate(list, defaultParams);
+	};
+};
+dojo._loaders.unshift(function(){
+	if(dojo.config.parseOnLoad){
+		dojox.mobile.parser.parse();
+	}
+});
+
diff --git a/dojox/mobile/tests/complexListApp/app/assistants/main-assistant.js b/dojox/mobile/tests/complexListApp/app/assistants/main-assistant.js
new file mode 100644
index 0000000..eb906b5
--- /dev/null
+++ b/dojox/mobile/tests/complexListApp/app/assistants/main-assistant.js
@@ -0,0 +1,123 @@
+dojo.provide("MainAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("MainAssistant", dojox.mobile.app.SceneAssistant, {
+  
+  setup: function(){
+    console.log("In main assistant setup");
+    
+    this.controller.parse();
+    console.log("In main assistant setup 2");
+    
+    var data1 = [
+      {
+        label: "Row 1",
+        button1Cls: "listButton1",
+        button2Cls: "listButton2",
+        buttonLabel1: "Add"
+      },
+      {
+        label: "Row 2",
+        button1Cls: "listButton2",
+        button2Cls: "listButton1"
+      }
+    ];
+    var data2 = [
+      {
+        label: "Row 3",
+        button1Cls: "listButton1",
+        button2Cls: "listButtonHidden"
+      },
+      {
+        label: "Row 4",
+        button1Cls: "listButton2",
+        button2Cls: "listButton3"
+      },
+      {
+        label: "Row 5",
+        button1Cls: "listButton3",
+        button2Cls: "listButton2",
+        buttonLabel2: "Del"
+      },
+      {
+        label: "Row 6",
+        button1Cls: "listButtonHidden",
+        button2Cls: "listButton2"
+      }
+    ];
+    var data3 = [];
+    
+    dijit.byId("listWidget").set("items", data1);
+    
+    var buttonOutput = this.controller.query("#buttonOutput")[0];
+    
+    this.connect(dijit.byId("btn1"), "onClick", function(){
+      dijit.byId("listWidget").set("items", data1);
+    });
+    this.connect(dijit.byId("btn2"), "onClick", function(){
+      dijit.byId("listWidget").set("items", data2);
+    });
+    this.connect(dijit.byId("btn3"), "onClick", function(){
+      dijit.byId("listWidget").set("items", data3);
+    });
+    
+    var _this = this;
+    
+    this.connect(dijit.byId("listWidget").domNode, "onclick", function(event){
+      // If the user clicked one of the buttons in a row,
+      // then show a popup menu for further actions.
+      if(!event.item){
+        return;
+      }
+      
+      if(dojo.hasClass(event.target, "listBtn")){
+        buttonOutput.innerHTML = "You clicked Item " + event.index
+                + " with the label '" + event.item.label + "'"
+                + " using a button with the CSS class '"
+                + event.target.className.split(" ")[2]
+                + "'";
+                
+        _this.showMenu(event.target);
+      } else {
+        buttonOutput.innerHTML = "You clicked Item " + event.index
+                + " with the label '" + event.item.label + "'"
+      }
+    });
+//    
+//    this.connect(dijit.byId("listWidget").domNode, "onmousedown", function(event){
+//      _this.controller.showAlertDialog({
+//        title: "MDown",
+//        text: "type: " + dojox.mobile.app.isIPhone//event.target.className
+//      })
+//    });
+    
+  },
+  
+  showMenu: function(fromNode){
+    
+    var buttonOutput = this.controller.query("#buttonOutput")[0];
+    
+    this.controller.popupSubMenu({
+      choices: [
+        {label: "Option 1", value: 1},
+        {label: "Option 2", value: 2},
+        {label: "Option 3 - A Bit Longer", value: 3},
+        {label: "Option 4", value: 4}
+      ],
+      
+      fromNode: fromNode,
+      
+      onChoose: function(value){
+        buttonOutput.innerHTML = "You chose the menu item with value " + value;
+      }
+      
+    })
+  },
+  
+  activate: function(){
+    console.log("In main assistant activate");
+    
+    
+  }
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/complexListApp/app/views/main/emptyTemplate.html b/dojox/mobile/tests/complexListApp/app/views/main/emptyTemplate.html
new file mode 100644
index 0000000..62d0802
--- /dev/null
+++ b/dojox/mobile/tests/complexListApp/app/views/main/emptyTemplate.html
@@ -0,0 +1,3 @@
+<div class="row first last">
+  No Items In List
+</div>
diff --git a/dojox/mobile/tests/complexListApp/app/views/main/main-scene.html b/dojox/mobile/tests/complexListApp/app/views/main/main-scene.html
new file mode 100644
index 0000000..320ad25
--- /dev/null
+++ b/dojox/mobile/tests/complexListApp/app/views/main/main-scene.html
@@ -0,0 +1,23 @@
+<div>
+  This scene shows how to render a list containing buttons. 
+  Swipe to delete rows.
+</div>
+
+<div dojoType="dojox.mobile.RoundRect" 
+    shadow="true" id="buttonOutput" style="min-height: 70px;">
+  Click a button in the list to see the output here
+</div>
+
+<button id="btn1" dojoType="dojox.mobile.Button">Data 1</button>
+<button id="btn2" dojoType="dojox.mobile.Button">Data 2</button>
+<button id="btn3" 
+        dojoType="dojox.mobile.Button" 
+        btnClass="mblRedButton">Empty Data</button>
+
+<div dojoType="dojox.mobile.RoundRect" shadow="true">
+  <div id="listWidget" dojoType="dojox.mobile.app.List" 
+      class="iconList"
+      autoDelete="false"
+      itemTemplate="app/views/main/rowTemplate.html"
+      emptyTemplate="app/views/main/emptyTemplate.html"></div>
+</div>
\ No newline at end of file
diff --git a/dojox/mobile/tests/complexListApp/app/views/main/rowTemplate.html b/dojox/mobile/tests/complexListApp/app/views/main/rowTemplate.html
new file mode 100644
index 0000000..1483081
--- /dev/null
+++ b/dojox/mobile/tests/complexListApp/app/views/main/rowTemplate.html
@@ -0,0 +1,15 @@
+<div class="row">
+  <table>
+    <tr>
+      <td style="width: 100%;">
+        ${label}
+      </td>
+      <td>
+          <span class="listBtn noclick ${button1Cls}">${buttonLabel1}</span>
+      </td>
+      <td>
+          <span class="listBtn noclick ${button2Cls}">${buttonLabel2}</span>
+      </td>
+    </tr>
+  </table>
+</div>
diff --git a/dojox/mobile/tests/complexListApp/images/i-icon-1.png b/dojox/mobile/tests/complexListApp/images/i-icon-1.png
new file mode 100755
index 0000000..8cbf494
Binary files /dev/null and b/dojox/mobile/tests/complexListApp/images/i-icon-1.png differ
diff --git a/dojox/mobile/tests/complexListApp/images/i-icon-2.png b/dojox/mobile/tests/complexListApp/images/i-icon-2.png
new file mode 100755
index 0000000..1965b3e
Binary files /dev/null and b/dojox/mobile/tests/complexListApp/images/i-icon-2.png differ
diff --git a/dojox/mobile/tests/complexListApp/images/i-icon-3.png b/dojox/mobile/tests/complexListApp/images/i-icon-3.png
new file mode 100755
index 0000000..3450131
Binary files /dev/null and b/dojox/mobile/tests/complexListApp/images/i-icon-3.png differ
diff --git a/dojox/mobile/tests/complexListApp/images/i-icon-4.png b/dojox/mobile/tests/complexListApp/images/i-icon-4.png
new file mode 100755
index 0000000..403990b
Binary files /dev/null and b/dojox/mobile/tests/complexListApp/images/i-icon-4.png differ
diff --git a/dojox/mobile/tests/complexListApp/index.html b/dojox/mobile/tests/complexListApp/index.html
new file mode 100644
index 0000000..f766c4c
--- /dev/null
+++ b/dojox/mobile/tests/complexListApp/index.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<link href="../../themes/iphone/iphone-app.css" rel="stylesheet">
+		<link href="styles/style.css" rel="stylesheet">
+		<style>
+		.lnk {
+			font-size: 17px;
+			color: cyan;
+			text-decoration: none;
+		}
+		</style>
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="parseOnLoad: false"></script>
+    
+    <!-- 
+      Include the files directly, as some mobile operating systems do not
+      allow synchronous XHR, and therefore break dojo.require
+    -->
+		<script type="text/javascript" src="../../../mobile/app.js"></script>
+		<script language="JavaScript" type="text/javascript">
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.app.compat");
+      
+      var appInfo = {
+        id: "org.dojo.simpleApp",
+        title: "Mobile App With Complex List",
+        initialScene: "main"
+      };
+      
+      dojo.ready(dojox.mobile.app.init);
+		</script>
+	</head>
+	<body>
+		
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mobile/tests/complexListApp/styles/style.css b/dojox/mobile/tests/complexListApp/styles/style.css
new file mode 100644
index 0000000..0989af2
--- /dev/null
+++ b/dojox/mobile/tests/complexListApp/styles/style.css
@@ -0,0 +1,38 @@
+.row .listBtn {
+  float: right;
+  min-width: 32px;
+  min-height: 32px;
+  -webkit-border-radius: 4px;
+	-moz-border-radius: 4px; 
+  margin-right: 8px;
+  color: #333;
+  padding-top: 5px;
+  padding-left: 2px;
+  padding-right: 5px;
+  font-size: smaller;
+}
+
+
+.iconList .row {
+  min-height: 36px;
+}
+
+.row .listButton1 {
+  background: url(../images/i-icon-1.png) no-repeat;
+}
+.row .listButton2 {
+  background: url(../images/i-icon-2.png) no-repeat;
+}
+.row .listButton3 {
+  background: url(../images/i-icon-3.png) no-repeat;
+}
+.row .listButton4 {
+  background: url(../images/i-icon-4.png) no-repeat;
+}
+.row .listButtonText {
+  
+}
+
+.row .listButtonHidden {
+  display: none;
+}
diff --git a/dojox/mobile/tests/dialogApp/app/assistants/main-assistant.js b/dojox/mobile/tests/dialogApp/app/assistants/main-assistant.js
new file mode 100644
index 0000000..58df3d6
--- /dev/null
+++ b/dojox/mobile/tests/dialogApp/app/assistants/main-assistant.js
@@ -0,0 +1,75 @@
+dojo.provide("MainAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("MainAssistant", dojox.mobile.app.SceneAssistant, {
+  
+  setup: function(){
+    console.log("In main assistant setup");
+    
+    // Instantiate widgets in the template HTML.
+    this.controller.parse();
+    
+    var appInfoNode = this.controller.query(".appInfoArea")[0];
+    
+    appInfoNode.innerHTML = 
+      "This app has the following info: \n" 
+        + dojo.toJson(dojox.mobile.app.info, true);
+        
+    function handleChoose(value){
+      appInfoNode.innerHTML = "Value selected: " + value;
+      
+    }
+    
+    
+    var controller = this.controller; 
+    
+    console.log("btn1 = ", dijit.byId("btn1"));
+    
+    dojo.connect(dijit.byId("btn1"), "onClick", function(){
+      console.log("Clicked btn1");
+      controller.showAlertDialog({
+        title: "First Dialog",
+        text: "This is a simple text message",
+        onChoose: handleChoose,
+        
+        buttons: [
+          {
+            label: "Tap Me!",
+            value: "tapped",
+            "class": "mblBlueButton"
+          }
+        ]
+      })
+    });
+    
+    dojo.connect(dijit.byId("btn2"), "onClick", function(){
+      console.log("Clicked btn2");
+      controller.showAlertDialog({
+        title: "Second Dialog",
+        text: "These two buttons return different values, 'value one' and 'value two'",
+        onChoose: handleChoose,
+        
+        buttons: [
+          {
+            label: "Im Am Button 1",
+            value: "value one",
+            "class": "mblBlueButton"
+          },
+          {
+            label: "Im Am Button 2",
+            value: "value two",
+            "class": "mblBlueButton"
+          }
+        ]
+      })
+    });
+    
+  },
+  
+  activate: function(){
+    console.log("In main assistant activate");
+    
+    
+  }
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/dialogApp/app/views/main/main-scene.html b/dojox/mobile/tests/dialogApp/app/views/main/main-scene.html
new file mode 100644
index 0000000..d192973
--- /dev/null
+++ b/dojox/mobile/tests/dialogApp/app/views/main/main-scene.html
@@ -0,0 +1,10 @@
+<div>
+  Press the buttons to show the alert dialogs.  Tap a button in a dialog to
+  choose a value, or tap anywhere else on the screen to cancel the dialog.
+</div>
+
+<pre class="appInfoArea"></pre>
+
+
+<button id="btn1" dojoType="dojox.mobile.Button">Dialog 1</button>
+<button id="btn2" dojoType="dojox.mobile.Button" btnClass="mblRedButton">Dialog 2</button>
diff --git a/dojox/mobile/tests/dialogApp/index.html b/dojox/mobile/tests/dialogApp/index.html
new file mode 100644
index 0000000..0b13f64
--- /dev/null
+++ b/dojox/mobile/tests/dialogApp/index.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Mobile App With Dialog Boxes</title>
+		<link href="../../themes/iphone/iphone-app.css" rel="stylesheet">
+		<style>
+            .lnk {
+                font-size: 17px;
+                color: cyan;
+                text-decoration: none;
+            }
+		</style>
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="parseOnLoad: false"></script>
+    
+    <!-- 
+      Include the files directly, as some mobile operating systems do not
+      allow synchronous XHR, and therefore break dojo.require
+    -->
+		<script type="text/javascript" src="../../../mobile/app.js"></script>
+		<script language="JavaScript" type="text/javascript">
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.app.compat");
+      
+            var appInfo = {
+                id: "org.dojo.simpleApp",
+                title: "Mobile App With Dialog Boxes",
+                initialScene: "main"
+            };
+      
+            dojo.ready(dojox.mobile.app.init);
+		</script>
+	</head>
+	<body>
+		
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-image-thumb-view-assistant.js b/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-image-thumb-view-assistant.js
new file mode 100644
index 0000000..f0b9c4e
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-image-thumb-view-assistant.js
@@ -0,0 +1,198 @@
+dojo.provide("FlickrImageThumbViewAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("FlickrImageThumbViewAssistant", dojox.mobile.app.SceneAssistant, {
+  
+	apiKey: "8c6803164dbc395fb7131c9d54843627",
+	
+	setup: function(){
+	
+		// Instantiate widgets in the template HTML.
+		this.controller.parse();
+		
+		this.handlePhotoLoad = dojo.hitch(this, this.handlePhotoLoad);
+		this.search = dojo.hitch(this, this.search);
+		
+		this.textWidget = dijit.byId("searchTextThumbInput");
+		
+		var viewer = this.viewer = dijit.byId("flickrImageThumbView");
+		
+		console.log("widget flickrImageThumbView = ", viewer);
+		
+		var _this = this;
+		
+		this.connect(viewer, "onSelect", function(item, index){
+			console.log("selected ", item, index);
+			
+			_this.controller.stageController.pushScene("flickr-image-view",{
+				type: "data",
+				images: _this.urls,
+				index: index
+			});
+		});
+
+		this.connect(this.textWidget, "onChange", function(value){
+			if(!value || value.length == 0){
+				_this.viewer.attr("items", []);
+				return;
+			}
+			
+			if(!_this.timer){
+				_this.timer = setTimeout(_this.search, 1000);
+			}
+		});
+	},
+  
+	activate: function(options){
+		
+		// If this is the first time this view is activated, then do the initial
+		// load of images
+		if (!this.dataType) {
+		
+			this.dataType = (options ? options.type : "interesting");
+
+			switch (this.dataType) {
+				case "interesting":
+					// Hide the search text box
+					dojo.style(this.textWidget.domNode, "display", "none");
+					this.loadInteresting();
+					break;
+				case "text":
+					dojo.style(this.textWidget.domNode, "visibility", "visible");
+					this.loadText(this.textWidget.attr("value"));
+					break;
+				case "tag":
+					// Another scene has passed in a list of images
+					// and an initial index
+					dojo.style(this.textWidget.domNode, "visibility", "visible");
+					this.loadTags(this.textWidget.attr("value"));
+					break;
+				default:
+					console.log("unknown type " + this.dataType, options);
+			}
+		}
+	},
+	
+	search: function(){
+		if(this.timer){
+			clearTimeout(this.timer);
+			this.timer = null;
+		}
+		
+		var searchText = this.textWidget.attr("value");
+		
+		if(!searchText || dojo.trim(searchText).length < 1){
+			this.viewer.attr("items", []);
+			
+			console.log("NOT SEARCHING");
+			return;
+		}
+		
+		console.log("search", searchText);
+		switch(this.dataType){
+			case "text":
+				this.loadText(searchText);
+				break;
+			case "tag":
+				// Another scene has passed in a list of images
+				// and an initial index
+				this.loadTags(searchText);
+				break;
+		}
+	},
+  
+	loadInteresting: function(){
+		console.log("loading interesting");
+		var _this = this;
+		
+		var url = "http://api.flickr.com/services/rest/?method=" +
+					"flickr.interestingness.getList";
+
+		var deferred = dojo.io.script.get({
+			url: url,
+			content: { 
+				api_key: this.apiKey,
+				format: "json",
+				per_page: 20
+			},
+			jsonp: "jsoncallback"
+		});
+		deferred.addBoth(this.handlePhotoLoad);
+	},
+
+	loadText: function(text){
+		console.log("loading text ", text);
+		var _this = this;
+		
+		var url = "http://api.flickr.com/services/rest/?method=" +
+					"flickr.photos.search";
+
+		var deferred = dojo.io.script.get({
+			url: url,
+			content: { 
+				api_key: this.apiKey,
+				format: "json",
+				text: text,
+				per_page: 20
+			},
+			jsonp: "jsoncallback"
+		});
+		deferred.addBoth(this.handlePhotoLoad);
+	},
+
+	loadTags: function(text){
+		console.log("loading tags ", text);
+		var _this = this;
+		
+		var url = "http://api.flickr.com/services/rest/?method=" +
+					"flickr.photos.search";
+
+		var deferred = dojo.io.script.get({
+			url: url,
+			content: { 
+				api_key: this.apiKey,
+				format: "json",
+				tags: text,
+				per_page: 20
+			},
+			jsonp: "jsoncallback"
+		});
+		deferred.addBoth(this.handlePhotoLoad);
+	},
+
+	handlePhotoLoad: function(res){
+		console.log("got photos", res);
+		if(res && res.photos && res.photos.photo){
+			var images = this.images = res.photos.photo;
+			
+			var urls = [];
+			
+			var baseUrl;
+			
+			for(var i = 0; i < images.length; i++){
+				baseUrl = "http://farm" 
+							+ images[i].farm 
+							+ ".static.flickr.com/"
+							+ images[i].server
+							+ "/"
+							+ images[i].id
+							+ "_"
+							+ images[i].secret;
+				urls.push({
+					large: baseUrl + ".jpg",
+					small: baseUrl + "_t.jpg",
+					thumb: baseUrl + "_s.jpg",
+					title: images[i].title
+				});
+			}
+			this.urls = urls;
+			this.index = 0;
+			
+			this.viewer.attr("items", urls);
+		}else{
+			this.viewer.attr("items", []);
+			console.log("didn't get photos");
+		}
+	}
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-image-view-assistant.js b/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-image-view-assistant.js
new file mode 100644
index 0000000..d867fb0
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-image-view-assistant.js
@@ -0,0 +1,170 @@
+dojo.provide("FlickrImageViewAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("FlickrImageViewAssistant", dojox.mobile.app.SceneAssistant, {
+  
+	apiKey: "8c6803164dbc395fb7131c9d54843627",
+	
+	setup: function(){
+	
+		// Instantiate widgets in the template HTML.
+		this.controller.parse();
+		
+		var viewer = this.viewer = dijit.byId("flickrImageView");
+		
+		var _this = this;
+		
+		this.handlePhotoLoad = dojo.hitch(this, this.handlePhotoLoad);
+		
+		var loadingDiv = this.controller.query(".loading")[0];
+		
+		// When the first image loads, hide the loading indicator.
+		var loadConn = dojo.connect(viewer, "onLoad", function(type, url, isSmall){
+			if(type == "center"){
+				dojo.disconnect(loadConn);
+				dojo.destroy(loadingDiv);
+				loadingDiv = null;
+			}
+		});
+		
+		var index = 1;
+		
+		var reportDiv = this.controller.query(".report")[0];
+		
+		this.connect(viewer, "onChange", function(direction){
+			_this.index += direction;
+			
+			// If we are not at the first image, set the leftUrl attribute
+			if(_this.index > 0){
+				viewer.attr("leftUrl", _this.urls[_this.index - 1]);
+			}
+		
+			// If we are not at the last image, set the rightUrl attribute
+			if(_this.index < _this.urls.length - 1){
+				viewer.attr("rightUrl", _this.urls[_this.index + 1]);
+			}
+			
+			reportDiv.innerHTML = 
+				(_this.index + 1) + " of " + _this.urls.length
+				+ " " + _this.urls[_this.index].title;
+		});
+	},
+  
+	activate: function(options){
+		
+		this.dataType = (options && options.type ? options.type : "interesting");
+		console.log("In main assistant activate, dataType = ", this.dataType, options);
+		
+		switch(this.dataType){
+			case "interesting":
+				this.loadInteresting();
+				break;
+			case "group":
+				this.loadGroup(options);
+				break;
+			case "data":
+				// Another scene has passed in a list of images
+				// and an initial index
+				this.useData(options.images, options.index || 0);
+				break;
+				
+		}
+	},
+	
+	useData: function(images, startIndex){
+		this.urls = images;
+		this.index = Math.min(images.length - 1, Math.max(0, startIndex));
+	
+		if (this.index > 0) {
+			this.viewer.attr("leftUrl", images[this.index - 1]);
+		}
+		this.viewer.attr("centerUrl", images[this.index]);
+		
+		if (this.index < images.length) {
+			this.viewer.attr("rightUrl", images[this.index + 1]);
+		}
+	},
+  
+	loadInteresting: function(){
+		console.log("loading interesting");
+		var _this = this;
+		
+		var url = "http://api.flickr.com/services/rest/?method=" +
+					"flickr.interestingness.getList";
+					
+
+		var deferred = dojo.io.script.get({
+			url: url,
+			content: { 
+				api_key: this.apiKey,
+				format: "json"
+			},
+			jsonp: "jsoncallback"
+		});
+		deferred.addBoth(this.handlePhotoLoad);
+	},
+
+	loadGroup: function(groupData){
+		console.log("loading group ", groupData);
+		var _this = this;
+		
+		var url = "http://api.flickr.com/services/rest/?method=" +
+					"flickr.groups.pools.getPhotos";
+					
+//		"http://api.flickr.com/services/rest/?method=flickr.groups.pools.getPhotos"
+//      + "&api_key=" + lib.API_KEY
+//      + "&group_id=" + group.id 
+//      + "&extras=owner_name" 
+//      + "&per_page=" + (perPage || 10)
+//      + "&format=json&nojsoncallback=1"
+
+		var deferred = dojo.io.script.get({
+			url: url,
+			content: { 
+				api_key: this.apiKey,
+				format: "json",
+				group_id: groupData.nsid,
+				per_page: 20
+			},
+			jsonp: "jsoncallback"
+		});
+		deferred.addBoth(this.handlePhotoLoad);
+	},
+	
+	
+	
+	handlePhotoLoad: function(res){
+		
+		if(res && res.photos && res.photos.photo){
+			var images = res.photos.photo;
+			
+			var urls = [];
+			
+			var baseUrl;
+			
+			for(var i = 0; i < images.length; i++){
+				baseUrl = "http://farm" 
+							+ images[i].farm 
+							+ ".static.flickr.com/"
+							+ images[i].server
+							+ "/"
+							+ images[i].id
+							+ "_"
+							+ images[i].secret;
+				urls.push({
+					large: baseUrl + "_m.jpg",
+					small: baseUrl + "_t.jpg",
+					title: images[i].title
+				});
+			}
+			this.urls = urls;
+			this.index = 0;
+		
+			this.viewer.attr("centerUrl", urls[0]);
+			this.viewer.attr("rightUrl", urls[1]);
+		}else{
+			console.log("didn't get photos");
+		}
+	}
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-search-group-assistant.js b/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-search-group-assistant.js
new file mode 100644
index 0000000..38ff4cb
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-search-group-assistant.js
@@ -0,0 +1,123 @@
+dojo.provide("FlickrSearchGroupAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("FlickrSearchGroupAssistant", dojox.mobile.app.SceneAssistant, {
+  
+	setup: function(){
+    
+		// Instantiate widgets in the template HTML.
+		this.controller.parse();
+		
+		// This api key should not be reused. You should get your own
+		// free api key from Flickr.
+		this.apiKey = "8c6803164dbc395fb7131c9d54843627";
+		
+		this.listWidget = dijit.byId("searchList");
+		this.textWidget = dijit.byId("searchTextInput");
+		
+		this.listWidget.attr("items", []);
+		
+		var _this = this;
+		
+		this.search = dojo.hitch(this, this.search);
+		this.handleGroupResults = dojo.hitch(this, this.handleGroupResults);
+		
+		// Listen for changes to the text widget.
+		// To ensure that onChange is called on every letter change,
+		// intermediateChanges is set to true on the widget
+		this.connect(this.textWidget, "onChange", function(value){
+		//		console.log("search value = ", value);
+			
+			if(!value || value.length == 0){
+				_this.listWidget.attr("items", []);
+				return;
+			}
+			
+			if(!_this.timer){
+				_this.timer = setTimeout(_this.search, 300);
+			}
+		});
+		
+		this.connect(this.listWidget, "onSelect", function(item, index, node){
+			console.log("select", arguments);
+			
+			_this.controller.stageController.pushScene("flickr-image-view",
+				dojo.mixin({type: "group"}, item));	
+		});
+	},
+  
+	activate: function(searchType){
+    
+		this.searchType = searchType;
+		
+		// Set the title of the screen based on the type of the search
+		if(searchType){
+			var sceneHeader = dijit.byId("searchHeader");
+			switch(searchType){
+				case "group":
+					sceneHeader.setLabel("Search Flickr Groups");
+					break;
+				case "user":
+					sceneHeader.setLabel("Search Flickr People");
+					break;
+				case "tag":
+					sceneHeader.setLabel("Search Flickr Tags");
+					break;
+			}
+		}
+		// Focus in the search text input
+		this.textWidget.focus();
+		
+		if(this.textWidget.attr("value")){
+			this.search();
+		}
+	},
+  
+	search: function(){
+	  	// summary:
+		//		Perform a search. Switch between group, user and tag search
+		
+	  	if(this.timer){
+			clearTimeout(this.timer);
+			this.timer = null;
+		}
+		
+		var searchText = this.textWidget.attr("value");
+		
+		if(!searchText || dojo.trim(searchText).length < 1){
+			this.listWidget.attr("items", []);
+			
+			console.log("NOT SEARCHING");
+			return;
+		}
+		
+		var url = "http://api.flickr.com/services/rest/?method=flickr.groups.search";
+		
+		var deferred = dojo.io.script.get({
+			url: url,
+			content: { 
+				api_key: this.apiKey,
+				format: "json",
+				text: searchText,
+				perPage: 10
+			},
+			jsonp: "jsoncallback"
+		});
+		deferred.addBoth(this.handleGroupResults);
+	},
+  
+	handleGroupResults: function(res){
+		var groups;
+		if(res && res.groups && res.groups.group){
+			groups = res.groups.group;
+			
+			for(var i = 0; i < groups.length; i++){
+				groups[i].label = groups[i].name;
+			}
+		}else{
+			groups = [];
+		}
+		this.listWidget.attr("items", groups);
+	}
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-search-selection-assistant.js b/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-search-selection-assistant.js
new file mode 100644
index 0000000..55477c8
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-search-selection-assistant.js
@@ -0,0 +1,54 @@
+dojo.provide("FlickrSearchSelectionAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("FlickrSearchSelectionAssistant", dojox.mobile.app.SceneAssistant, {
+  
+	setup: function(){
+    
+		// Instantiate widgets in the template HTML.
+		this.controller.parse();
+		
+		var scenes = [
+		  {
+		    label: "Interesting Photos",
+			scene: "flickr-image-view",
+			type: "interesting"
+		  },
+		  {
+		    label: "Search for Group",
+			scene: "flickr-search-group",
+			type: "group"
+		  },
+		  {
+		    label: "Search for Text",
+			scene: "flickr-image-thumb-view",
+			type: "text"
+		  },
+		  {
+		    label: "Search Tags",
+			scene: "flickr-image-thumb-view",
+			type: "tag"
+		  }
+		];
+		
+		var listWidget = dijit.byId("browseFlickrList");
+		listWidget.set("items", scenes);
+		
+		var _this = this;
+		
+		dojo.connect(listWidget, "onSelect", function(data, index, rowNode){
+			// Push the chosen scene, and pass in the data type, if any.
+			// The serach scene uses the "type" to determine
+			// what to search for
+			_this.controller.stageController.pushScene(data.scene, {
+				type: data.type
+			});
+		});
+  },
+  
+  activate: function(){
+    
+    
+  }
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-search-text-assistant.js b/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-search-text-assistant.js
new file mode 100644
index 0000000..b94e3d7
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/assistants/flickr-search-text-assistant.js
@@ -0,0 +1,119 @@
+dojo.provide("FlickrSearchTextAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("FlickrSearchTextAssistant", dojox.mobile.app.SceneAssistant, {
+  
+	setup: function(){
+    
+		// Instantiate widgets in the template HTML.
+		this.controller.parse();
+		
+		// This api key should not be reused. You should get your own
+		// free api key from Flickr.
+		this.apiKey = "8c6803164dbc395fb7131c9d54843627";
+		
+		this.listWidget = dijit.byId("searchList");
+		this.textWidget = dijit.byId("searchTextInput");
+		
+		this.listWidget.attr("items", []);
+		
+		var _this = this;
+		
+		this.search = dojo.hitch(this, this.search);
+		this.handleGroupResults = dojo.hitch(this, this.handleGroupResults);
+		
+		// Listen for changes to the text widget.
+		// To ensure that onChange is called on every letter change,
+		// intermediateChanges is set to true on the widget
+		this.connect(this.textWidget, "onChange", function(value){
+		//		console.log("search value = ", value);
+			
+			if(!value || value.length == 0){
+				_this.listWidget.attr("items", []);
+				return;
+			}
+			
+			if(!_this.timer){
+				_this.timer = setTimeout(_this.search, 300);
+			}
+		});
+		
+		this.connect(this.listWidget, "onSelect", function(item, index, node){
+			console.log("select", arguments);
+			
+			_this.controller.stageController.pushScene("flickr-image-view",
+				dojo.mixin({type: "group"}, item));	
+		});
+	},
+  
+	activate: function(searchType){
+    
+		this.searchType = searchType;
+		
+		// Set the title of the screen based on the type of the search
+		if(searchType){
+			var sceneHeader = dijit.byId("searchHeader");
+			switch(searchType){
+				case "group":
+					sceneHeader.setLabel("Search Flickr Groups");
+					break;
+				case "user":
+					sceneHeader.setLabel("Search Flickr People");
+					break;
+				case "tag":
+					sceneHeader.setLabel("Search Flickr Tags");
+					break;
+			}
+		}
+		// Focus in the search text input
+		dijit.byId("searchTextInput").focus();
+	},
+  
+	search: function(){
+	  	// summary:
+		//		Perform a search. Switch between group, user and tag search
+		
+	  	if(this.timer){
+			clearTimeout(this.timer);
+			this.timer = null;
+		}
+		
+		var searchText = this.textWidget.attr("value");
+		
+		if(!searchText || dojo.trim(searchText).length < 1){
+			this.listWidget.attr("items", []);
+			
+			console.log("NOT SEARCHING");
+			return;
+		}
+		
+		var url = "http://api.flickr.com/services/rest/?method=flickr.groups.search";
+		
+		var deferred = dojo.io.script.get({
+			url: url,
+			content: { 
+				api_key: this.apiKey,
+				format: "json",
+				text: searchText,
+				perPage: 10
+			},
+			jsonp: "jsoncallback"
+		});
+		deferred.addBoth(this.handleGroupResults);
+	},
+  
+	handleGroupResults: function(res){
+		var groups;
+		if(res && res.groups && res.groups.group){
+			groups = res.groups.group;
+			
+			for(var i = 0; i < groups.length; i++){
+				groups[i].label = groups[i].name;
+			}
+		}else{
+			groups = [];
+		}
+		this.listWidget.attr("items", groups);
+	}
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/assistants/image-view-assistant.js b/dojox/mobile/tests/imageControlsApp/app/assistants/image-view-assistant.js
new file mode 100644
index 0000000..e769d89
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/assistants/image-view-assistant.js
@@ -0,0 +1,92 @@
+dojo.provide("ImageViewAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("ImageViewAssistant", dojox.mobile.app.SceneAssistant, {
+  
+  setup: function(){
+    console.log("In main assistant setup");
+	
+	var images = [
+		"images/chris1_lg.jpg",
+		"images/chris2_lg.jpg",
+		"images/imageHoriz.jpg",
+		"images/imageVert.jpg",
+		"images/square.jpg"
+	];
+    
+    // Instantiate widgets in the template HTML.
+    this.controller.parse();
+    
+	var viewer = this.viewer = dijit.byId("imageView");
+	
+	this.viewer.attr("leftUrl", images[0]);
+	this.viewer.attr("centerUrl", images[1]);
+	this.viewer.attr("rightUrl", images[2]);
+	
+	dojo.connect(dijit.byId("decZoom"), "onClick", function(){
+		viewer.set("zoom", viewer.get("zoom") - 0.1);
+	});
+	dojo.connect(dijit.byId("incZoom"), "onClick", function(){
+		viewer.set("zoom", viewer.get("zoom") + 0.1);
+	});
+	dojo.connect(dijit.byId("resetZoom"), "onClick", function(){
+		viewer.set("zoom", 1);
+	});
+	dojo.connect(dijit.byId("toggleZoom"), "onClick", function(){
+		if(viewer.get("zoom") > 1){
+			console.log("setting animatedZoom to 1");
+			viewer.set("animatedZoom", 1);
+		}else{
+			console.log("setting animatedZoom to 2");
+			viewer.set("animatedZoom", 3);
+		}
+	});
+	dojo.connect(dijit.byId("panLeft"), "onClick", function(){
+		viewer.set("zoomCenter", {
+			x: viewer.get("zoomCenterX") - 20,
+			y: viewer.get("zoomCenterY")
+		});
+	});
+	dojo.connect(dijit.byId("panRight"), "onClick", function(){
+		viewer.set("zoomCenter", {
+			x: viewer.get("zoomCenterX") + 20,
+			y: viewer.get("zoomCenterY")
+		});
+	});
+	dojo.connect(dijit.byId("panUp"), "onClick", function(){
+		viewer.set("zoomCenter", {
+			x: viewer.get("zoomCenterX"),
+			y: viewer.get("zoomCenterY") - 20
+		});
+	});
+	dojo.connect(dijit.byId("panDown"), "onClick", function(){
+		viewer.set("zoomCenter", {
+			x: viewer.get("zoomCenterX"),
+			y: viewer.get("zoomCenterY") + 20
+		});
+	});
+	
+	var index = 1;
+	
+	dojo.connect(viewer, "onChange", function(direction){
+		index += direction;
+		
+		console.log("Index = " + index);
+		
+		if(index > 0){
+			viewer.attr("leftUrl", images[index - 1]);
+		}
+		if(index < images.length - 1){
+			viewer.attr("rightUrl", images[index + 1]);
+		}
+	});
+	
+  },
+  
+  activate: function(){
+    console.log("In main assistant activate");
+    
+    
+  }
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/assistants/main-assistant.js b/dojox/mobile/tests/imageControlsApp/app/assistants/main-assistant.js
new file mode 100644
index 0000000..2e8ab2e
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/assistants/main-assistant.js
@@ -0,0 +1,40 @@
+dojo.provide("MainAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("MainAssistant", dojox.mobile.app.SceneAssistant, {
+	setup: function(){
+		console.log("In main assistant setup");
+		
+		this.controller.parse();
+		
+		var scenes = [
+		  {
+		    label: "Simple ImageView Test",
+			scene: "image-view"
+		  },
+		  {
+		    label: "Flickr ImageView Test",
+			scene: "flickr-image-view"
+		  },
+		  {
+		    label: "Browse Flickr",
+			scene: "flickr-search-selection"
+		  }
+		];
+		
+		var listWidget = dijit.byId("listWidget");
+		listWidget.set("items", scenes);
+		
+		var _this = this;
+		
+		dojo.connect(listWidget, "onSelect", function(data, index, rowNode){
+		  _this.controller.stageController.pushScene(data.scene);
+		});
+  },
+  
+  activate: function(){
+    console.log("In main assistant activate");
+    
+    
+  }
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/flickr-image-thumb-view/flickr-image-thumb-view-scene.html b/dojox/mobile/tests/imageControlsApp/app/views/flickr-image-thumb-view/flickr-image-thumb-view-scene.html
new file mode 100644
index 0000000..55f37b4
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/flickr-image-thumb-view/flickr-image-thumb-view-scene.html
@@ -0,0 +1,17 @@
+<h1 dojoType="dojox.mobile.Heading" back="Back">
+	Flickr ImageThumbView
+</h1>
+<input 
+	dojoType="dojox.mobile.app.TextBox"
+	value="mountain"
+	class="fullWidthInput"
+	style="visibility: hidden;"
+	placeholder="Enter Search Text"
+	intermediateChanges="true"
+	id="searchTextThumbInput">
+<div 
+	dojoType="dojox.mobile.app.ImageThumbView" 
+	id="flickrImageThumbView" 
+	urlParam="thumb"
+	style="width:320px; height: 400px;">
+</div>
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/flickr-image-view/flickr-image-view-scene.html b/dojox/mobile/tests/imageControlsApp/app/views/flickr-image-view/flickr-image-view-scene.html
new file mode 100644
index 0000000..a74e241
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/flickr-image-view/flickr-image-view-scene.html
@@ -0,0 +1,10 @@
+<h1 dojoType="dojox.mobile.Heading" back="Back">
+	Flickr ImageView
+</h1>
+<div 
+	dojoType="dojox.mobile.app.ImageView" 
+	id="flickrImageView" 
+	style="width:320px; height: 400px;">
+</div>
+<div class="loading">Loading Flickr Data</div>
+<div class="report"></div>
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-group/emptyTemplate.html b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-group/emptyTemplate.html
new file mode 100644
index 0000000..322d8e8
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-group/emptyTemplate.html
@@ -0,0 +1,3 @@
+<div class="row first last">
+  Nothing Found
+</div>
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-group/flickr-search-group-scene.html b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-group/flickr-search-group-scene.html
new file mode 100644
index 0000000..c436e44
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-group/flickr-search-group-scene.html
@@ -0,0 +1,19 @@
+<h1 dojoType="dojox.mobile.Heading" back="Back" id="searchHeader">
+	Search Flickr
+</h1>
+<input 
+	dojoType="dojox.mobile.app.TextBox"
+	value="kinsale"
+	class="fullWidthInput"
+	placeholder="Enter Search Text"
+	intermediateChanges="true"
+	id="searchTextInput">
+	
+<div dojoType="dojox.mobile.RoundRect" shadow="true">
+  <div id="searchList" 
+  	  dojoType="dojox.mobile.app.List" 
+      class="iconList"
+      enableDelete="false"
+      itemTemplate="app/views/flickr-search-group/rowTemplate.html"
+      emptyTemplate="app/views/flickr-search-group/emptyTemplate.html"></div>
+</div>
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-group/rowTemplate.html b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-group/rowTemplate.html
new file mode 100644
index 0000000..ca07332
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-group/rowTemplate.html
@@ -0,0 +1,8 @@
+<div class="row mblListItem">
+  <a class="mblListItemAnchor">
+  	<div class="mblListItemTextBox">
+		${label}
+  	</div>
+	<div class="mblArrow"></div>
+  </a>
+</div>
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-selection/flickr-search-selection-scene.html b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-selection/flickr-search-selection-scene.html
new file mode 100644
index 0000000..58a16c0
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-selection/flickr-search-selection-scene.html
@@ -0,0 +1,7 @@
+<h1 dojoType="dojox.mobile.Heading" back="Back">
+	Browse Flickr
+</h1>
+<div dojoType="dojox.mobile.RoundRect" shadow="true">
+  <div id="browseFlickrList" dojoType="dojox.mobile.app.List"
+      itemTemplate="app/views/flickr-search-selection/rowTemplate.html"></div>
+</div>
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-selection/rowTemplate.html b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-selection/rowTemplate.html
new file mode 100644
index 0000000..ca07332
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-selection/rowTemplate.html
@@ -0,0 +1,8 @@
+<div class="row mblListItem">
+  <a class="mblListItemAnchor">
+  	<div class="mblListItemTextBox">
+		${label}
+  	</div>
+	<div class="mblArrow"></div>
+  </a>
+</div>
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-text/emptyTemplate.html b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-text/emptyTemplate.html
new file mode 100644
index 0000000..322d8e8
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-text/emptyTemplate.html
@@ -0,0 +1,3 @@
+<div class="row first last">
+  Nothing Found
+</div>
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-text/flickr-search-group-scene.html b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-text/flickr-search-group-scene.html
new file mode 100644
index 0000000..9e161b4
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-text/flickr-search-group-scene.html
@@ -0,0 +1,19 @@
+<h1 dojoType="dojox.mobile.Heading" back="Back" id="searchHeader">
+	Search Flickr
+</h1>
+<input 
+	dojoType="dojox.mobile.app.TextBox"
+	value=""
+	class="fullWidthInput"
+	placeholder="Enter Search Text"
+	intermediateChanges="true"
+	id="searchTextInput">
+	
+<div dojoType="dojox.mobile.RoundRect" shadow="true">
+  <div id="searchList" 
+  	  dojoType="dojox.mobile.app.List" 
+      class="iconList"
+      enableDelete="false"
+      itemTemplate="app/views/flickr-search-group/rowTemplate.html"
+      emptyTemplate="app/views/flickr-search-group/emptyTemplate.html"></div>
+</div>
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-text/rowTemplate.html b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-text/rowTemplate.html
new file mode 100644
index 0000000..1483081
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/flickr-search-text/rowTemplate.html
@@ -0,0 +1,15 @@
+<div class="row">
+  <table>
+    <tr>
+      <td style="width: 100%;">
+        ${label}
+      </td>
+      <td>
+          <span class="listBtn noclick ${button1Cls}">${buttonLabel1}</span>
+      </td>
+      <td>
+          <span class="listBtn noclick ${button2Cls}">${buttonLabel2}</span>
+      </td>
+    </tr>
+  </table>
+</div>
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/image-view/image-view-scene.html b/dojox/mobile/tests/imageControlsApp/app/views/image-view/image-view-scene.html
new file mode 100644
index 0000000..51a655f
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/image-view/image-view-scene.html
@@ -0,0 +1,23 @@
+<h1 dojoType="dojox.mobile.Heading" back="Back" id="imageViewHeader">
+	ImageView Widget
+</h1>
+
+<div 
+	dojoType="dojox.mobile.app.ImageView" 
+	id="imageView" 
+	style="width:300px; height: 300px;">
+</div>
+<div>
+	Zoom
+	<button id="decZoom" dojoType="dojox.mobile.Button">--</button>
+	<button id="incZoom" dojoType="dojox.mobile.Button">++</button>
+	<button id="resetZoom" dojoType="dojox.mobile.Button">Reset</button>
+	<button id="toggleZoom" dojoType="dojox.mobile.Button">Toggle</button>
+</div>
+<div>
+	Pan
+	<button id="panLeft" dojoType="dojox.mobile.Button"><</button>
+	<button id="panRight" dojoType="dojox.mobile.Button">></button>
+	<button id="panUp" dojoType="dojox.mobile.Button">^</button>
+	<button id="panDown" dojoType="dojox.mobile.Button">v</button>
+</div>
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/main/main-scene.html b/dojox/mobile/tests/imageControlsApp/app/views/main/main-scene.html
new file mode 100644
index 0000000..98300dc
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/main/main-scene.html
@@ -0,0 +1,6 @@
+<h1 dojoType="dojox.mobile.Heading" id="heading1">Choose Scene</h1>
+
+<div dojoType="dojox.mobile.RoundRect" shadow="true">
+  <div id="listWidget" dojoType="dojox.mobile.app.List"
+      itemTemplate="app/views/main/rowTemplate.html"></div>
+</div>
\ No newline at end of file
diff --git a/dojox/mobile/tests/imageControlsApp/app/views/main/rowTemplate.html b/dojox/mobile/tests/imageControlsApp/app/views/main/rowTemplate.html
new file mode 100644
index 0000000..ca07332
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/app/views/main/rowTemplate.html
@@ -0,0 +1,8 @@
+<div class="row mblListItem">
+  <a class="mblListItemAnchor">
+  	<div class="mblListItemTextBox">
+		${label}
+  	</div>
+	<div class="mblArrow"></div>
+  </a>
+</div>
diff --git a/dojox/mobile/tests/imageControlsApp/images/chris1_lg.jpg b/dojox/mobile/tests/imageControlsApp/images/chris1_lg.jpg
new file mode 100755
index 0000000..8999f0a
Binary files /dev/null and b/dojox/mobile/tests/imageControlsApp/images/chris1_lg.jpg differ
diff --git a/dojox/mobile/tests/imageControlsApp/images/chris2_lg.jpg b/dojox/mobile/tests/imageControlsApp/images/chris2_lg.jpg
new file mode 100755
index 0000000..fca25d3
Binary files /dev/null and b/dojox/mobile/tests/imageControlsApp/images/chris2_lg.jpg differ
diff --git a/dojox/mobile/tests/imageControlsApp/images/imageHoriz.jpg b/dojox/mobile/tests/imageControlsApp/images/imageHoriz.jpg
new file mode 100755
index 0000000..3948416
Binary files /dev/null and b/dojox/mobile/tests/imageControlsApp/images/imageHoriz.jpg differ
diff --git a/dojox/mobile/tests/imageControlsApp/images/imageVert.jpg b/dojox/mobile/tests/imageControlsApp/images/imageVert.jpg
new file mode 100755
index 0000000..1652338
Binary files /dev/null and b/dojox/mobile/tests/imageControlsApp/images/imageVert.jpg differ
diff --git a/dojox/mobile/tests/imageControlsApp/images/square.jpg b/dojox/mobile/tests/imageControlsApp/images/square.jpg
new file mode 100755
index 0000000..f8b6761
Binary files /dev/null and b/dojox/mobile/tests/imageControlsApp/images/square.jpg differ
diff --git a/dojox/mobile/tests/imageControlsApp/index.html b/dojox/mobile/tests/imageControlsApp/index.html
new file mode 100644
index 0000000..dda8384
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/index.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<link href="../../themes/iphone/iphone-app.css" rel="stylesheet">
+		<link href="styles/styles.css" rel="stylesheet">
+		<style>
+		.lnk {
+			font-size: 17px;
+			color: cyan;
+			text-decoration: none;
+		}
+		</style>
+		<script type="text/javascript" src="../../../../dojo/dojo.js" 
+				djConfig="parseOnLoad: false, mobileAnim:'slide'"></script>
+    
+    <!-- 
+      Include the files directly, as some mobile operating systems do not
+      allow synchronous XHR, and therefore break dojo.require
+    -->
+		<script type="text/javascript" src="../../../mobile/app.js"></script>
+		<script type="text/javascript" src="../../../../dojo/io/script.js"></script>
+		<script language="JavaScript" type="text/javascript">
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.app.compat");
+      
+			var appInfo = {
+				id: "org.dojo.imageWidgetApp",
+				title: "Mobile App With Image Widgets",
+				initialScene: "main"
+			};
+			
+			dojo.ready(dojox.mobile.app.init);
+		</script>
+	</head>
+	<body>
+		
+	</body>
+</html>
diff --git a/dojox/mobile/tests/imageControlsApp/styles/styles.css b/dojox/mobile/tests/imageControlsApp/styles/styles.css
new file mode 100644
index 0000000..2e64dc8
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/styles/styles.css
@@ -0,0 +1,13 @@
+.loading {
+	position: absolute;
+	top: 200px;
+	left: 50px;
+	font-size: larger;
+	color: blue;
+}
+
+.fullWidthInput {
+	padding-left: 10px;
+	padding-right: 10px;
+	width: 100%;
+}
diff --git a/dojox/mobile/tests/imageControlsApp/view-resources.json b/dojox/mobile/tests/imageControlsApp/view-resources.json
new file mode 100644
index 0000000..e79a3a6
--- /dev/null
+++ b/dojox/mobile/tests/imageControlsApp/view-resources.json
@@ -0,0 +1,14 @@
+[
+	{
+		scene: "flickr-image-thumb-view",
+		module: "dojo.io.script"
+	},
+	{
+		scene: "flickr-image-view",
+		module: "dojo.io.script"
+	},
+	{
+		scene: "flickr-search-group",
+		module: "dojo.io.script"
+	}
+]
diff --git a/dojox/mobile/tests/images/a-icon-1-41x41.png b/dojox/mobile/tests/images/a-icon-1-41x41.png
new file mode 100755
index 0000000..0e94b75
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-1-41x41.png differ
diff --git a/dojox/mobile/tests/images/a-icon-1.png b/dojox/mobile/tests/images/a-icon-1.png
new file mode 100755
index 0000000..5f28394
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-1.png differ
diff --git a/dojox/mobile/tests/images/a-icon-10.png b/dojox/mobile/tests/images/a-icon-10.png
new file mode 100644
index 0000000..b3df995
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-10.png differ
diff --git a/dojox/mobile/tests/images/a-icon-11.png b/dojox/mobile/tests/images/a-icon-11.png
new file mode 100644
index 0000000..307b8e3
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-11.png differ
diff --git a/dojox/mobile/tests/images/a-icon-12.png b/dojox/mobile/tests/images/a-icon-12.png
new file mode 100644
index 0000000..425cadb
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-12.png differ
diff --git a/dojox/mobile/tests/images/a-icon-13.png b/dojox/mobile/tests/images/a-icon-13.png
new file mode 100644
index 0000000..7244dbe
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-13.png differ
diff --git a/dojox/mobile/tests/images/a-icon-14.png b/dojox/mobile/tests/images/a-icon-14.png
new file mode 100644
index 0000000..c8afcec
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-14.png differ
diff --git a/dojox/mobile/tests/images/a-icon-15.png b/dojox/mobile/tests/images/a-icon-15.png
new file mode 100644
index 0000000..49812a3
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-15.png differ
diff --git a/dojox/mobile/tests/images/a-icon-16.png b/dojox/mobile/tests/images/a-icon-16.png
new file mode 100644
index 0000000..8208beb
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-16.png differ
diff --git a/dojox/mobile/tests/images/a-icon-17.png b/dojox/mobile/tests/images/a-icon-17.png
new file mode 100644
index 0000000..533870e
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-17.png differ
diff --git a/dojox/mobile/tests/images/a-icon-18.png b/dojox/mobile/tests/images/a-icon-18.png
new file mode 100644
index 0000000..d52419a
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-18.png differ
diff --git a/dojox/mobile/tests/images/a-icon-2-41x41.png b/dojox/mobile/tests/images/a-icon-2-41x41.png
new file mode 100755
index 0000000..df8aaaf
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-2-41x41.png differ
diff --git a/dojox/mobile/tests/images/a-icon-2.png b/dojox/mobile/tests/images/a-icon-2.png
new file mode 100755
index 0000000..c457062
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-2.png differ
diff --git a/dojox/mobile/tests/images/a-icon-3.png b/dojox/mobile/tests/images/a-icon-3.png
new file mode 100755
index 0000000..77671cb
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-3.png differ
diff --git a/dojox/mobile/tests/images/a-icon-4.png b/dojox/mobile/tests/images/a-icon-4.png
new file mode 100755
index 0000000..c7df122
Binary files /dev/null and b/dojox/mobile/tests/images/a-icon-4.png differ
diff --git a/dojox/mobile/tests/images/i-icon-1.png b/dojox/mobile/tests/images/i-icon-1.png
new file mode 100755
index 0000000..8cbf494
Binary files /dev/null and b/dojox/mobile/tests/images/i-icon-1.png differ
diff --git a/dojox/mobile/tests/images/i-icon-10.png b/dojox/mobile/tests/images/i-icon-10.png
new file mode 100755
index 0000000..65a7909
Binary files /dev/null and b/dojox/mobile/tests/images/i-icon-10.png differ
diff --git a/dojox/mobile/tests/images/i-icon-2.png b/dojox/mobile/tests/images/i-icon-2.png
new file mode 100755
index 0000000..1965b3e
Binary files /dev/null and b/dojox/mobile/tests/images/i-icon-2.png differ
diff --git a/dojox/mobile/tests/images/i-icon-3.png b/dojox/mobile/tests/images/i-icon-3.png
new file mode 100755
index 0000000..3450131
Binary files /dev/null and b/dojox/mobile/tests/images/i-icon-3.png differ
diff --git a/dojox/mobile/tests/images/i-icon-4.png b/dojox/mobile/tests/images/i-icon-4.png
new file mode 100755
index 0000000..403990b
Binary files /dev/null and b/dojox/mobile/tests/images/i-icon-4.png differ
diff --git a/dojox/mobile/tests/images/i-icon-5.png b/dojox/mobile/tests/images/i-icon-5.png
new file mode 100755
index 0000000..afd1199
Binary files /dev/null and b/dojox/mobile/tests/images/i-icon-5.png differ
diff --git a/dojox/mobile/tests/images/i-icon-6.png b/dojox/mobile/tests/images/i-icon-6.png
new file mode 100755
index 0000000..24d141b
Binary files /dev/null and b/dojox/mobile/tests/images/i-icon-6.png differ
diff --git a/dojox/mobile/tests/images/i-icon-7.png b/dojox/mobile/tests/images/i-icon-7.png
new file mode 100755
index 0000000..48b239f
Binary files /dev/null and b/dojox/mobile/tests/images/i-icon-7.png differ
diff --git a/dojox/mobile/tests/images/i-icon-8.png b/dojox/mobile/tests/images/i-icon-8.png
new file mode 100755
index 0000000..0880428
Binary files /dev/null and b/dojox/mobile/tests/images/i-icon-8.png differ
diff --git a/dojox/mobile/tests/images/i-icon-9.png b/dojox/mobile/tests/images/i-icon-9.png
new file mode 100755
index 0000000..e709a42
Binary files /dev/null and b/dojox/mobile/tests/images/i-icon-9.png differ
diff --git a/dojox/mobile/tests/images/i-icon-all.png b/dojox/mobile/tests/images/i-icon-all.png
new file mode 100755
index 0000000..d891dbd
Binary files /dev/null and b/dojox/mobile/tests/images/i-icon-all.png differ
diff --git a/dojox/mobile/tests/images/icon-1.png b/dojox/mobile/tests/images/icon-1.png
new file mode 100755
index 0000000..26dde5d
Binary files /dev/null and b/dojox/mobile/tests/images/icon-1.png differ
diff --git a/dojox/mobile/tests/images/not-images.png b/dojox/mobile/tests/images/not-images.png
new file mode 100755
index 0000000..7aee19a
Binary files /dev/null and b/dojox/mobile/tests/images/not-images.png differ
diff --git a/dojox/mobile/tests/images/red-button-bg.png b/dojox/mobile/tests/images/red-button-bg.png
new file mode 100755
index 0000000..5749018
Binary files /dev/null and b/dojox/mobile/tests/images/red-button-bg.png differ
diff --git a/dojox/mobile/tests/images/red-button-sel-bg.png b/dojox/mobile/tests/images/red-button-sel-bg.png
new file mode 100755
index 0000000..c5ba62a
Binary files /dev/null and b/dojox/mobile/tests/images/red-button-sel-bg.png differ
diff --git a/dojox/mobile/tests/images/widget-bg.png b/dojox/mobile/tests/images/widget-bg.png
new file mode 100755
index 0000000..144dd00
Binary files /dev/null and b/dojox/mobile/tests/images/widget-bg.png differ
diff --git a/dojox/mobile/tests/index.html b/dojox/mobile/tests/index.html
new file mode 100644
index 0000000..3222928
--- /dev/null
+++ b/dojox/mobile/tests/index.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<title>djMobile</title>
+	</head>
+	<body>
+		<a href="test_iPhone-Animation.html">test_iPhone-Animation.html</a><br>
+		<a href="test_iPhone-Button.html">test_iPhone-Button.html</a><br>
+		<a href="test_iPhone-ButtonList.html">test_iPhone-ButtonList.html</a><br>
+		<a href="test_iPhone-EdgeToEdge.html">test_iPhone-EdgeToEdge.html</a><br>
+		<a href="test_iPhone-EdgeToEdgeCategory.html">test_iPhone-EdgeToEdgeCategory.html</a><br>
+		<a href="test_iPhone-Heading.html">test_iPhone-Heading.html</a><br>
+		<a href="test_iPhone-Icon.html">test_iPhone-Icon.html</a><br>
+		<a href="test_iPhone-IconMulti.html">test_iPhone-IconMulti.html</a><br>
+		<a href="test_iPhone-IconSingle.html">test_iPhone-IconSingle.html</a><br>
+		<a href="test_iPhone-IconSingleBelow.html">test_iPhone-IconSingleBelow.html</a><br>
+		<a href="test_iPhone-ResultList.html">test_iPhone-ResultList.html</a><br>
+		<a href="test_iPhone-RoundRect.html">test_iPhone-RoundRect.html</a><br>
+		<a href="test_iPhone-RoundRectList.html">test_iPhone-RoundRectList.html</a><br>
+		<a href="test_iPhone-Settings.html">test_iPhone-Settings.html</a><br>
+		<a href="test_iPhone-Switch.html">test_iPhone-Switch.html</a><br>
+		<a href="test_iPhone-TabContainer.html">test_iPhone-TabContainer.html</a><br>
+		<a href="test_iPhone-VariableHeightList.html">test_iPhone-VariableHeightList.html</a><br>
+		<hr>
+		<a href="test_Android-ButtonList.html">test_Android-ButtonList.html</a><br>
+		<a href="test_Android-EdgeToEdge.html">test_Android-EdgeToEdge.html</a><br>
+		<a href="test_Android-EdgeToEdgeCategory.html">test_Android-EdgeToEdgeCategory.html</a><br>
+		<a href="test_Android-Icon.html">test_Android-Icon.html</a><br>
+		<a href="test_Android-RoundRectList.html">test_Android-RoundRectList.html</a><br>
+		<a href="test_Android-Settings.html">test_Android-Settings.html</a><br>
+		<a href="test_Android-Switch.html">test_Android-Switch.html</a><br>
+		<a href="test_Android-TabContainer.html">test_Android-TabContainer.html</a><br>
+		<a href="test_Android-VariableHeightList.html">test_Android-VariableHeightList.html</a><br>
+		<hr>
+		<a href="test_buttons.html">test_buttons.html</a><br>
+		<a href="test_bookmarkable.html">test_bookmarkable.html</a><br>
+		<a href="test_hash-parameter.html">test_hash-parameter.html</a><br>
+		<a href="test_progress-indicator.html">test_progress-indicator.html</a><br>
+		<a href="test_dynamic-items.html">test_dynamic-items.html</a><br>
+		<a href="test_dynamic-icons.html">test_dynamic-icons.html</a><br>
+		<a href="test_dynamic-view.html">test_dynamic-view.html</a><br>
+		<a href="test_ajax-html.html">test_ajax-html.html</a><br>
+		<a href="test_ajax-json.html">test_ajax-json.html</a><br>
+		<a href="test_anchor-label.html">test_anchor-label.html</a><br>
+		<hr>
+		<a href="simpleApp">Simple Full App</a><br>
+		<a href="simpleListApp">Simple Full App Using a List</a><br>
+		<a href="multiSceneApp">Multi-Scene Full App</a><br>
+		<a href="complexListApp">Full App Using a Complex List</a><br>
+		<a href="dialogApp">Full App with Dialogs</a><br>
+		<a href="inputApp">Full App with Form Inputs</a><br>
+		<a href="imageControlsApp">Full App with Image Widgets</a><br>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/inputApp/app/assistants/text-input-assistant.js b/dojox/mobile/tests/inputApp/app/assistants/text-input-assistant.js
new file mode 100644
index 0000000..cd69687
--- /dev/null
+++ b/dojox/mobile/tests/inputApp/app/assistants/text-input-assistant.js
@@ -0,0 +1,21 @@
+dojo.provide("TextInputAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("TextInputAssistant", dojox.mobile.app.SceneAssistant, {
+  
+  setup: function(){
+    console.log("In main assistant setup");
+    
+    // Instantiate widgets in the template HTML.
+    this.controller.parse();
+    
+    
+  },
+  
+  activate: function(){
+    console.log("In main assistant activate");
+    
+    
+  }
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/inputApp/app/views/text-input/text-input-scene.html b/dojox/mobile/tests/inputApp/app/views/text-input/text-input-scene.html
new file mode 100644
index 0000000..9e9366b
--- /dev/null
+++ b/dojox/mobile/tests/inputApp/app/views/text-input/text-input-scene.html
@@ -0,0 +1,50 @@
+<h1 dojoType="dojox.mobile.Heading">Text Inputs</h1>
+
+<div>
+	Simple Text Input	
+	<input dojoType="dojox.mobile.app.TextBox" value="Joe Bloggs" id="simpleTextInput">
+</div>
+<div>
+	Uppercase Text Input 
+	<input 	dojoType="dojox.mobile.app.TextBox" 
+			value="Joe Bloggs"
+			uppercase="true" 
+			id="upperCaseTextInput">
+</div>
+<div>
+	Lowercase Text Input 
+	<input 	dojoType="dojox.mobile.app.TextBox" 
+			value="Joe Bloggs"
+			lowercase="true" 
+			id="lowerCaseTextInput">
+</div>
+<div>
+	Propercase Text Input 
+	<input 	dojoType="dojox.mobile.app.TextBox" 
+			value="Joe Bloggs"
+			propercase="true" 
+			id="properCaseTextInput">
+</div>
+<div>
+	Max Length = 6 Text Input 
+	<input 	dojoType="dojox.mobile.app.TextBox" 
+			value="Joe Bloggs"
+			maxLength="6" 
+			id="maxLengthTextInput">
+</div>
+<div>
+	PlaceHolder Text Input 
+	<input 	dojoType="dojox.mobile.app.TextBox" 
+			value=""
+			placeHolder="Enter Name"
+			maxLength="6" 
+			id="placeholderTextInput">
+</div>
+<div>
+	Select On Click Text Input 
+	<input 	dojoType="dojox.mobile.app.TextBox" 
+			value="Joe Bloggs"
+			selectOnClick="true" 
+			id="selectOnClickTextInput">
+</div>
+
diff --git a/dojox/mobile/tests/inputApp/index.html b/dojox/mobile/tests/inputApp/index.html
new file mode 100644
index 0000000..c467e6c
--- /dev/null
+++ b/dojox/mobile/tests/inputApp/index.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<link href="../../themes/iphone/iphone-app.css" rel="stylesheet">
+		<style>
+		.lnk {
+			font-size: 17px;
+			color: cyan;
+			text-decoration: none;
+		}
+		</style>
+		
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="parseOnLoad: false"></script>
+    
+    <!-- 
+      Include the files directly, as some mobile operating systems do not
+      allow synchronous XHR, and therefore break dojo.require
+    -->
+		<script type="text/javascript" src="../../../mobile/app.js"></script>
+		<script language="JavaScript" type="text/javascript">
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.app.compat");
+      
+			var appInfo = {
+				id: "org.dojo.inputApp",
+				title: "Mobile App With Inputs",
+				initialScene: "text-input"
+			};
+
+			dojo.ready(dojox.mobile.app.init);
+		</script>
+	</head>
+	<body>
+		
+	</body>
+</html>
diff --git a/dojox/mobile/tests/multiSceneApp/app/assistants/main-assistant.js b/dojox/mobile/tests/multiSceneApp/app/assistants/main-assistant.js
new file mode 100644
index 0000000..5f4d132
--- /dev/null
+++ b/dojox/mobile/tests/multiSceneApp/app/assistants/main-assistant.js
@@ -0,0 +1,41 @@
+dojo.provide("MainAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("MainAssistant", dojox.mobile.app.SceneAssistant, {
+  
+  setup: function(){
+    console.log("In main assistant setup");
+    
+    var appInfoNode = this.controller.query(".appInfoArea")[0];
+    
+    appInfoNode.innerHTML = 
+      "This app has the following info: \n" 
+        + dojo.toJson(dojox.mobile.app.info, true).split("\t").join("  ");
+        
+    // Instantiate widgets in the template HTML.
+    this.controller.parse();
+    
+    var _this = this;
+    var launcher = dijit.byId("secondSceneLauncher");
+    
+    console.log("launcher = " , launcher, " node = ", this.domNode);
+    this.connect(launcher, "onClick", function(){
+      console.log("launching the second scene");
+      
+      _this.controller.stageController.pushScene("second", "Came from Main Scene");
+    });
+  },
+  
+  activate: function(data){
+    console.log("In main assistant activate");
+    
+    var node = this.controller.query(".inputData")[0];
+    if(data) {
+      node.innerHTML = "Scene got the data: " + data;
+    } else {
+      node.innerHTML = "Scene did not receive data";
+    }
+    
+  }
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/multiSceneApp/app/assistants/second-assistant.js b/dojox/mobile/tests/multiSceneApp/app/assistants/second-assistant.js
new file mode 100644
index 0000000..e07fa1d
--- /dev/null
+++ b/dojox/mobile/tests/multiSceneApp/app/assistants/second-assistant.js
@@ -0,0 +1,32 @@
+dojo.provide("SecondAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("SecondAssistant", dojox.mobile.app.SceneAssistant, {
+  
+  setup: function(){
+    console.log("In second assistant setup");
+    
+    // Instantiate widgets in the template HTML.
+    this.controller.parse();
+    
+    var _this = this;
+    var launcher = dijit.byId("secondSceneLauncher");
+    this.connect(dijit.byId("btn1"), "onClick", function(){
+      _this.controller.stageController.popScene("Button 1");
+    });
+    this.connect(dijit.byId("btn2"), "onClick", function(){
+      _this.controller.stageController.pushScene("third", "Came from second scene");
+    });
+  },
+  
+  activate: function(data){
+    console.log("In main assistant activate");
+    var node = this.controller.query(".inputData")[0];
+    if(data) {
+      node.innerHTML = "Scene got the data: " + data;
+    } else {
+      node.innerHTML = "Scene did not receive data";
+    }
+  }
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/multiSceneApp/app/assistants/third-assistant.js b/dojox/mobile/tests/multiSceneApp/app/assistants/third-assistant.js
new file mode 100644
index 0000000..bf58f3b
--- /dev/null
+++ b/dojox/mobile/tests/multiSceneApp/app/assistants/third-assistant.js
@@ -0,0 +1,33 @@
+dojo.provide("ThirdAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("ThirdAssistant", dojox.mobile.app.SceneAssistant, {
+  
+  setup: function(){
+    console.log("In third assistant setup");
+    
+    // Instantiate widgets in the template HTML.
+    this.controller.parse();
+    
+    var _this = this;
+    var launcher = dijit.byId("secondSceneLauncher");
+    this.connect(dijit.byId("btn3"), "onClick", function(){
+      _this.controller.stageController.popScenesTo("main", "From Third Scene");
+    });
+    this.connect(dijit.byId("btn4"), "onClick", function(){
+      _this.controller.stageController.popScene("From Third Scene");
+    });
+  },
+  
+  activate: function(data){
+    console.log("In third assistant activate");
+    var node = this.controller.query(".inputData")[0];
+    if(data) {
+      node.innerHTML = "Scene got the data: " + data;
+    } else {
+      node.innerHTML = "Scene did not receive data";
+    }
+    
+  }
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/multiSceneApp/app/views/main/main-scene.html b/dojox/mobile/tests/multiSceneApp/app/views/main/main-scene.html
new file mode 100644
index 0000000..9c15d0d
--- /dev/null
+++ b/dojox/mobile/tests/multiSceneApp/app/views/main/main-scene.html
@@ -0,0 +1,16 @@
+<h1 dojoType="dojox.mobile.Heading">Main Scene</h1>
+<div dojoType="dojox.mobile.RoundRect" shadow="true">
+  This is the content of the main scene. Use the buttons in each scene to move between
+  the multiple scenes, or views, contained in the app.
+  <pre class="appInfoArea"></pre>
+</div>
+<div class="inputData">
+  
+</div>
+<ul dojoType="dojox.mobile.RoundRectList" iconBase="../images/i-icon-all.png">
+	<li dojoType="dojox.mobile.ListItem" iconPos="0,0,29,29" 
+        rightText="Go" id="secondSceneLauncher" clickable="true">
+		Next Scene
+	</li>
+</ul>
+
diff --git a/dojox/mobile/tests/multiSceneApp/app/views/second/second-scene.html b/dojox/mobile/tests/multiSceneApp/app/views/second/second-scene.html
new file mode 100644
index 0000000..e663485
--- /dev/null
+++ b/dojox/mobile/tests/multiSceneApp/app/views/second/second-scene.html
@@ -0,0 +1,12 @@
+<h1 dojoType="dojox.mobile.Heading"  back="Back">Second Scene</h1>
+<div dojoType="dojox.mobile.RoundRect" shadow="true">
+  This is the second scene. Tap a button to go back to the first scene
+</div>
+
+<button id="btn1" dojoType="dojox.mobile.Button" style="width:120px">To First Scene</button>
+<p></p>
+<button id="btn2" dojoType="dojox.mobile.Button" 
+  btnClass="mblRedButton" style="width:120px">To Third Scene</button>
+<div class="inputData">
+  
+</div>
\ No newline at end of file
diff --git a/dojox/mobile/tests/multiSceneApp/app/views/third/third-scene.html b/dojox/mobile/tests/multiSceneApp/app/views/third/third-scene.html
new file mode 100644
index 0000000..a00f748
--- /dev/null
+++ b/dojox/mobile/tests/multiSceneApp/app/views/third/third-scene.html
@@ -0,0 +1,13 @@
+<h1 dojoType="dojox.mobile.Heading" back="Back">Third Scene</h1>
+<div dojoType="dojox.mobile.RoundRect" shadow="true">
+  This is the third scene. 
+  Tap the first button to jump back to the first scene,
+  or the second button to go back one scene to the second scene.
+</div>
+
+<button id="btn3" dojoType="dojox.mobile.Button" style="width:120px">To 1st Scene</button>
+<button id="btn4" dojoType="dojox.mobile.Button" 
+    btnClass="mblRedButton" style="width:120px">To 2nd Scene</button>
+<div class="inputData">
+  
+</div>
\ No newline at end of file
diff --git a/dojox/mobile/tests/multiSceneApp/index.html b/dojox/mobile/tests/multiSceneApp/index.html
new file mode 100644
index 0000000..3da165a
--- /dev/null
+++ b/dojox/mobile/tests/multiSceneApp/index.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<link href="../../themes/iphone/iphone-app.css" rel="stylesheet">
+		<style>
+		.lnk {
+			font-size: 17px;
+			color: cyan;
+			text-decoration: none;
+		}
+		</style>
+		<script type="text/javascript" src="../../../../dojo/dojo.js" 
+			djConfig="parseOnLoad: false,mobileAnim:'slide'"></script>
+    
+		<!-- 
+			Include the files directly, as some mobile operating systems do not
+			allow synchronous XHR, and therefore break dojo.require
+		-->
+		<script type="text/javascript" src="../../../mobile/app.js"></script>
+		<script language="JavaScript" type="text/javascript">
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.app.compat");
+      
+			var appInfo = {
+				id: "org.dojo.multiSceneApp",
+				title: "Multi Scene Mobile App",
+				initialScene: "main"
+			};
+      
+			dojo.ready(dojox.mobile.app.init);
+		</script>
+	</head>
+	<body>
+		
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mobile/tests/simpleApp/app/assistants/main-assistant.js b/dojox/mobile/tests/simpleApp/app/assistants/main-assistant.js
new file mode 100644
index 0000000..2838cd1
--- /dev/null
+++ b/dojox/mobile/tests/simpleApp/app/assistants/main-assistant.js
@@ -0,0 +1,23 @@
+dojo.provide("MainAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("MainAssistant", dojox.mobile.app.SceneAssistant, {
+  
+  setup: function(){
+    console.log("In main assistant setup");
+    
+    var appInfoNode = this.controller.query(".appInfoArea")[0];
+    
+    appInfoNode.innerHTML = 
+      "This app has the following info: \n" 
+        + dojo.toJson(dojox.mobile.app.info, true)
+    
+  },
+  
+  activate: function(){
+    console.log("In main assistant activate");
+    
+    
+  }
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/simpleApp/app/views/main/main-scene.html b/dojox/mobile/tests/simpleApp/app/views/main/main-scene.html
new file mode 100644
index 0000000..e251c56
--- /dev/null
+++ b/dojox/mobile/tests/simpleApp/app/views/main/main-scene.html
@@ -0,0 +1,3 @@
+<div>This is the content of the main scene</div>
+
+<pre class="appInfoArea"></pre>
diff --git a/dojox/mobile/tests/simpleApp/index.html b/dojox/mobile/tests/simpleApp/index.html
new file mode 100644
index 0000000..2bfe9d1
--- /dev/null
+++ b/dojox/mobile/tests/simpleApp/index.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<link href="../../themes/iphone/iphone-app.css" rel="stylesheet">
+		<style>
+		.lnk {
+			font-size: 17px;
+			color: cyan;
+			text-decoration: none;
+		}
+		</style>
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="parseOnLoad: false"></script>
+    
+		<!-- 
+			Include the files directly, as some mobile operating systems do not
+			allow synchronous XHR, and therefore break dojo.require
+		-->
+		<script type="text/javascript" src="../../../mobile/app.js"></script>
+		<script language="JavaScript" type="text/javascript">
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.app.compat");
+      
+			var appInfo = {
+				id: "org.dojo.simpleApp",
+				title: "Simple Mobile App",
+				initialScene: "main"
+			};
+
+			dojo.ready(dojox.mobile.app.init);
+		</script>
+	</head>
+	<body>
+		
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mobile/tests/simpleListApp/app/assistants/main-assistant.js b/dojox/mobile/tests/simpleListApp/app/assistants/main-assistant.js
new file mode 100644
index 0000000..b7d946d
--- /dev/null
+++ b/dojox/mobile/tests/simpleListApp/app/assistants/main-assistant.js
@@ -0,0 +1,66 @@
+dojo.provide("MainAssistant");
+dojo.require("dojox.mobile.app.SceneAssistant");
+
+dojo.declare("MainAssistant", dojox.mobile.app.SceneAssistant, {
+  
+  setup: function(){
+    console.log("In main assistant setup");
+    
+    this.controller.parse();
+    console.log("In main assistant setup 2");
+    
+    var data1 = [
+      {
+        label: "Row 1"
+      },
+      {
+        label: "Row 2"
+      }
+    ];
+    var data2 = [
+      {
+        label: "Row 3"
+      },
+      {
+        label: "Row 4"
+      },
+      {
+        label: "Row 5"
+      },
+      {
+        label: "Row 6"
+      }
+    ];
+    
+    var listWidget = dijit.byId("listWidget");
+    listWidget.set("items", data1);
+    
+    var _this = this;
+    
+    dojo.connect(listWidget, "onSelect", function(data, index, rowNode){
+      try {
+        console.log("selected data item  ", data);
+        _this.controller.query(".listInfo")[0].innerHTML 
+                = "Selected (" + index + ") '" + data.label + "'";
+      } catch(e){
+        console.log("caught ", e);
+      }
+    });
+    
+    this.connect(dijit.byId("btn1"), "onClick", function(){
+      dijit.byId("listWidget").set("items", data1);
+    });
+    this.connect(dijit.byId("btn2"), "onClick", function(){
+      dijit.byId("listWidget").set("items", data2);
+    });
+    
+    
+  },
+  
+  activate: function(){
+    console.log("In main assistant activate");
+    
+    
+  }
+  
+});
\ No newline at end of file
diff --git a/dojox/mobile/tests/simpleListApp/app/views/main/main-scene.html b/dojox/mobile/tests/simpleListApp/app/views/main/main-scene.html
new file mode 100644
index 0000000..35dd3d2
--- /dev/null
+++ b/dojox/mobile/tests/simpleListApp/app/views/main/main-scene.html
@@ -0,0 +1,14 @@
+<div dojoType="dojox.mobile.RoundRect">This scene shows how to render a simple list with just an itemTemplate</div>
+
+<div class="listInfo" dojoType="dojox.mobile.RoundRect">
+  Tap the list to see selected info here.
+</div>
+
+<button id="btn1" dojoType="dojox.mobile.Button" style="width:200px">Render 1st Data Set</button>
+<p></p>
+<button id="btn2" dojoType="dojox.mobile.Button" style="width:200px">Render 2nd Data Set</button>
+
+<div dojoType="dojox.mobile.RoundRect" shadow="true">
+  <div id="listWidget" dojoType="dojox.mobile.app.List"
+      itemTemplate="app/views/main/rowTemplate.html"></div>
+</div>
\ No newline at end of file
diff --git a/dojox/mobile/tests/simpleListApp/app/views/main/rowTemplate.html b/dojox/mobile/tests/simpleListApp/app/views/main/rowTemplate.html
new file mode 100644
index 0000000..f9c0e65
--- /dev/null
+++ b/dojox/mobile/tests/simpleListApp/app/views/main/rowTemplate.html
@@ -0,0 +1,3 @@
+<div class="row">
+  ${label}
+</div>
diff --git a/dojox/mobile/tests/simpleListApp/index.html b/dojox/mobile/tests/simpleListApp/index.html
new file mode 100644
index 0000000..195b777
--- /dev/null
+++ b/dojox/mobile/tests/simpleListApp/index.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<link href="../../themes/iphone/iphone-app.css" rel="stylesheet">
+		<style>
+		.lnk {
+			font-size: 17px;
+			color: cyan;
+			text-decoration: none;
+		}
+		</style>
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="parseOnLoad: false"></script>
+    
+		<!-- 
+			Include the files directly, as some mobile operating systems do not
+			allow synchronous XHR, and therefore break dojo.require
+		-->
+		<script type="text/javascript" src="../../../mobile/app.js"></script>
+		<script language="JavaScript" type="text/javascript">
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.app.compat");
+      
+			var appInfo = {
+				id: "org.dojo.simpleApp",
+				title: "Simple Mobile App With List",
+				initialScene: "main"
+			};
+      
+			dojo.ready(dojox.mobile.app.init);
+		</script>
+	</head>
+	<body>
+		
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/mobile/tests/test_Android-ButtonList.html b/dojox/mobile/tests/test_Android-ButtonList.html
new file mode 100644
index 0000000..9c3c69b
--- /dev/null
+++ b/dojox/mobile/tests/test_Android-ButtonList.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+
+		<title>Button List</title>
+		<link href="../themes/android/android.css" rel="stylesheet"></link>
+		<link href="../themes/buttons.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+
+			dojo.addOnLoad(function(){
+				var ul = dojo.byId("list");
+					for(var i = 0, len = ul.childNodes.length; i < len; i++){
+						var li = ul.childNodes[i];
+						if(li.nodeType != 1 || li.tagName != "LI"){ continue; }
+						var w = dijit.byNode(li);
+						dojo.connect(w.btnNode, "onclick", btnClicked);
+				}
+			});
+	
+			function btnClicked(e){
+				var btnDiv = e.currentTarget;
+				if(dojo.hasClass(btnDiv, "mblCheckOffButton")){
+					dojo.removeClass(btnDiv, "mblCheckOffButton");
+					dojo.addClass(btnDiv, "mblCheckOnButton");
+				}else if(dojo.hasClass(btnDiv, "mblCheckOnButton")){
+					dojo.removeClass(btnDiv, "mblCheckOnButton");
+					dojo.addClass(btnDiv, "mblCheckOffButton");
+				}
+			}
+		</script>
+	</head>
+	<body>
+	    <div id="settings" dojoType="dojox.mobile.View" selected="true">
+		    <h1 dojoType="dojox.mobile.Heading">Location & security settings</h1>
+		    <h2 class="mblHeading">My Location</h2>
+		    <ul id="list" dojoType="dojox.mobile.EdgeToEdgeList">
+			    <li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" btnClass="mblCheckOffButton">
+				    Use wireless networks
+				    <div class="mblListItemSubText">
+					    See location in applications (such as Maps) using wireless networks
+				    </div>
+			    </li>
+			    <li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" btnClass="mblCheckOnButton">
+				    Use GPS satellites
+				    <div class="mblListItemSubText">
+					    When locating, accurate to street level (uncheck to conserve battery)
+				    </div>
+			    </li>
+		    </ul>
+		    <h2 class="mblHeading">My Location</h2>
+		     <ul dojoType="dojox.mobile.EdgeToEdgeList">
+			    <li dojoType="dojox.mobile.ListItem">
+			       Set unlock pattern
+			    </li>
+		    </ul>
+	    </div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_Android-EdgeToEdge.html b/dojox/mobile/tests/test_Android-EdgeToEdge.html
new file mode 100644
index 0000000..d24b4bd
--- /dev/null
+++ b/dojox/mobile/tests/test_Android-EdgeToEdge.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Edge to Edge</title>
+		<link href="../themes/android/android.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+
+	</head>
+	<body>
+		<div id="settings" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Settings</h1>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-2-41x41.png">
+					Airplane Mode
+					<div class="mblItemSwitch" dojoType="dojox.mobile.Switch"></div>
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-2-41x41.png" rightText="mac" moveTo="hello">
+					Wi-Fi
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-2-41x41.png" rightText="AcmePhone" moveTo="hello">
+					Carrier
+				</li>
+			</ul>
+		</div>
+
+		<div id="hello" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading">Hello</h1>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+				<li dojoType="dojox.mobile.ListItem" moveTo="settings">
+					Hello
+				</li>
+				<li dojoType="dojox.mobile.ListItem" moveTo="settings">
+					Carrier
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_Android-EdgeToEdgeCategory.html b/dojox/mobile/tests/test_Android-EdgeToEdgeCategory.html
new file mode 100644
index 0000000..9f69394
--- /dev/null
+++ b/dojox/mobile/tests/test_Android-EdgeToEdgeCategory.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Edge to Edge</title>
+		<link href="../themes/android/android.css" rel="stylesheet"></link>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="settings" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Edge-to-Edge List</h1>
+			<h2 dojoType="dojox.mobile.EdgeToEdgeCategory">J</h2>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+				<li dojoType="dojox.mobile.ListItem">
+					Jack Coleman
+				</li>
+				<li dojoType="dojox.mobile.ListItem">
+					James Evans
+				</li>
+				<li dojoType="dojox.mobile.ListItem">
+					Jason Griffin
+				</li>
+			</ul>
+			<h2 dojoType="dojox.mobile.EdgeToEdgeCategory">K</h2>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+				<li dojoType="dojox.mobile.ListItem">
+					Karen Hughes
+				</li>
+				<li dojoType="dojox.mobile.ListItem">
+					Kelly Perry
+				</li>
+				<li dojoType="dojox.mobile.ListItem">
+					Kevin Rivera
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_Android-Icon.html b/dojox/mobile/tests/test_Android-Icon.html
new file mode 100755
index 0000000..851a874
--- /dev/null
+++ b/dojox/mobile/tests/test_Android-Icon.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Icon</title>
+		<link href="../themes/android/android.css" rel="stylesheet"></link>
+		<link href="../themes/buttons.css" rel="stylesheet"></link>
+
+		<style>
+			.box {
+				border: 1px solid #A7C0E0;
+				width: 300px;
+				height: 250px;
+				background-image: url(images/widget-bg.png);
+				background-repeat: no-repeat;
+				background-color: white;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Icon Container</h1>
+			<ul dojoType="dojox.mobile.IconContainer">
+				<li dojoType="dojox.mobile.IconItem" label="app1" icon="images/a-icon-3.png" lazy="true"><div class="box"></div></li>
+				<li dojoType="dojox.mobile.IconItem" label="app2" icon="images/a-icon-3.png" lazy="true"><div class="box"></div></li>
+				<li dojoType="dojox.mobile.IconItem" label="app3" icon="images/a-icon-3.png" lazy="true"><div class="box"></div></li>
+				<li dojoType="dojox.mobile.IconItem" label="moveTo" icon="images/a-icon-3.png" moveTo="about" transition="slide"></li>
+				<li dojoType="dojox.mobile.IconItem" label="href" icon="images/a-icon-3.png" href="test_Android-RoundRectList.html" transition="slide"></li>
+				<li dojoType="dojox.mobile.IconItem" label="url" icon="images/a-icon-3.png" url="view-sample.html" transition="slide"></li>
+			</ul>
+		</div>
+
+		<div id="about" dojoType="dojox.mobile.View" style="background-color:black">
+			<h1 dojoType="dojox.mobile.Heading" back="Icon Container" moveTo="foo">About</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">My Phone</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" rightText="AcmePhone">
+					Network											   
+				</li>												   
+				<li dojoType="dojox.mobile.ListItem" rightText="AcmePhone">
+					Line
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="1024">
+					Songs
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_Android-RoundRectList.html b/dojox/mobile/tests/test_Android-RoundRectList.html
new file mode 100755
index 0000000..150c0e3
--- /dev/null
+++ b/dojox/mobile/tests/test_Android-RoundRectList.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Round Rect List</title>
+		<link href="../themes/android/android.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Mobile Mashup</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Spaces</h2>
+			<ul dojoType="dojox.mobile.RoundRectList" iconBase="images/a-icon-2.png">
+				<li id="item1" dojoType="dojox.mobile.ListItem" icon="images/a-icon-10.png" rightText="Off" moveTo="bar" href="test_Android-Icon.html">
+					u1space
+				</li>
+				<li id="item12" dojoType="dojox.mobile.ListItem" icon="images/a-icon-11.png" rightText="Off" moveTo="bar" href="test_Android-Icon.html">
+					u2space
+				</li>
+				<li id="item2" dojoType="dojox.mobile.ListItem" icon="images/a-icon-12.png" rightText="Off" moveTo="bar" href="test_Android-Icon.html">
+					Wi-Fi
+				</li>
+				<li id="item3" dojoType="dojox.mobile.ListItem" icon="images/a-icon-13.png" rightText="VPN" moveTo="bar" href="test_Android-Icon.html">
+					VPN
+				</li>
+				<li id="item4" dojoType="dojox.mobile.ListItem" icon="none" rightText="Off">
+					World
+				</li>
+			</ul>
+			<div dojoType="dojox.mobile.RoundRect">
+				Tapping on an item label text opens a different page (test_Android-Icon.html), tapping on right-hand side of the label text shows another view in the same page.
+			</div>
+		</div>
+
+		<div id="bar" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Spaces" moveTo="foo">u1space</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Applications</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" rightText="Off">
+					Video
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-2.png" rightText="VPN">
+					Maps
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="Off">
+					Phone Number
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_Android-Settings.html b/dojox/mobile/tests/test_Android-Settings.html
new file mode 100644
index 0000000..7885694
--- /dev/null
+++ b/dojox/mobile/tests/test_Android-Settings.html
@@ -0,0 +1,104 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Settings</title>
+		<link href="../themes/android/android.css" rel="stylesheet"></link>
+		<link href="../themes/buttons.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+			dojo.addOnLoad(function(){
+				var ul = dojo.byId("list");
+				for(var i = 0, len = ul.childNodes.length; i < len; i++){
+					var li = ul.childNodes[i];
+					if(li.nodeType != 1 || li.tagName != "LI"){ continue; }
+					var w = dijit.byNode(li);
+					dojo.connect(w.btnNode, "onclick", btnClicked);
+				}
+			});
+			function btnClicked(e){
+				var btnDiv = e.currentTarget;
+				if(dojo.hasClass(btnDiv, "mblCheckOffButton")){
+					dojo.removeClass(btnDiv, "mblCheckOffButton");
+					dojo.addClass(btnDiv, "mblCheckOnButton");
+				}else if(dojo.hasClass(btnDiv, "mblCheckOnButton")){
+					dojo.removeClass(btnDiv, "mblCheckOnButton");
+					dojo.addClass(btnDiv, "mblCheckOffButton");
+				}
+			}
+		</script>
+	</head>
+	<body>
+		<div id="settings" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Settings</h1>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList" iconBase="images/a-icon-1-41x41.png">
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-10.png" moveTo="location">
+					Wireless & networks
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-11.png" moveTo="location">
+					Call settings
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-12.png" moveTo="location">
+					Sound & display
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-13.png" moveTo="location">
+					Location & security
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-14.png" moveTo="location">
+					Applications
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-15.png" moveTo="location">
+					Accounts & sync
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-16.png" moveTo="location">
+					Privacy
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-17.png" moveTo="location">
+					SD card &amp phone storage
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-18.png" moveTo="location">
+					Search
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-10.png" moveTo="location">
+					Language & keyboard
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-11.png" moveTo="location">
+					Accessibility
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-12.png" moveTo="location">
+					Text-to-speech
+				</li>
+		</div>
+		<div id="location" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Settings" moveTo="settings">Location & security settings</h1>
+			<h2 class="mblHeading">My Location</h2>
+			<ul id="list" dojoType="dojox.mobile.EdgeToEdgeList">
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" btnClass="mblCheckOffButton">
+					Use wireless networks
+					<div class="mblListItemSubText">
+						See location in applications (such as Maps) using wireless networks
+					</div>
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" btnClass="mblCheckOnButton">
+					Use GPS satellites
+					<div class="mblListItemSubText">
+						When locating, accurate to street level (uncheck to conserve battery)
+					</div>
+				</li>
+			</ul>
+			<h2 class="mblHeading">My Location</h2>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+				<li dojoType="dojox.mobile.ListItem">
+					Set unlock pattern
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_Android-Switch.html b/dojox/mobile/tests/test_Android-Switch.html
new file mode 100644
index 0000000..9ce7a1f
--- /dev/null
+++ b/dojox/mobile/tests/test_Android-Switch.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Switch</title>
+		<link href="../themes/android/android.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body style="padding:15px;visibility:visible">
+		<div dojoType="dojox.mobile.Switch" value="off"></div>
+		<hr>
+		<div dojoType="dojox.mobile.Switch" value="on" leftLabel="Start" rightLabel="Stop"></div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_Android-TabContainer.html b/dojox/mobile/tests/test_Android-TabContainer.html
new file mode 100644
index 0000000..2701fd1
--- /dev/null
+++ b/dojox/mobile/tests/test_Android-TabContainer.html
@@ -0,0 +1,139 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Tab Container</title>
+		<link href="../themes/android/android.css" rel="stylesheet"></link>
+		<style>
+		.lnk {
+			font-size: 17px;
+			color: cyan;
+			text-decoration: none;
+		}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="general" dojoType="dojox.mobile.View" selected="true">
+			<div dojoType="dojox.mobile.TabContainer">
+				<div dojoType="dojox.mobile.TabPane" label="Phone" icon="images/a-icon-10.png">
+					<ul id="list1" dojoType="dojox.mobile.EdgeToEdgeList">
+						<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+							<table>
+								<tr>
+									<td><img src="images/a-icon-2-41x41.png"></td>
+							        <td>
+								        <a href="#" class="lnk">Dojo: Traditional Karate-do Spirit</a><br>
+								        Sarah Connor Hardcover<br>
+								        Eligible for FREE Super Saver Shipping
+							        </td>
+								</tr>
+							</table>
+						</li>
+						<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+							<table>
+								<tr>
+									<td><img src="images/a-icon-2-41x41.png"></td>
+							        <td>
+								        <a href="#" class="lnk">Japanese Martial Arts Dojo</a><br>
+								        Martin Parker Hardcover<br>
+								        Eligible for FREE Super Saver Shipping<br>
+							        </td>
+								</tr>
+							</table>
+						</li>
+						<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+							<table>
+								<tr>
+									<td><img src="images/a-icon-2-41x41.png"></td>
+							        <td>
+								        <a href="#" class="lnk">Total Solar Eclipse</a><br>
+								        Steven Young Hardcover<br>
+								        Eligible for FREE Super Saver Shipping<br>
+							        </td>
+								</tr>
+							</table>
+						</li>
+						<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+							<table>
+								<tr>
+									<td><img src="images/a-icon-2-41x41.png"></td>
+							        <td>
+								        <a href="#" class="lnk">The History of Java Coffee</a><br>
+								        Marco Rodriguez Hardcover<br>
+								        Eligible for FREE Super Saver Shipping<br>
+							        </td>
+								</tr>
+							</table>
+						</li>
+						<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+							<table>
+								<tr>
+									<td><img src="images/a-icon-2-41x41.png"></td>
+							        <td>
+								        <a href="#" class="lnk">The Principles of Spider's Web</a><br>
+								        Melissa Morgan Hardcover<br>
+								        Eligible for FREE Super Saver Shipping<br>
+							        </td>
+								</tr>
+							</table>
+						</li>
+					</ul>
+				</div>
+
+				<div dojoType="dojox.mobile.TabPane" label="Call log" icon="images/a-icon-11.png">
+					<ul dojoType="dojox.mobile.RoundRectList">
+						<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-4.png" moveTo="hello">
+							Sounds
+						</li>
+						<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-4.png" moveTo="hello">
+							Brightness
+						</li>
+						<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-4.png" moveTo="hello">
+							Wallpaper
+						</li>
+					</ul>
+				</div>
+
+				<div dojoType="dojox.mobile.TabPane" label="Contacts" icon="images/a-icon-12.png">
+					<h1 dojoType="dojox.mobile.Heading">J</h1>
+					<ul dojoType="dojox.mobile.EdgeToEdgeList">
+						<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-4.png" moveTo="hello">
+							John Doe
+						</li>
+						<li dojoType="dojox.mobile.ListItem" icon="images/a-icon-4.png" moveTo="hello">
+							John Smith
+						</li>
+					</ul>
+				</div>
+
+				<div dojoType="dojox.mobile.TabPane" label="Farovites" icon="images/a-icon-13.png">
+					<div style="margin:16px;font-size:20px;color:#949694">
+					  You don't have any favorites.
+					</div>
+				</div>
+			</div>
+		</div>
+
+		<div id="hello" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading">Hello</h1>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+				<li dojoType="dojox.mobile.ListItem" moveTo="general">
+					Hello
+				</li>
+				<li dojoType="dojox.mobile.ListItem" moveTo="general">
+					Carrier
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_Android-VariableHeightList.html b/dojox/mobile/tests/test_Android-VariableHeightList.html
new file mode 100755
index 0000000..0c2bdff
--- /dev/null
+++ b/dojox/mobile/tests/test_Android-VariableHeightList.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>News</title>
+		<link href="../themes/android/android.css" rel="stylesheet"></link>
+		<style>
+		.content {
+			padding:0px 10px;
+			background-color: white;
+			color: black;
+		}
+		p {
+			font-family: Helvetica;
+			font-size: 12px;
+		}
+		.title {
+			color: blue;
+			margin-bottom: 4px;
+		}
+		.subtitle {
+			font-style: italic;
+			color: gray;
+			margin: 0px;
+			margin-bottom: 4px;
+		}
+		.subsubtitle {
+			margin: 16px 0px 0px 0px;
+		}
+		.lst {
+			margin: 0px;
+			padding: 0px 14px;
+		}
+		.lst li {
+			font-family: Helvetica;
+			font-size: 12px;
+			margin: 0px;
+			list-style-type: square;
+		}
+		</style>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojo.hash");
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="home" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">News</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Top Stories</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" moveTo="#article" transition="slide">
+					Top 10 news stories of the decade
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" moveTo="#article" transition="flip">
+					Create client-side diagrammatic interaction in Web applications with GFX
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" moveTo="#article" transition="fade">
+					Explores advanced topics in the new Java framework for implementing and consuming REST-based Web services, Part 3
+				</li>
+			</ul>
+		</div>
+
+		<div id="article" dojoType="dojox.mobile.View" style="background-color:white;height:100%">
+			<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="#home">Article</h1>
+			<div class="content">
+				<h3 class="title">Did you know?</h3>
+				<h4 class="subtitle">Features of dojox.mobile</h4>
+				<h5 class="subsubtitle">No images are used</h5>
+				<ul class="lst">
+				  	<li>UI parts consist of DOM and CSS3.</li>
+					<li>Only application icons are images.</li>
+				</ul>
+				<p>For example, none of the UI parts below are images.<br></p>
+				<img src="images/not-images.png">
+
+				<h5 class="subsubtitle">Removed dependencies on the dojo modules as much as possible</h5>
+				<ul class="lst">
+				  	<li>No dependencies even on some of the essential core modules like Templated, Container, Contained, dojo.query, or dojo.parser.</li>
+				</ul>
+
+				<h5 class="subsubtitle">Support for CSS sprite</h5>
+				<ul class="lst">
+					<li>Application icon images can be aggregated into a single file to reduce the number of http requests.</li>
+				</ul>
+
+				<h5 class="subsubtitle">Possible to use the webkitMobile build option (when PC browser support is unnecessary)</h5>
+				<ul class="lst">
+					<li>Drops IE and Firefox-specific code at build time, and thus reduces the dojo core size</li>
+				</ul>
+			</div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_ajax-html.html b/dojox/mobile/tests/test_ajax-html.html
new file mode 100644
index 0000000..ed4c7a3
--- /dev/null
+++ b/dojox/mobile/tests/test_ajax-html.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Ajax</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Ajax (HTML)</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">External Views</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" transition="slide" url="view1.html">
+					External View #1 (sync)
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-2.png" transition="flip" url="view2.html" sync="false">
+					External View #2 (async)
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-3.png" transition="fade" url="view3.html">
+					External View #3 (sync)
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_ajax-json.html b/dojox/mobile/tests/test_ajax-json.html
new file mode 100644
index 0000000..1f82d90
--- /dev/null
+++ b/dojox/mobile/tests/test_ajax-json.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Ajax</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Ajax (JSON)</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">External Views</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" transition="slide" url="view1.json">
+					External View #1 (sync)
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-2.png" transition="flip" url="view2.json" sync="false">
+					External View #2 (async)
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-3.png" transition="fade" url="view3.json">
+					External View #3 (sync)
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_anchor-label.html b/dojox/mobile/tests/test_anchor-label.html
new file mode 100644
index 0000000..c340df5
--- /dev/null
+++ b/dojox/mobile/tests/test_anchor-label.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Anchor Label</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+
+			dojo.declare(
+				"dojox.mobile.ListItemEx",
+				dojox.mobile.ListItem,
+			{
+				onAnchorLabelClicked: function(e){
+					if(this.id == "item1" || this.id == "item2"){
+						// go to a different html page
+						var href = "test_iPhone-Icon.html";
+						this.transitionTo(null, href);
+					}else if(this.id == "item3" || this.id == "item4"){
+						// load an external view into the current html page
+						var url = "view2.html";
+						this.transitionTo(null, null, url);
+					}
+				}
+			});
+		</script>
+	</head>
+	<body>
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Anchor Label</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Items</h2>
+			<ul dojoType="dojox.mobile.RoundRectList" iconBase="images/i-icon-all.png">
+				<li id="item1" dojoType="dojox.mobile.ListItemEx" iconPos="0,0,29,29" moveTo="bar" anchorLabel="true">
+					Different page
+				</li>
+				<li id="item2" dojoType="dojox.mobile.ListItemEx" iconPos="0,29,29,29" moveTo="bar" anchorLabel="true">
+					Different page
+				</li>
+				<li id="item3" dojoType="dojox.mobile.ListItemEx" iconPos="0,58,29,29" moveTo="bar" anchorLabel="true">
+					External view
+				</li>
+				<li id="item4" dojoType="dojox.mobile.ListItemEx" iconPos="0,87,29,29" moveTo="bar" anchorLabel="true">
+					External view
+				</li>
+			</ul>
+			<div dojoType="dojox.mobile.RoundRect">
+				Tapping on an item label text opens a different page (test_iPhone-Icon.html) or loads an external view (view2.html), while tapping on right-hand side of the label text shows another view in the same page.
+			</div>
+		</div>
+
+		<div id="bar" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Spaces" moveTo="foo">u1space</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Applications</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" rightText="Off">
+					Video
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" rightText="VPN">
+					Maps
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="Off">
+					Phone Number
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_bookmarkable.html b/dojox/mobile/tests/test_bookmarkable.html
new file mode 100755
index 0000000..45a20fd
--- /dev/null
+++ b/dojox/mobile/tests/test_bookmarkable.html
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Bookmarkable</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<style>
+		.lnk {
+			font-size: 14px;
+			color: #0B5199;
+			text-decoration: none;
+		}
+		</style>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojo.hash");
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="home" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Bookmarkable</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Transition Effects</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" moveTo="#page1" transition="slide">
+					Slide
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-2.png" moveTo="#page2" transition="flip">
+					Flip
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-3.png" moveTo="#page3" transition="fade">
+					Fade
+				</li>
+			</ul>
+			<div dojoType="dojox.mobile.RoundRect">
+				After you moves to other views, you should also be able to navigate through the views with browser's back and forward buttons. Also, views should be bookmarkable.
+			</div>
+		</div>
+
+		<div id="page1" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="#home" transition="slide">Page 1</h1>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" moveTo="#result1">
+					Item 1
+				</li>
+			</ul>
+		</div>
+
+		<div id="page2" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="#home" transition="flip">Page 2</h1>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-2.png" moveTo="#result2">
+					Item 2
+				</li>
+			</ul>
+		</div>
+
+		<div id="page3" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="#home" transition="fade">Page 3</h1>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-3.png" moveTo="#result3">
+					Item 3
+				</li>
+			</ul>
+		</div>
+
+		<div id="result1" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Page 1" moveTo="#page1">Search Result 1</h1>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					1. <a href="#" class="lnk">Dojo: Traditional Karate-do Spirit</a><br>
+					Sarah Connor Hardcover<br>
+					Eligible for FREE Super Saver Shipping<br>
+					<font color="red">$14.50 (50%)</font> In Stock<br>
+					# (531)
+				</li>
+			</ul>
+		</div>
+
+		<div id="result2" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Page 2" moveTo="#page2">Search Result 2</h1>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					2. <a href="#" class="lnk">Japanese Martial Arts Dojo</a><br>
+					Martin Parker Hardcover<br>
+					<font color="red">$14.00 (60%)</font> In Stock<br>
+					# (173)
+				</li>
+			</ul>
+		</div>
+
+		<div id="result3" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Page 3" moveTo="#page3">Search Result 3</h1>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					3. <a href="#" class="lnk">Total Solar Eclipse</a><br>
+					Steven Young Hardcover<br>
+					Get it by Mar. 2 if you order in the next <font color="green"><b>16 hours</b></font><br>
+					Eligible for FREE Super Saver Shipping<br>
+					<font color="red">$9.50 (62%)</font> In Stock<br>
+					# (1199)
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_buttons.html b/dojox/mobile/tests/test_buttons.html
new file mode 100644
index 0000000..318819b
--- /dev/null
+++ b/dojox/mobile/tests/test_buttons.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<title>Button</title>
+		<link href="../themes/buttons.css" rel="stylesheet"></link>
+		<link href="../themes/buttons-compat.css" rel="stylesheet"></link>
+	</head>
+	<body style="padding:20px;background-color: rgb(197,204,211);">
+		<div class="mblBlueMinusButton"><div></div><p></p></div>
+		<div class="mblDarkBlueMinusButton"><div></div><p></p></div>
+		<div class="mblRedMinusButton"><div></div></div>
+		<br>
+		<div class="mblBluePlusButton"><div></div><p></p></div>
+		<div class="mblDarkBluePlusButton"><div></div><p></p></div>
+		<div class="mblRedPlusButton"><div></div><p></p></div>
+		<br>
+		<div class="mblCheckOnButton"><div></div><p></p></div>
+		<div class="mblCheckOffButton"><div></div><p></p></div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_dynamic-icons.html b/dojox/mobile/tests/test_dynamic-icons.html
new file mode 100644
index 0000000..970a2e9
--- /dev/null
+++ b/dojox/mobile/tests/test_dynamic-icons.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Dynamic Icons</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<link href="../themes/buttons.css" rel="stylesheet"></link>
+		<link href="../../../dijit/themes/tundra/tundra.css" rel="stylesheet"></link>
+
+		<style>
+			.box {
+				border: 1px solid #A7C0E0;
+				width: 300px;
+				height: 250px;
+				background-image: url(images/widget-bg.png);
+				background-repeat: no-repeat;
+				background-color: white;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+
+			dojo.addOnLoad(function(){
+				var btnWidget = dijit.byId("btn1");
+				dojo.connect(btnWidget.domNode, "onclick", onBtnClicked);
+				function onBtnClicked(e){
+					var iconContainerWidget = dijit.byId("ic1");
+					var itemWidget = new dojox.mobile.IconItem({
+						icon: "images/icon-1.png",
+						label: "new icon",
+						lazy: true
+					});
+					itemWidget.containerNode.innerHTML = "<div dojoType='dijit._Calendar'></div>";
+					iconContainerWidget.addChild(itemWidget);
+				}
+			});
+		</script>
+	</head>
+	<body class="tundra">
+		<div id="myhome" dojoType="dojox.mobile.View" selected="true">
+			<ul id="ic1" dojoType="dojox.mobile.IconContainer" type="slide" iconBase="images/i-icon-all.png">
+				<li dojoType="dojox.mobile.IconItem" label="test1" icon="images/icon-1.png" lazy="true"><div class="box"></div></li>
+			</ul>
+			<button id="btn1" dojoType="dojox.mobile.Button" style="width:80px;margin-left:10px">More...</button>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_dynamic-items.html b/dojox/mobile/tests/test_dynamic-items.html
new file mode 100755
index 0000000..f3c663d
--- /dev/null
+++ b/dojox/mobile/tests/test_dynamic-items.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Dynamic Items</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojo.hash");
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+
+			var counter = 4;
+			dojo.addOnLoad(function(){
+				var btnWidget = dijit.byId("btn1");
+				dojo.connect(btnWidget.domNode, "onclick", onBtnClicked);
+				function onBtnClicked(e){
+					var listWidget = dijit.byId("list1");
+					for(var i = 1; i <= 3; i++){
+						var itemWidget = new dojox.mobile.ListItem({
+							icon: "images/i-icon-"+i+".png",
+							moveTo: "#bar&myParam=000"+counter,
+							label: "Document 000"+counter
+						});
+						listWidget.addChild(itemWidget);
+						counter++;
+					}
+				}
+			});
+
+			function loadPage(moveTo){
+				if(!(moveTo.match(/#(\w+)/))){ return; }
+				moveTo.match(/#(\w+)(.*)/);
+				var id = RegExp.$1;
+				var param = RegExp.$2;
+				if(!param){ return; }
+				var container = dojo.byId(id);
+				container.innerHTML = "";
+				var prog = dojox.mobile.ProgressIndicator.getInstance();
+				container.appendChild(prog.domNode);
+				prog.start();
+				/*
+				var url = "http://..." + param;
+				dojo.xhrGet({
+					url: url,
+					handleAs: "text",
+					load: function(response, ioArgs){
+						prog.stop();
+						container.innerHTML = response;
+						dojox.mobile.parser.parse(container);
+					}
+				});
+				*/
+				setTimeout(function(){ // network latency simulation
+					prog.stop();
+					container.innerHTML = '<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="#home">'+param+'</h1>\n'+param;
+					dojox.mobile.parser.parse(container);
+				}, 5000);
+			}
+			dojo.declare(
+				"dojox.mobile.ViewEx",
+				dojox.mobile.View,
+			{
+				onStartView: function(){
+					loadPage(location.hash);
+				},
+				onBeforeTransitionIn: function(moveTo, dir, transition, context, method){
+					loadPage("#"+moveTo);
+				}
+			});
+		</script>
+	</head>
+	<body>
+		<div id="home" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Dynamic Items</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">External Documents</h2>
+			<ul id="list1" dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" moveTo="#bar&myParam=0001">
+					Document 0001
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-2.png" moveTo="#bar&myParam=0002">
+					Document 0002
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-3.png" moveTo="#bar&myParam=0003">
+					Document 0003
+				</li>
+			</ul>
+			<button id="btn1" dojoType="dojox.mobile.Button" style="width:80px;margin-left:10px">More...</button>
+		</div>
+
+		<div id="bar" dojoType="dojox.mobile.ViewEx"></div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_dynamic-view.html b/dojox/mobile/tests/test_dynamic-view.html
new file mode 100644
index 0000000..6b0992c
--- /dev/null
+++ b/dojox/mobile/tests/test_dynamic-view.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Dynamic View</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<style>
+		.lnk {
+			font-size: 14px;
+			color: #0B5199;
+			text-decoration: none;
+		}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+
+			dojo.addOnLoad(function(){
+				var view1 = new dojox.mobile.View({
+					id: "foo",
+					selected: true
+				}, "view1");
+				view1.startup();
+
+				var heading1 = new dojox.mobile.Heading({
+					label: "Dynamic View"
+				});
+				view1.addChild(heading1);
+
+				var categ1 = new dojox.mobile.RoundRectCategory({
+					label: "Documents"
+				});
+				view1.addChild(categ1);
+
+				var list1 = new dojox.mobile.RoundRectList();
+				view1.addChild(list1);
+
+				var counter = 4;
+				for(var i = 1; i <= 3; i++){
+					var item1 = new dojox.mobile.ListItem({
+						icon: "images/i-icon-"+i+".png",
+						label: "Document 000"+counter
+					});
+					list1.addChild(item1);
+					counter++;
+				}
+			});
+		</script>
+	</head>
+	<body>
+		<div id="view1"></div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_hash-parameter.html b/dojox/mobile/tests/test_hash-parameter.html
new file mode 100755
index 0000000..d1e7899
--- /dev/null
+++ b/dojox/mobile/tests/test_hash-parameter.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Transition Parameter</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<style>
+		.lnk {
+			font-size: 14px;
+			color: #0B5199;
+			text-decoration: none;
+		}
+		</style>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojo.hash");
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+
+			function loadPage(moveTo){
+				if(!(moveTo.match(/#(\w+)/))){ return; }
+				moveTo.match(/#(\w+)(.*)/);
+				var id = RegExp.$1;
+				var param = RegExp.$2;
+				if(!param){ return; }
+				var container = dojo.byId(id);
+				// You may want to dynamically load page contents here
+				container.innerHTML = '<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="#home">'+param+'</h1>\n'+param;
+				dojox.mobile.parser.parse(container);
+			}
+			dojo.declare(
+				"dojox.mobile.ViewEx",
+				dojox.mobile.View,
+			{
+				onStartView: function(){
+					loadPage(location.hash);
+				},
+				onBeforeTransitionIn: function(moveTo, dir, transition, context, method){
+					loadPage("#"+moveTo);
+				}
+			});
+		</script>
+	</head>
+	<body>
+		<div id="home" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Animations</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Transition Effects</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" moveTo="#bar&myParam=0001">
+					Document 0001
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-2.png" moveTo="#bar&myParam=0002">
+					Document 0002
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-3.png" moveTo="#bar&myParam=0003">
+					Document 0003
+				</li>
+			</ul>
+			<div dojoType="dojox.mobile.RoundRect">
+				After you moves to other views, you should also be able to navigate through the views with browser's back and forward buttons. Also, views should be bookmarkable. Note that you can pass parameters (e.g. &myParam=001) to a destination view.
+			</div>
+		</div>
+
+		<div id="bar" dojoType="dojox.mobile.ViewEx">bar</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-Animation.html b/dojox/mobile/tests/test_iPhone-Animation.html
new file mode 100644
index 0000000..6088129
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-Animation.html
@@ -0,0 +1,81 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Animation</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<style>
+		.lnk {
+			font-size: 14px;
+			color: #0B5199;
+			text-decoration: none;
+		}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile");
+			dojo.require("dojox.mobile.parser");
+
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Animations</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Transition Effects</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" moveTo="bar" transition="slide">
+					Slide
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-2.png" moveTo="bar" transition="flip">
+					Flip
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-3.png" moveTo="bar" transition="fade">
+					Fade
+				</li>
+			</ul>
+		</div>
+
+		<div id="bar" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="foo">Search Result</h1>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					1. <a href="#" class="lnk">Dojo: Traditional Karate-do Spirit</a><br>
+					Sarah Connor Hardcover<br>
+					Eligible for FREE Super Saver Shipping<br>
+					<font color="red">$14.50 (50%)</font> In Stock<br>
+					# (531)
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					2. <a href="#" class="lnk">Japanese Martial Arts Dojo</a><br>
+					Martin Parker Hardcover<br>
+					<font color="red">$14.00 (60%)</font> In Stock<br>
+					# (173)
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					3. <a href="#" class="lnk">Total Solar Eclipse</a><br>
+					Steven Young Hardcover<br>
+					Get it by Mar. 2 if you order in the next <font color="green"><b>16 hours</b></font><br>
+					Eligible for FREE Super Saver Shipping<br>
+					<font color="red">$9.50 (62%)</font> In Stock<br>
+					# (1199)
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					4. <a href="#" class="lnk">The History of Java Coffee</a><br>
+					Marco Rodriguez Hardcover<br>
+					<font color="blue">Not Available</font>
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					5. <a href="#" class="lnk">The Principles of Spider's Web</a><br>
+					Melissa Morgan Hardcover<br>
+					Eligible for FREE Super Saver Shipping<br>
+					<font color="red">$12.00 (60%)</font> In Stock<br>
+					# (1847)
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-Button.html b/dojox/mobile/tests/test_iPhone-Button.html
new file mode 100755
index 0000000..6e22dab
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-Button.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Button</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<style>
+		.redButton {
+			border-color: #cc3333;
+			background-image: url(images/red-button-bg.png);
+			background: -webkit-gradient(linear, left top, left bottom, from(#D3656D), to(#BC1320), color-stop(0.5, #C9404B), color-stop(0.5, #BC1421));
+		}
+		.redButtonSelected {
+			background-image: url(images/red-button-sel-bg.png);
+			background: -webkit-gradient(linear, left top, left bottom, from(#AF333C), to(#880E17), color-stop(0.5, #952B33), color-stop(0.5, #870F18));
+		}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+
+			dojo.addOnLoad(function(){
+				var btnWidget = dijit.byId("btn1");
+				dojo.connect(btnWidget.domNode, "onclick", onBtnClicked);
+				function onBtnClicked(e){
+					// do something
+				}
+			});
+		</script>
+	</head>
+	<body style="padding: 20px;visibility:visible">
+		<button id="btn1" dojoType="dojox.mobile.Button" style="width:120px">Default Button</button>
+		<p></p>
+		<button id="btn2" dojoType="dojox.mobile.Button" btnClass="redButton" style="width:120px">Custom Button</button>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-ButtonList.html b/dojox/mobile/tests/test_iPhone-ButtonList.html
new file mode 100644
index 0000000..e666f01
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-ButtonList.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Button List</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<link href="../themes/buttons.css" rel="stylesheet"></link>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+			dojo.addOnLoad(function(){
+				var ul = dojo.byId("list");
+				for(var i = 0, len = ul.childNodes.length; i < len; i++){
+					var li = ul.childNodes[i];
+					if(li.nodeType != 1 || li.tagName != "LI"){ continue; }
+					var w = dijit.byNode(li);
+					dojo.connect(w.btnNode, "onclick", btnClicked);
+				}
+			});
+			function btnClicked(e){
+				var btnDiv = e.currentTarget;
+				if(dojo.hasClass(btnDiv, "mblBluePlusButton")){
+					dojo.removeClass(btnDiv, "mblBluePlusButton");
+					dojo.addClass(btnDiv, "mblRedMinusButton");
+				}else if(dojo.hasClass(btnDiv, "mblRedMinusButton")){
+					dojo.removeClass(btnDiv, "mblRedMinusButton");
+					dojo.addClass(btnDiv, "mblBluePlusButton");
+				}
+			}
+		</script>
+	</head>
+	<body>
+		<div id="mashups" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Mashups</h1>
+			<ul id="list" dojoType="dojox.mobile.EdgeToEdgeList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" btnClass="mblBluePlusButton">
+					XX Widget
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-2.png" btnClass="mblRedMinusButton">
+					YY Widget
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-EdgeToEdge.html b/dojox/mobile/tests/test_iPhone-EdgeToEdge.html
new file mode 100644
index 0000000..dada3e8
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-EdgeToEdge.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Edge to Edge</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="settings" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Settings</h1>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList" iconBase="images/i-icon-all.png">
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,0,29,29">
+					Airplane Mode
+					<div class="mblItemSwitch" dojoType="dojox.mobile.Switch"></div>
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,29,29,29" rightText="mac" moveTo="hello">
+					Wi-Fi
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,58,29,29" rightText="AcmePhone" moveTo="hello">
+					Carrier
+				</li>
+			</ul>
+		</div>
+
+		<div id="hello" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading">Hello</h1>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+				<li dojoType="dojox.mobile.ListItem" moveTo="settings">
+					Hello
+				</li>
+				<li dojoType="dojox.mobile.ListItem" moveTo="settings">
+					Carrier
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-EdgeToEdgeCategory.html b/dojox/mobile/tests/test_iPhone-EdgeToEdgeCategory.html
new file mode 100644
index 0000000..20ea91f
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-EdgeToEdgeCategory.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Edge to Edge</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="settings" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Edge-to-Edge List</h1>
+			<h2 dojoType="dojox.mobile.EdgeToEdgeCategory">J</h2>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+				<li dojoType="dojox.mobile.ListItem">
+					Jack Coleman
+				</li>
+				<li dojoType="dojox.mobile.ListItem">
+					James Evans
+				</li>
+				<li dojoType="dojox.mobile.ListItem">
+					Jason Griffin
+				</li>
+			</ul>
+			<h2 dojoType="dojox.mobile.EdgeToEdgeCategory">K</h2>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+				<li dojoType="dojox.mobile.ListItem">
+					Karen Hughes
+				</li>
+				<li dojoType="dojox.mobile.ListItem">
+					Kelly Perry
+				</li>
+				<li dojoType="dojox.mobile.ListItem">
+					Kevin Rivera
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-Heading.html b/dojox/mobile/tests/test_iPhone-Heading.html
new file mode 100644
index 0000000..efed861
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-Heading.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Heading</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="general" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading" back="Settings" moveTo="settings">General</h1>
+			<h1 dojoType="dojox.mobile.Heading" back="Long Button" moveTo="settings" xstyle="padding-left:100px">Very Very Long Title May Not Be Displayed in the Narrow Space</h1>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-Icon.html b/dojox/mobile/tests/test_iPhone-Icon.html
new file mode 100644
index 0000000..c6e2742
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-Icon.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Icon</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<link href="../themes/buttons.css" rel="stylesheet"></link>
+
+		<style>
+			.box {
+				border: 1px solid #A7C0E0;
+				width: 300px;
+				height: 250px;
+				background-image: url(images/widget-bg.png);
+				background-repeat: no-repeat;
+				background-color: white;
+			}
+		</style>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Icon Container</h1>
+			<ul dojoType="dojox.mobile.IconContainer">
+				<li dojoType="dojox.mobile.IconItem" label="app1" icon="images/icon-1.png" lazy="true"><div class="box"></div></li>
+				<li dojoType="dojox.mobile.IconItem" label="app2" icon="images/icon-1.png" lazy="true"><div class="box"></div></li>
+				<li dojoType="dojox.mobile.IconItem" label="app3" icon="images/icon-1.png" lazy="true"><div class="box"></div></li>
+				<li dojoType="dojox.mobile.IconItem" label="moveTo" icon="images/icon-1.png" moveTo="about" transition="slide"></li>
+				<li dojoType="dojox.mobile.IconItem" label="href" icon="images/icon-1.png" href="test_iPhone-RoundRectList.html" transition="slide"></li>
+				<li dojoType="dojox.mobile.IconItem" label="url" icon="images/icon-1.png" url="view-sample.html" transition="slide"></li>
+			</ul>
+		</div>
+
+		<div id="about" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Icon Container" moveTo="foo">About</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">My Phone</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" rightText="AcmePhone">
+					Network											   
+				</li>												   
+				<li dojoType="dojox.mobile.ListItem" rightText="AcmePhone">
+					Line
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="1024">
+					Songs
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-IconMulti.html b/dojox/mobile/tests/test_iPhone-IconMulti.html
new file mode 100644
index 0000000..5b651c5
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-IconMulti.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Icon Container (Multi Apps)</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<link href="../themes/buttons.css" rel="stylesheet"></link>
+		<link href="../../../dijit/themes/tundra/tundra.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body class="tundra" style="background-color:white">
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Icon Container (Multi Apps)</h1>
+			<ul dojoType="dojox.mobile.IconContainer" transition="flip">
+				<li dojoType="dojox.mobile.IconItem" label="Calendar" icon="images/icon-1.png" lazy="true">
+					<div dojoType='dijit._Calendar'></div>
+				</li>
+				<li dojoType="dojox.mobile.IconItem" label="Color Palette" icon="images/icon-1.png" lazy="true">
+					<div dojoType='dijit.ColorPalette'></div>
+				</li>
+				<li dojoType="dojox.mobile.IconItem" label="Progress Bar" icon="images/icon-1.png" lazy="true">
+					<div dojoType='dijit.ProgressBar'></div>
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-IconSingle.html b/dojox/mobile/tests/test_iPhone-IconSingle.html
new file mode 100644
index 0000000..f1cd249
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-IconSingle.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Icon Container (Single App)</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<link href="../../../dijit/themes/tundra/tundra.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body class="tundra" style="background-color:white">
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Icon Container (Single App)</h1>
+			<ul dojoType="dojox.mobile.IconContainer" transition="flip" single="true">
+				<li dojoType="dojox.mobile.IconItem" label="Calendar" icon="images/icon-1.png" lazy="true">
+					<div dojoType='dijit._Calendar'></div>
+				</li>
+				<li dojoType="dojox.mobile.IconItem" label="Color Palette" icon="images/icon-1.png" lazy="true">
+					<div dojoType='dijit.ColorPalette'></div>
+				</li>
+				<li dojoType="dojox.mobile.IconItem" label="Progress Bar" icon="images/icon-1.png" lazy="true">
+					<div dojoType='dijit.ProgressBar'></div>
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-IconSingleBelow.html b/dojox/mobile/tests/test_iPhone-IconSingleBelow.html
new file mode 100644
index 0000000..39c0e47
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-IconSingleBelow.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Icon Container (Single App)</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<link href="../../../dijit/themes/tundra/tundra.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body class="tundra" style="background-color:white">
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Icon Container (Single App)</h1>
+			<ul dojoType="dojox.mobile.IconContainer" transition="below" single="true">
+				<li dojoType="dojox.mobile.IconItem" label="Calendar" icon="images/icon-1.png" lazy="true">
+					<div dojoType='dijit._Calendar'></div>
+				</li>
+				<li dojoType="dojox.mobile.IconItem" label="Color Palette" icon="images/icon-1.png" lazy="true">
+					<div dojoType='dijit.ColorPalette'></div>
+				</li>
+				<li dojoType="dojox.mobile.IconItem" label="Progress Bar" icon="images/icon-1.png" lazy="true">
+					<div dojoType='dijit.ProgressBar'></div>
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-ResultList.html b/dojox/mobile/tests/test_iPhone-ResultList.html
new file mode 100644
index 0000000..78162fa
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-ResultList.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Result List</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<style>
+			.lnk {
+				font-size: 14px;
+				color: #0B5199;
+				text-decoration: none;
+			}
+		</style>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Search Result</h1>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					1. <a href="#" class="lnk">Dojo: Traditional Karate-do Spirit</a><br>
+					Sarah Connor Hardcover<br>
+					Eligible for FREE Super Saver Shipping<br>
+					<font color="red">$14.50 (50%)</font> In Stock<br>
+					# (531)
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					2. <a href="#" class="lnk">Japanese Martial Arts Dojo</a><br>
+					Martin Parker Hardcover<br>
+					<font color="red">$14.00 (60%)</font> In Stock<br>
+					# (173)
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					3. <a href="#" class="lnk">Total Solar Eclipse</a><br>
+					Steven Young Hardcover<br>
+					Get it by Mar. 2 if you order in the next <font color="green"><b>16 hours</b></font><br>
+					Eligible for FREE Super Saver Shipping<br>
+					<font color="red">$9.50 (62%)</font> In Stock<br>
+					# (1199)
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					4. <a href="#" class="lnk">The History of Java Coffee</a><br>
+					Marco Rodriguez Hardcover<br>
+					<font color="blue">Not Available</font>
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+					5. <a href="#" class="lnk">The Principles of Spider's Web</a><br>
+					Melissa Morgan Hardcover<br>
+					Eligible for FREE Super Saver Shipping<br>
+					<font color="red">$12.00 (60%)</font> In Stock<br>
+					# (1847)
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-RoundRect.html b/dojox/mobile/tests/test_iPhone-RoundRect.html
new file mode 100644
index 0000000..b9fb47f
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-RoundRect.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Round Rect</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Round Rectangle</h2>
+			<div dojoType="dojox.mobile.RoundRect" shadow="true">
+				This module provides some widgets that can be used to build web-based
+				applications for mobile devices such as iPhone or Android.
+			</div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-RoundRectList.html b/dojox/mobile/tests/test_iPhone-RoundRectList.html
new file mode 100644
index 0000000..2e7b882
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-RoundRectList.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Round Rect List</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="foo" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Mobile Mashup</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Spaces</h2>
+			<ul dojoType="dojox.mobile.RoundRectList" iconBase="images/i-icon-all.png">
+				<li id="item1" dojoType="dojox.mobile.ListItem" iconPos="0,0,29,29" rightText="Off" moveTo="bar">
+					u1space
+				</li>
+				<li id="item2" dojoType="dojox.mobile.ListItem" iconPos="0,29,29,29" rightText="Off" moveTo="bar">
+					u2space
+				</li>
+				<li id="item3" dojoType="dojox.mobile.ListItem" iconPos="0,58,29,29" rightText="Off" moveTo="bar">
+					Wi-Fi
+				</li>
+				<li id="item4" dojoType="dojox.mobile.ListItem" iconPos="0,87,29,29" rightText="VPN" moveTo="bar">
+					VPN
+				</li>
+			</ul>
+		</div>
+
+		<div id="bar" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Spaces" moveTo="foo">u1space</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Applications</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" rightText="Off">
+					Video
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" rightText="VPN">
+					Maps
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="Off">
+					Phone Number
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-Settings.html b/dojox/mobile/tests/test_iPhone-Settings.html
new file mode 100644
index 0000000..2c53df6
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-Settings.html
@@ -0,0 +1,168 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Settings</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="settings" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Settings</h1>
+			<ul dojoType="dojox.mobile.RoundRectList" iconBase="images/i-icon-all.png">
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,0,29,29">
+					Airplane Mode
+					<div class="mblItemSwitch" dojoType="dojox.mobile.Switch"></div>
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,29,29,29" rightText="mac" href="test_iPhone-Icon.html">
+					Wi-Fi
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,58,29,29" rightText="AcmePhone" moveTo="general">
+					Carrier
+				</li>
+			</ul>
+
+			<ul dojoType="dojox.mobile.RoundRectList" iconBase="images/i-icon-all.png">
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,87,29,29" moveTo="general">
+					Sounds
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,116,29,29" moveTo="general">
+					Brightness
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="29,0,29,29" moveTo="general">
+					Wallpaper
+				</li>
+			</ul>
+
+			<ul dojoType="dojox.mobile.RoundRectList" iconBase="images/i-icon-all.png">
+				<li dojoType="dojox.mobile.ListItem" iconPos="29,29,29,29" moveTo="general">
+					General
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="29,58,29,29" moveTo="general">
+					Mail, Contacts, Calendars
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="29,87,29,29" moveTo="general">
+					Phone
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="29,116,29,29" moveTo="general">
+					Safari
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,0,29,29" moveTo="general">
+					SMS/MMS
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,29,29,29" moveTo="general">
+					iPod
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,58,29,29" moveTo="general">
+					Photos
+				</li>
+				<li dojoType="dojox.mobile.ListItem" iconPos="0,87,29,29" moveTo="general">
+					Store
+				</li>
+			</ul>
+		</div>
+
+		<div id="general" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="Settings" moveTo="settings">General</h1>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" moveTo="about">
+					About
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="2h 40m" moveTo="about">
+					Usage
+				</li>
+			</ul>
+
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" moveTo="about">
+					Network
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="Off" moveTo="about">
+					Bluetooth
+				</li>
+				<li dojoType="dojox.mobile.ListItem" moveTo="about">
+					Location Services
+				</li>
+			</ul>
+
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" rightText="1 Minute" moveTo="about">
+					Auto-Lock
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="Off" moveTo="about">
+					Passcode Lock
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="Off" moveTo="about">
+					Restrictions
+				</li>
+			</ul>
+
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" moveTo="about">
+					Home
+				</li>
+				<li dojoType="dojox.mobile.ListItem" moveTo="about">
+					Date & Time					   
+				</li>							   
+				<li dojoType="dojox.mobile.ListItem" moveTo="about">
+					Keyboard					   
+				</li>							   
+				<li dojoType="dojox.mobile.ListItem" moveTo="about">
+					International				   
+				</li>							   
+				<li dojoType="dojox.mobile.ListItem" moveTo="about">
+					Accessibility
+				</li>
+			</ul>
+
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" moveTo="about">
+					Reset
+				</li>
+			</ul>
+		</div>
+
+		<div id="about" dojoType="dojox.mobile.View">
+			<h1 dojoType="dojox.mobile.Heading" back="General" moveTo="general">About</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Generic Mobile Device</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" rightText="AcmePhone">
+					Network											   
+				</li>												   
+				<li dojoType="dojox.mobile.ListItem" rightText="AcmePhone">
+					Line
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="1024">
+					Songs
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="10">
+					Videos
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="96">
+					Photos
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="2">
+					Applications
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="29.3 BG">
+					Capacity
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="28.0 BG">
+					Available
+				</li>
+				<li dojoType="dojox.mobile.ListItem" rightText="3.0 (7A341)">
+					Version
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-Switch.html b/dojox/mobile/tests/test_iPhone-Switch.html
new file mode 100644
index 0000000..df4a2ef
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-Switch.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Switch</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body style="padding:15px;visibility:visible">
+		<div dojoType="dojox.mobile.Switch" value="off"></div>
+		<hr>
+		<div dojoType="dojox.mobile.Switch" value="on" leftLabel="Start" rightLabel="Stop"></div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-TabContainer.html b/dojox/mobile/tests/test_iPhone-TabContainer.html
new file mode 100644
index 0000000..130db9d
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-TabContainer.html
@@ -0,0 +1,169 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Tab Container</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+
+		<style>
+			#list1 li{
+				border-style: solid;
+				border-width: 1px 0px 1px 0px;
+				border-top-color: #BABABC;
+				border-bottom-color: #89898C;
+				background-color: #ACACAF;
+				line-height: 0px;
+			}
+			#list1 li table{
+				line-height: normal;
+			}
+			#list1 li:nth-child(even){
+				background-color: #97979B;
+			}
+			.lnk {
+				font-size: 17px;
+				color: #0B5199;
+				text-decoration: none;
+			}
+		</style>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div dojoType="dojox.mobile.View" id="general" selected="true">
+			<div dojoType="dojox.mobile.TabContainer">
+				<div dojoType="dojox.mobile.TabPane" label="New">
+					<ul dojoType="dojox.mobile.EdgeToEdgeList" id="list1">
+						<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size: 10px;">
+							<table>
+								<tbody>
+									<tr>
+										<td>
+											<img src="images/icon-1.png">
+										</td>
+										<td>
+											<a class="lnk" href="#">Dojo: Traditional Karate-do Spirit</a><br>
+											Sarah Connor Hardcover<br>
+											Eligible for FREE Super Saver Shipping
+										</td>
+									</tr>
+								</tbody>
+							</table>
+						</li>
+						<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size: 10px;">
+							<table>
+								<tbody>
+									<tr>
+										<td>
+											<img src="images/icon-1.png">
+										</td>
+										<td>
+											<a class="lnk" href="#">Japanese Martial Arts Dojo</a><br>
+											Martin Parker Hardcover<br>
+											Eligible for FREE Super Saver Shipping<br>
+										</td>
+									</tr>
+								</tbody>
+							</table>
+						</li>
+						<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size: 10px;">
+							<table>
+								<tbody>
+									<tr>
+										<td>
+											<img src="images/icon-1.png">
+										</td>
+										<td>
+											<a class="lnk" href="#">Total Solar Eclipse</a><br>
+											Steven Young Hardcover<br>
+											Eligible for FREE Super Saver Shipping<br>
+										</td>
+									</tr>
+								</tbody>
+							</table>
+						</li>
+						<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size: 10px;">
+							<table>
+								<tbody>
+									<tr>
+										<td>
+											<img src="images/icon-1.png">
+										</td>
+										<td>
+											<a class="lnk" href="#">The History of Java Coffee</a><br>
+											Marco Rodriguez Hardcover<br>
+											Eligible for FREE Super Saver Shipping<br>
+										</td>
+									</tr>
+								</tbody>
+							</table>
+						</li>
+						<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size: 10px;">
+							<table>
+								<tbody>
+									<tr>
+										<td>
+											<img src="images/icon-1.png">
+										</td>
+										<td>
+											<a class="lnk" href="#">The Principles of Spider's Web</a><br>
+											Melissa Morgan Hardcover<br>
+											Eligible for FREE Super Saver Shipping<br>
+										</td>
+									</tr>
+								</tbody>
+							</table>
+						</li>
+					</ul>
+				</div>
+				<div dojoType="dojox.mobile.TabPane" label="What's Hot">
+					<ul dojoType="dojox.mobile.RoundRectList" iconBase="images/i-icon-all.png">
+						<li dojoType="dojox.mobile.ListItem" iconPos="0,0,29,29" moveTo="hello">
+							Sounds
+						</li>
+						<li dojoType="dojox.mobile.ListItem" iconPos="0,29,29,29" moveTo="hello">
+							Brightness
+						</li>
+						<li dojoType="dojox.mobile.ListItem" iconPos="0,58,29,29" moveTo="hello">
+							Wallpaper
+						</li>
+					</ul>
+				</div>
+				<div dojoType="dojox.mobile.TabPane" label="Genius">
+					<ul dojoType="dojox.mobile.RoundRectList" iconBase="images/i-icon-all.png">
+						<li dojoType="dojox.mobile.ListItem" iconPos="0,87,29,29" moveTo="hello">
+							General
+						</li>
+						<li dojoType="dojox.mobile.ListItem" iconPos="0,116,29,29" moveTo="hello">
+							Mail, Contacts, Calendars
+						</li>
+						<li dojoType="dojox.mobile.ListItem" iconPos="29,0,29,29" moveTo="hello">
+							Phone
+						</li>
+					</ul>
+				</div>
+			</div>
+		</div>
+		<div dojoType="dojox.mobile.View" id="hello">
+			<h1 dojoType="dojox.mobile.Heading">
+				Hello
+			</h1>
+			<ul dojoType="dojox.mobile.EdgeToEdgeList">
+				<li dojoType="dojox.mobile.ListItem" moveTo="general">
+					Hello
+				</li>
+				<li dojoType="dojox.mobile.ListItem" moveTo="general">
+					Carrier
+				</li>
+			</ul>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_iPhone-VariableHeightList.html b/dojox/mobile/tests/test_iPhone-VariableHeightList.html
new file mode 100755
index 0000000..46b194c
--- /dev/null
+++ b/dojox/mobile/tests/test_iPhone-VariableHeightList.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>News</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+		<style>
+		.content {
+			padding:0px 10px;
+			background-color: white;
+		}
+		p {
+			font-family: Helvetica;
+			font-size: 12px;
+		}
+		.title {
+			color: blue;
+			margin-bottom: 4px;
+		}
+		.subtitle {
+			font-style: italic;
+			color: gray;
+			margin: 0px;
+			margin-bottom: 4px;
+		}
+		.subsubtitle {
+			margin: 16px 0px 0px 0px;
+		}
+		.lst {
+			margin: 0px;
+			padding: 0px 14px;
+		}
+		.lst li {
+			font-family: Helvetica;
+			font-size: 12px;
+			margin: 0px;
+			list-style-type: square;
+		}
+		</style>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojo.hash");
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+		</script>
+	</head>
+	<body>
+		<div id="home" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">News</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">Top Stories</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" moveTo="#article" transition="slide">
+					Top 10 news stories of the decade
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" moveTo="#article" transition="flip">
+					Create client-side diagrammatic interaction in Web applications with GFX
+				</li>
+				<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" moveTo="#article" transition="fade">
+					Explores advanced topics in the new Java framework for implementing and consuming REST-based Web services, Part 3
+				</li>
+			</ul>
+		</div>
+
+		<div id="article" dojoType="dojox.mobile.View" style="background-color:white;height:100%">
+			<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="#home">Article</h1>
+			<div class="content">
+				<h3 class="title">Did you know?</h3>
+				<h4 class="subtitle">Features of dojox.mobile</h4>
+				<h5 class="subsubtitle">No images are used</h5>
+				<ul class="lst">
+				  	<li>UI parts consist of DOM and CSS3.</li>
+					<li>Only application icons are images.</li>
+				</ul>
+				<p>For example, none of the UI parts below are images.<br></p>
+				<img src="images/not-images.png">
+
+				<h5 class="subsubtitle">Removed dependencies on the dojo modules as much as possible</h5>
+				<ul class="lst">
+				  	<li>No dependencies even on some of the essential core modules like Templated, Container, Contained, dojo.query, or dojo.parser.</li>
+				</ul>
+
+				<h5 class="subsubtitle">Support for CSS sprite</h5>
+				<ul class="lst">
+					<li>Application icon images can be aggregated into a single file to reduce the number of http requests.</li>
+				</ul>
+
+				<h5 class="subsubtitle">Possible to use the webkitMobile build option (when PC browser support is unnecessary)</h5>
+				<ul class="lst">
+					<li>Drops IE and Firefox-specific code at build time, and thus reduces the dojo core size</li>
+				</ul>
+			</div>
+		</div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/test_progress-indicator.html b/dojox/mobile/tests/test_progress-indicator.html
new file mode 100755
index 0000000..b001080
--- /dev/null
+++ b/dojox/mobile/tests/test_progress-indicator.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
+		<meta name="apple-mobile-web-app-capable" content="yes" />
+		<title>Progress Indicator</title>
+		<link href="../themes/iphone/iphone.css" rel="stylesheet"></link>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+
+		<script language="JavaScript" type="text/javascript">
+			//dojo.require("dojo.parser"); // Use the lightweight parser.
+			dojo.require("dojo.hash");
+			dojo.require("dojox.mobile.parser");
+			dojo.require("dojox.mobile");
+			dojo.requireIf(!dojo.isWebKit, "dojox.mobile.compat");
+
+			function loadPage(moveTo){
+				if(!(moveTo.match(/#(\w+)/))){ return; }
+				moveTo.match(/#(\w+)(.*)/);
+				var id = RegExp.$1;
+				var param = RegExp.$2;
+				if(!param){ return; }
+				var container = dojo.byId(id);
+				container.innerHTML = "";
+				var prog = dojox.mobile.ProgressIndicator.getInstance();
+				container.appendChild(prog.domNode);
+				prog.start();
+				/*
+				var url = "http://..." + param;
+				dojo.xhrGet({
+					url: url,
+					handleAs: "text",
+					load: function(response, ioArgs){
+						prog.stop();
+						container.innerHTML = response;
+						dojox.mobile.parser.parse(container);
+					}
+				});
+				*/
+				setTimeout(function(){ // network latency simulation
+					prog.stop();
+					container.innerHTML = '<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="#home">'+param+'</h1>\n'+param;
+					dojox.mobile.parser.parse(container);
+				}, 5000);
+			}
+			dojo.declare(
+				"dojox.mobile.ViewEx",
+				dojox.mobile.View,
+			{
+				onStartView: function(){
+					loadPage(location.hash);
+				},
+				onBeforeTransitionIn: function(moveTo, dir, transition, context, method){
+					loadPage("#"+moveTo);
+				}
+			});
+		</script>
+	</head>
+	<body>
+		<div id="home" dojoType="dojox.mobile.View" selected="true">
+			<h1 dojoType="dojox.mobile.Heading">Progress Indicator</h1>
+			<h2 dojoType="dojox.mobile.RoundRectCategory">External Documents</h2>
+			<ul dojoType="dojox.mobile.RoundRectList">
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" moveTo="#bar&myParam=0001">
+					Document 0001
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-2.png" moveTo="#bar&myParam=0002">
+					Document 0002
+				</li>
+				<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-3.png" moveTo="#bar&myParam=0003">
+					Document 0003
+				</li>
+			</ul>
+			<div dojoType="dojox.mobile.RoundRect">
+				A progress indicator shows up about 5 seconds before a view content is displayed.
+				After you moves to other views, you should also be able to navigate through the views with browser's back and forward buttons. Also, views should be bookmarkable. Note that you can pass parameters (e.g. &myParam=001) to a destination view.
+			</div>
+		</div>
+
+		<div id="bar" dojoType="dojox.mobile.ViewEx"></div>
+	</body>
+</html>
diff --git a/dojox/mobile/tests/view-sample.html b/dojox/mobile/tests/view-sample.html
new file mode 100644
index 0000000..c866328
--- /dev/null
+++ b/dojox/mobile/tests/view-sample.html
@@ -0,0 +1,38 @@
+<div id="bar" dojoType="dojox.mobile.View">
+	<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="foo">View Sample</h1>
+	<ul dojoType="dojox.mobile.RoundRectList">
+		<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+			1. <a href="#" class="lnk">Dojo: Traditional Karate-do Spirit</a><br>
+			Sarah Connor Hardcover<br>
+			Eligible for FREE Super Saver Shipping<br>
+			<font color="red">$14.50 (50%)</font> In Stock<br>
+			# (531)
+		</li>
+		<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+			2. <a href="#" class="lnk">Japanese Martial Arts Dojo</a><br>
+			Martin Parker Hardcover<br>
+			<font color="red">$14.00 (60%)</font> In Stock<br>
+			# (173)
+		</li>
+		<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+			3. <a href="#" class="lnk">Total Solar Eclipse</a><br>
+			Steven Young Hardcover<br>
+			Get it by Mar. 2 if you order in the next <font color="green"><b>16 hours</b></font><br>
+			Eligible for FREE Super Saver Shipping<br>
+			<font color="red">$9.50 (62%)</font> In Stock<br>
+			# (1199)
+		</li>
+		<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+			4. <a href="#" class="lnk">The History of Java Coffee</a><br>
+			Marco Rodriguez Hardcover<br>
+			<font color="blue">Not Available</font>
+		</li>
+		<li class="mblVariableHeight" dojoType="dojox.mobile.ListItem" style="font-size:10px">
+			5. <a href="#" class="lnk">The Principles of Spider's Web</a><br>
+			Melissa Morgan Hardcover<br>
+			Eligible for FREE Super Saver Shipping<br>
+			<font color="red">$12.00 (60%)</font> In Stock<br>
+			# (1847)
+		</li>
+	</ul>
+</div>
diff --git a/dojox/mobile/tests/view1.html b/dojox/mobile/tests/view1.html
new file mode 100644
index 0000000..bf57f44
--- /dev/null
+++ b/dojox/mobile/tests/view1.html
@@ -0,0 +1,14 @@
+<div dojoType="dojox.mobile.View">
+	<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="foo">view1.html</h1>
+	<ul dojoType="dojox.mobile.EdgeToEdgeList">
+		<li dojoType="dojox.mobile.ListItem">
+			Jack Coleman
+		</li>
+		<li dojoType="dojox.mobile.ListItem">
+			James Evans
+		</li>
+		<li dojoType="dojox.mobile.ListItem">
+			Jason Griffin
+		</li>
+	</ul>
+</div>
diff --git a/dojox/mobile/tests/view1.json b/dojox/mobile/tests/view1.json
new file mode 100644
index 0000000..65ac978
--- /dev/null
+++ b/dojox/mobile/tests/view1.json
@@ -0,0 +1,18 @@
+{
+  "dojox.mobile.View": {
+    "dojox.mobile.Heading": {
+      "@back": "Home",
+      "@moveTo": "foo",
+      "@label": "view1.json"
+    },
+    "dojox.mobile.EdgeToEdgeList": {
+      "dojox.mobile.ListItem": [{
+        "@label": "Jack Coleman"
+      }, {
+        "@label": "James Evans"
+      }, {
+        "@label": "Jason Griffin"
+      }]
+    }
+  }
+}
diff --git a/dojox/mobile/tests/view2.html b/dojox/mobile/tests/view2.html
new file mode 100644
index 0000000..4573b73
--- /dev/null
+++ b/dojox/mobile/tests/view2.html
@@ -0,0 +1,9 @@
+<div dojoType="dojox.mobile.View">
+	<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="foo" label="view2.html"></h1>
+	<h2 dojoType="dojox.mobile.RoundRectCategory" label="Transition Effects"></h2>
+	<ul dojoType="dojox.mobile.RoundRectList">
+		<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-1.png" moveTo="foo" transition="slide" label="Slide"></li>
+		<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-2.png" moveTo="foo" transition="flip" label="Flip"></li>
+		<li dojoType="dojox.mobile.ListItem" icon="images/i-icon-3.png" moveTo="foo" transition="fade" label="Fade"></li>
+	</ul>
+</div>
diff --git a/dojox/mobile/tests/view2.json b/dojox/mobile/tests/view2.json
new file mode 100644
index 0000000..d1c35be
--- /dev/null
+++ b/dojox/mobile/tests/view2.json
@@ -0,0 +1,31 @@
+{
+  "dojox.mobile.View": {
+    "dojox.mobile.Heading": {
+      "@back": "Home",
+      "@label": "view2.json",
+      "@moveTo": "foo"
+    },
+    "dojox.mobile.RoundRectCategory": {
+      "@label": "Transition Effects"
+    },
+    "dojox.mobile.RoundRectList": {
+      "dojox.mobile.ListItem": [{
+        "@icon": "images/i-icon-1.png",
+        "@label": "Slide",
+        "@moveTo": "foo",
+        "@transition": "slide"
+      }, {
+        "@icon": "images/i-icon-2.png",
+        "@label": "Flip",
+        "@moveTo": "foo",
+        "@transition": "flip"
+      }, {
+        "@icon": "images/i-icon-3.png",
+        "@label": "Fade",
+        "@moveTo": "foo",
+        "@transition": "fade"
+      }]
+    }
+  }
+}
+
diff --git a/dojox/mobile/tests/view3.html b/dojox/mobile/tests/view3.html
new file mode 100644
index 0000000..f83c4bc
--- /dev/null
+++ b/dojox/mobile/tests/view3.html
@@ -0,0 +1,16 @@
+<div id="settings" dojoType="dojox.mobile.View">
+	<h1 dojoType="dojox.mobile.Heading" label="view3.html"></h1>
+	<ul dojoType="dojox.mobile.RoundRectList" iconBase="images/i-icon-all.png">
+		<li dojoType="dojox.mobile.ListItem" iconPos="0,0,29,29" label="Airplane Mode">
+			<div class="mblItemSwitch" dojoType="dojox.mobile.Switch"></div>
+		</li>
+		<li dojoType="dojox.mobile.ListItem" iconPos="0,29,29,29" rightText="mac" href="test_iPhone-Icon.html" label="Wi-Fi"></li>
+		<li dojoType="dojox.mobile.ListItem" iconPos="0,58,29,29" rightText="AcmePhone" moveTo="foo" label="Carrier"></li>
+	</ul>
+
+	<ul dojoType="dojox.mobile.RoundRectList" iconBase="images/i-icon-all.png">
+		<li dojoType="dojox.mobile.ListItem" iconPos="0,87,29,29" moveTo="foo" label="Sounds"></li>
+		<li dojoType="dojox.mobile.ListItem" iconPos="0,116,29,29" moveTo="foo" label="Brightness"></li>
+		<li dojoType="dojox.mobile.ListItem" iconPos="29,0,29,29" moveTo="foo" label="Wallpaper"></li>
+	</ul>
+</div>
diff --git a/dojox/mobile/tests/view3.json b/dojox/mobile/tests/view3.json
new file mode 100644
index 0000000..b37f15e
--- /dev/null
+++ b/dojox/mobile/tests/view3.json
@@ -0,0 +1,44 @@
+{
+  "dojox.mobile.View": {
+    "@id": "settings",
+    "dojox.mobile.Heading": {
+      "@label": "view3.json"
+    },
+    "dojox.mobile.RoundRectList": [{
+      "@iconBase": "images/i-icon-all.png",
+      "dojox.mobile.ListItem": [{
+        "@iconPos": "0,0,29,29",
+        "@label": "Airplane Mode",
+        "dojox.mobile.Switch": {
+          "@class": "mblItemSwitch"
+        }
+      }, {
+        "@href": "test_iPhone-Icon.html",
+        "@iconPos": "0,29,29,29",
+        "@label": "Wi-Fi",
+        "@rightText": "mac"
+      }, {
+        "@iconPos": "0,58,29,29",
+        "@label": "Carrier",
+        "@moveTo": "foo",
+        "@rightText": "AcmePhone"
+      }]
+    }, {
+      "@iconBase": "images/i-icon-all.png",
+      "dojox.mobile.ListItem": [{
+        "@iconPos": "0,87,29,29",
+        "@label": "Sounds",
+        "@moveTo": "foo"
+      }, {
+        "@iconPos": "0,116,29,29",
+        "@label": "Brightness",
+        "@moveTo": "foo"
+      }, {
+        "@iconPos": "29,0,29,29",
+        "@label": "Wallpaper",
+        "@moveTo": "foo"
+      }]
+    }]
+  }
+}
+
diff --git a/dojox/mobile/themes/android/android-compat.css b/dojox/mobile/themes/android/android-compat.css
new file mode 100755
index 0000000..a5a056c
--- /dev/null
+++ b/dojox/mobile/themes/android/android-compat.css
@@ -0,0 +1,284 @@
+/* mbl.widget.Heading */
+.mblHeading {
+	background-image: url(compat/heading-bg.png);
+}
+
+/* Heading Arrow Button */
+.mblArrowButtonHead {
+	position: absolute;
+	top: 0px;
+	left: 8px;
+	width: 19px;
+	height: 29px;
+	background-image: url(compat/arrow-button-head.png);
+}
+.mblArrowButtonBody {
+	background-image: url(compat/arrow-button-bg.png);
+}
+
+/* Round Corner */
+.mblRoundCorner {
+	background-color: black;
+	height: 1px;
+	font-size: 1px;
+	overflow: hidden;
+	border-style: solid;
+	border-color: #ADAAAD;
+	border-width: 0px 1px;
+}
+.mblRoundRectContainer {
+	padding: 3px 8px;
+	background-color: black;
+	border-style: solid;
+	border-color: #ADAAAD;
+	border-width: 0px 1px;
+}
+.mblRoundRectList .mblRoundRectContainer {
+	margin: 0px;
+	padding: 0px;
+}
+.mblRoundCorner0T {
+	height: 0px;
+}
+.mblRoundCorner1T {
+	background-color: #ADAAAD;
+	margin: 0px 5px;
+}
+.mblRoundCorner2T {
+	margin: 0px 2px;
+	border-width: 0px 3px;
+}
+.mblRoundCorner3T {
+	margin: 0px 1px;
+	border-width: 0px 2px;
+}
+.mblRoundCorner4T {
+	margin: 0px 1px;
+}
+.mblRoundCorner5T {
+	margin: 0px 1px;
+}
+
+.mblRoundCorner0B {
+	height: 0px;
+}
+.mblRoundCorner1B {
+	margin: 0px 1px;
+}
+.mblRoundCorner2B {
+	margin: 0px 1px;
+}
+.mblRoundCorner3B {
+	margin: 0px 1px;
+	border-width: 0px 2px;
+}
+.mblRoundCorner4B {
+	margin: 0px 2px;
+	border-width: 0px 3px;
+}
+.mblRoundCorner5B {
+	background-color: #ADAAAD;
+	margin: 0px 5px;
+}
+
+/* mbl.widget.ListItem */
+*html li.mblListItem.mblVariableHeight { /* IE6 hack */
+	height: 0;
+}
+
+li.mblListItem .mblArrow {
+	border-style: none;
+	width: 9px;
+	height: 13px;
+	background-image: url(compat/gray-arrow.png);
+}
+li.mblItemSelected .mblArrow {
+	background-image: url(compat/white-arrow.png);
+}
+
+/* Switch */
+.mblSwitchInner {
+	width: 100px;
+}
+.mblSwitchBg {
+	border: none;
+}
+.mblSwitchBgLeft {
+	width: 89px;
+	background: none;
+}
+.mblSwitchBgRight {
+	width: 89px;
+	left: 58px;
+	background: none;
+}
+.mblSwitchKnobContainer {
+	position: relative;
+	left: 53px;
+	width: 41px;
+	height: 26px;
+}
+.mblSwitchKnob {
+	position: relative;
+	top: 0px;
+	left: 0px;
+	width: auto;
+	height: 21px;
+	background-image: url(compat/switch-knob-bg.png);
+	border-width: 0px 1px;
+	-moz-border-radius: 0px;
+}
+.mblSwitchCorner {
+	position: relative;
+	height: 1px;
+	font-size: 1px;
+	overflow: hidden;
+	border-style: solid;
+	border-color: #878787;
+}
+.mblSwitchCorner1T {
+	background-color: #848684;
+	margin: 0px 1px;
+	border-width: 0px;
+}
+.mblSwitchCorner2T {
+	background-color: #C0C0C0;
+	margin: 0px 0px;
+	border-width: 0px 1px;
+}
+.mblSwitchCorner3T {
+	background-color: #C6C7C6;
+	margin: 0px 0px;
+	border-width: 0px 1px;
+}
+
+.mblSwitchCorner1B {
+	background-color: #FBFBFB;
+	margin: 0px 0px;
+	border-width: 0px 1px;
+}
+.mblSwitchCorner2B {
+	background-color: #FBFBFB;
+	margin: 0px 0px;
+	border-width: 0px 1px;
+}
+.mblSwitchCorner3B {
+	background-color: #878787;
+	margin: 0px 1px;
+	border-width: 0px;
+}
+
+.mblSwitchBgLeft .mblSwitchCorner1T {
+	border-width: 0px 2px;
+	background-color: #00A600;
+}
+.mblSwitchBgLeft .mblSwitchCorner2T {
+	background-color: #00A600;
+}
+.mblSwitchBgLeft .mblSwitchCorner3T {
+	background-color: #00A600;
+}
+
+.mblSwitchBgLeft .mblSwitchCorner1B {
+	background-color: #00D700;
+}
+.mblSwitchBgLeft .mblSwitchCorner2B {
+	background-color: #00D700;
+}
+.mblSwitchBgLeft .mblSwitchCorner3B {
+	background-color: #00D700;
+}
+
+.mblSwitchText {
+	height: 21px;
+	line-height: 21px;
+}
+.mblSwitchTextLeft {
+	background-image: url(compat/switch-green-bg.png);
+	border-left: 1px solid #848684;
+}
+.mblSwitchTextRight {
+	background-image: url(compat/switch-gray-bg.png);
+	left: 35px;
+	border-right: 1px solid #848684;
+}
+
+/* Icon Content Heading */
+.mblIconContentHeading {
+	background-image: url(compat/icon-content-heading-bg.png);
+}
+
+/* dojox.mobile.Button */
+.mblBlueButton {
+	background-image: url(compat/blue-button-bg.png);
+}
+.mblBlueButtonSelected {
+	background-image: url(compat/blue-button-sel-bg.png);
+}
+
+/* Tab Container */
+.mblTabPanelHeader {
+	background-image: url(compat/heading-bg.png);
+}
+.mblTabButton {
+	background-image: url(compat/tab-button-bg.png);
+}
+.mblTabButtonSelected {
+	background-image: url(compat/tab-sel-button-bg.png);
+}
+*html .mblTabButton { /* IE6 hack */
+	behavior: expression(
+		(function(el){
+			if(!el.previousSibling)
+				el.style.borderWidth = "1px";
+			el.style.behavior = "none";
+		})(this)
+	);
+}
+
+/* Progress Indicator */
+.mblProg {
+	position: absolute;
+	top: 0px;
+	width: 4px;
+	font-size: 1px;
+	height: 36px;
+	overflow: hidden;
+	background-color: #C0C0C0;
+}
+.mblProg0 {
+	left: 0px;
+}
+.mblProg1 {
+	left: 8px;
+}
+.mblProg2 {
+	left: 16px;
+}
+.mblProg3 {
+	left: 24px;
+}
+.mblProg4 {
+	left: 32px;
+}
+.mblProg5 {
+	left: 40px;
+}
+.mblProg6 {
+	left: 48px;
+}
+.mblProg7 {
+	left: 56px;
+}
+.mblProg8 {
+	left: 64px;
+}
+.mblProg9 {
+	left: 72px;
+}
+.mblProg10 {
+	left: 80px;
+}
+.mblProg11 {
+	left: 80px;
+}
diff --git a/dojox/mobile/themes/android/android.css b/dojox/mobile/themes/android/android.css
new file mode 100755
index 0000000..631129e
--- /dev/null
+++ b/dojox/mobile/themes/android/android.css
@@ -0,0 +1,738 @@
+body {
+	visibility: hidden;
+}
+
+html.mobile, .mobile body {
+	width: 100%;
+	margin: 0px;
+	padding: 0px;
+}
+.mobile body {
+	overflow-x: hidden;
+	-webkit-text-size-adjust: none;
+	background-color: black;
+	font-family: Helvetica;
+	font-size: 17px;
+	min-height: 440px;
+}
+
+/* dojox.mobile.View */
+.mblView {
+	position: relative;
+	top: 0px;
+	left: 0px;
+	width: 100%;
+	color: white;
+}
+
+.mblView.out {
+	position: absolute;
+}
+
+.mblView.in {
+	position: absolute;
+}
+
+.slide.out {
+	-webkit-animation-duration: .4s;
+	-webkit-animation-name: slideOut;
+	-webkit-animation-timing-function: linear;
+	-webkit-transform: translateX(-100%);
+}
+.slide.in {
+	-webkit-animation-duration: .4s;
+	-webkit-animation-name: slideIn;
+	-webkit-animation-timing-function: linear;
+	-webkit-transform: translateX(0px);
+}
+.slide.out.reverse {
+	-webkit-animation-name: slideOutReverse;
+}
+.slide.in.reverse {
+	-webkit-animation-name: slideInReverse;
+}
+ at -webkit-keyframes slideOut {
+	from { -webkit-transform: translateX(0px); }
+	to { -webkit-transform: translateX(-100%); }
+}
+ at -webkit-keyframes slideIn {
+	from { -webkit-transform: translateX(100%); }
+	to { -webkit-transform: translateX(0px); }
+}
+ at -webkit-keyframes slideOutReverse {
+	from { -webkit-transform: translateX(0px); }
+	to { -webkit-transform: translateX(100%); }
+}
+ at -webkit-keyframes slideInReverse {
+	from { -webkit-transform: translateX(-100%); }
+	to { -webkit-transform: translateX(0px); }
+}
+
+.flip.out {
+	-webkit-animation-duration: .6s;
+	-webkit-animation-name: flipOut;
+	-webkit-animation-timing-function: ease-in;
+	-webkit-transform: rotateY(90deg);
+}
+.flip.in {
+	-webkit-animation-duration: .6s;
+	-webkit-animation-name: flipIn;
+	-webkit-animation-timing-function: ease-out;
+}
+ at -webkit-keyframes flipOut {
+	0% { -webkit-transform: rotateY(0deg) scale(1); }
+	50% { -webkit-transform: rotateY(90deg) scale(.8); }
+	100% { -webkit-transform: rotateY(90deg) scale(.8); }
+}
+
+ at -webkit-keyframes flipIn {
+	0% { -webkit-transform: rotateY(90deg) scale(.8); }
+	50% { -webkit-transform: rotateY(90deg) scale(.8); }
+	100% { -webkit-transform: rotateY(0deg) scale(1); }
+}
+
+.fade.out {
+	-webkit-animation-duration: 1s;
+	-webkit-animation-name: fadeOut;
+	-webkit-animation-timing-function: ease-in;
+}
+.fade.in {
+	-webkit-animation-duration: 1s;
+	-webkit-animation-name: fadeIn;
+	-webkit-animation-timing-function: ease-out;
+}
+ at -webkit-keyframes fadeOut {
+	from { opacity: 1; }
+	to { opacity: 0; }
+}
+
+ at -webkit-keyframes fadeIn {
+	from { opacity: 0; }
+	to { opacity: 1; }
+}
+
+/* dojox.mobile.Heading */
+.mblHeading {
+	position: relative;
+	height: 25px;
+	margin: 0px;
+	padding: 0px 0px 0px 4px;
+	background-color: #8C8A8C;
+	background: -webkit-gradient(linear, left top, left bottom, from(#9C9E9C), to(#848284));
+	border-top: 1px solid #CDD5DF;
+	border-bottom: 1px solid #2D3642;
+	font-family: Helvetica;
+	font-size: 14px;
+	color: white;
+	text-align: center;
+	line-height: 23px;
+	text-shadow: rgba(0,0,0,0.6) 0px -1px 0px;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+/* Heading Arrow Button */
+.dj_webkit .mblArrowButtonHead {
+	position: absolute;
+	top: 5px;
+	left: 9px;
+	width: 19px;
+	height: 16px;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #3F3E3E;
+	-webkit-transform: scale(.8,1) rotate(45deg);
+	background: -webkit-gradient(linear, left top, left bottom, from(#E5E5E5), to(#7F7F7F), color-stop(0.5, #ADADAD), color-stop(0.5, #909090));
+}
+.mblArrowButtonBody {
+	position: absolute;
+	top: 0px;
+	left: 19px;
+	padding: 0px 10px 0px 3px;
+	height: 23px;
+	border-width: 1px 1px 1px 0px;
+	border-style: inset;
+	border-color: #3F3E3E;
+	font-family: Helvetica;
+	font-size: 13px;
+	color: white;
+	line-height: 23px;
+	cursor: pointer;
+	-webkit-border-radius: 5px;
+	background-color: #ADADAD;
+	background: -webkit-gradient(linear, left top, left bottom, from(#E5E5E5), to(#7F7F7F), color-stop(0.5, #ADADAD), color-stop(0.5, #909090));
+	-webkit-tap-highlight-color: transparent;
+}
+.dj_ie .mblArrowButtonBody, .dj_ff3 .mblArrowButtonBody {
+	padding: 0px 10px 0px 10px;
+}
+.dj_webkit .mblArrowButtonNeck {
+	position: absolute;
+	top: 0px;
+	left: 19px;
+	width: 4px;
+	height: 23px;
+	border-width: 1px 0px 1px 0px;
+	border-style: inset;
+	border-color: #3F3E3E;
+	background: -webkit-gradient(linear, left top, left bottom, from(#E5E5E5), to(#7F7F7F), color-stop(0.5, #ADADAD), color-stop(0.5, #909090));
+}
+.mblArrowButtonSelected .mblArrowButtonHead {
+	background: -webkit-gradient(linear, left top, left bottom, from(#AD7500), to(#FFAA00), color-stop(0.06, #FFB200), color-stop(0.5, #FFC700));
+}
+.mblArrowButtonSelected .mblArrowButtonBody, .mblArrowButtonSelected .mblArrowButtonNeck {
+	background-color: #FFC700;
+	background: -webkit-gradient(linear, left top, left bottom, from(#AD7500), to(#FFAA00), color-stop(0.06, #FFB200), color-stop(0.5, #FFC700));
+}
+
+/* dojox.mobile.RoundRect */
+.mblRoundRect {
+	margin: 7px 9px 16px;
+	padding: 8px;
+	border: 1px solid #ADAAAD;
+	-webkit-border-radius: 8px;
+	-moz-border-radius: 8px;
+	color: white;
+	background-color: black;
+}
+.mblRoundRect.mblShadow {
+	-webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);
+}
+
+/* dojox.mobile.EdgeToEdgeCategory */
+.mblEdgeToEdgeCategory {
+	position: relative;
+	height: 22px;
+	margin: 0px;
+	padding: 0px 10px;
+	border-bottom: 1px solid #393439;
+	background-color: #212021;
+	font-family: Helvetica;
+	font-size: 16px;
+	color: white;
+	line-height: 22px;
+	text-shadow: rgba(0,0,0,0.6) 0px -1px 0px;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+/* dojox.mobile.RoundRectCategory */
+.mblRoundRectCategory {
+	color: white;
+	margin: 18px 0px 0px 20px;
+	font-family: Helvetica;
+	font-size: 16px;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+/* dojox.mobile.RoundRectList */
+.mblRoundRectList {
+	margin: 7px 9px 16px;
+	padding: 0px;
+	border: 1px solid #ADAAAD;
+	-webkit-border-radius: 8px;
+	-moz-border-radius: 8px;
+	background-color: white;
+	position: relative; /* IE needs this */
+}
+
+/* dojox.mobile.EdgeToEdgeList */
+.mblEdgeToEdgeList {
+	padding: 0px;
+	background-color: black;
+	position: relative; /* IE needs this */
+	margin: 0px; /* IE needs this */
+}
+
+/* dojox.mobile.ListItem */
+.mblListItem {
+	list-style-type: none;
+	height: 64px;
+	border-bottom: solid 1px #313431;
+	line-height: 64px;
+	font-size: 21px;
+	position: relative;
+	color: white;
+	background-color: black;
+}
+.mblListItemIcon {
+	position: absolute;
+	margin: 18px 0px 0px 7px;
+}
+.mblListItem.mblVariableHeight {
+	line-height: normal;
+	height: auto;
+	padding: 11px 6px 10px 6px;
+}
+.mblItemSelected {
+	background-color: #FFC700;
+	background: -webkit-gradient(linear, left top, left bottom, from(#AD7500), to(#FFAA00), color-stop(0.06, #FFB200), color-stop(0.5, #FFC700));
+}
+li .mblListItemTextBox {
+	padding-right: 28px;
+}
+li .mblListItemTextBoxSelected {
+	background-color: #048BF4;
+}
+.mblRoundRectList .mblListItem:first-child {
+	-webkit-border-top-left-radius: 8px;
+	-webkit-border-top-right-radius: 8px;
+	-moz-border-radius-topleft: 8px;
+	-moz-border-radius-topright: 8px;
+}
+.mblRoundRectList .mblListItem:last-child {
+	border-bottom-width: 0px;
+	-webkit-border-bottom-left-radius: 8px;
+	-webkit-border-bottom-right-radius: 8px;
+	-moz-border-radius-bottomleft: 8px;
+	-moz-border-radius-bottomright: 8px;
+}
+.mblEdgeToEdgeList .mblListItem:last-child {
+	border-bottom-color: #313431;
+}
+.mblListItem a.mblListItemAnchor {
+	background-position: 14px 17px;
+	display: block;
+	padding-left: 53px;
+	text-decoration: none;
+	-webkit-tap-highlight-color: transparent;
+}
+.mblListItem a.mblListItemAnchorNoIcon {
+	padding-left: 14px;
+}
+.mblItemSelected a.mblListItemAnchor {
+	color: black;
+}
+.mblListItem a.mblListItemAnchorHasRightButton {
+	padding-right: 50px;
+}
+
+.mblListItem .mblArrow {
+	position: absolute;
+	top: 26px;
+	right: 12px;
+	width: 6px;
+	height: 6px;
+	font-size: 1px;
+	-webkit-transform: rotate(45deg);
+	border-width: 3px 3px 0px 0px;
+	border-style: solid;
+	border-color: #808080;
+}
+.mblItemSelected .mblArrow {
+	border-color: white;
+}
+.mblVariableHeight div.mblArrow {
+	top: 50%;
+	margin-top: -4px;
+}
+
+.mblRightText {
+	position: absolute;
+	top: 20px;
+	right: 30px;
+	color: white;
+	line-height: normal;
+}
+.mblListItem .mblRightButtonContainer {
+	position: absolute;
+	top: 50%;
+	right: 12px;
+}
+.mblListItem .mblRightButton {
+	position: absolute;
+	top: -50%;
+}
+.mblListItemSubText {
+	font-size: 14px;
+	color: gray;
+}
+
+/* Switch */
+.mblSwitch {
+	position: relative;
+	width: 94px;
+	height: 27px;
+	overflow: hidden;
+}
+.mblItemSwitch {
+	position: absolute;
+	top: 18px;
+	right: 12px;
+}
+.mblSwitchInner {
+	position: absolute;
+	top: 0px;
+	height: 27px;
+}
+.mblSwitchAnimation .mblSwitchInner {
+	-webkit-transition-property: left;
+	-webkit-transition-duration: .3s;
+}
+.mblSwitchOn .mblSwitchInner {
+	left: 0px;
+}
+.mblSwitchOff .mblSwitchInner {
+	left: -53px;
+}
+.mblSwitchBg {
+	position: absolute;
+	top: 0px;
+	height: 27px;
+	border-width: 1px;
+	border-style: inset;
+	border-color: #9CACC0;
+	font-family: Helvetica;
+	font-size: 16px;
+	font-weight: bold;
+	line-height: 29px;
+	-webkit-border-radius: 2px;
+	-moz-border-radius: 2px;
+	-webkit-box-sizing: border-box;
+	-moz-box-sizing: border-box;
+	-webkit-tap-highlight-color: transparent;
+}
+.mblSwitchBgLeft {
+	left: 0px;
+	width: 94px;
+	color: white;
+	background-color: #00D300;
+	background: -webkit-gradient(linear, left top, left bottom, from(#00A200), to(#00D300), color-stop(0.2, #00BA00), color-stop(0.2, #00BA00));
+}
+.mblSwitchBgRight {
+	left: 53px;
+	width: 94px;
+	color: #7F7F7F;
+	background-color: #EEEEEE;
+	background: -webkit-gradient(linear, left top, left bottom, from(#BDBEBD), to(#F7F3F7));
+}
+.mblSwitchKnob {
+	position: absolute;
+	top: 1px;
+	left: 53px;
+	width: 41px;
+	height: 26px;
+	font-size: 1px;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #EFEFEF #A5A5A5 #969696 #325E9E;
+	line-height: 29px;
+	background-color: #CCCCCC;
+	background: -webkit-gradient(linear, left top, left bottom, from(#9C9A9C), to(#848284));
+	-webkit-border-radius: 2px;
+	-moz-border-radius: 2px;
+	-webkit-box-sizing: border-box;
+	-moz-box-sizing: border-box;
+}
+.mblSwitchText {
+	position: relative;
+	top: 0px;
+	width: 53px;
+	height: 27px;
+	padding: 0px;
+	text-align: center;
+}
+.mblSwitchTextLeft {
+	left: 0px;
+}
+.mblSwitchTextRight {
+	left: 40px;
+}
+
+/* Icon Container */
+.mblIconContainer {
+	padding: 0px;
+	margin: 20px 0px 0px 10px;
+	padding: 0px 0px 40px 0px;
+}
+.mblIconItem {
+	list-style-type: none;
+	float: left;
+}
+.mblIconItemTerminator {
+	list-style-type: none;
+	height: 20px;
+	clear: both;
+}
+.mblIconItemSub {
+	list-style-type: none;
+	margin-left: -10px;
+	background-color: white;
+	color: black;
+}
+
+.mblIconArea {
+	font-family: Helvetica;
+	font-size: 12px;
+	height: 78px;
+	width: 74px;
+	text-align: center;
+	margin-bottom: 10px;
+	color: white;
+}
+
+.mblIconArea DIV {
+	position: relative;
+	height: 65px;
+}
+
+.mblIconArea IMG {
+	position: absolute;
+	top: 0px;
+	left: 6px;
+}
+
+.mblContent {
+	clear: both;
+	padding-bottom: 20px;
+}
+
+table.mblClose {
+	clear: both;
+	cursor: pointer;
+}
+
+.mblVibrate{
+	position: relative;
+	-webkit-animation-duration: .5s;
+	-webkit-animation-timing-function: ease-in-out;
+	-webkit-animation-iteration-count: 20;
+	-webkit-animation-name: vibrate;
+	-webkit-transform: rotate(0deg);
+}
+ at -webkit-keyframes vibrate{
+	0%{
+		-webkit-transform: rotate(-2deg);
+		bottom: -1px;
+		left: -1px;
+	}
+	25% {
+		-webkit-transform: rotate(1deg);
+		bottom: 2px;
+		left: 1px;
+	}
+	50% {
+		-webkit-transform: rotate(-1deg);
+		bottom: -2px;
+		left: -1px;
+	}
+	75% {
+		-webkit-transform: rotate(2deg);
+		bottom: 2px;
+		left: 1px;
+	}
+	100% {
+		-webkit-transform: rotate(-2deg);
+		bottom: -1px;
+		left: -1px;
+	}
+}
+
+.mblCloseContent{
+	-webkit-animation-duration: .3s;
+	-webkit-animation-timing-function: ease-in-out;
+	-webkit-animation-name: shrink;
+	-webkit-transform: scale(0.01);
+}
+.mblCloseContent.mblShrink0{
+	-webkit-animation-name: shrink0;
+}
+.mblCloseContent.mblShrink1{
+	-webkit-animation-name: shrink1;
+}
+.mblCloseContent.mblShrink2{
+	-webkit-animation-name: shrink2;
+}
+.mblCloseContent.mblShrink3{
+	-webkit-animation-name: shrink3;
+}
+ at -webkit-keyframes shrink{
+	from { -webkit-transform: scale(1); }
+	to { -webkit-transform: scale(0.01); }
+}
+ at -webkit-keyframes shrink0{
+	from { -webkit-transform: scale(1); }
+	to { -webkit-transform: translate(-40%,-70%) scale(0.01); }
+}
+ at -webkit-keyframes shrink1{
+	from { -webkit-transform: scale(1); }
+	to { -webkit-transform: translate(-14%,-70%) scale(0.01); }
+}
+ at -webkit-keyframes shrink2{
+	from { -webkit-transform: scale(1); }
+	to { -webkit-transform: translate(14%,-70%) scale(0.01); }
+}
+ at -webkit-keyframes shrink3{
+	from { -webkit-transform: scale(1); }
+	to { -webkit-transform: translate(40%,-70%) scale(0.01); }
+}
+
+/* Icon Content Heading */
+.mblIconContentHeading {
+	position: relative;
+	clear: both;
+	height: 25px;
+	padding-left: 40px;
+	margin-top: 0px;
+	background: -webkit-gradient(linear, left top, left bottom, from(#E0E4E7), to(#B4BEC6), color-stop(0.5, #C4CCD2), color-stop(0.5, #BFC8CE));
+	border-top: 1px solid #F1F3F4;
+	border-bottom: 1px solid #717D85;
+	font-family: Helvetica;
+	font-size: 14px;
+	color: white;
+	line-height: 26px;
+	text-shadow: rgba(0,0,0,0.6) 0px -1px 0px;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+/* dojox.mobile.Button */
+.mblButton {
+	padding: 0px 10px;
+	height: 29px;
+	border-width: 1px 1px 1px 1px;
+	border-style: outset;
+	color: white;
+	font-family: Helvetica;
+	font-size: 13px;
+	line-height: 29px;
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	-webkit-tap-highlight-color: transparent;
+}
+.mblBlueButton {
+	border-color: #9CACC0;
+	background-color: #366EDF;
+	background: -webkit-gradient(linear, left top, left bottom, from(#7A9DE9), to(#2362DD), color-stop(0.5, #366EDF), color-stop(0.5, #215FDC));
+	-webkit-tap-highlight-color: transparent;
+}
+.mblBlueButtonSelected {
+	background: -webkit-gradient(linear, left top, left bottom, from(#8EA4C1), to(#4A6C9B), color-stop(0.5, #5877A2), color-stop(0.5, #476999));
+}
+
+/* Tab Container */
+.mblTabContainer {
+}
+
+.mblTabButton {
+	position: relative;
+	float: left;
+	width: 78px;
+	text-align: center;
+	height: 61px;
+	margin-right: 2px;
+	border-width: 0px 1px 0px 1px;
+	border-style: solid;
+	border-color: black #182018 black #393C39;
+	font-family: Helvetica;
+	font-size: 13px;
+	color: white;
+	background-color: #212421;
+	background: -webkit-gradient(linear, left top, left bottom, from(#181818), to(#100C10), color-stop(0.1, #313031));
+	-webkit-tap-highlight-color: transparent;
+}
+.mblTabButtonSelected.mblTabButton {
+	background-color: #8C8E8C;
+	background: -webkit-gradient(linear, left top, left bottom, from(#A59EA5), to(#848284));
+}
+.mblTabButtonHighlighted.mblTabButton {
+	background-color: #FFB600;
+	background: -webkit-gradient(linear, left top, left bottom, from(#FFCB00), to(#FF9A00));
+}
+.mblTabButtonImgDiv {
+	position: relative;
+	margin-left: 24px;
+	height: 40px;
+}
+.mblTabButton IMG {
+	position: absolute;
+	left: 0px;
+	margin-top: 8px;
+}
+
+.mblTabPanelHeader {
+	position: relative;
+	height: 64px;
+	margin: 0px;
+	padding: 0px 0px 0px 0px;
+	background-color: #000000;
+	border-top: 1px solid #CDD5DF;
+	border-bottom: 2px solid #949694;
+	font-family: Helvetica;
+	font-size: 20px;
+	color: white;
+	text-align: center;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+.mblTabPanelPane {
+}
+
+.mblTabPane {
+}
+
+/* Progress Indicator */
+.mblProgContainer {
+	position: absolute;
+	width: 36px;
+	height: 36px;
+	top: 180px;
+	left: 50%;
+	margin: -18px 0px 0px -18px;
+}
+.mblProg {
+	position: absolute;
+	left: 0px;
+	top: 0px;
+	width: 11px;
+	font-size: 1px;
+	height: 4px;
+	overflow: hidden;
+	-webkit-transform-origin: 0 2px;
+	background-color: #C0C0C0;
+	-webkit-border-radius: 2px;
+	-moz-border-radius: 2px;
+}
+.mblProg0 {
+	-webkit-transform: translate(18px,10px) rotate(-90deg);
+}
+.mblProg1 {
+	-webkit-transform: translate(22px,11px) rotate(-60deg);
+}
+.mblProg2 {
+	-webkit-transform: translate(25px,14px) rotate(-30deg);
+}
+.mblProg3 {
+	-webkit-transform: translate(26px,18px) rotate(0deg);
+}
+.mblProg4 {
+	-webkit-transform: translate(25px,22px) rotate(30deg);
+}
+.mblProg5 {
+	-webkit-transform: translate(22px,25px) rotate(60deg);
+}
+.mblProg6 {
+	-webkit-transform: translate(18px,26px) rotate(90deg);
+}
+.mblProg7 {
+	-webkit-transform: translate(14px,25px) rotate(120deg);
+}
+.mblProg8 {
+	-webkit-transform: translate(11px,22px) rotate(150deg);
+}
+.mblProg9 {
+	-webkit-transform: translate(10px,18px) rotate(180deg);
+}
+.mblProg10 {
+	-webkit-transform: translate(11px,14px) rotate(210deg);
+}
+.mblProg11 {
+	-webkit-transform: translate(14px,11px) rotate(240deg);
+}
diff --git a/dojox/mobile/themes/android/compat/arrow-button-bg.png b/dojox/mobile/themes/android/compat/arrow-button-bg.png
new file mode 100755
index 0000000..7ac8061
Binary files /dev/null and b/dojox/mobile/themes/android/compat/arrow-button-bg.png differ
diff --git a/dojox/mobile/themes/android/compat/arrow-button-head.png b/dojox/mobile/themes/android/compat/arrow-button-head.png
new file mode 100755
index 0000000..74ecb76
Binary files /dev/null and b/dojox/mobile/themes/android/compat/arrow-button-head.png differ
diff --git a/dojox/mobile/themes/android/compat/blue-button-bg.png b/dojox/mobile/themes/android/compat/blue-button-bg.png
new file mode 100755
index 0000000..3bd558b
Binary files /dev/null and b/dojox/mobile/themes/android/compat/blue-button-bg.png differ
diff --git a/dojox/mobile/themes/android/compat/blue-button-sel-bg.png b/dojox/mobile/themes/android/compat/blue-button-sel-bg.png
new file mode 100755
index 0000000..6968458
Binary files /dev/null and b/dojox/mobile/themes/android/compat/blue-button-sel-bg.png differ
diff --git a/dojox/mobile/themes/android/compat/gray-arrow.png b/dojox/mobile/themes/android/compat/gray-arrow.png
new file mode 100755
index 0000000..c93d17f
Binary files /dev/null and b/dojox/mobile/themes/android/compat/gray-arrow.png differ
diff --git a/dojox/mobile/themes/android/compat/icon-content-heading-bg.png b/dojox/mobile/themes/android/compat/icon-content-heading-bg.png
new file mode 100755
index 0000000..3daa1a8
Binary files /dev/null and b/dojox/mobile/themes/android/compat/icon-content-heading-bg.png differ
diff --git a/dojox/mobile/themes/android/compat/switch-blue-bg.png b/dojox/mobile/themes/android/compat/switch-blue-bg.png
new file mode 100755
index 0000000..78c9647
Binary files /dev/null and b/dojox/mobile/themes/android/compat/switch-blue-bg.png differ
diff --git a/dojox/mobile/themes/android/compat/switch-gray-bg.png b/dojox/mobile/themes/android/compat/switch-gray-bg.png
new file mode 100755
index 0000000..04e884e
Binary files /dev/null and b/dojox/mobile/themes/android/compat/switch-gray-bg.png differ
diff --git a/dojox/mobile/themes/android/compat/switch-green-bg.png b/dojox/mobile/themes/android/compat/switch-green-bg.png
new file mode 100644
index 0000000..182310a
Binary files /dev/null and b/dojox/mobile/themes/android/compat/switch-green-bg.png differ
diff --git a/dojox/mobile/themes/android/compat/switch-knob-bg.png b/dojox/mobile/themes/android/compat/switch-knob-bg.png
new file mode 100755
index 0000000..e2d75fe
Binary files /dev/null and b/dojox/mobile/themes/android/compat/switch-knob-bg.png differ
diff --git a/dojox/mobile/themes/android/compat/tab-button-bg.png b/dojox/mobile/themes/android/compat/tab-button-bg.png
new file mode 100755
index 0000000..548ef73
Binary files /dev/null and b/dojox/mobile/themes/android/compat/tab-button-bg.png differ
diff --git a/dojox/mobile/themes/android/compat/tab-orange-button-bg.png b/dojox/mobile/themes/android/compat/tab-orange-button-bg.png
new file mode 100755
index 0000000..56f555b
Binary files /dev/null and b/dojox/mobile/themes/android/compat/tab-orange-button-bg.png differ
diff --git a/dojox/mobile/themes/android/compat/tab-sel-button-bg.png b/dojox/mobile/themes/android/compat/tab-sel-button-bg.png
new file mode 100755
index 0000000..c454088
Binary files /dev/null and b/dojox/mobile/themes/android/compat/tab-sel-button-bg.png differ
diff --git a/dojox/mobile/themes/buttons-compat.css b/dojox/mobile/themes/buttons-compat.css
new file mode 100755
index 0000000..0c2a925
--- /dev/null
+++ b/dojox/mobile/themes/buttons-compat.css
@@ -0,0 +1,30 @@
+.mblBlueMinusButton {
+	background-image: url(compat/small-blue-button-bg.png);
+}
+.mblDarkBlueMinusButton {
+	background-image: url(compat/small-darkblue-button-bg.png);
+}
+.mblRedMinusButton {
+	background-image: url(compat/small-red-button-bg.png);
+}
+.mblBluePlusButton {
+	background-image: url(compat/small-blue-button-bg.png);
+}
+.mblDarkBluePlusButton {
+	background-image: url(compat/small-darkblue-button-bg.png);
+}
+.mblRedPlusButton {
+	background-image: url(compat/small-red-button-bg.png);
+}
+.mblCheckOnButton {
+	background-image: url(compat/check-on-button.png);
+}
+.mblCheckOnButton DIV, .mblCheckOnButton P {
+	display: none;
+}
+.mblCheckOffButton {
+	background-image: url(compat/check-off-button.png);
+}
+.mblCheckOffButton DIV, .mblCheckOffButton P {
+	display: none;
+}
diff --git a/dojox/mobile/themes/buttons.css b/dojox/mobile/themes/buttons.css
new file mode 100755
index 0000000..0bf86ec
--- /dev/null
+++ b/dojox/mobile/themes/buttons.css
@@ -0,0 +1,191 @@
+/* Minus Button */
+.mblBlueMinusButton {
+	position: relative;
+	width: 22px;
+	height: 18px;
+	border-width: 1px 1px 1px 0px;
+	border-style: outset;
+	border-color: #6D89C7;
+	color: white;
+	-webkit-border-radius: 3px;
+	-moz-border-radius: 3px;
+	background-color: #366EDF;
+	background: -webkit-gradient(linear, left top, left bottom, from(#7A9DE9), to(#2362DD), color-stop(0.5, #366EDF), color-stop(0.5, #215FDC));
+}
+.mblDarkBlueMinusButton {
+	position: relative;
+	width: 22px;
+	height: 18px;
+	border-width: 1px 1px 1px 0px;
+	border-style: outset;
+	border-color: #6D89C7;
+	color: white;
+	-webkit-border-radius: 3px;
+	-moz-border-radius: 3px;
+	background-color: #5877A2;
+	background: -webkit-gradient(linear, left top, left bottom, from(#8EA4C1), to(#4A6C9B), color-stop(0.5, #5877A2), color-stop(0.5, #476999));
+}
+.mblRedMinusButton {
+	position: relative;
+	width: 22px;
+	height: 18px;
+	border-width: 1px 1px 1px 0px;
+	border-style: outset;
+	border-color: #cc1122;
+	color: white;
+	-webkit-border-radius: 3px;
+	-moz-border-radius: 3px;
+	background-color: #C9404B;
+	background: -webkit-gradient(linear, left top, left bottom, from(#D3656D), to(#BC1320), color-stop(0.5, #C9404B), color-stop(0.5, #BC1421));
+}
+.mblBlueMinusButton DIV, .mblDarkBlueMinusButton DIV, .mblRedMinusButton DIV {
+	position: absolute;
+	top: 7px;
+	left: 7px;
+	width: 8px;
+	height: 2px;
+	margin: 0px;
+	font-size: 1px;
+	background-color: white;
+	border-top: 1px solid #4A5A71;
+}
+
+/* Plus Button */
+.mblBluePlusButton {
+	position: relative;
+	width: 22px;
+	height: 18px;
+	border-width: 1px 1px 1px 0px;
+	border-style: outset;
+	border-color: #6D89C7;
+	color: white;
+	-webkit-border-radius: 3px;
+	-moz-border-radius: 3px;
+	background-color: #366EDF;
+	background: -webkit-gradient(linear, left top, left bottom, from(#7A9DE9), to(#2362DD), color-stop(0.5, #366EDF), color-stop(0.5, #215FDC));
+}
+.mblDarkBluePlusButton {
+	position: relative;
+	width: 22px;
+	height: 18px;
+	border-width: 1px 1px 1px 0px;
+	border-style: outset;
+	border-color: #6D89C7;
+	color: white;
+	-webkit-border-radius: 3px;
+	-moz-border-radius: 3px;
+	background-color: #5877A2;
+	background: -webkit-gradient(linear, left top, left bottom, from(#8EA4C1), to(#4A6C9B), color-stop(0.5, #5877A2), color-stop(0.5, #476999));
+}
+.mblRedPlusButton {
+	position: relative;
+	width: 22px;
+	height: 18px;
+	border-width: 1px 1px 1px 0px;
+	border-style: outset;
+	border-color: #6D89C7;
+	color: white;
+	-webkit-border-radius: 3px;
+	-moz-border-radius: 3px;
+	background-color: #C9404B;
+	background: -webkit-gradient(linear, left top, left bottom, from(#D3656D), to(#BC1320), color-stop(0.5, #C9404B), color-stop(0.5, #BC1421));
+}
+.mblBluePlusButton DIV, .mblDarkBluePlusButton DIV, .mblRedPlusButton DIV {
+	position: absolute;
+	top: 7px;
+	left: 7px;
+	width: 8px;
+	height: 2px;
+	margin: 0px;
+	font-size: 1px;
+	background-color: white;
+	border-top: 1px solid #4A5A71;
+}
+.mblBluePlusButton P, .mblDarkBluePlusButton P, .mblRedPlusButton P {
+	position: absolute;
+	top: 4px;
+	left: 10px;
+	width: 2px;
+	height: 8px;
+	margin: 0px;
+	font-size: 1px;
+	background-color: white;
+}
+
+.mblCheckOnButton {
+	position: relative;
+	width: 30px;
+	height: 30px;
+	border-width: 1px;
+	border-style: outset;
+	border-color: #A5A2A5;
+	color: white;
+	-webkit-border-radius: 3px;
+	-moz-border-radius: 3px;
+	background-color: #D6D3D6;
+	background: -webkit-gradient(linear, left top, left bottom, from(#EFF3EF), to(#BDBEBD));
+}
+.mblCheckOnButton DIV {
+	position: absolute;
+	top: 15px;
+	left: 3px;
+	width: 14px;
+	height: 4px;
+	margin: 0px;
+	font-size: 1px;
+	background-color: #00CF00;
+	border-top: 1px solid #4A5A71;
+	-webkit-border-radius: 2px;
+	-webkit-transform: rotate(50deg);
+}
+.mblCheckOnButton P {
+	position: absolute;
+	top: 11px;
+	left: 9px;
+	width: 20px;
+	height: 4px;
+	margin: 0px;
+	font-size: 1px;
+	background-color: #00CF00;
+	border-bottom: 1px solid #4A5A71;
+	-webkit-border-radius: 2px;
+	-webkit-transform: rotate(-50deg);
+}
+
+.mblCheckOffButton {
+	position: relative;
+	width: 30px;
+	height: 30px;
+	border-width: 1px;
+	border-style: outset;
+	border-color: #A5A2A5;
+	color: white;
+	-webkit-border-radius: 3px;
+	-moz-border-radius: 3px;
+	background-color: #D6D3D6;
+	background: -webkit-gradient(linear, left top, left bottom, from(#EFF3EF), to(#BDBEBD));
+}
+.mblCheckOffButton DIV {
+	position: absolute;
+	top: 11px;
+	left: 9px;
+	width: 20px;
+	height: 4px;
+	font-size: 1px;
+	background-color: #BDBABD;
+	border-top: 1px solid #8C8E8C;
+	-webkit-border-radius: 2px;
+	-webkit-transform: rotate(-50deg);
+}
+.mblCheckOffButton P {
+	position: absolute;
+	top: 15px;
+	left: 3px;
+	width: 14px;
+	height: 4px;
+	font-size: 1px;
+	background-color: #BDBABD;
+	border-bottom: 1px solid #8C8E8C;
+	-webkit-border-radius: 2px;
+	-webkit-transform: rotate(50deg);
+}
diff --git a/dojox/mobile/themes/compat/check-off-button.png b/dojox/mobile/themes/compat/check-off-button.png
new file mode 100755
index 0000000..fa7df3e
Binary files /dev/null and b/dojox/mobile/themes/compat/check-off-button.png differ
diff --git a/dojox/mobile/themes/compat/check-on-button.png b/dojox/mobile/themes/compat/check-on-button.png
new file mode 100755
index 0000000..2cec24f
Binary files /dev/null and b/dojox/mobile/themes/compat/check-on-button.png differ
diff --git a/dojox/mobile/themes/compat/small-blue-button-bg.png b/dojox/mobile/themes/compat/small-blue-button-bg.png
new file mode 100755
index 0000000..8d524b7
Binary files /dev/null and b/dojox/mobile/themes/compat/small-blue-button-bg.png differ
diff --git a/dojox/mobile/themes/compat/small-darkblue-button-bg.png b/dojox/mobile/themes/compat/small-darkblue-button-bg.png
new file mode 100755
index 0000000..f090e1d
Binary files /dev/null and b/dojox/mobile/themes/compat/small-darkblue-button-bg.png differ
diff --git a/dojox/mobile/themes/compat/small-red-button-bg.png b/dojox/mobile/themes/compat/small-red-button-bg.png
new file mode 100755
index 0000000..f28eba3
Binary files /dev/null and b/dojox/mobile/themes/compat/small-red-button-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/arrow-button-bg.png b/dojox/mobile/themes/iphone/compat/arrow-button-bg.png
new file mode 100755
index 0000000..5efaa9e
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/arrow-button-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/arrow-button-head.png b/dojox/mobile/themes/iphone/compat/arrow-button-head.png
new file mode 100755
index 0000000..85beb43
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/arrow-button-head.png differ
diff --git a/dojox/mobile/themes/iphone/compat/blue-button-bg.png b/dojox/mobile/themes/iphone/compat/blue-button-bg.png
new file mode 100755
index 0000000..3bd558b
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/blue-button-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/blue-button-sel-bg.png b/dojox/mobile/themes/iphone/compat/blue-button-sel-bg.png
new file mode 100755
index 0000000..6968458
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/blue-button-sel-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/edge-categ-bg.png b/dojox/mobile/themes/iphone/compat/edge-categ-bg.png
new file mode 100644
index 0000000..3a62e14
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/edge-categ-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/gray-arrow.png b/dojox/mobile/themes/iphone/compat/gray-arrow.png
new file mode 100755
index 0000000..c93d17f
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/gray-arrow.png differ
diff --git a/dojox/mobile/themes/iphone/compat/heading-bg.png b/dojox/mobile/themes/iphone/compat/heading-bg.png
new file mode 100755
index 0000000..888a92e
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/heading-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/icon-content-heading-bg.png b/dojox/mobile/themes/iphone/compat/icon-content-heading-bg.png
new file mode 100755
index 0000000..3daa1a8
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/icon-content-heading-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/switch-blue-bg.png b/dojox/mobile/themes/iphone/compat/switch-blue-bg.png
new file mode 100755
index 0000000..78c9647
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/switch-blue-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/switch-gray-bg.png b/dojox/mobile/themes/iphone/compat/switch-gray-bg.png
new file mode 100755
index 0000000..04e884e
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/switch-gray-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/switch-knob-bg.png b/dojox/mobile/themes/iphone/compat/switch-knob-bg.png
new file mode 100755
index 0000000..e2d75fe
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/switch-knob-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/tab-button-bg.png b/dojox/mobile/themes/iphone/compat/tab-button-bg.png
new file mode 100755
index 0000000..f8d6ef0
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/tab-button-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/tab-sel-button-bg.png b/dojox/mobile/themes/iphone/compat/tab-sel-button-bg.png
new file mode 100755
index 0000000..c3b0a33
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/tab-sel-button-bg.png differ
diff --git a/dojox/mobile/themes/iphone/compat/white-arrow.png b/dojox/mobile/themes/iphone/compat/white-arrow.png
new file mode 100755
index 0000000..84e435a
Binary files /dev/null and b/dojox/mobile/themes/iphone/compat/white-arrow.png differ
diff --git a/dojox/mobile/themes/iphone/images/thumb-overlay.png b/dojox/mobile/themes/iphone/images/thumb-overlay.png
new file mode 100755
index 0000000..b16efec
Binary files /dev/null and b/dojox/mobile/themes/iphone/images/thumb-overlay.png differ
diff --git a/dojox/mobile/themes/iphone/iphone-app-compat.css b/dojox/mobile/themes/iphone/iphone-app-compat.css
new file mode 100755
index 0000000..dc0a814
--- /dev/null
+++ b/dojox/mobile/themes/iphone/iphone-app-compat.css
@@ -0,0 +1,24 @@
+/* mbl.widget.Heading */
+ at import url("iphone-compat.css");
+
+.alertTitle {
+	background-image: url(compat/heading-bg.png);
+}
+
+.mblImageThumbView .mblThumb {
+	-moz-transition: all 0.5s ease-in-out;
+	-o-transition: all 0.5s ease-in-out;
+}
+
+.mblImageThumbView .mblThumb:hover {
+	-moz-transform: scale(1.2);
+	-moz-transition: all 0.3s ease-in-out;
+	-o-transform: scale(1.2);
+	-o-transition: all 0.3s ease-in-out;
+}
+.mblImageThumbView .mblThumbInner .mblThumbMask .mblThumbSrc {
+  -moz-background-size: 100% 100%;
+  -moz-border-radius: 5px;
+  -o-background-size: 100% 100%;
+  -o-border-radius: 5px;
+}
\ No newline at end of file
diff --git a/dojox/mobile/themes/iphone/iphone-app.css b/dojox/mobile/themes/iphone/iphone-app.css
new file mode 100644
index 0000000..4f19ecb
--- /dev/null
+++ b/dojox/mobile/themes/iphone/iphone-app.css
@@ -0,0 +1,281 @@
+ at import url("iphone.css");
+
+.alertDialog {
+	width: 100%;
+	padding-left: 2px;
+	padding-right: 2px;
+	z-index: 1000;
+}
+
+.alertDialogBody {
+	border: 1px solid #ADAAAD;
+	-webkit-border-radius: 10px;
+	-moz-border-radius: 10px;
+	background-color: white;
+	margin-left: 2px;
+	margin-right: 4px;
+}
+
+.alertTitle {
+	height: 42px;
+	margin: 0px;
+	padding: 0px;
+	background-color: #889BB3;
+	background: -webkit-gradient(linear, left top, left bottom, from(#B0BCCD), to(#6D84A2), color-stop(0.5, #889BB3), color-stop(0.5, #8195AF));
+	border-top: 1px solid #CDD5DF;
+	border-bottom: 1px solid #2D3642;
+	font-family: Helvetica;
+	font-size: 20px;
+	color: white;
+	text-align: center;
+	line-height: 44px;
+	text-shadow: rgba(0,0,0,0.6) 0px -1px 0px;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+	text-align: center;
+}
+
+.alertText {	
+	text-align: center;
+}
+
+.alertBtns {
+	padding: 5px;
+	text-align: center;
+}
+
+.alertBtns .mblButton {
+	width: 100%;
+	margin-top: 5px;
+}
+
+.alertDialog.out {
+	position: absolute;
+}
+
+.alertDialog.in {
+	position: absolute;
+}
+
+.slidev.out {
+	-webkit-animation-duration: .4s;
+	-webkit-animation-name: slideOut;
+	-webkit-animation-timing-function: linear;
+	-webkit-transform: translateY(-100%);
+}
+.slidev.in {
+	-webkit-animation-duration: .4s;
+	-webkit-animation-name: slideIn;
+	-webkit-animation-timing-function: linear;
+	-webkit-transform: translateY(0px);
+}
+.slidev.out.reverse {
+	-webkit-animation-name: slideOutReverse;
+}
+.slidev.in.reverse {
+	-webkit-animation-name: slideInReverse;
+}
+
+.dialogUnderlayWrapper {
+	position: absolute;
+	left: 0;
+	top: 0;
+	z-index: 998;
+	background: transparent !important;
+	visibility: visible;
+	height: 100%;
+	width: 100%;
+}
+
+.dialogUnderlay {
+	background-color: #eee;
+	opacity: 0.5;
+	width: 100%;
+	height: 100%;
+}
+
+.list .row {
+	padding: 10px;
+	border-bottom: 1px solid #444;
+	position: relative;
+	background-color: white;
+	z-index: 6; /* Must be greater than the .buttons z-index */
+}
+.list .row.mblListItem {
+	padding: 0px;
+}
+
+.list .row.last {
+	border-bottom: none;
+}
+
+.list .row.hold {
+	background-color: #ddd;
+}
+
+.list .buttons {
+	position: absolute;
+	text-align: center;
+	padding-top: 10px;
+	width: 100%;
+	height: 100%;
+	z-index: 5;
+}
+
+.list .buttons .mblButton {
+}
+
+.list .buttons .deleteBtn {
+	background-color: red;
+	
+}
+.list .buttons .cancelBtn {
+	margin-left: 10px;
+	background-color: blue;
+}
+
+.row.collapsed { 
+	-webkit-animation-name: collapse-vert;
+	-webkit-animation-duration: 0.5s;
+	-webkit-animation-timing-function: linear;
+}
+
+ at -webkit-keyframes collapse-vert {
+	from {
+		height: 100%;
+		padding: 10px;
+	}
+	to {
+		height: 0px;
+		padding: 0px;
+	} 
+}
+
+.listSelector {
+	position: absolute;
+	-webkit-border-radius: 10px;
+	-moz-border-radius: 10px;
+	border: 1px solid #666;
+	background-color: #ccc;
+	color: #333;
+	z-index: 1000;
+}
+.listSelectorRow {
+	padding: 10px;
+	border-bottom: 1px solid #666;
+	white-space: nowrap;
+}
+.listSelectorRow-selected {
+	background-color: #666;
+	color: #ccc;
+}
+
+.listSelectorRow.last {
+ 	border-bottom: none;
+}
+
+.mblImageView, .mblImageView canvas {
+	width: 100%;
+	height: 100%;
+}
+
+.mblPillar {
+	display: none;
+}
+
+/* Form Input Styles */
+
+input {
+	-webkit-text-size-adjust: 140%;
+}
+ 
+ 
+/* ImageThumbView styles */
+.mblImageThumbView {
+	position: relative;
+}
+
+.mblImageThumbView .mblThumb {
+	width: 93px;
+	min-height: 100px;
+	display: inline-block;
+	padding: 4px 3px 0px 4px;
+	z-index: 2;
+	position: absolute;
+	-webkit-transition-property: -webkit-transform, opacity;
+	-webkit-transition-duration: 0.5s, 0.5s;
+	-webkit-transition-delay: 0, 0;
+}
+
+.mblImageThumbView .mblThumb.hidden {
+	z-index: 1;
+	opacity: 0;
+}
+
+.mblImageThumbView .mblThumbInner {
+	width: 102px;
+	height: 102px;
+	position: relative;
+}
+
+.mblImageThumbView .mblThumbOverlay {
+	width: 102px;
+	height: 102px;
+	background: url(images/thumb-overlay.png) center top no-repeat;
+	position: absolute;
+	z-index: 20;
+	overflow: hidden;
+}
+
+.mblImageThumbView .mblThumb.selected .mblThumbOverlay {
+	background: url(images/thumb-overlay.png) center bottom no-repeat;
+}
+
+
+.mblImageThumbView .mblThumbInner .mblThumbMask {
+  width: 90px;
+  height: 90px;
+  overflow: hidden;
+  padding-left: 6px;
+  padding-top: 5px;
+  z-index: 10;
+  
+}
+
+.mblImageThumbView .mblThumbInner .mblThumbMask img {
+  left: 0px;
+  top: 0px;
+  width: 90px;
+  height: 90px;
+}
+
+.mblImageThumbView .mblThumbInner .mblThumbMask .mblThumbSrc {
+  left: 6px;
+  top: 5px;
+  background-position: center center;
+  background-repeat: no-repeat;
+  overflow: hidden;
+  position: absolute;
+  -webkit-background-size: 100% 100%;
+  -webkit-border-radius: 5px;
+  width: 90px;
+  height: 90px;
+  z-index: 5;
+}
+
+.mblImageThumbView .mblThumbMask div {
+  left: 0px;
+  top: 0px;
+  width: 90px;
+  height: 90px;
+  background-repeat: no-repeat;
+}
+
+.mblImageThumbView .mblThumb:hover,
+.mblImageThumbView .mblThumb.selected  {
+	-webkit-transform: scale(1.2);
+}
+
+
+
diff --git a/dojox/mobile/themes/iphone/iphone-compat.css b/dojox/mobile/themes/iphone/iphone-compat.css
new file mode 100755
index 0000000..6080512
--- /dev/null
+++ b/dojox/mobile/themes/iphone/iphone-compat.css
@@ -0,0 +1,290 @@
+/* mbl.widget.Heading */
+.mblHeading {
+	background-image: url(compat/heading-bg.png);
+}
+
+/* Heading Arrow Button */
+.mblArrowButtonHead {
+	position: absolute;
+	top: 5px;
+	left: 6px;
+	width: 19px;
+	height: 29px;
+	background-image: url(compat/arrow-button-head.png);
+}
+.mblArrowButtonBody {
+	background-image: url(compat/arrow-button-bg.png);
+}
+
+/* Round Corner */
+.mblRoundCorner {
+	background-color: white;
+	height: 1px;
+	font-size: 1px;
+	overflow: hidden;
+	border-style: solid;
+	border-color: #ADAAAD;
+	border-width: 0px 1px;
+}
+.mblRoundRectContainer {
+	margin: 0px;
+	padding: 0px;
+	background-color: white;
+	border-style: solid;
+	border-color: #ADAAAD;
+	border-width: 0px 1px;
+}
+.mblRoundRect .mblRoundRectContainer {
+	padding: 3px 8px;
+}
+.mblRoundCorner0T {
+	height: 0px;
+}
+.mblRoundCorner1T {
+	background-color: #ADAAAD;
+	margin: 0px 5px;
+}
+.mblRoundCorner2T {
+	margin: 0px 2px;
+	border-width: 0px 3px;
+}
+.mblRoundCorner3T {
+	margin: 0px 1px;
+	border-width: 0px 2px;
+}
+.mblRoundCorner4T {
+	margin: 0px 1px;
+}
+.mblRoundCorner5T {
+	margin: 0px 1px;
+}
+
+.mblRoundCorner0B {
+	height: 0px;
+}
+.mblRoundCorner1B {
+	margin: 0px 1px;
+}
+.mblRoundCorner2B {
+	margin: 0px 1px;
+}
+.mblRoundCorner3B {
+	margin: 0px 1px;
+	border-width: 0px 2px;
+}
+.mblRoundCorner4B {
+	margin: 0px 2px;
+	border-width: 0px 3px;
+}
+.mblRoundCorner5B {
+	background-color: #ADAAAD;
+	margin: 0px 5px;
+}
+
+/* dojox.mobile.EdgeToEdgeCategory */
+.mblEdgeToEdgeCategory {
+	background-image: url(compat/edge-categ-bg.png);
+}
+
+/* mbl.widget.ListItem */
+*html li.mblListItem.mblVariableHeight { /* IE6 hack */
+	height: 0;
+}
+
+li.mblListItem .mblArrow, div.mblListItem .mblArrow {
+	border-style: none;
+	top: 16px;
+	width: 9px;
+	height: 13px;
+	background-image: url(compat/gray-arrow.png);
+}
+li.mblItemSelected .mblArrow, div.mblItemSelected .mblArrow {
+	background-image: url(compat/white-arrow.png);
+}
+
+/* Switch */
+.mblSwitchInner {
+	width: 100px;
+}
+.mblSwitchBg {
+	border: none;
+}
+.mblSwitchBgLeft {
+	width: 89px;
+	background: none;
+}
+.mblSwitchBgRight {
+	width: 89px;
+	left: 58px;
+	background: none;
+}
+.mblSwitchKnobContainer {
+	position: relative;
+	left: 53px;
+	width: 41px;
+	height: 26px;
+}
+.mblSwitchKnob {
+	position: relative;
+	top: 0px;
+	left: 0px;
+	width: auto;
+	height: 21px;
+	background-image: url(compat/switch-knob-bg.png);
+	border-width: 0px 1px;
+	-moz-border-radius: 0px;
+}
+.mblSwitchCorner {
+	position: relative;
+	height: 1px;
+	font-size: 1px;
+	overflow: hidden;
+	border-style: solid;
+	border-color: #878787;
+}
+.mblSwitchCorner1T {
+	background-color: #848684;
+	margin: 0px 4px;
+	border-width: 0px;
+}
+.mblSwitchCorner2T {
+	background-color: #C0C0C0;
+	margin: 0px 2px;
+	border-width: 0px 2px;
+}
+.mblSwitchCorner3T {
+	background-color: #C6C7C6;
+	margin: 0px 1px;
+	border-width: 0px 1px;
+}
+
+.mblSwitchCorner1B {
+	background-color: #FBFBFB;
+	margin: 0px 1px;
+	border-width: 0px 1px;
+}
+.mblSwitchCorner2B {
+	background-color: #FBFBFB;
+	margin: 0px 2px;
+	border-width: 0px 2px;
+}
+.mblSwitchCorner3B {
+	background-color: #878787;
+	margin: 0px 4px;
+	border-width: 0px;
+}
+
+.mblSwitchBgLeft .mblSwitchCorner1T {
+	border-width: 0px 2px;
+	background-color: #093889;
+}
+.mblSwitchBgLeft .mblSwitchCorner2T {
+	background-color: #285AB2;
+}
+.mblSwitchBgLeft .mblSwitchCorner3T {
+	background-color: #285AB2;
+}
+
+.mblSwitchBgLeft .mblSwitchCorner1B {
+	background-color: #66A1F6;
+}
+.mblSwitchBgLeft .mblSwitchCorner2B {
+	background-color: #66A1F6;
+}
+.mblSwitchBgLeft .mblSwitchCorner3B {
+	background-color: #5289D7;
+}
+
+.mblSwitchText {
+	height: 21px;
+	line-height: 21px;
+}
+.mblSwitchTextLeft {
+	background-image: url(compat/switch-blue-bg.png);
+	border-left: 1px solid #848684;
+}
+.mblSwitchTextRight {
+	background-image: url(compat/switch-gray-bg.png);
+	left: 35px;
+	border-right: 1px solid #848684;
+}
+
+/* Icon Content Heading */
+.mblIconContentHeading {
+	background-image: url(compat/icon-content-heading-bg.png);
+}
+
+/* dojox.mobile.Button */
+.mblBlueButton {
+	background-image: url(compat/blue-button-bg.png);
+}
+.mblBlueButtonSelected {
+	background-image: url(compat/blue-button-sel-bg.png);
+}
+
+/* Tab Container */
+.mblTabPanelHeader {
+	background-image: url(compat/heading-bg.png);
+}
+.mblTabButton {
+	background-image: url(compat/tab-button-bg.png);
+}
+.mblTabButtonSelected {
+	background-image: url(compat/tab-sel-button-bg.png);
+}
+*html .mblTabButton { /* IE6 hack */
+	behavior: expression(
+		(function(el){
+			if(!el.previousSibling)
+				el.style.borderWidth = "1px";
+			el.style.behavior = "none";
+		})(this)
+	);
+}
+
+/* Progress Indicator */
+.mblProg {
+	position: absolute;
+	top: 0px;
+	width: 4px;
+	font-size: 1px;
+	height: 36px;
+	overflow: hidden;
+	background-color: #C0C0C0;
+}
+.mblProg0 {
+	left: 0px;
+}
+.mblProg1 {
+	left: 8px;
+}
+.mblProg2 {
+	left: 16px;
+}
+.mblProg3 {
+	left: 24px;
+}
+.mblProg4 {
+	left: 32px;
+}
+.mblProg5 {
+	left: 40px;
+}
+.mblProg6 {
+	left: 48px;
+}
+.mblProg7 {
+	left: 56px;
+}
+.mblProg8 {
+	left: 64px;
+}
+.mblProg9 {
+	left: 72px;
+}
+.mblProg10 {
+	left: 80px;
+}
+.mblProg11 {
+	left: 80px;
+}
diff --git a/dojox/mobile/themes/iphone/iphone.css b/dojox/mobile/themes/iphone/iphone.css
new file mode 100755
index 0000000..88939d1
--- /dev/null
+++ b/dojox/mobile/themes/iphone/iphone.css
@@ -0,0 +1,751 @@
+body {
+	visibility: hidden;
+}
+
+html.mobile, .mobile body {
+	width: 100%;
+	margin: 0px;
+	padding: 0px;
+}
+.mobile body {
+	overflow-x: hidden;
+	-webkit-text-size-adjust: none;
+	background-color: rgb(197,204,211);
+	font-family: Helvetica;
+	font-size: 17px;
+	min-height: 416px;
+}
+
+/* dojox.mobile.View */
+.mblView {
+	position: relative;
+	top: 0px;
+	left: 0px;
+	width: 100%;
+}
+
+.mblView.out {
+	position: absolute;
+}
+
+.mblView.in {
+	position: absolute;
+}
+
+.slide.out {
+	-webkit-animation-duration: .4s;
+	-webkit-animation-name: slideOut;
+	-webkit-animation-timing-function: linear;
+	-webkit-transform: translateX(-100%);
+}
+.slide.in {
+	-webkit-animation-duration: .4s;
+	-webkit-animation-name: slideIn;
+	-webkit-animation-timing-function: linear;
+	-webkit-transform: translateX(0px);
+}
+.slide.out.reverse {
+	-webkit-animation-name: slideOutReverse;
+}
+.slide.in.reverse {
+	-webkit-animation-name: slideInReverse;
+}
+ at -webkit-keyframes slideOut {
+	from { -webkit-transform: translateX(0px); }
+	to { -webkit-transform: translateX(-100%); }
+}
+ at -webkit-keyframes slideIn {
+	from { -webkit-transform: translateX(100%); }
+	to { -webkit-transform: translateX(0px); }
+}
+ at -webkit-keyframes slideOutReverse {
+	from { -webkit-transform: translateX(0px); }
+	to { -webkit-transform: translateX(100%); }
+}
+ at -webkit-keyframes slideInReverse {
+	from { -webkit-transform: translateX(-100%); }
+	to { -webkit-transform: translateX(0px); }
+}
+
+.flip.out {
+	-webkit-animation-duration: .6s;
+	-webkit-animation-name: flipOut;
+	-webkit-animation-timing-function: ease-in;
+	-webkit-transform: rotateY(90deg);
+}
+.flip.in {
+	-webkit-animation-duration: .6s;
+	-webkit-animation-name: flipIn;
+	-webkit-animation-timing-function: ease-out;
+}
+ at -webkit-keyframes flipOut {
+	0% { -webkit-transform: rotateY(0deg) scale(1); }
+	50% { -webkit-transform: rotateY(90deg) scale(.8); }
+	100% { -webkit-transform: rotateY(90deg) scale(.8); }
+}
+
+ at -webkit-keyframes flipIn {
+	0% { -webkit-transform: rotateY(90deg) scale(.8); }
+	50% { -webkit-transform: rotateY(90deg) scale(.8); }
+	100% { -webkit-transform: rotateY(0deg) scale(1); }
+}
+
+.fade.out {
+	-webkit-animation-duration: 1s;
+	-webkit-animation-name: fadeOut;
+	-webkit-animation-timing-function: ease-in;
+}
+.fade.out.fast {
+	-webkit-animation-duration: 0.3s;
+}
+.fade.in {
+	-webkit-animation-duration: 1s;
+	-webkit-animation-name: fadeIn;
+	-webkit-animation-timing-function: ease-out;
+}
+ at -webkit-keyframes fadeOut {
+	from { opacity: 1; }
+	to { opacity: 0; }
+}
+
+ at -webkit-keyframes fadeIn {
+	from { opacity: 0; }
+	to { opacity: 1; }
+}
+
+/* dojox.mobile.Heading */
+.mblHeading {
+	position: relative;
+	height: 42px;
+	margin: 0px;
+	padding: 0px;
+	background-color: #889BB3;
+	background: -webkit-gradient(linear, left top, left bottom, from(#B0BCCD), to(#6D84A2), color-stop(0.5, #889BB3), color-stop(0.5, #8195AF));
+	border-top: 1px solid #CDD5DF;
+	border-bottom: 1px solid #2D3642;
+	font-family: Helvetica;
+	font-size: 20px;
+	color: white;
+	text-align: center;
+	line-height: 44px;
+	text-shadow: rgba(0,0,0,0.6) 0px -1px 0px;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+/* Heading Arrow Button */
+.dj_webkit .mblArrowButtonHead {
+	position: absolute;
+	top: 10px;
+	left: 8px;
+	width: 19px;
+	height: 19px;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #3A4655;
+	-webkit-transform: scale(.8,1) rotate(45deg);
+	background: -webkit-gradient(linear, left top, right bottom, from(#8EA4C1), to(#4A6C9B), color-stop(0.5, #5877A2), color-stop(0.5, #476999));
+}
+.mblArrowButtonBody {
+	position: absolute;
+	top: 5px;
+	left: 19px;
+	padding: 0px 10px 0px 3px;
+	height: 29px;
+	border-width: 1px 1px 1px 0px;
+	border-style: inset;
+	border-color: #9CACC0;
+	font-family: Helvetica;
+	font-size: 13px;
+	color: white;
+	line-height: 29px;
+	cursor: pointer;
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	background-color: #5877A2;
+	background: -webkit-gradient(linear, left top, left bottom, from(#8EA4C1), to(#4A6C9B), color-stop(0.5, #5877A2), color-stop(0.5, #476999));
+	-webkit-tap-highlight-color: transparent;
+}
+.dj_ie .mblArrowButtonBody, .dj_ff3 .mblArrowButtonBody {
+	padding: 0px 10px 0px 10px;
+}
+.mblArrowButtonNeck {
+	position: absolute;
+	top: 5px;
+	left: 19px;
+	width: 4px;
+	height: 29px;
+	border-width: 1px 0px 1px 0px;
+	border-style: inset;
+	border-color: #9CACC0;
+	background: -webkit-gradient(linear, left top, left bottom, from(#8EA4C1), to(#4A6C9B), color-stop(0.5, #5877A2), color-stop(0.5, #476999));
+}
+.mblArrowButtonSelected .mblArrowButtonHead {
+	background: -webkit-gradient(linear, left top, right bottom, from(#7C87A4), to(#263E6C), color-stop(0.5, #394D77), color-stop(0.5, #243B69));
+}
+.mblArrowButtonSelected .mblArrowButtonBody, .mblArrowButtonSelected .mblArrowButtonNeck {
+	background: -webkit-gradient(linear, left top, left bottom, from(#7C87A4), to(#263E6C), color-stop(0.5, #394D77), color-stop(0.5, #243B69));
+}
+
+/* dojox.mobile.RoundRect */
+.mblRoundRect {
+	margin: 7px 9px 16px;
+	padding: 8px;
+	border: 1px solid #ADAAAD;
+	-webkit-border-radius: 8px;
+	-moz-border-radius: 8px;
+	background-color: white;
+}
+.mblRoundRect.mblShadow {
+	-webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);
+}
+
+/* dojox.mobile.EdgeToEdgeCategory */
+.mblEdgeToEdgeCategory {
+	position: relative;
+	height: 22px;
+	margin: 0px;
+	padding: 0px 10px;
+	border-top: 1px solid #A4B0B9;
+	border-bottom: 1px solid #979DA3;
+	background: -webkit-gradient(linear, left top, left bottom, from(#8F9EA9), to(#B7C0C7));
+	font-family: Helvetica;
+	font-size: 16px;
+	color: white;
+	line-height: 22px;
+	text-shadow: rgba(0,0,0,0.6) 0px -1px 0px;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+/* dojox.mobile.RoundRectCategory */
+.mblRoundRectCategory {
+	color: #4C566C;
+	margin: 18px 0px 0px 20px;
+	text-shadow: rgba(255, 255, 255, 1) 0px 1px 0px;
+	font-family: Helvetica;
+	font-size: 16px;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+/* dojox.mobile.RoundRectList */
+.mblRoundRectList {
+	margin: 7px 9px 16px;
+	padding: 0px;
+	border: 1px solid #ADAAAD;
+	-webkit-border-radius: 8px;
+	-moz-border-radius: 8px;
+	background-color: white;
+	position: relative; /* IE needs this */
+}
+
+/* dojox.mobile.EdgeToEdgeList */
+.mblEdgeToEdgeList {
+	padding: 0px;
+	background-color: white;
+	position: relative; /* IE needs this */
+	margin: 0px; /* IE needs this */
+}
+
+/* dojox.mobile.ListItem */
+.mblListItem {
+	list-style-type: none;
+	height: 43px;
+	border-bottom: 1px solid #ADAAAD;
+	line-height: 43px;
+	font-weight: bold;
+	position: relative;
+	color: black;
+	vertical-align: bottom; /* To avoid IE6 LI bug */
+}
+.mblListItemIcon {
+	position: absolute;
+	margin: 7px 0px 0px 8px;
+}
+.mblListItem.mblVariableHeight {
+	line-height: normal;
+	height: auto;
+	padding: 11px 6px 10px 6px;
+}
+.mblItemSelected {
+	background-color: #048BF4;
+	background: -webkit-gradient(linear, left top, left bottom, from(#048BF4), to(#005CE5));
+}
+li .mblListItemTextBox {
+	padding-right: 28px;
+}
+li .mblListItemTextBoxSelected {
+	background-color: #048BF4;
+}
+.mblRoundRectList .mblListItem:first-child {
+	-webkit-border-top-left-radius: 8px;
+	-webkit-border-top-right-radius: 8px;
+	-moz-border-radius-topleft: 8px;
+	-moz-border-radius-topright: 8px;
+}
+.mblRoundRectList .mblListItem:last-child {
+	border-bottom-width: 0px;
+	-webkit-border-bottom-left-radius: 8px;
+	-webkit-border-bottom-right-radius: 8px;
+	-moz-border-radius-bottomleft: 8px;
+	-moz-border-radius-bottomright: 8px;
+}
+.mblEdgeToEdgeList .mblListItem:last-child {
+	border-bottom-color: #707C84;
+}
+.mblListItem a.mblListItemAnchor {
+	background-position: 9px 7px;
+	display: block;
+	padding-left: 48px;
+	text-decoration: none;
+	-webkit-tap-highlight-color: transparent;
+}
+.mblListItem a.mblListItemAnchorNoIcon {
+	padding-left: 10px;
+}
+.mblItemSelected a.mblListItemAnchor {
+	color: white;
+}
+.mblListItem a.mblListItemAnchorHasRightButton {
+	padding-right: 40px;
+}
+
+.mblListItem .mblArrow {
+	position: absolute;
+	top: 18px;
+	right: 12px;
+	width: 6px;
+	height: 6px;
+	font-size: 1px;
+	-webkit-transform: rotate(45deg);
+	border-width: 3px 3px 0px 0px;
+	border-style: solid;
+	border-color: #808080;
+}
+.mblItemSelected .mblArrow {
+	border-color: white;
+}
+.mblVariableHeight div.mblArrow {
+	top: 50%;
+	margin-top: -4px;
+}
+
+.mblRightText {
+	position: absolute;
+	top: 12px;
+	right: 30px;
+	color: #324F85;
+	line-height: normal;
+}
+.mblListItem .mblRightButtonContainer {
+	position: absolute;
+	top: 50%;
+	right: 12px;
+}
+.mblListItem .mblRightButton {
+	position: absolute;
+	top: -50%;
+}
+
+/* Switch */
+.mblSwitch {
+	position: relative;
+	width: 94px;
+	height: 27px;
+	overflow: hidden;
+}
+.mblItemSwitch {
+	position: absolute;
+	top: 8px;
+	right: 12px;
+}
+.mblSwitchInner {
+	position: absolute;
+	top: 0px;
+	height: 27px;
+}
+.mblSwitchAnimation .mblSwitchInner {
+	-webkit-transition-property: left;
+	-webkit-transition-duration: .3s;
+}
+.mblSwitchOn .mblSwitchInner {
+	left: 0px;
+}
+.mblSwitchOff .mblSwitchInner {
+	left: -53px;
+}
+.mblSwitchBg {
+	position: absolute;
+	top: 0px;
+	height: 27px;
+	border-width: 1px;
+	border-style: inset;
+	border-color: #9CACC0;
+	font-family: Helvetica;
+	font-size: 16px;
+	font-weight: bold;
+	line-height: 29px;
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	-webkit-box-sizing: border-box;
+	-moz-box-sizing: border-box;
+	-webkit-tap-highlight-color: transparent;
+}
+.mblSwitchBgLeft {
+	left: 0px;
+	width: 94px;
+	color: white;
+	background-color: #3F84EB;
+	background: -webkit-gradient(linear, left top, left bottom, from(#2859B1), to(#75ACFB), color-stop(0.5, #3F84EB), color-stop(0.5, #4C8EEE));
+}
+.mblSwitchBgRight {
+	left: 53px;
+	width: 94px;
+	color: #7F7F7F;
+	background-color: #EEEEEE;
+	background: -webkit-gradient(linear, left top, left bottom, from(#CECECE), to(#FDFDFD), color-stop(0.5, #EEEEEE), color-stop(0.5, #F8F8F8));
+}
+.mblSwitchKnob {
+	position: absolute;
+	top: 1px;
+	left: 53px;
+	width: 41px;
+	height: 26px;
+	font-size: 1px;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #EFEFEF #A5A5A5 #969696 #325E9E;
+	line-height: 29px;
+	background-color: #CCCCCC;
+	background: -webkit-gradient(linear, left top, left bottom, from(#CCCCCC), to(#FAFAFA));
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	-webkit-box-sizing: border-box;
+	-moz-box-sizing: border-box;
+}
+.mblSwitchText {
+	position: relative;
+	top: 0px;
+	width: 53px;
+	height: 27px;
+	padding: 0px;
+	text-align: center;
+}
+.mblSwitchTextLeft {
+	left: 0px;
+}
+.mblSwitchTextRight {
+	left: 40px;
+}
+
+/* Icon Container */
+.mblIconContainer {
+	padding: 0px;
+	margin: 20px 0px 0px 10px;
+	padding: 0px 0px 40px 0px;
+}
+.mblIconItem {
+	list-style-type: none;
+	float: left;
+}
+.mblIconItemTerminator {
+	list-style-type: none;
+	height: 20px;
+	clear: both;
+}
+.mblIconItemSub {
+	list-style-type: none;
+	margin-left: -10px;
+	background-color: white;
+}
+
+.mblIconArea {
+	font-family: Helvetica;
+	font-size: 12px;
+	height: 78px;
+	width: 74px;
+	text-align: center;
+	margin-bottom: 10px;
+}
+
+.mblIconArea DIV {
+	position: relative;
+	height: 65px;
+}
+
+.mblIconArea IMG {
+	position: absolute;
+	top: 0px;
+	left: 6px;
+}
+
+.mblContent {
+	clear: both;
+	padding-bottom: 20px;
+}
+
+table.mblClose {
+	clear: both;
+	cursor: pointer;
+}
+
+.mblVibrate{
+	position: relative;
+	-webkit-animation-duration: .5s;
+	-webkit-animation-timing-function: ease-in-out;
+	-webkit-animation-iteration-count: 20;
+	-webkit-animation-name: vibrate;
+	-webkit-transform: rotate(0deg);
+}
+ at -webkit-keyframes vibrate{
+	0%{
+		-webkit-transform: rotate(-2deg);
+		bottom: -1px;
+		left: -1px;
+	}
+	25% {
+		-webkit-transform: rotate(1deg);
+		bottom: 2px;
+		left: 1px;
+	}
+	50% {
+		-webkit-transform: rotate(-1deg);
+		bottom: -2px;
+		left: -1px;
+	}
+	75% {
+		-webkit-transform: rotate(2deg);
+		bottom: 2px;
+		left: 1px;
+	}
+	100% {
+		-webkit-transform: rotate(-2deg);
+		bottom: -1px;
+		left: -1px;
+	}
+}
+
+.mblCloseContent{
+	-webkit-animation-duration: .3s;
+	-webkit-animation-timing-function: ease-in-out;
+	-webkit-animation-name: shrink;
+	-webkit-transform: scale(0.01);
+}
+.mblCloseContent.mblShrink0{
+	-webkit-animation-name: shrink0;
+}
+.mblCloseContent.mblShrink1{
+	-webkit-animation-name: shrink1;
+}
+.mblCloseContent.mblShrink2{
+	-webkit-animation-name: shrink2;
+}
+.mblCloseContent.mblShrink3{
+	-webkit-animation-name: shrink3;
+}
+ at -webkit-keyframes shrink{
+	from { -webkit-transform: scale(1); }
+	to { -webkit-transform: scale(0.01); }
+}
+ at -webkit-keyframes shrink0{
+	from { -webkit-transform: scale(1); }
+	to { -webkit-transform: translate(-40%,-70%) scale(0.01); }
+}
+ at -webkit-keyframes shrink1{
+	from { -webkit-transform: scale(1); }
+	to { -webkit-transform: translate(-14%,-70%) scale(0.01); }
+}
+ at -webkit-keyframes shrink2{
+	from { -webkit-transform: scale(1); }
+	to { -webkit-transform: translate(14%,-70%) scale(0.01); }
+}
+ at -webkit-keyframes shrink3{
+	from { -webkit-transform: scale(1); }
+	to { -webkit-transform: translate(40%,-70%) scale(0.01); }
+}
+
+/* Icon Content Heading */
+.mblIconContentHeading {
+	position: relative;
+	clear: both;
+	height: 25px;
+	padding-left: 40px;
+	margin-top: 0px;
+	background: -webkit-gradient(linear, left top, left bottom, from(#E0E4E7), to(#B4BEC6), color-stop(0.5, #C4CCD2), color-stop(0.5, #BFC8CE));
+	border-top: 1px solid #F1F3F4;
+	border-bottom: 1px solid #717D85;
+	font-family: Helvetica;
+	font-size: 14px;
+	color: white;
+	line-height: 26px;
+	text-shadow: rgba(0,0,0,0.6) 0px -1px 0px;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+/* dojox.mobile.Button */
+.mblButton {
+	padding: 0px 10px;
+	height: 29px;
+	border-width: 1px 1px 1px 1px;
+	border-style: outset;
+	color: white;
+	font-family: Helvetica;
+	font-size: 13px;
+	line-height: 29px;
+	-webkit-border-radius: 5px;
+	-moz-border-radius: 5px;
+	-webkit-tap-highlight-color: transparent;
+}
+.mblBlueButton {
+	border-color: #9CACC0;
+	background-color: #366EDF;
+	background: -webkit-gradient(linear, left top, left bottom, from(#7A9DE9), to(#2362DD), color-stop(0.5, #366EDF), color-stop(0.5, #215FDC));
+	-webkit-tap-highlight-color: transparent;
+}
+.mblBlueButtonSelected {
+	background: -webkit-gradient(linear, left top, left bottom, from(#8EA4C1), to(#4A6C9B), color-stop(0.5, #5877A2), color-stop(0.5, #476999));
+}
+.mblRedButton {
+	border-color: #9CACC0;
+	background-color: #366EDF;
+	background: -webkit-gradient(linear, left top, left bottom, from(#FA9D58), to(#EE4115), color-stop(0.5, #FF4D25), color-stop(0.5, #ED4D15));
+	-webkit-tap-highlight-color: transparent;
+}
+.mblRedButtonSelected {
+	background: -webkit-gradient(linear, left top, left bottom, from(#C1A48E), to(#9B6C4A), color-stop(0.5, #A27758), color-stop(0.5, #996947));
+}
+
+/* Tab Container */
+.mblTabContainer {
+}
+
+.mblTabButton {
+	float: left;
+	width: 100px;
+	text-align: center;
+	height: 28px;
+	border-width: 1px 1px 1px 0px;
+	border-style: inset;
+	border-color: #9CACC0;
+	border-right-color: #5E708A;
+	font-family: Helvetica;
+	font-size: 13px;
+	color: white;
+	cursor: pointer;
+	line-height: 29px;
+	background-color: #8297AF;
+	background: -webkit-gradient(linear, left top, left bottom, from(#ABB9CA), to(#788DA9), color-stop(0.5, #8297AF), color-stop(0.5, #768BA7));
+	-webkit-tap-highlight-color: transparent;
+}
+.mblTabButton:first-child {
+	-webkit-border-top-left-radius: 5px;
+	-webkit-border-bottom-left-radius: 5px;
+	-moz-border-radius-topleft: 5px;
+	-moz-border-radius-bottomleft: 5px;
+	border-left-width: 1px;
+}
+.mblTabButton:last-child {
+	-webkit-border-top-right-radius: 5px;
+	-webkit-border-bottom-right-radius: 5px;
+	-moz-border-radius-topright: 5px;
+	-moz-border-radius-bottomright: 5px;
+	border-right-color: #9CACC0;
+}
+.mblTabButtonSelected.mblTabButton {
+	background-color: #5877A2;
+	background: -webkit-gradient(linear, left top, left bottom, from(#8EA4C1), to(#4A6C9B), color-stop(0.5, #5877A2), color-stop(0.5, #476999));
+}
+.mblTabButtonImgDiv {
+	display: none;
+}
+
+.mblTabPanelHeader {
+	position: relative;
+	height: 39px;
+	margin: 0px;
+	padding: 3px 0px 0px 0px;
+	background-color: #889BB3;
+	background: -webkit-gradient(linear, left top, left bottom, from(#B0BCCD), to(#6D84A2), color-stop(0.5, #889BB3), color-stop(0.5, #8195AF));
+	border-top: 1px solid #CDD5DF;
+	border-bottom: 1px solid #2D3642;
+	font-family: Helvetica;
+	font-size: 20px;
+	color: white;
+	text-align: center;
+	line-height: 44px;
+	text-shadow: rgba(0,0,0,0.6) 0px -1px 0px;
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+
+.mblTabPanelPane {
+}
+
+.mblTabPane {
+}
+
+/* Progress Indicator */
+.mblProgContainer {
+	position: absolute;
+	width: 36px;
+	height: 36px;
+	top: 180px;
+	left: 50%;
+	margin: -18px 0px 0px -18px;
+}
+.mblProg {
+	position: absolute;
+	left: 0px;
+	top: 0px;
+	width: 11px;
+	font-size: 1px;
+	height: 4px;
+	overflow: hidden;
+	-webkit-transform-origin: 0 2px;
+	background-color: #C0C0C0;
+	-webkit-border-radius: 2px;
+	-moz-border-radius: 2px;
+}
+.mblProg0 {
+	-webkit-transform: translate(18px,10px) rotate(-90deg);
+}
+.mblProg1 {
+	-webkit-transform: translate(22px,11px) rotate(-60deg);
+}
+.mblProg2 {
+	-webkit-transform: translate(25px,14px) rotate(-30deg);
+}
+.mblProg3 {
+	-webkit-transform: translate(26px,18px) rotate(0deg);
+}
+.mblProg4 {
+	-webkit-transform: translate(25px,22px) rotate(30deg);
+}
+.mblProg5 {
+	-webkit-transform: translate(22px,25px) rotate(60deg);
+}
+.mblProg6 {
+	-webkit-transform: translate(18px,26px) rotate(90deg);
+}
+.mblProg7 {
+	-webkit-transform: translate(14px,25px) rotate(120deg);
+}
+.mblProg8 {
+	-webkit-transform: translate(11px,22px) rotate(150deg);
+}
+.mblProg9 {
+	-webkit-transform: translate(10px,18px) rotate(180deg);
+}
+.mblProg10 {
+	-webkit-transform: translate(11px,14px) rotate(210deg);
+}
+.mblProg11 {
+	-webkit-transform: translate(14px,11px) rotate(240deg);
+}
diff --git a/dojox/rails.js b/dojox/rails.js
new file mode 100644
index 0000000..0af14f1
--- /dev/null
+++ b/dojox/rails.js
@@ -0,0 +1,143 @@
+dojo.provide("dojox.rails");
+dojo.require("dojo.NodeList-traverse");
+
+dojox.rails.live = function(selector, evtName, fn){
+	if (dojo.isIE && evtName.match(/^(on)?submit$/i)){
+		dojox.rails.live(selector, "click", function(evt){
+			var target = evt.target, tag = target.tagName.toLowerCase();
+			if ((tag == "input" || tag == "button") && dojo.attr(target, "type").toLowerCase() == "submit"){
+				 var form = dojo.query(target).closest("form");
+				 if (form.length){
+					var h = dojo.connect(form[0], "submit", function(evt){
+					 	dojo.disconnect(h);
+					 	fn.call(evt.target, evt);
+				 	});
+				}
+			}
+		});
+	}else{
+		dojo.connect(dojo.body(), evtName, function(evt){
+			var nl = dojo.query(evt.target).closest(selector);
+			if (nl.length){
+				fn.call(nl[0], evt);
+			}
+		});
+	}
+};
+
+dojo.ready((function(d, dr, dg){
+	return function() {
+		var q = d.query, live = dr.live,
+				csrfToken = q("meta[name=csrf-token]").attr("content"),
+		    csrfParam = q("meta[name=csrf-param]").attr("content");
+
+		var createFormForLink = function(url, method){
+			var form = '<form style="display:none" method="post" action="'+ url +'">' +
+				'<input type="hidden" name="_method" value="'+ method +'" />' +
+				'<input type="hidden" name="'+ csrfParam +'" value="'+ csrfToken +'" />' +
+				'</form>';
+			return dojo.place(form, dojo.body());
+		};
+
+		var disable = function(elements){
+			d.forEach(elements, function(node){
+				if (!d.attr(node, "disabled")){
+					var attr = node.tagName.toLowerCase() == "input" ? "value" : "innerHTML";
+					var message = d.attr(node, "data-disable-with");
+					var originalValue = d.attr(node, attr);
+					d.attr(node, "disabled", true);
+					d.attr(node, "data-original-value", originalValue);
+					d.attr(node, attr, message);
+				}
+			});
+		};
+
+		var typeMap = {
+			"text":                  "text",
+			"json":                  "application/json",
+			"json-comment-optional": "text",
+			"json-comment-filtered": "text",
+			"javascript":            "application/javascript",
+			"xml":                   "text/xml"
+		};
+
+		var handleRemote = function(evt){
+			var el = evt.target, tag = el.tagName.toLowerCase();
+			var content = tag.toLowerCase() == "form" ? d.formToObject(el) : {},
+					type   =  d.attr(el, "data-type") || "javascript",
+					method = (d.attr(el, "method")    || d.attr(el, "data-method") || "get").toLowerCase(),
+					url    =  d.attr(el, "action")    || d.attr(el, "href");
+
+			if (tag != "form" && method != "get"){
+					el = createFormForLink(url, method);
+					method = "POST";
+			}
+			evt.preventDefault();
+
+
+			// ajax:loading, ajax:loaded, and ajax:interactive are not supported
+			d.publish("ajax:before", [el]);
+			var deferred = d.xhr(method, {
+				url:      url,
+				headers:  { "Accept": typeMap[type] },
+				content:  content,
+				handleAs: type,
+				load:		  function(response, ioArgs) {d.publish("ajax:success",	 [el, response, ioArgs]);},
+				error:	  function(response, ioArgs) {d.publish("ajax:failure",  [el, response, ioArgs]);},
+				handle:   function(response, ioArgs) {d.publish("ajax:complete", [el, response, ioArgs]);}
+			});
+			d.publish("ajax:after", [el]);
+		};
+
+		var handleEnable	= function(el){
+			q("*[data-disable-with][disabled]", el).forEach(function(node){
+				var attr = node.tagName.toLowerCase() == "input" ? "value" : "innerHTML";
+				var value = d.attr(node, "data-original-value");
+				d.attr(node, "disabled", false);
+				d.attr(node, "data-original-value", null);
+				d.attr(node, attr, value);
+			});
+		};
+
+		var handleDataMethod = function(evt){
+			var el = evt.target, form = createFormForLink(el.href, dojo.attr(el, "data-method"));
+			evt.preventDefault();
+			form.submit();
+		};
+
+		var handleFormSubmit = function(evt){
+			var el = evt.target, elements = q("*[data-disable-with]", el);
+			if (elements.length){ disable(elements); }
+			if (d.attr(el, "data-remote")){
+				evt.preventDefault();
+				handleRemote(evt);
+ 			}
+		};
+
+		var handleConfirm = function(evt){
+			var proceed = dg.confirm(d.attr(evt.target, "data-confirm"));
+			if (!proceed){
+				evt.preventDefault();
+			}else if (d.attr(evt.target, "data-remote")){
+				handleRemote(evt);
+			}
+		};
+
+		// Register data-{action} elements.	 Order is important since the return values
+		// from previously called functions in the connect chain influence whether
+		// or not the next function in the chain is called.
+
+		// Register data-confirm elements
+		live("*[data-confirm]", "click", handleConfirm);
+
+		// data-disable-with only applies to forms
+		d.subscribe("ajax:complete", handleEnable);
+
+		// Register data-remote elements
+		live("a[data-remote]:not([data-confirm])", "click", handleRemote);
+		live("a[data-method]:not([data-remote])", "click", handleDataMethod);
+
+		// Handle form submits
+		live("form", "submit", handleFormSubmit);
+	};
+})(dojo, dojox.rails, dojo.global));
diff --git a/dojox/rails/README b/dojox/rails/README
new file mode 100644
index 0000000..732184a
--- /dev/null
+++ b/dojox/rails/README
@@ -0,0 +1,41 @@
+-------------------------------------------------------------------------------
+Project Name:  dojox.rails
+-------------------------------------------------------------------------------
+Version 0.1
+Release date: 03/23/2010
+-------------------------------------------------------------------------------
+Project state:
+        experimental
+-------------------------------------------------------------------------------
+Credits:
+       Bob Remeika (bob.remeika at gmail.com)
+       ttilley (This code is based a lot on what he contributed).
+
+-------------------------------------------------------------------------------
+Project description
+
+This is a dojo plugin for Rails 3.x UJS support
+
+-------------------------------------------------------------------------------
+Dependencies:
+        dojo base
+-------------------------------------------------------------------------------
+Documentation
+        Documentatation will reside at:
+        http://docs.dojocampus.org/dojox/rails
+
+-------------------------------------------------------------------------------
+Installation instructions
+
+Grab the following from the Dojo SVN Repository:
+http://svn.dojotoolkit.org/src/dojox/trunk/rails.js
+
+Install into the following directory structure:
+/dojox/rails.js
+
+...which should be at the same level as your Dojo checkout.
+
+then dojo.require("dojox.rails") in your application to load it.
+
+-------------------------------------------------------------------------------
+
diff --git a/dojox/rails/tests/module.js b/dojox/rails/tests/module.js
new file mode 100644
index 0000000..fff89bf
--- /dev/null
+++ b/dojox/rails/tests/module.js
@@ -0,0 +1,7 @@
+dojo.provide("dojox.rails.tests.module");
+
+try{
+	doh.registerUrl("dojox.rails", dojo.moduleUrl("dojox.rails", "tests/test_rails.html"));
+}catch(e){
+	doh.debug(e);
+}
\ No newline at end of file
diff --git a/dojox/rails/tests/plugd/trigger.js b/dojox/rails/tests/plugd/trigger.js
new file mode 100644
index 0000000..a57992a
--- /dev/null
+++ b/dojox/rails/tests/plugd/trigger.js
@@ -0,0 +1,187 @@
+dojo.provide("dojox.rails.tests.plugd.trigger");
+(function(d){
+	
+	var isfn = d.isFunction, 
+		leaveRe = /mouse(enter|leave)/, 
+		_fix = function(_, p){
+			return "mouse" + (p == "enter" ? "over" : "out"); 
+		},
+		mix = d._mixin,
+		
+		// the guts of the node triggering logic:
+		// the function accepts node (not string|node), "on"-less event name,
+		// and an object of args to mix into the event. 
+		realTrigger = d.doc.createEvent ? 
+			function(n, e, a){
+				// the sane branch
+				var ev = d.doc.createEvent("HTMLEvents");
+				e = e.replace(leaveRe, _fix);
+				ev.initEvent(e, true, true);
+				a && mix(ev, a);
+				n.dispatchEvent(ev);
+			} : 
+			function(n, e, a){
+				// the janktastic branch
+				var ev = "on" + e, stop = false, lc = e.toLowerCase(), node = n; 
+				try{
+// FIXME: is this worth it? for mixed-case native event support:? Opera ends up in the
+//	createEvent path above, and also fails on _some_ native-named events. 
+//					if(lc !== e && d.indexOf(d.NodeList.events, lc) >= 0){
+//						// if the event is one of those listed in our NodeList list
+//						// in lowercase form but is mixed case, throw to avoid
+//						// fireEvent. /me sighs. http://gist.github.com/315318
+//						throw("janktastic");
+//					}
+					n.fireEvent(ev);
+				}catch(er){
+                    console.warn("in catch", er);
+					// a lame duck to work with. we're probably a 'custom event'
+					var evdata = mix({ 
+						type: e, target: n, faux: true,
+						// HACK: [needs] added support for customStopper to _base/event.js
+						// some tests will fail until del._stopPropagation has support.
+						_stopper: function(){ stop = this.cancelBubble; }
+					}, a);
+				
+					isfn(n[ev]) && n[ev](evdata);
+				
+					// handle bubbling of custom events, unless the event was stopped.
+					while(!stop && n !== d.doc && n.parentNode){
+						n = n.parentNode;
+						isfn(n[ev]) && n[ev](evdata);
+					}
+				}
+			}
+	;
+	
+	d._trigger = function(/* DomNode|String */node, /* String */event, extraArgs){
+		// summary: 
+		//		Helper for `dojo.trigger`, which handles the DOM cases. We should never
+		//		be here without a domNode reference and a string eventname.
+		var n = d.byId(node), ev = event && event.slice(0, 2) == "on" ? event.slice(2) : event;
+		realTrigger(n, ev, extraArgs);
+
+	};
+		
+	d.trigger = function(obj, event, extraArgs){
+		// summary: 
+		//		Trigger some event. It can be either a Dom Event, Custom Event, 
+		//		or direct function call. 
+		//
+		// description:
+		//		Trigger some event. It can be either a Dom Event, Custom Event, 
+		//		or direct function call. NOTE: This function does not trigger
+		//		default behavior, only triggers bound event listeneres. eg:
+		//		one cannot trigger("anchorNode", "onclick") and expect the browser
+		//		to follow the href="" attribute naturally.
+		//
+		// obj: String|DomNode|Object|Function
+		//		An ID, or DomNode reference, from which to trigger the event.
+		//		If an Object, fire the `event` in the scope of this object,
+		//		similar to calling dojo.hitch(obj, event)(). The return value
+		//		in this case is returned from `dojo.trigger`
+		//	 
+		// event: String|Function
+		//		The name of the event to trigger. Can be any DOM level 2 event
+		//		and can be in either form: "onclick" or "click" for instance.
+		//		In the object-firing case, this method can be a function or
+		//		a string version of a member function, just like `dojo.hitch`.
+		//
+		// extraArgs: Object?
+		//		An object to mix into the `event` object passed to any bound 
+		//		listeners. Be careful not to override important members, like
+		//		`type`, or `preventDefault`. It will likely error.
+		//
+		//		Additionally, extraArgs is moot in the object-triggering case,
+		//		as all arguments beyond the `event` are curried onto the triggered
+		//		function.
+		//
+		// example: 
+		//	|	dojo.connect(node, "onclick", function(e){ /* stuff */ });
+		//	|	// later:
+		//	|	dojo.trigger(node, "onclick");
+		//
+		// example:
+		//	|	// or from within dojo.query: (requires dojo.NodeList)
+		//	|	dojo.query("a").onclick(function(){}).trigger("onclick");
+		//
+		// example:
+		//	|	// fire obj.method() in scope of obj
+		//	|	dojo.trigger(obj, "method");
+		//
+		// example:
+		//	|	// fire an anonymous function:
+		//	|	dojo.trigger(d.global, function(){ /* stuff */ });
+		//
+		// example: 
+		//	|	// fire and anonymous function in the scope of obj
+		//	|	dojo.trigger(obj, function(){ this == obj; });
+		//
+		// example:
+		//	|	// with a connected function like:
+		//	|	dojo.connect(dojo.doc, "onclick", function(e){
+		//	|		if(e && e.manuallydone){
+		//	|			console.log("this was a triggered onclick, not natural");
+		//	|		}
+		//	|	});
+		//	|	// fire onclick, passing in a custom bit of info
+		//	|	dojo.trigger("someId", "onclick", { manuallydone:true });
+		//
+		// returns: Anything
+		//		Will not return anything in the Dom event case, but will return whatever
+		//		return value is received from the triggered event. 
+		return (isfn(obj) || isfn(event) || isfn(obj[event])) ? 
+			d.hitch.apply(d, arguments)() : d._trigger.apply(d, arguments);
+	};
+	
+	// adapt for dojo.query:
+	/*=====
+	dojo.extend(dojo.NodeList, {
+		trigger: function(event, data){
+			// summary:
+			//		Trigger some Event originating from each of the nodes in this
+			//		`dojo.NodeList`. 
+			//
+			// event: String
+			//		Any strig identifier for the event.type to be triggered.
+			//
+			// data: Object
+			//		Just like `extraArgs` for `dojo.trigger`, additional data
+			//		to mix into the event object.
+			//
+			// example:
+			//	|	dojo.query("a").trigger("onclick");
+			
+			return this; // dojo.NodeList
+		}
+	});
+	=====*/
+	d.NodeList.prototype.trigger = d.NodeList._adaptAsForEach(d._trigger); 
+
+	// if the node.js module is available, extend trigger into that.
+	if(d._Node && !d._Node.prototype.trigger){
+		d.extend(d._Node, {
+			trigger: function(ev, data){
+				// summary:
+				//		Fire some some event originating from this node.
+				//		Only available if both the `dojo.trigger` and `dojo.node` plugin 
+				//		are enabled. Allows chaining as all `dojo._Node` methods do.
+				//
+				// ev: String
+				//		Some string event name to fire. eg: "onclick", "submit"
+				//
+				// data: Object
+				//		Just like `extraArgs` for `dojo.trigger`, additional data
+				//		to mix into the event object.
+				//
+				// example:
+				//	|	// fire onlick orginiating from a node with id="someAnchorId"
+				//	|	dojo.node("someAnchorId").trigger("click");
+
+				d._trigger(this, ev, data);
+				return this; // dojo._Node
+			}
+		});
+	}
+	
+})(dojo);
diff --git a/dojox/rails/tests/runTests.html b/dojox/rails/tests/runTests.html
new file mode 100644
index 0000000..e73aedd
--- /dev/null
+++ b/dojox/rails/tests/runTests.html
@@ -0,0 +1,9 @@
+<html>
+	<head>
+		<title>DojoX Functional Unit Test Runner</title>
+		<meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.rails.tests.module" />
+	</head>
+	<body>
+		<p>Redirecting to D.O.H runner.</p>
+	</body>
+</html>
diff --git a/dojox/rails/tests/success_response.html b/dojox/rails/tests/success_response.html
new file mode 100644
index 0000000..bc3b9f6
--- /dev/null
+++ b/dojox/rails/tests/success_response.html
@@ -0,0 +1 @@
+<h1>some html</h1>
diff --git a/dojox/rails/tests/test_rails.html b/dojox/rails/tests/test_rails.html
new file mode 100644
index 0000000..c998efd
--- /dev/null
+++ b/dojox/rails/tests/test_rails.html
@@ -0,0 +1,320 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.rails test</title>
+	<style type="text/css">
+		body {
+			font-family: helvetica;
+		}
+		
+		.test-container {
+			width: 800px;
+			margin-bottom: 20px;
+		}
+		
+		.test-container:after {
+			clear: both;
+		}
+		
+		.test-container div {
+			float: left;
+			margin-right: 20px;
+		}
+		
+		.description {
+			width: 400px;
+			border: 1px solid #ccc;
+			-moz-border-radius: 5px;
+			-webkit-border-radius: 5px;
+			padding: 10px;
+		}
+		
+		span.clb {
+			display: block;
+			clear: both;
+		}
+	</style>
+	
+	<script src='../../../dojo/dojo.js' djConfig='isDebug:true, parseOnLoad:true'></script>
+	<script type="text/javascript">
+    // dojo.registerModulePath('dojox.rails.tests.plugd', '../dojox/rails/tests/plugd'); 
+		dojo.require('doh.runner');
+		dojo.require('dojox.rails');
+    dojo.require('dojox.rails.tests.plugd.trigger');
+		dojo.require('dojo.NodeList-manipulate');
+
+    var subscriptions = [];
+		
+		function createDom(){
+			var q = dojo.query;
+			q('#data-confirm-link-container').append('<a href="/foo/url" data-confirm="Are you sure?">click me!</a>');
+			q('#data-confirm-input-container').append('<input data-confirm="Are you sure?" name="commit" type="submit" value="Post" />');
+			q('#data-remote-success-link-container').append('<a href="success_response.html" data-type="text" data-remote="true">click me to load!</a>');
+			q('#data-remote-failure-link-container').append('<a href="failure_response.html" data-remote="true">click me to fail!</a>');
+		}
+
+    function listenForEvents(expectedNode, events){
+      for (var k in events){
+        var s = dojo.subscribe(k, (function(k){
+          return function(el, response, ioArgs){
+            if (el == expectedNode){ events[k] = true; }
+          };
+        })(k));
+        subscriptions.push(s);
+      }
+    }
+
+    function assertEvents(deferred, timeout, events){
+      setTimeout(function(){
+        for (var k in events){
+					console.debug("assertEvents: ", k, events[k]);
+          if (!events[k]){
+            deferred.errback(new Error(k + ' event was not dispatched'));
+            return;
+          }
+        }
+        deferred.callback(true);
+      }, timeout);
+    }
+
+    function unsubscribe(){
+      dojo.forEach(subscriptions, function(s){
+        dojo.unsubscribe(s);
+      });
+    }
+		
+		dojo.addOnLoad(function(){
+			createDom();
+      doh.register('data-remote', [
+        {
+          name: 'success events',
+          timeout: 3000,
+          tearDown: unsubscribe,
+          runTest: function() {
+            var d = new doh.Deferred();
+            var snl = dojo.query('#data-remote-success-link-container a');
+            var successEvents = { 'ajax:success': false, 'ajax:complete': false, 'ajax:after': false };
+            listenForEvents(snl[0], successEvents);
+            snl.trigger('click');
+            assertEvents(d, 300, successEvents);
+            return d;
+          }
+        },
+        {
+          name: 'failure events',
+          timeout: 3000,
+          tearDown: unsubscribe,
+          runTest: function() {
+            var d = new doh.Deferred();
+            var fnl = dojo.query('#data-remote-failure-link-container a');
+            var failureEvents = { 'ajax:failure': false, 'ajax:complete': false, 'ajax:after': false };
+            listenForEvents(fnl[0], failureEvents);
+            fnl.trigger('click');
+            assertEvents(d, 300, failureEvents);
+            return d;
+          }
+        },
+        {
+          name: 'forms',
+          runTest: function(t) {
+            var method, ioArgs;
+            var xhr = dojo.xhr;
+            dojo.xhr = function(m, io){
+              method = m;
+              ioArgs = io;
+            }
+
+            dojo.query('#data-remote-get-form-container form').trigger('submit');
+
+            t.assertEqual('get', method);
+            
+            var expectedArgs = {
+              url: '/posts',
+              content: {
+                'post[title]': 'Some title',
+                'post[body]': 'Some body'
+              }
+            }
+
+            t.is(expectedArgs.url, ioArgs.url);
+            t.is(expectedArgs.content['post[title]'], ioArgs.content['post[title]']);
+            t.is(expectedArgs.content['post[body]'], ioArgs.content['post[body]']);
+
+            dojo.xhr = xhr;
+          }
+        }
+      ]);
+
+      doh.register("data-disable-with", [
+        {
+          name: 'disabling form elements on submit',
+          runTest: function(t){
+            // var container = dojo.query('#data-disable-with-on-parent-container');
+            // var button = container.query('button');
+            // var input = container.query('input');
+            // var form = container.query('form');
+
+            // t.is('My Button', button.html());
+            // t.is('My Submit', input.val());
+            // 
+            // input.trigger('submit');
+
+            // t.is('Disable button...', button.html());
+            // t.is('Please wait...', input.val());
+
+            // t.t(button.attr('disabled'));
+            // t.t(input.attr('disabled'));
+          }
+        },
+        {
+          name: 're-enabling an element after an ajax event has completed',
+          tearDown: unsubscribe,
+          runTest: function(t){
+            var container = dojo.query('#data-disable-with-on-ajax-container');
+            var button = container.query('button');
+            var input = container.query('input');
+            var form = container.query('form');
+
+            t.is('My Button', button.html());
+            t.is('My Submit', input.val());
+            
+            var d = new doh.Deferred();
+            var failureHandlerCalled = false;
+
+            var s1 = dojo.subscribe("ajax:failure", function(){
+              failureHandlerCalled = true; 
+              t.is('Disable button...', button.html());
+              t.is('Please wait...', input.val());
+              t.t(button.attr('disabled'));
+              t.t(input.attr('disabled'));
+            });
+
+            var s2 = dojo.subscribe("ajax:complete", function(){
+              console.debug("-----------> ajax:complete: ");
+              t.is('My Button', button.html());
+              t.is('My Submit', input.val());
+              t.f(button.attr('disabled')[0]);
+              t.f(input.attr('disabled')[0]);
+
+              if (failureHandlerCalled){
+                d.callback(true);
+              }else{
+                d.errback("failureHandler was never called");
+              }
+              d.callback(true);
+            });
+
+            subscriptions.push(s1);
+            subscriptions.push(s2);
+
+            form.trigger('submit');
+            return d;
+          }
+        }
+      ]);
+
+			doh.run();
+		});
+	</script>
+</head>
+<body class='tundra'>
+
+<h1>Manual Tests</h1>
+
+<h3>Confirm</h3>
+
+<div class="test-container">
+	<div class="description">This is a dynamically created <em>link</em>.  When the confirm dialog is cancelled, it should stop processing.  When the confirm dialog is confirmed, it should proceed to the href url.</div>
+	<div id="data-confirm-link-container"></div>
+	<span class="clb"></div>
+</div>
+
+<div class="test-container">
+	<div class="description">This is a dynamically created <em>submit button</em>.  When the confirm dialog is cancelled, it should stop processing.  When the confirm dialog is confirmed, it should proceed to the form action url.</div>
+  <div id="data-confirm-input-container">
+		<form action="/posts" id="data-confirm-input-container" method="post"><input name="authenticity_token" type="hidden" value="Hfm4VBZJeCde+5evpma9Rq4eGtCq+/n7fZr0XVDalLw=" />
+			Title: <input id="post_title" name="post[title]" value="Some title" type="text" /><br />
+			Body: <input id="post_body" name="post[body]" value="Some body" type="text" />
+      <!-- submit button is created dynamically -->
+		</form>
+	</div>
+	<span class="clb"></div>
+</div>
+
+
+<h1>Automated Tests</h1>
+
+<h3>Remote</h3>
+<div class="test-container">
+	<div class="description">This is a dynamically created <em>link</em>.  When the link is clicked it should successfully make an ajax request.</div>
+	<div id="data-remote-success-link-container"></div>
+	<span class="clb"></div>
+</div>
+
+<div class="test-container">
+	<div class="description">This is a dynamically created <em>link</em>.  When the link is clicked it should fail when making an ajax request.</div>
+  <div id="data-remote-failure-link-container"></div>
+	<span class="clb"></div>
+</div>
+
+<div class="test-container">
+	<div class="description">This is a form created with markup.  When submit is clicked it should send a get request to <em>/posts</em></div>
+  <div id="data-remote-get-form-container">
+		<form action="/posts" data-remote="true" method="get">
+			Title: <input id="post_title" name="post[title]" value="Some title" type="text" /><br />
+			Body: <input id="post_body" name="post[body]" value="Some body" type="text" />
+      <input type="submit" value="submit" />
+      <input name="authenticity_token" type="hidden" value="Hfm4VBZJeCde+5evpma9Rq4eGtCq+/n7fZr0XVDalLw=" />
+		</form>
+  </div>
+	<span class="clb"></div>
+</div>
+
+
+
+<h3>Disable With</h3>
+<div class="test-container">
+	<div class="description">This is a regular form with <em>child elements</em> to disable.  All disable-with elements should be disabled when the form is submitted.</div>
+  <div id="data-disable-with-on-parent-container">
+    <form action="fail.html">
+      <button data-disable-with="Disable button..." name="cmd" type="button" value="value">My Button</button>
+      <input data-disable-with="Please wait..." name="commit" type="submit" value="My Submit" />
+    </form>
+  </div>
+	<span class="clb"></div>
+</div>
+
+<div class="test-container">
+	<div class="description">This is a ajax form that should have it's <em>elements reenabled</em> when the ajax request has completed.</div>
+  <div id="data-disable-with-on-ajax-container">
+    <form action="failure-url.html" data-remote="true" >
+      <button data-disable-with="Disable button..." name="cmd" type="button" value="value">My Button</button>
+      <input data-disable-with="Please wait..." name="commit" type="submit" value="My Submit" />
+    </form>
+  </div>
+	<span class="clb"></div>
+</div>
+
+
+<p>
+	Form (Ajaxy)<form action="/posts" class="new_post" data-remote="true" id="new_post" method="post"><input name="authenticity_token" type="hidden" value="Hfm4VBZJeCde+5evpma9Rq4eGtCq+/n7fZr0XVDalLw=" />
+		Title: <input id="post_title" name="post[title]" type="text" /><br />
+		Body: <input id="post_body" name="post[body]" type="text" />
+		<input data-disable-with="Please wait..." name="commit" type="submit" value="Post" />
+	</form>
+</p>
+
+<p>
+	Form (Normal):<br/>
+	<form action="/posts" class="new_post" id="new_post" method="post"><div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="Hfm4VBZJeCde+5evpma9Rq4eGtCq+/n7fZr0XVDalLw=" /></div>
+		Title: <input id="post_title" name="post[title]" size="30" type="text" /><br />
+		Body: <input id="post_body" name="post[body]" size="30" type="text" />
+		<input data-disable-with="Please wait..." name="commit" type="submit" value="Post" />
+	</form>
+</p>
+
+
+
+</body>
+</html>
diff --git a/dojox/resources/_modules.js b/dojox/resources/_modules.js
index 0b276e5..2d1b233 100644
--- a/dojox/resources/_modules.js
+++ b/dojox/resources/_modules.js
@@ -1,7 +1,252 @@
-/*
-	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 file is in place as a quick way to give summaries to all available dojox projects.
 
+dojox = {
+	// summary:
+	//	DojoX: the home for Dojo eXtensions
+	//
+	// description:
+	//	DojoX is a collection of subprojects provided by Dojo committers and subject to
+	//	the generous licensing and policies of the [Dojo CLA](http://dojotoolkit.org/cla)
+	//	Each subproject in DojoX has its own top-level directory and a README file with
+	//	status information and project status and a stability rating (experimental, beta, stable)
+	//
+	//	Projects may or may not depend on other top-level Dojo projects, like Dojo or Dijit.
+	//	Unlike Dojo and Dijit, code is not subject to i18n and a11y restrictions and may vary
+	//	in quality (experimental code is encouraged in DojoX, but currently prohibited in Dojo
+	//	and Dijit)
+	//
+	//	DojoX projects may mature to a stable state and stay in DojoX, or on occasion
+	//	after proving themselves may migrate to Dojo Core or Dijit.  Dojo and Dijit projects
+	//	are constrained both by development resources as well as design goals, so DojoX is
+	//	a natural place to provide enhanced behavior or extend Dojo Core or Dijit primitives.
+	//	DojoX can also be an incubator for entirely new projects.
+}
 
+dojox.analytics = { 
+	// summary: Website analytics and client monitoring system 
+};
+
+dojox.atom = { 
+	// summary: Implements the Atom Syndication Format and Atom Publishing Protocol 
+};
+
+dojox.av = { 
+	// summary: Provides Audio/Video capabilities 
+};
+
+dojox.charting = { 
+	// summary: Vector graphic, data-driven graphs and charts 
+};
+
+dojox.collections = { 
+	// summary: A set of lists and hashes for easy use within your applications.
+};
+
+dojox.color = { 
+	// summary: Advanced color methods, including HSV, HSL, and CMYK conversion, a color generator and advanced colorspace calculations.
+};
+
+dojox.cometd = { 
+	// summary: A cometd client written in Dojo
+};
+
+dojox.data = { 
+	// summary: Additional dojo.data data stores and demos
+};
+
+dojox.date = { 	
+	// summary: Additional date manipulation functions
+};
+
+dojox.drawing = { 	
+	// summary: A vector drawing program
+};
+
+dojox.dtl = { 
+	// summary: Django Templating Language implementation	
+};
+
+dojox.editor = { 
+	// summary: Extensions for dijit.Editor
+};
+
+dojox.embed = { 
+	// summary: Base code for embedding for external objects like Flash, Quicktime
+};
+
+dojox.encoding = { 
+	// summary: Various encoding algorithms, including crypto and digests.
+};
+
+dojox.flash = { 
+	// summary: Utilities to embed and communicate with Flash-based objects
+};
+
+dojox.form = { 
+	// summary: Form-related widgets
+};
+
+dojox.fx = {
+	// summary: Extension animations to the core dojo FX project
+	//
+	// description:
+	//	A package of animations, and FX-related code, extending Dojo Core fx.
+	//	Including this package includes all the Base and Core fx packages.
+	//
+	
+	style: { // summary: Module to provide CSS animations
+	},
+
+	scroll: { // summary: Module to provide scroll-related FX 
+	}
+};
+dojox.fx["ext-dojo"] = {
+	// summary: Direct extensions to dojo.fx namespace
+	NodeList: {
+		// summary: module to include to support dojox.fx animations in dojo.query()
+	}
+};
+
+dojox.gfx = { 
+	// summary: Cross-browser vector graphics API
+	// description: 
+	//
+	//	dojox.gfx is an advanced API providing normalized vector drawing
+	//	in a variety of browsers. It has individual renderers for SVG, VML,
+	//	Canvas, and Silverlight.
+};
+
+dojox.gfx3d = { 
+	// summary: A 3d API for dojox.gfx
+};
+
+dojox.grid = { 
+	// summary: An advanced Grid widget with virtual scrolling, cell editing, and much more 
+};	
+
+dojox.help = {
+	// summary: TODOC
+};
+
+dojox.highlight = { 
+	// summary: A client-side syntax highlighting engine.
+	// description:
+	//	This project parses pre > code nodes, and applies syntax highlighting for
+	//	a wide variety of languages. Simply dojo.require() in all the 
+	//	dojox.highlight.languages you wish to include in your highlighingting,
+	//	and customize colors in the highlight.css.
+	//
+	//	It is provided as a dojo package, contributed under CLA 
+	//	by Ivan Sagalaev and is available originally from:
+	// 	http://softwaremaniacs.org/soft/highlight/en/	
+	//	
+};
+
+dojox.html = {
+	// summary: TODOC
+};
+
+dojox.image = { 
+	// summary: A collection of image related widgets
+};
+
+dojox.io = { 
+	// summary: Extensions to the Core dojo.io transports
+};
+
+dojox.jq = {
+	// summary: A JQuery compatibility layer
+};
+
+dojox.jsonPath = { 
+	// summary: A query system for JavaScript objects
+};
+
+dojox.lang = { 
+	// summary: Language specific extensions
+	functional: {
+		// summary: Functional language constructs, including currying and lambda.
+	}
+};
+
+dojox.layout = { 
+	// summary: A collection of layout related Widgets
+};
+
+dojox.math = { 
+	// summary: A collection of various advanced math functions.
+};
+
+dojox.robot = {
+	// summary: TODOC
+};
+
+dojox.rpc = { 
+	// summary: TODOC
+};
+
+dojox.secure = { 
+	// summary: TODOC
+};
+
+dojox.sketch = { 
+	// summary: TODOC
+};
+
+dojox.sql = { 
+	// summary: objects to support Dojo Offline (dojox.off)  DEPRECATED
+};
+
+dojox.storage = { 
+	// summary: Objects for mass storage within the browser.  For when cookies just aren't enough.
+};
+
+dojox.string = {
+	// summary: A collection of various objects for advanced string manipulation, including a Builder and a tokenizer.
+};
+
+dojox.testing = {
+	// summary: TODOC
+};
+
+dojox.timing = {
+	// summary: A set of objects to perform advanced time-based tasks, including a basic Timer.
+};
+
+dojox.uuid = { 
+	// summary: Universally Unique Identifier (UUID) implementations, including an implementation of UUID 2
+};
+
+dojox.validate = { 
+	// summary: Additional input validation methods
+	ca : {
+		// summary: Methods specific to the Canadian provinces
+	},
+	creditCard : {
+		// summary: Validate various credit card types  
+	}
+};
+
+dojox.widget = { 
+	// summary: A collection of un-categorized widgets, or code not requiring its own package.
+	// 
+	// description: 
+	// 	These are standalone widgets with varying levels of stability. Some are useful, 
+	//	some were created for demonstration purposes, and learning tools. The each maintain
+	//	their own .css file (typically dojox/widget/WidgetName/WidgetName.css)
+};
+
+dojox.wire = {
+	// summary:
+	//	Declarative data binding and action tags for simplified MVC
+};
+
+dojox.xml = {
+	// summary: XML utilities.  Currently only includes a DomParser, which returns a psuedo-XML document in JSON-like form.
+};
+
+dojox.xmpp = {
+	// summary: TODOC
+};
+=====*/
diff --git a/dojox/resources/explore.php b/dojox/resources/explore.php
new file mode 100644
index 0000000..0644832
--- /dev/null
+++ b/dojox/resources/explore.php
@@ -0,0 +1,149 @@
+<?php // IF you don't have PHP5 installed, you can't use this index! ?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<link rel="stylesheet" href="../../dijit/tests/css/dijitTests.css">
+	<link rel="stylesheet" href="../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../../dojox/widget/Dialog/Dialog.css">
+	<style type="text/css">
+		.innard {
+			padding:12px;
+			margin-top:0;
+		}
+	</style>
+	<title>Dojo Toolkit - DojoX Demos and Tests by Project</title>
+
+	<script src="../../dojo/dojo.js"></script>
+	<script type="text/javascript">
+		dojo.require('dojox.widget.Dialog');
+		dojo.require("dojo.fx.easing");
+		dojo.addOnLoad(function(){
+			var dialog = new dojox.widget.Dialog({ title: "About", viewportPadding:100, fixedSize:true });
+			dialog.startup();
+			dojo.query("span.projectname + a")
+				.connect("onclick",function(e){
+					e.preventDefault();
+					dojo.xhrGet({
+						url: e.target.href,
+						load: function(data){
+							var content = data.replace(/\</g,"<");
+							dialog.show();
+							dialog.setContent("<pre class='innard'>" + content + "</pre>");
+						}
+					})
+				})
+			;
+		});
+	</script>
+
+</head>
+<body>
+
+	<h1 class="testTitle">DojoX test files overview</h1>
+	
+	<table id="testMatrix">
+		<thead>
+			<tr class="top"><th rowspan="2">Test</th><th colspan="4">Tundra</th><th colspan="4">Nihilo</th><th colspan="4">Soria</th></tr>
+			<tr class="tests"><th>Normal</th><th>a11y</th><th>rtl</th><th>a11y + rtl<th>Normal</th><th>a11y</th><th>rtl</th><th>a11y + rtl<th>Normal</th><th>a11y</th><th>rtl</th><th>a11y + rtl</tr>
+		</thead>
+		<tbody><?php
+
+			foreach(getprojects() as $project){
+				$note = "";
+				if($project['readme']){
+					$note = "<a class='readmeLink' href='".$project['readme']."'>about</a>"; 
+				}
+				if($project['tests'] || $project['demos']){
+					print "<tr class='spacer'><td colspan='13'><span class='projectname'>dojox.". $project['name'] . "</span> ".$note."</td></tr>";
+
+					if($project['tests']){
+						printLinks($project['tests']);					
+					}
+					if($project['demos']){
+						printLinks($project['demos']);
+					}
+
+				}
+				
+			}
+		//	printLinks("./tree","Dijit Tree Tests");
+			
+		?>
+		</tbody>
+	</table>
+
+	<p>* note: All themes and modes included for completeness. Some projects don't even use themes. The "basic" link
+		is the direct link to the file with no enhancements. The test file must include _testCommon from dijit to
+		include theme / rtl / a11y testing capabilities.</p>
+</body>
+</html>
+<?php
+
+function getprojects(){
+	$projects = array();
+	$path = "../../dojox";
+	$handle = opendir($path);
+	while(false !== ($file = readdir($handle))){
+		$README = "";
+		$full = $path."/".$file;
+		if(is_dir($full)){
+			if(file_exists($full."/README")){
+				$README = $full."/README";
+			}
+			$tests = false; $demos = false;
+			if(is_dir($full."/tests")){
+				$tests = $full."/tests";
+			}
+			if(is_dir($full."/demos")){
+				$demos = $full."/demos";
+			}
+			$projects[] = array(
+				"name" => $file,
+				"tests" => $tests,
+				"demos" => $demos,
+				"readme" => $README
+			);
+		}
+	}
+	return $projects;
+}
+
+function printLinks($path){
+	$handle = opendir($path);
+	$i = 0;
+
+	while(false !== ($file = readdir($handle))){
+		if(preg_match("/([a-zA-Z])(.*)\.html/", $file, $matches)){
+			$base = $matches[0];
+			$link = $path."/".$matches[0];
+			print 
+			"<tr class='testRow ". (++$i % 2 ==0 ? "alt" : "")   ."'>" .
+
+				"<td class='label'>" . $base . "</td>" .
+
+			    // standard / tundra:
+				"<td><a href='".$link."'>basic</a></td>" .
+				"<td><a href='".$link."?a11y=true'>a11y</a></td>" .
+				"<td><a href='".$link."?dir=rtl'>rtl</a></td>" .
+				"<td><a href='".$link."?dir=rtl&a11y=true'>both</a></td>" .
+				
+				// nihilo
+				"<td><a href='".$link."?theme=nihilo'>nihilo</a></td>" .
+				"<td><a href='".$link."?theme=nihilo&a11y=true'>a11y</a></td>" .
+				"<td><a href='".$link."?theme=nihilo&dir=rtl'>rtl</a></td>" .
+				"<td><a href='".$link."?theme=nihilo&dir=rtl&a11y=true'>combo</a></td>" .
+
+				// soria
+				"<td><a href='".$link."?theme=soria'>soria</a></td>" .
+				"<td><a href='".$link."?theme=soria&a11y=true'>a11y</a></td>" .
+				"<td><a href='".$link."?theme=soria&dir=rtl'>rtl</a></td>" .
+				"<td><a href='".$link."?theme=soria&dir=rtl&a11y=true'>combo</a></td>" .
+									
+			 "</tr>";
+		}
+	}
+}
+
+?>
diff --git a/dojox/robot/recorder.js b/dojox/robot/recorder.js
index 0c761f3..9d7b4b9 100644
--- a/dojox/robot/recorder.js
+++ b/dojox/robot/recorder.js
@@ -1,329 +1,501 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.robot.recorder"]){
-dojo._hasResource["dojox.robot.recorder"]=true;
 dojo.provide("dojox.robot.recorder");
 dojo.experimental("dojox.robot.recorder");
+// summary:
+// 	Generates a doh test as you interact with a Web page.
+// 	To record a test, click inside the document body and press CTRL-ALT-ENTER.
+// 	To finish recording a test and to display the autogenerated code, press CTRL-ALT-ENTER again.
+//
+
+
 (function(){
-var _1=1000;
-var _2=500;
-var _3=10000;
-var _4=[];
-var _5=0;
-var _6=null;
-var _7=null;
-var _8=function(){
-alert("Started recording.");
-_4=[];
-_6=new Date();
-_7=new Date();
-};
-var _9=function(_a,_b){
-if(_6==null||_a=="doh.robot.keyPress"&&_b[0]==dojo.keys.ENTER&&eval("("+_b[2]+")").ctrl&&eval("("+_b[2]+")").alt){
-return;
-}
-var dt=Math.max(Math.min(Math.round((new Date()).getTime()-_7.getTime()),_3),1);
-if(_a=="doh.robot.mouseMove"){
-_b[2]=dt;
-}else{
-_b[1]=dt;
-}
-_4.push({name:_a,args:_b});
-_7=new Date();
-};
-var _c=function(){
-var c=_4;
-if(c[0].name=="doh.robot.keyPress"&&(c[0].args[0]==dojo.keys.ENTER||c[0].args[0]==77)){
-c.splice(0,1);
-}
-for(var i=c.length-1;(i>=c.length-2)&&(i>=0);i--){
-if(c[i].name=="doh.robot.keyPress"&&c[i].args[0]==dojo.keys.ALT||c[i].args[0]==dojo.keys.CTRL){
-c.splice(i,1);
-}
-}
-for(i=0;i<c.length;i++){
-var _d,_e;
-if(c[i+1]&&c[i].name=="doh.robot.mouseMove"&&c[i+1].name==c[i].name&&c[i+1].args[2]<_2){
-_d=c[i+1];
-_e=0;
-while(_d&&_d.name==c[i].name&&_d.args[2]<_2){
-c.splice(i+1,1);
-_e+=_d.args[2];
-c[i].args[0]=_d.args[0];
-c[i].args[1]=_d.args[1];
-_d=c[i+1];
-}
-c[i].args[3]=_e;
-}else{
-if(c[i+1]&&c[i].name=="doh.robot.mouseWheel"&&c[i+1].name==c[i].name&&c[i+1].args[1]<_2){
-_d=c[i+1];
-_e=0;
-while(_d&&_d.name==c[i].name&&_d.args[1]<_2){
-c.splice(i+1,1);
-_e+=_d.args[1];
-c[i].args[0]+=_d.args[0];
-_d=c[i+1];
-}
-c[i].args[2]=_e;
-}else{
-if(c[i+2]&&c[i].name=="doh.robot.mouseMoveAt"&&c[i+2].name=="doh.robot.scrollIntoView"){
-var _f=c.splice(i+2,1)[0];
-c.splice(i,0,_f);
-}else{
-if(c[i+1]&&c[i].name=="doh.robot.mousePress"&&c[i+1].name=="doh.robot.mouseRelease"&&c[i].args[0]==c[i+1].args[0]){
-c[i].name="doh.robot.mouseClick";
-c.splice(i+1,1);
-if(c[i+1]&&c[i+1].name=="doh.robot.mouseClick"&&c[i].args[0]==c[i+1].args[0]){
-c.splice(i+1,1);
-}
-}else{
-if(c[i+1]&&c[i-1]&&c[i-1].name=="doh.robot.mouseMoveAt"&&c[i].name=="doh.robot.mousePress"&&c[i+1].name=="doh.robot.mouseMove"){
-var cmd={name:"doh.robot.mouseMoveAt",args:[c[i-1].args[0],1,100,c[i-1].args[3]+1,c[i-1].args[4]]};
-c.splice(i+1,0,cmd);
-}else{
-if(c[i+1]&&((c[i].name=="doh.robot.keyPress"&&typeof c[i].args[0]=="string")||c[i].name=="doh.robot.typeKeys")&&c[i+1].name=="doh.robot.keyPress"&&typeof c[i+1].args[0]=="string"&&c[i+1].args[1]<=_1&&!eval("("+c[i].args[2]+")").ctrl&&!eval("("+c[i].args[2]+")").alt&&!eval("("+c[i+1].args[2]+")").ctrl&&!eval("("+c[i+1].args[2]+")").alt){
-c[i].name="doh.robot.typeKeys";
-c[i].args.splice(3,1);
-_d=c[i+1];
-var _10=0;
-while(_d&&_d.name=="doh.robot.keyPress"&&typeof _d.args[0]=="string"&&_d.args[1]<=_1&&!eval("("+_d.args[2]+")").ctrl&&!eval("("+_d.args[2]+")").alt){
-c.splice(i+1,1);
-c[i].args[0]+=_d.args[0];
-_10+=_d.args[1];
-_d=c[i+1];
-}
-c[i].args[2]=_10;
-c[i].args[0]="'"+c[i].args[0]+"'";
-}else{
-if(c[i].name=="doh.robot.keyPress"){
-if(typeof c[i].args[0]=="string"){
-c[i].args[0]="'"+c[i].args[0]+"'";
-}else{
-if(c[i].args[0]==0){
-c.splice(i,1);
-}else{
-for(var j in dojo.keys){
-if(dojo.keys[j]==c[i].args[0]){
-c[i].args[0]="dojo.keys."+j;
-break;
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-};
-var _11=function(){
-if(!_6){
-_8();
-}else{
-_12();
-}
-};
-var _12=function(){
-var dt=Math.round((new Date()).getTime()-_6.getTime());
-_6=null;
-_c();
-var c=_4;
-if(c.length){
-var s="doh.register('dojox.robot.AutoGeneratedTestGroup',{\n";
-s+="     name: 'autotest"+(_5++)+"',\n";
-s+="     timeout: "+(dt+2000)+",\n";
-s+="     runTest: function(){\n";
-s+="          var d = new doh.Deferred();\n";
-for(var i=0;i<c.length;i++){
-s+="          "+c[i].name+"(";
-for(var j=0;j<c[i].args.length;j++){
-var arg=c[i].args[j];
-s+=arg;
-if(j!=c[i].args.length-1){
-s+=", ";
-}
+
+// CONSTANTS
+
+// consolidate keypresses into one typeKeys if they occur within 1 second of each other
+var KEYPRESS_MAXIMUM_DELAY = 1000;
+
+// consolidate mouse movements if they occur within .5 seconds of each other
+var MOUSEMOVE_MAXIMUM_DELAY = 500;
+
+// absolute longest wait between commands
+// anything longer gets chopped to 10
+var MAXIMUM_DELAY = 10000;
+
+// stack of commands recorded from dojo.connects
+var commands = [];
+
+// number to write next to test name
+// goes up after each recording
+var testNumber = 0;
+
+// time user started test
+var startTime = null;
+
+// time since last user input
+// robot commands work on deltas
+var prevTime = null;
+
+var start = function(){
+	// summary:
+	//	Starts recording the user's input.
+	//
+	alert("Started recording.");
+	commands = [];
+	startTime = new Date();
+	prevTime = new Date();
 }
-s+=");\n";
+
+var addCommand = function(name, args){
+	// summary:
+	//	Add a command to the stack.
+	//
+	// name:
+	//	doh.robot function to call.
+	//
+	// args:
+	//	arguments array to pass to the doh.robot
+	//
+
+	// omit start/stop record
+	if(startTime == null 
+		|| name=="doh.robot.keyPress" 
+		&& args[0]==dojo.keys.ENTER 
+		&& eval("("+args[2]+")").ctrl 
+		&& eval("("+args[2]+")").alt){ return; }
+	var dt = Math.max(Math.min(Math.round((new Date()).getTime() - prevTime.getTime()),MAXIMUM_DELAY),1);
+	// add in dt
+	// is usually args[1] but there are exceptions
+	if(name == "doh.robot.mouseMove"){
+		args[2]=dt;
+	}else{
+		args[1]=dt;
+	}
+	commands.push({name:name,args:args});
+	prevTime = new Date();
 }
-s+="          doh.robot.sequence(function(){\n";
-s+="               if(/*Your condition here*/){\n";
-s+="                    d.callback(true);\n";
-s+="               }else{\n";
-s+="                    d.errback(new Error('We got a failure'));\n";
-s+="               }\n";
-s+="          }, 1000);\n";
-s+="          return d;\n";
-s+="     }\n";
-s+="});\n";
-var div=document.createElement("div");
-div.id="dojox.robot.recorder";
-div.style.backgroundColor="white";
-div.style.position="absolute";
-var _13={y:(window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0),x:(window.pageXOffset||(window["dojo"]?dojo._fixIeBiDiScrollLeft(document.documentElement.scrollLeft):undefined)||document.body.scrollLeft||0)};
-div.style.left=_13.x+"px";
-div.style.top=_13.y+"px";
-var h1=document.createElement("h1");
-h1.innerHTML="Your code:";
-div.appendChild(h1);
-var pre=document.createElement("pre");
-if(pre.innerText!==undefined){
-pre.innerText=s;
-}else{
-pre.textContent=s;
+
+var _optimize = function(){
+	// make the stack more human-readable and remove any odditites
+	var c = commands;
+
+	// INITIAL OPTIMIZATIONS
+	// remove starting ENTER press
+	if(c[0].name == "doh.robot.keyPress" 
+		&& (c[0].args[0] == dojo.keys.ENTER || c[0].args[0] == 77)){
+		c.splice(0,1);
+	}
+	// remove ending CTRL + ALT keypresses in IE
+	for(var i = c.length-1; (i >= c.length-2) && (i>=0); i-- ){
+		if(c[i].name == "doh.robot.keyPress" 
+			&& c[i].args[0]==dojo.keys.ALT || c[i].args[0]==dojo.keys.CTRL){
+			c.splice(i,1);
+		}
+	}
+	// ITERATIVE OPTIMIZATIONS
+	for(i = 0; i<c.length; i++){
+		var next, nextdt;
+		if(c[i+1] 
+			&& c[i].name=="doh.robot.mouseMove" 
+			&& c[i+1].name==c[i].name 
+			&& c[i+1].args[2]<MOUSEMOVE_MAXIMUM_DELAY){
+			// mouse movement optimization
+			// if the movement is temporally close, collapse it
+			// example: mouseMove(a,b,delay 5)+mouseMove(x,y,delay 10)+mousePress(delay 1) becomes mouseMove(x,y,delay 5)+mousePress(delay 11)
+			// expected pattern:
+			// 	c[i]: mouseMove
+			// 	c[i+1]: mouseMove
+			// 	...
+			// 	c[i+n-1]: last mouseMove
+			// 	c[i+n]: something else
+			// result: 
+			// 	c[i]: last mouseMove
+			// 	c[i+1]: something else
+			// the c[i] mouse location changes to move to c[i+n-1]'s location, c[i+n] gains c[i+1]+c[i+2]+...c[i+n-1] delay so the timing is the same
+
+			next = c[i+1];
+			nextdt = 0;
+			while(next 
+				&& next.name==c[i].name 
+				&& next.args[2]<MOUSEMOVE_MAXIMUM_DELAY){
+				// cut out next
+				c.splice(i + 1,1);
+				// add next's delay to the total 
+				nextdt += next.args[2];
+				// move to next mouse position
+				c[i].args[0]=next.args[0];
+				c[i].args[1]=next.args[1];
+				next = c[i+1];
+			}
+			// make the total delay the duration
+			c[i].args[3]=nextdt;
+		}else if(c[i+1] 
+			&& c[i].name=="doh.robot.mouseWheel" 
+			&& c[i+1].name==c[i].name 
+			&& c[i+1].args[1]<MOUSEMOVE_MAXIMUM_DELAY){
+			// mouse wheel optimization
+			// if the movement is temporally close, collapse it
+			// example: mouseWheel(1,delay 5)+mouseWheel(-2,delay 10) becomes mouseWheel(-1,delay 5, speed 10)
+			// expected pattern:
+			// 	c[i]: mouseWheel
+
+			// 	c[i+1]: mouseWheel
+			// 	...
+			// 	c[i+n-1]: last mouseWheel
+			// 	c[i+n]: something else
+			// result: 
+			// 	c[i]: mouseWheel
+			// 	c[i+1]: something else
+
+			next = c[i+1];
+			nextdt = 0;
+			while(next 
+				&& next.name==c[i].name 
+				&& next.args[1]<MOUSEMOVE_MAXIMUM_DELAY){
+				// cut out next
+				c.splice(i + 1, 1);
+				// add next's delay to the total 
+				nextdt += next.args[1];
+				// add in wheel amount
+				c[i].args[0]+=next.args[0];
+				next = c[i+1];
+			}
+			// make the total delay the duration
+			c[i].args[2]=nextdt;
+		}else if(c[i + 2] 
+			&& c[i].name=="doh.robot.mouseMoveAt" 
+			&& c[i+2].name=="doh.robot.scrollIntoView"){
+			// swap scrollIntoView of widget and mouseMoveAt
+			// the recorder traps scrollIntoView after the mouse click registers, but in playback, it is better to go the other way
+			// expected pattern:
+			// 	c[i]: mouseMoveAt
+			// 	c[i+1]: mousePress
+			// 	c[i+2]: scrollIntoView
+			// result:
+			//	c[i]: scrollIntoView
+			//	c[i+1]: mouseMoveAt
+			//	c[i+2]: mousePress
+			var temp = c.splice(i+2,1)[0];
+			c.splice(i,0,temp);
+		}else if(c[i + 1] 
+			&& c[i].name=="doh.robot.mousePress" 
+			&& c[i+1].name=="doh.robot.mouseRelease" 
+			&& c[i].args[0]==c[i+1].args[0]){
+			// convert mousePress+mouseRelease to mouseClick
+			// expected pattern:
+			//	c[i]: mousePress
+			//	c[i+1]: mouseRelease
+			//	mouse buttons are the same
+			c[i].name = "doh.robot.mouseClick";
+			// delete extra mouseRelease
+			c.splice(i + 1,1);
+			// if this was already a mouse click, get rid of the next (dup) one
+			if(c[i+1] && c[i+1].name == "doh.robot.mouseClick" && c[i].args[0] == c[i+1].args[0]){
+				c.splice(i + 1, 1);
+			}
+		}else if(c[i + 1] 
+			&& c[i - 1]
+			&& c[i - 1].name=="doh.robot.mouseMoveAt"
+			&& c[i].name=="doh.robot.mousePress" 
+			&& c[i+1].name=="doh.robot.mouseMove"){
+			// convert mouseMoveAt+mousePress+mouseMove to mouseMoveAt+mousePress+mouseMoveAt+mouseMove
+			// this is to kick off dojo.dnd by moving the mouse 1 px
+			// expected pattern:
+			//	c[i-1]: mouseMoveAt
+			//	c[i]: mousePress
+			//	c[i+1]: mouseMove
+
+			// insert new mouseMoveAt, 1px to the right
+			var cmd={name:"doh.robot.mouseMoveAt",args:[c[i-1].args[0], 1, 100, c[i-1].args[3]+1,c[i-1].args[4]]};
+			c.splice(i+1,0,cmd);
+		}else if(c[i + 1]
+			&& ((c[i].name=="doh.robot.keyPress"
+				&& typeof c[i].args[0] =="string") 
+				|| c[i].name=="doh.robot.typeKeys") 
+			&& c[i+1].name=="doh.robot.keyPress" 
+			&& typeof c[i+1].args[0] =="string"
+			&& c[i+1].args[1]<=KEYPRESS_MAXIMUM_DELAY 
+			&& !eval("("+c[i].args[2]+")").ctrl 
+			&& !eval("("+c[i].args[2]+")").alt 
+			&& !eval("("+c[i+1].args[2]+")").ctrl 
+			&& !eval("("+c[i+1].args[2]+")").alt){
+			// convert keyPress+keyPress+... to typeKeys
+			// expected pattern:
+			// 	c[i]: keyPress(a)
+			// 	c[i+1]: keyPress(b)
+			// 	...
+			// 	c[i+n-1]: last keyPress(z)
+			// 	c[i+n]: something else
+			// result:
+			//	c[i]: typeKeys(ab...z)
+			//	c[i+1]: something else
+			// note: does not convert alt or ctrl keypresses, and does not convert non-character keypresses like enter
+			c[i].name = "doh.robot.typeKeys";
+			c[i].args.splice(3,1);
+			next = c[i+1];
+			var typeTime = 0;
+			while(next 
+				&& next.name == "doh.robot.keyPress" 
+				&& typeof next.args[0] =="string"
+				&& next.args[1]<=KEYPRESS_MAXIMUM_DELAY 
+				&& !eval("("+next.args[2]+")").ctrl 
+				&& !eval("("+next.args[2]+")").alt){
+				c.splice(i + 1,1);
+				c[i].args[0] += next.args[0];
+				typeTime += next.args[1];
+				next = c[i+1];
+			}
+			// set the duration to the total type time
+			c[i].args[2] = typeTime;
+			// wrap string in quotes
+			c[i].args[0] = "'"+c[i].args[0]+"'";
+		}else if(c[i].name == "doh.robot.keyPress"){
+			// take care of standalone keypresses
+			// characters should be wrapped in quotes.
+			// non-characters should be replaced with their corresponding dojo.keys constant
+			if(typeof c[i].args[0] == "string"){
+				// one keypress of a character by itself should be wrapped in quotes
+				c[i].args[0] = "'"+c[i].args[0]+"'";
+			}else{
+				if(c[i].args[0]==0){
+					// toss null keypresses
+					c.splice(i,1);
+				}else{
+					// look up dojo.keys.constant if possible
+					for(var j in dojo.keys){
+						if(dojo.keys[j] == c[i].args[0]){
+							c[i].args[0] = "dojo.keys."+j;
+							break;
+						}
+					}
+				}
+			}
+		}
+	}
 }
-div.appendChild(pre);
-var _14=document.createElement("button");
-_14.innerHTML="Close";
-var _15=dojo.connect(_14,"onmouseup",function(e){
-dojo.stopEvent(e);
-document.body.removeChild(div);
-dojo.disconnect(_15);
-});
-div.appendChild(_14);
-document.body.appendChild(div);
-_4=[];
+
+var toggle = function(){
+	// summary:
+	//	Toggles recording the user's input.
+	//	Hotkey: CTRL- ALT-ENTER
+	//
+	if(!startTime){ start(); }
+	else{ stop(); }
 }
-};
-var _16=function(_17){
-if(typeof _17=="string"){
-return "'"+_17+"'";
-}else{
-if(_17.id){
-return "'"+_17.id+"'";
-}else{
-var _18=document.getElementsByTagName(_17.nodeName);
-var i;
-for(i=0;i<_18.length;i++){
-if(_18[i]==_17){
-break;
+
+var stop = function(){
+	// summary:
+	//	Stops recording the user's input,
+	//	and displays the generated code.
+	//
+
+	var dt = Math.round((new Date()).getTime() - startTime.getTime());
+	startTime = null;
+	_optimize();
+	var c = commands;
+	console.log("Stop called. Commands: " + c.length);
+	if(c.length){
+		var s = "doh.register('dojox.robot.AutoGeneratedTestGroup',{\n";
+		s += "     name: 'autotest" + (testNumber++)+"',\n";
+		s += "     timeout: " + (dt+2000)+",\n";
+		s += "     runTest: function(){\n";
+		s += "          var d = new doh.Deferred();\n";
+		for(var i = 0; i<c.length; i++){
+			s += "          "+c[i].name+"(";
+			for(var j = 0; j<c[i].args.length; j++){
+				var arg = c[i].args[j];
+				s += arg;
+				if(j != c[i].args.length-1){ s += ", "; }
+			}
+			s += ");\n";
+		}
+		s += "          doh.robot.sequence(function(){\n";
+		s += "               if(/*Your condition here*/){\n";
+		s += "                    d.callback(true);\n";
+		s += "               }else{\n";
+		s += "                    d.errback(new Error('We got a failure'));\n";
+		s += "               }\n";
+		s += "          }, 1000);\n";
+		s += "          return d;\n";
+		s += "     }\n";
+		s += "});\n";
+		var div = document.createElement('div');
+		div.id="dojox.robot.recorder";
+		div.style.backgroundColor = "white";
+		div.style.position = "absolute";
+		var scroll = {y: (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0),
+		x: (window.pageXOffset || (window["dojo"]?dojo._fixIeBiDiScrollLeft(document.documentElement.scrollLeft):undefined) || document.body.scrollLeft || 0)};
+		div.style.left = scroll.x+"px";
+		div.style.top = scroll.y+"px";
+		var h1 = document.createElement('h1');
+		h1.innerHTML = "Your code:";
+		div.appendChild(h1);
+		var pre = document.createElement('pre');
+		if(pre.innerText !== undefined){
+			pre.innerText = s;
+		}else{
+			pre.textContent = s;
+		}
+		div.appendChild(pre);
+		var button = document.createElement('button');
+		button.innerHTML = "Close";
+		var connect = dojo.connect(button,'onmouseup',function(e){
+			dojo.stopEvent(e);
+			document.body.removeChild(div);
+			dojo.disconnect(connect);
+		});
+		div.appendChild(button);
+		document.body.appendChild(div);
+		commands = [];
+	}
 }
+
+var getSelector = function(node){
+	// Selenium/Windmill recorders have a concept of a "selector."
+	// The idea is that recorders need some reference to an element that persists even after a page refresh.
+	// For elements with ids, this is easy; just use the id.
+	// For other elements, we have to be more sly.
+
+	if(typeof node =="string"){
+		// it's already an id to be interpreted by dojo.byId
+		return "'" + node+"'";
+	}else if(node.id){
+		// it has an id
+		return "'" + node.id+"'";
+	}else{
+		// TODO: need a generic selector, like CSS3/dojo.query, for the default return value
+		// for now, just do getElementsByTagName
+		var nodes = document.getElementsByTagName(node.nodeName);
+		var i;
+		for(i = 0; i<nodes.length; i++){
+			if(nodes[i] == node){
+				break;
+			}
+		}
+		// wrap in a function to defer evaluation
+		return "function(){ return document.getElementsByTagName('" + node.nodeName+"')["+i+"]; }";
+	}
 }
-return "function(){ return document.getElementsByTagName('"+_17.nodeName+"')["+i+"]; }";
+
+var getMouseButtonObject = function(b){
+	// convert native event to doh.robot API
+	return "{left:" + (b==0)+", middle:" + (b==1)+", right:" + (b==2)+"}";
 }
+
+
+var getModifierObject = function(e){
+	// convert native event to doh.robot API
+	return "{'shift':" + (e.shiftKey)+", 'ctrl':" + (e.ctrlKey)+", 'alt':" + (e.altKey)+"}";
 }
-};
-var _19=function(b){
-return "{left:"+(b==0)+", middle:"+(b==1)+", right:"+(b==2)+"}";
-};
-var _1a=function(e){
-return "{'shift':"+(e.shiftKey)+", 'ctrl':"+(e.ctrlKey)+", 'alt':"+(e.altKey)+"}";
-};
+
+// dojo.connects
+
 dojo.connect(document,"onkeydown",function(e){
-if((e.keyCode==dojo.keys.ENTER||e.keyCode==77)&&e.ctrlKey&&e.altKey){
-dojo.stopEvent(e);
-_11();
-}
+	// the CTRL- ALT-ENTER hotkey to activate the recorder
+	//console.log(e.keyCode + ", " + e.ctrlKey+", " + e.altKey);
+	if((e.keyCode == dojo.keys.ENTER || e.keyCode==77) && e.ctrlKey && e.altKey){
+		dojo.stopEvent(e);
+		toggle();
+	}
 });
-var _1b={type:""};
-var _1c=function(e){
-if(!e||_1b.type==e.type&&_1b.button==e.button){
-return;
-}
-_1b={type:e.type,button:e.button};
-var _1d=_16(e.target);
-var _1e=dojo.coords(e.target);
-_9("doh.robot.mouseMoveAt",[_1d,0,100,e.clientX-_1e.x,e.clientY-_1e.y]);
-_9("doh.robot.mousePress",[_19(e.button-(dojo.isIE?1:0)),0]);
+
+var lastEvent = {type:""};
+
+var onmousedown = function(e){
+	// handler for mouse down
+	if(!e || lastEvent.type==e.type && lastEvent.button==e.button){ return; }
+	lastEvent={type:e.type, button:e.button};
+	var selector = getSelector(e.target);
+	var coords = dojo.coords(e.target);
+	addCommand("doh.robot.mouseMoveAt",[selector, 0, 100, e.clientX - coords.x, e.clientY-coords.y]);
+	addCommand("doh.robot.mousePress",[getMouseButtonObject(e.button-(dojo.isIE?1:0)), 0]);
 };
-var _1f=function(e){
-if(!e||_1b.type==e.type&&_1b.button==e.button){
-return;
-}
-_1b={type:e.type,button:e.button};
-var _20=_16(e.target);
-var _21=dojo.coords(e.target);
-_9("doh.robot.mouseClick",[_19(e.button-(dojo.isIE?1:0)),0]);
+
+var onclick = function(e){
+	// handler for mouse up
+	if(!e || lastEvent.type==e.type && lastEvent.button==e.button){ return; }
+	lastEvent={type:e.type, button:e.button};
+	var selector = getSelector(e.target);
+	var coords = dojo.coords(e.target);
+	addCommand("doh.robot.mouseClick",[getMouseButtonObject(e.button-(dojo.isIE?1:0)), 0]);
 };
-var _22=function(e){
-if(!e||_1b.type==e.type&&_1b.button==e.button){
-return;
-}
-_1b={type:e.type,button:e.button};
-var _23=_16(e.target);
-var _24=dojo.coords(e.target);
-_9("doh.robot.mouseRelease",[_19(e.button-(dojo.isIE?1:0)),0]);
+
+var onmouseup = function(e){
+	// handler for mouse up
+	if(!e || lastEvent.type==e.type && lastEvent.button==e.button){ return; }
+	lastEvent={type:e.type, button:e.button};
+	var selector = getSelector(e.target);
+	var coords = dojo.coords(e.target);
+	addCommand("doh.robot.mouseRelease",[getMouseButtonObject(e.button-(dojo.isIE?1:0)), 0]);
 };
-var _25=function(e){
-if(!e||_1b.type==e.type&&_1b.pageX==e.pageX&&_1b.pageY==e.pageY){
-return;
-}
-_1b={type:e.type,pageX:e.pageX,pageY:e.pageY};
-_9("doh.robot.mouseMove",[e.pageX,e.pageY,0,100,true]);
+
+var onmousemove = function(e){
+	// handler for mouse move
+	if(!e || lastEvent.type==e.type && lastEvent.pageX==e.pageX && lastEvent.pageY==e.pageY){ return; }
+	lastEvent={type:e.type, pageX:e.pageX, pageY:e.pageY};
+	addCommand("doh.robot.mouseMove",[e.pageX, e.pageY, 0, 100, true]);
 };
-var _26=function(e){
-if(!e||_1b.type==e.type&&_1b.pageX==e.pageX&&_1b.pageY==e.pageY){
-return;
-}
-_1b={type:e.type,detail:(e.detail?(e.detail):(-e.wheelDelta/120))};
-_9("doh.robot.mouseWheel",[_1b.detail]);
+
+var onmousewheel = function(e){
+	// handler for mouse move
+	if(!e || lastEvent.type==e.type && lastEvent.pageX==e.pageX && lastEvent.pageY==e.pageY){ return; }
+	lastEvent={type:e.type, detail:(e.detail ? (e.detail) : (-e.wheelDelta / 120))};
+	addCommand("doh.robot.mouseWheel",[lastEvent.detail]);
 };
-var _27=function(e){
-if(!e||_1b.type==e.type&&(_1b.charCode==e.charCode&&_1b.keyCode==e.keyCode)){
-return;
-}
-_1b={type:e.type,charCode:e.charCode,keyCode:e.keyCode};
-_9("doh.robot.keyPress",[e.charOrCode==dojo.keys.SPACE?" ":e.charOrCode,0,_1a(e)]);
+
+var onkeypress = function(e){
+	// handler for key press
+	if(!e || lastEvent.type==e.type && (lastEvent.charCode == e.charCode && lastEvent.keyCode == e.keyCode)){ return; }
+	lastEvent={type:e.type, charCode:e.charCode, keyCode:e.keyCode};
+	addCommand("doh.robot.keyPress",[e.charOrCode==dojo.keys.SPACE?' ':e.charOrCode, 0, getModifierObject(e)]);
 };
-var _28=function(e){
-if(!e||_1b.type==e.type&&(_1b.charCode==e.charCode&&_1b.keyCode==e.keyCode)){
-return;
+
+var onkeyup = function(e){
+	if(!e || lastEvent.type==e.type && (lastEvent.charCode == e.charCode && lastEvent.keyCode == e.keyCode)){ return; }
+	lastEvent={type:e.type, charCode:e.charCode, keyCode:e.keyCode};
 }
-_1b={type:e.type,charCode:e.charCode,keyCode:e.keyCode};
-};
-dojo.connect(document,"onmousedown",_1c);
-dojo.connect(document,"onmouseup",_22);
-dojo.connect(document,"onclick",_1f);
-dojo.connect(document,"onkeypress",_27);
-dojo.connect(document,"onkeyup",_28);
-dojo.connect(document,"onmousemove",_25);
-dojo.connect(document,!dojo.isMozilla?"onmousewheel":"DOMMouseScroll",_26);
+
+// trap all native elements' events
+dojo.connect(document,"onmousedown",onmousedown);
+dojo.connect(document,"onmouseup",onmouseup);
+dojo.connect(document,"onclick",onclick);
+dojo.connect(document,"onkeypress",onkeypress);
+dojo.connect(document,"onkeyup",onkeyup);
+dojo.connect(document,"onmousemove",onmousemove);
+dojo.connect(document,!dojo.isMozilla ? "onmousewheel" : 'DOMMouseScroll',onmousewheel);
+
 dojo.addOnLoad(function(){
-if(window["dijit"]&&dijit.scrollIntoView){
-dojo.connect(dijit,"scrollIntoView",function(_29){
-_9("doh.robot.scrollIntoView",[_16(_29)]);
-});
-}
-});
-dojo.connect(dojo,"connect",function(_2a,_2b,f){
-if(_2a&&(!f||!f._mine)){
-var _2c=null;
-if(_2b.toLowerCase()=="onmousedown"){
-_2c=dojo.hitch(this,_1c);
-}else{
-if(_2b.toLowerCase()==(!dojo.isMozilla?"onmousewheel":"dommousescroll")){
-_2c=dojo.hitch(this,_26);
-}else{
-if(_2b.toLowerCase()=="onclick"){
-_2c=dojo.hitch(this,_1f);
-}else{
-if(_2b.toLowerCase()=="onmouseup"){
-_2c=dojo.hitch(this,_22);
-}else{
-if(_2b.toLowerCase()=="onkeypress"){
-_2c=dojo.hitch(this,_27);
-}else{
-if(_2b.toLowerCase()=="onkeyup"){
-_2c=dojo.hitch(this,_28);
-}
-}
-}
-}
-}
-}
-if(_2c==null){
-return;
-}
-_2c._mine=true;
-dojo.connect(_2a,_2b,_2c);
-}
+	// get scrollIntoView for good measure
+	// catch: dojo.window might not be loaded (yet?) so addonload
+	if(dojo.window){
+		dojo.connect(dojo.window,"scrollIntoView",function(node){
+			addCommand("doh.robot.scrollIntoView",[getSelector(node)]);
+		});
+	}
 });
+
+// Get Dojo widget events too!
+dojo.connect(dojo, "connect", 
+	function(/*dijit._Widget*/ widget, /*String*/ event, /*Function*/ f){
+		// kill recursion
+		// check for private variable _mine to make sure this isn't a recursive loop
+		if(widget && (!f || !f._mine)){
+			var hitchedf = null;
+			if(event.toLowerCase() == "onmousedown"){
+				hitchedf = dojo.hitch(this,onmousedown);
+			}else if(event.toLowerCase() == (!dojo.isMozilla ? "onmousewheel" : 'dommousescroll')){
+				hitchedf = dojo.hitch(this,onmousewheel);
+			}else if(event.toLowerCase() == "onclick"){
+				hitchedf = dojo.hitch(this,onclick);
+			}else if(event.toLowerCase() == "onmouseup"){
+				hitchedf = dojo.hitch(this,onmouseup);
+			}else if(event.toLowerCase() == "onkeypress"){
+				hitchedf = dojo.hitch(this,onkeypress);
+			}else if(event.toLowerCase() == "onkeyup"){
+				hitchedf = dojo.hitch(this,onkeyup);
+			}
+			if(hitchedf == null){ return; }
+			hitchedf._mine = true;
+			dojo.connect(widget,event,hitchedf);
+		}
+	});
 })();
-}
diff --git a/dojox/robot/tests/module.js b/dojox/robot/tests/module.js
new file mode 100644
index 0000000..9a935e2
--- /dev/null
+++ b/dojox/robot/tests/module.js
@@ -0,0 +1,8 @@
+dojo.provide("dojox.robot.tests.module");
+
+try{
+	dojo.require("dojox.robot.tests.robotml");
+}catch(e){
+	doh.debug(e);
+}
+
diff --git a/dojox/robot/tests/robotml.js b/dojox/robot/tests/robotml.js
new file mode 100644
index 0000000..ddb17b0
--- /dev/null
+++ b/dojox/robot/tests/robotml.js
@@ -0,0 +1,9 @@
+dojo.provide("dojox.robot.tests.robotml");
+
+try{
+	if(dojo.isBrowser){
+		doh.registerUrl("dojox.robot.tests.test_recorder", dojo.moduleUrl("dojox", "robot/tests/test_recorder.html"), 999999);
+	}
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/robot/tests/runTests.html b/dojox/robot/tests/runTests.html
new file mode 100644
index 0000000..79dd4e4
--- /dev/null
+++ b/dojox/robot/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>dojox.robot Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.robot.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/robot/tests/test_recorder.html b/dojox/robot/tests/test_recorder.html
new file mode 100644
index 0000000..34a1c92
--- /dev/null
+++ b/dojox/robot/tests/test_recorder.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox Recorder Test</title>
+
+	<style>
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<!-- only needed for alternate theme testing: -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.robot");
+		dojo.require("dojox.robot.recorder");
+		dojo.addOnLoad(function(){
+			doh.register('dojox.robot.AutoGeneratedTestGroup',{
+				// would be nice to have Deferred support for setUp/tearDown
+				name: 'setUp',
+				timeout: 5100,
+				runTest: function(){
+					var d = new doh.Deferred();
+					// start the recorder and close the alert
+					dojo.byId('textbox').value="";
+					doh.robot.mouseMoveAt('safeclick');
+					doh.robot.mouseClick({left:true, middle:false, right:false}, 3);
+					doh.robot.keyPress(dojo.keys.ENTER, 3000,null,true);
+					doh.robot.keyPress(dojo.keys.ENTER, 1000,{ctrl:true,alt:true});
+					setTimeout(function(){
+						d.callback(true);
+					},5000);
+					return d;
+				}
+			});
+			doh.register('dojox.robot.AutoGeneratedTestGroup',{
+				name: 'autotest0',
+				timeout: 8879,
+				runTest: function(){
+					var d = new doh.Deferred();
+					// Safari/Mac stops listening to mouse movement after the alert pops up in the runner
+					// click to wake it up
+					doh.robot.mouseMoveAt('safeclick');
+					doh.robot.mouseClick({left:true, middle:false, right:false});
+					doh.robot.mouseMove(196, 124, 353,true);
+					doh.robot._scrollIntoView('widget_combo');
+					doh.robot.mouseMoveAt(dijit.byId('combo').downArrowNode, 18, 100, 1, 7);
+					doh.robot.mouseClick({left:true, middle:false, right:false}, 1);
+					doh.robot.mouseMove(195, 124, 546,true);
+					doh.robot.mouseMove(174, 165, 16,true);
+					doh.robot.mouseMoveAt('combo_popup2', 483, 100, 148, 5);
+					doh.robot.mouseClick({left:true, middle:false, right:false}, 1);
+					doh.robot.mouseMove(155, 195, 334,true);
+					doh.robot.mouseMoveAt('textbox', 331, 100, 131, 11);
+					doh.robot.mouseClick({left:true, middle:false, right:false}, 1);
+					doh.robot.typeKeys('test me', 602, 1500);
+					doh.robot.keyPress(dojo.keys.ENTER, 500,{ctrl:true,alt:true});
+					doh.robot.sequence(function(){
+						var div=dojo.byId('dojox.robot.recorder');
+						var text;
+						if(div["innerText"] !== undefined){
+							text = div.innerText;
+						}else if(div["textContent"]){
+							text = div.textContent;
+						}
+						var re = new RegExp
+("MoveAt.*Click.*Move.*scrollIntoView.*MoveAt.*Click.*Move\\(.*MoveAt.*Click.*Move\\(.*MoveAt.*Click.*typeKeys");
+						if(re.test(text.replace(/[\n\r\t]/g))){
+							d.callback(true);
+						}else{
+							d.errback(new Error('We got a failure'));
+						}
+					}, 1000);
+					return d;
+				}
+			});
+
+			doh.run();
+		});
+	</script>
+</head>
+<body class="tundra">
+<h1 id="safeclick">Recorder will use the DOH robot to record a test by itself.</h1>
+<p>dijit.form.ComboBox:</p>
+<select dojoType="dijit.form.ComboBox" id="combo">
+<option>A</option>
+<option>B</option>
+<option>C</option>
+</select>
+<p>Native element:</p>
+<input type="text" id="textbox">
+</body>
+</html>
diff --git a/dojox/rpc/Client.js b/dojox/rpc/Client.js
index 5a5e436..20c95d3 100644
--- a/dojox/rpc/Client.js
+++ b/dojox/rpc/Client.js
@@ -1,21 +1,21 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.rpc.Client"]){
-dojo._hasResource["dojox.rpc.Client"]=true;
 dojo.provide("dojox.rpc.Client");
-(function(){
-dojo._defaultXhr=dojo.xhr;
-dojo.xhr=function(_1,_2){
-var _3=_2.headers=_2.headers||{};
-_3["Client-Id"]=dojox.rpc.Client.clientId;
-_3["Seq-Id"]=dojox._reqSeqId=(dojox._reqSeqId||0)+1;
-return dojo._defaultXhr.apply(dojo,arguments);
-};
+// Provide extra headers for robust client and server communication
+(function() {
+	dojo._defaultXhr = dojo.xhr;
+	dojo.xhr = function(method,args){
+		var headers = args.headers = args.headers || {};
+		// set the client id, this can be used by servers to maintain state information with the
+		// a specific client. Many servers rely on sessions for this, but sessions are shared
+		// between tabs/windows, so this is not appropriate for application state, it
+		// really only useful for storing user authentication
+		headers["Client-Id"] = dojox.rpc.Client.clientId;
+		// set the sequence id. HTTP is non-deterministic, message can arrive at the server
+		// out of order. In complex Ajax applications, it may be more to ensure that messages
+		// can be properly sequenced deterministically. This applies a sequency id to each
+		// XHR request so that the server can order them.
+		headers["Seq-Id"] = dojox._reqSeqId = (dojox._reqSeqId||0)+1;
+		return dojo._defaultXhr.apply(dojo,arguments);
+	}
 })();
-dojox.rpc.Client.clientId=(Math.random()+"").substring(2,14)+(new Date().getTime()+"").substring(8,13);
-}
+// initiate the client id to a good random number
+dojox.rpc.Client.clientId = (Math.random() + '').substring(2,14) + (new Date().getTime() + '').substring(8,13);
diff --git a/dojox/rpc/JsonRPC.js b/dojox/rpc/JsonRPC.js
index 622af64..ce17815 100644
--- a/dojox/rpc/JsonRPC.js
+++ b/dojox/rpc/JsonRPC.js
@@ -1,39 +1,55 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.rpc.JsonRPC"]){
-dojo._hasResource["dojox.rpc.JsonRPC"]=true;
 dojo.provide("dojox.rpc.JsonRPC");
 dojo.require("dojox.rpc.Service");
+
 (function(){
-function _1(_2){
-return {serialize:function(_3,_4,_5,_6){
-var d={id:this._requestId++,method:_4.name,params:_5};
-if(_2){
-d.jsonrpc=_2;
-}
-return {data:dojo.toJson(d),handleAs:"json",contentType:"application/json",transport:"POST"};
-},deserialize:function(_7){
-if("Error"==_7.name){
-_7=dojo.fromJson(_7.responseText);
-}
-if(_7.error){
-var e=new Error(_7.error.message||_7.error);
-e._rpcErrorObject=_7.error;
-return e;
-}
-return _7.result;
-}};
-};
-dojox.rpc.envelopeRegistry.register("JSON-RPC-1.0",function(_8){
-return _8=="JSON-RPC-1.0";
-},dojo.mixin({namedParams:false},_1()));
-dojox.rpc.envelopeRegistry.register("JSON-RPC-2.0",function(_9){
-return _9=="JSON-RPC-2.0";
-},_1("2.0"));
+	function jsonRpcEnvelope(version){
+		return {
+			serialize: function(smd, method, data, options){
+				//not converted to json it self. This  will be done, if
+				//appropriate, at the transport level
+	
+				var d = {
+					id: this._requestId++,
+					method: method.name,
+					params: data
+				};
+				if(version){
+					d.jsonrpc = version;
+				}
+				return {
+					data: dojo.toJson(d),
+					handleAs:'json',
+					contentType: 'application/json',
+					transport:"POST"
+				};
+			},
+	
+			deserialize: function(obj){
+				if ('Error' == obj.name){
+					obj = dojo.fromJson(obj.responseText);
+				}
+				if(obj.error) {
+					var e = new Error(obj.error.message || obj.error);
+					e._rpcErrorObject = obj.error;
+					return e;
+				}
+				return obj.result;
+			}
+		};
+	}
+	dojox.rpc.envelopeRegistry.register(
+		"JSON-RPC-1.0",
+		function(str){
+			return str == "JSON-RPC-1.0";
+		},
+		dojo.mixin({namedParams:false},jsonRpcEnvelope()) // 1.0 will only work with ordered params
+	);
+
+	dojox.rpc.envelopeRegistry.register(
+		"JSON-RPC-2.0",
+		function(str){
+			return str == "JSON-RPC-2.0";
+		},
+		jsonRpcEnvelope("2.0")
+	);
 })();
-}
diff --git a/dojox/rpc/JsonRest.js b/dojox/rpc/JsonRest.js
index fd155c4..34c03b8 100644
--- a/dojox/rpc/JsonRest.js
+++ b/dojox/rpc/JsonRest.js
@@ -1,342 +1,457 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.rpc.JsonRest"]){
-dojo._hasResource["dojox.rpc.JsonRest"]=true;
 dojo.provide("dojox.rpc.JsonRest");
-dojo.require("dojox.json.ref");
+
+dojo.require("dojox.json.ref"); // this provides json indexing
 dojo.require("dojox.rpc.Rest");
+// summary:
+// 		Provides JSON/REST utility functions
 (function(){
-var _1=[];
-var _2=dojox.rpc.Rest;
-var jr;
-function _3(_4,_5,_6,_7){
-var _8=_5.ioArgs&&_5.ioArgs.xhr&&_5.ioArgs.xhr.getResponseHeader("Last-Modified");
-if(_8&&_2._timeStamps){
-_2._timeStamps[_7]=_8;
-}
-var _9=_4._schema&&_4._schema.hrefProperty;
-if(_9){
-dojox.json.ref.refAttribute=_9;
-}
-_6=_6&&dojox.json.ref.resolveJson(_6,{defaultId:_7,index:_2._index,timeStamps:_8&&_2._timeStamps,time:_8,idPrefix:_4.servicePath.replace(/[^\/]*$/,""),idAttribute:jr.getIdAttribute(_4),schemas:jr.schemas,loader:jr._loader,idAsRef:_4.idAsRef,assignAbsoluteIds:true});
-dojox.json.ref.refAttribute="$ref";
-return _6;
-};
-jr=dojox.rpc.JsonRest={serviceClass:dojox.rpc.Rest,conflictDateHeader:"If-Unmodified-Since",commit:function(_a){
-_a=_a||{};
-var _b=[];
-var _c={};
-var _d=[];
-for(var i=0;i<_1.length;i++){
-var _e=_1[i];
-var _f=_e.object;
-var old=_e.old;
-var _10=false;
-if(!(_a.service&&(_f||old)&&(_f||old).__id.indexOf(_a.service.servicePath))&&_e.save){
-delete _f.__isDirty;
-if(_f){
-if(old){
-var _11;
-if((_11=_f.__id.match(/(.*)#.*/))){
-_f=_2._index[_11[1]];
-}
-if(!(_f.__id in _c)){
-_c[_f.__id]=_f;
-if(_a.incrementalUpdates&&!_11){
-var _12=(typeof _a.incrementalUpdates=="function"?_a.incrementalUpdates:function(){
-_12={};
-for(var j in _f){
-if(_f.hasOwnProperty(j)){
-if(_f[j]!==old[j]){
-_12[j]=_f[j];
-}
-}else{
-if(old.hasOwnProperty(j)){
-return null;
-}
-}
-}
-return _12;
-})(_f,old);
-}
-if(_12){
-_b.push({method:"post",target:_f,content:_12});
-}else{
-_b.push({method:"put",target:_f,content:_f});
-}
-}
-}else{
-var _13=jr.getServiceAndId(_f.__id).service;
-var _14=jr.getIdAttribute(_13);
-if((_14 in _f)&&!_a.alwaysPostNewItems){
-_b.push({method:"put",target:_f,content:_f});
-}else{
-_b.push({method:"post",target:{__id:_13.servicePath},content:_f});
-}
-}
-}else{
-if(old){
-_b.push({method:"delete",target:old});
-}
-}
-_d.push(_e);
-_1.splice(i--,1);
-}
-}
-dojo.connect(_a,"onError",function(){
-if(_a.revertOnError!==false){
-var _15=_1;
-_1=_d;
-var _16=0;
-jr.revert();
-_1=_15;
-}else{
-_1=dirtyObject.concat(_d);
-}
-});
-jr.sendToServer(_b,_a);
-return _b;
-},sendToServer:function(_17,_18){
-var _19;
-var _1a=dojo.xhr;
-var _1b=_17.length;
-var i,_1c;
-var _1d;
-var _1e=this.conflictDateHeader;
-dojo.xhr=function(_1f,_20){
-_20.headers=_20.headers||{};
-_20.headers["Transaction"]=_17.length-1==i?"commit":"open";
-if(_1e&&_1d){
-_20.headers[_1e]=_1d;
-}
-if(_1c){
-_20.headers["Content-ID"]="<"+_1c+">";
-}
-return _1a.apply(dojo,arguments);
-};
-for(i=0;i<_17.length;i++){
-var _21=_17[i];
-dojox.rpc.JsonRest._contentId=_21.content&&_21.content.__id;
-var _22=_21.method=="post";
-_1d=_21.method=="put"&&_2._timeStamps[_21.content.__id];
-if(_1d){
-_2._timeStamps[_21.content.__id]=(new Date())+"";
-}
-_1c=_22&&dojox.rpc.JsonRest._contentId;
-var _23=jr.getServiceAndId(_21.target.__id);
-var _24=_23.service;
-var dfd=_21.deferred=_24[_21.method](_23.id.replace(/#/,""),dojox.json.ref.toJson(_21.content,false,_24.servicePath,true));
-(function(_25,dfd,_26){
-dfd.addCallback(function(_27){
-try{
-var _28=dfd.ioArgs.xhr&&dfd.ioArgs.xhr.getResponseHeader("Location");
-if(_28){
-var _29=_28.match(/(^\w+:\/\/)/)&&_28.indexOf(_26.servicePath);
-_28=_29>0?_28.substring(_29):(_26.servicePath+_28).replace(/^(.*\/)?(\w+:\/\/)|[^\/\.]+\/\.\.\/|^.*\/(\/)/,"$2$3");
-_25.__id=_28;
-_2._index[_28]=_25;
-}
-_27=_3(_26,dfd,_27,_25&&_25.__id);
-}
-catch(e){
-}
-if(!(--_1b)){
-if(_18.onComplete){
-_18.onComplete.call(_18.scope,_17);
-}
-}
-return _27;
-});
-})(_21.content,dfd,_24);
-dfd.addErrback(function(_2a){
-_1b=-1;
-_18.onError.call(_18.scope,_2a);
-});
-}
-dojo.xhr=_1a;
-},getDirtyObjects:function(){
-return _1;
-},revert:function(_2b){
-for(var i=_1.length;i>0;){
-i--;
-var _2c=_1[i];
-var _2d=_2c.object;
-var old=_2c.old;
-var _2e=dojox.data._getStoreForItem(_2d||old);
-if(!(_2b&&(_2d||old)&&(_2d||old).__id.indexOf(_2b.servicePath))){
-if(_2d&&old){
-for(var j in old){
-if(old.hasOwnProperty(j)&&_2d[j]!==old[j]){
-if(_2e){
-_2e.onSet(_2d,j,_2d[j],old[j]);
-}
-_2d[j]=old[j];
-}
-}
-for(j in _2d){
-if(!old.hasOwnProperty(j)){
-if(_2e){
-_2e.onSet(_2d,j,_2d[j]);
-}
-delete _2d[j];
-}
-}
-}else{
-if(!old){
-if(_2e){
-_2e.onDelete(_2d);
-}
-}else{
-if(_2e){
-_2e.onNew(old);
-}
-}
-}
-delete (_2d||old).__isDirty;
-_1.splice(i,1);
-}
-}
-},changing:function(_2f,_30){
-if(!_2f.__id){
-return;
-}
-_2f.__isDirty=true;
-for(var i=0;i<_1.length;i++){
-var _31=_1[i];
-if(_2f==_31.object){
-if(_30){
-_31.object=false;
-if(!this._saveNotNeeded){
-_31.save=true;
-}
-}
-return;
-}
-}
-var old=_2f instanceof Array?[]:{};
-for(i in _2f){
-if(_2f.hasOwnProperty(i)){
-old[i]=_2f[i];
-}
-}
-_1.push({object:!_30&&_2f,old:old,save:!this._saveNotNeeded});
-},deleteObject:function(_32){
-this.changing(_32,true);
-},getConstructor:function(_33,_34){
-if(typeof _33=="string"){
-var _35=_33;
-_33=new dojox.rpc.Rest(_33,true);
-this.registerService(_33,_35,_34);
-}
-if(_33._constructor){
-return _33._constructor;
-}
-_33._constructor=function(_36){
-var _37=this;
-var _38=arguments;
-var _39;
-var _3a;
-function _3b(_3c){
-if(_3c){
-_3b(_3c["extends"]);
-_39=_3c.properties;
-for(var i in _39){
-var _3d=_39[i];
-if(_3d&&(typeof _3d=="object")&&("default" in _3d)){
-_37[i]=_3d["default"];
-}
-}
-}
-if(_3c&&_3c.prototype&&_3c.prototype.initialize){
-_3a=true;
-_3c.prototype.initialize.apply(_37,_38);
-}
-};
-_3b(_33._schema);
-if(!_3a&&_36&&typeof _36=="object"){
-dojo.mixin(_37,_36);
-}
-var _3e=jr.getIdAttribute(_33);
-_2._index[this.__id=this.__clientId=_33.servicePath+(this[_3e]||Math.random().toString(16).substring(2,14)+"@"+((dojox.rpc.Client&&dojox.rpc.Client.clientId)||"client"))]=this;
-if(dojox.json.schema&&_39){
-dojox.json.schema.mustBeValid(dojox.json.schema.validate(this,_33._schema));
-}
-_1.push({object:this,save:true});
-};
-return dojo.mixin(_33._constructor,_33._schema,{load:_33});
-},fetch:function(_3f){
-var _40=jr.getServiceAndId(_3f);
-return this.byId(_40.service,_40.id);
-},getIdAttribute:function(_41){
-var _42=_41._schema;
-var _43;
-if(_42){
-if(!(_43=_42._idAttr)){
-for(var i in _42.properties){
-if(_42.properties[i].identity||(_42.properties[i].link=="self")){
-_42._idAttr=_43=i;
-}
-}
-}
-}
-return _43||"id";
-},getServiceAndId:function(_44){
-var _45="";
-for(var _46 in jr.services){
-if((_44.substring(0,_46.length)==_46)&&(_46.length>=_45.length)){
-_45=_46;
-}
-}
-if(_45){
-return {service:jr.services[_45],id:_44.substring(_45.length)};
-}
-var _47=_44.match(/^(.*\/)([^\/]*)$/);
-return {service:new jr.serviceClass(_47[1],true),id:_47[2]};
-},services:{},schemas:{},registerService:function(_48,_49,_4a){
-_49=_48.servicePath=_49||_48.servicePath;
-_48._schema=jr.schemas[_49]=_4a||_48._schema||{};
-jr.services[_49]=_48;
-},byId:function(_4b,id){
-var _4c,_4d=_2._index[(_4b.servicePath||"")+id];
-if(_4d&&!_4d._loadObject){
-_4c=new dojo.Deferred();
-_4c.callback(_4d);
-return _4c;
-}
-return this.query(_4b,id);
-},query:function(_4e,id,_4f){
-var _50=_4e(id,_4f);
-_50.addCallback(function(_51){
-if(_51.nodeType&&_51.cloneNode){
-return _51;
-}
-return _3(_4e,_50,_51,typeof id!="string"||(_4f&&(_4f.start||_4f.count))?undefined:id);
-});
-return _50;
-},_loader:function(_52){
-var _53=jr.getServiceAndId(this.__id);
-var _54=this;
-jr.query(_53.service,_53.id).addBoth(function(_55){
-if(_55==_54){
-delete _55.$ref;
-delete _55._loadObject;
-}else{
-_54._loadObject=function(_56){
-_56(_55);
-};
-}
-_52(_55);
-});
-},isDirty:function(_57){
-if(!_57){
-return !!_1.length;
-}
-return _57.__isDirty;
-}};
+	var dirtyObjects = [];
+	var Rest = dojox.rpc.Rest;
+	var jr;
+	function resolveJson(service, deferred, value, defaultId){
+		var timeStamp = deferred.ioArgs && deferred.ioArgs.xhr && deferred.ioArgs.xhr.getResponseHeader("Last-Modified");
+		if(timeStamp && Rest._timeStamps){
+			Rest._timeStamps[defaultId] = timeStamp;
+		}
+		var hrefProperty = service._schema && service._schema.hrefProperty;
+		if(hrefProperty){
+			dojox.json.ref.refAttribute = hrefProperty;
+		}
+		value = value && dojox.json.ref.resolveJson(value, {
+			defaultId: defaultId, 
+			index: Rest._index,
+			timeStamps: timeStamp && Rest._timeStamps,
+			time: timeStamp,
+			idPrefix: service.servicePath.replace(/[^\/]*$/,''),
+			idAttribute: jr.getIdAttribute(service),
+			schemas: jr.schemas,
+			loader:	jr._loader,
+			idAsRef: service.idAsRef, 
+			assignAbsoluteIds: true
+		});
+		dojox.json.ref.refAttribute  = "$ref";
+		return value;
+	}
+	jr = dojox.rpc.JsonRest={
+		serviceClass: dojox.rpc.Rest,
+		conflictDateHeader: "If-Unmodified-Since",
+		commit: function(kwArgs){
+			// summary:
+			//		Saves the dirty data using REST Ajax methods
+
+			kwArgs = kwArgs || {};
+			var actions = [];
+			var alreadyRecorded = {};
+			var savingObjects = [];
+			for(var i = 0; i < dirtyObjects.length; i++){
+				var dirty = dirtyObjects[i];
+				var object = dirty.object;
+				var old = dirty.old;
+				var append = false;
+				if(!(kwArgs.service && (object || old) && 
+						(object || old).__id.indexOf(kwArgs.service.servicePath)) && dirty.save){
+					delete object.__isDirty;
+					if(object){
+						if(old){
+							// changed object
+							var pathParts;
+							if((pathParts = object.__id.match(/(.*)#.*/))){ // it is a path reference
+								// this means it is a sub object, we must go to the parent object and save it
+								object = Rest._index[pathParts[1]];
+							}
+							if(!(object.__id in alreadyRecorded)){// if it has already been saved, we don't want to repeat it
+								// record that we are saving
+								alreadyRecorded[object.__id] = object;
+								if(kwArgs.incrementalUpdates 
+									&& !pathParts){ // I haven't figured out how we would do incremental updates on sub-objects yet
+									// make an incremental update using a POST
+									var incremental = (typeof kwArgs.incrementalUpdates == 'function' ?
+										kwArgs.incrementalUpdates : function(){
+											incremental = {};
+											for(var j in object){
+												if(object.hasOwnProperty(j)){
+													if(object[j] !== old[j]){
+														incremental[j] = object[j];
+													}
+												}else if(old.hasOwnProperty(j)){
+													// we can't use incremental updates to remove properties
+													return null;
+												}
+											}
+											return incremental;
+										})(object, old);
+								}
+								
+								if(incremental){
+									actions.push({method:"post",target:object, content: incremental});
+								}
+								else{
+									actions.push({method:"put",target:object,content:object});
+								}
+							}
+						}else{
+							// new object
+							var service = jr.getServiceAndId(object.__id).service;
+							var idAttribute = jr.getIdAttribute(service);
+							if((idAttribute in object) && !kwArgs.alwaysPostNewItems){
+								// if the id attribute is specified, then we should know the location
+								actions.push({method:"put",target:object, content:object});
+							}else{
+								actions.push({method:"post",target:{__id:service.servicePath},
+														content:object});
+							}
+						}
+					}else if(old){
+						// deleted object
+						actions.push({method:"delete",target:old});
+					}//else{ this would happen if an object is created and then deleted, don't do anything
+					savingObjects.push(dirty);
+					dirtyObjects.splice(i--,1);
+				}
+			}
+			dojo.connect(kwArgs,"onError",function(){
+				if(kwArgs.revertOnError !== false){
+					var postCommitDirtyObjects = dirtyObjects;
+					dirtyObjects = savingObjects;
+					var numDirty = 0; // make sure this does't do anything if it is called again
+					jr.revert(); // revert if there was an error
+					dirtyObjects = postCommitDirtyObjects;
+				}
+				else{
+					dirtyObjects = dirtyObject.concat(savingObjects); 
+				}
+			});
+			jr.sendToServer(actions, kwArgs);
+			return actions;
+		},
+		sendToServer: function(actions, kwArgs){
+			var xhrSendId;
+			var plainXhr = dojo.xhr;
+			var left = actions.length;// this is how many changes are remaining to be received from the server
+			var i, contentLocation;
+			var timeStamp;
+			var conflictDateHeader = this.conflictDateHeader;
+			// add headers for extra information
+			dojo.xhr = function(method,args){
+				// keep the transaction open as we send requests
+				args.headers = args.headers || {};
+				// the last one should commit the transaction
+				args.headers['Transaction'] = actions.length - 1 == i ? "commit" : "open";
+				if(conflictDateHeader && timeStamp){
+					args.headers[conflictDateHeader] = timeStamp; 
+				}
+				if(contentLocation){
+					args.headers['Content-ID'] = '<' + contentLocation + '>';
+				}
+				return plainXhr.apply(dojo,arguments);
+			};			
+			for(i =0; i < actions.length;i++){ // iterate through the actions to execute
+				var action = actions[i];
+				dojox.rpc.JsonRest._contentId = action.content && action.content.__id; // this is used by OfflineRest
+				var isPost = action.method == 'post';
+				timeStamp = action.method == 'put' && Rest._timeStamps[action.content.__id];
+				if(timeStamp){
+					// update it now
+					Rest._timeStamps[action.content.__id] = (new Date()) + '';
+				}
+				// send the content location to the server
+				contentLocation = isPost && dojox.rpc.JsonRest._contentId;
+				var serviceAndId = jr.getServiceAndId(action.target.__id);
+				var service = serviceAndId.service; 
+				var dfd = action.deferred = service[action.method](
+									serviceAndId.id.replace(/#/,''), // if we are using references, we need eliminate #
+									dojox.json.ref.toJson(action.content, false, service.servicePath, true)
+								);
+				(function(object, dfd, service){
+					dfd.addCallback(function(value){
+						try{
+							// Implements id assignment per the HTTP specification
+							var newId = dfd.ioArgs.xhr && dfd.ioArgs.xhr.getResponseHeader("Location");
+							//TODO: match URLs if the servicePath is relative...
+							if(newId){
+								// if the path starts in the middle of an absolute URL for Location, we will use the just the path part 
+								var startIndex = newId.match(/(^\w+:\/\/)/) && newId.indexOf(service.servicePath);
+								newId = startIndex > 0 ? newId.substring(startIndex) : (service.servicePath + newId).
+										// now do simple relative URL resolution in case of a relative URL. 
+										replace(/^(.*\/)?(\w+:\/\/)|[^\/\.]+\/\.\.\/|^.*\/(\/)/,'$2$3');
+								object.__id = newId;
+								Rest._index[newId] = object;
+							}
+							value = resolveJson(service, dfd, value, object && object.__id);
+						}catch(e){}
+						if(!(--left)){
+							if(kwArgs.onComplete){
+								kwArgs.onComplete.call(kwArgs.scope, actions);
+							}
+						}
+						return value;
+					});
+				})(action.content, dfd, service);
+								
+				dfd.addErrback(function(value){
+					
+					// on an error we want to revert, first we want to separate any changes that were made since the commit
+					left = -1; // first make sure that success isn't called
+					kwArgs.onError.call(kwArgs.scope, value);
+				});
+			}
+			// revert back to the normal XHR handler
+			dojo.xhr = plainXhr;
+			
+		},
+		getDirtyObjects: function(){
+			return dirtyObjects;
+		},
+		revert: function(service){
+			// summary:
+			//		Reverts all the changes made to JSON/REST data
+			for(var i = dirtyObjects.length; i > 0;){
+				i--;
+				var dirty = dirtyObjects[i];
+				var object = dirty.object;
+				var old = dirty.old;
+				var store = dojox.data._getStoreForItem(object || old);
+				
+				if(!(service && (object || old) && 
+					(object || old).__id.indexOf(service.servicePath))){
+					// if we are in the specified store or if this is a global revert
+					if(object && old){
+						// changed
+						for(var j in old){
+							if(old.hasOwnProperty(j) && object[j] !== old[j]){
+								if(store){
+									store.onSet(object, j, object[j], old[j]);
+								}
+								object[j] = old[j];
+							}
+						}
+						for(j in object){
+							if(!old.hasOwnProperty(j)){
+								if(store){
+									store.onSet(object, j, object[j]);
+								}
+								delete object[j];
+							}
+						}
+					}else if(!old){
+						// was an addition, remove it
+						if(store){
+							store.onDelete(object);
+						}
+					}else{
+						// was a deletion, we will add it back
+						if(store){
+							store.onNew(old);
+						}
+					}
+					delete (object || old).__isDirty;
+					dirtyObjects.splice(i, 1);
+				}
+			}
+		},
+		changing: function(object,_deleting){
+			// summary:
+			//		adds an object to the list of dirty objects.  This object
+			//		contains a reference to the object itself as well as a
+			//		cloned and trimmed version of old object for use with
+			//		revert.
+			if(!object.__id){
+				return;
+			}
+			object.__isDirty = true;
+			//if an object is already in the list of dirty objects, don't add it again
+			//or it will overwrite the premodification data set.
+			for(var i=0; i<dirtyObjects.length; i++){
+				var dirty = dirtyObjects[i];
+				if(object==dirty.object){
+					if(_deleting){
+						// we are deleting, no object is an indicator of deletiong
+						dirty.object = false;
+						if(!this._saveNotNeeded){
+							dirty.save = true;
+						}
+					}
+					return;
+				}
+			}
+			var old = object instanceof Array ? [] : {};
+			for(i in object){
+				if(object.hasOwnProperty(i)){
+					old[i] = object[i];
+				}
+			}
+			dirtyObjects.push({object: !_deleting && object, old: old, save: !this._saveNotNeeded});
+		},
+		deleteObject: function(object){
+			// summary:
+			//		deletes an object 
+			//	object:
+			//  	object to delete
+			this.changing(object,true);
+		},
+		getConstructor: function(/*Function|String*/service, schema){
+			// summary:
+			// 		Creates or gets a constructor for objects from this service
+			if(typeof service == 'string'){
+				var servicePath = service;
+				service = new dojox.rpc.Rest(service,true);
+				this.registerService(service, servicePath, schema);
+			}
+			if(service._constructor){
+				return service._constructor;
+			}
+			service._constructor = function(data){
+				// summary:
+				//		creates a new object for this table
+				//
+				//	data:
+				//		object to mixed in
+				var self = this;
+				var args = arguments;
+				var properties;
+				var initializeCalled;
+				function addDefaults(schema){
+					if(schema){
+						addDefaults(schema['extends']);
+						properties = schema.properties;
+						for(var i in properties){
+							var propDef = properties[i]; 
+							if(propDef && (typeof propDef == 'object') && ("default" in propDef)){
+								self[i] = propDef["default"];
+							}
+						}
+					}
+					if(schema && schema.prototype && schema.prototype.initialize){
+						initializeCalled = true;
+						schema.prototype.initialize.apply(self, args);
+					}
+				}
+				addDefaults(service._schema);
+				if(!initializeCalled && data && typeof data == 'object'){
+					dojo.mixin(self,data);
+				}
+				var idAttribute = jr.getIdAttribute(service);
+				Rest._index[this.__id = this.__clientId = 
+						service.servicePath + (this[idAttribute] || 
+							Math.random().toString(16).substring(2,14) + '@' + ((dojox.rpc.Client && dojox.rpc.Client.clientId) || "client"))] = this;
+				if(dojox.json.schema && properties){
+					dojox.json.schema.mustBeValid(dojox.json.schema.validate(this, service._schema));
+				} 
+				dirtyObjects.push({object:this, save: true});
+			};
+			return dojo.mixin(service._constructor, service._schema, {load:service});
+		},
+		fetch: function(absoluteId){
+			// summary:
+			//		Fetches a resource by an absolute path/id and returns a dojo.Deferred.
+			var serviceAndId = jr.getServiceAndId(absoluteId);
+			return this.byId(serviceAndId.service,serviceAndId.id);
+		},
+		getIdAttribute: function(service){
+			// summary:
+			//		Return the ids attribute used by this service (based on it's schema).
+			//		Defaults to "id", if not other id is defined
+			var schema = service._schema;
+			var idAttr;
+			if(schema){
+				if(!(idAttr = schema._idAttr)){
+					for(var i in schema.properties){
+						if(schema.properties[i].identity || (schema.properties[i].link == "self")){
+							schema._idAttr = idAttr = i;
+						}
+					}
+				}
+			}
+			return idAttr || 'id';
+		},
+		getServiceAndId: function(/*String*/absoluteId){
+			// summary:
+			//		Returns the REST service and the local id for the given absolute id. The result 
+			// 		is returned as an object with a service property and an id property
+			//	absoluteId:
+			//		This is the absolute id of the object
+			var serviceName = '';
+			
+			for(var service in jr.services){
+				if((absoluteId.substring(0, service.length) == service) && (service.length >= serviceName.length)){
+					serviceName = service;
+				}
+			}
+			if (serviceName){
+				return {service: jr.services[serviceName], id:absoluteId.substring(serviceName.length)};
+			}			
+			var parts = absoluteId.match(/^(.*\/)([^\/]*)$/);
+			return {service: new jr.serviceClass(parts[1], true), id:parts[2]};
+		},
+		services:{},
+		schemas:{},
+		registerService: function(/*Function*/ service, /*String*/ servicePath, /*Object?*/ schema){
+			//	summary:
+			//		Registers a service for as a JsonRest service, mapping it to a path and schema
+			//	service:
+			//		This is the service to register
+			//	servicePath:
+			//		This is the path that is used for all the ids for the objects returned by service
+			//	schema:
+			//		This is a JSON Schema object to associate with objects returned by this service
+			servicePath = service.servicePath = servicePath || service.servicePath;
+			service._schema = jr.schemas[servicePath] = schema || service._schema || {};
+			jr.services[servicePath] = service;
+		},
+		byId: function(service, id){
+			// if caching is allowed, we look in the cache for the result
+			var deferred, result = Rest._index[(service.servicePath || '') + id];
+			if(result && !result._loadObject){// cache hit
+				deferred = new dojo.Deferred();
+				deferred.callback(result);
+				return deferred;
+			}
+			return this.query(service, id);
+		},
+		query: function(service, id, args){
+			var deferred = service(id, args);
+			
+			deferred.addCallback(function(result){
+				if(result.nodeType && result.cloneNode){
+					// return immediately if it is an XML document
+					return result;
+				}				
+				return resolveJson(service, deferred, result, typeof id != 'string' || (args && (args.start || args.count)) ? undefined: id);
+			});
+			return deferred;			
+		},
+		_loader: function(callback){
+			// load a lazy object
+			var serviceAndId = jr.getServiceAndId(this.__id);
+			var self = this;
+			jr.query(serviceAndId.service, serviceAndId.id).addBoth(function(result){
+				// if they are the same this means an object was loaded, otherwise it 
+				// might be a primitive that was loaded or maybe an error
+				if(result == self){
+					// we can clear the flag, so it is a loaded object
+					delete result.$ref;
+					delete result._loadObject;
+				}else{
+					// it is probably a primitive value, we can't change the identity of an object to
+					//	the loaded value, so we will keep it lazy, but define the lazy loader to always
+					//	return the loaded value
+					self._loadObject = function(callback){
+						callback(result);
+					};
+				}
+				callback(result);
+			});
+		},
+		isDirty: function(item){
+			// summary
+			//		returns true if the item is marked as dirty or true if there are any dirty items
+			if(!item){
+				return !!dirtyObjects.length;
+			}
+			return item.__isDirty;
+		}
+		
+	};
 })();
-}
+
+
diff --git a/dojox/rpc/OfflineRest.js b/dojox/rpc/OfflineRest.js
index 8bcc172..29e4c23 100644
--- a/dojox/rpc/OfflineRest.js
+++ b/dojox/rpc/OfflineRest.js
@@ -1,203 +1,261 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.rpc.OfflineRest"]){
-dojo._hasResource["dojox.rpc.OfflineRest"]=true;
 dojo.provide("dojox.rpc.OfflineRest");
+
 dojo.require("dojox.data.ClientFilter");
 dojo.require("dojox.rpc.Rest");
 dojo.require("dojox.storage");
+
+// summary:
+// 		Makes the REST service be able to store changes in local
+// 		storage so it can be used offline automatically.
 (function(){
-var _1=dojox.rpc.Rest;
-var _2="dojox_rpc_OfflineRest";
-var _3;
-var _4=_1._index;
-dojox.storage.manager.addOnLoad(function(){
-_3=dojox.storage.manager.available;
-for(var i in _4){
-_5(_4[i],i);
-}
-});
-var _6;
-function _7(_8){
-return _8.replace(/[^0-9A-Za-z_]/g,"_");
-};
-function _5(_9,id){
-if(_3&&!_6&&(id||(_9&&_9.__id))){
-dojox.storage.put(_7(id||_9.__id),typeof _9=="object"?dojox.json.ref.toJson(_9):_9,function(){
-},_2);
-}
-};
-function _a(_b){
-return _b instanceof Error&&(_b.status==503||_b.status>12000||!_b.status);
-};
-function _c(){
-if(_3){
-var _d=dojox.storage.get("dirty",_2);
-if(_d){
-for(var _e in _d){
-_f(_e,_d);
-}
-}
-}
-};
-var _10;
-function _11(){
-_10.sendChanges();
-_10.downloadChanges();
-};
-var _12=setInterval(_11,15000);
-dojo.connect(document,"ononline",_11);
-_10=dojox.rpc.OfflineRest={turnOffAutoSync:function(){
-clearInterval(_12);
-},sync:_11,sendChanges:_c,downloadChanges:function(){
-},addStore:function(_13,_14){
-_10.stores.push(_13);
-_13.fetch({queryOptions:{cache:true},query:_14,onComplete:function(_15,_16){
-_13._localBaseResults=_15;
-_13._localBaseFetch=_16;
-}});
-}};
-_10.stores=[];
-var _17=_1._get;
-_1._get=function(_18,id){
-try{
-_c();
-if(window.navigator&&navigator.onLine===false){
-throw new Error();
-}
-var dfd=_17(_18,id);
-}
-catch(e){
-dfd=new dojo.Deferred();
-dfd.errback(e);
-}
-var _19=dojox.rpc._sync;
-dfd.addCallback(function(_1a){
-_5(_1a,_18._getRequest(id).url);
-return _1a;
-});
-dfd.addErrback(function(_1b){
-if(_3){
-if(_a(_1b)){
-var _1c={};
-var _1d=function(id,_1e){
-if(_1c[id]){
-return _1e;
-}
-var _1f=dojo.fromJson(dojox.storage.get(_7(id),_2))||_1e;
-_1c[id]=_1f;
-for(var i in _1f){
-var val=_1f[i];
-id=val&&val.$ref;
-if(id){
-if(id.substring&&id.substring(0,4)=="cid:"){
-id=id.substring(4);
-}
-_1f[i]=_1d(id,val);
-}
-}
-if(_1f instanceof Array){
-for(i=0;i<_1f.length;i++){
-if(_1f[i]===undefined){
-_1f.splice(i--,1);
-}
-}
-}
-return _1f;
-};
-_6=true;
-var _20=_1d(_18._getRequest(id).url);
-if(!_20){
-return _1b;
-}
-_6=false;
-return _20;
-}else{
-return _1b;
-}
-}else{
-if(_19){
-return new Error("Storage manager not loaded, can not continue");
-}
-dfd=new dojo.Deferred();
-dfd.addCallback(arguments.callee);
-dojox.storage.manager.addOnLoad(function(){
-dfd.callback();
-});
-return dfd;
-}
-});
-return dfd;
-};
-function _21(_22,_23,_24,_25,_26){
-if(_22=="delete"){
-dojox.storage.remove(_7(_23),_2);
-}else{
-dojox.storage.put(_7(_24),_25,function(){
-},_2);
-}
-var _27=_26&&_26._store;
-if(_27){
-_27.updateResultSet(_27._localBaseResults,_27._localBaseFetch);
-dojox.storage.put(_7(_26._getRequest(_27._localBaseFetch.query).url),dojox.json.ref.toJson(_27._localBaseResults),function(){
-},_2);
-}
-};
-dojo.addOnLoad(function(){
-dojo.connect(dojox.data,"restListener",function(_28){
-var _29=_28.channel;
-var _2a=_28.event.toLowerCase();
-var _2b=dojox.rpc.JsonRest&&dojox.rpc.JsonRest.getServiceAndId(_29).service;
-_21(_2a,_29,_2a=="post"?_29+_28.result.id:_29,dojo.toJson(_28.result),_2b);
-});
-});
-var _2c=_1._change;
-_1._change=function(_2d,_2e,id,_2f){
-if(!_3){
-return _2c.apply(this,arguments);
-}
-var _30=_2e._getRequest(id).url;
-_21(_2d,_30,dojox.rpc.JsonRest._contentId,_2f,_2e);
-var _31=dojox.storage.get("dirty",_2)||{};
-if(_2d=="put"||_2d=="delete"){
-var _32=_30;
-}else{
-_32=0;
-for(var i in _31){
-if(!isNaN(parseInt(i))){
-_32=i;
-}
-}
-_32++;
-}
-_31[_32]={method:_2d,id:_30,content:_2f};
-return _f(_32,_31);
-};
-function _f(_33,_34){
-var _35=_34[_33];
-var _36=dojox.rpc.JsonRest.getServiceAndId(_35.id);
-var _37=_2c(_35.method,_36.service,_36.id,_35.content);
-_34[_33]=_35;
-dojox.storage.put("dirty",_34,function(){
-},_2);
-_37.addBoth(function(_38){
-if(_a(_38)){
-return null;
-}
-var _39=dojox.storage.get("dirty",_2)||{};
-delete _39[_33];
-dojox.storage.put("dirty",_39,function(){
-},_2);
-return _38;
-});
-return _37;
-};
-dojo.connect(_4,"onLoad",_5);
-dojo.connect(_4,"onUpdate",_5);
+	var Rest = dojox.rpc.Rest;
+	var namespace = "dojox_rpc_OfflineRest";
+	var loaded;
+	var index = Rest._index;
+	dojox.storage.manager.addOnLoad(function(){
+		// now that we are loaded we need to save everything in the index
+		loaded = dojox.storage.manager.available;
+		for(var i in index){
+			saveObject(index[i], i);
+		}
+	});
+	var dontSave;
+	function getStorageKey(key){
+		// returns a key that is safe to use in storage
+		return key.replace(/[^0-9A-Za-z_]/g,'_');
+	}
+	function saveObject(object,id){
+		// save the object into local storage
+		
+		if(loaded && !dontSave && (id || (object && object.__id))){
+			dojox.storage.put(
+					getStorageKey(id||object.__id),
+					typeof object=='object'?dojox.json.ref.toJson(object):object, // makeshift technique to determine if the object is json object or not
+					function(){},
+					namespace);
+		}
+	}
+	function isNetworkError(error){
+		//	determine if the error was a network error and should be saved offline
+		// 	or if it was a server error and not a result of offline-ness
+		return error instanceof Error && (error.status == 503 || error.status > 12000 ||  !error.status); // TODO: Make the right error determination
+	}
+	function sendChanges(){
+		// periodical try to save our dirty data
+		if(loaded){
+			var dirty = dojox.storage.get("dirty",namespace);
+			if(dirty){
+				for (var dirtyId in dirty){
+					commitDirty(dirtyId,dirty);
+				}
+			}
+		}
+	}
+	var OfflineRest;
+	function sync(){
+		OfflineRest.sendChanges();
+		OfflineRest.downloadChanges();
+	} 
+	var syncId = setInterval(sync,15000);
+	dojo.connect(document, "ononline", sync);
+	OfflineRest = dojox.rpc.OfflineRest = {
+		turnOffAutoSync: function(){
+			clearInterval(syncId);
+		},
+		sync: sync,
+		sendChanges: sendChanges,
+		downloadChanges: function(){
+			
+		},
+		addStore: function(/*data-store*/store,/*query?*/baseQuery){
+			// summary:
+			//		Adds a store to the monitored store for local storage
+			//	store:
+			//		Store to add
+			//	baseQuery:
+			//		This is the base query to should be used to load the items for
+			//		the store. Generally you want to load all the items that should be
+			//		available when offline.
+			OfflineRest.stores.push(store);
+			store.fetch({queryOptions:{cache:true},query:baseQuery,onComplete:function(results,args){
+				store._localBaseResults = results;
+				store._localBaseFetch = args;
+			}});
+						
+		}
+	};
+	OfflineRest.stores = [];
+	var defaultGet = Rest._get;
+	Rest._get = function(service, id){
+		// We specifically do NOT want the paging information to be used by the default handler,
+		// this is because online apps want to minimize the data transfer,
+		// but an offline app wants the opposite, as much data as possible transferred to
+		// the client side
+		try{
+			// if we are reloading the application with local dirty data in an online environment
+			//	we want to make sure we save the changes first, so that we get up-to-date
+			//	information from the server
+			sendChanges();
+			if(window.navigator && navigator.onLine===false){
+				// we force an error if we are offline in firefox, otherwise it will silently load it from the cache
+				throw new Error();
+			}
+			var dfd = defaultGet(service, id);
+		}catch(e){
+			dfd = new dojo.Deferred();
+			dfd.errback(e);
+		} 
+		var sync = dojox.rpc._sync;
+		dfd.addCallback(function(result){
+			saveObject(result, service._getRequest(id).url);
+			return result;			
+		});
+		dfd.addErrback(function(error){
+			if(loaded){
+				// if the storage is loaded, we can go ahead and get the object out of storage
+				if(isNetworkError(error)){
+					var loadedObjects = {};
+					// network error, load from local storage
+					var byId = function(id,backup){
+						if(loadedObjects[id]){
+							return backup;
+						}
+						var result = dojo.fromJson(dojox.storage.get(getStorageKey(id),namespace)) || backup;
+						
+						loadedObjects[id] = result;
+						for(var i in result){
+							var val = result[i]; // resolve references if we can
+							id = val && val.$ref;
+							if (id){
+								if(id.substring && id.substring(0,4) == "cid:"){
+									// strip the cid scheme, we should be able to resolve it locally
+									id = id.substring(4);
+								}
+								result[i] = byId(id,val);
+							}
+						}
+						if (result instanceof Array){
+							//remove any deleted items
+							for (i = 0;i<result.length;i++){
+								if (result[i]===undefined){
+									result.splice(i--,1);
+								}
+							}
+						}
+						return result;
+					};
+					dontSave = true; // we don't want to be resaving objects when loading from local storage
+					//TODO: Should this reuse something from dojox.rpc.Rest
+					var result = byId(service._getRequest(id).url);
+					
+					if(!result){// if it is not found we have to just return the error
+						return error;
+					}
+					dontSave = false;
+					return result;
+				}
+				else{
+					return error; // server error, let the error propagate
+				}
+			}
+			else{
+				if(sync){
+					return new Error("Storage manager not loaded, can not continue");
+				}
+				// we are not loaded, so we need to defer until we are loaded
+				dfd = new dojo.Deferred();
+				dfd.addCallback(arguments.callee);
+				dojox.storage.manager.addOnLoad(function(){
+					dfd.callback();
+				});
+				return dfd;
+			}
+		});
+		return dfd;
+	};
+	function changeOccurred(method, absoluteId, contentId, serializedContent, service){
+		if(method=='delete'){
+			dojox.storage.remove(getStorageKey(absoluteId),namespace);
+		}		
+		else{
+			// both put and post should store the actual object
+			dojox.storage.put(getStorageKey(contentId), serializedContent, function(){
+			},namespace);
+		}
+		var store = service && service._store;
+		// record all the updated queries
+		if(store){
+			store.updateResultSet(store._localBaseResults, store._localBaseFetch);
+			dojox.storage.put(getStorageKey(service._getRequest(store._localBaseFetch.query).url),dojox.json.ref.toJson(store._localBaseResults),function(){
+				},namespace);
+			
+		}
+		
+	}
+	dojo.addOnLoad(function(){
+		dojo.connect(dojox.data, "restListener", function(message){
+			var channel = message.channel;
+			var method = message.event.toLowerCase();
+			var service = dojox.rpc.JsonRest && dojox.rpc.JsonRest.getServiceAndId(channel).service;
+			changeOccurred(
+				method, 
+				channel,
+				method == "post" ? channel + message.result.id : channel,
+				dojo.toJson(message.result),
+				service
+			);
+			
+		});
+	});
+	//FIXME: Should we make changes after a commit to see if the server rejected the change
+	// or should we come up with a revert mechanism? 
+	var defaultChange = Rest._change;
+	Rest._change = function(method,service,id,serializedContent){
+		if(!loaded){
+			return defaultChange.apply(this,arguments);
+		}
+		var absoluteId = service._getRequest(id).url;
+		changeOccurred(method, absoluteId, dojox.rpc.JsonRest._contentId, serializedContent, service);
+		var dirty = dojox.storage.get("dirty",namespace) || {};
+		if (method=='put' || method=='delete'){
+			// these supersede so we can overwrite anything using this id
+			var dirtyId = absoluteId;
+		}
+		else{
+			dirtyId = 0;
+			for (var i in dirty){
+				if(!isNaN(parseInt(i))){
+					dirtyId = i;
+				}
+			} // get the last dirtyId to make a unique id for non-idempotent methods
+			dirtyId++;
+		}
+		dirty[dirtyId] = {method:method,id:absoluteId,content:serializedContent};
+		return commitDirty(dirtyId,dirty);
+	};
+	function commitDirty(dirtyId, dirty){
+		var dirtyItem = dirty[dirtyId];
+		var serviceAndId = dojox.rpc.JsonRest.getServiceAndId(dirtyItem.id);
+		var deferred = defaultChange(dirtyItem.method,serviceAndId.service,serviceAndId.id,dirtyItem.content);
+		// add it to our list of dirty objects		
+		dirty[dirtyId] = dirtyItem;
+		dojox.storage.put("dirty",dirty,function(){},namespace);
+		deferred.addBoth(function(result){
+			if (isNetworkError(result)){
+				// if a network error (offlineness) was the problem, we leave it 
+				// dirty, and return to indicate successfulness
+				return null;
+			}
+			// it was successful or the server rejected it, we remove it from the dirty list 
+			var dirty = dojox.storage.get("dirty",namespace) || {};
+			delete dirty[dirtyId];
+			dojox.storage.put("dirty",dirty,function(){},namespace);
+			return result;
+		});
+		return deferred;
+	}
+		
+	dojo.connect(index,"onLoad",saveObject);
+	dojo.connect(index,"onUpdate",saveObject);
+	
 })();
-}
diff --git a/dojox/rpc/ProxiedPath.js b/dojox/rpc/ProxiedPath.js
index 5ef291a..9450442 100644
--- a/dojox/rpc/ProxiedPath.js
+++ b/dojox/rpc/ProxiedPath.js
@@ -1,30 +1,27 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.rpc.ProxiedPath"]){
-dojo._hasResource["dojox.rpc.ProxiedPath"]=true;
 dojo.provide("dojox.rpc.ProxiedPath");
 dojo.require("dojox.rpc.Service");
-dojox.rpc.envelopeRegistry.register("PROXIED-PATH",function(_1){
-return _1=="PROXIED-PATH";
-},{serialize:function(_2,_3,_4){
-var i;
-var _5=dojox.rpc.getTarget(_2,_3);
-if(dojo.isArray(_4)){
-for(i=0;i<_4.length;i++){
-_5+="/"+(_4[i]==null?"":_4[i]);
-}
-}else{
-for(i in _4){
-_5+="/"+i+"/"+_4[i];
-}
-}
-return {data:"",target:(_3.proxyUrl||_2.proxyUrl)+"?url="+encodeURIComponent(_5)};
-},deserialize:function(_6){
-return _6;
-}});
-}
+
+dojox.rpc.envelopeRegistry.register(
+	"PROXIED-PATH",function(str){return str == "PROXIED-PATH"},{
+		serialize:function(smd, method, data){
+			var i;
+			var target = dojox.rpc.getTarget(smd, method);
+			if(dojo.isArray(data)){
+				for(i = 0; i < data.length;i++){
+					target += '/' + (data[i] == null ? "" : data[i]);
+				}
+			}else{
+				for(i in data){
+					target += '/' + i + '/' + data[i];
+				}
+			}
+			return {
+				data:'',
+				target: (method.proxyUrl || smd.proxyUrl) + "?url=" + encodeURIComponent(target)
+			};
+		},
+		deserialize:function(results){
+			return results;
+		}
+	}
+);
diff --git a/dojox/rpc/Rest.js b/dojox/rpc/Rest.js
index 6773711..24d68c1 100644
--- a/dojox/rpc/Rest.js
+++ b/dojox/rpc/Rest.js
@@ -1,87 +1,134 @@
-/*
-	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
-*/
+dojo.provide("dojox.rpc.Rest"); 
+// Note: This doesn't require dojox.rpc.Service, and if you want it you must require it 
+// yourself, and you must load it prior to dojox.rpc.Rest.
 
-
-if(!dojo._hasResource["dojox.rpc.Rest"]){
-dojo._hasResource["dojox.rpc.Rest"]=true;
-dojo.provide("dojox.rpc.Rest");
+// summary:
+// 		This provides a HTTP REST service with full range REST verbs include PUT,POST, and DELETE.
+// description:
+// 		A normal GET query is done by using the service directly:
+// 		| var restService = dojox.rpc.Rest("Project");
+// 		| restService("4");
+//		This will do a GET for the URL "/Project/4".
+//		| restService.put("4","new content");
+//		This will do a PUT to the URL "/Project/4" with the content of "new content".
+//		You can also use the SMD service to generate a REST service:
+// 		| var services = dojox.rpc.Service({services: {myRestService: {transport: "REST",...
+// 		| services.myRestService("parameters");
+//
+// 		The modifying methods can be called as sub-methods of the rest service method like:
+//  	| services.myRestService.put("parameters","data to put in resource");
+//  	| services.myRestService.post("parameters","data to post to the resource");
+//  	| services.myRestService['delete']("parameters");
 (function(){
-if(dojox.rpc&&dojox.rpc.transportRegistry){
-dojox.rpc.transportRegistry.register("REST",function(_1){
-return _1=="REST";
-},{getExecutor:function(_2,_3,_4){
-return new dojox.rpc.Rest(_3.name,(_3.contentType||_4._smd.contentType||"").match(/json|javascript/),null,function(id,_5){
-var _6=_4._getRequest(_3,[id]);
-_6.url=_6.target+(_6.data?"?"+_6.data:"");
-return _6;
-});
-}});
-}
-var _7;
-function _8(_9,_a,_b,id){
-_9.addCallback(function(_c){
-if(_9.ioArgs.xhr&&_b){
-_b=_9.ioArgs.xhr.getResponseHeader("Content-Range");
-_9.fullLength=_b&&(_b=_b.match(/\/(.*)/))&&parseInt(_b[1]);
-}
-return _c;
-});
-return _9;
-};
-_7=dojox.rpc.Rest=function(_d,_e,_f,_10){
-var _11;
-_11=function(id,_12){
-return _7._get(_11,id,_12);
-};
-_11.isJson=_e;
-_11._schema=_f;
-_11.cache={serialize:_e?((dojox.json&&dojox.json.ref)||dojo).toJson:function(_13){
-return _13;
-}};
-_11._getRequest=_10||function(id,_14){
-if(dojo.isObject(id)){
-id=dojo.objectToQuery(id);
-id=id?"?"+id:"";
-}
-if(_14&&_14.sort&&!_14.queryStr){
-id+=(id?"&":"?")+"sort(";
-for(var i=0;i<_14.sort.length;i++){
-var _15=_14.sort[i];
-id+=(i>0?",":"")+(_15.descending?"-":"+")+encodeURIComponent(_15.attribute);
-}
-id+=")";
-}
-var _16={url:_d+(id==null?"":id),handleAs:_e?"json":"text",contentType:_e?"application/json":"text/plain",sync:dojox.rpc._sync,headers:{Accept:_e?"application/json,application/javascript":"*/*"}};
-if(_14&&(_14.start>=0||_14.count>=0)){
-_16.headers.Range="items="+(_14.start||"0")+"-"+((_14.count&&_14.count!=Infinity&&(_14.count+(_14.start||0)-1))||"");
-}
-dojox.rpc._sync=false;
-return _16;
-};
-function _17(_18){
-_11[_18]=function(id,_19){
-return _7._change(_18,_11,id,_19);
-};
-};
-_17("put");
-_17("post");
-_17("delete");
-_11.servicePath=_d;
-return _11;
-};
-_7._index={};
-_7._timeStamps={};
-_7._change=function(_1a,_1b,id,_1c){
-var _1d=_1b._getRequest(id);
-_1d[_1a+"Data"]=_1c;
-return _8(dojo.xhr(_1a.toUpperCase(),_1d,true),_1b);
-};
-_7._get=function(_1e,id,_1f){
-_1f=_1f||{};
-return _8(dojo.xhrGet(_1e._getRequest(id,_1f)),_1e,(_1f.start>=0||_1f.count>=0),id);
-};
+	if(dojox.rpc && dojox.rpc.transportRegistry){
+		// register it as an RPC service if the registry is available
+		dojox.rpc.transportRegistry.register(
+			"REST",
+			function(str){return str == "REST";},
+			{
+				getExecutor : function(func,method,svc){
+					return new dojox.rpc.Rest(
+						method.name,
+						(method.contentType||svc._smd.contentType||"").match(/json|javascript/), // isJson
+						null,
+						function(id, args){
+							var request = svc._getRequest(method,[id]);
+							request.url= request.target + (request.data ? '?'+  request.data : '');
+							return request;
+						}
+					);
+				}
+			}
+		);
+	}
+	var drr;
+
+	function index(deferred, service, range, id){
+		deferred.addCallback(function(result){
+			if(deferred.ioArgs.xhr && range){
+					// try to record the total number of items from the range header
+					range = deferred.ioArgs.xhr.getResponseHeader("Content-Range");
+					deferred.fullLength = range && (range=range.match(/\/(.*)/)) && parseInt(range[1]);
+			}
+			return result;
+		});
+		return deferred;
+	}
+	drr = dojox.rpc.Rest = function(/*String*/path, /*Boolean?*/isJson, /*Object?*/schema, /*Function?*/getRequest){
+		// summary:
+		//		Creates a REST service using the provided path.
+		var service;
+		// it should be in the form /Table/
+		service = function(id, args){
+			return drr._get(service, id, args);
+		};
+		service.isJson = isJson;
+		service._schema = schema;
+		// cache:
+		//		This is an object that provides indexing service
+		// 		This can be overriden to take advantage of more complex referencing/indexing
+		// 		schemes
+		service.cache = {
+			serialize: isJson ? ((dojox.json && dojox.json.ref) || dojo).toJson : function(result){
+				return result;
+			}
+		};
+		// the default XHR args creator:
+		service._getRequest = getRequest || function(id, args){
+			if(dojo.isObject(id)){
+				id = dojo.objectToQuery(id);
+				id = id ? "?" + id: "";
+			}
+			if(args && args.sort && !args.queryStr){
+				id += (id ? "&" : "?") + "sort("
+				for(var i = 0; i<args.sort.length; i++){
+					var sort = args.sort[i];
+					id += (i > 0 ? "," : "") + (sort.descending ? '-' : '+') + encodeURIComponent(sort.attribute); 
+				}
+				id += ")";
+			}
+			var request = {
+				url: path + (id == null ? "" : id),
+				handleAs: isJson ? 'json' : 'text', 
+				contentType: isJson ? 'application/json' : 'text/plain',
+				sync: dojox.rpc._sync,
+				headers: {
+					Accept: isJson ? 'application/json,application/javascript' : '*/*'
+				}
+			};
+			if(args && (args.start >= 0 || args.count >= 0)){
+				request.headers.Range = "items=" + (args.start || '0') + '-' + ((args.count && args.count != Infinity && (args.count + (args.start || 0) - 1)) || '');
+			}
+			dojox.rpc._sync = false;
+			return request;
+		};
+		// each calls the event handler
+		function makeRest(name){
+			service[name] = function(id,content){
+				return drr._change(name,service,id,content); // the last parameter is to let the OfflineRest know where to store the item
+			};
+		}
+		makeRest('put');
+		makeRest('post');
+		makeRest('delete');
+		// record the REST services for later lookup
+		service.servicePath = path;
+		return service;
+	};
+
+	drr._index={};// the map of all indexed objects that have gone through REST processing
+	drr._timeStamps={};
+	// these do the actual requests
+	drr._change = function(method,service,id,content){
+		// this is called to actually do the put, post, and delete
+		var request = service._getRequest(id);
+		request[method+"Data"] = content;
+		return index(dojo.xhr(method.toUpperCase(),request,true),service);
+	};
+
+	drr._get= function(service,id, args){
+		args = args || {};
+		// this is called to actually do the get
+		return index(dojo.xhrGet(service._getRequest(id, args)), service, (args.start >= 0 || args.count >= 0), id);
+	};
 })();
-}
diff --git a/dojox/rpc/SMDLibrary/google.smd b/dojox/rpc/SMDLibrary/google.smd
old mode 100644
new mode 100755
diff --git a/dojox/rpc/SMDLibrary/wikipedia.smd b/dojox/rpc/SMDLibrary/wikipedia.smd
index ffc94a4..d91b2c3 100644
--- a/dojox/rpc/SMDLibrary/wikipedia.smd
+++ b/dojox/rpc/SMDLibrary/wikipedia.smd
@@ -1,49 +1,49 @@
-{
-	"SMDVersion": "2.0",
-	"id": "http://en.wikipedia.org/w/api.php",
-	"description": "Wikipedia API",
-
-	transport: "JSONP",
-	envelope: "URL",
-	additionalParameters: true,
-	target: "http://en.wikipedia.org/w/api.php",
-	parameters: [
-		{ name: "format", optional: false, "default": "json" }
-	],
-
-	services: {
-
-		/*
-		 * This is a very very basic spec that just gives us a free-form API
-		 * endpoint to talk to. See http://en.wikipedia.org/w/api.php for
-		 * details on what parameters to supply and what sort of data you
-		 * should expect to see. Note that returned JSON is often somewhat
-		 * ... interesting ...:
-		 *
-		 * {
-		 *     "parse": {
-		 *         "text": {
-		 *             "*": "<table ..."
-		 *         },
-		 *         "langlinks": [
-		 *             {
-		 *                 "lang": "simple",
-		 *                 "*": ""
-		 *             },
-		 *             // etc.
-		 *         ]
-		 *     }
-		 * }
-		 * 
-		 * Not sure why we'd ever want an element to be named "*", but that's
-		 * how it is. So take care.
-		 *
-		 */
-		query: {
-			parameters: [
-				{ name: "action", type: "string", "default": "parse" }
-			]
-		}
-
-	}
-}
+{
+	"SMDVersion": "2.0",
+	"id": "http://en.wikipedia.org/w/api.php",
+	"description": "Wikipedia API",
+
+	transport: "JSONP",
+	envelope: "URL",
+	additionalParameters: true,
+	target: "http://en.wikipedia.org/w/api.php",
+	parameters: [
+		{ name: "format", optional: false, "default": "json" }
+	],
+
+	services: {
+
+		/*
+		 * This is a very very basic spec that just gives us a free-form API
+		 * endpoint to talk to. See http://en.wikipedia.org/w/api.php for
+		 * details on what parameters to supply and what sort of data you
+		 * should expect to see. Note that returned JSON is often somewhat
+		 * ... interesting ...:
+		 *
+		 * {
+		 *     "parse": {
+		 *         "text": {
+		 *             "*": "<table ..."
+		 *         },
+		 *         "langlinks": [
+		 *             {
+		 *                 "lang": "simple",
+		 *                 "*": ""
+		 *             },
+		 *             // etc.
+		 *         ]
+		 *     }
+		 * }
+		 * 
+		 * Not sure why we'd ever want an element to be named "*", but that's
+		 * how it is. So take care.
+		 *
+		 */
+		query: {
+			parameters: [
+				{ name: "action", type: "string", "default": "parse" }
+			]
+		}
+
+	}
+}
diff --git a/dojox/rpc/SMDLibrary/yahoo.smd b/dojox/rpc/SMDLibrary/yahoo.smd
old mode 100644
new mode 100755
diff --git a/dojox/rpc/Service.js b/dojox/rpc/Service.js
index a1f5b2e..911dbe9 100644
--- a/dojox/rpc/Service.js
+++ b/dojox/rpc/Service.js
@@ -1,217 +1,319 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.rpc.Service"]){
-dojo._hasResource["dojox.rpc.Service"]=true;
 dojo.provide("dojox.rpc.Service");
+
 dojo.require("dojo.AdapterRegistry");
-dojo.declare("dojox.rpc.Service",null,{constructor:function(_1,_2){
-var _3;
-var _4=this;
-function _5(_6){
-_6._baseUrl=new dojo._Url((dojo.isBrowser?location.href:dojo.config.baseUrl),_3||".")+"";
-_4._smd=_6;
-for(var _7 in _4._smd.services){
-var _8=_7.split(".");
-var _9=_4;
-for(var i=0;i<_8.length-1;i++){
-_9=_9[_8[i]]||(_9[_8[i]]={});
-}
-_9[_8[_8.length-1]]=_4._generateService(_7,_4._smd.services[_7]);
-}
-};
-if(_1){
-if((dojo.isString(_1))||(_1 instanceof dojo._Url)){
-if(_1 instanceof dojo._Url){
-_3=_1+"";
-}else{
-_3=_1;
-}
-var _a=dojo._getText(_3);
-if(!_a){
-throw new Error("Unable to load SMD from "+_1);
-}else{
-_5(dojo.fromJson(_a));
-}
-}else{
-_5(_1);
-}
-}
-this._options=(_2?_2:{});
-this._requestId=0;
-},_generateService:function(_b,_c){
-if(this[_c]){
-throw new Error("WARNING: "+_b+" already exists for service. Unable to generate function");
-}
-_c.name=_b;
-var _d=dojo.hitch(this,"_executeMethod",_c);
-var _e=dojox.rpc.transportRegistry.match(_c.transport||this._smd.transport);
-if(_e.getExecutor){
-_d=_e.getExecutor(_d,_c,this);
-}
-var _f=_c.returns||(_c._schema={});
-var _10="/"+_b+"/";
-_f._service=_d;
-_d.servicePath=_10;
-_d._schema=_f;
-_d.id=dojox.rpc.Service._nextId++;
-return _d;
-},_getRequest:function(_11,_12){
-var smd=this._smd;
-var _13=dojox.rpc.envelopeRegistry.match(_11.envelope||smd.envelope||"NONE");
-var _14=(_11.parameters||[]).concat(smd.parameters||[]);
-if(_13.namedParams){
-if((_12.length==1)&&dojo.isObject(_12[0])){
-_12=_12[0];
-}else{
-var _15={};
-for(var i=0;i<_11.parameters.length;i++){
-if(typeof _12[i]!="undefined"||!_11.parameters[i].optional){
-_15[_11.parameters[i].name]=_12[i];
-}
-}
-_12=_15;
-}
-if(_11.strictParameters||smd.strictParameters){
-for(i in _12){
-var _16=false;
-for(var j=0;j<_14.length;j++){
-if(_14[i].name==i){
-_16=true;
-}
-}
-if(!_16){
-delete _12[i];
-}
-}
-}
-for(i=0;i<_14.length;i++){
-var _17=_14[i];
-if(!_17.optional&&_17.name&&!_12[_17.name]){
-if(_17["default"]){
-_12[_17.name]=_17["default"];
-}else{
-if(!(_17.name in _12)){
-throw new Error("Required parameter "+_17.name+" was omitted");
-}
-}
-}
-}
-}else{
-if(_14&&_14[0]&&_14[0].name&&(_12.length==1)&&dojo.isObject(_12[0])){
-if(_13.namedParams===false){
-_12=dojox.rpc.toOrdered(_14,_12);
-}else{
-_12=_12[0];
-}
-}
-}
-if(dojo.isObject(this._options)){
-_12=dojo.mixin(_12,this._options);
-}
-var _18=_11._schema||_11.returns;
-var _19=_13.serialize.apply(this,[smd,_11,_12]);
-_19._envDef=_13;
-var _1a=(_11.contentType||smd.contentType||_19.contentType);
-return dojo.mixin(_19,{sync:dojox.rpc._sync,contentType:_1a,headers:{},target:_19.target||dojox.rpc.getTarget(smd,_11),transport:_11.transport||smd.transport||_19.transport,envelope:_11.envelope||smd.envelope||_19.envelope,timeout:_11.timeout||smd.timeout,callbackParamName:_11.callbackParamName||smd.callbackParamName,schema:_18,handleAs:_19.handleAs||"auto",preventCache:_11.preventCache||smd.preventCache,frameDoc:this._options.frameDoc||undefined});
-},_executeMethod:function(_1b){
-var _1c=[];
-var i;
-for(i=1;i<arguments.length;i++){
-_1c.push(arguments[i]);
-}
-var _1d=this._getRequest(_1b,_1c);
-var _1e=dojox.rpc.transportRegistry.match(_1d.transport).fire(_1d);
-_1e.addBoth(function(_1f){
-return _1d._envDef.deserialize.call(this,_1f);
+
+dojo.declare("dojox.rpc.Service", null, {
+	constructor: function(smd, options){
+		// summary:
+		//		Take a string as a url to retrieve an smd or an object that is an smd or partial smd to use
+		//		as a definition for the service
+		//
+		//	smd: object
+		//		Takes a number of properties as kwArgs for defining the service.  It also
+		//		accepts a string.  When passed a string, it is treated as a url from
+		//		which it should synchronously retrieve an smd file.  Otherwise it is a kwArgs
+		//		object.  It accepts serviceUrl, to manually define a url for the rpc service
+		//		allowing the rpc system to be used without an smd definition. strictArgChecks
+		//		forces the system to verify that the # of arguments provided in a call
+		//		matches those defined in the smd.  smdString allows a developer to pass
+		//		a jsonString directly, which will be converted into an object or alternatively
+		//		smdObject is accepts an smdObject directly.
+		//
+		//	description:
+		//		dojox.rpc.Service must be loaded prior to any plugin services like dojox.rpc.Rest
+		// 		dojox.rpc.JsonRpc in order for them to register themselves, otherwise you get
+		// 		a "No match found" error.  
+		var url;
+		var self = this;
+		function processSmd(smd){
+			smd._baseUrl = new dojo._Url((dojo.isBrowser ? location.href : dojo.config.baseUrl) ,url || '.') + '';
+			self._smd = smd;
+
+			//generate the methods
+ 			for(var serviceName in self._smd.services){
+				var pieces = serviceName.split("."); // handle "namespaced" services by breaking apart by .
+				var current = self;
+				for(var i=0; i< pieces.length-1; i++){
+					// create or reuse each object as we go down the chain
+					current = current[pieces[i]] || (current[pieces[i]] = {});
+				}
+				current[pieces[pieces.length-1]]=	self._generateService(serviceName, self._smd.services[serviceName]);
+ 			}
+		}
+		if(smd){
+			//ifthe arg is a string, we assume it is a url to retrieve an smd definition from
+			if( (dojo.isString(smd)) || (smd instanceof dojo._Url)){
+				if(smd instanceof dojo._Url){
+					url = smd + "";
+				}else{
+					url = smd;
+				}
+
+				var text = dojo._getText(url);
+				if(!text){
+					throw new Error("Unable to load SMD from " + smd);
+				}else{
+					processSmd(dojo.fromJson(text));
+				}
+			}else{
+				processSmd(smd);
+			}
+		}
+
+		this._options = (options ? options : {});
+		this._requestId = 0;
+	},
+
+	_generateService: function(serviceName, method){
+		if(this[method]){
+			throw new Error("WARNING: "+ serviceName+ " already exists for service. Unable to generate function");
+		}
+		method.name = serviceName;
+		var func = dojo.hitch(this, "_executeMethod",method);
+		var transport = dojox.rpc.transportRegistry.match(method.transport || this._smd.transport);
+		if(transport.getExecutor){
+			func = transport.getExecutor(func,method,this);
+		}
+		var schema = method.returns || (method._schema = {}); // define the schema
+		var servicePath = '/' + serviceName +'/';
+		// schemas are minimally used to track the id prefixes for the different services
+		schema._service = func;
+		func.servicePath = servicePath;
+		func._schema = schema;
+		func.id = dojox.rpc.Service._nextId++;
+		return func;
+	},
+	_getRequest: function(method,args){
+		var smd = this._smd;
+		var envDef = dojox.rpc.envelopeRegistry.match(method.envelope || smd.envelope || "NONE");
+		var parameters = (method.parameters || []).concat(smd.parameters || []);
+		if(envDef.namedParams){
+			// the serializer is expecting named params
+			if((args.length==1) && dojo.isObject(args[0])){
+				// looks like we have what we want
+				args = args[0];
+			}else{
+				// they provided ordered, must convert
+				var data={};
+				for(var i=0;i<method.parameters.length;i++){
+					if(typeof args[i] != "undefined" || !method.parameters[i].optional){
+						data[method.parameters[i].name]=args[i];
+					}
+				}
+				args = data;
+			}
+			if(method.strictParameters||smd.strictParameters){
+				//remove any properties that were not defined
+				for(i in args){
+					var found=false;
+					for(var j=0; j<parameters.length;j++){
+						if(parameters[i].name==i){ found=true; }
+					}
+					if(!found){
+						delete args[i];
+					}
+				}
+				
+			}
+			// setting default values
+			for(i=0; i< parameters.length; i++){
+				var param = parameters[i];
+				if(!param.optional && param.name && !args[param.name]){
+					if(param["default"]){
+						args[param.name] = param["default"];
+					}else if(!(param.name in args)){
+						throw new Error("Required parameter " + param.name + " was omitted");
+					}
+				}
+			}
+		}else if(parameters && parameters[0] && parameters[0].name && (args.length==1) && dojo.isObject(args[0])){
+			// looks like named params, we will convert
+			if(envDef.namedParams === false){
+				// the serializer is expecting ordered params, must be ordered
+				args = dojox.rpc.toOrdered(parameters, args);
+			}else{
+				// named is ok
+				args = args[0];
+			}
+		}
+		
+		if(dojo.isObject(this._options)){
+			args = dojo.mixin(args, this._options);
+		}
+		
+		var schema = method._schema || method.returns; // serialize with the right schema for the context;
+		var request = envDef.serialize.apply(this, [smd, method, args]);
+		request._envDef = envDef;// save this for executeMethod
+		var contentType = (method.contentType || smd.contentType || request.contentType);
+
+		// this allows to mandate synchronous behavior from elsewhere when necessary, this may need to be changed to be one-shot in FF3 new sync handling model
+		return dojo.mixin(request, {
+			sync: dojox.rpc._sync,
+			contentType: contentType,
+			headers: {},
+			target: request.target || dojox.rpc.getTarget(smd, method),
+			transport: method.transport || smd.transport || request.transport,
+			envelope: method.envelope || smd.envelope || request.envelope,
+			timeout: method.timeout || smd.timeout,
+			callbackParamName: method.callbackParamName || smd.callbackParamName,
+			schema: schema,
+			handleAs: request.handleAs || "auto",
+			preventCache: method.preventCache || smd.preventCache,
+			frameDoc: this._options.frameDoc || undefined
+		});
+	},
+	_executeMethod: function(method){
+		var args = [];
+		var i;
+		for(i=1; i< arguments.length; i++){
+			args.push(arguments[i]);
+		}
+		var request = this._getRequest(method,args);
+		var deferred = dojox.rpc.transportRegistry.match(request.transport).fire(request);
+		
+		deferred.addBoth(function(results){
+			return request._envDef.deserialize.call(this,results);
+		});
+		return deferred;
+	}
 });
-return _1e;
-}});
-dojox.rpc.getTarget=function(smd,_20){
-var _21=smd._baseUrl;
-if(smd.target){
-_21=new dojo._Url(_21,smd.target)+"";
-}
-if(_20.target){
-_21=new dojo._Url(_21,_20.target)+"";
-}
-return _21;
+
+dojox.rpc.getTarget = function(smd, method){
+	var dest=smd._baseUrl;
+	if(smd.target){
+		dest = new dojo._Url(dest,smd.target) + '';
+	}
+	if(method.target){
+		dest = new dojo._Url(dest,method.target) + '';
+	}
+	return dest;
 };
-dojox.rpc.toOrdered=function(_22,_23){
-if(dojo.isArray(_23)){
-return _23;
-}
-var _24=[];
-for(var i=0;i<_22.length;i++){
-_24.push(_23[_22[i].name]);
-}
-return _24;
+
+dojox.rpc.toOrdered=function(parameters, args){
+	if(dojo.isArray(args)){ return args; }
+	var data=[];
+	for(var i=0;i<parameters.length;i++){
+		data.push(args[parameters[i].name]);
+	}
+	return data;
 };
-dojox.rpc.transportRegistry=new dojo.AdapterRegistry(true);
-dojox.rpc.envelopeRegistry=new dojo.AdapterRegistry(true);
-dojox.rpc.envelopeRegistry.register("URL",function(str){
-return str=="URL";
-},{serialize:function(smd,_25,_26){
-var d=dojo.objectToQuery(_26);
-return {data:d,transport:"POST"};
-},deserialize:function(_27){
-return _27;
-},namedParams:true});
-dojox.rpc.envelopeRegistry.register("JSON",function(str){
-return str=="JSON";
-},{serialize:function(smd,_28,_29){
-var d=dojo.toJson(_29);
-return {data:d,handleAs:"json",contentType:"application/json"};
-},deserialize:function(_2a){
-return _2a;
-}});
-dojox.rpc.envelopeRegistry.register("PATH",function(str){
-return str=="PATH";
-},{serialize:function(smd,_2b,_2c){
-var i;
-var _2d=dojox.rpc.getTarget(smd,_2b);
-if(dojo.isArray(_2c)){
-for(i=0;i<_2c.length;i++){
-_2d+="/"+_2c[i];
-}
-}else{
-for(i in _2c){
-_2d+="/"+i+"/"+_2c[i];
-}
-}
-return {data:"",target:_2d};
-},deserialize:function(_2e){
-return _2e;
-}});
-dojox.rpc.transportRegistry.register("POST",function(str){
-return str=="POST";
-},{fire:function(r){
-r.url=r.target;
-r.postData=r.data;
-return dojo.rawXhrPost(r);
-}});
-dojox.rpc.transportRegistry.register("GET",function(str){
-return str=="GET";
-},{fire:function(r){
-r.url=r.target+(r.data?"?"+r.data:"");
-return dojo.xhrGet(r);
-}});
-dojox.rpc.transportRegistry.register("JSONP",function(str){
-return str=="JSONP";
-},{fire:function(r){
-r.url=r.target+((r.target.indexOf("?")==-1)?"?":"&")+r.data;
-r.callbackParamName=r.callbackParamName||"callback";
-return dojo.io.script.get(r);
-}});
-dojox.rpc.Service._nextId=1;
-dojo._contentHandlers.auto=function(xhr){
-var _2f=dojo._contentHandlers;
-var _30=xhr.getResponseHeader("Content-Type");
-var _31=!_30?_2f.text(xhr):_30.match(/\/.*json/)?_2f.json(xhr):_30.match(/\/javascript/)?_2f.javascript(xhr):_30.match(/\/xml/)?_2f.xml(xhr):_2f.text(xhr);
-return _31;
+
+dojox.rpc.transportRegistry = new dojo.AdapterRegistry(true);
+dojox.rpc.envelopeRegistry = new dojo.AdapterRegistry(true);
+//Built In Envelopes
+
+dojox.rpc.envelopeRegistry.register(
+	"URL",
+	function(str){ return str == "URL"; },
+	{
+		serialize:function(smd, method, data ){
+			var d = dojo.objectToQuery(data);
+			return {
+				data: d,
+				transport:"POST"
+			};
+		},
+		deserialize:function(results){
+			return results;
+		},
+		namedParams: true
+	}
+);
+
+dojox.rpc.envelopeRegistry.register(
+	"JSON",
+	function(str){ return str == "JSON"; },
+	{
+		serialize: function(smd, method, data){
+			var d = dojo.toJson(data);
+
+			return {
+				data: d,
+				handleAs: 'json',
+				contentType : 'application/json'
+			};
+		},
+		deserialize: function(results){
+			return results;
+		}
+	}
+);
+dojox.rpc.envelopeRegistry.register(
+	"PATH",
+	function(str){ return str == "PATH"; },
+	{
+		serialize:function(smd, method, data){
+			var i;
+			var target = dojox.rpc.getTarget(smd, method);
+			if(dojo.isArray(data)){
+				for(i = 0; i < data.length;i++){
+					target += '/' + data[i];
+				}
+			}else{
+				for(i in data){
+					target += '/' + i + '/' + data[i];
+				}
+			}
+
+			return {
+				data:'',
+				target: target
+			};
+		},
+		deserialize:function(results){
+			return results;
+		}
+	}
+);
+
+
+
+//post is registered first because it is the default;
+dojox.rpc.transportRegistry.register(
+	"POST",
+	function(str){ return str == "POST"; },
+	{
+		fire:function(r){
+			r.url = r.target;
+			r.postData = r.data;
+			return dojo.rawXhrPost(r);
+		}
+	}
+);
+
+dojox.rpc.transportRegistry.register(
+	"GET",
+	function(str){ return str == "GET"; },
+	{
+		fire: function(r){
+			r.url=  r.target + (r.data ? '?'+  r.data : '');
+			return dojo.xhrGet(r);
+		}
+	}
+);
+
+
+//only works ifyou include dojo.io.script
+dojox.rpc.transportRegistry.register(
+	"JSONP",
+	function(str){ return str == "JSONP"; },
+	{
+		fire: function(r){
+			r.url = r.target + ((r.target.indexOf("?") == -1) ? '?' : '&') + r.data;
+			r.callbackParamName = r.callbackParamName || "callback";
+			return dojo.io.script.get(r);
+		}
+	}
+);
+dojox.rpc.Service._nextId = 1;
+
+dojo._contentHandlers.auto = function(xhr){
+	// automatically choose the right handler based on the returned content type
+	var handlers = dojo._contentHandlers;
+	var retContentType = xhr.getResponseHeader("Content-Type");
+	var results = !retContentType ? handlers.text(xhr) :
+		retContentType.match(/\/.*json/) ? handlers.json(xhr) :
+		retContentType.match(/\/javascript/) ? handlers.javascript(xhr) :
+		retContentType.match(/\/xml/) ? handlers.xml(xhr) : handlers.text(xhr);
+	return results;
 };
-}
diff --git a/dojox/rpc/demos/demo_GoogleAjax.html b/dojox/rpc/demos/demo_GoogleAjax.html
new file mode 100644
index 0000000..fdd224f
--- /dev/null
+++ b/dojox/rpc/demos/demo_GoogleAjax.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Demo of Google SMD</title>
+	<style type="text/css">
+		@import "../../image/resources/image.css";
+		body, html {
+			width:100%;
+			margin:0; padding:0;
+		}
+		.logo {
+			border:0; vertical-align:middle;
+		}
+		.summary {
+			color:#666;
+			font:8pt Arial,sans-serif;
+		}
+		#container {
+			width:720px;
+			margin:0 auto;
+		}
+		#loader {
+			position:absolute;
+			top:3px;
+			left:3px;
+			visibility:hidden;
+			height:50px; 
+			width:50px;
+			background:url("../../../dojox/image/resources/images/loading.gif") no-repeat center center;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.rpc.Service");
+		dojo.require("dojo.io.script");
+
+		var google, tehloader = null;
+		function init(){
+
+			google = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc","SMDLibrary/google.smd")); 
+		
+			tehloader = dojo.partial(dojo.style,"loader","visibility");
+			var getResults = function(e){
+
+				tehloader("visible");
+				
+				dojo.query("li","top").forEach(function(item){
+					dojo.byId("archive").appendChild(item);
+				});
+
+                var searchType = dojo.byId("searchType").value || "webSearch";
+                google[searchType]({ q: dojo.byId("test").value })
+					// generic succes handler:
+					.addCallback(function(returned){
+						var ret = returned.responseData;
+						var info = ret.cursor; 
+						var data = ret.results || [];
+						dojo.forEach(data,function(item){
+							var li = dojo.doc.createElement('li');
+							li.innerHTML = "<a target='_new' hr"+"ef='"+ (item.unescapedUrl || item.url) +"'>" + item.title + "</a><br />" +
+								"<span class='summary'>" + (item.content || item.streetAddress || "unknown") + "</span>"; 
+							
+							console.log(item);
+							dojo.byId("top").appendChild(li);
+						});
+						tehloader("hidden");
+					})
+					// something bad happened:
+					.addErrback(function(err){
+						console.warn('ooops', err);
+						tehloader("hidden");
+					});
+			};
+
+			dojo.connect(dojo.byId("doit"), "onclick", getResults);
+
+		}
+		dojo.addOnLoad(init);
+
+	</script>
+</head>
+
+<body>
+		<div id="loader"></div>
+		<div id="container">
+			<h2><a href="http://google.com"><img class="logo" src="http://www.google.com/logos/Logo_40wht.gif" alt="Google" /></a> Ajax API SMD</h2>
+
+			<input id="test" name="test" type="text" size="30" value="The Dojo Toolkit"/>  
+			<select id="searchType">
+				<option value="webSearch">web</option>
+				<option value="localSearch">local</option>
+				<option value="videoSearch">videos</option>
+				<option value="blogSearch">blog</option>
+				<option value="newsSearch">news</option>
+				<option value="bookSearch">books</option>
+				<option value="imageSearch">images</option>
+			</select>   
+			<button id="doit" type="submit" value="search">Search</button>
+		
+			<div id="current">
+				<h3>Results:</h3>
+				<ul id="top"></ul>
+			</div>
+		
+			<div id="past">
+				<h3>Old Searches:</h3>
+				<ul id="archive"></ul>
+			</div>
+
+			<hr>
+			
+			<p>There are many per-serivce options available. This demo just pulls data and tries ...</p>
+			<p>That's all folks. Unit tests to come when we address the io.script issue.</p>
+			
+			
+		</div>
+
+
+</body>
+</html>
diff --git a/dojox/rpc/demos/demo_GoogleAjaxTranslate.html b/dojox/rpc/demos/demo_GoogleAjaxTranslate.html
new file mode 100644
index 0000000..d6d0d5f
--- /dev/null
+++ b/dojox/rpc/demos/demo_GoogleAjaxTranslate.html
@@ -0,0 +1,155 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Demo of Google SMD / Translate test</title>
+	<style type="text/css">
+		body, html {
+			width:100%;
+			margin:0; padding:0;
+		}
+		.logo {
+			border:0; vertical-align:middle;
+		}
+		.summary {
+			color:#666;
+			font:8pt Arial,sans-serif;
+		}
+		#container {
+			width:760px;
+			margin:0 auto;
+		}
+		#loader {
+			position:absolute;
+			top:3px;
+			left:3px;
+			visibility:hidden;
+			height:50px; 
+			width:50px;
+			background:url("../../../dojox/image/resources/images/loading.gif") no-repeat center center;
+		}
+		.inputBox {
+			width:300px;
+		}
+		.warn { color:magenta; }
+		.over { color:red !important; }
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.rpc.Service");
+		dojo.require("dojo.io.script");
+
+		var google, showLoader, hideLoader = null;
+		function init(){
+
+			var s = dojo.query("select.clone")[0];
+			var n = dojo.clone(s);
+			dojo.attr(s,"id","fromLang");
+			dojo.attr(n,"id","toLang");
+			dojo.place(n, "target", "after");
+			
+			google = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc","SMDLibrary/google.smd")); 
+			
+			showLoader = dojo.hitch(dojo,"style","loader","visibility","visible");
+			hideLoader = dojo.hitch(dojo,"style","loader","visibility","hidden");
+
+			dojo.connect(dojo.byId("test"),"onkeypress",function(e){
+				var n = dojo.byId('test');
+				var len = n.value.length + 1;
+				if(len >= 400 && len < 500){
+					if(!dojo.hasClass("progress","warn")){ dojo.addClass("progress","warn"); }
+				}else if(len >= 501){
+					n.value = n.value.substr(0, 500)
+					if(!dojo.hasClass("progress","over")){ dojo.addClass("progress","over"); }
+					return false;
+				}else{
+					dojo.removeClass("progress","over"); 
+					dojo.removeClass("progress","warn");
+				}
+				dojo.byId("used").innerHTML = len + "";
+				
+			});
+
+			var runner = function(e){
+				var pair = dojo.byId("fromLang").value + "|" + dojo.byId("toLang").value;
+				google.translate({ q: dojo.byId("test").value, langpair:pair })
+					.addBoth(function(response){
+						var r = response.responseData;
+						if(r && r.translatedText){
+							dojo.byId("response").value = r.translatedText;
+						}
+						dojo.byId("flop").disabled = false;
+					});
+			};
+
+			dojo.connect(dojo.byId("doit"),"onclick", runner);
+
+			dojo.connect(dojo.byId("flop"),"onclick", function(e){
+				// take the value from the translated text, dump it in the incoming
+				// and set the values opposite
+				var input = dojo.byId("test");
+				var resp = dojo.byId("response");
+				var trans = resp.value;
+
+				resp.value = "";
+				input.value = trans;
+				
+				var cur = dojo.byId("fromLang").selectedIndex;
+				dojo.query("#toLang option").map(function(n){ return (n.selected) ? n : false; })
+					.forEach(function(n,i){
+						if(n){
+							dojo.byId("fromLang").selectedIndex = i;
+							dojo.byId("toLang").selectedIndex = cur;
+						}
+				});
+				dojo.byId("flop").disabled = true;
+				runner();
+					
+			});
+
+		}
+		dojo.addOnLoad(init);
+
+	</script>
+</head>
+
+<body>
+		<div id="loader"></div>
+		<div id="container">
+			<h2><a href="http://google.com"><img class="logo" src="http://www.google.com/logos/Logo_40wht.gif" alt="Google" /></a> Ajax API SMD / Translation Test</h2>
+
+			<div id="progress">Used: <span id="used">?</span> of 500 max.</div>
+			<textarea id="test" style="float:left; width:300px; height:200px; border:1px solid #666; background:#ededed; color:#666"></textarea>
+			<textarea id="response" style="float:right; width:300px; height:200px; border:1px solid #666; background:#ededed; color:#666"></textarea>
+
+			<br style="clear:both">
+
+			<div style="padding-top:15px;">
+			From:
+			<select class="clone">
+				<option  value="ar">Arabic</option><option  value="bg">Bulgarian</option>
+				<option  value="zh-CN">Chinese (Simplified)</option><option  value="zh-TW">Chinese (Traditional)</option>
+				<option  value="hr">Croatian</option><option  value="cs">Czech</option><option  value="da">Danish</option>
+				<option  value="nl">Dutch</option><option SELECTED value="en">English</option><option  value="fi">Finnish</option>
+				<option  value="fr">French</option><option  value="de">German</option><option  value="el">Greek</option>
+				<option  value="hi">Hindi</option><option  value="it">Italian</option><option  value="ja">Japanese</option>
+				<option  value="ko">Korean</option><option  value="no">Norwegian</option><option  value="pl">Polish</option>
+				<option  value="pt">Portuguese</option><option  value="ro">Romanian</option><option  value="ru">Russian</option>
+				<option  value="es">Spanish</option><option  value="sv">Swedish</option>
+			</select>
+
+			<span id="target">To:  </span>
+			
+			<button id="doit">Translate</button>
+			<button id="flop" disabled="disabled">Flip Back</button>
+	
+			</div>
+			
+		
+			
+		</div>
+
+
+</body>
+</html>
diff --git a/dojox/rpc/demos/demo_GoogleFeed.html b/dojox/rpc/demos/demo_GoogleFeed.html
new file mode 100644
index 0000000..5ec3d0a
--- /dev/null
+++ b/dojox/rpc/demos/demo_GoogleFeed.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Demo of Google SMD Feed Service</title>
+<style type="text/css">
+th {
+	text-align:left;
+}
+table {
+	border-collapse:collapse;
+}
+th, td {
+	border:1px solid #ddd;
+}
+</style>
+<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+<script type="text/javascript">
+	dojo.require("dojox.rpc.Service");
+	dojo.require("dojo.io.script");
+
+	function init(){
+		var google = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc","SMDLibrary/google.smd")); 
+		dojo.connect(dojo.byId("go"),"onclick", function(e){
+
+			var resultsNode = dojo.byId("feedData");
+			resultsNode.innnerHTML = "Loading...";
+			
+			var url = dojo.byId("feedUrl").value;
+			google.getFeed({
+				q: url
+			}).addCallback(function(response){
+				console.log(response);
+				var feed = response.responseData.feed;
+
+				dojo.byId("feedTitleNode").innerHTML = feed.title;
+				dojo.byId("feedAuthorNode").innerHTML = feed.author;
+				dojo.byId("feedLinkNode").innerHTML = feed.link;
+				dojo.byId("feedTypeNode").innerHTML = feed.type;
+				dojo.byId("feedDescriptionNode").innerHTML = feed.description;
+
+				var feedEntriesNode = dojo.byId("feedEntriesNode");
+				dojo.forEach(feed.entries, function(entry){
+					var entryNode = document.createElement("li");
+					entryNode.innerHTML = entry.title + ", <i>" + entry.link + "</i>";
+					feedEntriesNode.appendChild(entryNode);
+				});
+
+			}).addErrback(function(err){
+				console.error("Error getting feed from " + url, err);
+			});
+		});
+
+	}
+	dojo.addOnLoad(init);
+
+</script>
+</head>
+
+<body>
+	<h2>Google API SMD - Feed Reader</h2>
+
+	<input id="feedUrl" name="feedUrl" type="text" size="60" value="http://dojotoolkit.org/aggregator/rss">
+	<button id="go" type="submit" value="Read Feed">Read Feed</button>
+
+	<p>Click the Read Feed button to load the feed data.</p>
+
+	<div id="feedData">
+		<table>
+			<tr>
+				<th>Title</th>
+				<td id="feedTitleNode"><i>none yet</i></td>
+			</tr>
+			<tr>
+				<th>Author</th>
+				<td id="feedAuthorNode"><i>none yet</i></td>
+			</tr>
+			<tr>
+				<th>Link</th>
+				<td id="feedLinkNode"><i>none yet</i></td>
+			</tr>
+			<tr>
+				<th>Type</th>
+				<td id="feedTypeNode"><i>none yet</i></td>
+			</tr>
+			<tr>
+				<th>Description</th>
+				<td id="feedDescriptionNode"><i>none yet</i></td>
+			</tr>
+		</table>
+
+		<p><b>Entries:</b></p>
+
+		<ul id="feedEntriesNode">
+		</ul>
+	</div>
+</body>
+</html>
diff --git a/dojox/rpc/demos/demo_jabsorb.html b/dojox/rpc/demos/demo_jabsorb.html
new file mode 100644
index 0000000..8452341
--- /dev/null
+++ b/dojox/rpc/demos/demo_jabsorb.html
@@ -0,0 +1,70 @@
+<!--
+This file is a demo of the Dojo + jabsorb
+
+You must have jabsorb installed in order for this to run.
+This assumes that jabsorb is at /jabsorb-1.3/, but you
+can change the target if it as a different location.
+
+This uses the Hello example from the jabsorb framework (Hello.java and hello.jsp)
+-->
+<html>
+<head>
+	<title>Demo of Dojo + jabsorb</title>
+	<style type="text/css">
+
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojo/resources/dojo.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.rpc.Service");
+		dojo.require("dojox.rpc.JsonRPC");
+		var services = new dojox.rpc.Service({
+			target:"/jabsorb-1.3/JSON-RPC",
+			transport:"POST",
+			envelope:"JSON-RPC-1.0",
+			contentType:"application/json",
+			services:{
+				"hello.sayHello":{
+					returns:{"type":"string"},
+					parameters:[{"type":"string"}]
+				}
+			}
+		});
+		function clickHello() {
+			var whoInput = document.getElementById("who");
+			var deferred = services["hello.sayHello"](whoInput.value);
+			deferred.addCallback(function(result) {
+				alert(result);
+				return result;
+			})
+		}
+
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>
+		DEMO:  jabsorb
+	</h1>
+	<hr>
+	<h3>
+		Description:
+	</h3>
+	<p>
+		This simple demo shows how to connect to a <a href="http://jabsorb.org/">jabsorb server</a>
+	</p>
+<p>The jabsorb <em>Hello World</em> application.</p>
+
+<p>
+  <strong>Who:</strong>
+  <input type="text" id="who" size="30" value="Michael"/>
+   
+
+  <input type="button" value="Say Hello" onclick="clickHello()"/>
+</p>
+<body>
+	<hr/>
+</body>
+</html>
diff --git a/dojox/rpc/demos/documentation.html b/dojox/rpc/demos/documentation.html
new file mode 100644
index 0000000..b5a2a44
--- /dev/null
+++ b/dojox/rpc/demos/documentation.html
@@ -0,0 +1,33 @@
+<html>
+	<head>
+		<script src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+		<script>
+			dojo.require("dojo.io.script")
+			dojo.require("dojox.rpc.Service");
+			dojo.require("dijit._Widget");
+			dojo.require("dojox.dtl._Templated");
+			dojo.require("dojo.parser");
+
+			dojo.declare("API", [dijit._Widget, dojox.dtl._Templated], {
+				constructor: function(params, node){
+					this.jsonp = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc", "SMDLibrary/dojo-api.smd"));
+				},
+				onSearch: function(e){
+					if(e.keyCode == dojo.keys.ENTER){
+						this.jsonp.get({
+							name: e.target.value
+						}).addCallback(this, function(results){
+							console.debug(results);
+							this.results = results;
+							this.render();
+						});
+					}
+				},
+				templateString: dojo.cache("dojox.rpc.demos.templates", "documentation.html")
+			});
+		</script>
+	</head>
+	<body>
+		<div dojoType="API"></div>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/rpc/demos/templates/documentation.html b/dojox/rpc/demos/templates/documentation.html
new file mode 100644
index 0000000..d14cf16
--- /dev/null
+++ b/dojox/rpc/demos/templates/documentation.html
@@ -0,0 +1,8 @@
+<div>
+	<input dojotAttachPoint="search" dojoAttachEvent="onkeyup: onSearch">
+	<ul>
+	{% for result in results %}
+		<li>{% if result.type %}<i>{{ result.type }}</i> {% endif %}{% ifequal result.type "Function" %}{% if not result.resources %}function {% endif %}{% endifequal %}{{ result.name }}{% ifequal result.type "Function" %}{% if not result.resources %}({% for parameter in result.parameters %}{% if not forloop.first %}, {% endif %}{% if parameter.types %}<i>{% for type in parameter.types %}{% if not forloop.first %}|{% endif %}{{ type.title }}{% endfor %}{% if parameter.optional %}?{% endif %}{% [...]
+	{% endfor %}
+	</ul>
+</div>
\ No newline at end of file
diff --git a/dojox/rpc/demos/templates/wikipedia.html b/dojox/rpc/demos/templates/wikipedia.html
new file mode 100644
index 0000000..e923a0b
--- /dev/null
+++ b/dojox/rpc/demos/templates/wikipedia.html
@@ -0,0 +1,10 @@
+<div>
+	<input dojotAttachPoint="search" dojoAttachEvent="onkeyup: onSearch">
+	{% if parsedText %}
+	<div style="border:2px solid #ddd; padding:20px;">
+		{{ parsedText }}
+	</div>
+	{% endif %}
+
+	{% if article.revid %}<p>Revision ID: {{ article.revid }}</p>{% endif %}
+</div>
diff --git a/dojox/rpc/demos/templates/yahoo.html b/dojox/rpc/demos/templates/yahoo.html
new file mode 100644
index 0000000..04339d2
--- /dev/null
+++ b/dojox/rpc/demos/templates/yahoo.html
@@ -0,0 +1,31 @@
+<div>
+	<input dojotAttachPoint="search" dojoAttachEvent="onkeyup: onSearch">
+	<ul>
+	{% for result in results.Result %}
+		<li><a href="{{ result.Url }}">{{ result.Title }}</a><br/>{{ result.Summary }}</li>
+	{% endfor %}
+	</ul>
+	<table>
+		{% if results.firstResultPosition %}
+		<tr>
+			<th align="left">First Result</th>
+			<td>{{ results.firstResultPosition }}</td>
+		</tr>
+		{% endif %}{% if results.totalResultsAvailable %}
+		<tr>
+			<th align="left">Total Results Available</th>
+			<td>{{ results.totalResultsAvailable }}</td>
+		</tr>
+		{% endif %}{% if results.totalResultsReturned %}
+		<tr>
+			<th align="left">Results Returned</th>
+			<td>{{ results.totalResultsReturned }}</td>
+		</tr>
+		{% endif %}{% if results.type %}
+		<tr>
+			<th align="left">Type</th>
+			<td>{{ results.type }}</td>
+		</tr>
+		{% endif %}
+	</table>
+</div>
diff --git a/dojox/rpc/demos/wikipedia.html b/dojox/rpc/demos/wikipedia.html
new file mode 100644
index 0000000..4aeb233
--- /dev/null
+++ b/dojox/rpc/demos/wikipedia.html
@@ -0,0 +1,41 @@
+<html>
+	<head>
+		<title>
+			Wikipedia Article Grabber Demo
+		</title>
+		<script src="../../../dojo/dojo.js" type="text/javascript"
+			djConfig="parseOnLoad: true, isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.io.script")
+			dojo.require("dojox.rpc.Service");
+			dojo.require("dijit._Widget");
+			dojo.require("dojox.dtl._Templated");
+			dojo.require("dojo.parser");
+
+			dojo.declare("WikipediaPageGrabber", [dijit._Widget, dojox.dtl._Templated], {
+				constructor: function(params, node){
+					var mu = dojo.moduleUrl("dojox.rpc.SMDLibrary", "wikipedia.smd");
+					this.wikipedia = new dojox.rpc.Service(mu);
+				},
+				onSearch: function(e){
+					if(e.keyCode == dojo.keys.ENTER){
+						this.wikipedia.query({
+							action: "parse",
+							page: e.target.value
+						}).addCallback(this, function(article){
+							console.debug(article.parse);
+							this.article = article.parse;
+							this.parsedText = article.parse.text["*"]; // ugh, crazy JSON structure here
+							this.render();
+						});
+					}
+				},
+				templateString: dojo.cache("dojox.rpc.demos.templates", "wikipedia.html")
+			});
+		</script>
+	</head>
+	<body>
+		<h1>Wikipedia Page Grabber</h1>
+		<div dojoType="WikipediaPageGrabber"></div>
+	</body>
+</html>
diff --git a/dojox/rpc/demos/yahoo.html b/dojox/rpc/demos/yahoo.html
new file mode 100644
index 0000000..4f1d705
--- /dev/null
+++ b/dojox/rpc/demos/yahoo.html
@@ -0,0 +1,39 @@
+<html>
+	<head>
+		<title>
+			Yahoo Search Demo
+		</title>
+		<script src="../../../dojo/dojo.js" type="text/javascript"
+			djConfig="parseOnLoad: true, isDebug: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.io.script")
+			dojo.require("dojox.rpc.Service");
+			dojo.require("dijit._Widget");
+			dojo.require("dojox.dtl._Templated");
+			dojo.require("dojo.parser");
+
+			dojo.declare("YahooWebSearchApiWidget", [dijit._Widget, dojox.dtl._Templated], {
+				constructor: function(params, node){
+					var mu = dojo.moduleUrl("dojox.rpc.SMDLibrary", "yahoo.smd");
+					this.yahoo = new dojox.rpc.Service(mu);
+				},
+				onSearch: function(e){
+					if(e.keyCode == dojo.keys.ENTER){
+						this.yahoo.webSearch({
+							query: e.target.value
+						}).addCallback(this, function(results){
+							console.debug(results.ResultSet);
+							this.results = results.ResultSet;
+							this.render();
+						});
+					}
+				},
+				templateString: dojo.cache("dojox.rpc.demos.templates", "yahoo.html")
+			});
+		</script>
+	</head>
+	<body>
+		<h1>Yahoo Web Search</h1>
+		<div dojoType="YahooWebSearchApiWidget"></div>
+	</body>
+</html>
diff --git a/dojox/rpc/tests/FriendFeed.js b/dojox/rpc/tests/FriendFeed.js
new file mode 100644
index 0000000..321e962
--- /dev/null
+++ b/dojox/rpc/tests/FriendFeed.js
@@ -0,0 +1,104 @@
+dojo.provide('dojox.rpc.tests.FriendFeed');
+
+dojo.require('dojo.io.script');
+dojo.require('dojox.rpc.Service');
+
+(function() {
+
+// simple class to help write tests...
+dojo.declare("dojox.rpc.tests.FFTest",null, {
+    name: "",
+    timeout: 8000,
+
+    constructor: function(name, method, parameters, fn) {
+        var props = { name: name,
+                      _method: method,
+                      _parameters: parameters,
+                      _test: fn
+        };
+        dojo.mixin( this, props );
+        return this;
+    },
+    setUp: function() {
+        this.service = new dojox.rpc.Service(
+                     dojo.moduleUrl("dojox.rpc.SMDLibrary", "friendfeed.smd"));
+    },
+    runTest: function( t ) {
+        var d = new doh.Deferred();
+        var ff = this.service[ this._method ]( this._parameters );
+        ff.addCallback( this, function( results ) {
+            if ( results.errorCode ) {
+                d.errback( new Error("Test failed", results ) );
+            } else {
+                if ( this._test( results ) )  {
+                    d.callback( true );
+                } else {
+                    d.errback( new Error("Test failed ", results ) );
+                }
+            }
+            return d;
+        });
+    },
+    tearDown: function() {
+        this.service = undefined;
+    }
+});
+
+// test the methods and parameters of the SMD file
+doh.register('dojox.rpc.tests.friendfeed',
+    [
+    new dojox.rpc.tests.FFTest("#1 Users",
+        "users",
+        { nickname: "paul" },
+        function( results ) {
+            return results.entries;
+        }
+    ),
+    new dojox.rpc.tests.FFTest("#2 Search",
+        "search",
+        { q: "dojo" },
+        function ( results ) {
+            return results.entries;
+        }
+    ),
+    new dojox.rpc.tests.FFTest("#3 Domain",
+        "entry",
+        { entry_id: "245da66c-d6dd-8a4b-1719-b5bfb1f9d5eb" },
+        function ( results ) {
+          return results.entries && results.entries.length == 1;
+          // ???: check user info too?
+        }
+    ),
+    new dojox.rpc.tests.FFTest("#4 URL",
+        "url",
+        { url: "http://blog.medryx.org/tag/doh/"  },
+        function( results ) {
+            return results.entries && results.entries.length >= 1;
+        }
+    ),
+    new dojox.rpc.tests.FFTest("#5 Domain",
+        "domain",
+        { domain: "dojotoolkit.org" },
+        function ( results ) {
+            return results.entries && results.entries.length >=1;
+        }
+    ),
+    new dojox.rpc.tests.FFTest("#6 Parameter - service",
+        "users",
+        { nickname: "paul", service: "twitter" },
+        function ( results ) {
+            var ent  = dojo.filter( results.entries, function( entry ) {
+                return entry.service.id != 'twitter';
+            });
+            return ent.length == 0;
+        }
+    ),
+    new dojox.rpc.tests.FFTest("#7 Parameter - num",
+        "users",
+        { nickname: "paul", num: 42 },
+        function ( results ) {
+            return results.length == 42;
+        }
+    )
+]);
+ })();
diff --git a/dojox/rpc/tests/Geonames.js b/dojox/rpc/tests/Geonames.js
new file mode 100644
index 0000000..0468f46
--- /dev/null
+++ b/dojox/rpc/tests/Geonames.js
@@ -0,0 +1,227 @@
+dojo.provide("dojox.rpc.tests.Geonames");
+dojo.require("dojo.io.script");
+dojo.require("dojox.rpc.Service");
+
+dojox.rpc.tests.service = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.SMDLibrary", "geonames.smd"));
+
+dojox.rpc.tests.TEST_METHOD_TIMEOUT = 20000;
+dojox.rpc.tests.TEST_METHOD_LONG_TIMEOUT = 30000;
+
+dojox.rpc.tests._testMethod = function(method){
+
+        return function(m){
+                var d = new doh.Deferred();
+
+                if (method.name && method.parameters) {
+                        var def = dojox.rpc.tests.service[method.name](method.parameters);
+                        def.addCallback(this, function(result){
+				if (method.debugTest) {
+					console.log("Results: ", dojo.toJson(result));	
+				}
+				var testType = method.testType || "compare";
+				switch(testType){
+					case "compare":	
+						console.log("Comparison Test");
+		                                if (dojo.toJson(result)==method.expectedResult){
+                                        		d.callback(true);
+						}else{
+							d.errback(new Error("Unexpected Return Value in comparison: ", result));
+						}
+						break;
+					case "result":
+						console.log("Result Test");
+						if (result && dojo.toJson(result)){
+							d.callback(true);	
+						}else{
+							d.errback(new Error("Unexpected Return Value, no result or not valid json: ", result));
+
+						}	
+						break;
+					default:
+						d.errback(new Error("Unknown test type"));
+						break;
+				}
+                        });
+                }
+
+                return d;
+        }
+};
+
+doh.register("dojox.rpc.tests.geonames", 
+	[
+		{
+			name: "#1, getCities()",
+			timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests._testMethod({
+				name: "getCities",
+                                parameters: {north: 44.1, south:-9.9, east: -22.4, west: 55.2},
+                                expectedResult: dojo.toJson({"geonames":[{"fcodeName":"capital of a political entity","countrycode":"MX","fcl":"P","fclName":"city, village,...","name":"Mexico City","wikipedia":"en.wikipedia.org/wiki/Mexico_City","lng":-99.1386111,"fcode":"PPLC","geonameId":3530597,"lat":19.4341667,"population":11285654},{"fcodeName":"capital of a political entity","countrycode":"PH","fcl":"P","fclName":"city, village,...","name":"Manila","wikipedia":"","lng":120.9822222, [...]
+			})
+		},
+                {
+                        name: "#2, getQuakes()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getQuakes",
+                                parameters: {north: 44.1, south:-9.9, east: -22.4, west: 55.2, "date": "2007-07-31", maxRows: 1},
+                                expectedResult: dojo.toJson({"earthquakes":[{"eqid":"2007flce","magnitude":6.1,"lng":-17.7996,"src":"us","datetime":"2007-07-31 22:55:31","depth":10,"lat":-0.095}]})
+                        })
+                },
+                {
+                        name: "#3, getWeather()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getWeather",
+				testType:'result',
+                                parameters: {north: 44.1, south:-9.9, east: -22.4, west: 55.2, "date": "2007-07-31", maxRows: 1}
+                        })
+                },
+
+                {
+                        name: "#4, getWeatherByICAO()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getWeatherByICAO",
+				testType:'result',
+                                parameters: {ICAO:"LSZH"}
+                        })
+                },
+
+                {
+                        name: "#5, getWeatherByCoords()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getWeatherByCoords",
+				testType:'result',
+                                parameters: {lat:43,lng:-2}
+                        })
+                },
+
+                {
+                        name: "#6, getChildren()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getChildren",
+                                parameters: {geonameId:3175395},
+				testType: 'result'
+                        })
+                },
+
+                {
+                        name: "#7, getHeirarchy()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getHierarchy",
+                                parameters: {geonameId:3175395},
+				testType: 'result'
+                        })
+                },
+                {
+                        name: "#8, getNeighbours()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getNeighbours",
+                                parameters: {geonameId:3175395},
+				testType: 'result'
+                        })
+                },
+
+                {
+                        name: "#9, getNeighbourhood()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getNeighbourhood",
+                                parameters: {lat:40.78343, lng:-73.96625},
+				expectedResult: dojo.toJson({"neighbourhood":{"adminName2":"New York County","adminCode2":"061","adminCode1":"NY","countryName":"United States","name":"Central Park","countryCode":"US","city":"New York City-Manhattan","adminName1":"New York"}})
+                        })
+                },
+
+                {
+                        name: "#10, getSiblings()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getSiblings",
+                                parameters: {geonameId:3175395},
+				testType: 'result'
+                        })
+                },
+
+                {
+                        name: "#11, getCountryCode()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getCountryCode",
+                                parameters:{lat:40.78343, lng:-73.96625},
+				expectedResult: dojo.toJson({"distance":0,"countryName":"United States","countryCode":"US"}) 
+                        })
+                },
+                {
+                        name: "#12, getCountrySubdivision()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getCountrySubdivision",
+                                parameters:{lat:40.78343, lng:-73.96625},
+				expectedResult: dojo.toJson({"distance":0,"adminCode1":"NY","countryName":"United States","countryCode":"US","codes":[{"code":"36","type":"FIPS10-4"},{"code":"NY","type":"ISO3166-2"}],"adminName1":"New York"})
+                        })
+                },
+                {
+                        name: "#13, getWikipediaBoundingBox()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getWikipediaBoundingBox",
+                                parameters:{north: "44.1", "south": "-9.9", "east": "-22.4", "west": "55.2", "maxRows": "1"},
+				testType: 'result'
+                        })
+                },
+                 {
+                        name: "#14, searchWikipedia()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "searchWikipedia",
+                                parameters:{q: "dojo", maxRows: 1},
+				expectedResult: dojo.toJson({"geonames":[{"summary":"which is an umbrella organisation of various national, as well as smaller, aikido organisations. Although the name strictly refers only to the main training hall (''dojo''), it is often used by extension to refer to the Aikikai organisation itself. The dojo was founded by Morihei Ueshiba in 1931 under the name ''Kobukan'' (...)","title":"Aikikai Hombu Dojo","wikipediaUrl":"en.wikipedia.org/wiki/Aikikai_Hombu_Dojo","elevation":0,"co [...]
+                        })
+                },
+                {
+                        name: "#15, getTimezone()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "getTimezone",
+                                parameters:{lat:40.78343,lng:-73.96625},
+				expectedResult: dojo.toJson({"countryName":"United States","dstOffset":-4,"countryCode":"US","gmtOffset":-5,"lng":-73.96625,"timezoneId":"America/New_York","lat":40.78343})
+                        })
+                },
+ 
+                {
+                        name: "#16, search()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "search",
+                                parameters:{q: "dojo", maxRows: 1},
+				testType: 'result'
+                        })
+                },
+
+                 {
+                        name: "#17, postalCodeLookup()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "postcalCodeLookup",
+				debugTest: true,
+                                parameters:{postalcode: "24060"},
+				expectedResult: dojo.toJson({})
+                        })
+                },
+ 
+                {
+                        name: "#18, postalCodeSearch()",
+                        timeout: dojox.rpc.tests.TEST_METHOD_TIMEOUT,
+                        runTest: dojox.rpc.tests._testMethod({
+                                name: "postalCodeSearch",
+                                parameters:{placename: "blacksburg"},
+				expectedResult: dojo.toJson({})
+                        })
+                }
+	]
+);
diff --git a/dojox/rpc/tests/Service.js b/dojox/rpc/tests/Service.js
new file mode 100644
index 0000000..a235b1c
--- /dev/null
+++ b/dojox/rpc/tests/Service.js
@@ -0,0 +1,725 @@
+dojo.provide("dojox.rpc.tests.Service");
+dojo.require("dojo.io.script");
+dojo.require("dojox.rpc.Service");
+dojo.require("dojox.rpc.JsonRPC");
+dojo.require("dojox.rpc.Rest");
+dojo.require("dojox.rpc.Client");
+//this is a copy of our smd in js form, so we can just share it easily
+//dojo.require("dojox.rpc.tests.resources.testSmd");
+
+dojox.rpc.tests.service = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.tests.resources", "test.smd"));
+
+doh.register("dojox.rpc.tests.echo", 
+	[
+		{
+			name: "#1 POST,URL,Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+				//test when given named params
+				var td = this.svc.postEcho({message: this.name,foo:2});
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#2 POST,URL,Ordered Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.postEcho(this.name,2);
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#3 GET,URL,Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.getEcho({message: this.name});
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		
+		{
+			name: "#3.1 REST PUT,Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				res = this.name + Math.random();
+				//test when given named params				
+				var td = this.svc.restStore.put({location: "res"},res);
+				td.addCallback(this, function(result){
+					var td = this.svc.restStore({location: "res"});
+					td.addCallback(this, function(result){
+						if (result==res){
+							d.callback(true);
+						}else{
+							d.errback(new Error("Unexpected Return Value: ", result));
+						}
+					});
+						
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#3.2 REST POST,Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+				var newRes = this.name + Math.random();
+				res += newRes;
+				//test when given named params
+				var td = this.svc.restStore.post({location: "res"},newRes);
+				td.addCallback(this, function(result){
+					var td = this.svc.restStore({location: "res"});
+					td.addCallback(this, function(result){
+						if (result==res){
+							d.callback(true);
+						}else{
+							d.errback(new Error("Unexpected Return Value: ", result));
+						}
+					});
+						
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#3.3 REST DELETE,Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.restStore['delete']({location: "res"});
+				td.addCallback(this, function(result){
+					var td = this.svc.restStore({location: "res"});
+					td.addCallback(this, function(result){
+						if (result=="deleted"){
+							d.callback(true);
+						}else{
+							d.errback(new Error("Unexpected Return Value: ", result));
+						}
+					});
+						
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#3.4 GET,URL,Named Parameters, Returning Json",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.getEchoJson({message:'{"foo":"bar"}'});
+				td.addCallback(this, function(result){
+					if (result.foo=='bar'){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#3.5 GET,PATH,Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.getPathEcho({path: "pathname"});
+				td.addCallback(this, function(result){
+					if (result=="/path/pathname"){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+
+		{
+			name: "#4.1 GET,URL,Ordered Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.getEcho(this.name);
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#4.2 Namespaced GET,URL,Ordered Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.namespace.getEcho(this.name);
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+
+		{
+			name: "#5 POST,URL,Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.postJsonEcho({message: this.name});
+				td.addCallback(this, function(result){
+					if (result && result.message && result.message==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+
+		{
+			name: "#6 POST,JSON,Ordered Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.postJsonEcho(this.name);
+				td.addCallback(this, function(result){
+					if (result && result[0] && result[0]==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#7 JSONP,URL,Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.jsonpEcho({message: this.name});
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#8 JSONP,URL, Ordered Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.jsonpEcho(this.name);
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#9 POST,JSON-RPC-1.0,Ordered Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.postJsonRpc10Echo(this.name);
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#10 POST,JSON-RPC-1.0,Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.postJsonRpc10EchoNamed(this.name);
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#11 POST,JSON-RPC 2.0, Ordered Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.postJsonRpc12Echo(this.name);
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#12 POST,JSON-RPC 2.0, Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.postJsonRpc12Echo({message: this.name});
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		}
+	/*
+		,{
+			name: "#13 GET,JSON-RPC 2.0, Ordered Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.getJsonRpc12Echo(this.name);
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "#14 GET,JSON-RPC 2.0, Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.getJsonRpc12EchoNamed({message: this.name});
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		},
+		,{
+			name: "#15 JSONP,JSON-RPC 2.0, Ordered Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.jsonpJsonRpc12Echo(this.name);
+				td.addCallback(this, function(result){
+					if (result==this.name){
+						d.callback(true);
+					}else{
+						d.errback(new Error("Unexpected Return Value: ", result));
+					}
+				});
+
+				return d;
+			}
+		}
+		*/
+	]
+);
+
+doh.register("dojox.rpc.tests.jsonRpcForcedError", [
+		{
+			name: "POST,JSON-RPC 1.0, Ordered Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.postJsonRpc10ForcedError(this.name);
+
+				td.addErrback(this, function(error){
+					d.callback(true);
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "POST,JSON-RPC 2.0, Ordered Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.postJsonRpc12ForcedError(this.name);
+
+				td.addErrback(this, function(error){
+					d.callback(true);
+				});
+
+				return d;
+			}
+		},
+		{
+			name: "POST,JSON-RPC 2.0, Named Parameters",
+			timeout: 4000,
+			setUp: function(){
+				//this.svc = new dojox.rpc.Service(dojox.rpc.tests.resources.testSmd);
+				this.svc = dojox.rpc.tests.service;
+			},
+			runTest: function(){
+				var d = new doh.Deferred();
+
+				if (window.location.protocol=="file:") {
+					var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://");
+					d.errback(err);
+					return d;
+				}
+
+				//test when given named params
+				var td = this.svc.postJsonRpc12ForcedError({message: this.name});
+
+				td.addErrback(this, function(error){
+					d.callback(true);
+				});
+
+				return d;
+			}
+		}
+]);
diff --git a/dojox/rpc/tests/Wikipedia.js b/dojox/rpc/tests/Wikipedia.js
new file mode 100644
index 0000000..136bce8
--- /dev/null
+++ b/dojox/rpc/tests/Wikipedia.js
@@ -0,0 +1,55 @@
+dojo.provide("dojox.rpc.tests.Wikipedia");
+dojo.require("dojo.io.script");
+dojo.require("dojox.rpc.Service");
+
+dojox.rpc.tests.wikipediaService = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.SMDLibrary", "wikipedia.smd"));
+
+dojox.rpc.tests.wikipediaService.TEST_METHOD_TIMEOUT = 8000;
+
+dojox.rpc.tests.wikipediaService._query = function(q){
+	return function(m){
+		var d = new doh.Deferred();
+
+		if (q.parameters && q.parameters.action && q.expectedResult) {
+			var wp = dojox.rpc.tests.wikipediaService.query(q.parameters);
+			wp.addCallback(this, function(result){
+				console.log(result);
+				if (result[q.expectedResult]){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected Return Value: ", result));
+				}
+			});
+		}
+
+		return d;
+	}
+};
+
+doh.register("dojox.rpc.tests.wikipedia", 
+	[
+		{
+			name: "#1, Wikipedia::parse",
+			timeout: dojox.rpc.tests.wikipediaService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.wikipediaService._query({
+				parameters: {
+					action: "parse",
+					page: "Dojo Toolkit"
+				},
+				expectedResult: "parse"
+			})
+		},
+		{
+			name: "#2, Wikipedia::search",
+			timeout: dojox.rpc.tests.wikipediaService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.wikipediaService._query({
+				parameters: {
+					action: "query",
+					list: "search",
+					srwhat: "text",
+					srsearch: "Dojo Toolkit"
+				},
+				expectedResult: "query"
+			})
+		}
+]);
diff --git a/dojox/rpc/tests/Yahoo.js b/dojox/rpc/tests/Yahoo.js
new file mode 100644
index 0000000..e32bc93
--- /dev/null
+++ b/dojox/rpc/tests/Yahoo.js
@@ -0,0 +1,313 @@
+dojo.provide("dojox.rpc.tests.Yahoo");
+dojo.require("dojo.io.script");
+dojo.require("dojox.rpc.Service");
+
+dojox.rpc.tests.yahooService = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.SMDLibrary", "yahoo.smd"));
+
+dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT = 8000;
+dojox.rpc.tests.yahooService.TEST_METHOD_LONG_TIMEOUT = 30000;
+
+dojox.rpc.tests.yahooService._testMethod = function(method){
+	return function(m){
+		var d = new doh.Deferred();
+
+		if (method.name && method.parameters && method.expectedResult) {
+			var yd = dojox.rpc.tests.yahooService[method.name](method.parameters);
+			yd.addCallback(this, function(result){
+				if (result[method.expectedResult]){
+					d.callback(true);
+				}else{
+					d.errback(new Error("Unexpected Return Value: ", result));
+				}
+			});
+		}
+
+		return d;
+	}
+};
+
+doh.register("dojox.rpc.tests.yahoo", 
+	[
+		{
+			name: "#1, Yahoo Answers::questionSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "questionSearch",
+				parameters: {query: "dojo toolkit"},
+				expectedResult: "all"
+			})
+		},
+		{
+			name: "#2, Yahoo Answers::getByCategory",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "getByCategory",
+				parameters: {category_name: "Computers+%26+Internet%3ESoftware"},
+				expectedResult: "all"
+			})
+		},
+		{
+			name: "#3, Yahoo Answers::getQuestion",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "getQuestion",
+				parameters: {question_id: "1005120800412"},
+				expectedResult: "all"
+			})
+		},
+		{
+			name: "#4, Yahoo Answers::getByUser",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "getByUser",
+				parameters: {user_id: "AA10001397"},
+				expectedResult: "all"
+			})
+		},
+		{
+			name: "#5, Yahoo Audio::artistSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "artistSearch",
+				parameters: {artist: "The Beatles"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#6, Yahoo Audio::albumSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "albumSearch",
+				parameters: {artist: "The Beatles", album: "Magical Mystery Tour"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#7, Yahoo Audio::songSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "songSearch",
+				parameters: {artist: "The Beatles", album: "Magical Mystery Tour", song: "Penny Lane"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#8, Yahoo Audio::songDownloadLocation",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "songDownloadLocation",
+				parameters: {songid: "XXXXXXT000995691"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#9, Yahoo ContentAnalysis::contextSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "contextSearch",
+				parameters: {
+					context: "Welcome to the Book of Dojo. This book covers both versions 0.9 and 1.0, and all 1.0 extensions and changes are clearly marked for your enjoyment. Please use the forums for support questions, but if you see something missing, incomplete, or just plain wrong in this book, please leave a comment.",
+					query: "dojo"
+				},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#10, Yahoo Image::imageSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "imageSearch",
+				parameters: {query: "dojo"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#11, Yahoo Local::localSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "localSearch",
+				parameters: {query: "pizza", zip: "98201"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#12, Yahoo Local::collectionSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_LONG_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "collectionSearch",
+				parameters: {query: "dojo"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#13, Yahoo Local::getCollection",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_LONG_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				expectedResult: "getCollection",
+				parameters: {collection_id: "1000031487"},
+				expectedResult: "Result"
+			})
+		},
+		{
+			name: "#14, Yahoo Local::trafficData",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_LONG_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "trafficData",
+				parameters: {street: "1600 Pennsylvania Ave", city: "Washington, DC"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#15, Yahoo MyWebs::urlSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_LONG_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "urlSearch",
+				parameters: {tag: "javascript"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#16, Yahoo MyWebs::tagSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_LONG_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "tagSearch",
+				parameters: {url: "dojotoolkit.org"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#17, Yahoo MyWebs::relatedTags",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_LONG_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "relatedTags",
+				parameters: {tag: "javascript"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#18, Yahoo NewsSearch::newsSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "newsSearch",
+				parameters: {query: "dojo toolkit"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#19, Yahoo Shopping::catalogListing",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "catalogListing",
+				parameters: {idtype: "brand,partnum", idvalue: "canon,1079B001", getspec: 1},
+				expectedResult: "Catalog"
+			})
+		},
+		{
+			name: "#20, Yahoo Shopping::merchantSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "merchantSearch",
+				parameters: {merchantid: "1021849"},
+				expectedResult: "Merchant"
+			})
+		},
+		{
+			name: "#21, Yahoo Shopping::productSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "productSearch",
+				parameters: {query: "dojo"},
+				expectedResult: "Categories"
+			})
+		},
+		{
+			name: "#22, Yahoo SiteExplorer::inlinkData",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "inlinkData",
+				parameters: {query: "dojotoolkit.org"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#23, Yahoo SiteExplorer::pageData",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "pageData",
+				parameters: {query: "dojotoolkit.org"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#24, Yahoo SiteExplorer::ping",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "ping",
+				parameters: {sitemap: "http://www.yahoo.com"},
+				expectedResult: "Success"
+			})
+		},
+		{
+			name: "#25, Yahoo SiteExplorer::updateNotification",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "updateNotification",
+				parameters: {url: "http://www.yahoo.com"},
+				expectedResult: "Success"
+			})
+		},
+		{
+			name: "#26, Yahoo Trip::tripSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "tripSearch",
+				parameters: {query: "eiffel tower"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#27, Yahoo Trip::getTrip",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "getTrip",
+				parameters: {id: "546303"},
+				expectedResult: "Result"
+			})
+		},
+		{
+			name: "#28, Yahoo Video::videoSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "videoSearch",
+				parameters: {query: "star wars kid"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#29, Yahoo Web::webSearch",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "webSearch",
+				parameters: {query: "dojo toolkit"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#30, Yahoo Web::spellingSuggestion",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "spellingSuggestion",
+				parameters: {query: "beatls"},
+				expectedResult: "ResultSet"
+			})
+		},
+		{
+			name: "#31, Yahoo Web::relatedSuggestion",
+			timeout: dojox.rpc.tests.yahooService.TEST_METHOD_TIMEOUT,
+			runTest: dojox.rpc.tests.yahooService._testMethod({
+				name: "relatedSuggestion",
+				parameters: {query: "dojo toolkit"},
+				expectedResult: "ResultSet"
+			})
+		}
+]);
diff --git a/dojox/rpc/tests/libraryTests.js b/dojox/rpc/tests/libraryTests.js
new file mode 100644
index 0000000..e4e7301
--- /dev/null
+++ b/dojox/rpc/tests/libraryTests.js
@@ -0,0 +1,11 @@
+dojo.provide("dojox.rpc.tests.libraryTests");
+
+try{
+	dojo.require("dojox.rpc.tests.Yahoo");
+	dojo.require("dojox.rpc.tests.Geonames");
+	dojo.require("dojox.rpc.tests.Wikipedia");
+	dojo.require("dojox.rpc.tests.FriendFeed");
+}catch(e){
+	doh.debug(e);
+}
+
diff --git a/dojox/rpc/tests/module.js b/dojox/rpc/tests/module.js
new file mode 100644
index 0000000..0017254
--- /dev/null
+++ b/dojox/rpc/tests/module.js
@@ -0,0 +1,9 @@
+dojo.provide("dojox.rpc.tests.module");
+
+try{
+	dojo.require("dojox.rpc.tests.Service");
+	dojo.require("dojox.rpc.tests.JsonReferencing");
+}catch(e){
+	doh.debug(e);
+}
+
diff --git a/dojox/rpc/tests/resources/JSON.php b/dojox/rpc/tests/resources/JSON.php
new file mode 100755
index 0000000..4a21ce7
--- /dev/null
+++ b/dojox/rpc/tests/resources/JSON.php
@@ -0,0 +1,724 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/** 
+ * Converts to and from JSON format.
+ * 
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
+ * format. It is easy for humans to read and write. It is easy for machines
+ * to parse and generate. It is based on a subset of the JavaScript
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+ * This feature can also be found in  Python. JSON is a text format that is
+ * completely language independent but uses conventions that are familiar
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
+ * ideal data-interchange language.
+ * 
+ * This package provides a simple encoder and decoder for JSON notation. It
+ * is intended for use with client-side Javascript applications that make
+ * use of HTTPRequest to perform server communication functions - data can
+ * be encoded into JSON notation for use in a client-side javascript, or
+ * decoded from incoming Javascript requests. JSON format is native to
+ * Javascript, and can be directly eval()'ed with no further parsing
+ * overhead
+ *
+ * All strings should be in ASCII or UTF-8 format!
+ *
+ * LICENSE: Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met: Redistributions of source code must retain the
+ * above copyright notice, this list of conditions and the following
+ * disclaimer. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * 
+ * @category   
+ * @package     Services_JSON
+ * @author      Michal Migurski <mike-json at teczno.com>
+ * @author      Matt Knapp <mdknapp[at]gmail[dot]com>
+ * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+ * @copyright   2005 Michal Migurski
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+ */
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_SLICE',   1);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_STR',  2);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_ARR',  4);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_OBJ',  8);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_CMT', 16);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_LOOSE_TYPE', 10);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_STRICT_TYPE', 11);
+
+/** 
+ * Converts to and from JSON format.
+ *
+ * Brief example of use:
+ *
+ * <code>
+ * // create a new instance of Services_JSON
+ * $json = new Services_JSON();
+ * 
+ * // convert a complexe value to JSON notation, and send it to the browser
+ * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
+ * $output = $json->encode($value);
+ *
+ * print($output);
+ * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
+ * 
+ * // accept incoming POST data, assumed to be in JSON notation
+ * $input = file_get_contents('php://input', 1000000);
+ * $value = $json->decode($input);
+ * </code>
+ */
+class Services_JSON
+{
+   /**
+    * constructs a new JSON instance
+    *
+    * @param    int     $use    object behavior: when encoding or decoding,
+    *                           be loose or strict about object/array usage
+    *
+    *                           possible values:
+    *                           - SERVICES_JSON_STRICT_TYPE: strict typing, default.
+    *                                                        "{...}" syntax creates objects in decode().
+    *                           - SERVICES_JSON_LOOSE_TYPE:  loose typing.
+    *                                                        "{...}" syntax creates associative arrays in decode().
+    */
+    function Services_JSON($use = SERVICES_JSON_STRICT_TYPE)
+    {
+        $this->use = $use;
+    }
+
+   /**
+    * convert a string from one UTF-16 char to one UTF-8 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf16  UTF-16 character
+    * @return   string  UTF-8 character
+    * @access   private
+    */
+    function utf162utf8($utf16)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding'))
+            return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
+        
+        $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
+
+        switch(true) {
+            case ((0x7F & $bytes) == $bytes):
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x7F & $bytes);
+
+            case (0x07FF & $bytes) == $bytes:
+                // return a 2-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xC0 | (($bytes >> 6) & 0x1F))
+                     . chr(0x80 | ($bytes & 0x3F));
+
+            case (0xFFFF & $bytes) == $bytes:
+                // return a 3-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xE0 | (($bytes >> 12) & 0x0F))
+                     . chr(0x80 | (($bytes >> 6) & 0x3F))
+                     . chr(0x80 | ($bytes & 0x3F));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }        
+
+   /**
+    * convert a string from one UTF-8 char to one UTF-16 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf8   UTF-8 character
+    * @return   string  UTF-16 character
+    * @access   private
+    */
+    function utf82utf16($utf8)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding'))
+            return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+        
+        switch(strlen($utf8)) {
+            case 1:
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return $ut8;
+
+            case 2:
+                // return a UTF-16 character from a 2-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x07 & (ord($utf8{0}) >> 2))
+                     . chr((0xC0 & (ord($utf8{0}) << 6))
+                         | (0x3F & ord($utf8{1})));
+                
+            case 3:
+                // return a UTF-16 character from a 3-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr((0xF0 & (ord($utf8{0}) << 4))
+                         | (0x0F & (ord($utf8{1}) >> 2)))
+                     . chr((0xC0 & (ord($utf8{1}) << 6))
+                         | (0x7F & ord($utf8{2})));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }        
+
+   /**
+    * encodes an arbitrary variable into JSON format
+    *
+    * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
+    *                           see argument 1 to Services_JSON() above for array-parsing behavior.
+    *                           if var is a strng, note that encode() always expects it
+    *                           to be in ASCII or UTF-8 format!
+    *
+    * @return   string  JSON string representation of input var
+    * @access   public
+    */
+    function encode($var)
+    {
+        switch (gettype($var)) {
+            case 'boolean':
+                return $var ? 'true' : 'false';
+            
+            case 'NULL':
+                return 'null';
+            
+            case 'integer':
+                return (int) $var;
+                
+            case 'double':
+            case 'float':
+                return (float) $var;
+                
+            case 'string':
+                // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+                $ascii = '';
+                $strlen_var = strlen($var);
+
+               /*
+                * Iterate over every character in the string,
+                * escaping with a slash or encoding to UTF-8 where necessary
+                */
+                for ($c = 0; $c < $strlen_var; ++$c) {
+                    
+                    $ord_var_c = ord($var{$c});
+                    
+                    switch (true) {
+                        case $ord_var_c == 0x08:
+                            $ascii .= '\b';
+                            break;
+                        case $ord_var_c == 0x09:
+                            $ascii .= '\t';
+                            break;
+                        case $ord_var_c == 0x0A:
+                            $ascii .= '\n';
+                            break;
+                        case $ord_var_c == 0x0C:
+                            $ascii .= '\f';
+                            break;
+                        case $ord_var_c == 0x0D:
+                            $ascii .= '\r';
+                            break;
+
+                        case $ord_var_c == 0x22:
+                        case $ord_var_c == 0x2F:
+                        case $ord_var_c == 0x5C:
+                            // double quote, slash, slosh
+                            $ascii .= '\\'.$var{$c};
+                            break;
+                            
+                        case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+                            // characters U-00000000 - U-0000007F (same as ASCII)
+                            $ascii .= $var{$c};
+                            break;
+                        
+                        case (($ord_var_c & 0xE0) == 0xC0):
+                            // characters U-00000080 - U-000007FF, mask 110XXXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+                            $c += 1;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xF0) == 0xE0):
+                            // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}));
+                            $c += 2;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xF8) == 0xF0):
+                            // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}));
+                            $c += 3;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xFC) == 0xF8):
+                            // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}));
+                            $c += 4;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xFE) == 0xFC):
+                            // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}),
+                                         ord($var{$c + 5}));
+                            $c += 5;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+                    }
+                }
+                
+                return '"'.$ascii.'"';
+                
+            case 'array':
+               /*
+                * As per JSON spec if any array key is not an integer
+                * we must treat the the whole array as an object. We
+                * also try to catch a sparsely populated associative
+                * array with numeric keys here because some JS engines
+                * will create an array with empty indexes up to
+                * max_index which can cause memory issues and because
+                * the keys, which may be relevant, will be remapped
+                * otherwise.
+                * 
+                * As per the ECMA and JSON specification an object may
+                * have any string as a property. Unfortunately due to
+                * a hole in the ECMA specification if the key is a
+                * ECMA reserved word or starts with a digit the
+                * parameter is only accessible using ECMAScript's
+                * bracket notation.
+                */
+                
+                // treat as a JSON object  
+                if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+                    return '{' .
+                           join(',', array_map(array($this, 'name_value'),
+                                               array_keys($var),
+                                               array_values($var)))
+                           . '}';
+                }
+
+                // treat it like a regular array
+                return '[' . join(',', array_map(array($this, 'encode'), $var)) . ']';
+                
+            case 'object':
+                $vars = get_object_vars($var);
+                return '{' .
+                       join(',', array_map(array($this, 'name_value'),
+                                           array_keys($vars),
+                                           array_values($vars)))
+                       . '}';
+
+            default:
+                return '';
+        }
+    }
+    
+   /**
+    * array-walking function for use in generating JSON-formatted name-value pairs
+    *
+    * @param    string  $name   name of key to use
+    * @param    mixed   $value  reference to an array element to be encoded
+    *
+    * @return   string  JSON-formatted name-value pair, like '"name":value'
+    * @access   private
+    */
+    function name_value($name, $value)
+    {
+        return $this->encode(strval($name)) . ':' . $this->encode($value);
+    }        
+
+   /**
+    * reduce a string by removing leading and trailing comments and whitespace
+    *
+    * @param    $str    string      string value to strip of comments and whitespace
+    *
+    * @return   string  string value stripped of comments and whitespace
+    * @access   private
+    */
+    function reduce_string($str)
+    {
+        $str = preg_replace(array(
+        
+                // eliminate single line comments in '// ...' form
+                '#^\s*//(.+)$#m',
+    
+                // eliminate multi-line comments in '/* ... */' form, at start of string
+                '#^\s*/\*(.+)\*/#Us',
+    
+                // eliminate multi-line comments in '/* ... */' form, at end of string
+                '#/\*(.+)\*/\s*$#Us'
+    
+            ), '', $str);
+        
+        // eliminate extraneous space
+        return trim($str);
+    }
+
+   /**
+    * decodes a JSON string into appropriate variable
+    *
+    * @param    string  $str    JSON-formatted string
+    *
+    * @return   mixed   number, boolean, string, array, or object
+    *                   corresponding to given JSON input string.
+    *                   See argument 1 to Services_JSON() above for object-output behavior.
+    *                   Note that decode() always returns strings
+    *                   in ASCII or UTF-8 format!
+    * @access   public
+    */
+    function decode($str)
+    {
+        $str = $this->reduce_string($str);
+    
+        switch (strtolower($str)) {
+            case 'true':
+                return true;
+
+            case 'false':
+                return false;
+            
+            case 'null':
+                return null;
+            
+            default:
+                if (is_numeric($str)) {
+                    // Lookie-loo, it's a number
+
+                    // This would work on its own, but I'm trying to be
+                    // good about returning integers where appropriate:
+                    // return (float)$str;
+
+                    // Return float or int, as appropriate
+                    return ((float)$str == (integer)$str)
+                        ? (integer)$str
+                        : (float)$str;
+                    
+                } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
+                    // STRINGS RETURNED IN UTF-8 FORMAT
+                    $delim = substr($str, 0, 1);
+                    $chrs = substr($str, 1, -1);
+                    $utf8 = '';
+                    $strlen_chrs = strlen($chrs);
+                    
+                    for ($c = 0; $c < $strlen_chrs; ++$c) {
+                    
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                        $ord_chrs_c = ord($chrs{$c});
+                        
+                        switch (true) {
+                            case $substr_chrs_c_2 == '\b':
+                                $utf8 .= chr(0x08);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\t':
+                                $utf8 .= chr(0x09);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\n':
+                                $utf8 .= chr(0x0A);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\f':
+                                $utf8 .= chr(0x0C);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\r':
+                                $utf8 .= chr(0x0D);
+                                ++$c;
+                                break;
+
+                            case $substr_chrs_c_2 == '\\"':
+                            case $substr_chrs_c_2 == '\\\'':
+                            case $substr_chrs_c_2 == '\\\\':
+                            case $substr_chrs_c_2 == '\\/':
+                                if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
+                                   ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
+                                    $utf8 .= $chrs{++$c};
+                                }
+                                break;
+                                
+                            case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
+                                // single, escaped unicode character
+                                $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
+                                       . chr(hexdec(substr($chrs, ($c + 4), 2)));
+                                $utf8 .= $this->utf162utf8($utf16);
+                                $c += 5;
+                                break;
+        
+                            case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
+                                $utf8 .= $chrs{$c};
+                                break;
+        
+                            case ($ord_chrs_c & 0xE0) == 0xC0:
+                                // characters U-00000080 - U-000007FF, mask 110XXXXX
+                                //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 2);
+                                ++$c;
+                                break;
+    
+                            case ($ord_chrs_c & 0xF0) == 0xE0:
+                                // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 3);
+                                $c += 2;
+                                break;
+    
+                            case ($ord_chrs_c & 0xF8) == 0xF0:
+                                // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 4);
+                                $c += 3;
+                                break;
+    
+                            case ($ord_chrs_c & 0xFC) == 0xF8:
+                                // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 5);
+                                $c += 4;
+                                break;
+    
+                            case ($ord_chrs_c & 0xFE) == 0xFC:
+                                // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 6);
+                                $c += 5;
+                                break;
+
+                        }
+
+                    }
+                    
+                    return $utf8;
+                
+                } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
+                    // array, or object notation
+
+                    if ($str{0} == '[') {
+                        $stk = array(SERVICES_JSON_IN_ARR);
+                        $arr = array();
+                    } else {
+                        if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = array();
+                        } else {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = new stdClass();
+                        }
+                    }
+                    
+                    array_push($stk, array('what'  => SERVICES_JSON_SLICE,
+                                           'where' => 0,
+                                           'delim' => false));
+
+                    $chrs = substr($str, 1, -1);
+                    $chrs = $this->reduce_string($chrs);
+                    
+                    if ($chrs == '') {
+                        if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                            return $arr;
+
+                        } else {
+                            return $obj;
+
+                        }
+                    }
+
+                    //print("\nparsing {$chrs}\n");
+                    
+                    $strlen_chrs = strlen($chrs);
+                    
+                    for ($c = 0; $c <= $strlen_chrs; ++$c) {
+                    
+                        $top = end($stk);
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                    
+                        if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
+                            // found a comma that is not inside a string, array, etc.,
+                            // OR we've reached the end of the character list
+                            $slice = substr($chrs, $top['where'], ($c - $top['where']));
+                            array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
+                            //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                            if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                                // we are in an array, so just push an element onto the stack
+                                array_push($arr, $this->decode($slice));
+
+                            } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                                // we are in an object, so figure
+                                // out the property name and set an
+                                // element in an associative array,
+                                // for now
+                                if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // "name":value pair
+                                    $key = $this->decode($parts[1]);
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // name:value pair, where name is unquoted
+                                    $key = $parts[1];
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use == SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                }
+
+                            }
+
+                        } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
+                            // found a quote, and we are not inside a string
+                            array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
+                            //print("Found start of string at {$c}\n");
+
+                        } elseif (($chrs{$c} == $top['delim']) &&
+                                 ($top['what'] == SERVICES_JSON_IN_STR) &&
+                                 (($chrs{$c - 1} != '\\') ||
+                                 ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) {
+                            // found a quote, we're in a string, and it's not escaped
+                            array_pop($stk);
+                            //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '[') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-bracket, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
+                            //print("Found start of array at {$c}\n");
+
+                        } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
+                            // found a right-bracket, and we're in an array
+                            array_pop($stk);
+                            //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '{') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-brace, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
+                            //print("Found start of object at {$c}\n");
+
+                        } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
+                            // found a right-brace, and we're in an object
+                            array_pop($stk);
+                            //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($substr_chrs_c_2 == '/*') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a comment start, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
+                            $c++;
+                            //print("Found start of comment at {$c}\n");
+
+                        } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
+                            // found a comment end, and we're in one now
+                            array_pop($stk);
+                            $c++;
+                            
+                            for ($i = $top['where']; $i <= $c; ++$i)
+                                $chrs = substr_replace($chrs, ' ', $i, 1);
+                            
+                            //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        }
+                    
+                    }
+                    
+                    if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                        return $arr;
+
+                    } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                        return $obj;
+
+                    }
+                
+                }
+        }
+    }
+    
+}
+    
+?>
\ No newline at end of file
diff --git a/dojox/rpc/tests/resources/bigQuery b/dojox/rpc/tests/resources/bigQuery
new file mode 100644
index 0000000..e8f9429
--- /dev/null
+++ b/dojox/rpc/tests/resources/bigQuery
@@ -0,0 +1 @@
+[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
\ No newline at end of file
diff --git a/dojox/rpc/tests/resources/bigQuery5 b/dojox/rpc/tests/resources/bigQuery5
new file mode 100644
index 0000000..e77ca8d
--- /dev/null
+++ b/dojox/rpc/tests/resources/bigQuery5
@@ -0,0 +1 @@
+[1,2,3,4,5]
\ No newline at end of file
diff --git a/dojox/rpc/tests/resources/echo.php b/dojox/rpc/tests/resources/echo.php
new file mode 100644
index 0000000..2f0762d
--- /dev/null
+++ b/dojox/rpc/tests/resources/echo.php
@@ -0,0 +1,11 @@
+<?php
+	// ensure that we don't try to send "html" down to the client
+	header("Content-Type: text/plain");
+
+	if (!$_REQUEST["message"]){
+		print "ERROR: message property not found";
+	}else{
+		//Escape it, just to be safe
+		print htmlentities($_REQUEST["message"]);
+	}
+?>
diff --git a/dojox/rpc/tests/resources/echoJson.php b/dojox/rpc/tests/resources/echoJson.php
new file mode 100644
index 0000000..52b5d03
--- /dev/null
+++ b/dojox/rpc/tests/resources/echoJson.php
@@ -0,0 +1,8 @@
+<?php
+	if (!$_REQUEST["message"]){
+		print "ERROR: message property not found";
+	}else{
+		header("Content-Type: application/json");
+		print $_REQUEST["message"];
+	}
+?>
diff --git a/dojox/rpc/tests/resources/fakestore.php b/dojox/rpc/tests/resources/fakestore.php
new file mode 100644
index 0000000..12c24ab
--- /dev/null
+++ b/dojox/rpc/tests/resources/fakestore.php
@@ -0,0 +1,38 @@
+<?php
+	session_start();
+	header("Content-Type: " . ($_SERVER["CONTENT_TYPE"] == 'application/json' ? 'application/json' : 'text/plain'));
+
+	$fn = preg_replace("/\W/","",$_REQUEST["location"]);
+	switch ($_SERVER["REQUEST_METHOD"]) {
+		case "GET" :
+			if (isset($_SESSION[$fn])) {
+				print($_SESSION[$fn]);
+			}
+			else {
+				$fh = fopen($fn, 'r');
+				print(fread($fh, filesize($fn)));
+				fclose($fh);
+			}
+			break;
+		case "PUT" :
+			$contents = file_get_contents('php://input');
+			print($contents);
+			$_SESSION[$fn]=$contents;
+			break;
+		case "POST" :
+			if (isset($_SESSION[$fn])) {
+				$old = $_SESSION[$fn];
+			}
+			else {
+				$fh = fopen($fn, 'r');
+				$old = fread($fh, filesize($fn));
+				fclose($fh);
+			}
+			$contents = file_get_contents('php://input');
+			$_SESSION[$fn]=$old . $contents;
+			break;
+		case "DELETE" :
+			$_SESSION[$fn]="deleted";
+			break;
+	}
+?>
diff --git a/dojox/rpc/tests/resources/jsonRpc10.php b/dojox/rpc/tests/resources/jsonRpc10.php
new file mode 100644
index 0000000..232ec90
--- /dev/null
+++ b/dojox/rpc/tests/resources/jsonRpc10.php
@@ -0,0 +1,47 @@
+<?php
+	require_once("./JSON.php");
+
+	// FIXME: doesn't look like we really need Pear at all
+	// which decreases the testing burden.
+	// Commenting out.the require and the new File() call.
+
+	// NOTE: File.php is installed via Pear using:
+	//	%> sudo pear install File
+	// Your server will also need the Pear library directory included in PHP's
+	// include_path configuration directive
+	// require_once('File.php');
+
+	// ensure that we don't try to send "html" down to the client
+	header("Content-Type: application/json");
+
+	$json = new Services_JSON;
+	//$fp = new File();
+
+	$results = array();
+	$results['error'] = null;
+
+	$jsonRequest = file_get_contents('php://input');
+	//$jsonRequest = '{"params":["Blah"],"method":"myecho","id":86}';
+
+	$req = $json->decode($jsonRequest);
+
+	$method = $req->method;
+	$params = $req->params;
+
+	switch($method) {
+		case "postJsonRpc10EchoNamed":
+		case "postJsonRpc10Echo":
+			$results['result']=$params[0];
+			break;
+		default:
+			$results['result']="";
+			$results['error']="JSON-RPC 1.0 METHOD NOT FOUND";
+			break;
+	}
+
+	$results['id'] = $req->id;
+
+	$encoded = $json->encode($results);
+
+	print $encoded;
+?>
diff --git a/dojox/rpc/tests/resources/jsonRpc11.php b/dojox/rpc/tests/resources/jsonRpc11.php
new file mode 100644
index 0000000..3c4f277
--- /dev/null
+++ b/dojox/rpc/tests/resources/jsonRpc11.php
@@ -0,0 +1,52 @@
+<?php
+	require_once("./JSON.php");
+
+	// FIXME: doesn't look like we really need Pear at all
+	// which decreases the testing burden.
+	// Commenting out.the require and the new File() call.
+
+	// NOTE: File.php is installed via Pear using:
+	//	%> sudo pear install File
+	// Your server will also need the Pear library directory included in PHP's
+	// include_path configuration directive
+	// require_once('File.php');
+
+	// ensure that we don't try to send "html" down to the client
+	header("Content-Type: application/json");
+
+	$json = new Services_JSON;
+	//$fp = new File();
+
+	$results = array();
+	$results['error'] = null;
+
+	$jsonRequest = file_get_contents('php://input');
+	//$jsonRequest = '{"params":["Blah"],"method":"myecho","id":86}';
+
+	$req = $json->decode($jsonRequest);
+
+	$method = $req->method;
+	$params = $req->params;
+
+	switch($method) {
+		case "rawPostJsonRpc11Echo":
+			if (is_array($params)){
+				$results['result']=$params;
+			}else{
+				$results['result']=$params->message;
+			}
+			break;
+		default:
+			$results['result']="";
+			$results['error']=array();
+			$results['error']['code']=-32601;
+			$results['error']["message"]="The requested remote-procedure does not exist / is not available.";
+			break;
+	}
+
+	$results['id'] = $req->id;
+
+	$encoded = $json->encode($results);
+
+	print $encoded;
+?>
diff --git a/dojox/rpc/tests/resources/jsonRpc12.php b/dojox/rpc/tests/resources/jsonRpc12.php
new file mode 100644
index 0000000..a3212f9
--- /dev/null
+++ b/dojox/rpc/tests/resources/jsonRpc12.php
@@ -0,0 +1,54 @@
+<?php
+	require_once("./JSON.php");
+
+	// FIXME: doesn't look like we really need Pear at all
+	// which decreases the testing burden.
+	// Commenting out.the require and the new File() call.
+
+	// NOTE: File.php is installed via Pear using:
+	//	%> sudo pear install File
+	// Your server will also need the Pear library directory included in PHP's
+	// include_path configuration directive
+	// require_once('File.php');
+
+	// ensure that we don't try to send "html" down to the client
+	header("Content-Type: application/json");
+
+	$json = new Services_JSON;
+	//$fp = new File();
+
+	$results = array();
+	$results['error'] = null;
+
+	$jsonRequest = file_get_contents('php://input');
+	//$jsonRequest = '{"params":["Blah"],"method":"myecho","id":86}';
+
+	$req = $json->decode($jsonRequest);
+
+	$method = $req->method;
+	$params = $req->params;
+
+	switch($method) {
+		case "postJsonRpc12Echo":
+		case "postJsonRpc12EchoNamed":
+			if (is_array($params)){
+				$results['result']=$params;
+			}else{
+				$results['result']=$params->message;
+			}
+			break;
+		default:
+			$results['result']="";
+			$results['error']=array();
+			$results['error']['code']=-32601;
+			$results['error']["message"]="The requested remote-procedure does not exist / is not available.";
+			header('HTTP/1.1 500 Server Error');
+			break;
+	}
+
+	$results['id'] = $req->id;
+
+	$encoded = $json->encode($results);
+
+	print $encoded;
+?>
diff --git a/dojox/rpc/tests/resources/jsonRpcPostGetEcho.php b/dojox/rpc/tests/resources/jsonRpcPostGetEcho.php
new file mode 100644
index 0000000..110d27f
--- /dev/null
+++ b/dojox/rpc/tests/resources/jsonRpcPostGetEcho.php
@@ -0,0 +1,41 @@
+<?php
+	// ensure that we don't try to send "html" down to the client
+	header("Content-Type: application/json");
+
+	require_once("./JSON.php");
+
+	$json = new Services_JSON;
+	$method = $_REQUEST["method"];
+	$id = $_REQUEST["id"];
+	$params = $_REQUEST["params"];
+	$result = "";
+
+	switch ($method){
+		case "postJsonRpc10Echo":
+		case "getJsonRpc10Echo":
+		case "postJsonRpc10EchoNamed":
+		case "getJsonRpc10EchoNamed":
+			$p = $json->decode($params);
+			$result = "{id:" . $id . ", 'result':'" . $p[0]. "', error:''}";
+			break;
+		case "postJsonRpc12Echo":
+		case "getJsonRpc12Echo":
+		case "postJsonRpc12EchoNamed":
+		case "getJsonRpc12EchoNamed":
+			$p = $json->decode($params);
+
+			if ($p->message){
+				$d = $p->message;
+			}else{
+				$d=$p[0];
+			}
+			$result = "{id:" . $id . ", 'result':'" . $d . "'}";
+			break;
+		default:
+			$result = "{id:'1','error':'Unknown Method', 'result':'this result only here for this test, shouldnt be here in real code'}";
+			break;
+	}
+
+	print $result;
+
+?>
diff --git a/dojox/rpc/tests/resources/jsonpEcho.php b/dojox/rpc/tests/resources/jsonpEcho.php
new file mode 100644
index 0000000..3998156
--- /dev/null
+++ b/dojox/rpc/tests/resources/jsonpEcho.php
@@ -0,0 +1,26 @@
+<?php
+	// ensure that we don't try to send "html" down to the client
+	header("Content-Type: application/json");
+
+	$jsonp = false;
+	$result = "";
+
+	if ($_REQUEST["testCallbackParam"]){
+		$jsonp=true;
+		$result .= $_REQUEST['testCallbackParam'] . "('";
+	}
+
+	if (!$_REQUEST["message"]){
+		$result .= "ERROR: message property not found";
+	}
+
+	$result .= $_REQUEST["message"];
+
+	if ($jsonp) {
+		$result .= "');";
+	}
+
+	print $result;
+
+
+?>
diff --git a/dojox/rpc/tests/resources/jsonpEcho.phps b/dojox/rpc/tests/resources/jsonpEcho.phps
new file mode 100644
index 0000000..3998156
--- /dev/null
+++ b/dojox/rpc/tests/resources/jsonpEcho.phps
@@ -0,0 +1,26 @@
+<?php
+	// ensure that we don't try to send "html" down to the client
+	header("Content-Type: application/json");
+
+	$jsonp = false;
+	$result = "";
+
+	if ($_REQUEST["testCallbackParam"]){
+		$jsonp=true;
+		$result .= $_REQUEST['testCallbackParam'] . "('";
+	}
+
+	if (!$_REQUEST["message"]){
+		$result .= "ERROR: message property not found";
+	}
+
+	$result .= $_REQUEST["message"];
+
+	if ($jsonp) {
+		$result .= "');";
+	}
+
+	print $result;
+
+
+?>
diff --git a/dojox/rpc/tests/resources/jsonpJsonRpcEcho.php b/dojox/rpc/tests/resources/jsonpJsonRpcEcho.php
new file mode 100644
index 0000000..be7ef3e
--- /dev/null
+++ b/dojox/rpc/tests/resources/jsonpJsonRpcEcho.php
@@ -0,0 +1,40 @@
+<?php
+	// ensure that we don't try to send "html" down to the client
+	header("Content-Type: application/json");
+
+        require_once("./JSON.php");
+        $json = new Services_JSON;
+
+	$id = $_REQUEST['id'];
+	$method = $_REQUEST['method'];
+	$params = $json->decode($_REQUEST['params']);
+	$callback = $_REQUEST["callback"];
+
+	switch($method){
+		case "jsonpJsonRpc10EchoNamed":
+		case "jsonpJsonRpc11Echo":
+		case "jsonpJsonRpc11EchoNamed":
+		case "jsonpJsonRpc10Echo":
+			if ( ($method=="jsonpJsonRpc10EchoNamed")||($method=="jsonpJsonRpc11EchoNamed")){
+				$message = $params->message;
+			}else{
+				$message = $params[0];
+			}
+			if ($message){
+				switch($method){
+					case "jsonpJsonRpc11Echo":
+					case "jsonpJsonRpc11EchoNamed":
+						$res = "{'id': '$id', result: '$message'}";
+						break;
+					default:
+						$res = "{'id': '$id', result: '$message', 'error':''}";
+						break;
+				}
+			}else{
+				$res = "{'id': '$id', error: {'code': 100, 'message':'no message provided'}}";
+			}
+	}
+
+	print "$callback($res)";
+
+?>
diff --git a/dojox/rpc/tests/resources/obj1 b/dojox/rpc/tests/resources/obj1
new file mode 100644
index 0000000..ff02ba8
--- /dev/null
+++ b/dojox/rpc/tests/resources/obj1
@@ -0,0 +1 @@
+{"id":"obj1","name":"Object 1","updated":1202755814406,"obj":{"foo":"bar"},"obj dup":{"$ref":"obj1.obj"},"testArray":[1,2,3,4]}
\ No newline at end of file
diff --git a/dojox/rpc/tests/resources/obj1lazyValue b/dojox/rpc/tests/resources/obj1lazyValue
new file mode 100644
index 0000000..6e6f460
--- /dev/null
+++ b/dojox/rpc/tests/resources/obj1lazyValue
@@ -0,0 +1 @@
+"Finally loaded"
\ No newline at end of file
diff --git a/dojox/rpc/tests/resources/obj1testArray b/dojox/rpc/tests/resources/obj1testArray
new file mode 100644
index 0000000..0c624c1
--- /dev/null
+++ b/dojox/rpc/tests/resources/obj1testArray
@@ -0,0 +1 @@
+[1,2,3,undefined,4]
\ No newline at end of file
diff --git a/dojox/rpc/tests/resources/obj3 b/dojox/rpc/tests/resources/obj3
new file mode 100644
index 0000000..21cb328
--- /dev/null
+++ b/dojox/rpc/tests/resources/obj3
@@ -0,0 +1 @@
+{"id":"obj3","name":"Object 3"}
\ No newline at end of file
diff --git a/dojox/rpc/tests/resources/obj4 b/dojox/rpc/tests/resources/obj4
new file mode 100644
index 0000000..a429ecf
--- /dev/null
+++ b/dojox/rpc/tests/resources/obj4
@@ -0,0 +1 @@
+{"id":"obj4","name":"Object 4"}
\ No newline at end of file
diff --git a/dojox/rpc/tests/resources/query b/dojox/rpc/tests/resources/query
new file mode 100644
index 0000000..52ce785
--- /dev/null
+++ b/dojox/rpc/tests/resources/query
@@ -0,0 +1,6 @@
+[
+	{id:"obj1",name:"Object 1","lazyValue":{$ref:"obj1.lazyValue"}}, 
+	{id:"obj2",name:"Object 2"},
+	{$ref:"obj3"}, 
+	{$ref:"obj4"}
+]
\ No newline at end of file
diff --git a/dojox/rpc/tests/resources/rawEcho.php b/dojox/rpc/tests/resources/rawEcho.php
new file mode 100644
index 0000000..c8ee9a2
--- /dev/null
+++ b/dojox/rpc/tests/resources/rawEcho.php
@@ -0,0 +1,8 @@
+<?php
+		// ensure that we don't try to send "html" down to the client
+		header("Content-Type: application/json");
+
+        print file_get_contents('php://input');
+
+?>
+
diff --git a/dojox/rpc/tests/resources/res b/dojox/rpc/tests/resources/res
new file mode 100644
index 0000000..3c22137
--- /dev/null
+++ b/dojox/rpc/tests/resources/res
@@ -0,0 +1 @@
+deleted
\ No newline at end of file
diff --git a/dojox/rpc/tests/resources/test.smd b/dojox/rpc/tests/resources/test.smd
new file mode 100644
index 0000000..3c6a687
--- /dev/null
+++ b/dojox/rpc/tests/resources/test.smd
@@ -0,0 +1,207 @@
+(window["http://localhost/dojox/rpc/tests/resources/test.smd"]||function(val){return val}) (
+{
+	transport: "POST",
+	envelope: "URL",
+	strictParameters: false,
+	parameters: {
+                appId: {},
+                outputType: {
+                        "default": "json"
+                },
+
+                ignoreErrors: {
+                        optional: true
+                }
+        },
+
+        services: {
+                postEcho: {
+                        target: "echo.php",
+                        parameters: [
+                                {name: "message", type: "string", optional: true}
+                        ]
+                },
+
+                getEcho: {
+					transport: "GET",
+                        target: "echo.php",
+
+                        parameters: [
+                                {name: "message", type: "string", optional: true}
+                        ]
+                },
+	            "namespace.getEcho": {
+					transport: "GET",
+                        target: "echo.php",
+
+                        parameters: [
+                                {name: "message", type: "string", optional: true}
+                        ]
+                },
+                getEchoJson: {
+			transport: "GET",
+                        target: "echoJson.php",
+			contentType:"application/json",
+                        parameters: [
+                                {name: "message", type: "string", optional: true}
+                        ]
+                },
+                getPathEcho: {
+			transport: "GET",
+			envelope: "PATH",
+			target: "echo.php?message=",
+
+			parameters: [
+                                {name: "message", type: "string", optional: true}
+                        ]
+                },
+		restStore: {
+			transport: "REST",
+			contentType:"text/plain",
+			preventCache: true,
+			target: "fakestore.php", 
+                        parameters: [
+                                {name: "location", type: "string", optional: true}
+                        ]
+                },
+		jsonRestStore: {
+				transport: "REST",
+                        target: "fakestore.php",
+						contentType:"application/json",
+                        parameters: [
+                                {name: "location", type: "string", optional: true}
+                        ],
+                        returns: {
+                        	properties:{
+	                        	name:{
+	                        		type:"string",
+	                        		minLength:3
+	                    		}
+                    		}
+                        }
+                },
+
+
+
+                postJsonEcho: {
+			transport: "POST",
+			envelope: "JSON",
+                        target: "rawEcho.php",
+
+                        parameters: [
+                                {name: "message", type: "string", optional: true}
+                        ]
+                },
+
+                jsonpEcho: {
+			transport: "JSONP",
+                        target: "jsonpEcho.php",
+			callbackParamName: "testCallbackParam",
+
+                        parameters: [
+                                {name: "message", type: "string", optional: true}
+                        ]
+                },
+
+                postJsonRpc10Echo: {
+			transport: "POST",
+			envelope: "JSON-RPC-1.0",
+			target: "jsonRpc10.php",
+
+                        parameters: [
+                                {type: "string", optional: true}
+                        ]
+                },
+
+                postJsonRpc10EchoNamed: {
+			transport: "POST",
+			envelope: "JSON-RPC-1.0",
+			target: "jsonRpc10.php",
+
+                        parameters: [
+                                {type: "string", optional: true}
+                        ]
+                },
+
+                jsonpJsonRpc12Echo: {
+			transport: "JSONP",
+			envelope: "JSON-RPC-2.0",
+			target: "jsonpJsonRpcEcho.php",
+
+                        parameters: [
+                                {type: "string", optional: true}
+                        ]
+                },
+
+                jsonpJsonRpc12EchoNamed: {
+			transport: "JSONP",
+			envelope: "JSON-RPC-2.0",
+			target: "jsonpJsonRpcEcho.php",
+
+                        parameters: [
+                                {name: "message", type: "string", optional: true}
+                        ]
+                },
+
+                postJsonRpc10ForcedError: {
+			envelope: "JSON-RPC-1.0",
+			transport: "POST",
+			target: "jsonRpc10.php",
+
+                        parameters: [
+                                {type: "string", optional: true}
+                        ]
+                },
+
+                postJsonRpc12Echo: {
+			transport: "POST",
+			envelope: "JSON-RPC-2.0",
+			target: "jsonRpc12.php",
+
+                        parameters: [
+                                {name: "message", type: "string", optional: true}
+                        ]
+                },
+
+                getJsonRpc12Echo: {
+			transport: "GET",
+			envelope: "JSON-RPC-2.0",
+			target: "jsonRpcPostGetEcho.php",
+
+                        parameters: [
+                                {type: "string", optional: true}
+                        ]
+                },
+
+                postJsonRpc12EchoNamed: {
+			transport: "POST",
+			envelope: "JSON-RPC-2.0",
+			target: "jsonRpcPostGetEcho.php",
+
+                        parameters: [
+                                {type: "string", optional: true}
+                        ]
+                },
+
+                getJsonRpc12EchoNamed: {
+			transport: "GET",
+			envelope: "JSON-RPC-2.0",
+			target: "jsonRpcPostGetEcho.php",
+
+                        parameters: [
+                                {type: "string", optional: true}
+                        ]
+                },
+
+
+                postJsonRpc12ForcedError: {
+			envelope: "JSON-RPC-2.0",
+			transport: "POST",
+			target: "jsonRpc12.php",
+
+                        parameters: [
+                                {type: "string", optional: true}
+                        ]
+                }
+	}	
+})
diff --git a/dojox/rpc/tests/runLibraryTests.html b/dojox/rpc/tests/runLibraryTests.html
new file mode 100644
index 0000000..25c88a7
--- /dev/null
+++ b/dojox/rpc/tests/runLibraryTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.rpc.tests.libraryTests"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/rpc/tests/runTests.html b/dojox/rpc/tests/runTests.html
new file mode 100644
index 0000000..bb937c6
--- /dev/null
+++ b/dojox/rpc/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.rpc.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/rpc/tests/stores/JsonRestStore.js b/dojox/rpc/tests/stores/JsonRestStore.js
new file mode 100644
index 0000000..d89cf25
--- /dev/null
+++ b/dojox/rpc/tests/stores/JsonRestStore.js
@@ -0,0 +1,233 @@
+dojo.provide("dojox.data.tests.stores.JsonRestStore");
+dojo.require("dojox.data.JsonRestStore");
+dojo.require("dojo.data.api.Read");
+dojo.require("dojox.rpc.Service");
+
+dojox.data.tests.stores.JsonRestStore.error = function(t, d, errData){
+	//  summary:
+	//		The error callback function to be used for all of the tests.
+	d.errback(errData);	
+}
+var testServices = new dojox.rpc.Service(dojo.moduleUrl("dojox.rpc.tests.resources", "test.smd"));
+var jsonStore = new dojox.data.JsonRestStore({service:testServices.jsonRestStore});
+
+doh.register("dojox.data.tests.stores.JsonRestStore", 
+	[
+		{
+			name: "Fetch some items",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonRestStore of a simple query.
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"query", 
+					onComplete: function(items, request){
+						t.is(4, items.length);
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "fetch by id",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Simple test of a basic fetch on JsonRestStore of a single item.
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"obj1", 
+					onComplete: function(item, request){
+						t.is("Object 1", item.name);
+						t.t(jsonStore.hasAttribute(item,"name"));
+						t.is(jsonStore.getValues(item,"name").length,1);
+						t.t(jsonStore.isItem(item));
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "Modify,save, check by id",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		Fetch an item from a query, modify and save it, and check to see if it was modified correctly
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"query", 
+					onComplete: function(items, request){
+						var now = new Date().getTime();
+						jsonStore.setValue(items[0],"updated",now);
+						jsonStore.setValue(items[0],"obj",{foo:'bar'});
+						jsonStore.setValue(items[0],"obj dup",items[0].obj);
+						jsonStore.setValue(items[0],"testArray",[1,2,3,4]);
+						jsonStore.save();
+						jsonStore.fetch({query:"obj1",
+							onComplete: function(item, request){
+								t.is("Object 1", item.name);
+								t.is(now, item.updated);
+								t.is("bar", item.obj.foo);
+								t.is(item.obj, item['obj dup']);
+								d.callback(true);
+							},
+							onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)});
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "Post, delete, and put",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		append/post an item, delete it, sort the lists, resort the list, saving each time.
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"obj1", 
+					onComplete: function(item, request){
+						var now = new Date().getTime();
+						var testArray = item.testArray;
+						var newObject = {"name":"new object"};
+						testArray.push(newObject);
+						jsonStore.save();
+						jsonStore.deleteItem(newObject,{parent:testArray});
+						jsonStore.save();
+						testArray.sort(function(obj1,obj2) { return obj1 < obj2; });
+						jsonStore.save();
+						testArray.sort(function(obj1,obj2) { return obj1 > obj2; });
+						jsonStore.save();
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "Revert",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		append/post an item, delete it, sort the lists, resort the list, saving each time.
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"obj1", 
+					onComplete: function(item, request){
+						jsonStore.setValue(item,"name","new name");
+						jsonStore.setValue(item,"newProp","new value");
+						jsonStore.unsetAttribute(item,"updated");
+						t.is(jsonStore.getValue(item,"name"),"new name");
+						t.is(jsonStore.getValue(item,"newProp"),"new value");
+						t.is(jsonStore.getValue(item,"updated"),undefined);
+						jsonStore.revert();
+						t.is(jsonStore.getValue(item,"name"),"Object 1");
+						t.is(jsonStore.getValue(item,"newProp"),undefined);
+						t.t(typeof jsonStore.getValue(item,"updated") == 'number');
+						d.callback(true);
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "Lazy loading",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		test lazy loading
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"query", 
+					onComplete: function(items, request){
+						/*var item = jsonStore.getValue(items,2); // sync lazy loading
+						t.is(item.name == 'Object 3');*/
+						jsonStore.getValue(items,3,function(item) { // async lazy loading
+							t.is(item.name,'Object 4');
+							d.callback(true);
+						});
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)});
+				return d; //Object
+			}
+		},
+		{
+			name: "Array manipulation",
+			timeout:	10000, //10 seconds.
+			runTest: function(t) {
+				//	summary: 
+				//		test array manipulation
+				var d = new doh.Deferred();
+				jsonStore.fetch({query:"obj1", 
+					onComplete: function(item, request){
+						var testArray = item.testArray;
+						testArray.reverse();
+						testArray.unshift(testArray.pop());
+						jsonStore.onSave = function(data) {
+							t.is(data.length,1);						
+							d.callback(true);
+							jsonStore.onSave = function(){};
+						};
+						jsonStore.save();
+					},
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, doh, d)});
+				return d; //Object
+			}
+		},
+		
+		{
+			name: "ReadAPI:  Fetch_20_Streaming",
+			timeout:	10000, //10 seconds.  Json can sometimes be slow.
+			runTest: function(t) {
+				//	summary: 
+				//		fetching with paging
+
+				var d = new doh.Deferred();
+				var count = 0;
+
+				function onItem(item, requestObj){
+				  t.assertTrue(typeof item == 'number');
+				  count++;
+				}
+				function onComplete(items, request){
+					t.is(5, count);
+					
+					t.is(null, items);
+					d.callback(true);
+				}
+				//Get everything...
+				jsonStore.fetch({	
+					query: "bigQuery",
+					onBegin: null,
+					count: 5,
+					onItem: onItem,
+					onComplete: onComplete,
+					onError: dojo.partial(dojox.data.tests.stores.JsonRestStore.error, t, d)
+				});
+				return d; //Object
+			}
+		},
+		function testReadAPI_functionConformance(t){
+			//	summary: 
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+			//	description:
+			//		Simple test read API conformance.  Checks to see all declared functions are actual functions on the instances.
+
+			var readApi = new dojo.data.api.Read();
+			var passed = true;
+
+			for(i in readApi){
+				if(i.toString().charAt(0) !== '_')
+				{
+					var member = readApi[i];
+					//Check that all the 'Read' defined functions exist on the test store.
+					if(typeof member === "function"){
+						var testStoreMember = jsonStore	[i];
+						if(!(typeof testStoreMember === "function")){
+							passed = false;
+							break;
+						}
+					}
+				}
+			}
+		}
+	]
+);
+
diff --git a/dojox/secure/DOM.js b/dojox/secure/DOM.js
index 790c416..7423509 100644
--- a/dojox/secure/DOM.js
+++ b/dojox/secure/DOM.js
@@ -1,234 +1,257 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.secure.DOM"]){
-dojo._hasResource["dojox.secure.DOM"]=true;
 dojo.provide("dojox.secure.DOM");
 dojo.require("dojox.lang.observable");
-dojox.secure.DOM=function(_1){
-function _2(_3){
-if(!_3){
-return _3;
-}
-var _4=_3;
-do{
-if(_4==_1){
-return _5(_3);
-}
-}while((_4=_4.parentNode));
-return null;
-};
-function _5(_6){
-if(_6){
-if(_6.nodeType){
-var _7=_8(_6);
-if(_6.nodeType==1&&typeof _7.style=="function"){
-_7.style=_9(_6.style);
-_7.ownerDocument=_a;
-_7.childNodes={__get__:function(i){
-return _5(_6.childNodes[i]);
-},length:0};
-}
-return _7;
-}
-if(_6&&typeof _6=="object"){
-if(_6.__observable){
-return _6.__observable;
-}
-_7=_6 instanceof Array?[]:{};
-_6.__observable=_7;
-for(var i in _6){
-if(i!="__observable"){
-_7[i]=_5(_6[i]);
-}
-}
-_7.data__=_6;
-return _7;
-}
-if(typeof _6=="function"){
-var _b=function(_c){
-if(typeof _c=="function"){
-return function(){
-for(var i=0;i<arguments.length;i++){
-arguments[i]=_5(arguments[i]);
-}
-return _b(_c.apply(_5(this),arguments));
-};
-}
-return dojox.secure.unwrap(_c);
-};
-return function(){
-if(_6.safetyCheck){
-_6.safetyCheck.apply(_b(this),arguments);
-}
-for(var i=0;i<arguments.length;i++){
-arguments[i]=_b(arguments[i]);
-}
-return _5(_6.apply(_b(this),arguments));
-};
-}
-}
-return _6;
-};
-unwrap=dojox.secure.unwrap;
-function _d(_e){
-_e+="";
-if(_e.match(/behavior:|content:|javascript:|binding|expression|\@import/)){
-throw new Error("Illegal CSS");
-}
-var id=_1.id||(_1.id="safe"+(""+Math.random()).substring(2));
-return _e.replace(/(\}|^)\s*([^\{]*\{)/g,function(t,a,b){
-return a+" #"+id+" "+b;
-});
-};
-function _f(url){
-if(url.match(/:/)&&!url.match(/^(http|ftp|mailto)/)){
-throw new Error("Unsafe URL "+url);
-}
-};
-function _10(el){
-if(el&&el.nodeType==1){
-if(el.tagName.match(/script/i)){
-var src=el.src;
-if(src&&src!=""){
-el.parentNode.removeChild(el);
-dojo.xhrGet({url:src,secure:true}).addCallback(function(_11){
-_a.evaluate(_11);
-});
-}else{
-var _12=el.innerHTML;
-el.parentNode.removeChild(el);
-_5.evaluate(_12);
-}
-}
-if(el.tagName.match(/link/i)){
-throw new Error("illegal tag");
-}
-if(el.tagName.match(/style/i)){
-var _13=function(_14){
-if(el.styleSheet){
-el.styleSheet.cssText=_14;
-}else{
-var _15=doc.createTextNode(_14);
-if(el.childNodes[0]){
-el.replaceChild(_15,el.childNodes[0]);
-}else{
-el.appendChild(_15);
-}
-}
-};
-src=el.src;
-if(src&&src!=""){
-alert("src"+src);
-el.src=null;
-dojo.xhrGet({url:src,secure:true}).addCallback(function(_16){
-_13(_d(_16));
-});
-}
-_13(_d(el.innerHTML));
-}
-if(el.style){
-_d(el.style.cssText);
-}
-if(el.href){
-_f(el.href);
-}
-if(el.src){
-_f(el.src);
-}
-var _17,i=0;
-while((_17=el.attributes[i++])){
-if(_17.name.substring(0,2)=="on"&&_17.value!="null"&&_17.value!=""){
-throw new Error("event handlers not allowed in the HTML, they must be set with element.addEventListener");
-}
-}
-var _18=el.childNodes;
-for(var i=0,l=_18.length;i<l;i++){
-_10(_18[i]);
-}
-}
-};
-function _19(_1a){
-var div=document.createElement("div");
-if(_1a.match(/<object/i)){
-throw new Error("The object tag is not allowed");
-}
-div.innerHTML=_1a;
-_10(div);
-return div;
-};
-var doc=_1.ownerDocument;
-var _a={getElementById:function(id){
-return _2(doc.getElementById(id));
-},createElement:function(_1b){
-return _5(doc.createElement(_1b));
-},createTextNode:function(_1c){
-return _5(doc.createTextNode(_1c));
-},write:function(str){
-var div=_19(str);
-while(div.childNodes.length){
-_1.appendChild(div.childNodes[0]);
-}
-}};
-_a.open=_a.close=function(){
-};
-var _1d={innerHTML:function(_1e,_1f){
-_1e.innerHTML=_19(_1f).innerHTML;
-}};
-_1d.outerHTML=function(_20,_21){
-throw new Error("Can not set this property");
-};
-function _22(_23,_24){
-return function(_25,_26){
-_10(_26[_24]);
-return _25[_23](_26[0]);
-};
-};
-var _27={appendChild:_22("appendChild",0),insertBefore:_22("insertBefore",0),replaceChild:_22("replaceChild",1),cloneNode:function(_28,_29){
-return _28.cloneNode(_29[0]);
-},addEventListener:function(_2a,_2b){
-dojo.connect(_2a,"on"+_2b[0],this,function(_2c){
-_2c=_8(_2c||window.event);
-_2b[1].call(this,_2c);
-});
-}};
-_27.childNodes=_27.style=_27.ownerDocument=function(){
-};
-function _2d(_2e){
-return dojox.lang.makeObservable(function(_2f,_30){
-var _31;
-return _2f[_30];
-},_2e,function(_32,_33,_34,_35){
-for(var i=0;i<_35.length;i++){
-_35[i]=unwrap(_35[i]);
-}
-if(_27[_34]){
-return _5(_27[_34].call(_32,_33,_35));
-}
-return _5(_33[_34].apply(_33,_35));
-},_27);
-};
-var _8=_2d(function(_36,_37,_38){
-if(_1d[_37]){
-_1d[_37](_36,_38);
-}
-_36[_37]=_38;
-});
-var _39={behavior:1,MozBinding:1};
-var _9=_2d(function(_3a,_3b,_3c){
-if(!_39[_3b]){
-_3a[_3b]=_d(_3c);
-}
-});
-_5.safeHTML=_19;
-_5.safeCSS=_d;
-return _5;
+
+dojox.secure.DOM = function(element){
+	function safeNode(node){
+		if(!node){
+			return node;
+		}
+		var parent = node;
+		do {
+			if(parent == element){
+				return wrap(node);
+			}
+		} while((parent = parent.parentNode));
+		return null;
+	}
+	function wrap(result){
+		if(result){
+			if(result.nodeType){
+				// wrap the node
+				var wrapped = nodeObserver(result);
+				if(result.nodeType == 1 && typeof wrapped.style == 'function'){ // if it is a function, that means it is holding a slot for us, now we will override it
+					wrapped.style = styleObserver(result.style);
+					wrapped.ownerDocument = safeDoc;
+					wrapped.childNodes = {__get__:function(i){
+						return wrap(result.childNodes[i]);
+						},
+						length:0
+					};
+					//TODO: maybe add attributes
+				}
+				return wrapped;
+			}
+			if(result && typeof result == 'object'){
+				if(result.__observable){ 
+					// we have already wrapped it, this helps prevent circular/infinite loops
+					return result.__observable;
+				}
+				// wrap the node list
+				wrapped = result instanceof Array ? [] : {};
+				result.__observable = wrapped;
+				for(var i in result){
+					if (i != '__observable'){
+						wrapped[i] = wrap(result[i]);
+					}
+				}
+				wrapped.data__ = result;
+				
+				return wrapped;
+			}
+			if(typeof result == 'function'){
+				var unwrap = function(result){
+					if(typeof result == 'function'){
+						// if untrusted code passes a function to trusted code, we want the trusted code to be 
+						// able to execute it and have the arguments automatically wrapped 
+						return function(){
+							for (var i = 0; i < arguments.length; i++){
+								arguments[i] = wrap(arguments[i]);
+							}
+							return unwrap(result.apply(wrap(this),arguments));
+						}
+					}
+					return dojox.secure.unwrap(result);	
+				};
+				// when we wrap a function we make it so that we can untrusted code can execute 
+				// the function and the arguments will be unwrapped for the trusted code 
+				return function(){
+					if(result.safetyCheck){
+						result.safetyCheck.apply(unwrap(this),arguments);
+					}
+					for (var i = 0; i < arguments.length; i++){
+						arguments[i] = unwrap(arguments[i]);
+					}
+					return wrap(result.apply(unwrap(this),arguments));
+				}
+			}
+		}
+		return result;
+	}
+	unwrap = dojox.secure.unwrap;
+	
+	function safeCSS(css){
+		css += ''; // make sure it is a string
+		if(css.match(/behavior:|content:|javascript:|binding|expression|\@import/)){
+			throw new Error("Illegal CSS");
+		}
+		var id = element.id || (element.id = "safe" + ('' + Math.random()).substring(2));
+		return css.replace(/(\}|^)\s*([^\{]*\{)/g,function(t,a,b){ // put all the styles in the context of the id of the sandbox
+			return a + ' #' + id + ' ' + b; // need to remove body and html references something like: .replace(/body/g,''); but that would break mybody...
+		});
+	}
+	function safeURL(url){
+		// test a url to see if it is safe
+		if(url.match(/:/) && !url.match(/^(http|ftp|mailto)/)){ 
+			throw new Error("Unsafe URL " + url);
+		}
+	}
+	function safeElement(el){
+		// test an element to see if it is safe
+		if(el && el.nodeType == 1){
+			if(el.tagName.match(/script/i)){
+				var src = el.src;
+				if (src && src != ""){
+					// load the src and evaluate it safely
+					el.parentNode.removeChild(el);					
+					dojo.xhrGet({url:src,secure:true}).addCallback(function(result){
+						safeDoc.evaluate(result);
+					});
+				}
+				else{
+					//evaluate the script safely and remove it
+					var script = el.innerHTML;
+					el.parentNode.removeChild(el);
+					wrap.evaluate(script);
+				}
+			}
+			if(el.tagName.match(/link/i)){
+				throw new Error("illegal tag");
+			}
+			if(el.tagName.match(/style/i)){
+				var setCSS = function(cssStr){
+					if(el.styleSheet){// IE
+						el.styleSheet.cssText = cssStr;
+					} else {// w3c
+						var cssText = doc.createTextNode(cssStr);
+						if (el.childNodes[0]) 
+							el.replaceChild(cssText,el.childNodes[0])
+						else 
+							el.appendChild(cssText);
+					 }
+					
+				}
+				src = el.src;
+				if(src && src != ""){
+					alert('src' + src);
+					// try to load it by url and safely load it
+					el.src = null;
+					dojo.xhrGet({url:src,secure:true}).addCallback(function(result){
+						setCSS(safeCSS(result));
+					});
+				}
+				setCSS(safeCSS(el.innerHTML));
+			}
+			if(el.style){
+				safeCSS(el.style.cssText);
+			}
+			if(el.href){		
+				safeURL(el.href);
+			}		
+			if(el.src){
+				safeURL(el.src);
+			}
+			var attr,i = 0;
+			while ((attr=el.attributes[i++])){
+				if(attr.name.substring(0,2)== "on" && attr.value != "null" && attr.value != ""){ // must remove all the event handlers
+					throw new Error("event handlers not allowed in the HTML, they must be set with element.addEventListener");
+				}
+			}		
+			var children = el.childNodes;
+			for (var i =0, l = children.length; i < l; i++){
+				safeElement(children[i]);
+			}
+		}
+	}
+	function safeHTML(html){
+		var div = document.createElement("div");
+		if(html.match(/<object/i))
+			throw new Error("The object tag is not allowed");
+		div.innerHTML = html; // this is safe with an unattached node
+		safeElement(div);
+		return div;
+	}
+	var doc = element.ownerDocument;
+	var safeDoc = {
+		getElementById : function(id){
+			return safeNode(doc.getElementById(id));
+		},
+		createElement : function(name){
+			return wrap(doc.createElement(name));
+		},
+		createTextNode : function(name){
+			return wrap(doc.createTextNode(name));
+		},
+		write : function(str){
+			var div = safeHTML(str);
+			while (div.childNodes.length){
+				// move all these children to the main node
+				element.appendChild(div.childNodes[0]);
+			}
+		}
+	};
+	safeDoc.open = safeDoc.close = function(){}; // no-op functions
+	var setters = {
+		innerHTML : function(node,value){
+			console.log('setting innerHTML');
+			node.innerHTML = safeHTML(value).innerHTML;
+		}
+	};
+	setters.outerHTML = function(node,value){
+		throw new Error("Can not set this property");
+	}; // blocked
+	function domChanger(name,newNodeArg){
+		return function(node,args){
+			safeElement(args[newNodeArg]);  // check to make sure the new node is safe
+			return node[name](args[0]);// execute the method
+		};
+	} 
+	var invokers = {
+		appendChild : domChanger("appendChild",0),
+		insertBefore : domChanger("insertBefore",0),
+		replaceChild : domChanger("replaceChild",1),
+		cloneNode : function(node,args){
+			return node.cloneNode(args[0]);
+		},
+		addEventListener : function(node,args){
+			dojo.connect(node,'on' + args[0],this,function(event){
+				event = nodeObserver(event || window.event);
+				args[1].call(this,event);
+			});
+		}
+	};
+	invokers.childNodes = invokers.style = invokers.ownerDocument = function(){}; // this is a trick to get these property slots available, they will be overridden  
+	function makeObserver(setter){ // we make two of these, but the setter for style nodes is different
+		return dojox.lang.makeObservable(
+			function(node, prop){
+				var result;
+				return node[prop];
+			},setter,
+			function(wrapper, node, methodName, args){
+				for (var i = 0; i < args.length; i++){
+					args[i] = unwrap(args[i]);
+				}
+				if(invokers[methodName]){
+					return wrap(invokers[methodName].call(wrapper,node,args));
+				}
+				return wrap(node[methodName].apply(node,args));
+			},invokers);
+	}
+	var nodeObserver = makeObserver(function(node, prop, value){
+			if(setters[prop]){
+				setters[prop](node,value);
+			}
+			node[prop] = value; 
+		});
+	var blockedStyles = {behavior:1,MozBinding:1}; 
+	var styleObserver = makeObserver(function(node, prop, value){
+			if(!blockedStyles[prop]){
+				node[prop] = safeCSS(value);
+			} 
+		}); 
+	wrap.safeHTML = safeHTML;
+	wrap.safeCSS = safeCSS;
+	return wrap;
 };
-dojox.secure.unwrap=function unwrap(_3d){
-return (_3d&&_3d.data__)||_3d;
+dojox.secure.unwrap = function unwrap(result){
+	return (result && result.data__) || result; 
 };
-}
diff --git a/dojox/secure/capability.js b/dojox/secure/capability.js
index 38fe225..01c4f7e 100644
--- a/dojox/secure/capability.js
+++ b/dojox/secure/capability.js
@@ -1,102 +1,130 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.secure.capability"]){
-dojo._hasResource["dojox.secure.capability"]=true;
 dojo.provide("dojox.secure.capability");
-dojox.secure.badProps=/^__|^(apply|call|callee|caller|constructor|eval|prototype|this|unwatch|valueOf|watch)$|__$/;
-dojox.secure.capability={keywords:["break","case","catch","const","continue","debugger","default","delete","do","else","enum","false","finally","for","function","if","in","instanceof","new","null","yield","return","switch","throw","true","try","typeof","var","void","while"],validate:function(_1,_2,_3){
-var _4=this.keywords;
-for(var i=0;i<_4.length;i++){
-_3[_4[i]]=true;
-}
-var _5="|this| keyword in object literal without a Class call";
-var _6=[];
-if(_1.match(/[\u200c-\u200f\u202a-\u202e\u206a-\u206f\uff00-\uffff]/)){
-throw new Error("Illegal unicode characters detected");
-}
-if(_1.match(/\/\*@cc_on/)){
-throw new Error("Conditional compilation token is not allowed");
-}
-_1=_1.replace(/\\["'\\\/bfnrtu]/g,"@").replace(/\/\/.*|\/\*[\w\W]*?\*\/|\/(\\[\/\\]|[^*\/])(\\.|[^\/\n\\])*\/[gim]*|("[^"]*")|('[^']*')/g,function(t){
-return t.match(/^\/\/|^\/\*/)?" ":"0";
-}).replace(/\.\s*([a-z\$_A-Z][\w\$_]*)|([;,{])\s*([a-z\$_A-Z][\w\$_]*\s*):/g,function(t,_7,_8,_9){
-_7=_7||_9;
-if(/^__|^(apply|call|callee|caller|constructor|eval|prototype|this|unwatch|valueOf|watch)$|__$/.test(_7)){
-throw new Error("Illegal property name "+_7);
-}
-return (_8&&(_8+"0:"))||"~";
-});
-_1.replace(/([^\[][\]\}]\s*=)|((\Wreturn|\S)\s*\[\s*\+?)|([^=!][=!]=[^=])/g,function(_a){
-if(!_a.match(/((\Wreturn|[=\&\|\:\?\,])\s*\[)|\[\s*\+$/)){
-throw new Error("Illegal operator "+_a.substring(1));
-}
-});
-_1=_1.replace(new RegExp("("+_2.join("|")+")[\\s~]*\\(","g"),function(_b){
-return "new(";
-});
-function _c(_d,_e){
-var _f={};
-_d.replace(/#\d+/g,function(b){
-var _10=_6[b.substring(1)];
-for(var i in _10){
-if(i==_5){
-throw i;
-}
-if(i=="this"&&_10[":method"]&&_10["this"]==1){
-i=_5;
-}
-if(i!=":method"){
-_f[i]=2;
-}
-}
-});
-_d.replace(/(\W|^)([a-z_\$A-Z][\w_\$]*)/g,function(t,a,_11){
-if(_11.charAt(0)=="_"){
-throw new Error("Names may not start with _");
-}
-_f[_11]=1;
-});
-return _f;
-};
-var _12,_13;
-function _14(t,_15,a,b,_16,_17){
-_17.replace(/(^|,)0:\s*function#(\d+)/g,function(t,a,b){
-var _18=_6[b];
-_18[":method"]=1;
-});
-_17=_17.replace(/(^|[^_\w\$])Class\s*\(\s*([_\w\$]+\s*,\s*)*#(\d+)/g,function(t,p,a,b){
-var _19=_6[b];
-delete _19[_5];
-return (p||"")+(a||"")+"#"+b;
-});
-_13=_c(_17,_15);
-function _1a(t,a,b,_1b){
-_1b.replace(/,?([a-z\$A-Z][_\w\$]*)/g,function(t,_1c){
-if(_1c=="Class"){
-throw new Error("Class is reserved");
-}
-delete _13[_1c];
-});
-};
-if(_15){
-_1a(t,a,a,_16);
-}
-_17.replace(/(\W|^)(var) ([ \t,_\w\$]+)/g,_1a);
-return (a||"")+(b||"")+"#"+(_6.push(_13)-1);
-};
-do{
-_12=_1.replace(/((function|catch)(\s+[_\w\$]+)?\s*\(([^\)]*)\)\s*)?{([^{}]*)}/g,_14);
-}while(_12!=_1&&(_1=_12));
-_14(0,0,0,0,0,_1);
-for(i in _13){
-if(!(i in _3)){
-throw new Error("Illegal reference to "+i);
-}
-}
-}};
-}
+
+dojox.secure.badProps = /^__|^(apply|call|callee|caller|constructor|eval|prototype|this|unwatch|valueOf|watch)$|__$/;
+dojox.secure.capability = {
+	keywords: ["break", "case", "catch", "const", "continue","debugger", "default", "delete", "do",
+		 "else", "enum","false", "finally", "for", "function","if", "in", "instanceof", "new", 
+		 "null","yield","return", "switch",  
+		 "throw", "true", "try", "typeof", "var", "void", "while"],
+	validate : function(/*string*/script,/*Array*/safeLibraries,/*Object*/safeGlobals) {
+		// summary:
+		// 		pass in the text of a script. If it passes and it can be eval'ed, it should be safe. 
+		// 		Note that this does not do full syntax checking, it relies on eval to reject invalid scripts.
+		// 		There are also known false rejections:
+		// 			Nesting vars inside blocks will not declare the variable for the outer block
+		// 	 		Named functions are not treated as declaration so they are generally not allowed unless the name is declared with a var.	
+		//			Var declaration that involve multiple comma delimited variable assignments are not accepted
+		//
+		// script:
+		// 		 the script to execute
+		//
+		// safeLibraries:
+		// 		The safe libraries that can be called (the functions can not be access/modified by the untrusted code, only called) 
+		//
+		// safeGlobals:
+		// 		These globals can be freely interacted with by the untrusted code
+		
+	
+		var keywords = this.keywords;
+		for (var i = 0; i < keywords.length; i++) {
+			safeGlobals[keywords[i]]=true;
+		}
+		var badThis = "|this| keyword in object literal without a Class call";
+		var blocks = []; // keeps track of the outer references from each inner block
+		if(script.match(/[\u200c-\u200f\u202a-\u202e\u206a-\u206f\uff00-\uffff]/)){
+			throw new Error("Illegal unicode characters detected");
+		}
+		if(script.match(/\/\*@cc_on/)){
+			throw new Error("Conditional compilation token is not allowed");
+		}
+		script = script.replace(/\\["'\\\/bfnrtu]/g, '@'). // borrows some tricks from json.js
+			// now clear line comments, block comments, regular expressions, and strings.
+			// By doing it all at once, the regular expression uses left to right parsing, and the most
+			// left token is read first. It is also more compact.
+			replace(/\/\/.*|\/\*[\w\W]*?\*\/|\/(\\[\/\\]|[^*\/])(\\.|[^\/\n\\])*\/[gim]*|("[^"]*")|('[^']*')/g,function(t) {
+				return t.match(/^\/\/|^\/\*/) ? ' ' : '0'; // comments are replaced with a space, strings and regex are replaced with a single safe token (0)
+			}).
+			replace(/\.\s*([a-z\$_A-Z][\w\$_]*)|([;,{])\s*([a-z\$_A-Z][\w\$_]*\s*):/g,function(t,prop,prefix,key) { 
+				// find all the dot property references, all the object literal keys, and labels
+				prop = prop || key; 
+				if(/^__|^(apply|call|callee|caller|constructor|eval|prototype|this|unwatch|valueOf|watch)$|__$/.test(prop)){
+					throw new Error("Illegal property name " + prop);
+				}
+				return (prefix && (prefix + "0:")) || '~'; // replace literal keys with 0: and replace properties with the innocuous ~
+			});
+		script.replace(/([^\[][\]\}]\s*=)|((\Wreturn|\S)\s*\[\s*\+?)|([^=!][=!]=[^=])/g,function(oper) {// check for illegal operator usages
+			if(!oper.match(/((\Wreturn|[=\&\|\:\?\,])\s*\[)|\[\s*\+$/)){ // the whitelist for [ operator for array initializer context or [+num] syntax
+				throw new Error("Illegal operator " + oper.substring(1));
+			}
+		});
+		script = script.replace(new RegExp("(" + safeLibraries.join("|") + ")[\\s~]*\\(","g"),function(call) { // find library calls and make them look safe
+			return "new("; // turn into a known safe call 
+		});
+		function findOuterRefs(block,func) {
+			var outerRefs = {};
+			block.replace(/#\d+/g,function(b) { // graft in the outer references from the inner scopes
+				var refs = blocks[b.substring(1)];
+				for (var i in refs) {
+					if(i == badThis) {
+						throw i;
+					}
+					if(i == 'this' && refs[':method'] && refs['this'] == 1) {
+						// if we are in an object literal the function may be a bindable method, this must only be in the local scope
+						i = badThis;
+					}
+					if(i != ':method'){
+						outerRefs[i] = 2; // the reference is more than just local
+					}
+				}
+			});
+			block.replace(/(\W|^)([a-z_\$A-Z][\w_\$]*)/g,function(t,a,identifier) { // find all the identifiers
+				if(identifier.charAt(0)=='_'){
+					throw new Error("Names may not start with _");
+				}
+				outerRefs[identifier] = 1;
+			});
+			return outerRefs;
+		}	
+		var newScript,outerRefs;
+		function parseBlock(t,func,a,b,params,block) {
+			block.replace(/(^|,)0:\s*function#(\d+)/g,function(t,a,b) { // find functions in object literals
+			// note that if named functions are allowed, it could be possible to have label: function name() {} which is a security breach
+					var refs = blocks[b]; 
+					refs[':method'] = 1;//mark it as a method
+			});
+			block = block.replace(/(^|[^_\w\$])Class\s*\(\s*([_\w\$]+\s*,\s*)*#(\d+)/g,function(t,p,a,b) { // find Class calls
+					var refs = blocks[b];
+					delete refs[badThis];
+					return (p||'') + (a||'') + "#" + b;
+			});
+			outerRefs = findOuterRefs(block,func); // find the variables in this block
+			function parseVars(t,a,b,decl) { // find var decls
+				decl.replace(/,?([a-z\$A-Z][_\w\$]*)/g,function(t,identifier) {
+					if(identifier == 'Class'){
+						throw new Error("Class is reserved");
+					}
+					delete outerRefs[identifier]; // outer reference is safely referenced here
+				});
+			}
+			
+			if(func) {
+				parseVars(t,a,a,params); // the parameters are declare variables
+			}
+			block.replace(/(\W|^)(var) ([ \t,_\w\$]+)/g,parseVars); // and vars declare variables
+			// FIXME: Give named functions #name syntax so they can be detected as vars in outer scopes (but be careful of nesting)
+			return (a || '') + (b || '') + "#" + (blocks.push(outerRefs)-1); // return a block reference so the outer block can fetch it 
+		}	
+		do {
+			// get all the blocks, starting with inside and moving out, capturing the parameters of functions and catchs as variables along the way
+			newScript = script.replace(/((function|catch)(\s+[_\w\$]+)?\s*\(([^\)]*)\)\s*)?{([^{}]*)}/g, parseBlock); 
+		}
+		while(newScript != script && (script = newScript)); // keep going until we can't find anymore blocks
+		parseBlock(0,0,0,0,0,script); //findOuterRefs(script); // find the references in the outside scope
+		for (i in outerRefs) {
+			if(!(i in safeGlobals)) {
+				throw new Error("Illegal reference to " + i);
+			}
+		}
+		
+	}
+};
\ No newline at end of file
diff --git a/dojox/secure/sandbox.js b/dojox/secure/sandbox.js
index d923f68..024185e 100644
--- a/dojox/secure/sandbox.js
+++ b/dojox/secure/sandbox.js
@@ -1,231 +1,342 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.secure.sandbox"]){
-dojo._hasResource["dojox.secure.sandbox"]=true;
 dojo.provide("dojox.secure.sandbox");
 dojo.require("dojox.secure.DOM");
 dojo.require("dojox.secure.capability");
 dojo.require("dojo.NodeList-fx");
-(function(){
-var _1=setTimeout;
-var _2=setInterval;
-if({}.__proto__){
-var _3=function(_4){
-var _5=Array.prototype[_4];
-if(_5&&!_5.fixed){
-(Array.prototype[_4]=function(){
-if(this==window){
-throw new TypeError("Called with wrong this");
-}
-return _5.apply(this,arguments);
-}).fixed=true;
-}
-};
-_3("concat");
-_3("reverse");
-_3("sort");
-_3("slice");
-_3("forEach");
-_3("filter");
-_3("reduce");
-_3("reduceRight");
-_3("every");
-_3("map");
-_3("some");
-}
-var _6=function(){
-return dojo.xhrGet.apply(dojo,arguments);
-};
-dojox.secure.sandbox=function(_7){
-var _8=dojox.secure.DOM(_7);
-_7=_8(_7);
-var _9=_7.ownerDocument;
-var _a,_b=dojox.secure._safeDojoFunctions(_7,_8);
-var _c=[];
-var _d=["isNaN","isFinite","parseInt","parseFloat","escape","unescape","encodeURI","encodeURIComponent","decodeURI","decodeURIComponent","alert","confirm","prompt","Error","EvalError","RangeError","ReferenceError","SyntaxError","TypeError","Date","RegExp","Number","Object","Array","String","Math","setTimeout","setInterval","clearTimeout","clearInterval","dojo","get","set","forEach","load","evaluate"];
-for(var i in _b){
-_d.push(i);
-_c.push("var "+i+"=dojo."+i);
-}
-eval(_c.join(";"));
-function _e(_f,_10){
-_10=""+_10;
-if(dojox.secure.badProps.test(_10)){
-throw new Error("bad property access");
-}
-if(_f.__get__){
-return _f.__get__(_10);
-}
-return _f[_10];
-};
-function set(obj,_11,_12){
-_11=""+_11;
-_e(obj,_11);
-if(obj.__set){
-return obj.__set(_11);
-}
-obj[_11]=_12;
-return _12;
-};
-function _13(obj,fun){
-if(typeof fun!="function"){
-throw new TypeError();
-}
-if("length" in obj){
-if(obj.__get__){
-var len=obj.__get__("length");
-for(var i=0;i<len;i++){
-if(i in obj){
-fun.call(obj,obj.__get__(i),i,obj);
-}
-}
-}else{
-len=obj.length;
-for(i=0;i<len;i++){
-if(i in obj){
-fun.call(obj,obj[i],i,obj);
-}
-}
-}
-}else{
-for(i in obj){
-fun.call(obj,_e(obj,i),i,obj);
-}
-}
-};
-function _14(_15,_16,_17){
-var _18,_19,_1a;
-var arg;
-for(var i=0,l=arguments.length;typeof (arg=arguments[i])=="function"&&i<l;i++){
-if(_18){
-_a(_18,arg.prototype);
-}else{
-_19=arg;
-var F=function(){
-};
-F.prototype=arg.prototype;
-_18=new F;
-}
-}
-if(arg){
-for(var j in arg){
-var _1b=arg[j];
-if(typeof _1b=="function"){
-arg[j]=function(){
-if(this instanceof _14){
-return arguments.callee.__rawMethod__.apply(this,arguments);
-}
-throw new Error("Method called on wrong object");
-};
-arg[j].__rawMethod__=_1b;
-}
-}
-if(arg.hasOwnProperty("constructor")){
-_1a=arg.constructor;
-}
-}
-_18=_18?_a(_18,arg):arg;
-function _14(){
-if(_19){
-_19.apply(this,arguments);
-}
-if(_1a){
-_1a.apply(this,arguments);
-}
-};
-_a(_14,arguments[i]);
-_18.constructor=_14;
-_14.prototype=_18;
-return _14;
-};
-function _1c(_1d){
-if(typeof _1d!="function"){
-throw new Error("String is not allowed in setTimeout/setInterval");
-}
-};
-function _1e(_1f,_20){
-_1c(_1f);
-return _1(_1f,_20);
-};
-function _21(_22,_23){
-_1c(_22);
-return _2(_22,_23);
-};
-function _24(_25){
-return _8.evaluate(_25);
-};
-var _26=_8.load=function(url){
-if(url.match(/^[\w\s]*:/)){
-throw new Error("Access denied to cross-site requests");
-}
-return _6({url:(new _b._Url(_8.rootUrl,url))+"",secure:true});
-};
-_8.evaluate=function(_27){
-dojox.secure.capability.validate(_27,_d,{document:1,element:1});
-if(_27.match(/^\s*[\[\{]/)){
-var _28=eval("("+_27+")");
-}else{
-eval(_27);
-}
-};
-return {loadJS:function(url){
-_8.rootUrl=url;
-return _6({url:url,secure:true}).addCallback(function(_29){
-_24(_29,_7);
-});
-},loadHTML:function(url){
-_8.rootUrl=url;
-return _6({url:url,secure:true}).addCallback(function(_2a){
-_7.innerHTML=_2a;
-});
-},evaluate:function(_2b){
-return _8.evaluate(_2b);
-}};
-};
-})();
-dojox.secure._safeDojoFunctions=function(_2c,_2d){
-var _2e=["mixin","require","isString","isArray","isFunction","isObject","isArrayLike","isAlien","hitch","delegate","partial","trim","disconnect","subscribe","unsubscribe","Deferred","toJson","style","attr"];
-var doc=_2c.ownerDocument;
-var _2f=dojox.secure.unwrap;
-dojo.NodeList.prototype.addContent.safetyCheck=function(_30){
-_2d.safeHTML(_30);
-};
-dojo.NodeList.prototype.style.safetyCheck=function(_31,_32){
-if(_31=="behavior"){
-throw new Error("Can not set behavior");
-}
-_2d.safeCSS(_32);
-};
-dojo.NodeList.prototype.attr.safetyCheck=function(_33,_34){
-if(_34&&(_33=="src"||_33=="href"||_33=="style")){
-throw new Error("Illegal to set "+_33);
-}
-};
-var _35={query:function(_36,_37){
-return _2d(dojo.query(_36,_2f(_37||_2c)));
-},connect:function(el,_38){
-var obj=el;
-arguments[0]=_2f(el);
-if(obj!=arguments[0]&&_38.substring(0,2)!="on"){
-throw new Error("Invalid event name for element");
-}
-return dojo.connect.apply(dojo,arguments);
-},body:function(){
-return _2c;
-},byId:function(id){
-return _2c.ownerDocument.getElementById(id);
-},fromJson:function(str){
-dojox.secure.capability.validate(str,[],{});
-return dojo.fromJson(str);
-}};
-for(var i=0;i<_2e.length;i++){
-_35[_2e[i]]=dojo[_2e[i]];
-}
-return _35;
+
+(function() {
+	var oldTimeout = setTimeout;
+	var oldInterval = setInterval;
+	if({}.__proto__){
+		// mozilla has unsafe methods on array	
+		var fixMozArrayFunction = function (name) {
+			var method = Array.prototype[name];
+			if(method && !method.fixed){
+				(Array.prototype[name] = function () {
+					if (this == window) {
+						throw new TypeError("Called with wrong this");
+					}
+					return method.apply(this, arguments);
+				}).fixed = true;
+			}
+		};
+		// these are not safe in mozilla
+		fixMozArrayFunction('concat');
+		fixMozArrayFunction('reverse');
+		fixMozArrayFunction('sort');
+		fixMozArrayFunction("slice");
+		fixMozArrayFunction("forEach");
+		fixMozArrayFunction("filter");
+		fixMozArrayFunction("reduce");
+		fixMozArrayFunction("reduceRight");
+		fixMozArrayFunction("every");
+		fixMozArrayFunction("map");
+		fixMozArrayFunction("some");
+	}
+	var xhrGet = function(){
+		return dojo.xhrGet.apply(dojo,arguments);
+	};
+	dojox.secure.sandbox = function(element) {
+		//	summary:
+		//		Creates a secure sandbox from which scripts and HTML can be loaded that
+		//		will only be able to access the provided element and it's descendants, the
+		//		rest of the DOM and JS environment will not be accessible to the sandboxed
+		//		scripts and HTML.
+		//
+		//	element:
+		//		The DOM element to use as the container for the sandbox
+		//
+		//	description:
+		//		This function will create and return a sandbox object (see dojox.secure.__Sandbox) 
+		// 		for the provided element.
+		var wrap = dojox.secure.DOM(element);
+		element = wrap(element);
+		var document = element.ownerDocument;
+		var mixin, dojo = dojox.secure._safeDojoFunctions(element,wrap);
+		var imports= [];
+		var safeCalls = ["isNaN","isFinite","parseInt","parseFloat","escape","unescape",
+										"encodeURI","encodeURIComponent","decodeURI","decodeURIComponent",
+										"alert","confirm","prompt", // some people may not want to allow these to be called, but they don't break capability-limiting
+										"Error","EvalError","RangeError","ReferenceError","SyntaxError","TypeError",
+										"Date","RegExp","Number","Object","Array","String","Math",
+										//"ADSAFE", // not using ADSAFE runtime for the time being 
+										"setTimeout","setInterval","clearTimeout","clearInterval", // we make these safe below
+										"dojo","get","set","forEach","load","evaluate"];
+	   	for(var i in dojo){
+	   		safeCalls.push(i); // add the safe dojo functions to as available global top level functions
+	    	imports.push("var " + i + "=dojo." + i); // add to the list of imports
+	    }
+		// open the dojo namespace (namespaces are pretty silly in an environment where you can't set globals)
+	   	eval(imports.join(";")); 
+		function get(obj,prop) {
+			// basic access by index function
+			prop = '' + prop;
+			if(dojox.secure.badProps.test(prop)) {
+				throw new Error("bad property access");
+			}
+			if(obj.__get__) {
+				return obj.__get__(prop);
+			}
+			return obj[prop];		
+		}
+		function set(obj,prop,value) {
+			// basic set by index function
+			prop = '' + prop;
+			get(obj,prop); // test it
+			if(obj.__set) {
+				return obj.__set(prop);
+			}
+			obj[prop] = value;
+			return value;
+		}
+		function forEach(obj,fun) {
+			//	short syntax iterator function 
+			if(typeof fun != "function"){
+				throw new TypeError();
+			}
+			if("length" in obj) {
+				// do arrays the fast way
+				if(obj.__get__) {
+					// use the catch getter
+					var len = obj.__get__('length');
+					for (var i = 0; i < len; i++) {
+						if(i in obj) {
+							fun.call(obj, obj.__get__(i), i, obj);
+						}
+					}
+				}
+				else {
+					// fast
+					len = obj.length;
+					for (i = 0; i < len; i++) {
+						if(i in obj) {
+							fun.call(obj, obj[i], i, obj);
+						}
+					}
+				}
+			}
+			else {
+				// for each an object
+				for (i in obj) {
+					fun.call(obj, get(obj,i), i, obj);
+				}
+			}
+		}
+		function Class(/*Function*/superclass, /*Object*/properties, /*Object*/classProperties) {
+			// summary: 
+			// 		A safe class constructor
+			// 
+			// superclass: 
+			// 		There may be zero or more superclass arguments. The constructed class 
+			// 		will inherit from any provided superclasses, protypically from the first, 
+			// 		via mixin for the subsequent. Later arguments
+			// 		will override properties/methods from earlier arguments 
+			// 
+			// properties: 
+			// 		The constructed
+			// 		"class" will also have the methods/properties defined in this argument. 
+			//		These methods may utilize the <em>this</em> operator, and they
+			// 		are only the code that has access to <em>this</em>. Inner functions 
+			// 		are also prohibited from using <em>this</em>. 
+			//
+			// 		If no superclasses are provided, this object will be the prototype of the 
+			// 		constructed class (no copying
+			// 		will be done). Consequently you can "beget" by calling new (Class(obj)).
+			// 		All methods are "bound", each call results in |this| safety checking call.
+			//
+			// classProperties: 
+			// 		This properties will be copied to the new class function.
+			//
+			// 		Note that neither dojo.declare nor dojo.extend are acceptable class constructors as
+			// 		they are completely unsecure. This class constructor is conceptually based on declare
+			// 		but also somewhat influenced by base2, prototype, YUI, resig's patterns, etc. 
+			//
+			// example:
+			// |	var Car = Class({drive:function(speed) { ... } ); // create a Car class with a "drive" method
+			// |	var FastCar = Class(Car,{driveFast: function(speed) { return this.drive(2 * speed); } }); // create a FastCar that extends Car
+			// |	var fastCar = new FastCar; // instantiate
+			// |	fastCar.driveFast(50); // call a method
+			// |	var driveFast = fastCar.driveFast; 
+			// |	var driveFast(50); // this will throw an error, the method can be used with an object that is not an instance of FastCar
+			var proto,superConstructor,ourConstructor;
+			var arg;
+			for (var i = 0, l = arguments.length; typeof (arg = arguments[i]) == 'function' && i < l; i++) {
+				// go through each superclass argument
+				if(proto) { // we have a prototype now, we must mixin now
+					mixin(proto,arg.prototype);
+				}  
+				else {
+					// this is the first argument, so we can define the prototype ourselves
+					// link up the prototype chain to the superclass's prototype, so we are a subtype
+					superConstructor = arg;
+					var F = function() {};
+					F.prototype = arg.prototype;
+					proto = new F;
+				}
+			}
+	
+			if(arg) { // the next object should be the properties
+				// apply binding checking on all the functions
+				for (var j in arg) {
+					// TODO: check on non-enumerables?
+					var value = arg[j];
+					if(typeof value == 'function') {
+						arg[j] = function() {
+							if(this instanceof Class){
+								return arguments.callee.__rawMethod__.apply(this,arguments);
+							}
+							throw new Error("Method called on wrong object");	
+						};
+						arg[j].__rawMethod__ = value; // may want to use this for reconstruction and toString,valueOf
+					}
+				}
+				if(arg.hasOwnProperty('constructor')) {
+					ourConstructor = arg.constructor;
+				}
+			}
+			proto = proto ? mixin(proto,arg) : arg; // if there is no proto yet, we can use the provided object
+			function Class() {
+				// the super class may not have been constructed using the same technique, we will just call the constructor 
+				if(superConstructor){
+					superConstructor.apply(this,arguments);
+				} 
+				if(ourConstructor){
+					ourConstructor.apply(this,arguments);
+				}
+			}
+			mixin(Class,arguments[i]); // the optional second object adds properties to the class
+			proto.constructor = Class; 
+			Class.prototype = proto;
+			return Class;
+		}
+		function checkString(func){
+			if(typeof func != 'function') {
+				throw new Error("String is not allowed in setTimeout/setInterval");
+			}
+		}
+		function setTimeout(func,time) {
+			// sandboxed setTimeout
+			checkString(func); 
+			return oldTimeout(func,time);
+		}
+		function setInterval(func,time) {
+			// sandboxed setInterval
+			checkString(func); 
+			return oldInterval(func,time);
+		}
+		function evaluate(script){
+			// sandboxed eval
+			return wrap.evaluate(script);
+		}
+		var load = wrap.load = function(url){
+			// provides a loader function for the sandbox
+			if (url.match(/^[\w\s]*:/)){
+				throw new Error("Access denied to cross-site requests");
+			}
+			return xhrGet({url:(new dojo._Url(wrap.rootUrl,url))+'',secure:true}); 
+		}  
+		wrap.evaluate = function(script){
+			//if(!alreadyValidated) {
+			dojox.secure.capability.validate(script,safeCalls, // the safe dojo library and standard operators
+											{document:1,element:1}); // these are secured DOM starting points
+		
+			//}
+			if(script.match(/^\s*[\[\{]/)) {
+				var result = eval('(' + script + ')');
+				// TODO: call render on result?
+			}
+			else {
+				eval(script);
+			}
+			//eval('wrap.evaluate=('+arguments.callee.toString()+')'); // yeah, recursive scoping;
+		};
+		return /*===== dojo.declare("dojox.secure.__Sandbox", null, =====*/ { // dojox.secure.__Sandbox
+			loadJS : function(url){
+				//	summary:
+				// 		Loads the script from the given URL using XHR (assuming 
+				// 		a plugin system is in place for cross-site requests) within the sandbox
+				//	
+				//	url:
+				//		The url of the script to load
+				wrap.rootUrl = url;
+				return xhrGet({url:url,secure:true}).addCallback(function(result) {
+					evaluate(result,element /*If we get the results with a secure proxy, we would call put true here */);
+				});
+			},
+			loadHTML : function(url){
+				//	summary:
+				//		Loads the web page from the provided URL using XHR (assuming the
+				//		plugin system is in place) within the sandbox. All scripts within the web
+				//		page will also be sandboxed.
+				//
+				//	url:
+				//		The url of the web page to load
+				
+				wrap.rootUrl = url;
+				return xhrGet({url:url,secure:true}).addCallback(function(result){
+					element.innerHTML = result;
+				});
+			},
+			evaluate : function(script){
+				//	summary:
+				//		Evaluates the given script within the sandbox
+				//	
+				//	script:
+				//		The JavaScript text to evaluate
+				return wrap.evaluate(script);
+			}
+			// TODO: could add something for pre-validated scripts
+		}/*===== ) =====*/;
+	};
+})(); 
+dojox.secure._safeDojoFunctions = function(element,wrap) {
+	//	Creates a safe subset of Dojo core library 
+	var safeFunctions = ["mixin","require","isString","isArray","isFunction","isObject","isArrayLike","isAlien",
+	"hitch","delegate","partial","trim","disconnect","subscribe","unsubscribe","Deferred","toJson","style","attr"];
+	//var domFunctions = ["clone","byId"];
+	var doc = element.ownerDocument;
+	var unwrap = dojox.secure.unwrap;
+	dojo.NodeList.prototype.addContent.safetyCheck = function(content){
+		wrap.safeHTML(content);
+	};
+	dojo.NodeList.prototype.style.safetyCheck = function(name,value){
+		if(name=='behavior'){
+			throw new Error("Can not set behavior");
+		}
+		wrap.safeCSS(value);
+	};
+	dojo.NodeList.prototype.attr.safetyCheck = function(name,value){
+		if (value && (name == 'src' || name == 'href' || name=='style')){
+			throw new Error("Illegal to set " + name);
+		}
+	};
+	var safe = {
+		query : function(query,root) {
+			return wrap(dojo.query(query,unwrap(root || element))); // wrap the NodeList
+		},
+		connect: function(el,event) {
+			var obj = el;
+			arguments[0] = unwrap(el);
+			if(obj!=arguments[0] && event.substring(0,2) != 'on'){ 
+				// it is probably an element, and it doesn't look like an event handler, probably not safe
+				throw new Error("Invalid event name for element");				
+			}
+			return dojo.connect.apply(dojo,arguments);
+		},
+		body : function() {
+			return element;
+		},
+		byId : function(id) {
+			return element.ownerDocument.getElementById(id); // use the safe document
+		},
+		fromJson : function(str) {
+			// make sure it is safe before passing it to the unsafe dojo.fromJson
+			dojox.secure.capability.validate(str,[],{}); 
+			return dojo.fromJson(str);
+		}
+	};
+	for (var i = 0; i < safeFunctions.length; i++) {
+		safe[safeFunctions[i]] = dojo[safeFunctions[i]];
+	} 
+	return safe;
 };
-}
+
diff --git a/dojox/secure/tests/DOM.js b/dojox/secure/tests/DOM.js
new file mode 100644
index 0000000..38360ef
--- /dev/null
+++ b/dojox/secure/tests/DOM.js
@@ -0,0 +1,183 @@
+dojo.provide("dojox.secure.tests.DOM");
+dojo.require("dojox.secure.DOM");
+
+doh.register("dojox.secure.tests.DOM.good", 
+	[
+		function setup(){
+			var div = document.createElement("div");
+			document.body.appendChild(div);
+			div.innerHTML = "Sandboxed div:";
+			div.style.position = "absolute";
+			div.style.top = "100px";
+			div.style.left = "100px";
+			div.style.backgroundColor = "red";
+			div.style.color = "white";
+			var container = document.createElement("div");
+			container.style.backgroundColor = "cyan";
+			container.style.color = "black";
+			div.appendChild(container);
+			wrap = dojox.secure.DOM(container);
+			securedElement = wrap(container);
+			console.log("securedElement",securedElement);
+			securedDoc = securedElement.ownerDocument;
+			console.log("securedDoc",securedDoc);
+		},
+		function innerHTML(t){
+			securedElement.innerHTML = "Hi there";
+			t.assertEqual("Hi there",securedElement.data__.innerHTML);
+		},
+		function docWrite(t){
+			securedDoc.write("<div style='color:red'>written</div>");
+			console.log("wrote");
+			securedDoc.close();
+			t.t(securedElement.data__.innerHTML.match(/written/));
+		},
+		function addNode(t){
+			var newDiv = securedDoc.createElement("div");
+			console.log("wrapped ",newDiv.data__);
+			newDiv.innerHTML = "inner div";
+			console.log("style ",newDiv.style.data__);
+			newDiv.style.color="blue";
+			console.log('appendChild ' + securedElement.appendChild);
+			securedElement.appendChild(newDiv);
+			t.t(securedElement.data__.innerHTML.match(/inner/));
+		},
+		/*function addStyleTag(t){
+			securedElement.innerHTML = "<style>div {color:green}</style><div>should be green</div>";
+			console.log('after style tag' + securedElement.innerHTML);
+			t.t(securedElement.innerHTML.match(/color/));
+		},*/
+		function addOnclickHandler(t){
+			securedElement.addEventListener("click",function(event) {
+				alert('proper click handler');	
+			});
+			
+		}
+	]);
+
+function violater(func) {
+	return {name: func.name,
+	runTest: function(t) {
+		var insecure;
+		try {
+			func(t);
+			insecure = true;
+		}catch(e){
+			console.log("successfully threw error",e);
+		}
+		t.f(insecure);
+	}};
+}
+doh.register("dojox.secure.tests.DOM.bad", 
+	[
+		function parentNode(t){
+			t.f(securedElement.parentNode);
+		},
+		function innerHTMLScript(t){
+			try {
+				securedElement.innerHTML = "<script>bad=true</script>";
+			}catch(e){}
+				t.t(typeof bad == 'undefined');
+		},
+		function innerHTMLScript2(t){
+			try{
+				securedElement.innerHTML = '</script><script>bad=true;//';
+			}catch(e){}
+				t.t(typeof bad == 'undefined');
+		},
+		function writeScript(t){
+			try{
+				securedDoc.write("<script>bad=true;</script>");
+			}catch(e){}
+				t.t(typeof bad == 'undefined');
+		},
+		function appendScript(t){
+			try {
+				var script = securedDoc.createElement('script');
+				script.appendChild(securedDoc.createTextNode(
+				        'bad=true'));
+				securedElement.appendChild(script);
+			}
+			catch(e) {
+				
+			}
+				t.t(typeof bad == 'undefined');
+		},
+		function cssExpression(t) {
+			if (dojo.isIE) {
+				securedElement.innerHTML = '<div id="oDiv" style="left:expression((bad=true), 0)">Example DIV</div>';
+				t.t(typeof bad == 'undefined');
+			}
+			else {
+				try{
+					securedElement.innerHTML = '<input style=\'-moz-binding: url("http://www.mozilla.org/xbl/htmlBindings.xml#checkbox");\'>';
+				}catch(e){}
+				
+				t.f(securedElement.innerHTML.match(/mozilla/))
+			}
+				
+		},
+		function cssExpression2(t) {
+			if (dojo.isIE) {
+				securedElement.style.left = 'expression(alert("hello"), 0)';
+				t.f(securedElement.style.left.match(/alert/));
+			}
+			else {
+				try {
+					securedElement.style.MozBinding = 'url("http://www.mozilla.org/xbl/htmlBindings.xml#checkbox")';
+				}catch(e){}
+					
+			}
+		},
+		function cssExpression3(t) {
+			if (dojo.isIE) {
+				securedElement.style.behavior = 'url(a1.htc)';
+				t.f(securedElement.style.behavior);
+			}
+			else {
+				
+			}
+		},
+		/*violater(function addStyleTag(t) {
+			securedElement.innerHTML = "<style>div {color:expression(alert(\"hello\")}</style><div>test</div>";		
+		}),
+		violater(function addStyleTag2(t) {
+			securedElement.innerHTML = "<style>@import 'unsafe.css'</style><div>unsafe css</div>";		
+		}),*/
+		function addJavaScriptHref(t) {
+			securedElement.innerHTML = "<a href='javascript:alert(3)'>illegal link</a>";		
+		},
+		/*violater(function addNullCharSrc(t) {
+			securedElement.innerHTML = "<a href='java�script:alert(3)'>illegal link</a>";		
+		}),*/
+		function addOnclickHandler(t) {
+			try{
+				securedElement.innerHTML = "<div onclick='alert(4)'>illegal link</div>";
+			}catch(e){}
+			
+			t.f(securedElement.innerHTML.match(/alert/));
+		},
+		function confusingHTML(t) {
+			try {
+				securedElement.innerHTML = '<div x="\"><img onload=alert(42)src=http://json.org/img/json160.gif>"></div>';
+			}catch(e){}
+			
+			t.f(securedElement.innerHTML.match(/alert/));
+		},
+		function confusingHTML2(t) {
+			try {
+				securedElement.innerHTML = '<iframe/src="javascript:alert(42)"></iframe>';
+			}catch(e){}
+			
+			t.f(securedElement.innerHTML.match(/alert/));
+		},
+		function confusingHTML2(t) {
+			try{
+				securedElement.innerHTML = '<iframe/ "onload=alert(/XSS/)></iframe>';
+			}catch(e){}
+			
+			t.f(securedElement.innerHTML.match(/alert/));
+		}
+		
+	]);
+	
\ No newline at end of file
diff --git a/dojox/secure/tests/bad.html b/dojox/secure/tests/bad.html
new file mode 100644
index 0000000..202498a
--- /dev/null
+++ b/dojox/secure/tests/bad.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid with Dojo.Data via binding</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+	<style type="text/css">
+		b{
+			color:red;
+		}
+	</style>
+<head>
+<body>
+	This is a <b>sandboxed</b> paged with a bad script.
+	<script type="text/javascript">
+		alert("safe script" + this);
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/secure/tests/bad.js b/dojox/secure/tests/bad.js
new file mode 100644
index 0000000..4cce072
--- /dev/null
+++ b/dojox/secure/tests/bad.js
@@ -0,0 +1,2 @@
+element.innerHTML = "Only doing <b>things</b> I am <i>not</i> allowed to do";
+alert(this);
\ No newline at end of file
diff --git a/dojox/secure/tests/good.html b/dojox/secure/tests/good.html
new file mode 100644
index 0000000..df2de73
--- /dev/null
+++ b/dojox/secure/tests/good.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.grid.Grid with Dojo.Data via binding</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+	<style type="text/css">
+		b{
+			color:red;
+		}
+	</style>
+<head>
+<body>
+	This is <b>sandboxed</b> with a script.
+	<script type="text/javascript">
+		query("b").style("color","red");
+		alert("done");
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/secure/tests/good.js b/dojox/secure/tests/good.js
new file mode 100644
index 0000000..9730d94
--- /dev/null
+++ b/dojox/secure/tests/good.js
@@ -0,0 +1,2 @@
+element.innerHTML = "Only doing <b>things</b> I am allowed to do";
+query("b").style("color","red");
\ No newline at end of file
diff --git a/dojox/secure/tests/load.html b/dojox/secure/tests/load.html
new file mode 100644
index 0000000..eea29c2
--- /dev/null
+++ b/dojox/secure/tests/load.html
@@ -0,0 +1,216 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<title>dojox.secure.sandbox Test Page</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		textarea { 
+			width:100%; 
+			height:250px;
+			font-size:0.8em; 
+		}
+		#container {
+			position: absolute;
+			z-index:100000;
+			top: 400px;
+			right: 40px;
+			background-color:blue;
+			color:white;
+		}
+		#sandbox {
+			background-color:white;
+			color:black;
+			border: 1px solid blue;
+			width: 400px;
+			height: 300px;
+			overflow:auto;
+		}
+		#instructions {
+			margin-right:450px;
+		}
+	</style>
+	<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+	<script type="text/javascript" src="../capability.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.io.xhrPlugins");
+		dojo.require("dojox.secure.sandbox");
+		dojox.io.xhrPlugins.addProxy("proxy.php?url=");
+		dojo.addOnLoad(function() {
+			var sandbox = dojox.secure.sandbox(document.getElementById("sandbox"));
+			dojo.byId("execute").onclick= function () {
+				var input = document.getElementById("input").value;
+				try{
+					sandbox.evaluate(input);
+				}catch(e){
+					alert(e.message || e);
+				}
+			}
+			dojo.byId("executeJs").onclick= function () {
+				var input = document.getElementById("jsFile").value;
+				sandbox.loadJS(input).addErrback(function(result){
+					alert(result);
+				});
+			}
+			dojo.byId("executeHtml").onclick= function () {
+				var input = document.getElementById("htmlFile").value;
+				sandbox.loadHTML(input).addErrback(function(result){
+					alert(result);
+				});
+			}
+		});
+	</script>
+</head>
+<body class="tundra">
+	<h5>dojox.secure.sandbox Tester</h5>
+	<p>
+	This a test page for dojox.secure.sandbox. dojox.secure.sandbox is intended to safely execute 
+	untrusted scripts, and allow the scripts to access only a certain sub-tree of the DOM. 
+	Eventually, this can be used to safely load ads and untrusted widgets. 
+	All attempts to subvert the security of this system
+	are greatly appreciated. If you find any holes, any ways that you can access the DOM or the 
+	JavaScript environment outside of the sandbox, please add a comment to the 
+	<a href="http://trac.dojotoolkit.org/ticket/6348">enhancement</a> ticket. To test secure load,
+	simply enter JavaScript in the text box below and click execute. The JavaScript should only
+	have access to the DOM within the floating div below. The sandbox element is available
+	as the <em>element</em> variable from within the sandboxed JavaScript. Please see below 
+	for more detailed instructions on what facilities are available within the sandbox. 
+	</p>
+	<div id="container">Sandboxed div:<div id="sandbox"></div></div>
+	<textarea id="input">
+element.innerHTML = "<p class='intro'>Hi there, element is the <b>sandboxed element</b>, which you can access and manipulate</p>";
+document.write("<p id='more'>You can use <em>document.write</em> for your sandbox area. However, the following limitations apply:</p>");
+query("em").style("color","blue"); // you can use query to find and modify
+//query(".intro").style("opacity",0).fadeIn().play();
+style(byId("more"),"color","red");
+var limitations = ["No access to |this| keyword",
+	"The [] index operator is only allowed if in the opening bracket is followed by a +",
+	"Global variables are not allowed except element and document",
+	"You can not access most of the relationship properties on elements (parentNode, firstSibling, nextSibling, etc.)"];
+// you can also use other standard DOM features as well
+var ul = document.createElement("ul");
+element.appendChild(ul);
+forEach(limitations,function(limitation) {
+  var li = document.createElement("li");
+  ul.appendChild(li);
+  li.innerHTML = limitation;
+});
+element.appendChild(document.createElement("p")).innerHTML = 
+	"Because " + get(limitations,1) + " you may use " +
+	"get(obj,property), set(obj,property,value), and forEach(array) instead";
+// here is an example of creating a class (where |this| can be used):
+var Flicker = Class({
+  constructor : function(element) {
+    this.element = element;
+    connect(element,"onmouseenter",this,"enter");
+    connect(element,"onmouseout",this,"exit");
+  },
+  enter: function(event) {
+    style(this.element,"color","green");
+  },
+  exit: function(event) {
+    style(this.element,"color","orange");
+  } 
+});
+new Flicker(ul);
+// you can also access other dojo functions:
+var copy = mixin({},limitations);
+
+</textarea><br/>
+	Note that these require a proxy file in order to load:
+	<button id="execute">Execute</button><br/>
+	<input type='text' id="jsFile" value="http://www.sitepen.com/labs/code/secure/dojox/secure/tests/good.js"></input>
+	<button id="executeJs">Load and execute JavaScript</button><br/>
+	<input type='text' id="htmlFile" value="http://www.sitepen.com/labs/code/secure/dojox/secure/tests/good.html"></input><button id="executeHtml">Load and show HTML</button><br/>
+	<div id="instructions">
+		<p>The JavaScript in the sandbox generally follows the rules of ADsafe:</p>
+		<ul>
+		<li>Use of <em>eval</em>, <em>with</em>, ==, and != are not allowed.</li>
+		<li>the subscript operator [] may only be used be used if the opening bracket is followed by a +.</li>
+		 
+		<li>Limited access to <em>this</em> and global variables.</li>
+		<li>These properties may not be used: apply arguments call callee caller constructor eval prototype 
+				this unwatch valueOf watch and anything beginning or ending with __.</li>
+		</ul>
+		<p>The following global variables are accessible:
+		<ul>
+		<li>element - This the root element of the sandbox. Sandboxed elements do not have 
+		access to relational properties (parentNode, firstSibling, nextSibling, etc.). You can still
+		use DOM methods and string properties like innerHTML. The style object can also be
+		used (accessed and modified) as well.</li>
+		<li>document - This is a sandboxed document object that provides node creation 
+		and basic element searching facilities. The sandboxed document provides the following 
+		methods: getElementById, createElement, createTextNode, and write.
+		</li>
+		</ul>
+		<p>
+		The following standard JavaScript/DOM functions/constructors and (their child functions when applicable)
+		may be called. They may only be used in call position, they may not be accessed 
+		in any other way. They generally behave as the standard JavaScript function, unless otherwise noted:
+		</p>
+		<ul>
+<li>isNaN</li><li>isFinite</li><li>parseInt</li><li>parseFloat</li><li>escape</li><li>unescape</li>
+										<li>encodeURI</li><li>encodeURIComponent</li><li>decodeURI</li><li>decodeURIComponent</li>
+										<li>alert</li><li>confirm</li><li>prompt</li>
+										<li>Date</li><li>RegExp</li><li>Error</li><li>Number</li><li>Math</li>
+										<li>setTimeout - This will only accept a function (not a string)</li><li>setInterval - This will only accept a function (not a string)</li><li>clearTimeout</li><li>clearInterval</li>
+		</ul>
+		The following special functions are available to compensate for the JavaScript syntax limitations imposed by the sandbox:
+		<ul>
+										<li>get(obj,prop) - This is a special function to handle accessing properties in lieu of the [] operator. Calling get(obj,prop) is equivalent to obj[prop].</li>
+										<li>set(obj,prop,value) - This is a special function to handle modifying properties in lieu of the [] operator. Calling set(obj,prop,value) is equivalent to obj[prop]=value.</li>
+										<li>forEach(obj,func) - This is a special function to iterate through all the properties in an object, or items in an array. 
+											For each item, the func function will be called with the item as the first argument, the index as the second,
+											and the obj as the third</li>
+										<li>Class(superclass..., properties, classProperties) - 
+		The <em>this</em> operator may only be used in class definitions. secure.sandbox provides <em>Class</em> as a 
+		class constructor. The following argument are accepted:
+		<ul>
+			<li>superclass: 
+			 		There may be zero or more superclass arguments. The constructed class 
+			 		will inherit from any provided superclasses, protypically from the first, 
+			 		via mixin for the subsequent. Later arguments
+			 		will override properties/methods from earlier arguments 
+			 </li>
+			 <li>
+			 properties: 
+			 		The constructed
+			 		"class" will also have the methods/properties defined in this argument.
+			 		These methods may utilize the <em>this</em> operator, and they
+			 		are only the code that has access to <em>this</em>. Inner functions 
+			 		are also prohibited from using <em>this</em>. 
+			 		If no superclasses are provided, this object will be the prototype of the 
+			 		constructed class (no copying
+			 		will be done). Consequently you can "beget" by calling new (Class(obj)).
+			 		All methods are "bound", each call results in |this| safety checking call.
+			</li>
+			<li>
+			 classProperties: 
+			 		This properties will be copied to the new class function.
+			
+		 	</li>
+	 	</ul> 
+			 		Note that neither dojo.declare nor dojo.extend are acceptable class constructors as
+			 		they are unsecure. This class constructor is conceptually based on declare
+			 		but also somewhat influenced by base2, prototype, YUI, resig's patterns, etc.
+		</li>
+		</ul>
+		The following functions for DOM manipulation and extra language features are
+		provided by the Dojo library. This represents a safe subset of Dojo. All Dojo library 
+		functions are provided as top level functions,
+		namespacing is unnecessary because scripts do have access to modify the global object,
+		and can't define global variables. Thus, you can call Dojo functions directly, for example you 
+		can call mixin(obj,mixinObj). You may also use the traditional syntax (dojox.mixin(...)).
+		Here are a list of available functions:
+		<ul>
+			<li>mixin</li><li>require</li><li>isString</li><li>isArray</li><li>isFunction</li>
+			<li>isObject</li><li>isArrayLike</li><li>isAlien</li><li>hitch</li><li>delegate</li>
+			<li>partial</li><li>trim</li><li>connect</li><li>disconnect</li><li>subscribe</li>
+			<li>unsubscribe</li><li>Deferred</li><li>toJson</li><li>fromJson</li><li>style</li><li>attr</li>	 
+			<li>query - This will only search within the sandbox.</li><li>byId</li><li>body - This returns the root element of the sandbox</li>
+			
+		</ul>
+	</div>
+	<iframe src="../../../dojo/resources/blank.html"></iframe>
+</body>
+</html>
diff --git a/dojox/secure/tests/sandbox.js b/dojox/secure/tests/sandbox.js
new file mode 100644
index 0000000..5e58293
--- /dev/null
+++ b/dojox/secure/tests/sandbox.js
@@ -0,0 +1,120 @@
+dojo.provide("dojox.secure.tests.secure");
+dojo.require("dojox.secure.secure");
+
+doh.register("dojox.secure.tests.secure.good", 
+	[
+		function setup(){
+			var div = document.createElement("div");
+			document.body.appendChild(div);
+			div.innerHTML = "Sandboxed div:";
+			div.style.position = "absolute";
+			div.style.top = "100px";
+			div.style.left = "100px";
+			div.style.backgroundColor = "red";
+			div.style.color = "white";
+			container = document.createElement("div");
+			container.style.backgroundColor = "cyan";
+			container.style.color = "black";
+			div.appendChild(container);			
+		},
+		function innerHTML(t){
+			dojox.secure.evaluate("element.innerHTML = 'Hi there';",container);
+			t.assertEqual("Hi there",container.innerHTML);
+		},
+		function docWrite(t){
+			dojox.secure.evaluate("document.write(\"<div style='color:red'>written</div>\");",container);
+			t.t(container.innerHTML.match(/written/));
+		}
+	]);
+
+function violater(func) {
+	return {name: func.name,
+	runTest: function(t) {
+		var insecure;
+		try {
+			func(t);
+			insecure = true;
+		}catch(e){
+			console.log("successfully threw error",e);
+		}
+		t.f(insecure);
+	}};
+}
+doh.register("dojox.secure.tests.secure.bad", 
+	[
+		function parentNode(t){
+			t.f(dojox.secure.evaluate("document.body",container));
+		},
+		function innerHTMLScript(t){
+			try {
+				dojox.secure.evaluate("bad = true",container);
+			}catch(e){}
+				t.t(typeof bad == 'undefined');
+		}
+		/*function innerHTMLScript2(t){
+			try{
+				securedElement.innerHTML = '</script><script>bad=true;//';
+			}catch(e){}
+				t.t(typeof bad == 'undefined');
+		},
+		function writeScript(t){
+			try{
+				securedDoc.write("<script>bad=true;</script>");
+			}catch(e){}
+				t.t(typeof bad == 'undefined');
+		},
+		function appendScript(t){
+			try {
+				var script = securedDoc.createElement('script');
+				script.appendChild(securedDoc.createTextNode(
+				        'bad=true'));
+				securedElement.appendChild(script);
+			}
+			catch(e) {
+				
+			}
+				t.t(typeof bad == 'undefined');
+		},
+		function cssExpression(t) {
+			if (dojo.isIE) {
+				securedElement.innerHTML = '<div id="oDiv" style="left:expression((bad=true), 0)">Example DIV</div>';
+				t.t(typeof bad == 'undefined');
+			}
+			else {
+				try{
+					securedElement.innerHTML = '<input style=\'-moz-binding: url("http://www.mozilla.org/xbl/htmlBindings.xml#checkbox");\'>';
+				}catch(e){}
+				
+				t.f(securedElement.innerHTML.match(/mozilla/))
+			}
+				
+		},
+		function cssExpression2(t) {
+			if (dojo.isIE) {
+				securedElement.style.left = 'expression(alert("hello"), 0)';
+				t.f(securedElement.style.left.match(/alert/));
+			}
+			else {
+				try {
+					securedElement.style.MozBinding = 'url("http://www.mozilla.org/xbl/htmlBindings.xml#checkbox")';
+				}catch(e){}
+					
+			}
+		},
+		function cssExpression3(t) {
+			if (dojo.isIE) {
+				securedElement.style.behavior = 'url(a1.htc)';
+				t.f(securedElement.style.behavior);
+			}
+			else {
+				
+			}
+		},
+		violater(function addStyleTag(t) {
+			securedElement.innerHTML = "<style>div {color:expression(alert(\"hello\")}</style><div>test</div>";		
+		}),
+		violater(function addStyleTag2(t) {
+			securedElement.innerHTML = "<style>@import 'unsafe.css'</style><div>unsafe css</div>";		
+		})*/
+	]);
+	
\ No newline at end of file
diff --git a/dojox/sketch.js b/dojox/sketch.js
index 8fbad1f..f05405e 100644
--- a/dojox/sketch.js
+++ b/dojox/sketch.js
@@ -1,15 +1,5 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch"]){
-dojo._hasResource["dojox.sketch"]=true;
 dojo.provide("dojox.sketch");
 dojo.require("dojox.xml.DomParser");
 dojo.require("dojox.sketch.UndoStack");
 dojo.require("dojox.sketch.Figure");
-dojo.require("dojox.sketch.Toolbar");
-}
+dojo.require("dojox.sketch.Toolbar");
\ No newline at end of file
diff --git a/dojox/sketch/Anchor.js b/dojox/sketch/Anchor.js
index cf373ff..66518f7 100644
--- a/dojox/sketch/Anchor.js
+++ b/dojox/sketch/Anchor.js
@@ -1,69 +1,66 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch.Anchor"]){
-dojo._hasResource["dojox.sketch.Anchor"]=true;
 dojo.provide("dojox.sketch.Anchor");
 dojo.require("dojox.gfx");
+
 (function(){
-var ta=dojox.sketch;
-ta.Anchor=function(an,id,_1){
-var _2=this;
-var _3=4;
-var _4=null;
-this.type=function(){
-return "Anchor";
-};
-this.annotation=an;
-this.id=id;
-this._key="anchor-"+ta.Anchor.count++;
-this.shape=null;
-this.isControl=(_1!=null)?_1:true;
-this.beginEdit=function(){
-this.annotation.beginEdit(ta.CommandTypes.Modify);
-};
-this.endEdit=function(){
-this.annotation.endEdit();
-};
-this.zoom=function(_5){
-if(this.shape){
-var rs=Math.floor(_3/_5);
-var _6=dojox.gfx.renderer=="vml"?1:1/_5;
-this.shape.setShape({x:an[id].x-rs,y:an[id].y-rs,width:rs*2,height:rs*2}).setStroke({color:"black",width:_6});
-}
-};
-this.setBinding=function(pt){
-an[id]={x:an[id].x+pt.dx,y:an[id].y+pt.dy};
-an.draw();
-an.drawBBox();
-};
-this.setUndo=function(){
-an.setUndo();
-};
-this.enable=function(){
-if(!an.shape){
-return;
-}
-an.figure._add(this);
-_4={x:an[id].x-_3,y:an[id].y-_3,width:_3*2,height:_3*2};
-this.shape=an.shape.createRect(_4).setFill([255,255,255,0.35]);
-this.shape.getEventSource().setAttribute("id",_2._key);
-this.shape.getEventSource().setAttribute("shape-rendering","crispEdges");
-this.zoom(an.figure.zoomFactor);
-};
-this.disable=function(){
-an.figure._remove(this);
-if(an.shape){
-an.shape.remove(this.shape);
-}
-this.shape=null;
-_4=null;
-};
-};
-ta.Anchor.count=0;
+	var ta=dojox.sketch;
+	ta.Anchor=function(an, id, isControl){
+		var self=this;
+		var size=4;	//	.5 * size of anchor.
+		var rect=null;
+
+		this.type=function(){ return "Anchor"; };
+		this.annotation=an;
+
+		this.id=id;
+		this._key="anchor-" + ta.Anchor.count++;
+		this.shape=null;
+		this.isControl=(isControl!=null)?isControl:true;
+
+		this.beginEdit=function(){
+			this.annotation.beginEdit(ta.CommandTypes.Modify);
+		};
+		this.endEdit=function(){
+			this.annotation.endEdit();
+		};
+		this.zoom=function(pct){
+			if(this.shape){
+				var rs=Math.floor(size/pct);
+				var width=dojox.gfx.renderer=='vml'?1:1/pct
+				this.shape.setShape({ x:an[id].x-rs, y:an[id].y-rs, width:rs*2, height:rs*2 }).setStroke({ color:"black", width:width }); //For IE, maybe we need Math.ceil(1/pct)||1
+			}
+		}
+		/*this.doChange=function(pt){
+			if(this.isControl){
+				this.shape.applyTransform(pt);
+			} else{
+				an.transform.dx+=pt.dx;
+				an.transform.dy+=pt.dy;
+			}
+		};*/
+		this.setBinding=function(pt){
+			an[id]={ x: an[id].x+pt.dx, y:an[id].y+pt.dy };
+			an.draw();
+			an.drawBBox();
+		};
+		this.setUndo=function(){ an.setUndo(); };
+
+		this.enable=function(){
+			if(!an.shape){ return; }
+			an.figure._add(this);
+			rect={ x:an[id].x-size, y:an[id].y-size, width:size*2, height:size*2 };
+			this.shape=an.shape.createRect(rect)
+				//.setStroke({ color:"black", width:1 })
+				.setFill([255,255,255,0.35]);
+			this.shape.getEventSource().setAttribute("id", self._key);
+			this.shape.getEventSource().setAttribute("shape-rendering", "crispEdges");
+			this.zoom(an.figure.zoomFactor);
+		};
+		this.disable=function(){
+			an.figure._remove(this);
+			if(an.shape){ an.shape.remove(this.shape); }
+			this.shape=null;
+			rect=null;
+		};
+	};
+	ta.Anchor.count=0;
 })();
-}
diff --git a/dojox/sketch/Annotation.js b/dojox/sketch/Annotation.js
index c5b24f8..c99c8fb 100644
--- a/dojox/sketch/Annotation.js
+++ b/dojox/sketch/Annotation.js
@@ -1,249 +1,271 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch.Annotation"]){
-dojo._hasResource["dojox.sketch.Annotation"]=true;
 dojo.provide("dojox.sketch.Annotation");
 dojo.require("dojox.sketch.Anchor");
 dojo.require("dojox.sketch._Plugin");
+
 (function(){
-var ta=dojox.sketch;
-dojo.declare("dojox.sketch.AnnotationTool",ta._Plugin,{onMouseDown:function(e){
-this._omd=true;
-},onMouseMove:function(e,_1){
-if(!this._omd){
-return;
-}
-if(this._cshape){
-this._cshape.setShape(_1);
-}else{
-this._cshape=this.figure.surface.createRect(_1).setStroke({color:"#999",width:1,style:"ShortDot"}).setFill([255,255,255,0.7]);
-this._cshape.getEventSource().setAttribute("shape-rendering","crispEdges");
-}
-},onMouseUp:function(e){
-if(!this._omd){
-return;
-}
-this._omd=false;
-var f=this.figure;
-if(this._cshape){
-f.surface.remove(this._cshape);
-delete this._cshape;
-}
-if(!(f._startPoint.x==e.pageX&&f._startPoint.y==e.pageY)){
-var _2=10;
-if(Math.max(_2,Math.abs(f._absEnd.x-f._start.x),Math.abs(f._absEnd.y-f._start.y))>_2){
-this._create(f._start,f._end);
-}
-}
-},_create:function(_3,_4){
-var f=this.figure;
-var _5=f.nextKey();
-var a=new (this.annotation)(f,_5);
-a.transform={dx:f._calCol(_3.x/f.zoomFactor),dy:f._calCol(_3.y/f.zoomFactor)};
-a.end={x:f._calCol(_4.x/f.zoomFactor),y:f._calCol(_4.y/f.zoomFactor)};
-if(a.control){
-a.control={x:f._calCol((_4.x/2)/f.zoomFactor),y:f._calCol((_4.y/2)/f.zoomFactor)};
-}
-f.onBeforeCreateShape(a);
-a.initialize();
-f.select(a);
-f.onCreateShape(a);
-f.history.add(ta.CommandTypes.Create,a);
-}});
-ta.Annotation=function(_6,id){
-this.id=this._key=id;
-this.figure=_6;
-this.mode=ta.Annotation.Modes.View;
-this.shape=null;
-this.boundingBox=null;
-this.hasAnchors=true;
-this.anchors={};
-this._properties={"stroke":{color:"blue",width:2},"font":{family:"Arial",size:16,weight:"bold"},"fill":"blue","label":""};
-if(this.figure){
-this.figure.add(this);
-}
-};
-var p=ta.Annotation.prototype;
-p.constructor=ta.Annotation;
-p.type=function(){
-return "";
-};
-p.getType=function(){
-return ta.Annotation;
-};
-p.onRemove=function(_7){
-this.figure.history.add(ta.CommandTypes.Delete,this,this.serialize());
-};
-p.property=function(_8,_9){
-var r;
-_8=_8.toLowerCase();
-if(this._properties[_8]!==undefined){
-r=this._properties[_8];
-}
-if(arguments.length>1){
-this._properties[_8]=_9;
-if(r!=_9){
-this.onPropertyChange(_8,r);
-}
-}
-return r;
-};
-p.onPropertyChange=function(_a,_b){
-};
-p.onCreate=function(){
-this.figure.history.add(ta.CommandTypes.Create,this);
-};
-p.onDblClick=function(e){
-var l=prompt("Set new text:",this.property("label"));
-if(l!==false){
-this.beginEdit(ta.CommandTypes.Modify);
-this.property("label",l);
-this.draw();
-this.endEdit();
-}
-};
-p.initialize=function(){
-};
-p.destroy=function(){
-};
-p.draw=function(){
-};
-p.apply=function(_c){
-};
-p.serialize=function(){
-};
-p.getBBox=function(){
-};
-p.beginEdit=function(_d){
-if(!this._type){
-this._type=_d||ta.CommandTypes.Move;
-this._prevState=this.serialize();
-}
-};
-p.endEdit=function(){
-if(this._prevState!=this.serialize()){
-this.figure.history.add(this._type,this,this._prevState);
-}
-this._type=this._prevState="";
-};
-p.calculate={slope:function(p1,p2){
-if(!(p1.x-p2.x)){
-return 0;
-}
-return ((p1.y-p2.y)/(p1.x-p2.x));
-},dx:function(p1,p2,dy){
-var s=this.slope(p1,p2);
-if(s==0){
-return s;
-}
-return dy/s;
-},dy:function(p1,p2,dx){
-return this.slope(p1,p2)*dx;
-}};
-p.drawBBox=function(){
-var r=this.getBBox();
-if(!this.boundingBox){
-this.boundingBox=this.shape.createRect(r).moveToBack().setStroke({color:"#999",width:1,style:"Dash"}).setFill([238,238,238,0.3]);
-this.boundingBox.getEventSource().setAttribute("id",this.id+"-boundingBox");
-this.boundingBox.getEventSource().setAttribute("shape-rendering","crispEdges");
-this.figure._add(this);
-}else{
-this.boundingBox.setShape(r);
-}
-};
-p.setBinding=function(pt){
-this.transform.dx+=pt.dx;
-this.transform.dy+=pt.dy;
-this.draw();
-};
-p.getTextBox=function(_e){
-var fp=this.property("font");
-var f={fontFamily:fp.family,fontSize:fp.size,fontWeight:fp.weight};
-if(_e){
-f.fontSize=Math.floor(f.fontSize/_e);
-}
-return dojox.gfx._base._getTextBox(this.property("label"),f);
-};
-p.setMode=function(m){
-if(this.mode==m){
-return;
-}
-this.mode=m;
-var _f="disable";
-if(m==ta.Annotation.Modes.Edit){
-_f="enable";
-}
-if(_f=="enable"){
-this.drawBBox();
-this.figure._add(this);
-}else{
-if(this.boundingBox){
-if(this.shape){
-this.shape.remove(this.boundingBox);
-}
-this.boundingBox=null;
-}
-}
-for(var p in this.anchors){
-this.anchors[p][_f]();
-}
-};
-p.zoom=function(pct){
-pct=pct||this.figure.zoomFactor;
-if(this.labelShape){
-var f=dojo.clone(this.property("font"));
-f.size=Math.ceil(f.size/pct)+"px";
-this.labelShape.setFont(f);
-}
-for(var n in this.anchors){
-this.anchors[n].zoom(pct);
-}
-if(dojox.gfx.renderer=="vml"){
-pct=1;
-}
-if(this.pathShape){
-var s=dojo.clone(this.property("stroke"));
-s.width=pct>1?s.width:Math.ceil(s.width/pct)+"px";
-this.pathShape.setStroke(s);
-}
-};
-p.writeCommonAttrs=function(){
-return "id=\""+this.id+"\" dojoxsketch:type=\""+this.type()+"\""+" transform=\"translate("+this.transform.dx+","+this.transform.dy+")\""+(this.data?(" ><![CDATA[data:"+dojo.toJson(this.data)+"]]"):"");
-};
-p.readCommonAttrs=function(obj){
-var i=0,cs=obj.childNodes,c;
-while((c=cs[i++])){
-if(c.nodeType==4){
-if(c.nodeValue.substr(0,11)=="properties:"){
-this._properties=dojo.fromJson(c.nodeValue.substr(11));
-}else{
-if(c.nodeValue.substr(0,5)=="data:"){
-this.data=dojo.fromJson(c.nodeValue.substr(5));
-}else{
-console.error("unknown CDATA node in node ",obj);
-}
-}
-}
-}
-if(obj.getAttribute("transform")){
-var t=obj.getAttribute("transform").replace("translate(","");
-var pt=t.split(",");
-this.transform.dx=parseFloat(pt[0],10);
-this.transform.dy=parseFloat(pt[1],10);
-}
-};
-ta.Annotation.Modes={View:0,Edit:1};
-ta.Annotation.register=function(_10,_11){
-var cls=ta[_10+"Annotation"];
-ta.registerTool(_10,function(p){
-dojo.mixin(p,{shape:_10,annotation:cls});
-return new (_11||ta.AnnotationTool)(p);
-});
-};
+	var ta=dojox.sketch;
+	dojo.declare("dojox.sketch.AnnotationTool", ta._Plugin, {
+		onMouseDown: function(e){
+			this._omd=true;
+		},
+		onMouseMove: function(e,rect){
+			if(!this._omd){
+				return;
+			}
+			if(this._cshape){ 
+				this._cshape.setShape(rect);
+			} else {
+				this._cshape=this.figure.surface.createRect(rect)
+					.setStroke({color:"#999", width:1, style:"ShortDot"})
+					.setFill([255,255,255,0.7]);
+				this._cshape.getEventSource().setAttribute("shape-rendering","crispEdges");
+			}
+		},
+		onMouseUp: function(e){
+			if(!this._omd){
+				return;
+			}
+			this._omd=false;
+			var f=this.figure;
+			if(this._cshape){ 
+				f.surface.remove(this._cshape);
+				delete this._cshape;
+			}
+			if(!(f._startPoint.x==e.pageX&&f._startPoint.y==e.pageY)){
+				//	The minimum number of pixels one has to travel before a shape
+				//		gets drawn.
+				var limit=10;
+				if(Math.max(
+					limit, 
+					Math.abs(f._absEnd.x-f._start.x), 
+					Math.abs(f._absEnd.y-f._start.y)
+				)>limit){
+					this._create(f._start, f._end);
+				}
+			}
+		},
+		_create: function(start,end){
+			//	create a new shape, needs to be accessible from the
+			//		dragging functions.
+			var f=this.figure;
+			var _=f.nextKey();
+			var a=new (this.annotation)(f, _);
+			a.transform={
+				dx:f._calCol(start.x/f.zoomFactor), 
+				dy:f._calCol(start.y/f.zoomFactor)
+			};
+			a.end={ 
+				x:f._calCol(end.x/f.zoomFactor), 
+				y:f._calCol(end.y/f.zoomFactor) 
+			};
+			if(a.control){
+				a.control={ 
+					x:f._calCol((end.x/2)/f.zoomFactor),
+					y:f._calCol((end.y/2)/f.zoomFactor) 
+				};
+			}
+			f.onBeforeCreateShape(a);
+			a.initialize();
+			f.select(a);
+			f.onCreateShape(a);
+			f.history.add(ta.CommandTypes.Create,a);
+		}
+	});
+
+	ta.Annotation=function(figure, id){
+		//	for editing stuff.
+		this.id=this._key=id;
+		this.figure=figure;
+		this.mode=ta.Annotation.Modes.View;
+		this.shape=null;	// dojox.gfx.Group
+		this.boundingBox=null;	// rect for boundaries
+		this.hasAnchors=true;
+		this.anchors={};	//	ta.Anchor
+		this._properties={
+			'stroke':{ color:"blue", width:2 },
+			'font': {family:"Arial", size:16, weight:"bold"},
+			'fill': "blue",
+			'label': ""
+		};
+
+		if(this.figure){ 
+			this.figure.add(this); 
+		}
+	};
+
+	var p=ta.Annotation.prototype;
+	p.constructor=ta.Annotation;
+	p.type=function(){ return ''; };
+	p.getType=function(){ return ta.Annotation; };
+	p.onRemove=function(noundo){
+		//this.figure._delete([this],noundo);
+		this.figure.history.add(ta.CommandTypes.Delete, this, this.serialize());
+	};
+	p.property=function(name,/*?*/value){
+		var r;
+		name=name.toLowerCase();
+		if(this._properties[name]!==undefined){
+			r=this._properties[name];
+		}
+		if(arguments.length>1){
+			this._properties[name]=value;
+			if(r!=value){
+				this.onPropertyChange(name,r);
+			}
+		}
+		return r;
+	};
+	p.onPropertyChange=function(name,oldvalue){};
+	p.onCreate=function(){
+		this.figure.history.add(ta.CommandTypes.Create,this);
+	}
+	p.onDblClick=function(e){
+		var l=prompt('Set new text:',this.property('label'));
+		if(l!==false){
+			this.beginEdit(ta.CommandTypes.Modify);
+			this.property('label',l);
+			this.draw();
+			this.endEdit();
+		}
+	}
+	p.initialize=function(){ };
+	p.destroy=function(){ };
+	p.draw=function(){ };
+	p.apply=function(obj){ };
+	p.serialize=function(){ };
+	p.getBBox=function(){ };
+	p.beginEdit=function(type){
+		if(!this._type){
+			this._type=type||ta.CommandTypes.Move;
+			this._prevState=this.serialize();
+		}
+	};
+	p.endEdit=function(){
+		if(this._prevState!=this.serialize()){
+			this.figure.history.add(this._type,this,this._prevState);
+		}
+		this._type=this._prevState='';
+	};
+	p.calculate={
+		slope:function(p1, p2){
+			if(!(p1.x-p2.x)){ return 0; }
+			return ((p1.y-p2.y)/(p1.x-p2.x));
+		},
+		dx:function(p1, p2, dy){
+			var s=this.slope(p1,p2);
+			if(s==0){ return s; }
+			return dy/s; 
+		},
+		dy:function(p1, p2, dx){ 
+			return this.slope(p1,p2)*dx; 
+		}
+	};
+	p.drawBBox=function(){
+		var r=this.getBBox();
+		if(!this.boundingBox){
+			this.boundingBox=this.shape.createRect(r)
+				.moveToBack()
+				.setStroke({color:"#999", width:1, style:"Dash"})
+				.setFill([238,238,238,0.3]);
+			this.boundingBox.getEventSource().setAttribute("id",this.id+"-boundingBox");
+			this.boundingBox.getEventSource().setAttribute("shape-rendering","crispEdges");
+			this.figure._add(this);
+		} else { 
+			this.boundingBox.setShape(r); 
+		}
+	};
+	p.setBinding=function(pt){
+		this.transform.dx+=pt.dx;
+		this.transform.dy+=pt.dy;
+		this.draw();
+	};
+	//p.doChange=function(pt){ };
+	p.getTextBox=function(zoomfactor){
+		var fp=this.property('font');
+		//_getTextBox expect style camlCase properties, do it manually here
+		var f = {fontFamily:fp.family,fontSize:fp.size,fontWeight:fp.weight};
+		if(zoomfactor){
+			f.fontSize = Math.floor(f.fontSize/zoomfactor);
+		}
+		return dojox.gfx._base._getTextBox(this.property('label'),f);
+	};
+	p.setMode=function(m){
+		if(this.mode==m){ return; }
+		this.mode=m;
+		var method="disable";
+		if(m==ta.Annotation.Modes.Edit){ method="enable"; }
+		if(method=="enable"){
+			//	draw the bounding box
+			this.drawBBox();
+			this.figure._add(this);
+		} else {
+			if(this.boundingBox){
+				if(this.shape){ this.shape.remove(this.boundingBox); }
+				this.boundingBox=null;
+			}
+		}
+		for(var p in this.anchors){ 
+			this.anchors[p][method](); 
+		}
+	};
+	p.zoom=function(pct){
+		pct = pct || this.figure.zoomFactor;
+		if(this.labelShape){
+			var f=dojo.clone(this.property('font'));
+			f.size=Math.ceil(f.size/pct)+"px";
+			this.labelShape.setFont(f);
+		}
+		
+		for(var n in this.anchors){
+			this.anchors[n].zoom(pct);
+		}
+		
+		//In VML, path are always the same width no matter scaling factors,
+		//so aways use 1 for VML
+		if(dojox.gfx.renderer=='vml'){
+        	pct=1;
+        }
+		if(this.pathShape){
+			var s=dojo.clone(this.property('stroke'));
+			s.width=pct>1?s.width:Math.ceil(s.width/pct)+"px";
+			this.pathShape.setStroke(s);
+		}
+	};
+	p.writeCommonAttrs=function(){
+		return 'id="' + this.id + '" dojoxsketch:type="' + this.type() + '"'
+			+ ' transform="translate('+ this.transform.dx + "," + this.transform.dy + ')"'
+			+ (this.data?(' ><![CDATA[data:'+dojo.toJson(this.data)+']]'):'');
+	};
+	p.readCommonAttrs=function(obj){
+		var i=0,cs=obj.childNodes,c;
+		while((c=cs[i++])){
+			if(c.nodeType==4){ //CDATA
+				if(c.nodeValue.substr(0,11)=='properties:'){
+					this._properties=dojo.fromJson(c.nodeValue.substr(11));
+				}else if(c.nodeValue.substr(0,5)=='data:'){
+					this.data=dojo.fromJson(c.nodeValue.substr(5));
+				}else{
+					console.error('unknown CDATA node in node ',obj);
+				}
+			}
+		}
+
+		if(obj.getAttribute('transform')){
+			var t=obj.getAttribute('transform').replace("translate(","");
+			var pt=t.split(",");
+			this.transform.dx=parseFloat(pt[0],10);
+			this.transform.dy=parseFloat(pt[1],10);
+		}
+	};
+	ta.Annotation.Modes={ View:0, Edit:1 };
+	ta.Annotation.register=function(name,toolclass){
+		var cls=ta[name+'Annotation'];
+		ta.registerTool(name, function(p){
+			dojo.mixin(p, {
+				shape: name,
+				annotation:cls
+			});
+			return new (toolclass || ta.AnnotationTool)(p);
+		});
+	};
 })();
-}
diff --git a/dojox/sketch/DoubleArrowAnnotation.js b/dojox/sketch/DoubleArrowAnnotation.js
index 7757f33..e6084b8 100644
--- a/dojox/sketch/DoubleArrowAnnotation.js
+++ b/dojox/sketch/DoubleArrowAnnotation.js
@@ -1,178 +1,234 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch.DoubleArrowAnnotation"]){
-dojo._hasResource["dojox.sketch.DoubleArrowAnnotation"]=true;
 dojo.provide("dojox.sketch.DoubleArrowAnnotation");
+
 dojo.require("dojox.sketch.Annotation");
 dojo.require("dojox.sketch.Anchor");
+
 (function(){
-var ta=dojox.sketch;
-ta.DoubleArrowAnnotation=function(_1,id){
-ta.Annotation.call(this,_1,id);
-this.transform={dx:0,dy:0};
-this.start={x:0,y:0};
-this.control={x:100,y:-50};
-this.end={x:200,y:0};
-this.textPosition={x:0,y:0};
-this.textOffset=6;
-this.textYOffset=10;
-this.textAlign="middle";
-this.startRotation=0;
-this.endRotation=0;
-this.labelShape=null;
-this.pathShape=null;
-this.startArrow=null;
-this.startArrowGroup=null;
-this.endArrow=null;
-this.endArrowGroup=null;
-this.anchors.start=new ta.Anchor(this,"start");
-this.anchors.control=new ta.Anchor(this,"control");
-this.anchors.end=new ta.Anchor(this,"end");
-};
-ta.DoubleArrowAnnotation.prototype=new ta.Annotation;
-var p=ta.DoubleArrowAnnotation.prototype;
-p.constructor=ta.DoubleArrowAnnotation;
-p.type=function(){
-return "DoubleArrow";
-};
-p.getType=function(){
-return ta.DoubleArrowAnnotation;
-};
-p._rot=function(){
-var _2=this.control.y-this.start.y;
-var _3=this.control.x-this.start.x;
-this.startRotation=Math.atan2(_2,_3);
-_2=this.end.y-this.control.y;
-_3=this.end.x-this.control.x;
-this.endRotation=Math.atan2(_2,_3);
-};
-p._pos=function(){
-var _4=this.textOffset;
-if(this.control.y<this.end.y){
-_4*=-1;
-}else{
-_4+=this.textYOffset;
-}
-var ab={x:((this.control.x-this.start.x)*0.5)+this.start.x,y:((this.control.y-this.start.y)*0.5)+this.start.y};
-var bc={x:((this.end.x-this.control.x)*0.5)+this.control.x,y:((this.end.y-this.control.y)*0.5)+this.control.y};
-this.textPosition={x:((bc.x-ab.x)*0.5)+ab.x,y:(((bc.y-ab.y)*0.5)+ab.y)+_4};
-};
-p.apply=function(_5){
-if(!_5){
-return;
-}
-if(_5.documentElement){
-_5=_5.documentElement;
-}
-this.readCommonAttrs(_5);
-for(var i=0;i<_5.childNodes.length;i++){
-var c=_5.childNodes[i];
-if(c.localName=="text"){
-this.property("label",c.childNodes.length?c.childNodes[0].nodeValue:"");
-}else{
-if(c.localName=="path"){
-var d=c.getAttribute("d").split(" ");
-var s=d[0].split(",");
-this.start.x=parseFloat(s[0].substr(1),10);
-this.start.y=parseFloat(s[1],10);
-s=d[1].split(",");
-this.control.x=parseFloat(s[0].substr(1),10);
-this.control.y=parseFloat(s[1],10);
-s=d[2].split(",");
-this.end.x=parseFloat(s[0],10);
-this.end.y=parseFloat(s[1],10);
-var _6=this.property("stroke");
-var _7=c.getAttribute("style");
-var m=_7.match(/stroke:([^;]+);/);
-if(m){
-_6.color=m[1];
-this.property("fill",m[1]);
-}
-m=_7.match(/stroke-width:([^;]+);/);
-if(m){
-_6.width=m[1];
-}
-this.property("stroke",_6);
-}
-}
-}
-};
-p.initialize=function(_8){
-var _9=(ta.Annotation.labelFont)?ta.Annotation.labelFont:{family:"Times",size:"16px"};
-this.apply(_8);
-this._rot();
-this._pos();
-var _a=this.startRotation;
-var _b=dojox.gfx.matrix.rotate(_a);
-_a=this.endRotation;
-var _c=dojox.gfx.matrix.rotateAt(_a,this.end.x,this.end.y);
-this.shape=this.figure.group.createGroup();
-this.shape.getEventSource().setAttribute("id",this.id);
-this.pathShape=this.shape.createPath("M"+this.start.x+" "+this.start.y+"Q"+this.control.x+" "+this.control.y+" "+this.end.x+" "+this.end.y+" l0,0");
-this.startArrowGroup=this.shape.createGroup().setTransform({dx:this.start.x,dy:this.start.y});
-this.startArrowGroup.applyTransform(_b);
-this.startArrow=this.startArrowGroup.createPath();
-this.endArrowGroup=this.shape.createGroup().setTransform(_c);
-this.endArrow=this.endArrowGroup.createPath();
-this.labelShape=this.shape.createText({x:this.textPosition.x,y:this.textPosition.y,text:this.property("label"),align:this.textAlign}).setFill(this.property("fill"));
-this.labelShape.getEventSource().setAttribute("id",this.id+"-labelShape");
-this.draw();
-};
-p.destroy=function(){
-if(!this.shape){
-return;
-}
-this.startArrowGroup.remove(this.startArrow);
-this.endArrowGroup.remove(this.endArrow);
-this.shape.remove(this.startArrowGroup);
-this.shape.remove(this.endArrowGroup);
-this.shape.remove(this.pathShape);
-this.shape.remove(this.labelShape);
-this.figure.group.remove(this.shape);
-this.shape=this.pathShape=this.labelShape=this.startArrowGroup=this.startArrow=this.endArrowGroup=this.endArrow=null;
-};
-p.draw=function(_d){
-this.apply(_d);
-this._rot();
-this._pos();
-var _e=this.startRotation;
-var _f=dojox.gfx.matrix.rotate(_e);
-_e=this.endRotation;
-var _10=dojox.gfx.matrix.rotateAt(_e,this.end.x,this.end.y);
-this.shape.setTransform(this.transform);
-this.pathShape.setShape("M"+this.start.x+" "+this.start.y+" Q"+this.control.x+" "+this.control.y+" "+this.end.x+" "+this.end.y+" l0,0");
-this.startArrowGroup.setTransform({dx:this.start.x,dy:this.start.y}).applyTransform(_f);
-this.startArrow.setFill(this.property("fill"));
-this.endArrowGroup.setTransform(_10);
-this.endArrow.setFill(this.property("fill"));
-this.labelShape.setShape({x:this.textPosition.x,y:this.textPosition.y,text:this.property("label")}).setFill(this.property("fill"));
-this.zoom();
-};
-p.zoom=function(pct){
-if(this.startArrow){
-pct=pct||this.figure.zoomFactor;
-ta.Annotation.prototype.zoom.call(this,pct);
-var l=pct>1?20:Math.floor(20/pct),w=pct>1?5:Math.floor(5/pct),h=pct>1?3:Math.floor(3/pct);
-this.startArrow.setShape("M0,0 l"+l+",-"+w+" -"+h+","+w+" "+h+","+w+" Z");
-this.endArrow.setShape("M"+this.end.x+","+this.end.y+" l-"+l+",-"+w+" "+h+","+w+" -"+h+","+w+" Z");
-}
-};
-p.getBBox=function(){
-var x=Math.min(this.start.x,this.control.x,this.end.x);
-var y=Math.min(this.start.y,this.control.y,this.end.y);
-var w=Math.max(this.start.x,this.control.x,this.end.x)-x;
-var h=Math.max(this.start.y,this.control.y,this.end.y)-y;
-return {x:x,y:y,width:w,height:h};
-};
-p.serialize=function(){
-var s=this.property("stroke");
-return "<g "+this.writeCommonAttrs()+">"+"<path style=\"stroke:"+s.color+";stroke-width:"+s.width+";fill:none;\" d=\""+"M"+this.start.x+","+this.start.y+" "+"Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+"\" />"+"<g transform=\"translate("+this.start.x+","+this.start.y+") "+"rotate("+(Math.round((this.startRotation*(180/Math.PI))*Math.pow(10,4))/Math.pow(10,4))+")\">"+"<path style=\"fill:"+s.color+";\" d=\"M0,0 l20,-5, -3,5, 3,5 Z\" />"+"</g>"+"<g transform=\"rotate( [...]
-};
-ta.Annotation.register("DoubleArrow");
+	var ta=dojox.sketch;
+	ta.DoubleArrowAnnotation=function(figure, id){
+		ta.Annotation.call(this, figure, id);
+		this.transform={ dx:0, dy:0 };
+		this.start={x:0, y:0};
+		this.control={x:100, y:-50};
+		this.end={x:200, y:0};
+		this.textPosition={ x:0, y:0 };
+		this.textOffset=6;
+		this.textYOffset=10;
+		this.textAlign="middle";
+		this.startRotation=0;
+		this.endRotation=0;
+
+//		this.property('label',this.id);
+		this.labelShape=null;
+		this.pathShape=null;
+		this.startArrow=null;
+		this.startArrowGroup=null;
+		this.endArrow=null;
+		this.endArrowGroup=null;
+
+		this.anchors.start=new ta.Anchor(this, "start");
+		this.anchors.control=new ta.Anchor(this, "control");
+		this.anchors.end=new ta.Anchor(this, "end");
+	};
+	ta.DoubleArrowAnnotation.prototype=new ta.Annotation;
+	var p=ta.DoubleArrowAnnotation.prototype;
+	p.constructor=ta.DoubleArrowAnnotation;
+
+	p.type=function(){ return 'DoubleArrow'; };
+	p.getType=function(){ return ta.DoubleArrowAnnotation; };
+
+	p._rot=function(){
+		//	arrowhead rotation
+		var opp=this.control.y-this.start.y;
+		var adj=this.control.x-this.start.x;
+		this.startRotation=Math.atan2(opp,adj);
+
+		opp=this.end.y-this.control.y;
+		adj=this.end.x-this.control.x;
+		this.endRotation=Math.atan2(opp,adj);
+	};
+	p._pos=function(){
+		//	text position
+		var offset=this.textOffset;
+
+		//	figure out the pull of the curve and place accordingly
+		if(this.control.y<this.end.y){ offset*=-1; }
+		else { offset+=this.textYOffset; }
+		var ab={
+			x:((this.control.x-this.start.x)*.5)+this.start.x, 
+			y:((this.control.y-this.start.y)*.5)+this.start.y
+		};
+		var bc={
+			x:((this.end.x-this.control.x)*.5)+this.control.x, 
+			y:((this.end.y-this.control.y)*.5)+this.control.y
+		};
+		this.textPosition={
+			x:((bc.x-ab.x)*.5)+ab.x, 
+			y:(((bc.y-ab.y)*.5)+ab.y)+offset
+		};
+	};
+	
+	p.apply=function(obj){
+		if(!obj){ return; }
+		if(obj.documentElement){ obj=obj.documentElement; }
+		this.readCommonAttrs(obj);
+		
+		for(var i=0; i<obj.childNodes.length; i++){
+			var c=obj.childNodes[i];
+			if(c.localName=="text"){ this.property('label',c.childNodes.length?c.childNodes[0].nodeValue:''); }
+			else if(c.localName=="path"){
+				//	the line
+				var d=c.getAttribute('d').split(" ");
+				var s=d[0].split(",");
+				this.start.x=parseFloat(s[0].substr(1),10);
+				this.start.y=parseFloat(s[1],10);
+				s=d[1].split(",");
+				this.control.x=parseFloat(s[0].substr(1),10);
+				this.control.y=parseFloat(s[1],10);
+				s=d[2].split(",");
+				this.end.x=parseFloat(s[0],10);
+				this.end.y=parseFloat(s[1],10);
+				var stroke=this.property('stroke');
+				var style=c.getAttribute('style');
+				var m=style.match(/stroke:([^;]+);/);
+				if(m){
+					stroke.color=m[1];
+					this.property('fill',m[1]);
+				}
+				m=style.match(/stroke-width:([^;]+);/);
+				if(m){
+					stroke.width=m[1];
+				}
+				this.property('stroke',stroke);
+			}
+		}
+	};
+	p.initialize=function(obj){
+		//	create, based on passed DOM node if available.
+		var font=(ta.Annotation.labelFont)?ta.Annotation.labelFont:{family:"Times", size:"16px"};
+		this.apply(obj);
+
+		//	calculate the other positions
+		this._rot();
+		this._pos();
+
+		//	rotation matrix
+		var rot=this.startRotation;
+		var startRot=dojox.gfx.matrix.rotate(rot);
+
+		rot=this.endRotation;
+		var endRot=dojox.gfx.matrix.rotateAt(rot, this.end.x, this.end.y);
+
+		//	draw the shapes
+		this.shape=this.figure.group.createGroup();
+		this.shape.getEventSource().setAttribute("id", this.id);
+		//if(this.transform.dx||this.transform.dy){ this.shape.setTransform(this.transform); }
+
+		this.pathShape=this.shape.createPath("M"+this.start.x+" "+this.start.y+"Q"+this.control.x+" "+this.control.y+" "+this.end.x+" "+this.end.y + " l0,0")
+			//.setStroke(this.property('stroke'));
+		
+		this.startArrowGroup=this.shape.createGroup().setTransform({ dx:this.start.x, dy:this.start.y });
+		this.startArrowGroup.applyTransform(startRot);
+		this.startArrow=this.startArrowGroup.createPath();//"M0,0 l20,-5 -3,5 3,5 Z").setFill(this.property('fill'));
+		
+		this.endArrowGroup=this.shape.createGroup().setTransform(endRot);
+		this.endArrow=this.endArrowGroup.createPath();//("M" + this.end.x + "," + this.end.y + " l-20,-5 3,5 -3,5 Z").setFill(this.property('fill'));
+
+		this.labelShape=this.shape.createText({
+				x:this.textPosition.x, 
+				y:this.textPosition.y, 
+				text:this.property('label'), 
+				align:this.textAlign
+			})
+			//.setFont(font)
+			.setFill(this.property('fill'));
+		this.labelShape.getEventSource().setAttribute('id',this.id+"-labelShape");
+		this.draw();
+	};
+	p.destroy=function(){
+		if(!this.shape){ return; }
+		this.startArrowGroup.remove(this.startArrow);
+		this.endArrowGroup.remove(this.endArrow);
+		this.shape.remove(this.startArrowGroup);
+		this.shape.remove(this.endArrowGroup);
+		this.shape.remove(this.pathShape);
+		this.shape.remove(this.labelShape);
+		this.figure.group.remove(this.shape);
+		this.shape=this.pathShape=this.labelShape=this.startArrowGroup=this.startArrow=this.endArrowGroup=this.endArrow=null;
+	};
+	p.draw=function(obj){
+		this.apply(obj);
+		this._rot();
+		this._pos();
+
+		//	rotation matrix
+		var rot=this.startRotation;
+		var startRot=dojox.gfx.matrix.rotate(rot);
+		rot=this.endRotation;
+		var endRot=dojox.gfx.matrix.rotateAt(rot, this.end.x, this.end.y);
+
+		this.shape.setTransform(this.transform);
+		this.pathShape.setShape("M"+this.start.x+" "+this.start.y+" Q"+this.control.x+" "+this.control.y+" "+this.end.x+" "+this.end.y + " l0,0")
+			//.setStroke(this.property('stroke'));
+		this.startArrowGroup.setTransform({ dx:this.start.x, dy:this.start.y }).applyTransform(startRot);
+		this.startArrow.setFill(this.property('fill'));
+		
+		this.endArrowGroup.setTransform(endRot);
+		this.endArrow.setFill(this.property('fill'));
+		this.labelShape.setShape({
+				x:this.textPosition.x, 
+				y:this.textPosition.y, 
+				text:this.property('label')
+			})
+			.setFill(this.property('fill'));
+		this.zoom();
+	};
+
+	p.zoom=function(pct){
+		if(this.startArrow){
+			pct = pct || this.figure.zoomFactor;
+			ta.Annotation.prototype.zoom.call(this,pct);
+
+			var l=pct>1?20:Math.floor(20/pct), w=pct>1?5:Math.floor(5/pct),h=pct>1?3:Math.floor(3/pct);
+			this.startArrow.setShape("M0,0 l"+l+",-"+w+" -"+h+","+w+" "+h+","+w+" Z");//.setFill(this.property('fill'));
+
+			this.endArrow.setShape("M" + this.end.x + "," + this.end.y + " l-"+l+",-"+w+" "+h+","+w+" -"+h+","+w+" Z");
+		}
+	};
+	
+	p.getBBox=function(){
+		var x=Math.min(this.start.x, this.control.x, this.end.x);
+		var y=Math.min(this.start.y, this.control.y, this.end.y);
+		var w=Math.max(this.start.x, this.control.x, this.end.x)-x;
+		var h=Math.max(this.start.y, this.control.y, this.end.y)-y;
+		return { x:x, y:y, width:w, height:h };
+	};
+
+	p.serialize=function(){
+		var s=this.property('stroke');
+		return '<g '+this.writeCommonAttrs()+'>'
+			+ '<path style="stroke:'+s.color+';stroke-width:'+s.width+';fill:none;" d="'
+			+ "M"+this.start.x+","+this.start.y+" "
+			+ "Q"+this.control.x+","+this.control.y+" "
+			+ this.end.x+","+this.end.y
+			+ '" />'
+			+ '<g transform="translate(' + this.start.x + "," + this.start.y + ") "
+			+ 'rotate(' + (Math.round((this.startRotation*(180/Math.PI))*Math.pow(10,4))/Math.pow(10,4)) + ')">'
+			+ '<path style="fill:'+s.color+';" d="M0,0 l20,-5, -3,5, 3,5 Z" />'
+			+ '</g>'
+			+ '<g transform="rotate('
+			+ (Math.round((this.endRotation*(180/Math.PI))*Math.pow(10,4))/Math.pow(10,4))
+			+ ", "+this.end.x+", "+this.end.y
+			+ ')">'
+			+ '<path style="fill:'+s.color+';" d="M'+this.end.x+","+this.end.y+' l-20,-5, 3,5, -3,5 Z" />'
+			+ '</g>'
+			+ '<text style="fill:'+s.color+';text-anchor:'+this.textAlign+'" font-weight="bold" '
+			+ 'x="' + this.textPosition.x + '" '
+			+ 'y="' + this.textPosition.y + '">'
+			+ this.property('label')
+			+ '</text>'
+			+ '</g>';
+	};
+
+	ta.Annotation.register("DoubleArrow");
 })();
-}
diff --git a/dojox/sketch/Figure.js b/dojox/sketch/Figure.js
index 6f58672..2fd6d13 100644
--- a/dojox/sketch/Figure.js
+++ b/dojox/sketch/Figure.js
@@ -1,470 +1,526 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch.Figure"]){
-dojo._hasResource["dojox.sketch.Figure"]=true;
 dojo.provide("dojox.sketch.Figure");
 dojo.experimental("dojox.sketch");
+
 dojo.require("dojox.gfx");
 dojo.require("dojox.sketch.UndoStack");
+
 (function(){
-var ta=dojox.sketch;
-ta.tools={};
-ta.registerTool=function(_1,fn){
-ta.tools[_1]=fn;
-};
-ta.Figure=function(_2){
-var _3=this;
-this.annCounter=1;
-this.shapes=[];
-this.image=null;
-this.imageSrc=null;
-this.size={w:0,h:0};
-this.surface=null;
-this.group=null;
-this.node=null;
-this.zoomFactor=1;
-this.tools=null;
-this.obj={};
-dojo.mixin(this,_2);
-this.selected=[];
-this.hasSelections=function(){
-return this.selected.length>0;
-};
-this.isSelected=function(_4){
-for(var i=0;i<_3.selected.length;i++){
-if(_3.selected[i]==_4){
-return true;
-}
-}
-return false;
-};
-this.select=function(_5){
-if(!_3.isSelected(_5)){
-_3.clearSelections();
-_3.selected=[_5];
-}
-_5.setMode(ta.Annotation.Modes.View);
-_5.setMode(ta.Annotation.Modes.Edit);
-};
-this.deselect=function(_6){
-var _7=-1;
-for(var i=0;i<_3.selected.length;i++){
-if(_3.selected[i]==_6){
-_7=i;
-break;
-}
-}
-if(_7>-1){
-_6.setMode(ta.Annotation.Modes.View);
-_3.selected.splice(_7,1);
-}
-return _6;
-};
-this.clearSelections=function(){
-for(var i=0;i<_3.selected.length;i++){
-_3.selected[i].setMode(ta.Annotation.Modes.View);
-}
-_3.selected=[];
-};
-this.replaceSelection=function(n,o){
-if(!_3.isSelected(o)){
-_3.select(n);
-return;
-}
-var _8=-1;
-for(var i=0;i<_3.selected.length;i++){
-if(_3.selected[i]==o){
-_8=i;
-break;
-}
-}
-if(_8>-1){
-_3.selected.splice(_8,1,n);
-}
-};
-this._c=null;
-this._ctr=null;
-this._lp=null;
-this._action=null;
-this._prevState=null;
-this._startPoint=null;
-this._ctool=null;
-this._start=null;
-this._end=null;
-this._absEnd=null;
-this._cshape=null;
-this._dblclick=function(e){
-var o=_3._fromEvt(e);
-if(o){
-_3.onDblClickShape(o,e);
-}
-};
-this._keydown=function(e){
-var _9=false;
-if(e.ctrlKey){
-if(e.keyCode===90||e.keyCode===122){
-_3.undo();
-_9=true;
-}else{
-if(e.keyCode===89||e.keyCode===121){
-_3.redo();
-_9=true;
-}
-}
-}
-if(e.keyCode===46||e.keyCode===8){
-_3._delete(_3.selected);
-_9=true;
-}
-if(_9){
-dojo.stopEvent(e);
-}
-};
-this._md=function(e){
-if(dojox.gfx.renderer=="vml"){
-_3.node.focus();
-}
-var o=_3._fromEvt(e);
-_3._startPoint={x:e.pageX,y:e.pageY};
-_3._ctr=dojo.position(_3.node);
-var _a={x:_3.node.scrollLeft,y:_3.node.scrollTop};
-_3._ctr={x:_3._ctr.x-_a.x,y:_3._ctr.y-_a.y};
-var X=e.clientX-_3._ctr.x,Y=e.clientY-_3._ctr.y;
-_3._lp={x:X,y:Y};
-_3._start={x:X,y:Y};
-_3._end={x:X,y:Y};
-_3._absEnd={x:X,y:Y};
-if(!o){
-_3.clearSelections();
-_3._ctool.onMouseDown(e);
-}else{
-if(o.type&&o.type()!="Anchor"){
-if(!_3.isSelected(o)){
-_3.select(o);
-_3._sameShapeSelected=false;
-}else{
-_3._sameShapeSelected=true;
-}
-}
-o.beginEdit();
-_3._c=o;
-}
-};
-this._mm=function(e){
-if(!_3._ctr){
-return;
-}
-var x=e.clientX-_3._ctr.x;
-var y=e.clientY-_3._ctr.y;
-var dx=x-_3._lp.x;
-var dy=y-_3._lp.y;
-_3._absEnd={x:x,y:y};
-if(_3._c){
-_3._c.setBinding({dx:dx/_3.zoomFactor,dy:dy/_3.zoomFactor});
-_3._lp={x:x,y:y};
-}else{
-_3._end={x:dx,y:dy};
-var _b={x:Math.min(_3._start.x,_3._absEnd.x),y:Math.min(_3._start.y,_3._absEnd.y),width:Math.abs(_3._start.x-_3._absEnd.x),height:Math.abs(_3._start.y-_3._absEnd.y)};
-if(_b.width&&_b.height){
-_3._ctool.onMouseMove(e,_b);
-}
-}
-};
-this._mu=function(e){
-if(_3._c){
-_3._c.endEdit();
-}else{
-_3._ctool.onMouseUp(e);
-}
-_3._c=_3._ctr=_3._lp=_3._action=_3._prevState=_3._startPoint=null;
-_3._cshape=_3._start=_3._end=_3._absEnd=null;
-};
-this.initUndoStack();
-};
-var p=ta.Figure.prototype;
-p.initUndoStack=function(){
-this.history=new ta.UndoStack(this);
-};
-p.setTool=function(t){
-this._ctool=t;
-};
-p.gridSize=0;
-p._calCol=function(v){
-return this.gridSize?(Math.round(v/this.gridSize)*this.gridSize):v;
-};
-p._delete=function(_c,_d){
-for(var i=0;i<_c.length;i++){
-_c[i].setMode(ta.Annotation.Modes.View);
-_c[i].destroy(_d);
-this.remove(_c[i]);
-this._remove(_c[i]);
-if(!_d){
-_c[i].onRemove();
-}
-}
-_c.splice(0,_c.length);
-};
-p.onDblClickShape=function(_e,e){
-if(_e["onDblClick"]){
-_e.onDblClick(e);
-}
-};
-p.onCreateShape=function(_f){
-};
-p.onBeforeCreateShape=function(_10){
-};
-p.initialize=function(_11){
-this.node=_11;
-this.surface=dojox.gfx.createSurface(_11,this.size.w,this.size.h);
-this.group=this.surface.createGroup();
-this._cons=[];
-var es=this.surface.getEventSource();
-this._cons.push(dojo.connect(es,"ondraggesture",dojo.stopEvent),dojo.connect(es,"ondragenter",dojo.stopEvent),dojo.connect(es,"ondragover",dojo.stopEvent),dojo.connect(es,"ondragexit",dojo.stopEvent),dojo.connect(es,"ondragstart",dojo.stopEvent),dojo.connect(es,"onselectstart",dojo.stopEvent),dojo.connect(es,"onmousedown",this._md),dojo.connect(es,"onmousemove",this._mm),dojo.connect(es,"onmouseup",this._mu),dojo.connect(es,"onclick",this,"onClick"),dojo.connect(es,"ondblclick",this._dbl [...]
-this.image=this.group.createImage({width:this.imageSize.w,height:this.imageSize.h,src:this.imageSrc});
-};
-p.destroy=function(_12){
-if(!this.node){
-return;
-}
-if(!_12){
-if(this.history){
-this.history.destroy();
-}
-if(this._subscribed){
-dojo.unsubscribe(this._subscribed);
-delete this._subscribed;
-}
-}
-dojo.forEach(this._cons,dojo.disconnect);
-this._cons=[];
-dojo.empty(this.node);
-this.group=this.surface=null;
-this.obj={};
-this.shapes=[];
-};
-p.nextKey=function(){
-return "annotation-"+this.annCounter++;
-};
-p.draw=function(){
-};
-p.zoom=function(pct){
-this.zoomFactor=pct/100;
-var w=this.size.w*this.zoomFactor;
-var h=this.size.h*this.zoomFactor;
-this.surface.setDimensions(w,h);
-this.group.setTransform(dojox.gfx.matrix.scale(this.zoomFactor,this.zoomFactor));
-for(var i=0;i<this.shapes.length;i++){
-this.shapes[i].zoom(this.zoomFactor);
-}
-};
-p.getFit=function(){
-var wF=(this.node.parentNode.offsetWidth-5)/this.size.w;
-var hF=(this.node.parentNode.offsetHeight-5)/this.size.h;
-return Math.min(wF,hF)*100;
-};
-p.unzoom=function(){
-this.zoomFactor=1;
-this.surface.setDimensions(this.size.w,this.size.h);
-this.group.setTransform();
-};
-p._add=function(obj){
-this.obj[obj._key]=obj;
-};
-p._remove=function(obj){
-if(this.obj[obj._key]){
-delete this.obj[obj._key];
-}
-};
-p._get=function(key){
-if(key&&key.indexOf("bounding")>-1){
-key=key.replace("-boundingBox","");
-}else{
-if(key&&key.indexOf("-labelShape")>-1){
-key=key.replace("-labelShape","");
-}
-}
-return this.obj[key];
-};
-p._keyFromEvt=function(e){
-var key=e.target.id+"";
-if(key.length==0){
-var p=e.target.parentNode;
-var _13=this.surface.getEventSource();
-while(p&&p.id.length==0&&p!=_13){
-p=p.parentNode;
-}
-key=p.id;
-}
-return key;
-};
-p._fromEvt=function(e){
-return this._get(this._keyFromEvt(e));
-};
-p.add=function(_14){
-for(var i=0;i<this.shapes.length;i++){
-if(this.shapes[i]==_14){
-return true;
-}
-}
-this.shapes.push(_14);
-return true;
-};
-p.remove=function(_15){
-var idx=-1;
-for(var i=0;i<this.shapes.length;i++){
-if(this.shapes[i]==_15){
-idx=i;
-break;
-}
-}
-if(idx>-1){
-this.shapes.splice(idx,1);
-}
-return _15;
-};
-p.get=function(id){
-for(var i=0;i<this.shapes.length;i++){
-if(this.shapes[i].id==id){
-return this.shapes[i];
-}
-}
-return null;
-};
-p.convert=function(ann,t){
-var _16=t+"Annotation";
-if(!ta[_16]){
-return;
-}
-var _17=ann.type(),id=ann.id,_18=ann.label,_19=ann.mode,_1a=ann.tokenId;
-var _1b,end,_1c,_1d;
-switch(_17){
-case "Preexisting":
-case "Lead":
-_1d={dx:ann.transform.dx,dy:ann.transform.dy};
-_1b={x:ann.start.x,y:ann.start.y};
-end={x:ann.end.x,y:ann.end.y};
-var cx=end.x-((end.x-_1b.x)/2);
-var cy=end.y-((end.y-_1b.y)/2);
-_1c={x:cx,y:cy};
-break;
-case "SingleArrow":
-case "DoubleArrow":
-_1d={dx:ann.transform.dx,dy:ann.transform.dy};
-_1b={x:ann.start.x,y:ann.start.y};
-end={x:ann.end.x,y:ann.end.y};
-_1c={x:ann.control.x,y:ann.control.y};
-break;
-case "Underline":
-_1d={dx:ann.transform.dx,dy:ann.transform.dy};
-_1b={x:ann.start.x,y:ann.start.y};
-_1c={x:_1b.x+50,y:_1b.y+50};
-end={x:_1b.x+100,y:_1b.y+100};
-break;
-case "Brace":
-}
-var n=new ta[_16](this,id);
-if(n.type()=="Underline"){
-n.transform={dx:_1d.dx+_1b.x,dy:_1d.dy+_1b.y};
-}else{
-if(n.transform){
-n.transform=_1d;
-}
-if(n.start){
-n.start=_1b;
-}
-}
-if(n.end){
-n.end=end;
-}
-if(n.control){
-n.control=_1c;
-}
-n.label=_18;
-n.token=dojo.lang.shallowCopy(ann.token);
-n.initialize();
-this.replaceSelection(n,ann);
-this._remove(ann);
-this.remove(ann);
-ann.destroy();
-n.setMode(_19);
-};
-p.setValue=function(_1e){
-var obj=dojox.xml.DomParser.parse(_1e);
-var _1f=this.node;
-this.load(obj,_1f);
-};
-p.load=function(obj,n){
-if(this.surface){
-this.destroy(true);
-}
-var _20=obj.documentElement;
-this.size={w:parseFloat(_20.getAttribute("width"),10),h:parseFloat(_20.getAttribute("height"),10)};
-var g=_20.childrenByName("g")[0];
-var img=g.childrenByName("image")[0];
-this.imageSize={w:parseFloat(img.getAttribute("width"),10),h:parseFloat(img.getAttribute("height"),10)};
-this.imageSrc=img.getAttribute("xlink:href");
-this.initialize(n);
-var ann=g.childrenByName("g");
-for(var i=0;i<ann.length;i++){
-this._loadAnnotation(ann[i]);
-}
-if(this._loadDeferred){
-this._loadDeferred.callback(this);
-this._loadDeferred=null;
-}
-this.onLoad();
-};
-p.onLoad=function(){
-};
-p.onClick=function(){
-};
-p._loadAnnotation=function(obj){
-var _21=obj.getAttribute("dojoxsketch:type")+"Annotation";
-if(ta[_21]){
-var a=new ta[_21](this,obj.id);
-a.initialize(obj);
-this.nextKey();
-a.setMode(ta.Annotation.Modes.View);
-this._add(a);
-return a;
-}
-return null;
-};
-p.onUndo=function(){
-};
-p.onBeforeUndo=function(){
-};
-p.onRedo=function(){
-};
-p.onBeforeRedo=function(){
-};
-p.undo=function(){
-if(this.history){
-this.onBeforeUndo();
-this.history.undo();
-this.onUndo();
-}
-};
-p.redo=function(){
-if(this.history){
-this.onBeforeRedo();
-this.history.redo();
-this.onRedo();
-}
-};
-p.serialize=function(){
-var s="<svg xmlns=\"http://www.w3.org/2000/svg\" "+"xmlns:xlink=\"http://www.w3.org/1999/xlink\" "+"xmlns:dojoxsketch=\"http://dojotoolkit.org/dojox/sketch\" "+"width=\""+this.size.w+"\" height=\""+this.size.h+"\">"+"<g>"+"<image xlink:href=\""+this.imageSrc+"\" x=\"0\" y=\"0\" width=\""+this.size.w+"\" height=\""+this.size.h+"\" />";
-for(var i=0;i<this.shapes.length;i++){
-s+=this.shapes[i].serialize();
-}
-s+="</g></svg>";
-return s;
-};
-p.getValue=p.serialize;
+	var ta=dojox.sketch;
+	ta.tools={};
+	ta.registerTool=function(type, fn){ ta.tools[type]=fn; };
+	ta.Figure = function(mixin){
+		var self=this;
+		this.annCounter=1;
+
+		this.shapes=[];
+		this.image=null;
+		this.imageSrc=null;
+		this.size={ w:0, h:0 };
+		this.surface=null;
+		this.group=null;
+		//node should have tabindex set, otherwise keyboard action does not work
+		this.node=null;
+
+		this.zoomFactor=1;	//	multiplier for zooming.
+		
+		this.tools=null;	//	toolbar reference.
+
+		this.obj={};		//	lookup table for shapes.  Not keen on this solution.
+
+		dojo.mixin(this,mixin);
+
+		//	what is selected.
+		this.selected=[];
+		this.hasSelections=function(){ return this.selected.length>0 };
+		this.isSelected=function(obj){
+			for(var i=0; i<self.selected.length; i++){
+				if(self.selected[i]==obj){ return true; }
+			}
+			return false;
+		};
+		this.select=function(obj){
+			//	TODO: deal with multiple vs. single selections.
+			if(!self.isSelected(obj)){
+				//	force single select
+				self.clearSelections();
+				self.selected=[ obj ];
+			}
+			//	force a bbox update, regardless
+			obj.setMode(ta.Annotation.Modes.View);
+			obj.setMode(ta.Annotation.Modes.Edit);
+		};
+		this.deselect=function(obj){
+			var idx=-1;
+			for(var i=0; i<self.selected.length; i++){
+				if(self.selected[i]==obj){
+					idx=i;
+					break;
+				}
+			}
+			if(idx>-1){
+				obj.setMode(ta.Annotation.Modes.View);
+				self.selected.splice(idx,1);
+			}
+			return obj;
+		};
+		this.clearSelections=function(){
+			for(var i=0; i<self.selected.length; i++){ 
+				self.selected[i].setMode(ta.Annotation.Modes.View);
+			}
+			self.selected=[]; 
+		};
+		this.replaceSelection=function(n, o){
+			if(!self.isSelected(o)){
+				self.select(n);
+				return;
+			}
+			var idx=-1;
+			for(var i=0; i<self.selected.length; i++){
+				if(self.selected[i]==o){
+					idx=i; 
+					break;
+				}
+			}
+			if(idx>-1){
+				self.selected.splice(idx,1,n);
+			}
+		};
+
+		//	for the drag and drop handlers.
+		this._c=null;		//	current shape
+		this._ctr=null;	//	container measurements
+		this._lp=null;		//	last position
+		this._action=null;
+		this._prevState=null;
+		this._startPoint=null;	//	test to record a move.
+
+		//	if an object isn't selected and we're dragging anyways.
+		this._ctool=null;	//	hard code it.
+		this._start=null;
+		this._end=null;
+		this._absEnd=null;
+		this._cshape=null;
+
+		this._dblclick=function(e){
+			var o=self._fromEvt(e);
+			if(o){
+				self.onDblClickShape(o,e);
+			}
+		};
+
+		this._keydown=function(e){
+			var prevent=false;
+			if(e.ctrlKey){
+				if(e.keyCode===90 || e.keyCode===122){ //ctrl+z
+					self.undo();
+					prevent = true;
+				}
+				else if(e.keyCode===89 || e.keyCode===121){ //ctrl+y
+					self.redo();
+					prevent = true;
+				}
+			}
+
+			if(e.keyCode===46 || e.keyCode===8){ //delete or backspace
+				self._delete(self.selected);
+				prevent = true;
+			}
+
+			if(prevent){
+				dojo.stopEvent(e);
+			}
+		};
+	
+		//	drag handlers.
+		this._md=function(e){
+			//in IE, when clicking into the drawing canvas, the node does not get focused,
+			//do it manually here to force it, otherwise the keydown event listener is 
+			//never triggered in IE.
+			if(dojox.gfx.renderer=='vml'){
+				self.node.focus();
+			}
+			var o=self._fromEvt(e);
+			self._startPoint={ x:e.pageX, y:e.pageY };
+
+			self._ctr=dojo.position(self.node);
+			//	figure out the coordinates taking scroll into account
+			var scroll={x:self.node.scrollLeft,y:self.node.scrollTop};
+			//var win = dojo.window.get(self.node.ownerDocument);
+			//var scroll=dojo.withGlobal(win,dojo._docScroll);
+			self._ctr={x:self._ctr.x-scroll.x, y:self._ctr.y-scroll.y};
+			var X=e.clientX-self._ctr.x, Y=e.clientY-self._ctr.y;
+			self._lp={ x:X, y:Y };
+
+			//	capture it separately
+			self._start={ x:X, y:Y };
+			self._end={ x:X, y:Y };
+			self._absEnd={ x:X, y:Y };
+			if(!o){
+				self.clearSelections();
+				self._ctool.onMouseDown(e);
+			}else{
+				if(o.type && o.type()!="Anchor"){
+					if(!self.isSelected(o)){
+						self.select(o);
+						self._sameShapeSelected=false;
+					}else{
+						self._sameShapeSelected=true;
+					}
+				}
+				o.beginEdit();
+				self._c=o;
+			}
+		};
+		this._mm=function(e){
+			if(!self._ctr){ return; }
+			var x=e.clientX-self._ctr.x;
+			var y=e.clientY-self._ctr.y;
+			var dx=x-self._lp.x;
+			var dy=y-self._lp.y;
+			self._absEnd={x:x, y:y};
+			if(self._c){
+				//self._c.doChange({dx:dx, dy:dy});
+				self._c.setBinding({dx:dx/self.zoomFactor, dy:dy/self.zoomFactor});
+				self._lp={x:x, y:y};
+			} else {
+				self._end={x:dx, y:dy};
+				var rect={
+					x:Math.min(self._start.x,self._absEnd.x),
+					y:Math.min(self._start.y,self._absEnd.y),
+					width:Math.abs(self._start.x-self._absEnd.x),
+					height:Math.abs(self._start.y-self._absEnd.y)
+				}
+				if(rect.width && rect.height){
+					self._ctool.onMouseMove(e,rect);
+				}
+			}
+		};
+		this._mu=function(e){
+			if(self._c){
+				//	record the event.
+				self._c.endEdit();
+			}else{
+				self._ctool.onMouseUp(e);
+			}
+
+			//	clear the stuff out.
+			self._c=self._ctr=self._lp=self._action=self._prevState=self._startPoint=null;
+			self._cshape=self._start=self._end=self._absEnd=null;
+		};
+
+		this.initUndoStack();
+	};
+
+	var p=ta.Figure.prototype;
+	p.initUndoStack=function(){
+		this.history=new ta.UndoStack(this);
+	};
+	p.setTool=function(/*dojox.sketch._Plugin*/t){
+		this._ctool=t;
+	};
+    //gridSize: int
+    //      if it is greater than 0, all new shapes placed on the drawing will have coordinates
+    //      snapped to the gridSize. For example, if gridSize is set to 10, all coordinates
+    //      (only including coordinates which specifies the x/y position of shape are affected
+    //      by this parameter) will be dividable by 10
+    p.gridSize=0;
+    p._calCol=function(v){
+        return this.gridSize?(Math.round(v/this.gridSize)*this.gridSize):v;
+    };
+	p._delete=function(arr,noundo){
+		for(var i=0; i<arr.length; i++){
+			//var before=arr[i].serialize();
+			arr[i].setMode(ta.Annotation.Modes.View);
+			arr[i].destroy(noundo);
+			this.remove(arr[i]);
+			this._remove(arr[i]);
+			if(!noundo){
+				arr[i].onRemove();
+			}
+		}
+		arr.splice(0,arr.length);
+	};
+	p.onDblClickShape=function(shape,e){
+		if(shape['onDblClick']){
+			shape.onDblClick(e);
+		}
+	};
+
+	p.onCreateShape=function(shape){};
+	p.onBeforeCreateShape=function(shape){};
+	p.initialize=function(node){
+		this.node=node;
+		this.surface=dojox.gfx.createSurface(node, this.size.w, this.size.h);
+		//this.backgroundRect=this.surface.createRect({ x:0, y:0, width:this.size.w, height:this.size.h })
+		//	.setFill("white");
+		this.group=this.surface.createGroup();
+
+		this._cons=[];
+		var es=this.surface.getEventSource();
+		this._cons.push(
+			//	kill any dragging events.
+			//		for FF
+			dojo.connect(es, "ondraggesture", dojo.stopEvent),
+			dojo.connect(es, "ondragenter", dojo.stopEvent),
+			dojo.connect(es, "ondragover", dojo.stopEvent),
+			dojo.connect(es, "ondragexit", dojo.stopEvent),
+			dojo.connect(es, "ondragstart", dojo.stopEvent),
+			//		for IE
+			dojo.connect(es, "onselectstart", dojo.stopEvent),
+			//	hook up the drag system.
+			dojo.connect(es, 'onmousedown', this._md),
+			dojo.connect(es, 'onmousemove', this._mm),
+			dojo.connect(es, 'onmouseup', this._mu),
+			// misc hooks
+			dojo.connect(es, 'onclick', this, 'onClick'),
+			dojo.connect(es, 'ondblclick', this._dblclick),
+			dojo.connect(node, 'onkeydown', this._keydown));
+		
+		this.image=this.group.createImage({ width:this.imageSize.w, height:this.imageSize.h, src:this.imageSrc });
+	};
+
+	p.destroy=function(isLoading){
+		if(!this.node){ return; }
+		if(!isLoading){
+			if(this.history){ this.history.destroy(); }
+			if(this._subscribed){
+				dojo.unsubscribe(this._subscribed);
+				delete this._subscribed;
+			}
+		}
+		dojo.forEach(this._cons, dojo.disconnect);
+		this._cons=[];
+
+		//TODO: how to destroy a surface properly?
+		dojo.empty(this.node);
+
+		//this.node.removeChild(this.surface.getEventSource());
+		this.group=this.surface=null;
+		this.obj={};
+		this.shapes=[];
+	};
+	p.nextKey=function(){ return "annotation-"+this.annCounter++; };
+	p.draw=function(){ };
+	p.zoom=function(pct){
+		//	first get the new dimensions
+		this.zoomFactor=pct/100;
+		var w=this.size.w*this.zoomFactor;
+		var h=this.size.h*this.zoomFactor;
+		this.surface.setDimensions(w, h);
+		//	then scale it.
+		this.group.setTransform(dojox.gfx.matrix.scale(this.zoomFactor, this.zoomFactor));
+
+		for(var i=0; i<this.shapes.length; i++){
+			this.shapes[i].zoom(this.zoomFactor);
+		}
+	};
+	p.getFit=function(){
+		//	assume fitting the parent node.
+//		var box=dojo.html.getContentBox(this.node.parentNode);
+		//the following should work under IE and FF, not sure about others though
+		var wF=(this.node.parentNode.offsetWidth-5)/this.size.w;
+		var hF=(this.node.parentNode.offsetHeight-5)/this.size.h;
+		return Math.min(wF, hF)*100;
+	};
+	p.unzoom=function(){
+		//	restore original size.
+		this.zoomFactor=1;
+		this.surface.setDimensions(this.size.w, this.size.h);
+		this.group.setTransform();
+	};
+
+	//	object registry for drag handling.
+	p._add=function(obj){ this.obj[obj._key]=obj; };
+	p._remove=function(obj){
+		if(this.obj[obj._key]){
+			delete this.obj[obj._key];
+		}
+	};
+	p._get=function(key){
+		if(key&&key.indexOf("bounding")>-1){ 
+			key=key.replace("-boundingBox","");
+		}else if(key&&key.indexOf("-labelShape")>-1){
+			key=key.replace("-labelShape","");
+		}
+		return this.obj[key];
+	};
+	p._keyFromEvt=function(e){
+		var key=e.target.id+"";
+		if(key.length==0){
+			//	ancestor tree until you get to the end (meaning this.surface)
+			var p=e.target.parentNode;
+			var node=this.surface.getEventSource();
+			while(p && p.id.length==0 && p!=node){
+				p=p.parentNode;
+			}
+			key=p.id;
+		}
+		return key;
+	};
+	p._fromEvt=function(e){
+		return this._get(this._keyFromEvt(e));
+	};
+
+	p.add=function(annotation){
+		for(var i=0; i<this.shapes.length; i++){
+			if(this.shapes[i]==annotation){ return true; }
+		}
+		this.shapes.push(annotation);
+		return true;
+	};
+	p.remove=function(annotation){
+		var idx=-1;
+		for(var i=0; i<this.shapes.length; i++){
+			if(this.shapes[i]==annotation){
+				idx=i;
+				break;
+			}
+		}
+		if(idx>-1){ this.shapes.splice(idx, 1); }
+		return annotation;
+	};
+	p.getAnnotator=function(id){
+		for(var i=0; i<this.shapes.length; i++){
+			if(this.shapes[i].id==id) {
+				return this.shapes[i];
+			}
+		}
+		return null;
+	};
+
+	p.convert=function(ann, t){
+		//	convert an existing annotation to a different kind of annotation
+		var ctor=t+"Annotation";
+		if(!ta[ctor]){ return; }
+		var type=ann.type(), id=ann.id, label=ann.label, mode=ann.mode, tokenId=ann.tokenId;
+		var start, end, control, transform;
+		switch(type){
+			case "Preexisting":
+			case "Lead":{
+				transform={dx:ann.transform.dx, dy:ann.transform.dy };
+				start={x:ann.start.x, y:ann.start.y};
+				end={x:ann.end.x, y:ann.end.y };
+				var cx=end.x-((end.x-start.x)/2);
+				var cy=end.y-((end.y-start.y)/2);
+				control={x:cx, y:cy};
+				break;
+			}
+			case "SingleArrow":
+			case "DoubleArrow":{
+				transform={dx:ann.transform.dx, dy:ann.transform.dy };
+				start={x:ann.start.x, y:ann.start.y};
+				end={x:ann.end.x, y:ann.end.y };
+				control={x:ann.control.x, y:ann.control.y};
+				break;
+			}
+			case "Underline":{
+				transform={dx:ann.transform.dx, dy:ann.transform.dy };
+				start={x:ann.start.x, y:ann.start.y};
+				control={x:start.x+50, y:start.y+50 };
+				end={x:start.x+100, y:start.y+100 };
+				break;
+			}
+			case "Brace":{ }
+		}
+		var n=new ta[ctor](this, id);
+
+		if(n.type()=="Underline"){
+			//	special handling, since we never move the start point.
+			n.transform={dx:transform.dx+start.x, dy:transform.dy+start.y };
+		} else {
+			if(n.transform){ n.transform=transform; }
+			if(n.start){ n.start=start; }
+		}
+		if(n.end){ n.end=end; }
+		if(n.control){ n.control=control; }
+		n.label=label;
+		n.token=dojo.lang.shallowCopy(ann.token);
+		n.initialize();
+
+		this.replaceSelection(n, ann);
+		this._remove(ann);
+		this.remove(ann);
+		ann.destroy();
+
+		//	this should do all the things we need it to do for getting it registered.
+		n.setMode(mode);
+	};
+	p.setValue=function(text){
+		var obj=dojox.xml.DomParser.parse(text);
+		var node=this.node;
+		this.load(obj,node);
+		//this.zoom(this.zoomFactor*100); //zoom to orignal scale
+	};
+	p.load=function(obj, n){
+		//	create from pseudo-DOM
+		if(this.surface){ this.destroy(true); }
+		var node=obj.documentElement;	//	should be either the document or the docElement
+		this.size={ 
+			w:parseFloat(node.getAttribute('width'),10), 
+			h:parseFloat(node.getAttribute('height'),10) 
+		};
+		var g=node.childrenByName("g")[0];
+		var img=g.childrenByName("image")[0];
+		this.imageSize={
+			w:parseFloat(img.getAttribute('width'),10), 
+			h:parseFloat(img.getAttribute('height'),10) 
+		};
+		this.imageSrc=img.getAttribute("xlink:href");
+		this.initialize(n);
+
+		//	now let's do the annotations.
+		var ann=g.childrenByName("g");
+		for(var i=0; i<ann.length; i++){ this._loadAnnotation(ann[i]); }
+		if(this._loadDeferred){
+			this._loadDeferred.callback(this);
+			this._loadDeferred=null;
+		}
+		this.onLoad();
+	};
+	p.onLoad=function(){};
+	p.onClick=function(){};
+	p._loadAnnotation=function(obj){
+		var ctor=obj.getAttribute('dojoxsketch:type')+"Annotation";
+		if(ta[ctor]){
+			var a=new ta[ctor](this, obj.id);
+			a.initialize(obj);
+			this.nextKey();
+			a.setMode(ta.Annotation.Modes.View);
+			this._add(a);
+			return a;
+		}
+		return null;
+	};
+	
+	p.onUndo=function(){};
+	p.onBeforeUndo=function(){};
+	p.onRedo=function(){};
+	p.onBeforeRedo=function(){};
+	p.undo=function(){
+		if(this.history){
+			this.onBeforeUndo();
+			this.history.undo();
+			this.onUndo();
+		}
+	};
+	p.redo=function(){
+		if(this.history){
+			this.onBeforeRedo();
+			this.history.redo();
+			this.onRedo();
+		}
+	};
+	p.serialize=function(){
+		var s='<svg xmlns="http://www.w3.org/2000/svg" '
+			+ 'xmlns:xlink="http://www.w3.org/1999/xlink" '
+			+ 'xmlns:dojoxsketch="http://dojotoolkit.org/dojox/sketch" '
+			+ 'width="' + this.size.w + '" height="' + this.size.h + '">'
+			+ '<g>'
+			+ '<image xlink:href="' + this.imageSrc + '" x="0" y="0" width="' 
+			+ this.size.w + '" height="' + this.size.h + '" />';
+		for(var i=0; i<this.shapes.length; i++){ s+= this.shapes[i].serialize(); }
+		s += '</g></svg>';
+		return s;
+	};
+	p.getValue=p.serialize;
 })();
-}
diff --git a/dojox/sketch/LeadAnnotation.js b/dojox/sketch/LeadAnnotation.js
index 791a278..7d7fc65 100644
--- a/dojox/sketch/LeadAnnotation.js
+++ b/dojox/sketch/LeadAnnotation.js
@@ -1,151 +1,162 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch.LeadAnnotation"]){
-dojo._hasResource["dojox.sketch.LeadAnnotation"]=true;
 dojo.provide("dojox.sketch.LeadAnnotation");
 dojo.require("dojox.sketch.Annotation");
 dojo.require("dojox.sketch.Anchor");
+
 (function(){
-var ta=dojox.sketch;
-ta.LeadAnnotation=function(_1,id){
-ta.Annotation.call(this,_1,id);
-this.transform={dx:0,dy:0};
-this.start={x:0,y:0};
-this.control={x:100,y:-50};
-this.end={x:200,y:0};
-this.textPosition={x:0,y:0};
-this.textOffset=4;
-this.textYOffset=10;
-this.pathShape=null;
-this.labelShape=null;
-this.anchors.start=new ta.Anchor(this,"start");
-this.anchors.control=new ta.Anchor(this,"control");
-this.anchors.end=new ta.Anchor(this,"end");
-};
-ta.LeadAnnotation.prototype=new ta.Annotation;
-var p=ta.LeadAnnotation.prototype;
-p.constructor=ta.LeadAnnotation;
-p.type=function(){
-return "Lead";
-};
-p.getType=function(){
-return ta.LeadAnnotation;
-};
-p._pos=function(){
-var _2=this.textOffset,x=0,y=0;
-var _3=this.calculate.slope(this.control,this.end);
-this.textAlign="middle";
-if(Math.abs(_3)>=1){
-x=this.end.x+this.calculate.dx(this.control,this.end,_2);
-if(this.control.y>this.end.y){
-y=this.end.y-_2;
-}else{
-y=this.end.y+_2+this.textYOffset;
-}
-}else{
-if(_3==0){
-x=this.end.x+_2;
-y=this.end.y+this.textYOffset;
-}else{
-if(this.start.x>this.end.x){
-x=this.end.x-_2;
-this.textAlign="end";
-}else{
-x=this.end.x+_2;
-this.textAlign="start";
-}
-if(this.start.y<this.end.y){
-y=this.end.y+this.calculate.dy(this.control,this.end,_2)+this.textYOffset;
-}else{
-y=this.end.y+this.calculate.dy(this.control,this.end,-_2);
-}
-}
-}
-this.textPosition={x:x,y:y};
-};
-p.apply=function(_4){
-if(!_4){
-return;
-}
-if(_4.documentElement){
-_4=_4.documentElement;
-}
-this.readCommonAttrs(_4);
-for(var i=0;i<_4.childNodes.length;i++){
-var c=_4.childNodes[i];
-if(c.localName=="text"){
-this.property("label",c.childNodes.length?c.childNodes[0].nodeValue:"");
-}else{
-if(c.localName=="path"){
-var d=c.getAttribute("d").split(" ");
-var s=d[0].split(",");
-this.start.x=parseFloat(s[0].substr(1),10);
-this.start.y=parseFloat(s[1],10);
-s=d[1].split(",");
-this.control.x=parseFloat(s[0].substr(1),10);
-this.control.y=parseFloat(s[1],10);
-s=d[2].split(",");
-this.end.x=parseFloat(s[0],10);
-this.end.y=parseFloat(s[1],10);
-var _5=this.property("stroke");
-var _6=c.getAttribute("style");
-var m=_6.match(/stroke:([^;]+);/);
-if(m){
-_5.color=m[1];
-this.property("fill",m[1]);
-}
-m=_6.match(/stroke-width:([^;]+);/);
-if(m){
-_5.width=m[1];
-}
-this.property("stroke",_5);
-}
-}
-}
-};
-p.initialize=function(_7){
-this.apply(_7);
-this._pos();
-this.shape=this.figure.group.createGroup();
-this.shape.getEventSource().setAttribute("id",this.id);
-this.pathShape=this.shape.createPath("M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0");
-this.labelShape=this.shape.createText({x:this.textPosition.x,y:this.textPosition.y,text:this.property("label"),align:this.textAlign});
-this.labelShape.getEventSource().setAttribute("id",this.id+"-labelShape");
-this.draw();
-};
-p.destroy=function(){
-if(!this.shape){
-return;
-}
-this.shape.remove(this.pathShape);
-this.shape.remove(this.labelShape);
-this.figure.group.remove(this.shape);
-this.shape=this.pathShape=this.labelShape=null;
-};
-p.getBBox=function(){
-var x=Math.min(this.start.x,this.control.x,this.end.x);
-var y=Math.min(this.start.y,this.control.y,this.end.y);
-var w=Math.max(this.start.x,this.control.x,this.end.x)-x;
-var h=Math.max(this.start.y,this.control.y,this.end.y)-y;
-return {x:x,y:y,width:w,height:h};
-};
-p.draw=function(_8){
-this.apply(_8);
-this._pos();
-this.shape.setTransform(this.transform);
-this.pathShape.setShape("M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0");
-this.labelShape.setShape({x:this.textPosition.x,y:this.textPosition.y,text:this.property("label")}).setFill(this.property("fill"));
-this.zoom();
-};
-p.serialize=function(){
-var _9=this.property("stroke");
-return "<g "+this.writeCommonAttrs()+">"+"<path style=\"stroke:"+_9.color+";stroke-width:"+_9.width+";fill:none;\" d=\""+"M"+this.start.x+","+this.start.y+" "+"Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+"\" />"+"<text style=\"fill:"+_9.color+";text-anchor:"+this.textAlign+"\" font-weight=\"bold\" "+"x=\""+this.textPosition.x+"\" "+"y=\""+this.textPosition.y+"\">"+this.property("label")+"</text>"+"</g>";
-};
-ta.Annotation.register("Lead");
+	var ta=dojox.sketch;
+	ta.LeadAnnotation=function(figure, id){
+		ta.Annotation.call(this, figure, id);
+		this.transform={dx:0, dy:0 };
+		this.start={ x:0, y:0 };
+		this.control={x:100, y:-50};
+		this.end={ x:200, y:0 };
+		this.textPosition={ x:0, y:0 };
+		this.textOffset=4;
+		//this.textAlign="middle";
+		this.textYOffset=10;
+
+//		this.property('label',this.id);
+		this.pathShape=null;
+		this.labelShape=null;
+
+		this.anchors.start=new ta.Anchor(this, "start");
+		this.anchors.control=new ta.Anchor(this, "control");
+		this.anchors.end=new ta.Anchor(this, "end");
+	};
+	ta.LeadAnnotation.prototype=new ta.Annotation;
+	var p=ta.LeadAnnotation.prototype;
+	p.constructor=ta.LeadAnnotation;
+
+	p.type=function(){ return 'Lead'; }
+	p.getType=function(){ return ta.LeadAnnotation; };
+
+	p._pos=function(){
+		var offset=this.textOffset, x=0, y=0;
+		var slope=this.calculate.slope(this.control, this.end);
+		this.textAlign="middle";
+		if(Math.abs(slope)>=1){
+			x=this.end.x+this.calculate.dx(this.control, this.end, offset);
+			if(this.control.y>this.end.y){ 
+				y=this.end.y-offset; 
+			} else { 
+				y=this.end.y+offset+this.textYOffset; 
+			}
+		} else if(slope==0){
+			x=this.end.x+offset;
+			y=this.end.y+this.textYOffset;
+		} else {
+			if(this.start.x>this.end.x){
+				x=this.end.x-offset;
+				this.textAlign="end";
+			} else {
+				x=this.end.x+offset;
+				this.textAlign="start";
+			}
+			if(this.start.y<this.end.y){
+				y=this.end.y+this.calculate.dy(this.control, this.end, offset)+this.textYOffset;
+			} else { 
+				y=this.end.y+this.calculate.dy(this.control, this.end, -offset);
+			}
+		}
+		this.textPosition={ x:x, y:y };
+	};
+	p.apply=function(obj){
+		if(!obj){ return; }
+		if(obj.documentElement){ obj=obj.documentElement; }
+		this.readCommonAttrs(obj);
+		
+		for(var i=0; i<obj.childNodes.length; i++){
+			var c=obj.childNodes[i];
+			if(c.localName=="text"){ 
+				this.property('label',c.childNodes.length?c.childNodes[0].nodeValue:'');
+			}
+			else if(c.localName=="path"){
+				//	the line
+				var d=c.getAttribute('d').split(" ");
+				var s=d[0].split(",");
+				this.start.x=parseFloat(s[0].substr(1),10);
+				this.start.y=parseFloat(s[1],10);
+				s=d[1].split(",");
+				this.control.x=parseFloat(s[0].substr(1),10);
+				this.control.y=parseFloat(s[1],10);
+				s=d[2].split(",");
+				this.end.x=parseFloat(s[0],10);
+				this.end.y=parseFloat(s[1],10);
+				var stroke=this.property('stroke');
+				var style=c.getAttribute('style');
+				var m=style.match(/stroke:([^;]+);/);
+				if(m){
+					stroke.color=m[1];
+					this.property('fill',m[1]);
+				}
+				m=style.match(/stroke-width:([^;]+);/);
+				if(m){
+					stroke.width=m[1];
+				}
+				this.property('stroke',stroke);
+			}
+		}
+	};
+
+	p.initialize=function(obj){
+		this.apply(obj);
+		this._pos();
+
+		//	create either from scratch or based on the passed node
+		this.shape=this.figure.group.createGroup();
+		this.shape.getEventSource().setAttribute("id", this.id);
+		this.pathShape=this.shape.createPath("M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0");
+		this.labelShape=this.shape.createText({
+				x:this.textPosition.x, 
+				y:this.textPosition.y, 
+				text:this.property('label'), 
+				align:this.textAlign
+			});
+		this.labelShape.getEventSource().setAttribute('id',this.id+"-labelShape");
+		this.draw();
+	};
+	p.destroy=function(){
+		if(!this.shape){ return; }
+		this.shape.remove(this.pathShape);
+		this.shape.remove(this.labelShape);
+		this.figure.group.remove(this.shape);
+		this.shape=this.pathShape=this.labelShape=null;
+	};
+	p.getBBox=function(){
+		var x=Math.min(this.start.x, this.control.x, this.end.x);
+		var y=Math.min(this.start.y, this.control.y, this.end.y);
+		var w=Math.max(this.start.x, this.control.x, this.end.x)-x;
+		var h=Math.max(this.start.y, this.control.y, this.end.y)-y;
+		return { x:x, y:y, width:w, height:h };
+	};
+	p.draw=function(obj){
+		this.apply(obj);
+		this._pos();
+		this.shape.setTransform(this.transform);
+		this.pathShape.setShape("M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0");
+		this.labelShape.setShape({ 
+				x:this.textPosition.x, 
+				y:this.textPosition.y, 
+				text:this.property('label') 
+			})
+			.setFill(this.property('fill'));
+		this.zoom();
+	};
+	p.serialize=function(){
+		var stroke=this.property('stroke');
+		return '<g '+this.writeCommonAttrs()+'>'
+			+ '<path style="stroke:'+stroke.color+';stroke-width:'+stroke.width+';fill:none;" d="'
+			+ "M"+this.start.x+","+this.start.y+" "
+			+ "Q"+this.control.x+","+this.control.y+" "
+			+ this.end.x+","+this.end.y
+			+ '" />'
+			+ '<text style="fill:'+stroke.color+';text-anchor:'+this.textAlign+'" font-weight="bold" '
+			+ 'x="' + this.textPosition.x + '" '
+			+ 'y="' + this.textPosition.y + '">'
+			+ this.property('label')
+			+ '</text>'
+			+ '</g>';
+	};
+
+	ta.Annotation.register("Lead");
 })();
-}
diff --git a/dojox/sketch/PreexistingAnnotation.js b/dojox/sketch/PreexistingAnnotation.js
index 8c58e30..5b526d8 100644
--- a/dojox/sketch/PreexistingAnnotation.js
+++ b/dojox/sketch/PreexistingAnnotation.js
@@ -1,141 +1,165 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch.PreexistingAnnotation"]){
-dojo._hasResource["dojox.sketch.PreexistingAnnotation"]=true;
 dojo.provide("dojox.sketch.PreexistingAnnotation");
+
 dojo.require("dojox.sketch.Annotation");
 dojo.require("dojox.sketch.Anchor");
+
 (function(){
-var ta=dojox.sketch;
-ta.PreexistingAnnotation=function(_1,id){
-ta.Annotation.call(this,_1,id);
-this.transform={dx:0,dy:0};
-this.start={x:0,y:0};
-this.end={x:200,y:200};
-this.radius=8;
-this.textPosition={x:196,y:196};
-this.textOffset=4;
-this.textAlign="end";
-this.rectShape=null;
-this.labelShape=null;
-this.anchors.start=new ta.Anchor(this,"start");
-this.anchors.end=new ta.Anchor(this,"end");
-};
-ta.PreexistingAnnotation.prototype=new ta.Annotation;
-var p=ta.PreexistingAnnotation.prototype;
-p.constructor=ta.PreexistingAnnotation;
-p.type=function(){
-return "Preexisting";
-};
-p.getType=function(){
-return ta.PreexistingAnnotation;
-};
-p._pos=function(){
-var x=Math.min(this.start.x,this.end.x);
-var y=Math.min(this.start.y,this.end.y);
-var w=Math.max(this.start.x,this.end.x);
-var h=Math.max(this.start.y,this.end.y);
-this.start={x:x,y:y};
-this.end={x:w,y:h};
-this.textPosition={x:this.end.x-this.textOffset,y:this.end.y-this.textOffset};
-};
-p.apply=function(_2){
-if(!_2){
-return;
-}
-if(_2.documentElement){
-_2=_2.documentElement;
-}
-this.readCommonAttrs(_2);
-for(var i=0;i<_2.childNodes.length;i++){
-var c=_2.childNodes[i];
-if(c.localName=="text"){
-this.property("label",c.childNodes.length?c.childNodes[0].nodeValue:"");
-}else{
-if(c.localName=="rect"){
-if(c.getAttribute("x")!==null){
-this.start.x=parseFloat(c.getAttribute("x"),10);
-}
-if(c.getAttribute("width")!==null){
-this.end.x=parseFloat(c.getAttribute("width"),10)+parseFloat(c.getAttribute("x"),10);
-}
-if(c.getAttribute("y")!==null){
-this.start.y=parseFloat(c.getAttribute("y"),10);
-}
-if(c.getAttribute("height")!==null){
-this.end.y=parseFloat(c.getAttribute("height"),10)+parseFloat(c.getAttribute("y"),10);
-}
-if(c.getAttribute("r")!==null){
-this.radius=parseFloat(c.getAttribute("r"),10);
-}
-var _3=this.property("stroke");
-var _4=c.getAttribute("style");
-var m=_4.match(/stroke:([^;]+);/);
-if(m){
-_3.color=m[1];
-this.property("fill",m[1]);
-}
-m=_4.match(/stroke-width:([^;]+);/);
-if(m){
-_3.width=m[1];
-}
-this.property("stroke",_3);
-}
-}
-}
-};
-p.initialize=function(_5){
-this.apply(_5);
-this._pos();
-this.shape=this.figure.group.createGroup();
-this.shape.getEventSource().setAttribute("id",this.id);
-this.rectShape=this.shape.createRect({x:this.start.x,y:this.start.y,width:this.end.x-this.start.x,height:this.end.y-this.start.y,r:this.radius}).setFill([255,255,255,0.1]);
-this.rectShape.getEventSource().setAttribute("shape-rendering","crispEdges");
-this.labelShape=this.shape.createText({x:this.textPosition.x,y:this.textPosition.y,text:this.property("label"),align:this.textAlign}).setFill(this.property("fill"));
-this.labelShape.getEventSource().setAttribute("id",this.id+"-labelShape");
-this.draw();
-};
-p.destroy=function(){
-if(!this.shape){
-return;
-}
-this.shape.remove(this.rectShape);
-this.shape.remove(this.labelShape);
-this.figure.group.remove(this.shape);
-this.shape=this.rectShape=this.labelShape=null;
-};
-p.getBBox=function(){
-var x=Math.min(this.start.x,this.end.x);
-var y=Math.min(this.start.y,this.end.y);
-var w=Math.max(this.start.x,this.end.x)-x;
-var h=Math.max(this.start.y,this.end.y)-y;
-return {x:x-2,y:y-2,width:w+4,height:h+4};
-};
-p.draw=function(_6){
-this.apply(_6);
-this._pos();
-this.shape.setTransform(this.transform);
-this.rectShape.setShape({x:this.start.x,y:this.start.y,width:this.end.x-this.start.x,height:this.end.y-this.start.y,r:this.radius}).setFill([255,255,255,0.1]);
-this.labelShape.setShape({x:this.textPosition.x,y:this.textPosition.y,text:this.property("label")}).setFill(this.property("fill"));
-this.zoom();
-};
-p.zoom=function(_7){
-if(this.rectShape){
-_7=_7||this.figure.zoomFactor;
-ta.Annotation.prototype.zoom.call(this,_7);
-_7=dojox.gfx.renderer=="vml"?1:_7;
-this.rectShape.setStroke({color:this.property("fill"),width:1/_7});
-}
-};
-p.serialize=function(){
-var s=this.property("stroke");
-return "<g "+this.writeCommonAttrs()+">"+"<rect style=\"stroke:"+s.color+";stroke-width:1;fill:none;\" "+"x=\""+this.start.x+"\" "+"width=\""+(this.end.x-this.start.x)+"\" "+"y=\""+this.start.y+"\" "+"height=\""+(this.end.y-this.start.y)+"\" "+"rx=\""+this.radius+"\" "+"ry=\""+this.radius+"\" "+" />"+"<text style=\"fill:"+s.color+";text-anchor:"+this.textAlign+"\" font-weight=\"bold\" "+"x=\""+this.textPosition.x+"\" "+"y=\""+this.textPosition.y+"\">"+this.property("label")+"</text>"+"</g>";
-};
-ta.Annotation.register("Preexisting");
+	var ta=dojox.sketch;
+	ta.PreexistingAnnotation=function(figure, id){
+		ta.Annotation.call(this, figure, id);
+		this.transform={dx:0, dy:0};
+		this.start={ x:0, y:0 };
+		this.end={ x:200, y:200 };
+		this.radius=8;
+		this.textPosition={ x:196, y:196 };
+		this.textOffset=4;
+		this.textAlign="end";
+
+		//this.property('label',this.id);
+		this.rectShape=null;
+		this.labelShape=null;
+
+		this.anchors.start=new ta.Anchor(this, "start");
+		this.anchors.end=new ta.Anchor(this, "end");
+	};
+	ta.PreexistingAnnotation.prototype=new ta.Annotation;
+	var p=ta.PreexistingAnnotation.prototype;
+	p.constructor=ta.PreexistingAnnotation;
+
+	p.type=function(){ return 'Preexisting' };
+	p.getType=function(){ return ta.PreexistingAnnotation; };
+
+	p._pos=function(){
+		var x=Math.min(this.start.x, this.end.x);
+		var y=Math.min(this.start.y, this.end.y);
+		var w=Math.max(this.start.x, this.end.x);
+		var h=Math.max(this.start.y, this.end.y);
+		this.start={ x:x, y:y };
+		this.end={ x:w, y:h };
+		this.textPosition={ x:this.end.x-this.textOffset, y:this.end.y-this.textOffset };
+	};
+	p.apply=function(obj){
+		if(!obj){ return; }
+		if(obj.documentElement){ obj=obj.documentElement; }
+		this.readCommonAttrs(obj);
+		
+		for(var i=0; i<obj.childNodes.length; i++){
+			var c=obj.childNodes[i];
+			if(c.localName=="text"){ 
+				this.property('label',c.childNodes.length?c.childNodes[0].nodeValue:'');
+			}
+			else if(c.localName=="rect"){
+				if(c.getAttribute('x')!==null){ this.start.x=parseFloat(c.getAttribute('x'), 10); }
+				if(c.getAttribute('width')!==null){ this.end.x=parseFloat(c.getAttribute('width'), 10)+parseFloat(c.getAttribute('x'), 10); }
+				if(c.getAttribute('y')!==null){ this.start.y=parseFloat(c.getAttribute('y'), 10); }
+				if(c.getAttribute('height')!==null){ this.end.y=parseFloat(c.getAttribute('height'), 10)+parseFloat(c.getAttribute('y'), 10); }
+				if(c.getAttribute('r')!==null){ this.radius=parseFloat(c.getAttribute('r'),10); }
+				var stroke=this.property('stroke');
+				var style=c.getAttribute('style');
+				var m=style.match(/stroke:([^;]+);/);
+				if(m){
+					stroke.color=m[1];
+					this.property('fill',m[1]);
+				}
+				m=style.match(/stroke-width:([^;]+);/);
+				if(m){
+					stroke.width=m[1];
+				}
+				this.property('stroke',stroke);
+			}
+		}
+	};
+	p.initialize=function(obj){
+		this.apply(obj);
+		this._pos();
+
+		//	create either from scratch or based on the passed node
+		this.shape=this.figure.group.createGroup();
+		this.shape.getEventSource().setAttribute("id", this.id);
+		//if(this.transform.dx || this.transform.dy){ this.shape.setTransform(this.transform); }
+		this.rectShape=this.shape.createRect({
+				x:this.start.x, 
+				y: this.start.y, 
+				width: this.end.x-this.start.x, 
+				height:this.end.y-this.start.y, 
+				r:this.radius
+			})
+			//.setStroke({color:this.property('fill'), width:1})
+			.setFill([255,255,255,0.1]);
+		this.rectShape.getEventSource().setAttribute("shape-rendering","crispEdges");
+		this.labelShape=this.shape.createText({
+				x:this.textPosition.x, 
+				y:this.textPosition.y, 
+				text:this.property('label'), 
+				align:this.textAlign
+			})
+			//.setFont(font)
+			.setFill(this.property('fill'));
+		this.labelShape.getEventSource().setAttribute('id',this.id+"-labelShape");
+		this.draw();
+	};
+	p.destroy=function(){
+		if(!this.shape){ return; }
+		this.shape.remove(this.rectShape);
+		this.shape.remove(this.labelShape);
+		this.figure.group.remove(this.shape);
+		this.shape=this.rectShape=this.labelShape=null;
+	};
+	p.getBBox=function(){
+		var x=Math.min(this.start.x, this.end.x);
+		var y=Math.min(this.start.y, this.end.y);
+		var w=Math.max(this.start.x, this.end.x)-x;
+		var h=Math.max(this.start.y, this.end.y)-y;
+		return { x:x-2, y:y-2, width:w+4, height:h+4 };
+	};
+	p.draw=function(obj){
+		this.apply(obj);
+		this._pos();
+		this.shape.setTransform(this.transform);
+		this.rectShape.setShape({
+				x:this.start.x, 
+				y: this.start.y, 
+				width: this.end.x-this.start.x, 
+				height:this.end.y-this.start.y, 
+				r:this.radius
+			})
+			//.setStroke({ color:this.property('fill'), width:1 })
+			.setFill([255,255,255,0.1]);
+
+		this.labelShape.setShape({ 
+				x:this.textPosition.x, 
+				y:this.textPosition.y, 
+				text:this.property('label') 
+			})
+			.setFill(this.property('fill'));
+		this.zoom();
+	};
+	p.zoom=function(pct){
+		if(this.rectShape){
+			pct = pct || this.figure.zoomFactor;
+			ta.Annotation.prototype.zoom.call(this,pct);
+			pct = dojox.gfx.renderer=='vml'?1:pct;
+			this.rectShape.setStroke({color:this.property('fill'), width:1/pct});
+		}
+	};
+	p.serialize=function(){
+		var s=this.property('stroke');
+		return '<g '+this.writeCommonAttrs()+'>'
+			+ '<rect style="stroke:'+s.color+';stroke-width:1;fill:none;" '
+			+ 'x="' + this.start.x + '" '
+			+ 'width="' + (this.end.x-this.start.x) + '" '
+			+ 'y="' + this.start.y + '" '
+			+ 'height="' + (this.end.y-this.start.y) + '" '
+			+ 'rx="' + this.radius + '" '
+			+ 'ry="' + this.radius + '" '
+			+ ' />'
+			+ '<text style="fill:'+s.color+';text-anchor:'+this.textAlign+'" font-weight="bold" '
+			+ 'x="' + this.textPosition.x + '" '
+			+ 'y="' + this.textPosition.y + '">'
+			+ this.property('label')
+			+ '</text>'
+			+ '</g>';
+	};
+
+	ta.Annotation.register("Preexisting");
 })();
-}
diff --git a/dojox/sketch/SingleArrowAnnotation.js b/dojox/sketch/SingleArrowAnnotation.js
index 6083e25..5cfb382 100644
--- a/dojox/sketch/SingleArrowAnnotation.js
+++ b/dojox/sketch/SingleArrowAnnotation.js
@@ -1,185 +1,227 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch.SingleArrowAnnotation"]){
-dojo._hasResource["dojox.sketch.SingleArrowAnnotation"]=true;
 dojo.provide("dojox.sketch.SingleArrowAnnotation");
 dojo.require("dojox.sketch.Annotation");
 dojo.require("dojox.sketch.Anchor");
+
 (function(){
-var ta=dojox.sketch;
-ta.SingleArrowAnnotation=function(_1,id){
-ta.Annotation.call(this,_1,id);
-this.transform={dx:0,dy:0};
-this.start={x:0,y:0};
-this.control={x:100,y:-50};
-this.end={x:200,y:0};
-this.textPosition={x:0,y:0};
-this.textOffset=4;
-this.textYOffset=10;
-this.rotation=0;
-this.pathShape=null;
-this.arrowhead=null;
-this.arrowheadGroup=null;
-this.labelShape=null;
-this.anchors.start=new ta.Anchor(this,"start");
-this.anchors.control=new ta.Anchor(this,"control");
-this.anchors.end=new ta.Anchor(this,"end");
-};
-ta.SingleArrowAnnotation.prototype=new ta.Annotation;
-var p=ta.SingleArrowAnnotation.prototype;
-p.constructor=ta.SingleArrowAnnotation;
-p.type=function(){
-return "SingleArrow";
-};
-p.getType=function(){
-return ta.SingleArrowAnnotation;
-};
-p._rot=function(){
-var _2=this.control.y-this.start.y;
-var _3=this.control.x-this.start.x;
-this.rotation=Math.atan2(_2,_3);
-};
-p._pos=function(){
-var _4=this.textOffset,x=0,y=0;
-var _5=this.calculate.slope(this.control,this.end);
-this.textAlign="middle";
-if(Math.abs(_5)>=1){
-x=this.end.x+this.calculate.dx(this.control,this.end,_4);
-if(this.control.y>this.end.y){
-y=this.end.y-_4;
-}else{
-y=this.end.y+_4+this.textYOffset;
-}
-}else{
-if(_5==0){
-x=this.end.x+_4;
-y=this.end.y+this.textYOffset;
-}else{
-if(this.start.x>this.end.x){
-x=this.end.x-_4;
-this.textAlign="end";
-}else{
-x=this.end.x+_4;
-this.textAlign="start";
-}
-if(this.start.y<this.end.y){
-y=this.end.y+this.calculate.dy(this.control,this.end,_4)+this.textYOffset;
-}else{
-y=this.end.y+this.calculate.dy(this.control,this.end,-_4);
-}
-}
-}
-this.textPosition={x:x,y:y};
-};
-p.apply=function(_6){
-if(!_6){
-return;
-}
-if(_6.documentElement){
-_6=_6.documentElement;
-}
-this.readCommonAttrs(_6);
-for(var i=0;i<_6.childNodes.length;i++){
-var c=_6.childNodes[i];
-if(c.localName=="text"){
-this.property("label",c.childNodes.length?c.childNodes[0].nodeValue:"");
-}else{
-if(c.localName=="path"){
-var d=c.getAttribute("d").split(" ");
-var s=d[0].split(",");
-this.start.x=parseFloat(s[0].substr(1),10);
-this.start.y=parseFloat(s[1],10);
-s=d[1].split(",");
-this.control.x=parseFloat(s[0].substr(1),10);
-this.control.y=parseFloat(s[1],10);
-s=d[2].split(",");
-this.end.x=parseFloat(s[0],10);
-this.end.y=parseFloat(s[1],10);
-var _7=this.property("stroke");
-var _8=c.getAttribute("style");
-var m=_8.match(/stroke:([^;]+);/);
-if(m){
-_7.color=m[1];
-this.property("fill",m[1]);
-}
-m=_8.match(/stroke-width:([^;]+);/);
-if(m){
-_7.width=m[1];
-}
-this.property("stroke",_7);
-}
-}
-}
-};
-p.initialize=function(_9){
-var _a=(ta.Annotation.labelFont)?ta.Annotation.labelFont:{family:"Times",size:"16px"};
-this.apply(_9);
-this._rot();
-this._pos();
-var _b=this.rotation;
-var _c=dojox.gfx.matrix.rotate(_b);
-this.shape=this.figure.group.createGroup();
-this.shape.getEventSource().setAttribute("id",this.id);
-this.pathShape=this.shape.createPath("M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0");
-this.arrowheadGroup=this.shape.createGroup();
-this.arrowhead=this.arrowheadGroup.createPath();
-this.labelShape=this.shape.createText({x:this.textPosition.x,y:this.textPosition.y,text:this.property("label"),align:this.textAlign});
-this.labelShape.getEventSource().setAttribute("id",this.id+"-labelShape");
-this.draw();
-};
-p.destroy=function(){
-if(!this.shape){
-return;
-}
-this.arrowheadGroup.remove(this.arrowhead);
-this.shape.remove(this.arrowheadGroup);
-this.shape.remove(this.pathShape);
-this.shape.remove(this.labelShape);
-this.figure.group.remove(this.shape);
-this.shape=this.pathShape=this.labelShape=this.arrowheadGroup=this.arrowhead=null;
-};
-p.draw=function(_d){
-this.apply(_d);
-this._rot();
-this._pos();
-var _e=this.rotation;
-var _f=dojox.gfx.matrix.rotate(_e);
-this.shape.setTransform(this.transform);
-this.pathShape.setShape("M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0");
-this.arrowheadGroup.setTransform({dx:this.start.x,dy:this.start.y}).applyTransform(_f);
-this.arrowhead.setFill(this.property("fill"));
-this.labelShape.setShape({x:this.textPosition.x,y:this.textPosition.y,text:this.property("label"),align:this.textAlign}).setFill(this.property("fill"));
-this.zoom();
-};
-p.zoom=function(pct){
-if(this.arrowhead){
-pct=pct||this.figure.zoomFactor;
-ta.Annotation.prototype.zoom.call(this,pct);
-if(this._curPct!==pct){
-this._curPct=pct;
-var l=pct>1?20:Math.floor(20/pct),w=pct>1?5:Math.floor(5/pct),h=pct>1?3:Math.floor(3/pct);
-this.arrowhead.setShape("M0,0 l"+l+",-"+w+" -"+h+","+w+" "+h+","+w+" Z");
-}
-}
-};
-p.getBBox=function(){
-var x=Math.min(this.start.x,this.control.x,this.end.x);
-var y=Math.min(this.start.y,this.control.y,this.end.y);
-var w=Math.max(this.start.x,this.control.x,this.end.x)-x;
-var h=Math.max(this.start.y,this.control.y,this.end.y)-y;
-return {x:x,y:y,width:w,height:h};
-};
-p.serialize=function(){
-var s=this.property("stroke");
-var r=this.rotation*(180/Math.PI);
-r=Math.round(r*Math.pow(10,4))/Math.pow(10,4);
-return "<g "+this.writeCommonAttrs()+">"+"<path style=\"stroke:"+s.color+";stroke-width:"+s.width+";fill:none;\" d=\""+"M"+this.start.x+","+this.start.y+" "+"Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+"\" />"+"<g transform=\"translate("+this.start.x+","+this.start.y+") "+"rotate("+r+")\">"+"<path style=\"fill:"+s.color+";\" d=\"M0,0 l20,-5, -3,5, 3,5 Z\" />"+"</g>"+"<text style=\"fill:"+s.color+";text-anchor:"+this.textAlign+"\" font-weight=\"bold\" "+"x=\""+this. [...]
-};
-ta.Annotation.register("SingleArrow");
+	var ta=dojox.sketch;
+	ta.SingleArrowAnnotation=function(figure, id){
+		ta.Annotation.call(this, figure, id);
+		this.transform={ dx:0, dy:0 };
+		this.start={x:0, y:0};
+		this.control={x:100, y:-50};
+		this.end={x:200, y:0};
+		this.textPosition={ x:0, y:0 };
+		this.textOffset=4;
+		//this.textAlign="middle";
+		this.textYOffset=10;
+		this.rotation=0;
+
+//		this.property('label',this.id);
+//		this.label=this.id;
+		this.pathShape=null;
+		this.arrowhead=null;
+		this.arrowheadGroup=null;
+		this.labelShape=null;
+
+		this.anchors.start=new ta.Anchor(this, "start");
+		this.anchors.control=new ta.Anchor(this, "control");
+		this.anchors.end=new ta.Anchor(this, "end");
+	};
+	ta.SingleArrowAnnotation.prototype=new ta.Annotation;
+	var p=ta.SingleArrowAnnotation.prototype;
+	p.constructor=ta.SingleArrowAnnotation;
+
+	p.type=function(){ return 'SingleArrow'; };
+	p.getType=function(){ return ta.SingleArrowAnnotation; };
+
+	//	helper functions
+	p._rot=function(){
+		//	arrowhead rotation
+		var opp=this.control.y-this.start.y;
+		var adj=this.control.x-this.start.x;
+		//if(!adj){ adj=1; }
+		this.rotation=Math.atan2(opp,adj);
+	};
+	p._pos=function(){
+		//	text position
+		var offset=this.textOffset, x=0, y=0;
+		var slope=this.calculate.slope(this.control, this.end);
+		this.textAlign="middle";
+		if(Math.abs(slope)>=1){
+			x=this.end.x+this.calculate.dx(this.control, this.end, offset);
+			if(this.control.y>this.end.y){ y=this.end.y-offset; }
+			else{ y=this.end.y+offset+this.textYOffset; }
+		} else if(slope==0){
+			x=this.end.x+offset;
+			y=this.end.y+this.textYOffset;
+		} else {
+			if(this.start.x>this.end.x){
+				x=this.end.x-offset;
+				this.textAlign="end";
+			} else {
+				x=this.end.x+offset;
+				this.textAlign="start";
+			}
+			if(this.start.y<this.end.y){
+				y=this.end.y+this.calculate.dy(this.control, this.end, offset)+this.textYOffset;
+			} else { 
+				y=this.end.y+this.calculate.dy(this.control, this.end, -offset);
+			}
+		}
+		this.textPosition={ x:x, y:y };
+	};
+	
+	p.apply=function(obj){
+		if(!obj){ return; }
+		if(obj.documentElement){ obj=obj.documentElement; }
+		this.readCommonAttrs(obj);
+		
+		for(var i=0; i<obj.childNodes.length; i++){
+			var c=obj.childNodes[i];
+			if(c.localName=="text"){ 
+				this.property('label',c.childNodes.length?c.childNodes[0].nodeValue:'');
+			}
+			else if(c.localName=="path"){
+				//	the line
+				var d=c.getAttribute('d').split(" ");
+				var s=d[0].split(",");
+				this.start.x=parseFloat(s[0].substr(1),10);
+				this.start.y=parseFloat(s[1],10);
+				s=d[1].split(",");
+				this.control.x=parseFloat(s[0].substr(1),10);
+				this.control.y=parseFloat(s[1],10);
+				s=d[2].split(",");
+				this.end.x=parseFloat(s[0],10);
+				this.end.y=parseFloat(s[1],10);
+				var stroke=this.property('stroke');
+				var style=c.getAttribute('style');
+				var m=style.match(/stroke:([^;]+);/);
+				if(m){
+					stroke.color=m[1];
+					this.property('fill',m[1]);
+				}
+				m=style.match(/stroke-width:([^;]+);/);
+				if(m){
+					stroke.width=m[1];
+				}
+				this.property('stroke',stroke);
+			}
+		}
+	};
+	p.initialize=function(obj){
+		//	create, based on passed DOM node if available.
+		var font=(ta.Annotation.labelFont)?ta.Annotation.labelFont:{family:"Times", size:"16px"};
+		this.apply(obj);
+
+		//	calculate the other positions
+		this._rot();
+		this._pos();
+
+		//	rotation matrix
+		var rot=this.rotation;
+		var tRot=dojox.gfx.matrix.rotate(rot);
+
+		//	draw the shapes
+		this.shape=this.figure.group.createGroup();
+		this.shape.getEventSource().setAttribute("id", this.id);
+		//if(this.transform.dx||this.transform.dy){ this.shape.setTransform(this.transform); }
+
+		this.pathShape=this.shape.createPath("M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0")
+			//.setStroke(this.property('stroke'));
+
+		this.arrowheadGroup=this.shape.createGroup();//.setTransform({ dx:this.start.x, dy:this.start.y }).applyTransform(tRot);
+		this.arrowhead=this.arrowheadGroup.createPath();//"M0,0 l50,-10 -6,10 6,10 Z").setFill(this.property('fill'));
+
+		this.labelShape=this.shape.createText({
+				x:this.textPosition.x, 
+				y:this.textPosition.y, 
+				text:this.property('label'), 
+				align:this.textAlign
+			})
+			//.setFont(font)
+			//.setFill(this.property('fill'));
+		this.labelShape.getEventSource().setAttribute('id',this.id+"-labelShape");
+		this.draw();
+	};
+
+	p.destroy=function(){
+		if(!this.shape){ return; }
+		this.arrowheadGroup.remove(this.arrowhead);
+		this.shape.remove(this.arrowheadGroup);
+		this.shape.remove(this.pathShape);
+		this.shape.remove(this.labelShape);
+		this.figure.group.remove(this.shape);
+		this.shape=this.pathShape=this.labelShape=this.arrowheadGroup=this.arrowhead=null;
+	};
+
+	p.draw=function(obj){
+		this.apply(obj);
+		this._rot();
+		this._pos();
+
+		//	rotation matrix
+		var rot=this.rotation;
+		var tRot=dojox.gfx.matrix.rotate(rot);
+
+		this.shape.setTransform(this.transform);
+		this.pathShape.setShape("M"+this.start.x+","+this.start.y+" Q"+this.control.x+","+this.control.y+" "+this.end.x+","+this.end.y+" l0,0")
+			//.setStroke(this.property('stroke'));
+
+		this.arrowheadGroup.setTransform({dx:this.start.x,dy:this.start.y}).applyTransform(tRot);
+		this.arrowhead.setFill(this.property('fill'));
+
+		this.labelShape.setShape({
+				x:this.textPosition.x, 
+				y:this.textPosition.y, 
+				text:this.property('label'), 
+				align:this.textAlign
+			})
+			.setFill(this.property('fill'));
+		this.zoom();
+	};
+
+	p.zoom=function(pct){
+		if(this.arrowhead){
+			pct = pct || this.figure.zoomFactor;
+			ta.Annotation.prototype.zoom.call(this,pct);
+			//pct = dojox.gfx.renderer=='vml'?1:pct;
+			if(this._curPct!==pct){
+				this._curPct=pct;
+				var l=pct>1?20:Math.floor(20/pct), w=pct>1?5:Math.floor(5/pct),h=pct>1?3:Math.floor(3/pct);
+				this.arrowhead.setShape("M0,0 l"+l+",-"+w+" -"+h+","+w+" "+h+","+w+" Z");
+			}
+		}
+	};
+
+	p.getBBox=function(){
+		var x=Math.min(this.start.x, this.control.x, this.end.x);
+		var y=Math.min(this.start.y, this.control.y, this.end.y);
+		var w=Math.max(this.start.x, this.control.x, this.end.x)-x;
+		var h=Math.max(this.start.y, this.control.y, this.end.y)-y;
+		return { x:x, y:y, width:w, height:h };
+	};
+
+	p.serialize=function(){
+		var s=this.property('stroke');
+		var r=this.rotation*(180/Math.PI);
+		r=Math.round(r*Math.pow(10,4))/Math.pow(10,4);
+		return '<g '+this.writeCommonAttrs()+'>'
+			+ '<path style="stroke:'+s.color+';stroke-width:'+s.width+';fill:none;" d="'
+			+ "M"+this.start.x+","+this.start.y+" "
+			+ "Q"+this.control.x+","+this.control.y+" "
+			+ this.end.x+","+this.end.y
+			+ '" />'
+			+ '<g transform="translate(' + this.start.x + "," + this.start.y + ") "
+			+ 'rotate(' + r + ')">'
+			+ '<path style="fill:'+s.color+';" d="M0,0 l20,-5, -3,5, 3,5 Z" />'
+			+ '</g>'
+			+ '<text style="fill:'+s.color+';text-anchor:'+this.textAlign+'" font-weight="bold" '
+			+ 'x="' + this.textPosition.x + '" '
+			+ 'y="' + this.textPosition.y + '">'
+			+ this.property('label')
+			+ '</text>'
+			+ '</g>';
+	};
+
+	ta.Annotation.register("SingleArrow");
 })();
-}
diff --git a/dojox/sketch/Slider.js b/dojox/sketch/Slider.js
index 36545e5..66d7cdf 100644
--- a/dojox/sketch/Slider.js
+++ b/dojox/sketch/Slider.js
@@ -1,36 +1,36 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch.Slider"]){
-dojo._hasResource["dojox.sketch.Slider"]=true;
 dojo.provide("dojox.sketch.Slider");
+
 dojo.require("dijit.form.HorizontalSlider");
-dojo.declare("dojox.sketch.Slider",dojox.sketch._Plugin,{_initButton:function(){
-this.slider=new dijit.form.HorizontalSlider({minimum:5,maximum:100,style:"width:100px;float:right"});
-this.slider._movable.node.title="Double Click to \"Zoom to Fit\"";
-this.connect(this.slider,"onChange","_setZoom");
-this.connect(this.slider.sliderHandle,"ondblclick","_zoomToFit");
-},_zoomToFit:function(){
-var r=this.figure.getFit();
-this.slider.attr("value",this.slider.maximum<r?this.slider.maximum:(this.slider.minimum>r?this.slider.minimum:r));
-},_setZoom:function(v){
-if(v&&this.figure){
-this.figure.zoom(v);
-}
-},reset:function(){
-this.slider.attr("value",this.slider.maximum);
-this._zoomToFit();
-},setToolbar:function(t){
-this._initButton();
-t.addChild(this.slider);
-if(!t._reset2Zoom){
-t._reset2Zoom=true;
-this.connect(t,"reset","reset");
-}
-}});
-dojox.sketch.registerTool("Slider",dojox.sketch.Slider);
-}
+
+dojo.declare("dojox.sketch.Slider",dojox.sketch._Plugin,{
+	_initButton: function(){
+		this.slider=new dijit.form.HorizontalSlider({minimum:5,maximum:100,style:"width:100px;float:right"});
+		this.slider._movable.node.title='Double Click to "Zoom to Fit"'; //I18N
+		this.connect(this.slider,'onChange','_setZoom');
+		this.connect(this.slider.sliderHandle,'ondblclick','_zoomToFit');
+	},
+	_zoomToFit: function(){
+		var r=this.figure.getFit();
+		this.slider.attr('value',this.slider.maximum<r?this.slider.maximum:(this.slider.minimum>r?this.slider.minimum:r));
+	},
+	_setZoom: function(v){
+		if(v && this.figure){
+			this.figure.zoom(v);
+		}
+	},
+	reset: function(){
+		//reset slider to maximum so that onChange will be fired when _zoomToFit is called
+		this.slider.attr('value',this.slider.maximum);
+		this._zoomToFit();
+	},
+	setToolbar: function(t){
+		this._initButton();
+		t.addChild(this.slider);
+		if(!t._reset2Zoom){
+			t._reset2Zoom=true;
+			this.connect(t,'reset','reset');
+		}
+	}
+});
+
+dojox.sketch.registerTool("Slider", dojox.sketch.Slider);
diff --git a/dojox/sketch/Toolbar.js b/dojox/sketch/Toolbar.js
index 2bd62c5..1d6d1b4 100644
--- a/dojox/sketch/Toolbar.js
+++ b/dojox/sketch/Toolbar.js
@@ -1,83 +1,97 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch.Toolbar"]){
-dojo._hasResource["dojox.sketch.Toolbar"]=true;
 dojo.provide("dojox.sketch.Toolbar");
+
 dojo.require("dojox.sketch.Annotation");
 dojo.require("dijit.Toolbar");
 dojo.require("dijit.form.Button");
-dojo.declare("dojox.sketch.ButtonGroup",null,{constructor:function(){
-this._childMaps={};
-this._children=[];
-},add:function(_1){
-this._childMaps[_1]=_1.connect(_1,"onActivate",dojo.hitch(this,"_resetGroup",_1));
-this._children.push(_1);
-},_resetGroup:function(p){
-var cs=this._children;
-dojo.forEach(cs,function(c){
-if(p!=c&&c["attr"]){
-c.attr("checked",false);
-}
-});
-}});
-dojo.declare("dojox.sketch.Toolbar",dijit.Toolbar,{figure:null,plugins:null,postCreate:function(){
-this.inherited(arguments);
-this.shapeGroup=new dojox.sketch.ButtonGroup;
-if(!this.plugins){
-this.plugins=["Slider","Lead","SingleArrow","DoubleArrow","Underline","Preexisting"];
-}
-this._plugins=[];
-dojo.forEach(this.plugins,function(_2){
-var _3=dojo.isString(_2)?_2:_2.name;
-var p=new dojox.sketch.tools[_3](_2.args||{});
-this._plugins.push(p);
-p.setToolbar(this);
-if(!this._defaultTool&&p.button){
-this._defaultTool=p;
-}
-},this);
-},setFigure:function(f){
-this.figure=f;
-this.connect(f,"onLoad","reset");
-dojo.forEach(this._plugins,function(p){
-p.setFigure(f);
+
+dojo.declare("dojox.sketch.ButtonGroup", null, {
+	constructor: function(){
+		this._childMaps={};
+		this._children=[];
+	},
+	add: function(/*_Plugin*/ plugin){
+		this._childMaps[plugin]=plugin.connect(plugin,'onActivate',dojo.hitch(this,'_resetGroup',plugin));
+		this._children.push(plugin);
+	},
+//	remove: function(/*_Plugin*/ plugin){
+//		widget.disconnect(this._childMaps[widget.id]);
+//		delete this._childMaps[widget.id];
+//		this._children.splice(this._children.indexOf(widget.id),1);
+//	},
+	_resetGroup: function(p){
+		var cs=this._children;
+		dojo.forEach(cs,function(c){
+			if(p!=c && c['attr']){
+				c.attr('checked',false);
+			}
+		});
+	}
 });
-},destroy:function(){
-dojo.forEach(this._plugins,function(p){
-p.destroy();
+
+dojo.declare("dojox.sketch.Toolbar", dijit.Toolbar, {
+	figure: null,
+	plugins: null,
+	postCreate: function(){
+		this.inherited(arguments);
+		this.shapeGroup=new dojox.sketch.ButtonGroup;
+
+		if(!this.plugins){
+			this.plugins=['Slider','Lead','SingleArrow','DoubleArrow','Underline','Preexisting'];
+		}
+		this._plugins=[];
+
+		dojo.forEach(this.plugins,function(obj){
+			var name=dojo.isString(obj)?obj:obj.name;
+			var p=new dojox.sketch.tools[name](obj.args||{});
+			this._plugins.push(p);
+			p.setToolbar(this);
+			if(!this._defaultTool && p.button){
+				this._defaultTool=p;
+			}
+		},this);
+	},
+	setFigure: function(f){
+		this.figure = f;
+		this.connect(f,'onLoad','reset');
+		dojo.forEach(this._plugins, function(p){
+			p.setFigure(f);
+		});
+	},
+	destroy: function(){
+		dojo.forEach(this._plugins,function(p){
+			p.destroy();
+		});
+		this.inherited(arguments);
+		delete this._defaultTool;
+		delete this._plugins;
+	},
+	addGroupItem: function(/*_Plugin*/item,group){
+		if(group!='toolsGroup'){
+			console.error('not supported group '+group);
+			return;
+		}
+
+		this.shapeGroup.add(item);
+	},
+	reset: function(){
+		this._defaultTool.activate();
+	},
+	_setShape: function(s){
+		if(!this.figure.surface) return;
+		//	now do the action.
+		if(this.figure.hasSelections()){
+			for(var i=0; i<this.figure.selected.length; i++){
+				var before=this.figure.selected[i].serialize();
+				this.figure.convert(this.figure.selected[i], s);
+				this.figure.history.add(dojox.sketch.CommandTypes.Convert, this.figure.selected[i], before);
+			}
+		}
+	}
 });
-this.inherited(arguments);
-delete this._defaultTool;
-delete this._plugins;
-},addGroupItem:function(_4,_5){
-if(_5!="toolsGroup"){
-console.error("not supported group "+_5);
-return;
-}
-this.shapeGroup.add(_4);
-},reset:function(){
-this._defaultTool.activate();
-},_setShape:function(s){
-if(!this.figure.surface){
-return;
-}
-if(this.figure.hasSelections()){
-for(var i=0;i<this.figure.selected.length;i++){
-var _6=this.figure.selected[i].serialize();
-this.figure.convert(this.figure.selected[i],s);
-this.figure.history.add(dojox.sketch.CommandTypes.Convert,this.figure.selected[i],_6);
-}
-}
-}});
-dojox.sketch.makeToolbar=function(_7,_8){
-var _9=new dojox.sketch.Toolbar();
-_9.setFigure(_8);
-_7.appendChild(_9.domNode);
-return _9;
+
+dojox.sketch.makeToolbar=function(node,figure){
+	var toolbar=new dojox.sketch.Toolbar();
+	toolbar.setFigure(figure);
+	node.appendChild(toolbar.domNode);
+	return toolbar;
 };
-}
diff --git a/dojox/sketch/UnderlineAnnotation.js b/dojox/sketch/UnderlineAnnotation.js
index e970d24..adf5166 100644
--- a/dojox/sketch/UnderlineAnnotation.js
+++ b/dojox/sketch/UnderlineAnnotation.js
@@ -1,113 +1,147 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch.UnderlineAnnotation"]){
-dojo._hasResource["dojox.sketch.UnderlineAnnotation"]=true;
 dojo.provide("dojox.sketch.UnderlineAnnotation");
 dojo.require("dojox.sketch.Annotation");
 dojo.require("dojox.sketch.Anchor");
+
 (function(){
-var ta=dojox.sketch;
-ta.UnderlineAnnotation=function(_1,id){
-ta.Annotation.call(this,_1,id);
-this.transform={dx:0,dy:0};
-this.start={x:0,y:0};
-this.property("label","#");
-this.labelShape=null;
-this.lineShape=null;
-};
-ta.UnderlineAnnotation.prototype=new ta.Annotation;
-var p=ta.UnderlineAnnotation.prototype;
-p.constructor=ta.UnderlineAnnotation;
-p.type=function(){
-return "Underline";
-};
-p.getType=function(){
-return ta.UnderlineAnnotation;
-};
-p.apply=function(_2){
-if(!_2){
-return;
-}
-if(_2.documentElement){
-_2=_2.documentElement;
-}
-this.readCommonAttrs(_2);
-for(var i=0;i<_2.childNodes.length;i++){
-var c=_2.childNodes[i];
-if(c.localName=="text"){
-this.property("label",c.childNodes[0].nodeValue);
-var _3=c.getAttribute("style");
-var m=_3.match(/fill:([^;]+);/);
-if(m){
-var _4=this.property("stroke");
-_4.collor=m[1];
-this.property("stroke",_4);
-this.property("fill",_4.collor);
-}
-}
-}
-};
-p.initialize=function(_5){
-this.apply(_5);
-this.shape=this.figure.group.createGroup();
-this.shape.getEventSource().setAttribute("id",this.id);
-this.labelShape=this.shape.createText({x:0,y:0,text:this.property("label"),decoration:"underline",align:"start"});
-this.labelShape.getEventSource().setAttribute("id",this.id+"-labelShape");
-this.lineShape=this.shape.createLine({x1:1,x2:this.labelShape.getTextWidth(),y1:2,y2:2});
-this.lineShape.getEventSource().setAttribute("shape-rendering","crispEdges");
-this.draw();
-};
-p.destroy=function(){
-if(!this.shape){
-return;
-}
-this.shape.remove(this.labelShape);
-this.shape.remove(this.lineShape);
-this.figure.group.remove(this.shape);
-this.shape=this.lineShape=this.labelShape=null;
-};
-p.getBBox=function(){
-var b=this.getTextBox();
-var z=this.figure.zoomFactor;
-return {x:0,y:(b.h*-1+4)/z,width:(b.w+2)/z,height:b.h/z};
-};
-p.draw=function(_6){
-this.apply(_6);
-this.shape.setTransform(this.transform);
-this.labelShape.setShape({x:0,y:0,text:this.property("label")}).setFill(this.property("fill"));
-this.zoom();
-};
-p.zoom=function(_7){
-if(this.labelShape){
-_7=_7||this.figure.zoomFactor;
-var _8=dojox.gfx.renderer=="vml"?0:2/_7;
-ta.Annotation.prototype.zoom.call(this,_7);
-_7=dojox.gfx.renderer=="vml"?1:_7;
-this.lineShape.setShape({x1:0,x2:this.getBBox().width-_8,y1:2,y2:2}).setStroke({color:this.property("fill"),width:1/_7});
-if(this.mode==ta.Annotation.Modes.Edit){
-this.drawBBox();
-}
-}
-};
-p.serialize=function(){
-var s=this.property("stroke");
-return "<g "+this.writeCommonAttrs()+">"+"<text style=\"fill:"+this.property("fill")+";\" font-weight=\"bold\" text-decoration=\"underline\" "+"x=\"0\" y=\"0\">"+this.property("label")+"</text>"+"</g>";
-};
-dojo.declare("dojox.sketch.UnderlineAnnotationTool",ta.AnnotationTool,{onMouseDown:function(){
-},onMouseUp:function(){
-var f=this.figure;
-if(!f._start){
-return;
-}
-f._end={x:0,y:0};
-this._create(f._start,{x:f._start.x+10,y:f._start.y+10});
-},onMouseMove:function(){
-}});
-ta.Annotation.register("Underline",ta.UnderlineAnnotationTool);
+	var ta=dojox.sketch;
+	ta.UnderlineAnnotation=function(figure, id){
+		ta.Annotation.call(this, figure, id);
+		this.transform={dx:0, dy:0};
+		this.start={x:0, y:0};
+		this.property('label','#');
+		this.labelShape=null;
+		this.lineShape=null;
+		//this.anchors.start=new ta.Anchor(this, "start");
+	};
+	ta.UnderlineAnnotation.prototype=new ta.Annotation;
+	var p=ta.UnderlineAnnotation.prototype;
+	p.constructor=ta.UnderlineAnnotation;
+
+	p.type=function(){ return 'Underline'; };
+	p.getType=function(){ return ta.UnderlineAnnotation; };
+
+	p.apply=function(obj){
+		if(!obj){ return; }
+		if(obj.documentElement){ obj=obj.documentElement; }
+		this.readCommonAttrs(obj);
+		
+		for(var i=0; i<obj.childNodes.length; i++){
+			var c=obj.childNodes[i];
+			if(c.localName=="text"){
+				this.property('label',c.childNodes[0].nodeValue);
+				var style=c.getAttribute('style');
+				var m=style.match(/fill:([^;]+);/);
+				if(m){
+					var stroke=this.property('stroke');
+					stroke.collor=m[1];
+					this.property('stroke',stroke);
+					this.property('fill',stroke.collor);
+				}
+			}/*else if(c.localName=="line"){
+				var stroke=this.property('stroke');
+				var style=c.getAttribute('style');
+				var m=style.match(/stroke:([^;]+);/)[1];
+				if(m){
+					stroke.color=m;
+					this.property('fill',m);
+				}
+				m=style.match(/stroke-width:([^;]+);/)[1];
+				if(m){
+					stroke.width=m;
+				}
+				this.property('stroke',stroke);
+			}*/
+		}
+	};
+	
+	p.initialize=function(obj){
+		//var font=(ta.Annotation.labelFont)?ta.Annotation.labelFont:{family:"Times", size:"16px"};
+		this.apply(obj);
+
+		//	create either from scratch or based on the passed node
+		this.shape=this.figure.group.createGroup();
+		this.shape.getEventSource().setAttribute("id", this.id);
+		//if(this.transform.dx || this.transform.dy){ this.shape.setTransform(this.transform); }
+
+		this.labelShape=this.shape.createText({
+				x:0, 
+				y:0, 
+				text:this.property('label'), 
+				decoration:"underline",
+				align:"start"
+			})
+			//.setFont(font)
+			//.setFill(this.property('fill'));
+		this.labelShape.getEventSource().setAttribute('id',this.id+"-labelShape");
+
+		this.lineShape=this.shape.createLine({ 
+				x1:1, 
+				x2:this.labelShape.getTextWidth(), 
+				y1:2, 
+				y2:2 
+			})
+			//.setStroke({ color:this.property('fill'), width:1 });
+		this.lineShape.getEventSource().setAttribute("shape-rendering","crispEdges");
+		this.draw();
+	};
+	p.destroy=function(){
+		if(!this.shape){ return; }
+		this.shape.remove(this.labelShape);
+		this.shape.remove(this.lineShape);
+		this.figure.group.remove(this.shape);
+		this.shape=this.lineShape=this.labelShape=null;
+	};
+	p.getBBox=function(){
+		var b=this.getTextBox();
+		var z=this.figure.zoomFactor;
+
+		return { x:0, y:(b.h*-1+4)/z, width:(b.w+2)/z, height:b.h/z };
+	};
+	p.draw=function(obj){
+		this.apply(obj);
+		this.shape.setTransform(this.transform);
+		this.labelShape.setShape({ x:0, y:0, text:this.property('label') })
+			.setFill(this.property('fill'));
+		this.zoom();
+	};
+	p.zoom=function(pct){
+		if(this.labelShape){
+			pct = pct || this.figure.zoomFactor;
+			var textwidthadj=dojox.gfx.renderer=='vml'?0:2/pct;
+			ta.Annotation.prototype.zoom.call(this,pct);
+			pct = dojox.gfx.renderer=='vml'?1:pct;
+			this.lineShape.setShape({ x1:0, x2:this.getBBox().width-textwidthadj, y1:2, y2:2 })
+				.setStroke({ color:this.property('fill'), width:1/pct });
+			if(this.mode==ta.Annotation.Modes.Edit){
+				this.drawBBox(); //the bbox is dependent on the size of the text, so need to update it here
+			}
+		}
+	};
+	p.serialize=function(){
+		var s=this.property('stroke');
+		return '<g '+this.writeCommonAttrs()+'>'
+			//+ '<line x1="1" x2="'+this.labelShape.getTextWidth()+1+'" y1="5" y2="5" style="stroke:'+s.color+';stroke-width:'+s.width+';" />'
+			+ '<text style="fill:'+this.property('fill')+';" font-weight="bold" text-decoration="underline" '
+			+ 'x="0" y="0">'
+			+ this.property('label')
+			+ '</text>'
+			+ '</g>';
+	};
+    
+    //customize AnnotationTool to place a underlilne shape onmouseup, no need
+	//to drag a box (like other shapes)
+    dojo.declare("dojox.sketch.UnderlineAnnotationTool", ta.AnnotationTool, {
+		onMouseDown: function(){},
+		onMouseUp: function(){
+			var f=this.figure;
+			if(!f._start){
+				return;
+			}
+			//zero out end so that the clickover is shown at the right pos
+			f._end={x:0,y:0};
+			this._create(f._start,{x:f._start.x+10,y:f._start.y+10});
+		},
+		onMouseMove: function(){}
+	});
+	ta.Annotation.register("Underline", ta.UnderlineAnnotationTool);
 })();
-}
diff --git a/dojox/sketch/UndoStack.js b/dojox/sketch/UndoStack.js
index 213f8e9..150dd0b 100644
--- a/dojox/sketch/UndoStack.js
+++ b/dojox/sketch/UndoStack.js
@@ -1,71 +1,100 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch.UndoStack"]){
-dojo._hasResource["dojox.sketch.UndoStack"]=true;
 dojo.provide("dojox.sketch.UndoStack");
 dojo.require("dojox.xml.DomParser");
+
 (function(){
-var ta=dojox.sketch;
-ta.CommandTypes={Create:"Create",Move:"Move",Modify:"Modify",Delete:"Delete",Convert:"Convert"};
-dojo.declare("dojox.sketch.UndoStack",null,{constructor:function(_1){
-this.figure=_1;
-this._steps=[];
-this._undoedSteps=[];
-},apply:function(_2,_3,to){
-if(!_3&&!to&&_2.fullText){
-this.figure.setValue(_2.fullText);
-return;
-}
-var _4=_3.shapeText;
-var _5=to.shapeText;
-if(_4.length==0&&_5.length==0){
-return;
-}
-if(_4.length==0){
-var o=dojox.xml.DomParser.parse(_5).documentElement;
-var a=this.figure._loadAnnotation(o);
-if(a){
-this.figure._add(a);
-}
-return;
-}
-if(_5.length==0){
-var _6=this.figure.get(_3.shapeId);
-this.figure._delete([_6],true);
-return;
-}
-var _7=this.figure.get(to.shapeId);
-var no=dojox.xml.DomParser.parse(_5).documentElement;
-_7.draw(no);
-this.figure.select(_7);
-return;
-},add:function(_8,_9,_a){
-var id=_9?_9.id:"";
-var _b=_9?_9.serialize():"";
-if(_8==ta.CommandTypes.Delete){
-_b="";
-}
-var _c={cmdname:_8,before:{shapeId:id,shapeText:_a||""},after:{shapeId:id,shapeText:_b}};
-this._steps.push(_c);
-this._undoedSteps=[];
-},destroy:function(){
-},undo:function(){
-var _d=this._steps.pop();
-if(_d){
-this._undoedSteps.push(_d);
-this.apply(_d,_d.after,_d.before);
-}
-},redo:function(){
-var _e=this._undoedSteps.pop();
-if(_e){
-this._steps.push(_e);
-this.apply(_e,_e.before,_e.after);
-}
-}});
+	var ta=dojox.sketch;
+	ta.CommandTypes={ Create:"Create", Move:"Move", Modify:"Modify", Delete:"Delete", Convert:"Convert"};
+
+	dojo.declare("dojox.sketch.UndoStack",null,{
+		constructor: function(figure){
+			this.figure=figure;
+			this._steps=[];
+			this._undoedSteps=[];
+		},
+		apply: function(state, from, to){
+			//	the key here is to neutrally move from one state to another.
+			//	we let the individual functions (i.e. undo and redo) actually
+			//	determine the from and to; all we do here is implement it.
+
+			//	check whether this is a fullText step
+			if(!from && !to && state.fullText){
+				this.figure.setValue(state.fullText);
+				return;
+			}
+
+			var fromText=from.shapeText;
+			var toText=to.shapeText;
+			
+			if(fromText.length==0&&toText.length==0){
+				//	nothing to reapply?
+				return;
+			}
+			if(fromText.length==0){
+				//	We are creating.
+				var o=dojox.xml.DomParser.parse(toText).documentElement;
+				var a=this.figure._loadAnnotation(o);
+				if(a) this.figure._add(a);
+				return;
+			}
+			if(toText.length==0){
+				//	we are deleting.
+				var ann=this.figure.getAnnotator(from.shapeId);
+				this.figure._delete([ann],true);
+				return;
+			}
+			
+			//	we can simply reinit and draw from the shape itself,
+			//		regardless of the actual command.
+			var nann=this.figure.getAnnotator(to.shapeId);
+			var no=dojox.xml.DomParser.parse(toText).documentElement;
+			nann.draw(no);
+			this.figure.select(nann);
+			return;
+		},
+		//	stack methods.
+		add: function(/*String*/cmd, /*ta.Annotation?*/ann, /*String?*/before){
+			var id=ann?ann.id:'';
+			//var bbox=ann?ann.getBBox():{};
+			var after=ann?ann.serialize():"";
+			if(cmd==ta.CommandTypes.Delete){ after=""; }
+			
+			/*if(ann){
+				//	fix the bbox x/y coords
+				var t=ann.transform;
+				bbox.x+=t.dx;
+				bbox.y+=t.dy;
+			}*/
+			var state={
+				cmdname:cmd,
+				//bbox:bbox,
+//					fullText:fullText,
+				before:{
+					shapeId: id,
+					shapeText:before||''
+				},
+				after:{
+					shapeId: id,
+					shapeText:after
+				}
+			};
+			//console.log('dojox.sketch history add',state);
+			this._steps.push(state);
+			this._undoedSteps = [];
+		},
+		destroy: function(){},
+		undo: function(){
+			var state=this._steps.pop();
+			if(state){
+				this._undoedSteps.push(state);
+				this.apply(state,state.after,state.before);
+			}
+		},
+		redo: function(){
+			var state=this._undoedSteps.pop();
+			if(state){
+				this._steps.push(state);
+				this.apply(state,state.before,state.after);
+			}
+		}
+	});
 })();
-}
diff --git a/dojox/sketch/_Plugin.js b/dojox/sketch/_Plugin.js
index 32c1dd1..c3777c4 100644
--- a/dojox/sketch/_Plugin.js
+++ b/dojox/sketch/_Plugin.js
@@ -1,51 +1,74 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sketch._Plugin"]){
-dojo._hasResource["dojox.sketch._Plugin"]=true;
 dojo.provide("dojox.sketch._Plugin");
+//dojo.require("dojox.sketch");
 dojo.require("dijit.form.Button");
-dojo.declare("dojox.sketch._Plugin",null,{constructor:function(_1){
-if(_1){
-dojo.mixin(this,_1);
-}
-this._connects=[];
-},figure:null,iconClassPrefix:"dojoxSketchIcon",itemGroup:"toolsGroup",button:null,queryCommand:null,shape:"",useDefaultCommand:true,buttonClass:dijit.form.ToggleButton,_initButton:function(){
-if(this.shape.length){
-var _2=this.iconClassPrefix+" "+this.iconClassPrefix+this.shape.charAt(0).toUpperCase()+this.shape.substr(1);
-if(!this.button){
-var _3={label:this.shape,showLabel:false,iconClass:_2,dropDown:this.dropDown,tabIndex:"-1"};
-this.button=new this.buttonClass(_3);
-this.connect(this.button,"onClick","activate");
-}
-}
-},attr:function(_4,_5){
-return this.button.attr(_4,_5);
-},onActivate:function(){
-},activate:function(e){
-this.onActivate();
-this.figure.setTool(this);
-this.attr("checked",true);
-},onMouseDown:function(e){
-},onMouseMove:function(e){
-},onMouseUp:function(e){
-},destroy:function(f){
-dojo.forEach(this._connects,dojo.disconnect);
-},connect:function(o,f,tf){
-this._connects.push(dojo.connect(o,f,this,tf));
-},setFigure:function(_6){
-this.figure=_6;
-},setToolbar:function(_7){
-this._initButton();
-if(this.button){
-_7.addChild(this.button);
-}
-if(this.itemGroup){
-_7.addGroupItem(this,this.itemGroup);
-}
-}});
-}
+
+dojo.declare("dojox.sketch._Plugin", null, {
+	// summary
+	//		This represents a "plugin" to the dojox.sketch.Figure, which is basically
+	//		a single button on the Toolbar and some associated code
+	constructor: function(/*Object?*/args){
+		if(args){
+			dojo.mixin(this, args);
+		}
+		this._connects=[];
+	},
+
+	figure: null,
+	iconClassPrefix: "dojoxSketchIcon",
+	itemGroup: 'toolsGroup',
+	button: null,
+	queryCommand: null,
+	shape: "",
+	useDefaultCommand: true,
+	buttonClass: dijit.form.ToggleButton,
+	_initButton: function(){
+		if(this.shape.length){
+			//TODO: i18n
+//			var label = dojox.sketch.shapes[this.shape];
+			var className = this.iconClassPrefix+" "+this.iconClassPrefix + this.shape.charAt(0).toUpperCase() + this.shape.substr(1);
+			if(!this.button){
+				var props = {
+					label: this.shape, //I18N
+					showLabel: false,
+					iconClass: className,
+					dropDown: this.dropDown,
+					tabIndex: "-1"
+				};
+				this.button = new this.buttonClass(props);
+				this.connect(this.button,'onClick','activate');
+			}
+		}
+	},
+	attr: function(name,/*?*/value){
+		return this.button.attr(name,value);
+	},
+	onActivate: function(){},
+	activate: function(/*?*/e){
+		this.onActivate();
+		this.figure.setTool(this);
+		this.attr('checked',true);
+	},
+	onMouseDown: function(e){},
+	onMouseMove: function(e){},
+	onMouseUp: function(e){},
+	destroy: function(f){
+		dojo.forEach(this._connects,dojo.disconnect);
+	},
+	connect: function(o,f,tf){
+		this._connects.push(dojo.connect(o,f,this,tf));
+	},
+	setFigure: function(/*dijit._Widget*/ figure){
+		// FIXME: detatch from previous figure!!
+		this.figure = figure;
+	},
+	setToolbar: function(/*dijit._Widget*/ toolbar){
+		// FIXME: prevent creating this if we don't need to (i.e., figure can't handle our command)
+		this._initButton();
+		if(this.button){
+			toolbar.addChild(this.button);
+		}
+		if(this.itemGroup){
+			toolbar.addGroupItem(this,this.itemGroup);
+		}
+	}
+});
diff --git a/dojox/sketch/resources/sketch.css b/dojox/sketch/resources/sketch.css
old mode 100644
new mode 100755
diff --git a/dojox/sketch/tests/FTHelper.js b/dojox/sketch/tests/FTHelper.js
new file mode 100755
index 0000000..4c6fcc2
--- /dev/null
+++ b/dojox/sketch/tests/FTHelper.js
@@ -0,0 +1,44 @@
+dojo.provide("dojox.sketch.tests.FTHelper");
+
+dojo.declare('dojox.sketch.tests.FTHelper',null,{
+    controlCss: "#dojox_sketch_Toolbar_0 .dijitButtonContents",
+    canvas:'canvas',
+    defaultDelay: 100,
+    //controls: ['lead','single','double','underline','preexisting'];
+    constructor: function(args){
+        this.controls=['lead','single','double','underline','preexisting'];
+        if(args){
+            dojo.mixin(this,args);
+        }
+    },
+    selectShape: function(shape,delay){
+        delay=delay||this.defaultDelay;
+        var i=dojo.indexOf(this.controls,shape);
+        if(i<0){
+            throw Error('shape "'+shape+'" is not recognized');
+        }
+        var buttons=dojo.query(this.controlCss);
+        if(buttons.length<=i){
+            throw Error('Can not find button for shape "'+shape+'" on the toolbar');
+        }
+        var button=buttons[i];
+        doh.robot.mouseMoveAt(button,delay);
+        doh.robot.mouseClick({left:true},delay);
+    },
+    drawShape: function(start,end,delay){
+        delay=delay||this.defaultDelay;
+        if(!this.coords){
+            this.coords=dojo.coords(this.canvas);
+        }
+        end=end||start;
+        doh.robot.mouseMove(this.coords.x+start.x,this.coords.y+start.y,delay,1);
+        doh.robot.mousePress({left:1},delay);
+        doh.robot.mouseMove(this.coords.x+end.x,this.coords.y+end.y,delay,1);
+        doh.robot.mouseRelease({left:1},delay);
+    },
+    click: function(args,delay){
+        delay=delay||this.defaultDelay;
+        doh.robot.mouseMove(this.coords.x+args.x,this.coords.y+args.y,delay,1);
+        doh.robot.mouseClick(args,delay);
+    }
+});
\ No newline at end of file
diff --git a/dojox/sketch/tests/annotation.svg b/dojox/sketch/tests/annotation.svg
new file mode 100755
index 0000000..998d71e
--- /dev/null
+++ b/dojox/sketch/tests/annotation.svg
@@ -0,0 +1,39 @@
+<svg xmlns="http://www.w3.org/2000/svg" 
+	xmlns:xlink="http://www.w3.org/1999/xlink" 
+	xmlns:dojoxsketch="http://dojotoolkit.org/dojox/sketch" 
+	width="1000" 
+	height="855"
+>
+	<g>
+		<image xlink:href="images/figure2.gif" x="0" y="0" width="1000" height="855" />
+		<g id="ann-1" dojoxsketch:type="Lead" transform="translate(437,169)">
+			<path style="stroke:blue;stroke-width:2;fill:none;" d="M0,0 Q100,-50 200,0" />
+			<text style="fill:blue;text-anchor:start" font-weight="bold" x="204" y="-2">1</text>
+		</g>
+		<g id="ann-2" dojoxsketch:type="Preexisting" transform="translate(526,408)">
+			<rect style="stroke:blue;stroke-weight:1;fill:none;" x="0" width="104" y="0" height="210" rx="8" ry="8"  />
+			<text style="fill:blue;text-anchor:end" font-weight="bold" x="100" y="206">2</text>
+		</g>
+		<g id="ann-3" dojoxsketch:type="SingleArrow" transform="translate(537,804)">
+			<path style="stroke:blue;stroke-width:2;fill:none;" d="M-44,13 Q-137,38 -162,-23" />
+			<g transform="translate(-44,13) rotate(-195.0464)">
+				<path style="fill:blue;" d="M0,0 l20,-5, -3,5, 3,5 Z" />
+			</g>
+			<text style="fill:blue;text-anchor:middle" font-weight="bold" x="-160.36065573770492" y="-27">3</text>
+		</g>
+		<g id="ann-4" dojoxsketch:type="DoubleArrow" transform="translate(329,-7)">
+			<path style="stroke:blue;stroke-width:2;fill:none;" d="M249,306 Q505,242 426,389" />
+			<g transform="translate(249,306) rotate(-14.0362)">
+				<path style="fill:blue;" d="M0,0 l20,-5, -3,5, 3,5 Z" />
+			</g>
+			<g transform="rotate(-61.7458, 426, 389)">
+				<path style="fill:blue;" d="M426,389 l-20,-5, 3,5, -3,5 Z" />
+			</g>
+			<text style="fill:blue;text-anchor:middle" font-weight="bold" x="421.25" y="288.75">4</text>
+		</g>
+		<g id="ann-5" dojoxsketch:type="Underline" transform="translate(821,517)">
+			<line x1="1" x2="91" y1="5" y2="5" style="stroke:blue;stroke-weight:2" />
+			<text style="fill:blue;" font-weight="bold" x="0" y="0">5</text>
+		</g>
+	</g>
+</svg>
diff --git a/dojox/sketch/tests/images/figure2.gif b/dojox/sketch/tests/images/figure2.gif
new file mode 100644
index 0000000..7218a4c
Binary files /dev/null and b/dojox/sketch/tests/images/figure2.gif differ
diff --git a/dojox/sketch/tests/images/testsBodyBg.gif b/dojox/sketch/tests/images/testsBodyBg.gif
new file mode 100644
index 0000000..4e0b4a7
Binary files /dev/null and b/dojox/sketch/tests/images/testsBodyBg.gif differ
diff --git a/dojox/sketch/tests/test_full.html b/dojox/sketch/tests/test_full.html
new file mode 100755
index 0000000..ff133c6
--- /dev/null
+++ b/dojox/sketch/tests/test_full.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Annotator/Figure Testing</title>
+<style type="text/css">
+ at import "../../../dojo/resources/dojo.css";
+ at Import "../../../dijit/themes/tundra/tundra.css";
+</style>
+		<link href="../resources/sketch.css" type="text/css" rel="stylesheet">
+		<style type="text/css">
+			body {
+				background:#fff url("images/testsBodyBg.gif") repeat-x top left;
+				padding:1em 3em;
+			}
+			table { margin:0; width:100%;}
+			table tr td { padding:0; }
+			table tr td table { border:0; width:auto;}
+
+			#container{ width:600px; }
+			#toolbar{ width:100%; }
+			#canvasContainer{ outline:none; width:600px; height:600px; background-color:#fff;border:1px solid #ccc; overflow:auto;position:relative;}
+		</style>
+		<script>var djConfig={ isDebug: false };</script>
+		<script src="../../../dojo/dojo.js"></script>
+		<script src="../Toolbar.js"></script>
+		<script>
+            dojo.require("dijit.robot");
+			dojo.require("dojox.sketch");
+			dojo.require("dojox.sketch.Slider");
+			dojo.require("dojox.sketch.LeadAnnotation");
+			dojo.require("dojox.sketch.UnderlineAnnotation");
+			dojo.require("dojox.sketch.SingleArrowAnnotation");
+			dojo.require("dojox.sketch.DoubleArrowAnnotation");
+			dojo.require("dojox.sketch.PreexistingAnnotation");
+			var f, a, t;
+			function init(){
+				var ta=dojox.sketch;
+				f=new ta.Figure({gridSize:10});
+				dojo.connect(f, "_mu", function(){ dojo.byId("output").value=f.serialize(); });
+
+				t=ta.makeToolbar(dojo.byId("toolbar"), f);
+
+				//	test loading from an SVG file
+				dojo.xhrGet({
+					url:"annotation.svg",
+					preventCache:true,
+					load:function(data, ioArgs){
+						var svg=dojox.xml.DomParser.parse(data);
+						f.load(svg, dojo.byId("canvas"));
+						dojo.byId("output").value=f.serialize();
+					}
+				});
+                
+                setTimeout(function(){
+                    doh.robot.startRobot();
+                    setTimeout(function(){
+                        rundoh();
+                    },1000);
+                },1000);
+			}
+			dojo.addOnLoad(init);
+            
+            function rundoh(){
+                dojo.require("dojox.sketch.tests.FTHelper");
+                var helper=new dojox.sketch.tests.FTHelper;
+                doh.register("placeLeadShape",{
+                    timeout: 1500,
+                    runTest:function(t){
+                        var d = new doh.Deferred();
+                        helper.drawShape({x:100,y:100},{x:200,y:200});
+                        doh.robot.sequence(d.getTestCallback(function(){
+                            t.is('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dojoxsketch="http://dojotoolkit.org/dojox/sketch" width="1000" height="855"><g><image xlink:href="images/figure2.gif" x="0" y="0" width="1000" height="855" /><g id="ann-1" dojoxsketch:type="Lead" transform="translate(437,169)"><path style="stroke:blue;stroke-width:2;fill:none;" d="M0,0 Q100,-50 200,0" /><text style="fill:blue;text-anchor:start" font-weight="bold" x=" [...]
+                        }), 500);
+                        return d;
+                    }
+                });
+                doh.register("removeLeadShape",{
+                    timeout: 1500,
+                    runTest:function(t){
+                        var d = new doh.Deferred();
+                        helper.click({left:true,x:100,y:100},100);
+                        doh.robot.keyPress(dojo.keys.DELETE,100);
+                        doh.robot.sequence(d.getTestCallback(function(){
+                                t.is('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dojoxsketch="http://dojotoolkit.org/dojox/sketch" width="1000" height="855"><g><image xlink:href="images/figure2.gif" x="0" y="0" width="1000" height="855" /><g id="ann-1" dojoxsketch:type="Lead" transform="translate(437,169)"><path style="stroke:blue;stroke-width:2;fill:none;" d="M0,0 Q100,-50 200,0" /><text style="fill:blue;text-anchor:start" font-weight="bold" [...]
+                        }),300);
+                        return d;
+                    }
+                });
+                doh.register("placeDoubleShape",{
+                    timeout: 1500,
+                    runTest:function(t){
+                        var d = new doh.Deferred();
+                        helper.selectShape('double');
+                        helper.drawShape({x:200,y:100},{x:100,y:200});
+                        doh.robot.sequence(d.getTestCallback(function(){
+                                t.is('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dojoxsketch="http://dojotoolkit.org/dojox/sketch" width="1000" height="855"><g><image xlink:href="images/figure2.gif" x="0" y="0" width="1000" height="855" /><g id="ann-1" dojoxsketch:type="Lead" transform="translate(437,169)"><path style="stroke:blue;stroke-width:2;fill:none;" d="M0,0 Q100,-50 200,0" /><text style="fill:blue;text-anchor:start" font-weight="bold" [...]
+                        }),500);
+                        return d;
+                    }
+                });
+                doh.register("placeUnderlineShape",{
+                    timeout: 2000,
+                    runTest:function(t){
+                        var d = new doh.Deferred();
+                        doh.robot.keyPress('z',100,{ctrl:true});
+                        helper.selectShape('underline');
+                        helper.drawShape({x:147,y:147},{x:147,y:147});
+                        doh.robot.sequence(d.getTestCallback(function(){
+                                t.is('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dojoxsketch="http://dojotoolkit.org/dojox/sketch" width="1000" height="855"><g><image xlink:href="images/figure2.gif" x="0" y="0" width="1000" height="855" /><g id="ann-1" dojoxsketch:type="Lead" transform="translate(437,169)"><path style="stroke:blue;stroke-width:2;fill:none;" d="M0,0 Q100,-50 200,0" /><text style="fill:blue;text-anchor:start" font-weight="bold" [...]
+                        }),500);
+                        return d;
+                    }
+                });
+                doh.run();
+            }
+		</script>
+	</head>
+	<body class="tundra">
+    <button onclick="rundoh()">FT</button>
+		<h1>Annotator/Figure Testing Platform</h1>
+		<p>This is a generic test to create a figure from an existing SVG file, to edit that figure, and to test the undo stack. Double click a shape to set new text for it.</p>
+		<div id="container">
+			<div id="toolbar"></div>
+			<div id="canvasContainer"><div id="canvas" tabindex="-1"></div></div>
+		</div>
+		<h2>Serialized output</h2>
+		<textarea id="output" style="width:100%;height:180px;overflow:auto;font-size:0.8em;"></textarea>
+	</body>
+</html>
diff --git a/dojox/sql.js b/dojox/sql.js
index 086b046..0addc86 100644
--- a/dojox/sql.js
+++ b/dojox/sql.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sql"]){
-dojo._hasResource["dojox.sql"]=true;
-dojo.provide("dojox.sql");
+dojo.provide("dojox.sql"); 
 dojo.require("dojox.sql._base");
-}
diff --git a/dojox/sql/_base.js b/dojox/sql/_base.js
index dd8edff..392d308 100644
--- a/dojox/sql/_base.js
+++ b/dojox/sql/_base.js
@@ -1,330 +1,547 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.sql._base"]){
-dojo._hasResource["dojox.sql._base"]=true;
 dojo.provide("dojox.sql._base");
 dojo.require("dojox.sql._crypto");
-dojo.mixin(dojox.sql,{dbName:null,debug:(dojo.exists("dojox.sql.debug")?dojox.sql.debug:false),open:function(_1){
-if(this._dbOpen&&(!_1||_1==this.dbName)){
-return;
-}
-if(!this.dbName){
-this.dbName="dot_store_"+window.location.href.replace(/[^0-9A-Za-z_]/g,"_");
-if(this.dbName.length>63){
-this.dbName=this.dbName.substring(0,63);
-}
-}
-if(!_1){
-_1=this.dbName;
-}
-try{
-this._initDb();
-this.db.open(_1);
-this._dbOpen=true;
-}
-catch(exp){
-throw exp.message||exp;
-}
-},close:function(_2){
-if(dojo.isIE){
-return;
-}
-if(!this._dbOpen&&(!_2||_2==this.dbName)){
-return;
-}
-if(!_2){
-_2=this.dbName;
-}
-try{
-this.db.close(_2);
-this._dbOpen=false;
-}
-catch(exp){
-throw exp.message||exp;
-}
-},_exec:function(_3){
-try{
-this._initDb();
-if(!this._dbOpen){
-this.open();
-this._autoClose=true;
-}
-var _4=null;
-var _5=null;
-var _6=null;
-var _7=dojo._toArray(_3);
-_4=_7.splice(0,1)[0];
-if(this._needsEncrypt(_4)||this._needsDecrypt(_4)){
-_5=_7.splice(_7.length-1,1)[0];
-_6=_7.splice(_7.length-1,1)[0];
-}
-if(this.debug){
-this._printDebugSQL(_4,_7);
-}
-var _8;
-if(this._needsEncrypt(_4)){
-_8=new dojox.sql._SQLCrypto("encrypt",_4,_6,_7,_5);
-return null;
-}else{
-if(this._needsDecrypt(_4)){
-_8=new dojox.sql._SQLCrypto("decrypt",_4,_6,_7,_5);
-return null;
-}
-}
-var rs=this.db.execute(_4,_7);
-rs=this._normalizeResults(rs);
-if(this._autoClose){
-this.close();
-}
-return rs;
-}
-catch(exp){
-exp=exp.message||exp;
-if(this._autoClose){
-try{
-this.close();
-}
-catch(e){
-}
-}
-throw exp;
-}
-return null;
-},_initDb:function(){
-if(!this.db){
-try{
-this.db=google.gears.factory.create("beta.database","1.0");
-}
-catch(exp){
-dojo.setObject("google.gears.denied",true);
-if(dojox.off){
-dojox.off.onFrameworkEvent("coreOperationFailed");
-}
-throw "Google Gears must be allowed to run";
-}
-}
-},_printDebugSQL:function(_9,_a){
-var _b="dojox.sql(\""+_9+"\"";
-for(var i=0;i<_a.length;i++){
-if(typeof _a[i]=="string"){
-_b+=", \""+_a[i]+"\"";
-}else{
-_b+=", "+_a[i];
-}
-}
-_b+=")";
-},_normalizeResults:function(rs){
-var _c=[];
-if(!rs){
-return [];
-}
-while(rs.isValidRow()){
-var _d={};
-for(var i=0;i<rs.fieldCount();i++){
-var _e=rs.fieldName(i);
-var _f=rs.field(i);
-_d[_e]=_f;
-}
-_c.push(_d);
-rs.next();
-}
-rs.close();
-return _c;
-},_needsEncrypt:function(sql){
-return /encrypt\([^\)]*\)/i.test(sql);
-},_needsDecrypt:function(sql){
-return /decrypt\([^\)]*\)/i.test(sql);
-}});
-dojo.declare("dojox.sql._SQLCrypto",null,{constructor:function(_10,sql,_11,_12,_13){
-if(_10=="encrypt"){
-this._execEncryptSQL(sql,_11,_12,_13);
-}else{
-this._execDecryptSQL(sql,_11,_12,_13);
-}
-},_execEncryptSQL:function(sql,_14,_15,_16){
-var _17=this._stripCryptoSQL(sql);
-var _18=this._flagEncryptedArgs(sql,_15);
-var _19=this;
-this._encrypt(_17,_14,_15,_18,function(_1a){
-var _1b=false;
-var _1c=[];
-var exp=null;
-try{
-_1c=dojox.sql.db.execute(_17,_1a);
-}
-catch(execError){
-_1b=true;
-exp=execError.message||execError;
-}
-if(exp!=null){
-if(dojox.sql._autoClose){
-try{
-dojox.sql.close();
-}
-catch(e){
-}
-}
-_16(null,true,exp.toString());
-return;
-}
-_1c=dojox.sql._normalizeResults(_1c);
-if(dojox.sql._autoClose){
-dojox.sql.close();
-}
-if(dojox.sql._needsDecrypt(sql)){
-var _1d=_19._determineDecryptedColumns(sql);
-_19._decrypt(_1c,_1d,_14,function(_1e){
-_16(_1e,false,null);
-});
-}else{
-_16(_1c,false,null);
-}
-});
-},_execDecryptSQL:function(sql,_1f,_20,_21){
-var _22=this._stripCryptoSQL(sql);
-var _23=this._determineDecryptedColumns(sql);
-var _24=false;
-var _25=[];
-var exp=null;
-try{
-_25=dojox.sql.db.execute(_22,_20);
-}
-catch(execError){
-_24=true;
-exp=execError.message||execError;
-}
-if(exp!=null){
-if(dojox.sql._autoClose){
-try{
-dojox.sql.close();
-}
-catch(e){
-}
-}
-_21(_25,true,exp.toString());
-return;
-}
-_25=dojox.sql._normalizeResults(_25);
-if(dojox.sql._autoClose){
-dojox.sql.close();
-}
-this._decrypt(_25,_23,_1f,function(_26){
-_21(_26,false,null);
-});
-},_encrypt:function(sql,_27,_28,_29,_2a){
-this._totalCrypto=0;
-this._finishedCrypto=0;
-this._finishedSpawningCrypto=false;
-this._finalArgs=_28;
-for(var i=0;i<_28.length;i++){
-if(_29[i]){
-var _2b=_28[i];
-var _2c=i;
-this._totalCrypto++;
-dojox.sql._crypto.encrypt(_2b,_27,dojo.hitch(this,function(_2d){
-this._finalArgs[_2c]=_2d;
-this._finishedCrypto++;
-if(this._finishedCrypto>=this._totalCrypto&&this._finishedSpawningCrypto){
-_2a(this._finalArgs);
-}
-}));
-}
-}
-this._finishedSpawningCrypto=true;
-},_decrypt:function(_2e,_2f,_30,_31){
-this._totalCrypto=0;
-this._finishedCrypto=0;
-this._finishedSpawningCrypto=false;
-this._finalResultSet=_2e;
-for(var i=0;i<_2e.length;i++){
-var row=_2e[i];
-for(var _32 in row){
-if(_2f=="*"||_2f[_32]){
-this._totalCrypto++;
-var _33=row[_32];
-this._decryptSingleColumn(_32,_33,_30,i,function(_34){
-_31(_34);
+
+dojo.mixin(dojox.sql, {
+	// summary:
+	//	Executes a SQL expression.
+	// description:
+	// 	There are four ways to call this:
+	// 	1) Straight SQL: dojox.sql("SELECT * FROM FOOBAR");
+	// 	2) SQL with parameters: dojox.sql("INSERT INTO FOOBAR VALUES (?)", someParam)
+	// 	3) Encrypting particular values: 
+	//			dojox.sql("INSERT INTO FOOBAR VALUES (ENCRYPT(?))", someParam, "somePassword", callback)
+	// 	4) Decrypting particular values:
+	//			dojox.sql("SELECT DECRYPT(SOMECOL1), DECRYPT(SOMECOL2) FROM
+	//					FOOBAR WHERE SOMECOL3 = ?", someParam,
+	//					"somePassword", callback)
+	//
+	// 	For encryption and decryption the last two values should be the the password for
+	// 	encryption/decryption, and the callback function that gets the result set.
+	//
+	// 	Note: We only support ENCRYPT(?) statements, and
+	// 	and DECRYPT(*) statements for now -- you can not have a literal string
+	// 	inside of these, such as ENCRYPT('foobar')
+	//
+	// 	Note: If you have multiple columns to encrypt and decrypt, you can use the following
+	// 	convenience form to not have to type ENCRYPT(?)/DECRYPT(*) many times:
+	//
+	// 	dojox.sql("INSERT INTO FOOBAR VALUES (ENCRYPT(?, ?, ?))", 
+	//					someParam1, someParam2, someParam3, 
+	//					"somePassword", callback)
+	//
+	// 	dojox.sql("SELECT DECRYPT(SOMECOL1, SOMECOL2) FROM
+	//					FOOBAR WHERE SOMECOL3 = ?", someParam,
+	//					"somePassword", callback)
+
+	dbName: null,
+	
+	// summary:
+	//	If true, then we print out any SQL that is executed
+	//	to the debug window
+	debug: (dojo.exists("dojox.sql.debug") ? dojox.sql.debug:false),
+
+	open: function(dbName){
+		if(this._dbOpen && (!dbName || dbName == this.dbName)){
+			return;
+		}
+		
+		if(!this.dbName){
+			this.dbName = "dot_store_" 
+				+ window.location.href.replace(/[^0-9A-Za-z_]/g, "_");
+			// database names in Gears are limited to 64 characters long
+			if(this.dbName.length > 63){
+			  this.dbName = this.dbName.substring(0, 63);
+			}
+		}
+		
+		if(!dbName){
+			dbName = this.dbName;
+		}
+		
+		try{
+			this._initDb();
+			this.db.open(dbName);
+			this._dbOpen = true;
+		}catch(exp){
+			throw exp.message||exp;
+		}
+	},
+
+	close: function(dbName){
+		// on Internet Explorer, Google Gears throws an exception
+		// "Object not a collection", when we try to close the
+		// database -- just don't close it on this platform
+		// since we are running into a Gears bug; the Gears team
+		// said it's ok to not close a database connection
+		if(dojo.isIE){ return; }
+		
+		if(!this._dbOpen && (!dbName || dbName == this.dbName)){
+			return;
+		}
+		
+		if(!dbName){
+			dbName = this.dbName;
+		}
+		
+		try{
+			this.db.close(dbName);
+			this._dbOpen = false;
+		}catch(exp){
+			throw exp.message||exp;
+		}
+	},
+	
+	_exec: function(params){
+		try{	
+			// get the Gears Database object
+			this._initDb();
+		
+			// see if we need to open the db; if programmer
+			// manually called dojox.sql.open() let them handle
+			// it; otherwise we open and close automatically on
+			// each SQL execution
+			if(!this._dbOpen){
+				this.open();
+				this._autoClose = true;
+			}
+		
+			// determine our parameters
+			var sql = null;
+			var callback = null;
+			var password = null;
+
+			var args = dojo._toArray(params);
+
+			sql = args.splice(0, 1)[0];
+
+			// does this SQL statement use the ENCRYPT or DECRYPT
+			// keywords? if so, extract our callback and crypto
+			// password
+			if(this._needsEncrypt(sql) || this._needsDecrypt(sql)){
+				callback = args.splice(args.length - 1, 1)[0];
+				password = args.splice(args.length - 1, 1)[0];
+			}
+
+			// 'args' now just has the SQL parameters
+
+			// print out debug SQL output if the developer wants that
+			if(this.debug){
+				this._printDebugSQL(sql, args);
+			}
+
+			// handle SQL that needs encryption/decryption differently
+			// do we have an ENCRYPT SQL statement? if so, handle that first
+			var crypto;
+			if(this._needsEncrypt(sql)){
+				crypto = new dojox.sql._SQLCrypto("encrypt", sql, 
+													password, args, 
+													callback);
+				return null; // encrypted results will arrive asynchronously
+			}else if(this._needsDecrypt(sql)){ // otherwise we have a DECRYPT statement
+				crypto = new dojox.sql._SQLCrypto("decrypt", sql, 
+													password, args, 
+													callback);
+				return null; // decrypted results will arrive asynchronously
+			}
+
+			// execute the SQL and get the results
+			var rs = this.db.execute(sql, args);
+			
+			// Gears ResultSet object's are ugly -- normalize
+			// these into something JavaScript programmers know
+			// how to work with, basically an array of 
+			// JavaScript objects where each property name is
+			// simply the field name for a column of data
+			rs = this._normalizeResults(rs);
+		
+			if(this._autoClose){
+				this.close();
+			}
+		
+			return rs;
+		}catch(exp){
+			exp = exp.message||exp;
+			
+			console.debug("SQL Exception: " + exp);
+			
+			if(this._autoClose){
+				try{ 
+					this.close(); 
+				}catch(e){
+					console.debug("Error closing database: " 
+									+ e.message||e);
+				}
+			}
+		
+			throw exp;
+		}
+		
+		return null;
+	},
+
+	_initDb: function(){
+		if(!this.db){
+			try{
+				this.db = google.gears.factory.create('beta.database', '1.0');
+			}catch(exp){
+				dojo.setObject("google.gears.denied", true);
+				if(dojox.off){
+				  dojox.off.onFrameworkEvent("coreOperationFailed");
+				}
+				throw "Google Gears must be allowed to run";
+			}
+		}
+	},
+
+	_printDebugSQL: function(sql, args){
+		var msg = "dojox.sql(\"" + sql + "\"";
+		for(var i = 0; i < args.length; i++){
+			if(typeof args[i] == "string"){
+				msg += ", \"" + args[i] + "\"";
+			}else{
+				msg += ", " + args[i];
+			}
+		}
+		msg += ")";
+	
+		console.debug(msg);
+	},
+
+	_normalizeResults: function(rs){
+		var results = [];
+		if(!rs){ return []; }
+	
+		while(rs.isValidRow()){
+			var row = {};
+		
+			for(var i = 0; i < rs.fieldCount(); i++){
+				var fieldName = rs.fieldName(i);
+				var fieldValue = rs.field(i);
+				row[fieldName] = fieldValue;
+			}
+		
+			results.push(row);
+		
+			rs.next();
+		}
+	
+		rs.close();
+		
+		return results;
+	},
+
+	_needsEncrypt: function(sql){
+		return /encrypt\([^\)]*\)/i.test(sql);
+	},
+
+	_needsDecrypt: function(sql){
+		return /decrypt\([^\)]*\)/i.test(sql);
+	}
 });
-}
-}
-}
-this._finishedSpawningCrypto=true;
-},_stripCryptoSQL:function(sql){
-sql=sql.replace(/DECRYPT\(\*\)/ig,"*");
-var _35=sql.match(/ENCRYPT\([^\)]*\)/ig);
-if(_35!=null){
-for(var i=0;i<_35.length;i++){
-var _36=_35[i];
-var _37=_36.match(/ENCRYPT\(([^\)]*)\)/i)[1];
-sql=sql.replace(_36,_37);
-}
-}
-_35=sql.match(/DECRYPT\([^\)]*\)/ig);
-if(_35!=null){
-for(i=0;i<_35.length;i++){
-var _38=_35[i];
-var _39=_38.match(/DECRYPT\(([^\)]*)\)/i)[1];
-sql=sql.replace(_38,_39);
-}
-}
-return sql;
-},_flagEncryptedArgs:function(sql,_3a){
-var _3b=new RegExp(/([\"][^\"]*\?[^\"]*[\"])|([\'][^\']*\?[^\']*[\'])|(\?)/ig);
-var _3c;
-var _3d=0;
-var _3e=[];
-while((_3c=_3b.exec(sql))!=null){
-var _3f=RegExp.lastMatch+"";
-if(/^[\"\']/.test(_3f)){
-continue;
-}
-var _40=false;
-if(/ENCRYPT\([^\)]*$/i.test(RegExp.leftContext)){
-_40=true;
-}
-_3e[_3d]=_40;
-_3d++;
-}
-return _3e;
-},_determineDecryptedColumns:function(sql){
-var _41={};
-if(/DECRYPT\(\*\)/i.test(sql)){
-_41="*";
-}else{
-var _42=/DECRYPT\((?:\s*\w*\s*\,?)*\)/ig;
-var _43=_42.exec(sql);
-while(_43){
-var _44=new String(RegExp.lastMatch);
-var _45=_44.replace(/DECRYPT\(/i,"");
-_45=_45.replace(/\)/,"");
-_45=_45.split(/\s*,\s*/);
-dojo.forEach(_45,function(_46){
-if(/\s*\w* AS (\w*)/i.test(_46)){
-_46=_46.match(/\s*\w* AS (\w*)/i)[1];
-}
-_41[_46]=true;
+
+dojo.declare("dojox.sql._SQLCrypto", null, {
+	// summary:
+	//	A private class encapsulating any cryptography that must be done
+	// 	on a SQL statement. We instantiate this class and have it hold
+	//	it's state so that we can potentially have several encryption
+	//	operations happening at the same time by different SQL statements.	
+	constructor: function(action, sql, password, args, callback){
+		if(action == "encrypt"){
+			this._execEncryptSQL(sql, password, args, callback);
+		}else{
+			this._execDecryptSQL(sql, password, args, callback);
+		}		
+	}, 
+	
+	_execEncryptSQL: function(sql, password, args, callback){
+		// strip the ENCRYPT/DECRYPT keywords from the SQL
+		var strippedSQL = this._stripCryptoSQL(sql);
+	
+		// determine what arguments need encryption
+		var encryptColumns = this._flagEncryptedArgs(sql, args);
+	
+		// asynchronously encrypt each argument that needs it
+		var self = this;
+		this._encrypt(strippedSQL, password, args, encryptColumns, function(finalArgs){
+			// execute the SQL
+			var error = false;
+			var resultSet = [];
+			var exp = null;
+			try{
+				resultSet = dojox.sql.db.execute(strippedSQL, finalArgs);
+			}catch(execError){
+				error = true;
+				exp = execError.message||execError;
+			}
+		
+			// was there an error during SQL execution?
+			if(exp != null){
+				if(dojox.sql._autoClose){
+					try{ dojox.sql.close(); }catch(e){}
+				}
+			
+				callback(null, true, exp.toString());
+				return;
+			}
+		
+			// normalize SQL results into a JavaScript object 
+			// we can work with
+			resultSet = dojox.sql._normalizeResults(resultSet);
+		
+			if(dojox.sql._autoClose){
+				dojox.sql.close();
+			}
+				
+			// are any decryptions necessary on the result set?
+			if(dojox.sql._needsDecrypt(sql)){
+				// determine which of the result set columns needs decryption
+	 			var needsDecrypt = self._determineDecryptedColumns(sql);
+
+				// now decrypt columns asynchronously
+				// decrypt columns that need it
+				self._decrypt(resultSet, needsDecrypt, password, function(finalResultSet){
+					callback(finalResultSet, false, null);
+				});
+			}else{
+				callback(resultSet, false, null);
+			}
+		});
+	},
+
+	_execDecryptSQL: function(sql, password, args, callback){
+		// strip the ENCRYPT/DECRYPT keywords from the SQL
+		var strippedSQL = this._stripCryptoSQL(sql);
+	
+		// determine which columns needs decryption; this either
+		// returns the value *, which means all result set columns will
+		// be decrypted, or it will return the column names that need
+		// decryption set on a hashtable so we can quickly test a given
+		// column name; the key is the column name that needs
+		// decryption and the value is 'true' (i.e. needsDecrypt["someColumn"] 
+		// would return 'true' if it needs decryption, and would be 'undefined'
+		// or false otherwise)
+		var needsDecrypt = this._determineDecryptedColumns(sql);
+	
+		// execute the SQL
+		var error = false;
+		var resultSet = [];
+		var exp = null;
+		try{
+			resultSet = dojox.sql.db.execute(strippedSQL, args);
+		}catch(execError){
+			error = true;
+			exp = execError.message||execError;
+		}
+	
+		// was there an error during SQL execution?
+		if(exp != null){
+			if(dojox.sql._autoClose){
+				try{ dojox.sql.close(); }catch(e){}
+			}
+		
+			callback(resultSet, true, exp.toString());
+			return;
+		}
+	
+		// normalize SQL results into a JavaScript object 
+		// we can work with
+		resultSet = dojox.sql._normalizeResults(resultSet);
+	
+		if(dojox.sql._autoClose){
+			dojox.sql.close();
+		}
+	
+		// decrypt columns that need it
+		this._decrypt(resultSet, needsDecrypt, password, function(finalResultSet){
+			callback(finalResultSet, false, null);
+		});
+	},
+
+	_encrypt: function(sql, password, args, encryptColumns, callback){
+		//console.debug("_encrypt, sql="+sql+", password="+password+", encryptColumns="+encryptColumns+", args="+args);
+	
+		this._totalCrypto = 0;
+		this._finishedCrypto = 0;
+		this._finishedSpawningCrypto = false;
+		this._finalArgs = args;
+	
+		for(var i = 0; i < args.length; i++){
+			if(encryptColumns[i]){
+				// we have an encrypt() keyword -- get just the value inside
+				// the encrypt() parantheses -- for now this must be a ?
+				var sqlParam = args[i];
+				var paramIndex = i;
+			
+				// update the total number of encryptions we know must be done asynchronously
+				this._totalCrypto++;
+			
+				// FIXME: This currently uses DES as a proof-of-concept since the
+				// DES code used is quite fast and was easy to work with. Modify dojox.sql
+				// to be able to specify a different encryption provider through a 
+				// a SQL-like syntax, such as dojox.sql("SET ENCRYPTION BLOWFISH"),
+				// and modify the dojox.crypto.Blowfish code to be able to work using
+				// a Google Gears Worker Pool
+			
+				// do the actual encryption now, asychronously on a Gears worker thread
+				dojox.sql._crypto.encrypt(sqlParam, password, dojo.hitch(this, function(results){
+					// set the new encrypted value
+					this._finalArgs[paramIndex] = results;
+					this._finishedCrypto++;
+					// are we done with all encryption?
+					if(this._finishedCrypto >= this._totalCrypto
+						&& this._finishedSpawningCrypto){
+						callback(this._finalArgs);
+					}
+				}));
+			}
+		}
+	
+		this._finishedSpawningCrypto = true;
+	},
+
+	_decrypt: function(resultSet, needsDecrypt, password, callback){
+		//console.debug("decrypt, resultSet="+resultSet+", needsDecrypt="+needsDecrypt+", password="+password);
+		
+		this._totalCrypto = 0;
+		this._finishedCrypto = 0;
+		this._finishedSpawningCrypto = false;
+		this._finalResultSet = resultSet;
+	
+		for(var i = 0; i < resultSet.length; i++){
+			var row = resultSet[i];
+		
+			// go through each of the column names in row,
+			// seeing if they need decryption
+			for(var columnName in row){
+				if(needsDecrypt == "*" || needsDecrypt[columnName]){
+					this._totalCrypto++;
+					var columnValue = row[columnName];
+				
+					// forming a closure here can cause issues, with values not cleanly
+					// saved on Firefox/Mac OS X for some of the values above that
+					// are needed in the callback below; call a subroutine that will form 
+					// a closure inside of itself instead
+					this._decryptSingleColumn(columnName, columnValue, password, i,
+												function(finalResultSet){
+						callback(finalResultSet);
+					});
+				}
+			}
+		}
+	
+		this._finishedSpawningCrypto = true;
+	},
+
+	_stripCryptoSQL: function(sql){
+		// replace all DECRYPT(*) occurrences with a *
+		sql = sql.replace(/DECRYPT\(\*\)/ig, "*");
+	
+		// match any ENCRYPT(?, ?, ?, etc) occurrences,
+		// then replace with just the question marks in the
+		// middle
+		var matches = sql.match(/ENCRYPT\([^\)]*\)/ig);
+		if(matches != null){
+			for(var i = 0; i < matches.length; i++){
+				var encryptStatement = matches[i];
+				var encryptValue = encryptStatement.match(/ENCRYPT\(([^\)]*)\)/i)[1];
+				sql = sql.replace(encryptStatement, encryptValue);
+			}
+		}
+	
+		// match any DECRYPT(COL1, COL2, etc) occurrences,
+		// then replace with just the column names
+		// in the middle
+		matches = sql.match(/DECRYPT\([^\)]*\)/ig);
+		if(matches != null){
+			for(i = 0; i < matches.length; i++){
+				var decryptStatement = matches[i];
+				var decryptValue = decryptStatement.match(/DECRYPT\(([^\)]*)\)/i)[1];
+				sql = sql.replace(decryptStatement, decryptValue);
+			}
+		}
+	
+		return sql;
+	},
+
+	_flagEncryptedArgs: function(sql, args){
+		// capture literal strings that have question marks in them,
+		// and also capture question marks that stand alone
+		var tester = new RegExp(/([\"][^\"]*\?[^\"]*[\"])|([\'][^\']*\?[^\']*[\'])|(\?)/ig);
+		var matches;
+		var currentParam = 0;
+		var results = [];
+		while((matches = tester.exec(sql)) != null){
+			var currentMatch = RegExp.lastMatch+"";
+
+			// are we a literal string? then ignore it
+			if(/^[\"\']/.test(currentMatch)){
+				continue;
+			}
+
+			// do we have an encrypt keyword to our left?
+			var needsEncrypt = false;
+			if(/ENCRYPT\([^\)]*$/i.test(RegExp.leftContext)){
+				needsEncrypt = true;
+			}
+
+			// set the encrypted flag
+			results[currentParam] = needsEncrypt;
+
+			currentParam++;
+		}
+	
+		return results;
+	},
+
+	_determineDecryptedColumns: function(sql){
+		var results = {};
+
+		if(/DECRYPT\(\*\)/i.test(sql)){
+			results = "*";
+		}else{
+			var tester = /DECRYPT\((?:\s*\w*\s*\,?)*\)/ig;
+			var matches = tester.exec(sql);
+			while(matches){
+				var lastMatch = new String(RegExp.lastMatch);
+				var columnNames = lastMatch.replace(/DECRYPT\(/i, "");
+				columnNames = columnNames.replace(/\)/, "");
+				columnNames = columnNames.split(/\s*,\s*/);
+				dojo.forEach(columnNames, function(column){
+					if(/\s*\w* AS (\w*)/i.test(column)){
+						column = column.match(/\s*\w* AS (\w*)/i)[1];
+					}
+					results[column] = true;
+				});
+				
+				matches = tester.exec(sql)
+			}
+		}
+
+		return results;
+	},
+
+	_decryptSingleColumn: function(columnName, columnValue, password, currentRowIndex,
+											callback){
+		//console.debug("decryptSingleColumn, columnName="+columnName+", columnValue="+columnValue+", currentRowIndex="+currentRowIndex)
+		dojox.sql._crypto.decrypt(columnValue, password, dojo.hitch(this, function(results){
+			// set the new decrypted value
+			this._finalResultSet[currentRowIndex][columnName] = results;
+			this._finishedCrypto++;
+			
+			// are we done with all encryption?
+			if(this._finishedCrypto >= this._totalCrypto
+				&& this._finishedSpawningCrypto){
+				//console.debug("done with all decrypts");
+				callback(this._finalResultSet);
+			}
+		}));
+	}
 });
-_43=_42.exec(sql);
-}
-}
-return _41;
-},_decryptSingleColumn:function(_47,_48,_49,_4a,_4b){
-dojox.sql._crypto.decrypt(_48,_49,dojo.hitch(this,function(_4c){
-this._finalResultSet[_4a][_47]=_4c;
-this._finishedCrypto++;
-if(this._finishedCrypto>=this._totalCrypto&&this._finishedSpawningCrypto){
-_4b(this._finalResultSet);
-}
-}));
-}});
+
 (function(){
-var _4d=dojox.sql;
-dojox.sql=new Function("return dojox.sql._exec(arguments);");
-dojo.mixin(dojox.sql,_4d);
+
+	var orig_sql = dojox.sql;
+	dojox.sql = new Function("return dojox.sql._exec(arguments);");
+	dojo.mixin(dojox.sql, orig_sql);
+	
 })();
-}
diff --git a/dojox/sql/_crypto.js b/dojox/sql/_crypto.js
index db0b704..119cf92 100644
--- a/dojox/sql/_crypto.js
+++ b/dojox/sql/_crypto.js
@@ -1,293 +1,440 @@
-/*
-	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
-*/
+dojo.provide("dojox.sql._crypto");
+dojo.mixin(dojox.sql._crypto, {
+	// summary: dojox.sql cryptography code
+	// description: 
+	//	Taken from http://www.movable-type.co.uk/scripts/aes.html by
+	// 	Chris Veness (CLA signed); adapted for Dojo and Google Gears Worker Pool
+	// 	by Brad Neuberg, bkn3 at columbia.edu
+	//
+	// _POOL_SIZE:
+	//	Size of worker pool to create to help with crypto
+	_POOL_SIZE: 100,
 
+	encrypt: function(plaintext, password, callback){
+		// summary:
+		//	Use Corrected Block TEA to encrypt plaintext using password
+		//	(note plaintext & password must be strings not string objects).
+		//	Results will be returned to the 'callback' asychronously.	
+		this._initWorkerPool();
 
-if(!dojo._hasResource["dojox.sql._crypto"]){
-dojo._hasResource["dojox.sql._crypto"]=true;
-dojo.provide("dojox.sql._crypto");
-dojo.mixin(dojox.sql._crypto,{_POOL_SIZE:100,encrypt:function(_1,_2,_3){
-this._initWorkerPool();
-var _4={plaintext:_1,password:_2};
-_4=dojo.toJson(_4);
-_4="encr:"+String(_4);
-this._assignWork(_4,_3);
-},decrypt:function(_5,_6,_7){
-this._initWorkerPool();
-var _8={ciphertext:_5,password:_6};
-_8=dojo.toJson(_8);
-_8="decr:"+String(_8);
-this._assignWork(_8,_7);
-},_initWorkerPool:function(){
-if(!this._manager){
-try{
-this._manager=google.gears.factory.create("beta.workerpool","1.0");
-this._unemployed=[];
-this._employed={};
-this._handleMessage=[];
-var _9=this;
-this._manager.onmessage=function(_a,_b){
-var _c=_9._employed["_"+_b];
-_9._employed["_"+_b]=undefined;
-_9._unemployed.push("_"+_b);
-if(_9._handleMessage.length){
-var _d=_9._handleMessage.shift();
-_9._assignWork(_d.msg,_d.callback);
-}
-_c(_a);
-};
-var _e="function _workerInit(){"+"gearsWorkerPool.onmessage = "+String(this._workerHandler)+";"+"}";
-var _f=_e+" _workerInit();";
-for(var i=0;i<this._POOL_SIZE;i++){
-this._unemployed.push("_"+this._manager.createWorker(_f));
-}
-}
-catch(exp){
-throw exp.message||exp;
-}
-}
-},_assignWork:function(msg,_10){
-if(!this._handleMessage.length&&this._unemployed.length){
-var _11=this._unemployed.shift().substring(1);
-this._employed["_"+_11]=_10;
-this._manager.sendMessage(msg,parseInt(_11,10));
-}else{
-this._handleMessage={msg:msg,callback:_10};
-}
-},_workerHandler:function(msg,_12){
-var _13=[99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,95,151,68,23 [...]
-var _14=[[0,0,0,0],[1,0,0,0],[2,0,0,0],[4,0,0,0],[8,0,0,0],[16,0,0,0],[32,0,0,0],[64,0,0,0],[128,0,0,0],[27,0,0,0],[54,0,0,0]];
-function _15(_16,w){
-var Nb=4;
-var Nr=w.length/Nb-1;
-var _17=[[],[],[],[]];
-for(var i=0;i<4*Nb;i++){
-_17[i%4][Math.floor(i/4)]=_16[i];
-}
-_17=_18(_17,w,0,Nb);
-for(var _19=1;_19<Nr;_19++){
-_17=_1a(_17,Nb);
-_17=_1b(_17,Nb);
-_17=_1c(_17,Nb);
-_17=_18(_17,w,_19,Nb);
-}
-_17=_1a(_17,Nb);
-_17=_1b(_17,Nb);
-_17=_18(_17,w,Nr,Nb);
-var _1d=new Array(4*Nb);
-for(var i=0;i<4*Nb;i++){
-_1d[i]=_17[i%4][Math.floor(i/4)];
-}
-return _1d;
-};
-function _1a(s,Nb){
-for(var r=0;r<4;r++){
-for(var c=0;c<Nb;c++){
-s[r][c]=_13[s[r][c]];
-}
-}
-return s;
-};
-function _1b(s,Nb){
-var t=new Array(4);
-for(var r=1;r<4;r++){
-for(var c=0;c<4;c++){
-t[c]=s[r][(c+r)%Nb];
-}
-for(var c=0;c<4;c++){
-s[r][c]=t[c];
-}
-}
-return s;
-};
-function _1c(s,Nb){
-for(var c=0;c<4;c++){
-var a=new Array(4);
-var b=new Array(4);
-for(var i=0;i<4;i++){
-a[i]=s[i][c];
-b[i]=s[i][c]&128?s[i][c]<<1^283:s[i][c]<<1;
-}
-s[0][c]=b[0]^a[1]^b[1]^a[2]^a[3];
-s[1][c]=a[0]^b[1]^a[2]^b[2]^a[3];
-s[2][c]=a[0]^a[1]^b[2]^a[3]^b[3];
-s[3][c]=a[0]^b[0]^a[1]^a[2]^b[3];
-}
-return s;
-};
-function _18(_1e,w,rnd,Nb){
-for(var r=0;r<4;r++){
-for(var c=0;c<Nb;c++){
-_1e[r][c]^=w[rnd*4+c][r];
-}
-}
-return _1e;
-};
-function _1f(key){
-var Nb=4;
-var Nk=key.length/4;
-var Nr=Nk+6;
-var w=new Array(Nb*(Nr+1));
-var _20=new Array(4);
-for(var i=0;i<Nk;i++){
-var r=[key[4*i],key[4*i+1],key[4*i+2],key[4*i+3]];
-w[i]=r;
-}
-for(var i=Nk;i<(Nb*(Nr+1));i++){
-w[i]=new Array(4);
-for(var t=0;t<4;t++){
-_20[t]=w[i-1][t];
-}
-if(i%Nk==0){
-_20=_21(_22(_20));
-for(var t=0;t<4;t++){
-_20[t]^=_14[i/Nk][t];
-}
-}else{
-if(Nk>6&&i%Nk==4){
-_20=_21(_20);
-}
-}
-for(var t=0;t<4;t++){
-w[i][t]=w[i-Nk][t]^_20[t];
-}
-}
-return w;
-};
-function _21(w){
-for(var i=0;i<4;i++){
-w[i]=_13[w[i]];
-}
-return w;
-};
-function _22(w){
-w[4]=w[0];
-for(var i=0;i<4;i++){
-w[i]=w[i+1];
-}
-return w;
-};
-function _23(_24,_25,_26){
-if(!(_26==128||_26==192||_26==256)){
-return "";
-}
-var _27=_26/8;
-var _28=new Array(_27);
-for(var i=0;i<_27;i++){
-_28[i]=_25.charCodeAt(i)&255;
-}
-var key=_15(_28,_1f(_28));
-key=key.concat(key.slice(0,_27-16));
-var _29=16;
-var _2a=new Array(_29);
-var _2b=(new Date()).getTime();
-for(var i=0;i<4;i++){
-_2a[i]=(_2b>>>i*8)&255;
-}
-for(var i=0;i<4;i++){
-_2a[i+4]=(_2b/4294967296>>>i*8)&255;
-}
-var _2c=_1f(key);
-var _2d=Math.ceil(_24.length/_29);
-var _2e=new Array(_2d);
-for(var b=0;b<_2d;b++){
-for(var c=0;c<4;c++){
-_2a[15-c]=(b>>>c*8)&255;
-}
-for(var c=0;c<4;c++){
-_2a[15-c-4]=(b/4294967296>>>c*8);
-}
-var _2f=_15(_2a,_2c);
-var _30=b<_2d-1?_29:(_24.length-1)%_29+1;
-var ct="";
-for(var i=0;i<_30;i++){
-var _31=_24.charCodeAt(b*_29+i);
-var _32=_31^_2f[i];
-ct+=String.fromCharCode(_32);
-}
-_2e[b]=_33(ct);
-}
-var _34="";
-for(var i=0;i<8;i++){
-_34+=String.fromCharCode(_2a[i]);
-}
-_34=_33(_34);
-return _34+"-"+_2e.join("-");
-};
-function _35(_36,_37,_38){
-if(!(_38==128||_38==192||_38==256)){
-return "";
-}
-var _39=_38/8;
-var _3a=new Array(_39);
-for(var i=0;i<_39;i++){
-_3a[i]=_37.charCodeAt(i)&255;
-}
-var _3b=_1f(_3a);
-var key=_15(_3a,_3b);
-key=key.concat(key.slice(0,_39-16));
-var _3c=_1f(key);
-_36=_36.split("-");
-var _3d=16;
-var _3e=new Array(_3d);
-var _3f=_40(_36[0]);
-for(var i=0;i<8;i++){
-_3e[i]=_3f.charCodeAt(i);
-}
-var _41=new Array(_36.length-1);
-for(var b=1;b<_36.length;b++){
-for(var c=0;c<4;c++){
-_3e[15-c]=((b-1)>>>c*8)&255;
-}
-for(var c=0;c<4;c++){
-_3e[15-c-4]=((b/4294967296-1)>>>c*8)&255;
-}
-var _42=_15(_3e,_3c);
-_36[b]=_40(_36[b]);
-var pt="";
-for(var i=0;i<_36[b].length;i++){
-var _43=_36[b].charCodeAt(i);
-var _44=_43^_42[i];
-pt+=String.fromCharCode(_44);
-}
-_41[b-1]=pt;
-}
-return _41.join("");
-};
-function _33(str){
-return str.replace(/[\0\t\n\v\f\r\xa0!-]/g,function(c){
-return "!"+c.charCodeAt(0)+"!";
-});
-};
-function _40(str){
-return str.replace(/!\d\d?\d?!/g,function(c){
-return String.fromCharCode(c.slice(1,-1));
+		var msg ={plaintext: plaintext, password: password};
+		msg = dojo.toJson(msg);
+		msg = "encr:" + String(msg);
+
+		this._assignWork(msg, callback);
+	},
+
+	decrypt: function(ciphertext, password, callback){
+		// summary:
+		//	Use Corrected Block TEA to decrypt ciphertext using password
+		//	(note ciphertext & password must be strings not string objects).
+		//	Results will be returned to the 'callback' asychronously.
+		this._initWorkerPool();
+
+		var msg = {ciphertext: ciphertext, password: password};
+		msg = dojo.toJson(msg);
+		msg = "decr:" + String(msg);
+
+		this._assignWork(msg, callback);
+	},
+
+	_initWorkerPool: function(){
+		// bugs in Google Gears prevents us from dynamically creating
+		// and destroying workers as we need them -- the worker
+		// pool functionality stops working after a number of crypto
+		// cycles (probably related to a memory leak in Google Gears).
+		// this is too bad, since it results in much simpler code.
+
+		// instead, we have to create a pool of workers and reuse them. we
+		// keep a stack of 'unemployed' Worker IDs that are currently not working.
+		// if a work request comes in, we pop off the 'unemployed' stack
+		// and put them to work, storing them in an 'employed' hashtable,
+		// keyed by their Worker ID with the value being the callback function
+		// that wants the result. when an employed worker is done, we get
+		// a message in our 'manager' which adds this worker back to the 
+		// unemployed stack and routes the result to the callback that
+		// wanted it. if all the workers were employed in the past but
+		// more work needed to be done (i.e. it's a tight labor pool ;) 
+		// then the work messages are pushed onto
+		// a 'handleMessage' queue as an object tuple{msg: msg, callback: callback}
+
+		if(!this._manager){
+			try{
+				this._manager = google.gears.factory.create("beta.workerpool", "1.0");
+				this._unemployed = [];
+				this._employed ={};
+				this._handleMessage = [];
+		
+				var self = this;
+				this._manager.onmessage = function(msg, sender){
+					// get the callback necessary to serve this result
+					var callback = self._employed["_" + sender];
+			
+					// make this worker unemployed
+					self._employed["_" + sender] = undefined;
+					self._unemployed.push("_" + sender);
+			
+					// see if we need to assign new work
+					// that was queued up needing to be done
+					if(self._handleMessage.length){
+						var handleMe = self._handleMessage.shift();
+						self._assignWork(handleMe.msg, handleMe.callback);
+					}
+			
+					// return results
+					callback(msg);
+				}
+			
+				var workerInit = "function _workerInit(){"
+									+ "gearsWorkerPool.onmessage = "
+										+ String(this._workerHandler)
+									+ ";"
+								+ "}";
+		
+				var code = workerInit + " _workerInit();";
+
+				// create our worker pool
+				for(var i = 0; i < this._POOL_SIZE; i++){
+					this._unemployed.push("_" + this._manager.createWorker(code));
+				}
+			}catch(exp){
+				throw exp.message||exp;
+			}
+		}
+	},
+
+	_assignWork: function(msg, callback){
+		// can we immediately assign this work?
+		if(!this._handleMessage.length && this._unemployed.length){
+			// get an unemployed worker
+			var workerID = this._unemployed.shift().substring(1); // remove _
+	
+			// list this worker as employed
+			this._employed["_" + workerID] = callback;
+	
+			// do the worke
+			this._manager.sendMessage(msg, parseInt(workerID,10));
+		}else{
+			// we have to queue it up
+			this._handleMessage ={msg: msg, callback: callback};
+		}
+	},
+
+	_workerHandler: function(msg, sender){
+	
+		/* Begin AES Implementation */
+	
+		/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+	
+		// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [§5.1.1]
+		var Sbox =	[0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
+					 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
+					 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
+					 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
+					 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
+					 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
+					 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
+					 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
+					 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
+					 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
+					 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
+					 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
+					 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
+					 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
+					 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
+					 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16];
+
+		// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2]
+		var Rcon = [ [0x00, 0x00, 0x00, 0x00],
+					 [0x01, 0x00, 0x00, 0x00],
+					 [0x02, 0x00, 0x00, 0x00],
+					 [0x04, 0x00, 0x00, 0x00],
+					 [0x08, 0x00, 0x00, 0x00],
+					 [0x10, 0x00, 0x00, 0x00],
+					 [0x20, 0x00, 0x00, 0x00],
+					 [0x40, 0x00, 0x00, 0x00],
+					 [0x80, 0x00, 0x00, 0x00],
+					 [0x1b, 0x00, 0x00, 0x00],
+					 [0x36, 0x00, 0x00, 0x00] ]; 
+
+		/*
+		 * AES Cipher function: encrypt 'input' with Rijndael algorithm
+		 *
+		 *	 takes	 byte-array 'input' (16 bytes)
+		 *			 2D byte-array key schedule 'w' (Nr+1 x Nb bytes)
+		 *
+		 *	 applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage
+		 *
+		 *	 returns byte-array encrypted value (16 bytes)
+		 */
+		function Cipher(input, w) {	   // main Cipher function [§5.1]
+		  var Nb = 4;				// block size (in words): no of columns in state (fixed at 4 for AES)
+		  var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
+
+		  var state = [[],[],[],[]];  // initialise 4xNb byte-array 'state' with input [§3.4]
+		  for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i];
+
+		  state = AddRoundKey(state, w, 0, Nb);
+
+		  for (var round=1; round<Nr; round++) {
+			state = SubBytes(state, Nb);
+			state = ShiftRows(state, Nb);
+			state = MixColumns(state, Nb);
+			state = AddRoundKey(state, w, round, Nb);
+		  }
+
+		  state = SubBytes(state, Nb);
+		  state = ShiftRows(state, Nb);
+		  state = AddRoundKey(state, w, Nr, Nb);
+
+		  var output = new Array(4*Nb);	 // convert state to 1-d array before returning [§3.4]
+		  for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)];
+		  return output;
+		}
+
+
+		function SubBytes(s, Nb) {	  // apply SBox to state S [§5.1.1]
+		  for (var r=0; r<4; r++) {
+			for (var c=0; c<Nb; c++) s[r][c] = Sbox[s[r][c]];
+		  }
+		  return s;
+		}
+
+
+		function ShiftRows(s, Nb) {	   // shift row r of state S left by r bytes [§5.1.2]
+		  var t = new Array(4);
+		  for (var r=1; r<4; r++) {
+			for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb];	// shift into temp copy
+			for (var c=0; c<4; c++) s[r][c] = t[c];			// and copy back
+		  }			 // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
+		  return s;	 // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf 
+		}
+
+
+		function MixColumns(s, Nb) {   // combine bytes of each col of state S [§5.1.3]
+		  for (var c=0; c<4; c++) {
+			var a = new Array(4);  // 'a' is a copy of the current column from 's'
+			var b = new Array(4);  // 'b' is a•{02} in GF(2^8)
+			for (var i=0; i<4; i++) {
+			  a[i] = s[i][c];
+			  b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1;
+			}
+			// a[n] ^ b[n] is a•{03} in GF(2^8)
+			s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3
+			s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3
+			s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3
+			s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3
+		  }
+		  return s;
+		}
+
+
+		function AddRoundKey(state, w, rnd, Nb) {  // xor Round Key into state S [§5.1.4]
+		  for (var r=0; r<4; r++) {
+			for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r];
+		  }
+		  return state;
+		}
+
+
+		function KeyExpansion(key) {  // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2]
+		  var Nb = 4;			 // block size (in words): no of columns in state (fixed at 4 for AES)
+		  var Nk = key.length/4	 // key length (in words): 4/6/8 for 128/192/256-bit keys
+		  var Nr = Nk + 6;		 // no of rounds: 10/12/14 for 128/192/256-bit keys
+
+		  var w = new Array(Nb*(Nr+1));
+		  var temp = new Array(4);
+
+		  for (var i=0; i<Nk; i++) {
+			var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];
+			w[i] = r;
+		  }
+
+		  for (var i=Nk; i<(Nb*(Nr+1)); i++) {
+			w[i] = new Array(4);
+			for (var t=0; t<4; t++) temp[t] = w[i-1][t];
+			if (i % Nk == 0) {
+			  temp = SubWord(RotWord(temp));
+			  for (var t=0; t<4; t++) temp[t] ^= Rcon[i/Nk][t];
+			} else if (Nk > 6 && i%Nk == 4) {
+			  temp = SubWord(temp);
+			}
+			for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t];
+		  }
+
+		  return w;
+		}
+
+		function SubWord(w) {	 // apply SBox to 4-byte word w
+		  for (var i=0; i<4; i++) w[i] = Sbox[w[i]];
+		  return w;
+		}
+
+		function RotWord(w) {	 // rotate 4-byte word w left by one byte
+		  w[4] = w[0];
+		  for (var i=0; i<4; i++) w[i] = w[i+1];
+		  return w;
+		}
+
+		/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+		/* 
+		 * Use AES to encrypt 'plaintext' with 'password' using 'nBits' key, in 'Counter' mode of operation
+		 *							 - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+		 *	 for each block
+		 *	 - outputblock = cipher(counter, key)
+		 *	 - cipherblock = plaintext xor outputblock
+		 */
+		function AESEncryptCtr(plaintext, password, nBits) {
+		  if (!(nBits==128 || nBits==192 || nBits==256)) return '';	 // standard allows 128/192/256 bit keys
+
+		  // for this example script, generate the key by applying Cipher to 1st 16/24/32 chars of password; 
+		  // for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1
+		  var nBytes = nBits/8;	 // no bytes in key
+		  var pwBytes = new Array(nBytes);
+		  for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
+
+		  var key = Cipher(pwBytes, KeyExpansion(pwBytes));
+
+		  key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
+
+		  // initialise counter block (NIST SP800-38A §B.2): millisecond time-stamp for nonce in 1st 8 bytes,
+		  // block counter in 2nd 8 bytes
+		  var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
+		  var counterBlock = new Array(blockSize);	// block size fixed at 16 bytes / 128 bits (Nb=4) for AES
+		  var nonce = (new Date()).getTime();  // milliseconds since 1-Jan-1970
+
+		  // encode nonce in two stages to cater for JavaScript 32-bit limit on bitwise ops
+		  for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff;
+		  for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff; 
+
+		  // generate key schedule - an expansion of the key into distinct Key Rounds for each round
+		  var keySchedule = KeyExpansion(key);
+
+		  var blockCount = Math.ceil(plaintext.length/blockSize);
+		  var ciphertext = new Array(blockCount);  // ciphertext as array of strings
+ 
+		  for (var b=0; b<blockCount; b++) {
+			// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
+			// again done in two stages for 32-bit ops
+			for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;
+			for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8)
+
+			var cipherCntr = Cipher(counterBlock, keySchedule);	 // -- encrypt counter block --
+
+			// calculate length of final block:
+			var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1;
+
+			var ct = '';
+			for (var i=0; i<blockLength; i++) {	 // -- xor plaintext with ciphered counter byte-by-byte --
+			  var plaintextByte = plaintext.charCodeAt(b*blockSize+i);
+			  var cipherByte = plaintextByte ^ cipherCntr[i];
+			  ct += String.fromCharCode(cipherByte);
+			}
+			// ct is now ciphertext for this block
+
+			ciphertext[b] = escCtrlChars(ct);  // escape troublesome characters in ciphertext
+		  }
+
+		  // convert the nonce to a string to go on the front of the ciphertext
+		  var ctrTxt = '';
+		  for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]);
+		  ctrTxt = escCtrlChars(ctrTxt);
+
+		  // use '-' to separate blocks, use Array.join to concatenate arrays of strings for efficiency
+		  return ctrTxt + '-' + ciphertext.join('-');
+		}
+
+
+		/* 
+		 * Use AES to decrypt 'ciphertext' with 'password' using 'nBits' key, in Counter mode of operation
+		 *
+		 *	 for each block
+		 *	 - outputblock = cipher(counter, key)
+		 *	 - cipherblock = plaintext xor outputblock
+		 */
+		function AESDecryptCtr(ciphertext, password, nBits) {
+		  if (!(nBits==128 || nBits==192 || nBits==256)) return '';	 // standard allows 128/192/256 bit keys
+
+		  var nBytes = nBits/8;	 // no bytes in key
+		  var pwBytes = new Array(nBytes);
+		  for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
+		  var pwKeySchedule = KeyExpansion(pwBytes);
+		  var key = Cipher(pwBytes, pwKeySchedule);
+		  key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
+
+		  var keySchedule = KeyExpansion(key);
+
+		  ciphertext = ciphertext.split('-');  // split ciphertext into array of block-length strings 
+
+		  // recover nonce from 1st element of ciphertext
+		  var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
+		  var counterBlock = new Array(blockSize);
+		  var ctrTxt = unescCtrlChars(ciphertext[0]);
+		  for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i);
+
+		  var plaintext = new Array(ciphertext.length-1);
+
+		  for (var b=1; b<ciphertext.length; b++) {
+			// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
+			for (var c=0; c<4; c++) counterBlock[15-c] = ((b-1) >>> c*8) & 0xff;
+			for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff;
+
+			var cipherCntr = Cipher(counterBlock, keySchedule);	 // encrypt counter block
+
+			ciphertext[b] = unescCtrlChars(ciphertext[b]);
+
+			var pt = '';
+			for (var i=0; i<ciphertext[b].length; i++) {
+			  // -- xor plaintext with ciphered counter byte-by-byte --
+			  var ciphertextByte = ciphertext[b].charCodeAt(i);
+			  var plaintextByte = ciphertextByte ^ cipherCntr[i];
+			  pt += String.fromCharCode(plaintextByte);
+			}
+			// pt is now plaintext for this block
+
+			plaintext[b-1] = pt;  // b-1 'cos no initial nonce block in plaintext
+		  }
+
+		  return plaintext.join('');
+		}
+
+		/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+		function escCtrlChars(str) {  // escape control chars which might cause problems handling ciphertext
+		  return str.replace(/[\0\t\n\v\f\r\xa0!-]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });
+		}  // \xa0 to cater for bug in Firefox; include '-' to leave it free for use as a block marker
+
+		function unescCtrlChars(str) {	// unescape potentially problematic control characters
+		  return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });
+		}
+
+		/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+	
+		function encrypt(plaintext, password){
+			return AESEncryptCtr(plaintext, password, 256);
+		}
+
+		function decrypt(ciphertext, password){	
+			return AESDecryptCtr(ciphertext, password, 256);
+		}
+	
+		/* End AES Implementation */
+	
+		var cmd = msg.substr(0,4);
+		var arg = msg.substr(5);
+		if(cmd == "encr"){
+			arg = eval("(" + arg + ")");
+			var plaintext = arg.plaintext;
+			var password = arg.password;
+			var results = encrypt(plaintext, password);
+			gearsWorkerPool.sendMessage(String(results), sender);
+		}else if(cmd == "decr"){
+			arg = eval("(" + arg + ")");
+			var ciphertext = arg.ciphertext;
+			var password = arg.password;
+			var results = decrypt(ciphertext, password);
+			gearsWorkerPool.sendMessage(String(results), sender);
+		}
+	}
 });
-};
-function _45(_46,_47){
-return _23(_46,_47,256);
-};
-function _48(_49,_4a){
-return _35(_49,_4a,256);
-};
-var cmd=msg.substr(0,4);
-var arg=msg.substr(5);
-if(cmd=="encr"){
-arg=eval("("+arg+")");
-var _4b=arg.plaintext;
-var _4c=arg.password;
-var _4d=_45(_4b,_4c);
-gearsWorkerPool.sendMessage(String(_4d),_12);
-}else{
-if(cmd=="decr"){
-arg=eval("("+arg+")");
-var _4e=arg.ciphertext;
-var _4c=arg.password;
-var _4d=_48(_4e,_4c);
-gearsWorkerPool.sendMessage(String(_4d),_12);
-}
-}
-}});
-}
diff --git a/dojox/sql/demos/customers/customers.html b/dojox/sql/demos/customers/customers.html
new file mode 100644
index 0000000..a4c0c03
--- /dev/null
+++ b/dojox/sql/demos/customers/customers.html
@@ -0,0 +1,292 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+	<head>
+	    <script type="text/javascript" 
+	            src="../../../../dojo/dojo.js" djConfig="isDebug: false"></script>
+		<script type="text/javascript" src="../../../../dojox/off/offline.js"></script>
+		
+		<style type="text/css">
+			body{
+				padding: 2em;
+			}
+			
+			#dataTable{
+				margin-top: 2em;
+			}
+			
+			button{
+				margin-left: 1em;
+			}
+			
+			th, tr, td{
+				text-align: left;
+			}
+			
+			table{
+				text-align: center;
+				clear: both;
+			}
+			
+			#cryptoContainer{
+				float: left;
+				width: 60%;
+			}
+			
+			#numRowsContainer{
+				float: right;
+				width: 40%;
+			}
+			
+			#numRowsContainer input{
+				margin-left: 1.5em;
+				width: 5em;
+			}
+			
+			.table-columns{
+				font-weight: bold;
+			}
+		</style>
+		
+		<script>
+			dojo.require("dojox.sql");
+			
+			dojo.connect(window, "onload", function(){
+				// draw our customer table on the screen
+				createTable();
+				
+				// create our customer table in the database
+				dojox.sql("DROP TABLE IF EXISTS CUSTOMERS");
+				dojox.sql("CREATE TABLE CUSTOMERS ("
+								+ "last_name TEXT, "
+								+ "first_name TEXT, "
+								+ "social_security TEXT"
+								+ ")"
+							);
+			});
+			
+			function createTable(){	
+				// get number of rows to create
+				var NUM_ROWS = document.getElementById("numRows").value;
+				if(!NUM_ROWS){
+					alert("Please enter the number of "
+							+ "customer rows the table should have");
+					return;
+				} 
+				
+				var table = document.getElementById("dataTable");
+				if(table){
+					table.parentNode.removeChild(table);
+				}
+				
+				table = document.createElement("table");
+				table.setAttribute("id", "dataTable");
+				table.setAttribute("border", 1);
+				
+				// if we don't use IE's craptacular proprietary table methods
+				// we get strange display glitches
+				var tr = (dojo.isIE) ? table.insertRow() : document.createElement("tr");
+				tr.className = "table-columns";
+				var th = (dojo.isIE) ? tr.insertCell() : document.createElement("th");
+				th.appendChild(document.createTextNode("Last Name"));
+				if(!dojo.isIE){
+					tr.appendChild(th);
+				}
+				th = (dojo.isIE) ? tr.insertCell() : document.createElement("th");
+				th.appendChild(document.createTextNode("First Name"));
+				if(!dojo.isIE){
+					tr.appendChild(th);
+				}
+				th = (dojo.isIE) ? tr.insertCell() : document.createElement("th");
+				th.appendChild(document.createTextNode("Social Security"));
+				if(!dojo.isIE){
+					tr.appendChild(th);
+					
+					table.appendChild(tr);
+				}
+				
+				for(var i = 1; i <= NUM_ROWS; i++){
+					tr = (dojo.isIE) ? table.insertRow() : document.createElement("tr");
+					tr.className = "data-item";
+					
+					var elem = (dojo.isIE) ? tr.insertCell() : document.createElement("td");
+					elem.className = "last-name";
+					var lastName = "Doe" + i;
+					elem.appendChild(document.createTextNode(lastName));
+					if(!dojo.isIE){
+						tr.appendChild(elem);
+					}
+					
+					elem = (dojo.isIE) ? tr.insertCell() : document.createElement("td");
+					elem.className = "first-name";
+					var firstName = "John" + i;
+					elem.appendChild(document.createTextNode(firstName));
+					if(!dojo.isIE){
+						tr.appendChild(elem);
+					}
+					
+					elem = elem = (dojo.isIE) ? tr.insertCell() : document.createElement("td");
+					elem.className = "social-security";
+					var ss = 513121500 + i;
+					ss = new String(ss);
+					ss = ss.slice(0, 3) + "-" + ss.slice(3, 5) + "-" + ss.slice(5);
+					elem.appendChild(document.createTextNode(ss));
+					if(!dojo.isIE){
+						tr.appendChild(elem);
+					
+						table.appendChild(tr);
+					}
+				}
+				
+				document.body.appendChild(table);
+				
+				// reset button state
+				dojo.byId("encrypt").disabled = false;
+				dojo.byId("decrypt").disabled = true;
+			}
+			
+			function readTable(){
+				var data = [];
+				var rows = dojo.query(".data-item");
+				dojo.forEach(rows, function(row){
+					var td = row.getElementsByTagName("td");
+					
+					var lastName = td[0].childNodes[0].nodeValue;
+					var firstName = td[1].childNodes[0].nodeValue;
+					var ssNumber = td[2].childNodes[0].nodeValue;
+
+					data.push({lastName: lastName, firstName: firstName, ssNumber: ssNumber,
+								toString: function(){
+									return "{lastName: " + lastName 
+												+ ", firstName: " + firstName
+												+ ", ssNumber: " + ssNumber
+												+ "}";
+								}});
+				});
+				
+				return data;
+			}
+			
+			function setData(data){
+				var rows = document.getElementsByTagName("tr");
+				for(var i = 1; i < rows.length; i++){
+					var customer = data[i - 1];
+					var td = rows[i].getElementsByTagName("td");
+					td[2].childNodes[0].nodeValue = customer.social_security;
+				}
+			}
+			
+			function encrypt(){
+				// disable our buttons
+				dojo.byId("encrypt").disabled = true;
+				dojo.byId("decrypt").disabled = true;
+				
+				var data = readTable();
+				
+				var password = document.getElementById("password").value;
+				
+				// delete any old data
+				dojox.sql("DELETE FROM CUSTOMERS");
+				
+				// insert new data
+				insertCustomers(data, 0, password);
+			}
+			
+			function insertCustomers(data, i, password){
+				var nextIndex = i + 1;
+				
+				if(i >= data.length){
+					var savedRows = dojox.sql("SELECT * FROM CUSTOMERS");
+					setData(savedRows);
+					return;
+				}
+				dojox.sql("INSERT INTO CUSTOMERS VALUES (?, ?, ENCRYPT(?))",
+							data[i].lastName, data[i].firstName,
+							data[i].ssNumber,
+							password,
+							function(results, error, errorMsg){
+								// enable our buttons
+								dojo.byId("encrypt").disabled = true;
+								dojo.byId("decrypt").disabled = false;
+								
+								if(error == true){
+									alert(errorMsg);
+									return;
+								}
+								
+								insertCustomers(data, nextIndex, password);
+							}
+						);
+			}
+			
+			function decrypt(){
+				// disable our buttons
+				dojo.byId("encrypt").disabled = true;
+				dojo.byId("decrypt").disabled = true;
+				
+				var password = document.getElementById("password").value;
+				
+				dojox.sql("SELECT last_name, first_name, DECRYPT(social_security) FROM CUSTOMERS",
+							password,
+							function(results, error, errorMsg){
+								// enable our buttons
+								dojo.byId("encrypt").disabled = false;
+								dojo.byId("decrypt").disabled = true;
+								
+								if(error == true){
+									alert(errorMsg);
+									return;
+								}
+								
+								setData(results);
+							}
+						);
+			}
+		</script>
+	</head>
+	
+	<body>
+		<h1>Dojo SQL Cryptography</h1>
+		
+		<h2>Instructions</h2>
+		
+		<p>This demo shows Dojo Offline's SQL encryption technologies. In the table below, we have a
+			sample SQL table that has three columns of data: a last name, a first name, and
+			a social security number. We don't want to store the social security numbers
+			in the clear, just in case they are downloaded for offline use to a laptop and the
+			laptop is stolen.</p>
+		
+		<p>To use this demo, enter a password and press the ENCRYPT button to see the Social Security column encrypt. Enter
+			the same password and press DECRYPT to see it decrypt. If you enter an incorrect password and
+			press DECRYPT, the Social Security column will remain encrypted and only show gibberish.</p>
+			
+		<p>Under the covers we use 256-bit AES encryption and your password to derive the crypto key; we use
+			a facility in Google Gears to do the cryptography in such a way that the browser does not lock up
+			during processing. Dojo Offline ties this cryptography into Dojo SQL, providing convenient ENCRYPT()
+			and DECRYPT() SQL keywords you can use to easily have this functionality in your
+			own offline applications. To learn how you can use this feature 
+			<a href="http://docs.google.com/View?docid=dhkhksk4_8gdp9gr#crypto" target="_blank">see here</a>.</p>
+		
+		<div id="cryptoContainer">
+			<label for="password">
+				Password:
+			</label>
+		
+			<input type="input" name="password" id="password" value="sample_password">
+		
+			<button id="encrypt" onclick="window.setTimeout(encrypt, 1)">Encrypt</button>
+		
+			<button id="decrypt" onclick="window.setTimeout(decrypt, 1)" disabled="true">Decrypt</button>
+		</div>
+		
+		<div id="numRowsContainer">
+			<label for="numRows">
+				Number of Customer Rows in Table:
+			</label>
+		
+			<input id="numRows" type="input" value="30">
+			
+			<button onclick="createTable()">Update</button>
+		</div>
+	</body>
+</html>
\ No newline at end of file
diff --git a/dojox/storage.js b/dojox/storage.js
index 4ef6a01..1c2d149 100644
--- a/dojox/storage.js
+++ b/dojox/storage.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.storage"]){
-dojo._hasResource["dojox.storage"]=true;
 dojo.provide("dojox.storage");
 dojo.require("dojox.storage._common");
-}
diff --git a/dojox/string/BidiComplex.js b/dojox/string/BidiComplex.js
index 627e2cf..ef3f52c 100644
--- a/dojox/string/BidiComplex.js
+++ b/dojox/string/BidiComplex.js
@@ -1,246 +1,313 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.string.BidiComplex"]){
-dojo._hasResource["dojox.string.BidiComplex"]=true;
 dojo.provide("dojox.string.BidiComplex");
 dojo.experimental("dojox.string.BidiComplex");
-(function(){
-var _1=[];
-dojox.string.BidiComplex.attachInput=function(_2,_3){
-_2.alt=_3;
-dojo.connect(_2,"onkeydown",this,"_ceKeyDown");
-dojo.connect(_2,"onkeyup",this,"_ceKeyUp");
-dojo.connect(_2,"oncut",this,"_ceCutText");
-dojo.connect(_2,"oncopy",this,"_ceCopyText");
-_2.value=dojox.string.BidiComplex.createDisplayString(_2.value,_2.alt);
-};
-dojox.string.BidiComplex.createDisplayString=function(_4,_5){
-_4=dojox.string.BidiComplex.stripSpecialCharacters(_4);
-var _6=dojox.string.BidiComplex._parse(_4,_5);
-var _7="‪"+_4;
-var _8=1;
-dojo.forEach(_6,function(n){
-if(n!=null){
-var _9=_7.substring(0,n+_8);
-var _a=_7.substring(n+_8,_7.length);
-_7=_9+"‎"+_a;
-_8++;
-}
-});
-return _7;
-};
-dojox.string.BidiComplex.stripSpecialCharacters=function(_b){
-return _b.replace(/[\u200E\u200F\u202A-\u202E]/g,"");
-};
-dojox.string.BidiComplex._ceKeyDown=function(_c){
-var _d=dojo.isIE?_c.srcElement:_c.target;
-_1=_d.value;
-};
-dojox.string.BidiComplex._ceKeyUp=function(_e){
-var _f="‎";
-var _10=dojo.isIE?_e.srcElement:_e.target;
-var _11=_10.value;
-var _12=_e.keyCode;
-if((_12==dojo.keys.HOME)||(_12==dojo.keys.END)||(_12==dojo.keys.SHIFT)){
-return;
-}
-var _13,_14;
-var _15=dojox.string.BidiComplex._getCaretPos(_e,_10);
-if(_15){
-_13=_15[0];
-_14=_15[1];
-}
-if(dojo.isIE){
-var _16=_13,_17=_14;
-if(_12==dojo.keys.LEFT_ARROW){
-if((_11.charAt(_14-1)==_f)&&(_13==_14)){
-dojox.string.BidiComplex._setSelectedRange(_10,_13-1,_14-1);
-}
-return;
-}
-if(_12==dojo.keys.RIGHT_ARROW){
-if(_11.charAt(_14-1)==_f){
-_17=_14+1;
-if(_13==_14){
-_16=_13+1;
-}
-}
-dojox.string.BidiComplex._setSelectedRange(_10,_16,_17);
-return;
-}
-}else{
-if(_12==dojo.keys.LEFT_ARROW){
-if(_11.charAt(_14-1)==_f){
-dojox.string.BidiComplex._setSelectedRange(_10,_13-1,_14-1);
-}
-return;
-}
-if(_12==dojo.keys.RIGHT_ARROW){
-if(_11.charAt(_14-1)==_f){
-dojox.string.BidiComplex._setSelectedRange(_10,_13+1,_14+1);
-}
-return;
-}
-}
-var _18=dojox.string.BidiComplex.createDisplayString(_11,_10.alt);
-if(_11!=_18){
-window.status=_11+" c="+_14;
-_10.value=_18;
-if((_12==dojo.keys.DELETE)&&(_18.charAt(_14)==_f)){
-_10.value=_18.substring(0,_14)+_18.substring(_14+2,_18.length);
-}
-if(_12==dojo.keys.DELETE){
-dojox.string.BidiComplex._setSelectedRange(_10,_13,_14);
-}else{
-if(_12==dojo.keys.BACKSPACE){
-if((_1.length>=_14)&&(_1.charAt(_14-1)==_f)){
-dojox.string.BidiComplex._setSelectedRange(_10,_13-1,_14-1);
-}else{
-dojox.string.BidiComplex._setSelectedRange(_10,_13,_14);
-}
-}else{
-if(_10.value.charAt(_14)!=_f){
-dojox.string.BidiComplex._setSelectedRange(_10,_13+1,_14+1);
-}
-}
-}
-}
-};
-dojox.string.BidiComplex._processCopy=function(_19,_1a,_1b){
-if(_1a==null){
-if(dojo.isIE){
-var _1c=document.selection.createRange();
-_1a=_1c.text;
-}else{
-_1a=_19.value.substring(_19.selectionStart,_19.selectionEnd);
-}
-}
-var _1d=dojox.string.BidiComplex.stripSpecialCharacters(_1a);
-if(dojo.isIE){
-window.clipboardData.setData("Text",_1d);
-}
-return true;
-};
-dojox.string.BidiComplex._ceCopyText=function(_1e){
-if(dojo.isIE){
-_1e.returnValue=false;
-}
-return dojox.string.BidiComplex._processCopy(_1e,null,false);
-};
-dojox.string.BidiComplex._ceCutText=function(_1f){
-var ret=dojox.string.BidiComplex._processCopy(_1f,null,false);
-if(!ret){
-return false;
-}
-if(dojo.isIE){
-document.selection.clear();
-}else{
-var _20=_1f.selectionStart;
-_1f.value=_1f.value.substring(0,_20)+_1f.value.substring(_1f.selectionEnd);
-_1f.setSelectionRange(_20,_20);
-}
-return true;
-};
-dojox.string.BidiComplex._getCaretPos=function(_21,_22){
-if(dojo.isIE){
-var _23=0,_24=document.selection.createRange().duplicate(),_25=_24.duplicate(),_26=_24.text.length;
-if(_22.type=="textarea"){
-_25.moveToElementText(_22);
-}else{
-_25.expand("textedit");
-}
-while(_24.compareEndPoints("StartToStart",_25)>0){
-_24.moveStart("character",-1);
-++_23;
-}
-return [_23,_23+_26];
-}
-return [_21.target.selectionStart,_21.target.selectionEnd];
-};
-dojox.string.BidiComplex._setSelectedRange=function(_27,_28,_29){
-if(dojo.isIE){
-var _2a=_27.createTextRange();
-if(_2a){
-if(_27.type=="textarea"){
-_2a.moveToElementText(_27);
-}else{
-_2a.expand("textedit");
-}
-_2a.collapse();
-_2a.moveEnd("character",_29);
-_2a.moveStart("character",_28);
-_2a.select();
-}
-}else{
-_27.selectionStart=_28;
-_27.selectionEnd=_29;
-}
-};
-var _2b=function(c){
-return (c>="0"&&c<="9")||(c>"ÿ");
-};
-var _2c=function(c){
-return (c>="A"&&c<="Z")||(c>="a"&&c<="z");
-};
-var _2d=function(_2e,i,_2f){
-while(i>0){
-if(i==_2f){
-return false;
-}
-i--;
-if(_2b(_2e.charAt(i))){
-return true;
-}
-if(_2c(_2e.charAt(i))){
-return false;
-}
-}
-return false;
-};
-dojox.string.BidiComplex._parse=function(str,_30){
-var _31=-1,_32=[];
-var _33={FILE_PATH:"/\\:.",URL:"/:.?=&#",XPATH:"/\\:.<>=[]",EMAIL:"<>@.,;"}[_30];
-switch(_30){
-case "FILE_PATH":
-case "URL":
-case "XPATH":
-dojo.forEach(str,function(ch,i){
-if(_33.indexOf(ch)>=0&&_2d(str,i,_31)){
-_31=i;
-_32.push(i);
-}
-});
-break;
-case "EMAIL":
-var _34=false;
-dojo.forEach(str,function(ch,i){
-if(ch=="\""){
-if(_2d(str,i,_31)){
-_31=i;
-_32.push(i);
-}
-i++;
-var i1=str.indexOf("\"",i);
-if(i1>=i){
-i=i1;
-}
-if(_2d(str,i,_31)){
-_31=i;
-_32.push(i);
-}
-}
-if(_33.indexOf(ch)>=0&&_2d(str,i,_31)){
-_31=i;
-_32.push(i);
-}
-});
-}
-return _32;
-};
+
+// summary:
+//		BiDiComplex module handles complex expression issues known when using BiDi characters
+//		in File Paths, URLs, E-mail Address, XPATH, etc. 
+//		this module adds property listeners to the text fields to correct the text representation
+//		in both static text and dynamic text during user input. 
+
+(function(){  
+
+	var _str0 = []; //FIXME: shared reference here among various functions means the functions can't be reused
+
+	dojox.string.BidiComplex.attachInput = function(/*DOMNode*/field, /*String*/pattern){
+		// summary:
+		//		Attach key listeners to the INPUT field to accomodate dynamic complex BiDi expressions 
+		// field: INPUT DOM node
+		// pattern: Complex Expression Pattern type. One of "FILE_PATH", "URL", "EMAIL", "XPATH"
+
+		field.alt = pattern;
+
+		dojo.connect(field, "onkeydown",  this, "_ceKeyDown");
+		dojo.connect(field, "onkeyup", this, "_ceKeyUp");
+
+		dojo.connect(field, "oncut", this, "_ceCutText");
+		dojo.connect(field, "oncopy", this, "_ceCopyText");
+
+		field.value = dojox.string.BidiComplex.createDisplayString(field.value, field.alt);    
+	};
+		
+	dojox.string.BidiComplex.createDisplayString = function(/*String*/str, /*String*/pattern){
+		// summary:
+		//		Create the display string by adding the Unicode direction Markers 
+		// pattern: Complex Expression Pattern type. One of "FILE_PATH", "URL", "EMAIL", "XPATH"
+
+		str = dojox.string.BidiComplex.stripSpecialCharacters(str);
+		var segmentsPointers = dojox.string.BidiComplex._parse(str, pattern); 
+		
+		var buf = '\u202A'/*LRE*/ + str;
+		var shift = 1;                                           
+		dojo.forEach(segmentsPointers, function(n){
+			if(n != null){
+				var preStr = buf.substring(0, n + shift);
+				var postStr = buf.substring(n + shift, buf.length);
+				buf = preStr + '\u200E'/*LRM*/ + postStr;
+				shift++;
+			}
+		});
+		return buf;        
+	};
+
+	dojox.string.BidiComplex.stripSpecialCharacters = function(str){
+		// summary:
+		//		removes all Unicode directional markers from the string
+
+		return str.replace(/[\u200E\u200F\u202A-\u202E]/g, ""); // String
+	};
+
+	dojox.string.BidiComplex._ceKeyDown = function(event){
+		var elem = dojo.isIE ? event.srcElement : event.target;        
+		_str0 = elem.value;
+	};
+				
+	dojox.string.BidiComplex._ceKeyUp = function(event){
+		var LRM = '\u200E';
+		var elem = dojo.isIE ? event.srcElement : event.target;
+
+		var str1 = elem.value;
+		var ieKey = event.keyCode;
+		
+		if((ieKey == dojo.keys.HOME)
+			|| (ieKey == dojo.keys.END)
+			|| (ieKey == dojo.keys.SHIFT)){
+			return;
+		}
+
+		var cursorStart, cursorEnd;
+		var selection = dojox.string.BidiComplex._getCaretPos(event, elem);
+		if(selection){
+			cursorStart = selection[0];
+			cursorEnd = selection[1];
+		}
+
+	//Jump over a cursor processing
+		if(dojo.isIE){
+			var cursorStart1 = cursorStart, cursorEnd1 = cursorEnd;
+
+			if(ieKey == dojo.keys.LEFT_ARROW){
+				if((str1.charAt(cursorEnd-1) == LRM)
+						&& (cursorStart == cursorEnd)){
+					dojox.string.BidiComplex._setSelectedRange(elem,cursorStart - 1, cursorEnd - 1);
+				}
+				return;
+			}
+
+			if(ieKey == dojo.keys.RIGHT_ARROW){             
+				if(str1.charAt(cursorEnd-1) == LRM){
+					cursorEnd1 = cursorEnd + 1;
+					if(cursorStart == cursorEnd){
+						cursorStart1 = cursorStart + 1;
+					}
+				}
+
+				dojox.string.BidiComplex._setSelectedRange(elem, cursorStart1, cursorEnd1);                        
+				return;
+			}                   
+		}else{ //Firefox
+			if(ieKey == dojo.keys.LEFT_ARROW){
+				if(str1.charAt(cursorEnd-1) == LRM){
+					dojox.string.BidiComplex._setSelectedRange(elem, cursorStart - 1, cursorEnd - 1);
+				}
+				return;
+			}
+			if(ieKey == dojo.keys.RIGHT_ARROW){
+				if(str1.charAt(cursorEnd-1) == LRM){
+					dojox.string.BidiComplex._setSelectedRange(elem, cursorStart + 1, cursorEnd + 1);
+				}
+				return;
+			}
+		}
+		
+		var str2 = dojox.string.BidiComplex.createDisplayString(str1, elem.alt);
+
+		if(str1 != str2)
+		{
+			window.status = str1 + " c=" + cursorEnd;
+			elem.value = str2;
+
+			if((ieKey == dojo.keys.DELETE) && (str2.charAt(cursorEnd)==LRM)){
+				elem.value = str2.substring(0, cursorEnd) + str2.substring(cursorEnd+2, str2.length);
+			}
+
+			if(ieKey == dojo.keys.DELETE){
+				dojox.string.BidiComplex._setSelectedRange(elem,cursorStart,cursorEnd); 
+			}else if(ieKey == dojo.keys.BACKSPACE){
+				if((_str0.length >= cursorEnd) && (_str0.charAt(cursorEnd-1)==LRM)){
+					dojox.string.BidiComplex._setSelectedRange(elem, cursorStart - 1, cursorEnd - 1);
+				}else{
+					dojox.string.BidiComplex._setSelectedRange(elem, cursorStart, cursorEnd);
+				}
+			}else if(elem.value.charAt(cursorEnd) != LRM){
+				dojox.string.BidiComplex._setSelectedRange(elem, cursorStart + 1, cursorEnd + 1);
+			}
+		}
+	};
+
+	dojox.string.BidiComplex._processCopy = function(elem, text, isReverse){
+		// summary:
+		//		This function strips the unicode directional controls when the text copied to the Clipboard
+
+		if(text == null){
+			if(dojo.isIE){
+				var range = document.selection.createRange();
+				text = range.text;
+			}else{
+				text = elem.value.substring(elem.selectionStart, elem.selectionEnd);
+			}
+		}
+
+		var textToClipboard = dojox.string.BidiComplex.stripSpecialCharacters(text);
+	
+		if(dojo.isIE){
+			window.clipboardData.setData("Text", textToClipboard);
+		}
+		return true;
+	};
+
+	dojox.string.BidiComplex._ceCopyText = function(elem){
+		if(dojo.isIE){
+			elem.returnValue = false;
+		}
+		return dojox.string.BidiComplex._processCopy(elem, null, false);
+	};
+
+	dojox.string.BidiComplex._ceCutText = function(elem){
+
+		var ret = dojox.string.BidiComplex._processCopy(elem, null, false);
+		if(!ret){ 
+			return false;
+		}
+
+		if(dojo.isIE){
+	//		curPos = elem.selectionStart; 
+			document.selection.clear(); 
+		}else{
+			var curPos = elem.selectionStart;
+			elem.value = elem.value.substring(0, curPos) + elem.value.substring(elem.selectionEnd);
+			elem.setSelectionRange(curPos, curPos);
+		}
+
+		return true;
+	};
+
+	// is there dijit code to do this?
+	dojox.string.BidiComplex._getCaretPos = function(event, elem){
+		if(dojo.isIE){
+			var position = 0,
+			range = document.selection.createRange().duplicate(),
+			range2 = range.duplicate(),
+			rangeLength = range.text.length;
+
+			if(elem.type == "textarea"){
+				range2.moveToElementText(elem);
+			}else{
+				range2.expand('textedit');
+			}
+			while(range.compareEndPoints('StartToStart', range2) > 0){
+				range.moveStart('character', -1);
+				++position;
+			}
+
+			return [position, position + rangeLength];
+		}
+
+		return [event.target.selectionStart, event.target.selectionEnd];
+	};
+
+	// is there dijit code to do this?
+	dojox.string.BidiComplex._setSelectedRange = function(elem,selectionStart,selectionEnd){
+		if(dojo.isIE){
+			var range = elem.createTextRange();
+			if(range){
+				if(elem.type == "textarea"){
+					range.moveToElementText(elem);
+				}else{
+					range.expand('textedit');
+				}
+
+				range.collapse();            
+				range.moveEnd('character', selectionEnd);
+				range.moveStart('character', selectionStart);
+				range.select();
+			}
+		}else{        
+			elem.selectionStart = selectionStart;
+			elem.selectionEnd = selectionEnd;
+		}
+	};
+
+	var _isBidiChar = function(c){    
+		return (c >= '\u0030' && c <= '\u0039') || (c > '\u00ff');
+	};
+
+	var _isLatinChar = function(c){
+		return (c >= '\u0041' && c <= '\u005A') || (c >= '\u0061' && c <= '\u007A');
+	};
+
+	var _isCharBeforeBiDiChar = function(buffer, i, previous){
+		while(i > 0){    
+			if(i == previous){
+				return false;
+			}
+			i--;                        
+			if(_isBidiChar(buffer.charAt(i))){
+				return true;
+			}
+			if(_isLatinChar(buffer.charAt(i))){
+				return false;
+			}
+		}
+		return false;       
+	};
+
+
+	dojox.string.BidiComplex._parse = function(/*String*/str, /*String*/pattern){    
+		var previous = -1, segmentsPointers = [];
+		var delimiters = {
+			FILE_PATH: "/\\:.",
+			URL: "/:.?=&#",
+			XPATH: "/\\:.<>=[]",
+			EMAIL: "<>@.,;"
+		}[pattern];
+
+		switch(pattern){
+			case "FILE_PATH":
+			case "URL":
+			case "XPATH":
+				dojo.forEach(str, function(ch, i){
+					if(delimiters.indexOf(ch) >= 0 && _isCharBeforeBiDiChar(str, i, previous)){
+						previous = i;
+						segmentsPointers.push(i);  
+					}
+				});
+				break;
+			case "EMAIL":
+				var inQuotes = false; // FIXME: unused?
+	
+				dojo.forEach(str, function(ch, i){     
+					if(ch== '\"'){
+						if(_isCharBeforeBiDiChar(str, i, previous)){
+							previous = i;    
+							segmentsPointers.push(i);  
+						}                    
+						i++;
+						var i1 = str.indexOf('\"', i);
+						if(i1 >= i){
+							i = i1;
+						}
+						if(_isCharBeforeBiDiChar(str, i, previous)){
+							previous = i;    
+							segmentsPointers.push(i);  
+						}                                   
+					}
+	
+					if(delimiters.indexOf(ch) >= 0 && _isCharBeforeBiDiChar(str, i, previous)){
+								previous = i;    
+								segmentsPointers.push(i); 
+					}                                            
+				});
+		}
+		return segmentsPointers;
+	};  
 })();
-}
diff --git a/dojox/string/Builder.js b/dojox/string/Builder.js
index 15f69ca..e18bbc0 100644
--- a/dojox/string/Builder.js
+++ b/dojox/string/Builder.js
@@ -1,91 +1,130 @@
-/*
-	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
-*/
+dojo.provide("dojox.string.Builder");
 
+dojox.string.Builder = function(/*String?*/str){
+	//	summary:
+	//		A fast buffer for creating large strings.
+	//
+	//	length: Number
+	//		The current length of the internal string.
 
-if(!dojo._hasResource["dojox.string.Builder"]){
-dojo._hasResource["dojox.string.Builder"]=true;
-dojo.provide("dojox.string.Builder");
-dojox.string.Builder=function(_1){
-var b="";
-this.length=0;
-this.append=function(s){
-if(arguments.length>1){
-var _2="",l=arguments.length;
-switch(l){
-case 9:
-_2=""+arguments[8]+_2;
-case 8:
-_2=""+arguments[7]+_2;
-case 7:
-_2=""+arguments[6]+_2;
-case 6:
-_2=""+arguments[5]+_2;
-case 5:
-_2=""+arguments[4]+_2;
-case 4:
-_2=""+arguments[3]+_2;
-case 3:
-_2=""+arguments[2]+_2;
-case 2:
-b+=""+arguments[0]+arguments[1]+_2;
-break;
-default:
-var i=0;
-while(i<arguments.length){
-_2+=arguments[i++];
-}
-b+=_2;
-}
-}else{
-b+=s;
-}
-this.length=b.length;
-return this;
-};
-this.concat=function(s){
-return this.append.apply(this,arguments);
-};
-this.appendArray=function(_3){
-return this.append.apply(this,_3);
-};
-this.clear=function(){
-b="";
-this.length=0;
-return this;
-};
-this.replace=function(_4,_5){
-b=b.replace(_4,_5);
-this.length=b.length;
-return this;
-};
-this.remove=function(_6,_7){
-if(_7===undefined){
-_7=b.length;
-}
-if(_7==0){
-return this;
-}
-b=b.substr(0,_6)+b.substr(_6+_7);
-this.length=b.length;
-return this;
-};
-this.insert=function(_8,_9){
-if(_8==0){
-b=_9+b;
-}else{
-b=b.slice(0,_8)+_9+b.slice(_8);
-}
-this.length=b.length;
-return this;
-};
-this.toString=function(){
-return b;
-};
-if(_1){
-this.append(_1);
-}
+	//	N.B. the public nature of the internal buffer is no longer
+	//	needed because the IE-specific fork is no longer needed--TRT.
+	var b = "";
+	this.length = 0;
+	
+	this.append = function(/* String... */s){ 
+		// summary: Append all arguments to the end of the buffer 
+		if(arguments.length>1){
+			/*  
+				This is a loop unroll was designed specifically for Firefox;
+				it would seem that static index access on an Arguments
+				object is a LOT faster than doing dynamic index access.
+				Therefore, we create a buffer string and take advantage
+				of JS's switch fallthrough.  The peformance of this method
+				comes very close to straight up string concatenation (+=).
+
+				If the arguments object length is greater than 9, we fall
+				back to standard dynamic access.
+
+				This optimization seems to have no real effect on either
+				Safari or Opera, so we just use it for all.
+
+				It turns out also that this loop unroll can increase performance
+				significantly with Internet Explorer, particularly when 
+				as many arguments are provided as possible.
+
+				Loop unroll per suggestion from Kris Zyp, implemented by 
+				Tom Trenka.
+
+				Note: added empty string to force a string cast if needed.
+			 */
+			var tmp="", l=arguments.length;
+			switch(l){
+				case 9: tmp=""+arguments[8]+tmp;
+				case 8: tmp=""+arguments[7]+tmp;
+				case 7: tmp=""+arguments[6]+tmp;
+				case 6: tmp=""+arguments[5]+tmp;
+				case 5: tmp=""+arguments[4]+tmp;
+				case 4: tmp=""+arguments[3]+tmp;
+				case 3: tmp=""+arguments[2]+tmp;
+				case 2: {
+					b+=""+arguments[0]+arguments[1]+tmp;
+					break;
+				}
+				default: {
+					var i=0;
+					while(i<arguments.length){
+						tmp += arguments[i++];
+					}
+					b += tmp;
+				}
+			}
+		} else {
+			b += s;
+		}
+		this.length = b.length;
+		return this;	//	dojox.string.Builder
+	};
+	
+	this.concat = function(/*String...*/s){
+		//	summary:
+		//		Alias for append.
+		return this.append.apply(this, arguments);	//	dojox.string.Builder
+	};
+	
+	this.appendArray = function(/*Array*/strings) {
+		//	summary:
+		//		Append an array of items to the internal buffer.
+
+		//	Changed from String.prototype.concat.apply because of IE.
+		return this.append.apply(this, strings);	//	dojox.string.Builder
+	};
+	
+	this.clear = function(){
+		//	summary: 
+		//		Remove all characters from the buffer.
+		b = "";
+		this.length = 0;
+		return this;	//	dojox.string.Builder
+	};
+	
+	this.replace = function(/* String */oldStr, /* String */ newStr){
+		// 	summary: 
+		//		Replace instances of one string with another in the buffer.
+		b = b.replace(oldStr,newStr);
+		this.length = b.length;
+		return this;	//	dojox.string.Builder
+	};
+	
+	this.remove = function(/* Number */start, /* Number? */len){
+		//	summary:
+		//		Remove len characters starting at index start.  If len
+		//		is not provided, the end of the string is assumed.
+		if(len===undefined){ len = b.length; }
+		if(len == 0){ return this; }
+		b = b.substr(0, start) + b.substr(start+len);
+		this.length = b.length;
+		return this;	//	dojox.string.Builder
+	};
+	
+	this.insert = function(/* Number */index, /* String */str){
+		//	summary: 
+		//		Insert string str starting at index.
+		if(index == 0){
+			b = str + b;
+		}else{
+			b = b.slice(0, index) + str + b.slice(index);
+		}
+		this.length = b.length;
+		return this;	//	dojox.string.Builder
+	};
+	
+	this.toString = function(){
+		//	summary:
+		//		Return the string representation of the internal buffer.
+		return b;	//	String
+	};
+
+	//	initialize the buffer.
+	if(str){ this.append(str); }
 };
-}
diff --git a/dojox/string/sprintf.js b/dojox/string/sprintf.js
index 2e3d5d0..4060061 100644
--- a/dojox/string/sprintf.js
+++ b/dojox/string/sprintf.js
@@ -1,280 +1,402 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.string.sprintf"]){
-dojo._hasResource["dojox.string.sprintf"]=true;
 dojo.provide("dojox.string.sprintf");
+
 dojo.require("dojox.string.tokenize");
-dojox.string.sprintf=function(_1,_2){
-for(var _3=[],i=1;i<arguments.length;i++){
-_3.push(arguments[i]);
-}
-var _4=new dojox.string.sprintf.Formatter(_1);
-return _4.format.apply(_4,_3);
-};
-dojox.string.sprintf.Formatter=function(_5){
-var _6=[];
-this._mapped=false;
-this._format=_5;
-this._tokens=dojox.string.tokenize(_5,this._re,this._parseDelim,this);
-};
-dojo.extend(dojox.string.sprintf.Formatter,{_re:/\%(?:\(([\w_]+)\)|([1-9]\d*)\$)?([0 +\-\#]*)(\*|\d+)?(\.)?(\*|\d+)?[hlL]?([\%scdeEfFgGiouxX])/g,_parseDelim:function(_7,_8,_9,_a,_b,_c,_d){
-if(_7){
-this._mapped=true;
-}
-return {mapping:_7,intmapping:_8,flags:_9,_minWidth:_a,period:_b,_precision:_c,specifier:_d};
-},_specifiers:{b:{base:2,isInt:true},o:{base:8,isInt:true},x:{base:16,isInt:true},X:{extend:["x"],toUpper:true},d:{base:10,isInt:true},i:{extend:["d"]},u:{extend:["d"],isUnsigned:true},c:{setArg:function(_e){
-if(!isNaN(_e.arg)){
-var _f=parseInt(_e.arg);
-if(_f<0||_f>127){
-throw new Error("invalid character code passed to %c in sprintf");
-}
-_e.arg=isNaN(_f)?""+_f:String.fromCharCode(_f);
-}
-}},s:{setMaxWidth:function(_10){
-_10.maxWidth=(_10.period==".")?_10.precision:-1;
-}},e:{isDouble:true,doubleNotation:"e"},E:{extend:["e"],toUpper:true},f:{isDouble:true,doubleNotation:"f"},F:{extend:["f"]},g:{isDouble:true,doubleNotation:"g"},G:{extend:["g"],toUpper:true}},format:function(_11){
-if(this._mapped&&typeof _11!="object"){
-throw new Error("format requires a mapping");
-}
-var str="";
-var _12=0;
-for(var i=0,_13;i<this._tokens.length;i++){
-_13=this._tokens[i];
-if(typeof _13=="string"){
-str+=_13;
-}else{
-if(this._mapped){
-if(typeof _11[_13.mapping]=="undefined"){
-throw new Error("missing key "+_13.mapping);
-}
-_13.arg=_11[_13.mapping];
-}else{
-if(_13.intmapping){
-var _12=parseInt(_13.intmapping)-1;
-}
-if(_12>=arguments.length){
-throw new Error("got "+arguments.length+" printf arguments, insufficient for '"+this._format+"'");
-}
-_13.arg=arguments[_12++];
-}
-if(!_13.compiled){
-_13.compiled=true;
-_13.sign="";
-_13.zeroPad=false;
-_13.rightJustify=false;
-_13.alternative=false;
-var _14={};
-for(var fi=_13.flags.length;fi--;){
-var _15=_13.flags.charAt(fi);
-_14[_15]=true;
-switch(_15){
-case " ":
-_13.sign=" ";
-break;
-case "+":
-_13.sign="+";
-break;
-case "0":
-_13.zeroPad=(_14["-"])?false:true;
-break;
-case "-":
-_13.rightJustify=true;
-_13.zeroPad=false;
-break;
-case "#":
-_13.alternative=true;
-break;
-default:
-throw Error("bad formatting flag '"+_13.flags.charAt(fi)+"'");
-}
-}
-_13.minWidth=(_13._minWidth)?parseInt(_13._minWidth):0;
-_13.maxWidth=-1;
-_13.toUpper=false;
-_13.isUnsigned=false;
-_13.isInt=false;
-_13.isDouble=false;
-_13.precision=1;
-if(_13.period=="."){
-if(_13._precision){
-_13.precision=parseInt(_13._precision);
-}else{
-_13.precision=0;
-}
-}
-var _16=this._specifiers[_13.specifier];
-if(typeof _16=="undefined"){
-throw new Error("unexpected specifier '"+_13.specifier+"'");
-}
-if(_16.extend){
-dojo.mixin(_16,this._specifiers[_16.extend]);
-delete _16.extend;
-}
-dojo.mixin(_13,_16);
-}
-if(typeof _13.setArg=="function"){
-_13.setArg(_13);
-}
-if(typeof _13.setMaxWidth=="function"){
-_13.setMaxWidth(_13);
-}
-if(_13._minWidth=="*"){
-if(this._mapped){
-throw new Error("* width not supported in mapped formats");
-}
-_13.minWidth=parseInt(arguments[_12++]);
-if(isNaN(_13.minWidth)){
-throw new Error("the argument for * width at position "+_12+" is not a number in "+this._format);
-}
-if(_13.minWidth<0){
-_13.rightJustify=true;
-_13.minWidth=-_13.minWidth;
-}
-}
-if(_13._precision=="*"&&_13.period=="."){
-if(this._mapped){
-throw new Error("* precision not supported in mapped formats");
-}
-_13.precision=parseInt(arguments[_12++]);
-if(isNaN(_13.precision)){
-throw Error("the argument for * precision at position "+_12+" is not a number in "+this._format);
-}
-if(_13.precision<0){
-_13.precision=1;
-_13.period="";
-}
-}
-if(_13.isInt){
-if(_13.period=="."){
-_13.zeroPad=false;
-}
-this.formatInt(_13);
-}else{
-if(_13.isDouble){
-if(_13.period!="."){
-_13.precision=6;
-}
-this.formatDouble(_13);
-}
-}
-this.fitField(_13);
-str+=""+_13.arg;
-}
-}
-return str;
-},_zeros10:"0000000000",_spaces10:"          ",formatInt:function(_17){
-var i=parseInt(_17.arg);
-if(!isFinite(i)){
-if(typeof _17.arg!="number"){
-throw new Error("format argument '"+_17.arg+"' not an integer; parseInt returned "+i);
-}
-i=0;
-}
-if(i<0&&(_17.isUnsigned||_17.base!=10)){
-i=4294967295+i+1;
-}
-if(i<0){
-_17.arg=(-i).toString(_17.base);
-this.zeroPad(_17);
-_17.arg="-"+_17.arg;
-}else{
-_17.arg=i.toString(_17.base);
-if(!i&&!_17.precision){
-_17.arg="";
-}else{
-this.zeroPad(_17);
-}
-if(_17.sign){
-_17.arg=_17.sign+_17.arg;
-}
-}
-if(_17.base==16){
-if(_17.alternative){
-_17.arg="0x"+_17.arg;
-}
-_17.arg=_17.toUpper?_17.arg.toUpperCase():_17.arg.toLowerCase();
-}
-if(_17.base==8){
-if(_17.alternative&&_17.arg.charAt(0)!="0"){
-_17.arg="0"+_17.arg;
-}
-}
-},formatDouble:function(_18){
-var f=parseFloat(_18.arg);
-if(!isFinite(f)){
-if(typeof _18.arg!="number"){
-throw new Error("format argument '"+_18.arg+"' not a float; parseFloat returned "+f);
-}
-f=0;
-}
-switch(_18.doubleNotation){
-case "e":
-_18.arg=f.toExponential(_18.precision);
-break;
-case "f":
-_18.arg=f.toFixed(_18.precision);
-break;
-case "g":
-if(Math.abs(f)<0.0001){
-_18.arg=f.toExponential(_18.precision>0?_18.precision-1:_18.precision);
-}else{
-_18.arg=f.toPrecision(_18.precision);
-}
-if(!_18.alternative){
-_18.arg=_18.arg.replace(/(\..*[^0])0*/,"$1");
-_18.arg=_18.arg.replace(/\.0*e/,"e").replace(/\.0$/,"");
-}
-break;
-default:
-throw new Error("unexpected double notation '"+_18.doubleNotation+"'");
-}
-_18.arg=_18.arg.replace(/e\+(\d)$/,"e+0$1").replace(/e\-(\d)$/,"e-0$1");
-if(dojo.isOpera){
-_18.arg=_18.arg.replace(/^\./,"0.");
-}
-if(_18.alternative){
-_18.arg=_18.arg.replace(/^(\d+)$/,"$1.");
-_18.arg=_18.arg.replace(/^(\d+)e/,"$1.e");
-}
-if(f>=0&&_18.sign){
-_18.arg=_18.sign+_18.arg;
-}
-_18.arg=_18.toUpper?_18.arg.toUpperCase():_18.arg.toLowerCase();
-},zeroPad:function(_19,_1a){
-_1a=(arguments.length==2)?_1a:_19.precision;
-if(typeof _19.arg!="string"){
-_19.arg=""+_19.arg;
-}
-var _1b=_1a-10;
-while(_19.arg.length<_1b){
-_19.arg=(_19.rightJustify)?_19.arg+this._zeros10:this._zeros10+_19.arg;
-}
-var pad=_1a-_19.arg.length;
-_19.arg=(_19.rightJustify)?_19.arg+this._zeros10.substring(0,pad):this._zeros10.substring(0,pad)+_19.arg;
-},fitField:function(_1c){
-if(_1c.maxWidth>=0&&_1c.arg.length>_1c.maxWidth){
-return _1c.arg.substring(0,_1c.maxWidth);
-}
-if(_1c.zeroPad){
-this.zeroPad(_1c,_1c.minWidth);
-return;
-}
-this.spacePad(_1c);
-},spacePad:function(_1d,_1e){
-_1e=(arguments.length==2)?_1e:_1d.minWidth;
-if(typeof _1d.arg!="string"){
-_1d.arg=""+_1d.arg;
-}
-var _1f=_1e-10;
-while(_1d.arg.length<_1f){
-_1d.arg=(_1d.rightJustify)?_1d.arg+this._spaces10:this._spaces10+_1d.arg;
-}
-var pad=_1e-_1d.arg.length;
-_1d.arg=(_1d.rightJustify)?_1d.arg+this._spaces10.substring(0,pad):this._spaces10.substring(0,pad)+_1d.arg;
-}});
+
+dojox.string.sprintf = function(/*String*/ format, /*mixed...*/ filler){
+	for(var args = [], i = 1; i < arguments.length; i++){
+		args.push(arguments[i]);
+	}
+	var formatter = new dojox.string.sprintf.Formatter(format);
+	return formatter.format.apply(formatter, args);
 }
+
+dojox.string.sprintf.Formatter = function(/*String*/ format){
+	var tokens = [];
+	this._mapped = false;
+	this._format = format;
+	this._tokens = dojox.string.tokenize(format, this._re, this._parseDelim, this);
+}
+dojo.extend(dojox.string.sprintf.Formatter, {
+	_re: /\%(?:\(([\w_]+)\)|([1-9]\d*)\$)?([0 +\-\#]*)(\*|\d+)?(\.)?(\*|\d+)?[hlL]?([\%scdeEfFgGiouxX])/g,
+	_parseDelim: function(mapping, intmapping, flags, minWidth, period, precision, specifier){
+		if(mapping){
+			this._mapped = true;
+		}
+		return {
+			mapping: mapping,
+			intmapping: intmapping,
+			flags: flags,
+			_minWidth: minWidth, // May be dependent on parameters
+			period: period,
+			_precision: precision, // May be dependent on parameters
+			specifier: specifier
+		};
+	},
+	_specifiers: {
+		b: {
+			base: 2,
+			isInt: true
+		},
+		o: {
+			base: 8,
+			isInt: true
+		},
+		x: {
+			base: 16,
+			isInt: true
+		},
+		X: {
+			extend: ["x"],
+			toUpper: true
+		},
+		d: {
+			base: 10,
+			isInt: true
+		},
+		i: {
+			extend: ["d"]
+		},
+		u: {
+			extend: ["d"],
+			isUnsigned: true
+		},
+		c: {
+			setArg: function(token){
+				if(!isNaN(token.arg)){
+					var num = parseInt(token.arg);
+					if(num < 0 || num > 127){
+						throw new Error("invalid character code passed to %c in sprintf");
+					}
+					token.arg = isNaN(num) ? "" + num : String.fromCharCode(num);
+				}
+			}
+		},
+		s: {
+			setMaxWidth: function(token){
+				token.maxWidth = (token.period == ".") ? token.precision : -1;
+			}
+		},
+		e: {
+			isDouble: true,
+			doubleNotation: "e"
+		},
+		E: {
+			extend: ["e"],
+			toUpper: true
+		},
+		f: {
+			isDouble: true,
+			doubleNotation: "f"
+		},
+		F: {
+			extend: ["f"]
+		},
+		g: {
+			isDouble: true,
+			doubleNotation: "g"
+		},
+		G: {
+			extend: ["g"],
+			toUpper: true
+		}
+	},
+	format: function(/*mixed...*/ filler){
+		if(this._mapped && typeof filler != "object"){
+			throw new Error("format requires a mapping");
+		}
+
+		var str = "";
+		var position = 0;
+		for(var i = 0, token; i < this._tokens.length; i++){
+			token = this._tokens[i];
+			if(typeof token == "string"){
+				str += token;
+			}else{
+				if(this._mapped){
+					if(typeof filler[token.mapping] == "undefined"){
+						throw new Error("missing key " + token.mapping);
+					}
+					token.arg = filler[token.mapping];
+				}else{
+					if(token.intmapping){
+						var position = parseInt(token.intmapping) - 1;
+					}
+					if(position >= arguments.length){
+						throw new Error("got " + arguments.length + " printf arguments, insufficient for '" + this._format + "'");
+					}
+					token.arg = arguments[position++];
+				}
+
+				if(!token.compiled){
+					token.compiled = true;
+					token.sign = "";
+					token.zeroPad = false;
+					token.rightJustify = false;
+					token.alternative = false;
+
+					var flags = {};
+					for(var fi = token.flags.length; fi--;){
+						var flag = token.flags.charAt(fi);
+						flags[flag] = true;
+						switch(flag){
+							case " ":
+								token.sign = " ";
+								break;
+							case "+":
+								token.sign = "+";
+								break;
+							case "0":
+								token.zeroPad = (flags["-"]) ? false : true;
+								break;
+							case "-":
+								token.rightJustify = true;
+								token.zeroPad = false;
+								break;
+							case "\#":
+								token.alternative = true;
+								break;
+							default:
+								throw Error("bad formatting flag '" + token.flags.charAt(fi) + "'");
+						}
+					}
+
+					token.minWidth = (token._minWidth) ? parseInt(token._minWidth) : 0;
+					token.maxWidth = -1;
+					token.toUpper = false;
+					token.isUnsigned = false;
+					token.isInt = false;
+					token.isDouble = false;
+					token.precision = 1;
+					if(token.period == '.'){
+						if(token._precision){
+							token.precision = parseInt(token._precision);
+						}else{
+							token.precision = 0;
+						}
+					}
+
+					var mixins = this._specifiers[token.specifier];
+					if(typeof mixins == "undefined"){
+						throw new Error("unexpected specifier '" + token.specifier + "'");
+					}
+					if(mixins.extend){
+						dojo.mixin(mixins, this._specifiers[mixins.extend]);
+						delete mixins.extend;
+					}
+					dojo.mixin(token, mixins);
+				}
+
+				if(typeof token.setArg == "function"){
+					token.setArg(token);
+				}
+
+				if(typeof token.setMaxWidth == "function"){
+					token.setMaxWidth(token);
+				}
+
+				if(token._minWidth == "*"){
+					if(this._mapped){
+						throw new Error("* width not supported in mapped formats");
+					}
+					token.minWidth = parseInt(arguments[position++]);
+					if(isNaN(token.minWidth)){
+						throw new Error("the argument for * width at position " + position + " is not a number in " + this._format);
+					}
+					// negative width means rightJustify
+					if (token.minWidth < 0) {
+						token.rightJustify = true;
+						token.minWidth = -token.minWidth;
+					}
+				}
+
+				if(token._precision == "*" && token.period == "."){
+					if(this._mapped){
+						throw new Error("* precision not supported in mapped formats");
+					}
+					token.precision = parseInt(arguments[position++]);
+					if(isNaN(token.precision)){
+						throw Error("the argument for * precision at position " + position + " is not a number in " + this._format);
+					}
+					// negative precision means unspecified
+					if (token.precision < 0) {
+						token.precision = 1;
+						token.period = '';
+					}
+				}
+
+				if(token.isInt){
+					// a specified precision means no zero padding
+					if(token.period == '.'){
+						token.zeroPad = false;
+					}
+					this.formatInt(token);
+				}else if(token.isDouble){
+					if(token.period != '.'){
+						token.precision = 6;
+					}
+					this.formatDouble(token); 
+				}
+				this.fitField(token);
+
+				str += "" + token.arg;
+			}
+		}
+
+		return str;
+	},
+	_zeros10: '0000000000',
+	_spaces10: '          ',
+	formatInt: function(token) {
+		var i = parseInt(token.arg);
+		if(!isFinite(i)){ // isNaN(f) || f == Number.POSITIVE_INFINITY || f == Number.NEGATIVE_INFINITY)
+			// allow this only if arg is number
+			if(typeof token.arg != "number"){
+				throw new Error("format argument '" + token.arg + "' not an integer; parseInt returned " + i);
+			}
+			//return '' + i;
+			i = 0;
+		}
+
+		// if not base 10, make negatives be positive
+		// otherwise, (-10).toString(16) is '-a' instead of 'fffffff6'
+		if(i < 0 && (token.isUnsigned || token.base != 10)){
+			i = 0xffffffff + i + 1;
+		} 
+
+		if(i < 0){
+			token.arg = (- i).toString(token.base);
+			this.zeroPad(token);
+			token.arg = "-" + token.arg;
+		}else{
+			token.arg = i.toString(token.base);
+			// need to make sure that argument 0 with precision==0 is formatted as ''
+			if(!i && !token.precision){
+				token.arg = "";
+			}else{
+				this.zeroPad(token);
+			}
+			if(token.sign){
+				token.arg = token.sign + token.arg;
+			}
+		}
+		if(token.base == 16){
+			if(token.alternative){
+				token.arg = '0x' + token.arg;
+			}
+			token.arg = token.toUpper ? token.arg.toUpperCase() : token.arg.toLowerCase();
+		}
+		if(token.base == 8){
+			if(token.alternative && token.arg.charAt(0) != '0'){
+				token.arg = '0' + token.arg;
+			}
+		}
+	},
+	formatDouble: function(token) {
+		var f = parseFloat(token.arg);
+		if(!isFinite(f)){ // isNaN(f) || f == Number.POSITIVE_INFINITY || f == Number.NEGATIVE_INFINITY)
+			// allow this only if arg is number
+			if(typeof token.arg != "number"){
+				throw new Error("format argument '" + token.arg + "' not a float; parseFloat returned " + f);
+			}
+			// C99 says that for 'f':
+			//   infinity -> '[-]inf' or '[-]infinity' ('[-]INF' or '[-]INFINITY' for 'F')
+			//   NaN -> a string  starting with 'nan' ('NAN' for 'F')
+			// this is not commonly implemented though.
+			//return '' + f;
+			f = 0;
+		}
+
+		switch(token.doubleNotation) {
+			case 'e': {
+				token.arg = f.toExponential(token.precision); 
+				break;
+			}
+			case 'f': {
+				token.arg = f.toFixed(token.precision); 
+				break;
+			}
+			case 'g': {
+				// C says use 'e' notation if exponent is < -4 or is >= prec
+				// ECMAScript for toPrecision says use exponential notation if exponent is >= prec,
+				// though step 17 of toPrecision indicates a test for < -6 to force exponential.
+				if(Math.abs(f) < 0.0001){
+					//print("forcing exponential notation for f=" + f);
+					token.arg = f.toExponential(token.precision > 0 ? token.precision - 1 : token.precision);
+				}else{
+					token.arg = f.toPrecision(token.precision); 
+				}
+
+				// In C, unlike 'f', 'gG' removes trailing 0s from fractional part, unless alternative format flag ("#").
+				// But ECMAScript formats toPrecision as 0.00100000. So remove trailing 0s.
+				if(!token.alternative){ 
+					//print("replacing trailing 0 in '" + s + "'");
+					token.arg = token.arg.replace(/(\..*[^0])0*/, "$1");
+					// if fractional part is entirely 0, remove it and decimal point
+					token.arg = token.arg.replace(/\.0*e/, 'e').replace(/\.0$/,'');
+				}
+				break;
+			}
+			default: throw new Error("unexpected double notation '" + token.doubleNotation + "'");
+		}
+
+		// C says that exponent must have at least two digits.
+		// But ECMAScript does not; toExponential results in things like "1.000000e-8" and "1.000000e+8".
+		// Note that s.replace(/e([\+\-])(\d)/, "e$10$2") won't work because of the "$10" instead of "$1".
+		// And replace(re, func) isn't supported on IE50 or Safari1.
+		token.arg = token.arg.replace(/e\+(\d)$/, "e+0$1").replace(/e\-(\d)$/, "e-0$1");
+
+		// Ensure a '0' before the period.
+		// Opera implements (0.001).toString() as '0.001', but (0.001).toFixed(1) is '.001'
+		if(dojo.isOpera){
+			token.arg = token.arg.replace(/^\./, '0.');
+		}
+
+		// if alt, ensure a decimal point
+		if(token.alternative){
+			token.arg = token.arg.replace(/^(\d+)$/,"$1.");
+			token.arg = token.arg.replace(/^(\d+)e/,"$1.e");
+		}
+
+		if(f >= 0 && token.sign){
+			token.arg = token.sign + token.arg;
+		}
+
+		token.arg = token.toUpper ? token.arg.toUpperCase() : token.arg.toLowerCase();
+	},
+	zeroPad: function(token, /*Int*/ length) {
+		length = (arguments.length == 2) ? length : token.precision;
+		if(typeof token.arg != "string"){
+			token.arg = "" + token.arg;
+		}
+
+		var tenless = length - 10;
+		while(token.arg.length < tenless){
+			token.arg = (token.rightJustify) ? token.arg + this._zeros10 : this._zeros10 + token.arg;
+		}
+		var pad = length - token.arg.length;
+		token.arg = (token.rightJustify) ? token.arg + this._zeros10.substring(0, pad) : this._zeros10.substring(0, pad) + token.arg;
+	},
+	fitField: function(token) {
+		if(token.maxWidth >= 0 && token.arg.length > token.maxWidth){
+			return token.arg.substring(0, token.maxWidth);
+		}
+		if(token.zeroPad){
+			this.zeroPad(token, token.minWidth);
+			return;
+		}
+		this.spacePad(token);
+	},
+	spacePad: function(token, /*Int*/ length) {
+		length = (arguments.length == 2) ? length : token.minWidth;
+		if(typeof token.arg != 'string'){
+			token.arg = '' + token.arg;
+		}
+
+		var tenless = length - 10;
+		while(token.arg.length < tenless){
+			token.arg = (token.rightJustify) ? token.arg + this._spaces10 : this._spaces10 + token.arg;
+		}
+		var pad = length - token.arg.length;
+		token.arg = (token.rightJustify) ? token.arg + this._spaces10.substring(0, pad) : this._spaces10.substring(0, pad) + token.arg;
+	}
+});
\ No newline at end of file
diff --git a/dojox/string/tests/BidiComplex.js b/dojox/string/tests/BidiComplex.js
new file mode 100644
index 0000000..2b0a759
--- /dev/null
+++ b/dojox/string/tests/BidiComplex.js
@@ -0,0 +1,67 @@
+dojo.provide("dojox.string.tests.BidiComplex");
+dojo.require("dojox.string.BidiComplex");
+
+tests.register("dojox.string.tests.BidiComplex", 
+	[
+		{
+			name: "createDisplayString: FILE_PATH",
+			runTest: function(t){
+				var originalString = "c:\\قائمة\\ملف.txt";	
+				var fixedString="‪c:\\قائمة‎\\ملف‎.txt";				
+				var displayString = dojox.string.BidiComplex.createDisplayString(originalString, "FILE_PATH");
+				t.is(displayString, fixedString);
+
+//				originalString = "c:\\אבג\\דהו\\123\\אa";	
+//				fixedString="‪‪c:\\אבג‎\\דהו‎\\123‎\\אa";				
+//				var displayString = dojox.string.BidiComplex.createDisplayString(originalString, "FILE_PATH");
+//				t.is(displayString, fixedString);
+			}
+		},
+		{
+			name: "stripSpecialCharacters: FILE_PATH",
+			runTest: function(t){
+				var originalString = "c:\\قائمة\\ملف.txt";	
+				var fixedString="‪c:\\قائمة‎\\ملف‎.txt";				
+				var stripedString = dojox.string.BidiComplex.stripSpecialCharacters(fixedString);
+				t.is(stripedString, originalString);
+			}
+		},
+		{
+			name: "createDisplayString: EMAIL",
+			runTest: function(t){
+				var originalString = "موظف@شركة.com";
+				var fixedString="‪موظف‎@شركة‎.com";				
+				var displayString = dojox.string.BidiComplex.createDisplayString(originalString, "EMAIL");
+				t.is(displayString, fixedString);
+			}
+		},
+		{
+			name: "stripSpecialCharacters: EMAIL",
+			runTest: function(t){
+				var originalString = "موظف@شركة.com";	
+				var fixedString="‪موظف‎@شركة‎.com";				
+				var stripedString = dojox.string.BidiComplex.stripSpecialCharacters(fixedString);
+				t.is(stripedString, originalString);
+			}
+		},
+		{
+			name: "createDisplayString: URL",
+			runTest: function(t){
+				var originalString ="http://قطاع.شركة.com/الموقع/صفحة?دليل=اختبار&&تعيين=نعم"; 
+				var fixedString="‪http://قطاع‎.شركة‎.com/الموقع‎/صفحة‎?دليل‎=اختبار‎&&تعيين‎=نعم";					
+				var displayString = dojox.string.BidiComplex.createDisplayString(originalString, "URL");
+				t.is(displayString, fixedString);
+			}
+		},
+		{
+			name: "stripSpecialCharacters: URL",
+			runTest: function(t){
+				var originalString ="http://قطاع.شركة.com/الموقع/صفحة?دليل=اختبار&&تعيين=نعم"; 
+				var fixedString="‪http://قطاع‎.شركة‎.com/الموقع‎/صفحة‎?دليل‎=اختبار‎&&تعيين‎=نعم";				
+				var stripedString = dojox.string.BidiComplex.stripSpecialCharacters(fixedString);
+				t.is(stripedString, originalString);
+			}
+		}
+		
+	]
+);
diff --git a/dojox/string/tests/Builder.js b/dojox/string/tests/Builder.js
new file mode 100644
index 0000000..34defe5
--- /dev/null
+++ b/dojox/string/tests/Builder.js
@@ -0,0 +1,104 @@
+dojo.provide("dojox.string.tests.Builder");
+
+dojo.require("dojox.string.Builder");
+
+tests.register("dojox.string.tests.Builder", [
+	{
+		name: "Append",
+		runTest: function(t) {
+			var b = new dojox.string.Builder();
+			b.append("foo");
+			t.is("foo", b.toString());
+			b.append("bar", "baz");
+			t.is("foobarbaz", b.toString());
+			b.append("ben").append("zoo");
+			t.is("foobarbazbenzoo", b.toString());
+			b.append(5);
+			t.is("foobarbazbenzoo5", b.toString());
+		}
+	},
+	{
+		name: "AppendArray",
+		runTest: function(t){
+			var b = new dojox.string.Builder();
+			b.appendArray([ "foo", "bar", "baz" ]);
+			t.is("foobarbaz", b.toString());
+			b.appendArray([ "bar", "baz" ]);
+			t.is("foobarbazbarbaz", b.toString());
+			b.appendArray(["ben","zoo"]).appendArray(["zoo","ben"]);
+			t.is("foobarbazbarbazbenzoozooben", b.toString());
+			b.appendArray([ 5, 8 ]);
+			t.is("foobarbazbarbazbenzoozooben58", b.toString());
+		}
+	},
+	{
+		name: "Construction",
+		runTest: function(t){
+			var b = new dojox.string.Builder();
+			t.is("", b.toString());
+			b = new dojox.string.Builder("foo");
+			t.is("foo", b.toString()); 
+		}
+	},
+	{
+		name: "Replace",
+		runTest: function(t){
+			var b = new dojox.string.Builder("foobar");
+			t.is("foobar", b.toString());
+			b.replace("foo", "baz");
+			t.is("bazbar", b.toString());
+			b.replace("baz", "ben");
+			t.is("benbar", b.toString());
+			b.replace("foo", "moo");
+			t.is("benbar", b.toString());
+			b.replace("enba", "o");
+			t.is("bor", b.toString());
+			b.replace("o", "a").replace("b", "f");
+			t.is("far", b.toString());
+		}
+	},
+	{
+		name: "Insert",
+		runTest: function(t){
+			var b = new dojox.string.Builder();
+			//insert at 0 is prepend
+			b.insert(0, "foo");
+			t.is("foo", b.toString());
+			b.insert(0, "more");
+			t.is("morefoo", b.toString());
+			
+			//insert positions stuff after the 4th character
+			b.insert(4, "fun");
+			t.is("morefunfoo", b.toString());
+			
+			//insert at len of string is push_back
+			b.insert(10, "awesome");
+			t.is("morefunfooawesome", b.toString());
+			
+			//insert past len of string is push_back
+			b.insert(100, "bad");
+			t.is("morefunfooawesomebad", b.toString());
+			
+			b = new dojox.string.Builder();
+			b.insert(0, "foo").insert(3, "bar").insert(3, "zoo");
+			t.is("foozoobar", b.toString());
+		}
+	},
+	{
+		name: "Remove",
+		runTest: function(t){
+			var b = new dojox.string.Builder("foobarbaz");
+			b.remove(3,3);
+			t.is("foobaz", b.toString());
+			b.remove(0,3);
+			t.is("baz", b.toString());
+			b.remove(2, 100);
+			t.is("ba", b.toString());
+			b.remove(0,0);
+			t.is("ba", b.toString());
+			b.append("zbarfoo");
+			b.remove(5);
+			t.is("bazba", b.toString());
+		}
+	}
+]);
diff --git a/dojox/string/tests/BuilderArguments.html b/dojox/string/tests/BuilderArguments.html
new file mode 100644
index 0000000..6d49866
--- /dev/null
+++ b/dojox/string/tests/BuilderArguments.html
@@ -0,0 +1,505 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+  "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+  <head>
+    <title>Builder Perf Arguments Tests</title>
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug: true"></script>
+    <script type="text/javascript" src="../Builder.js"></script>
+    <script type="text/javascript" src="lipsum.js"></script>
+    <script type="text/javascript">
+
+    dojo.addOnLoad(function(){
+      dojo.byId("run").disabled="";
+      dojo.connect(dojo.byId("run"), 
+                   "onclick", 
+                   function(evt) { 
+                     setTimeout(function() { 
+                       var words = parseInt(dojo.byId("numWords").value) || 10;
+                       var iters = parseInt(dojo.byId("numIters").value) || 1000;
+                       var dict = eval(dojo.byId("dict").value);
+                       buildAndRunSet(words, dict, iters); 
+                      }, 0); 
+                    });
+    });
+    
+    function element(tag, textOrChildOrArray) {
+      var e = document.createElement(tag);
+      function append(n) {
+        if(dojo.isString(n)){
+          n = document.createTextNode(n);
+        } 
+        e.appendChild(n);
+      }
+      if(dojo.isArray(textOrChildOrArray)) {
+        dojo.forEach(textOrChildOrArray, append);
+      }else{
+        append(textOrChildOrArray);
+      }
+      return e;
+    }
+    
+    function log(t) {
+      dojo.byId("mess").innerHTML = t;
+      console.log(t);
+    }
+    
+    function reportRun(results){
+      var runs = results.runs
+      var report = element("dl",
+                     element("dt", 
+                             "Run with " + results.words + " words, " + 
+                                           results.iterations + " iterations, for loop overhead of " + 
+                                           results.overhead + ", average phrase of " +
+                                           results.wordSize + " characters"));
+                          
+  //    runs.sort(function(a,b) { return a.time - b.time; });
+      dojo.forEach(runs, function(r) {
+        report.appendChild(element("dd", r.time + " - " + r.name));
+      });
+      
+      dojo.body().appendChild(report);
+    }
+    
+    function runTest(test, iterations, expected) {
+      var i;
+      if(expected != test()) throw new Error("Test failed expecting " + expected + ", got " + test());
+      var start = new Date().getTime(), end;
+      for(i=0; i < iterations; i++){
+        test();
+      }
+      end = new Date().getTime();
+      return end-start;
+    }
+    
+    function runSet(set, iterations){
+      
+      function averagePhraseLen(words) {
+        var sizes = dojo.map(words, function(w) { return w.length; });
+        var total = 0;
+        dojo.forEach(sizes, function(s) { total += s; });
+        return total / sizes.length;
+      }
+      
+      var tests = set.tests.concat(); //copy tests
+      var resultSet = {};
+      resultSet.words = set.words.length;
+      resultSet.overhead = runTest(set.overhead, iterations);
+      resultSet.iterations = iterations;
+      resultSet.wordSize = averagePhraseLen(set.words);
+      var runs = [];
+      
+      function _run() {
+        var t = tests.pop();
+        try {
+          log("Running " + t.name);
+          if(t) runs.push({ name: t.name, time: runTest(t.test, iterations, set.expected)});
+        } catch(e) {
+          console.error("Error running " + t.name);
+          console.error(e);
+        }
+        if(tests.length > 0) {
+          setTimeout(_run, 0);
+        }
+        else {
+          log("Done!");
+          resultSet.runs = runs;
+          reportRun(resultSet);
+          dojo.publish("perf/run/done");
+        }
+      }
+      setTimeout(_run, 25);
+    }
+    
+    function buildTestSet(numWords, dict) {
+      var words = [], i, dl = dict.length;
+      for(i = numWords; i > 0; i-=dl) { 
+        if(i >= dl) { words = words.concat(dict); }
+        else { words = words.concat(dict.slice(-i)); } 
+      }
+      if(words.length != numWords) throw new Error("wrong number of words, got " + words.length + ", expected " + numWords);
+      
+      var expected = words.join("");
+      
+      var _builder = new dojox.string.Builder();
+      
+      return { 
+        tests: [
+          /*
+          {
+            name: "concatFor",
+            test: function() {
+              var s = "";
+              for(var i = 0; i < words.length; i++) {
+                s = s.concat(words[i]);
+              }
+              return s;
+            }
+          },
+          {
+            name: "concatForAlias",
+            test: function() {
+              var s = "", w = words, l = w.length;
+              for(var i = 0; i < l; i++) {
+                s = s.concat(w[i]);
+              }
+              return s;
+            }
+          },
+          {
+            name: "concatForEach",
+            test: function() {
+              var s = "";
+              dojo.forEach(words, function(w) {
+                s = s.concat(w);
+              });
+              return s;
+            }
+          },
+          {
+            name: "concatOnce",
+            test: function() {
+              var s = "";
+              s = String.prototype.concat.apply(s, words);
+              return s;
+            }
+          },
+          */
+          {
+            name: "builderFor",
+            test: function() {
+              var b = new dojox.string.Builder();
+              for(var i = 0; i < words.length; i++) {
+                b.append(words[i]);
+              }
+              return b.toString();
+            }
+          },
+          {
+            name: "builderFor2Args",
+            test: function() {
+				var b = new dojox.string.Builder(), l=words.length, r=words.length%2;
+              for(var i = 0; i < words.length; i+=2) {
+				  b.append(words[i], words[i+1]);
+              }
+			  for(i=l-r; i<l; i++){
+				  b.append(words[i]);
+			  }
+              return b.toString();
+            }
+          },
+          {
+            name: "builderFor3Args",
+            test: function() {
+				var b = new dojox.string.Builder(), l=words.length, r=words.length%3;
+              for(var i = 0; i < l-r; i+=3) {
+				  b.append(words[i], words[i+1], words[i+2]);
+			  }
+			  for(i=l-r; i<l; i++){
+				  b.append(words[i]);
+			  }
+              return b.toString();
+            }
+          },
+          {
+            name: "builderFor4Args",
+            test: function() {
+				var b = new dojox.string.Builder(), l=words.length, r=words.length%4;
+              for(var i = 0; i < l-r; i+=4) {
+				  b.append(words[i], words[i+1], words[i+2], words[i+3]);
+              }
+			  for(i=l-r; i<l; i++){
+				  b.append(words[i]);
+			  }
+              return b.toString();
+            }
+          },
+          {
+            name: "builderFor5Args",
+            test: function() {
+				var b = new dojox.string.Builder(), l=words.length, r=words.length%5;
+              for(var i = 0; i < l-r; i+=5) {
+				  b.append(words[i], words[i+1], words[i+2], words[i+3], words[i+4]);
+              }
+			  for(i=l-r; i<l; i++){
+				  b.append(words[i]);
+			  }
+              return b.toString();
+            }
+          },
+          {
+            name: "builderFor6Args",
+            test: function() {
+				var b = new dojox.string.Builder(), l=words.length, r=words.length%6;
+              for(var i = 0; i < l-r; i+=6) {
+				  b.append(words[i], words[i+1], words[i+2], words[i+3], words[i+4], words[i+5]);
+              }
+			  for(i=l-r; i<l; i++){
+				  b.append(words[i]);
+			  }
+              return b.toString();
+            }
+          },
+          {
+            name: "builderFor7Args",
+            test: function() {
+				var b = new dojox.string.Builder(), l=words.length, r=words.length%7;
+              for(var i = 0; i < l-r; i+=7) {
+				  b.append(words[i], words[i+1], words[i+2], words[i+3], words[i+4], words[i+5], words[i+6]);
+              }
+			  for(i=l-r; i<l; i++){
+				  b.append(words[i]);
+			  }
+              return b.toString();
+            }
+          },
+          {
+            name: "builderFor8Args",
+            test: function() {
+				var b = new dojox.string.Builder(), l=words.length, r=words.length%8;
+              for(var i = 0; i < l-r; i+=8) {
+				  b.append(words[i], words[i+1], words[i+2], words[i+3], words[i+4], words[i+5], words[i+6], words[i+7]);
+              }
+			  for(i=l-r; i<l; i++){
+				  b.append(words[i]);
+			  }
+              return b.toString();
+            }
+          },
+          {
+            name: "builderFor9Args",
+            test: function() {
+				var b = new dojox.string.Builder(), l=words.length, r=words.length%9;
+              for(var i = 0; i < l-r; i+=9) {
+				  b.append(words[i], words[i+1], words[i+2], words[i+3], words[i+4], words[i+5], words[i+6], words[i+7], words[i+8]);
+              }
+			  for(i=l-r; i<l; i++){
+				  b.append(words[i]);
+			  }
+              return b.toString();
+            }
+          } /*,
+          {
+            name: "builderForEach",
+            test: function() {
+              var b = new dojox.string.Builder();
+              dojo.forEach(words, function(w) {
+                b.append(w);
+              });
+              return b.toString();
+            }
+          },
+          
+          {
+            name: "builderReusedFor",
+            test: function() {
+              _builder.clear();
+              for(var i = 0; i < words.length; i++) {
+                _builder.append(words[i]);
+              }
+              return _builder.toString();
+            }
+		},		
+          {
+            name: "builderOnce",
+            test: function() {
+              var b = new dojox.string.Builder();
+              b.appendArray(words);
+              return b.toString();
+            }
+          },
+          {
+            name: "builderReusedOnce",
+            test: function() {
+              _builder.clear();
+              _builder.appendArray(words);
+              return _builder.toString();
+            }
+          },
+          {
+            name: "plusFor",
+            test: function() {
+              var s = "";
+              for(var i = 0; i < words.length; i++) {
+                s += words[i];
+              }
+              return s;
+            }
+          },
+          {
+            name: "plusForAlias",
+            test: function() {
+              var s = "", w = words, l = w.length;
+              for(var i = 0; i < l; i++) {
+                s += w[i];
+              }
+              return s;
+            }
+          },
+          {
+            name: "plusForEach",
+            test: function() {
+              var s = "";
+              dojo.forEach(words, function(w) { s += w; });
+              return s;
+            }
+          },
+          {
+            name: "joinOnce",
+            test: function() {
+              return words.join("");
+            }
+          },
+          {
+            name: "joinFor",
+            test: function() {
+              var a = [];
+              for(var i = 0; i < words.length; i++) {
+                a.push(words[i]);
+              }
+              return a.join("");
+            }
+		},
+          {
+            name: "joinForAlias",
+            test: function() {
+              var a = [], w = words, l = w.length;
+              for(var i = 0; i <l; i++) {
+                a.push(w[i]);
+              }
+              return a.join("");
+            }
+          },
+          {
+            name: "joinForEach",
+            test: function() {
+              var a = [];
+              dojo.forEach(words, function(w) { a.push(w); });
+              return a.join("");
+            }
+          }
+          */
+        ],
+        words: words,
+        expected: expected,
+        overhead: function() { 
+          var w = words; 
+          var l = w.length; 
+          for(var i=0; i < l; i++) { 
+            ident(w[i]); 
+          } 
+        }
+      };
+    }
+    
+    function buildAndRunSet(words, dict, times) {
+      runSet(buildTestSet(words, dict), times);
+    }
+    
+    function runSuite() {
+      var suite = [
+        {
+          words: 2,
+          times: 10000
+        },
+        {
+          words: 4,
+          times: 10000
+        },
+        {
+          words: 8,
+          times: 10000
+        },
+        {
+          words: 16,
+          times: 10000
+        },
+        {
+          words: 32,
+          times: 10000
+        },
+        {
+          words: 64,
+          times: 10000
+        },
+        {
+          words: 128,
+          times: 1000
+        },
+        {
+          words: 256,
+          times: 1000
+        },
+        {
+          words: 512,
+          times: 1000
+        },
+        {
+          words: 1024,
+          times: 1000
+        },
+        {
+          words: 2048,
+          times: 1000
+        },
+        {
+          words: 4096,
+          times: 100
+        },
+        {
+          words: 8192,
+          times: 100
+        }
+      ];
+      
+      var totalSuite = dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsum; return n; });
+      totalSuite = totalSuite.concat(dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsumLong; return n; }));
+      console.log(totalSuite);
+      
+      var handle = dojo.subscribe("perf/run/done", _run);
+      dojo.subscribe("perf/run/done", function(){ console.log("perf run done"); });
+      
+      function _run() {
+        var t = totalSuite.shift();
+        if(t) buildAndRunSet(t.words, t.dict, t.times);
+        if(totalSuite.length == 0) dojo.unsubscribe(handle);
+      }
+      
+      _run();
+    }
+    
+    function ident(i) { return i; }
+    </script>
+    <style type="text/css">
+    html { 
+      font-family: Lucida Grande, Tahoma;
+    }
+    div { margin-bottom: 1em; }
+    #results {
+      border: 1px solid #999;
+      border-collapse: collapse;
+    }
+    #results caption {
+      font-size: medium;
+      font-weight: bold;
+    }
+    #results td, #results th {
+      text-align: right;
+      width: 10em;
+      font-size: small;
+      white-space: nowrap;
+    }
+    #wordsCol { background: yellow; }
+    td.max { color: red; font-weight: bold; }
+    td.min { color: green; font-weight: bold; }
+    </style>
+  </head>
+  <body>
+    <table>
+      <tr><td><label for="numWords">Words</label></td><td><input type="text" id="numWords" value="100"/></td></tr>
+      <tr><td><label for="numIters">Iterations</label></td><td><input type="text" id="numIters" value="1000"/></td></tr>
+      <tr><td><label for="dict">Dictionary</label></td><td><input type="text" id="dict" value="lipsum"></td></tr>
+      <tr><td></td><td><button id="run" disabled>Run Tests!</button></td></tr>
+    </table>
+    <div id="mess"></div>    
+  </body>
+</html>
diff --git a/dojox/string/tests/BuilderPerf.html b/dojox/string/tests/BuilderPerf.html
new file mode 100644
index 0000000..54e3780
--- /dev/null
+++ b/dojox/string/tests/BuilderPerf.html
@@ -0,0 +1,413 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+  "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+  <head>
+    <title>Builder Perf Tests</title>
+    <script type="text/javascript" src="../../../dojo/dojo.js"></script>
+    <script type="text/javascript" src="../Builder.js"></script>
+    <script type="text/javascript" src="lipsum.js"></script>
+    <script type="text/javascript">
+
+    dojo.addOnLoad(function(){
+      dojo.byId("run").disabled="";
+      dojo.connect(dojo.byId("run"), 
+                   "onclick", 
+                   function(evt) { 
+                     setTimeout(function() { 
+                       var words = parseInt(dojo.byId("numWords").value) || 10;
+                       var iters = parseInt(dojo.byId("numIters").value) || 1000;
+                       var dict = eval(dojo.byId("dict").value);
+                       buildAndRunSet(words, dict, iters); 
+                      }, 0); 
+                    });
+    });
+    
+    function element(tag, textOrChildOrArray) {
+      var e = document.createElement(tag);
+      function append(n) {
+        if(dojo.isString(n)){
+          n = document.createTextNode(n);
+        } 
+        e.appendChild(n);
+      }
+      if(dojo.isArray(textOrChildOrArray)) {
+        dojo.forEach(textOrChildOrArray, append);
+      }else{
+        append(textOrChildOrArray);
+      }
+      return e;
+    }
+    
+    function log(t) {
+      dojo.byId("mess").innerHTML = t;
+      console.log(t);
+    }
+    
+    function reportRun(results){
+      var runs = results.runs
+      var report = element("dl",
+                     element("dt", 
+                             "Run with " + results.words + " words, " + 
+                                           results.iterations + " iterations, for loop overhead of " + 
+                                           results.overhead + ", average phrase of " +
+                                           results.wordSize + " characters"));
+                          
+      runs.sort(function(a,b) { return a.time - b.time; });
+      dojo.forEach(runs, function(r) {
+        report.appendChild(element("dd", r.time + " - " + r.name));
+      });
+      
+      dojo.body().appendChild(report);
+    }
+    
+    function runTest(test, iterations, expected) {
+      var i;
+      if(expected != test()) throw new Error("Test failed expecting " + expected + ", got " + test());
+      var start = new Date().getTime(), end;
+      for(i=0; i < iterations; i++){
+        test();
+      }
+      end = new Date().getTime();
+      return end-start;
+    }
+    
+    function runSet(set, iterations){
+      
+      function averagePhraseLen(words) {
+        var sizes = dojo.map(words, function(w) { return w.length; });
+        var total = 0;
+        dojo.forEach(sizes, function(s) { total += s; });
+        return total / sizes.length;
+      }
+      
+      var tests = set.tests.concat(); //copy tests
+      var resultSet = {};
+      resultSet.words = set.words.length;
+      resultSet.overhead = runTest(set.overhead, iterations);
+      resultSet.iterations = iterations;
+      resultSet.wordSize = averagePhraseLen(set.words);
+      var runs = [];
+      
+      function _run() {
+        var t = tests.pop();
+        try {
+          log("Running " + t.name);
+          if(t) runs.push({ name: t.name, time: runTest(t.test, iterations, set.expected)});
+        } catch(e) {
+          console.error("Error running " + t.name);
+          console.error(e);
+        }
+        if(tests.length > 0) {
+          setTimeout(_run, 0);
+        }
+        else {
+          log("Done!");
+          resultSet.runs = runs;
+          reportRun(resultSet);
+          dojo.publish("perf/run/done");
+        }
+      }
+      setTimeout(_run, 25);
+    }
+    
+    function buildTestSet(numWords, dict) {
+      var words = [], i, dl = dict.length;
+      for(i = numWords; i > 0; i-=dl) { 
+        if(i >= dl) { words = words.concat(dict); }
+        else { words = words.concat(dict.slice(-i)); } 
+      }
+      if(words.length != numWords) throw new Error("wrong number of words, got " + words.length + ", expected " + numWords);
+      
+      var expected = words.join("");
+      
+      var _builder = new dojox.string.Builder();
+      
+      return { 
+        tests: [
+          {
+            name: "concatFor",
+            test: function() {
+              var s = "";
+              for(var i = 0; i < words.length; i++) {
+                s = s.concat(words[i]);
+              }
+              return s;
+            }
+          },
+          /*
+          {
+            name: "concatForAlias",
+            test: function() {
+              var s = "", w = words, l = w.length;
+              for(var i = 0; i < l; i++) {
+                s = s.concat(w[i]);
+              }
+              return s;
+            }
+          },
+          {
+            name: "concatForEach",
+            test: function() {
+              var s = "";
+              dojo.forEach(words, function(w) {
+                s = s.concat(w);
+              });
+              return s;
+            }
+          },
+          */
+          {
+            name: "concatOnce",
+            test: function() {
+              var s = "";
+              s = String.prototype.concat.apply(s, words);
+              return s;
+            }
+          },
+          {
+            name: "builderFor",
+            test: function() {
+              var b = new dojox.string.Builder();
+              for(var i = 0; i < words.length; i++) {
+                b.append(words[i]);
+              }
+              return b.toString();
+            }
+          },
+          {
+            name: "builderForMulti",
+            test: function() {
+              var b = new dojox.string.Builder();
+              for(var i = 0; i < words.length; i+=2) {
+				  b.append(words[i], words[i+1]);
+              }
+              return b.toString();
+            }
+          },
+          /*
+          {
+            name: "builderForEach",
+            test: function() {
+              var b = new dojox.string.Builder();
+              dojo.forEach(words, function(w) {
+                b.append(w);
+              });
+              return b.toString();
+            }
+          },
+          */
+          {
+            name: "builderReusedFor",
+            test: function() {
+              _builder.clear();
+              for(var i = 0; i < words.length; i++) {
+                _builder.append(words[i]);
+              }
+              return _builder.toString();
+            }
+          },
+          {
+            name: "builderOnce",
+            test: function() {
+              var b = new dojox.string.Builder();
+              b.appendArray(words);
+              return b.toString();
+            }
+          },
+          {
+            name: "builderReusedOnce",
+            test: function() {
+              _builder.clear();
+              _builder.appendArray(words);
+              return _builder.toString();
+            }
+          },
+          {
+            name: "plusFor",
+            test: function() {
+              var s = "";
+              for(var i = 0; i < words.length; i++) {
+                s += words[i];
+              }
+              return s;
+            }
+          },
+          /*
+          {
+            name: "plusForAlias",
+            test: function() {
+              var s = "", w = words, l = w.length;
+              for(var i = 0; i < l; i++) {
+                s += w[i];
+              }
+              return s;
+            }
+          },
+          {
+            name: "plusForEach",
+            test: function() {
+              var s = "";
+              dojo.forEach(words, function(w) { s += w; });
+              return s;
+            }
+          },*/
+          {
+            name: "joinOnce",
+            test: function() {
+              return words.join("");
+            }
+          },
+          {
+            name: "joinFor",
+            test: function() {
+              var a = [];
+              for(var i = 0; i < words.length; i++) {
+                a.push(words[i]);
+              }
+              return a.join("");
+            }
+          }/*,
+          {
+            name: "joinForAlias",
+            test: function() {
+              var a = [], w = words, l = w.length;
+              for(var i = 0; i <l; i++) {
+                a.push(w[i]);
+              }
+              return a.join("");
+            }
+          },
+          {
+            name: "joinForEach",
+            test: function() {
+              var a = [];
+              dojo.forEach(words, function(w) { a.push(w); });
+              return a.join("");
+            }
+          }
+          */
+        ],
+        words: words,
+        expected: expected,
+        overhead: function() { 
+          var w = words; 
+          var l = w.length; 
+          for(var i=0; i < l; i++) { 
+            ident(w[i]); 
+          } 
+        }
+      };
+    }
+    
+    function buildAndRunSet(words, dict, times) {
+      runSet(buildTestSet(words, dict), times);
+    }
+    
+    function runSuite() {
+      var suite = [
+        {
+          words: 2,
+          times: 10000
+        },
+        {
+          words: 4,
+          times: 10000
+        },
+        {
+          words: 8,
+          times: 10000
+        },
+        {
+          words: 16,
+          times: 10000
+        },
+        {
+          words: 32,
+          times: 10000
+        },
+        {
+          words: 64,
+          times: 10000
+        },
+        {
+          words: 128,
+          times: 1000
+        },
+        {
+          words: 256,
+          times: 1000
+        },
+        {
+          words: 512,
+          times: 1000
+        },
+        {
+          words: 1024,
+          times: 1000
+        },
+        {
+          words: 2048,
+          times: 1000
+        },
+        {
+          words: 4096,
+          times: 100
+        },
+        {
+          words: 8192,
+          times: 100
+        }
+      ];
+      
+      var totalSuite = dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsum; return n; });
+      totalSuite = totalSuite.concat(dojo.map(suite, function(s) { var n = {}; dojo.mixin(n,s); n.dict = lipsumLong; return n; }));
+      console.log(totalSuite);
+      
+      var handle = dojo.subscribe("perf/run/done", _run);
+      dojo.subscribe("perf/run/done", function(){ console.log("perf run done"); });
+      
+      function _run() {
+        var t = totalSuite.shift();
+        if(t) buildAndRunSet(t.words, t.dict, t.times);
+        if(totalSuite.length == 0) dojo.unsubscribe(handle);
+      }
+      
+      _run();
+    }
+    
+    function ident(i) { return i; }
+    </script>
+    <style type="text/css">
+    html { 
+      font-family: Lucida Grande, Tahoma;
+    }
+    div { margin-bottom: 1em; }
+    #results {
+      border: 1px solid #999;
+      border-collapse: collapse;
+    }
+    #results caption {
+      font-size: medium;
+      font-weight: bold;
+    }
+    #results td, #results th {
+      text-align: right;
+      width: 10em;
+      font-size: small;
+      white-space: nowrap;
+    }
+    #wordsCol { background: yellow; }
+    td.max { color: red; font-weight: bold; }
+    td.min { color: green; font-weight: bold; }
+    </style>
+  </head>
+  <body>
+    <table>
+      <tr><td><label for="numWords">Words</label></td><td><input type="text" id="numWords" value="100"/></td></tr>
+      <tr><td><label for="numIters">Iterations</label></td><td><input type="text" id="numIters" value="1000"/></td></tr>
+      <tr><td><label for="dict">Dictionary</label></td><td><input type="text" id="dict" value="lipsum"></td></tr>
+      <tr><td></td><td><button id="run" disabled>Run Tests!</button></td></tr>
+    </table>
+    <div id="mess"></div>    
+  </body>
+</html>
diff --git a/dojox/string/tests/PerfFun.html b/dojox/string/tests/PerfFun.html
new file mode 100644
index 0000000..f317428
--- /dev/null
+++ b/dojox/string/tests/PerfFun.html
@@ -0,0 +1,263 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+  "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+  <head>
+    <title>Perf Tests</title>
+    <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+    <script type="text/javascript" src="lipsum.js"></script>
+    <script type="text/javascript">
+    dojo.addOnLoad(function(){
+      dojo.byId("run").disabled="";
+      dojo.connect(dojo.byId("run"), 
+                   "onclick", 
+                   function(evt) { 
+                     setTimeout(function() { 
+                       var words = parseInt(dojo.byId("numWords").value) || 10;
+                       var iters = parseInt(dojo.byId("numIters").value) || 1000;
+                       buildAndRunSet(words, iters); 
+                      }, 0); 
+                    });
+    });
+    
+    function element(tag, textOrChild) {
+      var e = document.createElement(tag);
+      if(dojo.isArray(textOrChild)){  dojo.forEach(textOrChild, function(c) { e.appendChild(c); }); }
+      if(dojo.isString(textOrChild)){
+      	e.appendChild(document.createTextNode(textOrChild));
+      }else{
+      	e.appendChild(textOrChild);
+      }
+      return e;
+    }
+    
+    function log(t) {
+      dojo.byId("mess").innerHTML = t;
+    }
+    
+    function reportRun(results){
+      var runs = results.runs;
+      var report = element("dl",
+                     element("dt", 
+                             "Run with " + results.words + " words, " + 
+                                           results.iterations + " iterations and overhead of " + 
+                                           results.overhead));
+                          
+      runs.sort(function(a,b) { return a.time - b.time; });
+      dojo.forEach(runs, function(r) {
+        report.appendChild(element("dd", r.time + " - " + r.name));
+      });
+      
+      dojo.body().appendChild(report);
+    }
+    
+    function runTest(test, iterations, expected) {
+      var i;
+      if(expected != test()){ throw new Error("Test failed expecting " + expected + ", got " + test()); }
+      var start = new Date().getTime(), end;
+      for(i=0; i < iterations; i++){
+        test();
+      }
+      end = new Date().getTime();
+      return end-start;
+    }
+    
+    function runSet(set, iterations){
+      
+      var tests = set.tests.concat(); //copy tests
+      var resultSet = {};
+      resultSet.words = set.words.length;
+      resultSet.overhead = runTest(function(){}, iterations);
+      resultSet.iterations = iterations;
+      var runs = [];
+      
+      function _run() {
+        var t = tests.pop();
+        try {
+          log("Running " + t.name);
+          if(t && !t.skip){ runs.push({ name: t.name, time: runTest(t.test, iterations, set.expected)}); }
+        } catch(e) {
+          console.error("Error running " + t.name, e);
+        }
+        if(tests.length > 0) {
+          setTimeout(_run, 0);
+        }
+        else {
+          log("Done!");
+          resultSet.runs = runs;
+          reportRun(resultSet);
+        }
+      }
+      setTimeout(_run, 0);
+    }
+    
+    function buildTestSet(numWords) {
+      var words = [], i, wordsInLipsum = lipsum.length;
+      for(i = numWords; i > 0; i-=wordsInLipsum) { 
+        if(i >= wordsInLipsum) { words = words.concat(lipsum); }
+        else { words = words.concat(lipsum.slice(-i)); } 
+      }
+      if(words.length != numWords){ throw new Error("wrong number of words, got " + words.length + ", expected " + numWords); }
+
+      var expected = words.join("");
+      
+      //console.log(words);
+      
+      return { 
+        tests: [
+          {
+            name: "dojoForEach",
+            test: function() {
+              var s = "";
+              dojo.forEach(words, function(w) { s+=w; });
+              return s;
+            }
+          },
+          {
+            name: "nativeForEach",
+            test: function() {
+              var s = "";
+              words.forEach(function(w) { s += w; });
+              return s;
+            },
+            skip: !words.forEach
+          },
+          {
+            name: "forLoop",
+            test: function() {
+              var s="",w=words; l=w.length;
+              for(var i = 0; i < l; i++) {
+                s += w[i];
+              }
+              return s;
+            }
+          },
+          {
+            name: "forLoopCallingInlineFunction",
+            test: function() {
+              var s="",w=words; l=w.length;
+              function fn(w) { s += w; }
+              for(var i = 0; i < l; i++) {
+                fn(w[i]);
+              }
+              return s;
+            }
+          },
+          {
+            name: "forLoopCallingExternalFunction",
+            test: function() {
+              var g_s="",w=words; l=w.length;
+              for(var i = 0; i < l; i++) {
+                externalAppend(w[i]);
+              }
+              return g_s;
+            }
+          },
+          {
+            name: "forLoopWithInCheck",
+            test: function() {
+              var s="",w=words; l=w.length;
+              for(var i = 0; i < l; i++) {
+                if(i in w){ s += w[i]; }
+              }
+              return s;
+            }
+          },
+          {
+            name: "emptyFor",
+            test: function() {
+              var w = words; l = w.length;
+              for(var i = 0; i < l; i++){ empty(w[i]); }
+              return expected;
+            }
+          },
+          {
+            name: "emptyForEach",
+            test: function() {
+              dojo.forEach(words, empty);
+              return expected;
+            }
+          } ,
+          {
+            name: "identFor",
+            test: function() {
+              var w = words; l = w.length;
+              for(var i = 0; i < l; i++){ ident(w[i]); }
+              return expected;
+            }
+          },
+          {
+            name: "identForEach",
+            test: function() {
+              dojo.forEach(words, ident);
+              return expected;
+            }
+          },
+          {
+            name: "addUsingFor",
+            test: function() {
+              var x=0;
+              for(var i=0;i<1000;i++){x=x+a[i];}
+              return expected; // fake
+            }
+          },
+          {
+            name: "addUsingForEach",
+            test: function() {
+              var x=0;
+              dojo.forEach(a, function(v,i){x=x+a[i];});
+              return expected; // fake
+            }
+          }
+        ],
+        words: words,
+        expected: expected
+      };
+    }
+    
+    function buildAndRunSet(words, times) {
+      runSet(buildTestSet(words), times);
+    }
+    
+    function ident(w) { return w; }
+    function empty() { }
+    
+    var g_s = "";
+    function externalAppend(w){ g_s += w; }
+    
+    var a = new Array(1000);
+    for(var i=0; i<1000;i++){a[i]=i;}
+    
+    </script>
+    <style type="text/css">
+    html { 
+      font-family: Lucida Grande, Tahoma;
+    }
+    div { margin-bottom: 1em; }
+    #results {
+      border: 1px solid #999;
+      border-collapse: collapse;
+    }
+    #results caption {
+      font-size: medium;
+      font-weight: bold;
+    }
+    #results td, #results th {
+      text-align: right;
+      width: 10em;
+      font-size: small;
+      white-space: nowrap;
+    }
+    #wordsCol { background: yellow; }
+    td.max { color: red; font-weight: bold; }
+    td.min { color: green; font-weight: bold; }
+    </style>
+  </head>
+  <body>
+    <table>
+      <tr><td><label for="numWords">Words</label></td><td><input type="text" id="numWords" value="100"/></td></tr>
+      <tr><td><label for="numIters">Iterations</label></td><td><input type="text" id="numIters" value="1000"/></td></tr>
+      <tr><td></td><td><button id="run" disabled>Run Tests!</button></td></tr>
+    </table>
+    <div id="mess"></div>    
+  </body>
+</html>
diff --git a/dojox/string/tests/lipsum.js b/dojox/string/tests/lipsum.js
new file mode 100644
index 0000000..ea62a25
--- /dev/null
+++ b/dojox/string/tests/lipsum.js
@@ -0,0 +1,133 @@
+var lipsum = ["Lorem", "ipsum", "dolor", "sit", "amet,", "consectetuer",
+"adipiscing", "elit.", "Suspendisse", "nisi.", "Pellentesque", "facilisis",
+"pretium", "nulla.", "Sed", "semper", "accumsan", "quam.", "Donec",
+"vulputate", "auctor", "neque.", "Aenean", "arcu", "pede,", "consequat",
+"eget,", "molestie", "sed,", "bibendum", "quis,", "ante.", "Praesent", "sit",
+"amet", "odio", "ut", "ipsum", "suscipit", "faucibus.", "Vestibulum",
+"accumsan,", "nunc", "non", "adipiscing", "hendrerit,", "lorem", "arcu",
+"dignissim", "mi,", "vel", "blandit", "urna", "velit", "dictum", "leo.",
+"Aliquam", "ornare", "massa", "quis", "lacus.", "Cum", "sociis", "natoque",
+"penatibus", "et", "magnis", "dis", "parturient", "montes,", "nascetur",
+"ridiculus", "mus.", "Vivamus", "sit", "amet", "ligula.", "Pellentesque",
+"vitae", "nunc", "sed", "mauris", "consequat", "condimentum.Lorem", "ipsum",
+"dolor", "sit", "amet,", "consectetuer", "adipiscing", "elit.", "Donec", "in",
+"lectus", "eu", "magna", "consectetuer", "pellentesque.", "Donec", "ante.",
+"Integer", "ut", "turpis.", "Sed", "tincidunt", "consectetuer", "purus.",
+"Cras", "lacus.", "Nunc", "et", "lacus.", "Ut", "aliquet", "urna", "ut",
+"urna.", "Etiam", "vel", "urna.", "Nunc", "id", "diam.", "Fusce", "at",
+"purus", "id", "velit", "molestie", "pretium.Aenean", "vel", "sapien", "et",
+"justo", "ornare", "cursus.", "Donec", "facilisis.", "Vestibulum", "feugiat",
+"magna", "in", "nulla.", "Curabitur", "orci.", "Vestibulum", "molestie",
+"aliquet", "est.", "Sed", "eget", "erat", "non", "sem", "laoreet",
+"pellentesque.", "Cras", "at", "odio", "nec", "leo", "egestas", "blandit.",
+"Nullam", "at", "dui.", "Duis", "felis", "lacus,", "blandit", "non,",
+"consequat", "ut,", "fringilla", "at,", "est.", "Etiam", "blandit", "porta",
+"tellus.", "Etiam", "purus", "turpis,", "molestie", "ut,", "tristique",
+"eget,", "elementum", "sit", "amet,", "orci.", "Pellentesque", "condimentum",
+"ultrices", "neque.", "Duis", "dignissim.", "Curabitur", "condimentum",
+"arcu", "id", "sapien.Nunc", "diam", "eros,", "pellentesque", "non,",
+"lobortis", "et,", "venenatis", "eu,", "felis.", "Vestibulum", "vel", "dolor",
+"quis", "nunc", "semper", "consectetuer.", "Nullam", "mollis.", "Aenean",
+"molestie", "cursus", "mi.", "Mauris", "ante.", "In", "hac", "habitasse",
+"platea", "dictumst.", "Nunc", "sem", "dui,", "fermentum", "ac,", "luctus",
+"a,", "imperdiet", "in,", "neque.", "Cras", "mattis", "pretium", "metus.",
+"Praesent", "ligula", "mi,", "imperdiet", "eu,", "rutrum", "volutpat,",
+"blandit", "id,", "lectus.", "Duis", "sed", "mauris", "id", "lacus",
+"lacinia", "rhoncus.", "Vivamus", "ultricies", "sem", "a", "nisi",
+"fermentum", "pretium.", "Cras", "sagittis", "tempus", "velit.", "Mauris",
+"eget", "quam.", "Sed", "facilisis", "tincidunt", "tellus.", "Vestibulum",
+"rhoncus", "venenatis", "felis.", "Aliquam", "erat", "volutpat.Proin", "et",
+"orci", "at", "libero", "faucibus", "iaculis.", "Nam", "id", "purus.", "Ut",
+"aliquet,", "turpis", "id", "volutpat", "gravida,", "felis", "urna",
+"viverra", "justo,", "id", "semper", "nulla", "ligula", "id", "libero.",
+"Sed", "fringilla.", "Fusce", "vel", "lorem", "ut", "tortor", "porta",
+"tincidunt.", "Nunc", "arcu.", "Class", "aptent", "taciti", "sociosqu", "ad",
+"litora", "torquent", "per", "coubia", "ostra,", "per", "iceptos",
+"hymeaeos.", "Doec", "ullamcorper", "ate", "vel", "felis.", "Mauris", "quis",
+"dolor.", "Vestibulum", "ulla", "felis,", "laoreet", "ut,", "placerat", "at,",
+"malesuada", "et,", "lacus.", "Suspedisse", "eget", "mi", "id", "dui",
+"porttitor", "porttitor.", "Quisque", "elemetum.", "Sed", "tortor.", "Etiam",
+"malesuada.", "Cum", "sociis", "atoque", "peatibus", "et", "magis", "dis",
+"parturiet", "motes,", "ascetur", "ridiculus", "mus.Suspedisse", "euismod",
+"sagittis", "eros.", "uc", "sollicitudi.", "Doec", "ac", "turpis.", "Mauris",
+"feugiat", "isl", "vel", "ate.", "am", "isi.", "Etiam", "auctor", "elemetum",
+"diam.", "uc", "ut", "elit", "auctor", "ibh", "orare", "viverra.", "Iteger",
+"vulputate.", "Duis", "dictum", "justo", "sagittis", "tortor.", "Suspedisse",
+"placerat.", "am", "faucibus", "eros", "eget", "odio.", "Proi", "et",
+"lectus.", "uc", "massa", "ligula,", "vulputate", "eu,", "mattis", "ac,",
+"euismod", "ec,", "isl.", "ullam", "sit", "amet", "turpis", "eu", "ura",
+"elemetum", "auctor.", "Pelletesque", "lobortis", "orare", "justo.",
+"Suspedisse", "metus", "felis,", "iterdum", "ac,", "placerat", "at,",
+"frigilla", "mollis,", "erat.", "ullam", "sed", "odio", "eu", "mi", "egestas",
+"scelerisque.", "Pelletesque", "habitat", "morbi", "tristique", "seectus",
+"et", "etus", "et", "malesuada", "fames", "ac", "turpis", "egestas.", "Cras",
+"purus", "leo,", "aliquam", "eget,", "accumsa", "volutpat,", "eleifed",
+"vel,", "eros.", "I", "ultricies", "mattis", "turpis.Curabitur", "volutpat",
+"aliquam", "lorem.", "Sed", "at", "risus.", "Quisque", "tristique.",
+"Suspedisse", "mollis.", "I", "tellus", "quam,", "viverra", "eget,", "mollis",
+"vitae,", "bibedum", "sit", "amet,", "eim.", "Pelletesque", "frigilla",
+"tortor", "ac", "orci.", "Phasellus", "commodo", "porttitor", "elit.",
+"Maeceas", "ate", "orci,", "vehicula", "ticidut,", "lobortis", "eu,",
+"vehicula", "id,", "lorem.", "Quisque", "sapie", "ura,", "iaculis",
+"laoreet,", "digissim", "ac,", "adipiscig", "vitae,", "elit.", "ulla",
+"fermetum,", "leo", "ec", "posuere", "tempor,", "isi", "diam", "cursus",
+"arcu,", "at", "egestas", "ibh", "maga", "i", "odio.", "Mauris", "o", "diam",
+"sed", "dolor", "ultricies", "egestas.", "Aliquam", "erat", "volutpat.",
+"Quisque", "rhocus.", "ulla", "vitae", "arcu", "o", "pede", "scelerisque",
+"luctus.", "Pelletesque", "pretium", "massa.", "Fusce", "i", "leo", "eget",
+"eros", "fermetum", "ticidut.", "ulla", "velit", "risus,", "malesuada",
+"sed,", "auctor", "faucibus,", "porta", "sed,", "lacus.", "Aeea", "at",
+"eque.Doec", "o", "maga.", "Suspedisse", "cosequat", "orci", "sit", "amet",
+"velit.", "Ut", "est.", "Iteger", "sollicitudi,", "libero", "vitae",
+"gravida", "imperdiet,", "sem", "lorem", "tristique", "odio,", "sed",
+"pulviar", "tortor", "arcu", "vel", "mi.", "Aliquam", "erat", "volutpat.",
+"Vivamus", "tellus.", "Cras", "semper.", "Cras", "dictum", "dictum", "eros.",
+"Praeset", "et", "ulla", "i", "ulla", "ultricies", "auctor.", "Aeea",
+"tortor", "odio,", "ticidut", "sit", "amet,", "vestibulum", "id,", "covallis",
+"vel,", "pede.", "Vivamus", "volutpat", "elit", "i", "orci.", "Praeset",
+"arcu", "justo,", "adipiscig", "ac,", "commodo", "quis,", "scelerisque",
+"ac,", "libero.", "I", "odio", "ate,", "rutrum", "eu,", "aliquam", "vitae,",
+"ullamcorper", "et,", "sapie.", "Ut", "augue", "purus,", "pelletesque", "ut,",
+"auctor", "sit", "amet,", "laoreet", "eget,", "lectus.", "Vestibulum", "ate",
+"ipsum", "primis", "i", "faucibus", "orci", "luctus", "et", "ultrices",
+"posuere", "cubilia", "Curae;", "I", "orare,", "dui", "ac", "cosequat",
+"posuere,", "justo", "odio", "fermetum", "sem,", "eget", "covallis", "lacus",
+"quam", "o", "dui.", "Etiam", "mattis", "lacus", "cosectetuer", "pede",
+"veeatis", "eleifed.", "Cras", "quis", "tortor.uc", "libero", "erat,",
+"ultricies", "eget,", "ticidut", "sed,", "placerat", "eu,", "sapie.", "Cras",
+"posuere,", "pede", "ec", "dictum", "egestas,", "tortor", "orci", "faucibus",
+"lorem,", "eget", "iterdum", "mauris", "velit", "dapibus", "velit.", "ulla",
+"digissim", "imperdiet", "sapie.", "Ut", "tempus", "tellus.", "Pelletesque",
+"adipiscig", "varius", "tortor.", "Doec", "ligula", "dolor,", "pulviar",
+"ut,", "rutrum", "ac,", "dictum", "eget,", "diam.", "Sed", "at", "justo.",
+"Etiam", "orare", "scelerisque", "erat.", "am", "arcu.", "Iteger", "i",
+"orci.", "Fusce", "cosectetuer,", "isi", "o", "iterdum", "bladit,", "velit",
+"turpis", "codimetum", "tellus,", "i", "ullamcorper", "turpis", "leo", "at",
+"tellus.", "Doec", "velit.", "Phasellus", "augue.", "Doec", "et", "dui",
+"quis", "tortor", "fermetum", "eleifed.", "ulla", "facilisi.", "am",
+"veeatis", "suscipit", "ate.", "Aeea", "volutpat.", "Pelletesque",
+"ultricies", "accumsa", "orci.", "Pelletesque", "tellus", "diam,", "frigilla",
+"eu,", "cursus", "at,", "porta", "eget,", "justo.am", "dui.", "Suspedisse",
+"poteti.", "Vestibulum", "porttitor,", "purus", "a", "ullamcorper",
+"placerat,", "justo", "libero", "digissim", "augue,", "quis", "pelletesque",
+"ura", "tortor", "a", "orci.", "Duis", "eim.", "Aeea", "auctor,", "augue",
+"sed", "facilisis", "vulputate,", "ipsum", "lacus", "vestibulum", "metus,",
+"eu", "egestas", "felis", "diam", "a", "mauris.", "ulla", "imperdiet", "elit",
+"vel", "lectus.", "Ut", "ac", "ibh", "vel", "pede", "gravida", "hedrerit.",
+"Sed", "pelletesque,", "odio", "et", "eleifed", "cosequat,", "ulla", "ligula",
+"pretium", "ura,", "vel", "ultricies", "eros", "orci", "ut", "pede.", "Doec",
+"cosequat", "orare", "maga.", "Pelletesque", "ulla", "eim,", "bladit",
+"eget,", "sollicitudi", "ticidut,", "posuere", "vel,", "dolor.", "Phasellus",
+"facilisis", "arcu", "ut", "isi.", "Vivamus", "varius.", "Curabitur",
+"hedrerit,", "ligula", "sit", "amet", "molestie", "facilisis,", "ligula",
+"libero", "ultricies", "ulla,", "at", "bibedum", "libero", "dolor", "ticidut",
+"ibh.", "Doec", "pede", "tellus,", "pharetra", "pelletesque,", "euismod",
+"eget,", "placerat", "ut,", "dolor.Aeea", "mauris.", "Pelletesque", "sed",
+"ligula.", "Quisque", "faucibus", "tristique", "eque.", "Maeceas", "tempus",
+"auctor", "uc.", "Etiam", "et", "justo.", "Praeset", "ultrices", "odio", "id",
+"arcu", "aliquam", "pretium.", "Sed", "pulviar", "purus", "eu", "lorem.",
+"Suspedisse", "poteti.", "Aeea", "lacus.", "Vestibulum", "sit", "amet", "isi",
+"sed", "justo", "bibedum", "ticidut.", "Aliquam", "semper", "vestibulum",
+"quam.", "Sed."];
+
+var lipsumLong = ["sed justo bibedum ticidut. Aliquam semper vestibulum quam. Sed. Lorem ipsum dolor sit amet, consecte...", "facilisis pretium nulla. Sed semper accumsan quam. Donec vulputate auctor", "neque. Aenean arcu pede, consequat eget, molestie sed, bibendum quis,", "ante. Praesent sit amet odio ut ipsum suscipit faucibus. Vestibulum", "accumsan, nunc non adipiscing hendrerit, lorem arcu dignissim mi, vel", "blandit urna velit dictum leo. Aliquam ornare massa quis lacus.", "Cum s [...]
diff --git a/dojox/string/tests/notes.txt b/dojox/string/tests/notes.txt
new file mode 100644
index 0000000..71d7887
--- /dev/null
+++ b/dojox/string/tests/notes.txt
@@ -0,0 +1,153 @@
+notes:
+reference:
+Run with 100 words, 1000 iterations and overhead of 2
+    62 - concatOnce
+    73 - joinExisting
+    241 - plusForAlias
+    261 - plusFor
+    360 - concatFor
+    391 - joinForAlias
+    398 - concatForAlias
+    408 - joinFor
+    636 - plusForEach
+    763 - concatForEach
+    851 - joinForEach
+    4188 - builderReusedFor
+    4319 - builderFor
+    5155 - builderForEach
+    
+switch to for loop in append and ditch arraylike for array(r9607)
+Run with 100 words, 1000 iterations and overhead of 3
+    62 - concatOnce
+    72 - joinExisting
+    235 - concatForAlias
+    242 - plusForAlias
+    263 - plusFor
+    361 - concatFor
+    394 - joinForAlias
+    414 - joinFor
+    635 - plusForEach
+    757 - concatForEach
+    855 - joinForEach
+    2005 - builderReusedFor
+    2073 - builderFor
+    2830 - builderForEach
+    
+    
+inline append for array, remove string check
+Run with 100 words, 1000 iterations and overhead of 4
+    55 - concatOnce
+    75 - joinExisting
+    243 - plusForAlias
+    263 - plusFor
+    363 - concatFor
+    382 - concatForAlias
+    398 - joinForAlias
+    410 - joinFor
+    629 - plusForEach
+    754 - concatForEach
+    857 - joinForEach
+    1854 - builderReusedFor
+    1922 - builderFor
+    2714 - builderForEach
+    
+add string check back in using typeof
+Run with 100 words, 1000 iterations and overhead of 3
+    63 - concatOnce
+    72 - joinExisting
+    242 - plusForAlias
+    262 - plusFor
+    363 - concatFor
+    381 - concatForAlias
+    394 - joinForAlias
+    410 - joinFor
+    633 - plusForEach
+    773 - concatForEach
+    862 - joinForEach
+    1870 - builderReusedFor
+    1937 - builderFor
+    2702 - builderForEach
+    
+first cut less complex isArray
+Run with 100 words, 1000 iterations and overhead of 3
+    63 - concatOnce
+    73 - joinExisting
+    184 - plusFor
+    251 - plusForAlias
+    282 - concatFor
+    381 - concatForAlias
+    395 - joinForAlias
+    412 - joinFor
+    629 - plusForEach
+    770 - concatForEach
+    851 - joinForEach
+    2027 - builderReusedFor
+    2129 - builderFor
+    2898 - builderForEach
+    
+switch to typeof for array, put string check back in using typeof (r9610)
+Run with 100 words, 1000 iterations and overhead of 2
+    63 - concatOnce
+    77 - joinExisting
+    251 - plusForAlias
+    272 - plusFor
+    282 - concatFor
+    364 - concatForAlias
+    404 - joinForAlias
+    415 - joinFor
+    630 - plusForEach
+    766 - concatForEach
+    850 - joinForEach
+    1274 - builderReusedFor
+    1510 - builderFor
+    2108 - builderForEach
+
+remove arguments-style array support. only support an explicit array.    
+Run with 100 words, 1000 iterations and overhead of 2
+    63 - concatOnce
+    75 - joinExisting
+    186 - plusFor
+    207 - builderReusedOnce
+    255 - plusForAlias
+    283 - concatFor
+    306 - builderOnce
+    367 - concatForAlias
+    408 - joinForAlias
+    419 - joinFor
+    639 - plusForEach
+    767 - concatForEach
+    817 - builderReusedFor
+    865 - joinForEach
+    975 - builderFor
+    1562 - builderForEach
+    
+just running for tests
+Run with 100 words, 1000 iterations and overhead of 3
+    63 - concatOnce
+    203 - plusFor
+    204 - builderReusedOnce
+    303 - builderOnce
+    330 - joinFor
+    385 - concatFor
+    748 - builderFor
+    748 - builderReusedFor
+    
+remove array support in append
+Run with 1000 words, 1000 iterations and overhead of 2
+    382 - concatOnce
+    1951 - plusFor
+    2779 - builderFor
+    2883 - builderReusedFor
+    3038 - concatFor
+    3549 - joinFor
+
+add in appendArray support to match once, use += for append    
+Run with 1000 words, 1000 iterations and overhead of 3
+    379 - concatOnce
+    381 - builderReusedOnce
+    393 - builderOnce
+    2022 - plusFor
+    2862 - builderFor
+    2973 - builderReusedFor
+    3128 - concatFor
+    3548 - joinFor
\ No newline at end of file
diff --git a/dojox/string/tests/peller.html b/dojox/string/tests/peller.html
new file mode 100644
index 0000000..d526548
--- /dev/null
+++ b/dojox/string/tests/peller.html
@@ -0,0 +1,78 @@
+<html>
+<head>
+  <title>peller's test</title>
+  <script type="text/javascript" src="../../../dojo/dojo.js"></script>
+  <script type="text/javascript">
+  
+  var lq = [];
+  function log(s) {
+    lq.push(s);
+    //console.log(s);
+  }
+  
+  function dumpLog() {
+    dojo.forEach(lq, function(l) { console.log(l); });
+    lq = [];
+  }
+  
+  dojo.addOnLoad(function() {
+    forLoop();
+    forEachLoop();
+    forAgain();
+    forEachAgain();
+    dumpLog();
+  });
+  
+  function forLoop() {
+    var x=0;
+    var a = g_a;
+    var start=new Date();
+    for(var i=0;i<100000;i++){x=x+a[i];};
+    log("for loop elapsed:"+(new Date()-start)+" value="+x);
+  }
+  
+  function forEachLoop() {
+    var x=0;
+    var a = g_a;
+    var start=new Date();
+    dojo.forEach(a, function(v,i){x=x+a[i];});
+    log("dojo.forEach elapsed:"+(new Date()-start)+" value="+x);
+  }
+  
+  function forAgain(){
+    log("for results:");
+    var start=new Date();
+    var x=0;
+    for(var i=0;i<100000;i++){x=x+g_a[i];}
+    log("elapsed:"+(new Date()-start)+" value="+x);
+  }
+  function forEachAgain(){
+    log("forEach results:");
+    var a = g_a;
+    var x=0;
+    var start=new Date();
+    a.forEach(function(v,i){x=x+a[i];});
+    log("elapsed:"+(new Date()-start)+" value="+x);
+  }
+  
+  var g_a = new Array(100000);
+  for(var i=0; i<100000;i++){g_a[i]=i;}
+  
+  var start, x, i;
+  log("inline for results:");
+  start=new Date();
+  x=0;
+  for(i=0;i<100000;i++){x=x+g_a[i];}
+  log("elapsed:"+(new Date()-start)+" value="+x);
+
+  log("inline forEach results:");
+  start=new Date();
+  x=0;
+  g_a.forEach(function(v,i){x=x+g_a[i];});
+  log("elapsed:"+(new Date()-start)+" value="+x);
+  dumpLog();
+  </script>
+</head>
+<body>
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/string/tests/runTests.html b/dojox/string/tests/runTests.html
new file mode 100644
index 0000000..b3ea76d
--- /dev/null
+++ b/dojox/string/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.string.tests.string"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/string/tests/sprintf.js b/dojox/string/tests/sprintf.js
new file mode 100644
index 0000000..af239d1
--- /dev/null
+++ b/dojox/string/tests/sprintf.js
@@ -0,0 +1,273 @@
+dojo.provide("dojox.string.tests.sprintf");
+
+dojo.require("dojox.string.sprintf");
+dojo.require("dojo.string");
+
+
+// Mapping using the %(var) format
+
+// Flags:
+//	(space): Preceeds a positive number with a blank space
+//	+: Preceeds a positive number with a + sign
+//	0: Pads numbers using zeroes
+//	-: Left justify a number (they're right justified by default)
+//	#: Alternate view for the specifier
+
+tests.register("dojox.string.tests.sprintf", [
+	{
+		name: "Flag: (space)",
+		runTest: function(t){
+			var sprintf = dojox.string.sprintf;
+
+			t.is(" 42", sprintf("% d", 42));
+			t.is("-42", sprintf("% d", -42));
+			t.is("   42", sprintf("% 5d", 42));
+			t.is("  -42", sprintf("% 5d", -42));
+			t.is("             42", sprintf("% 15d", 42));
+			t.is("            -42", sprintf("% 15d", -42));
+		}
+	},
+	{
+		name: "Flag: +",
+		runTest: function(t){
+			var sprintf = dojox.string.sprintf;
+
+			t.is("+42", sprintf("%+d", 42));
+			t.is("-42", sprintf("%+d", -42));
+			t.is("  +42", sprintf("%+5d", 42));
+			t.is("  -42", sprintf("%+5d", -42));
+			t.is("            +42", sprintf("%+15d", 42));
+			t.is("            -42", sprintf("%+15d", -42));
+		}
+	},
+	{
+		name: "Flag: 0",
+		runTest: function(t){
+			var sprintf = dojox.string.sprintf;
+
+			t.is("42", sprintf("%0d", 42));
+			t.is("-42", sprintf("%0d", -42));
+			t.is("00042", sprintf("%05d", 42));
+			t.is("00-42", sprintf("%05d", -42));
+			t.is("000000000000042", sprintf("%015d", 42));
+			t.is("000000000000-42", sprintf("%015d", -42));
+		}
+	},
+	{
+		name: "Flag: -",
+		runTest: function(t){
+			var sprintf = dojox.string.sprintf;
+
+			t.is("42", sprintf("%-d", 42));
+			t.is("-42", sprintf("%-d", -42));
+			t.is("42   ", sprintf("%-5d", 42));
+			t.is("-42  ", sprintf("%-5d", -42));
+			t.is("42             ", sprintf("%-15d", 42));
+			t.is("-42            ", sprintf("%-15d", -42));
+
+			t.is("42", sprintf("%-0d", 42));
+			t.is("-42", sprintf("%-0d", -42));
+			t.is("42   ", sprintf("%-05d", 42));
+			t.is("-42  ", sprintf("%-05d", -42));
+			t.is("42             ", sprintf("%-015d", 42));
+			t.is("-42            ", sprintf("%-015d", -42));
+
+			t.is("42", sprintf("%0-d", 42));
+			t.is("-42", sprintf("%0-d", -42));
+			t.is("42   ", sprintf("%0-5d", 42));
+			t.is("-42  ", sprintf("%0-5d", -42));
+			t.is("42             ", sprintf("%0-15d", 42));
+			t.is("-42            ", sprintf("%0-15d", -42));
+		}
+	},
+	{
+		name: "Precision",
+		runTest: function(t){
+			var sprintf = dojox.string.sprintf;
+
+			t.is("42", sprintf("%d", 42.8952));
+			t.is("42", sprintf("%.2d", 42.8952)); // Note: the %d format is an int
+			t.is("42", sprintf("%.2i", 42.8952));
+			t.is("42.90", sprintf("%.2f", 42.8952));
+			t.is("42.90", sprintf("%.2F", 42.8952));
+			t.is("42.8952000000", sprintf("%.10f", 42.8952));
+			t.is("42.90", sprintf("%1.2f", 42.8952));
+			t.is(" 42.90", sprintf("%6.2f", 42.8952));
+			t.is("042.90", sprintf("%06.2f", 42.8952));
+			t.is("+42.90", sprintf("%+6.2f", 42.8952));
+			t.is("42.8952000000", sprintf("%5.10f", 42.8952));
+		}
+	},
+	{
+		name: "Bases",
+		runTest: function(t){
+			var sprintf = dojox.string.sprintf;
+
+			t.is("\x7f", sprintf("%c", 0x7f));
+
+			var error = false;
+			try {
+				sprintf("%c", -100);
+			}catch(e){
+				t.is("invalid character code passed to %c in sprintf", e.message);
+				error = true;
+			}
+			t.t(error);
+
+			error = false;
+			try {
+				sprintf("%c", 0x200000);
+			}catch(e){
+				t.is("invalid character code passed to %c in sprintf", e.message);
+				error = true;
+			}
+			t.t(error);
+		}
+	},
+	{
+		name: "Mapping",
+		runTest: function(t){
+			var sprintf = dojox.string.sprintf;
+
+			// %1$s format
+			t.is("%1$", sprintf("%1$"));
+			t.is("%0$s", sprintf("%0$s"));
+			t.is("Hot Pocket", sprintf("%1$s %2$s", "Hot", "Pocket"));
+			t.is("12.0 Hot Pockets", sprintf("%1$.1f %2$s %3$ss", 12, "Hot", "Pocket"));
+			t.is(" 42", sprintf("%1$*.f", "42", 3));
+
+			error = false;
+			try {
+				sprintf("%2$*s", "Hot Pocket");
+			}catch(e){
+				t.is("got 1 printf arguments, insufficient for '%2$*s'", e.message);
+				error = true;
+			}
+			t.t(error);
+
+			// %(map)s format
+			t.is("%(foo", sprintf("%(foo", {}));
+			t.is("Hot Pocket", sprintf("%(temperature)s %(crevace)s", {
+				temperature: "Hot",
+				crevace: "Pocket"
+			}));
+			t.is("12.0 Hot Pockets", sprintf("%(quantity).1f %(temperature)s %(crevace)ss", {
+				quantity: 12,
+				temperature: "Hot",
+				crevace: "Pocket"
+			}));
+
+			var error = false;
+			try {
+				sprintf("%(foo)s", 42);
+			}catch(e){
+				t.is("format requires a mapping", e.message);
+				error = true;
+			}
+			t.t(error);
+
+			error = false;
+			try {
+				sprintf("%(foo)s %(bar)s", "foo", 42);
+			}catch(e){
+				t.is("format requires a mapping", e.message);
+				error = true;
+			}
+			t.t(error);
+
+			error = false;
+			try {
+				sprintf("%(foo)*s", {
+					foo: "Hot Pocket"
+				});
+			}catch(e){
+				t.is("* width not supported in mapped formats", e.message);
+				error = true;
+			}
+			t.t(error);
+		}
+	},
+	{
+		name: "Positionals",
+		runTest: function(t){
+			var sprintf = dojox.string.sprintf;
+
+			t.is(" foo", sprintf("%*s", "foo", 4));
+			t.is("      3.14", sprintf("%*.*f", 3.14159265, 10, 2));
+			t.is("0000003.14", sprintf("%0*.*f", 3.14159265, 10, 2));
+			t.is("3.14      ", sprintf("%-*.*f", 3.14159265, 10, 2));
+
+			var error = false;
+			try {
+				sprintf("%*s", "foo", "bar");
+			}catch(e){
+				t.is("the argument for * width at position 2 is not a number in %*s", e.message);
+				error = true;
+			}
+			t.t(error);
+
+			error = false;
+			try {
+				sprintf("%10.*f", "foo", 42);
+			}catch(e){
+				t.is("format argument 'foo' not a float; parseFloat returned NaN", e.message);
+				error = true;
+			}
+			t.t(error);
+		}
+	},
+	{
+		name: "vs. Formatter",
+		runTest: function(t){
+			var sprintf = dojox.string.sprintf;
+
+			for(var i = 0; i < 1000; i++){
+				sprintf("%d %s Pockets", i, "Hot");
+			}
+		}
+	},
+	{
+		name: "Formatter",
+		runTest: function(t){
+			var Formatter = dojox.string.sprintf.Formatter;
+
+			var str = new Formatter("%d %s Pockets");
+			for(var i = 0; i < 1000; i++){
+				str.format(i, "Hot");
+			}
+		}
+	},
+	{
+		name: "Miscellaneous",
+		runTest: function(t) {
+			var sprintf = dojox.string.sprintf;
+
+			t.is("+hello+", sprintf("+%s+", "hello"));
+			t.is("+10+", sprintf("+%d+", 10));
+			t.is("a", sprintf("%c", "a"));
+			t.is('"', sprintf("%c", 34));
+			t.is('$', sprintf("%c", 36));
+			t.is("10", sprintf("%d", 10));
+
+			var error = false;
+			try {
+				sprintf("%s%s", 42);
+			}catch(e){
+				t.is("got 1 printf arguments, insufficient for '%s%s'", e.message);
+				error = true;
+			}
+			t.t(error);
+
+			error = false;
+			try {
+				sprintf("%c");
+			}catch(e){
+				t.is("got 0 printf arguments, insufficient for '%c'", e.message);
+				error = true;
+			}
+			t.t(error);
+
+			t.is("%10", sprintf("%10", 42));
+		}
+	}
+]);
\ No newline at end of file
diff --git a/dojox/string/tests/string.js b/dojox/string/tests/string.js
new file mode 100644
index 0000000..fe265db
--- /dev/null
+++ b/dojox/string/tests/string.js
@@ -0,0 +1,7 @@
+dojo.provide("dojox.string.tests.string");
+
+try{
+	dojo.require("dojox.string.tests.Builder");
+	dojo.require("dojox.string.tests.sprintf");
+	dojo.require("dojox.string.tests.BidiComplex");
+} catch(e){ }
diff --git a/dojox/string/tests/test_BidiComplex.html b/dojox/string/tests/test_BidiComplex.html
new file mode 100644
index 0000000..aee94e2
--- /dev/null
+++ b/dojox/string/tests/test_BidiComplex.html
@@ -0,0 +1,60 @@
+<html>
+	<head>
+		<title></title>
+		<meta name="vs_snapToGrid" content="True">
+		<meta name="vs_showGrid" content="True">
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script>
+		<script language="javascript" type="text/javascript">
+			dojo.require("dojox.string.BidiComplex");
+			
+			function change(select){
+			dojox.string.BidiComplex.attachInput(document.getElementById("ctext"), select.value);
+			}
+		</script>
+	</head>
+	<body>
+		<DIV ms_positioning="FlowLayout" id="DIV1">
+			<TABLE border="0" cellSpacing="0" cellPadding="0" width="100" height="100" ms_1d_layout="TRUE">
+				<TR>
+					<TD>
+						<TABLE border="0" cellSpacing="0" cellPadding="1" width="608" height="192">
+							<TR>
+								<td width="197">
+									Complex Expression Pattern
+								</td>
+								<TD>
+									<SELECT ID="Type" NAME="Type" onchange="change(this)">
+										<OPTION selected value="FILE_PATH">FILE_PATH</OPTION>
+										<OPTION value="URL">URL</OPTION>
+										<OPTION value="EMAIL">EMAIL</OPTION>
+										<OPTION value="XPATH">XPATH</OPTION>
+									</SELECT>
+								</TD>
+							</TR>
+							<TR>
+								<TD width="197">
+									Original Complex Bidi Text Display
+								</TD>
+								<TD>
+									<INPUT id="nText" name='nText' cols="21" rows="1"> </INPUT>
+								</TD>
+							<TR>
+								<TD width="197">
+									Fixed Complex Bidi Text Display
+								</TD>
+								<td>
+									<INPUT id="ctext" name='nText' cols="21" rows="1"> </INPUT>
+								</td>
+							</TR>
+						</TABLE>
+					</TD>
+				</TR>
+			</TABLE>
+		</DIV>
+		<script type="text/javascript">
+			//var co = new dojox.string.BidiComplex();
+			
+			dojox.string.BidiComplex.attachInput(document.getElementById("ctext"), "FILE_PATH");
+		</script>
+	</body>
+</html>
diff --git a/dojox/string/tokenize.js b/dojox/string/tokenize.js
index c3c98d0..7dc7c12 100644
--- a/dojox/string/tokenize.js
+++ b/dojox/string/tokenize.js
@@ -1,40 +1,38 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.string.tokenize"]){
-dojo._hasResource["dojox.string.tokenize"]=true;
 dojo.provide("dojox.string.tokenize");
-dojox.string.tokenize=function(_1,re,_2,_3){
-var _4=[];
-var _5,_6,_7=0;
-while(_5=re.exec(_1)){
-_6=_1.slice(_7,re.lastIndex-_5[0].length);
-if(_6.length){
-_4.push(_6);
-}
-if(_2){
-if(dojo.isOpera){
-var _8=_5.slice(0);
-while(_8.length<_5.length){
-_8.push(null);
-}
-_5=_8;
-}
-var _9=_2.apply(_3,_5.slice(1).concat(_4.length));
-if(typeof _9!="undefined"){
-_4.push(_9);
-}
-}
-_7=re.lastIndex;
-}
-_6=_1.slice(_7);
-if(_6.length){
-_4.push(_6);
-}
-return _4;
-};
-}
+
+dojox.string.tokenize = function(/*String*/ str, /*RegExp*/ re, /*Function?*/ parseDelim, /*Object?*/ instance){
+	// summary:
+	//		Split a string by a regular expression with the ability to capture the delimeters
+	// parseDelim:
+	//		Each group (excluding the 0 group) is passed as a parameter. If the function returns
+	//		a value, it's added to the list of tokens.
+	// instance:
+	//		Used as the "this" instance when calling parseDelim
+	var tokens = [];
+	var match, content, lastIndex = 0;
+	while(match = re.exec(str)){
+		content = str.slice(lastIndex, re.lastIndex - match[0].length);
+		if(content.length){
+			tokens.push(content);
+		}
+		if(parseDelim){
+			if(dojo.isOpera){
+				var copy = match.slice(0);
+				while(copy.length < match.length){
+					copy.push(null);
+				}
+				match = copy;
+			}
+			var parsed = parseDelim.apply(instance, match.slice(1).concat(tokens.length));
+			if(typeof parsed != "undefined"){
+				tokens.push(parsed);
+			}
+		}
+		lastIndex = re.lastIndex;
+	}
+	content = str.slice(lastIndex);
+	if(content.length){
+		tokens.push(content);
+	}
+	return tokens;
+}
\ No newline at end of file
diff --git a/dojox/testing/DocTest.js b/dojox/testing/DocTest.js
index 50d6575..56f6e1b 100644
--- a/dojox/testing/DocTest.js
+++ b/dojox/testing/DocTest.js
@@ -1,89 +1,277 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.testing.DocTest"]){
-dojo._hasResource["dojox.testing.DocTest"]=true;
 dojo.provide("dojox.testing.DocTest");
 dojo.require("dojo.string");
-dojo.declare("dojox.testing.DocTest",null,{errors:[],getTests:function(_1){
-var _2=dojo.moduleUrl(_1).path;
-var _3=_2.substring(0,_2.length-1)+".js";
-var _4=dojo.xhrGet({url:_3,handleAs:"text"});
-var _5=dojo._getText(_3);
-return this._getTestsFromString(_5,true);
-},getTestsFromString:function(_6){
-return this._getTestsFromString(_6,false);
-},_getTestsFromString:function(_7,_8){
-var _9=dojo.hitch(dojo.string,"trim");
-var _a=_7.split("\n");
-var _b=_a.length;
-var _c=[];
-var _d={commands:[],expectedResult:[],line:null};
-for(var i=0;i<_b+1;i++){
-var l=_9(_a[i]||"");
-if((_8&&l.match(/^\/\/\s+>>>\s.*/))||l.match(/^\s*>>>\s.*/)){
-if(!_d.line){
-_d.line=i+1;
-}
-if(_d.expectedResult.length>0){
-_c.push({commands:_d.commands,expectedResult:_d.expectedResult.join("\n"),line:_d.line});
-_d={commands:[],expectedResult:[],line:i+1};
-}
-l=_8?_9(l).substring(2,l.length):l;
-l=_9(l).substring(3,l.length);
-_d.commands.push(_9(l));
-}else{
-if((!_8||l.match(/^\/\/\s+.*/))&&_d.commands.length&&_d.expectedResult.length==0){
-l=_8?_9(l).substring(3,l.length):l;
-_d.expectedResult.push(_9(l));
-}else{
-if(_d.commands.length>0&&_d.expectedResult.length){
-if(!_8||l.match(/^\/\/\s*$/)){
-_c.push({commands:_d.commands,expectedResult:_d.expectedResult.join("\n"),line:_d.line});
-}
-if(_8&&!l.match(/^\/\//)){
-_c.push({commands:_d.commands,expectedResult:_d.expectedResult.join("\n"),line:_d.line});
-}
-_d={commands:[],expectedResult:[],line:0};
-}
-}
-}
-}
-return _c;
-},run:function(_e){
-this.errors=[];
-var _f=this.getTests(_e);
-if(_f){
-this._run(_f);
-}
-},_run:function(_10){
-var len=_10.length;
-this.tests=len;
-var oks=0;
-for(var i=0;i<len;i++){
-var t=_10[i];
-var res=this.runTest(t.commands,t.expectedResult);
-var msg="Test "+(i+1)+": ";
-var _11=t.commands.join(" ");
-_11=(_11.length>50?_11.substr(0,50)+"...":_11);
-if(res.success){
-oks+=1;
-}else{
-this.errors.push({commands:t.commands,actual:res.actualResult,expected:t.expectedResult});
-console.error(msg+"Failed: "+_11,{commands:t.commands,actualResult:res.actualResult,expectedResult:t.expectedResult});
-}
-}
-},runTest:function(_12,_13){
-var ret={success:false,actualResult:null};
-var _14=_12.join("\n");
-ret.actualResult=eval(_14);
-if((String(ret.actualResult)==_13)||(dojo.toJson(ret.actualResult)==_13)||((_13.charAt(0)=="\"")&&(_13.charAt(_13.length-1)=="\"")&&(String(ret.actualResult)==_13.substring(1,_13.length-1)))){
-ret.success=true;
-}
-return ret;
-}});
-}
+
+dojo.declare(
+	"dojox.testing.DocTest",
+	null,
+	{
+		//	summary:
+		//		This class executes doctests.
+		//	description:
+		//		DocTests are tests that are defined inside the comment.
+		//		A doctest looks as if it was copied from the shell (which it mostly is).
+		//		A doctest is executed when the following conditions match:
+		//		1) all lines are comments
+		//		2) the line always starts with spaces/tabs followed by "//"
+		//		   and at least one space
+		//		3) the line(s) of the test to execute starts with ">>>"
+		//		   preceeded by what is described in 2)
+		//		4) the first line after 3) starting without ">>>" is the exptected result.
+		//		   preceeded by what is described in 2)
+		//		5) the test sequence is terminated by an empty line, or the next
+		//		   test in the following line, or a new line that does not start as described in 2)
+		//		   (simple said: is not a comment)
+		//		   preceeded by what is described in 2)
+		//
+		//		I.e. the following is a simple doctest, that will actually also be run
+		//		if you run this class against this file here:
+		//		>>> 1+1 // A simple test case. Terminated by an empty line
+		//		2
+		//
+		//		>>> 1==2
+		//		false
+		//		>>> "a"+"b" // Also without the empty line before, this is a new test.
+		//		"ab"
+		//
+		//		>>> var anything = "anything" // Multiple commands for one test.
+		//		>>> "something"==anything
+		//		false
+		//
+		//		DocTests are great for inline documenting a class or method, they also
+		//		are very helpful in understanding what the class/method actually does.
+		//		They don't make sense everywhere, but sometimes they are really handy.
+
+
+		//	TODO:
+		//		-	using console.log() in a test prints something on the
+		//			console (if you do it on the console) but its not accepted
+		//			yet to be the test result, may be override console.log!?
+		//			i.e. here i wanted to: dojo.forEach(["one", 2],
+		//			function(el, index) {console.log(el, index)}) that works on
+		//			the console, but not as a docTest :-(
+		//		-	surround the eval for each test case singlely with a
+		//			try-catch, to to catch syntax errors etc (though the
+		//			shouldn't happen if you copy the test from the shell :-))
+	
+		
+		errors: [],
+		
+		getTests:function(/*String*/moduleName){
+			// summary: Extract the tests from the given module or string.
+			// examples:
+			// 		>>> dojo.isArray(new dojox.testing.DocTest().getTests("dojox.testing.DocTest")) // Use the module name to extract the tests from.
+			//		true
+			var path = dojo.moduleUrl(moduleName).path;
+			// TODO:
+			//		this needs to be done better, this is pretty simple and
+			//		surely not dummy proof
+			var file = path.substring(0, path.length-1)+".js";
+			var xhr = dojo.xhrGet({url:file, handleAs:"text"});
+			// Make loading synchronously, mainly so we can use it in doh.
+			var data = dojo._getText(file);
+			return this._getTestsFromString(data, true);
+		},
+		
+		getTestsFromString:function(/*String*/data){
+			// examples:
+			//		>>> (new dojox.testing.DocTest().getTestsFromString(">>> 1+1\n2\n>>> 2+2\n4")).length // Do tests from strings get detected properly?
+			//		2
+			return this._getTestsFromString(data, false);
+		},
+		
+		_getTestsFromString:function(/*String*/data, /*Boolean*/insideComments){
+			// summary: Parse the given string for tests.
+			// insideComments: Boolean, if false "data" contains only the pure tests, comments already stripped.
+			var trim = dojo.hitch(dojo.string, "trim");
+			var lines = data.split("\n");
+			var len = lines.length;
+			var tests = [];
+			var test = {
+				commands: [],
+				expectedResult: [],
+				line: null
+			};
+			for(var i=0; i<len+1; i++){
+				// Trim the line, so we don't have to worry about leading
+				// spaces or tabs, bla bla ...
+				var l = trim(lines[i] || ""); // The '|| ""' makes sure tests that have no preceeding \n are taken into account too.
+				// TODO:
+				//		detect tests that dont match the condition: commands,
+				//		result, empty line. esp the empty line might be missing
+				//		or be tolerant and accept a new test starting on the
+				//		next line, which would allow to omit the empty line!?
+				if((insideComments && l.match(/^\/\/\s+>>>\s.*/)) || l.match(/^\s*>>>\s.*/)){
+					if(!test.line){
+						test.line = i+1;
+					}
+					// Find the test commands.
+					if(test.expectedResult.length>0){
+						// Start a new test right after the expected result,
+						// without an empty line.
+						tests.push({
+							commands: test.commands,
+							expectedResult: test.expectedResult.join("\n"),
+							line: test.line
+						});
+						test = {commands:[], expectedResult:[], line:i+1};
+					}
+					l = insideComments ? trim(l).substring(2, l.length) : l; // Remove the leading slashes.
+					l = trim(l).substring(3, l.length); // Remove the ">>>".
+					test.commands.push(trim(l));
+				}else if((!insideComments || l.match(/^\/\/\s+.*/)) && test.commands.length && test.expectedResult.length==0){
+					// Detect the lines after the ">>>"-lines, the exptected result.
+					l = insideComments ? trim(l).substring(3, l.length) : l; // Remove the leading slashes.
+					test.expectedResult.push(trim(l));
+				}else if(test.commands.length>0 && test.expectedResult.length){
+					if(!insideComments || l.match(/^\/\/\s*$/)){
+						// Detect the empty line.
+						tests.push({
+							commands: test.commands,
+							expectedResult: test.expectedResult.join("\n"),
+							line: test.line
+						});
+					}
+					if(insideComments && !l.match(/^\/\//)){
+						// If the next line is not a comment at all (doesn't start with "//").
+						tests.push({
+							commands: test.commands,
+							expectedResult: test.expectedResult.join("\n"),
+							line:test.line
+						});
+					}
+					test = { 
+						commands: [], 
+						expectedResult: [],
+						line:0
+					};
+				}
+			}
+			return tests;
+		},
+		
+		run: function(moduleName){
+			//	summary:
+			//		Run the doctests in the module given.
+			//	example:
+			//		doctest = new dojox.testing.DocTest();
+			//		doctest.run("dojox.testing.DocTest");
+			//		doctest.errors should finally be an empty array.
+			//		// The above is not a doctest, because it just would
+			//		//	execute itself in a never ending loop.
+			//
+			//		>>> true==true // Test a new line terminating the test.
+			//		true
+			//
+			//		>>> true==true // Test a new test terminating the test.
+			//		true
+			//		>>> true==true // Test a "not a comment"-line, especially an empty line terminating the test.
+			//		true
+
+			//		Make sure the result as printed on the console is the same as what
+			//		is returned by the test. An array is printed as follows on the console.
+			//		>>> [1,2,3,4]
+			//		[1,2,3,4]
+			//
+			//		Test a "not a comment"-line, with some real code(!) terminating the test.
+			//		This used to be a bug, so make sure the line below the test is real
+			//		from this method! Don't write a test after it, always above!
+			//		>>> true==true // Test code on new line terminating the test.
+			//		true
+	
+			this.errors = [];
+			
+			var tests = this.getTests(moduleName);
+			if(tests){
+				this._run(tests);
+			}
+		},
+		
+		_run: function(/*Array*/tests){
+			//	summary:
+			//		Each element in the array contains the test in the first element, 
+			//		and the expected result in the second element.
+			//	tests:
+			//		Make sure that the types are compared properly. There used to be
+			//		the bug that a return value false was compared to "false" which
+			//		made the test fail. This is fixed and should be verified by the
+			//		following tests.
+			//		>>> false
+			//		false
+			//
+			//		>>> "false"
+			//		"false"
+			//
+			//		>>> true
+			//		true
+			//
+			//		>>> 1
+			//		1
+			//
+			//		>>> "s"
+			//		"s"
+			//
+			//		>>> dojo.toJson({one:1})
+			//		"{"one":1}"
+			//
+			var len = tests.length;
+			this.tests = len;
+			var oks = 0;
+			for(var i=0; i<len; i++){
+				var t = tests[i];
+				var res = this.runTest(t.commands, t.expectedResult);
+				var msg = "Test "+(i+1)+": ";
+				var viewCommands = t.commands.join(" ");
+				// Show the first part of the test command.
+				viewCommands = (viewCommands.length > 50 ? 
+								viewCommands.substr(0,50) + "..." : 
+								viewCommands
+				);
+				if(res.success){
+					// the last if-condition, dojo.toJson() adds a quote sign "
+					// before and after the result, may be we remove it and
+					// test the result again
+					console.info(msg+"OK: "+viewCommands);
+					oks += 1;
+				}else{
+					this.errors.push({
+						commands: t.commands,
+						actual: res.actualResult,
+						expected: t.expectedResult
+					});
+					console.error(msg+"Failed: "+viewCommands, {
+						commands: t.commands,
+						actualResult: res.actualResult,
+						expectedResult: t.expectedResult
+					});
+				}
+			}
+			console.info(len+" tests ran.", oks+" Success,", this.errors.length+" Errors");
+		},
+		
+		runTest: function(commands, expected){
+			var ret = { 
+				success: false,
+				actualResult: null
+			};
+			// Concat multiple commands with new lines, so "//" comments at
+			// the end of a line don't deactivate the next line (which it
+			// would if we only concatenated with ";").
+			var cmds = commands.join("\n");
+			ret.actualResult = eval(cmds);
+			if( (String(ret.actualResult)==expected) ||
+				(dojo.toJson(ret.actualResult)==expected) || 
+				(
+					(expected.charAt(0)=='"')&&
+					(expected.charAt(expected.length-1)=='"')&&
+					(String(ret.actualResult)==expected.substring(1, expected.length-1))
+				)
+			){
+				// the last if-condition, dojo.toJson() adds a quote sign "
+				// before and after the result, may be we remove it and test
+				// the result again
+				ret.success = true;
+			}
+			return ret;
+		}
+	}
+);
\ No newline at end of file
diff --git a/dojox/testing/tests/DocTest.js b/dojox/testing/tests/DocTest.js
new file mode 100644
index 0000000..bb06a15
--- /dev/null
+++ b/dojox/testing/tests/DocTest.js
@@ -0,0 +1,6 @@
+dojo.provide("dojox.testing.tests.DocTest");
+
+dojo.require("dojox.testing.DocTest");
+dojo.require("dojo.string");
+
+tests.registerDocTests("dojox.testing.DocTest");
\ No newline at end of file
diff --git a/dojox/testing/tests/module.js b/dojox/testing/tests/module.js
new file mode 100644
index 0000000..40c945c
--- /dev/null
+++ b/dojox/testing/tests/module.js
@@ -0,0 +1,7 @@
+dojo.provide("dojox.testing.tests.module");
+
+try{
+	dojo.require("dojox.testing.tests.DocTest");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/testing/tests/runTests.html b/dojox/testing/tests/runTests.html
new file mode 100644
index 0000000..cff6e2c
--- /dev/null
+++ b/dojox/testing/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.testing.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/timing.js b/dojox/timing.js
index f2751a6..ebc43f7 100644
--- a/dojox/timing.js
+++ b/dojox/timing.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.timing"]){
-dojo._hasResource["dojox.timing"]=true;
 dojo.provide("dojox.timing");
-dojo.require("dojox.timing._base");
-}
+dojo.require("dojox.timing._base"); 
diff --git a/dojox/timing/Sequence.js b/dojox/timing/Sequence.js
index daca046..5e6a241 100644
--- a/dojox/timing/Sequence.js
+++ b/dojox/timing/Sequence.js
@@ -1,87 +1,147 @@
-/*
-	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
-*/
+dojo.provide("dojox.timing.Sequence");
+dojo.experimental("dojox.timing.Sequence"); 
 
+dojo.declare("dojox.timing.Sequence", null, {
+	// summary: 
+	//	This class provides functionality to really sequentialize 
+	//	function calls. You need to provide a list of functions and 
+	//	some parameters for each (like: pauseBefore) and they will
+	//	be run one after another. This can be very useful for slideshows
+	//	or alike things.
+	//
+	// description: 
+	//	This array will contain the sequence defines resolved, so that
+	// 	ie. repeat:10 will result in 10 elements in the sequence, so 
+	// 	the repeat handling is easier and we don't need to handle that
+	// 	many extra cases. Also the doneFunction, if given is added at the
+	// 	end of the resolved-sequences.
 
-if(!dojo._hasResource["dojox.timing.Sequence"]){
-dojo._hasResource["dojox.timing.Sequence"]=true;
-dojo.provide("dojox.timing.Sequence");
-dojo.experimental("dojox.timing.Sequence");
-dojo.declare("dojox.timing.Sequence",null,{_goOnPause:0,_running:false,constructor:function(){
-this._defsResolved=[];
-},go:function(_1,_2){
-this._running=true;
-dojo.forEach(_1,function(_3){
-if(_3.repeat>1){
-var _4=_3.repeat;
-for(var j=0;j<_4;j++){
-_3.repeat=1;
-this._defsResolved.push(_3);
-}
-}else{
-this._defsResolved.push(_3);
-}
-},this);
-var _5=_1[_1.length-1];
-if(_2){
-this._defsResolved.push({func:_2});
-}
-this._defsResolved.push({func:[this.stop,this]});
-this._curId=0;
-this._go();
-},_go:function(){
-if(!this._running){
-return;
-}
-var _6=this._defsResolved[this._curId];
-this._curId+=1;
-function _7(_8){
-var _9=null;
-if(dojo.isArray(_8)){
-if(_8.length>2){
-_9=_8[0].apply(_8[1],_8.slice(2));
-}else{
-_9=_8[0].apply(_8[1]);
-}
-}else{
-_9=_8();
-}
-return _9;
-};
-if(this._curId>=this._defsResolved.length){
-_7(_6.func);
-return;
-}
-if(_6.pauseAfter){
-if(_7(_6.func)!==false){
-setTimeout(dojo.hitch(this,"_go"),_6.pauseAfter);
-}else{
-this._goOnPause=_6.pauseAfter;
-}
-}else{
-if(_6.pauseBefore){
-var x=dojo.hitch(this,function(){
-if(_7(_6.func)!==false){
-this._go();
-}
-});
-setTimeout(x,_6.pauseBefore);
-}else{
-if(_7(_6.func)!==false){
-this._go();
-}
-}
-}
-},goOn:function(){
-if(this._goOnPause){
-setTimeout(dojo.hitch(this,"_go"),this._goOnPause);
-this._goOnPause=0;
-}else{
-this._go();
-}
-},stop:function(){
-this._running=false;
-}});
-}
+/*=====
+	// _defsResolved: Array
+	// 	The resolved sequence, for easier handling.
+	_defsResolved: [],
+=====*/
+
+	// This is the time to wait before goOn() calls _go(), which 
+	// mostly results from a pauseAfter for a function that returned
+	// false and is later continued by the external goOn() call.
+	// The time to wait needs to be waited in goOn() where the
+	// sequence is continued.
+
+	// _goOnPause: Integer
+	//	The pause to wait before really going on.
+	_goOnPause: 0,
+
+	_running: false,
+
+	constructor: function(){
+		this._defsResolved = [];
+	},
+
+	go: function(/* Array */defs, /* Function|Array? */doneFunction){
+		// summary: Run the passed sequence definition
+		//
+		// defs: Array
+		//		The sequence of actions
+		// doneFunction: Function|Array?
+		//		The function to call when done
+		this._running = true;
+		dojo.forEach(defs, function(cur){
+			if(cur.repeat > 1){
+				var repeat = cur.repeat;
+				for(var j = 0; j < repeat; j++){
+					cur.repeat = 1;
+					this._defsResolved.push(cur);
+				}
+			}else{
+				this._defsResolved.push(cur);
+			}
+		}, this);
+		var last = defs[defs.length - 1];
+		if(doneFunction){
+			this._defsResolved.push({ func: doneFunction });
+		}
+		// stop the sequence, this actually just sets this._running to false
+		this._defsResolved.push({ func: [this.stop, this] });
+		this._curId = 0;
+		this._go();
+	},
+
+	_go: function(){
+		// summary: Execute one task of this._defsResolved.
+
+		// if _running was set to false stop the sequence, this is the
+		// case when i.e. stop() was called.
+		if(!this._running){
+			return;
+		}
+		var cur = this._defsResolved[this._curId];
+		this._curId += 1;
+		// create the function to call, the func property might be an array, which means
+		// [function, context, parameter1, parameter2, ...]
+		function resolveAndCallFunc(func) {
+			var ret = null;
+			if(dojo.isArray(func)){
+				// Two elements might only be given when the function+context
+				// is given, this is nice for using this, ie: [this.func, this]
+				if(func.length>2){
+					ret = func[0].apply(func[1], func.slice(2));
+				}else{
+					ret = func[0].apply(func[1]);
+				}
+			}else{
+				ret = func();
+			}
+			return ret;
+		}
+
+		if(this._curId >= this._defsResolved.length){
+			resolveAndCallFunc(cur.func); // call the last function, since it is the doneFunction we dont need to handle pause stuff
+			// don't go on and call this._go() again, we are done
+			return;
+		}
+
+		if(cur.pauseAfter){
+			if(resolveAndCallFunc(cur.func) !== false){
+				setTimeout(dojo.hitch(this, "_go"), cur.pauseAfter);
+			}else{
+				this._goOnPause = cur.pauseAfter;
+			}
+		}else if(cur.pauseBefore){
+			var x = dojo.hitch(this,function(){
+				if(resolveAndCallFunc(cur.func) !== false){
+					this._go()
+				}
+			});
+			setTimeout(x, cur.pauseBefore);
+		}else{
+			if(resolveAndCallFunc(cur.func) !== false){
+				this._go();
+			}
+		}
+	},
+
+	goOn: function(){
+		// summary: This method just provides a hook from the outside, so that
+		//		an interrupted sequence can be continued.
+		if(this._goOnPause){
+			setTimeout(dojo.hitch(this, "_go"), this._goOnPause);
+			this._goOnPause = 0; // reset it, so if the next one doesnt set it we dont use the old pause
+		}else{ this._go(); }
+	},
+
+	stop: function(){
+		// summary:  Stop the currently running sequence.
+		//
+		// description: 
+		//		This can only interrupt the sequence not the last function that
+		//		had been started. If the last function was i.e. a slideshow
+		//		that is handled inside a function that you have given as
+		//		one sequence item it cant be stopped, since it is not controlled
+		//		by this object here. In this case it would be smarter to 
+		//		run the slideshow using a sequence object so you can also stop 
+		//		it using this method.
+		this._running = false;
+	}
+
+}); 
diff --git a/dojox/timing/Streamer.js b/dojox/timing/Streamer.js
index 6462f13..cc2ecf7 100644
--- a/dojox/timing/Streamer.js
+++ b/dojox/timing/Streamer.js
@@ -1,64 +1,90 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.timing.Streamer"]){
-dojo._hasResource["dojox.timing.Streamer"]=true;
 dojo.provide("dojox.timing.Streamer");
+
 dojo.require("dojox.timing._base");
-dojox.timing.Streamer=function(_1,_2,_3,_4,_5){
-var _6=this;
-var _7=[];
-this.interval=_3||1000;
-this.minimumSize=_4||10;
-this.inputFunction=_1||function(q){
-};
-this.outputFunction=_2||function(_8){
-};
-var _9=new dojox.timing.Timer(this.interval);
-var _a=function(){
-_6.onTick(_6);
-if(_7.length<_6.minimumSize){
-_6.inputFunction(_7);
-}
-var _b=_7.shift();
-while(typeof (_b)=="undefined"&&_7.length>0){
-_b=_7.shift();
-}
-if(typeof (_b)=="undefined"){
-_6.stop();
-return;
-}
-_6.outputFunction(_b);
-};
-this.setInterval=function(ms){
-this.interval=ms;
-_9.setInterval(ms);
-};
-this.onTick=function(_c){
-};
-this.start=function(){
-if(typeof (this.inputFunction)=="function"&&typeof (this.outputFunction)=="function"){
-_9.start();
-return;
-}
-throw new Error("You cannot start a Streamer without an input and an output function.");
-};
-this.onStart=function(){
-};
-this.stop=function(){
-_9.stop();
-};
-this.onStop=function(){
-};
-_9.onTick=this.tick;
-_9.onStart=this.onStart;
-_9.onStop=this.onStop;
-if(_5){
-_7.concat(_5);
-}
+
+dojox.timing.Streamer = function(
+	/* function */input, 
+	/* function */output, 
+	/* int */interval, 
+	/* int */minimum,
+	/* array */initialData
+){
+	//	summary
+	//	Streamer will take an input function that pushes N datapoints into a
+	//		queue, and will pass the next point in that queue out to an
+	//		output function at the passed interval; this way you can emulate
+	//		a constant buffered stream of data.
+	//	input: the function executed when the internal queue reaches minimumSize
+	//	output: the function executed on internal tick
+	//	interval: the interval in ms at which the output function is fired.
+	//	minimum: the minimum number of elements in the internal queue.
+
+	var self = this;
+	var queue = [];
+
+	//	public properties
+	this.interval = interval || 1000;
+	this.minimumSize = minimum || 10;	//	latency usually == interval * minimumSize
+	this.inputFunction = input || function(q){ };
+	this.outputFunction = output || function(point){ };
+
+	//	more setup
+	var timer = new dojox.timing.Timer(this.interval);
+	var tick = function(){
+		self.onTick(self);
+
+		if(queue.length < self.minimumSize){
+			self.inputFunction(queue);
+		}
+
+		var obj = queue.shift();
+		while(typeof(obj) == "undefined" && queue.length > 0){
+			obj = queue.shift();
+		}
+		
+		//	check to see if the input function needs to be fired
+		//	stop before firing the output function
+		//	TODO: relegate this to the output function?
+		if(typeof(obj) == "undefined"){
+			self.stop();
+			return;
+		}
+
+		//	call the output function.
+		self.outputFunction(obj);
+	};
+
+	this.setInterval = function(/* int */ms){
+		//	summary
+		//	sets the interval in milliseconds of the internal timer
+		this.interval = ms;
+		timer.setInterval(ms);
+	};
+
+	this.onTick = function(/* dojox.timing.Streamer */obj){ };
+	// wrap the timer functions so that we can connect to them if needed.
+	this.start = function(){
+		//	summary
+		//	starts the Streamer
+		if(typeof(this.inputFunction) == "function" && typeof(this.outputFunction) == "function"){
+			timer.start();
+			return;
+		}
+		throw new Error("You cannot start a Streamer without an input and an output function.");
+	};
+	this.onStart = function(){ };
+	this.stop = function(){
+		//	summary
+		//	stops the Streamer
+		timer.stop();
+	};
+	this.onStop = function(){ };
+
+	//	finish initialization
+	timer.onTick = this.tick;
+	timer.onStart = this.onStart;
+	timer.onStop = this.onStop;
+	if(initialData){
+		queue.concat(initialData);
+	}
 };
-}
diff --git a/dojox/timing/ThreadPool.js b/dojox/timing/ThreadPool.js
index 89b46d0..7bd0637 100644
--- a/dojox/timing/ThreadPool.js
+++ b/dojox/timing/ThreadPool.js
@@ -1,142 +1,153 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.timing.ThreadPool"]){
-dojo._hasResource["dojox.timing.ThreadPool"]=true;
 dojo.provide("dojox.timing.ThreadPool");
 dojo.require("dojox.timing");
+
 dojo.experimental("dojox.timing.ThreadPool");
+
+//	dojox.timing.Timer is included as part of _base
+/********************************************************************
+	This is a port of the original System.Threading.ThreadPool from 
+	the f(m) class library.
+	
+	Donated to the Dojo toolkit by the author :)
+*********************************************************************/
 (function(){
-var t=dojox.timing;
-t.threadStates={UNSTARTED:"unstarted",STOPPED:"stopped",PENDING:"pending",RUNNING:"running",SUSPENDED:"suspended",WAITING:"waiting",COMPLETE:"complete",ERROR:"error"};
-t.threadPriorities={LOWEST:1,BELOWNORMAL:2,NORMAL:3,ABOVENORMAL:4,HIGHEST:5};
-t.Thread=function(fn,_1){
-var _2=this;
-this.state=t.threadStates.UNSTARTED;
-this.priority=_1||t.threadPriorities.NORMAL;
-this.lastError=null;
-this.func=fn;
-this.invoke=function(){
-_2.state=t.threadStates.RUNNING;
-try{
-fn(this);
-_2.state=t.threadStates.COMPLETE;
-}
-catch(e){
-_2.lastError=e;
-_2.state=t.threadStates.ERROR;
-}
-};
-};
-t.ThreadPool=new (function(_3,_4){
-var _5=this;
-var _6=_3;
-var _7=_6;
-var _8=_4;
-var _9=Math.floor((_8/2)/_6);
-var _a=[];
-var _b=new Array(_6+1);
-var _c=new dojox.timing.Timer();
-var _d=function(){
-var _e=_b[0]={};
-for(var i=0;i<_b.length;i++){
-window.clearTimeout(_b[i]);
-var _f=_a.shift();
-if(typeof (_f)=="undefined"){
-break;
-}
-_e["thread-"+i]=_f;
-_b[i]=window.setTimeout(_f.invoke,(_9*i));
-}
-_7=_6-(i-1);
-};
-this.getMaxThreads=function(){
-return _6;
-};
-this.getAvailableThreads=function(){
-return _7;
-};
-this.getTickInterval=function(){
-return _8;
-};
-this.queueUserWorkItem=function(fn){
-var _10=fn;
-if(_10 instanceof Function){
-_10=new t.Thread(_10);
-}
-var idx=_a.length;
-for(var i=0;i<_a.length;i++){
-if(_a[i].priority<_10.priority){
-idx=i;
-break;
-}
-}
-if(idx<_a.length){
-_a.splice(idx,0,_10);
-}else{
-_a.push(_10);
-}
-return true;
-};
-this.removeQueuedUserWorkItem=function(_11){
-if(_11 instanceof Function){
-var idx=-1;
-for(var i=0;i<_a.length;i++){
-if(_a[i].func==_11){
-idx=i;
-break;
-}
-}
-if(idx>-1){
-_a.splice(idx,1);
-return true;
-}
-return false;
-}
-var idx=-1;
-for(var i=0;i<_a.length;i++){
-if(_a[i]==_11){
-idx=i;
-break;
-}
-}
-if(idx>-1){
-_a.splice(idx,1);
-return true;
-}
-return false;
-};
-this.start=function(){
-_c.start();
-};
-this.stop=function(){
-_c.stop();
-};
-this.abort=function(){
-this.stop();
-for(var i=1;i<_b.length;i++){
-if(_b[i]){
-window.clearTimeout(_b[i]);
-}
-}
-for(var _12 in _b[0]){
-this.queueUserWorkItem(_12);
-}
-_b[0]={};
-};
-this.reset=function(){
-this.abort();
-_a=[];
-};
-this.sleep=function(_13){
-_c.stop();
-window.setTimeout(_c.start,_13);
-};
-_c.onTick=_5.invoke;
-})(16,5000);
+	var t=dojox.timing;
+	t.threadStates={ 
+		UNSTARTED:"unstarted", 
+		STOPPED:"stopped", 
+		PENDING:"pending", 
+		RUNNING:"running", 
+		SUSPENDED:"suspended", 
+		WAITING:"waiting", 
+		COMPLETE:"complete",
+		ERROR:"error"
+	};
+
+	//	Before rar says a word, we actually *use* these numbers for a purpose :)
+	t.threadPriorities={ 
+		LOWEST:1, 
+		BELOWNORMAL:2, 
+		NORMAL:3, 
+		ABOVENORMAL:4, 
+		HIGHEST:5 
+	};
+	
+	t.Thread=function(/* Function */fn, /* dojox.timing.threadPriorities? */priority){
+		var self=this;
+		this.state=t.threadStates.UNSTARTED;
+		this.priority=priority||t.threadPriorities.NORMAL;
+		this.lastError=null;
+		this.func=fn;	//	for lookup purposes.
+		this.invoke=function(){
+			self.state=t.threadStates.RUNNING;
+			try{
+				fn(this);
+				self.state=t.threadStates.COMPLETE;
+			}catch(e){
+				self.lastError=e;
+				self.state=t.threadStates.ERROR;
+			}
+		};
+	};
+
+	//	TODO: allow for changing of maxThreads and tick interval
+	t.ThreadPool=new (function(/* Number */mxthrs, /* Number */intvl){
+		var self=this;
+		var maxThreads=mxthrs;
+		var availableThreads=maxThreads;
+		var interval=intvl;
+		var fireInterval=Math.floor((interval/2)/maxThreads);
+		var queue=[];
+		var timers=new Array(maxThreads+1);
+		var timer=new dojox.timing.Timer();
+		var invoke=function(){
+			var tracker=timers[0]={};
+			for(var i=0; i<timers.length; i++){
+				window.clearTimeout(timers[i]);
+				var thread=queue.shift();
+				if(typeof(thread)=="undefined"){ break; }
+				tracker["thread-"+i]=thread;
+				timers[i]=window.setTimeout(thread.invoke,(fireInterval*i));
+			}
+			availableThreads=maxThreads-(i-1);
+		};
+
+		//	public methods
+		this.getMaxThreads=function(){ return maxThreads; };
+		this.getAvailableThreads=function(){ return availableThreads; };
+		this.getTickInterval=function(){ return interval; };
+		this.queueUserWorkItem=function(/* Function || dojox.timing.Thread */fn){
+			var item=fn;
+			if(item instanceof Function){
+				item=new t.Thread(item);
+			}
+			var idx=queue.length;
+			for(var i=0; i<queue.length; i++){
+				if(queue[i].priority<item.priority){
+					idx=i;
+					break;
+				}
+			}
+			if(idx<queue.length){
+				queue.splice(idx, 0, item);
+			} else {
+				queue.push(item);
+			}
+			return true;
+		};
+		this.removeQueuedUserWorkItem=function(/* Function || dojox.timing.Thread */item){
+			if(item instanceof Function){
+				var idx=-1;
+				for(var i=0; i<queue.length; i++){
+					if(queue[i].func==item){
+						idx=i;
+						break;
+					}
+				}
+				if(idx>-1){
+					queue.splice(idx,1);
+					return true;
+				}
+				return false;
+			}
+
+			var idx=-1;
+			for(var i=0; i<queue.length; i++){
+				if(queue[i]==item){
+					idx=i;
+					break;
+				}
+			}
+			if(idx>-1){
+				queue.splice(idx,1);
+				return true;
+			}
+			return false;
+		};
+		this.start=function(){ timer.start(); };
+		this.stop=function(){ timer.stop(); };
+		this.abort=function(){
+			this.stop();
+			for(var i=1; i<timers.length; i++){
+				if(timers[i]){
+					window.clearTimeout(timers[i]);
+				}
+			}
+			for(var thread in timers[0]){
+				this.queueUserWorkItem(thread);
+			}
+			timers[0]={};
+		};
+		this.reset=function(){
+			this.abort();
+			queue=[];
+		};
+		this.sleep=function(/* Number */nSleep){
+			timer.stop();
+			window.setTimeout(timer.start, nSleep);
+		};
+
+		//	dedicate the timer to us.
+		timer.onTick=self.invoke;
+	})(16, 5000);
 })();
-}
diff --git a/dojox/timing/_base.js b/dojox/timing/_base.js
index c056c92..90168ce 100644
--- a/dojox/timing/_base.js
+++ b/dojox/timing/_base.js
@@ -1,41 +1,54 @@
-/*
-	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
-*/
+dojo.provide("dojox.timing._base");
+dojo.experimental("dojox.timing"); 
 
+dojox.timing.Timer = function(/*int*/ interval){
+	// summary: Timer object executes an "onTick()" method repeatedly at a specified interval. 
+	//			repeatedly at a given interval.
+	// interval: Interval between function calls, in milliseconds.
+	this.timer = null;
+	this.isRunning = false;
+	this.interval = interval;
 
-if(!dojo._hasResource["dojox.timing._base"]){
-dojo._hasResource["dojox.timing._base"]=true;
-dojo.provide("dojox.timing._base");
-dojo.experimental("dojox.timing");
-dojox.timing.Timer=function(_1){
-this.timer=null;
-this.isRunning=false;
-this.interval=_1;
-this.onStart=null;
-this.onStop=null;
+	this.onStart = null;
+	this.onStop = null;
 };
-dojo.extend(dojox.timing.Timer,{onTick:function(){
-},setInterval:function(_2){
-if(this.isRunning){
-window.clearInterval(this.timer);
-}
-this.interval=_2;
-if(this.isRunning){
-this.timer=window.setInterval(dojo.hitch(this,"onTick"),this.interval);
-}
-},start:function(){
-if(typeof this.onStart=="function"){
-this.onStart();
-}
-this.isRunning=true;
-this.timer=window.setInterval(dojo.hitch(this,"onTick"),this.interval);
-},stop:function(){
-if(typeof this.onStop=="function"){
-this.onStop();
-}
-this.isRunning=false;
-window.clearInterval(this.timer);
-}});
-}
+
+dojo.extend(dojox.timing.Timer, {
+	onTick : function(){
+		// summary: Method called every time the interval passes.  Override to do something useful.
+	},
+		
+	setInterval : function(interval){
+		// summary: Reset the interval of a timer, whether running or not.
+		// interval: New interval, in milliseconds.
+		if (this.isRunning){
+			window.clearInterval(this.timer);
+		}
+		this.interval = interval;
+		if (this.isRunning){
+			this.timer = window.setInterval(dojo.hitch(this, "onTick"), this.interval);
+		}
+	},
+	
+	start : function(){
+		// summary: Start the timer ticking.
+		// description: Calls the "onStart()" handler, if defined.
+		// 				Note that the onTick() function is not called right away, 
+		//				only after first interval passes.
+		if (typeof this.onStart == "function"){
+			this.onStart();
+		}
+		this.isRunning = true;
+		this.timer = window.setInterval(dojo.hitch(this, "onTick"), this.interval);
+	},
+	
+	stop : function(){
+		// summary: Stop the timer.
+		// description: Calls the "onStop()" handler, if defined.
+		if (typeof this.onStop == "function"){
+			this.onStop();
+		}
+		this.isRunning = false;
+		window.clearInterval(this.timer);
+	}
+});
diff --git a/dojox/timing/doLater.js b/dojox/timing/doLater.js
index 76d7c8c..c908078 100644
--- a/dojox/timing/doLater.js
+++ b/dojox/timing/doLater.js
@@ -1,24 +1,42 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.timing.doLater"]){
-dojo._hasResource["dojox.timing.doLater"]=true;
 dojo.provide("dojox.timing.doLater");
-dojo.experimental("dojox.timing.doLater");
-dojox.timing.doLater=function(_1,_2,_3){
-if(_1){
-return false;
-}
-var _4=dojox.timing.doLater.caller,_5=dojox.timing.doLater.caller.arguments;
-_3=_3||100;
-_2=_2||dojo.global;
-setTimeout(function(){
-_4.apply(_2,_5);
-},_3);
-return true;
-};
+dojo.experimental("dojox.timing.doLater"); 
+
+dojox.timing.doLater = function(/*anything*/conditional,/*Object ?*/context, /* Number ? */interval){
+	// summary:
+	//		Check if a parameter is ready, and if not,
+	//		"do later". doLater will ping the parameter
+	//		until it evaluates to something (truthy).
+	//		It thens calls the caller with original
+	//		arguments, using the supplied context or 
+	//		window.
+	//	description:
+	//		dojox.timing.doLater(conditional) is testing if the call
+	//		should be done later. So it returns
+	//		true if the param is false. 
+	//	arguments:
+	//		conditional: anything
+	//			Can be a property that eventually gets set, or
+	//			an expression, method... anything that can be
+	//			evaluated.
+	//		context:	Object
+	//			The namespace where the call originated.
+	//			Defaults to global and anonymous functions
+	//		interval:	Number
+	//			Poll time to check conditional in Milliseconds 
+	// example:
+	//		| setTimeout(function(){
+	//		| 		if(dojox.timing.doLater(app.ready)){return;}
+	//		| 		console.log("Code is ready! anonymous.function SUCCESS")
+	//		| 	},700);
+	//
+	if(conditional){ return false; }  // Boolean
+	var callback = dojox.timing.doLater.caller,
+		args = dojox.timing.doLater.caller.arguments;
+	interval = interval || 100;
+	context = context || dojo.global;
+	
+	setTimeout(function(){
+		callback.apply(context, args);
+	},interval);
+	return true; // Boolean
 }
diff --git a/dojox/timing/tests/test_Sequence.html b/dojox/timing/tests/test_Sequence.html
new file mode 100644
index 0000000..1d0513d
--- /dev/null
+++ b/dojox/timing/tests/test_Sequence.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	
+	<title>dojox.timing.Sequence class</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true" ></script>
+	<script type="text/javascript" src="../Sequence.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.timing.Sequence"); 
+
+		var seqObj = null,
+			outputNode = null,
+			otherObj = null;
+
+		dojo.addOnLoad(function(){
+			outputNode = dojo.byId('logBox'); 
+			seqObj = new dojox.timing.Sequence({});
+		 	otherObj = new dojox.timing.Sequence({});
+		});
+
+		function runSequence(){
+			outputNode.innerHTML = ""; 
+			seqObj.go(seq, function() { logMsg('done') });
+			otherObj.go(otherSeq, function(){ console.log('other done'); });
+		};
+
+		function logMsg(msg){
+			outputNode.innerHTML += msg + "<br>"; 
+		}
+	
+		function showMessage(msg) {
+			logMsg(msg);
+		}
+
+		function returnWhenDone() {
+			logMsg("in returnWhenDone");
+			setTimeout(continueSequence, 1000);
+			return false;
+		}
+
+		function continueSequence() {
+		// continue the sequence run
+			seqObj.goOn();
+		}
+			// this is our example sequence array:
+		var seq = [
+			{ func: [showMessage, window, "i am first"], pauseAfter: 1000 },
+			{ func: [showMessage, window, "after 1000ms pause this should be seen"], pauseAfter: 2000 },
+			{ func: [showMessage, window, "another 2000ms pause and 1000ms pause before"], pauseAfter: 1000 },
+			{ func: [showMessage, window, "repeat 10 times and pause 100ms after"], repeat: 10, pauseAfter: 100 },
+			{ func: returnWhenDone } // no array, just a function to call 
+		];
+
+		var otherSeq = [
+			{ func: [dojo.hitch(console,"log","woot"), window, "woot2?"], pauseAfter: 1000, repeat:20 }
+		];
+
+	</script>
+</head>
+<body class="tundra">
+
+	<h1>dojox.timing.Sequence tests</h1>
+
+	<br>(example code in page source)<br>
+	<input type="button" onClick="runSequence()" value="Run Sequence">
+
+	<h3>Sequence output:</h3>
+	<div id="logBox" style="width:420px; height:250px; overflow:auto; border:1px solid #ccc;">
+	</div>
+
+	<p>TODO: maybe need to put an Animation sequence example here? seems much more robust 
+	than using chains and combines with delays and durations to hack timing ... also, need
+	examples for stop() and other methods of class</p>
+
+
+
+</body>
+</html>
diff --git a/dojox/timing/tests/test_ThreadPool.html b/dojox/timing/tests/test_ThreadPool.html
new file mode 100644
index 0000000..53e4bfb
--- /dev/null
+++ b/dojox/timing/tests/test_ThreadPool.html
@@ -0,0 +1,16 @@
+<html>
+	<head>
+		<title>Quick Thread Pool Test</title>
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true" ></script>
+		<script type="text/javascript" src="../ThreadPool.js"></script>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+		</style>
+		<script type="text/javascript">
+			dojo.require("dojox.timing.ThreadPool");
+		</script>
+	</head>
+	<body>
+		testing.
+	</body>
+</html>
diff --git a/dojox/timing/tests/test_doLater.html b/dojox/timing/tests/test_doLater.html
new file mode 100644
index 0000000..d2cfe1a
--- /dev/null
+++ b/dojox/timing/tests/test_doLater.html
@@ -0,0 +1,140 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html lang="en">
+<head>
+    <title>dojox.timing.doLater</title>
+    <style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+    <script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true" ></script>
+    <script>
+       dojo.require("dojox.timing.doLater");
+		
+		
+        /*========================
+            TEST 1 - Global space
+         =========================*/
+        
+		// triggers our pseudo "isReady"
+		setTimeout(function(){ pseudoReadyThing = true; },700);
+        
+        var objectId ="global";            // objectId is used to check we are in the correct context.
+		var pseudoReadyThing = false;      // our global "ready" conditional
+		
+		// testing function in global context
+		var doThing = function(first, last){
+			if(dojox.timing.doLater(pseudoReadyThing)){return;}                      // our key statement 
+			console.log("doThing:", objectId, "::", first, last);            // success!
+		}
+		
+        // invoke!
+		doThing("Selina", "Kyle");  // invoke doThing, although it will not be ready for 700ms
+		
+		/*=====================
+            TEST 2 - context
+         ======================*/
+        
+        // triggers our "onReady"
+        setTimeout(function(){ app.ready = true; },900);
+        
+		// testing a function within an object context
+		var app = {
+			objectId:"app",
+			ready:false,
+			doStuff: function(first, last){
+				if(dojox.timing.doLater(this.ready, this)){return;}
+				console.log("app.doStuff:", this.objectId, "::", first, last)
+			},
+			goCrazy: function(first, last){
+				if(dojox.timing.doLater(this.ready, this)){return;}
+				console.log("app.goCrazy:", this.objectId, "::", first, last);
+			}
+		}
+		
+		// These three calls happen (almost) simultaneously 
+		// to test that they don't clobber each other
+		app.doStuff("Oswald", "Cobblepot");
+		app.doStuff("Edward", "Nigma");
+		app.goCrazy("Mike", "Wilcox");
+		
+        /*=====================
+               Misc Tests
+         ======================*/
+        
+        // NOTE: the timeouts used to invoke these tests cause the
+        // results to sometimes return in an unpredictable order.
+        
+		// testing an anonymous function 
+		setTimeout(function(){
+			if(dojox.timing.doLater(app.ready)){return;}
+			console.log("anonymous.function SUCCESS")
+		},700);
+        
+        // testing conditional usage OR
+		setTimeout(function(){
+			if(dojox.timing.doLater(pseudoReadyThing || app.ready)){return;}
+			console.log("pseudoReadyThing OR app.ready is ready")
+		},0);
+        
+        // testing conditional usage AND
+        setTimeout(function(){
+			if(dojox.timing.doLater(pseudoReadyThing && app.ready)){return;}
+			console.log("pseudoReadyThing AND app.ready is ready")
+		},0);
+        
+        // testing conditional expression, incremented
+        // essentially, anonymous function will get
+        // called ten times (every default 100 ms)
+        var count = 0
+        setTimeout(function(){
+			if(dojox.timing.doLater(++count>=10)){return;}
+			console.log("incremented count:", count);
+		},0);
+        
+        // testing random conditional
+        // anonymous function will be called until
+        // random result >= 8
+        setTimeout(function(){
+			if(dojox.timing.doLater(Math.random(1)*10>8)){return;}
+			console.log("random returned greater than 8");
+		},0);
+        
+        
+    </script>
+    <style>
+        p{ width:500px; }
+        .code{
+            font-family:monospace;
+            line-height:16px;
+            margin-left:20px;
+        }
+    </style>
+</head>
+<body>
+    <h1>dojox.timing.doLater()</h1>
+    <p>
+        There are several tests running in the background - open the console to view.
+    </p>
+    <p>
+        <em>dojox.timing.doLater()</em> provides a simple mechanism that checks a conditional before allowing
+        your function to continue. If the conditional is false, the function is blocked and continually
+        re-called, with arguments, until the conditional passes.
+    </p>
+    <div>
+        <em>dojox.timing.doLater()</em> is designed to be used with one key statement (in bold):<br/>
+        <div class="code">
+            var doThing = function(first, last){
+                <div class="code"><strong>if(dojox.timing.doLater(</strong><em>pseudoReadyThing</em><strong>)){return;} </strong></div>
+                <div class="code">doOther(first);</div>
+                <div class="code">doMore(last);</div>
+            }
+        </div>
+    </div>
+    <p>
+        Although these tests are using timers and incremnters, the idea behind
+        <em>dojox.timing.doLater()</em> is to test for things like if a window is loaded,
+        or if an XHR has returned.
+    </p>
+    
+</body>
+</html>
diff --git a/dojox/uuid.js b/dojox/uuid.js
index b8443a4..c85931c 100644
--- a/dojox/uuid.js
+++ b/dojox/uuid.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.uuid"]){
-dojo._hasResource["dojox.uuid"]=true;
 dojo.provide("dojox.uuid");
 dojo.require("dojox.uuid._base");
-}
diff --git a/dojox/uuid/Uuid.js b/dojox/uuid/Uuid.js
index 02ee540..d676bd2 100644
--- a/dojox/uuid/Uuid.js
+++ b/dojox/uuid/Uuid.js
@@ -1,99 +1,196 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.uuid.Uuid"]){
-dojo._hasResource["dojox.uuid.Uuid"]=true;
 dojo.provide("dojox.uuid.Uuid");
 dojo.require("dojox.uuid");
-dojox.uuid.Uuid=function(_1){
-this._uuidString=dojox.uuid.NIL_UUID;
-if(_1){
-dojox.uuid.assert(dojo.isString(_1));
-this._uuidString=_1.toLowerCase();
-dojox.uuid.assert(this.isValid());
-}else{
-var _2=dojox.uuid.Uuid.getGenerator();
-if(_2){
-this._uuidString=_2();
-dojox.uuid.assert(this.isValid());
-}
-}
+
+dojox.uuid.Uuid = function(/*String?*/ input){
+	// summary: 
+	//		This is the constructor for the Uuid class.  The Uuid class offers 
+	//		methods for inspecting existing UUIDs.
+	// input: A 36-character string that conforms to the UUID spec.
+	// examples:
+	//		var uuid;
+	//		uuid = new dojox.uuid.Uuid("3b12f1df-5232-4804-897e-917bf397618a");
+	//		uuid = new dojox.uuid.Uuid(); // "00000000-0000-0000-0000-000000000000"
+	//		uuid = new dojox.uuid.Uuid(dojox.uuid.generateRandomUuid());
+	//		uuid = new dojox.uuid.Uuid(dojox.uuid.generateTimeBasedUuid());
+	//		dojox.uuid.Uuid.setGenerator(dojox.uuid.generateRandomUuid);
+	//		uuid = new dojox.uuid.Uuid();
+	//		dojox.uuid.assert(!uuid.isEqual(dojox.uuid.NIL_UUID));
+	this._uuidString = dojox.uuid.NIL_UUID;
+	if(input){
+		dojox.uuid.assert(dojo.isString(input));
+		this._uuidString = input.toLowerCase();
+		dojox.uuid.assert(this.isValid());
+	}else{
+		var ourGenerator = dojox.uuid.Uuid.getGenerator();
+		if(ourGenerator){
+			this._uuidString = ourGenerator();
+			dojox.uuid.assert(this.isValid());
+		}
+	}
 };
-dojox.uuid.Uuid.compare=function(_3,_4){
-var _5=_3.toString();
-var _6=_4.toString();
-if(_5>_6){
-return 1;
-}
-if(_5<_6){
-return -1;
-}
-return 0;
+
+dojox.uuid.Uuid.compare = function(/*dojox.uuid.Uuid*/ uuidOne, /*dojox.uuid.Uuid*/ uuidTwo){
+	// summary: 
+	//		Given two UUIDs to compare, this method returns 0, 1, or -1.
+	// description:
+	//		This method is designed to be used by sorting routines, like the
+	//		JavaScript built-in Array sort() method. This implementation is 
+	//		intended to match the sample implementation in IETF RFC 4122:
+	//		http://www.ietf.org/rfc/rfc4122.txt
+	// uuidOne: Any object that has toString() method that returns a 36-character string that conforms to the UUID spec.
+	// uuidTwo: Any object that has toString() method that returns a 36-character string that conforms to the UUID spec.
+
+	// examples:
+	//		var uuid;
+	//		var generator = dojox.uuid.TimeBasedGenerator;
+	//		var a = new dojox.uuid.Uuid(generator);
+	//		var b = new dojox.uuid.Uuid(generator);
+	//		var c = new dojox.uuid.Uuid(generator);
+	//		var array = new Array(a, b, c);
+	//		array.sort(dojox.uuid.Uuid.compare);
+	var uuidStringOne = uuidOne.toString();
+	var uuidStringTwo = uuidTwo.toString();
+	if (uuidStringOne > uuidStringTwo) return 1;   // integer
+	if (uuidStringOne < uuidStringTwo) return -1;  // integer
+	return 0; // integer (either 0, 1, or -1)
 };
-dojox.uuid.Uuid.setGenerator=function(_7){
-dojox.uuid.assert(!_7||dojo.isFunction(_7));
-dojox.uuid.Uuid._ourGenerator=_7;
+
+dojox.uuid.Uuid.setGenerator = function(/*Function?*/ generator){
+	// summary: 
+	//		Sets the default generator, which will be used by the 
+	//		"new dojox.uuid.Uuid()" constructor if no parameters
+	//		are passed in.
+	// generator: A UUID generator function, such as dojox.uuid.generateTimeBasedUuid.
+	dojox.uuid.assert(!generator || dojo.isFunction(generator));
+	dojox.uuid.Uuid._ourGenerator = generator;
 };
-dojox.uuid.Uuid.getGenerator=function(){
-return dojox.uuid.Uuid._ourGenerator;
+
+dojox.uuid.Uuid.getGenerator = function(){
+	// summary: 
+	//		Returns the default generator.  See setGenerator().
+	return dojox.uuid.Uuid._ourGenerator; // generator (A UUID generator, such as dojox.uuid.TimeBasedGenerator).
 };
-dojox.uuid.Uuid.prototype.toString=function(){
-return this._uuidString;
+
+dojox.uuid.Uuid.prototype.toString = function(){
+	// summary: 
+	//		This method returns a standard 36-character string representing 
+	//		the UUID, such as "3b12f1df-5232-4804-897e-917bf397618a".
+	return this._uuidString; // string
 };
-dojox.uuid.Uuid.prototype.compare=function(_8){
-return dojox.uuid.Uuid.compare(this,_8);
+
+dojox.uuid.Uuid.prototype.compare = function(/*dojox.uuid.Uuid*/ otherUuid){
+	// summary: 
+	//		Compares this UUID to another UUID, and returns 0, 1, or -1.
+	// description:
+	//		This implementation is intended to match the sample implementation
+	//		in IETF RFC 4122: http://www.ietf.org/rfc/rfc4122.txt
+	// otherUuid: Any object that has toString() method that returns a 36-character string that conforms to the UUID spec.
+	return dojox.uuid.Uuid.compare(this, otherUuid); // integer (either 0, 1, or -1)
 };
-dojox.uuid.Uuid.prototype.isEqual=function(_9){
-return (this.compare(_9)==0);
+
+dojox.uuid.Uuid.prototype.isEqual = function(/*dojox.uuid.Uuid*/ otherUuid){
+	// summary: 
+	//		Returns true if this UUID is equal to the otherUuid, or false otherwise.
+	// otherUuid: Any object that has toString() method that returns a 36-character string that conforms to the UUID spec.
+	return (this.compare(otherUuid) == 0); // boolean
 };
-dojox.uuid.Uuid.prototype.isValid=function(){
-return dojox.uuid.isValid(this);
+
+dojox.uuid.Uuid.prototype.isValid = function(){
+	// summary: 
+	//		Returns true if the UUID was initialized with a valid value.
+	return dojox.uuid.isValid(this);
 };
-dojox.uuid.Uuid.prototype.getVariant=function(){
-return dojox.uuid.getVariant(this);
+
+dojox.uuid.Uuid.prototype.getVariant = function(){
+	// summary: 
+	//		Returns a variant code that indicates what type of UUID this is.
+	//		Returns one of the enumerated dojox.uuid.variant values.
+
+	// example: 
+	//		var uuid = new dojox.uuid.Uuid("3b12f1df-5232-4804-897e-917bf397618a");
+	//		var variant = uuid.getVariant();
+	//		dojox.uuid.assert(variant == dojox.uuid.variant.DCE);
+	// example: 
+	// "3b12f1df-5232-4804-897e-917bf397618a"
+	//                     ^
+	//                     |
+	//         (variant "10__" == DCE)
+	return dojox.uuid.getVariant(this);
 };
-dojox.uuid.Uuid.prototype.getVersion=function(){
-if(!this._versionNumber){
-this._versionNumber=dojox.uuid.getVersion(this);
-}
-return this._versionNumber;
+
+dojox.uuid.Uuid.prototype.getVersion = function(){
+	// summary: 
+	//		Returns a version number that indicates what type of UUID this is.
+	//		Returns one of the enumerated dojox.uuid.version values.
+	// example: 
+	//		var uuid = new dojox.uuid.Uuid("b4308fb0-86cd-11da-a72b-0800200c9a66");
+	//		var version = uuid.getVersion();
+	//		dojox.uuid.assert(version == dojox.uuid.version.TIME_BASED);
+	// exceptions: 
+	//		Throws an Error if this is not a DCE Variant UUID.
+	if(!this._versionNumber){
+		this._versionNumber = dojox.uuid.getVersion(this);
+	}
+	return this._versionNumber; // dojox.uuid.version
 };
-dojox.uuid.Uuid.prototype.getNode=function(){
-if(!this._nodeString){
-this._nodeString=dojox.uuid.getNode(this);
-}
-return this._nodeString;
+
+dojox.uuid.Uuid.prototype.getNode = function(){
+	// summary: 
+	//		If this is a version 1 UUID (a time-based UUID), getNode() returns a 
+	//		12-character string with the "node" or "pseudonode" portion of the UUID, 
+	//		which is the rightmost 12 characters.  
+	// exceptions: 
+	//		Throws an Error if this is not a version 1 UUID.
+	if (!this._nodeString) {
+		this._nodeString = dojox.uuid.getNode(this);
+	}
+	return this._nodeString; // String (a 12-character string, which will look something like "917bf397618a")
 };
-dojox.uuid.Uuid.prototype.getTimestamp=function(_a){
-if(!_a){
-_a=null;
-}
-switch(_a){
-case "string":
-case String:
-return this.getTimestamp(Date).toUTCString();
-break;
-case "hex":
-if(!this._timestampAsHexString){
-this._timestampAsHexString=dojox.uuid.getTimestamp(this,"hex");
-}
-return this._timestampAsHexString;
-break;
-case null:
-case "date":
-case Date:
-if(!this._timestampAsDate){
-this._timestampAsDate=dojox.uuid.getTimestamp(this,Date);
-}
-return this._timestampAsDate;
-break;
-default:
-dojox.uuid.assert(false,"The getTimestamp() method dojox.uuid.Uuid was passed a bogus returnType: "+_a);
-break;
-}
+
+dojox.uuid.Uuid.prototype.getTimestamp = function(/*String?*/ returnType){
+	// summary: 
+	//		If this is a version 1 UUID (a time-based UUID), this method returns
+	//		the timestamp value encoded in the UUID.  The caller can ask for the
+	//		timestamp to be returned either as a JavaScript Date object or as a 
+	//		15-character string of hex digits.
+	// returnType: Any of these five values: "string", String, "hex", "date", Date
+	// returns: 
+	//		Returns the timestamp value as a JavaScript Date object or a 15-character string of hex digits.
+	// examples: 
+	//		var uuid = new dojox.uuid.Uuid("b4308fb0-86cd-11da-a72b-0800200c9a66");
+	//		var date, string, hexString;
+	//		date   = uuid.getTimestamp();         // returns a JavaScript Date
+	//		date   = uuid.getTimestamp(Date);     // 
+	//		string = uuid.getTimestamp(String);   // "Mon, 16 Jan 2006 20:21:41 GMT"
+	//		hexString = uuid.getTimestamp("hex"); // "1da86cdb4308fb0"
+	// exceptions: 
+	//		Throws an Error if this is not a version 1 UUID.
+	if(!returnType){returnType = null};
+	switch(returnType){
+		case "string":
+		case String:
+			return this.getTimestamp(Date).toUTCString(); // String (e.g. "Mon, 16 Jan 2006 20:21:41 GMT")
+			break;
+		case "hex":
+			// Return a 15-character string of hex digits containing the 
+			// timestamp for this UUID, with the high-order bits first.
+			if (!this._timestampAsHexString) {
+				this._timestampAsHexString = dojox.uuid.getTimestamp(this, "hex");
+			}
+			return this._timestampAsHexString; // String (e.g. "1da86cdb4308fb0")
+			break;
+		case null: // no returnType was specified, so default to Date
+		case "date":
+		case Date:
+			// Return a JavaScript Date object. 
+			if (!this._timestampAsDate) {
+				this._timestampAsDate = dojox.uuid.getTimestamp(this, Date);
+			}
+			return this._timestampAsDate; // Date
+			break;
+		default:
+			// we got passed something other than a valid returnType
+			dojox.uuid.assert(false, "The getTimestamp() method dojox.uuid.Uuid was passed a bogus returnType: " + returnType);
+			break;
+	}
 };
-}
diff --git a/dojox/uuid/_base.js b/dojox/uuid/_base.js
index 7fc0c9a..466e0e3 100644
--- a/dojox/uuid/_base.js
+++ b/dojox/uuid/_base.js
@@ -1,136 +1,241 @@
-/*
-	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
-*/
+dojo.provide("dojox.uuid._base");
 
+// Public constants:
+dojox.uuid.NIL_UUID = "00000000-0000-0000-0000-000000000000";
+dojox.uuid.version = {
+	//	Enumeration for the different UUID versions.
+	UNKNOWN: 0,
+	TIME_BASED: 1,
+	DCE_SECURITY: 2,
+	NAME_BASED_MD5: 3,
+	RANDOM: 4,
+	NAME_BASED_SHA1: 5 };
+dojox.uuid.variant = {
+	//	Enumeration for the different UUID variants.
+	NCS: "0",
+	DCE: "10",
+	MICROSOFT: "110",
+	UNKNOWN: "111" };
 
-if(!dojo._hasResource["dojox.uuid._base"]){
-dojo._hasResource["dojox.uuid._base"]=true;
-dojo.provide("dojox.uuid._base");
-dojox.uuid.NIL_UUID="00000000-0000-0000-0000-000000000000";
-dojox.uuid.version={UNKNOWN:0,TIME_BASED:1,DCE_SECURITY:2,NAME_BASED_MD5:3,RANDOM:4,NAME_BASED_SHA1:5};
-dojox.uuid.variant={NCS:"0",DCE:"10",MICROSOFT:"110",UNKNOWN:"111"};
-dojox.uuid.assert=function(_1,_2){
-if(!_1){
-if(!_2){
-_2="An assert statement failed.\n"+"The method dojox.uuid.assert() was called with a 'false' value.\n";
-}
-throw new Error(_2);
-}
+dojox.uuid.assert = function(/*Boolean*/ booleanValue, /*String?*/ message){
+	// summary: 
+	//		Throws an exception if the assertion fails.
+	// description: 
+	//		If the asserted condition is true, this method does nothing. If the
+	//		condition is false, we throw an error with a error message. 
+	// booleanValue: Must be true for the assertion to succeed.
+	// message: A string describing the assertion.
+	// throws: Throws an Error if 'booleanValue' is false.
+	if(!booleanValue){
+		if(!message){
+			message = "An assert statement failed.\n" +
+			"The method dojox.uuid.assert() was called with a 'false' value.\n";
+		}
+		throw new Error(message);
+	}
 };
-dojox.uuid.generateNilUuid=function(){
-return dojox.uuid.NIL_UUID;
+
+dojox.uuid.generateNilUuid = function(){
+	// summary: 
+	//		This function returns the Nil UUID: "00000000-0000-0000-0000-000000000000".
+	// description: 
+	//		The Nil UUID is described in section 4.1.7 of
+	//		RFC 4122: http://tools.ietf.org/html/rfc4122#section-4.1.7
+	// examples: 
+	//		var string = dojox.uuid.generateNilUuid();
+	return dojox.uuid.NIL_UUID; // String
 };
-dojox.uuid.isValid=function(_3){
-_3=_3.toString();
-var _4=(dojo.isString(_3)&&(_3.length==36)&&(_3==_3.toLowerCase()));
-if(_4){
-var _5=_3.split("-");
-_4=((_5.length==5)&&(_5[0].length==8)&&(_5[1].length==4)&&(_5[2].length==4)&&(_5[3].length==4)&&(_5[4].length==12));
-var _6=16;
-for(var i in _5){
-var _7=_5[i];
-var _8=parseInt(_7,_6);
-_4=_4&&isFinite(_8);
-}
-}
-return _4;
+
+dojox.uuid.isValid = function(/*String*/ uuidString){
+	// summary: 
+	//		Returns true if the UUID was initialized with a valid value.
+	uuidString = uuidString.toString();
+	var valid = (dojo.isString(uuidString) &&
+		(uuidString.length == 36) &&
+		(uuidString == uuidString.toLowerCase()));
+	if(valid){
+		var arrayOfParts = uuidString.split("-");
+		valid = ((arrayOfParts.length == 5) &&
+			(arrayOfParts[0].length == 8) &&
+			(arrayOfParts[1].length == 4) &&
+			(arrayOfParts[2].length == 4) &&
+			(arrayOfParts[3].length == 4) &&
+			(arrayOfParts[4].length == 12));
+		var HEX_RADIX = 16;
+		for (var i in arrayOfParts) {
+			var part = arrayOfParts[i];
+			var integer = parseInt(part, HEX_RADIX);
+			valid = valid && isFinite(integer);
+		}
+	}
+	return valid; // boolean
 };
-dojox.uuid.getVariant=function(_9){
-if(!dojox.uuid._ourVariantLookupTable){
-var _a=dojox.uuid.variant;
-var _b=[];
-_b[0]=_a.NCS;
-_b[1]=_a.NCS;
-_b[2]=_a.NCS;
-_b[3]=_a.NCS;
-_b[4]=_a.NCS;
-_b[5]=_a.NCS;
-_b[6]=_a.NCS;
-_b[7]=_a.NCS;
-_b[8]=_a.DCE;
-_b[9]=_a.DCE;
-_b[10]=_a.DCE;
-_b[11]=_a.DCE;
-_b[12]=_a.MICROSOFT;
-_b[13]=_a.MICROSOFT;
-_b[14]=_a.UNKNOWN;
-_b[15]=_a.UNKNOWN;
-dojox.uuid._ourVariantLookupTable=_b;
-}
-_9=_9.toString();
-var _c=_9.charAt(19);
-var _d=16;
-var _e=parseInt(_c,_d);
-dojox.uuid.assert((_e>=0)&&(_e<=16));
-return dojox.uuid._ourVariantLookupTable[_e];
+
+dojox.uuid.getVariant = function(/*String*/ uuidString){
+	// summary: 
+	//		Returns a variant code that indicates what type of UUID this is.
+	//		Returns one of the enumerated dojox.uuid.variant values.
+	// example: 
+	//		var variant = dojox.uuid.getVariant("3b12f1df-5232-4804-897e-917bf397618a");
+	//		dojox.uuid.assert(variant == dojox.uuid.variant.DCE);
+	// example: 
+	// "3b12f1df-5232-4804-897e-917bf397618a"
+	//                     ^
+	//                     |
+	//         (variant "10__" == DCE)
+	if(!dojox.uuid._ourVariantLookupTable){
+		var variant = dojox.uuid.variant;
+		var lookupTable = [];
+
+		lookupTable[0x0] = variant.NCS;       // 0000
+		lookupTable[0x1] = variant.NCS;       // 0001
+		lookupTable[0x2] = variant.NCS;       // 0010
+		lookupTable[0x3] = variant.NCS;       // 0011
+
+		lookupTable[0x4] = variant.NCS;       // 0100
+		lookupTable[0x5] = variant.NCS;       // 0101
+		lookupTable[0x6] = variant.NCS;       // 0110
+		lookupTable[0x7] = variant.NCS;       // 0111
+
+		lookupTable[0x8] = variant.DCE;       // 1000
+		lookupTable[0x9] = variant.DCE;       // 1001
+		lookupTable[0xA] = variant.DCE;       // 1010
+		lookupTable[0xB] = variant.DCE;       // 1011
+
+		lookupTable[0xC] = variant.MICROSOFT; // 1100
+		lookupTable[0xD] = variant.MICROSOFT; // 1101
+		lookupTable[0xE] = variant.UNKNOWN;   // 1110
+		lookupTable[0xF] = variant.UNKNOWN;   // 1111
+		
+		dojox.uuid._ourVariantLookupTable = lookupTable;
+	}
+
+	uuidString = uuidString.toString();
+	var variantCharacter = uuidString.charAt(19);
+	var HEX_RADIX = 16;
+	var variantNumber = parseInt(variantCharacter, HEX_RADIX);
+	dojox.uuid.assert((variantNumber >= 0) && (variantNumber <= 16));
+	return dojox.uuid._ourVariantLookupTable[variantNumber]; // dojox.uuid.variant
 };
-dojox.uuid.getVersion=function(_f){
-var _10="dojox.uuid.getVersion() was not passed a DCE Variant UUID.";
-dojox.uuid.assert(dojox.uuid.getVariant(_f)==dojox.uuid.variant.DCE,_10);
-_f=_f.toString();
-var _11=_f.charAt(14);
-var _12=16;
-var _13=parseInt(_11,_12);
-return _13;
+
+dojox.uuid.getVersion = function(/*String*/ uuidString){
+	// summary: 
+	//		Returns a version number that indicates what type of UUID this is.
+	//		Returns one of the enumerated dojox.uuid.version values.
+	// example: 
+	//		var version = dojox.uuid.getVersion("b4308fb0-86cd-11da-a72b-0800200c9a66");
+	//		dojox.uuid.assert(version == dojox.uuid.version.TIME_BASED);
+	// exceptions: 
+	//		Throws an Error if this is not a DCE Variant UUID.
+	var errorMessage = "dojox.uuid.getVersion() was not passed a DCE Variant UUID.";
+	dojox.uuid.assert(dojox.uuid.getVariant(uuidString) == dojox.uuid.variant.DCE, errorMessage);
+	uuidString = uuidString.toString();
+	
+		// "b4308fb0-86cd-11da-a72b-0800200c9a66"
+		//                ^
+		//                |
+		//       (version 1 == TIME_BASED)
+	var versionCharacter = uuidString.charAt(14);
+	var HEX_RADIX = 16;
+	var versionNumber = parseInt(versionCharacter, HEX_RADIX);
+	return versionNumber; // dojox.uuid.version
 };
-dojox.uuid.getNode=function(_14){
-var _15="dojox.uuid.getNode() was not passed a TIME_BASED UUID.";
-dojox.uuid.assert(dojox.uuid.getVersion(_14)==dojox.uuid.version.TIME_BASED,_15);
-_14=_14.toString();
-var _16=_14.split("-");
-var _17=_16[4];
-return _17;
+
+dojox.uuid.getNode = function(/*String*/ uuidString){
+	// summary: 
+	//		If this is a version 1 UUID (a time-based UUID), getNode() returns a 
+	//		12-character string with the "node" or "pseudonode" portion of the UUID, 
+	//		which is the rightmost 12 characters. 
+	// exceptions: 
+	//		Throws an Error if this is not a version 1 UUID.
+	var errorMessage = "dojox.uuid.getNode() was not passed a TIME_BASED UUID.";
+	dojox.uuid.assert(dojox.uuid.getVersion(uuidString) == dojox.uuid.version.TIME_BASED, errorMessage);
+
+	uuidString = uuidString.toString();
+	var arrayOfStrings = uuidString.split('-');
+	var nodeString = arrayOfStrings[4];
+	return nodeString; // String (a 12-character string, which will look something like "917bf397618a")
 };
-dojox.uuid.getTimestamp=function(_18,_19){
-var _1a="dojox.uuid.getTimestamp() was not passed a TIME_BASED UUID.";
-dojox.uuid.assert(dojox.uuid.getVersion(_18)==dojox.uuid.version.TIME_BASED,_1a);
-_18=_18.toString();
-if(!_19){
-_19=null;
-}
-switch(_19){
-case "string":
-case String:
-return dojox.uuid.getTimestamp(_18,Date).toUTCString();
-break;
-case "hex":
-var _1b=_18.split("-");
-var _1c=_1b[0];
-var _1d=_1b[1];
-var _1e=_1b[2];
-_1e=_1e.slice(1);
-var _1f=_1e+_1d+_1c;
-dojox.uuid.assert(_1f.length==15);
-return _1f;
-break;
-case null:
-case "date":
-case Date:
-var _20=3394248;
-var _21=16;
-var _22=_18.split("-");
-var _23=parseInt(_22[0],_21);
-var _24=parseInt(_22[1],_21);
-var _25=parseInt(_22[2],_21);
-var _26=_25&4095;
-_26<<=16;
-_26+=_24;
-_26*=4294967296;
-_26+=_23;
-var _27=_26/10000;
-var _28=60*60;
-var _29=_20;
-var _2a=_29*_28;
-var _2b=_2a*1000;
-var _2c=_27-_2b;
-var _2d=new Date(_2c);
-return _2d;
-break;
-default:
-dojox.uuid.assert(false,"dojox.uuid.getTimestamp was not passed a valid returnType: "+_19);
-break;
-}
+
+dojox.uuid.getTimestamp = function(/*String*/ uuidString, /*String?*/ returnType){
+	// summary: 
+	//		If this is a version 1 UUID (a time-based UUID), this method returns
+	//		the timestamp value encoded in the UUID.  The caller can ask for the
+	//		timestamp to be returned either as a JavaScript Date object or as a 
+	//		15-character string of hex digits.
+	// returnType: Any of these five values: "string", String, "hex", "date", Date
+	// returns: 
+	//		Returns the timestamp value as a JavaScript Date object or a 15-character string of hex digits.
+	// examples: 
+	//		var uuidString = "b4308fb0-86cd-11da-a72b-0800200c9a66";
+	//		var date, string, hexString;
+	//		date   = dojox.uuid.getTimestamp(uuidString);         // returns a JavaScript Date
+	//		date   = dojox.uuid.getTimestamp(uuidString, Date);     // 
+	//		string = dojox.uuid.getTimestamp(uuidString, String);   // "Mon, 16 Jan 2006 20:21:41 GMT"
+	//		hexString = dojox.uuid.getTimestamp(uuidString, "hex"); // "1da86cdb4308fb0"
+	// exceptions: 
+	//		Throws an Error if this is not a version 1 UUID.
+	var errorMessage = "dojox.uuid.getTimestamp() was not passed a TIME_BASED UUID.";
+	dojox.uuid.assert(dojox.uuid.getVersion(uuidString) == dojox.uuid.version.TIME_BASED, errorMessage);
+	
+	uuidString = uuidString.toString();
+	if(!returnType){returnType = null};
+	switch(returnType){
+		case "string":
+		case String:
+			return dojox.uuid.getTimestamp(uuidString, Date).toUTCString(); // String (e.g. "Mon, 16 Jan 2006 20:21:41 GMT")
+			break;
+		case "hex":
+			// Return a 15-character string of hex digits containing the 
+			// timestamp for this UUID, with the high-order bits first.
+			var arrayOfStrings = uuidString.split('-');
+			var hexTimeLow = arrayOfStrings[0];
+			var hexTimeMid = arrayOfStrings[1];
+			var hexTimeHigh = arrayOfStrings[2];
+		
+			// Chop off the leading "1" character, which is the UUID 
+			// version number for time-based UUIDs.
+			hexTimeHigh = hexTimeHigh.slice(1);
+		
+			var timestampAsHexString = hexTimeHigh + hexTimeMid + hexTimeLow;
+			dojox.uuid.assert(timestampAsHexString.length == 15);
+			return timestampAsHexString; // String (e.g. "1da86cdb4308fb0")
+			break;
+		case null: // no returnType was specified, so default to Date
+		case "date":
+		case Date:
+			// Return a JavaScript Date object. 
+			var GREGORIAN_CHANGE_OFFSET_IN_HOURS = 3394248;
+			var HEX_RADIX = 16;
+		
+			var arrayOfParts = uuidString.split('-');
+			var timeLow = parseInt(arrayOfParts[0], HEX_RADIX);
+			var timeMid = parseInt(arrayOfParts[1], HEX_RADIX);
+			var timeHigh = parseInt(arrayOfParts[2], HEX_RADIX);
+			var hundredNanosecondIntervalsSince1582 = timeHigh & 0x0FFF;
+			hundredNanosecondIntervalsSince1582 <<= 16;
+			hundredNanosecondIntervalsSince1582 += timeMid;
+			// What we really want to do next is shift left 32 bits, but the 
+			// result will be too big to fit in an int, so we'll multiply by 2^32,
+			// and the result will be a floating point approximation.
+			hundredNanosecondIntervalsSince1582 *= 0x100000000;
+			hundredNanosecondIntervalsSince1582 += timeLow;
+			var millisecondsSince1582 = hundredNanosecondIntervalsSince1582 / 10000;
+		
+			// Again, this will be a floating point approximation.
+			// We can make things exact later if we need to.
+			var secondsPerHour = 60 * 60;
+			var hoursBetween1582and1970 = GREGORIAN_CHANGE_OFFSET_IN_HOURS;
+			var secondsBetween1582and1970 = hoursBetween1582and1970 * secondsPerHour;
+			var millisecondsBetween1582and1970 = secondsBetween1582and1970 * 1000;
+			var millisecondsSince1970 = millisecondsSince1582 - millisecondsBetween1582and1970;
+		
+			var timestampAsDate = new Date(millisecondsSince1970);
+			return timestampAsDate; // Date
+			break;
+		default:
+			// we got passed something other than a valid returnType
+			dojox.uuid.assert(false, "dojox.uuid.getTimestamp was not passed a valid returnType: " + returnType);
+			break;
+	}
 };
-}
diff --git a/dojox/uuid/generateRandomUuid.js b/dojox/uuid/generateRandomUuid.js
index 0506379..5f23c7d 100644
--- a/dojox/uuid/generateRandomUuid.js
+++ b/dojox/uuid/generateRandomUuid.js
@@ -1,34 +1,52 @@
-/*
-	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
-*/
+dojo.provide("dojox.uuid.generateRandomUuid");
 
+dojox.uuid.generateRandomUuid = function(){
+	// summary:
+	//		This function generates random UUIDs, meaning "version 4" UUIDs.
+	// description:
+	//		A typical generated value would be something like this:
+	//		"3b12f1df-5232-4804-897e-917bf397618a"
+	//		
+	//		For more information about random UUIDs, see sections 4.4 and 
+	//		4.5 of RFC 4122: http://tools.ietf.org/html/rfc4122#section-4.4
+	//		
+	//		This generator function is designed to be small and fast,
+	//		but not necessarily good.
+	//		
+	//		Small: This generator has a small footprint. Once comments are
+	//		stripped, it's only about 25 lines of code, and it doesn't 
+	//		dojo.require() any other modules.
+	//		
+	//		Fast: This generator can generate lots of new UUIDs fairly quickly 
+	//		(at least, more quickly than the other dojo UUID generators).
+	//		
+	//		Not necessarily good: We use Math.random() as our source
+	//		of randomness, which may or may not provide much randomness. 
+	// examples: 
+	//		var string = dojox.uuid.generateRandomUuid();
+	var HEX_RADIX = 16;
 
-if(!dojo._hasResource["dojox.uuid.generateRandomUuid"]){
-dojo._hasResource["dojox.uuid.generateRandomUuid"]=true;
-dojo.provide("dojox.uuid.generateRandomUuid");
-dojox.uuid.generateRandomUuid=function(){
-var _1=16;
-function _2(){
-var _3=Math.floor((Math.random()%1)*Math.pow(2,32));
-var _4=_3.toString(_1);
-while(_4.length<8){
-_4="0"+_4;
-}
-return _4;
-};
-var _5="-";
-var _6="4";
-var _7="8";
-var a=_2();
-var b=_2();
-b=b.substring(0,4)+_5+_6+b.substring(5,8);
-var c=_2();
-c=_7+c.substring(1,4)+_5+c.substring(4,8);
-var d=_2();
-var _8=a+_5+b+_5+c+d;
-_8=_8.toLowerCase();
-return _8;
+	function _generateRandomEightCharacterHexString(){
+		// Make random32bitNumber be a randomly generated floating point number
+		// between 0 and (4,294,967,296 - 1), inclusive.
+		var random32bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 32) );
+		var eightCharacterHexString = random32bitNumber.toString(HEX_RADIX);
+		while(eightCharacterHexString.length < 8){
+			eightCharacterHexString = "0" + eightCharacterHexString;
+		}
+		return eightCharacterHexString; // for example: "3B12F1DF"
+	}
+
+	var hyphen = "-";
+	var versionCodeForRandomlyGeneratedUuids = "4"; // 8 == binary2hex("0100")
+	var variantCodeForDCEUuids = "8"; // 8 == binary2hex("1000")
+	var a = _generateRandomEightCharacterHexString();
+	var b = _generateRandomEightCharacterHexString();
+	b = b.substring(0, 4) + hyphen + versionCodeForRandomlyGeneratedUuids + b.substring(5, 8);
+	var c = _generateRandomEightCharacterHexString();
+	c = variantCodeForDCEUuids + c.substring(1, 4) + hyphen + c.substring(4, 8);
+	var d = _generateRandomEightCharacterHexString();
+	var returnValue = a + hyphen + b + hyphen + c + d;
+	returnValue = returnValue.toLowerCase();
+	return returnValue; // String
 };
-}
diff --git a/dojox/uuid/generateTimeBasedUuid.js b/dojox/uuid/generateTimeBasedUuid.js
index 55c60b4..97bfc29 100644
--- a/dojox/uuid/generateTimeBasedUuid.js
+++ b/dojox/uuid/generateTimeBasedUuid.js
@@ -1,197 +1,286 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.uuid.generateTimeBasedUuid"]){
-dojo._hasResource["dojox.uuid.generateTimeBasedUuid"]=true;
 dojo.provide("dojox.uuid.generateTimeBasedUuid");
-dojox.uuid.generateTimeBasedUuid=function(_1){
-var _2=dojox.uuid.generateTimeBasedUuid._generator.generateUuidString(_1);
-return _2;
-};
-dojox.uuid.generateTimeBasedUuid.isValidNode=function(_3){
-var _4=16;
-var _5=parseInt(_3,_4);
-var _6=dojo.isString(_3)&&_3.length==12&&isFinite(_5);
-return _6;
-};
-dojox.uuid.generateTimeBasedUuid.setNode=function(_7){
-dojox.uuid.assert((_7===null)||this.isValidNode(_7));
-this._uniformNode=_7;
-};
-dojox.uuid.generateTimeBasedUuid.getNode=function(){
-return this._uniformNode;
-};
-dojox.uuid.generateTimeBasedUuid._generator=new function(){
-this.GREGORIAN_CHANGE_OFFSET_IN_HOURS=3394248;
-var _8=null;
-var _9=null;
-var _a=null;
-var _b=0;
-var _c=null;
-var _d=null;
-var _e=16;
-function _f(_10){
-_10[2]+=_10[3]>>>16;
-_10[3]&=65535;
-_10[1]+=_10[2]>>>16;
-_10[2]&=65535;
-_10[0]+=_10[1]>>>16;
-_10[1]&=65535;
-dojox.uuid.assert((_10[0]>>>16)===0);
-};
-function _11(x){
-var _12=new Array(0,0,0,0);
-_12[3]=x%65536;
-x-=_12[3];
-x/=65536;
-_12[2]=x%65536;
-x-=_12[2];
-x/=65536;
-_12[1]=x%65536;
-x-=_12[1];
-x/=65536;
-_12[0]=x;
-return _12;
-};
-function _13(_14,_15){
-dojox.uuid.assert(dojo.isArray(_14));
-dojox.uuid.assert(dojo.isArray(_15));
-dojox.uuid.assert(_14.length==4);
-dojox.uuid.assert(_15.length==4);
-var _16=new Array(0,0,0,0);
-_16[3]=_14[3]+_15[3];
-_16[2]=_14[2]+_15[2];
-_16[1]=_14[1]+_15[1];
-_16[0]=_14[0]+_15[0];
-_f(_16);
-return _16;
-};
-function _17(_18,_19){
-dojox.uuid.assert(dojo.isArray(_18));
-dojox.uuid.assert(dojo.isArray(_19));
-dojox.uuid.assert(_18.length==4);
-dojox.uuid.assert(_19.length==4);
-var _1a=false;
-if(_18[0]*_19[0]!==0){
-_1a=true;
-}
-if(_18[0]*_19[1]!==0){
-_1a=true;
-}
-if(_18[0]*_19[2]!==0){
-_1a=true;
-}
-if(_18[1]*_19[0]!==0){
-_1a=true;
-}
-if(_18[1]*_19[1]!==0){
-_1a=true;
-}
-if(_18[2]*_19[0]!==0){
-_1a=true;
-}
-dojox.uuid.assert(!_1a);
-var _1b=new Array(0,0,0,0);
-_1b[0]+=_18[0]*_19[3];
-_f(_1b);
-_1b[0]+=_18[1]*_19[2];
-_f(_1b);
-_1b[0]+=_18[2]*_19[1];
-_f(_1b);
-_1b[0]+=_18[3]*_19[0];
-_f(_1b);
-_1b[1]+=_18[1]*_19[3];
-_f(_1b);
-_1b[1]+=_18[2]*_19[2];
-_f(_1b);
-_1b[1]+=_18[3]*_19[1];
-_f(_1b);
-_1b[2]+=_18[2]*_19[3];
-_f(_1b);
-_1b[2]+=_18[3]*_19[2];
-_f(_1b);
-_1b[3]+=_18[3]*_19[3];
-_f(_1b);
-return _1b;
+
+dojox.uuid.generateTimeBasedUuid = function(/*String?*/ node){
+	// summary: 
+	//		This function generates time-based UUIDs, meaning "version 1" UUIDs. 
+	// description: 
+	// For more info, see
+	//		http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt
+	//		http://www.infonuovo.com/dma/csdocs/sketch/instidid.htm
+	//		http://kruithof.xs4all.nl/uuid/uuidgen
+	//		http://www.opengroup.org/onlinepubs/009629399/apdxa.htm#tagcjh_20
+	//		http://jakarta.apache.org/commons/sandbox/id/apidocs/org/apache/commons/id/uuid/clock/Clock.html
+	// node:
+	//		A 12-character hex string representing either a pseudo-node or 
+	//		hardware-node (an IEEE 802.3 network node).  A hardware-node 
+	//		will be something like "017bf397618a", always with the first bit 
+	//		being 0.  A pseudo-node will be something like "f17bf397618a", 
+	//		always with the first bit being 1.
+	// examples: 
+	//		string = dojox.uuid.generateTimeBasedUuid();
+	//		string = dojox.uuid.generateTimeBasedUuid("017bf397618a");
+	//		dojox.uuid.generateTimeBasedUuid.setNode("017bf397618a");
+	//		string = dojox.uuid.generateTimeBasedUuid(); // the generated UUID has node == "017bf397618a"	
+	var uuidString = dojox.uuid.generateTimeBasedUuid._generator.generateUuidString(node);
+	return uuidString; // String
 };
-function _1c(_1d,_1e){
-while(_1d.length<_1e){
-_1d="0"+_1d;
-}
-return _1d;
+
+dojox.uuid.generateTimeBasedUuid.isValidNode = function(/*String?*/ node){
+	var HEX_RADIX = 16;
+	var integer = parseInt(node, HEX_RADIX);
+	var valid = dojo.isString(node) && node.length == 12 && isFinite(integer);
+	return valid; // Boolean
 };
-function _1f(){
-var _20=Math.floor((Math.random()%1)*Math.pow(2,32));
-var _21=_20.toString(_e);
-while(_21.length<8){
-_21="0"+_21;
-}
-return _21;
+
+dojox.uuid.generateTimeBasedUuid.setNode = function(/*String?*/ node){
+	// summary: 
+	//		Sets the 'node' value that will be included in generated UUIDs.
+	// node: A 12-character hex string representing a pseudoNode or hardwareNode.
+	dojox.uuid.assert((node === null) || this.isValidNode(node));
+	this._uniformNode = node;
 };
-this.generateUuidString=function(_22){
-if(_22){
-dojox.uuid.assert(dojox.uuid.generateTimeBasedUuid.isValidNode(_22));
-}else{
-if(dojox.uuid.generateTimeBasedUuid._uniformNode){
-_22=dojox.uuid.generateTimeBasedUuid._uniformNode;
-}else{
-if(!_8){
-var _23=32768;
-var _24=Math.floor((Math.random()%1)*Math.pow(2,15));
-var _25=(_23|_24).toString(_e);
-_8=_25+_1f();
-}
-_22=_8;
-}
-}
-if(!_9){
-var _26=32768;
-var _27=Math.floor((Math.random()%1)*Math.pow(2,14));
-_9=(_26|_27).toString(_e);
-}
-var now=new Date();
-var _28=now.valueOf();
-var _29=_11(_28);
-if(!_c){
-var _2a=_11(60*60);
-var _2b=_11(dojox.uuid.generateTimeBasedUuid._generator.GREGORIAN_CHANGE_OFFSET_IN_HOURS);
-var _2c=_17(_2b,_2a);
-var _2d=_11(1000);
-_c=_17(_2c,_2d);
-_d=_11(10000);
-}
-var _2e=_29;
-var _2f=_13(_c,_2e);
-var _30=_17(_2f,_d);
-if(now.valueOf()==_a){
-_30[3]+=_b;
-_f(_30);
-_b+=1;
-if(_b==10000){
-while(now.valueOf()==_a){
-now=new Date();
-}
-}
-}else{
-_a=now.valueOf();
-_b=1;
-}
-var _31=_30[2].toString(_e);
-var _32=_30[3].toString(_e);
-var _33=_1c(_31,4)+_1c(_32,4);
-var _34=_30[1].toString(_e);
-_34=_1c(_34,4);
-var _35=_30[0].toString(_e);
-_35=_1c(_35,3);
-var _36="-";
-var _37="1";
-var _38=_33+_36+_34+_36+_37+_35+_36+_9+_36+_22;
-_38=_38.toLowerCase();
-return _38;
+
+dojox.uuid.generateTimeBasedUuid.getNode = function(){
+	// summary: 
+	//		Returns the 'node' value that will be included in generated UUIDs.
+	return this._uniformNode; // String (a 12-character hex string representing a pseudoNode or hardwareNode)
 };
+
+	
+dojox.uuid.generateTimeBasedUuid._generator = new function(){
+	// Number of hours between October 15, 1582 and January 1, 1970:
+	this.GREGORIAN_CHANGE_OFFSET_IN_HOURS = 3394248;
+	
+	// Number of seconds between October 15, 1582 and January 1, 1970:
+	//   dojox.uuid.generateTimeBasedUuid.GREGORIAN_CHANGE_OFFSET_IN_SECONDS = 12219292800;	
+	
+	// --------------------------------------------------
+	// Private variables:
+	var _uuidPseudoNodeString = null;
+	var _uuidClockSeqString = null;
+	var _dateValueOfPreviousUuid = null;
+	var _nextIntraMillisecondIncrement = 0;
+	var _cachedMillisecondsBetween1582and1970 = null;
+	var _cachedHundredNanosecondIntervalsPerMillisecond = null;
+	
+	// --------------------------------------------------
+	// Private constants:
+	var HEX_RADIX = 16;
+
+	function _carry(/* array */ arrayA){
+		// summary: 
+		//		Given an array which holds a 64-bit number broken into 4 16-bit 
+		//		elements, this method carries any excess bits (greater than 16-bits) 
+		//		from each array element into the next.
+		// arrayA: An array with 4 elements, each of which is a 16-bit number.
+		arrayA[2] += arrayA[3] >>> 16;
+		arrayA[3] &= 0xFFFF;
+		arrayA[1] += arrayA[2] >>> 16;
+		arrayA[2] &= 0xFFFF;
+		arrayA[0] += arrayA[1] >>> 16;
+		arrayA[1] &= 0xFFFF;
+		dojox.uuid.assert((arrayA[0] >>> 16) === 0);
+	}
+
+	function _get64bitArrayFromFloat(/* float */ x){
+		// summary: 
+		//		Given a floating point number, this method returns an array which 
+		//		holds a 64-bit number broken into 4 16-bit elements.
+		var result = new Array(0, 0, 0, 0);
+		result[3] = x % 0x10000;
+		x -= result[3];
+		x /= 0x10000;
+		result[2] = x % 0x10000;
+		x -= result[2];
+		x /= 0x10000;
+		result[1] = x % 0x10000;
+		x -= result[1];
+		x /= 0x10000;
+		result[0] = x;
+		return result; // Array with 4 elements, each of which is a 16-bit number.
+	}
+
+	function _addTwo64bitArrays(/* array */ arrayA, /* array */ arrayB){
+		// summary: 
+		//		Takes two arrays, each of which holds a 64-bit number broken into 4
+		//		16-bit elements, and returns a new array that holds a 64-bit number
+		//		that is the sum of the two original numbers.
+		// arrayA: An array with 4 elements, each of which is a 16-bit number.
+		// arrayB: An array with 4 elements, each of which is a 16-bit number.
+		dojox.uuid.assert(dojo.isArray(arrayA));
+		dojox.uuid.assert(dojo.isArray(arrayB));
+		dojox.uuid.assert(arrayA.length == 4);
+		dojox.uuid.assert(arrayB.length == 4);
+	
+		var result = new Array(0, 0, 0, 0);
+		result[3] = arrayA[3] + arrayB[3];
+		result[2] = arrayA[2] + arrayB[2];
+		result[1] = arrayA[1] + arrayB[1];
+		result[0] = arrayA[0] + arrayB[0];
+		_carry(result);
+		return result; // Array with 4 elements, each of which is a 16-bit number.
+	}
+
+	function _multiplyTwo64bitArrays(/* array */ arrayA, /* array */ arrayB){
+		// summary: 
+		//		Takes two arrays, each of which holds a 64-bit number broken into 4
+		//		16-bit elements, and returns a new array that holds a 64-bit number
+		//		that is the product of the two original numbers.
+		// arrayA: An array with 4 elements, each of which is a 16-bit number.
+		// arrayB: An array with 4 elements, each of which is a 16-bit number.
+		dojox.uuid.assert(dojo.isArray(arrayA));
+		dojox.uuid.assert(dojo.isArray(arrayB));
+		dojox.uuid.assert(arrayA.length == 4);
+		dojox.uuid.assert(arrayB.length == 4);
+	
+		var overflow = false;
+		if(arrayA[0] * arrayB[0] !== 0){ overflow = true; }
+		if(arrayA[0] * arrayB[1] !== 0){ overflow = true; }
+		if(arrayA[0] * arrayB[2] !== 0){ overflow = true; }
+		if(arrayA[1] * arrayB[0] !== 0){ overflow = true; }
+		if(arrayA[1] * arrayB[1] !== 0){ overflow = true; }
+		if(arrayA[2] * arrayB[0] !== 0){ overflow = true; }
+		dojox.uuid.assert(!overflow);
+	
+		var result = new Array(0, 0, 0, 0);
+		result[0] += arrayA[0] * arrayB[3];
+		_carry(result);
+		result[0] += arrayA[1] * arrayB[2];
+		_carry(result);
+		result[0] += arrayA[2] * arrayB[1];
+		_carry(result);
+		result[0] += arrayA[3] * arrayB[0];
+		_carry(result);
+		result[1] += arrayA[1] * arrayB[3];
+		_carry(result);
+		result[1] += arrayA[2] * arrayB[2];
+		_carry(result);
+		result[1] += arrayA[3] * arrayB[1];
+		_carry(result);
+		result[2] += arrayA[2] * arrayB[3];
+		_carry(result);
+		result[2] += arrayA[3] * arrayB[2];
+		_carry(result);
+		result[3] += arrayA[3] * arrayB[3];
+		_carry(result);
+		return result; // Array with 4 elements, each of which is a 16-bit number.
+	}
+
+	function _padWithLeadingZeros(/* string */ string, /* int */ desiredLength){
+		// summary: 
+		//		Pads a string with leading zeros and returns the result.
+		// string: A string to add padding to.
+		// desiredLength: The number of characters the return string should have.
+
+		// examples: 
+		//		result = _padWithLeadingZeros("abc", 6);
+		//		dojox.uuid.assert(result == "000abc");
+		while(string.length < desiredLength){
+			string = "0" + string;
+		}
+		return string; // string
+	}
+
+	function _generateRandomEightCharacterHexString() {
+		// summary: 
+		//		Returns a randomly generated 8-character string of hex digits.
+
+		// FIXME: This probably isn't a very high quality random number.
+	
+		// Make random32bitNumber be a randomly generated floating point number
+		// between 0 and (4,294,967,296 - 1), inclusive.
+		var random32bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 32) );
+	
+		var eightCharacterString = random32bitNumber.toString(HEX_RADIX);
+		while(eightCharacterString.length < 8){
+			eightCharacterString = "0" + eightCharacterString;
+		}
+		return eightCharacterString; // String (an 8-character hex string)
+	}
+	
+	this.generateUuidString = function(/*String?*/ node){
+		// summary: 
+		//		Generates a time-based UUID, meaning a version 1 UUID.  
+		// description: 
+		//		JavaScript code running in a browser doesn't have access to the 
+		//		IEEE 802.3 address of the computer, so if a node value isn't 
+		//		supplied, we generate a random pseudonode value instead.
+		// node: An optional 12-character string to use as the node in the new UUID.
+		if(node){
+			dojox.uuid.assert(dojox.uuid.generateTimeBasedUuid.isValidNode(node));
+		}else{
+			if(dojox.uuid.generateTimeBasedUuid._uniformNode){
+				node = dojox.uuid.generateTimeBasedUuid._uniformNode;
+			}else{
+				if(!_uuidPseudoNodeString){
+					var pseudoNodeIndicatorBit = 0x8000;
+					var random15bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 15) );
+					var leftmost4HexCharacters = (pseudoNodeIndicatorBit | random15bitNumber).toString(HEX_RADIX);
+					_uuidPseudoNodeString = leftmost4HexCharacters + _generateRandomEightCharacterHexString();
+				}
+				node = _uuidPseudoNodeString;
+			}
+		}
+		if(!_uuidClockSeqString){
+			var variantCodeForDCEUuids = 0x8000; // 10--------------, i.e. uses only first two of 16 bits.
+			var random14bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 14) );
+			_uuidClockSeqString = (variantCodeForDCEUuids | random14bitNumber).toString(HEX_RADIX);
+		}
+	
+		// Maybe we should think about trying to make the code more readable to
+		// newcomers by creating a class called "WholeNumber" that encapsulates
+		// the methods and data structures for working with these arrays that
+		// hold 4 16-bit numbers?  And then these variables below have names
+		// like "wholeSecondsPerHour" rather than "arraySecondsPerHour"?
+		var now = new Date();
+		var millisecondsSince1970 = now.valueOf(); // milliseconds since midnight 01 January, 1970 UTC.
+		var nowArray = _get64bitArrayFromFloat(millisecondsSince1970);
+		if(!_cachedMillisecondsBetween1582and1970){
+			var arraySecondsPerHour = _get64bitArrayFromFloat(60 * 60);
+			var arrayHoursBetween1582and1970 = _get64bitArrayFromFloat(dojox.uuid.generateTimeBasedUuid._generator.GREGORIAN_CHANGE_OFFSET_IN_HOURS);
+			var arraySecondsBetween1582and1970 = _multiplyTwo64bitArrays(arrayHoursBetween1582and1970, arraySecondsPerHour);
+			var arrayMillisecondsPerSecond = _get64bitArrayFromFloat(1000);
+			_cachedMillisecondsBetween1582and1970 = _multiplyTwo64bitArrays(arraySecondsBetween1582and1970, arrayMillisecondsPerSecond);
+			_cachedHundredNanosecondIntervalsPerMillisecond = _get64bitArrayFromFloat(10000);
+		}
+		var arrayMillisecondsSince1970 = nowArray;
+		var arrayMillisecondsSince1582 = _addTwo64bitArrays(_cachedMillisecondsBetween1582and1970, arrayMillisecondsSince1970);
+		var arrayHundredNanosecondIntervalsSince1582 = _multiplyTwo64bitArrays(arrayMillisecondsSince1582, _cachedHundredNanosecondIntervalsPerMillisecond);
+	
+		if(now.valueOf() == _dateValueOfPreviousUuid){
+			arrayHundredNanosecondIntervalsSince1582[3] += _nextIntraMillisecondIncrement;
+			_carry(arrayHundredNanosecondIntervalsSince1582);
+			_nextIntraMillisecondIncrement += 1;
+			if (_nextIntraMillisecondIncrement == 10000) {
+				// If we've gotten to here, it means we've already generated 10,000
+				// UUIDs in this single millisecond, which is the most that the UUID
+				// timestamp field allows for.  So now we'll just sit here and wait
+				// for a fraction of a millisecond, so as to ensure that the next
+				// time this method is called there will be a different millisecond
+				// value in the timestamp field.
+				while (now.valueOf() == _dateValueOfPreviousUuid) {
+					now = new Date();
+				}
+			}
+		}else{
+			_dateValueOfPreviousUuid = now.valueOf();
+			_nextIntraMillisecondIncrement = 1;
+		}
+	
+		var hexTimeLowLeftHalf  = arrayHundredNanosecondIntervalsSince1582[2].toString(HEX_RADIX);
+		var hexTimeLowRightHalf = arrayHundredNanosecondIntervalsSince1582[3].toString(HEX_RADIX);
+		var hexTimeLow = _padWithLeadingZeros(hexTimeLowLeftHalf, 4) + _padWithLeadingZeros(hexTimeLowRightHalf, 4);
+		var hexTimeMid = arrayHundredNanosecondIntervalsSince1582[1].toString(HEX_RADIX);
+		hexTimeMid = _padWithLeadingZeros(hexTimeMid, 4);
+		var hexTimeHigh = arrayHundredNanosecondIntervalsSince1582[0].toString(HEX_RADIX);
+		hexTimeHigh = _padWithLeadingZeros(hexTimeHigh, 3);
+		var hyphen = "-";
+		var versionCodeForTimeBasedUuids = "1"; // binary2hex("0001")
+		var resultUuid = hexTimeLow + hyphen + hexTimeMid + hyphen +
+					versionCodeForTimeBasedUuids + hexTimeHigh + hyphen +
+					_uuidClockSeqString + hyphen + node;
+		resultUuid = resultUuid.toLowerCase();
+		return resultUuid; // String (a 36 character string, which will look something like "b4308fb0-86cd-11da-a72b-0800200c9a66")
+	}
+
 }();
-}
diff --git a/dojox/uuid/tests/runTests.html b/dojox/uuid/tests/runTests.html
new file mode 100644
index 0000000..41ba177
--- /dev/null
+++ b/dojox/uuid/tests/runTests.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox.uuid Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.uuid.tests.uuid">
+	</head>
+    <body>
+        Redirecting to D.O.H runner.
+    </body>
+</html> 
diff --git a/dojox/uuid/tests/uuid.js b/dojox/uuid/tests/uuid.js
new file mode 100644
index 0000000..b5bdc5d
--- /dev/null
+++ b/dojox/uuid/tests/uuid.js
@@ -0,0 +1,373 @@
+dojo.provide("dojox.uuid.tests.uuid");
+dojo.require("dojox.uuid");
+dojo.require("dojox.uuid.Uuid");
+dojo.require("dojox.uuid.generateRandomUuid");
+dojo.require("dojox.uuid.generateTimeBasedUuid");
+
+dojox.uuid.tests.uuid.checkValidityOfUuidString = function(/*String*/uuidString){
+	// summary:
+	//		A helper function that's used by the registered test functions
+	var NIL_UUID = "00000000-0000-0000-0000-000000000000";
+	if (uuidString == NIL_UUID) {
+		// We'll consider the Nil UUID to be valid, so now 
+		// we can just return, with not further checks.
+		return;
+	}
+	
+	doh.assertTrue(uuidString.length == 36); // UUIDs have 36 characters
+
+	var validCharacters = "0123456789abcedfABCDEF-";
+	var character;
+	var position;
+	for(var i = 0; i < 36; ++i){
+		character = uuidString.charAt(i);
+		position = validCharacters.indexOf(character);
+		doh.assertTrue(position != -1); // UUIDs have only valid characters
+	}
+
+	var arrayOfParts = uuidString.split("-");
+	doh.assertTrue(arrayOfParts.length == 5); // UUIDs have 5 sections separated by 4 hyphens
+	doh.assertTrue(arrayOfParts[0].length == 8); // Section 0 has 8 characters
+	doh.assertTrue(arrayOfParts[1].length == 4); // Section 1 has 4 characters
+	doh.assertTrue(arrayOfParts[2].length == 4); // Section 2 has 4 characters
+	doh.assertTrue(arrayOfParts[3].length == 4); // Section 3 has 4 characters
+	doh.assertTrue(arrayOfParts[4].length == 12); // Section 4 has 8 characters
+
+	// check to see that the "UUID variant code" starts with the binary bits '10'
+	var section3 = arrayOfParts[3];
+	var HEX_RADIX = 16;
+	var hex3 = parseInt(section3, HEX_RADIX);
+	var binaryString = hex3.toString(2);
+	// alert("section3 = " + section3 + "\n binaryString = " + binaryString);
+	doh.assertTrue(binaryString.length == 16); // section 3 has 16 bits
+	doh.assertTrue(binaryString.charAt(0) == '1'); // first bit of section 3 is 1
+	doh.assertTrue(binaryString.charAt(1) == '0'); // second bit of section 3 is 0
+}
+
+dojox.uuid.tests.uuid.checkValidityOfTimeBasedUuidString = function(/*String*/uuidString){
+	// summary:
+	//		A helper function that's used by the registered test functions
+	dojox.uuid.tests.uuid.checkValidityOfUuidString(uuidString);
+	var arrayOfParts = uuidString.split("-");
+	var section2 = arrayOfParts[2];
+	doh.assertTrue(section2.charAt(0) == "1"); // Section 2 starts with a 1
+}
+
+dojox.uuid.tests.uuid.checkForPseudoNodeBitInTimeBasedUuidString = function(/*String*/uuidString){
+	// summary:
+	//		A helper function that's used by the registered test functions
+	var arrayOfParts = uuidString.split("-");
+	var section4 = arrayOfParts[4];
+	var firstChar = section4.charAt(0);
+	var HEX_RADIX = 16;
+	var hexFirstChar = parseInt(firstChar, HEX_RADIX);
+	var binaryString = hexFirstChar.toString(2);
+	var firstBit;
+	if(binaryString.length == 4){
+		firstBit = binaryString.charAt(0);
+	}else{
+		firstBit = '0';
+	}
+	doh.assertTrue(firstBit == '1'); // first bit of section 4 is 1
+}
+
+doh.register("dojox.uuid.tests.uuid", 
+	[
+		/*
+		function test_uuid_performance(){
+			var start = new Date();
+			var startMS = start.valueOf();
+			var nowMS = startMS;
+			var i;
+			var now;
+			var numTrials = 100000;
+		
+			while(nowMS == startMS){
+				now = new Date();
+				nowMS = now.valueOf();
+			}
+			
+			startMS = nowMS;
+			for(i = 0; i < numTrials; ++i){
+				var a = dojox.uuid.LightweightGenerator.generate();
+			}
+			now = new Date();
+			nowMS = now.valueOf();
+			var elapsedMS = nowMS - startMS;
+			// dojo.log.debug("created " + numTrials + " UUIDs in " + elapsedMS + " milliseconds");
+		},
+		*/
+
+		function test_uuid_capitalization(){
+			var randomLowercaseString = "3b12f1df-5232-4804-897e-917bf397618a";
+			var randomUppercaseString = "3B12F1DF-5232-4804-897E-917BF397618A";
+			
+			var timebasedLowercaseString = "b4308fb0-86cd-11da-a72b-0800200c9a66";
+			var timebasedUppercaseString = "B4308FB0-86CD-11DA-A72B-0800200C9A66";
+			
+			var uuidRL = new dojox.uuid.Uuid(randomLowercaseString);
+			var uuidRU = new dojox.uuid.Uuid(randomUppercaseString);
+			
+			var uuidTL = new dojox.uuid.Uuid(timebasedLowercaseString);
+			var uuidTU = new dojox.uuid.Uuid(timebasedUppercaseString);
+			
+			doh.assertTrue(uuidRL.isEqual(uuidRU));
+			doh.assertTrue(uuidRU.isEqual(uuidRL));
+			
+			doh.assertTrue(uuidTL.isEqual(uuidTU));
+			doh.assertTrue(uuidTU.isEqual(uuidTL));
+		},
+	
+		function test_uuid_constructor(){
+			var uuid, uuidToo;
+			
+			var nilUuid = '00000000-0000-0000-0000-000000000000';
+			uuid = new dojox.uuid.Uuid();
+			doh.assertTrue(uuid == nilUuid); // 'new dojox.uuid.Uuid()' returns the Nil UUID
+			
+			var randomUuidString = "3b12f1df-5232-4804-897e-917bf397618a";
+			uuid = new dojox.uuid.Uuid(randomUuidString);
+			doh.assertTrue(uuid.isValid());
+			doh.assertTrue(uuid.getVariant() == dojox.uuid.variant.DCE);
+			doh.assertTrue(uuid.getVersion() == dojox.uuid.version.RANDOM);
+			uuidToo = new dojox.uuid.Uuid(new String(randomUuidString));
+			doh.assertTrue(uuid.isEqual(uuidToo));	
+		
+			var timeBasedUuidString = "b4308fb0-86cd-11da-a72b-0800200c9a66";
+			uuid = new dojox.uuid.Uuid(timeBasedUuidString);
+			doh.assertTrue(uuid.isValid());
+			doh.assertTrue(uuid.getVariant() == dojox.uuid.variant.DCE);
+			doh.assertTrue(uuid.getVersion() == dojox.uuid.version.TIME_BASED);
+			doh.assertTrue(uuid.getNode() == "0800200c9a66");
+			var timestamp = uuid.getTimestamp();
+			var date = uuid.getTimestamp(Date);
+			var dateString = uuid.getTimestamp(String);
+			var hexString = uuid.getTimestamp("hex");
+			var now = new Date();
+			doh.assertTrue(timestamp.valueOf() == date.valueOf());
+			doh.assertTrue(hexString == "1da86cdb4308fb0");
+			doh.assertTrue(timestamp < now);
+		},
+		
+		function test_uuid_generators(){
+			var generators = [
+				dojox.uuid.generateNilUuid,
+				dojox.uuid.generateRandomUuid,
+				dojox.uuid.generateTimeBasedUuid
+			];
+			
+			for(var i in generators){
+				var generator = generators[i];
+				var uuidString = generator();
+
+				doh.assertTrue((typeof uuidString) == 'string');
+				dojox.uuid.tests.uuid.checkValidityOfUuidString(uuidString);
+
+				var uuid = new dojox.uuid.Uuid(uuidString);
+				if(generator != dojox.uuid.generateNilUuid){
+					doh.assertTrue(uuid.getVariant() == dojox.uuid.variant.DCE);
+				}
+
+				doh.assertTrue(uuid.isEqual(uuid));
+				doh.assertTrue(uuid.compare(uuid) == 0);
+				doh.assertTrue(dojox.uuid.Uuid.compare(uuid, uuid) == 0);
+				dojox.uuid.tests.uuid.checkValidityOfUuidString(uuid.toString());
+				doh.assertTrue(uuid.toString().length == 36);
+		
+				if(generator != dojox.uuid.generateNilUuid){
+					var uuidStringOne = generator();
+					var uuidStringTwo = generator();
+					doh.assertTrue(uuidStringOne != uuidStringTwo);
+					
+					dojox.uuid.Uuid.setGenerator(generator);
+					var uuidOne = new dojox.uuid.Uuid();
+					var uuidTwo = new dojox.uuid.Uuid();
+					doh.assertTrue(generator === dojox.uuid.Uuid.getGenerator());
+					dojox.uuid.Uuid.setGenerator(null);
+					doh.assertTrue(uuidOne != uuidTwo);
+					doh.assertTrue(!uuidOne.isEqual(uuidTwo));
+					doh.assertTrue(!uuidTwo.isEqual(uuidOne));
+					
+					var oneVsTwo = dojox.uuid.Uuid.compare(uuidOne, uuidTwo); // either 1 or -1
+					var twoVsOne = dojox.uuid.Uuid.compare(uuidTwo, uuidOne); // either -1 or 1
+					doh.assertTrue(oneVsTwo + twoVsOne == 0);
+					doh.assertTrue(oneVsTwo != 0);
+					doh.assertTrue(twoVsOne != 0);
+					
+					doh.assertTrue(!uuidTwo.isEqual(uuidOne));
+				}
+				
+				if(generator == dojox.uuid.generateRandomUuid){
+					doh.assertTrue(uuid.getVersion() == dojox.uuid.version.RANDOM);
+				}
+				
+				if(generator == dojox.uuid.generateTimeBasedUuid){
+					dojox.uuid.tests.uuid.checkValidityOfTimeBasedUuidString(uuid.toString());
+					doh.assertTrue(uuid.getVersion() == dojox.uuid.version.TIME_BASED);
+					doh.assertTrue(dojo.isString(uuid.getNode()));
+					doh.assertTrue(uuid.getNode().length == 12);
+					var timestamp = uuid.getTimestamp();
+					var date = uuid.getTimestamp(Date);
+					var dateString = uuid.getTimestamp(String);
+					var hexString = uuid.getTimestamp("hex");
+					doh.assertTrue(date instanceof Date);
+					doh.assertTrue(timestamp.valueOf() == date.valueOf());
+					doh.assertTrue(hexString.length == 15);
+				}
+			}
+		},
+		
+		function test_uuid_nilGenerator(){
+			var nilUuidString = '00000000-0000-0000-0000-000000000000';
+			var uuidString = dojox.uuid.generateNilUuid();
+			doh.assertTrue(uuidString == nilUuidString);
+		},
+		
+		function test_uuid_timeBasedGenerator(){
+			var uuid;   // an instance of dojox.uuid.Uuid
+			var string; // a simple string literal
+			var generator = dojox.uuid.generateTimeBasedUuid;
+
+			var string1 = generator();
+			var uuid2    = new dojox.uuid.Uuid(generator());
+			var string3 = generator("017bf397618a");         // hardwareNode
+			var string4 = generator("f17bf397618a");         // pseudoNode
+			var string5 = generator(new String("017BF397618A"));
+			
+			dojox.uuid.generateTimeBasedUuid.setNode("017bf397618a");
+			var string6 = generator(); // the generated UUID has node == "017bf397618a"
+			var uuid7   = new dojox.uuid.Uuid(generator()); // the generated UUID has node == "017bf397618a"
+			var returnedNode = dojox.uuid.generateTimeBasedUuid.getNode();
+			doh.assertTrue(returnedNode == "017bf397618a");
+		
+			function getNode(string){
+				var arrayOfStrings = string.split('-');
+				return arrayOfStrings[4];
+			}
+			dojox.uuid.tests.uuid.checkForPseudoNodeBitInTimeBasedUuidString(string1);
+			dojox.uuid.tests.uuid.checkForPseudoNodeBitInTimeBasedUuidString(uuid2.toString());
+			dojox.uuid.tests.uuid.checkForPseudoNodeBitInTimeBasedUuidString(string4);
+			
+			doh.assertTrue(getNode(string3) == "017bf397618a");
+			doh.assertTrue(getNode(string4) == "f17bf397618a");
+			doh.assertTrue(getNode(string5) == "017bf397618a");
+			doh.assertTrue(getNode(string6) == "017bf397618a");
+			doh.assertTrue(uuid7.getNode() == "017bf397618a");
+			
+			dojox.uuid.tests.uuid.checkValidityOfTimeBasedUuidString(string1);
+			dojox.uuid.tests.uuid.checkValidityOfTimeBasedUuidString(uuid2.toString());
+			dojox.uuid.tests.uuid.checkValidityOfTimeBasedUuidString(string3);
+			dojox.uuid.tests.uuid.checkValidityOfTimeBasedUuidString(string4);
+			dojox.uuid.tests.uuid.checkValidityOfTimeBasedUuidString(string5);
+			dojox.uuid.tests.uuid.checkValidityOfTimeBasedUuidString(string6);
+			dojox.uuid.tests.uuid.checkValidityOfTimeBasedUuidString(uuid7.toString());
+		},
+
+		function test_uuid_invalidUuids(){
+			var uuidStrings = [];
+			uuidStrings.push("Hello world!");                          // not a UUID
+			uuidStrings.push("3B12F1DF-5232-1804-897E-917BF39761");    // too short
+			uuidStrings.push("3B12F1DF-5232-1804-897E-917BF39761-8A"); // extra '-'
+			uuidStrings.push("3B12F1DF-5232-1804-897E917BF39761-8A");  // last '-' in wrong place
+			uuidStrings.push("HB12F1DF-5232-1804-897E-917BF397618A");  // "HB12F1DF" is not a hex string
+		
+			var numberOfFailures = 0;
+			for(var i in uuidStrings){
+				var uuidString = uuidStrings[i];
+				try{
+					new dojox.uuid.Uuid(uuidString);
+				}catch (e){
+					++numberOfFailures;
+				}
+			}
+			doh.assertTrue(numberOfFailures == uuidStrings.length);
+		}
+	]
+);
+
+
+
+/*
+function test_uuid_get64bitArrayFromFloat(){
+	// summary:
+	//		This is a test we'd like to be able to run, but we can't run it
+	//		because it tests a function which is private in generateTimeBasedUuid
+	var x = Math.pow(2, 63) + Math.pow(2, 15);
+	var result = dojox.uuid.generateTimeBasedUuid._get64bitArrayFromFloat(x);
+	doh.assertTrue(result[0] === 0x8000);
+	doh.assertTrue(result[1] === 0x0000);
+	doh.assertTrue(result[2] === 0x0000);
+	doh.assertTrue(result[3] === 0x8000);
+
+	var date = new Date();
+	x = date.valueOf();
+	result = dojox.uuid.generateTimeBasedUuid._get64bitArrayFromFloat(x);
+	var reconstructedFloat = result[0];
+	reconstructedFloat *= 0x10000;
+	reconstructedFloat += result[1];
+	reconstructedFloat *= 0x10000;
+	reconstructedFloat += result[2];
+	reconstructedFloat *= 0x10000;
+	reconstructedFloat += result[3];
+
+	doh.assertTrue(reconstructedFloat === x);
+}
+
+function test_uuid_addTwo64bitArrays(){
+	// summary:
+	//		This is a test we'd like to be able to run, but we can't run it
+	//		because it tests a function which is private in generateTimeBasedUuid
+	var a = [0x0000, 0x0000, 0x0000, 0x0001];
+	var b = [0x0FFF, 0xFFFF, 0xFFFF, 0xFFFF];
+	var result = dojox.uuid.generateTimeBasedUuid._addTwo64bitArrays(a, b);
+	doh.assertTrue(result[0] === 0x1000);
+	doh.assertTrue(result[1] === 0x0000);
+	doh.assertTrue(result[2] === 0x0000);
+	doh.assertTrue(result[3] === 0x0000);
+
+	a = [0x4000, 0x8000, 0x8000, 0x8000];
+	b = [0x8000, 0x8000, 0x8000, 0x8000];
+	result = dojox.uuid.generateTimeBasedUuid._addTwo64bitArrays(a, b);
+	doh.assertTrue(result[0] === 0xC001);
+	doh.assertTrue(result[1] === 0x0001);
+	doh.assertTrue(result[2] === 0x0001);
+	doh.assertTrue(result[3] === 0x0000);
+
+	a = [7, 6, 2, 5];
+	b = [1, 0, 3, 4];
+	result = dojox.uuid.generateTimeBasedUuid._addTwo64bitArrays(a, b);
+	doh.assertTrue(result[0] === 8);
+	doh.assertTrue(result[1] === 6);
+	doh.assertTrue(result[2] === 5);
+	doh.assertTrue(result[3] === 9);
+}
+
+function test_uuid_multiplyTwo64bitArrays(){
+	// summary:
+	//		This is a test we'd like to be able to run, but we can't run it
+	//		because it tests a function which is private in generateTimeBasedUuid
+	var a = [     0, 0x0000, 0x0000, 0x0003];
+	var b = [0x1111, 0x1234, 0x0000, 0xFFFF];
+	var result = dojox.uuid.generateTimeBasedUuid._multiplyTwo64bitArrays(a, b);
+	doh.assertTrue(result[0] === 0x3333);
+	doh.assertTrue(result[1] === 0x369C);
+	doh.assertTrue(result[2] === 0x0002);
+	doh.assertTrue(result[3] === 0xFFFD);
+
+	a = [0, 0, 0, 5];
+	b = [0, 0, 0, 4];
+	result = dojox.uuid.generateTimeBasedUuid._multiplyTwo64bitArrays(a, b);
+	doh.assertTrue(result[0] === 0);
+	doh.assertTrue(result[1] === 0);
+	doh.assertTrue(result[2] === 0);
+	doh.assertTrue(result[3] === 20);
+
+	a = [0, 0, 2, 5];
+	b = [0, 0, 3, 4];
+	result = dojox.uuid.generateTimeBasedUuid._multiplyTwo64bitArrays(a, b);
+	doh.assertTrue(result[0] === 0);
+	doh.assertTrue(result[1] === 6);
+	doh.assertTrue(result[2] === 23);
+	doh.assertTrue(result[3] === 20);
+}
+*/
diff --git a/dojox/validate.js b/dojox/validate.js
index 98ee537..be0fb1d 100644
--- a/dojox/validate.js
+++ b/dojox/validate.js
@@ -1,12 +1,2 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.validate"]){
-dojo._hasResource["dojox.validate"]=true;
 dojo.provide("dojox.validate");
-dojo.require("dojox.validate._base");
-}
+dojo.require("dojox.validate._base"); 
diff --git a/dojox/validate/_base.js b/dojox/validate/_base.js
index 5577fa0..11abd53 100644
--- a/dojox/validate/_base.js
+++ b/dojox/validate/_base.js
@@ -1,68 +1,135 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.validate._base"]){
-dojo._hasResource["dojox.validate._base"]=true;
 dojo.provide("dojox.validate._base");
 dojo.experimental("dojox.validate");
-dojo.require("dojo.regexp");
-dojo.require("dojo.number");
-dojo.require("dojox.validate.regexp");
-dojox.validate.isText=function(_1,_2){
-_2=(typeof _2=="object")?_2:{};
-if(/^\s*$/.test(_1)){
-return false;
-}
-if(typeof _2.length=="number"&&_2.length!=_1.length){
-return false;
-}
-if(typeof _2.minlength=="number"&&_2.minlength>_1.length){
-return false;
-}
-if(typeof _2.maxlength=="number"&&_2.maxlength<_1.length){
-return false;
-}
-return true;
-};
-dojox.validate._isInRangeCache={};
-dojox.validate.isInRange=function(_3,_4){
-_3=dojo.number.parse(_3,_4);
-if(isNaN(_3)){
-return false;
-}
-_4=(typeof _4=="object")?_4:{};
-var _5=(typeof _4.max=="number")?_4.max:Infinity,_6=(typeof _4.min=="number")?_4.min:-Infinity,_7=(typeof _4.decimal=="string")?_4.decimal:".",_8=dojox.validate._isInRangeCache,_9=_3+"max"+_5+"min"+_6+"dec"+_7;
-if(typeof _8[_9]!="undefined"){
-return _8[_9];
-}
-_8[_9]=!(_3<_6||_3>_5);
-return _8[_9];
-};
-dojox.validate.isNumberFormat=function(_a,_b){
-var re=new RegExp("^"+dojox.validate.regexp.numberFormat(_b)+"$","i");
-return re.test(_a);
-};
-dojox.validate.isValidLuhn=function(_c){
-var _d=0,_e,_f;
-if(!dojo.isString(_c)){
-_c=String(_c);
-}
-_c=_c.replace(/[- ]/g,"");
-_e=_c.length%2;
-for(var i=0;i<_c.length;i++){
-_f=parseInt(_c.charAt(i));
-if(i%2==_e){
-_f*=2;
+
+dojo.require("dojo.regexp");		// dojo core expressions
+dojo.require("dojo.number");		// dojo number expressions
+dojo.require("dojox.validate.regexp"); 	// additional expressions
+
+dojox.validate.isText = function(/*String*/value, /*Object?*/flags){
+	// summary:
+	//	Checks if a string has non whitespace characters. 
+	//	Parameters allow you to constrain the length.
+	//
+	// value: A string
+	// flags: {length: Number, minlength: Number, maxlength: Number}
+	//    flags.length  If set, checks if there are exactly flags.length number of characters.
+	//    flags.minlength  If set, checks if there are at least flags.minlength number of characters.
+	//    flags.maxlength  If set, checks if there are at most flags.maxlength number of characters.
+	
+	flags = (typeof flags == "object") ? flags : {};
+	
+	// test for text
+	if(/^\s*$/.test(value)){ return false; } // Boolean
+	
+	// length tests
+	if(typeof flags.length == "number" && flags.length != value.length){ return false; } // Boolean
+	if(typeof flags.minlength == "number" && flags.minlength > value.length){ return false; } // Boolean
+	if(typeof flags.maxlength == "number" && flags.maxlength < value.length){ return false; } // Boolean
+	
+	return true; // Boolean
+
 }
-if(_f>9){
-_f-=9;
+
+dojox.validate._isInRangeCache = {};
+dojox.validate.isInRange = function(/*String*/value, /*Object?*/flags){
+	// summary:
+	//	Validates whether a string denoting a number
+	//	is between a max and min. 
+	//
+	// value: A string
+	// flags: {max:Number, min:Number, decimal:String}
+	//    flags.max  A number, which the value must be less than or equal to for the validation to be true.
+	//    flags.min  A number, which the value must be greater than or equal to for the validation to be true.
+	//    flags.decimal  The character used for the decimal point.  Default is ".".
+	
+	value = dojo.number.parse(value, flags);
+	if(isNaN(value)){
+		return false; // Boolean
+	}
+    
+	// assign default values to missing paramters
+	flags = (typeof flags == "object") ? flags : {};
+	var max = (typeof flags.max == "number") ? flags.max : Infinity,
+		min = (typeof flags.min == "number") ? flags.min : -Infinity,
+		dec = (typeof flags.decimal == "string") ? flags.decimal : ".",
+	
+		cache = dojox.validate._isInRangeCache,
+		cacheIdx = value + "max" + max + "min" + min + "dec" + dec
+	;
+	if(typeof cache[cacheIdx] != "undefined"){
+		return cache[cacheIdx];
+	}
+
+	cache[cacheIdx] = !(value < min || value > max);
+	return cache[cacheIdx]; // Boolean
+
 }
-_d+=_f;
+
+dojox.validate.isNumberFormat = function(/* String */value, /* Object? */flags){
+	// summary: Validates any sort of number based format
+	//
+	// description:
+	//		Validates any sort of number based format. Use it for phone numbers,
+	//		social security numbers, zip-codes, etc. The value can be validated 
+	//		against one format or one of multiple formats.
+	//
+	// Format Definition
+	// |   #        Stands for a digit, 0-9.
+	// |   ?        Stands for an optional digit, 0-9 or nothing.
+	//    All other characters must appear literally in the expression.
+	//
+	// example:   
+	// |  "(###) ###-####"       ->   (510) 542-9742
+	// |  "(###) ###-#### x#???" ->   (510) 542-9742 x153
+	// |  "###-##-####"          ->   506-82-1089       i.e. social security number
+	// |  "#####-####"           ->   98225-1649        i.e. zip code
+	//
+	// value: A string
+	//
+	// flags: Object? 
+	//		FIXME: make pseudo-object for this
+	//		format: String
+	//			
+	//    flags.format  A string or an Array of strings for multiple formats.
+	//
+	// example:
+	// | // returns true:
+	// | dojox.validate.isNumberFormat("123-45", { format:"###-##" });
+	//
+	// example:
+	// 		Check Multiple formats:
+	// |	dojox.validate.isNumberFormat("123-45", {	
+	// |		format:["### ##","###-##","## ###"]
+	// |	});
+	//
+
+	var re = new RegExp("^" + dojox.validate.regexp.numberFormat(flags) + "$", "i");
+	return re.test(value); // Boolean
 }
-return !(_d%10);
-};
+
+dojox.validate.isValidLuhn = function(/* String */value){
+	// summary: Validate a String value against the Luhn algorithm.
+	// description:
+	//		Validate a String value against the Luhn algorithm to verify
+	//		its integrity. 
+	
+	var sum = 0, parity, curDigit;
+	if(!dojo.isString(value)){
+		value = String(value);
+	}
+	value = value.replace(/[- ]/g,''); //ignore dashes and whitespaces
+	parity = value.length % 2;
+
+	for(var i = 0; i < value.length; i++){
+		curDigit = parseInt(value.charAt(i));
+		if(i % 2 == parity){
+			curDigit *= 2;
+		}
+		if(curDigit > 9){
+			curDigit -= 9;
+		}
+		sum += curDigit;
+	}
+	return !(sum % 10); // Boolean
 }
+
diff --git a/dojox/validate/br.js b/dojox/validate/br.js
old mode 100644
new mode 100755
index c1c439c..9042ac2
--- a/dojox/validate/br.js
+++ b/dojox/validate/br.js
@@ -1,203 +1,275 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.validate.br"]){
-dojo._hasResource["dojox.validate.br"]=true;
 dojo.provide("dojox.validate.br");
 dojo.require("dojox.validate._base");
-dojox.validate.br.isValidCnpj=function(_1){
-if(!dojo.isString(_1)){
-if(!_1){
-return false;
-}
-_1=_1+"";
-while(_1.length<14){
-_1="0"+_1;
-}
-}
-var _2={format:["##.###.###/####-##","########/####-##","############-##","##############"]};
-if(dojox.validate.isNumberFormat(_1,_2)){
-_1=_1.replace("/","").replace(/\./g,"").replace("-","");
-var _3=[];
-var dv=[];
-var i,j,_4;
-for(i=0;i<10;i++){
-_4="";
-for(j=0;j<_1.length;j++){
-_4+=""+i;
-}
-if(_1===_4){
-return false;
-}
-}
-for(i=0;i<12;i++){
-_3.push(parseInt(_1.charAt(i),10));
-}
-for(i=12;i<14;i++){
-dv.push(parseInt(_1.charAt(i),10));
-}
-var _5=[9,8,7,6,5,4,3,2,9,8,7,6].reverse();
-var _6=0;
-for(i=0;i<_3.length;i++){
-_6+=_3[i]*_5[i];
-}
-var _7=_6%11;
-if(_7==dv[0]){
-_6=0;
-_5=[9,8,7,6,5,4,3,2,9,8,7,6,5].reverse();
-_3.push(_7);
-for(i=0;i<_3.length;i++){
-_6+=_3[i]*_5[i];
-}
-var _8=_6%11;
-if(_8===dv[1]){
-return true;
-}
-}
-}
-return false;
+
+dojox.validate.br.isValidCnpj = function(/*String*/value){
+	// summary: 
+	//		Validates a CNPJ/CGC number
+	//
+	// value: String
+	//		The CNPJ/CGC number in ##.###.###/####-##, ########/####-##,
+	//		############-## or ############## format
+	if(!dojo.isString(value)){
+		if(!value){
+			return false;
+		}
+		value = value + "";
+		while(value.length < 14){
+			value = "0" + value;
+		}
+	}
+	var flags = {
+		format: [
+			"##.###.###/####-##",
+			"########/####-##",
+			"############-##",
+			"##############"
+		]
+	};
+	if(dojox.validate.isNumberFormat(value, flags)){
+		// Matched the initial test, so break this down into the 
+		// parts to be validated.
+		value = value.replace("/", "").replace(/\./g, "").replace("-", "");
+		var cgc = [];
+		var dv = [];
+		var i, j, tmp;
+
+		// Check for obvious bad combos
+		// all 0s to all 9's.
+		for(i = 0; i < 10; i++){
+			tmp = "";
+			for(j = 0; j < value.length; j++){
+				tmp += "" + i; 
+			}
+			if(value === tmp){
+				return false;
+			}
+		}
+
+		//Split out the DV from the main number.
+		for(i = 0; i < 12; i++){
+			cgc.push(parseInt(value.charAt(i), 10));
+		}
+		for(i = 12; i < 14; i++){
+			dv.push(parseInt(value.charAt(i), 10));
+		}
+		
+		var base = [9,8,7,6,5,4,3,2,9,8,7,6].reverse();
+		var sum = 0;
+		for(i = 0; i < cgc.length; i++){
+			sum += cgc[i] * base[i];
+		}
+		var dv0 = sum % 11;
+		if(dv0 == dv[0]){
+			// Still seems valid, keep going.
+			sum = 0;
+			base = [9,8,7,6,5,4,3,2,9,8,7,6,5].reverse();
+			cgc.push(dv0);
+			for(i = 0; i < cgc.length; i++){
+				sum += cgc[i] * base[i];
+			}
+			var dv1 = sum % 11;
+			if(dv1 === dv[1]){
+				// Whew, looks valid.
+				return true;
+			}
+		}
+	}
+	return false;
 };
-dojox.validate.br.computeCnpjDv=function(_9){
-if(!dojo.isString(_9)){
-if(!_9){
-return "";
-}
-_9=_9+"";
-while(_9.length<12){
-_9="0"+_9;
-}
-}
-var _a={format:["##.###.###/####","########/####","############"]};
-if(dojox.validate.isNumberFormat(_9,_a)){
-_9=_9.replace("/","").replace(/\./g,"");
-var _b=[];
-var i,j,_c;
-for(i=0;i<10;i++){
-_c="";
-for(j=0;j<_9.length;j++){
-_c+=""+i;
-}
-if(_9===_c){
-return "";
-}
-}
-for(i=0;i<_9.length;i++){
-_b.push(parseInt(_9.charAt(i),10));
-}
-var _d=[9,8,7,6,5,4,3,2,9,8,7,6].reverse();
-var _e=0;
-for(i=0;i<_b.length;i++){
-_e+=_b[i]*_d[i];
-}
-var _f=_e%11;
-_e=0;
-_d=[9,8,7,6,5,4,3,2,9,8,7,6,5].reverse();
-_b.push(_f);
-for(i=0;i<_b.length;i++){
-_e+=_b[i]*_d[i];
-}
-var dv1=_e%11;
-return (""+_f)+dv1;
-}
-return "";
+
+dojox.validate.br.computeCnpjDv = function(/*String*/value){
+	// summary: Generate the DV code (checksum part) for a Cnpj number
+	//
+	// value: The CGC number in ##.###.###/#### or ############ format
+	if(!dojo.isString(value)){
+		if(!value){
+			return "";
+		}
+		value = value + "";
+		while(value.length < 12){
+			value = "0" + value;
+		}
+	}
+	var flags = {
+		format: [
+			"##.###.###/####",
+			"########/####",
+			"############"
+		]
+	};
+	if(dojox.validate.isNumberFormat(value, flags)){
+		// Matched the initial test, so break this down into the 
+		// parts to compute the DV.
+		value = value.replace("/", "").replace(/\./g, "");
+		var cgc = [];
+		var i, j, tmp;
+
+		// Check for obvious bad combos
+		// all 0s to all 9's.
+		for(i = 0; i < 10; i++){
+			tmp = "";
+			for(j = 0; j < value.length; j++){
+				tmp += "" + i; 
+			}
+			if(value === tmp){
+				return "";
+			}
+		}
+
+		for(i = 0; i < value.length; i++){
+			cgc.push(parseInt(value.charAt(i), 10));
+		}
+		var base = [9,8,7,6,5,4,3,2,9,8,7,6].reverse();
+		var sum = 0;
+		for(i = 0; i < cgc.length; i++){
+			sum += cgc[i] * base[i];
+		}
+		var dv0 = sum % 11;
+		sum = 0;
+		base = [9,8,7,6,5,4,3,2,9,8,7,6,5].reverse();
+		cgc.push(dv0);
+		for(i = 0; i < cgc.length; i++){
+			sum += cgc[i] * base[i];
+		}
+		var dv1 = sum % 11;
+		return ("" + dv0) + dv1;
+	}
+	return "";
 };
-dojox.validate.br.isValidCpf=function(_10){
-if(!dojo.isString(_10)){
-if(!_10){
-return false;
-}
-_10=_10+"";
-while(_10.length<11){
-_10="0"+_10;
-}
-}
-var _11={format:["###.###.###-##","#########-##","###########"]};
-if(dojox.validate.isNumberFormat(_10,_11)){
-_10=_10.replace("-","").replace(/\./g,"");
-var cpf=[];
-var dv=[];
-var i,j,tmp;
-for(i=0;i<10;i++){
-tmp="";
-for(j=0;j<_10.length;j++){
-tmp+=""+i;
-}
-if(_10===tmp){
-return false;
-}
-}
-for(i=0;i<9;i++){
-cpf.push(parseInt(_10.charAt(i),10));
-}
-for(i=9;i<12;i++){
-dv.push(parseInt(_10.charAt(i),10));
-}
-var _12=[9,8,7,6,5,4,3,2,1].reverse();
-var sum=0;
-for(i=0;i<cpf.length;i++){
-sum+=cpf[i]*_12[i];
-}
-var dv0=sum%11;
-if(dv0==dv[0]){
-sum=0;
-_12=[9,8,7,6,5,4,3,2,1,0].reverse();
-cpf.push(dv0);
-for(i=0;i<cpf.length;i++){
-sum+=cpf[i]*_12[i];
-}
-var dv1=sum%11;
-if(dv1===dv[1]){
-return true;
-}
-}
-}
-return false;
+
+
+dojox.validate.br.isValidCpf = function(/*String*/value){
+	// summary: 
+	//		Validates a CPF number
+	//
+	// value: String
+	//		The CPF number in #########-## or ###########,
+	//		format
+	if(!dojo.isString(value)){
+		if(!value){
+			return false;
+		}
+		value = value + "";
+		while(value.length < 11){
+			value = "0" + value;
+		}
+	}
+	var flags = {
+		format: [
+			"###.###.###-##",
+			"#########-##",
+			"###########"
+		]
+	};
+	if(dojox.validate.isNumberFormat(value, flags)){
+		// Matched the initial test, so break this down into the 
+		// parts to be validated.
+		value = value.replace("-", "").replace(/\./g, "");
+		var cpf = [];
+		var dv = [];
+		var i, j, tmp;
+
+		// Check for obvious bad combos
+		// all 0s to all 9's.
+		for(i = 0; i < 10; i++){
+			tmp = "";
+			for(j = 0; j < value.length; j++){
+				tmp += "" + i; 
+			}
+			if(value === tmp){
+				return false;
+			}
+		}
+
+		//Split out the DV from the main number.
+		for(i = 0; i < 9; i++){
+			cpf.push(parseInt(value.charAt(i), 10));
+		}
+		for(i = 9; i < 12; i++){
+			dv.push(parseInt(value.charAt(i), 10));
+		}
+		
+		var base = [9,8,7,6,5,4,3,2,1].reverse();
+		var sum = 0;
+		for(i = 0; i < cpf.length; i++){
+			sum += cpf[i] * base[i];
+		}
+		var dv0 = sum % 11;
+		if(dv0 == dv[0]){
+			// Still seems valid, keep going.
+			sum = 0;
+			base = [9,8,7,6,5,4,3,2,1,0].reverse();
+			cpf.push(dv0);
+			for(i = 0; i < cpf.length; i++){
+				sum += cpf[i] * base[i];
+			}
+			var dv1 = sum % 11;
+			if(dv1 === dv[1]){
+				// Whew, looks valid.
+				return true;
+			}
+		}
+	}
+	return false;
 };
-dojox.validate.br.computeCpfDv=function(_13){
-if(!dojo.isString(_13)){
-if(!_13){
-return "";
-}
-_13=_13+"";
-while(_13.length<9){
-_13="0"+_13;
-}
-}
-var _14={format:["###.###.###","#########"]};
-if(dojox.validate.isNumberFormat(_13,_14)){
-_13=_13.replace(/\./g,"");
-var cpf=[];
-for(i=0;i<10;i++){
-tmp="";
-for(j=0;j<_13.length;j++){
-tmp+=""+i;
-}
-if(_13===tmp){
-return "";
-}
-}
-for(i=0;i<_13.length;i++){
-cpf.push(parseInt(_13.charAt(i),10));
-}
-var _15=[9,8,7,6,5,4,3,2,1].reverse();
-var sum=0;
-for(i=0;i<cpf.length;i++){
-sum+=cpf[i]*_15[i];
-}
-var dv0=sum%11;
-sum=0;
-_15=[9,8,7,6,5,4,3,2,1,0].reverse();
-cpf.push(dv0);
-for(i=0;i<cpf.length;i++){
-sum+=cpf[i]*_15[i];
-}
-var dv1=sum%11;
-return (""+dv0)+dv1;
-}
-return "";
+
+dojox.validate.br.computeCpfDv = function(/*String*/value){
+	// summary: 
+	//		Generate the DV code (checksum part) for a CPF number
+	//
+	// value: String
+	//		The CPF number in ######### format
+	if(!dojo.isString(value)){
+		if(!value){
+			return "";
+		}
+		value = value + "";
+		while(value.length < 9){
+			value = "0" + value;
+		}
+	}
+	var flags = {
+		format: [
+			"###.###.###",
+			"#########"
+		]
+	};
+	if(dojox.validate.isNumberFormat(value, flags)){
+		// Matched the initial test, so break this down into the 
+		// parts to compute the DV.
+		value = value.replace(/\./g, "");
+		var cpf = [];
+		
+		// Check for obvious bad combos
+		// all 0s to all 9's.
+		for(i = 0; i < 10; i++){
+			tmp = "";
+			for(j = 0; j < value.length; j++){
+				tmp += "" + i; 
+			}
+			if(value === tmp){
+				return "";
+			}
+		}
+
+		for(i = 0; i < value.length; i++){
+			cpf.push(parseInt(value.charAt(i), 10));
+		}
+		var base = [9,8,7,6,5,4,3,2,1].reverse();
+		var sum = 0;
+		for(i = 0; i < cpf.length; i++){
+			sum += cpf[i] * base[i];
+		}
+		var dv0 = sum % 11;
+		sum = 0;
+		base = [9,8,7,6,5,4,3,2,1,0].reverse();
+		cpf.push(dv0);
+		for(i = 0; i < cpf.length; i++){
+			sum += cpf[i] * base[i];
+		}
+		var dv1 = sum % 11;
+		return ("" + dv0) + dv1;
+	}
+	return "";
 };
-}
+
diff --git a/dojox/validate/ca.js b/dojox/validate/ca.js
index 3b84da5..d3c16a9 100644
--- a/dojox/validate/ca.js
+++ b/dojox/validate/ca.js
@@ -1,24 +1,50 @@
-/*
-	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
-*/
+dojo.provide("dojox.validate.ca");
+/*=====
 
+	dojox.validate.ca = {
+		// summary: Module which includes Canadian-specific methods for dojox.validate
+	}
 
-if(!dojo._hasResource["dojox.validate.ca"]){
-dojo._hasResource["dojox.validate.ca"]=true;
-dojo.provide("dojox.validate.ca");
+=====*/
 dojo.require("dojox.validate._base");
-dojo.mixin(dojox.validate.ca,{isPhoneNumber:function(_1){
-return dojox.validate.us.isPhoneNumber(_1);
-},isProvince:function(_2){
-var re=new RegExp("^"+dojox.validate.regexp.ca.province()+"$","i");
-return re.test(_2);
-},isSocialInsuranceNumber:function(_3){
-var _4={format:["###-###-###","### ### ###","#########"]};
-return dojox.validate.isNumberFormat(_3,_4);
-},isPostalCode:function(_5){
-var re=new RegExp("^"+dojox.validate.regexp.ca.postalCode()+"$","i");
-return re.test(_5);
-}});
-}
+
+dojo.mixin(dojox.validate.ca,{
+	
+	isPhoneNumber: function(/* String */value){
+		// summary: Validates Canadian 10-digit phone number for several common formats
+		return dojox.validate.us.isPhoneNumber(value);  // Boolean
+	},
+
+	isProvince: function(/* String[2] */value) {
+		// summary: Validates Canadian province abbreviations (2 characters)
+		var re = new RegExp("^" + dojox.validate.regexp.ca.province() + "$", "i");
+		return re.test(value); // Boolean
+	}, 
+ 
+	isSocialInsuranceNumber: function(/* String */value) {
+		// summary: Validates Canadian 9 digit social insurance number for several 
+		//		common formats
+		//
+		// description:
+		//		Validates Canadian 9 digit social insurance number for several 
+		//		common formats. This routine only pattern matches and does not 
+		//		use the Luhn Algorithm to validate number.
+		//
+		var flags = { format: [ "###-###-###", "### ### ###", "#########" ]};
+		return dojox.validate.isNumberFormat(value, flags); // Boolean
+	},
+
+	isPostalCode: function(value) {
+		// summary: Validates Canadian 6 digit postal code
+		// 
+		// description:
+		//		Validates Canadian 6 digit postal code.
+		//		Canadian postal codes are in the format ANA NAN,
+		//		where A is a letter and N is a digit, with a space
+		//		separating the third and fourth characters.
+		//
+		var re = new RegExp("^" + dojox.validate.regexp.ca.postalCode() + "$", "i");
+		return re.test(value); // Boolean
+	}
+
+});
diff --git a/dojox/validate/check.js b/dojox/validate/check.js
index c3aadaf..8ebe6a4 100644
--- a/dojox/validate/check.js
+++ b/dojox/validate/check.js
@@ -1,230 +1,324 @@
-/*
-	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
+dojo.provide("dojox.validate.check");
+dojo.experimental
+dojo.require("dojox.validate._base");
+
+/**
+	FIXME: How much does this overlap with dojox.form.Manager and friends?
+
+	Procedural API Description
+
+		The main aim is to make input validation expressible in a simple format.
+		You define profiles which declare the required and optional fields and any constraints they might have.
+		The results are provided as an object that makes it easy to handle missing and invalid input.
+
+	Usage
+
+		var results = dojox.validate.check(form, profile);
+
+	Profile Object
+
+		var profile = {
+			// filters change the field value and are applied before validation.
+			trim: ["tx1", "tx2"],
+			uppercase: ["tx9"],
+			lowercase: ["tx5", "tx6", "tx7"],
+			ucfirst: ["tx10"],
+			digit: ["tx11"],
+
+			// required input fields that are blank will be reported missing.
+			// required radio button groups and drop-down lists with no selection will be reported missing.
+			// checkbox groups and selectboxes can be required to have more than one value selected.
+			// List required fields by name and use this notation to require more than one value: {checkboxgroup: 2}, {selectboxname: 3}.
+			required: ["tx7", "tx8", "pw1", "ta1", "rb1", "rb2", "cb3", "s1", {"doubledip":2}, {"tripledip":3}],
+
+			// dependant/conditional fields are required if the target field is present and not blank.
+			// At present only textbox, password, and textarea fields are supported.
+			dependencies:	{
+				cc_exp: "cc_no",	
+				cc_type: "cc_no"	
+			},
+
+			// Fields can be validated using any boolean valued function.  
+			// Use arrays to specify parameters in addition to the field value.
+			constraints: {
+				field_name1: myValidationFunction,
+				field_name2: dojox.validate.isInteger,
+				field_name3: [myValidationFunction, additional parameters],
+				field_name4: [dojox.validate.isValidDate, "YYYY.MM.DD"],
+				field_name5: [dojox.validate.isEmailAddress, false, true]
+			},
+
+			// Confirm is a sort of conditional validation.
+			// It associates each field in its property list with another field whose value should be equal.
+			// If the values are not equal, the field in the property list is reported as Invalid. Unless the target field is blank.
+			confirm: {
+				email_confirm: "email",	
+				pw2: "pw1"
+			}
+		};
+
+	Results Object
+
+		isSuccessful(): Returns true if there were no invalid or missing fields, else it returns false.
+		hasMissing():  Returns true if the results contain any missing fields.
+		getMissing():  Returns a list of required fields that have values missing.
+		isMissing(field):  Returns true if the field is required and the value is missing.
+		hasInvalid():  Returns true if the results contain fields with invalid data.
+		getInvalid():  Returns a list of fields that have invalid values.
+		isInvalid(field):  Returns true if the field has an invalid value.
+
 */
 
+dojox.validate.check = function(/*HTMLFormElement*/form, /*Object*/profile){
+	// summary: validates user input of an HTML form based on input profile
+	//
+	// description:
+	//	returns an object that contains several methods summarizing the results of the validation
+	//
+	// form: form to be validated
+	// profile: specifies how the form fields are to be validated
+	// {trim:Array, uppercase:Array, lowercase:Array, ucfirst:Array, digit:Array,
+	//	required:Array, dependencies:Object, constraints:Object, confirm:Object}
 
-if(!dojo._hasResource["dojox.validate.check"]){
-dojo._hasResource["dojox.validate.check"]=true;
-dojo.provide("dojox.validate.check");
-dojo.experimental;
-dojo.require("dojox.validate._base");
-dojox.validate.check=function(_1,_2){
-var _3=[];
-var _4=[];
-var _5={isSuccessful:function(){
-return (!this.hasInvalid()&&!this.hasMissing());
-},hasMissing:function(){
-return (_3.length>0);
-},getMissing:function(){
-return _3;
-},isMissing:function(_6){
-for(var i=0;i<_3.length;i++){
-if(_6==_3[i]){
-return true;
-}
-}
-return false;
-},hasInvalid:function(){
-return (_4.length>0);
-},getInvalid:function(){
-return _4;
-},isInvalid:function(_7){
-for(var i=0;i<_4.length;i++){
-if(_7==_4[i]){
-return true;
-}
-}
-return false;
-}};
-var _8=function(_9,_a){
-return (typeof _a[_9]=="undefined");
-};
-if(_2.trim instanceof Array){
-for(var i=0;i<_2.trim.length;i++){
-var _b=_1[_2.trim[i]];
-if(_8("type",_b)||_b.type!="text"&&_b.type!="textarea"&&_b.type!="password"){
-continue;
-}
-_b.value=_b.value.replace(/(^\s*|\s*$)/g,"");
-}
-}
-if(_2.uppercase instanceof Array){
-for(var i=0;i<_2.uppercase.length;i++){
-var _b=_1[_2.uppercase[i]];
-if(_8("type",_b)||_b.type!="text"&&_b.type!="textarea"&&_b.type!="password"){
-continue;
-}
-_b.value=_b.value.toUpperCase();
-}
-}
-if(_2.lowercase instanceof Array){
-for(var i=0;i<_2.lowercase.length;i++){
-var _b=_1[_2.lowercase[i]];
-if(_8("type",_b)||_b.type!="text"&&_b.type!="textarea"&&_b.type!="password"){
-continue;
-}
-_b.value=_b.value.toLowerCase();
-}
-}
-if(_2.ucfirst instanceof Array){
-for(var i=0;i<_2.ucfirst.length;i++){
-var _b=_1[_2.ucfirst[i]];
-if(_8("type",_b)||_b.type!="text"&&_b.type!="textarea"&&_b.type!="password"){
-continue;
-}
-_b.value=_b.value.replace(/\b\w+\b/g,function(_c){
-return _c.substring(0,1).toUpperCase()+_c.substring(1).toLowerCase();
-});
-}
-}
-if(_2.digit instanceof Array){
-for(var i=0;i<_2.digit.length;i++){
-var _b=_1[_2.digit[i]];
-if(_8("type",_b)||_b.type!="text"&&_b.type!="textarea"&&_b.type!="password"){
-continue;
-}
-_b.value=_b.value.replace(/\D/g,"");
-}
-}
-if(_2.required instanceof Array){
-for(var i=0;i<_2.required.length;i++){
-if(!dojo.isString(_2.required[i])){
-continue;
-}
-var _b=_1[_2.required[i]];
-if(!_8("type",_b)&&(_b.type=="text"||_b.type=="textarea"||_b.type=="password"||_b.type=="file")&&/^\s*$/.test(_b.value)){
-_3[_3.length]=_b.name;
-}else{
-if(!_8("type",_b)&&(_b.type=="select-one"||_b.type=="select-multiple")&&(_b.selectedIndex==-1||/^\s*$/.test(_b.options[_b.selectedIndex].value))){
-_3[_3.length]=_b.name;
-}else{
-if(_b instanceof Array){
-var _d=false;
-for(var j=0;j<_b.length;j++){
-if(_b[j].checked){
-_d=true;
-}
-}
-if(!_d){
-_3[_3.length]=_b[0].name;
-}
-}
-}
-}
-}
-}
-if(_2.required instanceof Array){
-for(var i=0;i<_2.required.length;i++){
-if(!dojo.isObject(_2.required[i])){
-continue;
-}
-var _b,_e;
-for(var _f in _2.required[i]){
-_b=_1[_f];
-_e=_2.required[i][_f];
-}
-if(_b instanceof Array){
-var _d=0;
-for(var j=0;j<_b.length;j++){
-if(_b[j].checked){
-_d++;
-}
-}
-if(_d<_e){
-_3[_3.length]=_b[0].name;
-}
-}else{
-if(!_8("type",_b)&&_b.type=="select-multiple"){
-var _10=0;
-for(var j=0;j<_b.options.length;j++){
-if(_b.options[j].selected&&!/^\s*$/.test(_b.options[j].value)){
-_10++;
-}
-}
-if(_10<_e){
-_3[_3.length]=_b.name;
-}
-}
-}
-}
-}
-if(dojo.isObject(_2.dependencies)){
-for(_f in _2.dependencies){
-var _b=_1[_f];
-if(_8("type",_b)){
-continue;
-}
-if(_b.type!="text"&&_b.type!="textarea"&&_b.type!="password"){
-continue;
-}
-if(/\S+/.test(_b.value)){
-continue;
-}
-if(_5.isMissing(_b.name)){
-continue;
-}
-var _11=_1[_2.dependencies[_f]];
-if(_11.type!="text"&&_11.type!="textarea"&&_11.type!="password"){
-continue;
-}
-if(/^\s*$/.test(_11.value)){
-continue;
-}
-_3[_3.length]=_b.name;
-}
-}
-if(dojo.isObject(_2.constraints)){
-for(_f in _2.constraints){
-var _b=_1[_f];
-if(!_b){
-continue;
-}
-if(!_8("tagName",_b)&&(_b.tagName.toLowerCase().indexOf("input")>=0||_b.tagName.toLowerCase().indexOf("textarea")>=0)&&/^\s*$/.test(_b.value)){
-continue;
-}
-var _12=true;
-if(dojo.isFunction(_2.constraints[_f])){
-_12=_2.constraints[_f](_b.value);
-}else{
-if(dojo.isArray(_2.constraints[_f])){
-if(dojo.isArray(_2.constraints[_f][0])){
-for(var i=0;i<_2.constraints[_f].length;i++){
-_12=dojox.validate.evaluateConstraint(_2,_2.constraints[_f][i],_f,_b);
-if(!_12){
-break;
-}
-}
-}else{
-_12=dojox.validate.evaluateConstraint(_2,_2.constraints[_f],_f,_b);
-}
-}
-}
-if(!_12){
-_4[_4.length]=_b.name;
-}
-}
-}
-if(dojo.isObject(_2.confirm)){
-for(_f in _2.confirm){
-var _b=_1[_f];
-var _11=_1[_2.confirm[_f]];
-if(_8("type",_b)||_8("type",_11)||(_b.type!="text"&&_b.type!="textarea"&&_b.type!="password")||(_11.type!=_b.type)||(_11.value==_b.value)||(_5.isInvalid(_b.name))||(/^\s*$/.test(_11.value))){
-continue;
-}
-_4[_4.length]=_b.name;
-}
-}
-return _5;
-};
-dojox.validate.evaluateConstraint=function(_13,_14,_15,_16){
-var _17=_14[0];
-var _18=_14.slice(1);
-_18.unshift(_16.value);
-if(typeof _17!="undefined"){
-return _17.apply(null,_18);
-}
-return false;
+	// Essentially private properties of results object
+	var missing = [];
+	var invalid = [];
+
+	// results object summarizes the validation
+	var results = {
+		isSuccessful: function() {return ( !this.hasInvalid() && !this.hasMissing() );},
+		hasMissing: function() {return ( missing.length > 0 );},
+		getMissing: function() {return missing;},
+		isMissing: function(elemname) {
+			for(var i = 0; i < missing.length; i++){
+				if(elemname == missing[i]){ return true; }
+			}
+			return false;
+		},
+		hasInvalid: function() {return ( invalid.length > 0 );},
+		getInvalid: function() {return invalid;},
+		isInvalid: function(elemname){
+			for(var i = 0; i < invalid.length; i++){
+				if(elemname == invalid[i]){ return true; }
+			}
+			return false;
+		}
+	};
+
+	var _undef = function(name,object){
+                return (typeof object[name] == "undefined");
+        };
+
+	// Filters are applied before fields are validated.
+	// Trim removes white space at the front and end of the fields.
+	if(profile.trim instanceof Array){
+		for(var i = 0; i < profile.trim.length; i++){
+			var elem = form[profile.trim[i]];
+			if(_undef("type", elem) || elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; }
+			elem.value = elem.value.replace(/(^\s*|\s*$)/g, "");
+		}
+	}
+	// Convert to uppercase
+	if(profile.uppercase instanceof Array){
+		for(var i = 0; i < profile.uppercase.length; i++){
+			var elem = form[profile.uppercase[i]];
+			if(_undef("type", elem) || elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; }
+			elem.value = elem.value.toUpperCase();
+		}
+	}
+	// Convert to lowercase
+	if(profile.lowercase instanceof Array){
+		for (var i = 0; i < profile.lowercase.length; i++){
+			var elem = form[profile.lowercase[i]];
+			if(_undef("type", elem) || elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; }
+			elem.value = elem.value.toLowerCase();
+		}
+	}
+	// Uppercase first letter
+	if(profile.ucfirst instanceof Array){
+		for(var i = 0; i < profile.ucfirst.length; i++){
+			var elem = form[profile.ucfirst[i]];
+			if(_undef("type", elem) || elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; }
+			elem.value = elem.value.replace(/\b\w+\b/g, function(word) { return word.substring(0,1).toUpperCase() + word.substring(1).toLowerCase(); });
+		}
+	}
+	// Remove non digits characters from the input.
+	if(profile.digit instanceof Array){
+		for(var i = 0; i < profile.digit.length; i++){
+			var elem = form[profile.digit[i]];
+			if(_undef("type", elem) || elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; }
+			elem.value = elem.value.replace(/\D/g, "");
+		}
+	}
+
+	// See if required input fields have values missing.
+	if(profile.required instanceof Array){
+		for(var i = 0; i < profile.required.length; i++){ 
+			if(!dojo.isString(profile.required[i])){ continue; }
+			var elem = form[profile.required[i]];
+			// Are textbox, textarea, or password fields blank.
+			if(!_undef("type", elem) 
+				&& (elem.type == "text" || elem.type == "textarea" || elem.type == "password" || elem.type == "file") 
+				&& /^\s*$/.test(elem.value)){	
+				missing[missing.length] = elem.name;
+			}
+			// Does drop-down box have option selected.
+			else if(!_undef("type", elem) && (elem.type == "select-one" || elem.type == "select-multiple") 
+						&& (elem.selectedIndex == -1 
+						|| /^\s*$/.test(elem.options[elem.selectedIndex].value))){
+				missing[missing.length] = elem.name;
+			}
+			// Does radio button group (or check box group) have option checked.
+			else if(elem instanceof Array){
+				var checked = false;
+				for(var j = 0; j < elem.length; j++){
+					if (elem[j].checked) { checked = true; }
+				}
+				if(!checked){	
+					missing[missing.length] = elem[0].name;
+				}
+			}
+		}
+	}
+
+	// See if checkbox groups and select boxes have x number of required values.
+	if(profile.required instanceof Array){
+		for (var i = 0; i < profile.required.length; i++){ 
+			if(!dojo.isObject(profile.required[i])){ continue; }
+			var elem, numRequired;
+			for(var name in profile.required[i]){ 
+				elem = form[name]; 
+				numRequired = profile.required[i][name];
+			}
+			// case 1: elem is a check box group
+			if(elem instanceof Array){
+				var checked = 0;
+				for(var j = 0; j < elem.length; j++){
+					if(elem[j].checked){ checked++; }
+				}
+				if(checked < numRequired){	
+					missing[missing.length] = elem[0].name;
+				}
+			}
+			// case 2: elem is a select box
+			else if(!_undef("type", elem) && elem.type == "select-multiple" ){
+				var selected = 0;
+				for(var j = 0; j < elem.options.length; j++){
+					if (elem.options[j].selected && !/^\s*$/.test(elem.options[j].value)) { selected++; }
+				}
+				if(selected < numRequired){	
+					missing[missing.length] = elem.name;
+				}
+			}
+		}
+	}
+
+	// Dependent fields are required when the target field is present (not blank).
+	// Todo: Support dependent and target fields that are radio button groups, or select drop-down lists.
+	// Todo: Make the dependency based on a specific value of the target field.
+	// Todo: allow dependent fields to have several required values, like {checkboxgroup: 3}.
+	if(dojo.isObject(profile.dependencies)){
+		// properties of dependencies object are the names of dependent fields to be checked
+		for(name in profile.dependencies){
+			var elem = form[name];	// the dependent element
+			if(_undef("type", elem)){continue;}
+			if(elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; } // limited support
+			if(/\S+/.test(elem.value)){ continue; }	// has a value already
+			if(results.isMissing(elem.name)){ continue; }	// already listed as missing
+			var target = form[profile.dependencies[name]];
+			if(target.type != "text" && target.type != "textarea" && target.type != "password"){ continue; }	// limited support
+			if(/^\s*$/.test(target.value)){ continue; }	// skip if blank
+			missing[missing.length] = elem.name;	// ok the dependent field is missing
+		}
+	}
+
+	// Find invalid input fields.
+	if(dojo.isObject(profile.constraints)){
+		// constraint properties are the names of fields to bevalidated
+		for(name in profile.constraints){
+			var elem = form[name];
+			if(!elem) {continue;}
+			
+			// skip if blank - its optional unless required, in which case it
+			// is already listed as missing.
+			if(!_undef("tagName",elem) 
+				&& (elem.tagName.toLowerCase().indexOf("input") >= 0
+					|| elem.tagName.toLowerCase().indexOf("textarea") >= 0) 
+				&& /^\s*$/.test(elem.value)){ 
+				continue; 
+			}
+			
+			var isValid = true;
+			// case 1: constraint value is validation function
+			if(dojo.isFunction(profile.constraints[name])){
+				isValid = profile.constraints[name](elem.value);
+			}else if(dojo.isArray(profile.constraints[name])){
+				
+				// handle nested arrays for multiple constraints
+				if(dojo.isArray(profile.constraints[name][0])){
+					for (var i=0; i<profile.constraints[name].length; i++){
+						isValid = dojox.validate.evaluateConstraint(profile, profile.constraints[name][i], name, elem);
+						if(!isValid){ break; }
+					}
+				}else{
+					// case 2: constraint value is array, first elem is function,
+					// tail is parameters
+					isValid = dojox.validate.evaluateConstraint(profile, profile.constraints[name], name, elem);
+				}
+			}
+			
+			if(!isValid){	
+				invalid[invalid.length] = elem.name;
+			}
+		}
+	}
+
+	// Find unequal confirm fields and report them as Invalid.
+	if(dojo.isObject(profile.confirm)){
+		for(name in profile.confirm){
+			var elem = form[name];	// the confirm element
+			var target = form[profile.confirm[name]];
+			if (_undef("type", elem) || _undef("type", target) || (elem.type != "text" && elem.type != "textarea" && elem.type != "password") 
+				||(target.type != elem.type)
+				||(target.value == elem.value)	// it's valid
+				||(results.isInvalid(elem.name))// already listed as invalid
+				||(/^\s*$/.test(target.value)))	// skip if blank - only confirm if target has a value
+			{
+				continue; 
+			}
+			invalid[invalid.length] = elem.name;
+		}
+	}
+	return results; // Object
 };
+
+//TODO: evaluateConstraint doesn't use profile or fieldName args?
+dojox.validate.evaluateConstraint=function(profile, /*Array*/constraint, fieldName, elem){
+	// summary:
+	//	Evaluates dojo.validate.check() constraints that are specified as array
+	//	arguments
+	//
+	// description: The arrays are expected to be in the format of:
+	//      constraints:{
+	//              fieldName: [functionToCall, param1, param2, etc.],
+	//              fieldName: [[functionToCallFirst, param1],[functionToCallSecond,param2]]
+	//      }
+	// 
+	//  This function evaluates a single array function in the format of:
+	//      [functionName, argument1, argument2, etc]
+	// 
+	//  The function will be parsed out and evaluated against the incoming parameters.
+	//
+	// profile: The dojo.validate.check() profile that this evaluation is against.
+	// constraint: The single [] array of function and arguments for the function.
+	// fieldName: The form dom name of the field being validated.
+	// elem: The form element field.
+	
+ 	var isValidSomething = constraint[0];
+	var params = constraint.slice(1);
+	params.unshift(elem.value);
+	if(typeof isValidSomething != "undefined"){
+		return isValidSomething.apply(null, params);
+	}
+	return false; // Boolean
 }
diff --git a/dojox/validate/creditCard.js b/dojox/validate/creditCard.js
index 8bec221..f2e2674 100644
--- a/dojox/validate/creditCard.js
+++ b/dojox/validate/creditCard.js
@@ -1,48 +1,124 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.validate.creditCard"]){
-dojo._hasResource["dojox.validate.creditCard"]=true;
 dojo.provide("dojox.validate.creditCard");
+/*=====
+
+	dojox.validate.creditCard = {
+		// summary: 
+		//		Module provides validation functions for Credit Cards, using account number 
+		//		rules in conjunction with the Luhn algorigthm, with a plugable card info database.
+	};
+	
+=====*/
 dojo.require("dojox.validate._base");
-dojox.validate._cardInfo={"mc":"5[1-5][0-9]{14}","ec":"5[1-5][0-9]{14}","vi":"4(?:[0-9]{12}|[0-9]{15})","ax":"3[47][0-9]{13}","dc":"3(?:0[0-5][0-9]{11}|[68][0-9]{12})","bl":"3(?:0[0-5][0-9]{11}|[68][0-9]{12})","di":"6011[0-9]{12}","jcb":"(?:3[0-9]{15}|(2131|1800)[0-9]{11})","er":"2(?:014|149)[0-9]{11}"};
-dojox.validate.isValidCreditCard=function(_1,_2){
-return ((_2.toLowerCase()=="er"||dojox.validate.isValidLuhn(_1))&&dojox.validate.isValidCreditCardNumber(_1,_2.toLowerCase()));
-};
-dojox.validate.isValidCreditCardNumber=function(_3,_4){
-_3=String(_3).replace(/[- ]/g,"");
-var _5=dojox.validate._cardInfo,_6=[];
-if(_4){
-var _7=_5[_4.toLowerCase()];
-return _7?!!_3.match(_7):false;
-}
-for(var p in _5){
-if(_3.match("^"+_5[p]+"$")){
-_6.push(p);
-}
+
+dojox.validate._cardInfo = {
+	// summary: A dictionary list of credit card abbreviations 
+	//
+	// description: 
+	//	
+	//		A hash of valid CC abbreviations and regular expressions 
+	//	
+	//		mc: Mastercard
+	//		ec: Eurocard
+	//		vi: Visa
+	//		ax: American Express
+	//		dc: Diners Club
+	//		bl: Carte Blanch
+	//		di: Discover
+	//		jcb: JCB
+	//		er: Enroute
+	//
+	//	example:
+	//		Define your own card, gift-card, whatever. Starts with 7,
+	//		is 15 total length.
+	//	| dojo.mixin(dojox.validate._cardInfo, {
+	//	| 	"my":"7[0-9]{14}"
+	//	| });	
+	
+	'mc':'5[1-5][0-9]{14}',
+	'ec':'5[1-5][0-9]{14}',
+	'vi':'4(?:[0-9]{12}|[0-9]{15})',
+	'ax':'3[47][0-9]{13}', 
+	'dc':'3(?:0[0-5][0-9]{11}|[68][0-9]{12})',
+	'bl':'3(?:0[0-5][0-9]{11}|[68][0-9]{12})',
+	'di':'6011[0-9]{12}',
+	'jcb':'(?:3[0-9]{15}|(2131|1800)[0-9]{11})',
+	'er':'2(?:014|149)[0-9]{11}'
 }
-return _6.length?_6.join("|"):false;
-};
-dojox.validate.isValidCvv=function(_8,_9){
-if(!dojo.isString(_8)){
-_8=String(_8);
+
+dojox.validate.isValidCreditCard = function(value, ccType){
+	// summary: Validate a credit card number by type with Luhn checking.
+	//
+	// description:
+	//		Checks if a credit card type matches the # scheme in a passed value, and if 
+	//		the Luhn checksum is accurate (unless its an Enroute card, in which case 
+	//		the checkSum is skipped), returning a Boolean to check against. 
+	//
+	// value: String|Int
+	//		A Value (credit card number) to validate
+	//
+	// ccType: String
+	//		A credit-card abbreviation. 
+	//
+	// example:
+	// |	if(dojox.validate.isValidCreditCard("12345", "mc")){ 
+	// |		console.log('inconceivable'); 
+	// |	}
+	
+	return ((ccType.toLowerCase() == 'er' || dojox.validate.isValidLuhn(value)) &&
+			dojox.validate.isValidCreditCardNumber(value, ccType.toLowerCase())); // Boolean
 }
-var _a;
-switch(_9.toLowerCase()){
-case "mc":
-case "ec":
-case "vi":
-case "di":
-_a="###";
-break;
-case "ax":
-_a="####";
-break;
+
+dojox.validate.isValidCreditCardNumber = function(value, ccType){
+	// summary: 
+	//		Checks if value matches the pattern for that card or any card types if none is specified
+	//
+	// value: String|Int
+	//		CC #, white spaces and dashes are ignored
+	//
+	// ccType: String?
+	//		One of the abbreviation values in `dojox.validate._cardInfo` -- 
+	//		if Omitted, function returns a `|` delimited string of matching card types, 
+	//		or false if no matches found.
+
+	value = String(value).replace(/[- ]/g,''); //ignore dashes and whitespaces
+
+	var cardinfo = dojox.validate._cardInfo, results = [];
+	if(ccType){
+		var expr = '^' + cardinfo[ccType.toLowerCase()] + '$';
+		return expr ? !!value.match(expr) : false; // boolean
+	}
+
+	for(var p in cardinfo){
+		if(value.match('^' + cardinfo[p] + '$')){
+			results.push(p);
+		}
+	}
+	return results.length ? results.join('|') : false; // String | boolean
 }
-return !!_a&&_8.length&&dojox.validate.isNumberFormat(_8,{format:_a});
-};
+
+dojox.validate.isValidCvv = function(/* String|Int */value, /* String */ccType) {
+	// summary:
+	//  	Validate the security code (CCV) for a passed credit-card type.
+	//
+	// description:
+	// 
+	// value: 
+	
+	if(!dojo.isString(value)){
+		value = String(value);
+	}
+	var format;
+	switch (ccType.toLowerCase()){
+		case 'mc':
+		case 'ec':
+		case 'vi':
+		case 'di':
+			format = '###';
+			break;
+		case 'ax':
+			format = '####';
+			break;
+	}
+	
+	return !!format && value.length && dojox.validate.isNumberFormat(value, { format: format }); // Boolean
 }
diff --git a/dojox/validate/isbn.js b/dojox/validate/isbn.js
index 3e118f5..66949c2 100644
--- a/dojox/validate/isbn.js
+++ b/dojox/validate/isbn.js
@@ -1,40 +1,38 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.validate.isbn"]){
-dojo._hasResource["dojox.validate.isbn"]=true;
 dojo.provide("dojox.validate.isbn");
-dojox.validate.isValidIsbn=function(_1){
-var _2,_3=0,_4;
-if(!dojo.isString(_1)){
-_1=String(_1);
-}
-_1=_1.replace(/[- ]/g,"");
-_2=_1.length;
-switch(_2){
-case 10:
-_4=_2;
-for(var i=0;i<9;i++){
-_3+=parseInt(_1.charAt(i))*_4;
-_4--;
-}
-var t=_1.charAt(9).toUpperCase();
-_3+=t=="X"?10:parseInt(t);
-return _3%11==0;
-break;
-case 13:
-_4=-1;
-for(var i=0;i<_2;i++){
-_3+=parseInt(_1.charAt(i))*(2+_4);
-_4*=-1;
-}
-return _3%10==0;
-break;
-}
-return false;
-};
+// summary: Provides ISBN validation functions in `dojox.validate`
+//
+dojox.validate.isValidIsbn = function(/* String */value) {
+	// summary: Validate ISBN-10 or ISBN-13 based on the length of value
+	// value: String
+	//		An ISBN to validate
+	// returns: Boolean
+	var len, sum = 0, weight;
+	if(!dojo.isString(value)){
+		value = String(value);
+	}
+	value = value.replace(/[- ]/g,''); //ignore dashes and whitespaces
+	len = value.length;
+
+	switch(len){
+		case 10: 
+			weight = len;
+			// ISBN-10 validation algorithm
+			for(var i = 0; i < 9; i++){
+				sum += parseInt(value.charAt(i)) * weight;
+				weight--;
+			}
+			var t = value.charAt(9).toUpperCase();
+			sum += t == 'X' ? 10 : parseInt(t);
+			return sum % 11 == 0; // Boolean			
+			break;
+		case 13:
+			weight = -1;
+			for(var i = 0; i< len; i++){
+				sum += parseInt(value.charAt(i)) * (2 + weight);
+				weight *= -1;
+			}
+			return sum % 10 == 0; // Boolean		
+			break;			
+	}
+	return false;
 }
diff --git a/dojox/validate/regexp.js b/dojox/validate/regexp.js
index 7f3fc7c..73eac32 100644
--- a/dojox/validate/regexp.js
+++ b/dojox/validate/regexp.js
@@ -1,164 +1,280 @@
-/*
-	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
-*/
+dojo.provide("dojox.validate.regexp");
 
+dojo.require("dojo.regexp"); 
 
-if(!dojo._hasResource["dojox.validate.regexp"]){
-dojo._hasResource["dojox.validate.regexp"]=true;
-dojo.provide("dojox.validate.regexp");
-dojo.require("dojo.regexp");
-dojo.mixin(dojox.validate.regexp,{ipAddress:function(_1){
-_1=(typeof _1=="object")?_1:{};
-if(typeof _1.allowDottedDecimal!="boolean"){
-_1.allowDottedDecimal=true;
-}
-if(typeof _1.allowDottedHex!="boolean"){
-_1.allowDottedHex=true;
-}
-if(typeof _1.allowDottedOctal!="boolean"){
-_1.allowDottedOctal=true;
-}
-if(typeof _1.allowDecimal!="boolean"){
-_1.allowDecimal=true;
-}
-if(typeof _1.allowHex!="boolean"){
-_1.allowHex=true;
-}
-if(typeof _1.allowIPv6!="boolean"){
-_1.allowIPv6=true;
-}
-if(typeof _1.allowHybrid!="boolean"){
-_1.allowHybrid=true;
-}
-var _2="((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])";
-var _3="(0[xX]0*[\\da-fA-F]?[\\da-fA-F]\\.){3}0[xX]0*[\\da-fA-F]?[\\da-fA-F]";
-var _4="(0+[0-3][0-7][0-7]\\.){3}0+[0-3][0-7][0-7]";
-var _5="(0|[1-9]\\d{0,8}|[1-3]\\d{9}|4[01]\\d{8}|42[0-8]\\d{7}|429[0-3]\\d{6}|"+"4294[0-8]\\d{5}|42949[0-5]\\d{4}|429496[0-6]\\d{3}|4294967[01]\\d{2}|42949672[0-8]\\d|429496729[0-5])";
-var _6="0[xX]0*[\\da-fA-F]{1,8}";
-var _7="([\\da-fA-F]{1,4}\\:){7}[\\da-fA-F]{1,4}";
-var _8="([\\da-fA-F]{1,4}\\:){6}"+"((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])";
-var a=[];
-if(_1.allowDottedDecimal){
-a.push(_2);
-}
-if(_1.allowDottedHex){
-a.push(_3);
-}
-if(_1.allowDottedOctal){
-a.push(_4);
-}
-if(_1.allowDecimal){
-a.push(_5);
-}
-if(_1.allowHex){
-a.push(_6);
-}
-if(_1.allowIPv6){
-a.push(_7);
-}
-if(_1.allowHybrid){
-a.push(_8);
-}
-var _9="";
-if(a.length>0){
-_9="("+a.join("|")+")";
-}
-return _9;
-},host:function(_a){
-_a=(typeof _a=="object")?_a:{};
-if(typeof _a.allowIP!="boolean"){
-_a.allowIP=true;
-}
-if(typeof _a.allowLocal!="boolean"){
-_a.allowLocal=false;
-}
-if(typeof _a.allowPort!="boolean"){
-_a.allowPort=true;
-}
-if(typeof _a.allowNamed!="boolean"){
-_a.allowNamed=false;
-}
-var _b="(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)";
-var _c="(?:[a-zA-Z](?:[-\\da-zA-Z]{0,6}[\\da-zA-Z])?)";
-var _d=_a.allowPort?"(\\:\\d+)?":"";
-var _e="((?:"+_b+"\\.)+"+_c+"\\.?)";
-if(_a.allowIP){
-_e+="|"+dojox.validate.regexp.ipAddress(_a);
-}
-if(_a.allowLocal){
-_e+="|localhost";
-}
-if(_a.allowNamed){
-_e+="|^[^-][a-zA-Z0-9_-]*";
-}
-return "("+_e+")"+_d;
-},url:function(_f){
-_f=(typeof _f=="object")?_f:{};
-if(!("scheme" in _f)){
-_f.scheme=[true,false];
-}
-var _10=dojo.regexp.buildGroupRE(_f.scheme,function(q){
-if(q){
-return "(https?|ftps?)\\://";
-}
-return "";
+dojo.mixin(dojox.validate.regexp, {
+	
+	ipAddress: function(/*Object?*/flags){
+		// summary: Builds a RE that matches an IP Address
+		//
+		// description:
+		//  Supports 5 formats for IPv4: dotted decimal, dotted hex, dotted octal, decimal and hexadecimal.
+		//  Supports 2 formats for Ipv6.
+		//
+		// flags  An object.  All flags are boolean with default = true.
+		//    flags.allowDottedDecimal  Example, 207.142.131.235.  No zero padding.
+		//    flags.allowDottedHex  Example, 0x18.0x11.0x9b.0x28.  Case insensitive.  Zero padding allowed.
+		//    flags.allowDottedOctal  Example, 0030.0021.0233.0050.  Zero padding allowed.
+		//    flags.allowDecimal  Example, 3482223595.  A decimal number between 0-4294967295.
+		//    flags.allowHex  Example, 0xCF8E83EB.  Hexadecimal number between 0x0-0xFFFFFFFF.
+		//      Case insensitive.  Zero padding allowed.
+		//    flags.allowIPv6   IPv6 address written as eight groups of four hexadecimal digits.
+		//	FIXME: ipv6 can be written multiple ways IIRC
+		//    flags.allowHybrid   IPv6 address written as six groups of four hexadecimal digits
+		//      followed by the usual 4 dotted decimal digit notation of IPv4. x:x:x:x:x:x:d.d.d.d
+
+		// assign default values to missing paramters
+		flags = (typeof flags == "object") ? flags : {};
+		if(typeof flags.allowDottedDecimal != "boolean"){ flags.allowDottedDecimal = true; }
+		if(typeof flags.allowDottedHex != "boolean"){ flags.allowDottedHex = true; }
+		if(typeof flags.allowDottedOctal != "boolean"){ flags.allowDottedOctal = true; }
+		if(typeof flags.allowDecimal != "boolean"){ flags.allowDecimal = true; }
+		if(typeof flags.allowHex != "boolean"){ flags.allowHex = true; }
+		if(typeof flags.allowIPv6 != "boolean"){ flags.allowIPv6 = true; }
+		if(typeof flags.allowHybrid != "boolean"){ flags.allowHybrid = true; }
+
+		// decimal-dotted IP address RE.
+		var dottedDecimalRE = 
+			// Each number is between 0-255.  Zero padding is not allowed.
+			"((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])";
+
+		// dotted hex IP address RE.  Each number is between 0x0-0xff.  Zero padding is allowed, e.g. 0x00.
+		var dottedHexRE = "(0[xX]0*[\\da-fA-F]?[\\da-fA-F]\\.){3}0[xX]0*[\\da-fA-F]?[\\da-fA-F]";
+
+		// dotted octal IP address RE.  Each number is between 0000-0377.  
+		// Zero padding is allowed, but each number must have at least 4 characters.
+		var dottedOctalRE = "(0+[0-3][0-7][0-7]\\.){3}0+[0-3][0-7][0-7]";
+
+		// decimal IP address RE.  A decimal number between 0-4294967295.  
+		var decimalRE =  "(0|[1-9]\\d{0,8}|[1-3]\\d{9}|4[01]\\d{8}|42[0-8]\\d{7}|429[0-3]\\d{6}|" +
+			"4294[0-8]\\d{5}|42949[0-5]\\d{4}|429496[0-6]\\d{3}|4294967[01]\\d{2}|42949672[0-8]\\d|429496729[0-5])";
+
+		// hexadecimal IP address RE. 
+		// A hexadecimal number between 0x0-0xFFFFFFFF. Case insensitive.  Zero padding is allowed.
+		var hexRE = "0[xX]0*[\\da-fA-F]{1,8}";
+
+		// IPv6 address RE. 
+		// The format is written as eight groups of four hexadecimal digits, x:x:x:x:x:x:x:x,
+		// where x is between 0000-ffff. Zero padding is optional. Case insensitive. 
+		var ipv6RE = "([\\da-fA-F]{1,4}\\:){7}[\\da-fA-F]{1,4}";
+
+		// IPv6/IPv4 Hybrid address RE. 
+		// The format is written as six groups of four hexadecimal digits, 
+		// followed by the 4 dotted decimal IPv4 format. x:x:x:x:x:x:d.d.d.d
+		var hybridRE = "([\\da-fA-F]{1,4}\\:){6}" + 
+			"((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])";
+
+		// Build IP Address RE
+		var a = [];
+		if(flags.allowDottedDecimal){ a.push(dottedDecimalRE); }
+		if(flags.allowDottedHex){ a.push(dottedHexRE); }
+		if(flags.allowDottedOctal){ a.push(dottedOctalRE); }
+		if(flags.allowDecimal){ a.push(decimalRE); }
+		if(flags.allowHex){ a.push(hexRE); }
+		if(flags.allowIPv6){ a.push(ipv6RE); }
+		if(flags.allowHybrid){ a.push(hybridRE); }
+
+		var ipAddressRE = "";
+		if(a.length > 0){
+			ipAddressRE = "(" + a.join("|") + ")";
+		}
+		return ipAddressRE; // String
+	},
+
+	host: function(/*Object?*/flags){
+		// summary: Builds a RE that matches a host
+		// description: A host is a named host (A-z0-9_- but not starting with -), a domain name or an IP address, possibly followed by a port number.
+		// flags: An object.
+		//	  flags.allowNamed Allow a named host for local networks. Default is false.
+		//    flags.allowIP  Allow an IP address for hostname.  Default is true.
+		//    flags.allowLocal  Allow the host to be "localhost".  Default is false.
+		//    flags.allowPort  Allow a port number to be present.  Default is true.
+		//    flags in regexp.ipAddress can be applied.
+
+		// assign default values to missing paramters
+		flags = (typeof flags == "object") ? flags : {};
+
+		if(typeof flags.allowIP != "boolean"){ flags.allowIP = true; }
+		if(typeof flags.allowLocal != "boolean"){ flags.allowLocal = false; }
+		if(typeof flags.allowPort != "boolean"){ flags.allowPort = true; }
+		if(typeof flags.allowNamed != "boolean"){ flags.allowNamed = false; }
+
+		//TODO: support unicode hostnames?
+		// Domain name labels can not end with a dash.
+		var domainLabelRE = "(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)";
+		var domainNameRE = "(?:[a-zA-Z](?:[-\\da-zA-Z]{0,6}[\\da-zA-Z])?)"; // restricted version to allow backwards compatibility with allowLocal, allowIP
+
+		// port number RE
+		var portRE = flags.allowPort ? "(\\:\\d+)?" : "";
+
+		// build host RE
+		var hostNameRE = "((?:" + domainLabelRE + "\\.)+" + domainNameRE + "\\.?)";
+		if(flags.allowIP){ hostNameRE += "|" +  dojox.validate.regexp.ipAddress(flags); }
+		if(flags.allowLocal){ hostNameRE += "|localhost"; }
+		if(flags.allowNamed){ hostNameRE += "|^[^-][a-zA-Z0-9_-]*"; }
+		return "(" + hostNameRE + ")" + portRE; // String
+
+	},
+
+	url: function(/*Object?*/flags){
+		// summary: Builds a regular expression that matches a URL
+		//
+		// flags: An object
+		//    flags.scheme  Can be true, false, or [true, false]. 
+		//      This means: required, not allowed, or match either one.
+		//    flags in regexp.host can be applied.
+		//    flags in regexp.ipAddress can be applied.
+
+		// assign default values to missing paramters
+		flags = (typeof flags == "object") ? flags : {};
+		if(!("scheme" in flags)){ flags.scheme = [true, false]; }
+
+		// Scheme RE
+		var protocolRE = dojo.regexp.buildGroupRE(flags.scheme,
+			function(q){ if(q){ return "(https?|ftps?)\\://"; } return ""; }
+		);
+
+		// Path and query and anchor RE
+		var pathRE = "(/(?:[^?#\\s/]+/)*(?:[^?#\\s/]+(?:\\?[^?#\\s/]*)?(?:#[A-Za-z][\\w.:-]*)?)?)?";
+
+		return protocolRE + dojox.validate.regexp.host(flags) + pathRE;
+	},
+
+	emailAddress: function(/*Object?*/flags){
+
+		// summary: Builds a regular expression that matches an email address
+		//
+		//flags: An object
+		//    flags.allowCruft  Allow address like <mailto:foo at yahoo.com>.  Default is false.
+		//    flags in regexp.host can be applied.
+		//    flags in regexp.ipAddress can be applied.
+
+		// assign default values to missing paramters
+		flags = (typeof flags == "object") ? flags : {};
+		if (typeof flags.allowCruft != "boolean") { flags.allowCruft = false; }
+		flags.allowPort = false; // invalid in email addresses
+
+		// user name RE per rfc5322
+		var usernameRE = "([!#-'*+\\-\\/-9=?A-Z^-~]+[.])*[!#-'*+\\-\\/-9=?A-Z^-~]+";
+
+		// build emailAddress RE
+		var emailAddressRE = usernameRE + "@" + dojox.validate.regexp.host(flags);
+
+		// Allow email addresses with cruft
+		if ( flags.allowCruft ) {
+			emailAddressRE = "<?(mailto\\:)?" + emailAddressRE + ">?";
+		}
+
+		return emailAddressRE; // String
+	},
+
+	emailAddressList: function(/*Object?*/flags){
+		// summary: Builds a regular expression that matches a list of email addresses.
+		//
+		// flags: An object.
+		//    flags.listSeparator  The character used to separate email addresses.  Default is ";", ",", "\n" or " ".
+		//    flags in regexp.emailAddress can be applied.
+		//    flags in regexp.host can be applied.
+		//    flags in regexp.ipAddress can be applied.
+
+		// assign default values to missing paramters
+		flags = (typeof flags == "object") ? flags : {};
+		if(typeof flags.listSeparator != "string"){ flags.listSeparator = "\\s;,"; }
+
+		// build a RE for an Email Address List
+		var emailAddressRE = dojox.validate.regexp.emailAddress(flags);
+		var emailAddressListRE = "(" + emailAddressRE + "\\s*[" + flags.listSeparator + "]\\s*)*" + 
+			emailAddressRE + "\\s*[" + flags.listSeparator + "]?\\s*";
+
+		return emailAddressListRE; // String
+	},
+	
+	numberFormat: function(/*Object?*/flags){
+		// summary: Builds a regular expression to match any sort of number based format
+		// description:
+		//  Use this method for phone numbers, social security numbers, zip-codes, etc.
+		//  The RE can match one format or one of multiple formats.
+		//
+		//  Format
+		//    #        Stands for a digit, 0-9.
+		//    ?        Stands for an optional digit, 0-9 or nothing.
+		//    All other characters must appear literally in the expression.
+		//
+		//  Example   
+		//    "(###) ###-####"       ->   (510) 542-9742
+		//    "(###) ###-#### x#???" ->   (510) 542-9742 x153
+		//    "###-##-####"          ->   506-82-1089       i.e. social security number
+		//    "#####-####"           ->   98225-1649        i.e. zip code
+		//
+		// flags:  An object
+		//    flags.format  A string or an Array of strings for multiple formats.
+
+		// assign default values to missing paramters
+		flags = (typeof flags == "object") ? flags : {};
+		if(typeof flags.format == "undefined"){ flags.format = "###-###-####"; }
+
+		// Converts a number format to RE.
+		var digitRE = function(format){
+			// escape all special characters, except '?'
+			return dojo.regexp.escapeString(format, "?")
+				// Now replace '?' with Regular Expression
+				.replace(/\?/g, "\\d?")
+				// replace # with Regular Expression
+				.replace(/#/g, "\\d")
+			;
+		};
+
+		// build RE for multiple number formats
+		return dojo.regexp.buildGroupRE(flags.format, digitRE); //String
+	}
+	
 });
-var _11="(/(?:[^?#\\s/]+/)*(?:[^?#\\s/]+(?:\\?[^?#\\s/]*)?(?:#[A-Za-z][\\w.:-]*)?)?)?";
-return _10+dojox.validate.regexp.host(_f)+_11;
-},emailAddress:function(_12){
-_12=(typeof _12=="object")?_12:{};
-if(typeof _12.allowCruft!="boolean"){
-_12.allowCruft=false;
-}
-_12.allowPort=false;
-var _13="([!#-'*+\\-\\/-9=?A-Z^-~]+[.])*[!#-'*+\\-\\/-9=?A-Z^-~]+";
-var _14=_13+"@"+dojox.validate.regexp.host(_12);
-if(_12.allowCruft){
-_14="<?(mailto\\:)?"+_14+">?";
-}
-return _14;
-},emailAddressList:function(_15){
-_15=(typeof _15=="object")?_15:{};
-if(typeof _15.listSeparator!="string"){
-_15.listSeparator="\\s;,";
-}
-var _16=dojox.validate.regexp.emailAddress(_15);
-var _17="("+_16+"\\s*["+_15.listSeparator+"]\\s*)*"+_16+"\\s*["+_15.listSeparator+"]?\\s*";
-return _17;
-},numberFormat:function(_18){
-_18=(typeof _18=="object")?_18:{};
-if(typeof _18.format=="undefined"){
-_18.format="###-###-####";
-}
-var _19=function(_1a){
-return dojo.regexp.escapeString(_1a,"?").replace(/\?/g,"\\d?").replace(/#/g,"\\d");
+
+dojox.validate.regexp.ca = {
+	
+	postalCode: function(){
+		// summary: String regular Express to match Canadain Postal Codes
+		return "([A-Z][0-9][A-Z] [0-9][A-Z][0-9])";
+	},
+
+	province: function(){
+		// summary: a regular expression to match Canadian Province Abbreviations
+		return "(AB|BC|MB|NB|NL|NS|NT|NU|ON|PE|QC|SK|YT)";
+	}
+	
+};
+
+dojox.validate.regexp.us = {
+	
+	state: function(/*Object?*/flags){
+		// summary: A regular expression to match US state and territory abbreviations
+		//
+		// flags  An object.
+		//    flags.allowTerritories  Allow Guam, Puerto Rico, etc.  Default is true.
+		//    flags.allowMilitary  Allow military 'states', e.g. Armed Forces Europe (AE).  Default is true.
+
+		// assign default values to missing paramters
+		flags = (typeof flags == "object") ? flags : {};
+		if(typeof flags.allowTerritories != "boolean"){ flags.allowTerritories = true; }
+		if(typeof flags.allowMilitary != "boolean"){ flags.allowMilitary = true; }
+
+		// state RE
+		var statesRE = 
+			"AL|AK|AZ|AR|CA|CO|CT|DE|DC|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|" + 
+			"NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY";
+
+		// territories RE
+		var territoriesRE = "AS|FM|GU|MH|MP|PW|PR|VI";
+
+		// military states RE
+		var militaryRE = "AA|AE|AP";
+
+		// Build states and territories RE
+		if(flags.allowTerritories){ statesRE += "|" + territoriesRE; }
+		if(flags.allowMilitary){ statesRE += "|" + militaryRE; }
+
+		return "(" + statesRE + ")"; // String
+	}
+	
 };
-return dojo.regexp.buildGroupRE(_18.format,_19);
-}});
-dojox.validate.regexp.ca={postalCode:function(){
-return "([A-Z][0-9][A-Z] [0-9][A-Z][0-9])";
-},province:function(){
-return "(AB|BC|MB|NB|NL|NS|NT|NU|ON|PE|QC|SK|YT)";
-}};
-dojox.validate.regexp.us={state:function(_1b){
-_1b=(typeof _1b=="object")?_1b:{};
-if(typeof _1b.allowTerritories!="boolean"){
-_1b.allowTerritories=true;
-}
-if(typeof _1b.allowMilitary!="boolean"){
-_1b.allowMilitary=true;
-}
-var _1c="AL|AK|AZ|AR|CA|CO|CT|DE|DC|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|"+"NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY";
-var _1d="AS|FM|GU|MH|MP|PW|PR|VI";
-var _1e="AA|AE|AP";
-if(_1b.allowTerritories){
-_1c+="|"+_1d;
-}
-if(_1b.allowMilitary){
-_1c+="|"+_1e;
-}
-return "("+_1c+")";
-}};
-}
+
diff --git a/dojox/validate/tests/br.js b/dojox/validate/tests/br.js
new file mode 100755
index 0000000..041b9cc
--- /dev/null
+++ b/dojox/validate/tests/br.js
@@ -0,0 +1,104 @@
+dojo.provide("dojox.validate.tests.br");
+dojo.require("dojox.validate.br");
+
+
+tests.register("dojox.validate.tests.br",[
+	//Randomy generated valid CNJP/CGC numbers.
+	{
+		name:"isValidCnpj",
+		runTest: function(doh) { 
+			doh.assertTrue(dojox.validate.br.isValidCnpj('75.730.657/0001-03'), "1 Checking ##.###.###/####-## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj('75730657/0001-03'), "1 Checking ########/####-## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj('757306570001-03'), "1 Checking ############-## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj('75730657000103'), "1 Checking ############## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj(75730657000103), "1 Checking numeric ############## format");
+
+			doh.assertTrue(dojox.validate.br.isValidCnpj('05.101.993/0001-01'), "2 Checking ##.###.###/####-## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj('05101993/0001-01'), "2 Checking ########/####-## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj('051019930001-01'), "2 Checking ############-## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj('05101993000101'), "2 Checking ############## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj(5101993000101), "2 Checking numeric ############## format");
+
+			doh.assertTrue(dojox.validate.br.isValidCnpj('79.577.986/0001-17'), "3 Checking ##.###.###/####-## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj('79577986/0001-17'), "3 Checking ########/####-## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj('795779860001-17'), "3 Checking ############-## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj('79577986000117'), "3 Checking ############## format");
+			doh.assertTrue(dojox.validate.br.isValidCnpj(79577986000117), "3 Checking numeric ############## format");
+
+			doh.assertFalse(dojox.validate.br.isValidCnpj('79.577.986/0001-18'), "4 Checking ##.###.###/####-## format");
+			doh.assertFalse(dojox.validate.br.isValidCnpj('79577986/0001-18'), "4 Checking ########/####-## format");
+			doh.assertFalse(dojox.validate.br.isValidCnpj('795779860001-18'), "4 Checking ############-## format");
+			doh.assertFalse(dojox.validate.br.isValidCnpj('79577986000118'), "4 Checking ############## format");
+			doh.assertFalse(dojox.validate.br.isValidCnpj(79577986000118), "4 Checking numeric ############## format");
+			doh.assertFalse(dojox.validate.br.isValidCnpj(0), "5 Checking numeric ############## format");
+			doh.assertFalse(dojox.validate.br.isValidCnpj('00000000000000'), "4 Checking numeric ############## format");
+			doh.assertFalse(dojox.validate.br.isValidCnpj('11111111111111'), "4 Checking numeric ############## format");
+			doh.assertFalse(dojox.validate.br.isValidCnpj('22222222222222'), "4 Checking numeric ############## format");
+		}
+	},
+	{
+		name:"computeCnpjDv",
+		runTest: function(doh) { 
+			doh.assertEqual("03", dojox.validate.br.computeCnpjDv('75.730.657/0001'), "1 Checking ##.###.###/#### format");
+			doh.assertEqual("03", dojox.validate.br.computeCnpjDv('75730657/0001'), "1 Checking ########/#### format");
+			doh.assertEqual("03", dojox.validate.br.computeCnpjDv('757306570001'), "1 Checking ############ format");
+			doh.assertEqual("03", dojox.validate.br.computeCnpjDv(757306570001), "1 Checking numeric ############ format");
+
+			doh.assertEqual("01", dojox.validate.br.computeCnpjDv('05.101.993/0001'), "2 Checking ##.###.###/#### format");
+			doh.assertEqual("01", dojox.validate.br.computeCnpjDv('05101993/0001'), "2 Checking ########/#### format");
+			doh.assertEqual("01", dojox.validate.br.computeCnpjDv('051019930001'), "2 Checking ############ format");
+			doh.assertEqual("01", dojox.validate.br.computeCnpjDv(51019930001), "2 Checking numeric ############ format");
+
+			doh.assertEqual("17", dojox.validate.br.computeCnpjDv('79.577.986/0001'), "3 Checking ##.###.###/#### format");
+			doh.assertEqual("17", dojox.validate.br.computeCnpjDv('79577986/0001'), "3 Checking ########/#### format");
+			doh.assertEqual("17", dojox.validate.br.computeCnpjDv('795779860001'), "3 Checking ############ format");
+			doh.assertEqual("17", dojox.validate.br.computeCnpjDv(795779860001), "3 Checking numeric ############ format");
+		}
+	},
+	//All CPF numbers randomly generated from: http://www.gerardocumentos.com.br
+	{
+		name:"isValidCpf",
+		runTest: function(doh) { 
+			doh.assertTrue(dojox.validate.br.isValidCpf('362.866.226-59'), "1 Checking ###.###.###-## format");
+			doh.assertTrue(dojox.validate.br.isValidCpf('362866226-59'), "1 Checking #########-## format");
+			doh.assertTrue(dojox.validate.br.isValidCpf('36286622659'), "1 Checking ########### format");
+			doh.assertTrue(dojox.validate.br.isValidCpf(36286622659), "1 Checking numeric ########### format");
+
+			doh.assertTrue(dojox.validate.br.isValidCpf('781.215.062-39'), "2 Checking ###.###.###-## format");
+			doh.assertTrue(dojox.validate.br.isValidCpf('781215062-39'), "2 Checking #########-## format");
+			doh.assertTrue(dojox.validate.br.isValidCpf('78121506239'), "2 Checking ########### format");
+			doh.assertTrue(dojox.validate.br.isValidCpf(78121506239), "2 Checking numeric ########### format");
+
+			doh.assertTrue(dojox.validate.br.isValidCpf('670.832.400-86'), "3 Checking ###.###.###-## format");
+			doh.assertTrue(dojox.validate.br.isValidCpf('670832400-86'), "3 Checking #########-## format");
+			doh.assertTrue(dojox.validate.br.isValidCpf('67083240086'), "3 Checking ########### format");
+			doh.assertTrue(dojox.validate.br.isValidCpf(67083240086), "3 Checking numeric ########### format");
+
+			doh.assertTrue(dojox.validate.br.isValidCpf('271.034.755-55'), "4 Checking ###.###.###-## format");
+			doh.assertTrue(dojox.validate.br.isValidCpf('271034755-55'), "4 Checking #########-## format");
+			doh.assertTrue(dojox.validate.br.isValidCpf('27103475555'), "4 Checking ########### format");
+			doh.assertTrue(dojox.validate.br.isValidCpf(27103475555), "4 Checking numeric ########### format");
+		}
+	},
+	{
+		name:"computeCpfDv",
+		runTest: function(doh) { 
+			doh.assertEqual("59", dojox.validate.br.computeCpfDv('362.866.226'), "1 Checking ###.###.### format");
+			doh.assertEqual("59", dojox.validate.br.computeCpfDv('362866226'), "1 Checking ######### format");
+			doh.assertEqual("59", dojox.validate.br.computeCpfDv(362866226), "1 Checking numeric ######### format");
+
+			doh.assertEqual("39", dojox.validate.br.computeCpfDv('781.215.062'), "2 Checking ###.###.### format");
+			doh.assertEqual("39", dojox.validate.br.computeCpfDv('781215062'), "2 Checking ######### format");
+			doh.assertEqual("39", dojox.validate.br.computeCpfDv(781215062), "2 Checking numeric ######### format");
+
+			doh.assertEqual("86", dojox.validate.br.computeCpfDv('670.832.400'), "3 Checking ###.###.### format");
+			doh.assertEqual("86", dojox.validate.br.computeCpfDv('670832400'), "3 Checking ######### format");
+			doh.assertEqual("86", dojox.validate.br.computeCpfDv(670832400), "3 Checking numeric ######### format");
+
+			doh.assertEqual("55", dojox.validate.br.computeCpfDv('271.034.755'), "4 Checking ###.###.### format");
+			doh.assertEqual("55", dojox.validate.br.computeCpfDv('271034755'), "4 Checking ######### format");
+			doh.assertEqual("55", dojox.validate.br.computeCpfDv(271034755), "4 Checking numeric ######### format");
+
+		}
+	}
+]);
diff --git a/dojox/validate/tests/creditcard.js b/dojox/validate/tests/creditcard.js
new file mode 100644
index 0000000..f6c7c42
--- /dev/null
+++ b/dojox/validate/tests/creditcard.js
@@ -0,0 +1,115 @@
+dojo.provide("dojox.validate.tests.creditcard");
+dojo.require("dojox.validate.creditCard");
+
+tests.register("dojox.validate.tests.creditcard",
+	[{
+		name:"isValidLuhn",
+		runTest: function(tests) { 
+			tests.t(dojox.validate.isValidLuhn('5105105105105100')); //test string input
+			tests.t(dojox.validate.isValidLuhn('5105-1051 0510-5100')); //test string input with dashes and spaces (commonly used when entering card #'s)
+			tests.t(dojox.validate.isValidLuhn(38520000023237)); //test numerical input as well
+			tests.f(dojox.validate.isValidLuhn(3852000002323)); //testing failures
+			tests.t(dojox.validate.isValidLuhn(18)); //length doesnt matter
+			tests.f(dojox.validate.isValidLuhn(818181)); //short length failure
+		}
+	},
+	{
+		name:"isValidCvv", 
+		runTest: function(tests) {
+			tests.t(dojox.validate.isValidCvv('123','mc')); //string is ok
+			tests.f(dojox.validate.isValidCvv('5AA','ec')); //invalid characters are not ok
+			tests.t(dojox.validate.isValidCvv(723,'mc')); //numbers are ok too
+			tests.f(dojox.validate.isValidCvv(7234,'mc')); //too long
+			tests.t(dojox.validate.isValidCvv(612,'ec'));
+			tests.t(dojox.validate.isValidCvv(421,'vi'));
+			tests.t(dojox.validate.isValidCvv(543,'di'));
+			tests.t(dojox.validate.isValidCvv('1234','ax')); 
+			tests.t(dojox.validate.isValidCvv(4321,'ax'));
+			tests.f(dojox.validate.isValidCvv(43215,'ax')); //too long
+			tests.f(dojox.validate.isValidCvv(215,'ax')); //too short
+		}
+	},
+	{
+		name:"isValidCreditCard",
+		runTest: function(tests) {
+			//misc checks
+			tests.t(dojox.validate.isValidCreditCard('5105105105105100','mc')); //test string input
+			tests.t(dojox.validate.isValidCreditCard('5105-1051 0510-5100','mc')); //test string input with dashes and spaces (commonly used when entering card #'s)
+			tests.t(dojox.validate.isValidCreditCard(5105105105105100,'mc')); //test numerical input as well
+			tests.f(dojox.validate.isValidCreditCard('5105105105105100','vi')); //fails, wrong card type
+			//Mastercard/Eurocard checks
+			tests.t(dojox.validate.isValidCreditCard('5105105105105100','mc'));
+			tests.t(dojox.validate.isValidCreditCard('5204105105105100','ec'));
+			tests.t(dojox.validate.isValidCreditCard('5303105105105100','mc'));
+			tests.t(dojox.validate.isValidCreditCard('5402105105105100','ec'));
+			tests.t(dojox.validate.isValidCreditCard('5501105105105100','mc'));
+			//Visa card checks
+			tests.t(dojox.validate.isValidCreditCard('4111111111111111','vi'));
+			tests.t(dojox.validate.isValidCreditCard('4111111111010','vi'));
+			//American Express card checks
+			tests.t(dojox.validate.isValidCreditCard('378 2822 4631 0005','ax'));
+			tests.t(dojox.validate.isValidCreditCard('341-1111-1111-1111','ax'));
+			//Diners Club/Carte Blanch card checks
+			tests.t(dojox.validate.isValidCreditCard('36400000000000','dc'));
+			tests.t(dojox.validate.isValidCreditCard('38520000023237','bl'));
+			tests.t(dojox.validate.isValidCreditCard('30009009025904','dc'));
+			tests.t(dojox.validate.isValidCreditCard('30108009025904','bl'));
+			tests.t(dojox.validate.isValidCreditCard('30207009025904','dc'));
+			tests.t(dojox.validate.isValidCreditCard('30306009025904','bl'));
+			tests.t(dojox.validate.isValidCreditCard('30405009025904','dc'));
+			tests.t(dojox.validate.isValidCreditCard('30504009025904','bl'));
+			//Discover card checks
+			tests.t(dojox.validate.isValidCreditCard('6011111111111117','di'));
+			//JCB card checks
+			tests.t(dojox.validate.isValidCreditCard('3530111333300000','jcb'));
+			tests.t(dojox.validate.isValidCreditCard('213100000000001','jcb'));
+			tests.t(dojox.validate.isValidCreditCard('180000000000002','jcb'));
+			tests.f(dojox.validate.isValidCreditCard('1800000000000002','jcb')); //should fail, good checksum, good prefix, but wrong length'
+			//Enroute card checks
+			tests.t(dojox.validate.isValidCreditCard('201400000000000','er'));
+			tests.t(dojox.validate.isValidCreditCard('214900000000000','er')); 
+		}
+	},
+	{
+		name:"isValidCreditCardNumber",
+		runTest: function(tests) {
+			//misc checks
+			tests.t(dojox.validate.isValidCreditCardNumber('5105105105105100','mc')); //test string input
+			tests.t(dojox.validate.isValidCreditCardNumber('5105-1051 0510-5100','mc')); //test string input with dashes and spaces (commonly used when entering card #'s)
+			tests.t(dojox.validate.isValidCreditCardNumber(5105105105105100,'mc')); //test numerical input as well
+			tests.f(dojox.validate.isValidCreditCardNumber('5105105105105100','vi')); //fails, wrong card type
+			//Mastercard/Eurocard checks
+			tests.is("mc|ec", dojox.validate.isValidCreditCardNumber('5100000000000000')); //should match 'mc|ec'
+			tests.is("mc|ec", dojox.validate.isValidCreditCardNumber('5200000000000000')); //should match 'mc|ec'
+			tests.is("mc|ec", dojox.validate.isValidCreditCardNumber('5300000000000000')); //should match 'mc|ec'
+			tests.is("mc|ec", dojox.validate.isValidCreditCardNumber('5400000000000000')); //should match 'mc|ec'
+			tests.is("mc|ec", dojox.validate.isValidCreditCardNumber('5500000000000000')); //should match 'mc|ec'
+			tests.f(dojox.validate.isValidCreditCardNumber('55000000000000000')); //should fail, too long
+			//Visa card checks
+			tests.is("vi", dojox.validate.isValidCreditCardNumber('4111111111111111')); //should match 'vi'
+			tests.is("vi", dojox.validate.isValidCreditCardNumber('4111111111010')); //should match 'vi'
+			//American Express card checks
+			tests.is("ax", dojox.validate.isValidCreditCardNumber('378 2822 4631 0005')); //should match 'ax'
+			tests.is("ax", dojox.validate.isValidCreditCardNumber('341-1111-1111-1111')); //should match 'ax'
+			//Diners Club/Carte Blanch card checks
+			tests.is("dc|bl", dojox.validate.isValidCreditCardNumber('36400000000000')); //should match 'dc|bl'
+			tests.is("dc|bl", dojox.validate.isValidCreditCardNumber('38520000023237')); //should match 'dc|bl'
+			tests.is("dc|bl", dojox.validate.isValidCreditCardNumber('30009009025904')); //should match 'di|bl'
+			tests.is("dc|bl", dojox.validate.isValidCreditCardNumber('30108009025904')); //should match 'di|bl'
+			tests.is("dc|bl", dojox.validate.isValidCreditCardNumber('30207009025904')); //should match 'di|bl'
+			tests.is("dc|bl", dojox.validate.isValidCreditCardNumber('30306009025904')); //should match 'di|bl'
+			tests.is("dc|bl", dojox.validate.isValidCreditCardNumber('30405009025904')); //should match 'di|bl'
+			tests.is("dc|bl", dojox.validate.isValidCreditCardNumber('30504009025904')); //should match 'di|bl'
+			//Discover card checks
+			tests.is("di", dojox.validate.isValidCreditCardNumber('6011111111111117')); //should match 'di'
+			//JCB card checks
+			tests.is("jcb", dojox.validate.isValidCreditCardNumber('3530111333300000')); //should match 'jcb'
+			tests.is("jcb", dojox.validate.isValidCreditCardNumber('213100000000001')); //should match 'jcb'
+			tests.is("jcb", dojox.validate.isValidCreditCardNumber('180000000000002')); //should match 'jcb'
+			tests.f(dojox.validate.isValidCreditCardNumber('1800000000000002')); //should fail, good checksum, good prefix, but wrong length'
+			//Enroute card checks
+			tests.is("er", dojox.validate.isValidCreditCardNumber('201400000000000')); //should match 'er'
+			tests.is("er", dojox.validate.isValidCreditCardNumber('214900000000000')); //should match 'er'
+		}
+	}
+]);
diff --git a/dojox/validate/tests/module.js b/dojox/validate/tests/module.js
new file mode 100644
index 0000000..7805e7b
--- /dev/null
+++ b/dojox/validate/tests/module.js
@@ -0,0 +1,11 @@
+dojo.provide("dojox.validate.tests.module");
+
+try{
+	dojo.require("dojox.validate.tests.creditcard");
+	dojo.require("dojox.validate.tests.validate"); 
+	dojo.require("dojox.validate.tests.br"); 
+
+}catch(e){
+	doh.debug(e);
+	console.debug(e); 
+}
diff --git a/dojox/validate/tests/runTests.html b/dojox/validate/tests/runTests.html
new file mode 100644
index 0000000..390674c
--- /dev/null
+++ b/dojox/validate/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dijit Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.validate.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/validate/tests/validate.js b/dojox/validate/tests/validate.js
new file mode 100644
index 0000000..6b95495
--- /dev/null
+++ b/dojox/validate/tests/validate.js
@@ -0,0 +1,321 @@
+dojo.provide("dojox.validate.tests.validate"); 
+
+dojo.require("dojox.validate._base");
+dojo.require("dojox.validate.check");
+dojo.require("dojox.validate.us");
+dojo.require("dojox.validate.ca"); 
+dojo.require("dojox.validate.web");
+dojo.require("dojox.validate.isbn");
+
+tests.register("dojox.validate.tests.validate",
+	[{
+		name: "isText",
+
+		setUp: function(){
+			var localeList = ["en-us"];
+			for(var i = 0 ; i < localeList.length; i ++){
+				dojo.requireLocalization("dojo.cldr", "currency", localeList[i]);
+				dojo.requireLocalization("dojo.cldr", "number", localeList[i]);
+			}
+		},
+
+		runTest: function(tests){
+			tests.t(dojox.validate.isValidIsbn('0596007590')); //test string input
+			tests.t(dojox.validate.isValidIsbn('0-596-00759-0')); //test string input with dashes
+			tests.f(dojox.validate.isValidIsbn(596007590)); //test numerical input as well
+			tests.t(dojox.validate.isValidIsbn("960-425-059-0")); 
+			tests.t(dojox.validate.isValidIsbn(9604250590)); //test numerical input as well
+			tests.t(dojox.validate.isValidIsbn('0-9752298-0-X')); // test string with X
+			tests.t(dojox.validate.isValidIsbn('0-9752298-0-x')); 
+			tests.t(dojox.validate.isValidIsbn('097522980x')); 
+			tests.t(dojox.validate.isValidIsbn('097522980X')); 
+			tests.f(dojox.validate.isValidIsbn(596007598)); //testing failures
+			tests.f(dojox.validate.isValidIsbn('059-600759-X')); //testing failures
+			tests.f(dojox.validate.isValidIsbn('059600')); // too short
+
+			tests.t(dojox.validate.isValidIsbn('9780596007591'));
+			tests.t(dojox.validate.isValidIsbn('978-0-596 00759-1'));
+			tests.t(dojox.validate.isValidIsbn(9780596007591));
+			tests.f(dojox.validate.isValidIsbn('978059600759X'));
+			tests.f(dojox.validate.isValidIsbn('978-3250-596 00759-1 '));
+			tests.f(dojox.validate.isValidIsbn('3250-596 00759 '));
+
+			tests.t(dojox.validate.isText('            x'));
+			tests.t(dojox.validate.isText('x             '));
+			tests.t(dojox.validate.isText('        x     '));
+			tests.f(dojox.validate.isText('   '));
+			tests.f(dojox.validate.isText(''));
+		
+			// test lengths
+			tests.t(dojox.validate.isText('123456', {length: 6} ));
+			tests.f(dojox.validate.isText('1234567', {length: 6} ));
+			tests.t(dojox.validate.isText('1234567', {minlength: 6} ));
+			tests.t(dojox.validate.isText('123456', {minlength: 6} ));
+			tests.f(dojox.validate.isText('12345', {minlength: 6} ));
+			tests.f(dojox.validate.isText('1234567', {maxlength: 6} ));
+			tests.t(dojox.validate.isText('123456', {maxlength: 6} ));
+		}
+	},
+	{
+		name: "isIpAddress",
+		runTest: function(tests){
+			tests.t(dojox.validate.isIpAddress('24.17.155.40'));
+			tests.f(dojox.validate.isIpAddress('024.17.155.040'));       
+			tests.t(dojox.validate.isIpAddress('255.255.255.255'));       
+			tests.f(dojox.validate.isIpAddress('256.255.255.255'));       
+			tests.f(dojox.validate.isIpAddress('255.256.255.255'));       
+			tests.f(dojox.validate.isIpAddress('255.255.256.255'));       
+			tests.f(dojox.validate.isIpAddress('255.255.255.256'));       
+
+			// test dotted hex       
+			tests.t(dojox.validate.isIpAddress('0x18.0x11.0x9b.0x28'));       
+			tests.f(dojox.validate.isIpAddress('0x18.0x11.0x9b.0x28', {allowDottedHex: false}) );       
+			tests.t(dojox.validate.isIpAddress('0x18.0x000000011.0x9b.0x28'));       
+			tests.t(dojox.validate.isIpAddress('0xff.0xff.0xff.0xff'));       
+			tests.f(dojox.validate.isIpAddress('0x100.0xff.0xff.0xff'));       
+
+			// test dotted octal       
+			tests.t(dojox.validate.isIpAddress('0030.0021.0233.0050'));       
+			tests.f(dojox.validate.isIpAddress('0030.0021.0233.0050', {allowDottedOctal: false}) );
+			tests.t(dojox.validate.isIpAddress('0030.0000021.0233.00000050'));       
+			tests.t(dojox.validate.isIpAddress('0377.0377.0377.0377'));       
+			tests.f(dojox.validate.isIpAddress('0400.0377.0377.0377'));       
+			tests.f(dojox.validate.isIpAddress('0377.0378.0377.0377'));       
+			tests.f(dojox.validate.isIpAddress('0377.0377.0380.0377'));       
+			tests.f(dojox.validate.isIpAddress('0377.0377.0377.377'));       
+		
+			// test decimal       
+			tests.t(dojox.validate.isIpAddress('3482223595'));       
+			tests.t(dojox.validate.isIpAddress('0'));       
+			tests.t(dojox.validate.isIpAddress('4294967295'));       
+			tests.f(dojox.validate.isIpAddress('4294967296'));       
+			tests.f(dojox.validate.isIpAddress('3482223595', {allowDecimal: false}));       
+		
+			// test hex       
+			tests.t(dojox.validate.isIpAddress('0xCF8E83EB'));       
+			tests.t(dojox.validate.isIpAddress('0x0'));       
+			tests.t(dojox.validate.isIpAddress('0x00ffffffff'));       
+			tests.f(dojox.validate.isIpAddress('0x100000000'));
+			tests.f(dojox.validate.isIpAddress('0xCF8E83EB', {allowHex: false}));       
+			
+			// IPv6       
+			tests.t(dojox.validate.isIpAddress('fedc:BA98:7654:3210:FEDC:BA98:7654:3210'));       
+			tests.t(dojox.validate.isIpAddress('1080:0:0:0:8:800:200C:417A'));
+			tests.f(dojox.validate.isIpAddress('1080:0:0:0:8:800:200C:417A', {allowIPv6: false}));
+		
+			// Hybrid of IPv6 and IPv4
+			tests.t(dojox.validate.isIpAddress('0:0:0:0:0:0:13.1.68.3'));
+			tests.t(dojox.validate.isIpAddress('0:0:0:0:0:FFFF:129.144.52.38'));
+			tests.f(dojox.validate.isIpAddress('0:0:0:0:0:FFFF:129.144.52.38', {allowHybrid: false}));
+			
+		}
+	},
+	{
+		name: "isUrlTest",
+		runTest: function(tests){ 
+			
+			tests.t(dojox.validate.isUrl('www.yahoo.com'));
+			tests.t(dojox.validate.isUrl('http://www.yahoo.com'));
+			tests.t(dojox.validate.isUrl('https://www.yahoo.com'));
+			tests.f(dojox.validate.isUrl('http://.yahoo.com'));
+			tests.f(dojox.validate.isUrl('http://www.-yahoo.com'));
+			tests.f(dojox.validate.isUrl('http://www.yahoo-.com'));
+			tests.t(dojox.validate.isUrl('http://y-a---h-o-o.com'));
+			tests.t(dojox.validate.isUrl('http://www.y.com'));
+			tests.t(dojox.validate.isUrl('http://www.yahoo.museum'));
+			tests.t(dojox.validate.isUrl('http://www.yahoo.co.uk'));
+			tests.f(dojox.validate.isUrl('http://www.micro$oft.com'));
+		
+			tests.t(dojox.validate.isUrl('http://www.y.museum:8080'));
+			tests.t(dojox.validate.isUrl('http://12.24.36.128:8080'));
+			tests.f(dojox.validate.isUrl('http://12.24.36.128:8080', {allowIP: false} ));
+			tests.t(dojox.validate.isUrl('www.y.museum:8080'));
+			tests.f(dojox.validate.isUrl('www.y.museum:8080', {scheme: true} ));
+			tests.t(dojox.validate.isUrl('localhost:8080', {allowLocal: true} ));
+			tests.f(dojox.validate.isUrl('localhost:8080', {} ));
+			tests.t(dojox.validate.isUrl('http://www.yahoo.com/index.html?a=12&b=hello%20world#anchor'));
+			tests.t(dojox.validate.isUrl('http://www.yahoo.xyz'));
+			tests.t(dojox.validate.isUrl('http://www.yahoo.com/index.html#anchor'));
+			tests.t(dojox.validate.isUrl('http://cocoon.apache.org/2.1/'));
+		}
+	},
+	{
+		name: "isEmailAddress",
+		runTest: function(tests) {
+			tests.t(dojox.validate.isEmailAddress('x at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x at yahoo'));
+			tests.t(dojox.validate.isEmailAddress('x.y.z.w at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x..y.z.w at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x. at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('.x at yahoo.com'));
+			tests.t(dojox.validate.isEmailAddress('azAZ09!#$%.&\'*+-/=?_`{|}y at yahoo.com'));
+			tests.t(dojox.validate.isEmailAddress('x=y at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x(y at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x)y at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x<y at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x>y at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x[y at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x]y at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x:y at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x;y at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x at y@yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x\\y at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x,y at yahoo.com'));
+			tests.f(dojox.validate.isEmailAddress('x\"y at yahoo.com'));
+			tests.t(dojox.validate.isEmailAddress('x at z.com'));
+			tests.t(dojox.validate.isEmailAddress('x at yahoo.x'));
+			tests.t(dojox.validate.isEmailAddress('x at yahoo.museum'));
+			tests.t(dojox.validate.isEmailAddress("o'mally at yahoo.com"));
+			tests.t(dojox.validate.isEmailAddress("o''mally at yahoo.com"));
+			tests.t(dojox.validate.isEmailAddress("'mally at yahoo.com"));
+			tests.t(dojox.validate.isEmailAddress("fred&barney at stonehenge.com"));
+			tests.t(dojox.validate.isEmailAddress("fred&&barney at stonehenge.com"));
+		
+			// local addresses
+			tests.t(dojox.validate.isEmailAddress("fred&barney at localhost", {allowLocal: true} ));
+			tests.f(dojox.validate.isEmailAddress("fred&barney at localhost"));
+		
+			// addresses with cruft
+			tests.t(dojox.validate.isEmailAddress("mailto:fred&barney at stonehenge.com", {allowCruft: true} ));
+			tests.t(dojox.validate.isEmailAddress("<fred&barney at stonehenge.com>", {allowCruft: true} ));
+			tests.f(dojox.validate.isEmailAddress("mailto:fred&barney at stonehenge.com"));
+			tests.f(dojox.validate.isEmailAddress("<fred&barney at stonehenge.com>"));
+	
+			// local addresses with cruft
+			tests.t(dojox.validate.isEmailAddress("<mailto:fred&barney at localhost>", {allowLocal: true, allowCruft: true} ));
+			tests.f(dojox.validate.isEmailAddress("<mailto:fred&barney at localhost>", {allowCruft: true} ));
+			tests.f(dojox.validate.isEmailAddress("<mailto:fred&barney at localhost>", {allowLocal: true} ));
+		}
+	},
+	{
+		name: "isEmailsAddressList",
+		runTest: function(tests) {
+			tests.t(dojox.validate.isEmailAddressList(
+				"x at yahoo.com \n x.y.z.w at yahoo.com ; o'mally at yahoo.com , fred&barney at stonehenge.com \n" )
+			);
+			tests.t(dojox.validate.isEmailAddressList(
+				"x at yahoo.com \n x.y.z.w at localhost \n o'mally at yahoo.com \n fred&barney at localhost", 
+				{allowLocal: true} )
+			);
+			tests.f(dojox.validate.isEmailAddressList(
+				"x at yahoo.com; x.y.z.w at localhost; o'mally at yahoo.com; fred&barney at localhost", {listSeparator: ";"} )
+			);
+			tests.t(dojox.validate.isEmailAddressList(
+					"mailto:x at yahoo.com; <x.y.z.w at yahoo.com>; <mailto:o'mally at yahoo.com>; fred&barney at stonehenge.com", 
+					{allowCruft: true, listSeparator: ";"} )
+			);
+			tests.f(dojox.validate.isEmailAddressList(
+					"mailto:x at yahoo.com; <x.y.z.w at yahoo.com>; <mailto:o'mally at yahoo.com>; fred&barney at stonehenge.com", 
+					{listSeparator: ";"} )
+			);
+			tests.t(dojox.validate.isEmailAddressList(
+					"mailto:x at yahoo.com; <x.y.z.w at localhost>; <mailto:o'mally at localhost>; fred&barney at localhost", 
+					{allowLocal: true, allowCruft: true, listSeparator: ";"} )
+			);
+		}
+	},
+	{
+		name: "getEmailAddressList",
+		runTest: function(tests) {
+			var list = "x at yahoo.com \n x.y.z.w at yahoo.com ; o'mally at yahoo.com , fred&barney at stonehenge.com";
+			tests.is(4, dojox.validate.getEmailAddressList(list).length);
+
+			var localhostList = "x at yahoo.com; x.y.z.w at localhost; o'mally at yahoo.com; fred&barney at localhost";
+			tests.is(0, dojox.validate.getEmailAddressList(localhostList).length);
+			tests.is(4, dojox.validate.getEmailAddressList(localhostList, {allowLocal: true} ).length);
+		}
+	},
+	{
+		name: "isInRangeInt",
+		runTest: function(tests) {
+			// test integers
+			tests.f(dojox.validate.isInRange( '0', {min: 1, max: 100} ));
+			tests.t(dojox.validate.isInRange( '1', {min: 1, max: 100} ));
+			tests.f(dojox.validate.isInRange( '-50', {min: 1, max: 100} ));
+//			tests.t(dojox.validate.isInRange( '+50', {min: 1, max: 100} )); //TODO: dojo.number.parse does not support plus sign
+			tests.t(dojox.validate.isInRange( '100', {min: 1, max: 100} ));
+			tests.f(dojox.validate.isInRange( '101', {min: 1, max: 100} ));
+		}
+	},
+	{
+		name:"isInRangeReal",
+		runTest: function(tests){
+	
+			tests.f(dojox.validate.isInRange( '0.9', {min: 1.0, max: 10.0, locale: 'en-us'} ));
+			tests.t(dojox.validate.isInRange( '1.0', {min: 1.0, max: 10.0, locale: 'en-us'} ));
+			tests.f(dojox.validate.isInRange( '-5.0', {min: 1.0, max: 10.0, locale: 'en-us'} ));
+//			tests.t(dojox.validate.isInRange( '+5.50', {min: 1.0, max: 10.0, locale: 'en-us'} )); //TODO: dojo.number.parse does not support plus sign
+			tests.t(dojox.validate.isInRange( '10.0', {min: 1.0, max: 10.0, locale: 'en-us'} ));
+			tests.f(dojox.validate.isInRange( '10.1', {min: 1.0, max: 10.0, locale: 'en-us'} ));
+// TODO: dojo.number.parse does not support scientific notation at this time
+//			tests.f(dojox.validate.isInRange( '5.566e28', {min: 5.567e28, max: 6.000e28, locale: 'en-us'} ));
+//			tests.t(dojox.validate.isInRange( '5.7e28', {min: 5.567e28, max: 6.000e28, locale: 'en-us'} ));
+//			tests.f(dojox.validate.isInRange( '6.00000001e28', {min: 5.567e28, max: 6.000e28, locale: 'en-us'} ));
+//			tests.f(dojox.validate.isInRange( '10.000.000,12345e-5', {decimal: ",", max: 10000000.1e-5, locale: 'de-de'} ));
+//			tests.f(dojox.validate.isInRange( '10.000.000,12345e-5', {decimal: ",", min: 10000000.2e-5, locale: 'de-de'} ));
+			tests.t(dojox.validate.isInRange('1,500,000', { min: 0, locale: 'en-us'}));
+			tests.f(dojox.validate.isInRange('1,500,000', { min: 1000, max: 20000, locale: 'en-us'}));
+		}
+	},
+	{	
+		name: "isUsPhoneNumber",
+		runTest: function(tests) {
+			tests.t(dojox.validate.us.isPhoneNumber('(111) 111-1111'));
+			tests.t(dojox.validate.us.isPhoneNumber('(111) 111 1111'));
+			tests.t(dojox.validate.us.isPhoneNumber('111 111 1111'));
+			tests.t(dojox.validate.us.isPhoneNumber('111.111.1111'));
+			tests.t(dojox.validate.us.isPhoneNumber('111-111-1111'));
+			tests.t(dojox.validate.us.isPhoneNumber('111/111-1111'));
+			tests.f(dojox.validate.us.isPhoneNumber('111 111-1111'));
+			tests.f(dojox.validate.us.isPhoneNumber('111-1111'));
+			tests.f(dojox.validate.us.isPhoneNumber('(111)-111-1111'));
+		
+			// test extensions
+			tests.t(dojox.validate.us.isPhoneNumber('111-111-1111 x1'));
+			tests.t(dojox.validate.us.isPhoneNumber('111-111-1111 x12'));
+			tests.t(dojox.validate.us.isPhoneNumber('111-111-1111 x1234'));
+		}
+	},
+	{
+		name: "isUsSocialSecurityNumber",
+		runTest: function(tests) {
+			tests.t(dojox.validate.us.isSocialSecurityNumber('123-45-6789'));
+			tests.t(dojox.validate.us.isSocialSecurityNumber('123 45 6789'));
+			tests.t(dojox.validate.us.isSocialSecurityNumber('123456789'));
+			tests.f(dojox.validate.us.isSocialSecurityNumber('123-45 6789'));
+			tests.f(dojox.validate.us.isSocialSecurityNumber('12345 6789'));
+			tests.f(dojox.validate.us.isSocialSecurityNumber('123-456789'));
+		}
+	},
+	{
+		name:"isUsZipCode",
+		runTest: function(tests) {
+			tests.t(dojox.validate.us.isZipCode('12345-6789'));
+			tests.t(dojox.validate.us.isZipCode('12345 6789'));
+			tests.t(dojox.validate.us.isZipCode('123456789'));
+			tests.t(dojox.validate.us.isZipCode('12345'));
+		}
+	},
+	{
+		name:"isCaZipCode",
+		runTest: function(tests) {
+			tests.t(dojox.validate.ca.isPostalCode('A1Z 3F3'));
+			tests.f(dojox.validate.ca.isPostalCode('1AZ 3F3'));
+			tests.t(dojox.validate.ca.isPostalCode('a1z 3f3'));
+			tests.f(dojox.validate.ca.isPostalCode('xxxxxx'));
+			tests.f(dojox.validate.ca.isPostalCode('A1Z3F3')); 
+			
+		}
+	},
+	{
+		name:"isUsState",
+		runTest: function(tests) {
+			tests.t(dojox.validate.us.isState('CA'));
+			tests.t(dojox.validate.us.isState('ne'));
+			tests.t(dojox.validate.us.isState('PR'));
+			tests.f(dojox.validate.us.isState('PR', {allowTerritories: false} ));
+			tests.t(dojox.validate.us.isState('AA'));
+			tests.f(dojox.validate.us.isState('AA', {allowMilitary: false} ));
+		}
+	}
+]);
diff --git a/dojox/validate/us.js b/dojox/validate/us.js
index 51bfaeb..07166ee 100644
--- a/dojox/validate/us.js
+++ b/dojox/validate/us.js
@@ -1,28 +1,64 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.validate.us"]){
-dojo._hasResource["dojox.validate.us"]=true;
 dojo.provide("dojox.validate.us");
 dojo.require("dojox.validate._base");
-dojox.validate.us.isState=function(_1,_2){
-var re=new RegExp("^"+dojox.validate.regexp.us.state(_2)+"$","i");
-return re.test(_1);
-};
-dojox.validate.us.isPhoneNumber=function(_3){
-var _4={format:["###-###-####","(###) ###-####","(###) ### ####","###.###.####","###/###-####","### ### ####","###-###-#### x#???","(###) ###-#### x#???","(###) ### #### x#???","###.###.#### x#???","###/###-#### x#???","### ### #### x#???","##########"]};
-return dojox.validate.isNumberFormat(_3,_4);
-};
-dojox.validate.us.isSocialSecurityNumber=function(_5){
-var _6={format:["###-##-####","### ## ####","#########"]};
-return dojox.validate.isNumberFormat(_5,_6);
-};
-dojox.validate.us.isZipCode=function(_7){
-var _8={format:["#####-####","##### ####","#########","#####"]};
-return dojox.validate.isNumberFormat(_7,_8);
-};
+
+
+dojox.validate.us.isState = function(/*String*/value, /*Object?*/flags){
+	// summary: Validates US state and territory abbreviations.
+	//
+	// value: A two character string
+	// flags: An object
+	//    flags.allowTerritories  Allow Guam, Puerto Rico, etc.  Default is true.
+	//    flags.allowMilitary  Allow military 'states', e.g. Armed Forces Europe (AE).  Default is true.
+
+	var re = new RegExp("^" + dojox.validate.regexp.us.state(flags) + "$", "i");
+	return re.test(value); // Boolean
+}
+
+dojox.validate.us.isPhoneNumber = function(/*String*/value){
+	// summary: Validates 10 US digit phone number for several common formats
+	// value: The telephone number string
+
+	var flags = {
+		format: [
+			"###-###-####",
+			"(###) ###-####",
+			"(###) ### ####",
+			"###.###.####",
+			"###/###-####",
+			"### ### ####",
+			"###-###-#### x#???",
+			"(###) ###-#### x#???",
+			"(###) ### #### x#???",
+			"###.###.#### x#???",
+			"###/###-#### x#???",
+			"### ### #### x#???",
+			"##########"
+		]
+	};
+	return dojox.validate.isNumberFormat(value, flags); // Boolean
+}
+
+dojox.validate.us.isSocialSecurityNumber = function(/*String*/value){
+	// summary: Validates social security number
+	var flags = {
+		format: [
+			"###-##-####",
+			"### ## ####",
+			"#########"
+		]
+	};
+	return dojox.validate.isNumberFormat(value, flags); // Boolean
+}
+
+dojox.validate.us.isZipCode = function(/*String*/value){
+	// summary: Validates U.S. zip-code
+	var flags = {
+		format: [
+			"#####-####",
+			"##### ####",
+			"#########",
+			"#####"
+		]
+	};
+	return dojox.validate.isNumberFormat(value, flags); // Boolean
 }
diff --git a/dojox/validate/web.js b/dojox/validate/web.js
index 930f92c..75dc275 100644
--- a/dojox/validate/web.js
+++ b/dojox/validate/web.js
@@ -1,40 +1,85 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.validate.web"]){
-dojo._hasResource["dojox.validate.web"]=true;
 dojo.provide("dojox.validate.web");
 dojo.require("dojox.validate._base");
-dojox.validate.isIpAddress=function(_1,_2){
-var re=new RegExp("^"+dojox.validate.regexp.ipAddress(_2)+"$","i");
-return re.test(_1);
-};
-dojox.validate.isUrl=function(_3,_4){
-var re=new RegExp("^"+dojox.validate.regexp.url(_4)+"$","i");
-return re.test(_3);
-};
-dojox.validate.isEmailAddress=function(_5,_6){
-var re=new RegExp("^"+dojox.validate.regexp.emailAddress(_6)+"$","i");
-return re.test(_5);
-};
-dojox.validate.isEmailAddressList=function(_7,_8){
-var re=new RegExp("^"+dojox.validate.regexp.emailAddressList(_8)+"$","i");
-return re.test(_7);
-};
-dojox.validate.getEmailAddressList=function(_9,_a){
-if(!_a){
-_a={};
+
+dojox.validate.isIpAddress = function(/*String*/value, /*Object?*/flags) {
+	// summary: Validates an IP address
+	//
+	// description:
+	//  Supports 5 formats for IPv4: dotted decimal, dotted hex, dotted octal, decimal and hexadecimal.
+	//  Supports 2 formats for Ipv6.
+	//
+	// value  A string.
+	// flags  An object.  All flags are boolean with default = true.
+	//    flags.allowDottedDecimal  Example, 207.142.131.235.  No zero padding.
+	//    flags.allowDottedHex  Example, 0x18.0x11.0x9b.0x28.  Case insensitive.  Zero padding allowed.
+	//    flags.allowDottedOctal  Example, 0030.0021.0233.0050.  Zero padding allowed.
+	//    flags.allowDecimal  Example, 3482223595.  A decimal number between 0-4294967295.
+	//    flags.allowHex  Example, 0xCF8E83EB.  Hexadecimal number between 0x0-0xFFFFFFFF.
+	//      Case insensitive.  Zero padding allowed.
+	//    flags.allowIPv6   IPv6 address written as eight groups of four hexadecimal digits.
+	//    flags.allowHybrid   IPv6 address written as six groups of four hexadecimal digits
+	//      followed by the usual 4 dotted decimal digit notation of IPv4. x:x:x:x:x:x:d.d.d.d
+
+	var re = new RegExp("^" + dojox.validate.regexp.ipAddress(flags) + "$", "i");
+	return re.test(value); // Boolean
 }
-if(!_a.listSeparator){
-_a.listSeparator="\\s;,";
+
+
+dojox.validate.isUrl = function(/*String*/value, /*Object?*/flags) {
+	// summary: Checks if a string could be a valid URL
+	// value: A string
+	// flags: An object
+	//    flags.scheme  Can be true, false, or [true, false]. 
+	//      This means: required, not allowed, or either.
+	//    flags in regexp.host can be applied.
+	//    flags in regexp.ipAddress can be applied.
+	//    flags in regexp.tld can be applied.
+
+	var re = new RegExp("^" + dojox.validate.regexp.url(flags) + "$", "i");
+	return re.test(value); // Boolean
 }
-if(dojox.validate.isEmailAddressList(_9,_a)){
-return _9.split(new RegExp("\\s*["+_a.listSeparator+"]\\s*"));
+
+dojox.validate.isEmailAddress = function(/*String*/value, /*Object?*/flags) {
+	// summary: Checks if a string could be a valid email address
+	//
+	// value: A string
+	// flags: An object
+	//    flags.allowCruft  Allow address like <mailto:foo at yahoo.com>.  Default is false.
+	//    flags in regexp.host can be applied.
+	//    flags in regexp.ipAddress can be applied.
+	//    flags in regexp.tld can be applied.
+
+	var re = new RegExp("^" + dojox.validate.regexp.emailAddress(flags) + "$", "i");
+	return re.test(value); // Boolean
+}
+
+dojox.validate.isEmailAddressList = function(/*String*/value, /*Object?*/flags) {
+	// summary: Checks if a string could be a valid email address list.
+	//
+	// value  A string.
+	// flags  An object.
+	//    flags.listSeparator  The character used to separate email addresses.  Default is ";", ",", "\n" or " ".
+	//    flags in regexp.emailAddress can be applied.
+	//    flags in regexp.host can be applied.
+	//    flags in regexp.ipAddress can be applied.
+	//    flags in regexp.tld can be applied.
+
+	var re = new RegExp("^" + dojox.validate.regexp.emailAddressList(flags) + "$", "i");
+	return re.test(value); // Boolean
 }
-return [];
-};
+
+dojox.validate.getEmailAddressList = function(/*String*/value, /*Object?*/flags) {
+	// summary: Check if value is an email address list. If an empty list
+	//  is returned, the value didn't pass the test or it was empty.
+	//
+	// value: A string
+	// flags: An object (same as dojo.validate.isEmailAddressList)
+
+	if(!flags) { flags = {}; }
+	if(!flags.listSeparator) { flags.listSeparator = "\\s;,"; }
+
+	if ( dojox.validate.isEmailAddressList(value, flags) ) {
+		return value.split(new RegExp("\\s*[" + flags.listSeparator + "]\\s*")); // Array
+	}
+	return []; // Array
 }
diff --git a/dojox/widget/AnalogGauge.js b/dojox/widget/AnalogGauge.js
index 2d4eed6..015ec2b 100644
--- a/dojox/widget/AnalogGauge.js
+++ b/dojox/widget/AnalogGauge.js
@@ -1,246 +1,358 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.AnalogGauge"]){
-dojo._hasResource["dojox.widget.AnalogGauge"]=true;
 dojo.provide("dojox.widget.AnalogGauge");
+
 dojo.require("dojox.gfx");
 dojo.require("dojox.widget.gauge._Gauge");
+
 dojo.experimental("dojox.widget.AnalogGauge");
-dojo.declare("dojox.widget.gauge.AnalogLineIndicator",[dojox.widget.gauge._Indicator],{_getShapes:function(){
-var _1=[];
-_1[0]=this._gauge.surface.createLine({x1:0,y1:-this.offset,x2:0,y2:-this.length-this.offset}).setStroke({color:this.color,width:this.width});
-return _1;
-},draw:function(_2){
-if(this.shapes){
-this._move(_2);
-}else{
-if(this.text){
-this._gauge.surface.rawNode.removeChild(this.text);
-this.text=null;
-}
-var v=this.value;
-if(v<this._gauge.min){
-v=this._gauge.min;
-}
-if(v>this._gauge.max){
-v=this._gauge.max;
-}
-var a=this._gauge._getAngle(v);
-this.color=this.color||"#000000";
-this.length=this.length||this._gauge.radius;
-this.width=this.width||1;
-this.offset=this.offset||0;
-this.highlight=this.highlight||"#D0D0D0";
-this.shapes=this._getShapes(this._gauge,this);
-if(this.shapes){
-for(var s=0;s<this.shapes.length;s++){
-this.shapes[s].setTransform([{dx:this._gauge.cx,dy:this._gauge.cy},dojox.gfx.matrix.rotateg(a)]);
-if(this.hover){
-this.shapes[s].getEventSource().setAttribute("hover",this.hover);
-}
-if(this.onDragMove&&!this.noChange){
-this._gauge.connect(this.shapes[s].getEventSource(),"onmousedown",this._gauge.handleMouseDown);
-this.shapes[s].getEventSource().style.cursor="pointer";
-}
-}
-}
-if(this.label){
-var _3=this.length+this.offset;
-var x=this._gauge.cx+(_3+5)*Math.sin(this._gauge._getRadians(a));
-var y=this._gauge.cy-(_3+5)*Math.cos(this._gauge._getRadians(a));
-var _4="start";
-if(a<=-10){
-_4="end";
-}
-if(a>-10&&a<10){
-_4="middle";
-}
-var _5="bottom";
-if((a<-90)||(a>90)){
-_5="top";
-}
-this.text=this._gauge.drawText(""+this.label,x,y,_4,_5,this.color,this.font);
-}
-this.currentValue=this.value;
-}
-},_move:function(_6){
-var v=this.value;
-if(v<this._gauge.min){
-v=this._gauge.min;
-}
-if(v>this._gauge.max){
-v=this._gauge.max;
-}
-var c=this.currentValue;
-if(_6){
-var _7=this._gauge._getAngle(v);
-for(var i in this.shapes){
-this.shapes[i].setTransform([{dx:this._gauge.cx,dy:this._gauge.cy},dojox.gfx.matrix.rotateg(_7)]);
-if(this.hover){
-this.shapes[i].getEventSource().setAttribute("hover",this.hover);
-}
-}
-}else{
-if(c!=v){
-var _8=new dojo.Animation({curve:[c,v],duration:this.duration,easing:this.easing});
-dojo.connect(_8,"onAnimate",dojo.hitch(this,function(_9){
-for(var i in this.shapes){
-this.shapes[i].setTransform([{dx:this._gauge.cx,dy:this._gauge.cy},dojox.gfx.matrix.rotateg(this._gauge._getAngle(_9))]);
-if(this.hover){
-this.shapes[i].getEventSource().setAttribute("hover",this.hover);
-}
-}
-this.currentValue=_9;
-}));
-_8.play();
-}
-}
-}});
-dojo.declare("dojox.widget.AnalogGauge",dojox.widget.gauge._Gauge,{startAngle:-90,endAngle:90,cx:0,cy:0,radius:0,_defaultIndicator:dojox.widget.gauge.AnalogLineIndicator,startup:function(){
-if(this.getChildren){
-dojo.forEach(this.getChildren(),function(_a){
-_a.startup();
+
+dojo.declare("dojox.widget.gauge.AnalogLineIndicator",[dojox.widget.gauge._Indicator],{
+	_getShapes: function(){
+		// summary:
+		//		Private function for generating the shapes for this indicator. An indicator that behaves the 
+		//		same might override this one and simply replace the shapes (such as ArrowIndicator).
+		var shapes = [];
+		shapes[0] = this._gauge.surface.createLine({x1: 0, y1: -this.offset, 
+													x2: 0, y2: -this.length-this.offset})
+					.setStroke({color: this.color, width: this.width});
+		return shapes;
+	},
+	draw: function(/*Boolean?*/ dontAnimate){
+		// summary: 
+		//		Override of dojox.widget.gauge._Indicator.draw
+		// dontAnimate: Boolean
+		//		Indicates if the drawing should not be animated (vs. the default of doing an animation)
+		if(this.shapes){
+			this._move(dontAnimate);
+		}else{
+			if(this.text){
+				this._gauge.surface.rawNode.removeChild(this.text);
+				this.text = null;
+			}
+
+			var v = this.value;
+			if(v < this._gauge.min){v = this._gauge.min;}
+			if(v > this._gauge.max){v = this._gauge.max;}
+			var a = this._gauge._getAngle(v);
+
+			this.color = this.color || '#000000';
+			this.length = this.length || this._gauge.radius;
+			this.width = this.width || 1;
+			this.offset = this.offset || 0;
+			this.highlight = this.highlight || '#D0D0D0';
+
+			this.shapes = this._getShapes(this._gauge, this);
+
+			if(this.shapes){
+				for(var s = 0; s < this.shapes.length; s++){
+					this.shapes[s].setTransform([{dx:this._gauge.cx,dy:this._gauge.cy}, dojox.gfx.matrix.rotateg(a)]);
+					if(this.hover){
+						this.shapes[s].getEventSource().setAttribute('hover',this.hover);
+					}
+					if(this.onDragMove && !this.noChange){
+						//TODO
+						this._gauge.connect(this.shapes[s].getEventSource(), 'onmousedown', this._gauge.handleMouseDown);
+						this.shapes[s].getEventSource().style.cursor = 'pointer';
+					}
+				}
+			}
+	
+			if(this.label){
+				var len=this.length+this.offset;
+				var x=this._gauge.cx+(len+5)*Math.sin(this._gauge._getRadians(a));
+				var y=this._gauge.cy-(len+5)*Math.cos(this._gauge._getRadians(a));
+				var align = 'start';
+				if(a <= -10){align = 'end';}
+				if(a > -10 && a < 10){align='middle';}
+				var vAlign = 'bottom';
+				if((a < -90) || (a > 90)){vAlign = 'top';}
+				this.text = this._gauge.drawText(''+this.label, x, y, align, vAlign, this.color, this.font);
+			}
+			this.currentValue = this.value;
+		}
+	},
+	_move: function(/*Boolean?*/ dontAnimate){
+		// summary: 
+		//		Moves this indicator (since it's already been drawn once)
+		// dontAnimate: Boolean
+		//		Indicates if the drawing should not be animated (vs. the default of doing an animation)
+		var v = this.value;
+		if(v < this._gauge.min){v = this._gauge.min;}
+		if(v > this._gauge.max){v = this._gauge.max;}
+		var c = this.currentValue;
+		if(dontAnimate){
+			var angle = this._gauge._getAngle(v);
+			for(var i in this.shapes){
+				this.shapes[i].setTransform([{dx:this._gauge.cx,dy:this._gauge.cy}, dojox.gfx.matrix.rotateg(angle)]);
+				if(this.hover){
+					this.shapes[i].getEventSource().setAttribute('hover',this.hover);
+				}
+			}
+		}else{
+			if(c!=v){
+				var anim = new dojo.Animation({curve: [c, v], duration: this.duration, easing: this.easing});
+				dojo.connect(anim, "onAnimate", dojo.hitch(this, function(step){
+					for(var i in this.shapes){
+						this.shapes[i].setTransform([{dx:this._gauge.cx,dy:this._gauge.cy}, dojox.gfx.matrix.rotateg(this._gauge._getAngle(step))]);
+						if(this.hover){
+							this.shapes[i].getEventSource().setAttribute('hover',this.hover);
+						}
+					}
+					this.currentValue = step;
+				}));
+				anim.play();
+			}
+		}
+	}
+});
+dojo.declare("dojox.widget.AnalogGauge",dojox.widget.gauge._Gauge,{
+	// summary:
+	//		a gauge built using the dojox.gfx package.
+	//
+	// description:
+	//		using dojo.gfx (and thus either SVG or VML based on what is supported), this widget
+	//		builds a gauge component, used to display numerical data in a familiar format 
+	//
+	// usage:
+	//		<script type="text/javascript">
+	//			dojo.require("dojox.widget.AnalogGauge");
+	//			dojo.require("dijit.util.parser");
+	//		</script>
+	//		...
+	//		<div	dojoType="dojox.widget.AnalogGauge"
+	//				id="testGauge"
+	//				width="300"
+	//				height="200"
+	//				cx=150
+	//				cy=175
+	//				radius=125
+	//				image="gaugeOverlay.png"
+	//				imageOverlay="false"
+	//				imageWidth="280"
+	//				imageHeight="155"
+	//				imageX="12"
+	//				imageY="38">
+	//		</div>
+
+	// startAngle: Number
+	// angle (in degrees) for start of gauge (default is -90)
+	startAngle: -90,
+
+	// endAngle: Number
+	// angle (in degrees) for end of gauge (default is 90)
+	endAngle: 90,
+
+	// cx: Number
+	// center of gauge x coordinate (default is gauge width / 2)
+	cx: 0,
+
+	// cy: Number
+	// center of gauge x coordinate (default is gauge height / 2)
+	cy: 0,
+
+	// radius: Number
+	// radius of gauge (default is smaller of cx-25 or cy-25)
+	radius: 0,
+
+	// _defaultIndicator: override of dojox.widget._Gauge._defaultIndicator
+	_defaultIndicator: dojox.widget.gauge.AnalogLineIndicator,
+
+	startup: function(){
+		// handle settings from HTML by making sure all the options are
+		// converted correctly to numbers and that we calculate defaults
+		// for cx, cy and radius
+		// also connects mouse handling events
+
+		if(this.getChildren){
+			dojo.forEach(this.getChildren(), function(child){ child.startup(); });
+		}
+
+		this.startAngle = Number(this.startAngle);
+		this.endAngle = Number(this.endAngle);
+
+		this.cx = Number(this.cx);
+		if(!this.cx){this.cx = this.width/2;}
+		this.cy = Number(this.cy);
+		if(!this.cy){this.cy = this.height/2;}
+		this.radius = Number(this.radius);
+		if(!this.radius){this.radius = Math.min(this.cx,this.cy) - 25;}
+		this._oppositeMiddle = (this.startAngle+this.endAngle)/2+180;
+
+		this.inherited(arguments);
+	},
+
+	_getAngle: function(/*Number*/value){
+		// summary:
+		//		This is a helper function used to determine the angle that represents
+		//		a given value on the gauge
+		// value:	Number
+		//			A value to be converted to an angle for this gauage.
+		return (value - this.min)/(this.max - this.min)*(this.endAngle - this.startAngle) + this.startAngle;
+	},
+
+	_getValueForAngle: function(/*Number*/angle){
+		// summary:
+		//		This is a helper function used to determie the value represented by a
+		//		given angle on the gauge
+		// angle:	Number
+		//			A angle to be converted to a value for this gauge.
+		if(angle > this._oppositeMiddle){ angle -= 360; }
+		return (angle - this.startAngle)*(this.max - this.min)/(this.endAngle - this.startAngle) + this.min;
+	},
+
+	_getRadians: function(/*Number*/angle){
+		// summary:
+		//		This is a helper function than converts degrees to radians
+		// angle:	Number
+		//			An angle, in degrees, to be converted to radians.
+		return angle*Math.PI/180;
+	},
+
+	_getDegrees: function(/*Number*/radians){
+		// summary:
+		//		This is a helper function that converts radians to degrees
+		// radians:	Number
+		//			An angle, in radians, to be converted to degrees.
+		return radians*180/Math.PI;
+	},
+
+	draw: function(){
+		// summary:
+		//		This function is used to draw (or redraw) the gauge.
+		// description:
+		//		Draws the gauge by drawing the surface, the ranges, and the indicators.
+		var i;
+		if(this._rangeData){
+			for(i=0; i<this._rangeData.length; i++){
+				this.drawRange(this._rangeData[i]);
+			}
+			if(this._img && this.image.overlay){
+				this._img.moveToFront();
+			}
+		}
+		if(this._indicatorData){
+			for(i=0; i<this._indicatorData.length; i++){
+				this._indicatorData[i].draw();
+			}
+		}
+	},
+
+	drawRange: function(/*Object*/range){
+		// summary:
+		//		This function is used to draw (or redraw) a range
+		// description:
+		//		Draws a range (colored area on the background of the gauge) 
+		//		based on the given arguments.
+		// range:
+		//		A range is a dojox.widget.gauge.Range or an object
+		//		with similar parameters (low, high, hover, etc.).
+		var path;
+		if(range.shape){
+			this.surface.remove(range.shape);
+			range.shape = null;
+		}
+		var a1;
+		var a2;
+		if((range.low == this.min) && (range.high == this.max) && ((this.endAngle - this.startAngle) == 360)){
+			path = this.surface.createCircle({cx: this.cx, cy: this.cy, r: this.radius});
+		}else{
+			a1 = this._getRadians(this._getAngle(range.low));
+			a2 = this._getRadians(this._getAngle(range.high));
+			var x1=this.cx+this.radius*Math.sin(a1);
+			var y1=this.cy-this.radius*Math.cos(a1);
+			var x2=this.cx+this.radius*Math.sin(a2);
+			var y2=this.cy-this.radius*Math.cos(a2);
+			var big=0;
+			if((a2-a1)>Math.PI){big=1;}
+
+			path = this.surface.createPath();
+			if(range.size){
+				path.moveTo(this.cx+(this.radius-range.size)*Math.sin(a1),
+							this.cy-(this.radius-range.size)*Math.cos(a1));
+			}else{
+				path.moveTo(this.cx,this.cy);
+			}
+			path.lineTo(x1,y1);
+			path.arcTo(this.radius,this.radius,0,big,1,x2,y2);
+			if(range.size){
+				path.lineTo(this.cx+(this.radius-range.size)*Math.sin(a2),
+							this.cy-(this.radius-range.size)*Math.cos(a2));
+				path.arcTo((this.radius-range.size),(this.radius-range.size),0,big,0,
+							this.cx+(this.radius-range.size)*Math.sin(a1),
+							this.cy-(this.radius-range.size)*Math.cos(a1));
+			}
+			path.closePath();
+		}
+
+		if(dojo.isArray(range.color) || dojo.isString(range.color)){
+			path.setStroke({color: range.color});
+			path.setFill(range.color);
+		}else if(range.color.type){
+			// Color is a gradient
+			a1 = this._getRadians(this._getAngle(range.low));
+			a2 = this._getRadians(this._getAngle(range.high));
+			range.color.x1 = this.cx+(this.radius*Math.sin(a1))/2;
+			range.color.x2 = this.cx+(this.radius*Math.sin(a2))/2;
+			range.color.y1 = this.cy-(this.radius*Math.cos(a1))/2;
+			range.color.y2 = this.cy-(this.radius*Math.cos(a2))/2;
+			path.setFill(range.color);
+			path.setStroke({color: range.color.colors[0].color});
+		}else{
+			// We've defined a style rather than an explicit color
+			path.setStroke({color: "green"});	// Arbitrary color, just have to indicate
+			path.setFill("green");				// that we want it filled
+			path.getEventSource().setAttribute("class", range.color.style);
+		}
+		if(range.hover){
+			path.getEventSource().setAttribute('hover',range.hover);
+		}
+		range.shape = path;
+	},
+
+	getRangeUnderMouse: function(/*Object*/event){
+		// summary:
+		//		Determines which range the mouse is currently over
+		// event:	Object
+		//			The event object as received by the mouse handling functions below.
+		var range = null;
+		var pos = dojo.coords(this.gaugeContent);
+		var x = event.clientX - pos.x;
+		var y = event.clientY - pos.y;
+		var r = Math.sqrt((y - this.cy)*(y - this.cy) + (x - this.cx)*(x - this.cx));
+		if(r < this.radius){
+			var angle = this._getDegrees(Math.atan2(y - this.cy, x - this.cx) + Math.PI/2);
+			//if(angle > this.endAngle){angle = angle - 360;}
+			var value = this._getValueForAngle(angle);
+			if(this._rangeData){
+				for(var i=0; (i<this._rangeData.length) && !range; i++){
+					if((Number(this._rangeData[i].low) <= value) && (Number(this._rangeData[i].high) >= value)){
+						range = this._rangeData[i];
+					}
+				}
+			}
+		}
+		return range;
+	},
+
+	_dragIndicator: function(/*Object*/ widget, /*Object*/ event){
+		// summary:
+		//		Handles the dragging of an indicator, including moving/re-drawing
+		// get angle for mouse position
+		var pos = dojo.coords(widget.gaugeContent);
+		var x = event.clientX - pos.x;
+		var y = event.clientY - pos.y;
+		var angle = widget._getDegrees(Math.atan2(y - widget.cy, x - widget.cx) + Math.PI/2);
+		//if(angle > widget.endAngle){angle = angle - 360;}
+		// get value and restrict to our min/max
+		var value = widget._getValueForAngle(angle);
+		if(value < widget.min){value = widget.min;}
+		if(value > widget.max){value = widget.max;}
+		// update the indicator
+		widget._drag.value = value;
+		widget._drag.currentValue = value;
+		// callback
+		widget._drag.onDragMove(widget._drag);
+		// rotate indicator
+		widget._drag.draw(true);
+		dojo.stopEvent(event);
+	}
 });
-}
-this.startAngle=Number(this.startAngle);
-this.endAngle=Number(this.endAngle);
-this.cx=Number(this.cx);
-if(!this.cx){
-this.cx=this.width/2;
-}
-this.cy=Number(this.cy);
-if(!this.cy){
-this.cy=this.height/2;
-}
-this.radius=Number(this.radius);
-if(!this.radius){
-this.radius=Math.min(this.cx,this.cy)-25;
-}
-this._oppositeMiddle=(this.startAngle+this.endAngle)/2+180;
-this.inherited(arguments);
-},_getAngle:function(_b){
-return (_b-this.min)/(this.max-this.min)*(this.endAngle-this.startAngle)+this.startAngle;
-},_getValueForAngle:function(_c){
-if(_c>this._oppositeMiddle){
-_c-=360;
-}
-return (_c-this.startAngle)*(this.max-this.min)/(this.endAngle-this.startAngle)+this.min;
-},_getRadians:function(_d){
-return _d*Math.PI/180;
-},_getDegrees:function(_e){
-return _e*180/Math.PI;
-},draw:function(){
-var i;
-if(this._rangeData){
-for(i=0;i<this._rangeData.length;i++){
-this.drawRange(this._rangeData[i]);
-}
-if(this._img&&this.image.overlay){
-this._img.moveToFront();
-}
-}
-if(this._indicatorData){
-for(i=0;i<this._indicatorData.length;i++){
-this._indicatorData[i].draw();
-}
-}
-},drawRange:function(_f){
-var _10;
-if(_f.shape){
-this.surface.remove(_f.shape);
-_f.shape=null;
-}
-var a1;
-var a2;
-if((_f.low==this.min)&&(_f.high==this.max)&&((this.endAngle-this.startAngle)==360)){
-_10=this.surface.createCircle({cx:this.cx,cy:this.cy,r:this.radius});
-}else{
-a1=this._getRadians(this._getAngle(_f.low));
-a2=this._getRadians(this._getAngle(_f.high));
-var x1=this.cx+this.radius*Math.sin(a1);
-var y1=this.cy-this.radius*Math.cos(a1);
-var x2=this.cx+this.radius*Math.sin(a2);
-var y2=this.cy-this.radius*Math.cos(a2);
-var big=0;
-if((a2-a1)>Math.PI){
-big=1;
-}
-_10=this.surface.createPath();
-if(_f.size){
-_10.moveTo(this.cx+(this.radius-_f.size)*Math.sin(a1),this.cy-(this.radius-_f.size)*Math.cos(a1));
-}else{
-_10.moveTo(this.cx,this.cy);
-}
-_10.lineTo(x1,y1);
-_10.arcTo(this.radius,this.radius,0,big,1,x2,y2);
-if(_f.size){
-_10.lineTo(this.cx+(this.radius-_f.size)*Math.sin(a2),this.cy-(this.radius-_f.size)*Math.cos(a2));
-_10.arcTo((this.radius-_f.size),(this.radius-_f.size),0,big,0,this.cx+(this.radius-_f.size)*Math.sin(a1),this.cy-(this.radius-_f.size)*Math.cos(a1));
-}
-_10.closePath();
-}
-if(dojo.isArray(_f.color)||dojo.isString(_f.color)){
-_10.setStroke({color:_f.color});
-_10.setFill(_f.color);
-}else{
-if(_f.color.type){
-a1=this._getRadians(this._getAngle(_f.low));
-a2=this._getRadians(this._getAngle(_f.high));
-_f.color.x1=this.cx+(this.radius*Math.sin(a1))/2;
-_f.color.x2=this.cx+(this.radius*Math.sin(a2))/2;
-_f.color.y1=this.cy-(this.radius*Math.cos(a1))/2;
-_f.color.y2=this.cy-(this.radius*Math.cos(a2))/2;
-_10.setFill(_f.color);
-_10.setStroke({color:_f.color.colors[0].color});
-}else{
-_10.setStroke({color:"green"});
-_10.setFill("green");
-_10.getEventSource().setAttribute("class",_f.color.style);
-}
-}
-if(_f.hover){
-_10.getEventSource().setAttribute("hover",_f.hover);
-}
-_f.shape=_10;
-},getRangeUnderMouse:function(_11){
-var _12=null;
-var pos=dojo.coords(this.gaugeContent);
-var x=_11.clientX-pos.x;
-var y=_11.clientY-pos.y;
-var r=Math.sqrt((y-this.cy)*(y-this.cy)+(x-this.cx)*(x-this.cx));
-if(r<this.radius){
-var _13=this._getDegrees(Math.atan2(y-this.cy,x-this.cx)+Math.PI/2);
-var _14=this._getValueForAngle(_13);
-if(this._rangeData){
-for(var i=0;(i<this._rangeData.length)&&!_12;i++){
-if((Number(this._rangeData[i].low)<=_14)&&(Number(this._rangeData[i].high)>=_14)){
-_12=this._rangeData[i];
-}
-}
-}
-}
-return _12;
-},_dragIndicator:function(_15,_16){
-var pos=dojo.coords(_15.gaugeContent);
-var x=_16.clientX-pos.x;
-var y=_16.clientY-pos.y;
-var _17=_15._getDegrees(Math.atan2(y-_15.cy,x-_15.cx)+Math.PI/2);
-var _18=_15._getValueForAngle(_17);
-if(_18<_15.min){
-_18=_15.min;
-}
-if(_18>_15.max){
-_18=_15.max;
-}
-_15._drag.value=_18;
-_15._drag.currentValue=_18;
-_15._drag.onDragMove(_15._drag);
-_15._drag.draw(true);
-dojo.stopEvent(_16);
-}});
-}
diff --git a/dojox/widget/AutoRotator.js b/dojox/widget/AutoRotator.js
index c11cabb..f66f9a2 100644
--- a/dojox/widget/AutoRotator.js
+++ b/dojox/widget/AutoRotator.js
@@ -1,104 +1,217 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.AutoRotator"]){
-dojo._hasResource["dojox.widget.AutoRotator"]=true;
 dojo.provide("dojox.widget.AutoRotator");
 dojo.require("dojox.widget.Rotator");
+
 (function(d){
-d.declare("dojox.widget.AutoRotator",dojox.widget.Rotator,{suspendOnHover:false,duration:4000,autoStart:true,pauseOnManualChange:false,cycles:-1,random:false,reverse:false,constructor:function(){
-var _1=this;
-if(_1.cycles-0==_1.cycles&&_1.cycles>0){
-_1.cycles++;
-}else{
-_1.cycles=_1.cycles?-1:0;
-}
-_1._connects=[d.connect(_1._domNode,"onmouseover",function(){
-if(_1.suspendOnHover&&!_1.anim&&!_1.wfe){
-var t=_1._endTime,n=_1._now();
-_1._suspended=true;
-_1._resetTimer();
-_1._resumeDuration=t>n?t-n:0.01;
-}
-}),d.connect(_1._domNode,"onmouseout",function(){
-if(_1.suspendOnHover&&!_1.anim){
-_1._suspended=false;
-if(_1.playing&&!_1.wfe){
-_1.play(true);
-}
-}
-})];
-if(_1.autoStart&&_1.panes.length>1){
-_1.play();
-}else{
-_1.pause();
-}
-},destroy:function(){
-d.forEach(this._connects,d.disconnect);
-this.inherited(arguments);
-},play:function(_2,_3){
-this.playing=true;
-this._resetTimer();
-if(_2!==true&&this.cycles>0){
-this.cycles--;
-}
-if(this.cycles==0){
-this.pause();
-}else{
-if(!this._suspended){
-this.onUpdate("play");
-if(_3){
-this._cycle();
-}else{
-var r=(this._resumeDuration||0)-0,u=(r>0?r:(this.panes[this.idx].duration||this.duration))-0;
-this._resumeDuration=0;
-this._endTime=this._now()+u;
-this._timer=setTimeout(d.hitch(this,"_cycle",false),u);
-}
-}
-}
-},pause:function(){
-this.playing=this._suspended=false;
-this.cycles=-1;
-this._resetTimer();
-this.onUpdate("pause");
-},_now:function(){
-return (new Date()).getTime();
-},_resetTimer:function(){
-clearTimeout(this._timer);
-},_cycle:function(_4){
-var _5=this,i=_5.idx,j;
-if(_5.random){
-do{
-j=Math.floor(Math.random()*_5.panes.length+1);
-}while(j==i);
-}else{
-j=i+(_5.reverse?-1:1);
-}
-var _6=_5.go(j);
-if(_6){
-_6.addCallback(function(_7){
-_5.onUpdate("cycle");
-if(_5.playing){
-_5.play(false,_7);
-}
-});
-}
-},onManualChange:function(_8){
-this.cycles=-1;
-if(_8!="play"){
-this._resetTimer();
-if(this.pauseOnManualChange){
-this.pause();
-}
-}
-if(this.playing){
-this.play();
-}
-}});
-})(dojo);
-}
+
+	d.declare("dojox.widget.AutoRotator", dojox.widget.Rotator, {
+		//	summary:
+		//		A rotator that automatically transitions between child nodes.
+		//
+		//	description:
+		//		Adds automatic rotating to the dojox.widget.Rotator.  The
+		//		AutoRotator has parameters that control how user input can
+		//		affect the rotator including a suspend when hovering over the
+		//		rotator and pausing when the user manually advances to another
+		//		pane.
+		//
+		//	example:
+		//	|	<div dojoType="dojox.widget.AutoRotator" duration="3000">
+		//	|		<div>
+		//	|			Pane 1!
+		//	|		</div>
+		//	|		<div duration="5000">
+		//	|			Pane 2 with an overrided duration!
+		//	|		</div>
+		//	|	</div>
+
+		//	suspendOnHover: boolean
+		//		Pause the rotator when the mouse hovers over it.
+		suspendOnHover: false,
+
+		//	duration: int
+		//		The time in milliseconds before transitioning to the next pane.  The
+		//		default value is 4000 (4 seconds).
+		duration: 4000,
+
+		//	autoStart: boolean
+		//		Starts the timer to transition children upon creation.
+		autoStart: true,
+
+		//	pauseOnManualChange: boolean
+		//		Pause the rotator when the pane is changed or a controller's next or
+		//		previous buttons are clicked.
+		pauseOnManualChange: false,
+
+		//	cycles: int
+		//		Number of cycles before pausing.
+		cycles: -1,
+
+		//	random: boolean
+		//		Determines if the panes should cycle randomly.
+		random: false,
+
+		//	reverse: boolean
+		//		Causes the rotator to rotate in reverse order.
+		reverse: false,
+
+		constructor: function(){
+			//	summary:
+			//		Initializes the timer and connect to the rotator.
+
+			var _t = this;
+
+			// validate the cycles counter
+			if(_t.cycles-0 == _t.cycles && _t.cycles > 0){
+				// we need to add 1 because we decrement cycles before the animation starts
+				_t.cycles++;
+			}else{
+				_t.cycles = _t.cycles ? -1 : 0;
+			}
+
+			// wire up the mouse hover events
+			_t._connects = [
+				d.connect(_t._domNode, "onmouseover", function(){
+					// temporarily suspend the cycling, but don't officially pause
+					// it and don't allow suspending if we're transitioning
+					if(_t.suspendOnHover && !_t.anim && !_t.wfe){
+						var t = _t._endTime,
+							n = _t._now();
+						_t._suspended = true;
+						_t._resetTimer();
+						_t._resumeDuration = t > n ? t - n : 0.01;
+					}
+				}),
+
+				d.connect(_t._domNode, "onmouseout", function(){
+					// if we were playing, resume playback unless were in the
+					// middle of a transition
+					if(_t.suspendOnHover && !_t.anim){
+						_t._suspended = false;
+						if(_t.playing && !_t.wfe){
+							_t.play(true);
+						}
+					}
+				})
+			];
+
+			// everything is ready, so start
+			if(_t.autoStart && _t.panes.length > 1){
+				// start playing
+				_t.play();
+			}else{
+				// since we're not playing, lets pause
+				_t.pause();
+			}
+		},
+
+		destroy: function(){
+			//	summary:
+			//		Disconnect the AutoRotator's events.
+			d.forEach(this._connects, d.disconnect);
+			this.inherited(arguments);
+		},
+
+		play: function(/*boolean?*/skipCycleDecrement, /*boolean?*/skipDuration){
+			//	summary:
+			//		Sets the state to "playing" and schedules the next cycle to run.
+			this.playing = true;
+			this._resetTimer();
+
+			// don't decrement the count if we're resuming play
+			if(skipCycleDecrement !== true && this.cycles > 0){
+				this.cycles--;
+			}
+
+			if(this.cycles == 0){
+				// we have reached the number of cycles, so pause
+				this.pause();
+			}else if(!this._suspended){
+				this.onUpdate("play");
+				// if we haven't been suspended, then grab the duration for this pane and
+				// schedule a cycle to be run
+				if(skipDuration){
+					this._cycle();
+				}else{
+					var r = (this._resumeDuration || 0)-0,
+						u = (r > 0 ? r : (this.panes[this.idx].duration || this.duration))-0;
+					// call _cycle() after a duration and pass in false so it isn't manual
+					this._resumeDuration = 0;
+					this._endTime = this._now() + u;
+					this._timer = setTimeout(d.hitch(this, "_cycle", false), u);
+				}
+			}
+		},
+
+		pause: function(){
+			//	summary:
+			//		Sets the state to "not playing" and clears the cycle timer.
+			this.playing = this._suspended = false;
+			this.cycles = -1;
+			this._resetTimer();
+
+			// notify the controllers we're paused
+			this.onUpdate("pause");
+		},
+
+		_now: function(){
+			//	summary:
+			//		Helper function to return the current system time in milliseconds.
+			return (new Date()).getTime(); /*int*/
+		},
+
+		_resetTimer: function(){
+			//	summary:
+			//		Resets the timer used to schedule the next transition.
+			clearTimeout(this._timer);
+		},
+
+		_cycle: function(/*boolean|int?*/manual){
+			//	summary:
+			//		Cycles the rotator to the next/previous pane.
+			var _t = this,
+				i = _t.idx,
+				j;
+
+			if(_t.random){
+				// make sure we don't randomly pick the pane we're already on
+				do{
+					j = Math.floor(Math.random() * _t.panes.length + 1);
+				}while(j == i);
+			}else{
+				j = i + (_t.reverse ? -1 : 1)
+			}
+
+			// rotate!
+			var def = _t.go(j);
+
+			if(def){
+				def.addCallback(function(/*boolean?*/skipDuration){
+					_t.onUpdate("cycle");
+					if(_t.playing){
+						_t.play(false, skipDuration);
+					}
+				});
+			}
+		},
+
+		onManualChange: function(/*string*/action){
+			//	summary:
+			//		Override the Rotator's onManualChange so we can pause.
+
+			this.cycles = -1;
+
+			// obviously we don't want to pause if play was just clicked
+			if(action != "play"){
+				this._resetTimer();
+				if(this.pauseOnManualChange){
+					this.pause();
+				}
+			}
+
+			if(this.playing){
+				this.play();
+			}
+		}
+	});
+
+})(dojo);
\ No newline at end of file
diff --git a/dojox/widget/BarGauge.js b/dojox/widget/BarGauge.js
index 242531d..f5d6697 100644
--- a/dojox/widget/BarGauge.js
+++ b/dojox/widget/BarGauge.js
@@ -1,194 +1,292 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.BarGauge"]){
-dojo._hasResource["dojox.widget.BarGauge"]=true;
 dojo.provide("dojox.widget.BarGauge");
+
 dojo.require("dojox.gfx");
 dojo.require("dojox.widget.gauge._Gauge");
+
 dojo.experimental("dojox.widget.BarGauge");
-dojo.declare("dojox.widget.gauge.BarLineIndicator",[dojox.widget.gauge._Indicator],{width:1,_getShapes:function(){
-if(!this._gauge){
-return null;
-}
-var v=this.value;
-if(v<this._gauge.min){
-v=this._gauge.min;
-}
-if(v>this._gauge.max){
-v=this._gauge.max;
-}
-var _1=this._gauge._getPosition(v);
-var _2=[];
-if(this.width>1){
-_2[0]=this._gauge.surface.createRect({x:_1,y:this._gauge.dataY+this.offset,width:this.width,height:this.length});
-_2[0].setStroke({color:this.color});
-_2[0].setFill(this.color);
-}else{
-_2[0]=this._gauge.surface.createLine({x1:_1,y1:this._gauge.dataY+this.offset,x2:_1,y2:this._gauge.dataY+this.offset+this.length});
-_2[0].setStroke({color:this.color});
-}
-return _2;
-},draw:function(_3){
-var i;
-if(this.shapes){
-this._move(_3);
-}else{
-if(this.shapes){
-for(i=0;i<this.shapes.length;i++){
-this._gauge.surface.remove(this.shapes[i]);
-}
-this.shapes=null;
-}
-if(this.text){
-this._gauge.surface.rawNode.removeChild(this.text);
-this.text=null;
-}
-this.color=this.color||"#000000";
-this.length=this.length||this._gauge.dataHeight;
-this.width=this.width||3;
-this.offset=this.offset||0;
-this.highlight=this.highlight||"#4D4D4D";
-this.highlight2=this.highlight2||"#A3A3A3";
-this.shapes=this._getShapes(this._gauge,this);
-if(this.label){
-var v=this.value;
-if(v<this._gauge.min){
-v=this._gauge.min;
-}
-if(v>this._gauge.max){
-v=this._gauge.max;
-}
-var _4=this._gauge._getPosition(v);
-this.text=this._gauge.drawText(""+this.label,_4,this._gauge.dataY+this.offset-5,"middle","top",this.color,this.font);
-}
-for(i=0;i<this.shapes.length;i++){
-if(this.hover){
-this.shapes[i].getEventSource().setAttribute("hover",this.hover);
-}
-if(this.onDragMove&&!this.noChange){
-this._gauge.connect(this.shapes[i].getEventSource(),"onmousedown",this._gauge.handleMouseDown);
-this.shapes[i].getEventSource().style.cursor="pointer";
-}
-}
-this.currentValue=this.value;
-}
-},_move:function(_5){
-var v=this.value;
-if(v<this.min){
-v=this.min;
-}
-if(v>this.max){
-v=this.max;
-}
-var c=this._gauge._getPosition(this.currentValue);
-this.currentValue=v;
-v=this._gauge._getPosition(v)-this._gauge.dataX;
-if(_5){
-this.shapes[0].applyTransform(dojox.gfx.matrix.translate(v-(this.shapes[0].matrix?this.shapes[0].matrix.dx:0),0));
-}else{
-var _6=new dojo.Animation({curve:[c,v],duration:this.duration,easing:this.easing});
-dojo.connect(_6,"onAnimate",dojo.hitch(this,function(_7){
-this.shapes[0].applyTransform(dojox.gfx.matrix.translate(_7-(this.shapes[0].matrix?this.shapes[0].matrix.dx:0),0));
-}));
-_6.play();
-}
-}});
-dojo.declare("dojox.widget.BarGauge",dojox.widget.gauge._Gauge,{dataX:5,dataY:5,dataWidth:0,dataHeight:0,_defaultIndicator:dojox.widget.gauge.BarLineIndicator,startup:function(){
-if(this.getChildren){
-dojo.forEach(this.getChildren(),function(_8){
-_8.startup();
+
+dojo.declare("dojox.widget.gauge.BarLineIndicator",[dojox.widget.gauge._Indicator],{
+	width: 1,
+	_getShapes: function(){
+		// summary:
+		//		Private function for generating the shapes for this indicator. An indicator that behaves the 
+		//		same might override this one and simply replace the shapes (such as BarIndicator).
+		if(!this._gauge){
+			return null;
+		}
+		var v = this.value;
+		if(v < this._gauge.min){v = this._gauge.min;}
+		if(v > this._gauge.max){v = this._gauge.max;}
+		var pos = this._gauge._getPosition(v);
+		var shapes = [];
+		if(this.width > 1){
+			shapes[0] = this._gauge.surface.createRect({
+				x:pos, 
+				y:this._gauge.dataY + this.offset,
+				width:this.width, 
+				height:this.length
+			});
+			shapes[0].setStroke({color: this.color});
+			shapes[0].setFill(this.color);
+		}else{
+			shapes[0] = this._gauge.surface.createLine({
+				x1:pos, 
+				y1:this._gauge.dataY + this.offset,
+				x2:pos, 
+				y2:this._gauge.dataY + this.offset + this.length
+			});
+			shapes[0].setStroke({color: this.color});
+		}
+		return shapes;
+	},
+	draw: function(/*Boolean?*/ dontAnimate){
+		// summary: 
+		//		Override of dojox.widget.gauge._Indicator.draw
+		// dontAnimate: Boolean
+		//		Indicates if the drawing should not be animated (vs. the default of doing an animation)
+		var i;
+		if(this.shapes){
+			this._move(dontAnimate);
+		}else{
+			if(this.shapes){
+				for(i=0; i<this.shapes.length; i++){
+					this._gauge.surface.remove(this.shapes[i]);
+				}
+				this.shapes = null;
+			}
+			if(this.text){
+				this._gauge.surface.rawNode.removeChild(this.text);
+				this.text = null;
+			}
+	
+			this.color = this.color || '#000000';
+			this.length = this.length || this._gauge.dataHeight;
+			this.width = this.width || 3;
+			this.offset = this.offset || 0;
+			this.highlight = this.highlight || '#4D4D4D';
+			this.highlight2 = this.highlight2 || '#A3A3A3';
+	
+			this.shapes = this._getShapes(this._gauge, this);
+			if(this.label){
+				var v = this.value;
+				if(v < this._gauge.min){v = this._gauge.min;}
+				if(v > this._gauge.max){v = this._gauge.max;}
+				var pos = this._gauge._getPosition(v);
+				this.text = this._gauge.drawText(''+this.label, pos, this._gauge.dataY + this.offset - 5, 'middle','top', this.color, this.font);
+			}
+	
+			for(i=0; i<this.shapes.length; i++){
+				if(this.hover){
+					this.shapes[i].getEventSource().setAttribute('hover',this.hover);
+				}
+				if(this.onDragMove && !this.noChange){
+					this._gauge.connect(this.shapes[i].getEventSource(), 'onmousedown', this._gauge.handleMouseDown);
+					this.shapes[i].getEventSource().style.cursor = 'pointer';
+				}
+			}
+			this.currentValue = this.value;
+		}
+	},
+	_move: function(/*Boolean?*/ dontAnimate){
+		// summary: 
+		//		Moves this indicator (since it's already been drawn once)
+		// dontAnimate: Boolean
+		//		Indicates if the drawing should not be animated (vs. the default of doing an animation)
+		var v = this.value ;
+		if(v < this.min){v = this.min;}
+		if(v > this.max){v = this.max;}
+		var c = this._gauge._getPosition(this.currentValue);
+		this.currentValue = v;
+		v = this._gauge._getPosition(v)-this._gauge.dataX;
+		if(dontAnimate){
+			this.shapes[0].applyTransform(dojox.gfx.matrix.translate(v-(this.shapes[0].matrix?this.shapes[0].matrix.dx:0),0));
+		}else{
+			var anim = new dojo.Animation({curve: [c, v], duration: this.duration, easing: this.easing});
+			dojo.connect(anim, "onAnimate", dojo.hitch(this, function(jump){
+				this.shapes[0].applyTransform(dojox.gfx.matrix.translate(jump-(this.shapes[0].matrix?this.shapes[0].matrix.dx:0),0));
+			}));
+			anim.play();
+		}
+	}
+});
+dojo.declare("dojox.widget.BarGauge",dojox.widget.gauge._Gauge,{
+	// summary:
+	//		a bar graph built using the dojox.gfx package.
+	//
+	// description:
+	//		using dojo.gfx (and thus either SVG or VML based on what is supported), this widget
+	//		builds a bar graph component, used to display numerical data in a familiar format.
+	//
+	// usage:
+	//		<script type="text/javascript">
+	//			dojo.require("dojox.widget.BarGauge");
+	//			dojo.require("dijit.util.parser");
+	//		</script>
+	//		...
+	//		<div 	dojoType="dojox.widget.BarGauge"
+	//				id="testBarGauge"
+	//				barGaugeHeight="55"
+	//				dataY="25"
+	//				dataHeight="25"
+	//				dataWidth="225">
+	//		</div>
+
+	// dataX: Number
+	// x position of data area (default 5)
+	dataX: 5,
+
+	// dataY: Number
+	// y position of data area (default 5)
+	dataY: 5,
+
+	// dataWidth: Number
+	// width of data area (default is bar graph width - 10)
+	dataWidth: 0,
+
+	// dataHeight: Number
+	// height of data area (default is bar graph width - 10)
+	dataHeight: 0,
+
+	// _defaultIndicator: override of dojox.widget._Gauge._defaultIndicator
+	_defaultIndicator: dojox.widget.gauge.BarLineIndicator,
+
+	startup: function(){
+		// handle settings from HTML by making sure all the options are
+		// converted correctly to numbers 
+		//
+		// also connects mouse handling events
+
+		if(this.getChildren){
+			dojo.forEach(this.getChildren(), function(child){ child.startup(); });
+		}
+
+		if(!this.dataWidth){this.dataWidth = this.gaugeWidth - 10;}
+		if(!this.dataHeight){this.dataHeight = this.gaugeHeight - 10;}
+
+		this.inherited(arguments);
+	},
+
+	_getPosition: function(/*Number*/value){
+		// summary:
+		//		This is a helper function used to determine the position that represents
+		//		a given value on the bar graph
+		// value:	Number
+		//			A value to be converted to a position for this bar graph.
+
+		return this.dataX + Math.floor((value - this.min)/(this.max - this.min)*this.dataWidth);
+	},
+
+	_getValueForPosition: function(/*Number*/pos){
+		// summary:
+		//		This is a helper function used to determine the value represented by
+		//		a position on the bar graph
+		// pos:		Number
+		//			A position to be converted to a value.
+		return (pos - this.dataX)*(this.max - this.min)/this.dataWidth + this.min;
+	},
+
+	draw: function(){
+		// summary:
+		//		This function is used to draw (or redraw) the bar graph
+		// description:
+		//		Draws the bar graph by drawing the surface, the ranges, and the indicators.
+
+		if(!this.surface){this.createSurface();}
+
+		var i;
+		if(this._rangeData){
+			for(i=0; i<this._rangeData.length; i++){
+				this.drawRange(this._rangeData[i]);
+			}
+			if(this._img && this.image.overlay){
+				this._img.moveToFront();
+			}
+		}
+		if(this._indicatorData){
+			for(i=0; i<this._indicatorData.length; i++){
+				this._indicatorData[i].draw();
+			}
+		}
+	},
+
+	drawRange: function(/*Object*/range){
+		// summary:
+		//		This function is used to draw (or redraw) a range
+		// description:
+		//		Draws a range (colored area on the background of the gauge) 
+		//		based on the given arguments.
+		// range:
+		//		A range is either a dojox.widget.gauge.Range or an object
+		//		with similar parameters (low, high, hover, etc.).
+		if(range.shape){
+			this.surface.remove(range.shape);
+			range.shape = null;
+		}
+
+		var x1 = this._getPosition(range.low);
+		var x2 = this._getPosition(range.high);
+		var path = this.surface.createRect({x:x1, 
+											y:this.dataY, 
+											width:x2-x1, 
+											height:this.dataHeight});
+		if(dojo.isArray(range.color) || dojo.isString(range.color)){
+			path.setStroke({color: range.color});
+			path.setFill(range.color);
+		}else if(range.color.type){
+			// Color is a gradient
+			var y = this.dataY + this.dataHeight/2;
+			range.color.x1 = x1;
+			range.color.x2 = x2;
+			range.color.y1 = y;
+			range.color.y2 = y;
+			path.setFill(range.color);
+			path.setStroke({color: range.color.colors[0].color});
+		}else{
+			// We've defined a style rather than an explicit color
+			path.setStroke({color: "green"});	// Arbitrary color, just have to indicate
+			path.setFill("green");				// that we want it filled
+			path.getEventSource().setAttribute("class", range.color.style);
+		}
+		if(range.hover){
+			path.getEventSource().setAttribute('hover',range.hover);
+		}
+		range.shape = path;
+	},
+
+	getRangeUnderMouse: function(/*Object*/event){
+		// summary:
+		//		Determines which range the mouse is currently over
+		// event:	Object
+		//			The event object as received by the mouse handling functions below.
+		var range = null;
+		var pos = dojo.coords(this.gaugeContent);
+		var x = event.clientX - pos.x;
+		var value = this._getValueForPosition(x);
+		if(this._rangeData){
+			for(var i=0; (i<this._rangeData.length) && !range; i++){
+				if((Number(this._rangeData[i].low) <= value) && (Number(this._rangeData[i].high) >= value)){
+					range = this._rangeData[i];
+				}
+			}
+		}
+		return range;
+	},
+
+	_dragIndicator: function(/*Object*/ widget, /*Object*/ event){
+		// summary:
+		//		Handles the dragging of an indicator, including moving/re-drawing
+		// get new value based on mouse position
+		var pos = dojo.coords(widget.gaugeContent);
+		var x = event.clientX - pos.x;
+		var value = widget._getValueForPosition(x);
+		if(value < widget.min){value = widget.min;}
+		if(value > widget.max){value = widget.max;}
+		// update the indicator
+		widget._drag.value = value;
+		// callback
+		widget._drag.onDragMove(widget._drag);
+		// redraw/move indicator(s)
+		widget._drag.draw(true);
+		dojo.stopEvent(event);
+	}
 });
-}
-if(!this.dataWidth){
-this.dataWidth=this.gaugeWidth-10;
-}
-if(!this.dataHeight){
-this.dataHeight=this.gaugeHeight-10;
-}
-this.inherited(arguments);
-},_getPosition:function(_9){
-return this.dataX+Math.floor((_9-this.min)/(this.max-this.min)*this.dataWidth);
-},_getValueForPosition:function(_a){
-return (_a-this.dataX)*(this.max-this.min)/this.dataWidth+this.min;
-},draw:function(){
-if(!this.surface){
-this.createSurface();
-}
-var i;
-if(this._rangeData){
-for(i=0;i<this._rangeData.length;i++){
-this.drawRange(this._rangeData[i]);
-}
-if(this._img&&this.image.overlay){
-this._img.moveToFront();
-}
-}
-if(this._indicatorData){
-for(i=0;i<this._indicatorData.length;i++){
-this._indicatorData[i].draw();
-}
-}
-},drawRange:function(_b){
-if(_b.shape){
-this.surface.remove(_b.shape);
-_b.shape=null;
-}
-var x1=this._getPosition(_b.low);
-var x2=this._getPosition(_b.high);
-var _c=this.surface.createRect({x:x1,y:this.dataY,width:x2-x1,height:this.dataHeight});
-if(dojo.isArray(_b.color)||dojo.isString(_b.color)){
-_c.setStroke({color:_b.color});
-_c.setFill(_b.color);
-}else{
-if(_b.color.type){
-var y=this.dataY+this.dataHeight/2;
-_b.color.x1=x1;
-_b.color.x2=x2;
-_b.color.y1=y;
-_b.color.y2=y;
-_c.setFill(_b.color);
-_c.setStroke({color:_b.color.colors[0].color});
-}else{
-_c.setStroke({color:"green"});
-_c.setFill("green");
-_c.getEventSource().setAttribute("class",_b.color.style);
-}
-}
-if(_b.hover){
-_c.getEventSource().setAttribute("hover",_b.hover);
-}
-_b.shape=_c;
-},getRangeUnderMouse:function(_d){
-var _e=null;
-var _f=dojo.coords(this.gaugeContent);
-var x=_d.clientX-_f.x;
-var _10=this._getValueForPosition(x);
-if(this._rangeData){
-for(var i=0;(i<this._rangeData.length)&&!_e;i++){
-if((Number(this._rangeData[i].low)<=_10)&&(Number(this._rangeData[i].high)>=_10)){
-_e=this._rangeData[i];
-}
-}
-}
-return _e;
-},_dragIndicator:function(_11,_12){
-var pos=dojo.coords(_11.gaugeContent);
-var x=_12.clientX-pos.x;
-var _13=_11._getValueForPosition(x);
-if(_13<_11.min){
-_13=_11.min;
-}
-if(_13>_11.max){
-_13=_11.max;
-}
-_11._drag.value=_13;
-_11._drag.onDragMove(_11._drag);
-_11._drag.draw(true);
-dojo.stopEvent(_12);
-}});
-}
diff --git a/dojox/widget/Calendar.js b/dojox/widget/Calendar.js
index f292d95..09f3b6b 100644
--- a/dojox/widget/Calendar.js
+++ b/dojox/widget/Calendar.js
@@ -1,502 +1,885 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.Calendar"]){
-dojo._hasResource["dojox.widget.Calendar"]=true;
 dojo.provide("dojox.widget.Calendar");
 dojo.experimental("dojox.widget.Calendar");
+
 dojo.require("dijit.Calendar");
 dojo.require("dijit._Container");
-dojo.declare("dojox.widget._CalendarBase",[dijit._Widget,dijit._Templated,dijit._Container],{templateString:dojo.cache("dojox.widget","Calendar/Calendar.html","<div class=\"dojoxCalendar\">\n    <div tabindex=\"0\" class=\"dojoxCalendarContainer\" style=\"visibility: visible;\" dojoAttachPoint=\"container\">\n\t\t<div style=\"display:none\">\n\t\t\t<div dojoAttachPoint=\"previousYearLabelNode\"></div>\n\t\t\t<div dojoAttachPoint=\"nextYearLabelNode\"></div>\n\t\t\t<div dojoAttachPoint=\" [...]
-this._views=[];
-},postMixInProperties:function(){
-var c=this.constraints;
-if(c){
-var _1=dojo.date.stamp.fromISOString;
-if(typeof c.min=="string"){
-c.min=_1(c.min);
-}
-if(typeof c.max=="string"){
-c.max=_1(c.max);
-}
-}
-},postCreate:function(){
-this.displayMonth=new Date(this.attr("value"));
-var _2={parent:this,_getValueAttr:dojo.hitch(this,function(){
-return new Date(this._internalValue||this.value);
-}),_getDisplayMonthAttr:dojo.hitch(this,function(){
-return new Date(this.displayMonth);
-}),_getConstraintsAttr:dojo.hitch(this,function(){
-return this.constraints;
-}),getLang:dojo.hitch(this,function(){
-return this.lang;
-}),isDisabledDate:dojo.hitch(this,this.isDisabledDate),getClassForDate:dojo.hitch(this,this.getClassForDate),addFx:this.useFx?dojo.hitch(this,this.addFx):function(){
-}};
-dojo.forEach(this._views,function(_3){
-var _4=new _3(_2,dojo.create("div"));
-this.addChild(_4);
-var _5=_4.getHeader();
-if(_5){
-this.header.appendChild(_5);
-dojo.style(_5,"display","none");
-}
-dojo.style(_4.domNode,"visibility","hidden");
-dojo.connect(_4,"onValueSelected",this,"_onDateSelected");
-_4.attr("value",this.attr("value"));
-},this);
-if(this._views.length<2){
-dojo.style(this.header,"cursor","auto");
-}
-this.inherited(arguments);
-this._children=this.getChildren();
-this._currentChild=0;
-var _6=new Date();
-this.footer.innerHTML="Today: "+dojo.date.locale.format(_6,{formatLength:this.footerFormat,selector:"date",locale:this.lang});
-dojo.connect(this.footer,"onclick",this,"goToToday");
-var _7=this._children[0];
-dojo.style(_7.domNode,"top","0px");
-dojo.style(_7.domNode,"visibility","visible");
-var _8=_7.getHeader();
-if(_8){
-dojo.style(_7.getHeader(),"display","");
-}
-dojo[_7.useHeader?"removeClass":"addClass"](this.container,"no-header");
-_7.onDisplay();
-var _9=this;
-var _a=function(_b,_c,_d){
-dijit.typematic.addMouseListener(_9[_b],_9,function(_e){
-if(_e>=0){
-_9._adjustDisplay(_c,_d);
-}
-},0.8,500);
-};
-_a("incrementMonth","month",1);
-_a("decrementMonth","month",-1);
-this._updateTitleStyle();
-},addFx:function(_f,_10){
-},_setValueAttr:function(_11){
-if(!_11["getFullYear"]){
-_11=dojo.date.stamp.fromISOString(_11+"");
-}
-if(!this.value||dojo.date.compare(_11,this.value)){
-_11=new Date(_11);
-this.displayMonth=new Date(_11);
-this._internalValue=_11;
-if(!this.isDisabledDate(_11,this.lang)&&this._currentChild==0){
-this.value=_11;
-this.onChange(_11);
-}
-this._children[this._currentChild].attr("value",this.value);
-return true;
-}
-return false;
-},isDisabledDate:function(_12,_13){
-var c=this.constraints;
-var _14=dojo.date.compare;
-return c&&(c.min&&(_14(c.min,_12,"date")>0)||(c.max&&_14(c.max,_12,"date")<0));
-},onValueSelected:function(_15){
-},_onDateSelected:function(_16,_17,_18){
-this.displayMonth=_16;
-this.attr("value",_16);
-if(!this._transitionVert(-1)){
-if(!_17&&_17!==0){
-_17=this.attr("value");
-}
-this.onValueSelected(_17);
-}
-},onChange:function(_19){
-},onHeaderClick:function(e){
-this._transitionVert(1);
-},goToToday:function(){
-this.attr("value",new Date());
-this.onValueSelected(this.attr("value"));
-},_transitionVert:function(_1a){
-var _1b=this._children[this._currentChild];
-var _1c=this._children[this._currentChild+_1a];
-if(!_1c){
-return false;
-}
-dojo.style(_1c.domNode,"visibility","visible");
-var _1d=dojo.style(this.containerNode,"height");
-_1c.attr("value",this.displayMonth);
-if(_1b.header){
-dojo.style(_1b.header,"display","none");
-}
-if(_1c.header){
-dojo.style(_1c.header,"display","");
-}
-dojo.style(_1c.domNode,"top",(_1d*-1)+"px");
-dojo.style(_1c.domNode,"visibility","visible");
-this._currentChild+=_1a;
-var _1e=_1d*_1a;
-var _1f=0;
-dojo.style(_1c.domNode,"top",(_1e*-1)+"px");
-var _20=dojo.animateProperty({node:_1b.domNode,properties:{top:_1e},onEnd:function(){
-dojo.style(_1b.domNode,"visibility","hidden");
-}});
-var _21=dojo.animateProperty({node:_1c.domNode,properties:{top:_1f},onEnd:function(){
-_1c.onDisplay();
-}});
-dojo[_1c.useHeader?"removeClass":"addClass"](this.container,"no-header");
-_20.play();
-_21.play();
-_1b.onBeforeUnDisplay();
-_1c.onBeforeDisplay();
-this._updateTitleStyle();
-return true;
-},_updateTitleStyle:function(){
-dojo[this._currentChild<this._children.length-1?"addClass":"removeClass"](this.header,"navToPanel");
-},_slideTable:function(_22,_23,_24){
-var _25=_22.domNode;
-var _26=_25.cloneNode(true);
-var _27=dojo.style(_25,"width");
-_25.parentNode.appendChild(_26);
-dojo.style(_25,"left",(_27*_23)+"px");
-_24();
-var _28=dojo.animateProperty({node:_26,properties:{left:_27*_23*-1},duration:500,onEnd:function(){
-_26.parentNode.removeChild(_26);
-}});
-var _29=dojo.animateProperty({node:_25,properties:{left:0},duration:500});
-_28.play();
-_29.play();
-},_addView:function(_2a){
-this._views.push(_2a);
-},getClassForDate:function(_2b,_2c){
-},_adjustDisplay:function(_2d,_2e,_2f){
-var _30=this._children[this._currentChild];
-var _31=this.displayMonth=_30.adjustDate(this.displayMonth,_2e);
-this._slideTable(_30,_2e,function(){
-_30.attr("value",_31);
+
+dojo.declare("dojox.widget._CalendarBase", [dijit._Widget, dijit._Templated, dijit._Container], {
+	// summary: 
+	//		The Root class for all _Calendar extensions
+
+	// templateString: String
+	//		The template to be used to construct the widget.
+	templateString: dojo.cache("dojox.widget","Calendar/Calendar.html"),
+
+	// _views: Array
+	//		The list of mixin views available on this calendar.
+	_views: null,
+
+	// useFx: Boolean
+	//		Specifies if visual effects should be applied to the widget.
+	//		The default behavior of the widget does not contain any effects.
+	//		The dojox.widget.CalendarFx package is needed for these.
+	useFx: true,
+
+	// widgetsInTemplate: Boolean
+	//		This widget is a container of other widgets, so this is true.
+	widgetsInTemplate: true,
+
+	// value: Date
+	//		The currently selected Date
+	value: new Date(),
+
+	constraints: null,
+
+	// footerFormat: String
+	//		The date format of the date displayed in the footer.	Can be
+	//		'short', 'medium', and 'long'
+	footerFormat: "medium",
+
+	constructor: function(){
+		this._views = [];
+	},
+
+	postMixInProperties: function(){
+		var c = this.constraints;
+		if(c){
+			var fromISO = dojo.date.stamp.fromISOString;
+			if(typeof c.min == "string"){
+				c.min = fromISO(c.min);
+			}
+			if(typeof c.max == "string"){
+				c.max = fromISO(c.max);
+			}
+		}
+	},
+
+	postCreate: function(){
+		// summary:
+		//		Instantiates the mixin views
+		this.displayMonth = new Date(this.get('value'));
+
+		var mixin = {
+			parent: this,
+			_getValueAttr: dojo.hitch(this, function(){return new Date(this._internalValue || this.value);}),
+			_getDisplayMonthAttr: dojo.hitch(this, function(){return new Date(this.displayMonth);}),
+			_getConstraintsAttr: dojo.hitch(this, function(){return this.constraints;}),
+			getLang: dojo.hitch(this, function(){return this.lang;}),
+			isDisabledDate: dojo.hitch(this, this.isDisabledDate),
+			getClassForDate: dojo.hitch(this, this.getClassForDate),
+			addFx: this.useFx ? dojo.hitch(this, this.addFx) : function(){}
+		};
+
+		//Add the mixed in views.
+		dojo.forEach(this._views, function(widgetType){
+			var widget = new widgetType(mixin, dojo.create('div'));
+			this.addChild(widget);
+
+			var header = widget.getHeader();
+			if(header){
+			//place the views's header node in the header of the main widget
+				this.header.appendChild(header);
+
+				//hide the header node of the widget
+				dojo.style(header, "display", "none");
+			}
+			//Hide all views
+			dojo.style(widget.domNode, "visibility", "hidden");
+
+			//Listen for the values in a view to be selected
+			dojo.connect(widget, "onValueSelected", this, "_onDateSelected");
+			widget.attr("value", this.get('value'));
+		}, this);
+
+		if(this._views.length < 2){
+			dojo.style(this.header, "cursor", "auto");
+		}
+
+		this.inherited(arguments);
+
+		// Cache the list of children widgets.
+		this._children = this.getChildren();
+
+		this._currentChild = 0;
+
+		//Populate the footer with today's date.
+		var today = new Date();
+
+		this.footer.innerHTML = "Today: " 
+			+ dojo.date.locale.format(today, {
+				formatLength:this.footerFormat,
+				selector:'date', 
+				locale:this.lang});
+
+		dojo.connect(this.footer, "onclick", this, "goToToday");
+
+		var first = this._children[0];
+
+		dojo.style(first.domNode, "top", "0px");
+		dojo.style(first.domNode, "visibility", "visible");
+
+		var header = first.getHeader();
+		if(header){
+			dojo.style(first.getHeader(), "display", "");
+		}
+
+		dojo[first.useHeader ? "removeClass" : "addClass"](this.container, "no-header");
+
+		first.onDisplay();
+
+		var _this = this;
+
+		var typematic = function(nodeProp, dateProp, adj){
+			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);
+		this._updateTitleStyle();
+	},
+
+	addFx: function(query, fromNode){
+		// Stub function than can be overridden to add effects.
+	},
+
+	_setValueAttr: function(/*Date*/ value){
+		// summary:
+		//		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.
+		if(!value["getFullYear"]){
+			value = dojo.date.stamp.fromISOString(value + "");
+		}
+		if(!this.value || dojo.date.compare(value, this.value)){
+			value = new Date(value);
+			this.displayMonth = new Date(value);
+			this._internalValue = value;
+			if(!this.isDisabledDate(value, this.lang) && this._currentChild == 0){
+				this.value = value;
+				this.onChange(value);
+			}
+			this._children[this._currentChild].attr("value", this.value);
+			return true;
+		}
+		return false;
+	},
+
+	isDisabledDate: function(/*Date*/date, /*String?*/locale){
+		// summary:
+		//		May be overridden to disable certain dates in the calendar e.g. `isDisabledDate=dojo.date.locale.isWeekend`
+		var c = this.constraints;
+		var compare = dojo.date.compare;
+		return c && (c.min && (compare(c.min, date, "date") > 0) ||
+							(c.max && compare(c.max, date, "date") < 0));
+	},
+
+	onValueSelected: function(/*Date*/date){
+		// summary: 
+		//		A date cell was selected. It may be the same as the previous value.
+	},
+
+	_onDateSelected: function(date, formattedValue, force){
+		this.displayMonth = date;
+
+		this.set("value", date)
+		//Only change the selected value if it was chosen from the
+		//first child.
+		if(!this._transitionVert(-1)){
+			if(!formattedValue && formattedValue !== 0){
+				formattedValue = this.get('value');
+			}
+			this.onValueSelected(formattedValue);
+		}
+
+	},
+
+	onChange: function(/*Date*/date){
+		// summary:
+		//		Called only when the selected date has changed
+	},
+
+	onHeaderClick: function(e){
+		// summary:
+		//	Transitions to the next view.
+		this._transitionVert(1);
+	},
+
+	goToToday: function(){
+		this.set("value", new Date());
+		this.onValueSelected(this.get('value'));
+	},
+
+	_transitionVert: function(/*Number*/direction){
+		// summary: 
+		//		Animates the views to show one and hide another, in a
+		//		vertical direction.
+		//		If 'direction' is 1, then the views slide upwards.
+		//		If 'direction' is -1, the views slide downwards.
+		var curWidget = this._children[this._currentChild];
+		var nextWidget = this._children[this._currentChild + direction];
+		if(!nextWidget){return false;}
+
+		dojo.style(nextWidget.domNode, "visibility", "visible");
+
+		var height = dojo.style(this.containerNode, "height");
+		nextWidget.attr("value", this.displayMonth);
+
+		if(curWidget.header){
+			dojo.style(curWidget.header, "display", "none");
+		}
+		if(nextWidget.header){
+			dojo.style(nextWidget.header, "display", "");
+		}
+		dojo.style(nextWidget.domNode, "top", (height * -1) + "px");
+		dojo.style(nextWidget.domNode, "visibility", "visible");
+
+		this._currentChild += direction;
+
+		var height1 = height * direction;
+		var height2 = 0;
+		dojo.style(nextWidget.domNode, "top", (height1 * -1) + "px");
+
+		// summary: Slides two nodes vertically.
+		var anim1 = dojo.animateProperty({
+			node: curWidget.domNode,
+			properties: {top: height1},
+			onEnd: function(){
+				dojo.style(curWidget.domNode, "visibility", "hidden");
+			}
+		});
+		var anim2 = dojo.animateProperty({
+			node: nextWidget.domNode,
+			properties: {top: height2},
+			onEnd: function(){
+				nextWidget.onDisplay();
+			}
+		});
+
+		dojo[nextWidget.useHeader ? "removeClass" : "addClass"](this.container, "no-header");
+
+		anim1.play();
+		anim2.play();
+		curWidget.onBeforeUnDisplay()
+		nextWidget.onBeforeDisplay();
+
+		this._updateTitleStyle();
+		return true;
+	},
+
+	_updateTitleStyle: function(){
+		dojo[this._currentChild < this._children.length -1 ? "addClass" : "removeClass"](this.header, "navToPanel");
+	},
+
+	_slideTable: function(/*String*/widget, /*Number*/direction, /*Function*/callback){
+		// summary:
+		//		Animates the horizontal sliding of a table.
+		var table = widget.domNode;
+
+		//Clone the existing table
+		var newTable = table.cloneNode(true);
+		var left = dojo.style(table, "width");
+
+		table.parentNode.appendChild(newTable);
+
+		//Place the existing node either to the left or the right of the new node,
+		//depending on which direction it is to slide.
+		dojo.style(table, "left", (left * direction) + "px");
+
+		//Call the function that generally populates the new cloned node with new data.
+		//It may also attach event listeners.
+		callback();
+
+		//Animate the two nodes.
+		var anim1 = dojo.animateProperty({node: newTable, properties:{left: left * direction * -1}, duration: 500, onEnd: function(){
+			newTable.parentNode.removeChild(newTable);
+		}});
+		var anim2 = dojo.animateProperty({node: table, properties:{left: 0}, duration: 500});
+
+		anim1.play();
+		anim2.play();
+	},
+
+	_addView: function(view){
+		//Insert the view at the start of the array.
+		this._views.push(view);
+	},
+
+	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.
+
+/*=====
+		return ""; // String
+=====*/
+	},
+
+	_adjustDisplay: function(/*String*/part, /*int*/amount, noSlide){
+		// summary:
+		//		This function overrides the base function defined in dijit.Calendar.
+		//		It changes the displayed years, months and days depending on the inputs.
+		var child = this._children[this._currentChild];
+
+		var month = this.displayMonth = child.adjustDate(this.displayMonth, amount);
+
+		this._slideTable(child, amount, function(){
+			child.attr("value", month);
+		});
+	}
 });
-}});
-dojo.declare("dojox.widget._CalendarView",dijit._Widget,{headerClass:"",useHeader:true,cloneClass:function(_32,n,_33){
-var _34=dojo.query(_32,this.domNode)[0];
-var i;
-if(!_33){
-for(i=0;i<n;i++){
-_34.parentNode.appendChild(_34.cloneNode(true));
-}
-}else{
-var _35=dojo.query(_32,this.domNode)[0];
-for(i=0;i<n;i++){
-_34.parentNode.insertBefore(_34.cloneNode(true),_35);
-}
-}
-},_setText:function(_36,_37){
-if(_36.innerHTML!=_37){
-dojo.empty(_36);
-_36.appendChild(dojo.doc.createTextNode(_37));
-}
-},getHeader:function(){
-return this.header||(this.header=this.header=dojo.create("span",{"class":this.headerClass}));
-},onValueSelected:function(_38){
-},adjustDate:function(_39,_3a){
-return dojo.date.add(_39,this.datePart,_3a);
-},onDisplay:function(){
-},onBeforeDisplay:function(){
-},onBeforeUnDisplay:function(){
-}});
-dojo.declare("dojox.widget._CalendarDay",null,{parent:null,constructor:function(){
-this._addView(dojox.widget._CalendarDayView);
-}});
-dojo.declare("dojox.widget._CalendarDayView",[dojox.widget._CalendarView,dijit._Templated],{templateString:dojo.cache("dojox.widget","Calendar/CalendarDay.html","<div class=\"dijitCalendarDayLabels\" style=\"left: 0px;\" dojoAttachPoint=\"dayContainer\">\n\t<div dojoAttachPoint=\"header\">\n\t\t<div dojoAttachPoint=\"monthAndYearHeader\">\n\t\t\t<span dojoAttachPoint=\"monthLabelNode\" class=\"dojoxCalendarMonthLabelNode\"></span>\n\t\t\t<span dojoAttachPoint=\"headerComma\" class=\"dojo [...]
-this.cloneClass(".dijitCalendarDayLabelTemplate",6);
-this.cloneClass(".dijitCalendarDateTemplate",6);
-this.cloneClass(".dijitCalendarWeekTemplate",5);
-var _3b=dojo.date.locale.getNames("days",this.dayWidth,"standAlone",this.getLang());
-var _3c=dojo.cldr.supplemental.getFirstDayOfWeek(this.getLang());
-dojo.query(".dijitCalendarDayLabel",this.domNode).forEach(function(_3d,i){
-this._setText(_3d,_3b[(i+_3c)%7]);
-},this);
-},onDisplay:function(){
-if(!this._addedFx){
-this._addedFx=true;
-this.addFx(".dijitCalendarDateTemplate div",this.domNode);
-}
-},_onDayClick:function(e){
-if(typeof (e.target._date)=="undefined"){
-return;
-}
-var _3e=new Date(this.attr("displayMonth"));
-var p=e.target.parentNode;
-var c="dijitCalendar";
-var d=dojo.hasClass(p,c+"PreviousMonth")?-1:(dojo.hasClass(p,c+"NextMonth")?1:0);
-if(d){
-_3e=dojo.date.add(_3e,"month",d);
-}
-_3e.setDate(e.target._date);
-if(this.isDisabledDate(_3e)){
-dojo.stopEvent(e);
-return;
-}
-this.parent._onDateSelected(_3e);
-},_setValueAttr:function(_3f){
-this._populateDays();
-},_populateDays:function(){
-var _40=new Date(this.attr("displayMonth"));
-_40.setDate(1);
-var _41=_40.getDay();
-var _42=dojo.date.getDaysInMonth(_40);
-var _43=dojo.date.getDaysInMonth(dojo.date.add(_40,"month",-1));
-var _44=new Date();
-var _45=this.attr("value");
-var _46=dojo.cldr.supplemental.getFirstDayOfWeek(this.getLang());
-if(_46>_41){
-_46-=7;
-}
-var _47=dojo.date.compare;
-var _48=".dijitCalendarDateTemplate";
-var _49="dijitCalendarSelectedDate";
-var _4a=this._lastDate;
-var _4b=_4a==null||_4a.getMonth()!=_40.getMonth()||_4a.getFullYear()!=_40.getFullYear();
-this._lastDate=_40;
-if(!_4b){
-dojo.query(_48,this.domNode).removeClass(_49).filter(function(_4c){
-return _4c.className.indexOf("dijitCalendarCurrent")>-1&&_4c._date==_45.getDate();
-}).addClass(_49);
-return;
-}
-dojo.query(_48,this.domNode).forEach(function(_4d,i){
-i+=_46;
-var _4e=new Date(_40);
-var _4f,_50="dijitCalendar",adj=0;
-if(i<_41){
-_4f=_43-_41+i+1;
-adj=-1;
-_50+="Previous";
-}else{
-if(i>=(_41+_42)){
-_4f=i-_41-_42+1;
-adj=1;
-_50+="Next";
-}else{
-_4f=i-_41+1;
-_50+="Current";
-}
-}
-if(adj){
-_4e=dojo.date.add(_4e,"month",adj);
-}
-_4e.setDate(_4f);
-if(!_47(_4e,_44,"date")){
-_50="dijitCalendarCurrentDate "+_50;
-}
-if(!_47(_4e,_45,"date")&&!_47(_4e,_45,"month")&&!_47(_4e,_45,"year")){
-_50=_49+" "+_50;
-}
-if(this.isDisabledDate(_4e,this.getLang())){
-_50=" dijitCalendarDisabledDate "+_50;
-}
-var _51=this.getClassForDate(_4e,this.getLang());
-if(_51){
-_50+=_51+" "+_50;
-}
-_4d.className=_50+"Month dijitCalendarDateTemplate";
-_4d.dijitDateValue=_4e.valueOf();
-var _52=dojo.query(".dijitCalendarDateLabel",_4d)[0];
-this._setText(_52,_4e.getDate());
-_52._date=_52.parentNode._date=_4e.getDate();
-},this);
-var _53=dojo.date.locale.getNames("months","wide","standAlone",this.getLang());
-this._setText(this.monthLabelNode,_53[_40.getMonth()]);
-this._setText(this.yearLabelNode,_40.getFullYear());
-}});
-dojo.declare("dojox.widget._CalendarMonthYear",null,{constructor:function(){
-this._addView(dojox.widget._CalendarMonthYearView);
-}});
-dojo.declare("dojox.widget._CalendarMonthYearView",[dojox.widget._CalendarView,dijit._Templated],{templateString:dojo.cache("dojox.widget","Calendar/CalendarMonthYear.html","<div class=\"dojoxCal-MY-labels\" style=\"left: 0px;\"\t\n\tdojoAttachPoint=\"myContainer\" dojoAttachEvent=\"onclick: onClick\">\n\t\t<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" style=\"margin: auto;\">\n\t\t\t\t<tbody>\n\t\t\t\t\t\t<tr class=\"dojoxCal-MY-G-Template\">\n\t\t\t\t\t\t\t\t<td class=\"dojox [...]
-this.cloneClass(".dojoxCal-MY-G-Template",5,".dojoxCal-MY-btns");
-this.monthContainer=this.yearContainer=this.myContainer;
-var _54="dojoxCalendarYearLabel";
-var _55="dojoxCalendarDecrease";
-var _56="dojoxCalendarIncrease";
-dojo.query("."+_54,this.myContainer).forEach(function(_57,idx){
-var _58=_56;
-switch(idx){
-case 0:
-_58=_55;
-case 1:
-dojo.removeClass(_57,_54);
-dojo.addClass(_57,_58);
-break;
-}
+
+dojo.declare("dojox.widget._CalendarView", dijit._Widget, {
+	// summary:
+	//		Base implementation for all view mixins.
+	//		All calendar views should extend this widget.
+	headerClass: "",
+
+	useHeader: true,
+
+	cloneClass: function(clazz, n, before){
+		// summary:
+		//		Clones all nodes with the class 'clazz' in a widget
+		var template = dojo.query(clazz, this.domNode)[0];
+		var i;
+		if(!before){
+			for(i = 0; i < n; i++){
+				template.parentNode.appendChild(template.cloneNode(true));
+			}
+		}else{
+			var bNode = dojo.query(clazz, this.domNode)[0];
+			for(i = 0; i < n; i++){
+				template.parentNode.insertBefore(template.cloneNode(true), bNode);
+			}
+		}
+	},
+
+	_setText: function(node, text){
+		// summary: 
+		//		Sets the text inside a node
+		if(node.innerHTML != text){
+			dojo.empty(node);
+			node.appendChild(dojo.doc.createTextNode(text));
+		}
+	},
+
+	getHeader: function(){
+		// summary: 
+		//		Returns the header node of a view. If none exists,
+		//		an empty DIV is created and returned.
+		return this.header || (this.header = this.header = dojo.create("span", { "class":this.headerClass }));
+	},
+
+	onValueSelected: function(date){
+		//Stub function called when a date is selected
+	},
+
+	adjustDate: function(date, amount){
+		// summary: 
+		//		Adds or subtracts values from a date.
+		//		The unit, e.g. "day", "month" or "year", is
+		//		specified in the "datePart" property of the
+		//		calendar view mixin.
+		return dojo.date.add(date, this.datePart, amount);
+	},
+
+	onDisplay: function(){
+		// summary: 
+		//		Stub function that can be used to tell a view when it is shown.
+	},
+
+	onBeforeDisplay: function(){
+		// summary: 
+		//		Stub function that can be used to tell a view it is about to be shown.
+	},
+
+	onBeforeUnDisplay: function(){
+		// summary: 
+		//		Stub function that can be used to tell
+		//		a view when it is no longer shown.
+	}
 });
-this._decBtn=dojo.query("."+_55,this.myContainer)[0];
-this._incBtn=dojo.query("."+_56,this.myContainer)[0];
-dojo.query(".dojoxCal-MY-M-Template",this.domNode).filter(function(_59){
-return _59.cellIndex==1;
-}).addClass("dojoxCal-MY-M-last");
-dojo.connect(this,"onBeforeDisplay",dojo.hitch(this,function(){
-this._cachedDate=new Date(this.attr("value").getTime());
-this._populateYears(this._cachedDate.getFullYear());
-this._populateMonths();
-this._updateSelectedMonth();
-this._updateSelectedYear();
-}));
-dojo.connect(this,"_populateYears",dojo.hitch(this,function(){
-this._updateSelectedYear();
-}));
-dojo.connect(this,"_populateMonths",dojo.hitch(this,function(){
-this._updateSelectedMonth();
-}));
-this._cachedDate=this.attr("value");
-this._populateYears();
-this._populateMonths();
-this.addFx(".dojoxCalendarMonthLabel,.dojoxCalendarYearLabel ",this.myContainer);
-},_setValueAttr:function(_5a){
-this._populateYears(_5a.getFullYear());
-},getHeader:function(){
-return null;
-},_getMonthNames:function(_5b){
-this._monthNames=this._monthNames||dojo.date.locale.getNames("months",_5b,"standAlone",this.getLang());
-return this._monthNames;
-},_populateMonths:function(){
-var _5c=this._getMonthNames("abbr");
-dojo.query(".dojoxCalendarMonthLabel",this.monthContainer).forEach(dojo.hitch(this,function(_5d,cnt){
-this._setText(_5d,_5c[cnt]);
-}));
-var _5e=this.attr("constraints");
-if(_5e){
-var _5f=new Date();
-_5f.setFullYear(this._year);
-var min=-1,max=12;
-if(_5e.min){
-var _60=_5e.min.getFullYear();
-if(_60>this._year){
-min=12;
-}else{
-if(_60==this._year){
-min=_5e.min.getMonth();
-}
-}
-}
-if(_5e.max){
-var _61=_5e.max.getFullYear();
-if(_61<this._year){
-max=-1;
-}else{
-if(_61==this._year){
-max=_5e.max.getMonth();
-}
-}
-}
-dojo.query(".dojoxCalendarMonthLabel",this.monthContainer).forEach(dojo.hitch(this,function(_62,cnt){
-dojo[(cnt<min||cnt>max)?"addClass":"removeClass"](_62,"dijitCalendarDisabledDate");
-}));
-}
-var h=this.getHeader();
-if(h){
-this._setText(this.getHeader(),this.attr("value").getFullYear());
-}
-},_populateYears:function(_63){
-var _64=this.attr("constraints");
-var _65=_63||this.attr("value").getFullYear();
-var _66=_65-Math.floor(this.displayedYears/2);
-var min=_64&&_64.min?_64.min.getFullYear():_66-10000;
-_66=Math.max(min,_66);
-this._displayedYear=_65;
-var _67=dojo.query(".dojoxCalendarYearLabel",this.yearContainer);
-var max=_64&&_64.max?_64.max.getFullYear()-_66:_67.length;
-var _68="dijitCalendarDisabledDate";
-_67.forEach(dojo.hitch(this,function(_69,cnt){
-if(cnt<=max){
-this._setText(_69,_66+cnt);
-dojo.removeClass(_69,_68);
-}else{
-dojo.addClass(_69,_68);
-}
-}));
-if(this._incBtn){
-dojo[max<_67.length?"addClass":"removeClass"](this._incBtn,_68);
-}
-if(this._decBtn){
-dojo[min>=_66?"addClass":"removeClass"](this._decBtn,_68);
-}
-var h=this.getHeader();
-if(h){
-this._setText(this.getHeader(),_66+" - "+(_66+11));
-}
-},_updateSelectedYear:function(){
-this._year=String((this._cachedDate||this.attr("value")).getFullYear());
-this._updateSelectedNode(".dojoxCalendarYearLabel",dojo.hitch(this,function(_6a,idx){
-return this._year!==null&&_6a.innerHTML==this._year;
-}));
-},_updateSelectedMonth:function(){
-var _6b=(this._cachedDate||this.attr("value")).getMonth();
-this._month=_6b;
-this._updateSelectedNode(".dojoxCalendarMonthLabel",function(_6c,idx){
-return idx==_6b;
+
+dojo.declare("dojox.widget._CalendarDay", null, {
+	// summary:
+	//		Mixin for the dojox.widget.Calendar which provides
+	//		the standard day-view. A single month is shown at a time.
+	parent: null,
+
+	constructor: function(){
+		this._addView(dojox.widget._CalendarDayView);
+	}
 });
-},_updateSelectedNode:function(_6d,_6e){
-var sel="dijitCalendarSelectedDate";
-dojo.query(_6d,this.domNode).forEach(function(_6f,idx,_70){
-dojo[_6e(_6f,idx,_70)?"addClass":"removeClass"](_6f.parentNode,sel);
+
+dojo.declare("dojox.widget._CalendarDayView", [dojox.widget._CalendarView, dijit._Templated], {
+	// summary: View class for the dojox.widget.Calendar.
+	//		Adds a view showing every day of a single month to the calendar.
+	//		This should not be mixed in directly with dojox.widget._CalendarBase.
+	//		Instead, use dojox.widget._CalendarDay
+
+	// templateString: String
+	//		The template to be used to construct the widget.
+	templateString: dojo.cache("dojox.widget","Calendar/CalendarDay.html"),
+
+	// datePart: String
+	//		Specifies how much to increment the displayed date when the user
+	//		clicks the array button to increment of decrement the view.
+	datePart: "month",
+
+	// dayWidth: String
+	//		Specifies the type of day name to display.	"narrow" causes just one letter to be shown.
+	dayWidth: "narrow",
+
+	postCreate: function(){
+		// summary: 
+		//		Constructs the calendar view.
+		this.cloneClass(".dijitCalendarDayLabelTemplate", 6);
+		this.cloneClass(".dijitCalendarDateTemplate", 6);
+
+		// now make 6 week rows
+		this.cloneClass(".dijitCalendarWeekTemplate", 5);
+
+		// insert localized day names in the header
+		var dayNames = dojo.date.locale.getNames('days', this.dayWidth, 'standAlone', this.getLang());
+		var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.getLang());
+
+		// Set the text of the day labels.
+		dojo.query(".dijitCalendarDayLabel", this.domNode).forEach(function(label, i){
+			this._setText(label, dayNames[(i + dayOffset) % 7]);
+		}, this);
+	},
+
+	onDisplay: function(){
+		if(!this._addedFx){
+		// Add visual effects to the view, if any has been specified.
+			this._addedFx = true;
+			this.addFx(".dijitCalendarDateTemplate div", this.domNode);
+		}
+	},
+
+	_onDayClick: function(e){
+		// summary: 
+		//		Executed when a day value is clicked.
+		
+		// If the user somehow clicked the TR, rather than a 
+		// cell, ignore it.
+		if(typeof(e.target._date) == "undefined"){return;}
+		
+		var date = new Date(this.get("displayMonth"));
+
+		var p = e.target.parentNode;
+		var c = "dijitCalendar";
+		var d = dojo.hasClass(p, c + "PreviousMonth") ? -1 :
+							(dojo.hasClass(p, c + "NextMonth") ? 1 : 0);
+		if(d){date = dojo.date.add(date, "month", d)}
+		date.setDate(e.target._date);
+
+		// If the day is disabled, ignore it
+		if(this.isDisabledDate(date)){
+			dojo.stopEvent(e);
+			return;
+		}
+		this.parent._onDateSelected(date);
+	},
+
+	_setValueAttr: function(value){
+		//Change the day values
+		this._populateDays();
+	},
+
+	_populateDays: function(){
+		// summary: 
+		//		Fills the days of the current month.
+		var currentDate = new Date(this.get("displayMonth"));
+		currentDate.setDate(1);
+		var firstDay = currentDate.getDay();
+		var daysInMonth = dojo.date.getDaysInMonth(currentDate);
+		var daysInPreviousMonth = dojo.date.getDaysInMonth(dojo.date.add(currentDate, "month", -1));
+		var today = new Date();
+		var selected = this.get('value');
+
+		var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.getLang());
+		if(dayOffset > firstDay){ dayOffset -= 7; }
+		
+		var compareDate = dojo.date.compare;
+		var templateCls = ".dijitCalendarDateTemplate";
+		var selectedCls = "dijitCalendarSelectedDate";
+		
+		var oldDate = this._lastDate;
+		var redrawRequired = oldDate == null 
+				|| oldDate.getMonth() != currentDate.getMonth()
+				|| oldDate.getFullYear() != currentDate.getFullYear();
+		this._lastDate = currentDate;
+		
+		// If still showing the same month, it's much faster to not redraw,
+		// and just change the selected date.
+		if(!redrawRequired){
+			dojo.query(templateCls, this.domNode)
+					.removeClass(selectedCls)
+					.filter(function(node){
+						return node.className.indexOf("dijitCalendarCurrent") > -1
+									&& node._date == selected.getDate();
+					})
+					.addClass(selectedCls);
+			return;
+		}
+
+		// Iterate through dates in the calendar and fill in date numbers and style info
+		dojo.query(templateCls, this.domNode).forEach(function(template, i){
+			i += dayOffset;
+			var date = new Date(currentDate);
+			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(!compareDate(date, today, "date")){
+				clazz = "dijitCalendarCurrentDate " + clazz;
+			}
+
+			if(!compareDate(date, selected, "date") 
+					&& !compareDate(date, selected, "month") 
+					&& !compareDate(date, selected, "year") ){
+				clazz = selectedCls + " " + clazz;
+			}
+
+			if(this.isDisabledDate(date, this.getLang())){
+				clazz = " dijitCalendarDisabledDate " + clazz;
+			}
+
+			var clazz2 = this.getClassForDate(date, this.getLang());
+			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());
+			
+			label._date = label.parentNode._date = date.getDate();
+		}, this);
+
+		// Fill in localized month name
+		var monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.getLang());
+		this._setText(this.monthLabelNode, monthNames[currentDate.getMonth()]);
+		this._setText(this.yearLabelNode, currentDate.getFullYear());
+	}
+});
+
+
+dojo.declare("dojox.widget._CalendarMonthYear", null, {
+	// summary:
+	//		Mixin class for adding a view listing all 12 
+	//		months of the year to the dojox.widget._CalendarBase
+
+	constructor: function(){
+		// summary:
+		//		Adds a dojox.widget._CalendarMonthView view to the calendar widget.
+		this._addView(dojox.widget._CalendarMonthYearView);
+	}
 });
-var _71=dojo.query(".dojoxCal-MY-M-Template div",this.myContainer).filter(function(_72){
-return dojo.hasClass(_72.parentNode,sel);
-})[0];
-if(!_71){
-return;
-}
-var _73=dojo.hasClass(_71,"dijitCalendarDisabledDate");
-dojo[_73?"addClass":"removeClass"](this.okBtn,"dijitDisabled");
-},onClick:function(evt){
-var _74;
-var _75=this;
-var sel="dijitCalendarSelectedDate";
-function hc(c){
-return dojo.hasClass(evt.target,c);
-};
-if(hc("dijitCalendarDisabledDate")){
-dojo.stopEvent(evt);
-return false;
-}
-if(hc("dojoxCalendarMonthLabel")){
-_74="dojoxCal-MY-M-Template";
-this._month=evt.target.parentNode.cellIndex+(evt.target.parentNode.parentNode.rowIndex*2);
-this._cachedDate.setMonth(this._month);
-this._updateSelectedMonth();
-}else{
-if(hc("dojoxCalendarYearLabel")){
-_74="dojoxCal-MY-Y-Template";
-this._year=Number(evt.target.innerHTML);
-this._cachedDate.setYear(this._year);
-this._populateMonths();
-this._updateSelectedYear();
-}else{
-if(hc("dojoxCalendarDecrease")){
-this._populateYears(this._displayedYear-10);
-return true;
-}else{
-if(hc("dojoxCalendarIncrease")){
-this._populateYears(this._displayedYear+10);
-return true;
-}else{
-return true;
-}
-}
-}
-}
-dojo.stopEvent(evt);
-return false;
-},onOk:function(evt){
-dojo.stopEvent(evt);
-if(dojo.hasClass(this.okBtn,"dijitDisabled")){
-return false;
-}
-this.onValueSelected(this._cachedDate);
-return false;
-},onCancel:function(evt){
-dojo.stopEvent(evt);
-this.onValueSelected(this.attr("value"));
-return false;
-}});
-dojo.declare("dojox.widget.Calendar2Pane",[dojox.widget._CalendarBase,dojox.widget._CalendarDay,dojox.widget._CalendarMonthYear],{});
-dojo.declare("dojox.widget.Calendar",[dojox.widget._CalendarBase,dojox.widget._CalendarDay,dojox.widget._CalendarMonthYear],{});
-dojo.declare("dojox.widget.DailyCalendar",[dojox.widget._CalendarBase,dojox.widget._CalendarDay],{});
-dojo.declare("dojox.widget.MonthAndYearlyCalendar",[dojox.widget._CalendarBase,dojox.widget._CalendarMonthYear],{});
-}
+
+dojo.declare("dojox.widget._CalendarMonthYearView", [dojox.widget._CalendarView, dijit._Templated], {
+	// summary:
+	//		A Calendar view listing the 12 months of the year
+
+	// templateString: String
+	//		The template to be used to construct the widget.
+	templateString: dojo.cache("dojox.widget","Calendar/CalendarMonthYear.html"),
+
+	// datePart: String
+	//		Specifies how much to increment the displayed date when the user
+	//		clicks the array button to increment of decrement the view.
+	datePart: "year",
+
+	// displayedYears: Number
+	//		The number of years to display at once.
+	displayedYears: 10,
+
+	useHeader: false,
+
+	postCreate: function(){
+		this.cloneClass(".dojoxCal-MY-G-Template", 5, ".dojoxCal-MY-btns");
+		this.monthContainer = this.yearContainer = this.myContainer;
+
+		var yClass = "dojoxCalendarYearLabel";
+		var dClass = "dojoxCalendarDecrease";
+		var iClass = "dojoxCalendarIncrease";
+
+		dojo.query("." + yClass, this.myContainer).forEach(function(node, idx){
+			var clazz = iClass;
+			switch(idx){
+				case 0:
+					clazz = dClass;
+				case 1:
+					dojo.removeClass(node, yClass);
+					dojo.addClass(node, clazz);
+					break;
+			}
+		});
+		// Get the year increment and decrement buttons.
+		this._decBtn = dojo.query('.' + dClass, this.myContainer)[0];
+		this._incBtn = dojo.query('.' + iClass, this.myContainer)[0];
+
+		dojo.query(".dojoxCal-MY-M-Template", this.domNode)
+			.filter(function(item){
+				return item.cellIndex == 1;
+			})
+			.addClass("dojoxCal-MY-M-last");
+
+		dojo.connect(this, "onBeforeDisplay", dojo.hitch(this, function(){
+			this._cachedDate = new Date(this.get("value").getTime());
+			this._populateYears(this._cachedDate.getFullYear());
+			this._populateMonths();
+			this._updateSelectedMonth();
+			this._updateSelectedYear();
+		}));
+
+		dojo.connect(this, "_populateYears", dojo.hitch(this, function(){
+			this._updateSelectedYear();
+		}));
+		dojo.connect(this, "_populateMonths", dojo.hitch(this, function(){
+			this._updateSelectedMonth();
+		}));
+
+		this._cachedDate = this.get("value");
+
+		this._populateYears();
+		this._populateMonths();
+
+		// Add visual effects to the view, if any have been mixed in
+		this.addFx(".dojoxCalendarMonthLabel,.dojoxCalendarYearLabel ", this.myContainer);
+	},
+
+	_setValueAttr: function(value){
+		this._populateYears(value.getFullYear());
+	},
+
+	getHeader: function(){
+		return null;
+	},
+
+	_getMonthNames: function(format){
+		// summary: 
+		//		Returns localized month names
+		this._monthNames	= this._monthNames || dojo.date.locale.getNames('months', format, 'standAlone', this.getLang());
+		return this._monthNames;
+	},
+
+	_populateMonths: function(){
+		// summary:
+		//		Populate the month names using the localized values.
+		var monthNames = this._getMonthNames('abbr');
+		dojo.query(".dojoxCalendarMonthLabel", this.monthContainer).forEach(dojo.hitch(this, function(node, cnt){
+			this._setText(node, monthNames[cnt]);
+		}));
+		var constraints = this.get('constraints');
+
+		if(constraints){
+			var date = new Date();
+			date.setFullYear(this._year);
+			var min = -1, max = 12;
+			if(constraints.min){
+				var minY = constraints.min.getFullYear();
+				if(minY > this._year){
+					min = 12;
+				}else if(minY == this._year){
+					min = constraints.min.getMonth();
+				}
+			}
+			if(constraints.max){
+				var maxY = constraints.max.getFullYear();
+				if(maxY < this._year){
+					max = -1;
+				}else if(maxY == this._year){
+					max = constraints.max.getMonth();
+				}
+			}
+			
+			dojo.query(".dojoxCalendarMonthLabel", this.monthContainer)
+				.forEach(dojo.hitch(this, function(node, cnt){
+					dojo[(cnt < min || cnt > max) ? "addClass" : "removeClass"]
+						(node, 'dijitCalendarDisabledDate');
+			}));
+		}
+
+		var h = this.getHeader();
+		if(h){
+			this._setText(this.getHeader(), this.get("value").getFullYear());
+		}
+	},
+
+	_populateYears: function(year){
+		// summary: 
+		//		Fills the list of years with a range of 12 numbers, with the current year
+		//		being the 6th number.
+		var constraints = this.get('constraints');
+		var dispYear = year || this.get("value").getFullYear();
+		var firstYear = dispYear - Math.floor(this.displayedYears/2);
+		var min = constraints && constraints.min ? constraints.min.getFullYear() : firstYear -10000;
+
+		firstYear = Math.max(min, firstYear);
+
+		// summary: Writes the years to display to the view
+		this._displayedYear = dispYear;
+
+		var yearLabels = dojo.query(".dojoxCalendarYearLabel", this.yearContainer);
+
+		var max = constraints && constraints.max ? constraints.max.getFullYear() - firstYear :	yearLabels.length;
+		var disabledClass = 'dijitCalendarDisabledDate';
+
+		yearLabels.forEach(dojo.hitch(this, function(node, cnt){
+			if(cnt <= max){
+				this._setText(node, firstYear + cnt);
+				dojo.removeClass(node, disabledClass);
+			}else{
+				dojo.addClass(node, disabledClass);
+			}
+		}));
+
+		if(this._incBtn){
+			dojo[max < yearLabels.length ? "addClass" : "removeClass"](this._incBtn, disabledClass);
+		}
+		if(this._decBtn){
+			dojo[min >= firstYear ? "addClass" : "removeClass"](this._decBtn, disabledClass);
+		}
+
+		var h = this.getHeader();
+		if(h){
+			this._setText(this.getHeader(), firstYear + " - " + (firstYear + 11));
+		}
+	},
+
+	_updateSelectedYear: function(){
+		this._year = String((this._cachedDate || this.get("value")).getFullYear());
+		this._updateSelectedNode(".dojoxCalendarYearLabel", dojo.hitch(this, function(node, idx){
+			return this._year !== null && node.innerHTML == this._year;
+		}));
+	},
+
+	_updateSelectedMonth: function(){
+		var month = (this._cachedDate || this.get("value")).getMonth();
+		this._month = month;
+		this._updateSelectedNode(".dojoxCalendarMonthLabel", function(node, idx){
+			return idx == month;
+		});
+	},
+
+	_updateSelectedNode: function(query, filter){
+		var sel = "dijitCalendarSelectedDate";
+		dojo.query(query, this.domNode)
+			.forEach(function(node, idx, array){
+				dojo[filter(node, idx, array) ? "addClass" : "removeClass"](node.parentNode, sel);
+		});
+		var selMonth = dojo.query('.dojoxCal-MY-M-Template div', this.myContainer)
+			.filter(function(node){
+				return dojo.hasClass(node.parentNode, sel);
+		})[0];
+		if(!selMonth){return;}
+		var disabled = dojo.hasClass(selMonth, 'dijitCalendarDisabledDate');
+		
+		dojo[disabled ? 'addClass' : 'removeClass'](this.okBtn, "dijitDisabled");
+	},
+	
+	onClick: function(evt){
+		// summary: 
+		//		Handles clicks on month names
+		var clazz;
+		var _this = this;
+		var sel = "dijitCalendarSelectedDate";
+		function hc(c){
+			return dojo.hasClass(evt.target, c);
+		}
+
+		if(hc('dijitCalendarDisabledDate')){
+			dojo.stopEvent(evt);
+			return false;
+		}
+
+		if(hc("dojoxCalendarMonthLabel")){
+			clazz = "dojoxCal-MY-M-Template";
+			this._month = evt.target.parentNode.cellIndex + (evt.target.parentNode.parentNode.rowIndex * 2);
+			this._cachedDate.setMonth(this._month);
+			this._updateSelectedMonth();
+		}else if(hc( "dojoxCalendarYearLabel")){
+			clazz = "dojoxCal-MY-Y-Template";
+			this._year = Number(evt.target.innerHTML);
+			this._cachedDate.setYear(this._year);
+			this._populateMonths();
+			this._updateSelectedYear();
+		}else if(hc("dojoxCalendarDecrease")){
+			this._populateYears(this._displayedYear - 10);
+			return true;
+		}else if(hc("dojoxCalendarIncrease")){
+			this._populateYears(this._displayedYear + 10);
+			return true;
+		}else{
+			return true;
+		}
+		dojo.stopEvent(evt);
+		return false;
+	},
+
+	onOk: function(evt){
+		dojo.stopEvent(evt);
+		if(dojo.hasClass(this.okBtn, "dijitDisabled")){
+			return false;
+		}
+		this.onValueSelected(this._cachedDate);
+		return false;
+	},
+
+	onCancel: function(evt){
+		dojo.stopEvent(evt);
+		this.onValueSelected(this.get("value"));
+		return false;
+	}
+});
+
+dojo.declare("dojox.widget.Calendar2Pane",
+	[dojox.widget._CalendarBase,
+	 dojox.widget._CalendarDay,
+	 dojox.widget._CalendarMonthYear], {
+	 	// summary: A Calendar withtwo panes, the second one
+		//		 containing both month and year
+	 }
+);
+
+dojo.declare("dojox.widget.Calendar",
+	[dojox.widget._CalendarBase,
+	 dojox.widget._CalendarDay,
+	 dojox.widget._CalendarMonthYear], {
+	 	// summary: The standard Calendar. It includes day and month/year views.
+		//	No visual effects are included.
+	 }
+);
+
+dojo.declare("dojox.widget.DailyCalendar",
+	[dojox.widget._CalendarBase,
+	 dojox.widget._CalendarDay], {
+	 	// summary: A calendar withonly a daily view.
+	 }
+);
+
+dojo.declare("dojox.widget.MonthAndYearlyCalendar",
+	[dojox.widget._CalendarBase,
+	 dojox.widget._CalendarMonthYear], {
+	 	// summary: A calendar withonly a daily view.
+	 }
+);
diff --git a/dojox/widget/Calendar/Calendar.css b/dojox/widget/Calendar/Calendar.css
index f31e1bc..5a49e02 100644
--- a/dojox/widget/Calendar/Calendar.css
+++ b/dojox/widget/Calendar/Calendar.css
@@ -10,6 +10,7 @@
 	width: 180px;
 	overflow: hidden;
 }
+
 .dojoxCalendarBody {
 	height: 138px;
 	overflow: hidden;
@@ -20,6 +21,7 @@
 .dojoxCalendar .no-header .dojoxCalendarBody {
 	height: 162px;
 }
+
 .dojoxCalendar .dijitCalendarDayLabels, .dojoxCalendarMonthLabels, .dojoxCalendarYearLabels, .dojoxCal-MY-labels {
 	width: 180px;
 	height: 138px;
@@ -29,26 +31,33 @@
 	margin: auto;
 	text-align: center;
 }
+
 .dojoxCalendar .dojoxCalendarBody > div {
 	width: 180px;
 }
+
 .dojoxCalendar .dijitCalendarDateTemplate {
 	padding: 0 1px 0 0 !important;
 }
+
 .nihilo .dojoxCalendar .dijitCalendarDateTemplate,
 .soria .dojoxCalendar .dijitCalendarDateTemplate {
 	border: 0px none !important; 
 }
+
 .soria tr.dojoxCal-MY-btns {
 	background:   url(../../../dijit/themes/soria/images/tabBottomHoverC.gif) repeat-x scroll 0px -21px;
 }
+
 .dojoxCalendar .noPointer, .dojoxCalendar .noPointer * {
 	cursor: auto;
 }
+
 .dojoxCalendarContainer table {
 	font-size: 11px;
 	border-bottom: 4px solid white;
 }
+
 .dojoxCalendarHeader {
 	height: 20px;
 	width: 172px;
@@ -57,22 +66,29 @@
 .dojoxCalendar .no-header .dojoxCalendarHeader {
 	display: none;
 }
+
 .soria .dojoxCalendarHeader {
 	background: #BED7F0 url(../../../dijit/themes/soria/images/titleBar.png) repeat-x scroll center top;
 }
+
+
 .dojoxCalendarDecrease, .dojoxCalendarIncrease {
 	height: 15px;
 	width: 15px;
 	cursor: pointer;
 }
+
 .dojoxCalendarDecrease {
 	background: transparent url(../../../dijit/themes/nihilo/images/spriteRoundedIconsSmall.png) no-repeat scroll left top;
 	float: left;
 }
+
 .dojoxCalendarIncrease {
 	background: transparent url(../../../dijit/themes/nihilo/images/spriteRoundedIconsSmall.png) no-repeat scroll -30px top;
 	float: right;
 }
+
+
 .dojoxCalendarMonthLabel {
 	cursor: pointer;
 	height: 35px;
@@ -81,6 +97,7 @@
 	text-align: center;
 	padding-top: 10px;
 }
+
 .dojoxCalendarYearLabel {
 	cursor: pointer;
 	height: 35px;
@@ -89,16 +106,19 @@
 	text-align: center;
 	padding-top: 10px;
 }
+
 .dojoxCalendarTitle {
 	cursor: pointer;
 	font-weight: bold;
 }
+
 .dojoxCalendar .navToPanel .dojoxCalendarDayYearLabel,
 .dojoxCalendar .navToPanel .dojoxCalendarYearHeader,
 .dojoxCalendar .navToPanel .dojoxCalendarMonthHeader  {
 	padding-right: 15px;
 	background: url(../../../dijit/themes/tundra/images/comboArrowDown.gif) right no-repeat;
 }
+
 .dojoxCalendar .dijitCalendarDateLabel {
 	height: 17px;
 	width: 17px;
@@ -106,6 +126,7 @@
 	text-align: center;
 	border: 1px solid white;
 }
+
 .dojoxCalendar .dijitCalendarDayLabel {
 	cursor: pointer;
 	height: 17px;
@@ -113,32 +134,40 @@
 	padding: 0pt 2px;
 	text-align: center;
 }
+
+
 .dojoxCalendar .dojoxCalendarContainer {
 	background-color: white;
 	border: 1px solid #656565;
 	color: black;
 }
+
 .dojoxCalendar .dijitCalendarDisabledDate {
 	text-decoration:line-through !important;
 	cursor:default !important;
 }
+
 .dojoxCalendar .dojoxCalendarFooter {
 	border-top: 1px solid #F4F4F4;
 	height: 15px;
 	padding-top: 4px;
 	cursor: pointer;
 }
+
 .soria .dojoxCalendar .dojoxCalendarFooter {
 	border-top: 0px none;
 	padding-top: 5px;
 	background: white url(../../../dijit/themes/soria/images/titleBar.png) repeat-x scroll center top
 }
+
 .dojoxCalendar .dojoxCalendarMonthLabel {
 	border: 1px solid white;
 }
+
 .dojoxCalendar .dojoxCalendarYearLabel {
 	border: 1px solid white;
 }
+
 .dojoxCalendar .dijitCalendarNextMonth .dijitCalendarDateLabel,
 .dojoxCalendar .dijitCalendarPreviousMonth .dijitCalendarDateLabel  {
 	border: 0px;
@@ -146,9 +175,11 @@
 	padding-left: 0px;
 	padding-right: 0px;
 }
+
 .dojoxCalendar .dijitCalendarNextMonth, .dojoxCalendar .dijitCalendarPreviousMonth {
   background-color: #E4E4E4;
 }
+
 .dojoxCalendar .dijitCalendarNextMonth .dojoxCalendarYearLabel,
 .dojoxCalendar .dijitCalendarPreviousMonth .dojoxCalendarYearLabel {
 	background-color: white;
@@ -158,23 +189,26 @@
 .dojoxCalendar .dijitCalendarSelectedDate,
 .tundra .dojoxCalendar .dijitCalendarSelectedDate,
 .nihilo .dojoxCalendar .dijitCalendarSelectedDate {
-	
+	/* cell for the selected date */
 	background-color:#ffe284 !important;
 	color:black !important;
 	border:#f5b93c solid 1px !important;
 }
+
+
 .soria .dojoxCalendar td.dijitCalendarSelectedDate {
 	background-color: #B9CBF1 !important;
 	color: black !important;
 	border: 1px solid #4B5AAA !important;
 }
+
 .soria .dojoxCalendar .dijitCalendarSelectedDate div {
-	
+	/* cell for the selected date */
 	background-color: #B9CBF1 !important;
 	border: none  !important;
 }
 .dojoxCalendar .dijitCalendarSelectedDate div {
-	
+	/* cell for the selected date */
 	background-color: #FFE284 !important;
 	border: none  !important;
 }
@@ -182,12 +216,15 @@ div.dojoxCalendar tr.dojoxCal-MY-G-Template td.dijitCalendarSelectedDate {
 	background-color: transparent;
 	width: 43px;
 }
+
 .dojoxCalendar tr.dojoxCal-MY-G-Template td {
 	width: 45px;
 }
+
 .dojoxCalendar .dijitCalendarSelectedDate div.dijitCalendarDateLabel {
 	padding: 1px 1px 0px 3px;
 }
+
 .dojoxCalendar .monthOnly .dijitCalendarDayLabels,
 .dojoxCalendar .yearOnly .dijitCalendarDayLabels,
 .dojoxCalendar .monthOnly .dojoxCalendarComma,
@@ -200,25 +237,30 @@ div.dojoxCalendar tr.dojoxCal-MY-G-Template td.dijitCalendarSelectedDate {
 .dojoxCalendar .yearOnly .dojoxCalendarMonthLabelNode {
 	display: none;
 }
+
 .dojoxCal-MY-labels .dojoxCalendarMonthLabel,
 .dojoxCal-MY-labels .dojoxCalendarYearLabel {
 	height: 13px;
 	padding-top: 4px;
 	padding-bottom: 3px;
 }
+
 .dojoxCal-MY-labels td.dojoxCal-MY-btns {
 	padding-top: 2px;
 	border-top: 1px solid grey;
 	text-align: center;
 }
+
 .dojoxCal-MY-labels {
 	background-color: white;
 }
+
 .dojoxCal-MY-labels .dojoxCalendarIncrease,
 .dojoxCal-MY-labels .dojoxCalendarDecrease {
 	float: none;
 	margin-left: 14px;
 }
+
 .dojoxCal-MY-btns button {
 	font-size: 8pt;
 }
@@ -252,6 +294,7 @@ div.dojoxCalendar tr.dojoxCal-MY-G-Template td.dijitCalendarSelectedDate {
 .dojoxCal-MY-labels .dojoxCal-MY-G-Template div.dojoxCalendarYearLabel {
 	width: 42px;
 }
+
 .dojoxCalendar .cancel-btn {
 	margin-left: 11px;
 }
diff --git a/dojox/widget/CalendarFx.js b/dojox/widget/CalendarFx.js
index 3814ba7..c3b6278 100644
--- a/dojox/widget/CalendarFx.js
+++ b/dojox/widget/CalendarFx.js
@@ -1,18 +1,26 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.CalendarFx"]){
-dojo._hasResource["dojox.widget.CalendarFx"]=true;
 dojo.provide("dojox.widget.CalendarFx");
 dojo.require("dojox.widget.FisheyeLite");
-dojo.declare("dojox.widget._FisheyeFX",null,{addFx:function(_1,_2){
-dojo.query(_1,_2).forEach(function(_3){
-new dojox.widget.FisheyeLite({properties:{fontSize:1.1}},_3);
+
+dojo.declare("dojox.widget._FisheyeFX",null, {
+	// summary
+	//   A mixin to add a FisheyeLite effect to the calendar
+	addFx: function(query, fromNode) {
+		//Use the query and base node passed from the calendar view mixin
+		//to select the nodes to attach the event to.
+		dojo.query(query, fromNode).forEach(function(node){
+			new dojox.widget.FisheyeLite({
+				properties: {
+					fontSize: 1.1
+				}
+			}, node);
+		});
+	}
 });
-}});
-dojo.declare("dojox.widget.CalendarFisheye",[dojox.widget.Calendar,dojox.widget._FisheyeFX],{});
-}
+
+dojo.declare("dojox.widget.CalendarFisheye",
+	[dojox.widget.Calendar,
+	 dojox.widget._FisheyeFX], {
+	 	// summary: The standard Calendar. It includes day, month and year views.
+		//  FisheyeLite effects are included.
+	 }
+);
diff --git a/dojox/widget/CalendarViews.js b/dojox/widget/CalendarViews.js
index bdc0344..deefa87 100644
--- a/dojox/widget/CalendarViews.js
+++ b/dojox/widget/CalendarViews.js
@@ -1,58 +1,134 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.CalendarViews"]){
-dojo._hasResource["dojox.widget.CalendarViews"]=true;
 dojo.provide("dojox.widget.CalendarViews");
 dojo.experimental("dojox.widget.CalendarViews");
+
 dojo.require("dojox.widget.Calendar");
-dojo.declare("dojox.widget._CalendarMonth",null,{constructor:function(){
-this._addView(dojox.widget._CalendarMonthView);
-}});
-dojo.declare("dojox.widget._CalendarMonthView",[dojox.widget._CalendarView,dijit._Templated],{templateString:dojo.cache("dojox.widget","Calendar/CalendarMonth.html","<div class=\"dojoxCalendarMonthLabels\" style=\"left: 0px;\"  \n\tdojoAttachPoint=\"monthContainer\" dojoAttachEvent=\"onclick: onClick\">\n    <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" style=\"margin: auto;\">\n        <tbody>\n            <tr class=\"dojoxCalendarMonthGroupTemplate\">\n                <td cla [...]
-this.cloneClass(".dojoxCalendarMonthTemplate",3);
-this.cloneClass(".dojoxCalendarMonthGroupTemplate",2);
-this._populateMonths();
-this.addFx(".dojoxCalendarMonthLabel",this.domNode);
-},_setValueAttr:function(_1){
-this.header.innerHTML=_1.getFullYear();
-},_getMonthNames:dojox.widget._CalendarMonthYearView.prototype._getMonthNames,_populateMonths:dojox.widget._CalendarMonthYearView.prototype._populateMonths,onClick:function(_2){
-if(!dojo.hasClass(_2.target,"dojoxCalendarMonthLabel")){
-dojo.stopEvent(_2);
-return;
-}
-var _3=_2.target.parentNode.cellIndex+(_2.target.parentNode.parentNode.rowIndex*4);
-var _4=this.attr("value");
-_4.setMonth(_3);
-this.onValueSelected(_4,_3);
-}});
-dojo.declare("dojox.widget._CalendarYear",null,{parent:null,constructor:function(){
-this._addView(dojox.widget._CalendarYearView);
-}});
-dojo.declare("dojox.widget._CalendarYearView",[dojox.widget._CalendarView,dijit._Templated],{templateString:dojo.cache("dojox.widget","Calendar/CalendarYear.html","<div class=\"dojoxCalendarYearLabels\" style=\"left: 0px;\" dojoAttachPoint=\"yearContainer\">\n    <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" style=\"margin: auto;\" dojoAttachEvent=\"onclick: onClick\">\n        <tbody>\n            <tr class=\"dojoxCalendarYearGroupTemplate\">\n                <td class=\"dojox [...]
-this.cloneClass(".dojoxCalendarYearTemplate",3);
-this.cloneClass(".dojoxCalendarYearGroupTemplate",2);
-this._populateYears();
-this.addFx(".dojoxCalendarYearLabel",this.domNode);
-},_setValueAttr:function(_5){
-this._populateYears(_5.getFullYear());
-},_populateYears:dojox.widget._CalendarMonthYearView.prototype._populateYears,adjustDate:function(_6,_7){
-return dojo.date.add(_6,"year",_7*12);
-},onClick:function(_8){
-if(!dojo.hasClass(_8.target,"dojoxCalendarYearLabel")){
-dojo.stopEvent(_8);
-return;
-}
-var _9=Number(_8.target.innerHTML);
-var _a=this.attr("value");
-_a.setYear(_9);
-this.onValueSelected(_a,_9);
-}});
-dojo.declare("dojox.widget.Calendar3Pane",[dojox.widget._CalendarBase,dojox.widget._CalendarDay,dojox.widget._CalendarMonth,dojox.widget._CalendarYear],{});
-dojo.declare("dojox.widget.MonthlyCalendar",[dojox.widget._CalendarBase,dojox.widget._CalendarMonth],{});
-dojo.declare("dojox.widget.YearlyCalendar",[dojox.widget._CalendarBase,dojox.widget._CalendarYear],{});
-}
+
+
+dojo.declare("dojox.widget._CalendarMonth", null, {
+	// summary: Mixin class for adding a view listing all 12 months of the year to the
+	//	 dojox.widget._CalendarBase
+
+
+	constructor: function(){
+		// summary: Adds a dojox.widget._CalendarMonthView view to the calendar widget.
+		this._addView(dojox.widget._CalendarMonthView);
+	}
+});
+
+dojo.declare("dojox.widget._CalendarMonthView", [dojox.widget._CalendarView, dijit._Templated], {
+	// summary: A Calendar view listing the 12 months of the year
+
+	// templateString: String
+	//	The template to be used to construct the widget.
+	templateString: dojo.cache("dojox.widget","Calendar/CalendarMonth.html"),
+
+	// datePart: String
+	//	Specifies how much to increment the displayed date when the user
+	//	clicks the array button to increment of decrement the view.
+	datePart: "year",
+
+	// headerClass: String
+	//	Specifies the CSS class to apply to the header node for this view.
+	headerClass: "dojoxCalendarMonthHeader",
+
+	postCreate: function(){
+		// summary: Constructs the view
+		this.cloneClass(".dojoxCalendarMonthTemplate", 3);
+		this.cloneClass(".dojoxCalendarMonthGroupTemplate", 2);
+		this._populateMonths();
+
+		// Add visual effects to the view, if any have been mixed in
+		this.addFx(".dojoxCalendarMonthLabel", this.domNode);
+	},
+
+	_setValueAttr: function(value){
+		this.header.innerHTML = value.getFullYear();
+	},
+
+	_getMonthNames: dojox.widget._CalendarMonthYearView.prototype._getMonthNames,
+
+	_populateMonths: dojox.widget._CalendarMonthYearView.prototype._populateMonths,
+
+	onClick: function(evt){
+		// summary: Handles clicks on month names
+		if(!dojo.hasClass(evt.target, "dojoxCalendarMonthLabel")){dojo.stopEvent(evt); return;}
+		var month = evt.target.parentNode.cellIndex + (evt.target.parentNode.parentNode.rowIndex * 4);
+		var date = this.get("value");
+		date.setMonth(month);
+		this.onValueSelected(date, month);
+	}
+});
+
+dojo.declare("dojox.widget._CalendarYear", null, {
+	// summary: Mixin class for adding a view listing 12 years to the
+	//	 dojox.widget._CalendarBase
+	parent: null,
+
+	constructor: function(){
+		// summary: Adds a dojox.widget._CalendarYearView view to the
+		//	dojo.widget._CalendarBase widget.
+		this._addView(dojox.widget._CalendarYearView);
+	}
+});
+
+dojo.declare("dojox.widget._CalendarYearView", [dojox.widget._CalendarView, dijit._Templated], {
+	// summary: A Calendar view listing 12 years
+
+	// templateString: String
+	//		The template to be used to construct the widget.
+	templateString: dojo.cache("dojox.widget","Calendar/CalendarYear.html"),
+
+	displayedYears: 6,
+
+	postCreate: function(){
+		// summary: Constructs the view
+		this.cloneClass(".dojoxCalendarYearTemplate", 3);
+		this.cloneClass(".dojoxCalendarYearGroupTemplate", 2);
+		this._populateYears();
+		this.addFx(".dojoxCalendarYearLabel", this.domNode);
+	},
+
+	_setValueAttr: function(value){
+		this._populateYears(value.getFullYear());
+	},
+
+	_populateYears: dojox.widget._CalendarMonthYearView.prototype._populateYears,
+
+	adjustDate: function(date, amount){
+		// summary: Adjusts the value of a date. It moves it by 12 years each time.
+		return dojo.date.add(date, "year", amount * 12);
+	},
+
+	onClick: function(evt){
+		// summary: Handles clicks on year values.
+		if(!dojo.hasClass(evt.target, "dojoxCalendarYearLabel")){dojo.stopEvent(evt); return;}
+		var year = Number(evt.target.innerHTML);
+		var date = this.get("value");
+		date.setYear(year);
+		this.onValueSelected(date, year);
+	}
+});
+
+
+dojo.declare("dojox.widget.Calendar3Pane",
+	[dojox.widget._CalendarBase,
+	 dojox.widget._CalendarDay,
+	 dojox.widget._CalendarMonth,
+	 dojox.widget._CalendarYear], {
+	 	// summary: The Calendar includes day, month and year views.
+		//	No visual effects are included.
+	 }
+);
+
+dojo.declare("dojox.widget.MonthlyCalendar",
+	[dojox.widget._CalendarBase,
+	 dojox.widget._CalendarMonth], {
+	 	// summary: A calendar with only a month view.
+	 }
+);
+dojo.declare("dojox.widget.YearlyCalendar",
+	[dojox.widget._CalendarBase,
+	 dojox.widget._CalendarYear], {
+	 	// summary: A calendar with only a year view.
+	 }
+);
diff --git a/dojox/widget/ColorPicker.js b/dojox/widget/ColorPicker.js
index fafca74..076c860 100644
--- a/dojox/widget/ColorPicker.js
+++ b/dojox/widget/ColorPicker.js
@@ -1,175 +1,571 @@
-/*
-	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
-*/
+dojo.provide("dojox.widget.ColorPicker");
+dojo.experimental("dojox.widget.ColorPicker"); // level: beta //TODO: which?
 
+dojo.requireLocalization("dojox.widget","ColorPicker");
+dojo.requireLocalization("dojo.cldr","number");
 
-if(!dojo._hasResource["dojox.widget.ColorPicker"]){
-dojo._hasResource["dojox.widget.ColorPicker"]=true;
-dojo.provide("dojox.widget.ColorPicker");
-dojo.experimental("dojox.widget.ColorPicker");
-dojo.requireLocalization("dojox.widget","ColorPicker",null,"ROOT,cs,de,es,fr,hu,it,ja,ko,pl,pt,ru,th,zh,zh-tw");
-dojo.requireLocalization("dojo.cldr","number",null,"ROOT,ar,ca,cs,da,de,de-de,el,en,en-au,en-gb,en-us,es,es-es,fi,fr,he,hu,it,ja,ja-jp,ko,ko-kr,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-cn,zh-tw");
 dojo.require("dijit.form._FormWidget");
-dojo.require("dojo.dnd.move");
-dojo.require("dojo.fx");
+dojo.require("dojo.dnd.move"); 
+dojo.require("dojo.fx"); 
 dojo.require("dojox.color");
 dojo.require("dojo.i18n");
+
 (function(d){
-var _1=function(_2){
-return _2;
-};
-dojo.declare("dojox.widget.ColorPicker",dijit.form._FormWidget,{showRgb:true,showHsv:true,showHex:true,webSafe:true,animatePoint:true,slideDuration:250,liveUpdate:false,PICKER_HUE_H:150,PICKER_SAT_VAL_H:150,PICKER_SAT_VAL_W:150,value:"#ffffff",_underlay:d.moduleUrl("dojox.widget","ColorPicker/images/underlay.png"),templateString:dojo.cache("dojox.widget","ColorPicker/ColorPicker.html","<div class=\"dojoxColorPicker\" dojoAttachEvent=\"onkeypress: _handleKey\">\n\t<div class=\"dojoxColorP [...]
-dojo.mixin(this,dojo.i18n.getLocalization("dojox.widget","ColorPicker"));
-dojo.mixin(this,dojo.i18n.getLocalization("dojo.cldr","number"));
-this.inherited(arguments);
-},postCreate:function(){
-this.inherited(arguments);
-if(d.isIE<7){
-this.colorUnderlay.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this._underlay+"', sizingMethod='scale')";
-this.colorUnderlay.src=this._blankGif.toString();
-}
-if(!this.showRgb){
-this.rgbNode.style.display="none";
-}
-if(!this.showHsv){
-this.hsvNode.style.display="none";
-}
-if(!this.showHex){
-this.hexNode.style.display="none";
-}
-if(!this.webSafe){
-this.safePreviewNode.style.visibility="hidden";
-}
-this._offset=0;
-var _3=d.marginBox(this.cursorNode);
-var _4=d.marginBox(this.hueCursorNode);
-this._shift={hue:{x:Math.round(_4.w/2)-1,y:Math.round(_4.h/2)-1},picker:{x:Math.floor(_3.w/2),y:Math.floor(_3.h/2)}};
-this.PICKER_HUE_H=d.coords(this.hueNode).h;
-var cu=d.coords(this.colorUnderlay);
-this.PICKER_SAT_VAL_H=cu.h;
-this.PICKER_SAT_VAL_W=cu.w;
-var ox=this._shift.picker.x;
-var oy=this._shift.picker.y;
-this._mover=new d.dnd.move.boxConstrainedMoveable(this.cursorNode,{box:{t:0-oy,l:0-ox,w:this.PICKER_SAT_VAL_W,h:this.PICKER_SAT_VAL_H}});
-this._hueMover=new d.dnd.move.boxConstrainedMoveable(this.hueCursorNode,{box:{t:0-this._shift.hue.y,l:0,w:0,h:this.PICKER_HUE_H}});
-d.subscribe("/dnd/move/stop",d.hitch(this,"_clearTimer"));
-d.subscribe("/dnd/move/start",d.hitch(this,"_setTimer"));
-},startup:function(){
-this._started=true;
-this.attr("value",this.value);
-},_setValueAttr:function(_5){
-if(!this._started){
-return;
-}
-this.setColor(_5,true);
-},setColor:function(_6,_7){
-var _8=dojox.color.fromString(_6);
-this._updatePickerLocations(_8);
-this._updateColorInputs(_8);
-this._updateValue(_8,_7);
-},_setTimer:function(_9){
-dijit.focus(_9.node);
-d.setSelectable(this.domNode,false);
-this._timer=setInterval(d.hitch(this,"_updateColor"),45);
-},_clearTimer:function(_a){
-clearInterval(this._timer);
-this._timer=null;
-this.onChange(this.value);
-d.setSelectable(this.domNode,true);
-},_setHue:function(h){
-d.style(this.colorUnderlay,"backgroundColor",dojox.color.fromHsv(h,100,100).toHex());
-},_updateColor:function(){
-var _b=d.style(this.hueCursorNode,"top")+this._shift.hue.y,_c=d.style(this.cursorNode,"top")+this._shift.picker.y,_d=d.style(this.cursorNode,"left")+this._shift.picker.x,h=Math.round(360-(_b/this.PICKER_HUE_H*360)),_e=dojox.color.fromHsv(h,_d/this.PICKER_SAT_VAL_W*100,100-(_c/this.PICKER_SAT_VAL_H*100));
-this._updateColorInputs(_e);
-this._updateValue(_e,true);
-if(h!=this._hue){
-this._setHue(h);
-}
-},_colorInputChange:function(e){
-var _f,_10=false;
-switch(e.target){
-case this.hexCode:
-_f=dojox.color.fromString(e.target.value);
-_10=true;
-break;
-case this.Rval:
-case this.Gval:
-case this.Bval:
-_f=dojox.color.fromArray([this.Rval.value,this.Gval.value,this.Bval.value]);
-_10=true;
-break;
-case this.Hval:
-case this.Sval:
-case this.Vval:
-_f=dojox.color.fromHsv(this.Hval.value,this.Sval.value,this.Vval.value);
-_10=true;
-break;
-}
-if(_10){
-this._updatePickerLocations(_f);
-this._updateColorInputs(_f);
-this._updateValue(_f,true);
-}
-},_updateValue:function(col,_11){
-var hex=col.toHex();
-this.value=this.valueNode.value=hex;
-if(_11&&(!this._timer||this.liveUpdate)){
-this.onChange(hex);
-}
-},_updatePickerLocations:function(col){
-var hsv=col.toHsv(),_12=Math.round(this.PICKER_HUE_H-hsv.h/360*this.PICKER_HUE_H-this._shift.hue.y),_13=Math.round(hsv.s/100*this.PICKER_SAT_VAL_W-this._shift.picker.x),_14=Math.round(this.PICKER_SAT_VAL_H-hsv.v/100*this.PICKER_SAT_VAL_H-this._shift.picker.y);
-if(this.animatePoint){
-d.fx.slideTo({node:this.hueCursorNode,duration:this.slideDuration,top:_12,left:0}).play();
-d.fx.slideTo({node:this.cursorNode,duration:this.slideDuration,top:_14,left:_13}).play();
-}else{
-d.style(this.hueCursorNode,"top",_12+"px");
-d.style(this.cursorNode,{left:_13+"px",top:_14+"px"});
-}
-if(hsv.h!=this._hue){
-this._setHue(hsv.h);
-}
-},_updateColorInputs:function(col){
-var hex=col.toHex();
-if(this.showRgb){
-this.Rval.value=col.r;
-this.Gval.value=col.g;
-this.Bval.value=col.b;
-}
-if(this.showHsv){
-var hsv=col.toHsv();
-this.Hval.value=Math.round((hsv.h));
-this.Sval.value=Math.round(hsv.s);
-this.Vval.value=Math.round(hsv.v);
-}
-if(this.showHex){
-this.hexCode.value=hex;
-}
-this.previewNode.style.backgroundColor=hex;
-if(this.webSafe){
-this.safePreviewNode.style.backgroundColor=_1(hex);
-}
-},_setHuePoint:function(evt){
-var _15=evt.layerY-this._shift.hue.y;
-if(this.animatePoint){
-d.fx.slideTo({node:this.hueCursorNode,duration:this.slideDuration,top:_15,left:0,onEnd:d.hitch(this,"_updateColor",true)}).play();
-}else{
-d.style(this.hueCursorNode,"top",_15+"px");
-this._updateColor(false);
-}
-},_setPoint:function(evt){
-var _16=evt.layerY-this._shift.picker.y,_17=evt.layerX-this._shift.picker.x;
-if(evt){
-dijit.focus(evt.target);
-}
-if(this.animatePoint){
-d.fx.slideTo({node:this.cursorNode,duration:this.slideDuration,top:_16,left:_17,onEnd:d.hitch(this,"_updateColor",true)}).play();
-}else{
-d.style(this.cursorNode,{left:_17+"px",top:_16+"px"});
-this._updateColor(false);
-}
-},_handleKey:function(e){
-}});
+	
+	var webSafeFromHex = function(hex){
+		// stub, this is planned later:
+		return hex;
+	};
+	
+	dojo.declare("dojox.widget.ColorPicker",
+		dijit.form._FormWidget,
+		{
+		// summary: a HSV color picker - similar to Photoshop picker
+		//
+		// description: 
+		//		Provides an interactive HSV ColorPicker similar to
+		//		PhotoShop's color selction tool. This is an enhanced 
+		//		version of the default dijit.ColorPalette, though provides
+		//		no accessibility.
+		//
+		// example:
+		// |	var picker = new dojox.widget.ColorPicker({
+		// |		// a couple of example toggles:
+		// |		animatePoint:false,
+		// |		showHsv: false,
+		// |		webSafe: false,
+		// |		showRgb: false
+		// |	});
+		//	
+		// example: 
+		// |	<!-- markup: -->
+		// |	<div dojoType="dojox.widget.ColorPicker"></div>
+		//
+		// showRgb: Boolean
+		//	show/update RGB input nodes
+		showRgb: true,
+	
+		// showHsv: Boolean
+		//	show/update HSV input nodes
+		showHsv: true,
+	
+		// showHex: Boolean
+		//	show/update Hex value field
+		showHex: true,
+
+		// webSafe: Boolean
+		//	deprecated? or just use a toggle to show/hide that node, too?
+		webSafe: true,
+
+		// animatePoint: Boolean
+		//	toggle to use slideTo (true) or just place the cursor (false) on click
+		animatePoint: true,
+
+		// slideDuration: Integer
+		//	time in ms picker node will slide to next location (non-dragging) when animatePoint=true
+		slideDuration: 250, 
+
+		// liveUpdate: Boolean
+		//		Set to true to fire onChange in an indeterminate way
+		liveUpdate: false, 
+
+		// PICKER_HUE_H: int
+		//     Height of the hue picker, used to calculate positions    
+		PICKER_HUE_H: 150,
+		
+		// PICKER_SAT_VAL_H: int
+		//     Height of the 2d picker, used to calculate positions    
+		PICKER_SAT_VAL_H: 150,
+		
+		// PICKER_SAT_VAL_W: int
+		//     Width of the 2d picker, used to calculate positions    
+		PICKER_SAT_VAL_W: 150,
+
+		// PICKER_HUE_SELECTOR_H: int
+		//		Height of the hue selector DOM node, used to calc offsets so that selection
+		//		is center of the image node.
+		PICKER_HUE_SELECTOR_H: 8,
+		
+		// PICKER_SAT_SELECTOR_H: int
+		//		Height of the saturation selector DOM node, used to calc offsets so that selection
+		//		is center of the image node.
+		PICKER_SAT_SELECTOR_H: 10,
+
+		// PICKER_SAT_SELECTOR_W: int
+		//		Width of the saturation selector DOM node, used to calc offsets so that selection
+		//		is center of the image node.
+		PICKER_SAT_SELECTOR_W: 10,
+
+		// value: String
+		//	Default color for this component. Only hex values are accepted as incoming/returned
+		//	values. Adjust this value with `.attr`, eg: dijit.byId("myPicker").attr("value", "#ededed");
+		//	to cause the points to adjust and the values to reflect the current color. 
+		value: "#ffffff",
+		
+		_underlay: d.moduleUrl("dojox.widget","ColorPicker/images/underlay.png"),
+
+		_hueUnderlay: d.moduleUrl("dojox.widget","ColorPicker/images/hue.png"),
+
+		_pickerPointer: d.moduleUrl("dojox.widget","ColorPicker/images/pickerPointer.png"),
+
+		_huePickerPointer: d.moduleUrl("dojox.widget","ColorPicker/images/hueHandle.png"),
+
+		_huePickerPointerAlly: d.moduleUrl("dojox.widget","ColorPicker/images/hueHandleA11y.png"),
+
+		// don't change to d.moduleUrl, build won't intern it.
+		templateString: dojo.cache("dojox.widget","ColorPicker/ColorPicker.html"),
+
+		postMixInProperties: function(){
+			if(dojo.hasClass(dojo.body(), "dijit_a11y")){
+				// Use the pointer that will show up in high contrast.
+				this._huePickerPointer = this._huePickerPointerAlly;
+			}
+			this._uId = dijit.getUniqueId(this.id);
+			dojo.mixin(this, dojo.i18n.getLocalization("dojox.widget", "ColorPicker"));
+			dojo.mixin(this, dojo.i18n.getLocalization("dojo.cldr", "number"));
+			this.inherited(arguments);
+		},
+
+		postCreate: function(){
+			// summary: 
+			//		As quickly as we can, set up ie6 alpha-filter support for our
+			//		underlay.  we don't do image handles (done in css), just the 'core' 
+			//		of this widget: the underlay. 
+			this.inherited(arguments);
+			if(d.isIE < 7){ 
+				this.colorUnderlay.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this._underlay+"', sizingMethod='scale')";
+				this.colorUnderlay.src = this._blankGif.toString();
+			}
+			// hide toggle-able nodes:
+			if(!this.showRgb){ this.rgbNode.style.visibility = "hidden"; }
+			if(!this.showHsv){ this.hsvNode.style.visibility = "hidden"; }
+			if(!this.showHex){ this.hexNode.style.visibility = "hidden"; } 
+			if(!this.webSafe){ this.safePreviewNode.style.visibility = "hidden"; } 
+		},
+		
+		startup: function(){
+			if(this._started){
+				return;
+			}
+			this._started = true;
+			this.set("value", this.value);
+			this._mover = new d.dnd.move.boxConstrainedMoveable(this.cursorNode, {
+				box: {
+					t: -(this.PICKER_SAT_SELECTOR_H/2),
+					l: -(this.PICKER_SAT_SELECTOR_W/2),
+					w:this.PICKER_SAT_VAL_W,
+					h:this.PICKER_SAT_VAL_H
+				}
+			});
+			
+			this._hueMover = new d.dnd.move.boxConstrainedMoveable(this.hueCursorNode, {
+				box: {
+					t: -(this.PICKER_HUE_SELECTOR_H/2),
+					l:0,
+					w:0,
+					h:this.PICKER_HUE_H
+				}
+			});
+			
+			this._subs = [];
+			// no dnd/move/move published ... use a timer:
+			this._subs.push(d.subscribe("/dnd/move/stop", d.hitch(this, "_clearTimer")));
+			this._subs.push(d.subscribe("/dnd/move/start", d.hitch(this, "_setTimer")));
+
+			// Bind to up, down, left and right  arrows on the hue and saturation nodes.
+			this._keyListeners = [];
+			this._connects.push(dijit.typematic.addKeyListener(this.hueCursorNode,{
+				charOrCode: dojo.keys.UP_ARROW,
+				shiftKey: false,
+				metaKey: false,
+				ctrlKey: false,
+				altKey: false
+			}, this, dojo.hitch(this, this._updateHueCursorNode), 25, 25));
+			this._connects.push(dijit.typematic.addKeyListener(this.hueCursorNode,{
+				charOrCode: dojo.keys.DOWN_ARROW,
+				shiftKey: false,
+				metaKey: false,
+				ctrlKey: false,
+				altKey: false
+			}, this, dojo.hitch(this, this._updateHueCursorNode), 25, 25));
+			this._connects.push(dijit.typematic.addKeyListener(this.cursorNode,{
+				charOrCode: dojo.keys.UP_ARROW,
+				shiftKey: false,
+				metaKey: false,
+				ctrlKey: false,
+				altKey: false
+			}, this, dojo.hitch(this, this._updateCursorNode), 25, 25));
+			this._connects.push(dijit.typematic.addKeyListener(this.cursorNode,{
+				charOrCode: dojo.keys.DOWN_ARROW,
+				shiftKey: false,
+				metaKey: false,
+				ctrlKey: false,
+				altKey: false
+			}, this, dojo.hitch(this, this._updateCursorNode), 25, 25));
+			this._connects.push(dijit.typematic.addKeyListener(this.cursorNode,{
+				charOrCode: dojo.keys.LEFT_ARROW,
+				shiftKey: false,
+				metaKey: false,
+				ctrlKey: false,
+				altKey: false
+			}, this, dojo.hitch(this, this._updateCursorNode), 25, 25));
+			this._connects.push(dijit.typematic.addKeyListener(this.cursorNode,{
+				charOrCode: dojo.keys.RIGHT_ARROW,
+				shiftKey: false,
+				metaKey: false,
+				ctrlKey: false,
+				altKey: false
+			}, this, dojo.hitch(this, this._updateCursorNode), 25, 25));
+		},
+		
+		_setValueAttr: function(value){
+			if(!this._started){ return; }
+			this.setColor(value, true);
+		},
+		
+		setColor: function(/* String */color, force){
+			// summary: Set a color on a picker. Usually used to set
+			//          initial color as an alternative to passing defaultColor option
+			//          to the constructor. 
+			var col = dojox.color.fromString(color);
+			this._updatePickerLocations(col);
+			this._updateColorInputs(col);
+			this._updateValue(col, force);
+		},
+		
+		_setTimer: function(/* d.dnd.Mover */mover){
+			// FIXME: should I assume this? focus on mouse down so on mouse up
+			dijit.focus(mover.node);
+			d.setSelectable(this.domNode,false);
+			this._timer = setInterval(d.hitch(this, "_updateColor"), 45);	
+		},
+		
+		_clearTimer: function(/* d.dnd.Mover */mover){
+			clearInterval(this._timer);
+			this._timer = null;
+			this.onChange(this.value);
+			d.setSelectable(this.domNode,true);
+		},
+		
+		_setHue: function(/* Decimal */h){
+			// summary: 
+			//		Sets a natural color background for the 
+			//		underlay image against closest hue value (full saturation) 
+			//		h: 0..360 
+			d.style(this.colorUnderlay, "backgroundColor", dojox.color.fromHsv(h,100,100).toHex());
+			
+		},
+
+		_updateHueCursorNode: function(count, node, e){
+			// summary:
+			//		Function used by the typematic code to handle cursor position and update
+			//		via keyboard.
+			// count:
+			//		-1 means stop, anything else is just how many times it was called.
+			// node:
+			//		The node generating the event.
+			// e:
+			//		The event.
+			if(count !== -1){
+				var y = dojo.style(this.hueCursorNode, "top");
+				var selCenter = (this.PICKER_HUE_SELECTOR_H/2);
+
+				// Account for our offset
+				y += selCenter;
+				var update = false;
+				if(e.charOrCode == dojo.keys.UP_ARROW){
+					if(y > 0){
+						y -= 1;
+						update = true;
+					}
+				}else if(e.charOrCode == dojo.keys.DOWN_ARROW){
+					if(y < this.PICKER_HUE_H){
+						y += 1;
+						update = true;
+					}
+				}
+				y -= selCenter;
+				if(update){
+					dojo.style(this.hueCursorNode, "top", y + "px");	
+				}
+			}else{
+				this._updateColor(true);
+			}
+		},
+		
+		_updateCursorNode: function(count, node, e){
+			// summary:
+			//		Function used by the typematic code to handle cursor position and update
+			//		via keyboard.
+			// count:
+			//		-1 means stop, anything else is just how many times it was called.
+			// node:
+			//		The node generating the event.
+			// e:
+			//		The event.
+			var selCenterH = this.PICKER_SAT_SELECTOR_H/2;
+			var selCenterW = this.PICKER_SAT_SELECTOR_W/2;
+
+			if(count !== -1){
+				var y = dojo.style(this.cursorNode, "top");
+				var x = dojo.style(this.cursorNode, "left");
+				
+				// Account for our offsets to center
+				y += selCenterH;
+				x += selCenterW;
+
+				var update = false;
+				if(e.charOrCode == dojo.keys.UP_ARROW){
+					if(y > 0){
+						y -= 1;
+						update = true;
+					}
+				}else if(e.charOrCode == dojo.keys.DOWN_ARROW){
+					if(y < this.PICKER_SAT_VAL_H){
+						y += 1;
+						update = true;
+					}
+				}else if(e.charOrCode == dojo.keys.LEFT_ARROW){
+					if(x > 0){
+						x -= 1;
+						update = true;
+					}
+				}else if(e.charOrCode == dojo.keys.RIGHT_ARROW){
+					if(x < this.PICKER_SAT_VAL_W){
+						x += 1;
+						update = true;
+					}
+				}
+				if(update){
+					// Account for our offsets to center
+					y -= selCenterH;
+					x -= selCenterW;
+					dojo.style(this.cursorNode, "top", y + "px");	
+					dojo.style(this.cursorNode, "left", x + "px");	
+				}
+			}else{
+				this._updateColor(true);
+			}
+		},
+
+		_updateColor: function(){
+			// summary: update the previewNode color, and input values [optional]
+			
+			var hueSelCenter = this.PICKER_HUE_SELECTOR_H/2,
+				satSelCenterH = this.PICKER_SAT_SELECTOR_H/2,
+				satSelCenterW = this.PICKER_SAT_SELECTOR_W/2;
+
+			var _huetop = d.style(this.hueCursorNode,"top") + hueSelCenter, 
+				_pickertop = d.style(this.cursorNode,"top") + satSelCenterH,
+				_pickerleft = d.style(this.cursorNode,"left") + satSelCenterW,
+				h = Math.round(360 - (_huetop / this.PICKER_HUE_H * 360)),
+				col = dojox.color.fromHsv(h, _pickerleft / this.PICKER_SAT_VAL_W * 100, 100 - (_pickertop / this.PICKER_SAT_VAL_H * 100))
+			;
+			
+			this._updateColorInputs(col);
+			this._updateValue(col, true);
+			
+			// update hue, not all the pickers
+			if (h!=this._hue) {
+				this._setHue(h);
+			}
+		},
+		
+		_colorInputChange: function(e){
+			//summary: updates picker position and inputs 
+			//         according to rgb, hex or hsv input changes
+			var col, hasit = false;
+			switch (e.target) {
+				//transform to hsv to pixels
+
+				case this.hexCode:
+					col = dojox.color.fromString(e.target.value);
+					hasit = true;
+					
+					break;
+				case this.Rval:
+				case this.Gval:
+				case this.Bval:
+					col = dojox.color.fromArray([this.Rval.value, this.Gval.value, this.Bval.value]);
+					hasit = true;
+					break;
+				case this.Hval:
+				case this.Sval:
+				case this.Vval:
+					col = dojox.color.fromHsv(this.Hval.value, this.Sval.value, this.Vval.value);
+					hasit = true;
+					break;
+			}
+			
+			if(hasit){
+				this._updatePickerLocations(col);
+				this._updateColorInputs(col);
+				this._updateValue(col, true);
+			}
+			
+		},
+		
+		_updateValue: function(/* dojox.color.Color */col, /* Boolean */fireChange){
+			// summary: updates the value of the widget
+			//          can cancel reverse onChange by specifying second param
+			var hex = col.toHex();
+			
+			this.value = this.valueNode.value = hex;
+			
+			// anytime we muck with the color, fire onChange?
+			if(fireChange && (!this._timer || this.liveUpdate)) {
+				this.onChange(hex);
+			}
+		},
+		
+		_updatePickerLocations: function(/* dojox.color.Color */col){
+			//summary: update handles on the pickers acording to color values
+			//
+			var hueSelCenter = this.PICKER_HUE_SELECTOR_H/2,
+				satSelCenterH = this.PICKER_SAT_SELECTOR_H/2,
+				satSelCenterW = this.PICKER_SAT_SELECTOR_W/2;
+
+            var hsv = col.toHsv(),
+				ypos = Math.round(this.PICKER_HUE_H - hsv.h / 360 * this.PICKER_HUE_H) - hueSelCenter,
+				newLeft = Math.round(hsv.s / 100 * this.PICKER_SAT_VAL_W) - satSelCenterW,
+				newTop = Math.round(this.PICKER_SAT_VAL_H - hsv.v / 100 * this.PICKER_SAT_VAL_H) - satSelCenterH
+			;
+			
+			if (this.animatePoint) {
+				d.fx.slideTo({
+					node: this.hueCursorNode,
+					duration: this.slideDuration,
+					top: ypos,
+					left: 0
+				}).play();
+				
+				d.fx.slideTo({
+					node: this.cursorNode,
+					duration: this.slideDuration,
+					top: newTop,
+					left: newLeft
+				}).play();
+				
+			}
+			else {
+				d.style(this.hueCursorNode, "top", ypos + "px");
+				d.style(this.cursorNode, {
+					left: newLeft + "px",
+					top: newTop + "px"
+				});
+			}
+			
+			// limit hue calculations to only when it changes
+			if (hsv.h != this._hue) {
+				this._setHue(hsv.h);
+			}
+			
+		},
+		
+		_updateColorInputs: function(/* dojox.color.Color */col){
+			//summary: updates color inputs that were changed through other inputs
+			//or by clicking on the picker
+			
+			var hex = col.toHex();
+			
+			if (this.showRgb) {
+				this.Rval.value = col.r;
+				this.Gval.value = col.g;
+				this.Bval.value = col.b;
+			}
+			
+			if (this.showHsv) {
+				var hsv = col.toHsv();
+				this.Hval.value = Math.round((hsv.h)); // convert to 0..360
+				this.Sval.value = Math.round(hsv.s);
+				this.Vval.value = Math.round(hsv.v);
+			}
+			
+			if (this.showHex) {
+				this.hexCode.value = hex;
+			}
+			
+			this.previewNode.style.backgroundColor = hex;
+			
+			if (this.webSafe) {
+				this.safePreviewNode.style.backgroundColor = webSafeFromHex(hex);
+			}
+		},
+		
+		_setHuePoint: function(/* Event */evt){ 
+			// summary: set the hue picker handle on relative y coordinates
+			var selCenter = (this.PICKER_HUE_SELECTOR_H/2);
+			var ypos = evt.layerY - selCenter;
+			if(this.animatePoint){
+				d.fx.slideTo({ 
+					node: this.hueCursorNode, 
+					duration:this.slideDuration,
+					top: ypos,
+					left: 0,
+					onEnd: d.hitch(this, function() {this._updateColor(true); dijit.focus(this.hueCursorNode);})
+				}).play();
+			}else{
+				d.style(this.hueCursorNode, "top", ypos + "px");
+				this._updateColor(false); 
+			}
+		},
+		
+		_setPoint: function(/* Event */evt){
+			// summary: set our picker point based on relative x/y coordinates
+			//  evt.preventDefault();
+			var satSelCenterH = this.PICKER_SAT_SELECTOR_H/2;
+			var satSelCenterW = this.PICKER_SAT_SELECTOR_W/2;
+			var newTop = evt.layerY - satSelCenterH;
+			var newLeft = evt.layerX - satSelCenterW;
+			
+			if(evt){ dijit.focus(evt.target); }
+
+			if(this.animatePoint){
+				d.fx.slideTo({ 
+					node: this.cursorNode, 
+					duration: this.slideDuration,
+					top: newTop,
+					left: newLeft,
+					onEnd: d.hitch(this, function() {this._updateColor(true); dijit.focus(this.cursorNode);})
+				}).play();
+			}else{
+				d.style(this.cursorNode, {
+					left: newLeft + "px",
+					top: newTop + "px"	
+				});
+				this._updateColor(false); 
+			}
+		},
+		
+		_handleKey: function(/* Event */e){
+			// FIXME: not implemented YET
+			// var keys = d.keys;
+		},
+
+		focus: function(){
+			// summary:
+			//		Put focus on this widget, only if focus isn't set on it already.
+			if(!this._focused){
+				dijit.focus(this.focusNode);
+			}
+		},
+
+		_stopDrag: function(e){
+			// summary:
+			//		Function to hald the mouse down default
+			//		to disable draggong of images out of the color
+			//		picker.
+			dojo.stopEvent(e);
+		},
+
+		destroy: function(){
+			// summary:
+			//		Over-ride to clean up subscriptions, etc.
+			this.inherited(arguments);
+			dojo.forEach(this._subs, function(sub){
+				dojo.unsubscribe(sub);
+			});
+			delete this._subs;
+		}
+	});
 })(dojo);
-}
diff --git a/dojox/widget/ColorPicker/ColorPicker.css b/dojox/widget/ColorPicker/ColorPicker.css
index 56aa4c9..a7b8fa9 100644
--- a/dojox/widget/ColorPicker/ColorPicker.css
+++ b/dojox/widget/ColorPicker/ColorPicker.css
@@ -1,15 +1,19 @@
 .dojoxColorPicker {
 	padding:8px;
-	width:300px;
-	height:150px; 
 	-moz-border-radius:4pt;
 	-webkit-border-radius:5pt;
 	-webkit-drop-shadow:3pt;
 }
+
+.dojoxColorPickerRightPad {
+	padding-right: 8px;
+}
+
 .tundra .dojoxColorPicker {
 	background:#ededed;
 	border:1px solid #ccc;
 }
+
 .dojoxColorPickerBox {
 	position:relative;
 	width:150px;	
@@ -17,8 +21,9 @@
 	margin:0; 
 	padding:0;
 }
+
 .dojoxColorPickerUnderlay {
-	position:absolute; 
+	position:relative; 
 	top:0; left:0;
 	width:150px; 
 	height:150px;
@@ -27,34 +32,45 @@
 .tundra .dojoxColorPickerUnderlay {
 	border:1px solid #a0a0a0;
 }
+
+.claro .dojoxColorPicker {
+	background:#ededed;
+	border:1px solid #cdcdcd;
+}
+
+.claro .dojoxColorPickerUnderlay {
+	border:1px solid #cccccc;
+}
+
 .dojoxHuePickerUnderlay {
-	background:url(images/hue.png) no-repeat top center; 
-	position:absolute;
+	position:relative;
 	top:0; left:0;
 	height:150px;
 	width:20px;
 	z-index:1;
+	text-align: center;
 }
-.dojoxHuePicker { position:relative; top:-150px; left:157px; }
+
+.dojoxHuePicker { position:relative; top: 0px; left: 0px; padding: 0px;}
+
 .dojoxHuePickerPoint {
 	position:absolute;
 	top:0; left:0;
 	width:20px;
 	height:8px;
 	z-index:3; 
-	background-color:#666; 
 	cursor:move;
-	background:url(images/hueHandle.png) no-repeat center center; 
 }
+
 .dojoxColorPickerPoint {
 	position:absolute;
 	width:10px; 
 	height:10px;
-	background: url(images/pickerPointer.png) no-repeat center center; 
 	border:0;
 	z-index:3; 
 	cursor:move; 
 }
+
 .dojoxColorPickerPreview {
 	display:block;	
 	width:45px;	
@@ -62,32 +78,41 @@
 	border:1px solid #333;
 	background-color:#fff; 
 	position:relative;
-	top:-150px;
-	left: 185px; 
+	top: 0px;
+	left: 0px; 
 }
 .dojoxColorPickerWebSafePreview {
 	display:block;
 	width:25px; 
 	height:25px; 
 	position:relative;
-	top:-197px;
-	left:240px; 
+	top: 0px;
+	left: 0px; 
 	border:1px solid #333; 
 }
+
 .dojoxColorPickerOptional {
 	position:relative;
-	top:-170px;
-	left:185px;
+	top: 0px;
+	left: 0px;
+	height: 100%;
+}
+
+.dojoxColorPickerOptional table {
+	border-spacing: 4px;
+}
+
+.dojoxColorPickerPreviewContainer table {
+	border-spacing: 6px 0px;
 }
+
 .dojoxColorPickerOptional input {
 	border:1px solid #a7a7a7;
 	width:25px;
 	padding:1px 3px 1px 3px;
 	line-height:1.1em;
 }
-.dojoxColorPickerRgb { position:absolute; top:0; left:0;  } 
-.dojoxColorPickerHsv { position:absolute; top:0; left:50px;  } 
-.dojoxColorPickerHex { position:absolute; top:73px; left:2px;  } 
+
 .dojoxColorPickerHex input {
 	width:55px;	
 }
diff --git a/dojox/widget/ColorPicker/ColorPicker.html b/dojox/widget/ColorPicker/ColorPicker.html
index 032f882..2939ac6 100644
--- a/dojox/widget/ColorPicker/ColorPicker.html
+++ b/dojox/widget/ColorPicker/ColorPicker.html
@@ -1,31 +1,72 @@
-<div class="dojoxColorPicker" dojoAttachEvent="onkeypress: _handleKey">
-	<div class="dojoxColorPickerBox">
-		<div dojoAttachPoint="cursorNode" tabIndex="0" class="dojoxColorPickerPoint"></div>
-		<img dojoAttachPoint="colorUnderlay" dojoAttachEvent="onclick: _setPoint" class="dojoxColorPickerUnderlay" src="${_underlay}">
-	</div>
-	<div class="dojoxHuePicker">
-		<div dojoAttachPoint="hueCursorNode" tabIndex="0" class="dojoxHuePickerPoint"></div>
-		<div dojoAttachPoint="hueNode" class="dojoxHuePickerUnderlay" dojoAttachEvent="onclick: _setHuePoint"></div>
-	</div>
-	<div dojoAttachPoint="previewNode" class="dojoxColorPickerPreview"></div>
-	<div dojoAttachPoint="safePreviewNode" class="dojoxColorPickerWebSafePreview"></div>
-	<div class="dojoxColorPickerOptional" dojoAttachEvent="onchange: _colorInputChange">
-		<div class="dijitInline dojoxColorPickerRgb" dojoAttachPoint="rgbNode">
-			<table>
-			<tr><td>${redLabel}</td><td><input dojoAttachPoint="Rval" size="1"></td></tr>
-			<tr><td>${greenLabel}</td><td><input dojoAttachPoint="Gval" size="1"></td></tr>
-			<tr><td>${blueLabel}</td><td><input dojoAttachPoint="Bval" size="1"></td></tr>
+<table class="dojoxColorPicker" dojoAttachEvent="onkeypress: _handleKey" cellpadding="0" cellspacing="0">
+	<tr>
+		<td valign="top" class="dojoxColorPickerRightPad">
+			<div class="dojoxColorPickerBox">
+				<!-- Forcing ABS in style attr due to dojo DND issue with not picking it up form the class. -->
+				<img role="status" title="${saturationPickerTitle}" alt="${saturationPickerTitle}" class="dojoxColorPickerPoint" src="${_pickerPointer}" tabIndex="0" dojoAttachPoint="cursorNode" style="position: absolute; top: 0px; left: 0px;">
+				<img role="presentation" alt="" dojoAttachPoint="colorUnderlay" dojoAttachEvent="onclick: _setPoint, onmousedown: _stopDrag" class="dojoxColorPickerUnderlay" src="${_underlay}" ondragstart="return false">
+			</div>
+		</td>
+		<td valign="top" class="dojoxColorPickerRightPad">
+			<div class="dojoxHuePicker">
+				<!-- Forcing ABS in style attr due to dojo DND issue with not picking it up form the class. -->
+				<img role="status" dojoAttachPoint="hueCursorNode" tabIndex="0" class="dojoxHuePickerPoint" title="${huePickerTitle}" alt="${huePickerTitle}" src="${_huePickerPointer}" style="position: absolute; top: 0px; left: 0px;">
+				<div class="dojoxHuePickerUnderlay" dojoAttachPoint="hueNode">
+				    <img role="presentation" alt="" dojoAttachEvent="onclick: _setHuePoint, onmousedown: _stopDrag" src="${_hueUnderlay}">
+				</div>
+			</div>
+		</td>
+		<td valign="top">
+			<table cellpadding="0" cellspacing="0">
+				<tr>
+					<td valign="top" class="dojoxColorPickerPreviewContainer">
+						<table cellpadding="0" cellspacing="0">
+							<tr>
+								<td valign="top" class="dojoxColorPickerRightPad">
+									<div dojoAttachPoint="previewNode" class="dojoxColorPickerPreview"></div>
+								</td>
+								<td valign="top">
+									<div dojoAttachPoint="safePreviewNode" class="dojoxColorPickerWebSafePreview"></div>
+								</td>
+							</tr>
+						</table>
+					</td>
+				</tr>
+				<tr>
+					<td valign="bottom">
+						<table class="dojoxColorPickerOptional" cellpadding="0" cellspacing="0">
+							<tr>
+								<td>
+									<div class="dijitInline dojoxColorPickerRgb" dojoAttachPoint="rgbNode">
+										<table cellpadding="1" cellspacing="1">
+										<tr><td><label for="${_uId}_r">${redLabel}</label></td><td><input id="${_uId}_r" dojoAttachPoint="Rval" size="1" dojoAttachEvent="onchange: _colorInputChange"></td></tr>
+										<tr><td><label for="${_uId}_g">${greenLabel}</label></td><td><input id="${_uId}_g" dojoAttachPoint="Gval" size="1" dojoAttachEvent="onchange: _colorInputChange"></td></tr>
+										<tr><td><label for="${_uId}_b">${blueLabel}</label></td><td><input id="${_uId}_b" dojoAttachPoint="Bval" size="1" dojoAttachEvent="onchange: _colorInputChange"></td></tr>
+										</table>
+									</div>
+								</td>
+								<td>
+									<div class="dijitInline dojoxColorPickerHsv" dojoAttachPoint="hsvNode">
+										<table cellpadding="1" cellspacing="1">
+										<tr><td><label for="${_uId}_h">${hueLabel}</label></td><td><input id="${_uId}_h" dojoAttachPoint="Hval"size="1" dojoAttachEvent="onchange: _colorInputChange"> ${degLabel}</td></tr>
+										<tr><td><label for="${_uId}_s">${saturationLabel}</label></td><td><input id="${_uId}_s" dojoAttachPoint="Sval" size="1" dojoAttachEvent="onchange: _colorInputChange"> ${percentSign}</td></tr>
+										<tr><td><label for="${_uId}_v">${valueLabel}</label></td><td><input id="${_uId}_v" dojoAttachPoint="Vval" size="1" dojoAttachEvent="onchange: _colorInputChange"> ${percentSign}</td></tr>
+										</table>
+									</div>
+								</td>
+							</tr>
+							<tr>
+								<td colspan="2">
+									<div class="dojoxColorPickerHex" dojoAttachPoint="hexNode" aria-live="polite">	
+										<label for="${_uId}_hex"> ${hexLabel} </label><input id="${_uId}_hex" dojoAttachPoint="hexCode, focusNode, valueNode" size="6" class="dojoxColorPickerHexCode" dojoAttachEvent="onchange: _colorInputChange">
+									</div>
+								</td>
+							</tr>
+						</table>
+					</td>
+				</tr>
 			</table>
-		</div>
-		<div class="dijitInline dojoxColorPickerHsv" dojoAttachPoint="hsvNode">
-			<table>
-			<tr><td>${hueLabel}</td><td><input dojoAttachPoint="Hval"size="1"> ${degLabel}</td></tr>
-			<tr><td>${saturationLabel}</td><td><input dojoAttachPoint="Sval" size="1"> ${percentSign}</td></tr>
-			<tr><td>${valueLabel}</td><td><input dojoAttachPoint="Vval" size="1"> ${percentSign}</td></tr>
-			</table>
-		</div>
-		<div class="dojoxColorPickerHex" dojoAttachPoint="hexNode">	
-			${hexLabel}: <input dojoAttachPoint="hexCode, focusNode, valueNode" size="6" class="dojoxColorPickerHexCode">
-		</div>
-	</div>
-</div>
+		</td>
+	</tr>
+</table>
+
diff --git a/dojox/widget/ColorPicker/images/hue.png b/dojox/widget/ColorPicker/images/hue.png
old mode 100644
new mode 100755
diff --git a/dojox/widget/ColorPicker/images/hueHandle.png b/dojox/widget/ColorPicker/images/hueHandle.png
old mode 100644
new mode 100755
diff --git a/dojox/widget/ColorPicker/images/hueHandleA11y.png b/dojox/widget/ColorPicker/images/hueHandleA11y.png
new file mode 100755
index 0000000..58c648d
Binary files /dev/null and b/dojox/widget/ColorPicker/images/hueHandleA11y.png differ
diff --git a/dojox/widget/ColorPicker/images/pickerPointer.png b/dojox/widget/ColorPicker/images/pickerPointer.png
old mode 100644
new mode 100755
diff --git a/dojox/widget/ColorPicker/images/underlay.png b/dojox/widget/ColorPicker/images/underlay.png
old mode 100644
new mode 100755
diff --git a/dojox/widget/DataPresentation.js b/dojox/widget/DataPresentation.js
index 20accf6..9c46d1d 100644
--- a/dojox/widget/DataPresentation.js
+++ b/dojox/widget/DataPresentation.js
@@ -1,395 +1,897 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.DataPresentation"]){
-dojo._hasResource["dojox.widget.DataPresentation"]=true;
 dojo.provide("dojox.widget.DataPresentation");
 dojo.experimental("dojox.widget.DataPresentation");
+
 dojo.require("dojox.grid.DataGrid");
 dojo.require("dojox.charting.Chart2D");
 dojo.require("dojox.charting.widget.Legend");
 dojo.require("dojox.charting.action2d.Tooltip");
 dojo.require("dojox.charting.action2d.Highlight");
-dojo.require("dojo.colors");
+dojo.require("dojo.colors");		
 dojo.require("dojo.data.ItemFileWriteStore");
+
 (function(){
-var _1=function(_2,_3,_4,_5,_6){
-var _7=[],_8=_3;
-_7[0]={value:0,text:""};
-var _9=_2.slice(0);
-if(_4){
-_9.reverse();
-}
-var _a=_9.length;
-if((_5!=="ClusteredBars")&&(_5!=="StackedBars")){
-var _b=_6.offsetWidth;
-var _c=(""+_9[0]).length*_9.length*7;
-if(_8==1){
-for(var z=1;z<500;++z){
-if((_c/z)<_b){
-break;
-}
-++_8;
-}
-}
-}
-for(var i=0;i<_a;i++){
-if(i%_8==0){
-_7.push({value:(i+1),text:_9[i]});
-}else{
-_7.push({value:(i+1),text:""});
-}
-}
-_7.push({value:(_a+1),text:""});
-return _7;
-};
-var _d=function(_e,_f){
-var _10={vertical:false,labels:_f,min:0,max:_f.length-1,majorTickStep:1,minorTickStep:1};
-if((_e==="ClusteredBars")||(_e==="StackedBars")){
-_10.vertical=true;
-}
-if((_e==="Lines")||(_e==="Areas")||(_e==="StackedAreas")){
-_10.min++;
-_10.max--;
-}
-return _10;
-};
-var _11=function(_12,_13,_14,_15){
-var _16={vertical:true,fixLower:"major",fixUpper:"major",natural:true};
-if(_13==="secondary"){
-_16.leftBottom=false;
-}
-if((_12==="ClusteredBars")||(_12==="StackedBars")){
-_16.vertical=false;
-}
-if(_14==_15){
-_16.min=_14-1;
-_16.max=_15+1;
-}
-return _16;
-};
-var _17=function(_18,_19,_1a){
-var _1b={type:_18,hAxis:"independent",vAxis:"dependent-"+_19,gap:4,lines:false,areas:false,markers:false};
-if((_18==="ClusteredBars")||(_18==="StackedBars")){
-_1b.hAxis=_1b.vAxis;
-_1b.vAxis="independent";
-}
-if((_18==="Lines")||(_18==="Hybrid-Lines")||(_18==="Areas")||(_18==="StackedAreas")){
-_1b.lines=true;
-}
-if((_18==="Areas")||(_18==="StackedAreas")){
-_1b.areas=true;
-}
-if(_18==="Lines"){
-_1b.markers=true;
-}
-if(_18==="Hybrid-Lines"){
-_1b.shadows={dx:2,dy:2,dw:2};
-_1b.type="Lines";
-}
-if(_18==="Hybrid-ClusteredColumns"){
-_1b.type="ClusteredColumns";
-}
-if(_1a){
-_1b.animate=_1a;
-}
-return _1b;
-};
-var _1c=function(_1d,_1e,_1f,_20,_21,_22,_23,_24,_25,_26){
-var _27=_1e;
-if(!_27){
-_1d.innerHTML="";
-_27=new dojox.charting.Chart2D(_1d);
-}
-if(_23){
-_23._clone=function(){
-var _28=new dojox.charting.Theme({chart:this.chart,plotarea:this.plotarea,axis:this.axis,series:this.series,marker:this.marker,antiAlias:this.antiAlias,assignColors:this.assignColors,assignMarkers:this.assigneMarkers,colors:dojo.delegate(this.colors)});
-_28.markers=this.markers;
-_28._buildMarkerArray();
-return _28;
-};
-_27.setTheme(_23);
-}
-var _29=_1(_24.series_data[0],_22,_20,_1f,_1d);
-var _2a={};
-var _2b=null;
-var _2c=null;
-var _2d=_24.series_name.length;
-for(var i=0;i<_2d;i++){
-if(_24.series_chart[i]&&(_24.series_data[i].length>0)){
-var _2e=_1f;
-var _2f=_24.series_axis[i];
-if(_2e=="Hybrid"){
-if(_24.series_charttype[i]=="line"){
-_2e="Hybrid-Lines";
-}else{
-_2e="Hybrid-ClusteredColumns";
-}
-}
-if(!_2a[_2f]){
-_2a[_2f]={};
-}
-if(!_2a[_2f][_2e]){
-var _30=_2f+"-"+_2e;
-_27.addPlot(_30,_17(_2e,_2f,_21));
-new dojox.charting.action2d.Tooltip(_27,_30);
-if((_2e!=="Lines")&&(_2e!=="Hybrid-Lines")){
-new dojox.charting.action2d.Highlight(_27,_30);
-}
-_2a[_2f][_2e]=true;
-}
-var _31=[];
-var _32=_24.series_data[i].length;
-for(var j=0;j<_32;j++){
-var val=_24.series_data[i][j];
-_31.push(val);
-if(_2b===null||val>_2b){
-_2b=val;
-}
-if(_2c===null||val<_2c){
-_2c=val;
-}
-}
-if(_20){
-_31.reverse();
-}
-var _33={plot:_2f+"-"+_2e};
-if(_24.series_linestyle[i]){
-_33.stroke={style:_24.series_linestyle[i]};
-}
-_27.addSeries(_24.series_name[i],_31,_33);
-}
-}
-_27.addAxis("independent",_d(_1f,_29));
-_27.addAxis("dependent-primary",_11(_1f,"primary",_2c,_2b));
-_27.addAxis("dependent-secondary",_11(_1f,"secondary",_2c,_2b));
-_27.render();
-return _27;
-};
-var _34=function(_35,_36,_37,_38){
-var _39=_36;
-if(!_39){
-if(_38){
-_39=new dojox.charting.widget.Legend({chart:_37,horizontal:false},_35);
-}else{
-_39=new dojox.charting.widget.Legend({chart:_37,vertical:false},_35);
-}
-}
-return _39;
-};
-var _3a=function(_3b,_3c,_3d,_3e,_3f){
-var _40=_3c||new dojox.grid.DataGrid({},_3b);
-_40.startup();
-_40.setStore(_3d,_3e,_3f);
-var _41=[];
-for(var ser=0;ser<_3d.series_name.length;ser++){
-if(_3d.series_grid[ser]&&(_3d.series_data[ser].length>0)){
-_41.push({field:"data."+ser,name:_3d.series_name[ser],width:"auto",formatter:_3d.series_gridformatter[ser]});
-}
-}
-_40.setStructure(_41);
-_40.render();
-return _40;
-};
-var _42=function(_43,_44){
-if(_44.title){
-_43.innerHTML=_44.title;
-}
-};
-var _45=function(_46,_47){
-if(_47.footer){
-_46.innerHTML=_47.footer;
-}
-};
-var _48=function(_49,_4a){
-var _4b=_49;
-if(_4a){
-var _4c=_4a.split(/[.\[\]]+/);
-for(var _4d in _4c){
-if(_4b){
-_4b=_4b[_4c[_4d]];
-}
-}
-}
-return _4b;
-};
-dojo.declare("dojox.widget.DataPresentation",null,{type:"chart",chartType:"clusteredBars",reverse:false,animate:null,labelMod:1,legendVertical:false,constructor:function(_4e,_4f){
-dojo.mixin(this,_4f);
-this.domNode=dojo.byId(_4e);
-this[this.type+"Node"]=this.domNode;
-if(typeof this.theme=="string"){
-this.theme=dojo.getObject(this.theme);
-}
-this.chartNode=dojo.byId(this.chartNode);
-this.legendNode=dojo.byId(this.legendNode);
-this.gridNode=dojo.byId(this.gridNode);
-this.titleNode=dojo.byId(this.titleNode);
-this.footerNode=dojo.byId(this.footerNode);
-if(this.url){
-this.setURL(null,this.refreshInterval);
-}else{
-if(this.data){
-this.setData(null,this.refreshInterval);
-}else{
-this.setStore();
-}
-}
-},setURL:function(url,_50){
-if(_50){
-this.cancelRefresh();
-}
-this.url=url||this.url;
-this.refreshInterval=_50||this.refreshInterval;
-var me=this;
-dojo.xhrGet({url:this.url,handleAs:"json-comment-optional",load:function(_51,_52){
-me.setData(_51);
-},error:function(xhr,_53){
-if(me.urlError&&(typeof me.urlError=="function")){
-me.urlError(xhr,_53);
-}
-}});
-if(_50&&(this.refreshInterval>0)){
-this.refreshIntervalPending=setInterval(function(){
-me.setURL();
-},this.refreshInterval);
-}
-},setData:function(_54,_55){
-if(_55){
-this.cancelRefresh();
-}
-this.data=_54||this.data;
-this.refreshInterval=_55||this.refreshInterval;
-var _56=(typeof this.series=="function")?this.series(this.data):this.series;
-var _57=[],_58=[],_59=[],_5a=[],_5b=[],_5c=[],_5d=[],_5e=[],_5f=[],_60=0;
-for(var ser=0;ser<_56.length;ser++){
-_57[ser]=_48(this.data,_56[ser].datapoints);
-if(_57[ser]&&(_57[ser].length>_60)){
-_60=_57[ser].length;
-}
-_58[ser]=[];
-_59[ser]=_56[ser].name||(_56[ser].namefield?_48(this.data,_56[ser].namefield):null)||("series "+ser);
-_5a[ser]=(_56[ser].chart!==false);
-_5b[ser]=_56[ser].charttype||"bar";
-_5c[ser]=_56[ser].linestyle;
-_5d[ser]=_56[ser].axis||"primary";
-_5e[ser]=(_56[ser].grid!==false);
-_5f[ser]=_56[ser].gridformatter;
-}
-var _61,_62,_63,_64;
-var _65=[];
-for(_61=0;_61<_60;_61++){
-_62={index:_61};
-for(ser=0;ser<_56.length;ser++){
-if(_57[ser]&&(_57[ser].length>_61)){
-_63=_48(_57[ser][_61],_56[ser].field);
-if(_5a[ser]){
-_64=parseFloat(_63);
-if(!isNaN(_64)){
-_63=_64;
-}
-}
-_62["data."+ser]=_63;
-_58[ser].push(_63);
-}
-}
-_65.push(_62);
-}
-if(_60<=0){
-_65.push({index:0});
-}
-var _66=new dojo.data.ItemFileWriteStore({data:{identifier:"index",items:_65}});
-if(this.data.title){
-_66.title=this.data.title;
-}
-if(this.data.footer){
-_66.footer=this.data.footer;
-}
-_66.series_data=_58;
-_66.series_name=_59;
-_66.series_chart=_5a;
-_66.series_charttype=_5b;
-_66.series_linestyle=_5c;
-_66.series_axis=_5d;
-_66.series_grid=_5e;
-_66.series_gridformatter=_5f;
-this.setPreparedStore(_66);
-if(_55&&(this.refreshInterval>0)){
-var me=this;
-this.refreshIntervalPending=setInterval(function(){
-me.setData();
-},this.refreshInterval);
-}
-},refresh:function(){
-if(this.url){
-this.setURL(this.url,this.refreshInterval);
-}else{
-if(this.data){
-this.setData(this.data,this.refreshInterval);
-}
-}
-},cancelRefresh:function(){
-if(this.refreshIntervalPending){
-clearInterval(this.refreshIntervalPending);
-this.refreshIntervalPending=undefined;
-}
-},setStore:function(_67,_68,_69){
-this.setPreparedStore(_67,_68,_69);
-},setPreparedStore:function(_6a,_6b,_6c){
-this.preparedstore=_6a||this.store;
-this.query=_6b||this.query;
-this.queryOptions=_6c||this.queryOptions;
-if(this.preparedstore){
-if(this.chartNode){
-this.chartWidget=_1c(this.chartNode,this.chartWidget,this.chartType,this.reverse,this.animate,this.labelMod,this.theme,this.preparedstore,this.query,this,_6c);
-}
-if(this.legendNode){
-this.legendWidget=_34(this.legendNode,this.legendWidget,this.chartWidget,this.legendVertical);
-}
-if(this.gridNode){
-this.gridWidget=_3a(this.gridNode,this.gridWidget,this.preparedstore,this.query,this.queryOptions);
-}
-if(this.titleNode){
-_42(this.titleNode,this.preparedstore);
-}
-if(this.footerNode){
-_45(this.footerNode,this.preparedstore);
-}
-}
-},getChartWidget:function(){
-return this.chartWidget;
-},getGridWidget:function(){
-return this.gridWidget;
-},destroy:function(){
-this.cancelRefresh();
-if(this.chartWidget){
-this.chartWidget.destroy();
-this.chartWidget=undefined;
-}
-if(this.legendWidget){
-this.legendWidget=undefined;
-}
-if(this.gridWidget){
-this.gridWidget=undefined;
-}
-if(this.chartNode){
-this.chartNode.innerHTML="";
-}
-if(this.legendNode){
-this.legendNode.innerHTML="";
-}
-if(this.gridNode){
-this.gridNode.innerHTML="";
-}
-if(this.titleNode){
-this.titleNode.innerHTML="";
-}
-if(this.footerNode){
-this.footerNode.innerHTML="";
-}
-}});
+	
+	// sort out the labels for the independent axis of the chart
+	var getLabels = function(range, labelMod, charttype, domNode){
+		
+		// prepare labels for the independent axis
+		var labels = [];
+		// add empty label, hack
+		labels[0] = {value: 0, text: ''};
+
+		var nlabels = range.length;
+
+		// auto-set labelMod for horizontal charts if the labels will otherwise collide
+		if((charttype !== "ClusteredBars") && (charttype !== "StackedBars")){
+    		var cwid = domNode.offsetWidth;
+    		var tmp = ("" + range[0]).length * range.length * 7; // *assume* 7 pixels width per character ( was 9 )
+    	  
+    		if(labelMod == 1){
+    			for(var z = 1; z < 500; ++z){
+    				if((tmp / z) < cwid){
+    					break;
+    				}
+    				++labelMod;
+    			}
+    		}
+	    }
+
+		// now set the labels
+		for(var i = 0; i < nlabels; i++){
+			//sparse labels
+			labels.push({
+				value: i + 1,
+				text: (!labelMod || i % labelMod) ? "" : range[i]
+			});
+		}
+		
+		// add empty label again, hack
+		labels.push({value: nlabels + 1, text:''});
+		
+		return labels;
+	};
+	
+	// get the configuration of an independent axis for the chart
+	var getIndependentAxisArgs = function(charttype, labels){
+
+		var args = { vertical: false, labels: labels, min: 0, max: labels.length-1, majorTickStep: 1, minorTickStep: 1 };
+		
+		// clustered or stacked bars have a vertical independent axis 
+		if((charttype === "ClusteredBars") || (charttype === "StackedBars")){
+			args.vertical = true;
+		}
+		
+		// lines, areas and stacked areas don't need the extra slots at each end
+		if((charttype === "Lines") || (charttype === "Areas") || (charttype === "StackedAreas")){
+			args.min++;
+			args.max--;
+		}
+
+		return args;
+	};
+
+	// get the configuration of a dependent axis for the chart
+	var getDependentAxisArgs = function(charttype, axistype, minval, maxval){
+		
+		var args = { vertical: true, fixLower: "major", fixUpper: "major", natural: true };
+		
+		// secondary dependent axis is not left-bottom
+		if(axistype === "secondary"){
+			args.leftBottom = false;
+		}
+
+		// clustered or stacked bars have horizontal dependent axes 
+		if((charttype === "ClusteredBars") || (charttype === "StackedBars")){
+			args.vertical = false;
+		}
+		
+		// ensure axis does not "collapse" for flat series
+		if(minval == maxval){
+			args.min = minval - 1;
+			args.max = maxval + 1;
+		}
+		
+		return args;
+	};
+	
+	// get the configuration of a plot for the chart
+	var getPlotArgs = function(charttype, axistype, animate){
+		
+		var args = { type: charttype, hAxis: "independent", vAxis: "dependent-" + axistype, gap: 4, lines: false, areas: false, markers: false };
+		
+		// clustered or stacked bars have horizontal dependent axes 
+		if((charttype === "ClusteredBars") || (charttype === "StackedBars")){
+			args.hAxis = args.vAxis;
+			args.vAxis = "independent";
+		}
+
+		// turn on lines for Lines, Areas and StackedAreas 
+		if((charttype === "Lines") || (charttype === "Hybrid-Lines") || (charttype === "Areas") || (charttype === "StackedAreas")){
+			args.lines = true;
+		}
+		
+		// turn on areas for Areas and StackedAreas 
+		if((charttype === "Areas") || (charttype === "StackedAreas")){
+			args.areas = true;
+		}
+		
+		// turn on markers and shadow for Lines 
+		if(charttype === "Lines"){
+			args.markers = true;
+		}
+		
+		// turn on shadow for Hybrid-Lines 
+		// also, Hybrid-Lines is not a true chart type: use Lines for the actual plot
+		if(charttype === "Hybrid-Lines"){
+			args.shadows = {dx: 2, dy: 2, dw: 2};
+			args.type = "Lines";
+		}
+		
+		// also, Hybrid-ClusteredColumns is not a true chart type: use ClusteredColumns for the actual plot
+		if(charttype === "Hybrid-ClusteredColumns"){
+			args.type = "ClusteredColumns";
+		}
+		
+		// enable animation on the plot if animation is requested
+		if(animate){
+			args.animate = animate;
+		}
+		
+		return args;
+	};
+
+	// set up a chart presentation
+	var setupChart = function(/*DomNode*/domNode, /*Object?*/chart, /*String*/type, /*Boolean*/reverse, /*Object*/animate, /*Integer*/labelMod, /*String*/theme, /*String*/tooltip, /*Object?*/store, /*String?*/query, /*String?*/queryOptions){
+		var _chart = chart;
+		
+		if(!_chart){
+			domNode.innerHTML = "";  // any other content in the node disrupts the chart rendering
+			_chart = new dojox.charting.Chart2D(domNode);
+		}
+		
+		// set the theme
+		if(theme){
+
+			// workaround for a theme bug: its _clone method
+			// does not transfer the markers, so we repair
+			// that omission here
+			// FIXME this should be removed once the theme bug is fixed
+	        theme._clone = function(){
+			      var result = new dojox.charting.Theme({
+			        chart: this.chart,
+			        plotarea: this.plotarea,
+			        axis: this.axis,
+			        series: this.series,
+			        marker: this.marker,
+			        antiAlias: this.antiAlias,
+			        assignColors: this.assignColors,
+			        assignMarkers: this.assigneMarkers,
+			        colors: dojo.delegate(this.colors)
+			      });
+			      
+			      result.markers = this.markers;
+			      result._buildMarkerArray();
+			      
+			      return result;
+	        };
+			
+			_chart.setTheme(theme);
+		}
+
+		var range = store.series_data[0].slice(0);
+		
+		// reverse the labels if requested
+		if(reverse){
+			range.reverse();
+		}
+			
+		var labels = getLabels(range, labelMod, type, domNode);
+
+		// collect details of whether primary and/or secondary axes are required 
+		// and what plots we have instantiated using each type of axis
+		var plots = {};
+		
+		// collect maximum and minimum data values
+		var maxval = null;
+		var minval = null;
+		
+		var seriestoremove = {};
+		for(var sname in _chart.runs){
+			seriestoremove[sname] = true;
+		}
+
+		// set x values & max data value
+		var nseries = store.series_name.length;
+		for(var i = 0; i < nseries; i++){
+			// only include series with chart=true and with some data values in
+			if(store.series_chart[i] && (store.series_data[i].length > 0)){
+
+				var charttype = type;
+				var axistype = store.series_axis[i];
+
+				if(charttype == "Hybrid"){
+					if(store.series_charttype[i] == 'line'){
+						charttype = "Hybrid-Lines";
+					}else{
+						charttype = "Hybrid-ClusteredColumns";
+					}
+				}
+				
+				// ensure we have recorded that we are using this axis type
+				if(!plots[axistype]){
+					plots[axistype] = {};
+				}
+				
+				// ensure we have the correct type of plot for this series
+				if(!plots[axistype][charttype]){
+					var axisname = axistype + "-" + charttype;
+					
+					// create the plot and enable tooltips
+					_chart.addPlot(axisname, getPlotArgs(charttype, axistype, animate));
+
+					var tooltipArgs = {};
+					if(typeof tooltip == 'string'){
+						tooltipArgs.text = function(o){
+							var substitutions = [o.element, o.run.name, range[o.index], ((charttype === "ClusteredBars") || (charttype === "StackedBars")) ? o.x : o.y];
+							return dojo.replace(tooltip, substitutions);  // from Dojo 1.4 onward
+							//return tooltip.replace(/\{([^\}]+)\}/g, function(_, token){ return dojo.getObject(token, false, substitutions); });  // prior to Dojo 1.4
+						}
+					}else if(typeof tooltip == 'function'){
+						tooltipArgs.text = tooltip;
+					}
+					new dojox.charting.action2d.Tooltip(_chart, axisname, tooltipArgs);
+					
+					// add highlighting, except for lines
+					if(charttype !== "Lines" && charttype !== "Hybrid-Lines"){
+						new dojox.charting.action2d.Highlight(_chart, axisname);
+					}
+					
+					// record that this plot type is now created
+					plots[axistype][charttype] = true;
+				}
+				
+				// extract the series values
+				var xvals = [];
+				var valen = store.series_data[i].length;
+				for(var j = 0; j < valen; j++){
+					var val = store.series_data[i][j];
+					xvals.push(val);
+					if(maxval === null || val > maxval){
+						maxval = val;
+					}
+					if(minval === null || val < minval){
+						minval = val;
+					}
+				}
+					
+				// reverse the values if requested
+				if(reverse){
+					xvals.reverse();
+				}
+
+				var seriesargs = { plot: axistype + "-" + charttype };
+				if(store.series_linestyle[i]){
+					seriesargs.stroke = { style: store.series_linestyle[i] };
+				}
+
+				_chart.addSeries(store.series_name[i], xvals, seriesargs);
+				delete seriestoremove[store.series_name[i]];
+			}
+		}
+		
+		// remove any series that are no longer needed
+		for(sname in seriestoremove){
+			_chart.removeSeries(sname);
+		}
+
+		// create axes
+		_chart.addAxis("independent", getIndependentAxisArgs(type, labels));
+		_chart.addAxis("dependent-primary", getDependentAxisArgs(type, "primary", minval, maxval));
+		_chart.addAxis("dependent-secondary", getDependentAxisArgs(type, "secondary", minval, maxval));
+		
+		return _chart;
+	};		
+
+	// set up a legend presentation
+	var setupLegend = function(/*DomNode*/domNode, /*Legend*/legend, /*Chart2D*/chart, /*Boolean*/horizontal){
+		// destroy any existing legend and recreate
+		var _legend = legend;
+		
+		if(!_legend){
+			_legend = new dojox.charting.widget.Legend({ chart: chart, horizontal: horizontal }, domNode);
+		}else{
+			_legend.refresh();
+		}
+		
+		return _legend;
+	};
+	
+	// set up a grid presentation
+	var setupGrid = function(/*DomNode*/domNode, /*Object?*/grid, /*Object?*/store, /*String?*/query, /*String?*/queryOptions){
+		var _grid = grid || new dojox.grid.DataGrid({}, domNode);		
+		_grid.startup();		
+		_grid.setStore(store, query, queryOptions);
+		
+		var structure = [];
+		for(var ser = 0; ser < store.series_name.length; ser++){
+			// only include series with grid=true and with some data values in
+			if(store.series_grid[ser] && (store.series_data[ser].length > 0)){
+				structure.push({ field: "data." + ser, name: store.series_name[ser], width: "auto", formatter: store.series_gridformatter[ser] });
+			}
+		}
+		
+		_grid.setStructure(structure);
+		
+		return _grid;
+	};
+	
+	// set up a title presentation
+	var setupTitle = function(/*DomNode*/domNode, /*object*/store){
+		if(store.title){
+			domNode.innerHTML = store.title;
+		}
+	};
+	
+	// set up a footer presentation
+	var setupFooter = function(/*DomNode*/domNode, /*object*/store){
+		if(store.footer){
+			domNode.innerHTML = store.footer;
+		}
+	};
+	
+	// obtain a subfield from a field specifier which may contain
+	// multiple levels (eg, "child.foo[36].manacle")
+	var getSubfield = function(/*Object*/object, /*String*/field){
+		var result = object;
+		
+		if(field){			
+			var fragments = field.split(/[.\[\]]+/);
+			for(var frag in fragments){
+				if(result){
+					result = result[fragments[frag]];
+				}
+			}
+		}
+		
+		return result;
+	};
+	
+	dojo.declare("dojox.widget.DataPresentation", null, {
+		//	summary:
+		//
+		//		DataPresentation
+		//
+		//		A widget that connects to a data store in a simple manner,
+		//      and also provides some additional convenience mechanisms
+		//      for connecting to common data sources without needing to
+		//      explicitly construct a Dojo data store. The widget can then
+		//      present the data in several forms: as a graphical chart,
+		//      as a tabular grid, or as display panels presenting meta-data
+		//      (title, creation information, etc) from the data. The
+		//      widget can also create and manage several of these forms
+		//      in one simple construction.
+		//
+		//      Note: this is a first experimental draft and any/all details
+		//      are subject to substantial change in later drafts.
+		//
+		//	example:
+		//
+		//	 	var pres = new dojox.data.DataPresentation("myChartNode", {
+		//	 		type: "chart",
+		//	 		url: "/data/mydata",
+		//          gridNode: "myGridNode"
+		//	 	});
+		//
+		//	properties:
+		//
+		//  store: Object
+		//      Dojo data store used to supply data to be presented. This may
+		//      be supplied on construction or created implicitly based on
+		//      other construction parameters ('data', 'url').
+		//
+		//  query: String
+		//      Query to apply to the Dojo data store used to supply data to
+		//      be presented.
+		//
+		//  queryOptions: String
+		//      Query options to apply to the Dojo data store used to supply
+		//      data to be presented.
+		//
+		//  data: Object
+		//      Data to be presented. If supplied on construction this property
+		//      will override any value supplied for the 'store' property.
+		//
+		//  url: String
+		//      URL to fetch data from in JSON format. If supplied on
+		//      construction this property will override any values supplied
+		//      for the 'store' and/or 'data' properties. Note that the data
+		//      can also be comment-filtered JSON, although this will trigger
+		//      a warning message in the console unless djConfig.useCommentedJson
+		//      has been set to true.
+		//
+		//  urlContent: Object   
+		//      Content to be passed to the URL when fetching data. If a URL has
+		//      not been supplied, this value is ignored.
+		//
+		//  urlError: function
+		//      A function to be called if an error is encountered when fetching
+		//      data from the supplied URL. This function will be supplied with
+		//      two parameters exactly as the error function supplied to the
+		//      dojo.xhrGet function. This function may be called multiple times
+		//      if a refresh interval has been supplied.
+		//
+		//  refreshInterval: Number
+		//      the time interval in milliseconds after which the data supplied
+		//      via the 'data' property or fetched from a URL via the 'url'
+		//      property should be regularly refreshed. This property is
+		//      ignored if neither the 'data' nor 'url' property has been
+		//      supplied. If the refresh interval is zero, no regular refresh is done.
+		//
+		//  refreshIntervalPending:
+		//      the JavaScript set interval currently in progress, if any
+		//
+		//  series: Array
+		//      an array of objects describing the data series to be included
+		//      in the data presentation. Each object may contain the 
+		//      following fields:
+		//			datapoints: the name of the field from the source data which
+		//				contains an array of the data points for this data series.
+		//				If not supplied, the source data is assumed to be an array
+		//				of data points to be used.
+		//			field: the name of the field within each data point which
+		//				contains the data for this data series. If not supplied,
+		//				each data point is assumed to be the value for the series.
+		//      	name: a name for the series, used in the legend and grid headings
+		//          namefield: the name of the field from the source data which
+		//              contains the name the series, used in the legend and grid
+		//              headings. If both name and namefield are supplied, name takes
+		//              precedence. If neither are supplied, a default name is used.
+		//			chart: true if the series should be included in a chart presentation (default: true)
+		//          charttype: the type of presentation of the series in the chart, which can be
+		//				"range", "line", "bar" (default: "bar")
+		//          linestyle: the stroke style for lines (if applicable) (default: "Solid")
+		//          axis: the dependant axis to which the series will be attached in the chart,
+		//              which can be "primary" or "secondary"
+		//			grid: true if the series should be included in a data grid presentation (default: true)
+		//			gridformatter: an optional formatter to use for this series in the data grid
+		//
+		//      a call-back function may alternatively be supplied. The function takes
+		//      a single parameter, which will be the data (from the 'data' field or
+		//      loaded from the value in the 'url' field), and should return the array
+		//      of objects describing the data series to be included in the data
+		//      presentation. This enables the series structures to be built dynamically
+		//      after data load, and rebuilt if necessary on data refresh. The call-back
+		//      function will be called each time new data is set, loaded or refreshed.
+		//      A call-back function cannot be used if the data is supplied directly
+		//      from a Dojo data store.
+		//
+		//  type: String
+		//      the type of presentation to be applied at the DOM attach point.
+		//      This can be 'chart', 'legend', 'grid', 'title', 'footer'. The
+		//      default type is 'chart'.
+		type: "chart",
+		//
+		//  chartType: String
+		//      the type of chart to display. This can be 'clusteredbars',
+		//      'areas', 'stackedcolumns', 'stackedbars', 'stackedareas',
+		//      'lines', 'hybrid'. The default type is 'bar'.
+		chartType: "clusteredBars",
+		//
+		//  reverse: Boolean
+		//      true if the chart independant axis should be reversed.
+		reverse: false,
+		//
+		//  animate: Object
+		//      if an object is supplied, then the chart bars or columns will animate
+		//      into place. If the object contains a field 'duration' then the value
+		//      supplied is the duration of the animation in milliseconds, otherwise
+		//      a default duration is used. A boolean value true can alternatively be
+		//      supplied to enable animation with the default duration.
+		//      The default is null (no animation).
+		animate: null,
+		//
+		//  labelMod: Integer
+		//      the frequency of label annotations to be included on the
+		//      independent axis. 1=every label. 0=no labels. The default is 1.
+		labelMod: 1,
+		//
+		//  tooltip: String | Function
+		//      a string pattern defining the tooltip text to be applied to chart
+		//      data points, or a function which takes a single parameter and returns
+		//      the tooltip text to be applied to chart data points. The string pattern
+		//      will have the following substitutions applied:
+		//       {0} - the type of chart element ('bar', 'surface', etc)
+		//       {1} - the name of the data series
+		//       {2} - the independent axis value at the tooltip data point
+		//       {3} - the series value at the tooltip data point point
+		//      The function, if supplied, will receive a single parameter exactly
+		//      as per the dojox.charting.action2D.Tooltip class. The default value
+		//      is to apply the default tooltip as defined by the
+		//      dojox.charting.action2D.Tooltip class.
+		//
+		//  legendHorizontal: Boolean | Number
+		//      true if the legend should be rendered horizontally, or a number if
+		//      the legend should be rendered as horizontal rows with that number of
+		//      items in each row, or false if the legend should be rendered
+		//      vertically (same as specifying 1). The default is true (legend
+		//      rendered horizontally).
+		legendHorizontal: true,
+		//
+		//  theme: String|Theme
+		//      a theme to use for the chart, or the name of a theme.
+		//
+		//  chartNode: String|DomNode
+		//      an optional DOM node or the id of a DOM node to receive a
+		//      chart presentation of the data. Supply only when a chart is
+		//      required and the type is not 'chart'; when the type is
+		//      'chart' this property will be set to the widget attach point.
+		//
+		//  legendNode: String|DomNode
+		//      an optional DOM node or the id of a DOM node to receive a
+		//      chart legend for the data. Supply only when a legend is
+		//      required and the type is not 'legend'; when the type is
+		//      'legend' this property will be set to the widget attach point.
+		//
+		//  gridNode: String|DomNode
+		//      an optional DOM node or the id of a DOM node to receive a
+		//      grid presentation of the data. Supply only when a grid is
+		//      required and the type is not 'grid'; when the type is
+		//      'grid' this property will be set to the widget attach point.
+		//
+		//  titleNode: String|DomNode
+		//      an optional DOM node or the id of a DOM node to receive a
+		//      title for the data. Supply only when a title is
+		//      required and the type is not 'title'; when the type is
+		//      'title' this property will be set to the widget attach point.
+		//
+		//  footerNode: String|DomNode
+		//      an optional DOM node or the id of a DOM node to receive a
+		//      footer presentation of the data. Supply only when a footer is
+		//      required and the type is not 'footer'; when the type is
+		//      'footer' this property will be set to the widget attach point.
+		//
+		//  chartWidget: Object
+		//      the chart widget, if any
+		//
+		//  legendWidget: Object
+		//      the legend widget, if any
+		//
+		//  gridWidget: Object
+		//      the grid widget, if any
+		
+		constructor: function(node, args){
+			// summary:
+			//		Set up properties and initialize.
+			//
+			//	arguments:
+			//		node: DomNode
+			//			The node to attach the data presentation to.
+			//		kwArgs:	Object (see above)
+			
+			// apply arguments directly
+			dojo.mixin(this, args);
+
+			// store our DOM attach point
+			this.domNode = dojo.byId(node);
+			
+			// also apply the DOM attach point as the node for the presentation type
+			this[this.type + "Node"] = this.domNode;
+			
+			// load the theme if provided by name
+			if(typeof this.theme == 'string'){
+				this.theme = dojo.getObject(this.theme);
+			}
+			
+			// resolve any the nodes that were supplied as ids
+			this.chartNode = dojo.byId(this.chartNode);
+			this.legendNode = dojo.byId(this.legendNode);
+			this.gridNode = dojo.byId(this.gridNode);
+			this.titleNode = dojo.byId(this.titleNode);
+			this.footerNode = dojo.byId(this.footerNode);
+			
+			// we used to support a 'legendVertical' so for now
+			// at least maintain backward compatibility
+			if(this.legendVertical){
+				this.legendHorizontal = !this.legendVertical;
+			}
+			
+			if(this.url){
+				this.setURL(null, null, this.refreshInterval);
+			}
+			else{
+				if(this.data){
+					this.setData(null, this.refreshInterval);
+				}
+				else{
+					this.setStore();
+				}
+			}
+		},
+		
+		setURL: function(/*String?*/url, /*Object?*/ urlContent, /*Number?*/refreshInterval){
+			// summary:
+			//      Sets the URL to fetch data from, with optional content
+			//      supplied with the request, and an optional
+			//      refresh interval in milliseconds (0=no refresh)
+
+			// if a refresh interval is supplied we will start a fresh
+			// refresh after storing the supplied url
+			if(refreshInterval){
+				this.cancelRefresh();
+			}
+			
+			this.url = url || this.url;
+			this.urlContent = urlContent || this.urlContent;
+			this.refreshInterval = refreshInterval || this.refreshInterval;
+			
+			var me = this;
+			
+			dojo.xhrGet({
+				url: this.url,
+				content: this.urlContent,
+				handleAs: 'json-comment-optional',
+				load: function(response, ioArgs){
+					me.setData(response);
+				},
+				error: function(xhr, ioArgs){
+					if(me.urlError && (typeof me.urlError == "function")){
+						me.urlError(xhr, ioArgs);
+					}
+				}
+			});
+			
+			if(refreshInterval && (this.refreshInterval > 0)){
+				this.refreshIntervalPending = setInterval(function(){
+					me.setURL();
+				}, this.refreshInterval);
+			}
+		},
+		
+		setData: function(/*Object?*/data, /*Number?*/refreshInterval){
+			// summary:
+			//      Sets the data to be presented, and an optional
+			//      refresh interval in milliseconds (0=no refresh)
+			
+			// if a refresh interval is supplied we will start a fresh
+			// refresh after storing the supplied data reference
+			if(refreshInterval){
+				this.cancelRefresh();
+			}
+			
+			this.data = data || this.data;
+			this.refreshInterval = refreshInterval || this.refreshInterval;
+			
+			// TODO if no 'series' property was provided, build one intelligently here
+			// (until that is done, a 'series' property must be supplied)
+			
+			var _series = (typeof this.series == 'function') ? this.series(this.data) : this.series;
+
+			var datasets = [],
+				series_data = [],
+				series_name = [],
+				series_chart = [],
+				series_charttype = [],
+				series_linestyle = [],
+				series_axis = [],
+				series_grid = [],
+				series_gridformatter = [],
+				maxlen = 0;
+			
+			// identify the dataset arrays in which series values can be found
+			for(var ser = 0; ser < _series.length; ser++){
+				datasets[ser] = getSubfield(this.data, _series[ser].datapoints);
+				if(datasets[ser] && (datasets[ser].length > maxlen)){
+					maxlen = datasets[ser].length;
+				}
+				
+				series_data[ser] = [];
+				// name can be specified in series structure, or by field in series structure, otherwise use a default
+				series_name[ser] = _series[ser].name || (_series[ser].namefield ? getSubfield(this.data, _series[ser].namefield) : null) || ("series " + ser);
+				series_chart[ser] = (_series[ser].chart !== false);
+				series_charttype[ser] = _series[ser].charttype || "bar";
+				series_linestyle[ser] = _series[ser].linestyle;
+				series_axis[ser] = _series[ser].axis || "primary";
+				series_grid[ser] = (_series[ser].grid !== false);
+				series_gridformatter[ser] = _series[ser].gridformatter;
+			}
+		
+			// create an array of data points by sampling the series
+			// and an array of series arrays by collecting the series
+			// each data point has an 'index' item containing a sequence number
+			// and items named "data.0", "data.1", ... containing the series samples
+			// and the first data point also has items named "name.0", "name.1", ... containing the series names
+			// and items named "series.0", "series.1", ... containing arrays with the complete series in
+			var point, datapoint, datavalue, fdatavalue;
+			var datapoints = [];
+			
+			for(point = 0; point < maxlen; point++){
+				datapoint = { index: point };
+				for(ser = 0; ser < _series.length; ser++){
+					if(datasets[ser] && (datasets[ser].length > point)){
+						datavalue = getSubfield(datasets[ser][point], _series[ser].field);
+						
+						if(series_chart[ser]){
+							// convert the data value to a float if possible
+							fdatavalue = parseFloat(datavalue);						
+							if(!isNaN(fdatavalue)){
+								datavalue = fdatavalue;
+							}
+						}
+						
+						datapoint["data." + ser] = datavalue;
+						series_data[ser].push(datavalue);
+					}
+				}
+				datapoints.push(datapoint);
+			}
+
+			if(maxlen <= 0){
+				datapoints.push({index: 0});
+			}
+		
+			// now build a prepared store from the data points we've constructed
+			var store = new dojo.data.ItemFileWriteStore({ data: { identifier: 'index', items: datapoints }});
+			if(this.data.title){
+				store.title = this.data.title;
+			}
+			if(this.data.footer){
+				store.footer = this.data.footer;
+			}
+			
+			store.series_data = series_data;
+			store.series_name = series_name; 
+			store.series_chart = series_chart; 
+			store.series_charttype = series_charttype; 
+			store.series_linestyle = series_linestyle; 
+			store.series_axis = series_axis; 
+			store.series_grid = series_grid; 
+			store.series_gridformatter = series_gridformatter;
+			
+			this.setPreparedStore(store);			
+			
+			if(refreshInterval && (this.refreshInterval > 0)){
+				var me = this;
+				this.refreshIntervalPending = setInterval(function(){
+					me.setData();
+				}, this.refreshInterval);
+			}
+		},
+		
+		refresh: function(){
+			// summary:
+			//      If a URL or data has been supplied, refreshes the
+			//      presented data from the URL or data. If a refresh
+			//      interval is also set, the periodic refresh is
+			//      restarted. If a URL or data was not supplied, this
+			//      method has no effect.
+			if(this.url){
+				this.setURL(this.url, this.urlContent, this.refreshInterval);
+			}else if(this.data){
+				this.setData(this.data, this.refreshInterval);
+			}
+		},
+		
+		cancelRefresh: function(){
+			// summary:
+			//      Cancels any and all outstanding data refreshes
+			if(this.refreshIntervalPending){
+				// cancel existing refresh
+				clearInterval(this.refreshIntervalPending);
+				this.refreshIntervalPending = undefined;
+			}
+		},
+	
+		setStore: function(/*Object?*/store, /*String?*/query, /*Object?*/queryOptions){
+			// FIXME build a prepared store properly -- this requires too tight a convention to be followed to be useful
+			this.setPreparedStore(store, query, queryOptions);
+		},
+		
+		setPreparedStore: function(/*Object?*/store, /*String?*/query, /*Object?*/queryOptions){
+			// summary:
+			//		Sets the store and query.
+			//
+			this.preparedstore = store || this.store;
+			this.query = query || this.query;
+			this.queryOptions = queryOptions || this.queryOptions;
+			
+			if(this.preparedstore){
+				if(this.chartNode){
+					this.chartWidget = setupChart(this.chartNode, this.chartWidget, this.chartType, this.reverse, this.animate, this.labelMod, this.theme, this.tooltip, this.preparedstore, this.query, this,queryOptions);
+					this.renderChartWidget();
+				}
+				if(this.legendNode){
+					this.legendWidget = setupLegend(this.legendNode, this.legendWidget, this.chartWidget, this.legendHorizontal);
+				}
+				if(this.gridNode){
+					this.gridWidget = setupGrid(this.gridNode, this.gridWidget, this.preparedstore, this.query, this.queryOptions);
+					this.renderGridWidget();
+				}
+				if(this.titleNode){
+					setupTitle(this.titleNode, this.preparedstore);
+				}
+				if(this.footerNode){
+					setupFooter(this.footerNode, this.preparedstore);
+				}
+			}
+		},
+		
+		renderChartWidget: function(){
+			// summary:
+			//      Renders the chart widget (if any). This method is
+			//      called whenever a chart widget is created or
+			//      configured, and may be connected to.
+			if(this.chartWidget){
+				this.chartWidget.render();
+			}
+		},
+		
+		renderGridWidget: function(){
+			// summary:
+			//      Renders the grid widget (if any). This method is
+			//      called whenever a grid widget is created or
+			//      configured, and may be connected to.
+			if(this.gridWidget){
+				this.gridWidget.render();
+			}
+		},
+		
+		getChartWidget: function(){
+			// summary:
+			//      Returns the chart widget (if any) created if the type
+			//      is "chart" or the "chartNode" property was supplied.
+			return this.chartWidget;
+		},
+		
+		getGridWidget: function(){
+			// summary:
+			//      Returns the grid widget (if any) created if the type
+			//      is "grid" or the "gridNode" property was supplied.
+			return this.gridWidget;
+		},
+		
+		destroy: function(){
+			// summary:
+			//		Destroys the widget and all components and resources.
+
+			// cancel any outstanding refresh requests
+			this.cancelRefresh();
+			
+			if(this.chartWidget){
+				this.chartWidget.destroy();
+				delete this.chartWidget;
+			}
+			
+			if(this.legendWidget){
+				// no legend.destroy()
+				delete this.legendWidget;				
+			}
+
+			if(this.gridWidget){
+				// no grid.destroy()
+				delete this.gridWidget;
+			}
+			
+			if(this.chartNode){
+				this.chartNode.innerHTML = "";
+			}
+			
+			if(this.legendNode){
+				this.legendNode.innerHTML = "";
+			}
+			
+			if(this.gridNode){
+				this.gridNode.innerHTML = "";
+			}
+			
+			if(this.titleNode){
+				this.titleNode.innerHTML = "";
+			}
+			
+			if(this.footerNode){
+				this.footerNode.innerHTML = "";
+			}
+		}
+		
+	});
+		
 })();
-}
diff --git a/dojox/widget/Dialog.js b/dojox/widget/Dialog.js
index 00af40d..5ed3fdf 100644
--- a/dojox/widget/Dialog.js
+++ b/dojox/widget/Dialog.js
@@ -1,86 +1,249 @@
-/*
-	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
-*/
+dojo.provide('dojox.widget.Dialog');
+dojo.experimental('dojox.widget.Dialog');
 
-
-if(!dojo._hasResource["dojox.widget.Dialog"]){
-dojo._hasResource["dojox.widget.Dialog"]=true;
-dojo.provide("dojox.widget.Dialog");
-dojo.experimental("dojox.widget.Dialog");
-dojo.require("dijit.Dialog");
+dojo.require("dojo.window");
+dojo.require('dijit.Dialog');
 dojo.require("dojox.layout.ContentPane");
-dojo.require("dojox.fx");
-dojo.declare("dojox.widget.Dialog",[dojox.layout.ContentPane,dijit._DialogBase],{templateString:dojo.cache("dojox.widget","Dialog/Dialog.html","<div class=\"dojoxDialog\" tabindex=\"-1\" waiRole=\"dialog\" waiState=\"labelledby-${id}_title\">\n\t<div dojoAttachPoint=\"titleBar\" class=\"dojoxDialogTitleBar\">\n\t\t<span dojoAttachPoint=\"titleNode\" class=\"dojoxDialogTitle\" id=\"${id}_title\">${title}</span>\n\t</div>\n\t<div dojoAttachPoint=\"dojoxDialogWrapper\">\n\t\t<div dojoAttach [...]
-this.easing=_1.easing||dojo._defaultEasing;
-this.dimensions=_1.dimensions||[300,300];
-},_setup:function(){
-this.inherited(arguments);
-if(!this._alreadyInitialized){
-this._navIn=dojo.fadeIn({node:this.closeButtonNode});
-this._navOut=dojo.fadeOut({node:this.closeButtonNode});
-if(!this.showTitle){
-dojo.addClass(this.domNode,"dojoxDialogNoTitle");
-}
-}
-},layout:function(e){
-this._setSize();
-this.inherited(arguments);
-},_setSize:function(){
-this._vp=dijit.getViewport();
-var tc=this.containerNode,_3=this.sizeToViewport;
-return this._displaysize={w:_3?tc.scrollWidth:this.dimensions[0],h:_3?tc.scrollHeight:this.dimensions[1]};
-},show:function(){
-if(this.open){
-return;
-}
-this._setSize();
-dojo.style(this.closeButtonNode,"opacity",0);
-dojo.style(this.domNode,{overflow:"hidden",opacity:0,width:"1px",height:"1px"});
-dojo.style(this.containerNode,{opacity:0,overflow:"hidden"});
-this.inherited(arguments);
-if(this.modal){
-this._modalconnects.push(dojo.connect(dojo.body(),"onkeypress",function(e){
-if(e.charOrCode==dojo.keys.ESCAPE){
-dojo.stopEvent(e);
-}
-}));
-}else{
-this._modalconnects.push(dojo.connect(dijit._underlay.domNode,"onclick",this,"onCancel"));
-}
-this._modalconnects.push(dojo.connect(this.domNode,"onmouseenter",this,"_handleNav"));
-this._modalconnects.push(dojo.connect(this.domNode,"onmouseleave",this,"_handleNav"));
-},_handleNav:function(e){
-var _4="_navOut",_5="_navIn",_6=(e.type=="mouseout"?_5:_4),_7=(e.type=="mouseout"?_4:_5);
-this[_6].stop();
-this[_7].play();
-},_position:function(){
-if(!this._started){
-return;
-}
-if(this._sizing){
-this._sizing.stop();
-this.disconnect(this._sizingConnect);
-delete this._sizing;
-}
-this.inherited(arguments);
-if(!this.open){
-dojo.style(this.containerNode,"opacity",0);
-}
-var _8=this.viewportPadding*2;
-var _9={node:this.domNode,duration:this.sizeDuration||dijit._defaultDuration,easing:this.easing,method:this.sizeMethod};
-var ds=this._displaysize||this._setSize();
-_9["width"]=ds.w=(ds.w+_8>=this._vp.w||this.sizeToViewport)?this._vp.w-_8:ds.w;
-_9["height"]=ds.h=(ds.h+_8>=this._vp.h||this.sizeToViewport)?this._vp.h-_8:ds.h;
-this._sizing=dojox.fx.sizeTo(_9);
-this._sizingConnect=this.connect(this._sizing,"onEnd","_showContent");
-this._sizing.play();
-},_showContent:function(e){
-var _a=this.containerNode;
-dojo.style(this.domNode,{overflow:"visible",opacity:1});
-dojo.style(this.closeButtonNode,"opacity",1);
-dojo.style(_a,{height:this._displaysize.h-this.titleNode.offsetHeight+"px",width:this._displaysize.w+"px",overflow:"auto"});
-dojo.anim(_a,{opacity:1});
-}});
-}
+
+dojo.require('dojox.fx');
+
+dojo.declare('dojox.widget.Dialog', 
+	[dojox.layout.ContentPane, dijit._DialogBase], 
+	{
+	// summary:
+	//		A Lightbox-like Modal-dialog for HTML Content
+	//
+	// description:
+	//		An HTML-capable Dialog widget with advanced sizing 
+	//		options, animated show/hide and other useful options.
+	//		
+	//		This Dialog is also very easy to apply custom styles to.
+	//		
+	//		It works identically to a `dijit.Dialog` with several 
+	//		additional parameters.
+	
+	templateString: dojo.cache('dojox.widget','Dialog/Dialog.html'),
+	
+	// sizeToViewport: Boolean
+	//		If true, fix the size of the dialog to the Viewport based on 
+	//		viewportPadding value rather than the calculated or natural 
+	//		stlye. If false, base the size on a passed dimension attribute.
+	//		Eitherway, the viewportPadding value is used if the the content
+	//		extends beyond the viewport size for whatever reason.
+	sizeToViewport: false,
+	
+	// viewportPadding: Integer
+	//		If sizeToViewport="true", this is the amount of padding in pixels to leave 
+	//    between the dialog border and the viewport edge.
+	//    This value is also used when sizeToViewport="false" and dimensions exceeded
+	//    by dialog content to ensure dialog does not go outside viewport boundary
+	//		 
+	viewportPadding: 35,
+	
+	// dimensions: Array
+	//		A two-element array of [widht,height] to animate the Dialog to if sizeToViewport="false"
+	//    Defaults to [300,300]
+	dimensions: null, 
+	
+	// easing: Function?|String?
+	//		An easing function to apply to the sizing animation. 
+	easing: null,
+	
+	// sizeDuration: Integer
+	//		Time (in ms) to use in the Animation for sizing. 
+	sizeDuration: dijit._defaultDuration,
+	
+	// sizeMethod: String
+	// 		To be passed to dojox.fx.sizeTo, one of "chain" or "combine" to effect
+	//		the animation sequence.
+	sizeMethod: "chain",
+	
+	// showTitle: Boolean
+	//		Toogle to show or hide the Title area. Can only be set at startup.
+	showTitle: false,
+	
+	// draggable: Boolean
+	//		Make the pane draggable. Differs from dijit.Dialog by setting default to false
+	draggable: false, // simply over-ride the default from dijit.Dialog 
+	
+	// modal: Boolean
+	// 		If true, this Dialog instance will be truly modal and prevent closing until
+	//		explicitly told to by calling hide() - Defaults to false to preserve previous
+	// 		behaviors.
+	modal: false,
+	
+	constructor: function(props, node){
+		this.easing = props.easing || dojo._defaultEasing; 
+		this.dimensions = props.dimensions || [300, 300];
+	},
+	
+	_setup: function(){
+		// summary: Piggyback on dijit.Dialog's _setup for load-time options, deferred to 
+		//		
+		this.inherited(arguments);
+		if(!this._alreadyInitialized){			
+			this._navIn = dojo.fadeIn({ node: this.closeButtonNode });
+			this._navOut = dojo.fadeOut({ node: this.closeButtonNode }); 
+			if(!this.showTitle){
+				dojo.addClass(this.domNode,"dojoxDialogNoTitle");
+			}
+		}	
+	},
+	
+	layout: function(e){
+		this._setSize();
+		this.inherited(arguments);
+	},
+	
+	_setSize: function(){
+		// summary: cache and set our desired end position 
+		this._vp = dojo.window.getBox();
+		var tc = this.containerNode,
+			vpSized = this.sizeToViewport
+		;
+		return this._displaysize = {
+			w: vpSized ? tc.scrollWidth : this.dimensions[0],
+			h: vpSized ? tc.scrollHeight : this.dimensions[1]
+		}; // Object
+	},
+	
+	show: function(){
+		if(this.open){ return; }
+		
+		this._setSize();
+		dojo.style(this.closeButtonNode,"opacity", 0);
+		dojo.style(this.domNode, {
+			overflow: "hidden",
+			opacity: 0,
+			width: "1px",
+			height: "1px"
+		});
+		dojo.style(this.containerNode, {
+			opacity: 0,
+			overflow: "hidden"
+		});	
+		
+		this.inherited(arguments);
+
+		if(this.modal){
+			// prevent escape key from closing dialog
+			// connect to body to trap this event from the Dialog a11y code, and stop escape key
+			// from doing anything in the modal:true case:
+			this._modalconnects.push(dojo.connect(dojo.body(), "onkeypress", function(e){
+				if(e.charOrCode == dojo.keys.ESCAPE){
+					dojo.stopEvent(e);
+				}
+			}));
+		}else{
+			// otherwise, allow clicking on the underlay to close
+			this._modalconnects.push(dojo.connect(dijit._underlay.domNode, "onclick", this, "onCancel"));
+		}
+		this._modalconnects.push(dojo.connect(this.domNode,"onmouseenter",this,"_handleNav"));
+		this._modalconnects.push(dojo.connect(this.domNode,"onmouseleave",this,"_handleNav"));
+		
+	},
+	
+	_handleNav: function(e){
+		// summary: Handle's showing or hiding the close icon
+
+		var navou = "_navOut", 
+			navin = "_navIn",
+			animou = (e.type == "mouseout" ? navin : navou),
+			animin = (e.type == "mouseout" ? navou : navin)
+		;
+		
+		this[animou].stop();
+		this[animin].play();
+		
+	},
+	
+	// an experiment in a quicksilver-like hide. too choppy for me.
+	/*
+	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;
+		}
+
+		this._fadeIn && this._fadeIn.stop();
+
+		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;	
+		}
+		
+		dojox.fx.sizeTo({ 
+			node: this.domNode,
+			duration:this.sizeDuration || this.duration,
+			width: this._vp.w - 1,
+			height: 5,
+			onBegin: dojo.hitch(this,function(){
+				this._fadeOut.play(this.sizeDuration / 2);
+			})
+		}).play();
+		
+		this.open = false;
+	}, */
+
+	_position: function(){
+		
+		if(!this._started){ return; } // prevent content: from firing this anim #8914
+		
+		if(this._sizing){
+			this._sizing.stop();	
+			this.disconnect(this._sizingConnect);
+			delete this._sizing; 
+		}
+		
+		this.inherited(arguments);
+		
+		if(!this.open){ dojo.style(this.containerNode, "opacity", 0); }
+		var pad = this.viewportPadding * 2; 
+		
+		var props = {
+			node: this.domNode,
+			duration: this.sizeDuration || dijit._defaultDuration,
+			easing: this.easing,
+			method: this.sizeMethod
+		};
+
+		var ds = this._displaysize || this._setSize();
+		props['width'] = ds.w = (ds.w + pad >= this._vp.w || this.sizeToViewport) 
+			? this._vp.w - pad : ds.w;
+			
+		props['height'] = ds.h = (ds.h + pad >= this._vp.h || this.sizeToViewport) 
+			? this._vp.h - pad : ds.h;
+		
+		this._sizing = dojox.fx.sizeTo(props);
+		this._sizingConnect = this.connect(this._sizing,"onEnd","_showContent");
+		this._sizing.play();
+
+	},
+
+	_showContent: function(e){
+		// summary: Show the inner container after sizing animation
+
+		var container = this.containerNode;
+		dojo.style(this.domNode, {
+			overflow: "visible",
+			opacity: 1
+		});
+		dojo.style(this.closeButtonNode,"opacity",1);
+		dojo.style(container, {
+			height: this._displaysize.h - this.titleNode.offsetHeight + "px",
+			width: this._displaysize.w + "px",
+			overflow:"auto"
+		});
+		dojo.anim(container, { opacity:1 });
+	}
+	
+});
\ No newline at end of file
diff --git a/dojox/widget/Dialog/Dialog.css b/dojox/widget/Dialog/Dialog.css
index cc073d5..c7fccf1 100644
--- a/dojox/widget/Dialog/Dialog.css
+++ b/dojox/widget/Dialog/Dialog.css
@@ -4,18 +4,22 @@
 	z-index: 999;
 	outline:0;
 }
+
 .dojoxDialog .closeText {
 	display:none;
-	
+	/* for the onhover border in high contrast on IE: */
 	position:absolute;
 }
+
 .dojoxDialogFixed div.dojoxDialogTitleBar {
 	cursor:default; 
 }
+
 .dojoxDialogWrapper {
 	left: 0;
 	top: 0;
 }
+
 .dojoxDialog {
 	background: #fff;
 	-webkit-box-shadow: 0px 5px 10px #adadad;
@@ -24,22 +28,25 @@
 	border:1px solid #b7b7b7;
 	padding:1.5em 3px 3px 3px;
 }
+
 .dojoxDialogFocused {
 	border:1px solid #ccc;
 }
+
 .dojoxDialog .dojoxDialogPaneContent {
 	border:none;
 	padding:0;
 }
+
 .dojoxDialogTitleBar {
-	
+	/* outer container for the titlebar of the dialog */
 	cursor:move;
 	top:0;
 	left:0;
 	right:0;
 	background:#ededed;
 	height:1.5em;
-	outline:0; 
+	outline:0; /* remove this line if keyboard focus on dialog startup is an issue. tab still takes you to first focusable element */
 	-moz-border-radius-topleft:8pt;
 	-moz-border-radius-topright:8pt;
 	-webkik-border-radius-topleft:7pt;
@@ -48,23 +55,30 @@
 .dj_webkit .dojoxDialogTitleBar {
 	border:1px solid #ccc;
 }
+
 .dojoxDialogNoTitle .dojoxDialogTitleBar {
 	display:none;
 }
+
 .dojoxDialogContent {
-	
+	/* the body of the dialog */
 	padding: 3px;
 	margin-top:1.2em;
 }
+
+/* pseudo-tundra-like */
+
 .dojoxDialogTitle {
 	font-weight: bold;
 	padding: 8px 12px 8px 12px;
 	outline:0;
 	border-bottom:#b7b7b7;
 }
+
 div.dojoxDialogNoTitle {
 	padding-top:9px;
 }
+
 .dojoxDialogCloseIcon {
 	background : url("images/dialogCloseButton.png") no-repeat top right;
 	position: absolute;
@@ -79,6 +93,14 @@ div.dojoxDialogNoTitle {
 .dj_ie6 .dojoxDialogCloseIcon {
 	background-image: url("images/dialogCloseButton.gif");
 }
+
+.dojoxDialog .dijitDialogCloseIconHover {
+    background-image: url("images/dialogCloseButton.png");
+}
+.dj_ie6 .dojoxDialog .dijitDialogCloseIconHover {
+    background-image: url("images/dialogCloseButton.gif");
+}
+
 .dojoxDialogNoTitle .dojoxDialogCloseIcon {
 	top: -15px;
 	left: -15px;
diff --git a/dojox/widget/DocTester.js b/dojox/widget/DocTester.js
index f393ce2..fb905f8 100644
--- a/dojox/widget/DocTester.js
+++ b/dojox/widget/DocTester.js
@@ -1,70 +1,86 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.DocTester"]){
-dojo._hasResource["dojox.widget.DocTester"]=true;
 dojo.provide("dojox.widget.DocTester");
+
 dojo.require("dojo.string");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dojox.form.BusyButton");
 dojo.require("dojox.testing.DocTest");
-dojo.declare("dojox.widget.DocTester",[dijit._Widget,dijit._Templated],{templateString:dojo.cache("dojox.widget","DocTester/DocTester.html","<div dojoAttachPoint=\"domNode\" class=\"dojoxDocTester\">\n\t<div dojoAttachPoint=\"containerNode\"></div>\n\t<button dojoType=\"dojox.form.BusyButton\" busyLabel=\"Testing...\" dojoAttachPoint=\"runButtonNode\">Run tests</button>\n\t<button dojoType=\"dijit.form.Button\" dojoAttachPoint=\"resetButtonNode\" style=\"display:none;\">Reset</button>\n\ [...]
-var _2=_1.innerHTML;
-this.doctests=new dojox.testing.DocTest();
-this.tests=this.doctests.getTestsFromString(this._unescapeHtml(_2));
-var _3=dojo.map(this.tests,"return item.line-1");
-var _4=_2.split("\n");
-var _5="<div class=\"actualResult\">FAILED, actual result was: <span class=\"result\"></span></div>";
-var _6="<pre class=\"testCase testNum0 odd\">";
-for(var i=0;i<_4.length;i++){
-var _7=dojo.indexOf(_3,i);
-if(_7>0&&_7!=-1){
-var _8=_7%2?"even":"odd";
-_6+=_5;
-_6+="</pre><pre class=\"testCase testNum"+_7+" "+_8+"\">";
-}
-_6+=_4[i].replace(/^\s+/,"")+"\n";
-}
-_6+=_5+"</pre>";
-this.containerNode.innerHTML=_6;
-},postCreate:function(){
-this.inherited("postCreate",arguments);
-dojo.connect(this.runButtonNode,"onClick",dojo.hitch(this,"runTests"));
-dojo.connect(this.resetButtonNode,"onClick",dojo.hitch(this,"reset"));
-this.numTestsNode.innerHTML=this.tests.length;
-},runTests:function(){
-var _9={ok:0,nok:0};
-for(var i=0;i<this.tests.length;i++){
-var _a=this.doctests.runTest(this.tests[i].commands,this.tests[i].expectedResult);
-dojo.query(".testNum"+i,this.domNode).addClass(_a.success?"resultOk":"resultNok");
-if(!_a.success){
-_9.nok++;
-this.numTestsNokNode.innerHTML=_9.nok;
-var _b=dojo.query(".testNum"+i+" .actualResult",this.domNode)[0];
-dojo.style(_b,"display","inline");
-dojo.query(".result",_b)[0].innerHTML=dojo.toJson(_a.actualResult);
-}else{
-_9.ok++;
-this.numTestsOkNode.innerHTML=_9.ok;
-}
-}
-this.runButtonNode.cancel();
-dojo.style(this.runButtonNode.domNode,"display","none");
-dojo.style(this.resetButtonNode.domNode,"display","");
-},reset:function(){
-dojo.style(this.runButtonNode.domNode,"display","");
-dojo.style(this.resetButtonNode.domNode,"display","none");
-this.numTestsOkNode.innerHTML="0";
-this.numTestsNokNode.innerHTML="0";
-dojo.query(".actualResult",this.domNode).style("display","none");
-dojo.query(".testCase",this.domNode).removeClass("resultOk").removeClass("resultNok");
-},_unescapeHtml:function(_c){
-_c=String(_c).replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,"\"");
-return _c;
-}});
-}
+
+dojo.declare('dojox.widget.DocTester', 
+	[dijit._Widget, dijit._Templated],
+	{
+		// summary: A widget to run DocTests inside an HTML page.
+		// 
+		templateString: dojo.cache('dojox.widget','DocTester/DocTester.html'),
+		widgetsInTemplate: true,
+	
+		_fillContent:function(/*DomNode*/source){
+			// summary: Overridden from _Templates.js, which actually just takes care of filling the containerNode.
+			var src = source.innerHTML;
+			this.doctests = new dojox.testing.DocTest();
+			this.tests = this.doctests.getTestsFromString(this._unescapeHtml(src));
+			var lineNumbers = dojo.map(this.tests, 'return item.line-1');
+			var lines = src.split("\n");
+			var actualResultHtml = '<div class="actualResult">FAILED, actual result was: <span class="result"></span></div>';
+			var content = '<pre class="testCase testNum0 odd">';
+			for (var i=0; i<lines.length; i++){
+				var index = dojo.indexOf(lineNumbers, i);
+				if (index>0 && index!=-1){
+					var evenOdd = index%2 ? "even" : "odd";
+					content += actualResultHtml;
+ 					content += '</pre><pre class="testCase testNum'+ index +' '+evenOdd+'">';
+				}
+				content += lines[i].replace(/^\s+/, "")+"\n";
+			}
+			content += actualResultHtml + '</pre>';
+			this.containerNode.innerHTML = content;
+		},
+	
+		postCreate:function(){
+			this.inherited("postCreate", arguments);
+			dojo.connect(this.runButtonNode, "onClick", dojo.hitch(this, "runTests"));
+			dojo.connect(this.resetButtonNode, "onClick", dojo.hitch(this, "reset"));
+			this.numTestsNode.innerHTML = this.tests.length;
+		},
+		
+		runTests:function(){
+			var results = {ok:0, nok:0};
+			for (var i=0; i<this.tests.length; i++){
+				var ret = this.doctests.runTest(this.tests[i].commands, this.tests[i].expectedResult);
+				dojo.query(".testNum"+i, this.domNode).addClass(ret.success ? "resultOk" : "resultNok");
+				if (!ret.success){
+					results.nok++;
+					this.numTestsNokNode.innerHTML = results.nok;
+					var act = dojo.query(".testNum"+i+" .actualResult", this.domNode)[0];
+					dojo.style(act, "display", "inline");
+					dojo.query(".result", act)[0].innerHTML = dojo.toJson(ret.actualResult);
+				} else {
+					results.ok++;
+					this.numTestsOkNode.innerHTML = results.ok;
+				}
+			}
+			this.runButtonNode.cancel();
+			dojo.style(this.runButtonNode.domNode, "display", "none");
+			dojo.style(this.resetButtonNode.domNode, "display", "");
+		},
+		
+		reset:function(){
+			// summary: Reset the DocTester visuals and enable the "Run tests" button again.
+			dojo.style(this.runButtonNode.domNode, "display", "");
+			dojo.style(this.resetButtonNode.domNode, "display", "none");
+			this.numTestsOkNode.innerHTML = "0";
+			this.numTestsNokNode.innerHTML = "0";
+			dojo.query(".actualResult", this.domNode).style("display", "none");
+			dojo.query(".testCase", this.domNode).removeClass("resultOk").removeClass("resultNok");
+		},
+		
+		_unescapeHtml:function(/*string*/str){
+			// TODO Should become dojo.html.unentities() or so, when exists use instead
+			// summary:
+			//		Adds escape sequences for special characters in XML: &<>"'
+			str = String(str).replace(/&/gm, "&").replace(/</gm, "<")
+				.replace(/>/gm, ">").replace(/"/gm, '"');
+			return str; // string
+		}
+	}
+);
\ No newline at end of file
diff --git a/dojox/widget/DocTester/DocTester.css b/dojox/widget/DocTester/DocTester.css
index 34fbaa5..04dac19 100644
--- a/dojox/widget/DocTester/DocTester.css
+++ b/dojox/widget/DocTester/DocTester.css
@@ -12,6 +12,7 @@
 .dojoxDocTester pre.odd.resultNok{
 	background-color:#FFC3C3;
 }
+
 .dojoxDocTester pre.even{
         background-color:#F3F3F3;
 }
@@ -21,6 +22,7 @@
 .dojoxDocTester pre.even.resultNok{
 	background-color:#FFCFCF;
 }
+
 .dojoxDocTester .actualResult{
 	display:none;
 	font-weight:bold;
diff --git a/dojox/widget/DynamicTooltip.js b/dojox/widget/DynamicTooltip.js
index de83ef3..70dffca 100644
--- a/dojox/widget/DynamicTooltip.js
+++ b/dojox/widget/DynamicTooltip.js
@@ -1,44 +1,107 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.DynamicTooltip"]){
-dojo._hasResource["dojox.widget.DynamicTooltip"]=true;
 dojo.provide("dojox.widget.DynamicTooltip");
 dojo.experimental("dojox.widget.DynamicTooltip");
+
 dojo.require("dijit.Tooltip");
-dojo.requireLocalization("dijit","loading",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dojox.widget.DynamicTooltip",dijit.Tooltip,{hasLoaded:false,href:"",label:"",preventCache:false,postMixInProperties:function(){
-this.inherited(arguments);
-this._setLoadingLabel();
-},_setLoadingLabel:function(){
-if(this.href){
-this.label=dojo.i18n.getLocalization("dijit","loading",this.lang).loadingState;
-}
-},_setHrefAttr:function(_1){
-this.href=_1;
-this.hasLoaded=false;
-},loadContent:function(){
-if(!this.hasLoaded&&this.href){
-this._setLoadingLabel();
-this.hasLoaded=true;
-dojo.xhrGet({url:this.href,handleAs:"text",tooltipWidget:this,load:function(_2,_3){
-this.tooltipWidget.label=_2;
-this.tooltipWidget.close();
-this.tooltipWidget.open();
-},preventCache:this.preventCache});
-}
-},refresh:function(){
-this.hasLoaded=false;
-},open:function(_4){
-_4=_4||this._connectNodes[0];
-if(!_4){
-return;
-}
-this.loadContent();
-this.inherited(arguments);
-}});
-}
+dojo.requireLocalization("dijit", "loading");
+
+dojo.declare("dojox.widget.DynamicTooltip", dijit.Tooltip,
+	{
+		// summary:
+		//		Extention of dijit.Tooltip providing content set via XHR
+		//		request via href param	
+
+		// hasLoaded: Boolean
+		//		false if the contents are yet to be loaded from the HTTP request
+		hasLoaded: false,
+		
+		// href: String
+		//		location from where to fetch the contents
+		href: "",
+		
+		// label: String
+		//		contents to diplay in the tooltip. Initialized to a loading icon.
+		label: "",
+
+		// preventCache: Boolean
+		//		Cache content retreived externally
+		preventCache:	false,
+		
+		postMixInProperties: function(){
+			this.inherited(arguments);
+			this._setLoadingLabel();
+		},
+		
+		_setLoadingLabel: function(){
+			// summary:
+			//		Changes the tooltip label / contents to loading message, only if 
+			//		there's an href param, otherwise acts as normal tooltip
+
+			if(this.href){
+				this.label = dojo.i18n.getLocalization("dijit", "loading", this.lang).loadingState;
+			}
+		},
+
+		// MOW: this is a new widget, do we really need a deprecated stub?
+		// setHref: function(/*String|Uri*/ href){
+		//	// summary:
+		//	//		Deprecated.   Use set('href', ...) instead.
+		//	dojo.deprecated("dojox.widget.DynamicTooltip.setHref() is deprecated.	Use set('href', ...) instead.", "", "2.0");
+		//	return this.set("href", href);
+		// },
+
+		_setHrefAttr: function(/*String|Uri*/ href){
+			// summary:
+			//		Hook so attr("href", ...) works.
+			// description:
+			//		resets so next show loads new href
+			//	href:
+			//		url to the content you want to show, must be within the same domain as your mainpage
+		
+			this.href = href;
+			this.hasLoaded = false;
+		},
+		
+		loadContent: function(){
+			// summary:
+			//		Download contents of href via XHR and display
+			// description:
+			//		1. checks if content already loaded
+			//		2. if not, sends XHR to download new data
+			if(!this.hasLoaded && this.href){
+				this._setLoadingLabel();
+				this.hasLoaded = true;
+				
+				dojo.xhrGet({
+					url: this.href,
+					handleAs: "text",
+					tooltipWidget: this,
+					load: function(response, ioArgs){
+						this.tooltipWidget.label = response;
+						this.tooltipWidget.close();
+						this.tooltipWidget.open();
+					},
+					preventCache: this.preventCache
+				});
+			}
+		},
+		
+		refresh: function(){
+			// summary:
+			//		Allows re-download of contents of href and display
+			//		Useful with preventCache = true
+
+			this.hasLoaded = false;
+		},
+		
+		open: function(/*DomNode*/ target){
+ 			// summary:
+			//		Display the tooltip; usually not called directly.
+			
+			target = target || this._connectNodes[0];
+			if(!target){ return; }
+
+			this.loadContent();
+			this.inherited(arguments);
+		}
+	}
+);
diff --git a/dojox/widget/FeedPortlet.js b/dojox/widget/FeedPortlet.js
index 37e9d3c..b4187e3 100644
--- a/dojox/widget/FeedPortlet.js
+++ b/dojox/widget/FeedPortlet.js
@@ -1,227 +1,430 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.FeedPortlet"]){
-dojo._hasResource["dojox.widget.FeedPortlet"]=true;
 dojo.provide("dojox.widget.FeedPortlet");
 dojo.require("dojox.widget.Portlet");
 dojo.require("dijit.Tooltip");
 dojo.require("dijit.form.TextBox");
 dojo.require("dijit.form.Button");
 dojo.require("dojox.data.GoogleFeedStore");
-dojo.declare("dojox.widget.FeedPortlet",dojox.widget.Portlet,{local:false,maxResults:5,url:"",openNew:true,showFeedTitle:true,postCreate:function(){
-this.inherited(arguments);
-if(this.local&&!dojox.data.AtomReadStore){
-throw Error(this.declaredClass+": To use local feeds, you must include dojox.data.AtomReadStore on the page.");
-}
-},onFeedError:function(){
-this.containerNode.innerHTML="Error accessing the feed.";
-},addChild:function(_1){
-this.inherited(arguments);
-var _2=_1.attr("feedPortletUrl");
-if(_2){
-this.attr("url",_2);
-}
-},_getTitle:function(_3){
-var t=this.store.getValue(_3,"title");
-return this.local?t.text:t;
-},_getLink:function(_4){
-var l=this.store.getValue(_4,"link");
-return this.local?l.href:l;
-},_getContent:function(_5){
-var c=this.store.getValue(_5,"summary");
-if(!c){
-return null;
-}
-if(this.local){
-c=c.text;
-}
-c=c.split("<script").join("<!--").split("</script>").join("-->");
-c=c.split("<iframe").join("<!--").split("</iframe>").join("-->");
-return c;
-},_setUrlAttr:function(_6){
-this.url=_6;
-if(this._started){
-this.load();
-}
-},startup:function(){
-if(this.started||this._started){
-return;
-}
-this.inherited(arguments);
-if(!this.url||this.url==""){
-throw new Error(this.id+": A URL must be specified for the feed portlet");
-}
-if(this.url&&this.url!=""){
-this.load();
-}
-},load:function(){
-if(this._resultList){
-dojo.destroy(this._resultList);
-}
-var _7,_8;
-if(this.local){
-_7=new dojox.data.AtomReadStore({url:this.url});
-_8={};
-}else{
-_7=new dojox.data.GoogleFeedStore();
-_8={url:this.url};
-}
-var _9={query:_8,count:this.maxResults,onComplete:dojo.hitch(this,function(_a){
-if(this.showFeedTitle&&_7.getFeedValue){
-var _b=this.store.getFeedValue("title");
-if(_b){
-this.attr("title",_b.text?_b.text:_b);
-}
-}
-this.generateResults(_a);
-}),onError:dojo.hitch(this,"onFeedError")};
-this.store=_7;
-_7.fetch(_9);
-},generateResults:function(_c){
-var _d=this.store;
-var _e;
-var ul=this._resultList=dojo.create("ul",{"class":"dojoxFeedPortletList"},this.containerNode);
-dojo.forEach(_c,dojo.hitch(this,function(_f){
-var li=dojo.create("li",{innerHTML:"<a href=\""+this._getLink(_f)+"\""+(this.openNew?" target=\"_blank\"":"")+">"+this._getTitle(_f)+"</a>"},ul);
-dojo.connect(li,"onmouseover",dojo.hitch(this,function(evt){
-if(_e){
-clearTimeout(_e);
-}
-_e=setTimeout(dojo.hitch(this,function(){
-_e=null;
-var _10=this._getContent(_f);
-if(!_10){
-return;
-}
-var _11="<div class=\"dojoxFeedPortletPreview\">"+_10+"</div>";
-dojo.query("li",ul).forEach(function(_12){
-if(_12!=evt.target){
-dijit.hideTooltip(_12);
-}
-});
-dijit.showTooltip(_11,li.firstChild);
-}),500);
-}));
-dojo.connect(li,"onmouseout",function(){
-if(_e){
-clearTimeout(_e);
-_e=null;
-}
-dijit.hideTooltip(li.firstChild);
+
+dojo.declare("dojox.widget.FeedPortlet", dojox.widget.Portlet, {
+	// summary: 
+	//		A Portlet that loads a XML feed.
+	// description: The feed is displayed as
+	//		an unordered list of links.	When a link is hovered over
+	//		by the mouse, it displays a summary in a tooltip.
+	
+	// local: Boolean
+	//		Specifies whether the feed is to be loaded from the same domain as the
+	//		page, or a remote domain.	If local is true, then the feed must be an
+	//		Atom feed.	If it is false, it can be an Atom or RSS feed.
+	local: false, 
+	
+	// maxResults: Number
+	//		The number of results to display from the feed.
+	maxResults: 5,
+	
+	// url: String
+	//		The URL of the feed to load.	If this is different to the domain
+	//		of the HTML page, local should be set to false.
+	url: "",
+	
+	// openNew: Boolean
+	//		If true, when a link is clicked it will open in a new window.
+	//		If false, it will not.
+	openNew: true,
+
+	// useFeedTitle: Boolean
+	//		If true, the title of the loaded feed is displayed in the title bar of the portlet.
+	//		If false, the title remains unchanged.
+	showFeedTitle: true,
+	
+	postCreate: function(){
+		this.inherited(arguments);
+		if(this.local && !dojox.data.AtomReadStore){
+			throw Error(this.declaredClass + ": To use local feeds, you must include dojox.data.AtomReadStore on the page.");
+		}
+	},
+	
+	onFeedError: function(){
+		// summary: 
+		//		Called when a feed fails to load successfully.
+		this.containerNode.innerHTML = "Error accessing the feed."
+	},
+	
+	addChild: function(child){
+		this.inherited(arguments);
+		var url = child.attr("feedPortletUrl");
+		if(url){
+			this.set("url", url);
+		}
+	},
+	
+	_getTitle: function(item){
+		// summary: 
+		//		Gets the title of a feed item.
+		var t = this.store.getValue(item, "title");
+		return this.local ? t.text : t;
+	},
+	
+	_getLink: function(item){
+		// summary: 
+		//		Gets the href link of a feed item.
+		var l = this.store.getValue(item, "link");
+		return this.local ? l.href : l;
+	},
+	
+	_getContent: function(item){
+		// summary: 
+		//		Gets the summary of a feed item.
+		var c = this.store.getValue(item, "summary");
+		if(!c){
+			return null;
+		}
+		if(this.local){
+			c = c.text;
+		}
+		// Filter out any sneaky scripts in the code
+		c = c.split("<script").join("<!--").split("</script>").join("-->");
+		c = c.split("<iframe").join("<!--").split("</iframe>").join("-->");
+		return c;
+		
+	},
+	
+	_setUrlAttr: function(url){
+		// summary:
+		//		Sets the URL to load.
+		this.url = url;
+		if(this._started){
+			this.load();
+		}
+	},
+	
+	startup: function(){
+		// summary: 
+		//		Loads the widget.
+		if(this.started || this._started){return;}
+		
+		this.inherited(arguments);
+		
+		if(!this.url || this.url == ""){
+			throw new Error(this.id + ": A URL must be specified for the feed portlet");
+		}
+		if(this.url && this.url != ""){
+			this.load();
+		}
+	},
+	
+	load: function(){
+		// summary:
+		//		Loads the feed.
+		if(this._resultList){
+			dojo.destroy(this._resultList);
+		}
+		var store, query;
+		
+		// If the feed is on the same domain, use the AtomReadStore, 
+		// as we cannot be guaranteed that it will be available to
+		// Google services.
+		if(this.local){
+			store = new dojox.data.AtomReadStore({
+				url: this.url
+			});
+			query = {};
+			
+		}else{
+			store = new dojox.data.GoogleFeedStore();
+			query = {url: this.url};
+		}
+		var request = {
+			query: query,
+			count: this.maxResults,
+			onComplete: dojo.hitch(this, function(items){
+				if (this.showFeedTitle && store.getFeedValue) {
+					var title = this.store.getFeedValue("title");
+					if(title){
+						this.set("title", title.text ? title.text : title);
+					}
+				}
+				this.generateResults(items);
+			}),
+			onError: dojo.hitch(this, "onFeedError")
+		};
+		
+		this.store = store;
+		store.fetch(request);
+	},
+	
+	generateResults: function (items){
+		// summary: 
+		//		Generates a list of hyperlinks and displays a tooltip
+		//		containing a summary when the mouse hovers over them.
+		var store = this.store;
+		var timer;
+		var ul = (this._resultList = 
+			dojo.create("ul", {"class" : "dojoxFeedPortletList"}, this.containerNode));
+
+		dojo.forEach(items, dojo.hitch(this, function(item){
+			var li = dojo.create("li", {
+				innerHTML: '<a href="' 
+					+ this._getLink(item) 
+					+ '"' 
+					+ (this.openNew ? ' target="_blank"' : '')
+					+'>' 
+					+ this._getTitle(item) + '</a>'
+			},ul);
+			
+			dojo.connect(li, "onmouseover", dojo.hitch(this, function(evt){
+				if(timer){
+					clearTimeout(timer);
+				}
+				
+				// Show the tooltip after the mouse has been hovering
+				// for a short time.
+				timer = setTimeout(dojo.hitch(this, function(){
+					timer = null;
+					var summary = this._getContent(item);
+					if(!summary){return;}
+					var content = '<div class="dojoxFeedPortletPreview">' 
+						+ summary + '</div>'
+					
+					dojo.query("li", ul).forEach(function(item){
+						if(item != evt.target){
+							dijit.hideTooltip(item);
+						}
+					});
+					
+					// Hover the tooltip over the anchor tag
+					dijit.showTooltip(content, li.firstChild, !this.isLeftToRight());
+				}), 500);
+				
+				
+			}));
+			
+			// Hide the tooltip when the mouse leaves a list item.
+			dojo.connect(li, "onmouseout", function(){
+				if(timer){
+					clearTimeout(timer);
+					timer = null;
+				}
+				dijit.hideTooltip(li.firstChild);
+			});
+		}));
+		
+		this.resize();
+	}
 });
-}));
-this.resize();
-}});
-dojo.declare("dojox.widget.ExpandableFeedPortlet",dojox.widget.FeedPortlet,{onlyOpenOne:false,generateResults:function(_13){
-var _14=this.store;
-var _15="dojoxPortletToggleIcon";
-var _16="dojoxPortletItemCollapsed";
-var _17="dojoxPortletItemOpen";
-var _18;
-var ul=this._resultList=dojo.create("ul",{"class":"dojoxFeedPortletExpandableList"},this.containerNode);
-dojo.forEach(_13,dojo.hitch(this,dojo.hitch(this,function(_19){
-var li=dojo.create("li",{"class":_16},ul);
-var _1a=dojo.create("div",{style:"width: 100%;"},li);
-var _1b=dojo.create("div",{"class":"dojoxPortletItemSummary",innerHTML:this._getContent(_19)},li);
-dojo.create("span",{"class":_15,innerHTML:"<img src='"+dojo.config.baseUrl+"/resources/blank.gif'>"},_1a);
-var a=dojo.create("a",{href:this._getLink(_19),innerHTML:this._getTitle(_19)},_1a);
-if(this.openNew){
-dojo.attr(a,"target","_blank");
-}
-})));
-dojo.connect(ul,"onclick",dojo.hitch(this,function(evt){
-if(dojo.hasClass(evt.target,_15)||dojo.hasClass(evt.target.parentNode,_15)){
-dojo.stopEvent(evt);
-var li=evt.target.parentNode;
-while(li.tagName!="LI"){
-li=li.parentNode;
-}
-if(this.onlyOpenOne){
-dojo.query("li",ul).filter(function(_1c){
-return _1c!=li;
-}).removeClass(_17).addClass(_16);
-}
-var _1d=dojo.hasClass(li,_17);
-dojo.toggleClass(li,_17,!_1d);
-dojo.toggleClass(li,_16,_1d);
-}
-}));
-}});
-dojo.declare("dojox.widget.PortletFeedSettings",dojox.widget.PortletSettings,{"class":"dojoxPortletFeedSettings",urls:null,selectedIndex:0,buildRendering:function(){
-if(this.urls&&this.urls.length>0){
-var s=dojo.create("select");
-if(this.srcNodeRef){
-dojo.place(s,this.srcNodeRef,"before");
-dojo.destroy(this.srcNodeRef);
-}
-this.srcNodeRef=s;
-dojo.forEach(this.urls,function(url){
-dojo.create("option",{value:url.url||url,innerHTML:url.label||url},s);
+
+dojo.declare("dojox.widget.ExpandableFeedPortlet", dojox.widget.FeedPortlet, {
+	// summary: 
+	//		A FeedPortlet that uses an list of expandable links to display 
+	//		a feed.	An icon is placed to the left of each item
+	//		which, when clicked, toggles the visible state
+	//		of the item summary.
+	
+	// onlyOpenOne: Boolean
+	//		If true, only a single item can be expanded at any given time.
+	onlyOpenOne: false,
+	
+	generateResults: function(items){
+		// summary:
+		//		Generates a list of items, and places an icon beside them that
+		//		can be used to show or hide a summary of that item.
+		
+		var store = this.store;
+		var iconCls = "dojoxPortletToggleIcon";
+		var collapsedCls = "dojoxPortletItemCollapsed";
+		var expandedCls = "dojoxPortletItemOpen";
+		
+		var timer;
+		var ul = (this._resultList = dojo.create("ul", {
+			"class": "dojoxFeedPortletExpandableList"
+		}, this.containerNode));
+		
+		// Create the LI elements.	Each LI has two DIV elements, the 
+		// top DIV contains the toggle icon and title, and the bottom
+		// div contains the extended summary.
+		dojo.forEach(items, dojo.hitch(this, dojo.hitch(this, function(item){
+			var li = dojo.create("li", {"class": collapsedCls}, ul);
+			var upper = dojo.create("div", {style: "width: 100%;"}, li);
+			var lower = dojo.create("div", {"class": "dojoxPortletItemSummary", innerHTML: this._getContent(item)}, li);
+			dojo.create("span", {
+				"class": iconCls, 
+				innerHTML: "<img src='" + dojo.config.baseUrl + "/resources/blank.gif'>"}, upper);
+			var a = dojo.create("a", {href: this._getLink(item), innerHTML: this._getTitle(item) }, upper);
+			
+			if(this.openNew){
+				dojo.attr(a, "target", "_blank");
+			}
+		})));
+		
+		// Catch all clicks on the list. If a toggle icon is clicked,
+		// toggle the visible state of the summary DIV.
+		dojo.connect(ul, "onclick", dojo.hitch(this, function(evt){
+			if(dojo.hasClass(evt.target, iconCls) || dojo.hasClass(evt.target.parentNode, iconCls)){
+				dojo.stopEvent(evt);
+				var li = evt.target.parentNode;
+				while(li.tagName != "LI"){
+					li = li.parentNode;
+				}
+				if(this.onlyOpenOne){
+					dojo.query("li", ul).filter(function(item){
+						return item != li;
+					}).removeClass(expandedCls).addClass(collapsedCls);
+				}
+				var isExpanded = dojo.hasClass(li, expandedCls);
+				dojo.toggleClass(li, expandedCls, !isExpanded);
+				dojo.toggleClass(li, collapsedCls, isExpanded);
+			}
+		}));
+	}
 });
-}
-if(this.srcNodeRef.tagName=="SELECT"){
-this.text=this.srcNodeRef;
-var div=dojo.create("div",{},this.srcNodeRef,"before");
-div.appendChild(this.text);
-this.srcNodeRef=div;
-dojo.query("option",this.text).filter("return !item.value;").forEach("item.value = item.innerHTML");
-if(!this.text.value){
-dojo.attr(s||this.text,"value",this.text.options[this.selectedIndex].value);
-}
-}
-this.inherited(arguments);
-},postCreate:function(){
-if(!this.text){
-var _1e=this.text=new dijit.form.TextBox({});
-dojo.create("span",{innerHTML:"Choose Url: "},this.domNode);
-this.addChild(_1e);
-}
-this.addChild(new dijit.form.Button({label:"Load",onClick:dojo.hitch(this,function(){
-this.portlet.attr("url",(this.text.tagName=="SELECT")?this.text.value:this.text.attr("value"));
-if(this.text.tagName=="SELECT"){
-dojo.some(this.text.options,dojo.hitch(this,function(opt,idx){
-if(opt.selected){
-this.attr("selectedIndex",idx);
-return true;
-}
-return false;
-}));
-}
-this.toggle();
-})}));
-this.addChild(new dijit.form.Button({label:"Cancel",onClick:dojo.hitch(this,"toggle")}));
-this.inherited(arguments);
-},startup:function(){
-if(this._started){
-return;
-}
-this.inherited(arguments);
-if(!this.portlet){
-throw Error(this.declaredClass+": A PortletFeedSettings widget cannot exist without a Portlet.");
-}
-if(this.text.tagName=="SELECT"){
-dojo.forEach(this.text.options,dojo.hitch(this,function(opt,_1f){
-dojo.attr(opt,"selected",_1f==this.selectedIndex);
-}));
-}
-var url=this.portlet.attr("url");
-if(url){
-if(this.text.tagName=="SELECT"){
-if(!this.urls&&dojo.query("option[value='"+url+"']",this.text).length<1){
-dojo.place(dojo.create("option",{value:url,innerHTML:url,selected:"true"}),this.text,"first");
-}
-}else{
-this.text.attr("value",url);
-}
-}else{
-this.portlet.attr("url",this.attr("feedPortletUrl"));
-}
-},_getFeedPortletUrlAttr:function(){
-return this.text.value;
-}});
-}
+
+
+dojo.declare("dojox.widget.PortletFeedSettings", 
+	dojox.widget.PortletSettings, {
+		
+	// summary:
+	//		A Settings widget designed to be used with a dojox.widget.FeedPortlet
+	// description:
+	//		It provides form items that the user can use to change the URL
+	//		for a feed to load into the FeedPortlet.
+	//		There are two forms that it can take.	<br>
+	//		The first is to display a text field, with Load and Cancel buttons,
+	//		which is prepopulated with the enclosing FeedPortlet's URL.
+	//		If a <select> DOM node is used as the source node for this widget,
+	//		it displays a list of predefined URLs that the user can select from
+	//		to load into the enclosing FeedPortlet.
+	//					
+	// example:
+	//		<div dojoType="dojox.widget.PortletFeedSettings"></div>
+	//
+	// example:
+	//		<select dojoType="dojox.widget.PortletFeedSettings">
+	//			<option>http://www.dojotoolkit.org/aggregator/rss</option>
+	//			<option>http://dojocampus.org/content/category/podcast/feed/</option>
+	//		</select>
+	
+	"class" : "dojoxPortletFeedSettings",
+	
+	// urls: Array
+	//		An array of JSON object specifying URLs to display in the
+	//		PortletFeedSettings object. Each object contains a 'url' and 'label'
+	//		attribute, e.g.
+	//		[{url:'http:google.com', label:'Google'}, {url:'http://dojotoolkit.org', label: 'Dojo'}]
+	urls: null,
+	
+	// selectedIndex: Number
+	//		The selected URL. Defaults to zero.
+	selectedIndex: 0,
+	
+	buildRendering: function(){
+
+		// If JSON URLs have been specified, create a SELECT DOM node,
+		// and insert the required OPTION elements.
+		if(this.urls && this.urls.length > 0){
+			
+			var s = dojo.create("select");
+			if(this.srcNodeRef){
+				dojo.place(s, this.srcNodeRef, "before");
+				dojo.destroy(this.srcNodeRef);
+			}
+			this.srcNodeRef = s;
+			dojo.forEach(this.urls, function(url){
+				dojo.create("option", {value: url.url || url, innerHTML: url.label || url}, s);
+			});
+		}
+
+		// If the srcNodeRef is a SELECT node, then replace it with a DIV, and insert
+		// the SELECT node into that div.
+		if(this.srcNodeRef.tagName == "SELECT"){
+			this.text = this.srcNodeRef;
+			var div = dojo.create("div", {}, this.srcNodeRef, "before");
+			div.appendChild(this.text);
+			this.srcNodeRef = div;
+			dojo.query("option", this.text).filter("return !item.value;").forEach("item.value = item.innerHTML");
+			if(!this.text.value){
+				dojo.attr(s || this.text, "value", this.text.options[this.selectedIndex].value);
+			}
+		}
+		this.inherited(arguments);
+	},
+	
+	postCreate: function(){
+		if(!this.text){
+			// If a select node is not being used, create a new TextBox to 
+			// edit the URL.
+			var text = this.text = new dijit.form.TextBox({});
+			dojo.create("span", {
+				innerHTML: "Choose Url: "
+			}, this.domNode);
+			this.addChild(text);
+		}
+
+		// Add a LOAD button
+		this.addChild(new dijit.form.Button({
+			label: "Load",
+			onClick: dojo.hitch(this, function(){
+				// Set the URL of the containing Portlet with the selected URL.
+				this.portlet.attr("url", 
+					(this.text.tagName == "SELECT") ? this.text.value : this.text.attr('value'));
+				if(this.text.tagName == "SELECT"){
+					// Set the selected index on the Select node.
+					dojo.some(this.text.options, dojo.hitch(this, function(opt, idx){
+						if(opt.selected){
+							this.set("selectedIndex", idx);
+							return true;
+						}
+						return false;
+					}));
+				}
+				// Hide the widget.
+				this.toggle();
+			})
+		}));
+		
+		// Add a CANCEL button, which hides this widget
+		this.addChild(new dijit.form.Button({
+			label: "Cancel",
+			onClick: dojo.hitch(this, "toggle")
+		}));
+		this.inherited(arguments);
+	},
+		
+	startup: function(){
+		// summary:
+		//		Sets the portlet associated with this PortletSettings object.
+		if(this._started){return;}
+		this.inherited(arguments);
+		
+		if(!this.portlet){
+			throw Error(this.declaredClass + ": A PortletFeedSettings widget cannot exist without a Portlet.");
+		}
+		if(this.text.tagName == "SELECT"){
+			// Set the initial selected option.
+			dojo.forEach(this.text.options, dojo.hitch(this, function(opt, index){
+				dojo.attr(opt, "selected", index == this.selectedIndex);
+			}));
+		}
+		var url = this.portlet.attr("url");
+		if(url){
+			// If a SELECT node is used to choose a URL, ensure that the Portlet's URL
+			// is one of the options.
+			if(this.text.tagName == "SELECT"){
+				if(!this.urls && dojo.query("option[value='" + url + "']", this.text).length < 1){
+					dojo.place(dojo.create("option", {
+						value: url,
+						innerHTML: url,
+						selected: "true"
+					}), this.text, "first");
+				}
+			}else{
+				this.text.attr("value", url);
+			}
+		}else{
+			this.portlet.attr("url", this.get("feedPortletUrl"));
+		}
+	},
+	
+	_getFeedPortletUrlAttr: function(){
+		return this.text.value;
+	}
+});
\ No newline at end of file
diff --git a/dojox/widget/FilePicker.js b/dojox/widget/FilePicker.js
index 18e49d3..5e76952 100644
--- a/dojox/widget/FilePicker.js
+++ b/dojox/widget/FilePicker.js
@@ -1,160 +1,223 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.FilePicker"]){
-dojo._hasResource["dojox.widget.FilePicker"]=true;
 dojo.provide("dojox.widget.FilePicker");
+
 dojo.require("dojox.widget.RollingList");
-dojo.require("dojo.i18n");
-dojo.requireLocalization("dojox.widget","FilePicker",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dojox.widget._FileInfoPane",[dojox.widget._RollingListPane],{templateString:"",templateString:dojo.cache("dojox.widget","FilePicker/_FileInfoPane.html","<div class=\"dojoxFileInfoPane\">\n\t<table>\n\t\t<tbody>\n\t\t\t<tr>\n\t\t\t\t<td class=\"dojoxFileInfoLabel dojoxFileInfoNameLabel\">${_messages.name}</td>\n\t\t\t\t<td class=\"dojoxFileInfoName\" dojoAttachPoint=\"nameNode\"></td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td class=\"dojoxFileInfoLabel dojoxFileInfoPathLabel\">$ [...]
-this._messages=dojo.i18n.getLocalization("dojox.widget","FilePicker",this.lang);
-this.inherited(arguments);
-},onItems:function(){
-var _1=this.store,_2=this.items[0];
-if(!_2){
-this._onError("Load",new Error("No item defined"));
-}else{
-this.nameNode.innerHTML=_1.getLabel(_2);
-this.pathNode.innerHTML=_1.getIdentity(_2);
-this.sizeNode.innerHTML=_1.getValue(_2,"size");
-this.parentWidget.scrollIntoView(this);
-this.inherited(arguments);
-}
-}});
-dojo.declare("dojox.widget.FilePicker",dojox.widget.RollingList,{className:"dojoxFilePicker",pathSeparator:"",topDir:"",parentAttr:"parentDir",pathAttr:"path",preloadItems:50,selectDirectories:true,selectFiles:true,_itemsMatch:function(_3,_4){
-if(!_3&&!_4){
-return true;
-}else{
-if(!_3||!_4){
-return false;
-}else{
-if(_3==_4){
-return true;
-}else{
-if(this._isIdentity){
-var _5=[this.store.getIdentity(_3),this.store.getIdentity(_4)];
-dojo.forEach(_5,function(i,_6){
-if(i.lastIndexOf(this.pathSeparator)==(i.length-1)){
-_5[_6]=i.substring(0,i.length-1);
-}else{
-}
-},this);
-return (_5[0]==_5[1]);
-}
-}
-}
-}
-return false;
-},startup:function(){
-if(this._started){
-return;
-}
-this.inherited(arguments);
-var _7,_8=this.getChildren()[0];
-var _9=dojo.hitch(this,function(){
-if(_7){
-this.disconnect(_7);
-}
-delete _7;
-var _a=_8.items[0];
-if(_a){
-var _b=this.store;
-var _c=_b.getValue(_a,this.parentAttr);
-var _d=_b.getValue(_a,this.pathAttr);
-this.pathSeparator=this.pathSeparator||_b.pathSeparator;
-if(!this.pathSeparator){
-this.pathSeparator=_d.substring(_c.length,_c.length+1);
-}
-if(!this.topDir){
-this.topDir=_c;
-if(this.topDir.lastIndexOf(this.pathSeparator)!=(this.topDir.length-1)){
-this.topDir+=this.pathSeparator;
-}
-}
-}
+
+dojo.require("dojo.i18n"); 
+dojo.requireLocalization("dojox.widget", "FilePicker"); 
+
+dojo.declare("dojox.widget._FileInfoPane", 
+	[dojox.widget._RollingListPane], {
+	// summary: a pane to display the information for the currently-selected
+	//	file
+	
+	// templateString: string
+	//	delete our template string
+	templateString: "",
+	
+	// templateString: String
+	//		The template to be used to construct the widget.
+	templateString: dojo.cache("dojox.widget", "FilePicker/_FileInfoPane.html"),
+	
+	postMixInProperties: function(){
+		this._messages = dojo.i18n.getLocalization("dojox.widget", "FilePicker", this.lang);
+		this.inherited(arguments);
+	},
+
+	onItems: function(){
+		// summary:
+		//	called after a fetch or load - at this point, this.items should be
+		//  set and loaded.
+		var store = this.store, item = this.items[0];
+		if(!item){
+			this._onError("Load", new Error("No item defined"));
+		}else{
+			this.nameNode.innerHTML = store.getLabel(item);
+			this.pathNode.innerHTML = store.getIdentity(item);
+			this.sizeNode.innerHTML = store.getValue(item, "size");
+			this.parentWidget.scrollIntoView(this);
+			this.inherited(arguments);
+		}
+	}
 });
-if(!this.pathSeparator||!this.topDir){
-if(!_8.items){
-_7=this.connect(_8,"onItems",_9);
-}else{
-_9();
-}
-}
-},getChildItems:function(_e){
-var _f=this.inherited(arguments);
-if(!_f&&this.store.getValue(_e,"directory")){
-_f=[];
-}
-return _f;
-},getMenuItemForItem:function(_10,_11,_12){
-var _13={iconClass:"dojoxDirectoryItemIcon"};
-if(!this.store.getValue(_10,"directory")){
-_13.iconClass="dojoxFileItemIcon";
-var l=this.store.getLabel(_10),idx=l.lastIndexOf(".");
-if(idx>=0){
-_13.iconClass+=" dojoxFileItemIcon_"+l.substring(idx+1);
-}
-if(!this.selectFiles){
-_13.disabled=true;
-}
-}
-var ret=new dijit.MenuItem(_13);
-return ret;
-},getPaneForItem:function(_14,_15,_16){
-var ret=null;
-if(!_14||(this.store.isItem(_14)&&this.store.getValue(_14,"directory"))){
-ret=new dojox.widget._RollingListGroupPane({});
-}else{
-if(this.store.isItem(_14)&&!this.store.getValue(_14,"directory")){
-ret=new dojox.widget._FileInfoPane({});
-}
-}
-return ret;
-},_setPathValueAttr:function(_17,_18,_19){
-if(!_17){
-this.attr("value",null);
-return;
-}
-if(_17.lastIndexOf(this.pathSeparator)==(_17.length-1)){
-_17=_17.substring(0,_17.length-1);
-}
-this.store.fetchItemByIdentity({identity:_17,onItem:function(v){
-if(_18){
-this._lastExecutedValue=v;
-}
-this.attr("value",v);
-if(_19){
-_19();
-}
-},scope:this});
-},_getPathValueAttr:function(val){
-if(!val){
-val=this.value;
-}
-if(val&&this.store.isItem(val)){
-return this.store.getValue(val,this.pathAttr);
-}else{
-return "";
-}
-},_setValue:function(_1a){
-delete this._setInProgress;
-var _1b=this.store;
-if(_1a&&_1b.isItem(_1a)){
-var _1c=this.store.getValue(_1a,"directory");
-if((_1c&&!this.selectDirectories)||(!_1c&&!this.selectFiles)){
-return;
-}
-}else{
-_1a=null;
-}
-if(!this._itemsMatch(this.value,_1a)){
-this.value=_1a;
-this._onChange(_1a);
-}
-}});
-}
+
+dojo.declare("dojox.widget.FilePicker", dojox.widget.RollingList, {
+	// summary: a specialized version of RollingList that handles file information
+	//  in a store
+	
+	className: "dojoxFilePicker",
+	
+	// pathSeparator: string
+	//  Our file separator - it will be guessed if not set
+	pathSeparator: "",
+	
+	// topDir: string
+	//	The top directory string - it will be guessed if not set
+	topDir: "",
+		
+	// parentAttr: string
+	//	the attribute to read for finding our parent directory
+	parentAttr: "parentDir",
+	
+	// pathAttr: string
+	//  the attribute to read for getting the full path of our file
+	pathAttr: "path",
+	
+	// preloadItems: boolean or int
+	//  Set this to a sane number - since we expect to mostly be using the 
+	//	dojox.data.FileStore - which doesn't like loading lots of items
+	//	all at once.
+	preloadItems: 50,
+
+	// selectDirectories: boolean
+	//  whether or not we allow selection of directories - that is, whether or
+	//  our value can be set to a directory.
+	selectDirectories: true,
+
+	// selectFiles: boolean
+	//  whether or not we allow selection of files - that is, we will disable
+	//  the file entries.
+	selectFiles: true,
+
+	_itemsMatch: function(/*item*/ item1, /*item*/ item2){
+		// Summary: returns whether or not the two items match - checks ID if
+		//  they aren't the exact same object - ignoring trailing slashes
+		if(!item1 && !item2){ 
+			return true;
+		}else if(!item1 || !item2){
+			return false;
+		}else if(item1 == item2){
+			return true;
+		}else if (this._isIdentity){
+			var iArr = [ this.store.getIdentity(item1), this.store.getIdentity(item2) ];
+			dojo.forEach(iArr, function(i, idx){
+				if(i.lastIndexOf(this.pathSeparator) == (i.length - 1)){
+					iArr[idx] = i.substring(0, i.length - 1); 
+				}else{
+				}
+			}, this);
+			return (iArr[0] == iArr[1]);
+		}
+		return false;
+	},
+	
+	startup: function(){
+		if(this._started){ return; }
+		this.inherited(arguments);
+		// Figure out our file separator if we don't have it yet
+		var conn, child = this.getChildren()[0];
+		var setSeparator = dojo.hitch(this, function(){
+			if(conn){
+				this.disconnect(conn);
+			}
+			delete conn;
+			var item = child.items[0];
+			if(item){
+				var store = this.store;
+				var parent = store.getValue(item, this.parentAttr);
+				var path = store.getValue(item, this.pathAttr);
+				this.pathSeparator = this.pathSeparator || store.pathSeparator;
+				if(!this.pathSeparator){
+					this.pathSeparator = path.substring(parent.length, parent.length + 1);
+				}
+				if(!this.topDir){
+					this.topDir = parent;
+					if(this.topDir.lastIndexOf(this.pathSeparator) != (this.topDir.length - 1)){
+						this.topDir += this.pathSeparator;
+					}
+				}
+			}
+		});
+		if(!this.pathSeparator || !this.topDir){
+			if(!child.items){
+				conn = this.connect(child, "onItems", setSeparator);
+			}else{
+				setSeparator();
+			}
+		}
+	},
+	
+	getChildItems: function(item){
+		var ret = this.inherited(arguments);
+		if(!ret && this.store.getValue(item, "directory")){
+			// It's an empty directory - so pass through an empty array
+			ret = [];
+		}
+		return ret;
+	},
+	
+	getMenuItemForItem: function(/*item*/ item, /* dijit._Contained */ parentPane, /* item[]? */ children){
+		var menuOptions = {iconClass: "dojoxDirectoryItemIcon"};
+		if(!this.store.getValue(item, "directory")){
+			menuOptions.iconClass = "dojoxFileItemIcon";
+			var l = this.store.getLabel(item), idx = l.lastIndexOf(".");
+			if(idx >= 0){
+				menuOptions.iconClass += " dojoxFileItemIcon_" + l.substring(idx + 1);
+			}
+			if(!this.selectFiles){
+				menuOptions.disabled = true;
+			}
+		}
+		var ret = new dijit.MenuItem(menuOptions);
+		return ret;
+	},
+	
+	getPaneForItem: function(/*item*/ item, /* dijit._Contained */ parentPane, /* item[]? */ children){
+		var ret = null;
+		if(!item || (this.store.isItem(item) && this.store.getValue(item, "directory"))){
+			ret = new dojox.widget._RollingListGroupPane({});
+		}else if(this.store.isItem(item) && !this.store.getValue(item, "directory")){
+			ret = new dojox.widget._FileInfoPane({});
+		}
+		return ret;
+	},
+	
+	_setPathValueAttr: function(/*string*/ path, /*boolean?*/ resetLastExec, /*function?*/ onSet){
+		// Summary: sets the value of this widget based off the given path
+		if(!path){
+			this.set("value", null);
+			return;
+		}
+		if(path.lastIndexOf(this.pathSeparator) == (path.length - 1)){
+			path = path.substring(0, path.length - 1);
+		}
+		this.store.fetchItemByIdentity({identity: path,
+										onItem: function(v){
+											if(resetLastExec){ 
+												this._lastExecutedValue = v;
+											}
+											this.set("value", v);
+											if(onSet){ onSet(); }
+										},
+										scope: this});
+	},
+	
+	_getPathValueAttr: function(/*item?*/val){
+		// summary: returns the path value of the given value (or current value
+		//  if not passed a value)
+		if(!val){
+			val = this.value;
+		}
+		if(val && this.store.isItem(val)){
+			return this.store.getValue(val, this.pathAttr);
+		}else{
+			return "";
+		}
+	},
+	
+	_setValue: function(/* item */ value){
+		// summary: internally sets the value and fires onchange
+		delete this._setInProgress;
+		var store = this.store;
+		if(value && store.isItem(value)){
+			var isDirectory = this.store.getValue(value, "directory");
+			if((isDirectory && !this.selectDirectories) ||
+				(!isDirectory && !this.selectFiles)){ return; }
+		}else{
+			value = null;
+		}
+		if(!this._itemsMatch(this.value, value)){
+			this.value = value;
+			this._onChange(value);
+		}
+	}	
+});
\ No newline at end of file
diff --git a/dojox/widget/FilePicker/FilePicker.css b/dojox/widget/FilePicker/FilePicker.css
index d57847a..fefea25 100644
--- a/dojox/widget/FilePicker/FilePicker.css
+++ b/dojox/widget/FilePicker/FilePicker.css
@@ -1,153 +1,18 @@
-.dojoxRollingList {
-	border: 1px solid #000;
-	height: 20em;
-	background-color: #FFF;
-	position: relative;
-}
-.dijitPopup .dojoxRollingList {
-	position: static;
-}
-.dojoxRollingListContainer {
-	overflow: scroll;
-	overflow-y: hidden;
-	overflow-x: scroll;
-	white-space: nowrap;
-}
-.dojoxRollingListButtons {
-	position: absolute;
-	right: 5px;
-	padding: 5px 0px;
-}
-.dojoxRollingListButtonsHidden .dojoxRollingListButtons {
-	display: none;
-}
-.dojoxRollingListPane {
-	overflow: scroll;
-	overflow-x: hidden;
-	overflow-y: scroll;
-	display:-moz-inline-box;		
-	display:inline-block;			
-	#zoom: 1; 
-	#display:inline; 
-	border:0;
-	padding:0;
-	vertical-align:middle;
-	#vertical-align: auto;	
-}
-.dojoxRollingListPane .dijitMenuItem td {
-	width: 1px;
-}
-.dojoxRollingListPane .dijitMenuItem td.dijitMenuItemLabel {
-	width: auto;
-}
-.dojoxRollingListPane .dijitMenuItemLabel,
-.dojoxRollingListPane .dijitMenuItemIcon {
-	position: static !important;
-}
-.dj_webkit .dojoxRollingListPane,
-.dj_ie .dojoxRollingListPane {
-	padding-right: 15px; 
-}
-.dojoxRollingListPane .dijitMenu {
-	border: none !important;
-}
-.dojoxRollingListItem {
-	cursor: default;
-}
-.tundra .dojoxRollingList {
-	border-color: #b3b3b3;
-}
-.tundra .dijitPopup .dojoxRollingList {
-	border-color: #406b9b;
-}
-.tundra .dojoxRollingListPane {
-	background-color: #f7f7f7;
-}
-.tundra .dojoxRollingListPane .dojoxRollingListItemHover,
-.tundra .dojoxRollingListPane .dojoxRollingListItemFocus {
-	background-color: #e3e3e3;
-}
-.tundra .dojoxRollingListPane .dojoxRollingListItemSelected {
-	color: #fff;
-	background-color: #999;
-	font-weight: bold;
-}
-.tundra .dojoxRollingListPaneCurrentSelected .dojoxRollingListItemSelected {
-	background-color: #3559ac;
-}
-.tundra .dojoxRollingListPane .dojoxRollingListItemHoverSelected,
-.tundra .dojoxRollingListPane .dojoxRollingListItemFocusSelected {
-	background-color: #9aacd6;
-}
-.tundra .dojoxRollingListItem {
-	font-family: inherit;
-}
-.soria .dojoxRollingList {
-	border-color: #8ba0bd;
-}
-.soria .dijitPopup .dojoxRollingList {
-	border-color: #406b9b;
-}
-.soria .dojoxRollingListPane {
-	background-color: #fff;
-}
-.soria .dojoxRollingListPane .dojoxRollingListItemHover, 
-.soria .dojoxRollingListPane .dojoxRollingListItemFocus {
-	background-color: #e3e3e3;
-}
-.soria .dojoxRollingListPane .dojoxRollingListItemSelected {
-	color: #243C5F;
-	background-color: #ccc;
-	font-weight: bold;
-}
-.soria .dojoxRollingListPaneCurrentSelected .dojoxRollingListItemSelected {
-	background-color: #d9e6f9;
-}
-.soria .dojoxRollingListPane .dojoxRollingListItemHoverSelected,
-.soria .dojoxRollingListPane .dojoxRollingListItemFocusSelected {
-	background-color: #ecf3fc;
-}
-.soria .dojoxRollingListItem {
-	font-family: inherit;
-}
-.nihilo .dojoxRollingList {
-	border-color: #d3d3d3;
-}
-.nihilo .dijitPopup .dojoxRollingList {
-	border-color: #b3b3b3;
-}
-.nihilo .dojoxRollingListPane {
-	background-color: #fff;
-}
-.nihilo .dojoxRollingListPane .dojoxRollingListItemHover,
-.nihilo .dojoxRollingListPane .dojoxRollingListItemFocus {
-	background-color: #e3e3e3;
-}
-.nihilo .dojoxRollingListPane .dojoxRollingListItemSelected {
-	color: #243C5F;
-	background-color: #ccc;
-	font-weight: bold;
-}
-.nihilo .dojoxRollingListPaneCurrentSelected .dojoxRollingListItemSelected {
-	background-color: #ffe284;
-}
-.nihilo .dojoxRollingListPane .dojoxRollingListItemHoverSelected,
-.nihilo .dojoxRollingListPane .dojoxRollingListItemFocusSelected {
-	background-color: #fff1c2;
-}
-.nihilo .dojoxRollingListItem {
-	font-family: inherit;
-}
+ at import url("../RollingList/RollingList.css");
+
 .dojoxFileInfoPane *{
 	white-space: normal;
 }
+
 .dojoxFileInfoLabel {
 	font-weight: bold;
 	white-space: nowrap;
 }
+
 .dojoxFileInfoPane {
 	width: 20em;
 }
+
 .tundra .dojoxFilePickerItem .dijitMenuItemIcon {
 	background-image: url("images/tundraFileIcons.gif");
 	background-repeat: no-repeat;
@@ -167,6 +32,7 @@
 .tundra .dojoxFilePickerItemSelected .dojoxFileItemIcon {
 	background-position: -48px;
 }
+
 .soria .dojoxFilePickerItem .dijitMenuItemIcon {
 	background-image: url("images/soriaFileIcons.gif");
 	background-repeat: no-repeat;
@@ -186,6 +52,8 @@
 .soria .dojoxFilePickerItemSelected .dojoxFileItemIcon {
 	background-position: -48px;
 }
+
+
 .nihilo .dojoxFilePickerItem .dijitMenuItemIcon {
 	background-image: url("images/nihiloFileIcons.gif");
 	background-repeat: no-repeat;
@@ -205,3 +73,4 @@
 .nihilo .dojoxFilePickerItemSelected .dojoxFileItemIcon {
 	background-position: -48px;
 }
+
diff --git a/dojox/widget/FisheyeList.js b/dojox/widget/FisheyeList.js
index 6ffea3b..505da18 100644
--- a/dojox/widget/FisheyeList.js
+++ b/dojox/widget/FisheyeList.js
@@ -1,428 +1,703 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.FisheyeList"]){
-dojo._hasResource["dojox.widget.FisheyeList"]=true;
 dojo.provide("dojox.widget.FisheyeList");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Container");
 dojo.require("dijit._Contained");
-dojo.declare("dojox.widget.FisheyeList",[dijit._Widget,dijit._Templated,dijit._Container],{constructor:function(){
-this.pos={"x":-1,"y":-1};
-this.timerScale=1;
-},EDGE:{CENTER:0,LEFT:1,RIGHT:2,TOP:3,BOTTOM:4},templateString:"<div class=\"dojoxFisheyeListBar\" dojoAttachPoint=\"containerNode\"></div>",snarfChildDomOutput:true,itemWidth:40,itemHeight:40,itemMaxWidth:150,itemMaxHeight:150,imgNode:null,orientation:"horizontal",isFixed:false,conservativeTrigger:false,effectUnits:2,itemPadding:10,attachEdge:"center",labelEdge:"bottom",postCreate:function(){
-var e=this.EDGE;
-dojo.setSelectable(this.domNode,false);
-var _1=this.isHorizontal=(this.orientation=="horizontal");
-this.selectedNode=-1;
-this.isOver=false;
-this.hitX1=-1;
-this.hitY1=-1;
-this.hitX2=-1;
-this.hitY2=-1;
-this.anchorEdge=this._toEdge(this.attachEdge,e.CENTER);
-this.labelEdge=this._toEdge(this.labelEdge,e.TOP);
-if(this.labelEdge==e.CENTER){
-this.labelEdge=e.TOP;
-}
-if(_1){
-if(this.anchorEdge==e.LEFT){
-this.anchorEdge=e.CENTER;
-}
-if(this.anchorEdge==e.RIGHT){
-this.anchorEdge=e.CENTER;
-}
-if(this.labelEdge==e.LEFT){
-this.labelEdge=e.TOP;
-}
-if(this.labelEdge==e.RIGHT){
-this.labelEdge=e.TOP;
-}
-}else{
-if(this.anchorEdge==e.TOP){
-this.anchorEdge=e.CENTER;
-}
-if(this.anchorEdge==e.BOTTOM){
-this.anchorEdge=e.CENTER;
-}
-if(this.labelEdge==e.TOP){
-this.labelEdge=e.LEFT;
-}
-if(this.labelEdge==e.BOTTOM){
-this.labelEdge=e.LEFT;
-}
-}
-var _2=this.effectUnits;
-this.proximityLeft=this.itemWidth*(_2-0.5);
-this.proximityRight=this.itemWidth*(_2-0.5);
-this.proximityTop=this.itemHeight*(_2-0.5);
-this.proximityBottom=this.itemHeight*(_2-0.5);
-if(this.anchorEdge==e.LEFT){
-this.proximityLeft=0;
-}
-if(this.anchorEdge==e.RIGHT){
-this.proximityRight=0;
-}
-if(this.anchorEdge==e.TOP){
-this.proximityTop=0;
-}
-if(this.anchorEdge==e.BOTTOM){
-this.proximityBottom=0;
-}
-if(this.anchorEdge==e.CENTER){
-this.proximityLeft/=2;
-this.proximityRight/=2;
-this.proximityTop/=2;
-this.proximityBottom/=2;
-}
-},startup:function(){
-this.children=this.getChildren();
-this._initializePositioning();
-if(!this.conservativeTrigger){
-this._onMouseMoveHandle=dojo.connect(document.documentElement,"onmousemove",this,"_onMouseMove");
-}
-if(this.isFixed){
-this._onScrollHandle=dojo.connect(document,"onscroll",this,"_onScroll");
-}
-this._onMouseOutHandle=dojo.connect(document.documentElement,"onmouseout",this,"_onBodyOut");
-this._addChildHandle=dojo.connect(this,"addChild",this,"_initializePositioning");
-this._onResizeHandle=dojo.connect(window,"onresize",this,"_initializePositioning");
-},_initializePositioning:function(){
-this.itemCount=this.children.length;
-this.barWidth=(this.isHorizontal?this.itemCount:1)*this.itemWidth;
-this.barHeight=(this.isHorizontal?1:this.itemCount)*this.itemHeight;
-this.totalWidth=this.proximityLeft+this.proximityRight+this.barWidth;
-this.totalHeight=this.proximityTop+this.proximityBottom+this.barHeight;
-for(var i=0;i<this.children.length;i++){
-this.children[i].posX=this.itemWidth*(this.isHorizontal?i:0);
-this.children[i].posY=this.itemHeight*(this.isHorizontal?0:i);
-this.children[i].cenX=this.children[i].posX+(this.itemWidth/2);
-this.children[i].cenY=this.children[i].posY+(this.itemHeight/2);
-var _3=this.isHorizontal?this.itemWidth:this.itemHeight;
-var r=this.effectUnits*_3;
-var c=this.isHorizontal?this.children[i].cenX:this.children[i].cenY;
-var _4=this.isHorizontal?this.proximityLeft:this.proximityTop;
-var _5=this.isHorizontal?this.proximityRight:this.proximityBottom;
-var _6=this.isHorizontal?this.barWidth:this.barHeight;
-var _7=r;
-var _8=r;
-if(_7>c+_4){
-_7=c+_4;
-}
-if(_8>(_6-c+_5)){
-_8=_6-c+_5;
-}
-this.children[i].effectRangeLeft=_7/_3;
-this.children[i].effectRangeRght=_8/_3;
-}
-this.domNode.style.width=this.barWidth+"px";
-this.domNode.style.height=this.barHeight+"px";
-for(var i=0;i<this.children.length;i++){
-var _9=this.children[i];
-var _a=_9.domNode;
-_a.style.left=_9.posX+"px";
-_a.style.top=_9.posY+"px";
-_a.style.width=this.itemWidth+"px";
-_a.style.height=this.itemHeight+"px";
-_9.imgNode.style.left=this.itemPadding+"%";
-_9.imgNode.style.top=this.itemPadding+"%";
-_9.imgNode.style.width=(100-2*this.itemPadding)+"%";
-_9.imgNode.style.height=(100-2*this.itemPadding)+"%";
-}
-this._calcHitGrid();
-},_overElement:function(_b,e){
-_b=dojo.byId(_b);
-var _c={x:e.pageX,y:e.pageY};
-var bb=dojo._getBorderBox(_b);
-var _d=dojo.coords(_b,true);
-var _e=_d.y;
-var _f=_e+bb.h;
-var _10=_d.x;
-var _11=_10+bb.w;
-return (_c.x>=_10&&_c.x<=_11&&_c.y>=_e&&_c.y<=_f);
-},_onBodyOut:function(e){
-if(this._overElement(dojo.body(),e)){
-return;
-}
-this._setDormant(e);
-},_setDormant:function(e){
-if(!this.isOver){
-return;
-}
-this.isOver=false;
-if(this.conservativeTrigger){
-dojo.disconnect(this._onMouseMoveHandle);
-}
-this._onGridMouseMove(-1,-1);
-},_setActive:function(e){
-if(this.isOver){
-return;
-}
-this.isOver=true;
-if(this.conservativeTrigger){
-this._onMouseMoveHandle=dojo.connect(document.documentElement,"onmousemove",this,"_onMouseMove");
-this.timerScale=0;
-this._onMouseMove(e);
-this._expandSlowly();
-}
-},_onMouseMove:function(e){
-if((e.pageX>=this.hitX1)&&(e.pageX<=this.hitX2)&&(e.pageY>=this.hitY1)&&(e.pageY<=this.hitY2)){
-if(!this.isOver){
-this._setActive(e);
-}
-this._onGridMouseMove(e.pageX-this.hitX1,e.pageY-this.hitY1);
-}else{
-if(this.isOver){
-this._setDormant(e);
-}
-}
-},_onScroll:function(){
-this._calcHitGrid();
-},onResized:function(){
-this._calcHitGrid();
-},_onGridMouseMove:function(x,y){
-this.pos={x:x,y:y};
-this._paint();
-},_paint:function(){
-var x=this.pos.x;
-var y=this.pos.y;
-if(this.itemCount<=0){
-return;
-}
-var pos=this.isHorizontal?x:y;
-var prx=this.isHorizontal?this.proximityLeft:this.proximityTop;
-var siz=this.isHorizontal?this.itemWidth:this.itemHeight;
-var sim=this.isHorizontal?(1-this.timerScale)*this.itemWidth+this.timerScale*this.itemMaxWidth:(1-this.timerScale)*this.itemHeight+this.timerScale*this.itemMaxHeight;
-var cen=((pos-prx)/siz)-0.5;
-var _12=(sim/siz)-0.5;
-if(_12>this.effectUnits){
-_12=this.effectUnits;
-}
-var _13=0;
-if(this.anchorEdge==this.EDGE.BOTTOM){
-var _14=(y-this.proximityTop)/this.itemHeight;
-_13=(_14>0.5)?1:y/(this.proximityTop+(this.itemHeight/2));
-}
-if(this.anchorEdge==this.EDGE.TOP){
-var _14=(y-this.proximityTop)/this.itemHeight;
-_13=(_14<0.5)?1:(this.totalHeight-y)/(this.proximityBottom+(this.itemHeight/2));
-}
-if(this.anchorEdge==this.EDGE.RIGHT){
-var _14=(x-this.proximityLeft)/this.itemWidth;
-_13=(_14>0.5)?1:x/(this.proximityLeft+(this.itemWidth/2));
-}
-if(this.anchorEdge==this.EDGE.LEFT){
-var _14=(x-this.proximityLeft)/this.itemWidth;
-_13=(_14<0.5)?1:(this.totalWidth-x)/(this.proximityRight+(this.itemWidth/2));
-}
-if(this.anchorEdge==this.EDGE.CENTER){
-if(this.isHorizontal){
-_13=y/(this.totalHeight);
-}else{
-_13=x/(this.totalWidth);
-}
-if(_13>0.5){
-_13=1-_13;
-}
-_13*=2;
-}
-for(var i=0;i<this.itemCount;i++){
-var _15=this._weighAt(cen,i);
-if(_15<0){
-_15=0;
-}
-this._setItemSize(i,_15*_13);
-}
-var _16=Math.round(cen);
-var _17=0;
-if(cen<0){
-_16=0;
-}else{
-if(cen>this.itemCount-1){
-_16=this.itemCount-1;
-}else{
-_17=(cen-_16)*((this.isHorizontal?this.itemWidth:this.itemHeight)-this.children[_16].sizeMain);
-}
-}
-this._positionElementsFrom(_16,_17);
-},_weighAt:function(cen,i){
-var _18=Math.abs(cen-i);
-var _19=((cen-i)>0)?this.children[i].effectRangeRght:this.children[i].effectRangeLeft;
-return (_18>_19)?0:(1-_18/_19);
-},_setItemSize:function(p,_1a){
-_1a*=this.timerScale;
-var w=Math.round(this.itemWidth+((this.itemMaxWidth-this.itemWidth)*_1a));
-var h=Math.round(this.itemHeight+((this.itemMaxHeight-this.itemHeight)*_1a));
-if(this.isHorizontal){
-this.children[p].sizeW=w;
-this.children[p].sizeH=h;
-this.children[p].sizeMain=w;
-this.children[p].sizeOff=h;
-var y=0;
-if(this.anchorEdge==this.EDGE.TOP){
-y=(this.children[p].cenY-(this.itemHeight/2));
-}else{
-if(this.anchorEdge==this.EDGE.BOTTOM){
-y=(this.children[p].cenY-(h-(this.itemHeight/2)));
-}else{
-y=(this.children[p].cenY-(h/2));
-}
-}
-this.children[p].usualX=Math.round(this.children[p].cenX-(w/2));
-this.children[p].domNode.style.top=y+"px";
-this.children[p].domNode.style.left=this.children[p].usualX+"px";
-}else{
-this.children[p].sizeW=w;
-this.children[p].sizeH=h;
-this.children[p].sizeOff=w;
-this.children[p].sizeMain=h;
-var x=0;
-if(this.anchorEdge==this.EDGE.LEFT){
-x=this.children[p].cenX-(this.itemWidth/2);
-}else{
-if(this.anchorEdge==this.EDGE.RIGHT){
-x=this.children[p].cenX-(w-(this.itemWidth/2));
-}else{
-x=this.children[p].cenX-(w/2);
-}
-}
-this.children[p].domNode.style.left=x+"px";
-this.children[p].usualY=Math.round(this.children[p].cenY-(h/2));
-this.children[p].domNode.style.top=this.children[p].usualY+"px";
-}
-this.children[p].domNode.style.width=w+"px";
-this.children[p].domNode.style.height=h+"px";
-if(this.children[p].svgNode){
-this.children[p].svgNode.setSize(w,h);
-}
-},_positionElementsFrom:function(p,_1b){
-var pos=0;
-if(this.isHorizontal){
-pos=Math.round(this.children[p].usualX+_1b);
-this.children[p].domNode.style.left=pos+"px";
-}else{
-pos=Math.round(this.children[p].usualY+_1b);
-this.children[p].domNode.style.top=pos+"px";
-}
-this._positionLabel(this.children[p]);
-var _1c=pos;
-for(var i=p-1;i>=0;i--){
-_1c-=this.children[i].sizeMain;
-if(this.isHorizontal){
-this.children[i].domNode.style.left=_1c+"px";
-}else{
-this.children[i].domNode.style.top=_1c+"px";
-}
-this._positionLabel(this.children[i]);
-}
-var _1d=pos;
-for(var i=p+1;i<this.itemCount;i++){
-_1d+=this.children[i-1].sizeMain;
-if(this.isHorizontal){
-this.children[i].domNode.style.left=_1d+"px";
-}else{
-this.children[i].domNode.style.top=_1d+"px";
-}
-this._positionLabel(this.children[i]);
-}
-},_positionLabel:function(itm){
-var x=0;
-var y=0;
-var mb=dojo.marginBox(itm.lblNode);
-if(this.labelEdge==this.EDGE.TOP){
-x=Math.round((itm.sizeW/2)-(mb.w/2));
-y=-mb.h;
-}
-if(this.labelEdge==this.EDGE.BOTTOM){
-x=Math.round((itm.sizeW/2)-(mb.w/2));
-y=itm.sizeH;
-}
-if(this.labelEdge==this.EDGE.LEFT){
-x=-mb.w;
-y=Math.round((itm.sizeH/2)-(mb.h/2));
-}
-if(this.labelEdge==this.EDGE.RIGHT){
-x=itm.sizeW;
-y=Math.round((itm.sizeH/2)-(mb.h/2));
-}
-itm.lblNode.style.left=x+"px";
-itm.lblNode.style.top=y+"px";
-},_calcHitGrid:function(){
-var pos=dojo.coords(this.domNode,true);
-this.hitX1=pos.x-this.proximityLeft;
-this.hitY1=pos.y-this.proximityTop;
-this.hitX2=this.hitX1+this.totalWidth;
-this.hitY2=this.hitY1+this.totalHeight;
-},_toEdge:function(inp,def){
-return this.EDGE[inp.toUpperCase()]||def;
-},_expandSlowly:function(){
-if(!this.isOver){
-return;
-}
-this.timerScale+=0.2;
-this._paint();
-if(this.timerScale<1){
-setTimeout(dojo.hitch(this,"_expandSlowly"),10);
-}
-},destroyRecursive:function(){
-dojo.disconnect(this._onMouseOutHandle);
-dojo.disconnect(this._onMouseMoveHandle);
-dojo.disconnect(this._addChildHandle);
-if(this.isFixed){
-dojo.disconnect(this._onScrollHandle);
-}
-dojo.disconnect(this._onResizeHandle);
-this.inherited("destroyRecursive",arguments);
-}});
-dojo.declare("dojox.widget.FisheyeListItem",[dijit._Widget,dijit._Templated,dijit._Contained],{iconSrc:"",label:"",id:"",templateString:"<div class=\"dojoxFisheyeListItem\">"+"  <img class=\"dojoxFisheyeListItemImage\" dojoAttachPoint=\"imgNode\" dojoAttachEvent=\"onmouseover:onMouseOver,onmouseout:onMouseOut,onclick:onClick\">"+"  <div class=\"dojoxFisheyeListItemLabel\" dojoAttachPoint=\"lblNode\"></div>"+"</div>",_isNode:function(wh){
-if(typeof Element=="function"){
-try{
-return wh instanceof Element;
-}
-catch(e){
-}
-}else{
-return wh&&!isNaN(wh.nodeType);
-}
-},_hasParent:function(_1e){
-return Boolean(_1e&&_1e.parentNode&&this._isNode(_1e.parentNode));
-},postCreate:function(){
-if((this.iconSrc.toLowerCase().substring(this.iconSrc.length-4)==".png")&&dojo.isIE<7){
-if(this._hasParent(this.imgNode)&&this.id!=""){
-var _1f=this.imgNode.parentNode;
-_1f.setAttribute("id",this.id);
-}
-this.imgNode.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.iconSrc+"', sizingMethod='scale')";
-this.imgNode.src=this._blankGif.toString();
-}else{
-if(this._hasParent(this.imgNode)&&this.id!=""){
-var _1f=this.imgNode.parentNode;
-_1f.setAttribute("id",this.id);
-}
-this.imgNode.src=this.iconSrc;
-}
-if(this.lblNode){
-this.lblNode.appendChild(document.createTextNode(this.label));
-}
-dojo.setSelectable(this.domNode,false);
-this.startup();
-},startup:function(){
-this.parent=this.getParent();
-},onMouseOver:function(e){
-if(!this.parent.isOver){
-this.parent._setActive(e);
-}
-if(this.label!=""){
-dojo.addClass(this.lblNode,"dojoxFishSelected");
-this.parent._positionLabel(this);
-}
-},onMouseOut:function(e){
-dojo.removeClass(this.lblNode,"dojoxFishSelected");
-},onClick:function(e){
-}});
-}
+
+dojo.declare("dojox.widget.FisheyeList", [dijit._Widget, dijit._Templated, dijit._Container], {
+	// summary:
+	//	Menu similar to the fish eye menu on the Mac OS
+	// example:
+	// |	<div dojoType="FisheyeList"
+	// |		itemWidth="40" itemHeight="40"
+	// |		itemMaxWidth="150" itemMaxHeight="150"
+	// |		orientation="horizontal"
+	// |		effectUnits="2"
+	// |		itemPadding="10"
+	// |		attachEdge="center"
+	// |		labelEdge="bottom">
+	// |
+	// |		<div dojoType="FisheyeListItem"
+	// |			id="item1"
+	// |			onclick="alert('click on' + this.label + '(from widget id ' + this.widgetId + ')!');"
+	// |			label="Item 1"
+	// |			iconSrc="images/fisheye_1.png">
+	// |		</div>
+	// |		...
+	// |	</div>
+	//
+	constructor: function(){
+		//
+		// TODO
+		// fix really long labels in vertical mode
+		//
+	
+		this.pos = {'x': -1, 'y': -1};	// current cursor position, relative to the grid
+		
+		// for conservative trigger mode, when triggered, timerScale is gradually increased from 0 to 1
+		this.timerScale = 1.0;
+	
+	},
+
+	EDGE: {
+		CENTER: 0,
+		LEFT: 1,
+		RIGHT: 2,
+		TOP: 3,
+		BOTTOM: 4
+	},
+
+	templateString: '<div class="dojoxFisheyeListBar" dojoAttachPoint="containerNode"></div>',
+
+	snarfChildDomOutput: true,
+	
+	// itemWidth: Integer
+	//	width of menu item (in pixels) in it's dormant state (when the mouse is far away)
+	itemWidth: 40,
+	
+	// itemHeight: Integer
+	//	height of menu item (in pixels) in it's dormant state (when the mouse is far away)
+	itemHeight: 40,
+	
+	// itemMaxWidth: Integer
+	//	width of menu item (in pixels) in it's fully enlarged state (when the mouse is directly over it)
+	itemMaxWidth: 150,
+	
+	// itemMaxHeight: Integer
+	//	height of menu item (in pixels) in it's fully enlarged state (when the mouse is directly over it)
+	itemMaxHeight: 150,
+
+	imgNode: null,
+	
+	// orientation: String
+	//	orientation of the menu, either "horizontal" or "vertical"
+	orientation: 'horizontal',
+
+	// isFixed: Boolean
+	//	toggle to enable additional listener (window scroll) if FisheyeList is in a fixed postion
+	isFixed: false,
+	
+	// conservativeTrigger: Boolean
+	//	if true, don't start enlarging menu items until mouse is over an image;
+	//	if false, start enlarging menu items as the mouse moves near them.
+	conservativeTrigger: false,
+	
+	// effectUnits: Number
+	//	controls how much reaction the menu makes, relative to the distance of the mouse from the menu
+	effectUnits: 2,
+		
+	// itemPadding: Integer
+	//	padding (in pixels) betweeen each menu item
+	itemPadding: 10,
+	
+	// attachEdge: String
+	//	controls the border that the menu items don't expand past;
+	//	for example, if set to "top", then the menu items will drop downwards as they expand.
+	// values
+	//	"center", "left", "right", "top", "bottom".
+	attachEdge: 'center',
+
+	// labelEdge: String
+	//	controls were the labels show up in relation to the menu item icons
+	// values
+	//	"center", "left", "right", "top", "bottom".
+	labelEdge: 'bottom',
+
+	postCreate: function(){
+		var e = this.EDGE;
+		dojo.setSelectable(this.domNode, false);
+
+		var isHorizontal = this.isHorizontal = (this.orientation == 'horizontal');
+		this.selectedNode = -1;
+
+		this.isOver = false;
+		this.hitX1 = -1;
+		this.hitY1 = -1;
+		this.hitX2 = -1;
+		this.hitY2 = -1;
+
+		//
+		// only some edges make sense...
+		//
+		this.anchorEdge = this._toEdge(this.attachEdge, e.CENTER);
+		this.labelEdge  = this._toEdge(this.labelEdge,  e.TOP);
+
+		if(this.labelEdge == e.CENTER){ this.labelEdge = e.TOP; }
+
+		if(isHorizontal){
+			if(this.anchorEdge == e.LEFT){ this.anchorEdge = e.CENTER; }
+			if(this.anchorEdge == e.RIGHT){ this.anchorEdge = e.CENTER; }
+			if(this.labelEdge == e.LEFT){ this.labelEdge = e.TOP; }
+			if(this.labelEdge == e.RIGHT){ this.labelEdge = e.TOP; }
+		}else{
+			if(this.anchorEdge == e.TOP){ this.anchorEdge = e.CENTER; }
+			if(this.anchorEdge == e.BOTTOM){ this.anchorEdge = e.CENTER; }
+			if(this.labelEdge == e.TOP){ this.labelEdge = e.LEFT; }
+			if(this.labelEdge == e.BOTTOM){ this.labelEdge = e.LEFT; }
+		}
+
+		//
+		// figure out the proximity size
+		//
+		var effectUnits = this.effectUnits;
+		this.proximityLeft   = this.itemWidth  * (effectUnits - 0.5);
+		this.proximityRight  = this.itemWidth  * (effectUnits - 0.5);
+		this.proximityTop    = this.itemHeight * (effectUnits - 0.5);
+		this.proximityBottom = this.itemHeight * (effectUnits - 0.5);
+	
+		if(this.anchorEdge == e.LEFT){
+			this.proximityLeft = 0;
+		}
+		if(this.anchorEdge == e.RIGHT){
+			this.proximityRight = 0;
+		}
+		if(this.anchorEdge == e.TOP){
+			this.proximityTop = 0;
+		}
+		if(this.anchorEdge == e.BOTTOM){
+			this.proximityBottom = 0;
+		}
+		if(this.anchorEdge == e.CENTER){
+			this.proximityLeft   /= 2;
+			this.proximityRight  /= 2;
+			this.proximityTop    /= 2;
+			this.proximityBottom /= 2;
+		}
+	},
+	
+	startup: function(){
+		// summary: create our connections and setup our FisheyeList
+		this.children = this.getChildren();
+		//original postCreate() --tk
+		this._initializePositioning();
+	
+		//
+		// in liberal trigger mode, activate menu whenever mouse is close
+		//
+		if(!this.conservativeTrigger){
+			this._onMouseMoveHandle = dojo.connect(document.documentElement, "onmousemove", this, "_onMouseMove");
+		}
+		if (this.isFixed){
+			this._onScrollHandle = dojo.connect(document,"onscroll",this,"_onScroll");
+		}
+			
+		// Deactivate the menu if mouse is moved off screen (doesn't work for FF?)
+		this._onMouseOutHandle = dojo.connect(document.documentElement, "onmouseout", this, "_onBodyOut");
+		this._addChildHandle = dojo.connect(this, "addChild", this, "_initializePositioning");
+		this._onResizeHandle = dojo.connect(window,"onresize", this, "_initializePositioning");
+	},
+	
+	_initializePositioning: function(){
+		this.itemCount = this.children.length;
+	
+		this.barWidth  = (this.isHorizontal ? this.itemCount : 1) * this.itemWidth;
+		this.barHeight = (this.isHorizontal ? 1 : this.itemCount) * this.itemHeight;
+	
+		this.totalWidth  = this.proximityLeft + this.proximityRight  + this.barWidth;
+		this.totalHeight = this.proximityTop  + this.proximityBottom + this.barHeight;
+	
+		//
+		// calculate effect ranges for each item
+		//
+
+		for(var i=0; i<this.children.length; i++){
+
+			this.children[i].posX = this.itemWidth  * (this.isHorizontal ? i : 0);
+			this.children[i].posY = this.itemHeight * (this.isHorizontal ? 0 : i);
+
+			this.children[i].cenX = this.children[i].posX + (this.itemWidth  / 2);
+			this.children[i].cenY = this.children[i].posY + (this.itemHeight / 2);
+
+			var isz = this.isHorizontal ? this.itemWidth : this.itemHeight;
+			var r = this.effectUnits * isz;
+			var c = this.isHorizontal ? this.children[i].cenX : this.children[i].cenY;
+			var lhs = this.isHorizontal ? this.proximityLeft : this.proximityTop;
+			var rhs = this.isHorizontal ? this.proximityRight : this.proximityBottom;
+			var siz = this.isHorizontal ? this.barWidth : this.barHeight;
+
+			var range_lhs = r;
+			var range_rhs = r;
+
+			if(range_lhs > c+lhs){ range_lhs = c+lhs; }
+			if(range_rhs > (siz-c+rhs)){ range_rhs = siz-c+rhs; }
+
+			this.children[i].effectRangeLeft = range_lhs / isz;
+			this.children[i].effectRangeRght = range_rhs / isz;
+
+			//dojo.debug('effect range for '+i+' is '+range_lhs+'/'+range_rhs);
+		}
+
+		//
+		// create the bar
+		//
+		this.domNode.style.width = this.barWidth + 'px';
+		this.domNode.style.height = this.barHeight + 'px';
+
+		//
+		// position the items
+		//
+		for(var i=0; i<this.children.length; i++){
+			var itm = this.children[i];
+			var elm = itm.domNode;
+			elm.style.left   = itm.posX + 'px';
+			elm.style.top    = itm.posY + 'px';
+			elm.style.width  = this.itemWidth + 'px';
+			elm.style.height = this.itemHeight + 'px';
+			
+			itm.imgNode.style.left = this.itemPadding+'%';
+			itm.imgNode.style.top = this.itemPadding+'%';
+			itm.imgNode.style.width = (100 - 2 * this.itemPadding) + '%';
+			itm.imgNode.style.height = (100 - 2 * this.itemPadding) + '%';
+		}
+
+		//
+		// calc the grid
+		//
+		this._calcHitGrid();
+	},
+
+	_overElement: function(/* DomNode|String */node, /* Event */e){
+		// summary:
+		//	Returns whether the mouse is over the passed element.
+		// Node: Must must be display:block (ie, not a <span>)
+		node = dojo.byId(node);
+		var mouse = {x: e.pageX, y: e.pageY};
+		var bb = dojo._getBorderBox(node);
+		var absolute = dojo.coords(node, true);
+		var top = absolute.y;
+		var bottom = top + bb.h;
+		var left = absolute.x;
+		var right = left + bb.w;
+
+		return (mouse.x >= left
+			&& mouse.x <= right
+			&& mouse.y >= top
+			&& mouse.y <= bottom
+		);	//	boolean
+	},
+
+	_onBodyOut: function(/*Event*/ e){
+		// clicking over an object inside of body causes this event to fire; ignore that case
+		if( this._overElement(dojo.body(), e) ){
+			return;
+		}
+		this._setDormant(e);
+	},
+
+	_setDormant: function(/*Event*/ e){
+		// summary: called when mouse moves out of menu's range
+
+		if(!this.isOver){ return; }	// already dormant?
+		this.isOver = false;
+
+		if(this.conservativeTrigger){
+			// user can't re-trigger the menu expansion
+			// until he mouses over a icon again
+			dojo.disconnect(this._onMouseMoveHandle);
+		}
+		this._onGridMouseMove(-1, -1);
+	},
+
+	_setActive: function(/*Event*/ e){
+		// summary: called when mouse is moved into menu's range
+
+		if(this.isOver){ return; }	// already activated?
+		this.isOver = true;
+
+		if(this.conservativeTrigger){
+			// switch event handlers so that we handle mouse events from anywhere near
+			// the menu
+			this._onMouseMoveHandle = dojo.connect(document.documentElement, "onmousemove", this, "_onMouseMove");
+
+			this.timerScale=0.0;
+
+			// call mouse handler to do some initial necessary calculations/positioning
+			this._onMouseMove(e);
+
+			// slowly expand the icon size so it isn't jumpy
+			this._expandSlowly();
+		}
+	},
+
+	_onMouseMove: function(/*Event*/ e){
+		// summary: called when mouse is moved
+		if(	(e.pageX >= this.hitX1) && (e.pageX <= this.hitX2) &&
+			(e.pageY >= this.hitY1) && (e.pageY <= this.hitY2)	){
+			if(!this.isOver){
+				this._setActive(e);
+			}
+			this._onGridMouseMove(e.pageX-this.hitX1, e.pageY-this.hitY1);
+		}else{
+			if(this.isOver){
+				this._setDormant(e);
+			}
+		}
+	},
+
+	_onScroll: function(){
+		this._calcHitGrid();	
+	},
+
+	onResized: function(){
+		this._calcHitGrid();
+	},
+
+	_onGridMouseMove: function(x, y){
+		// summary: called when mouse is moved in the vicinity of the menu
+		this.pos = {x:x, y:y};
+		this._paint();
+	},
+
+	_paint: function(){
+		var x=this.pos.x;
+		var y=this.pos.y;
+
+		if(this.itemCount <= 0){ return; }
+
+		//
+		// figure out our main index
+		//
+		var pos = this.isHorizontal ? x : y;
+		var prx = this.isHorizontal ? this.proximityLeft : this.proximityTop;
+		var siz = this.isHorizontal ? this.itemWidth : this.itemHeight;
+		var sim = this.isHorizontal ? 
+			(1.0-this.timerScale)*this.itemWidth + this.timerScale*this.itemMaxWidth :
+			(1.0-this.timerScale)*this.itemHeight + this.timerScale*this.itemMaxHeight ;
+
+		var cen = ((pos - prx) / siz) - 0.5;
+		var max_off_cen = (sim / siz) - 0.5;
+
+		if(max_off_cen > this.effectUnits){ max_off_cen = this.effectUnits; }
+
+		//
+		// figure out our off-axis weighting
+		//
+		var off_weight = 0;
+
+		if(this.anchorEdge == this.EDGE.BOTTOM){
+			var cen2 = (y - this.proximityTop) / this.itemHeight;
+			off_weight = (cen2 > 0.5) ? 1 : y / (this.proximityTop + (this.itemHeight / 2));
+		}
+		if(this.anchorEdge == this.EDGE.TOP){
+			var cen2 = (y - this.proximityTop) / this.itemHeight;
+			off_weight = (cen2 < 0.5) ? 1 : (this.totalHeight - y) / (this.proximityBottom + (this.itemHeight / 2));
+		}
+		if(this.anchorEdge == this.EDGE.RIGHT){
+			var cen2 = (x - this.proximityLeft) / this.itemWidth;
+			off_weight = (cen2 > 0.5) ? 1 : x / (this.proximityLeft + (this.itemWidth / 2));
+		}
+		if(this.anchorEdge == this.EDGE.LEFT){
+			var cen2 = (x - this.proximityLeft) / this.itemWidth;
+			off_weight = (cen2 < 0.5) ? 1 : (this.totalWidth - x) / (this.proximityRight + (this.itemWidth / 2));
+		}
+		if(this.anchorEdge == this.EDGE.CENTER){
+			if(this.isHorizontal){
+				off_weight = y / (this.totalHeight);
+			}else{
+				off_weight = x / (this.totalWidth);
+			}
+
+			if(off_weight > 0.5){
+				off_weight = 1 - off_weight;
+			}
+
+			off_weight *= 2;
+		}
+
+		//
+		// set the sizes
+		//
+		for(var i=0; i<this.itemCount; i++){
+			var weight = this._weighAt(cen, i);
+			if(weight < 0){weight = 0;}
+			this._setItemSize(i, weight * off_weight);
+		}
+
+		//
+		// set the positions
+		//
+
+		var main_p = Math.round(cen);
+		var offset = 0;
+
+		if(cen < 0){
+
+			main_p = 0;
+
+		}else if(cen > this.itemCount - 1){
+
+			main_p = this.itemCount -1;
+
+		}else{
+
+			offset = (cen - main_p) * ((this.isHorizontal ? this.itemWidth : this.itemHeight) - this.children[main_p].sizeMain);
+		}
+
+		this._positionElementsFrom(main_p, offset);
+	},
+
+	_weighAt: function(/*Integer*/ cen, /*Integer*/ i){
+		var dist = Math.abs(cen - i);
+		var limit = ((cen - i) > 0) ? this.children[i].effectRangeRght : this.children[i].effectRangeLeft;
+		return (dist > limit) ? 0 : (1 - dist / limit); // Integer
+	},
+
+	_setItemSize: function(p, scale){
+		scale *= this.timerScale;
+		var w = Math.round(this.itemWidth  + ((this.itemMaxWidth  - this.itemWidth ) * scale));
+		var h = Math.round(this.itemHeight + ((this.itemMaxHeight - this.itemHeight) * scale));
+
+		if(this.isHorizontal){
+
+			this.children[p].sizeW = w;
+			this.children[p].sizeH = h;
+
+			this.children[p].sizeMain = w;
+			this.children[p].sizeOff  = h;
+
+			var y = 0;
+			if(this.anchorEdge == this.EDGE.TOP){
+				y = (this.children[p].cenY - (this.itemHeight / 2));
+			}else if(this.anchorEdge == this.EDGE.BOTTOM){
+				y = (this.children[p].cenY - (h - (this.itemHeight / 2)));
+			}else{
+				y = (this.children[p].cenY - (h / 2));
+			}
+
+			this.children[p].usualX = Math.round(this.children[p].cenX - (w / 2));
+			this.children[p].domNode.style.top  = y + 'px';
+			this.children[p].domNode.style.left  = this.children[p].usualX + 'px';
+
+		}else{
+
+			this.children[p].sizeW = w;
+			this.children[p].sizeH = h;
+
+			this.children[p].sizeOff  = w;
+			this.children[p].sizeMain = h;
+
+			var x = 0;
+			if(this.anchorEdge == this.EDGE.LEFT){
+				x = this.children[p].cenX - (this.itemWidth / 2);
+			}else if (this.anchorEdge == this.EDGE.RIGHT){
+				x = this.children[p].cenX - (w - (this.itemWidth / 2));
+			}else{
+				x = this.children[p].cenX - (w / 2);
+			}
+
+			this.children[p].domNode.style.left = x + 'px';
+			this.children[p].usualY = Math.round(this.children[p].cenY - (h / 2));
+
+			this.children[p].domNode.style.top  = this.children[p].usualY + 'px';
+		}
+
+		this.children[p].domNode.style.width  = w + 'px';
+		this.children[p].domNode.style.height = h + 'px';
+
+		if(this.children[p].svgNode){
+			this.children[p].svgNode.setSize(w, h);
+		}
+	},
+
+	_positionElementsFrom: function(p, offset){
+		var pos = 0;
+
+		if(this.isHorizontal){
+			pos = Math.round(this.children[p].usualX + offset);
+			this.children[p].domNode.style.left = pos + 'px';
+		}else{
+			pos = Math.round(this.children[p].usualY + offset);
+			this.children[p].domNode.style.top = pos + 'px';
+		}
+		this._positionLabel(this.children[p]);
+
+		// position before
+		var bpos = pos;
+		for(var i=p-1; i>=0; i--){
+			bpos -= this.children[i].sizeMain;
+
+			if (this.isHorizontal){
+				this.children[i].domNode.style.left = bpos + 'px';
+			}else{
+				this.children[i].domNode.style.top = bpos + 'px';
+			}
+			this._positionLabel(this.children[i]);
+		}
+
+		// position after
+		var apos = pos;
+		for(var i=p+1; i<this.itemCount; i++){
+			apos += this.children[i-1].sizeMain;
+			if(this.isHorizontal){
+				this.children[i].domNode.style.left = apos + 'px';
+			}else{
+				this.children[i].domNode.style.top = apos + 'px';
+			}
+			this._positionLabel(this.children[i]);
+		}
+
+	},
+
+	_positionLabel: function(itm){
+		var x = 0;
+		var y = 0;
+		
+		var mb = dojo.marginBox(itm.lblNode);
+
+		if(this.labelEdge == this.EDGE.TOP){
+			x = Math.round((itm.sizeW / 2) - (mb.w / 2));
+			y = -mb.h;
+		}
+
+		if(this.labelEdge == this.EDGE.BOTTOM){
+			x = Math.round((itm.sizeW / 2) - (mb.w / 2));
+			y = itm.sizeH;
+		}
+
+		if(this.labelEdge == this.EDGE.LEFT){
+			x = -mb.w;
+			y = Math.round((itm.sizeH / 2) - (mb.h / 2));
+		}
+
+		if(this.labelEdge == this.EDGE.RIGHT){
+			x = itm.sizeW;
+			y = Math.round((itm.sizeH / 2) - (mb.h / 2));
+		}
+
+		itm.lblNode.style.left = x + 'px';
+		itm.lblNode.style.top  = y + 'px';
+	},
+
+	_calcHitGrid: function(){
+
+		var pos = dojo.coords(this.domNode, true);
+
+		this.hitX1 = pos.x - this.proximityLeft;
+		this.hitY1 = pos.y - this.proximityTop;
+		this.hitX2 = this.hitX1 + this.totalWidth;
+		this.hitY2 = this.hitY1 + this.totalHeight;
+
+	},
+
+	_toEdge: function(inp, def){
+		return this.EDGE[inp.toUpperCase()] || def;
+	},
+
+	_expandSlowly: function(){
+		// summary: slowly expand the image to user specified max size
+		if(!this.isOver){ return; }
+		this.timerScale += 0.2;
+		this._paint();
+		if(this.timerScale<1.0){
+			setTimeout(dojo.hitch(this, "_expandSlowly"), 10);
+		}
+	},
+
+	destroyRecursive: function(){
+		// need to disconnect when we destroy
+		dojo.disconnect(this._onMouseOutHandle);
+		dojo.disconnect(this._onMouseMoveHandle);
+		dojo.disconnect(this._addChildHandle);
+		if (this.isFixed) { dojo.disconnect(this._onScrollHandle); }
+		dojo.disconnect(this._onResizeHandle); 
+		this.inherited("destroyRecursive",arguments);
+	}
+});
+
+dojo.declare("dojox.widget.FisheyeListItem", [dijit._Widget, dijit._Templated, dijit._Contained], {
+	/*
+	 * summary
+	 *	Menu item inside of a FisheyeList.
+	 *	See FisheyeList documentation for details on usage.
+	 */
+
+	// iconSrc: String
+	//	pathname to image file (jpg, gif, png, etc.) of icon for this menu item
+	iconSrc: "",
+
+	// label: String
+	//	label to print next to the icon, when it is moused-over
+	label: "",
+
+	// id: String
+	//	will be set to the id of the orginal div element
+	id: "",
+
+	templateString:
+		'<div class="dojoxFisheyeListItem">' +
+		'  <img class="dojoxFisheyeListItemImage" dojoAttachPoint="imgNode" dojoAttachEvent="onmouseover:onMouseOver,onmouseout:onMouseOut,onclick:onClick">' +
+		'  <div class="dojoxFisheyeListItemLabel" dojoAttachPoint="lblNode"></div>' +
+		'</div>',
+
+	_isNode: function(/* object */wh){
+		//	summary:
+		//		checks to see if wh is actually a node.
+		if(typeof Element == "function") {
+			try{
+				return wh instanceof Element;	//	boolean
+			}catch(e){}
+		}else{
+			// best-guess
+			return wh && !isNaN(wh.nodeType);	//	boolean
+		}
+	},
+
+	_hasParent: function(/*Node*/node){
+		//	summary:
+		//		returns whether or not node is a child of another node.
+		return Boolean(node && node.parentNode && this._isNode(node.parentNode));	//	boolean
+	},
+
+	postCreate: function() {
+
+		// set image
+		if((this.iconSrc.toLowerCase().substring(this.iconSrc.length-4)==".png") && dojo.isIE < 7){
+			/* we set the id of the new fisheyeListItem to the id of the div defined in the HTML */
+			if(this._hasParent(this.imgNode) && this.id != ""){
+				var parent = this.imgNode.parentNode;
+				parent.setAttribute("id", this.id);
+			}
+			this.imgNode.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.iconSrc+"', sizingMethod='scale')";
+			this.imgNode.src = this._blankGif.toString();
+		}else{
+			if(this._hasParent(this.imgNode) && this.id != ""){
+				var parent = this.imgNode.parentNode;
+				parent.setAttribute("id", this.id);
+			}
+			this.imgNode.src = this.iconSrc;
+		}
+
+		// Label
+		if(this.lblNode){
+			this.lblNode.appendChild(document.createTextNode(this.label));
+		}
+		dojo.setSelectable(this.domNode, false);
+		this.startup();
+	},
+
+	startup: function(){
+		this.parent = this.getParent();
+	},
+	
+	onMouseOver: function(/*Event*/ e){
+		// summary: callback when user moves mouse over this menu item
+		// in conservative mode, don't activate the menu until user mouses over an icon
+		if(!this.parent.isOver){
+			this.parent._setActive(e);
+		}
+		if(this.label != "" ){
+			dojo.addClass(this.lblNode, "dojoxFishSelected");
+			this.parent._positionLabel(this);
+		}
+	},
+	
+	onMouseOut: function(/*Event*/ e){
+		// summary: callback when user moves mouse off of this menu item
+		dojo.removeClass(this.lblNode, "dojoxFishSelected");
+	},
+
+	onClick: function(/*Event*/ e){
+		// summary: user overridable callback when user clicks this menu item
+	}
+});
diff --git a/dojox/widget/FisheyeList/FisheyeList.css b/dojox/widget/FisheyeList/FisheyeList.css
index c9b78a9..82469d8 100644
--- a/dojox/widget/FisheyeList/FisheyeList.css
+++ b/dojox/widget/FisheyeList/FisheyeList.css
@@ -8,17 +8,21 @@
 	display: none;
 	white-space:pre; 
 }
+
 .dojoxFisheyeListItemLabel.dojoxFishSelected {
 	display: block;
 }
+
 .dojoxFisheyeListItemImage {
 	border: 0px;
 	position: absolute;
 }
+
 .dojoxFisheyeListItem {
 	position: absolute;
 	z-index: 2;
 }
+
 .dojoxFisheyeListBar {
 	position: relative;
 }
diff --git a/dojox/widget/FisheyeLite.js b/dojox/widget/FisheyeLite.js
index 5222017..b3c53f4 100644
--- a/dojox/widget/FisheyeLite.js
+++ b/dojox/widget/FisheyeLite.js
@@ -1,42 +1,149 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.FisheyeLite"]){
-dojo._hasResource["dojox.widget.FisheyeLite"]=true;
 dojo.provide("dojox.widget.FisheyeLite");
 dojo.experimental("dojox.widget.FisheyeLite");
+
 dojo.require("dijit._Widget");
 dojo.require("dojo.fx.easing");
-dojo.declare("dojox.widget.FisheyeLite",dijit._Widget,{durationIn:350,easeIn:dojo.fx.easing.backOut,durationOut:1420,easeOut:dojo.fx.easing.elasticOut,properties:null,units:"px",constructor:function(_1,_2){
-this.properties=_1.properties||{fontSize:2.75};
-},postCreate:function(){
-this.inherited(arguments);
-this._target=dojo.query(".fisheyeTarget",this.domNode)[0]||this.domNode;
-this._makeAnims();
-this.connect(this.domNode,"onmouseover","show");
-this.connect(this.domNode,"onmouseout","hide");
-this.connect(this._target,"onclick","onClick");
-},show:function(){
-this._runningOut.stop();
-this._runningIn.play();
-},hide:function(){
-this._runningIn.stop();
-this._runningOut.play();
-},_makeAnims:function(){
-var _3={},_4={},cs=dojo.getComputedStyle(this._target);
-for(var p in this.properties){
-var _5=this.properties[p],_6=dojo.isObject(_5),v=parseInt(cs[p]);
-_4[p]={end:v,units:this.units};
-_3[p]=_6?_5:{end:_5*v,units:this.units};
-}
-this._runningIn=dojo.animateProperty({node:this._target,easing:this.easeIn,duration:this.durationIn,properties:_3});
-this._runningOut=dojo.animateProperty({node:this._target,duration:this.durationOut,easing:this.easeOut,properties:_4});
-this.connect(this._runningIn,"onEnd",dojo.hitch(this,"onSelected",this));
-},onClick:function(e){
-},onSelected:function(e){
-}});
-}
+
+dojo.declare("dojox.widget.FisheyeLite",
+	dijit._Widget,
+	{
+	// summary:  A Light-weight Fisheye Component, or an exhanced version
+	//		of dojo.fx.Toggler ... 
+	//
+	// description:
+	//		A Simple FisheyeList-like widget which (in the interest of
+	//		performance) relies on well-styled content for positioning,
+	// 		and natural page layout for rendering.
+	//
+	//		use position:absolute/relative nodes to prevent layout
+	//		changes, and use caution when seleting properties to
+	//		scale. Negative scaling works, but some properties
+	//		react poorly to being set to negative values, IE being
+	//		particularly annoying in that regard.
+	//
+	//		quirk: uses the domNode as the target of the animation
+	//		unless it finds a node class="fisheyeTarget" in the container
+	//		being turned into a FisheyeLite instance
+	//
+	// example:
+	//	|	// make all the LI's in a node Fisheye's:
+	//	|   dojo.query("#node li").forEach(function(n){
+	// 	|		new dojox.widget.FisheyeLite({},n);
+	//	|	});
+	//
+	//
+	// example:
+	//	|	new dojox.widget.FisheyeLite({ 
+	//	|		properties:{
+	//	|			// height is literal, width is multiplied
+	//	|			height:{ end: 200 }, width:2.3
+	//	|		}
+	//	|	}, "someNode");
+	//
+	// duationIn: Integer
+	//		The time (in ms) the run the show animation
+	durationIn: 350,
+	
+	// easeIn: Function
+	//		An easing function to use for the show animation
+	easeIn: dojo.fx.easing.backOut,
+	
+	// durationOut: Integer
+	//		The Time (in ms) to run the hide animation
+	durationOut: 1420,
+	
+	// easeOut: Function	
+	// 		An easing function to use for the hide animation
+	easeOut: dojo.fx.easing.elasticOut,
+
+	//	properties: Object
+	//			An object of "property":scale pairs, or "property":{} pairs.
+	//			defaults to font-size with a scale of 2.75
+	//			If a named property is an integer or float, the "scale multiplier"
+	//			is used. If the named property is an object, that object is mixed
+	//			into the animation directly. eg: height:{ end:20, units:"em" }
+	properties: null,
+	
+	// units: String
+	//		Sometimes, you need to specify a unit. Should be part of
+	//		properties attrib, but was trying to shorthand the logic there
+	units:"px",
+	
+	constructor: function(props, node){
+		this.properties = props.properties || {
+			fontSize: 2.75
+		}
+	},
+	
+	postCreate: function(){
+		
+		this.inherited(arguments);
+		this._target = dojo.query(".fisheyeTarget", this.domNode)[0] || this.domNode;
+		this._makeAnims();
+		
+		this.connect(this.domNode, "onmouseover", "show");
+		this.connect(this.domNode, "onmouseout", "hide");
+		this.connect(this._target, "onclick", "onClick");
+
+	},
+	
+	show: function(){
+		// summary:
+		//		Show this Fisheye item. 
+		this._runningOut.stop();
+		this._runningIn.play();
+	},
+	
+	hide: function(){
+		// summary:
+		//		Hide this fisheye item on mouse leave
+		this._runningIn.stop();
+		this._runningOut.play();
+	},
+	
+	_makeAnims: function(){
+		// summary:
+		//		Pre-generate the animations
+
+		// create two properties: objects, one for each "state"
+		var _in = {}, _out = {}, cs = dojo.getComputedStyle(this._target);
+		for(var p in this.properties){
+			var prop = this.properties[p],
+				deep = dojo.isObject(prop),
+				v = parseInt(cs[p])
+			;
+			// note: do not set negative scale for [a list of properties] for IE support
+			// note: filter:'s are your own issue, too ;)
+			// FIXME: this.unit here is bad, likely. d._toPixelValue ?
+			_out[p] = { end: v, units:this.units };
+			_in[p] = deep ? prop : { end: prop * v, units:this.units };
+		}
+		
+		this._runningIn = dojo.animateProperty({
+			node: this._target,
+			easing: this.easeIn,
+			duration: this.durationIn,
+			properties: _in
+		});
+		
+		this._runningOut = dojo.animateProperty({
+			node: this._target,
+			duration: this.durationOut,
+			easing: this.easeOut,
+			properties: _out
+		});
+		
+		this.connect(this._runningIn, "onEnd", dojo.hitch(this, "onSelected", this));
+	},
+	
+	onClick: function(/* Event */e){
+		// summary: stub function fired when target is clicked
+		//		connect or override to use.
+	},
+	
+	onSelected: function(/* Object */e){
+		// summary: stub function fired when Fisheye Item is fully visible and
+		// 		hovered. connect or override use.
+	}
+	
+});
diff --git a/dojox/widget/Iterator.js b/dojox/widget/Iterator.js
index 256be19..b2e82a2 100644
--- a/dojox/widget/Iterator.js
+++ b/dojox/widget/Iterator.js
@@ -1,83 +1,173 @@
+dojo.provide("dojox.widget.Iterator");
+dojo.require("dijit.Declaration");
+
+dojo.experimental("dojox.widget.Iterator"); // level: prototype, designed for dijit.chat.demo
+
 /*
-	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
+	example:
+		from markup:
+	|	<span dojoType="dojo.data.ItemFileReadStore" 
+	|		jsId="cstore" url="countries.json"></span>
+	|	
+	|	<div>
+	|		<div dojoType="dojox.widget.Iterator" store="cstore"
+	|			query="{ name: 'A*'}">
+	|			${name} is a ${type}
+	|		</div>
+	|	</div>
+
+	example:
+		programmatic:
+	|	var store = new dojo.data.ItemFileReadStore({ url: "countries.json" });
+	|	
+	|	var iter = new dojox.widget.Iterator({ 
+	|		store: store,
+	|		template: ""
+	|	});
+	|		
+
+	example:
+		programmatic from an array of objects:
+	|	var dataArr = [
+	|		{ name: "foo", valueAttr: "bar" },
+	|		{ name: "thinger", valueAttr: "blah" }
+	|	];
+	|	
+	|	var iter = new dojox.widget.Iterator({ 
+	|		data: dataArr,
+	|		template: ""
+	|	});
+
+	example:
+		programmatic from an array of strings:
+	|	var dataArr = [
+	|		{ name: "foo", valueAttr: "bar" },
+	|		{ name: "thinger", valueAttr: "blah" }
+	|	];
+	|	
+	|	var iter = new dojox.widget.Iterator({ 
+	|		data: dataArr,
+	|		template: ""
+	|	});
+
 */
 
 
-if(!dojo._hasResource["dojox.widget.Iterator"]){
-dojo._hasResource["dojox.widget.Iterator"]=true;
-dojo.provide("dojox.widget.Iterator");
-dojo.require("dijit.Declaration");
-dojo.experimental("dojox.widget.Iterator");
-dojo.declare("dojox.widget.Iterator",[dijit.Declaration],{constructor:(function(){
-var _1=0;
-return function(){
-this.attrs=[];
-this.children=[];
-this.widgetClass="dojox.widget.Iterator._classes._"+(_1++);
-};
-})(),start:0,fetchMax:1000,query:{name:"*"},attrs:[],defaultValue:"",widgetCtor:null,dataValues:[],data:null,store:null,_srcIndex:0,_srcParent:null,_setSrcIndex:function(s){
-this._srcIndex=0;
-this._srcParent=s.parentNode;
-var ts=s;
-while(ts.previousSibling){
-this._srcIndex++;
-ts=ts.previousSibling;
-}
-},postscript:function(p,s){
-this._setSrcIndex(s);
-this.inherited("postscript",arguments);
-var wc=this.widgetCtor=dojo.getObject(this.widgetClass);
-this.attrs=dojo.map(wc.prototype.templateString.match(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g),function(s){
-return s.slice(2,-1);
-});
-dojo.forEach(this.attrs,function(m){
-wc.prototype[m]="";
+dojo.declare("dojox.widget.Iterator",
+	[ dijit.Declaration ],
+	{
+
+	constructor: (function(){
+		var ctr = 0;
+		return function(){
+			this.attrs = [];
+			this.children = [];
+			this.widgetClass = "dojox.widget.Iterator._classes._"+(ctr++);
+		}
+	})(),
+
+	start: 0,
+	fetchMax: 1000,
+	query: { name: "*" },
+	attrs: [],
+	defaultValue: "",
+	widgetCtor: null,
+	dataValues: [], // an array of strings
+	data: null, // should be a reference to an Array
+	store: null,
+	_srcIndex: 0,
+	_srcParent: null, 
+
+	_setSrcIndex: function(s){
+		this._srcIndex = 0;
+		this._srcParent = s.parentNode;
+		var ts = s;
+		while(ts.previousSibling){
+			this._srcIndex++;
+			ts = ts.previousSibling;
+		};
+	},
+
+	postscript: function(p, s){
+		// figure out the position of the source node in it's parent
+		this._setSrcIndex(s);
+		// this._srcIndex = dojo.query(">", this._srcParent).indexOf(s);
+
+		this.inherited("postscript", arguments);
+		var wc = this.widgetCtor = dojo.getObject(this.widgetClass);
+
+		this.attrs = dojo.map(
+			wc.prototype.templateString.match(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g),
+			function(s){ return s.slice(2, -1); }
+		);
+		dojo.forEach(
+			this.attrs,
+			function(m){ wc.prototype[m] = ""; }
+		);
+		this.update();
+	},
+
+	clear: function(){
+		if(this.children.length){
+			this._setSrcIndex(this.children[0].domNode);
+		}
+		dojo.forEach(this.children, "item.destroy();");
+		this.children = [];
+	},
+
+	update: function(){
+		if(this.store){
+			// we're executing a query
+			this.fetch();
+		}else{
+			// we came from an array of objects. Easier!
+			this.onDataAvailable(this.data||this.dataValues);
+		}
+	},
+
+	_addItem: function(/*Object*/config, idx){
+		if(dojo.isString(config)){
+			config = { value: config };
+		}
+		var widget = new this.widgetCtor(config);
+		this.children.push(widget);
+		dojo.place(widget.domNode, this._srcParent, this._srcIndex+idx);
+	},
+
+	getAttrValuesObj: function(item){
+		var obj = {};
+		if(dojo.isString(item)){
+			dojo.forEach(this.attrs, function(attr){
+				obj[attr] = (attr == "value") ? item : this.defaultValue;
+			}, this);
+		}else{
+			dojo.forEach(this.attrs, function(attr){
+				if(this.store){
+					obj[attr] = this.store.getValue(item, attr)||this.defaultValue;
+				}else{
+					obj[attr] = item[attr]||this.defaultValue;
+				}
+			}, this);
+		}
+		return obj;
+	},
+
+	onDataAvailable: function(data){
+		this.clear();
+		// console.debug(data);
+		dojo.forEach(data, function(item, idx){
+			this._addItem(this.getAttrValuesObj(item), idx);
+		}, this);
+	},
+
+	fetch: function(query, start, end){
+		this.store.fetch({
+			query: query||this.query,
+			start: start||this.start,
+			count: end||this.fetchMax,
+			onComplete: dojo.hitch(this,"onDataAvailable")
+		});
+	}
 });
-this.update();
-},clear:function(){
-if(this.children.length){
-this._setSrcIndex(this.children[0].domNode);
-}
-dojo.forEach(this.children,"item.destroy();");
-this.children=[];
-},update:function(){
-if(this.store){
-this.fetch();
-}else{
-this.onDataAvailable(this.data||this.dataValues);
-}
-},_addItem:function(_2,_3){
-if(dojo.isString(_2)){
-_2={value:_2};
-}
-var _4=new this.widgetCtor(_2);
-this.children.push(_4);
-dojo.place(_4.domNode,this._srcParent,this._srcIndex+_3);
-},getAttrValuesObj:function(_5){
-var _6={};
-if(dojo.isString(_5)){
-dojo.forEach(this.attrs,function(_7){
-_6[_7]=(_7=="value")?_5:this.defaultValue;
-},this);
-}else{
-dojo.forEach(this.attrs,function(_8){
-if(this.store){
-_6[_8]=this.store.getValue(_5,_8)||this.defaultValue;
-}else{
-_6[_8]=_5[_8]||this.defaultValue;
-}
-},this);
-}
-return _6;
-},onDataAvailable:function(_9){
-this.clear();
-dojo.forEach(_9,function(_a,_b){
-this._addItem(this.getAttrValuesObj(_a),_b);
-},this);
-},fetch:function(_c,_d,_e){
-this.store.fetch({query:_c||this.query,start:_d||this.start,count:_e||this.fetchMax,onComplete:dojo.hitch(this,"onDataAvailable")});
-}});
-dojox.widget.Iterator._classes={};
-}
+
+dojox.widget.Iterator._classes = {};
diff --git a/dojox/widget/Loader.js b/dojox/widget/Loader.js
index e35c96f..9033823 100644
--- a/dojox/widget/Loader.js
+++ b/dojox/widget/Loader.js
@@ -1,49 +1,106 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.Loader"]){
-dojo._hasResource["dojox.widget.Loader"]=true;
 dojo.provide("dojox.widget.Loader");
-dojo.deprecated("dojox.widget.Loader","","2.0");
+dojo.deprecated("dojox.widget.Loader", "", "2.0"); 
+
 dojo.require("dijit._Widget");
-dojo.require("dijit._Templated");
-dojo.declare("dojox.widget.Loader",[dijit._Widget,dijit._Templated],{loadIcon:dojo.moduleUrl("dojox.widget.Loader","icons/loading.gif"),loadMessage:"Loading ...",hasVisuals:true,attachToPointer:true,duration:125,_offset:16,_pointerConnect:null,_xhrStart:null,_xhrEnd:null,templateString:"<div dojoAttachPoint=\"loadNode\" class=\"dojoxLoader\">"+"<img src=\"${loadIcon}\" class=\"dojoxLoaderIcon\"> <span dojoAttachPoint=\"loadMessageNode\" class=\"dojoxLoaderMessage\"></span>"+"</div>",post [...]
-if(!this.hasVisuals){
-this.loadNode.style.display="none";
-}else{
-if(this.attachToPointer){
-dojo.removeClass(this.loadNode,"dojoxLoader");
-dojo.addClass(this.loadNode,"dojoxLoaderPointer");
-}
-this._hide();
-}
-this._setMessage(this.loadMessage);
-this._xhrStart=this.connect(dojo,"_ioSetArgs","_show");
-this._xhrEnd=this.connect(dojo.Deferred.prototype,"_fire","_hide");
-},_setMessage:function(_1){
-this.loadMessageNode.innerHTML=_1;
-},_putLoader:function(e){
-dijit.placeOnScreen(this.loadNode,{x:e.clientX+this._offset,y:e.clientY+this._offset},["TL","BR"]);
-},_show:function(){
-dojo.publish("Loader",[{message:"started"}]);
-if(this.hasVisuals){
-if(this.attachToPointer){
-this._pointerConnect=this.connect(document,"onmousemove","_putLoader");
-}
-dojo.style(this.loadNode,{opacity:0,display:""});
-dojo.fadeIn({node:this.loadNode,duration:this.duration}).play();
-}
-},_hide:function(){
-dojo.publish("Loader",[{message:"ended"}]);
-if(this.hasVisuals){
-if(this.attachToPointer){
-this.disconnect(this._pointerConnect);
-}
-dojo.fadeOut({node:this.loadNode,duration:this.duration,onEnd:dojo.partial(dojo.style,this.loadNode,"display","none")}).play();
-}
-}});
-}
+dojo.require("dijit._Templated"); 
+
+dojo.declare("dojox.widget.Loader", [dijit._Widget,dijit._Templated], {
+	// summary: a configurable global xhr-listener to display
+	// a loading message during running xhr's or to simply provide 
+	// base-level topic to subscribe to for custom loading messages 
+	//
+	// loadIcon: String
+	// 	location to the icon used. 
+	loadIcon: dojo.moduleUrl("dojox.widget.Loader","icons/loading.gif"),
+
+	// loadMessage: String
+	//	string to use for progress loading
+	loadMessage: 'Loading ...',
+
+	// hasVisuals: Boolean
+	// 	true to display a fixed loading message in TR cornder, false to unly provide
+	//	"Loader" topic to subscribe to for your own custom loading message.	
+	hasVisuals: true,
+
+	// attachToPointer
+	// 	true to use visual indicator where cursor is
+	attachToPointer: true,
+
+	// duration: Integer
+	//	time in ms to toggle in/out the visual load indicator
+	duration: 125,
+
+	// _offset: Integer
+	//	distance in px from the mouse pointer to show attachToPointer avatar
+	_offset: 16, 
+
+	// holder for mousemove connection
+	_pointerConnect: null, 
+	_xhrStart: null,
+	_xhrEnd: null,
+
+	templateString: '<div dojoAttachPoint="loadNode" class="dojoxLoader">'
+		+'<img src="${loadIcon}" class="dojoxLoaderIcon"> <span dojoAttachPoint="loadMessageNode" class="dojoxLoaderMessage"></span>'
+		+'</div>',
+	
+	postCreate: function(){
+		// summary: setup the loader
+
+		if(!this.hasVisuals){ 
+			this.loadNode.style.display = "none"; // _destroy()?
+		}else{
+			if(this.attachToPointer){
+				dojo.removeClass(this.loadNode,"dojoxLoader"); 
+				dojo.addClass(this.loadNode,"dojoxLoaderPointer"); 
+			}
+			this._hide();
+		}
+		this._setMessage(this.loadMessage); 
+
+		// FIXME: create our connections.  would be easier, and this might be redundant
+		// if Deferred published something
+		this._xhrStart = this.connect(dojo,"_ioSetArgs","_show"); 
+		this._xhrEnd = this.connect(dojo.Deferred.prototype,"_fire","_hide"); 
+
+	},
+
+	_setMessage: function(/* String */ message){
+		// summary: set's the message in the loader
+		this.loadMessageNode.innerHTML = message;
+	},
+
+	_putLoader: function(/* Event */ e){
+		// summary: place the floating loading element based on mousemove connection position
+		dijit.placeOnScreen(this.loadNode,{ x: e.clientX+this._offset, y:e.clientY+this._offset }, ["TL","BR"]); 
+	},
+
+	_show: function(){
+		// summary: publish and show progress indicator
+		dojo.publish("Loader",[{ message: 'started' }]);
+		if(this.hasVisuals){ 
+			if(this.attachToPointer){
+				this._pointerConnect = this.connect(document,"onmousemove","_putLoader");
+			}
+			dojo.style(this.loadNode, {
+				opacity:0, display:""
+			});
+			dojo.fadeIn({ node: this.loadNode, duration:this.duration }).play(); 
+		}
+	},
+
+	_hide: function(){
+		// summary: publish "xhr ended" and hide progress indicator
+		dojo.publish("Loader",[{ message: 'ended' }]);
+		if(this.hasVisuals){ 
+			if(this.attachToPointer){
+				this.disconnect(this._pointerConnect); 
+			}
+			dojo.fadeOut({ 
+				node: this.loadNode, 
+				duration:this.duration,
+				onEnd: dojo.partial(dojo.style, this.loadNode, "display", "none")
+			}).play();
+		}
+	}
+
+});
diff --git a/dojox/widget/Loader/Loader.css b/dojox/widget/Loader/Loader.css
index f209d70..4b2d19c 100644
--- a/dojox/widget/Loader/Loader.css
+++ b/dojox/widget/Loader/Loader.css
@@ -2,6 +2,7 @@
 	position:absolute; 
 	z-index:999; 
 }
+
 .dojoxLoader {
 	float:right; 
 	position:fixed; 
@@ -14,10 +15,12 @@
 	background:#fff;  
 	min-width:42px; 
 }
+
 .dojoxLoaderIcon {
 	height:22px; width:22px; 
 	vertical-align:middle; 
 }
+
 .dojoxLoaderMessage {
 	font:8pt Arial,san-serif;
 	color:#666; 
diff --git a/dojox/widget/Loader/icons/loading.gif b/dojox/widget/Loader/icons/loading.gif
old mode 100644
new mode 100755
diff --git a/dojox/widget/Pager.js b/dojox/widget/Pager.js
index b860f0e..e78e776 100644
--- a/dojox/widget/Pager.js
+++ b/dojox/widget/Pager.js
@@ -1,387 +1,550 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.Pager"]){
-dojo._hasResource["dojox.widget.Pager"]=true;
 dojo.provide("dojox.widget.Pager");
 dojo.experimental("dojox.widget.Pager");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dojo.fx");
-dojo.declare("dojox.widget.Pager",[dijit._Widget,dijit._Templated],{templateString:dojo.cache("dojox.widget","Pager/Pager.html","<div dojoAttachPoint=\"pagerContainer\" tabIndex=\"0\" dojoAttachEvent=\"onkeypress: _handleKey, onfocus: _a11yStyle, onblur:_a11yStyle\" class=\"${orientation}PagerContainer\">\n    <div class=\"pagerContainer\">\n\t\t<div dojoAttachPoint=\"pagerContainerStatus\" class=\"${orientation}PagerStatus\"></div>\n\t\t<div dojoAttachPoint=\"pagerContainerView\" class= [...]
-var h=(this.orientation=="horizontal");
-dojo.mixin(this,{_totalPages:0,_currentPage:1,dirClass:"pager"+(h?"Horizontal":"Vertical"),iconNext:dojo.moduleUrl("dojox.widget","Pager/images/"+(h?"h":"v")+"Next.png"),iconPrevious:dojo.moduleUrl("dojox.widget","Pager/images/"+(h?"h":"v")+"Previous.png")});
-},postCreate:function(){
-this.inherited(arguments);
-this.store.fetch({onComplete:dojo.hitch(this,"_init")});
-},_a11yStyle:function(e){
-dojo[(e.type=="focus"?"addClass":"removeClass")](e.target,"pagerFocus");
-},_handleKey:function(e){
-var dk=dojo.keys;
-var _1=(e.charCode==dk.SPACE?dk.SPACE:e.keyCode);
-switch(_1){
-case dk.UP_ARROW:
-case dk.RIGHT_ARROW:
-case 110:
-case 78:
-e.preventDefault();
-this._pagerNext();
-break;
-case dk.DOWN_ARROW:
-case dk.LEFT_ARROW:
-case 112:
-case 80:
-e.preventDefault();
-this._pagerPrevious();
-break;
-case dk.ENTER:
-switch(e.target){
-case this.pagerNext:
-this._pagerNext();
-break;
-case this.pagerPrevious:
-this._pagerPrevious();
-break;
-}
-break;
-}
-},_init:function(_2){
-this.items=_2;
-this._renderPages();
-this._renderStatus();
-this._renderPager();
-},_renderPages:function(){
-var _3=this.pagerContainerView;
-var _4=(this.orientation=="horizontal");
-var _5=dojo.style;
-if(_4){
-var _6=dojo.marginBox(this.pagerContainerPager).h;
-var _7=dojo.marginBox(this.pagerContainerStatus).h;
-if(this.pagerPos!="center"){
-var _8=_6+_7;
-}else{
-var _8=_7;
-var _9=this.pagerIconNext.width;
-var _a=_5(_3,"width");
-var _b=_a-(2*_9);
-_5(_3,{width:_b+"px",marginLeft:this.pagerIconNext.width+"px",marginRight:this.pagerIconNext.width+"px"});
-}
-var _c=_5(this.pagerContainer,"height")-_8;
-_5(this.pagerContainerView,"height",_c+"px");
-var _d=Math.floor(_5(_3,"width")/this.itemsPage);
-if(this.statusPos=="trailing"){
-if(this.pagerPos!="center"){
-_5(_3,"marginTop",_6+"px");
-}
-_5(_3,"marginBottom",_7+"px");
-}else{
-_5(_3,"marginTop",_7+"px");
-if(this.pagerPos!="center"){
-_5(_3,"marginTop",_6+"px");
-}
-}
-}else{
-var _e=dojo.marginBox(this.pagerContainerPager).w;
-var _f=dojo.marginBox(this.pagerContainerStatus).w;
-var _10=_5(this.pagerContainer,"width");
-if(this.pagerPos!="center"){
-var _11=_e+_f;
-}else{
-var _11=_f;
-var _12=this.pagerIconNext.height;
-var _13=_5(_3,"height");
-var _14=_13-(2*_12);
-_5(_3,{height:_14+"px",marginTop:this.pagerIconNext.height+"px",marginBottom:this.pagerIconNext.height+"px"});
-}
-var _15=_5(this.pagerContainer,"width")-_11;
-_5(_3,"width",_15+"px");
-var _d=Math.floor(_5(_3,"height")/this.itemsPage);
-if(this.statusPos=="trailing"){
-if(this.pagerPos!="center"){
-_5(_3,"marginLeft",_e+"px");
-}
-_5(_3,"marginRight",_f+"px");
-}else{
-_5(_3,"marginLeft",_f+"px");
-if(this.pagerPos!="center"){
-_5(_3,"marginRight",_e+"px");
-}
-}
-}
-var _16=dojo.getObject(this.itemClass);
-var _17="padding"+(_4?"Left":"Top");
-var _18="padding"+(_4?"Right":"Bottom");
-dojo.forEach(this.items,function(_19,cnt){
-var _1a=dojo.create("div",{innerHTML:_19.content});
-var _1b=new _16({id:this.id+"-item-"+(cnt+1)},_1a);
-this.pagerItems.appendChild(_1b.domNode);
-var _1c={};
-_1c[(_4?"width":"height")]=(_d-this.itemSpace)+"px";
-var p=(_4?"height":"width");
-_1c[p]=_5(_3,p)+"px";
-_5(_1b.containerNode,_1c);
-if(this.resizeChildren){
-_1b.resizeChildren();
-}
-_1b.parseChildren();
-_5(_1b.domNode,"position","absolute");
-if(cnt<this.itemsPage){
-var pos=(cnt)*_d;
-var _1d=(_4?"left":"top");
-var dir=(_4?"top":"left");
-_5(_1b.domNode,dir,"0px");
-_5(_1b.domNode,_1d,pos+"px");
-}else{
-_5(_1b.domNode,"top","-1000px");
-_5(_1b.domNode,"left","-1000px");
-}
-_5(_1b.domNode,_18,(this.itemSpace/2)+"px");
-_5(_1b.domNode,_17,(this.itemSpace/2)+"px");
-},this);
-},_renderPager:function(){
-var tcp=this.pagerContainerPager;
-var _1e="0px";
-var _1f=(this.orientation=="horizontal");
-if(_1f){
-if(this.statusPos=="center"){
-}else{
-if(this.statusPos=="trailing"){
-dojo.style(tcp,"top",_1e);
-}else{
-dojo.style(tcp,"bottom",_1e);
-}
-}
-dojo.style(this.pagerNext,"right",_1e);
-dojo.style(this.pagerPrevious,"left",_1e);
-}else{
-if(this.statusPos=="trailing"){
-dojo.style(tcp,"left",_1e);
-}else{
-dojo.style(tcp,"right",_1e);
-}
-dojo.style(this.pagerNext,"bottom",_1e);
-dojo.style(this.pagerPrevious,"top",_1e);
-}
-},_renderStatus:function(){
-this._totalPages=Math.ceil(this.items.length/this.itemsPage);
-this.iconWidth=0;
-this.iconHeight=0;
-this.iconsLoaded=0;
-this._iconConnects=[];
-for(var i=1;i<=this._totalPages;i++){
-var _20=new Image();
-var _21=i;
-dojo.connect(_20,"onclick",dojo.hitch(this,function(_22){
-this._pagerSkip(_22);
-},_21));
-this._iconConnects[_21]=dojo.connect(_20,"onload",dojo.hitch(this,function(_23){
-this.iconWidth+=_20.width;
-this.iconHeight+=_20.height;
-this.iconsLoaded++;
-if(this._totalPages==this.iconsLoaded){
-if(this.orientation=="horizontal"){
-if(this.statusPos=="trailing"){
-if(this.pagerPos=="center"){
-var _24=dojo.style(this.pagerContainer,"height");
-var _25=dojo.style(this.pagerContainerStatus,"height");
-dojo.style(this.pagerContainerPager,"top",((_24/2)-(_25/2))+"px");
-}
-dojo.style(this.pagerContainerStatus,"bottom","0px");
-}else{
-if(this.pagerPos=="center"){
-var _24=dojo.style(this.pagerContainer,"height");
-var _25=dojo.style(this.pagerContainerStatus,"height");
-dojo.style(this.pagerContainerPager,"bottom",((_24/2)-(_25/2))+"px");
-}
-dojo.style(this.pagerContainerStatus,"top","0px");
-}
-var _26=(dojo.style(this.pagerContainer,"width")/2)-(this.iconWidth/2);
-dojo.style(this.pagerContainerStatus,"paddingLeft",_26+"px");
-}else{
-if(this.statusPos=="trailing"){
-if(this.pagerPos=="center"){
-var _27=dojo.style(this.pagerContainer,"width");
-var _28=dojo.style(this.pagerContainerStatus,"width");
-dojo.style(this.pagerContainerPager,"left",((_27/2)-(_28/2))+"px");
-}
-dojo.style(this.pagerContainerStatus,"right","0px");
-}else{
-if(this.pagerPos=="center"){
-var _27=dojo.style(this.pagerContainer,"width");
-var _28=dojo.style(this.pagerContainerStatus,"width");
-dojo.style(this.pagerContainerPager,"right",((_27/2)-(_28/2))+"px");
-}
-dojo.style(this.pagerContainerStatus,"left","0px");
-}
-var _26=(dojo.style(this.pagerContainer,"height")/2)-(this.iconHeight/2);
-dojo.style(this.pagerContainerStatus,"paddingTop",_26+"px");
-}
-}
-dojo.disconnect(this._iconConnects[_23]);
-},_21));
-if(i==this._currentPage){
-_20.src=this.iconPageActive;
-}else{
-_20.src=this.iconPage;
-}
-var _21=i;
-dojo.addClass(_20,this.orientation+"PagerIcon");
-dojo.attr(_20,"id",this.id+"-status-"+i);
-this.pagerContainerStatus.appendChild(_20);
-if(this.orientation=="vertical"){
-dojo.style(_20,"display","block");
-}
-}
-},_pagerSkip:function(_29){
-if(this._currentPage==_29){
-return;
-}else{
-var _2a;
-var _2b;
-if(_29<this._currentPage){
-_2a=this._currentPage-_29;
-_2b=(this._totalPages+_29)-this._currentPage;
-}else{
-_2a=(this._totalPages+this._currentPage)-_29;
-_2b=_29-this._currentPage;
-}
-var b=(_2b>_2a);
-this._toScroll=(b?_2a:_2b);
-var cmd=(b?"_pagerPrevious":"_pagerNext");
-var _2c=this.connect(this,"onScrollEnd",function(){
-this._toScroll--;
-if(this._toScroll<1){
-this.disconnect(_2c);
-}else{
-this[cmd]();
-}
+
+dojo.declare("dojox.widget.Pager", 
+	[dijit._Widget, dijit._Templated], 
+	{
+	// summary: A Pager, displaying a list of sized nodes
+	
+	
+	templateString: dojo.cache("dojox.widget", "Pager/Pager.html"),
+
+/*=====	
+	// iconPrevious: String?
+	//		The url of the previous page icon
+	iconPrevious: "",
+	
+	// iconNext: String?
+	//		The url of the next page icon
+	iconNext: "",
+=====*/
+
+	iconPage: dojo.moduleUrl("dojox.widget", "Pager/images/pageInactive.png"),
+	iconPageActive: dojo.moduleUrl("dojox.widget", "Pager/images/pageActive.png"),
+	
+	// store: Object
+	//		A dojo.data Data store
+	store: null, // data store for items
+
+	// orientation: String
+	//		Either "horizontal or "vertical" to define the direction the pages will slide
+	orientation: "horizontal", // or vertical
+	
+	// statusPos: String
+	//		A string describing where to put the Pager "current page" indicator. Options are
+	//		"leading" or "trailing". In the case of horiztonal orientation, "leading" indicates
+	//		positioned above the PageItems. In the case of vertical, "leading" indicates "before".
+	statusPos: "leading", 
+	
+	// pagerPos: String
+	//		TODOC
+	pagerPos: "center", 
+
+	// duration: Integer
+	// 		Time in milliseconds to transition the pages
+	duration: 500,
+	
+	// itemSpace: Integer
+	//		Spacing between items? TODOC
+	itemSpace: 2,
+	
+	// resizeChildren: Boolean
+	// 		TODOC
+	resizeChildren: true,
+	
+	// itemClass: String
+	//		The full dotted named of a Class to use for the internal Pager Items.
+	itemClass: "dojox.widget._PagerItem",
+	
+	// itemsPage: Integer
+	//		The numbers of items to display in each "Page"
+	itemsPage: 3, 
+	
+	postMixInProperties: function(){
+		var h = (this.orientation == "horizontal");
+		dojo.mixin(this,{
+			_totalPages:0,
+			_currentPage:1,
+			dirClass: "pager" + (h ? "Horizontal" : "Vertical"),
+			iconNext: dojo.moduleUrl("dojox.widget", "Pager/images/" + (h ? "h" : "v") + "Next.png"),
+			iconPrevious: dojo.moduleUrl("dojox.widget", "Pager/images/" + (h ? "h" : "v") + "Previous.png")
+		});
+	},
+		
+	postCreate: function(){
+		this.inherited(arguments);
+		//this.connect(this.domNode,"onkeypress","_handleKey");
+		this.store.fetch({
+			onComplete: dojo.hitch(this, "_init")
+		});
+		
+	},
+	
+	_a11yStyle: function(e){
+		// summary: top level onfocus/onblur listen to set a class "pagerFocus" on some node
+		// 		and remove it onblur
+		dojo[(e.type == "focus" ? "addClass" : "removeClass")](e.target,"pagerFocus");
+	},
+	
+	_handleKey: function(e){
+		// summary: Handle keyboard navigation internally
+
+		var dk = dojo.keys;
+		var key = (e.charCode == dk.SPACE ? dk.SPACE : e.keyCode);
+		switch(key){
+			
+			case dk.UP_ARROW:
+			case dk.RIGHT_ARROW:
+			case 110:
+			case 78: // key "n"
+				e.preventDefault();
+				this._pagerNext();
+				break;
+
+			case dk.DOWN_ARROW:
+			case dk.LEFT_ARROW:
+			case 112: 
+			case 80: // key "p"
+				e.preventDefault();
+				this._pagerPrevious();
+				break;
+			
+			case dk.ENTER:
+				switch(e.target){
+					case this.pagerNext : this._pagerNext(); break;
+					case this.pagerPrevious : this._pagerPrevious(); break;
+				}
+				break;
+		}
+	},
+	
+	_init: function(items) {
+		this.items = items;
+		this._renderPages();
+		this._renderStatus();
+		this._renderPager();
+	},
+	
+	_renderPages: function(){
+		var pcv = this.pagerContainerView;
+		var _h = (this.orientation == "horizontal");
+		var style = dojo.style;
+		if(_h){
+
+			var pagerH = dojo.marginBox(this.pagerContainerPager).h;
+			var statusH = dojo.marginBox(this.pagerContainerStatus).h;
+			if (this.pagerPos != 'center'){
+				var addonHeight = pagerH+statusH;
+			}else{
+				var addonHeight = statusH;
+				var widthSub = this.pagerIconNext.width;
+				var containerWidth = style(pcv, 'width');
+				var newWidth = containerWidth-(2*widthSub);
+				style(pcv, {
+					width: newWidth+'px',
+					marginLeft: this.pagerIconNext.width+'px',
+					marginRight: this.pagerIconNext.width+'px'
+				});
+			}
+			var totalH = style(this.pagerContainer, 'height') - addonHeight;
+			style(this.pagerContainerView, 'height', totalH+'px');
+			
+			var itemSpace = Math.floor(style(pcv, 'width') / this.itemsPage);
+			if(this.statusPos == 'trailing'){
+				if(this.pagerPos != 'center'){
+					style(pcv, 'marginTop', pagerH+'px');
+				}
+				style(pcv, 'marginBottom', statusH+'px');
+			}else{
+				style(pcv, 'marginTop', statusH+'px');
+				if (this.pagerPos != 'center'){
+					style(pcv, 'marginTop', pagerH+'px');
+				}
+			}
+			
+		}else{
+
+			var pagerW = dojo.marginBox(this.pagerContainerPager).w;
+			var statusW = dojo.marginBox(this.pagerContainerStatus).w;
+			var containerW = style(this.pagerContainer, 'width');
+			if(this.pagerPos != 'center'){
+				var addonWidth = pagerW + statusW;
+			}else{
+				var addonWidth = statusW;
+				var heightSub = this.pagerIconNext.height;
+				var containerHeight = style(pcv, 'height');
+				var newHeight = containerHeight - (2 * heightSub);
+				style(pcv,{
+					height: newHeight+'px',
+					marginTop: this.pagerIconNext.height+'px',
+					marginBottom: this.pagerIconNext.height+'px'
+				});
+			}
+			var totalW = style(this.pagerContainer, 'width') - addonWidth;
+			style(pcv, 'width', totalW+'px');
+			
+			var itemSpace = Math.floor(style(pcv, 'height') / this.itemsPage);
+			if(this.statusPos == 'trailing'){
+				if (this.pagerPos != 'center'){
+					style(pcv, 'marginLeft', pagerW + 'px');
+				}
+				style(pcv, 'marginRight', statusW + 'px');
+			}else{
+				style(pcv, 'marginLeft', statusW + 'px');
+				if(this.pagerPos != 'center'){
+					style(pcv, 'marginRight', pagerW+'px');
+				}
+			}
+		}
+		
+		var _PagerItem = dojo.getObject(this.itemClass);
+		var paddingLead = "padding" + (_h ? "Left" : "Top");
+		var paddingTrail = "padding" + (_h ? "Right" : "Bottom");
+			
+		dojo.forEach(this.items, function(item, cnt){
+			
+			var contentContainer = dojo.create('div', {
+				innerHTML: item.content
+			});
+
+			var pagerItem = new _PagerItem({
+				id: this.id + '-item-' + (cnt + 1)
+			}, contentContainer);
+			
+			this.pagerItems.appendChild(pagerItem.domNode);
+			
+			var containerProps = {};
+			containerProps[(_h ? "width" : "height")] = (itemSpace - this.itemSpace) + "px";
+			var p = (_h ? "height" : "width");
+			containerProps[p] = style(pcv, p) + "px";
+			style(pagerItem.containerNode, containerProps);
+
+			if(this.resizeChildren){
+				pagerItem.resizeChildren();
+			}
+			pagerItem.parseChildren();
+			
+			// only display amount of items as defined in itemsPage
+			style(pagerItem.domNode, "position", "absolute");
+
+			if (cnt < this.itemsPage){
+				var pos = (cnt) * itemSpace;
+				var trailingDir = (_h ? "left" : "top");
+				var dir = (_h ? "top" : "left");
+				style(pagerItem.domNode, dir, "0px");
+				style(pagerItem.domNode, trailingDir, pos+"px");
+			}else{
+				style(pagerItem.domNode, "top", "-1000px");
+				style(pagerItem.domNode, "left", "-1000px");
+			}
+
+			style(pagerItem.domNode, paddingTrail, (this.itemSpace/2)+"px");
+			style(pagerItem.domNode, paddingLead, (this.itemSpace/2)+"px");
+			
+		}, this);
+	},
+	
+	_renderPager: function() {
+		var tcp = this.pagerContainerPager;
+		var zero = "0px";
+		var _h = (this.orientation == "horizontal");
+		if(_h){
+
+			if(this.statusPos == 'center'){
+				
+			}else if (this.statusPos == 'trailing'){
+				dojo.style(tcp, 'top', zero);
+			}else{
+				dojo.style(tcp, 'bottom', zero);
+			}
+			dojo.style(this.pagerNext, 'right', zero);
+			dojo.style(this.pagerPrevious, 'left', zero);
+			
+		}else{
+			
+			if (this.statusPos == 'trailing'){
+				dojo.style(tcp, 'left', zero);
+			}else{
+				dojo.style(tcp, 'right', zero);
+			}
+			dojo.style(this.pagerNext, 'bottom', zero);
+			dojo.style(this.pagerPrevious, 'top', zero);
+		}
+		
+	},
+	
+	_renderStatus: function() {
+		this._totalPages = Math.ceil(this.items.length / this.itemsPage);
+		// FIXME!!
+		this.iconWidth = 0;
+		this.iconHeight = 0;
+		this.iconsLoaded = 0;
+		this._iconConnects = [];
+		
+		for (var i = 1; i <= this._totalPages; i++){
+			var icon = new Image();
+			
+			var pointer = i;
+			dojo.connect(icon, 'onclick', dojo.hitch(this, function(pointer) {
+				this._pagerSkip(pointer);
+			}, pointer));
+			
+			this._iconConnects[pointer] = dojo.connect(icon, 'onload', dojo.hitch(this,function(pointer){
+				this.iconWidth += icon.width;
+				this.iconHeight += icon.height;
+				this.iconsLoaded++;
+
+				if (this._totalPages == this.iconsLoaded){
+					if (this.orientation == "horizontal"){
+						if (this.statusPos == 'trailing'){
+							if (this.pagerPos == 'center'){
+								var containerHeight = dojo.style(this.pagerContainer, 'height');
+								var statusHeight = dojo.style(this.pagerContainerStatus, 'height');
+								dojo.style(this.pagerContainerPager, 'top', ((containerHeight/2)-(statusHeight/2))+'px');
+							}
+							dojo.style(this.pagerContainerStatus, 'bottom', '0px');
+						}else{
+							if (this.pagerPos == 'center'){
+								var containerHeight = dojo.style(this.pagerContainer, 'height');
+								var statusHeight = dojo.style(this.pagerContainerStatus, 'height');
+								dojo.style(this.pagerContainerPager, 'bottom', ((containerHeight/2)-(statusHeight/2))+'px');
+							}
+							dojo.style(this.pagerContainerStatus, 'top', '0px');
+						}
+					
+						var position = (dojo.style(this.pagerContainer, 'width')/2)-(this.iconWidth/2);
+						dojo.style(this.pagerContainerStatus, 'paddingLeft', position+'px');
+					}else{
+						if (this.statusPos == 'trailing'){
+							if (this.pagerPos == 'center'){
+								var containerWidth = dojo.style(this.pagerContainer, 'width');
+								var statusWidth = dojo.style(this.pagerContainerStatus, 'width');
+								dojo.style(this.pagerContainerPager, 'left', ((containerWidth/2)-(statusWidth/2))+'px');
+							}
+							dojo.style(this.pagerContainerStatus, 'right', '0px');
+						}else{
+							if (this.pagerPos == 'center'){
+								var containerWidth = dojo.style(this.pagerContainer, 'width');
+								var statusWidth = dojo.style(this.pagerContainerStatus, 'width');
+								dojo.style(this.pagerContainerPager, 'right', ((containerWidth/2)-(statusWidth/2))+'px');
+							}
+							dojo.style(this.pagerContainerStatus, 'left', '0px');
+						}
+						var position = (dojo.style(this.pagerContainer, 'height')/2)-(this.iconHeight/2);
+						dojo.style(this.pagerContainerStatus, 'paddingTop', position+'px');
+					}
+				}	
+				dojo.disconnect(this._iconConnects[pointer]);
+			}, pointer));
+			
+			if (i==this._currentPage){
+				icon.src=this.iconPageActive;
+			}else{
+				icon.src=this.iconPage;
+			}
+			var pointer = i;
+
+			dojo.addClass(icon, this.orientation+'PagerIcon');
+			dojo.attr(icon, 'id', this.id+'-status-'+i);
+			this.pagerContainerStatus.appendChild(icon);
+					
+			if (this.orientation == "vertical"){
+				dojo.style(icon, 'display', 'block');
+			}
+		}
+	},
+	
+	_pagerSkip: function(page){
+		if (this._currentPage == page){
+			return;
+		}else{
+			// calculate whether to go left or right, take shortest way
+			var distanceP; var distanceN;
+			if (page < this._currentPage){
+				distanceP = this._currentPage - page;
+				distanceN = (this._totalPages + page) - this._currentPage;
+			}else{
+				distanceP = (this._totalPages + this._currentPage) - page;
+				distanceN = page - this._currentPage;
+			}
+			
+			var b = (distanceN > distanceP);
+			this._toScroll = (b ? distanceP : distanceN);
+			var cmd = (b ? "_pagerPrevious" : "_pagerNext");
+			var connect = this.connect(this, "onScrollEnd", function(){
+				this._toScroll--;
+				if(this._toScroll < 1){ 
+					this.disconnect(connect); 
+				}else{
+					this[cmd]();
+				}
+			});
+			this[cmd]();
+			
+		}
+	},
+	
+	_pagerNext: function(){
+		if(this._anim) return;
+
+		/**
+		 * fade slide out current items
+		 * make sure that next items are ligned up nicely before sliding them in
+		 */
+		var _anims = [];
+		for (var i = this._currentPage * this.itemsPage; i > (this._currentPage - 1) * this.itemsPage; i--){
+			if (!dojo.byId(this.id+'-item-'+i)) continue;
+			
+			var currentItem = dojo.byId(this.id+'-item-'+i);
+			var marginBox = dojo.marginBox(currentItem);
+			if (this.orientation == "horizontal") {
+				var move = marginBox.l - (this.itemsPage * marginBox.w);
+				_anims.push(dojo.fx.slideTo({node: currentItem, left: move, duration: this.duration}));
+			}else{
+				var move = marginBox.t - (this.itemsPage * marginBox.h);
+				_anims.push(dojo.fx.slideTo({node: currentItem, top: move, duration: this.duration}));
+			}
+
+		}
+		var previousPage = this._currentPage;
+		if (this._currentPage == this._totalPages){
+			this._currentPage = 1;
+		}else{
+			this._currentPage++;
+		}
+		
+		var cnt = this.itemsPage;
+		for (var i=this._currentPage*this.itemsPage; i>(this._currentPage-1)*this.itemsPage; i--){
+			if (dojo.byId(this.id+'-item-'+i)){
+				var currentItem = dojo.byId(this.id+'-item-'+i);
+				var marginBox = dojo.marginBox(currentItem);
+				if (this.orientation == "horizontal") {
+					var newPos = (dojo.style(this.pagerContainerView, 'width')+((cnt-1)*marginBox.w))-1;
+					dojo.style(currentItem, 'left', newPos+'px');
+					dojo.style(currentItem, 'top', '0px');
+					
+					var move = newPos-(this.itemsPage*marginBox.w);
+					_anims.push(dojo.fx.slideTo({node: currentItem, left: move, duration: this.duration}));
+				}else{
+					newPos = (dojo.style(this.pagerContainerView, 'height')+((cnt-1)*marginBox.h))-1;
+					dojo.style(currentItem, 'top', newPos+'px');
+					dojo.style(currentItem, 'left', '0px');
+					
+					var move = newPos-(this.itemsPage*marginBox.h);
+					_anims.push(dojo.fx.slideTo({ node: currentItem, top: move, duration: this.duration}));
+				}
+			}
+			cnt--;
+		}
+		
+		this._anim = dojo.fx.combine(_anims);
+		var animConnect = this.connect(this._anim, "onEnd", function(){ 
+			delete this._anim; 
+			this.onScrollEnd();
+			this.disconnect(animConnect);
+		});
+		this._anim.play();
+		
+		// set pager icons
+		dojo.byId(this.id+'-status-'+previousPage).src = this.iconPage;
+		dojo.byId(this.id+'-status-'+this._currentPage).src = this.iconPageActive;
+	},
+
+    _pagerPrevious: function(){
+		if(this._anim) return;
+   
+		var _anims = [];
+		for (var i=this._currentPage*this.itemsPage; i>(this._currentPage-1)*this.itemsPage; i--){
+				if (!dojo.byId(this.id+'-item-'+i)) continue;
+		   
+				var currentItem = dojo.byId(this.id+'-item-'+i);
+				var marginBox = dojo.marginBox(currentItem);
+				if (this.orientation == "horizontal") {
+						var move = dojo.style(currentItem, 'left')+(this.itemsPage*marginBox.w);
+						_anims.push(dojo.fx.slideTo({node: currentItem, left: move, duration: this.duration}));
+				}else{
+						var move = dojo.style(currentItem, 'top')+(this.itemsPage*marginBox.h);
+						_anims.push(dojo.fx.slideTo({node: currentItem, top: move, duration: this.duration}));
+				}
+		}
+
+		var previousPage = this._currentPage;
+		if (this._currentPage == 1){
+				this._currentPage = this._totalPages;
+		}else{
+				this._currentPage--;
+		}
+   
+		var cnt = this.itemsPage;
+		var j=1;
+		for (var i=this._currentPage*this.itemsPage; i>(this._currentPage-1)*this.itemsPage; i--){
+			if(dojo.byId(this.id+'-item-'+i)){
+				var currentItem = dojo.byId(this.id+'-item-'+i);
+				var marginBox = dojo.marginBox(currentItem);
+   
+				if (this.orientation == "horizontal") {
+					var newPos = -(j * marginBox.w) + 1;
+					dojo.style(currentItem, 'left', newPos+'px');
+					dojo.style(currentItem, 'top', '0px');
+			   
+					var move = ((cnt - 1) * marginBox.w);
+					_anims.push(dojo.fx.slideTo({node: currentItem, left: move, duration: this.duration}));
+			   
+					var move = newPos+(this.itemsPage * marginBox.w);
+					_anims.push(dojo.fx.slideTo({node: currentItem, left: move, duration: this.duration}));
+				}else{
+					newPos = -((j * marginBox.h) + 1);
+					dojo.style(currentItem, 'top', newPos+'px');
+					dojo.style(currentItem, 'left', '0px');
+			   
+					var move = ((cnt - 1) * marginBox.h);
+					_anims.push(dojo.fx.slideTo({node: currentItem, top: move, duration: this.duration}));
+				}
+		   
+			}
+			cnt--;
+			j++;
+		}
+   
+		this._anim = dojo.fx.combine(_anims);
+		var animConnect = dojo.connect(this._anim, "onEnd", dojo.hitch(this, function(){
+			delete this._anim;
+			this.onScrollEnd();
+			dojo.disconnect(animConnect);
+		}));
+		this._anim.play();
+   
+		// set pager icons
+		dojo.byId(this.id + '-status-' + previousPage).src = this.iconPage;
+		dojo.byId(this.id + '-status-' + this._currentPage).src = this.iconPageActive;
+
+	},
+	
+	onScrollEnd: function(){
+		// summary: Stub Function. Fired after the slide is complete. Override or connect.
+	}
+
 });
-this[cmd]();
-}
-},_pagerNext:function(){
-if(this._anim){
-return;
-}
-var _2d=[];
-for(var i=this._currentPage*this.itemsPage;i>(this._currentPage-1)*this.itemsPage;i--){
-if(!dojo.byId(this.id+"-item-"+i)){
-continue;
-}
-var _2e=dojo.byId(this.id+"-item-"+i);
-var _2f=dojo.marginBox(_2e);
-if(this.orientation=="horizontal"){
-var _30=_2f.l-(this.itemsPage*_2f.w);
-_2d.push(dojo.fx.slideTo({node:_2e,left:_30,duration:this.duration}));
-}else{
-var _30=_2f.t-(this.itemsPage*_2f.h);
-_2d.push(dojo.fx.slideTo({node:_2e,top:_30,duration:this.duration}));
-}
-}
-var _31=this._currentPage;
-if(this._currentPage==this._totalPages){
-this._currentPage=1;
-}else{
-this._currentPage++;
-}
-var cnt=this.itemsPage;
-for(var i=this._currentPage*this.itemsPage;i>(this._currentPage-1)*this.itemsPage;i--){
-if(dojo.byId(this.id+"-item-"+i)){
-var _2e=dojo.byId(this.id+"-item-"+i);
-var _2f=dojo.marginBox(_2e);
-if(this.orientation=="horizontal"){
-var _32=(dojo.style(this.pagerContainerView,"width")+((cnt-1)*_2f.w))-1;
-dojo.style(_2e,"left",_32+"px");
-dojo.style(_2e,"top","0px");
-var _30=_32-(this.itemsPage*_2f.w);
-_2d.push(dojo.fx.slideTo({node:_2e,left:_30,duration:this.duration}));
-}else{
-_32=(dojo.style(this.pagerContainerView,"height")+((cnt-1)*_2f.h))-1;
-dojo.style(_2e,"top",_32+"px");
-dojo.style(_2e,"left","0px");
-var _30=_32-(this.itemsPage*_2f.h);
-_2d.push(dojo.fx.slideTo({node:_2e,top:_30,duration:this.duration}));
-}
-}
-cnt--;
-}
-this._anim=dojo.fx.combine(_2d);
-var _33=this.connect(this._anim,"onEnd",function(){
-delete this._anim;
-this.onScrollEnd();
-this.disconnect(_33);
+
+dojo.declare("dojox.widget._PagerItem",
+	[dijit._Widget, dijit._Templated], 
+	{
+	
+	templateString: '<li class="pagerItem" dojoAttachPoint="containerNode"></li>',
+	
+	resizeChildren: function(){
+		var box = dojo.marginBox(this.containerNode);
+		dojo.style(this.containerNode.firstChild, {
+			width: box.w +'px',
+			height: box.h + 'px'
+		});
+	},
+	
+	parseChildren: function(){
+		dojo.parser.parse(this.containerNode);
+	}
 });
-this._anim.play();
-dojo.byId(this.id+"-status-"+_31).src=this.iconPage;
-dojo.byId(this.id+"-status-"+this._currentPage).src=this.iconPageActive;
-},_pagerPrevious:function(){
-if(this._anim){
-return;
-}
-var _34=[];
-for(var i=this._currentPage*this.itemsPage;i>(this._currentPage-1)*this.itemsPage;i--){
-if(!dojo.byId(this.id+"-item-"+i)){
-continue;
-}
-var _35=dojo.byId(this.id+"-item-"+i);
-var _36=dojo.marginBox(_35);
-if(this.orientation=="horizontal"){
-var _37=dojo.style(_35,"left")+(this.itemsPage*_36.w);
-_34.push(dojo.fx.slideTo({node:_35,left:_37,duration:this.duration}));
-}else{
-var _37=dojo.style(_35,"top")+(this.itemsPage*_36.h);
-_34.push(dojo.fx.slideTo({node:_35,top:_37,duration:this.duration}));
-}
-}
-var _38=this._currentPage;
-if(this._currentPage==1){
-this._currentPage=this._totalPages;
-}else{
-this._currentPage--;
-}
-var cnt=this.itemsPage;
-var j=1;
-for(var i=this._currentPage*this.itemsPage;i>(this._currentPage-1)*this.itemsPage;i--){
-if(dojo.byId(this.id+"-item-"+i)){
-var _35=dojo.byId(this.id+"-item-"+i);
-var _36=dojo.marginBox(_35);
-if(this.orientation=="horizontal"){
-var _39=-(j*_36.w)+1;
-dojo.style(_35,"left",_39+"px");
-dojo.style(_35,"top","0px");
-var _37=((cnt-1)*_36.w);
-_34.push(dojo.fx.slideTo({node:_35,left:_37,duration:this.duration}));
-var _37=_39+(this.itemsPage*_36.w);
-_34.push(dojo.fx.slideTo({node:_35,left:_37,duration:this.duration}));
-}else{
-_39=-((j*_36.h)+1);
-dojo.style(_35,"top",_39+"px");
-dojo.style(_35,"left","0px");
-var _37=((cnt-1)*_36.h);
-_34.push(dojo.fx.slideTo({node:_35,top:_37,duration:this.duration}));
-}
-}
-cnt--;
-j++;
-}
-this._anim=dojo.fx.combine(_34);
-var _3a=dojo.connect(this._anim,"onEnd",dojo.hitch(this,function(){
-delete this._anim;
-this.onScrollEnd();
-dojo.disconnect(_3a);
-}));
-this._anim.play();
-dojo.byId(this.id+"-status-"+_38).src=this.iconPage;
-dojo.byId(this.id+"-status-"+this._currentPage).src=this.iconPageActive;
-},onScrollEnd:function(){
-}});
-dojo.declare("dojox.widget._PagerItem",[dijit._Widget,dijit._Templated],{templateString:"<li class=\"pagerItem\" dojoAttachPoint=\"containerNode\"></li>",resizeChildren:function(){
-var box=dojo.marginBox(this.containerNode);
-dojo.style(this.containerNode.firstChild,{width:box.w+"px",height:box.h+"px"});
-},parseChildren:function(){
-dojo.parser.parse(this.containerNode);
-}});
-}
diff --git a/dojox/widget/Pager/Pager.css b/dojox/widget/Pager/Pager.css
index df6bc82..e6bb23b 100644
--- a/dojox/widget/Pager/Pager.css
+++ b/dojox/widget/Pager/Pager.css
@@ -3,11 +3,14 @@
 	height: 100%;
 	width: 100%;
 	overflow: hidden;
-	
+	/* FIXME: need basline styles for tundra, soria, and nihilo */
 	border:1px solid #ccc;
 	-moz-border-radius:6pt;
 	-webkit-border-radius:7pt;
 }
+
+/* Horizontal classes */
+
 .horizontalPagerPager {
 	position: absolute;
 	height: 12px;
@@ -15,6 +18,7 @@
 	padding-top: 4px;
 	padding-bottom: 4px;
 }
+
 .horizontalPagerStatus {
 	position: absolute;
 	height: 10px;
@@ -22,15 +26,20 @@
 	padding-bottom: 5px;
 	width: 100%;
 }
+
 .horizontalPagerView {
 	position: absolute;
 	height: 100%;
 	width: 100%;
 	overflow: hidden;
 }
+
 .horizontalPagerIcon {
 	cursor: pointer;	
 }
+
+/* Vertical classes */
+
 .verticalPagerPager {
 	position: absolute;
 	width: 12px;
@@ -38,6 +47,7 @@
 	padding-left: 4px;
 	padding-right: 4px;
 }
+
 .verticalPagerStatus {
 	position: absolute;
 	width: 10px;
@@ -45,21 +55,30 @@
 	padding-right: 5px;
 	height: 100%;
 }
+
 .verticalPagerView {
 	position: absolute;
 	height: 100%;
 	width: 100%;
 	overflow: hidden;
 }
+
 .verticalPagerIcon {
 	cursor: pointer;	
 }
+
+/* Misc. */
+
 .pagerIconContainer {
 	position: absolute;	
 }
+
 .pagerIconContainer img {
 	cursor: pointer;	
 }
+
+/* Items */
+
 .pagerItems {
 	list-style: none;
 	padding: 0;
@@ -70,4 +89,4 @@
 	overflow: hidden;
 	padding: 0;
 	margin: 0;
-}
+}
\ No newline at end of file
diff --git a/dojox/widget/PlaceholderMenuItem.js b/dojox/widget/PlaceholderMenuItem.js
index aa47168..3aee250 100644
--- a/dojox/widget/PlaceholderMenuItem.js
+++ b/dojox/widget/PlaceholderMenuItem.js
@@ -1,75 +1,105 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.PlaceholderMenuItem"]){
-dojo._hasResource["dojox.widget.PlaceholderMenuItem"]=true;
 dojo.provide("dojox.widget.PlaceholderMenuItem");
+
 dojo.require("dijit.Menu");
-dojo.declare("dojox.widget.PlaceholderMenuItem",dijit.MenuItem,{_replaced:false,_replacedWith:null,_isPlaceholder:true,postCreate:function(){
-this.domNode.style.display="none";
-this._replacedWith=[];
-if(!this.label){
-this.label=this.containerNode.innerHTML;
-}
-this.inherited(arguments);
-},replace:function(_1){
-if(this._replaced){
-return false;
-}
-var _2=this.getIndexInParent();
-if(_2<0){
-return false;
-}
-var p=this.getParent();
-dojo.forEach(_1,function(_3){
-p.addChild(_3,_2++);
-});
-this._replacedWith=_1;
-this._replaced=true;
-return true;
-},unReplace:function(_4){
-if(!this._replaced){
-return [];
-}
-var p=this.getParent();
-if(!p){
-return [];
-}
-var r=this._replacedWith;
-dojo.forEach(this._replacedWith,function(_5){
-p.removeChild(_5);
-if(_4){
-_5.destroy();
-}
-});
-this._replacedWith=[];
-this._replaced=false;
-return r;
-}});
-dojo.extend(dijit.Menu,{getPlaceholders:function(_6){
-var r=[];
-var _7=this.getChildren();
-_7.forEach(function(_8){
-if(_8._isPlaceholder&&(!_6||_8.label==_6)){
-r.push(_8);
-}else{
-if(_8._started&&_8.popup&&_8.popup.getPlaceholders){
-r=r.concat(_8.popup.getPlaceholders(_6));
-}else{
-if(!_8._started&&_8.dropDownContainer){
-var _9=dojo.query("[widgetId]",_8.dropDownContainer)[0];
-var _a=dijit.byNode(_9);
-if(_a.getPlaceholders){
-r=r.concat(_a.getPlaceholders(_6));
-}
-}
-}
-}
-},this);
-return r;
-}});
-}
+
+dojo.declare("dojox.widget.PlaceholderMenuItem", dijit.MenuItem, {
+	// summary:
+	//		A menu item that can be used as a placeholder.  Set the label
+	//		of this item to a unique key and you can then use it to add new
+	//		items at that location.  This item is not displayed.
+	
+	_replaced: false, 
+	_replacedWith: null, 
+	_isPlaceholder: true, 
+
+	postCreate: function(){ 
+		this.domNode.style.display = "none"; 
+		this._replacedWith = []; 
+		if(!this.label){
+			this.label = this.containerNode.innerHTML;
+		}
+		this.inherited(arguments); 
+	}, 
+	
+	replace: function(/*dijit.MenuItem[]*/ menuItems){ 
+		// summary:
+		//		replaces this menu item with the given menuItems.  The original
+		//		menu item is not actually removed from the menu - so if you want
+		//		it removed, you must do that explicitly.
+		// returns:
+		//		true if the replace happened, false if not
+		if(this._replaced){ return false; } 
+
+		var index = this.getIndexInParent(); 
+		if(index < 0){ return false; } 
+
+		var p = this.getParent(); 
+
+		dojo.forEach(menuItems, function(item){ 
+			p.addChild(item, index++); 
+		}); 
+		this._replacedWith = menuItems; 
+
+		this._replaced = true; 
+		return true;
+	}, 
+	
+	unReplace: function(/*Boolean?*/ destroy){ 
+		// summary:
+		//		Removes menu items added by calling replace().  It returns the
+		//		array of items that were actually removed (in case you want to
+		//		clean them up later)
+		// destroy:
+		//		Also call destroy on any removed items.
+		// returns:
+		//		The array of items that were actually removed
+		
+		if(!this._replaced){ return []; } 
+
+		var p = this.getParent(); 
+		if(!p){ return []; } 
+
+		var r = this._replacedWith; 
+		dojo.forEach(this._replacedWith, function(item){ 
+			p.removeChild(item); 
+			if(destroy){ 
+				item.destroy(); 
+			} 
+		}); 
+		this._replacedWith = []; 
+		this._replaced = false; 
+
+		return r; // dijit.MenuItem[] 
+	} 
+}); 
+
+// Se need to extend dijit.Menu so that we have a getPlaceholders function.
+dojo.extend(dijit.Menu, { 
+	getPlaceholders: function(/*String?*/ label){ 
+		// summary:
+		//		returns an array of placeholders with the given label.  There
+		//		can be multiples.
+		// label:
+		//		Label to search for - if not specified, then all placeholders
+		//		are returned
+		// returns:
+		//		An array of placeholders that match the given label
+		var r = []; 
+
+		var children = this.getChildren(); 
+		children.forEach(function(child){ 
+			if(child._isPlaceholder && (!label || child.label == label)){
+				r.push(child); 
+			}else if(child._started && child.popup && child.popup.getPlaceholders){
+				r = r.concat(child.popup.getPlaceholders(label));
+			}else if(!child._started && child.dropDownContainer){
+				var node = dojo.query("[widgetId]", child.dropDownContainer)[0];
+				var menu = dijit.byNode(node);
+				if(menu.getPlaceholders){
+					r = r.concat(menu.getPlaceholders(label));
+				}
+			}
+		}, this); 
+		return r; // dojox.widget.PlaceholderMenuItem[]
+	}
+}); 
\ No newline at end of file
diff --git a/dojox/widget/Portlet.js b/dojox/widget/Portlet.js
index e4ccaa1..67a5d14 100644
--- a/dojox/widget/Portlet.js
+++ b/dojox/widget/Portlet.js
@@ -1,222 +1,425 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.Portlet"]){
-dojo._hasResource["dojox.widget.Portlet"]=true;
 dojo.experimental("dojox.widget.Portlet");
 dojo.provide("dojox.widget.Portlet");
 dojo.require("dijit.TitlePane");
 dojo.require("dojo.fx");
-dojo.declare("dojox.widget.Portlet",[dijit.TitlePane,dijit._Container],{resizeChildren:true,closable:true,_parents:null,_size:null,dragRestriction:false,buildRendering:function(){
-this.inherited(arguments);
-dojo.style(this.domNode,"visibility","hidden");
-},postCreate:function(){
-this.inherited(arguments);
-dojo.addClass(this.domNode,"dojoxPortlet");
-dojo.removeClass(this.arrowNode,"dijitArrowNode");
-dojo.addClass(this.arrowNode,"dojoxPortletIcon dojoxArrowDown");
-dojo.addClass(this.titleBarNode,"dojoxPortletTitle");
-dojo.addClass(this.hideNode,"dojoxPortletContentOuter");
-dojo.addClass(this.domNode,"dojoxPortlet-"+(!this.dragRestriction?"movable":"nonmovable"));
-var _1=this;
-if(this.resizeChildren){
-this.subscribe("/dnd/drop",function(){
-_1._updateSize();
-});
-this.subscribe("/Portlet/sizechange",function(_2){
-_1.onSizeChange(_2);
-});
-this.connect(window,"onresize",function(){
-_1._updateSize();
-});
-var _3=dojo.hitch(this,function(id,_4){
-var _5=dijit.byId(id);
-if(_5.selectChild){
-var s=this.subscribe(id+"-selectChild",function(_6){
-var n=_1.domNode.parentNode;
-while(n){
-if(n==_6.domNode){
-_1.unsubscribe(s);
-_1._updateSize();
-break;
-}
-n=n.parentNode;
-}
-});
-var _7=dijit.byId(_4);
-if(_5&&_7){
-_1._parents.push({parent:_5,child:_7});
-}
-}
-});
-var _8;
-this._parents=[];
-for(var p=this.domNode.parentNode;p!=null;p=p.parentNode){
-var id=p.getAttribute?p.getAttribute("widgetId"):null;
-if(id){
-_3(id,_8);
-_8=id;
-}
-}
-}
-this.connect(this.titleBarNode,"onmousedown",function(_9){
-if(dojo.hasClass(_9.target,"dojoxPortletIcon")){
-dojo.stopEvent(_9);
-return false;
-}
-return true;
-});
-this.connect(this._wipeOut,"onEnd",function(){
-_1._publish();
-});
-this.connect(this._wipeIn,"onEnd",function(){
-_1._publish();
-});
-if(this.closable){
-this.closeIcon=this._createIcon("dojoxCloseNode","dojoxCloseNodeHover",dojo.hitch(this,"onClose"));
-dojo.style(this.closeIcon,"display","");
-}
-},startup:function(){
-if(this._started){
-return;
-}
-var _a=this.getChildren();
-this._placeSettingsWidgets();
-dojo.forEach(_a,function(_b){
-try{
-if(!_b.started&&!_b._started){
-_b.startup();
-}
-}
-catch(e){
-}
-});
-this.inherited(arguments);
-dojo.style(this.domNode,"visibility","visible");
-},_placeSettingsWidgets:function(){
-dojo.forEach(this.getChildren(),dojo.hitch(this,function(_c){
-if(_c.portletIconClass&&_c.toggle&&!_c.attr("portlet")){
-this._createIcon(_c.portletIconClass,_c.portletIconHoverClass,dojo.hitch(_c,"toggle"));
-dojo.place(_c.domNode,this.containerNode,"before");
-_c.attr("portlet",this);
-}
-}));
-},_createIcon:function(_d,_e,fn){
-var _f=dojo.create("div",{"class":"dojoxPortletIcon "+_d,"waiRole":"presentation"});
-dojo.place(_f,this.arrowNode,"before");
-this.connect(_f,"onclick",fn);
-if(_e){
-this.connect(_f,"onmouseover",function(){
-dojo.addClass(_f,_e);
+
+dojo.declare("dojox.widget.Portlet", [dijit.TitlePane, dijit._Container],{
+	// summary: A container widget that is designed to be contained
+	//		in a dojox.layout.GridContainer. Child widgets can insert
+	//		an icon into the title bar of the Portlet, which when
+	//		clicked, executes the "toggle" method of the child widget.
+	//		A child widget must specify the attribute 
+	//		"portletIconClass", and the optional class
+	//		"portletIconHoverClass", as well as the 
+	//		"toggle" function.
+
+	// resizeChildren: Boolean
+	//		If true, when the Portlet is resized, any child widgets
+	//		with a 'resize' method have that method called.
+	resizeChildren: true,
+
+	// closable: Boolean
+	//		If true, a close button is placed in the title bar,
+	//		and the Portlet can be hidden. If false, the Portlet
+	//		cannot be closed.
+	closable: true,
+
+	// _parents: Array
+	//		 An array of all the StackContainer widgets that this Portlet
+	//		is contained in.	These are used to determine if the portlet
+	//		is visible or not.
+	_parents: null,
+
+	// _size: Object
+	//		Cache of the previous size of the portlet, used to determine
+	//		if the size has changed and if the child widgets should be
+	//		resized.
+	_size: null,
+
+	// dragRestriction: Boolean
+	//		To remove the drag capability.
+	dragRestriction : false,
+
+	buildRendering: function(){
+		this.inherited(arguments);
+
+		// Hide the portlet until it is fully constructed.
+		dojo.style(this.domNode, "visibility", "hidden");
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+
+		// Add the portlet classes
+		dojo.addClass(this.domNode, "dojoxPortlet");
+		dojo.removeClass(this.arrowNode, "dijitArrowNode");
+		dojo.addClass(this.arrowNode, "dojoxPortletIcon dojoxArrowDown");
+		dojo.addClass(this.titleBarNode, "dojoxPortletTitle");
+		dojo.addClass(this.hideNode, "dojoxPortletContentOuter");
+
+		// Choose the class to add depending on if the portlet is draggable or not.
+		dojo.addClass(this.domNode, "dojoxPortlet-" + (!this.dragRestriction ? "movable" : "nonmovable"));
+
+		var _this = this;
+		if(this.resizeChildren){
+			// If children should be resized	when the portlet size changes,
+			// listen for items being dropped, when the window is resized,
+			// or when another portlet's size changes.
+
+			this.subscribe("/dnd/drop", function(){_this._updateSize();});
+
+			this.subscribe("/Portlet/sizechange", function(widget){_this.onSizeChange(widget);});
+			this.connect(window, "onresize", function(){_this._updateSize();});
+
+			// Subscribe to all possible child-selection events that could affect this
+			// portlet
+			var doSelectSubscribe = dojo.hitch(this, function(id, lastId){
+				var widget = dijit.byId(id);
+				if(widget.selectChild){
+					var s = this.subscribe(id + "-selectChild", function(child){
+						var n = _this.domNode.parentNode;
+
+						while(n){
+							if(n == child.domNode){
+								
+								// Only fire this once, as the widget is now visible
+								// at least once, so child measurements should be accurate.
+								_this.unsubscribe(s);
+								_this._updateSize();
+								break;
+							}
+							n = n.parentNode;
+						}
+					});
+
+					// Record the StackContainer and child widget that this portlet
+					// is in, so it can figure out whether or not it is visible.
+					// If it is not visible, it will not update it's size dynamically.
+					var child = dijit.byId(lastId);
+					if(widget && child){
+						_this._parents.push({parent: widget, child: child});
+					}
+				}
+			});
+			var lastId;
+			this._parents = [];
+
+			// Find all parent widgets, and if they are StackContainers,
+			// subscribe to their selectChild method calls.
+			for(var p = this.domNode.parentNode; p != null; p = p.parentNode){
+				var id = p.getAttribute ? p.getAttribute("widgetId") : null;
+				if(id){
+					doSelectSubscribe(id, lastId);
+					lastId = id;
+				}
+			}
+		}
+		
+		// Prevent clicks on icons from causing a drag to start.
+		this.connect(this.titleBarNode, "onmousedown", function(evt){
+			if (dojo.hasClass(evt.target, "dojoxPortletIcon")) {
+				dojo.stopEvent(evt);
+				return false;
+			}
+			return true;
+		});
+
+		// Inform all portlets that the size of this one has changed,
+		// and therefore perhaps they have too
+		this.connect(this._wipeOut, "onEnd", function(){_this._publish();});
+		this.connect(this._wipeIn, "onEnd", function(){_this._publish();});
+
+		if(this.closable){
+			this.closeIcon = this._createIcon("dojoxCloseNode", "dojoxCloseNodeHover", dojo.hitch(this, "onClose"));
+			dojo.style(this.closeIcon, "display", "");
+		}
+	},
+
+	startup: function(){
+		if(this._started){return;}
+
+		var children = this.getChildren();
+		this._placeSettingsWidgets();
+
+		// Start up the children
+		dojo.forEach(children, function(child){
+			try{
+				if(!child.started && !child._started){
+					child.startup()
+				}
+			} 
+			catch(e){
+				console.log(this.id + ":" + this.declaredClass, e);
+			}
+		});
+
+		this.inherited(arguments);
+
+		//this._updateSize();
+		dojo.style(this.domNode, "visibility", "visible");
+	},
+
+	_placeSettingsWidgets: function(){
+		// summary: Checks all the children to see if they are instances
+		//		of dojox.widget.PortletSettings.	If they are, 
+		//		create an icon for them in the title bar which when clicked,
+		//		calls their toggle() method.
+
+		dojo.forEach(this.getChildren(), dojo.hitch(this, function(child){
+			if(child.portletIconClass && child.toggle && !child.attr("portlet")){
+				this._createIcon(child.portletIconClass, child.portletIconHoverClass, dojo.hitch(child, "toggle"));
+				dojo.place(child.domNode, this.containerNode, "before");
+				child.attr("portlet", this);
+				this._settingsWidget = child;
+			}
+		}));
+	},
+
+	_createIcon: function(clazz, hoverClazz, fn){
+		// summary: 
+		//		creates an icon in the title bar.
+
+		var icon = dojo.create("div",{
+			"class": "dojoxPortletIcon " + clazz,
+			"waiRole": "presentation"
+		});
+		dojo.place(icon, this.arrowNode, "before");
+
+		this.connect(icon, "onclick", fn);
+
+		if(hoverClazz){
+			this.connect(icon, "onmouseover", function(){
+				dojo.addClass(icon, hoverClazz);
+			});
+			this.connect(icon, "onmouseout", function(){
+				dojo.removeClass(icon, hoverClazz);
+			});
+		}
+		return icon;
+	},
+
+	onClose: function(evt){
+		// summary: 
+		//		Hides the portlet. Note that it does not
+		//		persist this, so it is up to the client to
+		//		listen to this method and persist the closed state
+		//		in their own way.
+		dojo.style(this.domNode, "display", "none");
+	},
+
+	onSizeChange: function(widget){
+		// summary:
+		//		Updates the Portlet size if any other Portlet
+		//		changes its size.
+		if(widget == this){
+			return;
+		}
+		this._updateSize();
+	},
+
+	_updateSize: function(){
+		// summary: 
+		//		Updates the size of all child widgets.
+		if(!this.open || !this._started || !this.resizeChildren){
+			return;
+		}
+		
+		if(this._timer){
+			clearTimeout(this._timer);
+		}
+		// Delay applying the size change in case the size 
+		// changes very frequently, for performance reasons.
+		this._timer = setTimeout(dojo.hitch(this, function(){
+			var size ={
+				w: dojo.style(this.domNode, "width"),
+				h: dojo.style(this.domNode, "height")
+			};
+	
+			// If the Portlet is in a StackWidget, and it is not
+			// visible, do not update the size, as it could
+			// make child widgets miscalculate.
+			for(var i = 0; i < this._parents.length; i++){
+				var p = this._parents[i];
+				var sel = p.parent.selectedChildWidget
+				if(sel && sel != p.child){
+					return;
+				}
+			}
+	
+			if(this._size){
+				// If the size of the portlet hasn't changed, don't
+				// resize the children, as this can be expensive
+				if(this._size.w == size.w && this._size.h == size.h){
+					return;
+				}
+			}
+			this._size = size;
+	
+			
+
+			var fns = ["resize", "layout"];
+			this._timer = null;
+			var kids = this.getChildren();
+
+			dojo.forEach(kids, function(child){
+				for(var i = 0; i < fns.length; i++){
+					if(dojo.isFunction(child[fns[i]])){
+						try{
+							child[fns[i]]();
+						} catch(e){
+							console.log(e);
+						}
+						break;
+					} 
+				}
+			});	
+			this.onUpdateSize();
+		}), 100);
+	},
+
+	onUpdateSize: function(){
+		// summary:
+		//		Stub function called when the size is changed.
+	},
+
+	_publish: function(){
+		// summary: Publishes an event that all other portlets listen to.
+		//		This causes them to update their child widgets if their
+		//		size has changed.
+		dojo.publish("/Portlet/sizechange",[this]);
+	},
+
+	_onTitleClick: function(evt){
+		if(evt.target == this.arrowNode){
+			this.inherited(arguments);
+		}
+	},
+
+	addChild: function(child){
+		// summary: 
+		//		Adds a child widget to the portlet.
+		this._size = null;
+		this.inherited(arguments);
+		
+		if(this._started){
+			this._placeSettingsWidgets();
+			this._updateSize();
+		}
+		if(this._started && !child.started && !child._started){
+			child.startup();
+		}
+	},
+	
+	destroyDescendants: function(/*Boolean*/ preserveDom){
+		this.inherited(arguments);
+		if(this._settingsWidget){
+			this._settingsWidget.destroyRecursive(preserveDom);
+		}
+	},
+	
+	_setCss: function(){
+		this.inherited(arguments);
+		dojo.style(this.arrowNode, "display", this.toggleable ? "":"none");
+	}
 });
-this.connect(_f,"onmouseout",function(){
-dojo.removeClass(_f,_e);
+
+dojo.declare("dojox.widget.PortletSettings", [dijit._Container, dijit.layout.ContentPane],{
+	// summary: 
+	//		A settings widget to be used with a dojox.widget.Portlet.
+	// description: 
+	//		This widget should be placed inside a dojox.widget.Portlet widget.
+	//		It is used to set some preferences for that Portlet.	It is essentially
+	//		a ContentPane, and should contain other widgets and DOM nodes that
+	//		do the real work of setting preferences for the portlet.
+
+	// portletIconClass: String
+	//		The CSS class to apply to the icon in the Portlet title bar that is used
+	//		to toggle the visibility of this widget.
+	portletIconClass: "dojoxPortletSettingsIcon",
+
+	// portletIconHoverClass: String
+	//		The CSS class to apply to the icon in the Portlet title bar that is used
+	//		to toggle the visibility of this widget when the mouse hovers over it.
+	portletIconHoverClass: "dojoxPortletSettingsIconHover",
+
+	postCreate: function(){
+		// summary:
+		//		Sets the require CSS classes on the widget.
+
+		// Start the PortletSettings widget hidden, always.
+		dojo.style(this.domNode, "display", "none");
+		dojo.addClass(this.domNode, "dojoxPortletSettingsContainer");
+
+		// Remove the unwanted content pane class.
+		dojo.removeClass(this.domNode, "dijitContentPane");
+	},
+
+	_setPortletAttr: function(portlet){
+		// summary: 
+		//		Sets the portlet that encloses this widget.
+		this.portlet = portlet;
+	},
+
+	toggle: function(){
+		// summary: 
+		//		Toggles the visibility of this widget.
+		var n = this.domNode;
+		if(dojo.style(n, "display") == "none"){
+			dojo.style(n,{
+				"display": "block",
+				"height": "1px",
+				"width": "auto"
+			});
+			dojo.fx.wipeIn({
+				node: n
+			}).play();
+		}else{
+			dojo.fx.wipeOut({
+				node: n,
+				onEnd: dojo.hitch(this, function(){
+					dojo.style(n,{"display": "none", "height": "", "width":""});
+				}
+			)}).play();
+		}
+	}
 });
-}
-return _f;
-},onClose:function(evt){
-dojo.style(this.domNode,"display","none");
-},onSizeChange:function(_10){
-if(_10==this){
-return;
-}
-this._updateSize();
-},_updateSize:function(){
-if(!this.open||!this._started||!this.resizeChildren){
-return;
-}
-if(this._timer){
-clearTimeout(this._timer);
-}
-this._timer=setTimeout(dojo.hitch(this,function(){
-var _11={w:dojo.style(this.domNode,"width"),h:dojo.style(this.domNode,"height")};
-for(var i=0;i<this._parents.length;i++){
-var p=this._parents[i];
-var sel=p.parent.selectedChildWidget;
-if(sel&&sel!=p.child){
-return;
-}
-}
-if(this._size){
-if(this._size.w==_11.w&&this._size.h==_11.h){
-return;
-}
-}
-this._size=_11;
-var fns=["resize","layout"];
-this._timer=null;
-var _12=this.getChildren();
-dojo.forEach(_12,function(_13){
-for(var i=0;i<fns.length;i++){
-if(dojo.isFunction(_13[fns[i]])){
-try{
-_13[fns[i]]();
-}
-catch(e){
-}
-break;
-}
-}
+
+dojo.declare("dojox.widget.PortletDialogSettings", 
+	dojox.widget.PortletSettings,{
+	// summary: 
+	//		A settings widget to be used with a dojox.widget.Portlet, which displays
+	//		the contents of this widget in a dijit.Dialog box.
+
+	// dimensions: Array
+	//		The size of the dialog to display.	This defaults to [300, 300]
+	dimensions: null,
+
+	constructor: function(props, node){
+		this.dimensions = props.dimensions || [300, 100];
+	},
+
+	toggle: function(){
+		// summary: 
+		//		Shows and hides the Dialog box.
+		if(!this.dialog){
+			dojo["require"]("dijit.Dialog");
+			this.dialog = new dijit.Dialog({title: this.title});
+			
+			dojo.body().appendChild(this.dialog.domNode);
+
+			// Move this widget inside the dialog
+			this.dialog.containerNode.appendChild(this.domNode);
+
+			dojo.style(this.dialog.domNode,{
+				"width" : this.dimensions[0] + "px",
+				"height" : this.dimensions[1] + "px"
+			});
+			dojo.style(this.domNode, "display", "");
+		}
+		if(this.dialog.open){
+			this.dialog.hide();
+		}else{
+			this.dialog.show(this.domNode);
+		}
+	}
 });
-this.onUpdateSize();
-}),100);
-},onUpdateSize:function(){
-},_publish:function(){
-dojo.publish("/Portlet/sizechange",[this]);
-},_onTitleClick:function(evt){
-if(evt.target==this.arrowNode){
-this.inherited(arguments);
-}
-},addChild:function(_14){
-this._size=null;
-this.inherited(arguments);
-if(this._started){
-this._placeSettingsWidgets();
-this._updateSize();
-}
-if(this._started&&!_14.started&&!_14._started){
-_14.startup();
-}
-},_setCss:function(){
-this.inherited(arguments);
-dojo.style(this.arrowNode,"display",this.toggleable?"":"none");
-}});
-dojo.declare("dojox.widget.PortletSettings",[dijit._Container,dijit.layout.ContentPane],{portletIconClass:"dojoxPortletSettingsIcon",portletIconHoverClass:"dojoxPortletSettingsIconHover",postCreate:function(){
-dojo.style(this.domNode,"display","none");
-dojo.addClass(this.domNode,"dojoxPortletSettingsContainer");
-dojo.removeClass(this.domNode,"dijitContentPane");
-},_setPortletAttr:function(_15){
-this.portlet=_15;
-},toggle:function(){
-var n=this.domNode;
-if(dojo.style(n,"display")=="none"){
-dojo.style(n,{"display":"block","height":"1px","width":"auto"});
-dojo.fx.wipeIn({node:n}).play();
-}else{
-dojo.fx.wipeOut({node:n,onEnd:dojo.hitch(this,function(){
-dojo.style(n,{"display":"none","height":"","width":""});
-})}).play();
-}
-}});
-dojo.declare("dojox.widget.PortletDialogSettings",dojox.widget.PortletSettings,{dimensions:null,constructor:function(_16,_17){
-this.dimensions=_16.dimensions||[300,100];
-},toggle:function(){
-if(!this.dialog){
-dojo["require"]("dijit.Dialog");
-this.dialog=new dijit.Dialog({title:this.title});
-dojo.body().appendChild(this.dialog.domNode);
-this.dialog.containerNode.appendChild(this.domNode);
-dojo.style(this.dialog.domNode,{"width":this.dimensions[0]+"px","height":this.dimensions[1]+"px"});
-dojo.style(this.domNode,"display","");
-}
-if(this.dialog.open){
-this.dialog.hide();
-}else{
-this.dialog.show(this.domNode);
-}
-}});
-}
diff --git a/dojox/widget/Portlet/Portlet.css b/dojox/widget/Portlet/Portlet.css
index 50c2c59..ba0f746 100644
--- a/dojox/widget/Portlet/Portlet.css
+++ b/dojox/widget/Portlet/Portlet.css
@@ -1,6 +1,7 @@
 .dojoxPortlet {
 	margin-bottom: 5px;
 }
+
 .dojoxPortlet .dijitTitlePaneTitle .dojoxPortletIcon {
 	width: 15px;
 	height: 15px;
@@ -17,6 +18,7 @@
 	font-weight: bold;
 	font-size: 0.9em;
 }
+
 .soria .dojoxPortlet .dijitTitlePaneTitle {
 	color: #243C5F;
 }
@@ -27,6 +29,7 @@
 .dojoxPortlet-nonmovable .dijitTitlePaneTitle {
 	cursor: default;
 }
+
 .tundra .dojoxPortlet .dojoxPortletIcon {
 	background-image: url("../../../dijit/themes/tundra/images/spriteRoundedIconsSmall.gif");
 }
@@ -43,6 +46,7 @@
 .dojoxPortlet .dojoxCloseNodeHover {
 	background-position: right -15px;
 }
+
 .tundra .dojoxPortlet .dijitOpen .dojoxArrowDown,
 .soria .dojoxPortlet .dijitOpen .dojoxArrowDown,
 .nihilo .dojoxPortlet .dijitOpen .dojoxArrowDown {
@@ -53,6 +57,7 @@
 .nihilo .dojoxPortlet .dijitClosed .dojoxArrowDown {
 	background-position: 0 top;
 }
+
 .tundra .dojoxPortlet .dojoxPortletSettingsIcon,
 .soria .dojoxPortlet .dojoxPortletSettingsIcon,
 .nihilo .dojoxPortlet .dojoxPortletSettingsIcon {
@@ -70,8 +75,10 @@
 .nihilo .dijitDialogPaneContent .dojoxPortletSettingsContainer {
 	border-bottom: none;
 }
+
+
 .soria .dojoDndItemOver .dojoxPortletTitle {
-  border-top: 1px solid #8D8D8D;
+	border-top: 1px solid #8D8D8D;
 	border-left: 1px solid #8D8D8D;
 	border-right: 1px solid #8D8D8D;
 }
@@ -80,9 +87,11 @@
 	border-left: 1px solid #9D9D9D;
 	border-right: 1px solid #9D9D9D;
 }
+
 .dojoxPortlet div.dojoxPortletContentOuter {
-	background: url(../../../dijit/themes/tundra/images/validationInputBg.gif) repeat-x top left;
+	background: #fff url(../../../dijit/themes/tundra/images/validationInputBg.gif) repeat-x top left;
 }
+
 .dojoxFeedPortletList {
 	padding-left: 25px;
 	margin: 0px;
@@ -136,3 +145,4 @@
 .dojoxPortletItemOpen .dojoxPortletItemSummary {
   display: block;
 }
+
diff --git a/dojox/widget/Roller.js b/dojox/widget/Roller.js
index f76f092..ff9cb42 100644
--- a/dojox/widget/Roller.js
+++ b/dojox/widget/Roller.js
@@ -1,84 +1,228 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.Roller"]){
-dojo._hasResource["dojox.widget.Roller"]=true;
 dojo.provide("dojox.widget.Roller");
 dojo.require("dijit._Widget");
-dojo.declare("dojox.widget.Roller",dijit._Widget,{delay:2000,autoStart:true,itemSelector:"> li",durationIn:400,durationOut:275,_idx:-1,postCreate:function(){
-if(!this["items"]){
-this.items=[];
-}
-dojo.addClass(this.domNode,"dojoxRoller");
-dojo.query(this.itemSelector,this.domNode).forEach(function(_1,i){
-this.items.push(_1.innerHTML);
-if(i==0){
-this._roller=_1;
-this._idx=0;
-}else{
-dojo.destroy(_1);
-}
-},this);
-if(!this._roller){
-this._roller=dojo.create("li",null,this.domNode);
-}
-this.makeAnims();
-if(this.autoStart){
-this.start();
-}
-},makeAnims:function(){
-var n=this.domNode;
-dojo.mixin(this,{_anim:{"in":dojo.fadeIn({node:n,duration:this.durationIn}),"out":dojo.fadeOut({node:n,duration:this.durationOut})}});
-this._setupConnects();
-},_setupConnects:function(){
-var _2=this._anim;
-this.connect(_2["out"],"onEnd",function(){
-this._set(this._idx+1);
-_2["in"].play(15);
+
+dojo.declare("dojox.widget.Roller", dijit._Widget, {
+	// summary: A simple widget to take an unordered-list of Text and roll through them
+	// 
+	// description: 
+	//		The Roller widget takes an unordered-list of items, and converts
+	//		them to a single-area (the size of one list-item, however you so choose
+	//		to style it) and loops continually, fading between items. 
+	//		
+	//		In it's current state, it requires it be created from an unordered (or ordered)
+	//		list, though can contain complex markup. 
+	//
+	//		You can manipulate the `items` array at any point during the cycle with
+	//		standard array manipulation techniques.
+	//
+	//		The class "dojoxRoller" is added to the UL element for styling purposes.
+	//
+	//	example: 
+	//	|	// create a scroller from a unordered list with id="lister"
+	//  |	var thinger = new dojox.widget.Roller.Roller({},"lister");
+	//
+	//	example:
+	//	|	// create a scroller from a fixed array, and place in the DOM:
+	//	|	new dojox.widget.Roller({ items:["one","two","three"] }).placeAt(dojo.body());
+	//
+	//	example:
+	//	|	// add an item:
+	//	|	dijit.byId("roller").items.push("I am a new Label");
+	//
+	//  example: 
+	//	|	// stop a roller from rolling:
+	//	|	dijit.byId("roller").stop();
+	//
+	// delay: Integer
+	//		Interval between rolls
+	delay: 2000,
+
+	// autoStart: Boolean
+	//		Toggle to control starup behavior. Call .start() manually
+	//		if set to `false`
+	autoStart: true,
+	
+	// itemSelector: String
+	//		A CSS selector to be used by `dojo.query` to find the children
+	//		items in this widget. Defaults to "> li", finding only first-children
+	//		list-items in the list, allowing for embedded lists to occur.
+	itemSelector: "> li",
+	
+	// durationIn: Integer
+	// 		Speed (in ms) to apply to the "in" animation (show the node)
+	durationIn: 400,
+	
+	// durationOut: Integer
+	//		Speed (in ms) to apply to the "out" animation (hide the showing node)
+	durationOut: 275,
+/*=====
+	// items: Array
+	//		If populated prior to instantiation, is used as the Items over the children
+	items: [],
+=====*/	
+
+	// _idx: Integer
+	//		Index of the the currently visible item in the list of items[]
+	_idx: -1,
+	
+	postCreate: function(){
+
+		// add some instance vars:
+		if(!this["items"]){ 
+			this.items = [];
+		}
+		
+		dojo.addClass(this.domNode,"dojoxRoller");
+		
+		// find all the items in this list, and popuplate 
+		dojo.query(this.itemSelector, this.domNode).forEach(function(item, i){
+			this.items.push(item.innerHTML);
+			// reuse the first match, destroy the rest
+			if(i == 0){ 
+				this._roller = item; 
+				this._idx = 0; 
+			}else{ dojo.destroy(item); }
+		}, this);
+		
+		// handle the case where items[] were passed, and no srcNodeRef exists
+		if(!this._roller){
+			this._roller = dojo.create('li', null, this.domNode);
+		}
+		// stub out animation creation (for overloading maybe later)
+		this.makeAnims();
+		
+		// and start, if true:
+		if(this.autoStart){ this.start(); }
+		
+	},
+
+	makeAnims: function(){
+		// summary: Animation creator function. Need to create an 'in' and 'out'
+		// 		Animation stored in _anim Object, which the rest of the widget
+		//		will reuse. 
+		var n = this.domNode;
+		dojo.mixin(this, {
+			_anim: {
+				"in": dojo.fadeIn({ node:n, duration: this.durationIn }),
+				"out": dojo.fadeOut({ node:n, duration: this.durationOut })
+			}
+		});
+		this._setupConnects();
+		
+	},
+	
+	_setupConnects: function(){
+		// summary: setup the loop connection logic
+		var anim = this._anim;
+
+		this.connect(anim["out"], "onEnd", function(){
+			// onEnd of the `out` animation, select the next items and play `in` animation
+			this._set(this._idx + 1);
+			anim["in"].play(15);
+		});
+		
+		this.connect(anim["in"], "onEnd", function(){
+			// onEnd of the `in` animation, call `start` again after some delay:
+			this._timeout = setTimeout(dojo.hitch(this, "_run"), this.delay);
+		});
+	},
+	
+	start: function(){
+		// summary: Starts to Roller looping
+		if(!this.rolling){
+			this.rolling = true;
+			this._run();
+		}
+	},
+	
+	_run: function(){
+		this._anim["out"].gotoPercent(0, true);
+	},
+
+	stop: function(){
+		// summary: Stops the Roller from looping anymore.
+		this.rolling = false;
+
+		var m = this._anim, 
+			t = this._timeout;
+
+		if(t){ clearTimeout(t); }
+		m["in"].stop();
+		m["out"].stop();
+	},
+	
+	_set: function(i){
+		// summary: Set the Roller to some passed index. If beyond range, go to first.
+		var l = this.items.length - 1;
+		if(i < 0){ i = l; }
+		if(i > l){ i = 0; }
+		this._roller.innerHTML = this.items[i] || "error!";
+		this._idx = i;
+	}
+
+});
+
+dojo.declare("dojox.widget.RollerSlide", dojox.widget.Roller, {
+	// summary: An add-on to the Roller to modify animations. This produces 
+	//		a slide-from-bottom like effect. See `dojox.widget.Roller` for
+	//		full API information.
+	
+	durationOut: 175, // slightly faster than default
+	
+	makeAnims: function(){
+		// summary: Animation creator function. Need to create an 'in' and 'out'
+		// 		Animation stored in _anim Object, which the rest of the widget
+		//		will reuse.
+
+		var n = this.domNode, pos = "position", 
+			props = {
+				top: { end: 0, start: 25 },
+				opacity: 1
+			}
+		;
+		
+		dojo.style(n, pos, "relative");
+		dojo.style(this._roller, pos, "absolute");
+
+		dojo.mixin(this, {
+			_anim: {
+				
+				"in": dojo.animateProperty({ 
+					node: n, 
+					duration: this.durationIn,
+					properties: props
+				}),
+				
+				"out": dojo.fadeOut({ node: n, duration: this.durationOut })
+			}
+		});
+		// don't forget to do this in the class. override if necessary.
+		this._setupConnects();
+	}
+	
 });
-this.connect(_2["in"],"onEnd",function(){
-this._timeout=setTimeout(dojo.hitch(this,"_run"),this.delay);
+
+dojo.declare("dojox.widget._RollerHover", null, {
+	// summary: A mixin class to provide a way to automate the "stop on hover" functionality.
+	//
+	// description: 
+	//		A mixin class used to provide a way to automate a "stop on hover" behavior,
+	//		while still allowing for ambigious subclassing for custom animations.
+	//		Simply mix this class into a `dojox.widget.Roller` variant, and instantiate 
+	//		as you would. The hover connection is done automatically. 
+	//
+	//		The "hover" functionality is as such: Stop rotation while the mouse is over the
+	//		instance, and resume again once leaving. Even if autoStart is disabled, the widget
+	//		will start if a mouse enters and leaves the node in this case.
+	//
+	// example:
+	// | dojo.declare("my.Roller", [dojox.widget.RollerSlide, dojox.widget._RollerHover], {});
+	// | new my.Roller({}, "myList");
+	
+	postCreate: function(){
+		this.inherited(arguments);
+		this.connect(this.domNode, "onmouseenter", "stop");
+		this.connect(this.domNode, "onmouseleave", "start");
+	}
+	
 });
-},start:function(){
-if(!this.rolling){
-this.rolling=true;
-this._run();
-}
-},_run:function(){
-this._anim["out"].gotoPercent(0,true);
-},stop:function(){
-this.rolling=false;
-var m=this._anim,t=this._timeout;
-if(t){
-clearTimeout(t);
-}
-m["in"].stop();
-m["out"].stop();
-},_set:function(i){
-var l=this.items.length-1;
-if(i<0){
-i=l;
-}
-if(i>l){
-i=0;
-}
-this._roller.innerHTML=this.items[i]||"error!";
-this._idx=i;
-}});
-dojo.declare("dojox.widget.RollerSlide",dojox.widget.Roller,{durationOut:175,makeAnims:function(){
-var n=this.domNode,_3="position",_4={top:{end:0,start:25},opacity:1};
-dojo.style(n,_3,"relative");
-dojo.style(this._roller,_3,"absolute");
-dojo.mixin(this,{_anim:{"in":dojo.animateProperty({node:n,duration:this.durationIn,properties:_4}),"out":dojo.fadeOut({node:n,duration:this.durationOut})}});
-this._setupConnects();
-}});
-dojo.declare("dojox.widget._RollerHover",null,{postCreate:function(){
-this.inherited(arguments);
-this.connect(this.domNode,"onmouseenter","stop");
-this.connect(this.domNode,"onmouseleave","start");
-}});
-}
diff --git a/dojox/widget/RollingList.js b/dojox/widget/RollingList.js
index dd98fd2..031d141 100644
--- a/dojox/widget/RollingList.js
+++ b/dojox/widget/RollingList.js
@@ -1,893 +1,1203 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.RollingList"]){
-dojo._hasResource["dojox.widget.RollingList"]=true;
 dojo.provide("dojox.widget.RollingList");
 dojo.experimental("dojox.widget.RollingList");
+
+dojo.require("dojo.window");
+
 dojo.require("dijit.layout.ContentPane");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Contained");
 dojo.require("dijit.layout._LayoutWidget");
 dojo.require("dijit.Menu");
-dojo.require("dojox.html.metrics");
 dojo.require("dijit.form.Button");
-dojo.require("dojo.i18n");
-dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dojox.widget._RollingListPane",[dijit.layout.ContentPane,dijit._Templated,dijit._Contained],{templateString:"<div class=\"dojoxRollingListPane\"><table><tbody><tr><td dojoAttachPoint=\"containerNode\"></td></tr></tbody></div>",parentWidget:null,parentPane:null,store:null,items:null,query:null,queryOptions:null,_focusByNode:true,minWidth:0,_setContentAndScroll:function(_1,_2){
-this._setContent(_1,_2);
-this.parentWidget.scrollIntoView(this);
-},_updateNodeWidth:function(n,_3){
-n.style.width="";
-var _4=dojo.marginBox(n).w;
-if(_4<_3){
-dojo.marginBox(n,{w:_3});
-}
-},_onMinWidthChange:function(v){
-this._updateNodeWidth(this.domNode,v);
-},_setMinWidthAttr:function(v){
-if(v!==this.minWidth){
-this.minWidth=v;
-this._onMinWidthChange(v);
-}
-},startup:function(){
-if(this._started){
-return;
-}
-if(this.store&&this.store.getFeatures()["dojo.data.api.Notification"]){
-window.setTimeout(dojo.hitch(this,function(){
-this.connect(this.store,"onSet","_onSetItem");
-this.connect(this.store,"onNew","_onNewItem");
-this.connect(this.store,"onDelete","_onDeleteItem");
-}),1);
-}
-this.connect(this.focusNode||this.domNode,"onkeypress","_focusKey");
-this.parentWidget._updateClass(this.domNode,"Pane");
-this.inherited(arguments);
-this._onMinWidthChange(this.minWidth);
-},_focusKey:function(e){
-if(e.charOrCode==dojo.keys.BACKSPACE){
-dojo.stopEvent(e);
-return;
-}else{
-if(e.charOrCode==dojo.keys.LEFT_ARROW&&this.parentPane){
-this.parentPane.focus();
-this.parentWidget.scrollIntoView(this.parentPane);
-}else{
-if(e.charOrCode==dojo.keys.ENTER){
-this.parentWidget._onExecute();
-}
-}
-}
-},focus:function(_5){
-if(this.parentWidget._focusedPane!=this){
-this.parentWidget._focusedPane=this;
-this.parentWidget.scrollIntoView(this);
-if(this._focusByNode&&(!this.parentWidget._savedFocus||_5)){
-try{
-(this.focusNode||this.domNode).focus();
-}
-catch(e){
-}
-}
-}
-},_onShow:function(){
-if((this.store||this.items)&&((this.refreshOnShow&&this.domNode)||(!this.isLoaded&&this.domNode))){
-this.refresh();
-}
-},_load:function(){
-this.isLoaded=false;
-if(this.items){
-this._setContentAndScroll(this.onLoadStart(),true);
-window.setTimeout(dojo.hitch(this,"_doQuery"),1);
-}else{
-this._doQuery();
-}
-},_doLoadItems:function(_6,_7){
-var _8=0,_9=this.store;
-dojo.forEach(_6,function(_a){
-if(!_9.isItemLoaded(_a)){
-_8++;
-}
-});
-if(_8===0){
-_7();
-}else{
-var _b=function(_c){
-_8--;
-if((_8)===0){
-_7();
-}
-};
-dojo.forEach(_6,function(_d){
-if(!_9.isItemLoaded(_d)){
-_9.loadItem({item:_d,onItem:_b});
-}
-});
-}
-},_doQuery:function(){
-if(!this.domNode){
-return;
-}
-var _e=this.parentWidget.preloadItems;
-_e=(_e===true||(this.items&&this.items.length<=Number(_e)));
-if(this.items&&_e){
-this._doLoadItems(this.items,dojo.hitch(this,"onItems"));
-}else{
-if(this.items){
-this.onItems();
-}else{
-this._setContentAndScroll(this.onFetchStart(),true);
-this.store.fetch({query:this.query,onComplete:function(_f){
-this.items=_f;
-this.onItems();
-},onError:function(e){
-this._onError("Fetch",e);
-},scope:this});
-}
-}
-},_hasItem:function(_10){
-var _11=this.items||[];
-for(var i=0,_12;(_12=_11[i]);i++){
-if(this.parentWidget._itemsMatch(_12,_10)){
-return true;
-}
-}
-return false;
-},_onSetItem:function(_13,_14,_15,_16){
-if(this._hasItem(_13)){
-this.refresh();
-}
-},_onNewItem:function(_17,_18){
-var sel;
-if((!_18&&!this.parentPane)||(_18&&this.parentPane&&this.parentPane._hasItem(_18.item)&&(sel=this.parentPane._getSelected())&&this.parentWidget._itemsMatch(sel.item,_18.item))){
-this.items.push(_17);
-this.refresh();
-}else{
-if(_18&&this.parentPane&&this._hasItem(_18.item)){
-this.refresh();
-}
-}
-},_onDeleteItem:function(_19){
-if(this._hasItem(_19)){
-this.items=dojo.filter(this.items,function(i){
-return (i!=_19);
-});
-this.refresh();
-}
-},onFetchStart:function(){
-return this.loadingMessage;
-},onFetchError:function(_1a){
-return this.errorMessage;
-},onLoadStart:function(){
-return this.loadingMessage;
-},onLoadError:function(_1b){
-return this.errorMessage;
-},onItems:function(){
-if(!this.onLoadDeferred){
-this.cancel();
-this.onLoadDeferred=new dojo.Deferred(dojo.hitch(this,"cancel"));
-}
-this._onLoadHandler();
-}});
-dojo.declare("dojox.widget._RollingListGroupPane",[dojox.widget._RollingListPane],{templateString:"<div><div dojoAttachPoint=\"containerNode\"></div>"+"<div dojoAttachPoint=\"menuContainer\">"+"<div dojoAttachPoint=\"menuNode\"></div>"+"</div></div>",_menu:null,_setContent:function(_1c){
-if(!this._menu){
-this.inherited(arguments);
-}
-},_onMinWidthChange:function(v){
-if(!this._menu){
-return;
-}
-var _1d=dojo.marginBox(this.domNode).w;
-var _1e=dojo.marginBox(this._menu.domNode).w;
-this._updateNodeWidth(this._menu.domNode,v-(_1d-_1e));
-},onItems:function(){
-var _1f,_20=false;
-if(this._menu){
-_1f=this._getSelected();
-this._menu.destroyRecursive();
-}
-this._menu=this._getMenu();
-var _21,_22;
-if(this.items.length){
-dojo.forEach(this.items,function(_23){
-_21=this.parentWidget._getMenuItemForItem(_23,this);
-if(_21){
-if(_1f&&this.parentWidget._itemsMatch(_21.item,_1f.item)){
-_22=_21;
-}
-this._menu.addChild(_21);
-}
-},this);
-}else{
-_21=this.parentWidget._getMenuItemForItem(null,this);
-if(_21){
-this._menu.addChild(_21);
-}
-}
-if(_22){
-this._setSelected(_22);
-if((_1f&&!_1f.children&&_22.children)||(_1f&&_1f.children&&!_22.children)){
-var _24=this.parentWidget._getPaneForItem(_22.item,this,_22.children);
-if(_24){
-this.parentWidget.addChild(_24,this.getIndexInParent()+1);
-}else{
-this.parentWidget._removeAfter(this);
-this.parentWidget._onItemClick(null,this,_22.item,_22.children);
-}
-}
-}else{
-if(_1f){
-this.parentWidget._removeAfter(this);
-}
-}
-this.containerNode.innerHTML="";
-this.containerNode.appendChild(this._menu.domNode);
-this.parentWidget.scrollIntoView(this);
-this._checkScrollConnection(true);
-this.inherited(arguments);
-this._onMinWidthChange(this.minWidth);
-},_checkScrollConnection:function(_25){
-var _26=this.store;
-if(this._scrollConn){
-this.disconnect(this._scrollConn);
-}
-delete this._scrollConn;
-if(!dojo.every(this.items,function(i){
-return _26.isItemLoaded(i);
-})){
-if(_25){
-this._loadVisibleItems();
-}
-this._scrollConn=this.connect(this.domNode,"onscroll","_onScrollPane");
-}
-},startup:function(){
-this.inherited(arguments);
-this.parentWidget._updateClass(this.domNode,"GroupPane");
-},focus:function(_27){
-if(this._menu){
-if(this._pendingFocus){
-this.disconnect(this._pendingFocus);
-}
-delete this._pendingFocus;
-var _28=this._menu.focusedChild;
-if(!_28){
-var _29=dojo.query(".dojoxRollingListItemSelected",this.domNode)[0];
-if(_29){
-_28=dijit.byNode(_29);
-}
-}
-if(!_28){
-_28=this._menu.getChildren()[0]||this._menu;
-}
-this._focusByNode=false;
-if(_28.focusNode){
-if(!this.parentWidget._savedFocus||_27){
-try{
-_28.focusNode.focus();
-}
-catch(e){
-}
-}
-window.setTimeout(function(){
-try{
-dijit.scrollIntoView(_28.focusNode);
-}
-catch(e){
-}
-},1);
-}else{
-if(_28.focus){
-if(!this.parentWidget._savedFocus||_27){
-_28.focus();
-}
-}else{
-this._focusByNode=true;
-}
-}
-this.inherited(arguments);
-}else{
-if(!this._pendingFocus){
-this._pendingFocus=this.connect(this,"onItems","focus");
-}
-}
-},_getMenu:function(){
-var _2a=this;
-var _2b=new dijit.Menu({parentMenu:this.parentPane?this.parentPane._menu:null,onCancel:function(_2c){
-if(_2a.parentPane){
-_2a.parentPane.focus(true);
-}
-},_moveToPopup:function(evt){
-if(this.focusedChild&&!this.focusedChild.disabled){
-this.focusedChild._onClick(evt);
-}
-}},this.menuNode);
-this.connect(_2b,"onItemClick",function(_2d,evt){
-if(_2d.disabled){
-return;
-}
-evt.alreadySelected=dojo.hasClass(_2d.domNode,"dojoxRollingListItemSelected");
-if(evt.alreadySelected&&((evt.type=="keypress"&&evt.charOrCode!=dojo.keys.ENTER)||(evt.type=="internal"))){
-var p=this.parentWidget.getChildren()[this.getIndexInParent()+1];
-if(p){
-p.focus(true);
-this.parentWidget.scrollIntoView(p);
-}
-}else{
-this._setSelected(_2d,_2b);
-this.parentWidget._onItemClick(evt,this,_2d.item,_2d.children);
-if(evt.type=="keypress"&&evt.charOrCode==dojo.keys.ENTER){
-this.parentWidget._onExecute();
-}
-}
-});
-if(!_2b._started){
-_2b.startup();
-}
-return _2b;
-},_onScrollPane:function(){
-if(this._visibleLoadPending){
-window.clearTimeout(this._visibleLoadPending);
-}
-this._visibleLoadPending=window.setTimeout(dojo.hitch(this,"_loadVisibleItems"),500);
-},_loadVisibleItems:function(){
-delete this._visibleLoadPending;
-var _2e=this._menu;
-if(!_2e){
-return;
-}
-var _2f=_2e.getChildren();
-if(!_2f||!_2f.length){
-return;
-}
-var _30=function(n,m,pb){
-var s=dojo.getComputedStyle(n);
-var r=0;
-if(m){
-r+=dojo._getMarginExtents(n,s).t;
-}
-if(pb){
-r+=dojo._getPadBorderExtents(n,s).t;
-}
-return r;
-};
-var _31=_30(this.domNode,false,true)+_30(this.containerNode,true,true)+_30(_2e.domNode,true,true)+_30(_2f[0].domNode,true,false);
-var h=dojo.contentBox(this.domNode).h;
-var _32=this.domNode.scrollTop-_31-(h/2);
-var _33=_32+(3*h/2);
-var _34=dojo.filter(_2f,function(c){
-var cnt=c.domNode.offsetTop;
-var s=c.store;
-var i=c.item;
-return (cnt>=_32&&cnt<=_33&&!s.isItemLoaded(i));
-});
-var _35=dojo.map(_34,function(c){
-return c.item;
-});
-var _36=dojo.hitch(this,function(){
-var _37=this._getSelected();
-var _38;
-dojo.forEach(_35,function(_39,idx){
-var _3a=this.parentWidget._getMenuItemForItem(_39,this);
-var _3b=_34[idx];
-var _3c=_3b.getIndexInParent();
-_2e.removeChild(_3b);
-if(_3a){
-if(_37&&this.parentWidget._itemsMatch(_3a.item,_37.item)){
-_38=_3a;
-}
-_2e.addChild(_3a,_3c);
-if(_2e.focusedChild==_3b){
-_2e.focusChild(_3a);
-}
-}
-_3b.destroy();
-},this);
-this._checkScrollConnection(false);
-});
-this._doLoadItems(_35,_36);
-},_getSelected:function(_3d){
-if(!_3d){
-_3d=this._menu;
-}
-if(_3d){
-var _3e=this._menu.getChildren();
-for(var i=0,_3f;(_3f=_3e[i]);i++){
-if(dojo.hasClass(_3f.domNode,"dojoxRollingListItemSelected")){
-return _3f;
-}
-}
-}
-return null;
-},_setSelected:function(_40,_41){
-if(!_41){
-_41=this._menu;
-}
-if(_41){
-dojo.forEach(_41.getChildren(),function(i){
-this.parentWidget._updateClass(i.domNode,"Item",{"Selected":(_40&&(i==_40&&!i.disabled))});
-},this);
-}
-}});
-dojo.declare("dojox.widget.RollingList",[dijit._Widget,dijit._Templated,dijit._Container],{templateString:dojo.cache("dojox.widget","RollingList/RollingList.html","<div class=\"dojoxRollingList ${className}\"\n\t><div class=\"dojoxRollingListContainer\" dojoAttachPoint=\"containerNode\" dojoAttachEvent=\"onkeypress:_onKey\"\n\t></div\n\t><div class=\"dojoxRollingListButtons\" dojoAttachPoint=\"buttonsNode\"\n        ><button dojoType=\"dijit.form.Button\" dojoAttachPoint=\"okButton\"\n\t [...]
-this.inherited(arguments);
-var loc=dojo.i18n.getLocalization("dijit","common");
-this.okButtonLabel=this.okButtonLabel||loc.buttonOk;
-this.cancelButtonLabel=this.cancelButtonLabel||loc.buttonCancel;
-},_setShowButtonsAttr:function(_42){
-var _43=false;
-if((this.showButtons!=_42&&this._started)||(this.showButtons==_42&&!this.started)){
-_43=true;
-}
-dojo.toggleClass(this.domNode,"dojoxRollingListButtonsHidden",!_42);
-this.showButtons=_42;
-if(_43){
-if(this._started){
-this.layout();
-}else{
-window.setTimeout(dojo.hitch(this,"layout"),0);
-}
-}
-},_itemsMatch:function(_44,_45){
-if(!_44&&!_45){
-return true;
-}else{
-if(!_44||!_45){
-return false;
-}
-}
-return (_44==_45||(this._isIdentity&&this.store.getIdentity(_44)==this.store.getIdentity(_45)));
-},_removeAfter:function(idx){
-if(typeof idx!="number"){
-idx=this.getIndexOfChild(idx);
-}
-if(idx>=0){
-dojo.forEach(this.getChildren(),function(c,i){
-if(i>idx){
-this.removeChild(c);
-c.destroyRecursive();
-}
-},this);
-}
-var _46=this.getChildren(),_47=_46[_46.length-1];
-var _48=null;
-while(_47&&!_48){
-var val=_47._getSelected?_47._getSelected():null;
-if(val){
-_48=val.item;
-}
-_47=_47.parentPane;
-}
-if(!this._setInProgress){
-this._setValue(_48);
-}
-},addChild:function(_49,_4a){
-if(_4a>0){
-this._removeAfter(_4a-1);
-}
-this.inherited(arguments);
-if(!_49._started){
-_49.startup();
-}
-_49.attr("minWidth",this.minPaneWidth);
-this.layout();
-if(!this._savedFocus){
-_49.focus();
-}
-},_setMinPaneWidthAttr:function(_4b){
-if(_4b!==this.minPaneWidth){
-this.minPaneWidth=_4b;
-dojo.forEach(this.getChildren(),function(c){
-c.attr("minWidth",_4b);
-});
-}
-},_updateClass:function(_4c,_4d,_4e){
-if(!this._declaredClasses){
-this._declaredClasses=("dojoxRollingList "+this.className).split(" ");
-}
-dojo.forEach(this._declaredClasses,function(c){
-if(c){
-dojo.addClass(_4c,c+_4d);
-for(var k in _4e||{}){
-dojo.toggleClass(_4c,c+_4d+k,_4e[k]);
-}
-dojo.toggleClass(_4c,c+_4d+"FocusSelected",(dojo.hasClass(_4c,c+_4d+"Focus")&&dojo.hasClass(_4c,c+_4d+"Selected")));
-dojo.toggleClass(_4c,c+_4d+"HoverSelected",(dojo.hasClass(_4c,c+_4d+"Hover")&&dojo.hasClass(_4c,c+_4d+"Selected")));
-}
-});
-},scrollIntoView:function(_4f){
-if(this._scrollingTimeout){
-window.clearTimeout(this._scrollingTimeout);
-}
-delete this._scrollingTimeout;
-this._scrollingTimeout=window.setTimeout(dojo.hitch(this,function(){
-if(_4f.domNode){
-dijit.scrollIntoView(_4f.domNode);
-}
-delete this._scrollingTimeout;
-return;
-}),1);
-},resize:function(_50){
-dijit.layout._LayoutWidget.prototype.resize.call(this,_50);
-},layout:function(){
-var _51=this.getChildren();
-if(this._contentBox){
-var bn=this.buttonsNode;
-var _52=this._contentBox.h-dojo.marginBox(bn).h-dojox.html.metrics.getScrollbar().h;
-dojo.forEach(_51,function(c){
-dojo.marginBox(c.domNode,{h:_52});
-});
-}
-if(this._focusedPane){
-var foc=this._focusedPane;
-delete this._focusedPane;
-if(!this._savedFocus){
-foc.focus();
-}
-}else{
-if(_51&&_51.length){
-if(!this._savedFocus){
-_51[0].focus();
-}
-}
-}
-},_onChange:function(_53){
-this.onChange(_53);
-},_setValue:function(_54){
-delete this._setInProgress;
-if(!this._itemsMatch(this.value,_54)){
-this.value=_54;
-this._onChange(_54);
-}
-},_setValueAttr:function(_55){
-if(this._itemsMatch(this.value,_55)&&!_55){
-return;
-}
-if(this._setInProgress&&this._setInProgress===_55){
-return;
-}
-this._setInProgress=_55;
-if(!_55||!this.store.isItem(_55)){
-var _56=this.getChildren()[0];
-_56._setSelected(null);
-this._onItemClick(null,_56,null,null);
-return;
-}
-var _57=dojo.hitch(this,function(_58,_59){
-var _5a=this.store,id;
-if(this.parentAttr&&_5a.getFeatures()["dojo.data.api.Identity"]&&((id=this.store.getValue(_58,this.parentAttr))||id==="")){
-var cb=function(i){
-if(_5a.getIdentity(i)==_5a.getIdentity(_58)){
-_59(null);
-}else{
-_59([i]);
-}
-};
-if(id===""){
-_59(null);
-}else{
-if(typeof id=="string"){
-_5a.fetchItemByIdentity({identity:id,onItem:cb});
-}else{
-if(_5a.isItem(id)){
-cb(id);
-}
-}
-}
-}else{
-var _5b=this.childrenAttrs.length;
-var _5c=[];
-dojo.forEach(this.childrenAttrs,function(_5d){
-var q={};
-q[_5d]=_58;
-_5a.fetch({query:q,scope:this,onComplete:function(_5e){
-if(this._setInProgress!==_55){
-return;
-}
-_5c=_5c.concat(_5e);
-_5b--;
-if(_5b===0){
-_59(_5c);
-}
-}});
-},this);
-}
-});
-var _5f=dojo.hitch(this,function(_60,idx){
-var set=_60[idx];
-var _61=this.getChildren()[idx];
-var _62;
-if(set&&_61){
-var fx=dojo.hitch(this,function(){
-if(_62){
-this.disconnect(_62);
-}
-delete _62;
-if(this._setInProgress!==_55){
-return;
-}
-var _63=dojo.filter(_61._menu.getChildren(),function(i){
-return this._itemsMatch(i.item,set);
-},this)[0];
-if(_63){
-idx++;
-_61._menu.onItemClick(_63,{type:"internal",stopPropagation:function(){
-},preventDefault:function(){
-}});
-if(_60[idx]){
-_5f(_60,idx);
-}else{
-this._setValue(set);
-this.onItemClick(set,_61,this.getChildItems(set));
-}
-}
-});
-if(!_61.isLoaded){
-_62=this.connect(_61,"onLoad",fx);
-}else{
-fx();
-}
-}else{
-if(idx===0){
-this.attr("value",null);
-}
-}
-});
-var _64=[];
-var _65=dojo.hitch(this,function(_66){
-if(_66&&_66.length){
-_64.push(_66[0]);
-_57(_66[0],_65);
-}else{
-if(!_66){
-_64.pop();
-}
-_64.reverse();
-_5f(_64,0);
-}
-});
-var ns=this.domNode.style;
-if(ns.display=="none"||ns.visibility=="hidden"){
-this._setValue(_55);
-}else{
-if(!this._itemsMatch(_55,this._visibleItem)){
-_65([_55]);
-}
-}
-},_onItemClick:function(evt,_67,_68,_69){
-if(evt){
-var _6a=this._getPaneForItem(_68,_67,_69);
-var _6b=(evt.type=="click"&&evt.alreadySelected);
-if(_6b&&_6a){
-this._removeAfter(_67.getIndexInParent()+1);
-var _6c=_67.getNextSibling();
-if(_6c&&_6c._setSelected){
-_6c._setSelected(null);
-}
-this.scrollIntoView(_6c);
-}else{
-if(_6a){
-this.addChild(_6a,_67.getIndexInParent()+1);
-if(this._savedFocus){
-_6a.focus(true);
-}
-}else{
-this._removeAfter(_67);
-this.scrollIntoView(_67);
-}
-}
-}else{
-if(_67){
-this._removeAfter(_67);
-this.scrollIntoView(_67);
-}
-}
-if(!evt||evt.type!="internal"){
-this._setValue(_68);
-this.onItemClick(_68,_67,_69);
-}
-this._visibleItem=_68;
-},_getPaneForItem:function(_6d,_6e,_6f){
-var ret=this.getPaneForItem(_6d,_6e,_6f);
-ret.store=this.store;
-ret.parentWidget=this;
-ret.parentPane=_6e||null;
-if(!_6d){
-ret.query=this.query;
-ret.queryOptions=this.queryOptions;
-}else{
-if(_6f){
-ret.items=_6f;
-}else{
-ret.items=[_6d];
-}
-}
-return ret;
-},_getMenuItemForItem:function(_70,_71){
-var _72=this.store;
-if(!_70||!_72||!_72.isItem(_70)){
-var i=new dijit.MenuItem({label:"---",disabled:true,iconClass:"dojoxEmpty",focus:function(){
-}});
-this._updateClass(i.domNode,"Item");
-return i;
-}else{
-var _73=_72.isItemLoaded(_70);
-var _74=_73?this.getChildItems(_70):undefined;
-var _75;
-if(_74){
-_75=this.getMenuItemForItem(_70,_71,_74);
-_75.children=_74;
-this._updateClass(_75.domNode,"Item",{"Expanding":true});
-if(!_75._started){
-var c=_75.connect(_75,"startup",function(){
-this.disconnect(c);
-dojo.style(this.arrowWrapper,"display","");
-});
-}else{
-dojo.style(_75.arrowWrapper,"display","");
-}
-}else{
-_75=this.getMenuItemForItem(_70,_71,null);
-if(_73){
-this._updateClass(_75.domNode,"Item",{"Single":true});
-}else{
-this._updateClass(_75.domNode,"Item",{"Unloaded":true});
-_75.attr("disabled",true);
-}
-}
-_75.store=this.store;
-_75.item=_70;
-if(!_75.label){
-_75.attr("label",this.store.getLabel(_70).replace(/</,"<"));
-}
-if(_75.focusNode){
-var _76=this;
-_75.focus=function(){
-if(!this.disabled){
-try{
-this.focusNode.focus();
-}
-catch(e){
-}
-}
-};
-_75.connect(_75.focusNode,"onmouseenter",function(){
-if(!this.disabled){
-_76._updateClass(this.domNode,"Item",{"Hover":true});
-}
-});
-_75.connect(_75.focusNode,"onmouseleave",function(){
-if(!this.disabled){
-_76._updateClass(this.domNode,"Item",{"Hover":false});
-}
-});
-_75.connect(_75.focusNode,"blur",function(){
-_76._updateClass(this.domNode,"Item",{"Focus":false,"Hover":false});
-});
-_75.connect(_75.focusNode,"focus",function(){
-_76._updateClass(this.domNode,"Item",{"Focus":true});
-_76._focusedPane=_71;
-});
-if(this.executeOnDblClick){
-_75.connect(_75.focusNode,"ondblclick",function(){
-_76._onExecute();
+
+dojo.require("dojox.html.metrics");
+
+dojo.require("dojo.i18n"); 
+dojo.requireLocalization("dijit", "common");
+
+dojo.declare("dojox.widget._RollingListPane",
+	[dijit.layout.ContentPane, dijit._Templated, dijit._Contained], {
+	// summary: a core pane that can be attached to a RollingList.  All panes
+	//  should extend this one
+
+	// templateString: string
+	//	our template
+	templateString: '<div class="dojoxRollingListPane"><table><tbody><tr><td dojoAttachPoint="containerNode"></td></tr></tbody></div>',
+
+	// parentWidget: dojox.widget.RollingList
+	//  Our rolling list widget
+	parentWidget: null,
+	
+	// parentPane: dojox.widget._RollingListPane
+	//  The pane that immediately precedes ours
+	parentPane: null,
+			
+	// store: store
+	//  the store we must use
+	store: null,
+
+	// items: item[]
+	//  an array of (possibly not-yet-loaded) items to display in this.
+	//  If this array is null, then the query and query options are used to
+	//  get the top-level items to use.  This array is also used to watch and
+	//  see if the pane needs to be reloaded (store notifications are handled)
+	//  by the pane
+	items: null,
+	
+	// query: object
+	//  a query to pass to the datastore.  This is only used if items are null
+	query: null,
+	
+	// queryOptions: object
+	//  query options to be passed to the datastore
+	queryOptions: null,
+	
+	// focusByNode: boolean
+	//  set to false if the subclass will handle its own node focusing
+	_focusByNode: true,
+	
+	// minWidth: integer
+	//	the width (in px) for this pane
+	minWidth: 0,
+	
+	_setContentAndScroll: function(/*String|DomNode|Nodelist*/cont, /*Boolean?*/isFakeContent){
+		// summary: sets the value of the content and scrolls it into view
+		this._setContent(cont, isFakeContent);
+		this.parentWidget.scrollIntoView(this);
+	},
+
+	_updateNodeWidth: function(n, min){
+		// summary: updates the min width of the pane to be minPaneWidth
+		n.style.width = "";
+		var nWidth = dojo.marginBox(n).w;
+		if(nWidth < min){
+			dojo.marginBox(n, {w: min});
+		}
+	},
+	
+	_onMinWidthChange: function(v){
+		// Called when the min width of a pane has changed
+		this._updateNodeWidth(this.domNode, v);
+	},
+	
+	_setMinWidthAttr: function(v){
+		if(v !== this.minWidth){
+			this.minWidth = v;
+			this._onMinWidthChange(v);
+		}
+	},
+	
+	startup: function(){
+		if(this._started){ return; }
+		if(this.store && this.store.getFeatures()["dojo.data.api.Notification"]){
+			window.setTimeout(dojo.hitch(this, function(){
+				// Set connections after a slight timeout to avoid getting in the
+				// condition where we are setting them while events are still 
+				// being fired
+				this.connect(this.store, "onSet", "_onSetItem");
+				this.connect(this.store, "onNew", "_onNewItem");
+				this.connect(this.store, "onDelete", "_onDeleteItem");
+			}), 1);
+		}
+		this.connect(this.focusNode||this.domNode, "onkeypress", "_focusKey");
+		this.parentWidget._updateClass(this.domNode, "Pane");
+		this.inherited(arguments);
+		this._onMinWidthChange(this.minWidth);
+	},
+
+	_focusKey: function(/*Event*/e){
+		// summary: called when a keypress happens on the widget
+		if(e.charOrCode == dojo.keys.BACKSPACE){
+			dojo.stopEvent(e);
+			return;
+		}else if(e.charOrCode == dojo.keys.LEFT_ARROW && this.parentPane){
+			this.parentPane.focus();
+			this.parentWidget.scrollIntoView(this.parentPane);
+		}else if(e.charOrCode == dojo.keys.ENTER){
+			this.parentWidget._onExecute();
+		}
+	},
+	
+	focus: function(/*boolean*/force){
+		// summary: sets the focus to this current widget
+		if(this.parentWidget._focusedPane != this){
+			this.parentWidget._focusedPane = this;
+			this.parentWidget.scrollIntoView(this);
+			if(this._focusByNode && (!this.parentWidget._savedFocus || force)){
+				try{(this.focusNode||this.domNode).focus();}catch(e){}
+			}
+		}
+	},
+	
+	_onShow: function(){
+		// summary: checks that the store is loaded
+		if((this.store || this.items) && ((this.refreshOnShow && this.domNode) || (!this.isLoaded && this.domNode))){
+			this.refresh();
+		}
+	},
+	
+	_load: function(){
+		// summary: sets the "loading" message and then kicks off a query asyncronously
+		this.isLoaded = false;
+		if(this.items){
+			this._setContentAndScroll(this.onLoadStart(), true);
+			window.setTimeout(dojo.hitch(this, "_doQuery"), 1);
+		}else{
+			this._doQuery();
+		}
+	},
+	
+	_doLoadItems: function(/*item[]*/items, /*function*/callback){
+		// summary: loads the given items, and then calls the callback when they
+		//		are finished.
+		var _waitCount = 0, store = this.store;
+		dojo.forEach(items, function(item){ 
+			if(!store.isItemLoaded(item)){ _waitCount++; }
+		});
+		if(_waitCount === 0){
+			callback();
+		}else{
+			var onItem = function(item){
+				_waitCount--;
+				if((_waitCount) === 0){
+					callback();
+				}
+			};
+			dojo.forEach(items, function(item){
+				if(!store.isItemLoaded(item)){
+					store.loadItem({item: item, onItem: onItem});
+				}
+			});
+		}	
+	},
+	
+	_doQuery: function(){
+		// summary: either runs the query or loads potentially not-yet-loaded items.
+		if(!this.domNode){return;}
+		var preload = this.parentWidget.preloadItems;
+		preload = (preload === true || (this.items && this.items.length <= Number(preload)));
+		if(this.items && preload){
+			this._doLoadItems(this.items, dojo.hitch(this, "onItems"));
+		}else if(this.items){
+			this.onItems();
+		}else{
+			this._setContentAndScroll(this.onFetchStart(), true);
+			this.store.fetch({query: this.query, 
+				onComplete: function(items){
+					this.items = items;
+					this.onItems();
+				}, 
+				onError: function(e){
+					this._onError("Fetch", e);
+				},
+				scope: this});
+		}
+	},
+
+	_hasItem: function(/* item */ item){
+		// summary: returns whether or not the given item is handled by this 
+		//  pane
+		var items = this.items || [];
+		for(var i = 0, myItem; (myItem = items[i]); i++){
+			if(this.parentWidget._itemsMatch(myItem, item)){
+				return true;
+			}
+		}
+		return false;
+	},
+	
+	_onSetItem: function(/* item */ item, 
+					/* attribute-name-string */ attribute, 
+					/* object | array */ oldValue,
+					/* object | array */ newValue){	
+		// Summary: called when an item in the store has changed
+		if(this._hasItem(item)){
+			this.refresh();
+		}
+	},
+	
+	_onNewItem: function(/* item */ newItem, /*object?*/ parentInfo){
+		// Summary: called when an item is added to the store
+		var sel;
+		if((!parentInfo && !this.parentPane) ||
+			(parentInfo && this.parentPane && this.parentPane._hasItem(parentInfo.item) &&
+			(sel = this.parentPane._getSelected()) && this.parentWidget._itemsMatch(sel.item, parentInfo.item))){
+			this.items.push(newItem);
+			this.refresh();
+		}else if(parentInfo && this.parentPane && this._hasItem(parentInfo.item)){
+			this.refresh();
+		}
+	},
+	
+	_onDeleteItem: function(/* item */ deletedItem){
+		// Summary: called when an item is removed from the store
+		if(this._hasItem(deletedItem)){
+			this.items = dojo.filter(this.items, function(i){
+				return (i != deletedItem);
+			});
+			this.refresh();
+		}
+	},
+	
+	onFetchStart: function(){
+		// summary:
+		//		called before a fetch starts
+		return this.loadingMessage;
+	},
+	
+	onFetchError: function(/*Error*/ error){
+		// summary:
+		//	called when a fetch error occurs.
+		return this.errorMessage;
+	},
+
+	onLoadStart: function(){
+		// summary:
+		//		called before a load starts
+		return this.loadingMessage;
+	},
+	
+	onLoadError: function(/*Error*/ error){
+		// summary:
+		//	called when a load error occurs.
+		return this.errorMessage;
+	},
+	
+	onItems: function(){
+		// summary:
+		//	called after a fetch or load - at this point, this.items should be
+		//  set and loaded.  Override this function to "do your stuff"
+		if(!this.onLoadDeferred){
+			this.cancel();
+			this.onLoadDeferred = new dojo.Deferred(dojo.hitch(this, "cancel"));
+		}
+		this._onLoadHandler();		
+	}
+			
 });
-}
-}
-return _75;
-}
-},_setStore:function(_77){
-if(_77===this.store&&this._started){
-return;
-}
-this.store=_77;
-this._isIdentity=_77.getFeatures()["dojo.data.api.Identity"];
-var _78=this._getPaneForItem();
-this.addChild(_78,0);
-},_onKey:function(e){
-if(e.charOrCode==dojo.keys.BACKSPACE){
-dojo.stopEvent(e);
-return;
-}else{
-if(e.charOrCode==dojo.keys.ESCAPE&&this._savedFocus){
-try{
-dijit.focus(this._savedFocus);
-}
-catch(e){
-}
-dojo.stopEvent(e);
-return;
-}else{
-if(e.charOrCode==dojo.keys.LEFT_ARROW||e.charOrCode==dojo.keys.RIGHT_ARROW){
-dojo.stopEvent(e);
-return;
-}
-}
-}
-},_resetValue:function(){
-this.attr("value",this._lastExecutedValue);
-},_onCancel:function(){
-this._resetValue();
-this.onCancel();
-},_onExecute:function(){
-this._lastExecutedValue=this.attr("value");
-this.onExecute();
-},focus:function(){
-var _79=this._savedFocus;
-this._savedFocus=dijit.getFocus(this);
-if(!this._savedFocus.node){
-delete this._savedFocus;
-}
-if(!this._focusedPane){
-var _7a=this.getChildren()[0];
-if(_7a&&!_79){
-_7a.focus(true);
-}
-}else{
-this._savedFocus=dijit.getFocus(this);
-var foc=this._focusedPane;
-delete this._focusedPane;
-if(!_79){
-foc.focus(true);
-}
-}
-},handleKey:function(e){
-if(e.charOrCode==dojo.keys.DOWN_ARROW){
-delete this._savedFocus;
-this.focus();
-return false;
-}else{
-if(e.charOrCode==dojo.keys.ESCAPE){
-this._onCancel();
-return false;
-}
-}
-return true;
-},_updateChildClasses:function(){
-var _7b=this.getChildren();
-var _7c=_7b.length;
-dojo.forEach(_7b,function(c,idx){
-dojo.toggleClass(c.domNode,"dojoxRollingListPaneCurrentChild",(idx==(_7c-1)));
-dojo.toggleClass(c.domNode,"dojoxRollingListPaneCurrentSelected",(idx==(_7c-2)));
+
+dojo.declare("dojox.widget._RollingListGroupPane",
+	[dojox.widget._RollingListPane], {
+	// summary: a pane that will handle groups (treats them as menu items)
+	
+	// templateString: string
+	//	our template
+	templateString: '<div><div dojoAttachPoint="containerNode"></div>' +
+					'<div dojoAttachPoint="menuContainer">' +
+						'<div dojoAttachPoint="menuNode"></div>' +
+					'</div></div>',
+
+	// _menu: dijit.Menu
+	//  The menu that we will call addChild() on for adding items
+	_menu: null,
+	
+	_setContent: function(/*String|DomNode|Nodelist*/cont){
+		if(!this._menu){
+			// Only set the content if we don't already have a menu
+			this.inherited(arguments);
+		}
+	},
+
+	_onMinWidthChange: function(v){
+		// override and resize the menu instead
+		if(!this._menu){ return; }
+		var dWidth = dojo.marginBox(this.domNode).w;
+		var mWidth = dojo.marginBox(this._menu.domNode).w;
+		this._updateNodeWidth(this._menu.domNode, v - (dWidth - mWidth));
+	},
+
+	onItems: function(){
+		// summary:
+		//	called after a fetch or load
+		var selectItem, hadChildren = false;
+		if(this._menu){
+			selectItem = this._getSelected();
+			this._menu.destroyRecursive();
+		}
+		this._menu = this._getMenu();
+		var child, selectMenuItem;
+		if(this.items.length){
+			dojo.forEach(this.items, function(item){
+				child = this.parentWidget._getMenuItemForItem(item, this);
+				if(child){
+					if(selectItem && this.parentWidget._itemsMatch(child.item, selectItem.item)){
+						selectMenuItem = child;
+					}
+					this._menu.addChild(child);
+				}
+			}, this);
+		}else{
+			child = this.parentWidget._getMenuItemForItem(null, this);
+			if(child){
+				this._menu.addChild(child);
+			}
+		}
+		if(selectMenuItem){
+			this._setSelected(selectMenuItem);
+			if((selectItem && !selectItem.children && selectMenuItem.children) ||
+				(selectItem && selectItem.children && !selectMenuItem.children)){
+				var itemPane = this.parentWidget._getPaneForItem(selectMenuItem.item, this, selectMenuItem.children);
+				if(itemPane){
+					this.parentWidget.addChild(itemPane, this.getIndexInParent() + 1);
+				}else{
+					this.parentWidget._removeAfter(this);
+					this.parentWidget._onItemClick(null, this, selectMenuItem.item, selectMenuItem.children);
+				}
+			}
+		}else if(selectItem){
+			this.parentWidget._removeAfter(this);
+		}
+		this.containerNode.innerHTML = "";
+		this.containerNode.appendChild(this._menu.domNode);
+		this.parentWidget.scrollIntoView(this);
+		this._checkScrollConnection(true);
+		this.inherited(arguments);
+		this._onMinWidthChange(this.minWidth);
+	},
+	
+	_checkScrollConnection: function(doLoad){
+		// summary: checks whether or not we need to connect to our onscroll 
+		//		function
+		var store = this.store
+		if(this._scrollConn){
+			this.disconnect(this._scrollConn);
+		}
+		delete this._scrollConn;
+		if(!dojo.every(this.items, function(i){return store.isItemLoaded(i);})){
+			if(doLoad){
+				this._loadVisibleItems();
+			}
+			this._scrollConn = this.connect(this.domNode, "onscroll", "_onScrollPane");
+		}	
+	},
+	
+	startup: function(){
+		this.inherited(arguments);
+		this.parentWidget._updateClass(this.domNode, "GroupPane");
+	},
+	
+	focus: function(/*boolean*/force){
+		// summary: sets the focus to this current widget
+		if(this._menu){
+			if(this._pendingFocus){
+				this.disconnect(this._pendingFocus);
+			}
+			delete this._pendingFocus;
+			
+			// We focus the right widget - either the focusedChild, the
+			//   selected node, the first menu item, or the menu itself
+			var focusWidget = this._menu.focusedChild;
+			if(!focusWidget){
+				var focusNode = dojo.query(".dojoxRollingListItemSelected", this.domNode)[0];
+				if(focusNode){
+					focusWidget = dijit.byNode(focusNode);
+				}
+			}
+			if(!focusWidget){
+				focusWidget = this._menu.getChildren()[0] || this._menu;
+			}
+			this._focusByNode = false;
+			if(focusWidget.focusNode){
+				if(!this.parentWidget._savedFocus || force){
+					try{focusWidget.focusNode.focus();}catch(e){}
+				}
+				window.setTimeout(function(){
+					try{
+						dojo.window.scrollIntoView(focusWidget.focusNode);
+					}catch(e){}
+				}, 1);
+			}else if(focusWidget.focus){
+				if(!this.parentWidget._savedFocus || force){
+					focusWidget.focus();
+				}
+			}else{
+				this._focusByNode = true;
+			}
+			this.inherited(arguments);
+		}else if(!this._pendingFocus){
+			this._pendingFocus = this.connect(this, "onItems", "focus");
+		}
+	},
+	
+	_getMenu: function(){
+		// summary: returns a widget to be used for the container widget.
+		var self = this;
+		var menu = new dijit.Menu({
+			parentMenu: this.parentPane ? this.parentPane._menu : null,
+			onCancel: function(/*Boolean*/ closeAll){ 
+				if(self.parentPane){
+					self.parentPane.focus(true);
+				}
+			},
+			_moveToPopup: function(/*Event*/ evt){
+				if(this.focusedChild && !this.focusedChild.disabled){
+					this.focusedChild._onClick(evt);
+				}
+			}
+		}, this.menuNode);
+		this.connect(menu, "onItemClick", function(/*dijit.MenuItem*/ item, /*Event*/ evt){
+			if(item.disabled){ return; }
+			evt.alreadySelected = dojo.hasClass(item.domNode, "dojoxRollingListItemSelected");
+			if(evt.alreadySelected && 
+				((evt.type == "keypress" && evt.charOrCode != dojo.keys.ENTER) ||
+				(evt.type == "internal"))){
+				var p = this.parentWidget.getChildren()[this.getIndexInParent() + 1];
+				if(p){
+					p.focus(true);
+					this.parentWidget.scrollIntoView(p);
+				}
+			}else{
+				this._setSelected(item, menu);
+				this.parentWidget._onItemClick(evt, this, item.item, item.children);
+				if(evt.type == "keypress" && evt.charOrCode == dojo.keys.ENTER){
+					this.parentWidget._onExecute();
+				}
+			}
+		});
+		if(!menu._started){
+			menu.startup();
+		}
+		return menu;
+	},
+	
+	_onScrollPane: function(){
+		// summary: called when the pane has been scrolled - it sets a timeout
+		//		so that we don't try and load our visible items too often during
+		//		a scroll
+		if(this._visibleLoadPending){
+			window.clearTimeout(this._visibleLoadPending);
+		}
+		this._visibleLoadPending = window.setTimeout(dojo.hitch(this, "_loadVisibleItems"), 500);
+	},
+	
+	_loadVisibleItems: function(){
+		// summary: loads the items that are currently visible in the pane
+		delete this._visibleLoadPending
+		var menu = this._menu;
+		if(!menu){ return; }
+		var children = menu.getChildren();
+		if(!children || !children.length){ return; }
+		var gpbme = function(n, m, pb){
+			var s = dojo.getComputedStyle(n);
+			var r = 0;
+			if(m){ r += dojo._getMarginExtents(n, s).t; }
+			if(pb){ r += dojo._getPadBorderExtents(n, s).t; }
+			return r;
+		};
+		var topOffset = gpbme(this.domNode, false, true) + 
+						gpbme(this.containerNode, true, true) + 
+						gpbme(menu.domNode, true, true) +
+						gpbme(children[0].domNode, true, false);
+		var h = dojo.contentBox(this.domNode).h;
+		var minOffset = this.domNode.scrollTop - topOffset - (h/2);
+		var maxOffset = minOffset + (3*h/2);
+		var menuItemsToLoad = dojo.filter(children, function(c){
+			var cnt = c.domNode.offsetTop;
+			var s = c.store;
+			var i = c.item;
+			return (cnt >= minOffset && cnt <= maxOffset && !s.isItemLoaded(i));
+		})
+		var itemsToLoad = dojo.map(menuItemsToLoad, function(c){
+			return c.item;
+		});
+		var onItems = dojo.hitch(this, function(){
+			var selectItem = this._getSelected();
+			var selectMenuItem;
+			dojo.forEach(itemsToLoad, function(item, idx){
+				var newItem = this.parentWidget._getMenuItemForItem(item, this);
+				var oItem = menuItemsToLoad[idx];
+				var oIdx = oItem.getIndexInParent();
+				menu.removeChild(oItem);
+				if(newItem){
+					if(selectItem && this.parentWidget._itemsMatch(newItem.item, selectItem.item)){
+						selectMenuItem = newItem;
+					}
+					menu.addChild(newItem, oIdx);
+					if(menu.focusedChild == oItem){
+						menu.focusChild(newItem);
+					}
+				}
+				oItem.destroy();
+			}, this);
+			this._checkScrollConnection(false);
+		});
+		this._doLoadItems(itemsToLoad, onItems);
+	},
+	
+	_getSelected: function(/*dijit.Menu?*/ menu){
+		// summary:
+		//	returns the selected menu item - or null if none are selected
+		if(!menu){ menu = this._menu; }
+		if(menu){
+			var children = this._menu.getChildren();
+			for(var i = 0, item; (item = children[i]); i++){
+				if(dojo.hasClass(item.domNode, "dojoxRollingListItemSelected")){
+					return item;
+				}
+			}
+		}
+		return null;
+	},
+	
+	_setSelected: function(/*dijit.MenuItem?*/ item, /*dijit.Menu?*/ menu){
+		// summary:
+		//	selectes the given item in the given menu (defaults to pane's menu)
+		if(!menu){ menu = this._menu;}
+		if(menu){
+			dojo.forEach(menu.getChildren(), function(i){
+				this.parentWidget._updateClass(i.domNode, "Item", {"Selected": (item && (i == item && !i.disabled))});
+			}, this);
+		}
+	}
 });
-},startup:function(){
-if(this._started){
-return;
-}
-if(!this.getParent||!this.getParent()){
-this.resize();
-this.connect(dojo.global,"onresize","resize");
-}
-this.connect(this,"addChild","_updateChildClasses");
-this.connect(this,"removeChild","_updateChildClasses");
-this._setStore(this.store);
-this.attr("showButtons",this.showButtons);
-this.inherited(arguments);
-this._lastExecutedValue=this.attr("value");
-},getChildItems:function(_7d){
-var _7e,_7f=this.store;
-dojo.forEach(this.childrenAttrs,function(_80){
-var _81=_7f.getValues(_7d,_80);
-if(_81&&_81.length){
-_7e=(_7e||[]).concat(_81);
-}
+
+dojo.declare("dojox.widget.RollingList",
+	[dijit._Widget, dijit._Templated, dijit._Container], {
+	// summary: a rolling list that can be tied to a data store with children
+		
+	// templateString: String
+	//		The template to be used to construct the widget.
+	templateString: dojo.cache("dojox.widget", "RollingList/RollingList.html"),
+	widgetsInTemplate: true,
+	
+	// className: string
+	//  an additional class (or space-separated classes) to add for our widget
+	className: "",
+	
+	// store: store
+	//  the store we must use
+	store: null,
+	
+	// query: object
+	//  a query to pass to the datastore.  This is only used if items are null
+	query: null,
+	
+	// queryOptions: object
+	//  query options to be passed to the datastore
+	queryOptions: null,
+	
+	// childrenAttrs: String[]
+	//		one ore more attributes that holds children of a node
+	childrenAttrs: ["children"],
+
+	// parentAttr: string
+	//	the attribute to read for finding our parent item (if any)
+	parentAttr: "",
+	
+	// value: item
+	//		The value that has been selected
+	value: null,
+	
+	// executeOnDblClick: boolean
+	//		Set to true if you want to call onExecute when an item is
+	//		double-clicked, false if you want to call onExecute yourself. (mainly
+	//		used for popups to control how they want to be handled)
+	executeOnDblClick: true,
+	
+	// preloadItems: boolean or int
+	//		if set to true, then onItems will be called only *after* all items have
+	//		been loaded (ie store.isLoaded will return true for all of them).  If 
+	//		false, then no preloading will occur.  If set to an integer, preloading
+	//		will occur if the number of items is less than or equal to the value
+	//		of the integer.  The onItems function will need to be aware of handling
+	//		items that may not be loaded
+	preloadItems: false,
+	
+	// showButtons: boolean
+	//		if set to true, then buttons for "OK" and "Cancel" will be provided
+	showButtons: false,
+	
+	// okButtonLabel: string
+	//		The string to use for the OK button - will use dijit's common "OK" string
+	//		if not set
+	okButtonLabel: "",
+	
+	// cancelButtonLabel: string
+	//		The string to use for the Cancel button - will use dijit's common 
+	//		"Cancel" string if not set
+	cancelButtonLabel: "",
+
+	// minPaneWidth: integer
+	//	the minimum pane width (in px) for all child panes.  If they are narrower,
+	//  the width will be increased to this value.
+	minPaneWidth: 0,
+	
+	postMixInProperties: function(){
+		// summary: Mix in our labels, if they are not set
+		this.inherited(arguments);
+		var loc = dojo.i18n.getLocalization("dijit", "common");
+		this.okButtonLabel = this.okButtonLabel || loc.buttonOk;
+		this.cancelButtonLabel = this.cancelButtonLabel || loc.buttonCancel;
+	},
+	
+	_setShowButtonsAttr: function(doShow){
+		// summary: Sets the visibility of the buttons for the widget
+		var needsLayout = false;
+		if((this.showButtons != doShow && this._started) ||
+			(this.showButtons == doShow && !this.started)){
+			needsLayout = true;
+		}
+		dojo.toggleClass(this.domNode, "dojoxRollingListButtonsHidden", !doShow);
+		this.showButtons = doShow;
+		if(needsLayout){
+			if(this._started){
+				this.layout();
+			}else{
+				window.setTimeout(dojo.hitch(this, "layout"), 0);
+			}
+		}
+	},
+	
+	_itemsMatch: function(/*item*/ item1, /*item*/ item2){
+		// Summary: returns whether or not the two items match - checks ID if
+		//  they aren't the exact same object
+		if(!item1 && !item2){ 
+			return true;
+		}else if(!item1 || !item2){
+			return false;
+		}
+		return (item1 == item2 || 
+			(this._isIdentity && this.store.getIdentity(item1) == this.store.getIdentity(item2)));
+	},
+	
+	_removeAfter: function(/*Widget or int*/ idx){
+		// summary: removes all widgets after the given widget (or index)
+		if(typeof idx != "number"){
+			idx = this.getIndexOfChild(idx);
+		}
+		if(idx >= 0){
+			dojo.forEach(this.getChildren(), function(c, i){
+				if(i > idx){
+					this.removeChild(c);
+					c.destroyRecursive();
+				}
+			}, this);
+		}
+		var children = this.getChildren(), child = children[children.length - 1];
+		var selItem = null;
+		while(child && !selItem){
+			var val = child._getSelected ? child._getSelected() : null;
+			if(val){
+				selItem = val.item;
+			}
+			child = child.parentPane;
+		}
+		if(!this._setInProgress){
+			this._setValue(selItem);
+		}
+	},
+	
+	addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
+		// summary: adds a child to this rolling list - if passed an insertIndex,
+		//  then all children from that index on will be removed and destroyed
+		//  before adding the child.
+		if(insertIndex > 0){
+			this._removeAfter(insertIndex - 1);
+		}
+		this.inherited(arguments);
+		if(!widget._started){
+			widget.startup();
+		}
+		widget.attr("minWidth", this.minPaneWidth);
+		this.layout();
+		if(!this._savedFocus){
+			widget.focus();
+		}
+	},
+	
+	_setMinPaneWidthAttr: function(value){
+		// summary:
+		//		Sets the min pane width of all children
+		if(value !== this.minPaneWidth){
+			this.minPaneWidth = value;
+			dojo.forEach(this.getChildren(), function(c){
+				c.attr("minWidth", value);
+			});
+		}
+	},
+	
+	_updateClass: function(/* Node */ node, /* String */ type, /* Object? */ options){
+		// summary: 
+		//		sets the state of the given node with the given type and options
+		// options: 
+		//		an object with key-value-pairs.  The values are boolean, if true,
+		//		the key is added as a class, if false, it is removed.
+		if(!this._declaredClasses){
+			this._declaredClasses = ("dojoxRollingList " + this.className).split(" ");
+		}
+		dojo.forEach(this._declaredClasses, function(c){
+			if(c){
+				dojo.addClass(node, c + type);
+				for(var k in options||{}){
+					dojo.toggleClass(node, c + type + k, options[k]);
+				}
+				dojo.toggleClass(node, c + type + "FocusSelected", 
+					(dojo.hasClass(node, c + type + "Focus") && dojo.hasClass(node, c + type + "Selected")));
+				dojo.toggleClass(node, c + type + "HoverSelected", 
+					(dojo.hasClass(node, c + type + "Hover") && dojo.hasClass(node, c + type + "Selected")));
+			}
+		});
+	},
+	
+	scrollIntoView: function(/*dijit._Widget*/ childWidget){
+		// summary: scrolls the given widget into view
+		if(this._scrollingTimeout){ 
+			window.clearTimeout(this._scrollingTimeout);
+		}
+		delete this._scrollingTimeout;
+		this._scrollingTimeout = window.setTimeout(dojo.hitch(this, function(){
+			if(childWidget.domNode){
+				dojo.window.scrollIntoView(childWidget.domNode);
+			}
+			delete this._scrollingTimeout;
+			return;
+		}), 1);
+	},
+	
+	resize: function(args){
+		dijit.layout._LayoutWidget.prototype.resize.call(this, args);
+	},
+	
+	layout: function(){
+		var children = this.getChildren();
+		if(this._contentBox){
+			var bn = this.buttonsNode;
+			var height = this._contentBox.h - dojo.marginBox(bn).h -
+								dojox.html.metrics.getScrollbar().h;
+			dojo.forEach(children, function(c){
+				dojo.marginBox(c.domNode, {h: height});
+			});
+		}
+		if(this._focusedPane){
+			var foc = this._focusedPane;
+			delete this._focusedPane;
+			if(!this._savedFocus){
+				foc.focus();
+			}
+		}else if(children && children.length){
+			if(!this._savedFocus){
+				children[0].focus();
+			}
+		}
+	},
+	
+	_onChange: function(/*item*/ value){
+		this.onChange(value);
+	},
+
+	_setValue: function(/* item */ value){
+		// summary: internally sets the value and fires onchange
+		delete this._setInProgress;
+		if(!this._itemsMatch(this.value, value)){
+			this.value = value;
+			this._onChange(value);
+		}
+	},
+	
+	_setValueAttr: function(/* item */ value){
+		// summary: sets the value of this widget to the given store item
+		if(this._itemsMatch(this.value, value) && !value){ return; }
+		if(this._setInProgress && this._setInProgress === value){ return; }
+		this._setInProgress = value;
+		if(!value || !this.store.isItem(value)){
+			var pane = this.getChildren()[0];
+			pane._setSelected(null);
+			this._onItemClick(null, pane, null, null);
+			return;
+		}
+		
+		var fetchParentItems = dojo.hitch(this, function(/*item*/ item, /*function*/callback){
+			// Summary: Fetchs the parent items for the given item
+			var store = this.store, id;
+			if(this.parentAttr && store.getFeatures()["dojo.data.api.Identity"] &&
+				((id = this.store.getValue(item, this.parentAttr)) || id === "")){
+				// Fetch by parent attribute
+				var cb = function(i){
+					if(store.getIdentity(i) == store.getIdentity(item)){
+						callback(null);
+					}else{
+						callback([i]);
+					}
+				};
+				if(id === ""){
+					callback(null);
+				}else if(typeof id == "string"){
+					store.fetchItemByIdentity({identity: id, onItem: cb});
+				}else if(store.isItem(id)){
+					cb(id);
+				}
+			}else{
+				// Fetch by finding children
+				var numCheck = this.childrenAttrs.length;
+				var parents = [];
+				dojo.forEach(this.childrenAttrs, function(attr){
+					var q = {};
+					q[attr] = item;
+					store.fetch({query: q, scope: this, 
+						onComplete: function(items){
+							if(this._setInProgress !== value){
+								return;
+							}
+							parents = parents.concat(items);
+							numCheck--;
+							if(numCheck === 0){
+								callback(parents);
+							}
+						}
+					});
+				}, this);
+			}
+		});
+		
+		var setFromChain = dojo.hitch(this, function(/*item[]*/itemChain, /*integer*/idx){
+			// Summary: Sets the value of the widget at the given index in the chain - onchanges are not 
+			// fired here
+			var set = itemChain[idx];
+			var child = this.getChildren()[idx];
+			var conn;
+			if(set && child){
+				var fx = dojo.hitch(this, function(){
+					if(conn){
+						this.disconnect(conn);
+					}
+					delete conn;
+					if(this._setInProgress !== value){
+						return;
+					}
+					var selOpt = dojo.filter(child._menu.getChildren(), function(i){
+						return this._itemsMatch(i.item, set);
+					}, this)[0];
+					if(selOpt){
+						idx++;
+						child._menu.onItemClick(selOpt, {type: "internal",
+													stopPropagation: function(){},
+													preventDefault: function(){}});
+						if(itemChain[idx]){
+							setFromChain(itemChain, idx);
+						}else{
+							this._setValue(set);
+							this.onItemClick(set, child, this.getChildItems(set));
+						}
+					}
+				});
+				if(!child.isLoaded){
+					conn = this.connect(child, "onLoad", fx);
+				}else{
+					fx();
+				}
+			}else if(idx === 0){
+				this.set("value", null);
+			}
+		});
+		
+		var parentChain = [];
+		var onParents = dojo.hitch(this, function(/*item[]*/ parents){
+			// Summary: recursively grabs the parents - only the first one is followed
+			if(parents && parents.length){
+				parentChain.push(parents[0]);
+				fetchParentItems(parents[0], onParents);
+			}else{
+				if(!parents){
+					parentChain.pop();
+				}
+				parentChain.reverse();
+				setFromChain(parentChain, 0);
+			}
+		});
+		
+		// Only set the value in display if we are shown - if we are in a dropdown, 
+		// and are hidden, don't actually do the scrolling in the display (it can
+		// mess up layouts)
+		var ns = this.domNode.style;
+		if(ns.display == "none" || ns.visibility == "hidden"){
+			this._setValue(value);
+		}else if(!this._itemsMatch(value, this._visibleItem)){
+			onParents([value]);
+		}
+	},
+	
+	_onItemClick: function(/* Event */ evt, /* dijit._Contained */ pane, /* item */ item, /* item[]? */ children){
+		// summary: internally called when a widget should pop up its child
+		
+		if(evt){
+			var itemPane = this._getPaneForItem(item, pane, children);
+			var alreadySelected = (evt.type == "click" && evt.alreadySelected);
+
+			if(alreadySelected && itemPane){
+				this._removeAfter(pane.getIndexInParent() + 1);
+				var next = pane.getNextSibling();
+				if(next && next._setSelected){
+					next._setSelected(null);
+				}
+				this.scrollIntoView(next);
+			}else if(itemPane){
+				this.addChild(itemPane, pane.getIndexInParent() + 1);
+				if(this._savedFocus){
+					itemPane.focus(true);
+				}
+			}else{
+				this._removeAfter(pane);
+				this.scrollIntoView(pane);
+			}
+		}else if(pane){
+			this._removeAfter(pane);
+			this.scrollIntoView(pane);
+		}
+		if(!evt || evt.type != "internal"){
+			this._setValue(item);
+			this.onItemClick(item, pane, children);
+		}
+		this._visibleItem = item;
+	},
+	
+	_getPaneForItem: function(/* item? */ item, /* dijit._Contained? */ parentPane, /* item[]? */ children){		// summary: gets the pane for the given item, and mixes in our needed parts
+		// Returns the pane for the given item (null if the root pane) - after mixing in
+		// its stuff.
+		var ret = this.getPaneForItem(item, parentPane, children);
+		ret.store = this.store;
+		ret.parentWidget = this;
+		ret.parentPane = parentPane||null;
+		if(!item){
+			ret.query = this.query;
+			ret.queryOptions = this.queryOptions;
+		}else if(children){
+			ret.items = children;
+		}else{
+			ret.items = [item];
+		}
+		return ret;
+	},
+	
+	_getMenuItemForItem: function(/*item*/ item, /* dijit._Contained */ parentPane){
+		// summary: returns a widget for the given store item.  The returned
+		//  item will be added to this widget's container widget.  null will
+		//  be passed in for an "empty" item.
+		var store = this.store;
+		if(!item || !store || !store.isItem(item)){
+			var i = new dijit.MenuItem({
+				label: "---",
+				disabled: true,
+				iconClass: "dojoxEmpty",
+				focus: function(){
+					// Do nothing on focus of this guy...
+				}
+			});	
+			this._updateClass(i.domNode, "Item");
+			return i;
+		}else{
+			var itemLoaded = store.isItemLoaded(item);
+			var childItems = itemLoaded ? this.getChildItems(item) : undefined;
+			var widgetItem;
+			if(childItems){
+				widgetItem = this.getMenuItemForItem(item, parentPane, childItems);
+				widgetItem.children = childItems;
+				this._updateClass(widgetItem.domNode, "Item", {"Expanding": true});
+				if(!widgetItem._started){
+					var c = widgetItem.connect(widgetItem, "startup", function(){
+						this.disconnect(c);
+						dojo.style(this.arrowWrapper, "display", "");
+					});
+				}else{
+					dojo.style(widgetItem.arrowWrapper, "display", "");
+				}
+			}else{
+				widgetItem = this.getMenuItemForItem(item, parentPane, null);
+				if(itemLoaded){
+					this._updateClass(widgetItem.domNode, "Item", {"Single": true});				
+				}else{
+					this._updateClass(widgetItem.domNode, "Item", {"Unloaded": true});				
+					widgetItem.attr("disabled", true);
+				}
+			}
+			widgetItem.store = this.store;
+			widgetItem.item = item;
+			if(!widgetItem.label){
+				widgetItem.attr("label", this.store.getLabel(item).replace(/</,"<"));
+			}
+			if(widgetItem.focusNode){
+				var self = this;
+				widgetItem.focus = function(){
+					// Don't set our class
+					if(!this.disabled){try{this.focusNode.focus();}catch(e){}}
+				};
+				widgetItem.connect(widgetItem.focusNode, "onmouseenter", function(){
+					if(!this.disabled){
+						self._updateClass(this.domNode, "Item", {"Hover": true});
+					}
+				});
+				widgetItem.connect(widgetItem.focusNode, "onmouseleave", function(){
+					if(!this.disabled){
+						self._updateClass(this.domNode, "Item", {"Hover": false});
+					}
+				});
+				widgetItem.connect(widgetItem.focusNode, "blur", function(){
+					self._updateClass(this.domNode, "Item", {"Focus": false, "Hover": false});
+				});
+				widgetItem.connect(widgetItem.focusNode, "focus", function(){
+					self._updateClass(this.domNode, "Item", {"Focus": true});
+					self._focusedPane = parentPane;
+				});
+				if(this.executeOnDblClick){
+					widgetItem.connect(widgetItem.focusNode, "ondblclick", function(){
+						self._onExecute();
+					});
+				}
+			}
+			return widgetItem;
+		}
+	},
+	
+	_setStore: function(/* dojo.data.api.Read */ store){
+		// summary: sets the store for this widget */
+		if(store === this.store && this._started){ return; }
+		this.store = store;
+		this._isIdentity = store.getFeatures()["dojo.data.api.Identity"];
+		var rootPane = this._getPaneForItem();
+		this.addChild(rootPane, 0);
+	},
+	
+	_onKey: function(/*Event*/ e){
+		// summary: called when a keypress event happens on this widget
+		if(e.charOrCode == dojo.keys.BACKSPACE){
+			dojo.stopEvent(e);
+			return;
+		}else if(e.charOrCode == dojo.keys.ESCAPE && this._savedFocus){
+			try{dijit.focus(this._savedFocus);}catch(e){}
+			dojo.stopEvent(e);
+			return;
+		}else if(e.charOrCode == dojo.keys.LEFT_ARROW || 
+			e.charOrCode == dojo.keys.RIGHT_ARROW){
+			dojo.stopEvent(e);
+			return;
+		}
+	},
+	
+	_resetValue: function(){
+		// Summary: function called when the value is reset.
+		this.set("value", this._lastExecutedValue);
+	},
+	
+	_onCancel: function(){
+		// Summary: function called when the cancel button is clicked.  It 
+		//		resets its value to whatever was last executed and then cancels
+		this._resetValue();
+		this.onCancel();
+	},
+	
+	_onExecute: function(){
+		// Summary: function called when the OK button is clicked or when an
+		//		item is selected (double-clicked or "enter" pressed on it)
+		this._lastExecutedValue = this.get("value");
+		this.onExecute();
+	},
+	
+	focus: function(){
+		// summary: sets the focus state of this widget
+		var wasSaved = this._savedFocus;
+		this._savedFocus = dijit.getFocus(this);
+		if(!this._savedFocus.node){
+			delete this._savedFocus;
+		}
+		if(!this._focusedPane){
+			var child = this.getChildren()[0];
+			if(child && !wasSaved){
+				child.focus(true);
+			}
+		}else{
+			this._savedFocus = dijit.getFocus(this);
+			var foc = this._focusedPane;
+			delete this._focusedPane;
+			if(!wasSaved){
+				foc.focus(true);
+			}
+		}
+	},
+	
+	handleKey:function(/*Event*/e){
+		// summary: handle the key for the given event - called by dropdown
+		//	widgets
+		if(e.charOrCode == dojo.keys.DOWN_ARROW){
+			delete this._savedFocus;
+			this.focus();
+			return false;
+		}else if(e.charOrCode == dojo.keys.ESCAPE){
+			this._onCancel();
+			return false;
+		}
+		return true;
+	},
+	
+	_updateChildClasses: function(){
+		// summary: Called when a child is added or removed - so that we can 
+		//	update the classes for styling the "current" one differently than
+		//	the others
+		var children = this.getChildren();
+		var length = children.length;
+		dojo.forEach(children, function(c, idx){
+			dojo.toggleClass(c.domNode, "dojoxRollingListPaneCurrentChild", (idx == (length - 1)));
+			dojo.toggleClass(c.domNode, "dojoxRollingListPaneCurrentSelected", (idx == (length - 2)));
+		});
+	},
+
+	startup: function(){
+		if(this._started){ return; }
+		if(!this.getParent || !this.getParent()){
+			this.resize();
+			this.connect(dojo.global, "onresize", "resize");
+		}
+		this.connect(this, "addChild", "_updateChildClasses");
+		this.connect(this, "removeChild", "_updateChildClasses");
+		this._setStore(this.store);
+		this.set("showButtons", this.showButtons);	
+		this.inherited(arguments);
+		this._lastExecutedValue = this.get("value");
+	},
+	
+	getChildItems: function(/*item*/ item){
+		// summary: Returns the child items for the given store item
+		var childItems, store = this.store;
+		dojo.forEach(this.childrenAttrs, function(attr){
+			var vals = store.getValues(item, attr);
+			if(vals && vals.length){
+				childItems = (childItems||[]).concat(vals);
+			}
+		});
+		return childItems;
+	},
+	
+	getMenuItemForItem: function(/*item*/ item, /* dijit._Contained */ parentPane, /* item[]? */ children){
+		// summary: user overridable function to return a widget for the given item
+		//  and its children.
+		return new dijit.MenuItem({});
+	},
+
+	getPaneForItem: function(/* item? */ item, /* dijit._Contained? */ parentPane, /* item[]? */ children){
+		// summary: user-overridable function to return a pane that corresponds
+		//  to the given item in the store.  It can return null to not add a new pane
+		//  (ie, you are planning on doing something else with it in onItemClick)
+		//
+		//  Item is undefined for the root pane, children is undefined for non-group panes 
+		if(!item || children){
+			return new dojox.widget._RollingListGroupPane({});
+		}else{
+			return null;
+		}
+	},
+
+	onItemClick: function(/* item */ item, /* dijit._Contained */ pane, /* item[]? */ children){
+		// summary: called when an item is clicked - it receives the store item
+	},
+	
+	onExecute: function(){
+		// summary: exists so that popups don't disappear too soon
+	},
+	
+	onCancel: function(){
+		// summary: exists so that we can close ourselves if we wish
+	},
+	
+	onChange: function(/* item */ value){
+		// summary: called when the value of this widget has changed
+	}
+	
 });
-return _7e;
-},getMenuItemForItem:function(_82,_83,_84){
-return new dijit.MenuItem({});
-},getPaneForItem:function(_85,_86,_87){
-if(!_85||_87){
-return new dojox.widget._RollingListGroupPane({});
-}else{
-return null;
-}
-},onItemClick:function(_88,_89,_8a){
-},onExecute:function(){
-},onCancel:function(){
-},onChange:function(_8b){
-}});
-}
diff --git a/dojox/widget/RollingList/RollingList.css b/dojox/widget/RollingList/RollingList.css
index 6334510..31649e7 100644
--- a/dojox/widget/RollingList/RollingList.css
+++ b/dojox/widget/RollingList/RollingList.css
@@ -4,56 +4,68 @@
 	background-color: #FFF;
 	position: relative;
 }
+
 .dijitPopup .dojoxRollingList {
 	position: static;
 }
+
 .dojoxRollingListContainer {
 	overflow: scroll;
 	overflow-y: hidden;
 	overflow-x: scroll;
 	white-space: nowrap;
 }
+
 .dojoxRollingListButtons {
 	position: absolute;
 	right: 5px;
 	padding: 5px 0px;
 }
+
 .dojoxRollingListButtonsHidden .dojoxRollingListButtons {
 	display: none;
 }
+
 .dojoxRollingListPane {
 	overflow: scroll;
 	overflow-x: hidden;
 	overflow-y: scroll;
-	display:-moz-inline-box;		
-	display:inline-block;			
-	#zoom: 1; 
-	#display:inline; 
+	display:-moz-inline-box;		/* FF2 */
+	display:inline-block;			/* webkit and FF3 */
+	#zoom: 1; /* set hasLayout:true to mimic inline-block */
+	#display:inline; /* don't use .dj_ie since that increases the priority */
 	border:0;
 	padding:0;
 	vertical-align:middle;
-	#vertical-align: auto;	
+	#vertical-align: auto;	/* makes TextBox,Button line up w/native counterparts on IE6 */
 }
+
 .dojoxRollingListPane .dijitMenuItem td {
 	width: 1px;
 }
 .dojoxRollingListPane .dijitMenuItem td.dijitMenuItemLabel {
 	width: auto;
 }
+
 .dojoxRollingListPane .dijitMenuItemLabel,
 .dojoxRollingListPane .dijitMenuItemIcon {
 	position: static !important;
 }
+
 .dj_webkit .dojoxRollingListPane,
 .dj_ie .dojoxRollingListPane {
-	padding-right: 15px; 
+	padding-right: 15px; /* Account for scroll bar */
 }
+
 .dojoxRollingListPane .dijitMenu {
 	border: none !important;
 }
+
 .dojoxRollingListItem {
 	cursor: default;
 }
+
+/* Background colors to match menus */
 .tundra .dojoxRollingList {
 	border-color: #b3b3b3;
 }
@@ -82,6 +94,7 @@
 .tundra .dojoxRollingListItem {
 	font-family: inherit;
 }
+
 .soria .dojoxRollingList {
 	border-color: #8ba0bd;
 }
@@ -110,6 +123,8 @@
 .soria .dojoxRollingListItem {
 	font-family: inherit;
 }
+
+
 .nihilo .dojoxRollingList {
 	border-color: #d3d3d3;
 }
@@ -138,3 +153,4 @@
 .nihilo .dojoxRollingListItem {
 	font-family: inherit;
 }
+
diff --git a/dojox/widget/Rotator.js b/dojox/widget/Rotator.js
index 7a90d9a..58b45ef 100644
--- a/dojox/widget/Rotator.js
+++ b/dojox/widget/Rotator.js
@@ -1,148 +1,364 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.Rotator"]){
-dojo._hasResource["dojox.widget.Rotator"]=true;
 dojo.provide("dojox.widget.Rotator");
 dojo.require("dojo.parser");
+
 (function(d){
-var _1="dojox.widget.rotator.swap",_2=500,_3="display",_4="none",_5="zIndex";
-d.declare("dojox.widget.Rotator",null,{transition:_1,transitionParams:"duration:"+_2,panes:null,constructor:function(_6,_7){
-d.mixin(this,_6);
-var _8=this,t=_8.transition,tt=_8._transitions={},_9=_8._idMap={},tp=_8.transitionParams=eval("({ "+_8.transitionParams+" })"),_7=_8._domNode=dojo.byId(_7),cb=_8._domNodeContentBox=d.contentBox(_7),p={left:0,top:0},_a=function(bt,dt){
-console.warn(_8.declaredClass," - Unable to find transition \"",bt,"\", defaulting to \"",dt,"\".");
-};
-_8.id=_7.id||(new Date()).getTime();
-if(d.style(_7,"position")=="static"){
-d.style(_7,"position","relative");
-}
-tt[t]=d.getObject(t);
-if(!tt[t]){
-_a(t,_1);
-tt[_8.transition=_1]=d.getObject(_1);
-}
-if(!tp.duration){
-tp.duration=_2;
-}
-d.forEach(_8.panes,function(p){
-d.create("div",p,_7);
-});
-var pp=_8.panes=[];
-d.query(">",_7).forEach(function(n,i){
-var q={node:n,idx:i,params:d.mixin({},tp,eval("({ "+(d.attr(n,"transitionParams")||"")+" })"))},r=q.trans=d.attr(n,"transition")||_8.transition;
-d.forEach(["id","title","duration","waitForEvent"],function(a){
-q[a]=d.attr(n,a);
-});
-if(q.id){
-_9[id]=i;
-}
-if(!tt[r]&&!(tt[r]=d.getObject(r))){
-_a(r,q.trans=_8.transition);
-}
-p.position="absolute";
-p.display=_4;
-if(_8.idx==null||d.attr(n,"selected")){
-if(_8.idx!=null){
-d.style(pp[_8.idx].node,_3,_4);
-}
-_8.idx=i;
-p.display="";
-}
-d.style(n,p);
-d.query("> script[type^='dojo/method']",n).orphan().forEach(function(s){
-var e=d.attr(s,"event");
-if(e){
-q[e]=d.parser._functionFromScript(s);
-}
-});
-pp.push(q);
-});
-_8._controlSub=d.subscribe(_8.id+"/rotator/control",_8,"control");
-},destroy:function(){
-d.forEach([this._controlSub,this.wfe],d.unsubscribe);
-d.destroy(this._domNode);
-},next:function(){
-return this.go(this.idx+1);
-},prev:function(){
-return this.go(this.idx-1);
-},go:function(p){
-var _b=this,i=_b.idx,pp=_b.panes,_c=pp.length,_d=_b._idMap[p];
-_b._resetWaitForEvent();
-p=_d!=null?_d:(p||0);
-p=p<_c?(p<0?_c-1:p):0;
-if(p==i||_b.anim){
-return null;
-}
-var _e=pp[i],_f=pp[p];
-d.style(_e.node,_5,2);
-d.style(_f.node,_5,1);
-var _10={current:_e,next:_f,rotator:_b},_11=_b.anim=_b._transitions[_f.trans](d.mixin({rotatorBox:_b._domNodeContentBox},_10,_f.params));
-if(_11){
-var def=new d.Deferred(),ev=_f.waitForEvent,h=d.connect(_11,"onEnd",function(){
-d.style(_e.node,{display:_4,left:0,opacity:1,top:0,zIndex:0});
-d.disconnect(h);
-_b.anim=null;
-_b.idx=p;
-if(_e.onAfterOut){
-_e.onAfterOut(_10);
-}
-if(_f.onAfterIn){
-_f.onAfterIn(_10);
-}
-_b.onUpdate("onAfterTransition");
-if(!ev){
-_b._resetWaitForEvent();
-def.callback();
-}
-});
-_b.wfe=ev?d.subscribe(ev,function(){
-_b._resetWaitForEvent();
-def.callback(true);
-}):null;
-_b.onUpdate("onBeforeTransition");
-if(_e.onBeforeOut){
-_e.onBeforeOut(_10);
-}
-if(_f.onBeforeIn){
-_f.onBeforeIn(_10);
-}
-_11.play();
-return def;
-}
-},onUpdate:function(_12,_13){
-d.publish(this.id+"/rotator/update",[_12,this,_13||{}]);
-},_resetWaitForEvent:function(){
-if(this.wfe){
-d.unsubscribe(this.wfe);
-this.wfe=null;
-}
-},control:function(_14){
-var _15=d._toArray(arguments),_16=this;
-_15.shift();
-_16._resetWaitForEvent();
-if(_16[_14]){
-var def=_16[_14].apply(_16,_15);
-if(def){
-def.addCallback(function(){
-_16.onUpdate(_14);
-});
-}
-_16.onManualChange(_14);
-}else{
-console.warn(_16.declaredClass," - Unsupported action \"",_14,"\".");
-}
-},onManualChange:function(){
-}});
-d.setObject(_1,function(_17){
-return new d._Animation({play:function(){
-d.style(_17.current.node,_3,_4);
-d.style(_17.next.node,_3,"");
-this._fire("onEnd");
-}});
-});
-})(dojo);
-}
+
+	// build friendly strings
+	var _defaultTransition = "dojox.widget.rotator.swap", // please do NOT change
+		_defaultTransitionDuration = 500,
+		_displayStr = "display",
+		_noneStr = "none",
+		_zIndex = "zIndex";
+
+	d.declare("dojox.widget.Rotator", null, {
+		//	summary:
+		//		A widget for rotating through child nodes using transitions.
+		//
+		//	description:
+		//		A small, fast, extensible, awesome rotator that cycles, with transitions,
+		//		through panes (child nodes) displaying only one at a time and ties into
+		//		controllers used to change state.
+		//
+		//		The Rotator does not rely on dijit.  It is designed to be as lightweight
+		//		as possible.  Controllers and transitions have been externalized
+		//		so builds can be as optimized with only the components you want to use.
+		//
+		//		For best results, each rotator pane should be the same height and width as
+		//		the Rotator container node and consider setting overflow to hidden.
+		//		While the Rotator will accept any DOM node for a rotator pane, a block
+		//		element or element with display:block is recommended.
+		//
+		//		Note: When the Rotator begins, it does not transition the first pane.
+		//
+		//	subscribed topics:
+		//		[id]/rotator/control - Controls the Rotator
+		//			Parameters:
+		//				/*string*/ action        - The name of a method of the Rotator to run
+		//				/*anything?*/ args       - One or more arguments to pass to the action
+		//
+		//	published topics:
+		//		[id]/rotator/update - Notifies controllers that a pane or state has changed.
+		//			Parameters:
+		//				/*string*/ type          - the type of notification
+		//				/*dojox.widget.Rotator*/ rotator
+		//										 - the rotator instance
+		//				/*object?*/ params		 - params
+		//
+		//	declarative dojo/method events (per pane):
+		//		onBeforeIn  - Fired before the transition in starts.
+		//		onAfterIn   - Fired after the transition in ends.
+		//		onBeforeOut - Fired before the transition out starts.
+		//		onAfterOut  - Fired after the transition out ends.
+		//
+		//	example:
+		//	|	<div dojoType="dojox.widget.Rotator">
+		//	|		<div>Pane 1!</div>
+		//	|		<div>Pane 2!</div>
+		//	|	</div>
+		//
+		//	example:
+		//	|	<script type="text/javascript">
+		//	|		dojo.require("dojox.widget.rotator.Fade");
+		//	|	</script>
+		//	|	<div dojoType="dojox.widget.Rotator" transition="dojox.widget.rotator.crossFade">
+		//	|		<div>Pane 1!</div>
+		//	|		<div>Pane 2!</div>
+		//	|	</div>
+
+		//	transition: string
+		//		The name of a function that is passed two panes nodes and a duration,
+		//		then returns a dojo.Animation object. The default value is
+		//		"dojox.widget.rotator.swap".
+		transition: _defaultTransition,
+
+		//	transitionParams: string
+		//		Parameters for the transition. The string is read in and eval'd as an
+		//		object.  If the duration is absent, the default value will be used.
+		transitionParams: "duration:" + _defaultTransitionDuration,
+
+		//	panes: array
+		//		Array of panes to be created in the Rotator. Each array element
+		//		will be passed as attributes to a dojo.create() call.
+		panes: null,
+
+		constructor: function(/*Object*/params, /*DomNode|string*/node){
+			//	summary:
+			//		Initializes the panes and events.
+			d.mixin(this, params);
+
+			var _t = this,
+				t = _t.transition,
+				tt = _t._transitions = {},
+				idm = _t._idMap = {},
+				tp = _t.transitionParams = eval("({ " + _t.transitionParams + " })"),
+				node = _t._domNode = dojo.byId(node),
+				cb = _t._domNodeContentBox = d.contentBox(node), // we are going to assume the rotator will not be changing size
+
+				// default styles to apply to all the container node and rotator's panes
+				p = {
+					left: 0,
+					top: 0
+				},
+
+				warn = function(bt, dt){
+					console.warn(_t.declaredClass, ' - Unable to find transition "', bt, '", defaulting to "', dt, '".');
+				};
+
+			// if we don't have an id, then generate one
+			_t.id = node.id || (new Date()).getTime();
+
+			// force the rotator DOM node to a relative position and attach the container node to it
+			if(d.style(node, "position") == "static"){
+				d.style(node, "position", "relative");
+			}
+
+			// create our object for caching transition objects
+			tt[t] = d.getObject(t);
+			if(!tt[t]){
+				warn(t, _defaultTransition);
+				tt[_t.transition = _defaultTransition] = d.getObject(_defaultTransition);
+			}
+
+			// clean up the transition params
+			if(!tp.duration){
+				tp.duration = _defaultTransitionDuration;
+			}
+
+			// if there are any panes being passed in, add them to this node
+			d.forEach(_t.panes, function(p){
+				d.create("div", p, node);
+			});
+
+			// zero out our panes array to store the real pane instance
+			var pp = _t.panes = [];
+
+			// find and initialize the panes
+			d.query(">", node).forEach(function(n, i){
+				var q = { node: n, idx: i, params: d.mixin({}, tp, eval("({ " + (d.attr(n, "transitionParams") || "") + " })")) },
+					r = q.trans = d.attr(n, "transition") || _t.transition;
+
+				// cache each pane's title, duration, and waitForEvent attributes
+				d.forEach(["id", "title", "duration", "waitForEvent"], function(a){
+					q[a] = d.attr(n, a);
+				});
+
+				if(q.id){
+					idm[q.id] = i;
+				}
+
+				// cache the transition function
+				if(!tt[r] && !(tt[r] = d.getObject(r))){
+					warn(r, q.trans = _t.transition);
+				}
+
+				p.position = "absolute";
+				p.display = _noneStr;
+
+				// find the selected pane and initialize styles
+				if(_t.idx == null || d.attr(n, "selected")){
+					if(_t.idx != null){
+						d.style(pp[_t.idx].node, _displayStr, _noneStr);
+					}
+					_t.idx = i;
+					p.display = "";
+				}
+				d.style(n, p);
+
+				// check for any declarative script blocks
+				d.query("> script[type^='dojo/method']", n).orphan().forEach(function(s){
+					var e = d.attr(s, "event");
+					if(e){
+						q[e] = d.parser._functionFromScript(s);
+					}
+				});
+
+				// add this pane to the array of panes
+				pp.push(q);
+			});
+
+			_t._controlSub = d.subscribe(_t.id + "/rotator/control", _t, "control");
+		},
+
+		destroy: function(){
+			//	summary:
+			//		Destroys the Rotator and its DOM node.
+			d.forEach([this._controlSub, this.wfe], d.unsubscribe);
+			d.destroy(this._domNode);
+		},
+
+		next: function(){
+			//	summary:
+			//		Transitions the Rotator to the next pane.
+			return this.go(this.idx + 1);
+		},
+
+		prev: function(){
+			//	summary:
+			//		Transitions the Rotator to the previous pane.
+			return this.go(this.idx - 1);
+		},
+
+		go: function(/*int|string?*/p){
+			//	summary:
+			//		Transitions the Rotator to the specified pane index.
+			var _t = this,
+				i = _t.idx,
+				pp = _t.panes,
+				len = pp.length,
+				idm = _t._idMap[p];
+
+			// we gotta move on, so if the current pane is waiting for an event, just
+			// ignore it and clean up
+			_t._resetWaitForEvent();
+
+			// determine the next index and set it to idx for the next go to
+			p = idm != null ? idm : (p || 0);
+			p = p < len ? (p < 0 ? len-1 : p) : 0;
+
+			// if we're already on the requested pane or still transitioning, then return
+			if(p == i || _t.anim){
+				return null;
+			}
+
+			// get the current and next panes
+			var current = pp[i],
+				next = pp[p];
+
+			// adjust the zIndexes so our animations look good... this must be done before
+			// the animation is created so the animation could override it if necessary
+			d.style(current.node, _zIndex, 2);
+			d.style(next.node, _zIndex, 1);
+
+			// info object passed to animations and onIn/Out events
+			var info = {
+					current: current,
+					next: next,
+					rotator: _t
+				},
+
+				// get the transition
+				anim = _t.anim = _t._transitions[next.trans](d.mixin({
+					rotatorBox: _t._domNodeContentBox
+				}, info, next.params));
+
+			if(anim){
+				// create the deferred that we'll be returning
+				var def = new d.Deferred(),
+					ev = next.waitForEvent,
+
+					h = d.connect(anim, "onEnd", function(){
+						// reset the node styles
+						d.style(current.node, {
+							display: _noneStr,
+							left: 0,
+							opacity: 1,
+							top: 0,
+							zIndex: 0
+						});
+
+						d.disconnect(h);
+						_t.anim = null;
+						_t.idx = p;
+
+						// fire end events
+						if(current.onAfterOut){ current.onAfterOut(info); }
+						if(next.onAfterIn){ next.onAfterIn(info); }
+
+						_t.onUpdate("onAfterTransition");
+
+						if(!ev){
+							// if there is a previous waitForEvent, then we need to make
+							// sure it gets unsubscribed
+							_t._resetWaitForEvent();
+
+							// animation is all done, fire the deferred callback.
+							def.callback();
+						}
+					});
+
+				// if we're waiting for an event, subscribe to it so we know when to continue
+				_t.wfe = ev ? d.subscribe(ev, function(){
+					_t._resetWaitForEvent();
+					def.callback(true);
+				}) : null;
+
+				_t.onUpdate("onBeforeTransition");
+
+				// fire start events
+				if(current.onBeforeOut){ current.onBeforeOut(info); }
+				if(next.onBeforeIn){ next.onBeforeIn(info); }
+
+				// play the animation
+				anim.play();
+
+				// return the deferred
+				return def; /*Deferred*/
+			}
+		},
+
+		onUpdate: function(/*string*/type, /*object?*/params){
+			//	summary:
+			//		Send a notification to all controllers with the state of the rotator.
+			d.publish(this.id + "/rotator/update", [type, this, params || {}]);
+		},
+
+		_resetWaitForEvent: function(){
+			//	summary:
+			//		If there is a waitForEvent pending, kill it.
+			if(this.wfe){
+				d.unsubscribe(this.wfe);
+				this.wfe = null;
+			}
+		},
+
+		control: function(/*string*/action){
+			//	summary:
+			//		Dispatches an action, first to this engine, then to the Rotator.
+			var args = d._toArray(arguments),
+				_t = this;
+			args.shift();
+
+			_t._resetWaitForEvent();
+
+			if(_t[action]){
+				// action exists, so call it and fire deferred if applicable
+				var def = _t[action].apply(_t, args);
+				if(def){
+					def.addCallback(function(){
+						_t.onUpdate(action);
+					});
+				}
+
+				// since this action was triggered by a controller, we assume this was a
+				// manual action, so check if we should pause
+				_t.onManualChange(action);
+			}else{
+				console.warn(_t.declaredClass, ' - Unsupported action "', action, '".');
+			}
+		},
+
+		resize: function(/*int*/width, /*int*/height){
+			var b = this._domNodeContentBox = { w: width, h: height };
+			d.contentBox(this._domNode, b);
+			d.forEach(this.panes, function(p){ d.contentBox(p.node, b); });
+		},
+
+		onManualChange: function(){
+			//	summary:
+			//		Stub function that can be overriden or connected to.
+		}
+	});
+
+	d.setObject(_defaultTransition, function(/*Object*/args){
+		//	summary:
+		//		The default rotator transition which swaps two panes.
+		return new d._Animation({ // dojo.Animation
+			play: function(){
+				d.style(args.current.node, _displayStr, _noneStr);
+				d.style(args.next.node, _displayStr, "");
+				this._fire("onEnd");
+			}
+		});
+	});
+
+})(dojo);
\ No newline at end of file
diff --git a/dojox/widget/SortList.js b/dojox/widget/SortList.js
index ebc3c66..25b5475 100644
--- a/dojox/widget/SortList.js
+++ b/dojox/widget/SortList.js
@@ -1,86 +1,150 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.SortList"]){
-dojo._hasResource["dojox.widget.SortList"]=true;
 dojo.provide("dojox.widget.SortList");
-dojo.experimental("dojox.widget.SortList");
+dojo.experimental("dojox.widget.SortList"); // level: prototype, designed for dijit.chat.demo
+
 dojo.require("dijit.layout._LayoutWidget");
 dojo.require("dijit._Templated");
-dojo.declare("dojox.widget.SortList",[dijit.layout._LayoutWidget,dijit._Templated],{title:"",heading:"",descending:true,selected:null,sortable:true,store:"",key:"name",baseClass:"dojoxSortList",templateString:dojo.cache("dojox.widget","SortList/SortList.html","<div class=\"sortList\" id=\"${id}\">\n\t\t<div class=\"sortListTitle\" dojoAttachPoint=\"titleNode\">\n\t\t<div class=\"dijitInline sortListIcon\"> </div>\n\t\t<span dojoAttachPoint=\"focusNode\">${title}</span>\n\t\t</div> [...]
-dojo.create("li",{innerHTML:this.store.getValue(_1,this.key).replace(/</g,"<")},this.containerNode);
-},postCreate:function(){
-if(this.store){
-this.store=dojo.getObject(this.store);
-var _2={onItem:dojo.hitch(this,"_addItem"),onComplete:dojo.hitch(this,"onSort")};
-this.store.fetch(_2);
-}else{
-this.onSort();
-}
-this.inherited(arguments);
-},startup:function(){
-this.inherited(arguments);
-if(this.heading){
-this.setTitle(this.heading);
-this.title=this.heading;
-}
-setTimeout(dojo.hitch(this,"resize"),5);
-if(this.sortable){
-this.connect(this.titleNode,"onclick","onSort");
-}
-},resize:function(){
-this.inherited(arguments);
-var _3=((this._contentBox.h)-(dojo.style(this.titleNode,"height")))-10;
-this.bodyWrapper.style.height=Math.abs(_3)+"px";
-},onSort:function(e){
-var _4=dojo.query("li",this.domNode);
-if(this.sortable){
-this.descending=!this.descending;
-dojo.addClass(this.titleNode,((this.descending)?"sortListDesc":"sortListAsc"));
-dojo.removeClass(this.titleNode,((this.descending)?"sortListAsc":"sortListDesc"));
-_4.sort(this._sorter);
-if(this.descending){
-_4.reverse();
-}
-}
-var i=0;
-dojo.forEach(_4,function(_5){
-dojo[(i++)%2===0?"addClass":"removeClass"](_5,"sortListItemOdd");
-this.containerNode.appendChild(_5);
-},this);
-},_set:function(e){
-if(e.target!==this.bodyWrapper){
-dojo.addClass(e.target,"sortListItemHover");
-}
-},_unset:function(e){
-dojo.removeClass(e.target,"sortListItemHover");
-},_handleClick:function(e){
-dojo.toggleClass(e.target,"sortListItemSelected");
-e.target.focus();
-this._updateValues(e.target.innerHTML);
-},_updateValues:function(){
-this._selected=dojo.query("li.sortListItemSelected",this.containerNode);
-this.selected=[];
-dojo.forEach(this._selected,function(_6){
-this.selected.push(_6.innerHTML);
-},this);
-this.onChanged(arguments);
-},_sorter:function(a,b){
-var _7=a.innerHTML;
-var _8=b.innerHTML;
-if(_7>_8){
-return 1;
-}
-if(_7<_8){
-return -1;
-}
-return 0;
-},setTitle:function(_9){
-this.focusNode.innerHTML=this.title=_9;
-},onChanged:function(){
-}});
-}
+
+dojo.declare("dojox.widget.SortList",
+	[dijit.layout._LayoutWidget, dijit._Templated],
+	{
+	// summary: A sortable unordered-list with a fixed header for use in dijit.demos.chat
+	//		for demonstration purposes only for now. feel free to make API suggestions
+	//		or fixes. 
+	//
+	// title: String 
+	//		The title in the header
+	title: "",
+	
+	// heading: String
+	//		In the event a parent container is expecting a title="" attribute, set it for the parent 
+	//		via title, and the title of this widget via heading="" ... assuming you want different 
+	//		titles for each. eg: TabContainer, AccordionContainer, etc. 
+	heading: "",
+
+	// descending: Boolean
+	//		Toggle sort order based on this value. 
+	descending: true,
+
+	// selected: Array
+	//		A list of the selected <li> nodes at any given time.
+	selected: null,
+
+	// sortable: Boolean
+	//	toggle to enable/disable sorting
+	sortable: true,
+
+	// FIXME: this is really simple store support
+	store: "",
+	key: "name",
+	
+	baseClass: "dojoxSortList",
+
+	templateString: dojo.cache("dojox.widget","SortList/SortList.html"),
+
+	_addItem: function(item){
+		dojo.create("li", {
+			innerHTML: this.store.getValue(item, this.key).replace(/</g, "<")
+		}, this.containerNode);
+	},
+
+	postCreate: function(){
+		if(this.store){
+			this.store = dojo.getObject(this.store);
+			var props = {
+				onItem: dojo.hitch(this, "_addItem"),
+				onComplete: dojo.hitch(this, "onSort")
+			};
+			this.store.fetch(props);	
+		}else{ this.onSort(); }
+		this.inherited(arguments);
+	},
+
+	startup: function(){
+		this.inherited(arguments);
+		if(this.heading){ 
+			this.setTitle(this.heading); 
+			this.title = this.heading; 
+		}
+		// we cheat, and give the browser just enough time so we know our height
+		setTimeout(dojo.hitch(this,"resize"), 5);
+		if(this.sortable){ this.connect(this.titleNode,"onclick", "onSort"); }
+	},
+
+	resize: function(){
+		// summary: do our additional calculations when resize() is called by or in a parent
+		this.inherited(arguments);
+		// FIXME: 
+		// the 10 comes from the difference between the contentBox and calculated height
+		// because of badding and border extents. this shouldn't be done this way, a theme change will 
+		// break it: but we also don't want to run getComputedStyle or dojo.coords() every time resize() 
+		// is fired.
+		var offset = ((this._contentBox.h) - (dojo.style(this.titleNode,"height")))-10;
+		this.bodyWrapper.style.height = Math.abs(offset) + "px"; 
+	},
+	
+	onSort: function(/* Event */e){
+		// summary: sort the data, and style the nodes.
+
+		var arr = dojo.query("li",this.domNode);
+		if (this.sortable){
+			this.descending = !this.descending;
+			dojo.addClass(this.titleNode,((this.descending)?"sortListDesc":"sortListAsc"));
+			dojo.removeClass(this.titleNode,((this.descending)?"sortListAsc":"sortListDesc"));
+			arr.sort(this._sorter);
+			if(this.descending){ arr.reverse(); }
+		}
+		var i=0;
+		dojo.forEach(arr,function(item){
+			dojo[(i++) % 2 === 0 ? "addClass" : "removeClass"](item,"sortListItemOdd");
+			this.containerNode.appendChild(item); 
+		},this);
+	},
+	
+	_set: function(/* Event */e){
+		// summary: set hover state 
+		if(e.target !== this.bodyWrapper){
+			dojo.addClass(e.target,"sortListItemHover");
+		}
+	},
+
+	_unset: function(/* Event */e){
+		// summary: remove hover state (FIXME: combine with _set?) 
+		dojo.removeClass(e.target,"sortListItemHover"); 
+	},
+
+	_handleClick: function(/* Event */e){
+		// summary: click listener for data portion of widget. toggle selected state
+		//	of node, and update this.selected array accordingly
+		dojo.toggleClass(e.target,"sortListItemSelected");
+		e.target.focus();
+		this._updateValues(e.target.innerHTML);
+	},
+
+	_updateValues: function(){
+		this._selected = dojo.query("li.sortListItemSelected", this.containerNode);
+		this.selected = [];
+		dojo.forEach(this._selected, function(node){
+			this.selected.push(node.innerHTML);
+		}, this);
+		this.onChanged(arguments);
+	},
+
+	_sorter: function(a,b){
+		// summary: a basic sort function, use query sort, or keep this?
+		var aStr = a.innerHTML;
+		var bStr = b.innerHTML;
+		if(aStr>bStr){ return 1; }
+		if(aStr<bStr){ return -1; }
+		return 0;
+	},
+
+	setTitle: function(/* String */title){
+		// summary: Sets the widget title to a String
+		this.focusNode.innerHTML = this.title = title;
+	},
+
+	onChanged: function(){
+		// summary: stub function, passes the last changed item, and is fired after current state 
+	}
+	
+});
diff --git a/dojox/widget/SortList/SortList.css b/dojox/widget/SortList/SortList.css
index e15d52a..a3eb54e 100644
--- a/dojox/widget/SortList/SortList.css
+++ b/dojox/widget/SortList/SortList.css
@@ -1,4 +1,5 @@
 .sortListBody { margin:0; padding:0; background:#fff; }
+
 .soria .sortListBody li,
 .tundra .sortListBody li {
 	border-bottom:1px solid #b7b7b7;
@@ -8,17 +9,23 @@
 	cursor:pointer; 
 	padding:4px 4px 3px 4px;
 }
+
 .sortList { height:100%; width:100%; }
+
+/* for nested layout elements */
 .dijitBorderContainer .dojoxSortList { width: auto; height: auto;}
+
 .sortListBodyWrapper { 
 	border:1px solid #b7b7b7; 
 	overflow:auto; 
 	height:100%; 
 	cursor:pointer;
 } 
+
 .soria .sortListBodyWrapper {
 	border:1px solid #333; 
 }
+
 .soria .sortListItemOdd,
 .tundra .sortListItemOdd { background:#f2f5f9; }
 .tundra .sortListTitle {
@@ -34,8 +41,10 @@
 	font-weight:bold;
 	color:#fff; 
 }
+
 .sortListItemSelected { background:#b7cdee !important; }
 .sortListItemHover { background:#ff6 !important; }
+
 .soria .sortListIcon,
 .tundra .sortListIcon { 
 	float:right;
@@ -48,10 +57,12 @@
 .tundra .sortListAsc .sortListIcon {
 	background-position: -21px center;
 }
+
 .soria .sortListDesc .sortListIcon,
 .soria .sortListAsc .sortListIcon {
 	background:url('../../../dijit/themes/soria/images/spriteRoundedIconsSmall.png') no-repeat -15px top;
 }
+
 .soria .sortListDesc .sortListIcon {
 	background-position:-45px 0px; 
 }
diff --git a/dojox/widget/Standby.js b/dojox/widget/Standby.js
old mode 100644
new mode 100755
index fa53cdb..4432115
--- a/dojox/widget/Standby.js
+++ b/dojox/widget/Standby.js
@@ -1,328 +1,736 @@
-/*
-	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
-*/
+dojo.provide("dojox.widget.Standby");
 
+dojo.require("dojo.window");
+dojo.require("dojo.fx");
 
-if(!dojo._hasResource["dojox.widget.Standby"]){
-dojo._hasResource["dojox.widget.Standby"]=true;
-dojo.provide("dojox.widget.Standby");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.require("dojo.fx");
+
 dojo.experimental("dojox.widget.Standby");
-dojo.declare("dojox.widget.Standby",[dijit._Widget,dijit._Templated],{templateString:"<div>"+"<div style=\"display: none; opacity: 0; z-index: 9999; "+"position: absolute; cursor:wait;\" dojoAttachPoint=\"_underlayNode\"></div>"+"<img src=\"${image}\" style=\"opacity: 0; display: none; z-index: -10000; "+"position: absolute; top: 0px; left: 0px; cursor:wait;\" "+"dojoAttachPoint=\"_imageNode\">"+"<div style=\"opacity: 0; display: none; z-index: -10000; position: absolute; "+"top: 0px;\"  [...]
-if(!this._started){
-if(typeof this.target==="string"){
-var w=dijit.byId(this.target);
-if(w){
-this.target=w.domNode;
-}else{
-this.target=dojo.byId(this.target);
-}
-}
-if(this.text){
-this._textNode.innerHTML=this.text;
-}
-if(this.centerIndicator==="image"){
-this._centerNode=this._imageNode;
-dojo.attr(this._imageNode,"src",this.image);
-dojo.attr(this._imageNode,"alt",this.imageText);
-}else{
-this._centerNode=this._textNode;
-}
-dojo.style(this._underlayNode,{display:"none",backgroundColor:this.color});
-dojo.style(this._centerNode,"display","none");
-this.connect(this._underlayNode,"onclick","_ignore");
-if(this.domNode.parentNode&&this.domNode.parentNode!=dojo.body()){
-dojo.body().appendChild(this.domNode);
-}
-if(dojo.isIE==7){
-this._ieFixNode=dojo.doc.createElement("div");
-dojo.style(this._ieFixNode,{opacity:"0",zIndex:"-1000",position:"absolute",top:"-1000px"});
-dojo.body().appendChild(this._ieFixNode);
-}
-}
-},show:function(){
-if(!this._displayed){
-this._displayed=true;
-this._size();
-this._disableOverflow();
-this._fadeIn();
-}
-},hide:function(){
-if(this._displayed){
-this._size();
-this._fadeOut();
-this._displayed=false;
-if(this._resizeCheck!==null){
-clearInterval(this._resizeCheck);
-this._resizeCheck=null;
-}
-}
-},isVisible:function(){
-return this._displayed;
-},onShow:function(){
-},onHide:function(){
-},uninitialize:function(){
-this._displayed=false;
-if(this._resizeCheck){
-clearInterval(this._resizeCheck);
-}
-dojo.style(this._centerNode,"display","none");
-dojo.style(this._underlayNode,"display","none");
-if(dojo.isIE==7){
-dojo.body().removeChild(this._ieFixNode);
-delete this._ieFixNode;
-}
-this.target=null;
-this._imageNode=null;
-this._textNode=null;
-this._centerNode=null;
-this.inherited(arguments);
-},_size:function(){
-if(this._displayed){
-var _2=dojo.attr(dojo.body(),"dir");
-if(_2){
-_2=_2.toLowerCase();
-}
-var _3;
-var _4=this._scrollerWidths();
-var _5=this.target;
-var _6=dojo.style(this._centerNode,"display");
-dojo.style(this._centerNode,"display","block");
-var _7=dojo.position(_5,true);
-if(_5===dojo.body()||_5===dojo.doc){
-_7=dijit.getViewport();
-_7.x=_7.l;
-_7.y=_7.t;
-}
-var _8=dojo.marginBox(this._centerNode);
-dojo.style(this._centerNode,"display",_6);
-if(this._ieFixNode){
-_3=-this._ieFixNode.offsetTop/1000;
-_7.x=Math.floor((_7.x+0.9)/_3);
-_7.y=Math.floor((_7.y+0.9)/_3);
-_7.w=Math.floor((_7.w+0.9)/_3);
-_7.h=Math.floor((_7.h+0.9)/_3);
-}
-var zi=dojo.style(_5,"zIndex");
-var _9=zi;
-var _a=zi;
-if(this.zIndex==="auto"){
-if(zi!="auto"){
-_9=parseInt(_9,10)+1;
-_a=parseInt(_a,10)+2;
-}
-}else{
-_9=parseInt(this.zIndex,10)+1;
-_a=parseInt(this.zIndex,10)+2;
-}
-dojo.style(this._centerNode,"zIndex",_a);
-dojo.style(this._underlayNode,"zIndex",_9);
-var pn=_5.parentNode;
-if(pn&&pn!==dojo.body()&&_5!==dojo.body()&&_5!==dojo.doc){
-var _b=_7.h;
-var _c=_7.w;
-var _d=dojo.position(pn,true);
-if(this._ieFixNode){
-_3=-this._ieFixNode.offsetTop/1000;
-_d.x=Math.floor((_d.x+0.9)/_3);
-_d.y=Math.floor((_d.y+0.9)/_3);
-_d.w=Math.floor((_d.w+0.9)/_3);
-_d.h=Math.floor((_d.h+0.9)/_3);
-}
-_d.w-=pn.scrollHeight>pn.clientHeight&&pn.clientHeight>0?_4.v:0;
-_d.h-=pn.scrollWidth>pn.clientWidth&&pn.clientWidth>0?_4.h:0;
-if(_2==="rtl"){
-if(dojo.isOpera){
-_7.x+=pn.scrollHeight>pn.clientHeight&&pn.clientHeight>0?_4.v:0;
-_d.x+=pn.scrollHeight>pn.clientHeight&&pn.clientHeight>0?_4.v:0;
-}else{
-if(dojo.isIE){
-_d.x+=pn.scrollHeight>pn.clientHeight&&pn.clientHeight>0?_4.v:0;
-}else{
-if(dojo.isWebKit){
-}
-}
-}
-}
-if(_d.w<_7.w){
-_7.w=_7.w-_d.w;
-}
-if(_d.h<_7.h){
-_7.h=_7.h-_d.h;
-}
-var _e=_d.y;
-var _f=_d.y+_d.h;
-var _10=_7.y;
-var _11=_7.y+_b;
-var _12=_d.x;
-var _13=_d.x+_d.w;
-var _14=_7.x;
-var _15=_7.x+_c;
-var _16;
-if(_11>_e&&_10<_e){
-_7.y=_d.y;
-_16=_e-_10;
-var _17=_b-_16;
-if(_17<_d.h){
-_7.h=_17;
-}else{
-_7.h-=2*(pn.scrollWidth>pn.clientWidth&&pn.clientWidth>0?_4.h:0);
-}
-}else{
-if(_10<_f&&_11>_f){
-_7.h=_f-_10;
-}else{
-if(_11<=_e||_10>=_f){
-_7.h=0;
-}
-}
-}
-if(_15>_12&&_14<_12){
-_7.x=_d.x;
-_16=_12-_14;
-var _18=_c-_16;
-if(_18<_d.w){
-_7.w=_18;
-}else{
-_7.w-=2*(pn.scrollHeight>pn.clientHeight&&pn.clientHeight>0?_4.w:0);
-}
-}else{
-if(_14<_13&&_15>_13){
-_7.w=_13-_14;
-}else{
-if(_15<=_12||_14>=_13){
-_7.w=0;
-}
-}
-}
-}
-if(_7.h>0&&_7.w>0){
-dojo.style(this._underlayNode,{display:"block",width:_7.w+"px",height:_7.h+"px",top:_7.y+"px",left:_7.x+"px"});
-var _19=["borderRadius","borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius"];
-this._cloneStyles(_19);
-if(!dojo.isIE){
-_19=["MozBorderRadius","MozBorderRadiusTopleft","MozBorderRadiusTopright","MozBorderRadiusBottomleft","MozBorderRadiusBottomright","WebkitBorderRadius","WebkitBorderTopLeftRadius","WebkitBorderTopRightRadius","WebkitBorderBottomLeftRadius","WebkitBorderBottomRightRadius"];
-this._cloneStyles(_19,this);
-}
-var _1a=(_7.h/2)-(_8.h/2);
-var _1b=(_7.w/2)-(_8.w/2);
-if(_7.h>=_8.h&&_7.w>=_8.w){
-dojo.style(this._centerNode,{top:(_1a+_7.y)+"px",left:(_1b+_7.x)+"px",display:"block"});
-}else{
-dojo.style(this._centerNode,"display","none");
-}
-}else{
-dojo.style(this._underlayNode,"display","none");
-dojo.style(this._centerNode,"display","none");
-}
-if(this._resizeCheck===null){
-var _1c=this;
-this._resizeCheck=setInterval(function(){
-_1c._size();
-},100);
-}
-}
-},_cloneStyles:function(_1d){
-dojo.forEach(_1d,function(_1e){
-dojo.style(this._underlayNode,_1e,dojo.style(this.target,_1e));
-},this);
-},_fadeIn:function(){
-var _1f=this;
-var _20=dojo.animateProperty({duration:_1f.duration,node:_1f._underlayNode,properties:{opacity:{start:0,end:0.75}}});
-var _21=dojo.animateProperty({duration:_1f.duration,node:_1f._centerNode,properties:{opacity:{start:0,end:1}},onEnd:function(){
-_1f.onShow();
-}});
-var _22=dojo.fx.combine([_20,_21]);
-_22.play();
-},_fadeOut:function(){
-var _23=this;
-var _24=dojo.animateProperty({duration:_23.duration,node:_23._underlayNode,properties:{opacity:{start:0.75,end:0}},onEnd:function(){
-dojo.style(_23._underlayNode,{"display":"none","zIndex":"-1000"});
-}});
-var _25=dojo.animateProperty({duration:_23.duration,node:_23._centerNode,properties:{opacity:{start:1,end:0}},onEnd:function(){
-dojo.style(_23._centerNode,{"display":"none","zIndex":"-1000"});
-_23.onHide();
-_23._enableOverflow();
-}});
-var _26=dojo.fx.combine([_24,_25]);
-_26.play();
-},_ignore:function(_27){
-if(_27){
-dojo.stopEvent(_27);
-}
-},_scrollerWidths:function(){
-var div=dojo.doc.createElement("div");
-dojo.style(div,{position:"absolute",opacity:0,overflow:"hidden",width:"50px",height:"50px",zIndex:"-100",top:"-200px",left:"-200px",padding:"0px",margin:"0px"});
-var _28=dojo.doc.createElement("div");
-dojo.style(_28,{width:"200px",height:"10px"});
-div.appendChild(_28);
-dojo.body().appendChild(div);
-var b=dojo.contentBox(div);
-dojo.style(div,"overflow","scroll");
-var a=dojo.contentBox(div);
-dojo.body().removeChild(div);
-return {v:b.w-a.w,h:b.h-a.h};
-},_setTextAttr:function(_29){
-this._textNode.innerHTML=_29;
-this.text=_29;
-},_setColorAttr:function(c){
-dojo.style(this._underlayNode,"backgroundColor",c);
-this.color=c;
-},_setImageTextAttr:function(_2a){
-dojo.attr(this._imageNode,"alt",_2a);
-this.imageText=_2a;
-},_setImageAttr:function(url){
-dojo.attr(this._imageNode,"src",url);
-this.image=url;
-},_setCenterIndicatorAttr:function(_2b){
-this.centerIndicator=_2b;
-if(_2b==="image"){
-this._centerNode=this._imageNode;
-dojo.style(this._textNode,"display","none");
-}else{
-this._centerNode=this._textNode;
-dojo.style(this._imageNode,"display","none");
-}
-},_disableOverflow:function(){
-if(this.target===dojo.body()||this.target===dojo.doc){
-this._overflowDisabled=true;
-var _2c=dojo.body();
-if(_2c.style&&_2c.style.overflow){
-this._oldOverflow=dojo.style(_2c,"overflow");
-}else{
-this._oldOverflow="";
-}
-if(dojo.isIE&&!dojo.isQuirks){
-if(_2c.parentNode&&_2c.parentNode.style&&_2c.parentNode.style.overflow){
-this._oldBodyParentOverflow=_2c.parentNode.style.overflow;
-}else{
-this._oldBodyParentOverflow="scroll";
-}
-dojo.style(_2c.parentNode,"overflow","hidden");
-}
-dojo.style(_2c,"overflow","hidden");
-}
-},_enableOverflow:function(){
-if(this._overflowDisabled){
-delete this._overflowDisabled;
-var _2d=dojo.body();
-if(dojo.isIE&&!dojo.isQuirks){
-_2d.parentNode.style.overflow=this._oldBodyParentOverflow;
-delete this._oldBodyParentOverflow;
-}
-dojo.style(_2d,"overflow",this._oldOverflow);
-if(dojo.isWebKit){
-var div=dojo.create("div",{style:{height:"2px"}});
-_2d.appendChild(div);
-setTimeout(function(){
-_2d.removeChild(div);
-},0);
-}
-delete this._oldOverflow;
-}
-}});
-}
+
+dojo.declare("dojox.widget.Standby",[dijit._Widget, dijit._Templated],{
+	// summary:
+	//		A widget designed to act as a Standby/Busy/Disable/Blocking widget to indicate a 
+	//		particular DOM node is processing and cannot be clicked on at this time.
+	//		This widget uses absolute positioning to apply the overlay and image.
+	// 
+	// image:	
+	//		A URL to an image to center within the blocking overlay.  
+	//		The default is a basic spinner.
+	//
+	// imageText:
+	//		Text to set on the ALT tag of the image.  
+	//		The default is 'Please wait...'
+	//
+	// text:
+	//		Text to display in the center instead of an image.
+	//		Defaults to 'Please Wait...'
+	//
+	// centerIndicator:
+	//		Which to use as the center info, the text or the image.
+	//		Defaults to image.
+	//
+	// color:
+	//		The color to use for the translucent overlay.  
+	//		Text string such as: darkblue, #FE02FD, etc.
+	//
+	// duration:
+	//		How long the fade in and out effects should run in milliseconds.
+	//		Default is 500ms
+	//
+	// zIndex:
+	//		Control that lets you specify if the zIndex for the overlay
+	//		should be auto-computed based off parent zIndex, or should be set
+	//		to a particular value.  This is useful when you want to overlay 
+	//		things in digit.Dialogs, you can specify a base zIndex to append from.
+	//		Default is 'auto'.
+
+	// templateString: [protected] String
+	//		The template string defining out the basics of the widget.  No need for an external
+	//		file.
+	templateString: 
+		"<div>" +
+			"<div style=\"display: none; opacity: 0; z-index: 9999; " +
+				"position: absolute; cursor:wait;\" dojoAttachPoint=\"_underlayNode\"></div>" +
+			"<img src=\"${image}\" style=\"opacity: 0; display: none; z-index: -10000; " +
+				"position: absolute; top: 0px; left: 0px; cursor:wait;\" "+
+				"dojoAttachPoint=\"_imageNode\">" +
+			"<div style=\"opacity: 0; display: none; z-index: -10000; position: absolute; " +
+				"top: 0px;\" dojoAttachPoint=\"_textNode\"></div>" +
+		"</div>",
+
+	// _underlayNode: [private] DOMNode
+	//		The node that is the translucent underlay for the 
+	//		image that blocks access to the target.
+	_underlayNode: null,	
+
+	// _imageNode: [private] DOMNode
+	//		The image node where we attach and define the image to display.
+	_imageNode: null,
+
+	// _textNode: [private] DOMNode
+	//		The div to attach text/HTML in the overlay center item.
+	_textNode: null,
+
+	// _centerNode: [private] DOMNode
+	//		Which node to use as the center node, the image or the text node.
+	_centerNode: null,
+
+	// image: String
+	//		The URL to the image to center in the overlay.
+	image: dojo.moduleUrl("dojox", "widget/Standby/images/loading.gif").toString(), 
+
+	// imageText: String
+	//		Text for the ALT tag.
+	imageText: "Please Wait...", 
+
+	// text: String
+	//		Text/HTML to display in the center of the overlay
+	//		This is used if image center is disabled.
+	text: "Please wait...",
+
+	// centerIndicator: String
+	//		Property to define if the image and its alt text should be used, or
+	//		a simple Text/HTML node should be used.  Allowable values are 'image'
+	//		and 'text'.
+	//		Default is 'image'.
+	centerIndicator: "image",
+
+	// _displayed: [private] Boolean
+	//		Flag to indicate if the overlay is displayed or not.
+	_displayed: false, 
+
+	// _resizeCheck: [private] Object
+	//		Handle to interval function that checks the target for changes.
+	_resizeCheck: null, 
+	
+	// target: DOMNode||DOMID(String)||WidgetID(String)
+	//		The target to overlay when active.  Can be a widget id, a 
+	//		dom id, or a direct node reference.
+	target: "", 
+
+	// color:	String
+	//		The color to set the overlay.  Should be in #XXXXXX form.
+	//		Default color for the translucent overlay is light gray.
+	color: "#C0C0C0",
+
+	// duration: integer
+	//		Integer defining how long the show and hide effects should take.
+	duration: 500,
+
+	// _started: [private] Boolean 
+	//		Trap flag to ensure startup only processes once.
+	_started: false,
+
+	// _parent: [private] DOMNode
+	//		Wrapping div for the widget, also used for IE 7 in dealing with the
+	//		zoom issue.
+	_parent: null,
+
+	// zIndex: String
+	//		Control that lets you specify if the zIndex for the overlay
+	//		should be auto-computed based off parent zIndex, or should be set
+	//		to a particular value.  This is useful when you want to overlay 
+	//		things in digit.Dialogs, you can specify a base zIndex to append from.
+	zIndex: "auto",
+
+	startup: function(args){
+		// summary:
+		//		Over-ride of the basic widget startup function.  
+		//		Configures the target node and sets the image to use.
+		if(!this._started){
+			if(typeof this.target === "string"){
+				var w = dijit.byId(this.target);
+				if(w){
+					this.target = w.domNode;
+				}else{
+					this.target = dojo.byId(this.target);
+				}
+			}
+
+			if(this.text){
+				this._textNode.innerHTML = this.text;
+			}
+			if(this.centerIndicator === "image"){
+				this._centerNode = this._imageNode;
+				dojo.attr(this._imageNode, "src", this.image);
+				dojo.attr(this._imageNode, "alt", this.imageText);
+			}else{
+				this._centerNode = this._textNode;
+			}
+			dojo.style(this._underlayNode, {
+				display: "none",
+				backgroundColor: this.color
+			});
+			dojo.style(this._centerNode, "display", "none");
+			this.connect(this._underlayNode, "onclick", "_ignore");
+
+			//Last thing to do is move the widgets parent, if any, to the current document body.  
+			//Avoids having to deal with parent relative/absolute mess.  Otherwise positioning 
+			//tends to go goofy.  
+			if(this.domNode.parentNode && this.domNode.parentNode != dojo.body()){
+				dojo.body().appendChild(this.domNode);
+			}
+
+			//IE 7 has a horrible bug with zoom, so we have to create this node
+			//to cross-check later.  Sigh.
+			if(dojo.isIE == 7){
+				this._ieFixNode = dojo.doc.createElement("div");
+				dojo.style(this._ieFixNode, {
+					opacity: "0",
+					zIndex: "-1000",
+					position: "absolute",
+					top: "-1000px"
+				});
+				dojo.body().appendChild(this._ieFixNode);
+			}
+		}
+	},
+
+	show: function(){
+		// summary:
+		//		Function to display the blocking overlay and busy/status icon or text.
+		if(!this._displayed){
+			this._displayed = true;
+			this._size();
+			this._disableOverflow();
+			this._fadeIn();
+		}
+	},
+
+	hide: function(){
+		// summary:
+		//		Function to hide the blocking overlay and status icon or text.
+		if(this._displayed){
+			this._size();
+			this._fadeOut();
+			this._displayed = false;
+			if(this._resizeCheck !== null){
+				clearInterval(this._resizeCheck);
+				this._resizeCheck = null;
+			}
+		}
+	},
+
+	isVisible: function(){
+		// summary:
+		//		Helper function so you can test if the widget is already visible or not.
+		// returns:
+		//		boolean indicating if the widget is in 'show' state or not.
+		return this._displayed; // boolean
+	},
+
+	onShow: function(){
+		// summary:
+		//		Event that fires when the display of the Standby completes.
+	},
+
+	onHide: function(){
+		// summary:
+		//		Event that fires when the display of the Standby completes.
+	},
+
+	uninitialize: function(){
+		// summary:	
+		//		Over-ride to hide the widget, which clears intervals, before cleanup.
+		this._displayed = false;
+		if(this._resizeCheck){
+			clearInterval(this._resizeCheck);
+		}
+		dojo.style(this._centerNode, "display", "none");
+		dojo.style(this._underlayNode, "display", "none");
+		if(dojo.isIE == 7){
+			dojo.body().removeChild(this._ieFixNode);
+			delete this._ieFixNode;
+		}
+		this.target = null;
+		this._imageNode = null;
+		this._textNode = null;
+		this._centerNode = null;
+		this.inherited(arguments);
+	},
+
+	_size: function(){
+		// summary:
+		//		Internal function that handles resizing the overlay and 
+		//		centering of the image on window resizing.
+		// tags:
+		//		private
+		if(this._displayed){
+			var dir = dojo.attr(dojo.body(), "dir");
+			if(dir){dir = dir.toLowerCase();}
+			var _ie7zoom;
+			var scrollers = this._scrollerWidths();
+
+			var target = this.target;
+
+			//Show the image and make sure the zIndex is set high.
+			var curStyle = dojo.style(this._centerNode, "display"); 
+			dojo.style(this._centerNode, "display", "block");
+			var box = dojo.position(target, true);
+			if(target === dojo.body() || target === dojo.doc){
+				// Target is the whole doc, so scale to viewport.
+				box = dojo.window.getBox();
+				box.x = box.l;
+				box.y = box.t;
+			}
+
+			var cntrIndicator = dojo.marginBox(this._centerNode);
+			dojo.style(this._centerNode, "display", curStyle);
+
+			//IE has a horrible zoom bug.  So, we have to try and account for 
+			//it and fix up the scaling.
+			if(this._ieFixNode){
+				_ie7zoom = -this._ieFixNode.offsetTop / 1000;
+				box.x = Math.floor((box.x + 0.9) / _ie7zoom);
+				box.y = Math.floor((box.y + 0.9) / _ie7zoom);
+				box.w = Math.floor((box.w + 0.9) / _ie7zoom);
+				box.h = Math.floor((box.h + 0.9) / _ie7zoom);
+			}
+
+			//Figure out how to zIndex this thing over the target.
+			var zi = dojo.style(target, "zIndex");
+			var ziUl = zi;
+			var ziIn = zi;
+
+			if(this.zIndex === "auto"){
+				if(zi != "auto"){
+					ziUl = parseInt(ziUl, 10) + 1;
+					ziIn = parseInt(ziIn, 10) + 2;
+				}else{
+					//We need to search up the chain to see if there
+					//are any parent zIndexs to overlay.
+					var cNode = target.parentNode;
+					var oldZi = -100000;
+					while(cNode && cNode !== dojo.body()){
+						zi = dojo.style(cNode, "zIndex");
+						if(!zi || zi === "auto"){
+							cNode = cNode.parentNode;
+						}else{
+							var newZi = parseInt(zi, 10);
+							if(oldZi < newZi){
+								oldZi = newZi;
+								ziUl = newZi + 1;
+								ziIn = newZi + 2;
+							}
+							// Keep looking until we run out, we want the highest zIndex.
+							cNode = cNode.parentNode;
+						}
+					}
+				}
+			}else{
+				ziUl = parseInt(this.zIndex, 10) + 1;
+				ziIn = parseInt(this.zIndex, 10) + 2;
+			}
+
+			dojo.style(this._centerNode, "zIndex", ziIn);
+			dojo.style(this._underlayNode, "zIndex", ziUl);
+
+
+			var pn = target.parentNode;
+			if(pn && pn !== dojo.body() && 
+				target !== dojo.body() && 
+				target !== dojo.doc){
+				
+				// If the parent is the body tag itself,
+				// we can avoid all this, the body takes 
+				// care of overflow for me.  Besides, browser
+				// weirdness with height and width on body causes 
+				// problems with this sort of intersect testing 
+				// anyway.
+				var obh = box.h;
+				var obw = box.w;
+				var pnBox = dojo.position(pn, true);
+
+				//More IE zoom corrections.  Grr.
+				if(this._ieFixNode){
+					_ie7zoom = -this._ieFixNode.offsetTop / 1000;
+					pnBox.x = Math.floor((pnBox.x + 0.9) / _ie7zoom);
+					pnBox.y = Math.floor((pnBox.y + 0.9) / _ie7zoom);
+					pnBox.w = Math.floor((pnBox.w + 0.9) / _ie7zoom);
+					pnBox.h = Math.floor((pnBox.h + 0.9) / _ie7zoom);
+				}
+				
+				//Shift the parent width/height a bit if scollers are present.
+				pnBox.w -= pn.scrollHeight > pn.clientHeight && 
+					pn.clientHeight > 0 ? scrollers.v: 0;
+				pnBox.h -= pn.scrollWidth > pn.clientWidth && 
+					pn.clientWidth > 0 ? scrollers.h: 0;
+
+				//RTL requires a bit of massaging in some cases 
+				//(and differently depending on browser, ugh!)
+				//WebKit and others still need work.
+				if(dir === "rtl"){
+					if(dojo.isOpera){
+						box.x += pn.scrollHeight > pn.clientHeight && 
+							pn.clientHeight > 0 ? scrollers.v: 0;
+						pnBox.x += pn.scrollHeight > pn.clientHeight && 
+							pn.clientHeight > 0 ? scrollers.v: 0;
+					}else if(dojo.isIE){
+						pnBox.x += pn.scrollHeight > pn.clientHeight && 
+							pn.clientHeight > 0 ? scrollers.v: 0;
+					}else if(dojo.isWebKit){
+						//TODO:  FIX THIS!
+					}
+				}
+
+				//Figure out if we need to adjust the overlay to fit a viewable 
+				//area, then resize it, we saved the original height/width above.
+				//This is causing issues on IE.  Argh!
+				if(pnBox.w < box.w){
+					//Scale down the width if necessary.
+					box.w = box.w - pnBox.w;
+				}
+				if(pnBox.h < box.h){
+					//Scale down the width if necessary.
+					box.h = box.h - pnBox.h;
+				}
+
+				//Look at the y positions and see if we intersect with the
+				//viewport borders.  Will have to do computations off it.
+				var vpTop = pnBox.y;
+				var vpBottom = pnBox.y + pnBox.h;
+				var bTop = box.y;
+				var bBottom = box.y + obh;
+				var vpLeft = pnBox.x;
+				var vpRight = pnBox.x + pnBox.w;
+				var bLeft = box.x;
+				var bRight = box.x + obw;
+				var delta;
+				//Adjust the height now
+				if(bBottom > vpTop && 
+					bTop < vpTop){
+					box.y = pnBox.y;
+					//intersecting top, need to do some shifting.
+					delta = vpTop - bTop;
+					var visHeight = obh - delta;
+					//If the visible height < viewport height, 
+					//We need to shift it.
+					if(visHeight < pnBox.h){
+						box.h = visHeight;
+					}else{
+						//Deal with horizontal scrollbars if necessary.
+						box.h -= 2*(pn.scrollWidth > pn.clientWidth && 
+							pn.clientWidth > 0? scrollers.h: 0);
+					}
+				}else if(bTop < vpBottom && bBottom > vpBottom){
+					//Intersecting bottom, just figure out how much 
+					//overlay to show.
+					box.h = vpBottom - bTop;
+				}else if(bBottom <= vpTop || bTop >= vpBottom){
+					//Outside view, hide it.
+					box.h = 0;
+				}
+
+				//adjust width
+				if(bRight > vpLeft && bLeft < vpLeft){
+					box.x = pnBox.x;
+					//intersecting left, need to do some shifting.
+					delta = vpLeft - bLeft;
+					var visWidth = obw - delta;
+					//If the visible width < viewport width, 
+					//We need to shift it.
+					if(visWidth < pnBox.w){
+						box.w = visWidth;
+					}else{
+						//Deal with horizontal scrollbars if necessary.
+						box.w -= 2*(pn.scrollHeight > pn.clientHeight && 
+							pn.clientHeight > 0? scrollers.w:0);
+					}
+				}else if(bLeft < vpRight && bRight > vpRight){
+					//Intersecting right, just figure out how much 
+					//overlay to show.
+					box.w = vpRight - bLeft;
+				}else if(bRight <= vpLeft || bLeft >= vpRight){
+					//Outside view, hide it.
+					box.w = 0;
+				}
+			}
+
+			if(box.h > 0 && box.w > 0){
+				//Set position and size of the blocking div overlay.
+				dojo.style(this._underlayNode, {
+					display: "block",
+					width: box.w + "px",
+					height: box.h + "px",
+					top: box.y + "px",
+					left: box.x + "px"
+				});
+
+				var styles = ["borderRadius", "borderTopLeftRadius", 
+					"borderTopRightRadius","borderBottomLeftRadius", 
+					"borderBottomRightRadius"];
+				this._cloneStyles(styles);
+				if(!dojo.isIE){
+					//Browser specific styles to try and clone if non-IE.
+					styles = ["MozBorderRadius", "MozBorderRadiusTopleft", 
+						"MozBorderRadiusTopright","MozBorderRadiusBottomleft", 
+						"MozBorderRadiusBottomright","WebkitBorderRadius", 
+						"WebkitBorderTopLeftRadius", "WebkitBorderTopRightRadius", 
+						"WebkitBorderBottomLeftRadius","WebkitBorderBottomRightRadius"
+					];
+					this._cloneStyles(styles, this);
+				}
+				var cntrIndicatorTop = (box.h/2) - (cntrIndicator.h/2);
+				var cntrIndicatorLeft = (box.w/2) - (cntrIndicator.w/2);
+				//Only show the image if there is height and width room.
+				if(box.h >= cntrIndicator.h && box.w >= cntrIndicator.w){
+					dojo.style(this._centerNode, {
+						top: (cntrIndicatorTop + box.y) + "px",
+						left: (cntrIndicatorLeft + box.x) + "px",
+						display: "block"
+					});
+				}else{
+					dojo.style(this._centerNode, "display", "none");
+				}
+			}else{
+				//Target has no size, display nothing on it!
+				dojo.style(this._underlayNode, "display", "none");
+				dojo.style(this._centerNode, "display", "none");
+			}
+			if(this._resizeCheck === null){
+				//Set an interval timer that checks the target size and scales as needed.
+				//Checking every 10th of a second seems to generate a fairly smooth update.
+				var self = this;
+				this._resizeCheck = setInterval(function(){self._size();}, 100);
+			}
+		}
+	},
+
+	_cloneStyles: function(list){
+		// summary:
+		//		Internal function to clone a set of styles from the target to 
+		//		the underlay.
+		// list: Array
+		//		An array of style names to clone.
+		//
+		// tags:
+		//		private
+		dojo.forEach(list, function(style){
+			dojo.style(this._underlayNode,style,dojo.style(this.target,style));
+		}, this);
+	},
+
+	_fadeIn: function(){
+		// summary:
+		//		Internal function that does the opacity style fade in animation.
+		// tags:
+		//		private
+		var self = this;
+		var underlayNodeAnim = dojo.animateProperty({
+			duration: self.duration,
+			node: self._underlayNode, 
+			properties: {opacity: {start: 0, end: 0.75}}
+		});
+		var imageAnim = dojo.animateProperty({
+			duration: self.duration,
+			node: self._centerNode, 
+			properties: {opacity: {start: 0, end: 1}},
+			onEnd: function(){
+				self.onShow();
+			}
+		});
+		var anim = dojo.fx.combine([underlayNodeAnim,imageAnim]);
+		anim.play();
+	},
+
+	_fadeOut: function(){
+		// summary:
+		//		Internal function that does the opacity style fade out animation.
+		// tags:
+		//		private
+		var self = this;
+		var underlayNodeAnim = dojo.animateProperty({
+			duration: self.duration,
+			node: self._underlayNode, 
+			properties: {opacity: {start: 0.75, end: 0}},
+			onEnd: function(){
+				dojo.style(this.node,{"display":"none", "zIndex": "-1000"});
+			}
+		});
+		var imageAnim = dojo.animateProperty({
+			duration: self.duration,
+			node: self._centerNode, 
+			properties: {opacity: {start: 1, end: 0}},
+			onEnd: function(){
+				dojo.style(this.node,{"display":"none", "zIndex": "-1000"});
+				self.onHide();
+				self._enableOverflow();
+			}
+		});
+		var anim = dojo.fx.combine([underlayNodeAnim,imageAnim]);
+		anim.play();
+	},
+
+	_ignore: function(event){
+		// summary:
+		//		Function to ignore events that occur on the overlay.
+		// event: Event
+		//		The event to halt
+		// tags:
+		//		private
+		if(event){
+			dojo.stopEvent(event);
+		}
+	},
+
+	_scrollerWidths: function(){
+		// summary:
+		//		This function will calculate the size of the vertical and
+		//		horizontaol scrollbars.
+		// returns:
+		//		Object of form: {v: Number, h: Number} where v is vertical scrollbar width
+		//		and h is horizontal scrollbar width.
+		// tags:
+		//		private
+		var div = dojo.doc.createElement("div");
+		dojo.style(div, {
+			position: "absolute",
+			opacity: 0,
+			overflow: "hidden",
+			width: "50px",
+			height: "50px",
+			zIndex: "-100",
+			top: "-200px",
+			left: "-200px",
+			padding: "0px",
+			margin: "0px"
+		});
+		var iDiv = dojo.doc.createElement("div");
+		dojo.style(iDiv, {
+			width: "200px",
+			height: "10px"
+		});
+		div.appendChild(iDiv);
+		dojo.body().appendChild(div);
+
+		//Figure out content size before and after 
+		//scrollbars are there, then just subtract to 
+		//get width.
+		var b = dojo.contentBox(div);
+		dojo.style(div, "overflow", "scroll");
+		var a = dojo.contentBox(div);
+		dojo.body().removeChild(div);
+		return { v: b.w - a.w, h: b.h - a.h };
+	},
+
+	/* The following are functions that tie into _Widget.attr() */
+
+	_setTextAttr: function(text){
+		// summary:
+		//		Function to allow widget.attr to set the text displayed in center 
+		//		if using text display.
+		// text: String
+		//		The text to set.
+		this._textNode.innerHTML = text;
+		this.text = text;
+	},
+
+	_setColorAttr: function(c){
+		// summary:
+		//		Function to allow widget.attr to set the color used for the translucent
+		//		div overlay.
+		// c: String
+		//		The color to set the background underlay to in #XXXXXX format..
+		dojo.style(this._underlayNode, "backgroundColor", c);
+		this.color = c;
+	},
+
+	_setImageTextAttr: function(text){
+		// summary:
+		//		Function to allow widget.attr to set the ALT text text displayed for
+		//		the image (if using image center display).
+		// text: String
+		//		The text to set.
+		dojo.attr(this._imageNode, "alt", text);
+		this.imageText = text;
+	},
+
+	_setImageAttr: function(url){
+		// summary:
+		//		Function to allow widget.attr to set the url source for the center image
+		// text: String
+		//		The url to set for the image.
+		dojo.attr(this._imageNode, "src", url);
+		this.image = url;
+	},
+
+	_setCenterIndicatorAttr: function(indicator){
+		// summary:
+		//		Function to allow widget.attr to set the node used for the center indicator,
+		//		either the image or the text.
+		// indicator: String
+		//		The indicator to use, either 'image' or 'text'.
+		this.centerIndicator = indicator;
+		if(indicator === "image"){
+			this._centerNode = this._imageNode;
+			dojo.style(this._textNode, "display", "none");
+		}else{
+			this._centerNode = this._textNode;
+			dojo.style(this._imageNode, "display", "none");
+		}
+	},
+
+	_disableOverflow: function(){
+		 // summary:
+		 //		Function to disable scrollbars on the body.  Only used if the overlay 
+		 //		targets the body or the document.
+		 if(this.target === dojo.body() || this.target === dojo.doc){
+			 // Store the overflow state we have to restore later.
+			 // IE had issues, so have to check that it's defined.  Ugh.
+			 this._overflowDisabled = true;
+			 var body = dojo.body();
+			 if(body.style && body.style.overflow){
+				 this._oldOverflow = dojo.style(body, "overflow");
+			 }else{
+				 this._oldOverflow = "";
+			 }
+			 if(dojo.isIE && !dojo.isQuirks){
+				 // IE will put scrollbars in anyway, html (parent of body)
+				 // also controls them in standards mode, so we have to 
+				 // remove them, argh.
+				 if(body.parentNode && 
+					body.parentNode.style && 
+					body.parentNode.style.overflow){
+					 this._oldBodyParentOverflow = body.parentNode.style.overflow;
+				 }else{
+					 try{
+						this._oldBodyParentOverflow = dojo.style(body.parentNode, "overflow");
+					 }catch(e){
+						 this._oldBodyParentOverflow = "scroll";
+					 }
+				 }
+				 dojo.style(body.parentNode, "overflow", "hidden");
+			 }
+			 dojo.style(body, "overflow", "hidden");
+		 }
+	},
+
+	_enableOverflow: function(){
+		 // summary:
+		 //		Function to restore scrollbars on the body.  Only used if the overlay 
+		 //		targets the body or the document.
+		 if(this._overflowDisabled){
+			delete this._overflowDisabled;
+			var body = dojo.body();
+			// Restore all the overflow.
+			if(dojo.isIE && !dojo.isQuirks){
+				body.parentNode.style.overflow = this._oldBodyParentOverflow;
+				delete this._oldBodyParentOverflow;
+			}
+			dojo.style(body, "overflow", this._oldOverflow);
+			if(dojo.isWebKit){
+				//Gotta poke WebKit, or scrollers don't come back. :-(
+				var div = dojo.create("div", { style: {
+						height: "2px"
+					}
+				});
+				body.appendChild(div);
+				setTimeout(function(){
+					body.removeChild(div);
+				}, 0);
+			}
+			delete this._oldOverflow;
+		}
+	}
+});	
diff --git a/dojox/widget/Standby/images/loading.gif b/dojox/widget/Standby/images/loading.gif
old mode 100644
new mode 100755
diff --git a/dojox/widget/Toaster.js b/dojox/widget/Toaster.js
index 3d42d9b..c2fa25f 100644
--- a/dojox/widget/Toaster.js
+++ b/dojox/widget/Toaster.js
@@ -1,173 +1,276 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.Toaster"]){
-dojo._hasResource["dojox.widget.Toaster"]=true;
 dojo.provide("dojox.widget.Toaster");
+
 dojo.require("dojo.fx");
+dojo.require("dojo.window");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.declare("dojox.widget.Toaster",[dijit._Widget,dijit._Templated],{templateString:"<div class=\"dijitToasterClip\" dojoAttachPoint=\"clipNode\"><div class=\"dijitToasterContainer\" dojoAttachPoint=\"containerNode\" dojoAttachEvent=\"onclick:onSelect\"><div class=\"dijitToasterContent\" dojoAttachPoint=\"contentNode\"></div></div></div>",messageTopic:"",messageTypes:{MESSAGE:"message",WARNING:"warning",ERROR:"error",FATAL:"fatal"},defaultType:"message",positionDirection:"br-up",positio [...]
-this.inherited(arguments);
-this.hide();
-dojo.body().appendChild(this.domNode);
-if(this.messageTopic){
-dojo.subscribe(this.messageTopic,this,"_handleMessage");
-}
-},_handleMessage:function(_1){
-if(dojo.isString(_1)){
-this.setContent(_1);
-}else{
-this.setContent(_1.message,_1.type,_1.duration);
-}
-},_capitalize:function(w){
-return w.substring(0,1).toUpperCase()+w.substring(1);
-},setContent:function(_2,_3,_4){
-_4=_4||this.duration;
-if(this.slideAnim){
-if(this.slideAnim.status()!="playing"){
-this.slideAnim.stop();
-}
-if(this.slideAnim.status()=="playing"||(this.fadeAnim&&this.fadeAnim.status()=="playing")){
-setTimeout(dojo.hitch(this,function(){
-this.setContent(_2,_3,_4);
-}),50);
-return;
-}
-}
-for(var _5 in this.messageTypes){
-dojo.removeClass(this.containerNode,"dijitToaster"+this._capitalize(this.messageTypes[_5]));
-}
-dojo.style(this.containerNode,"opacity",1);
-this._setContent(_2);
-dojo.addClass(this.containerNode,"dijitToaster"+this._capitalize(_3||this.defaultType));
-this.show();
-var _6=dojo.marginBox(this.containerNode);
-this._cancelHideTimer();
-if(this.isVisible){
-this._placeClip();
-if(!this._stickyMessage){
-this._setHideTimer(_4);
-}
-}else{
-var _7=this.containerNode.style;
-var pd=this.positionDirection;
-if(pd.indexOf("-up")>=0){
-_7.left=0+"px";
-_7.top=_6.h+10+"px";
-}else{
-if(pd.indexOf("-left")>=0){
-_7.left=_6.w+10+"px";
-_7.top=0+"px";
-}else{
-if(pd.indexOf("-right")>=0){
-_7.left=0-_6.w-10+"px";
-_7.top=0+"px";
-}else{
-if(pd.indexOf("-down")>=0){
-_7.left=0+"px";
-_7.top=0-_6.h-10+"px";
-}else{
-throw new Error(this.id+".positionDirection is invalid: "+pd);
-}
-}
-}
-}
-this.slideAnim=dojo.fx.slideTo({node:this.containerNode,top:0,left:0,duration:this.slideDuration});
-this.connect(this.slideAnim,"onEnd",function(_8,_9){
-this.fadeAnim=dojo.fadeOut({node:this.containerNode,duration:1000});
-this.connect(this.fadeAnim,"onEnd",function(_a){
-this.isVisible=false;
-this.hide();
-});
-this._setHideTimer(_4);
-this.connect(this,"onSelect",function(_b){
-this._cancelHideTimer();
-this._stickyMessage=false;
-this.fadeAnim.play();
-});
-this.isVisible=true;
-});
-this.slideAnim.play();
-}
-},_setContent:function(_c){
-if(dojo.isFunction(_c)){
-_c(this);
-return;
-}
-if(_c&&this.isVisible){
-_c=this.contentNode.innerHTML+this.separator+_c;
-}
-this.contentNode.innerHTML=_c;
-},_cancelHideTimer:function(){
-if(this._hideTimer){
-clearTimeout(this._hideTimer);
-this._hideTimer=null;
-}
-},_setHideTimer:function(_d){
-this._cancelHideTimer();
-if(_d>0){
-this._cancelHideTimer();
-this._hideTimer=setTimeout(dojo.hitch(this,function(_e){
-if(this.bgIframe&&this.bgIframe.iframe){
-this.bgIframe.iframe.style.display="none";
-}
-this._hideTimer=null;
-this._stickyMessage=false;
-this.fadeAnim.play();
-}),_d);
-}else{
-this._stickyMessage=true;
-}
-},_placeClip:function(){
-var _f=dijit.getViewport();
-var _10=dojo.marginBox(this.containerNode);
-var _11=this.clipNode.style;
-_11.height=_10.h+"px";
-_11.width=_10.w+"px";
-var pd=this.positionDirection;
-if(pd.match(/^t/)){
-_11.top=_f.t+"px";
-}else{
-if(pd.match(/^b/)){
-_11.top=(_f.h-_10.h-2+_f.t)+"px";
-}
-}
-if(pd.match(/^[tb]r-/)){
-_11.left=(_f.w-_10.w-1-_f.l)+"px";
-}else{
-if(pd.match(/^[tb]l-/)){
-_11.left=0+"px";
-}
-}
-_11.clip="rect(0px, "+_10.w+"px, "+_10.h+"px, 0px)";
-if(dojo.isIE){
-if(!this.bgIframe){
-this.clipNode.id=dijit.getUniqueId("dojox_widget_Toaster_clipNode");
-this.bgIframe=new dijit.BackgroundIframe(this.clipNode);
-}
-var _12=this.bgIframe.iframe;
-if(_12){
-_12.style.display="block";
-}
-}
-},onSelect:function(e){
-},show:function(){
-dojo.style(this.domNode,"display","block");
-this._placeClip();
-if(!this._scrollConnected){
-this._scrollConnected=dojo.connect(window,"onscroll",this,this._placeClip);
-}
-},hide:function(){
-dojo.style(this.domNode,"display","none");
-if(this._scrollConnected){
-dojo.disconnect(this._scrollConnected);
-this._scrollConnected=false;
-}
-dojo.style(this.containerNode,"opacity",1);
-}});
-}
+
+dojo.declare("dojox.widget.Toaster", [dijit._Widget, dijit._Templated], {
+		// summary:
+		//		Message that slides in from the corner of the screen, used for notifications
+		//		like "new email".
+
+		templateString: '<div class="dijitToasterClip" dojoAttachPoint="clipNode"><div class="dijitToasterContainer" dojoAttachPoint="containerNode" dojoAttachEvent="onclick:onSelect"><div class="dijitToasterContent" dojoAttachPoint="contentNode"></div></div></div>',
+
+		// messageTopic: String
+		//		Name of topic; anything published to this topic will be displayed as a message.
+		//		Message format is either String or an object like
+		//		{message: "hello word", type: "error", duration: 500}
+		messageTopic: "",
+
+		// messageTypes: Enumeration
+		//		Possible message types.
+		messageTypes: {
+			MESSAGE: "message",
+			WARNING: "warning",
+			ERROR: "error",
+			FATAL: "fatal"
+		},
+
+		// defaultType: String
+		//		If message type isn't specified (see "messageTopic" parameter),
+		//		then display message as this type.
+		//		Possible values in messageTypes enumeration ("message", "warning", "error", "fatal")
+		defaultType: "message",
+
+		// positionDirection: String
+		//		Position from which message slides into screen, one of
+		//		["br-up", "br-left", "bl-up", "bl-right", "tr-down", "tr-left", "tl-down", "tl-right"]
+		positionDirection: "br-up",
+		
+		// positionDirectionTypes: Array
+		//		Possible values for positionDirection parameter
+		positionDirectionTypes: ["br-up", "br-left", "bl-up", "bl-right", "tr-down", "tr-left", "tl-down", "tl-right"],
+
+		// duration: Integer
+		//		Number of milliseconds to show message
+		duration: 2000,
+
+		// slideDuration: Integer
+		//		Number of milliseconds for the slide animation, increasing will cause the Toaster 
+		//    to slide in more slowly.
+		slideDuration: 500,
+
+		//separator: String
+		//		String used to separate messages if consecutive calls are made to setContent before previous messages go away
+		separator: "<hr></hr>",
+
+		postCreate: function(){
+			this.inherited(arguments);
+			this.hide();
+			
+			// place node as a child of body for positioning
+			dojo.body().appendChild(this.domNode);
+			
+			if(this.messageTopic){
+				dojo.subscribe(this.messageTopic, this, "_handleMessage");
+			}
+		},
+
+		_handleMessage: function(/*String|Object*/message){
+			if(dojo.isString(message)){
+				this.setContent(message);
+			}else{
+				this.setContent(message.message, message.type, message.duration);
+			}
+		},
+
+		_capitalize: function(/* String */w){
+				return w.substring(0,1).toUpperCase() + w.substring(1);
+		},
+
+		setContent: function(/*String|Function*/message, /*String*/messageType, /*int?*/duration){
+			// summary:
+			//		sets and displays the given message and show duration
+			// message:
+			//		the message. If this is a function, it will be called with this toaster widget as the only argument.
+			// messageType:
+			//		type of message; possible values in messageTypes enumeration ("message", "warning", "error", "fatal")
+			// duration:
+			//		duration in milliseconds to display message before removing it. Widget has default value.
+			duration = duration||this.duration;
+			// sync animations so there are no ghosted fades and such
+			if(this.slideAnim){
+				if(this.slideAnim.status() != "playing"){
+					this.slideAnim.stop();
+				}
+				if(this.slideAnim.status() == "playing" || (this.fadeAnim && this.fadeAnim.status() == "playing")){
+					setTimeout(dojo.hitch(this, function(){
+						this.setContent(message, messageType, duration);
+					}), 50);
+					return;
+				}
+			}
+
+			// determine type of content and apply appropriately
+			for(var type in this.messageTypes){
+				dojo.removeClass(this.containerNode, "dijitToaster" + this._capitalize(this.messageTypes[type]));
+			}
+
+			dojo.style(this.containerNode, "opacity", 1);
+
+			this._setContent(message);
+
+			dojo.addClass(this.containerNode, "dijitToaster" + this._capitalize(messageType || this.defaultType));
+
+			// now do funky animation of widget appearing from
+			// bottom right of page and up
+			this.show();
+			var nodeSize = dojo.marginBox(this.containerNode);
+			this._cancelHideTimer();
+			if(this.isVisible){
+				this._placeClip();
+				//update hide timer if no sticky message in stack 
+				if(!this._stickyMessage) {
+					this._setHideTimer(duration);
+				}
+			}else{
+				var style = this.containerNode.style;
+				var pd = this.positionDirection;
+				// sets up initial position of container node and slide-out direction
+				if(pd.indexOf("-up") >= 0){
+					style.left=0+"px";
+					style.top=nodeSize.h + 10 + "px";
+				}else if(pd.indexOf("-left") >= 0){
+					style.left=nodeSize.w + 10 +"px";
+					style.top=0+"px";
+				}else if(pd.indexOf("-right") >= 0){
+					style.left = 0 - nodeSize.w - 10 + "px";
+					style.top = 0+"px";
+				}else if(pd.indexOf("-down") >= 0){
+					style.left = 0+"px";
+					style.top = 0 - nodeSize.h - 10 + "px";
+				}else{
+					throw new Error(this.id + ".positionDirection is invalid: " + pd);
+				}
+				this.slideAnim = dojo.fx.slideTo({
+					node: this.containerNode,
+					top: 0, left: 0,
+					duration: this.slideDuration});
+				this.connect(this.slideAnim, "onEnd", function(nodes, anim){
+						//we build the fadeAnim here so we dont have to duplicate it later
+						// can't do a fadeHide because we're fading the
+						// inner node rather than the clipping node
+						this.fadeAnim = dojo.fadeOut({
+							node: this.containerNode,
+							duration: 1000});
+						this.connect(this.fadeAnim, "onEnd", function(evt){
+							this.isVisible = false;
+							this.hide();
+						});
+						this._setHideTimer(duration);
+						this.connect(this, 'onSelect', function(evt){
+							this._cancelHideTimer();
+							//force clear sticky message
+							this._stickyMessage=false;
+							this.fadeAnim.play();
+						});
+
+						this.isVisible = true;
+					});
+				this.slideAnim.play();
+			}
+		},
+		
+		_setContent: function(message){
+			if(dojo.isFunction(message)){
+				message(this);
+				return;
+			}
+			if(message && this.isVisible){
+				message = this.contentNode.innerHTML + this.separator + message;
+			}
+			this.contentNode.innerHTML = message;
+		},
+		_cancelHideTimer:function(){
+			if (this._hideTimer){
+				clearTimeout(this._hideTimer);
+				this._hideTimer=null;
+			}
+		},
+		
+		_setHideTimer:function(duration){
+			this._cancelHideTimer();
+			//if duration == 0 we keep the message displayed until clicked
+			if(duration>0){
+				this._cancelHideTimer();
+				this._hideTimer=setTimeout(dojo.hitch(this, function(evt){
+					// we must hide the iframe in order to fade
+					// TODO: figure out how to fade with a BackgroundIframe
+					if(this.bgIframe && this.bgIframe.iframe){
+						this.bgIframe.iframe.style.display="none";
+					}
+					this._hideTimer=null;
+					//force clear sticky message
+					this._stickyMessage=false;
+					this.fadeAnim.play();
+				}), duration);
+			}
+			else
+				this._stickyMessage=true;
+		},
+		
+		_placeClip: function(){
+			var view = dojo.window.getBox();
+
+			var nodeSize = dojo.marginBox(this.containerNode);
+
+			var style = this.clipNode.style;
+			// sets up the size of the clipping node
+			style.height = nodeSize.h+"px";
+			style.width = nodeSize.w+"px";
+
+			// sets up the position of the clipping node
+			var pd = this.positionDirection;
+			if(pd.match(/^t/)){
+				style.top = view.t+"px";
+			}else if(pd.match(/^b/)){
+				style.top = (view.h - nodeSize.h - 2 + view.t)+"px";
+			}
+			if(pd.match(/^[tb]r-/)){
+				style.left = (view.w - nodeSize.w - 1 - view.l)+"px";
+			}else if(pd.match(/^[tb]l-/)){
+				style.left = 0 + "px";
+			}
+
+			style.clip = "rect(0px, " + nodeSize.w + "px, " + nodeSize.h + "px, 0px)";
+			if(dojo.isIE){
+				if(!this.bgIframe){
+					this.clipNode.id = dijit.getUniqueId("dojox_widget_Toaster_clipNode");
+					this.bgIframe = new dijit.BackgroundIframe(this.clipNode);
+				}
+				var iframe = this.bgIframe.iframe;
+				if(iframe){ iframe.style.display="block"; }
+			}
+		},
+
+		onSelect: function(/*Event*/e){
+			// summary: callback for when user clicks the message
+		},
+
+		show: function(){
+			// summary: show the Toaster
+			dojo.style(this.domNode, 'display', 'block');
+
+			this._placeClip();
+
+			if(!this._scrollConnected){
+				this._scrollConnected = dojo.connect(window, "onscroll", this, this._placeClip);
+			}
+		},
+
+		hide: function(){
+			// summary: hide the Toaster
+
+			dojo.style(this.domNode, 'display', 'none');
+
+			if(this._scrollConnected){
+				dojo.disconnect(this._scrollConnected);
+				this._scrollConnected = false;
+			}
+
+			dojo.style(this.containerNode, "opacity", 1);
+		}
+	}
+);
diff --git a/dojox/widget/Toaster/Toaster.css b/dojox/widget/Toaster/Toaster.css
index b898452..b933063 100644
--- a/dojox/widget/Toaster/Toaster.css
+++ b/dojox/widget/Toaster/Toaster.css
@@ -1,34 +1,42 @@
+/* main classes for dojox.widget.Toaster */
 
 .dijitToasterContent {
 	padding:1em;
 	padding-top:0.25em;
 	background:#73c74a;
 }
+
 .dijitToasterMessage{ 
 	color:#fff;
 }
+
 .dijitToasterWarning{ }
 .dijitToasterError,
 .dijitToasterFatal{
 	font-weight:bold;
 	color:#fff;
 }
+
 .dijitToasterWarning .dijitToasterContent{
 	padding:1em;
 	padding-top:0.25em;
 	background:#d4d943;
 } 
+
 .dijitToasterError .dijitToasterContent{
 	padding:1em;
 	padding-top:0.25em;
 	background:#c46600;
 }
+
+/* imported from dijit.css */
  
 .dijitToasterClip {
 	position: absolute;
 	z-index: 5000;
 	overflow: hidden;
 }
+
 .dijitToasterContainer {
 	display: block;
 	position: absolute;
diff --git a/dojox/widget/UpgradeBar.js b/dojox/widget/UpgradeBar.js
old mode 100644
new mode 100755
index 879a825..cb3820e
--- a/dojox/widget/UpgradeBar.js
+++ b/dojox/widget/UpgradeBar.js
@@ -1,101 +1,223 @@
-/*
-	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
-*/
+dojo.provide("dojox.widget.UpgradeBar");
 
+dojo.require("dojo.window");
+dojo.require("dojo.fx");
+dojo.require("dojo.cookie");
 
-if(!dojo._hasResource["dojox.widget.UpgradeBar"]){
-dojo._hasResource["dojox.widget.UpgradeBar"]=true;
-dojo.provide("dojox.widget.UpgradeBar");
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
-dojo.require("dojo.fx");
-dojo.require("dojo.cookie");
+
 dojo.experimental("dojox.widget.UpgradeBar");
-dojo.declare("dojox.widget.UpgradeBar",[dijit._Widget,dijit._Templated],{notifications:[],buttonCancel:"Close for now",noRemindButton:"Don't Remind Me Again",templateString:dojo.cache("dojox.widget","UpgradeBar/UpgradeBar.html","<div class=\"dojoxUpgradeBar\">\n\t<div class=\"dojoxUpgradeBarMessage\" dojoAttachPoint=\"messageNode\">message</div>\n\t<div class=\"dojoxUpgradeBarReminderButton\" dojoAttachPoint=\"dontRemindButtonNode\" dojoAttachEvent=\"onclick:_onDontRemindClick\">${noRemi [...]
-if(!_1.notifications&&_2){
-dojo.forEach(_2.childNodes,function(n){
-if(n.nodeType==1){
-var _3=dojo.attr(n,"validate");
-this.notifications.push({message:n.innerHTML,validate:function(){
-var _4=true;
-try{
-_4=dojo.eval(_3);
-}
-catch(e){
-}
-return _4;
-}});
-}
-},this);
-}
-},checkNotifications:function(){
-if(!this.notifications.length){
-return;
-}
-for(var i=0;i<this.notifications.length;i++){
-var _5=this.notifications[i].validate();
-if(_5){
-this.notify(this.notifications[i].message);
-break;
-}
-}
-},postCreate:function(){
-this.inherited(arguments);
-if(this.domNode.parentNode){
-dojo.style(this.domNode,"display","none");
-}
-dojo.mixin(this.attributeMap,{message:{node:"messageNode",type:"innerHTML"}});
-if(!this.noRemindButton){
-dojo.destroy(this.dontRemindButtonNode);
-}
-if(dojo.isIE==6){
-var _6=this;
-var _7=function(){
-var v=dijit.getViewport();
-dojo.style(_6.domNode,"width",v.w+"px");
-};
-this.connect(window,"resize",function(){
-_7();
-});
-_7();
-}
-dojo.addOnLoad(this,"checkNotifications");
-},notify:function(_8){
-if(dojo.cookie("disableUpgradeReminders")){
-return;
-}
-if(!this.domNode.parentNode){
-document.body.appendChild(this.domNode);
-}else{
-dojo.style(this.domNode,"display","");
-}
-if(_8){
-this.attr("message",_8);
-}
-},show:function(){
-this._bodyMarginTop=dojo.style(dojo.body(),"marginTop");
-this._size=dojo.contentBox(this.domNode).h;
-dojo.style(this.domNode,{display:"block",height:0,opacity:0});
-if(!this._showAnim){
-this._showAnim=dojo.fx.combine([dojo.animateProperty({node:dojo.body(),duration:500,properties:{marginTop:this._bodyMarginTop+this._size}}),dojo.animateProperty({node:this.domNode,duration:500,properties:{height:this._size,opacity:1}})]);
-}
-this._showAnim.play();
-},hide:function(){
-if(!this._hideAnim){
-this._hideAnim=dojo.fx.combine([dojo.animateProperty({node:dojo.body(),duration:500,properties:{marginTop:this._bodyMarginTop}}),dojo.animateProperty({node:this.domNode,duration:500,properties:{height:0,opacity:0}})]);
-dojo.connect(this._hideAnim,"onEnd",this,function(){
-dojo.style(this.domNode,"display","none");
+
+
+dojo.declare("dojox.widget.UpgradeBar", [dijit._Widget, dijit._Templated], {
+	//	summary:
+	//				Shows a bar at the top of the screen when the user is to
+	//				be notified that they should upgrade their browser or a
+	//				plugin.
+	//
+	//	description:
+	//				You can insert custom validations to trigger the UpgradeBar
+	//				to display. An evaluation of 'true' shows the bar (as this
+	//				version *is* less than it should be). Multiple validations
+	//				may be checked, although only the first in the list will be
+	//				displayed.
+	//				Markup and programmatic are supported. Markup is a little
+	//				cleaner, since a majority of the parameters are the HTML
+	//				snippets to be displayed. In markup, the validate code should
+	//				be an expression that will evaluate to true or false. This
+	//				expression is wrapped in a try/catch, so if it blows up, it
+	//				is assumed to be true and trigger the bar.
+	//				In programmtic, a function should be used that returns true
+	//				or false. You would need to use your own try/catch in that.
+	//
+	//	example:	See tests for examples.
+	//
+	//	notifications: Array
+	//		An array of objects that hold the criteria for upgrades.
+	//			message: String
+	//				The message to display in the bar. Can be HTML.
+	//			validate:Function
+	//				The expression to evaluate to determine if the
+	//				bar should show or not. Should be a simple expression
+	//				if used in HTML:
+	//				|	<div validate="!google.gears">
+	//				|	<div validate="dojo.isIE<8">
+	notifications:[],
+	//
+	//	buttonCancel:String
+	//		The HTML tip show when hovering over the close button.
+	buttonCancel:"Close for now",
+	//
+	//	noRemindButton:String
+	//		The text link shown that when clicked, permanently dismisses
+	//		the message (sets a cookie). If this string is blank, this
+	//		link is not displayed.
+	noRemindButton:"Don't Remind Me Again",
+
+	templateString: dojo.cache("dojox.widget","UpgradeBar/UpgradeBar.html"),
+
+	constructor: function(props, node){
+
+		if(!props.notifications && node){
+			// From markup. Create the notifications Array from the
+			//	srcRefNode children.
+			dojo.forEach(node.childNodes, function(n){
+				if(n.nodeType==1){
+					var val = dojo.attr(n, "validate");
+					this.notifications.push({
+						message:n.innerHTML,
+						validate:function(){
+							// the function that fires to determine if the
+							// bar shows or not.
+							var evals = true;
+							try{
+								evals = dojo.eval(val);
+							}catch(e){ /* squelch. it's true.*/ }
+							return evals;
+						}
+					});
+				}
+			}, this);
+		}
+
+	},
+
+	checkNotifications: function(){
+		// 	summary:
+		//			Internal. Go through the notifications Array
+		//			and check for any that evaluate to true.
+		// tags:
+		//		private
+		//
+		if(!this.notifications.length){
+			// odd. why use the bar but not set any notifications?
+			return;
+		}
+
+		for(var i=0;i<this.notifications.length;i++){
+			var evals = this.notifications[i].validate();
+			if(evals){
+				this.notify(this.notifications[i].message);
+				// Validation resulted in true, meaning a feature is missing
+				// Don't check any other messages. One at a time.
+				break;
+			}
+		}
+	},
+
+	postCreate: function(){
+		this.inherited(arguments);
+		if(this.domNode.parentNode){
+			dojo.style(this.domNode, "display", "none");
+		}
+		dojo.mixin(this.attributeMap, {
+			message:{ node:"messageNode", type:"innerHTML" }
+		});
+		if(!this.noRemindButton){
+			dojo.destroy(this.dontRemindButtonNode)
+		}
+		if(dojo.isIE==6){
+			// IE6 is challenged when it comes to 100% width.
+			// It thinks the body has more padding and more
+			// margin than it really does. It would work to
+			// set the body pad and margin to 0, but we can't
+			// set that and disturb a potential layout.
+			//
+			var self = this;
+			var setWidth = function(){
+				var v = dojo.window.getBox();
+				dojo.style(self.domNode, "width", v.w+"px");
+			}
+			this.connect(window, "resize", function(){
+				setWidth();
+			});
+
+			setWidth();
+		}
+		dojo.addOnLoad(this, "checkNotifications");
+		//this.checkNotifications();
+	},
+
+	notify: function(msg){
+		// 	summary:
+		//		Triggers the bar to display. An internal function,
+		//		but could ne called externally for fun.
+		// tags:
+		//		protected
+		//
+		if(dojo.cookie("disableUpgradeReminders")){
+			return;
+		}
+		if(!this.domNode.parentNode || !this.domNode.parentNode.innerHTML){
+			document.body.appendChild(this.domNode);
+		}
+		dojo.style(this.domNode, "display", "");
+		if(msg){
+			this.set("message", msg);
+		}
+
+	},
+
+	show: function(){
+		//	summary:
+		//		Internal. Shows the bar. Do not call directly.
+		//		Use notify();
+		// tags:
+		//		private
+		//
+		this._bodyMarginTop = dojo.style(dojo.body(), "marginTop");
+		this._size = dojo.contentBox(this.domNode).h;
+		dojo.style(this.domNode, { display:"block", height:0, opacity:0 });
+
+		if(!this._showAnim){
+			this._showAnim = dojo.fx.combine([
+				dojo.animateProperty({ node:dojo.body(), duration:500, properties:{ marginTop:this._bodyMarginTop+this._size } }),
+				dojo.animateProperty({ node:this.domNode, duration:500, properties:{ height:this._size, opacity:1 } })
+			]);
+		}
+		this._showAnim.play();
+	},
+
+	hide: function(){
+		//	summary:
+		//		Hides the bar. May be called externally.
+		//
+		if(!this._hideAnim){
+			this._hideAnim = dojo.fx.combine([
+				dojo.animateProperty({ node:dojo.body(), duration:500, properties:{ marginTop:this._bodyMarginTop } }),
+				dojo.animateProperty({ node:this.domNode, duration:500, properties:{ height:0, opacity:0 } })
+			]);
+			dojo.connect(this._hideAnim, "onEnd", this, function(){
+				dojo.style(this.domNode, "display", "none");
+			});
+		}
+		this._hideAnim.play();
+	},
+
+	_onDontRemindClick: function(){
+		// summary:
+		//		Called when user clicks the "do not remind" link.
+		// tags:
+		//		private
+		dojo.cookie("disableUpgradeReminders", true, { expires:3650 });
+		this.hide();
+	},
+
+	_onCloseEnter: function(){
+		// summary:
+		//		Called when user hovers over close icon
+		// tags:
+		//		private
+		dojo.addClass(this.closeButtonNode, "dojoxUpgradeBarCloseIcon-hover");
+	},
+
+	_onCloseLeave: function(){
+		// summary:
+		//		Called when user stops hovering over close icon
+		// tags:
+		//		private
+		dojo.removeClass(this.closeButtonNode, "dojoxUpgradeBarCloseIcon-hover");
+	}
+
 });
-}
-this._hideAnim.play();
-},_onDontRemindClick:function(){
-dojo.cookie("disableUpgradeReminders",true,{expires:3650});
-this.hide();
-},_onCloseEnter:function(){
-dojo.addClass(this.closeButtonNode,"dojoxUpgradeBarCloseIcon-hover");
-},_onCloseLeave:function(){
-dojo.removeClass(this.closeButtonNode,"dojoxUpgradeBarCloseIcon-hover");
-}});
-}
diff --git a/dojox/widget/UpgradeBar/UpgradeBar.css b/dojox/widget/UpgradeBar/UpgradeBar.css
old mode 100644
new mode 100755
index 2526b90..dea4e7f
--- a/dojox/widget/UpgradeBar/UpgradeBar.css
+++ b/dojox/widget/UpgradeBar/UpgradeBar.css
@@ -13,6 +13,7 @@
 	-moz-box-shadow:0 1px 6px #444;
 	font-size:.8em;
 }
+
 .dj_ie .dojoxUpgradeBar {
 	border-bottom:#665F48 2px solid;
 }
@@ -27,6 +28,16 @@
 .dojoxUpgradeBarMessage a{
 	margin-left:10px;
 }
+/*
+.dojoxUpgradeBarControls {
+	position:absolute;
+	right:35px;
+	top:0;
+	bottom:0;
+	width:140px;
+	text-align:right;
+}
+*/
 .dojoxUpgradeBarReminderButton {
 	position:absolute;
 	top:25%;
@@ -40,6 +51,7 @@
 .dj_ie6 .dojoxUpgradeBarReminderButton {
 	margin-top:2px;
 }
+
 .dojoxUpgradeBarCloseIcon {
 	background: url("../../../dijit/themes/tundra/images/tabClose.png") no-repeat right top;
 	position: absolute;
diff --git a/dojox/widget/Wizard.js b/dojox/widget/Wizard.js
index bd96723..2e2cb5f 100644
--- a/dojox/widget/Wizard.js
+++ b/dojox/widget/Wizard.js
@@ -1,108 +1,199 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.Wizard"]){
-dojo._hasResource["dojox.widget.Wizard"]=true;
 dojo.provide("dojox.widget.Wizard");
+
 dojo.require("dijit.layout.StackContainer");
 dojo.require("dijit.layout.ContentPane");
 dojo.require("dijit.form.Button");
-dojo.require("dojo.i18n");
-dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.requireLocalization("dojox.widget","Wizard",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ru,sk,sl,sv,th,tr,zh,zh-tw");
-dojo.declare("dojox.widget.Wizard",[dijit.layout.StackContainer,dijit._Templated],{widgetsInTemplate:true,templateString:dojo.cache("dojox.widget","Wizard/Wizard.html","<div class=\"dojoxWizard\" dojoAttachPoint=\"wizardNode\">\n    <div class=\"dojoxWizardContainer\" dojoAttachPoint=\"containerNode\"></div>\n    <div class=\"dojoxWizardButtons\" dojoAttachPoint=\"wizardNav\">\n        <button dojoType=\"dijit.form.Button\" type=\"button\" dojoAttachPoint=\"previousButton\">${previousBut [...]
-this.inherited(arguments);
-var _1=dojo.mixin({cancel:dojo.i18n.getLocalization("dijit","common",this.lang).buttonCancel},dojo.i18n.getLocalization("dojox.widget","Wizard",this.lang));
-var _2;
-for(_2 in _1){
-if(!this[_2+"ButtonLabel"]){
-this[_2+"ButtonLabel"]=_1[_2];
-}
-}
-},startup:function(){
-if(this._started){
-return;
-}
-this.inherited(arguments);
-this.connect(this.nextButton,"onClick","_forward");
-this.connect(this.previousButton,"onClick","back");
-if(this.cancelFunction){
-if(dojo.isString(this.cancelFunction)){
-this.cancelFunction=dojo.getObject(this.cancelFunction);
-}
-this.connect(this.cancelButton,"onClick",this.cancelFunction);
-}else{
-this.cancelButton.domNode.style.display="none";
-}
-this.connect(this.doneButton,"onClick","done");
-this._subscription=dojo.subscribe(this.id+"-selectChild",dojo.hitch(this,"_checkButtons"));
-this._checkButtons();
-this._started=true;
-},_checkButtons:function(){
-var sw=this.selectedChildWidget;
-var _3=sw.isLastChild;
-this.nextButton.attr("disabled",_3);
-this._setButtonClass(this.nextButton);
-if(sw.doneFunction){
-this.doneButton.domNode.style.display="";
-if(_3){
-this.nextButton.domNode.style.display="none";
-}
-}else{
-this.doneButton.domNode.style.display="none";
-}
-this.previousButton.attr("disabled",!this.selectedChildWidget.canGoBack);
-this._setButtonClass(this.previousButton);
-},_setButtonClass:function(_4){
-_4.domNode.style.display=(this.hideDisabled&&_4.disabled)?"none":"";
-},_forward:function(){
-if(this.selectedChildWidget._checkPass()){
-this.forward();
-}
-},done:function(){
-this.selectedChildWidget.done();
-},destroy:function(){
-dojo.unsubscribe(this._subscription);
-this.inherited(arguments);
-}});
-dojo.declare("dojox.widget.WizardPane",dijit.layout.ContentPane,{canGoBack:true,passFunction:null,doneFunction:null,startup:function(){
-this.inherited(arguments);
-if(this.isFirstChild){
-this.canGoBack=false;
-}
-if(dojo.isString(this.passFunction)){
-this.passFunction=dojo.getObject(this.passFunction);
-}
-if(dojo.isString(this.doneFunction)&&this.doneFunction){
-this.doneFunction=dojo.getObject(this.doneFunction);
-}
-},_onShow:function(){
-if(this.isFirstChild){
-this.canGoBack=false;
-}
-this.inherited(arguments);
-},_checkPass:function(){
-var r=true;
-if(this.passFunction&&dojo.isFunction(this.passFunction)){
-var _5=this.passFunction();
-switch(typeof _5){
-case "boolean":
-r=_5;
-break;
-case "string":
-alert(_5);
-r=false;
-break;
-}
-}
-return r;
-},done:function(){
-if(this.doneFunction&&dojo.isFunction(this.doneFunction)){
-this.doneFunction();
-}
-}});
-}
+
+dojo.require("dojo.i18n"); 
+dojo.requireLocalization("dijit", "common"); 
+dojo.requireLocalization("dojox.widget", "Wizard"); 
+
+dojo.declare(
+	"dojox.widget.Wizard",
+	[dijit.layout.StackContainer, dijit._Templated],
+	{
+	// summary:
+	//		A set of panels that display sequentially, typically notating a step-by-step
+	//		procedure like an install
+	//
+	
+	widgetsInTemplate: true,
+	templateString: dojo.cache("dojox.widget", "Wizard/Wizard.html"),
+	
+	// nextButtonLabel: String
+	//		Label override for the "Next" button.
+	nextButtonLabel: "",
+
+	// previousButtonLabel: String
+	//		Label override for the "Previous" button.
+	previousButtonLabel: "",
+
+	// cancelButtonLabel: String
+	//		Label override for the "Cancel" button.
+	cancelButtonLabel: "",
+
+	// doneButtonLabel: String
+	//		Label override for the "Done" button.
+	doneButtonLabel: "",
+
+	// cancelFunction: Function|String
+	//		Name of function to call if user presses cancel button.
+	//		Cancel button is not displayed if function is not specified.
+	cancelFunction: null,
+
+	// hideDisabled: Boolean
+	//		If true, disabled buttons are hidden; otherwise, they are assigned the
+	//		"WizardButtonDisabled" CSS class
+	hideDisabled: false,
+
+	postMixInProperties: function(){
+		this.inherited(arguments);
+		var labels = dojo.mixin({cancel: dojo.i18n.getLocalization("dijit", "common", this.lang).buttonCancel},
+			dojo.i18n.getLocalization("dojox.widget", "Wizard", this.lang));
+		var prop;
+		for(prop in labels){
+			if(!this[prop + "ButtonLabel"]){
+				this[prop + "ButtonLabel"] = labels[prop];
+			}
+		}
+	},
+
+	startup: function(){
+		if(this._started){ 
+			//console.log('started'); 
+			return; 
+		}
+		this.inherited(arguments);
+		
+		this.connect(this.nextButton, "onClick", "_forward");
+		this.connect(this.previousButton, "onClick", "back");
+
+		if(this.cancelFunction){
+			if(dojo.isString(this.cancelFunction)){
+				this.cancelFunction = dojo.getObject(this.cancelFunction);
+			}
+			this.connect(this.cancelButton, "onClick", this.cancelFunction);
+		}else{
+			this.cancelButton.domNode.style.display = "none";
+		}
+		this.connect(this.doneButton, "onClick", "done");
+
+		this._subscription = dojo.subscribe(this.id + "-selectChild", dojo.hitch(this,"_checkButtons"));
+		this._checkButtons();
+		this._started = true;
+		
+	},
+
+	_checkButtons: function(){
+		
+		var sw = this.selectedChildWidget;
+		
+		var lastStep = sw.isLastChild;
+		this.nextButton.set("disabled", lastStep);
+		this._setButtonClass(this.nextButton);
+		if(sw.doneFunction){
+			//console.log(sw.doneFunction);
+			this.doneButton.domNode.style.display = "";
+			if(lastStep){
+				this.nextButton.domNode.style.display = "none";
+			}
+		}else{
+			// #1438 issue here.
+			this.doneButton.domNode.style.display = "none";
+		}
+		this.previousButton.set("disabled", !this.selectedChildWidget.canGoBack);
+		this._setButtonClass(this.previousButton);
+	},
+
+	_setButtonClass: function(button){
+		button.domNode.style.display = (this.hideDisabled && button.disabled) ? "none" : "";	
+	},
+
+	_forward: function(){
+		// summary: callback when next button is clicked
+		if(this.selectedChildWidget._checkPass()){
+			this.forward();
+		}
+	},
+	
+	done: function(){
+		// summary: Finish the wizard's operation
+		this.selectedChildWidget.done();
+	},
+	
+	destroy: function(){
+		dojo.unsubscribe(this._subscription);
+		this.inherited(arguments);
+	}
+	
+});
+
+dojo.declare("dojox.widget.WizardPane",
+	dijit.layout.ContentPane,
+	{
+	// summary: A panel in a `dojox.widget.Wizard`
+	//
+	// description:
+	//	An extended ContentPane with additional hooks for passing named
+	//	functions to prevent the pane from going either forward or
+	//	backwards. 
+	//
+	// canGoBack: Boolean
+	//		If true, then can move back to a previous panel (by clicking the "Previous" button)
+	canGoBack: true,
+
+	// passFunction: String
+	//		Name of function that checks if it's OK to advance to the next panel.
+	//		If it's not OK (for example, mandatory field hasn't been entered), then
+	//		returns an error message (String) explaining the reason.
+	passFunction: null,
+	
+	// doneFunction: String
+	//		Name of function that is run if you press the "Done" button from this panel
+	doneFunction: null,
+
+	startup: function(){
+		this.inherited(arguments);
+		if(this.isFirstChild){ this.canGoBack = false; }
+		if(dojo.isString(this.passFunction)){
+			this.passFunction = dojo.getObject(this.passFunction);
+		}
+		if(dojo.isString(this.doneFunction) && this.doneFunction){
+			this.doneFunction = dojo.getObject(this.doneFunction);
+		}
+	},
+
+	_onShow: function(){
+		if(this.isFirstChild){ this.canGoBack = false; }
+		this.inherited(arguments);
+	},
+
+	_checkPass: function(){
+		// summary:
+		//		Called when the user presses the "next" button.
+		//		Calls passFunction to see if it's OK to advance to next panel, and
+		//		if it isn't, then display error.
+		//		Returns true to advance, false to not advance. If passFunction
+		//		returns a string, it is assumed to be a custom error message, and
+		//		is alert()'ed
+		var r = true;
+		if(this.passFunction && dojo.isFunction(this.passFunction)){
+			var failMessage = this.passFunction();
+			switch(typeof failMessage){
+				case "boolean":
+					r = failMessage;
+					break;
+				case "string":
+					alert(failMessage);
+					r = false;
+					break;
+			}
+		}
+		return r; // Boolean
+	},
+
+	done: function(){
+		if(this.doneFunction && dojo.isFunction(this.doneFunction)){ this.doneFunction(); }
+	}
+
+});
diff --git a/dojox/widget/Wizard/Wizard.css b/dojox/widget/Wizard/Wizard.css
index f1a9177..d760993 100644
--- a/dojox/widget/Wizard/Wizard.css
+++ b/dojox/widget/Wizard/Wizard.css
@@ -1,11 +1,13 @@
 .dojoxWizard {
 	position:relative; 
 }
+
 .dojoxWizardButtons {
 	position:absolute;
 	bottom:5px;
 	right:5px;	
 }
+
 .tundra .dojoxWizard {
 	background: #eeeeee;
 	border: #b7b7b7 1px solid;
@@ -13,7 +15,13 @@
 	-moz-border-radius:3pt;
 	-webkit-border-radius:4pt;
 }
+
 .soria .dojoxWizard {
 	border:1px solid #b7b7b7;
 	padding:2px;
 }
+
+.claro .dojoxWizard {
+    border:1px solid #b5bcc7;
+    padding:2px;
+}
\ No newline at end of file
diff --git a/dojox/widget/gauge/AnalogArcIndicator.js b/dojox/widget/gauge/AnalogArcIndicator.js
index 8aa9d61..e124c77 100644
--- a/dojox/widget/gauge/AnalogArcIndicator.js
+++ b/dojox/widget/gauge/AnalogArcIndicator.js
@@ -1,69 +1,66 @@
-/*
-	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
-*/
+dojo.provide('dojox.widget.gauge.AnalogArcIndicator');
+dojo.require('dojox.widget.AnalogGauge');
 
-
-if(!dojo._hasResource["dojox.widget.gauge.AnalogArcIndicator"]){
-dojo._hasResource["dojox.widget.gauge.AnalogArcIndicator"]=true;
-dojo.provide("dojox.widget.gauge.AnalogArcIndicator");
-dojo.require("dojox.widget.AnalogGauge");
 dojo.experimental("dojox.widget.gauge.AnalogArcIndicator");
-dojo.declare("dojox.widget.gauge.AnalogArcIndicator",[dojox.widget.gauge.AnalogLineIndicator],{_createArc:function(_1){
-if(this.shapes[0]){
-var a=this._gauge._getRadians(this._gauge._getAngle(_1));
-var _2=Math.cos(a);
-var _3=Math.sin(a);
-var sa=this._gauge._getRadians(this._gauge.startAngle);
-var _4=Math.cos(sa);
-var _5=Math.sin(sa);
-var _6=this.offset+this.width;
-var p=["M"];
-p.push(this._gauge.cx+this.offset*_5);
-p.push(this._gauge.cy-this.offset*_4);
-p.push("A",this.offset,this.offset,0,((a-sa)>Math.PI)?1:0,1);
-p.push(this._gauge.cx+this.offset*_3);
-p.push(this._gauge.cy-this.offset*_2);
-p.push("L");
-p.push(this._gauge.cx+_6*_3);
-p.push(this._gauge.cy-_6*_2);
-p.push("A",_6,_6,0,((a-sa)>Math.PI)?1:0,0);
-p.push(this._gauge.cx+_6*_5);
-p.push(this._gauge.cy-_6*_4);
-this.shapes[0].setShape(p.join(" "));
-this.currentValue=_1;
-}
-},draw:function(_7){
-var v=this.value;
-if(v<this._gauge.min){
-v=this._gauge.min;
-}
-if(v>this._gauge.max){
-v=this._gauge.max;
-}
-if(this.shapes){
-if(_7){
-this._createArc(v);
-}else{
-var _8=new dojo.Animation({curve:[this.currentValue,v],duration:this.duration,easing:this.easing});
-dojo.connect(_8,"onAnimate",dojo.hitch(this,this._createArc));
-_8.play();
-}
-}else{
-var _9={color:this.color,width:1};
-if(this.color.type){
-_9.color=this.color.colors[0].color;
-}
-this.shapes=[this._gauge.surface.createPath().setStroke(_9).setFill(this.color)];
-this._createArc(v);
-if(this.hover){
-this.shapes[0].getEventSource().setAttribute("hover",this.hover);
-}
-if(this.onDragMove&&!this.noChange){
-this._gauge.connect(this.shapes[0].getEventSource(),"onmousedown",this._gauge.handleMouseDown);
-this.shapes[0].getEventSource().style.cursor="pointer";
-}
-}
-}});
-}
+
+dojo.declare("dojox.widget.gauge.AnalogArcIndicator",[dojox.widget.gauge.AnalogLineIndicator],{
+	_createArc: function(val){
+		// Creating the Arc Path string manually.  This is instead of creating new dojox.gfx.Path object
+		// each time since we really just need the Path string (to use with setShape) and we don't want to 
+		// have to redo the connects, etc.
+		if(this.shapes[0]){
+			var a = this._gauge._getRadians(this._gauge._getAngle(val));
+			var cosa = Math.cos(a);
+			var sina = Math.sin(a);
+			var sa = this._gauge._getRadians(this._gauge.startAngle);
+			var cossa = Math.cos(sa);
+			var sinsa = Math.sin(sa);
+			var off = this.offset + this.width;
+			var p = ['M'];
+			p.push(this._gauge.cx+this.offset*sinsa);
+			p.push(this._gauge.cy-this.offset*cossa);
+			p.push('A', this.offset, this.offset, 0, ((a-sa)>Math.PI)?1:0, 1);
+			p.push(this._gauge.cx+this.offset*sina);
+			p.push(this._gauge.cy-this.offset*cosa);
+			p.push('L');
+			p.push(this._gauge.cx+off*sina);
+			p.push(this._gauge.cy-off*cosa);
+			p.push('A', off, off, 0, ((a-sa)>Math.PI)?1:0, 0);
+			p.push(this._gauge.cx+off*sinsa);
+			p.push(this._gauge.cy-off*cossa);
+			this.shapes[0].setShape(p.join(' '));
+			this.currentValue = val;
+		}
+	},
+	draw: function(/*Boolean?*/ dontAnimate){
+		// summary: 
+		//		Override of dojox.widget._Indicator.draw
+		var v = this.value;
+		if(v < this._gauge.min){v = this._gauge.min;}
+		if(v > this._gauge.max){v = this._gauge.max;}
+		if(this.shapes){
+			if(dontAnimate){
+				this._createArc(v);
+			}else{
+				var anim = new dojo.Animation({curve: [this.currentValue, v], duration: this.duration, easing: this.easing});
+				dojo.connect(anim, "onAnimate", dojo.hitch(this, this._createArc));
+				anim.play();
+			}
+		}else{
+			var stroke = {color: this.color, width: 1};
+			if(this.color.type){
+				stroke.color = this.color.colors[0].color;
+			}
+			this.shapes = [this._gauge.surface.createPath()
+							.setStroke(stroke).setFill(this.color)];
+			this._createArc(v);
+			if(this.hover){
+				this.shapes[0].getEventSource().setAttribute('hover',this.hover);
+			}
+			if(this.onDragMove && !this.noChange){
+				this._gauge.connect(this.shapes[0].getEventSource(), 'onmousedown', this._gauge.handleMouseDown);
+				this.shapes[0].getEventSource().style.cursor = 'pointer';
+			}
+		}
+	}
+});
diff --git a/dojox/widget/gauge/AnalogArrowIndicator.js b/dojox/widget/gauge/AnalogArrowIndicator.js
index 6d3b650..4e6d00d 100644
--- a/dojox/widget/gauge/AnalogArrowIndicator.js
+++ b/dojox/widget/gauge/AnalogArrowIndicator.js
@@ -1,28 +1,37 @@
-/*
-	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
-*/
+dojo.provide('dojox.widget.gauge.AnalogArrowIndicator');
+dojo.require('dojox.widget.AnalogGauge');
 
-
-if(!dojo._hasResource["dojox.widget.gauge.AnalogArrowIndicator"]){
-dojo._hasResource["dojox.widget.gauge.AnalogArrowIndicator"]=true;
-dojo.provide("dojox.widget.gauge.AnalogArrowIndicator");
-dojo.require("dojox.widget.AnalogGauge");
 dojo.experimental("dojox.widget.gauge.AnalogArrowIndicator");
-dojo.declare("dojox.widget.gauge.AnalogArrowIndicator",[dojox.widget.gauge.AnalogLineIndicator],{_getShapes:function(){
-if(!this._gauge){
-return null;
-}
-var x=Math.floor(this.width/2);
-var _1=this.width*5;
-var _2=(this.width&1);
-var _3=[];
-var _4=[{x:-x,y:0},{x:-x,y:-this.length+_1},{x:-2*x,y:-this.length+_1},{x:0,y:-this.length},{x:2*x+_2,y:-this.length+_1},{x:x+_2,y:-this.length+_1},{x:x+_2,y:0},{x:-x,y:0}];
-_3[0]=this._gauge.surface.createPolyline(_4).setStroke({color:this.color}).setFill(this.color);
-_3[1]=this._gauge.surface.createLine({x1:-x,y1:0,x2:-x,y2:-this.length+_1}).setStroke({color:this.highlight});
-_3[2]=this._gauge.surface.createLine({x1:-x-3,y1:-this.length+_1,x2:0,y2:-this.length}).setStroke({color:this.highlight});
-_3[3]=this._gauge.surface.createCircle({cx:0,cy:0,r:this.width}).setStroke({color:this.color}).setFill(this.color);
-return _3;
-}});
-}
+
+dojo.declare("dojox.widget.gauge.AnalogArrowIndicator",[dojox.widget.gauge.AnalogLineIndicator],{
+	_getShapes: function(){
+		// summary: 
+		//		Override of dojox.widget.AnalogLineIndicator._getShapes
+		if(!this._gauge){
+			return null;
+		}
+		var x = Math.floor(this.width/2);
+		var head = this.width * 5;
+		var odd = (this.width & 1);
+		var shapes = [];
+		var points = [{x:-x,	 y:0},
+					  {x:-x,	 y:-this.length+head},
+					  {x:-2*x,	 y:-this.length+head},
+					  {x:0,		 y:-this.length},
+					  {x:2*x+odd,y:-this.length+head},
+					  {x:x+odd,	 y:-this.length+head},
+					  {x:x+odd,	 y:0},
+					  {x:-x,	 y:0}];
+		shapes[0] = this._gauge.surface.createPolyline(points)
+					.setStroke({color: this.color})
+					.setFill(this.color);
+		shapes[1] = this._gauge.surface.createLine({ x1:-x, y1: 0, x2: -x, y2:-this.length+head })
+					.setStroke({color: this.highlight});
+		shapes[2] = this._gauge.surface.createLine({ x1:-x-3, y1: -this.length+head, x2: 0, y2:-this.length })
+					.setStroke({color: this.highlight});
+		shapes[3] = this._gauge.surface.createCircle({cx: 0, cy: 0, r: this.width})
+					.setStroke({color: this.color})
+					.setFill(this.color);
+		return shapes;
+	}
+});
diff --git a/dojox/widget/gauge/AnalogNeedleIndicator.js b/dojox/widget/gauge/AnalogNeedleIndicator.js
index 95c1b50..4a139d3 100644
--- a/dojox/widget/gauge/AnalogNeedleIndicator.js
+++ b/dojox/widget/gauge/AnalogNeedleIndicator.js
@@ -1,30 +1,31 @@
-/*
-	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
-*/
+dojo.provide('dojox.widget.gauge.AnalogNeedleIndicator');
+dojo.require('dojox.widget.AnalogGauge');
 
-
-if(!dojo._hasResource["dojox.widget.gauge.AnalogNeedleIndicator"]){
-dojo._hasResource["dojox.widget.gauge.AnalogNeedleIndicator"]=true;
-dojo.provide("dojox.widget.gauge.AnalogNeedleIndicator");
-dojo.require("dojox.widget.AnalogGauge");
 dojo.experimental("dojox.widget.gauge.AnalogNeedleIndicator");
-dojo.declare("dojox.widget.gauge.AnalogNeedleIndicator",[dojox.widget.gauge.AnalogLineIndicator],{_getShapes:function(){
-if(!this._gauge){
-return null;
-}
-var x=Math.floor(this.width/2);
-var _1=this.width*5;
-var _2=(this.width&1);
-var _3=[];
-var _4={color:this.color,width:1};
-if(this.color.type){
-_4.color=this.color.colors[0].color;
-}
-var xy=(Math.sqrt(2)*(x));
-_3[0]=this._gauge.surface.createPath().setStroke(_4).setFill(this.color).moveTo(xy,-xy).arcTo((2*x),(2*x),0,0,0,-xy,-xy).lineTo(0,-this.length).closePath();
-_3[1]=this._gauge.surface.createCircle({cx:0,cy:0,r:this.width}).setStroke({color:this.color}).setFill(this.color);
-return _3;
-}});
-}
+
+dojo.declare("dojox.widget.gauge.AnalogNeedleIndicator",[dojox.widget.gauge.AnalogLineIndicator],{
+	_getShapes: function(){
+		// summary: 
+		//		Override of dojox.widget.AnalogLineIndicator._getShapes
+		if(!this._gauge){
+			return null;
+		}
+		var x = Math.floor(this.width/2);
+		var head = this.width * 5;
+		var odd = (this.width & 1);
+		var shapes = [];
+		var stroke = {color: this.color, width: 1};
+		if(this.color.type){
+			stroke.color = this.color.colors[0].color;
+		}
+		var xy = (Math.sqrt(2) * (x));
+		shapes[0] = this._gauge.surface.createPath()
+					.setStroke(stroke).setFill(this.color)
+					.moveTo(xy, -xy).arcTo((2*x), (2*x), 0, 0, 0, -xy, -xy)
+					.lineTo(0, -this.length).closePath();
+		shapes[1] = this._gauge.surface.createCircle({cx: 0, cy: 0, r: this.width})
+					.setStroke({color: this.color})
+					.setFill(this.color);
+		return shapes;
+	}
+});
diff --git a/dojox/widget/gauge/BarIndicator.js b/dojox/widget/gauge/BarIndicator.js
index dfd6342..2a5f3e6 100644
--- a/dojox/widget/gauge/BarIndicator.js
+++ b/dojox/widget/gauge/BarIndicator.js
@@ -1,80 +1,72 @@
-/*
-	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
-*/
+dojo.provide('dojox.widget.gauge.BarIndicator');
+dojo.require('dojox.widget.BarGauge');
 
-
-if(!dojo._hasResource["dojox.widget.gauge.BarIndicator"]){
-dojo._hasResource["dojox.widget.gauge.BarIndicator"]=true;
-dojo.provide("dojox.widget.gauge.BarIndicator");
-dojo.require("dojox.widget.BarGauge");
 dojo.experimental("dojox.widget.gauge.BarIndicator");
-dojo.declare("dojox.widget.gauge.BarIndicator",[dojox.widget.gauge.BarLineIndicator],{_getShapes:function(){
-if(!this._gauge){
-return null;
-}
-var v=this.value;
-if(v<this._gauge.min){
-v=this._gauge.min;
-}
-if(v>this._gauge.max){
-v=this._gauge.max;
-}
-var _1=this._gauge._getPosition(v);
-if(_1==this.dataX){
-_1=this.dataX+1;
-}
-var y=this._gauge.dataY+Math.floor((this._gauge.dataHeight-this.width)/2)+this.offset;
-var _2=[];
-_2[0]=this._gauge.surface.createRect({x:this._gauge.dataX,y:y,width:_1-this._gauge.dataX,height:this.width});
-_2[0].setStroke({color:this.color});
-_2[0].setFill(this.color);
-_2[1]=this._gauge.surface.createLine({x1:this._gauge.dataX,y1:y,x2:_1,y2:y});
-_2[1].setStroke({color:this.highlight});
-if(this.highlight2){
-y--;
-_2[2]=this._gauge.surface.createLine({x1:this._gauge.dataX,y1:y,x2:_1,y2:y});
-_2[2].setStroke({color:this.highlight2});
-}
-return _2;
-},_createShapes:function(_3){
-for(var i in this.shapes){
-i=this.shapes[i];
-var _4={};
-for(var j in i){
-_4[j]=i[j];
-}
-if(i.shape.type=="line"){
-_4.shape.x2=_3+_4.shape.x1;
-}else{
-if(i.shape.type=="rect"){
-_4.width=_3;
-}
-}
-i.setShape(_4);
-}
-},_move:function(_5){
-var _6=false;
-var c;
-var v=this.value;
-if(v<this.min){
-v=this.min;
-}
-if(v>this.max){
-v=this.max;
-}
-c=this._gauge._getPosition(this.currentValue);
-this.currentValue=v;
-v=this._gauge._getPosition(v)-this._gauge.dataX;
-if(_5){
-this._createShapes(v);
-}else{
-if(c!=v){
-var _7=new dojo.Animation({curve:[c,v],duration:this.duration,easing:this.easing});
-dojo.connect(_7,"onAnimate",dojo.hitch(this,this._createShapes));
-_7.play();
-}
-}
-}});
-}
+
+dojo.declare("dojox.widget.gauge.BarIndicator",[dojox.widget.gauge.BarLineIndicator],{
+	_getShapes: function(){
+		// summary:
+		//		Override of dojox.widget.BarLineIndicator._getShapes
+		if(!this._gauge){
+			return null;
+		}
+		var v = this.value;
+		if(v < this._gauge.min){v = this._gauge.min;}
+		if(v > this._gauge.max){v = this._gauge.max;}
+		var pos = this._gauge._getPosition(v);
+		if(pos == this.dataX){pos = this.dataX+1;}
+		var y = this._gauge.dataY + Math.floor((this._gauge.dataHeight - this.width)/2) + this.offset;
+
+		var shapes = [];
+		shapes[0] = this._gauge.surface.createRect({x:this._gauge.dataX, y:y, width:pos - this._gauge.dataX, height:this.width});
+		shapes[0].setStroke({color: this.color});
+		shapes[0].setFill(this.color);
+		shapes[1] = this._gauge.surface.createLine({ x1:this._gauge.dataX, y1:y, x2:pos, y2:y });
+		shapes[1].setStroke({color: this.highlight});
+		if(this.highlight2){
+			y--;
+			shapes[2] = this._gauge.surface.createLine({ x1:this._gauge.dataX, y1:y, x2:pos, y2:y });
+			shapes[2].setStroke({color: this.highlight2});
+		}
+
+		return shapes;
+	},
+	_createShapes: function(val){
+		// summary:
+		//		Creates a shallow copy of the current shapes while adjusting for the new value
+		for(var i in this.shapes){
+			i = this.shapes[i];
+			var newShape = {};
+			for(var j in i){
+				newShape[j] = i[j];
+			}
+			if(i.shape.type == "line"){
+				newShape.shape.x2 = val+newShape.shape.x1;
+			}else if(i.shape.type == "rect"){
+				newShape.width = val;
+			}
+			i.setShape(newShape);
+		}
+	},
+	_move: function(/*Boolean?*/ dontAnimate){
+		// summary:
+		//		Override of dojox.widget.BarLineIndicator._move to resize the bar (rather than moving it)
+		var changed = false;
+		var c;
+		var v = this.value ;
+		if(v < this.min){v = this.min;}
+		if(v > this.max){v = this.max;}
+		c = this._gauge._getPosition(this.currentValue);
+		this.currentValue = v;
+		v = this._gauge._getPosition(v)-this._gauge.dataX;
+		if(dontAnimate){
+			this._createShapes(v);
+		}else{
+			if(c!=v){
+				var anim = new dojo.Animation({curve: [c, v], duration: this.duration, easing: this.easing});
+				dojo.connect(anim, "onAnimate", dojo.hitch(this, this._createShapes)); 
+				anim.play();
+			}
+		}
+	}
+});
diff --git a/dojox/widget/gauge/_Gauge.css b/dojox/widget/gauge/_Gauge.css
index d2001a7..7eaa756 100644
--- a/dojox/widget/gauge/_Gauge.css
+++ b/dojox/widget/gauge/_Gauge.css
@@ -1,51 +1,63 @@
 @CHARSET "ISO-8859-1";
+
 .dojoxGaugeContent {
 	font-family: Verdana;
 	border-width: 1px;
 	border-style: solid;
 	border-color: #CCCCCC;
 }
+
 .dojoxGaugeRange1 {
 	fill: #606060 ;
 	stroke: #606060 ;
 }
+
 .dojoxGaugeRange2 {
 	fill: #707070 ;
 	stroke: #707070 ;
 }
+
 .dojoxGaugeRange3 {
 	fill: #808080 ;
 	stroke: #808080 ;
 }
+
 .dojoxGaugeRange4 {
 	fill: #909090 ;
 	stroke: #909090 ;
 }
+
 .dojoxGaugeRange5 {
 	fill: #A0A0A0;
 	stroke: #A0A0A0;
 }
+
 .dojoxGaugeRange6 {
 	fill: #B0B0B0;
 	stroke: #B0B0B0;
 }
+
 .dojoxGaugeRange7 {
 	fill: #C0C0C0;
 	stroke: #C0C0C0;
 }
+
 .dojoxGaugeRange8 {
 	fill: #D0D0D0;
 	stroke: #D0D0D0;
 }
+
 .dojoxGaugeRange9 {
 	fill: #E0E0E0;
 	stroke: #E0E0E0;
 }
+
 .dojoxGaugeRange10 {
 	fill: #F0F0F0;
 	stroke: #F0F0F0;
 }
+
 .testing {
 	fill: blue;
 	stroke: blue;
-}
+}
\ No newline at end of file
diff --git a/dojox/widget/gauge/_Gauge.js b/dojox/widget/gauge/_Gauge.js
index d7b6d9a..5ecc4f9 100644
--- a/dojox/widget/gauge/_Gauge.js
+++ b/dojox/widget/gauge/_Gauge.js
@@ -1,13 +1,5 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.gauge._Gauge"]){
-dojo._hasResource["dojox.widget.gauge._Gauge"]=true;
 dojo.provide("dojox.widget.gauge._Gauge");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Templated");
 dojo.require("dijit._Container");
@@ -15,290 +7,750 @@ dojo.require("dijit._Contained");
 dojo.require("dijit.Tooltip");
 dojo.require("dojo.fx.easing");
 dojo.require("dojox.gfx");
+
 dojo.experimental("dojox.widget.gauge._Gauge");
-dojo.declare("dojox.widget.gauge._Gauge",[dijit._Widget,dijit._Templated,dijit._Container],{width:0,height:0,background:null,min:0,max:0,image:null,useRangeStyles:0,useTooltip:true,majorTicks:null,minorTicks:null,_defaultIndicator:null,defaultColors:[[0,84,170,1],[68,119,187,1],[102,153,204,1],[153,187,238,1],[153,204,255,1],[204,238,255,1],[221,238,255,1]],min:null,max:null,surface:null,hideValues:false,gaugeContent:undefined,templateString:dojo.cache("dojox.widget.gauge","_Gauge.html", [...]
-if(this.image===null){
-this.image={};
-}
-this.connect(this.gaugeContent,"onmousemove",this.handleMouseMove);
-this.connect(this.gaugeContent,"onmouseover",this.handleMouseOver);
-this.connect(this.gaugeContent,"onmouseout",this.handleMouseOut);
-this.connect(this.gaugeContent,"onmouseup",this.handleMouseUp);
-if(!dojo.isArray(this.ranges)){
-this.ranges=[];
-}
-if(!dojo.isArray(this.indicators)){
-this.indicators=[];
-}
-var _1=[],_2=[];
-var i;
-if(this.hasChildren()){
-var _3=this.getChildren();
-for(i=0;i<_3.length;i++){
-if(/dojox\.widget\..*Indicator/.test(_3[i].declaredClass)){
-_2.push(_3[i]);
-continue;
-}
-switch(_3[i].declaredClass){
-case "dojox.widget.gauge.Range":
-_1.push(_3[i]);
-break;
-}
-}
-this.ranges=this.ranges.concat(_1);
-this.indicators=this.indicators.concat(_2);
-}
-if(!this.background){
-this.background=this._backgroundDefault;
-}
-this.background=this.background.color||this.background;
-if(!this.surface){
-this.createSurface();
-}
-this.addRanges(this.ranges);
-if(this.minorTicks&&this.minorTicks.interval){
-this.setMinorTicks(this.minorTicks);
-}
-if(this.majorTicks&&this.majorTicks.interval){
-this.setMajorTicks(this.majorTicks);
-}
-for(i=0;i<this.indicators.length;i++){
-this.addIndicator(this.indicators[i]);
-}
-},_setTicks:function(_4,_5,_6){
-var i;
-if(_4&&dojo.isArray(_4._ticks)){
-for(i=0;i<_4._ticks.length;i++){
-this.removeIndicator(_4._ticks[i]);
-}
-}
-var t={length:_5.length,offset:_5.offset,noChange:true};
-if(_5.color){
-t.color=_5.color;
-}
-if(_5.font){
-t.font=_5.font;
-}
-_5._ticks=[];
-for(i=this.min;i<=this.max;i+=_5.interval){
-t.value=i;
-if(_6){
-t.label=""+i;
-}
-_5._ticks.push(this.addIndicator(t));
-}
-return _5;
-},setMinorTicks:function(_7){
-this.minorTicks=this._setTicks(this.minorTicks,_7,false);
-},setMajorTicks:function(_8){
-this.majorTicks=this._setTicks(this.majorTicks,_8,true);
-},postCreate:function(){
-if(this.hideValues){
-dojo.style(this.containerNode,"display","none");
-}
-dojo.style(this.mouseNode,"width","0");
-dojo.style(this.mouseNode,"height","0");
-dojo.style(this.mouseNode,"position","absolute");
-dojo.style(this.mouseNode,"z-index","100");
-if(this.useTooltip){
-dijit.showTooltip("test",this.mouseNode);
-dijit.hideTooltip(this.mouseNode);
-}
-},createSurface:function(){
-this.gaugeContent.style.width=this.width+"px";
-this.gaugeContent.style.height=this.height+"px";
-this.surface=dojox.gfx.createSurface(this.gaugeContent,this.width,this.height);
-this._background=this.surface.createRect({x:0,y:0,width:this.width,height:this.height});
-this._background.setFill(this.background);
-if(this.image.url){
-this._img=this.surface.createImage({width:this.image.width||this.width,height:this.image.height||this.height,src:this.image.url});
-if(this.image.overlay){
-this._img.getEventSource().setAttribute("overlay",true);
-}
-if(this.image.x||this.image.y){
-this._img.setTransform({dx:this.image.x||0,dy:this.image.y||0});
-}
-}
-},setBackground:function(_9){
-if(!_9){
-_9=this._backgroundDefault;
-}
-this.background=_9.color||_9;
-this._background.setFill(this.background);
-},addRange:function(_a){
-this.addRanges([_a]);
-},addRanges:function(_b){
-if(!this._rangeData){
-this._rangeData=[];
-}
-var _c;
-for(var i=0;i<_b.length;i++){
-_c=_b[i];
-if((this.min===null)||(_c.low<this.min)){
-this.min=_c.low;
-}
-if((this.max===null)||(_c.high>this.max)){
-this.max=_c.high;
-}
-if(!_c.color){
-var _d=this._rangeData.length%this.defaultColors.length;
-if(dojox.gfx.svg&&this.useRangeStyles>0){
-_d=(this._rangeData.length%this.useRangeStyles)+1;
-_c.color={style:"dojoxGaugeRange"+_d};
-}else{
-_d=this._rangeData.length%this.defaultColors.length;
-_c.color=this.defaultColors[_d];
-}
-}
-this._rangeData[this._rangeData.length]=_c;
-}
-this.draw();
-},addIndicator:function(_e){
-_e._gauge=this;
-if(!_e.declaredClass){
-_e=new this._defaultIndicator(_e);
-}
-if(!_e.hideValue){
-this.containerNode.appendChild(_e.domNode);
-}
-if(!this._indicatorData){
-this._indicatorData=[];
-}
-this._indicatorData[this._indicatorData.length]=_e;
-_e.draw();
-return _e;
-},removeIndicator:function(_f){
-for(var i=0;i<this._indicatorData.length;i++){
-if(this._indicatorData[i]===_f){
-this._indicatorData.splice(i,1);
-_f.remove();
-break;
-}
-}
-},moveIndicatorToFront:function(_10){
-if(_10.shapes){
-for(var i=0;i<_10.shapes.length;i++){
-_10.shapes[i].moveToFront();
-}
-}
-},drawText:function(txt,x,y,_11,_12,_13,_14){
-var t=this.surface.createText({x:x,y:y,text:txt,align:_11});
-t.setFill(_13);
-t.setFont(_14);
-return t;
-},removeText:function(t){
-this.surface.rawNode.removeChild(t);
-},updateTooltip:function(txt,e){
-if(this._lastHover!=txt){
-if(txt!==""){
-dijit.hideTooltip(this.mouseNode);
-dijit.showTooltip(txt,this.mouseNode);
-}else{
-dijit.hideTooltip(this.mouseNode);
-}
-this._lastHover=txt;
-}
-},handleMouseOver:function(_15){
-var _16=_15.target.getAttribute("hover");
-if(_15.target.getAttribute("overlay")){
-this._overOverlay=true;
-var r=this.getRangeUnderMouse(_15);
-if(r&&r.hover){
-_16=r.hover;
-}
-}
-if(this.useTooltip&&!this._drag){
-if(_16){
-this.updateTooltip(_16,_15);
-}else{
-this.updateTooltip("",_15);
-}
-}
-},handleMouseOut:function(_17){
-if(_17.target.getAttribute("overlay")){
-this._overOverlay=false;
-}
-if(this.useTooltip&&this.mouseNode){
-dijit.hideTooltip(this.mouseNode);
-}
-},handleMouseDown:function(_18){
-for(var i=0;i<this._indicatorData.length;i++){
-var _19=this._indicatorData[i].shapes;
-for(var s=0;s<_19.length;s++){
-if(_19[s].getEventSource()==_18.target){
-this._drag=this._indicatorData[i];
-s=_19.length;
-i=this._indicatorData.length;
-}
-}
-}
-dojo.stopEvent(_18);
-},handleMouseUp:function(_1a){
-this._drag=null;
-dojo.stopEvent(_1a);
-},handleMouseMove:function(_1b){
-if(_1b){
-dojo.style(this.mouseNode,"left",_1b.pageX+1+"px");
-dojo.style(this.mouseNode,"top",_1b.pageY+1+"px");
-}
-if(this._drag){
-this._dragIndicator(this,_1b);
-}else{
-if(this.useTooltip&&this._overOverlay){
-var r=this.getRangeUnderMouse(_1b);
-if(r&&r.hover){
-this.updateTooltip(r.hover,_1b);
-}else{
-this.updateTooltip("",_1b);
-}
-}
-}
-}});
-dojo.declare("dojox.widget.gauge.Range",[dijit._Widget,dijit._Contained],{low:0,high:0,hover:"",color:null,size:0,startup:function(){
-this.color=this.color.color||this.color;
-}});
-dojo.declare("dojox.widget.gauge._Indicator",[dijit._Widget,dijit._Contained,dijit._Templated],{value:0,type:"",color:"black",label:"",font:{family:"sans-serif",size:"12px"},length:0,width:0,offset:0,hover:"",front:false,easing:dojo._defaultEasing,duration:1000,hideValue:false,noChange:false,_gauge:null,title:"",templateString:dojo.cache("dojox.widget.gauge","_Indicator.html","<div class=\"dojoxGaugeIndicatorDiv\">\n\t<label class=\"dojoxGaugeIndicatorLabel\" for=\"${title}\">${title}:</ [...]
-if(this.onDragMove){
-this.onDragMove=dojo.hitch(this.onDragMove);
-}
-},postCreate:function(){
-if(this.title===""){
-dojo.style(this.domNode,"display","none");
-}
-if(dojo.isString(this.easing)){
-this.easing=dojo.getObject(this.easing);
-}
-},_update:function(_1c){
-var _1d=this.valueNode.value;
-if(_1d===""){
-this.value=null;
-}else{
-this.value=Number(_1d);
-this.hover=this.title+": "+_1d;
-}
-if(this._gauge){
-this.draw();
-this.valueNode.value=this.value;
-if((this.title=="Target"||this.front)&&this._gauge.moveIndicator){
-this._gauge.moveIndicatorToFront(this);
-}
-}
-},update:function(_1e){
-if(!this.noChange){
-this.valueNode.value=_1e;
-this._update();
-}
-},onDragMove:function(){
-this.value=Math.floor(this.value);
-this.valueNode.value=this.value;
-this.hover=this.title+": "+this.value;
-},draw:function(_1f){
-},remove:function(){
-for(var i=0;i<this.shapes.length;i++){
-this._gauge.surface.remove(this.shapes[i]);
-}
-if(this.text){
-this._gauge.surface.remove(this.text);
-}
-}});
-}
+
+dojo.declare("dojox.widget.gauge._Gauge",[dijit._Widget, dijit._Templated, dijit._Container],{
+	// summary:
+	//		a gauge built using the dojox.gfx package.
+	//
+	// description:
+	//		using dojo.gfx (and thus either SVG or VML based on what is supported), this widget
+	//		builds a gauge component, used to display numerical data in a familiar format 
+	//
+	// usage:
+	//		this widget is not to be used alone. it is meant to be subclassed, such as
+	//		dojox.widget.BarGauge or dojox.widget.AnalogGauge
+
+	// width: Number
+	// the width of the gauge (default is 300)
+	width: 0,
+
+	// height: Number
+	// the height of the gauge (default is 200)
+	height: 0,
+
+	// background: Object
+	// the color of the background.  This must be an object of one of two forms:
+	// {'color': 'color-name'}
+	// OR
+	// (for a gradient:)
+	// {'type': 'linear', 'x1': 0, 'x2': 0, 'y1': 0, 'y2': 200, 'colors': [{offset: 0, color:'#C0C0C0'}, {offset: 1, color: '#E0E0E0'}] }
+	background: null,
+
+	// min: Number
+	// minimum value displayed by gauge (default is lowest range value)
+	min: 0,
+
+	// max: Number
+	// maximum value displayed by gauge (default is largest range value)
+	max: 0,
+
+	// image: String
+	// background image for gauge (default is no image)
+	image: null,
+
+	// useRangeStyles: Number
+	// indicates whether to use given css classes (dojoxGaugeRangeXX)
+	// to determine the color (and other style attributes?) of the ranges
+	// this value should be the number of dojoxGaugeRange classes that are 
+	// defined, starting at dojoxGaugeRange1 (0 indicates falling to default
+	// hardcoded colors)
+	useRangeStyles: 0,
+
+	// useTooltip: Boolean
+	// indicates whether tooltips should be displayed for ranges, indicators, etc.
+	useTooltip: true,
+	
+	// majorTicks: Object
+	// An object representing the tick marks that should be added to the gauge. Major tick marks have a text label
+	// indicating the value.  The object can have the following attributes (required are marked with a *):
+	//		offset: the distance from the 'center' of the gauge.  Used differently for Analog vs. Bar
+	//		width: The width of the mark
+	//		length: The length of the mark
+	//		interval: The interval the ticks should be added on
+	//		color: The color of the mark and text
+	//		font: an object with any/all of the following parameters:
+	//			{family: "Helvetica", style: "italic", variant: 'small-caps', weight: 'bold', size: "18pt"}
+	majorTicks: null,
+	
+	// minorTicks: Object
+	// An object of the same format as majorTicks, indicating where the minor (label-less) marks should be placed
+	// The font parameter is ignored if provided since minor tick marks have no text label.
+	minorTicks: null,
+
+	// _defaultIndicator: Objection
+	// Should be overridden by any extending classes and used to indicate what the 'default' indicator is.
+	// This object is used as the indicator when creating tick marks or when an anonmyous object is passed into 
+	// addIndicator.
+	_defaultIndicator: null,
+
+	// defaultColors: Array
+	// Set of default colors to color ranges with.
+	defaultColors: [[0x00,0x54,0xAA,1],
+					[0x44,0x77,0xBB,1],
+					[0x66,0x99,0xCC,1],
+					[0x99,0xBB,0xEE,1],
+					[0x99,0xCC,0xFF,1],
+					[0xCC,0xEE,0xFF,1],
+					[0xDD,0xEE,0xFF,1]],
+	
+	// min: Number
+	// The minimum value of the gauge.  Normally not set explicitly, as it will be determined by
+	// the ranges that are added.
+	min: null,
+	
+	// max: Number
+	// The maximum value of the gauge.  Normally not set explicitly, as it will be determined by
+	// the ranges that are added.
+	max: null,
+	
+	// surface: Object
+	// The SVG/VML surface that the shapes are drawn on.  Can be accessed/used by indicators to draw themselves
+	surface: null,
+
+	// hideValues: Boolean
+	// indicates whether the text boxes showing the value of the indicator (as text 
+	// content) should be hidden or shown.  Default is not hidden, aka shown.
+	hideValues: false,
+
+	// internal data
+	gaugeContent: undefined,
+	templateString: dojo.cache("dojox.widget.gauge", "_Gauge.html"),
+	_backgroundDefault: {color: '#E0E0E0'},
+	_rangeData: null,
+	_indicatorData: null,
+	_drag: null,
+	_img: null,
+	_overOverlay: false,
+	_lastHover: '',
+
+	startup: function(){
+		// handle settings from HTML by making sure all the options are
+		// converted correctly to numbers and that we calculate defaults
+		// for cx, cy and radius
+		if(this.image === null){
+			this.image={};
+		}
+
+		this.connect(this.gaugeContent, 'onmousemove', this.handleMouseMove);
+		this.connect(this.gaugeContent, 'onmouseover', this.handleMouseOver);
+		this.connect(this.gaugeContent, 'onmouseout', this.handleMouseOut);
+		this.connect(this.gaugeContent, 'onmouseup', this.handleMouseUp);
+
+		if(!dojo.isArray(this.ranges)){ this.ranges = []; }
+		if(!dojo.isArray(this.indicators)){ this.indicators = []; }
+		var ranges = [], indicators = [];
+		var i;
+		if(this.hasChildren()){
+			var children = this.getChildren();
+			for(i=0; i<children.length; i++){
+				if(/dojox\.widget\..*Indicator/.test(children[i].declaredClass)){
+					indicators.push(children[i]);
+					//this.addIndicator(children[i]);
+					continue;
+				}
+				switch(children[i].declaredClass){
+					case "dojox.widget.gauge.Range":
+						ranges.push(children[i]);
+						break;
+				}
+			}
+			this.ranges = this.ranges.concat(ranges);
+			this.indicators = this.indicators.concat(indicators);
+		}
+		if(!this.background){ this.background = this._backgroundDefault; }
+		this.background = this.background.color || this.background;
+		if(!this.surface){ this.createSurface(); }
+
+		this.addRanges(this.ranges);
+		if(this.minorTicks && this.minorTicks.interval){
+			this.setMinorTicks(this.minorTicks);
+		}
+		if(this.majorTicks && this.majorTicks.interval){
+			this.setMajorTicks(this.majorTicks);
+		}
+		for(i=0; i<this.indicators.length; i++){
+			this.addIndicator(this.indicators[i]);
+		}
+	},
+
+	_setTicks: function(/*Object*/ oldTicks, /*Object*/ newTicks, /*Boolean*/ label){
+		// summary: 
+		//		internal method used to clear existing tick marks, then add new ones
+		var i;
+		if(oldTicks && dojo.isArray(oldTicks._ticks)){
+			for(i=0; i<oldTicks._ticks.length; i++){
+				this.removeIndicator(oldTicks._ticks[i]);
+			}
+		}
+		var t = {length: newTicks.length, 
+					offset: newTicks.offset,
+					noChange: true};
+		if(newTicks.color){ t.color = newTicks.color; }
+		if(newTicks.font){ t.font = newTicks.font; }
+		newTicks._ticks = [];
+		for(i=this.min; i<=this.max; i+=newTicks.interval){
+			t.value = i;
+			if(label){t.label = ''+i;}
+			newTicks._ticks.push(this.addIndicator(t));
+		}
+		return newTicks;
+	},
+	
+	setMinorTicks: function(/*Object*/ ticks){
+		// summary:
+		//		Creates and draws the minor tick marks based on the passed object (expecting the same format
+		//		as the minorTicks object documented above)
+		this.minorTicks = this._setTicks(this.minorTicks, ticks, false);
+	},
+
+	setMajorTicks: function(/*Object*/ ticks){
+		// summary:
+		//		Creates and draws the major tick marks based on the passed object (expecting the same format
+		//		as the majorTicks object documented above)
+		this.majorTicks = this._setTicks(this.majorTicks, ticks, true);
+	},
+
+	postCreate: function(){
+		if(this.hideValues){
+			dojo.style(this.containerNode, "display", "none");
+		}
+		dojo.style(this.mouseNode, 'width', '0');
+		dojo.style(this.mouseNode, 'height', '0');
+		dojo.style(this.mouseNode, 'position', 'absolute');
+		dojo.style(this.mouseNode, 'z-index', '100');
+		if(this.useTooltip){
+			dijit.showTooltip('test',this.mouseNode, !this.isLeftToRight());
+			dijit.hideTooltip(this.mouseNode);
+		}
+	},
+
+	createSurface: function(){
+		// summary:
+		//		internal method used by the gauge to create the graphics surface area
+		this.gaugeContent.style.width = this.width + 'px';
+		this.gaugeContent.style.height = this.height + 'px';
+		this.surface = dojox.gfx.createSurface(this.gaugeContent, this.width, this.height);
+		this._background = this.surface.createRect({x: 0, y: 0, width: this.width, height: this.height });
+		this._background.setFill(this.background);
+
+		if(this.image.url){
+			this._img = this.surface.createImage({width: this.image.width || this.width, height: this.image.height || this.height, src: this.image.url});
+			if(this.image.overlay){
+				this._img.getEventSource().setAttribute('overlay',true);
+			}
+			if(this.image.x || this.image.y){
+				this._img.setTransform({dx: this.image.x || 0, dy: this.image.y || 0});
+			}
+		}
+	},
+
+	setBackground: function(background){
+		// summary:
+		//		This method is used to set the background of the gauge after it is created.
+		// description:
+		//		Sets the background using the given object.  Must be the same 'type' of object 
+		//		as the original background argument.
+		// background:
+		//		An object in one of the two forms:
+		//			{'color': 'color-name'}
+		//				OR
+		//			(for a gradient:)
+		//			{'type': 'linear', 'colors': [{offset: 0, color:'#C0C0C0'}, {offset: 1, color: '#E0E0E0'}] }
+		//		If background is null or undefined, this will set the fill to this._backgroundDefault
+		if(!background){ background = this._backgroundDefault; }
+		this.background = background.color || background;
+		this._background.setFill(this.background);
+	},
+
+	addRange: function(/*Object*/range){
+		// summary:
+		//		This method is used to add a range to the gauge.
+		// description:
+		//		Creates a range (colored area on the background of the gauge)
+		//		based on the given arguments.
+		// range:
+		//		A range is either a dojox.widget.gauge.Range object, or a object
+		//		with similar parameters (low, high, hover, etc.).
+		this.addRanges([range]);
+	},
+
+	addRanges: function(/*Array*/ranges){
+		// summary:
+		//		This method is used to add ranges to the gauge.
+		// description:
+		//		Creates a range (colored area on the background of the gauge) 
+		//		based on the given arguments.
+		// range:
+		//		A range is either a dojox.widget.gauge.Range object, or a object 
+		//		with similar parameters (low, high, hover, etc.).
+		if(!this._rangeData){ 
+			this._rangeData = [];
+		}
+		var range;
+		for(var i=0; i<ranges.length; i++){
+			range = ranges[i];
+			if((this.min === null) || (range.low < this.min)){this.min = range.low;}
+			if((this.max === null) || (range.high > this.max)){this.max = range.high;}
+
+			if(!range.color){
+				var colorIndex = this._rangeData.length % this.defaultColors.length;
+				if(dojox.gfx.svg && this.useRangeStyles > 0){
+					colorIndex = (this._rangeData.length % this.useRangeStyles)+1;
+					range.color = {style: "dojoxGaugeRange"+colorIndex};
+				}else{
+					colorIndex = this._rangeData.length % this.defaultColors.length;
+					range.color = this.defaultColors[colorIndex];
+				}
+			}
+			this._rangeData[this._rangeData.length] = range;
+		}
+		this.draw();
+	},
+
+	addIndicator: function(/*Object*/indicator){
+		// summary:
+		//		This method is used to add an indicator to the bar graph.
+		// description:
+		//		This method adds an indicator, such as a tick mark or needle,
+		//		to the bar graph.
+		// indicator:
+		//		A dojox.widget.gauge._Indicator or an object with similar parameters
+		//		(value, color, offset, etc.).
+
+		indicator._gauge = this;
+		if(!indicator.declaredClass){// !== 'dojox.widget.gauge.Indicator'){
+			// We were passed a plain object, need to make an indicator out of it.
+			indicator = new this._defaultIndicator(indicator);
+		}
+		if(!indicator.hideValue){
+			this.containerNode.appendChild(indicator.domNode);
+		}
+		if(!this._indicatorData){this._indicatorData = [];}
+		this._indicatorData[this._indicatorData.length] = indicator;
+		indicator.draw();
+		return indicator;
+	},
+
+	removeIndicator: function(/*Object*/indicator){
+		// summary:
+		//		Removes the given indicator from the gauge by calling it's remove function 
+		//		and removing it from the local cache.
+		for(var i=0; i<this._indicatorData.length; i++){
+			if(this._indicatorData[i] === indicator){
+				this._indicatorData.splice(i, 1);
+				indicator.remove();
+				break;
+			}
+		}
+	},
+
+	moveIndicatorToFront: function(/*Object*/indicator){
+		// summary:
+		//		This function is used to move an indicator the the front (top)
+		//		of the gauge
+		// indicator:
+		//		A dojox.widget.gauge._Indicator or an object with similar parameters
+		//		(value, color, offset, etc.).
+		if(indicator.shapes){
+			for(var i=0; i<indicator.shapes.length; i++){
+				indicator.shapes[i].moveToFront();
+			}
+		}
+	},
+
+	drawText: function(/*String*/txt, /*Number*/x, /*Number*/y, /*String?*/align, /*String?*/vAlign, /*String?*/color, /*Object?*/font){
+		// summary:
+		//		This function is used draw text onto the gauge.  The text object
+		//		is also returned by the function so that may be removed later
+		//		by calling removeText
+		// txt:		String
+		//			The text to be drawn
+		// x:		Number
+		//			The x coordinate at which to place the text
+		// y:		Number
+		//			The y coordinate at which to place the text
+		// align?:	String
+		//			Indicates how to align the text
+		//			Valid value is 'right', otherwise text is left-aligned
+		// vAlign?:	String
+		//			Indicates how to align the text vertically.
+		//			Valid value is 'top', otherwise text is bottom-aligned
+		// color?:	String
+		//			Indicates the color of the text
+		// font?:	Object
+		//			A font object, generally of the following format:
+		//			{family: "Helvetica", style: "italic", variant: 'small-caps', weight: 'bold', size: "18pt"}
+
+		var t = this.surface.createText({x: x, y: y, text: txt, align: align});
+		t.setFill(color);
+		t.setFont(font);
+		return t;
+	},
+
+	removeText:function(/*String*/t){
+		// summary:
+		//		Removes a text element from the gauge.
+		// t:	String
+		//		The text to remove.
+		this.surface.rawNode.removeChild(t);
+	},
+
+	updateTooltip: function(/*String*/txt, /*Event*/ e){
+		// summary:
+		//		Updates the tooltip for the gauge to display the given text.
+		// txt:		String
+		//			The text to put in the tooltip.
+		if(this._lastHover != txt){
+			if(txt !== ''){ 
+				dijit.hideTooltip(this.mouseNode);
+				dijit.showTooltip(txt,this.mouseNode, !this.isLeftToRight());
+			}else{
+				dijit.hideTooltip(this.mouseNode);
+			}
+			this._lastHover = txt;
+		}
+	},
+
+	handleMouseOver: function(/*Object*/event){
+		// summary:
+		//		This is an internal handler used by the gauge to support 
+		//		hover text
+		// event:	Object
+		//			The event object
+		var hover = event.target.getAttribute('hover');
+		if(event.target.getAttribute('overlay')){
+			this._overOverlay = true;
+			var r = this.getRangeUnderMouse(event);
+			if(r && r.hover){
+				hover = r.hover;
+			}
+		}
+		if(this.useTooltip && !this._drag){
+			if(hover){
+				this.updateTooltip(hover, event);
+			}else{
+				this.updateTooltip('', event);
+			}
+		}
+	},
+
+	handleMouseOut: function(/*Object*/event){
+		// summary:
+		//		This is an internal handler used by the gauge to support 
+		//		hover text
+		// event:	Object
+		//			The event object
+		if(event.target.getAttribute('overlay')){
+			this._overOverlay = false;
+		}
+		if(this.useTooltip && this.mouseNode){
+			dijit.hideTooltip(this.mouseNode);
+		}
+	},
+
+	handleMouseDown: function(/*Object*/event){
+		// summary:
+		//		This is an internal handler used by the gauge to support using
+		//		the mouse to drag an indicator to modify it's value
+		// event:	Object
+		//			The event object
+
+		// find the indicator being dragged
+		for(var i=0; i<this._indicatorData.length; i++){
+			var shapes = this._indicatorData[i].shapes;
+			for(var s=0; s<shapes.length; s++){
+				if(shapes[s].getEventSource() == event.target){
+					 this._drag = this._indicatorData[i];
+					 s = shapes.length;
+					 i = this._indicatorData.length;
+				}
+			}
+		}
+		dojo.stopEvent(event);
+	},
+
+	handleMouseUp: function(/*Object*/event){
+		// summary:
+		//		This is an internal handler used by the gauge to support using
+		//		the mouse to drag an indicator to modify it's value
+		// event:	Object
+		//			The event object
+		this._drag = null;
+		dojo.stopEvent(event);
+	},
+
+	handleMouseMove: function(/*Object*/event){
+		// summary:
+		//		This is an internal handler used by the gauge to support using
+		//		the mouse to drag an indicator to modify it's value
+		// event:	Object
+		//			The event object
+		if(event){
+			dojo.style(this.mouseNode, 'left', event.pageX+1+'px');
+			dojo.style(this.mouseNode, 'top', event.pageY+1+'px');
+		}
+		if(this._drag){
+			this._dragIndicator(this, event);
+		}else{
+			if(this.useTooltip && this._overOverlay){
+				var r = this.getRangeUnderMouse(event);
+				if(r && r.hover){
+					this.updateTooltip(r.hover, event);
+				}else{
+					this.updateTooltip('', event);
+				}
+			}
+		}
+	}
+});
+
+dojo.declare("dojox.widget.gauge.Range",[dijit._Widget, dijit._Contained],{
+	// summary:
+	//		a range to be used in a _Gauge
+	//
+	// description:
+	//		a range widget, which has given properties.  drawn by a _Gauge.
+	//
+	// usage:
+	//		<script type="text/javascript">
+	//			dojo.require("dojox.widget.AnalogGauge");
+	//			dojo.require("dijit.util.parser");
+	//		</script>
+	//		...
+	//		<div	dojoType="dojox.widget.AnalogGauge"
+	//				id="testGauge"
+	//				width="300"
+	//				height="200"
+	//				cx=150
+	//				cy=175
+	//				radius=125
+	//				image="gaugeOverlay.png"
+	//				imageOverlay="false"
+	//				imageWidth="280"
+	//				imageHeight="155"
+	//				imageX="12"
+	//				imageY="38">
+	//			<div	dojoType="dojox.widget.gauge.Range"
+	//					low=5
+	//					high=10
+	//					hover="5 - 10"
+	//			></div>
+	//			<div	dojoType="dojox.widget.gauge.Range"
+	//					low=10
+	//					high=20
+	//					hover="10 - 20"
+	//			></div>
+	//		</div>
+	
+	// low: Number
+	// the low value of the range 
+	low: 0,
+	
+	// high: Numbe
+	// the high value of the range
+	high: 0,
+	
+	// hover: String
+	// the text to put in the tooltip for the gauge
+	hover: '',
+	
+	// color: Object
+	// the color of the range.  This must be an object of one of two forms:
+	// {'color': 'color-name'}
+	// OR
+	// (for a gradient:)
+	// {'type': 'linear', 'colors': [{offset: 0, color:'#C0C0C0'}, {offset: 1, color: '#E0E0E0'}] }
+	color: null,
+	
+	// size: Number
+	// for a circular gauge (such as an AnalogGauge), this dictates the size of the arc 
+	size: 0,
+
+	startup: function(){
+		this.color = this.color.color || this.color;
+	}
+});
+
+dojo.declare("dojox.widget.gauge._Indicator",[dijit._Widget, dijit._Contained, dijit._Templated],{
+	// summary:
+	//		a indicator to be used in a gauge
+	//
+	// description:
+	//		an indicator widget, which has given properties.  drawn by a gauge. 
+	//
+	// usage:
+	//		<script type="text/javascript">
+	//			dojo.require("dojox.widget.AnalogGauge");
+	//			dojo.require("dijit.util.parser");
+	//		</script>
+	//		...
+	//		<div	dojoType="dojox.widget.AnalogGauge"
+	//				id="testGauge"
+	//				width="300"
+	//				height="200"
+	//				cx=150
+	//				cy=175
+	//				radius=125
+	//				image="gaugeOverlay.png"
+	//				imageOverlay="false"
+	//				imageWidth="280"
+	//				imageHeight="155"
+	//				imageX="12"
+	//				imageY="38">
+	//			<div 	dojoType="dojox.widget.gauge.Indicator"
+	//					value=17
+	//					type="arrow"
+	//					length=135
+	//					width=3
+	//					hover="Value: 17"
+	//					onDragMove="handleDragMove">
+	//			</div>
+	//		</div>
+
+	// value: Number
+	// The value (on the gauge) that this indicator should be placed at
+	value: 0,
+
+	// type: String
+	// The type of indicator to draw.  Varies by gauge type.  Some examples include
+	// "line", "arrow", and "bar"
+	type: '',
+
+	// color: String
+	// The color of the indicator.
+	color: 'black',
+
+	// label: String
+	// The text label for the indicator.
+	label: '',
+
+	// font: Object
+	// Generally in a format similar to:
+	// {family: "Helvetica", weight: "bold", style: "italic", size: "18pt", rotated: true}
+	font: {family: "sans-serif", size: "12px"},
+
+	// length: Number
+	// The length of the indicator.  In the above example, the radius of the AnalogGauge
+	// is 125, but the length of the indicator is 135, meaning it would project beyond
+	// the edge of the AnalogGauge
+	length: 0,
+
+	// width: Number
+	// The width of the indicator.
+	width: 0,
+
+	// offset: Number
+	// The offset of the indicator
+	offset: 0,
+
+	// hover: String
+	// The string to put in the tooltip when this indicator is hovered over.
+	hover: '',
+
+	// front: boolean
+	// Keep this indicator at the front
+	front: false,
+
+	// onDragMove: String
+	// The function to call when this indicator is moved by dragging.
+	//onDragMove: '',
+
+	// easing: String|Object
+	// indicates the easing function to be used when animating the of an indicator.
+	easing: dojo._defaultEasing,
+
+	// duration: Number
+	// indicates how long an animation of the indicator should take
+	duration: 1000,
+
+	// hideValues: Boolean
+	// indicates whether the text boxes showing the value of the indicator (as text 
+	// content) should be hidden or shown.  Default is not hidden, aka shown.
+	hideValue: false,
+
+	// noChange: Boolean
+	// indicates whether the indicator's value can be changed.  Useful for 
+	// a static target indicator.  Default is false (that the value can be changed).
+	noChange: false,
+
+	_gauge: null,
+	
+	// title: String
+	// The title of the indicator, to be displayed next to it's input box for the text-representation.
+	title: "",
+
+	templateString: dojo.cache("dojox.widget.gauge", "_Indicator.html"),
+
+	startup: function(){
+		if(this.onDragMove){
+			this.onDragMove = dojo.hitch(this.onDragMove);
+		}
+	},
+
+	postCreate: function(){
+		if(this.title === ""){
+			dojo.style(this.domNode, "display", "none");
+		}
+		if(dojo.isString(this.easing)){
+			this.easing = dojo.getObject(this.easing);
+		}
+	},
+
+	_update: function(event){
+		// summary:
+		//		A private function, handling the updating of the gauge
+		var value = this.valueNode.value;
+		if(value === ''){
+			this.value = null;
+		}else{
+			this.value = Number(value);
+			this.hover = this.title+': '+value;
+		}
+		if(this._gauge){
+			this.draw();
+			this.valueNode.value = this.value;
+			if((this.title == 'Target' || this.front) && this._gauge.moveIndicator){
+				// if re-drawing value, make sure target is still on top
+				this._gauge.moveIndicatorToFront(this);
+			}
+		}
+	},
+
+	update: function(value){
+		// summary:
+		//		Updates the value of the indicator, including moving/re-drawing at it's new location and 
+		//		updating the text box
+		if(!this.noChange){
+			this.valueNode.value = value;
+			this._update();
+		}
+	},
+
+	onDragMove: function(){
+		// summary:
+		//		Handles updating the text box and the hover text while dragging an indicator
+		this.value = Math.floor(this.value);
+		this.valueNode.value = this.value;
+		this.hover = this.title+': '+this.value;
+	},
+
+	draw: function(/* Boolean? */ dontAnimate){
+		// summary:
+		//		Performs the initial drawing of the indicator.
+		// dontAnimate:
+		//		Indicates if the drawing should not be animated (rather than teh default, to animate)
+	},
+
+	remove: function(){
+		// summary:
+		//		Removes the indicator's shapes from the gauge surface.
+		for(var i=0; i<this.shapes.length; i++){
+			this._gauge.surface.remove(this.shapes[i]);
+		}
+		if(this.text){
+			this._gauge.surface.remove(this.text);
+		}
+	}
+});
diff --git a/dojox/widget/nls/ColorPicker.js b/dojox/widget/nls/ColorPicker.js
index 480e3d8..799144a 100644
--- a/dojox/widget/nls/ColorPicker.js
+++ b/dojox/widget/nls/ColorPicker.js
@@ -1 +1,12 @@
-({"redLabel":"r","valueLabel":"v","hexLabel":"hex","hueLabel":"h","saturationLabel":"s","degLabel":"°","greenLabel":"g","blueLabel":"b"})
\ No newline at end of file
+({
+redLabel: "r",
+greenLabel: "g",
+blueLabel: "b",
+hueLabel: "h",
+saturationLabel: "s",
+valueLabel: "v", /* aka intensity or brightness */
+degLabel: "\u00B0",
+hexLabel: "hex",
+huePickerTitle: "Hue Selector",
+saturationPickerTitle: "Saturation Selector"
+})
diff --git a/dojox/widget/nls/FilePicker.js b/dojox/widget/nls/FilePicker.js
index 542f043..1869be9 100644
--- a/dojox/widget/nls/FilePicker.js
+++ b/dojox/widget/nls/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Name","size":"Size (in bytes)","path":"Path"})
\ No newline at end of file
+({
+name: "Name",
+path: "Path",
+size: "Size (in bytes)"
+})
diff --git a/dojox/widget/nls/Wizard.js b/dojox/widget/nls/Wizard.js
index ec10f3f..9f03c21 100644
--- a/dojox/widget/nls/Wizard.js
+++ b/dojox/widget/nls/Wizard.js
@@ -1 +1,5 @@
-({"next":"Next","done":"Done","previous":"Previous"})
\ No newline at end of file
+({
+next: "Next",
+previous: "Previous",
+done: "Done"
+})
diff --git a/dojox/widget/nls/ar/ColorPicker.js b/dojox/widget/nls/ar/ColorPicker.js
new file mode 100644
index 0000000..1fe2a1b
--- /dev/null
+++ b/dojox/widget/nls/ar/ColorPicker.js
@@ -0,0 +1,3 @@
+({
+})
+
diff --git a/dojox/widget/nls/ar/FilePicker.js b/dojox/widget/nls/ar/FilePicker.js
index 01d76ae..e878525 100644
--- a/dojox/widget/nls/ar/FilePicker.js
+++ b/dojox/widget/nls/ar/FilePicker.js
@@ -1 +1,5 @@
-({"name":"الاسم","size":"الحجم (بالبايت) ","path":"‏المسار‏"})
\ No newline at end of file
+({
+name: "الاسم",
+path: "‏المسار‏",
+size: "الحجم (بالبايت) "
+})
diff --git a/dojox/widget/nls/ar/Wizard.js b/dojox/widget/nls/ar/Wizard.js
index c8acda0..3138965 100644
--- a/dojox/widget/nls/ar/Wizard.js
+++ b/dojox/widget/nls/ar/Wizard.js
@@ -1 +1,5 @@
-({"next":"تالي","done":"اتمام","previous":"‏سابق‏"})
\ No newline at end of file
+({
+next: "تالي",
+previous: "‏سابق‏",
+done: "اتمام"
+})
diff --git a/dojox/widget/nls/ca/ColorPicker.js b/dojox/widget/nls/ca/ColorPicker.js
new file mode 100644
index 0000000..e1b7023
--- /dev/null
+++ b/dojox/widget/nls/ca/ColorPicker.js
@@ -0,0 +1,6 @@
+({
+redLabel: "v",
+greenLabel: "e",
+hueLabel: "m"
+})
+
diff --git a/dojox/widget/nls/ca/FilePicker.js b/dojox/widget/nls/ca/FilePicker.js
index 5902820..4f7a56f 100644
--- a/dojox/widget/nls/ca/FilePicker.js
+++ b/dojox/widget/nls/ca/FilePicker.js
@@ -1 +1,6 @@
-({"name":"Nom","size":"Mida (en bytes)","path":"Camí d'accés"})
\ No newline at end of file
+({
+name: "Nom",
+path: "Camí d'accés",
+size: "Mida (en bytes)"
+})
+
diff --git a/dojox/widget/nls/ca/Wizard.js b/dojox/widget/nls/ca/Wizard.js
index da85941..dad929c 100644
--- a/dojox/widget/nls/ca/Wizard.js
+++ b/dojox/widget/nls/ca/Wizard.js
@@ -1 +1,6 @@
-({"next":"Següent","done":"Fet","previous":"Anterior"})
\ No newline at end of file
+({
+next: "Següent",
+previous: "Anterior",
+done: "Fet"
+})
+
diff --git a/dojox/widget/nls/cs/ColorPicker.js b/dojox/widget/nls/cs/ColorPicker.js
index 6707c44..0add331 100644
--- a/dojox/widget/nls/cs/ColorPicker.js
+++ b/dojox/widget/nls/cs/ColorPicker.js
@@ -1 +1,10 @@
-({"redLabel":"č","valueLabel":"j","hexLabel":"hex","hueLabel":"o","saturationLabel":"n","greenLabel":"z","blueLabel":"m","degLabel":"°"})
\ No newline at end of file
+({
+redLabel: "č",
+greenLabel: "z",
+blueLabel: "m",
+hueLabel: "o",
+saturationLabel: "n",
+valueLabel: "j", /* aka intensity or brightness */
+hexLabel: "hex"
+})
+
diff --git a/dojox/widget/nls/cs/FilePicker.js b/dojox/widget/nls/cs/FilePicker.js
index 54f7366..662cec3 100644
--- a/dojox/widget/nls/cs/FilePicker.js
+++ b/dojox/widget/nls/cs/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Název","size":"Velikost (v bajtech)","path":"Cesta"})
\ No newline at end of file
+({
+name: "Název",
+path: "Cesta",
+size: "Velikost (v bajtech)"
+})
diff --git a/dojox/widget/nls/cs/Wizard.js b/dojox/widget/nls/cs/Wizard.js
index 4075772..70f1996 100644
--- a/dojox/widget/nls/cs/Wizard.js
+++ b/dojox/widget/nls/cs/Wizard.js
@@ -1 +1,5 @@
-({"next":"Další","done":"Hotovo","previous":"Předchozí"})
\ No newline at end of file
+({
+next: "Další",
+previous: "Předchozí",
+done: "Hotovo"
+})
diff --git a/dojox/widget/nls/da/ColorPicker.js b/dojox/widget/nls/da/ColorPicker.js
new file mode 100644
index 0000000..1fe2a1b
--- /dev/null
+++ b/dojox/widget/nls/da/ColorPicker.js
@@ -0,0 +1,3 @@
+({
+})
+
diff --git a/dojox/widget/nls/da/FilePicker.js b/dojox/widget/nls/da/FilePicker.js
index 35cc924..282de00 100644
--- a/dojox/widget/nls/da/FilePicker.js
+++ b/dojox/widget/nls/da/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Navn","size":"Størrelse (i byte)","path":"Sti"})
\ No newline at end of file
+({
+name: "Navn",
+path: "Sti",
+size: "Størrelse (i byte)"
+})
diff --git a/dojox/widget/nls/da/Wizard.js b/dojox/widget/nls/da/Wizard.js
index e447f70..f7ebe6b 100644
--- a/dojox/widget/nls/da/Wizard.js
+++ b/dojox/widget/nls/da/Wizard.js
@@ -1 +1,5 @@
-({"next":"Næste","done":"Udført","previous":"Forrige"})
\ No newline at end of file
+({
+next: "Næste",
+previous: "Forrige",
+done: "Udført"
+})
diff --git a/dojox/widget/nls/de/ColorPicker.js b/dojox/widget/nls/de/ColorPicker.js
index 480e3d8..1fe2a1b 100644
--- a/dojox/widget/nls/de/ColorPicker.js
+++ b/dojox/widget/nls/de/ColorPicker.js
@@ -1 +1,3 @@
-({"redLabel":"r","valueLabel":"v","hexLabel":"hex","hueLabel":"h","saturationLabel":"s","degLabel":"°","greenLabel":"g","blueLabel":"b"})
\ No newline at end of file
+({
+})
+
diff --git a/dojox/widget/nls/de/FilePicker.js b/dojox/widget/nls/de/FilePicker.js
index b33ec5d..5d931eb 100644
--- a/dojox/widget/nls/de/FilePicker.js
+++ b/dojox/widget/nls/de/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Name","size":"Größe (in Byte)","path":"Pfad"})
\ No newline at end of file
+({
+name: "Name",
+path: "Pfad",
+size: "Größe (in Byte)"
+})
diff --git a/dojox/widget/nls/de/Wizard.js b/dojox/widget/nls/de/Wizard.js
index a7f2164..edbbd7e 100644
--- a/dojox/widget/nls/de/Wizard.js
+++ b/dojox/widget/nls/de/Wizard.js
@@ -1 +1,5 @@
-({"next":"Weiter","done":"Fertig","previous":"Zurück"})
\ No newline at end of file
+({
+next: "Weiter",
+previous: "Zurück",
+done: "Fertig"
+})
diff --git a/dojox/widget/nls/el/ColorPicker.js b/dojox/widget/nls/el/ColorPicker.js
new file mode 100644
index 0000000..1604f9f
--- /dev/null
+++ b/dojox/widget/nls/el/ColorPicker.js
@@ -0,0 +1,10 @@
+({
+redLabel: "κ",
+greenLabel: "π",
+blueLabel: "μ",
+hueLabel: "α",
+saturationLabel: "κ",
+valueLabel: "τ", /* aka intensity or brightness */
+hexLabel: "16-αδικό"
+})
+
diff --git a/dojox/widget/nls/el/FilePicker.js b/dojox/widget/nls/el/FilePicker.js
index e6d8b24..19ba81e 100644
--- a/dojox/widget/nls/el/FilePicker.js
+++ b/dojox/widget/nls/el/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Όνομα","size":"Μέγεθος (σε bytes)","path":"Διαδρομή"})
\ No newline at end of file
+({
+name: "Όνομα",
+path: "Διαδρομή",
+size: "Μέγεθος (σε bytes)"
+})
diff --git a/dojox/widget/nls/el/Wizard.js b/dojox/widget/nls/el/Wizard.js
index 6a25346..588844a 100644
--- a/dojox/widget/nls/el/Wizard.js
+++ b/dojox/widget/nls/el/Wizard.js
@@ -1 +1,5 @@
-({"next":"Επόμενο","done":"Ολοκλήρωση","previous":"Προηγούμενο"})
\ No newline at end of file
+({
+next: "Επόμενο",
+previous: "Προηγούμενο",
+done: "Ολοκλήρωση"
+})
diff --git a/dojox/widget/nls/es/ColorPicker.js b/dojox/widget/nls/es/ColorPicker.js
index 480e3d8..1fe2a1b 100644
--- a/dojox/widget/nls/es/ColorPicker.js
+++ b/dojox/widget/nls/es/ColorPicker.js
@@ -1 +1,3 @@
-({"redLabel":"r","valueLabel":"v","hexLabel":"hex","hueLabel":"h","saturationLabel":"s","degLabel":"°","greenLabel":"g","blueLabel":"b"})
\ No newline at end of file
+({
+})
+
diff --git a/dojox/widget/nls/es/FilePicker.js b/dojox/widget/nls/es/FilePicker.js
index b926640..a313e9f 100644
--- a/dojox/widget/nls/es/FilePicker.js
+++ b/dojox/widget/nls/es/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Nombre","size":"Tamaño (en bytes)","path":"Vía de acceso"})
\ No newline at end of file
+({
+name: "Nombre",
+path: "Vía de acceso",
+size: "Tamaño (en bytes)"
+})
diff --git a/dojox/widget/nls/es/Wizard.js b/dojox/widget/nls/es/Wizard.js
index aab5661..80dd2b6 100644
--- a/dojox/widget/nls/es/Wizard.js
+++ b/dojox/widget/nls/es/Wizard.js
@@ -1 +1,5 @@
-({"next":"Siguiente","done":"Terminado","previous":"Anterior"})
\ No newline at end of file
+({
+next: "Siguiente",
+previous: "Anterior",
+done: "Terminado"
+})
diff --git a/dojox/widget/nls/fi/ColorPicker.js b/dojox/widget/nls/fi/ColorPicker.js
new file mode 100644
index 0000000..1fe2a1b
--- /dev/null
+++ b/dojox/widget/nls/fi/ColorPicker.js
@@ -0,0 +1,3 @@
+({
+})
+
diff --git a/dojox/widget/nls/fi/FilePicker.js b/dojox/widget/nls/fi/FilePicker.js
index df2efcf..5d8e1f0 100644
--- a/dojox/widget/nls/fi/FilePicker.js
+++ b/dojox/widget/nls/fi/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Nimi","size":"Koko (tavuina)","path":"Polku"})
\ No newline at end of file
+({
+name: "Nimi",
+path: "Polku",
+size: "Koko (tavuina)"
+})
diff --git a/dojox/widget/nls/fi/Wizard.js b/dojox/widget/nls/fi/Wizard.js
index ea6a9db..907f6d1 100644
--- a/dojox/widget/nls/fi/Wizard.js
+++ b/dojox/widget/nls/fi/Wizard.js
@@ -1 +1,5 @@
-({"next":"Seuraava","done":"Valmis","previous":"Edellinen"})
\ No newline at end of file
+({
+next: "Seuraava",
+previous: "Edellinen",
+done: "Valmis"
+})
diff --git a/dojox/widget/nls/fr/ColorPicker.js b/dojox/widget/nls/fr/ColorPicker.js
index d8524b9..4c68c9c 100644
--- a/dojox/widget/nls/fr/ColorPicker.js
+++ b/dojox/widget/nls/fr/ColorPicker.js
@@ -1 +1,10 @@
-({"redLabel":"r","valueLabel":"v","hexLabel":"hex","hueLabel":"t","saturationLabel":"s","greenLabel":"v","blueLabel":"b","degLabel":"°"})
\ No newline at end of file
+({
+redLabel: "r",
+greenLabel: "v",
+blueLabel: "b",
+hueLabel: "t",
+saturationLabel: "s",
+valueLabel: "v", /* aka intensity or brightness */
+hexLabel: "hex"
+})
+
diff --git a/dojox/widget/nls/fr/FilePicker.js b/dojox/widget/nls/fr/FilePicker.js
index 8b1045f..4d6530d 100644
--- a/dojox/widget/nls/fr/FilePicker.js
+++ b/dojox/widget/nls/fr/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Nom","size":"Taille (en octets)","path":"Chemin"})
\ No newline at end of file
+({
+name: "Nom",
+path: "Chemin",
+size: "Taille (en octets)"
+})
diff --git a/dojox/widget/nls/fr/Wizard.js b/dojox/widget/nls/fr/Wizard.js
index 779919e..76062ed 100644
--- a/dojox/widget/nls/fr/Wizard.js
+++ b/dojox/widget/nls/fr/Wizard.js
@@ -1 +1,5 @@
-({"next":"Suivant","done":"Terminé","previous":"Précédent"})
\ No newline at end of file
+({
+next: "Suivant",
+previous: "Précédent",
+done: "Terminé"
+})
diff --git a/dojox/widget/nls/he/ColorPicker.js b/dojox/widget/nls/he/ColorPicker.js
new file mode 100644
index 0000000..91685a1
--- /dev/null
+++ b/dojox/widget/nls/he/ColorPicker.js
@@ -0,0 +1,10 @@
+({
+redLabel: "א",
+greenLabel: "י",
+blueLabel: "כ",
+hueLabel: "ג",
+saturationLabel: "ר",
+valueLabel: "ע", /* aka intensity or brightness */
+hexLabel: "הקס"
+})
+
diff --git a/dojox/widget/nls/he/FilePicker.js b/dojox/widget/nls/he/FilePicker.js
index 7b4e52a..d1d4296 100644
--- a/dojox/widget/nls/he/FilePicker.js
+++ b/dojox/widget/nls/he/FilePicker.js
@@ -1 +1,5 @@
-({"name":"שם","size":"גודל (בבתים)","path":"נתיב"})
\ No newline at end of file
+({
+name: "שם",
+path: "נתיב",
+size: "גודל (בבתים)"
+})
diff --git a/dojox/widget/nls/he/Wizard.js b/dojox/widget/nls/he/Wizard.js
index e5ee2ee..0885317 100644
--- a/dojox/widget/nls/he/Wizard.js
+++ b/dojox/widget/nls/he/Wizard.js
@@ -1 +1,5 @@
-({"next":"הבא","done":"סיום","previous":"הקודם"})
\ No newline at end of file
+({
+next: "הבא",
+previous: "הקודם",
+done: "סיום"
+})
diff --git a/dojox/widget/nls/hu/ColorPicker.js b/dojox/widget/nls/hu/ColorPicker.js
index 480e3d8..1fe2a1b 100644
--- a/dojox/widget/nls/hu/ColorPicker.js
+++ b/dojox/widget/nls/hu/ColorPicker.js
@@ -1 +1,3 @@
-({"redLabel":"r","valueLabel":"v","hexLabel":"hex","hueLabel":"h","saturationLabel":"s","degLabel":"°","greenLabel":"g","blueLabel":"b"})
\ No newline at end of file
+({
+})
+
diff --git a/dojox/widget/nls/hu/FilePicker.js b/dojox/widget/nls/hu/FilePicker.js
index 8323b89..c9b183e 100644
--- a/dojox/widget/nls/hu/FilePicker.js
+++ b/dojox/widget/nls/hu/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Név","size":"Méret (byte)","path":"Elérési út"})
\ No newline at end of file
+({
+name: "Név",
+path: "Elérési út",
+size: "Méret (byte)"
+})
diff --git a/dojox/widget/nls/hu/Wizard.js b/dojox/widget/nls/hu/Wizard.js
index 6ad86c7..83a8b52 100644
--- a/dojox/widget/nls/hu/Wizard.js
+++ b/dojox/widget/nls/hu/Wizard.js
@@ -1 +1,5 @@
-({"next":"Következő","done":"Kész","previous":"Előző"})
\ No newline at end of file
+({
+next: "Következő",
+previous: "Előző",
+done: "Kész"
+})
diff --git a/dojox/widget/nls/it/ColorPicker.js b/dojox/widget/nls/it/ColorPicker.js
index d8524b9..4c68c9c 100644
--- a/dojox/widget/nls/it/ColorPicker.js
+++ b/dojox/widget/nls/it/ColorPicker.js
@@ -1 +1,10 @@
-({"redLabel":"r","valueLabel":"v","hexLabel":"hex","hueLabel":"t","saturationLabel":"s","greenLabel":"v","blueLabel":"b","degLabel":"°"})
\ No newline at end of file
+({
+redLabel: "r",
+greenLabel: "v",
+blueLabel: "b",
+hueLabel: "t",
+saturationLabel: "s",
+valueLabel: "v", /* aka intensity or brightness */
+hexLabel: "hex"
+})
+
diff --git a/dojox/widget/nls/it/FilePicker.js b/dojox/widget/nls/it/FilePicker.js
index 77801d2..d34d5c7 100644
--- a/dojox/widget/nls/it/FilePicker.js
+++ b/dojox/widget/nls/it/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Nome","size":"Dimensione (in byte)","path":"Percorso"})
\ No newline at end of file
+({
+name: "Nome",
+path: "Percorso",
+size: "Dimensione (in byte)"
+})
diff --git a/dojox/widget/nls/it/Wizard.js b/dojox/widget/nls/it/Wizard.js
index 78ea64b..816ab45 100644
--- a/dojox/widget/nls/it/Wizard.js
+++ b/dojox/widget/nls/it/Wizard.js
@@ -1 +1,5 @@
-({"next":"Successivo","done":"Eseguito","previous":"Precedente"})
\ No newline at end of file
+({
+next: "Successivo",
+previous: "Precedente",
+done: "Eseguito"
+})
diff --git a/dojox/widget/nls/ja/ColorPicker.js b/dojox/widget/nls/ja/ColorPicker.js
index 5cbbfd9..e279369 100644
--- a/dojox/widget/nls/ja/ColorPicker.js
+++ b/dojox/widget/nls/ja/ColorPicker.js
@@ -1 +1,4 @@
-({"hexLabel":"16 進","redLabel":"r","valueLabel":"v","hueLabel":"h","saturationLabel":"s","degLabel":"°","greenLabel":"g","blueLabel":"b"})
\ No newline at end of file
+({
+hexLabel: "16 進"
+})
+
diff --git a/dojox/widget/nls/ja/FilePicker.js b/dojox/widget/nls/ja/FilePicker.js
index 61068a9..5ee41d2 100644
--- a/dojox/widget/nls/ja/FilePicker.js
+++ b/dojox/widget/nls/ja/FilePicker.js
@@ -1 +1,5 @@
-({"name":"名前","size":"サイズ (バイト単位)","path":"パス"})
\ No newline at end of file
+({
+name: "名前",
+path: "パス",
+size: "サイズ (バイト単位)"
+})
diff --git a/dojox/widget/nls/ja/Wizard.js b/dojox/widget/nls/ja/Wizard.js
index 6394cb3..8f11a3c 100644
--- a/dojox/widget/nls/ja/Wizard.js
+++ b/dojox/widget/nls/ja/Wizard.js
@@ -1 +1,5 @@
-({"next":"次へ","done":"完了","previous":"前へ"})
\ No newline at end of file
+({
+next: "次へ",
+previous: "前へ",
+done: "完了"
+})
diff --git a/dojox/widget/nls/ko/ColorPicker.js b/dojox/widget/nls/ko/ColorPicker.js
index 7f98cb7..451a08a 100644
--- a/dojox/widget/nls/ko/ColorPicker.js
+++ b/dojox/widget/nls/ko/ColorPicker.js
@@ -1 +1,10 @@
-({"hexLabel":"16진","redLabel":"r","valueLabel":"v","hueLabel":"h","saturationLabel":"s","degLabel":"°","greenLabel":"g","blueLabel":"b"})
\ No newline at end of file
+({
+redLabel: "R",
+greenLabel: "G",
+blueLabel: "B",
+hueLabel: "H",
+saturationLabel: "S",
+valueLabel: "V", /* aka intensity or brightness */
+hexLabel: "HEX"
+})
+
diff --git a/dojox/widget/nls/ko/FilePicker.js b/dojox/widget/nls/ko/FilePicker.js
index fd59903..fc21dba 100644
--- a/dojox/widget/nls/ko/FilePicker.js
+++ b/dojox/widget/nls/ko/FilePicker.js
@@ -1 +1,5 @@
-({"name":"이름","size":"크기(바이트)","path":"경로"})
\ No newline at end of file
+({
+name: "이름",
+path: "경로",
+size: "크기(바이트)"
+})
diff --git a/dojox/widget/nls/ko/Wizard.js b/dojox/widget/nls/ko/Wizard.js
index dec3546..e9dea10 100644
--- a/dojox/widget/nls/ko/Wizard.js
+++ b/dojox/widget/nls/ko/Wizard.js
@@ -1 +1,5 @@
-({"next":"다음","done":"완료","previous":"이전"})
\ No newline at end of file
+({
+next: "다음",
+previous: "이전",
+done: "완료"
+})
diff --git a/dojox/widget/nls/nb/ColorPicker.js b/dojox/widget/nls/nb/ColorPicker.js
new file mode 100644
index 0000000..1fe2a1b
--- /dev/null
+++ b/dojox/widget/nls/nb/ColorPicker.js
@@ -0,0 +1,3 @@
+({
+})
+
diff --git a/dojox/widget/nls/nb/FilePicker.js b/dojox/widget/nls/nb/FilePicker.js
index ef78320..36775a3 100644
--- a/dojox/widget/nls/nb/FilePicker.js
+++ b/dojox/widget/nls/nb/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Navn","size":"Størrelse (i byte)","path":"Bane"})
\ No newline at end of file
+({
+name: "Navn",
+path: "Bane",
+size: "Størrelse (i byte)"
+})
diff --git a/dojox/widget/nls/nb/Wizard.js b/dojox/widget/nls/nb/Wizard.js
index 0cbe813..1f8d0bc 100644
--- a/dojox/widget/nls/nb/Wizard.js
+++ b/dojox/widget/nls/nb/Wizard.js
@@ -1 +1,5 @@
-({"next":"Neste","done":"Ferdig","previous":"Forrige"})
\ No newline at end of file
+({
+next: "Neste",
+previous: "Forrige",
+done: "Ferdig"
+})
diff --git a/dojox/widget/nls/nl/ColorPicker.js b/dojox/widget/nls/nl/ColorPicker.js
new file mode 100644
index 0000000..9789f65
--- /dev/null
+++ b/dojox/widget/nls/nl/ColorPicker.js
@@ -0,0 +1,6 @@
+({
+hueLabel: "t",
+saturationLabel: "i",
+valueLabel: "h" /* aka intensity or brightness */
+})
+
diff --git a/dojox/widget/nls/nl/FilePicker.js b/dojox/widget/nls/nl/FilePicker.js
index a841a1d..e91c5f8 100644
--- a/dojox/widget/nls/nl/FilePicker.js
+++ b/dojox/widget/nls/nl/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Naam","size":"Grootte (in bytes)","path":"Pad"})
\ No newline at end of file
+({
+name: "Naam",
+path: "Pad",
+size: "Grootte (in bytes)"
+})
diff --git a/dojox/widget/nls/nl/Wizard.js b/dojox/widget/nls/nl/Wizard.js
index d5e680f..2d40908 100644
--- a/dojox/widget/nls/nl/Wizard.js
+++ b/dojox/widget/nls/nl/Wizard.js
@@ -1 +1,5 @@
-({"next":"Volgende","done":"Klaar","previous":"Vorige"})
\ No newline at end of file
+({
+next: "Volgende",
+previous: "Vorige",
+done: "Klaar"
+})
diff --git a/dojox/widget/nls/pl/ColorPicker.js b/dojox/widget/nls/pl/ColorPicker.js
index 51b1800..967da23 100644
--- a/dojox/widget/nls/pl/ColorPicker.js
+++ b/dojox/widget/nls/pl/ColorPicker.js
@@ -1 +1,10 @@
-({"redLabel":"c","valueLabel":"jas.","hexLabel":"szesnastkowe","hueLabel":"barwa","saturationLabel":"nas.","greenLabel":"z","blueLabel":"n","degLabel":"°"})
\ No newline at end of file
+({
+redLabel: "c",
+greenLabel: "z",
+blueLabel: "n",
+hueLabel: "barwa",
+saturationLabel: "nas.",
+valueLabel: "jas.", /* aka intensity or brightness */
+hexLabel: "szesnastkowe"
+})
+
diff --git a/dojox/widget/nls/pl/FilePicker.js b/dojox/widget/nls/pl/FilePicker.js
index 5afd4b7..5ac0739 100644
--- a/dojox/widget/nls/pl/FilePicker.js
+++ b/dojox/widget/nls/pl/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Nazwa","size":"Wielkość (w bajtach)","path":"Ścieżka"})
\ No newline at end of file
+({
+name: "Nazwa",
+path: "Ścieżka",
+size: "Wielkość (w bajtach)"
+})
diff --git a/dojox/widget/nls/pl/Wizard.js b/dojox/widget/nls/pl/Wizard.js
index 3bcfb9c..44cdf79 100644
--- a/dojox/widget/nls/pl/Wizard.js
+++ b/dojox/widget/nls/pl/Wizard.js
@@ -1 +1,5 @@
-({"next":"Następna","done":"Gotowe","previous":"Poprzednia"})
\ No newline at end of file
+({
+next: "Następna",
+previous: "Poprzednia",
+done: "Gotowe"
+})
diff --git a/dojox/widget/nls/pt-pt/ColorPicker.js b/dojox/widget/nls/pt-pt/ColorPicker.js
new file mode 100644
index 0000000..5760b12
--- /dev/null
+++ b/dojox/widget/nls/pt-pt/ColorPicker.js
@@ -0,0 +1,8 @@
+({
+redLabel: "e",
+greenLabel: "v",
+blueLabel: "a",
+hueLabel: "t",
+valueLabel: "val" /* aka intensity or brightness */
+})
+
diff --git a/dojox/widget/nls/pt-pt/FilePicker.js b/dojox/widget/nls/pt-pt/FilePicker.js
index 22e342e..26465b7 100644
--- a/dojox/widget/nls/pt-pt/FilePicker.js
+++ b/dojox/widget/nls/pt-pt/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Nome","size":"Tamanho (em bytes)","path":"Caminho"})
\ No newline at end of file
+({
+name: "Nome",
+path: "Caminho",
+size: "Tamanho (em bytes)"
+})
diff --git a/dojox/widget/nls/pt-pt/Wizard.js b/dojox/widget/nls/pt-pt/Wizard.js
index 2b6bb1e..c6c9ec7 100644
--- a/dojox/widget/nls/pt-pt/Wizard.js
+++ b/dojox/widget/nls/pt-pt/Wizard.js
@@ -1 +1,5 @@
-({"next":"Seguinte","done":"Concluído","previous":"Anterior"})
\ No newline at end of file
+({
+next: "Seguinte",
+previous: "Anterior",
+done: "Concluído"
+})
diff --git a/dojox/widget/nls/pt/ColorPicker.js b/dojox/widget/nls/pt/ColorPicker.js
index 480e3d8..1fe2a1b 100644
--- a/dojox/widget/nls/pt/ColorPicker.js
+++ b/dojox/widget/nls/pt/ColorPicker.js
@@ -1 +1,3 @@
-({"redLabel":"r","valueLabel":"v","hexLabel":"hex","hueLabel":"h","saturationLabel":"s","degLabel":"°","greenLabel":"g","blueLabel":"b"})
\ No newline at end of file
+({
+})
+
diff --git a/dojox/widget/nls/pt/FilePicker.js b/dojox/widget/nls/pt/FilePicker.js
index 22e342e..26465b7 100644
--- a/dojox/widget/nls/pt/FilePicker.js
+++ b/dojox/widget/nls/pt/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Nome","size":"Tamanho (em bytes)","path":"Caminho"})
\ No newline at end of file
+({
+name: "Nome",
+path: "Caminho",
+size: "Tamanho (em bytes)"
+})
diff --git a/dojox/widget/nls/pt/Wizard.js b/dojox/widget/nls/pt/Wizard.js
index 8f7aa7c..2beb4f2 100644
--- a/dojox/widget/nls/pt/Wizard.js
+++ b/dojox/widget/nls/pt/Wizard.js
@@ -1 +1,5 @@
-({"next":"Próximo","done":"Concluído","previous":"Anterior"})
\ No newline at end of file
+({
+next: "Próximo",
+previous: "Anterior",
+done: "Concluído"
+})
diff --git a/dojox/widget/nls/ro/ColorPicker.js b/dojox/widget/nls/ro/ColorPicker.js
new file mode 100644
index 0000000..85fa9ae
--- /dev/null
+++ b/dojox/widget/nls/ro/ColorPicker.js
@@ -0,0 +1,5 @@
+({
+huePickerTitle: "Selector nuanţă",
+saturationPickerTitle: "Selector saturaţie"
+})
+
diff --git a/dojox/widget/nls/ro/FilePicker.js b/dojox/widget/nls/ro/FilePicker.js
new file mode 100644
index 0000000..922ae7d
--- /dev/null
+++ b/dojox/widget/nls/ro/FilePicker.js
@@ -0,0 +1,6 @@
+({
+name: "Nume",
+path: "Cale ",
+size: "Dimensiune (în octeţi)"
+})
+
diff --git a/dojox/widget/nls/ro/Wizard.js b/dojox/widget/nls/ro/Wizard.js
new file mode 100644
index 0000000..0c6a488
--- /dev/null
+++ b/dojox/widget/nls/ro/Wizard.js
@@ -0,0 +1,6 @@
+({
+next: "Următor",
+previous: "Anterior",
+done: "Gata"
+})
+
diff --git a/dojox/widget/nls/ru/ColorPicker.js b/dojox/widget/nls/ru/ColorPicker.js
index c19586a..1de7125 100644
--- a/dojox/widget/nls/ru/ColorPicker.js
+++ b/dojox/widget/nls/ru/ColorPicker.js
@@ -1 +1,10 @@
-({"redLabel":"к","valueLabel":"з","hexLabel":"шест","hueLabel":"о","saturationLabel":"н","greenLabel":"з","blueLabel":"с","degLabel":"°"})
\ No newline at end of file
+({
+redLabel: "к",
+greenLabel: "з",
+blueLabel: "с",
+hueLabel: "о",
+saturationLabel: "н",
+valueLabel: "з", /* aka intensity or brightness */
+hexLabel: "шест"
+})
+
diff --git a/dojox/widget/nls/ru/FilePicker.js b/dojox/widget/nls/ru/FilePicker.js
index af2d596..303a58f 100644
--- a/dojox/widget/nls/ru/FilePicker.js
+++ b/dojox/widget/nls/ru/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Имя","size":"Размер (байт)","path":"Путь"})
\ No newline at end of file
+({
+name: "Имя",
+path: "Путь",
+size: "Размер (байт)"
+})
diff --git a/dojox/widget/nls/ru/Wizard.js b/dojox/widget/nls/ru/Wizard.js
index bbc1b51..c4a361c 100644
--- a/dojox/widget/nls/ru/Wizard.js
+++ b/dojox/widget/nls/ru/Wizard.js
@@ -1 +1,5 @@
-({"next":"Далее","done":"Готово","previous":"Назад"})
\ No newline at end of file
+({
+next: "Далее",
+previous: "Назад",
+done: "Готово"
+})
diff --git a/dojox/widget/nls/sk/ColorPicker.js b/dojox/widget/nls/sk/ColorPicker.js
new file mode 100644
index 0000000..1fe2a1b
--- /dev/null
+++ b/dojox/widget/nls/sk/ColorPicker.js
@@ -0,0 +1,3 @@
+({
+})
+
diff --git a/dojox/widget/nls/sk/FilePicker.js b/dojox/widget/nls/sk/FilePicker.js
index c165416..dad2f6b 100644
--- a/dojox/widget/nls/sk/FilePicker.js
+++ b/dojox/widget/nls/sk/FilePicker.js
@@ -1 +1,6 @@
-({"name":"Názov","size":"Veľkosť (v bajtoch)","path":"Cesta"})
\ No newline at end of file
+({
+name: "Názov",
+path: "Cesta",
+size: "Veľkosť (v bajtoch)"
+})
+
diff --git a/dojox/widget/nls/sk/Wizard.js b/dojox/widget/nls/sk/Wizard.js
index d740aa4..e35147e 100644
--- a/dojox/widget/nls/sk/Wizard.js
+++ b/dojox/widget/nls/sk/Wizard.js
@@ -1 +1,6 @@
-({"next":"Ďalej","done":"Hotovo","previous":"Späť"})
\ No newline at end of file
+({
+next: "Ďalej",
+previous: "Späť",
+done: "Hotovo"
+})
+
diff --git a/dojox/widget/nls/sl/ColorPicker.js b/dojox/widget/nls/sl/ColorPicker.js
new file mode 100644
index 0000000..1fe2a1b
--- /dev/null
+++ b/dojox/widget/nls/sl/ColorPicker.js
@@ -0,0 +1,3 @@
+({
+})
+
diff --git a/dojox/widget/nls/sl/FilePicker.js b/dojox/widget/nls/sl/FilePicker.js
index f977154..d2eac31 100644
--- a/dojox/widget/nls/sl/FilePicker.js
+++ b/dojox/widget/nls/sl/FilePicker.js
@@ -1 +1,6 @@
-({"name":"Ime","size":"Velikost (v bajtih)","path":"Pot"})
\ No newline at end of file
+({
+name: "Ime",
+path: "Pot",
+size: "Velikost (v bajtih)"
+})
+
diff --git a/dojox/widget/nls/sl/Wizard.js b/dojox/widget/nls/sl/Wizard.js
index a89a23c..2ace11a 100644
--- a/dojox/widget/nls/sl/Wizard.js
+++ b/dojox/widget/nls/sl/Wizard.js
@@ -1 +1,6 @@
-({"next":"Naprej","done":"Opravljeno","previous":"Nazaj"})
\ No newline at end of file
+({
+next: "Naprej",
+previous: "Nazaj",
+done: "Opravljeno"
+})
+
diff --git a/dojox/widget/nls/sv/ColorPicker.js b/dojox/widget/nls/sv/ColorPicker.js
new file mode 100644
index 0000000..e6fd6e6
--- /dev/null
+++ b/dojox/widget/nls/sv/ColorPicker.js
@@ -0,0 +1,6 @@
+({
+hueLabel: "n",
+saturationLabel: "m",
+valueLabel: "l" /* aka intensity or brightness */
+})
+
diff --git a/dojox/widget/nls/sv/FilePicker.js b/dojox/widget/nls/sv/FilePicker.js
index 1c66552..295ed0a 100644
--- a/dojox/widget/nls/sv/FilePicker.js
+++ b/dojox/widget/nls/sv/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Namn","size":"Storlek (byte)","path":"Sökväg"})
\ No newline at end of file
+({
+name: "Namn",
+path: "Sökväg",
+size: "Storlek (byte)"
+})
diff --git a/dojox/widget/nls/sv/Wizard.js b/dojox/widget/nls/sv/Wizard.js
index ae75b03..6542886 100644
--- a/dojox/widget/nls/sv/Wizard.js
+++ b/dojox/widget/nls/sv/Wizard.js
@@ -1 +1,5 @@
-({"next":"Nästa","done":"Stäng","previous":"Föregående"})
\ No newline at end of file
+({
+next: "Nästa",
+previous: "Föregående",
+done: "Stäng"
+})
diff --git a/dojox/widget/nls/th/ColorPicker.js b/dojox/widget/nls/th/ColorPicker.js
index 2edfabd..37068ae 100644
--- a/dojox/widget/nls/th/ColorPicker.js
+++ b/dojox/widget/nls/th/ColorPicker.js
@@ -1 +1,9 @@
-({"redLabel":"อาร์","valueLabel":"วี","hexLabel":"เลขฐานสิบหก","hueLabel":"เอช","saturationLabel":"เอส","greenLabel":"จี","blueLabel":"บี","degLabel":"°"})
\ No newline at end of file
+({
+redLabel: "อาร์",
+greenLabel: "จี",
+blueLabel: "บี",
+hueLabel: "เอช",
+saturationLabel: "เอส",
+valueLabel: "วี",
+hexLabel: "เลขฐานสิบหก"
+})
diff --git a/dojox/widget/nls/th/FilePicker.js b/dojox/widget/nls/th/FilePicker.js
index 362f1c1..c59ae24 100644
--- a/dojox/widget/nls/th/FilePicker.js
+++ b/dojox/widget/nls/th/FilePicker.js
@@ -1 +1,6 @@
-({"name":"ชื่อ","size":"ขนาด (ไบต์)","path":"พาธ"})
\ No newline at end of file
+({
+name: "ชื่อ",
+path: "พาธ",
+size: "ขนาด (ไบต์)"
+})
+
diff --git a/dojox/widget/nls/th/Wizard.js b/dojox/widget/nls/th/Wizard.js
index d9b793a..2aaffd3 100644
--- a/dojox/widget/nls/th/Wizard.js
+++ b/dojox/widget/nls/th/Wizard.js
@@ -1 +1,6 @@
-({"next":"ถัดไป","done":"เสร็จสิ้น","previous":"ก่อนหน้า"})
\ No newline at end of file
+({
+next: "ถัดไป",
+previous: "ก่อนหน้า",
+done: "เสร็จสิ้น"
+})
+
diff --git a/dojox/widget/nls/tr/ColorPicker.js b/dojox/widget/nls/tr/ColorPicker.js
new file mode 100644
index 0000000..2d26abf
--- /dev/null
+++ b/dojox/widget/nls/tr/ColorPicker.js
@@ -0,0 +1,10 @@
+({
+redLabel: "k",
+greenLabel: "y",
+blueLabel: "m",
+hueLabel: "t",
+saturationLabel: "d",
+valueLabel: "d", /* aka intensity or brightness */
+hexLabel: "onaltılı"
+})
+
diff --git a/dojox/widget/nls/tr/FilePicker.js b/dojox/widget/nls/tr/FilePicker.js
index 2c0d44c..c561303 100644
--- a/dojox/widget/nls/tr/FilePicker.js
+++ b/dojox/widget/nls/tr/FilePicker.js
@@ -1 +1,5 @@
-({"name":"Ad","size":"Boyut (bayt cinsinden)","path":"Yol"})
\ No newline at end of file
+({
+name: "Ad",
+path: "Yol",
+size: "Boyut (bayt cinsinden)"
+})
diff --git a/dojox/widget/nls/tr/Wizard.js b/dojox/widget/nls/tr/Wizard.js
index 752b8ac..a2655aa 100644
--- a/dojox/widget/nls/tr/Wizard.js
+++ b/dojox/widget/nls/tr/Wizard.js
@@ -1 +1,5 @@
-({"next":"İleri","done":"Bitti","previous":"Geri"})
\ No newline at end of file
+({
+next: "İleri",
+previous: "Geri",
+done: "Bitti"
+})
diff --git a/dojox/widget/nls/zh-tw/ColorPicker.js b/dojox/widget/nls/zh-tw/ColorPicker.js
index 2941074..254e7cd 100644
--- a/dojox/widget/nls/zh-tw/ColorPicker.js
+++ b/dojox/widget/nls/zh-tw/ColorPicker.js
@@ -1 +1,4 @@
-({"hexLabel":"十六進位","redLabel":"r","valueLabel":"v","hueLabel":"h","saturationLabel":"s","degLabel":"°","greenLabel":"g","blueLabel":"b"})
\ No newline at end of file
+({
+hexLabel: "十六進位"
+})
+
diff --git a/dojox/widget/nls/zh-tw/FilePicker.js b/dojox/widget/nls/zh-tw/FilePicker.js
index 9053ece..dd33b12 100644
--- a/dojox/widget/nls/zh-tw/FilePicker.js
+++ b/dojox/widget/nls/zh-tw/FilePicker.js
@@ -1 +1,5 @@
-({"name":"名稱","size":"大小 (以位元組為單位)","path":"路徑"})
\ No newline at end of file
+({
+name: "名稱",
+path: "路徑",
+size: "大小 (以位元組為單位)"
+})
diff --git a/dojox/widget/nls/zh-tw/Wizard.js b/dojox/widget/nls/zh-tw/Wizard.js
index fe45203..3d9f229 100644
--- a/dojox/widget/nls/zh-tw/Wizard.js
+++ b/dojox/widget/nls/zh-tw/Wizard.js
@@ -1 +1,5 @@
-({"next":"下一步","done":"完成","previous":"上一步"})
\ No newline at end of file
+({
+next: "下一步",
+previous: "上一步",
+done: "完成"
+})
diff --git a/dojox/widget/nls/zh/ColorPicker.js b/dojox/widget/nls/zh/ColorPicker.js
index 4f195c2..786296d 100644
--- a/dojox/widget/nls/zh/ColorPicker.js
+++ b/dojox/widget/nls/zh/ColorPicker.js
@@ -1 +1,4 @@
-({"hexLabel":"十六进制","redLabel":"r","valueLabel":"v","hueLabel":"h","saturationLabel":"s","degLabel":"°","greenLabel":"g","blueLabel":"b"})
\ No newline at end of file
+({
+hexLabel: "十六进制"
+})
+
diff --git a/dojox/widget/nls/zh/FilePicker.js b/dojox/widget/nls/zh/FilePicker.js
index 3efdbc4..23cab53 100644
--- a/dojox/widget/nls/zh/FilePicker.js
+++ b/dojox/widget/nls/zh/FilePicker.js
@@ -1 +1,5 @@
-({"name":"名称","size":"大小(字节","path":"路径"})
\ No newline at end of file
+({
+name: "名称",
+path: "路径",
+size: "大小(字节"
+})
diff --git a/dojox/widget/nls/zh/Wizard.js b/dojox/widget/nls/zh/Wizard.js
index fe45203..3d9f229 100644
--- a/dojox/widget/nls/zh/Wizard.js
+++ b/dojox/widget/nls/zh/Wizard.js
@@ -1 +1,5 @@
-({"next":"下一步","done":"完成","previous":"上一步"})
\ No newline at end of file
+({
+next: "下一步",
+previous: "上一步",
+done: "完成"
+})
diff --git a/dojox/widget/rotator/Controller.js b/dojox/widget/rotator/Controller.js
index d6fda59..9931742 100644
--- a/dojox/widget/rotator/Controller.js
+++ b/dojox/widget/rotator/Controller.js
@@ -1,87 +1,192 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.rotator.Controller"]){
-dojo._hasResource["dojox.widget.rotator.Controller"]=true;
 dojo.provide("dojox.widget.rotator.Controller");
+
 (function(d){
-var _1="dojoxRotator",_2=_1+"Play",_3=_1+"Pause",_4=_1+"Number",_5=_1+"Tab",_6=_1+"Selected";
-d.declare("dojox.widget.rotator.Controller",null,{rotator:null,commands:"prev,play/pause,info,next",constructor:function(_7,_8){
-d.mixin(this,_7);
-var r=this.rotator;
-if(r){
-while(_8.firstChild){
-_8.removeChild(_8.firstChild);
-}
-var ul=this._domNode=d.create("ul",null,_8),_9=" "+_1+"Icon",cb=function(_a,_b,_c){
-d.create("li",{className:_b,innerHTML:"<a href=\"#\"><span>"+_a+"</span></a>",onclick:function(e){
-d.stopEvent(e);
-if(r){
-r.control.apply(r,_c);
-}
-}},ul);
-};
-d.forEach(this.commands.split(","),function(b,i){
-switch(b){
-case "prev":
-cb("Prev",_1+"Prev"+_9,["prev"]);
-break;
-case "play/pause":
-cb("Play",_2+_9,["play"]);
-cb("Pause",_3+_9,["pause"]);
-break;
-case "info":
-this._info=d.create("li",{className:_1+"Info",innerHTML:this._buildInfo(r)},ul);
-break;
-case "next":
-cb("Next",_1+"Next"+_9,["next"]);
-break;
-case "#":
-case "titles":
-for(var j=0;j<r.panes.length;j++){
-cb(b=="#"?j+1:r.panes[j].title||"Tab "+(j+1),(b=="#"?_4:_5)+" "+(j==r.idx?_6:"")+" "+_1+"Pane"+j,["go",j]);
-}
-break;
-}
-},this);
-d.query("li:first-child",ul).addClass(_1+"First");
-d.query("li:last-child",ul).addClass(_1+"Last");
-this._togglePlay();
-this._con=d.connect(r,"onUpdate",this,"_onUpdate");
-}
-},destroy:function(){
-d.disconnect(this._con);
-d.destroy(this._domNode);
-},_togglePlay:function(_d){
-var p=this.rotator.playing;
-d.query("."+_2,this._domNode).style("display",p?"none":"");
-d.query("."+_3,this._domNode).style("display",p?"":"none");
-},_buildInfo:function(r){
-return "<span>"+(r.idx+1)+" / "+r.panes.length+"</span>";
-},_onUpdate:function(_e){
-var r=this.rotator;
-switch(_e){
-case "play":
-case "pause":
-this._togglePlay();
-break;
-case "onAfterTransition":
-if(this._info){
-this._info.innerHTML=this._buildInfo(r);
-}
-var s=function(n){
-if(r.idx<n.length){
-d.addClass(n[r.idx],_6);
-}
-};
-s(d.query("."+_4,this._domNode).removeClass(_6));
-s(d.query("."+_5,this._domNode).removeClass(_6));
-break;
-}
-}});
-})(dojo);
-}
+
+	var _dojoxRotator = "dojoxRotator",
+		_play = _dojoxRotator + "Play",
+		_pause = _dojoxRotator + "Pause",
+		_number = _dojoxRotator + "Number",
+		_tab = _dojoxRotator + "Tab",
+		_selected = _dojoxRotator + "Selected";
+
+	d.declare("dojox.widget.rotator.Controller", null, {
+		//	summary:
+		//		A controller that manipulates a Rotator or AutoRotator.
+		//
+		//	description:
+		//		Displays a series of controls that send actions to a Rotator or
+		//		AutoRotator.  The Controller supports the following controls:
+		//
+		//		* Next pane
+		//		* Previous pane
+		//		* Play/Pause toggler
+		//		* Numbered tabs
+		//		* Titled tabs
+		//		* Information
+		//
+		//		You may specify any of these controls in any order.  You may also
+		//		have multiple Controllers tied to a single Rotator instance.
+		//
+		//		The Controller's DOM node may also be styled for positioning or
+		//		other styled preferences.
+		//
+		//	example:
+		//	|	<div dojoType="dojox.widget.rotator.Controller"
+		//	|		rotator="myRotator"
+		//	|	></div>
+		//
+		//	example:
+		//	|	<div dojoType="dojox.widget.rotator.Controller"
+		//	|		rotator="myRotator"
+		//	|		controls="prev,#,next"
+		//	|		class="myCtrl"
+		//	|	></div>
+		//
+		//	example:
+		//	|	<div dojoType="dojox.widget.rotator.Controller"
+		//	|		rotator="myRotator"
+		//	|		controls="titles"
+		//	|		class="myCtrl"
+		//	|	></div>s
+
+		//	rotator: dojox.widget.Rotator
+		//		An instance of a Rotator widget.
+		rotator: null,
+
+		//	commands: string
+		//		A comma-separated list of commands. Valid commands are:
+		//		  prev			An icon button to go to the previous pane.
+		//		  next			An icon button to go to the next pane.
+		//		  play/pause	A play and pause toggle icon button.
+		//		  info			Displays the current and total panes. (ie "1 / 4")
+		//		  #				Displays a number button for each pane. (ie "1 2 3 4")
+		//		  titles		Displays each pane's title as a tab. (ie "Home Services Contact Blog")
+		commands: "prev,play/pause,info,next",
+
+		constructor: function(/*Object*/params, /*DomNode|string*/node){
+			//	summary:
+			//		Initializes the pager and connect to the rotator.
+
+			d.mixin(this, params);
+
+			// check if we have a valid rotator
+			var r = this.rotator;
+			if(r){
+				// remove all of the controller's child nodes just in case
+				while(node.firstChild){
+					node.removeChild(node.firstChild);
+				}
+
+				var ul = this._domNode = d.create("ul", null, node),
+					icon = " " + _dojoxRotator + "Icon",
+
+					// helper function for creating a button
+					cb = function(/*string*/label, /*string*/css, /*array*/action){
+						d.create("li", {
+							className: css,
+							innerHTML: '<a href="#"><span>' + label + '</span></a>',
+							onclick: function(/*event*/e){
+								d.stopEvent(e);
+								if(r){
+									r.control.apply(r, action);
+								}
+							}
+						}, ul);
+					};
+
+				// build out the commands
+				d.forEach(this.commands.split(','), function(b, i){
+					switch(b){
+						case "prev":
+							cb("Prev", _dojoxRotator + "Prev" + icon, ["prev"]);
+							break;
+						case "play/pause":
+							cb("Play", _play + icon, ["play"]);
+							cb("Pause", _pause + icon, ["pause"]);
+							break;
+						case "info":
+							this._info = d.create("li", {
+								className: _dojoxRotator + "Info",
+								innerHTML: this._buildInfo(r)
+							}, ul);
+							break;
+						case "next":
+							cb("Next", _dojoxRotator + "Next" + icon, ["next"]);
+							break;
+						case "#":
+						case "titles":
+							for(var j=0; j<r.panes.length; j++){
+								cb(
+									/*label*/ b == '#' ? j+1 : r.panes[j].title || "Tab " + (j+1),
+									/*css*/ (b == '#' ? _number : _tab) + ' ' + (j == r.idx ? _selected : "") + ' ' + _dojoxRotator + "Pane" + j,
+									/*action*/ ["go", j]
+								);
+							}
+							break;
+					}
+				}, this);
+
+				// add the first/last classes for styling
+				d.query("li:first-child", ul).addClass(_dojoxRotator + "First");
+				d.query("li:last-child", ul).addClass(_dojoxRotator + "Last");
+
+				// set the initial state of the play/pause toggle button
+				this._togglePlay();
+
+				this._con = d.connect(r, "onUpdate", this, "_onUpdate");
+			}
+		},
+
+		destroy: function(){
+			//	summary:
+			//		Disconnect from the rotator.
+			d.disconnect(this._con);
+			d.destroy(this._domNode);
+		},
+
+		_togglePlay: function(/*boolean*/playing){
+			//	summary:
+			//		Toggles the play/pause button, if it exists.
+
+			var p = this.rotator.playing;
+			d.query('.'+_play, this._domNode).style("display", p ? "none" : "");
+			d.query('.'+_pause, this._domNode).style("display", p ? "" : "none");
+		},
+
+		_buildInfo: function(/*dojox.widget.Rotator*/r){
+			//	summary:
+			//		Return a string containing the current pane number and the total number of panes.
+			return '<span>' + (r.idx+1) + ' / ' + r.panes.length + '</span>'; /*string*/
+		},
+
+		_onUpdate: function(/*string*/type){
+			//	summary:
+			//		Updates various pager controls when the rotator updates.
+
+			var r = this.rotator; // no need to test if this is null since _onUpdate is only fired by the rotator
+
+			switch(type){
+				case "play":
+				case "pause":
+					this._togglePlay();
+					break;
+				case "onAfterTransition":
+					if(this._info){
+						this._info.innerHTML = this._buildInfo(r);
+					}
+
+					// helper function for selecting the current tab
+					var s = function(/*NodeList*/n){
+						if(r.idx < n.length){
+							d.addClass(n[r.idx], _selected);
+						}
+					};
+
+					s(d.query('.' + _number, this._domNode).removeClass(_selected));
+					s(d.query('.' + _tab, this._domNode).removeClass(_selected));
+					break;
+			}
+		}
+	});
+
+})(dojo);
\ No newline at end of file
diff --git a/dojox/widget/rotator/Fade.js b/dojox/widget/rotator/Fade.js
index 6c85de3..3fdf974 100644
--- a/dojox/widget/rotator/Fade.js
+++ b/dojox/widget/rotator/Fade.js
@@ -1,25 +1,40 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.rotator.Fade"]){
-dojo._hasResource["dojox.widget.rotator.Fade"]=true;
 dojo.provide("dojox.widget.rotator.Fade");
 dojo.require("dojo.fx");
+
 (function(d){
-function _1(_2,_3){
-var n=_2.next.node;
-d.style(n,{display:"",opacity:0});
-_2.node=_2.current.node;
-return d.fx[_3]([d.fadeOut(_2),d.fadeIn(d.mixin(_2,{node:n}))]);
-};
-d.mixin(dojox.widget.rotator,{fade:function(_4){
-return _1(_4,"chain");
-},crossFade:function(_5){
-return _1(_5,"combine");
-}});
-})(dojo);
-}
+
+	function _fade(/*Object*/args, /*string*/action){
+		//	summary:
+		//		Returns an animation of a fade out and fade in of the current and next
+		//		panes.  It will either chain (fade) or combine (crossFade) the fade
+		//		animations.
+		var n = args.next.node;
+		d.style(n, {
+			display: "",
+			opacity: 0
+		});
+
+		args.node = args.current.node;
+
+		return d.fx[action]([ /*dojo.Animation*/
+			d.fadeOut(args),
+			d.fadeIn(d.mixin(args, { node: n }))
+		]);
+	}
+
+	d.mixin(dojox.widget.rotator, {
+		fade: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that fades out the current pane, then fades in
+			//		the next pane.
+			return _fade(args, "chain"); /*dojo.Animation*/
+		},
+
+		crossFade: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that cross fades two rotator panes.
+			return _fade(args, "combine"); /*dojo.Animation*/
+		}
+	});
+
+})(dojo);
\ No newline at end of file
diff --git a/dojox/widget/rotator/Pan.js b/dojox/widget/rotator/Pan.js
index 03877fc..834b363 100644
--- a/dojox/widget/rotator/Pan.js
+++ b/dojox/widget/rotator/Pan.js
@@ -1,75 +1,207 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.rotator.Pan"]){
-dojo._hasResource["dojox.widget.rotator.Pan"]=true;
 dojo.provide("dojox.widget.rotator.Pan");
 dojo.require("dojo.fx");
+
 (function(d){
-var _1=0,_2=1,UP=2,_3=3;
-function _4(_5,_6){
-var n=_6.next.node,r=_6.rotatorBox,m=_5%2,a=m?"left":"top",s=(m?r.w:r.h)*(_5<2?-1:1),p={},q={};
-d.style(n,"display","");
-p[a]={start:0,end:-s};
-q[a]={start:s,end:0};
-return d.fx.combine([d.animateProperty({node:_6.current.node,duration:_6.duration,properties:p,easing:_6.easing}),d.animateProperty({node:n,duration:_6.duration,properties:q,easing:_6.easing})]);
-};
-function _7(n,z){
-d.style(n,"zIndex",z);
-};
-d.mixin(dojox.widget.rotator,{pan:function(_8){
-var w=_8.wrap,p=_8.rotator.panes,_9=p.length,z=_9,j=_8.current.idx,k=_8.next.idx,nw=Math.abs(k-j),ww=Math.abs((_9-Math.max(j,k))+Math.min(j,k))%_9,_a=j<k,_b=_3,_c=[],_d=[],_e=_8.duration;
-if((!w&&!_a)||(w&&(_a&&nw>ww||!_a&&nw<ww))){
-_b=_2;
-}
-if(_8.continuous){
-if(_8.quick){
-_e=Math.round(_e/(w?Math.min(ww,nw):nw));
-}
-_7(p[j].node,z--);
-var f=(_b==_3);
-while(1){
-var i=j;
-if(f){
-if(++j>=_9){
-j=0;
-}
-}else{
-if(--j<0){
-j=_9-1;
-}
-}
-var x=p[i],y=p[j];
-_7(y.node,z--);
-_c.push(_4(_b,d.mixin({easing:function(m){
-return m;
-}},_8,{current:x,next:y,duration:_e})));
-if((f&&j==k)||(!f&&j==k)){
-break;
-}
-_d.push(y.node);
-}
-var _f=d.fx.chain(_c),h=d.connect(_f,"onEnd",function(){
-d.disconnect(h);
-d.forEach(_d,function(q){
-d.style(q,{display:"none",left:0,opacity:1,top:0,zIndex:0});
-});
-});
-return _f;
-}
-return _4(_b,_8);
-},panDown:function(_10){
-return _4(_1,_10);
-},panRight:function(_11){
-return _4(_2,_11);
-},panUp:function(_12){
-return _4(UP,_12);
-},panLeft:function(_13){
-return _4(_3,_13);
-}});
+
+	// Constants used to identify which edge the pane pans in from.
+	var DOWN = 0,
+		RIGHT = 1,
+		UP = 2,
+		LEFT = 3;
+
+	function _pan(/*int*/type, /*Object*/args){
+		//	summary:
+		//		Handles the preparation of the dom node and creates the dojo.Animation object.
+		var n = args.next.node,
+			r = args.rotatorBox,
+			m = type % 2,
+			a = m ? "left" : "top",
+			s = (m ? r.w : r.h) * (type < 2 ? -1 : 1),
+			p = {},
+			q = {};
+
+		d.style(n, "display", "");
+
+		p[a] = {
+			start: 0,
+			end: -s
+		};
+
+		q[a] = {
+			start: s,
+			end: 0
+		};
+
+		return d.fx.combine([ /*dojo.Animation*/
+			d.animateProperty({
+				node: args.current.node,
+				duration: args.duration,
+				properties: p,
+				easing: args.easing
+			}),
+			d.animateProperty({
+				node: n,
+				duration: args.duration,
+				properties: q,
+				easing: args.easing
+			})
+		]);
+	}
+
+	function _setZindex(/*DomNode*/n, /*int*/z){
+		//	summary:
+		//		Helper function for continuously panning.
+		d.style(n, "zIndex", z);
+	}
+
+	d.mixin(dojox.widget.rotator, {
+		pan: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that either pans left or right to the next pane.
+			//		The actual direction depends on the order of the panes.
+			//
+			//		If panning forward from index 1 to 3, it will perform a pan left. If panning
+			//		backwards from 5 to 1, then it will perform a pan right.
+			//
+			//		If the parameter "continuous" is set to true, it will return an animation
+			//		chain of several pan animations of each intermediate pane panning. For
+			//		example, if you pan forward from 1 to 3, it will return an animation panning
+			//		left from 1 to 2 and then 2 to 3.
+			//
+			//		If an easing is specified, it will be applied to each pan transition.  For
+			//		example, if you are panning from pane 1 to pane 5 and you set the easing to
+			//		"dojo.fx.easing.elasticInOut", then it will "wobble" 5 times, once for each
+			//		pan transition.
+			//
+			//		If the parameter "wrap" is set to true, it will pan to the next pane using
+			//		the shortest distance in the array of panes. For example, if there are 6
+			//		panes, then panning from 5 to 1 will pan forward (left) from pane 5 to 6 and
+			//		6 to 1.  If the distance is the same either going forward or backwards, then
+			//		it will always pan forward (left).
+			//
+			//		A continuous pan will use the target pane's duration to pan all intermediate
+			//		panes.  To use the target's pane duration for each intermediate pane, then
+			//		set the "quick" parameter to "false".
+
+			var w = args.wrap,
+				p = args.rotator.panes,
+				len = p.length,
+				z = len,
+				j = args.current.idx,
+				k = args.next.idx,
+				nw = Math.abs(k - j),
+				ww = Math.abs((len - Math.max(j, k)) + Math.min(j, k)) % len,
+				_forward = j < k,
+				_dir = LEFT,
+				_pans = [],
+				_nodes = [],
+				_duration = args.duration;
+
+			// default to pan left, but check if we should pan right.
+			// need to take into account wrapping.
+			if((!w && !_forward) || (w && (_forward && nw > ww || !_forward && nw < ww))){
+				_dir = RIGHT;
+			}
+
+			if(args.continuous){
+				// if continuous pans are quick, then divide the duration by the number of panes
+				if(args.quick){
+					_duration = Math.round(_duration / (w ? Math.min(ww, nw) : nw));
+				}
+
+				// set the current pane's z-index
+				_setZindex(p[j].node, z--);
+
+				var f = (_dir == LEFT);
+
+				// loop and set z-indexes and get all pan animations
+				while(1){
+					// set the current pane
+					var i = j;
+
+					// increment/decrement the next pane's index
+					if(f){
+						if(++j >= len){
+							j = 0;
+						}
+					}else{
+						if(--j < 0){
+							j = len - 1;
+						}
+					}
+
+					var x = p[i],
+						y = p[j];
+
+					// set next pane's z-index
+					_setZindex(y.node, z--);
+
+					// build the pan animation
+					_pans.push(_pan(_dir, d.mixin({
+						easing: function(m){ return m; } // continuous gets a linear easing by default
+					}, args, {
+						current: x,
+						next: y,
+						duration: _duration
+					})));
+
+					// if we're done, then break out of the loop
+					if((f && j == k) || (!f && j == k)){
+						break;
+					}
+
+					// this must come after the break... we don't want the last pane to get it's
+					// styles reset.
+					_nodes.push(y.node);
+				}
+
+				// build the chained animation of all pan animations
+				var _anim = d.fx.chain(_pans),
+
+					// clean up styles when the chained animation finishes
+					h = d.connect(_anim, "onEnd", function(){
+						d.disconnect(h);
+						d.forEach(_nodes, function(q){
+							d.style(q, {
+								display: "none",
+								left: 0,
+								opacity: 1,
+								top: 0,
+								zIndex: 0
+							});
+						});
+					});
+
+				return _anim;
+			}
+
+			// we're not continuous, so just return a normal pan animation
+			return _pan(_dir, args); /*dojo.Animation*/
+		},
+
+		panDown: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that pans in the next rotator pane from the top.
+			return _pan(DOWN, args); /*dojo.Animation*/
+		},
+
+		panRight: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that pans in the next rotator pane from the right.
+			return _pan(RIGHT, args); /*dojo.Animation*/
+		},
+
+		panUp: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that pans in the next rotator pane from the bottom.
+			return _pan(UP, args); /*dojo.Animation*/
+		},
+
+		panLeft: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that pans in the next rotator pane from the left.
+			return _pan(LEFT, args); /*dojo.Animation*/
+		}
+	});
+
 })(dojo);
-}
diff --git a/dojox/widget/rotator/Slide.js b/dojox/widget/rotator/Slide.js
index 03846c9..dc1196c 100644
--- a/dojox/widget/rotator/Slide.js
+++ b/dojox/widget/rotator/Slide.js
@@ -1,32 +1,61 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.rotator.Slide"]){
-dojo._hasResource["dojox.widget.rotator.Slide"]=true;
 dojo.provide("dojox.widget.rotator.Slide");
+
 (function(d){
-var _1=0,_2=1,UP=2,_3=3;
-function _4(_5,_6){
-var _7=_6.node=_6.next.node,r=_6.rotatorBox,m=_5%2,s=(m?r.w:r.h)*(_5<2?-1:1);
-d.style(_7,{display:"",zIndex:(d.style(_6.current.node,"zIndex")||1)+1});
-if(!_6.properties){
-_6.properties={};
-}
-_6.properties[m?"left":"top"]={start:s,end:0};
-return d.animateProperty(_6);
-};
-d.mixin(dojox.widget.rotator,{slideDown:function(_8){
-return _4(_1,_8);
-},slideRight:function(_9){
-return _4(_2,_9);
-},slideUp:function(_a){
-return _4(UP,_a);
-},slideLeft:function(_b){
-return _4(_3,_b);
-}});
+
+	// Constants used to identify which edge the pane slides in from.
+	var DOWN = 0,
+		RIGHT = 1,
+		UP = 2,
+		LEFT = 3;
+
+	function _slide(/*int*/type, /*Object*/args){
+		//	summary:
+		//		Handles the preparation of the dom node and creates the dojo.Animation object.
+		var node = args.node = args.next.node,
+			r = args.rotatorBox,
+			m = type % 2,
+			s = (m ? r.w : r.h) * (type < 2 ? -1 : 1);
+
+		d.style(node, {
+			display: "",
+			zIndex: (d.style(args.current.node, "zIndex") || 1) + 1
+		});
+
+		if(!args.properties){
+			args.properties = {};
+		}
+		args.properties[m ? "left" : "top"] = {
+			start: s,
+			end: 0
+		};
+
+		return d.animateProperty(args); /*dojo.Animation*/
+	}
+
+	d.mixin(dojox.widget.rotator, {
+		slideDown: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that slides in the next rotator pane from the top.
+			return _slide(DOWN, args); /*dojo.Animation*/
+		},
+
+		slideRight: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that slides in the next rotator pane from the right.
+			return _slide(RIGHT, args); /*dojo.Animation*/
+		},
+
+		slideUp: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that slides in the next rotator pane from the bottom.
+			return _slide(UP, args); /*dojo.Animation*/
+		},
+
+		slideLeft: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that slides in the next rotator pane from the left.
+			return _slide(LEFT, args); /*dojo.Animation*/
+		}
+	});
+
 })(dojo);
-}
diff --git a/dojox/widget/rotator/ThumbnailController.js b/dojox/widget/rotator/ThumbnailController.js
new file mode 100644
index 0000000..c080c8f
--- /dev/null
+++ b/dojox/widget/rotator/ThumbnailController.js
@@ -0,0 +1,96 @@
+dojo.provide("dojox.widget.rotator.ThumbnailController");
+
+(function(d){
+
+	var _css = "dojoxRotatorThumb",
+		_selected = _css + "Selected";
+
+	d.declare("dojox.widget.rotator.ThumbnailController", null, {
+		//	summary:
+		//		A rotator controller that displays thumbnails of each rotator pane.
+		//
+		//	description:
+		//		The ThumbnailController will look at each of the rotator's panes and
+		//		only if the node is an <img> tag, then it will create an thumbnail of
+		//		the pane's image using the <img> tag's "thumbsrc" or "src" attribute.
+		//
+		//		The size of the thumbnails and the style of the selected thumbnail is
+		//		controlled using CSS.
+		//
+		//	example:
+		//	|	<div dojoType="dojox.widget.Rotator" jsId="myRotator">
+		//	|		<img src="/path/to/image1.jpg" thumbsrc="/path/to/thumb1.jpg" alt="Image 1"/>
+		//	|		<img src="/path/to/image2.jpg" thumbsrc="/path/to/thumb2.jpg" alt="Image 2"/>
+		//	|	</div>
+		//	|	<div dojoType="dojox.widget.rotator.ThumbnailController" rotator="myRotator"></div>
+
+		//	rotator: dojox.widget.Rotator
+		//		An instance of a Rotator widget.
+		rotator: null,
+
+		constructor: function(/*Object*/params, /*DomNode|string*/node){
+			//	summary:
+			//		Initializes the thumbnails and connect to the rotator.
+
+			d.mixin(this, params);
+
+			this._domNode = node;
+
+			// check if we have a valid rotator
+			var r = this.rotator;
+			if(r){
+				// remove all of the controller's child nodes just in case
+				while(node.firstChild){
+					node.removeChild(node.firstChild);
+				}
+
+				for(var i=0; i<r.panes.length; i++){
+					var n = r.panes[i].node,
+						s = d.attr(n, "thumbsrc") || d.attr(n, "src"),
+						t = d.attr(n, "alt") || "";
+
+					if(/img/i.test(n.tagName)){
+						(function(j){
+							d.create("a", {
+								classname: _css + ' ' + _css + j + ' ' + (j == r.idx ? _selected : ""),
+								href: s,
+								onclick: function(e){
+									d.stopEvent(e);
+									if(r){
+										r.control.apply(r, ["go", j]);
+									}
+								},
+								title: t,
+								innerHTML: '<img src="' + s + '" alt="' + t + '"/>'
+							}, node);
+						})(i);
+					}
+				}
+
+				this._con = d.connect(r, "onUpdate", this, "_onUpdate");
+			}
+		},
+
+		destroy: function(){
+			//	summary:
+			//		Disconnect from the rotator.
+
+			d.disconnect(this._con);
+			d.destroy(this._domNode);
+		},
+
+		_onUpdate: function(/*string*/type){
+			//	summary:
+			//		Updates various pager controls when the rotator updates.
+
+			var r = this.rotator; // no need to test if this is null since _onUpdate is only fired by the rotator
+			if(type == "onAfterTransition"){
+				var n = d.query('.' + _css, this._domNode).removeClass(_selected);
+				if(r.idx < n.length){
+					d.addClass(n[r.idx], _selected);
+				}
+			}
+		}
+	});
+
+})(dojo);
\ No newline at end of file
diff --git a/dojox/widget/rotator/Wipe.js b/dojox/widget/rotator/Wipe.js
index af1fc39..763c187 100644
--- a/dojox/widget/rotator/Wipe.js
+++ b/dojox/widget/rotator/Wipe.js
@@ -1,52 +1,87 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.widget.rotator.Wipe"]){
-dojo._hasResource["dojox.widget.rotator.Wipe"]=true;
 dojo.provide("dojox.widget.rotator.Wipe");
+
 (function(d){
-var _1=2,_2=3,UP=0,_3=1;
-function _4(_5,w,h,x){
-var a=[0,w,0,0];
-if(_5==_2){
-a=[0,w,h,w];
-}else{
-if(_5==UP){
-a=[h,w,h,0];
-}else{
-if(_5==_3){
-a=[0,0,h,0];
-}
-}
-}
-if(x!=null){
-a[_5]=_5==_1||_5==_3?x:(_5%2?w:h)-x;
-}
-return a;
-};
-function _6(n,_7,w,h,x){
-d.style(n,"clip",_7==null?"auto":"rect("+_4(_7,w,h,x).join("px,")+"px)");
-};
-function _8(_9,_a){
-var _b=_a.next.node,w=_a.rotatorBox.w,h=_a.rotatorBox.h;
-d.style(_b,{display:"",zIndex:(d.style(_a.current.node,"zIndex")||1)+1});
-_6(_b,_9,w,h);
-return new d.Animation(d.mixin({node:_b,curve:[0,_9%2?w:h],onAnimate:function(x){
-_6(_b,_9,w,h,parseInt(x));
-}},_a));
-};
-d.mixin(dojox.widget.rotator,{wipeDown:function(_c){
-return _8(_1,_c);
-},wipeRight:function(_d){
-return _8(_2,_d);
-},wipeUp:function(_e){
-return _8(UP,_e);
-},wipeLeft:function(_f){
-return _8(_3,_f);
-}});
+
+	// Constants used to identify which clip edge is being wiped. The values are
+	// the index of the clip array that is changed during the animation.
+	var DOWN = 2,
+		RIGHT = 3,
+		UP = 0,
+		LEFT = 1;
+
+	function _clipArray(/*int*/type, /*int*/w, /*int*/h, /*number*/x){
+		// summary:
+		//		Returns an array containing the down, right, up, and
+		//		left clip region based on the type.  If "x" is specified,
+		//		then it is applied to the appropriate clipping edge.
+		var a = [0, w, 0, 0]; // default to the top edge
+		if(type == RIGHT){
+			a = [0, w, h, w];
+		}else if(type == UP){
+			a = [h, w, h, 0];
+		}else if(type == LEFT){
+			a = [0, 0, h, 0];
+		}
+		if(x != null){
+			a[type] = type == DOWN || type == LEFT ? x : (type % 2 ? w : h) - x;
+		}
+		return a; /*Array*/
+	}
+
+	function _setClip(/*DomNode*/n, /*int*/type, /*int*/w, /*int*/h, /*number*/x){
+		//	summary:
+		//		Sets the clip region of the node. If a type is passed in then we
+		//		return a rect(), otherwise return "auto".
+		d.style(n, "clip", type == null ? "auto" : "rect(" + _clipArray(type, w, h, x).join("px,") + "px)");
+	}
+
+	function _wipe(/*int*/type, /*Object*/args){
+		//	summary:
+		//		Handles the preparation of the dom node and creates the dojo.Animation object.
+		var node = args.next.node,
+			w = args.rotatorBox.w,
+			h = args.rotatorBox.h;
+
+		d.style(node, {
+			display: "",
+			zIndex: (d.style(args.current.node, "zIndex") || 1) + 1
+		});
+
+		_setClip(node, type, w, h);
+
+		return new d.Animation(d.mixin({ /*dojo.Animation*/
+			node: node,
+			curve: [0, type % 2 ? w : h],
+			onAnimate: function(x){
+				_setClip(node, type, w, h, parseInt(x));
+			}
+		}, args));
+	}
+
+	d.mixin(dojox.widget.rotator, {
+		wipeDown: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that wipes in the next rotator pane from the top.
+			return _wipe(DOWN, args); /*dojo.Animation*/
+		},
+
+		wipeRight: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that wipes in the next rotator pane from the right.
+			return _wipe(RIGHT, args); /*dojo.Animation*/
+		},
+
+		wipeUp: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that wipes in the next rotator pane from the bottom.
+			return _wipe(UP, args); /*dojo.Animation*/
+		},
+
+		wipeLeft: function(/*Object*/args){
+			//	summary:
+			//		Returns a dojo.Animation that wipes in the next rotator pane from the left.
+			return _wipe(LEFT, args); /*dojo.Animation*/
+		}
+	});
+
 })(dojo);
-}
diff --git a/dojox/widget/tests/CalendarStackLayout.js b/dojox/widget/tests/CalendarStackLayout.js
new file mode 100644
index 0000000..a927fe7
--- /dev/null
+++ b/dojox/widget/tests/CalendarStackLayout.js
@@ -0,0 +1,99 @@
+dojo.provide("dojox.widget.tests.CalendarStackLayout");
+dojo.require("dijit.layout.ContentPane");
+dojo.require("dijit.layout.StackContainer");
+dojo.require("dojox.widget.Calendar");
+dojo.require("dijit._Widget");
+dojo.require("dijit._Container");
+dojo.require("dojo.string");
+
+dojo.declare("dojox.widget.tests.CalendarStackLayout", [dijit._Widget, dijit._Container],{
+	dateToPane: {},
+	startup: function(){
+		if(this._started){
+			return null;
+		}
+		
+		// Get a list of the stack panes
+		var kids = this.getChildren();
+		var dates = [];
+
+		// Store the dates for each pane
+		dojo.forEach(kids, dojo.hitch(this, function(childContainer){
+			var dateRef = childContainer.domNode.getAttribute("dateref");
+			this.dateToPane[dateRef] = childContainer;
+			
+			var parts = dateRef.split("-");
+			var date = new Date();
+			date.setFullYear(parts[0]);
+			date.setMonth(Number(parts[1]) - 1);
+			date.setDate(parts[2]);
+			dates.push(date.getTime());
+		}));
+		
+		dates.sort();
+		var lastDate = new Date(dates[dates.length -1]);
+		var firstDate = new Date(dates[0]);
+
+		var _this = this;
+
+		function getChildByDate(date){
+			return _this.dateToPane[
+				date.getFullYear() 
+				+  "-" + dojo.string.pad(String(date.getMonth() + 1), 2) 
+				+ "-" + dojo.string.pad(String(date.getDate()))];
+		}
+
+		// Instantiate the calendar, overriding the getClassForDate and isDisabledDate functions
+		this.calendar = new dojox.widget.Calendar({
+			getClassForDate: function(date){
+				return getChildByDate(date) ? " hasAppointment" : " noAppointment";
+		    },
+
+		    isDisabledDate: function(date){
+				return getChildByDate(date) ? false : true;
+		    }
+		});
+		
+		if(this.calendar.attr("value").getTime() > lastDate.getTime()){
+			this.calendar.attr("value", lastDate);
+		}else if(this.calendar.attr("value").getTime() < firstDate.getTime()){
+			this.calendar.attr("value", firstDate);
+		}
+
+		// Instantiate the stack container
+		this.stack = new dijit.layout.StackContainer();
+		dojo.addClass(this.stack.domNode, "calendarStack");
+
+		//Add the calendar and stack container to this widget
+		this.addChild(this.calendar);
+		this.addChild(this.stack);
+
+		// Set up some styles on the calendar and stack container
+		dojo.style(this.stack.domNode, "width", dojo.style(this.calendar.domNode, "width") + "px");
+		
+		dojo.addClass(this.stack.domNode, "dijitCalendarStackDetails");
+
+		// Add all the content panes to the stack container
+		dojo.forEach(kids, dojo.hitch(this,function(childContainer){
+			this.stack.addChild(childContainer);
+		}));
+
+		// Add a listener to the onValueSelected method of the calendar
+		// to select the correct pane
+		dojo.connect(this.calendar, "onValueSelected", dojo.hitch(this, function(date){
+			var pane = getChildByDate(date);
+
+			if(pane){
+				this.stack.selectChild(pane);
+			}
+		}));
+		
+		// Show the last pane automatically
+		this.stack.selectChild(kids[kids.length - 1]);
+			if(!this.stack.started && !this.stack._started){
+				this.stack.startup();
+			}
+		return this.inherited(arguments);
+		
+	}
+});
\ No newline at end of file
diff --git a/dojox/widget/tests/_pager-data.json b/dojox/widget/tests/_pager-data.json
new file mode 100644
index 0000000..2699790
--- /dev/null
+++ b/dojox/widget/tests/_pager-data.json
@@ -0,0 +1,19 @@
+{
+	identifier: 'name',
+	label:'label',
+	items: [
+		{ name:'widget0', label: 'dojoforDummies',      content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget1', label: 'dojoforaDummies',    content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget2', label: 'dojoforDdsummies',   content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget3', label: 'dojoforDudmmies',    content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget4', label: 'dojoforDfummies',  content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget5', label: 'dojotforDfummies', content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget6', label: 'dojofrorDfummies', content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget7', label: 'dojoforDfumemies', content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget8', label: 'dojoforDfummwies', content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget9', label: 'dojofodrDfummies', content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget10', label: 'dojofforDfummies', content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget11', label: 'dojofodrDfummies', content: '<p>FoobarBAZ!</p>' },
+		{ name:'widget12', label: 'dojoforsDumfgmies',content: '<p>FoobarBAZ!</p>' }
+	]
+}
\ No newline at end of file
diff --git a/dojox/widget/tests/demo_FisheyeList.html b/dojox/widget/tests/demo_FisheyeList.html
new file mode 100644
index 0000000..703fc55
--- /dev/null
+++ b/dojox/widget/tests/demo_FisheyeList.html
@@ -0,0 +1,117 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>FisheyeList Widget Demonstration</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+	
+		.fisheyebar {
+			width:550px;
+			margin: 0 auto;
+			text-align: center;
+		}
+
+		.outerbar {
+			background-color: #666;
+			text-align: center;
+			position: absolute;
+			left: 0px;
+			top: 0px;
+			width: 100%;
+			height:85px; 
+			border-bottom:2px solid #333;
+		}
+		
+		body {
+			font-family: Arial, Helvetica, sans-serif;
+			padding: 0;
+			margin: 0;
+			background-color:#fff;
+			background-image:none; 
+		}
+		
+		.page {
+			padding: 85px 20px 20px 20px;
+		}
+		.outerbar img {
+			top:0;
+			position:relative;
+			vertical-align:super;
+			float:left;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.widget.FisheyeLite");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		function load_app(id){
+			alert('icon '+id+' was clicked');
+		}
+
+	</script>
+</head>
+<body class="tundra"><div class="outerbar">
+	<div class="fisheyebar">
+	<img dojoType="dojox.widget.FisheyeLite"
+		style="width:75px; height:75px"
+		properties="{ width:1.65, height:1.65 }"
+		onClick="alert('click on ' + this.label + '(from widget id ' + this.widgetid + ')!');"
+		src="images/icon_browser.png"
+	/>
+
+	<img dojoType="dojox.widget.FisheyeLite"
+		label="Item 2"
+		src="images/icon_calendar.png"
+		style="width:75px; height:75px"
+		properties="{ width:1.65, height:1.65 }"
+	/>
+
+	<img dojoType="dojox.widget.FisheyeLite"
+		label="Item 3"
+		style="width:75px; height:75px"
+		properties="{ width:1.55, height:1.65 }"
+		onClick="alert('click on ' + this.label + '(from widget id ' + this.widgetid + ')!');"
+		src="images/icon_email.png"
+	/>
+
+	<img dojoType="dojox.widget.FisheyeLite"
+		src="images/icon_texteditor.png" style="width:75px; height:75px"
+		properties="{ width:1.65, height:1.65 }"
+	/>
+
+	<img dojoType="dojox.widget.FisheyeLite"
+		label="Really Long Item Label"
+		src="images/icon_update.png"
+		style="width:75px; height:75px"
+		properties="{ width:1.65, height:1.65 }"
+	/>
+
+	<img dojoType="dojox.widget.FisheyeLite"
+		src="images/icon_users.png"
+		style="width:75px; height:75px"
+		properties="{ width:1.75, height:1.75 }"
+	/>
+</div></div>
+
+<div class="page">
+	<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam facilisis enim. Pellentesque in elit et lacus euismod dignissim. Aliquam dolor pede, convallis eget, dictum a, blandit ac, urna. Pellentesque sed nunc ut justo volutpat egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. In erat. Suspendisse potenti. Fusce faucibus nibh sed nisi. Phasellus faucibus, dui a cursus dapibus, mauris nulla euismod velit, a lobortis turpis arcu vel [...]
+
+	<p>Sed congue. Aenean blandit sollicitudin mi. Maecenas pellentesque. Vivamus ac urna. Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin suscipit porta magna. Duis accumsan nunc in velit. Nam et nibh. Nulla facilisi. Cras venenatis urna et magna. Aenean magna mauris, bibendum sit amet, semper quis, aliquet nec, sapien. Aliquam aliquam odio quis erat. Etiam est nisi, condimentum non, lacinia ac, vehicula laoreet, elit. Sed interdum augue sit amet quam dapibus semper. Nulla faci [...]
+
+	<p>Sed arcu magna, molestie at, fringilla in, sodales eu, elit. Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus ut elit convallis eleifend. Fusce tincidunt, justo quis tempus euismod, magna nulla viverra libero, sit amet lacinia odio diam id risus. Ut varius viverra turpis. M [...]
+
+	<p>Fusce rutrum pede eget quam. Praesent purus. Aenean at elit in sem volutpat facilisis. Nunc est augue, commodo at, pretium a, fermentum at, quam. Nam sit amet enim. Suspendisse potenti. Cras hendrerit rhoncus justo. Integer libero. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam erat volutpat. Sed adipiscing mi vel ipsum.</p>
+
+	<p>Sed aliquam, quam consectetuer condimentum bibendum, neque libero commodo metus, non consectetuer magna risus vitae eros. Pellentesque mollis augue id libero. Morbi nonummy hendrerit dui. Morbi nisi felis, fringilla ac, euismod vitae, dictum mollis, pede. Integer suscipit, est sed posuere ullamcorper, ipsum lectus interdum nunc, quis blandit erat eros hendrerit pede. Vestibulum varius, elit id mattis mattis, nulla est feugiat ante, eget vestibulum augue eros ut odio. Maecenas euismod [...]
+
+
+</div>
+
+
+
+</body>
+</html>
diff --git a/dojox/widget/tests/demo_FisheyeLite.html b/dojox/widget/tests/demo_FisheyeLite.html
new file mode 100644
index 0000000..e937698
--- /dev/null
+++ b/dojox/widget/tests/demo_FisheyeLite.html
@@ -0,0 +1,175 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+	<title>A responsive Fisheye-like FisheyeLite widget | The Dojo Toolkit</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dojox/layout/resources/RadioGroup.css";
+	    body, html { margin:0; padding:0; width:100%;
+			font-family:Arial,sans-serif;
+		}
+		
+		#content {
+			height:300px;
+			border-left:1px solid #333;
+			border-right:1px solid #333;
+		}
+		
+		#container {
+			top:150px;
+			width:720px;
+			margin:0 auto;
+		}
+		#header {
+			position:relative;
+			height:90px;
+			border-bottom:1px solid #dedede;
+		}
+		#dojoLink, #dijitLink, #dojoxLink {
+			background:#dedede;
+			position:absolute;
+			bottom:0;
+			width:200px;
+			padding:0;
+			cursor:pointer;
+		}
+		#dojoLink {
+			left:20px;
+		}
+		#dojoxLink {
+			left:460px;
+		}
+		#dijitLink {
+			left:240px;
+		}
+		.fisheyeTarget {
+			position:relative;
+			bottom:0;
+			left:0;
+			height:1px;
+			width:1px;
+			cursor:pointer;
+		}
+		.inner {
+			cursor:pointer;
+			position:absolute;
+			bottom:5px;
+			margin-left:10px;
+		}
+		.subtext {
+			visibility:hidden;
+			position:absolute;
+			bottom:27px;
+			left:10px;
+			font:8pt Arial,sans-serif;
+			color:#666;
+		}
+		.cpContent {
+			padding:15px;
+		}
+		.cp {
+			background:#bebebe;
+			color:#666;
+		}
+	</style>
+	<script type="text/javascript">
+		var djConfig = { isDebug:true, parseOnLoad:true };
+	</script>
+	<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+	<script type="text/javascript" src="../FisheyeLite.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojox.layout.RadioGroup");
+		dojo.require("dojox.widget.FisheyeLite");
+		dojo.require("dojox.fx.easing");
+		dojo.addOnLoad(function(){
+			dojo.query(".headLink").forEach(function(n){
+
+				var linkto = dojo.attr(n,"id") + "Pane";
+				
+				var widget = new dojox.widget.FisheyeLite({
+					properties: {
+						height:45
+					},
+					easeOut:dojox.fx.easing.bounceOut,
+					durationOut:700
+				},n);
+				
+				var myTarget = dojo.query(".subtext",n)[0];
+				if(myTarget){
+					
+					dojo.style(myTarget,{ opacity:"0", visibility:"visible" });
+					
+					var _anim = null;
+					dojo.connect(widget,"show",function(e){
+						_anim && _anim.status && _anim.stop();
+						_anim = dojo.fadeIn({ node: myTarget, duration:250 });
+						_anim.play();
+					});
+					dojo.connect(widget,"hide",function(e){
+						_anim && _anim.status && _anim.stop();
+						_anim = dojo.fadeOut({ node: myTarget, duration:250 });
+						_anim.play();
+					});
+				}
+				
+				dojo.connect(n,"onclick",function(e){	
+					dijit.byId("content").selectChild(dijit.byId(linkto));
+				});
+			
+			});
+			
+			dojo.query(".cp").instantiate(dijit.layout.ContentPane);			
+			dojo.query("#content").forEach(function(n){
+				new dojox.layout.RadioGroupSlide({
+					hasButtons:false
+				},n).startup();
+			});
+		});			
+	</script>
+    </head>
+    <body class="tundra">
+		
+		<div id="container">
+			<div>
+			<h2>The Dojo Toolkit:</h2>	
+			</div>
+			<div id="header">
+				<div class="headLink" id="dojoLink">
+					<div class="fisheyeTarget"></div>
+					<div class="inner">Dojo Base</div>
+					<span class="subtext">the JavaScript Toolkit</span>
+				</div>
+				<div class="headLink" id="dijitLink">
+					<div class="fisheyeTarget"></div>
+					<div class="inner">Dijit</div>
+					<span class="subtext">Themeable, extensible widget system</span>
+				</div>
+				<div class="headLink" id="dojoxLink">
+					<div class="fisheyeTarget"></div>
+					<div class="inner">DojoX</div>
+					<span class="subtext">Extensions, experiments, and extras</span>
+				</div>
+			</div>
+			<div id="content">
+				<div class="cp" id="dojoLinkPane">
+					<div class="cpContent">
+					Dojo Pane
+					</div>
+				</div>
+				<div class="cp" id="dijitLinkPane">
+					<div class="cpContent">
+					Dijit Pane
+					</div>
+				</div>
+				<div class="cp" id="dojoxLinkPane">
+					<div class="cpContent">
+					DojoX Pane
+					</div>
+				</div>
+			</div>
+		</div>
+		
+    </body>
+</html>
\ No newline at end of file
diff --git a/dojox/widget/tests/get_time.php b/dojox/widget/tests/get_time.php
new file mode 100644
index 0000000..bc32a68
--- /dev/null
+++ b/dojox/widget/tests/get_time.php
@@ -0,0 +1,5 @@
+<?php
+
+	print '<div style="color: blue;">The server time is now: ' . date('r') . "</div>\n";
+
+?>
diff --git a/dojox/widget/tests/honey.php b/dojox/widget/tests/honey.php
new file mode 100644
index 0000000..5b7ad69
--- /dev/null
+++ b/dojox/widget/tests/honey.php
@@ -0,0 +1,27 @@
+<?php
+/* honey.php - sample fake delay script to push data
+   - should use ob_flush() to send chunks rather than 
+   just take a long time ...
+*/
+
+session_start(); 
+
+$char = " "; 
+$fakeDelay = (empty($_GET['delay'])) ? 1 : $_GET['delay'];
+$dataSize = (empty($_GET['size'])) ? 2*1024 : $_GET['size'];
+if (empty($_SESSION['counter'])) $_SESSION['counter'] = 1; 
+$dataSent = 0;
+$blockSize = 1024;
+
+if ($fakeDelay) { sleep($fakeDelay); }
+
+print "view num: ".$_SESSION['counter']++;
+while ($dataSent<=$dataSize) {
+	for ($i=0; $i<$blockSize/4; $i++) {
+		print $char; 
+	} print "<br />"; 
+	$dataSent += $blockSize; 
+	sleep(1);
+}
+
+?>
diff --git a/dojox/widget/tests/images/busy.gif b/dojox/widget/tests/images/busy.gif
new file mode 100755
index 0000000..e827056
Binary files /dev/null and b/dojox/widget/tests/images/busy.gif differ
diff --git a/dojox/widget/tests/images/fisheye_1.png b/dojox/widget/tests/images/fisheye_1.png
new file mode 100644
index 0000000..7499dcc
Binary files /dev/null and b/dojox/widget/tests/images/fisheye_1.png differ
diff --git a/dojox/widget/tests/images/fisheye_2.png b/dojox/widget/tests/images/fisheye_2.png
new file mode 100644
index 0000000..2db041b
Binary files /dev/null and b/dojox/widget/tests/images/fisheye_2.png differ
diff --git a/dojox/widget/tests/images/fisheye_3.png b/dojox/widget/tests/images/fisheye_3.png
new file mode 100644
index 0000000..5d9cc09
Binary files /dev/null and b/dojox/widget/tests/images/fisheye_3.png differ
diff --git a/dojox/widget/tests/images/fisheye_4.png b/dojox/widget/tests/images/fisheye_4.png
new file mode 100644
index 0000000..4e74550
Binary files /dev/null and b/dojox/widget/tests/images/fisheye_4.png differ
diff --git a/dojox/widget/tests/images/flare.png b/dojox/widget/tests/images/flare.png
new file mode 100755
index 0000000..2054044
Binary files /dev/null and b/dojox/widget/tests/images/flare.png differ
diff --git a/dojox/widget/tests/images/gaugeOverlay.png b/dojox/widget/tests/images/gaugeOverlay.png
new file mode 100755
index 0000000..72bcdbb
Binary files /dev/null and b/dojox/widget/tests/images/gaugeOverlay.png differ
diff --git a/dojox/widget/tests/images/icon_browser.png b/dojox/widget/tests/images/icon_browser.png
new file mode 100644
index 0000000..72fae26
Binary files /dev/null and b/dojox/widget/tests/images/icon_browser.png differ
diff --git a/dojox/widget/tests/images/icon_calendar.png b/dojox/widget/tests/images/icon_calendar.png
new file mode 100644
index 0000000..d9e9a22
Binary files /dev/null and b/dojox/widget/tests/images/icon_calendar.png differ
diff --git a/dojox/widget/tests/images/icon_email.png b/dojox/widget/tests/images/icon_email.png
new file mode 100644
index 0000000..899dfa5
Binary files /dev/null and b/dojox/widget/tests/images/icon_email.png differ
diff --git a/dojox/widget/tests/images/icon_texteditor.png b/dojox/widget/tests/images/icon_texteditor.png
new file mode 100644
index 0000000..ced8c14
Binary files /dev/null and b/dojox/widget/tests/images/icon_texteditor.png differ
diff --git a/dojox/widget/tests/images/icon_update.png b/dojox/widget/tests/images/icon_update.png
new file mode 100644
index 0000000..b741cd0
Binary files /dev/null and b/dojox/widget/tests/images/icon_update.png differ
diff --git a/dojox/widget/tests/images/icon_users.png b/dojox/widget/tests/images/icon_users.png
new file mode 100644
index 0000000..569e712
Binary files /dev/null and b/dojox/widget/tests/images/icon_users.png differ
diff --git a/dojox/widget/tests/images/rotator_aol.png b/dojox/widget/tests/images/rotator_aol.png
new file mode 100644
index 0000000..fc98146
Binary files /dev/null and b/dojox/widget/tests/images/rotator_aol.png differ
diff --git a/dojox/widget/tests/images/rotator_aptana.png b/dojox/widget/tests/images/rotator_aptana.png
new file mode 100644
index 0000000..668b60c
Binary files /dev/null and b/dojox/widget/tests/images/rotator_aptana.png differ
diff --git a/dojox/widget/tests/images/rotator_bea.png b/dojox/widget/tests/images/rotator_bea.png
new file mode 100644
index 0000000..3728a1f
Binary files /dev/null and b/dojox/widget/tests/images/rotator_bea.png differ
diff --git a/dojox/widget/tests/images/rotator_bg.gif b/dojox/widget/tests/images/rotator_bg.gif
new file mode 100644
index 0000000..be1d843
Binary files /dev/null and b/dojox/widget/tests/images/rotator_bg.gif differ
diff --git a/dojox/widget/tests/images/rotator_dots.png b/dojox/widget/tests/images/rotator_dots.png
new file mode 100644
index 0000000..1d7f85e
Binary files /dev/null and b/dojox/widget/tests/images/rotator_dots.png differ
diff --git a/dojox/widget/tests/images/rotator_google.png b/dojox/widget/tests/images/rotator_google.png
new file mode 100644
index 0000000..e1dc9e3
Binary files /dev/null and b/dojox/widget/tests/images/rotator_google.png differ
diff --git a/dojox/widget/tests/images/rotator_ibm.png b/dojox/widget/tests/images/rotator_ibm.png
new file mode 100644
index 0000000..43f6659
Binary files /dev/null and b/dojox/widget/tests/images/rotator_ibm.png differ
diff --git a/dojox/widget/tests/images/rotator_icons.gif b/dojox/widget/tests/images/rotator_icons.gif
new file mode 100644
index 0000000..b3070ce
Binary files /dev/null and b/dojox/widget/tests/images/rotator_icons.gif differ
diff --git a/dojox/widget/tests/images/rotator_nexaweb.png b/dojox/widget/tests/images/rotator_nexaweb.png
new file mode 100644
index 0000000..773caed
Binary files /dev/null and b/dojox/widget/tests/images/rotator_nexaweb.png differ
diff --git a/dojox/widget/tests/images/rotator_openlaszlo.png b/dojox/widget/tests/images/rotator_openlaszlo.png
new file mode 100644
index 0000000..38cf419
Binary files /dev/null and b/dojox/widget/tests/images/rotator_openlaszlo.png differ
diff --git a/dojox/widget/tests/images/rotator_renkoo.png b/dojox/widget/tests/images/rotator_renkoo.png
new file mode 100644
index 0000000..afe47e8
Binary files /dev/null and b/dojox/widget/tests/images/rotator_renkoo.png differ
diff --git a/dojox/widget/tests/images/rotator_sitepen.png b/dojox/widget/tests/images/rotator_sitepen.png
new file mode 100644
index 0000000..10a603a
Binary files /dev/null and b/dojox/widget/tests/images/rotator_sitepen.png differ
diff --git a/dojox/widget/tests/images/rotator_sun.png b/dojox/widget/tests/images/rotator_sun.png
new file mode 100644
index 0000000..d89dd4f
Binary files /dev/null and b/dojox/widget/tests/images/rotator_sun.png differ
diff --git a/dojox/widget/tests/images/rotator_tibco.png b/dojox/widget/tests/images/rotator_tibco.png
new file mode 100644
index 0000000..d493cf0
Binary files /dev/null and b/dojox/widget/tests/images/rotator_tibco.png differ
diff --git a/dojox/widget/tests/images/rotator_uxebu.png b/dojox/widget/tests/images/rotator_uxebu.png
new file mode 100644
index 0000000..9bf11e5
Binary files /dev/null and b/dojox/widget/tests/images/rotator_uxebu.png differ
diff --git a/dojox/widget/tests/images/rotator_wavemaker.png b/dojox/widget/tests/images/rotator_wavemaker.png
new file mode 100644
index 0000000..f201adc
Binary files /dev/null and b/dojox/widget/tests/images/rotator_wavemaker.png differ
diff --git a/dojox/widget/tests/images/rotator_webtide.png b/dojox/widget/tests/images/rotator_webtide.png
new file mode 100644
index 0000000..b2aae20
Binary files /dev/null and b/dojox/widget/tests/images/rotator_webtide.png differ
diff --git a/dojox/widget/tests/images/rotator_zend.png b/dojox/widget/tests/images/rotator_zend.png
new file mode 100644
index 0000000..4a93b10
Binary files /dev/null and b/dojox/widget/tests/images/rotator_zend.png differ
diff --git a/dojox/widget/tests/testAtom.xml b/dojox/widget/tests/testAtom.xml
new file mode 100644
index 0000000..365bc0d
--- /dev/null
+++ b/dojox/widget/tests/testAtom.xml
@@ -0,0 +1,662 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en" xml:base="http://www.dojocampus.org/explorer">
+	<title type="text">DojoCampus Feature Explorer: Latest Demos</title>
+	<subtitle type="text">The latest demos from the Dojo toolkit</subtitle>
+	<generator uri="http://dojocampus.org/" version="MU">DojoCampus</generator>
+	<link rel="alternate" type="text/html" href="http://dojocampus.org/explorer" />
+	<id>http://www.dojocampus.org/explorer/featureexplorer/latestDemos.xml</id>
+	<link rel="self" type="application/atom+xml" href="http://www.dojocampus.org/explorer/featureexplorer/latestDemos.xml" />
+
+	<updated>2008-06-11T17:33:29+02:00</updated>
+	<entry>
+		<author>
+			<name>The Dojo Community</name>
+			<uri>http://www.dojocampus.org</uri>
+		</author>
+		<title type="text">Dojox / Widgets / Iterator / Data Store</title>
+
+		<link rel="alternate" type="text/html" href="http://www.dojocampus.org/explorer#Dojox_Widgets_Iterator_Data%20Store"/>
+		<id>http://www.dojocampus.org/explorer#Dojox_Widgets_Iterator_Data%20Store</id>
+		<updated>2008-06-11T17:33:29+02:00</updated>
+		<published>2008-06-11T17:33:29+02:00</published>
+		<summary type="html"><![CDATA[This example shows how to create a dojox.widget.Iterator widget and feed it 
+data from a simple data store.  Note how the <b>jsId</b> attribute of the 
+data store is identical to the <b>store</b> attribute of the Iterator widget. 
+A <b>query</b> attribute can also be specified to select a subset of the data
+in the data store.
+]]>
+		</summary>
+		<content type="html"><![CDATA[<script type="text/javascript">
+	dojo.require("dojo.data.ItemFileReadStore");
+	dojo.require("dojox.widget.Iterator");
+	dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+</script>
+<div dojoType="dojo.data.ItemFileReadStore"
+	url="/dojotoolkit/dijit/tests/_data/countries.json"
+	jsId="stateStore"></div>
+
+<h3>Data store backed Iterator</h3>
+<ul>
+	<li>before</li>
+	<li dojoType="dojox.widget.Iterator"
+		query="{ name: 'A*' }"
+		store="stateStore">
+		${name}
+	</li>
+	<li>after</li>
+</ul>
+]]>
+
+		</content>
+	</entry>
+	<entry>
+		<author>
+			<name>The Dojo Community</name>
+			<uri>http://www.dojocampus.org</uri>
+		</author>
+		<title type="text">Dojox / Widgets / SortList / From Data Store</title>
+
+		<link rel="alternate" type="text/html" href="http://www.dojocampus.org/explorer#Dojox_Widgets_SortList_From%20Data%20Store"/>
+		<id>http://www.dojocampus.org/explorer#Dojox_Widgets_SortList_From%20Data%20Store</id>
+		<updated>2008-06-11T17:33:29+02:00</updated>
+		<published>2008-06-11T17:33:29+02:00</published>
+		<summary type="html"><![CDATA[This example shows how to create a dojox.widget.SortList widget, and 
+populate it with data from a data store.
+]]>
+		</summary>
+		<content type="html"><![CDATA[<style type="text/css">
+	@import "/dojotoolkit/dojox/widget/SortList/SortList.css";
+</style>
+
+<script type="text/javascript">
+	dojo.require("dojox.widget.SortList");
+	dojo.require("dojo.data.ItemFileReadStore");
+	dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+</script>
+
+<div dojoType="dojo.data.ItemFileReadStore"
+	url="/dojotoolkit/dijit/tests/_data/countries.json"
+	jsId="stateStore"></div>
+
+<h3>Simple sortable example</h3>
+<ul dojoType="dojox.widget.SortList" store="stateStore"
+	title="sortable List" style="width:200px; height:200px;"></ul>
+]]>
+
+		</content>
+	</entry>
+	<entry>
+		<author>
+			<name>The Dojo Community</name>
+			<uri>http://www.dojocampus.org</uri>
+		</author>
+		<title type="text">Dojox / Widgets / SortList / From Markup</title>
+
+		<link rel="alternate" type="text/html" href="http://www.dojocampus.org/explorer#Dojox_Widgets_SortList_From%20Markup"/>
+		<id>http://www.dojocampus.org/explorer#Dojox_Widgets_SortList_From%20Markup</id>
+		<updated>2008-06-11T17:33:29+02:00</updated>
+		<published>2008-06-11T17:33:29+02:00</published>
+		<summary type="html"><![CDATA[This example shows how to create a simple dojox.widget.SortList widget, which
+sorts the HTML elements already present in the UL list.
+]]>
+		</summary>
+		<content type="html"><![CDATA[<style type="text/css">
+	@import "/dojotoolkit/dojox/widget/SortList/SortList.css";
+</style>
+
+<script type="text/javascript">
+	dojo.require("dojox.widget.SortList");
+	dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+</script>	
+
+<ul dojoType="dojox.widget.SortList" title="SortList From Markup" 
+	sortable="true" style="width:200px; height:200px;">
+	<li>one</li>
+	<li>two</li>
+	<li>three</li>
+	<li>four</li>
+	<li>five</li>
+	<li>six</li>
+	<li>four</li>
+	<li>five</li>
+	<li>six</li>
+	<li>four</li>
+	<li>five</li>
+	<li>six</li>
+	<li>four</li>
+	<li>five</li>
+	<li>six</li>
+</ul>
+]]>
+
+		</content>
+	</entry>
+	<entry>
+		<author>
+			<name>The Dojo Community</name>
+			<uri>http://www.dojocampus.org</uri>
+		</author>
+		<title type="text">Dojox / Widgets / SortList / Custom Sort</title>
+
+		<link rel="alternate" type="text/html" href="http://www.dojocampus.org/explorer#Dojox_Widgets_SortList_Custom%20Sort"/>
+		<id>http://www.dojocampus.org/explorer#Dojox_Widgets_SortList_Custom%20Sort</id>
+		<updated>2008-06-11T17:33:29+02:00</updated>
+		<published>2008-06-11T17:33:29+02:00</published>
+		<summary type="html"><![CDATA[This example shows how to create a simple dojox.widget.SortList widget, which
+sorts the HTML elements already present in the UL list. It also shows how to 
+add a customized sorting method to the widget, in this case to sort the 
+numbers based on their numerical value rather than their alphabetical value.
+]]>
+		</summary>
+		<content type="html"><![CDATA[<style type="text/css">
+	@import "/dojotoolkit/dojox/widget/SortList/SortList.css";
+</style>
+
+<script type="text/javascript">
+	dojo.require("dojox.widget.SortList");
+	dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	var numberTranslations = {
+			"one":1,
+			"two":2,
+			"three":3,
+			"four":4,
+			"five":5,
+			"six":6
+		};
+	
+</script>	
+
+<ul dojoType="dojox.widget.SortList" title="SortList From Markup" 
+	sortable="true" style="width:200px; height:200px;">
+	<script type="dojo/method" event="_sorter", args="a,b">
+		//This is a custom sort method.
+		var aNum = numberTranslations[a.innerHTML];
+		var bNum = numberTranslations[b.innerHTML];
+		if(aNum>bNum){ return 1; }
+		if(aNum<bNum){ return -1; }
+		return 0;		
+	</script>
+	<li>one</li>
+	<li>two</li>
+	<li>three</li>
+	<li>four</li>
+	<li>five</li>
+	<li>six</li>
+	<li>four</li>
+	<li>five</li>
+	<li>six</li>
+	<li>four</li>
+	<li>five</li>
+	<li>six</li>
+	<li>four</li>
+	<li>five</li>
+	<li>six</li>
+</ul>
+]]>
+
+		</content>
+	</entry>
+	<entry>
+		<author>
+			<name>The Dojo Community</name>
+			<uri>http://www.dojocampus.org</uri>
+		</author>
+		<title type="text">Dojox / Layout / Resize Handle / Animated</title>
+
+		<link rel="alternate" type="text/html" href="http://www.dojocampus.org/explorer#Dojox_Layout_Resize%20Handle_Animated"/>
+		<id>http://www.dojocampus.org/explorer#Dojox_Layout_Resize%20Handle_Animated</id>
+		<updated>2008-06-11T17:33:28+02:00</updated>
+		<published>2008-06-11T17:33:28+02:00</published>
+		<summary type="html"><![CDATA[]]>
+		</summary>
+		<content type="html"><![CDATA[<style type="text/css">
+	@import "/dojotoolkit/dojox/layout/resources/ResizeHandle.css";
+</style>
+<script language="JavaScript" type="text/javascript">
+	dojo.require("dojox.layout.ResizeHandle"); 
+	dojo.require("dijit.layout.ContentPane"); 
+	dojo.require("dojo.parser");
+</script>
+<style type="text/css">
+	#testWindow {
+		margin:8px; 
+		padding:15px; 
+		float:left; 
+		width: 300px; 
+		height: 200px; 
+		border: solid red 5px; 
+		position: relative; 
+		background: white;
+	}
+	
+	.handle {
+		bottom: 2px; 
+		right: 2px; 
+		position: absolute;
+	}
+</style>
+<div dojoType="dijit.layout.ContentPane"
+	title="Test window"
+	id="testWindow"
+>
+	Content Pane w/a resize handle.Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
+	Nam facilisis enim. Pellentesque in elit et lacus euismod dignissim. Aliquam dolor pede, convallis eget, 
+	dictum a, blandit ac, urna. Pellentesque sed nunc ut justo volutpat egestas. Class aptent taciti sociosqu ad 
+	litora torquent per conubia nostra, per inceptos hymenaeos. In erat. Suspendisse potenti. Fusce faucibus nibh 
+	sed nisi. Phasellus faucibus, dui a cursus dapibus, mauris nulla euismod velit, a lobortis turpis arcu vel dui. 
+	Pellentesque fermentum ultrices pede. Donec auctor lectus eu arcu. Curabitur non orci eget est porta gravida.
+	<div dojoType="dojox.layout.ResizeHandle" targetId="testWindow" 
+		resizeAxis="xy" animateMethod="combine" class="handle"></div>
+</div>
+
+<br/><br/>
+
+	<p>Sed arcu magna, molestie at, fringilla in, sodales eu, elit. Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus ut elit convallis eleifend. Fusce tincidunt, justo quis tempus euismod, magna nulla viverra libero, sit amet lacinia odio diam id risus. Ut varius viverra turpis. M [...]
+
+	<p>Fusce rutrum pede eget quam. Praesent purus. Aenean at elit in sem volutpat facilisis. Nunc est augue, commodo at, pretium a, fermentum at, quam. Nam sit amet enim. Suspendisse potenti. Cras hendrerit rhoncus justo. Integer libero. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam erat volutpat. Sed adipiscing mi vel ipsum.</p>
+
+	<p>Sed aliquam, quam consectetuer condimentum bibendum, neque libero commodo metus, non consectetuer magna risus 
+	vitae eros. Pellentesque mollis augue id libero. Morbi nonummy hendrerit dui. Morbi nisi felis, fringilla ac, 
+	euismod vitae, dictum mollis, pede. Integer suscipit, est sed posuere ullamcorper, ipsum lectus interdum nunc, 
+	quis blandit erat eros hendrerit pede. Vestibulum varius, elit id mattis mattis, nulla est feugiat ante, eget 
+	vestibulum augue eros ut odio. Maecenas euismod purus quis felis. Ut hendrerit tincidunt est. Fusce euismod, 
+	nunc eu tempus tempor, purus ligula volutpat tellus, nec lacinia sapien enim id risus. Aliquam orci turpis, 
+	condimentum sed, sollicitudin vel, placerat in, purus. Proin tortor nisl, blandit quis, imperdiet quis, 
+	scelerisque at, nisl. Maecenas suscipit fringilla erat. Curabitur consequat, dui blandit suscipit dictum, 
+	felis lectus imperdiet tellus, sit amet ornare risus mauris non ipsum. 
+	Fusce a purus. Vestibulum sodales. Sed porta ultrices nibh. Vestibulum metus.</p>
+]]>
+
+		</content>
+	</entry>
+	<entry>
+		<author>
+			<name>The Dojo Community</name>
+			<uri>http://www.dojocampus.org</uri>
+		</author>
+		<title type="text">Dojox / Layout / ScrollPane / Programmatic</title>
+
+		<link rel="alternate" type="text/html" href="http://www.dojocampus.org/explorer#Dojox_Layout_ScrollPane_Programmatic"/>
+		<id>http://www.dojocampus.org/explorer#Dojox_Layout_ScrollPane_Programmatic</id>
+		<updated>2008-06-11T17:33:28+02:00</updated>
+		<published>2008-06-11T17:33:28+02:00</published>
+		<summary type="html"><![CDATA[This example shows how to construct a horizontal 
+<b>dojox.layout.ScrollPane</b> progammatically.  
+Note that you must
+specify the dimensions of the widget, done here 
+using the style attribute.
+]]>
+		</summary>
+		<content type="html"><![CDATA[<script language="JavaScript" type="text/javascript">
+	dojo.require("dojox.layout.ScrollPane");
+	dojo.require("dijit.form.Button");
+
+	function makeScrollPane() {
+		// programatic example:
+		var widget = new dojox.layout.ScrollPane({
+			orientation: "horizontal",
+			style:"width:600px; height:125px; border:1px solid #b7b7b7"
+		},"scrollPane1");
+		widget.startup();
+	}
+
+</script>
+<link href="/dojotoolkit/dojox/layout/resources/ScrollPane.css"
+	type="text/css" rel="stylesheet"></link>
+<style type="text/css">
+	table.fooBar td {
+		width:50px;
+		border-right:2px solid #000;
+		padding:20px;
+	}
+	.foo { float:left; }
+</style>
+
+<div dojoType="dijit.form.Button" onclick="makeScrollPane()">
+	Make Widget
+</div>
+
+<div id="scrollPane1">
+	<table class="fooBar">
+		<tr>
+			<td style="padding-left:20px;">On Raglan</td>
+			<td>Road On An</td>
+			<td>autumn day</td>
+			<td>I saw her</td>
+			<td>first and</td>
+			<td>knew, that</td>
+			<td>her dark hair</td>
+			<td>would weave</td>
+			<td>a snare that</td>
+			<td>I might one</td>
+			<td>day rue.</td>
+			<td>I saw the</td>
+			<td>danger yet I</td>
+			<td>walked, along</td>
+			<td>the enchanted</td>
+			<td>way. And I</td>
+			<td>said let grief</td>
+			<td>be a falling</td>
+			<td>leaf at the</td>
+			<td>dawning of</td>
+			<td>the Day.</td>
+
+			<td>On Grafton</td>
+			<td>Street in</td>
+			<td>November, we</td>
+			<td>tripped lightly</td>
+			<td>along the ledge,</td>
+			<td>Of the deep ravine</td>
+			<td>where can be</td>
+			<td>seen, the worth</td>
+			<td>of passions</td>
+			<td>pledge. The</td>
+			<td>Queen of hearts</td>
+			<td>still baking</td>
+			<td>tarts, and I</td>
+			<td>not making hay,</td>
+			<td>Oh I loved</td>
+			<td>too much, and</td>
+			<td>by such and such</td>
+			<td>is happiness</td>
+			<td>thrown away.</td>
+
+			<td>I gave her</td>
+			<td>gifts of the</td>
+			<td>mind, I gave</td>
+			<td>her the secret</td>
+			<td>sign, that's</td>
+			<td>known to the</td>
+			<td>artists who have</td>
+			<td>known, the true</td>
+			<td>gods of sound</td>
+			<td>and time. With</td>
+			<td>word and tint</td>
+			<td>I did not</td>
+			<td>stint, for I gave</td>
+			<td>her poems to </td>
+			<td>say, With her</td>
+			<td>own name there</td>
+			<td>and her own dark</td>
+			<td>hair, Like clouds</td>
+			<td>over fields of May</td>
+
+			<td>On a quiet</td>
+			<td>street, where old</td>
+			<td>ghosts meet, I</td>
+			<td>see her walking</td>
+			<td>now. Away from me</td>
+			<td>so hurriedly, my</td>
+			<td>reason must allow,</td>
+			<td>that I have</td>
+			<td>loved not as I</td>
+			<td>should, a creature</td>
+			<td>made of clay.</td>
+			<td>When the angel</td>
+			<td>woos the clay</td>
+			<td>he'll lost his</td>
+			<td>wings, at the</td>
+			<td>dawn of day.</td>
+			<td> </td>
+			<td>For Pat & Luke</td>
+		</tr>
+	</table>
+</div>
+]]>
+
+		</content>
+	</entry>
+	<entry>
+		<author>
+			<name>The Dojo Community</name>
+			<uri>http://www.dojocampus.org</uri>
+		</author>
+		<title type="text">Dojox / Layout / Resize Handle / X Axis</title>
+
+		<link rel="alternate" type="text/html" href="http://www.dojocampus.org/explorer#Dojox_Layout_Resize%20Handle_X%20Axis"/>
+		<id>http://www.dojocampus.org/explorer#Dojox_Layout_Resize%20Handle_X%20Axis</id>
+		<updated>2008-06-11T17:33:28+02:00</updated>
+		<published>2008-06-11T17:33:28+02:00</published>
+		<summary type="html"><![CDATA[This example to shows how to put a resize handle on a Dojo Layout widget,
+with resizing only on the X Axis.
+]]>
+		</summary>
+		<content type="html"><![CDATA[<style type="text/css">
+	@import "/dojotoolkit/dojox/layout/resources/ResizeHandle.css";
+</style>
+
+
+<script language="JavaScript" type="text/javascript">
+	dojo.require("dojox.layout.ResizeHandle"); 
+	dojo.require("dijit.layout.ContentPane"); 
+	dojo.require("dojo.parser");
+</script>
+<style type="text/css">
+	#testWindow {
+		width: 300px; 
+		height: 200px; 
+		padding:10px; 
+		border: 1px 
+		solid #dedede; 
+		position: relative; 
+		background: white;
+	}
+</style>
+<div dojoType="dijit.layout.ContentPane"
+	title="Test window"
+	id="testWindow"
+>
+	Content Pane w/a resize handle.Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam facilisis enim. Pellentesque in elit et lacus euismod dignissim. Aliquam dolor pede, convallis eget, dictum a, blandit ac, urna. Pellentesque sed nunc ut justo volutpat egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. In erat. Suspendisse potenti. Fusce faucibus nibh sed nisi. Phasellus faucibus, dui a cursus dapibus, mauris nulla euismod velit [...]
+	<div dojoType="dojox.layout.ResizeHandle" targetId="testWindow" resizeAxis="x" activeResize="true"></div>
+</div>
+]]>
+
+		</content>
+	</entry>
+	<entry>
+		<author>
+			<name>The Dojo Community</name>
+			<uri>http://www.dojocampus.org</uri>
+		</author>
+		<title type="text">Dojox / Widgets / Color Picker / Basic</title>
+
+		<link rel="alternate" type="text/html" href="http://www.dojocampus.org/explorer#Dojox_Widgets_Color%20Picker_Basic"/>
+		<id>http://www.dojocampus.org/explorer#Dojox_Widgets_Color%20Picker_Basic</id>
+		<updated>2008-06-11T17:33:28+02:00</updated>
+		<published>2008-06-11T17:33:28+02:00</published>
+		<summary type="html"><![CDATA[This example shows how to put a dojox.widget.ColorPicker widget on the page,
+and how to attach an event to be notified of the selected color.
+]]>
+		</summary>
+		<content type="html"><![CDATA[<style type="text/css">
+	@import "/dojotoolkit/dojox/widget/ColorPicker/ColorPicker.css";
+</style>
+
+<script type="text/javascript">
+	dojo.require("dojox.widget.ColorPicker");
+	dojo.require("dojo.parser"); // scan page for widgets and instantiate them
+	
+	function printColor(val){
+		dojo.byId("colorOutput").innerHTML = "Color is "+val;
+	}
+</script>
+<div id="colorOutput">
+	Color is 
+</div>
+<div id="picker1" dojoType="dojox.widget.ColorPicker"
+	onChange="printColor(this.value)"
+></div>
+
+
+]]>
+
+		</content>
+	</entry>
+	<entry>
+		<author>
+			<name>The Dojo Community</name>
+			<uri>http://www.dojocampus.org</uri>
+		</author>
+		<title type="text">Dojox / Layout / ScrollPane / Vertical</title>
+
+		<link rel="alternate" type="text/html" href="http://www.dojocampus.org/explorer#Dojox_Layout_ScrollPane_Vertical"/>
+		<id>http://www.dojocampus.org/explorer#Dojox_Layout_ScrollPane_Vertical</id>
+		<updated>2008-06-11T17:33:28+02:00</updated>
+		<published>2008-06-11T17:33:28+02:00</published>
+		<summary type="html"><![CDATA[This example shows how to construct a vertical 
+<b>dojox.layout.ScrollPane</b>.  Note that you must
+specify the dimensions of the widget, done here 
+using the style attribute.
+]]>
+		</summary>
+		<content type="html"><![CDATA[<script language="JavaScript" type="text/javascript">
+	dojo.require("dojox.layout.ScrollPane");
+</script>
+<link href="/dojotoolkit/dojox/layout/resources/ScrollPane.css"
+	type="text/css" rel="stylesheet"></link>
+<style type="text/css">
+	table.fooBar td {
+		width:50px;
+		border-right:2px solid #000;
+		padding:20px;
+	}
+	.foo { float:left; }
+</style>
+<div dojoType="dojox.layout.ScrollPane"
+	orientation="vertical"
+	style="width:200px; height:250px; border:1px solid #b7b7b7">
+	<ul class="fooBar">
+		<li>On Raglan</li>
+		<li>Road On An</li>
+		<li>autumn day</li>
+		<li>I saw her</li>
+		<li>first and</li>
+		<li>knew, that</li>
+		<li>her dark hair</li>
+		<li>would weave</li>
+		<li>a snare that</li>
+		<li>I might one</li>
+		<li>day rue.</li>
+		<li>I saw the</li>
+		<li>danger yet I</li>
+		<li>walked, along</li>
+		<li>the enchanted</li>
+		<li>way. And I</li>
+		<li>said let grief</li>
+		<li>be a falling</li>
+		<li>leaf at the</li>
+		<li>dawning of</li>
+		<li>the Day.</li>
+
+		<li>On Grafton</li>
+		<li>Street in</li>
+		<li>November, we</li>
+		<li>tripped lightly</li>
+		<li>along the ledge,</li>
+		<li>Of the deep ravine</li>
+		<li>where can be</li>
+		<li>seen, the worth</li>
+		<li>of passions</li>
+		<li>pledge. The</li>
+		<li>Queen of hearts</li>
+		<li>still baking</li>
+		<li>tarts, and I</li>
+		<li>not making hay,</li>
+		<li>Oh I loved</li>
+		<li>too much, and</li>
+		<li>by such and such</li>
+		<li>is happiness</li>
+		<li>thrown away.</li>
+
+		<li>I gave her</li>
+		<li>gifts of the</li>
+		<li>mind, I gave</li>
+		<li>her the secret</li>
+		<li>sign, that's</li>
+		<li>known to the</li>
+		<li>artists who have</li>
+		<li>known, the true</li>
+		<li>gods of sound</li>
+		<li>and time. With</li>
+		<li>word and tint</li>
+		<li>I did not</li>
+		<li>stint, for I gave</li>
+		<li>her poems to </li>
+		<li>say, With her</li>
+		<li>own name there</li>
+		<li>and her own dark</li>
+		<li>hair, Like clouds</li>
+		<li>over fields of May</li>
+
+		<li>On a quiet</li>
+		<li>street, where old</li>
+		<li>ghosts meet, I</li>
+		<li>see her walking</li>
+		<li>now. Away from me</li>
+		<li>so hurriedly, my</li>
+		<li>reason must allow,</li>
+		<li>that I have</li>
+		<li>loved not as I</li>
+		<li>should, a creature</li>
+		<li>made of clay.</li>
+		<li>When the angel</li>
+		<li>woos the clay</li>
+		<li>he'll lost his</li>
+		<li>wings, at the</li>
+		<li>dawn of day.</li>
+		<li> </li>
+		<li>For Pat & Luke</li>
+
+	</ul>
+</div>
+]]>
+
+		</content>
+	</entry>
+	<entry>
+		<author>
+			<name>The Dojo Community</name>
+			<uri>http://www.dojocampus.org</uri>
+		</author>
+		<title type="text">Dojox / Widgets / Color Picker / Customized</title>
+
+		<link rel="alternate" type="text/html" href="http://www.dojocampus.org/explorer#Dojox_Widgets_Color%20Picker_Customized"/>
+		<id>http://www.dojocampus.org/explorer#Dojox_Widgets_Color%20Picker_Customized</id>
+		<updated>2008-06-11T17:33:28+02:00</updated>
+		<published>2008-06-11T17:33:28+02:00</published>
+		<summary type="html"><![CDATA[This example shows how to put a dojox.widget.ColorPicker on the page, and how
+to customize it to not animate the pointer, disable the display of the
+RGB and HSV values, and to not restrict it to web safe values. Also shown
+is how to attach an event to be notified of the selected color.
+]]>
+		</summary>
+		<content type="html"><![CDATA[<style type="text/css">
+	@import "/dojotoolkit/dojox/widget/ColorPicker/ColorPicker.css";
+</style>
+
+
+<script type="text/javascript">
+	dojo.require("dojox.widget.ColorPicker");
+	dojo.require("dojo.parser"); // scan page for widgets and instantiate them
+	
+	function printColor(val){
+		dojo.byId("colorOutput").innerHTML = "Color is "+val;
+	}
+</script>
+
+<div id="colorOutput">
+	Color is 
+</div>
+
+<div id="pickerToo" dojoType="dojox.widget.ColorPicker"
+	animatePoint="false"
+	showHsv="false"
+	showRgb="false"	
+	webSafe="false"
+	onChange="printColor(this.value)"
+></div>
+]]>
+
+		</content>
+	</entry>
+</feed>
\ No newline at end of file
diff --git a/dojox/widget/tests/test_AnalogGaugeWidget.html b/dojox/widget/tests/test_AnalogGaugeWidget.html
new file mode 100644
index 0000000..e15d8e0
--- /dev/null
+++ b/dojox/widget/tests/test_AnalogGaugeWidget.html
@@ -0,0 +1,554 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Analog Gauge Widget</title>
+<style>
+	@import "../gauge/_Gauge.css";
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+</style>
+<script type="text/javascript">
+	djConfig = {
+		parseOnLoad: true,
+		isDebug: true
+	};
+</script>
+<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+<script language="JavaScript" type="text/javascript">
+	dojo.require('dojox.widget.AnalogGauge');
+	dojo.require('dojox.widget.gauge.AnalogArcIndicator');
+	dojo.require('dojox.widget.gauge.AnalogNeedleIndicator');
+	dojo.require('dojox.widget.gauge.AnalogArrowIndicator');
+	dojo.require('dijit.form.Button');
+	dojo.require('dojo.parser');
+
+	dojo.addOnLoad(init);
+
+	var gauge, valueIndicator, targetIndicator, handle;
+	var ranges1 = [ {low:5, high:10, hover:'5 - 10'},
+				   {low:10, high:20, hover:'10 - 20'},
+				   {low:20, high:30, hover:'20 - 30'},
+				   {low:30, high:40, hover:'30 - 40'},
+				   {low:40, high:50, hover:'40 - 50'},
+				   {low:50, high:60, hover:'50 - 60'},
+				   {low:60, high:70, hover:'60 - 70'},
+				   {low:70, high:75, hover:'70 - 75'}
+				 ];
+	var ranges2 = [ {low:5, high:10, hover:'5 - 10'},
+				   {low:10, high:20, hover:'10 - 20'},
+				   {low:20, high:30, hover:'20 - 30'},
+				   {low:30, high:40, hover:'30 - 40'},
+				   {low:40, high:50, hover:'40 - 50'},
+				   {low:50, high:60, hover:'50 - 60'},
+				   {low:60, high:70, hover:'60 - 70'},
+				   {low:70, high:75, hover:'70 - 75'}
+				 ];
+	
+	function init() {
+		gauge = dojo.byId("defaultGauge");
+		gauge = new dojox.widget.AnalogGauge({
+			id: "defaultGauge",
+			width: 350,
+			height: 200,
+			cx: 175,
+			cy: 175,
+			radius: 125,
+			ranges: ranges1,
+			minorTicks: {
+				offset: 125,
+				interval: 2.5,
+				length: 5,
+				color: 'gray'
+			},
+			majorTicks: {
+				offset: 125,
+				interval: 5,
+				length: 10
+			},
+			indicators: [
+				new dojox.widget.gauge.AnalogArrowIndicator({
+					value:17, 
+					width: 3,
+					hover:'Value: 17', 
+					title: 'Value'
+				}),
+				new dojox.widget.gauge.AnalogLineIndicator({
+					value:6, 
+					color:'#D00000',
+					width: 3,
+					hover:'Target: 6',
+					title: 'Target'
+				})
+			]
+		}, gauge);
+		gauge.startup();
+		var g = gauge;
+		var int = 10
+		dojo.connect(dijit.byId('changeTicks'), 'onClick', function(){
+			var o = g.majorTicks;
+			o.interval = ++int;
+			g.setMajorTicks(o);
+		});
+
+		/* Entirely programmatic gauge (ranges, ticks, indicators, etc.) */
+		var fill = {
+			'type': 'linear',
+			'x1': 0,
+			'x2': 0,
+			'y2': 0,
+			'y1': gauge.height,
+			'colors': [{offset: 0, color: "#ECECEC"}, {offset: 1, color: "white"}]
+		};
+		gauge = dojo.byId("programmaticGauge");
+		gauge = new dojox.widget.AnalogGauge({
+			id: "programmaticGauge",
+			width: 350,
+			height: 200,
+			cx: 175,
+			cy: 175,
+			radius: 125,
+			background: fill,
+			image: {
+				url: "images/gaugeOverlay.png",
+				width: 280,
+				height: 155,
+				x: 35,
+				y: 38,
+				overlay: true
+			},
+			useRangeStyles: 8
+		}, gauge);
+		gauge.startup();
+		gauge.addRanges(ranges2);
+		gauge.setMajorTicks({
+			length: 5,
+			interval: 5,
+			offset: 125,
+			font: {family: "Arial", style: "italic", variant: 'small-caps', weight: 'bold', size: "18px"}
+		});
+		valueIndicator = new dojox.widget.gauge.AnalogArrowIndicator({
+			value:17, 
+			width: 3,
+			hover:'Value: 17', 
+			title: 'Value',
+			easing: dojo.fx.easing.bounceOut
+		});
+		gauge.addIndicator(valueIndicator);
+		targetIndicator = new dojox.widget.gauge.AnalogLineIndicator({
+			value:6, 
+			color:'#D00000', 
+			width: 3,
+			hover:'Target: 6', 
+			title: 'Target',
+			// Can use string to indicate easing function (just like in de
+			easing: 'dojo.fx.easing.linear'
+		});
+		gauge.addIndicator(targetIndicator);
+		handle = setInterval((function(t, v){
+			return (function(){
+				t.update(Math.floor(Math.random() * 70) + 5);
+				v.update(Math.floor(Math.random() * 70) + 5);
+			});
+		})(valueIndicator, targetIndicator), 3000);
+		dojo.connect(dijit.byId('stop'), 'onClick', function(){
+			clearInterval(handle);
+		});
+
+		gauge = dojo.byId("speedometer");
+		gauge = new dojox.widget.AnalogGauge({
+			id: "speedometer",
+			width:270,
+			height: 230,
+			cx: 135,
+			cy: 135,
+			radius: 125,
+			image: {
+				url: "images/flare.png",
+				width: 112,
+				height: 116,
+				x: 140,
+				y: 40,
+				overlay: true
+			},
+			startAngle: -135,
+			endAngle: 135,
+			useRangeStyles: 8,
+			ranges: [{low:0, high:180, color: 'black'}],
+			majorTicks: {
+				offset: 85,
+				length: 10,
+				interval: 20,
+				color: 'gray'
+			},
+			minorTicks: {
+				offset: 85,
+				length: 5,
+				interval: 5,
+				color: 'gray'
+			},
+			indicators: [new dojox.widget.gauge.AnalogNeedleIndicator({
+							value:0, 
+							width: 3,
+							length: 100,
+							hover:'Value: 0', 
+							title: 'Value',
+							color: 'red'
+			})]
+		}, gauge);
+		gauge.startup();
+
+		gauge = dojo.byId("tachometer");
+		gauge = new dojox.widget.AnalogGauge({
+			id: "tachometer",
+			width:270,
+			height: 230,
+			cx: 135,
+			cy: 135,
+			radius: 125,
+			image: {
+				url: "images/flare.png",
+				width: 112,
+				height: 116,
+				x: 140,
+				y: 40,
+				overlay: true
+			},
+			startAngle: -135,
+			endAngle: 135,
+			useRangeStyles: 8,
+			ranges: [{low:0, high:9000, color: 'black'}],
+			majorTicks: {
+				offset: 75,
+				length: 10,
+				color: 'gray',
+				interval: 1000
+			},
+			minorTicks: {
+				offset: 75,
+				length: 5,
+				color: 'gray',
+				interval: 500
+			},
+			indicators: [new dojox.widget.gauge.AnalogNeedleIndicator({
+							value:0, 
+							width: 3,
+							length: 100,
+							hover:'Value: 0', 
+							title: 'Value',
+							color: 'red'
+			})]
+		}, gauge);
+		gauge.startup();
+
+		// Used for a gradient arc indicator below:
+		var fill = {
+			'type': 'linear',
+			'x1': 50,
+			'y1': 50,
+			'x2': 550,
+			'y2': 550,
+			'colors': [{offset: 0, color: 'black'}, {offset: 0.5, color: 'black'}, {offset: 0.75, color: 'yellow'}, {offset: 1, color: 'red'}]
+		};
+		gauge = dojo.byId("arctest");
+		gauge = new dojox.widget.AnalogGauge({
+			id: "arctest",
+			width: 650,
+			height: 550,
+			radius: 300,
+			cx: 320,
+			cy: 310,
+			startAngle: -135,
+			endAngle: 135,
+			ranges: [
+				{low: 0, high: 100, color: 'black'},
+				{low: 100, high: 200, color: 'black'}
+			],
+			minorTicks: {
+				offset: 235,
+				interval: 5,
+				length: 5,
+				color: 'gray'
+			},
+			majorTicks: {
+				offset: 235,
+				interval: 10,
+				length: 10,
+				color: 'gray'
+			},
+			indicators: [new dojox.widget.gauge.AnalogArcIndicator({
+							value: 200, 
+							width: 20,
+							offset: 280,
+							color: fill,
+							noChange: true,
+							hideValue: true
+						}),
+						new dojox.widget.gauge.AnalogArcIndicator({
+							value: 80, 
+							width: 10,
+							offset: 280,
+							hover:'Arc: 80', 
+							title: 'Arc',
+							color: 'blue'
+						}),
+						new dojox.widget.gauge.AnalogLineIndicator({
+							value:6, 
+							color:'#D00000', 
+							width: 8,
+							hover:'Target: 6', 
+							title: 'Target',
+							// Can use string to indicate easing function (just like in declarative version) 
+							easing: 'dojo.fx.easing.linear'
+						}),
+						new dojox.widget.gauge.AnalogArrowIndicator({
+							value: 20, 
+							width: 8,
+							length: 300,
+							hover:'Arrow: 20', 
+							title: 'Arrow',
+							color: 'red',
+							easing: dojo.fx.easing.bounceOut
+						}),
+						new dojox.widget.gauge.AnalogNeedleIndicator({
+							value: 100, 
+							width: 8,
+							length: 300,
+							hover: 'Needle: 100', 
+							title: 'Needle',
+							color: 'red'
+						})
+			]
+		}, gauge);
+		gauge.startup();
+
+		var fill = {
+			'type': 'linear',
+			'x1': 0,
+			'x2': 0,
+			'y2': 0,
+			'y1': gauge.height,
+			'colors': [{offset: 0, color: "#ECECEC"}, {offset: 1, color: "white"}]
+		};
+		gauge.setBackground(fill);
+	}
+	dojo.addOnUnload(function(){
+		clearInterval(handle);
+	});
+</script>
+</head>
+<body class="tundra">
+<h1>Analog Gauge Widget</h1>
+<h2>Default Colored Gauge</h2>
+<div id="defaultGauge"></div>
+<button dojoType="dijit.form.Button" id="changeTicks">Change Ticks</button>
+<h2>CSS Themed Ranges, Image Overlay, Gradient Background, Updating to Random Values on 3s Timer</h2>
+<div id="programmaticGauge"></div>
+<button dojoType="dijit.form.Button" id="stop">Stop Timer</button>
+<div style="float: left;">
+	<h2>Speedometer</h2>
+	<div id="speedometer"></div>
+</div>
+<div style="float: left;">
+	<h2>Tachometer</h2>
+	<div id="tachometer"></div>
+</div>
+<div style="clear: both;">
+	<h2>Various Indicators Test</h2>
+	<div id="arctest"></div>
+</div>
+<h2>Declarative, Gradient Ranges, Gradient Background, No Indicator Boxes</h2>
+<div	dojoType="dojox.widget.AnalogGauge"
+		id="declarativeGauge"
+		width="270"
+		height="265"
+		cx="110"
+		cy="150"
+		radius="125"
+		startAngle="-45"
+		endAngle="135"
+		useRangeStyles="0"
+		hideValues="true"
+		majorTicks="{length: 5, offset: 125, interval: 5}"
+		background="{
+			'type': 'linear',
+			'x1': 0,
+			'y1': 265,
+			'x2': 0,
+			'y2': 0,
+			'colors': [{offset: 0, color: '#ECECEC'}, {offset: 1, color: 'white'}]
+		}">
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="5"
+			high="10"
+			hover="5 - 10"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#606060'}, {offset: 1, color: '#707070'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range1"
+			low="10"
+			high="20"
+			hover="10 - 20"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#707070'}, {offset: 1, color: '#808080'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range2"
+			low="20"
+			high="30"
+			hover="20 - 30"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#808080'}, {offset: 1, color: '#909090'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range3"
+			low="30"
+			high="40"
+			hover="30 - 40"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#909090'}, {offset: 1, color: '#A0A0A0'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range4"
+			low="40"
+			high="50"
+			hover="40 - 50"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#A0A0A0'}, {offset: 1, color: '#B0B0B0'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range5"
+			low="50"
+			high="60"
+			hover="50 - 60"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#B0B0B0'}, {offset: 1, color: '#C0C0C0'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range6"
+			low="60"
+			high="70"
+			hover="60 - 70"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#C0C0C0'}, {offset: 1, color: '#D0D0D0'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range7"
+			low="70"
+			high="75"
+			hover="70 - 75"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#D0D0D0'}, {offset: 1, color: '#E0E0E0'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.AnalogLineIndicator"
+			id="target"
+			value="6"
+			color="#D00000"
+			width="3"
+			hover="Target: 6"
+			title="Target">
+	</div>
+	<div 	dojoType="dojox.widget.gauge.AnalogArrowIndicator"
+			id="value"
+			value="17"
+			type="arrow"
+			length="135"
+			width="3"
+			hover="Value: 17"
+			title="Value">
+	</div>
+</div>
+<h2>Declarative, (Ugly) Colored Ranges, No Numbers, No Indicator Boxes</h2>
+<div	dojoType="dojox.widget.AnalogGauge"
+		id="declarativeGauge2"
+		width="270"
+		height="270"
+		cx="135"
+		cy="135"
+		radius="125"
+		startAngle="-90"
+		endAngle="270"
+		useRangeStyles="0"
+		hideValues="true"
+		background="{color: 'green'}">
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="5"
+			high="10"
+			hover="5 - 10"
+			color="{color: 'red'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="10"
+			high="20"
+			hover="10 - 20"
+			color="{color: '#FFA500'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="20"
+			high="30"
+			hover="20 - 30"
+			color="{color: 'yellow'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="30"
+			high="40"
+			hover="30 - 40"
+			color="{color: '#7FFF00'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="40"
+			high="50"
+			hover="40 - 50"
+			color="{color: '#00FFFF'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="50"
+			high="60"
+			hover="50 - 60"
+			color="{color: 'blue'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="60"
+			high="70"
+			hover="60 - 70"
+			color="{color: '#191970'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="70"
+			high="75"
+			hover="70 - 75"
+			color="{color: 'purple'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.AnalogLineIndicator"
+			value="6"
+			color="#D00000"
+			width="3"
+			hover="Target: 6"
+			title="Target">
+	</div>
+	<div 	dojoType="dojox.widget.gauge.AnalogArrowIndicator"
+			value="55"
+			length="135"
+			width="3"
+			hover="Value: 55"
+			title="Value">
+	</div>
+</div>
+</body>
+</html>
diff --git a/dojox/widget/tests/test_AutoRotator.html b/dojox/widget/tests/test_AutoRotator.html
new file mode 100644
index 0000000..ed4ab84
--- /dev/null
+++ b/dojox/widget/tests/test_AutoRotator.html
@@ -0,0 +1,389 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.widget.AutoRotator Test</title>
+	<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+
+	.rotator{
+		background-color:#fff;
+		border:solid 1px #e5e5e5;
+		width:384px;
+		height:90px;
+		overflow:hidden;
+	}
+	.rotatorStacked{
+		width:384px;
+		height:90px;
+		overflow:hidden;
+		position:absolute;
+		left:0;
+		top:0;
+	}
+	.rotatorStacked .pane{
+		background-color:transparent;
+	}
+	.pane{
+		background-color:#fff;
+		width:384px;
+		height:90px;
+		overflow:hidden;
+	}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad:true, isDebug:true"></script>
+	<script type="text/javascript">
+	dojo.require("dojo.parser");
+	dojo.require("dojox.widget.AutoRotator");
+	dojo.require("dojox.widget.rotator.Fade");
+	dojo.require("dojox.widget.rotator.Pan");
+	dojo.require("dojox.widget.rotator.Slide");
+	dojo.require("dojox.widget.rotator.Wipe");
+
+	dojo.addOnLoad(function(){
+		// programmatic example
+		var contributors = [
+			[ "http://www.nexaweb.com",		"nexaweb.png",		"Nexaweb" ],
+			[ "http://www.renkoo.com",		"renkoo.png",		"Renkoo" ],
+			[ "http://www.sitepen.com",		"sitepen.png",		"Sitepen" ],
+			[ "http://www.tibco.com",		"tibco.png",		"Tibco" ],
+			[ "http://www.webtide.com",		"webtide.png",		"Webtide" ],
+			[ "http://www.openlaszlo.com",	"openlaszlo.png",	"OpenLaszlo" ],
+			[ "http://www.sun.com",			"sun.png",			"Sun" ],
+			[ "http://www.google.com",		"google.png",		"Google" ],
+			[ "http://www.aptana.com",		"aptana.png",		"Aptana" ],
+			[ "http://www.aol.com",			"aol.png",			"AOL" ],
+			[ "http://www.ibm.com",			"ibm.png",			"IBM" ],
+			[ "http://www.zend.com",		"zend.png",			"Zend" ],
+			[ "http://www.bea.com",			"bea.png",			"BEA" ],
+			[ "http://www.uxebu.com",		"uxebu.png",		"Uxebu" ],
+			[ "http://www.wavemaker.com",	"wavemaker.png",	"WaveMaker" ],
+			[ "http://www.aptana.com",		"aptana.png",		"Aptana" ]
+		];
+		
+		var panes = [];
+		for(var i=0; i<contributors.length; i++){
+			var html = '<a href="' + contributors[i][0] + '" target="_new"><img src="images/rotator_'
+						+ contributors[i][1] + '" width="130" alt="' + contributors[i][2] + '"/></a>';
+			if(i % 2 == 0){
+				panes.push({
+					className: "pane",
+					innerHTML: html
+				});
+			}else{
+				panes[panes.length-1].innerHTML += html
+			}
+		}
+
+		var r = new dojox.widget.AutoRotator({
+				id: "myRotator13",
+				duration: 2000,
+				transition: "dojox.widget.rotator.panLeft",
+				panes: panes
+			},
+			dojo.byId("myRotator4")
+		);
+	});
+	</script>
+</head>
+<body>
+
+	<h1 class="testTitle">dojox.widget.AutoRotator Test</h1>
+
+	<h2>Default Swap Transition</h2>
+	
+	<p>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['play']);">Play</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['pause']);">Pause</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['prev']);">Prev</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['next']);">Next</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 0]);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 1]);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 2]);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 3]);">Goto 3 (Sun, Google)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 4]);">Goto 4 (Aptana, AOL)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 5]);">Goto 5 (IBM, Zend)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 6]);">Goto 6 (BEA, Uxebu)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 7]);">Goto 7 (WaveMaker, Aptana)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 8]);">Goto 8 (bad)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['test']);">Bad Action</button>
+	</p>
+	
+	<div dojoType="dojox.widget.AutoRotator" class="rotator" id="myRotator" duration="2000">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+			<a href="http://www.aol.com" target="_new"><img src="images/rotator_aol.png" width="130" alt="AOL"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.ibm.com" target="_new"><img src="images/rotator_ibm.png" width="100" alt="IBM"/></a>
+			<a href="http://www.zend.com/" target="_new"><img src="images/rotator_zend.png" width="130" alt="Zend"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.bea.com" target="_new"><img src="images/rotator_bea.png" width="80" alt="BEA"/></a>
+			<a href="http://www.uxebu.com" target="_new"><img src="images/rotator_uxebu.png" width="120" alt="Uxebu"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.wavemaker.com" target="_new"><img src="images/rotator_wavemaker.png" width="130" alt="WaveMaker"/></a>
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+		</div>
+	</div>
+
+	<h2>4 Random Panes, Then Pause</h2>
+	
+	<p>
+	<button onclick="myRotator2.play();">Play</button>
+	<button onclick="myRotator2.pause();">Pause</button>
+	<button onclick="myRotator2.prev();">Prev</button>
+	<button onclick="myRotator2.next();">Next</button>
+	<button onclick="myRotator2.go(0);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="myRotator2.go(1);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="myRotator2.go(2);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="myRotator2.go(3);">Goto 3 (Sun, Google)</button>
+	<button onclick="myRotator2.go(4);">Goto 4 (Aptana, AOL)</button>
+	<button onclick="myRotator2.go(5);">Goto 5 (IBM, Zend)</button>
+	<button onclick="myRotator2.go(6);">Goto 6 (BEA, Uxebu)</button>
+	<button onclick="myRotator2.go(7);">Goto 7 (WaveMaker, Aptana)</button>
+	<button onclick="myRotator2.go(8);">Goto 8 (bad)</button>
+	</p>
+	
+	<div dojoType="dojox.widget.AutoRotator" class="rotator" jsId="myRotator2" random="true" duration="2000" cycles="4">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+			<a href="http://www.aol.com" target="_new"><img src="images/rotator_aol.png" width="130" alt="AOL"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.ibm.com" target="_new"><img src="images/rotator_ibm.png" width="100" alt="IBM"/></a>
+			<a href="http://www.zend.com/" target="_new"><img src="images/rotator_zend.png" width="130" alt="Zend"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.bea.com" target="_new"><img src="images/rotator_bea.png" width="80" alt="BEA"/></a>
+			<a href="http://www.uxebu.com" target="_new"><img src="images/rotator_uxebu.png" width="120" alt="Uxebu"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.wavemaker.com" target="_new"><img src="images/rotator_wavemaker.png" width="130" alt="WaveMaker"/></a>
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+		</div>
+	</div>
+	
+	<h2>Wait For Event</h2>
+	
+	<p>The 2nd pane will wait for a event to be published by the button before proceeding.</p>
+	
+	<div dojoType="dojox.widget.AutoRotator" class="rotator" jsId="myRotator3" duration="2000" transition="dojox.widget.rotator.crossFade">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane" waitForEvent="myEvent">
+			<button onclick="dojo.publish('myEvent')">Continue!</button><br>
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+	</div>
+	
+	<h2>Programmatic Example with Pan Left Transition</h2>
+	
+	<p>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['play']);">Play</button>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['pause']);">Pause</button>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['prev']);">Prev</button>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['next']);">Next</button>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['go', 0]);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['go', 1]);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['go', 2]);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['go', 3]);">Goto 3 (Sun, Google)</button>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['go', 4]);">Goto 4 (Aptana, AOL)</button>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['go', 5]);">Goto 5 (IBM, Zend)</button>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['go', 6]);">Goto 6 (BEA, Uxebu)</button>
+	<button onclick="dojo.publish('myRotator4/rotator/control', ['go', 7]);">Goto 7 (WaveMaker, Aptana)</button>
+	</p>
+
+	<div class="rotator" id="myRotator4"></div>
+	
+	<h2>Stacked Example: Pan Rotator Over Crossfade Rotator</h2>
+	
+	<p>
+	<button onclick="myRotator3_3.play();myRotator3_4.play();">Play</button>
+	<button onclick="myRotator3_3.pause();myRotator3_4.pause();">Pause</button>
+	<button onclick="myRotator3_3.prev();myRotator3_4.prev();">Prev</button>
+	<button onclick="myRotator3_3.next();myRotator3_4.next();">Next</button>
+	<button onclick="myRotator3_3.go(0);myRotator3_4.go(0);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="myRotator3_3.go(1);myRotator3_4.go(1);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="myRotator3_3.go(2);myRotator3_4.go(2);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="myRotator3_3.go(3);myRotator3_4.go(3);">Goto 3 (Sun, Google)</button>
+	</p>
+
+	<div class="rotator" style="position:relative;">
+		<div dojoType="dojox.widget.AutoRotator" class="rotatorStacked" style="z-index:100;" jsId="myRotator3_3" duration="1500" transition="dojox.widget.rotator.panLeft">
+			<div class="pane">
+				<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+				<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+			</div>
+			<div class="pane" transition="dojox.widget.rotator.panDown">
+				<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+				<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+			</div>
+			<div class="pane" transition="dojox.widget.rotator.panRight">
+				<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+				<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+			</div>
+			<div class="pane" transition="dojox.widget.rotator.panUp">
+				<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+				<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+			</div>
+		</div>
+		<div dojoType="dojox.widget.AutoRotator" class="rotatorStacked" style="z-index:50;" jsId="myRotator3_4" duration="1500" transition="dojox.widget.rotator.crossFade">
+			<div class="pane" style="background-color:red;"></div>
+			<div class="pane" style="background-color:yellow;"></div>
+			<div class="pane" style="background-color:green;"></div>
+			<div class="pane" style="background-color:blue;"></div>
+		</div>
+	</div>
+	
+	<h2>Suspend on Hover</h2>
+	
+	<p>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['play']);">Play</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['pause']);">Pause</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['prev']);">Prev</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['next']);">Next</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['go', 0]);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['go', 1]);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['go', 2]);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['go', 3]);">Goto 3 (Sun, Google)</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['go', 4]);">Goto 4 (Aptana, AOL)</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['go', 5]);">Goto 5 (IBM, Zend)</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['go', 6]);">Goto 6 (BEA, Uxebu)</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['go', 7]);">Goto 7 (WaveMaker, Aptana)</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['go', 8]);">Goto 8 (bad)</button>
+	<button onclick="dojo.publish('myRotator5/rotator/control', ['test']);">Bad Action</button>
+	</p>
+	
+	<div dojoType="dojox.widget.AutoRotator" class="rotator" id="myRotator5" suspendOnHover="true" duration="1000">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+			<a href="http://www.aol.com" target="_new"><img src="images/rotator_aol.png" width="130" alt="AOL"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.ibm.com" target="_new"><img src="images/rotator_ibm.png" width="100" alt="IBM"/></a>
+			<a href="http://www.zend.com/" target="_new"><img src="images/rotator_zend.png" width="130" alt="Zend"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.bea.com" target="_new"><img src="images/rotator_bea.png" width="80" alt="BEA"/></a>
+			<a href="http://www.uxebu.com" target="_new"><img src="images/rotator_uxebu.png" width="120" alt="Uxebu"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.wavemaker.com" target="_new"><img src="images/rotator_wavemaker.png" width="130" alt="WaveMaker"/></a>
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+		</div>
+	</div>
+	
+	<h2>Pause on Manual Change</h2>
+	
+	<p>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['play']);">Play</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['pause']);">Pause</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['prev']);">Prev</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['next']);">Next</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['go', 0]);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['go', 1]);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['go', 2]);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['go', 3]);">Goto 3 (Sun, Google)</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['go', 4]);">Goto 4 (Aptana, AOL)</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['go', 5]);">Goto 5 (IBM, Zend)</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['go', 6]);">Goto 6 (BEA, Uxebu)</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['go', 7]);">Goto 7 (WaveMaker, Aptana)</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['go', 8]);">Goto 8 (bad)</button>
+	<button onclick="dojo.publish('myRotator6/rotator/control', ['test']);">Bad Action</button>
+	</p>
+	
+	<div dojoType="dojox.widget.AutoRotator" class="rotator" id="myRotator6" pauseOnManualChange="true" duration="1000">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+			<a href="http://www.aol.com" target="_new"><img src="images/rotator_aol.png" width="130" alt="AOL"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.ibm.com" target="_new"><img src="images/rotator_ibm.png" width="100" alt="IBM"/></a>
+			<a href="http://www.zend.com/" target="_new"><img src="images/rotator_zend.png" width="130" alt="Zend"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.bea.com" target="_new"><img src="images/rotator_bea.png" width="80" alt="BEA"/></a>
+			<a href="http://www.uxebu.com" target="_new"><img src="images/rotator_uxebu.png" width="120" alt="Uxebu"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.wavemaker.com" target="_new"><img src="images/rotator_wavemaker.png" width="130" alt="WaveMaker"/></a>
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+		</div>
+	</div>
+	
+</body>
+</html>
diff --git a/dojox/widget/tests/test_BarGaugeWidget.html b/dojox/widget/tests/test_BarGaugeWidget.html
new file mode 100644
index 0000000..a74aafc
--- /dev/null
+++ b/dojox/widget/tests/test_BarGaugeWidget.html
@@ -0,0 +1,339 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Bar Gauge Widget</title>
+<style>
+	@import "../gauge/_Gauge.css";
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/themes/tundra/tundra.css";
+</style>
+<script type="text/javascript">
+	djConfig = {
+		parseOnLoad: true,
+		isDebug: true
+	};
+</script>
+<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+<script language="JavaScript" type="text/javascript">
+	dojo.require('dojox.widget.BarGauge');
+	dojo.require('dojox.widget.gauge.BarIndicator');
+	dojo.require('dijit.form.Button');
+	dojo.require('dojo.parser');
+
+	dojo.addOnLoad(init);
+
+	var gauge, valueIndicator, targetIndicator, handle;
+	var ranges1 = [ {low:5, high:10, hover:'5 - 10'},
+				   {low:10, high:20, hover:'10 - 20'},
+				   {low:20, high:30, hover:'20 - 30'},
+				   {low:30, high:40, hover:'30 - 40'},
+				   {low:40, high:50, hover:'40 - 50'},
+				   {low:50, high:60, hover:'50 - 60'},
+				   {low:60, high:70, hover:'60 - 70'},
+				   {low:70, high:75, hover:'70 - 75'}
+				 ];
+	var ranges2 = [ {low:5, high:10, hover:'5 - 10'},
+				   {low:10, high:20, hover:'10 - 20'},
+				   {low:20, high:30, hover:'20 - 30'},
+				   {low:30, high:40, hover:'30 - 40'},
+				   {low:40, high:50, hover:'40 - 50'},
+				   {low:50, high:60, hover:'50 - 60'},
+				   {low:60, high:70, hover:'60 - 70'},
+				   {low:70, high:75, hover:'70 - 75'}
+				 ];
+	
+	function init() {
+		gauge = dojo.byId("defaultGauge");
+		gauge = new dojox.widget.BarGauge({
+			id: "defaultGauge",
+			width: 300,
+			height: 55,
+			dataHeight: 25,
+			dataWidth: 275,
+			dataY: 25,
+			dataX: 10,
+			ranges: ranges1,
+			majorTicks: {
+				length: 5,
+				width: 1,
+				offset: -5,
+				interval: 5
+			},
+			indicators: [
+				new dojox.widget.gauge.BarIndicator({
+					value:17,
+					width: 7,
+					hover:'Value: 17',
+					title: 'Value'
+				}),
+				new dojox.widget.gauge.BarLineIndicator({
+					value:6,
+					color:'#D00000',
+					hover:'Target: 6',
+					title: 'Target'
+				})
+			]
+		}, gauge);
+		gauge.startup();
+
+		var fill = {
+			type: "linear",
+			x1: 0,
+			y1: gauge.height,
+			x2: 0,
+			y2: 0,
+			colors: [{offset: 0, color: "#ECECEC"}, {offset: 1, color: "white"}]
+		};
+		gauge = dojo.byId("programmaticGauge");
+		gauge = new dojox.widget.BarGauge({
+			id: "programmaticGauge",
+			width: 300,
+			height: 55,
+			dataHeight: 25,
+			dataWidth: 275,
+			dataX: 10,
+			dataY: 25,
+			useRangeStyles: 8,
+			background: fill
+		}, gauge);
+		gauge.startup();
+		
+		gauge.addRanges(ranges2);
+		gauge.setMinorTicks({interval: 1,
+							 length:2,
+							 offset:-2,
+							 width: 1});
+		gauge.setMajorTicks({interval: 5,
+							 length:5,
+							 offset:-5,
+							 width: 1,
+							 font: {family: "Arial", style: "italic", variant: 'small-caps', weight: 'bold', size: "12px"}});
+		valueIndicator = new dojox.widget.gauge.BarIndicator({
+			value:17,
+			width: 7,
+			hover:'Value: 17', 
+			title: 'Value',
+			easing: dojo.fx.easing.bounceOut
+		});
+		targetIndicator = new dojox.widget.gauge.BarLineIndicator({
+			value:6,
+			color:'#D00000',
+			hover:'Target: 6',
+			title: 'Target',
+			// Can use string to indicate easing function (just like in declarative)
+			easing: 'dojo.fx.easing.linear'
+		});
+		gauge.addIndicator(targetIndicator);
+		gauge.addIndicator(valueIndicator);
+		//targetIndicator.update(Math.floor(Math.random() * 70) + 5);
+		handle = setInterval((function(t, v){
+			return (function(){
+				t.update(Math.floor(Math.random() * 70) + 5);
+				v.update(Math.floor(Math.random() * 70) + 5);
+			});
+		})(valueIndicator, targetIndicator), 3000);
+		dojo.connect(dijit.byId('stop'), 'onClick', function(){
+			clearInterval(handle);
+		});
+	}
+	dojo.addOnUnload(function(){
+		clearInterval(handle);
+	});
+</script>
+</head>
+<body class="tundra">
+<h1>Bar Gauge Widget</h1>
+<h2>Default Colored Gauge</h2>
+<div id="defaultGauge"></div>
+<h2>CSS Themed Ranges, Gradient Background, Updating to Random Values on 3s Timer</h2>
+<div id="programmaticGauge"></div>
+<button dojoType="dijit.form.Button" id="stop">Stop Timer</button>
+<h2>Declarative, Gradient Ranges, Gradient Background, No Indicator Boxes</h2>
+<div	dojoType="dojox.widget.BarGauge"
+		id="declarativeGauge"
+		width="300"
+		height="55"
+		dataHeight="25"
+		dataWidth="275"
+		dataX="10"
+		dataY="25"
+		useRangeStyles="0"
+		hideValues="true"
+		majorTicks="{length: 5, width: 1, offset: -5, interval: 5}"
+		background="{
+			type: 'linear',
+			x1: 0,
+			x2: 0,
+			y1: 55,
+			y2: 0,
+			colors: [{offset: 0, color: '#ECECEC'}, {offset: 1, color: 'white'}]
+		}">
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="5"
+			high="10"
+			hover="5 - 10"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#606060'}, {offset: 1, color: '#707070'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range1"
+			low="10"
+			high="20"
+			hover="10 - 20"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#707070'}, {offset: 1, color: '#808080'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range2"
+			low="20"
+			high="30"
+			hover="20 - 30"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#808080'}, {offset: 1, color: '#909090'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range3"
+			low="30"
+			high="40"
+			hover="30 - 40"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#909090'}, {offset: 1, color: '#A0A0A0'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range4"
+			low="40"
+			high="50"
+			hover="40 - 50"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#A0A0A0'}, {offset: 1, color: '#B0B0B0'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range5"
+			low="50"
+			high="60"
+			hover="50 - 60"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#B0B0B0'}, {offset: 1, color: '#C0C0C0'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range6"
+			low="60"
+			high="70"
+			hover="60 - 70"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#C0C0C0'}, {offset: 1, color: '#C0C0C0'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			id="range7"
+			low="70"
+			high="75"
+			hover="70 - 75"
+			color="{
+				'type': 'linear',
+				'colors': [{offset: 0, color:'#C0C0C0'}, {offset: 1, color: '#E0E0E0'}]
+			}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.BarLineIndicator"
+			id="target"
+			value="6"
+			color="#D00000"
+			width="3"
+			hover="Target: 6"
+			title="Target">
+	</div>
+	<div 	dojoType="dojox.widget.gauge.BarIndicator"
+			id="value"
+			value="17"
+			length="135"
+			width="3"
+			hover="Value: 17"
+			title="Value">
+	</div>
+</div>
+<h2>Declarative, (Ugly) Colored Ranges, No Numbers, No Indicator Boxes</h2>
+<div	dojoType="dojox.widget.BarGauge"
+		id="declarativeGauge2"
+		width="300"
+		height="35"
+		dataHeight="25"
+		dataWidth="290"
+		useRangeStyles="0"
+		hideValues="true"
+		background="{color: 'green'}">
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="5"
+			high="10"
+			hover="5 - 10"
+			color="{color: 'red'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="10"
+			high="20"
+			hover="10 - 20"
+			color="{color: '#FFA500'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="20"
+			high="30"
+			hover="20 - 30"
+			color="{color: 'yellow'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="30"
+			high="40"
+			hover="30 - 40"
+			color="{color: '#7FFF00'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="40"
+			high="50"
+			hover="40 - 50"
+			color="{color: '#00FFFF'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="50"
+			high="60"
+			hover="50 - 60"
+			color="{color: 'blue'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="60"
+			high="70"
+			hover="60 - 70"
+			color="{color: '#191970'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.Range"
+			low="70"
+			high="75"
+			hover="70 - 75"
+			color="{color: 'purple'}">
+	</div>
+	<div	dojoType="dojox.widget.gauge.BarLineIndicator"
+			value="6"
+			color="#D00000"
+			hover="Target: 6"
+			title="Target">
+	</div>
+	<div 	dojoType="dojox.widget.gauge.BarIndicator"
+			value="55"
+			width="7"
+			hover="Value: 55"
+			title="Value">
+	</div>
+</div>
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Calendar.html b/dojox/widget/tests/test_Calendar.html
new file mode 100644
index 0000000..a3b38a2
--- /dev/null
+++ b/dojox/widget/tests/test_Calendar.html
@@ -0,0 +1,217 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Dojox Calendar Test</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			@import "../../../dijit/themes/dijit.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+			@import "../Calendar/Calendar.css";
+
+			.title {
+				font-weight: bolder;
+			}
+		</style>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+		<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+		<script type="text/javascript" src="../../../dijit/dijit.js"></script>
+		<script type="text/javascript" src="../../../dijit/_Calendar.js"></script>
+		<script type="text/javascript" src="../FisheyeLite.js"></script>
+		<script type="text/javascript" src="../../fx/_base.js"></script>
+		<script type="text/javascript" src="../Calendar.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+			dojo.require("dojox.fx");
+			dojo.require("dojox.widget.CalendarFx");
+
+			dojo.declare(
+				"test.CalendarCustomFx",
+			 	[dojox.widget.Calendar], {
+
+				addFx: function(query, fromNode){
+					dojo.query(query, fromNode).onmouseover(function(evt){
+						dojox.fx.highlight({node: evt.target}).play();
+					});
+				}
+			});
+			function log(str){
+					dojo.byId("report").innerHTML = str;
+				}
+
+		</script>
+	</head>
+	<body>
+		<div>
+			Use different theme:
+			<a href="test_Calendar.html?theme=tundra">tundra</a>
+			<a href="test_Calendar.html?theme=soria">soria</a>
+			<a href="test_Calendar.html?theme=nihilo">nihilo</a>
+		</div>
+		<div id="report" style="float:left; width:100%;height:40px;color:red;font-weight:bold;"></div>
+
+		<div>
+			<span style="width:33%;float:left;">
+				<div class="title">Typical Calendar usage, with day, and month/year views</div>
+				<div dojoType="dojox.widget.Calendar" id="cal">
+					<script type="dojo/connect" event="onValueSelected" args="value">
+						log("Date Value selected: " + value);
+					</script>
+				</div>
+
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+			</span>
+
+			<span style="width:33%;float:left;">
+				<div class="title">With day only view, no month/year view</div>
+
+				<div dojoType="dojox.widget.DailyCalendar" id="calDayOnly">
+					<script type="dojo/connect" event="onValueSelected" args="value">
+						log("Day Value selected: " + value);
+					</script>
+				</div>
+
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+			</span>
+			<span style="width:33%;float:left;">
+				<div class="title">With day only view, no month/year view</div>
+
+				<div dojoType="dojox.widget.MonthAndYearlyCalendar" id="calMonthAndYearOnly">
+					<script type="dojo/connect" event="onValueSelected" args="value">
+						log("Date Value selected from Month and Year Only Calendar: " + value);
+					</script>
+				</div>
+
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+			</span>
+		</div>
+
+    <div>
+			<span style="width:33%;float:left;">
+				<div class="title">Typical calendar, with min/max constraints = {min:'2008-12-12',max:'2009-01-15'}</div>
+				<div dojoType="dojox.widget.Calendar" id="calLimits" value="2008-12-25"
+						constraints="{min:'2008-12-12',max:'2009-01-15'}">
+					<script type="dojo/connect" event="onValueSelected" args="value">
+						log("Date Value selected: " + value);
+					</script>
+				</div>
+
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+			</span>
+			<span style="width:33%;float:left;">
+				<div class="title">Typical calendar, with min/max constraints a week before and after the current date</div>
+				<div dojoType="dojox.widget.Calendar" id="calLimitsWeek">
+					<script type="dojo/method" event="postMixInProperties">						
+						// This runs after the constructor, before properties are mixed in
+						var currentDate = new Date();
+						this.constraints = {
+						  min: dojo.date.add(currentDate, 'week', -1),
+							max: dojo.date.add(currentDate, 'week', +1)
+						};
+						dojox.widget.Calendar.prototype.postMixInProperties.call(this);
+					</script>
+					<script type="dojo/connect" event="onValueSelected" args="value">
+						log("Date Value selected: " + value);
+					</script>
+				</div>
+
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+			</span>
+			<span style="width:33%;float:left;">
+				<div class="title">Typical calendar, initial date set in HTML to December 25th, 2007</div>
+				<div dojoType="dojox.widget.Calendar" id="calXmas" value="2007-12-25">
+					<script type="dojo/connect" event="onValueSelected" args="value">
+						log("Date Value selected: " + value);
+					</script>
+				</div>
+
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+			</span>
+	 </div>
+
+		<div>
+			<span style="width:50%;float:left;">
+				<div class="title">Standard calendar, with FisheyeLite effects (in development, just here to show that FX can be applied)</div>
+
+				<div dojoType="dojox.widget.CalendarFisheye" id="calFisheye">
+					<script type="dojo/connect" event="onValueSelected" args="value">
+						log("Date Value selected from Fisheye Calendar: " + value);
+					</script>
+				</div>
+
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+			</span>
+			<span style="width:50%;float:left;">
+				<div class="title">With custom Highlighting effects (in development, just here to show that FX can be applied)</div>
+
+				<div dojoType="test.CalendarCustomFx" id="calCustomFx">
+					<script type="dojo/connect" event="onValueSelected" args="value">
+						log("Date Value selected in FX Calendar: " + value);
+					</script>
+				</div><p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+			</span>
+		</div>
+
+
+	</body>
+</html>
diff --git a/dojox/widget/tests/test_CalendarViews.html b/dojox/widget/tests/test_CalendarViews.html
new file mode 100644
index 0000000..b9d08ea
--- /dev/null
+++ b/dojox/widget/tests/test_CalendarViews.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<title>Dojox Calendar Views Test</title>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+			@import "../../../dijit/themes/soria/soria.css";
+			@import "../../../dijit/themes/nihilo/nihilo.css";
+			@import "../../../dijit/themes/dijit.css";
+			@import "../../../dijit/tests/css/dijitTests.css";
+			@import "../Calendar/Calendar.css";
+
+			.title {
+				font-weight: bolder;
+			}
+		</style>
+
+		<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+		<!-- not needed, for testing alternate themes -->
+		<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+		<script type="text/javascript" src="../../../dijit/dijit.js"></script>
+		<script type="text/javascript" src="../../../dijit/_Calendar.js"></script>
+		<script type="text/javascript" src="../Calendar.js"></script>
+		<script type="text/javascript" src="../CalendarViews.js"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+			dojo.require("dojox.fx");
+			dojo.require("dojox.widget.CalendarViews");
+
+			function log(str){
+				dojo.byId("report").innerHTML = str;
+			}
+		</script>
+	</head>
+	<body class="soria">
+		<div>
+			Use different theme:
+			<a href="test_CalendarViews.html?theme=tundra">tundra</a>
+			<a href="test_CalendarViews.html?theme=soria">soria</a>
+			<a href="test_CalendarViews.html?theme=nihilo">nihilo</a>
+		</div>
+		<div id="report" style="float:left; width:100%;height:40px;color:red;font-weight:bold;"></div>
+		<p>
+			This page shows the dojox.widget.Calendar widget with three panes, a day, month and year view.
+			Click on the date on the top of the widget to select the month, and click it again to
+			select the year.
+		</p>
+
+		<div>
+			<span style="width:33%;float:left;">
+				<div class="title">With day, month and year views</div>
+
+				<div dojoType="dojox.widget.Calendar3Pane" id="cal3Pane">
+					<script type="dojo/connect" event="onValueSelected" args="value">
+						log("Date Value selected: " + value);
+					</script>
+				</div>
+
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+			</span>
+			<span style="width:33%;float:left;">
+				<div class="title">With month only view, no daily or yearly</div>
+
+				<div dojoType="dojox.widget.MonthlyCalendar" id="calMonthOnly">
+					<script type="dojo/connect" event="onValueSelected" args="value">
+						log("Month Value selected: " + value);
+					</script>
+				</div>
+
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+			</span>
+			<span style="width:33%;float:left;">
+				<div class="title">With year only view, no daily or yearly</div>
+
+				<div dojoType="dojox.widget.YearlyCalendar" id="calYearOnly">
+					<script type="dojo/connect" event="onValueSelected" args="value">
+						log("Year Value selected: " + value);
+					</script>
+				</div><p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+			</span>
+		</div>
+
+	</body>
+</html>
diff --git a/dojox/widget/tests/test_ColorPicker.html b/dojox/widget/tests/test_ColorPicker.html
new file mode 100644
index 0000000..fb6bc54
--- /dev/null
+++ b/dojox/widget/tests/test_ColorPicker.html
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	
+	<title>Dojox ColorPicker Test</title>
+	
+	<!-- required: a default theme file, and ColorPicker css -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../ColorPicker/ColorPicker.css">
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		#absolutey {
+			position:absolute;
+			top: 62px;
+			left: 362px;
+		}
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	
+	<!-- debugging include -->
+	<script type="text/javascript" src="../ColorPicker.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.widget.ColorPicker");
+		dojo.require("dijit.form.Button");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		// generic onChange handler:
+		var handler = function(val,id){
+			dojo.byId(id).value = val;
+		};
+
+		dojo.addOnLoad(function(){
+			dojo.connect(dijit.byId("testFocusButton"), "onClick", function(){
+			dijit.byId("picker").focus();
+			});
+		});
+	</script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">Dojox ColorPicker test</h1>
+
+	<h3>defaults:</h3>
+	<div id="picker" dojoType="dojox.widget.ColorPicker"
+		value="#9ebf6c"
+		onChange="handler(arguments[0],'onchangeOne')"
+	></div>
+	<p>Current value: <input readonly="true" id="onchangeOne" value="???" /></p>
+	
+	<h3>no animation, no hsv, no rgb, no webSafe info:</h3>
+	<div id="pickerToo" dojoType="dojox.widget.ColorPicker"
+		animatePoint="false"
+		showHsv="false"
+		showRgb="false"	
+		webSafe="false"
+		onChange="handler(arguments[0],'onchangeTwo')"
+	></div>
+	<p>Current value: <input readonly="true" id="onchangeTwo" value="???" /></p>
+	
+	<h3>Fires onChange a lot:</h3>
+	<div id="pickerLive" dojoType="dojox.widget.ColorPicker"
+		webSafe="false"
+		liveUpdate="true"
+		onChange="handler(arguments[0],'onchangeThree')"
+	></div>
+	<p>Current value: <input readonly="true" id="onchangeThree" value="???" /></p>
+	
+	<div id="absolutey">
+		<h3>To See how it positions in an absolute node (editor plugin, input popup)</h3>
+		<input dojoType="dojox.widget.ColorPicker" value="#ededed">
+	</div>
+
+	<button id="testFocusButton" type="button" dojoType="dijit.form.Button">Click to focus first widget</button>
+	
+	<p>that's all folks!</p>
+	
+</body>
+</html>
diff --git a/dojox/widget/tests/test_DataPresentation.html b/dojox/widget/tests/test_DataPresentation.html
new file mode 100644
index 0000000..41a3764
--- /dev/null
+++ b/dojox/widget/tests/test_DataPresentation.html
@@ -0,0 +1,158 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html style="height: 100%;">
+<head>
+	<title>DataPresentation widget example</title>
+	
+	<style type="text/css"> 
+     		@import "../../../dijit/themes/tundra/tundra.css";
+			  @import "../../../dojox/grid/resources/tundraGrid.css";
+     		@import "../../../dojo/resources/dojo.css"
+        @import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	
+	
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
+  
+	<script type="text/javascript">
+
+    dojo.require("dojox.widget.DataPresentation");
+    dojo.require("dojox.charting.themes.Minty");
+    
+		var jsondata0 = {
+				"title"  : "Softdrink Sales (2007)",
+				"footer" : "North America only",
+				"range"  : [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ],
+				"series" : [                            
+					{ "legend" : "Cola", "line" : true, "values" : [ "35", "37", "44", "41", "43", "57", "62", "69", "74", "86", "101", "124" ] },
+					{ "legend" : "Lemonade", "values" : [ "122", "99", "111", "98", "82", "77", "76", "67", "72", "75", "66", "67" ] },
+					{ "legend" : "Dandelion and burdock", "values" : [ "99", "98", "98", "99", "97", "102", "100", "99", "102", "97", "95", "98" ] },
+					{ "legend" : "Ginger ale", "values" : [ "54", "59", "76", "84", "98", "110", "126", "121", "115", "109", "104", "99" ] },
+					{ "legend" : "Creme soda", "values" : [ "44", "58", "44", "36", "48", "54", "34", "38", "24", "56", "48", "34" ] },
+					{ "legend" : "Orangeade", "values" : [ "45", "25", "45", "31", "42", "33", "49", "34", "46", "25", "44", "37" ] },
+					{ "legend" : "Diet lemonade", "values" : [ "34", "17", "38", "13", "33", "14", "22", "39", "26", "17", "35", "21" ] },
+					{ "legend" : "Shandy", "values" : [ "14", "23", "16", "32", "12", "24", "18", "25", "13", "33", "15", "25" ] }
+				]
+		};
+
+    // shake things up a bit, just for fun
+    setInterval(function() {
+      var series = Math.floor(jsondata0.series.length * Math.random());
+      var value = Math.floor(jsondata0.series[series].values.length * Math.random());
+      var newvalue = parseInt(jsondata0.series[series].values[value]) + Math.floor(11 * Math.random()) - 5;
+      jsondata0.series[series].values[value] = "" + newvalue;  
+    }, 100);		
+
+	  var jsondata1 = {
+        "title"  : "Softdrink Sales (2007)",
+        "footer" : "North America only",
+        "sales"  : [
+          { "month": "Jan", "cola": "84", "lemonade": "75", "dandelionandburdock": "64", "gingerale": "54" },
+          { "month": "Feb", "cola": "108", "lemonade": "65", "dandelionandburdock": "47", "gingerale": "43" },
+          { "month": "Mar", "cola": "24", "lemonade": "85", "dandelionandburdock": "68", "gingerale": "76" },
+          { "month": "Apr", "cola": "56", "lemonade": "75", "dandelionandburdock": "73", "gingerale": "92" },
+          { "month": "May", "cola": "78", "lemonade": "82", "dandelionandburdock": "43", "gingerale": "32" },
+          { "month": "Jun", "cola": "124", "lemonade": "43", "dandelionandburdock": "34", "gingerale": "54" },
+          { "month": "Jul", "cola": "84", "lemonade": "59", "dandelionandburdock": "42", "gingerale": "78" },
+          { "month": "Aug", "cola": "108", "lemonade": "34", "dandelionandburdock": "69", "gingerale": "65" },
+          { "month": "Sep", "cola": "24", "lemonade": "76", "dandelionandburdock": "86", "gingerale": "43" },
+          { "month": "Oct", "cola": "56", "lemonade": "65", "dandelionandburdock": "77", "gingerale": "43" },
+          { "month": "Nov", "cola": "78", "lemonade": "34", "dandelionandburdock": "65", "gingerale": "45" },
+          { "month": "Dec", "cola": "124", "lemonade": "67", "dandelionandburdock": "41", "gingerale": "65" }
+        ]
+    };
+
+	  var salesnumbers = function(value, index)
+	  {
+		  var ivalue = parseInt(value);
+		  
+		  if (ivalue > 100)
+			  return '<div style="text-align: right; background-color: #ddffcc; width: ' + (((ivalue * 80) / 130) + 20) + '%;">' + value + '</div>';
+			else
+	      return '<div style="text-align: right; background-color: #ffddcc; width: ' + (((ivalue * 80) / 130) + 20) + '%;">' + value + '</div>';
+	  }
+
+    var makeseries = function(data)
+    {
+      if (!data.sales)
+	      return [ { datapoints: "range", name: "Month", type: "range", chart: false },
+	               { datapoints: "series[0].values", namefield: "series[0].legend", gridformatter: salesnumbers },
+	               { datapoints: "series[1].values", name: "Lemonade (fizzy)", charttype: "line", gridformatter: salesnumbers },
+	               { datapoints: "series[2].values", namefield: "series[2].legend", gridformatter: salesnumbers },
+	               { datapoints: "series[3].values", namefield: "series[3].legend", gridformatter: salesnumbers }
+	             ];
+      else
+        return [ { datapoints: "sales", field: "month", name: "Month", type: "range", chart: false },
+                 { datapoints: "sales", field: "lemonade", name: "Lemonade (fizzy)" },
+                 { datapoints: "sales", field: "dandelionandburdock", name: "Dandelion and burdock" },
+                 { datapoints: "sales", field: "cola", name: "Cola" },
+                 { datapoints: "sales", field: "gingerale", name: "Ginger ale" }
+               ];
+    }
+	  
+	  var dp;
+
+		dojo.addOnLoad(function() {
+
+			  var jsondata = jsondata0;   // (or jsondata1)
+
+			  dp = new dojox.widget.DataPresentation("chartdiv", {
+				  type: "chart",
+				  chartType: "Hybrid",
+				  data: jsondata,
+          refreshInterval: 3000,
+				  series: makeseries(jsondata),
+          legendNode: "legenddiv",
+          legendHorizontal: 2,
+          //labelMod: 2,  // display every other x-axis label
+          //labelMod: 0,  // suppress x-axis labels
+          gridNode: "griddiv",
+          titleNode: "title",
+          footerNode: "footer",
+          theme: "dojox.charting.themes.Minty",
+          labelMod: 2,
+          tooltip: "The value for this {0} for '{1}' in {2} is <b>{3}</b>"
+			  });
+
+		});
+	</script>
+</head>
+<body style="font-family: arial; font-size: 12px; height: 100%;" class="tundra">
+
+<h1>An example of DataPresentation widget</h1>
+
+<p>This example shows automatic refresh (every 3 seconds), although this is
+most useful in conjunction with a URL where the data may change each time. 
+To make something visible, some background code is tweaking the values randomly
+so that the automatic refresh always pulls changed data.</p>
+
+<p>To see how the widget can cope with different data shapes, switch from 
+jsondata0 to jsondata1 as the input data. jsondata0 is structured as complete
+'series' of values, gathered into an array with series titles. jsondata1 is
+structures as 'data points', each containing multiple sales values.
+
+<p>Note that the widget is driving its own DOM node (the chart, in this case, 
+although it could be any of the components) and is also driving other nodes
+containing the grid, legend, etc.</p>
+
+  <div style="width:400px; text-align: center;">
+    <h2 id="title" style="margin-bottom: 0;"></h2>
+    <p id="footer" style="color: gray; font-size: 0.85em; margin-top: 0.2em;"></p>
+  </div>
+	
+  <div style="width: 450px; position: relative;">
+	  <div id="chartdiv" style="width: 400px; height: 300px;"></div>
+      
+    <div style="position: absolute; top: 40px; right: 0px; padding: 0.2em 0.5em; border: 1px solid gray; background-color: rgba(255, 255, 221, 0.8);">
+      <div id="legenddiv" style="z-index: 1;"></div>
+    </div>
+	</div>
+	  
+	<p>Now here is the same data displayed in a grid (also driven by the same DataPresentation widget):</p>
+	
+  <div style="width:400px; height:240px;">
+    <div id="griddiv"></div>
+  </div>    
+
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Dialog.html b/dojox/widget/tests/test_Dialog.html
new file mode 100644
index 0000000..f95b0d9
--- /dev/null
+++ b/dojox/widget/tests/test_Dialog.html
@@ -0,0 +1,307 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>DojoX Dialog example</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../Dialog/Dialog.css">
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+
+		/* this is how you style underlays */	
+		#thirdTest_underlay { background-color: #000 }
+		#fourthTest_underlay,
+		#secondTest_underlay { background-color: #369 }
+	</style>		
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dojox.widget.Dialog");
+		dojo.require("dojo.fx.easing");
+		dojo.require("dijit.form.Button");
+		dojo.addOnLoad(function(){
+			
+			// a programatic test:
+			var thinger = new dojox.widget.Dialog({
+				title:"foobar",
+				dimensions: [200,200],
+				draggable:false,
+				easing: dojo.fx.easing.elasticOut,
+				sizeDuration:900,
+				sizeMethod:"combine"
+			},"codeMade");
+			thinger.startup();
+			
+
+			// make the "stock" buttons dijit Buttons, but skip the 
+			// dojoType="" for the purists.
+			dojo.query("button")
+				.forEach(function(n){
+					var oc = dojo.attr(n,"onclick");
+					var button = new dijit.form.Button({
+						onClick: oc
+					},n)
+				});
+
+			// programatic with content: 
+			var thing2 = new dojox.widget.Dialog({
+				content:"<p>I am teh inner content</p>"
+			});
+			thing2.startup();
+				
+			new dijit.form.Button({
+				onClick:function(){
+					thing2.show()
+				},
+				label:"show prog."
+			}).placeAt("testholder");
+
+			// test double show (but #9147)
+			var dblDialog = new dojox.widget.Dialog({
+				content:"<p>.show() is called twice on me</p>"
+			});
+			dblDialog.startup();
+
+			new dijit.form.Button({
+				onClick:function(){
+					dblDialog.show();
+					dblDialog.show(); // intentially calling show() on an already shown dialog
+				},
+				label:"double show."
+			}).placeAt("testholder");
+			
+		});
+	</script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">dojox.widget.Dialog tests</h1>
+	
+	<p>This is the DojoX version of the dijit.Dialog. It's very different.</p>
+
+	<div id='testholder' class="tests">
+		<button onclick="dijit.byId('firstTest').show()">Defaults only</button>
+		
+		<div id="firstTest" dojoType="dojox.widget.Dialog" title="A Dialog Thinger">
+			<p style="margin-top:0">Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+			</p>
+		</div>
+	
+		<button onclick="dijit.byId('secondTest').show()">Size to viewport, default padding (35)</button>
+	
+		<div id="secondTest" dojoType="dojox.widget.Dialog" sizeToViewport="true" title="A Dialog Thinger">
+			<p style="margin-top:0">Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+			</p>
+		</div>
+
+		<button onclick="dijit.byId('thirdTest').show()">Size to viewport + 100 padding</button>
+	
+		<div id="thirdTest" dojoType="dojox.widget.Dialog" sizeToViewport="true" viewportPadding="100" title="A Dialog Thinger">
+			<p style="margin-top:0">Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+			</p>
+		</div>
+
+		<button onclick="dijit.byId('fourthTest').show()">dimensions 600 x 420</button>	
+		<div id="fourthTest" dojoType="dojox.widget.Dialog" dimensions="[600,420]" title="A Dialog Thinger">
+			<p style="margin-top:0">Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+			</p>
+		</div>
+
+		<button onclick="dijit.byId('anotherTest').show()">sizeDuration and easing</button>	
+		<div id="anotherTest" dojoType="dojox.widget.Dialog" sizeToViewport="true" 
+			viewportPadding="150" easing="dojo.fx.easing.backOut" sizeDuration="1400" 
+			title="A Dialog Thinger"
+		>
+			<h2 style="margin-top:0">Wow!</h2>
+			<p style="margin-top:0">Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+			</p>
+		</div>
+
+		<button onclick="dijit.byId('hrefText').show()">href + defaults</button>
+		<div id="hrefText" dojoType="dojox.widget.Dialog" href="../../../dijit/tests/layout/getResponse.php?delay=3000&messId=3"></div>
+		
+		<button onclick="dijit.byId('yetanotherTest').show()">showTitle</button>	
+		<div id="yetanotherTest" dojoType="dojox.widget.Dialog" showTitle="true" title="I am A title!!!">
+			<h2 style="margin-top:0">Wow!</h2>
+			<p style="margin-top:0">
+				Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+				Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+				Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+				Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+				Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+				Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+			</p>
+		</div>
+	
+		<button onclick="dijit.byId('yetanotherTest2').show()">draggable</button>	
+		<div id="yetanotherTest2" dojoType="dojox.widget.Dialog" draggable="true" showTitle="true" title="I am A title!!!">
+			<h2 style="margin-top:0">Wow!</h2>
+			<p style="margin-top:0">Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+			</p>
+		</div>
+	
+		<button onclick="dijit.byId('yetanotherTest3').show()">method = combine, easing</button>	
+		<div id="yetanotherTest3" dojoType="dojox.widget.Dialog" sizeMethod="combine"
+		 	easing="dojo.fx.easing.bounceOut" sizeDuration="600">
+			<h2 style="margin-top:0">Wow!</h2>
+			<p style="margin-top:0">Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+			</p>
+		</div>
+	
+		<button onclick="dijit.byId('codeMade').show()">programatic</button>
+		<div id="codeMade"><h2 style="margin-top:0">Wow!</h2><p>A small dialog</p></div>
+
+		<button onclick="dijit.byId('modaltest').show()">modal:true</button>
+		<div id="modaltest" dojoType="dojox.widget.Dialog" modal="true"
+		 	easing="dojo.fx.easing.bounceOut" sizeDuration="600">
+			<h2 style="margin-top:0">Wow!</h2>
+			<p style="margin-top:0">Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam
+			ornare elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque
+			nonummy mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus
+			lobortis, sem vitae nonummy lacinia, nisl est gravida magna, non cursus
+			est quam sed urna. Phasellus adipiscing justo in ipsum. Duis sagittis
+			dolor sit amet magna. Suspendisse suscipit, neque eu dictum auctor,
+			nisi augue tincidunt arcu, non lacinia magna purus nec magna. Praesent
+			pretium sollicitudin sapien. Suspendisse imperdiet. Class aptent taciti
+			sociosqu ad litora torquent per conubia nostra, per inceptos
+			hymenaeos.
+			</p>
+		</div>
+
+	
+	</div>
+
+	<p>There are several additional parameters to define how you want to display the dialog. It makes 
+		<em>some</em> assumption about how you want to size your pane.</p>
+		 
+	<p>That's all folks, all of the supported options have buttons and inline tests.</p>
+
+</body>
+</html>
+
diff --git a/dojox/widget/tests/test_DocTester.html b/dojox/widget/tests/test_DocTester.html
new file mode 100644
index 0000000..54ed592
--- /dev/null
+++ b/dojox/widget/tests/test_DocTester.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox DocTester Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		@import "../DocTester/DocTester.css"; 
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../DocTester.js"></script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">Dojox DocTester test</h1>
+
+	<h2>Default Usage</h2>
+	You can just "throw" your doctests inside a node and give it the <code>dojoType="dojox.widget.DocTester"</code>, and you will get the box below.
+	Including the buttons and the summary below the box.
+	
+	<div id="t1" dojoType="dojox.widget.DocTester">
+		>>> 1+1
+		2
+		>>> "one" + "two"
+		"three"
+		>>> (new dojo._Url("http://localhost/?a=1&b=2")).query
+		"a=1&b=2"
+		>>> dojo.trim(" 123 ")
+		"123"
+		>>> var one = 1
+		>>> "two" + one
+		"two1"
+		
+		>>> var one = 1
+		>>> 2 + one
+		"21"
+		
+		>>> var l = [1,5,8,9,0];
+		>>> dojo.indexOf(l, 8);
+		2
+	</div>
+
+</body>
+</html>
diff --git a/dojox/widget/tests/test_DynamicTooltip.html b/dojox/widget/tests/test_DynamicTooltip.html
new file mode 100644
index 0000000..06e5679
--- /dev/null
+++ b/dojox/widget/tests/test_DynamicTooltip.html
@@ -0,0 +1,178 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo Dynamcic Tooltip Widget Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		
+		td { padding: 20px; }
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+	
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dojox.widget.DynamicTooltip");
+		dojo.require("dijit.ColorPalette");
+		dojo.addOnLoad(function(){
+			console.log("on load func");
+			var tt = new dojox.widget.DynamicTooltip({
+				label:"programmatically created tooltip", 
+				connectId:["programmaticTest"]
+			});
+			console.log("created", tt, tt.id);
+			var ttd = new dojox.widget.DynamicTooltip({
+				label:"programmatically created dynmaic tooltip", 
+				href: 'get_time.php', 
+				connectId:["programmaticTestDynamic"]
+			});
+			console.log("created", ttd, ttd.id);
+		});
+	</script>
+</head>
+<body class="tundra">
+	
+	<h1 class="testTitle">Dynamic Tooltip test</h1>
+
+	<p>Mouse-over or focus the items below to test tooltips.</p>
+	<table>
+		<tr>
+			<td>
+				Change tooltip positioning search list:
+			</td>
+			<td>
+				Set background color:
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<button onclick="dojox.widget.DynamicTooltip.defaultPosition=['above', 'below']; dojo.byId('current').innerHTML='Current: ' + dojox.widget.DynamicTooltip.defaultPosition;">above, below</button>
+				<button onclick="dojox.widget.DynamicTooltip.defaultPosition=['after', 'before']; dojo.byId('current').innerHTML='Current: ' + dojox.widget.DynamicTooltip.defaultPosition;">after, before (default)</button>
+				<div id=current>
+					Current: default (unchanged)
+				</div>
+			</td>
+			<td>
+				<div dojoType="dijit.ColorPalette" onChange="dojo.query('body').style('background', arguments[0]);"></div>
+			</td>
+		</tr>
+	</table>
+	
+	<div><span id="dyn_one" class="tt" tabindex="0"> dynamic tooltip </span>
+		<span dojoType="dojox.widget.DynamicTooltip" connectId="dyn_one" id="dyn_one_tooltip" href="get_time.php" preventCache="true">
+			<b>
+				<span style="color: blue;">Should not ever see this!</span>
+			</b>
+		</span>
+		<span style="color: blue;"><button onclick="dijit.byId('dyn_one_tooltip').refresh();">Refresh Dynamic Tooltip</button></span>
+	</div>
+	<div><span id="dyn_two" class="tt" tabindex="0"> dynamic tooltip set href</span>
+		<span dojoType="dojox.widget.DynamicTooltip" connectId="dyn_two" id="dyn_two_tooltip" href="get_time.php" preventCache="true">
+			<b>
+				<span style="color: blue;">Should not ever see this!</span>
+			</b>
+		</span>
+		<span style="color: blue;">
+			<button onclick="dijit.byId('dyn_two_tooltip').attr('href', 'honey.php');">Set URL honey.php, delayed</button>
+			<button onclick="dijit.byId('dyn_two_tooltip').attr('href', 'get_time.php');">Set URL get_time.php</button>
+		</span>
+	</div>
+	<span id="programmaticTestDynamic">this text has a programmatically created dynamic tooltip</span>
+
+	<br><br>
+	
+	<div><span id="one" class="tt" tabindex="0"> focusable text </span>
+		<span dojoType="dojox.widget.DynamicTooltip" connectId="one" id="one_tooltip">
+			<b>
+				<span style="color: blue;">rich formatting</span>
+				<span style="color: red; font-size: x-large;"><i>!</i></span>
+			</b>
+		</span>
+	</div>
+	<span id="oneA" class="tt"> plain text (not focusable) </span>
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="oneA" id="oneA_tooltip">
+		<span> keyboard users can not access this tooltip</span>
+	</span>
+    <a id="three" href="#bogus">anchor</a>
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="three" id="three_tooltip">tooltip on a link </span>
+	<p></p>
+
+	<span id="programmaticTest">this text has a programmatically created tooltip</span>
+	<br>
+
+	<button id="four">button w/tooltip</button>
+	<span id="btnTt" dojoType="dojox.widget.DynamicTooltip" connectId="four" id="four_tooltip">tooltip on a button</span>
+	<button onclick="dijit.byId('btnTt').destroy()">Remove</button> tooltip from "button w/tooltip".
+
+	<span style="float: right">
+		Test tooltip on right aligned element.  Tooltip should flow to the left -->
+		<select id="seven">
+			<option value="alpha">Alpha</option>
+			<option value="beta">Beta</option>
+			<option value="gamma">Gamma</option>
+			<option value="delta">Delta</option>
+		</select>
+
+		<span dojoType="dojox.widget.DynamicTooltip" connectId="seven" id="seven_tooltip">
+			tooltip on a select<br>
+			two line tooltip.
+		</span>
+	</span>
+
+	<p></p>
+
+	<form>
+		<input id="id1" value="#1"><br>
+		<input id="id2" value="#2"><br>
+		<input id="id3" value="#3"><br>
+		<input id="id4" value="#4"><br>
+   		<input id="id5" value="#5"><br>
+		<input id="id6" value="#6"><br>
+	</form>
+	<br>
+
+	<div style="overflow: auto; height: 100px; position: relative; border: solid blue 3px;">
+		<span id="s1">s1 text</span><br><br><br>
+		<span id="s2">s2 text</span><br><br><br>
+		<span id="s3">s3 text</span><br><br><br>
+		<span id="s4">s4 text</span><br><br><br>
+		<span id="s5">s5 text</span><br><br><br>
+	</div>
+
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="id1" id="id1_tooltip">
+
+	tooltip for #1<br>
+	long long long long long long long long long long long text<br>
+	make sure that this works properly with a really narrow window
+	</span>
+
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="id2" id="id2_tooltip">tooltip for #2</span>
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="id3" id="id3_tooltip">tooltip for #3</span>
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="id4" id="id4_tooltip">tooltip for #4</span>
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="id5" id="id5_tooltip">tooltip for #5</span>
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="id6" id="id6_tooltip">tooltip for #6</span>
+
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="s1" id="s1_tooltip">s1 tooltip</span>
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="s2" id="s2_tooltip">s2 tooltip</span>
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="s3" id="s3_tooltip">s3 tooltip</span>
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="s4" id="s4_tooltip">s4 tooltip</span>
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="s5" id="s5_tooltip">s5 tooltip</span>
+
+	<h3>One Tooltip for multiple connect nodes</h3>
+	<span dojoType="dojox.widget.DynamicTooltip" connectId="multi1,multi2" id="multi1,multi2_tooltip" style="display:none;">multi tooltip</span>
+	<a id="multi1" href="#bogus">multi1</a><br><a id="multi2" href="#bogus">multi2</a>
+
+</body>
+</html>
+
diff --git a/dojox/widget/tests/test_FilePicker.html b/dojox/widget/tests/test_FilePicker.html
new file mode 100644
index 0000000..142a242
--- /dev/null
+++ b/dojox/widget/tests/test_FilePicker.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>File Picker Demo</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+	
+	<!-- the additional styles for the widget -->
+	<link id="widgetStyle" rel="stylesheet" href="../FilePicker/FilePicker.css">
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true, useCommentedJson: true"></script>
+	
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.widget.FilePicker");
+		dojo.require("dojox.data.FileStore");
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>
+		Demo: File Browser widget using dojox.data.FileStore
+	</h1>
+	<p>The picker below uses the dojox.data.FileStore and a PHP implementation for the serverside to browse the dojo tree hierarchy in a lazy-load fashion.</p>
+	<p><i><b>This demo must be run from a web-server with PHP support enabled.  Without PHP support, this demo cannot function.</b></i></p>
+	<hr>
+	<div dojoType="dojox.data.FileStore" url="../../data/demos/stores/filestore_dojotree.php" jsId="fileStore" pathAsQueryParam="true"></div>
+	<div dojoType="dojox.widget.FilePicker" jsId="myPicker" id="myPicker" style="width: 50%;" store="fileStore" query="{}"></div>
+</body>
+</html>
+
+
diff --git a/dojox/widget/tests/test_FisheyeList.html b/dojox/widget/tests/test_FisheyeList.html
new file mode 100644
index 0000000..348ea13
--- /dev/null
+++ b/dojox/widget/tests/test_FisheyeList.html
@@ -0,0 +1,144 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>FisheyeList Widget Dojo Tests</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		@import "../FisheyeList/FisheyeList.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../FisheyeList.js"></script>
+	<script type="text/javascript">
+		//dojo.require("dojox.widget.FisheyeList");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		dojo.addOnLoad(function(){
+			fish1 = dijit.byId("fisheye1");
+			fish2 = dijit.byId("fisheye2");
+		});
+		var counter = 1;
+		function addToFirstList(){
+			var item = new dojox.widget.FisheyeListItem();
+			item.label = "Dynamically Added "+counter;
+			item.iconSrc = "images/fisheye_"+counter+".png"
+			item.postCreate();
+			counter++;
+			if(counter>4){counter=1;}
+			fish1.addChild(item);
+			fish1.startup();
+			item.startup();
+		}
+	</script>
+</head>
+<body class="tundra">
+	<h1>dojox.widget.FisheyeList test</h1>
+<p>HTML before</p>
+<button onclick="addToFirstList();">Add a new item to the first list</button>
+<p>HTML before</p>
+<p>HTML before</p>
+<p>Liberal trigger: move the mouse anywhere near the menu and it will start to expand:</p>
+<div dojoType="dojox.widget.FisheyeList"
+	itemWidth="40" itemHeight="40"
+	itemMaxWidth="150" itemMaxHeight="150"
+	orientation="horizontal"
+	effectUnits="2"
+	itemPadding="10"
+	attachEdge="center"
+	labelEdge="bottom"
+	id="fisheye1"
+>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		id="item1"
+		onclick="alert('click on ' + this.label + '(from widget id ' + this.widgetId + ')!');"
+		label="Item 1"
+		iconSrc="images/fisheye_1.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		label="Item 2"
+		iconSrc="images/fisheye_2.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		label="Item 3"
+		iconSrc="images/fisheye_3.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		iconSrc="images/fisheye_4.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		label="Really Long Item Label"
+		iconSrc="images/fisheye_3.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		iconSrc="images/fisheye_2.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		iconSrc="images/fisheye_1.png">
+	</div>
+</div>
+
+<p>HTML after</p>
+<p>HTML after</p>
+<p>HTML after</p>
+<p>This one has strict triggering, so you actually have to mouse over the menu to make it start moving:</p>
+<div dojoType="dojox.widget.FisheyeList"
+	itemWidth="40" itemHeight="40"
+	itemMaxWidth="150" itemMaxHeight="150"
+	orientation="horizontal"
+	effectUnits="2"
+	itemPadding="10"
+	attachEdge="center"
+	labelEdge="bottom"
+	conservativeTrigger="true"
+	id="fisheye2"
+>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		id="item1b"
+		onclick="alert('click on ' + this.label + '(from widget id ' + this.widgetId + ')!');"
+		label="Item 1"
+		iconSrc="images/fisheye_1.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		label="Item 2"
+		iconSrc="images/fisheye_2.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		label="Item 3"
+		iconSrc="images/fisheye_3.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		iconSrc="images/fisheye_4.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		label="Really Long Item Label"
+		iconSrc="images/fisheye_3.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		iconSrc="images/fisheye_2.png">
+	</div>
+
+	<div dojoType="dojox.widget.FisheyeListItem"
+		iconSrc="images/fisheye_1.png">
+	</div>
+</div>
+
+
+</body>
+</html>
diff --git a/dojox/widget/tests/test_FisheyeLite.html b/dojox/widget/tests/test_FisheyeLite.html
new file mode 100644
index 0000000..befe1a6
--- /dev/null
+++ b/dojox/widget/tests/test_FisheyeLite.html
@@ -0,0 +1,327 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+	<title>A responsive Fisheye-like FisheyeLite widget | The Dojo Toolkit</title>
+	<style type="text/css">
+
+	    body, html { margin:0; padding:0; width:100%;
+			font-family:Arial,sans-serif;
+		}
+		a { letter-spacing:0.1em; }
+		#list {
+			position:absolute; left:0px; cursor:pointer;
+		}
+		#container { margin:0 auto; width:400px; }
+		#list ul {
+			width:175px;
+			list-style-type:none;
+		}
+		.fisheyeTarget {
+			font-weight:bold;
+			font-size:19px;
+		}
+		#container li {
+			text-align:right;
+			padding-bottom:12px;
+		}
+		.ilk {
+			border-top:1px solid #999;
+			color:#666;
+			font:14px Arial,sans-serif;
+		}
+		#inlineList li {
+			margin-top:20px;
+			margin-bottom:20px;
+			padding:20px;
+			border:2px solid #ededed;
+			display:inline;
+			background:#fff;
+		}
+		
+		#lineHeightTest {
+			text-align:center;
+			position:relative;
+			overflow:visible;
+		}
+		span.line {
+			margin:10px;
+			padding:3px;
+			line-height:22px;
+			font:10px Arial,sans-serif;
+			display:block;
+		}
+		.imgBounce {
+			padding:0;
+			width:35px; height:35px;
+			vertical-align:middle;
+			position:relative;
+			top:0;
+		}
+	</style>
+	<script type="text/javascript">
+		var djConfig = { isDebug:true, parseOnLoad:true };
+	</script>
+	<script type="text/javascript" src="../../../dojo/dojo.js"></script>
+	<script type="text/javascript" src="../FisheyeLite.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojox.widget.FisheyeLite");
+
+		var beenDestroyed = false;
+		var hasInit = false;
+		var init = function(e){
+			
+			if(e && !beenDestroyed){ return; }
+			e && e.preventDefault();
+			
+			// turn li's in this page into fisheye items, presumtiously:	
+			dojo.query("li.bounce").instantiate(dojox.widget.FisheyeLite,{});
+
+			var l = dojo.query("span.line")
+				.instantiate(dojox.widget.FisheyeLite,{
+				// make a widget from each of the lines in the lineHeightTest
+					properties: {
+						fontSize:1.75
+					},
+					easeOut: dojo.fx.easing.backInOut,
+					durationOut: 500
+				});
+				
+			if(!hasInit){
+				l.connect("onclick",function(e){
+				// you can still access the onclick of the real node
+					alert(e.target.innerHTML);
+				});
+			}
+
+			var lm = dojo.query("a").instantiate(dojox.widget.FisheyeLite,{
+				properties:{
+					fontSize:1.15,
+					letterSpacing:2.85
+				}
+			});
+			if(!hasInit){
+			// stop anchors from doing _anything_	
+				lm.connect("onclick",dojo,"stopEvent");
+			}
+
+			dojo.query(".imgBounce").instantiate(dojox.widget.FisheyeLite,{
+				// all the images need a width and a height (well, not need,
+				// but to scale you do)				
+				properties: {
+					height:1.75,
+					width:1.75
+				}
+			});
+			
+			// show the new non-numeric multiplier version of fisheyelite
+			dojo.query(".advancedProps").instantiate(dojox.widget.FisheyeLite,{
+				properties:{
+					height: {
+						end: 100
+					}
+				}
+			})
+			
+			// 
+			var vv = 0;
+			var r = dijit.registry.byClass("dojox.widget.FisheyeLite")._hash;
+			for(var l in r){
+				vv++;
+			}
+			
+			// a few in markup, mostly from the query()'ies:
+			console.log("fisheyes on this page: ", vv);
+				
+			beenDestroyed = false;
+			hasInit = true;
+		};
+		dojo.addOnLoad(init);
+		
+		dojo.addOnLoad(function(){
+			dojo.query("#restore").connect("onclick",init);
+			dojo.query("#destroy").connect("onclick",destroyAll);
+		});
+		
+		var destroyAll = function(e){
+			e && e.preventDefault();
+			if(confirm("really?")){
+				dijit.registry.filter(function(w){
+					return w && w.declaredClass == "dojox.widget.FisheyeLite";
+				}).forEach(function(w){
+					w.destroy(true);
+				});
+				beenDestroyed = true;
+			}
+		};
+			
+	</script>
+    </head>
+    <body class="tundra">
+		<div id="container">
+			
+			<div id="list">
+				<ul>
+					<li class="bounce"><span class="fisheyeTarget">Dojo</span><br><div class="ilk">the javascript toolkit</div></li>
+					<li class="bounce"><span class="fisheyeTarget">Dijit</span><br><div class="ilk">UI y mas - themeable, plugable.</div></li>
+					<li class="bounce"><span class="fisheyeTarget">DojoX</span><br><div class="ilk">extensions, experimentals, extras. innovation.</div></li>
+					<li class="bounce"><span class="fisheyeTarget">Dojo</span><br><div class="ilk">the javascript toolkit</div></li>
+					<li class="bounce"><span class="fisheyeTarget">Dijit</span><br><div class="ilk">UI y mas - themeable, plugable.</div></li>
+					<li class="bounce"><span class="fisheyeTarget">DojoX</span><br><div class="ilk">extensions, experimentals, extras. innovation.</div></li>
+					<li class="bounce"><span class="fisheyeTarget">Dojo</span><br><div class="ilk">the javascript toolkit</div></li>
+					<li class="bounce"><span class="fisheyeTarget">Dijit</span><br><div class="ilk">UI y mas - themeable, plugable.</div></li>
+				</ul>
+			</div>
+		
+			<h2>A paragraph: (with links)</h2>
+		
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+
+			<h3>read the fine print:</h3>
+				
+				<p>
+					<input type="button" onclick="dijit.byId('l1').show()" value="show first" />
+					<input type="button" onclick="dijit.byId('l1').hide()" value="hide first" />
+					<input type="button" onclick="dijit.byId('l3').show()" value="show third" />
+					<input type="button" onclick="dijit.byId('l3').hide()" value="hide third" />					
+				</p>
+
+				<div id="lineHeightTest">
+					<span id="l1" class="line">Aliquam vitae enim. Duis scelerisque metus auctor est venenatis</span>
+					<span class="line">imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer</span>
+					<span id="l3" class="line">lorem nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean</span>
+					<span class="line">id mi in massa bibendum suscipit. Integer eros. Nullam suscipit</span>
+					<span id="l5" class="line">mauris. In pellentesque. Mauris ipsum est, pharetra semper,</span>
+					<span class="line">pharetra in, viverra quis, tellus. Etiam purus.</span>
+				</div>
+
+				<div>
+					<div dojoType="dojox.widget.FisheyeLite" properties="{ fontSize:1.25 }" style="padding:3px"
+					><a id='destroy' href="#" class="fisheyeTarget">test destroy()</a></div>
+
+					<div dojoType="dojox.widget.FisheyeLite" properties="{ fontSize:1.25 }" style="padding:3px"
+					><a id='restore' href="#" class="fisheyeTarget">restore</a></div>
+				</div>
+
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. <a href="#">Morbi</a> dictum rutrum
+				magna. Sed vitae risus.
+				</p>
+				<p>
+				Lorem ipsum dolor sit amet, <a href="#">consectetuer</a> adipiscing elit. Aenean
+				semper sagittis velit. Cras in mi. Duis porta mauris ut ligula.
+				Proin porta rutrum lacus. <a href="#">Etiam</a> consequat scelerisque quam. Nulla
+				facilisi.  Maecenas luctus venenatis nulla. In sit amet dui non mi
+				semper iaculis.  Sed molestie tortor at ipsum. 
+				</p>
+				
+				<h3>another list: (no target, or ilk)</h3>
+				<div style="height:125px; position:relative;">
+					<div style="position:absolute; width:600px;">
+						<ul id="inlineList">
+							<li class="bounce">Foo</li>
+							<li class="bounce">Bar</li>
+							<li class="bounce">Baz</li>
+							<li class="bounce">Bam</li>
+						</ul>	
+					</div>
+				</div>
+				
+				<h3>oh right, Images:</h3>
+				
+				<div style="position:relative; height:60px;"><div style="position:absolute">
+					<img src="images/fisheye_1.png" class="imgBounce" onClick="alert('clicked img 1')"/>
+					<img src="images/fisheye_2.png" class="imgBounce" onClick="alert('clicked img 2')"/>
+					<img src="images/fisheye_3.png" class="imgBounce" onClick="alert('clicked img 3')"/>
+					<img src="images/fisheye_4.png" class="imgBounce" />
+					<img src="images/fisheye_3.png" class="imgBounce" onClick="alert('clicked img 3')"/>
+					<img src="images/fisheye_2.png" class="imgBounce" onClick="alert('clicked img 2')"/>
+					<img src="images/fisheye_1.png" class="imgBounce" onClick="alert('clicked img 1')"/>
+				</div></div>
+				
+				<div style="position:relative; float:left; width:1px; left:-75px; top:0;">
+					<img src="images/fisheye_1.png" class="imgBounce" onClick="alert('clicked img 1')"/><br>
+					<img src="images/fisheye_2.png" class="imgBounce" onClick="alert('clicked img 2')"/><br>
+					<img src="images/fisheye_3.png" class="imgBounce" onClick="alert('clicked img 3')"/><br>
+					<img src="images/fisheye_4.png" class="imgBounce" /><br>
+					<img src="images/fisheye_3.png" class="imgBounce" onClick="alert('clicked img 3')"/><br>
+					<img src="images/fisheye_2.png" class="imgBounce" onClick="alert('clicked img 2')"/><br>
+					<img src="images/fisheye_1.png" class="imgBounce" onClick="alert('clicked img 1')"/>
+				</div>
+				
+				<p dojoType="dojox.widget.FisheyeLite"
+				   properties="{ padding:1.55 }"
+				   style="padding:12px; text-align:justify;">
+					
+				Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+				imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer
+				lorem nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean
+				id mi in massa bibendum suscipit. Integer eros. Nullam suscipit
+				mauris. In pellentesque. Mauris ipsum est, pharetra semper,
+				pharetra in, viverra quis, tellus. Etiam purus. Quisque egestas,
+				tortor ac cursus lacinia, felis leo adipiscing nisi, et rhoncus
+				elit dolor eget eros. Fusce ut quam. Suspendisse eleifend leo vitae
+				ligula. Nulla facilisi. Nulla rutrum, erat vitae lacinia dictum,
+				pede purus imperdiet lacus, ut semper velit ante id metus. Praesent
+				massa dolor, porttitor sed, pulvinar in, consequat ut, leo. Nullam
+				nec est. Aenean id risus blandit tortor pharetra congue.
+				Suspendisse pulvinar.
+				</p>
+				
+				<p class="advancedProps" style="height:25px; background:#000">Lorem</p>
+				<p class="advancedPropsToo" dojoType="dojox.widget.FisheyeLite"
+					style="height:25px; background:#000"
+					properties="{ height:{ end: 150 } }"
+					easeIn="dojo._defaultEasing"
+					easeOut="dojo._defaultEasing"
+					durationOut="175"
+				>Lorem</p>
+				
+				<p>the end</p>
+				
+				<p>Aliquam vitae enim. Duis scelerisque metus auctor est venenatis
+				imperdiet. Fusce dignissim porta augue. Nulla vestibulum. Integer
+				lorem nunc, ullamcorper a, commodo ac, malesuada sed, dolor. Aenean
+				id mi in massa bibendum suscipit. Integer eros. Nullam suscipit
+				mauris. In pellentesque. Mauris ipsum est, pharetra semper,
+				pharetra in, viverra quis, tellus. Etiam purus. Quisque egestas,
+				tortor ac cursus lacinia, felis leo adipiscing nisi, et rhoncus
+				elit dolor eget eros. Fusce ut quam. Suspendisse eleifend leo vitae
+				ligula. Nulla facilisi. Nulla rutrum, erat vitae lacinia dictum,
+				pede purus imperdiet lacus, ut semper velit ante id metus. Praesent
+				massa dolor, porttitor sed, pulvinar in, consequat ut, leo. Nullam
+				nec est. Aenean id risus blandit tortor pharetra congue.
+				Suspendisse pulvinar.
+				</p>
+				
+				
+		</div>	
+    </body>
+</html>
diff --git a/dojox/widget/tests/test_Iterator.html b/dojox/widget/tests/test_Iterator.html
new file mode 100644
index 0000000..c14b9a2
--- /dev/null
+++ b/dojox/widget/tests/test_Iterator.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox Iterator Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.SplitContainer");
+		dojo.require("dojo.data.ItemFileReadStore"); 
+		dojo.require("dojox.widget.Iterator"); 
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+	
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">Dojox Iterator test</h1>
+
+	<div dojoType="dojo.data.ItemFileReadStore" 
+		url="../../../dijit/tests/_data/countries.json" 
+		jsId="stateStore"></div>
+	
+	<h3>Data store backed Iterator</h3>
+	<ul>
+		<li>before</li>
+		<li dojoType="dojox.widget.Iterator" 
+			query="{ name: 'A*' }"
+			store="stateStore">
+			${name}
+		</li>
+		<li>after</li>
+	</ul>
+
+	<h3>Array backed Iterator</h3>
+	<ul>
+		<li>before</li>
+		<script>
+			var tdata = [
+				{ thinger: "blah", name: "named:" },
+				{ thinger: "..." },
+				{ thinger: "w00t!" }
+			];
+		</script>
+		<li dojoType="dojox.widget.Iterator" 
+			defaultValue="*this space intentionally left blank*"
+			data="tdata">
+			${name} ${thinger}
+		</li>
+		<li>after</li>
+	</ul>
+
+	<h3>Array-property Iterator</h3>
+	<ul>
+		<li>before</li>
+		<li>blah</li>
+		<li dojoType="dojox.widget.Iterator" 
+			dataValues="thinger, blah, blah">
+			${value}
+		</li>
+		<li>after</li>
+	</ul>
+
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Loader.html b/dojox/widget/tests/test_Loader.html
new file mode 100644
index 0000000..637bef5
--- /dev/null
+++ b/dojox/widget/tests/test_Loader.html
@@ -0,0 +1,81 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo Visual Loader Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		@import "../Loader/Loader.css"; 
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript" src="../Loader.js"></script>
+	<script type="text/javascript">
+		// dojo.require("dojox.widget.Loader"); 
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		function getHoney(){
+			// simple xhrGet example
+			var foo = dojo.xhrGet({
+				url: 'honey.php?delay=0',
+				handleAs: 'text',
+				load: function(result){
+					content.innerHTML = result; 
+				}
+			});
+		}
+
+		function postHoney(){
+			// simple xhrPost example
+			var foo = dojo.xhrPost({
+				url: 'honey.php?delay=0',
+				handleAs: 'text',
+				load: function(result){
+					content.innerHTML = result; 
+				}
+			});
+		}
+
+		function alertMe(){ 
+			console.log('subscription fired',arguments); 
+		}
+
+		var content = null; 
+		dojo.addOnLoad(function(){
+
+			content = dojo.byId("dataholder"); 
+			// FIXME: why aren't you working?
+			// var foo = dojo.subscribe("Loader",null,"alertMe");
+			// console.log(foo); 
+
+		});
+	</script>
+</head>
+<body class="tundra">
+	<div id="globalLoader" dojoType="dojox.widget.Loader"></div>
+
+	<!-- Other examples: 
+	<div id="globalLoader" dojoType="dojox.widget.Loader" hasVisuals="false"></div>
+	<div id="globalLoader" dojoType="dojox.widget.Loader" hasVisuals="true" attachToPointer="false"></div>
+	-->
+
+	<h1 class="testTitle">Dojox xhrListener test</h1>
+
+	<a href="javascript:getHoney();">start xhrGet demo</a>
+	<a href="javascript:postHoney();">start xhrPost demo</a>
+
+	<p>No additional code is required except for the existance of a 
+	dojoType="dojox.widget.Loader" node. It will listen for the start
+	and end of xhr* requests (via _ioSetArgs [ugh] and Deferred.prototype._fire .. 
+	</p>
+
+	<br>
+	<div id="dataholder" style="float:left; height:300px; overflow:auto; width:400px; border:1px solid #ccc; "></div>
+	<!-- make me a scrollbar. a Taaaaaall scrollbar  -->
+	<div style="float:left; height:2000px; width:1px; overflow:hidden">spacer</div>
+
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Pager.html b/dojox/widget/tests/test_Pager.html
new file mode 100644
index 0000000..96740c7
--- /dev/null
+++ b/dojox/widget/tests/test_Pager.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+	<title>Testing the DataPager</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../Pager/Pager.css";
+	</style>
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" djconfig="parseOnLoad:true, isDebug: true"></script>
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<script type="text/javascript" src="../Pager.js"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dojox.widget.Pager");
+	</script>
+	
+	<style type="text/css">
+		body {
+			font-family: Arial;
+		}
+		
+		ol li, ul li {
+			font-size:1em;
+			line-height:1.5em;
+			margin:0pt;
+		}
+		#result {
+			font-size: 12px;
+			margin-bottom: 15px;
+		}
+	</style>
+</head>
+<body class="tundra">
+	
+	<h1 class="testTitle">dojox.widget.Pager</h1>
+
+	<div style="clear: both" id="result">Click on one of the menu items</div>
+
+	<!-- the datastore -->
+	<div dojoType="dojo.data.ItemFileReadStore" jsId="pagerStore" id="pagerStore" url="_pager-data.json"></div>
+
+	<h2>Horizontal</h2>
+
+	<div style="padding:8px">
+		<div dojoType="dojox.widget.Pager" id="dojoxMenu1" 
+			store="pagerStore" style="width: 410px; height: 150px"></div>
+	</div>
+	<div style="padding:8px">
+		<div dojoType="dojox.widget.Pager" id="dojoxMenu2" itemsPage="4" 
+			store="pagerStore" statusPos="trailing" style="width: 410px; height: 150px"></div>
+	</div>
+	<div style="padding:8px">
+		<div dojoType="dojox.widget.Pager" id="dojoxMenu1s" store="pagerStore" pagerPos="none" 
+			style="width: 410px; height: 150px"></div>
+		</div>
+	<div style="padding:8px">
+		<div dojoType="dojox.widget.Pager" id="dojoxMenu2s" itemsPage="4" pagerPos="none" 
+			store="pagerStore" statusPos="trailing" style="width: 410px; height: 150px"></div>
+	</div>
+	
+	<h2>Vertical</h2>
+	
+	<div style="padding:8px; float:left;">
+		<div dojoType="dojox.widget.Pager" id="dojoxMenu3" itemsPage="2" orientation="vertical" 
+			store="pagerStore" style="width: 150px; height: 400px"></div>
+	</div>
+	<div style="padding:8px; float:left;">
+		<div dojoType="dojox.widget.Pager" id="dojoxMenu4" itemsPage="5" orientation="vertical" 
+			statusPos="trailing" store="pagerStore" style="width: 150px; height: 600px"></div>
+	</div>
+	<div style="padding:8px;float:left;">
+		<div dojoType="dojox.widget.Pager" id="dojoxMenus3" itemsPage="2" pagerPos="none" 
+			orientation="vertical" store="pagerStore" style="width: 150px; height: 400px"></div>
+	</div>
+	<div style="padding:8px; float:left;">
+		<div dojoType="dojox.widget.Pager" id="dojoxMenus4" itemsPage="5" pagerPos="none" 
+			orientation="vertical" statusPos="trailing" store="pagerStore" style="width: 150px; height: 600px"></div>
+	</div>
+
+	<div style="clear: both" id="result2">That's all folks.</div>
+
+</body>
+</html>
diff --git a/dojox/widget/tests/test_PlaceholderMenuItem.html b/dojox/widget/tests/test_PlaceholderMenuItem.html
new file mode 100644
index 0000000..d9dbbcd
--- /dev/null
+++ b/dojox/widget/tests/test_PlaceholderMenuItem.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>PlaceholderMenuItem Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+	
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("doh.runner");
+		dojo.require("dojox.widget.PlaceholderMenuItem");
+		dojo.require("dijit.ColorPalette");
+		dojo.require("dijit.Calendar");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+    
+    <script language="Javascript" type="text/javascript">
+		dojo.addOnLoad(function(){
+			doh.register("tests",
+				[
+					function test_getPlaceholder(t){
+						var m = dijit.byId("submenu1");
+						t.is(3, m.getPlaceholders().length);
+						t.is(2, m.getPlaceholders("PHCopyPaste").length);
+						t.is(1, m.getPlaceholders("PH2").length);
+						t.is(0, m.getPlaceholders("None").length);
+					},
+					function test_replace(t){
+						var m = dijit.byId("submenu1"), m3 = dijit.byId("submenu3");
+						t.is(6, m.getChildren().length); // Placeholder counts as one
+						t.is(1, m3.getChildren().length); // Placeholder counts as one
+						dojo.forEach(m.getPlaceholders("PHCopyPaste"), function(ph){
+							ph.replace([
+								new dijit.MenuItem({iconClass: "dijitEditorIcon dijitEditorIconCut",
+													onClick: function(){alert('not actually cutting')},
+													label: "Cut"}),
+								new dijit.MenuItem({iconClass: "dijitEditorIcon dijitEditorIconCopy",
+													onClick: function(){alert('not actually copying')},
+													label: "Copy"}),
+								new dijit.MenuItem({iconClass: "dijitEditorIcon dijitEditorIconPaste",
+													onClick: function(){alert('not actually pasting')},
+													label: "Paste"})
+							]);
+						});
+						t.is(9, m.getChildren().length); // Placeholder is still there
+						t.is(4, m3.getChildren().length); // Placeholder is still there
+					},
+					function test_unReplace(t){
+						var m = dijit.byId("submenu1"), m2 = dijit.byId("submenu2");
+						t.is(3, m2.getChildren().length); // Placeholder counts as one
+						var ph = m.getPlaceholders("PH2")[0];
+						t.f(ph._replaced);
+						ph.replace([
+							new dijit.MenuItem({label: "Added 1"}),
+							new dijit.MenuItem({label: "Added 2"})
+						]);
+						t.t(ph._replaced);
+						t.is(5, m2.getChildren().length); // Placeholder is still there
+						t.is(2, ph.unReplace(true).length);
+						t.f(ph._replaced);
+						t.is(3, m2.getChildren().length);
+						ph = m.getPlaceholders("PH2")[0];
+						ph.replace([
+							new dijit.MenuItem({label: "Added Submenu Item"})
+						]);
+						t.t(ph._replaced);
+						t.is(4, m2.getChildren().length);
+					}
+				]
+			);
+			doh.run();
+		});
+    </script>
+</head>
+<body class="tundra">
+
+	<div dojoType="dijit.Menu" id="submenu1" contextMenuForWindow="true" style="display: none;">
+		<div dojoType="dijit.MenuItem">First Item</div>
+		<div dojoType="dijit.MenuItem" disabled="true">Disabled Item</div>
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dojox.widget.PlaceholderMenuItem">PHCopyPaste</div>
+<!--
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut"
+			onClick="alert('not actually cutting anything, just a test!')">Cut</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy"
+			onClick="alert('not actually copying anything, just a test!')">Copy</div>
+		<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste"
+			onClick="alert('not actually pasting anything, just a test!')">Paste</div>
+-->
+		<div dojoType="dijit.MenuSeparator"></div>
+		<div dojoType="dijit.PopupMenuItem">
+			<span>Enabled Submenu</span>
+			<div dojoType="dijit.Menu" id="submenu2">
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</div>
+				<div dojoType="dojox.widget.PlaceholderMenuItem">PH2</div>
+<!--
+				<div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</div>
+-->
+				<div dojoType="dijit.PopupMenuItem">
+					<span>Deeper Submenu</span>
+					<div dojoType="dijit.Menu" id="submenu3"">
+						<div dojoType="dojox.widget.PlaceholderMenuItem">PHCopyPaste</div>
+					</div>
+				</div>
+			</div>
+		</div>
+	</div>
+
+	<div style="padding: 1em">
+		
+		<h1 class="testTitle">PlaceholderMenuItem Test</h1>
+		left click to open the menu
+		
+	</div>
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Portlet.html b/dojox/widget/tests/test_Portlet.html
new file mode 100644
index 0000000..0eb909e
--- /dev/null
+++ b/dojox/widget/tests/test_Portlet.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>DojoX Portlet example</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../Dialog/Dialog.css">
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		
+		@import "../Portlet/Portlet.css";
+
+	</style>		
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dojox.widget.Portlet");
+		dojo.require("dijit.form.CheckBox");
+	</script>
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">dojox.widget.Portlet tests</h1>
+	
+	<p>This is a Portlet widget, which is similar to a dijit.TitlePane, but is designed
+	   to be used with the dojox.layout.GridContainer widget.  Each widget can be extended
+		 with a number of different plug in widgets, with each plug in specifying
+		 an icon to display in the title bar.
+	</p>
+	<p>
+		Two settings widgets are currently defined, <b>dojox.widget.PortletSettings</b>
+		and <b>dojox.widget.PortletDialogSettings</b>
+	</p>
+
+	<div id='testholder' class="tests" style="width: 400px;">
+		<div dojoType="dojox.widget.Portlet" title="Test Title 1" id="portlet1">
+			<div dojoType="dojox.widget.PortletSettings">
+				Use Bold Text: <div dojoType="dijit.form.CheckBox">
+					<script type="dojo/connect" event="onClick">
+						var portlet = dijit.byId("portlet1");
+					  dojo.style(portlet.containerNode, "fontWeight", this.checked ? "bold" : "normal");
+					</script>
+				</div>
+			</div>
+			<div>
+				Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
+			  Nam facilisis enim. Pellentesque in elit et lacus euismod dignissim.
+			  Aliquam dolor pede, convallis eget, dictum a, blandit ac, urna. 
+			  Pellentesque sed nunc ut justo volutpat egestas. Class aptent taciti
+			  sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. 
+				In erat. Suspendisse potenti. Fusce faucibus nibh sed nisi. Phasellus 
+				faucibus, dui a cursus dapibus, mauris nulla euismod velit, a lobortis turpis 
+				arcu vel dui. Pellentesque fermentum ultrices pede. Donec auctor lectus eu arcu. 
+				Curabitur non orci eget est porta gravida. Aliquam pretium orci id nisi. Duis faucibus,
+				mi non adipiscing venenatis, erat urna aliquet elit, eu fringilla lacus tellus quis erat. 
+				Nam tempus ornare lorem. Nullam feugiat.
+			</div>
+		</div>
+		
+		<div dojoType="dojox.widget.Portlet" title="Portlet with Dialog Settings" id="portlet2">
+			<div dojoType="dojox.widget.PortletDialogSettings" title="Settings in a Dialog">
+				Use Bold Text: <div dojoType="dijit.form.CheckBox">
+					<script type="dojo/connect" event="onClick">
+					  dojo.style(dijit.byId('portlet2').containerNode, "fontWeight", this.checked ? "bold" : "normal");
+					</script>
+				</div>
+			</div>
+			<div>
+				Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
+			  Nam facilisis enim. Pellentesque in elit et lacus euismod dignissim.
+			  Aliquam dolor pede, convallis eget, dictum a, blandit ac, urna. 
+			  Pellentesque sed nunc ut justo volutpat egestas. Class aptent taciti
+			  sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. 
+				In erat. Suspendisse potenti. Fusce faucibus nibh sed nisi. Phasellus 
+				faucibus, dui a cursus dapibus, mauris nulla euismod velit, a lobortis turpis 
+				arcu vel dui. Pellentesque fermentum ultrices pede. Donec auctor lectus eu arcu. 
+				Curabitur non orci eget est porta gravida. Aliquam pretium orci id nisi. Duis faucibus,
+				mi non adipiscing venenatis, erat urna aliquet elit, eu fringilla lacus tellus quis erat. 
+				Nam tempus ornare lorem. Nullam feugiat.
+			</div>
+		</div>		
+	</div>
+</body>
+</html>
+
diff --git a/dojox/widget/tests/test_PortletInGridContainer.html b/dojox/widget/tests/test_PortletInGridContainer.html
new file mode 100644
index 0000000..26edcfd
--- /dev/null
+++ b/dojox/widget/tests/test_PortletInGridContainer.html
@@ -0,0 +1,657 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>DojoX Portlet In a GridContainer example</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/soria/soria.css">
+	<link rel="stylesheet" href="../Dialog/Dialog.css">
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		
+		@import "../Portlet/Portlet.css";
+		@import "../../layout/resources/GridContainer.css";
+		@import "../Calendar/Calendar.css";
+		@import "../../grid/resources/Grid.css";
+		@import "../../grid/resources/tundraGrid.css";
+		@import "../../grid/resources/soriaGrid.css";
+		@import "../../grid/resources/nihiloGrid.css";
+		@import "../../image/resources/image.css";
+		@import "../../layout/resources/ExpandoPane.css";
+		
+		.dijitTabContainer  .gridContainerTable {
+			border: 0px none;
+		}
+		.dijitTabContainer .gridContainer {
+			padding: 2px;
+		}
+		
+		#masker {
+			position: absolute;
+			width: 100%;
+			height: 100%;
+			left: 0;
+			top: 0;
+			background: white;
+			z-index: 1000;
+		}
+		
+		#clients .dijitTitlePaneContentInner,
+		#quotes  .dijitTitlePaneContentInner {
+			padding: 0;
+		}
+		body , html{
+			padding: 0px;
+			height: 100%;
+			width: 100%;
+		}
+		.calendarStack span {
+			font-weight: bold;
+		}
+		.calendarStack div {
+			padding-bottom: 5px;
+		}
+		.gridContainer {overflow-y: auto;}
+		
+		.dijitTooltip {
+			max-width: 400px;
+		}
+		.labelTable td {
+			padding: 4px;
+			border: 0;
+		}
+		.labelTable .tableContainer-labelCell {
+			background-color: #CCC;
+		}
+		.portletNoBorder div.dijitTitlePaneContentInner {
+			padding: 0;
+		}
+		.dj_ie6 .dropIndicator, .dj_ie6 .dojoxPortlet{
+			margin: 5px;
+		}
+		.gridContainerZone > *{
+			margin: 5px !important;
+		}
+	</style>		
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: false"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	
+	<script type="text/javascript" src="test_PortletInGridContainer.js"></script>
+	<script type="text/javascript" src="../FeedPortlet.js"></script>
+	<script type="text/javascript" src="CalendarStackLayout.js"></script>
+</head>
+<body class="soria">
+	<div id="masker"></div>
+
+	<span dojoType="dojox.data.HtmlStore" 
+		jsId="htmlStore" dataId="gridDataTable">
+	</span>
+	
+	<div dojoType="dojox.data.FileStore" url="../../data/demos/stores/filestore_dojotree.php" 
+					jsId="fileStore" pathAsQueryParam="true"></div>
+	
+	<div dojoType="dijit.tree.ForestStoreModel" jsId="fileModel" 
+		store="fileStore" query="{}"
+		rootId="DojoFiles" rootLabel="Dojo Files" childrenAttrs="children">
+		<script type="dojo/method" event="getChildren" args="parent, callback">
+			if (!this._allItems) {
+			  this._allItems = [];
+			}
+			dijit.tree.ForestStoreModel.prototype.getChildren.apply(this, [parent, dojo.hitch(this, function(items){
+			  this._allItems = this._allItems.concat(items);
+				console.log("getChildren of " + parent.name);
+			  dojo.publish("/fileChange", [this._allItems]);
+			  callback(items);
+			})]);
+		</script>
+		
+	</div>
+
+	<div dojoType="dijit.Menu" id="gridCols" jsId="gridCols" style="display: none">
+		<div dojoType="dojox.widget.PlaceholderMenuItem" label="GridColumns"></div>
+	</div>
+
+	<div dojoType="dijit.layout.TabContainer" region="center" style="height:100%;">
+		
+		<div dojoType="dijit.layout.BorderContainer" 
+				id="mainLayout"
+				title="Home"
+				style="width: 100%; height: 100%; padding: 2px;">
+	
+			<div dojoType="dojox.layout.GridContainer"
+					id="gridContainer"
+					region="center"
+					acceptTypes="Portlet"
+					hasResizableColumns="false"
+					nbZones="2"
+					dragHandleClass="dijitTitlePaneTitle">
+				<div dojoType="dojox.widget.Portlet" title="Info" toggleable="false" dragRestriction="true">
+					<p onclick="text_explode_2(this)">This is a Portlet widget, which is similar to a dijit.TitlePane, 
+						but is designed to be used with the dojox.layout.GridContainer widget.  Each widget can be extended
+						 with a number of different plug in widgets, with each plug in specifying
+						 an icon to display in the title bar. (<i>By the way, click this paragraph somewhere</i> :-) 
+					</p>
+					<p>
+						Two settings widgets are currently defined, <b>dojox.widget.PortletSettings</b>
+						and <b>dojox.widget.PortletDialogSettings</b>
+					</p>
+					<p>This Portlet is not draggable, but all others are.</p>
+				</div>
+	
+				<div dojoType="dojox.widget.FeedPortlet" title="Todays News" 
+					id="todaysNews"
+					url="http://news.google.com/news?hl=en&topic=t&output=atom"
+					maxResults="5"
+					dndType="Portlet"
+					>
+					<div dojoType="dojox.widget.PortletFeedSettings"></div>
+					
+					<div>
+					This is a FeedPortlet with a single feed.
+					Click the settings icon in the title bar to enter a
+					different feed to load.  Hovering over a news item shows a summary
+					of it in a tooltip.
+					</div>
+				</div>
+	
+				<div dojoType="dojox.widget.Portlet" title="Clients"  id="clients"
+					class="gridPortlet"
+					dndType="Portlet">
+					
+					<div id="staticGrid" 
+						dojoType="dojox.grid.DataGrid" 
+						rowsPerPage="10"
+						columnReordering="false"
+						store="htmlStore" 
+						structure="layoutHtmlTable", 
+						query="{}"
+						headerMenu="gridCols" 
+						columnToggling="true" 
+						title="Simple Grid"
+						autoHeight="true"
+						>
+						<script type="dojo/connect">
+							setTimeout(dojo.hitch(this, "resize"), 100);
+						</script>
+						
+					</div>
+	
+				</div>
+	
+				<div dojoType="dojox.widget.Portlet" title="Line Chart" id="lineChartPortlet" dndType="Portlet">
+					<div dojoType="dojox.widget.PortletDialogSettings" 
+							id="lineChartSettings" dimensions="[300, 117]" title="Line Chart Settings">
+						<div dojoType="dojox.layout.TableContainer" cols="1">
+						  <div dojoType="dijit.form.TextBox" title="Option 3"></div>
+							<div dojoType="dijit.form.TextBox" title="Option 4"></div>
+						</div>
+						<div style="text-align: center;">
+						  <div dojoType="dijit.form.Button" onClick="dijit.byId('lineChartSettings').toggle();">OK</div>
+						</div>
+					</div>
+					<script type="dojo/connect" event="onUpdateSize">
+						if(window.chart){chart.resize();}
+					</script>
+					<div>
+						Change the zoom of the chart using the slider, then drag it using the mouse.  This portlet uses
+						a dialog settings widget, click the settings icon in the title bar to see it.
+					</div>
+					<div id="zoomer" style="height:200px; width: 400px;"></div>
+					<div style="margin-bottom:5px;">Scale:</div>
+					<div id="scaleXSlider" dojoType="dijit.form.HorizontalSlider" 
+							value="1" minimum="1" maximum="10" discreteValues="10" showButtons="false">
+						<div dojoType="dijit.form.HorizontalRule" container="bottomDecoration" count="10" style="height:5px;"></div>
+						<div dojoType="dijit.form.HorizontalRuleLabels" container="bottomDecoration" minimum="1" maximum="10" count="10"
+							constraints="{pattern: '##'}" style="height:1.2em;font-size:75%;color:gray;"></div>
+					</div>
+					
+				</div>
+				
+			</div>
+				
+			<div dojoType="dojox.layout.ExpandoPane" region="right" 
+					title="Calendar"
+					style="height: 100%;">
+
+				<div dojoType="dojox.widget.tests.CalendarStackLayout">
+					<div dojoType="dijit.layout.ContentPane" dateref="2009-06-20">
+						<div>
+							<span>
+								Type:
+							</span>
+							Meeting
+						</div>
+						<div>
+							<span>
+								Time:
+							</span>
+							12:00 - 13:00
+						</div>
+						<div>
+							<span>
+								Details:
+							</span>
+						</div>
+						<div>
+							Meeting about the User Interface
+						</div>
+					</div>
+					<div dojoType="dijit.layout.ContentPane" dateref="2009-06-22">
+						<div>
+							<span>
+								Type:
+							</span>
+							Meeting
+						</div>
+						<div>
+							<span>
+								Time:
+							</span>
+							09:00 - 10:30
+						</div>
+						<div>
+							<span>
+								Details:
+							</span>
+						</div>
+						<div>
+							Morning prayer for the end of life of IE6
+						</div>
+					</div>
+					<div dojoType="dijit.layout.ContentPane" dateref="2009-06-24">
+						<div>
+							<span>
+								Type:
+							</span>
+							Appointment
+						</div>
+						<div>
+							<span>
+								Time:
+							</span>
+							19:00 - 20:30
+						</div>
+						<div>
+							<span>
+								Details:
+							</span>
+						</div>
+						<div>
+							Root canal at dentist.  Gonna get a candy bar!
+						</div>
+					</div>
+				</div>
+
+			</div>
+		</div>
+			
+		<div dojoType="dijit.layout.BorderContainer" title="My Interests">
+			<div dojoType="dojox.layout.GridContainer"
+				id="gridContainer2"
+				acceptTypes="Portlet"
+				hasResizableColumns="false"
+				nbZones="2"
+				dragHandleClass="dijitTitlePaneTitle"
+				region="center"
+			>
+				<div dojoType="dojox.widget.ExpandableFeedPortlet" dndType="Portlet" title="Cool Blogs -> Remembering Your Selection" showFeedTitle="false">
+					<select dojoType="dojox.widget.PortletFeedSettings" id="coolBlogsSettings">
+						<script type="dojo/connect">
+							this.set("selectedIndex", dojo.cookie(this.id + "-selectedIndex") || 0);
+						</script>
+						<script type="dojo/connect" event="attr" args="name, value">
+							if(name == "selectedIndex"){
+								dojo.cookie(this.id + "-selectedIndex", value);
+
+								// Set a custom title when selection changes.
+								if (this.portlet){
+									this.portlet.attr("title", "Cool Blogs - " + this.text.options[value].innerHTML);
+								}
+							}
+						</script>
+						<option value="http://shaneosullivan.wordpress.com/category/dojo/feed/">Dojo Blatherings</option>
+						<option value="http://www.dojotoolkit.org/aggregator/rss">Planet Dojo</option>
+						<option value="http://feeds2.feedburner.com/ajaxian">Ajaxian</option>
+					</select>
+					<div>
+					This is an ExpandableFeedPortlet with multiple available feeds. 
+					Click the settings icon in the title bar to choose a feed to load.
+					This Portlet also maintains its state using a cookie, so when you choose
+					a feed to show and refresh the page, that same feed will be selected.
+					this example also shows how to modify the title of the portlet when a new
+					feed is selected.
+					When a feed is loaded, it automatically sets the title of the Portlet to the 
+					title of the feed.  This portlet has disabled that behavior using
+					showFeedTitle="false"
+					</div>
+				</div>
+				<div dndType="Portlet" dojoType="dojox.widget.ExpandableFeedPortlet"  title="Cool Blogs -> onlyOpenOne == true" 
+						onlyOpenOne="true" >
+					<select dojoType="dojox.widget.PortletFeedSettings" id="multiOptions">
+						<option value="http://www.dojotoolkit.org/aggregator/rss/">Planet Dojo</option>
+						<option value="http://shaneosullivan.wordpress.com/category/dojo/feed/">Dojo Blatherings</option>
+						<option value="http://feeds2.feedburner.com/ajaxian">Ajaxian</option>
+					</select>
+					<div>
+					This is an ExpandableFeedPortlet with multiple available feeds, in which you
+					can only expand a single item at a time. 
+					Click the settings icon in the title bar to choose a feed to load.
+					</div>
+				</div>
+				<div dojoType="dojox.widget.Portlet" dndType="Portlet" title="Quotes of the Day" id="quotes">
+					<div dojoType="dojox.widget.PortletSettings">
+						<div dojoType="dojox.layout.TableContainer" cols="1">
+						  <div dojoType="dijit.form.TextBox" title="Option 3"></div>
+							<div dojoType="dijit.form.TextBox" title="Option 4"></div>
+						</div>
+					</div>
+					<script type="dojo/connect">
+						loadFeed("http://feeds2.feedburner.com/quotationspage/qotd", "quotes");
+					</script>
+					<div id="quotes">
+						
+					</div>
+				</div>
+				
+				<div dojoType="dojox.widget.FeedPortlet" dndType="Portlet" title="Dojo Campus - Local Feed" 
+						url="testAtom.xml"
+						maxResults="5"
+						local="true"
+						>
+					<div>
+					This is a FeedPortlet with a local feed, which is useful
+					if you have a feed that is not public, perhaps on an
+					intranet.
+					</div>
+				</div>
+				
+				<div dojoType="dojox.widget.Portlet" dndType="Portlet" title="My Flickr">
+					<div dojoType="dojox.widget.PortletSettings">
+						<div dojoType="dojox.layout.TableContainer" cols="1">
+						  <div dojoType="dijit.form.TextBox" title="Option 3"></div>
+							<div dojoType="dijit.form.TextBox" title="Option 4"></div>
+						</div>
+					</div>
+					
+					<div dojoType="dojox.image.SlideShow" imageWidth="300" imageHeight="300">
+						<script type="dojo/connect">
+							
+							var flickrRestStore = new dojox.data.FlickrRestStore();
+							var req = {
+								query: {
+									userid: "44153025 at N00",
+									apikey: "8c6803164dbc395fb7131c9d54843627",
+									setid: "72057594114596784",
+									sort: [
+										   {
+											attribute: "interestingness",
+											descending: true
+											}
+										   ],
+									tag_mode: "any"
+								},
+								count: 20
+							};
+							this.setDataStore(flickrRestStore, req);
+						</script>
+					</div>
+				</div>
+
+			</div>
+		</div>
+
+		<div dojoType="dijit.layout.BorderContainer" title="My Files">
+			<div dojoType="dojox.layout.ExpandoPane" region="left" title="File Explorer" style="width: 230px;">
+				<div 
+					id="tree" 
+					dojoType="dijit.Tree" 
+					model="fileModel" 
+					persist="false"
+					style="overflow-y: auto;height: 100%;max-width: 230px;">
+					<script type="dojo/method" event="onClick" args="item">
+						if (fileStore.isItem(item)){
+							dojo.publish("/fileinfo", [fileStore, item]);
+						}
+					</script>
+				</div>
+			</div>
+				
+				<div dojoType="dojox.layout.GridContainer"
+						region="center"
+						acceptTypes="Portlet"
+						hasResizableColumns="false"
+						nbZones="2"
+						dragHandleClass="dijitTitlePaneTitle"
+					>
+						<div dojoType="dojox.widget.Portlet" dndType="Portlet" title="File Info" class="portletNoBorder">
+							<script type="dojo/connect">
+								var mapping = {
+									"fileName" : "name", 
+									"filePath": "path", 
+									"fileSize": "size", 
+									"fileModified": "modified", 
+									"fileParent":"parentDir",
+									"fileIsDir": "directory"
+								};
+								
+								dojo.subscribe("/fileinfo", function(store, item) {
+								  for (var dijitId in mapping) {
+										var attrib = mapping[dijitId];
+									  var val = store.getValue(item, attrib);
+									  if (attrib == "size") {
+										  val += " bytes";
+										} else if (attrib == "modified") {
+										  val = dojo.date.locale.format(new Date(Number(val)), {formatLength: "medium"});
+										} else if (attrib == "directory") {
+										  val = val ? "Yes" : "No";
+										}
+									
+									  dijit.byId(dijitId).attr("content", val);
+									}
+								});
+							</script>
+							<div dojoType="dojox.layout.TableContainer" class="labelTable" spacing="0">
+								<div dojoType="dijit.layout.ContentPane" label="Name:" id="fileName"></div>
+								<div dojoType="dijit.layout.ContentPane" label="Path:" id="filePath"></div>
+								<div dojoType="dijit.layout.ContentPane" label="Size:" id="fileSize"></div>
+								<div dojoType="dijit.layout.ContentPane" label="Modified:" id="fileModified"></div>
+								<div dojoType="dijit.layout.ContentPane" label="Parent Directory:" id="fileParent"></div>
+								<div dojoType="dijit.layout.ContentPane" label="Is Directory?:" id="fileIsDir"></div>
+							</div>
+						</div>
+					
+						<div dojoType="dojox.widget.Portlet" dndType="Portlet" title="File Contents" 
+							id="fileContentPortlet"
+								style="max-height: 350px;">
+							<script type="dojo/connect" event="startup">
+								var widget = dijit.byId("fileContents");
+								dojo.style(this.containerNode, {
+								  height: "310px",
+									paddingTop: 0,
+									paddingBottom: 0,
+									paddingRight: 0
+								});
+								dojo.subscribe("/fileinfo", function(store, item) {
+								  var path = dojo.config.baseUrl + "../" + store.getValue(item, "path");
+									
+									if (path.indexOf(".png") > -1 || path.indexOf(".jpg") > -1 || path.indexOf(".gif") > -1) {
+									  widget.attr("content", "<img src='" +path + "'>");
+									} else if(store.getValue(item, "size") > 0 
+											&& path.indexOf(".zip") < 0
+											&& path.indexOf(".tgz") < 0){
+									  widget.attr("href", path);
+									} else {
+										widget.attr("content", "");
+									}
+								});
+							</script>
+							<div dojoType="dijit.layout.ContentPane" id="fileContents" parseOnLoad="false">
+								<script type="dojo/method" event="_setContent" args="data, isFake">
+									if (data.indexOf("<img") != 0 && data.indexOf("<span") != 0) {
+									  data = data.replace(/</gm, "<").replace(/>/gm, ">")
+													.replace(/\t/g, "  ").split("\n").join("<br>");
+									}
+									dijit.layout.ContentPane.prototype._setContent.apply(this, [data, isFake]);
+								</script>
+								File contents are loaded here.  Click on any file in the tree to see its contents.
+							</div>
+						</div>
+						
+						<div dojoType="dojox.widget.Portlet" dndType="Portlet" title="Selected Files">
+							<script type="dojo/connect">
+								console.log("connecting to fileModel", fileModel);
+								var timer;
+								
+							  dojo.subscribe("/fileChange", dojo.hitch(this, function(items){
+								  this._items = items;
+									if (this._started) {
+									  if (timer) {
+										  clearTimeout(timer);
+										}
+										timer = setTimeout(dojo.hitch(this, "updateChart"), 200);
+									}
+								}));
+									
+								</script>
+								<script type="dojo/connect" event="startup">
+									dojo.require("dojox.charting.themes.Bahamation");
+									var dc = dojox.charting;
+									
+									var container = dojo.create("div", {}, this.containerNode);
+									dojo.style(container, {"height": "300px", "width" : "300px"});
+									
+									console.log("dimensions of container are", dojo.marginBox(container));
+									
+									var chart = this.chart = new dc.Chart2D(container);	
+									chart.setTheme(dc.themes.Bahamation);
+									chart.addPlot("default", {
+										type: "Pie", 
+										font: "normal normal 11pt Tahoma", 
+										fontColor: "black", 
+										labelOffset: -30,
+										radius: 80
+									});									
+									this.updateChart();
+								</script>
+								<script type="dojo/method" event="updateChart">
+									var extensions = {};
+									var items = this._items;
+									var dc = dojox.charting;
+									
+									if (!items || items.length < 1) {
+									  return;
+									}
+									
+									function val(item, attr) {
+									  return fileStore.getValue(item, attr);
+									}
+									function getExtension(item) {
+									  if (val(item, "directory")) {
+										  return "folder";
+										}
+										var str = val(item, "name");
+										var parts = str.split(".");
+										if (parts.length < 2) {
+										  return "none";
+										}
+										return parts[1];
+									}
+									
+									dojo.forEach(items, function(item){
+									  if (val(item, "directory")) {
+										  return;
+										}
+									
+									  var count = extensions[getExtension(item)] ;
+										if (!count) {
+										  count = 0;
+										}
+										var ext = getExtension(item);
+										extensions[ext] = ++count;
+									});
+									var series = [];
+									for (var ext in extensions) {
+										series.push({
+										  y : extensions[ext],
+											text: ext,
+											stroke: "black",
+											tooltip: extensions[ext] + " " + 
+												(ext == "none" ? 
+												  "files with no extension" :
+													ext + " files")
+													+ " found" 
+										});
+									}
+									
+									
+									this.chart.addSeries("Series A", series);
+								  this.chart.resize(300, 300);	
+									
+									dojo.forEach(this._anims || [], function(anim){
+									  anim.destroy();
+									});
+									
+									this._anims = [
+									new dc.action2d.MoveSlice(this.chart, "default"),
+									new dc.action2d.Highlight(this.chart, "default"),
+									new dc.action2d.Tooltip(this.chart, "default")];
+									
+									this.chart.render();
+								</script>
+								<div>
+									This Pie chart shows the proportion of files in the Dojo toolkit.
+									As you open folders in the tree, it updates the chart.
+								</div>
+							</div>
+						
+						</div>
+			</div>
+		
+		</div>
+		
+		<table id="gridDataTable" style="display:none;">
+			<thead>
+				<tr>
+					<th >First Name</th>
+					<th >Last Name</th>
+					<th >DOB</th>
+				</tr>
+			</thead>
+			<tbody>
+				<tr >
+					<td >Davy</td>
+					<td >Jones</td>
+					<td >10/26/1974</td>
+				</tr>
+				<tr >				
+					<td >Dee</td>
+					<td >Murphy</td>
+					<td >2/25/1936</td>
+				</tr>
+				<tr >
+					<td >Dozy</td>
+					<td >Kowalski</td>
+					<td >3/17/1991</td>
+				</tr>
+				<tr >
+					<td >Mick</td>
+					<td >Mickelson</td>
+					<td >3/31/1993</td>
+				</tr>
+				<tr >
+					<td >Titch</td>
+					<td >Woods</td>
+					<td >1/29/1998</td>
+				</tr>
+			</tbody>
+		</table>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/widget/tests/test_PortletInGridContainer.js b/dojox/widget/tests/test_PortletInGridContainer.js
new file mode 100644
index 0000000..e3e4167
--- /dev/null
+++ b/dojox/widget/tests/test_PortletInGridContainer.js
@@ -0,0 +1,239 @@
+dojo.require("dijit.dijit");
+dojo.require("dojo.date.locale");
+dojo.require("dojo.cookie");
+dojo.require("dijit.form.CheckBox");
+dojo.require("dijit.form.TextBox");
+dojo.require("dijit.form.Slider");
+dojo.require("dijit.layout.TabContainer");
+dojo.require("dijit.layout.AccordionContainer");
+dojo.require("dijit.layout.BorderContainer");
+dojo.require("dijit.Tooltip");
+dojo.require("dijit.Tree");
+dojo.require("dijit.tree.ForestStoreModel");
+dojo.require("dojox.image.Gallery");
+dojo.require("dojox.widget.PlaceholderMenuItem");
+dojo.require("dojox.data.FileStore");
+dojo.require("dojox.charting.widget.Chart2D");
+dojo.require("dojox.charting.themes.Grasslands");
+dojo.require("dojox.charting.themes.PlotKit.orange");
+dojo.require("dojox.widget.Calendar");
+dojo.require("dojox.widget.Portlet");
+dojo.require("dojox.layout.GridContainer");
+dojo.require("dojox.layout.TableContainer");
+dojo.require("dojox.grid.DataGrid");
+dojo.require("dojox.data.HtmlStore");
+dojo.require("dojox.data.FlickrRestStore");
+dojo.require("dojox.fx.text");
+dojo.require("dojox.layout.ExpandoPane");
+dojo.require("dojox.charting.Chart3D");
+dojo.require("dojox.charting.action2d.Highlight");
+dojo.require("dojox.charting.action2d.MoveSlice");
+dojo.require("dojox.charting.action2d.Tooltip");
+
+//This must be included on the page for FeedPortlets that
+//load local feeds.
+dojo.require("dojox.data.AtomReadStore");
+	
+dojo.require("dojo.parser");
+
+dojo.addOnLoad(function(){
+	dojo.parser.parse();
+	var chart = window.chart = new dojox.charting.Chart2D("zoomer");
+	chart.setTheme(dojox.charting.themes.PlotKit.orange);
+	chart.addAxis("x", {fixLower: "minor", natural: true, stroke: "grey",
+		majorTick: {stroke: "black", length: 4}, minorTick: {stroke: "gray", length: 2}});
+	chart.addAxis("y", {vertical: true, min: 0, max: 30, majorTickStep: 5, minorTickStep: 1, stroke: "grey",
+		majorTick: {stroke: "black", length: 4}, minorTick: {stroke: "gray", length: 2}});
+	chart.addPlot("default", {type: "Areas"});
+	chart.addSeries("Series A", [0, 25, 5, 20, 10, 15, 5, 20, 0, 25]);
+	chart.addAxis("x2", {fixLower: "minor", natural: true, leftBottom: false, stroke: "grey",
+		majorTick: {stroke: "black", length: 4}, minorTick: {stroke: "gray", length: 2}});
+	chart.addAxis("y2", {vertical: true, min: 0, max: 20, leftBottom: false, stroke: "grey",
+		majorTick: {stroke: "black", length: 4}, minorTick: {stroke: "gray", length: 2}});
+	chart.addPlot("plot2", {type: "Areas", hAxis: "x2", vAxis: "y2"});
+	chart.addSeries("Series B", [15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15], {plot: "plot2"});
+	chart.addPlot("grid", {type: "Grid", hMinorLines: true});
+	chart.render();
+	
+	var show = setInterval(function(){
+		var w = dijit.byId("gridContainer");
+		if (w && w.domNode) {
+			dojo.body().removeChild(dojo.byId("masker"));
+			clearInterval(show);
+		}
+	}, 500);
+	
+
+	var scaleX = 1, scaleY = 1, offsetX = 0, offsetY = 0;
+	dojo.connect(dijit.byId("scaleXSlider"), "onChange", function(value){
+		scaleX = value;
+		console.log("calling update");
+		update();
+	});
+	
+	function update() {
+		chart.setWindow(scaleX, scaleY, offsetX, offsetY).render();
+	}
+	
+	var _init = null;
+	var onMouseDown = function(e){
+		_init = {x: e.clientX, y: e.clientY, ox: offsetX, oy: offsetY};
+		dojo.stopEvent(e);
+	};
+	
+	var onMouseUp = function(e){
+		if(_init){
+			_init = null;
+			dojo.stopEvent(e);
+		}
+	};
+	
+	var onMouseMove = function(e){
+		if(_init){
+			var dx = e.clientX - _init.x,
+				dy = e.clientY - _init.y;
+			offsetX = _init.ox - dx;
+			offsetY = _init.oy + dy;
+			chart.setWindow(scaleX, scaleY, offsetX, offsetY).render();
+			dojo.stopEvent(e);
+		}
+	};
+	
+	dojo.connect(chart.node, "onmousedown", onMouseDown);
+	dojo.connect(chart.node, "onmousemove", onMouseMove);
+	dojo.connect(chart.node, "onmouseup",   onMouseUp);
+	
+	
+	createProgrammaticPortlet();
+});
+
+function createProgrammaticPortlet() {
+	var portlet = new dojox.widget.FeedPortlet({
+		id: "ProgrammaticPortlet",
+		dndType: "Portlet", 
+		title: "Programmatic FeedPortlet with multiple feeds"
+	}, dojo.create("div", {
+		innerHTML: "This portlet was created programmatically, and has mulitple feeds to select from."
+				+ " Click the settings icon in the title bar to choose another feed."
+	}));
+	var settings = new dojox.widget.PortletFeedSettings({
+		id: "ProgrammaticPortletSettings",
+		urls: [
+			{
+				url: "http://news.google.com/news?hl=en&topic=t&output=atom", 
+				label: "Google News"
+			},
+			{
+				url: "http://shaneosullivan.wordpress.com/category/dojo/feed/",
+				label: "Dojo Blatherings"
+			},
+			{
+				url: "http://www.dojotoolkit.org/aggregator/rss",
+				label: "Planet Dojo"
+			}
+		]
+	});
+	portlet.addChild(settings);
+	dijit.byId("gridContainer2").addService(portlet, 0, 0);
+}
+
+var count = 0;
+function loadFeed(url, nodeId, emptyMsg, type) {
+	
+	var query = {
+		url: url
+	};
+	var request = {query:query};
+
+	var maxBufSize = 8;
+	var outNode = dojo.byId(nodeId);
+
+	var testStore = new dojox.data.GoogleFeedStore();
+
+	function doAppend(items){
+		console.log(items);
+		if (items.length > 0) {
+      if (type == "list") {
+				dojo.addClass(outNode, "feedList");
+
+	      var ul = dojo.create("ul", null, outNode);
+				dojo.forEach(items, function(item){
+					var li = dojo.create("li", {
+						innerHTML: '<a href="' + testStore.getValue(item, 'link') + '">' 
+												+ testStore.getValue(item, 'title') + '</a>'
+					},ul);
+					
+					dojo.connect(li, "onmouseover", function() {
+						dijit.showTooltip(testStore.getValue(item, "content"), li);
+					});
+					dojo.connect(li, "onmouseout", function() {
+						dijit.hideTooltip(li);
+					});
+				});
+			}
+			else {
+				var accordion = new dijit.layout.AccordionContainer({});
+				dojo.byId(nodeId).appendChild(accordion.domNode);
+				
+				dojo.forEach(items, function(item){
+					var summary = testStore.getValue(item, "title");
+					
+					if (summary.length > 40) {
+						summary = summary.substring(0, 50);
+					}
+					var contentPane = new dijit.layout.ContentPane({
+						title: summary,
+						content: testStore.getValue(item, "content")
+					});
+					dojo.style(contentPane.domNode, "width", "100%");
+					accordion.addChild(contentPane);
+					contentPane.startup();
+				});
+				
+				var portlet = dijit.getEnclosingWidget(dojo.byId(nodeId));
+				portlet.addChild(accordion);
+			}
+	  } else {
+			dojo.byId(nodeId).innerHTML = emptyMsg || "No results";
+		}
+	}
+
+	request.onBegin = function(numItems){};
+
+	request.onComplete = doAppend;
+
+	request.count = 4;
+
+	testStore.fetch(request);
+}
+
+var layoutHtmlTable = [
+	 [
+		{name: 'First Name', field: 'First Name', width: '50%'},
+		{name: 'Last Name', field: 'Last Name', width: '25%'},
+		{name: 'DOB', field: 'DOB', width: '25%'}
+		]
+	];
+			
+var text_explode_2 = function(node){
+	
+	if(node.style.height){
+		return;
+	}
+	var originalText = node.innerHTML;
+	var properties = {
+		node: node,
+		words: true,
+		distance: 1.5,
+		duration: 1500,
+		random: 0.5
+	};
+	properties.onEnd = function(){
+		currentAnimation = dojox.fx.text.converge(dojo.mixin(properties,{
+			onEnd: undefined,
+			text: originalText
+		}));
+		currentAnimation.play();
+	};
+	currentAnimation = dojox.fx.text.explode(properties).play();
+};
diff --git a/dojox/widget/tests/test_PortletInGridContainerColumns.html b/dojox/widget/tests/test_PortletInGridContainerColumns.html
new file mode 100644
index 0000000..4dc493d
--- /dev/null
+++ b/dojox/widget/tests/test_PortletInGridContainerColumns.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>DojoX Portlet In a GridContainer: Using specific columns test</title>
+
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/soria/soria.css">
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		
+		@import "../Portlet/Portlet.css";
+		@import "../../layout/resources/GridContainer.css";
+		
+		.dj_ie6 .dropIndicator, .dj_ie6 .dojoxPortlet{
+			margin: 5px;
+		}
+		.gridContainerZone > *{
+			margin: 5px !important;
+		}
+	</style>		
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:false, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dojox.layout.GridContainer");
+		dojo.require("dojox.widget.Portlet");
+	</script>
+</head>
+<body class="soria">
+	<h1>Test inserting Portlets in specific GridContainer columns</h1>
+	<div>
+		This page tests the inserting of Portlets into specific columns of the GridContainer.
+		To do this, each Portlet must be assigned a "column" attribute, and the "isAutoOrganized"
+		attribute of the GridContainer must be set to false.
+	</div>
+	<div dojoType="dojox.layout.GridContainer"
+			id="gridContainer"
+			isAutoOrganized="false"
+			hasResizableColumns="false"
+			nbZones="3"
+			dragHandleClass="dijitTitlePaneTitle"
+			style="width:100%;"
+			doLayout="false"
+	>
+		<div dojoType="dojox.widget.Portlet" title="First Col, top" column="1">
+			This Portlet is placed in Column 1
+		</div>
+		
+		<div dojoType="dojox.widget.Portlet" title="First Col, middle" column="1">
+			This Portlet is placed in Column 1
+		</div>
+		
+		<div dojoType="dojox.widget.Portlet" title="First Col, bottom" column="1">
+			This Portlet is placed in Column 1
+		</div>
+		
+		<div dojoType="dojox.widget.Portlet" title="Second Col, top" column="2">
+			This Portlet is placed in Column 2
+		</div>
+		
+		<div dojoType="dojox.widget.Portlet" title="Third Col, top" column="3">
+			This Portlet is placed in Column 3
+		</div>
+		
+		<div dojoType="dojox.widget.Portlet" title="Third Col, bottom" column="3">
+			This Portlet is placed in Column 3
+		</div>
+
+	</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/widget/tests/test_Roller.html b/dojox/widget/tests/test_Roller.html
new file mode 100644
index 0000000..ef6fa79
--- /dev/null
+++ b/dojox/widget/tests/test_Roller.html
@@ -0,0 +1,226 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+	<title>Testing the Roller / Slider / Exploder</title>
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" djconfig="parseOnLoad:true, isDebug: true, defaultTestTheme:'soria'"></script>
+	<script type="text/javascript" src="../Roller.js"></script>
+	<script type="text/javascript">
+	dojo.require("dojo.parser");
+	dojo.require("dojox.data.GoogleFeedStore");
+	
+	var request;
+	var makeDojoDataExample = function(){
+
+		// an entirely programatic one, from a DataStore. First make the store:
+		var store = new dojox.data.GoogleFeedStore();
+		// then the widget
+		var roller = new dojox.widget.Roller({
+			autoStart: false,
+			delay: 6000
+		});
+		// and put it in the dom somewhere
+		dojo.byId("wrapper").appendChild(roller.domNode);
+				
+		var insertItem = function(item){
+			// for each feed result, make a simple link, then add it to the widget
+			var htmlPiece = "<div class='exTitle'>" +
+				"<p><a href='" + item.link + "'>" + item.title + "</a></p>" + //" - <span class='exAuthor'>by: " + item.author + "</span></p>" +
+				"<div class='exSummary'>" + item.summary + "" +
+				"</div></div>";
+				
+			roller.items.push(htmlPiece);
+		}
+
+		var sourceIdx = 0,
+			sources = [
+				"http://twitter.com/statuses/user_timeline/14572071.rss",
+				"http://dojocampus.org/content/category/dojo-cookies/feed/",
+				"http://www.dojotoolkit.org/aggregator/rss"
+			]
+		;
+		var source = function(){ return sources[sourceIdx++]; }
+		
+		var start = 0;
+		// send off a store request
+		request = {
+			query: {
+				// we'll get the campus cookie feed
+				url: source(),
+				count: 10,
+				start: start
+			},
+			onItem: insertItem,
+			onComplete: function(){
+				// once we have das data, start it up
+				console.log('oncomplete fired');
+				
+				var s = source();
+				if(s){
+					request.query.url = s + "";
+					setTimeout(dojo.hitch(store, "fetch", request), 5000);
+				}
+				
+				// make sure she's running:
+				roller.start();
+				
+			},
+			onError: function(e){
+				// stub for debugging:
+				console.warn(e);
+			}			
+		};
+		store.fetch(request);
+
+	}
+	
+	dojo.addOnLoad(function(){
+		
+		var dasroller = new dojox.widget.Roller({ delay: 3000 }, "dasroller");
+		dojo.connect(dasroller.domNode, "onmouseenter", dasroller, "stop");
+		dojo.connect(dasroller.domNode, "onmouseleave", dasroller, "start");
+		
+		var items = ["one","two","three","four","five"];
+		new dojox.widget.Roller({ delay: 1000, items: items }, "roller2");
+		new dojox.widget.RollerSlide({ delay: 2000, items: items }, "rollerslide");
+		
+		// programatic google-store fed roller:
+		makeDojoDataExample();
+		
+	})
+	</script>
+	
+	<style type="text/css">
+		body {
+			font-family: Arial;
+		}
+		.dojoxRoller {
+			list-style:none;
+			margin:0; padding:7px;
+		}
+		.dj_ie6 ul.dojoxRoller li {
+			float:left;
+		}
+		div ul.dojoxRoller li {
+			padding:4px;
+			text-align:center;
+		}
+		#wrapper .dojoxRoller {
+			padding:0; margin:0;
+		}
+		#wrapper .exSummary,
+		#wrapper .exAuthor {
+			font-size:10pt;
+			padding:6px; 
+		}
+		#wrapper p {
+			padding:4px;
+			margin-top:4px;
+		}
+	</style>
+</head>
+<body>
+		
+	<h1 class="testTitle">dojox.widget.Roller</h1>
+	
+	<div id="googleStore">
+		<h2>Powered by dojo.data (by way of <a href="http://google.com">google</a>):</h2>
+		<div id="wrapper" style="border:2px dashed #666; background:#dedede; width:500px; height:120px; overflow:hidden;"></div>
+	</div>
+
+	<h2>A Simple UL: (progressive)</h2>
+	<p>start/stop onhover</p>
+	<div id="ex1" style="background:#ededed; width:175px;">
+		<ul id="dasroller">
+			<li>First Item</li>			
+			<li>Second Item</li>
+			<li>items added 1</li>
+			<li>items added 2</li>
+			<li>items added 3</li>
+			<li>items added 4</li>
+			<li>items added 5</li>
+			<li>items added 6</li>
+			<li>items added 7</li>
+			<li>items added 8</li>
+			<li>items added 9</li>
+			<li>items added 0</li>
+		</ul>
+	</div>
+
+	<h2>An empty UL, programatic from Array</h2>
+	<div style="background:#ededed; width:175px;">
+		<ul id="roller2"></ul>
+	</div>
+
+	<h2>An empty UL, programatic Slider from Array</h2>
+	<div style="background:#ededed; width:175px; height:42px">
+		<ul id="rollerslide"></ul>
+	</div>
+	
+	<h2>and a dojoType one</h2>
+	<div style="background:#ededed; width:375px;">
+		<ul id="foo" dojoType="dojox.widget.Roller" delay="5000">
+			<li>Today's episode of random widget</li>
+			<li>brought to you by <a href="http://dojotoolkit.org">Dojo</a></li>
+			<li>(really just testing simple markup)</li>
+			<li>enjoy.</li>
+			<li>  <!-- left blank for fake delay --></li>
+			<li>wow that was 10 seconds</li>
+		</ul>
+	</div>
+
+	<h2>One with embedded LI's</h2>
+	<div>
+		<ul id="embedded" dojoType="dojox.widget.Roller">
+			<li>one: <ul><li>inner</li><li>inner</li></ul></li>
+			<li>one: <ul><li>inner</li><li>inner</li></ul></li>
+			<li>one: <ul><li>inner</li><li>inner</li></ul></li>
+		</ul>
+	</div>
+	
+	<h2>Customer RollerHover</h2>
+	<div>
+		<ul id="customType">
+			<li>test 1</li>
+			<li>test 2</li>
+			<li>test 3</li>
+			<li>test 4</li>
+		</ul>
+	</div>
+
+	<script type="text/javascript">
+		dojo.addOnLoad(function(){
+			// taking advantage of the _RollerHover mixin:
+			dojo.declare("a.custom.Roller", [dojox.widget.RollerSlide, dojox.widget._RollerHover], {});
+			new a.custom.Roller({}, "customType");
+		});
+	</script>
+	
+	<!-- disabled because of styling mishaps :)
+	<h2>programatic Exploder:</h2>
+	<div id="ex1" style="background:#ededed; width:175px;">
+		<ul id="exploder">
+			<li>First Item</li>
+			<li>Second Item</li>
+			<li>items added 1</li>
+			<li>items added 2</li>
+			<li>items added 3</li>
+			<li>items added 4</li>
+			<li>items added 5</li>
+			<li>items added 6</li>
+			<li>items added 7</li>
+			<li>items added 8</li>
+			<li>items added 9</li>
+			<li>items added 0</li>
+		</ul>
+	</div>
+	-->
+
+</body>
+</html>
\ No newline at end of file
diff --git a/dojox/widget/tests/test_RollingList.html b/dojox/widget/tests/test_RollingList.html
new file mode 100644
index 0000000..9fd0f2c
--- /dev/null
+++ b/dojox/widget/tests/test_RollingList.html
@@ -0,0 +1,203 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox Rolling List Test</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<!-- required: a default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../../dijit/themes/tundra/tundra.css">
+	
+	<!-- the additional styles for the widget -->
+	<link id="widgetStyle" rel="stylesheet" href="../RollingList/RollingList.css">
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="parseOnLoad: true, isDebug: true"></script>
+	
+	<!-- not needed, for testing alternate themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+
+	<script language="JavaScript" type="text/javascript">
+		dojo.require("dojo.data.ItemFileWriteStore");
+		dojo.require("dojox.widget.RollingList");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+		
+		dojo.declare("dojox.widget.RollingStore", dojo.data.ItemFileWriteStore, {
+			getLabel: function(item){
+				return this.inherited(arguments) + " (" + this.getValue(item, "type") + ")";
+			}
+		});
+
+		addedT = false;
+		addedD = false;
+		addedA = false;
+		removedC = false;
+		removedE = false;
+		changedD = false;
+		isBig = true;
+		
+		addTijuana = function(){
+			if(addedT){ 
+				console.log("Tijuana is already added");
+				return; 
+			}
+			addedT = true;
+			continentStore.fetchItemByIdentity({identity: "MX", onItem: function(i){
+				continentStore.newItem({id: "Tijuana", name: "Tijuana", type: "city"}, 
+										{parent: i, attribute: "children"});
+				continentStore.save();
+			}});
+		}
+		addDC = function(){
+			if(addedD){ 
+				console.log("Washington DC is already added");
+				return; 
+			}			
+			addedD = true;
+			continentStore.fetchItemByIdentity({identity: "US", onItem: function(i){
+				continentStore.newItem({id: "Washington DC", name: "Washington DC", type: "city"}, 
+										{parent: i, attribute: "children"});
+				continentStore.save();
+			}});
+		}
+		addAntarctica = function(){
+			if(addedA){ 
+				console.log("Antarctica is already added");
+				return; 
+			}
+			continentStore.newItem({id: "Antarctica", name: "Antarctica", type: "continent"});
+			addedA = true;
+		}
+		removeTijuana = function(){
+			if(!addedT){ 
+				console.log("Tijuana is not yet added");
+				return; 
+			}
+			addedT = false;
+			continentStore.fetchItemByIdentity({identity: "Tijuana", onItem: function(i){
+				continentStore.deleteItem(i);
+				continentStore.save();
+			}});
+		}
+		removeCanada = function(){
+			if(removedC){ 
+				console.log("Canada is already removed");
+				return; 
+			}			
+			removedC = true;
+			continentStore.fetchItemByIdentity({identity: "CA", onItem: function(i){
+				continentStore.deleteItem(i);
+			}});
+		}
+		removeEurope = function(){
+			if(removedE){ 
+				console.log("Europe is already removed");
+				return; 
+			}			
+			removedE = true;
+			continentStore.fetchItemByIdentity({identity: "EU", onItem: function(i){
+				continentStore.deleteItem(i);
+			}});
+		}
+		changeDC = function(){
+			if(!addedD){ 
+				console.log("Washington DC is not yet added");
+				return; 
+			}			
+			if(changedD){ 
+				console.log("Washington DC is already changed");
+				return; 
+			}			
+			changedD = true;
+			continentStore.fetchItemByIdentity({identity: "Washington DC", onItem: function(i){
+				continentStore.setValue(i, "type", "district");
+			}});
+		}
+		removeDC = function(){
+			if(!addedD){
+				console.log("Washington DC is not yet added");
+				return;
+			}
+			changedD = false;
+			addedD = false;
+			continentStore.fetchItemByIdentity({identity: "Washington DC", onItem: function(i){
+				continentStore.deleteItem(i);
+				continentStore.save();
+			}});
+			
+		}
+		doResize = function(){
+			var newSize = isBig ? {w: 340, h: 100} : {w: 500, h: 300};
+			myList.resize(newSize);
+			isBig = !isBig;
+		}
+		setValue = function(id){
+			if(id){
+				continentStore.fetchItemByIdentity({identity: id, onItem: function(i){
+					myList.attr("value", i);
+				}});
+			}else{
+				myList.attr("value", null);
+			}
+		}
+	</script>
+
+</head>
+<body class="tundra">
+
+	<h1 class="testTitle">Dojox Rolling List Test</h1>
+
+	<div dojoType="dojox.widget.RollingStore" jsId="continentStore" 
+		url="../../../dijit/tests/_data/countries.json">
+	</div>
+	
+	<h3>Rolling List - <input dojoType="dijit.form.TextBox" type="text" id="clickWatch" disabled value="None Selected..."></h3>
+	<div dojoType="dojox.widget.RollingList" jsId="myList" id="myList" store="continentStore"
+		query="{type:'continent'}">
+		<script type="dojo/method" event="onChange" args="value">
+			console.debug("Set Value:", value);
+			if(value){
+				dijit.byId("clickWatch").attr("value", this.store.getIdentity(value));
+			}else{
+				dijit.byId("clickWatch").attr("value", "None Selected...");
+			}
+		</script>
+		<script type="dojo/method" event="getPaneForItem" args="item,parentPane,children">
+			var ret = dojox.widget.RollingList.prototype.getPaneForItem.apply(this, arguments);
+
+			if(!ret){
+				ret = new dojox.widget._RollingListPane({
+									onItems: function(){
+										if(this.items.length){
+											this._setContentAndScroll("Details for " + this.store.getLabel(this.items[0]).replace(/</,"<"));
+										}
+									}});
+			}
+			return ret;
+		</script>
+	</div>
+	<hr>
+	<button dojoType="dijit.form.Button" onClick="doResize()">Resize widget</button>
+	<hr>
+	<button dojoType="dijit.form.Button" onClick="setValue('Guadalajara')">Set Value to Guadalajara</button>
+	<button dojoType="dijit.form.Button" onClick="setValue('AF')">Set Value to Africa</button>
+	<button dojoType="dijit.form.Button" onClick="setValue('Toronto')">Set Value to Toronto</button>
+	<button dojoType="dijit.form.Button" onClick="setValue('')">Set No Value</button>
+	<hr>
+	<button dojoType="dijit.form.Button" onClick="addTijuana()">Add Item To Mexico (Tijuana)</button>
+	<button dojoType="dijit.form.Button" onClick="removeTijuana()">Remove Tijuana</button><br>
+	<button dojoType="dijit.form.Button" onClick="addDC()">Add Item To USA (Washington DC)</button>
+	<button dojoType="dijit.form.Button" onClick="changeDC()">Change Washington DC</button>
+	<button dojoType="dijit.form.Button" onClick="removeDC()">Remove Washington DC</button><br>
+	<button dojoType="dijit.form.Button" onClick="addAntarctica()">Add Item To Top-level (Antarctica)</button><br>
+	<button dojoType="dijit.form.Button" onClick="removeCanada()">Remove Canada</button>
+	<button dojoType="dijit.form.Button" onClick="removeEurope()">Remove Europe</button>
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Rotator.html b/dojox/widget/tests/test_Rotator.html
new file mode 100644
index 0000000..743b2ac
--- /dev/null
+++ b/dojox/widget/tests/test_Rotator.html
@@ -0,0 +1,709 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.widget.Rotator Test</title>
+	<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+
+	.rotator{
+		background-color:#fff;
+		border:solid 1px #e5e5e5;
+		width:384px;
+		height:90px;
+		overflow:hidden;
+	}
+	.rotatorStacked{
+		width:384px;
+		height:90px;
+		overflow:hidden;
+		position:absolute;
+		left:0;
+		top:0;
+	}
+	.rotatorStacked .pane{
+		background-color:transparent;
+	}
+	.pane{
+		background-color:#fff;
+		width:384px;
+		height:90px;
+		overflow:hidden;
+	}
+	.logWindow{
+		border:solid 1px #e5e5e5;
+		margin-left:20px;
+		width:400px;
+		height:90px;
+		overflow:auto;
+	}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad:true, isDebug:true"></script>
+	<script type="text/javascript">
+	dojo.require("dojo.parser");
+	dojo.require("dojo.fx.easing");
+	dojo.require("dojox.widget.Rotator");
+	dojo.require("dojox.widget.rotator.Fade");
+	dojo.require("dojox.widget.rotator.Pan");
+	dojo.require("dojox.widget.rotator.Slide");
+	dojo.require("dojox.widget.rotator.Wipe");
+	
+	function log(id, msg){
+		var e = dojo.byId(id);
+		e.innerHTML += msg + "<br>";
+		e.scrollTop = 9999;
+	}
+	
+	dojo.addOnLoad(function(){
+		// programmatic example
+		var contributors = [
+			[ "http://www.nexaweb.com",		"nexaweb.png",		"Nexaweb" ],
+			[ "http://www.renkoo.com",		"renkoo.png",		"Renkoo" ],
+			[ "http://www.sitepen.com",		"sitepen.png",		"Sitepen" ],
+			[ "http://www.tibco.com",		"tibco.png",		"Tibco" ],
+			[ "http://www.webtide.com",		"webtide.png",		"Webtide" ],
+			[ "http://www.openlaszlo.com",	"openlaszlo.png",	"OpenLaszlo" ],
+			[ "http://www.sun.com",			"sun.png",			"Sun" ],
+			[ "http://www.google.com",		"google.png",		"Google" ],
+			[ "http://www.aptana.com",		"aptana.png",		"Aptana" ],
+			[ "http://www.aol.com",			"aol.png",			"AOL" ],
+			[ "http://www.ibm.com",			"ibm.png",			"IBM" ],
+			[ "http://www.zend.com",		"zend.png",			"Zend" ],
+			[ "http://www.bea.com",			"bea.png",			"BEA" ],
+			[ "http://www.uxebu.com",		"uxebu.png",		"Uxebu" ],
+			[ "http://www.wavemaker.com",	"wavemaker.png",	"WaveMaker" ],
+			[ "http://www.aptana.com",		"aptana.png",		"Aptana" ]
+		];
+		
+		var panes = [];
+		for(var i=0; i<contributors.length; i++){
+			var html = '<a href="' + contributors[i][0] + '" target="_new"><img src="images/rotator_'
+						+ contributors[i][1] + '" width="130" alt="' + contributors[i][2] + '"/></a>';
+			if(i % 2 == 0){
+				panes.push({
+					className: "pane",
+					innerHTML: html
+				});
+			}else{
+				panes[panes.length-1].innerHTML += html
+			}
+		}
+
+		var r = new dojox.widget.Rotator({
+				id: "myRotator13",
+				duration: 2000,
+				transition: "dojox.widget.rotator.fade",
+				panes: panes
+			},
+			dojo.byId("myRotator13")
+		);
+	});
+	</script>
+</head>
+<body>
+
+	<h1 class="testTitle">dojox.widget.Rotator Test</h1>
+
+	<h2>Controlled By Topics, Default Swap Transition</h2>
+	
+	<p>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['prev']);">Prev</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['next']);">Next</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 0]);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 1]);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 2]);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 3]);">Goto 3 (Sun, Google)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 4]);">Goto 4 (Aptana, AOL)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 5]);">Goto 5 (IBM, Zend)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 6]);">Goto 6 (BEA, Uxebu)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 7]);">Goto 7 (WaveMaker, Aptana)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['go', 8]);">Goto 8 (bad)</button>
+	<button onclick="dojo.publish('myRotator/rotator/control', ['test']);">Bad Action</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" id="myRotator">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+			<a href="http://www.aol.com" target="_new"><img src="images/rotator_aol.png" width="130" alt="AOL"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.ibm.com" target="_new"><img src="images/rotator_ibm.png" width="100" alt="IBM"/></a>
+			<a href="http://www.zend.com/" target="_new"><img src="images/rotator_zend.png" width="130" alt="Zend"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.bea.com" target="_new"><img src="images/rotator_bea.png" width="80" alt="BEA"/></a>
+			<a href="http://www.uxebu.com" target="_new"><img src="images/rotator_uxebu.png" width="120" alt="Uxebu"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.wavemaker.com" target="_new"><img src="images/rotator_wavemaker.png" width="130" alt="WaveMaker"/></a>
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+		</div>
+	</div>
+
+	<h2>Controlled By jsId Reference, Default Swap Transition</h2>
+	
+	<p>
+	<button onclick="myRotator2.prev();">Prev</button>
+	<button onclick="myRotator2.next();">Next</button>
+	<button onclick="myRotator2.go(0);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="myRotator2.go(1);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="myRotator2.go(2);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="myRotator2.go(3);">Goto 3 (Sun, Google)</button>
+	<button onclick="myRotator2.go(4);">Goto 4 (Aptana, AOL)</button>
+	<button onclick="myRotator2.go(5);">Goto 5 (IBM, Zend)</button>
+	<button onclick="myRotator2.go(6);">Goto 6 (BEA, Uxebu)</button>
+	<button onclick="myRotator2.go(7);">Goto 7 (WaveMaker, Aptana)</button>
+	<button onclick="myRotator2.go(8);">Goto 8 (bad)</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator2">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+			<a href="http://www.aol.com" target="_new"><img src="images/rotator_aol.png" width="130" alt="AOL"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.ibm.com" target="_new"><img src="images/rotator_ibm.png" width="100" alt="IBM"/></a>
+			<a href="http://www.zend.com/" target="_new"><img src="images/rotator_zend.png" width="130" alt="Zend"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.bea.com" target="_new"><img src="images/rotator_bea.png" width="80" alt="BEA"/></a>
+			<a href="http://www.uxebu.com" target="_new"><img src="images/rotator_uxebu.png" width="120" alt="Uxebu"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.wavemaker.com" target="_new"><img src="images/rotator_wavemaker.png" width="130" alt="WaveMaker"/></a>
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+		</div>
+	</div>
+
+	<h2>Crossfade Transition</h2>
+	
+	<p>
+	<button onclick="myRotator3.prev();">Prev</button>
+	<button onclick="myRotator3.next();">Next</button>
+	<button onclick="myRotator3.go(0);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="myRotator3.go(1);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="myRotator3.go(2);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="myRotator3.go(3);">Goto 3 (Sun, Google)</button>
+	<button onclick="myRotator3.go(4);">Goto 4 (Aptana, AOL)</button>
+	<button onclick="myRotator3.go(5);">Goto 5 (IBM, Zend)</button>
+	<button onclick="myRotator3.go(6);">Goto 6 (BEA, Uxebu)</button>
+	<button onclick="myRotator3.go(7);">Goto 7 (WaveMaker, Aptana)</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator3" transition="dojox.widget.rotator.crossFade">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+			<a href="http://www.aol.com" target="_new"><img src="images/rotator_aol.png" width="130" alt="AOL"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.ibm.com" target="_new"><img src="images/rotator_ibm.png" width="100" alt="IBM"/></a>
+			<a href="http://www.zend.com/" target="_new"><img src="images/rotator_zend.png" width="130" alt="Zend"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.bea.com" target="_new"><img src="images/rotator_bea.png" width="80" alt="BEA"/></a>
+			<a href="http://www.uxebu.com" target="_new"><img src="images/rotator_uxebu.png" width="120" alt="Uxebu"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.wavemaker.com" target="_new"><img src="images/rotator_wavemaker.png" width="130" alt="WaveMaker"/></a>
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+		</div>
+	</div>
+
+	<h2>Crossfade Transition 2</h2>
+	
+	<p>
+	<button onclick="myRotator3_2.prev();">Prev</button>
+	<button onclick="myRotator3_2.next();">Next</button>
+	<button onclick="myRotator3_2.go(0);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="myRotator3_2.go(1);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="myRotator3_2.go(2);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="myRotator3_2.go(3);">Goto 3 (Sun, Google)</button>
+	</p>
+
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator3_2" transition="dojox.widget.rotator.crossFade">
+		<div class="pane" style="background-color:red;"></div>
+		<div class="pane" style="background-color:yellow;"></div>
+		<div class="pane" style="background-color:green;"></div>
+		<div class="pane" style="background-color:blue;"></div>
+	</div>
+	
+	<h2>Pan Transition</h2>
+	
+	<p>
+	<button onclick="myRotator4.prev();">Prev</button>
+	<button onclick="myRotator4.next();">Next</button>
+	<button onclick="myRotator4.go(0);">Goto 0 (Nexaweb, Renkoo) [pan left]</button>
+	<button onclick="myRotator4.go(1);">Goto 1 (Sitepen, Tibco) [pan down]</button>
+	<button onclick="myRotator4.go(2);">Goto 2 (Webtide, OpenLaszlo) [pan right]</button>
+	<button onclick="myRotator4.go(3);">Goto 3 (Sun, Google) [pan up]</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator4" transition="dojox.widget.rotator.panLeft">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.panDown">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.panRight">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.panUp">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+	</div>
+
+	<h2>Pan Continuous Transition</h2>
+	
+	<p>It is set to wrap so it will detect the shortest distance to the next pane and determine to go left or right.</p>
+	<p>The transition duration is 1 second. Quick transitions are enabled, so it will perform X number of transitions within the transition duration timeframe.</p>
+	
+	<p>
+	<button onclick="myRotator5.prev();">Prev</button>
+	<button onclick="myRotator5.next();">Next</button>
+	<button onclick="myRotator5.go(0);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="myRotator5.go(1);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="myRotator5.go(2);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="myRotator5.go(3);">Goto 3 (Sun, Google)</button>
+	<button onclick="myRotator5.go(4);">Goto 4 (Aptana, AOL)</button>
+	<button onclick="myRotator5.go(5);">Goto 5 (IBM, Zend)</button>
+	<button onclick="myRotator5.go(6);">Goto 6 (BEA, Uxebu)</button>
+	<button onclick="myRotator5.go(7);">Goto 7 (WaveMaker, Aptana)</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator5" transition="dojox.widget.rotator.pan"
+			transitionParams="continuous:true,wrap:true,quick:true,duration:1000">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+			<a href="http://www.aol.com" target="_new"><img src="images/rotator_aol.png" width="130" alt="AOL"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.ibm.com" target="_new"><img src="images/rotator_ibm.png" width="100" alt="IBM"/></a>
+			<a href="http://www.zend.com/" target="_new"><img src="images/rotator_zend.png" width="130" alt="Zend"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.bea.com" target="_new"><img src="images/rotator_bea.png" width="80" alt="BEA"/></a>
+			<a href="http://www.uxebu.com" target="_new"><img src="images/rotator_uxebu.png" width="120" alt="Uxebu"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.wavemaker.com" target="_new"><img src="images/rotator_wavemaker.png" width="130" alt="WaveMaker"/></a>
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+		</div>
+	</div>
+
+	<h2>Pan Transition with Easing</h2>
+	
+	<p>
+	<button onclick="myRotator6.prev();">Prev</button>
+	<button onclick="myRotator6.next();">Next</button>
+	<button onclick="myRotator6.go(0);">Goto 0 (Nexaweb, Renkoo) [pan left]</button>
+	<button onclick="myRotator6.go(1);">Goto 1 (Sitepen, Tibco) [pan down]</button>
+	<button onclick="myRotator6.go(2);">Goto 2 (Webtide, OpenLaszlo) [pan right]</button>
+	<button onclick="myRotator6.go(3);">Goto 3 (Sun, Google) [pan up]</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator6" transition="dojox.widget.rotator.panLeft"
+			transitionParams="easing:dojo.fx.easing.cubicInOut">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.panDown">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.panRight">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.panUp">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+	</div>
+
+	<h2>Pan Continuous Transition with Easing</h2>
+	
+	<p>Easing not supported with continuous pan... forces a linear easing.</p>
+	
+	<p>
+	<button onclick="myRotator7.prev();">Prev</button>
+	<button onclick="myRotator7.next();">Next</button>
+	<button onclick="myRotator7.go(0);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="myRotator7.go(1);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="myRotator7.go(2);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="myRotator7.go(3);">Goto 3 (Sun, Google)</button>
+	<button onclick="myRotator7.go(4);">Goto 4 (Aptana, AOL)</button>
+	<button onclick="myRotator7.go(5);">Goto 5 (IBM, Zend)</button>
+	<button onclick="myRotator7.go(6);">Goto 6 (BEA, Uxebu)</button>
+	<button onclick="myRotator7.go(7);">Goto 7 (WaveMaker, Aptana)</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator7" transition="dojox.widget.rotator.pan"
+			transitionParams="continuous:true,quick:true,duration:500,easing:dojo.fx.easing.cubicInOut">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+			<a href="http://www.aol.com" target="_new"><img src="images/rotator_aol.png" width="130" alt="AOL"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.ibm.com" target="_new"><img src="images/rotator_ibm.png" width="100" alt="IBM"/></a>
+			<a href="http://www.zend.com/" target="_new"><img src="images/rotator_zend.png" width="130" alt="Zend"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.bea.com" target="_new"><img src="images/rotator_bea.png" width="80" alt="BEA"/></a>
+			<a href="http://www.uxebu.com" target="_new"><img src="images/rotator_uxebu.png" width="120" alt="Uxebu"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.wavemaker.com" target="_new"><img src="images/rotator_wavemaker.png" width="130" alt="WaveMaker"/></a>
+			<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+		</div>
+	</div>
+
+	<h2>Slide Transition</h2>
+	
+	<p>
+	<button onclick="myRotator8.prev();">Prev</button>
+	<button onclick="myRotator8.next();">Next</button>
+	<button onclick="myRotator8.go(0);">Goto 0 (Nexaweb, Renkoo) [slide left]</button>
+	<button onclick="myRotator8.go(1);">Goto 1 (Sitepen, Tibco) [slide down]</button>
+	<button onclick="myRotator8.go(2);">Goto 2 (Webtide, OpenLaszlo) [slide right]</button>
+	<button onclick="myRotator8.go(3);">Goto 3 (Sun, Google) [slide up]</button>
+	<button onclick="myRotator8.resize(500, 125);">Resize to 500 x 125</button>
+	<button onclick="myRotator8.resize(384, 90);">Resize to 384 x 90</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator8" transition="dojox.widget.rotator.slideLeft">
+		<div class="pane" style="background-color:#fff799;">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.slideDown" style="background-color:#6dcff6;">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.slideRight" style="background-color:#c7b299;">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.slideUp" style="background-color:#f4cedf;">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+	</div>
+
+	<h2>Slide Transition with Easing</h2>
+	
+	<p>
+	<button onclick="myRotator9.prev();">Prev</button>
+	<button onclick="myRotator9.next();">Next</button>
+	<button onclick="myRotator9.go(0);">Goto 0 (Nexaweb, Renkoo) [slide left]</button>
+	<button onclick="myRotator9.go(1);">Goto 1 (Sitepen, Tibco) [slide down]</button>
+	<button onclick="myRotator9.go(2);">Goto 2 (Webtide, OpenLaszlo) [slide right]</button>
+	<button onclick="myRotator9.go(3);">Goto 3 (Sun, Google) [slide up]</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator9" transition="dojox.widget.rotator.slideLeft"
+			transitionParams="duration:1000,easing:dojo.fx.easing.cubicInOut">
+		<div class="pane" style="background-color:#fff799;">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.slideDown" style="background-color:#6dcff6;">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.slideRight" style="background-color:#c7b299;">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.slideUp" style="background-color:#f4cedf;">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+	</div>
+
+	<h2>Wipe Transition</h2>
+	
+	<p>
+	<button onclick="myRotator10.prev();">Prev</button>
+	<button onclick="myRotator10.next();">Next</button>
+	<button onclick="myRotator10.go(0);">Goto 0 (Nexaweb, Renkoo) [wipe left]</button>
+	<button onclick="myRotator10.go(1);">Goto 1 (Sitepen, Tibco) [wipe down]</button>
+	<button onclick="myRotator10.go(2);">Goto 2 (Webtide, OpenLaszlo) [wipe right]</button>
+	<button onclick="myRotator10.go(3);">Goto 3 (Sun, Google) [wipe up]</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator10" transition="dojox.widget.rotator.wipeLeft">
+		<div class="pane" style="background-color:#fff799;">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.wipeDown" style="background-color:#6dcff6;">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.wipeRight" style="background-color:#c7b299;">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.wipeUp" style="background-color:#f4cedf;">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+	</div>
+	
+	<h2>Wipe Transition with Easing</h2>
+	
+	<p>
+	<button onclick="myRotator11.prev();">Prev</button>
+	<button onclick="myRotator11.next();">Next</button>
+	<button onclick="myRotator11.go(0);">Goto 0 (Nexaweb, Renkoo) [wipe left]</button>
+	<button onclick="myRotator11.go(1);">Goto 1 (Sitepen, Tibco) [wipe down]</button>
+	<button onclick="myRotator11.go(2);">Goto 2 (Webtide, OpenLaszlo) [wipe right]</button>
+	<button onclick="myRotator11.go(3);">Goto 3 (Sun, Google) [wipe up]</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator11" transition="dojox.widget.rotator.wipeLeft"
+			transitionParams="duration:500,easing:dojo.fx.easing.cubicInOut">
+		<div class="pane" style="background-color:#fff799;">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.wipeDown" style="background-color:#6dcff6;">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.wipeRight" style="background-color:#c7b299;">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane" transition="dojox.widget.rotator.wipeUp" style="background-color:#f4cedf;">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+	</div>
+
+	<h2>Declarative Event Hooks</h2>
+	
+	<p>The 2nd pane will output when the onBeforeIn/Out and onAfterIn/Out events are fired.</p>
+	
+	<p>
+	<button onclick="myRotator12.prev();">Prev</button>
+	<button onclick="myRotator12.next();">Next</button>
+	<button onclick="myRotator12.go(0);">Goto 0 (Nexaweb, Renkoo) [pan left]</button>
+	<button onclick="myRotator12.go(1);">Goto 1 (Sitepen, Tibco) [pan down]</button>
+	<button onclick="myRotator12.go(2);">Goto 2 (Webtide, OpenLaszlo) [pan right]</button>
+	<button onclick="myRotator12.go(3);">Goto 3 (Sun, Google) [pan up]</button>
+	</p>
+	
+	<table><tr><td>
+	
+		<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator12" transition="dojox.widget.rotator.panLeft">
+			<div class="pane">
+				<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+				<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+			</div>
+			<div class="pane" transition="dojox.widget.rotator.panDown">
+				<script type="dojo/method" event="onBeforeIn" args="args">
+					log("myRotator12Log", "onBeforeIn - get dom nodes ready to be displayed, wire events");
+				</script>
+				<script type="dojo/method" event="onAfterIn" args="args">
+					log("myRotator12Log", "onAfterIn - this pane is now visible, so do cool stuff!");
+				</script>
+				<script type="dojo/method" event="onBeforeOut" args="args">
+					log("myRotator12Log", "onBeforeOut - stop any animations, disconnect events, etc");
+				</script>
+				<script type="dojo/method" event="onAfterOut" args="args">
+					log("myRotator12Log", "onAfterOut - clean up dom, reset state, disconnect events, etc");
+				</script>
+				<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+				<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+			</div>
+			<div class="pane" transition="dojox.widget.rotator.panRight">
+				<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+				<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+			</div>
+			<div class="pane" transition="dojox.widget.rotator.panUp">
+				<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+				<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+			</div>
+		</div>
+	
+	</td><td>
+		<div class="logWindow" id="myRotator12Log"></div>
+	</td></tr></table>
+	
+	<h2>Programmatic Example with Fade Transition</h2>
+	
+	<p>
+	<button onclick="dojo.publish('myRotator13/rotator/control', ['prev']);">Prev</button>
+	<button onclick="dojo.publish('myRotator13/rotator/control', ['next']);">Next</button>
+	<button onclick="dojo.publish('myRotator13/rotator/control', ['go', 0]);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="dojo.publish('myRotator13/rotator/control', ['go', 1]);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="dojo.publish('myRotator13/rotator/control', ['go', 2]);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="dojo.publish('myRotator13/rotator/control', ['go', 3]);">Goto 3 (Sun, Google)</button>
+	<button onclick="dojo.publish('myRotator13/rotator/control', ['go', 4]);">Goto 4 (Aptana, AOL)</button>
+	<button onclick="dojo.publish('myRotator13/rotator/control', ['go', 5]);">Goto 5 (IBM, Zend)</button>
+	<button onclick="dojo.publish('myRotator13/rotator/control', ['go', 6]);">Goto 6 (BEA, Uxebu)</button>
+	<button onclick="dojo.publish('myRotator13/rotator/control', ['go', 7]);">Goto 7 (WaveMaker, Aptana)</button>
+	</p>
+
+	<div class="rotator" id="myRotator13"></div>
+	
+	<h2>Stacked Example: Pan Rotator Over Crossfade Rotator</h2>
+	
+	<p>
+	<button onclick="myRotator3_3.prev();myRotator3_4.prev();">Prev</button>
+	<button onclick="myRotator3_3.next();myRotator3_4.next();">Next</button>
+	<button onclick="myRotator3_3.go(0);myRotator3_4.go(0);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="myRotator3_3.go(1);myRotator3_4.go(1);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="myRotator3_3.go(2);myRotator3_4.go(2);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="myRotator3_3.go(3);myRotator3_4.go(3);">Goto 3 (Sun, Google)</button>
+	</p>
+
+	<div class="rotator" style="position:relative;">
+		<div dojoType="dojox.widget.Rotator" class="rotatorStacked" style="z-index:100;" jsId="myRotator3_3" transition="dojox.widget.rotator.panLeft">
+			<div class="pane">
+				<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+				<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+			</div>
+			<div class="pane" transition="dojox.widget.rotator.panDown">
+				<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+				<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+			</div>
+			<div class="pane" transition="dojox.widget.rotator.panRight">
+				<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+				<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+			</div>
+			<div class="pane" transition="dojox.widget.rotator.panUp">
+				<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+				<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+			</div>
+		</div>
+		<div dojoType="dojox.widget.Rotator" class="rotatorStacked" style="z-index:50;" jsId="myRotator3_4" transition="dojox.widget.rotator.crossFade">
+			<div class="pane" style="background-color:red;"></div>
+			<div class="pane" style="background-color:yellow;"></div>
+			<div class="pane" style="background-color:green;"></div>
+			<div class="pane" style="background-color:blue;"></div>
+		</div>
+	</div>
+	
+	<h2>Bad Global Transition</h2>
+	
+	<p>Uses a transtion "dojox.widget.rotator.doesNotExist" and should default to the swap transition.</p>
+	
+	<p>
+	<button onclick="myRotator14.prev();">Prev</button>
+	<button onclick="myRotator14.next();">Next</button>
+	<button onclick="myRotator14.go(0);">Goto 0 (Nexaweb, Renkoo)</button>
+	<button onclick="myRotator14.go(1);">Goto 1 (Sitepen, Tibco)</button>
+	<button onclick="myRotator14.go(2);">Goto 2 (Webtide, OpenLaszlo)</button>
+	<button onclick="myRotator14.go(3);">Goto 3 (Sun, Google)</button>
+	</p>
+	
+	<div dojoType="dojox.widget.Rotator" class="rotator" jsId="myRotator14" transition="dojox.widget.rotator.doesNotExist">
+		<div class="pane">
+			<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+			<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+			<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+			<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+		</div>
+		<div class="pane">
+			<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+			<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+		</div>
+	</div>
+
+</body>
+</html>
diff --git a/dojox/widget/tests/test_RotatorController.html b/dojox/widget/tests/test_RotatorController.html
new file mode 100644
index 0000000..aef8731
--- /dev/null
+++ b/dojox/widget/tests/test_RotatorController.html
@@ -0,0 +1,346 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.widget.rotator.Controller Test</title>
+	<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+
+	.rotator{
+		background-color:#fff;
+		border:solid 1px #e5e5e5;
+		width:384px;
+		height:90px;
+		overflow:hidden;
+	}
+	.pane{
+		background-color:#fff;
+		width:384px;
+		height:90px;
+		overflow:hidden;
+	}
+	td{
+		padding-right:15px;
+		vertical-align:top;
+	}
+	
+	/* test 1 styles */
+	.test1 .dojoxRotatorSelected{
+		background-color:#e5e5e5;
+		font-weight:bold;
+	}
+	
+	/* test 2 styles */
+	.test2 .rotatorContainer{
+		width:384px;
+		height:110px;
+		position:relative;
+	}
+	.test2 .rotator{
+		background-color:#e5e5e5;
+		border:solid 1px #ccc;
+		position:relative;
+		top:20px;
+		left:0;
+		z-index:10;
+	}
+	.test2 .pane{
+		background-color:#e5e5e5;
+	}
+	
+	.test2 .tabs{
+		position:absolute;
+		top:0;
+		left:0;
+		z-index:20;
+	}
+	.test2 .tabs ul{
+		margin:0;
+		padding:0;
+	}
+	.test2 .tabs li{
+		float:left;
+		list-style:none;
+		margin:0 5px 0 0;
+		padding:0;
+	}
+	.test2 .tabs li a{
+		background-color:#fff;
+		border-top-left-radius:5px;
+		border-top-right-radius:5px;
+		-moz-border-radius-topleft:5px;
+		-moz-border-radius-topright:5px;
+		border:solid 1px #ccc;
+		border-bottom:0;
+		color:#666;
+		display:block;
+		font-size:10px;
+		height:20px;
+		padding:0 4px;
+		text-decoration:none;
+	}
+	.test2 .tabs li.dojoxRotatorSelected a{
+		background-color:#e5e5e5;
+		color:#000;
+	}
+	
+	.test2 .dots{
+		position:absolute;
+		right:5px;
+		top:25px;
+		z-index:20;
+	}
+	.test2 .dots ul{
+		margin:0;
+		padding:0;
+	}
+	.test2 .dots li{
+		float:left;
+		list-style:none;
+		margin:0;
+		padding:0;
+	}
+	.test2 .dots a span{
+		display:none;
+	}
+	.test2 .dots .dojoxRotatorNumber a{
+		display:block;
+		width:10px;
+		height:10px;
+		background:url(images/rotator_dots.png) no-repeat 0 0;
+	}
+	.test2 .dots .dojoxRotatorSelected a{
+		background:url(images/rotator_dots.png) no-repeat 0 -10px;
+	}
+	
+	.test2 .pager1{
+		background:url(images/rotator_bg.gif) no-repeat 0 0;
+		bottom:5px;
+		padding:3px 0 0 12px;
+		position:absolute;
+		left:5px;
+		z-index:20;
+	}
+	.test2 .pager1 ul{
+		height:16px;
+		margin:0;
+		padding:0;
+		width:97px;
+	}
+	.test2 .pager1 li{
+		float:left;
+		line-height:12px;
+		list-style:none;
+		margin:0;
+		padding:0;
+	}
+	.test2 .pager1 a{
+		color:#fff;
+		font-size:10px;
+		text-decoration:none;
+	}
+	.test2 .pager1 li.dojoxRotatorIcon a{
+		display:block;
+		width:14px;
+		height:14px;
+	}
+	.test2 .pager1 li.dojoxRotatorPrev a{
+		background:url(images/rotator_icons.gif) no-repeat 0 0;
+	}
+	.test2 .pager1 li.dojoxRotatorPrev a span,
+	.test2 .pager1 li.dojoxRotatorNext a span{
+		display:none;
+	}
+	.test2 .pager1 li.dojoxRotatorNext a{
+		background:url(images/rotator_icons.gif) no-repeat -14px 0;
+	}
+	.test2 .pager1 li.dojoxRotatorNumber a{
+		color:#ccc;
+		padding:0 4px;
+	}
+	.test2 .pager1 li.dojoxRotatorSelected a{
+		color:#fff;
+		font-weight:bold;
+	}
+	
+	.test2 .pager2{
+		background:url(images/rotator_bg.gif) no-repeat 0 0;
+		bottom:5px;
+		padding:3px 0 0 12px;
+		position:absolute;
+		right:5px;
+		z-index:20;
+	}
+	.test2 .pager2 ul{
+		height:16px;
+		margin:0;
+		padding:0;
+		width:97px;
+	}
+	.test2 .pager2 li{
+		float:left;
+		list-style:none;
+		margin:0;
+		padding:0;
+	}
+	.test2 .pager2 li.dojoxRotatorIcon a{
+		display:block;
+		width:14px;
+		height:14px;
+	}
+	.test2 .pager2 li.dojoxRotatorPrev a{
+		background:url(images/rotator_icons.gif) no-repeat 0 0;
+	}
+	.test2 .pager2 li.dojoxRotatorPlay a{
+		background:url(images/rotator_icons.gif) no-repeat -28px 0;
+	}
+	.test2 .pager2 li.dojoxRotatorPause a{
+		background:url(images/rotator_icons.gif) no-repeat -42px 0;
+	}
+	.test2 .pager2 li.dojoxRotatorNext a{
+		background:url(images/rotator_icons.gif) no-repeat -14px 0;
+	}
+	.test2 .pager2 li.dojoxRotatorInfo{
+		color:#e5e5e5;
+		font-size:10px;
+		line-height:12px;
+		padding:0 4px 0 7px;
+		width:32px;
+	}
+	.test2 .pager2 li a span{
+		display:none;
+	}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad:true, isDebug:true"></script>
+	<script type="text/javascript">
+	dojo.require("dojo.parser");
+	dojo.require("dojox.widget.AutoRotator");
+	dojo.require("dojox.widget.rotator.Controller");
+	dojo.require("dojox.widget.rotator.Fade");
+	dojo.require("dojox.widget.rotator.Pan");
+	</script>
+</head>
+<body>
+
+	<h1 class="testTitle">dojox.widget.rotator.Controller Test</h1>
+	
+	<h2>Controller Commands Test</h2>
+	
+	<div class="test1">
+		
+		<div dojoType="dojox.widget.AutoRotator" class="rotator" jsId="myRotator" duration="1000" transition="dojox.widget.rotator.crossFade">
+			<div class="pane" title="Nexaweb/Renkoo">
+				<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+				<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+			</div>
+			<div class="pane" title="Sitepen/Tibco">
+				<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+				<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+			</div>
+			<div class="pane" title="Webtide/OpenLaszlo">
+				<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+				<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+			</div>
+			<div class="pane" title="Sun/Google">
+				<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+				<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+			</div>
+			<div class="pane" title="Aptana/AOL">
+				<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+				<a href="http://www.aol.com" target="_new"><img src="images/rotator_aol.png" width="130" alt="AOL"/></a>
+			</div>
+			<div class="pane" title="IBM/Zend">
+				<a href="http://www.ibm.com" target="_new"><img src="images/rotator_ibm.png" width="100" alt="IBM"/></a>
+				<a href="http://www.zend.com/" target="_new"><img src="images/rotator_zend.png" width="130" alt="Zend"/></a>
+			</div>
+			<div class="pane" title="BEA/Uxebu">
+				<a href="http://www.bea.com" target="_new"><img src="images/rotator_bea.png" width="80" alt="BEA"/></a>
+				<a href="http://www.uxebu.com" target="_new"><img src="images/rotator_uxebu.png" width="120" alt="Uxebu"/></a>
+			</div>
+			<div class="pane"> <!-- no title for testing -->
+				<a href="http://www.wavemaker.com" target="_new"><img src="images/rotator_wavemaker.png" width="130" alt="WaveMaker"/></a>
+				<a href="http://www.aptana.com" target="_new"><img src="images/rotator_aptana.png" width="130" alt="Aptana"/></a>
+			</div>
+		</div>
+
+		<table>
+			<tr>
+				<td>
+					<h3>Default</h3>
+					<div dojoType="dojox.widget.rotator.Controller" rotator="myRotator"></div>
+				</td>
+				<td>
+					<h3>Prev, Next</h3>
+					<div dojoType="dojox.widget.rotator.Controller" rotator="myRotator" commands="prev,next"></div>
+				</td>
+				<td>
+					<h3>Prev, Play/Pause, Next</h3>
+					<div dojoType="dojox.widget.rotator.Controller" rotator="myRotator" commands="prev,play/pause,next"></div>
+				</td>
+				<td>
+					<h3>Prev, Numbers, Next</h3>
+					<div dojoType="dojox.widget.rotator.Controller" rotator="myRotator" commands="prev,#,next"></div>
+				</td>
+				<td>
+					<h3>Titles</h3>
+					<div dojoType="dojox.widget.rotator.Controller" rotator="myRotator" commands="titles"></div>
+					<div>Note: Last pane has no title and<br>uses default.</div>
+				</td>
+				<td>
+					<h3>Play/Pause, Info</h3>
+					<div dojoType="dojox.widget.rotator.Controller" rotator="myRotator" commands="play/pause,info"></div>
+				</td>
+				<td>
+					<h3>Numbers, Info</h3>
+					<div dojoType="dojox.widget.rotator.Controller" rotator="myRotator" commands="#,info"></div>
+				</td>
+				<td>
+					<h3>Info</h3>
+					<div dojoType="dojox.widget.rotator.Controller" rotator="myRotator" commands="info"></div>
+				</td>
+			</tr>
+		</table>
+		
+	</div>
+	
+	<h2>Styled Controllers</h2>
+	
+	<div class="test2">
+	
+		<div class="rotatorContainer">
+			
+			<div dojoType="dojox.widget.AutoRotator" class="rotator" jsId="myRotator2" duration="1000" transition="dojox.widget.rotator.pan"
+					transitionParams="quick:true,continuous:true" pauseOnManualChange="true" suspendOnHover="true">
+				<div class="pane" title="Nexaweb/Renkoo">
+					<a href="http://www.nexaweb.com" target="_new"><img src="images/rotator_nexaweb.png" width="130" alt="Nexaweb"/></a>
+					<a href="http://www.renkoo.com" target="_new"><img src="images/rotator_renkoo.png" width="130" alt="Renkoo"/></a>
+				</div>
+				<div class="pane" title="Sitepen/Tibco">
+					<a href="http://www.sitepen.com" target="_new"><img src="images/rotator_sitepen.png" width="130" alt="Sitepen"/></a>
+					<a href="http://www.tibco.com" target="_new"><img src="images/rotator_tibco.png" width="130" alt="Tibco"/></a>
+				</div>
+				<div class="pane" title="Webtide/OpenLaszlo">
+					<a href="http://www.webtide.com/" target="_new"><img src="images/rotator_webtide.png" width="130" alt="Webtide"/></a>
+					<a href="http://www.openlaszlo.com" target="_new"><img src="images/rotator_openlaszlo.png" width="150" alt="OpenLaszlo"/></a>
+				</div>
+				<div class="pane" title="Sun/Google">
+					<a href="http://www.sun.com" target="_new"><img src="images/rotator_sun.png" width="130" alt="Sun"/></a>
+					<a href="http://www.google.com" target="_new"><img src="images/rotator_google.png" width="130" alt="Google"/></a>
+				</div>
+			</div>
+			
+			<div dojoType="dojox.widget.rotator.Controller" class="tabs" rotator="myRotator2" commands="titles"></div>
+			
+			<div dojoType="dojox.widget.rotator.Controller" class="dots" rotator="myRotator2" commands="#"></div>
+			
+			<div dojoType="dojox.widget.rotator.Controller" class="pager1" rotator="myRotator2" commands="prev,#,next"></div>
+			
+			<div dojoType="dojox.widget.rotator.Controller" class="pager2" rotator="myRotator2" commands="prev,play/pause,info,next"></div>
+			
+		</div>
+		
+	</div>
+	
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Rotator_ThumbnailController.html b/dojox/widget/tests/test_Rotator_ThumbnailController.html
new file mode 100644
index 0000000..28ea74a
--- /dev/null
+++ b/dojox/widget/tests/test_Rotator_ThumbnailController.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>dojox.widget.rotator.ThumbnailController Test</title>
+	<style type="text/css">
+	@import "../../../dojo/resources/dojo.css";
+	@import "../../../dijit/tests/css/dijitTests.css";
+
+	.rotator{
+		background-color:#fff;
+		border:solid 1px #e5e5e5;
+		width:500px;
+		height:375px;
+		overflow:hidden;
+	}
+	.rotator img{
+		background-color:#fff;
+		width:500px;
+		height:375px;
+		overflow:hidden;
+	}
+	.dojoxRotatorThumb{
+		display:inline-block;
+		width:240px;
+		height:180px;
+		margin:2px;
+	}
+	.dojoxRotatorThumb img{
+		width:240px;
+		height:180px;
+	}
+	.dojoxRotatorThumbSelected{
+		border:solid 2px #00f;
+		margin:0;
+	}
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="parseOnLoad:true, isDebug:true"></script>
+	<script type="text/javascript">
+	dojo.require("dojo.parser");
+	dojo.require("dojox.widget.AutoRotator");
+	dojo.require("dojox.widget.rotator.Fade");
+	dojo.require("dojox.widget.rotator.ThumbnailController");
+	</script>
+</head>
+<body>
+
+	<h1 class="testTitle">dojox.widget.rotator.ThumbnailController Test</h1>
+	
+	<div class="test1">
+		
+		<div dojoType="dojox.widget.AutoRotator" class="rotator" jsId="myRotator" duration="1000" transition="dojox.widget.rotator.crossFade">
+			<img src="../../image/tests/images/chris1_lg.jpg" thumbsrc="../../image/tests/images/chris1_sm.jpg" alt="Image 1"/>
+			<img src="../../image/tests/images/chris2_lg.jpg" thumbsrc="../../image/tests/images/chris2_sm.jpg" alt="Image 2"/>
+			<img src="../../image/tests/images/chris3_lg.jpg" thumbsrc="../../image/tests/images/chris3_sm.jpg" alt="Image 3"/>
+		</div>
+
+		<div dojoType="dojox.widget.rotator.ThumbnailController" rotator="myRotator"></div>
+		
+	</div>
+	
+</body>
+</html>
diff --git a/dojox/widget/tests/test_SortList.html b/dojox/widget/tests/test_SortList.html
new file mode 100644
index 0000000..dcc4cf8
--- /dev/null
+++ b/dojox/widget/tests/test_SortList.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojox SortList Test</title>
+	
+	<!-- required: a default theme file -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../SortList/SortList.css">
+	
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+	</style>
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	<!-- debugging -->
+	<script type="text/javascript" src="../SortList.js"></script>
+	
+	<script type="text/javascript">
+		dojo.require("dojox.widget.SortList");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dojo.data.ItemFileReadStore"); 
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+	</script>
+</head>
+
+<body class="tundra">
+
+	<h1 class="testTitle">Dojox SortList test</h1>
+
+	<div dojoType="dojo.data.ItemFileReadStore" url="../../../dijit/tests/_data/countries.json" jsId="stateStore"></div>
+	
+	<h3>Simple sortable example</h3>
+	<ul dojoType="dojox.widget.SortList" store="stateStore" title="sortable List" style="width:200px; height:200px;"></ul>
+
+	<h3>Children of a TabContainer</h3>
+	<div dojoType="dijit.layout.TabContainer" style="width:300px; height:300px;">
+		<div dojoType="dojox.widget.SortList" store="stateStore" title="list 1" heading="countires"></div>
+		<div dojoType="dojox.widget.SortList" store="stateStore" title="list 2" heading="states"></div>
+		<div dojoType="dojox.widget.SortList" store="stateStore" title="closable" heading="countries" closable="true"></div>
+	</div>
+
+	<h3>Child of a BorderContainer</h3>
+	<div dojoType="dijit.layout.BorderContainer" design="sidebar" gutters="true" liveSplitters="true" style="border: 1px solid #ccc; width:600px; height:200px;">
+		<div dojoType="dojox.widget.SortList" splitter="true" store="stateStore" title="list 1" region="leading" style="width: 33%"></div>
+		<div dojoType="dojox.widget.SortList" splitter="true" store="stateStore" title="list 2" region="center"></div>
+		<div dojoType="dojox.widget.SortList" splitter="true" store="stateStore" title="closable" region="trailing" style="width: 33%"></div>
+	</div>
+	
+	<br>
+	<h3>Raw, degradable UL list:</h3>
+	<ul dojoType="dojox.widget.SortList" title="SortList From Markup" sortable="false" style="width:200px; height:200px;">
+		<li>one</li>
+		<li>two</li>
+		<li>three</li>
+		<li>four</li>
+		<li>five</li>
+		<li>six</li>
+		<li>four</li>
+		<li>five</li>
+		<li>six</li>
+		<li>four</li>
+		<li>five</li>
+		<li>six</li>
+		<li>four</li>
+		<li>five</li>
+		<li>six</li>
+	</ul>
+
+	<h3>normal ul:</h3>
+		<ul style="width:200px; height:200px;">
+			<li>one</li><li>one</li><li>one</li><li>one</li><li>one</li><li>one</li><li>one</li><li>one</li>
+		</ul>
+	
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Standby.html b/dojox/widget/tests/test_Standby.html
new file mode 100755
index 0000000..47dba5e
--- /dev/null
+++ b/dojox/widget/tests/test_Standby.html
@@ -0,0 +1,388 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+	<title>Testing the Standby widget</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/soria/soria.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dojox/grid/resources/soriaGrid.css";
+
+		.curvedClass {
+			background-color: darkblue;
+			width: 250px;
+			height: 250px;
+			-moz-border-radius: 15px 15px 15px 15px; 
+			-webkit-border-radius: 15px;"        
+		}
+	</style>
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" djconfig="parseOnLoad:true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.widget.Standby");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+		dojo.require("dijit.Dialog");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileReadStore");
+
+		var connects = [];
+
+		function init() {
+			var button1 = dijit.byId("overlay1Button1");
+			var button2 = dijit.byId("overlay1Button2");
+			var overlay1= dijit.byId("standby1");
+			connects.push(dojo.connect(button1, "onClick", function(){overlay1.show()}));
+			connects.push(dojo.connect(button2, "onClick", function(){overlay1.hide()}));
+
+			var button3 = dijit.byId("overlay2Button1");
+			var button4 = dijit.byId("overlay2Button2");
+			var overlay2= dijit.byId("standby2");
+			connects.push(dojo.connect(button3, "onClick", function(){overlay2.show()}));
+			connects.push(dojo.connect(button4, "onClick", function(){overlay2.hide()}));
+
+			var button5 = dijit.byId("overlay3Button1");
+			var button6 = dijit.byId("overlay3Button2");
+			var overlay3= dijit.byId("standby3");
+			connects.push(dojo.connect(button5, "onClick", function(){overlay3.show()}));
+			connects.push(dojo.connect(button6, "onClick", function(){overlay3.hide()}));
+
+			var button7 = dijit.byId("overlay4Button1");
+			var button8 = dijit.byId("overlay4Button2");
+			var overlay4= dijit.byId("standby4");
+			connects.push(dojo.connect(button7, "onClick", function(){overlay4.show()}));
+			connects.push(dojo.connect(button8, "onClick", function(){overlay4.hide()}));
+
+			var button9 = dijit.byId("overlay5Button1");
+			var button10 = dijit.byId("overlay5Button2");
+			var overlay5= dijit.byId("standby5");
+			connects.push(dojo.connect(button9, "onClick", function(){overlay5.show()}));
+			connects.push(dojo.connect(button10, "onClick", function(){overlay5.hide()}));
+
+			var button11 = dijit.byId("overlay6Button1");
+			var button12 = dijit.byId("overlay6Button2");
+			var overlay6= dijit.byId("standby6");
+			connects.push(dojo.connect(button11, "onClick", function(){overlay6.show()}));
+			connects.push(dojo.connect(button12, "onClick", function(){overlay6.hide()}));
+
+			var button13 = dijit.byId("overlay7Button1");
+			var button14 = dijit.byId("overlay7Button2");
+			var overlay7= dijit.byId("standby7");
+			connects.push(dojo.connect(button13, "onClick", function(){overlay7.show()}));
+			connects.push(dojo.connect(button14, "onClick", function(){overlay7.hide()}));
+
+			var button15 = dijit.byId("overlay8Button1");
+			var button16 = dijit.byId("overlay8Button2");
+			var overlay8= dijit.byId("standby8");
+			connects.push(dojo.connect(button15, "onClick", function(){overlay8.show()}));
+			connects.push(dojo.connect(button16, "onClick", function(){overlay8.hide()}));
+
+			var button17 = dijit.byId("overlay9Button1");
+			var button18 = dijit.byId("overlay9Button2");
+			var overlay9= dijit.byId("standby9");
+			connects.push(dojo.connect(button17, "onClick", function(){overlay9.show()}));
+			connects.push(dojo.connect(button18, "onClick", function(){overlay9.hide()}));
+
+			var button19 = dijit.byId("overlay10Button1");
+			var button20 = dijit.byId("overlay10Button2");
+			var overlay10= dijit.byId("standby10");
+			connects.push(dojo.connect(button19, "onClick", function(){
+				overlay10.show();
+				var moveDiv = dojo.byId("overlayTarget10");
+				var moveAnim = dojo.animateProperty({node: moveDiv, properties: {marginLeft: {start: 0, end: 300}}});
+				moveAnim.play();
+			}));
+			connects.push(dojo.connect(button20, "onClick", function(){
+				var moveDiv = dojo.byId("overlayTarget10");
+				var moveAnim = dojo.animateProperty({node: moveDiv, properties: {marginLeft: {start: 300, end: 0}}, onEnd: function(){overlay10.hide()}});
+				moveAnim.play();
+			}));
+
+			var button21 = dijit.byId("overlay11Button1");
+			var button22 = dijit.byId("overlay11Button2");
+			var overlay11= dijit.byId("standby11");
+			connects.push(dojo.connect(button21, "onClick", function(){overlay11.show()}));
+			connects.push(dojo.connect(button22, "onClick", function(){overlay11.hide()}));
+			
+			var button23 = dijit.byId("overlay12Button1");
+			var button24 = dijit.byId("overlay12Button2");
+			var overlay12= dijit.byId("standby12");
+			connects.push(dojo.connect(button23, "onClick", function(){overlay12.show()}));
+			connects.push(dojo.connect(button24, "onClick", function(){overlay12.hide()}));
+
+			var button25 = dijit.byId("overlay13Button1");
+			var button26 = dijit.byId("overlay13Button2");
+			var overlay13= dijit.byId("standby13");
+			connects.push(dojo.connect(button25, "onClick", function(){overlay13.show()}));
+			connects.push(dojo.connect(button26, "onClick", function(){overlay13.hide()}));
+
+			var button27 = dijit.byId("overlay14Button1");
+			var button28 = dijit.byId("overlay14Button2");
+			var overlay14= dijit.byId("standby14");
+			connects.push(dojo.connect(button27, "onClick", function(){overlay14.show()}));
+			connects.push(dojo.connect(button28, "onClick", function(){overlay14.hide()}));
+
+			var button29 = dijit.byId("overlay15Button1");
+			var button30 = dijit.byId("overlay15Button2");
+			var overlay15= dijit.byId("standby15");
+			connects.push(dojo.connect(button29, "onClick", function(){overlay15.show()}));
+			connects.push(dojo.connect(button30, "onClick", function(){overlay15.hide()}));
+
+			var button31 = dijit.byId("overlay16Button1");
+			var button32 = dijit.byId("overlay16Button2");
+			var overlay16= dijit.byId("standby16");
+			connects.push(dojo.connect(button31, "onClick", function(){overlay16.show()}));
+			connects.push(dojo.connect(button32, "onClick", function(){overlay16.hide()}));
+
+			var button33 = dijit.byId("overlay17Button1");
+			var button34 = dijit.byId("overlay17Button2");
+			var overlay17= dijit.byId("standby17");
+			connects.push(dojo.connect(button33, "onClick", function(){overlay17.show()}));
+			connects.push(dojo.connect(button34, "onClick", function(){overlay17.hide()}));
+
+			var showCount = 0;
+			var button35 = dijit.byId("overlay18Button1");
+			var button36 = dijit.byId("overlay18Button2");
+			var overlay18= dijit.byId("standby18");
+			connects.push(dojo.connect(button35, "onClick", function(){
+				showCount++;
+				console.log(overlay18.attr("text"));
+				overlay18.attr("text", "Shown: " + showCount);
+				overlay18.show()}));
+			connects.push(dojo.connect(button36, "onClick", function(){overlay18.hide()}));
+
+			var colors = ["red", "green", "gray", "black", "purple"]
+			var cPos = 0;
+			var button37 = dijit.byId("overlay19Button1");
+			var button38 = dijit.byId("overlay19Button2");
+			var overlay19= dijit.byId("standby19");
+			connects.push(dojo.connect(button37, "onClick", function(){
+				console.log(overlay19.attr("color"));
+				overlay19.attr("color", colors[cPos]);
+				cPos++;
+				if(cPos === colors.length - 1){
+					cPos = 0;
+				}
+				overlay19.show()}));
+			connects.push(dojo.connect(button38, "onClick", function(){overlay19.hide()}));
+			dijit.byId("dialog").show();
+
+			var button39 = dijit.byId("overlay20Button1");
+			var overlay20= dijit.byId("standby20");
+			connects.push(dojo.connect(button39, "onClick", function(){
+				overlay20.show();
+				setTimeout(function(){
+	                overlay20.hide();
+				}, 5000);
+			}));
+		}
+		dojo.addOnLoad(init);
+
+		//Cleanup, so I can check for leaks in the widget itself.
+		dojo.addOnUnload(function(){
+			var i;
+			for(i = 0; i < connects.length; i++){
+				dojo.disconnect(connects[i]);
+			}
+		});
+
+	</script>
+	
+</head>
+<body class="soria" id="bodyId">
+	
+	<h1 class="testTitle">dojox.widget.Standby</h1>
+
+	<h3>Testing a basic on a div contained in a scrolling div</h3>
+	<button id ="overlay14Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay14Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div style="width: 250px; height: 100px; overflow: auto">
+		<br>
+		<br>
+		<br>
+		<br>
+		<br>
+	<div id ="overlayTarget14" style="width: 200px; height: 200px; background-color: darkblue;"></div>
+		<div style="width: 400px; height: 5px"></div>
+		<br>
+		<br>
+		<br>
+		<br>
+		<br>
+	</div>
+	<div id ="standby14" target="overlayTarget14" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<br>
+	<br>
+	<br> 
+	<h3>Testing an overlay of the entire document body.</h3>
+	<button id ="overlay20Button1" dojoType="dijit.form.Button">Click to show the standby overlay on body for 5 seconds!</button>
+	<div id ="standby20" target="bodyId" dojoType="dojox.widget.Standby" zIndex="1000"></div>
+
+	<hr>
+	<h3>Testing a basic overlay</h3>
+	<button id ="overlay1Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay1Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget1" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby1" target="overlayTarget1" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+
+	<h3>Testing a basic overlay on a positioned div</h3>
+	<button id ="overlay2Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay2Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget2" style="position: absolute; width: 200px; height: 100px; background-color: darkblue; top: 500px; left: 500px;"></div>
+	<div id ="standby2" target="overlayTarget2" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a basic overlay on a dijit</h3>
+	<button id ="overlay3Button1" dojoType="dijit.form.Button">Really long button!!!!!  Click to show the standby overlay on the button.</button>
+	<br>
+	<button id ="overlay3Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="standby3" target="overlay3Button1" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a basic on a nested div</h3>
+	<button id ="overlay4Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay4Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div><div><div><div id ="overlayTarget4" style="width: 200px; height: 100px; background-color: darkblue;"></div></div></div></div>
+	<div id ="standby4" target="overlayTarget4" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a different image</h3>
+	<button id ="overlay5Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay5Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget5" style="width: 500px; height: 500px; background-color: darkgray;"></div>
+	<div id ="standby5" target="overlayTarget5" dojoType="dojox.widget.Standby" image="images/busy.gif"></div>
+	<hr>
+
+	<h3>Testing an overlay on a div that has curved borders (CSS styles, Firefox and Webkit (Safari), only)</h3>
+	<button id ="overlay6Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay6Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget6" style="width: 200px; height: 100px; background-color: darkblue; -moz-border-radius: 15px; -webkit-border-radius: 15px;"></div>
+	<div id ="standby6" target="overlayTarget6" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing an overlay on a div that has curved borders (CSS styles, Firefox and Webkit (Safari), only, margined to the center) and a different color for the overlay</h3>
+	<button id ="overlay7Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay7Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget7" style="width: 200px; height: 100px; background-color: darkblue; -moz-border-radius: 15px; -webkit-border-radius: 15px; margin: auto"></div>
+	<div id ="standby7" target="overlayTarget7" dojoType="dojox.widget.Standby" color="lightblue"></div>
+	<hr>
+
+
+	<h3>Testing an overlay on a grid</h3>
+	<button id ="overlay8Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay8Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div jsId="ifsStore" dojoType="dojo.data.ItemFileReadStore" url="../../../dijit/tests/_data/countries.json"></div>
+	<table id ="overlayTarget8" dojoType="dojox.grid.DataGrid" style="width: 500px; height: 300px; margin: auto" store="ifsStore" query="{}">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+	<div id ="standby8" target="overlayTarget8" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+
+	<h3>Testing an overlay on a dijit.Tree</h3>
+	<button id ="overlay9Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay9Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div jsId="ifsStore2" dojoType="dojo.data.ItemFileReadStore" url="../../../dijit/tests/_data/countries.json"></div>
+	<div dojoType="dijit.tree.ForestStoreModel" jsId="continentModel" store="ifsStore2" query="{type:'continent'}" rootId="continentRoot" rootLabel="Continents" childrenAttrs="children"></div>
+	<div id ="overlayTarget9" dojoType="dijit.Tree" style="width: 30%" model="continentModel" query="{}"></div>
+	<div id ="standby9" target="overlayTarget9" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing overlay following a div as it moves (And with some whacky margins that need to be accounted for)</h3>
+	<button id ="overlay10Button1" dojoType="dijit.form.Button">Click to show the standby overlay and move the overlayed div.</button>
+	<br>
+	<button id ="overlay10Button2" dojoType="dijit.form.Button">Click to scoot the div back and hide the standby overlay.</button>
+	<div style="width: 100%;"><div id ="overlayTarget10" style="width: 200px; height: 100px; background-color: darkblue; margin-right: 100px; margin-top: 100px; margin-bottom: 100px;"></div></div>
+	<div id ="standby10" target="overlayTarget10" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing an overlay with class set styles for curves (Firefox, safari only).</h3>
+	<button id ="overlay11Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay11Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget11" class="curvedClass"></div>
+	<div id ="standby11" target="overlayTarget11" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a basic on a zIndex'ed div</h3>
+	<button id ="overlay13Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay13Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget13" style="width: 200px; height: 100px; background-color: darkblue; z-index: 200"></div>
+	<div id ="standby13" target="overlayTarget13" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+   	<h3>Testing that this still works in a dialog after zIndex changes</h3>
+	<div dojoType="dijit.Dialog" id="dialog">
+		<button id ="overlay15Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+		<br>
+		<button id ="overlay15Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+		<div id ="overlayTarget15" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+		<div id ="standby15" target="overlayTarget15" dojoType="dojox.widget.Standby" zIndex="1000"></div>
+	</div>
+   	<hr>
+
+	<h3>Testing a basic on a node, using only centered text.</h3>
+	<button id ="overlay16Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay16Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget16" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby16" target="overlayTarget16" dojoType="dojox.widget.Standby" centerIndicator="text"></div>
+	<hr>
+
+	<h3>Testing a basic on a node, using only centered text that was customized.</h3>
+	<button id ="overlay17Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay17Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget17" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby17" target="overlayTarget17" dojoType="dojox.widget.Standby" centerIndicator="text" text="<span style='color: red; font-weight: bold; font-style: italic;'>WAIT, FOO!</span>"></div>
+	<hr>
+
+	<h3>Testing a basic on a node, using only centered text that is changed with each display.</h3>
+	<button id ="overlay18Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay18Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget18" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby18" target="overlayTarget18" dojoType="dojox.widget.Standby" centerIndicator="text" text="<span style='color: red; font-weight: bold; font-style: italic;'>WAIT, FOO!</span>"></div>
+	<hr>
+
+	<h3>Testing a basic on a node, using only centered text, and with a background color that changes with each show</h3>
+	<button id ="overlay19Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay19Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget19" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby19" target="overlayTarget19" dojoType="dojox.widget.Standby" centerIndicator="text" text="<span style='color: red; font-weight: bold; font-style: italic;'>Watch Background</span>"></div>
+	<hr>
+
+	<h3>Testing the widget in a relatively positioned block.  This has caused problems, verifying the fix of reparenting to document.body works.</h3>
+	<button id ="overlay12Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay12Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div style="position: relative; top: 50px; left: 50px;">
+		<div id ="overlayTarget12" class="curvedClass"></div>
+		<div id ="standby12" target="overlayTarget12" dojoType="dojox.widget.Standby"></div>
+	</div>        
+
+
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Standby_quirks.html b/dojox/widget/tests/test_Standby_quirks.html
new file mode 100755
index 0000000..1b82fc6
--- /dev/null
+++ b/dojox/widget/tests/test_Standby_quirks.html
@@ -0,0 +1,386 @@
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+	<title>Testing the Standby widget</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/soria/soria.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dojox/grid/resources/soriaGrid.css";
+
+		.curvedClass {
+			background-color: darkblue;
+			width: 250px;
+			height: 250px;
+			-moz-border-radius: 15px 15px 15px 15px; 
+			-webkit-border-radius: 15px;"        
+		}
+	</style>
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" djconfig="parseOnLoad:true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.widget.Standby");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+		dojo.require("dijit.Dialog");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileReadStore");
+
+		var connects = [];
+
+		function init() {
+			var button1 = dijit.byId("overlay1Button1");
+			var button2 = dijit.byId("overlay1Button2");
+			var overlay1= dijit.byId("standby1");
+			connects.push(dojo.connect(button1, "onClick", function(){overlay1.show()}));
+			connects.push(dojo.connect(button2, "onClick", function(){overlay1.hide()}));
+
+			var button3 = dijit.byId("overlay2Button1");
+			var button4 = dijit.byId("overlay2Button2");
+			var overlay2= dijit.byId("standby2");
+			connects.push(dojo.connect(button3, "onClick", function(){overlay2.show()}));
+			connects.push(dojo.connect(button4, "onClick", function(){overlay2.hide()}));
+
+			var button5 = dijit.byId("overlay3Button1");
+			var button6 = dijit.byId("overlay3Button2");
+			var overlay3= dijit.byId("standby3");
+			connects.push(dojo.connect(button5, "onClick", function(){overlay3.show()}));
+			connects.push(dojo.connect(button6, "onClick", function(){overlay3.hide()}));
+
+			var button7 = dijit.byId("overlay4Button1");
+			var button8 = dijit.byId("overlay4Button2");
+			var overlay4= dijit.byId("standby4");
+			connects.push(dojo.connect(button7, "onClick", function(){overlay4.show()}));
+			connects.push(dojo.connect(button8, "onClick", function(){overlay4.hide()}));
+
+			var button9 = dijit.byId("overlay5Button1");
+			var button10 = dijit.byId("overlay5Button2");
+			var overlay5= dijit.byId("standby5");
+			connects.push(dojo.connect(button9, "onClick", function(){overlay5.show()}));
+			connects.push(dojo.connect(button10, "onClick", function(){overlay5.hide()}));
+
+			var button11 = dijit.byId("overlay6Button1");
+			var button12 = dijit.byId("overlay6Button2");
+			var overlay6= dijit.byId("standby6");
+			connects.push(dojo.connect(button11, "onClick", function(){overlay6.show()}));
+			connects.push(dojo.connect(button12, "onClick", function(){overlay6.hide()}));
+
+			var button13 = dijit.byId("overlay7Button1");
+			var button14 = dijit.byId("overlay7Button2");
+			var overlay7= dijit.byId("standby7");
+			connects.push(dojo.connect(button13, "onClick", function(){overlay7.show()}));
+			connects.push(dojo.connect(button14, "onClick", function(){overlay7.hide()}));
+
+			var button15 = dijit.byId("overlay8Button1");
+			var button16 = dijit.byId("overlay8Button2");
+			var overlay8= dijit.byId("standby8");
+			connects.push(dojo.connect(button15, "onClick", function(){overlay8.show()}));
+			connects.push(dojo.connect(button16, "onClick", function(){overlay8.hide()}));
+
+			var button17 = dijit.byId("overlay9Button1");
+			var button18 = dijit.byId("overlay9Button2");
+			var overlay9= dijit.byId("standby9");
+			connects.push(dojo.connect(button17, "onClick", function(){overlay9.show()}));
+			connects.push(dojo.connect(button18, "onClick", function(){overlay9.hide()}));
+
+			var button19 = dijit.byId("overlay10Button1");
+			var button20 = dijit.byId("overlay10Button2");
+			var overlay10= dijit.byId("standby10");
+			connects.push(dojo.connect(button19, "onClick", function(){
+				overlay10.show();
+				var moveDiv = dojo.byId("overlayTarget10");
+				var moveAnim = dojo.animateProperty({node: moveDiv, properties: {marginLeft: {start: 0, end: 300}}});
+				moveAnim.play();
+			}));
+			connects.push(dojo.connect(button20, "onClick", function(){
+				var moveDiv = dojo.byId("overlayTarget10");
+				var moveAnim = dojo.animateProperty({node: moveDiv, properties: {marginLeft: {start: 300, end: 0}}, onEnd: function(){overlay10.hide()}});
+				moveAnim.play();
+			}));
+
+			var button21 = dijit.byId("overlay11Button1");
+			var button22 = dijit.byId("overlay11Button2");
+			var overlay11= dijit.byId("standby11");
+			connects.push(dojo.connect(button21, "onClick", function(){overlay11.show()}));
+			connects.push(dojo.connect(button22, "onClick", function(){overlay11.hide()}));
+			
+			var button23 = dijit.byId("overlay12Button1");
+			var button24 = dijit.byId("overlay12Button2");
+			var overlay12= dijit.byId("standby12");
+			connects.push(dojo.connect(button23, "onClick", function(){overlay12.show()}));
+			connects.push(dojo.connect(button24, "onClick", function(){overlay12.hide()}));
+
+			var button25 = dijit.byId("overlay13Button1");
+			var button26 = dijit.byId("overlay13Button2");
+			var overlay13= dijit.byId("standby13");
+			connects.push(dojo.connect(button25, "onClick", function(){overlay13.show()}));
+			connects.push(dojo.connect(button26, "onClick", function(){overlay13.hide()}));
+
+			var button27 = dijit.byId("overlay14Button1");
+			var button28 = dijit.byId("overlay14Button2");
+			var overlay14= dijit.byId("standby14");
+			connects.push(dojo.connect(button27, "onClick", function(){overlay14.show()}));
+			connects.push(dojo.connect(button28, "onClick", function(){overlay14.hide()}));
+
+			var button29 = dijit.byId("overlay15Button1");
+			var button30 = dijit.byId("overlay15Button2");
+			var overlay15= dijit.byId("standby15");
+			connects.push(dojo.connect(button29, "onClick", function(){overlay15.show()}));
+			connects.push(dojo.connect(button30, "onClick", function(){overlay15.hide()}));
+
+			var button31 = dijit.byId("overlay16Button1");
+			var button32 = dijit.byId("overlay16Button2");
+			var overlay16= dijit.byId("standby16");
+			connects.push(dojo.connect(button31, "onClick", function(){overlay16.show()}));
+			connects.push(dojo.connect(button32, "onClick", function(){overlay16.hide()}));
+
+			var button33 = dijit.byId("overlay17Button1");
+			var button34 = dijit.byId("overlay17Button2");
+			var overlay17= dijit.byId("standby17");
+			connects.push(dojo.connect(button33, "onClick", function(){overlay17.show()}));
+			connects.push(dojo.connect(button34, "onClick", function(){overlay17.hide()}));
+
+			var showCount = 0;
+			var button35 = dijit.byId("overlay18Button1");
+			var button36 = dijit.byId("overlay18Button2");
+			var overlay18= dijit.byId("standby18");
+			connects.push(dojo.connect(button35, "onClick", function(){
+				showCount++;
+				console.log(overlay18.attr("text"));
+				overlay18.attr("text", "Shown: " + showCount);
+				overlay18.show()}));
+			connects.push(dojo.connect(button36, "onClick", function(){overlay18.hide()}));
+
+			var colors = ["red", "green", "gray", "black", "purple"]
+			var cPos = 0;
+			var button37 = dijit.byId("overlay19Button1");
+			var button38 = dijit.byId("overlay19Button2");
+			var overlay19= dijit.byId("standby19");
+			connects.push(dojo.connect(button37, "onClick", function(){
+				console.log(overlay19.attr("color"));
+				overlay19.attr("color", colors[cPos]);
+				cPos++;
+				if(cPos === colors.length - 1){
+					cPos = 0;
+				}
+				overlay19.show()}));
+			connects.push(dojo.connect(button38, "onClick", function(){overlay19.hide()}));
+			dijit.byId("dialog").show();
+
+			var button39 = dijit.byId("overlay20Button1");
+			var overlay20= dijit.byId("standby20");
+			connects.push(dojo.connect(button39, "onClick", function(){
+				overlay20.show();
+				setTimeout(function(){
+	                overlay20.hide();
+				}, 5000);
+			}));
+		}
+		dojo.addOnLoad(init);
+
+		//Cleanup, so I can check for leaks in the widget itself.
+		dojo.addOnUnload(function(){
+			var i;
+			for(i = 0; i < connects.length; i++){
+				dojo.disconnect(connects[i]);
+			}
+		});
+
+	</script>
+	
+</head>
+<body class="soria" id="bodyId">
+	
+	<h1 class="testTitle">dojox.widget.Standby</h1>
+
+	<h3>Testing a basic on a div contained in a scrolling div</h3>
+	<button id ="overlay14Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay14Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div style="width: 250px; height: 100px; overflow: auto">
+		<br>
+		<br>
+		<br>
+		<br>
+		<br>
+	<div id ="overlayTarget14" style="width: 200px; height: 200px; background-color: darkblue;"></div>
+		<div style="width: 400px; height: 5px"></div>
+		<br>
+		<br>
+		<br>
+		<br>
+		<br>
+	</div>
+	<div id ="standby14" target="overlayTarget14" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<hr>
+	<h3>Testing a basic overlay</h3>
+	<button id ="overlay1Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay1Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget1" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby1" target="overlayTarget1" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+
+	<h3>Testing a basic overlay on a positioned div</h3>
+	<button id ="overlay2Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay2Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget2" style="position: absolute; width: 200px; height: 100px; background-color: darkblue; top: 500px; left: 500px;"></div>
+	<div id ="standby2" target="overlayTarget2" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a basic overlay on a dijit</h3>
+	<button id ="overlay3Button1" dojoType="dijit.form.Button">Really long button!!!!!  Click to show the standby overlay on the button.</button>
+	<br>
+	<button id ="overlay3Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="standby3" target="overlay3Button1" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a basic on a nested div</h3>
+	<button id ="overlay4Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay4Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div><div><div><div id ="overlayTarget4" style="width: 200px; height: 100px; background-color: darkblue;"></div></div></div></div>
+	<div id ="standby4" target="overlayTarget4" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a different image</h3>
+	<button id ="overlay5Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay5Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget5" style="width: 500px; height: 500px; background-color: darkgray;"></div>
+	<div id ="standby5" target="overlayTarget5" dojoType="dojox.widget.Standby" image="images/busy.gif"></div>
+	<hr>
+
+	<h3>Testing an overlay on a div that has curved borders (CSS styles, Firefox and Webkit (Safari), only)</h3>
+	<button id ="overlay6Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay6Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget6" style="width: 200px; height: 100px; background-color: darkblue; -moz-border-radius: 15px; -webkit-border-radius: 15px;"></div>
+	<div id ="standby6" target="overlayTarget6" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing an overlay on a div that has curved borders (CSS styles, Firefox and Webkit (Safari), only, margined to the center) and a different color for the overlay</h3>
+	<button id ="overlay7Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay7Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget7" style="width: 200px; height: 100px; background-color: darkblue; -moz-border-radius: 15px; -webkit-border-radius: 15px; margin: auto"></div>
+	<div id ="standby7" target="overlayTarget7" dojoType="dojox.widget.Standby" color="lightblue"></div>
+	<hr>
+
+
+	<h3>Testing an overlay on a grid</h3>
+	<button id ="overlay8Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay8Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div jsId="ifsStore" dojoType="dojo.data.ItemFileReadStore", url="../../../dijit/tests/_data/countries.json"></div>
+	<table id ="overlayTarget8" dojoType="dojox.grid.DataGrid", style="width: 500px; height: 300px; margin: auto" store="ifsStore", query="{}">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+	<div id ="standby8" target="overlayTarget8" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+
+	<h3>Testing an overlay on a dijit.Tree</h3>
+	<button id ="overlay9Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay9Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div jsId="ifsStore2" dojoType="dojo.data.ItemFileReadStore", url="../../../dijit/tests/_data/countries.json"></div>
+	<div dojoType="dijit.tree.ForestStoreModel" jsId="continentModel" store="ifsStore2" query="{type:'continent'}" rootId="continentRoot" rootLabel="Continents" childrenAttrs="children"></div>
+	<div id ="overlayTarget9" dojoType="dijit.Tree", style="width: 30%" model="continentModel", query="{}"></div>
+	<div id ="standby9" target="overlayTarget9" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing overlay following a div as it moves (And with some whacky margins that need to be accounted for)</h3>
+	<button id ="overlay10Button1" dojoType="dijit.form.Button">Click to show the standby overlay and move the overlayed div.</button>
+	<br>
+	<button id ="overlay10Button2" dojoType="dijit.form.Button">Click to scoot the div back and hide the standby overlay.</button>
+	<div style="width: 100%;"><div id ="overlayTarget10" style="width: 200px; height: 100px; background-color: darkblue; margin-right: 100px; margin-top: 100px; margin-bottom: 100px;"></div></div>
+	<div id ="standby10" target="overlayTarget10" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing an overlay with class set styles for curves (Firefox, safari only).</h3>
+	<button id ="overlay11Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay11Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget11" class="curvedClass"></div>
+	<div id ="standby11" target="overlayTarget11" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a basic on a zIndex'ed div</h3>
+	<button id ="overlay13Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay13Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget13" style="width: 200px; height: 100px; background-color: darkblue; z-index: 200"></div>
+	<div id ="standby13" target="overlayTarget13" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+   	<h3>Testing that this still works in a dialog after zIndex changes</h3>
+	<div dojoType="dijit.Dialog" id="dialog">
+		<button id ="overlay15Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+		<br>
+		<button id ="overlay15Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+		<div id ="overlayTarget15" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+		<div id ="standby15" target="overlayTarget15" dojoType="dojox.widget.Standby" zIndex="1000"></div>
+	</div>
+   	<hr>
+
+	<h3>Testing a basic on a node, using only centered text.</h3>
+	<button id ="overlay16Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay16Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget16" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby16" target="overlayTarget16" dojoType="dojox.widget.Standby" centerIndicator="text"></div>
+	<hr>
+
+	<h3>Testing a basic on a node, using only centered text that was customized.</h3>
+	<button id ="overlay17Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay17Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget17" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby17" target="overlayTarget17" dojoType="dojox.widget.Standby" centerIndicator="text" text="<span style='color: red; font-weight: bold; font-style: italic;'>WAIT, FOO!</span>"></div>
+	<hr>
+
+	<h3>Testing a basic on a node, using only centered text that is changed with each display.</h3>
+	<button id ="overlay18Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay18Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget18" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby18" target="overlayTarget18" dojoType="dojox.widget.Standby" centerIndicator="text" text="<span style='color: red; font-weight: bold; font-style: italic;'>WAIT, FOO!</span>"></div>
+	<hr>
+
+	<h3>Testing a basic on a node, using only centered text, and with a background color that changes with each show</h3>
+	<button id ="overlay19Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay19Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget19" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby19" target="overlayTarget19" dojoType="dojox.widget.Standby" centerIndicator="text" text="<span style='color: red; font-weight: bold; font-style: italic;'>Watch Background</span>"></div>
+	<hr>
+
+	<h3>Testing the widget in a relatively positioned block.  This has caused problems, verifying the fix of reparenting to document.body works.</h3>
+	<button id ="overlay12Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay12Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div style="position: relative; top: 50px; left: 50px;">
+		<div id ="overlayTarget12" class="curvedClass"></div>
+		<div id ="standby12" target="overlayTarget12" dojoType="dojox.widget.Standby"></div>
+	</div>        
+
+	<br>
+	<br>
+	<br> 
+	<h3>Testing an overlay of the entire document body.</h3>
+	<button id ="overlay20Button1" dojoType="dijit.form.Button">Click to show the standby overlay on body for 5 seconds!</button>
+	<div id ="standby20" target="bodyId" dojoType="dojox.widget.Standby"></div>
+
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Standby_rtl.html b/dojox/widget/tests/test_Standby_rtl.html
new file mode 100755
index 0000000..b7b1f08
--- /dev/null
+++ b/dojox/widget/tests/test_Standby_rtl.html
@@ -0,0 +1,387 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+	<title>Testing the Standby widget</title>
+	<style type="text/css">
+		@import "../../../dijit/themes/soria/soria.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+		@import "../../../dojox/grid/resources/soriaGrid.css";
+
+		.curvedClass {
+			background-color: darkblue;
+			width: 250px;
+			height: 250px;
+			-moz-border-radius: 15px 15px 15px 15px; 
+			-webkit-border-radius: 15px;"        
+		}
+	</style>
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" djconfig="parseOnLoad:true, isDebug: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.widget.Standby");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.tree.ForestStoreModel");
+		dojo.require("dijit.Dialog");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileReadStore");
+
+		var connects = [];
+
+		function init() {
+			var button1 = dijit.byId("overlay1Button1");
+			var button2 = dijit.byId("overlay1Button2");
+			var overlay1= dijit.byId("standby1");
+			connects.push(dojo.connect(button1, "onClick", function(){overlay1.show()}));
+			connects.push(dojo.connect(button2, "onClick", function(){overlay1.hide()}));
+
+			var button3 = dijit.byId("overlay2Button1");
+			var button4 = dijit.byId("overlay2Button2");
+			var overlay2= dijit.byId("standby2");
+			connects.push(dojo.connect(button3, "onClick", function(){overlay2.show()}));
+			connects.push(dojo.connect(button4, "onClick", function(){overlay2.hide()}));
+
+			var button5 = dijit.byId("overlay3Button1");
+			var button6 = dijit.byId("overlay3Button2");
+			var overlay3= dijit.byId("standby3");
+			connects.push(dojo.connect(button5, "onClick", function(){overlay3.show()}));
+			connects.push(dojo.connect(button6, "onClick", function(){overlay3.hide()}));
+
+			var button7 = dijit.byId("overlay4Button1");
+			var button8 = dijit.byId("overlay4Button2");
+			var overlay4= dijit.byId("standby4");
+			connects.push(dojo.connect(button7, "onClick", function(){overlay4.show()}));
+			connects.push(dojo.connect(button8, "onClick", function(){overlay4.hide()}));
+
+			var button9 = dijit.byId("overlay5Button1");
+			var button10 = dijit.byId("overlay5Button2");
+			var overlay5= dijit.byId("standby5");
+			connects.push(dojo.connect(button9, "onClick", function(){overlay5.show()}));
+			connects.push(dojo.connect(button10, "onClick", function(){overlay5.hide()}));
+
+			var button11 = dijit.byId("overlay6Button1");
+			var button12 = dijit.byId("overlay6Button2");
+			var overlay6= dijit.byId("standby6");
+			connects.push(dojo.connect(button11, "onClick", function(){overlay6.show()}));
+			connects.push(dojo.connect(button12, "onClick", function(){overlay6.hide()}));
+
+			var button13 = dijit.byId("overlay7Button1");
+			var button14 = dijit.byId("overlay7Button2");
+			var overlay7= dijit.byId("standby7");
+			connects.push(dojo.connect(button13, "onClick", function(){overlay7.show()}));
+			connects.push(dojo.connect(button14, "onClick", function(){overlay7.hide()}));
+
+			var button15 = dijit.byId("overlay8Button1");
+			var button16 = dijit.byId("overlay8Button2");
+			var overlay8= dijit.byId("standby8");
+			connects.push(dojo.connect(button15, "onClick", function(){overlay8.show()}));
+			connects.push(dojo.connect(button16, "onClick", function(){overlay8.hide()}));
+
+			var button17 = dijit.byId("overlay9Button1");
+			var button18 = dijit.byId("overlay9Button2");
+			var overlay9= dijit.byId("standby9");
+			connects.push(dojo.connect(button17, "onClick", function(){overlay9.show()}));
+			connects.push(dojo.connect(button18, "onClick", function(){overlay9.hide()}));
+
+			var button19 = dijit.byId("overlay10Button1");
+			var button20 = dijit.byId("overlay10Button2");
+			var overlay10= dijit.byId("standby10");
+			connects.push(dojo.connect(button19, "onClick", function(){
+				overlay10.show();
+				var moveDiv = dojo.byId("overlayTarget10");
+				var moveAnim = dojo.animateProperty({node: moveDiv, properties: {marginLeft: {start: 0, end: 300}}});
+				moveAnim.play();
+			}));
+			connects.push(dojo.connect(button20, "onClick", function(){
+				var moveDiv = dojo.byId("overlayTarget10");
+				var moveAnim = dojo.animateProperty({node: moveDiv, properties: {marginLeft: {start: 300, end: 0}}, onEnd: function(){overlay10.hide()}});
+				moveAnim.play();
+			}));
+
+			var button21 = dijit.byId("overlay11Button1");
+			var button22 = dijit.byId("overlay11Button2");
+			var overlay11= dijit.byId("standby11");
+			connects.push(dojo.connect(button21, "onClick", function(){overlay11.show()}));
+			connects.push(dojo.connect(button22, "onClick", function(){overlay11.hide()}));
+			
+			var button23 = dijit.byId("overlay12Button1");
+			var button24 = dijit.byId("overlay12Button2");
+			var overlay12= dijit.byId("standby12");
+			connects.push(dojo.connect(button23, "onClick", function(){overlay12.show()}));
+			connects.push(dojo.connect(button24, "onClick", function(){overlay12.hide()}));
+
+			var button25 = dijit.byId("overlay13Button1");
+			var button26 = dijit.byId("overlay13Button2");
+			var overlay13= dijit.byId("standby13");
+			connects.push(dojo.connect(button25, "onClick", function(){overlay13.show()}));
+			connects.push(dojo.connect(button26, "onClick", function(){overlay13.hide()}));
+
+			var button27 = dijit.byId("overlay14Button1");
+			var button28 = dijit.byId("overlay14Button2");
+			var overlay14= dijit.byId("standby14");
+			connects.push(dojo.connect(button27, "onClick", function(){overlay14.show()}));
+			connects.push(dojo.connect(button28, "onClick", function(){overlay14.hide()}));
+
+			var button29 = dijit.byId("overlay15Button1");
+			var button30 = dijit.byId("overlay15Button2");
+			var overlay15= dijit.byId("standby15");
+			connects.push(dojo.connect(button29, "onClick", function(){overlay15.show()}));
+			connects.push(dojo.connect(button30, "onClick", function(){overlay15.hide()}));
+
+			var button31 = dijit.byId("overlay16Button1");
+			var button32 = dijit.byId("overlay16Button2");
+			var overlay16= dijit.byId("standby16");
+			connects.push(dojo.connect(button31, "onClick", function(){overlay16.show()}));
+			connects.push(dojo.connect(button32, "onClick", function(){overlay16.hide()}));
+
+			var button33 = dijit.byId("overlay17Button1");
+			var button34 = dijit.byId("overlay17Button2");
+			var overlay17= dijit.byId("standby17");
+			connects.push(dojo.connect(button33, "onClick", function(){overlay17.show()}));
+			connects.push(dojo.connect(button34, "onClick", function(){overlay17.hide()}));
+
+			var showCount = 0;
+			var button35 = dijit.byId("overlay18Button1");
+			var button36 = dijit.byId("overlay18Button2");
+			var overlay18= dijit.byId("standby18");
+			connects.push(dojo.connect(button35, "onClick", function(){
+				showCount++;
+				console.log(overlay18.attr("text"));
+				overlay18.attr("text", "Shown: " + showCount);
+				overlay18.show()}));
+			connects.push(dojo.connect(button36, "onClick", function(){overlay18.hide()}));
+
+			var colors = ["red", "green", "gray", "black", "purple"]
+			var cPos = 0;
+			var button37 = dijit.byId("overlay19Button1");
+			var button38 = dijit.byId("overlay19Button2");
+			var overlay19= dijit.byId("standby19");
+			connects.push(dojo.connect(button37, "onClick", function(){
+				console.log(overlay19.attr("color"));
+				overlay19.attr("color", colors[cPos]);
+				cPos++;
+				if(cPos === colors.length - 1){
+					cPos = 0;
+				}
+				overlay19.show()}));
+			connects.push(dojo.connect(button38, "onClick", function(){overlay19.hide()}));
+			dijit.byId("dialog").show();
+
+			var button39 = dijit.byId("overlay20Button1");
+			var overlay20= dijit.byId("standby20");
+			connects.push(dojo.connect(button39, "onClick", function(){
+				overlay20.show();
+				setTimeout(function(){
+	                overlay20.hide();
+				}, 5000);
+			}));
+		}
+		dojo.addOnLoad(init);
+
+		//Cleanup, so I can check for leaks in the widget itself.
+		dojo.addOnUnload(function(){
+			var i;
+			for(i = 0; i < connects.length; i++){
+				dojo.disconnect(connects[i]);
+			}
+		});
+
+	</script>
+	
+</head>
+<body class="soria" id="bodyId" dir="rtl">
+	
+	<h1 class="testTitle">dojox.widget.Standby</h1>
+
+	<h3>Testing a basic on a div contained in a scrolling div</h3>
+	<button id ="overlay14Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay14Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div style="width: 250px; height: 100px; overflow: auto">
+		<br>
+		<br>
+		<br>
+		<br>
+		<br>
+	<div id ="overlayTarget14" style="width: 200px; height: 200px; background-color: darkblue;"></div>
+		<div style="width: 400px; height: 5px"></div>
+		<br>
+		<br>
+		<br>
+		<br>
+		<br>
+	</div>
+	<div id ="standby14" target="overlayTarget14" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<hr>
+	<h3>Testing a basic overlay</h3>
+	<button id ="overlay1Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay1Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget1" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby1" target="overlayTarget1" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+
+	<h3>Testing a basic overlay on a positioned div</h3>
+	<button id ="overlay2Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay2Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget2" style="position: absolute; width: 200px; height: 100px; background-color: darkblue; top: 500px; left: 500px;"></div>
+	<div id ="standby2" target="overlayTarget2" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a basic overlay on a dijit</h3>
+	<button id ="overlay3Button1" dojoType="dijit.form.Button">Really long button!!!!!  Click to show the standby overlay on the button.</button>
+	<br>
+	<button id ="overlay3Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="standby3" target="overlay3Button1" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a basic on a nested div</h3>
+	<button id ="overlay4Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay4Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div><div><div><div id ="overlayTarget4" style="width: 200px; height: 100px; background-color: darkblue;"></div></div></div></div>
+	<div id ="standby4" target="overlayTarget4" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a different image</h3>
+	<button id ="overlay5Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay5Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget5" style="width: 500px; height: 500px; background-color: darkgray;"></div>
+	<div id ="standby5" target="overlayTarget5" dojoType="dojox.widget.Standby" image="images/busy.gif"></div>
+	<hr>
+
+	<h3>Testing an overlay on a div that has curved borders (CSS styles, Firefox and Webkit (Safari), only)</h3>
+	<button id ="overlay6Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay6Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget6" style="width: 200px; height: 100px; background-color: darkblue; -moz-border-radius: 15px; -webkit-border-radius: 15px;"></div>
+	<div id ="standby6" target="overlayTarget6" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing an overlay on a div that has curved borders (CSS styles, Firefox and Webkit (Safari), only, margined to the center) and a different color for the overlay</h3>
+	<button id ="overlay7Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay7Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget7" style="width: 200px; height: 100px; background-color: darkblue; -moz-border-radius: 15px; -webkit-border-radius: 15px; margin: auto"></div>
+	<div id ="standby7" target="overlayTarget7" dojoType="dojox.widget.Standby" color="lightblue"></div>
+	<hr>
+
+
+	<h3>Testing an overlay on a grid</h3>
+	<button id ="overlay8Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay8Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div jsId="ifsStore" dojoType="dojo.data.ItemFileReadStore", url="../../../dijit/tests/_data/countries.json"></div>
+	<table id ="overlayTarget8" dojoType="dojox.grid.DataGrid", style="width: 500px; height: 300px; margin: auto" store="ifsStore", query="{}">
+		<thead>
+			<tr>
+				<th field="name" width="300px">Country/Continent Name</th>
+				<th field="type" width="auto">Type</th>
+			</tr>
+		</thead>
+	</table>
+	<div id ="standby8" target="overlayTarget8" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+
+	<h3>Testing an overlay on a dijit.Tree</h3>
+	<button id ="overlay9Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay9Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div jsId="ifsStore2" dojoType="dojo.data.ItemFileReadStore", url="../../../dijit/tests/_data/countries.json"></div>
+	<div dojoType="dijit.tree.ForestStoreModel" jsId="continentModel" store="ifsStore2" query="{type:'continent'}" rootId="continentRoot" rootLabel="Continents" childrenAttrs="children"></div>
+	<div id ="overlayTarget9" dojoType="dijit.Tree", style="width: 30%" model="continentModel", query="{}"></div>
+	<div id ="standby9" target="overlayTarget9" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing overlay following a div as it moves (And with some whacky margins that need to be accounted for)</h3>
+	<button id ="overlay10Button1" dojoType="dijit.form.Button">Click to show the standby overlay and move the overlayed div.</button>
+	<br>
+	<button id ="overlay10Button2" dojoType="dijit.form.Button">Click to scoot the div back and hide the standby overlay.</button>
+	<div style="width: 100%;"><div id ="overlayTarget10" style="width: 200px; height: 100px; background-color: darkblue; margin-right: 100px; margin-top: 100px; margin-bottom: 100px;"></div></div>
+	<div id ="standby10" target="overlayTarget10" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing an overlay with class set styles for curves (Firefox, safari only).</h3>
+	<button id ="overlay11Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay11Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget11" class="curvedClass"></div>
+	<div id ="standby11" target="overlayTarget11" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+	<h3>Testing a basic on a zIndex'ed div</h3>
+	<button id ="overlay13Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay13Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget13" style="width: 200px; height: 100px; background-color: darkblue; z-index: 200"></div>
+	<div id ="standby13" target="overlayTarget13" dojoType="dojox.widget.Standby"></div>
+	<hr>
+
+   	<h3>Testing that this still works in a dialog after zIndex changes</h3>
+	<div dojoType="dijit.Dialog" id="dialog">
+		<button id ="overlay15Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+		<br>
+		<button id ="overlay15Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+		<div id ="overlayTarget15" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+		<div id ="standby15" target="overlayTarget15" dojoType="dojox.widget.Standby" zIndex="1000"></div>
+	</div>
+   	<hr>
+
+	<h3>Testing a basic on a node, using only centered text.</h3>
+	<button id ="overlay16Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay16Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget16" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby16" target="overlayTarget16" dojoType="dojox.widget.Standby" centerIndicator="text"></div>
+	<hr>
+
+	<h3>Testing a basic on a node, using only centered text that was customized.</h3>
+	<button id ="overlay17Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay17Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget17" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby17" target="overlayTarget17" dojoType="dojox.widget.Standby" centerIndicator="text" text="<span style='color: red; font-weight: bold; font-style: italic;'>WAIT, FOO!</span>"></div>
+	<hr>
+
+	<h3>Testing a basic on a node, using only centered text that is changed with each display.</h3>
+	<button id ="overlay18Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay18Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget18" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby18" target="overlayTarget18" dojoType="dojox.widget.Standby" centerIndicator="text" text="<span style='color: red; font-weight: bold; font-style: italic;'>WAIT, FOO!</span>"></div>
+	<hr>
+
+	<h3>Testing a basic on a node, using only centered text, and with a background color that changes with each show</h3>
+	<button id ="overlay19Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay19Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div id ="overlayTarget19" style="width: 200px; height: 100px; background-color: darkblue;"></div>
+	<div id ="standby19" target="overlayTarget19" dojoType="dojox.widget.Standby" centerIndicator="text" text="<span style='color: red; font-weight: bold; font-style: italic;'>Watch Background</span>"></div>
+	<hr>
+
+	<h3>Testing the widget in a relatively positioned block.  This has caused problems, verifying the fix of reparenting to document.body works.</h3>
+	<button id ="overlay12Button1" dojoType="dijit.form.Button">Click to show the standby overlay</button>
+	<br>
+	<button id ="overlay12Button2" dojoType="dijit.form.Button">Click to hide the standby overlay</button>
+	<div style="position: relative; top: 50px; left: 50px;">
+		<div id ="overlayTarget12" class="curvedClass"></div>
+		<div id ="standby12" target="overlayTarget12" dojoType="dojox.widget.Standby"></div>
+	</div>        
+
+	<br>
+	<br>
+	<br> 
+	<h3>Testing an overlay of the entire document body.</h3>
+	<button id ="overlay20Button1" dojoType="dijit.form.Button">Click to show the standby overlay on body for 5 seconds!</button>
+	<div id ="standby20" target="bodyId" dojoType="dojox.widget.Standby"></div>
+
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Toaster.html b/dojox/widget/tests/test_Toaster.html
new file mode 100644
index 0000000..d35f311
--- /dev/null
+++ b/dojox/widget/tests/test_Toaster.html
@@ -0,0 +1,161 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Toaster Widget Dojo Tests</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+		@import "../../../dijit/themes/dijit.css";
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		@import "../Toaster/Toaster.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojox.widget.Toaster");
+		dojo.require("dojo.parser");	// scan page for widgets and instantiate them
+
+		dojo.require("dijit.Tooltip");
+		
+		var toast = null;
+		function showTestMessage(){
+			dojo.publish("testMessageTopic", 
+				[ "This is a message! It's kind of long to show message wrapping."]
+			);
+		}
+		function showAnotherMessage(){
+			dojo.publish("testMessageTopic", 
+				[{
+					message: "This is another message!", 
+					type: "warning", 
+					duration: 500
+				}]
+			);
+		}
+		function showYetAnotherMessage(){
+			dojo.publish("testMessageTopic", 
+				[{ message: "This is yet another message!" }]
+			);
+		}
+
+		dojo.addOnLoad(function(){
+			toast = dijit.byId("toast");
+		});
+	</script>
+</head>
+<body class="tundra">
+	<div dojoType="dojox.widget.Toaster" id="toast" 
+		positionDirection="br-left" duration="0" 
+		messageTopic="testMessageTopic"></div>
+
+	<div dojoType="dojox.widget.Toaster" id="toast2" 
+		separator="<hr>" positionDirection="bl-up" 
+		messageTopic="testMessageTopic"></div>
+
+	<button type="submit" 
+		onclick="showTestMessage();">Click to show message</button>
+	<button type="submit" 
+		onclick="showAnotherMessage();">Click to show another message</button>
+	<button type="submit" 
+		onclick="showYetAnotherMessage();">Click to show yet another message</button>
+
+	<h1>dojox.widget.Toaster test</h1>
+
+	<div style="color: #FF0000;">
+		When you click any of the buttons above, the bottom right hand message will
+		stay on the screen until you acknowledge it by clicking inside the message
+		box. If you click one of the message buttons while a message is still
+		displayed in the bottom right corner it should append the new message below
+		the old one with a separator between them.
+	</div>
+	
+	<h2>A Tooltip: (#10046)</h2>
+	<div><span id="one" class="tt" tabindex="0"> focusable text </span>
+		<span dojoType="dijit.Tooltip" connectId="one" id="one_tooltip">
+			<b>
+				<span style="color: blue;">rich formatting</span>
+				<span style="color: red; font-size: x-large;"><i>!</i></span>
+			</b>
+		</span>
+	</div>
+	
+	<p>
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper
+		sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin porta rutrum
+		lacus. Etiam consequat scelerisque quam. Nulla facilisi.  Maecenas luctus
+		venenatis nulla. In sit amet dui non mi semper iaculis.  Sed molestie
+		tortor at ipsum. Morbi dictum rutrum magna. Sed vitae risus.
+	</p>
+	<p>
+		Aliquam vitae enim. Duis scelerisque metus auctor est venenatis imperdiet.
+		Fusce dignissim porta augue. Nulla vestibulum. Integer lorem nunc,
+		ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in massa
+		bibendum suscipit. Integer eros. Nullam suscipit mauris. In pellentesque.
+		Mauris ipsum est, pharetra semper, pharetra in, viverra quis, tellus. Etiam
+		purus. Quisque egestas, tortor ac cursus lacinia, felis leo adipiscing
+		nisi, et rhoncus elit dolor eget eros. Fusce ut quam. Suspendisse eleifend
+		leo vitae ligula. Nulla facilisi. Nulla rutrum, erat vitae lacinia dictum,
+		pede purus imperdiet lacus, ut semper velit ante id metus. Praesent massa
+		dolor, porttitor sed, pulvinar in, consequat ut, leo. Nullam nec est.
+		Aenean id risus blandit tortor pharetra congue. Suspendisse pulvinar.
+	</p>
+	<p>
+		Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam ornare
+		elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque nonummy
+		mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus lobortis, sem
+		vitae nonummy lacinia, nisl est gravida magna, non cursus est quam sed
+		urna. Phasellus adipiscing justo in ipsum. Duis sagittis dolor sit amet
+		magna. Suspendisse suscipit, neque eu dictum auctor, nisi augue tincidunt
+		arcu, non lacinia magna purus nec magna. Praesent pretium sollicitudin
+		sapien. Suspendisse imperdiet. Class aptent taciti sociosqu ad litora
+		torquent per conubia nostra, per inceptos hymenaeos.
+	</p>
+	<p>
+		Mauris pharetra lorem sit amet sapien. Nulla libero metus, tristique et,
+		dignissim a, tempus et, metus. Ut libero. Vivamus tempus purus vel ipsum.
+		Quisque mauris urna, vestibulum commodo, rutrum vitae, ultrices vitae,
+		nisl. Class aptent taciti sociosqu ad litora torquent per conubia nostra,
+		per inceptos hymenaeos. Nulla id erat sit amet odio luctus eleifend. Proin
+		massa libero, ultricies non, tincidunt a, vestibulum non, tellus. Nunc nunc
+		purus, lobortis a, pulvinar at, egestas a, mi. Cras adipiscing velit a
+		mauris. Morbi felis. Etiam at felis. Cras eget eros et justo mattis
+		pulvinar. Nullam at justo id risus porttitor dignissim. Vestibulum sed
+		velit vel metus tincidunt tempus. Nunc euismod nisl id dolor tristique
+		tincidunt. Nullam placerat turpis sed odio. Curabitur in est id nibh tempus
+		ultrices. Aliquam consectetuer dapibus eros. Aliquam nisl.
+	</p>
+	<p>
+		Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean semper
+		sagittis velit. Cras in mi. Duis porta mauris ut ligula. Proin porta rutrum
+		lacus. Etiam consequat scelerisque quam. Nulla facilisi.  Maecenas luctus
+		venenatis nulla. In sit amet dui non mi semper iaculis.  Sed molestie
+		tortor at ipsum. Morbi dictum rutrum magna. Sed vitae risus.
+	</p>
+	<p>
+		Aliquam vitae enim. Duis scelerisque metus auctor est venenatis imperdiet.
+		Fusce dignissim porta augue. Nulla vestibulum. Integer lorem nunc,
+		ullamcorper a, commodo ac, malesuada sed, dolor. Aenean id mi in massa
+		bibendum suscipit. Integer eros. Nullam suscipit mauris. In pellentesque.
+		Mauris ipsum est, pharetra semper, pharetra in, viverra quis, tellus. Etiam
+		purus. Quisque egestas, tortor ac cursus lacinia, felis leo adipiscing
+		nisi, et rhoncus elit dolor eget eros. Fusce ut quam. Suspendisse eleifend
+		leo vitae ligula. Nulla facilisi. Nulla rutrum, erat vitae lacinia dictum,
+		pede purus imperdiet lacus, ut semper velit ante id metus. Praesent massa
+		dolor, porttitor sed, pulvinar in, consequat ut, leo. Nullam nec est.
+		Aenean id risus blandit tortor pharetra congue. Suspendisse pulvinar.
+	</p>
+	<p>
+		Vestibulum convallis eros ac justo. Proin dolor. Etiam aliquam. Nam ornare
+		elit vel augue. Suspendisse potenti. Etiam sed mauris eu neque nonummy
+		mollis. Vestibulum vel purus ac pede semper accumsan. Vivamus lobortis, sem
+		vitae nonummy lacinia, nisl est gravida magna, non cursus est quam sed
+		urna. Phasellus adipiscing justo in ipsum. Duis sagittis dolor sit amet
+		magna. Suspendisse suscipit, neque eu dictum auctor, nisi augue tincidunt
+		arcu, non lacinia magna purus nec magna. Praesent pretium sollicitudin
+		sapien. Suspendisse imperdiet. Class aptent taciti sociosqu ad litora
+		torquent per conubia nostra, per inceptos hymenaeos.
+	</p>
+		
+</body>
+</html>
diff --git a/dojox/widget/tests/test_UpgradeBar.html b/dojox/widget/tests/test_UpgradeBar.html
new file mode 100755
index 0000000..16fa52a
--- /dev/null
+++ b/dojox/widget/tests/test_UpgradeBar.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+	<title>UpgradeBar Test</title>
+	<style type="text/css">
+		body{
+			font-family:sans-serif;
+		}
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	<link href="../UpgradeBar/UpgradeBar.css" rel="stylesheet" />
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" djconfig="parseOnLoad:false, isDebug: false"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.widget.UpgradeBar");
+		
+		new dojox.widget.UpgradeBar({
+			notifications:[
+				{
+					validate:function(){
+						return dojo.isIE<10;	
+					},
+					message:   '<span>Your version of Internet Explorer needs to be upgraded to Firefox.</span>'
+							 + '<a href="http://www.getfirefox.net/">Get Firefox</a>'
+				},
+				{
+					validate:function(){
+						return dojo.isFF<4;
+					},
+					message:   '<span>Your version of Firefox needs to be upgraded to a version that does not exist.</span>'
+							 + '<a href="http://www.getfirefox.net/">Get Firefox</a>'
+				},
+				{
+					validate:function(){
+						var evals = true;
+						try{ evals = dojox.embed.Flash.available<14}catch(e){}
+						return evals;	
+					},
+					message:   '<span>This app needs a version of Flash that has never been released.</span>'
+							 + '<a href="http://www.adobe.com/downloads/">Get Flash Player</a>'
+				},
+				{
+					validate:function(){
+						return !google.gears;	
+					},
+					message:   '<span>This app will perform better with Google Gears.</span>'
+							 + '<a href="http://gears.google.com/download.html">Download Google Gears</a>'
+				}
+			]	
+		});
+	</script>
+	
+</head>
+<body class="tundra">
+	<h1 class="testTitle">dojox.widget.UpgradeBar</h1>
+</body>
+</html>
diff --git a/dojox/widget/tests/test_UpgradeBar_markup.html b/dojox/widget/tests/test_UpgradeBar_markup.html
new file mode 100644
index 0000000..387649c
--- /dev/null
+++ b/dojox/widget/tests/test_UpgradeBar_markup.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+	<title>UpgradeBar Test</title>
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+	<link href="../UpgradeBar/UpgradeBar.css" rel="stylesheet" />
+	
+	<script type="text/javascript" src="../../../dojo/dojo.js" djconfig="parseOnLoad:true, isDebug: false, popup:true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojox.widget.UpgradeBar");
+		
+		// for testing:
+		//dojo.require("dojo.gears");
+		//dojo.require("dojox.embed.Flash");
+		
+	</script>
+	
+</head>
+<body class="tundra">
+	
+	<h1 class="testTitle">dojox.widget.UpgradeBar</h1>
+	
+	<div dojoType="dojox.widget.UpgradeBar" id="upgradeBar" permDismiss="true">
+		<div validate="dojo.isIE<10">
+			<span>Your browser sucks. Download a good one.</span>
+			<a href="http://www.getfirefox.net/">Get Firefox</a>	
+		</div>
+	
+		<div validate="dojo.isFF<3">
+			<span>Your version of Firefox needs to be upgraded to version 3.</span>
+			<a href="http://www.getfirefox.net/">Get Firefox</a>	
+		</div>
+		
+		<div validate="dojox.embed.Flash.available<14">
+			<span>This app needs a version of Flash that does not yet exist.</span>
+			<a href="http://www.adobe.com/downloads/">Download Flash 14</a>
+		</div>
+		
+		<div validate="!google.gears">
+			<span>This app will perform better with Google Gears.</span>
+			<a href="http://gears.google.com/download.html">Download Google Gears</a>
+		</div>
+	</div>
+</body>
+</html>
diff --git a/dojox/widget/tests/test_Wizard.html b/dojox/widget/tests/test_Wizard.html
new file mode 100644
index 0000000..202ea79
--- /dev/null
+++ b/dojox/widget/tests/test_Wizard.html
@@ -0,0 +1,236 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+
+	<title>Wizard Demo</title>
+
+	<!-- required: a default theme file, and Wizard styles -->
+	<link rel="stylesheet" id="themeStyles" href="../../../dijit/themes/tundra/tundra.css">
+	<link rel="stylesheet" href="../Wizard/Wizard.css">
+	
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true, parseOnLoad: true"></script>
+
+	<!-- do not use! only for testing dynamic themes -->
+	<script type="text/javascript" src="../../../dijit/tests/_testCommon.js"></script>
+	<!-- for debugging: -->
+	<script type="text/javascript" src="../Wizard.js"></script>
+
+	<script type="text/javascript">
+		dojo.require("dojox.widget.Wizard");
+	
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.BorderContainer");
+		
+		function cancel() {
+			alert("Wizard Cancelled!");
+		}
+	    
+		function done() {
+			alert("Wizard Done!");
+		}
+		
+		var programatic_Example = function(){
+			
+			var wizard = new dojox.widget.Wizard({
+				style:"width:300px; height:300px"
+			}).placeAt(dojo.body(),"last");
+			
+			var contents = [
+				"Pane 1 content", "Pane 2 content", "<h3>Done!</h3>"
+			];
+			
+			dojo.forEach(contents, function(term){
+			
+				new dojox.widget.WizardPane({})
+					.placeAt(wizard)
+					.attr("content", term)
+				;
+			});
+			wizard.startup();
+			
+		}
+		
+		dojo.addOnLoad(programatic_Example)
+	</script>
+
+	<style type="text/css">
+		@import "../../../dijit/tests/css/dijitTests.css"; 
+		body {
+			font-family : sans-serif;
+		}
+	</style>
+</head>
+
+<body class="tundra">
+
+	<div style="width:800px; margin:0 auto">
+
+		<h1 class="testTitle">dojox.widget.Wizard tests</h1>
+
+		<p>This example shows a wizard with customized button labels.</p>
+
+		<div id="wizard1" dojoType="dojox.widget.Wizard"
+			 style="width: 640px; height: 200px;"
+			 nextButtonLabel="Go on"
+			 >
+			<div dojoType="dojox.widget.WizardPane" title="Tab 1">
+				<h1>Tab 1</h1>
+				<p>Sized content, box one</p>
+			</div>
+			<div dojoType="dojox.widget.WizardPane">
+				<h1>Tab 2</h1>
+			</div>
+			<div dojoType="dojox.widget.WizardPane">
+				<h1>Tab 3</h1>
+	
+				You won't be able to come back, but you can finish now...
+				<script type='dojo/method' event="doneFunction">
+					done();
+					console.log('inline done function called');
+				</script>
+			</div>
+			<div dojoType="dojox.widget.WizardPane" canGoBack="false">
+				<h1>Tab 4</h1>
+	
+				... and now you can't go back.
+			</div>
+			<div dojoType="dojox.widget.WizardPane" doneFunction="done">
+				<h1>Tab 5</h1>
+				... and now you can finish up.
+			</div>
+			<script type="dojo/method" event="cancelFunction">
+				alert("dojo/method cancel function on container! bye.")
+				this.destroy();
+			</script>
+		</div>
+	
+		<p>The next shows the option to hide the inactive buttons, with a smaller width...</p>
+	
+		<div id="wizard2" dojoType="dojox.widget.Wizard" hideDisabled="true" style="width: 50%; height: 200px;">
+			<div dojoType="dojox.widget.WizardPane">
+				<h1>Step 1 of 3</h1>
+				<p>Lorem ipsum dolor sit amet</p>
+			</div>
+			<div dojoType="dojox.widget.WizardPane">
+				<h1>Step 2 of 3</h1>
+				<p>consectetur adipisicing elit</p>
+			</div>
+			<div dojoType="dojox.widget.WizardPane">
+				<h1>Step 3 of 3</h1>
+				<p>sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</p>
+			</div>
+		</div>
+
+		<p>Layout Children</p>
+		<div id="wizard2lay" dojoType="dojox.widget.Wizard" hideDisabled="true" style="width: 50%; height: 240px;">
+			<div dojoType="dojox.widget.WizardPane">
+				<p>The next two (hidden) children container AccordionContainers. You'll have to be
+					more careful about the styling / sizing, as the child wants to take 100% of
+					it's height. You can size explicitly if you like, or add margin-bottom to
+					leave room for the buttons
+				</p>
+			</div>
+			<div dojoType="dojox.widget.WizardPane" style="padding:8px; margin-bottom:35px">
+				<div dojoType="dijit.layout.AccordionContainer">
+					<div title="foo" dojoType="dijit.layout.ContentPane">
+						foo.
+					</div>
+					<div title="bar" dojoType="dijit.layout.ContentPane">
+						foo.
+					</div>
+				</div>				
+			</div>
+			<div dojoType="dojox.widget.WizardPane" style="padding:8px; margin-bottom:35px">
+				<div dojoType="dijit.layout.BorderContainer">
+					<div region="left" style="width:75px" dojoType="dijit.layout.ContentPane">
+						left pane
+					</div>
+					<div region="center" dojoType="dijit.layout.ContentPane">
+						main pane
+					</div>
+					<div dojoType="dijit.layout.ContentPane" region="right" style="width:75px">
+						right pane
+					</div>
+				</div>
+			</div>
+			<div dojoType="dojox.widget.WizardPane" style="padding:8px; margin-bottom:35px">
+				<div dojoType="dijit.layout.TabContainer">
+					<div title="tab1" dojoType="dijit.layout.ContentPane">
+						foo
+					</div>
+					<div title="tab2" dojoType="dijit.layout.ContentPane">
+						foo
+					</div>
+					<div title="tab3" dojoType="dijit.layout.ContentPane">
+						foo
+					</div>
+				</div>
+			</div>
+			
+			
+		</div>
+
+	
+		<p>The next shows blocking moving to the next step with a JS function...</p>
+	
+		<script>
+			function checkAgreement() {
+				var frm = document.forms['acceptAgreement'];
+				var accept = frm.accept;
+				if (!accept.checked) {
+					return "You must agree to the terms before continuing.";
+				}
+			}
+		</script>
+		<div id="wizard3" dojoType="dojox.widget.Wizard" style="width: 600px; height: 400px; margin:0 auto;">
+			<div dojoType="dojox.widget.WizardPane" id="Agreement1" passFunction="checkAgreement">
+				<h1>Agreement Terms</h1>
+	
+				<div dojoType="dijit.layout.ContentPane" style="width:400px; border:1px solid #b7b7b7; background:#fff; padding:8px; margin:0 auto; height:200px; overflow:auto; "
+					href="../../../dojo/LICENSE"></div>
+	
+				<form action="#" name="acceptAgreement">
+					<p>
+					<input type="checkbox" name="accept" value="true"/> I accept the terms of this agreement.
+					</p>
+				</form>
+			</div>
+			<div dojoType="dojox.widget.WizardPane" canGoBack="false">
+				<h1>Complete</h1>
+				<p>The license has been accepted.</p>
+			</div>
+		</div>
+
+			<h2>Another like above, but with dojo/method passFunction</h2>
+			<div id="wizard4" dojoType="dojox.widget.Wizard" style="width: 600px; height: 400px; margin:0 auto;">
+				<div dojoType="dojox.widget.WizardPane" id="Agreement12">
+					<script type="dojo/method" event="passFunction">
+						return "cant do that yet";
+					</script>
+					<h1>Agreement Terms</h1>
+
+					<div dojoType="dijit.layout.ContentPane" style="width:400px; border:1px solid #b7b7b7; background:#fff; padding:8px; margin:0 auto; height:200px; overflow:auto; "
+						href="../../../dojo/LICENSE"></div>
+
+					<form action="#" name="acceptAgreement">
+						<p>
+						<input type="checkbox" name="accept" value="true"/> I accept the terms of this agreement.
+						</p>
+					</form>
+				</div>
+				<div dojoType="dojox.widget.WizardPane" canGoBack="false">
+					<h1>Complete</h1>
+					<p>The license has been accepted.</p>
+				</div>
+			</div>
+			
+	</div>
+
+</body>
+</html>
+
+
diff --git a/dojox/wire.js b/dojox/wire.js
index b4886f1..3426381 100644
--- a/dojox/wire.js
+++ b/dojox/wire.js
@@ -1,12 +1,3 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire"]){
-dojo._hasResource["dojox.wire"]=true;
 dojo.provide("dojox.wire");
 dojo.require("dojox.wire._base");
-}
+
diff --git a/dojox/wire/CompositeWire.js b/dojox/wire/CompositeWire.js
index bd33da4..5dc145b 100644
--- a/dojox/wire/CompositeWire.js
+++ b/dojox/wire/CompositeWire.js
@@ -1,44 +1,99 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.CompositeWire"]){
-dojo._hasResource["dojox.wire.CompositeWire"]=true;
 dojo.provide("dojox.wire.CompositeWire");
+
 dojo.require("dojox.wire._base");
 dojo.require("dojox.wire.Wire");
-dojo.declare("dojox.wire.CompositeWire",dojox.wire.Wire,{_wireClass:"dojox.wire.CompositeWire",constructor:function(_1){
-this._initializeChildren(this.children);
-},_getValue:function(_2){
-if(!_2||!this.children){
-return _2;
-}
-var _3=(dojo.isArray(this.children)?[]:{});
-for(var c in this.children){
-_3[c]=this.children[c].getValue(_2);
-}
-return _3;
-},_setValue:function(_4,_5){
-if(!_4||!this.children){
-return _4;
-}
-for(var c in this.children){
-this.children[c].setValue(_5[c],_4);
-}
-return _4;
-},_initializeChildren:function(_6){
-if(!_6){
-return;
-}
-for(var c in _6){
-var _7=_6[c];
-_7.parent=this;
-if(!dojox.wire.isWire(_7)){
-_6[c]=dojox.wire.create(_7);
-}
-}
-}});
-}
+
+dojo.declare("dojox.wire.CompositeWire", dojox.wire.Wire, {
+	//	summary:
+	//		A Wire for composite values in object or array
+	//	description:
+	//		This class has multiple child Wires for object properties or array
+	//		elements.
+	//		When an object with Wires is specified to 'children' property, they
+	//		are used to get or set an object with property values.
+	//		When an array of Wiares is specified to 'children' property, they
+	//		are used to get or set an array with element values.
+	
+	_wireClass: "dojox.wire.CompositeWire",
+
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		Initialize properties
+		//	description:
+		//		If object properties or array elements specified in 'children'
+		//		property are not Wires, Wires are created from them as
+		//		arguments, with 'parent' property set to this Wire instance.
+		//	args:
+		//		Arguments to initialize properties
+		//		children:
+		//			An object or array containing child Wires
+		this._initializeChildren(this.children);
+	},
+	_getValue: function(/*Object||Array*/object){
+		//	summary:
+		//		Return an object with property values or an array with element
+		//		values
+		//	description:
+		//		This method calls getValue() method of the child Wires with
+		//		'object' argument and returns an object with the values as
+		//		properties or an arary of the values as elements.
+		//	object:
+		//		A root object
+		//	returns:
+		//		An object or array with values
+		if(!object || !this.children){
+			return object; //Object||Array
+		}
+
+		var value = (dojo.isArray(this.children) ? [] : {}); // array or object
+		for(var c in this.children){
+			value[c] = this.children[c].getValue(object);
+		}
+		return value;//Object||Array
+	},
+
+	_setValue: function(/*Object||Array*/object, /*Object||Array*/value){
+		//	summary:
+		//		Set an object properties or an array elements to an object
+		//	desription:
+		//		This method calls setValues() method of the child Wires with
+		//		a corresponding property or element in 'value' argument and
+		//		'object' argument.
+		//	object:
+		//		A root object
+		//	value:
+		//		An object or array with values to set
+		//	returns:
+		//		'object'
+		if(!object || !this.children){
+			return object; //Object||Array
+		}
+
+		for(var c in this.children){
+			this.children[c].setValue(value[c], object);
+		}
+		return object; //Object||Array
+	},
+
+	_initializeChildren: function(/*Object||Array*/children){
+		//	summary:
+		//		Initialize child Wires
+		//	description:
+		//		If object properties or array elements specified in 'children'
+		//		argument are not Wires, Wires are created from them as
+		//		arguments, with 'parent' property set to this Wire instance.
+		//	children:
+		//		An object or array containing child Wires
+		if(!children){
+			return; //undefined
+		}
+
+		for(var c in children){
+			var child = children[c];
+			child.parent = this;
+			if(!dojox.wire.isWire(child)){
+				children[c] = dojox.wire.create(child);
+			}
+		}
+	}
+});
diff --git a/dojox/wire/DataWire.js b/dojox/wire/DataWire.js
index 27b4dff..e18c8ed 100644
--- a/dojox/wire/DataWire.js
+++ b/dojox/wire/DataWire.js
@@ -1,84 +1,175 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.DataWire"]){
-dojo._hasResource["dojox.wire.DataWire"]=true;
 dojo.provide("dojox.wire.DataWire");
+
 dojo.require("dojox.wire.Wire");
-dojo.declare("dojox.wire.DataWire",dojox.wire.Wire,{_wireClass:"dojox.wire.DataWire",constructor:function(_1){
-if(!this.dataStore&&this.parent){
-this.dataStore=this.parent.dataStore;
-}
-},_getValue:function(_2){
-if(!_2||!this.attribute||!this.dataStore){
-return _2;
-}
-var _3=_2;
-var _4=this.attribute.split(".");
-for(var i in _4){
-_3=this._getAttributeValue(_3,_4[i]);
-if(!_3){
-return undefined;
-}
-}
-return _3;
-},_setValue:function(_5,_6){
-if(!_5||!this.attribute||!this.dataStore){
-return _5;
-}
-var _7=_5;
-var _8=this.attribute.split(".");
-var _9=_8.length-1;
-for(var i=0;i<_9;i++){
-_7=this._getAttributeValue(_7,_8[i]);
-if(!_7){
-return undefined;
-}
-}
-this._setAttributeValue(_7,_8[_9],_6);
-return _5;
-},_getAttributeValue:function(_a,_b){
-var _c=undefined;
-var i1=_b.indexOf("[");
-if(i1>=0){
-var i2=_b.indexOf("]");
-var _d=_b.substring(i1+1,i2);
-_b=_b.substring(0,i1);
-var _e=this.dataStore.getValues(_a,_b);
-if(_e){
-if(!_d){
-_c=_e;
-}else{
-_c=_e[_d];
-}
-}
-}else{
-_c=this.dataStore.getValue(_a,_b);
-}
-return _c;
-},_setAttributeValue:function(_f,_10,_11){
-var i1=_10.indexOf("[");
-if(i1>=0){
-var i2=_10.indexOf("]");
-var _12=_10.substring(i1+1,i2);
-_10=_10.substring(0,i1);
-var _13=null;
-if(!_12){
-_13=_11;
-}else{
-_13=this.dataStore.getValues(_f,_10);
-if(!_13){
-_13=[];
-}
-_13[_12]=_11;
-}
-this.dataStore.setValues(_f,_10,_13);
-}else{
-this.dataStore.setValue(_f,_10,_11);
-}
-}});
-}
+
+dojo.declare("dojox.wire.DataWire", dojox.wire.Wire, {
+	//	summary:
+	//		A Wire for item attributes of data stores
+	//	description:
+	//		This class accesses item attributes of data stores with a dotted
+	//		notation of attribute names specified to 'attribute' property,
+	//		using data APIs of a data store specified to 'dataStore' property.
+	//		The root object for this class must be an item of the data store.
+	//		Intermediate attribute names in the dotted notation specify
+	//		attributes for child items, which are used for repeated calls to
+	//		data APIs until reached to a descendant attribute.
+	//		Attribute names may have an array index, such as "a[0]", to
+	//		identify an array element of the attribute value.
+	
+	_wireClass: "dojox.wire.DataWire",
+
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		Initialize properties
+		//	description:
+		//		If 'dataStore' property is not specified, but 'parent' property
+		//		is specified, 'dataStore' property is copied from the parent.
+		//	args:
+		//		Arguments to initialize properties
+		//		dataStore:
+		//			A data store
+		//		attribute:
+		//			A dotted notation to a descendant attribute
+		if(!this.dataStore && this.parent){
+			this.dataStore = this.parent.dataStore;
+		}
+	},
+	_getValue: function(/*Object*/object){
+		//	summary:
+		//		Return an attribute value of an item
+		//	description:
+		//		This method uses a root item passed in 'object' argument and
+		//		'attribute' property to call getValue() method of
+		//		'dataStore'.
+		//		If an attribute name have an array suffix ("[]"), getValues()
+		//		method is called, instead.
+		//		If an index is specified in the array suffix, an array element
+		//		for the index is returned, instead of the array itself.
+		//	object:
+		//		A root item
+		//	returns:
+		//		A value found, otherwise 'undefined'
+		if(!object || !this.attribute || !this.dataStore){
+			return object; //Object
+		}
+
+		var value = object;
+		var list = this.attribute.split('.');
+		for(var i in list){
+			value = this._getAttributeValue(value, list[i]);
+			if(!value){
+				return undefined; //undefined
+			}
+		}
+		return value; //anything
+	},
+
+	_setValue: function(/*Object*/object, /*anything*/value){
+		//	summary:
+		//		Set an attribute value to an item
+		//	description:
+		//		This method uses a root item passed in 'object' argument and
+		//		'attribute' property to identify an item.
+		//		Then, setValue() method of 'dataStore' is called with a leaf
+		//		attribute name and 'value' argument.
+		//		If an attribute name have an array suffix ("[]"), setValues()
+		//		method is called, instead.
+		//		If an index is specified in the array suffix, an array element
+		//		for the index is set to 'value', instead of the array itself.
+		//	object:
+		//		A root item
+		//	value:
+		//		A value to set
+		//	returns:
+		//		'object', or 'undefined' for invalid attribute
+		if(!object || !this.attribute || !this.dataStore){
+			return object; //Object
+		}
+
+		var item = object;
+		var list = this.attribute.split('.');
+		var last = list.length - 1;
+		for(var i = 0; i < last; i++){
+			item = this._getAttributeValue(item, list[i]);
+			if(!item){
+				return undefined; //undefined
+			}
+		}
+		this._setAttributeValue(item, list[last], value);
+		return object; //Object
+	},
+
+	_getAttributeValue: function(/*Object*/item, /*String*/attribute){
+		//	summary:
+		//		Return an attribute value of an item
+		//	description:
+		//		This method uses an item passed in 'item' argument and
+		//		'attribute' argument to call getValue() method of 'dataStore'.
+		//		If an attribute name have an array suffix ("[]"), getValues()
+		//		method is called, instead.
+		//		If an index is specified in the array suffix, an array element
+		//		for the index is returned, instead of the array itself.
+		//	item:
+		//		An item
+		//	attribute
+		//		An attribute name
+		//	returns:
+		//		A value found, otherwise 'undefined'
+		var value = undefined;
+		var i1 = attribute.indexOf('[');
+		if(i1 >= 0){
+			var i2 = attribute.indexOf(']');
+			var index = attribute.substring(i1 + 1, i2);
+			attribute = attribute.substring(0, i1);
+			var array = this.dataStore.getValues(item, attribute);
+			if(array){
+				if(!index){ // return array for "attribute[]"
+					value = array;
+				}else{
+					value = array[index];
+				}
+			}
+		}else{
+			value = this.dataStore.getValue(item, attribute);
+		}
+		return value; //anything 
+	},
+
+	_setAttributeValue: function(/*Object*/item, /*String*/attribute, /*anything*/value){
+		//	summary:
+		//		Set an attribute value to an item
+		//	description:
+		//		This method uses an item passed in 'item' argument and
+		//		'attribute' argument to call setValue() method of 'dataStore'
+		//		with 'value' argument.
+		//		If an attribute name have an array suffix ("[]"), setValues()
+		//		method is called, instead.
+		//		If an index is specified in the array suffix, an array element
+		//		for the index is set to 'value', instead of the array itself.
+		//	item:
+		//		An item
+		//	attribute:
+		//		An attribute name
+		//	value:
+		//		A value to set
+		var i1 = attribute.indexOf('[');
+		if(i1 >= 0){
+			var i2 = attribute.indexOf(']');
+			var index = attribute.substring(i1 + 1, i2);
+			attribute = attribute.substring(0, i1);
+			var array = null;
+			if(!index){ // replace whole array for "attribute[]"
+				array = value;
+			}else{
+				array = this.dataStore.getValues(item, attribute);
+				if(!array){
+					array = [];
+				}
+				array[index] = value;
+			}
+			this.dataStore.setValues(item, attribute, array);
+		}else{
+			this.dataStore.setValue(item, attribute, value);
+		}
+	}
+});
diff --git a/dojox/wire/TableAdapter.js b/dojox/wire/TableAdapter.js
index b66cbad..292cb7f 100644
--- a/dojox/wire/TableAdapter.js
+++ b/dojox/wire/TableAdapter.js
@@ -1,37 +1,84 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.TableAdapter"]){
-dojo._hasResource["dojox.wire.TableAdapter"]=true;
 dojo.provide("dojox.wire.TableAdapter");
+
 dojo.require("dojox.wire.CompositeWire");
-dojo.declare("dojox.wire.TableAdapter",dojox.wire.CompositeWire,{_wireClass:"dojox.wire.TableAdapter",constructor:function(_1){
-this._initializeChildren(this.columns);
-},_getValue:function(_2){
-if(!_2||!this.columns){
-return _2;
-}
-var _3=_2;
-if(!dojo.isArray(_3)){
-_3=[_3];
-}
-var _4=[];
-for(var i in _3){
-var _5=this._getRow(_3[i]);
-_4.push(_5);
-}
-return _4;
-},_setValue:function(_6,_7){
-throw new Error("Unsupported API: "+this._wireClass+"._setValue");
-},_getRow:function(_8){
-var _9=(dojo.isArray(this.columns)?[]:{});
-for(var c in this.columns){
-_9[c]=this.columns[c].getValue(_8);
-}
-return _9;
-}});
-}
+
+dojo.declare("dojox.wire.TableAdapter", dojox.wire.CompositeWire, {
+	//	summary:
+	//		A composite Wire for table rows
+	//	description:
+	//		This class has multiple child Wires for object properties or array
+	//		elements of a table row.
+	//		The root object for this class must be an array.
+	//		When an object with Wires is specified to 'columns' property, they
+	//		are used to get a row object with property values.
+	//		When an array of Wires is specified to 'columns' property, they
+	//		are used to get a row array with element values.
+	//		The row values are returned in an array.
+	//		This class only supports getValue(), but not setValue().
+	
+	_wireClass: "dojox.wire.TableAdapter",
+	
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		Initialize properties
+		//	description:
+		//		If object properties or array elements specified in 'columns'
+		//		property are not Wires, Wires are created from them as
+		//		arguments, with 'parent' property set to this Wire instance.
+		//	args:
+		//		Arguments to initialize properties
+		//		columns:
+		//			An object or array containing child Wires for column values
+		this._initializeChildren(this.columns);
+	},
+
+	_getValue: function(/*Array*/object){
+		//	summary:
+		//		Return an array of table row value (object or array)
+		//	description:
+		//		This method iterates over an array specified to 'object'
+		//		argument and calls getValue() method of the child Wires with
+		//		each element of the array to get a row object or array.
+		//		Finally, an array with the row objects or arrays are retuned.
+		//	object:
+		//		A root array
+		//	returns:
+		//		An array of table row value
+		if(!object || !this.columns){
+			return object; //Array
+		}
+
+		var array = object;
+		if(!dojo.isArray(array)){
+			array = [array];
+		}
+
+		var rows = [];
+		for(var i in array){
+			var row = this._getRow(array[i]);
+			rows.push(row);
+		}
+		return rows; //Array
+	},
+
+	_setValue: function(/*Array*/object, /*Array*/value){
+		//	summary:
+		//		Not supported
+		throw new Error("Unsupported API: " + this._wireClass + "._setValue");
+	},
+
+	_getRow: function(/*Object||Array*/object){
+		//	summary:
+		//		Return an array or object for a table row
+		//	description:
+		//		This method calls getValue() method of the child Wires to
+		//		create a row object or array.
+		//	returns:
+		//		An array or object for a table row
+		var row = (dojo.isArray(this.columns) ? [] : {}); // array or object
+		for(var c in this.columns){
+			row[c] = this.columns[c].getValue(object);
+		}
+		return row; //Array||Object
+	}
+});
diff --git a/dojox/wire/TextAdapter.js b/dojox/wire/TextAdapter.js
index 6e733ce..8293bbe 100644
--- a/dojox/wire/TextAdapter.js
+++ b/dojox/wire/TextAdapter.js
@@ -1,40 +1,84 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.TextAdapter"]){
-dojo._hasResource["dojox.wire.TextAdapter"]=true;
 dojo.provide("dojox.wire.TextAdapter");
+
 dojo.require("dojox.wire.CompositeWire");
-dojo.declare("dojox.wire.TextAdapter",dojox.wire.CompositeWire,{_wireClass:"dojox.wire.TextAdapter",constructor:function(_1){
-this._initializeChildren(this.segments);
-if(!this.delimiter){
-this.delimiter="";
-}
-},_getValue:function(_2){
-if(!_2||!this.segments){
-return _2;
-}
-var _3="";
-for(var i in this.segments){
-var _4=this.segments[i].getValue(_2);
-_3=this._addSegment(_3,_4);
-}
-return _3;
-},_setValue:function(_5,_6){
-throw new Error("Unsupported API: "+this._wireClass+"._setValue");
-},_addSegment:function(_7,_8){
-if(!_8){
-return _7;
-}else{
-if(!_7){
-return _8;
-}else{
-return _7+this.delimiter+_8;
-}
-}
-}});
-}
+
+dojo.declare("dojox.wire.TextAdapter", dojox.wire.CompositeWire, {
+	//	summary:
+	//		A composite Wire for a concatenated text
+	//	description:
+	//		This class has multiple child Wires for text segment values.
+	//		Wires in 'segments' property are used to get text segments and
+	//		values are concatenated with an optional delimiter string specified
+	//		to 'delimiter' property.
+	
+	_wireClass: "dojox.wire.TextAdapter",
+	
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		Initialize properties
+		//	description:
+		//		If array elements specified in 'segments' are not Wires, Wires
+		//		are created from them as arguments, with 'parent' property set
+		//		to this Wire instance.
+		//	args:
+		//		Arguments to initialize properties
+		//		segments:
+		//			An array containing child Wires for text segment values
+		//		delimiter:
+		//			A delimiter string
+		this._initializeChildren(this.segments);
+		if(!this.delimiter){
+			this.delimiter = "";
+		}
+	},
+
+	_getValue: function(/*Object||Array*/object){
+		//	summary:
+		//		Return a concatenated text
+		//	description:
+		//		This method calls getValue() method of the child Wires wuth
+		//		'object' argument and concatenate the values with 'delimiter'
+		//		property to return.
+		//	arg:
+		//		A root object
+		//	returns:
+		//		A concatinated text
+		if(!object || !this.segments){
+			return object; //Object||Array
+		}
+
+		var text = "";
+		for(var i in this.segments){
+			var segment = this.segments[i].getValue(object);
+			text = this._addSegment(text, segment);
+		}
+		return text; //String
+	},
+
+	_setValue: function(/*Object||Array*/object, /*String*/value){
+		//	summary:
+		//		Not supported
+		throw new Error("Unsupported API: " + this._wireClass + "._setValue");
+	},
+
+	_addSegment: function(/*String*/text, /*String*/segment){
+		//	summary:
+		//		Return a concatenated text
+		//	description:
+		//		This method add a text segment specified to 'segment' argument
+		//		to a base text specified to 'text', with 'delimiter' property.
+		//	text:
+		//		A base text
+		//	segment:
+		//		A text segment to add
+		//	returns:
+		//		A concatinated text
+		if(!segment){
+			return text; //String
+		}else if(!text){
+			return segment; //String
+		}else{
+			return text + this.delimiter + segment; //String
+		}
+	}
+});
diff --git a/dojox/wire/TreeAdapter.js b/dojox/wire/TreeAdapter.js
index 15ba3ab..55897c0 100644
--- a/dojox/wire/TreeAdapter.js
+++ b/dojox/wire/TreeAdapter.js
@@ -1,88 +1,184 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.TreeAdapter"]){
-dojo._hasResource["dojox.wire.TreeAdapter"]=true;
 dojo.provide("dojox.wire.TreeAdapter");
+
 dojo.require("dojox.wire.CompositeWire");
-dojo.declare("dojox.wire.TreeAdapter",dojox.wire.CompositeWire,{_wireClass:"dojox.wire.TreeAdapter",constructor:function(_1){
-this._initializeChildren(this.nodes);
-},_getValue:function(_2){
-if(!_2||!this.nodes){
-return _2;
-}
-var _3=_2;
-if(!dojo.isArray(_3)){
-_3=[_3];
-}
-var _4=[];
-for(var i in _3){
-for(var i2 in this.nodes){
-_4=_4.concat(this._getNodes(_3[i],this.nodes[i2]));
-}
-}
-return _4;
-},_setValue:function(_5,_6){
-throw new Error("Unsupported API: "+this._wireClass+"._setValue");
-},_initializeChildren:function(_7){
-if(!_7){
-return;
-}
-for(var i in _7){
-var _8=_7[i];
-if(_8.node){
-_8.node.parent=this;
-if(!dojox.wire.isWire(_8.node)){
-_8.node=dojox.wire.create(_8.node);
-}
-}
-if(_8.title){
-_8.title.parent=this;
-if(!dojox.wire.isWire(_8.title)){
-_8.title=dojox.wire.create(_8.title);
-}
-}
-if(_8.children){
-this._initializeChildren(_8.children);
-}
-}
-},_getNodes:function(_9,_a){
-var _b=null;
-if(_a.node){
-_b=_a.node.getValue(_9);
-if(!_b){
-return [];
-}
-if(!dojo.isArray(_b)){
-_b=[_b];
-}
-}else{
-_b=[_9];
-}
-var _c=[];
-for(var i in _b){
-_9=_b[i];
-var _d={};
-if(_a.title){
-_d.title=_a.title.getValue(_9);
-}else{
-_d.title=_9;
-}
-if(_a.children){
-var _e=[];
-for(var i2 in _a.children){
-_e=_e.concat(this._getNodes(_9,_a.children[i2]));
-}
-if(_e.length>0){
-_d.children=_e;
-}
-}
-_c.push(_d);
-}
-return _c;
-}});
-}
+
+dojo.declare("dojox.wire.TreeAdapter", dojox.wire.CompositeWire, {
+	//	summary:
+	//		A composite Wire for tree nodes
+	//	description:
+	//		This class has multiple child Wires for tree nodes, their title and
+	//		child nodes.
+	//		The root object for this class must be an array.
+	//		'node' Wires in 'nodes' property is used to identify an object
+	//		representing a node.
+	//		'title' Wires in 'nodes' property is used to get the title string
+	//		of a node.
+	//		'children' Wires in 'nodes' property is used to iterate over child
+	//		node objects.
+	//		The node values are returned in an array as follows:
+	//			[
+	//				{title: title1,
+	//		  	 	children: [
+	//					{title: title2,
+	//					 child: ...},
+	//					{title: title3,
+	//					 child: ...},
+	//					...
+	//				]},
+	//				...
+	//			]
+	//		This class only supports getValue(), but not setValue().
+	
+	_wireClass: "dojox.wire.TreeAdapter",
+	
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		Initialize properties
+		//	description:
+		//		If object properties ('node', 'title' and 'children') of array
+		//		elements specified in 'nodes' property are not Wires, Wires are
+		//		created from them as arguments, with 'parent' property set to
+		//		this Wire instance.
+		//	args:
+		//		Arguments to initialize properties
+		//		nodes:
+		//			An array containing objects for child Wires for node values
+		this._initializeChildren(this.nodes);
+	},
+	_getValue: function(/*Array*/object){
+		//	summary:
+		//		Return an array of tree node values
+		//	description:
+		//		This method iterates over an array specified to 'object'
+		//		argument and calls getValue() method of 'node' Wires with each
+		//		element of the array to get object(s) that represetns nodes.
+		//		(If 'node' Wires are omitted, the array element is used for
+		//		further processing.)
+		//		Then, getValue() method of 'title' Wires are called to get
+		//		title strings for nodes.
+		//		(If 'title' Wires are omitted, the objects representing nodes
+		//		are used as title strings.)
+		//		And if an array of objects with 'node' and 'title' Wires is
+		//		specified to 'children', it is used to gather child nodes and
+		//		their title strings in the same way recursively.
+		//		Finally, an array of the top-level node objects are retuned.
+		//	object:
+		//		A root array
+		//	returns:
+		//		An array of tree node values
+		if(!object || !this.nodes){
+			return object; //Array
+		}
+
+		var array = object;
+		if(!dojo.isArray(array)){
+			array = [array];
+		}
+
+		var nodes = [];
+		for(var i in array){
+			for(var i2 in this.nodes){
+				nodes = nodes.concat(this._getNodes(array[i], this.nodes[i2]));
+			}
+		}
+		return nodes; //Array
+	},
+
+	_setValue: function(/*Array*/object, /*Array*/value){
+		//	summary:
+		//		Not supported
+		throw new Error("Unsupported API: " + this._wireClass + "._setValue");
+	},
+
+	_initializeChildren: function(/*Array*/children){
+		//	summary:
+		//		Initialize child Wires
+		//	description:
+		//		If 'node' or 'title' properties of array elements specified in
+		//		'children' argument are not Wires, Wires are created from them
+		//		as arguments, with 'parent' property set to this Wire instance.
+		//		If an array element has 'children' property, this method is
+		//		called recursively with it.
+		//	children:
+		//		An array of objects containing child Wires
+		if(!children){
+			return; //undefined
+		}
+
+		for(var i in children){
+			var child = children[i];
+			if(child.node){
+				child.node.parent = this;
+				if(!dojox.wire.isWire(child.node)){
+					child.node = dojox.wire.create(child.node);
+				}
+			}
+			if(child.title){
+				child.title.parent = this;
+				if(!dojox.wire.isWire(child.title)){
+					child.title = dojox.wire.create(child.title);
+				}
+			}
+			if(child.children){
+				this._initializeChildren(child.children);
+			}
+		}
+	},
+
+	_getNodes: function(/*Object*/object, /*Object*/child){
+		//	summary:
+		//		Return an array of tree node values
+		//	description:
+		//		This method calls getValue() method of 'node' Wires with
+		//		'object' argument to get object(s) that represents nodes.
+		//		(If 'node' Wires are omitted, 'object' is used for further
+		//		processing.)
+		//		Then, getValue() method of 'title' Wires are called to get
+		//		title strings for nodes.
+		//		(If 'title' Wires are omitted, the objects representing nodes
+		//		are used as title strings.)
+		//		And if an array of objects with 'node' and 'title' Wires is
+		//		specified to 'children', it is used to gather child nodes and
+		//		their title strings in the same way recursively.
+		//		Finally, an array of node objects are returned.
+		//	object:
+		//		An object
+		//	child:
+		//		An object with child Wires
+		//	returns:
+		var array = null;
+		if(child.node){
+			array = child.node.getValue(object);
+			if(!array){
+				return [];
+			}
+			if(!dojo.isArray(array)){
+				array = [array];
+			}
+		}else{
+			array = [object];
+		}
+
+		var nodes = [];
+		for(var i in array){
+			object = array[i];
+			var node = {};
+			if(child.title){
+				node.title = child.title.getValue(object);
+			}else{
+				node.title = object;
+			}
+			if(child.children){
+				var children = [];
+				for(var i2 in child.children){
+					children = children.concat(this._getNodes(object, child.children[i2]));
+				}
+				if(children.length > 0){
+					node.children = children;
+				}
+			}
+			nodes.push(node);
+		}
+		return nodes; //Array
+	}
+});
diff --git a/dojox/wire/Wire.js b/dojox/wire/Wire.js
index 529f68a..7ba703d 100644
--- a/dojox/wire/Wire.js
+++ b/dojox/wire/Wire.js
@@ -1,231 +1,377 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.Wire"]){
-dojo._hasResource["dojox.wire.Wire"]=true;
 dojo.provide("dojox.wire.Wire");
+
 dojo.require("dojox.wire._base");
-dojo.declare("dojox.wire.Wire",null,{_wireClass:"dojox.wire.Wire",constructor:function(_1){
-dojo.mixin(this,_1);
-if(this.converter){
-if(dojo.isString(this.converter)){
-var _2=dojo.getObject(this.converter);
-if(dojo.isFunction(_2)){
-try{
-var _3=new _2();
-if(_3&&!dojo.isFunction(_3["convert"])){
-this.converter={convert:_2};
-}else{
-this.converter=_3;
-}
-}
-catch(e){
-}
-}else{
-if(dojo.isObject(_2)){
-if(dojo.isFunction(_2["convert"])){
-this.converter=_2;
-}
-}
-}
-if(dojo.isString(this.converter)){
-var _4=dojox.wire._getClass(this.converter);
-if(_4){
-this.converter=new _4();
-}else{
-this.converter=undefined;
-}
-}
-}else{
-if(dojo.isFunction(this.converter)){
-this.converter={convert:this.converter};
-}
-}
-}
-},getValue:function(_5){
-var _6=undefined;
-if(dojox.wire.isWire(this.object)){
-_6=this.object.getValue(_5);
-}else{
-_6=(this.object||_5);
-}
-if(this.property){
-var _7=this.property.split(".");
-for(var i in _7){
-if(!_6){
-return _6;
-}
-_6=this._getPropertyValue(_6,_7[i]);
-}
-}
-var _8=undefined;
-if(this._getValue){
-_8=this._getValue(_6);
-}else{
-_8=_6;
-}
-if(_8){
-if(this.type){
-if(this.type=="string"){
-_8=_8.toString();
-}else{
-if(this.type=="number"){
-_8=parseInt(_8,10);
-}else{
-if(this.type=="boolean"){
-_8=(_8!="false");
-}else{
-if(this.type=="array"){
-if(!dojo.isArray(_8)){
-_8=[_8];
-}
-}
-}
-}
-}
-}
-if(this.converter&&this.converter.convert){
-_8=this.converter.convert(_8,this);
-}
-}
-return _8;
-},setValue:function(_9,_a){
-var _b=undefined;
-if(dojox.wire.isWire(this.object)){
-_b=this.object.getValue(_a);
-}else{
-_b=(this.object||_a);
-}
-var _c=undefined;
-var o;
-if(this.property){
-if(!_b){
-if(dojox.wire.isWire(this.object)){
-_b={};
-this.object.setValue(_b,_a);
-}else{
-throw new Error(this._wireClass+".setValue(): invalid object");
-}
-}
-var _d=this.property.split(".");
-var _e=_d.length-1;
-for(var i=0;i<_e;i++){
-var p=_d[i];
-o=this._getPropertyValue(_b,p);
-if(!o){
-o={};
-this._setPropertyValue(_b,p,o);
-}
-_b=o;
-}
-_c=_d[_e];
-}
-if(this._setValue){
-if(_c){
-o=this._getPropertyValue(_b,_c);
-if(!o){
-o={};
-this._setPropertyValue(_b,_c,o);
-}
-_b=o;
-}
-var _f=this._setValue(_b,_9);
-if(!_b&&_f){
-if(dojox.wire.isWire(this.object)){
-this.object.setValue(_f,_a);
-}else{
-throw new Error(this._wireClass+".setValue(): invalid object");
-}
-}
-}else{
-if(_c){
-this._setPropertyValue(_b,_c,_9);
-}else{
-if(dojox.wire.isWire(this.object)){
-this.object.setValue(_9,_a);
-}else{
-throw new Error(this._wireClass+".setValue(): invalid property");
-}
-}
-}
-},_getPropertyValue:function(_10,_11){
-var _12=undefined;
-var i1=_11.indexOf("[");
-if(i1>=0){
-var i2=_11.indexOf("]");
-var _13=_11.substring(i1+1,i2);
-var _14=null;
-if(i1===0){
-_14=_10;
-}else{
-_11=_11.substring(0,i1);
-_14=this._getPropertyValue(_10,_11);
-if(_14&&!dojo.isArray(_14)){
-_14=[_14];
-}
-}
-if(_14){
-_12=_14[_13];
-}
-}else{
-if(_10.getPropertyValue){
-_12=_10.getPropertyValue(_11);
-}else{
-var _15="get"+_11.charAt(0).toUpperCase()+_11.substring(1);
-if(this._useAttr(_10)){
-_12=_10.attr(_11);
-}else{
-if(_10[_15]){
-_12=_10[_15]();
-}else{
-_12=_10[_11];
-}
-}
-}
-}
-return _12;
-},_setPropertyValue:function(_16,_17,_18){
-var i1=_17.indexOf("[");
-if(i1>=0){
-var i2=_17.indexOf("]");
-var _19=_17.substring(i1+1,i2);
-var _1a=null;
-if(i1===0){
-_1a=_16;
-}else{
-_17=_17.substring(0,i1);
-_1a=this._getPropertyValue(_16,_17);
-if(!_1a){
-_1a=[];
-this._setPropertyValue(_16,_17,_1a);
-}
-}
-_1a[_19]=_18;
-}else{
-if(_16.setPropertyValue){
-_16.setPropertyValue(_17,_18);
-}else{
-var _1b="set"+_17.charAt(0).toUpperCase()+_17.substring(1);
-if(this._useAttr(_16)){
-_16.attr(_17,_18);
-}else{
-if(_16[_1b]){
-_16[_1b](_18);
-}else{
-_16[_17]=_18;
-}
-}
-}
-}
-},_useAttr:function(_1c){
-var _1d=false;
-if(dojo.isFunction(_1c.attr)){
-_1d=true;
-}
-return _1d;
-}});
-}
+
+dojo.declare("dojox.wire.Wire", null, {
+	//	summary:
+	//		A default and base Wire to access an object property
+	//	description:
+	//		This class accesses a property of an object with a dotted notation
+	//		specified to 'property' property, such as "a.b.c", which identifies
+	//		a descendant property, "object.a.b.c".
+	//		Property names in the dotted notation may have an array index, such
+	//		as "a[0]", to identify an array element, literally, "object.a[0]".
+	//		When a notation start with an array index, such as "[0].a", it
+	//		specifies an array element of the root object (array),
+	//		"object[0].a".
+	//		This class also serves as a base class for other Wire classes,
+	//		preparing a root object and converting a return value, so that
+	//		sub-classes just can implement _getValue() and _setValue() called
+	//		from getValue() and setValue() implemented by this calss.
+	
+	_wireClass: "dojox.wire.Wire",
+	
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		Initialize properties
+		//	description:
+		//		If 'converter' property is specified and is a string for
+		//		a converter class, an instanceof the converter class is
+		//		created.
+		//	args:
+		//		Arguments to initialize properties
+		//		object:
+		//			A root object (or another Wire to access a root object)
+		//		property:
+		//			A dotted notation to a descendant property
+		//		type:
+		//			A type of the return value (for the source Wire)
+		//		converter:
+		//			A converter object (or class name) to convert the return
+		//			value (for the source Wire)
+		dojo.mixin(this, args);
+
+		if(this.converter){
+			if(dojo.isString(this.converter)){
+				//First check the object tree for it.  Might be defined variable
+				//name/global function (like a jsId, or just a function name).
+				var convertObject = dojo.getObject(this.converter);
+				if(dojo.isFunction(convertObject)){
+					//We need to see if this is a pure function or an object constructor...
+					try{
+						var testObj = new convertObject();
+						if(testObj && !dojo.isFunction(testObj["convert"])){
+							//Looks like a 'pure' function...
+							this.converter = {convert: convertObject};
+						}else{
+							this.converter = testObj;
+						}
+					}catch(e){
+						//Do if this fails.	
+					}
+				}else if(dojo.isObject(convertObject)){
+					//It's an object, like a jsId ... see if it has a convert function
+					if(dojo.isFunction(convertObject["convert"])){
+						this.converter = convertObject;
+					}
+				}
+
+				//No object with that name (Converter is still a string), 
+				//then look for a class that needs to be dynamically loaded...
+				if(dojo.isString(this.converter)){
+					var converterClass = dojox.wire._getClass(this.converter);
+					if(converterClass){
+						this.converter = new converterClass();
+					}else{
+						this.converter = undefined;
+					}
+				}
+			}else if(dojo.isFunction(this.converter)){
+				this.converter = {convert: this.converter};
+			}
+		}
+	},
+
+	getValue: function(/*Object||Array*/defaultObject){
+		//	summary:
+		//		Return a value of an object
+		//	description:
+		//		This method first determins a root object as follows:
+		//		1. If 'object' property specified,
+		//		1.1 If 'object' is a Wire, its getValue() method is called to
+		//	    	obtain a root object.
+		//		1.2 Otherwise, use 'object' as a root object.
+		//		2. Otherwise, use 'defaultObject' argument.
+		//		3. If 'property' is specified, it is used to get a property
+		//			value.
+		//		Then, if a sub-class implements _getValue() method, it is
+		//		called with the root object to get the return value.
+		//		Otherwise, the root object (typically, a property valye) is
+		//		used for the return value.
+		//		Finally, if 'type' property is specified, the return value is
+		//		converted to the specified primitive type ("string", "number",
+		//		"boolean" and "array").
+		//		If 'converter' property is specified, its convert() method is
+		//		called to convert the value.
+		//	defaultObject:
+		//		A default root object
+		//	returns:
+		//		A value found
+		var object = undefined;
+		if(dojox.wire.isWire(this.object)){
+			object = this.object.getValue(defaultObject);
+		}else{
+			object = (this.object || defaultObject);
+		}
+
+		if(this.property){
+			var list = this.property.split('.');
+			for(var i in list){
+				if(!object){
+					return object; //anything (null, undefined, etc)
+				}
+				object = this._getPropertyValue(object, list[i]);
+			}
+		}
+
+		var value = undefined;
+		if(this._getValue){
+			value = this._getValue(object);
+		}else{
+			value = object;
+		}
+
+		if(value){
+			if(this.type){
+				if(this.type == "string"){
+					value = value.toString();
+				}else if(this.type == "number"){
+					value = parseInt(value, 10);
+				}else if(this.type == "boolean"){
+					value = (value != "false");
+				}else if(this.type == "array"){
+					if(!dojo.isArray(value)){
+						value = [value];
+					}
+				}
+			}
+			if(this.converter && this.converter.convert){
+				value = this.converter.convert(value, this); // optional "this" context
+			}
+		}
+		return value; //anything
+	},
+
+	setValue: function(/*anything*/value, /*Object||Array*/defaultObject){
+		//	summary:
+		//		Set a value to an object
+		//	description:
+		//		This method first determins a root object as follows:
+		//		1. If 'object' property specified,
+		//		1.1 If 'object' is a Wire, its getValue() method is called to
+		//	    	obtain a root object.
+		//		1.2 Otherwise, use 'object' as a root object.
+		//		2. Otherwise, use 'defaultObject' argument.
+		//		3. If 'property' is specified, it is used to get a property
+		//			value.
+		//		Then, if a sub-class implements _setValue() method, it is
+		//		called with the root object and 'value' argument to set
+		//		the value.
+		//		Otherwise, 'value' is set to a property specified with
+		//		'property' property.
+		//		If the root object is undefined and 'object' property is a Wire
+		//		and a new object is created and returned by _setValue() it is
+		//		set through 'object' (setValue() method).
+		//	value:
+		//		A value to set
+		//	defaultObject:
+		//		A default root object
+		var object = undefined;
+		if(dojox.wire.isWire(this.object)){
+			object = this.object.getValue(defaultObject);
+		}else{
+			object = (this.object || defaultObject);
+		}
+
+		var property = undefined;
+		var o;
+		if(this.property){
+			if(!object){
+				if(dojox.wire.isWire(this.object)){
+					object = {};
+					this.object.setValue(object, defaultObject);
+				}else{
+					throw new Error(this._wireClass + ".setValue(): invalid object");
+				}
+			}
+			var list = this.property.split('.');
+			var last = list.length - 1;
+			for(var i = 0; i < last; i++){
+				var p = list[i];
+				o = this._getPropertyValue(object, p);
+				if(!o){
+					o = {};
+					this._setPropertyValue(object, p, o);
+				}
+				object = o;
+			}
+			property = list[last];
+		}
+
+		if(this._setValue){
+			if(property){
+				o = this._getPropertyValue(object, property);
+				if(!o){
+					o = {};
+					this._setPropertyValue(object, property, o);
+				}
+				object = o;
+			}
+			var newObject = this._setValue(object, value);
+			if(!object && newObject){
+				if(dojox.wire.isWire(this.object)){
+					this.object.setValue(newObject, defaultObject);
+				}else{
+					throw new Error(this._wireClass + ".setValue(): invalid object");
+				}
+			}
+		}else{
+			if(property){
+				this._setPropertyValue(object, property, value);
+			}else{
+				if(dojox.wire.isWire(this.object)){
+					this.object.setValue(value, defaultObject);
+				}else{
+					throw new Error(this._wireClass + ".setValue(): invalid property");
+				}
+			}
+		}
+	},
+
+	_getPropertyValue: function(/*Object||Array*/object, /*String*/property){
+		//	summary:
+		//		Return a property value of an object
+		//	description:
+		//		A value for 'property' of 'object' is returned.
+		//		If 'property' ends with an array index, it is used to indentify
+		//		an element of an array property.
+		//		If 'object' implements getPropertyValue(), it is called with
+		//		'property' to obtain the property value.
+		//		If 'object' implements a getter for the property, it is called
+		//		to obtain the property value.
+		//	object:
+		//		A default root object
+		//	property:
+		//		A property name
+		//	returns:
+		//		A value found, otherwise 'undefined'
+		var value = undefined;
+		var i1 = property.indexOf('[');
+		if(i1 >= 0){
+			var i2 = property.indexOf(']');
+			var index = property.substring(i1 + 1, i2);
+			var array = null;
+			if(i1 === 0){ // object is array
+				array = object;
+			}else{
+				property = property.substring(0, i1);
+				array = this._getPropertyValue(object, property);
+				if(array && !dojo.isArray(array)){
+					array = [array];
+				}
+			}
+			if(array){
+				value = array[index];
+			}
+		}else if(object.getPropertyValue){
+			value = object.getPropertyValue(property);
+		}else{
+			var getter = "get" + property.charAt(0).toUpperCase() + property.substring(1);
+			if(this._useGet(object)){
+				value = object.get(property);
+			}else if(this._useAttr(object)){
+				value = object.attr(property);
+			} else if(object[getter]){
+				value = object[getter]();
+			}else{
+				value = object[property];
+			}
+		}
+		return value; //anything
+	},
+
+	_setPropertyValue: function(/*Object||Array*/object, /*String*/property, /*anything*/value){
+		//	summary:
+		//		Set a property value to an object
+		//	description:
+		//		'value' is set to 'property' of 'object'.
+		//		If 'property' ends with an array index, it is used to indentify
+		//		an element of an array property to set the value.
+		//		If 'object' implements setPropertyValue(), it is called with
+		//		'property' and 'value' to set the property value.
+		//		If 'object' implements a setter for the property, it is called
+		//		with 'value' to set the property value.
+		//	object:
+		//		An object
+		//	property:
+		//		A property name
+		//	value:
+		//		A value to set
+		var i1 = property.indexOf('[');
+		if(i1 >= 0){
+			var i2 = property.indexOf(']');
+			var index = property.substring(i1 + 1, i2);
+			var array = null;
+			if(i1 === 0){ // object is array
+				array = object;
+			}else{
+				property = property.substring(0, i1);
+				array = this._getPropertyValue(object, property);
+				if(!array){
+					array = [];
+					this._setPropertyValue(object, property, array);
+				}
+			}
+			array[index] = value;
+		}else if(object.setPropertyValue){
+			object.setPropertyValue(property, value);
+		}else{
+			var setter = "set" + property.charAt(0).toUpperCase() + property.substring(1);
+			if(this._useSet(object)){
+				object.set(property, value);
+			}else if(this._useAttr(object)){
+				object.attr(property, value);
+			}else if(object[setter]){
+				object[setter](value);
+			}else{
+				object[property] = value;
+			}
+		}
+	},
+
+	_useGet: function(object){
+		// summary:
+		//		Function to detect if dijit.get support exists on the target
+		// object:
+		//		The target object to set the property of.
+		var useGet = false;
+		if(dojo.isFunction(object.get)){
+			useGet = true;
+		}
+		return useGet;
+	},
+
+	_useSet: function(object){
+		// summary:
+		//		Function to detect if dijit.set support exists on the target
+		// object:
+		//		The target object to set the property of.
+		var useSet = false;
+		if(dojo.isFunction(object.set)){
+			useSet = true;
+		}
+		return useSet;
+	},
+
+	_useAttr: function(object){
+		// summary:
+		//		Function to detect if dijit.attr support exists on the target
+		// object:
+		//		The target object to set the property of.
+		var useAttr = false;
+		if(dojo.isFunction(object.attr)){
+			useAttr = true;
+		}
+		return useAttr;
+	}
+});
diff --git a/dojox/wire/XmlWire.js b/dojox/wire/XmlWire.js
index 9fbc833..ca5e0af 100644
--- a/dojox/wire/XmlWire.js
+++ b/dojox/wire/XmlWire.js
@@ -1,135 +1,242 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.XmlWire"]){
-dojo._hasResource["dojox.wire.XmlWire"]=true;
 dojo.provide("dojox.wire.XmlWire");
+
 dojo.require("dojox.xml.parser");
 dojo.require("dojox.wire.Wire");
-dojo.declare("dojox.wire.XmlWire",dojox.wire.Wire,{_wireClass:"dojox.wire.XmlWire",constructor:function(_1){
-},_getValue:function(_2){
-if(!_2||!this.path){
-return _2;
-}
-var _3=_2;
-var _4=this.path;
-var i;
-if(_4.charAt(0)=="/"){
-i=_4.indexOf("/",1);
-_4=_4.substring(i+1);
-}
-var _5=_4.split("/");
-var _6=_5.length-1;
-for(i=0;i<_6;i++){
-_3=this._getChildNode(_3,_5[i]);
-if(!_3){
-return undefined;
-}
-}
-var _7=this._getNodeValue(_3,_5[_6]);
-return _7;
-},_setValue:function(_8,_9){
-if(!this.path){
-return _8;
-}
-var _a=_8;
-var _b=this._getDocument(_a);
-var _c=this.path;
-var i;
-if(_c.charAt(0)=="/"){
-i=_c.indexOf("/",1);
-if(!_a){
-var _d=_c.substring(1,i);
-_a=_b.createElement(_d);
-_8=_a;
-}
-_c=_c.substring(i+1);
-}else{
-if(!_a){
-return undefined;
-}
-}
-var _e=_c.split("/");
-var _f=_e.length-1;
-for(i=0;i<_f;i++){
-var _10=this._getChildNode(_a,_e[i]);
-if(!_10){
-_10=_b.createElement(_e[i]);
-_a.appendChild(_10);
-}
-_a=_10;
-}
-this._setNodeValue(_a,_e[_f],_9);
-return _8;
-},_getNodeValue:function(_11,exp){
-var _12=undefined;
-if(exp.charAt(0)=="@"){
-var _13=exp.substring(1);
-_12=_11.getAttribute(_13);
-}else{
-if(exp=="text()"){
-var _14=_11.firstChild;
-if(_14){
-_12=_14.nodeValue;
-}
-}else{
-_12=[];
-for(var i=0;i<_11.childNodes.length;i++){
-var _15=_11.childNodes[i];
-if(_15.nodeType===1&&_15.nodeName==exp){
-_12.push(_15);
-}
-}
-}
-}
-return _12;
-},_setNodeValue:function(_16,exp,_17){
-if(exp.charAt(0)=="@"){
-var _18=exp.substring(1);
-if(_17){
-_16.setAttribute(_18,_17);
-}else{
-_16.removeAttribute(_18);
-}
-}else{
-if(exp=="text()"){
-while(_16.firstChild){
-_16.removeChild(_16.firstChild);
-}
-if(_17){
-var _19=this._getDocument(_16).createTextNode(_17);
-_16.appendChild(_19);
-}
-}
-}
-},_getChildNode:function(_1a,_1b){
-var _1c=1;
-var i1=_1b.indexOf("[");
-if(i1>=0){
-var i2=_1b.indexOf("]");
-_1c=_1b.substring(i1+1,i2);
-_1b=_1b.substring(0,i1);
-}
-var _1d=1;
-for(var i=0;i<_1a.childNodes.length;i++){
-var _1e=_1a.childNodes[i];
-if(_1e.nodeType===1&&_1e.nodeName==_1b){
-if(_1d==_1c){
-return _1e;
-}
-_1d++;
-}
-}
-return null;
-},_getDocument:function(_1f){
-if(_1f){
-return (_1f.nodeType==9?_1f:_1f.ownerDocument);
-}else{
-return dojox.xml.parser.parse();
-}
-}});
-}
+
+dojo.declare("dojox.wire.XmlWire", dojox.wire.Wire, {
+	//	summary:
+	//		A Wire for XML nodes or values (element, attribute and text)
+	//	description:
+	//		This class accesses XML nodes or value with a simplified XPath
+	//		specified to 'path' property.
+	//		The root object for this class must be an DOM document or element
+	//		node.
+	//		"@name" accesses to an attribute value of an element and "text()"
+	//		accesses to a text value of an element.
+	//		The hierarchy of the elements from the root node can be specified
+	//		with slash-separated list, such as "a/b/@c", which specifies
+	//		the value of an attribute named "c" of an element named "b" as
+	//		a child of another element named "a" of a child of the root node.
+	
+	_wireClass: "dojox.wire.XmlWire",
+	
+	constructor: function(/*Object*/args){
+		//	summary:
+		//		Initialize properties
+		//	description:
+		//		'args' is just mixed in with no further processing.
+		//	args:
+		//		Arguments to initialize properties
+		//		path:
+		//			A simplified XPath to an attribute, a text or elements
+	},
+	_getValue: function(/*Node*/object){
+		//	summary:
+		//		Return an attribute value, a text value or an array of elements
+		//	description:
+		//		This method first uses a root node passed in 'object' argument
+		//		and 'path' property to identify an attribute, a text or
+		//		elements.
+		//		If 'path' starts with a slash (absolute), the first path
+		//		segment is ignored assuming it point to the root node.
+		//		(That is, "/a/b/@c" and "b/@c" against a root node access
+		//		the same attribute value, assuming the root node is an element
+		//		with a tag name, "a".)
+		//	object:
+		//		A root node
+		//	returns:
+		//		A value found, otherwise 'undefined'
+		if(!object || !this.path){
+			return object; //Node
+		}
+
+		var node = object;
+		var path = this.path;
+		var i;
+		if(path.charAt(0) == '/'){ // absolute
+			// skip the first expression (supposed to select the top node)
+			i = path.indexOf('/', 1);
+			path = path.substring(i + 1);
+		}
+		var list = path.split('/');
+		var last = list.length - 1;
+		for(i = 0; i < last; i++){
+			node = this._getChildNode(node, list[i]);
+			if(!node){
+				return undefined; //undefined
+			}
+		}
+		var value = this._getNodeValue(node, list[last]);
+		return value; //String||Array
+	},
+
+	_setValue: function(/*Node*/object, /*String*/value){
+		//	summary:
+		//		Set an attribute value or a child text value to an element
+		//	description:
+		//		This method first uses a root node passed in 'object' argument
+		//		and 'path' property to identify an attribute, a text or
+		//		elements.
+		//		If an intermediate element does not exist, it creates
+		//		an element of the tag name in the 'path' segment as a child
+		//		node of the current node.
+		//		Finally, 'value' argument is set to an attribute or a text
+		//		(a child node) of the leaf element.
+		//	object:
+		//		A root node
+		//	value:
+		//		A value to set
+		if(!this.path){
+			return object; //Node
+		}
+
+		var node = object;
+		var doc = this._getDocument(node);
+		var path = this.path;
+		var i;
+		if(path.charAt(0) == '/'){ // absolute
+			i = path.indexOf('/', 1);
+			if(!node){
+				var name = path.substring(1, i);
+				node = doc.createElement(name);
+				object = node; // to be returned as a new object
+			}
+			// skip the first expression (supposed to select the top node)
+			path = path.substring(i + 1);
+		}else{
+			if(!node){
+				return undefined; //undefined
+			}
+		}
+
+		var list = path.split('/');
+		var last = list.length - 1;
+		for(i = 0; i < last; i++){
+			var child = this._getChildNode(node, list[i]);
+			if(!child){
+				child = doc.createElement(list[i]);
+				node.appendChild(child);
+			}
+			node = child;
+		}
+		this._setNodeValue(node, list[last], value);
+		return object; //Node
+	},
+
+	_getNodeValue: function(/*Node*/node, /*String*/exp){
+		//	summary:
+		//		Return an attribute value, a text value or an array of elements
+		//	description:
+		//		If 'exp' starts with '@', an attribute value of the specified
+		//		attribute is returned.
+		//		If 'exp' is "text()", a child text value is returned.
+		//		Otherwise, an array of child elements, the tag name of which
+		//		match 'exp', is returned.
+		//	node:
+		//		A node
+		//	exp:
+		//		An expression for attribute, text or elements
+		//	returns:
+		//		A value found, otherwise 'undefined'
+		var value = undefined;
+		if(exp.charAt(0) == '@'){
+			var attribute = exp.substring(1);
+			value = node.getAttribute(attribute);
+		}else if(exp == "text()"){
+			var text = node.firstChild;
+			if(text){
+				value = text.nodeValue;
+			}
+		}else{ // assume elements
+			value = [];
+			for(var i = 0; i < node.childNodes.length; i++){
+				var child = node.childNodes[i];
+				if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == exp){
+					value.push(child);
+				}
+			}
+		}
+		return value; //String||Array
+	},
+
+	_setNodeValue: function(/*Node*/node, /*String*/exp, /*String*/value){
+		//	summary:
+		//		Set an attribute value or a child text value to an element
+		//	description:
+		//		If 'exp' starts with '@', 'value' is set to the specified
+		//		attribute.
+		//		If 'exp' is "text()", 'value' is set to a child text.
+		//	node:
+		//		A node
+		//	exp:
+		//		An expression for attribute or text
+		//	value:
+		//		A value to set
+		if(exp.charAt(0) == '@'){
+			var attribute = exp.substring(1);
+			if(value){
+				node.setAttribute(attribute, value);
+			}else{
+				node.removeAttribute(attribute);
+			}
+		}else if(exp == "text()"){
+			while(node.firstChild){
+				node.removeChild(node.firstChild);
+			}
+			if(value){
+				var text = this._getDocument(node).createTextNode(value);
+				node.appendChild(text);
+			}
+		}
+		// else not supported
+	},
+
+	_getChildNode: function(/*Node*/node, /*String*/name){
+		//	summary:
+		//		Return a child node
+		//	description:
+		//		A child element of the tag name specified with 'name' is
+		//		returned.
+		//		If 'name' ends with an array index, it is used to pick up
+		//		the corresponding element from multiple child elements.
+		//	node:
+		//		A parent node
+		//	name:
+		//		A tag name	
+		//	returns:
+		//		A child node
+		var index = 1;
+		var i1 = name.indexOf('[');
+		if(i1 >= 0){
+			var i2 = name.indexOf(']');
+			index = name.substring(i1 + 1, i2);
+			name = name.substring(0, i1);
+		}
+		var count = 1;
+		for(var i = 0; i < node.childNodes.length; i++){
+			var child = node.childNodes[i];
+			if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == name){
+				if(count == index){
+					return child; //Node
+				}
+				count++;
+			}
+		}
+		return null; //null
+	},
+
+	_getDocument: function(/*Node*/node){
+		//	summary:
+		//		Return a DOM document
+		//	description:
+		//		If 'node' is specified, a DOM document of the node is returned.
+		//		Otherwise, a DOM document is created.
+		//	returns:
+		//		A DOM document
+		if(node){
+			return (node.nodeType == 9 /* DOCUMENT_NODE */ ? node : node.ownerDocument); //Document
+		}else{
+			return dojox.xml.parser.parse(); //Document
+		}
+	}
+});
diff --git a/dojox/wire/_base.js b/dojox/wire/_base.js
index bc50dad..d508a53 100644
--- a/dojox/wire/_base.js
+++ b/dojox/wire/_base.js
@@ -1,102 +1,191 @@
-/*
-	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
-*/
+dojo.provide("dojox.wire._base");
 
+dojox.wire._defaultWireClass = "dojox.wire.Wire";
 
-if(!dojo._hasResource["dojox.wire._base"]){
-dojo._hasResource["dojox.wire._base"]=true;
-dojo.provide("dojox.wire._base");
-dojox.wire._defaultWireClass="dojox.wire.Wire";
-dojox.wire._wireClasses={"attribute":"dojox.wire.DataWire","path":"dojox.wire.XmlWire","children":"dojox.wire.CompositeWire","columns":"dojox.wire.TableAdapter","nodes":"dojox.wire.TreeAdapter","segments":"dojox.wire.TextAdapter"};
-dojox.wire.register=function(_1,_2){
-if(!_1||!_2){
-return;
-}
-if(dojox.wire._wireClasses[_2]){
-return;
-}
-dojox.wire._wireClasses[_2]=_1;
+dojox.wire._wireClasses = {
+	"attribute": "dojox.wire.DataWire",
+	"path": "dojox.wire.XmlWire",
+	"children": "dojox.wire.CompositeWire",
+	"columns": "dojox.wire.TableAdapter",
+	"nodes": "dojox.wire.TreeAdapter",
+	"segments": "dojox.wire.TextAdapter"
 };
-dojox.wire._getClass=function(_3){
-dojo["require"](_3);
-return dojo.getObject(_3);
+
+dojox.wire.register = function(/*Function||String*/wireClass, /*String*/key){
+	//	summary:
+	//		Register a Wire class
+	//	desription:
+	//		The specified Wire class or a class name is registered with
+	//		a key property of arguments to create a Wire
+	//	wireClass:
+	//		A class or full qualified class name
+	//	key:
+	//		A key property of arguments to create a Wire
+	if(!wireClass || !key){
+		return; //undefined
+	}
+	if(dojox.wire._wireClasses[key]){ // key already in use
+		return; //undefined
+	}
+	dojox.wire._wireClasses[key] = wireClass;
 };
-dojox.wire.create=function(_4){
-if(!_4){
-_4={};
-}
-var _5=_4.wireClass;
-if(_5){
-if(dojo.isString(_5)){
-_5=dojox.wire._getClass(_5);
-}
-}else{
-for(var _6 in _4){
-if(!_4[_6]){
-continue;
-}
-_5=dojox.wire._wireClasses[_6];
-if(_5){
-if(dojo.isString(_5)){
-_5=dojox.wire._getClass(_5);
-dojox.wire._wireClasses[_6]=_5;
-}
-break;
-}
-}
-}
-if(!_5){
-if(dojo.isString(dojox.wire._defaultWireClass)){
-dojox.wire._defaultWireClass=dojox.wire._getClass(dojox.wire._defaultWireClass);
-}
-_5=dojox.wire._defaultWireClass;
-}
-return new _5(_4);
+
+dojox.wire._getClass = function(/*String*/name){
+	//	summary:
+	//		Returns a class 
+	//	description:
+	//		The class is loaded by dojo.require() and returned
+	//		by dojo.getObject().
+	//	name:
+	//		A class name
+	//	returns:
+	//		A class
+	dojo["require"](name); // use dojo["require"] instead of dojo.require to avoid a build problem
+	return dojo.getObject(name); //Function
 };
-dojox.wire.isWire=function(_7){
-return (_7&&_7._wireClass);
+
+dojox.wire.create = function(/*Object*/args){
+	//	summary:
+	//		Create a Wire from arguments
+	//	description:
+	//		If 'args' specifies 'wireClass', it is used as a class or full
+	//		qualified class name to create a Wire with 'args' as arguments.
+	//		Otherwise, a Wire class is determined by other proeprties of 'args'
+	//		checking if 'args' specifies a key property for a Wire class.
+	//		If no key property found, the default Wire class is used.
+	//	args:
+	//		Arguments to create a Wire
+	//	returns:
+	//		A Wire
+	if(!args){
+		args = {};
+	}
+	var wireClass = args.wireClass;
+	if(wireClass){
+		if(dojo.isString(wireClass)){
+			wireClass = dojox.wire._getClass(wireClass);
+		}
+	}else{
+		for(var key in args){
+			if(!args[key]){
+				continue;
+			}
+			wireClass = dojox.wire._wireClasses[key];
+			if(wireClass){
+				if(dojo.isString(wireClass)){
+					wireClass = dojox.wire._getClass(wireClass);
+					dojox.wire._wireClasses[key] = wireClass;
+				}
+				break;
+			}
+		}
+	}
+	if(!wireClass){
+		if(dojo.isString(dojox.wire._defaultWireClass)){
+			dojox.wire._defaultWireClass = dojox.wire._getClass(dojox.wire._defaultWireClass);
+		}
+		wireClass = dojox.wire._defaultWireClass;
+	}
+	return new wireClass(args); //Object
 };
-dojox.wire.transfer=function(_8,_9,_a,_b){
-if(!_8||!_9){
-return;
-}
-if(!dojox.wire.isWire(_8)){
-_8=dojox.wire.create(_8);
-}
-if(!dojox.wire.isWire(_9)){
-_9=dojox.wire.create(_9);
-}
-var _c=_8.getValue(_a);
-_9.setValue(_c,(_b||_a));
+
+dojox.wire.isWire = function(/*Object*/wire){
+	//	summary:
+	//		Check if an object is a Wire
+	//	description:
+	//		If the specified object is a Wire, true is returned.
+	//		Otherwise, false is returned.
+	//	wire:
+	//		An object to check
+	//	returns:
+	//		True if the object is a Wire, otherwise false
+	return (wire && wire._wireClass); //Boolean
 };
-dojox.wire.connect=function(_d,_e,_f){
-if(!_d||!_e||!_f){
-return;
-}
-var _10={topic:_d.topic};
-if(_d.topic){
-_10.handle=dojo.subscribe(_d.topic,function(){
-dojox.wire.transfer(_e,_f,arguments);
-});
-}else{
-if(_d.event){
-_10.handle=dojo.connect(_d.scope,_d.event,function(){
-dojox.wire.transfer(_e,_f,arguments);
-});
-}
-}
-return _10;
+
+dojox.wire.transfer = function(/*Wire||Object*/source, /*Wire||Object*/target, /*Object?*/defaultObject, /*Object?*/defaultTargetObject){
+	//	summary:
+	//		Transfer a source value to a target value
+	//	description:
+	//		If 'source' and/or 'target' are not Wires, Wires are created with
+	//		them as arguments.
+	//		A value is got through the source Wire and set through the target
+	//		Wire.
+	//		'defaultObject' is passed to Wires as a default root object.
+	//		If 'defaultTargetObject' is specified, it is passed to the target
+	//		Wire as a default root object, instead of 'defaultObject'.
+	//	source:
+	//		A Wire or arguments to create a Wire for a source value
+	//	target:
+	//		A Wire or arguments to create a Wire for a target value
+	//	defaultObject:
+	//	defaultTargetObject;
+	//		Optional default root objects passed to Wires
+	if(!source || !target){
+		return; //undefined
+	}
+	if(!dojox.wire.isWire(source)){
+		source = dojox.wire.create(source);
+	}
+	if(!dojox.wire.isWire(target)){
+		target = dojox.wire.create(target);
+	}
+
+	var value = source.getValue(defaultObject);
+	target.setValue(value, (defaultTargetObject || defaultObject));
+};
+
+dojox.wire.connect = function(/*Object*/trigger, /*Wire||Object*/source, /*Wire||Object*/target){
+	//	summary:
+	//		Transfer a source value to a target value on a trigger event or
+	//		topic
+	//	description:
+	//		If 'trigger' specifies 'topic', the topic is subscribed to transer
+	//		a value on the topic.
+	//		Otherwise, the event specified to 'event' of 'trigger' is listened
+	//		to transfer a value.
+	//		On the specified event or topic, transfer() is called with
+	//		'source', 'target' and the arguments of the event or topic (as
+	//		default root objects).
+	//	trigger:
+	//		An event or topic to trigger a transfer
+	//	source:
+	//		A Wire or arguments to create a Wire for a source value
+	//	target:
+	//		A Wire or arguments to create a Wire for a target value
+	//	returns:
+	//		A connection handle for disconnect()
+	if(!trigger || !source || !target){
+		return; //undefined
+	}
+
+	var connection = {topic: trigger.topic};
+	if(trigger.topic){
+		connection.handle = dojo.subscribe(trigger.topic, function(){
+			dojox.wire.transfer(source, target, arguments);
+		});
+	}else if(trigger.event){
+		connection.handle = dojo.connect(trigger.scope, trigger.event, function(){
+			dojox.wire.transfer(source, target, arguments);
+		});
+	}
+	return connection; //Object
 };
-dojox.wire.disconnect=function(_11){
-if(!_11||!_11.handle){
-return;
-}
-if(_11.topic){
-dojo.unsubscribe(_11.handle);
-}else{
-dojo.disconnect(_11.handle);
-}
+
+dojox.wire.disconnect = function(/*Object*/connection){
+	//	summary:
+	//		Remove a connection or subscription for transfer
+	//	description:
+	//		If 'handle' has 'topic', the topic is unsubscribed.
+	//		Otherwise, the listener to an event is removed.
+	//	connection:
+	//		A connection handle returned by connect()
+	if(!connection || !connection.handle){
+		return; //undefined
+	}
+
+	if(connection.topic){
+		dojo.unsubscribe(connection.handle);
+	}else{
+		dojo.disconnect(connection.handle);
+	}
 };
-}
diff --git a/dojox/wire/demos/TableContainer.css b/dojox/wire/demos/TableContainer.css
new file mode 100644
index 0000000..4ee2706
--- /dev/null
+++ b/dojox/wire/demos/TableContainer.css
@@ -0,0 +1,30 @@
+.tablecontainer {
+	padding: 3 3 3 3;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #000000;
+	border-collapse: separate;
+}
+
+.tablecontainer th {
+	text-align: left;
+} 
+
+.tablecontainer tr {
+	padding: 3 3 3 3;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #000000;
+}
+
+.tablecontainer tr td {
+	padding: 3 3 3 3;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #000000;
+}
+
+.alternate {
+	background-color: #EEEEEE;
+}
+
diff --git a/dojox/wire/demos/TableContainer.js b/dojox/wire/demos/TableContainer.js
new file mode 100644
index 0000000..5e8d2ce
--- /dev/null
+++ b/dojox/wire/demos/TableContainer.js
@@ -0,0 +1,64 @@
+dojo.provide("dojox.wire.demos.TableContainer");
+
+dojo.require("dojo.parser");
+dojo.require("dijit._Widget");
+dojo.require("dijit._Templated");
+
+dojo.declare("dojox.wire.demos.TableContainer", [ dijit._Widget, dijit._Templated, dijit._Container ], {
+	//	summary:
+	//		Extremely simple 'widget' that is a table generator with an addRow function that takes an array
+	//		as the row to add, where each entry is a cell in the row.  This demo widget is for use with the
+	//		wire demos.
+
+	templateString: "<table class='tablecontainer'><tbody dojoAttachPoint='tableContainer'></tbody></table>",
+	rowCount: 0,
+	headers: "",
+	addRow: function(array){
+		//	summary:
+		//		Function to add in a new row from the elements in the array map to cells in the row.
+		//	array:
+		//		Array of row values to add.
+		try{
+			var row = document.createElement("tr");
+			if((this.rowCount%2) === 0){
+				dojo.addClass(row, "alternate");
+			}
+			this.rowCount++;
+			for(var i in array){
+				var cell = document.createElement("td");
+				var text = document.createTextNode(array[i]);
+				cell.appendChild(text);
+				row.appendChild(cell);
+				
+			}
+			this.tableContainer.appendChild(row);
+		}catch(e){ console.debug(e); }
+	},
+
+	clearTable: function(){
+		//	summary:
+		//		Function to clear all the current rows in the table, except for the header.
+
+		//Always leave the first row, which is the table header.
+		while(this.tableContainer.firstChild.nextSibling){
+			this.tableContainer.removeChild(this.tableContainer.firstChild.nextSibling);
+		}
+		this.rowCount = 0;
+	},
+
+	postCreate: function(){
+		//	summary:
+		//		Widget lifecycle function to handle generation of the header elements in the table.
+		var headers = this.headers.split(",");
+		var tr = document.createElement("tr");
+		for(i in headers){
+			
+			var header = headers[i];
+			var th = document.createElement("th");
+			var text = document.createTextNode(header);
+			th.appendChild(text);
+			tr.appendChild(th);
+		}
+		this.tableContainer.appendChild(tr);
+	}
+});
diff --git a/dojox/wire/demos/WidgetRepeater.js b/dojox/wire/demos/WidgetRepeater.js
new file mode 100644
index 0000000..9cdea16
--- /dev/null
+++ b/dojox/wire/demos/WidgetRepeater.js
@@ -0,0 +1,29 @@
+dojo.provide("dojox.wire.demos.WidgetRepeater")
+		
+dojo.require("dojo.parser");
+dojo.require("dijit._Widget");
+dojo.require("dijit._Templated");
+dojo.require("dijit._Container");
+
+dojo.declare("dojox.wire.demos.WidgetRepeater", [ dijit._Widget, dijit._Templated, dijit._Container ], {
+	//	summary:
+	//		Simple widget that does generation of widgets repetatively, based on calls to 
+	//		the createNew function and contains them as child widgets.
+	templateString: "<div class='WidgetRepeater' dojoAttachPoint='repeaterNode'></div>",
+	widget: null,
+	repeater: null,
+	createNew: function(obj){
+		//	summary:
+		//		Function to handle the creation of a new widget and appending it into the widget tree.
+		//	obj:	
+		//		The parameters to pass to the widget.
+		try{
+			if(dojo.isString(this.widget)){
+				dojo.require(this.widget);
+				this.widget = dojo.getObject(this.widget);
+			}
+			this.addChild(new this.widget(obj));
+			this.repeaterNode.appendChild(document.createElement("br"));
+		}catch(e){ console.debug(e); }
+	}
+});
diff --git a/dojox/wire/demos/markup/countries.json b/dojox/wire/demos/markup/countries.json
new file mode 100644
index 0000000..ad3a07a
--- /dev/null
+++ b/dojox/wire/demos/markup/countries.json
@@ -0,0 +1,43 @@
+{ identifier: 'name',
+   items: [
+	 { name:'Africa', type:'continent',
+		 children:[{_reference:'Egypt'}, {_reference:'Kenya'}, {_reference:'Sudan'}] },
+	 { name:'Egypt', type:'country' },
+	 { name:'Kenya', type:'country',
+		 children:[{_reference:'Nairobi'}, {_reference:'Mombasa'}] },
+	 { name:'Nairobi', type:'city' },
+	 { name:'Mombasa', type:'city' },
+	 { name:'Sudan', type:'country',
+		 children:{_reference:'Khartoum'} },
+	 { name:'Khartoum', type:'city' },
+	 { name:'Asia', type:'continent',
+		 children:[{_reference:'China'}, {_reference:'India'}, {_reference:'Russia'}, {_reference:'Mongolia'}] },
+	 { name:'China', type:'country' },
+	 { name:'India', type:'country' },
+	 { name:'Russia', type:'country' },
+	 { name:'Mongolia', type:'country' },
+	 { name:'Australia', type:'continent', population:'21 million',
+		 children:{_reference:'Commonwealth of Australia'}},
+	 { name:'Commonwealth of Australia', type:'country', population:'21 million'},
+	 { name:'Europe', type:'continent',
+		 children:[{_reference:'Germany'}, {_reference:'France'}, {_reference:'Spain'}, {_reference:'Italy'}] },
+	 { name:'Germany', type:'country' },
+	 { name:'France', type:'country' },
+	 { name:'Spain', type:'country' },
+	 { name:'Italy', type:'country' },
+	 { name:'North America', type:'continent',
+		 children:[{_reference:'Mexico'}, {_reference:'Canada'}, {_reference:'United States of America'}] },
+	 { name:'Mexico', type:'country',  population:'108 million', area:'1,972,550 sq km',
+		 children:[{_reference:'Mexico City'}, {_reference:'Guadalajara'}] },
+	 { name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'},
+	 { name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' },
+	 { name:'Canada', type:'country',  population:'33 million', area:'9,984,670 sq km',
+		 children:[{_reference:'Ottawa'}, {_reference:'Toronto'}] },
+	 { name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'},
+	 { name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' },
+	 { name:'United States of America', type:'country' },
+	 { name:'South America', type:'continent',
+		 children:[{_reference:'Brazil'}, {_reference:'Argentina'}] },
+	 { name:'Brazil', type:'country', population:'186 million' },
+	 { name:'Argentina', type:'country', population:'40 million' }
+]}
diff --git a/dojox/wire/demos/markup/demo_ActionChaining.html b/dojox/wire/demos/markup/demo_ActionChaining.html
new file mode 100644
index 0000000..bba408a
--- /dev/null
+++ b/dojox/wire/demos/markup/demo_ActionChaining.html
@@ -0,0 +1,112 @@
+<!--
+	This file demonstrates how the dojox.wire code can be used to do declarative
+	wiring of events.  Specifically, it shows how you can chain actions together
+	in a sequence.  In this case the setting of a value on one textbox triggers a 
+	copy over to another textbox.  That in turn triggers yet another copy to another
+	text box.
+-->
+<html>
+<head>
+	<title>Sample Action Chaining</title>
+	<style type="text/css">
+
+		@import "../../../../dijit/themes/tundra/tundra.css";
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/tests/css/dijitTests.css";
+		@import "../TableContainer.css";
+
+		.splitView {
+			width: 90%;
+			height: 90%;
+			border: 1px solid #bfbfbf;
+			border-collapse: separate;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojox.wire");
+		dojo.require("dojox.wire.ml.Invocation");
+		dojo.require("dojox.wire.ml.DataStore");
+		dojo.require("dojox.wire.ml.Transfer");
+		dojo.require("dojox.wire.ml.Data");
+		dojo.require("dijit.form.TextBox");
+	</script>
+</head>
+
+<body class="tundra">
+
+	<!-- Layout -->
+	<font size="3"><b>Demo of Chaining Actions:</b></font><br/><br/>
+	This demo shows how you can chain actions together to fire in a sequence.  
+	Such as the completion of setting one value on a widget triggers the setting of another value on the widget
+	<br/>
+	<br/>
+	<table>
+		<tr>
+			<td>
+				<div dojoType="dijit.form.TextBox" id="inputField" value="" size="50" intermediateChanges="true"></div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<div dojoType="dijit.form.TextBox" id="targetField1" value="" disabled="true" size="50"></div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<div dojoType="dijit.form.TextBox" id="targetField2" value="" disabled="true" size="50"></div>
+			</td>
+		</tr>
+	</table>
+
+
+	<!-------------------------------- Using dojox.wire, declaratively wire up the widgets. --------------------------->
+
+	<!--
+		This is an example of using the declarative data value definition.
+		These are effectively declarative variables to act as placeholders
+		for data values.
+	-->
+	<div dojoType="dojox.wire.ml.Data"
+		id="data">
+		<div dojoType="dojox.wire.ml.DataProperty"
+			name="tempData"
+			value="">
+		</div>
+		<div dojoType="dojox.wire.ml.DataProperty"
+			name="value"
+			value="value">
+		</div>
+	</div>
+
+	<!-- 
+		Whenever a key is entered into the textbox, copy the value somewhere, then invoke a method on another widget, in this case
+		on just another text box.
+	-->
+	<div dojoType="dojox.wire.ml.Action"
+		id="action1"
+		trigger="inputField"
+		triggerEvent="onChange">
+		<div dojoType="dojox.wire.ml.Transfer" source="inputField.value" target="data.tempData"></div>
+		<div dojoType="dojox.wire.ml.Invocation" id="targetCopy" object="targetField1"  method="set" parameters="data.value, data.tempData"></div>
+	</div>    
+
+	<!-- 
+		Whenever the primary cloning invocation completes, invoke a secondary cloning action.
+	-->
+	<div dojoType="dojox.wire.ml.Action"
+		id="action2"
+		trigger="targetCopy"
+		triggerEvent="onComplete">
+		<!--
+			Note that this uses the basic 'property' form of copying the property over and setting it.  The Wire
+			code supports both getX and setX functions of setting a property as well as direct access.  It first looks
+			for the getX/setX functions and if present, uses them.  If missing, it will just do direct access.  Because
+			of the standard getValue/setValue API of dijit form widgets, these transfers work really well and are very compact.   
+		-->
+		<div dojoType="dojox.wire.ml.Transfer" source="targetField1.value" target="targetField2.value"></div>
+	</div>    
+</body>
+</html>
diff --git a/dojox/wire/demos/markup/demo_ActionWiring.html b/dojox/wire/demos/markup/demo_ActionWiring.html
new file mode 100644
index 0000000..3f57a74
--- /dev/null
+++ b/dojox/wire/demos/markup/demo_ActionWiring.html
@@ -0,0 +1,138 @@
+<!--
+  This file demonstrates how the dojox.wire code can be used to do declarative
+  wiring of events on one item to trigger event on other widgets.  It also shows
+  how you can use the Transfer object to morph data values from one format to 
+  another.  In this specific case, it maps the values from a dojo.data Datastore
+  item into values stored in a JavaScript Array, which is the format required for
+  the addRow method of the demonstration TableContainer.
+
+  Note that this demo expects dojo, digit, and dojox to all be peers in the same directory
+  in order for it to execute.
+-->
+<html>
+<head>
+	<title>Sample declarative data binding</title>
+	<style type="text/css">
+
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/themes/soria/soria.css";
+		@import "../../../../dijit/tests/css/dijitTests.css";
+		@import "../TableContainer.css";
+
+		.splitView {
+			width: 90%;
+			height: 90%;
+			overflow: hidden;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojox.wire.ml.Invocation");
+		dojo.require("dojox.wire.ml.DataStore");
+		dojo.require("dojox.wire.ml.Transfer");
+
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.TextBox");
+
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dojox.wire");
+		dojo.require("dojox.wire.demos.TableContainer");
+
+		//Toplevel JS Object to contain a few basics for us, such as the request to pass to the store and a stub onItem function
+		// to trap on for triggering other events.
+		dataHolder = {
+			//Simple object definition to get all items and sort it by the attribute 'type'.
+			request: {query: {name: "*"}, onItem: function(item, req){}, sort: [{attribute: "type"}]},
+			//Spot to store off data values as they're generated by the declarative binding.
+			result: null
+		};
+
+	</script>
+</head>
+
+<body class="soria">
+
+	<!-- The following is the basic layout.  A split container with a button and a text field.  Data will be displayed on the right. -->
+	<div dojoType="dijit.layout.BorderContainer"
+		gutters="true"
+		design="sidebar"
+		class="splitView">
+		<div dojoType="dijit.layout.ContentPane" region="left" style="width: 50%; overflow: auto;">
+			<font size="3"><b>Demo Searcher (Searches on Attribute 'name'):</b></font><br/><br/>
+			<b>Usage:</b><br/>
+			Enter the name you want to search the store for.  Wildcards * (multiple character), and ? (single character), are allowed.
+			<br/>
+			<br/>
+			<table style="width: 90%;">
+				<tr>
+					<td align="left">
+						<div dojoType="dijit.form.Button" jsId="searchButton">Search Datastore</div>
+					</td>
+					<td align="right">
+						<div dojoType="dijit.form.TextBox" jsId="inputField" value="*" intermediateChanges="true"></div>
+					</td>
+				</tr>
+			</table>
+		</div>
+		<div dojoType="dijit.layout.ContentPane" region="right" style="width: 50%; overflow: auto;">
+			<div class="dataTable" dojoType="dojox.wire.demos.TableContainer" jsId="dataTable" headers="Name,Location Type"></div>
+		</div>
+	</div>
+
+	<!-------------------------------- Using dojox.wire, declaratively wire up the widgets. --------------------------->
+
+	<!-- The store that is queried in this demo -->    
+	<div dojoType="dojo.data.ItemFileReadStore"
+		jsId="DataStore1"
+		url="countries.json">
+	</div>
+
+	<!-- 
+		When the search button is clicked, clear existing rows from table, 
+		Then invoke the fetch to repopulate the table.
+	-->
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="searchButton"
+		triggerEvent="onClick">
+		<div dojoType="dojox.wire.ml.Invocation" object="dataTable"  method="clearTable"></div>
+		<div dojoType="dojox.wire.ml.Invocation" object="DataStore1" method="fetch" parameters="dataHolder.request"></div>
+	</div>    
+
+	<!-- 
+		Link existing of the text box to transfering the search string to the query param.
+		We are wiring the value of TextBox value of the widget to the name property of our request
+		object.  The copy of values to the search should occur on each keyup event (each keypress)
+	 -->
+	<div dojoType="dojox.wire.ml.Transfer"
+		trigger="inputField" triggerEvent="onChange"
+		source="inputField.textbox.value" 
+		target="dataHolder.request.query.name">
+	</div>
+
+	<!-- 
+	  On the call of the onItem function of 'dataHolder', trigger a binding/mapping of the
+	  item's attribute 'name' and 'type' attributes to specific columns in an array.  Note here that since
+	  sourceStore is set, it treats the arguments as items from that store and accesses the attributes
+	  appropriately.  In this case 'name' becomes array entry 0, type, array entry 1, and so on.
+
+	  Then take the result of the data mapping and pass it into the invoke of the addRow function on the
+	  TableContainer widget.
+	-->  
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="dataHolder.request" triggerEvent="onItem">
+		<div dojoType="dojox.wire.ml.Transfer"
+			source="arguments[0]" sourceStore="DataStore1"
+			target="dataHolder.result">
+			<div dojoType="dojox.wire.ml.ColumnWire" attribute="name"></div>
+			<div dojoType="dojox.wire.ml.ColumnWire" attribute="type"></div>
+		</div>
+		<div dojoType="dojox.wire.ml.Invocation"
+			object="dataTable" method="addRow" parameters='dataHolder.result'>
+		</div>
+	</div>         
+</body>
+</html>
diff --git a/dojox/wire/demos/markup/demo_BasicChildWire.html b/dojox/wire/demos/markup/demo_BasicChildWire.html
new file mode 100644
index 0000000..f5973e7
--- /dev/null
+++ b/dojox/wire/demos/markup/demo_BasicChildWire.html
@@ -0,0 +1,78 @@
+<!--
+	This file demonstrates how the dojox.wire code can be used to do declarative
+	wiring of properties/attributes of some object to the properties/attributes of
+	another object.  It specifically uses the Child (Composite) wire type to perform
+	the mapping.
+
+	Note that this demo expects dojo, digit, and dojox to all be peers in the same directory
+	in order for it to execute.
+-->
+<html>
+	<head>
+	<title>Sample Composite (Child) Wire usage.</title>
+		<style type="text/css">
+			@import "../../../../dijit/themes/tundra/tundra.css";
+			@import "../../../../dojo/resources/dojo.css";
+			@import "../../../../dijit/tests/css/dijitTests.css";
+		</style>
+
+		<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+		<script type="text/javascript">
+			dojo.require("dojo.parser");
+			dojo.require("dijit.form.Button");
+			dojo.require("dojo.data.ItemFileReadStore");
+			dojo.require("dojox.wire.ml.Invocation");
+			dojo.require("dojox.wire.ml.DataStore");
+			dojo.require("dojox.wire.ml.Transfer");
+			dojo.require("dojox.wire");
+			dojo.require("dojox.wire.demos.WidgetRepeater");
+
+			dataHolder = {
+				request: {onItem: function(item){}},
+				result: null
+			};
+		</script>
+	</head>
+	<body class="tundra">
+		<!-- 
+			On load of the page, invoke the fetch method of the object 'DataStore1', 
+			get its parameters from the JS object 'sample.request
+		-->     
+		<div dojoType="dojox.wire.ml.Invocation"
+			triggerEvent="onLoad"
+			object="DataStore1" method="fetch" parameters="dataHolder.request">
+		</div>
+
+		<!-- 
+			The store that is queried in this demo 
+		-->    
+		<div dojoType="dojo.data.ItemFileReadStore"
+			jsId="DataStore1"
+			url="countries.json">
+		</div>
+
+		<!--
+			Simple container widget for creating a 'list' of some set of widgets
+			As defined by the widget type it contains.
+		-->
+		<div dojoType="dojox.wire.demos.WidgetRepeater"
+			widget="dijit.form.Button" jsId="r1">
+		</div>
+
+		<!-- 
+			On the call of the onItem function of 'sample', trigger a binding/mapping of the
+			item's attribute 'name' to the target object property: dataHolder.result.caption
+			Then invoke the WidgetRepeater (r1)'s createNew method, using the parameters from
+			dataHolder.result.
+		-->  
+		<div dojoType="dojox.wire.ml.Action"
+			trigger="dataHolder.request" triggerEvent="onItem">
+			<div dojoType="dojox.wire.ml.Transfer"
+				source="arguments[0]" sourceStore="DataStore1"
+				target="dataHolder.result">
+				<div dojoType="dojox.wire.ml.ChildWire" name="label" attribute="name"></div>
+			</div>
+			<div dojoType="dojox.wire.ml.Invocation" object="r1" method="createNew" parameters='dataHolder.result'></div>
+		</div>    
+	</body>
+</html>
diff --git a/dojox/wire/demos/markup/demo_BasicColumnWiring.html b/dojox/wire/demos/markup/demo_BasicColumnWiring.html
new file mode 100644
index 0000000..48c327e
--- /dev/null
+++ b/dojox/wire/demos/markup/demo_BasicColumnWiring.html
@@ -0,0 +1,90 @@
+<!--
+	This file demonstrates how the dojox.wire code can be used to do declarative
+	wiring of events on one item to trigger event on other items.  It also shows
+	how you can use the Transfer object to morph data values from one format to 
+	another.  In this specific case, it maps the values from a dojo.data Datastore
+	item into values stored in a JavaScript Array, which is the format required for
+	the addRow method of the demonstration TableContainer.
+
+	Note that this demo expects dojo, digit, and dojox to all be peers in the same directory
+	in order for it to execute.
+-->
+<html>
+<head>
+	<title>Sample Declarative Data Binding using ColumnWire</title>
+	<style type="text/css">
+		@import "../../../../dijit/themes/tundra/tundra.css";
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/tests/css/dijitTests.css";
+		@import "../TableContainer.css";
+	</style>
+
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojox.wire.ml.Invocation");
+		dojo.require("dojox.wire.ml.DataStore");
+		dojo.require("dojox.wire.ml.Transfer");
+
+		dojo.require("dijit._Widget");
+		dojo.require("dijit._Templated");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dojox.wire");
+		dojo.require("dojox.wire.demos.TableContainer");
+
+		//Toplevel JS Object to contain a few basics for us, such as the request to pass to the store and a stub onItem function
+		// to trap on for triggering other events.
+		dataHolder = {
+			//Simple object definition to get all items and sort it by the attribute 'type'.
+			request: {onItem: function(item){}, sort: [{attribute: "type"}]},
+			//Spot to store off data values as they're generated by the declarative binding.
+			result: null
+		};
+	</script>
+</head>
+
+<body class="tundra">
+	<!-- 
+		The store that is queried in this demo 
+	-->    
+	<div dojoType="dojo.data.ItemFileReadStore"
+		jsId="DataStore1"
+		url="countries.json">
+	</div>
+
+	<!-- 
+		On load of the page, invoke the fetch method of the object 'DataStore1', 
+		get its parameters from the JS object 'sample.request
+	-->     
+	<div dojoType="dojox.wire.ml.Invocation"
+		triggerEvent="onLoad"
+		object="DataStore1" method="fetch" parameters="dataHolder.request"></div>
+
+	<!--
+		Simple container widget for creating a 'table from rows defined by an array
+	-->    
+	<div dojoType="dojox.wire.demos.TableContainer" jsId="r1" headers="Name,Location Type"></div>
+
+	<!-- 
+		On the call of the onItem function of 'dataHolder', trigger a binding/mapping of the
+		item's attribute 'name' and 'type' attributes to specific columns in an array.  Note here that since
+		sourceStore is set, it treats the arguments as items from that store and accesses the attributes
+		appropriately.  In this case 'name' becomes array entry 0, type, array entry 1, and so on.
+
+		Then take the result of the data mapping and pass it into the invoke of the addRow function on the
+		TableContainer widget.
+	-->  
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="dataHolder.request" triggerEvent="onItem">
+		<div dojoType="dojox.wire.ml.Transfer"
+			source="arguments[0]" sourceStore="DataStore1"
+			target="dataHolder.result">
+			<div dojoType="dojox.wire.ml.ColumnWire" attribute="name"></div>
+			<div dojoType="dojox.wire.ml.ColumnWire" attribute="type"></div>
+		</div>
+		<div dojoType="dojox.wire.ml.Invocation"
+			object="r1" method="addRow" parameters='dataHolder.result'>
+		</div>
+	</div>         
+</body>
+</html>
diff --git a/dojox/wire/demos/markup/demo_ConditionalActions.html b/dojox/wire/demos/markup/demo_ConditionalActions.html
new file mode 100644
index 0000000..1a6dc91
--- /dev/null
+++ b/dojox/wire/demos/markup/demo_ConditionalActions.html
@@ -0,0 +1,221 @@
+<!--
+	This file demonstrates how the dojox.wire code can be used to do declarative
+	wiring of events.  Specifically, it shows how you can wire actions to set values 
+	across to other widgets, but only if certain conditions are met.
+-->
+<html>
+<head>
+	<title>Conditional Actions Demo</title>
+	<style type="text/css">
+
+		@import "../../../../dijit/themes/tundra/tundra.css";
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/tests/css/dijitTests.css";
+		@import "../TableContainer.css";
+
+		.splitView {
+			width: 90%;
+			height: 90%;
+			border: 1px solid #bfbfbf;
+			border-collapse: separate;
+		}
+
+		b {
+			float: left;
+		}
+
+		.rJustified {
+			float: right;
+		}
+
+	</style>
+
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dojox.wire");
+		dojo.require("dojox.wire.ml.Invocation");
+		dojo.require("dojox.wire.ml.DataStore");
+		dojo.require("dojox.wire.ml.Transfer");
+		dojo.require("dojox.wire.ml.Data");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.CheckBox");
+		dojo.require("dijit.form.ComboBox");
+	</script>
+</head>
+
+<body class="tundra">
+
+	<!-- Layout -->
+	<font size="3"><b>Demo of Conditional Actions:</b></font><br/><br/>
+	This demo shows how you can use actions to read and set widget values, as well as have actions only occur if 
+	if certain conditions are met, such as cloning values as they are typed from the billing address over to the
+	shipping address if the 'Use Same Address' checkbox is checked true.
+	<br/>
+	<br/>
+	<div dojoType="dojo.data.ItemFileReadStore" url="states.json" jsId="statesStore"></div>
+	<table width="100%">
+		<tr>
+			<td colspan="2" align="center">
+				Use Same Address: <div dojoType="dijit.form.CheckBox" id="useSameAddress" checked="true"></div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<b>Billing Address</b>
+			</td>
+			<td>
+				<b>Shipping Address</b>
+			</td>
+		</tr>
+
+		<tr>
+			<td>
+				<b>Name:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="BillingName" name="billingname" value=""  size="50" intermediateChanges="true"></div>
+			</td>
+			<td>
+				<b>Name:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="ShippingName" name="shippingname" value="" disabled="true" size="50"></div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<b>Address 1:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="BillingAddress1" name="billingaddress1" value=""  size="50" intermediateChanges="true"></div>
+			</td>
+			<td>
+				<b>Address 1:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="ShippingAddress1" name="shippingaddress1" value="" disabled="true" size="50"></div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<b>Address 2:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="BillingAddress2" name="billingaddress2" value=""  size="50" intermediateChanges="true"></div>
+			</td>
+			<td>
+				<b>Address 2:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="ShippingAddress2" name="shippingaddress2" value="" disabled="true" size="50"></div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<b>City:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="BillingCity" name="billingcity" value=""  size="50" intermediateChanges="true"></div>
+			</td>
+			<td>
+				<b>City:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="ShippingCity" name="shippingcity" value="" disabled="true" size="50"></div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<b>State:</b> <div class="rJustified" dojoType="dijit.form.ComboBox" searchAttr="name" id="BillingState" name="billingstate" value=""   store="statesStore" size="46"></div>
+			</td>
+			<td>
+				<b>State:</b> <div class="rJustified" dojoType="dijit.form.ComboBox" searchAttr="name" id="ShippingState" name="shippingstate" value="" store="statesStore" disabled="true" size="46"></div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<b>Zip code:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="BillingZip" name="billingzip" value=""  size="50" intermediateChanges="true"></div>
+			</td>
+			<td>
+				<b>Zip code:</b> <div class="rJustified" dojoType="dijit.form.TextBox" id="ShippingZip" name="shippingzip" value="" disabled="true" size="50"></div>
+			</td>
+		</tr>
+	</table>
+
+
+	<!-------------------------------- Using dojox.wire, declaratively wire up the widgets. --------------------------->
+
+	<!--
+		This is a simple data map so that the attributes we support modifying on ComboBox, TextField, etc, are lookupable.
+		since steAttribute(attr, value), replaced the single attribute setDisabled
+	-->
+	<div dojoType="dojox.wire.ml.Data"
+		id="attributesMap">
+		<div dojoType="dojox.wire.ml.DataProperty"
+			name="disabled"
+			value="disabled"></div>
+	</div>
+
+
+	<!-- 
+		Enable/disable the Right hand side of the shipping address view based on the checkbox events. 
+	-->
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="useSameAddress"
+		triggerEvent="onChange">
+		<!--
+			Trigger a setting of the Shipping fields' input state based on the state of the checkbox.
+		-->
+		<div dojoType="dojox.wire.ml.Invocation" object="ShippingName"    method="set" parameters="attributesMap.disabled, arguments[0]"></div>
+		<div dojoType="dojox.wire.ml.Invocation" object="ShippingAddress1"    method="set" parameters="attributesMap.disabled, arguments[0]"></div>
+		<div dojoType="dojox.wire.ml.Invocation" object="ShippingAddress2"    method="set" parameters="attributesMap.disabled, arguments[0]"></div>
+		<div dojoType="dojox.wire.ml.Invocation" object="ShippingCity"    method="set" parameters="attributesMap.disabled, arguments[0]"></div>
+		<div dojoType="dojox.wire.ml.Invocation" object="ShippingState"    method="set" parameters="attributesMap.disabled, arguments[0]"></div>
+		<div dojoType="dojox.wire.ml.Invocation" object="ShippingZip"    method="set" parameters="attributesMap.disabled, arguments[0]"></div>
+	</div>    
+
+	<!-- 
+		Clone the values of form fields while typing based on the setting of the checkbox.
+	-->
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="BillingName"
+		triggerEvent="onChange">
+		<div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div>        
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingName.value" target="ShippingName.value"></div>
+	</div>    
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="BillingAddress1"
+		triggerEvent="onChange">
+		<div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div>        
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingAddress1.value" target="ShippingAddress1.value"></div>
+	</div>    
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="BillingAddress2"
+		triggerEvent="onChange">
+		<div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div>        
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingAddress2.value" target="ShippingAddress2.value"></div>
+	</div>
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="BillingCity"
+		triggerEvent="onChange">
+		<div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div>        
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingCity.value" target="ShippingCity.value"></div>
+	</div>    
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="BillingState"
+		triggerEvent="onChange">
+		<div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div>        
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingState.value" target="ShippingState.value"></div>
+	</div>    
+
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="BillingZip"
+		triggerEvent="onChange">
+		<div dojoType="dojox.wire.ml.ActionFilter" required="useSameAddress.checked" requiredValue="true" type="boolean"></div>        
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingZip.value" target="ShippingZip.value"></div>
+	</div>    
+
+
+	<!-- 
+		Clone the values of form fields from billing over to shipping  over if the 
+		useSameAddress checkbox is set back to true.
+	-->
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="useSameAddress"
+		triggerEvent="onChange">
+		<div dojoType="dojox.wire.ml.ActionFilter" required="arguments[0]" requiredValue="true" type="boolean"></div>        
+
+		<!--
+			Note that this uses the basic 'property' form of copying the property over and setting it.  The Wire
+			code supports both getX and setX functions of setting a property as well as direct access.  It first looks
+			for the getX/setX functions and if present, uses them.  If missing, it will just do direct access.  Because
+			of the standard getValue/setValue API of dijit form widgets, transfers work well and are compact.   
+		-->
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingName.value" target="ShippingName.value"></div>
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingAddress1.value" target="ShippingAddress1.value"></div>
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingAddress2.value" target="ShippingAddress2.value"></div>
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingCity.value" target="ShippingCity.value"></div>
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingState.value" target="ShippingState.value"></div>
+		<div dojoType="dojox.wire.ml.Transfer" source="BillingZip.value" target="ShippingZip.value"></div>
+	</div>
+
+</body>
+</html>
diff --git a/dojox/wire/demos/markup/demo_FlickrStoreWire.html b/dojox/wire/demos/markup/demo_FlickrStoreWire.html
new file mode 100644
index 0000000..4d0d9ec
--- /dev/null
+++ b/dojox/wire/demos/markup/demo_FlickrStoreWire.html
@@ -0,0 +1,227 @@
+<!--
+  This file is a demo of the FlickrStore, a simple wrapper to the public feed service
+  of Flickr.  This just does very basic queries against Flickr and loads the results
+  into a list viewing widget.
+-->
+<html>
+<head>
+	<title>Demo of FlickrStore</title>
+	<style type="text/css">
+
+		@import "../../../../dijit/themes/tundra/tundra.css";
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/tests/css/dijitTests.css";
+		@import "./flickrDemo.css";
+	</style>
+
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.NumberSpinner");
+		dojo.require("dojox.data.FlickrStore");
+		dojo.require("dojox.wire.ml.Invocation");
+		dojo.require("dojox.wire.ml.Transfer");
+		dojo.require("dojox.wire.ml.Data");
+		dojo.require("dojox.wire");
+		dojo.require("dojox.data.demos.widgets.FlickrViewList");
+
+		//Toplevel JS Object to contain a few basics for us, such as the request to pass to the store and a stub onItem and onComplete function
+		// to trap on for triggering other events.
+		var dataHolder = {
+			//Simple stub datastore request
+			request: {query: {}}
+		};
+
+		//Function to convert the input from a widget into a comma separated list.
+		//that is the format of the store parameter.
+		var tagsInputConverter = function(tags){
+			if(tags && tags !== ""){
+				var tagsArray = tags.split(" ");
+				tags = "";
+				for(var i = 0; i < tagsArray.length; i++){
+					tags = tags + tagsArray[i];
+					if(i < (tagsArray.length - 1)){
+						tags += ","
+					}
+				}
+			}
+			return tags
+		}
+	</script>
+</head>
+
+<body class="tundra">
+	<h1>
+		DEMO:  FlickrStore Search
+	</h1>
+	<hr>
+	<h3>
+		Description:
+	</h3>
+	<p>
+		This simple demo shows how services, such as Flickr, can be wrapped by the datastore API.  In this demo, you can search public 
+		Flickr images through a simple FlickrStore by specifying a series of tags (separated by spaces) to search on.  The results 
+		will be displayed below the search box.  This demo is the same as the example demo provided in dojox/data/demos/demo_FlickrStore.html, 
+		except that all the interactions are implemented via Wire instead of a script that runs at dojo.addOnLoad().
+	</p>
+	<p>
+		For fun, search on the 3dny tag!
+	</p>
+
+	<blockquote>
+
+	<!--
+		Layout.
+	-->
+	<table>
+		<tbody>
+			<tr>
+				<td>
+					<b>Status:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="status" jsId="statusWidget" disabled="true"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>ID:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="userid" jsId="idWidget"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>Tags:</b>
+				</td>
+				<td>
+					<div dojoType="dijit.form.TextBox" size="50" id="tags" jsId="tagsWidget" value="3dny"></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>Tagmode:</b>
+				</td>
+				<td>
+					<select id="tagmode"
+							jsId="tagmodeWidget"
+							dojoType="dijit.form.ComboBox"
+							autocomplete="false"
+							value="any"
+					>
+						<option>any</option>
+						<option>all</option>
+					</select>
+				</td>
+			</tr>
+			<tr>
+				<td>
+					<b>Number of Pictures:</b>
+				</td>
+				<td>
+					<div   
+						id="count"
+						jsId="countWidget"
+						dojoType="dijit.form.NumberSpinner"
+						value="20"
+						constraints="{min:1,max:20,places:0}" 
+					></div>
+				</td>
+			</tr>
+			<tr>
+				<td>
+				</td>
+				<td>
+					<div dojoType="dijit.form.Button" label="Search" id="searchButton" jsId="searchButtonWidget"></div>
+				</td>
+			</tr>
+		</tbody>
+	</table>
+    </blockquote>
+	<!--
+		The store instance used by this demo.
+	-->
+	<div dojoType="dojox.data.FlickrStore" jsId="flickrStore" label="title"></div>
+	<div dojoType="dojox.data.demos.widgets.FlickrViewList" store="flickrStore" id="flickrViews" jsId="flickrViewsWidget"></div>
+
+	<!-------------------------------- Using dojox.wire, declaratively wire up the widgets. --------------------------->
+
+	<!--
+		This is an example of using the declarative data value definition.
+		These are effectively declarative variables to act as placeholders
+		for data values.
+	-->
+	<div dojoType="dojox.wire.ml.Data"
+		id="messageData"
+		jsId="messageData">
+		<div dojoType="dojox.wire.ml.DataProperty"
+			name="processingStart"
+			value="PROCESSING REQUEST">
+		</div>
+		<div dojoType="dojox.wire.ml.DataProperty"
+			name="processingDone"
+			value="PROCESSING COMPLETE">
+		</div>
+	</div>
+
+
+	<!-- 
+		When the search button is clicked, do the following in order:
+		1.)  Map the widget values over to the request properties.
+		2.)  Set the status to processing
+		3.)  Invoke the fetch on the  FLickrList to repopulate the table.
+	-->
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="searchButtonWidget"
+		triggerEvent="onClick">
+		
+		<!-- 
+			Read in the values from the widgets and bind them to the appropriate data locations
+            The Transfer tag looks for a getter property before using direct access, so it calls
+            getValue() to get the data from the widget, which works well for the dijit.form.* widgets.
+		-->
+		<div dojoType="dojox.wire.ml.Transfer" 
+			 source="idWidget.value" 
+			 target="dataHolder.request.query.id">
+		</div>
+
+		<!--
+		   For the tags, we need to get the value and then perform a conversion on the result
+		   This is done by doing a transfer through a converter.
+		-->
+		<div dojoType="dojox.wire.ml.Transfer" 
+			 source="tagsWidget.value" 
+			 target="dataHolder.request.query.tags"
+             converter="tagsInputConverter">
+		</div>
+        
+		<div dojoType="dojox.wire.ml.Transfer" 
+			 source="tagmodeWidget.value" 
+			 target="dataHolder.request.query.tagmode">
+		</div>
+
+		<div dojoType="dojox.wire.ml.Transfer" 
+			 source="countWidget.value" 
+			 target="dataHolder.request.count">
+		</div>
+
+		<!-- Now invoke the actions in order. -->
+		<div dojoType="dojox.wire.ml.Transfer" target="statusWidget.value" source="messageData.processingStart"></div>
+		<div dojoType="dojox.wire.ml.Invocation" object="flickrViewsWidget" method="fetch" parameters="dataHolder.request"></div>
+	</div>    
+
+	<!-- 
+		When the fetch processing finishes (onComplete is called), then set status to complete.
+	-->
+	<div dojoType="dojox.wire.ml.Action"
+		trigger="flickrViewsWidget"
+		triggerEvent="onComplete">
+		<div dojoType="dojox.wire.ml.Transfer" target="statusWidget.value" source="messageData.processingDone"></div>
+	</div>    
+
+</body>
+</html>
diff --git a/dojox/wire/demos/markup/demo_TopicWiring.html b/dojox/wire/demos/markup/demo_TopicWiring.html
new file mode 100644
index 0000000..b56fa6b
--- /dev/null
+++ b/dojox/wire/demos/markup/demo_TopicWiring.html
@@ -0,0 +1,84 @@
+<!--
+	This file demonstrates how the dojox.wire code can be used to do declarative
+	wiring of events.  Specifically, it shows how you can publish and subscribe 
+	to topics.  In this case the setting of a value on one textbox triggers a 
+	publish of that value to a topic.  Another invoke is wired to fire when
+	values are published to that topic which is then displayed in another 
+	textbox.
+-->
+<html>
+<head>
+	<title>Sample Topic Wiring</title>
+	<style type="text/css">
+
+		@import "../../../../dijit/themes/tundra/tundra.css";
+		@import "../../../../dojo/resources/dojo.css";
+		@import "../../../../dijit/tests/css/dijitTests.css";
+		@import "../TableContainer.css";
+
+		.splitView {
+			width: 90%;
+			height: 90%;
+			border: 1px solid #bfbfbf;
+			border-collapse: separate;
+		}
+	</style>
+
+	<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+	<script type="text/javascript">
+		dojo.require("dojo.parser");
+		dojo.require("dojox.wire");
+		dojo.require("dojox.wire.ml.Invocation");
+		dojo.require("dojox.wire.ml.DataStore");
+		dojo.require("dojox.wire.ml.Transfer");
+		dojo.require("dojox.wire.ml.Data");
+
+		dojo.require("dijit.form.TextBox");
+	</script>
+</head>
+
+<body class="tundra">
+
+	<!-- Layout -->
+	<font size="3"><b>Demo of Topic Wiring</b></font><br/><br/>
+	This demo shows how you can wire events to publish to a topic as well as receive topic events
+	<br/>
+	<br/>
+	<table>
+		<tr>
+			<td>
+				<div dojoType="dijit.form.TextBox" jsId="inputField" value="" size="50" intermediateChanges="true"></div>
+			</td>
+		</tr>
+		<tr>
+			<td>
+				<div dojoType="dijit.form.TextBox" jsId="targetField1" value="" disabled="true" size="50"></div>
+			</td>
+		</tr>
+	</table>
+
+
+	<!-------------------------------- Using dojox.wire, declaratively wire up the widgets. --------------------------->
+	
+	<!-- 
+		Whenever a key is entered into the textbox, publish the value of it to a topic.
+	-->
+	<div dojoType="dojox.wire.ml.Action"
+		id="action1"
+		trigger="inputField"
+		triggerEvent="onChange">
+		<div dojoType="dojox.wire.ml.Invocation" topic="sampleTopic"    parameters="inputField.value"></div>
+	</div>    
+
+	<!-- 
+		Whenever a value is published to a topic, set it as the value of the textbox by using Transfer to transfer the value from the
+		topic publish to the target property.  The underlying wire code will invoke the proper setter for the target, in this case
+		it will invoke the dijit 'attr' function.
+	-->
+	<div dojoType="dojox.wire.ml.Action"
+		id="action2"
+		triggerTopic="sampleTopic">
+		<div dojoType="dojox.wire.ml.Transfer" target="targetField1.value"  source="arguments[0]"></div>
+	</div>    
+</body>
+</html>
diff --git a/dojox/wire/demos/markup/flickrDemo.css b/dojox/wire/demos/markup/flickrDemo.css
new file mode 100644
index 0000000..7e75a5d
--- /dev/null
+++ b/dojox/wire/demos/markup/flickrDemo.css
@@ -0,0 +1,35 @@
+.flickrView {
+	padding: 3 3 3 3;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #000000;
+	border-collapse: separate;
+        width: 100%;
+}
+
+.flickrView th {
+	text-align: left;
+} 
+
+.flickrView tr {
+	padding: 3 3 3 3;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #000000;
+}
+
+.flickrView tr td {
+	padding: 3 3 3 3;
+	border-width: 1px;
+	border-style: solid;
+	border-color: #000000;
+}
+
+.flickrView {
+	background-color: #EFEFEF;
+}
+
+.flickrTitle {
+	background-color: #CCCCCC;
+}
+
diff --git a/dojox/wire/demos/markup/states.json b/dojox/wire/demos/markup/states.json
new file mode 100644
index 0000000..bdaa609
--- /dev/null
+++ b/dojox/wire/demos/markup/states.json
@@ -0,0 +1,56 @@
+{"identifier":"abbreviation",
+"label": "label",
+"items": [
+	{"name":"Alabama", "label":"Alabama","abbreviation":"AL"},
+	{"name":"Alaska", "label":"Alaska","abbreviation":"AK"},
+	{"name":"American Samoa", "label":"American Samoa","abbreviation":"AS"},
+	{"name":"Arizona", "label":"Arizona","abbreviation":"AZ"},
+	{"name":"Arkansas", "label":"Arkansas","abbreviation":"AR"},
+	{"name":"California", "label":"California","abbreviation":"CA"},
+	{"name":"Colorado", "label":"Colorado","abbreviation":"CO"},
+	{"name":"Connecticut", "label":"Connecticut","abbreviation":"CT"},
+	{"name":"Delaware", "label":"Delaware","abbreviation":"DE"},
+	{"name":"Florida", "label":"Florida","abbreviation":"FL"},
+	{"name":"Georgia", "label":"Georgia","abbreviation":"GA"},
+	{"name":"Hawaii", "label":"Hawaii","abbreviation":"HI"},
+	{"name":"Idaho", "label":"Idaho","abbreviation":"ID"},
+	{"name":"Illinois", "label":"Illinois","abbreviation":"IL"},
+	{"name":"Indiana", "label":"Indiana","abbreviation":"IN"},
+	{"name":"Iowa", "label":"Iowa","abbreviation":"IA"},
+	{"name":"Kansas", "label":"Kansas","abbreviation":"KS"},
+	{"name":"Kentucky", "label":"Kentucky","abbreviation":"KY"},
+	{"name":"Louisiana", "label":"Louisiana","abbreviation":"LA"},
+	{"name":"Maine", "label":"Maine","abbreviation":"ME"},
+	{"name":"Marshall Islands", "label":"Marshall Islands","abbreviation":"MH"},
+	{"name":"Maryland", "label":"Maryland","abbreviation":"MD"},
+	{"name":"Massachusetts", "label":"Massachusetts","abbreviation":"MA"},
+	{"name":"Michigan", "label":"Michigan","abbreviation":"MI"},
+	{"name":"Minnesota", "label":"Minnesota","abbreviation":"MN"},
+	{"name":"Mississippi", "label":"Mississippi","abbreviation":"MS"},
+	{"name":"Missouri", "label":"Missouri","abbreviation":"MO"},
+	{"name":"Montana", "label":"Montana","abbreviation":"MT"},
+	{"name":"Nebraska", "label":"Nebraska","abbreviation":"NE"},
+	{"name":"Nevada", "label":"Nevada","abbreviation":"NV"},
+	{"name":"New Hampshire", "label":"New Hampshire","abbreviation":"NH"},
+	{"name":"New Jersey", "label":"New Jersey","abbreviation":"NJ"},
+	{"name":"New Mexico", "label":"New Mexico","abbreviation":"NM"},
+	{"name":"New York", "label":"New York","abbreviation":"NY"},
+	{"name":"North Carolina", "label":"North Carolina","abbreviation":"NC"},
+	{"name":"North Dakota", "label":"North Dakota","abbreviation":"ND"},
+	{"name":"Ohio", "label":"Ohio","abbreviation":"OH"},
+	{"name":"Oklahoma", "label":"Oklahoma","abbreviation":"OK"},
+	{"name":"Oregon", "label":"Oregon","abbreviation":"OR"},
+	{"name":"Pennsylvania", "label":"Pennsylvania","abbreviation":"PA"},
+	{"name":"Rhode Island", "label":"Rhode Island","abbreviation":"RI"},
+	{"name":"South Carolina", "label":"South Carolina","abbreviation":"SC"},
+	{"name":"South Dakota", "label":"South Dakota","abbreviation":"SD"},
+	{"name":"Tennessee", "label":"Tennessee","abbreviation":"TN"},
+	{"name":"Texas", "label":"Texas","abbreviation":"TX"},
+	{"name":"Utah", "label":"Utah","abbreviation":"UT"},
+	{"name":"Vermont", "label":"Vermont","abbreviation":"VT"},
+	{"name":"Virginia", "label":"Virginia","abbreviation":"VA"},
+	{"name":"Washington", "label":"Washington","abbreviation":"WA"},
+	{"name":"West Virginia", "label":"West Virginia","abbreviation":"WV"},
+	{"name":"Wisconsin", "label":"Wisconsin","abbreviation":"WI"},
+	{"name":"Wyoming", "label":"Wyoming","abbreviation":"WY"}
+]}
\ No newline at end of file
diff --git a/dojox/wire/ml/Action.js b/dojox/wire/ml/Action.js
index 4a2ef3d..542db29 100644
--- a/dojox/wire/ml/Action.js
+++ b/dojox/wire/ml/Action.js
@@ -1,113 +1,221 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.ml.Action"]){
-dojo._hasResource["dojox.wire.ml.Action"]=true;
 dojo.provide("dojox.wire.ml.Action");
 dojo.provide("dojox.wire.ml.ActionFilter");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Container");
 dojo.require("dojox.wire.Wire");
 dojo.require("dojox.wire.ml.util");
-dojo.declare("dojox.wire.ml.Action",[dijit._Widget,dijit._Container],{trigger:"",triggerEvent:"",triggerTopic:"",postCreate:function(){
-this._connect();
-},_connect:function(){
-if(this.triggerEvent){
-if(this.trigger){
-var _1=dojox.wire.ml._getValue(this.trigger);
-if(_1){
-if(!_1[this.triggerEvent]){
-_1[this.triggerEvent]=function(){
-};
-}
-this._triggerHandle=dojo.connect(_1,this.triggerEvent,this,"run");
-}
-}else{
-var _2=this.triggerEvent.toLowerCase();
-if(_2=="onload"){
-var _3=this;
-dojo.addOnLoad(function(){
-_3._run.apply(_3,arguments);
+
+dojo.declare("dojox.wire.ml.Action", [dijit._Widget, dijit._Container], {
+	//	summary:
+	//		A base widget to "run" a task on an event or a topic
+	//	description:
+	//		This widget represents a controller task to be run when an event
+	//		(a function) or a topic is issued.
+	//		Sub-classes must implement _run() method to implement their tasks.
+	//		'trigger' specifies an event scope, an ID of a widget or an DOM
+	//		element, or its property with the optional dotted notation.
+	//		If this widget has child ActionFilter widgets, their filter()
+	//		methods are called with the arguments to the event or the topic.
+	//		If one of filter() methods returns false, run() won't be invoked.
+	//		This widget also can serve as a composite task to run child
+	//		Actions on an event or a topic specified to this widget.
+	//	trigger:
+	//		An event scope
+	//	triggerEvent:
+	//		An event (function) name
+	//	triggerTopic:
+	//		A topic name
+	trigger: "",
+	triggerEvent: "",
+	triggerTopic: "",
+
+	postCreate: function(){
+		//	summary:
+		//		Call _connect()
+		//	description:
+		//		See _connect().
+		this._connect();
+	},
+
+	_connect: function(){
+		//	summary:
+		//		Connect run() method to an event or a topic
+		//	description:
+		//		If 'triggerEvent' and 'trigger' are specified, connect() is
+		//		used to set up run() to be called on the event.
+		//		If 'triggerTopic' is specified, subscribe() is used to set up
+		//		run() to be called on the topic.
+		if(this.triggerEvent){
+			if(this.trigger){
+				var scope = dojox.wire.ml._getValue(this.trigger);
+				if(scope){
+					if(!scope[this.triggerEvent]){
+						// set a dummy function for an anonymous object
+						scope[this.triggerEvent] = function(){};
+					}
+					this._triggerHandle = dojo.connect(scope, this.triggerEvent, this, "run");
+				}
+			}else{
+				var event = this.triggerEvent.toLowerCase();
+				if(event == "onload"){
+					var self = this;
+					dojo.addOnLoad(function(){
+						self._run.apply(self, arguments);
+					});
+				}
+			}
+		}else if(this.triggerTopic){
+			this._triggerHandle = dojo.subscribe(this.triggerTopic, this, "run");
+		}
+	},
+
+	_disconnect: function(){
+		//	summary:
+		//		Disconnect run() method from an event or a topic
+		//	description:
+		//		If 'triggerEvent' and 'trigger' are specified, disconnect() is
+		//		used to set up run() not to be called on the event.
+		//		If 'triggerTopic' is specified, unsubscribe() is used to set up
+		//		run() not to be called on the topic.
+		if(this._triggerHandle){
+			if(this.triggerTopic){
+				dojo.unsubscribe(this.triggerTopic, this._triggerHandle);
+			}else{
+				dojo.disconnect(this._triggerHandle);
+			}
+		}
+	},
+
+	run: function(){
+		//	summary:
+		//		Run a task
+		//	description:
+		//		This method calls filter() method of child ActionFilter
+		//		widgets.
+		//		If one of them returns false, this method returns.
+		//		Otherwise, _run() method is called.
+		var children = this.getChildren();
+		for(var i in children){
+			var child = children[i];
+			if(child instanceof dojox.wire.ml.ActionFilter){
+				if(!child.filter.apply(child, arguments)){
+					return;
+				}
+			}
+		}
+		this._run.apply(this, arguments);
+	},
+
+	_run: function(){
+		//	summary:
+		//		Call run() methods of child Action widgets
+		//	description:
+		//		If this widget has child Action widgets, their run() methods
+		//		are called.
+		var children = this.getChildren();
+		for(var i in children){
+			var child = children[i];
+			if(child instanceof dojox.wire.ml.Action){
+				child.run.apply(child, arguments);
+			}
+		}
+	},
+
+	uninitialize: function(){
+		//	summary:
+		//		Over-ride of base widget unitialize function to do some connection cleanup.
+		this._disconnect();
+		return true;
+	}
+});
+
+dojo.declare("dojox.wire.ml.ActionFilter", dijit._Widget, {
+	//	summary:
+	//		A widget to define a filter for the parent Action to run
+	//	description:
+	//		This base class checks a required property specified with
+	//		'required' attribute.
+	//		If 'message' is specified, the message is set to a property
+	//		specified with 'error'.
+	//		Subclasses may implement their own filter() method.
+	//	required:
+	//		A property required
+	//	requiredValue:
+	//		Optional.  A specific value the property is required to have.  If this isn't provided
+	//		than any non-false/non-null value of the required propery will cause this filter
+	//		to pass.
+	//	type:
+	//		Optional.  A specific type to compare the values as (if requiredValue is set)
+	//		Valid values for type are boolean, int, string.  Default is string.
+	//	message:
+	//		An error message to emit if the filter doesn't execute due to property mismatch.
+	//	error:
+	//		A property to store an error due to property mismatch.
+	required: "",
+	requiredValue: "",
+	type: "",
+	message: "",
+	error: "",
+
+
+	filter: function(){
+		//	summary:
+		//		Check if a required property is specified.  Also, if provided, check to see 
+		//		if the required property contains a specific value.
+		//	description:
+		//		If a value is undefined for a property, specified with
+		//		'required', this method returns false.
+		//		If the value for a property is defined, but there isn't a requiredValue for it
+		//		then any non-false value will cause the method to return true.
+		//		if requiredValue is set, then filter compares that value with the value from
+		//		the required property and returns true if and only if they match.
+		//		The type option just allows for a way to convert the required property values
+		//		into a proper form for comparison (boolean, number, etc).
+		//		If 'message' is specified, it is set to a proeprty specified
+		//		with 'error' or shown with alert().
+		//		If 'required' starts with "arguments", a property of
+		//		the method arguments are checked.
+		//	returns:
+		//		True if a required property is specified (and if requiredValue is specified, 
+		//		that they match), otherwise false
+		if(this.required === ""){
+			return true; //Boolean
+		}else{
+			var value = dojox.wire.ml._getValue(this.required, arguments);
+			if(this.requiredValue === ""){
+				//Just see if there's a value, nothing to compare it to.
+				if(value){
+					return true; //Boolean
+				}
+			}else{
+				//See if we need to type convert.
+				var reqValue = this.requiredValue;
+				if(this.type !== ""){
+					var lType = this.type.toLowerCase();
+					if(lType === "boolean"){
+						if(reqValue.toLowerCase() === "false"){
+							reqValue = false;
+						}else{
+							reqValue = true;
+						}
+					}else if(lType === "number"){
+						reqValue = parseInt(reqValue, 10);
+					}
+				}
+				if(value === reqValue){
+					return true; //boolean
+				}
+			}
+		}
+		
+		if(this.message){
+			if(this.error){
+				dojox.wire.ml._setValue(this.error, this.message);
+			}else{
+				alert(this.message);
+			}
+		}
+		return false; //Boolean
+	}
 });
-}
-}
-}else{
-if(this.triggerTopic){
-this._triggerHandle=dojo.subscribe(this.triggerTopic,this,"run");
-}
-}
-},_disconnect:function(){
-if(this._triggerHandle){
-if(this.triggerTopic){
-dojo.unsubscribe(this.triggerTopic,this._triggerHandle);
-}else{
-dojo.disconnect(this._triggerHandle);
-}
-}
-},run:function(){
-var _4=this.getChildren();
-for(var i in _4){
-var _5=_4[i];
-if(_5 instanceof dojox.wire.ml.ActionFilter){
-if(!_5.filter.apply(_5,arguments)){
-return;
-}
-}
-}
-this._run.apply(this,arguments);
-},_run:function(){
-var _6=this.getChildren();
-for(var i in _6){
-var _7=_6[i];
-if(_7 instanceof dojox.wire.ml.Action){
-_7.run.apply(_7,arguments);
-}
-}
-},uninitialize:function(){
-this._disconnect();
-return true;
-}});
-dojo.declare("dojox.wire.ml.ActionFilter",dijit._Widget,{required:"",requiredValue:"",type:"",message:"",error:"",filter:function(){
-if(this.required===""){
-return true;
-}else{
-var _8=dojox.wire.ml._getValue(this.required,arguments);
-if(this.requiredValue===""){
-if(_8){
-return true;
-}
-}else{
-var _9=this.requiredValue;
-if(this.type!==""){
-var _a=this.type.toLowerCase();
-if(_a==="boolean"){
-if(_9.toLowerCase()==="false"){
-_9=false;
-}else{
-_9=true;
-}
-}else{
-if(_a==="number"){
-_9=parseInt(_9,10);
-}
-}
-}
-if(_8===_9){
-return true;
-}
-}
-}
-if(this.message){
-if(this.error){
-dojox.wire.ml._setValue(this.error,this.message);
-}else{
-alert(this.message);
-}
-}
-return false;
-}});
-}
diff --git a/dojox/wire/ml/Data.js b/dojox/wire/ml/Data.js
index ade9d43..44e2c79 100644
--- a/dojox/wire/ml/Data.js
+++ b/dojox/wire/ml/Data.js
@@ -1,81 +1,143 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.ml.Data"]){
-dojo._hasResource["dojox.wire.ml.Data"]=true;
 dojo.provide("dojox.wire.ml.Data");
 dojo.provide("dojox.wire.ml.DataProperty");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Container");
 dojo.require("dojox.wire.ml.util");
-dojo.declare("dojox.wire.ml.Data",[dijit._Widget,dijit._Container],{startup:function(){
-this._initializeProperties();
-},_initializeProperties:function(_1){
-if(!this._properties||_1){
-this._properties={};
-}
-var _2=this.getChildren();
-for(var i in _2){
-var _3=_2[i];
-if((_3 instanceof dojox.wire.ml.DataProperty)&&_3.name){
-this.setPropertyValue(_3.name,_3.getValue());
-}
-}
-},getPropertyValue:function(_4){
-return this._properties[_4];
-},setPropertyValue:function(_5,_6){
-this._properties[_5]=_6;
-}});
-dojo.declare("dojox.wire.ml.DataProperty",[dijit._Widget,dijit._Container],{name:"",type:"",value:"",_getValueAttr:function(){
-return this.getValue();
-},getValue:function(){
-var _7=this.value;
-if(this.type){
-if(this.type=="number"){
-_7=parseInt(_7);
-}else{
-if(this.type=="boolean"){
-_7=(_7=="true");
-}else{
-if(this.type=="array"){
-_7=[];
-var _8=this.getChildren();
-for(var i in _8){
-var _9=_8[i];
-if(_9 instanceof dojox.wire.ml.DataProperty){
-_7.push(_9.getValue());
-}
-}
-}else{
-if(this.type=="object"){
-_7={};
-var _8=this.getChildren();
-for(var i in _8){
-var _9=_8[i];
-if((_9 instanceof dojox.wire.ml.DataProperty)&&_9.name){
-_7[_9.name]=_9.getValue();
-}
-}
-}else{
-if(this.type=="element"){
-_7=new dojox.wire.ml.XmlElement(_7);
-var _8=this.getChildren();
-for(var i in _8){
-var _9=_8[i];
-if((_9 instanceof dojox.wire.ml.DataProperty)&&_9.name){
-_7.setPropertyValue(_9.name,_9.getValue());
-}
-}
-}
-}
-}
-}
-}
-}
-return _7;
-}});
-}
+
+dojo.declare("dojox.wire.ml.Data", [dijit._Widget, dijit._Container], {
+	//	summary:
+	//		A widget for a data object
+	//	description:
+	//		This widget represents an object with '_properties' property.
+	//		If child 'DataProperty' widgets exist, they are used to initialize
+	//		propertiy values of '_properties' object.
+
+	startup: function(){
+		//	summary:
+		//		Call _initializeProperties()
+		//	description:
+		//		See _initializeProperties().
+		this._initializeProperties();
+	},
+
+	_initializeProperties: function(/*Boolean*/reset){
+		//	summary:
+		//		Initialize a data object
+		//	description:
+		//		If this widget has child DataProperty widgets, their getValue()
+		//		methods are called and set the return value to a property
+		//		specified by 'name' attribute of the child widgets.
+		//	reset:
+		//		A boolean to reset current properties
+		if(!this._properties || reset){
+			this._properties = {};
+		}
+		var children = this.getChildren();
+		for(var i in children){
+			var child = children[i];
+			if((child instanceof dojox.wire.ml.DataProperty) && child.name){
+				this.setPropertyValue(child.name, child.getValue());
+			}
+		}
+	},
+
+	getPropertyValue: function(/*String*/property){
+		//	summary:
+		//		Return a property value
+		//	description:
+		//		This method returns the value of a property, specified with
+		//		'property' argument, in '_properties' object.
+		//	property:
+		//		A property name
+		//	returns:
+		//		A property value
+		return this._properties[property]; //anything
+	},
+
+	setPropertyValue: function(/*String*/property, /*anything*/value){
+		//	summary:
+		//		Store a property value
+		//	description:
+		//		This method stores 'value' as a property, specified with
+		//		'property' argument, in '_properties' object.
+		//	property:
+		//		A property name
+		//	value:
+		//		A property value
+		this._properties[property] = value;
+	}
+});
+
+dojo.declare("dojox.wire.ml.DataProperty", [dijit._Widget, dijit._Container], {
+	//	summary:
+	//		A widget to define a data property
+	//	description:
+	//		Attributes of this widget are used to add a property to the parent
+	//		Data widget.
+	//		'type' attribute specifies one of "string", "number", "boolean",
+	//		"array", "object" and "element" (DOM Element)
+	//		(default to "string").
+	//		If 'type' is "array" or "object", child DataProperty widgets are
+	//		used to initialize the array elements or the object properties.
+	//	name:
+	//		A property name
+	//	type:
+	//		A property type name
+	//	value:
+	//		A property value
+	name: "",
+	type: "",
+	value: "",
+
+	_getValueAttr: function(){
+		return this.getValue();
+	},
+
+	getValue: function(){
+		//	summary:
+		//		Returns a property value
+		//	description:
+		//		If 'type' is specified, 'value' attribute is converted to
+		//		the specified type and returned.
+		//		Otherwise, 'value' attribute is returned as is.
+		//	returns:
+		//		A property value
+		var value = this.value;
+		if(this.type){
+			if(this.type == "number"){
+				value = parseInt(value);
+			}else if(this.type == "boolean"){
+				value = (value == "true");
+			}else if(this.type == "array"){
+				value = [];
+				var children = this.getChildren();
+				for(var i in children){
+					var child = children[i];
+					if(child instanceof dojox.wire.ml.DataProperty){
+						value.push(child.getValue());
+					}
+				}
+			}else if(this.type == "object"){
+				value = {};
+				var children = this.getChildren();
+				for(var i in children){
+					var child = children[i];
+					if((child instanceof dojox.wire.ml.DataProperty) && child.name){
+						value[child.name] = child.getValue();
+					}
+				}
+			}else if(this.type == "element"){
+				value = new dojox.wire.ml.XmlElement(value);
+				var children = this.getChildren();
+				for(var i in children){
+					var child = children[i];
+					if((child instanceof dojox.wire.ml.DataProperty) && child.name){
+						value.setPropertyValue(child.name, child.getValue());
+					}
+				}
+			}
+		}
+		return value; //anything
+	}
+});
diff --git a/dojox/wire/ml/DataStore.js b/dojox/wire/ml/DataStore.js
index 619493a..d10aebf 100644
--- a/dojox/wire/ml/DataStore.js
+++ b/dojox/wire/ml/DataStore.js
@@ -1,45 +1,112 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.ml.DataStore"]){
-dojo._hasResource["dojox.wire.ml.DataStore"]=true;
 dojo.provide("dojox.wire.ml.DataStore");
+
 dojo.require("dijit._Widget");
 dojo.require("dojox.wire._base");
-dojo.declare("dojox.wire.ml.DataStore",dijit._Widget,{storeClass:"",postCreate:function(){
-this.store=this._createStore();
-},_createStore:function(){
-if(!this.storeClass){
-return null;
-}
-var _1=dojox.wire._getClass(this.storeClass);
-if(!_1){
-return null;
-}
-var _2={};
-var _3=this.domNode.attributes;
-for(var i=0;i<_3.length;i++){
-var a=_3.item(i);
-if(a.specified&&!this[a.nodeName]){
-_2[a.nodeName]=a.nodeValue;
-}
-}
-return new _1(_2);
-},getFeatures:function(){
-return this.store.getFeatures();
-},fetch:function(_4){
-return this.store.fetch(_4);
-},save:function(_5){
-this.store.save(_5);
-},newItem:function(_6){
-return this.store.newItem(_6);
-},deleteItem:function(_7){
-return this.store.deleteItem(_7);
-},revert:function(){
-return this.store.revert();
-}});
-}
+
+dojo.declare("dojox.wire.ml.DataStore", dijit._Widget, {
+	//	summary:
+	//		A widget for a data store
+	//	description:
+	//		This widget represents a data store of 'storeClass' attribute.
+	//	storeClass:
+	//		A class name of a data store
+	storeClass: "",
+
+	postCreate: function(){
+		//	summary:
+		//		Call _createStore()
+		//	description:
+		//		See _createStore().
+		this.store = this._createStore();
+	},
+
+	_createStore: function(){
+		//	summary:
+		//		Create a data store
+		//	desription:
+		//		A data store of 'storeClass' is created with arguments
+		//		specified with attributes.
+		//	returns:
+		//		A data store
+		if(!this.storeClass){
+			return null; //null
+		}
+		var storeClass = dojox.wire._getClass(this.storeClass);
+		if(!storeClass){
+			return null; //null
+		}
+		var args = {};
+		var attributes = this.domNode.attributes;
+		for(var i = 0; i < attributes.length; i++){
+			var a = attributes.item(i);
+			if(a.specified && !this[a.nodeName]){
+				args[a.nodeName] = a.nodeValue;
+			}
+		}
+		return new storeClass(args); //Object
+	},
+
+	getFeatures: function(){
+		//	summary:
+		//		Call getFeatures() method of a data store
+		//	description:
+		//		See dojo.data.api.Read.getFeatures().
+		//	returns:
+		//		A features object
+		return this.store.getFeatures(); //Object
+	},
+
+	fetch: function(/*Object*/request){
+		//	summary:
+		//		Call fetch() method of a data store
+		//	description:
+		//		See dojo.data.api.Read.fetch().
+		//	request:
+		//		A request object
+		//	returns:
+		//		A request object
+		return this.store.fetch(request); //Object
+	},
+
+	save: function(/*Object*/args){
+		//	summary:
+		//		Call save() method of a data store
+		//	description:
+		//		See dojo.data.api.Write.save().
+		//	args:
+		//		A save arguments object
+		this.store.save(args);
+	},
+
+	newItem: function(/*Object*/args){
+		//	summary:
+		//		Call newItem() method of a data store
+		//	description:
+		//		See dojo.data.api.Write.newItem().
+		//	args:
+		//		A new item arguments object
+		//	returns:
+		//		A new item
+		return this.store.newItem(args); //Object
+	},
+
+	deleteItem: function(/*Object*/item){
+		//	summary:
+		//		Call deleteItem() method of a data store
+		//	description:
+		//		See dojo.data.api.Write.deleteItem().
+		//	returns:
+		//		A boolean
+		return this.store.deleteItem(item); //Boolean
+	},
+
+	revert: function(){
+		//	summary:
+		//		Call revert() method of a data store
+		//	description:
+		//		See dojo.data.api.Write.revert().
+		//	returns:
+		//		A boolean
+		return this.store.revert(); //Boolean
+	}
+});
diff --git a/dojox/wire/ml/Invocation.js b/dojox/wire/ml/Invocation.js
index 17d5613..e0ba0f5 100644
--- a/dojox/wire/ml/Invocation.js
+++ b/dojox/wire/ml/Invocation.js
@@ -1,109 +1,167 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.ml.Invocation"]){
-dojo._hasResource["dojox.wire.ml.Invocation"]=true;
 dojo.provide("dojox.wire.ml.Invocation");
+
 dojo.require("dojox.wire.ml.Action");
-dojo.declare("dojox.wire.ml.Invocation",dojox.wire.ml.Action,{object:"",method:"",topic:"",parameters:"",result:"",error:"",_run:function(){
-if(this.topic){
-var _1=this._getParameters(arguments);
-try{
-dojo.publish(this.topic,_1);
-this.onComplete();
-}
-catch(e){
-this.onError(e);
-}
-}else{
-if(this.method){
-var _2=(this.object?dojox.wire.ml._getValue(this.object):dojo.global);
-if(!_2){
-return;
-}
-var _1=this._getParameters(arguments);
-var _3=_2[this.method];
-if(!_3){
-_3=_2.callMethod;
-if(!_3){
-return;
-}
-_1=[this.method,_1];
-}
-try{
-var _4=false;
-if(_2.getFeatures){
-var _5=_2.getFeatures();
-if((this.method=="fetch"&&_5["dojo.data.api.Read"])||(this.method=="save"&&_5["dojo.data.api.Write"])){
-var _6=_1[0];
-if(!_6.onComplete){
-_6.onComplete=function(){
-};
-}
-this.connect(_6,"onComplete","onComplete");
-if(!_6.onError){
-_6.onError=function(){
-};
-}
-this.connect(_6,"onError","onError");
-_4=true;
-}
-}
-var r=_3.apply(_2,_1);
-if(!_4){
-if(r&&(r instanceof dojo.Deferred)){
-var _7=this;
-r.addCallbacks(function(_8){
-_7.onComplete(_8);
-},function(_9){
-_7.onError(_9);
+
+dojo.declare("dojox.wire.ml.Invocation", dojox.wire.ml.Action, {
+	//	summary:
+	//		A widget to invoke a method or publish a topic
+	//	description:
+	//		This widget represents a controller task to invoke a method or
+	//		publish a topic when an event (a function) or a topic is issued.
+	//	object:
+	//		A scope of a method to invoke
+	//	method:
+	//		A name of a method to invoke
+	//	topic:
+	//		A name of a topic to publish
+	//	parameters:
+	//		Arguments for the method or the topic
+	//	result:
+	//		A property to store a return value of the method call
+	//	error:
+	//		A property to store an error on the method call
+	object: "",
+	method: "",
+	topic: "",
+	parameters: "",
+	result: "",
+	error: "",
+
+	_run: function(){
+		//	summary:
+		//		Invoke a method or publish a topic
+		//	description:
+		//		If 'topic' is specified, the topic is published with arguments
+		//		specified to 'parameters'.
+		//		If 'method' and 'object' are specified, the method is invoked
+		//		with arguments specified to 'parameters' and set the return
+		//		value to a property specified to 'result'.
+		//		'object', 'parameters' and 'result' can specify properties of
+		//		a widget or an DOM element with the dotted notation.
+		//		If 'parameters' are omitted, the arguments to this method are
+		//		passed as is.
+		if(this.topic){
+			var args = this._getParameters(arguments);
+			try{
+				dojo.publish(this.topic, args);
+				this.onComplete();
+			}catch(e){
+				this.onError(e);
+			}
+		}else if(this.method){
+			var scope = (this.object ? dojox.wire.ml._getValue(this.object) : dojo.global);
+			if(!scope){
+				return; //undefined
+			}
+			var args = this._getParameters(arguments);
+			var func = scope[this.method];
+			if(!func){
+				func = scope.callMethod;
+				if(!func){
+					return; //undefined
+				}
+				args = [this.method, args];
+			}
+			try{
+				var connected = false;
+				if(scope.getFeatures){
+					var features = scope.getFeatures();
+					if((this.method == "fetch" && features["dojo.data.api.Read"]) ||
+						(this.method == "save" && features["dojo.data.api.Write"])){
+						var arg = args[0];
+						if(!arg.onComplete){
+							arg.onComplete = function(){};
+						}
+						//dojo.connect(arg, "onComplete", this, "onComplete");
+						this.connect(arg, "onComplete", "onComplete");
+						if(!arg.onError){
+							arg.onError = function(){};
+						}
+						//dojo.connect(arg, "onError", this, "onError");
+						this.connect(arg, "onError", "onError");
+						connected = true;
+					}
+				}
+				var r = func.apply(scope, args);
+				if(!connected){
+					if(r && (r instanceof dojo.Deferred)){
+						var self = this;
+						r.addCallbacks(
+							function(result){self.onComplete(result);},
+							function(error){self.onError(error);}
+						);
+					}else{
+						this.onComplete(r);
+					}
+				}
+			}catch(e){
+				this.onError(e);
+			}
+		}
+	},
+
+	onComplete: function(/*anything*/result){
+		//	summary:
+		//		A function called when the method or the topic publish
+		//		completed
+		//	description:
+		//		If 'result' attribute is specified, the result object also set
+		//		to the specified property.
+		//	result:
+		//		The return value of a method or undefined for a topic
+		if(this.result){
+			dojox.wire.ml._setValue(this.result, result);
+		}
+		if(this.error){ // clear error
+			dojox.wire.ml._setValue(this.error, "");
+		}
+	},
+
+	onError: function(/*anything*/error){
+		//	summary:
+		//		A function called on an error occurs
+		//	description:
+		//		If 'error' attribute is specified, the error object also set to
+		//		the specified property.
+		//	error:
+		//		The exception or error occurred
+		if(this.error){
+			if(error && error.message){
+				error = error.message;
+			}
+			dojox.wire.ml._setValue(this.error, error);
+		}
+	},
+
+	_getParameters: function(/*Array*/args){
+		//	summary:
+		//		Returns arguments to a method or topic to invoke
+		//	description:
+		//		This method retunrs an array of arguments specified by
+		//		'parameters' attribute, a comma-separated list of IDs and
+		//		their properties in a dotted notation.
+		//		If 'parameters' are omitted, the original arguments are
+		//		used.
+		//	args:
+		//		Arguments to a trigger event or topic
+		if(!this.parameters){
+		 	// use arguments as is
+			return args; //Array
+		}
+		var parameters = [];
+		var list = this.parameters.split(",");
+		if(list.length == 1){
+			var parameter = dojox.wire.ml._getValue(dojo.trim(list[0]), args);
+			if(dojo.isArray(parameter)){
+				parameters = parameter;
+			}else{
+				parameters.push(parameter);
+			}
+		}else{
+			for(var i in list){
+				parameters.push(dojox.wire.ml._getValue(dojo.trim(list[i]), args));
+			}
+		}
+		return parameters; //Array
+	}
 });
-}else{
-this.onComplete(r);
-}
-}
-}
-catch(e){
-this.onError(e);
-}
-}
-}
-},onComplete:function(_a){
-if(this.result){
-dojox.wire.ml._setValue(this.result,_a);
-}
-if(this.error){
-dojox.wire.ml._setValue(this.error,"");
-}
-},onError:function(_b){
-if(this.error){
-if(_b&&_b.message){
-_b=_b.message;
-}
-dojox.wire.ml._setValue(this.error,_b);
-}
-},_getParameters:function(_c){
-if(!this.parameters){
-return _c;
-}
-var _d=[];
-var _e=this.parameters.split(",");
-if(_e.length==1){
-var _f=dojox.wire.ml._getValue(dojo.trim(_e[0]),_c);
-if(dojo.isArray(_f)){
-_d=_f;
-}else{
-_d.push(_f);
-}
-}else{
-for(var i in _e){
-_d.push(dojox.wire.ml._getValue(dojo.trim(_e[i]),_c));
-}
-}
-return _d;
-}});
-}
diff --git a/dojox/wire/ml/Service.js b/dojox/wire/ml/Service.js
index af10330..8ecc11c 100644
--- a/dojox/wire/ml/Service.js
+++ b/dojox/wire/ml/Service.js
@@ -1,170 +1,336 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.ml.Service"]){
-dojo._hasResource["dojox.wire.ml.Service"]=true;
 dojo.provide("dojox.wire.ml.Service");
 dojo.provide("dojox.wire.ml.RestHandler");
 dojo.provide("dojox.wire.ml.XmlHandler");
 dojo.provide("dojox.wire.ml.JsonHandler");
+
 dojo.require("dijit._Widget");
 dojo.require("dojox.xml.parser");
 dojo.require("dojox.wire._base");
 dojo.require("dojox.wire.ml.util");
-dojo.declare("dojox.wire.ml.Service",dijit._Widget,{url:"",serviceUrl:"",serviceType:"",handlerClass:"",preventCache:true,postCreate:function(){
-this.handler=this._createHandler();
-},_handlerClasses:{"TEXT":"dojox.wire.ml.RestHandler","XML":"dojox.wire.ml.XmlHandler","JSON":"dojox.wire.ml.JsonHandler","JSON-RPC":"dojo.rpc.JsonService"},_createHandler:function(){
-if(this.url){
-var _1=this;
-var d=dojo.xhrGet({url:this.url,handleAs:"json",sync:true});
-d.addCallback(function(_2){
-_1.smd=_2;
+
+dojo.declare("dojox.wire.ml.Service", dijit._Widget, {
+	//	summary:
+	//		A widget for a service
+	//	description:
+	//		This widget represents a service defined by a service description
+	//		specified with 'url' attribute.
+	//		If 'serviceType' and 'serviceUrl' attributes are specified, 'url'
+	//		attribute can be omitted.
+	//	url:
+	//		A URL to a service description
+	//	serviceUrl:
+	//		A URL to a service
+	//	serviceType:
+	//		A service type
+	//	handlerClass:
+	//		A service handler class name
+	url: "",
+	serviceUrl: "",
+	serviceType: "",
+	handlerClass: "",
+	preventCache: true,
+
+	postCreate: function(){
+		//	summary:
+		//		Call _createHandler()
+		//	description:
+		//		See _createHandler().
+		this.handler = this._createHandler();
+	},
+
+	_handlerClasses: {
+		"TEXT": "dojox.wire.ml.RestHandler",
+		"XML": "dojox.wire.ml.XmlHandler",
+		"JSON": "dojox.wire.ml.JsonHandler",
+		"JSON-RPC": "dojo.rpc.JsonService"
+	},
+
+	_createHandler: function(){
+		//	summary:
+		//		Create a service handler
+		//	desription:
+		//		A service handler class is determined by:
+		//		1. 'handlerClass' attribute
+		//		2. 'serviceType' attribute
+		//		3. 'serviceType' property in a service description
+		//	returns:
+		//		A service handler
+		if(this.url){
+			var self = this;
+			var d = dojo.xhrGet({
+				url: this.url,
+				handleAs: "json",
+				sync: true
+			});
+			d.addCallback(function(result){
+				self.smd = result;
+			});
+			if(this.smd && !this.serviceUrl){
+				this.serviceUrl = (this.smd.serviceUrl || this.smd.serviceURL);
+			}
+		}
+		var handlerClass = undefined;
+		if(this.handlerClass){
+			handlerClass = dojox.wire._getClass(this.handlerClass);
+		}else if(this.serviceType){
+			handlerClass = this._handlerClasses[this.serviceType];
+			if(handlerClass && dojo.isString(handlerClass)){
+				handlerClass = dojox.wire._getClass(handlerClass);
+				this._handlerClasses[this.serviceType] = handlerClass;
+			}
+		}else if(this.smd && this.smd.serviceType){
+			handlerClass = this._handlerClasses[this.smd.serviceType];
+			if(handlerClass && dojo.isString(handlerClass)){
+				handlerClass = dojox.wire._getClass(handlerClass);
+				this._handlerClasses[this.smd.serviceType] = handlerClass;
+			}
+		}
+		if(!handlerClass){
+			return null; //null
+		}
+		return new handlerClass(); //Object
+	},
+
+	callMethod: function(method, parameters){
+		//	summary:
+		//		Call a service method with parameters
+		//	method:
+		//		A method name
+		//	parameters:
+		//		An array parameters
+		var deferred = new dojo.Deferred();
+		this.handler.bind(method, parameters, deferred, this.serviceUrl);
+		return deferred;
+	}
+});
+
+dojo.declare("dojox.wire.ml.RestHandler", null, {
+	//	summary:
+	//		A REST service handler
+	//	description:
+	//		This class serves as a base REST service.
+	//		Sub-classes may override _getContent() and _getResult() to handle
+	//		specific content types.
+	contentType: "text/plain",
+	handleAs: "text",
+
+	bind: function(method, parameters, deferred, url){
+		//	summary:
+		//		Call a service method with parameters.
+		//	description:
+		//		A service is called with a URL generated by _getUrl() and
+		//		an HTTP method specified with 'method'.
+		//		For "POST" and "PUT", a content is generated by _getContent().
+		//		When data is loaded, _getResult() is used to pass the result to
+		//		Deferred.callback().
+		//	method:
+		//		A method name
+		//	parameters:
+		//		An array of parameters
+		//	deferred:
+		//		'Deferred'
+		//	url:
+		//		A URL for the method
+		method = method.toUpperCase();
+		var self = this;
+		var args = {
+			url: this._getUrl(method, parameters, url),
+			contentType: this.contentType,
+			handleAs: this.handleAs,
+			headers: this.headers,
+			preventCache: this.preventCache
+		};
+		var d = null;
+		if(method == "POST"){
+			args.postData = this._getContent(method, parameters);
+			d = dojo.rawXhrPost(args);
+		}else if(method == "PUT"){
+			args.putData = this._getContent(method, parameters);
+			d = dojo.rawXhrPut(args);
+		}else if(method == "DELETE"){
+			d = dojo.xhrDelete(args);
+		}else{ // "GET"
+			d = dojo.xhrGet(args);
+		}
+		d.addCallbacks(function(result){
+			deferred.callback(self._getResult(result));
+		}, function(error){
+			deferred.errback(error);
+		});
+	},
+
+	_getUrl: function(/*String*/method, /*Array*/parameters, /*String*/url){
+		//	summary:
+		//		Generate a URL
+		//	description:
+		//		If 'method' is "GET" or "DELETE", a query string is generated
+		//		from a query object specified to the first parameter in
+		//		'parameters' and appended to 'url'.
+		//		If 'url' contains variable seguments ("{parameter_name}"),
+		//		they are replaced with corresponding parameter values, instead.
+		//	method:
+		//		A method name
+		//	parameters:
+		//		An array of parameters
+		//	url:
+		//		A base URL
+		//	returns:
+		//		A URL
+		var query;
+		if(method == "GET" || method == "DELETE"){
+			if(parameters.length > 0){
+				query = parameters[0];
+			}
+		}else{ // "POST" || "PUT"
+			if(parameters.length > 1){
+				query = parameters[1];
+			}
+		}
+		if(query){
+			var queryString = "";
+			for(var name in query){
+				var value = query[name];
+				if(value){
+					value = encodeURIComponent(value);
+					var variable = "{" + name + "}";
+					var index = url.indexOf(variable);
+					if(index >= 0){ // encode in path
+						url = url.substring(0, index) + value + url.substring(index + variable.length);
+					}else{ // encode as query string
+						if(queryString){
+							queryString += "&";
+						}
+						queryString += (name + "=" + value);
+					}
+				}
+			}
+			if(queryString){
+				url += "?" + queryString;
+			}
+		}
+		return url; //String
+	},
+
+	_getContent: function(/*String*/method, /*Array*/parameters){
+		//	summary:
+		//		Generate a request content
+		//	description:
+		//		If 'method' is "POST" or "PUT", the first parameter in
+		//		'parameters' is returned.
+		//	method:
+		//		A method name
+		//	parameters:
+		//		An array of parameters
+		//	returns:
+		//		A request content
+		if(method == "POST" || method == "PUT"){
+			return (parameters ? parameters[0] : null); //anything
+		}else{
+			return null; //null
+		}
+	},
+
+	_getResult: function(/*anything*/data){
+		//	summary:
+		//		Extract a result
+		//	description:
+		//		A response data is returned as is.
+		//	data:
+		//		A response data returned by a service
+		//	returns:
+		//		A result object
+		return data; //anything
+	}
+});
+
+dojo.declare("dojox.wire.ml.XmlHandler", dojox.wire.ml.RestHandler, {
+	//	summary:
+	//		A REST service handler for XML
+	//	description:
+	//		This class provides XML handling for a REST service.
+	contentType: "text/xml",
+	handleAs: "xml",
+
+	_getContent: function(/*String*/method, /*Array*/parameters){
+		//	description:
+		//		If 'method' is "POST" or "PUT", the first parameter in
+		//		'parameters' is used to generate an XML content.
+		//	method:
+		//		A method name
+		//	parameters:
+		//		An array of parameters
+		//	returns:
+		//		A request content
+		var content = null;
+		if(method == "POST" || method == "PUT"){
+			var p = parameters[0];
+			if(p){
+				if(dojo.isString(p)){
+					content = p;
+				}else{
+					var element = p;
+					if(element instanceof dojox.wire.ml.XmlElement){
+						element = element.element;
+					}else if(element.nodeType === 9 /* DOCUMENT_NODE */){
+						element = element.documentElement;
+					}
+					var declaration = "<?xml version=\"1.0\"?>"; // TODO: encoding?
+					content = declaration + dojox.xml.parser.innerXML(element);
+				}
+			}
+		}
+		return content;
+	},
+
+	_getResult: function(/*Document*/data){
+		//	summary:
+		//		Extract a result
+		//	description:
+		//		A response data (XML Document) is returned wrapped with
+		//		XmlElement.
+		//	data:
+		//		A response data returned by a service
+		//	returns:
+		//		A result object
+		if(data){
+			data = new dojox.wire.ml.XmlElement(data);
+		}
+		return data;
+	}
 });
-if(this.smd&&!this.serviceUrl){
-this.serviceUrl=(this.smd.serviceUrl||this.smd.serviceURL);
-}
-}
-var _3=undefined;
-if(this.handlerClass){
-_3=dojox.wire._getClass(this.handlerClass);
-}else{
-if(this.serviceType){
-_3=this._handlerClasses[this.serviceType];
-if(_3&&dojo.isString(_3)){
-_3=dojox.wire._getClass(_3);
-this._handlerClasses[this.serviceType]=_3;
-}
-}else{
-if(this.smd&&this.smd.serviceType){
-_3=this._handlerClasses[this.smd.serviceType];
-if(_3&&dojo.isString(_3)){
-_3=dojox.wire._getClass(_3);
-this._handlerClasses[this.smd.serviceType]=_3;
-}
-}
-}
-}
-if(!_3){
-return null;
-}
-return new _3();
-},callMethod:function(_4,_5){
-var _6=new dojo.Deferred();
-this.handler.bind(_4,_5,_6,this.serviceUrl);
-return _6;
-}});
-dojo.declare("dojox.wire.ml.RestHandler",null,{contentType:"text/plain",handleAs:"text",bind:function(_7,_8,_9,_a){
-_7=_7.toUpperCase();
-var _b=this;
-var _c={url:this._getUrl(_7,_8,_a),contentType:this.contentType,handleAs:this.handleAs,headers:this.headers,preventCache:this.preventCache};
-var d=null;
-if(_7=="POST"){
-_c.postData=this._getContent(_7,_8);
-d=dojo.rawXhrPost(_c);
-}else{
-if(_7=="PUT"){
-_c.putData=this._getContent(_7,_8);
-d=dojo.rawXhrPut(_c);
-}else{
-if(_7=="DELETE"){
-d=dojo.xhrDelete(_c);
-}else{
-d=dojo.xhrGet(_c);
-}
-}
-}
-d.addCallbacks(function(_d){
-_9.callback(_b._getResult(_d));
-},function(_e){
-_9.errback(_e);
+
+dojo.declare("dojox.wire.ml.JsonHandler", dojox.wire.ml.RestHandler, {
+	//	summary:
+	//		A REST service handler for JSON
+	//	description:
+	//		This class provides JSON handling for a REST service.
+	contentType: "text/json",
+	handleAs: "json",
+	headers: {"Accept": "*/json"},
+
+	_getContent: function(/*String*/method, /*Array*/parameters){
+		//	summary:
+		//		Generate a request content
+		//	description:
+		//		If 'method' is "POST" or "PUT", the first parameter in
+		//		'parameter' is used to generate a JSON content.
+		//	method:
+		//		A method name
+		//	parameters:
+		//		An array of parameters
+		//	returns:
+		//		A request content
+		var content = null;
+		if(method == "POST" || method == "PUT"){
+			var p = (parameters ? parameters[0] : undefined);
+			if(p){
+				if(dojo.isString(p)){
+					content = p;
+				}else{
+					content = dojo.toJson(p);
+				}
+			}
+		}
+		return content; //String
+	}
 });
-},_getUrl:function(_f,_10,url){
-var _11;
-if(_f=="GET"||_f=="DELETE"){
-if(_10.length>0){
-_11=_10[0];
-}
-}else{
-if(_10.length>1){
-_11=_10[1];
-}
-}
-if(_11){
-var _12="";
-for(var _13 in _11){
-var _14=_11[_13];
-if(_14){
-_14=encodeURIComponent(_14);
-var _15="{"+_13+"}";
-var _16=url.indexOf(_15);
-if(_16>=0){
-url=url.substring(0,_16)+_14+url.substring(_16+_15.length);
-}else{
-if(_12){
-_12+="&";
-}
-_12+=(_13+"="+_14);
-}
-}
-}
-if(_12){
-url+="?"+_12;
-}
-}
-return url;
-},_getContent:function(_17,_18){
-if(_17=="POST"||_17=="PUT"){
-return (_18?_18[0]:null);
-}else{
-return null;
-}
-},_getResult:function(_19){
-return _19;
-}});
-dojo.declare("dojox.wire.ml.XmlHandler",dojox.wire.ml.RestHandler,{contentType:"text/xml",handleAs:"xml",_getContent:function(_1a,_1b){
-var _1c=null;
-if(_1a=="POST"||_1a=="PUT"){
-var p=_1b[0];
-if(p){
-if(dojo.isString(p)){
-_1c=p;
-}else{
-var _1d=p;
-if(_1d instanceof dojox.wire.ml.XmlElement){
-_1d=_1d.element;
-}else{
-if(_1d.nodeType===9){
-_1d=_1d.documentElement;
-}
-}
-var _1e="<?xml version=\"1.0\"?>";
-_1c=_1e+dojox.xml.parser.innerXML(_1d);
-}
-}
-}
-return _1c;
-},_getResult:function(_1f){
-if(_1f){
-_1f=new dojox.wire.ml.XmlElement(_1f);
-}
-return _1f;
-}});
-dojo.declare("dojox.wire.ml.JsonHandler",dojox.wire.ml.RestHandler,{contentType:"text/json",handleAs:"json",headers:{"Accept":"*/json"},_getContent:function(_20,_21){
-var _22=null;
-if(_20=="POST"||_20=="PUT"){
-var p=(_21?_21[0]:undefined);
-if(p){
-if(dojo.isString(p)){
-_22=p;
-}else{
-_22=dojo.toJson(p);
-}
-}
-}
-return _22;
-}});
-}
diff --git a/dojox/wire/ml/Transfer.js b/dojox/wire/ml/Transfer.js
index 3dabb9a..221fc95 100644
--- a/dojox/wire/ml/Transfer.js
+++ b/dojox/wire/ml/Transfer.js
@@ -1,122 +1,355 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.ml.Transfer"]){
-dojo._hasResource["dojox.wire.ml.Transfer"]=true;
 dojo.provide("dojox.wire.ml.Transfer");
 dojo.provide("dojox.wire.ml.ChildWire");
 dojo.provide("dojox.wire.ml.ColumnWire");
 dojo.provide("dojox.wire.ml.NodeWire");
 dojo.provide("dojox.wire.ml.SegmentWire");
+
 dojo.require("dijit._Widget");
 dojo.require("dijit._Container");
 dojo.require("dojox.wire._base");
 dojo.require("dojox.wire.ml.Action");
-dojo.declare("dojox.wire.ml.Transfer",dojox.wire.ml.Action,{source:"",sourceStore:"",sourceAttribute:"",sourcePath:"",type:"",converter:"",delimiter:"",target:"",targetStore:"",targetAttribute:"",targetPath:"",_run:function(){
-var _1=this._getWire("source");
-var _2=this._getWire("target");
-dojox.wire.transfer(_1,_2,arguments);
-},_getWire:function(_3){
-var _4=undefined;
-if(_3=="source"){
-_4={object:this.source,dataStore:this.sourceStore,attribute:this.sourceAttribute,path:this.sourcePath,type:this.type,converter:this.converter};
-}else{
-_4={object:this.target,dataStore:this.targetStore,attribute:this.targetAttribute,path:this.targetPath};
-}
-if(_4.object){
-if(_4.object.length>=9&&_4.object.substring(0,9)=="arguments"){
-_4.property=_4.object.substring(9);
-_4.object=null;
-}else{
-var i=_4.object.indexOf(".");
-if(i<0){
-_4.object=dojox.wire.ml._getValue(_4.object);
-}else{
-_4.property=_4.object.substring(i+1);
-_4.object=dojox.wire.ml._getValue(_4.object.substring(0,i));
-}
-}
-}
-if(_4.dataStore){
-_4.dataStore=dojox.wire.ml._getValue(_4.dataStore);
-}
-var _5=undefined;
-var _6=this.getChildren();
-for(var i in _6){
-var _7=_6[i];
-if(_7 instanceof dojox.wire.ml.ChildWire&&_7.which==_3){
-if(!_5){
-_5={};
-}
-_7._addWire(this,_5);
-}
-}
-if(_5){
-_5.object=dojox.wire.create(_4);
-_5.dataStore=_4.dataStore;
-_4=_5;
-}
-return _4;
-}});
-dojo.declare("dojox.wire.ml.ChildWire",dijit._Widget,{which:"source",object:"",property:"",type:"",converter:"",attribute:"",path:"",name:"",_addWire:function(_8,_9){
-if(this.name){
-if(!_9.children){
-_9.children={};
-}
-_9.children[this.name]=this._getWire(_8);
-}else{
-if(!_9.children){
-_9.children=[];
-}
-_9.children.push(this._getWire(_8));
-}
-},_getWire:function(_a){
-return {object:(this.object?dojox.wire.ml._getValue(this.object):undefined),property:this.property,type:this.type,converter:this.converter,attribute:this.attribute,path:this.path};
-}});
-dojo.declare("dojox.wire.ml.ColumnWire",dojox.wire.ml.ChildWire,{column:"",_addWire:function(_b,_c){
-if(this.column){
-if(!_c.columns){
-_c.columns={};
-}
-_c.columns[this.column]=this._getWire(_b);
-}else{
-if(!_c.columns){
-_c.columns=[];
-}
-_c.columns.push(this._getWire(_b));
-}
-}});
-dojo.declare("dojox.wire.ml.NodeWire",[dojox.wire.ml.ChildWire,dijit._Container],{titleProperty:"",titleAttribute:"",titlePath:"",_addWire:function(_d,_e){
-if(!_e.nodes){
-_e.nodes=[];
-}
-_e.nodes.push(this._getWires(_d));
-},_getWires:function(_f){
-var _10={node:this._getWire(_f),title:{type:"string",property:this.titleProperty,attribute:this.titleAttribute,path:this.titlePath}};
-var _11=[];
-var _12=this.getChildren();
-for(var i in _12){
-var _13=_12[i];
-if(_13 instanceof dojox.wire.ml.NodeWire){
-_11.push(_13._getWires(_f));
-}
-}
-if(_11.length>0){
-_10.children=_11;
-}
-return _10;
-}});
-dojo.declare("dojox.wire.ml.SegmentWire",dojox.wire.ml.ChildWire,{_addWire:function(_14,_15){
-if(!_15.segments){
-_15.segments=[];
-}
-_15.segments.push(this._getWire(_14));
-if(_14.delimiter&&!_15.delimiter){
-_15.delimiter=_14.delimiter;
-}
-}});
-}
+
+dojo.declare("dojox.wire.ml.Transfer", dojox.wire.ml.Action, {
+	//	summary:
+	//		A widget to transfer values through source and target Wires
+	//	description:
+	//		This widget represents a controller task to transfer a value from
+	//		a source to a target, through a source and a target Wires, when
+	//		an event (a function) or a topic is issued.
+	//		If this widget has child ChildWire widgets, their _addWire()
+	//		methods are called to add Wire arguments to a source or a target
+	//		Wire.
+	//	source:
+	//		A source object and/or property
+	//	sourceStore:
+	//		A data store for a source data item
+	//	sourceAttribute:
+	//		An attribute of a source data item
+	//	sourcePath:
+	//		A simplified XPath to a source property of an XML element
+	//	type:
+	//		A type of the value to be transferred
+	//	converter:
+	//		A class name of a converter for the value to be transferred
+	//	target:
+	//		A target object and/or property
+	//	targetStore:
+	//		A data store for a target data item
+	//	targetAttribute:
+	//		An attribute of a target data item
+	//	targetPath:
+	//		A simplified XPath to a target property of an XML element
+	source: "",
+	sourceStore: "",
+	sourceAttribute: "",
+	sourcePath: "",
+	type: "",
+	converter: "",
+	delimiter: "",
+	target: "",
+	targetStore: "",
+	targetAttribute: "",
+	targetPath: "",
+
+	_run: function(){
+		//	summary:
+		//		Transfer a value from a source to a target
+		//	description:
+		//		First, Wires for a source and a target are created from attributes.
+		//		Then, a value is obtained by getValue() of the source Wire is set
+		//		by setValue() of the target Wire.
+		//		The arguments to this method is passed to getValue() and setValue()
+		//		of Wires, so that they can be used to identify the root objects off
+		//		the arguments.
+		var sourceWire = this._getWire("source");
+		var targetWire = this._getWire("target");
+		dojox.wire.transfer(sourceWire, targetWire, arguments);
+	},
+
+	_getWire: function(/*String*/which){
+		//	summary:
+		//		Build Wire arguments from attributes
+		//	description:
+		//		Arguments object for a source or a target Wire, specified by
+		//		'which' argument, are build from corresponding attributes,
+		//		including '*Store' (for 'dataStore'), '*Attribute'
+		//		(for 'attribute), '*Path' (for 'path'), 'type' and 'converter'.
+		//		'source' or 'target' attribute is parsed as:
+		//			"object_id.property_name[.sub_property_name...]"
+		//		If 'source' or 'target' starts with "arguments", 'object'
+		//		argument for a Wire is set to null, so that the root object is
+		//		given as an event or topic arguments.
+		//		If this widget has child ChildWire widgets with a corresponding
+		//		'which' attribute, their _addWire() methods are called to add
+		//		additional Wire arguments and nested Wire is created,
+		//		specifying the Wire defined by this widget to 'object' argument.
+		//	which:
+		//		Which Wire arguments to build, "source" or "target"
+		//	returns:
+		//		Wire arguments object
+		var args = undefined;
+		if(which == "source"){
+			args = {
+				object: this.source,
+				dataStore: this.sourceStore,
+				attribute: this.sourceAttribute,
+				path: this.sourcePath,
+				type: this.type,
+				converter: this.converter
+			};
+		}else{ // "target"
+			args = {
+				object: this.target,
+				dataStore: this.targetStore,
+				attribute: this.targetAttribute,
+				path: this.targetPath
+			};
+		}
+		if(args.object){
+			if(args.object.length >= 9 && args.object.substring(0, 9) == "arguments"){
+				args.property = args.object.substring(9);
+				args.object = null;
+			}else{
+				var i = args.object.indexOf('.');
+				if(i < 0){
+					args.object = dojox.wire.ml._getValue(args.object);
+				}else{
+					args.property = args.object.substring(i + 1);
+					args.object = dojox.wire.ml._getValue(args.object.substring(0, i));
+				}
+			}
+		}
+		if(args.dataStore){
+			args.dataStore = dojox.wire.ml._getValue(args.dataStore);
+		}
+		var childArgs = undefined;
+		var children = this.getChildren();
+		for(var i in children){
+			var child = children[i];
+			if(child instanceof dojox.wire.ml.ChildWire && child.which == which){
+				if(!childArgs){
+					childArgs = {};
+				}
+				child._addWire(this, childArgs);
+			}
+		}
+		if(childArgs){ // make nested Wires
+			childArgs.object = dojox.wire.create(args);
+			childArgs.dataStore = args.dataStore;
+			args = childArgs;
+		}
+		return args; //Object
+	}
+});
+
+dojo.declare("dojox.wire.ml.ChildWire", dijit._Widget, {
+	//	summary:
+	//		A widget to add a child wire
+	//	description:
+	//		Attributes of this widget are used to add a child Wire to
+	//		a composite Wire of the parent Transfer widget.
+	//	which:
+	//		Which Wire to add a child Wire, "source" or "target", default to
+	//		"source"
+	//	object:
+	//		A root object for the value
+	//	property:
+	//		A property for the value
+	//	type:
+	//		A type of the value
+	//	converter:
+	//		A class name of a converter for the value
+	//	attribute:
+	//		A data item attribute for the value
+	//	path:
+	//		A simplified XPath for the value
+	//	name:
+	//		A composite property name
+	which: "source",
+	object: "",
+	property: "",
+	type: "",
+	converter: "",
+	attribute: "",
+	path: "",
+	name: "",
+
+	_addWire: function(/*Transfer*/parent, /*Object*/args){
+		//	summary:
+		//		Add a child Wire to Wire arguments
+		//	description:
+		//		If 'name' attribute is specified, a child Wire is added as
+		//		the named property of 'children' object of 'args'.
+		//		Otherwise, a child Wire is added to 'children' array of 'args'.
+		//	parent:
+		//		A parent Transfer widget
+		//	args:
+		//		Wire arguments
+		if(this.name){ // object
+			if(!args.children){
+				args.children = {};
+			}
+			args.children[this.name] = this._getWire(parent);
+		}else{ // array
+			if(!args.children){
+				args.children = [];
+			}
+			args.children.push(this._getWire(parent));
+		}
+	},
+
+	_getWire: function(/*Transfer*/parent){
+		//	summary:
+		//		Build child Wire arguments from attributes
+		//	description:
+		//		Arguments object for a child Wire are build from attributes,
+		//		including 'object', 'property', 'type', 'converter',
+		//		'attribute' and 'path'.
+		//	parent:
+		//		A parent Transfer widget
+		//	returns:
+		//		Wire arguments object
+		return {
+			object: (this.object ? dojox.wire.ml._getValue(this.object) : undefined),
+			property: this.property,
+			type: this.type,
+			converter: this.converter,
+			attribute: this.attribute,
+			path: this.path
+		}; //Object
+	}
+});
+
+dojo.declare("dojox.wire.ml.ColumnWire", dojox.wire.ml.ChildWire, {
+	//	summary:
+	//		A widget to add a column wire
+	//	description:
+	//		Attributes of this widget are used to add a column Wire to
+	//		a TableAdapter of the parent Transfer widget.
+	//	column:
+	//		A column name
+	column: "",
+
+	_addWire: function(/*Transfer*/parent, /*Object*/args){
+		//	summary:
+		//		Add a column Wire to Wire arguments
+		//	description:
+		//		If 'column' attribute is specified, a column Wire is added as
+		//		the named property of 'columns' object of 'args'.
+		//		Otherwise, a column Wire is added to 'columns' array of 'args'.
+		//	parent:
+		//		A parent Transfer widget
+		//	args:
+		//		Wire arguments
+		if(this.column){ // object
+			if(!args.columns){
+				args.columns = {};
+			}
+			args.columns[this.column] = this._getWire(parent);
+		}else{ // array
+			if(!args.columns){
+				args.columns = [];
+			}
+			args.columns.push(this._getWire(parent));
+		}
+	}
+});
+
+dojo.declare("dojox.wire.ml.NodeWire", [dojox.wire.ml.ChildWire, dijit._Container], {
+	//	summary:
+	//		A widget to add node wires
+	//	description:
+	//		Attributes of this widget are used to add node Wires to
+	//		a TreeAdapter of the parent Transfer widget.
+	//	titleProperty:
+	//		A property for the node title
+	//	titleAttribute:
+	//		A data item attribute for the node title
+	//	titlePath:
+	//		A simplified XPath for the node title
+	titleProperty: "",
+	titleAttribute: "",
+	titlePath: "",
+
+	_addWire: function(/*Transfer*/parent, /*Object*/args){
+		//	summary:
+		//		Add node Wires to Wire arguments
+		//	description:
+		//		Node Wires are added to 'nodes' array of 'args'.
+		//	parent:
+		//		A parent Transfer widget
+		//	args:
+		//		Wire arguments
+		if(!args.nodes){
+			args.nodes = [];
+		}
+		args.nodes.push(this._getWires(parent));
+	},
+
+	_getWires: function(/*Transfer*/parent){
+		//	summary:
+		//		Build node Wires arguments from attributes
+		//	description:
+		//		Arguments object for 'node' Wire are build from attributes,
+		//		including 'object', 'property', 'type', 'converter',
+		//		'attribute' and 'path'.
+		//		Arguments object for 'title' Wire are build from another set of
+		//		attributes, 'titleProperty', 'titleAttribute' and 'titlePath'.
+		//		If this widget has child NodeWire widgets, their _getWires()
+		//		methods are called recursively to build 'children' array of
+		//		'args'.
+		//	parent:
+		//		A parent Transfer widget
+		//	returns:
+		//		Wire arguments object
+		var args = {
+			node: this._getWire(parent),
+			title: {
+				type: "string",
+				property: this.titleProperty,
+				attribute: this.titleAttribute,
+				path: this.titlePath
+			}
+		};
+		var childArgs = [];
+		var children = this.getChildren();
+		for(var i in children){
+			var child = children[i];
+			if(child instanceof dojox.wire.ml.NodeWire){
+				childArgs.push(child._getWires(parent));
+			}
+		}
+		if(childArgs.length > 0){
+			args.children = childArgs;
+		}
+		return args; //Object
+	}
+});
+
+dojo.declare("dojox.wire.ml.SegmentWire", dojox.wire.ml.ChildWire, {
+	//	summary:
+	//		A widget to add a segment wire
+	//	description:
+	//		Attributes of this widget are used to add a segment Wire to
+	//		a TextAdapter of the parent Transfer widget.
+
+	_addWire: function(/*Transfer*/parent, /*Object*/args){
+		//	summary:
+		//		Add a segument Wire to Wire arguments
+		//	description:
+		//		A segment Wire is added to 'segments' array of 'args'.
+		//		If 'parent' has 'delimiter' attribute, it is used for
+		//		'delimiter' property of 'args'.
+		//	parent:
+		//		A parent Transfer widget
+		//	args:
+		//		Wire arguments
+		if(!args.segments){
+			args.segments = [];
+		}
+		args.segments.push(this._getWire(parent));
+		if(parent.delimiter && !args.delimiter){
+			args.delimiter = parent.delimiter;
+		}
+	}
+});
diff --git a/dojox/wire/ml/util.js b/dojox/wire/ml/util.js
index bfb10a6..6697246 100644
--- a/dojox/wire/ml/util.js
+++ b/dojox/wire/ml/util.js
@@ -1,213 +1,295 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.wire.ml.util"]){
-dojo._hasResource["dojox.wire.ml.util"]=true;
 dojo.provide("dojox.wire.ml.util");
+
 dojo.require("dojox.xml.parser");
 dojo.require("dojox.wire.Wire");
-dojox.wire.ml._getValue=function(_1,_2){
-if(!_1){
-return undefined;
-}
-var _3=undefined;
-if(_2&&_1.length>=9&&_1.substring(0,9)=="arguments"){
-_3=_1.substring(9);
-return new dojox.wire.Wire({property:_3}).getValue(_2);
-}
-var i=_1.indexOf(".");
-if(i>=0){
-_3=_1.substring(i+1);
-_1=_1.substring(0,i);
-}
-var _4=(dijit.byId(_1)||dojo.byId(_1)||dojo.getObject(_1));
-if(!_4){
-return undefined;
-}
-if(!_3){
-return _4;
-}else{
-return new dojox.wire.Wire({object:_4,property:_3}).getValue();
-}
+
+dojox.wire.ml._getValue = function(/*String*/source, /*Array*/args){
+	//	summary:
+	//		Return a value
+	//	description:
+	//		This method obtains an object by an ID of a widget or an DOM
+	//		element.
+	//		If 'source' specifies a dotted notation to its property, a Wire is
+	//		used to get the object property.
+	//		If 'source' starts with "arguments", 'args' is used as a root
+	//		object for the Wire.
+	//	source:
+	//		A string to specify an object and its property
+	//	args:
+	//		An optional arguments array
+	//	returns:
+	//		A value
+	if(!source){
+		return undefined; //undefined
+	}
+	var property = undefined;
+	if(args && source.length >= 9 && source.substring(0, 9) == "arguments"){
+		property = source.substring(9);
+		return new dojox.wire.Wire({property: property}).getValue(args);
+	}
+	var i = source.indexOf('.');
+	if(i >= 0){
+		property = source.substring(i + 1);
+		source = source.substring(0, i);
+	}
+	var object = (dijit.byId(source) || dojo.byId(source) || dojo.getObject(source));
+	if(!object){
+		return undefined; //undefined
+	}
+	if(!property){
+		return object; //Object
+	}else{
+		return new dojox.wire.Wire({object: object, property: property}).getValue(); //anything
+	}
 };
-dojox.wire.ml._setValue=function(_5,_6){
-if(!_5){
-return;
-}
-var i=_5.indexOf(".");
-if(i<0){
-return;
-}
-var _7=this._getValue(_5.substring(0,i));
-if(!_7){
-return;
-}
-var _8=_5.substring(i+1);
-var _9=new dojox.wire.Wire({object:_7,property:_8}).setValue(_6);
+
+dojox.wire.ml._setValue = function(/*String*/target, /*anything*/value){
+	//	summary:
+	//		Store a value
+	//	description:
+	//		This method stores a value by an ID of a widget or an DOM
+	//		element with a dotted notation to its property, using a Wire.
+	//	target:
+	//		A string to specify an object and its property
+	//	value:
+	//		A value
+	if(!target){
+		return; //undefined
+	}
+	var i = target.indexOf('.');
+	if(i < 0){
+		return; //undefined
+	}
+	var object = this._getValue(target.substring(0, i));
+	if(!object){
+		return; //undefined
+	}
+	var property = target.substring(i + 1);
+	var wire = new dojox.wire.Wire({object: object, property: property}).setValue(value);
 };
-dojo.declare("dojox.wire.ml.XmlElement",null,{constructor:function(_a){
-if(dojo.isString(_a)){
-_a=this._getDocument().createElement(_a);
-}
-this.element=_a;
-},getPropertyValue:function(_b){
-var _c=undefined;
-if(!this.element){
-return _c;
-}
-if(!_b){
-return _c;
-}
-if(_b.charAt(0)=="@"){
-var _d=_b.substring(1);
-_c=this.element.getAttribute(_d);
-}else{
-if(_b=="text()"){
-var _e=this.element.firstChild;
-if(_e){
-_c=_e.nodeValue;
-}
-}else{
-var _f=[];
-for(var i=0;i<this.element.childNodes.length;i++){
-var _10=this.element.childNodes[i];
-if(_10.nodeType===1&&_10.nodeName==_b){
-_f.push(new dojox.wire.ml.XmlElement(_10));
-}
-}
-if(_f.length>0){
-if(_f.length===1){
-_c=_f[0];
-}else{
-_c=_f;
-}
-}
-}
-}
-return _c;
-},setPropertyValue:function(_11,_12){
-var i;
-var _13;
-if(!this.element){
-return;
-}
-if(!_11){
-return;
-}
-if(_11.charAt(0)=="@"){
-var _14=_11.substring(1);
-if(_12){
-this.element.setAttribute(_14,_12);
-}else{
-this.element.removeAttribute(_14);
-}
-}else{
-if(_11=="text()"){
-while(this.element.firstChild){
-this.element.removeChild(this.element.firstChild);
-}
-if(_12){
-_13=this._getDocument().createTextNode(_12);
-this.element.appendChild(_13);
-}
-}else{
-var _15=null;
-var _16;
-for(i=this.element.childNodes.length-1;i>=0;i--){
-_16=this.element.childNodes[i];
-if(_16.nodeType===1&&_16.nodeName==_11){
-if(!_15){
-_15=_16.nextSibling;
-}
-this.element.removeChild(_16);
-}
-}
-if(_12){
-if(dojo.isArray(_12)){
-for(i in _12){
-var e=_12[i];
-if(e.element){
-this.element.insertBefore(e.element,_15);
-}
-}
-}else{
-if(_12 instanceof dojox.wire.ml.XmlElement){
-if(_12.element){
-this.element.insertBefore(_12.element,_15);
-}
-}else{
-_16=this._getDocument().createElement(_11);
-_13=this._getDocument().createTextNode(_12);
-_16.appendChild(_13);
-this.element.insertBefore(_16,_15);
-}
-}
-}
-}
-}
-},toString:function(){
-var s="";
-if(this.element){
-var _17=this.element.firstChild;
-if(_17){
-s=_17.nodeValue;
-}
-}
-return s;
-},toObject:function(){
-if(!this.element){
-return null;
-}
-var _18="";
-var obj={};
-var _19=0;
-var i;
-for(i=0;i<this.element.childNodes.length;i++){
-var _1a=this.element.childNodes[i];
-if(_1a.nodeType===1){
-_19++;
-var o=new dojox.wire.ml.XmlElement(_1a).toObject();
-var _1b=_1a.nodeName;
-var p=obj[_1b];
-if(!p){
-obj[_1b]=o;
-}else{
-if(dojo.isArray(p)){
-p.push(o);
-}else{
-obj[_1b]=[p,o];
-}
-}
-}else{
-if(_1a.nodeType===3||_1a.nodeType===4){
-_18+=_1a.nodeValue;
-}
-}
-}
-var _1c=0;
-if(this.element.nodeType===1){
-_1c=this.element.attributes.length;
-for(i=0;i<_1c;i++){
-var _1d=this.element.attributes[i];
-obj["@"+_1d.nodeName]=_1d.nodeValue;
-}
-}
-if(_19===0){
-if(_1c===0){
-return _18;
-}
-obj["text()"]=_18;
-}
-return obj;
-},_getDocument:function(){
-if(this.element){
-return (this.element.nodeType==9?this.element:this.element.ownerDocument);
-}else{
-return dojox.xml.parser.parse();
-}
-}});
-}
+
+dojo.declare("dojox.wire.ml.XmlElement", null, {
+	//	summary:
+	//		An object wrapping an XML element
+	//	description:
+	//		This class represents an XML element.
+
+	constructor: function(/*Element||String*/element){
+		//	summary:
+		//		Initialize with an XML element or a tag name
+		//	element:
+		//		An XML element or a tag name
+		if(dojo.isString(element)){
+			element = this._getDocument().createElement(element);
+		}
+		this.element = element;
+	},
+	getPropertyValue: function(/*String*/property){
+		//	summary:
+		//		Return a property value
+		//	description:
+		//		If 'property' starts with '@', the attribute value is returned.
+		//		If 'property' specifies "text()", the value of the first child
+		//		text is returned.
+		//		Otherwise, child elements of the tag name specified with
+		//		'property' are returned.
+		//	property:
+		//		A property name
+		//	returns:
+		//		A property value
+		var value = undefined;
+		if(!this.element){
+			return value; //undefined
+		}
+		if(!property){
+			return value; //undefined
+		}
+
+		if(property.charAt(0) == '@'){
+			var attribute = property.substring(1);
+			value = this.element.getAttribute(attribute);
+		}else if(property == "text()"){
+			var text = this.element.firstChild;
+			if(text){
+				value = text.nodeValue;
+			}
+		}else{ // child elements
+			var elements = [];
+			for(var i = 0; i < this.element.childNodes.length; i++){
+				var child = this.element.childNodes[i];
+				if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == property){
+					elements.push(new dojox.wire.ml.XmlElement(child));
+				}
+			}
+			if(elements.length > 0){
+				if(elements.length === 1){
+					value = elements[0];
+				}else{
+					value = elements;
+				}
+			}
+		}
+		return value; //String||Array||XmlElement
+	},
+
+	setPropertyValue: function(/*String*/property, /*String||Array||XmlElement*/value){
+		//	summary:
+		//		Store a property value
+		//	description:
+		//		If 'property' starts with '@', 'value' is set to the attribute.
+		//		If 'property' specifies "text()", 'value' is set as the first
+		//		child text.
+		//		If 'value' is a string, a child element of the tag name
+		//		specified with 'property' is created and 'value' is set as
+		//		the first child text of the child element.
+		//		Otherwise, 'value' is set to as child elements.
+		//	property:
+		//		A property name
+		//	value:
+		//		A property value
+		var i;
+		var text;
+		if(!this.element){
+			return; //undefined
+		}
+		if(!property){
+			return; //undefined
+		}
+
+		if(property.charAt(0) == '@'){
+			var attribute = property.substring(1);
+			if(value){
+				this.element.setAttribute(attribute, value);
+			}else{
+				this.element.removeAttribute(attribute);
+			}
+		}else if(property == "text()"){
+			while(this.element.firstChild){
+				this.element.removeChild(this.element.firstChild);
+			}
+			if(value){
+				text = this._getDocument().createTextNode(value);
+				this.element.appendChild(text);
+			}
+		}else{ // child elements
+			var nextChild = null;
+			var child;
+			for(i = this.element.childNodes.length - 1; i >= 0; i--){
+				child = this.element.childNodes[i];
+				if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == property){
+					if(!nextChild){
+						nextChild = child.nextSibling;
+					}
+					this.element.removeChild(child);
+				}
+			}
+			if(value){
+				if(dojo.isArray(value)){
+					for(i in value){
+						var e = value[i];
+						if(e.element){
+							this.element.insertBefore(e.element, nextChild);
+						}
+					}
+				}else if(value instanceof dojox.wire.ml.XmlElement){
+					if(value.element){
+						this.element.insertBefore(value.element, nextChild);
+					}
+				}else{ // assume string
+					child = this._getDocument().createElement(property);
+					text = this._getDocument().createTextNode(value);
+					child.appendChild(text);
+					this.element.insertBefore(child, nextChild);
+				}
+			}
+		}
+	},
+
+	toString: function(){
+		//	summary:
+		//		Return a value of the first text child of the element
+		//	description:
+		//		A value of the first text child of the element is returned.
+		//	returns:
+		//		A value of the first text child of the element
+		var s = "";
+		if(this.element){
+			var text = this.element.firstChild;
+			if(text){
+				s = text.nodeValue;
+			}
+		}
+		return s; //String
+	},
+
+	toObject: function(){
+		//	summary:
+		//		Return an object representation of the element
+		//	description:
+		//		An object with properties for child elements, attributes and
+		//		text is returned.
+		//	returns:
+		//		An object representation of the element
+		if(!this.element){
+			return null; //null
+		}
+		var text = "";
+		var obj = {};
+		var elements = 0;
+		var i;
+		for(i = 0; i < this.element.childNodes.length; i++){
+			var child = this.element.childNodes[i];
+			if(child.nodeType === 1 /* ELEMENT_NODE */){
+				elements++;
+				var o = new dojox.wire.ml.XmlElement(child).toObject();
+				var name = child.nodeName;
+				var p = obj[name];
+				if(!p){
+					obj[name] = o;
+				}else if(dojo.isArray(p)){
+					p.push(o);
+				}else{
+					obj[name] = [p, o]; // make them array
+				}
+			}else if(child.nodeType === 3 /* TEXT_NODE */ ||
+					 child.nodeType === 4 /* CDATA_SECTION_NODE */){
+				text += child.nodeValue;
+			}
+		}
+		var attributes = 0;
+		if(this.element.nodeType === 1 /* ELEMENT_NODE */){
+			attributes = this.element.attributes.length;
+			for(i = 0; i < attributes; i++){
+				var attr = this.element.attributes[i];
+				obj["@" + attr.nodeName] = attr.nodeValue;
+			}
+		}
+		if(elements === 0){
+			if(attributes === 0){
+				// text only
+				return text; //String
+			}
+			// text with attributes
+			obj["text()"] = text;
+		}
+		// else ignore text
+		return obj; //Object
+	},
+
+	_getDocument: function(){
+		//	summary:
+		//		Return a DOM document
+		//	description:
+		//		If 'element' is specified, a DOM document of the element is
+		//		returned.
+		//		Otherwise, a DOM document is created.
+		//	returns:
+		//		A DOM document
+		if(this.element){
+			return (this.element.nodeType == 9 /* DOCUMENT_NODE */ ?
+				this.element : this.element.ownerDocument); //Document
+		}else{
+			return dojox.xml.parser.parse(); //Document
+		}
+	}
+});
diff --git a/dojox/wire/tests/markup/Action.html b/dojox/wire/tests/markup/Action.html
new file mode 100644
index 0000000..75cbd49
--- /dev/null
+++ b/dojox/wire/tests/markup/Action.html
@@ -0,0 +1,147 @@
+<html>
+<head>
+<title>Test Action</title>
+<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+<script type="text/javascript">
+dojo.provide("dojox.wire.ml.tests.markup.Action");
+
+dojo.require("dojo.parser");
+dojo.require("doh.runner");
+dojo.require("dojox.wire.ml.Action");
+dojo.require("dojox.wire.ml.Transfer");
+
+dojox.wire.ml.tests.markup.Action = {
+	transfer: function(){},
+	source: {a: "A", b: "B"}
+};
+
+dojo.addOnLoad(function(){
+	doh.register("dojox.wire.ml.tests.markup.Action", [
+		function test_Action_triggerEvent(t){
+			dojox.wire.ml.tests.markup.Action.target = {};
+			dojox.wire.ml.tests.markup.Action.transfer();
+			t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a);
+			t.assertEqual(dojox.wire.ml.tests.markup.Action.source.b, dojox.wire.ml.tests.markup.Action.target.b);
+		},
+
+		function test_Action_triggerTopic(t){
+			dojox.wire.ml.tests.markup.Action.target = {};
+			dojo.publish("transfer");
+			t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a);
+		},
+
+		function test_ActionFilter_required(t){
+			dojox.wire.ml.tests.markup.Action.target = {};
+			dojo.publish("transferFilter");
+			t.assertEqual(undefined, dojox.wire.ml.tests.markup.Action.target.a);
+			t.assertEqual("no required", dojox.wire.ml.tests.markup.Action.error);
+			dojox.wire.ml.tests.markup.Action.required = true;
+			dojo.publish("transferFilter");
+			t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a);
+		},
+
+		function test_ActionFilter_requiredSpecificNumber(t){
+			dojox.wire.ml.tests.markup.Action.value = null
+			dojox.wire.ml.tests.markup.Action.target = {};
+			dojo.publish("transferFilterNumber");
+
+			t.assertEqual(undefined, dojox.wire.ml.tests.markup.Action.target.a);
+
+			dojox.wire.ml.tests.markup.Action.value = 20;
+			dojo.publish("transferFilterNumber");
+			t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a);
+		},
+
+		function test_ActionFilter_requiredSpecificBoolean(t){
+			dojox.wire.ml.tests.markup.Action.value = null;
+			dojox.wire.ml.tests.markup.Action.target = {};
+			dojo.publish("transferFilterBoolean");
+	
+			t.assertEqual(undefined, dojox.wire.ml.tests.markup.Action.target.a);
+	
+			dojox.wire.ml.tests.markup.Action.value = true;
+			dojo.publish("transferFilterBoolean");
+			t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a);
+		},
+
+		function test_ActionFilter_requiredSpecificString(t){
+			dojox.wire.ml.tests.markup.Action.target = {};
+			dojox.wire.ml.tests.markup.Action.value = null;
+			dojo.publish("transferFilterString");
+	
+			t.assertEqual(undefined, dojox.wire.ml.tests.markup.Action.target.a);
+	
+			dojox.wire.ml.tests.markup.Action.value = "executeThis";
+			dojo.publish("transferFilterString");
+			t.assertEqual(dojox.wire.ml.tests.markup.Action.source.a, dojox.wire.ml.tests.markup.Action.target.a);
+		}
+	]);
+	doh.run();
+});
+</script>
+</head>
+<body>
+<div dojoType="dojox.wire.ml.Action"
+	trigger="dojox.wire.ml.tests.markup.Action"
+	triggerEvent="transfer">
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Action.source.a"
+		target="dojox.wire.ml.tests.markup.Action.target.a"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Action.source.b"
+		target="dojox.wire.ml.tests.markup.Action.target.b"></div>
+</div>
+<div dojoType="dojox.wire.ml.Action"
+	triggerTopic="transfer">
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Action.source.a"
+		target="dojox.wire.ml.tests.markup.Action.target.a"></div>
+</div>
+<div dojoType="dojox.wire.ml.Action"
+	triggerTopic="transferFilter">
+	<div dojoType="dojox.wire.ml.ActionFilter"
+		required="dojox.wire.ml.tests.markup.Action.required"
+		message="no required"
+		error="dojox.wire.ml.tests.markup.Action.error"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Action.source.a"
+		target="dojox.wire.ml.tests.markup.Action.target.a"></div>
+</div>
+
+<div dojoType="dojox.wire.ml.Action"
+	triggerTopic="transferFilterNumber">
+	<div dojoType="dojox.wire.ml.ActionFilter"
+		required="dojox.wire.ml.tests.markup.Action.value"
+		requiredValue="20"
+		type="number">
+	</div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Action.source.a"
+		target="dojox.wire.ml.tests.markup.Action.target.a"></div>
+</div>
+
+<div dojoType="dojox.wire.ml.Action"
+	triggerTopic="transferFilterBoolean">
+	<div dojoType="dojox.wire.ml.ActionFilter"
+		required="dojox.wire.ml.tests.markup.Action.value"
+		requiredValue="true"
+		type="boolean">
+	</div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Action.source.a"
+		target="dojox.wire.ml.tests.markup.Action.target.a"></div>
+</div>
+
+<div dojoType="dojox.wire.ml.Action"
+	triggerTopic="transferFilterString">
+	<div dojoType="dojox.wire.ml.ActionFilter"
+		required="dojox.wire.ml.tests.markup.Action.value"
+		requiredValue="executeThis">
+	</div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Action.source.a"
+		target="dojox.wire.ml.tests.markup.Action.target.a"></div>
+</div>
+
+</body>
+</html>
diff --git a/dojox/wire/tests/markup/Data.html b/dojox/wire/tests/markup/Data.html
new file mode 100644
index 0000000..b1107c0
--- /dev/null
+++ b/dojox/wire/tests/markup/Data.html
@@ -0,0 +1,105 @@
+<html>
+<head>
+<title>Test Data</title>
+<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+<script type="text/javascript">
+dojo.provide("dojox.wire.ml.tests.markup.Data");
+
+dojo.require("dojo.parser");
+dojo.require("doh.runner");
+dojo.require("dojox.wire.ml.Action");
+dojo.require("dojox.wire.ml.Data");
+dojo.require("dojox.wire.ml.Transfer");
+
+dojox.wire.ml.tests.markup.Data = {};
+
+dojo.addOnLoad(function(){
+	doh.register("dojox.wire.ml.tests.markup.Data", [
+
+		function test_DataProperty(t){
+			dojox.wire.ml.tests.markup.Data.target = {};
+			dojo.publish("transfer");
+			t.assertEqual("A", dojox.wire.ml.tests.markup.Data.target.a);
+			t.assertEqual(1, dojox.wire.ml.tests.markup.Data.target.b);
+			t.assertEqual(true, dojox.wire.ml.tests.markup.Data.target.c);
+			t.assertEqual("DA", dojox.wire.ml.tests.markup.Data.target.d.a);
+			t.assertEqual("DB", dojox.wire.ml.tests.markup.Data.target.d.b);
+			t.assertEqual("E1", dojox.wire.ml.tests.markup.Data.target.e[0]);
+			t.assertEqual("E2", dojox.wire.ml.tests.markup.Data.target.e[1]);
+			t.assertEqual("F", dojox.wire.ml.tests.markup.Data.target.f);
+			t.assertEqual("G", dojox.wire.ml.tests.markup.Data.target.g);
+		}
+
+	]);
+	doh.run();
+});
+</script>
+</head>
+<body>
+<div dojoType="dojox.wire.ml.Data"
+	id="Data1">
+	<div dojoType="dojox.wire.ml.DataProperty"
+		name="a"
+		value="A"></div>
+	<div dojoType="dojox.wire.ml.DataProperty"
+		name="b"
+		type="number" value="1"></div>
+	<div dojoType="dojox.wire.ml.DataProperty"
+		name="c"
+		type="boolean" value="true"></div>
+	<div dojoType="dojox.wire.ml.DataProperty"
+		name="d"
+		type="object">
+		<div dojoType="dojox.wire.ml.DataProperty"
+			name="a"
+			value="DA"></div>
+		<div dojoType="dojox.wire.ml.DataProperty"
+			name="b"
+			value="DB"></div>
+	</div>
+	<div dojoType="dojox.wire.ml.DataProperty"
+		name="e"
+		type="array">
+		<div dojoType="dojox.wire.ml.DataProperty"
+			value="E1"></div>
+		<div dojoType="dojox.wire.ml.DataProperty"
+			value="E2"></div>
+	</div>
+	<div dojoType="dojox.wire.ml.DataProperty"
+		name="f"
+		type="element"
+		value="x">
+		<div dojoType="dojox.wire.ml.DataProperty"
+			name="text()"
+			value="F"></div>
+		<div dojoType="dojox.wire.ml.DataProperty"
+			name="@y"
+			value="G"></div>
+	</div>
+</div>
+<div dojoType="dojox.wire.ml.Action"
+	triggerTopic="transfer">
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="Data1.a"
+		target="dojox.wire.ml.tests.markup.Data.target.a"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="Data1.b"
+		target="dojox.wire.ml.tests.markup.Data.target.b"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="Data1.c"
+		target="dojox.wire.ml.tests.markup.Data.target.c"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="Data1.d"
+		target="dojox.wire.ml.tests.markup.Data.target.d"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="Data1.e"
+		target="dojox.wire.ml.tests.markup.Data.target.e"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="Data1.f"
+		target="dojox.wire.ml.tests.markup.Data.target.f"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="Data1.f. at y"
+		target="dojox.wire.ml.tests.markup.Data.target.g"></div>
+</div>
+</body>
+</html>
diff --git a/dojox/wire/tests/markup/DataStore.html b/dojox/wire/tests/markup/DataStore.html
new file mode 100644
index 0000000..3c55f7e
--- /dev/null
+++ b/dojox/wire/tests/markup/DataStore.html
@@ -0,0 +1,66 @@
+<html>
+<head>
+<title>Test DataStore</title>
+<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+<script type="text/javascript">
+dojo.provide("dojox.wire.ml.tests.markup.DataStore");
+
+dojo.require("dojo.parser");
+dojo.require("doh.runner");
+dojo.require("dojox.wire.ml.DataStore");
+dojo.require("dojox.wire.ml.Invocation");
+dojo.require("dojox.wire.ml.Transfer");
+
+dojox.wire.ml.tests.markup.DataStore = {
+	request: {onComplete: function(){}, onError: function(){}}
+};
+
+dojo.addOnLoad(function(){
+	doh.register("dojox.wire.ml.tests.markup.DataStore", [
+
+		function test_DataStore_url(t){
+			var d = new doh.Deferred();
+			dojo.connect(dojox.wire.ml.tests.markup.DataStore.request, "onComplete", function(){
+				t.assertEqual("X1", dojox.wire.ml.tests.markup.DataStore.target[0].a);
+				t.assertEqual("Y2", dojox.wire.ml.tests.markup.DataStore.target[1].b);
+				t.assertEqual("Z3", dojox.wire.ml.tests.markup.DataStore.target[2].c);
+				d.callback(true);
+			});
+			dojo.connect(dojox.wire.ml.tests.markup.DataStore.request, "onError", function(error){
+				d.errback(error);
+			});
+			dojo.publish("invokeFetch");
+			return d;
+		}
+
+	]);
+	doh.run();
+});
+</script>
+</head>
+<body>
+<div dojoType="dojox.wire.ml.DataStore"
+	id="DataStore1"
+	storeClass="dojox.data.XmlStore"
+	url="DataStore.xml"></div>
+<div dojoType="dojox.wire.ml.Invocation"
+	triggerTopic="invokeFetch"
+	object="DataStore1"
+	method="fetch"
+	parameters="dojox.wire.ml.tests.markup.DataStore.request">
+</div>
+<div dojoType="dojox.wire.ml.Transfer"
+	trigger="dojox.wire.ml.tests.markup.DataStore.request"
+	triggerEvent="onComplete"
+	source="arguments[0]"
+	sourceStore="DataStore1.store"
+	target="dojox.wire.ml.tests.markup.DataStore.target">
+	<div dojoType="dojox.wire.ml.ColumnWire"
+		column="a" attribute="x"></div>
+	<div dojoType="dojox.wire.ml.ColumnWire"
+		column="b" attribute="y"></div>
+	<div dojoType="dojox.wire.ml.ColumnWire"
+		column="c" attribute="z"></div>
+</div>
+</body>
+</html>
diff --git a/dojox/wire/tests/markup/DataStore.xml b/dojox/wire/tests/markup/DataStore.xml
new file mode 100644
index 0000000..eeff4c2
--- /dev/null
+++ b/dojox/wire/tests/markup/DataStore.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<dataStore>
+	<item>
+		<x>X1</x>
+		<y>Y1</y>
+		<z>Z1</z>
+	</item>
+	<item>
+		<x>X2</x>
+		<y>Y2</y>
+		<z>Z2</z>
+	</item>
+	<item>
+		<x>X3</x>
+		<y>Y3</y>
+		<z>Z3</z>
+	</item>
+</dataStore>
diff --git a/dojox/wire/tests/markup/Invocation.html b/dojox/wire/tests/markup/Invocation.html
new file mode 100644
index 0000000..dd6f6e4
--- /dev/null
+++ b/dojox/wire/tests/markup/Invocation.html
@@ -0,0 +1,53 @@
+<html>
+<head>
+<title>Test Invocation</title>
+<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad:true "></script>
+<script type="text/javascript">
+dojo.provide("dojox.wire.ml.tests.markup.Invocation");
+
+dojo.require("dojo.parser");
+dojo.require("doh.runner");
+dojo.require("dojox.wire.ml.Invocation");
+
+dojox.wire.ml.tests.markup.Invocation = {
+	invoke: function(p1, p2){return p1 + p2;},
+	invokeError: function(p){throw new Error(p);},
+	parameters: {a: "A", b: "B", c: "C"}
+};
+
+dojo.addOnLoad(function(){
+	doh.register("dojox.wire.ml.tests.markup.Invocation", [
+
+		function test_Invocation_method(t){
+			dojo.publish("invokeMethod");
+			t.assertEqual("AB", dojox.wire.ml.tests.markup.Invocation.result);
+		},
+
+		function test_Invocation_topic(t){
+			dojo.publish("invokeTopic");
+			t.assertEqual("C", dojox.wire.ml.tests.markup.Invocation.error);
+		}
+
+	]);
+	doh.run();
+});
+</script>
+</head>
+<body>
+<div dojoType="dojox.wire.ml.Invocation"
+	triggerTopic="invokeMethod"
+	object="dojox.wire.ml.tests.markup.Invocation"
+	method="invoke"
+	parameters="dojox.wire.ml.tests.markup.Invocation.parameters.a,dojox.wire.ml.tests.markup.Invocation.parameters.b"
+	result="dojox.wire.ml.tests.markup.Invocation.result"></div>
+<div dojoType="dojox.wire.ml.Invocation"
+	triggerTopic="invokeTopic"
+	topic="invokeError"
+	parameters="dojox.wire.ml.tests.markup.Invocation.parameters.c"></div>
+<div dojoType="dojox.wire.ml.Invocation"
+	triggerTopic="invokeError"
+	object="dojox.wire.ml.tests.markup.Invocation"
+	method="invokeError"
+	error="dojox.wire.ml.tests.markup.Invocation.error"></div>
+</body>
+</html>
diff --git a/dojox/wire/tests/markup/Service.html b/dojox/wire/tests/markup/Service.html
new file mode 100644
index 0000000..0448c61
--- /dev/null
+++ b/dojox/wire/tests/markup/Service.html
@@ -0,0 +1,84 @@
+<html>
+<head>
+<title>Test Service</title>
+<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+<script type="text/javascript">
+dojo.provide("dojox.wire.ml.tests.markup.Service");
+
+dojo.require("dojo.parser");
+dojo.require("doh.runner");
+dojo.require("dojox.wire.ml.Service");
+dojo.require("dojox.wire.ml.Invocation");
+dojo.require("dojox.wire.ml.Transfer");
+
+dojox.wire.ml.tests.markup.Service = {
+	query: {name: "a"}
+};
+
+dojo.addOnLoad(function(){
+	doh.register("dojox.wire.ml.tests.markup.Service", [
+
+		function test_Service_url(t){
+			var d = new doh.Deferred();
+			dojo.connect(dijit.byId("Invocation1"), "onComplete", function(result){
+ 				t.assertEqual("a", dojox.wire.ml.tests.markup.Service.target.a);
+ 				var o = result.toObject();
+				t.assertEqual("a", o.item.name); // test XmlElement.toObject()
+				t.assertEqual("b", o.item.data); // test XmlElement.toObject()
+
+ 				d.callback(true);
+ 			});
+			dojo.connect(dijit.byId("Invocation1"), "onError", function(error){
+				d.errback(error);
+			});
+			dojo.publish("invokeGetXml");
+			return d;
+		},
+
+		function test_Service_serviceUrl(t){
+			var d = new doh.Deferred();
+			dojo.connect(dijit.byId("Invocation2"), "onComplete", function(){
+				t.assertEqual("a", dojox.wire.ml.tests.markup.Service.result.item.name);
+				d.callback(true);
+			});
+			dojo.connect(dijit.byId("Invocation2"), "onError", function(error){
+				d.errback(error);
+			});
+			dojo.publish("invokeGetJson");
+			return d;
+		}
+
+	]);
+	doh.run();
+});
+</script>
+</head>
+<body>
+<div dojoType="dojox.wire.ml.Service"
+	id="Service1"
+	url="Service/XML.smd"></div>
+<div dojoType="dojox.wire.ml.Invocation"
+	id="Invocation1"
+	triggerTopic="invokeGetXml"
+	object="Service1"
+	method="get"
+	parameters="dojox.wire.ml.tests.markup.Service.query">
+</div>
+<div dojoType="dojox.wire.ml.Transfer"
+	trigger="Invocation1"
+	triggerEvent="onComplete"
+	source="arguments[0].item.name"
+	target="dojox.wire.ml.tests.markup.Service.target.a"></div>
+<div dojoType="dojox.wire.ml.Service"
+	id="Service2"
+	serviceType="JSON"
+	serviceUrl="Service/{name}.json"></div>
+<div dojoType="dojox.wire.ml.Invocation"
+	id="Invocation2"
+	triggerTopic="invokeGetJson"
+	object="Service2"
+	method="get"
+	parameters="dojox.wire.ml.tests.markup.Service.query"
+	result="dojox.wire.ml.tests.markup.Service.result"></div>
+</body>
+</html>
diff --git a/dojox/wire/tests/markup/Service/JSON.smd b/dojox/wire/tests/markup/Service/JSON.smd
new file mode 100644
index 0000000..2ac9682
--- /dev/null
+++ b/dojox/wire/tests/markup/Service/JSON.smd
@@ -0,0 +1,11 @@
+{
+	"serviceType": "JSON",
+	"serviceURL": "Service/{name}.json",
+	"methods": [{
+		"name": "get",
+		"parameters": [{
+			"name": "name",
+			"type": "str"
+		}]
+	}]
+}
diff --git a/dojox/wire/tests/markup/Service/XML.smd b/dojox/wire/tests/markup/Service/XML.smd
new file mode 100644
index 0000000..d833f88
--- /dev/null
+++ b/dojox/wire/tests/markup/Service/XML.smd
@@ -0,0 +1,11 @@
+{
+	"serviceType": "XML",
+	"serviceURL": "Service/{name}.xml",
+	"methods": [{
+		"name": "get",
+		"parameters": [{
+			"name": "name",
+			"type": "str"
+		}]
+	}]
+}
diff --git a/dojox/wire/tests/markup/Service/a.json b/dojox/wire/tests/markup/Service/a.json
new file mode 100644
index 0000000..93fc00b
--- /dev/null
+++ b/dojox/wire/tests/markup/Service/a.json
@@ -0,0 +1,5 @@
+{
+	"item": {
+		"name": "a"
+	}
+}
diff --git a/dojox/wire/tests/markup/Service/a.xml b/dojox/wire/tests/markup/Service/a.xml
new file mode 100644
index 0000000..21e4367
--- /dev/null
+++ b/dojox/wire/tests/markup/Service/a.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<item>
+	<name>a</name>
+	<data><![CDATA[b]]></data>    
+</item>
diff --git a/dojox/wire/tests/markup/Transfer.html b/dojox/wire/tests/markup/Transfer.html
new file mode 100644
index 0000000..afab400
--- /dev/null
+++ b/dojox/wire/tests/markup/Transfer.html
@@ -0,0 +1,157 @@
+<html>
+<head>
+<title>Test Transfer</title>
+<script type="text/javascript" src="../../../../dojo/dojo.js" djConfig="isDebug: true, parseOnLoad: true"></script>
+<script type="text/javascript">
+dojo.provide("dojox.wire.ml.tests.markup.Transfer");
+
+dojo.require("dojo.parser");
+dojo.require("doh.runner");
+dojo.require("dojox.xml.parser");
+dojo.require("dojox.data.XmlStore");
+dojo.require("dojox.wire.ml.Action");
+dojo.require("dojox.wire.ml.Transfer");
+
+dojox.wire.ml.tests.markup.Transfer = {
+	source: {a: "A", b: "B", c: [
+		{d: "D1", e: "E1"},
+		{d: "D2", e: "E2"}
+	]}
+};
+
+dojo.addOnLoad(function(){
+	doh.register("dojox.wire.ml.tests.markup.Transfer", [
+
+		function test_Transfer_attribute(t){
+			dojox.wire.ml.tests.markup.Transfer.store = new dojox.data.XmlStore();
+			dojox.wire.ml.tests.markup.Transfer.item = dojox.wire.ml.tests.markup.Transfer.store.newItem({tagName: "x"});
+			dojox.wire.ml.tests.markup.Transfer.target = {};
+			dojo.publish("transferData");
+			t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.a, dojox.wire.ml.tests.markup.Transfer.target.a);
+		},
+
+		function test_Transfer_path(t){
+			dojox.wire.ml.tests.markup.Transfer.element = dojox.xml.parser.parse().createElement("x");
+			dojox.wire.ml.tests.markup.Transfer.target = {};
+			dojo.publish("transferXml");
+			t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.a, dojox.wire.ml.tests.markup.Transfer.target.a);
+		},
+
+		function test_ChildWire(t){
+			dojox.wire.ml.tests.markup.Transfer.target = {};
+			dojo.publish("transferComposite");
+			t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.a, dojox.wire.ml.tests.markup.Transfer.target.c);
+			t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.b, dojox.wire.ml.tests.markup.Transfer.target.d);
+		},
+
+		function test_ColumnWire(t){
+			dojox.wire.ml.tests.markup.Transfer.target = {};
+			dojo.publish("transferTable");
+			t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.c[0].d, dojox.wire.ml.tests.markup.Transfer.target.a[0].b);
+			t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.c[1].e, dojox.wire.ml.tests.markup.Transfer.target.a[1].c);
+		},
+
+		function test_NodeWire(t){
+			dojox.wire.ml.tests.markup.Transfer.target = {};
+			dojo.publish("transferTree");
+			t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.c[0].d, dojox.wire.ml.tests.markup.Transfer.target.a[0].title);
+			t.assertEqual(dojox.wire.ml.tests.markup.Transfer.source.c[1].e, dojox.wire.ml.tests.markup.Transfer.target.a[1].children[0].title);
+		},
+
+		function test_SegimentWire(t){
+			dojox.wire.ml.tests.markup.Transfer.target = {};
+			dojo.publish("transferText");
+			t.assertEqual("A/B", dojox.wire.ml.tests.markup.Transfer.target.c);
+		}
+
+	]);
+	doh.run();
+});
+</script>
+</head>
+<body>
+<div dojoType="dojox.wire.ml.Action"
+	triggerTopic="transferData">
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Transfer.source.a"
+		target="dojox.wire.ml.tests.markup.Transfer.item"
+		targetStore="dojox.wire.ml.tests.markup.Transfer.store"
+		targetAttribute="y"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Transfer.item"
+		sourceStore="dojox.wire.ml.tests.markup.Transfer.store"
+		sourceAttribute="y"
+		target="dojox.wire.ml.tests.markup.Transfer.target.a"></div>
+</div>
+<div dojoType="dojox.wire.ml.Action"
+	triggerTopic="transferXml">
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Transfer.source.a"
+		target="dojox.wire.ml.tests.markup.Transfer.element"
+		targetPath="y/text()"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Transfer.element"
+		sourcePath="y/text()"
+		target="dojox.wire.ml.tests.markup.Transfer.target.a"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Transfer.source.b"
+		target="dojox.wire.ml.tests.markup.Transfer.element"
+		targetPath="y/@z"></div>
+	<div dojoType="dojox.wire.ml.Transfer"
+		source="dojox.wire.ml.tests.markup.Transfer.element"
+		sourcePath="y/@z"
+		target="dojox.wire.ml.tests.markup.Transfer.target.b"></div>
+</div>
+<div dojoType="dojox.wire.ml.Transfer"
+	triggerTopic="transferComposite"
+	source="dojox.wire.ml.tests.markup.Transfer.source"
+	target="dojox.wire.ml.tests.markup.Transfer.target">
+	<div dojoType="dojox.wire.ml.ChildWire"
+		name="x"
+		property="a"></div>
+	<div dojoType="dojox.wire.ml.ChildWire"
+		which="source"
+		name="y"
+		property="b"></div>
+	<div dojoType="dojox.wire.ml.ChildWire"
+		which="target"
+		name="x"
+		property="c"></div>
+	<div dojoType="dojox.wire.ml.ChildWire"
+		which="target"
+		name="y"
+		property="d"></div>
+</div>
+<div dojoType="dojox.wire.ml.Transfer"
+	triggerTopic="transferTable"
+	source="dojox.wire.ml.tests.markup.Transfer.source.c"
+	target="dojox.wire.ml.tests.markup.Transfer.target.a">
+	<div dojoType="dojox.wire.ml.ColumnWire"
+		column="b"
+		property="d"></div>
+	<div dojoType="dojox.wire.ml.ColumnWire"
+		column="c"
+		property="e"></div>
+</div>
+<div dojoType="dojox.wire.ml.Transfer"
+	triggerTopic="transferTree"
+	source="dojox.wire.ml.tests.markup.Transfer.source.c"
+	target="dojox.wire.ml.tests.markup.Transfer.target.a">
+	<div dojoType="dojox.wire.ml.NodeWire"
+		titleProperty="d">
+		<div dojoType="dojox.wire.ml.NodeWire"
+			titleProperty="e"></div>
+	</div>
+</div>
+<div dojoType="dojox.wire.ml.Transfer"
+	triggerTopic="transferText"
+	source="dojox.wire.ml.tests.markup.Transfer.source"
+	delimiter="/"
+	target="dojox.wire.ml.tests.markup.Transfer.target.c">
+	<div dojoType="dojox.wire.ml.SegmentWire"
+		property="a"></div>
+	<div dojoType="dojox.wire.ml.SegmentWire"
+		property="b"></div>
+</div>
+</body>
+</html>
diff --git a/dojox/wire/tests/module.js b/dojox/wire/tests/module.js
new file mode 100644
index 0000000..55c864e
--- /dev/null
+++ b/dojox/wire/tests/module.js
@@ -0,0 +1,9 @@
+dojo.provide("dojox.wire.tests.module");
+
+try{
+	dojo.require("dojox.wire.tests.wire");
+	dojo.require("dojox.wire.tests.wireml");
+}catch(e){
+	doh.debug(e);
+}
+
diff --git a/dojox/wire/tests/programmatic/CompositeWire.js b/dojox/wire/tests/programmatic/CompositeWire.js
new file mode 100644
index 0000000..63c3b66
--- /dev/null
+++ b/dojox/wire/tests/programmatic/CompositeWire.js
@@ -0,0 +1,47 @@
+dojo.provide("dojox.wire.tests.programmatic.CompositeWire");
+
+dojo.require("dojox.wire.CompositeWire");
+
+tests.register("dojox.wire.tests.programmatic.CompositeWire", [
+
+	function test_CompositeWire_children(t){
+		var source = {a: "A", b: "B"};
+		var target = {};
+		var children = {x: {property: "a"}, y: {property: "b"}};
+		var value = new dojox.wire.CompositeWire({object: source, children: children}).getValue();
+		t.assertEqual(source.a, value.x);
+		t.assertEqual(source.b, value.y);
+		new dojox.wire.CompositeWire({object: target, children: children}).setValue(value);
+		t.assertEqual(source.a, target.a);
+		t.assertEqual(source.b, target.b);
+
+		// with argument
+		target = {};
+		value = new dojox.wire.CompositeWire({children: children}).getValue(source);
+		t.assertEqual(source.a, value.x);
+		t.assertEqual(source.b, value.y);
+		new dojox.wire.CompositeWire({children: children}).setValue(value, target);
+		t.assertEqual(source.a, target.a);
+		t.assertEqual(source.b, target.b);
+
+		// by array
+		target = {};
+		children = [{property: "a"}, {property: "b"}];
+		value = new dojox.wire.CompositeWire({object: source, children: children}).getValue();
+		t.assertEqual(source.a, value[0]);
+		t.assertEqual(source.b, value[1]);
+		new dojox.wire.CompositeWire({object: target, children: children}).setValue(value);
+		t.assertEqual(source.a, target.a);
+		t.assertEqual(source.b, target.b);
+
+		// by array with argument
+		target = {};
+		value = new dojox.wire.CompositeWire({children: children}).getValue(source);
+		t.assertEqual(source.a, value[0]);
+		t.assertEqual(source.b, value[1]);
+		new dojox.wire.CompositeWire({children: children}).setValue(value, target);
+		t.assertEqual(source.a, target.a);
+		t.assertEqual(source.b, target.b);
+	}
+
+]);
diff --git a/dojox/wire/tests/programmatic/ConverterDynamic.js b/dojox/wire/tests/programmatic/ConverterDynamic.js
new file mode 100644
index 0000000..ff31ba0
--- /dev/null
+++ b/dojox/wire/tests/programmatic/ConverterDynamic.js
@@ -0,0 +1,8 @@
+dojo.provide("dojox.wire.tests.programmatic.ConverterDynamic");
+
+dojo.declare("dojox.wire.tests.programmatic.ConverterDynamic", null, {
+	convert: function(v){
+		return v + 1;
+	}
+});
+
diff --git a/dojox/wire/tests/programmatic/DataWire.js b/dojox/wire/tests/programmatic/DataWire.js
new file mode 100644
index 0000000..904f8be
--- /dev/null
+++ b/dojox/wire/tests/programmatic/DataWire.js
@@ -0,0 +1,21 @@
+dojo.provide("dojox.wire.tests.programmatic.DataWire");
+
+dojo.require("dojox.wire.DataWire");
+dojo.require("dojox.data.XmlStore");
+
+tests.register("dojox.wire.tests.programmatic.DataWire", [
+
+	function test_DataWire_attribute(t){
+		var store = new dojox.data.XmlStore();
+		var item = store.newItem({tagName: "x"});
+		new dojox.wire.DataWire({dataStore: store, object: item, attribute: "y"}).setValue("Y");
+		var value = new dojox.wire.DataWire({dataStore: store, object: item, attribute: "y"}).getValue();
+		t.assertEqual("Y", value);
+
+		// nested attribute
+		new dojox.wire.DataWire({dataStore: store, object: item, attribute: "y.z"}).setValue("Z");
+		value = new dojox.wire.DataWire({dataStore: store, object: item, attribute: "y.z"}).getValue();
+		t.assertEqual("Z", value);
+	}
+
+]);
diff --git a/dojox/wire/tests/programmatic/TableAdapter.js b/dojox/wire/tests/programmatic/TableAdapter.js
new file mode 100644
index 0000000..b28d86d
--- /dev/null
+++ b/dojox/wire/tests/programmatic/TableAdapter.js
@@ -0,0 +1,20 @@
+dojo.provide("dojox.wire.tests.programmatic.TableAdapter");
+
+dojo.require("dojox.wire.TableAdapter");
+
+tests.register("dojox.wire.tests.programmatic.TableAdapter", [
+
+	function test_TableAdapter_columns(t){
+		var source = [
+			{a: "A1", b: "B1", c: "C1"},
+			{a: "A2", b: "B2", c: "C2"},
+			{a: "A3", b: "B3", c: "C3"}
+		];
+		var columns = {x: {property: "a"}, y: {property: "b"}, z: {property: "c"}};
+		var value = new dojox.wire.TableAdapter({object: source, columns: columns}).getValue();
+		t.assertEqual(source[0].a, value[0].x);
+		t.assertEqual(source[1].b, value[1].y);
+		t.assertEqual(source[2].c, value[2].z);
+	}
+
+]);
diff --git a/dojox/wire/tests/programmatic/TextAdapter.js b/dojox/wire/tests/programmatic/TextAdapter.js
new file mode 100644
index 0000000..96d4a3e
--- /dev/null
+++ b/dojox/wire/tests/programmatic/TextAdapter.js
@@ -0,0 +1,21 @@
+dojo.provide("dojox.wire.tests.programmatic.TextAdapter");
+
+dojo.require("dojox.wire.TextAdapter");
+
+tests.register("dojox.wire.tests.programmatic.TextAdapter", [
+
+	function test_TextAdapter_segments(t){
+		var source = {a: "a", b: "b", c: "c"};
+		var segments = [{property: "a"}, {property: "b"}, {property: "c"}];
+		var value = new dojox.wire.TextAdapter({object: source, segments: segments}).getValue();
+		t.assertEqual("abc", value);
+	},
+
+	function test_TextAdapter_delimiter(t){
+		var source = {a: "a", b: "b", c: "c"};
+		var segments = [{property: "a"}, {property: "b"}, {property: "c"}];
+		var value = new dojox.wire.TextAdapter({object: source, segments: segments, delimiter: "/"}).getValue();
+		t.assertEqual("a/b/c", value);
+	}
+
+]);
diff --git a/dojox/wire/tests/programmatic/TreeAdapter.js b/dojox/wire/tests/programmatic/TreeAdapter.js
new file mode 100644
index 0000000..bb3d650
--- /dev/null
+++ b/dojox/wire/tests/programmatic/TreeAdapter.js
@@ -0,0 +1,25 @@
+dojo.provide("dojox.wire.tests.programmatic.TreeAdapter");
+
+dojo.require("dojox.wire.TreeAdapter");
+
+tests.register("dojox.wire.tests.programmatic.TreeAdapter", [
+
+	function test_TreeAdapter_nodes(t){
+		var source = [
+			{a: "A1", b: "B1", c: "C1"},
+			{a: "A2", b: "B2", c: "C2"},
+			{a: "A3", b: "B3", c: "C3"}
+		];
+		var nodes = [
+			{title: {property: "a"}, children: [
+				{node: {property: "b"}},
+				{title: {property: "c"}}
+			]}
+		];
+		var value = new dojox.wire.TreeAdapter({object: source, nodes: nodes}).getValue();
+		t.assertEqual(source[0].a, value[0].title);
+		t.assertEqual(source[1].b, value[1].children[0].title);
+		t.assertEqual(source[2].c, value[2].children[1].title);
+	}
+
+]);
diff --git a/dojox/wire/tests/programmatic/Wire.js b/dojox/wire/tests/programmatic/Wire.js
new file mode 100644
index 0000000..b595153
--- /dev/null
+++ b/dojox/wire/tests/programmatic/Wire.js
@@ -0,0 +1,119 @@
+dojo.provide("dojox.wire.tests.programmatic.Wire");
+dojo.require("dojox.wire.Wire");
+
+//Simple connverter class to try to use.
+dojo.declare("dojox.wire.tests.programmatic.Wire.Converter", null, {
+	convert: function(v){
+		return v + 1;
+	}
+});
+
+//Simple converter function to try to use.
+//To get it in the global namespace, gotta assign it to the
+//'window' toplevel object.  Otherwise it ends up in the
+//dojo NS and can't be found.
+if (dojo.isBrowser) {
+	window["__wireTestConverterFunction"] = function(v){
+		return v + 1;
+	};
+}else{
+	var __wireTestConverterFunction = function(v){
+		return v + 1;
+	};
+}
+
+tests.register("dojox.wire.tests.programmatic.Wire", [
+
+	function test_Wire_property(t){
+		var source = {a: "A", b: {c: "B.C"}};
+		var target = {a: "a", b: {c: "b.c"}};
+		var value = new dojox.wire.Wire({object: source, property: "a"}).getValue();
+		new dojox.wire.Wire({object: target, property: "a"}).setValue(value);
+		t.assertEqual(source.a, target.a);
+
+		// child property
+		value = new dojox.wire.Wire({object: source, property: "b.c"}).getValue();
+		new dojox.wire.Wire({object: target, property: "b.c"}).setValue(value);
+		t.assertEqual(source.b.c, target.b.c);
+
+		// new property
+		target = {};
+		value = new dojox.wire.Wire({object: source, property: "a"}).getValue();
+		new dojox.wire.Wire({object: target, property: "a"}).setValue(value);
+		t.assertEqual(source.a, target.a);
+
+		// new parent and child property
+		target.b = {};
+		value = new dojox.wire.Wire({object: source, property: "b.c"}).getValue();
+		new dojox.wire.Wire({object: target, property: "b.c"}).setValue(value);
+		t.assertEqual(source.b.c, target.b.c);
+
+		// new parent and child property
+		target = {};
+		value = new dojox.wire.Wire({object: source, property: "b.c"}).getValue();
+		new dojox.wire.Wire({object: target, property: "b.c"}).setValue(value);
+		t.assertEqual(source.b.c, target.b.c);
+
+		// new array property
+		source = {a: ["A"]};
+		target = {};
+		value = new dojox.wire.Wire({object: source, property: "a[0]"}).getValue();
+		new dojox.wire.Wire({object: target, property: "a[0]"}).setValue(value);
+		t.assertEqual(source.a[0], target.a[0]);
+
+		// by getter/setter
+		source = {getA: function() { return this._a; }, _a: "A"};
+		target = {setA: function(a) { this._a = a; }};
+		value = new dojox.wire.Wire({object: source, property: "a"}).getValue();
+		new dojox.wire.Wire({object: target, property: "a"}).setValue(value);
+		t.assertEqual(source._a, target._a);
+
+		// by get/setPropertyValue
+		source = {getPropertyValue: function(p) { return this["_" + p]; }, _a: "A"};
+		target = {setPropertyValue: function(p, v) { this["_" + p] = v; }};
+		value = new dojox.wire.Wire({object: source, property: "a"}).getValue();
+		new dojox.wire.Wire({object: target, property: "a"}).setValue(value);
+		t.assertEqual(source._a, target._a);
+	},
+
+	function test_Wire_type(t){
+		var source = {a: "1"};
+		var string = new dojox.wire.Wire({object: source, property: "a"}).getValue();
+		t.assertEqual("11", string + 1);
+		var number = new dojox.wire.Wire({object: source, property: "a", type: "number"}).getValue();
+		t.assertEqual(2, number + 1);
+	},
+
+	function test_Wire_converterObject(t){
+		var source = {a: "1"};
+		var converter = {convert: function(v) { return v + 1; }};
+		var string = new dojox.wire.Wire({object: source, property: "a", converter: converter}).getValue();
+		t.assertEqual("11", string);
+	},
+
+	function test_Wire_converterFunction(t){
+		var source = {a: "1"};
+		var converter = {convert: function(v) { return v + 1; }};
+		var number = new dojox.wire.Wire({object: source, property: "a", type: "number", converter: converter.convert}).getValue();
+		t.assertEqual(2, number);
+	},
+
+	function test_Wire_converterObjectByString(t){
+		var source = {a: "1"};
+		var number = new dojox.wire.Wire({object: source, property: "a", type: "number", converter: "dojox.wire.tests.programmatic.Wire.Converter"}).getValue();
+		t.assertEqual(2, number);
+	},
+
+	function test_Wire_converterFunctionByString(t){
+		var source = {a: "1"};
+		var number = new dojox.wire.Wire({object: source, property: "a", type: "number", converter: "__wireTestConverterFunction"}).getValue();
+		t.assertEqual(2, number);
+	},
+
+	function test_Wire_converterObjectByStringDynamic(t){
+		var source = {a: "1"};
+		var number = new dojox.wire.Wire({object: source, property: "a", type: "number", converter: "dojox.wire.tests.programmatic.ConverterDynamic"}).getValue();
+		t.assertEqual(2, number);
+	}
+
+]);
diff --git a/dojox/wire/tests/programmatic/XmlWire.js b/dojox/wire/tests/programmatic/XmlWire.js
new file mode 100644
index 0000000..75fd10d
--- /dev/null
+++ b/dojox/wire/tests/programmatic/XmlWire.js
@@ -0,0 +1,28 @@
+dojo.provide("dojox.wire.tests.programmatic.XmlWire");
+
+dojo.require("dojox.wire.XmlWire");
+
+tests.register("dojox.wire.tests.programmatic.XmlWire", [
+
+	function test_XmlWire_path(t){
+		var object = {};
+		var wire = dojox.wire.create({object: object, property: "element"});
+		new dojox.wire.XmlWire({object: wire, path: "/x/y/text()"}).setValue("Y");
+		var value = new dojox.wire.XmlWire({object: object, property: "element", path: "y/text()"}).getValue();
+		t.assertEqual("Y", value);
+
+		// attribute
+		new dojox.wire.XmlWire({object: object, property: "element", path: "y/@z"}).setValue("Z");
+		value = new dojox.wire.XmlWire({object: wire, path: "/x/y/@z"}).getValue();
+		t.assertEqual("Z", value);
+
+		// with index
+		var document = object.element.ownerDocument;
+		var element = document.createElement("y");
+		element.appendChild(document.createTextNode("Y2"));
+		object.element.appendChild(element);
+		value = new dojox.wire.XmlWire({object: object.element, path: "y[2]/text()"}).getValue();
+		t.assertEqual("Y2", value);
+	}
+
+]);
diff --git a/dojox/wire/tests/programmatic/_base.js b/dojox/wire/tests/programmatic/_base.js
new file mode 100644
index 0000000..8c9907c
--- /dev/null
+++ b/dojox/wire/tests/programmatic/_base.js
@@ -0,0 +1,107 @@
+dojo.provide("dojox.wire.tests.programmatic._base");
+
+dojo.require("dojox.wire._base");
+
+tests.register("dojox.wire.tests.programmatic._base", [
+
+	function test_create(t){
+		var wire = dojox.wire.create({});
+		t.assertTrue(wire instanceof dojox.wire.Wire);
+
+		wire = dojox.wire.create({property: "a"});
+		t.assertTrue(wire instanceof dojox.wire.Wire);
+
+		wire = dojox.wire.create({attribute: "a"});
+		t.assertTrue(wire instanceof dojox.wire.DataWire);
+
+		wire = dojox.wire.create({path: "a"});
+		t.assertTrue(wire instanceof dojox.wire.XmlWire);
+
+		wire = dojox.wire.create({children: "a"});
+		t.assertTrue(wire instanceof dojox.wire.CompositeWire);
+
+		wire = dojox.wire.create({columns: "a"});
+		t.assertTrue(wire instanceof dojox.wire.TableAdapter);
+
+		wire = dojox.wire.create({nodes: "a"});
+		t.assertTrue(wire instanceof dojox.wire.TreeAdapter);
+
+		wire = dojox.wire.create({segments: "a"});
+		t.assertTrue(wire instanceof dojox.wire.TextAdapter);
+
+		wire = dojox.wire.create({wireClass: "dojox.wire.DataWire"});
+		t.assertTrue(wire instanceof dojox.wire.DataWire);
+	},
+	
+	function test_transfer(t){
+		var source = {a: "A"};
+		var target = {};
+		dojox.wire.transfer(
+			{object: source, property: "a"},
+			{object: target, property: "a"});
+		t.assertEqual(source.a, target.a);
+	},
+
+	function test_connect(t){
+		var trigger = {transfer: function() {}, transferArgument: function() {}};
+		var source = {a: "A"};
+		var target = {};
+		dojox.wire.connect({scope: trigger, event: "transfer"},
+			{object: source, property: "a"},
+			{object: target, property: "a"});
+		trigger.transfer();
+		t.assertEqual(source.a, target.a);
+
+		// with argument
+		target = {};
+		dojox.wire.connect({scope: trigger, event: "transferArgument"},
+			{property: "[0].a"},
+			{object: target, property: "a"});
+		trigger.transferArgument(source);
+		t.assertEqual(source.a, target.a);
+
+		// by topic
+		target = {};
+		dojox.wire.connect({topic: "transfer"},
+			{object: source, property: "a"},
+			{object: target, property: "a"});
+		dojo.publish("transfer");
+		t.assertEqual(source.a, target.a);
+
+		// by topic with argument
+		target = {};
+		dojox.wire.connect({topic: "transferArgument"},
+			{property: "[0].a"},
+			{object: target, property: "a"});
+		dojo.publish("transferArgument", [source]);
+		t.assertEqual(source.a, target.a);
+	},
+
+	function test_disconnect(t){
+		var trigger = {transferDisconnect: function() {}};
+		var source = {a: "A"};
+		var target = {};
+		var connection = dojox.wire.connect({scope: trigger, event: "transferDisconnect"},
+			{object: source, property: "a"},
+			{object: target, property: "a"});
+		trigger.transferDisconnect();
+		t.assertEqual(source.a, target.a);
+		delete target.a;
+		dojox.wire.disconnect(connection);
+		trigger.transferDisconnect();
+		t.assertEqual(undefined, target.a);
+
+		// by topic
+		target = {};
+		connection = dojox.wire.connect({topic: "transferDisconnect"},
+			{object: source, property: "a"},
+			{object: target, property: "a"});
+		dojo.publish("transferDisconnect");
+		t.assertEqual(source.a, target.a);
+		delete target.a;
+		dojox.wire.disconnect(connection);
+		dojo.publish("transferDisconnect");
+		t.assertEqual(undefined, target.a);
+	}
+
+]);
diff --git a/dojox/wire/tests/runTests.html b/dojox/wire/tests/runTests.html
new file mode 100644
index 0000000..f4a51de
--- /dev/null
+++ b/dojox/wire/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox.wire Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.wire.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/wire/tests/wire.js b/dojox/wire/tests/wire.js
new file mode 100644
index 0000000..8d1ffbb
--- /dev/null
+++ b/dojox/wire/tests/wire.js
@@ -0,0 +1,14 @@
+dojo.provide("dojox.wire.tests.wire");
+
+try{
+	dojo.require("dojox.wire.tests.programmatic._base");
+	dojo.require("dojox.wire.tests.programmatic.Wire");
+	dojo.requireIf(dojo.isBrowser, "dojox.wire.tests.programmatic.DataWire");
+	dojo.requireIf(dojo.isBrowser, "dojox.wire.tests.programmatic.XmlWire");
+	dojo.require("dojox.wire.tests.programmatic.CompositeWire");
+	dojo.require("dojox.wire.tests.programmatic.TableAdapter");
+	dojo.require("dojox.wire.tests.programmatic.TreeAdapter");
+	dojo.require("dojox.wire.tests.programmatic.TextAdapter");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/wire/tests/wireml.js b/dojox/wire/tests/wireml.js
new file mode 100644
index 0000000..70e088f
--- /dev/null
+++ b/dojox/wire/tests/wireml.js
@@ -0,0 +1,14 @@
+dojo.provide("dojox.wire.tests.wireml");
+
+try{
+	if(dojo.isBrowser){
+		doh.registerUrl("dojox.wire.tests.ml.Action", dojo.moduleUrl("dojox", "wire/tests/markup/Action.html"));
+		doh.registerUrl("dojox.wire.tests.ml.Transfer", dojo.moduleUrl("dojox", "wire/tests/markup/Transfer.html"));
+		doh.registerUrl("dojox.wire.tests.ml.Invocation", dojo.moduleUrl("dojox", "wire/tests/markup/Invocation.html"));
+		doh.registerUrl("dojox.wire.tests.ml.Data", dojo.moduleUrl("dojox", "wire/tests/markup/Data.html"));
+		doh.registerUrl("dojox.wire.tests.ml.DataStore", dojo.moduleUrl("dojox", "wire/tests/markup/DataStore.html"));
+		doh.registerUrl("dojox.wire.tests.ml.Service", dojo.moduleUrl("dojox", "wire/tests/markup/Service.html"));
+	}
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/xml/DomParser.js b/dojox/xml/DomParser.js
index 812df63..804c2ce 100644
--- a/dojox/xml/DomParser.js
+++ b/dojox/xml/DomParser.js
@@ -1,325 +1,389 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.xml.DomParser"]){
-dojo._hasResource["dojox.xml.DomParser"]=true;
 dojo.provide("dojox.xml.DomParser");
+
 dojox.xml.DomParser=new (function(){
-var _1={ELEMENT:1,ATTRIBUTE:2,TEXT:3,CDATA_SECTION:4,PROCESSING_INSTRUCTION:7,COMMENT:8,DOCUMENT:9};
-var _2=/<([^>\/\s+]*)([^>]*)>([^<]*)/g;
-var _3=/([^=]*)=(("([^"]*)")|('([^']*)'))/g;
-var _4=/<!ENTITY\s+([^"]*)\s+"([^"]*)">/g;
-var _5=/<!\[CDATA\[([\u0001-\uFFFF]*?)\]\]>/g;
-var _6=/<!--([\u0001-\uFFFF]*?)-->/g;
-var _7=/^\s+|\s+$/g;
-var _8=/\s+/g;
-var _9=/\>/g;
-var _a=/\</g;
-var _b=/\"/g;
-var _c=/\'/g;
-var _d=/\&/g;
-var _e="_def_";
-function _f(){
-return new (function(){
-var all={};
-this.nodeType=_1.DOCUMENT;
-this.nodeName="#document";
-this.namespaces={};
-this._nsPaths={};
-this.childNodes=[];
-this.documentElement=null;
-this._add=function(obj){
-if(typeof (obj.id)!="undefined"){
-all[obj.id]=obj;
-}
-};
-this._remove=function(id){
-if(all[id]){
-delete all[id];
-}
-};
-this.byId=this.getElementById=function(id){
-return all[id];
-};
-this.byName=this.getElementsByTagName=_10;
-this.byNameNS=this.getElementsByTagNameNS=_11;
-this.childrenByName=_12;
-this.childrenByNameNS=_13;
-})();
-};
-function _10(_14){
-function _15(_16,_17,arr){
-dojo.forEach(_16.childNodes,function(c){
-if(c.nodeType==_1.ELEMENT){
-if(_17=="*"){
-arr.push(c);
-}else{
-if(c.nodeName==_17){
-arr.push(c);
-}
-}
-_15(c,_17,arr);
-}
-});
-};
-var a=[];
-_15(this,_14,a);
-return a;
-};
-function _11(_18,ns){
-function _19(_1a,_1b,ns,arr){
-dojo.forEach(_1a.childNodes,function(c){
-if(c.nodeType==_1.ELEMENT){
-if(_1b=="*"&&c.ownerDocument._nsPaths[ns]==c.namespace){
-arr.push(c);
-}else{
-if(c.localName==_1b&&c.ownerDocument._nsPaths[ns]==c.namespace){
-arr.push(c);
-}
-}
-_19(c,_1b,ns,arr);
-}
-});
-};
-if(!ns){
-ns=_e;
-}
-var a=[];
-_19(this,_18,ns,a);
-return a;
-};
-function _12(_1c){
-var a=[];
-dojo.forEach(this.childNodes,function(c){
-if(c.nodeType==_1.ELEMENT){
-if(_1c=="*"){
-a.push(c);
-}else{
-if(c.nodeName==_1c){
-a.push(c);
-}
-}
-}
-});
-return a;
-};
-function _13(_1d,ns){
-var a=[];
-dojo.forEach(this.childNodes,function(c){
-if(c.nodeType==_1.ELEMENT){
-if(_1d=="*"&&c.ownerDocument._nsPaths[ns]==c.namespace){
-a.push(c);
-}else{
-if(c.localName==_1d&&c.ownerDocument._nsPaths[ns]==c.namespace){
-a.push(c);
-}
-}
-}
-});
-return a;
-};
-function _1e(v){
-return {nodeType:_1.TEXT,nodeName:"#text",nodeValue:v.replace(_8," ").replace(_9,">").replace(_a,"<").replace(_c,"'").replace(_b,"\"").replace(_d,"&")};
-};
-function _1f(_20){
-for(var i=0;i<this.attributes.length;i++){
-if(this.attributes[i].nodeName==_20){
-return this.attributes[i].nodeValue;
-}
-}
-return null;
-};
-function _21(_22,ns){
-for(var i=0;i<this.attributes.length;i++){
-if(this.ownerDocument._nsPaths[ns]==this.attributes[i].namespace&&this.attributes[i].localName==_22){
-return this.attributes[i].nodeValue;
-}
-}
-return null;
-};
-function _23(_24,val){
-var old=null;
-for(var i=0;i<this.attributes.length;i++){
-if(this.attributes[i].nodeName==_24){
-old=this.attributes[i].nodeValue;
-this.attributes[i].nodeValue=val;
-break;
-}
-}
-if(_24=="id"){
-if(old!=null){
-this.ownerDocument._remove(old);
-}
-this.ownerDocument._add(this);
-}
-};
-function _25(_26,val,ns){
-for(var i=0;i<this.attributes.length;i++){
-if(this.ownerDocument._nsPaths[ns]==this.attributes[i].namespace&&this.attributes[i].localName==_26){
-this.attributes[i].nodeValue=val;
-return;
-}
-}
-};
-function _27(){
-var p=this.parentNode;
-if(p){
-for(var i=0;i<p.childNodes.length;i++){
-if(p.childNodes[i]==this&&i>0){
-return p.childNodes[i-1];
-}
-}
-}
-return null;
-};
-function _28(){
-var p=this.parentNode;
-if(p){
-for(var i=0;i<p.childNodes.length;i++){
-if(p.childNodes[i]==this&&(i+1)<p.childNodes.length){
-return p.childNodes[i+1];
-}
-}
-}
-return null;
-};
-this.parse=function(str){
-var _29=_f();
-if(str==null){
-return _29;
-}
-if(str.length==0){
-return _29;
-}
-if(str.indexOf("<!ENTITY")>0){
-var _2a,eRe=[];
-if(_4.test(str)){
-_4.lastIndex=0;
-while((_2a=_4.exec(str))!=null){
-eRe.push({entity:"&"+_2a[1].replace(_7,"")+";",expression:_2a[2]});
-}
-for(var i=0;i<eRe.length;i++){
-str=str.replace(new RegExp(eRe[i].entity,"g"),eRe[i].expression);
-}
-}
-}
-var _2b=[],_2c;
-while((_2c=_5.exec(str))!=null){
-_2b.push(_2c[1]);
-}
-for(var i=0;i<_2b.length;i++){
-str=str.replace(_2b[i],i);
-}
-var _2d=[],_2e;
-while((_2e=_6.exec(str))!=null){
-_2d.push(_2e[1]);
-}
-for(i=0;i<_2d.length;i++){
-str=str.replace(_2d[i],i);
-}
-var res,obj=_29;
-while((res=_2.exec(str))!=null){
-if(res[2].charAt(0)=="/"&&res[2].replace(_7,"").length>1){
-if(obj.parentNode){
-obj=obj.parentNode;
-}
-var _2f=(res[3]||"").replace(_7,"");
-if(_2f.length>0){
-obj.childNodes.push(_1e(_2f));
-}
-}else{
-if(res[1].length>0){
-if(res[1].charAt(0)=="?"){
-var _30=res[1].substr(1);
-var _31=res[2].substr(0,res[2].length-2);
-obj.childNodes.push({nodeType:_1.PROCESSING_INSTRUCTION,nodeName:_30,nodeValue:_31});
-}else{
-if(res[1].charAt(0)=="!"){
-if(res[1].indexOf("![CDATA[")==0){
-var val=parseInt(res[1].replace("![CDATA[","").replace("]]",""));
-obj.childNodes.push({nodeType:_1.CDATA_SECTION,nodeName:"#cdata-section",nodeValue:_2b[val]});
-}else{
-if(res[1].substr(0,3)=="!--"){
-var val=parseInt(res[1].replace("!--","").replace("--",""));
-obj.childNodes.push({nodeType:_1.COMMENT,nodeName:"#comment",nodeValue:_2d[val]});
-}
-}
-}else{
-var _30=res[1].replace(_7,"");
-var o={nodeType:_1.ELEMENT,nodeName:_30,localName:_30,namespace:_e,ownerDocument:_29,attributes:[],parentNode:null,childNodes:[]};
-if(_30.indexOf(":")>-1){
-var t=_30.split(":");
-o.namespace=t[0];
-o.localName=t[1];
-}
-o.byName=o.getElementsByTagName=_10;
-o.byNameNS=o.getElementsByTagNameNS=_11;
-o.childrenByName=_12;
-o.childrenByNameNS=_13;
-o.getAttribute=_1f;
-o.getAttributeNS=_21;
-o.setAttribute=_23;
-o.setAttributeNS=_25;
-o.previous=o.previousSibling=_27;
-o.next=o.nextSibling=_28;
-var _32;
-while((_32=_3.exec(res[2]))!=null){
-if(_32.length>0){
-var _30=_32[1].replace(_7,"");
-var val=(_32[4]||_32[6]||"").replace(_8," ").replace(_9,">").replace(_a,"<").replace(_c,"'").replace(_b,"\"").replace(_d,"&");
-if(_30.indexOf("xmlns")==0){
-if(_30.indexOf(":")>0){
-var ns=_30.split(":");
-_29.namespaces[ns[1]]=val;
-_29._nsPaths[val]=ns[1];
-}else{
-_29.namespaces[_e]=val;
-_29._nsPaths[val]=_e;
-}
-}else{
-var ln=_30;
-var ns=_e;
-if(_30.indexOf(":")>0){
-var t=_30.split(":");
-ln=t[1];
-ns=t[0];
-}
-o.attributes.push({nodeType:_1.ATTRIBUTE,nodeName:_30,localName:ln,namespace:ns,nodeValue:val});
-if(ln=="id"){
-o.id=val;
-}
-}
-}
-}
-_29._add(o);
-if(obj){
-obj.childNodes.push(o);
-o.parentNode=obj;
-if(res[2].charAt(res[2].length-1)!="/"){
-obj=o;
-}
-}
-var _2f=res[3];
-if(_2f.length>0){
-obj.childNodes.push(_1e(_2f));
-}
-}
-}
-}
-}
-}
-for(var i=0;i<_29.childNodes.length;i++){
-var e=_29.childNodes[i];
-if(e.nodeType==_1.ELEMENT){
-_29.documentElement=e;
-break;
-}
-}
-return _29;
-};
+	/**********************************************************
+	 *	The DomParser is a close-to (but not entirely)
+	 *	conforming XML parser based on regular
+	 *	expressions.  It will take any XML fragment
+	 *	and return a lightweight JS structure that is
+	 *	similar to (but not exactly) the DOM specification.
+	 *
+	 *	Getter and setter methods are NOT available; the goal
+	 *	was to keep the resulting object model entirely JS-like.
+	 *
+	 *	All node types but document fragments are supported;
+	 *	all nodes support getElementsByTagName and 
+	 *	getElementsByTagNameNS (with short names byName and 
+	 *	byNameNS).  The document node supports getElementById
+	 *	(byId), and all nodes support a supplimental
+	 *	childrenByName/childrenByNameNS method as well.
+	 *
+	 *	The object model is intended to be a READONLY format;
+	 *	mutation events are NOT supported, and though you
+	 *	can change properties on a node-by-node basis, certain
+	 *	operations are not supported (such as changing the ID 
+	 *	of an element).
+	 **********************************************************/
+
+	//	internal use only.
+	var nodeTypes={ ELEMENT:1, ATTRIBUTE:2, TEXT:3, CDATA_SECTION:4, PROCESSING_INSTRUCTION:7, COMMENT:8, DOCUMENT:9 };
+
+	//	compile the regular expressions once.
+	var reTags=/<([^>\/\s+]*)([^>]*)>([^<]*)/g;
+	var reAttr=/([^=]*)=(("([^"]*)")|('([^']*)'))/g;	//	patch from tdedischew AT gmail, with additional grouping
+	var reEntity=/<!ENTITY\s+([^"]*)\s+"([^"]*)">/g;
+	var reCData=/<!\[CDATA\[([\u0001-\uFFFF]*?)\]\]>/g;
+	var reComments=/<!--([\u0001-\uFFFF]*?)-->/g;
+	var trim=/^\s+|\s+$/g;
+	var normalize=/\s+/g;
+	var egt=/\>/g;
+	var elt=/\</g;
+	var equot=/\"/g;
+	var eapos=/\'/g;
+	var eamp=/\&/g;
+	var dNs="_def_";
+
+	//	create a root node.
+	function _doc(){
+		return new (function(){
+			var all={};
+			this.nodeType=nodeTypes.DOCUMENT;
+			this.nodeName="#document";
+			this.namespaces={};
+			this._nsPaths={};
+			this.childNodes=[];
+			this.documentElement=null;
+
+			//	any element with an ID attribute will be added to the internal hashtable.
+			this._add=function(obj){
+				if(typeof(obj.id)!="undefined"){ all[obj.id]=obj; }
+			};
+			this._remove=function(id){
+				if(all[id]){ delete all[id]; }
+			};
+
+			this.byId=this.getElementById=function(id){ return all[id]; };
+			this.byName=this.getElementsByTagName=byName;
+			this.byNameNS=this.getElementsByTagNameNS=byNameNS;
+			this.childrenByName=childrenByName;
+			this.childrenByNameNS=childrenByNameNS;
+		})();
+	}
+
+	//	functions attached to element nodes
+	function byName(name){
+		//	return all descendants with name.  Fully qualified (i.e. svg:svg)
+		function __(node, name, arr){
+			dojo.forEach(node.childNodes, function(c){
+				if(c.nodeType==nodeTypes.ELEMENT){
+					if(name=="*"){ arr.push(c); }
+					else if(c.nodeName==name){ arr.push(c); }
+					__(c, name, arr);
+				}
+			});
+		}
+		var a=[];
+		__(this, name, a);
+		return a;
+	}
+	function byNameNS(name, ns){
+		//	return all descendants with name by namespace.  If no namespace passed, the default is used.
+		function __(node, name, ns, arr){
+			dojo.forEach(node.childNodes, function(c){
+				if(c.nodeType==nodeTypes.ELEMENT){
+					if(name=="*"&&c.ownerDocument._nsPaths[ns]==c.namespace){ arr.push(c); }
+					else if(c.localName==name&&c.ownerDocument._nsPaths[ns]==c.namespace){ arr.push(c); }
+					__(c, name, ns, arr);
+				}
+			});
+		}
+		if(!ns){ ns=dNs; }
+		var a=[];
+		__(this, name, ns, a);
+		return a;
+	}
+	//	Only child nodes with name.
+	function childrenByName(name){
+		var a=[];
+		dojo.forEach(this.childNodes, function(c){
+			if(c.nodeType==nodeTypes.ELEMENT){
+				if(name=="*"){ a.push(c); }
+				else if(c.nodeName==name){ a.push(c); }
+			}
+		});
+		return a;
+	}
+
+	function childrenByNameNS(name, ns){
+		var a=[];
+		dojo.forEach(this.childNodes, function(c){
+			if(c.nodeType==nodeTypes.ELEMENT){
+				if(name=="*"&&c.ownerDocument._nsPaths[ns]==c.namespace){ a.push(c); }
+				else if(c.localName==name&&c.ownerDocument._nsPaths[ns]==c.namespace){ a.push(c); }
+			}
+		});
+		return a;
+	}
+
+	function _createTextNode(v){
+		return { 
+			nodeType:nodeTypes.TEXT,
+			nodeName:"#text",
+			nodeValue:v.replace(normalize," ").replace(egt,">").replace(elt,"<").replace(eapos,"'").replace(equot,'"').replace(eamp,"&")
+		};
+	}
+
+	//	attribute functions
+	function getAttr(name){
+		for(var i=0; i<this.attributes.length; i++){
+			if(this.attributes[i].nodeName==name){
+				return this.attributes[i].nodeValue;
+			}
+		}
+		return null;
+	}
+	function getAttrNS(name, ns){
+		for(var i=0; i<this.attributes.length; i++){
+			if(this.ownerDocument._nsPaths[ns]==this.attributes[i].namespace
+				&&this.attributes[i].localName==name
+			){
+				return this.attributes[i].nodeValue;
+			}
+		}
+		return null;
+	}
+	//	note that you can only swap IDs using setAttribute, NOT with setAttributeNS.
+	function setAttr(name, val){
+		var old=null;
+		for(var i=0; i<this.attributes.length; i++){
+			if(this.attributes[i].nodeName==name){
+				old=this.attributes[i].nodeValue;
+				this.attributes[i].nodeValue=val;
+				break;
+			}
+		}
+		if(name=="id"){
+			if(old!=null){ this.ownerDocument._remove(old); }
+			this.ownerDocument._add(this);
+		}
+	}
+	function setAttrNS(name, val, ns){
+		for(var i=0; i<this.attributes.length; i++){
+			if(this.ownerDocument._nsPaths[ns]==this.attributes[i].namespace
+				&&this.attributes[i].localName==name
+			){
+				this.attributes[i].nodeValue=val;
+				return;
+			}
+		}
+	}
+
+	//	navigation
+	function prev(){
+		var p=this.parentNode;
+		if(p){
+			for(var i=0;i<p.childNodes.length;i++){
+				if(p.childNodes[i]==this&&i>0){
+					return p.childNodes[i-1];
+				}
+			}
+		}
+		return null;
+	}
+	function next(){
+		var p=this.parentNode;
+		if(p){
+			for(var i=0;i<p.childNodes.length;i++){
+				if(p.childNodes[i]==this&&(i+1)<p.childNodes.length){
+					return p.childNodes[i+1];
+				}
+			}
+		}
+		return null;
+	}
+
+	//	the main method.
+	this.parse=function(/* String */str){
+		var root=_doc();
+		if(str==null){ return root; }
+		if(str.length==0){ return root; }
+
+		//	preprocess custom entities
+		if(str.indexOf("<!ENTITY")>0){
+			var entity, eRe=[];
+			if(reEntity.test(str)){
+				reEntity.lastIndex=0;
+				//	match entities
+				while((entity=reEntity.exec(str))!=null){
+					eRe.push({ 
+						entity:"&"+entity[1].replace(trim,"")+";", 
+						expression:entity[2] 
+					});
+				}
+				//	replace instances in the document.
+				for(var i=0; i<eRe.length; i++){
+					str=str.replace(new RegExp(eRe[i].entity, "g"), eRe[i].expression);
+				}
+			}
+		}
+
+		//	pre-parse for CData, and tokenize.
+		var cdSections=[], cdata;
+		while((cdata=reCData.exec(str))!=null){ cdSections.push(cdata[1]); }
+		for(var i=0; i<cdSections.length; i++){ str=str.replace(cdSections[i], i); }
+		
+		//	pre-parse for comments, and tokenize.
+		var comments=[], comment;
+		while((comment=reComments.exec(str))!=null){ comments.push(comment[1]); }
+		for(i=0; i<comments.length; i++){ str=str.replace(comments[i], i); }
+
+		//	parse the document
+		var res, obj=root;
+		while((res=reTags.exec(str))!=null){
+			//	closing tags.
+			if(res[2].charAt(0)=="/" && res[2].replace(trim, "").length>1){
+				if(obj.parentNode){
+					obj=obj.parentNode;
+				}
+				var text=(res[3]||"").replace(trim, "");
+				if(text.length>0) {
+					obj.childNodes.push(_createTextNode(text));
+				}
+			}
+
+			//	open tags.
+			else if(res[1].length>0){
+				//	figure out the type of node.
+				if(res[1].charAt(0)=="?"){
+					//	processing instruction
+					var name=res[1].substr(1);
+					var target=res[2].substr(0,res[2].length-2);
+					obj.childNodes.push({ 
+						nodeType:nodeTypes.PROCESSING_INSTRUCTION, 
+						nodeName:name, 
+						nodeValue:target 
+					});
+				}
+				else if(res[1].charAt(0)=="!"){
+					//	CDATA; skip over any declaration elements.
+					if(res[1].indexOf("![CDATA[")==0){
+						var val=parseInt(res[1].replace("![CDATA[","").replace("]]",""));
+						obj.childNodes.push({ 
+							nodeType:nodeTypes.CDATA_SECTION, 
+							nodeName:"#cdata-section", 
+							nodeValue:cdSections[val] 
+						});
+					}
+					//	Comments.
+					else if(res[1].substr(0,3)=="!--"){
+						var val=parseInt(res[1].replace("!--","").replace("--",""));
+						obj.childNodes.push({ 
+							nodeType:nodeTypes.COMMENT, 
+							nodeName:"#comment", 
+							nodeValue:comments[val] 
+						});
+					}
+				}
+				else {
+					//	Elements (with attribute and text)
+					var name=res[1].replace(trim,"");
+					var o={ 
+						nodeType:nodeTypes.ELEMENT, 
+						nodeName:name, 
+						localName:name, 
+						namespace:dNs, 
+						ownerDocument:root, 
+						attributes:[], 
+						parentNode:null, 
+						childNodes:[] 
+					};
+
+					//	check to see if it's namespaced.
+					if(name.indexOf(":")>-1){
+						var t=name.split(":");
+						o.namespace=t[0];
+						o.localName=t[1];
+					}
+
+					//	set the function references.
+					o.byName=o.getElementsByTagName=byName;
+					o.byNameNS=o.getElementsByTagNameNS=byNameNS;
+					o.childrenByName=childrenByName;
+					o.childrenByNameNS=childrenByNameNS;
+					o.getAttribute=getAttr;
+					o.getAttributeNS=getAttrNS;
+					o.setAttribute=setAttr;
+					o.setAttributeNS=setAttrNS;
+					o.previous=o.previousSibling=prev;
+					o.next=o.nextSibling=next;
+
+					//	parse the attribute string.
+					var attr;
+					while((attr=reAttr.exec(res[2]))!=null){
+						if(attr.length>0){
+							var name=attr[1].replace(trim,"");
+							var val=(attr[4]||attr[6]||"").replace(normalize," ")
+								.replace(egt,">")
+								.replace(elt,"<")
+								.replace(eapos,"'")
+								.replace(equot,'"')
+								.replace(eamp,"&");
+							if(name.indexOf("xmlns")==0){
+								if(name.indexOf(":")>0){
+									var ns=name.split(":");
+									root.namespaces[ns[1]]=val;
+									root._nsPaths[val]=ns[1];
+								} else {
+									root.namespaces[dNs]=val;
+									root._nsPaths[val]=dNs;
+								}
+							} else {
+								var ln=name;
+								var ns=dNs;
+								if(name.indexOf(":")>0){
+									var t=name.split(":");
+									ln=t[1];
+									ns=t[0];
+								}
+								o.attributes.push({
+									nodeType:nodeTypes.ATTRIBUTE, 
+									nodeName:name, 
+									localName:ln, 
+									namespace:ns, 
+									nodeValue:val 
+								});
+
+								//	only add id as a property.
+								if(ln=="id"){ o.id=val; }
+							}
+						}
+					}
+					root._add(o);
+
+					if(obj){
+						obj.childNodes.push(o);
+						o.parentNode=obj;
+						//	if it's not a self-closing node.
+						if(res[2].charAt(res[2].length-1)!="/"){
+							obj=o;
+						}
+					}
+					var text=res[3];
+					if(text.length>0){
+						obj.childNodes.push(_createTextNode(text));
+					}
+				}
+			}
+		}
+
+		//	set the document element
+		for(var i=0; i<root.childNodes.length; i++){
+			var e=root.childNodes[i];
+			if(e.nodeType==nodeTypes.ELEMENT){
+				root.documentElement=e;
+				break;
+			}
+		}
+		return root;
+	};
 })();
-}
diff --git a/dojox/xml/Script.js b/dojox/xml/Script.js
index 07acb09..9b0a2e8 100644
--- a/dojox/xml/Script.js
+++ b/dojox/xml/Script.js
@@ -1,16 +1,11 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.xml.Script"]){
-dojo._hasResource["dojox.xml.Script"]=true;
 dojo.provide("dojox.xml.Script");
 dojo.require("dojo.parser");
 dojo.require("dojox.xml.widgetParser");
-dojo.declare("dojox.xml.Script",null,{constructor:function(_1,_2){
-dojo.parser.instantiate(dojox.xml.widgetParser._processScript(_2));
-}});
-}
+
+dojo.declare("dojox.xml.Script", null, {
+	constructor: function(props, node){
+		dojo.parser.instantiate(
+			dojox.xml.widgetParser._processScript(node)
+		);
+	}
+});
diff --git a/dojox/xml/parser.js b/dojox/xml/parser.js
index 0855194..7486cfc 100644
--- a/dojox/xml/parser.js
+++ b/dojox/xml/parser.js
@@ -1,137 +1,187 @@
-/*
-	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
-*/
+dojo.provide("dojox.xml.parser");
 
+//DOM type to int value for reference.
+//Ints make for more compact code than full constant names.
+//ELEMENT_NODE                  = 1;
+//ATTRIBUTE_NODE                = 2;
+//TEXT_NODE                     = 3;
+//CDATA_SECTION_NODE            = 4;
+//ENTITY_REFERENCE_NODE         = 5;
+//ENTITY_NODE                   = 6;
+//PROCESSING_INSTRUCTION_NODE   = 7;
+//COMMENT_NODE                  = 8;
+//DOCUMENT_NODE                 = 9;
+//DOCUMENT_TYPE_NODE            = 10;
+//DOCUMENT_FRAGMENT_NODE        = 11;
+//NOTATION_NODE                 = 12;
 
-if(!dojo._hasResource["dojox.xml.parser"]){
-dojo._hasResource["dojox.xml.parser"]=true;
-dojo.provide("dojox.xml.parser");
-dojox.xml.parser.parse=function(_1,_2){
-var _3=dojo.doc;
-var _4;
-_2=_2||"text/xml";
-if(_1&&dojo.trim(_1)&&"DOMParser" in dojo.global){
-var _5=new DOMParser();
-_4=_5.parseFromString(_1,_2);
-var de=_4.documentElement;
-var _6="http://www.mozilla.org/newlayout/xml/parsererror.xml";
-if(de.nodeName=="parsererror"&&de.namespaceURI==_6){
-var _7=de.getElementsByTagNameNS(_6,"sourcetext")[0];
-if(!_7){
-_7=_7.firstChild.data;
-}
-throw new Error("Error parsing text "+nativeDoc.documentElement.firstChild.data+" \n"+_7);
-}
-return _4;
-}else{
-if("ActiveXObject" in dojo.global){
-var ms=function(n){
-return "MSXML"+n+".DOMDocument";
-};
-var dp=["Microsoft.XMLDOM",ms(6),ms(4),ms(3),ms(2)];
-dojo.some(dp,function(p){
-try{
-_4=new ActiveXObject(p);
-}
-catch(e){
-return false;
-}
-return true;
-});
-if(_1&&_4){
-_4.async=false;
-_4.loadXML(_1);
-var pe=_4.parseError;
-if(pe.errorCode!==0){
-throw new Error("Line: "+pe.line+"\n"+"Col: "+pe.linepos+"\n"+"Reason: "+pe.reason+"\n"+"Error Code: "+pe.errorCode+"\n"+"Source: "+pe.srcText);
-}
-}
-if(_4){
-return _4;
-}
-}else{
-if(_3.implementation&&_3.implementation.createDocument){
-if(_1&&dojo.trim(_1)&&_3.createElement){
-var _8=_3.createElement("xml");
-_8.innerHTML=_1;
-var _9=_3.implementation.createDocument("foo","",null);
-dojo.forEach(_8.childNodes,function(_a){
-_9.importNode(_a,true);
-});
-return _9;
-}else{
-return _3.implementation.createDocument("","",null);
-}
-}
-}
-}
-return null;
-};
-dojox.xml.parser.textContent=function(_b,_c){
-if(arguments.length>1){
-var _d=_b.ownerDocument||dojo.doc;
-dojox.xml.parser.replaceChildren(_b,_d.createTextNode(_c));
-return _c;
-}else{
-if(_b.textContent!==undefined){
-return _b.textContent;
-}
-var _e="";
-if(_b){
-dojo.forEach(_b.childNodes,function(_f){
-switch(_f.nodeType){
-case 1:
-case 5:
-_e+=dojox.xml.parser.textContent(_f);
-break;
-case 3:
-case 2:
-case 4:
-_e+=_f.nodeValue;
-}
-});
-}
-return _e;
-}
-};
-dojox.xml.parser.replaceChildren=function(_10,_11){
-var _12=[];
-if(dojo.isIE){
-dojo.forEach(_10.childNodes,function(_13){
-_12.push(_13);
-});
-}
-dojox.xml.parser.removeChildren(_10);
-dojo.forEach(_12,dojo.destroy);
-if(!dojo.isArray(_11)){
-_10.appendChild(_11);
-}else{
-dojo.forEach(_11,function(_14){
-_10.appendChild(_14);
-});
-}
-};
-dojox.xml.parser.removeChildren=function(_15){
-var _16=_15.childNodes.length;
-while(_15.hasChildNodes()){
-_15.removeChild(_15.firstChild);
+dojox.xml.parser.parse = function(/*String?*/ str, /*String?*/ mimetype){
+	//	summary:
+	//		cross-browser implementation of creating an XML document object from null, empty string, and XML text..
+	//
+	//	str:
+	//		Optional text to create the document from.  If not provided, an empty XML document will be created.  
+	//		If str is empty string "", then a new empty document will be created.
+	//	mimetype:
+	//		Optional mimetype of the text.  Typically, this is text/xml.  Will be defaulted to text/xml if not provided.
+	var _document = dojo.doc;
+	var doc;
+
+	mimetype = mimetype || "text/xml";
+	if(str && dojo.trim(str) && "DOMParser" in dojo.global){
+		//Handle parsing the text on Mozilla based browsers etc..
+		var parser = new DOMParser();
+		doc = parser.parseFromString(str, mimetype);
+		var de = doc.documentElement;
+		var errorNS = "http://www.mozilla.org/newlayout/xml/parsererror.xml";
+		if(de.nodeName == "parsererror" && de.namespaceURI == errorNS){
+			var sourceText = de.getElementsByTagNameNS(errorNS, 'sourcetext')[0];
+			if(sourceText){
+				sourceText = sourceText.firstChild.data;
+			}
+        	throw new Error("Error parsing text " + de.firstChild.data + " \n" + sourceText);
+		}
+		return doc;
+
+	}else if("ActiveXObject" in dojo.global){
+		//Handle IE.
+		var ms = function(n){ return "MSXML" + n + ".DOMDocument"; };
+		var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)];
+		dojo.some(dp, function(p){
+			try{
+				doc = new ActiveXObject(p);
+			}catch(e){ return false; }
+			return true;
+		});
+		if(str && doc){
+			doc.async = false;
+			doc.loadXML(str);
+			var pe = doc.parseError;
+			if(pe.errorCode !== 0){
+				throw new Error("Line: " + pe.line + "\n" +
+					"Col: " + pe.linepos + "\n" +
+					"Reason: " + pe.reason + "\n" + 
+					"Error Code: " + pe.errorCode + "\n" +
+					"Source: " + pe.srcText);
+			}
+		}
+		if(doc){
+			return doc; //DOMDocument
+		}
+	}else if(_document.implementation && _document.implementation.createDocument){
+		if(str && dojo.trim(str) && _document.createElement){
+			//Everyone else that we couldn't get to work.  Fallback case.
+			// FIXME: this may change all tags to uppercase!
+			var tmp = _document.createElement("xml");
+			tmp.innerHTML = str;
+			var xmlDoc = _document.implementation.createDocument("foo", "", null);
+			dojo.forEach(tmp.childNodes, function(child){
+				xmlDoc.importNode(child, true);
+			});
+			return xmlDoc;	//	DOMDocument
+		}else{
+			return _document.implementation.createDocument("", "", null); // DOMDocument
+		}
+	}
+	return null;	//	null
 }
-return _16;
-};
-dojox.xml.parser.innerXML=function(_17){
-if(_17.innerXML){
-return _17.innerXML;
-}else{
-if(_17.xml){
-return _17.xml;
-}else{
-if(typeof XMLSerializer!="undefined"){
-return (new XMLSerializer()).serializeToString(_17);
+
+dojox.xml.parser.textContent = function(/*Node*/node, /*String?*/text){
+	//	summary:
+	//		Implementation of the DOM Level 3 attribute; scan node for text
+	//	description:
+	//		Implementation of the DOM Level 3 attribute; scan node for text
+	//		This function can also update the text of a node by replacing all child 
+	//		content of the node.
+	//	node:
+	//		The node to get the text off of or set the text on.
+	//	text:
+	//		Optional argument of the text to apply to the node.
+	if(arguments.length>1){
+		var _document = node.ownerDocument || dojo.doc;  //Preference is to get the node owning doc first or it may fail
+		dojox.xml.parser.replaceChildren(node, _document.createTextNode(text));
+		return text;	//	String
+	}else{
+		if(node.textContent !== undefined){ //FF 1.5 -- remove?
+			return node.textContent;	//	String
+		}
+		var _result = "";
+		if(node){
+			dojo.forEach(node.childNodes, function(child){
+				switch(child.nodeType){
+					case 1: // ELEMENT_NODE
+					case 5: // ENTITY_REFERENCE_NODE
+						_result += dojox.xml.parser.textContent(child);
+						break;
+					case 3: // TEXT_NODE
+					case 2: // ATTRIBUTE_NODE
+					case 4: // CDATA_SECTION_NODE
+						_result += child.nodeValue;
+				}
+			});
+		}
+		return _result;	//	String
+	}
 }
+
+dojox.xml.parser.replaceChildren = function(/*Element*/node, /*Node || Array*/ newChildren){
+	//	summary:
+	//		Removes all children of node and appends newChild. All the existing
+	//		children will be destroyed.
+	//	description:
+	//		Removes all children of node and appends newChild. All the existing
+	//		children will be destroyed.
+	// 	node:
+	//		The node to modify the children on
+	//	newChildren:
+	//		The children to add to the node.  It can either be a single Node or an
+	//		array of Nodes.
+	var nodes = [];
+
+	if(dojo.isIE){
+		dojo.forEach(node.childNodes, function(child){
+			nodes.push(child);
+		});
+	}
+
+	dojox.xml.parser.removeChildren(node);
+	dojo.forEach(nodes, dojo.destroy);
+
+	if(!dojo.isArray(newChildren)){
+		node.appendChild(newChildren);
+	}else{
+		dojo.forEach(newChildren, function(child){
+			node.appendChild(child);
+		});
+	}
 }
+
+dojox.xml.parser.removeChildren = function(/*Element*/node){
+	//	summary:
+	//		removes all children from node and returns the count of children removed.
+	//		The children nodes are not destroyed. Be sure to call dojo.destroy on them
+	//		after they are not used anymore.
+	//	node:
+	//		The node to remove all the children from.
+	var count = node.childNodes.length;
+	while(node.hasChildNodes()){
+		node.removeChild(node.firstChild);
+	}
+	return count; // int
 }
-return null;
-};
+
+
+dojox.xml.parser.innerXML = function(/*Node*/node){
+	//	summary:
+	//		Implementation of MS's innerXML function.
+	//	node:
+	//		The node from which to generate the XML text representation.
+	if(node.innerXML){
+		return node.innerXML;	//	String
+	}else if(node.xml){
+		return node.xml;		//	String
+	}else if(typeof XMLSerializer != "undefined"){
+		return (new XMLSerializer()).serializeToString(node);	//	String
+	}
+	return null;
 }
diff --git a/dojox/xml/tests/mail.html b/dojox/xml/tests/mail.html
new file mode 100644
index 0000000..a09fd9d
--- /dev/null
+++ b/dojox/xml/tests/mail.html
@@ -0,0 +1,484 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Demo Mail Application</title>
+
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/soria/soria.css";
+		@import "mail/mail.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true, defaultTestTheme: 'soria'"></script>
+	<script type="text/javascript" src="../../../dijit/tests/tests/_testCommon.js"></script>
+	<script type="text/javascript">
+		// Use profile builds, if available. Since we use pretty much all of
+		// the widgets, just use dijit-all. A custom profile would provide some
+		// additional savings.
+		dojo.require("dijit.dijit");
+		dojo.require("dijit.dijit-all");
+
+		dojo.require("dojo.parser");
+		dojo.require("dojo.data.ItemFileWriteStore");
+
+		dojo.require("dijit.dijit");
+		dojo.require("dijit.Declaration");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.Menu");
+		dojo.require("dijit.Tree");
+		dojo.require("dijit.Tooltip");
+		dojo.require("dijit.Dialog");
+		dojo.require("dijit.Toolbar");
+		dojo.require("dijit.Calendar");
+		dojo.require("dijit.ColorPalette");
+		dojo.require("dijit.Editor");
+		dojo.require("dijit._editor.plugins.LinkDialog");
+		dojo.require("dijit.ProgressBar");
+
+		dojo.require("dijit.form.ComboBox");
+		dojo.require("dijit.form.CheckBox");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dijit.form.Textarea");
+
+		dojo.require("dijit.layout.LayoutContainer");
+		dojo.require("dijit.layout.SplitContainer");
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojox.xml.Script");
+
+
+
+		var paneId=1;
+
+		// for "new message" tab closing
+		function testClose(pane,tab){
+		  return confirm("Are you sure you want to leave your changes?");
+		}
+
+		// fake mail download code:
+		var numMails;
+		var updateFetchStatus = function(x){
+			if(x == 0){
+				dijit.byId('fakeFetch').update({ indeterminate: false });
+				return;
+			}
+			dijit.byId('fakeFetch').update({ progress: x });
+			if (x == numMails){
+				dojo.fadeOut({ node: 'fetchMail', duration:800,
+					// set progress back to indeterminate. we're cheating, because this
+					// doesn't actually have any data to "progress"
+					onEnd: function(){
+						dijit.byId('fakeFetch').update({ indeterminate: true });
+						dojo.byId('fetchMail').style.visibility='hidden'; // remove progress bar from tab order
+					}
+				}).play();
+			}
+		}
+		var fakeReport = function(percent){
+			// FIXME: can't set a label on an indeterminate progress bar
+			// like if(this.indeterminate) { return " connecting."; }
+			return "Fetching: "+(percent*this.maximum) + " of " + this.maximum + " messages.";
+		}
+		var fakeDownload = function(){
+			dojo.byId('fetchMail').style.visibility='visible';
+			numMails = Math.floor(Math.random()*10)+1;
+			dijit.byId('fakeFetch').update({ maximum: numMails, progress:0 });
+			dojo.fadeIn({ node: 'fetchMail', duration:300 }).play();
+			for (var i=0; i<=numMails; i++){
+				setTimeout("updateFetchStatus("+i+")",((i+1)*(Math.floor(Math.random()*100)+400)));
+			}
+		}
+		// fake sending dialog progress bar
+		var stopSendBar = function(){
+			dijit.byId('fakeSend').update({indeterminate: false});
+			dijit.byId('sendDialog').hide();
+			tabs.selectedChildWidget.onClose = function(){return true;};  // don want confirm message
+			tabs.closeChild(tabs.selectedChildWidget);
+		}
+
+		var showSendBar = function(){
+			dijit.byId('fakeSend').update({ indeterminate: true });
+			dijit.byId('sendDialog').show();
+			setTimeout("stopSendBar()", 3000);
+		}
+
+	</script>
+</head>
+<body class="soria">
+	<script type="text/xml" dojoType="dojox.xml.Script">
+		<ui xmlns:dojo="dojo" xmlns="html">
+			<dojo:data.ItemFileWriteStore jsId="mailStore" url="mail/mail.json"/>
+		</ui>
+	</script>
+
+	<!-- Inline declaration of a table widget (thanks Alex!) -->
+	<script type="text/xml" dojoType="dojox.xml.Script">
+		<ui xmlns:dijit="dijit" xmlns:html="html" xmlns:dojo="dojo" xmlns="html">
+
+		<table dojoType="dijit.Declaration"
+			widgetClass="demo.Table" class="demoTable"
+			defaults="{ store: null, query: { query: { type: 'message' } }, columns: [ { name: 'From', attribute: 'sender' }, { name: 'Subject', attribute: 'label' }, { name: 'Sent on', attribute: 'sent',
+			format: function(v){ return dojo.date.locale.format(dojo.date.stamp.fromISOString(v), {selector: 'date'}); }
+			} ] }">
+			<thead dojoAttachPoint="head">
+				<tr dojoAttachPoint="headRow"></tr>
+			</thead>
+			<tbody dojoAttachPoint="body">
+				<tr dojoAttachPoint="row"></tr>
+			</tbody>
+
+			<html:script type="dojo/method">
+			<![CDATA[
+				dojo.forEach(this.columns, function(item, idx){
+					var icn = item.className||"";
+					// add a header for each column
+					var tth = document.createElement("th");
+					tth.innerHTML = "<span class='arrowNode'></span>"+ item.name;
+					tth.className = icn;
+					dojo.connect(tth, "onclick", dojo.hitch(this, "onSort", idx));
+					this.headRow.appendChild(tth);
+
+					// and fill in the column cell in the template row
+					this.row.appendChild(document.createElement("td"));
+					this.row.lastChild.className = icn;
+				}, this);
+				this.runQuery();
+				]]>
+			</html:script>
+			<html:script type="dojo/method" event="onSort" args="index">
+			<![CDATA[
+				var ca = this.columns[index].attribute;
+				var qs = this.query.sort;
+				// clobber an existing sort arrow
+				dojo.query("> th", this.headRow).removeClass("arrowUp").removeClass("arrowDown");
+				if(qs && qs[0].attribute == ca){
+					qs[0].descending = !qs[0].descending;
+				}else{
+					this.query.sort = [{
+						attribute: ca,
+						descending: false
+					}];
+				}
+				var th = dojo.query("> th", this.headRow)[index];
+				dojo.addClass(th, (this.query.sort[0].descending ? "arrowUp" : "arrowDown"));
+				this.runQuery();
+				]]>
+			</html:script>
+			<html:script type="dojo/method" event="runQuery">
+			<![CDATA[
+				this.query.onBegin = dojo.hitch(this, function(){ dojo.query("tr", this.body).orphan(); });
+				this.query.onItem = dojo.hitch(this, "onItem");
+				this.query.onComplete = dojo.hitch(this, function(){
+					dojo.query("tr:nth-child(odd)", this.body).addClass("oddRow");
+					dojo.query("tr:nth-child(even)", this.body).removeClass("oddRow");
+				});
+				this.store.fetch(this.query);
+				]]>
+			</html:script>
+			<html:script type="dojo/method" event="onItem" args="item">
+			<![CDATA[
+				var tr = this.row.cloneNode(true);
+				dojo.query("td", tr).forEach(function(n, i, a){
+					var tc = this.columns[i];
+					var tv = this.store.getValue(item, tc.attribute)||"";
+					if(tc.format){ tv = tc.format(tv, item, this.store); }
+					n.innerHTML = tv;
+				}, this);
+				this.body.appendChild(tr);
+				dojo.connect(tr, "onclick", this, function(){ this.onClick(item); });
+				]]>
+			</html:script>
+			<html:script type="dojo/method" event="onClick" args="item">
+			<![CDATA[
+				// user should override
+				console.log("click on item " + item);
+			]]>
+			</html:script>
+		</table>
+		</ui>
+	</script>
+
+	<script type="text/xml" dojoType="dojox.xml.Script">
+	<ui xmlns:dijit="dijit" xmlns:html="html" xmlns:dojo="dojo" xmlns="html">
+	<!-- Inline declaration for programmatically created "New Message" tabs -->
+	<dijit:Declaration widgetClass="mail.NewMessage">
+		<dijit:layout.LayoutContainer dojoAttachPoint="container" title="Composing..." closeable="true">
+			<dijit:layout.LayoutContainer layoutAlign="top" style="overflow: visible; z-index: 10; color:#666; ">
+				<table width="100%">
+				<tbody>
+					<tr style="padding-top:5px;">
+						<td style="padding-left:20px; padding-right: 8px; text-align:right;"><label for="${id}_to">To:</label></td>
+						<td width="100%">
+							<dijit:form.ComboBox id="${id}_to" value=" " hasDownArrow="false">
+								<option></option>
+								<option>adam at yahoo.com</option>
+								<option>barry at yahoo.com</option>
+								<option>bob at yahoo.com</option>
+								<option>cal at yahoo.com</option>
+								<option>chris at yahoo.com</option>
+								<option>courtney at yahoo.com</option>
+							</dijit:form.ComboBox>
+						</td>
+					</tr>
+					<tr>
+						<td style="padding-left: 20px; padding-right:8px; text-align:right;"><label for="${id}_subject">Subject:</label></td>
+						<td width="100%">
+							<dijit:form.ComboBox id="${id}_subject" value=" " hasDownArrow="false">
+								<option></option>
+								<option>progress meeting</option>
+								<option>reports</option>
+								<option>lunch</option>
+								<option>vacation</option>
+								<option>status meeting</option>
+							</dijit:form.ComboBox>
+						</td>
+					</tr>
+				</tbody>
+				</table>
+				<hr noshade="true" size="1"/>
+			</dijit:layout.LayoutContainer>
+
+			<!-- new messase part -->
+			<dijit:layout.LayoutContainer  dojoType="dijit.layout.LayoutContainer" layoutAlign="client">
+				<dijit:layout.ContentPane href="mail/newMail.xml"/>
+			</dijit:layout.LayoutContainer>
+
+			<dijit:layout.LayoutContainer  dojoType="dijit.layout.LayoutContainer" layoutAlign="bottom" align="center">
+				<dijit:form.Button iconClass="mailIconOk" label="Send">
+					<html:script type="dojo/method" event="onClick">
+						var toField = dojo.byId("${id}_to");
+						if(toField.value == ""){
+							alert("Please enter a recipient address");
+						}else{
+							showSendBar();
+						}
+					</html:script>
+				</dijit:form.Button>
+				<dijit:form.Button iconClass="mailIconCancel" label="Cancel">
+					<html:script type="dojo/method" event="onClick">
+						tabs.closeChild(tabs.selectedChildWidget);
+					</html:script>
+				</dijit:form.Button>
+			</dijit:layout.LayoutContainer>
+
+		</dijit:layout.LayoutContainer>
+	</dijit:Declaration>
+
+	<dijit:layout.LayoutContainer id="main">
+		<!-- toolbar with new mail button, etc. -->
+		<dijit:Toolbar dojoType="dijit.Toolbar" layoutAlign="top" style="height:25px;">
+			<dijit:form.ComboButton id="getMail"
+				iconClass="mailIconGetMail" optionsTitle="Mail Source Options">
+				<html:script type="dojo/method" event="onClick">
+					 fakeDownload();
+				</html:script>
+				<span>Get Mail</span>
+				<dijit:Menu dojoType="dijit.Menu">
+					<dijit:MenuItem iconClass="mailIconGetMail">Yahoo</dijit:MenuItem>
+					<dijit:MenuItem  iconClass="mailIconGetMail">GMail</dijit:MenuItem>
+				</dijit:Menu>
+			</dijit:form.ComboButton>
+			<dijit:Tooltip connectId="getMail">Click to download new mail.</dijit:Tooltip>
+
+			<dijit:form.Button
+				id="newMsg"
+				iconClass="mailIconNewMessage"
+				label="New Message">
+				<html:script type="dojo/method" event="onClick">
+					/* make a new tab for composing the message */
+					var newTab = new mail.NewMessage({id: "new"+paneId  }).container;
+					dojo.mixin(newTab,
+						{
+							title: "New Message #" + paneId++,
+							closable: true,
+							onClose: testClose
+						}
+					);
+					tabs.addChild(newTab);
+					tabs.selectChild(newTab);
+				</html:script>
+			</dijit:form.Button>
+			<dijit:Tooltip dojoType="dijit.Tooltip" connectId="newMsg">Click to compose new message.</dijit:Tooltip>
+
+			<dijit:form.Button label="Options" iconClass="mailIconOptions">
+				<html:script type="dojo/method" event="onClick">
+								dijit.byId('optionsDialog').show();
+				</html:script>
+			</dijit:form.Button>
+			<dijit:Tooltip connectId="options">Set various options</dijit:Tooltip>
+		</dijit:Toolbar>
+
+		<dijit:layout.TabContainer dojoType="dijit.layout.TabContainer" id="tabs" jsId="tabs" layoutAlign="client">
+			<!-- main section with tree, table, and preview -->
+			<dijit:layout.SplitContainer
+				orientation="horizontal"
+				sizerWidth="5"
+				activeSizing="0"
+				title="Inbox"
+			>
+				<dijit:layout.AccordionContainer sizeMin="20" sizeShare="20">
+					<dijit:layout.AccordionPane title="Folders">
+						<!--<span id="treePlaceHolder"
+								style="background-color:#F00; color:#FFF;">
+								Loading tree widget...
+						</span>-->
+						<dijit:Tree id="mytree" store="mailStore"
+							labelAttr="label" childrenAttr="folders" query="{type:'folder'}" label="Folders">
+							<html:script type="dojo/method" event="onClick" args="item">
+								if(!item){
+									return;	// top level node in tree doesn't correspond to any item
+								}
+								/* filter the message list to messages in this folder */
+								table.query.query = {
+									type: "message",
+									folder: mailStore.getValue(item, "id")
+								};
+								table.runQuery();
+							</html:script>
+							<html:script type="dojo/method" event="getIconClass" args="item">
+							<![CDATA[
+								return (item && mailStore.getValue(item, "icon")) || "mailIconFolderDocuments";
+							]]>
+							</html:script>
+						</dijit:Tree>
+					</dijit:layout.AccordionPane>
+					<dijit:layout.AccordionPane title="Address Book">
+						<span dojoType="demo.Table" store="mailStore"
+							query="{ query: { type: 'address' }, columns: [ {name: 'User name', attribute: 'label'} ], sort: [ { attribute: 'label' } ]  }"
+							id="addresses" style="width: 100%" >
+							<html:script type="dojo/method" event="preamble">
+								this.query = { type: "address" };
+								this.columns = [
+									{
+										name: "Name",
+										attribute: "label"
+									}
+								];
+							</html:script>
+							<html:script type="dojo/method" event="onClick" args="item">
+								table.query.query.sender = mailStore.getValue(item, "sender");
+								delete table.query.query.folder;
+								table.runQuery();
+							</html:script>
+						</span>
+					</dijit:layout.AccordionPane>
+				</dijit:layout.AccordionContainer>
+
+				<dijit:layout.SplitContainer
+					id="rightPane"
+					orientation="vertical"
+					sizerWidth="5"
+					activeSizing="0"
+					sizeMin="50" sizeShare="85"
+				>
+					<dijit:layout.ContentPane id="listPane" sizeMin="20" sizeShare="20">
+						<span dojoType="demo.Table" store="mailStore"
+							query="{ query: { type: 'message' }, sort: [ { attribute: 'label' } ]  }"
+							id="foo" jsId="table" style="width: 100%">
+							<html:script type="dojo/method" event="onClick" args="item">
+							var sender = this.store.getValue(item, "sender");
+								var subject = this.store.getValue(item, "label");
+								var sent = dojo.date.locale.format(
+									dojo.date.stamp.fromISOString(this.store.getValue(item, "sent")),
+									{formatLength: "long", selector: "date"});
+								var text = this.store.getValue(item, "text");
+
+								var messageInner = "<span class='messageHeader'>From: "  + sender + "<br>" +
+																	"Subject: "+ subject + "<br>" +
+									"Date: " + sent + "<br><br></span>" +
+									text;
+								dijit.byId("message").setContent(messageInner);
+							</html:script>
+						</span>
+					</dijit:layout.ContentPane>
+					<dijit:layout.ContentPane id="message" sizeMin="20" sizeShare="80">
+						<p>
+						This is a simple application mockup showing some of the dojo widgets:
+						</p>
+						<ul>
+						  <li>layout widgets: SplitContainer, LayoutContainer, AccordionContainer</li>
+						  <li>TooltipDialog, Tooltip</li>
+						  <li>Tree</li>
+						  <li>form widgets: Button, DropDownButton, ComboButton, FilteringSelect, ComboBox</li>
+						  <li>Editor</li>
+						</ul>
+						<p>
+						The message list above originally contains all the messages, but you can filter it by clicking on items in the left Accordion. Then click on the messages in the above list to display them. There's no server running, so the app is just a facade and it doesn't really do anything.
+						<!-- TODO: delete button (we can delete since we are using ItemFileWriteStore -->
+						</p>
+						<p>
+						<span style="font-family: 'Comic Sans MS',Textile,cursive; color: blue; font-style: italic;">-- Bill</span>
+						</p>
+					</dijit:layout.ContentPane>
+				</dijit:layout.SplitContainer><!-- end of vertical SplitContainer -->
+			</dijit:layout.SplitContainer><!-- end of horizontal SplitContainer -->
+		</dijit:layout.TabContainer><!-- end of TabContainer -->
+
+		<dijit:layout.ContentPane layoutAlign="bottom" id="footer" align="left">
+			<span style="float:right;">DojoMail v1.0 (demo only)</span>
+			<div id="fetchMail" style="opacity:0;visibility:hidden">
+				<dijit:ProgressBar annotate="true" id="fakeFetch" style="height:15px; width:275px;" indeterminate="true" report="fakeReport"/>
+			</div>
+		</dijit:layout.ContentPane>
+	</dijit:layout.LayoutContainer> <!-- end of Layoutcontainer -->
+
+		<dijit:Dialog id="optionsDialog" title="Options:">
+				<table>
+				<tbody>
+					<tr>
+					<td style="text-align:right;">
+						<label for="option1">Transport type:</label>
+					</td>
+					<td>
+						<dijit:form.FilteringSelect id="option1" value=" ">
+									<option value="pop3">POP3</option>
+									<option value="imap">IMAP</option>
+						</dijit:form.FilteringSelect>
+					</td>
+					</tr>
+					<tr>
+					<td style="text-align:right;">
+						<label for="option2">Server:</label>
+					</td>
+					<td>
+						<dijit:form.TextBox id="option2" type="text"/>
+					</td>
+					</tr>
+
+					<tr>
+					<td style="text-align:right;">
+						<dijit:form.CheckBox type="checkbox" id="fooCB"/>
+					</td>
+					<td>
+						<label for="fooCB">Leave messages on Server</label>
+					</td>
+					</tr>
+					<tr>
+					<td style="text-align:right;">
+						<dijit:form.CheckBox type="checkbox" id="fooCB2"/>
+					</td>
+					<td>
+						<label for="fooCB2">Remember Password</label>
+					</td>
+					</tr>
+
+					<tr>
+					<td colSpan="2" style="text-align:center;">
+					<dijit:form.Button iconClass="mailIconOk" onclick="dijit.byId('optionsDialog').hide();">OK</dijit:form.Button>
+					<dijit:form.Button iconClass="mailIconCancel" onclick="dijit.byId('optionsDialog').hide();">Abort</dijit:form.Button>
+					</td>
+					</tr>
+				</tbody>
+				</table>
+		</dijit:Dialog>
+
+		<dijit:Dialog dojoType="dijit.Dialog" id="sendDialog" title="Sending Mail">
+			<dijit:ProgressBar id="fakeSend" style="height:15px; width:175px;" indeterminate="true" ></dijit:ProgressBar>
+		</dijit:Dialog>
+	</ui>
+	</script>
+</body>
+</html>
diff --git a/dojox/xml/tests/mail/mail.css b/dojox/xml/tests/mail/mail.css
new file mode 100644
index 0000000..9625925
--- /dev/null
+++ b/dojox/xml/tests/mail/mail.css
@@ -0,0 +1,266 @@
+html, body, #main{	
+	width: 100%;	/* make the body expand to fill the visible window */
+	height: 100%;
+	overflow: hidden;	/* erase window level scrollbars */
+	padding: 0 0 0 0;
+	margin: 0 0 0 0;
+	font: 10pt Arial,Myriad,Tahoma,Verdana,sans-serif;
+}
+
+#banner, #footer {
+background-color: #b7cdee; 
+color: #333;
+padding:3px; 
+}
+#banner { text-align:right; } 
+
+/* list of messages
+TODO: If i add the rules below as a plain tr/td it seems to mess up accordion, tree, etc. ???
+*/
+#listPane tr:hover, #listPane td:hover, .dijitTreeContent:hover {
+	background-color: #b7cdee;
+	color: #333;
+	cursor: pointer;
+}
+#listPane tr, #listPane td { cursor: pointer; }
+
+th {
+	background-color: #4f8ce5; 
+	color: #fff; 
+	font-weight:: bold !important;
+	margin:0;
+	padding:3px; 
+	background-image:url('../../themes/soria/images/gradientTopBg.png');
+	background-position:0px -1px; 
+}
+
+th .arrowNode { position:relative; right:2px; 
+	width:16px;
+	height:16px;
+} 
+th.arrowUp .arrowNode {
+	padding-right: 16px;
+	background:transparent url("../../themes/soria/images/arrows.png") no-repeat;
+	background-position:-32px 0px; 
+}
+
+th.arrowDown .arrowNode {
+	padding-right: 16px;
+	background:transparent url("../../themes/soria/images/arrows.png") no-repeat;
+	background-position:0px 0px; 
+}
+
+.demoTable td { padding:3px; } 
+.demoTable {
+	border-spacing:0; 
+	padding:0; margin:0; 
+	width:98%;
+	
+}
+.oddRow {
+	background-color: #f2f5f9;
+}
+
+#message {
+	padding: 8px;
+}
+
+/* Stuff for new messages */
+
+.subject {
+	background: gray;
+	width: 100%;
+	padding-top: 5px;
+	padding-bottom: 10px;
+}
+
+.message {
+	border: black 2px;
+}
+.messageHeader {
+	font:12pt Arial,sans-serif;
+	font-weight:bold;
+	color:#333; 
+}
+body .dojoSplitPane {
+	background: #ededff;
+	overflow: auto;
+}
+
+/* Icons */
+
+.mailIconCancel,
+.mailIconOptions,
+.mailIconFolderDocuments,
+.mailIconFolderInbox,
+.mailIconFolderSent,
+.mailIconGetMail,
+.mailIconNewMessage,
+.mailIconMailbox,
+.mailIconOk,
+.mailIconTrashcanFull {
+	background-image: url('icons.png'); /* mail icons sprite image */
+	background-repeat: no-repeat; 
+	width: 16px;
+	height: 16px;
+	text-align: center;
+	padding-right:4px; 
+}
+
+.dj_ie6 .mailIconCancel,
+.dj_ie6 .mailIconOptions,
+.dj_ie6 .mailIconFolderDocuments,
+.dj_ie6 .mailIconFolderInbox,
+.dj_ie6 .mailIconFolderSent,
+.dj_ie6 .mailIconGetMail,
+.dj_ie6 .mailIconNewMessage,
+.dj_ie6 .mailIconMailbox,
+.dj_ie6 .mailIconOk,
+.dj_ie6 .mailIconTrashcanFull {
+	background-image: url('icons.gif');
+}
+
+
+.mailIconCancel { background-position: 0px; }
+.mailIconOptions { background-position: -22px; }
+.mailIconFolderDocuments { background-position: -44px; }
+.mailIconFolderInbox { background-position: -66px; }
+.mailIconFolderSent { background-position: -88px; }
+.mailIconGetMail { background-position: -110px; }
+.mailIconNewMessage { background-position: -132px; }
+.mailIconMailbox { background-position: -154px; }
+.mailIconOk { background-position: -176px; }
+.mailIconTrashcanFull { background-position: -198px; }
+html, body, #main{	
+	width: 100%;	/* make the body expand to fill the visible window */
+	height: 100%;
+	overflow: hidden;	/* erase window level scrollbars */
+	padding: 0 0 0 0;
+	margin: 0 0 0 0;
+	font: 10pt Arial,Myriad,Tahoma,Verdana,sans-serif;
+}
+
+#banner, #footer {
+background-color: #b7cdee; 
+color: #333;
+padding:3px; 
+}
+#banner { text-align:right; } 
+
+/* list of messages
+TODO: If i add the rules below as a plain tr/td it seems to mess up accordion, tree, etc. ???
+*/
+#listPane tr:hover, #listPane td:hover, .dijitTreeContent:hover {
+	background-color: #b7cdee;
+	color: #333;
+	cursor: pointer;
+}
+#listPane tr, #listPane td { cursor: pointer; }
+
+th {
+	background-color: #4f8ce5; 
+	color: #fff; 
+	font-weight:: bold !important;
+	margin:0;
+	padding:3px; 
+	background-image:url('../../themes/soria/images/gradientTopBg.png');
+	background-position:0px -1px; 
+}
+
+th .arrowNode { position:relative; right:2px; 
+	width:16px;
+	height:16px;
+} 
+th.arrowUp .arrowNode {
+	padding-right: 16px;
+	background:transparent url("../../themes/soria/images/arrows.png") no-repeat;
+	background-position:-32px 0px; 
+}
+
+th.arrowDown .arrowNode {
+	padding-right: 16px;
+	background:transparent url("../../themes/soria/images/arrows.png") no-repeat;
+	background-position:0px 0px; 
+}
+
+.demoTable td { padding:3px; } 
+.demoTable {
+	border-spacing:0; 
+	padding:0; margin:0; 
+	width:98%;
+	
+}
+.oddRow {
+	background-color: #f2f5f9;
+}
+
+#message {
+	padding: 8px;
+}
+
+/* Stuff for new messages */
+
+.subject {
+	background: gray;
+	width: 100%;
+	padding-top: 5px;
+	padding-bottom: 10px;
+}
+
+.message {
+	border: black 2px;
+}
+.messageHeader {
+	font:12pt Arial,sans-serif;
+	font-weight:bold;
+	color:#333; 
+}
+body .dojoSplitPane {
+	background: #ededff;
+	overflow: auto;
+}
+
+/* Icons */
+
+.mailIconCancel,
+.mailIconOptions,
+.mailIconFolderDocuments,
+.mailIconFolderInbox,
+.mailIconFolderSent,
+.mailIconGetMail,
+.mailIconNewMessage,
+.mailIconMailbox,
+.mailIconOk,
+.mailIconTrashcanFull {
+	background-image: url('icons.png'); /* mail icons sprite image */
+	background-repeat: no-repeat; 
+	width: 16px;
+	height: 16px;
+	text-align: center;
+	padding-right:4px; 
+}
+
+.dj_ie6 .mailIconCancel,
+.dj_ie6 .mailIconOptions,
+.dj_ie6 .mailIconFolderDocuments,
+.dj_ie6 .mailIconFolderInbox,
+.dj_ie6 .mailIconFolderSent,
+.dj_ie6 .mailIconGetMail,
+.dj_ie6 .mailIconNewMessage,
+.dj_ie6 .mailIconMailbox,
+.dj_ie6 .mailIconOk,
+.dj_ie6 .mailIconTrashcanFull {
+	background-image: url('icons.gif');
+}
+
+
+.mailIconCancel { background-position: 0px; }
+.mailIconOptions { background-position: -22px; }
+.mailIconFolderDocuments { background-position: -44px; }
+.mailIconFolderInbox { background-position: -66px; }
+.mailIconFolderSent { background-position: -88px; }
+.mailIconGetMail { background-position: -110px; }
+.mailIconNewMessage { background-position: -132px; }
+.mailIconMailbox { background-position: -154px; }
+.mailIconOk { background-position: -176px; }
+.mailIconTrashcanFull { background-position: -198px; }
diff --git a/dojox/xml/tests/mail/mail.json b/dojox/xml/tests/mail/mail.json
new file mode 100644
index 0000000..779cecf
--- /dev/null
+++ b/dojox/xml/tests/mail/mail.json
@@ -0,0 +1,76 @@
+{ 
+	"identifier": "id",
+	"label": "label",
+	"items": [
+
+		// Hierarchy of folders
+		{ "type": "folder", "id": "inbox", "label":"Inbox", "icon":"mailIconFolderInbox" },
+		{ "type": "folder", "id": "deleted", "label":"Trash", "icon":"mailIconTrashcanFull" },
+		{ "type": "folder", "id": "save", "label":"Save",  "folders":[
+			{ "id": "work", "label":"stuff for work"},
+			{ "id": "fun", "label":"stuff for fun"}
+		]},
+
+		// Address book (list of people that have sent me messages)
+		{ "type": "address", "id": "adam", "label": "Adam Arlen" },
+		{ "type": "address", "id": "bob", "label": "Bob Baxter" },
+		{ "type": "address", "id": "carrie", "label": "Carrie Crow" },
+
+		// Flat list of messages (each message lists it"s folder)
+
+		{ "type": "message", "id": "node1.1", "folder": "inbox", "label": "today's meeting", "sender": "Adam Arlen", "sent": "2005-12-19",
+			"text": "Today's meeting is cancelled.<br>Let's do it tomorrow instead.<br><br>Adam" },
+		{ "type": "message", "id": "node1.2", "folder": "inbox", "label": "remaining work", "sender": "Bob Baxter", "sent": "2005-12-18",
+			"text":
+				"<p>Hey, we need to talk about who's gonna do all the left over work.  Pick a day you want to meet: <div dojoType='dijit.Calendar'></div></p>"
+		},
+		{ "type": "message", "id": "node1.3", "folder": "inbox", "label": "Hey, look!", "sender": "Carrey Crown", "sent": "2005-12-17", "text":
+				"This is our new simple mail app. What do you think? <br><br>You can navigate around this demo with arrows and tabs ... <br><br>Regards,<br>Carrey"
+		},
+		{ "type": "message", "id": "node1.4", "folder": "inbox", "label": "paint", "sender": "David Davis", "sent": "2005-12-16", "text":
+			"<p>what color is good for the new office?</p><div dojoType='dijit.ColorPalette'></div><p>Let me know soon</p>"
+		},
+		{ "type": "message", "id": "node2.1", "folder": "deleted", "label": "today's meeting", "sender": "Madam Marlen", "sent": "2005-12-19",
+			"text": "Today's meeting is cancelled.<br>Let's do it tomorrow instead.<br><br>Madam" },
+		{ "type": "message", "id": "node2.2", "folder": "deleted", "label": "congratulations", "sender": "Rob Raxter", "sent": "2005-12-18", "text": " Good job on that project! " },
+		{ "type": "message", "id": "node2.3", "folder": "deleted", "label": "schedule", "sender": "Carrie Crow", "sent": "2005-12-17", "text": " Are we still on schedule?<br>The deadline is next Friday. " },
+		{ "type": "message", "id": "node2.4", "folder": "deleted", "label": "paint", "sender": "Daniel Dooey", "sent": "2005-12-16", "text":
+			"<p>what color is good for the new office?</p><div dojoType='dijit.ColorPalette'></div><p>Let me know soon</p>"
+		},
+		{ "type": "message", "id": "node3.1", "folder": "work", "label": "today's meeting", "sender": "Bob Baxter", "sent": "2005-12-19",
+			"text": "Today's meeting is cancelled.<br>Unnecessary.<br><br>Bob" },
+		{ "type": "message", "id": "node3.2", "folder": "work", "label": "remaining work", "sender": "Bob Baxter", "sent": "2005-12-18", "text": " Are we still on schedule?<br>The deadline is next Friday. " },
+		{ "type": "message", "id": "node3.3", "folder": "work", "label": "lunch", "sender": "Bob Baxter", "sent": "2005-12-17", "text":
+				"Where do you want to go for lunch?<br><br><ul><li>Fresh Choice<li>Starbucks<li>Dominos</ul><br><br>Let me know..."
+		},
+		{ "type": "message", "id": "node3.4", "folder": "work", "label": "paint", "sender": "Bob Baxter", "sent": "2005-12-16", "text":
+			"<p>what color is good for the new office?</p><div dojoType='dijit.ColorPalette'></div><p>Let me know soon</p>"
+		},
+		{ "type": "message", "id": "node4.1", "folder": "fun", "label": "today's meeting", "sender": "Jack Jackson", "sent": "2005-12-19",
+			"text": "Today's meeting is cancelled.<br>Let's do it friday instead.<br><br>Joe" },
+		{ "type": "message", "id": "node4.2", "folder": "fun", "label": "remaining work", "sender": "Jack Jackson", "sent": "2005-12-18",
+			"text":
+				"<p>Hey, we need to talk about who's gonna do all the left over work.  Pick a day you want to meet: <div dojoType='dijit.Calendar'></div></p>"
+		},
+		{ "type": "message", "id": "node4.3", "folder": "fun", "label": "lunch", "sender": "Jack Jackson", "sent": "2005-12-17", "text":
+				"Where do you want to go for lunch?<br><br><ul><li>Indian<li>Mexican<li>Chinese<li>Japanese<li>Pizza</ul><br><br>Let me know..."
+		},
+		{ "type": "message", "id": "node4.4", "folder": "fun", "label": "paint", "sender": "Jack Jackson", "sent": "2005-12-16", "text":
+			"<p>what color is good for the new office?</p><div dojoType='dijit.ColorPalette'></div><p>Let me know soon</p>"
+		},
+
+		{ "type": "message", "id": "node5.1", "folder": "deleted", "label": "today's meeting", "sender": "Jill Jones", "sent": "2005-12-19",
+			"text": "Today's meeting is cancelled.<br>Let's do it thursday instead.<br><br>Jill" },
+		{ "type": "message", "id": "node5.2", "folder": "deleted", "label": "remaining work", "sender": "Jill Jones", "sent": "2005-12-18",
+			"text":
+				"<p>Hey, we need to talk about who's gonna do all the left over work.  Pick a day you want to meet: <div dojoType='dijit.Calendar'></div></p>"
+		},
+		{ "type": "message", "id": "node5.3", "folder": "deleted", "label": "lunch", "sender": "Jill Jones", "sent": "2005-12-17", "text":
+				"Where do you want to go for lunch?<br><br><ul><li>McDonalds<li>Burger King<li>KFC</ul><br><br>Let me know..."
+		},
+		{ "type": "message", "id": "node5.4", "folder": "deleted", "label": "paint", "sender": "Jill Jones", "sent": "2005-12-16", "text":
+			"<p>what color is good for the new office?</p><div dojoType='dijit.ColorPalette'></div><p>Let me know soon</p>"
+		}
+	]
+}
+
diff --git a/dojox/xml/tests/mail/newMail.xml b/dojox/xml/tests/mail/newMail.xml
new file mode 100644
index 0000000..0175a8e
--- /dev/null
+++ b/dojox/xml/tests/mail/newMail.xml
@@ -0,0 +1,16 @@
+<xml>
+<dijit:Editor dojoType="dijit.Editor" style="overflow:auto"
+	extraPlugins="[{name:'dijit._editor.plugins.LinkDialog'}]"
+>
+<i> This is just a sample message. There is email-address auto-complete in the to: field.
+<br/><br/> give it a whirl.
+</i>
+</dijit:Editor>
+<dijit:Editor dojoType="dijit.Editor" style="overflow:auto"
+	extraPlugins="[{name:'dijit._editor.plugins.LinkDialog'}]"
+>
+<i> This is just a sample message. There is email-address auto-complete in the to: field.
+<br/><br/> give it a whirl.
+</i>
+</dijit:Editor>
+</xml>
diff --git a/dojox/xml/tests/module.js b/dojox/xml/tests/module.js
new file mode 100644
index 0000000..b61b228
--- /dev/null
+++ b/dojox/xml/tests/module.js
@@ -0,0 +1,8 @@
+dojo.provide("dojox.xml.tests.module");
+
+try{
+	dojo.require("dojox.xml.tests.parser");
+	//dojo.require("dojox.xml.tests.widgetParser");
+}catch(e){
+	doh.debug(e);
+}
diff --git a/dojox/xml/tests/myPage.xml b/dojox/xml/tests/myPage.xml
new file mode 100644
index 0000000..5e5cd72
--- /dev/null
+++ b/dojox/xml/tests/myPage.xml
@@ -0,0 +1,3 @@
+<ui xmlns="dijit">
+	<form.Button label="a button from another file" onclick="alert('clicked');"/>
+</ui>
\ No newline at end of file
diff --git a/dojox/xml/tests/parser.js b/dojox/xml/tests/parser.js
new file mode 100755
index 0000000..5017adb
--- /dev/null
+++ b/dojox/xml/tests/parser.js
@@ -0,0 +1,147 @@
+dojo.provide("dojox.xml.tests.parser");
+dojo.require("dojox.xml.parser");
+
+tests.register("dojox.xml.tests.parser", 
+	[
+		function testParse(t){
+			var document = dojox.xml.parser.parse();
+			t.assertTrue(document !== null);
+		},
+		function testParseFromText(t){
+			var simpleXml = "<parentNode><childNode><grandchildNode/></childNode><childNode/></parentNode>";
+			var document = dojox.xml.parser.parse(simpleXml, "text/xml");
+			
+			var parent = document.firstChild;
+			t.assertTrue(parent !== null);
+			t.assertTrue(parent.tagName === "parentNode");
+			t.assertTrue(parent.childNodes.length == 2);
+			
+			var firstChild = parent.firstChild;
+			t.assertTrue(firstChild !== null);
+			t.assertTrue(firstChild.tagName === "childNode");
+			t.assertTrue(firstChild.childNodes.length == 1);
+			
+			var secondChild = firstChild.nextSibling;
+			t.assertTrue(secondChild !== null);
+			t.assertTrue(secondChild.tagName === "childNode");
+
+			var grandChild = firstChild.firstChild;
+			t.assertTrue(grandChild !== null);
+			t.assertTrue(grandChild.tagName === "grandchildNode");
+
+		},
+		function testParseEmptyString(t){
+			var simpleXml = "";
+			var document = dojox.xml.parser.parse(simpleXml, "text/xml");
+			
+			t.assertTrue(typeof document != "undefined");
+
+			var parent = document.firstChild;
+			t.assertTrue(parent === null);
+		},
+		function testParseEmpty(t){
+			var simpleXml;
+			var document = dojox.xml.parser.parse();
+			
+			t.assertTrue(typeof document != "undefined");
+
+			var parent = document.firstChild;
+			t.assertTrue(parent === null);
+		},
+		function testReadTextContent(t){
+			var text = "This is a bunch of child text on the node";
+			var simpleXml = "<parentNode>" + text + "</parentNode>";
+			var document = dojox.xml.parser.parse(simpleXml, "text/xml");
+            
+			var topNode = document.firstChild;
+			t.assertTrue(topNode !== null);
+			t.assertTrue(topNode.tagName === "parentNode");
+			t.assertTrue(text === dojox.xml.parser.textContent(topNode));
+			dojo.destroy(topNode);
+			t.assertTrue(document.firstChild === null);
+		},
+		function testSetTextContent(t){
+			var text = "This is a bunch of child text on the node";
+			var text2 = "This is the new text";
+			var simpleXml = "<parentNode>" + text + "</parentNode>";
+			var document = dojox.xml.parser.parse(simpleXml, "text/xml");
+            
+			var topNode = document.firstChild;
+			t.assertTrue(topNode !== null);
+			t.assertTrue(topNode.tagName === "parentNode");
+			t.assertTrue(text === dojox.xml.parser.textContent(topNode));
+			dojox.xml.parser.textContent(topNode, text2);
+			t.assertTrue(text2 === dojox.xml.parser.textContent(topNode));
+			dojo.destroy(topNode);
+			t.assertTrue(document.firstChild === null);
+
+		},
+		function testReplaceChildrenArray(t){
+			var simpleXml1 = "<parentNode><child1/><child2/><child3/></parentNode>";
+			var simpleXml2 = "<parentNode><child4/><child5/><child6/><child7/></parentNode>";
+			var doc1 = dojox.xml.parser.parse(simpleXml1, "text/xml");
+			var doc2 = dojox.xml.parser.parse(simpleXml2, "text/xml");
+            
+			var topNode1 = doc1.firstChild;
+			var topNode2 = doc2.firstChild;
+			t.assertTrue(topNode1 !== null);
+			t.assertTrue(topNode1.tagName === "parentNode");
+			t.assertTrue(topNode2 !== null);
+			t.assertTrue(topNode2.tagName === "parentNode");
+			dojox.xml.parser.removeChildren(topNode1);
+			var newChildren=[];
+			for(var i=0;i<topNode2.childNodes.length;i++){
+				newChildren.push(topNode2.childNodes[i]);
+			}
+			dojox.xml.parser.removeChildren(topNode2);
+			dojox.xml.parser.replaceChildren(topNode1,newChildren);
+			t.assertEqual(4, topNode1.childNodes.length);
+			t.assertEqual("child4", topNode1.firstChild.tagName);
+			t.assertEqual("child7", topNode1.lastChild.tagName);
+
+		},
+		function testReplaceChildrenSingle(t){
+			var simpleXml1 = "<parentNode><child1/><child2/><child3/></parentNode>";
+			var simpleXml2 = "<parentNode><child4/></parentNode>";
+			var doc1 = dojox.xml.parser.parse(simpleXml1, "text/xml");
+			var doc2 = dojox.xml.parser.parse(simpleXml2, "text/xml");
+            
+			var topNode1 = doc1.firstChild;
+			var topNode2 = doc2.firstChild;
+			t.assertTrue(topNode1 !== null);
+			t.assertTrue(topNode1.tagName === "parentNode");
+			t.assertTrue(topNode2 !== null);
+			t.assertTrue(topNode2.tagName === "parentNode");
+			dojox.xml.parser.removeChildren(topNode1);
+			
+			var newChildren = topNode2.firstChild;
+			dojox.xml.parser.removeChildren(topNode2);
+			dojox.xml.parser.replaceChildren(topNode1,newChildren);
+			t.assertTrue(topNode1.childNodes.length === 1);
+			t.assertTrue(topNode1.firstChild.tagName === "child4");
+			t.assertTrue(topNode1.lastChild.tagName === "child4");
+		},
+		function testRemoveChildren(t){
+			var simpleXml1 = "<parentNode><child1/><child2/><child3/></parentNode>";
+			var doc1 = dojox.xml.parser.parse(simpleXml1, "text/xml");
+            
+			var topNode1 = doc1.firstChild;
+			t.assertTrue(topNode1 !== null);
+			t.assertTrue(topNode1.tagName === "parentNode");
+			dojox.xml.parser.removeChildren(topNode1);
+			t.assertTrue(topNode1.childNodes.length === 0);
+			t.assertTrue(topNode1.firstChild === null);
+		},
+		function testInnerXML(t){
+			var simpleXml1 = "<parentNode><child1/><child2/><child3/></parentNode>";
+			var doc1 = dojox.xml.parser.parse(simpleXml1, "text/xml");
+            
+			var topNode1 = doc1.firstChild;
+			t.assertTrue(topNode1 !== null);
+			t.assertTrue(topNode1.tagName === "parentNode");
+
+			var innerXml = dojox.xml.parser.innerXML(topNode1);
+			t.assertTrue(simpleXml1 === innerXml);
+		}
+	]
+);
diff --git a/dojox/xml/tests/runTests.html b/dojox/xml/tests/runTests.html
new file mode 100644
index 0000000..6b85be7
--- /dev/null
+++ b/dojox/xml/tests/runTests.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+    <head>
+    <title>Dojox.wire Unit Test Runner</title>
+    <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.xml.tests.module"></HEAD>
+    <BODY>
+        Redirecting to D.O.H runner.
+    </BODY>
+</HTML> 
diff --git a/dojox/xml/tests/widgetParser.html b/dojox/xml/tests/widgetParser.html
new file mode 100644
index 0000000..77e30c1
--- /dev/null
+++ b/dojox/xml/tests/widgetParser.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Accordion Widget Demo</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/themes/tundra/tundra.css";
+	</style>
+
+
+	<script type="text/javascript" src="../../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+		
+	<script type="text/javascript" src="../widgetParser.js"></script>
+		
+	<script type="text/javascript">
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.layout.AccordionContainer");
+		dojo.require("dijit.form.TextBox");
+		dojo.require("dojox.xml.Script");
+	</script>
+
+		
+</head>
+
+<body style="padding: 50px;" class="tundra">
+
+<h1 class="testTitle">AccordionContainer Tests</h1>
+
+
+<script type="text/xml" dojoType="dojox.xml.Script">
+<ui xmlns:dijit="dijit" xmlns:html="html">
+<html:h2>Accordion from markup:</html:h2>
+	<html:p>HTML before</html:p>
+	<dijit:form.Button label="Hello, World!">
+		<html:script type="dojo/method" event="onClick"><![CDATA[
+		    alert(true && true);
+		]]></html:script>
+	</dijit:form.Button>
+	<html:p>HTML before</html:p>
+	
+	<html:table>
+	<html:tbody>
+    <html:tr>
+            <html:td>
+                        <html:label style="width:160px;height:60px">HTML Label</html:label>
+            </html:td>
+    </html:tr>
+    </html:tbody>
+    </html:table>
+
+	
+
+	<dijit:layout.AccordionContainer duration="200"
+		style="float: left; margin-right: 30px;  width: 400px; height: 300px; overflow: hidden">
+	
+		<dijit:layout.AccordionPane title="a">
+			Hello World
+		</dijit:layout.AccordionPane>
+		<dijit:layout.AccordionPane title="b">
+			<html:p>
+				Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin
+				suscipit porta magna. Duis accumsan nunc in velit. Nam et nibh.
+				Nulla facilisi. Cras venenatis urna et magna. Aenean magna mauris,
+				bibendum sit amet, semper quis, aliquet nec, sapien.  Aliquam
+				aliquam odio quis erat. Etiam est nisi, condimentum non, lacinia
+				ac, vehicula laoreet, elit. Sed interdum augue sit amet quam
+				dapibus semper. Nulla facilisi. Pellentesque lobortis erat nec
+				quam.
+			</html:p>
+			<html:p>
+				Sed arcu magna, molestie at, fringilla in, sodales eu, elit.
+				Curabitur mattis lorem et est. Quisque et tortor. Integer bibendum
+				vulputate odio. Nam nec ipsum. Vestibulum mollis eros feugiat
+				augue. Integer fermentum odio lobortis odio. Nullam mollis nisl non
+				metus. Maecenas nec nunc eget pede ultrices blandit. Ut non purus
+				ut elit convallis eleifend. Fusce tincidunt, justo quis tempus
+				euismod, magna nulla viverra libero, sit amet lacinia odio diam id
+				risus. Ut varius viverra turpis. Morbi urna elit, imperdiet eu,
+				porta ac, pharetra sed, nisi. Etiam ante libero, ultrices ac,
+				faucibus ac, cursus sodales, nisl. Praesent nisl sem, fermentum eu,
+				consequat quis, varius interdum, nulla. Donec neque tortor,
+				sollicitudin sed, consequat nec, facilisis sit amet, orci. Aenean
+				ut eros sit amet ante pharetra interdum.
+			</html:p>			
+		</dijit:layout.AccordionPane>
+	</dijit:layout.AccordionContainer>
+</ui>
+</script>
+
+<div style="clear: both;">
+<p>This should appear after the accordion</p>
+</div>
+
+<script type="text/xml" 
+	dojoType="dojox.xml.Script"
+	src="myPage.xml">
+</script>
+
+<div>
+<p>This should appear after the accordion</p>
+</div>
+</body>
+
+
+</html>
diff --git a/dojox/xml/widgetParser.js b/dojox/xml/widgetParser.js
index af8ae24..55055e1 100644
--- a/dojox/xml/widgetParser.js
+++ b/dojox/xml/widgetParser.js
@@ -1,69 +1,169 @@
-/*
-	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
+/**
+Take some sort of xml block
+* like <dojo.button caption="blah"/> and turn
+* it into a widget..
 */
 
-
-if(!dojo._hasResource["dojox.xml.widgetParser"]){
-dojo._hasResource["dojox.xml.widgetParser"]=true;
 dojo.provide("dojox.xml.widgetParser");
 dojo.require("dojox.xml.parser");
 dojo.require("dojo.parser");
-dojox.xml.widgetParser=new function(){
-var d=dojo;
-this.parseNode=function(_1){
-var _2=[];
-d.query("script[type='text/xml']",_1).forEach(function(_3){
-_2.push.apply(_2,this._processScript(_3));
-},this).orphan();
-return d.parser.instantiate(_2);
-};
-this._processScript=function(_4){
-var _5=_4.src?d._getText(_4.src):_4.innerHTML||_4.firstChild.nodeValue;
-var _6=this.toHTML(dojox.xml.parser.parse(_5).firstChild);
-var _7=d.query("[dojoType]",_6);
-dojo.query(">",_6).place(_4,"before");
-_4.parentNode.removeChild(_4);
-return _7;
-};
-this.toHTML=function(_8){
-var _9;
-var _a=_8.nodeName;
-var dd=dojo.doc;
-var _b=_8.nodeType;
-if(_b>=3){
-return dd.createTextNode((_b==3||_b==4)?_8.nodeValue:"");
-}
-var _c=_8.localName||_a.split(":").pop();
-var _d=_8.namespaceURI||(_8.getNamespaceUri?_8.getNamespaceUri():"");
-if(_d=="html"){
-_9=dd.createElement(_c);
-}else{
-var _e=_d+"."+_c;
-_9=_9||dd.createElement((_e=="dijit.form.ComboBox")?"select":"div");
-_9.setAttribute("dojoType",_e);
-}
-d.forEach(_8.attributes,function(_f){
-var _10=_f.name||_f.nodeName;
-var _11=_f.value||_f.nodeValue;
-if(_10.indexOf("xmlns")!=0){
-if(dojo.isIE&&_10=="style"){
-_9.style.setAttribute("cssText",_11);
-}else{
-_9.setAttribute(_10,_11);
-}
-}
-});
-d.forEach(_8.childNodes,function(cn){
-var _12=this.toHTML(cn);
-if(_c=="script"){
-_9.text+=_12.nodeValue;
-}else{
-_9.appendChild(_12);
-}
-},this);
-return _9;
-};
+
+
+	/**
+	 * We want to support something like:
+	 * <body>
+	 * 	<script>
+	 * 	<dijit.layout.SplitContainer>
+	 * 		<dijit.button/>
+	 * 		<div>...</div>
+	 * 	</dijit.layout.SplitContainer>
+	 * </body>
+	 * 
+	 * This is very tricky because if we parse this as XML then the <div> tag
+	 * is actually an XML tag, not an XML tag, which is problematic in at least
+	 * IE.
+	 *
+	 * So the strategy is this, silly as it may be: Convert EVERYTHING to HTML
+	 * nodes, including the dijit.layout.SplitContainer by converting it to a
+	 * div with the dojoType. Then run it through the standard parser.
+	 * The more HTML you have relative to XML the less extra overhead this is.
+	 * 
+	 * For something that is all XML we could have a different approach,
+	 * perhaps signified by a different type of script tag. In that case we
+	 * could just instantiate all the elements without a sourceNodeRef and then
+	 * add the top level components to the app.
+	 * 
+	 * That is very straightforward but I haven't done it.
+	 * 
+	 * Right now there is no mechanism to have an intermediary bridge between
+	 * the XML and the widget, because we are relying on dojo.parser
+	 * to do the instantiation. It isn't clear to me why we would want
+	 * those bridges in this approach and not in that approach.
+	 * 
+	 */
+
+dojox.xml.widgetParser = new function(){
+	
+	var d = dojo;
+	
+	this.parseNode = function(node){
+		
+		var toBuild = [];
+		//TODO figure out the proper type
+		d.query("script[type='text/xml']", node).forEach(function(script){
+			toBuild.push.apply(toBuild, this._processScript(script));
+		}, this).orphan();
+		
+		//instantiate everything at the end, doing it piecewise can give ID conflicts
+		return d.parser.instantiate(toBuild);
+	};
+
+	this._processScript = function(script){
+		//the text is either loaded from a separate file by the src
+		//attribute or underneath the src tag
+		var text = script.src ?  d._getText(script.src) : script.innerHTML || script.firstChild.nodeValue;
+		var htmlNode = this.toHTML( dojox.xml.parser.parse(text).firstChild );
+		
+		//make the list BEFORE we copy things over to keep the query scope as
+		//small as possible
+		var ret = d.query('[dojoType]', htmlNode);
+		//remove the script tag and replace with new HTML block
+		dojo.query(">", htmlNode).place(script, "before")
+		script.parentNode.removeChild(script);
+		return ret;
+	};
+	
+	/**
+	 * Given an XML node converts it to HTML where the existing HTML
+	 * is preserved and the dojo widget tags are converted to divs
+	 * with dojoType on them.
+	 */
+	this.toHTML = function (/*XmlNode*/ node){
+		var newNode;
+		var nodeName = node.nodeName;
+		var dd = dojo.doc;
+		var type = node.nodeType;
+		
+		
+		///node type 3 and 4 are text and cdata
+		if(type >= 3){
+			return dd.createTextNode( (type == 3 || type == 4) ? node.nodeValue : "" );
+		}
+		
+		var localName = node.localName||nodeName.split(":").pop();
+		
+		//TODO:
+		//		only check for namespace ONCE ever, instead of each time here,
+		//		by mixing in the right check for each browser?
+		var namespace = node.namespaceURI || (node.getNamespaceUri ? node.getNamespaceUri() : "");
+		
+		//TODO check for some real namespace
+		if(namespace == "html"){
+			newNode = dd.createElement(localName);
+		}else{
+			var dojoType = namespace + "." + localName;
+			
+			/**
+			 * This is a horrible hack we need because creating a <div>
+			 * with <option> children doesn't work well. Specifically with
+			 * dojo.Declaration at some point the <option> tags get lost 
+			 * entirely so we need the parent of <option> tags to be <select>
+			 * tags. (Not a problem outside of dojo.Delcaration)
+			 * There are a couple other ways we could do this:
+			 * 1. Look at the first element child to see if it is an option and 
+			 * if so create a <select> here.
+			 * 2. When we add a child to parent fix up the parent then if the 
+			 * child is an <option> and the parent isn't a <select>.
+			 * Both of those are a bit messy and slower than this.
+			 * 
+			 * This is potentially a problem for other tag combinations as well,
+			 * such as <tr> under a <table> or <li> under a <ul>/<ol>.
+			 * (dojox.widget.SortList for example). Probably need a robust strategy for
+			 * dealing with this. Worst case scenario for now is that user has to use
+			 * html tag with dojoType for misbehaving widget.
+			 */
+			newNode = newNode || dd.createElement((dojoType == "dijit.form.ComboBox") ? "select" : "div");
+			newNode.setAttribute("dojoType", dojoType);
+		}
+		
+		//	TODO:
+		//		we should probably set this up different, mixin a function
+		//		depending on if it is IE rather than checking every time here
+		//		the xmlns problem and the style problem are both IE specific
+		d.forEach(node.attributes, function(attr){
+			// NOTE: IE always iterates *all* properties!!!
+			var name = attr.name || attr.nodeName;
+			var value = attr.value || attr.nodeValue;
+			if(name.indexOf("xmlns") != 0){
+				// style=blah blah blah is a problem, in IE if you use
+				// setAttribute here you get all sorts of problems. Maybe it
+				// would be better to just create a giant string of HTML
+				// instead of an object graph, then set innerHTML on something
+				// to get the object graph? That might be cleaner...  that way
+				// is uses the browser HTML parsing exactly at is and won't
+				// cause any sort of issues. We could just special case style
+				// as well?
+				if(dojo.isIE && name == "style"){
+					newNode.style.setAttribute("cssText", value);
+				}else{
+					newNode.setAttribute(name, value);
+				}
+			}
+		});
+		d.forEach(node.childNodes, function(cn){
+			var childNode = this.toHTML(cn);
+			
+			// script tags in IE don't like appendChild, innerHTML or innerText
+			// so if we are creating one programatically set text instead
+			// could special case this for IE only
+			if(localName == "script"){
+				newNode.text += childNode.nodeValue;
+			}else{
+				newNode.appendChild(childNode);
+			}
+		}, this);
+		return newNode;
+	};
+	
 }();
-}
+
diff --git a/dojox/xmpp/ChatService.js b/dojox/xmpp/ChatService.js
index 7daa51d..e40c264 100644
--- a/dojox/xmpp/ChatService.js
+++ b/dojox/xmpp/ChatService.js
@@ -1,90 +1,141 @@
+dojo.provide("dojox.xmpp.ChatService");
+
+dojox.xmpp.chat = {
+	CHAT_STATE_NS: 'http://jabber.org/protocol/chatstates',
+
+	ACTIVE_STATE: 'active',
+	COMPOSING_STATE: 'composing',
+	INACTIVE_STATE: 'inactive',
+	PAUSED_STATE: 'paused',
+	GONE_STATE: 'gone'
+}
+
+dojo.declare("dojox.xmpp.ChatService", null, {
+	state: "",
+
+	constructor: function(){
+		this.state="";
+		this.chatid = Math.round(Math.random() * 1000000000000000);
+	},
+	
+	recieveMessage: function(msg,initial){
+		if (msg&&!initial){
+			this.onNewMessage(msg);
+		}
+	},
+
+	setSession: function(session){
+		this.session = session;
+	},
+
+	setState: function(state){
+		if (this.state != state){
+			this.state = state;
+		}
+	},
+	
+	invite: function(contact){
+		if (this.uid){return;}	
+
+
+		if(!contact || contact==''){
+			throw new Error("ChatService::invite() contact is NULL");
+		}
+
+		this.uid = contact;
+
+		var req = {
+			xmlns: "jabber:client",
+			to: this.uid,
+			from: this.session.jid + "/" + this.session.resource,
+			type: "chat"
+		}
+		var request = new dojox.string.Builder(dojox.xmpp.util.createElement("message", req, false));
+		request.append(dojox.xmpp.util.createElement("thread",{},false));	
+		request.append(this.chatid);
+		request.append("</thread>");
+		request.append(dojox.xmpp.util.createElement("active",{xmlns: dojox.xmpp.chat.CHAT_STATE_NS},true));
+		request.append("</message>");
+		this.session.dispatchPacket(request.toString());
+
+		this.onInvite(contact);
+		this.setState(dojox.xmpp.chat.CHAT_STATE_NS);
+	},
+
+
+	sendMessage: function(msg){
+		if (!this.uid){
+			//console.log("ChatService::sendMessage() -  Contact Id is null, need to invite to chat");
+			return;
+		}
+
+		if ((!msg.body || msg.body=="") && !msg.xhtml){return;}
+
+		var req = {
+			xmlns: "jabber:client",
+			to: this.uid,
+			from: this.session.jid + "/" + this.session.resource,
+			type: "chat"
+		}
+
+		var message = new dojox.string.Builder(dojox.xmpp.util.createElement("message",req,false));
+		var html = dojox.xmpp.util.createElement("html", { "xmlns":dojox.xmpp.xmpp.XHTML_IM_NS},false)
+
+		var bodyTag = dojox.xmpp.util.createElement("body", {"xml:lang":this.session.lang, "xmlns":dojox.xmpp.xmpp.XHTML_BODY_NS}, false) + msg.body + "</body>";
+		var bodyPlainTag = dojox.xmpp.util.createElement("body", {}, false) + dojox.xmpp.util.stripHtml(msg.body) + "</body>";
 /*
-	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
+		if (msg.xhtml){
+			if (msg.xhtml.getAttribute('xmlns') != dojox.xmpp.xmpp.XHTML_IM_NS){
+				//console.log("ChatService::sendMessage() - Cannot use this xhtml without the propper xmlns");
+			}else{
+				//FIXME do this in some portable way
+				//console.log("ChatService::sendMessage() - FIXME Serialize XHTML to string: ", msg.xhtml.toString());
+			}
+		}
 */
+		if (message.subject && message.subject != ""){
+			message.append(dojox.xmpp.util.createElement("subject",{},false));
+			message.append(message.subject);
+			message.append("</subject>");
+		}
+		message.append(bodyPlainTag);
+		message.append(html);
+		message.append(bodyTag);
+		message.append("</html>");
+		message.append(dojox.xmpp.util.createElement("thread", {}, false));
+		message.append(this.chatid);
+		message.append("</thread>");
 
+		if (this.useChatStates){
+			message.append(dojox.xmpp.util.createElement("active",{xmlns: dojox.xmpp.chat.CHAT_STATE_NS},true));
+		}
+		message.append("</message>");
+	
+		this.session.dispatchPacket(message.toString());
+	},
 
-if(!dojo._hasResource["dojox.xmpp.ChatService"]){
-dojo._hasResource["dojox.xmpp.ChatService"]=true;
-dojo.provide("dojox.xmpp.ChatService");
-dojox.xmpp.chat={CHAT_STATE_NS:"http://jabber.org/protocol/chatstates",ACTIVE_STATE:"active",COMPOSING_STATE:"composing",INACTIVE_STATE:"inactive",PAUSED_STATE:"paused",GONE_STATE:"gone"};
-dojo.declare("dojox.xmpp.ChatService",null,{state:"",constructor:function(){
-this.state="";
-this.chatid=Math.round(Math.random()*1000000000000000);
-},recieveMessage:function(_1,_2){
-if(_1&&!_2){
-this.onNewMessage(_1);
-}
-},setSession:function(_3){
-this.session=_3;
-},setState:function(_4){
-if(this.state!=_4){
-this.state=_4;
-}
-},invite:function(_5){
-if(this.uid){
-return;
-}
-if(!_5||_5==""){
-throw new Error("ChatService::invite() contact is NULL");
-}
-this.uid=_5;
-var _6={xmlns:"jabber:client",to:this.uid,from:this.session.jid+"/"+this.session.resource,type:"chat"};
-var _7=new dojox.string.Builder(dojox.xmpp.util.createElement("message",_6,false));
-_7.append(dojox.xmpp.util.createElement("thread",{},false));
-_7.append(this.chatid);
-_7.append("</thread>");
-_7.append(dojox.xmpp.util.createElement("active",{xmlns:dojox.xmpp.chat.CHAT_STATE_NS},true));
-_7.append("</message>");
-this.session.dispatchPacket(_7.toString());
-this.onInvite(_5);
-this.setState(dojox.xmpp.chat.CHAT_STATE_NS);
-},sendMessage:function(_8){
-if(!this.uid){
-return;
-}
-if((!_8.body||_8.body=="")&&!_8.xhtml){
-return;
-}
-var _9={xmlns:"jabber:client",to:this.uid,from:this.session.jid+"/"+this.session.resource,type:"chat"};
-var _a=new dojox.string.Builder(dojox.xmpp.util.createElement("message",_9,false));
-var _b=dojox.xmpp.util.createElement("html",{"xmlns":dojox.xmpp.xmpp.XHTML_IM_NS},false);
-var _c=dojox.xmpp.util.createElement("body",{"xml:lang":this.session.lang,"xmlns":dojox.xmpp.xmpp.XHTML_BODY_NS},false)+_8.body+"</body>";
-var _d=dojox.xmpp.util.createElement("body",{},false)+dojox.xmpp.util.stripHtml(_8.body)+"</body>";
-if(_a.subject&&_a.subject!=""){
-_a.append(dojox.xmpp.util.createElement("subject",{},false));
-_a.append(_a.subject);
-_a.append("</subject>");
-}
-_a.append(_d);
-_a.append(_b);
-_a.append(_c);
-_a.append("</html>");
-_a.append(dojox.xmpp.util.createElement("thread",{},false));
-_a.append(this.chatid);
-_a.append("</thread>");
-if(this.useChatStates){
-_a.append(dojox.xmpp.util.createElement("active",{xmlns:dojox.xmpp.chat.CHAT_STATE_NS},true));
-}
-_a.append("</message>");
-this.session.dispatchPacket(_a.toString());
-},sendChatState:function(_e){
-if(!this.useChatState||this.firstMessage){
-return;
-}
-if(_e==this._currentState){
-return;
-}
-var _f={xmlns:"jabber:client",to:this.uid,from:this.session.jid+"/"+this.session.resource,type:"chat"};
-var _10=new dojox.string.Builder(dojox.xmpp.util.createElement("message",_f,false));
-_10.append(dojox.xmpp.util.createElement(_e,{xmlns:dojox.xmpp.chat.CHAT_STATE_NS},true));
-this._currentState=_e;
-_10.append("<thread>");
-_10.append(this.chatid);
-_10.append("</thread></message>");
-this.session.dispatchPacket(_10.toString());
-},onNewMessage:function(msg){
-},onInvite:function(_11){
-}});
-}
+	sendChatState: function(state){
+		if (!this.useChatState || this.firstMessage){return;}
+		if (state==this._currentState){return;}
+		
+		var req={
+			xmlns: "jabber:client",
+			to: this.uid,
+			from: this.session.jid + "/" + this.session.resource,
+			type: "chat"
+		}
+
+		var request = new dojox.string.Builder(dojox.xmpp.util.createElement("message",req,false));	
+		request.append(dojox.xmpp.util.createElement(state, {xmlns: dojox.xmpp.chat.CHAT_STATE_NS},true));
+		this._currentState = state;
+		request.append("<thread>");
+		request.append(this.chatid);
+		request.append("</thread></message>");	
+		
+		this.session.dispatchPacket(request.toString());
+	},
+
+	//EVENTS 
+	onNewMessage: function(msg){},
+	onInvite: function(contact){}
+});
diff --git a/dojox/xmpp/PresenceService.js b/dojox/xmpp/PresenceService.js
index c3d12c7..90cfba9 100644
--- a/dojox/xmpp/PresenceService.js
+++ b/dojox/xmpp/PresenceService.js
@@ -1,163 +1,307 @@
-/*
-	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
-*/
+dojo.provide("dojox.xmpp.PresenceService");
 
+dojox.xmpp.presence = {
+	UPDATE: 201,
+	SUBSCRIPTION_REQUEST: 202,
+//	SUBSCRIPTION_REQUEST_PENDING: 203,
+	/* used when 'ask' attribute is absent on a roster item */
+	SUBSCRIPTION_SUBSTATUS_NONE: 204,
 
-if(!dojo._hasResource["dojox.xmpp.PresenceService"]){
-dojo._hasResource["dojox.xmpp.PresenceService"]=true;
-dojo.provide("dojox.xmpp.PresenceService");
-dojox.xmpp.presence={UPDATE:201,SUBSCRIPTION_REQUEST:202,SUBSCRIPTION_SUBSTATUS_NONE:204,SUBSCRIPTION_NONE:"none",SUBSCRIPTION_FROM:"from",SUBSCRIPTION_TO:"to",SUBSCRIPTION_BOTH:"both",SUBSCRIPTION_REQUEST_PENDING:"pending",STATUS_ONLINE:"online",STATUS_AWAY:"away",STATUS_CHAT:"chat",STATUS_DND:"dnd",STATUS_EXTENDED_AWAY:"xa",STATUS_OFFLINE:"offline",STATUS_INVISIBLE:"invisible"};
-dojo.declare("dojox.xmpp.PresenceService",null,{constructor:function(_1){
-this.session=_1;
-this.isInvisible=false;
-this.avatarHash=null;
-this.presence=null;
-this.restrictedContactjids={};
-},publish:function(_2){
-this.presence=_2;
-this._setPresence();
-},sendAvatarHash:function(_3){
-this.avatarHash=_3;
-this._setPresence();
-},_setPresence:function(){
-var _4=this.presence;
-var p={xmlns:"jabber:client"};
-if(_4&&_4.to){
-p.to=_4.to;
-}
-if(_4.show&&_4.show==dojox.xmpp.presence.STATUS_OFFLINE){
-p.type="unavailable";
-}
-if(_4.show&&_4.show==dojox.xmpp.presence.STATUS_INVISIBLE){
-this._setInvisible();
-this.isInvisible=true;
-return;
-}
-if(this.isInvisible){
-this._setVisible();
-}
-var _5=new dojox.string.Builder(dojox.xmpp.util.createElement("presence",p,false));
-if(_4.show&&_4.show!=dojox.xmpp.presence.STATUS_OFFLINE){
-_5.append(dojox.xmpp.util.createElement("show",{},false));
-_5.append(_4.show);
-_5.append("</show>");
-}
-if(_4.status){
-_5.append(dojox.xmpp.util.createElement("status",{},false));
-_5.append(_4.status);
-_5.append("</status>");
-}
-if(this.avatarHash){
-_5.append(dojox.xmpp.util.createElement("x",{xmlns:"vcard-temp:x:update"},false));
-_5.append(dojox.xmpp.util.createElement("photo",{},false));
-_5.append(this.avatarHash);
-_5.append("</photo>");
-_5.append("</x>");
-}
-if(_4.priority&&_4.show!=dojox.xmpp.presence.STATUS_OFFLINE){
-if(_4.priority>127||_4.priority<-128){
-_4.priority=5;
-}
-_5.append(dojox.xmpp.util.createElement("priority",{},false));
-_5.append(_4.priority);
-_5.append("</priority>");
-}
-_5.append("</presence>");
-this.session.dispatchPacket(_5.toString());
-},toggleBlockContact:function(_6){
-if(!this.restrictedContactjids[_6]){
-this.restrictedContactjids[_6]=this._createRestrictedJid();
-}
-this.restrictedContactjids[_6].blocked=!this.restrictedContactjids[_6].blocked;
-this._updateRestricted();
-return this.restrictedContactjids;
-},toggleContactInvisiblity:function(_7){
-if(!this.restrictedContactjids[_7]){
-this.restrictedContactjids[_7]=this._createRestrictedJid();
-}
-this.restrictedContactjids[_7].invisible=!this.restrictedContactjids[_7].invisible;
-this._updateRestricted();
-return this.restrictedContactjids;
-},_createRestrictedJid:function(){
-return {invisible:false,blocked:false};
-},_updateRestricted:function(){
-var _8={id:this.session.getNextIqId(),from:this.session.jid+"/"+this.session.resource,type:"set"};
-var _9=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_8,false));
-_9.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:privacy"},false));
-_9.append(dojox.xmpp.util.createElement("list",{name:"iwcRestrictedContacts"},false));
-var _a=1;
-for(var _b in this.restrictedContactjids){
-var _c=this.restrictedContactjids[_b];
-if(_c.blocked||_c.invisible){
-_9.append(dojox.xmpp.util.createElement("item",{value:dojox.xmpp.util.encodeJid(_b),action:"deny",order:_a++},false));
-if(_c.blocked){
-_9.append(dojox.xmpp.util.createElement("message",{},true));
-}
-if(_c.invisible){
-_9.append(dojox.xmpp.util.createElement("presence-out",{},true));
-}
-_9.append("</item>");
-}else{
-delete this.restrictedContactjids[_b];
-}
-}
-_9.append("</list>");
-_9.append("</query>");
-_9.append("</iq>");
-var _d=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_8,false));
-_d.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:privacy"},false));
-_d.append(dojox.xmpp.util.createElement("active",{name:"iwcRestrictedContacts"},true));
-_d.append("</query>");
-_d.append("</iq>");
-this.session.dispatchPacket(_9.toString());
-this.session.dispatchPacket(_d.toString());
-},_setVisible:function(){
-var _e={id:this.session.getNextIqId(),from:this.session.jid+"/"+this.session.resource,type:"set"};
-var _f=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_e,false));
-_f.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:privacy"},false));
-_f.append(dojox.xmpp.util.createElement("active",{},true));
-_f.append("</query>");
-_f.append("</iq>");
-this.session.dispatchPacket(_f.toString());
-},_setInvisible:function(){
-var _10={id:this.session.getNextIqId(),from:this.session.jid+"/"+this.session.resource,type:"set"};
-var req=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_10,false));
-req.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:privacy"},false));
-req.append(dojox.xmpp.util.createElement("list",{name:"invisible"},false));
-req.append(dojox.xmpp.util.createElement("item",{action:"deny",order:"1"},false));
-req.append(dojox.xmpp.util.createElement("presence-out",{},true));
-req.append("</item>");
-req.append("</list>");
-req.append("</query>");
-req.append("</iq>");
-_10={id:this.session.getNextIqId(),from:this.session.jid+"/"+this.session.resource,type:"set"};
-var _11=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_10,false));
-_11.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:privacy"},false));
-_11.append(dojox.xmpp.util.createElement("active",{name:"invisible"},true));
-_11.append("</query>");
-_11.append("</iq>");
-this.session.dispatchPacket(req.toString());
-this.session.dispatchPacket(_11.toString());
-},_manageSubscriptions:function(_12,_13){
-if(!_12){
-return;
-}
-if(_12.indexOf("@")==-1){
-_12+="@"+this.session.domain;
-}
-var req=dojox.xmpp.util.createElement("presence",{to:_12,type:_13},true);
-this.session.dispatchPacket(req);
-},subscribe:function(_14){
-this._manageSubscriptions(_14,"subscribe");
-},approveSubscription:function(_15){
-this._manageSubscriptions(_15,"subscribed");
-},unsubscribe:function(_16){
-this._manageSubscriptions(_16,"unsubscribe");
-},declineSubscription:function(_17){
-this._manageSubscriptions(_17,"unsubscribed");
-},cancelSubscription:function(_18){
-this._manageSubscriptions(_18,"unsubscribed");
-}});
+	SUBSCRIPTION_NONE: 'none',
+	SUBSCRIPTION_FROM: 'from',
+	SUBSCRIPTION_TO: 'to',
+	SUBSCRIPTION_BOTH: 'both',
+	SUBSCRIPTION_REQUEST_PENDING: 'pending',
+
+	STATUS_ONLINE: 'online',
+	STATUS_AWAY: 'away',
+	STATUS_CHAT: 'chat',
+	STATUS_DND: 'dnd',
+	STATUS_EXTENDED_AWAY: 'xa',
+	STATUS_OFFLINE: 'offline',
+	
+	STATUS_INVISIBLE: 'invisible'
 }
+
+dojo.declare("dojox.xmpp.PresenceService", null, {
+	constructor: function(xmppService){
+		this.session= xmppService;
+		this.isInvisible = false;
+		this.avatarHash = null;
+		this.presence = null;
+		this.restrictedContactjids = {};
+	},
+
+	publish: function(presence){
+		////console.log("Presence::publish() ", presence);
+		this.presence  = presence;
+		this._setPresence();
+	},
+	
+	/**
+	<presence from='juliet at capulet.com/balcony'>
+	  <x xmlns='vcard-temp:x:update'>
+	    <photo>sha1-hash-of-image</photo>
+	  </x>
+	</presence>
+	
+	
+	<presence>
+	  <x xmlns='vcard-temp:x:update'>
+	    <photo/>
+	  </x>
+	</presence>
+	
+	*/
+	
+	sendAvatarHash: function(avatarHash) {
+			this.avatarHash = avatarHash;
+			this._setPresence();
+	},
+	
+	
+	_setPresence: function() {
+			var presence = 	this.presence;
+			var p = {xmlns: 'jabber:client'};
+
+			if (presence && presence.to){
+				p.to = presence.to;
+			}
+
+			if (presence.show && presence.show==dojox.xmpp.presence.STATUS_OFFLINE){
+				p.type = 'unavailable';
+			}
+
+			if (presence.show && presence.show==dojox.xmpp.presence.STATUS_INVISIBLE) {
+				this._setInvisible();
+				this.isInvisible = true;
+				return;
+			};
+
+			if(this.isInvisible) {
+				//console.log("was invisible, making visible");
+				this._setVisible();
+			}
+
+			var req = new dojox.string.Builder(dojox.xmpp.util.createElement("presence",p, false));
+
+			if (presence.show && presence.show!=dojox.xmpp.presence.STATUS_OFFLINE  ) {
+				req.append(dojox.xmpp.util.createElement("show",{},false));
+				req.append(presence.show);
+				req.append("</show>");
+			}
+
+			if(presence.status) {
+				req.append(dojox.xmpp.util.createElement("status",{},false));
+				req.append(presence.status);
+				req.append("</status>");
+			}
+
+			if(this.avatarHash) {
+				req.append(dojox.xmpp.util.createElement("x",{xmlns: 'vcard-temp:x:update'},false));
+					req.append(dojox.xmpp.util.createElement("photo",{},false));
+					req.append(this.avatarHash);
+					req.append("</photo>");
+				req.append("</x>");
+			}
+
+
+			if (presence.priority && presence.show!=dojox.xmpp.presence.STATUS_OFFLINE){
+				if(presence.priority > 127 || presence.priority < -128){
+					presence.priority = 5;
+				}
+				req.append(dojox.xmpp.util.createElement("priority",{},false));
+				req.append(presence.priority);
+				req.append("</priority>");
+			}
+
+			req.append("</presence>");
+			this.session.dispatchPacket(req.toString());
+	},
+	
+	/*
+	
+	<iq from='bilbo at tolkien.lit/shire' type='set' id='inv1'>
+	  <query xmlns='jabber:iq:privacy'>
+	    <list name='invisible'>
+	      <item action='deny' order='1'>
+	        <presence-out/>
+	      </item>
+	    </list>
+	  </query>
+	</iq>
+	
+	<iq from='bilbo at tolkien.lit/shire' type='set' id='active1'>
+	  <query xmlns='jabber:iq:privacy'>
+	    <active name='invisible'/>
+	  </query>
+	</iq>
+	
+	Make visible:
+	<iq from='bilbo at tolkien.lit/shire' type='set' id='active6'>
+	  <query xmlns='jabber:iq:privacy'>
+	    <active/>
+	  </query>
+	</iq>
+	
+	*/
+	
+	toggleBlockContact: function(jid) {
+		if(!this.restrictedContactjids[jid]) {
+			this.restrictedContactjids[jid] = this._createRestrictedJid();
+		}
+		
+		this.restrictedContactjids[jid].blocked = !this.restrictedContactjids[jid].blocked;
+		//console.log("setting outbound block for ", jid, this.restrictedContactjids[jid]);
+		this._updateRestricted();
+		return this.restrictedContactjids;
+	},
+	
+	
+	toggleContactInvisiblity: function(jid) {
+		if(!this.restrictedContactjids[jid]) {
+			this.restrictedContactjids[jid] = this._createRestrictedJid();
+		}
+		
+		this.restrictedContactjids[jid].invisible = !this.restrictedContactjids[jid].invisible;
+		//console.log("setting outbound presence for ", jid, this.restrictedContactjids[jid]);
+		this._updateRestricted();
+		return this.restrictedContactjids;
+	},
+	
+	_createRestrictedJid: function() {
+		return {invisible: false, blocked:false};
+	},
+	
+	_updateRestricted: function() {
+		
+		var props={
+			id: this.session.getNextIqId(),
+			from: this.session.jid + "/" + this.session.resource,
+			type: "set"
+		};
+		
+		var req = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",props,false));
+		req.append(dojox.xmpp.util.createElement("query",{xmlns: "jabber:iq:privacy"},false));
+		req.append(dojox.xmpp.util.createElement("list",{name: "iwcRestrictedContacts"},false))
+		var count = 1;
+		for(var jid in this.restrictedContactjids) {
+			var item = this.restrictedContactjids[jid];
+			//console.log("restricted ", jid, item);
+			if(item.blocked || item.invisible) {
+				req.append(dojox.xmpp.util.createElement("item",{value:  dojox.xmpp.util.encodeJid(jid), action: "deny", order: count++},false));
+				if(item.blocked) {
+					req.append(dojox.xmpp.util.createElement("message",{},true));
+				}
+				if(item.invisible) {
+					req.append(dojox.xmpp.util.createElement("presence-out",{},true));
+				}
+				req.append("</item>");
+			} else {
+				delete this.restrictedContactjids[jid];
+			}
+			
+		
+			
+		}
+				req.append("</list>");
+			req.append("</query>");
+		req.append("</iq>");
+		//console.log("Restricted list: ", req.toString());
+		
+			var req2 = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",props,false));
+				req2.append(dojox.xmpp.util.createElement("query",{xmlns: "jabber:iq:privacy"},false));
+					req2.append(dojox.xmpp.util.createElement("active",{name:"iwcRestrictedContacts"},true));
+				req2.append("</query>");
+			req2.append("</iq>");
+		
+				//console.log("Activate list: ", req2.toString());
+		
+		
+		this.session.dispatchPacket(req.toString());
+		this.session.dispatchPacket(req2.toString());
+	},
+	
+	_setVisible: function() {
+			var props={
+				id: this.session.getNextIqId(),
+				from: this.session.jid + "/" + this.session.resource,
+				type: "set"
+			};
+			var req = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",props,false));
+				req.append(dojox.xmpp.util.createElement("query",{xmlns: "jabber:iq:privacy"},false));
+					req.append(dojox.xmpp.util.createElement("active",{},true));
+				req.append("</query>");
+			req.append("</iq>");
+			//console.log(req.toString());
+			this.session.dispatchPacket(req.toString());
+	},
+	
+	_setInvisible: function() {
+		//console.log("Setting user as invisible");
+		var props={
+			id: this.session.getNextIqId(),
+			from: this.session.jid + "/" + this.session.resource,
+			type: "set"
+		};
+		var req = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",props,false));
+			req.append(dojox.xmpp.util.createElement("query",{xmlns: "jabber:iq:privacy"},false));
+				req.append(dojox.xmpp.util.createElement("list",{name: "invisible"},false))
+					req.append(dojox.xmpp.util.createElement("item",{action: "deny", order: "1"},false))
+						req.append(dojox.xmpp.util.createElement("presence-out",{},true));
+					req.append("</item>");
+				req.append("</list>");
+			req.append("</query>");
+		req.append("</iq>");
+		
+		
+		props={
+			id: this.session.getNextIqId(),
+			from: this.session.jid + "/" + this.session.resource,
+			type: "set"
+		};
+
+		var req2 = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",props,false));
+			req2.append(dojox.xmpp.util.createElement("query",{xmlns: "jabber:iq:privacy"},false));
+				req2.append(dojox.xmpp.util.createElement("active",{name:"invisible"},true));
+			req2.append("</query>");
+		req2.append("</iq>");
+		//console.log(req.toString());
+		//console.log(req2.toString());
+		this.session.dispatchPacket(req.toString());
+		this.session.dispatchPacket(req2.toString());
+	},
+
+	_manageSubscriptions: function(contact, type){
+		if (!contact){return;}
+		
+		if (contact.indexOf('@')==-1){
+			contact += '@' + this.session.domain;
+		}
+
+		var req = dojox.xmpp.util.createElement("presence",{to:contact,type:type},true);
+		this.session.dispatchPacket(req);
+
+	},
+
+	subscribe: function(contact){
+		this._manageSubscriptions(contact, "subscribe");
+	},
+
+	approveSubscription: function(contact){
+		this._manageSubscriptions(contact, "subscribed");
+	},
+
+	unsubscribe: function(contact){
+		this._manageSubscriptions(contact, "unsubscribe");
+	},
+
+	declineSubscription: function(contact){
+		this._manageSubscriptions(contact, "unsubscribed");
+	},
+	
+	cancelSubscription: function(contact){
+		this._manageSubscriptions(contact, "unsubscribed");
+	}
+
+});
diff --git a/dojox/xmpp/RosterService.js b/dojox/xmpp/RosterService.js
index 9d1f523..8d0da99 100644
--- a/dojox/xmpp/RosterService.js
+++ b/dojox/xmpp/RosterService.js
@@ -1,210 +1,268 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.xmpp.RosterService"]){
-dojo._hasResource["dojox.xmpp.RosterService"]=true;
 dojo.provide("dojox.xmpp.RosterService");
-dojox.xmpp.roster={ADDED:101,CHANGED:102,REMOVED:103};
-dojo.declare("dojox.xmpp.RosterService",null,{constructor:function(_1){
-this.session=_1;
-},addRosterItem:function(_2,_3,_4){
-if(!_2){
-throw new Error("Roster::addRosterItem() - User ID is null");
-}
-var _5=this.session.getNextIqId();
-var _6={id:_5,from:this.session.jid+"/"+this.session.resource,type:"set"};
-var _7=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_6,false));
-_7.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:roster"},false));
-_2=dojox.xmpp.util.encodeJid(_2);
-if(_2.indexOf("@")==-1){
-_2=_2+"@"+this.session.domain;
-}
-_7.append(dojox.xmpp.util.createElement("item",{jid:_2,name:dojox.xmpp.util.xmlEncode(_3)},false));
-if(_4){
-for(var i=0;i<_4.length;i++){
-_7.append("<group>");
-_7.append(_4[i]);
-_7.append("</group>");
-}
-}
-_7.append("</item></query></iq>");
-var _8=this.session.dispatchPacket(_7.toString(),"iq",_6.id);
-_8.addCallback(this,"verifyRoster");
-return _8;
-},updateRosterItem:function(_9,_a,_b){
-if(_9.indexOf("@")==-1){
-_9+=_9+"@"+this.session.domain;
-}
-var _c={id:this.session.getNextIqId(),from:this.session.jid+"/"+this.session.resource,type:"set"};
-var _d=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_c,false));
-_d.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:roster"},false));
-var i=this.session.getRosterIndex(_9);
-if(i==-1){
-return;
-}
-var _e={jid:_9};
-if(_a){
-_e.name=_a;
-}else{
-if(this.session.roster[i].name){
-_e.name=this.session.roster[i].name;
-}
-}
-if(_e.name){
-_e.name=dojox.xmpp.util.xmlEncode(_e.name);
-}
-_d.append(dojox.xmpp.util.createElement("item",_e,false));
-var _f=_b?_b:this.session.roster[i].groups;
-if(_f){
-for(var x=0;x<_f.length;x++){
-_d.append("<group>");
-_d.append(_f[x]);
-_d.append("</group>");
-}
-}
-_d.append("</item></query></iq>");
-var def=this.session.dispatchPacket(_d.toString(),"iq",_c.id);
-def.addCallback(this,"verifyRoster");
-return def;
-},verifyRoster:function(res){
-if(res.getAttribute("type")=="result"){
-}else{
-var err=this.session.processXmppError(res);
-this.onAddRosterItemFailed(err);
-}
-return res;
-},addRosterItemToGroup:function(jid,_10){
-if(!jid){
-throw new Error("Roster::addRosterItemToGroup() JID is null or undefined");
-}
-if(!_10){
-throw new Error("Roster::addRosterItemToGroup() group is null or undefined");
-}
-var _11=this.session.getRosterIndex(jid);
-if(_11==-1){
-return;
-}
-var _12=this.session.roster[_11];
-var _13=[];
-var _14=false;
-for(var i=0;((_12<_12.groups.length)&&(!_14));i++){
-if(_12.groups[i]!=_10){
-continue;
-}
-_14=true;
-}
-if(!_14){
-return this.updateRosterItem(jid,_12.name,_12.groups.concat(_10),_11);
-}
-return dojox.xmpp.xmpp.INVALID_ID;
-},removeRosterGroup:function(_15){
-var _16=this.session.roster;
-for(var i=0;i<_16.length;i++){
-var _17=_16[i];
-if(_17.groups.length>0){
-for(var j=0;j<_17.groups.length;j++){
-if(_17.groups[j]==_15){
-_17.groups.splice(j,1);
-this.updateRosterItem(_17.jid,_17.name,_17.groups);
-}
-}
-}
-}
-},renameRosterGroup:function(_18,_19){
-var _1a=this.session.roster;
-for(var i=0;i<_1a.length;i++){
-var _1b=_1a[i];
-if(_1b.groups.length>0){
-for(var j=0;j<_1b.groups.length;j++){
-if(_1b.groups[j]==_18){
-_1b.groups[j]=_19;
-this.updateRosterItem(_1b.jid,_1b.name,_1b.groups);
-}
-}
-}
-}
-},removeRosterItemFromGroup:function(jid,_1c){
-if(!jid){
-throw new Error("Roster::addRosterItemToGroup() JID is null or undefined");
-}
-if(!_1c){
-throw new Error("Roster::addRosterItemToGroup() group is null or undefined");
-}
-var _1d=this.session.getRosterIndex(jid);
-if(_1d==-1){
-return;
-}
-var _1e=this.session.roster[_1d];
-var _1f=false;
-for(var i=0;((i<_1e.groups.length)&&(!_1f));i++){
-if(_1e.groups[i]!=_1c){
-continue;
-}
-_1f=true;
-_1d=i;
-}
-if(_1f==true){
-_1e.groups.splice(_1d,1);
-return this.updateRosterItem(jid,_1e.name,_1e.groups);
-}
-return dojox.xmpp.xmpp.INVALID_ID;
-},rosterItemRenameGroup:function(jid,_20,_21){
-if(!jid){
-throw new Error("Roster::rosterItemRenameGroup() JID is null or undefined");
-}
-if(!_21){
-throw new Error("Roster::rosterItemRenameGroup() group is null or undefined");
-}
-var _22=this.session.getRosterIndex(jid);
-if(_22==-1){
-return;
-}
-var _23=this.session.roster[_22];
-var _24=false;
-for(var i=0;((i<_23.groups.length)&&(!_24));i++){
-if(_23.groups[i]==_20){
-_23.groups[i]=_21;
-_24=true;
-}
-}
-if(_24==true){
-return this.updateRosterItem(jid,_23.name,_23.groups);
-}
-return dojox.xmpp.xmpp.INVALID_ID;
-},renameRosterItem:function(jid,_25){
-if(!jid){
-throw new Error("Roster::addRosterItemToGroup() JID is null or undefined");
-}
-if(!_25){
-throw new Error("Roster::addRosterItemToGroup() New Name is null or undefined");
-}
-var _26=this.session.getRosterIndex(jid);
-if(_26==-1){
-return;
-}
-return this.updateRosterItem(jid,_25,this.session.roster.groups,_26);
-},removeRosterItem:function(jid){
-if(!jid){
-throw new Error("Roster::addRosterItemToGroup() JID is null or undefined");
-}
-var req={id:this.session.getNextIqId(),from:this.session.jid+"/"+this.session.resource,type:"set"};
-var _27=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",req,false));
-_27.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:roster"},false));
-if(jid.indexOf("@")==-1){
-jid+=jid+"@"+this.session.domain;
-}
-_27.append(dojox.xmpp.util.createElement("item",{jid:jid,subscription:"remove"},true));
-_27.append("</query></iq>");
-var def=this.session.dispatchPacket(_27.toString(),"iq",req.id);
-def.addCallback(this,"verifyRoster");
-return def;
-},getAvatar:function(jid){
-},publishAvatar:function(_28,_29){
-},onVerifyRoster:function(id){
-},onVerifyRosterFailed:function(err){
-}});
+
+dojox.xmpp.roster = {
+	ADDED: 101,
+	CHANGED: 102,
+	REMOVED: 103
 }
+
+dojo.declare("dojox.xmpp.RosterService", null, {
+	constructor: function(xmppSession){
+		this.session = xmppSession;
+	},
+
+	addRosterItem: function(jid, name, groups){
+		if(!jid){
+			throw new Error ("Roster::addRosterItem() - User ID is null");
+		}
+		var iqId = this.session.getNextIqId();
+		var req = {
+			id: iqId,
+			from: this.session.jid + "/" + this.session.resource,
+			type: "set"
+		}
+
+		var request = new dojox.string.Builder(dojox.xmpp.util.createElement("iq", req, false));
+		request.append(dojox.xmpp.util.createElement("query",{xmlns: 'jabber:iq:roster'},false));
+		jid = dojox.xmpp.util.encodeJid(jid);
+		if (jid.indexOf('@')== -1){
+			jid = jid + '@' + this.session.domain;
+		}
+
+
+		request.append(dojox.xmpp.util.createElement("item",{jid:jid,name:dojox.xmpp.util.xmlEncode(name)},false));
+
+		if (groups){
+			for (var i=0; i<groups.length; i++){
+				request.append("<group>");
+				request.append(groups[i]);
+				request.append("</group>");
+			}
+		}
+	
+		request.append("</item></query></iq>");
+		//console.log(request.toString());
+
+		var def = this.session.dispatchPacket(request.toString(),"iq",req.id);
+		def.addCallback(this, "verifyRoster");
+		return def;
+	},
+
+	updateRosterItem: function(jid, name, groups){
+		if (jid.indexOf('@') == -1){
+			jid += jid + '@' + this.session.domain;
+		}
+
+		var req = {
+			id: this.session.getNextIqId(),
+			from: this.session.jid + "/" + this.session.resource,
+			type: "set"
+		}
+
+		var request = new dojox.string.Builder(dojox.xmpp.util.createElement("iq", req, false));
+		request.append(dojox.xmpp.util.createElement("query",{xmlns: 'jabber:iq:roster'},false));
+
+		var i = this.session.getRosterIndex(jid);
+
+		//item not found
+		if (i==-1){return;}
+		var item = {
+			jid:jid
+		};
+		if(name){
+			item.name = name;
+		} else if(this.session.roster[i].name){
+			item.name = this.session.roster[i].name;
+		}
+		if(item.name) {
+			item.name = dojox.xmpp.util.xmlEncode(item.name);
+		}
+		request.append(dojox.xmpp.util.createElement("item",item,false));
+		
+		var newGroups = groups ? groups : this.session.roster[i].groups; 
+		
+		if (newGroups){
+			for (var x=0;x<newGroups.length;x++){
+				request.append("<group>");
+				request.append(newGroups[x]);
+				request.append("</group>");
+			}
+		}
+		
+		request.append("</item></query></iq>");
+		
+		var def = this.session.dispatchPacket(request.toString(),"iq",req.id);
+		def.addCallback(this, "verifyRoster");
+		return def;
+	},
+
+	verifyRoster: function(res){
+		if (res.getAttribute('type')=='result'){
+			//this.onAddRosterItem(res.getAttribute('id'));	
+		}else{
+			var err=this.session.processXmppError(res);
+			this.onAddRosterItemFailed(err);
+		}
+		return res;
+	},
+
+	addRosterItemToGroup: function(jid, group){
+		if (!jid) throw new Error("Roster::addRosterItemToGroup() JID is null or undefined");
+		if (!group) throw new Error("Roster::addRosterItemToGroup() group is null or undefined");
+
+		var index = this.session.getRosterIndex(jid);
+		if (index==-1){return;}
+
+		var item = this.session.roster[index];
+		var tgroups = [];
+
+		var found = false; 
+
+		for (var i=0; ((item<item.groups.length) && (!found)); i++){
+			if (item.groups[i]!=group){continue;}	
+			found=true;
+		} 	
+	
+		if(!found){
+			return this.updateRosterItem(jid, item.name, item.groups.concat(group),index);
+		}	
+	
+		return dojox.xmpp.xmpp.INVALID_ID;
+	},
+	
+	removeRosterGroup: function(group) {
+		var roster = this.session.roster;
+		for(var i=0;i<roster.length;i++){
+			var item = roster[i];
+			if(item.groups.length > 0) {
+				//var found = false;
+				for(var j = 0;j < item.groups.length; j++) {
+					if (item.groups[j]==group){
+						item.groups.splice(j,1);
+						this.updateRosterItem(item.jid, item.name, item.groups);
+						//found=true;
+					}				
+				}
+			}
+		}
+	},
+	
+	renameRosterGroup: function(group, newGroup) {
+		var roster = this.session.roster;
+		for(var i=0;i<roster.length;i++){
+			var item = roster[i];
+			if(item.groups.length > 0) {
+				//var found = false;
+				for(var j = 0;j < item.groups.length; j++) {
+					if (item.groups[j]==group){
+						item.groups[j] = newGroup;
+						this.updateRosterItem(item.jid, item.name, item.groups);
+				//		found=true;
+					}				
+				}
+			}
+		}
+	},
+
+	removeRosterItemFromGroup: function(jid, group){
+		if (!jid) throw new Error("Roster::addRosterItemToGroup() JID is null or undefined");
+		if (!group) throw new Error("Roster::addRosterItemToGroup() group is null or undefined");
+
+		var index = this.session.getRosterIndex(jid);
+		if (index==-1){return;}
+
+		var item = this.session.roster[index];
+		var found = false; 
+
+		for (var i=0; ((i<item.groups.length) && (!found)); i++){
+			if (item.groups[i]!=group){continue;}	
+			found=true;
+			index = i;
+		} 	
+
+		if(found==true){
+			item.groups.splice(index,1);
+			return this.updateRosterItem(jid, item.name, item.groups);
+		}		
+		
+		return dojox.xmpp.xmpp.INVALID_ID;
+	},
+	
+	rosterItemRenameGroup: function(jid, oldGroup, newGroup){
+		if (!jid) throw new Error("Roster::rosterItemRenameGroup() JID is null or undefined");
+		if (!newGroup) throw new Error("Roster::rosterItemRenameGroup() group is null or undefined");
+	
+		var index = this.session.getRosterIndex(jid);
+		if (index==-1){return;}
+
+		var item = this.session.roster[index];
+		var found = false; 
+
+		for (var i=0; ((i<item.groups.length) && (!found)); i++){
+			if (item.groups[i]==oldGroup){
+				item.groups[i] = newGroup;
+				found=true;
+			}
+		} 	
+
+		if(found==true){
+			return this.updateRosterItem(jid, item.name, item.groups);
+		}		
+		
+		return dojox.xmpp.xmpp.INVALID_ID;
+	},
+
+	renameRosterItem: function(jid,newName){
+		if (!jid) throw new Error("Roster::addRosterItemToGroup() JID is null or undefined");
+		if (!newName) throw new Error("Roster::addRosterItemToGroup() New Name is null or undefined");
+
+		var index = this.session.getRosterIndex(jid);
+		if (index==-1){return;}
+
+		return this.updateRosterItem(jid, newName, this.session.roster.groups,index);
+	},
+
+	removeRosterItem: function(jid){
+		if (!jid) throw new Error("Roster::addRosterItemToGroup() JID is null or undefined");
+		
+		var req={
+			id: this.session.getNextIqId(),
+			from: this.session.jid + "/" + this.session.resource,
+			type: 'set'
+		};
+		var request = new dojox.string.Builder(dojox.xmpp.util.createElement("iq", req, false));
+		
+		request.append(dojox.xmpp.util.createElement("query",{xmlns: "jabber:iq:roster"},false));
+
+		if (jid.indexOf('@')== -1){
+			jid += jid + '@' + this.session.domain;
+		}	
+
+		request.append(dojox.xmpp.util.createElement('item',{jid:jid,subscription:"remove"},true));
+
+		request.append("</query></iq>");
+
+		var def = this.session.dispatchPacket(request.toString(),"iq",req.id);
+		def.addCallback(this, "verifyRoster");
+		return def;
+	},
+
+	//Avatar functions...I removed this stuff for now..can we even do anything useful
+	//with this data even if we have it? 	
+	getAvatar: function(jid){
+	},
+
+	publishAvatar: function(type,binval){
+
+	},
+
+	//EVENTS
+
+	onVerifyRoster: function(id){
+		//console.log("Roster::onVerifyRoster() - ", id);	
+	},
+
+	onVerifyRosterFailed: function(err){
+		//console.log("onVerifyRosterFailed: ", err);
+	}
+});
diff --git a/dojox/xmpp/TransportSession.js b/dojox/xmpp/TransportSession.js
index 8eb7da8..e06ba77 100644
--- a/dojox/xmpp/TransportSession.js
+++ b/dojox/xmpp/TransportSession.js
@@ -1,301 +1,507 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.xmpp.TransportSession"]){
-dojo._hasResource["dojox.xmpp.TransportSession"]=true;
 dojo.provide("dojox.xmpp.TransportSession");
 dojo.require("dojox.xmpp.bosh");
 dojo.require("dojox.xmpp.util");
 dojo.require("dojox.data.dom");
-dojox.xmpp.TransportSession=function(_1){
-this.sendTimeout=(this.wait+20)*1000;
-if(_1&&dojo.isObject(_1)){
-dojo.mixin(this,_1);
-if(this.useScriptSrcTransport){
-this.transportIframes=[];
-}
-}
+
+dojox.xmpp.TransportSession = function(props) {
+	// we have to set this here because "this" doesn't work
+	// in the dojo.extend call.
+	this.sendTimeout = (this.wait+20)*1000;
+
+	//mixin any options that we want to provide to this service
+	if (props && dojo.isObject(props)) {
+		dojo.mixin(this, props);
+		if(this.useScriptSrcTransport){
+			this.transportIframes = [];
+		}
+	}
+	
 };
-dojo.extend(dojox.xmpp.TransportSession,{rid:0,hold:1,polling:1000,secure:false,wait:60,lang:"en",submitContentType:"text/xml; charset=utf=8",serviceUrl:"/httpbind",defaultResource:"dojoIm",domain:"imserver.com",sendTimeout:0,useScriptSrcTransport:false,keepAliveTimer:null,state:"NotReady",transmitState:"Idle",protocolPacketQueue:[],outboundQueue:[],outboundRequests:{},inboundQueue:[],deferredRequests:{},matchTypeIdAttribute:{},open:function(){
-this.status="notReady";
-this.rid=Math.round(Math.random()*1000000000);
-this.protocolPacketQueue=[];
-this.outboundQueue=[];
-this.outboundRequests={};
-this.inboundQueue=[];
-this.deferredRequests={};
-this.matchTypeIdAttribute={};
-this.keepAliveTimer=setTimeout(dojo.hitch(this,"_keepAlive"),10000);
-if(this.useScriptSrcTransport){
-dojox.xmpp.bosh.initialize({iframes:this.hold+1,load:dojo.hitch(this,function(){
-this._sendLogin();
-})});
-}else{
-this._sendLogin();
-}
-},_sendLogin:function(){
-var _2=this.rid++;
-var _3={content:this.submitContentType,hold:this.hold,rid:_2,to:this.domain,secure:this.secure,wait:this.wait,"xml:lang":this.lang,"xmpp:version":"1.0",xmlns:dojox.xmpp.xmpp.BODY_NS,"xmlns:xmpp":"urn:xmpp:xbosh"};
-var _4=dojox.xmpp.util.createElement("body",_3,true);
-this.addToOutboundQueue(_4,_2);
-},_sendRestart:function(){
-var _5=this.rid++;
-var _6={rid:_5,sid:this.sid,to:this.domain,"xmpp:restart":"true","xml:lang":this.lang,xmlns:dojox.xmpp.xmpp.BODY_NS,"xmlns:xmpp":"urn:xmpp:xbosh"};
-var _7=dojox.xmpp.util.createElement("body",_6,true);
-this.addToOutboundQueue(_7,_5);
-},processScriptSrc:function(_8,_9){
-var _a=dojox.xml.parser.parse(_8,"text/xml");
-if(_a){
-this.processDocument(_a,_9);
-}else{
-}
-},_keepAlive:function(){
-if(this.state=="wait"||this.isTerminated()){
-return;
-}
-this._dispatchPacket();
-this.keepAliveTimer=setTimeout(dojo.hitch(this,"_keepAlive"),10000);
-},close:function(_b){
-var _c=this.rid++;
-var _d={sid:this.sid,rid:_c,type:"terminate"};
-var _e=null;
-if(_b){
-_e=new dojox.string.Builder(dojox.xmpp.util.createElement("body",_d,false));
-_e.append(_b);
-_e.append("</body>");
-}else{
-_e=new dojox.string.Builder(dojox.xmpp.util.createElement("body",_d,false));
-}
-this.addToOutboundQueue(_e.toString(),_c);
-this.state=="Terminate";
-},dispatchPacket:function(_f,_10,_11,_12){
-if(_f){
-this.protocolPacketQueue.push(_f);
-}
-var def=new dojo.Deferred();
-if(_10&&_11){
-def.protocolMatchType=_10;
-def.matchId=_11;
-def.matchProperty=_12||"id";
-if(def.matchProperty!="id"){
-this.matchTypeIdAttribute[_10]=def.matchProperty;
-}
-}
-this.deferredRequests[def.protocolMatchType+"-"+def.matchId]=def;
-if(!this.dispatchTimer){
-this.dispatchTimer=setTimeout(dojo.hitch(this,"_dispatchPacket"),600);
-}
-return def;
-},_dispatchPacket:function(){
-clearTimeout(this.dispatchTimer);
-delete this.dispatchTimer;
-if(!this.sid){
-return;
-}
-if(!this.authId){
-return;
-}
-if(this.transmitState!="error"&&(this.protocolPacketQueue.length==0)&&(this.outboundQueue.length>0)){
-return;
-}
-if(this.state=="wait"||this.isTerminated()){
-return;
-}
-var req={sid:this.sid,xmlns:dojox.xmpp.xmpp.BODY_NS};
-var _13;
-if(this.protocolPacketQueue.length>0){
-req.rid=this.rid++;
-_13=new dojox.string.Builder(dojox.xmpp.util.createElement("body",req,false));
-_13.append(this.processProtocolPacketQueue());
-_13.append("</body>");
-delete this.lastPollTime;
-}else{
-if(this.lastPollTime){
-var now=new Date().getTime();
-if(now-this.lastPollTime<this.polling){
-this.dispatchTimer=setTimeout(dojo.hitch(this,"_dispatchPacket"),this.polling-(now-this.lastPollTime)+10);
-return;
-}
-}
-req.rid=this.rid++;
-this.lastPollTime=new Date().getTime();
-_13=new dojox.string.Builder(dojox.xmpp.util.createElement("body",req,true));
-}
-this.addToOutboundQueue(_13.toString(),req.rid);
-},redispatchPacket:function(rid){
-var env=this.outboundRequests[rid];
-this.sendXml(env,rid);
-},addToOutboundQueue:function(msg,rid){
-this.outboundQueue.push({msg:msg,rid:rid});
-this.outboundRequests[rid]=msg;
-this.sendXml(msg,rid);
-},removeFromOutboundQueue:function(rid){
-for(var i=0;i<this.outboundQueue.length;i++){
-if(rid==this.outboundQueue[i]["rid"]){
-this.outboundQueue.splice(i,1);
-break;
-}
-}
-delete this.outboundRequests[rid];
-},processProtocolPacketQueue:function(){
-var _14=new dojox.string.Builder();
-for(var i=0;i<this.protocolPacketQueue.length;i++){
-_14.append(this.protocolPacketQueue[i]);
-}
-this.protocolPacketQueue=[];
-return _14.toString();
-},sendXml:function(_15,rid){
-if(this.isTerminated()){
-return false;
-}
-this.transmitState="transmitting";
-var def=null;
-if(this.useScriptSrcTransport){
-def=dojox.xmpp.bosh.get({rid:rid,url:this.serviceUrl+"?"+encodeURIComponent(_15),error:dojo.hitch(this,function(res,io){
-this.setState("Terminate","error");
-return false;
-}),timeout:this.sendTimeout});
-}else{
-def=dojo.rawXhrPost({contentType:"text/xml",url:this.serviceUrl,postData:_15,handleAs:"xml",error:dojo.hitch(this,function(res,io){
-return this.processError(io.xhr.responseXML,io.xhr.status,rid);
-}),timeout:this.sendTimeout});
-}
-def.addCallback(this,function(res){
-return this.processDocument(res,rid);
+
+dojo.extend(dojox.xmpp.TransportSession, {
+
+		/* options/defaults */
+		rid: 0,
+		hold: 1,
+		polling:1000,
+		secure: false,
+		wait: 60,
+		lang: 'en',
+		submitContentType: 'text/xml; charset=utf=8',
+		serviceUrl: '/httpbind',
+		defaultResource: "dojoIm",
+		domain: 'imserver.com',
+		sendTimeout: 0, //(this.wait+20)*1000
+		
+		useScriptSrcTransport:false,
+		
+		
+		keepAliveTimer:null,
+
+		//status
+		state: "NotReady",
+		transmitState: "Idle",
+
+		protocolPacketQueue: [],
+		outboundQueue: [],
+		outboundRequests: {},
+		inboundQueue: [],
+		deferredRequests: {},
+		matchTypeIdAttribute: {},
+
+		open: function() {
+			this.status = "notReady";
+			this.rid = Math.round(Math.random() * 1000000000);
+			this.protocolPacketQueue = [];
+			this.outboundQueue = [];
+			this.outboundRequests = {};
+			this.inboundQueue = [];
+			this.deferredRequests = {};
+			this.matchTypeIdAttribute = {};
+			
+		
+			this.keepAliveTimer = setTimeout(dojo.hitch(this, "_keepAlive"), 10000);
+			
+			if(this.useScriptSrcTransport){
+				dojox.xmpp.bosh.initialize({
+					iframes: this.hold+1,
+					load: dojo.hitch(this, function(){
+						this._sendLogin();
+					})
+				});
+			} else {
+				this._sendLogin();
+			}
+		},
+		
+		_sendLogin: function() {
+				var rid = this.rid++;
+				var req = {
+					content: this.submitContentType,
+					hold: this.hold,
+					rid: rid,
+					to: this.domain,
+					secure: this.secure,
+					wait: this.wait,
+					"xml:lang": this.lang,
+					"xmpp:version": "1.0",
+					xmlns: dojox.xmpp.xmpp.BODY_NS,
+					"xmlns:xmpp": "urn:xmpp:xbosh"
+				};
+
+				var msg = dojox.xmpp.util.createElement("body", req, true);
+				this.addToOutboundQueue(msg, rid);
+		},
+
+		_sendRestart: function(){
+			var rid = this.rid++;
+			var req = {
+				rid: rid,
+				sid: this.sid,
+				to: this.domain,
+				"xmpp:restart": "true",
+				"xml:lang": this.lang,
+				xmlns: dojox.xmpp.xmpp.BODY_NS,
+				"xmlns:xmpp": "urn:xmpp:xbosh"
+			};
+
+			var msg = dojox.xmpp.util.createElement("body", req, true);
+			this.addToOutboundQueue(msg, rid);
+		},
+		
+		processScriptSrc: function(msg, rid) {
+			//console.log("processScriptSrc::", rid, msg);
+		//	var msgDom = dojox.xml.DomParser.parse(msg);
+			var msgDom = dojox.xml.parser.parse(msg, "text/xml");
+			//console.log("parsed mgs", msgDom);
+			//console.log("Queue", this.outboundQueue);
+			if(msgDom) {
+				this.processDocument(msgDom, rid);
+			} else {
+				//console.log("Recived bad document from server",msg);
+			}
+		},
+		
+		_keepAlive: function(){
+			if (this.state=="wait" || this.isTerminated()) {
+				return;
+			}
+			this._dispatchPacket();
+			this.keepAliveTimer = setTimeout(dojo.hitch(this, "_keepAlive"), 10000);
+		},
+		
+		
+		close: function(protocolMsg){
+
+	
+			var rid = this.rid++;
+			var req = {
+				
+				sid: this.sid,
+				rid: rid,
+				type: "terminate"
+			};
+			var envelope = null;
+
+			if (protocolMsg) {
+				envelope = new dojox.string.Builder(dojox.xmpp.util.createElement("body", req, false));
+				envelope.append(protocolMsg);
+				envelope.append("</body>");
+			} else {
+				envelope = new dojox.string.Builder(dojox.xmpp.util.createElement("body", req, false));
+			}
+
+		//	this.sendXml(envelope,rid);
+			this.addToOutboundQueue(envelope.toString(), rid);
+			this.state=="Terminate";
+		},
+
+		dispatchPacket: function(msg, protocolMatchType, matchId, matchProperty){
+			// summary
+			// Main Packet dispatcher, most calls should be made with this other 
+			// than a few setup calls which use add items to the queue directly 
+			//protocolMatchType, matchId, and matchProperty are optional params
+			//that allow a deferred to be tied to a protocol response instad of the whole
+			//rid
+	
+		//	//console.log("In dispatchPacket ", msg, protocolMatchType, matchId, matchProperty);
+			if (msg){
+				this.protocolPacketQueue.push(msg);	
+			}
+			
+			var def = new dojo.Deferred();
+			//def.rid = req.rid;
+
+			if (protocolMatchType && matchId){
+				def.protocolMatchType = protocolMatchType;
+				def.matchId = matchId;	
+				def.matchProperty = matchProperty || "id";	
+				if(def.matchProperty != "id") {
+					this.matchTypeIdAttribute[protocolMatchType] = def.matchProperty;
+				}
+			}
+
+			this.deferredRequests[def.protocolMatchType + "-" +def.matchId]=def;
+			if(!this.dispatchTimer) {
+				this.dispatchTimer = setTimeout(dojo.hitch(this, "_dispatchPacket"), 600);
+			}
+			return def;	
+		},
+	
+		_dispatchPacket: function(){
+			
+			clearTimeout(this.dispatchTimer);
+			delete this.dispatchTimer;
+			
+			if (!this.sid){
+				console.debug("TransportSession::dispatchPacket() No SID, packet dropped.")
+				return;
+			}
+
+			if (!this.authId){
+				//FIXME according to original nodes, this should wait a little while and try
+				//      again up to three times to see if we get this data.
+				console.debug("TransportSession::dispatchPacket() No authId, packet dropped [FIXME]")
+				return;
+			}
+
+		
+
+			//if there is a pending request with the server, don't poll
+			if (this.transmitState != "error" && (this.protocolPacketQueue.length == 0) && (this.outboundQueue.length > 0)) {
+				return;
+			}
+
+			if (this.state=="wait" || this.isTerminated()) {
+				return;
+			}
+
+			var req = {
+				sid: this.sid,
+				xmlns: dojox.xmpp.xmpp.BODY_NS
+			}
+
+			var envelope
+			if (this.protocolPacketQueue.length > 0){
+				req.rid= this.rid++;
+				envelope = new dojox.string.Builder(dojox.xmpp.util.createElement("body", req, false));
+				envelope.append(this.processProtocolPacketQueue());
+				envelope.append("</body>");
+				delete this.lastPollTime;
+			} else {
+				//console.log("Nothing to send, I'm just polling.");
+				if(this.lastPollTime) {
+					var now = new Date().getTime();
+					if(now - this.lastPollTime < this.polling) {
+						//console.log("Waiting to poll ", this.polling - (now - this.lastPollTime)+10);
+						this.dispatchTimer = setTimeout(dojo.hitch(this, "_dispatchPacket"), this.polling - (now - this.lastPollTime)+10);
+						return;
+					}
+				
+				} 
+				req.rid= this.rid++;
+				this.lastPollTime = new Date().getTime();
+				envelope = new dojox.string.Builder(dojox.xmpp.util.createElement("body", req, true));
+
+			}
+
+		
+			this.addToOutboundQueue(envelope.toString(),req.rid);
+
+		},
+
+		redispatchPacket: function(rid){
+			var env = this.outboundRequests[rid];
+			this.sendXml(env, rid);
+		},
+
+		addToOutboundQueue: function(msg, rid){
+			this.outboundQueue.push({msg: msg,rid: rid});
+			this.outboundRequests[rid]=msg;
+			this.sendXml(msg, rid);
+		},
+
+		removeFromOutboundQueue: function(rid){
+			for(var i=0; i<this.outboundQueue.length;i++){
+				if (rid == this.outboundQueue[i]["rid"]){
+					this.outboundQueue.splice(i, 1);
+					break;
+				}
+			}
+			delete this.outboundRequests[rid];
+		},
+
+		processProtocolPacketQueue: function(){
+			var packets = new dojox.string.Builder();
+			for(var i=0; i<this.protocolPacketQueue.length;i++){
+				packets.append(this.protocolPacketQueue[i]);
+			}
+			this.protocolPacketQueue=[];
+			return packets.toString();
+		},
+
+		sendXml: function(message, rid){
+			if(this.isTerminated()) {
+				return false;
+			}
+			//console.log("TransportSession::sendXml()"+ new Date().getTime() + " RID: ", rid, " MSG: ", message);
+			this.transmitState = "transmitting";
+			var def = null;
+			if(this.useScriptSrcTransport) { 
+				//console.log("using script src to transmit");
+				def = dojox.xmpp.bosh.get({
+					rid: rid,
+					url: this.serviceUrl+'?'+encodeURIComponent(message),
+					error: dojo.hitch(this, function(res, io){
+						this.setState("Terminate", "error");
+						return false;
+					}),
+					timeout: this.sendTimeout
+				});
+			} else {
+				def = dojo.rawXhrPost({
+					contentType: "text/xml",
+					url: this.serviceUrl,
+					postData: message,
+					handleAs: "xml",
+					error: dojo.hitch(this, function(res, io) {
+						////console.log("foo", res, io.xhr.responseXML, io.xhr.status);
+						return this.processError(io.xhr.responseXML, io.xhr.status , rid);
+					}),
+					timeout: this.sendTimeout
+				});
+			}
+			//process the result document 
+			def.addCallback(this, function(res){
+				return this.processDocument(res, rid);
+			});
+			return def;
+		},
+
+		processDocument: function(doc, rid){
+			if(this.isTerminated() || !doc.firstChild) {
+				return false;
+			}
+			//console.log("TransportSession:processDocument() ", doc, rid);
+			this.transmitState = "idle";
+
+			var body = doc.firstChild;
+			if (body.nodeName != 'body'){
+				//console.log("TransportSession::processDocument() firstChild is not <body> element ", doc, " RID: ", rid);
+			}
+
+			if (this.outboundQueue.length<1){return false;}
+
+			var expectedId = this.outboundQueue[0]["rid"];
+			//console.log("expectedId", expectedId);
+			if (rid==expectedId){
+				this.removeFromOutboundQueue(rid);	
+				this.processResponse(body, rid);
+				this.processInboundQueue();	
+			}else{
+				//console.log("TransportSession::processDocument() rid: ", rid, " expected: ", expectedId);
+				var gap = rid-expectedId;
+			
+				if (gap < this.hold + 2){
+					this.addToInboundQueue(doc,rid);	
+				}else{
+					//console.log("TransportSession::processDocument() RID is outside of the expected response window");
+				}
+			}
+			return doc;	
+		},
+
+		processInboundQueue: function(){
+			while (this.inboundQueue.length > 0) {
+				var item = this.inboundQueue.shift();
+				this.processDocument(item["doc"], item["rid"]);
+			}
+		},
+
+		addToInboundQueue: function(doc,rid){
+			for (var i=0; i<this.inboundQueue.length;i++){
+				if (rid < this.inboundQueue[i]["rid"]){continue;}
+				this.inboundQueue.splice(i,0,{doc: doc, rid: rid});	
+			}
+		},
+
+		processResponse: function(body,rid){
+			////console.log("TransportSession:processResponse() ", body, " RID: ", rid);
+
+			if (body.getAttribute("type")=='terminate'){
+				var reasonNode = body.firstChild.firstChild;
+				var errorMessage = "";
+					if(reasonNode.nodeName == "conflict") {
+						errorMessage = "conflict"
+					}
+				this.setState("Terminate", errorMessage);
+	
+				return;
+			}
+
+			if ((this.state != 'Ready')&&(this.state != 'Terminate')) {
+				var sid=body.getAttribute("sid");
+				if (sid){
+					this.sid=sid;
+				} else {
+					throw new Error("No sid returned during xmpp session startup");
+				}
+
+				this.authId = body.getAttribute("authid");	
+				if (this.authId == "") {
+					if (this.authRetries-- < 1) {
+						console.error("Unable to obtain Authorization ID");
+						this.terminateSession();	
+					}
+				}
+				this.wait= body.getAttribute("wait");	
+				if( body.getAttribute("polling")){
+					this.polling= parseInt(body.getAttribute("polling"))*1000;
+				}
+			
+				//console.log("Polling value ", this.polling);
+				this.inactivity = body.getAttribute("inactivity");	
+				this.setState("Ready");
+			}
+
+			dojo.forEach(body.childNodes, function(node){
+				this.processProtocolResponse(node, rid);
+			}, this);
+
+			//need to make sure, since if you use sendXml directly instead of using
+			//dispatch packets, there wont' be a call back function here
+			//normally the deferred will get fired by a child message at the protocol level
+			//but if it hasn't fired by now, go ahead and fire it with the full body
+			/*if (this.deferredRequests[rid] && this.deferredRequests[rid].fired==-1){
+				this.deferredRequests[rid].callback(body);
+			}*/
+
+			//delete from the list of outstanding requests
+			//delete this.deferredRequests[rid];
+
+			if (this.transmitState == "idle"){
+				this.dispatchPacket();
+			}
+		},
+
+
+		processProtocolResponse: function(msg, rid){
+			//summary
+			//process the individual protocol messages and if there
+			//is a matching set of protocolMatchType, matchId, and matchPropery
+			//fire off the deferred
+
+			this.onProcessProtocolResponse(msg);
+			var key = msg.nodeName + "-" +msg.getAttribute("id");
+			var def = this.deferredRequests[key];
+			if (def){
+				def.callback(msg);
+				delete this.deferredRequests[key];
+			}
+		},
+
+		setState: function(state, message){
+			if (this.state != state) {
+				if (this["on"+state]){
+					this["on"+state](state, this.state, message);
+				}
+				this.state=state;
+			}
+		},
+		
+		isTerminated: function() {
+			
+			return this.state=="Terminate";
+		},
+
+		processError: function(err, httpStatusCode,rid){
+			//console.log("Processing server error ", err, httpStatusCode,rid);
+			if(this.isTerminated()) {
+				return false;
+			}
+			
+			
+			if(httpStatusCode != 200) {
+				if(httpStatusCode >= 400 && httpStatusCode < 500){
+					/* Any status code between 400 and 500 should terminate
+					 * the connection */
+					this.setState("Terminate", errorMessage);
+					return false;
+				}else{
+					this.removeFromOutboundQueue(rid);	
+					setTimeout(dojo.hitch(this, function(){ this.dispatchPacket(); }), 200);	
+					return true;
+				}
+				return false;
+			}
+			
+			if (err && err.dojoType && err.dojoType=="timeout"){
+				//console.log("Wait timeout");
+			}
+			
+			this.removeFromOutboundQueue(rid);	
+			//FIXME conditional processing if request will be needed based on type of error.
+			if(err && err.firstChild) {
+			//console.log("Error ", err.firstChild.getAttribute("type") + " status code " + httpStatusCode);
+			
+				if (err.firstChild.getAttribute("type")=='terminate'){
+					var reasonNode = err.firstChild.firstChild;
+					var errorMessage = "";
+					if(reasonNode && reasonNode.nodeName == "conflict") {
+						errorMessage = "conflict"
+					}
+					this.setState("Terminate", errorMessage);
+					return false;
+				}			
+			}
+			this.transmitState = "error";
+			setTimeout(dojo.hitch(this, function(){ this.dispatchPacket(); }), 200);	
+			//console.log("Error: ", arguments);
+			return true;
+		},
+
+		//events
+		onTerminate: function(newState, oldState, message){ },
+		onProcessProtocolResponse: function(msg){},
+		onReady: function(newState, oldState){}
 });
-return def;
-},processDocument:function(doc,rid){
-if(this.isTerminated()||!doc.firstChild){
-return false;
-}
-this.transmitState="idle";
-var _16=doc.firstChild;
-if(_16.nodeName!="body"){
-}
-if(this.outboundQueue.length<1){
-return false;
-}
-var _17=this.outboundQueue[0]["rid"];
-if(rid==_17){
-this.removeFromOutboundQueue(rid);
-this.processResponse(_16,rid);
-this.processInboundQueue();
-}else{
-var gap=rid-_17;
-if(gap<this.hold+2){
-this.addToInboundQueue(doc,rid);
-}else{
-}
-}
-return doc;
-},processInboundQueue:function(){
-while(this.inboundQueue.length>0){
-var _18=this.inboundQueue.shift();
-this.processDocument(_18["doc"],_18["rid"]);
-}
-},addToInboundQueue:function(doc,rid){
-for(var i=0;i<this.inboundQueue.length;i++){
-if(rid<this.inboundQueue[i]["rid"]){
-continue;
-}
-this.inboundQueue.splice(i,0,{doc:doc,rid:rid});
-}
-},processResponse:function(_19,rid){
-if(_19.getAttribute("type")=="terminate"){
-var _1a=_19.firstChild.firstChild;
-var _1b="";
-if(_1a.nodeName=="conflict"){
-_1b="conflict";
-}
-this.setState("Terminate",_1b);
-return;
-}
-if((this.state!="Ready")&&(this.state!="Terminate")){
-var sid=_19.getAttribute("sid");
-if(sid){
-this.sid=sid;
-}else{
-throw new Error("No sid returned during xmpp session startup");
-}
-this.authId=_19.getAttribute("authid");
-if(this.authId==""){
-if(this.authRetries--<1){
-console.error("Unable to obtain Authorization ID");
-this.terminateSession();
-}
-}
-this.wait=_19.getAttribute("wait");
-if(_19.getAttribute("polling")){
-this.polling=parseInt(_19.getAttribute("polling"))*1000;
-}
-this.inactivity=_19.getAttribute("inactivity");
-this.setState("Ready");
-}
-dojo.forEach(_19.childNodes,function(_1c){
-this.processProtocolResponse(_1c,rid);
-},this);
-if(this.transmitState=="idle"){
-this.dispatchPacket();
-}
-},processProtocolResponse:function(msg,rid){
-this.onProcessProtocolResponse(msg);
-var key=msg.nodeName+"-"+msg.getAttribute("id");
-var def=this.deferredRequests[key];
-if(def){
-def.callback(msg);
-delete this.deferredRequests[key];
-}
-},setState:function(_1d,_1e){
-if(this.state!=_1d){
-if(this["on"+_1d]){
-this["on"+_1d](_1d,this.state,_1e);
-}
-this.state=_1d;
-}
-},isTerminated:function(){
-return this.state=="Terminate";
-},processError:function(err,_1f,rid){
-if(this.isTerminated()){
-return false;
-}
-if(_1f!=200){
-if(_1f>=400&&_1f<500){
-this.setState("Terminate",_20);
-return false;
-}else{
-this.removeFromOutboundQueue(rid);
-setTimeout(dojo.hitch(this,function(){
-this.dispatchPacket();
-}),200);
-return true;
-}
-return false;
-}
-if(err&&err.dojoType&&err.dojoType=="timeout"){
-}
-this.removeFromOutboundQueue(rid);
-if(err&&err.firstChild){
-if(err.firstChild.getAttribute("type")=="terminate"){
-var _21=err.firstChild.firstChild;
-var _20="";
-if(_21&&_21.nodeName=="conflict"){
-_20="conflict";
-}
-this.setState("Terminate",_20);
-return false;
-}
-}
-this.transmitState="error";
-setTimeout(dojo.hitch(this,function(){
-this.dispatchPacket();
-}),200);
-return true;
-},onTerminate:function(_22,_23,_24){
-},onProcessProtocolResponse:function(msg){
-},onReady:function(_25,_26){
-}});
-}
diff --git a/dojox/xmpp/UserService.js b/dojox/xmpp/UserService.js
index ffcc744..9e27972 100644
--- a/dojox/xmpp/UserService.js
+++ b/dojox/xmpp/UserService.js
@@ -1,76 +1,93 @@
-/*
-	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
-*/
+dojo.provide("dojox.xmpp.UserService");
 
+dojo.declare("dojox.xmpp.UserService", null, {
+	constructor: function(xmppService){
+		this.session= xmppService;
+	},
 
-if(!dojo._hasResource["dojox.xmpp.UserService"]){
-dojo._hasResource["dojox.xmpp.UserService"]=true;
-dojo.provide("dojox.xmpp.UserService");
-dojo.declare("dojox.xmpp.UserService",null,{constructor:function(_1){
-this.session=_1;
-},getPersonalProfile:function(){
-var _2={id:this.session.getNextIqId(),type:"get"};
-var _3=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_2,false));
-_3.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:private"},false));
-_3.append(dojox.xmpp.util.createElement("sunmsgr",{xmlsns:"sun:xmpp:properties"},true));
-_3.append("</query></iq>");
-var _4=this.session.dispatchPacket(_3.toString(),"iq",_2.id);
-_4.addCallback(this,"_onGetPersonalProfile");
-},setPersonalProfile:function(_5){
-var _6={id:this.session.getNextIqId(),type:"set"};
-var _7=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_6,false));
-_7.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:private"},false));
-_7.append(dojox.xmpp.util.createElement("sunmsgr",{xmlsns:"sun:xmpp:properties"},false));
-for(var _8 in _5){
-_7.append(dojox.xmpp.util.createElement("property",{name:_8},false));
-_7.append(dojox.xmpp.util.createElement("value",{},false));
-_7.append(_5[_8]);
-_7.append("</value></props>");
-}
-_7.append("</sunmsgr></query></iq>");
-var _9=this.session.dispatchPacket(_7.toString(),"iq",_6.id);
-_9.addCallback(this,"_onSetPersonalProfile");
-},_onSetPersonalProfile:function(_a){
-if(_a.getAttribute("type")=="result"){
-this.onSetPersonalProfile(_a.getAttribute("id"));
-}else{
-if(_a.getAttribute("type")=="error"){
-var _b=this.session.processXmppError(_a);
-this.onSetPersonalProfileFailure(_b);
-}
-}
-},onSetPersonalProfile:function(id){
-},onSetPersonalProfileFailure:function(_c){
-},_onGetPersonalProfile:function(_d){
-if(_d.getAttribute("type")=="result"){
-var _e={};
-if(_d.hasChildNodes()){
-var _f=_d.firstChild;
-if((_f.nodeName=="query")&&(_f.getAttribute("xmlns")=="jabber:iq:private")){
-var _10=_f.firstChild;
-if((_10.nodeName=="query")&&(_10.getAttributes("xmlns")=="sun:xmpp:properties")){
-for(var i=0;i<_10.childNodes.length;i++){
-var n=_10.childNodes[i];
-if(n.nodeName=="property"){
-var _11=n.getAttribute("name");
-var val=n.firstChild||"";
-_e[_11]=val;
-}
-}
-}
-}
-this.onGetPersonalProfile(_e);
-}
-}else{
-if(_d.getAttribute("type")=="error"){
-var err=this.session.processXmppError(_d);
-this.onGetPersonalProfileFailure(err);
-}
-}
-return _d;
-},onGetPersonalProfile:function(_12){
-},onGetPersonalProfileFailure:function(err){
-}});
-}
+	getPersonalProfile: function(){
+		var req={
+			id: this.session.getNextIqId(),
+			type: 'get'
+		}
+		var request = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",req,false));
+		request.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:private"},false));
+		request.append(dojox.xmpp.util.createElement("sunmsgr",{xmlsns:'sun:xmpp:properties'},true));
+		request.append("</query></iq>");
+
+		var def = this.session.dispatchPacket(request.toString(),"iq",req.id);
+		def.addCallback(this, "_onGetPersonalProfile");
+	},
+
+	setPersonalProfile: function(props){
+		var req={
+			id: this.session.getNextIqId(),
+			type: 'set'
+		}			
+		
+		var request = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",req,false));
+		request.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:private"},false));
+		request.append(dojox.xmpp.util.createElement("sunmsgr",{xmlsns:'sun:xmpp:properties'},false));
+
+		for (var key in props){
+			request.append(dojox.xmpp.util.createElement("property",{name: key},false));
+			request.append(dojox.xmpp.util.createElement("value",{},false));
+			request.append(props[key]);
+			request.append("</value></props>");
+		}
+		
+		request.append("</sunmsgr></query></iq>");
+
+		var def = this.session.dispatchPacket(request.toString(), "iq", req.id);
+		def.addCallback(this, "_onSetPersonalProfile");
+	},
+
+	_onSetPersonalProfile: function(response){
+		if(response.getAttribute('type')=='result'){
+			this.onSetPersonalProfile(response.getAttribute('id'));
+		}else if(response.getAttribute('type')=='error'){
+			var err = this.session.processXmppError(response);
+			this.onSetPersonalProfileFailure(err);
+		}
+	},
+
+	onSetPersonalProfile: function(id){},
+	onSetPersonalProfileFailure: function(err){},
+
+	_onGetPersonalProfile: function(profile){
+		if (profile.getAttribute('type')=='result'){
+			var props = {};
+
+			if (profile.hasChildNodes()){
+				var queryNode = profile.firstChild;
+				if ((queryNode.nodeName=="query")&&(queryNode.getAttribute('xmlns')=='jabber:iq:private')){
+					var sunNode = queryNode.firstChild;
+					if ((sunNode.nodeName=='query')&&(sunNode.getAttributes('xmlns')=='sun:xmpp:properties')){
+						for (var i=0; i<sunNode.childNodes.length;i++){
+							var n = sunNode.childNodes[i];
+							if(n.nodeName == 'property'){
+								var name = n.getAttribute('name');
+								var val = n.firstChild || "";
+								props[name]=val;
+							}
+						}
+					}
+				}
+				this.onGetPersonalProfile(props);
+			}
+		}else if (profile.getAttribute('type')=='error'){
+			var err = this.session.processXmppError(profile);
+			this.onGetPersonalProfileFailure(err);
+		}
+
+		return profile;
+	},
+
+	onGetPersonalProfile: function(profile){
+		//console.log("UserService::onGetPersonalProfile() ", profile);
+	},
+
+	onGetPersonalProfileFailure: function(err){
+		//console.log("UserService::onGetPersonalProfileFailure() ", err);
+	}
+});
diff --git a/dojox/xmpp/bosh.js b/dojox/xmpp/bosh.js
index 98284bb..b7e3176 100644
--- a/dojox/xmpp/bosh.js
+++ b/dojox/xmpp/bosh.js
@@ -1,132 +1,238 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.xmpp.bosh"]){
-dojo._hasResource["dojox.xmpp.bosh"]=true;
 dojo.provide("dojox.xmpp.bosh");
+
 dojo.require("dojo.io.script");
 dojo.require("dojo.io.iframe");
 dojo.require("dojox.xml.parser");
-dojox.xmpp.bosh={transportIframes:[],initialize:function(_1){
-this.transportIframes=[];
-var _2=dojox._scopeName+".xmpp.bosh";
-var c=dojo.connect(dojo.getObject(_2),"_iframeOnload",this,function(_3){
-if(_3==0){
-_1.load();
-dojo.disconnect(c);
-}
+
+/*=====
+dojo.declare("dojox.xmpp.bosh.__initArgs", null, {
+	constructor: function(){
+		//	summary:
+		//		The arguments passed to dojox.xmpp.bosh.initialize
+		//	iframes:
+		//		The number of iframes to use for transmission
+		//	load:
+		//		The function called when the first iframe is
+		//		loaded.  Generally used to signal when to send
+		//		login information
+		this.iframes = iframes;
+		this.load = load;
+	}
+});
+dojo.declare("dojox.xmpp.bosh.__ioArgs", dojo.__IoArgs, {
+	constructor: function(){
+		//	summary:
+		//		All the properties described in the dojo.__ioArgs type, apply to this
+		//		type as well, EXCEPT "handleAs". It is not applicable to
+		//		dojox.xmpp.bosh.get() calls, since it is implied that the
+		//		return will be a string of XML.
+		//	rid:
+		//		The rid of the message being sent.
+		this.rid = rid;
+	}
 });
-for(var i=0;i<_1.iframes;i++){
-var _4="xmpp-transport-"+i;
-var _5=dojo.byId("xmpp-transport-"+i);
-if(_5){
-if(window[_4]){
-window[_4]=null;
-}
-if(window.frames[_4]){
-window.frames[_4]=null;
-}
-dojo.destroy(_5);
-}
-_5=dojo.io.iframe.create("xmpp-transport-"+i,_2+"._iframeOnload("+i+");");
-this.transportIframes.push(_5);
-}
-},_iframeOnload:function(_6){
-var _7=dojo.io.iframe.doc(dojo.byId("xmpp-transport-"+_6));
-_7.write("<script>var isLoaded=true; var rid=0; var transmiting=false; function _BOSH_(msg) { transmiting=false; parent.dojox.xmpp.bosh.handle(msg, rid); } </script>");
-},findOpenIframe:function(){
-for(var i=0;i<this.transportIframes.length;i++){
-var _8=this.transportIframes[i];
-var _9=_8.contentWindow;
-if(_9.isLoaded&&!_9.transmiting){
-return _8;
-}
-}
-return false;
-},handle:function(_a,_b){
-var _c=this["rid"+_b];
-var _d=dojox.xml.parser.parse(_a,"text/xml");
-if(_d){
-_c.ioArgs.xmppMessage=_d;
-}else{
-_c.errback(new Error("Recieved bad document from server: "+_a));
-}
-},get:function(_e){
-var _f=this.findOpenIframe();
-var _10=dojo.io.iframe.doc(_f);
-_e.frameDoc=_10;
-var dfd=this._makeScriptDeferred(_e);
-var _11=dfd.ioArgs;
-_f.contentWindow.rid=_11.rid;
-_f.contentWindow.transmiting=true;
-dojo._ioAddQueryToUrl(_11);
-dojo._ioNotifyStart(dfd);
-dojo.io.script.attach(_11.id,_11.url,_10);
-dojo._ioWatch(dfd,this._validCheck,this._ioCheck,this._resHandle);
-return dfd;
-},remove:function(id,_12){
-dojo.destroy(dojo.byId(id,_12));
-if(this[id]){
-delete this[id];
-}
-},_makeScriptDeferred:function(_13){
-var dfd=dojo._ioSetArgs(_13,this._deferredCancel,this._deferredOk,this._deferredError);
-var _14=dfd.ioArgs;
-_14.id="rid"+_13.rid;
-_14.rid=_13.rid;
-_14.canDelete=true;
-_14.frameDoc=_13.frameDoc;
-this[_14.id]=dfd;
-return dfd;
-},_deferredCancel:function(dfd){
-dfd.canceled=true;
-if(dfd.ioArgs.canDelete){
-dojox.xmpp.bosh._addDeadScript(dfd.ioArgs);
-}
-},_deferredOk:function(dfd){
-var _15=dfd.ioArgs;
-if(_15.canDelete){
-dojox.xmpp.bosh._addDeadScript(_15);
-}
-return _15.xmppMessage||_15;
-},_deferredError:function(_16,dfd){
-if(dfd.ioArgs.canDelete){
-if(_16.dojoType=="timeout"){
-dojox.xmpp.bosh.remove(dfd.ioArgs.id,dfd.ioArgs.frameDoc);
-}else{
-dojox.xmpp.bosh._addDeadScript(dfd.ioArgs);
-}
-}
-return _16;
-},_deadScripts:[],_addDeadScript:function(_17){
-dojox.xmpp.bosh._deadScripts.push({id:_17.id,frameDoc:_17.frameDoc});
-_17.frameDoc=null;
-},_validCheck:function(dfd){
-var _18=dojox.xmpp.bosh;
-var _19=_18._deadScripts;
-if(_19&&_19.length>0){
-for(var i=0;i<_19.length;i++){
-_18.remove(_19[i].id,_19[i].frameDoc);
-_19[i].frameDoc=null;
-}
-dojox.xmpp.bosh._deadScripts=[];
-}
-return true;
-},_ioCheck:function(dfd){
-var _1a=dfd.ioArgs;
-if(_1a.xmppMessage){
-return true;
-}
-return false;
-},_resHandle:function(dfd){
-if(dojox.xmpp.bosh._ioCheck(dfd)){
-dfd.callback(dfd);
-}else{
-dfd.errback(new Error("inconceivable dojox.xmpp.bosh._resHandle error"));
-}
-}};
-}
+=====*/
+
+dojox.xmpp.bosh = {
+	transportIframes: [],
+	initialize: function(/*dojox.xmpp.bosh.__initArgs*/ args){
+		this.transportIframes = [];
+
+		var scopedObj = dojox._scopeName + '.xmpp.bosh';
+
+		var c = dojo.connect(dojo.getObject(scopedObj), '_iframeOnload', this, function(index){
+			if(index==0){
+				args.load();
+				dojo.disconnect(c);
+			}
+		});
+
+		for(var i = 0; i < args.iframes; i++){
+			var fname = 'xmpp-transport-'+i;
+			var iframe = dojo.byId('xmpp-transport-'+i);
+			if(iframe){
+				// we have to clean up the dojo.io.iframe references
+				if(window[fname]){ window[fname] = null; }
+				if(window.frames[fname]){ window.frames[fname] = null; }
+				dojo.destroy(iframe);
+			}
+			iframe = dojo.io.iframe.create("xmpp-transport-" + i, scopedObj + "._iframeOnload("+i+");" );
+			this.transportIframes.push(iframe);
+		}
+	},
+
+	_iframeOnload: function(index){
+		var doc = dojo.io.iframe.doc(dojo.byId("xmpp-transport-" + index));
+		doc.write("<script>var isLoaded=true; var rid=0; var transmiting=false; function _BOSH_(msg) { transmiting=false; parent.dojox.xmpp.bosh.handle(msg, rid); } </script>");
+	},
+
+	findOpenIframe: function() {
+		for(var i = 0; i < this.transportIframes.length; i++) {
+			var iframe = this.transportIframes[i];
+			var win = iframe.contentWindow;
+			//console.log("Open transport?", win, win.isLoaded, win.transmiting);
+			
+			if(win.isLoaded && !win.transmiting) {
+				return iframe;
+			}
+		}
+		return false;
+	},
+
+	handle: function(msg, rid){
+		var dfd = this['rid'+rid];
+
+		var xmlMsg = dojox.xml.parser.parse(msg, 'text/xml');
+
+		if(xmlMsg){
+			dfd.ioArgs.xmppMessage = xmlMsg;
+		}else{
+			dfd.errback(new Error("Recieved bad document from server: " + msg));
+		}
+	},
+
+	get: function(/*dojox.xmpp.bosh.__ioArgs*/args){
+		//	summary:
+		//		sends a get request using a dynamically created script tag.
+		var iframe = this.findOpenIframe();
+		var iframeDoc = dojo.io.iframe.doc(iframe);
+
+		args.frameDoc = iframeDoc;
+
+		var dfd = this._makeScriptDeferred(args);
+		var ioArgs = dfd.ioArgs;
+
+		iframe.contentWindow.rid=ioArgs.rid;
+		iframe.contentWindow.transmiting=true;
+
+		dojo._ioAddQueryToUrl(ioArgs);
+		dojo._ioNotifyStart(dfd);
+
+		dojo.io.script.attach(ioArgs.id, ioArgs.url, iframeDoc);
+
+		dojo._ioWatch(dfd, this._validCheck, this._ioCheck, this._resHandle);
+		return dfd;
+	},
+
+	remove: function(/*String*/id, /*Document?*/frameDocument){
+		//summary: removes the script element with the given id, from the given frameDocument.
+		//If no frameDocument is passed, the current document is used.
+		dojo.destroy(dojo.byId(id, frameDocument));
+
+		//Remove the BOSH callback on dojox.xmpp.bosh, if it exists.
+		if(this[id]){
+			delete this[id];
+		}
+	},
+
+	_makeScriptDeferred: function(/*Object*/args){
+		//summary: 
+		//		sets up a Deferred object for an IO request.
+		var dfd = dojo._ioSetArgs(args, this._deferredCancel, this._deferredOk, this._deferredError);
+
+		var ioArgs = dfd.ioArgs;
+
+		ioArgs.id = 'rid' + args.rid;
+		ioArgs.rid = args.rid;
+		ioArgs.canDelete = true;
+		ioArgs.frameDoc = args.frameDoc;
+
+		this[ioArgs.id] = dfd;
+
+		return dfd; // dojo.Deferred
+	},
+
+	_deferredCancel: function(/*Deferred*/dfd){
+		//summary: canceller function for dojo._ioSetArgs call.
+
+		//DO NOT use "this" and expect it to be dojox.xmpp.bosh.
+		dfd.canceled = true;
+		if(dfd.ioArgs.canDelete){
+			dojox.xmpp.bosh._addDeadScript(dfd.ioArgs);
+		}
+	},
+
+	_deferredOk: function(/*Deferred*/dfd){
+		//summary: okHandler function for dojo._ioSetArgs call.
+
+		//DO NOT use "this" and expect it to be dojo.xmpp.bosh.
+		var ioArgs = dfd.ioArgs;
+
+		//Add script to list of things that can be removed.		
+		if(ioArgs.canDelete){
+			dojox.xmpp.bosh._addDeadScript(ioArgs);
+		}
+
+		//Favor JSONP responses, script load events then lastly ioArgs.
+		//The ioArgs are goofy, but cannot return the dfd since that stops
+		//the callback chain in Deferred. The return value is not that important
+		//in that case, probably a checkString case.
+		return ioArgs.xmppMessage || ioArgs;
+	},
+
+	_deferredError: function(/*Error*/error, /*Deferred*/dfd){
+		//summary: errHandler function for dojo._ioSetArgs call.
+
+		if(dfd.ioArgs.canDelete){
+			//DO NOT use "this" and expect it to be dojox.xmpp.bosh
+			if(error.dojoType == "timeout"){
+				//For timeouts, remove the script element immediately to
+				//avoid a response from it coming back later and causing trouble.
+				dojox.xmpp.bosh.remove(dfd.ioArgs.id, dfd.ioArgs.frameDoc);
+			}else{
+				dojox.xmpp.bosh._addDeadScript(dfd.ioArgs);
+			}
+		}
+		return error;
+	},
+
+	_deadScripts: [],
+	_addDeadScript: function(/*Object*/ioArgs){
+		//summary: sets up an entry in the deadScripts array.
+		dojox.xmpp.bosh._deadScripts.push({id: ioArgs.id, frameDoc: ioArgs.frameDoc});
+		//Being extra paranoid about leaks:
+		ioArgs.frameDoc = null;
+	},
+
+	_validCheck: function(/*Deferred*/dfd){
+		//summary: inflight check function to see if dfd is still valid.
+
+		//Do script cleanup here. We wait for one inflight pass
+		//to make sure we don't get any weird things by trying to remove a script
+		//tag that is part of the call chain (IE 6 has been known to
+		//crash in that case).
+		var _self = dojox.xmpp.bosh;
+		var deadScripts = _self._deadScripts;
+		if(deadScripts && deadScripts.length > 0){
+			for(var i = 0; i < deadScripts.length; i++){
+				//Remove the script tag
+				_self.remove(deadScripts[i].id, deadScripts[i].frameDoc);
+				deadScripts[i].frameDoc = null;
+			}
+			dojox.xmpp.bosh._deadScripts = [];
+		}
+
+		return true;
+	},
+
+	_ioCheck: function(/*Deferred*/dfd){
+		//summary: inflight check function to see if IO finished.
+		var ioArgs = dfd.ioArgs;
+		//Check for returned message
+		if(ioArgs.xmppMessage){
+			return true;
+		}
+		return false;
+	},
+
+	_resHandle: function(/*Deferred*/dfd){
+		//summary: inflight function to handle a completed response.
+		if(dojox.xmpp.bosh._ioCheck(dfd)){
+			dfd.callback(dfd);
+		}else{
+			//This path should never happen since the only way we can get
+			//to _resHandle is if _ioCheck is true.
+			dfd.errback(new Error("inconceivable dojox.xmpp.bosh._resHandle error"));
+		}
+	}
+};
diff --git a/dojox/xmpp/sasl.js b/dojox/xmpp/sasl.js
index e5a3724..790d680 100644
--- a/dojox/xmpp/sasl.js
+++ b/dojox/xmpp/sasl.js
@@ -1,119 +1,182 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.xmpp.sasl"]){
-dojo._hasResource["dojox.xmpp.sasl"]=true;
 dojo.provide("dojox.xmpp.sasl");
 dojo.require("dojox.xmpp.util");
+
 dojo.require("dojo.AdapterRegistry");
 dojo.require("dojox.encoding.digests.MD5");
-dojox.xmpp.sasl.saslNS="urn:ietf:params:xml:ns:xmpp-sasl";
-dojo.declare("dojox.xmpp.sasl._Base",null,{mechanism:null,closeAuthTag:true,constructor:function(_1){
-this.session=_1;
-this.startAuth();
-},startAuth:function(){
-var _2=new dojox.string.Builder(dojox.xmpp.util.createElement("auth",{xmlns:dojox.xmpp.sasl.saslNS,mechanism:this.mechanism},this.closeAuthTag));
-this.appendToAuth(_2);
-this.session.dispatchPacket(_2.toString());
-},appendToAuth:function(_3){
-},onChallenge:function(_4){
-if(!this.first_challenge){
-this.first_challenge=true;
-this.onFirstChallenge(_4);
-}else{
-this.onSecondChallenge(_4);
-}
-},onFirstChallenge:function(){
-},onSecondChallenge:function(){
-},onSuccess:function(){
-this.session.sendRestart();
-}});
-dojo.declare("dojox.xmpp.sasl.SunWebClientAuth",dojox.xmpp.sasl._Base,{mechanism:"SUN-COMMS-CLIENT-PROXY-AUTH"});
-dojo.declare("dojox.xmpp.sasl.Plain",dojox.xmpp.sasl._Base,{mechanism:"PLAIN",closeAuthTag:false,appendToAuth:function(_5){
-var id=this.session.jid;
-var _6=this.session.jid.indexOf("@");
-if(_6!=-1){
-id=this.session.jid.substring(0,_6);
-}
-var _7=this.session.jid+"\x00"+id+"\x00"+this.session.password;
-_7=dojox.xmpp.util.Base64.encode(_7);
-_5.append(_7);
-_5.append("</auth>");
-delete this.session.password;
-}});
-dojo.declare("dojox.xmpp.sasl.DigestMD5",dojox.xmpp.sasl._Base,{mechanism:"DIGEST-MD5",onFirstChallenge:function(_8){
-var _9=dojox.encoding.digests;
-var _a=dojox.encoding.digests.outputTypes;
-var _b=function(n){
-return _9.MD5(n,_a.Hex);
-};
-var H=function(s){
-return _9.MD5(s,_a.String);
-};
-var _c=dojox.xmpp.util.Base64.decode(_8.firstChild.nodeValue);
-var ch={realm:"",nonce:"",qop:"auth",maxbuf:65536};
-_c.replace(/([a-z]+)=([^,]+)/g,function(t,k,v){
-v=v.replace(/^"(.+)"$/,"$1");
-ch[k]=v;
+
+dojox.xmpp.sasl.saslNS = "urn:ietf:params:xml:ns:xmpp-sasl";
+
+dojo.declare("dojox.xmpp.sasl._Base", null, {
+	mechanism: null,
+	closeAuthTag: true,
+
+	constructor: function(session){
+		this.session = session;
+
+		this.startAuth();
+	},
+	startAuth: function(){
+		var auth = new dojox.string.Builder(dojox.xmpp.util.createElement("auth", {
+			xmlns: dojox.xmpp.sasl.saslNS,
+			mechanism: this.mechanism
+		}, this.closeAuthTag));
+		this.appendToAuth(auth);
+		this.session.dispatchPacket(auth.toString());
+	},
+	appendToAuth: function(auth){},
+	onChallenge: function(msg){
+		if(!this.first_challenge){
+			this.first_challenge = true;
+			this.onFirstChallenge(msg);
+		}else{
+			this.onSecondChallenge(msg);
+		}
+	},
+	onFirstChallenge: function(){},
+	onSecondChallenge: function(){},
+	onSuccess: function(){
+		this.session.sendRestart();
+	}
 });
-var _d="";
-switch(ch.qop){
-case "auth-int":
-case "auth-conf":
-_d=":00000000000000000000000000000000";
-case "auth":
-break;
-default:
-return false;
-}
-var _e=_9.MD5(Math.random()*1234567890,_a.Hex);
-var _f="xmpp/"+this.session.domain;
-var _10=this.session.jid;
-var _11=this.session.jid.indexOf("@");
-if(_11!=-1){
-_10=this.session.jid.substring(0,_11);
-}
-_10=dojox.xmpp.util.encodeJid(_10);
-var A1=new dojox.string.Builder();
-A1.append(H(_10+":"+ch.realm+":"+this.session.password),":",ch.nonce+":"+_e);
-delete this.session.password;
-var _12=":"+_f+_d;
-var A2="AUTHENTICATE"+_12;
-var _13=new dojox.string.Builder();
-_13.append(_b(A1.toString()),":",ch.nonce,":00000001:",_e,":",ch.qop,":");
-var ret=new dojox.string.Builder();
-ret.append("username=\"",_10,"\",","realm=\"",ch.realm,"\",","nonce=",ch.nonce,",","cnonce=\"",_e,"\",","nc=\"00000001\",qop=\"",ch.qop,"\",digest-uri=\"",_f,"\",","response=\"",_b(_13.toString()+_b(A2)),"\",charset=\"utf-8\"");
-var _14=new dojox.string.Builder(dojox.xmpp.util.createElement("response",{xmlns:dojox.xmpp.xmpp.SASL_NS},false));
-_14.append(dojox.xmpp.util.Base64.encode(ret.toString()));
-_14.append("</response>");
-this.rspauth=_b(_13.toString()+_b(_12));
-this.session.dispatchPacket(_14.toString());
-},onSecondChallenge:function(msg){
-var _15=dojox.xmpp.util.Base64.decode(msg.firstChild.nodeValue);
-if(this.rspauth==_15.substring(8)){
-var _16=new dojox.string.Builder(dojox.xmpp.util.createElement("response",{xmlns:dojox.xmpp.xmpp.SASL_NS},true));
-this.session.dispatchPacket(_16.toString());
-}else{
-}
-}});
-dojox.xmpp.sasl.registry=new dojo.AdapterRegistry();
-dojox.xmpp.sasl.registry.register("SUN-COMMS-CLIENT-PROXY-AUTH",function(_17){
-return _17=="SUN-COMMS-CLIENT-PROXY-AUTH";
-},function(_18,_19){
-return new dojox.xmpp.sasl.SunWebClientAuth(_19);
+
+dojo.declare("dojox.xmpp.sasl.SunWebClientAuth", dojox.xmpp.sasl._Base, {
+	mechanism: "SUN-COMMS-CLIENT-PROXY-AUTH"
 });
-dojox.xmpp.sasl.registry.register("DIGEST-MD5",function(_1a){
-return _1a=="DIGEST-MD5";
-},function(_1b,_1c){
-return new dojox.xmpp.sasl.DigestMD5(_1c);
+
+dojo.declare("dojox.xmpp.sasl.Plain", dojox.xmpp.sasl._Base, {
+	mechanism: "PLAIN",
+	closeAuthTag: false,
+
+	appendToAuth: function(auth){
+		var id = this.session.jid;
+		var index = this.session.jid.indexOf('@');
+		if (index != -1){
+			id = this.session.jid.substring(0, index);
+		}
+		var token = this.session.jid + '\u0000' + id + '\u0000' + this.session.password;
+		token = dojox.xmpp.util.Base64.encode(token);
+
+		auth.append(token);
+		auth.append("</auth>");
+
+		delete this.session.password;
+	}
 });
-dojox.xmpp.sasl.registry.register("PLAIN",function(_1d){
-return _1d=="PLAIN";
-},function(_1e,_1f){
-return new dojox.xmpp.sasl.Plain(_1f);
+
+dojo.declare("dojox.xmpp.sasl.DigestMD5", dojox.xmpp.sasl._Base, {
+	mechanism: "DIGEST-MD5",
+
+	onFirstChallenge: function(msg){
+		var dxed = dojox.encoding.digests;
+		var dxedo = dojox.encoding.digests.outputTypes;
+		var HEX = function(n){
+			return dxed.MD5(n, dxedo.Hex);
+		};
+		var H = function(s){
+			return dxed.MD5(s, dxedo.String);
+		};
+
+		var ch_str = dojox.xmpp.util.Base64.decode(msg.firstChild.nodeValue);
+		var ch = {
+			realm: "",
+			nonce: "",
+			qop: "auth",
+			maxbuf: 65536
+		};
+		ch_str.replace(/([a-z]+)=([^,]+)/g, function(t,k,v){
+			v = v.replace(/^"(.+)"$/, "$1");
+			ch[k] = v;
+		});
+
+		var A2_append = '';
+		switch(ch.qop){
+			case 'auth-int':
+			case 'auth-conf':
+				A2_append = ':00000000000000000000000000000000';
+			case 'auth':
+				break;
+			default:
+				return false;
+		}
+		var cnonce = dxed.MD5(Math.random() * 1234567890, dxedo.Hex);
+		var digest_uri = 'xmpp/' + this.session.domain;
+
+		var username = this.session.jid;
+		var index = this.session.jid.indexOf('@');
+		if (index != -1){
+			username = this.session.jid.substring(0, index);
+		}
+		username = dojox.xmpp.util.encodeJid(username);
+
+		var A1 = new dojox.string.Builder();
+		A1.append(H(username + ':' + ch.realm + ':' + this.session.password),
+			':', ch.nonce + ':' + cnonce);
+		delete this.session.password;
+		var A2_rspauth = ':' + digest_uri + A2_append;
+		var A2 = 'AUTHENTICATE' + A2_rspauth;
+
+		var response_value = new dojox.string.Builder();
+		response_value.append(HEX(A1.toString()), ':', ch.nonce, ':00000001:', cnonce, ':',
+			ch.qop, ':')
+
+		var ret = new dojox.string.Builder();
+		ret.append('username="', username, '",',
+			'realm="', ch.realm, '",',
+			'nonce=', ch.nonce, ',',
+			'cnonce="', cnonce, '",',
+			'nc="00000001",qop="', ch.qop, '",digest-uri="', digest_uri, '",',
+			'response="', HEX(response_value.toString() + HEX(A2)), '",charset="utf-8"');
+
+		var response = new dojox.string.Builder(dojox.xmpp.util.createElement("response", {
+			xmlns: dojox.xmpp.xmpp.SASL_NS
+		}, false));
+		response.append(dojox.xmpp.util.Base64.encode(ret.toString()));
+		response.append('</response>');
+
+		this.rspauth = HEX(response_value.toString() + HEX(A2_rspauth));
+
+		this.session.dispatchPacket(response.toString());
+	},
+
+	onSecondChallenge: function(msg){
+		var ch_str = dojox.xmpp.util.Base64.decode(msg.firstChild.nodeValue);
+
+		if(this.rspauth == ch_str.substring(8)){
+			var response = new dojox.string.Builder(dojox.xmpp.util.createElement("response", {
+				xmlns: dojox.xmpp.xmpp.SASL_NS
+			}, true));
+			this.session.dispatchPacket(response.toString());
+		}else{
+			//FIXME
+		}
+	}
 });
-}
+
+dojox.xmpp.sasl.registry = new dojo.AdapterRegistry();
+dojox.xmpp.sasl.registry.register(
+	'SUN-COMMS-CLIENT-PROXY-AUTH',
+	function(mechanism){
+		return mechanism == 'SUN-COMMS-CLIENT-PROXY-AUTH';
+	},
+	function(mechanism, session){
+		return new dojox.xmpp.sasl.SunWebClientAuth(session);
+	}
+);
+dojox.xmpp.sasl.registry.register(
+	'DIGEST-MD5',
+	function(mechanism){
+		return mechanism == 'DIGEST-MD5';
+	},
+	function(mechanism, session){
+		return new dojox.xmpp.sasl.DigestMD5(session);
+	}
+);
+dojox.xmpp.sasl.registry.register(
+	'PLAIN',
+	function(mechanism){
+		return mechanism == 'PLAIN';
+	},
+	function(mechanism, session){
+		return new dojox.xmpp.sasl.Plain(session);
+	}
+);
diff --git a/dojox/xmpp/tests/test_xmppService.html b/dojox/xmpp/tests/test_xmppService.html
new file mode 100644
index 0000000..9ad288c
--- /dev/null
+++ b/dojox/xmpp/tests/test_xmppService.html
@@ -0,0 +1,515 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+	<head>
+		<style type="text/css">
+			@import "../../../dojo/resources/dojo.css";
+			@import "../../../dijit/themes/dijit.css";
+			@import "../../../dijit/themes/tundra/tundra.css";
+	
+			html,body {
+				width: 100%;
+				height: 100%;
+				overflow: none;
+			}
+			
+			.dijitSplitPane{
+				margin: 5px;
+			}
+
+			#buddyList {
+				cursor:pointer;
+			}
+			
+			.presence {
+				background:#525252;
+				height: 10px;
+				width: 10px;
+				margin:5px;
+			}
+			
+			.online, 
+			.available {
+				background: #00AC00;
+			}
+			
+			
+			.away {
+				background: #E20000;
+			}
+			
+		
+			.offline {
+				background: #ccc;
+			}	
+
+		</style>
+		<title>xmpp test page</title>
+
+		<script type="text/javascript" 
+			src="../../../dojo/dojo.js" djConfig="isDebug:true,parseOnLoad:true">
+		</script>
+		<script type="text/javascript">
+			
+			dojo.require('dijit.layout.LayoutContainer');
+			dojo.require('dijit.layout.ContentPane');
+			dojo.require("dijit.layout.TabContainer");
+			dojo.require("dijit.form.FilteringSelect");
+			dojo.require("dijit.Menu");
+			dojo.require("dijit.Dialog");
+			dojo.require("dijit.Toolbar");
+			dojo.require("dijit.TitlePane");
+			dojo.require("dojox.xmpp.xmppSession");
+
+			dojo.require("dojox.xmpp.widget.ChatSession");
+			
+			dojo.require("dojo.date");
+			dojo.require("dojo.date.locale");
+			dojo.require("dojo.parser");
+		</script>
+
+		<script type="text/javascript">
+		
+			
+			//We want to know which chat instance is selected, so we can associate
+			//the <input> area with it
+			var selectedTab = "";
+			var chatTabs = {};
+			var chatTabContainer = null;
+			var chatInstances = {};
+			
+			/*Local copy of the user's roster*/
+			var roster = {}; 
+			var groups = {};
+			var rosterPresence = {};
+			var selectedJID = null;
+
+			dojo.addOnLoad(function() {
+			
+						dijit.byId("loginDialog").show();
+					var buddyList = dojo.byId("buddyList");
+						dojo.connect(buddyList, "ondblclick",function(evt){
+									var target = findTargetContact(evt);
+									if(target) {
+										openChat(target.jid);
+									}
+						});
+						
+						
+						dojo.connect(buddyList, "oncontextmenu",function(evt){
+								selectedJID = null;
+								var target = findTargetContact(evt);
+								if(target) {
+											selectedJID = target.jid;
+											dojo.stopEvent(evt);
+										var pop = dijit.popup.open({
+											popup: dijit.byId("buddyMenu"),
+											around: target.target,
+											onExecute: function(){
+													dijit.popup.close( dijit.byId("buddyMenu"));
+											},
+											onCancel: function(){
+													dijit.popup.close( dijit.byId("buddyMenu"));
+											}
+										});
+									
+								}
+						});
+						
+					
+						
+			});
+			
+		   	function findTargetContact(evt) {
+				var buddyList = dojo.byId("buddyList");
+					var jid = null;
+					var target = evt.target;
+					while(!jid && target != buddyList) {
+						jid = target.getAttribute("imContactId");
+						if(!jid) {
+							target = target.parentNode;
+						}
+					}
+					return jid ? {jid:jid, target:target} : null;
+			}
+
+			function login() {
+				
+					var bindUrl = dijit.byId("bindUrl").attr("value");
+					var domain = dijit.byId("loginDomain").attr("value");
+					var jid = dijit.byId("loginJid").attr("value");
+					var password = dijit.byId("loginPassword").attr("value");
+				
+					var useScriptSrcTransport = false;
+					if(bindUrl.indexOf("http") == 0) {
+						useScriptSrcTransport = true;
+					}
+					var options =  {
+							serviceUrl:bindUrl,// "http://other.host.local/http-bind/",
+							hold: 1,
+							secure: false,
+							useScriptSrcTransport: useScriptSrcTransport,
+							wait: 60,
+							lang: 'en',
+							retryCount: 2,
+							domain: domain
+						};
+
+					session = new dojox.xmpp.xmppSession(options);
+					//TESTUSER
+					
+					//currently svc.openSession doesn't accept any params
+					//so the iwc.userPrefs stuff above setup the user id, dont' forget it!		
+					session.open(jid, password, "test-client");
+
+
+
+					buddyList = dojo.byId("buddyList");
+					chatTabContainer = dijit.byId("chatTabs");
+					//sendInput = dojo.byId("sendInput");
+
+					//When the session becomes active, get the buddy list and populate it
+					dojo.connect(session, "onActive", function(){
+						session.presenceService.publish({});
+					});
+					
+					dojo.connect(this.session, 'onRosterAdded',  buddyAdded);
+					
+					dojo.connect(this.session, 'onRosterChanged',  function(rosterItem, previousCopy) { 
+						var presence = rosterPresence[rosterItem.id];
+						buddyRemoved(previousCopy);
+						buddyAdded(rosterItem);
+						if(presence) {
+							updateBuddyPresence(presence);
+						}	
+					});
+					dojo.connect(this.session, 'onRosterRemoved',  buddyRemoved);
+				
+
+					dojo.connect(session, "onRosterUpdated", function() {
+							for(var i=0;i<session.roster.length;i++){
+								var buddy = session.roster[i];
+								roster[buddy.jid] = buddy;
+								if(buddy.groups.length == 0 ) {
+									addBuddyToGroup(buddy, "buddies");
+								} else {
+									for(var j= 0; j < buddy.groups.length; j++) {
+										addBuddyToGroup(buddy, buddy.groups[j]);
+									}
+								}	
+							}
+							for(groupName in groups) {
+								createGroup(groupName);
+							}
+					});
+					
+					
+
+					//subscribe to presence notifications
+					dojo.connect(session, 'onPresenceUpdate', updateBuddyPresence);
+
+
+					//subscribe to onSubscriptionRequest.  For this test, we'll just
+					//automatically accept any susbscription request
+					dojo.connect(session, "onSubscriptionRequest", function(from){
+						session.presenceService.approveSubscription(from);
+					});
+
+
+
+					dojo.connect(session, "onRegisterChatInstance", function(instance, message){
+
+						//in the case of we are creating a new chat instance, defer the tab creation
+						//until the invite has occurred and the contact's uid has been added
+						if (instance.uid){
+							if(!chatInstances[instance.uid] || chatInstances[instance.uid].chatid != instance.chatid){
+								newMessage(instance, instance.uid, message);
+							}
+							chatInstances[instance.uid] = instance;		
+						}
+
+						dojo.connect(instance, "onInvite", dojo.hitch(this,function(contact){
+							chatInstances[contact] = instance;
+							newMessage(instance, contact, null);
+						}));	
+
+
+						//do something when we get a new message from this chat instance
+						dojo.connect(instance, "onNewMessage", dojo.hitch(this, function(msg){
+							newMessage(instance, instance.uid, msg);		
+						}));		
+
+						//I'm not going to wire this up for this example, but this
+						//is the event that would signal whether a person is writing,
+						//idle, etc (ie, the little pencil in adium)
+						dojo.connect(instance, "setState", function(state){
+							console.log("IM: ",  instance.uid, " is now ", state);
+						});
+					});
+
+			}
+			
+			function createGroup(groupName) {
+				var div = document.createElement("div");
+				buddyList.appendChild(div);
+				var groupItems = groups[groupName].items;
+				 var buffer = new dojox.string.Builder();
+				for(var i=0;i<groupItems.length;i++){
+					var buddy = groupItems[i];
+					renderBuddy(buffer, buddy);
+				}
+				div.innerHTML = buffer.toString();
+				var titlePane = new dijit.TitlePane({title: groupName}, div);
+				
+				 groups[groupName].container = titlePane;
+				return titlePane;
+			}
+			
+			function updateBuddyPresence(p){
+				rosterPresence[p.from] = p;
+				dojo.query('div[imContactId="'+p.from+'"]', buddyList).forEach(function(contact) { 
+					contact.firstChild.className = "dijitInline presence "  + p.show;
+				 });
+			
+			}
+			
+			function buddyRemoved(buddy){
+				delete roster[buddy.id];
+				delete rosterPresence[buddy.id];
+				dojo.query('div[imContactId="'+buddy.id+'"]', buddyList).forEach(function(contact) { 
+						contact.parentNode.removeChild(contact);
+				 });
+			}
+			
+			function buddyAdded(buddy) {
+					roster[buddy.id] =buddy
+					if(buddy) {
+						var div  = null;
+						if(buddy.groups.length == 0 ) {
+							addBuddyToGroup(buddy, "buddies");
+							var container = groups["buddies"].container;
+							if(container) {
+								div = container.containerNode;
+								var buffer = new dojox.string.Builder();
+								buffer.append(div.innerHTML);
+								renderBuddy(buffer, buddy);
+								div.innerHTML = buffer;
+							} else {
+								div =  createGroup("buddies").containerNode;
+							}
+						
+						} else {
+							for(var j= 0; j < buddy.groups.length; j++) {
+								var groupName = buddy.groups[j];
+								addBuddyToGroup(buddy, groupName);
+								var container = groups[groupName].container;
+								if(container) {
+									div = container.containerNode;
+									var buffer = new dojox.string.Builder();
+									buffer.append(div.innerHTML);
+									renderBuddy(buffer, buddy);
+									div.innerHTML = buffer;
+								} else {
+									div =  createGroup(groupName).containerNode;
+								}
+								
+							}
+						}
+					}
+					
+			}
+			
+			
+			function renderBuddy(buffer, buddy) {
+				buffer.append('<div imContactId="');
+				buffer.append(buddy.jid);
+				buffer.append('"><div class="dijitInline presence"></div><div class="dijitInline ">');
+				buffer.append(buddy.name?buddy.name:buddy.jid);
+				buffer.append('</div></div>');
+			}
+			
+			function addBuddyToGroup(buddy, groupName) {
+				var group = groups[groupName];
+				if(!group) {
+					group = {name:groupName, items: []};
+					groups[groupName] =group;
+				}
+				group.items.push(buddy);
+			}
+
+			function newMessage(instance, jid, message) {
+				var tab = chatTabs[jid];
+				if(!tab) {
+					var div = document.createElement("div");
+					var buddy = roster[jid];
+					var chatWith = jid;
+					if(buddy && buddy.name) {
+						chatWith = buddy.name;
+					}
+				 	tab = new dojox.xmpp.widget.ChatSession({title: jid, chatWith: chatWith, instance: instance, closable: true}, div);
+					dojo.connect(tab, "onClose", function() {
+						delete chatTabs[jid];
+					});
+					chatTabContainer.addChild(tab);
+					chatTabContainer.selectChild(tab);	
+					chatTabContainer.layout();
+					chatTabs[jid] = tab;
+				}
+				tab.displayMessage(message);
+				
+			}
+
+			function openChat(jid){
+				var tab = chatTabs[jid];
+				if(tab) {
+				  chatTabContainer.selectChild(tab);	
+				}
+
+				var chatInstance = new dojox.xmpp.ChatService();
+				session.registerChatInstance(chatInstance);
+				chatInstance.invite(jid);
+			}
+
+
+			function updatePresence(p){
+				//since the filtering select wants to call its onChange
+				//at startup and the svc isn't started up yet, we just ignore it 
+				//for this test case
+				if (session && session.presenceService) {
+					session.presenceService.publish({show:p});
+				}
+			}
+			
+			
+			function addUser() {
+			    var userJID = dijit.byId("userJID").attr("value");
+				var userAlias = dijit.byId("userAlias").attr("value");
+				var userGroups = dijit.byId("userGroups").attr("value");
+				
+				var groups = userGroups.split(",");
+				session.rosterService.addRosterItem(userJID, userAlias, groups);
+			}
+			
+			function showAddBuddy() {
+				dijit.byId("userJID").setValue("");
+				dijit.byId("userJID").setDisabled(false);
+				
+				dijit.byId("userAlias").setValue("");
+				dijit.byId("userGroups").setValue("");
+				dijit.byId('addUser').show();
+			}
+			
+			function showEditBuddy() {
+				var buddy = roster[selectedJID];
+				if(buddy) { 
+					dijit.byId("userJID").setValue(selectedJID);
+					dijit.byId("userJID").setDisabled(true);
+
+					dijit.byId("userAlias").setValue(buddy.name? buddy.name : "");
+					dijit.byId("userGroups").setValue(buddy.groups? buddy.groups.join(",") : "");
+					dijit.byId('addUser').show();
+				}
+			}
+			
+			function subscribeBuddy(){
+				session.presenceService.subscribe(selectedJID);
+			}
+			
+			
+			function deleteBuddy(){
+				if(confirm("Sure you want to delete "  + selectedJID + " ?")) {
+					session.rosterService.removeRosterItem(selectedJID);
+				}
+			}
+
+		</script>
+	</head>
+
+	<body class="tundra">
+		foo
+		<div dojoType="dijit.Dialog" id="loginDialog" style="display: none; width:400px" title="Login">
+			<table>
+				<tr>
+					<td><label for="name">JID: </label></td>
+					<td><input dojoType="dijit.form.TextBox" type="text"  id="loginJid" value="foo"></td>
+				</tr>
+				<tr>
+					<td><label for="loc">Password: </label></td>
+					<td><input dojoType="dijit.form.TextBox" type="password"  id="loginPassword" value="papajeza"></td>
+				</tr>
+				<tr>
+					<td><label for="loc">Domain: </label></td>
+					<td><input dojoType="dijit.form.TextBox" type="text"  id="loginDomain" value="mac"></td>
+				</tr>
+				<tr>
+					<td><label for="loc">HTTP-Bind URL: </label></td>
+					<td><input dojoType="dijit.form.TextBox" type="text"  id="bindUrl" value="http://127.0.0.1:7070/http-bind/"></td>
+				</tr>
+				<tr>
+					<td colspan="2"><small>Note: a relative Bind URL will use the standard XHR transport and a full URL will use the cross-domain BOSH script syntax.</small></td>
+				</tr>
+				<tr>
+					<td colspan="2" align="center">
+						<button dojoType="dijit.form.Button" onClick="login()" type="submit">Login</button></td>
+				</tr>
+			</table>
+		</div>
+		
+		<div dojoType="dijit.Dialog" id="addUser" style="display: none" title="Add User">
+			<table>
+				<tr>
+					<td><label for="name">JID: </label></td>
+					<td><input dojoType="dijit.form.TextBox" type="text"  id="userJID" value=""></td>
+				</tr>
+				<tr>
+					<td><label for="name">Alias: </label></td>
+					<td><input dojoType="dijit.form.TextBox" type="text"  id="userAlias" value=""></td>
+				</tr>
+				<tr>
+					<td><label for="name">Groups: </label></td>
+					<td><input dojoType="dijit.form.TextBox" type="text"  id="userGroups" value=""></td>
+				</tr>
+				<tr>
+					<td colspan="2" align="center">
+						<button dojoType="dijit.form.Button"  onClick="addUser()" type="submit">Save</button>
+						<button dojoType="dijit.form.Button" onClick="dijit.byId('addUser').hide();" type="submit">Cancel</button></td>
+				</tr>
+			</table>
+		</div>
+			<div dojoType="dijit.Menu" id="buddyMenu" style="display:none; width: 190px;">
+			
+				<div dojoType="dijit.MenuItem"  onClick="showEditBuddy" >
+				 	Edit Buddy
+				</div>
+				<div dojoType="dijit.MenuItem"   onClick="subscribeBuddy">
+					Re-request subscription
+				</div>
+				<div dojoType="dijit.MenuItem"   onClick="deleteBuddy">
+					Delete
+				</div>
+
+			</div>
+		
+		<div dojoType="dijit.layout.LayoutContainer" style="width: 100%; height: 100%;">
+			<div dojoType="dijit.layout.ContentPane" layoutAlign="top" style="height: 50px; background: #999999;">
+				XMPP Test Client
+				<div style="top:10px; float: right;">
+					Status: <select dojoType="dijit.form.FilteringSelect" id="presence" name="presence" autoComplete="false" onChange="updatePresence(arguments[0]);">
+						<option value="available" selected>Online</option>
+						<option value="away">Away</option>
+						<option value="chat">Free to Chat</option>
+						<option value="dnd">Do Not Disturb</option>
+						<option value="xa">Extended Away</option>
+					</select>
+					<button dojoType="dijit.form.Button" id="addUserButton" onClick="showAddBuddy()">Add Buddy</button>
+				</div>
+			</div>
+		
+			<div id="buddyListCP" dojoType="dijit.layout.ContentPane" layoutAlign="right" style="width: 200px; border: 1px solid #999999; overflow:auto;">
+				
+			  	<div id="buddyList">
+				</div>
+			</div>
+			<div id="chatTabs" dojoType="dijit.layout.TabContainer" layoutAlign="client" style="border: 1px solid #999999; height:100%"></div>
+		</div>	
+	</body>
+</html>
diff --git a/dojox/xmpp/util.js b/dojox/xmpp/util.js
index b4bb7f5..6f43ad3 100644
--- a/dojox/xmpp/util.js
+++ b/dojox/xmpp/util.js
@@ -1,136 +1,146 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.xmpp.util"]){
-dojo._hasResource["dojox.xmpp.util"]=true;
 dojo.provide("dojox.xmpp.util");
 dojo.require("dojox.string.Builder");
 dojo.require("dojox.encoding.base64");
-dojox.xmpp.util.xmlEncode=function(_1){
-if(_1){
-_1=_1.replace("&","&").replace(">",">").replace("<","<").replace("'","'").replace("\"",""");
-}
-return _1;
-};
-dojox.xmpp.util.encodeJid=function(_2){
-var _3=new dojox.string.Builder();
-for(var i=0;i<_2.length;i++){
-var ch=_2.charAt(i);
-var _4=ch;
-switch(ch){
-case " ":
-_4="\\20";
-break;
-case "\"":
-_4="\\22";
-break;
-case "#":
-_4="\\23";
-break;
-case "&":
-_4="\\26";
-break;
-case "'":
-_4="\\27";
-break;
-case "/":
-_4="\\2f";
-break;
-case ":":
-_4="\\3a";
-break;
-case "<":
-_4="\\3c";
-break;
-case ">":
-_4="\\3e";
-break;
+
+dojox.xmpp.util.xmlEncode = function(str) {
+	if(str) {
+		str = str.replace("&", "&").replace(">", ">").replace("<", "<").replace("'", "'").replace('"', """);
+	}
+	return str;
 }
-_3.append(_4);
+
+dojox.xmpp.util.encodeJid = function(jid) {
+		var buffer = new dojox.string.Builder();
+		for(var i =0; i < jid.length; i++) {
+			var ch = jid.charAt(i);
+			var rep = ch;
+			switch(ch){
+				case ' ' : 
+					rep = "\\20";
+				break;
+				case '"' :
+					rep = "\\22"; 
+				break;
+				case '#' :
+					rep = "\\23"; 
+				break;
+				case '&' :
+					rep = "\\26"; 
+				break;
+				case "'" :
+					rep = "\\27"; 
+				break;
+				case '/' :
+					rep = "\\2f"; 
+				break;
+				case ':' :
+					rep = "\\3a"; 
+				break;
+				case '<' :
+					rep = "\\3c"; 
+				break;
+				case '>' :
+					rep = "\\3e"; 
+				break;			
+			}
+			buffer.append(rep);
+		}
+		return buffer.toString();
+	}
+
+dojox.xmpp.util.decodeJid = function(jid) {
+	
+	jid = jid.replace(/\\([23][02367acef])/g, function(match) {
+			switch(match){
+				case "\\20" : 
+					return  ' ';
+				case "\\22"  :
+					return '"'; 
+				case "\\23" :
+					return '#' ; 
+				case "\\26" :
+					return  '&'; 
+				case "\\27" :
+					return   "'"; 
+				case "\\2f" :
+					return  '/'; 
+				case "\\3a" :
+					return ':' ; 
+				case "\\3c" :
+					return  '<'; 
+				case "\\3e" :
+					return  '>'; 
+			}
+			return "ARG";
+	});
+	
+	return jid;
 }
-return _3.toString();
-};
-dojox.xmpp.util.decodeJid=function(_5){
-_5=_5.replace(/\\([23][02367acef])/g,function(_6){
-switch(_6){
-case "\\20":
-return " ";
-case "\\22":
-return "\"";
-case "\\23":
-return "#";
-case "\\26":
-return "&";
-case "\\27":
-return "'";
-case "\\2f":
-return "/";
-case "\\3a":
-return ":";
-case "\\3c":
-return "<";
-case "\\3e":
-return ">";
+
+
+dojox.xmpp.util.createElement = function(tag, attributes, terminal){
+	var elem = new dojox.string.Builder("<");
+	elem.append(tag + " ");
+
+	for (var attr in attributes){
+		elem.append(attr + '="');
+		elem.append(attributes[attr]);
+		elem.append('" ');
+	}	
+	
+	if (terminal){
+		elem.append("/>");		
+	}else{
+		elem.append(">");
+	}
+
+	return elem.toString();
 }
-return "ARG";
-});
-return _5;
-};
-dojox.xmpp.util.createElement=function(_7,_8,_9){
-var _a=new dojox.string.Builder("<");
-_a.append(_7+" ");
-for(var _b in _8){
-_a.append(_b+"=\"");
-_a.append(_8[_b]);
-_a.append("\" ");
+
+dojox.xmpp.util.stripHtml = function(str){
+	// summary
+	//		Strips all HTML, including attributes and brackets
+	//		| <div onmouse="doBadThing()">Click <b>Me</b></div>
+	//		| becomes: Click Me
+	var re=/<[^>]*?>/gi;
+	for (var i=0; i<arguments.length; i++) {}
+	return str.replace(re, "");
 }
-if(_9){
-_a.append("/>");
-}else{
-_a.append(">");
+
+dojox.xmpp.util.decodeHtmlEntities = function(str){
+	// Summary: decodes HTML entities to js characters so the string can be 
+	// fed to a textarea.value
+	var ta = dojo.doc.createElement("textarea");
+	ta.innerHTML = str.replace(/</g,"<").replace(/>/g,">");
+	return ta.value;
 }
-return _a.toString();
-};
-dojox.xmpp.util.stripHtml=function(_c){
-var re=/<[^>]*?>/gi;
-for(var i=0;i<arguments.length;i++){
+
+dojox.xmpp.util.htmlToPlain = function(str){
+	str = dojox.xmpp.util.decodeHtmlEntities(str);
+	str = str.replace(/<br\s*[i\/]{0,1}>/gi,"\n");
+	str = dojox.xmpp.util.stripHtml(str);
+	return str;
 }
-return _c.replace(re,"");
-};
-dojox.xmpp.util.decodeHtmlEntities=function(_d){
-var ta=dojo.doc.createElement("textarea");
-ta.innerHTML=_d.replace(/</g,"<").replace(/>/g,">");
-return ta.value;
-};
-dojox.xmpp.util.htmlToPlain=function(_e){
-_e=dojox.xmpp.util.decodeHtmlEntities(_e);
-_e=_e.replace(/<br\s*[i\/]{0,1}>/gi,"\n");
-_e=dojox.xmpp.util.stripHtml(_e);
-return _e;
-};
-dojox.xmpp.util.Base64={};
-dojox.xmpp.util.Base64.encode=function(_f){
-var s2b=function(s){
-var b=[];
-for(var i=0;i<s.length;++i){
-b.push(s.charCodeAt(i));
+
+dojox.xmpp.util.Base64 = {};
+
+dojox.xmpp.util.Base64.encode = function(input){
+	var s2b = function(s){
+		var b = [];
+		for(var i = 0; i < s.length; ++i){
+			b.push(s.charCodeAt(i));
+		}
+		return b;
+	};
+	return dojox.encoding.base64.encode(s2b(input));
 }
-return b;
-};
-return dojox.encoding.base64.encode(s2b(_f));
-};
-dojox.xmpp.util.Base64.decode=function(_10){
-var b2s=function(b){
-var s=[];
-dojo.forEach(b,function(c){
-s.push(String.fromCharCode(c));
-});
-return s.join("");
-};
-return b2s(dojox.encoding.base64.decode(_10));
-};
+
+
+dojox.xmpp.util.Base64.decode = function(input){
+	var b2s = function(b){
+		var s = [];
+		dojo.forEach(b, function(c){ s.push(String.fromCharCode(c)); });
+		return s.join("");
+	};
+	return b2s(dojox.encoding.base64.decode(input));
 }
diff --git a/dojox/xmpp/widget/ChatSession.js b/dojox/xmpp/widget/ChatSession.js
index 6edad66..9209f43 100644
--- a/dojox/xmpp/widget/ChatSession.js
+++ b/dojox/xmpp/widget/ChatSession.js
@@ -1,28 +1,38 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.xmpp.widget.ChatSession"]){
-dojo._hasResource["dojox.xmpp.widget.ChatSession"]=true;
 dojo.provide("dojox.xmpp.widget.ChatSession");
-dojo.declare("dojox.xmpp.widget.ChatSession",[dijit.layout.LayoutContainer,dijit._Templated],{templateString:dojo.cache("dojox.xmpp.widget","templates/ChatSession.html","<div>\n<div dojoAttachPoint=\"messages\" dojoType=\"dijit.layout.ContentPane\" layoutAlign=\"client\" style=\"overflow:auto\">\n</div>\n<div dojoType=\"dijit.layout.ContentPane\" layoutAlign=\"bottom\" style=\"border-top: 2px solid #333333; height: 35px;\"><input dojoAttachPoint=\"chatInput\" dojoAttachEvent=\"onkeypress [...]
-},displayMessage:function(_1,_2){
-if(_1){
-var _3=_1.from?this.chatWith:"me";
-this.messages.domNode.innerHTML+="<b>"+_3+":</b> "+_1.body+"<br/>";
-this.goToLastMessage();
-}
-},goToLastMessage:function(){
-this.messages.domNode.scrollTop=this.messages.domNode.scrollHeight;
-},onKeyPress:function(e){
-var _4=e.keyCode||e.charCode;
-if((_4==dojo.keys.ENTER)&&(this.chatInput.value!="")){
-this.instance.sendMessage({body:this.chatInput.value});
-this.displayMessage({body:this.chatInput.value},"out");
-this.chatInput.value="";
-}
-}});
-}
+dojo.declare("dojox.xmpp.widget.ChatSession",
+	[dijit.layout.LayoutContainer, dijit._Templated],
+	{
+			templateString: dojo.cache("dojox.xmpp.widget", "templates/ChatSession.html"),
+			enableSubWidgets: true, 
+			widgetsInTemplate: true,
+			
+			widgetType: "ChatSession",
+			chatWith: null,
+			instance: null,
+			postCreate: function(){
+				//console.log("Neato!");
+			},
+	
+			displayMessage: function(message, type) {
+				//console.log("displayMessage", this, message);
+				if(message) {
+					var name =  message.from ? this.chatWith : "me";
+					this.messages.domNode.innerHTML += "<b>" + name + ":</b> " +   message.body + "<br/>";
+					this.goToLastMessage();
+				}
+				
+			},
+			
+			goToLastMessage: function() {
+				this.messages.domNode.scrollTop = this.messages.domNode.scrollHeight;
+			},
+			
+			onKeyPress: function(e){
+				var key = e.keyCode || e.charCode;
+				if ((key == dojo.keys.ENTER) && (this.chatInput.value != "")){
+					this.instance.sendMessage({body: this.chatInput.value});
+					this.displayMessage( {body: this.chatInput.value}, "out");
+					this.chatInput.value = "";
+				}
+			}
+});
\ No newline at end of file
diff --git a/dojox/xmpp/xmppSession.js b/dojox/xmpp/xmppSession.js
index f2f624b..120222c 100644
--- a/dojox/xmpp/xmppSession.js
+++ b/dojox/xmpp/xmppSession.js
@@ -1,554 +1,849 @@
-/*
-	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
-*/
-
-
-if(!dojo._hasResource["dojox.xmpp.xmppSession"]){
-dojo._hasResource["dojox.xmpp.xmppSession"]=true;
 dojo.provide("dojox.xmpp.xmppSession");
+
 dojo.require("dojox.xmpp.TransportSession");
 dojo.require("dojox.xmpp.RosterService");
 dojo.require("dojox.xmpp.PresenceService");
 dojo.require("dojox.xmpp.UserService");
 dojo.require("dojox.xmpp.ChatService");
 dojo.require("dojox.xmpp.sasl");
-dojox.xmpp.xmpp={STREAM_NS:"http://etherx.jabber.org/streams",CLIENT_NS:"jabber:client",STANZA_NS:"urn:ietf:params:xml:ns:xmpp-stanzas",SASL_NS:"urn:ietf:params:xml:ns:xmpp-sasl",BIND_NS:"urn:ietf:params:xml:ns:xmpp-bind",SESSION_NS:"urn:ietf:params:xml:ns:xmpp-session",BODY_NS:"http://jabber.org/protocol/httpbind",XHTML_BODY_NS:"http://www.w3.org/1999/xhtml",XHTML_IM_NS:"http://jabber.org/protocol/xhtml-im",INACTIVE:"Inactive",CONNECTED:"Connected",ACTIVE:"Active",TERMINATE:"Terminate", [...]
-dojox.xmpp.xmppSession=function(_1){
-this.roster=[];
-this.chatRegister=[];
-this._iqId=Math.round(Math.random()*1000000000);
-if(_1&&dojo.isObject(_1)){
-dojo.mixin(this,_1);
-}
-this.session=new dojox.xmpp.TransportSession(_1);
-dojo.connect(this.session,"onReady",this,"onTransportReady");
-dojo.connect(this.session,"onTerminate",this,"onTransportTerminate");
-dojo.connect(this.session,"onProcessProtocolResponse",this,"processProtocolResponse");
+
+dojox.xmpp.xmpp = {
+	STREAM_NS:  'http://etherx.jabber.org/streams',
+	CLIENT_NS: 'jabber:client',
+	STANZA_NS: 'urn:ietf:params:xml:ns:xmpp-stanzas',
+	SASL_NS: 'urn:ietf:params:xml:ns:xmpp-sasl',
+	BIND_NS: 'urn:ietf:params:xml:ns:xmpp-bind',
+	SESSION_NS: 'urn:ietf:params:xml:ns:xmpp-session',
+	BODY_NS: "http://jabber.org/protocol/httpbind",
+	
+	XHTML_BODY_NS: "http://www.w3.org/1999/xhtml",
+	XHTML_IM_NS: "http://jabber.org/protocol/xhtml-im",
+
+	INACTIVE: "Inactive",
+	CONNECTED: "Connected",
+	ACTIVE: "Active",
+	TERMINATE: "Terminate",
+	LOGIN_FAILURE: "LoginFailure",
+
+	INVALID_ID: -1,
+	NO_ID: 0,
+
+	error:{
+		BAD_REQUEST: 'bad-request',
+		CONFLICT: 'conflict',
+		FEATURE_NOT_IMPLEMENTED: 'feature-not-implemented',
+		FORBIDDEN: 'forbidden',
+		GONE: 'gone',
+		INTERNAL_SERVER_ERROR: 'internal-server-error',
+		ITEM_NOT_FOUND: 'item-not-found',
+		ID_MALFORMED: 'jid-malformed',
+		NOT_ACCEPTABLE: 'not-acceptable',
+		NOT_ALLOWED: 'not-allowed',
+		NOT_AUTHORIZED: 'not-authorized',
+		SERVICE_UNAVAILABLE: 'service-unavailable',
+		SUBSCRIPTION_REQUIRED: 'subscription-required',
+		UNEXPECTED_REQUEST: 'unexpected-request'
+	}
 };
-dojo.extend(dojox.xmpp.xmppSession,{roster:[],chatRegister:[],_iqId:0,open:function(_2,_3,_4){
-if(!_2){
-throw new Error("User id cannot be null");
-}else{
-this.jid=_2;
-if(_2.indexOf("@")==-1){
-this.jid=this.jid+"@"+this.domain;
-}
-}
-if(_3){
-this.password=_3;
-}
-if(_4){
-this.resource=_4;
-}
-this.session.open();
-},close:function(){
-this.state=dojox.xmpp.xmpp.TERMINATE;
-this.session.close(dojox.xmpp.util.createElement("presence",{type:"unavailable",xmlns:dojox.xmpp.xmpp.CLIENT_NS},true));
-},processProtocolResponse:function(_5){
-var _6=_5.nodeName;
-var _7=_6.indexOf(":");
-if(_7>0){
-_6=_6.substring(_7+1);
-}
-switch(_6){
-case "iq":
-case "presence":
-case "message":
-case "features":
-this[_6+"Handler"](_5);
-break;
-default:
-if(_5.getAttribute("xmlns")==dojox.xmpp.xmpp.SASL_NS){
-this.saslHandler(_5);
-}
-}
-},messageHandler:function(_8){
-switch(_8.getAttribute("type")){
-case "chat":
-this.chatHandler(_8);
-break;
-case "normal":
-default:
-this.simpleMessageHandler(_8);
-}
-},iqHandler:function(_9){
-if(_9.getAttribute("type")=="set"){
-this.iqSetHandler(_9);
-return;
-}else{
-if(_9.getAttribute("type")=="get"){
-return;
-}
-}
-},presenceHandler:function(_a){
-switch(_a.getAttribute("type")){
-case "subscribe":
-this.presenceSubscriptionRequest(_a.getAttribute("from"));
-break;
-case "subscribed":
-case "unsubscribed":
-break;
-case "error":
-this.processXmppError(_a);
-break;
-default:
-this.presenceUpdate(_a);
-break;
-}
-},featuresHandler:function(_b){
-var _c=[];
-var _d=false;
-var _e=false;
-if(_b.hasChildNodes()){
-for(var i=0;i<_b.childNodes.length;i++){
-var n=_b.childNodes[i];
-switch(n.nodeName){
-case "mechanisms":
-for(var x=0;x<n.childNodes.length;x++){
-_c.push(n.childNodes[x].firstChild.nodeValue);
-}
-break;
-case "bind":
-_d=true;
-break;
-case "session":
-_e=true;
-}
-}
-}
-if(this.state==dojox.xmpp.xmpp.CONNECTED){
-if(!this.auth){
-for(var i=0;i<_c.length;i++){
-try{
-this.auth=dojox.xmpp.sasl.registry.match(_c[i],this);
-break;
-}
-catch(e){
-console.warn("No suitable auth mechanism found for: ",_c[i]);
-}
-}
-}else{
-if(_d){
-this.bindResource(_e);
-}
-}
-}
-},saslHandler:function(_f){
-if(_f.nodeName=="success"){
-this.auth.onSuccess();
-return;
-}
-if(_f.nodeName=="challenge"){
-this.auth.onChallenge(_f);
-return;
-}
-if(_f.hasChildNodes()){
-this.onLoginFailure(_f.firstChild.nodeName);
-this.session.setState("Terminate",_f.firstChild.nodeName);
-}
-},sendRestart:function(){
-this.session._sendRestart();
-},chatHandler:function(msg){
-var _10={from:msg.getAttribute("from"),to:msg.getAttribute("to")};
-var _11=null;
-for(var i=0;i<msg.childNodes.length;i++){
-var n=msg.childNodes[i];
-if(n.hasChildNodes()){
-switch(n.nodeName){
-case "thread":
-_10.chatid=n.firstChild.nodeValue;
-break;
-case "body":
-if(!n.getAttribute("xmlns")||(n.getAttribute("xmlns")=="")){
-_10.body=n.firstChild.nodeValue;
-}
-break;
-case "subject":
-_10.subject=n.firstChild.nodeValue;
-case "html":
-if(n.getAttribute("xmlns")==dojox.xmpp.xmpp.XHTML_IM_NS){
-_10.xhtml=n.getElementsByTagName("body")[0];
-}
-break;
-case "x":
-break;
-default:
-}
-}
-}
-var _12=-1;
-if(_10.chatid){
-for(var i=0;i<this.chatRegister.length;i++){
-var ci=this.chatRegister[i];
-if(ci&&ci.chatid==_10.chatid){
-_12=i;
-break;
-}
-}
-}else{
-for(var i=0;i<this.chatRegister.length;i++){
-var ci=this.chatRegister[i];
-if(ci){
-if(ci.uid==this.getBareJid(_10.from)){
-_12=i;
-}
-}
-}
-}
-if(_12>-1&&_11){
-var _13=this.chatRegister[_12];
-_13.setState(_11);
-if(_13.firstMessage){
-if(_11==dojox.xmpp.chat.ACTIVE_STATE){
-_13.useChatState=(_11!=null)?true:false;
-_13.firstMessage=false;
-}
-}
-}
-if((!_10.body||_10.body=="")&&!_10.xhtml){
-return;
-}
-if(_12>-1){
-var _13=this.chatRegister[_12];
-_13.recieveMessage(_10);
-}else{
-var _14=new dojox.xmpp.ChatService();
-_14.uid=this.getBareJid(_10.from);
-_14.chatid=_10.chatid;
-_14.firstMessage=true;
-if(!_11||_11!=dojox.xmpp.chat.ACTIVE_STATE){
-this.useChatState=false;
-}
-this.registerChatInstance(_14,_10);
-}
-},simpleMessageHandler:function(msg){
-},registerChatInstance:function(_15,_16){
-_15.setSession(this);
-this.chatRegister.push(_15);
-this.onRegisterChatInstance(_15,_16);
-_15.recieveMessage(_16,true);
-},iqSetHandler:function(msg){
-if(msg.hasChildNodes()){
-var fn=msg.firstChild;
-switch(fn.nodeName){
-case "query":
-if(fn.getAttribute("xmlns")=="jabber:iq:roster"){
-this.rosterSetHandler(fn);
-this.sendIqResult(msg.getAttribute("id"),msg.getAttribute("from"));
-}
-break;
-default:
-break;
-}
-}
-},sendIqResult:function(_17,to){
-var req={id:_17,to:to||this.domain,type:"result",from:this.jid+"/"+this.resource};
-this.dispatchPacket(dojox.xmpp.util.createElement("iq",req,true));
-},rosterSetHandler:function(_18){
-for(var i=0;i<_18.childNodes.length;i++){
-var n=_18.childNodes[i];
-if(n.nodeName=="item"){
-var _19=false;
-var _1a=-1;
-var _1b=null;
-var _1c=null;
-for(var x=0;x<this.roster.length;x++){
-var r=this.roster[x];
-if(n.getAttribute("jid")==r.jid){
-_19=true;
-if(n.getAttribute("subscription")=="remove"){
-_1b={id:r.jid,name:r.name,groups:[]};
-for(var y=0;y<r.groups.length;y++){
-_1b.groups.push(r.groups[y]);
-}
-this.roster.splice(x,1);
-_1a=dojox.xmpp.roster.REMOVED;
-}else{
-_1c=dojo.clone(r);
-var _1d=n.getAttribute("name");
-if(_1d){
-this.roster[x].name=_1d;
-}
-r.groups=[];
-if(n.getAttribute("subscription")){
-r.status=n.getAttribute("subscription");
-}
-r.substatus=dojox.xmpp.presence.SUBSCRIPTION_SUBSTATUS_NONE;
-if(n.getAttribute("ask")=="subscribe"){
-r.substatus=dojox.xmpp.presence.SUBSCRIPTION_REQUEST_PENDING;
-}
-for(var y=0;y<n.childNodes.length;y++){
-var _1e=n.childNodes[y];
-if((_1e.nodeName=="group")&&(_1e.hasChildNodes())){
-var _1f=_1e.firstChild.nodeValue;
-r.groups.push(_1f);
-}
-}
-_1b=r;
-_1a=dojox.xmpp.roster.CHANGED;
-}
-break;
-}
-}
-if(!_19&&(n.getAttribute("subscription")!="remove")){
-r=this.createRosterEntry(n);
-_1b=r;
-_1a=dojox.xmpp.roster.ADDED;
-}
-switch(_1a){
-case dojox.xmpp.roster.ADDED:
-this.onRosterAdded(_1b);
-break;
-case dojox.xmpp.roster.REMOVED:
-this.onRosterRemoved(_1b);
-break;
-case dojox.xmpp.roster.CHANGED:
-this.onRosterChanged(_1b,_1c);
-break;
-}
-}
-}
-},presenceUpdate:function(msg){
-if(msg.getAttribute("to")){
-var jid=this.getBareJid(msg.getAttribute("to"));
-if(jid!=this.jid){
-return;
-}
-}
-var _20=this.getResourceFromJid(msg.getAttribute("from"));
-var p={from:this.getBareJid(msg.getAttribute("from")),resource:_20,show:dojox.xmpp.presence.STATUS_ONLINE,priority:5,hasAvatar:false};
-if(msg.getAttribute("type")=="unavailable"){
-p.show=dojox.xmpp.presence.STATUS_OFFLINE;
-}
-for(var i=0;i<msg.childNodes.length;i++){
-var n=msg.childNodes[i];
-if(n.hasChildNodes()){
-switch(n.nodeName){
-case "status":
-case "show":
-p[n.nodeName]=n.firstChild.nodeValue;
-break;
-case "status":
-p.priority=parseInt(n.firstChild.nodeValue);
-break;
-case "x":
-if(n.firstChild&&n.firstChild.firstChild&&n.firstChild.firstChild.nodeValue!=""){
-p.avatarHash=n.firstChild.firstChild.nodeValue;
-p.hasAvatar=true;
-}
-break;
-}
-}
-}
-this.onPresenceUpdate(p);
-},retrieveRoster:function(){
-var _21={id:this.getNextIqId(),from:this.jid+"/"+this.resource,type:"get"};
-var req=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_21,false));
-req.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:roster"},true));
-req.append("</iq>");
-var def=this.dispatchPacket(req,"iq",_21.id);
-def.addCallback(this,"onRetrieveRoster");
-},getRosterIndex:function(jid){
-if(jid.indexOf("@")==-1){
-jid+="@"+this.domain;
-}
-for(var i=0;i<this.roster.length;i++){
-if(jid==this.roster[i].jid){
-return i;
-}
-}
-return -1;
-},createRosterEntry:function(_22){
-var re={name:_22.getAttribute("name"),jid:_22.getAttribute("jid"),groups:[],status:dojox.xmpp.presence.SUBSCRIPTION_NONE,substatus:dojox.xmpp.presence.SUBSCRIPTION_SUBSTATUS_NONE};
-if(!re.name){
-re.name=re.id;
-}
-for(var i=0;i<_22.childNodes.length;i++){
-var n=_22.childNodes[i];
-if(n.nodeName=="group"&&n.hasChildNodes()){
-re.groups.push(n.firstChild.nodeValue);
-}
-}
-if(_22.getAttribute("subscription")){
-re.status=_22.getAttribute("subscription");
-}
-if(_22.getAttribute("ask")=="subscribe"){
-re.substatus=dojox.xmpp.presence.SUBSCRIPTION_REQUEST_PENDING;
-}
-return re;
-},bindResource:function(_23){
-var _24={id:this.getNextIqId(),type:"set"};
-var _25=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_24,false));
-_25.append(dojox.xmpp.util.createElement("bind",{xmlns:dojox.xmpp.xmpp.BIND_NS},false));
-if(this.resource){
-_25.append(dojox.xmpp.util.createElement("resource"));
-_25.append(this.resource);
-_25.append("</resource>");
-}
-_25.append("</bind></iq>");
-var def=this.dispatchPacket(_25,"iq",_24.id);
-def.addCallback(this,function(msg){
-this.onBindResource(msg,_23);
-return msg;
+
+dojox.xmpp.xmppSession = function(props){
+	this.roster = [];
+	this.chatRegister = [];
+	this._iqId = Math.round(Math.random() * 1000000000);
+
+	//mixin any options that we want to provide to this service
+	if (props && dojo.isObject(props)) {
+		dojo.mixin(this, props);
+	}
+
+	this.session = new dojox.xmpp.TransportSession(props); 
+	dojo.connect(this.session, "onReady", this, "onTransportReady");
+	dojo.connect(this.session, "onTerminate", this, "onTransportTerminate");
+	dojo.connect(this.session, "onProcessProtocolResponse", this, "processProtocolResponse");
+};
+
+
+dojo.extend(dojox.xmpp.xmppSession, {
+
+		roster: [],
+		chatRegister: [],
+		_iqId: 0,
+	
+		open: function(user, password, resource){
+
+			if (!user) {
+				throw new Error("User id cannot be null");
+			} else {
+				this.jid = user;
+				if(user.indexOf('@') == -1) {
+					this.jid = this.jid + '@' + this.domain;
+				}
+        	}
+
+			//allow null password here as its not needed in the SSO case
+			if (password) {
+				this.password = password;
+			}
+
+			//normally you should NOT supply a resource and let the server send you one
+			//as part of your jid...see onBindResource()
+			if (resource) {
+				this.resource = resource;
+			}
+
+			this.session.open();
+		},
+
+		close: function(){
+			this.state = dojox.xmpp.xmpp.TERMINATE;
+			this.session.close(dojox.xmpp.util.createElement("presence",{type:"unavailable",xmlns:dojox.xmpp.xmpp.CLIENT_NS},true));	
+		},
+
+		processProtocolResponse: function(msg){
+			//console.log("xmppSession::processProtocolResponse() ", msg, msg.nodeName);
+			var type = msg.nodeName;
+			var nsIndex =type.indexOf(":");
+			if(nsIndex > 0) {
+				type = type.substring(nsIndex+1);
+			}
+			switch(type){
+				case "iq":
+				case "presence":
+				case "message":
+				case "features":
+					this[type + "Handler"](msg);
+					break;
+				default:
+					//console.log("default action?", msg.getAttribute('xmlns'));
+					if(msg.getAttribute('xmlns')==dojox.xmpp.xmpp.SASL_NS){
+						this.saslHandler(msg);
+					}	
+			}
+		},
+
+		//HANDLERS 
+
+		messageHandler: function(msg){
+			//console.log("xmppSession::messageHandler() ",msg);
+			switch(msg.getAttribute('type')){
+				case "chat":
+					this.chatHandler(msg);
+					break;
+				case "normal":
+				default:
+					this.simpleMessageHandler(msg);	
+			}
+			
+		},
+
+		iqHandler: function(msg){
+			//console.log("xmppSession::iqHandler()", msg);
+			if (msg.getAttribute('type')=="set"){
+				this.iqSetHandler(msg);
+				return;
+			} else if (msg.getAttribute('type')=='get'){
+			//	this.sendStanzaError('iq', this.domain, msg.getAttribute('from'), 'cancel', 'service-unavailable', 'service not implemented');
+				return;
+			}
+		},
+
+		presenceHandler: function(msg){
+			//console.log("xmppSession::presenceHandler()");
+			switch(msg.getAttribute('type')){
+				case 'subscribe':
+					//console.log("PresenceHandler: ", msg.getAttribute('from'));
+					this.presenceSubscriptionRequest(msg.getAttribute('from'));
+					break;
+				case 'subscribed':
+				case 'unsubscribed':
+					break;
+				case 'error':		
+					this.processXmppError(msg);
+					//console.log("xmppService::presenceHandler() Error");
+					break;
+				default:
+					this.presenceUpdate(msg);
+					break;
+			}
+		},
+
+		featuresHandler: function(msg){
+			//console.log("xmppSession::featuresHandler() ",msg);
+			var authMechanisms = [];
+			var hasBindFeature = false;
+			var hasSessionFeature = false;
+
+			if(msg.hasChildNodes()){
+				for(var i=0; i<msg.childNodes.length;i++){
+					var n = msg.childNodes[i];
+					//console.log("featuresHandler::node", n);
+					switch(n.nodeName){
+						case 'mechanisms':
+							for (var x=0; x<n.childNodes.length; x++){
+								//console.log("featuresHandler::node::mechanisms", n.childNodes[x].firstChild.nodeValue);
+								authMechanisms.push(n.childNodes[x].firstChild.nodeValue);
+							}
+							break;
+						case 'bind':
+							//if (n.getAttribute('xmlns')==dojox.xmpp.xmpp.BIND_NS) {
+							hasBindFeature = true;
+						//	}
+							break;
+						case 'session':
+							hasSessionFeature = true;
+					}	
+				}
+			}
+			//console.log("Has connected/bind?", this.state, hasBindFeature, authMechanisms);
+			if(this.state == dojox.xmpp.xmpp.CONNECTED){
+				if(!this.auth){
+					// start the login
+					for(var i=0; i<authMechanisms.length; i++){
+						try{
+							this.auth = dojox.xmpp.sasl.registry.match(authMechanisms[i], this);
+							break;
+						}catch(e){
+							console.warn("No suitable auth mechanism found for: ", authMechanisms[i]);
+						}
+					}
+				}else if(hasBindFeature){
+					this.bindResource(hasSessionFeature);
+				}
+			}
+		},
+
+		saslHandler: function(msg){
+			//console.log("xmppSession::saslHandler() ", msg);
+			if(msg.nodeName=="success"){
+				this.auth.onSuccess();
+				return;
+			}
+
+			if(msg.nodeName=="challenge"){
+				this.auth.onChallenge(msg);
+				return;
+			}
+
+			if(msg.hasChildNodes()){
+				this.onLoginFailure(msg.firstChild.nodeName);
+				this.session.setState('Terminate', msg.firstChild.nodeName);
+			}
+		},
+
+		sendRestart: function(){
+			this.session._sendRestart();
+		},
+
+
+		//SUB HANDLERS
+
+		chatHandler: function(msg){
+			//console.log("xmppSession::chatHandler() ", msg);
+			var message = {
+				from: msg.getAttribute('from'),
+				to: msg.getAttribute('to')
+			}
+
+			var chatState = null;
+				//console.log("chat child node ", msg.childNodes, msg.childNodes.length);
+			for (var i=0; i<msg.childNodes.length; i++){
+				var n = msg.childNodes[i];
+				if (n.hasChildNodes()){
+					//console.log("chat child node ", n);
+					switch(n.nodeName){
+						case 'thread':
+							message.chatid = n.firstChild.nodeValue;
+							break;
+						case 'body':
+							if (!n.getAttribute('xmlns') || (n.getAttribute('xmlns')=="")){
+								message.body = n.firstChild.nodeValue;
+							}
+							break;
+						case 'subject':
+							message.subject = n.firstChild.nodeValue;
+						case 'html':
+							if (n.getAttribute('xmlns')==dojox.xmpp.xmpp.XHTML_IM_NS){
+								message.xhtml = n.getElementsByTagName("body")[0];
+							}
+							break;
+						case 'x':
+							break;
+						default:
+							//console.log("xmppSession::chatHandler() Unknown node type: ",n.nodeName);
+					}
+				}
+				/*//console.log("Foo", n, n.nodeName);
+				if(n.getAttribute('xmlns')==dojox.xmpp.chat.CHAT_STATE_NS){
+					chatState = n.nodeName;
+				}*/
+			}
+
+			var found = -1;
+			if (message.chatid){
+				for (var i=0; i< this.chatRegister.length; i++){
+					var ci = this.chatRegister[i];
+					////console.log("ci.chatid: ", ci.chatid, message.chatid);
+					if (ci && ci.chatid == message.chatid) {
+						found = i;
+						break;	
+					}
+				}
+			} else {
+				for (var i=0; i< this.chatRegister.length; i++){
+					var ci = this.chatRegister[i];
+					if(ci){
+						if (ci.uid==this.getBareJid(message.from)){
+							found = i;
+						}
+					}
+				}
+			}	
+
+			if (found>-1 && chatState){
+				var chat = this.chatRegister[found];
+				chat.setState(chatState);
+
+				if (chat.firstMessage){
+					if (chatState == dojox.xmpp.chat.ACTIVE_STATE) {
+						chat.useChatState = (chatState != null) ? true : false;
+						chat.firstMessage = false;	
+					}
+				}
+			} 
+
+			if ((!message.body || message.body=="") && !message.xhtml) {return;}
+
+			if (found>-1){
+				var chat = this.chatRegister[found];
+				chat.recieveMessage(message);
+			}else{
+				var chatInstance = new dojox.xmpp.ChatService();
+				chatInstance.uid = this.getBareJid(message.from);
+				chatInstance.chatid = message.chatid;
+				chatInstance.firstMessage = true;
+				if(!chatState || chatState != dojox.xmpp.chat.ACTIVE_STATE){
+					this.useChatState = false;
+				}
+				this.registerChatInstance(chatInstance, message);
+			}
+		},
+
+		simpleMessageHandler: function(msg){
+			//console.log("xmppSession::simpleMessageHandler() ", msg);
+		},
+
+		registerChatInstance: function(chatInstance, message){
+			chatInstance.setSession(this);
+			this.chatRegister.push(chatInstance);
+			this.onRegisterChatInstance(chatInstance, message);
+			chatInstance.recieveMessage(message,true);
+		},
+		
+		iqSetHandler: function(msg){
+			if (msg.hasChildNodes()){
+				var fn = msg.firstChild;
+				switch(fn.nodeName){
+					case 'query':
+						if(fn.getAttribute('xmlns') == "jabber:iq:roster"){
+							this.rosterSetHandler(fn);
+							this.sendIqResult(msg.getAttribute('id'), msg.getAttribute('from'));	
+						}
+						break;
+					default:
+					//	this.sendStanzaError('iq', this.domain, msg.getAttribute('id'), 'cancel', 'service-unavailable', 'service not implemented');
+						break;
+				}
+			}
+		},
+
+		sendIqResult: function(iqId, to){
+			var req = {
+				id: iqId,
+				to: to || this.domain,
+				type: 'result',
+				from: this.jid + "/" + this.resource
+			}
+			this.dispatchPacket(dojox.xmpp.util.createElement("iq",req,true));
+		},
+
+		rosterSetHandler: function(elem){
+			//console.log("xmppSession::rosterSetHandler()", arguments);
+			for (var i=0; i<elem.childNodes.length;i++){
+				var n = elem.childNodes[i];
+			
+				if (n.nodeName=="item"){
+					var found = false;
+					var state = -1;
+					var rosterItem = null;
+					var previousCopy = null;
+					for(var x=0; x<this.roster.length;x++){
+						var r = this.roster[x];
+						if(n.getAttribute('jid')==r.jid){
+							found = true;
+							if(n.getAttribute('subscription')=='remove'){
+								//remove the item
+								rosterItem = {
+									id: r.jid,
+									name: r.name,
+									groups:[]
+								}
+
+								for (var y=0;y<r.groups.length;y++){
+									rosterItem.groups.push(r.groups[y]);
+								}
+
+								this.roster.splice(x,1);
+								state = dojox.xmpp.roster.REMOVED;
+
+							} else { //update
+								previousCopy = dojo.clone(r);
+								var itemName = n.getAttribute('name');
+								if (itemName){
+									this.roster[x].name = itemName;
+								}	
+
+								r.groups = [];
+
+								if (n.getAttribute('subscription')){
+									r.status = n.getAttribute('subscription');
+								}
+						
+								r.substatus = dojox.xmpp.presence.SUBSCRIPTION_SUBSTATUS_NONE;
+								if(n.getAttribute('ask')=='subscribe'){
+									r.substatus = dojox.xmpp.presence.SUBSCRIPTION_REQUEST_PENDING;
+								}
+					
+								for(var y=0;y<n.childNodes.length;y++){
+									var groupNode = n.childNodes[y];
+									if ((groupNode.nodeName=='group')&&(groupNode.hasChildNodes())){
+										var gname = groupNode.firstChild.nodeValue;
+										r.groups.push(gname);
+									}
+								}
+								rosterItem = r;
+								state = dojox.xmpp.roster.CHANGED;
+							}
+							break;
+						}
+					}
+					if(!found && (n.getAttribute('subscription')!='remove')){
+						r = this.createRosterEntry(n);
+						rosterItem = r;
+						state = dojox.xmpp.roster.ADDED;
+					}
+				
+					switch(state){
+						case dojox.xmpp.roster.ADDED:
+							this.onRosterAdded(rosterItem);
+							break;
+						case dojox.xmpp.roster.REMOVED:
+							this.onRosterRemoved(rosterItem);
+							break;
+						case dojox.xmpp.roster.CHANGED:
+							this.onRosterChanged(rosterItem, previousCopy);
+							break;
+					}	
+				}	
+			}
+		},
+
+		presenceUpdate: function(msg){
+			if(msg.getAttribute('to')){
+				var jid = this.getBareJid(msg.getAttribute('to'));
+				if(jid != this.jid) {
+					//console.log("xmppService::presenceUpdate Update Recieved with wrong address - ",jid);
+					return;
+				}
+			}
+
+			var fromRes = this.getResourceFromJid(msg.getAttribute('from'));
+
+			var p = {
+				from: this.getBareJid(msg.getAttribute('from')),
+				resource: fromRes,
+				show: dojox.xmpp.presence.STATUS_ONLINE,
+				priority: 5,
+				hasAvatar: false
+			}	
+
+			if(msg.getAttribute('type')=='unavailable'){
+				p.show=dojox.xmpp.presence.STATUS_OFFLINE
+			}
+
+			for (var i=0; i<msg.childNodes.length;i++){
+				var n=msg.childNodes[i];
+				if (n.hasChildNodes()){
+					switch(n.nodeName){
+						case 'status':
+						case 'show':
+							p[n.nodeName]=n.firstChild.nodeValue;
+							break;
+						case 'status':
+							p.priority=parseInt(n.firstChild.nodeValue);
+							break;
+						case 'x':
+							if(n.firstChild && n.firstChild.firstChild &&  n.firstChild.firstChild.nodeValue != "") { 
+								p.avatarHash= n.firstChild.firstChild.nodeValue;
+								p.hasAvatar = true;
+							}
+							break;
+					}
+				}
+			}	
+
+			this.onPresenceUpdate(p);
+		},
+
+		retrieveRoster: function(){
+			////console.log("xmppService::retrieveRoster()");
+			var props={
+				id: this.getNextIqId(),
+				from: this.jid + "/" + this.resource,
+				type: "get"
+			}
+			var req = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",props,false));
+			req.append(dojox.xmpp.util.createElement("query",{xmlns: "jabber:iq:roster"},true));
+			req.append("</iq>");
+
+			var def = this.dispatchPacket(req,"iq", props.id);
+			def.addCallback(this, "onRetrieveRoster");
+			
+		},
+
+		getRosterIndex: function(jid){
+			if(jid.indexOf('@')==-1){
+				jid += '@' + this.domain;
+			}
+			for (var i=0; i<this.roster.length;i++){
+				if(jid == this.roster[i].jid) { return i; }
+			}
+			return -1;
+		},
+
+		createRosterEntry: function(elem){
+			////console.log("xmppService::createRosterEntry()");
+			var re = {
+				name: elem.getAttribute('name'),
+				jid: elem.getAttribute('jid'),
+				groups: [],
+				status: dojox.xmpp.presence.SUBSCRIPTION_NONE,
+				substatus: dojox.xmpp.presence.SUBSCRIPTION_SUBSTATUS_NONE
+			//	displayToUser: false
+			}	
+
+			if (!re.name){
+				re.name = re.id;
+			}
+			
+			
+
+			for(var i=0; i<elem.childNodes.length;i++){
+				var n = elem.childNodes[i];
+				if (n.nodeName=='group' && n.hasChildNodes()){
+					re.groups.push(n.firstChild.nodeValue);
+				}
+			} 
+
+			if (elem.getAttribute('subscription')){
+				re.status = elem.getAttribute('subscription');
+			}	
+
+			if (elem.getAttribute('ask')=='subscribe'){
+				re.substatus = dojox.xmpp.presence.SUBSCRIPTION_REQUEST_PENDING;
+			}	
+			//Display contact rules from http://www.xmpp.org/extensions/xep-0162.html#contacts
+		/*	if(re.status == dojox.xmpp.presence.SUBSCRIPTION_REQUEST_PENDING || 
+				re.status == dojox.xmpp.presence.SUBSCRIPTION_TO || 
+				re.status == dojox.xmpp.presence.SUBSCRIPTION_BOTH ||
+				re.groups.length > 0 ||
+				re.name
+				) {
+					re.displayToUser = true;
+				}
+*/
+			return re;
+		},
+
+		bindResource: function(hasSession){
+			var props = {
+				id: this.getNextIqId(),
+				type: "set"
+			}
+			var bindReq = new dojox.string.Builder(dojox.xmpp.util.createElement("iq", props, false));
+			bindReq.append(dojox.xmpp.util.createElement("bind", {xmlns: dojox.xmpp.xmpp.BIND_NS}, false));
+
+			if (this.resource){
+				bindReq.append(dojox.xmpp.util.createElement("resource"));
+				bindReq.append(this.resource);
+				bindReq.append("</resource>");
+			}
+
+			bindReq.append("</bind></iq>");
+
+			var def = this.dispatchPacket(bindReq, "iq", props.id);
+			def.addCallback(this, function(msg){
+				this.onBindResource(msg, hasSession);
+				return msg;
+			});
+		},
+
+		getNextIqId: function(){
+			return "im_" + this._iqId++;
+		},
+
+		presenceSubscriptionRequest: function(msg) {
+			this.onSubscriptionRequest(msg);
+			/*
+			this.onSubscriptionRequest({
+				from: msg,
+				resource:"",
+				show:"",
+				status:"",
+				priority: 5
+			});
+			*/
+		},
+
+		dispatchPacket: function(msg, type, matchId){
+			if (this.state != "Terminate") {
+				return this.session.dispatchPacket(msg,type,matchId);
+			}else{
+				//console.log("xmppSession::dispatchPacket - Session in Terminate state, dropping packet");
+			}
+		},
+
+		setState: function(state, message){
+			if (this.state != state){
+				if (this["on"+state]){
+					this["on"+state](state, this.state, message);
+				}	
+				this.state=state;
+			}
+		},
+
+		search: function(searchString, service, searchAttribute){
+			var req={
+				id: this.getNextIqId(),
+				"xml:lang": this.lang,
+				type: 'set',
+				from: this.jid + '/' + this.resource,
+				to: service
+			}
+			var request = new dojox.string.Builder(dojox.xmpp.util.createElement("iq",req,false));
+			request.append(dojox.xmpp.util.createElement('query',{xmlns:'jabber:iq:search'},false));
+			request.append(dojox.xmpp.util.createElement(searchAttribute,{},false));
+			request.append(searchString);
+			request.append("</").append(searchAttribute).append(">");
+			request.append("</query></iq>");
+
+			var def = this.dispatchPacket(request.toString,"iq",req.id);
+			def.addCallback(this, "_onSearchResults");
+		},
+
+		_onSearchResults: function(msg){
+			if ((msg.getAttribute('type')=='result')&&(msg.hasChildNodes())){
+				//console.log("xmppSession::_onSearchResults(): ", msg.firstChild);
+
+				//call the search results event with an array of results
+				this.onSearchResults([]);
+			}
+		},
+
+		// EVENTS
+
+		onLogin: function(){ 
+			////console.log("xmppSession::onLogin()"); 
+			this.retrieveRoster();
+		},
+
+		onLoginFailure: function(msg){
+			//console.log("xmppSession::onLoginFailure ", msg);
+		},
+
+		onBindResource: function(msg, hasSession){
+			//console.log("xmppSession::onBindResource() ", msg);
+		
+			if (msg.getAttribute('type')=='result'){
+				//console.log("xmppSession::onBindResource() Got Result Message");
+				if ((msg.hasChildNodes()) && (msg.firstChild.nodeName=="bind")){
+					var bindTag = msg.firstChild;
+					if ((bindTag.hasChildNodes()) && (bindTag.firstChild.nodeName=="jid")){
+						if (bindTag.firstChild.hasChildNodes()){
+							var fulljid = bindTag.firstChild.firstChild.nodeValue;
+							this.jid = this.getBareJid(fulljid);
+							this.resource = this.getResourceFromJid(fulljid);
+						}
+					}
+					if(hasSession){
+						var props = {
+							id: this.getNextIqId(),
+							type: "set"
+						}
+						var bindReq = new dojox.string.Builder(dojox.xmpp.util.createElement("iq", props, false));
+						bindReq.append(dojox.xmpp.util.createElement("session", {xmlns: dojox.xmpp.xmpp.SESSION_NS}, true));
+						bindReq.append("</iq>");
+
+						var def = this.dispatchPacket(bindReq, "iq", props.id);
+						def.addCallback(this, "onBindSession");
+						return;
+					}
+				}else{
+					//console.log("xmppService::onBindResource() No Bind Element Found");
+				}
+
+				this.onLogin();
+		
+			}else if(msg.getAttribute('type')=='error'){
+				//console.log("xmppSession::onBindResource() Bind Error ", msg);
+				var err = this.processXmppError(msg);
+				this.onLoginFailure(err);
+			}
+		},
+
+		onBindSession: function(msg){
+			if(msg.getAttribute('type')=='error'){
+				//console.log("xmppSession::onBindSession() Bind Error ", msg);
+				var err = this.processXmppError(msg);
+				this.onLoginFailure(err);
+			}else{
+				this.onLogin();
+			}
+		},
+
+		onSearchResults: function(results){
+			//console.log("xmppSession::onSearchResult() ", results);
+		},
+
+		onRetrieveRoster: function(msg){
+			////console.log("xmppService::onRetrieveRoster() ", arguments);
+
+			if ((msg.getAttribute('type')=='result') && msg.hasChildNodes()){
+				var query = msg.getElementsByTagName('query')[0];
+				if (query.getAttribute('xmlns')=="jabber:iq:roster"){
+					for (var i=0;i<query.childNodes.length;i++){
+						if (query.childNodes[i].nodeName=="item"){
+							this.roster[i] = this.createRosterEntry(query.childNodes[i]);
+						}
+					}
+				}	
+			}else if(msg.getAttribute('type')=="error"){
+				//console.log("xmppService::storeRoster()  Error recieved on roster get");	
+			}
+
+			////console.log("Roster: ", this.roster);
+			this.setState(dojox.xmpp.xmpp.ACTIVE);
+			this.onRosterUpdated();
+
+			return msg;	
+		},
+		
+		onRosterUpdated: function() {},
+
+		onSubscriptionRequest: function(req){},
+
+		onPresenceUpdate: function(p){},
+
+		onTransportReady: function(){
+			this.setState(dojox.xmpp.xmpp.CONNECTED);
+			this.rosterService = new dojox.xmpp.RosterService(this);
+			this.presenceService= new dojox.xmpp.PresenceService(this);
+			this.userService = new dojox.xmpp.UserService(this);
+
+			////console.log("xmppSession::onTransportReady()");
+		},
+
+		onTransportTerminate: function(newState, oldState, message){
+			this.setState(dojox.xmpp.xmpp.TERMINATE, message);
+		},
+
+		onConnected: function(){
+			////console.log("xmppSession::onConnected()");
+		},
+
+		onTerminate: function(newState, oldState, message){
+			//console.log("xmppSession::onTerminate()", newState, oldState, message);
+		},
+
+		onActive: function(){
+			////console.log("xmppSession::onActive()");
+			//this.presenceService.publish({show: dojox.xmpp.presence.STATUS_ONLINE});
+		},
+
+		onRegisterChatInstance: function(chatInstance, message){
+			////console.log("xmppSession::onRegisterChatInstance()");
+		},
+
+		onRosterAdded: function(ri){},
+		onRosterRemoved: function(ri){},
+		onRosterChanged: function(ri, previousCopy){},
+
+		//Utilities
+
+		processXmppError: function(msg){
+			////console.log("xmppSession::processXmppError() ", msg);
+			var err = {
+				stanzaType: msg.nodeName,
+				id: msg.getAttribute('id')
+			}
+	
+			for (var i=0; i<msg.childNodes.length; i++){
+				var n = msg.childNodes[i];
+				switch(n.nodeName){
+					case 'error':
+						err.errorType = n.getAttribute('type');
+						for (var x=0; x< n.childNodes.length; x++){
+							var cn = n.childNodes[x];
+							if ((cn.nodeName=="text") && (cn.getAttribute('xmlns') == dojox.xmpp.xmpp.STANZA_NS) && cn.hasChildNodes()) {	
+								err.message = cn.firstChild.nodeValue;
+							} else if ((cn.getAttribute('xmlns') == dojox.xmpp.xmpp.STANZA_NS) &&(!cn.hasChildNodes())){
+								err.condition = cn.nodeName;
+							}
+						}
+						break;
+					default:
+						break;
+				}
+			}	
+			return err;
+		},
+
+		sendStanzaError: function(stanzaType,to,id,errorType,condition,text){
+			////console.log("xmppSession: sendStanzaError() ", arguments);
+			var req = {type:'error'};
+			if (to) { req.to=to; }	
+			if (id) { req.id=id; }	
+		
+			var request = new dojox.string.Builder(dojox.xmpp.util.createElement(stanzaType,req,false));
+			request.append(dojox.xmpp.util.createElement('error',{type:errorType},false));
+			request.append(dojox.xmpp.util.createElement('condition',{xmlns:dojox.xmpp.xmpp.STANZA_NS},true));
+
+			if(text){
+				var textAttr={
+					xmlns: dojox.xmpp.xmpp.STANZA_NS,
+					"xml:lang":this.lang
+				}
+				request.append(dojox.xmpp.util.createElement('text',textAttr,false));
+				request.append(text).append("</text>");
+			}
+			request.append("</error></").append(stanzaType).append(">");
+
+			this.dispatchPacket(request.toString());
+		},
+
+		getBareJid: function(jid){
+			var i = jid.indexOf('/');
+			if (i != -1){
+				return jid.substring(0, i);
+			}
+			return jid;
+		},
+
+		getResourceFromJid: function(jid){
+			var i = jid.indexOf('/');
+			if (i != -1){
+				return jid.substring((i + 1), jid.length);
+			}
+			return "";
+		}
+
 });
-},getNextIqId:function(){
-return "im_"+this._iqId++;
-},presenceSubscriptionRequest:function(msg){
-this.onSubscriptionRequest(msg);
-},dispatchPacket:function(msg,_26,_27){
-if(this.state!="Terminate"){
-return this.session.dispatchPacket(msg,_26,_27);
-}else{
-}
-},setState:function(_28,_29){
-if(this.state!=_28){
-if(this["on"+_28]){
-this["on"+_28](_28,this.state,_29);
-}
-this.state=_28;
-}
-},search:function(_2a,_2b,_2c){
-var req={id:this.getNextIqId(),"xml:lang":this.lang,type:"set",from:this.jid+"/"+this.resource,to:_2b};
-var _2d=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",req,false));
-_2d.append(dojox.xmpp.util.createElement("query",{xmlns:"jabber:iq:search"},false));
-_2d.append(dojox.xmpp.util.createElement(_2c,{},false));
-_2d.append(_2a);
-_2d.append("</").append(_2c).append(">");
-_2d.append("</query></iq>");
-var def=this.dispatchPacket(_2d.toString,"iq",req.id);
-def.addCallback(this,"_onSearchResults");
-},_onSearchResults:function(msg){
-if((msg.getAttribute("type")=="result")&&(msg.hasChildNodes())){
-this.onSearchResults([]);
-}
-},onLogin:function(){
-this.retrieveRoster();
-},onLoginFailure:function(msg){
-},onBindResource:function(msg,_2e){
-if(msg.getAttribute("type")=="result"){
-if((msg.hasChildNodes())&&(msg.firstChild.nodeName=="bind")){
-var _2f=msg.firstChild;
-if((_2f.hasChildNodes())&&(_2f.firstChild.nodeName=="jid")){
-if(_2f.firstChild.hasChildNodes()){
-var _30=_2f.firstChild.firstChild.nodeValue;
-this.jid=this.getBareJid(_30);
-this.resource=this.getResourceFromJid(_30);
-}
-}
-if(_2e){
-var _31={id:this.getNextIqId(),type:"set"};
-var _32=new dojox.string.Builder(dojox.xmpp.util.createElement("iq",_31,false));
-_32.append(dojox.xmpp.util.createElement("session",{xmlns:dojox.xmpp.xmpp.SESSION_NS},true));
-_32.append("</iq>");
-var def=this.dispatchPacket(_32,"iq",_31.id);
-def.addCallback(this,"onBindSession");
-return;
-}
-}else{
-}
-this.onLogin();
-}else{
-if(msg.getAttribute("type")=="error"){
-var err=this.processXmppError(msg);
-this.onLoginFailure(err);
-}
-}
-},onBindSession:function(msg){
-if(msg.getAttribute("type")=="error"){
-var err=this.processXmppError(msg);
-this.onLoginFailure(err);
-}else{
-this.onLogin();
-}
-},onSearchResults:function(_33){
-},onRetrieveRoster:function(msg){
-if((msg.getAttribute("type")=="result")&&msg.hasChildNodes()){
-var _34=msg.getElementsByTagName("query")[0];
-if(_34.getAttribute("xmlns")=="jabber:iq:roster"){
-for(var i=0;i<_34.childNodes.length;i++){
-if(_34.childNodes[i].nodeName=="item"){
-this.roster[i]=this.createRosterEntry(_34.childNodes[i]);
-}
-}
-}
-}else{
-if(msg.getAttribute("type")=="error"){
-}
-}
-this.setState(dojox.xmpp.xmpp.ACTIVE);
-this.onRosterUpdated();
-return msg;
-},onRosterUpdated:function(){
-},onSubscriptionRequest:function(req){
-},onPresenceUpdate:function(p){
-},onTransportReady:function(){
-this.setState(dojox.xmpp.xmpp.CONNECTED);
-this.rosterService=new dojox.xmpp.RosterService(this);
-this.presenceService=new dojox.xmpp.PresenceService(this);
-this.userService=new dojox.xmpp.UserService(this);
-},onTransportTerminate:function(_35,_36,_37){
-this.setState(dojox.xmpp.xmpp.TERMINATE,_37);
-},onConnected:function(){
-},onTerminate:function(_38,_39,_3a){
-},onActive:function(){
-},onRegisterChatInstance:function(_3b,_3c){
-},onRosterAdded:function(ri){
-},onRosterRemoved:function(ri){
-},onRosterChanged:function(ri,_3d){
-},processXmppError:function(msg){
-var err={stanzaType:msg.nodeName,id:msg.getAttribute("id")};
-for(var i=0;i<msg.childNodes.length;i++){
-var n=msg.childNodes[i];
-switch(n.nodeName){
-case "error":
-err.errorType=n.getAttribute("type");
-for(var x=0;x<n.childNodes.length;x++){
-var cn=n.childNodes[x];
-if((cn.nodeName=="text")&&(cn.getAttribute("xmlns")==dojox.xmpp.xmpp.STANZA_NS)&&cn.hasChildNodes()){
-err.message=cn.firstChild.nodeValue;
-}else{
-if((cn.getAttribute("xmlns")==dojox.xmpp.xmpp.STANZA_NS)&&(!cn.hasChildNodes())){
-err.condition=cn.nodeName;
-}
-}
-}
-break;
-default:
-break;
-}
-}
-return err;
-},sendStanzaError:function(_3e,to,id,_3f,_40,_41){
-var req={type:"error"};
-if(to){
-req.to=to;
-}
-if(id){
-req.id=id;
-}
-var _42=new dojox.string.Builder(dojox.xmpp.util.createElement(_3e,req,false));
-_42.append(dojox.xmpp.util.createElement("error",{type:_3f},false));
-_42.append(dojox.xmpp.util.createElement("condition",{xmlns:dojox.xmpp.xmpp.STANZA_NS},true));
-if(_41){
-var _43={xmlns:dojox.xmpp.xmpp.STANZA_NS,"xml:lang":this.lang};
-_42.append(dojox.xmpp.util.createElement("text",_43,false));
-_42.append(_41).append("</text>");
-}
-_42.append("</error></").append(_3e).append(">");
-this.dispatchPacket(_42.toString());
-},getBareJid:function(jid){
-var i=jid.indexOf("/");
-if(i!=-1){
-return jid.substring(0,i);
-}
-return jid;
-},getResourceFromJid:function(jid){
-var i=jid.indexOf("/");
-if(i!=-1){
-return jid.substring((i+1),jid.length);
-}
-return "";
-}});
-}
diff --git a/util/LICENSE b/util/LICENSE
new file mode 100644
index 0000000..4c93ded
--- /dev/null
+++ b/util/LICENSE
@@ -0,0 +1,195 @@
+Dojo is available under *either* the terms of the modified BSD license *or* the
+Academic Free License version 2.1. As a recipient of Dojo, you may choose which
+license to receive this code under (except as noted in per-module LICENSE
+files). Some modules may not be the copyright of the Dojo Foundation. These
+modules contain explicit declarations of copyright in both the LICENSE files in
+the directories in which they reside and in the code itself. No external
+contributions are allowed under licenses which are fundamentally incompatible
+with the AFL or BSD licenses that Dojo is distributed under.
+
+The text of the AFL and BSD licenses is reproduced below. 
+
+-------------------------------------------------------------------------------
+The "New" BSD License:
+**********************
+
+Copyright (c) 2005-2010, The Dojo Foundation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this
+    list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+  * Neither the name of the Dojo Foundation nor the names of its contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------------------
+The Academic Free License, v. 2.1:
+**********************************
+
+This Academic Free License (the "License") applies to any original work of
+authorship (the "Original Work") whose owner (the "Licensor") has placed the
+following notice immediately following the copyright notice for the Original
+Work:
+
+Licensed under the Academic Free License version 2.1
+
+1) Grant of Copyright License. Licensor hereby grants You a world-wide,
+royalty-free, non-exclusive, perpetual, sublicenseable license to do the
+following:
+
+a) to reproduce the Original Work in copies;
+
+b) to prepare derivative works ("Derivative Works") based upon the Original
+Work;
+
+c) to distribute copies of the Original Work and Derivative Works to the
+public;
+
+d) to perform the Original Work publicly; and
+
+e) to display the Original Work publicly.
+
+2) Grant of Patent License. Licensor hereby grants You a world-wide,
+royalty-free, non-exclusive, perpetual, sublicenseable license, under patent
+claims owned or controlled by the Licensor that are embodied in the Original
+Work as furnished by the Licensor, to make, use, sell and offer for sale the
+Original Work and Derivative Works.
+
+3) Grant of Source Code License. The term "Source Code" means the preferred
+form of the Original Work for making modifications to it and all available
+documentation describing how to modify the Original Work. Licensor hereby
+agrees to provide a machine-readable copy of the Source Code of the Original
+Work along with each copy of the Original Work that Licensor distributes.
+Licensor reserves the right to satisfy this obligation by placing a
+machine-readable copy of the Source Code in an information repository
+reasonably calculated to permit inexpensive and convenient access by You for as
+long as Licensor continues to distribute the Original Work, and by publishing
+the address of that information repository in a notice immediately following
+the copyright notice that applies to the Original Work.
+
+4) Exclusions From License Grant. Neither the names of Licensor, nor the names
+of any contributors to the Original Work, nor any of their trademarks or
+service marks, may be used to endorse or promote products derived from this
+Original Work without express prior written permission of the Licensor. Nothing
+in this License shall be deemed to grant any rights to trademarks, copyrights,
+patents, trade secrets or any other intellectual property of Licensor except as
+expressly stated herein. No patent license is granted to make, use, sell or
+offer to sell embodiments of any patent claims other than the licensed claims
+defined in Section 2. No right is granted to the trademarks of Licensor even if
+such marks are included in the Original Work. Nothing in this License shall be
+interpreted to prohibit Licensor from licensing under different terms from this
+License any Original Work that Licensor otherwise would have a right to
+license.
+
+5) This section intentionally omitted.
+
+6) Attribution Rights. You must retain, in the Source Code of any Derivative
+Works that You create, all copyright, patent or trademark notices from the
+Source Code of the Original Work, as well as any notices of licensing and any
+descriptive text identified therein as an "Attribution Notice." You must cause
+the Source Code for any Derivative Works that You create to carry a prominent
+Attribution Notice reasonably calculated to inform recipients that You have
+modified the Original Work.
+
+7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
+the copyright in and to the Original Work and the patent rights granted herein
+by Licensor are owned by the Licensor or are sublicensed to You under the terms
+of this License with the permission of the contributor(s) of those copyrights
+and patent rights. Except as expressly stated in the immediately proceeding
+sentence, the Original Work is provided under this License on an "AS IS" BASIS
+and WITHOUT WARRANTY, either express or implied, including, without limitation,
+the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU.
+This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No
+license to Original Work is granted hereunder except under this disclaimer.
+
+8) Limitation of Liability. Under no circumstances and under no legal theory,
+whether in tort (including negligence), contract, or otherwise, shall the
+Licensor be liable to any person for any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License
+or the use of the Original Work including, without limitation, damages for loss
+of goodwill, work stoppage, computer failure or malfunction, or any and all
+other commercial damages or losses. This limitation of liability shall not
+apply to liability for death or personal injury resulting from Licensor's
+negligence to the extent applicable law prohibits such limitation. Some
+jurisdictions do not allow the exclusion or limitation of incidental or
+consequential damages, so this exclusion and limitation may not apply to You.
+
+9) Acceptance and Termination. If You distribute copies of the Original Work or
+a Derivative Work, You must make a reasonable effort under the circumstances to
+obtain the express assent of recipients to the terms of this License. Nothing
+else but this License (or another written agreement between Licensor and You)
+grants You permission to create Derivative Works based upon the Original Work
+or to exercise any of the rights granted in Section 1 herein, and any attempt
+to do so except under the terms of this License (or another written agreement
+between Licensor and You) is expressly prohibited by U.S. copyright law, the
+equivalent laws of other countries, and by international treaty. Therefore, by
+exercising any of the rights granted to You in Section 1 herein, You indicate
+Your acceptance of this License and all of its terms and conditions.
+
+10) Termination for Patent Action. This License shall terminate automatically
+and You may no longer exercise any of the rights granted to You by this License
+as of the date You commence an action, including a cross-claim or counterclaim,
+against Licensor or any licensee alleging that the Original Work infringes a
+patent. This termination provision shall not apply for an action alleging
+patent infringement by combinations of the Original Work with other software or
+hardware.
+
+11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this
+License may be brought only in the courts of a jurisdiction wherein the
+Licensor resides or in which Licensor conducts its primary business, and under
+the laws of that jurisdiction excluding its conflict-of-law provisions. The
+application of the United Nations Convention on Contracts for the International
+Sale of Goods is expressly excluded. Any use of the Original Work outside the
+scope of this License or after its termination shall be subject to the
+requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et
+seq., the equivalent laws of other countries, and international treaty. This
+section shall survive the termination of this License.
+
+12) Attorneys Fees. In any action to enforce the terms of this License or
+seeking damages relating thereto, the prevailing party shall be entitled to
+recover its costs and expenses, including, without limitation, reasonable
+attorneys' fees and costs incurred in connection with such action, including
+any appeal of such action. This section shall survive the termination of this
+License.
+
+13) Miscellaneous. This License represents the complete agreement concerning
+the subject matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent necessary to
+make it enforceable.
+
+14) Definition of "You" in This License. "You" throughout this License, whether
+in upper or lower case, means an individual or a legal entity exercising rights
+under, and complying with all of the terms of, this License. For legal
+entities, "You" includes any entity that controls, is controlled by, or is
+under common control with you. For purposes of this definition, "control" means
+(i) the power, direct or indirect, to cause the direction or management of such
+entity, whether by contract or otherwise, or (ii) ownership of fifty percent
+(50%) or more of the outstanding shares, or (iii) beneficial ownership of such
+entity.
+
+15) Right to Use. You may use the Original Work in all ways not otherwise
+restricted or conditioned by this License or by law, and Licensor promises not
+to interfere with or be responsible for such uses by You.
+
+This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved.
+Permission is hereby granted to copy and distribute this license without
+modification. This license may not be modified without the express written
+permission of its copyright owner.
diff --git a/dijit/LICENSE b/util/buildscripts/LICENSE
similarity index 100%
copy from dijit/LICENSE
copy to util/buildscripts/LICENSE
diff --git a/util/buildscripts/README b/util/buildscripts/README
new file mode 100644
index 0000000..d89acb8
--- /dev/null
+++ b/util/buildscripts/README
@@ -0,0 +1,44 @@
+The util/buildscripts directory allows you do to custom builds of the dojo source.
+
+REQUIREMENTS
+=======================
+The build system requires that Java 1.4.2 or later is installed.
+
+DIRECTORY STRUCTURE
+=======================
+Recommended directory structure and names (if using dijit and dojox in addition to
+dojo core):
+
+- dijit
+- dojo
+- dojox
+- util
+  - buildscripts
+
+Builds will be generated in a "release" directory that is a sibling to util
+(the output directory will also be printed at the end of the build).
+  
+DOING A BUILD
+=======================
+In the util/buildscripts directory, to run the the build, type the following:
+
+Windows-based operating systems:
+> build.bat
+
+All other operating systems:
+> build.sh
+(may need to chmod +x build.sh to get it to execute as a script)
+
+Typing the above command will give you some help text with the allowed build
+options.
+
+TYPICAL BUILDS
+=======================
+This command will use the build profile at util/buildscripts/profiles/standard.profile.js
+to do a build:
+
+> build.sh profile=standard action=release
+
+To do an xdomain build, add the loader argument:
+
+> build.sh profile=standard loader=xdomain action=release
diff --git a/util/buildscripts/build.bat b/util/buildscripts/build.bat
new file mode 100644
index 0000000..9e00b95
--- /dev/null
+++ b/util/buildscripts/build.bat
@@ -0,0 +1,3 @@
+java -classpath ../shrinksafe/js.jar;../shrinksafe/shrinksafe.jar org.mozilla.javascript.tools.shell.Main build.js %*
+
+ at rem java -Xms256m -Xmx256m -classpath ../shrinksafe/js.jar;../shrinksafe/shrinksafe.jar org.mozilla.javascript.tools.shell.Main  build.js %*
diff --git a/util/buildscripts/build.js b/util/buildscripts/build.js
new file mode 100644
index 0000000..91324b9
--- /dev/null
+++ b/util/buildscripts/build.js
@@ -0,0 +1,374 @@
+//Main build script for Dojo
+var buildTimerStart = (new Date()).getTime();
+buildScriptsPath = typeof buildScriptsPath == "undefined" ? "./" : buildScriptsPath;
+load(buildScriptsPath + "jslib/logger.js");
+load(buildScriptsPath + "jslib/fileUtil.js");
+load(buildScriptsPath + "jslib/buildUtil.js");
+load(buildScriptsPath + "jslib/buildUtilXd.js");
+load(buildScriptsPath + "jslib/i18nUtil.js");
+
+//NOTE: See buildUtil.DojoBuildOptions for the list of build options.
+
+//*****************************************************************************
+//Convert arguments to keyword arguments.
+var kwArgs = buildUtil.makeBuildOptions(arguments);
+
+//Remove the default namespaces that are created by Rhino, but only
+//if asked to -- it has bad consequences if the build system is used
+//with other rhino-based server-side code.
+if(kwArgs.removeDefaultNameSpaces){
+	delete com;
+	delete net;
+	delete org;
+}
+
+//Set logging level.
+logger.level = kwArgs["log"];
+
+//Execute the requested build actions
+var action = kwArgs.action;
+for(var i = 0; i < action.length; i ++){
+	logger.logPrefix = action[i] + ": ";
+	this[action[i]]();
+	logger.logPrefix = "";
+}
+
+var buildTime = ((new Date().getTime() - buildTimerStart) / 1000);
+logger.info("Build time: " + buildTime + " seconds");
+//*****************************************************************************
+
+//********* Start help ************
+function help(){
+	var buildOptionText = "";
+	for(var param in buildUtil.DojoBuildOptions){
+		buildOptionText += param + "=" + buildUtil.DojoBuildOptions[param].defaultValue + "\n"
+			+ buildUtil.DojoBuildOptions[param].helpText + "\n\n";
+	}
+
+	var helpText = "To run the build, you must have Java 1.4.2 or later installed.\n"
+		+ "To run a build run the following command from this directory:\n\n"
+		+ "> java -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar "
+		+ "org.mozilla.javascript.tools.shell.Main build.js [name=value...]\n\n"
+		+ "Here is an example of a typical release build:\n\n"
+		+ "> java -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar " 
+		+ "org.mozilla.javascript.tools.shell.Main  build.js profile=base action=release\n\n"
+		+ "If you get a 'java.lang.OutOfMemoryError: Java heap space' error, try increasing the "
+		+ "memory Java can use for the command:\n\n"
+		+ "> java -Xms256m -Xmx256m -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar "
+		+ "org.mozilla.javascript.tools.shell.Main build.js profile=base action=release\n\n"
+		+ "Change the 256 number to the number of megabytes you want to give Java.\n\n"
+		+ "The possible name=value build options are shown below with the defaults as their values:\n\n"
+		+ buildOptionText;
+	
+	print(helpText);
+}
+//********* End help *********
+
+//********* Start clean ************
+function clean(){
+	logger.info("Deleting: " + kwArgs.releaseDir);
+	fileUtil.deleteFile(kwArgs.releaseDir);
+}
+//********* End clean *********
+
+//********* Start release *********
+function release(){
+	logger.info("Using profile: " + kwArgs.profileFile);
+	logger.info("Using version number: " + kwArgs.version + " for the release.");
+
+	if(!kwArgs.buildLayers){
+		clean();
+	}
+
+	var dependencies = kwArgs.profileProperties.dependencies;
+	var prefixes = dependencies.prefixes;
+	var lineSeparator = fileUtil.getLineSeparator();
+	var copyrightText = fileUtil.readFile(buildScriptsPath + "copyright.txt");
+	var buildNoticeText = fileUtil.readFile(buildScriptsPath + "build_notice.txt");
+	
+	//Find the dojo prefix path. Need it to process other module prefixes.
+	var dojoPrefixPath = buildUtil.getDojoPrefixPath(prefixes);
+
+	//Convert targeted build layers to an array.
+	var buildLayers = null;
+	if(kwArgs.buildLayers){
+		//Make sure to copy over any "source" files for the layers be targeted by
+		//buildLayers. Otherwise dependencies will not be calculated correctly.
+		buildLayers = kwArgs.buildLayers.split(",");
+	}
+
+	//Get the list of module directories we need to process.
+	//They will be in the dependencies.prefixes array.
+	//Copy each prefix dir to the releases and
+	//operate on that copy instead of modifying the source.
+	for(var i = 0; i < prefixes.length; i++){
+		var prefixName = prefixes[i][0];
+		var prefixPath = prefixes[i][1];
+
+		var finalPrefixPath = prefixPath;
+		if(finalPrefixPath.indexOf(".") == 0 && prefixName != "dojo"){
+			finalPrefixPath = dojoPrefixPath + "/" + prefixPath;
+		}
+		_copyToRelease(prefixName, finalPrefixPath, kwArgs, buildLayers);
+
+		if(kwArgs.symbol){
+			var releasePath = kwArgs.releaseDir + "/"  + prefixName.replace(/\./g, "/");
+			buildUtil.insertSymbols(releasePath, kwArgs);
+		}
+	}
+
+	//Fix all the prefix paths to be in the release directory.
+	//Do this after the copy step above. If it is done as part
+	//of that loop, then dojo path gets set first usually, and any prefixes
+	//after it are wrong.
+	for(i = 0; i < prefixes.length; i++){
+		prefixes[i][1] = kwArgs.releaseDir + "/"  + prefixes[i][0].replace(/\./g, "/");
+	}
+
+	//Make sure dojo is clear before trying to map dependencies.
+	if(typeof dojo != "undefined"){
+		dojo = undefined;
+	}
+
+	logger.trace("Building dojo.js and layer files");
+	var result = buildUtil.makeDojoJs(buildUtil.loadDependencyList(kwArgs.profileProperties, kwArgs, buildScriptsPath), kwArgs.version, kwArgs);
+
+	//Save the build layers. The first layer is dojo.js.
+	var defaultLegalText = copyrightText + buildNoticeText;
+	var dojoReleaseDir = kwArgs.releaseDir + "/dojo/";
+	var layerIgnoreString = "";
+	var nlsIgnoreString = "";
+	
+	//Add an ending comma to the list to make matches easier.
+	//Also make sure we normalize to unix path separators.
+	if(kwArgs.buildLayers){
+		kwArgs.buildLayers += ",";
+		kwArgs.buildLayers = kwArgs.buildLayers.replace(/\\/g, "/");
+	}
+	for(i = 0; i < result.length; i++){
+		var currentLayer = result[i];
+		var layerName = currentLayer.layerName;
+		var layerLegalText = (currentLayer.copyrightFile ? fileUtil.readFile(currentLayer.copyrightFile) : defaultLegalText);
+		var fileName = dojoReleaseDir + currentLayer.layerName;
+		var fileContents = currentLayer.contents;
+
+		//Build up string of files to ignore for the directory optimization step
+		var ignoreName = layerName.replace(/\.\.\//g, "");
+		var nameSegment = ignoreName.replace(/\.js$/, "");
+		layerIgnoreString += (layerIgnoreString ? "|" : "") + buildUtil.regExpEscape(ignoreName) + "$";
+		layerIgnoreString += "|" + buildUtil.regExpEscape(ignoreName + ".uncompressed.js") + "$";
+
+		if(nameSegment.indexOf("/") != -1){
+			nameSegment = nameSegment.substring(nameSegment.lastIndexOf("/") + 1, nameSegment.length);
+		}
+		nlsIgnoreString += (nlsIgnoreString ? "|" : "") + buildUtil.regExpEscape(nameSegment);
+
+		//If only want to build certain layers, skip ones that do not match.
+		if(kwArgs.buildLayers && kwArgs.buildLayers.indexOf(layerName + ",") == -1){
+			continue;
+		}
+
+		//Burn in djConfig for dojo.js/xd.js if requested.
+		if(kwArgs.scopeDjConfig && (layerName.match(/dojo\.xd\.js$/) || layerName.match(/dojo\.js$/))){
+			fileContents = buildUtil.setScopeDjConfig(fileContents, kwArgs.scopeDjConfig);
+		}
+
+		//Burn in scope names for dojo.js/xd.js if requested.
+		if(kwArgs.scopeMap && (layerName.match(/dojo\.xd\.js$/) || layerName.match(/dojo\.js$/))){
+			fileContents = buildUtil.setScopeNames(fileContents, kwArgs.scopeMap);
+		}
+
+		//Burn in xd path for dojo if requested, and only do this in dojo.xd.js.
+		if(layerName == "dojo.xd.js" && kwArgs.xdDojoPath){
+			fileContents = buildUtilXd.setXdDojoConfig(fileContents, kwArgs.xdDojoPath);
+		}
+
+		//Flatten resources
+		fileContents = i18nUtil.flattenLayerFileBundles(fileName, fileContents, kwArgs);
+
+		//Save uncompressed file.
+		var uncompressedFileName = fileName + ".uncompressed.js";
+		var uncompressedContents = layerLegalText + fileContents;
+		if(layerName.match(/\.xd\.js$/) && !layerName.match(/dojo(\.xd)?\.js/)){
+			uncompressedContents = buildUtilXd.makeXdContents(uncompressedContents, prefixes, kwArgs);
+		}
+		fileUtil.saveUtf8File(uncompressedFileName, uncompressedContents);
+
+		//Intern strings if desired. Do this before compression, since, in the xd case,
+		//"dojo" gets converted to a shortened name.
+		if(kwArgs.internStrings){
+			logger.info("Interning strings for file: " + fileName);
+			prefixes = dependencies["prefixes"] || [];
+			var skiplist = dependencies["internSkipList"] || [];
+			buildUtil.internTemplateStringsInFile(uncompressedFileName, dojoReleaseDir, prefixes, skiplist);
+
+			//Load the file contents after string interning, to pick up interned strings.
+			fileContents = fileUtil.readFile(uncompressedFileName);
+		}else{
+			fileContents = uncompressedContents;
+		}
+
+		//Save compressed file.
+		logger.trace("Optimizing (" + kwArgs.layerOptimize + ") file: " + fileName);
+		var compressedContents = buildUtil.optimizeJs(fileName, fileContents, layerLegalText, kwArgs.layerOptimize, kwArgs.stripConsole);
+		fileUtil.saveUtf8File(fileName, compressedContents);
+	}
+
+	//Save the dependency lists to build.txt
+	var buildText = "Files baked into this build:" + lineSeparator;
+	for(i = 0; i < result.length; i++){
+		buildText += lineSeparator + result[i].layerName + ":" + lineSeparator;
+		buildText += result[i].depList.join(lineSeparator) + lineSeparator;
+	}
+	fileUtil.saveFile(kwArgs.releaseDir + "/dojo/build.txt", buildText);
+	logger.info(buildText);
+
+	//Run string interning, xd file building, etc.. on the prefix dirs in the
+	//release area.
+	var layerIgnoreRegExp = new RegExp("(" + layerIgnoreString + ")");
+	var nlsIgnoreRegExp = new RegExp("\\/nls\\/(" + nlsIgnoreString + ")_");
+
+	for(i = 0; i < prefixes.length; i++){
+		copyrightText = null;
+		if(prefixes[i][2]){
+			copyrightText = fileUtil.readFile(prefixes[i][2]);
+		}
+
+		//Optimize the release dirs, but only if we are not building just a layer.
+		if(!kwArgs.buildLayers){
+			_optimizeReleaseDirs(prefixes[i][0], prefixes[i][1], copyrightText, kwArgs, layerIgnoreRegExp, nlsIgnoreRegExp);
+		}
+	}
+
+	//Copy over DOH if tests where copied.
+	if(kwArgs.copyTests && !kwArgs.mini){
+		fileUtil.copyDir("../doh", kwArgs.releaseDir + "/util/doh", /./);
+	}
+	
+	//Remove any files no longer needed.
+	if(kwArgs.mini && kwArgs.internStrings){
+		fileUtil.deleteFile(kwArgs.releaseDir + "/dijit/templates");
+		fileUtil.deleteFile(kwArgs.releaseDir + "/dijit/form/templates");
+		fileUtil.deleteFile(kwArgs.releaseDir + "/dijit/layout/templates");
+	}
+
+	logger.info("Build is in directory: " + kwArgs.releaseDir);
+}
+//********* End release *********
+
+//********* Start _copyToRelease *********
+function _copyToRelease(/*String*/prefixName, /*String*/prefixPath, /*Object*/kwArgs, /*Array?*/buildLayers){
+	//summary: copies modules and supporting files from the prefix path to the release
+	//directory. Also adds code guards to module resources.
+	var prefixSlashName = prefixName.replace(/\./g, "/");
+	var releasePath = kwArgs.releaseDir + "/"  + prefixSlashName;
+	var copyRegExps = {
+		include: /./
+	};
+	
+	//Use the copyRegExps to filter out tests if requested.
+	if(!kwArgs.copyTests){
+		copyRegExps.exclude = /\/tests\//;
+	}
+	
+	if(kwArgs.mini){
+		copyRegExps.exclude = /\/tests\/|\/demos\/|tests\.js|dijit\/bench|dijit\/themes\/themeTest|(\.php$)/;
+	}
+
+	logger.info("Copying: " + prefixPath + " to: " + releasePath);
+	var copiedFiles = fileUtil.copyDir(prefixPath, releasePath, copyRegExps, true);
+
+	//If want a different selector engine, adjust that now.
+	//Copy the new selector js over the dojo._base.query file
+	if(prefixName == "dojo" && kwArgs.query == "sizzle"){
+		fileUtil.copyFile(releasePath + "/_base/query-sizzle.js", releasePath + "/_base/query.js");
+	}
+	
+	if(!copiedFiles){ 
+		logger.info(" ********** Not Copied: " + prefixPath ); 
+	}
+	
+	//Make sure to copy over any "source" files for the layers be targeted by
+	//buildLayers. Otherwise dependencies will not be calculated correctly.
+	if(buildLayers){
+		for(i = 0; i < buildLayers.length; i++){		
+			var relativeLayerPath = buildLayers[i].replace(/\.\.\//g, "");
+			
+			//See if relativeLayerPath has teh prefix slash name in it.
+			//This means the layer is probably in this prefix dir (but no guarantee)
+			//This is a bit hacky.
+			if(relativeLayerPath.indexOf(prefixSlashName) == 0){
+				
+				//Remove the prefix part from the dir and add the prefix path to get a
+				//full path.
+				var layerPathSuffix = relativeLayerPath.replace(prefixSlashName, "");
+				relativeLayerPath = prefixPath + layerPathSuffix;
+				
+				//If that source path exists, it means we need to copy over the source
+				//layer file.
+				if((new java.io.File(relativeLayerPath)).exists()){
+					//Need to copy over from the source area.
+					var destPath = releasePath + layerPathSuffix;
+					fileUtil.copyFile(relativeLayerPath, destPath);
+				}
+			}
+		}
+	}
+
+	//Put in code guards for each resource, to protect against redefinition of
+	//code in the layered build cases. Also inject base require calls if there is 
+	//a layer with the customBase attribute. Do this here before the layers are built.
+	if(copiedFiles){
+		var needBaseRequires = false;
+		var layers = kwArgs.profileProperties.dependencies.layers;
+		if(layers){
+			for(var i = 0; i < layers.length; i++){
+				if((needBaseRequires = layers[i].customBase)){
+					break;
+				}
+			}
+		}
+
+		if(kwArgs.addGuards){
+			buildUtil.addGuardsAndBaseRequires(copiedFiles, needBaseRequires);
+		}
+	}
+}
+//********* End _copyToRelease *********
+
+//********* Start _optimizeReleaseDirs *********
+function _optimizeReleaseDirs(
+	/*String*/prefixName, 
+	/*String*/prefixPath,
+	/*String*/copyrightText,
+	/*Object*/kwArgs,
+	/*RegExp*/layerIgnoreRegExp,
+	/*RegExp*/nlsIgnoreRegExp){	
+	//summary: runs intern strings, i18n bundle flattening and xdomain file generation
+	//on the files in a release directory, if those options are enabled.
+	var releasePath = kwArgs.releaseDir + "/"  + prefixName.replace(/\./g, "/");
+	var prefixes = kwArgs.profileProperties.dependencies.prefixes;
+
+	//Intern strings if desired.
+	if(kwArgs.internStrings){
+		logger.info("Interning strings for: " + releasePath);
+		buildUtil.internTemplateStrings(kwArgs.profileProperties.dependencies, releasePath, layerIgnoreRegExp);
+	}
+
+	//Process build conditionals in non-layer module files.
+	buildUtil.processConditionalsForDir(releasePath, layerIgnoreRegExp, kwArgs);
+
+	//Flatten bundles inside the directory
+	i18nUtil.flattenDirBundles(prefixName, prefixPath, kwArgs, nlsIgnoreRegExp);	
+	
+	if(kwArgs.loader == "xdomain"){
+		buildUtilXd.xdgen(prefixName, prefixPath, prefixes, layerIgnoreRegExp, kwArgs);
+	}
+
+	buildUtil.optimizeJsDir(releasePath, layerIgnoreRegExp, copyrightText, kwArgs.optimize, kwArgs.stripConsole);
+
+	if(kwArgs.cssOptimize){
+		buildUtil.optimizeCss(releasePath, kwArgs.cssOptimize, kwArgs.cssImportIgnore);
+	}
+}
+//********* End _optimizeReleaseDirs *********
diff --git a/util/buildscripts/build.sh b/util/buildscripts/build.sh
new file mode 100755
index 0000000..bacfe03
--- /dev/null
+++ b/util/buildscripts/build.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+java -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar org.mozilla.javascript.tools.shell.Main build.js "$@"
+
+# if you experience an "Out of Memory" error, you can increase it as follows:
+#java -Xms256m -Xmx256m -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar org.mozilla.javascript.tools.shell.Main  build.js "$@"
diff --git a/util/buildscripts/build_notice.txt b/util/buildscripts/build_notice.txt
new file mode 100644
index 0000000..65d78b0
--- /dev/null
+++ b/util/buildscripts/build_notice.txt
@@ -0,0 +1,7 @@
+/*
+	This is an optimized version of Dojo, built for deployment and not for
+	development. To get sources and documentation, please visit:
+
+		http://dojotoolkit.org
+*/
+
diff --git a/util/buildscripts/build_release.sh b/util/buildscripts/build_release.sh
new file mode 100755
index 0000000..7f0a407
--- /dev/null
+++ b/util/buildscripts/build_release.sh
@@ -0,0 +1,140 @@
+#!/bin/bash
+
+#version should be something like 0.9.0beta or 0.9.0
+version=$1
+#svnUserName is the name you use to connect to Dojo's subversion.
+svnUserName=$2
+#The svn revision number to use for tag. Should be a number, like 11203
+svnRevision=$3
+
+#If no svnRevision number, get the latest one from he repo.
+if [ "$svnRevision" = "" ]; then
+	svnRevision=`svn info http://svn.dojotoolkit.org/src/util/trunk/buildscripts/build_release.sh | grep Revision | sed 's/Revision: //'`
+fi
+
+tagName=release-$version
+buildName=dojo-$tagName
+
+echo "This is a RELEASE build for Dojo, you probably meant to run build.sh"
+read -p "If you mean to create a tag for Dojo $version from r$svnRevision ... press a key to continue."
+
+#Make the SVN tag.
+svn mkdir -m "Using r$svnRevision to create a tag for the $version release." https://svn.dojotoolkit.org/src/tags/$tagName
+svn copy -r $svnRevision https://svn.dojotoolkit.org/src/dojo/trunk  https://svn.dojotoolkit.org/src/tags/$tagName/dojo -m "Using r$svnRevision to create a tag for the $version release."
+svn copy -r $svnRevision https://svn.dojotoolkit.org/src/dijit/trunk https://svn.dojotoolkit.org/src/tags/$tagName/dijit -m "Using r$svnRevision to create a tag for the $version release."
+svn copy -r $svnRevision https://svn.dojotoolkit.org/src/dojox/trunk https://svn.dojotoolkit.org/src/tags/$tagName/dojox -m "Using r$svnRevision to create a tag for the $version release."
+svn copy -r $svnRevision https://svn.dojotoolkit.org/src/util/trunk  https://svn.dojotoolkit.org/src/tags/$tagName/util -m "Using r$svnRevision to create a tag for the $version release."
+svn copy -r $svnRevision https://svn.dojotoolkit.org/src/demos/trunk https://svn.dojotoolkit.org/src/tags/$tagName/demos -m "Using r$svnRevision to create a tag for the $version release."
+
+#Check out the tag
+mkdir ../../build
+cd ../../build
+svn co https://svn.dojotoolkit.org/src/tags/$tagName $buildName
+cd $buildName/util/buildscripts
+
+#Update the dojo version in the tag
+java -jar ../shrinksafe/js.jar changeVersion.js $version ../../dojo/_base/_loader/bootstrap.js
+cd ../../dojo
+svn commit -m "Updating dojo version for the tag. \!strict" _base/_loader/bootstrap.js
+
+#Erase the SVN dir and replace with an exported SVN contents.
+cd ../..
+rm -rf ./$buildName/
+svn export http://svn.dojotoolkit.org/src/tags/$tagName $buildName
+
+# clobber cruft that we don't want in builds
+rm -rf ./$buildName/dijit/themes/noir
+rm -rf ./$buildName/dijit/bench
+
+#Make a shrinksafe bundle
+shrinksafeName=$buildName-shrinksafe
+cp -r $buildName/util/shrinksafe $buildName/util/$shrinksafeName
+cd $buildName/util
+zip -rq $shrinksafeName.zip $shrinksafeName/
+tar -zcf $shrinksafeName.tar.gz $shrinksafeName/
+mv $shrinksafeName.zip ../../
+mv $shrinksafeName.tar.gz ../../
+cd ../..
+rm -rf $buildName/util/$shrinksafeName
+
+#Make a -demos bundle (note, this is before build. Build profile=demos-all if you want to release them)
+# the -demos archives are meant to be extracted from the same folder -src or release archives, and have
+# a matching prefixed folder in the archive
+demoName=$buildName-demos
+zip -rq $demoName.zip $buildName/demos/
+tar -zcf $demoName.tar.gz $buildName/demos/
+# prevent demos/ from appearing in the -src build
+rm -rf $buildName/demos
+
+#Make a src bundle
+srcName=$buildName-src
+mv $buildName $srcName
+zip -rq $srcName.zip $srcName/
+tar -zcf $srcName.tar.gz $srcName/
+mv $srcName $buildName
+
+#Run the build.
+cd $buildName/util/buildscripts/
+chmod +x ./build.sh
+./build.sh profile=standard version=$1 releaseName=$buildName cssOptimize=comments.keepLines optimize=shrinksafe.keepLines action=release 
+# remove tests and demos, but only for the actual release:
+chmod +x ./clean_release.sh
+./clean_release.sh ../../release $buildName
+cd ../../release/
+
+#Pause to allow manual process of packing Dojo.
+currDir=`pwd`
+echo "You can find dojo in $currDir/$buildName/dojo/dojo.js"
+read -p "Build Done. If you want to pack Dojo manually, do it now, then press Enter to continue build packaging..."
+
+#Continuing with packaging up the release.
+zip -rq $buildName.zip $buildName/
+tar -zcf $buildName.tar.gz $buildName/
+mv $buildName.zip ../../
+mv $buildName.tar.gz ../../
+
+#copy compressed and uncompressed Dojo to the root
+cp $buildName/dojo/dojo.js* ../../
+
+# remove the testless release build, and unpack a -src archive to rebuild from
+cd ../../
+rm -rf $buildName/
+tar -xzvf $srcName.tar.gz
+cd $srcName/util/buildscripts/
+
+# build the version that will be extracted and live on downloads.dojotoolkit.org (with tests)
+./build.sh action=release version=$1 profile=standard cssOptimize=comments.keepLines releaseName=$buildName copyTests=true mini=false
+
+# cleanup the -src extraction, moving the newly built tree into place. 
+cd ../../release
+mv $buildName ../../
+cd ..
+rm -rf release/
+
+# generate api.xml and api.json
+cd util/docscripts/
+php -q generate.php
+mv api.* ../../../../build/
+cd ../../../../
+
+# make a folder structure appropriate for directly extracting on downloads.dojotoolkit.org
+mv build release-$1
+rm -rf release-$1/$srcName/
+cd release-$1
+
+# md5sum the release files
+for i in *.zip; do md5sum $i > $i.md5; done
+for i in *.gz; do md5sum $i > $i.md5; done
+for i in *.js; do md5sum $i > $i.md5; done
+
+# pack up the whole thing for easy copying
+cd ..
+tar -czvf dj-$1-dtk.tar.gz release-$1
+
+#Finished.
+outDirName=`pwd`
+echo "Build complete. Files are in: $outDirName"
+echo "A copy/paste command to push files to downloads.dojotoolkit.org with permission:"
+echo "scp dj-$1-dtk.tar.gz download.dojotoolkit.org:/srv/www/vhosts/download.dojotoolkit.org"
+echo "... then extract in place and rm dj-$1-dtk.tar.gz"
+cd ../util/buildscripts
diff --git a/util/buildscripts/cdnBuild.sh b/util/buildscripts/cdnBuild.sh
new file mode 100755
index 0000000..9e0f946
--- /dev/null
+++ b/util/buildscripts/cdnBuild.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# only run this in a pristine export of an svn tag.
+# It should only be run on unix, more specifically, where sha1sum is available.
+
+#version should be something like 0.9.0beta or 0.9.0, should match the name of the svn export.
+version=$1
+
+if [ -z $version ]; then
+    echo "Please pass in a version number"
+    exit 1
+fi
+
+dobuild() {
+	java -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar org.mozilla.javascript.tools.shell.Main build.js profile=standard releaseName=$1 cssOptimize=comments.keepLines optimize=shrinksafe stripConsole=normal loader=xdomain xdDojoPath=$3 version=$1 copyTests=false mini=true action=release xdDojoScopeName=window[\(typeof\(djConfig\)\!\=\"undefined\"\&\&djConfig.scopeMap\&\&djConfig.scopeMap[0][1]\)\|\|\"dojo\"]
+	mv ../../release/$1 ../../release/$1-cdn/$2
+	cd ../../release/$1-cdn/$2
+	zip -rq $1.zip $1/*
+	sha1sum $1.zip > sha1.txt
+	cd $1
+	find . -type f -exec sha1sum {} >> ../sha1.txt \;
+	cd ../../../../util/buildscripts
+}
+
+# Generate locale info
+cd cldr
+ant
+cd ..
+
+# Setup release area
+mkdir ../../release
+mkdir ../../release/$version-cdn
+mkdir ../../release/$version-cdn/google
+mkdir ../../release/$version-cdn/aol
+
+# Google build
+dobuild $version "google" "http://ajax.googleapis.com/ajax/libs/dojo/$version"
+# AOL build
+dobuild $version "aol" "http://o.aolcdn.com/dojo/$version"
diff --git a/util/buildscripts/cdnBuild.txt b/util/buildscripts/cdnBuild.txt
new file mode 100644
index 0000000..5fe5995
--- /dev/null
+++ b/util/buildscripts/cdnBuild.txt
@@ -0,0 +1,18 @@
+CDN build process
+===================
+Run the cdnBuild.sh script to generate the CDN distributions for the Google and AOL CDNs. Be sure to:
+- use a pristine svn export of a tag and run cdnBuild.sh from the util/buildscripts directory in that tag.
+  svn export https://svn.dojotoolkit.org/src/tags/release-1.4.3 1.4.3
+- make sure sha1sum is available on the OS, otherwise the signature generation will fail.
+- Apache Ant is needed to run the cldr i18n resources. the cldr build process does not work with 
+  Ant 1.7.0, but does work with Ant 1.7.1 and 1.6.5. Download one of those and do this to set the version of Ant to use:
+  export ANT_HOME=/full/path/to/ant-1.7.1
+
+The result will be in the svn exported tag directory's release/VERSION-cdn directory.
+
+After doing the build, place the VERSION-cdn directory on the dojotoolkit.org site and notify the CDN owners.
+Let the know the .zip file's sha signature is in the sha1.txt file at the top, and ask them to update
+their symlink for the MAJOR.MINOR version number to the latest MAJOR.MINOR.PATCH number.
+
+An example based on the AOL CDN: if releaseName was 1.3.1, then update http://o.aolcdn.com/dojo/1.3 to point to 
+http://o.aolcdn.com/dojo/1.3.1 (where http://o.aolcdn.com/dojo will be different based on the xdDojoPath build option).
diff --git a/util/buildscripts/changeVersion.js b/util/buildscripts/changeVersion.js
new file mode 100644
index 0000000..38058de
--- /dev/null
+++ b/util/buildscripts/changeVersion.js
@@ -0,0 +1,13 @@
+//Changes the Dojo version in a file. Used during the release process.
+
+var version = new String(arguments[0]);
+var fileName = new String(arguments[1]);
+
+load("jslib/logger.js");
+load("jslib/fileUtil.js");
+load("jslib/buildUtil.js");
+
+var fileContents = fileUtil.readFile(fileName);
+fileContents = buildUtil.changeVersion(version, fileContents);
+
+fileUtil.saveUtf8File(fileName, fileContents);
\ No newline at end of file
diff --git a/util/buildscripts/cldr/README b/util/buildscripts/cldr/README
new file mode 100644
index 0000000..8962d33
--- /dev/null
+++ b/util/buildscripts/cldr/README
@@ -0,0 +1,13 @@
+The scripts in this directory are responsible for generating the data tables in dojo/cldr/nls.
+Dojo provides a subset of this output in dojo/cldr/nls under source control, the rest must be
+generated by the developer using these scripts.  See dojo/cldr/README for details.
+
+To trigger generation of a full set of locale resources, simply type "ant".  An optional
+list of locales may be specified as an ant property to limit the set of locales built.
+Currencies may also be specified, but a default list is included in the ant script.
+
+NOTE: it is currently necessary to perform a one-time installation of the Saxon XSLT 
+  processor in ~/.ant/lib due to classpath issues and workarounds.  The ant task will do this for you.
+  
+  Also, ant version 1.6.5 is recommended with Java 1.5.  The build script does not properly resolve the
+  XSLT catalog with newer versions of ant which makes the process take much longer.  See ticket #7969
\ No newline at end of file
diff --git a/util/buildscripts/cldr/alias.js b/util/buildscripts/cldr/alias.js
new file mode 100644
index 0000000..0d7fa33
--- /dev/null
+++ b/util/buildscripts/cldr/alias.js
@@ -0,0 +1,242 @@
+/**
+ * There are basically two kinds of alias in CLDR:
+ * 1. locale alias e.g. 
+ *    in xml, <alias source="locale" path="......"/>, 
+ *    in gernated JSON bunle, xxxx at localeAlias:{'target':'xxx', 'bundle':'xxxx'}
+ * 2. other locale alias e.g.
+ *    in xml, currently only like <alias source="fr" path="//ldml"/>
+ * #1 is supported by this 'alias.js', 
+ * #2 is covered by 'specialLocale.js' and may need enhancement for future CLDR versions.
+ */
+
+djConfig={baseUrl: "../../../dojo/"};
+
+load("../../../dojo/dojo.js");
+load("../jslib/logger.js");
+load("../jslib/fileUtil.js");
+load("cldrUtil.js");
+
+dojo.require("dojo.i18n");
+
+var dir/*String*/ = arguments[0];// ${dojo}/dojo/cldr/nls
+var logDir = arguments[1];
+var logStr = "";
+
+//Add new bundles to the list so that they will be aliased according to the ldml spec. 
+var BUNDLES = ['gregorian','hebrew','islamic','islamic-civil','buddhist'];
+
+var LOCALE_ALIAS_MARK = '@localeAlias';
+var LOCALE_ALIAS_SOURCE_PROPERTY = 'source';
+var LOCALE_ALIAS_TARGET_PROPERTY = 'target';
+var LOCALE_ALIAS_TARGET_BUNDLE = 'bundle';
+var localeAliasPaths = [];/**/
+var records = {};/*{property : boolean}, record whether a property has been calculated for alias path*/
+var updated = false;
+
+print('alias.js...');
+
+for(var i = 0; i < BUNDLES.length; i++){
+	var regExp = new RegExp('\/' + BUNDLES[i] + '\.js$'); //e.g. new RegExp('\/gregorian\.js$')
+	var fileList = fileUtil.getFilteredFileList(dir, regExp, true);
+	
+	for(var j = 0; j < fileList.length; j++){
+		var jsFileName = new String(fileList[j]); //Java String
+		var jsFilePath = jsFileName.split("/");
+		var locale = jsFilePath[jsFilePath.length-2];
+		if(locale=="nls"){continue;} // no need for root bundle
+		try{
+			dojo.i18n._requireLocalization('dojo.cldr', BUNDLES[i], locale); //declare bundle						
+			var bundle = dojo.i18n.getLocalization('dojo.cldr', BUNDLES[i], locale); //get bundle
+			var nativeSrcBundle = getNativeBundle(jsFileName);//bundle not flattened
+		}catch(e){print(e);/* simply ignore if no bundle found*/}
+		
+		if(!bundle) continue;
+		
+		updated = false;
+		//logStr += locale + ":" + BUNDLES[i] + "=========================================================================\n";
+		
+		_calculateAliasPath(bundle);
+		//logStr += "all alias paths=" + dojo.toJson(localeAliasPaths) + "\n";
+				
+		_processLocaleAlias(localeAliasPaths, bundle, nativeSrcBundle,locale);
+		
+		if(updated){
+			fileUtil.saveUtf8File(jsFileName, "(" + dojo.toJson(nativeSrcBundle, true) + ")");
+		}
+		//logStr += '\n';
+	}
+	cleanLocaleAlias(fileList);
+}
+
+//fileUtil.saveUtf8File(logDir + '/alias.log',logStr+'\n');
+//print('CLDR finished, please refer to logs at ' + logDir + ' for more details.');
+
+
+function _calculateAliasPath(bundle){
+	for(p in bundle){
+		var index = p.indexOf(LOCALE_ALIAS_MARK);
+		if(index >= 0 /*p like 'xxx at localeAlias6'*/){
+			var localeAliasSource/*String*/ = p.substring(0,index);
+			if(records[localeAliasSource]/*calculated*/){
+				//logStr += p + " has been calculated, ignored\n"
+				continue;
+			} 
+			
+			var path = [];
+			var aliasIndex = new Number(p.substring(index + LOCALE_ALIAS_MARK.length));
+			//logStr += "aliasIndex for " + p + " is " + aliasIndex + "\n";
+			var i = aliasIndex;
+			while(bundle[localeAliasSource + LOCALE_ALIAS_MARK + (--i)]){}
+			
+			var src = localeAliasSource;
+			while(bundle[localeAliasSource + LOCALE_ALIAS_MARK + (++i)]){
+				var mapping = {};
+				mapping[LOCALE_ALIAS_SOURCE_PROPERTY] = src;
+				mapping[LOCALE_ALIAS_TARGET_PROPERTY] = bundle[localeAliasSource + LOCALE_ALIAS_MARK + i][LOCALE_ALIAS_TARGET_PROPERTY];
+				mapping[LOCALE_ALIAS_TARGET_BUNDLE] = bundle[localeAliasSource + LOCALE_ALIAS_MARK + i][LOCALE_ALIAS_TARGET_BUNDLE];
+				path.push(mapping);
+				records[src] = true;
+				src = bundle[localeAliasSource + LOCALE_ALIAS_MARK + i][LOCALE_ALIAS_TARGET_PROPERTY];
+			}
+			path = path.reverse();
+			//logStr += "alias path calucated for " + localeAliasSource + "=" + dojo.toJson(path) + "\n";
+			localeAliasPaths.push(path);
+		}
+	}
+}
+
+function _processLocaleAlias(localeAliasPaths/*Array*/, bundle/*JSON Obj*/, nativeSrcBundle/*JSON Obj*/,locale/*String*/){
+	//Summary: Update all properties as defined by 'locale' alias mapping
+	//		   E.g.'months-format-abbr at localeAlias6':{'target':"months-format-wide", 'bundle':"gregorian"},
+	//		   means the array values of 'months-format-abbr' in current bundle should be
+	//		   merged with(inherit or overwrite) that of 'months-format-wide' in 'gregorian' bundle
+	//
+	//Note:	   Currently no bundle recognition, always assume 'gregorian'.
+	var processed = {};
+	for(var i = 0; i < localeAliasPaths.length; i++){
+		var path = localeAliasPaths[i];
+		for(var j = 0; j < path.length; j++){
+			var mapping = path[j];
+			if(mapping[LOCALE_ALIAS_SOURCE_PROPERTY] != mapping[LOCALE_ALIAS_TARGET_PROPERTY]
+			   && bundle[mapping[LOCALE_ALIAS_TARGET_PROPERTY]]/*target existed*/){
+				//e.g. {'source':'months-format-abbr','target':"months-format-wide",'bundle':"gregorian"},
+				//currently source and target bundles are the same - gregorian
+				if(processed[mapping[LOCALE_ALIAS_SOURCE_PROPERTY]]){/*haven't been processed*/
+					//logStr += "!" + mapping[LOCALE_ALIAS_SOURCE_PROPERTY] +" has been processed for alias, escaped\n";
+					continue;
+				}
+				_updateLocaleAlias(bundle, mapping[LOCALE_ALIAS_SOURCE_PROPERTY], bundle, 
+								   mapping[LOCALE_ALIAS_TARGET_PROPERTY], nativeSrcBundle);	
+				processed[mapping[LOCALE_ALIAS_SOURCE_PROPERTY]] =  true;
+			}else{
+				//For other non-gregorian calendars. e.g. "hebrew" etc.
+				//Get the bundle according to the locale.
+				var targetBundle = dojo.i18n.getLocalization('dojo.cldr', mapping[LOCALE_ALIAS_TARGET_BUNDLE], locale); 
+				if(processed[mapping[LOCALE_ALIAS_SOURCE_PROPERTY]]){//If being processed, continue;
+					continue;
+				}
+				_updateNoneGregAlias(bundle, mapping[LOCALE_ALIAS_SOURCE_PROPERTY], targetBundle, 
+								   mapping[LOCALE_ALIAS_TARGET_PROPERTY], nativeSrcBundle);	
+				processed[mapping[LOCALE_ALIAS_SOURCE_PROPERTY]] =  true;
+			}
+		}
+	}
+}
+/*
+* This function will flatten the source bundle for non-gregorian ones by searching in the bundle files generated from the ldml spec which have terms like:
+* "'months-standAlone-abbr at localeAlias131':{'target':"months-format-abbr",'bundle':"hebrew"},".
+*   Parameters:
+*   	sourceBundle: The bundles which need to be aliased.
+*   	aliasSource:  The source mark string. 'months-standAlone-abbr' for example.
+*   	targetBundle: The aliased bundle. 'hebrew' for example.
+*   	aliasTarget:  The target mark string. 'months-format-abbr' for example.
+*   	nativeSrcBundle: The final flattened bundle file.
+* According to the dojo way of fetching resource bundle, this function will firstly check the bundle under the appointed
+* locale. If the wanted calendar bundle is not under the locale, the root calendar bundle will be fetched. If the non-gregorian
+* bundle in the root can not be found, dojo will finally get the root gregorian bundle.
+*/
+function _updateNoneGregAlias(sourceBundle/*JSON Obj*/, aliasSource/*String*/, targetBundle/*JSON Obj*/, aliasTarget/*String*/, nativeSrcBundle/*JSON Obj*/){
+    for (var sKey in sourceBundle) {
+        if (sKey.indexOf(aliasSource) == 0 && !nativeSrcBundle[sKey] && targetBundle[sKey]&&!compare(sourceBundle[sKey],targetBundle[sKey])) {
+            nativeSrcBundle[sKey] = targetBundle[sKey];
+            sourceBundle[sKey] = targetBundle[sKey];
+            updated = true;
+        }
+        else 
+            if (sKey.indexOf(aliasSource) == 0 && nativeSrcBundle[sKey] && dojo.isArray(sourceBundle[sKey]) && dojo.isArray(targetBundle[sKey])) {
+                for (var i = 0; i < sourceBundle[sKey].length; i++) {
+                    if (sourceBundle[sKey][i] == undefined) {
+                        sourceBundle[sKey][i] = targetBundle[sKey][i];
+                        updated = true;
+                    }
+                }
+                if (sourceBundle[sKey].length < targetBundle[sKey].length) {
+                    sourceBundle[sKey] = sourceBundle[sKey].concat(targetBundle[sKey].slice(sourceBundle[sKey].length));
+                    updated = true;
+                }
+                if (updated) {
+                    nativeSrcBundle[sKey] = sourceBundle[sKey];
+                }
+            }
+    }
+}
+function _updateLocaleAlias(sourceBundle/*JSON Obj*/,aliasSource/*String*/, targetBundle/*JSON Obj*/,
+							aliasTarget/*String*/, nativeSrcBundle/*JSON Obj*/){
+		//single property
+		if(!nativeSrcBundle[aliasSource] && nativeSrcBundle[aliasTarget]//no this property in current locale
+		   && !compare(sourceBundle[aliasSource], targetBundle[aliasTarget])){
+			// then should inherit from alias target (as defined by 'locale' alias)
+			//logStr += '1 '+aliasSource + "=" + sourceBundle[aliasSource] + " is replaced with " + aliasTarget + "=" + targetBundle[aliasTarget]+'\n';
+			//sourceBundle[aliasSource] =  targetBundle[aliasTarget];
+			nativeSrcBundle[aliasSource] =  targetBundle[aliasTarget];
+			sourceBundle[aliasSource] = nativeSrcBundle[aliasSource];
+			updated = true;	
+		}else if(nativeSrcBundle[aliasSource] && dojo.isArray(sourceBundle[aliasSource]) 
+		         && dojo.isArray(targetBundle[aliasTarget])){
+			if(sourceBundle[aliasSource].length > targetBundle[aliasTarget].length){
+				//logStr +="Error:" + aliasSource + ".length > " +  aliasTarget + ".length \n";
+			}
+			//array property, see if need inherit
+			for(var i = 0; i < sourceBundle[aliasSource].length; i++){
+				if(sourceBundle[aliasSource][i] == undefined){//need inherit
+					//logStr += '2 ' + aliasSource + "["+i+"]=" +sourceBundle[aliasSource][i]+" is replaced with " + aliasTarget+"["+i+"]="+targetBundle[aliasTarget][i]+'\n';
+					sourceBundle[aliasSource][i] =  targetBundle[aliasTarget][i];
+					updated = true;	
+				}// otherwise no change and use current value
+			}
+			if(sourceBundle[aliasSource].length < targetBundle[aliasTarget].length){
+				//logStr +='3 ' + aliasSource +' from ' + sourceBundle[aliasSource].length +' to ' 
+				//		  + (targetBundle[aliasTarget].length-1) + ' are copied from ' 
+				//		  +aliasTarget + '='+ targetBundle[aliasTarget] +'\n';
+				sourceBundle[aliasSource] = sourceBundle[aliasSource].concat(
+											targetBundle[aliasTarget].slice(sourceBundle[aliasSource].length));
+				updated = true;	
+			}
+			if(updated){
+				nativeSrcBundle[aliasSource] = sourceBundle[aliasSource];
+			}
+		}
+}
+
+function cleanLocaleAlias(fileList/*Array*/){
+	for(var i = 0; i < fileList.length; i++){
+		var fileName = new String(fileList[i]); //Java String
+		try{
+			var bundle = getNativeBundle(fileName);//bundle not flattened
+		}catch(e){print(e);/* simply ignore if no bundle found*/}
+		
+		var newBundle = {};
+		var needUpdate = false;
+		for(p in bundle){
+			if(p.indexOf(LOCALE_ALIAS_MARK) < 0){
+				newBundle[p] = bundle[p];
+			}else{
+				needUpdate = true;
+			}
+		}
+		if(needUpdate){
+			fileUtil.saveUtf8File(fileName, "(" + dojo.toJson(newBundle, true) + ")");
+			//logStr += "cleaned @localAlias for " + fileName + "\n";
+		} 
+	}
+}
diff --git a/util/buildscripts/cldr/arrayInherit.js b/util/buildscripts/cldr/arrayInherit.js
new file mode 100644
index 0000000..e5232b3
--- /dev/null
+++ b/util/buildscripts/cldr/arrayInherit.js
@@ -0,0 +1,128 @@
+/**
+ *  The CLDR represents some lists, like month names, as separate entries, and our JSON uses arrays to express them.
+ *  For some variants, the best our XSLT can do is translate this to a sparse array with 'undefined' entries.
+ *  These entries need to be picked up from the parent locale(s) and copied into the array as necessary(only when the item
+ *  is not the source of a locale alias mapping, like 'months-format-abbr' should be ignored if it is the source of 
+ *  locale alias mapping like 'months-format-abbr at localeAlias' :{'target':"months-format-wide",'bundle':"gregorian"}).
+ *  So, this script is responsible for taking all the generated JSON files, and for values which are of type
+ *  array and not the source of locale alias mapping, mixing in the parent values with the undefined ones, recursing 
+ *  all the way to the 'root' locale,and replacing the contents of the file.  
+ *
+ *  this script traverses all locales dir in the given root dir
+ *  
+ *   E.g.(Just for example, the contents are not applicable)
+ *   parent locale - "en":
+ *    // generated from ldml/main/ *.xml, xpath: ldml/calendars/calendar-ethiopic
+ *    ({
+ *    	'months-format-abbr':["1","2","3","4","5","6","7","8","9","10","11","12"],
+ *    	'dateFormat-long': "yyyy MMMM d",
+ *    	'dateTimeFormat': "{1} {0}"
+ *    })
+ *
+ *   child locale - "en-us":
+ *    // generated from ldml/main/ *.xml, xpath: ldml/calendars/calendar-ethiopic
+ *    ({
+ *    	'months-format-abbr':[undefined,undefined,"March",undefined,undefined,"June"],
+ *    	'dateFormat-long': "yyyy-MMMM-d"
+ *    })
+ *
+ *   After process, the result will be:
+ *    child locale - "en-us":
+ *    // generated from ldml/main/ *.xml, xpath: ldml/calendars/calendar-ethiopic
+ *    ({
+ *    	'months-format-abbr':["1","2","March","4","5","June","7","8","9","10","11","12"],
+ *    	'dateFormat-long': "yyyy-MMMM-d"
+ *    })
+ */
+
+djConfig={baseUrl: "../../../dojo/"};
+
+load("../../../dojo/dojo.js");
+load("../jslib/logger.js");
+load("../jslib/fileUtil.js");
+load("../jslib/buildUtil.js");
+load("cldrUtil.js");
+
+dojo.require("dojo.i18n");
+
+var dir = arguments[0];
+var logDir = arguments[1];
+var logStr = "";
+
+print('arrayInherit.js...');
+
+// limit search to gregorian.js files, which are the only ones to use Array as data type
+var fileList = fileUtil.getFilteredFileList(dir, /\/gregorian\.js$/, true);
+
+for(var i= 0; i < fileList.length; i++){
+	//Use new String so we get a JS string and not a Java string.
+	var jsFileName = new String(fileList[i]);
+	var data = null;
+	var jsPath = jsFileName.split("/");
+	var localeIndex = jsPath.length-2;
+	var locale = jsPath[localeIndex];
+	if(locale=="nls"){continue;} // don't run on ROOT resource
+	var hasChanged = false;
+	
+	try{
+		dojo.i18n._requireLocalization('dojo.cldr', 'gregorian', locale);						
+		var bundle = dojo.i18n.getLocalization('dojo.cldr', 'gregorian', locale); //flattened bundle
+	}catch(e){print(e);/* simply ignore if no bundle found*/}
+	
+	dojo.i18n._searchLocalePath(locale, true, function(variant){
+		var isComplete = false;
+		var path = jsPath;
+		if(variant=="ROOT"){
+			path = path.slice(0, localeIndex);
+			path.push(jsPath[localeIndex+1]);
+		}else{
+			path[localeIndex] = variant;
+		}
+		var contents;
+		try{
+			contents = new String(readFile(path.join("/"), "utf-8"));
+		}catch(e){
+			print(e); //TODO: should we be catching this?
+			return false;
+		}
+		var variantData = dojo.fromJson(contents);
+		if(!data){
+			data = variantData;
+		}else{
+			isComplete = true;
+			//logStr += locale + "===============================================\n";
+			for(prop in data){
+				if(dojo.isArray(data[prop])){
+					//ignore if the property is an alias source, for alias.js and specialLocale.js 
+					if(isLocaleAliasSrc(prop, bundle)){
+						//logStr += prop + " is alias, ignored\n";
+						continue;
+					}			
+
+					var variantArray = variantData[prop];
+					dojo.forEach(data[prop], function(element, index, list){
+						if(element === undefined && dojo.isArray(variantArray)){
+							list[index] = variantArray[index];
+							//logStr += prop + "[" + index + "] undefined, is replaced with " + list[index] + "\n";
+							hasChanged = true;
+							if(!("index" in list)){
+								isComplete = false;
+							}
+						}
+					});
+					if(dojo.isArray(variantArray) && variantArray.length > data[prop].length){
+						data[prop] = data[prop].concat(variantArray.slice(data[prop].length));
+						hasChanged = true;
+					}
+				}
+			}
+			//logStr += "\n";
+		}
+		return isComplete;
+	});
+	if(hasChanged){
+		fileUtil.saveUtf8File(jsFileName, "(" + dojo.toJson(data, true) + ")");
+	}
+}
+
+//fileUtil.saveUtf8File(logDir + '/arrayInherit.log',logStr+'\n');
\ No newline at end of file
diff --git a/util/buildscripts/cldr/build.xml b/util/buildscripts/cldr/build.xml
new file mode 100644
index 0000000..7240fd4
--- /dev/null
+++ b/util/buildscripts/cldr/build.xml
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+
+<!--
+	Copyright (c) 2004-2010 The Dojo Foundation, Licensed under the Academic
+	Free License version 2.1 or BSD licenses
+-->
+<project name="dojo" default="cldr" basedir=".">
+	<description>Build the Dojo toolkit</description>
+
+	<property name="project" value="dojo"/>
+	<property name="root" location="../../.."/>
+	<property name="dojoLoader" value="default"/>
+	<property name="ldml" location="ldml"/>
+	<property name="logDir" location="."/>
+	<property name="json" location="${root}/dojo/cldr/nls"/>
+
+	<!-- Arbitrary defaults. locales and currencies properties can be altered or eliminated to build the entire set -->
+	<!--property name="locales" value="ar,hi,he,hu,ru,en-au,en-ca,en-gb,en-us,de-de,es-es,fr-fr,it-it,pt-br,ko-kr,zh-hant,zh-tw,zh-hans,zh-cn,ja-jp"/-->
+	<property name="currencies" value="GBP,USD,CAD,AUD,EUR,CHF,HKD,JPY,CNY" />
+
+	<target name="-check-config"
+		description="checks to make sure than we're sane before doing anything else">
+		<available property="bsf_ok" file="${user.home}/.ant/lib/bsf.jar" />
+		<available property="ant_bsf_ok" file="${user.home}/.ant/lib/ant-apache-bsf.jar" />
+		<available property="js_ok" file="${user.home}/.ant/lib/js.jar" />
+		<available property="saxon9_ok" file="${user.home}/.ant/lib/saxon9.jar" />
+		<available property="resolver_ok" file="${user.home}/.ant/lib/resolver.jar" />
+		<available property="logger_ok" file="${user.home}/.ant/lib/commons-logging-1.1.1.jar" />
+		
+		<condition property="config_ok">
+			<and>
+				<isset property="bsf_ok" />
+				<isset property="ant_bsf_ok" />
+				<isset property="js_ok" />
+				<isset property="saxon9_ok" />
+				<isset property="resolver_ok" />
+				<isset property="logger_ok" />
+			</and>
+		</condition>
+	</target>
+
+	<target name="-fix-config"
+		depends="-check-config"
+		unless="config_ok"
+		description="fixes our ant classpath (if possible)">
+		<copy todir="${user.home}/.ant/lib"
+			preservelastmodified="true">
+			<fileset dir="lib/">
+				<include name="bsf.jar"/>
+				<include name="ant-apache-bsf.jar"/>
+				<include name="saxon9.jar"/>
+				<include name="resolver.jar"/>
+				<include name="commons-logging-1.1.1.jar"/>
+			</fileset>
+		</copy>
+		<copy todir="${user.home}/.ant/lib"
+			preservelastmodified="true">
+			<fileset dir="../../shrinksafe">
+				<include name="js.jar"/>
+			</fileset>
+		</copy>
+
+		<echo message=""/>
+		<echo message="+--------------------------------------------------------+" />
+		<echo message="| Due to some horrendous design decisions by the authors |" />
+		<echo message="| of Ant, it has been necessary to install some jar     |" />
+		<echo message="| files to your ~/.ant/ directory. Given the nature of   |" />
+		<echo message="| the problem, it will be necessary for you to re-run   |" />
+		<echo message="| your build command.                                    |" />
+		<echo message="|                                                        |" />
+		<echo message="| The Dojo team apologies for this inconvenience.        |" />
+		<echo message="|                                                        |" />
+		<echo message="| The system will now exit.                              |" />
+		<echo message="+--------------------------------------------------------+" />
+		<echo message=""/>
+
+		<fail message="Sorry, please re-run your build command, it should work now"/>
+	</target>
+
+	<target name="ldml" depends="-ldml-check" unless="ldmlUnpacked"
+		description="Unpack LDML (CLDR repository XML markup)">
+		<mkdir dir="${ldml}/core" />
+		<unzip src="${ldml}/core.zip" dest="${ldml}/core" />
+	</target>
+	<target name="-ldml-check">
+		<available property="ldmlUnpacked" file="${ldml}/core" type="dir" />
+	</target>
+
+	<target name="clean">
+		<delete dir="${ldml}/core" />
+		<delete dir="${json}" />
+		<mkdir dir="${json}" />
+	</target>
+
+	<target name="cldr" depends="-fix-config, ldml"
+		description="Transforms LDML from the CLDR into JSON">
+
+		<scriptdef name="removeEmptyOutput" language="javascript">
+			<attribute name="dir"/>
+			<![CDATA[
+		function isEmpty(o){
+			for(x in o){
+				return false;
+			}
+			return true;
+		}
+
+		var delTask = project.createTask("delete");
+		function deleteResource(f){
+			f.isDirectory() ? delTask.setDir(f) : delTask.setFile(f);
+			delTask.perform();
+		}
+
+	var fs = project.createDataType("fileset");
+	var dir = new java.io.File(attributes.get("dir"));
+	fs.setDir(dir);
+	fs.setIncludes("*.js");
+	ds = fs.getDirectoryScanner(project);
+	jsFiles = ds.getIncludedFiles();
+
+	var load = project.createTask("loadfile");
+	load.setEncoding("UTF8");
+	for (var i=0; i<jsFiles.length; i++) {
+		var srcFile = java.io.File(dir, jsFiles[i]);
+		load.setSrcFile(srcFile);
+		//FIXME: spawn task as separate ant process to avoid stale properties, collisions?
+		var uniqueId = "removeEmptyOutput.json."+dir+"."+i;
+		load.setProperty(uniqueId);
+		load.perform();
+
+		var contents = String(project.getProperty(uniqueId));
+		if(contents.charCodeAt(0) == 0xfeff){ contents = contents.substring(1); } // JDK bug workaround
+
+		try{
+			var value = eval(contents);
+		}catch(e){
+			java.lang.System.out.print("Syntax error in "+srcFile.getCanonicalPath());
+			throw e;
+		}
+		if(isEmpty(value)){
+			deleteResource(srcFile);
+		}
+	}
+
+	// delete the directory if empty
+	ds.scan();
+	if(!ds.getIncludedFilesCount()){
+		deleteResource(dir);
+	}
+			]]>
+		</scriptdef>
+
+		<macrodef name="processLdml">
+			<attribute name="in"/>
+			<attribute name="basedir"/>
+			<attribute name="destdir"/>
+
+			<sequential>
+				<mkdir dir="@{destdir}"/>
+				<transform in="@{in}" style="calendar.xsl" basedir="@{basedir}" destdir="@{destdir}"/>
+				<transform in="@{in}" style="number.xsl" basedir="@{basedir}" destdir="@{destdir}"/>
+				<transform in="@{in}" style="currency.xsl" basedir="@{basedir}" destdir="@{destdir}"/>
+				<echo level="info" message="Transformed @{in} to @{destDir}" taskName="cldr"/>
+				<removeEmptyOutput dir="@{destdir}" />
+			</sequential>
+		</macrodef>
+		<macrodef name="transform">
+			<attribute name="in"/>
+			<attribute name="style"/>
+			<attribute name="basedir"/>
+			<attribute name="destdir"/>
+			<sequential>
+				<xslt includes="@{in}" style="@{style}" destdir="@{destdir}" basedir="@{basedir}" extension=".tmp">
+					<factory name="net.sf.saxon.TransformerFactoryImpl" />
+					<xmlcatalog>
+						<catalogpath path="ldml/catalog" />
+					</xmlcatalog>
+					<param name="basedir" expression="@{basedir}/" />
+					<param name="currencyList" expression="${currencies}" />
+				</xslt>
+				<delete>
+					<fileset dir="@{destdir}" includes="*.tmp" />
+				</delete>
+			</sequential>
+		</macrodef>
+
+		<scriptdef name="transformCldr" language="javascript">
+			<attribute name="destdir"/>
+			<element name="fileset" type="fileset"/>
+			<![CDATA[
+	var fs = elements.get("fileset").get(0);
+	var basedir = fs.getDir(project);
+
+	var filter = project.getProperty("locales");
+	if(filter){
+		filter = String(filter).replace(/-/g,'_').split(",");
+		for(var i in filter){
+			filter[i] = filter[i].replace(/\s/g,'');
+			var variants = filter[i].split("_");
+			for(var j = 1; j <= variants.length - 1; j++){
+				var partial = variants.slice(0, j).join("_");
+				for(var k = 0; k < filter.length; k++){
+					if(filter[k]==partial){
+						partial=null; continue;
+					}
+				}
+				if(partial){filter.push(partial)};
+			}
+		}
+		filter.push("root");
+		var fs = project.createDataType("fileset");
+		fs.setDir(basedir);
+		fs.setCaseSensitive(false);
+		var orSelector = new Packages.org.apache.tools.ant.types.selectors.OrSelector();
+		for(i in filter){
+			var locale=filter[i];
+			var selector = new Packages.org.apache.tools.ant.types.selectors.FilenameSelector();
+			selector.setName(locale + ".xml");
+			selector.setCasesensitive(false);
+			orSelector.addFilename(selector);
+		}
+		fs.addOr(orSelector);
+	}
+		
+	ds = fs.getDirectoryScanner(project);
+	srcFiles = ds.getIncludedFiles();
+	var destdir = attributes.get("destdir");
+
+	for (i=0; i<srcFiles.length; i++) {
+		var filename = srcFiles[i];
+		var locale = filename.substring(0, filename.indexOf(".")).replace("_","-").toLowerCase();
+		var outdir = new java.io.File(locale == "root" ? destdir : destdir+"/"+locale);
+
+		var ldml = project.createTask("processLdml");
+		ldml.setDynamicAttribute("in", new java.io.File(filename));
+		ldml.setDynamicAttribute("destdir", outdir);
+		ldml.setDynamicAttribute("basedir", basedir);
+		ldml.perform();
+	}
+			]]>
+		</scriptdef>
+
+		<transformCldr destdir="${json}">
+			<fileset dir="${ldml}/core/common/main" includes="**/*.xml" />
+		</transformCldr>
+		<java jar="../../shrinksafe/js.jar" failonerror="true" fork="true" logError="true" >
+			<arg value="arrayInherit.js" />
+			<arg value="${json}" />
+			<arg value="${logDir}"/>
+			<sysproperty key="DOJO_LOADER" value="${dojoLoader}" />
+		</java>
+		<java jar="../../shrinksafe/js.jar" failonerror="true" fork="true" logError="true" >
+			<arg value="specialLocale.js" />
+			<arg value="${json}" />
+			<arg value="${locales}" />
+			<arg value="${logDir}"/>
+			<sysproperty key="DOJO_LOADER" value="${dojoLoader}" />
+		</java>
+		<java jar="../../shrinksafe/js.jar" failonerror="true" fork="true" logError="true" >
+			<arg value="alias.js" />
+			<arg value="${json}" />
+			<arg value="${logDir}"/>
+			<sysproperty key="DOJO_LOADER" value="${dojoLoader}" />
+		</java>
+	</target>
+</project>
diff --git a/util/buildscripts/cldr/calendar.xsl b/util/buildscripts/cldr/calendar.xsl
new file mode 100644
index 0000000..859d42d
--- /dev/null
+++ b/util/buildscripts/cldr/calendar.xsl
@@ -0,0 +1,716 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:saxon="http://saxon.sf.net/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" extension-element-prefixes="saxon" version="2.0">
+<xsl:import href="util.xsl"/>
+<xsl:output method="text" indent="yes" saxon:byte-order-mark="yes"/>
+<!-- list the data elements whose spaces should be preserved
+   it seems listing only the parent node doesn't work -->
+    <xsl:preserve-space elements="month day quarter dayPeriod era pattern dateFormatItem appendItem displayName"/>
+<xsl:strip-space elements="*"/> 
+<xsl:variable name="index" select="number(1)" saxon:assignable="yes"/>
+
+<xsl:template match="/">
+     <xsl:apply-templates/>
+</xsl:template>
+
+<!-- process ldml,dates,calendars-->
+<xsl:template name="top" match="/ldml">
+    <xsl:choose>
+        <xsl:when test="count(./alias)>0">
+            <!-- Handle Alias -->
+            <xsl:for-each select="./alias">
+                <xsl:call-template name="alias_template">
+                    <xsl:with-param name="templateToCall">top</xsl:with-param>
+                    <xsl:with-param name="source" select="@source"></xsl:with-param>
+                    <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+                </xsl:call-template>  
+                </xsl:for-each>
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:choose>
+                <xsl:when test="name()='calendars'">
+                    <!-- calendars -->
+                    <xsl:for-each select="calendar">
+                        <saxon:assign name="first" select="true()"/>
+                        <xsl:result-document href="{concat(@type,'.js')}" encoding="UTF-8"><!--<xsl:value-of select="codepoints-to-string(65279)"/>-->// generated from ldml/main/*.xml, xpath: ldml/calendars/calendar-<xsl:value-of select="./@type"/>
+({<xsl:call-template name="calendar"></xsl:call-template>
+})
+                        </xsl:result-document>
+                    </xsl:for-each>
+                </xsl:when>
+                <xsl:otherwise>                    
+                    <xsl:if test="name()='ldml'">
+                        <!-- ldml -->
+                        <xsl:for-each select="dates">
+                            <xsl:call-template name="top"></xsl:call-template>
+                        </xsl:for-each>
+                    </xsl:if>
+                    <xsl:if test="name()='dates'">
+                        <!-- dates -->
+                        <xsl:for-each select="calendars">
+                            <xsl:call-template name="top"></xsl:call-template>
+                        </xsl:for-each>
+                    </xsl:if>                 
+                </xsl:otherwise>
+            </xsl:choose>
+         </xsl:otherwise>
+    </xsl:choose>        
+</xsl:template>
+
+    <!-- process calendar-->
+<xsl:template name="calendar" match="calendar">
+    <!-- will be overridden with 'true' if from 'locale' alias, see 'invoke_template_by_name' -->   
+    <xsl:param name="fromLocaleAlias" select="false()"/>
+
+    <!-- insert 'locale' alias information  start -->
+    <xsl:if test="$fromLocaleAlias">
+        <xsl:call-template name="insert_alias_info">
+			<xsl:with-param name="sourceName">*</xsl:with-param>
+            <xsl:with-param name="bundle" select="@type"/>
+        </xsl:call-template>
+    </xsl:if>
+    <!-- insert 'locale' alias information  start -->
+    <xsl:choose>
+        <xsl:when test="count(./alias)>0">
+            <!-- Handle Alias -->
+            <xsl:for-each select="./alias">
+                <xsl:call-template name="alias_template">
+                    <xsl:with-param name="templateToCall">calendar</xsl:with-param>
+                    <xsl:with-param name="source" select="@source"></xsl:with-param>
+                    <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+                </xsl:call-template>     
+            </xsl:for-each>
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:apply-templates/>
+        </xsl:otherwise>
+    </xsl:choose>
+</xsl:template>
+
+<!-- process months | days | quarters | dayPeriods -->
+    <xsl:template name="months_days_quarters_dayPeriods" match="months | days | quarters | dayPeriods">
+    <xsl:param name="name" select="name()"/>
+    <xsl:param name="width" select="@type"/>
+    <xsl:param name="ctx" select="../@type"/>
+     <!-- will be overridden with 'true' if from 'locale' alias, see 'invoke_template_by_name' -->   
+     <xsl:param name="fromLocaleAlias" select="false()"/>
+
+	<xsl:variable name="item" select="substring-before(name(), 'Width')"/>
+	<!-- insert 'locale' alias information start -->
+    <xsl:if test="$fromLocaleAlias">
+        <xsl:if test="name()='months' or name()='days' or name()='quarters' or name()='dayPeriods'">
+                <xsl:call-template name="insert_alias_info"/>
+         </xsl:if>
+        <xsl:if test="name()='monthWidth' or name()='dayWidth' or name()='quarterWidth' or name()='dayPeriodWidth'">
+            <!-- e.g.  for <monthContext type="format">
+        		<monthWidth type="abbreviated">
+        			<alias source="locale" path="../monthWidth[@type='wide']"/>
+        		</monthWidth> 
+                          ......                   
+	            alias info will be recorded as 'months-format-abbr at localeAlias' : {'target' : "months-format-wide"}                        
+	            TBD: Seems the following section cann't be extracted out as a reusable template       
+	            insert 'locale' alias information end -->
+	            <xsl:call-template name="insert_comma"/>
+	'<xsl:value-of select="$item"/><xsl:text>s-</xsl:text>
+	            <xsl:call-template name="camel_case">
+	                <xsl:with-param name="name"><xsl:value-of select="$ctx"></xsl:value-of></xsl:with-param>
+	            </xsl:call-template>
+	            <xsl:choose>
+	                <xsl:when test="$width='abbreviated'"><xsl:text>-abbr</xsl:text></xsl:when>
+	                <xsl:otherwise><xsl:value-of select="concat('-',$width)"></xsl:value-of></xsl:otherwise>
+	            </xsl:choose>
+	            <xsl:text>@localeAlias</xsl:text>
+				<xsl:value-of select="$index"/><saxon:assign name="index" select="sum($index + 1)"/>
+				<xsl:text>':{'target':"</xsl:text><xsl:value-of select="$item"/><xsl:text>s-</xsl:text>
+	            <xsl:call-template name="camel_case">
+	                <xsl:with-param name="name"><xsl:value-of select="../@type"/></xsl:with-param>
+	            </xsl:call-template>
+	            <xsl:choose>
+	                <xsl:when test="@type='abbreviated'"><xsl:text>-abbr</xsl:text></xsl:when>
+	                <xsl:otherwise><xsl:value-of select="concat('-', at type)"/></xsl:otherwise>
+	            </xsl:choose> 
+	            <xsl:text>",'bundle':"</xsl:text><xsl:value-of select="../../../@type"/><xsl:text>"}</xsl:text>
+		</xsl:if>  
+    </xsl:if>
+	<!-- insert 'locale' alias information end -->       
+	 
+    <xsl:choose>       
+        <xsl:when test="count(./alias)>0">
+            <!-- Handle Alias -->
+            <xsl:for-each select="./alias">
+                <xsl:call-template name="alias_template">
+                    <xsl:with-param name="templateToCall">months_days_quarters_dayPeriods</xsl:with-param>
+                    <xsl:with-param name="source" select="@source"></xsl:with-param>
+                    <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+                    <xsl:with-param name="name" select="$name"></xsl:with-param>
+					<xsl:with-param name="width" select="$width"></xsl:with-param>
+                    <xsl:with-param name="ctx" select="$ctx"></xsl:with-param>
+                </xsl:call-template>
+            </xsl:for-each>            
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:if test="name()='months' or name()='monthContext' or name()='days' or name()='dayContext'
+                or name()='quarters' or name()='quarterContext' or name()='dayPeriods' or name()='dayPeriodContext'">
+                <xsl:for-each select="*">
+                    <xsl:call-template name="months_days_quarters_dayPeriods"></xsl:call-template>
+                </xsl:for-each>
+            </xsl:if>
+            <xsl:if test="name()='monthWidth' or name()='dayWidth' or name()='quarterWidth' or name()='dayPeriodWidth' ">
+                <!--xsl:variable name="item" select="substring-before(name(), 'Width')"/-->
+                <xsl:if test="count(*[not(@draft)])>0 or count(*[@draft!='provisional' and @draft!='unconfirmed'])>0">
+					<xsl:choose>
+						<!-- special format for dayPeriodWidth e.g.'dayPeriods-am-format-wide':"AM"-->
+						<xsl:when test="name()='dayPeriodWidth'">
+					        <xsl:call-template name="apm">
+				                <xsl:with-param name="item" select="$item"></xsl:with-param>
+								<xsl:with-param name="width" select="$width"></xsl:with-param>
+								<xsl:with-param name="ctx" select="$ctx"></xsl:with-param>
+					        </xsl:call-template>				
+						</xsl:when>
+						<!--monthWidth, dayWidth and quarterWidth-->
+						<xsl:otherwise>					
+			                <xsl:call-template name="insert_comma"/>
+	'<xsl:value-of select="$item"/>
+			                <xsl:text>s-</xsl:text>
+			                <xsl:call-template name="camel_case">
+			                    <xsl:with-param name="name"><xsl:value-of select="$ctx"></xsl:value-of></xsl:with-param>
+			                </xsl:call-template>
+			                <xsl:choose>
+			                	<xsl:when test="$width='abbreviated'"><xsl:text>-abbr</xsl:text></xsl:when>
+			                	<xsl:otherwise>
+			                       <xsl:value-of select="concat('-',$width)"></xsl:value-of>
+			                    </xsl:otherwise>
+			                </xsl:choose>
+			                <xsl:text>':</xsl:text>
+			                <!--xsl:call-template name="subSelect"><xsl:with-param name="name" select="./*[name()=$item]"></xsl:with-param></xsl:call-template-->
+			                <xsl:call-template name="subSelect_in_place"><xsl:with-param name="name" select="$item"></xsl:with-param></xsl:call-template>
+							<!-- for leap month -->
+							<xsl:for-each select="*[@yeartype='leap']">
+	    						<xsl:call-template name="insert_comma"/>
+	'<xsl:value-of select="$item"/><xsl:text>s-</xsl:text>
+	    						<xsl:call-template name="camel_case">
+							        <xsl:with-param name="name"><xsl:value-of select="$ctx"></xsl:value-of></xsl:with-param>
+							    </xsl:call-template>
+							    <xsl:choose>
+							    	<xsl:when test="$width='abbreviated'"><xsl:text>-abbr</xsl:text></xsl:when>
+							    	<xsl:otherwise>
+							           <xsl:value-of select="concat('-',$width)"></xsl:value-of>
+							        </xsl:otherwise>
+							    </xsl:choose>
+								<xsl:text>-</xsl:text><xsl:value-of select="@yeartype"/><xsl:text>':"</xsl:text>
+							    <xsl:value-of select="replace(.,'"', '\\"')"/><xsl:text>"</xsl:text>
+							</xsl:for-each>						
+						</xsl:otherwise>
+					</xsl:choose>
+                </xsl:if>               
+         	</xsl:if>
+         </xsl:otherwise>
+    </xsl:choose>
+</xsl:template>
+  
+    <!-- template for inserting 'locale' alias information, 
+           e.g. for     <calendar type="buddhist">
+                                <months>
+                                    <alias source="locale" path="../../calendar[@type='gregorian']/months"/>
+                                </months>
+                                      ......
+         alias info will be recorded as 'months at localeAlias' : {'target':"months", 'bundle' : 'gregorian'}    -->
+    <xsl:template name="insert_alias_info">
+        <!-- alias source node name-->
+        <xsl:param name="sourceName" select="name()"></xsl:param>
+        <!-- alias target node name, same as source node by default-->
+        <xsl:param name="targetName" select="$sourceName"></xsl:param>
+        <!-- alias target bundle-->
+        <xsl:param name="bundle" select="../@type"></xsl:param>
+        <xsl:call-template name="insert_comma"/>
+	'<xsl:value-of select="$sourceName"/><xsl:text>@localeAlias</xsl:text>
+		<xsl:value-of select="$index"/><saxon:assign name="index" select="sum($index + 1)"/>
+		<xsl:text>':{'target':"</xsl:text><xsl:value-of select="$targetName"/><xsl:text>", 'bundle':"</xsl:text>
+        <xsl:value-of select="$bundle"/><xsl:text>"}</xsl:text>
+    </xsl:template>
+    
+	
+<!--process am & noon & pm for <dayPeriod> -->
+<xsl:template name="apm">
+	<xsl:param name="item"></xsl:param>
+	<xsl:param name="ctx"></xsl:param>
+	<xsl:param name="width"></xsl:param>
+	
+    <xsl:for-each select="*[not(@alt) and (not(@draft) or @draft!='provisional' and @draft!='unconfirmed')]">
+	    <xsl:call-template name="insert_comma"/>
+	'<xsl:value-of select="$item"/><xsl:text>s-</xsl:text>
+	    <xsl:call-template name="camel_case">
+	        <xsl:with-param name="name"><xsl:value-of select="$ctx"></xsl:value-of></xsl:with-param>
+	    </xsl:call-template>
+	    <xsl:choose>
+	    	<xsl:when test="$width='abbreviated'"><xsl:text>-abbr</xsl:text></xsl:when>
+	    	<xsl:otherwise>
+	           <xsl:value-of select="concat('-',$width)"></xsl:value-of>
+	        </xsl:otherwise>
+	    </xsl:choose>
+	    <xsl:text>-</xsl:text><xsl:value-of select="@type"/><xsl:text>':"</xsl:text>
+	    <xsl:value-of select="replace(.,'"', '\\"')"/><xsl:text>"</xsl:text>
+    </xsl:for-each>
+ </xsl:template>
+
+
+<!-- process eras -->
+<xsl:template match="eras" name="eras">
+	<xsl:param name="name" select="name()"></xsl:param>
+    <!-- will be overridden with 'true' if from alias, see 'invoke_template_by_name' -->   
+    <xsl:param name="fromLocaleAlias" select="false()"/>
+			
+   <!-- insert 'locale' alias information start -->
+   <xsl:if test="$fromLocaleAlias">
+		<xsl:choose>
+			<xsl:when test="name()='eras'">
+		        <xsl:call-template name="insert_alias_info">
+		                <xsl:with-param name="sourceName">era</xsl:with-param>
+		        </xsl:call-template>				
+			</xsl:when>
+			<xsl:otherwise>
+		        <xsl:call-template name="insert_alias_info">
+		            <xsl:with-param name="sourceName" select="$name"></xsl:with-param>
+		            <xsl:with-param name="targetName" select="name()"></xsl:with-param>
+		            <xsl:with-param name="bundle" select="../../@type"></xsl:with-param>
+		        </xsl:call-template>
+			</xsl:otherwise>
+		</xsl:choose>	
+    </xsl:if>
+    <!-- insert 'locale' alias information end -->
+
+	<xsl:choose>
+		<xsl:when test="count(./alias)>0">
+			<!-- Handle Alias -->  
+			<xsl:for-each select="./alias">
+				<xsl:call-template name="alias_template">
+					<xsl:with-param name="templateToCall">eras</xsl:with-param>
+					<xsl:with-param name="source" select="@source"></xsl:with-param>
+					<xsl:with-param name="xpath" select="@path"></xsl:with-param>
+					<xsl:with-param name="name" select="$name"></xsl:with-param>
+				</xsl:call-template>
+			</xsl:for-each>	   
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:choose>
+				<xsl:when test="name()='eras'">
+					<xsl:for-each select="*">
+						<xsl:call-template name="eras"></xsl:call-template>
+					</xsl:for-each>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:for-each select=".">
+					    <xsl:if test="count(*[not(@draft)])>0 
+					        or count(*[@draft!='provisional' and @draft!='unconfirmed'])>0">
+					        <xsl:call-template name="insert_comma"/>
+	'<xsl:value-of select="$name"></xsl:value-of>
+						<xsl:text>':</xsl:text>
+					           <xsl:choose>
+					               <xsl:when test="name()='eraNarrow'">
+					                   <!-- only one special case for eraNarrow in root.xml - japanese
+					                         index starts from 232,not 0-->
+					                   <xsl:call-template name="subSelect">
+					                       <xsl:with-param name="name" select="era"></xsl:with-param>
+					                   </xsl:call-template>
+					               </xsl:when>
+					               <xsl:otherwise>
+					                   <xsl:call-template name="subSelect_in_place">
+					                       <xsl:with-param name="name" select="'era'"></xsl:with-param>
+					                   </xsl:call-template>
+					               </xsl:otherwise>
+					           </xsl:choose>
+					        </xsl:if>
+					</xsl:for-each>
+				</xsl:otherwise>
+				</xsl:choose>	  
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<!-- process dateFormat & timeFormat -->   
+ <xsl:template match="dateFormats | timeFormats" name="date_time_Formats">
+     <xsl:param name="width" select="@type"></xsl:param>
+     <!-- will be overridden with 'true' if from alias, see 'invoke_template_by_name' -->   
+     <xsl:param name="fromLocaleAlias" select="false()"/>
+	 
+   <!-- insert 'locale' alias information start -->
+   <xsl:if test="$fromLocaleAlias">
+		<xsl:if test="name()='dateFormats' or name()='timeFormats'">
+             <xsl:call-template name="insert_alias_info">
+                 <xsl:with-param name="sourceName" select="substring-before(name(), 's')"/>
+             </xsl:call-template>
+		</xsl:if>
+        <xsl:if test="name()!='default' and (name()='dateFormatLength' or name()='timeFormatLength')">
+             <xsl:call-template name="insert_alias_info">
+                 <xsl:with-param name="sourceName" select="concat(substring-before(name(), 'Length'), '-',  $width)"/>
+                 <xsl:with-param name="targetName" select="concat(substring-before(name(), 'Length'), '-',  @type)"/>
+                 <xsl:with-param name="bundle" select="../../@type"/>
+             </xsl:call-template>
+         </xsl:if>
+    </xsl:if>
+    <!-- insert 'locale' alias information end -->
+	 
+     <xsl:choose>
+         <xsl:when test="count(./alias)>0">
+             <!-- Handle Alias -->  
+             <xsl:for-each select="./alias">
+                 <xsl:call-template name="alias_template">
+                     <xsl:with-param name="templateToCall">date_time_Formats</xsl:with-param>
+                     <xsl:with-param name="source" select="@source"></xsl:with-param>
+                     <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+					 <xsl:with-param name="width" select="$width"></xsl:with-param>
+                 </xsl:call-template>
+             </xsl:for-each>       
+         </xsl:when>
+         <xsl:otherwise>
+             <xsl:choose>
+                 <xsl:when test="name()='dateFormats' or name()='timeFormats'">
+                     <xsl:for-each select="*">
+                         <xsl:call-template name="date_time_Formats"></xsl:call-template>
+                     </xsl:for-each>
+                 </xsl:when>
+                 <xsl:otherwise>
+                     <xsl:if test="name()!='default'">
+                         <xsl:for-each select=".//pattern[not(@draft)] | 
+                          .//pattern[@draft!='provisional' and @draft!='unconfirmed']">
+                             <xsl:call-template name="insert_comma"/>
+	'<xsl:value-of select="name(..)"></xsl:value-of>
+                         <xsl:text>-</xsl:text>
+                         <xsl:value-of select='$width'/>': "<xsl:value-of select="replace(.,'"', '\\"')"/>
+                         <xsl:text>"</xsl:text>
+                     </xsl:for-each>
+                     </xsl:if>
+                 </xsl:otherwise>
+             </xsl:choose>
+                </xsl:otherwise>
+     </xsl:choose>
+</xsl:template>
+ 
+<!-- process dateTimeFormat -->
+<xsl:template name="dateTimeFormats" match="dateTimeFormats">
+    <xsl:param name="width" select="@type"></xsl:param>
+    <!-- will be overridden with 'true' if from alias, see 'invoke_template_by_name' -->   
+    <xsl:param name="fromLocaleAlias" select="false()"/>
+
+   <!-- insert 'locale' alias information start -->
+   <xsl:if test="$fromLocaleAlias">
+			<xsl:if test="name()='dateTimeFormats'">
+                <xsl:call-template name="insert_alias_info">
+                    <xsl:with-param name="sourceName">dateTime</xsl:with-param>
+                </xsl:call-template>
+			</xsl:if>
+            <xsl:if test="name()='dateTimeFormatLength'">
+                <xsl:call-template name="insert_alias_info">
+                    <xsl:with-param name="sourceName">dateTimeFormat</xsl:with-param>
+                    <xsl:with-param name="bundle" select="../../@type"/>
+                </xsl:call-template>
+            </xsl:if>
+            <xsl:if test="name()='availableFormats'">
+                 <xsl:call-template name="insert_alias_info">
+                     <xsl:with-param name="sourceName">dateTimeAvailableFormats</xsl:with-param>
+                     <xsl:with-param name="bundle" select="../../@type"/>
+                 </xsl:call-template>
+            </xsl:if>
+            <xsl:if test="name()='appendItems'">
+                <xsl:call-template name="insert_alias_info">
+                    <xsl:with-param name="sourceName">dateTimeFormats-appendItem-</xsl:with-param>
+                    <xsl:with-param name="bundle" select="../../@type"/>
+                </xsl:call-template>
+            </xsl:if>
+    </xsl:if>
+	<!-- insert 'locale' alias information start -->
+	
+    <xsl:choose>
+    <xsl:when test="./alias">
+        <!-- Handle Alias -->
+        <xsl:for-each select="./alias">
+            <xsl:call-template name="alias_template">
+                <xsl:with-param name="templateToCall">dateTimeFormats</xsl:with-param>
+                <xsl:with-param name="source" select="@source"></xsl:with-param>
+                <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+				<xsl:with-param name="width" select="$width"></xsl:with-param>
+            </xsl:call-template>
+        </xsl:for-each>
+    </xsl:when>
+    <xsl:otherwise>
+       <xsl:choose>
+            <xsl:when test="name()='dateTimeFormats'">
+                <xsl:for-each select="*">
+                    <xsl:call-template name="dateTimeFormats"></xsl:call-template>
+                </xsl:for-each>
+            </xsl:when>
+            <xsl:otherwise>
+        <xsl:if test="name()!='default'">
+        <!-- patterns -->
+        <xsl:if test="name()='dateTimeFormatLength'">
+            <xsl:for-each select=".//pattern[not(@draft)] | 
+                .//pattern[@draft!='provisional' and @draft!='unconfirmed']">
+                <xsl:call-template name="insert_comma"/>
+	'<xsl:value-of select="name(..)"></xsl:value-of>
+             <xsl:if test="string-length($width) > 0">
+             	<xsl:text>-</xsl:text>
+                          <xsl:value-of select='$width'/>
+              </xsl:if>
+               <xsl:text>': "</xsl:text>
+               <xsl:value-of select="replace(.,'"', '\\"')"/><xsl:text>" </xsl:text>          
+            </xsl:for-each>
+         </xsl:if>
+        <!-- availableFormats -->
+            <xsl:if test="name()='availableFormats'">
+                <xsl:for-each select=".//dateFormatItem[not(@draft)] | 
+                    .//dateFormatItem[@draft!='provisional' and @draft!='unconfirmed']">
+                    <xsl:call-template name="insert_comma"/>
+	'dateFormatItem-<xsl:value-of select="@id"></xsl:value-of>
+                <xsl:text>':"</xsl:text>
+                <xsl:value-of select="replace(.,'"', '\\"')"></xsl:value-of>
+                <xsl:text>"</xsl:text>
+                </xsl:for-each>
+            </xsl:if>
+        <!-- appendItems -->
+            <xsl:if test="name()='appendItems'">
+                <xsl:for-each select=".//appendItem[not(@draft)] | 
+                    .//appendItem[@draft!='provisional' and @draft!='unconfirmed']">
+                    <xsl:call-template name="insert_comma"/>
+	'dateTimeFormats-appendItem-<xsl:value-of select="@request"></xsl:value-of>
+                <xsl:text>':"</xsl:text>
+                <xsl:value-of select="replace(.,'"', '\\"')"></xsl:value-of>
+                <xsl:text>"</xsl:text>
+                </xsl:for-each>
+            </xsl:if>
+     </xsl:if>
+    </xsl:otherwise>
+    </xsl:choose>
+    </xsl:otherwise>
+    </xsl:choose>
+</xsl:template>
+    
+ <!-- process fields-->
+<xsl:template name="fields" match="fields">
+    <xsl:param name="width" select="@type"></xsl:param>
+    <!-- will be overridden with 'true' if from alias, see 'invoke_template_by_name' -->   
+    <xsl:param name="fromLocaleAlias" select="false()"/>
+
+   <!-- insert 'locale' alias information start -->
+   <xsl:if test="$fromLocaleAlias">
+		<xsl:if test="name()='fields'">
+            <xsl:call-template name="insert_alias_info">
+                <xsl:with-param name="sourceName">field</xsl:with-param>
+            </xsl:call-template>				
+		</xsl:if>
+        <xsl:if test="name() = 'field'">
+            <xsl:call-template name="insert_alias_info">
+                <xsl:with-param name="sourceName" select="concat(name(), '-', $width)"/>
+                <xsl:with-param name="targetName" select="concat(name(), '-', @type)"/>
+                <xsl:with-param name="bundle" select="../../@type"/>
+            </xsl:call-template>
+        </xsl:if>
+    </xsl:if>
+    <!-- insert 'locale' alias information end -->	
+	
+    <xsl:choose>
+        <xsl:when test="count(./alias)>0">
+            <!-- Handle Alias -->
+            <xsl:for-each select="./alias">
+                <xsl:call-template name="alias_template">
+                    <xsl:with-param name="templateToCall">fields</xsl:with-param>
+                    <xsl:with-param name="source" select="@source"></xsl:with-param>
+                    <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+					<xsl:with-param name="width" select="$width"></xsl:with-param>
+                </xsl:call-template>
+            </xsl:for-each>
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:choose>
+                <xsl:when test="name()='fields'">
+                    <xsl:for-each select="*">
+                        <xsl:call-template name="fields"></xsl:call-template>
+                    </xsl:for-each>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:for-each select=".//displayName[not(@draft)] | 
+                        .//displayName[@draft!='provisional' and @draft!='unconfirmed']">
+                        <xsl:call-template name="insert_comma"/>
+	'field-<xsl:value-of select="$width"></xsl:value-of>
+                        <xsl:text>':"</xsl:text>
+                        <xsl:value-of select="replace(.,'"', '\\"')"/>
+                        <xsl:text>"</xsl:text>
+                    </xsl:for-each>                    
+                    <xsl:for-each select=".//relative">
+                        <xsl:call-template name="insert_comma"/>
+	'field-<xsl:value-of select="$width"></xsl:value-of>
+                        <xsl:text>-relative+</xsl:text>
+                        <xsl:value-of select="@type"/>
+                        <xsl:text>':"</xsl:text>
+                        <xsl:value-of select="replace(.,'"', '\\"')"/>
+                        <xsl:text>"</xsl:text>
+                    </xsl:for-each>                    
+                </xsl:otherwise>
+            </xsl:choose> 
+         </xsl:otherwise>
+    </xsl:choose>    
+</xsl:template>
+
+<!-- Sub output routine-->
+<xsl:template name="subSelect">
+    <xsl:param name="name"></xsl:param>
+    <xsl:variable name="num" select="count(./$name[not(@draft)])+count(./$name[@draft!='provisional' and @draft!='unconfirmed'])"></xsl:variable>
+    <xsl:if test="$num>1">
+        <xsl:text>[</xsl:text>
+        <xsl:for-each select="$name[not(@draft)] | $name[@draft!='provisional' and @draft!='unconfirmed']">
+            <xsl:text>"</xsl:text>
+            <xsl:value-of select="replace(.,'"', '\\"')"/>
+            <xsl:text>"</xsl:text>
+            <xsl:if test="$num>position()">
+                <xsl:text>,</xsl:text>
+            </xsl:if>            
+        </xsl:for-each>
+        <xsl:text>]</xsl:text>
+    </xsl:if>
+    <xsl:if test="$num=1">
+        <xsl:text>"</xsl:text><xsl:value-of select="replace($name[not(@draft)] 
+            | $name[@draft!='provisional' and @draft!='unconfirmed'],'"', '\\"')"/><xsl:text>"</xsl:text>
+    </xsl:if>
+</xsl:template>
+    
+    
+ <!-- Special sub output routine, only for month, day,quarter,and era, each none
+	"provisional/unconfirmed" draft item should be output in its corresponding place
+	(according to its @type)
+
+	e.g. <month type="5">5</month> should be in the 5th position in the output array,
+	undefined is stuffed for preceding elements-->
+
+<xsl:variable name="last_sibling_type" select="-1" saxon:assignable="yes"/>
+<xsl:variable name="type_value" select="-1" saxon:assignable="yes"/>
+<xsl:variable name="num_expect_preceding_sibling" select="-1" saxon:assignable="yes"/>
+    
+<xsl:template name="subSelect_in_place">
+    <xsl:param name="name"></xsl:param>
+    <!--xsl:variable name="num" select="count(./$name[not(@draft)])+count(./$name[@draft!='provisional' and @draft!='unconfirmed'])"></xsl:variable-->
+    <xsl:variable name="num" select="count(./*[name()=$name and (not(@draft) or @draft!='provisional' and @draft!='unconfirmed') and not(@yeartype)])"></xsl:variable>
+    <xsl:text>[</xsl:text>
+    <!--xsl:for-each select="$name[not(@draft)] | $name[@draft!='provisional' and @draft!='unconfirmed']"-->
+    <xsl:for-each select="./*[name()=$name and (not(@draft) or @draft!='provisional' and @draft!='unconfirmed') and not(@yeartype)]">        
+        <xsl:choose>
+            <xsl:when test="$name='day'">
+                <!--TODO: too bad that assign name can not be variable -->
+                <xsl:if test="@type='sun'"><saxon:assign name="type_value" select="1"/> </xsl:if>
+                <xsl:if test="@type='mon'"><saxon:assign name="type_value" select="2"/> </xsl:if>
+                <xsl:if test="@type='tue'"><saxon:assign name="type_value" select="3"/> </xsl:if>
+                <xsl:if test="@type='wed'"><saxon:assign name="type_value" select="4"/> </xsl:if>
+                <xsl:if test="@type='thu'"><saxon:assign name="type_value" select="5"/> </xsl:if>
+                <xsl:if test="@type='fri'"><saxon:assign name="type_value" select="6"/> </xsl:if>
+                <xsl:if test="@type='sat'"><saxon:assign name="type_value" select="7"/> </xsl:if>
+            </xsl:when>
+            <xsl:otherwise><saxon:assign name="type_value" select="@type"/></xsl:otherwise>
+        </xsl:choose>
+        
+        <xsl:choose>
+            <xsl:when test="$name='era'">
+                <!-- index of era starts from  0 -->
+                <saxon:assign name="num_expect_preceding_sibling" select="number($type_value)"/>
+            </xsl:when>
+            <xsl:otherwise><saxon:assign name="num_expect_preceding_sibling" select="number($type_value)-1"/></xsl:otherwise>
+        </xsl:choose>
+        
+        <!--xsl:variable name="num_preceding_sibling" select="count(preceding-sibling::node()[name()=$name and  (not(@draft))])
+            + count(preceding-sibling::node()[name()=$name and @draft!='provisional' and @draft!='unconfirmed'])"></xsl:variable-->
+        <xsl:variable name="num_preceding_sibling" 
+         select="count(preceding-sibling::node()[name()=$name and (not(@draft) or @draft!='provisional' and @draft!='unconfirmed') and not(@yeartype)])"></xsl:variable>
+        
+        <xsl:if test=" $num_expect_preceding_sibling > $num_preceding_sibling">
+            <xsl:if test="$num_preceding_sibling > 0">
+                <xsl:for-each select="(preceding-sibling::node()[name()=$name and (not(@draft) or @draft!='provisional' and @draft!='unconfirmed') and not(@yeartype)])[last()]">
+                    <xsl:choose>
+                        <xsl:when test="$name='day'">
+                            <!--TODO: too bad that assign name can not be variable -->
+                            <xsl:if test="@type='sun'"><saxon:assign name="last_sibling_type" select="1"/> </xsl:if>
+                            <xsl:if test="@type='mon'"><saxon:assign name="last_sibling_type" select="2"/> </xsl:if>
+                            <xsl:if test="@type='tue'"><saxon:assign name="last_sibling_type" select="3"/> </xsl:if>
+                            <xsl:if test="@type='wed'"><saxon:assign name="last_sibling_type" select="4"/> </xsl:if>
+                            <xsl:if test="@type='thu'"><saxon:assign name="last_sibling_type" select="5"/> </xsl:if>
+                            <xsl:if test="@type='fri'"><saxon:assign name="last_sibling_type" select="6"/> </xsl:if>
+                            <xsl:if test="@type='sat'"><saxon:assign name="last_sibling_type" select="7"/> </xsl:if>
+                        </xsl:when>
+                        <xsl:otherwise><saxon:assign name="last_sibling_type" select="@type"/></xsl:otherwise>
+                    </xsl:choose>
+                </xsl:for-each>
+                <xsl:call-template name="retain_preceding_positions">
+                    <xsl:with-param name="num" select="number($type_value)-number($last_sibling_type)-1"></xsl:with-param>
+                </xsl:call-template>
+            </xsl:if>
+            <xsl:if test="$num_preceding_sibling = 0">  
+                <xsl:call-template name="retain_preceding_positions">
+                    <xsl:with-param name="num" select="$num_expect_preceding_sibling"></xsl:with-param>
+                </xsl:call-template>
+            </xsl:if>
+        </xsl:if>
+        <xsl:text>"</xsl:text><xsl:value-of select="replace(.,'"', '\\"')"/><xsl:text>"</xsl:text>
+        <xsl:if test="$num>position()">
+            <xsl:text>,</xsl:text>
+        </xsl:if>            
+    </xsl:for-each>
+    <xsl:text>]</xsl:text>
+</xsl:template>    
+    
+<xsl:variable name="i" select="0" saxon:assignable="yes"/>    
+<xsl:template name="retain_preceding_positions">
+    <xsl:param name="num"></xsl:param>
+    <saxon:assign name="i" select="0"/>
+    <saxon:while test="$num > $i">
+        <xsl:text>undefined,</xsl:text>
+        <saxon:assign name="i" select="$i+1"/>
+    </saxon:while>   
+</xsl:template>
+    
+  <!-- too bad that can only use standard xsl:call-template(name can not be variable) 
+         error occurs if use <saxon:call-templates($templateToCall)  /> -->
+ <xsl:template name="invoke_template_by_name">
+     <xsl:param name="templateName"></xsl:param>
+     <xsl:param name="name"></xsl:param> 
+     <xsl:param name="width"></xsl:param>
+	 <xsl:param name="ctx"></xsl:param>
+     <xsl:param name="fromLocaleAlias"></xsl:param>
+     <xsl:if test="$templateName='top'">
+         <xsl:call-template name="top"></xsl:call-template>
+     </xsl:if>
+     <xsl:if test="$templateName='calendar'">
+         <xsl:call-template name="calendar">
+		 	<xsl:with-param name="fromLocaleAlias" select="$fromLocaleAlias"></xsl:with-param>
+		 </xsl:call-template>
+     </xsl:if>
+     <xsl:if test="$templateName='months_days_quarters_dayPeriods'">
+         <xsl:call-template name="months_days_quarters_dayPeriods">
+		  	  <xsl:with-param name="name" select="$name"></xsl:with-param>
+              <xsl:with-param name="width" select="$width"></xsl:with-param>
+			  <xsl:with-param name="ctx" select="$ctx"></xsl:with-param>
+             <xsl:with-param name="fromLocaleAlias" select="$fromLocaleAlias"></xsl:with-param>
+          </xsl:call-template>
+     </xsl:if>
+     <xsl:if test="$templateName='eras'">
+         <xsl:call-template name="eras">
+             <xsl:with-param name="name" select="$name"></xsl:with-param>
+             <xsl:with-param name="fromLocaleAlias" select="$fromLocaleAlias"></xsl:with-param>
+         </xsl:call-template>
+     </xsl:if>
+     <xsl:if test="$templateName='date_time_Formats'">
+         <xsl:call-template name="date_time_Formats">
+             <xsl:with-param name="width" select="$width"></xsl:with-param>
+             <xsl:with-param name="fromLocaleAlias" select="$fromLocaleAlias"></xsl:with-param>
+         </xsl:call-template>
+     </xsl:if>
+     <xsl:if test="$templateName='dateTimeFormats'">
+         <xsl:call-template name="dateTimeFormats">
+             <xsl:with-param name="width" select="$width"></xsl:with-param>
+             <xsl:with-param name="fromLocaleAlias" select="$fromLocaleAlias"></xsl:with-param>
+         </xsl:call-template>
+     </xsl:if>
+     <xsl:if test="$templateName='fields'">
+         <xsl:call-template name="fields">
+             <xsl:with-param name="width" select="$width"></xsl:with-param>
+             <xsl:with-param name="fromLocaleAlias" select="$fromLocaleAlias"></xsl:with-param>
+         </xsl:call-template>
+     </xsl:if>     
+ </xsl:template>
+    
+</xsl:stylesheet>
diff --git a/util/buildscripts/cldr/cldrUtil.js b/util/buildscripts/cldr/cldrUtil.js
new file mode 100644
index 0000000..b29b40f
--- /dev/null
+++ b/util/buildscripts/cldr/cldrUtil.js
@@ -0,0 +1,49 @@
+(function(){
+	// monkey patch fromJson to avoid Rhino bug in eval: https://bugzilla.mozilla.org/show_bug.cgi?id=471005
+	var fromJson = dojo.fromJson;
+	dojo.fromJson = function(json){
+		json = json.replace(/[\u200E\u200F\u202A-\u202E]/g, function(match){
+			return "\\u" + match.charCodeAt(0).toString(16);
+		})
+		return json ? fromJson(json) : ""; //TODO: json value passed in shouldn't be empty
+	}
+})();
+
+function isLocaleAliasSrc(prop, bundle){
+	if(!bundle){ return false; }
+	var isAlias = false;
+	var LOCALE_ALIAS_MARK = '@localeAlias';
+
+	for(x in bundle){
+		if(x.indexOf(LOCALE_ALIAS_MARK) > 0){
+			var prefix = x.substring(0,x.indexOf(LOCALE_ALIAS_MARK));
+			if(prop.indexOf(prefix) == 0){
+				isAlias = true;
+			}
+		}
+	}	
+	return isAlias;
+}
+
+function getNativeBundle(filePath){
+	//summary: get native bundle content with utf-8 encoding
+	//	native means the content of this bundle is not flattened with parent 
+	//	returns empty object if file not found
+	try{
+		var content = readFile(filePath, "utf-8");
+		return (!content || !content.length) ? {} : dojo.fromJson(content);
+	}catch(e){
+		return {};
+	}
+}
+
+function compare(a/*String or Array*/, b/*String or Array*/){
+	//summary: simple comparison
+	if(dojo.isArray(a) && dojo.isArray(b)){
+		for(var i = 0; i < a.length; i++){
+			if(a[i] != b[i]){ return false; }
+		}
+		return true;
+	}
+	return a==b;
+}
diff --git a/util/buildscripts/cldr/currency.xsl b/util/buildscripts/cldr/currency.xsl
new file mode 100644
index 0000000..6ef1d48
--- /dev/null
+++ b/util/buildscripts/cldr/currency.xsl
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:saxon="http://saxon.sf.net/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" extension-element-prefixes="saxon" version="2.0">
+<xsl:import href="util.xsl"/>
+<xsl:output method="text" indent="yes" saxon:byte-order-mark="yes"/>
+<!-- list the data elements whose spaces should be preserved
+       it seems listing only the parent node doesn't work -->
+<xsl:preserve-space elements="displayName symbol"/>
+<xsl:strip-space elements="*"/>
+
+<!--  currencyList is an external string property like "AUD|BEF|CAD|CHF|CNY|DEM|...|USD",
+        if it is provided, only those currencies in this list will be extracted,
+        otherwise all the currencies will be extracted by default-->
+<xsl:param name="currencyList"></xsl:param>
+
+<xsl:template match="/">
+     <xsl:apply-templates/>
+</xsl:template>
+
+<!-- process ldml, numbers and currencies -->
+<xsl:template name="top" match="/ldml">
+    <xsl:choose>
+        <xsl:when test="count(./alias)>0">
+            <!-- Handle Alias -->
+            <xsl:for-each select="./alias">
+                <xsl:call-template name="alias_template">
+                    <xsl:with-param name="templateToCall">top</xsl:with-param>
+                    <xsl:with-param name="source" select="@source"></xsl:with-param>
+                    <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+                </xsl:call-template>     
+                </xsl:for-each>
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:choose>
+                <xsl:when test="name()='currencies'">
+                    <xsl:result-document href="currency.js" encoding="UTF-8">// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies
+({<xsl:choose><xsl:when test="string-length(string($currencyList))>0 and string($currencyList)!='${currencies}'">
+<!--if outer param $currencyList is not initiated, it will be '${currencies}' by default,please see ${util}/buildscripts/cldr/build.xml -->
+                                 <xsl:for-each select="currency">
+                                     <xsl:if test="contains($currencyList, at type)">
+                                         <xsl:call-template name="currency"></xsl:call-template>
+                                     </xsl:if>
+                                 </xsl:for-each>
+                         </xsl:when>
+                         <xsl:otherwise>
+                             <xsl:for-each select="currency">
+                                 <xsl:call-template name="currency"></xsl:call-template>                        
+                             </xsl:for-each>
+                         </xsl:otherwise>
+                     </xsl:choose>
+})
+                 </xsl:result-document>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:if test="name()='ldml'">
+                        <!-- ldml -->
+                        <xsl:for-each select="numbers">    
+                            <xsl:call-template name="top"></xsl:call-template>
+                        </xsl:for-each>
+                    </xsl:if>
+                    <xsl:if test="name()='numbers'">
+                        <!-- numbers -->
+                        <xsl:for-each select="currencies">
+                            <xsl:call-template name="top"></xsl:call-template>
+                        </xsl:for-each>
+                    </xsl:if>                 
+                </xsl:otherwise>
+            </xsl:choose>
+         </xsl:otherwise>
+    </xsl:choose>        
+</xsl:template>
+
+    <!-- currency-->
+    <xsl:template name="currency" match="currency">
+    <xsl:param name="width" select="@type"></xsl:param>
+    <xsl:choose>
+        <xsl:when test="count(./alias)>0">
+            <!-- Handle Alias -->
+            <xsl:for-each select="./alias">
+                <xsl:call-template name="alias_template">
+                    <xsl:with-param name="templateToCall">currency</xsl:with-param>
+                    <xsl:with-param name="source" select="@source"></xsl:with-param>
+                    <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+                </xsl:call-template>
+            </xsl:for-each>
+        </xsl:when>
+        <xsl:otherwise>
+        <!-- CLDR 1.6+: skip entries in the form of displayName count="" until we implement plurals -->
+            <xsl:for-each select="*[not(@count) and (not(@draft) or (@draft!='provisional' and @draft!='unconfirmed'))]">
+				<xsl:call-template name="insert_comma"/>
+                <xsl:text>
+	</xsl:text>
+		        <xsl:value-of select="$width"></xsl:value-of>
+                <xsl:text>_</xsl:text>
+                <xsl:value-of select="name()"></xsl:value-of>
+                <xsl:text>:"</xsl:text>
+                <xsl:value-of select="replace(.,'"', '\\"')"></xsl:value-of>
+                <xsl:text>"</xsl:text>
+            </xsl:for-each>
+         </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <!-- too bad that can only use standard xsl:call-template(name can not be variable) 
+         error occurs if use <saxson:call-templates($templateToCall)  /> -->
+    <xsl:template name="invoke_template_by_name">
+        <xsl:param name="templateName"></xsl:param>
+        <xsl:param name="name"></xsl:param> 
+        <xsl:param name="width"></xsl:param>
+		<xsl:param name="ctx"></xsl:param>
+		<xsl:param name="fromLocaleAlias"></xsl:param>
+        <xsl:if test="$templateName='top'">
+            <xsl:call-template name="top"></xsl:call-template>
+        </xsl:if>
+        <xsl:if test="$templateName='currency'">
+            <xsl:call-template name="currency"></xsl:call-template>
+        </xsl:if>
+    </xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/util/buildscripts/cldr/ldml/CatalogManager.properties b/util/buildscripts/cldr/ldml/CatalogManager.properties
new file mode 100755
index 0000000..f6f730e
--- /dev/null
+++ b/util/buildscripts/cldr/ldml/CatalogManager.properties
@@ -0,0 +1,16 @@
+#CatalogManager.properties
+
+verbosity=1
+
+relative-catalogs=no
+
+# Always use semicolons in this list
+catalogs= catalog;
+
+prefer=system
+
+static-catalog=yes
+
+allow-oasis-xml-catalog-pi=yes
+
+catalog-class-name=org.apache.xml.resolver.Resolver
diff --git a/util/buildscripts/cldr/ldml/LICENSE b/util/buildscripts/cldr/ldml/LICENSE
new file mode 100644
index 0000000..7aeb1dd
--- /dev/null
+++ b/util/buildscripts/cldr/ldml/LICENSE
@@ -0,0 +1,29 @@
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+
+Unicode Data Files include all data files under the directories http://www.unicode.org/Public/, http://www.unicode.org/reports/, 
+and http://www.unicode.org/cldr/data/ . Unicode Software includes any source code published in the Unicode Standard or under
+the directories http://www.unicode.org/Public/, http://www.unicode.org/reports/, and http://www.unicode.org/cldr/data/.
+NOTICE TO USER: Carefully read the following legal agreement. BY DOWNLOADING, INSTALLING, COPYING OR 
+OTHERWISE USING UNICODE INC.'S DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU
+UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF THIS
+AGREEMENT. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+Copyright � 1991-2007 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of the Unicode data files and any associated
+documentation (the "Data Files") or Unicode software and any associated documentation (the "Software") to deal in the Data 
+Files or Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell 
+copies of the Data Files or Software, and to permit persons to whom the Data Files or Software are furnished to do so, provided
+that (a) the above copyright notice(s) and this permission notice appear with all copies of the Data Files or Software, (b) both the
+above copyright notice(s) and this permission notice appear in associated documentation, and (c) there is clear notice in each modified Data File 
+or in the Software as well as in the documentation associated with the Data File(s) or Software that the data or software has been modified.
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 
+AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other 
+dealings in these Data Files or Software without prior written authorization of the copyright holder.
\ No newline at end of file
diff --git a/util/buildscripts/cldr/ldml/README b/util/buildscripts/cldr/ldml/README
new file mode 100644
index 0000000..d51c628
--- /dev/null
+++ b/util/buildscripts/cldr/ldml/README
@@ -0,0 +1,3 @@
+The contents of this directory are based on the Common Locale Data Repository (CLDR) project
+located at http://www.unicode.org/cldr and are covered by Unicode Org's terms of use:
+http://www.unicode.org/copyright.html
diff --git a/util/buildscripts/cldr/ldml/catalog b/util/buildscripts/cldr/ldml/catalog
new file mode 100755
index 0000000..ca329b0
--- /dev/null
+++ b/util/buildscripts/cldr/ldml/catalog
@@ -0,0 +1,8 @@
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+
+<system systemId="http://www.unicode.org/cldr/dtd/1.6/ldml.dtd"
+        uri="core/common/dtd/ldml.dtd"/>
+
+</catalog>
+
+
diff --git a/util/buildscripts/cldr/ldml/core.zip b/util/buildscripts/cldr/ldml/core.zip
new file mode 100644
index 0000000..b90e79b
Binary files /dev/null and b/util/buildscripts/cldr/ldml/core.zip differ
diff --git a/util/buildscripts/cldr/lib/APL-2.0.html b/util/buildscripts/cldr/lib/APL-2.0.html
new file mode 100644
index 0000000..26ced39
--- /dev/null
+++ b/util/buildscripts/cldr/lib/APL-2.0.html
@@ -0,0 +1,408 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+               "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright 1999-2006 The Apache Software Foundation
+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=iso-8859-1" />
+  <link rel="stylesheet" href="../style/style.css" type="text/css">
+       <meta name="author" content="The Apache Software Foundation" /><meta name="email" content="apache.AT.apache.DOT.org" />
+    <title>Apache License, Version 2.0 - The Apache Software Foundation</title>
+ </head>
+ <body>        
+  <table border="0" width="100%" cellspacing="0">
+   <tr><!-- SITE BANNER AND PROJECT IMAGE -->
+    <td align="left" valign="top">
+<a href="http://www.apache.org/"><img src="../images/asf_logo_wide.gif" alt="The Apache Software Foundation" align="left" border="0"/></a>
+</td>
+   </tr>
+  </table>
+  <table border="0" width="100%" cellspacing="4">
+   <tr><td colspan="3"><hr noshade="noshade" size="1"/></td></tr>
+   <tr>
+    <!-- LEFT SIDE NAVIGATION -->
+    <td valign="top" nowrap="nowrap" class="navleft">
+           <div class="menuheader"><a 
+href="http://projects.apache.org/">Apache Projects</a></div> 
+    <menu compact="compact">
+          <li><a href="http://httpd.apache.org/" title="Apache Web Server (httpd)">HTTP Server</a></li> 
+          <li><a href="http://activemq.apache.org/" title="Distributed Messaging System">ActiveMQ</a></li> 
+          <li><a href="http://ant.apache.org/" title="Java-based build tool">Ant</a></li> 
+          <li><a href="http://apr.apache.org/" title="Apache Portable Runtime libraries">APR</a></li> 
+          <li><a href="http://beehive.apache.org/" title="Metadata frameworks for enterprise applications">Beehive</a></li> 
+          <li><a href="http://cayenne.apache.org/" title="User-friendly Java ORM with Tools">Cayenne</a></li> 
+          <li><a href="http://cocoon.apache.org/" title="Web development framework: separation of concerns, component-based">Cocoon</a></li> 
+          <li><a href="http://commons.apache.org/" title="Reusable Java components">Commons</a></li> 
+          <li><a href="http://db.apache.org/" title="Database access">DB</a></li> 
+          <li><a href="http://directory.apache.org/" title="Apache Directory Server">Directory</a></li> 
+          <li><a href="http://excalibur.apache.org/" title="Embeddable software libraries related to component and service management access">Excalibur</a></li> 
+          <li><a href="http://felix.apache.org/" title="OSGi Framework and components.">Felix</a></li> 
+          <li><a href="http://forrest.apache.org/" title="Aggregated multi-channel documentation, separation of concerns">Forrest</a></li> 
+          <li><a href="http://geronimo.apache.org/" title="Java2, Enterprise Edition (J2EE) container">Geronimo</a></li> 
+          <li><a href="http://gump.apache.org/" title="Continuous integration of open source projects">Gump</a></li> 
+          <li><a href="http://harmony.apache.org/" title="Open source implementation of Java SE">Harmony</a></li> 
+          <li><a href="http://hivemind.apache.org/" title="A services and configuration microkernel">HiveMind</a></li> 
+          <li><a href="http://ibatis.apache.org/" title="SQL Data Mapper for Java and .NET">iBATIS</a></li> 
+          <li><a href="http://incubator.apache.org/" title="Shepherd for new projects">Incubator</a></li> 
+          <li><a href="http://jackrabbit.apache.org/" title="Content Repository for Java">Jackrabbit</a></li> 
+          <li><a href="http://jakarta.apache.org/" title="Server-side Java">Jakarta</a></li> 
+          <li><a href="http://james.apache.org/" title="Java Apache Mail Enterprise Server">James</a></li> 
+          <li><a href="http://labs.apache.org/" title="The Innovation Laboratories of the Apache Software Foundation">Labs</a></li> 
+          <li><a href="http://lenya.apache.org/" title="Content Management System">Lenya</a></li> 
+          <li><a href="http://logging.apache.org/" title="Cross-language logging services">Logging</a></li> 
+          <li><a href="http://lucene.apache.org/" title="Search engine library">Lucene</a></li> 
+          <li><a href="http://maven.apache.org/" title="Java project management and comprehension tools">Maven</a></li> 
+          <li><a href="http://mina.apache.org/" title="Multipurpose Infrastructure for Network Application">Mina</a></li> 
+          <li><a href="http://myfaces.apache.org/" title="JavaServer(tm) Faces implementation and components">MyFaces</a></li> 
+          <li><a href="http://ode.apache.org/" title="Orchestration Director Engine: Business Process Management (BPM), Process Orchestration and Workflow through service compositioni.">ODE</a></li> 
+          <li><a href="http://ofbiz.apache.org/" title="Open for Business: enterprise automation software">OFBiz</a></li> 
+          <li><a href="http://openejb.apache.org/" title="OpenEJB: a modular, configurable, and extendable EJB Container System and Server">OpenEJB</a></li> 
+          <li><a href="http://openjpa.apache.org/" title="OpenJPA: Object Relational Mapping for Java">OpenJPA</a></li> 
+          <li><a href="http://perl.apache.org/" title="Dynamic websites using Perl">Perl</a></li> 
+          <li><a href="http://poi.apache.org/" title="Java API for OLE 2 Compound Documents">POI</a></li> 
+          <li><a href="http://portals.apache.org/" title="Portal technology">Portals</a></li> 
+          <li><a href="http://roller.apache.org/" title="Java blog server">Roller</a></li> 
+          <li><a href="http://santuario.apache.org/" title="XML Security in Java and C++">Santuario</a></li> 
+          <li><a href="http://shale.apache.org/" title="Web application framework based on JavaServer(tm) Faces">Shale</a></li> 
+          <li><a href="http://spamassassin.apache.org/" title="Mail filter to identify spam">SpamAssassin</a></li> 
+          <li><a href="http://struts.apache.org/" title="Model 2 framework for building Java web applications">Struts</a></li> 
+          <li><a href="http://tapestry.apache.org/" title="Component-based Java Web Application Framework">Tapestry</a></li> 
+          <li><a href="http://tcl.apache.org/" title="Dynamic websites using TCL">TCL</a></li> 
+          <li><a href="http://tiles.apache.org/" title="A templating framework for web application user interfaces">Tiles</a></li> 
+          <li><a href="http://tomcat.apache.org/" title="A Java Servlet and JSP Container">Tomcat</a></li> 
+          <li><a href="http://turbine.apache.org/" title="A Java Servlet Web Application Framework and associated component library">
+         Turbine</a></li> 
+          <li><a href="http://velocity.apache.org/" title="A Java Templating Engine">Velocity</a></li> 
+          <li><a href="http://wicket.apache.org/" title="Component-based Java Web Application Framework.">Wicket</a></li> 
+          <li><a href="http://ws.apache.org/">Web Services</a></li> 
+          <li><a href="http://xalan.apache.org/" title="XSLT processors in Java and C++">Xalan</a></li> 
+          <li><a href="http://xerces.apache.org/" title="XML parsers in Java, C++ and Perl">Xerces</a></li> 
+          <li><a href="http://xml.apache.org/" title="XML solutions focused on the web">XML</a></li> 
+          <li><a href="http://xmlbeans.apache.org/" title="XML-Java binding tool">XMLBeans</a></li> 
+          <li><a href="http://xmlgraphics.apache.org/" title="Conversion from XML to graphical output">XML Graphics</a></li> 
+        </menu>
+    </td>
+    <!-- CONTENT -->
+    <td align="left" valign="top" class="content">
+                <h2><img src="/images/redarrow.gif" alt=" "/>
+   Apache License, Version 2.0
+</h2>
+<div class="section-content">
+<p align="center">
+Apache License<br />
+Version 2.0, January 2004<br />
+<a href="http://www.apache.org/licenses/">http://www.apache.org/licenses/</a>
+</p>
+<p>
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+</p>
+<p><b><a name="definitions">1. Definitions</a></b>.</p>
+<p>
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+</p>
+<p>
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+</p>
+<p>
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+</p>
+<p>
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+</p>
+<p>
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+</p>
+<p>
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+</p>
+<p>
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+</p>
+<p>
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+</p>
+<p>
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+</p>
+<p>
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+</p>
+<p><b><a name="copyright">2. Grant of Copyright License</a></b>.
+Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+</p>
+<p><b><a name="patent">3. Grant of Patent License</a></b>.
+Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+</p>
+<div><b><a name="redistribution">4. Redistribution</a></b>.
+You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+<ol type="a">
+<li>You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+<br /> <br /></li>
+
+<li>You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+<br /> <br /></li>
+
+<li>You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+<br /> <br /></li>
+
+<li>If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.</li>
+</ol>
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+</div>
+<p><b><a name="contributions">5. Submission of Contributions</a></b>.
+Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+</p>
+<p><b><a name="trademarks">6. Trademarks</a></b>.
+This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+</p>
+<p><b><a name="no-warranty">7. Disclaimer of Warranty</a></b>.
+Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+</p>
+<p><b><a name="no-liability">8. Limitation of Liability</a></b>.
+In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+</p>
+<p><b><a name="additional">9. Accepting Warranty or Additional Liability</a></b>.
+While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+</p>
+<p>
+END OF TERMS AND CONDITIONS
+</p>
+</div>
+           <h2><img src="/images/redarrow.gif" alt=" "/>
+   <a name="apply">APPENDIX: How to apply the Apache License to your work</a>
+</h2>
+<div class="section-content">
+<p>
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+</p>
+<div class="source"><code>
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+</code>
+</div>
+</div>
+         </td>
+    <!-- RIGHT SIDE NAVIGATION -->
+    <td valign="top" nowrap="nowrap" class="navright">
+           <div class="menuheader"><a 
+href="/foundation/">Foundation</a></div>
+    <menu compact="compact">
+          <li><a href="/foundation/faq.html">FAQ</a></li> 
+          <li><a href="/licenses/">Licenses</a></li> 
+          <li><a href="/foundation/news.html">News</a></li> 
+          <li><a href="/foundation/records/">Public Records</a></li> 
+          <li><a href="/foundation/sponsorship.html">Sponsorship</a></li> 
+          <li><a href="/foundation/contributing.html">Donations</a></li> 
+          <li><a href="/foundation/thanks.html">Thanks</a></li> 
+          <li><a href="/foundation/contact.html">Contact</a></li> 
+        </menu>
+      <div class="menuheader">Foundation Projects</div>
+    <menu compact="compact">
+          <li><a href="/foundation/conferences.html" title="Meetings of developers and users">Conferences</a></li> 
+          <li><a href="/dev/" title="ASF Infrastructure: Operations and howto documents for PMCs and contributors">Infrastructure</a></li> 
+          <li><a href="/jcp/" title="Apache and the Java Community Process">JCP</a></li> 
+        </menu>
+      <div class="menuheader">How it works</div>
+    <menu compact="compact">
+          <li><a href="/foundation/how-it-works.html">Introduction</a></li> 
+          <li><a href="/foundation/how-it-works.html#meritocracy">Meritocracy</a></li> 
+          <li><a href="/foundation/how-it-works.html#structure">Structure</a></li> 
+          <li><a href="/foundation/how-it-works.html#roles">Roles</a></li> 
+          <li><a href="/foundation/how-it-works.html#management">Collaboration</a></li> 
+          <li><a href="/foundation/how-it-works.html#infrastructure">Infrastructure</a></li> 
+          <li><a href="/foundation/how-it-works.html#incubator">Incubator</a></li> 
+          <li><a href="/foundation/how-it-works.html#other">Other entities</a></li> 
+          <li><a href="/foundation/glossary.html">Glossary</a></li> 
+          <li><a href="/foundation/voting.html">Voting</a></li> 
+        </menu>
+      <div class="menuheader"><a 
+href="/foundation/getinvolved.html">Get Involved</a></div>
+    <menu compact="compact">
+          <li><a href="/foundation/mailinglists.html">Mailing Lists</a></li> 
+          <li><a href="/dev/version-control.html">Version Control</a></li> 
+          <li><a href="/dev/">Developer Info</a></li> 
+        </menu>
+      <div class="menuheader">Download</div>
+    <menu compact="compact">
+          <li><a href="http://www.apache.org/dyn/closer.cgi">from a mirror</a></li> 
+        </menu>
+      <div class="menuheader">Related Sites</div>
+    <menu compact="compact">
+          <li><a href="http://apachecon.com/" title="Official Apache Conference">ApacheCon</a></li> 
+          <li><a href="http://apachebookstore.com/" title="Apache Books">Bookstore</a></li> 
+          <li><a href="http://feathercast.org/" title="Apache Podcasts">Feathercast</a></li> 
+          <li><a href="http://planetapache.org/" title="Apache Community Blogs">PlanetApache</a></li> 
+        </menu>
+
+     <div class="menuheader">Search apache.org</div>
+     <div class="searchbox">
+       <form action="http://www.google.com/search" method="get">
+         <input value="*.apache.org" name="sitesearch" type="hidden"/>
+         <input size="10" name="q" id="query" type="text"/>
+         <input name="Search" value="Go" type="submit"/>
+       </form>
+     </div>
+
+    </td>     
+   </tr>
+   <!-- FOOTER -->
+   <tr><td colspan="3"><hr noshade="noshade" size="1"/></td></tr>
+   <tr><td colspan="3" class="footer">
+         Copyright © 2007 The Apache Software Foundation<br />
+Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.
+       </td>
+   </tr>
+  </table>
+ </body>
+</html>
diff --git a/util/buildscripts/cldr/lib/LICENSE b/util/buildscripts/cldr/lib/LICENSE
new file mode 100644
index 0000000..e60f2bc
--- /dev/null
+++ b/util/buildscripts/cldr/lib/LICENSE
@@ -0,0 +1,10 @@
+This directory contains third-party libraries available under the following licenses:
+
+Apache Software License Version 2.0
+* ant-apache-bsf.jar
+* bsf.jar
+* commons-logging-1.1.1.jar
+* resolver.jar
+
+Mozilla Public License 1.0 (MPL), available at http://www.mozilla.org/MPL/MPL-1.0.html
+* saxon9.jar
diff --git a/util/buildscripts/cldr/lib/MPL-1.0.html b/util/buildscripts/cldr/lib/MPL-1.0.html
new file mode 100644
index 0000000..41efa34
--- /dev/null
+++ b/util/buildscripts/cldr/lib/MPL-1.0.html
@@ -0,0 +1,420 @@
+<TITLE>Mozilla Public License version 1.0</TITLE>
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000"
+      LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
+
+<P ALIGN=CENTER>
+  <FONT SIZE="+2"><B>MOZILLA PUBLIC LICENSE</B></FONT><BR>
+  <B>Version 1.0</B>
+</P>
+
+<P><HR WIDTH="20%"><P>
+
+<P><B>1. Definitions.</B>
+<UL>
+
+    <B>1.1. ``Contributor''</B> means each entity that creates or contributes
+    to the creation of Modifications.
+
+    <P><B>1.2. ``Contributor Version''</B> means the combination of the
+    Original Code, prior Modifications used by a Contributor, and the
+    Modifications made by that particular Contributor.
+
+    <P><B>1.3. ``Covered Code''</B> means the Original Code or Modifications
+    or the combination of the Original Code and Modifications, in each case
+    including portions thereof<B>.</B>
+
+    <P><B>1.4. ``Electronic Distribution Mechanism''</B> means a mechanism
+    generally accepted in the software development community for the
+    electronic transfer of data.
+
+    <P><B>1.5. ``Executable''</B> means Covered Code in any form other than
+    Source Code.
+
+    <P><B>1.6. ``Initial Developer''</B> means the individual or entity
+    identified as the Initial Developer in the Source Code notice required by
+    <B>Exhibit A</B>.
+
+    <P><B>1.7. ``Larger Work''</B> means a work which combines Covered Code
+    or portions thereof with code not governed by the terms of this License.
+
+    <P><B>1.8. ``License''</B> means this document.
+
+    <P><B>1.9. ``Modifications''</B> means any addition to or deletion from
+    the substance or structure of either the Original Code or any previous
+    Modifications.  When Covered Code is released as a series of files, a
+    Modification is: 
+
+	<UL>
+
+	<P><B>A.</B> Any addition to or deletion from the contents of a file
+	containing Original Code or previous Modifications.
+
+	<P><B>B.</B> Any new file that contains any part of the Original
+	Code or previous Modifications.
+
+	</UL>
+
+    <P><B>1.10. ``Original Code''</B> means Source Code of computer software
+    code which is described in the Source Code notice required by <B>Exhibit
+    A</B> as Original Code, and which, at the time of its release under this
+    License is not already Covered Code governed by this License.
+
+    <P><B>1.11. ``Source Code''</B> means the preferred form of the Covered
+    Code for making modifications to it, including all modules it contains,
+    plus any associated interface definition files, scripts used to control
+    compilation and installation of an Executable, or a list of source code
+    differential comparisons against either the Original Code or another well
+    known, available Covered Code of the Contributor's choice. The Source
+    Code can be in a compressed or archival form, provided the appropriate
+    decompression or de-archiving software is widely available for no charge.
+
+    <P><B>1.12. ``You''</B> means an individual or a legal entity exercising
+    rights under, and complying with all of the terms of, this License or a
+    future version of this License issued under Section 6.1. For legal
+    entities, ``You'' includes any entity which controls, is controlled by,
+    or is under common control with You. For purposes of this definition,
+    ``control'' means (a) the power, direct or indirect, to cause the
+    direction or management of such entity, whether by contract or otherwise,
+    or (b) ownership of fifty percent (50%) or more of the outstanding shares
+    or beneficial ownership of such entity.
+
+</UL>
+<B>2. Source Code License.</B>
+<UL>
+
+    <B>2.1. The Initial Developer Grant.</B>
+
+    <BR>The Initial Developer hereby grants You a world-wide, royalty-free,
+    non-exclusive license, subject to third party intellectual property
+    claims: 
+
+	<UL>
+
+	<P><B>(a)</B> to use, reproduce, modify, display, perform, sublicense
+	and distribute the Original Code (or portions thereof) with or
+	without Modifications, or as part of a Larger Work; and
+
+        <P><B>(b)</B> under patents now or hereafter owned or controlled by
+        Initial Developer, to make, have made, use and sell (``Utilize'') the
+        Original Code (or portions thereof), but solely to the extent that
+        any such patent is reasonably necessary to enable You to Utilize the
+        Original Code (or portions thereof) and not to any greater extent
+        that may be necessary to Utilize further Modifications or
+        combinations.
+    </UL>
+
+    <P><B>2.2. Contributor Grant.</B>
+
+    <BR>Each Contributor hereby grants You a world-wide, royalty-free,
+    non-exclusive license, subject to third party intellectual property
+    claims: 
+
+    <UL>
+
+    <P><B>(a)</B> to use, reproduce, modify, display, perform, sublicense and
+    distribute the Modifications created by such Contributor (or portions
+    thereof) either on an unmodified basis, with other Modifications, as
+    Covered Code or as part of a Larger Work; and
+
+    <P><B>(b)</B> under patents now or hereafter owned or controlled by
+    Contributor, to Utilize the Contributor Version (or portions thereof),
+    but solely to the extent that any such patent is reasonably necessary to
+    enable You to Utilize the Contributor Version (or portions thereof), and
+    not to any greater extent that may be necessary to Utilize further
+    Modifications or combinations.
+
+    </UL>
+
+</UL>
+<B>3. Distribution Obligations.</B>
+<UL>
+
+    <B>3.1. Application of License.</B>
+
+    <BR>The Modifications which You create or to which You contribute are
+    governed by the terms of this License, including without limitation
+    Section <B>2.2</B>.  The Source Code version of Covered Code may be
+    distributed only under the terms of this License or a future version of
+    this License released under Section <B>6.1</B>, and You must include a
+    copy of this License with every copy of the Source Code You
+    distribute. You may not offer or impose any terms on any Source Code
+    version that alters or restricts the applicable version of this License
+    or the recipients' rights hereunder. However, You may include an
+    additional document offering the additional rights described in Section
+    <B>3.5</B>.
+
+    <P><B>3.2. Availability of Source Code.</B>
+
+    <BR>Any Modification which You create or to which You contribute must be
+    made available in Source Code form under the terms of this License either
+    on the same media as an Executable version or via an accepted Electronic
+    Distribution Mechanism to anyone to whom you made an Executable version
+    available; and if made available via Electronic Distribution Mechanism,
+    must remain available for at least twelve (12) months after the date it
+    initially became available, or at least six (6) months after a subsequent
+    version of that particular Modification has been made available to such
+    recipients. You are responsible for ensuring that the Source Code version
+    remains available even if the Electronic Distribution Mechanism is
+    maintained by a third party.
+
+    <P><B>3.3. Description of Modifications.</B>
+
+    <BR>You must cause all Covered Code to which you contribute to contain a
+    file documenting the changes You made to create that Covered Code and the
+    date of any change. You must include a prominent statement that the
+    Modification is derived, directly or indirectly, from Original Code
+    provided by the Initial Developer and including the name of the Initial
+    Developer in (a) the Source Code, and (b) in any notice in an Executable
+    version or related documentation in which You describe the origin or
+    ownership of the Covered Code.
+
+    <P><B>3.4. Intellectual Property Matters</B>
+    <UL>
+
+	<P><B>(a) Third Party Claims</B>. 
+
+	<BR>If You have knowledge that a party claims an intellectual
+	property right in particular functionality or code (or its
+	utilization under this License), you must include a text file with
+	the source code distribution titled ``LEGAL'' which describes the
+	claim and the party making the claim in sufficient detail that a
+	recipient will know whom to contact. If you obtain such knowledge
+	after You make Your Modification available as described in Section
+	<B>3.2</B>, You shall promptly modify the LEGAL file in all copies
+	You make available thereafter and shall take other steps (such as
+	notifying appropriate mailing lists or newsgroups) reasonably
+	calculated to inform those who received the Covered Code that new
+	knowledge has been obtained.
+
+	<P><B>(b) Contributor APIs</B>. 
+
+	<BR>If Your Modification is an application programming interface and
+	You own or control patents which are reasonably necessary to
+	implement that API, you must also include this information in the
+	LEGAL file.
+
+    </UL>
+
+    <P><B>3.5. Required Notices.</B>
+
+    <BR>You must duplicate the notice in <B>Exhibit A</B> in each file of the
+    Source Code, and this License in any documentation for the Source Code,
+    where You describe recipients' rights relating to Covered Code. If You
+    created one or more Modification(s), You may add your name as a
+    Contributor to the notice described in <B>Exhibit A</B>. If it is not
+    possible to put such notice in a particular Source Code file due to its
+    structure, then you must include such notice in a location (such as a
+    relevant directory file) where a user would be likely to look for such a
+    notice.  You may choose to offer, and to charge a fee for, warranty,
+    support, indemnity or liability obligations to one or more recipients of
+    Covered Code. However, You may do so only on Your own behalf, and not on
+    behalf of the Initial Developer or any Contributor.  You must make it
+    absolutely clear than any such warranty, support, indemnity or liability
+    obligation is offered by You alone, and You hereby agree to indemnify the
+    Initial Developer and every Contributor for any liability incurred by the
+    Initial Developer or such Contributor as a result of warranty, support,
+    indemnity or liability terms You offer.
+
+    <P><B>3.6. Distribution of Executable Versions.</B>
+
+    <BR>You may distribute Covered Code in Executable form only if the
+    requirements of Section <B>3.1-3.5</B> have been met for that Covered
+    Code, and if You include a notice stating that the Source Code version of
+    the Covered Code is available under the terms of this License, including
+    a description of how and where You have fulfilled the obligations of
+    Section <B>3.2</B>.  The notice must be conspicuously included in any
+    notice in an Executable version, related documentation or collateral in
+    which You describe recipients' rights relating to the Covered Code. You
+    may distribute the Executable version of Covered Code under a license of
+    Your choice, which may contain terms different from this License,
+    provided that You are in compliance with the terms of this License and
+    that the license for the Executable version does not attempt to limit or
+    alter the recipient's rights in the Source Code version from the rights
+    set forth in this License. If You distribute the Executable version under
+    a different license You must make it absolutely clear that any terms
+    which differ from this License are offered by You alone, not by the
+    Initial Developer or any Contributor. You hereby agree to indemnify the
+    Initial Developer and every Contributor for any liability incurred by the
+    Initial Developer or such Contributor as a result of any such terms You
+    offer.
+
+    <P><B>3.7. Larger Works.</B>
+
+    <BR>You may create a Larger Work by combining Covered Code with other
+    code not governed by the terms of this License and distribute the Larger
+    Work as a single product. In such a case, You must make sure the
+    requirements of this License are fulfilled for the Covered Code.
+
+</UL>
+<B>4. Inability to Comply Due to Statute or Regulation.</B>
+<UL>
+
+    <P>If it is impossible for You to comply with any of the terms of this
+    License with respect to some or all of the Covered Code due to statute or
+    regulation then You must: (a) comply with the terms of this License to
+    the maximum extent possible; and (b) describe the limitations and the
+    code they affect. Such description must be included in the LEGAL file
+    described in Section <B>3.4</B> and must be included with all
+    distributions of the Source Code. Except to the extent prohibited by
+    statute or regulation, such description must be sufficiently detailed for
+    a recipient of ordinary skill
+    to be able to understand it.
+
+</UL>
+<B>5. Application of this License.</B>
+<UL>
+
+    This License applies to code to which the Initial Developer has attached
+    the notice in <B>Exhibit A</B>, and to related Covered Code.
+
+</UL>
+<B>6. Versions of the License.</B>
+<UL>
+
+    <B>6.1. New Versions</B>. 
+
+    <BR>Netscape Communications Corporation (``Netscape'') may publish
+    revised and/or new versions of the License from time to time.  Each
+    version will be given a distinguishing version number.
+
+    <P><B>6.2. Effect of New Versions</B>. 
+
+    <BR>Once Covered Code has been published under a particular version of
+    the License, You may always continue to use it under the terms of that
+    version. You may also choose to use such Covered Code under the terms of
+    any subsequent version of the License published by Netscape. No one other
+    than Netscape has the right to modify the terms applicable to Covered
+    Code created under this License.
+
+    <P><B>6.3. Derivative Works</B>. 
+
+    <BR>If you create or use a modified version of this License (which you
+    may only do in order to apply it to code which is not already Covered
+    Code governed by this License), you must (a) rename Your license so that
+    the phrases ``Mozilla'', ``MOZILLAPL'', ``MOZPL'', ``Netscape'', ``NPL''
+    or any confusingly similar phrase do not appear anywhere in your license
+    and (b) otherwise make it clear that your version of the license contains
+    terms which differ from the Mozilla Public License and Netscape Public
+    License. (Filling in the name of the Initial Developer, Original Code or
+    Contributor in the notice described in <B>Exhibit A</B> shall not of
+    themselves be deemed to be modifications of this License.)
+
+</UL>
+<B>7. DISCLAIMER OF WARRANTY.</B>
+<UL>
+
+    COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN ``AS IS'' BASIS,
+    WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+    WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS,
+    MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE
+    RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH
+    YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
+    INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
+    NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY
+    CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE
+    IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+</UL>
+<B>8. TERMINATION.</B>
+<UL>
+
+    This License and the rights granted hereunder will terminate
+    automatically if You fail to comply with terms herein and fail to cure
+    such breach within 30 days of becoming aware of the breach. All
+    sublicenses to the Covered Code which are properly granted shall survive
+    any termination of this License.  Provisions which, by their nature, must
+    remain in effect beyond the termination of this License shall survive.
+
+</UL>
+<B>9. LIMITATION OF LIABILITY.</B>
+<UL>
+
+    UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING
+    NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY
+    OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF
+    ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
+    INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER
+    INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK
+    STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+    COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED
+    OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL
+    NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH
+    PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH
+    LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION
+    OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION
+    MAY NOT APPLY TO YOU.
+
+</UL>
+<B>10. U.S. GOVERNMENT END USERS.</B>
+<UL>
+
+    The Covered Code is a ``commercial item,'' as that term is defined in 48
+    C.F.R. 2.101 (Oct. 1995), consisting of ``commercial computer software''
+    and ``commercial computer software documentation,'' as such terms are
+    used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212
+    and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all
+    U.S. Government End Users acquire Covered Code with only those rights set
+    forth herein.
+
+</UL>
+<B>11. MISCELLANEOUS.</B>
+<UL>
+
+    This License represents the complete agreement concerning subject matter
+    hereof. If any provision of this License is held to be unenforceable,
+    such provision shall be reformed only to the extent necessary to make it
+    enforceable. This License shall be governed by California law provisions
+    (except to the extent applicable law, if any, provides otherwise),
+    excluding its conflict-of-law provisions. With respect to disputes in
+    which at least one party is a citizen of, or an entity chartered or
+    registered to do business in, the United States of America: (a) unless
+    otherwise agreed in writing, all disputes relating to this License
+    (excepting any dispute relating to intellectual property rights) shall be
+    subject to final and binding arbitration, with the losing party paying
+    all costs of arbitration; (b) any arbitration relating to this Agreement
+    shall be held in Santa Clara County, California, under the auspices of
+    JAMS/EndDispute; and (c) any litigation relating to this Agreement shall
+    be subject to the jurisdiction of the Federal Courts of the Northern
+    District of California, with venue lying in Santa Clara County,
+    California, with the losing party responsible for costs, including
+    without limitation, court costs and reasonable attorneys fees and
+    expenses.  The application of the United Nations Convention on Contracts
+    for the International Sale of Goods is expressly excluded. Any law or
+    regulation which provides that the language of a contract shall be
+    construed against the drafter shall not apply to this License.
+
+</UL>
+<B>12. RESPONSIBILITY FOR CLAIMS.</B>
+<UL>
+
+    Except in cases where another Contributor has failed to comply with
+    Section <B>3.4</B>, You are responsible for damages arising, directly or
+    indirectly, out of Your utilization of rights under this License, based
+    on the number of copies of Covered Code you made available, the revenues
+    you received from utilizing such rights, and other relevant factors. You
+    agree to work with affected parties to distribute responsibility on an
+    equitable basis.
+
+</UL>
+<B>EXHIBIT A.</B>
+<UL>
+
+    ``The contents of this file are subject to the Mozilla Public License
+    Version 1.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.mozilla.org/MPL/
+
+    <P>Software distributed under the License is distributed on an "AS IS"
+    basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+    License for the specific language governing rights and limitations under
+    the License.
+
+    <P>The Original Code is ______________________________________.
+
+    <P>The Initial Developer of the Original Code is
+    ________________________.  Portions created by ______________________ are
+    Copyright (C) ______ _______________________.  All Rights Reserved.
+
+    <P>Contributor(s): ______________________________________.''
+
+</UL>
diff --git a/util/buildscripts/cldr/lib/ant-apache-bsf.jar b/util/buildscripts/cldr/lib/ant-apache-bsf.jar
new file mode 100644
index 0000000..c2dca5e
Binary files /dev/null and b/util/buildscripts/cldr/lib/ant-apache-bsf.jar differ
diff --git a/util/buildscripts/cldr/lib/bsf.jar b/util/buildscripts/cldr/lib/bsf.jar
new file mode 100755
index 0000000..3028967
Binary files /dev/null and b/util/buildscripts/cldr/lib/bsf.jar differ
diff --git a/util/buildscripts/cldr/lib/commons-logging-1.1.1.jar b/util/buildscripts/cldr/lib/commons-logging-1.1.1.jar
new file mode 100644
index 0000000..8758a96
Binary files /dev/null and b/util/buildscripts/cldr/lib/commons-logging-1.1.1.jar differ
diff --git a/util/buildscripts/cldr/lib/resolver.jar b/util/buildscripts/cldr/lib/resolver.jar
new file mode 100755
index 0000000..e535bdc
Binary files /dev/null and b/util/buildscripts/cldr/lib/resolver.jar differ
diff --git a/util/buildscripts/cldr/lib/saxon9.jar b/util/buildscripts/cldr/lib/saxon9.jar
new file mode 100644
index 0000000..0106227
Binary files /dev/null and b/util/buildscripts/cldr/lib/saxon9.jar differ
diff --git a/util/buildscripts/cldr/number.xsl b/util/buildscripts/cldr/number.xsl
new file mode 100644
index 0000000..85183c4
--- /dev/null
+++ b/util/buildscripts/cldr/number.xsl
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:saxon="http://saxon.sf.net/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" extension-element-prefixes="saxon" version="2.0">
+<xsl:import href="util.xsl"/>
+<xsl:output method="text" indent="yes" saxon:byte-order-mark="yes"/>
+<!-- list the data elements whose spaces should be preserved
+       it seems listing only the parent node doesn't work -->
+<xsl:preserve-space elements="decimal group list pattern currencyMatch surroundingMatch insertBetween"/>
+<xsl:strip-space elements="*"/> 
+
+<xsl:template match="/">
+     <xsl:apply-templates/>
+</xsl:template>
+
+<!-- process ldml,numbers-->
+<xsl:template name="top" match="/ldml">
+    <xsl:choose>
+        <xsl:when test="count(./alias)>0">
+            <!-- Handle Alias -->
+            <xsl:for-each select="./alias">
+                <xsl:call-template name="alias_template">
+                    <xsl:with-param name="templateToCall">top</xsl:with-param>
+                    <xsl:with-param name="source" select="@source"></xsl:with-param>
+                    <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+                </xsl:call-template>     
+            </xsl:for-each>
+        </xsl:when>
+        <xsl:otherwise>
+                <!-- ldml -->
+                <xsl:if test="name()='ldml'">
+                    <!-- numbers -->
+                    <xsl:for-each select="numbers">
+                        <xsl:result-document href="number.js" encoding="UTF-8"><!--<xsl:value-of select="codepoints-to-string(65279)"/>-->// generated from ldml/main/*.xml, xpath: ldml/numbers
+({<xsl:call-template name="numbers"></xsl:call-template>
+})
+</xsl:result-document>
+                    </xsl:for-each>
+                </xsl:if>
+         </xsl:otherwise>
+    </xsl:choose>
+</xsl:template>
+
+<!-- process numbers-->
+<xsl:template name="numbers" match="numbers">
+    <xsl:choose>
+        <xsl:when test="count(./alias)>0">
+            <!-- Handle Alias -->
+            <xsl:for-each select="./alias">
+                <xsl:call-template name="alias_template">
+                    <xsl:with-param name="templateToCall">numbers</xsl:with-param>
+                    <xsl:with-param name="source" select="@source"></xsl:with-param>
+                    <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+                </xsl:call-template>     
+            </xsl:for-each>
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:apply-templates/>
+        </xsl:otherwise>
+    </xsl:choose>
+</xsl:template>
+
+<!-- process symbols -->
+<xsl:template name="symbols" match="symbols">
+    <xsl:choose>
+        <xsl:when test="count(./alias)>0">
+            <!-- Handle Alias -->
+            <xsl:for-each select="./alias">
+                <xsl:call-template name="alias_template">
+                    <xsl:with-param name="templateToCall">symbols</xsl:with-param>
+                    <xsl:with-param name="source" select="@source"></xsl:with-param>
+                    <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+                </xsl:call-template>     
+            </xsl:for-each>
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:for-each select="*[not(@draft)] | *[@draft!='provisional' and @draft!='unconfirmed']">
+                <xsl:call-template name="insert_comma"/>
+	'<xsl:value-of select="name()"></xsl:value-of>
+                <xsl:text>':"</xsl:text>
+                <xsl:value-of select="replace(.,'"', '\\"')"></xsl:value-of>
+                <xsl:text>"</xsl:text>
+                <!--xsl:if test="count(following-sibling::*)>0
+                    or count(parent::node()/following-sibling::*)>0">
+                    <xsl:text>,</xsl:text>
+                </xsl:if-->                
+            </xsl:for-each>
+        </xsl:otherwise>
+    </xsl:choose>
+</xsl:template>
+    
+<!-- process decimalFormats | scientificFormats | percentFormats | currencyFormats -->       
+<xsl:template name="formats" match="decimalFormats | scientificFormats | percentFormats | currencyFormats">
+    <xsl:param name="width" select="@type"></xsl:param>
+    <xsl:choose>
+        <xsl:when test="count(./alias)>0">
+            <!-- Handle Alias -->  
+            <xsl:for-each select="./alias">
+                <xsl:call-template name="alias_template">
+                    <xsl:with-param name="templateToCall">formats</xsl:with-param>
+                    <xsl:with-param name="source" select="@source"></xsl:with-param>
+                    <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+					<xsl:with-param name="width" select="$width"></xsl:with-param>
+                </xsl:call-template>
+            </xsl:for-each>       
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:choose>
+                <xsl:when test="contains(name(),'Formats')">                   
+                    <xsl:for-each select="*">
+                        <xsl:call-template name="formats"></xsl:call-template>
+                    </xsl:for-each>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:if test="name()!='default'">
+                        <xsl:if test="name()='currencySpacing'">
+                                <xsl:call-template name="currencySpacing"></xsl:call-template>
+                        </xsl:if><xsl:for-each select=".//pattern[not(@draft)] | 
+                          .//pattern[@draft!='provisional' and @draft!='unconfirmed']">
+			                <xsl:call-template name="insert_comma"/>
+	'<xsl:value-of select="name(..)"></xsl:value-of>                            
+                            <xsl:if test="string-length($width)>0">
+                                <xsl:text>-</xsl:text>
+                                <xsl:value-of select="$width"></xsl:value-of>
+                            </xsl:if>
+                            <xsl:text>':"</xsl:text><xsl:value-of select="replace(.,'"', '\\"')"/>
+                            <xsl:text>"</xsl:text>
+                            <!--xsl:if test="count(parent::node()/parent::node()/following-sibling::*)>0
+                                or count(parent::node()/parent::node()/parent::node()/following-sibling::*)>0">
+                                   <xsl:text>,</xsl:text>
+                            </xsl:if-->
+                        </xsl:for-each>                      
+                    </xsl:if>
+                </xsl:otherwise>
+            </xsl:choose>
+        </xsl:otherwise>
+    </xsl:choose>    
+</xsl:template>
+    
+<!-- process currencySpacing -->     
+<xsl:template name="currencySpacing">
+    <xsl:choose>
+        <xsl:when test="count(./alias)>0">
+            <!-- Handle Alias -->
+            <xsl:for-each select="./alias">
+                <xsl:call-template name="alias_template">
+                    <xsl:with-param name="templateToCall">symbols</xsl:with-param>
+                    <xsl:with-param name="source" select="@source"></xsl:with-param>
+                    <xsl:with-param name="xpath" select="@path"></xsl:with-param>
+                </xsl:call-template>     
+            </xsl:for-each>
+        </xsl:when>
+        <xsl:otherwise>
+            <xsl:choose>
+                <xsl:when test="name()='currencySpacing'
+                                  or name()='beforeCurrency' 
+                                  or name()='afterCurrency'" >
+                    <xsl:for-each select="*">
+                        <xsl:call-template name="currencySpacing"></xsl:call-template>
+                    </xsl:for-each>
+                </xsl:when>
+                <xsl:otherwise>
+                   <xsl:if test=".[(not(@draft) or @draft!='provisional' and @draft!='unconfirmed')]">
+	                <xsl:call-template name="insert_comma"/>
+	'<xsl:value-of select="name(../..)"></xsl:value-of>
+                    <xsl:text>-</xsl:text>
+                    <xsl:value-of select="name(..)"></xsl:value-of>
+                    <xsl:text>-</xsl:text>
+                    <xsl:value-of select="name()"></xsl:value-of>
+                     <xsl:text>':"</xsl:text>                   
+                     <xsl:value-of select="replace(.,'"', '\\"')"></xsl:value-of>
+                     <xsl:text>"</xsl:text>
+                    <!--xsl:if test="count(following-sibling::*)>0
+                        or count(parent::node()/following-sibling::*)>0
+                        or count(parent::node()/parent::node()/following-sibling::*)>0
+                        or count(parent::node()/parent::node()/parent::node()/following-sibling::*)>0">
+                        <xsl:text>,</xsl:text>
+                    </xsl:if-->
+                   </xsl:if>
+                </xsl:otherwise>
+            </xsl:choose>
+        </xsl:otherwise> 
+      </xsl:choose>
+</xsl:template>
+
+<xsl:template name="ignore" match="defaultNumberingSystem | currencies"></xsl:template>
+
+  <!-- too bad that can only use standard xsl:call-template(name can not be variable) 
+         error occurs if use <saxson:call-templates($templateToCall)  /> -->
+ <xsl:template name="invoke_template_by_name">
+     <xsl:param name="templateName"></xsl:param>
+     <xsl:param name="name"></xsl:param> 
+     <xsl:param name="width"></xsl:param>
+	 <xsl:param name="ctx"></xsl:param>
+	 <xsl:param name="fromLocaleAlias"></xsl:param>
+     <xsl:if test="$templateName='top'">
+         <xsl:call-template name="top"></xsl:call-template>
+     </xsl:if>
+     <xsl:if test="$templateName='numbers'">
+         <xsl:call-template name="numbers"></xsl:call-template>
+     </xsl:if>
+     <xsl:if test="$templateName='symbols'">
+         <xsl:call-template name="symbols"></xsl:call-template>
+     </xsl:if>
+     <xsl:if test="$templateName='formats'">
+         <xsl:call-template name="formats">
+             <xsl:with-param name="width" select="$width"></xsl:with-param>
+         </xsl:call-template>
+     </xsl:if>
+     <xsl:if test="$templateName='currencySpacing'">
+         <xsl:call-template name="currencySpacing"></xsl:call-template>
+     </xsl:if>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/util/buildscripts/cldr/specialLocale.js b/util/buildscripts/cldr/specialLocale.js
new file mode 100644
index 0000000..577896c
--- /dev/null
+++ b/util/buildscripts/cldr/specialLocale.js
@@ -0,0 +1,188 @@
+/**
+ * In CLDR, there are some special locales with abnormal hierarchy.
+ * 
+ * E.g.zh-hk.xml is aliased to zh-hant-hk.xml for all the calendar/number/currency data.
+ * So after CLDR transformation, JSON bundles under zh-hk is totally the same as those under zh-hant-hk.
+ * Problems will occur when dojo loads zh-hk bundle, as dojo will flatten it with the following sequence:
+ * Root -> zh -> zh-hk, but the right sequence should be Root -> zh -> zh-hant -> zh-hk(zh-hant-hk)
+ * so the bundles under zh-hant locale is missing.
+ * 
+ * This script is used to process all the special locales so that after CLDR transformation,
+ * zh-hk bundle will be flatted both with zh-hant and zh-hant-hk, nothing will be lost then.
+ * Please see the following SPECIAL_LOCALES_MAP for detail mapping info.
+ * 
+ * Note: Here for simplification, we name zh-hk as source locale,and name zh-hant-hk as alias locale.  
+ */
+djConfig={baseUrl: "../../../dojo/"};
+
+load("../../../dojo/dojo.js");
+load("../jslib/logger.js");
+load("../jslib/fileUtil.js");
+load("cldrUtil.js");
+
+dojo.require("dojo.i18n");
+
+var dir/*String*/ = arguments[0];// ${dojo}/dojo/cldr/nls
+
+//locales that are generated by ${dojo}/util/buildscripts/cldr/build.xml
+var allLocalesStr/*String*/ = arguments[1];//e.g. "ar,ar-eg,en-au,en-ca,en-gb,en-us,de-de,es-es,fr-fr,..."
+
+var logDir = arguments[2];
+
+//related bundles, currently only 'number','currency','gregorian' bundles
+//TBD - 'buddhist','chinese','coptic','currency','ethiopic','gregorian','hebrew','islamic','islamic-civil','japanese','persian'
+var BUNDLE_MAP = ['number','currency','gregorian'];
+
+//headers for generated bundle files
+var NLS_JSON_HEAD = ['// generated from ldml/main/*.xml, xpath: ldml/numbers\n',
+				 	 '// generated from ldml/main/*.xml, xpath: ldml/numbers/currencies\n',
+				     '// generated from ldml/main/*.xml, xpath: ldml/calendars/calendar-gregorian\n'];
+
+var SPECIAL_LOCALES_MAP = {
+	//Mapping info for some special locales with abnormal hierarchy.
+	//Currently for CLDR 1.6, will be updated with latest CLDR release.
+
+	'zh-hk':'zh-hant-hk',
+	'zh-mo':'zh-hant-mo',		
+	'sh':'sr-latn',	
+	'mo':'ro-md',
+	'pa-pk':'pa-arab-pk',//pa-pk and pa-arab-pk don't exist, but pa-arab exists		
+	'zh-tw':'zh-hant-tw',//zh-tw and zh-hant-tw don't exist, but zh-hant exists
+	'uz-af':'uz-arab-af',//uz-af and uz-arab-af don't exist, but uz-arab exists
+	'ha-sd':'ha-arab-sd',//ha-sd and ha-arab-sd don't exist, but ha-arab exists
+	'ku-tr':'ku-latn-tr' //ku-tr and ku-latn-tr don't exist, but ku-latn exists
+	
+	/* The following locales don't have any bundles currently (CLDR 1.6),
+	 * listed here for CLDR future release.
+	 *  
+	'az-az':'az-latn-az',
+	'ha-gh':'ha-latn-gh',
+	'ha-ne':'ha-latn-ne',
+	'ha-ng':'ha-latn-ng',
+	'kk-kz':'kk-cyrl-kz',
+	'ku-iq':'ku-latn-iq',
+	'ku-ir':'ku-latn-ir',
+	'ku-sy':'ku-latn-sy',
+	'pa-in':'pa-guru-in',	
+	'sr-cs':'sr-cyrl-cs',
+	'sr-me':'sr-cyrl-me',
+	'sr-rs':'sr-cyrl-rs',
+	'sr-yu':'sr-cyrl-rs',	
+	'uz-uz':'uz-cyrl-uz',
+	'zh-sg':'zh-hans-sg',
+	'zh-cn':'zh-hans-cn',
+	'mn-cn':'mn-mong-cn',
+	'mn-mn':'mn-cyrl-cn',
+	'pa-in':'pa-guru-in',
+	
+	*/
+	
+	/* Don't need to process the following locale alias
+	 * only listed here for futher comparison
+	 *
+	//sh is already aliased to sr-latn
+	'sh-cs':'sr-latn-rs',
+	'sh-yu':'sr-latn-rs',
+	'sh-ba':'sr-latn-ba',//sh-ba and sr-latn-ba don't exist, but sr-latn exists
+	
+	//has the same parent
+	'sr-cyrl-cs':'sr-cyrl-rs',
+	'sr-cyrl-yu':'sr-cyrl-rs',
+	
+	'sr-cs':'sr-cyrl-cs',
+	'sr-me':'sr-cyrl-me',
+	'sr-rs':'sr-cyrl-rs',
+	'sr-yu':'sr-cyrl-rs',
+	'sr-ba':'sr-cyrl-ba',//sr-cyrl is null
+	'tg-tj':'tg-cyrl-tj',//tg-cyrl is null
+	'ug-cn':'ug-arab-cn',//ug-arab is null
+	'uz-uz':'uz-cyrl-uz',//uz-cyrl is null
+	'zh-cn':'zh-hans-cn',//zh-hans is null
+	'zh-sg':'zh-hans-sg',//zh-hans is null
+	*/
+};
+
+print('specialLocale.js...');
+
+var srcLocaleList = [];//source locale file paths
+for(x in SPECIAL_LOCALES_MAP){
+	if(allLocalesStr == '${locales}' //no $locales parameter,all locales required
+	   || (allLocalesStr && 0 <= allLocalesStr.indexOf(x))){
+		//only if this locale is required
+		srcLocaleList.push(dir + '/' + x);
+	}
+}
+
+/*
+ * Get and compare the flattened bundles(using dojo.i18n) of each source locale and its alias
+ * Copy those bundles that alias has but source locale doesn't to source locale,
+ * and also update new items in source locale bundle
+ */
+var logStr = "";
+for(var i= 0; i < srcLocaleList.length; i++){
+	var srcLocalePath = srcLocaleList[i];//source locale path
+	var srcPathSegments = srcLocalePath.split("/");
+	var srcLocale = srcPathSegments[srcPathSegments.length - 1];
+	var aliasLocale = SPECIAL_LOCALES_MAP[srcLocale];
+	
+	//iterate each bundle
+	for(var len = 0; len < BUNDLE_MAP.length; len++){
+		try{
+			//declare bundles
+			dojo.i18n._requireLocalization('dojo.cldr', BUNDLE_MAP[len], srcLocale);
+			dojo.i18n._requireLocalization('dojo.cldr', BUNDLE_MAP[len], aliasLocale);
+						
+			//get bundles
+			var srcBundle = dojo.i18n.getLocalization('dojo.cldr', BUNDLE_MAP[len], srcLocale);
+			var aliasBundle = dojo.i18n.getLocalization('dojo.cldr', BUNDLE_MAP[len], aliasLocale);
+		}catch(e){print(e);/*it's ok if no bundle found*/}
+		
+		if(!aliasBundle && !srcBundle){ 
+			break;			
+		}else if(!aliasBundle && srcBundle){
+			//should be an error case
+			//logStr += 'specialLocale.js error: source locale has more bundles than alias locale\n';
+			break;
+		}else if(aliasBundle && !srcBundle){
+			//add the new bundle to source locale
+			validateDir(srcLocalePath);
+			fileUtil.saveUtf8File(srcLocalePath + '/' + BUNDLE_MAP[len] + '.js', NLS_JSON_HEAD[len] + '(' + dojo.toJson(aliasBundle, true) + ')');
+			//logStr += "specialLocale.js : copied " + BUNDLE_MAP[len] + '.js to ' + srcLocalePath + '\n';
+		}else if(aliasBundle && srcBundle){
+			var isUpdated = false;
+			//get native bundle whose content is not flattened
+			try{
+				var nativeSrcBundle = getNativeBundle(srcLocalePath + '/' + BUNDLE_MAP[len] + '.js');
+			}catch(e){
+				//if no nativeSrcBundle
+				nativeSrcBundle = {};
+			}
+
+			for(p in aliasBundle){
+				if(!isLocaleAliasSrc(p, aliasBundle) // p is not the source of a 'locale' alias mapping 
+				   && (!srcBundle[p] || !compare(srcBundle[p], aliasBundle[p]))){
+				   //inherit 
+				   nativeSrcBundle[p] = aliasBundle[p];
+				   //logStr += "copied " + p + "=" + aliasBundle[p] + "\n";
+				   isUpdated = true;
+				}
+			}
+			
+			if(isUpdated){
+				validateDir(srcLocalePath);
+				fileUtil.saveUtf8File(srcLocalePath + '/' + BUNDLE_MAP[len] + '.js', NLS_JSON_HEAD[len] + '(' + dojo.toJson(nativeSrcBundle, true) + ')');
+				//logStr += 'specialLocale.js : updated ' + BUNDLE_MAP[len] + '.js in ' + srcLocalePath + '\n';				
+			}
+		}
+	}
+}
+
+//fileUtil.saveUtf8File(logDir + '/specialLocale.log',logStr+'\n');
+
+function validateDir(/*String*/dirPath){
+	//summary:make sure the dir exists
+	var dir = new java.io.File(dirPath);
+	if(!dir.exists()){
+		dir.mkdir();
+	}	
+}
\ No newline at end of file
diff --git a/util/buildscripts/cldr/util.xsl b/util/buildscripts/cldr/util.xsl
new file mode 100644
index 0000000..6e7c65b
--- /dev/null
+++ b/util/buildscripts/cldr/util.xsl
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:saxon="http://saxon.sf.net/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" extension-element-prefixes="saxon" version="2.0">
+
+    <xsl:variable name="first" select="true()" saxon:assignable="yes"/>
+    <xsl:variable name="basedirsansslash" saxon:assignable="yes"/>
+
+    <xsl:param name="basedir"></xsl:param>
+
+    <xsl:template name="insert_comma">
+	    <xsl:choose>
+		    <xsl:when test="$first">
+			    <saxon:assign name="first" select="false()"/>
+	        </xsl:when>
+            <xsl:otherwise>
+			    <xsl:text>,</xsl:text>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <!-- Sub output routine-->
+    <xsl:variable name="vLowercaseChars_CONST" select="'abcdefghijklmnopqrstuvwxyz'"/> 
+    <xsl:variable name="vUppercaseChars_CONST" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
+    <xsl:template name="camel_case">
+        <xsl:param name="name"></xsl:param>
+        <xsl:variable name="words" select="tokenize($name, '-')"></xsl:variable>
+        <xsl:for-each select="$words">
+            <xsl:choose>
+                <xsl:when test="position()=1">
+                    <xsl:value-of select="."/>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:value-of select="translate(substring(., 1, 1), $vLowercaseChars_CONST, $vUppercaseChars_CONST)"/><xsl:value-of select="substring(., 2)"/>
+                </xsl:otherwise>
+            </xsl:choose>
+        </xsl:for-each>
+    </xsl:template>
+
+    <!--xsl:template name="invoke_template_by_name">
+        <xsl:param name="templateName"></xsl:param>
+        <xsl:param name="name"></xsl:param> 
+        <xsl:param name="width"></xsl:param>
+    </xsl:template-->
+
+    <!-- recursive process for alias -->
+    <xsl:template name="alias_template">
+        <xsl:param name="templateToCall"></xsl:param>
+        <xsl:param name="source"></xsl:param>
+        <xsl:param name="xpath"></xsl:param>
+        <xsl:param name="name"></xsl:param>
+        <xsl:param name="width"></xsl:param>
+        <xsl:param name="ctx"></xsl:param>
+        <xsl:choose>            
+            <xsl:when test="compare($source,'locale')=0">
+                <!-- source="locale" -->
+                <xsl:for-each select="saxon:evaluate(concat('../',$xpath))">   
+                    <xsl:call-template name="invoke_template_by_name">
+                        <xsl:with-param name="templateName" select="$templateToCall"></xsl:with-param>
+                        <xsl:with-param name="name" select="$name"></xsl:with-param>
+                        <xsl:with-param name="width" select="$width"></xsl:with-param>
+                        <xsl:with-param name="ctx" select="$ctx"></xsl:with-param>
+                        <xsl:with-param name="fromLocaleAlias" select="true()"></xsl:with-param>
+                    </xsl:call-template>
+                </xsl:for-each>
+            </xsl:when>
+            <xsl:otherwise>
+                <!-- source is an external xml file -->
+                <xsl:if test="string-length($xpath)>0">
+                    <xsl:choose>
+                        <xsl:when test="starts-with($basedir, '/')">
+                            <saxon:assign name="basedirsansslash" select="substring($basedir, 2)"/>
+                        </xsl:when>
+                        <xsl:otherwise>
+                            <saxon:assign name="basedirsansslash" select="$basedir"/>
+                        </xsl:otherwise>
+                    </xsl:choose>
+	                <xsl:for-each select="doc(concat('file:///',concat($basedirsansslash,concat($source,'.xml'))))">
+                        <xsl:for-each select="saxon:evaluate($xpath)">
+                            <xsl:call-template name="invoke_template_by_name">
+                                <xsl:with-param name="templateName" select="$templateToCall"></xsl:with-param>
+                                <xsl:with-param name="name" select="$name"></xsl:with-param>
+                                <xsl:with-param name="width" select="$width"></xsl:with-param>
+                                <xsl:with-param name="ctx" select="$ctx"></xsl:with-param>
+                                <xsl:with-param name="fromLocaleAlias" select="false()"></xsl:with-param>
+                            </xsl:call-template>
+                        </xsl:for-each>
+                    </xsl:for-each>
+                </xsl:if>            
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>   
+</xsl:stylesheet>
diff --git a/util/buildscripts/clean_release.sh b/util/buildscripts/clean_release.sh
new file mode 100755
index 0000000..5430c2c
--- /dev/null
+++ b/util/buildscripts/clean_release.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+#
+#	After the build completes, you can run this script to remove all unnecessary cruft.
+#
+#   WARNING: There are a lot of 'rm -f' commands in here, mostly checked, but know:
+#	Use at your own risk! 
+#
+#	NOTE: This is a fairly difinitive example of what is not needed (except in testing) ...
+
+releaseDir=$1;
+if [ "$releaseDir" = "" ]; then
+	releaseDir = ../../release
+fi
+
+buildName=$2;
+if [ "$buildName" = "" ]; then
+	buildName = dojo
+fi
+
+rm_dojo_files ()
+{
+	for d in "$@"
+	do
+		if [ -e "$buildName/$d" ]; then
+			# echo "Removing: $d";
+			rm -rf "$buildName/$d"
+		fi
+	done
+}
+
+# FIXME: refs #6616 - could be able to set a global copyright file and null out build_release.txt
+#mv build_notice.txt _build_notice.txt
+#touch build_notice.txt
+
+if [ -d $releaseDir ]; then
+
+	cd $releaseDir
+
+	# remove dojox tests and demos - they all follow this convention
+	for i in $buildName/dojox/* 
+	do
+	  if [ -d $i ]; then
+	    rm -rf $i/tests/
+	    rm -rf $i/demos/ 
+	  fi
+	done
+	
+	# removed dijit tests
+	rm_dojo_files "dijit/tests" "dijit/demos" "dijit/bench" "dojo/tests" "dojo/tests.js" "util"
+
+	# cleanup dijit/themes/ selectively
+	if [ -d $buildName/dijit/themes ]; then
+
+		# noir isn't worth including yet		
+		if [ -d $buildName/dijit/themes/noir ]; then
+			rm -rf $buildName/dijit/themes/noir/
+		fi
+		
+		# so the themes are there, lets assume that, piggyback on noir: FIXME later
+		find ./$buildName/dijit/themes/ -name *.html -exec rm '{}' ';'
+
+		# remove themeTester from minified build. 
+		rm -f $buildName/dijit/themes/templateThemeTest.html
+		rm -f $buildName/dijit/themes/themeTester*.html
+		rm -rf $buildName/dijit/themes/themeTesterImages/	
+
+	fi
+
+	# remove uncompressed .js files (leave for official release)
+	# find . -name *.uncompressed.js -exec rm '{}' ';'
+
+	# WARNING: templates have been inlined into the .js -- if you are using dynamic templates,
+	# or other build trickery, these lines might not work!
+	rm_dojo_files "dijit/templates" "dijit/form/templates" "dijit/layout/templates"
+
+	# NOTE: we're not doing this in DojoX because the resources/ folder (to me) is deemed
+	# ambigious, and should be treated on a per-project basis
+
+	# NOTE: if you aren't using anything in DojoX, uncomment this line:
+	# rm -rf dojo/dojox/
+	# OR get creative and only populate dojox/ folder with the projects you need, and leave alone.
+	# .. assume you didn't, and clean up all the README's (leaving LICENSE, mind you)
+	# find ./$buildName/dojox/ -name README -exec rm '{}' ';'
+	
+	# WARNING: if you care about _base existing (and not _always_ just dojo.js providing it) then comment this line:
+	# rm_dojo_files "dojo/_base" "dojo/_base.js"
+
+	# NOTE: we're not doing the above to dijit/_base/ because I secretly use dijit/_base functions
+	# when only using dojo.js (place.js and sniff.js in particular), and mini would break stuff ...
+
+	# last but not least
+	# rm_dojo_files "dojo/build.txt"
+	
+	cd ../util/buildscripts/
+
+fi
+
+# cleanup from above, refs #6616
+#mv _build_notice.txt build_notice.txt
diff --git a/util/buildscripts/copyright.txt b/util/buildscripts/copyright.txt
new file mode 100644
index 0000000..c9d4628
--- /dev/null
+++ b/util/buildscripts/copyright.txt
@@ -0,0 +1,6 @@
+/*
+	Copyright (c) 2004-2010, 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
+*/
+
diff --git a/util/buildscripts/jslib/buildUtil.js b/util/buildscripts/jslib/buildUtil.js
new file mode 100644
index 0000000..0b457d2
--- /dev/null
+++ b/util/buildscripts/jslib/buildUtil.js
@@ -0,0 +1,2031 @@
+var buildUtil = {};
+
+//Default build options.
+buildUtil.DojoBuildOptions = {
+	"profile": {
+		defaultValue: "base",
+		helpText: "The name of the profile to use for the build. It must be the first part of "
+			+ "the profile file name in the profiles/ directory. For instance, to use base.profile.js, "
+			+ "specify profile=base."
+	},
+	"profileFile": {
+		defaultValue: "",
+		helpText: "A file path to the the profile file. Use this if your profile is outside of the profiles "
+			+ "directory. Do not specify the \"profile\" build option if you use \"profileFile\"."
+	},
+	"action": {
+		defaultValue: "help",
+		helpText: "The build action(s) to run. Can be a comma-separated list, like action=clean,release. "
+			+ "The possible build actions are: clean, release."
+	},
+	"version": {
+		defaultValue: "0.0.0.dev",
+		helpText: "The build will be stamped with this version string."
+	},
+	"localeList": {
+		defaultValue: "ar,ca,cs,da,de-de,el,en-gb,en-us,es-es,fi-fi,fr-fr,he-il,hu,it-it,ja-jp,ko-kr,nl-nl,nb,pl,pt-br,pt-pt,ru,sk,sl,sv,th,tr,zh-tw,zh-cn",
+		helpText: "The set of locales to use when flattening i18n bundles."
+	},
+	
+	"releaseName": {
+		defaultValue: "dojo",
+		helpText: "The name of the release. A directory inside 'releaseDir' will be created with this name."
+	},
+	"releaseDir": {
+		defaultValue: "../../release/",
+		helpText: "The top level release directory where builds end up. The 'releaseName' directories will "
+			+ " be placed inside this directory."
+	},
+	"loader": {
+		defaultValue: "default",
+		helpText: "The type of dojo loader to use. \"default\" or \"xdomain\" are acceptable values."		
+	},
+	"internStrings": {
+		defaultValue: true,
+		helpText: "Turn on or off widget template file interning."
+	},
+	"optimize": {
+		defaultValue: "",
+		helpText: "Specifies how to optimize module files. If \"comments\" is specified, "
+			+ "then code comments are stripped. If \"shrinksafe\" is specified, then "
+			+ "Dojo Shrinksafe will be used on the files, and line returns will be removed. "
+			+ "If \"shrinksafe.keepLines\" is specified, then Dojo Shrinksafe will be used "
+			+ "on the files, and line returns will be preserved.  See also \"stripConsole\". "
+			+ "Google Closure's compiler can be used by specifying \"closure\" as the value. "
+			+ "It does not use the stripConsole build option, and it REQUIRES Java 6 to run, and it may make "
+			+ "some complaints about the code and print out 'error's, but if the build completes, "
+			+ "then the code should work. Do not taunt happy Closure compiler. To use Closure compiler, "
+			+ "download it from here:\n"
+			+ "http://code.google.com/p/closure-compiler/downloads/list\n"
+			+ "And place the compiler.jar file somewhere you can easily reference. Then use the following "
+			+ "to execute the build (remember Java 6):\n"
+			+ "java -classpath ../shrinksafe/js.jar:../closurecompiler/compiler.jar org.mozilla.javascript.tools.shell.Main build.js\n"
+			+ "and place your build arguments on the same line after that text. Change the ../closurecompiler "
+			+ "path to the path where you keep Closure's compiler.jar." 
+	},
+	"layerOptimize": {
+		defaultValue: "shrinksafe",
+		helpText: "Specifies how to optimize the layer files. If \"comments\" is specified, "
+			+ "then code comments are stripped. If \"shrinksafe\" is specified, then "
+			+ "Dojo Shrinksafe will be used on the files, and line returns will be removed. "
+			+ "If \"shrinksafe.keepLines\" is specified, then Dojo Shrinksafe will be used "
+			+ "on the layer files, and line returns will be preserved. "
+			+ "Google Closure's compiler can be used by specifying \"closure\" as the value. "
+			+ "It does not use the stripConsole build option, and it REQUIRES Java 6 to run, and it may make "
+			+ "some complaints about the code and print out 'error's, but if the build completes, "
+			+ "then the code should work. Do not taunt happy Closure compiler. To use Closure compiler, "
+			+ "download it from here:\n"
+			+ "http://code.google.com/p/closure-compiler/downloads/list\n"
+			+ "And place the compiler.jar file somewhere you can easily reference. Then use the following "
+			+ "to execute the build (remember Java 6):\n"
+			+ "java -classpath ../shrinksafe/js.jar:../closurecompiler/compiler.jar org.mozilla.javascript.tools.shell.Main build.js\n"
+			+ "and place your build arguments on the same line after that text. Change the ../closurecompiler "
+			+ "path to the path where you keep Closure's compiler.jar." 
+	},
+	"cssOptimize": {
+		defaultValue: "",
+		helpText: "Specifies how to optimize CSS files. If \"comments\" is specified, "
+			+ "then code comments and line returns are stripped, and files referenced via @import "
+			+ "are inlined. If \"comments.keepLines\" "	
+			+ "is specified, then code comments are stripped and @import calls are inlined, but line returns are preserved."
+	},
+
+	"cssImportIgnore": {
+		defaultValue: "",
+		helpText: "If using cssOptimize=\"comments\", then you can force the @import inlining step "
+			+ "to ignore a set of files by using this option. The value of this option should be a comma "	
+			+ "separated list of CSS files names to ignore. The file names should match whatever strings "
+			+ "are used for the @import calls."
+	},
+	
+	"stripConsole": {
+		defaultValue: undefined,
+		helpText: "Strips console method calls from JS source. Applied to layers and individual modules "
+			+ "resource files. Valid values are \"none\" (leaves all console calls alone, same as "
+			+ "default \"\"), \"normal\" (strips all but console.warn and console.error calls), "
+			+ "\"warn\" (strips all but console.error calls), \"all\" (strips all console calls).  "
+			+ "NOTE: only has effect if optimize includes use of shrinksafe."
+	},
+
+	"copyTests": {
+		defaultValue: false,
+		helpText: "Turn on or off copying of test files."
+	},
+	"mini": {
+		defaultValue: true,
+		helpText: "Removes files like tests, demos dijit/bench, unfinished themes, and interned "
+			+ "Dijit templates from the build. Overrides the value set for copyTests."
+	},
+	"log": {
+		defaultValue: logger.TRACE,
+		helpText: "Sets the logging verbosity. See jslib/logger.js for possible integer values."
+	},
+	"xdDojoPath": {
+		defaultValue: "",
+		helpText: "If the loader=xdomain build option is used, then the value of this option "
+			+ "will be used to call dojo.registerModulePath() for dojo, dijit and dojox. "
+			+ "The xdDojoPath should be the directory that contains the dojo, dijit and dojox "
+			+ "directories, and it should NOT end in a slash. For instance: 'http://some.domain.com/path/to/dojo090'."
+	},
+	"symbol": {
+		defaultValue: "",
+		helpText: "Inserts function symbols as global references so that anonymous "
+			+ "functions will show up in all debuggers (esp. IE which does not attempt "
+			+ "to infer function names from the context of their definition). Valid values "
+			+ "are \"long\" and \"short\". If \"short\" is used, then a symboltables.txt file "
+			+ "will be generated in each module prefix's release directory which maps the "
+			+ "short symbol names to more descriptive names."
+	},
+	"scopeDjConfig": {
+		defaultValue: "",
+		helpText: "Burn in a djConfig object into the built dojo.js file. Useful if you are making your own scoped dojo and you want a "
+			+ "djConfig object local to your version that will not be affected by any globally declared djConfig object in the page. "
+			+ "Value must be a string that will look like a javascript object literal once it is placed in the built source. "
+			+ "use Dojo as part of a JS library, but want to make a self-contained library with no external dojo/dijit/dojox. Example "
+			+ "(note that the backslashes below are required to avoid shell escaping if you type this on the command line):\n"
+			+ "scopeDjConfig={isDebug:true,scopeMap:[[\\\"dojo\\\",\\\"mydojo\\\"],[\\\"dijit\\\",\\\"mydijit\\\"],[\\\"dojox\\\",\\\"mydojox\\\"]]}"
+	},
+	"scopeMap": {
+		defaultValue: "",
+		helpText: "Change the default dojo, dijit and dojox scope names to something else. Useful if you want to "
+			+ "use Dojo as part of a JS library, but want to make a self-contained library with no external dojo/dijit/dojox "
+			+ "references. Format is a string that contains no spaces, and is similar to the djConfig.scopeMap value (note that the "
+			+ "backslashes below are required to avoid shell escaping):\n"
+			+ "scopeMap=[[\\\"dojo\\\",\\\"mydojo\\\"],[\\\"dijit\\\",\\\"mydijit\\\"],[\\\"dojox\\\",\\\"mydojox\\\"]]"
+	},
+	"xdScopeArgs": {
+		defaultValue: "",
+		helpText: "If the loader=xdomain build option is used, then the value of this option "
+			+ "will be used as the arguments to the function that defines the modules in the .xd.js files. "
+			+ "This allows for more than one version of the same module to be in a page. See documentation on "
+			+ "djConfig.scopeMap for more information."
+	},
+	"xdDojoScopeName": {
+		defaultValue: "dojo",
+		helpText: "If the loader=xdomain build option is used, then the value of this option "
+			+ "will be used instead of 'dojo' for the 'dojo._xdResourceLoaded()' calls that are done in the .xd.js files. "
+			+ "This allows for dojo to be under a different scope name but still allow xdomain loading with that scope name."
+	},
+	"expandProvide": {
+		defaultValue: false,
+		helpText: "Expands dojo.provide calls with faster calls at the expense of a larger file size. Only use the option "
+			+ "if your profiling reveals that dojo.provide calls are taking a noticeable amount of time. Even then, it could "
+			+ "cause errors in the built files. If you find an error after building, turn this option off. It replaces "
+			+ "dojo.provide(\"foo.bar\") statements with the shortest valid programmatic equivalent:\n"
+			+ "if(typeof foo==\"undefined\"){foo={};};foo.bar=foo.bar||{};\nIgnored for xdomain builds."
+	},
+	"buildLayers": {
+		defaultValue: "",
+		helpText: "A comma-separated list of layer names to build. Using this option means that only those layers will be built. "
+			+ "This helps if you are doing quick development and test cycles with layers. If you have problems using this option, "
+			+ "try removing it and doing a full build with action=clean,release. This build option assumes you have done at least one full build first."
+	},
+	"query": {
+		defaultValue: "default",
+		helpText: "Select a DOM query engine. Default value is the normal dojo.query engine. Using query=sizzle will use the Sizzle engine."
+			+ "Normal Dojo tests are not run routinely with the Sizzle engine. See dojo/_base/sizzle.js for the version of Sizzle."
+	},
+	"removeDefaultNameSpaces": {
+		defaultValue: false,
+		helpText: "Removes the default 'com', 'org' and 'net' namespaces that are present in Rhino. This is hazardous to use if "
+			+ "the build system is used as part of a Rhino-based server-side solution, so use with caution. Weird build errors "
+			+ "might occur. Only use if your own code includes things in a com, org or net namespace."
+	},
+	"addGuards": {
+		defaultValue: true,
+		helpText: "Set to false to remove the code guards that protect modules from re-definition. In general you SHOULD NOT "
+			+ "set this value to false. Only do it if you want an even smaller Dojo Base build and you know the implications "
+			+ "of re-defining modules. It is bad. Do not do it."
+	}
+};
+
+buildUtil.makeBuildOptions = function(/*Array*/scriptArgs){
+	//summary: constructs the build options by combining the scriptArgs with
+	//default build options and anything specified in a profile file.
+
+	var kwArgs = {}, param;
+
+	//Parse the command line arguments
+	kwArgs = buildUtil.convertArrayToObject(scriptArgs);
+	if(!kwArgs["profileFile"] && kwArgs["profile"]){
+		kwArgs.profileFile = "profiles/" + kwArgs.profile + ".profile.js";
+	}
+
+	//Load dependencies object from profile file, if there is one.
+	var dependencies = {};
+	if(kwArgs["profileFile"]){
+		var profileProperties = buildUtil.evalProfile(kwArgs.profileFile);
+		if(profileProperties){
+			kwArgs.profileProperties = profileProperties;
+			dependencies = kwArgs.profileProperties.dependencies;
+			
+			//Allow setting build options from on the profile's dependencies object.
+			//Do not override existing values from the command line though.
+			for(param in dependencies){
+				if(!(param in kwArgs) && param != "layers" && param != "prefixes"){
+					kwArgs[param] = dependencies[param];
+				}
+			}
+		}
+	}
+
+	//Set up default options
+	for(param in buildUtil.DojoBuildOptions){
+		//Only use default if there is no value so far.
+		if(typeof kwArgs[param] == "undefined"){
+			kwArgs[param] = buildUtil.DojoBuildOptions[param].defaultValue;
+		}else if(kwArgs[param] === "false"){
+			//Make sure "false" strings get translated to proper false value.
+			kwArgs[param] = false;
+		}
+	}
+
+	//Make sure releaseDir uses / since rest of build assumes / paths.
+	kwArgs.releaseDir = kwArgs.releaseDir.replace(/\\/g, "/");
+
+	//Set up some compound values
+	if(kwArgs["releaseName"]){
+		///Make sure releaseDir ends in a / so releaseName concat works.
+		if(!kwArgs.releaseDir.match(/\/$/)){
+			kwArgs.releaseDir += "/";
+		}
+		kwArgs.releaseDir += kwArgs["releaseName"];
+	}else{
+		//No releaseName, so strip off trailing slash
+		kwArgs.releaseDir = kwArgs.releaseDir.replace(/\/$/, "");
+	}
+
+	kwArgs.action = kwArgs.action.split(",");
+	kwArgs.localeList = kwArgs.localeList.split(",");
+
+	//Attach the final loader type to the dependencies
+	dependencies.loader = kwArgs.loader;
+
+	//Fix args for bugs
+	if(kwArgs.expandProvide && kwArgs.loader == "xdomain"){
+		logger.info("NOTE: expandProvide not compatible with xdomain builds. Ignoring expandProvide option.");
+		kwArgs.expandProvide = false;
+	}
+	
+	//Notify on incompatible options.
+	if(kwArgs.optimize && kwArgs.optimize != "shrinksafe" && kwArgs.stripConsole){
+		logger.info("NOTE: stripConsole is only supported for an optimize=shrinksafe value.");
+	}
+	if(kwArgs.layerOptimize && kwArgs.layerOptimize != "shrinksafe" && kwArgs.stripConsole){
+		logger.info("layerOPtimize: [" + kwArgs.layerOptimize + "]");
+		logger.info("NOTE: stripConsole is only supported for an layerOptimize=shrinksafe value.");
+	}
+
+	//Validate some values.
+	if(typeof kwArgs.scopeDjConfig != "string") {
+		throw "Due to deficiencies in the build system, scopeDjConfig needs to be a string.";
+	}
+
+
+	//Do some hackery for closure compiler.
+	if(kwArgs.optimize.indexOf("closure") == 0 || kwArgs.layerOptimize.indexOf("closure") == 0){
+		//directly call JSSourceFile.fromCode will actually invoke SourceFile.fromCode,
+		//which will lead to error: "Cannot convert com.google.javascript.jscomp.SourceFile$Preloaded at 26afa68a to com.google.javascript.jscomp.JSSourceFile"
+		//don't know whether it's a bug in closure or rhino - liucougar
+		var JSSourceFilefromCode=java.lang.Class.forName('com.google.javascript.jscomp.JSSourceFile').getMethod('fromCode',[java.lang.String,java.lang.String]);
+		buildUtil.closurefromCode = function(filename,content){
+			return JSSourceFilefromCode.invoke(null,[filename,content])
+		}
+	}
+
+	return kwArgs;
+}
+
+//Even though these are i18n-specific, they are not in i18nUtil.js since one is referenced
+//in this file. Want to avoid circular dependency loading issues.
+buildUtil.masterRequireLocalizationRegExpString = "dojo.(requireLocalization)\\(([\\w\\W]*?)\\)";
+buildUtil.globalRequireLocalizationRegExp = new RegExp(buildUtil.masterRequireLocalizationRegExpString, "mg");
+buildUtil.requireLocalizationRegExp = new RegExp(buildUtil.masterRequireLocalizationRegExpString);
+
+//FIXME: This should take the build kwArgs now instead.
+buildUtil.getDojoLoader = function(/*Object?*/dependencies){
+	//summary: gets the type of Dojo loader for the build. For example default or
+	//xdomain loading. Override for web builds.
+	return (dependencies && dependencies["loader"] ? dependencies["loader"] : java.lang.System.getProperty("DOJO_LOADER"));
+}
+
+buildUtil.includeLoaderFiles = function(/*String*/dojoLoader, /*String or Array*/hostenvType, /*String*/buildscriptsPath){
+	//summary: adds the loader files to the file list for a build file.
+	dojo._loadedUrls.push(buildscriptsPath + "jslib/dojoGuardStart.jsfrag");
+	dojo._loadedUrls.push(buildscriptsPath + "../../dojo/_base/_loader/bootstrap.js");
+	
+	if(dojoLoader == "default"){
+		dojo._loadedUrls.push(buildscriptsPath + "../../dojo/_base/_loader/loader.js");
+	}else if(dojoLoader == "xdomain"){
+		dojo._loadedUrls.push(buildscriptsPath + "../../dojo/_base/_loader/loader.js");
+		dojo._loadedUrls.push(buildscriptsPath + "../../dojo/_base/_loader/loader_xd.js");
+	}
+
+	if(hostenvType.constructor == Array){
+		for(var x=0; x<hostenvType.length; x++){
+			dojo._loadedUrls.push(buildscriptsPath + "../../dojo/_base/_loader/hostenv_"+hostenvType[x]+".js");
+		}
+		hostenvType = hostenvType.pop();
+	}else{
+		dojo._loadedUrls.push(buildscriptsPath + "../../dojo/_base/_loader/hostenv_"+hostenvType+".js");
+	}
+}
+
+buildUtil.getDependencyList = function(/*Object*/dependencies, /*String or Array*/hostenvType, /*Object?*/kwArgs, /*String?*/buildscriptsPath){
+	//summary: Main function that traces the files that are needed for a give list of dependencies.
+
+	if(!dependencies){
+		dependencies = {}
+	}
+
+	buildscriptsPath = buildscriptsPath || "./";
+	
+	var dojoLoader = buildUtil.getDojoLoader(dependencies);
+	if(!dojoLoader || dojoLoader=="null" || dojoLoader==""){
+		dojoLoader = "default";
+	}
+
+
+	//Now build the URI list, starting with the main dojo.js file
+	if(!dependencies["layers"]){
+		dependencies.layers = [];
+	}
+
+	//Set up the dojo.js layer. Add _base if the profile already
+	//defines a dojo.js layer. If the profile defines a dojo.js
+	//layer it MUST be the first layer.
+	if(dependencies.layers[0] && dependencies.layers[0].name == "dojo.js"){
+		if(!dependencies.layers[0].customBase){
+			dependencies.layers[0].dependencies.unshift("dojo._base");
+		}
+	}else{
+		dependencies.layers.unshift({
+			name: "dojo.js",
+			dependencies: [
+				"dojo._base"
+			]
+		});
+	}
+
+	currentProvideList = [];
+	var result = [];
+	var layers = dependencies["layers"];
+	var layerCount = layers.length;
+	
+	//Process dojo layer files 
+	if(layerCount){
+		//Set up a lookup table for the layer URIs based on layer file name.
+		var namedLayerUris = {};
+				
+		//If xd build, cycle over the layers twice. Second time through
+		//are the xd files.
+		var endCount = layerCount;
+		if(dojoLoader == "xdomain"){
+			endCount = endCount * 2;
+		}
+		
+		for(var i = 0; i < endCount; i++){
+			var j = i;
+			var isXd = false;
+			if(i >= layerCount){
+				//Dealing with the xd files.
+				if(i == layerCount){
+					//Reset the dependencies.
+					namedLayerUris = {};
+				}
+				j = i - layerCount;
+				isXd = true;
+			}
+			var layer = layers[j];
+			var layerName = layers[j].name;
+			if(isXd){
+				layerName = layerName.replace(/\.js$/, ".xd.js");
+			}
+
+			//Add dojo.i18n to dojo.xd.js. Too complicated to dynamically load it in that case.
+			if(isXd && layerName == "dojo.xd.js"){
+				layer.dependencies.splice(1, 0, "dojo.i18n");
+			}
+
+			djConfig = {
+				baseRelativePath: "../../dojo/"
+				// isDebug: true
+			};
+
+	
+			load(buildscriptsPath + "../../dojo/_base/_loader/bootstrap.js");
+			load(buildscriptsPath + "../../dojo/_base/_loader/loader.js");
+			load(buildscriptsPath + "../../dojo/_base/_loader/hostenv_rhino.js");
+			dojo.global = {};
+
+		
+			if(!hostenvType){
+				hostenvType = "browser";
+			}
+		
+			if(dependencies["prefixes"]){
+				var tmp = dependencies.prefixes;
+				for(var x=0; x<tmp.length; x++){
+					dojo.registerModulePath(tmp[x][0], tmp[x][1]);
+				}
+			}
+		
+			dojo._name = hostenvType;
+			if(hostenvType == "browser" || hostenvType == "ff_ext"){
+				//Make sure we setup the env so that dojo
+				//thinks we are running in a browser.
+				dojo.isBrowser = true;
+			}
+			
+			//Override dojo.provide to get a list of resource providers.
+			var currentProvideList = [];
+			dojo._provide = dojo.provide;
+			dojo.provide = function(resourceName){
+				currentProvideList.push(resourceName);
+				dojo._provide(resourceName);
+			}
+			
+			// over-write dojo.eval to prevent actual loading of subsequent files
+			dojo._oldEval = dojo["eval"];
+			dojo["eval"] = function(){ return true; }
+			var old_load = load;
+			load = function(uri){
+				try{
+					//Strip comments and apply conditional directives before tracing the dependencies.
+					var text = fileUtil.readFile(uri);
+					text = (kwArgs ? buildUtil.processConditionals(layerName, text, kwArgs) : text);
+					text = buildUtil.removeComments(text);
+
+					var requires = dojo._getRequiresAndProvides(text);
+					eval(requires.join(";"));
+					dojo._loadedUrls.push(uri);
+					dojo._loadedUrls[uri] = true;
+					var delayRequires = dojo._getDelayRequiresAndProvides(text);
+					
+					//Now do the requireIfs. Since they contain some code tests that could
+					//not be valid in the current scope (access variables that are not defined
+					//when running in Rhino, for instance), then do a try/catch around each
+					//one. If the expression fails, then it was not meant for this context.
+					for(var i = 0; i < delayRequires.length; i++){
+						try{
+							eval(delayRequires[i]);
+						}catch(e){
+							//logger.trace("A requireIf failed for text [" + delayRequires[i] + "], error: " + e);
+						}
+					}
+				}catch(e){
+					java.lang.System.err.println("error loading uri: " + uri + ", exception: " + e);
+					quit(-1);
+				}
+				return true;
+			}
+
+			dojo._getRequiresAndProvides = function(contents){
+				// FIXME: should probably memoize this!
+				if(!contents){ return []; }
+			
+				// check to see if we need to load anything else first. Ugg.
+				var deps = [];
+				var tmp;
+				RegExp.lastIndex = 0;
+				var testExp = /dojo.(require|platformRequire|provide)\s*\([\w\W]*?\)/mg;
+				while((tmp = testExp.exec(contents)) != null){
+					deps.push(tmp[0]);
+				}
+				
+				//If there is a dojo.requireLocalization() call, make sure to add dojo.i18n
+				if(contents.match(/dojo\.requireLocalization\(.*?\)/)){
+					deps.push('dojo.require("dojo.i18n")');
+				}
+		
+				return deps;
+			}
+			
+			dojo._getDelayRequiresAndProvides = function(contents){
+				// FIXME: should probably memoize this!
+				if(!contents){ return []; }
+			
+				// check to see if we need to load anything else first. Ugg.
+				var deps = [];
+				var tmp;
+				RegExp.lastIndex = 0;
+				var testExp = /dojo.(requireAfterIf|requireIf)\([\w\W]*?\)/mg;
+				while((tmp = testExp.exec(contents)) != null){
+					deps.push(tmp[0]);
+				}
+				return deps;
+			}
+		
+			if(dependencies["dojoLoaded"]){
+				dependencies["dojoLoaded"]();
+			}
+	
+			//Add the loader files if this is a loader layer.
+			if(layerName == "dojo.js"){
+				buildUtil.includeLoaderFiles("default", hostenvType, buildscriptsPath);
+			}else if(layerName == "dojo.xd.js"){
+				buildUtil.includeLoaderFiles("xdomain", hostenvType, buildscriptsPath);
+			}
+		
+			//Set up list of module URIs that are already defined for this layer's
+			//layer dependencies. Always include the dojo.js layer uris. dojo.js could
+			//have more than _base, and in xdomain, it has dojo.i18n.
+			var layerUris = [];
+			if(layer.name != "dojo.js"){
+				layerUris = layerUris.concat(namedLayerUris["dojo.js"]);
+			}
+			
+			if(layer["layerDependencies"]){
+				for(j = 0; j < layer.layerDependencies.length; j++){
+					if(namedLayerUris[layer.layerDependencies[j]]){
+						layerUris = layerUris.concat(namedLayerUris[layer.layerDependencies[j]]);
+					}
+				}
+			}
+
+			//Get the final list of dependencies in this layer
+			var depList = buildUtil.determineUriList(layer.dependencies, layerUris, dependencies["filters"]); 
+
+			//If dojo.xd.js, need to put dojo.i18n before the code in dojo._base.browser that does the 
+			//auto dojo.require calls based on dojo.config.require array.
+			//This is a little bit hackish, but it allows dojo.i18n to use any Base methods
+			//in the future.
+			if(layerName == "dojo.xd.js"){
+				//Find the dojo.i18n line. Start at the end of depList because it is likely closer
+				//to the end than the beginning.
+				var i18nXdEntry = null;
+				for(var i18nIndex = depList.length - 1; i18nIndex >= 0; i18nIndex--){
+					if(depList[i18nIndex].match(/\/dojo\/i18n\.js$/)){
+						i18nXdEntry = depList.splice(i18nIndex, 1)[0];
+						break;
+					}
+				}
+				
+				//Only operate if we have an i18n entry. We may allow building without
+				//dojo.i18n as part of the xd file.
+				if(i18nXdEntry){
+					var foundBrowserJs = false;
+					for(i18nIndex = depList.length - 1; i18nIndex >= 0; i18nIndex--){
+						if(depList[i18nIndex].match(/dojo\/_base\/browser\.js$/)){
+							depList.splice(i18nIndex, 0, i18nXdEntry);
+							foundBrowserJs = true;
+							break;
+						}
+					}
+					//If did not find browser entry (maybe a customBase build),
+					//Just add the i18n entry to the end.
+					if(!foundBrowserJs){
+						depList.push(i18nXdEntry);
+					}
+				}
+			}
+			
+			//Add the final closure guard to the list.
+			if(layerName == "dojo.js" || layerName == "dojo.xd.js"){
+				depList.push(buildscriptsPath + "jslib/dojoGuardEnd.jsfrag");
+			}
+
+			//Store the layer URIs that are in this file as well as all files it depends on.
+			namedLayerUris[layer.name] = layerUris.concat(depList);
+		
+			//Add to the results object.
+			if(!layer["discard"]){
+				result.push({
+					layerName: layerName,
+					resourceName: layer.resourceName,
+					copyrightFile: layer.copyrightFile,
+					depList: depList,
+					provideList: currentProvideList
+				});
+			}
+
+			//Reset for another run through the loop.
+			currentProvideList = []; 
+
+			load = old_load; // restore the original load function
+			dojo["eval"] = dojo._oldEval; // restore the original dojo.eval function
+	
+			var djGlobal = dojo.global;
+			djGlobal['djConfig'] = undefined;
+	
+			delete dojo;
+		}
+	}
+
+	return result; //Object with properties: name (String), depList (Array) and provideList (Array)
+}
+
+buildUtil.removeComments = function(/*String*/contents){
+	//summary: strips JS comments from a string. Not bulletproof, but does a good enough job
+	//for stripping out stuff that is not related to mapping resource dependencies.
+
+	//If we get the contents of the file from Rhino, it might not be a JS
+	//string, but rather a Java string, which will cause the replace() method
+	//to bomb.
+	contents = contents ? new String(contents) : "";
+	//clobber all comments
+	return contents.replace( /(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg , "");
+}
+
+//Function to do the actual collection of file names to join.
+buildUtil.determineUriList = function(/*Array*/dependencies, /*Array*/layerUris, /*Object*/filters){
+	for(var x=0; x<dependencies.length; x++){
+		try{
+			var dep = dependencies[x];
+
+			//Don't process loader_xd.js since it has some regexps 
+			//and mentions of dojo.require/provide, which will cause 
+			//havoc in the dojo._loadModule() method.
+			if(dep.indexOf("loader_xd.js") == -1){
+				dojo._loadModule(dep, true);
+			}
+		}catch(e){
+			java.lang.System.err.println("Error loading module!" + e);
+			quit(-1);
+		}
+	}
+
+	var depList = [];
+	var seen = {};
+	uris: for(x=0; x<dojo._loadedUrls.length; x++){
+		var curi = dojo._loadedUrls[x];
+		if(!seen[curi]){
+			seen[curi] = true;
+			if(filters){
+				for(var i in filters){
+					if(curi.match(filters[i])){
+						continue uris;
+					}
+				}
+			}
+			
+			//If the uri is already accounted for in another
+			//layer, skip it.
+			if(layerUris){
+				for(i = 0; i < layerUris.length; i++){ 
+					if(curi == layerUris[i]){ 
+						continue uris; 
+					} 
+				} 
+			} 
+
+			//No filter or layerUri matches, so it is good to keep.
+			depList.push(curi);
+		}
+	}
+	
+	//Clear out the loadedUris for the next run. 
+	dojo._loadedUrls = []; 
+	return depList; 
+}
+
+
+buildUtil.evalProfile = function(/*String*/profileFile, /*Boolean*/fileIsProfileText){
+	var dependencies = {};
+	var hostenvType = null;
+	var profileText = fileIsProfileText ? profileFile : fileUtil.readFile(profileFile);
+
+	//Remove the call to getDependencyList.js because it is not supported anymore.
+	profileText = profileText.replace(/load\(("|')getDependencyList.js("|')\)/, "");
+	eval(profileText);
+	
+	//Build up the prefixes so the rest of the scripts
+	//do not have to guess where things are at.
+	if(!dependencies["prefixes"]){
+		dependencies.prefixes = [];
+	}
+	
+	//Find prefixes that are used.
+	var usedPrefixes = ["dojo"];
+	usedPrefixes._entries = { dojo: true };
+	
+	//Check normal dependencies.
+	buildUtil.addPrefixesFromDependencies(usedPrefixes, dependencies);
+
+	//Check layer dependencies
+	var layerDeps = dependencies.layers;
+	
+	if(layerDeps){
+		for(var i = 0; i < layerDeps.length; i++){
+			buildUtil.addPrefixesFromDependencies(usedPrefixes, layerDeps[i].dependencies);
+		}
+	}
+
+	//Now add to the real prefix array.
+	//If not already in the prefix array, assume the default
+	//location, as a sibling to dojo (and util).
+	for(i = 0; i < usedPrefixes.length; i++){
+		var hasPrefix = false;
+		for(var j = 0; j < dependencies.prefixes.length; j++){
+			if(dependencies.prefixes[j][0] == usedPrefixes[i]){
+				hasPrefix = true;
+				break;
+			}
+		}
+		if(!hasPrefix){
+			//Assumptions are that any prefixes that are not dojo
+			//are a sibling to dojo. Dojo path is special, it needs
+			//to be relative to util/buildscripts. The dojo path is
+			//prepended to other paths later.
+			var dirPrefix = "../";
+			if(usedPrefixes[i] == "dojo"){
+				dirPrefix = "../../";
+			}
+			dependencies.prefixes.push([usedPrefixes[i], dirPrefix + usedPrefixes[i]]);
+		}
+	}
+
+	return {
+		dependencies: dependencies,
+		hostenvType: hostenvType
+	};
+}
+
+buildUtil.getDojoPrefixPath = function(/*Array*/prefixes){
+	//summary: Gets the path to Dojo from the prefixes.
+	var result = null;
+	for(var i = 0; i < prefixes.length; i++){
+		if(prefixes[i][0] == "dojo"){
+			result = prefixes[i][1];
+			break;
+		}
+	}
+	return result;
+}
+
+buildUtil.addPrefixesFromDependencies = function(/*Array*/prefixStore, /*Array*/dependencies){
+	//summary: finds the top level prefixes in the build process that
+	//we need to track for the build process. 
+	for(var i = 0; i < dependencies.length; i++){
+		var topPrefix = dependencies[i].split(".")[0];
+		if(!prefixStore._entries[topPrefix]){
+			prefixStore.push(topPrefix);
+			prefixStore._entries[topPrefix] = true;
+		}
+	}
+}
+
+buildUtil.loadDependencyList = function(/*Object*/profile, /*Object?*/kwArgs, /*String?*/buildscriptsPath){
+	//summary: Traverses the dependencies in the profile object.
+	//profile:
+	//		The profile object that is a result of a buildUtil.evalProfile() call.
+	var depResult = buildUtil.getDependencyList(profile.dependencies, profile.hostenvType, kwArgs, buildscriptsPath);
+	depResult.dependencies = profile.dependencies;
+	
+	return depResult;
+}
+
+buildUtil.createLayerContents = function(
+	/*String*/layerName,
+	/*String*/resourceName,
+	/*Array*/depList,
+	/*Array*/provideList,
+	/*String*/version,
+	/*Object?*/kwArgs){
+	//summary: Creates the core contents for a build layer (including dojo.js).
+
+	//Concat the files together, and mark where we should insert all the
+	//provide statements.
+	var dojoContents = resourceName ? "dojo.provide(\"" + resourceName + "\");\r\n" : "";
+	for(var i = 0; i < depList.length; i++){
+		//Run the file contents through the include/exclude "preprocessor".
+		var depContents = fileUtil.readFile(depList[i]);
+		dojoContents += (kwArgs ? buildUtil.processConditionals(layerName, depContents, kwArgs) : depContents)
+			+ "\r\n";
+	}
+
+	//Find out if the layer has any dojo.require calls we should not strip out,
+	//via the layer.keepRequires array. If there is one, convert to an object
+	//for each key lookup.
+	var keepRequires = null;
+	var layers = kwArgs.profileProperties.dependencies.layers;
+	for(i = 0; i < layers.length; i++){
+		if(layerName == layers[i].name){
+			var keepArray = layers[i].keepRequires;
+			if(keepArray){
+				keepRequires = {};
+				for(var j = 0; j < keepArray.length; j++){
+					keepRequires[keepArray[j]] = true;
+				}
+			}
+			break;
+		}
+	}
+
+	//Construct a string of all the dojo.provide statements.
+	//This string will be used to construct the regexp that will be
+	//used to remove matching dojo.require statements.
+	//Sort the provide list alphabetically to make it easy to read.
+	//Order of provide statements do not matter.
+	provideList = provideList.sort(); 
+	var depRegExpString = "";
+	for(i = 0; i < provideList.length; i++){
+		//Skip keepRequire matches.
+		if(keepRequires && keepRequires[provideList[i]]){
+			continue;
+		}
+		if(depRegExpString){
+			depRegExpString += "|";
+		}
+		depRegExpString += '([\'"]' + provideList[i] + '[\'"])';
+	}
+
+	//If we have a string for a regexp, do the dojo.require() and requireIf() removal now.
+	if(depRegExpString){
+		//Make to escape regexp-sensitive characters
+		depRegExpString = buildUtil.regExpEscape(depRegExpString);
+		//Build the regexp
+		var depRegExp = new RegExp("dojo\\.(require|requireIf)\\(.*?(" + depRegExpString + ")\\)(;?)", "g");
+		dojoContents = dojoContents.replace(depRegExp, "");
+	}
+
+	if(kwArgs.expandProvide){
+		// replace dojo.provide("foo.bar.Baz") statements with the shortest valid
+		// programmatic equivalent:
+		//		foo = foo||{};
+		//		foo.bar = foo.bar||{};
+		//		foo.bar.Baz = foo.bar.Baz||{};
+		//		dojo._loadedModules["foo.bar.Baz"] = foo.bar.Baz = foo.bar.Baz||{};
+	
+		var seenProvides = {};
+		var provideRegExp = /dojo.provide\(([\w\W]*?)\)/mg;
+		dojoContents = dojoContents.replace(provideRegExp, function(s, p1){
+			if(p1){
+				var ret = "";
+				p1 = p1.slice(1, -1); // trim the " or ' chars
+				var splits = p1.split(".");
+				splits.forEach(function(i, idx, a){
+					var simpleShortName = a.slice(0, idx+1).join(".");
+					var shortName = a[0];
+					for(var x=1; x<(idx+1); x++){
+						if(a[x].indexOf("-") >= 0){
+							shortName += '["'+a[x]+'"]';
+						}else{
+							shortName += "."+a[x];
+						}
+					}
+					// make sure that if, in a given module, we've already seen a
+					// parent that we don't re-generate its stub detection
+					if(!seenProvides[simpleShortName]){
+						seenProvides[simpleShortName] = true;
+						if(idx == 0){
+							ret += 'if(typeof ' + shortName + '=="undefined"){' + shortName + '={};};';
+						}else{
+							ret += shortName+'='+shortName+'||{};';
+						}
+					}
+					// at the last one?
+					if(idx == (a.length-1)){
+						// register in _loadedModules:
+						ret += 'dojo._loadedModules["'+simpleShortName+'"] = '+shortName+';';
+					}
+				});
+				return ret;
+			}else{
+				return s;
+			}
+		});
+	}
+
+	//Set version number.
+	dojoContents = buildUtil.changeVersion(version, dojoContents);
+
+	return dojoContents; //String
+}
+
+buildUtil.changeVersion = function(/*String*/version, /*String*/fileContents){
+	//summary: Changes the version number for dojo. Input should be the fileContents
+	//of a file that contains the version number.
+	
+	//Set version number.
+	//First, break apart the version string.
+	var verSegments = version.match(/^(\d*)\.?(\d*)\.?(\d*)\.?(.*)$/); 
+	var majorValue = verSegments[1] || 0; 
+	var minorValue = verSegments[2] || 0; 
+	var patchValue = verSegments[3] || 0; 
+	var flagValue  = verSegments[4] || ""; 
+
+	//Do the final version replacement.
+	fileContents = fileContents.replace(
+		/major:\s*\d*,\s*minor:\s*\d*,\s*patch:\s*\d*,\s*flag:\s*".*?"\s*,/g,
+		"major: " + majorValue + ", minor: " + minorValue + ", patch: " + patchValue + ", flag: \"" + flagValue + "\","
+	);
+
+	return fileContents; //String
+}
+
+buildUtil.makeDojoJs = function(/*Object*/dependencyResult, /*String*/version, /*Object?*/kwArgs){
+	//summary: Makes the uncompressed contents for dojo.js using the object
+	//returned from buildUtil.getDependencyList()
+
+	var lineSeparator = fileUtil.getLineSeparator();
+
+	//Cycle through the layers to create the content for each layer.
+	for(var i = 0; i< dependencyResult.length; i++){
+		var layerResult = dependencyResult[i];
+		layerResult.contents = buildUtil.createLayerContents(layerResult.layerName, layerResult.resourceName, layerResult.depList, layerResult.provideList, version, kwArgs);
+	}
+
+	//Object with properties:
+	//depList: Array of file paths (src/io/js)
+	//provideList: Array of module resource names (dojo.io)
+	//name: name of the layer file
+	//contents: the file contents for that layer file.
+	return dependencyResult; 
+
+	//Return the dependency list, since it is used for other things in the ant file.
+	return {
+		resourceDependencies: depList,
+		dojoContents: dojoContents
+	};
+}
+
+
+buildUtil.getDependencyPropertyFromProfile = function(/*String*/profileFile, /*String*/propName){
+	//summary: Gets a dependencies property from the profile file. The value
+	//of the property is assumed to be an array. An array will always be returned,
+	//but it may be an empty array.
+
+	//Use new String to make sure we have a JS string (not a Java string)
+	var profileText = fileUtil.readFile(profileFile);
+	//Get rid of CR and LFs since they seem to mess with the regexp match.
+	//Using the "m" option on the regexp was not enough.
+	profileText = profileText.replace(/\r/g, "");
+	profileText = profileText.replace(/\n/g, "");
+
+
+	var result = [];
+	var matchRegExp = new RegExp("(dependencies\\." + propName + "\\s*=\\s*\\[[^;]*\\s*\\])", "m");
+
+	var matches = profileText.match(matchRegExp);
+	//Create a shell object to hold the evaled properties.
+	var dependencies = {};
+	
+	if(matches && matches.length > 0){
+		eval(matches[0]);
+		if(dependencies && dependencies[propName] && dependencies[propName].length > 0){
+			result = dependencies[propName];
+		}
+	}
+
+	return result; //Array
+}
+
+buildUtil.configPrefixes = function(/*Object*/prefixes){
+	//summary: Registers the prefixes with Dojo.
+	if(prefixes && prefixes.length > 0){
+		for(i = 0; i < prefixes.length; i++){
+			dojo.registerModulePath(prefixes[i][0], prefixes[i][1]);
+		}
+	}
+}
+
+
+//The regular expressions that will help find dependencies in the file contents.
+buildUtil.masterDependencyRegExpString = "dojo.(requireLocalization|require|requireIf|provide|requireAfterIf|platformRequire|i18n\._preloadLocalizations)\\s*\\(([\\w\\W]*?)\\)";
+buildUtil.globalDependencyRegExp = new RegExp(buildUtil.masterDependencyRegExpString, "mg");
+buildUtil.dependencyPartsRegExp = new RegExp(buildUtil.masterDependencyRegExpString);
+
+buildUtil.mapPathToResourceName = function(pathName, prefixes){
+	//summary: converts a path name to the best fit for a resource name
+	//based on the available prefixes.
+	//Returns a value like "foo.bar" given an input of /some/path/to/foo/bar.js"
+
+	//First, find best fit prefix.
+	var bestPrefix = "";
+	var bestPrefixPath = "";
+	var bestPrefixPathIndex = 0;
+	var currentIndex = 0;
+	for(var i = 0; i < prefixes.length; i++){
+		//Prefix path must match somewhere in the pathName
+		currentIndex = pathName.lastIndexOf("/" + prefixes[i][0].replace(/\./g, "/") + "/");
+		if(currentIndex != -1 && currentIndex > bestPrefixPathIndex){
+			bestPrefix = prefixes[i][0];
+			bestPrefixPath = prefixes[i][1];
+			bestPrefixPathIndex = currentIndex;
+		}
+	}
+	
+	//Adjust the bestPrefixPathIndex by 2, to account for the slashes in the test above.
+	bestPrefixPathIndex += 2;
+	
+	if(!bestPrefix){
+		throw "Could not find a matching prefix for pathName: " + pathName;
+	}
+	
+	//Strip off first part of file name that is not relevant.
+	var startIndex = bestPrefixPathIndex + bestPrefix.length;
+	var newPathName = pathName.substring(startIndex, pathName.length);
+	
+	//Remove file extensions and any front slash.
+	newPathName = newPathName.replace(/^\//, "").replace(/\..*?$/, "");
+	
+	return bestPrefix + "." + newPathName.replace(/\//g, "."); 
+}
+
+buildUtil.mapResourceToPath = function(resourceName, prefixes){
+	//summary: converts a resourceName to a path.
+	//resourceName: String: like dojo.foo or mymodule.bar
+	//prefixes: Array: Actually an array of arrays. Comes from profile js file.
+	//          dependencies.prefixes = [["mymodule.foo", "../mymoduledir"]];
+	
+	var bestPrefix = "";
+	var bestPrefixPath = "";
+	if(prefixes){
+		for(var i = 0; i < prefixes.length; i++){
+			//Prefix must match from the start of the resourceName string.
+			if(resourceName.indexOf(prefixes[i][0]) == 0){
+				if(prefixes[i][0].length > bestPrefix.length){
+					bestPrefix = prefixes[i][0];
+					bestPrefixPath = prefixes[i][1];
+				}
+			}
+		}
+	}
+
+	//Get rid of matching prefix from resource name.
+	resourceName = resourceName.replace(bestPrefix, "");
+	
+	if(resourceName.charAt(0) == '.'){
+		resourceName = resourceName.substring(1, resourceName.length);
+	}
+	
+	resourceName = resourceName.replace(/\./g, "/");
+
+	var finalPath = bestPrefixPath;
+	if(finalPath.charAt(finalPath.length - 1) != "/"){
+		finalPath += "/";
+	}
+	if (resourceName){
+		finalPath += resourceName + "/";
+	}
+	
+	return finalPath;
+}
+
+buildUtil.makeResourceUri = function(resourceName, templatePath, srcRoot, prefixes){
+	var bestPrefix = "";
+	var bestPrefixPath = "";
+	if(prefixes){
+		for (var i = 0; i < prefixes.length; i++){
+			var prefix = prefixes[i];
+			//Prefix must match from the start of the resourceName string.
+			if(resourceName.indexOf(prefix[0]) == 0){
+				if(prefix[0].length > bestPrefix.length){
+					bestPrefix = prefix[0];
+					bestPrefixPath = prefix[1];
+				}
+			}
+		}
+
+		if(bestPrefixPath != ""){
+			//Convert resourceName to a path
+			resourceName = resourceName.replace(bestPrefix, "");
+			if(resourceName.indexOf(".") == 0){
+				resourceName = resourceName.substring(1, resourceName.length);
+			}
+			resourceName = resourceName.replace(/\./g, "/");
+
+			//Final path construction
+			var finalPath = bestPrefixPath + "/";
+			if(resourceName){
+				finalPath += resourceName + "/";
+			}
+			finalPath += templatePath;
+
+			return finalPath;
+		}
+	}
+
+	return srcRoot + templatePath;
+}
+
+buildUtil.internTemplateStrings = function(/*Object*/dependencies, /*String*/srcRoot, /*RegExp*/optimizeIgnoreRegExp){
+	//summary: interns strings in files for all .js files in the srcRoot directory.
+	var prefixes = dependencies["prefixes"] || [];
+	var skiplist = dependencies["internSkipList"] || [];
+
+	//Intern strings for all files in widget dir (xdomain and regular files)
+	var fileList = fileUtil.getFilteredFileList(srcRoot, /\.js$/, true);
+	if(fileList){
+		for(var i = 0; i < fileList.length; i++){
+			//Skip nls directories.
+			var fileName = fileList[i];
+			if(!fileName.match(/\/nls\//) && !fileName.match(optimizeIgnoreRegExp)){
+				buildUtil.internTemplateStringsInFile(fileList[i], srcRoot, prefixes, skiplist);
+			}
+		}
+	}
+}
+
+buildUtil.internTemplateStringsInFile = function(resourceFile, srcRoot, prefixes, skiplist){
+	var resourceContent = fileUtil.readFile(resourceFile);
+	resourceContent = buildUtil.interningRegexpMagic(resourceFile, resourceContent, srcRoot, prefixes, skiplist);
+	fileUtil.saveUtf8File(resourceFile, resourceContent);
+}
+
+buildUtil.interningDojoUriRegExpString = "(((templatePath|templateCssPath)\\s*(=|:)\\s*)dojo\\.(module)?Url\\(|dojo\\.cache\\s*\\(\\s*)\\s*?[\\\"\\']([\\w\\.\\/]+)[\\\"\\'](([\\,\\s]*)[\\\"\\']([\\w\\.\\/]*)[\\\"\\'])?(\\s*,\\s*)?([^\\)]*)?\\s*\\)";
+buildUtil.interningGlobalDojoUriRegExp = new RegExp(buildUtil.interningDojoUriRegExpString, "g");
+buildUtil.interningLocalDojoUriRegExp = new RegExp(buildUtil.interningDojoUriRegExpString);
+
+buildUtil.interningRegexpMagic = function(resourceFile, resourceContent, srcRoot, prefixes, skiplist){
+	var shownFileName = false;
+
+	return resourceContent.replace(buildUtil.interningGlobalDojoUriRegExp, function(matchString){
+		var parts = matchString.match(buildUtil.interningLocalDojoUriRegExp);
+
+		var filePath = "";
+		var resourceNsName = "";
+
+		if(!shownFileName){
+			logger.trace("Interning strings for : " + resourceFile);
+			shownFileName = true;
+		}
+
+		//logger.trace("Module match: " + parts[6] + " and " + parts[9]);
+		filePath = buildUtil.makeResourceUri(parts[6], parts[9], srcRoot, prefixes);
+		resourceNsName = parts[6] + ':' + parts[9];		
+
+		if(!filePath || buildUtil.isValueInArray(resourceNsName, skiplist)){
+			logger.trace("    skipping " + filePath);
+		}else{
+			logger.trace("    " + filePath);
+			//buildUtil.jsEscape will add starting and ending double-quotes.
+			var jsEscapedContent = buildUtil.jsEscape(fileUtil.readFile(filePath));
+			if(jsEscapedContent){
+				if(matchString.indexOf("dojo.cache") != -1){
+					//Handle dojo.cache-related interning.
+					var endContent = parts[11];
+					if(!endContent){
+						endContent = jsEscapedContent;
+					}else{
+						var braceIndex = endContent.indexOf("{");
+						if(braceIndex != -1){
+							endContent = endContent.substring(0, braceIndex + 1)
+								+ 'value: ' + jsEscapedContent + ','
+								+ endContent.substring(braceIndex + 1, endContent.length);
+						}
+					}
+					matchString = 'dojo.cache("' + parts[6] + '", "' + parts[9] + '", ' + endContent + ')';
+				}else{
+					//Handle templatePath/templateCssPath-related interning.
+					if(parts[3] == "templatePath"){
+						//Replace templatePaths
+						matchString = "templateString" + parts[4] + jsEscapedContent;
+					}else{
+						//Dealing with templateCssPath
+						//For the CSS we need to keep the template path in there
+						//since the widget loading stuff uses the template path to
+						//know whether the CSS has been processed yet.
+						//Could have matched assignment via : or =. Need different statement separators at the end.
+						var assignSeparator = parts[4];
+						var statementSeparator = ",";
+						var statementPrefix = "";
+			
+						//FIXME: this is a little weak because it assumes a "this" in front of the templateCssPath
+						//when it is assigned using an "=", as in 'this.templateCssPath = dojo.uri.dojoUri("some/path/to/Css.css");'
+						//In theory it could be something else, but in practice it is not, and it gets a little too weird
+						//to figure out, at least for now.
+						if(assignSeparator == "="){
+							statementSeparator = ";";
+							statementPrefix = "this.";
+						}
+						matchString = "templateCssString" + assignSeparator + jsEscapedContent + statementSeparator + statementPrefix + parts[0];
+					}
+				}
+			}
+		}
+
+		return matchString;
+	});
+}
+
+buildUtil.regExpEscape = function(/*String*/value){
+	//summary: Makes sure regexp-sensitive characters in a string are escaped correctly.
+	return value.replace(/([\.\*\/])/g, "\\$1");
+}
+
+buildUtil.jsEscape = function(/*string*/str){
+//summary:
+//	Adds escape sequences for non-visual characters, double quote and backslash
+//	and surrounds with double quotes to form a valid string literal.
+//	Take from the old dojo.string.escapeString code.
+//	Include it here so we don't have to load dojo.
+	return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'
+		).replace(/[\f]/g, "\\f"
+		).replace(/[\b]/g, "\\b"
+		).replace(/[\n]/g, "\\n"
+		).replace(/[\t]/g, "\\t"
+		).replace(/[\r]/g, "\\r"); // string
+}
+
+buildUtil.isValueInArray = function(/*Object*/value, /*Array*/ary){
+	//summary: sees if value is in the ary array. Uses == to see if the
+	//array item matches value.
+	for(var i = 0; i < ary.length; i++){
+		if(ary[i] == value){
+			return true; //boolean
+		}
+	}
+	return false; //boolean
+}
+
+buildUtil.convertArrayToObject = function(/*Array*/ary){
+	//summary: converts an array that has String members of "name=value"
+	//into an object, where the properties on the object are the names in the array
+	//member name/value pairs.
+	var result = {};
+	for(var i = 0; i < ary.length; i++){
+		var separatorIndex = ary[i].indexOf("=");
+		if(separatorIndex == -1){
+			throw "Malformed name/value pair: [" + ary[i] + "]. Format should be name=value";
+		}
+		result[ary[i].substring(0, separatorIndex)] = ary[i].substring(separatorIndex + 1, ary[i].length);
+	}
+	return result; //Object
+}
+
+buildUtil.optimizeJs = function(/*String fileName*/fileName, /*String*/fileContents, /*String*/copyright, /*String*/optimizeType, /*String*/stripConsole){
+	//summary: either strips comments from string or compresses it.
+	copyright = copyright || "";
+
+	// understand stripConsole from dojo 1.3 and before
+	if (stripConsole == "none") {
+		stripConsole = undefined;
+	} else if (stripConsole == "normal,warn") {
+		//logger.info("Converting stripConsole "normal,warn" to \"warn\"
+		logger.warn("stripConsole value \"normal,warn\" replaced with \"warn\".  Please update your build scripts.");
+		stripConsole = "warn";
+	} else if (stripConsole == "normal,error") {
+		logger.warn("stripConsole value \"normal,error\" replaced with \"all\".  Please update your build scripts.");
+		stripConsole = "all";
+	}
+
+	// sanity check stripConsole
+	if (stripConsole != undefined && !stripConsole.match(/normal|warn|all/)) {
+		throw "Invalid stripConsole provided (" + stripConsole + ")";
+	}
+	if (stripConsole == undefined) {
+		// java will receive undefined as "undefined" but null as null.
+		stripConsole = null;
+	}
+
+	//Use rhino to help do minifying/compressing.
+	var context = Packages.org.mozilla.javascript.Context.enter();
+	try{
+		// Use the interpreter for interactive input (copied this from Main rhino class).
+		context.setOptimizationLevel(-1);
+
+		if(optimizeType.indexOf("shrinksafe") == 0 || optimizeType == "packer"){
+			//Apply compression using custom compression call in Dojo-modified rhino.
+			fileContents = new String(Packages.org.dojotoolkit.shrinksafe.Compressor.compressScript(fileContents, 0, 1, stripConsole));
+			if(optimizeType.indexOf(".keepLines") == -1){
+				fileContents = fileContents.replace(/[\r\n]/g, "");
+			}
+		}else if(optimizeType.indexOf("closure") == 0){
+			var jscomp = com.google.javascript.jscomp;
+			var flags = com.google.common.flags;
+
+			//Fake extern
+			var externSourceFile = buildUtil.closurefromCode("fakeextern.js", " ");
+
+			//Set up source input
+			var jsSourceFile = buildUtil.closurefromCode(String(fileName), String(fileContents));
+		
+			//Set up options
+			var options = new jscomp.CompilerOptions();
+			options.prettyPrint = optimizeType.indexOf(".keepLines") !== -1;
+			var FLAG_compilation_level = flags.Flag.value(jscomp.CompilationLevel.SIMPLE_OPTIMIZATIONS);
+			FLAG_compilation_level.get().setOptionsForCompilationLevel(options);
+			var FLAG_warning_level = flags.Flag.value(jscomp.WarningLevel.DEFAULT);
+			FLAG_warning_level.get().setOptionsForWarningLevel(options);
+
+			//Run the compiler
+			var compiler = new Packages.com.google.javascript.jscomp.Compiler(Packages.java.lang.System.err);
+			result = compiler.compile(externSourceFile, jsSourceFile, options);
+			fileContents = compiler.toSource();
+		}else if(optimizeType == "comments"){
+			//Strip comments
+			var script = context.compileString(fileContents, fileName, 1, null);
+			fileContents = new String(context.decompileScript(script, 0));
+			
+			//Replace the spaces with tabs.
+			//Ideally do this in the pretty printer rhino code.
+			fileContents = fileContents.replace(/    /g, "\t");
+
+			//If this is an nls bundle, make sure it does not end in a ;
+			//Otherwise, bad things happen.
+			if(fileName.match(/\/nls\//)){
+				fileContents = fileContents.replace(/;\s*$/, "");
+			}
+		}
+	}finally{
+		Packages.org.mozilla.javascript.Context.exit();
+	}
+
+
+	return copyright + fileContents;
+}
+
+
+buildUtil.setupPacker = function(){
+	// no-op.
+}
+
+buildUtil.optimizeJsDir = function(/*String*/startDir, /*RegeExp*/optimizeIgnoreRegExp, /*String?*/copyrightText, /*String?*/optimizeType, /*String?*/stripConsole){
+	//summary: strips the JS comments from all the files in "startDir", and all subdirectories.
+	//Also runs shrinksafe minification, and console call removal.
+	var copyright = (copyrightText || fileUtil.readFile("copyright.txt")) + fileUtil.getLineSeparator();
+	var fileList = fileUtil.getFilteredFileList(startDir, /\.js$/, true);
+	
+	var messageType = optimizeType;
+	if(stripConsole){
+		messageType += (optimizeType ? ", " : "") + "stripConsole=" + stripConsole;
+	}
+
+	if(fileList){
+		for(var i = 0; i < fileList.length; i++){
+			//Don't process dojo.js since it has already been processed.
+			//Don't process dojo.js.uncompressed.js because it is huge.
+			//Don't process anything that might be in a buildscripts folder (only a concern for webbuild.sh)
+			if(!fileList[i].match(optimizeIgnoreRegExp)
+				&& !fileList[i].match(/buildscripts/)
+				&& !fileList[i].match(/nls/)
+				&& !fileList[i].match(/tests\//)){
+
+				if(messageType){
+					logger.trace("Optimizing (" + messageType + ") file: " + fileList[i]);
+				}
+
+				//Read in the file. Make sure we have a JS string.
+				var fileContents = fileUtil.readFile(fileList[i]);
+
+				//Do comment removal.
+				if(optimizeType){
+					try{
+						fileContents = buildUtil.optimizeJs(fileList[i], fileContents, copyright, optimizeType, stripConsole);
+					}catch(e){
+						logger.error("Could not strip comments for file: " + fileList[i] + ", error: " + e);
+					}
+				}else{
+					//Just apply copyright.
+					fileContents = copyright + fileContents;
+				}
+
+				//Write out the file with appropriate copyright.
+				fileUtil.saveUtf8File(fileList[i], fileContents);
+			}
+		}
+	}
+}
+
+buildUtil.optimizeCss = function(/*String*/startDir, /*String*/optimizeType, /*String?*/cssImportIgnore){
+	//summmary: Optimizes CSS files in a directory.
+	
+	if(optimizeType.indexOf("comments") != -1){
+		//Make sure we have a delimited ignore list to make matching faster
+		if(cssImportIgnore){
+			cssImportIgnore = cssImportIgnore + ",";
+		}
+
+		var fileList = fileUtil.getFilteredFileList(startDir, /\.css$/, true);
+		if(fileList){
+			for(var i = 0; i < fileList.length; i++){
+				var fileName = fileList[i];
+				logger.trace("Optimizing (" + optimizeType + ") CSS file: " + fileName);
+				
+				//Read in the file. Make sure we have a JS string.
+				var originalFileContents = fileUtil.readFile(fileName);
+				var fileContents = buildUtil.flattenCss(fileName, originalFileContents, cssImportIgnore);
+
+				//Do comment removal.
+				try{
+					var startIndex = -1;
+					//Get rid of comments.
+					while((startIndex = fileContents.indexOf("/*")) != -1){
+						var endIndex = fileContents.indexOf("*/", startIndex + 2);
+						if(endIndex == -1){
+							throw "Improper comment in CSS file: " + fileName;
+						}
+						fileContents = fileContents.substring(0, startIndex) + fileContents.substring(endIndex + 2, fileContents.length);
+					}
+					//Get rid of newlines.
+					if(optimizeType.indexOf(".keepLines") == -1){
+						fileContents = fileContents.replace(/[\r\n]/g, "");
+						fileContents = fileContents.replace(/\s+/g, " ");
+						fileContents = fileContents.replace(/\{\s/g, "{");
+						fileContents = fileContents.replace(/\s\}/g, "}");
+					}else{
+						//Remove multiple empty lines.
+						fileContents = fileContents.replace(/(\r\n)+/g, "\r\n");
+						fileContents = fileContents.replace(/(\n)+/g, "\n");
+					}
+				}catch(e){
+					fileContents = originalFileContents;
+					logger.error("Could not optimized CSS file: " + fileName + ", error: " + e);
+				}
+	
+				//Write out the file with appropriate copyright.
+				fileUtil.saveUtf8File(fileName, fileContents);
+			}
+		}
+	}
+}
+
+buildUtil.backSlashRegExp = /\\/g;
+buildUtil.cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/g;
+buildUtil.cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g;
+
+buildUtil.cleanCssUrlQuotes = function(/*String*/url){
+	//summary: If an URL from a CSS url value contains start/end quotes, remove them.
+	//This is not done in the regexp, since my regexp fu is not that strong,
+	//and the CSS spec allows for ' and " in the URL if they are backslash escaped.
+
+	//Make sure we are not ending in whitespace.
+	//Not very confident of the css regexps above that there will not be ending
+	//whitespace.
+	url = url.replace(/\s+$/, "");
+
+	if(url.charAt(0) == "'" || url.charAt(0) == "\""){
+		url = url.substring(1, url.length - 1);
+	}
+
+	return url;
+}
+
+buildUtil.flattenCss = function(/*String*/fileName, /*String*/fileContents, /*String?*/cssImportIgnore){
+	//summary: inlines nested stylesheets that have @import calls in them.
+
+	//Find the last slash in the name.
+	fileName = fileName.replace(buildUtil.backSlashRegExp, "/");
+	var endIndex = fileName.lastIndexOf("/");
+
+	//Make a file path based on the last slash.
+	//If no slash, so must be just a file name. Use empty string then.
+	var filePath = (endIndex != -1) ? fileName.substring(0, endIndex + 1) : "";
+
+	return fileContents.replace(buildUtil.cssImportRegExp, function(fullMatch, urlStart, importFileName, urlEnd, mediaTypes){
+		//Only process media type "all" or empty media type rules.
+		if(mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) != "all")){
+			return fullMatch;
+		}
+
+		importFileName = buildUtil.cleanCssUrlQuotes(importFileName);
+		
+		//Ignore the file import if it is part of an ignore list.
+		if(cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") != -1){
+			return fullMatch;
+		}
+
+		//Make sure we have a unix path for the rest of the operation.
+		importFileName = importFileName.replace(buildUtil.backSlashRegExp, "/");
+
+		try{
+			//if a relative path, then tack on the filePath.
+			//If it is not a relative path, then the readFile below will fail,
+			//and we will just skip that import.
+			var fullImportFileName = importFileName.charAt(0) == "/" ? importFileName : filePath + importFileName;
+			var importContents = fileUtil.readFile(fullImportFileName);
+
+			//Make sure to flatten any nested imports.
+			importContents = buildUtil.flattenCss(fullImportFileName, importContents);
+			
+			//Make the full import path
+			var importEndIndex = importFileName.lastIndexOf("/");
+
+			//Make a file path based on the last slash.
+			//If no slash, so must be just a file name. Use empty string then.
+			var importPath = (importEndIndex != -1) ? importFileName.substring(0, importEndIndex + 1) : "";
+
+			//Modify URL paths to match the path represented by this file.
+			importContents = importContents.replace(buildUtil.cssUrlRegExp, function(fullMatch, urlMatch){
+				var fixedUrlMatch = buildUtil.cleanCssUrlQuotes(urlMatch);
+				fixedUrlMatch = fixedUrlMatch.replace(buildUtil.backSlashRegExp, "/");
+
+				//Only do the work for relative URLs. Skip things that start with / or have
+				//a protocol.
+				var colonIndex = fixedUrlMatch.indexOf(":");
+				if(fixedUrlMatch.charAt(0) != "/" && (colonIndex == -1 || colonIndex > fixedUrlMatch.indexOf("/"))){
+					//It is a relative URL, tack on the path prefix
+					urlMatch = importPath + fixedUrlMatch;
+				}else{
+					logger.trace(importFileName + "\n  URL not a relative URL, skipping: " + urlMatch);
+				}
+
+				//Collapse .. and .
+				var parts = urlMatch.split("/");
+				for(var i = parts.length - 1; i > 0; i--){
+					if(parts[i] == "."){
+						parts.splice(i, 1);
+					}else if(parts[i] == ".."){
+						if(i != 0 && parts[i - 1] != ".."){
+							parts.splice(i - 1, 2);
+							i -= 1;
+						}
+					}
+				}
+
+				return "url(" + parts.join("/") + ")";
+			});
+
+			return importContents;
+		}catch(e){
+			logger.trace(fileName + "\n  Cannot inline css import, skipping: " + importFileName);
+			return fullMatch;
+		}
+	});
+}
+
+buildUtil.guardProvideRegExpString = "dojo\\s*\\.\\s*provide\\s*\\(\\s*([\\'\\\"][^\\'\\\"]*[\\'\\\"])\\s*\\)";
+buildUtil.guardProvideRegExp = new RegExp(buildUtil.guardProvideRegExpString);
+buildUtil.guardProvideRegExpGlobal = new RegExp(buildUtil.guardProvideRegExpString, "g");
+
+buildUtil.addGuardsAndBaseRequires = function(/*String || Array*/startDir, /*Boolean*/needBaseRequires){
+	//summary: adds a definition guard around code in a file to protect
+	//against redefinition cases when layered builds are used. Also injects
+	//dojo._base require calls if needBaseRequires is true. Accepts a string
+	//of the start directory to use, or an array of file name strings to process.
+	var lineSeparator = fileUtil.getLineSeparator();
+
+	var fileList = startDir;
+	if(fileList instanceof String){
+		fileList = fileUtil.getFilteredFileList(fileList, /\.js$/, true);
+	}else{
+		//Make sure we only process .js files
+		for(var i = fileList.length - 1; i >= 0; i--){
+			if(!fileList[i].match(/\.js$/)){
+				fileList.splice(i, 1);
+			}
+		}
+	}
+
+	if(fileList){
+		for(i = 0; i < fileList.length; i++){
+			var fileContents = fileUtil.readFile(fileList[i]);
+			
+			//See if we need to inject dojo._base require calls.
+			//Do not process _base.js since it already has the require calls in there.
+			if(needBaseRequires
+				&& fileList[i].indexOf("/tests/") == -1
+				&& fileList[i].indexOf("/demos/") == -1
+				&& fileList[i].indexOf("/themes/") == -1
+				&& fileList[i].indexOf("dojo/_base.js") == -1){
+				buildUtil.baseMappingRegExp.lastIndex = 0;
+				var matches = null;
+				
+				//Strip out comments to get a better picture.
+				var tempContents = buildUtil.removeComments(fileContents);
+				
+				//Find where we can place the new require calls. This should be after
+				//any dojo.provide calls, so we do not hit a weird problem with a circular dependency
+				//that does not get resolved since the dojo.provide call does not fire indicating
+				//the file has been loaded.
+				buildUtil.guardProvideRegExpGlobal.lastIndex = 0;
+				var lastPosition = -1;
+				while((matches = buildUtil.guardProvideRegExpGlobal.exec(fileContents))){
+					lastPosition = buildUtil.guardProvideRegExpGlobal.lastIndex;
+				}
+				
+				//If no dojo.provide calls found, do not bother with the file.
+				if(lastPosition != -1){
+					var contentChunks = [
+						fileContents.substring(0, lastPosition + 1) + "\n",
+						fileContents.substring(lastPosition + 1, fileContents.length)
+					];
+					
+					var addedResources = {};
+					while((matches = buildUtil.baseMappingRegExp.exec(tempContents))){
+						var baseResource = buildUtil.baseMappings[matches[1]];
+						//Make sure we do not add the dependency to its source resource.
+						if(!addedResources[baseResource] && fileList[i].indexOf("_base/" + baseResource) == -1){
+							logger.trace("Adding dojo._base." + baseResource + " because of match: " + matches[1] + " to file: " + fileList[i]);
+							contentChunks[0] += 'dojo.require("dojo._base.' + baseResource + '");\n';
+							addedResources[baseResource] = true;
+						}
+					}
+					
+					fileContents = contentChunks.join("");
+				}
+			}
+
+			buildUtil.guardProvideRegExp.lastIndex = 0;
+			var match = buildUtil.guardProvideRegExp.exec(fileContents);
+			if(match){
+				//Only add the guard if there is not already one in the file.
+				var existingGuardRegExp = new RegExp('if\\(\\!dojo\\._hasResource\\[' + match[1] + '\\]\\)');
+				if(!fileContents.match(existingGuardRegExp)){
+					fileContents = 'if(!dojo._hasResource[' + match[1] + ']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.'
+						+ lineSeparator
+						+ 'dojo._hasResource[' + match[1] + '] = true;'
+						+ lineSeparator
+						+ fileContents
+						+ lineSeparator
+						+ '}'
+						+ lineSeparator;
+	
+					fileUtil.saveUtf8File(fileList[i], fileContents);
+				}
+			}
+		}
+	}
+}
+
+//TODO: generate this via an algorithm.
+buildUtil.baseMappings = {
+	"trim": "lang",
+	"clone": "lang",
+	"_toArray": "lang",
+	"partial": "lang",
+	"delegate": "lang",
+	"_delegate": "lang",
+	"hitch": "lang",
+	"_hitchArgs": "lang",
+	"extend": "lang",
+	"isAlien": "lang",
+	"isArrayLike": "lang",
+	"isObject": "lang",
+	"isFunction": "lang",
+	"isArray": "lang",
+	"isString": "lang",
+	
+	"declare": "declare",
+	
+	"subscribe": "connect",
+	"unsubscribe": "connect",
+	"publish": "connect",
+	"connectPublisher": "connect",
+	
+	"Deferred": "Deferred",
+	
+	"fromJson": "json",
+	"_escapeString": "json",
+	"toJson": "json",
+	
+	"indexOf": "array",
+	"lastIndexOf": "array",
+	"forEach": "array",
+	"every": "array",
+	"some": "array",
+	"map": "array",
+	"filter": "array",
+	
+	"Color": "Color",
+	"blendColors": "Color",
+	"colorFromRgb": "Color",
+	"colorFromHex": "Color",
+	"colorFromArray": "Color",
+	"colorFromString": "Color",
+
+	"doc": "window",
+	"body": "window",
+	"setContext": "window",
+	"_fireCallback": "window",
+	"withGlobal": "window",
+	"withDoc": "window",
+	
+	"connect": "event",
+	"disconnect": "event",
+	"fixEvent": "event",
+	"stopEvent": "event",
+	"_connect": "event",
+	"_disconnect": "event",
+	"_ieDispatcher": "event",
+	"_getIeDispatcher": "event",
+	
+	"byId": "html",
+	"destroy": "html",
+	"_destroyElement": "html",
+	"isDescendant": "html",
+	"setSelectable": "html",
+	"place": "html", 
+	"getComputedStyle": "html", 
+	"_toPixelValue": "html", 
+	"_getOpacity": "html",
+	"_setOpacity": "html", 
+	"style": "html", 
+	"_getPadExtents": "html", 
+	"_getBorderExtents": "html",
+	"_getPadBorderExtents": "html", 
+	"_getMarginExtents": "html", 
+	"_getMarginBox": "html",
+	"_getContentBox": "html", 
+	"_getBorderBox": "html", 
+	"_setBox": "html", 
+	"_usesBorderBox": "html",
+	"_setContentSize": "html", 
+	"_setMarginBox": "html", 
+	"marginBox": "html", 
+	"contentBox": "html",
+	"_docScroll": "html", 
+	"_isBodyLtr": "html", 
+	"_getIeDocumentElementOffset": "html",
+	"_fixIeBiDiScrollLeft": "html",
+	"_abs": "html", 
+	"coords": "html", 
+	"hasAttr": "html", 
+	"attr": "html",
+	"removeAttr": "html",
+	"create": "html",
+	"empty": "html",
+	"_toDom": "html",
+	"hasClass": "html", 
+	"addClass": "html", 
+	"removeClass": "html",
+	"toggleClass": "html",
+	
+	"NodeList": "NodeList",
+	
+	"_filterQueryResult": "query",
+	"query": "query",
+	
+	"formToObject": "xhr", 
+	"objectToQuery": "xhr",
+	"formToQuery": "xhr",
+	"formToJson": "xhr",
+	"queryToObject": "xhr", 
+	"_ioSetArgs": "xhr",
+	"_ioCancelAll": "xhr",
+	"_ioAddQueryToUrl": "xhr",
+	"xhr": "xhr",
+	"xhrGet": "xhr",
+	"rawXhrPost": "xhr",
+	"rawXhrPut": "xhr",
+	"xhrDelete": "xhr",
+	"wrapForm": "xhr",
+	
+	"_Line": "fx",
+	"_Animation": "fx",
+	"Animation":"fx",
+	"_fade": "fx",
+	"fadeIn": "fx",
+	"fadeOut": "fx",
+	"_defaultEasing": "fx",
+	"animateProperty": "fx",
+	"anim": "fx"
+};
+
+(function(){
+	var names = "(";
+	for(var param in buildUtil.baseMappings){
+		if(names != "("){
+			names += "|";
+		}
+		names += param;
+	}
+	names += ")";
+	
+	buildUtil.baseMappingRegExp = new RegExp("\\." + names + "\\W", "g");
+})();
+
+buildUtil.processConditionalsForDir = function(/*String*/startDir, /*RegExp*/layerIgnoreRegExp, /*Object*/kwArgs){
+	//summary: processes build conditionals for a directory, but ignores files in the layerIgnoreRegExp argument.
+	var fileList = fileUtil.getFilteredFileList(startDir, /\.js$/, true);
+	if(fileList){
+		for(var i = 0; i < fileList.length; i++){
+			//Skip nls directories.
+			var fileName = fileList[i];
+			if(!fileName.match(layerIgnoreRegExp)){
+				var fileContents = fileUtil.readFile(fileName);
+				if(fileContents.indexOf("//>>") != -1){
+					fileUtil.saveFile(fileName, buildUtil.processConditionals(fileName, fileContents, kwArgs));
+				}
+			}
+		}
+	}
+}
+
+buildUtil.conditionalRegExp = /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/;
+buildUtil.processConditionals = function(/*String*/fileName, /*String*/fileContents, /*Object*/kwArgs){
+	//summary: processes the fileContents for some Dojo-specific conditional comments.
+	var foundIndex = -1;
+	var startIndex = 0;
+	
+	while((foundIndex = fileContents.indexOf("//>>", startIndex)) != -1){
+		//Found a conditional. Get the conditional line.
+		var lineEndIndex = fileContents.indexOf("\n", foundIndex);
+		if(lineEndIndex == -1){
+			lineEndIndex = fileContents.length - 1;
+		}
+
+		//Increment startIndex past the line so the next conditional search can be done.
+		startIndex = lineEndIndex + 1;
+
+		//Break apart the conditional.
+		var conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1);
+		var matches = conditionLine.match(buildUtil.conditionalRegExp);
+		if(matches){
+			var type = matches[1];
+			var marker = matches[2];
+			var condition = matches[3];
+			var isTrue = false;
+			//See if the condition is true.
+			try{
+				isTrue = !!eval("(" + condition + ")");
+			}catch(e){
+				throw "Error in file: "
+					+ fileName
+					+ ". Conditional comment: "
+					+ conditionLine
+					+ " failed with this error: " + e;
+			}
+		
+			//Find the endpoint marker.
+			var endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g");
+			var endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length));
+			if(endMatches){
+				
+				var endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length;
+				
+				//Find the next line return based on the match position.
+				lineEndIndex = fileContents.indexOf("\n", endMarkerIndex);
+				if(lineEndIndex == -1){
+					lineEndIndex = fileContents.length - 1;
+				}
+
+				//Should we include the segment?
+				var shouldInclude = ((type == "exclude" && !isTrue) || (type == "include" && isTrue));
+				
+				//Remove the conditional comments, and optionally remove the content inside
+				//the conditional comments.
+				var startLength = startIndex - foundIndex;
+				fileContents = fileContents.substring(0, foundIndex)
+					+ (shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "")
+					+ fileContents.substring(lineEndIndex + 1, fileContents.length);
+				
+				//Move startIndex to foundIndex, since that is the new position in the file
+				//where we need to look for more conditionals in the next while loop pass.
+				startIndex = foundIndex;
+			}else{
+				throw "Error in file: "
+					+ fileName
+					+ ". Cannot find end marker for conditional comment: "
+					+ conditionLine;
+				
+			}
+		}
+	}
+
+	return fileContents;
+}
+
+buildUtil.setScopeDjConfig = function(/*String*/fileContents, /*String*/djConfigString){
+	//summary: burns in a local djConfig for the file contents.
+	//djConfigString should be a string.
+	//Have to use eval to avoid name condensing by shrinksafe.
+	return fileContents.replace(/\/\*\*Build will replace this comment with a scoped djConfig \*\*\//, 'eval("var djConfig = ' + djConfigString.replace(/(['"])/g, '\\$1') + ';");');
+}
+
+buildUtil.setScopeNames = function(/*String*/fileContents, /*String*/scopeMap){
+	//summary: burns in the scope names into the file contents.
+	//scopeMap should be a [["name","value"],["name","value"]] string. Notice the lack of spaces.
+	//Single quotes can be used instead of double quotes.
+	return fileContents.replace(/var\s+sMap\s+=\s+null/, "var sMap = " + scopeMap);
+}
+
+buildUtil.symctr = 0;
+buildUtil.symtbl = null;
+buildUtil.generateSym = function(/*String*/name){
+	var m = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+	var len = m.length;
+	var s;
+	if(buildUtil.symctr < len*len){
+		s = m.charAt(Math.floor(buildUtil.symctr/len))
+			+m.charAt(buildUtil.symctr%len);
+	}else{
+		s = m.charAt(Math.floor(buildUtil.symctr/(len*len))-1)
+			+m.charAt(Math.floor(buildUtil.symctr/len)%len)
+			+m.charAt(buildUtil.symctr%len);
+	}
+	s = "$D" + s;
+	buildUtil.symctr++;
+	var ret;
+	
+	//Make sure name is valid JS
+	name = name.replace(/-/g, "__");
+	if(kwArgs.symbol == "long"){
+		ret = name; // + "_" + s;
+	}else if(kwArgs.symbol == "short"){
+		buildUtil.symtbl[s + "_"] = name;
+		ret = s + "_";
+	}
+	return ret;
+}
+
+buildUtil.insertSymbols = function(/*String*/startDir, /*Object*/kwArgs){
+	//summary: add global function symbols to anonymous functions.
+	buildUtil.symtbl = {};
+	var fileList = fileUtil.getFilteredFileList(startDir, /\.js$/, true);
+	if(fileList){
+		logger.trace("Inserting global function symbols in: "+startDir);
+		for(var i = 0; i < fileList.length; i++){
+			//Don't process loader_debug.js since global symbols conflict with loader.js.
+			//Don't process dojo.js.uncompressed.js because it is huge.
+			//Don't process anything that might be in a buildscripts folder (only a concern for webbuild.sh)
+			if(!fileList[i].match(/loader_debug\.js/)
+				&& !fileList[i].match(/\.uncompressed\.js/)
+				&& !fileList[i].match(/buildscripts/)
+				&& !fileList[i].match(/nls/)
+				&& !fileList[i].match(/tests\//)){
+				
+				//Read in the file. Make sure we have a JS string.
+				var fileContents = fileUtil.readFile(fileList[i]);
+
+				//Do insertion.
+				var className;
+				if(fileContents.match(/dojo\.provide\("(.*)"\);/)){
+					className = RegExp.$1.replace(/\./g, "_")+"_";
+				}
+				if(className){
+					fileContents = fileContents.replace(/^(\s*)(\w+)(\s*:\s*function)\s*(\(.*)$/mg, function(str, p1, p2, p3, p4){
+						return p1+p2+p3+" "+buildUtil.generateSym(className+p2)+p4;
+					});
+					fileContents = fileContents.replace(/^(\s*this\.)(\w+)(\s*=\s*function)\s*(\(.*)$/mg, function(str, p1, p2, p3, p4){
+						return p1+p2+p3+" "+buildUtil.generateSym(className+p2)+p4;
+					});
+				}
+				fileContents = fileContents.replace(/^(\s*)([\w\.]+)(\s*=\s*function)\s*(\(.*)/mg, function(str, p1, p2, p3, p4){
+					return p1+p2+p3+" "+buildUtil.generateSym(p2.replace(/\./g, "_"))+p4;
+				});
+
+				//Write out the file
+				fileUtil.saveUtf8File(fileList[i], fileContents);
+			}
+		}
+
+		if(kwArgs.symbol == "short"){
+			var symbolText = "";
+			var lineSeparator = fileUtil.getLineSeparator();
+			for(var key in buildUtil.symtbl){
+				symbolText += key + ": \"" + buildUtil.symtbl[key] + "\"" + lineSeparator;
+			}
+			fileUtil.saveFile(startDir + "/symboltable.txt", symbolText);
+		}
+	}
+}
+
+buildUtil.extractMatchedParens = function(/*RegExp*/ regexp, /*String*/fileContents, /*Boolean*/removeTrailingComma){
+	//summary: Pass in a regexp that includes a start parens: (, and this function will
+	//find the matching end parens for that regexp, remove the matches from fileContents,
+	//and return an array where the first member of the array is the modified fileContents
+	//and the rest of the array members are the matches found. If no matches are found,
+	//then returns null.
+
+	//Extracts
+	regexp.lastIndex = 0;
+
+	var parenRe = /[\(\)]/g;
+	parenRe.lastIndex = 0;
+
+	var results = [],
+		matches,
+		cleanedContent = [],
+		previousLastIndex = 0
+	;
+	
+	while((matches = regexp.exec(fileContents))){
+		
+		//Find end of the call by finding the matching end paren
+		parenRe.lastIndex = regexp.lastIndex;
+		var matchCount = 1;
+		var parenMatch;
+		while((parenMatch = parenRe.exec(fileContents))){
+			if(parenMatch[0] == ")"){
+				matchCount -= 1;
+			}else{
+				matchCount += 1;
+			}
+			if(matchCount == 0){
+				break;
+			}
+		}
+
+		if(matchCount != 0){
+			throw "unmatched paren around character " + parenRe.lastIndex + " in: " + fileContents;
+		}
+
+		// Put the master matching string in the results.
+		var startIndex = regexp.lastIndex - matches[0].length;
+		results.push(fileContents.substring(startIndex, parenRe.lastIndex));
+		// add file's fragment from previous console.* match to current match 
+		cleanedContent.push(fileContents.substring(previousLastIndex, startIndex));
+		
+		// Account for ending semicolon if desired.
+		var endPoint = parenRe.lastIndex;
+		if(removeTrailingComma && fileContents.charAt(endPoint) == ";"){
+			endPoint += 1;
+		}
+
+		previousLastIndex = regexp.lastIndex = endPoint;
+
+	}
+
+	// add the last matched fragment to the cleaned output
+	cleanedContent.push(fileContents.substring(previousLastIndex, fileContents.length));
+
+	if(results.length > 0){
+		results.unshift(cleanedContent.join(''));
+	}
+
+	return (results.length ? results : null);
+}
+
diff --git a/util/buildscripts/jslib/buildUtilXd.js b/util/buildscripts/jslib/buildUtilXd.js
new file mode 100644
index 0000000..a5e8a2f
--- /dev/null
+++ b/util/buildscripts/jslib/buildUtilXd.js
@@ -0,0 +1,192 @@
+//The functions in this file assume that buildUtil.js have been loaded.
+var buildUtilXd = {};
+
+buildUtilXd.setXdDojoConfig = function(/*String*/fileContents, /*String*/url){
+	//summary: sets sets up xdomain loading for a particular URL.
+	//parameters:
+	//		fileContents: be a built dojo.js (can be uncompressed or compressed).
+	//		url: value should be the url to the directory that contains the dojo,
+	//		dijit and dojox directories.
+	//			Example: "http://some.domain.com/dojo090" (no ending slash)
+	//This function will inject some contents after the dojo.registerModulePath() definition.
+	//The contents of fileName should have been a dojo.js that includes the contents
+	//of loader_xd.js (specify loader=xdomain in the build command).
+
+	//This code is not very robust. It will break if dojo.registerModulePath definition
+	//changes to anything more advanced.
+	var match = fileContents.match(/(dojo\.registerModulePath\s*=\s*function.*\{)/);
+	
+	//Find the next two } braces and in inject code after that.
+	var endIndex = fileContents.indexOf("}", match.index);
+	endIndex = fileContents.indexOf("}", endIndex + 1);
+	if(fileContents.charAt(endIndex + 1) == ";"){
+		endIndex += 1;
+	}
+	endIndex +=1;
+
+	var lineSeparator = fileUtil.getLineSeparator();
+	return fileContents.substring(0, endIndex)
+		+ lineSeparator
+		+ "if(typeof dojo.config[\"useXDomain\"] == \"undefined\"){"
+		+ "dojo.config.useXDomain = true;};\ndojo.registerModulePath(\"dojo\", \""
+		+ url + "/dojo"
+		+ "\");\ndojo.registerModulePath(\"dijit\", \""
+		+ url + "/dijit"
+		+ "\");\ndojo.registerModulePath(\"dojox\", \""
+		+ url + "/dojox"
+		+ "\");"
+		+ lineSeparator
+		+ fileContents.substring(endIndex, fileContents.length);
+}
+
+buildUtilXd.xdgen = function(
+	/*String*/prefixName,
+	/*String*/prefixPath,
+	/*Array*/prefixes,
+	/*RegExp*/optimizeIgnoreRegExp,
+	/*Object*/kwArgs
+){
+	//summary: generates the .xd.js files for a build.
+	var jsFileNames = fileUtil.getFilteredFileList(prefixPath, /\.js$/, true);
+	
+	//Construct a regexp to avoid xd generating loader_xd.js, since shrinksafe
+	//does not like the resulting javascript that is generated, because of
+	//bug http://trac.dojotoolkit.org/ticket/2766
+	var loaderIgnoreRegExp = /dojo\/_base\/_loader\/loader_xd/;
+
+	for(var i = 0; i < jsFileNames.length; i++){
+		var jsFileName = jsFileNames[i];
+
+		//Some files, like the layer files, have already been xd
+		//processed, so be sure to skip those.
+		if(!jsFileName.match(optimizeIgnoreRegExp) && !jsFileName.match(loaderIgnoreRegExp)){
+			var xdFileName = jsFileName.replace(/\.js$/, ".xd.js");
+			var fileContents = fileUtil.readFile(jsFileName);
+
+			//Files in nls directories, except for the ones that have multiple
+			//bundles flattened (therefore have a dojo.provide call),
+			//need to have special xd contents.
+			if(jsFileName.match(/\/nls\//) && fileContents.indexOf("dojo.provide(") == -1){
+				var xdContents = buildUtilXd.makeXdBundleContents(prefixName, prefixPath, jsFileName, fileContents, prefixes, kwArgs);			
+			}else{
+				xdContents = buildUtilXd.makeXdContents(fileContents, prefixes, kwArgs);
+			}
+			fileUtil.saveUtf8File(xdFileName, xdContents);
+		}
+	}
+}
+
+//Function that generates the XD version of the module file's contents
+buildUtilXd.makeXdContents = function(fileContents, prefixes, kwArgs){
+	var dependencies = [];
+
+	//Use the regexps to find resource dependencies for this module file.
+	var depMatches = buildUtil.removeComments(fileContents).match(buildUtil.globalDependencyRegExp);
+	if(depMatches){
+		for(var i = 0; i < depMatches.length; i++){
+			var partMatches = depMatches[i].match(buildUtil.dependencyPartsRegExp);
+			var depCall = partMatches[1];
+			var depArgs = partMatches[2];
+
+			if(depCall == "requireLocalization"){
+				//Need to find out what locales are available so the dojo loader
+				//only has to do one script request for the closest matching locale.
+				var reqArgs = i18nUtil.getRequireLocalizationArgsFromString(depArgs);
+				if(reqArgs.moduleName){
+					//Find the list of locales supported by looking at the path names.
+					var locales = i18nUtil.getLocalesForBundle(reqArgs.moduleName, reqArgs.bundleName, prefixes);
+
+					//Add the supported locales to the requireLocalization arguments.
+					if(!reqArgs.localeName){
+						depArgs += ", null";
+					}
+
+					depCall = "requireLocalization";
+					depArgs += ', "' + locales.join(",") + '"';
+				}else{
+					//Malformed requireLocalization call. Skip it. May be a comment.
+					continue;
+				}
+			}
+	
+			dependencies.push('"' + depCall + '", ' + depArgs);
+		}
+	}
+
+	//Build the xd file contents.
+	var xdContentsBuffer = [];
+	var scopeArgs = kwArgs.xdScopeArgs || "dojo, dijit, dojox";
+
+	//Start the module function wrapper.
+	xdContentsBuffer.push((kwArgs.xdDojoScopeName || "dojo") + "._xdResourceLoaded(function(" + scopeArgs + "){\n");
+
+	//See if there are any dojo.loadInit calls
+	var loadInitCalls = buildUtilXd.extractLoadInits(fileContents);
+	if(loadInitCalls){
+		//Adjust fileContents since extractLoadInits removed something.
+		fileContents = loadInitCalls[0];
+
+		//Add any loadInit calls to an array passed _xdResourceLoaded
+		for(i = 1; i < loadInitCalls.length; i++){
+			xdContentsBuffer.push(loadInitCalls[i] + ";\n");
+		}
+	}
+
+	xdContentsBuffer.push("return {");
+
+	//Add in dependencies section.
+	if(dependencies.length > 0){
+		xdContentsBuffer.push("depends: [");
+		for(i = 0; i < dependencies.length; i++){
+			if(i > 0){
+				xdContentsBuffer.push(",\n");
+			}
+			xdContentsBuffer.push("[" + dependencies[i] + "]");
+		}
+		xdContentsBuffer.push("],");
+	}
+	
+	//Add the contents of the file inside a function.
+	//Pass in module names to allow for multiple versions of modules in a page.
+	xdContentsBuffer.push("\ndefineResource: function(" + scopeArgs + "){");
+	//Remove requireLocalization calls, since that will mess things up.
+	//String() part is needed since fileContents is a Java object.
+	xdContentsBuffer.push(String(fileContents).replace(/dojo\.(requireLocalization|i18n\._preloadLocalizations)\([^\)]*\)/g, ""));
+	xdContentsBuffer.push("\n}};});");
+
+	return xdContentsBuffer.join("");
+}
+
+
+buildUtilXd.makeXdBundleContents = function(prefix, prefixPath, srcFileName, fileContents, prefixes, kwArgs){
+	//logger.info("Flattening bundle: " + srcFileName);
+
+	var bundleParts = i18nUtil.getBundlePartsFromFileName(prefix, prefixPath, srcFileName);
+	if(!bundleParts){
+		return null;
+	}
+	var moduleName = bundleParts.moduleName;
+	var bundleName = bundleParts.bundleName;
+	var localeName = bundleParts.localeName;
+	
+	//logger.trace("## moduleName: " + moduleName + ", bundleName: " + bundleName + ", localeName: " + localeName);
+	
+	//If this is a dojo bundle, it will have already been flattened via the normal build process.
+	//If it is an external bundle, then we didn't flatten it during the normal build process since
+	//right now, we don't make copies of the external module source files. Need to figure that out at some
+	//point, but for now, need to get flattened contents for external modules.
+	fileContents = (prefix.indexOf("dojo") == 0) ? fileContents : i18nUtil.makeFlatBundleContents(prefix, prefixPath, srcFileName);
+
+	//Final XD file contents.
+	fileContents = 'dojo.provide("' + moduleName + '.nls.' + (localeName ? localeName + '.' : '') + bundleName + '");'
+	                 + 'dojo._xdLoadFlattenedBundle("' + moduleName + '", "' + bundleName
+                   + '", "' + localeName + '", ' + fileContents + ');';
+
+	//Now make a proper xd.js file out of the content.
+	return buildUtilXd.makeXdContents(fileContents, prefixes, kwArgs);
+}
+
+buildUtilXd.loadInitRegExp = /dojo\.loadInit\s*\(/g;
+buildUtilXd.extractLoadInits = function(/*String*/fileContents){
+	return buildUtil.extractMatchedParens(buildUtilXd.loadInitRegExp, fileContents);
+}
diff --git a/util/buildscripts/jslib/checkBuildSize.js b/util/buildscripts/jslib/checkBuildSize.js
new file mode 100644
index 0000000..4c7a049
--- /dev/null
+++ b/util/buildscripts/jslib/checkBuildSize.js
@@ -0,0 +1,13 @@
+//assumes cwd of util/buildscripts
+
+//TODO: could take profile and compression option as args
+
+load("jslib/logger.js");
+load("jslib/fileUtil.js");
+load("jslib/buildUtil.js");
+
+var result = buildUtil.makeDojoJs(buildUtil.loadDependencyList(buildUtil.evalProfile("profiles/base.profile.js")), "0.0.0");
+
+var layer0 = buildUtil.optimizeJs(null, result[0].contents, null, "shrinksafe");
+print(layer0.length);
+
diff --git a/util/buildscripts/jslib/convertTestsToXDomain.js b/util/buildscripts/jslib/convertTestsToXDomain.js
new file mode 100644
index 0000000..74c56a6
--- /dev/null
+++ b/util/buildscripts/jslib/convertTestsToXDomain.js
@@ -0,0 +1,17 @@
+//Make a copy of the tests dir, then run this script, giving the location
+//of the tests copy, and the URL to use dojo.js
+
+var startDir = arguments[0];
+var xdDojoUrl = arguments[1];
+
+load("jslib/fileUtil.js");
+load("jslib/buildUtil.js");
+
+var fileList = fileUtil.getFilteredFileList(startDir, /\.(html|htm)$/, true);
+
+for(var i = 0; i < fileList.length; i++){
+	var fileName = fileList[i];	
+	var fileContents = fileUtil.readFile(fileName);
+	fileContents = fileContents.replace(/src\=\".*dojo.js"/, 'src="' + xdDojoUrl + '"');
+	fileUtil.saveUtf8File(fileName, fileContents);
+}
diff --git a/util/buildscripts/jslib/dojoGuardEnd.jsfrag b/util/buildscripts/jslib/dojoGuardEnd.jsfrag
new file mode 100644
index 0000000..7130263
--- /dev/null
+++ b/util/buildscripts/jslib/dojoGuardEnd.jsfrag
@@ -0,0 +1,12 @@
+	//INSERT dojo.i18n._preloadLocalizations HERE
+
+	//Check if document already complete, and if so, just trigger page load
+	//listeners. NOTE: does not work with Firefox before 3.6. To support
+	//those browsers, set djConfig.afterOnLoad = true when you know Dojo is added
+	//after page load. Using a timeout so the rest of this
+	//script gets evaluated properly. This work needs to happen after the
+	//dojo.config.require work done in dojo._base.
+	if(dojo.isBrowser && (document.readyState === "complete" || dojo.config.afterOnLoad)){
+		window.setTimeout(dojo._loadInit, 100);
+	}
+})();
diff --git a/util/buildscripts/jslib/dojoGuardStart.jsfrag b/util/buildscripts/jslib/dojoGuardStart.jsfrag
new file mode 100644
index 0000000..72cfb69
--- /dev/null
+++ b/util/buildscripts/jslib/dojoGuardStart.jsfrag
@@ -0,0 +1,39 @@
+;(function(){
+
+	/*
+	dojo, dijit, and dojox must always be the first three, and in that order.
+	djConfig.scopeMap = [
+		["dojo", "fojo"],
+		["dijit", "fijit"],
+		["dojox", "fojox"]
+	
+	]
+	*/
+
+	/**Build will replace this comment with a scoped djConfig **/
+
+	//The null below can be relaced by a build-time value used instead of djConfig.scopeMap.
+	var sMap = null;
+
+	//See if new scopes need to be defined.
+	if((sMap || (typeof djConfig != "undefined" && djConfig.scopeMap)) && (typeof window != "undefined")){
+		var scopeDef = "", scopePrefix = "", scopeSuffix = "", scopeMap = {}, scopeMapRev = {};
+		sMap = sMap || djConfig.scopeMap;
+		for(var i = 0; i < sMap.length; i++){
+			//Make local variables, then global variables that use the locals.
+			var newScope = sMap[i];
+			scopeDef += "var " + newScope[0] + " = {}; " + newScope[1] + " = " + newScope[0] + ";" + newScope[1] + "._scopeName = '" + newScope[1] + "';";
+			scopePrefix += (i == 0 ? "" : ",") + newScope[0];
+			scopeSuffix += (i == 0 ? "" : ",") + newScope[1];
+			scopeMap[newScope[0]] = newScope[1];
+			scopeMapRev[newScope[1]] = newScope[0];
+		}
+
+		eval(scopeDef + "dojo._scopeArgs = [" + scopeSuffix + "];");
+
+		dojo._scopePrefixArgs = scopePrefix;
+		dojo._scopePrefix = "(function(" + scopePrefix + "){";
+		dojo._scopeSuffix = "})(" + scopeSuffix + ")";
+		dojo._scopeMap = scopeMap;
+		dojo._scopeMapRev = scopeMapRev;
+	}
diff --git a/util/buildscripts/jslib/fileUtil.js b/util/buildscripts/jslib/fileUtil.js
new file mode 100644
index 0000000..1800e86
--- /dev/null
+++ b/util/buildscripts/jslib/fileUtil.js
@@ -0,0 +1,191 @@
+//Helper functions to deal with file I/O.
+
+var fileUtil = {};
+
+fileUtil.getLineSeparator = function(){
+	//summary: Gives the line separator for the platform.
+	//For web builds override this function.
+	return java.lang.System.getProperty("line.separator"); //Java String
+}
+
+fileUtil.getFilteredFileList = function(/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsJavaObject){
+	//summary: Recurses startDir and finds matches to the files that match regExpFilters.include
+	//and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
+	//and it will be treated as the "include" case.
+	//Ignores files/directories that start with a period (.).
+	var files = [];
+
+	var topDir = startDir;
+	if(!startDirIsJavaObject){
+		topDir = new java.io.File(startDir);
+	}
+
+	var regExpInclude = regExpFilters.include || regExpFilters;
+	var regExpExclude = regExpFilters.exclude || null;
+
+	if(topDir.exists()){
+		var dirFileArray = topDir.listFiles();
+		for (var i = 0; i < dirFileArray.length; i++){
+			var file = dirFileArray[i];
+			if(file.isFile()){
+				var filePath = file.getPath();
+				if(makeUnixPaths){
+					//Make sure we have a JS string.
+					filePath = new String(filePath);
+					if(filePath.indexOf("/") == -1){
+						filePath = filePath.replace(/\\/g, "/");
+					}
+				}
+				
+				var ok = true;
+				if(regExpInclude){
+					ok = filePath.match(regExpInclude);
+				}
+				if(ok && regExpExclude){
+					ok = !filePath.match(regExpExclude);
+				}
+
+				if(ok && !file.getName().match(/^\./)){
+					files.push(filePath);
+				}
+			}else if(file.isDirectory() && !file.getName().match(/^\./)){
+				var dirFiles = this.getFilteredFileList(file, regExpFilters, makeUnixPaths, true);
+				files.push.apply(files, dirFiles);
+			}
+		}
+	}
+
+	return files; //Array
+}
+
+
+fileUtil.copyDir = function(/*String*/srcDir, /*String*/destDir, /*RegExp*/regExpFilter, /*boolean?*/onlyCopyNew){
+	//summary: copies files from srcDir to destDir using the regExpFilter to determine if the
+	//file should be copied. Returns a list file name strings of the destinations that were copied.
+	var fileNames = fileUtil.getFilteredFileList(srcDir, regExpFilter, true);
+	var copiedFiles = [];
+	
+	for(var i = 0; i < fileNames.length; i++){
+		var srcFileName = fileNames[i];
+		var destFileName = srcFileName.replace(srcDir, destDir);
+
+		if(fileUtil.copyFile(srcFileName, destFileName, onlyCopyNew)){
+			copiedFiles.push(destFileName);
+		}
+	}
+
+	return copiedFiles.length ? copiedFiles : null; //Array or null
+}
+
+fileUtil.copyFile = function(/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew){
+	//summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
+	//srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
+	var destFile = new java.io.File(destFileName);
+
+	//logger.trace("Src filename: " + srcFileName);
+	//logger.trace("Dest filename: " + destFileName);
+
+	//If onlyCopyNew is true, then compare dates and only copy if the src is newer
+	//than dest.
+	if(onlyCopyNew){
+		var srcFile = new java.io.File(srcFileName);
+		if(destFile.exists() && destFile.lastModified() >= srcFile.lastModified()){
+			return false; //Boolean
+		}
+	}
+
+	//Make sure destination dir exists.
+	var parentDir = destFile.getParentFile();
+	if(!parentDir.exists()){
+		if(!parentDir.mkdirs()){
+			throw "Could not create directory: " + parentDir.getAbsolutePath();
+		}
+	}
+
+	//Java's version of copy file.
+	var srcChannel = new java.io.FileInputStream(srcFileName).getChannel();
+	var destChannel = new java.io.FileOutputStream(destFileName).getChannel();
+	destChannel.transferFrom(srcChannel, 0, srcChannel.size());
+	srcChannel.close();
+	destChannel.close();
+	
+	return true; //Boolean
+}
+
+fileUtil.readFile = function(/*String*/path, /*String?*/encoding){
+	//summary: reads a file and returns a string
+	encoding = encoding || "utf-8";
+	var file = new java.io.File(path);
+	var lineSeparator = fileUtil.getLineSeparator();
+	var input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding));
+	try{
+		var stringBuffer = new java.lang.StringBuffer();
+		var line = input.readLine();
+
+		// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
+		// http://www.unicode.org/faq/utf_bom.html
+		
+		// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
+		// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
+		if(line && line.length() && line.charAt(0) === 0xfeff){
+			// Eat the BOM, since we've already found the encoding on this file,
+			// and we plan to concatenating this buffer with others; the BOM should
+			// only appear at the top of a file.
+			line = line.substring(1);
+		}
+		while(line !== null){
+			stringBuffer.append(line);
+			stringBuffer.append(lineSeparator);
+			line = input.readLine();
+		}
+		//Make sure we return a JavaScript string and not a Java string.
+		return new String(stringBuffer.toString()); //String
+	}finally{
+		input.close();
+	}
+}
+
+fileUtil.saveUtf8File = function(/*String*/fileName, /*String*/fileContents){
+	//summary: saves a file using UTF-8 encoding.
+	fileUtil.saveFile(fileName, fileContents, "utf-8");
+}
+
+fileUtil.saveFile = function(/*String*/fileName, /*String*/fileContents, /*String?*/encoding){
+	//summary: saves a file.
+	var outFile = new java.io.File(fileName);
+	var outWriter;
+	
+	var parentDir = outFile.getParentFile();
+	if(!parentDir.exists()){
+		if(!parentDir.mkdirs()){
+			throw "Could not create directory: " + parentDir.getAbsolutePath();
+		}
+	}
+	
+	if(encoding){
+		outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding);
+	}else{
+		outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
+	}
+
+	var os = new java.io.BufferedWriter(outWriter);
+	try{
+		os.write(fileContents);
+	}finally{
+		os.close();
+	}
+}
+
+fileUtil.deleteFile = function(/*String*/fileName){
+	//summary: deletes a file or directory if it exists.
+	var file = new java.io.File(fileName);
+	if(file.exists()){
+		if(file.isDirectory()){
+			var files = file.listFiles();
+			for(var i = 0; i < files.length; i++){
+				this.deleteFile(files[i]);
+			}
+		}
+		file["delete"]();
+	}
+}
diff --git a/util/buildscripts/jslib/i18nUtil.js b/util/buildscripts/jslib/i18nUtil.js
new file mode 100644
index 0000000..73fa6fa
--- /dev/null
+++ b/util/buildscripts/jslib/i18nUtil.js
@@ -0,0 +1,334 @@
+i18nUtil = {};
+
+i18nUtil.setup = function(/*Object*/kwArgs){
+	//summary: loads dojo so we can use it for i18n bundle flattening.
+	
+	//Do the setup only if it has not already been done before.
+	if(typeof djConfig == "undefined" || !(typeof dojo != "undefined" && dojo["i18n"])){
+		djConfig={
+			locale: 'xx',
+			extraLocale: kwArgs.localeList,
+			baseUrl: buildScriptsPath + "../../dojo/"
+		};
+
+		load(buildScriptsPath + '../../dojo/dojo.js');
+
+		//Now set baseUrl so it is current directory, since all the prefixes
+		//will be relative to the release dir from this directory.
+		dojo.baseUrl = "./";
+
+		//Also be sure we register the right paths for module prefixes.
+		buildUtil.configPrefixes(kwArgs.profileProperties.dependencies.prefixes);
+
+		dojo.require("dojo.i18n");
+	}
+}
+
+i18nUtil.flattenLayerFileBundles = function(/*String*/fileName, /*String*/fileContents, /*Object*/kwArgs){
+	//summary:
+	//		This little utility is invoked by the build to flatten all of the JSON resource bundles used
+	//		by dojo.requireLocalization(), much like the main build itself, to optimize so that multiple
+	//		web hits will not be necessary to load these resources.  Normally, a request for a particular
+	//		bundle in a locale like "en-us" would result in three web hits: one looking for en_us/ another
+	//		for en/ and another for ROOT/.  All of this multiplied by the number of bundles used can result
+	//		in a lot of web hits and latency.  This script uses Dojo to actually load the resources into
+	//		memory, then flatten the object and spit it out using dojo.toJson.  The bootstrap
+	//		will be modified to download exactly one of these files, whichever is closest to the user's
+	//		locale.
+	//fileName:
+	//		The name of the file to process (like dojo.js). This function will use
+	//		it to determine the best resource name to give the flattened bundle.
+	//fileContents:
+	//		The contents of the file to process (like dojo.js). This function will look in
+	//		the contents for dojo.requireLocation() calls.
+	//kwArgs:
+	//		The build's kwArgs.
+	
+	var destDirName = fileName.replace(/\/[^\/]+$/, "/") + "nls";
+	var nlsNamePrefix = fileName.replace(/\.js$/, "");
+	nlsNamePrefix = nlsNamePrefix.substring(nlsNamePrefix.lastIndexOf("/") + 1, nlsNamePrefix.length);
+
+	i18nUtil.setup(kwArgs);
+	var djLoadedBundles = [];
+	
+	//TODO: register plain function handler (output source) in jsonRegistry?
+	var drl = dojo.requireLocalization;
+	var dupes = {};
+	dojo.requireLocalization = function(modulename, bundlename, locale){
+		var dupName = [modulename, bundlename, locale].join(":");
+		if(!dupes[dupName]){
+			drl(modulename, bundlename, locale);
+			djLoadedBundles.push({modulename: modulename, module: eval(modulename), bundlename: bundlename});
+			dupes[dupName] = 1;
+		}
+	};
+	
+	var requireStatements = fileContents.match(/dojo\.requireLocalization\(.*\)\;/g);
+	if(requireStatements){	
+		eval(requireStatements.join(";"));
+
+		//print("loaded bundles: "+djLoadedBundles.length);
+		
+		var djBundlesByLocale = {};
+		var jsLocale, entry, bundle;
+		
+		for (var i = 0; i < djLoadedBundles.length; i++){
+			entry = djLoadedBundles[i];
+			bundle = entry.module.nls[entry.bundlename];
+			for (jsLocale in bundle){
+				if (!djBundlesByLocale[jsLocale]){djBundlesByLocale[jsLocale]=[];}
+				djBundlesByLocale[jsLocale].push(entry);
+			}
+		}
+		
+		localeList = [];
+		
+		//Save flattened bundles used by dojo.js.
+		var mkdir = false;
+		var dir = new java.io.File(destDirName);
+		var modulePrefix = buildUtil.mapPathToResourceName(fileName, kwArgs.profileProperties.dependencies.prefixes);
+
+		//Adjust modulePrefix to include the nls part before the last segment.
+		var lastDot = modulePrefix.lastIndexOf(".");
+		if(lastDot != -1){
+			modulePrefix = modulePrefix.substring(0, lastDot + 1) + "nls." + modulePrefix.substring(lastDot + 1, modulePrefix.length);
+		}else{
+			throw "Invalid module prefix for flattened bundle: " + modulePrefix;
+		}
+
+		for (jsLocale in djBundlesByLocale){
+			var locale = jsLocale.replace(/\_/g, '-');
+			if(!mkdir){ dir.mkdir(); mkdir = true; }
+			
+			var outFile = new java.io.File(dir, nlsNamePrefix + "_" + locale + ".js");
+			//Make sure we can create the final file.
+			var parentDir = outFile.getParentFile();
+			if(!parentDir.exists()){
+				if(!parentDir.mkdirs()){
+					throw "Could not create directory: " + parentDir.getAbsolutePath();
+				}
+			}
+
+			var os = new java.io.BufferedWriter(
+					new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), "utf-8"));
+			try{
+				os.write("dojo.provide(\""+modulePrefix+"_"+locale+"\");");
+				for (var j = 0; j < djLoadedBundles.length; j++){
+					entry = djLoadedBundles[j];
+					var bundlePkg = [entry.modulename,"nls",entry.bundlename].join(".");
+					var translationPkg = [bundlePkg,jsLocale].join(".");
+					bundle = entry.module.nls[entry.bundlename];
+					if(bundle[jsLocale]){ //FIXME:redundant check?
+						os.write("dojo.provide(\""+bundlePkg+"\");");
+						os.write(bundlePkg+"._built=true;");
+						os.write("dojo.provide(\""+translationPkg+"\");");
+						os.write(translationPkg+"="+dojo.toJson(bundle[jsLocale])+";");
+					}
+				}
+			}finally{
+				os.close();
+			}
+			localeList.push(locale);
+		}
+		
+		//Remove dojo.requireLocalization calls from the file.
+		fileContents = fileContents.replace(/dojo\.requireLocalization\(.*\)\;/g, "");
+
+
+		var preloadCall = '\ndojo.i18n._preloadLocalizations("' + modulePrefix + '", ' + dojo.toJson(localeList.sort()) + ');\n';
+		//Inject the dojo._preloadLocalizations call into the file.
+		//Do this at the end of the file, since we need to make sure dojo.i18n has been loaded.
+		//The assumption is that if dojo.i18n is not in this layer file, dojo.i18n is
+		//in one of the layer files this layer file depends on.
+		//Allow call to be inserted in the dojo.js closure, if that is in play.
+		i18nUtil.preloadInsertionRegExp.lastIndex = 0;
+		if(fileContents.match(i18nUtil.preloadInsertionRegExp)){
+			i18nUtil.preloadInsertionRegExp.lastIndex = 0;
+			fileContents = fileContents.replace(i18nUtil.preloadInsertionRegExp, preloadCall);
+		}else{
+			fileContents += preloadCall;
+		}
+	}
+
+	return fileContents; //String
+}
+
+i18nUtil.preloadInsertionRegExp = /\/\/INSERT dojo.i18n._preloadLocalizations HERE/;
+
+i18nUtil.flattenDirBundles = function(/*String*/prefixName, /*String*/prefixDir, /*Object*/kwArgs, /*RegExp*/nlsIgnoreRegExp){
+	//summary: Flattens the i18n bundles inside a directory so that only request
+	//is needed per bundle. Does not handle resource flattening for dojo.js or
+	//layered build files.
+
+	i18nUtil.setup(kwArgs);
+	var fileList = fileUtil.getFilteredFileList(prefixDir, /\.js$/, true);
+	var prefixes = kwArgs.profileProperties.dependencies.prefixes;
+	for(var i= 0; i < fileList.length; i++){
+		//Use new String so we get a JS string and not a Java string.
+		var jsFileName = String(fileList[i]);
+		var fileContents = null;
+		
+		//Files in nls directories, except for layer bundles that already have been processed.
+		if(jsFileName.match(/\/nls\//) && !jsFileName.match(nlsIgnoreRegExp)){
+			fileContents = "(" + i18nUtil.makeFlatBundleContents(prefixName, prefixDir, jsFileName) + ")";			
+		}else{
+			fileContents = i18nUtil.modifyRequireLocalization(readText(jsFileName), prefixes);
+		}
+
+		if(fileContents){
+			fileUtil.saveUtf8File(jsFileName, fileContents);
+		}
+	}
+}
+
+i18nUtil.modifyRequireLocalization = function(/*String*/fileContents, /*Array*/prefixes){
+	//summary: Modifies any dojo.requireLocalization calls in the fileContents to have the
+	//list of supported locales as part of the call. This allows the i18n loading functions
+	//to only make request(s) for locales that actually exist on disk.
+	var dependencies = [];
+	
+	//Make sure we have a JS string, and not a Java string.
+	fileContents = String(fileContents);
+	
+	var modifiedContents = fileContents;
+	
+	if(fileContents.match(buildUtil.globalRequireLocalizationRegExp)){
+		modifiedContents = fileContents.replace(buildUtil.globalRequireLocalizationRegExp, function(matchString){
+			var replacement = matchString;
+			var partMatches = matchString.match(buildUtil.requireLocalizationRegExp);
+			var depCall = partMatches[1];
+			var depArgs = partMatches[2];
+	
+			if(depCall == "requireLocalization"){
+				//Need to find out what locales are available so the dojo loader
+				//only has to do one script request for the closest matching locale.
+				var reqArgs = i18nUtil.getRequireLocalizationArgsFromString(depArgs);
+				if(reqArgs.moduleName){
+					//Find the list of locales supported by looking at the path names.
+					var locales = i18nUtil.getLocalesForBundle(reqArgs.moduleName, reqArgs.bundleName, prefixes);
+	
+					//Add the supported locales to the requireLocalization arguments.
+					if(!reqArgs.localeName){
+						depArgs += ", null";
+					}
+	
+					depArgs += ', "' + locales.join(",") + '"';
+					
+					replacement = "dojo." + depCall + "(" + depArgs + ")";
+				}
+			}
+			return replacement;		
+		});
+	}	
+	return modifiedContents;
+}
+
+i18nUtil.makeFlatBundleContents = function(prefix, prefixPath, srcFileName){
+	//summary: Given a nls file name, flatten the bundles from parent locales into the nls bundle.
+	var bundleParts = i18nUtil.getBundlePartsFromFileName(prefix, prefixPath, srcFileName);
+	if(!bundleParts){
+		return null;
+	}
+	var moduleName = bundleParts.moduleName;
+	var bundleName = bundleParts.bundleName;
+	var localeName = bundleParts.localeName;
+
+	dojo.requireLocalization(moduleName, bundleName, localeName);
+	
+	//Get the generated, flattened bundle.
+	var module = dojo.getObject(moduleName);
+	var bundleLocale = localeName ? localeName.replace(/-/g, "_") : "ROOT";
+	var flattenedBundle = module.nls[bundleName][bundleLocale];
+	
+	if(!flattenedBundle){
+		throw "Cannot create flattened bundle for src file: " + srcFileName;
+	}
+
+	return dojo.toJson(flattenedBundle);
+}
+
+//Given a module and bundle name, find all the supported locales.
+i18nUtil.getLocalesForBundle = function(moduleName, bundleName, prefixes){
+	//Build a path to the bundle directory and ask for all files that match
+	//the bundle name.
+	var filePath = buildUtil.mapResourceToPath(moduleName, prefixes);
+	
+	var bundleRegExp = new RegExp("nls[/]?([\\w\\-]*)/" + bundleName + ".js$");
+	var bundleFiles = fileUtil.getFilteredFileList(filePath + "nls/", bundleRegExp, true);
+	
+	//Find the list of locales supported by looking at the path names.
+	var locales = [];
+	for(var j = 0; j < bundleFiles.length; j++){
+		var bundleParts = bundleFiles[j].match(bundleRegExp);
+		if(bundleParts && bundleParts[1]){
+			locales.push(bundleParts[1]);
+		}else{
+			locales.push("ROOT");
+		}
+	}
+
+	return locales.sort();
+}
+
+i18nUtil.getRequireLocalizationArgsFromString = function(argString){
+	//summary: Given a string of the arguments to a dojo.requireLocalization
+	//call, separate the string into individual arguments.
+	var argResult = {
+		moduleName: null,
+		bundleName: null,
+		localeName: null
+	};
+	
+	var l10nMatches = argString.split(/\,\s*/);
+	if(l10nMatches && l10nMatches.length > 1){
+		argResult.moduleName = l10nMatches[0] ? l10nMatches[0].replace(/\"/g, "") : null;
+		argResult.bundleName = l10nMatches[1] ? l10nMatches[1].replace(/\"/g, "") : null;
+		argResult.localeName = l10nMatches[2];
+	}
+	return argResult;
+}
+
+i18nUtil.getBundlePartsFromFileName = function(prefix, prefixPath, srcFileName){
+	//Pull off any ../ values from prefix path to make matching easier.
+	var prefixPath = prefixPath.replace(/\.\.\//g, "");
+
+	//Strip off the prefix path so we can find the real resource and bundle names.
+	var prefixStartIndex = srcFileName.lastIndexOf(prefixPath);
+	if(prefixStartIndex != -1){
+		var startIndex = prefixStartIndex + prefixPath.length;
+		
+		//Need to add one if the prefiPath does not include an ending /. Otherwise,
+		//We'll get extra dots in our bundleName.
+		if(prefixPath.charAt(prefixPath.length) != "/"){
+			startIndex += 1;
+		}
+		srcFileName = srcFileName.substring(startIndex, srcFileName.length);
+	}
+	
+	//var srcIndex = srcFileName.indexOf("src/");
+	//srcFileName = srcFileName.substring(srcIndex + 4, srcFileName.length);
+	var parts = srcFileName.split("/");
+
+	//Split up the srcFileName into arguments that can be used for dojo.requireLocalization()
+	var moduleParts = [prefix];
+	for(var i = 0; parts[i] != "nls"; i++){
+		moduleParts.push(parts[i]);
+	}
+	var moduleName = moduleParts.join(".");
+	if(parts[i+1].match(/\.js$/)){
+		var localeName = "";
+		var bundleName = parts[i+1];
+	}else{
+		var localeName = parts[i+1];
+		var bundleName = parts[i+2];	
+	}
+
+	if(!bundleName || bundleName.indexOf(".js") == -1){
+		//Not a valid bundle. Could be something like a README file.
+		return null;
+	}else{
+		bundleName = bundleName.replace(/\.js/, "");
+	}
+
+	return {moduleName: moduleName, bundleName: bundleName, localeName: localeName};
+}
diff --git a/util/buildscripts/jslib/logger.js b/util/buildscripts/jslib/logger.js
new file mode 100644
index 0000000..7bb394f
--- /dev/null
+++ b/util/buildscripts/jslib/logger.js
@@ -0,0 +1,36 @@
+var logger = {
+	TRACE: 0,
+	INFO: 1,
+	WARN: 2,
+	ERROR: 3,
+	level: 0,
+	logPrefix: "",
+
+	trace: function(message){
+		if(this.level <= this.TRACE){
+			this._print(message);
+		}
+	},
+
+	info: function(message){
+		if(this.level <= this.INFO){
+			this._print(message);
+		}
+	},
+
+	warn: function(message){
+		if(this.level <= this.WARN){
+			this._print(message);
+		}
+	},
+
+	error: function(message){
+		if(this.level <= this.ERROR){
+			this._print(message);
+		}
+	},
+
+	_print: function(message){
+		print((this.logPrefix ? (this.logPrefix + " ") : "") + message);
+	}
+}
diff --git a/util/buildscripts/listProfileDeps.js b/util/buildscripts/listProfileDeps.js
new file mode 100644
index 0000000..52cd5b6
--- /dev/null
+++ b/util/buildscripts/listProfileDeps.js
@@ -0,0 +1,18 @@
+//START of the "main" part of the script.
+//This is the entry point for this script file.
+load("jslib/logger.js");
+load("jslib/fileUtil.js");
+load("jslib/buildUtil.js");
+
+var profileFile = arguments[0];
+var lineSeparator = java.lang.System.getProperty("line.separator");
+
+var result = buildUtil.loadDependencyList(buildUtil.evalProfile(profileFile));
+
+var buildText = "Files included in this profile:" + lineSeparator;
+for(var i = 0; i < result.length; i++){
+	buildText += lineSeparator + result[i].layerName + ":" + lineSeparator;
+	buildText += result[i].depList.join(lineSeparator) + lineSeparator;
+}
+
+print(buildText);
diff --git a/util/buildscripts/makeDojoJsWeb.js b/util/buildscripts/makeDojoJsWeb.js
new file mode 100644
index 0000000..c24619b
--- /dev/null
+++ b/util/buildscripts/makeDojoJsWeb.js
@@ -0,0 +1,103 @@
+//START of the "main" part of the script.
+//This is the entry point for this script file.
+load("buildUtil.js");
+load("buildUtilXd.js");
+
+var result = "ERROR";
+
+var buildDirectory = new String(arguments[0]);
+var depList = new String(arguments[1]);
+var provideList = new String(arguments[2]);
+var version = new String(arguments[3]);
+var xdDojoUrl = new String(arguments[4]);
+
+depList = depList.split(",");
+
+//Check if there were no provideList (the caller can send string "null"
+//to indicate that the command line parameter is empty. We need some string
+//to make sure all the arguments are in the right spot.
+if(provideList == "null"){
+	provideList = "[]";
+}else{
+	provideList = provideList.split(",");
+	provideList = '["' + provideList.join('","') + '"]';
+}
+
+var dependencyResult;
+eval('dependencyResult = {depList: ["' + depList.join('","') + '"], provideList: ' + provideList + '};');
+
+//Make sure we are dealing with JS files and that the paths are not outside
+//of the working area. Do this to discourage fetching arbitrary files from
+//the server.
+var deps = dependencyResult.depList;
+var isInputOk = true;
+for(var i = 0; i < deps.length; i++){
+	var matches = deps[i].match(/\.\./g);
+	if((matches && matches.length > 1) || !deps[i].match(/\.js$/) || deps[i].indexOf(0) == '/'){
+		print("Error: Invalid file set.");
+		isInputOk = false;
+		break;
+	}
+}
+
+if(isInputOk){
+	//Load dojo (needed for string interning)
+	djConfig={
+		baseRelativePath: "../"
+	};
+	load('../dojo.js');
+	dojo.require("dojo.string.extras");
+	dojo.require("dojo.crypto.MD5");
+
+	var buildSigDir = dojo.crypto.MD5.compute(depList.sort().join(","), dojo.crypto.outputTypes.Hex);
+	try{
+		//xxx createLayerContents is broken: need kwargs? it is optional but probably should provide it.
+		var contents = buildUtil.createLayerContents(dependencyResult.depList, dependencyResult.provideList, version);
+		var compressedContents = "";
+		var prefixes = [["dojo", "src"]];
+	
+		//Make sure any dojo.requireLocalization calls are modified
+		//so that they inform the loader of valid locales that can be loaded.
+		contents = buildUtil.modifyRequireLocalization(contents, prefixes);
+
+		//Intern strings.
+		contents = buildUtil.interningRegexpMagic("xdomain", contents, djConfig.baseRelativePath, prefixes, [], true);
+		
+		//Set the xdomain dojo url
+		if(xdDojoUrl){
+			contents = buildUtilXd.setXdDojoConfig(contents, xdDojoUrl);
+		}
+
+		//Compress code.
+		compressedContents = buildUtil.optimizeJs("dojo.js", contents, "", "shrinksafe");
+
+		//Add copyright
+		var copyright = fileUtil.readFile("copyright.txt");
+		var buildNotice = fileUtil.readFile("build_notice.txt");
+		contents = copyright + buildNotice + contents;
+		compressedContents = copyright + buildNotice + compressedContents;
+		
+		//Prep cache location
+		var buildCachePath = buildDirectory + "/" + buildSigDir + "/";
+
+		//Create needed directories for cache location.
+		var dirFile = new java.io.File(buildCachePath + "compressed");
+		var dirsOk = dirFile.mkdirs();
+
+		result = "dirFile: " + dirFile.getAbsolutePath() + ", dirsOK: " + dirsOk;
+		
+		//Create build contents file
+		var buildContents = dependencyResult.provideList.sort().join("\n");
+
+		//Save files to disk
+		fileUtil.saveUtf8File(buildCachePath + "dojo.js", contents);
+		fileUtil.saveUtf8File(buildCachePath + "compressed/dojo.js", compressedContents);
+		fileUtil.saveUtf8File(buildCachePath + "build.txt", buildContents);
+		
+		result = "OK";
+	}catch(e){
+		result = "ERROR: " + e;	
+	}
+
+	print(result);
+}
diff --git a/util/buildscripts/mk_branch.sh b/util/buildscripts/mk_branch.sh
new file mode 100755
index 0000000..b0c202d
--- /dev/null
+++ b/util/buildscripts/mk_branch.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+#version should be something like 0.9.0beta or 0.9.0
+name=$1
+#The svn revision number to use for tag. Should be a number, like 11203
+svnRevision=$2
+
+#If no svnRevision number, get the latest one from he repo.
+if [ "$svnRevision" = "" ]; then
+    svnRevision=`svn info http://svn.dojotoolkit.org/src/util/trunk/buildscripts/build_release.sh | grep Revision | sed 's/Revision: //'`
+fi
+
+svn mkdir -m "Using r$svnRevision to create a branch named $name." https://svn.dojotoolkit.org/src/branches/$name
+svn copy -r $svnRevision https://svn.dojotoolkit.org/src/dojo/trunk  https://svn.dojotoolkit.org/src/branches/$name/dojo -m "Using r$svnRevision to create a branch named $name."
+svn copy -r $svnRevision https://svn.dojotoolkit.org/src/dijit/trunk https://svn.dojotoolkit.org/src/branches/$name/dijit -m "Using r$svnRevision to create a branch named $name."
+svn copy -r $svnRevision https://svn.dojotoolkit.org/src/dojox/trunk https://svn.dojotoolkit.org/src/branches/$name/dojox -m "Using r$svnRevision to create a branch named $name."
+svn copy -r $svnRevision https://svn.dojotoolkit.org/src/util/trunk  https://svn.dojotoolkit.org/src/branches/$name/util -m "Using r$svnRevision to create a branch named $name."
+svn copy -r $svnRevision https://svn.dojotoolkit.org/src/demos/trunk https://svn.dojotoolkit.org/src/branches/$name/demos -m "Using r$svnRevision to create a branch named $name."
+
diff --git a/util/buildscripts/profiles/base.profile.js b/util/buildscripts/profiles/base.profile.js
new file mode 100644
index 0000000..66d5bfa
--- /dev/null
+++ b/util/buildscripts/profiles/base.profile.js
@@ -0,0 +1 @@
+//To build just Dojo base, you just need an empty file.
diff --git a/util/buildscripts/profiles/baseplus.profile.js b/util/buildscripts/profiles/baseplus.profile.js
new file mode 100644
index 0000000..19e517d
--- /dev/null
+++ b/util/buildscripts/profiles/baseplus.profile.js
@@ -0,0 +1,21 @@
+dependencies = {
+	layers: [
+		{
+			// This is a specially named layer, literally 'dojo.js'
+			// adding dependencies to this layer will include the modules
+			// in addition to the standard dojo.js base APIs. 
+			name: "dojo.js",
+			dependencies: [
+				"dijit._Widget", 
+				"dijit._Templated",
+				"dojo.fx",
+				"dojo.NodeList-fx"
+			]
+		}
+	],
+
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ]
+	]
+}
diff --git a/util/buildscripts/profiles/cometd.profile.js b/util/buildscripts/profiles/cometd.profile.js
new file mode 100644
index 0000000..47d8cb8
--- /dev/null
+++ b/util/buildscripts/profiles/cometd.profile.js
@@ -0,0 +1,15 @@
+dependencies = {
+	layers: [
+		{
+			name: "../dojox/cometd.js",
+			dependencies: [
+				"dojox.cometd"
+			]
+		}
+	],
+
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ]
+	]
+};
diff --git a/util/buildscripts/profiles/demos-all.profile.js b/util/buildscripts/profiles/demos-all.profile.js
new file mode 100644
index 0000000..c0dc3d3
--- /dev/null
+++ b/util/buildscripts/profiles/demos-all.profile.js
@@ -0,0 +1,107 @@
+// This is the demos-all profile, which mimics the nightly checkout/build profile, but adds in the demos/
+// repo for easy debugging. We are not to link to the demos in nightly in a static fashion, but rather use
+// this repo as a testing place for versioned demos to be pushed onto dojotoolkit.org 
+dependencies = {
+	layers: [
+		// standard:
+		{
+			name: "../dijit/dijit.js",
+			dependencies: [
+				"dijit.dijit"
+			]
+		},
+		{
+			name: "../dijit/dijit-all.js",
+			layerDependencies: [
+				"../dijit/dijit.js"
+			],
+			dependencies: [
+				"dijit.dijit-all"
+			]
+		},
+			
+		// Here are the various demos with promotion:
+		{
+			// the dojo.moj.oe demo
+			name: "../demos/mojo/src.js",
+			dependencies: [
+				"demos.mojo.src"
+			]
+		},
+		{
+			// the dojo.workers() demo
+			name: "../demos/skew/src.js",
+			dependencies: [
+				"demos.skew.src"
+			]
+		},
+		{
+			// the mail app demo
+			name: "../demos/mail/src.js",
+			dependencies: [
+				"demos.mail.src"
+			]
+		},
+		{
+			// the i18n / flags demo
+			name: "../demos/i18n/src.js",
+			dependencies: [
+				"demos.i18n.src"
+			]
+		},
+		{
+			// the FlashCard demo
+			name: "../demos/flashCards/src.js",
+			dependencies: [
+				"demos.flashCards.src"
+			]
+		},
+		{
+			// the CastleParty demo
+			name: "../demos/castle/src.js",
+			dependencies: [
+				"demos.castle.src"
+			]
+		},
+		{
+			// the Image Preview demo:
+			name: "../demos/cropper/src.js",
+			dependencies:[
+				"demos.cropper.src"
+			]
+		},
+		{
+			// the Survey demo
+			name: "../demos/survey/src.js",
+			dependencies:[
+				"demos.survey.src"
+			]
+		},
+		{
+			// the BabelChat demo
+			name: "../demos/babelChat/src.js",
+			dependencies:[
+				"demos.babelChat.src"
+			]
+		},
+		{
+			name: "../demos/faces/src.js",
+			dependencies:[
+				"demos.faces.src"
+			]
+		},
+		{
+			// the CSS3 animations demo
+			name: "../demos/css3/src.js",
+			dependencies:[
+				"demos.css3.src"
+			]
+		}
+	],
+	
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ],
+		[ "demos", "../demos" ]
+	]
+}
diff --git a/util/buildscripts/profiles/dtkapi.profile.js b/util/buildscripts/profiles/dtkapi.profile.js
new file mode 100644
index 0000000..9457669
--- /dev/null
+++ b/util/buildscripts/profiles/dtkapi.profile.js
@@ -0,0 +1,17 @@
+dependencies = {
+	layers: [
+		{
+			name: "../dojo/dtkapi.js",
+			dependencies: [
+				"dojox.widget.Dialog",
+				"dojo.fx.easing"
+			]
+		}
+	],
+
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ]
+	]
+};
+
diff --git a/util/buildscripts/profiles/fx.profile.js b/util/buildscripts/profiles/fx.profile.js
new file mode 100644
index 0000000..bf0babd
--- /dev/null
+++ b/util/buildscripts/profiles/fx.profile.js
@@ -0,0 +1,18 @@
+dependencies = {
+	layers: [
+		{
+			name: "../dojox/fx.js",
+			dependencies: [
+				"dojo.NodeList-fx",
+				"dojox.fx.ext-dojo.NodeList",
+				"dojox.fx",
+				"dojo.fx.easing"
+			]
+		}
+	],
+
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ]
+	]
+};
diff --git a/util/buildscripts/profiles/layers.profile.js b/util/buildscripts/profiles/layers.profile.js
new file mode 100644
index 0000000..b35d68f
--- /dev/null
+++ b/util/buildscripts/profiles/layers.profile.js
@@ -0,0 +1,66 @@
+//This profile is used just to illustrate the layout of a layered build.
+//All layers have an implicit dependency on dojo.js.
+
+//Normally you should not specify a layer object for dojo.js. It is normally
+//implicitly built containing the dojo "base" functionality (dojo._base).
+//However, if you prefer the Dojo 0.4.x build behavior, you can specify a
+//"dojo.js" layer to get that behavior. It is shown below, but the normal
+//0.9 approach is to *not* specify it.
+
+//
+
+dependencies = {
+	layers: [
+		{
+			//For 0.9 you normally do not specify a dojo.js layer.
+			//Note that you do not need to specify dojo.js as a dependency for
+			//other layers -- it is always an implicit dependency.
+			name: "dojo.js",
+			dependencies: [
+				"dojo.parser"
+			]
+		},
+		{
+			//This layer will be discarded, it is just used
+			//to specify some modules that should not be included
+			//in a later layer, but something that should not be
+			//saved as an actual layer output. The important property
+			//is the "discard" property. If set to true, then the layer
+			//will not be a saved layer in the release directory.
+			name: "string.discard",
+			resourceName: "string.discard",
+			discard: true,
+			//Path to the copyright file must be relative to
+			//the util/buildscripts directory, or an absolute path.
+			copyrightFile: "myCopyright.txt",
+			dependencies: [
+				"dojo.string"
+			]
+		},
+		{
+			name: "../dijit/dijit.js",
+			resourceName: "dijit.dijit",
+			layerDependencies: [
+			"string.discard"
+			],
+			dependencies: [
+				"dijit.dijit"
+			]
+		}
+	],
+
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ]
+	]
+}
+
+//If you choose to optimize the JS files in a prefix directory (via the optimize= build parameter),
+//you can choose to have a custom copyright text prepended to the optimized file. To do this, specify
+//the path to a file tha contains the copyright info as the third array item in the prefixes array. For
+//instance:
+//	prefixes: [
+//		[ "mycompany", "/path/to/mycompany", "/path/to/mycompany/copyright.txt"]
+//	]
+//
+//	If no copyright is specified in this optimize case, then by default, the dojo copyright will be used.
diff --git a/util/buildscripts/profiles/rhino.profile.js b/util/buildscripts/profiles/rhino.profile.js
new file mode 100644
index 0000000..9e02fb1
--- /dev/null
+++ b/util/buildscripts/profiles/rhino.profile.js
@@ -0,0 +1,16 @@
+/*This profile demonstrates how to do a custom build for the Rhino environment.
+  You only need to include the "shrinksafe" prefix entry below if you want to 
+  be able to run the DOH unit tests directly from the release directory.
+*/
+
+hostenvType = "rhino";
+
+dependencies = {
+	layers: [
+	],
+
+	prefixes: [
+		[ "dojox", "../dojox" ],
+		[ "shrinksafe", "../util/shrinksafe" ]
+	]
+};
diff --git a/util/buildscripts/profiles/sql.profile.js b/util/buildscripts/profiles/sql.profile.js
new file mode 100644
index 0000000..c9c8820
--- /dev/null
+++ b/util/buildscripts/profiles/sql.profile.js
@@ -0,0 +1,21 @@
+dependencies = {
+	//This option configures dojox.storage to just include the Gears
+	//storage provider for an offline use.
+	dojoxStorageBuildOption: "offline",
+
+	layers: [
+		{
+			name: "../dojox/sql.js",
+			layerDependencies: [
+			],
+			dependencies: [
+				"dojox.sql"
+			]
+		}
+	],
+
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ]
+	]
+}
diff --git a/util/buildscripts/profiles/standard.profile.js b/util/buildscripts/profiles/standard.profile.js
new file mode 100644
index 0000000..8ee6935
--- /dev/null
+++ b/util/buildscripts/profiles/standard.profile.js
@@ -0,0 +1,66 @@
+dependencies = {
+	//Strip all console.* calls except console.warn and console.error. This is basically a work-around
+	//for trac issue: http://bugs.dojotoolkit.org/ticket/6849 where Safari 3's console.debug seems
+	//to be flaky to set up (apparently fixed in a webkit nightly).
+	//But in general for a build, console.warn/error should be the only things to survive anyway.
+	stripConsole: "normal",
+
+	layers: [
+		{
+			name: "../dijit/dijit.js",
+			dependencies: [
+				"dijit.dijit"
+			]
+		},
+		{
+			name: "../dijit/dijit-all.js",
+			layerDependencies: [
+				"../dijit/dijit.js"
+			],
+			dependencies: [
+				"dijit.dijit-all"
+			]
+		},
+		{
+			name: "../dojox/grid/DataGrid.js",
+			dependencies: [
+				"dojox.grid.DataGrid"
+			]
+		},
+		{
+			name: "../dojox/gfx.js",
+			dependencies: [
+				"dojox.gfx"
+			]
+		},
+		// FIXME: 
+		//		we probably need a better structure for this layer and need to
+		//		add some of the most common themes
+		{
+			name: "../dojox/charting/widget/Chart2D.js",
+			dependencies: [
+				"dojox.charting.widget.Chart2D",
+				"dojox.charting.widget.Sparkline",
+				"dojox.charting.widget.Legend"
+			]
+		},
+		{
+			name: "../dojox/dtl.js",
+			dependencies: [
+				"dojox.dtl",
+				"dojox.dtl.Context",
+				"dojox.dtl.tag.logic",
+				"dojox.dtl.tag.loop",
+				"dojox.dtl.tag.date",
+				"dojox.dtl.tag.loader",
+				"dojox.dtl.tag.misc",
+				"dojox.dtl.ext-dojo.NodeList"
+			]
+		}
+	],
+
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ]
+	]
+}
diff --git a/util/buildscripts/profiles/standardCustomBase.profile.js b/util/buildscripts/profiles/standardCustomBase.profile.js
new file mode 100644
index 0000000..c4151cf
--- /dev/null
+++ b/util/buildscripts/profiles/standardCustomBase.profile.js
@@ -0,0 +1,40 @@
+dependencies = {
+	layers: [
+		{
+			name: "dojo.js",
+			customBase: true,
+			dependencies: [
+			]
+		},
+		{
+			name: "_base.js",
+			customBase: true,
+			layerDependencies: [
+				"dojo.js"
+			],
+			dependencies: [
+				"dojo._base"
+			]
+		},
+		{
+			name: "../dijit/dijit.js",
+			dependencies: [
+				"dijit.dijit"
+			]
+		},
+		{
+			name: "../dijit/dijit-all.js",
+			layerDependencies: [
+				"../dijit/dijit.js"
+			],
+			dependencies: [
+				"dijit.dijit-all"
+			]
+		}
+	],
+
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ]
+	]
+}
diff --git a/util/buildscripts/profiles/storage.profile.js b/util/buildscripts/profiles/storage.profile.js
new file mode 100644
index 0000000..3c4df23
--- /dev/null
+++ b/util/buildscripts/profiles/storage.profile.js
@@ -0,0 +1,21 @@
+dependencies = {
+	layers: [
+		{
+			name: "../dojox/storage/storage-browser.js",
+			layerDependencies: [
+			],
+			dependencies: [
+				"dojox.storage",
+				"dojox.storage.GearsStorageProvider",
+				"dojox.storage.WhatWGStorageProvider",
+				"dojox.storage.FlashStorageProvider",
+				"dojox.flash"
+			]
+		}
+	],
+
+	prefixes: [
+		[ "dijit", "../dijit" ],
+		[ "dojox", "../dojox" ]
+	]
+}
diff --git a/util/buildscripts/tests/conditionalTest.js b/util/buildscripts/tests/conditionalTest.js
new file mode 100644
index 0000000..c235180
--- /dev/null
+++ b/util/buildscripts/tests/conditionalTest.js
@@ -0,0 +1,21 @@
+//Test file for the conditional comment inclusion/exclusion code.
+//Run this file from the util/buildscripts/tests directory.
+
+load("../jslib/fileUtil.js");
+load("../jslib/logger.js");
+load("../jslib/buildUtil.js");
+
+
+
+
+var result = buildUtil.processConditionals(
+	"conditionalTest.txt", 
+	fileUtil.readFile("conditionalTest.txt"),
+	{
+		loader: "xdomain",
+		shouldInclude: true,
+		nesting: 1
+	}
+);
+
+print(result);
diff --git a/util/buildscripts/tests/conditionalTest.txt b/util/buildscripts/tests/conditionalTest.txt
new file mode 100644
index 0000000..f027f6c
--- /dev/null
+++ b/util/buildscripts/tests/conditionalTest.txt
@@ -0,0 +1,17 @@
+//>>includeStart("foo", kwArgs.loader == "xdomain");
+This content is included if kwArgs.loader == "xdomain"
+//>>includeEnd("foo");
+
+//This is an exclusion test
+//>>excludeStart("test2", kwArgs.loader == "xdomain");
+This content is excluded if kwArgs.loader == "xdomain"
+//>>excludeEnd("test2");
+
+
+//This is a nested test.
+//>>includeStart("outerMatch", kwArgs.shouldInclude);
+This content is included if kwArgs.shouldInclude evals to true.
+	//>>includeStart("innerMatch", kwArgs.nesting == 1);
+	This is a nested include if kwArgs.nesting == 1
+	//>>includeEnd("innerMatch");
+//>>includeEnd("outerMatch");
diff --git a/util/buildscripts/tests/css/blue/one.css b/util/buildscripts/tests/css/blue/one.css
new file mode 100644
index 0000000..afb3ed8
--- /dev/null
+++ b/util/buildscripts/tests/css/blue/one.css
@@ -0,0 +1,9 @@
+ at import url(two/two.css);
+
+.foo {
+	background-image:url(data:image/gif;base64,abcdeabcde);
+}
+
+.bar {
+	background-image: url("one.png");
+}
diff --git a/util/buildscripts/tests/css/blue/two/two.css b/util/buildscripts/tests/css/blue/two/two.css
new file mode 100644
index 0000000..506f677
--- /dev/null
+++ b/util/buildscripts/tests/css/blue/two/two.css
@@ -0,0 +1,12 @@
+
+.baz {
+	background-image: url(data.png);
+}
+
+.fuz {
+	background-image: url("data:image/gif;base64,abcdeabcde");
+}
+
+.fud {
+	background-image:url(data:image/gif;base64,abcdeabcde);
+}
diff --git a/util/buildscripts/tests/css/flattenTest.js b/util/buildscripts/tests/css/flattenTest.js
new file mode 100644
index 0000000..4714a08
--- /dev/null
+++ b/util/buildscripts/tests/css/flattenTest.js
@@ -0,0 +1,18 @@
+//Test file for the flattening of CSS files.
+//Run this file from the util/buildscripts/tests/css directory.
+
+//Example call to run the test:
+//java -classpath ../../../shrinksafe/js.jar org.mozilla.javascript.tools.shell.Main flattenTest.js
+
+load("../../jslib/logger.js");
+load("../../jslib/buildUtil.js");
+load("../../jslib/fileUtil.js");
+
+var result = buildUtil.flattenCss( "blue/one.css", fileUtil.readFile("blue/one.css"));
+
+/* Copy the blue folder to a folder called temp then try this command
+(warning, it modifies the folder contents
+var result = buildUtil.optimizeCss("temp", "comments");
+*/
+
+print(result);
diff --git a/util/buildscripts/tests/foo/page/view.js b/util/buildscripts/tests/foo/page/view.js
new file mode 100644
index 0000000..00639c9
--- /dev/null
+++ b/util/buildscripts/tests/foo/page/view.js
@@ -0,0 +1,7 @@
+dojo.provide("foo.page.view");
+
+dojo.require("dijit.layout.LayoutContainer");
+dojo.require("dijit.layout.SplitContainer");
+dojo.require("dijit.layout.AccordionContainer");
+dojo.require("dijit.layout.ContentPane");
+dojo.require("dojo.parser");
\ No newline at end of file
diff --git a/util/buildscripts/tests/profiles/customBase.profile.js b/util/buildscripts/tests/profiles/customBase.profile.js
new file mode 100644
index 0000000..25df470
--- /dev/null
+++ b/util/buildscripts/tests/profiles/customBase.profile.js
@@ -0,0 +1,15 @@
+var dependencies = {
+  layers: [
+    {
+      name: "dojo.js",
+      //Using the customBase: true property means that the dojo._base is not
+      //included by default for dojo.js. Define the _base modules by putting
+      //the appropriate _base resource names in the dependencies array below.
+      //If no dependencies are listed, then just the basic loader files are
+      //included (the appropriate files in _base/_loader).
+      customBase: true,
+      dependencies: [
+      ]
+    }
+  ]
+};
\ No newline at end of file
diff --git a/util/buildscripts/tests/profiles/nestedNls.profile.js b/util/buildscripts/tests/profiles/nestedNls.profile.js
new file mode 100644
index 0000000..e403624
--- /dev/null
+++ b/util/buildscripts/tests/profiles/nestedNls.profile.js
@@ -0,0 +1,21 @@
+var dependencies = {
+  prefixes: [
+    [ "foo", "../util/buildscripts/tests/foo" ],
+    [ "dojox", "../dojox" ],
+    [ "dijit", "../dijit" ]
+  ],
+  layers: [
+    {
+      name: "../dijit/dijit.js",
+      resourceName: "dijit.dijit",
+      layerDependencies: [ "dojo.js" ],
+      dependencies: [ "dijit.dijit" ]
+    },
+    {
+      name: "../foo/page/view.js",
+      resourceName: "foo.page.view",
+      layerDependencies: [ "dojo.js", "../dijit/dijit.js" ],
+      dependencies: [ "foo.page.view" ]
+    }
+  ]
+};
\ No newline at end of file
diff --git a/util/buildscripts/webbuild.html b/util/buildscripts/webbuild.html
new file mode 100644
index 0000000..fdcad82
--- /dev/null
+++ b/util/buildscripts/webbuild.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+	<title>Dojo Builder Prototype</title>
+	<script type="text/javascript">
+		djConfig = {
+			isDebug: true,
+			baseRelativePath: "../"
+		};
+	</script>
+	<script src="../dojo.js" type="text/javascript"></script>
+	<script src="buildUtil.js" type="text/javascript"></script>
+	<script src="buildUtilXd.js" type="text/javascript"></script>
+	<script src="webbuild/webbuild.js" type="text/javascript"></script>
+	<script type="text/javascript">
+		function startBuild(depString, version, xdDojoPath){
+			//Need a timeout here because otherwise the calling location is from the frame
+			//that calls this page, which messes up our path building for loading files.
+			//(at least in Firefox 2.0)
+			setTimeout(function(){webbuild.build(depString, version, xdDojoPath);}, 100);
+		}
+	</script>
+</head>
+
+<body>
+	Hidden builder content for webbuild/index.html. See that file for the entry
+	point into the web build system. This file needs to live in the buildscripts
+	directory because of some assumptions in buildUtil.js.
+</body>
+</html>
diff --git a/util/buildscripts/webbuild/index.html b/util/buildscripts/webbuild/index.html
new file mode 100644
index 0000000..f76ae7f
--- /dev/null
+++ b/util/buildscripts/webbuild/index.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Dojo Web Builder</title>
+	<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dojo/resources/dojo.css"/>
+	<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dijit/themes/tundra/tundra.css"/>
+	<style type="text/css">
+		#serverFrame {
+			width: 1px;
+			height: 1px;
+			visibility: hidden;
+		}
+	</style>
+	<script type="text/javascript">
+		djConfig = {
+			
+		};
+	</script>
+	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dojo/dojo.xd.js"></script>
+</head>
+<body class="tundra">
+<h1>Dojo Web Builder</h1>
+
+<form action="http://localhost:8080/dojoweb" method="POST" target="serverFrame">
+	<div class="formSection">
+		<label for="version">Version:</label>
+		<select id="version" name="version">
+			<option value="1.3.2" selected="selected">1.3.2</option>
+		</select>
+	</div>
+	<div class="formSection">
+		<label for="cdn">CDN preference:</label>
+		<select id="cdn" name="cdn">
+			<option value="google">Google</option>
+			<option value="aol">AOL</option>
+		</select>
+	</div>
+	<div class="formSection">
+		<label for="optimize">Optimization:</label>
+		<select id="optimize" name="optimize">
+			<option value="shrinksafe">ShrinkSafe minification without line returns</option>
+			<option value="shrinksafe.keepLines">ShrinkSafe minification with line returns</option>
+			<option value="comments">Comment removal only</option>
+			<option value="none">None (keeps comments and line returns)</option>
+		</select>
+	</div>
+	<div class="formSection">
+		<label for="dependencies">Dependencies:</label>
+		<textarea id="dependencies" name="dependencies" cols="60" rows="20"></textarea>
+	</div>
+	<div class="formSection">
+		<button name="submit">Build It!</button>
+	</div>
+
+</form>
+
+<iframe id="serverFrame" name="serverFrame" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dojo/resources/blank.html"></iframe>
+</body>
+</html>
diff --git a/util/buildscripts/webbuild/makeWebBuildModuleList.js b/util/buildscripts/webbuild/makeWebBuildModuleList.js
new file mode 100644
index 0000000..00399eb
--- /dev/null
+++ b/util/buildscripts/webbuild/makeWebBuildModuleList.js
@@ -0,0 +1,107 @@
+//This file generates a list of modules that can be used in a web build.
+//This file should be called from ant/command line, and the output file
+//needs to be generated before the web build will work.
+
+
+function buildTreeData(/*Object*/obj, /*String*/nodeName){
+	//summary: makes a TreeV3-friendly data structure.
+	
+	var result = null;
+	var childNames = [];
+	if(obj["dojoModuleName"]){
+		result = { title: nodeName, dojoModuleName: obj["dojoModuleName"]};
+	}else{
+		result = {};
+	}
+	
+	//Working with a branch.
+	for(var childName in obj){
+		if(childName != "dojoModuleName"){
+			childNames.push(childName);
+		}
+	}
+	childNames = childNames.sort();
+	if(childNames.length > 0){
+		result.children = [];
+		result = { title: nodeName, children: []};
+		for(var i = 0; i < childNames.length; i++){
+			result.children.push(buildTreeData(obj[childNames[i]], childNames[i]));
+		}
+	}
+	return result;
+}
+
+
+//START of the "main" part of the script.
+//This is the entry point for this script file.
+var srcRoot = arguments[0];
+var outputFileName = arguments[1];
+
+//Load Dojo so we can reuse code.
+djConfig={
+	baseUrl: "../../../dojo/"
+};
+load('../../../dojo/dojo.js');
+
+load("../jslib/logger.js");
+load("../jslib/fileUtil.js");
+
+//Get a list of files that might be modules.
+var fileList = fileUtil.getFilteredFileList(srcRoot, /\.js$/, true);
+
+var provideRegExp = /dojo\.provide\(\".*\"\)/g;
+
+//Search the modules for a matching dojo.provide() call.
+//Need to do this because some files (like nls/*.js files) are
+//not really modules.
+var provideList = [];
+for(var i = 0; i < fileList.length; i++){
+	var fileName = fileList[i];
+	var fileContents = new fileUtil.readFile(fileName);
+
+	var matches = fileContents.match(provideRegExp);
+	
+	if(matches){
+		for(var j = 0; j < matches.length; j++){
+			//strip off the .js file extension
+			var modFileName = fileName.substring(0, fileName.length - 3);
+			var provideName = matches[j].substring(matches[j].indexOf('"') + 1, matches[j].lastIndexOf('"'));
+
+			//Skip certain kinds of modules not needed in end use.
+			if(provideName.indexOf("tests.") != -1
+				|| provideName.indexOf("._") != -1
+				|| provideName.indexOf(".robot") != -1){
+				continue;
+			}
+
+			//Only allow the provides that match the file name.
+			//So, the different dijit permutations of dijit.form.Button will not show up.
+			if (modFileName.lastIndexOf(provideName.replace(/\./g, "/")) == modFileName.length - provideName.length){
+				provideList.push(provideName);
+				break;
+			}
+		}
+	
+	}
+}
+
+provideList = provideList.sort();
+
+logger.trace(provideList);
+
+//Create the object that represents the module structures.
+/*var moduleHolder = {};
+
+for(var i = 0; i < provideList.length; i++){
+	var moduleObject = dojo.getObject(provideList[i], moduleHolder, true);
+	moduleObject.obj[moduleObject.prop] = {dojoModuleName: provideList[i] };
+}
+
+//Transform the object into something appropriate for a tree control.
+var treeData = buildTreeData(moduleHolder, "Dojo Modules");
+
+//Output the results.
+fileUtil.saveFile(outputFileName, "var treeData = " + dojo.toJson(treeData) + ";");
+*/
+fileUtil.saveFile(outputFileName, "var provideList = [" + provideList + "];");
+
diff --git a/util/buildscripts/webbuild/server/build.xml b/util/buildscripts/webbuild/server/build.xml
new file mode 100644
index 0000000..669739d
--- /dev/null
+++ b/util/buildscripts/webbuild/server/build.xml
@@ -0,0 +1,172 @@
+<project name="dojoweb" default="compile" basedir=".">
+	<property file="build.properties"/>
+	<import file="${tomcat.home}/bin/catalina-tasks.xml"/>
+	
+
+	<property name="app.name"      value="dojoweb"/>
+	<property name="app.path"      value="/${app.name}"/>
+	<property name="app.version"   value="0.1-dev"/>
+	<property name="build.home"    value="${basedir}/build"/>
+	<property name="dist.home"     value="${basedir}/dist"/>
+	<property name="docs.home"     value="${basedir}/docs"/>
+	<property name="src.home"      value="${basedir}/src"/>
+	<property name="web.home"      value="${basedir}/web"/>
+	<property name="lib.home"      value="lib"/>
+	<property name="jslib.home"      value="jslib"/>
+
+	<property name="compile.debug"       value="true"/>
+	<property name="compile.deprecation" value="true"/>
+	<property name="compile.optimize"    value="false"/>
+
+	<path id="compile.classpath">
+		<pathelement location="${tomcat.home}/lib/servlet-api.jar"/>
+		<pathelement location="${lib.home}/js.jar" />
+		<pathelement location="${lib.home}/shinksafe.jar" />
+	</path>
+
+
+	<!-- ==================== All Target ==================================== -->
+	<target name="all" depends="clean,compile" description="Clean build and dist directories, then compile"/>
+
+	<!-- ==================== Clean Target ==================================== -->
+	<target name="clean" description="Delete old build and dist directories">
+		<delete dir="${build.home}"/>
+		<delete dir="${dist.home}"/>
+	</target>
+
+	<!-- ==================== Prepare Target ================================== -->
+	<target name="prepare">
+		<!-- Create build directories as needed -->
+		<mkdir  dir="${build.home}"/>
+		<mkdir  dir="${build.home}/WEB-INF"/>
+		<mkdir  dir="${build.home}/WEB-INF/classes"/>
+		
+		
+		<!-- Copy static content of this web application -->
+		<copy todir="${build.home}">
+			<fileset dir="${web.home}"/>
+		</copy>
+		
+		<!-- Copy external dependencies as required -->
+		<mkdir  dir="${build.home}/WEB-INF/lib"/>
+		<copy todir="${build.home}/WEB-INF/lib">
+			<fileset dir="${lib.home}"/>
+		</copy>
+	</target>
+
+	<!-- ==================== Compile Target ================================== -->
+	<target name="compile" depends="prepare" description="Compile Java sources">
+	
+		<!-- Compile Java classes as necessary -->
+		<mkdir    dir="${build.home}/WEB-INF/classes"/>
+		<javac srcdir="${src.home}"
+			destdir="${build.home}/WEB-INF/classes"
+			debug="${compile.debug}"
+			deprecation="${compile.deprecation}"
+			optimize="${compile.optimize}">
+			<classpath refid="compile.classpath"/>
+		</javac>
+
+		<!-- Copy application resources -->
+		<copy  todir="${build.home}/WEB-INF/classes">
+			<fileset dir="${src.home}" excludes="**/*.java"/>
+		</copy>
+	
+	</target>
+
+	<!-- ==================== Dist Target ===================================== -->
+	<target name="dist" depends="compile,javadoc" description="Create binary distribution">	
+		<!-- Copy documentation subdirectories -->
+		<!-- mkdir   dir="${dist.home}/docs"/>
+		<copy    todir="${dist.home}/docs">
+			<fileset dir="${docs.home}"/>
+		</copy -->
+		
+		<!-- Create application JAR file -->
+		<jar jarfile="${dist.home}/${app.name}-${app.version}.war" basedir="${build.home}"/>
+	</target>
+
+	<!-- ==================== Install Target ================================== -->
+	<!--
+	
+	The "install" target tells the specified Tomcat 6 installation to dynamically
+	install this web application and make it available for execution.  It does
+	*not* cause the existence of this web application to be remembered across
+	Tomcat restarts; if you restart the server, you will need to re-install all
+	this web application.
+	
+	If you have already installed this application, and simply want Tomcat to
+	recognize that you have updated Java classes (or the web.xml file), use the
+	"reload" target instead.
+	
+	NOTE:  This target will only succeed if it is run from the same server that
+	Tomcat is running on.
+	
+	NOTE:  This is the logical opposite of the "remove" target.
+	
+	-->
+	<target name="install" depends="compile" description="Install application to servlet container">
+		<deploy url="${manager.url}"
+			username="${manager.username}"
+			password="${manager.password}"
+			path="${app.path}"
+			localWar="file://${build.home}"/>
+	</target>
+
+
+	<!-- ==================== Javadoc Target ================================== -->
+	<!--
+	
+	  The "javadoc" target creates Javadoc API documentation for the Java
+	  classes included in your application.  Normally, this is only required
+	  when preparing a distribution release, but is available as a separate
+	  target in case the developer wants to create Javadocs independently.
+	
+	-->
+	<target name="javadoc" depends="compile" description="Create Javadoc API documentation">
+		<mkdir dir="${dist.home}/docs/api"/>
+		<javadoc sourcepath="${src.home}"
+			destdir="${dist.home}/docs/api"
+			packagenames="*">
+			<classpath refid="compile.classpath"/>
+		</javadoc>
+	</target>
+
+	<!-- ==================== Reload Target =================================== -->
+	<!--
+	
+	  The "reload" signals the specified application Tomcat 6 to shut itself down
+	  and reload. This can be useful when the web application context is not
+	  reloadable and you have updated classes or property files in the
+	  /WEB-INF/classes directory or when you have added or updated jar files in the
+	  /WEB-INF/lib directory.
+	
+	  NOTE: The /WEB-INF/web.xml web application configuration file is not reread
+	  on a reload. If you have made changes to your web.xml file you must stop
+	  then start the web application. 
+	
+	-->
+	<target name="reload" depends="compile" description="Reload application on servlet container">
+	
+	<reload url="${manager.url}"
+		username="${manager.username}"
+		password="${manager.password}"
+		path="${app.path}"/>
+	</target>
+
+	<!-- ==================== Remove Target =================================== -->
+	<!--
+	
+	  The "remove" target tells the specified Tomcat 6 installation to dynamically
+	  remove this web application from service.
+	
+	  NOTE:  This is the logical opposite of the "install" target.
+	
+	-->
+	<target name="remove" description="Remove application on servlet container">
+		<undeploy url="${manager.url}"
+			username="${manager.username}"
+			password="${manager.password}"
+			path="${app.path}"/>		
+	</target>
+</project>
diff --git a/util/buildscripts/webbuild/server/js/build.js b/util/buildscripts/webbuild/server/js/build.js
new file mode 100644
index 0000000..e05a0dc
--- /dev/null
+++ b/util/buildscripts/webbuild/server/js/build.js
@@ -0,0 +1,203 @@
+function load(/*String*/fileName){
+	//summary: opens the file at fileName and evals the contents as JavaScript.
+	
+	//Read the file
+	var fileContents = readFile(fileName);
+
+	//Eval the contents.
+	var Context = Packages.org.mozilla.javascript.Context;
+	var context = Context.enter();
+	try{
+		return context.evaluateString(this, fileContents, fileName, 1, null);
+	}finally{
+		Context.exit();
+	}
+}
+
+function readFile(/*String*/path, /*String?*/encoding){
+	//summary: reads a file and returns a string
+	encoding = encoding || "utf-8";
+	var file = new java.io.File(path);
+	var lineSeparator = "\n";
+	var input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding));
+	try {
+		var stringBuffer = new java.lang.StringBuffer();
+		var line = "";
+		while((line = input.readLine()) !== null){
+			stringBuffer.append(line);
+			stringBuffer.append(lineSeparator);
+		}
+		//Make sure we return a JavaScript string and not a Java string.
+		return new String(stringBuffer.toString()); //String
+	} finally {
+		input.close();
+	}
+}
+
+//TODO: inlining this function since the new shrinksafe.jar is used, and older
+//versions of Dojo's buildscripts are not compatible.
+function optimizeJs(/*String fileName*/fileName, /*String*/fileContents, /*String*/copyright, /*String*/optimizeType, /*String*/stripConsole){
+	//summary: either strips comments from string or compresses it.
+	copyright = copyright || "";
+
+	//Use rhino to help do minifying/compressing.
+	var context = Packages.org.mozilla.javascript.Context.enter();
+	try{
+		// Use the interpreter for interactive input (copied this from Main rhino class).
+		context.setOptimizationLevel(-1);
+
+		// the "packer" type is now just a synonym for shrinksafe
+		if(optimizeType.indexOf("shrinksafe") == 0 || optimizeType == "packer"){
+			//Apply compression using custom compression call in Dojo-modified rhino.
+			fileContents = new String(Packages.org.dojotoolkit.shrinksafe.Compressor.compressScript(fileContents, 0, 1, stripConsole));
+			if(optimizeType.indexOf(".keepLines") == -1){
+				fileContents = fileContents.replace(/[\r\n]/g, "");
+			}
+		}else if(optimizeType == "comments"){
+			//Strip comments
+			var script = context.compileString(fileContents, fileName, 1, null);
+			fileContents = new String(context.decompileScript(script, 0));
+			
+			//Replace the spaces with tabs.
+			//Ideally do this in the pretty printer rhino code.
+			fileContents = fileContents.replace(/    /g, "\t");
+
+			//If this is an nls bundle, make sure it does not end in a ;
+			//Otherwise, bad things happen.
+			if(fileName.match(/\/nls\//)){
+				fileContents = fileContents.replace(/;\s*$/, "");
+			}
+		}
+	}finally{
+		Packages.org.mozilla.javascript.Context.exit();
+	}
+
+
+	return copyright + fileContents;
+}
+
+build = {
+	make: function(
+		//The path to this file. Assumes dojo builds under it.
+		/*String*/builderPath,
+		
+		//"1.1.1" or "1.3.2": used to choose directory of dojo to use.
+		/*String*/version,
+		
+		//"google" or "aol" 
+		/*String*/cdnType,
+		
+		//comma-separated list of resource names. No double-quotes or quotes around values.
+		/*String*/dependencies,
+		
+		//comments, shrinksafe, none
+		/*String*/optimizeType){
+
+
+		//Validate.
+		if(version != "1.3.2"){
+			return "invalid version";
+		}
+		if(cdnType != "google" && cdnType != "aol"){
+			return "invalide CDN type";
+		}
+		if(optimizeType != "comments" && optimizeType != "shrinksafe"
+			&& optimizeType != "none" && optimizeType != "shrinksafe.keepLines"){
+			return "invalid optimize type";
+		}
+		if(!dependencies.match(/^[\w\-\,\s\.]+$/)){
+			return "invalid dependency list";
+		}
+		
+		//Set up full CDN path.
+		var xdDojoPath = "http://ajax.googleapis.com/ajax/libs/dojo/";
+		if(cdnType == "aol"){
+			xdDojoPath = "http://o.aolcdn.com/dojo/";
+		}
+		xdDojoPath += version;
+
+		//Directory that holds dojo source distro. Direct child under the helma dir
+		var dojoDir = builderPath + version + "/"; 
+		
+		//Normalize the dependencies so that have double-quotes
+		//around each dependency.
+		var normalizedDependencies = dependencies || "";
+		if(normalizedDependencies){
+			normalizedDependencies = '"' + normalizedDependencies.split(",").join('","') + '"';
+		}
+
+		var buildscriptDir = dojoDir + "util/buildscripts/";
+		
+		//Load the libraries to help in the build.
+		load(dojoDir + "util/buildscripts/jslib/logger.js");
+		load(dojoDir + "util/buildscripts/jslib/fileUtil.js");
+		load(dojoDir + "util/buildscripts/jslib/buildUtil.js");
+		load(dojoDir + "util/buildscripts/jslib/buildUtilXd.js");
+		load(dojoDir + "util/buildscripts/jslib/i18nUtil.js");
+		
+		//Set up the build args.
+		var kwArgs = buildUtil.makeBuildOptions([
+			"loader=xdomain",
+			"version=" + version,
+			"xdDojoPath=" + xdDojoPath,
+			"layerOptimize=" + optimizeType
+		]);
+		
+		//Specify the basic profile for build.
+		var profileText = 'dependencies = {'
+			+ 'layers: ['
+			+ '	{'
+			+ '		name: "dojo.js",'
+			+ '		dependencies: ['
+			+         normalizedDependencies
+			+ '		]'
+			+ '	}'
+			+ '],'
+		
+			+ 'prefixes: ['
+			+ '	[ "dojo", "' + dojoDir + 'dojo" ],'
+			+ '	[ "dijit", "' + dojoDir + 'dijit" ],'
+			+ '	[ "dojox", "' + dojoDir + 'dojox" ]'
+			+ ']'
+		+ '}';
+		
+		//Bring the profile into existence
+		var profileProperties = buildUtil.evalProfile(profileText, true);
+		kwArgs.profileProperties = profileProperties;
+		
+		//Set up some helper variables.
+		dependencies = kwArgs.profileProperties.dependencies;
+		var prefixes = dependencies.prefixes;
+		var lineSeparator = fileUtil.getLineSeparator();
+		var layerLegalText = fileUtil.readFile(buildscriptDir + "copyright.txt")
+			+ lineSeparator
+			+ fileUtil.readFile(buildscriptDir + "build_notice.txt");
+		
+		//Manually set the loader on the dependencies object. Ideally the buildUtil.loadDependencyList() function
+		//and subfunctions would take kwArgs directly.
+		dependencies.loader = kwArgs.loader;
+		
+		//Build the layer contents.
+		var depResult = buildUtil.makeDojoJs(buildUtil.loadDependencyList(kwArgs.profileProperties, null, buildscriptDir), kwArgs.version, kwArgs);
+		
+		//Grab the content from the "dojo.xd.js" layer.
+		var layerName = depResult[1].layerName;
+		var layerContents = depResult[1].contents;
+		
+		//Burn in xd path for dojo if requested, and only do this in dojo.xd.js.
+		if(layerName.match(/dojo\.xd\.js/) && kwArgs.xdDojoPath){
+			layerContents = buildUtilXd.setXdDojoConfig(layerContents, kwArgs.xdDojoPath);
+		}
+		
+		//Intern strings
+		if(kwArgs.internStrings){
+			prefixes = dependencies["prefixes"] || [];
+			var skiplist = dependencies["internSkipList"] || [];
+			layerContents = buildUtil.interningRegexpMagic(layerName, layerContents, dojoDir, prefixes, skiplist);
+		}
+		
+		//Minify the contents
+		return optimizeJs(layerName, layerContents, layerLegalText, kwArgs.layerOptimize, "");
+
+	}
+};
diff --git a/util/buildscripts/webbuild/server/lib/js.jar b/util/buildscripts/webbuild/server/lib/js.jar
new file mode 100644
index 0000000..c081d16
Binary files /dev/null and b/util/buildscripts/webbuild/server/lib/js.jar differ
diff --git a/util/buildscripts/webbuild/server/lib/shrinksafe.jar b/util/buildscripts/webbuild/server/lib/shrinksafe.jar
new file mode 100644
index 0000000..8481ba6
Binary files /dev/null and b/util/buildscripts/webbuild/server/lib/shrinksafe.jar differ
diff --git a/util/buildscripts/webbuild/server/src/org/dtk/BuilderContextAction.java b/util/buildscripts/webbuild/server/src/org/dtk/BuilderContextAction.java
new file mode 100644
index 0000000..1978119
--- /dev/null
+++ b/util/buildscripts/webbuild/server/src/org/dtk/BuilderContextAction.java
@@ -0,0 +1,80 @@
+package org.dtk;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ContextAction;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Script;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+
+public class BuilderContextAction implements ContextAction {
+    private String builderPath;
+    private String version;
+    private String cdn;
+    private String dependencies;
+    private String optimize;
+
+    private Exception exception;
+    private Scriptable topScope;
+    private Context context;
+    private String result;
+
+    public BuilderContextAction(String builderPath, String version, String cdn, String dependencies, String optimize) {
+        this.builderPath = builderPath;
+        this.version = version;
+        this.cdn = cdn;
+        this.dependencies = dependencies;
+        this.optimize = optimize;
+
+        this.exception = null;
+        this.context = null;
+        this.topScope = null;
+    }
+
+    public Object run(Context newContext) {
+        context = newContext;
+        context.setOptimizationLevel(-1);
+
+        // Set up standard scripts
+        topScope = context.initStandardObjects();
+
+        try {
+            String fileName = builderPath + "build.js";
+            String fileContent = FileUtil.readFromFile(fileName, null);
+            Script script = context.compileString(fileContent, fileName, 1, null);
+            
+            // Expose top level scope as the "global" scope.
+            //TODO: only need this for the load function, maybe there is a built in way
+            //to get this.
+            ScriptableObject.putProperty(topScope, "global", Context.javaToJS(topScope, topScope));
+
+            // Exec the build script.
+            script.exec(context, topScope);
+
+            // Call build.make(builderPath)
+            Scriptable build = Context.toObject(topScope.get("build", topScope), topScope);
+            Object args[] = {
+                    builderPath,
+                    version,
+                    cdn,
+                    dependencies,
+                    optimize
+            };
+            Function make = (Function) build.get("make", topScope);
+            Object resultObj = make.call(context, topScope, build, args);
+            result = (String) Context.jsToJava(resultObj, String.class); 
+        } catch (Exception e) {
+            this.exception = e;
+
+        }
+        return null;
+    }
+
+    public String getResult() {
+        return result;
+    }
+
+    public Exception getException() {
+        return exception;
+    }
+}
diff --git a/util/buildscripts/webbuild/server/src/org/dtk/BuilderServlet.java b/util/buildscripts/webbuild/server/src/org/dtk/BuilderServlet.java
new file mode 100644
index 0000000..7ab16c6
--- /dev/null
+++ b/util/buildscripts/webbuild/server/src/org/dtk/BuilderServlet.java
@@ -0,0 +1,149 @@
+package org.dtk;
+
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.mozilla.javascript.ContextFactory;
+
+import sun.misc.BASE64Encoder;
+
+public class BuilderServlet extends HttpServlet {
+    private String builderPath;
+    private String cachePath;
+ 
+    // *****************************************************
+    public void init() throws ServletException {
+        super.init();
+
+        // Read in the builderPath.
+        // - context-param
+        // - Java system property
+        ServletContext sc = getServletContext();
+        builderPath = sc.getInitParameter("builderPath");
+        cachePath = sc.getInitParameter("cachePath");
+       if (builderPath == null || builderPath.length() == 0) {
+            builderPath = System.getProperty("builderPath");
+            cachePath = System.getProperty("cachePath");
+       }
+       if (cachePath == null || cachePath.length() == 0) {
+           cachePath = System.getProperty("cachePath");
+       }
+    }
+
+    // *****************************************************
+    public void doPost(HttpServletRequest req, HttpServletResponse res)
+            throws ServletException, IOException {
+        doGet(req, res);
+    }
+
+    // *****************************************************
+    public void doGet(HttpServletRequest req, HttpServletResponse res)
+            throws ServletException, IOException {
+
+        //Pull out the parameters.
+        String version = req.getParameter("version");
+        String cdn = req.getParameter("cdn");
+        String dependencies = req.getParameter("dependencies");
+        String optimize = req.getParameter("optimize");
+        
+        String cacheFile = null;
+        String result = null;
+        boolean isCached = false;
+
+        Boolean isError = true;
+
+        //Validate parameters
+        if(!version.equals("1.3.2")) {
+            result = "invalid version: " + version;
+        }
+        if(!cdn.equals("google") && !cdn.equals("aol")) {
+            result = "invalide CDN type: " + cdn;
+        }
+        if(!optimize.equals("comments") && !optimize.equals("shrinksafe")
+            && !optimize.equals("none") && !optimize.equals("shrinksafe.keepLines")) {
+            result = "invalid optimize type: " + optimize;
+        }
+        if(!dependencies.matches("^[\\w\\-\\,\\s\\.]+$")) {
+            result = "invalid dependency list: " + dependencies;
+        }
+
+        try {
+            //See if we already did the work.
+            MessageDigest md = null;
+            try {
+                md = MessageDigest.getInstance("SHA");
+            } catch (NoSuchAlgorithmException e) {
+                result = e.getMessage();
+            }
+            if (result == null) {
+                md.update(dependencies.getBytes());
+                String digest = (new BASE64Encoder()).encode(md.digest()).replace('+', '~').replace('/', '_').replace('=', '_');
+                cacheFile = cachePath + "/" + version + "/" + cdn + "/" + digest + "/" + optimize + ".js";
+                
+                File file = new File(cacheFile);
+                if (file.exists()) {
+                    isCached = true;
+                    isError = false;
+                }
+            }
+    
+            //Generate the build.
+            if (result == null && !isCached) {
+                BuilderContextAction contextAction = new BuilderContextAction(builderPath, version, cdn, dependencies, optimize);
+                ContextFactory.getGlobal().call(contextAction);
+                Exception exception = contextAction.getException();
+    
+                if (exception != null) {
+                    result = exception.getMessage();
+                } else {
+                    result = contextAction.getResult();
+                    FileUtil.writeToFile(cacheFile, result, null, true);
+                    isError = false;
+                }
+            }
+        } catch (Exception e) {
+            result = e.getMessage();
+        }
+
+        //Write out response.
+        res.setCharacterEncoding("utf-8");
+        if (isError) {
+            result = result.replaceAll("\\\"", "\\\"");
+            result = "<html><head><script type=\"text/javascript\">alert(\"" + result + "\");</script></head><body></body></html>";
+            PrintWriter writer = res.getWriter();
+            writer.append(result);
+        } else {
+            res.setHeader("Content-Type", "application/x-javascript");
+            res.setHeader("Content-disposition", "attachment; filename=dojo.js");  
+            res.setHeader("Content-Encoding", "gzip");
+
+            //Read in the gzipped bytes of the cached file.
+            File file = new File(cacheFile);
+
+            BufferedInputStream in = new java.io.BufferedInputStream(
+                    new DataInputStream(new FileInputStream(file)));
+            OutputStream out = res.getOutputStream();
+            byte[] bytes = new byte[64000];
+            int bytesRead = 0;
+            while (bytesRead != -1) {
+                bytesRead = in.read(bytes);
+                if (bytesRead != -1) {
+                    out.write(bytes, 0, bytesRead);
+                }
+            }
+        }
+    }
+}
diff --git a/util/buildscripts/webbuild/server/src/org/dtk/FileUtil.java b/util/buildscripts/webbuild/server/src/org/dtk/FileUtil.java
new file mode 100644
index 0000000..9c9f4b2
--- /dev/null
+++ b/util/buildscripts/webbuild/server/src/org/dtk/FileUtil.java
@@ -0,0 +1,86 @@
+package org.dtk;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.zip.GZIPOutputStream;
+
+public class FileUtil {
+
+    public static String readFromFile(String path, String encoding) throws IOException {
+        // summary: reads a file and returns a string
+        if (encoding == null) {
+            encoding = "utf-8";
+        }
+        File file = new File(path);
+        String lineSeparator = System.getProperty("line.separator");
+        BufferedReader input = new java.io.BufferedReader(
+                new InputStreamReader(new FileInputStream(file), encoding));
+        try {
+            StringBuffer stringBuffer = new StringBuffer();
+            String line = input.readLine();
+        
+            // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page
+            // 324
+            // http://www.unicode.org/faq/utf_bom.html
+        
+            // Note that when we use utf-8, the BOM should appear as "EF BB BF",
+            // but it doesn't due to this bug in the JDK:
+            // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
+            if (line != null && line.length() > 0 && line.charAt(0) == 0xfeff) {
+                // Eat the BOM, since we've already found the encoding on this
+                // file,
+                // and we plan to concatenating this buffer with others; the BOM
+                // should
+                // only appear at the top of a file.
+                line = line.substring(1);
+            }
+            while (line != null) {
+                stringBuffer.append(line);
+                stringBuffer.append(lineSeparator);
+                line = input.readLine();
+            }
+            // Make sure we return a JavaScript string and not a Java string.
+            return stringBuffer.toString(); // String
+        } finally {
+            input.close();
+        }
+    }
+
+    public static void writeToFile(String path, String contents, String encoding, boolean useGzip) throws IOException {
+        // summary: writes a file
+        if (encoding == null) {
+            encoding = "utf-8";
+        }
+        File file = new File(path);
+        
+        //Make sure destination dir exists.
+        File parentDir = file.getParentFile();
+        if(!parentDir.exists()){
+            if(!parentDir.mkdirs()){
+                throw new IOException("Could not create directory: " + parentDir.getAbsolutePath());
+            }
+        }
+
+        OutputStream outStream = new FileOutputStream(file);
+        if (useGzip) {
+            outStream = new GZIPOutputStream(outStream);
+        } else {
+            
+        }
+ 
+        BufferedWriter output = new java.io.BufferedWriter(new OutputStreamWriter(outStream, encoding));
+        try {
+            output.append(contents);
+        } finally {
+            output.close();
+        }            
+
+    }
+}
diff --git a/util/buildscripts/webbuild/server/web/WEB-INF/web.xml b/util/buildscripts/webbuild/server/web/WEB-INF/web.xml
new file mode 100644
index 0000000..0616163
--- /dev/null
+++ b/util/buildscripts/webbuild/server/web/WEB-INF/web.xml
@@ -0,0 +1,40 @@
+<!DOCTYPE web-app 
+    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
+    "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+	<display-name>Dojo Web Builder</display-name>
+	<description></description>
+	
+	<context-param>
+		<param-name>someContextParam</param-name>
+			<param-value>someContextParamValue</param-value>
+		<description>
+		</description>
+	</context-param>
+
+	<servlet>
+		<servlet-name>builder</servlet-name>
+		<description>
+		</description>
+		<servlet-class>org.dtk.BuilderServlet</servlet-class>
+		<init-param>
+			<param-name>builderPath</param-name>
+			<param-value>/Users/jr/src/dojo/trunk/util/buildscripts/webbuild/server/js/</param-value>
+		</init-param>
+		<init-param>
+			<param-name>cachePath</param-name>
+			<param-value>/Users/jr/src/dojo/trunk/util/buildscripts/webbuild/server/js/cache/</param-value>
+		</init-param>
+		<init-param>
+			<param-name>appDir</param-name>
+			<param-value>.</param-value>
+		</init-param>
+		<load-on-startup>5</load-on-startup>
+	</servlet>
+
+	<servlet-mapping>
+		<servlet-name>builder</servlet-name>
+		<url-pattern>/*</url-pattern>
+	</servlet-mapping>
+</web-app>
diff --git a/util/buildscripts/zoneinfo/LICENSE b/util/buildscripts/zoneinfo/LICENSE
new file mode 100644
index 0000000..211d20a
--- /dev/null
+++ b/util/buildscripts/zoneinfo/LICENSE
@@ -0,0 +1,10 @@
+"Olson Database", available for download from ftp://elsie.nci.nih.gov/pub/
+
+These comments were included in each file.
+
+# This file is in the public domain, so clarified as of
+# 2009-05-17 by Arthur David Olson.
+
+# This data is by no means authoritative; if you think you know better,
+# go ahead and edit the file (and please send any changes to
+# tz at elsie.nci.nih.gov for general use in the future).
diff --git a/util/buildscripts/zoneinfo/README b/util/buildscripts/zoneinfo/README
new file mode 100644
index 0000000..08d6991
--- /dev/null
+++ b/util/buildscripts/zoneinfo/README
@@ -0,0 +1,9 @@
+Use these files and scripts to generate the zoneinfo files in dojox/date/zoneinfo
+
+In the tzdata folder are the olson zoneinfo files as distributed.  Only the following
+files are needed from this archive:
+	africa, antarctica, asia, australasia, backward, etcetera, europe,
+	northamerica, pacificnew, southamerica
+	
+The strip_olson_comments.rb script can be used to pull out unneeded comment lines
+from the files - thus making them smaller
diff --git a/util/buildscripts/zoneinfo/strip_olson_comments.rb b/util/buildscripts/zoneinfo/strip_olson_comments.rb
new file mode 100644
index 0000000..ba9bbc7
--- /dev/null
+++ b/util/buildscripts/zoneinfo/strip_olson_comments.rb
@@ -0,0 +1,30 @@
+#!/usr/bin/ruby
+ #
+ # Copyright 2009 Matthew Eernisse (mde at fleegix.org)
+ #
+ # 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.
+ #
+ # This is a sample script for stripping the copious comments
+ # from Olson timezone data files.
+ #
+if ARGV.length == 0
+  print "Usage: strip_comments.rb /path/to/input/file\n"
+  exit
+else
+  path = ARGV[0]
+end
+
+t = File.read(path)
+t.gsub!(/^#.*\n/, '')
+t.gsub!(/^\n/, '')
+print t
diff --git a/util/buildscripts/zoneinfo/tzdata2009k.tar.gz b/util/buildscripts/zoneinfo/tzdata2009k.tar.gz
new file mode 100644
index 0000000..c181f9f
Binary files /dev/null and b/util/buildscripts/zoneinfo/tzdata2009k.tar.gz differ
diff --git a/util/checkstyle/checkstyle.bat b/util/checkstyle/checkstyle.bat
new file mode 100644
index 0000000..5870cae
--- /dev/null
+++ b/util/checkstyle/checkstyle.bat
@@ -0,0 +1,3 @@
+java -classpath ../shrinksafe/js.jar;../shrinksafe/shrinksafe.jar org.mozilla.javascript.tools.shell.Main runCheckstyle.js %*
+
+ at rem java -Xms256m -Xmx256m -classpath ../shrinksafe/js.jar;../shrinksafe/shrinksafe.jar org.mozilla.javascript.tools.shell.Main  runCheckstyle.js %*
diff --git a/util/checkstyle/checkstyle.php.rename.html b/util/checkstyle/checkstyle.php.rename.html
new file mode 100644
index 0000000..4b027a8
--- /dev/null
+++ b/util/checkstyle/checkstyle.php.rename.html
@@ -0,0 +1,31 @@
+<?php
+	$action = $_POST["action"];
+	$fileName = $_POST["filename"];
+	$contents = $_POST["contents"];
+
+	if ($action == "save") {
+		save($fileName, $contents);
+	}
+	
+	
+	function save($fileName, $contents) {
+		$fileName = "../../".$fileName.".checkstyle.js";
+
+		$fh = fopen($fileName, 'w');
+		fwrite($fh, stripslashes($contents));
+		fclose($fh);
+		
+		print "File saved to $fileName\n";
+	}
+	
+	if(false) {
+?>
+<html>
+	<body>
+		Rename this file to checkstyle.php to enable saving fixed files.
+	</body>
+</html>
+
+<?php
+}
+?>
\ No newline at end of file
diff --git a/util/checkstyle/checkstyle.sh b/util/checkstyle/checkstyle.sh
new file mode 100644
index 0000000..68df7fe
--- /dev/null
+++ b/util/checkstyle/checkstyle.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+java -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar org.mozilla.javascript.tools.shell.Main runCheckstyle.js "$@"
+
+# if you experience an "Out of Memory" error, you can increase it as follows:
+#java -Xms256m -Xmx256m -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar org.mozilla.javascript.tools.shell.Main  runCheckstyle.js "$@"
diff --git a/util/checkstyle/checkstyleReport.html b/util/checkstyle/checkstyleReport.html
new file mode 100644
index 0000000..a4a3563
--- /dev/null
+++ b/util/checkstyle/checkstyleReport.html
@@ -0,0 +1,518 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<style type="text/css">
+		@import "../../dojo/resources/dojo.css";
+		@import "../../dojox/grid/resources/Grid.css";
+		@import "../../dojox/grid/resources/soriaGrid.css";
+
+		html, body, #main{	
+			width: 100%;	/* make the body expand to fill the visible window */
+			height: 100%;
+			overflow: hidden;	/* erase window level scrollbars */
+			padding: 0 0 0 0;
+			margin: 0 0 0 0;
+			font: 10pt Arial,Myriad,Tahoma,Verdana,sans-serif;
+		}
+		
+		#checks label {
+			padding: 4px;
+			float: left;
+		}
+		#checks input {
+			float: right;
+		}
+		#checks div {
+			height: 15px;
+			padding: 4px;
+			margin-top: 5px;
+		}
+	</style>
+
+	<!-- required: the default dijit theme: -->
+	<link id="themeStyles" rel="stylesheet" href="../../dijit/themes/soria/soria.css">
+
+	<!-- required: dojo.js -->
+	<script type="text/javascript" src="../../dojo/dojo.js"
+		djConfig="isDebug: true, parseOnLoad: true"></script>
+
+	<script type="text/javascript">
+		dojo.require("dijit.dijit"); // optimize: load dijit layer
+		dojo.require("dijit.layout.BorderContainer");
+		dojo.require("dijit.form.FilteringSelect");
+		dojo.require("dijit.form.Button");
+		dojo.require("dijit.layout.TabContainer");
+		dojo.require("dijit.layout.ContentPane");
+		dojo.require("dojox.grid.DataGrid");
+		dojo.require("dojo.data.ItemFileReadStore");
+		dojo.require("dojo.date.locale");
+		dojo.require("dijit.Dialog");
+	</script>
+
+	
+	<script type="text/javascript" src="checkstyleUtil.js"></script>
+	<script type="text/javascript">
+		var singleFileStore;
+		var errorQuery;
+		var saveErrorMsg = "You may need to rename the checkstyle.php.rename.html file to checkstyle.php."
+								+ "\nPlease read the readme.txt file in the /util/checkstyle folder.";
+
+		dojo.addOnLoad(function(){
+			checkstyleStore.fetch({query: {date : '*'}, onComplete: function(items){
+				var checkstyleReportDate = new Date(checkstyleStore.getValue(items[0], "date"));
+				var dateStr = dojo.date.locale.format((new Date(checkstyleReportDate)), {formatLength: "medium"});
+					
+				document.title = "Dojo Checkstyle report generated on " + dateStr;
+				dojo.byId("reportDate").innerHTML = dateStr;	
+			}});
+			
+			dojo.connect(dijit.byId("messagesGrid"), "onRowClick", doEdit);
+			
+		});
+		var cachedFiles = {};
+		var changedFiles = [];
+		var navKeys = {};
+		dojo.forEach([dojo.keys.UP_ARROW, dojo.keys.DOWN_ARROW, 
+						dojo.keys.LEFT_ARROW, dojo.keys.RIGHT_ARROW, 
+						dojo.keys.ENTER], function(code){
+							navKeys[code] = true;
+						});
+		function updateLine(evt) {
+			evt = dojo.fixEvent(evt);
+			if (navKeys[evt.keyCode]) {
+				dojo.byId("lineNumber").innerHTML = getCursorPosition(evt.target);
+			}
+		}
+		
+		function getCursorPosition(textarea) {
+			if(textarea.selectionStart){
+				return textarea.selectionStart;
+			}else if(dojo.doc.selection){ //IE
+				var range = dojo.doc.selection.createRange();
+				return range;
+			}
+		}
+
+		function onFolderClick(evt) {
+			var folderName = evt.grid.store.getValue(
+								evt.grid.getItem(evt.rowIndex), "file");
+			if (dojo.trim(folderName) == "All") {
+				folderName = "";
+			} else if (folderName.charAt(folderName.length - 1) != "/"){
+				folderName += "/";
+			}
+
+			showAllErrors({file: folderName + "*", folder: 0});
+			dijit.byId("mainTab").selectChild(dijit.byId("errorsTab"));
+		}
+		var chartInitialized = false;
+
+		dojo.subscribe("mainTab-selectChild", function(tab){
+			if(chartInitialized || tab.id != "chartTab"){
+				return;
+			}
+			chartInitialized = true;
+			checkstyleStore.fetch({query: {file: "*"}, onComplete: initializeChart});
+		});
+		function initializeChart(items) {
+			
+			dojo.require("dojox.charting.DataChart");
+			dojo.require("dojox.charting.action2d.Highlight");
+			dojo.require("dojox.charting.action2d.Tooltip");
+			dojo.require("dojox.charting.plot2d.Columns");
+			
+			var folderCounts = {};
+						
+			dojo.forEach(items, function(item){
+			  var fileName = checkstyleStore.getValue(item, "file");
+			  
+			  var parts = fileName.split("/");
+			  if (parts.length < 2) {
+			  	return;
+			  }
+			  var folderName = parts[0] + "/" + parts[1];
+			  
+			  if (!folderCounts[folderName]) {
+			  	folderCounts[folderName] = 0;
+			  }
+			  folderCounts[folderName]++;
+			});
+			
+			var folderCountsArr = [];
+
+			for (var x in folderCounts) {
+			  folderCountsArr.push({"folder": x, count: folderCounts[x]});
+			}
+			folderCountsArr.sort(function(a, b){
+			  if(a.count < b.count) {
+			  	return 1;
+			  } else if(a.count > b.count){
+			  	return -1;
+			  }
+			  return 0;
+			});
+
+			if (folderCountsArr.length > 20) {
+				folderCountsArr = folderCountsArr.slice(0, 20);
+			}
+			dojo.forEach(folderCountsArr, function(item, index){
+				item.id = index + 1;
+			});
+			var chartStore = new dojo.data.ItemFileReadStore({
+				data: {
+					identifier: 'id',
+					label: 'folder',
+					items: folderCountsArr
+				}
+			});
+			var chart = new dojox.charting.DataChart("chart", {
+				displayRange:12,
+				yaxis:{
+					max: folderCountsArr[0].count + 10, 
+					min: Math.max(0, folderCountsArr[folderCountsArr.length -1].count - 10), 
+					majorTickStep: Math.round(folderCountsArr[0].count / 10), 
+					maxLabelSize:20,
+					labelFunc: function(val) {
+						return val;
+					}
+				},
+				xaxis: {
+					labelFunc: "seriesLabels",
+					maxLabelSize:30
+				},
+				scroll:false,
+				type: dojox.charting.plot2d.Columns
+			});
+			
+			
+			var dc = dojox.charting;
+			new dc.action2d.Highlight(chart, "default");
+			new dc.action2d.Tooltip(chart, "default");
+			
+			chart.setStore(chartStore, {folder: "*"}, "count");	
+		}
+		
+		function formatMessage(item) {
+			return (singleFileStore || checkstyleStore).getValue(item, "msg");
+		}
+		
+		function doEdit(item) {
+			var grid = dijit.byId("messagesGrid");
+			var textarea = dojo.byId("editInput");
+			
+			var q = {folder: 0};
+			
+			if (errorQuery) {
+				q.file = errorQuery.file;
+			}
+			
+			grid.store.fetch({
+				query: q,
+				start: item.rowIndex,
+				count: 1,
+				onComplete: function(items) {
+					var file = grid.store.getValue(items[0], "file");
+					var line = grid.store.getValue(items[0], "line");
+
+					if (textarea._file != file) {
+						if (textarea._file) {
+							if(cachedFiles[textarea._file] && cachedFiles[textarea._file] != textarea.value) {
+								changedFiles.push(textarea._file);
+							}
+							cachedFiles[textarea._file] = textarea.value;
+						}
+						textarea._file = file;
+						if (cachedFiles[file]) {
+							textarea.value = cachedFiles[file];
+						}
+						else {
+							loadFile(file, line);
+						}
+					} else {
+						gotoLine(line);
+					}
+				}
+			});
+		}
+		
+		function loadFile(file, line) {
+			var textarea = dojo.byId("editInput");
+			textarea.value = "Loading....";
+			dojo.xhrGet({
+				url: "../../" + file,
+				type: "text",
+				load: function(text)  {
+					textarea.value = text;
+					dijit.byId("showFileErrorsBtn").attr("disabled", false);
+					gotoLine(line);
+				}
+			});
+		}
+		
+		function gotoLine(line) {
+			var count = line;
+			var textarea = dojo.byId("editInput");
+			var str = textarea.value;
+			var i;
+			for (i = 0; i < str.length && count > 1; i++) {
+				if (str.charAt(i) == "\n") {
+					count--;
+				}
+			}
+			var nextNL = str.indexOf("\n", i + 1);
+			selectChars(textarea, i, nextNL < 0 ? str.length - 1 : nextNL);
+		}
+		
+		function selectChars(textarea, start, end) {
+			
+			if(textarea.setSelectionRange){
+				setTimeout(function(){
+				//	textarea.focus();
+					textarea.setSelectionRange(start, start + 1);	
+					var ev = document.createEvent("KeyEvents");
+					ev.initKeyEvent("keypress", true, true, window, false, false, false, false, 0,
+						textarea.value.charCodeAt(start));
+					textarea.dispatchEvent(ev);
+					textarea.setSelectionRange(start, end);	
+					textarea.focus();
+				}, 10);
+				
+			}else if(dojo.doc.selection){ //IE
+				
+				var range = dojo.doc.selection.createRange();
+				// delete overflow characters
+				range.moveStart("character", start);
+				range.text = '';
+				// show cursor
+				range.select();
+			}
+		}
+		
+		function showCurrentErrors(){
+			dijit.byId("showAllErrorsBtn").attr("checked", false);
+			dijit.byId("showFileErrorsBtn").attr("checked", true);
+			
+			var textarea = dojo.byId("editInput");
+			var value = textarea.value;
+			checkstyleUtil.clear();
+
+			checkstyleUtil.applyRules(textarea._file, value);
+			var report = checkstyleUtil.generateReport(true);
+			var storeData = dojo.eval("(" + report + ")");
+			
+			singleFileStore = new dojo.data.ItemFileReadStore({
+				data: storeData
+			});
+
+			var grid = dijit.byId("messagesGrid");
+			errorQuery = null;
+			grid.setStore(singleFileStore, {folder: 0}, grid.attr("queryOptions"));
+		}
+
+		function showAllErrors(query){
+			errorQuery = query;
+		
+			dijit.byId("showFileErrorsBtn").attr("checked", false);
+			dijit.byId("showAllErrorsBtn").attr("checked", true);
+			var grid = dijit.byId("messagesGrid");
+			singleFileStore = null;
+			grid.setStore(checkstyleStore, query || grid.attr("query"), grid.attr("queryOptions"));
+		}
+		
+		function makeSimpleFixes() {
+			var textarea = dojo.byId("editInput");
+		
+			textarea.value = checkstyleUtil.makeSimpleFixes(textarea.value);
+			
+			if(dojo.indexOf(changedFiles, textarea._file) < 0) {
+				changedFiles.push(textarea._file);
+			}
+			showCurrentErrors();
+		}
+		
+		function saveFile(fileName, contents, callback) {
+			var textarea = dojo.byId("editInput");
+			fileName = fileName || textarea._file;
+			contents = contents || textarea.value;
+			
+			dojo.xhrPost({
+				url: "checkstyle.php",
+				content: {
+					action: "save",
+					filename: fileName,
+					contents: contents
+				}, 
+				handle: function(text, reqObj){
+					if (reqObj.xhr.readyState != 4) {
+						return;
+					}
+					if (reqObj.xhr.status == 200) {
+						if (!callback) {
+							alert("File " + fileName + " saved");
+						} else {
+							callback(true);
+						}
+						var idx = dojo.indexOf(changedFiles, fileName);
+						array.splice(idx, 1);
+					}
+					else if (callback){
+						callback(false);
+					} else {
+						alert("Failed to save file " + fileName + ". " + saveErrorMsg);
+					}
+				}
+			});
+		}
+		
+		function showSaveDialog(){
+			if (changedFiles.length == 0) {
+				alert("No files have been altered yet.");
+				return;
+			}
+			
+			var checksNode = dojo.byId("checks");
+			dojo.empty(checksNode);
+			
+			dojo.forEach(changedFiles, function(fileName){
+				dojo.create("div", {
+					innerHTML: "<label for='" + fileName + "'>" + fileName + "</label>"
+						+ "<input type='checkbox' id='" + fileName + "'></input>"
+				}, checksNode);
+			});
+			dijit.byId("changedFilesDlg").show();
+		}
+		
+		function saveAllChangedFiles(){
+			var successes = 0;
+			var inputs = dojo.query("input", "checks").forEach(
+				function(input) {
+					if (!input.checked) {
+						return;
+					}
+					var fileName = dojo.attr(input, "id");
+					saveFile(fileName, cachedFiles[fileName], function(success){
+						if (!success) {
+							alert("Failed to save " + fileName
+								+ saveErrorMsg);
+						} else {
+							successes++;
+							if (successes = inputs.length) {
+								alert("All files saved successfully");
+								dijit.byId("changedFilesDlg").hide();
+							}
+						}
+					});
+				}
+			);
+		}
+		
+		var checkstyleStore;
+		
+		dojo.xhrGet({
+			url: "checkstyleData.js",
+			sync: true,
+			handleAs: "json",
+			load: function(data) {
+				checkstyleStore = new dojo.data.ItemFileReadStore({
+					data: data
+				});
+			},
+			error: function(){
+				alert("Error: could not load the checkstyle data. You should run the checkstyle tool in util/checkstyle/");
+			}
+		});
+	</script>
+</head>
+<body class="soria">
+	
+	<div dojoType="dijit.layout.BorderContainer" design="sidebar" id="main">
+		<div id="folders" dojoType="dijit.layout.ContentPane" region="leading" 
+			style="width: 200px;padding: 0;" splitter="true">
+			<table dojoType="dojox.grid.DataGrid"id="folderGrid"
+				store="checkstyleStore" style="height: 100%; width: 100%;"
+				query="{ folder: 1 }" rowsPerPage="20" rowSelector="20px"
+				onCellClick="onFolderClick(arguments[0])"
+				>
+				<thead>
+					<tr>
+						<th field="file" width="auto">Folders</th>
+					</tr>
+				</thead>
+			</table>
+		</div>
+		<div id="header" dojoType="dijit.layout.ContentPane" region="top" style="height: 50px;">
+			<h1>Checkstyle results from <span id="reportDate"></span>
+				Total errors:<span id="totalErrors"></span>
+			</h1>
+		</div>
+		<div id="mainTab" dojoType="dijit.layout.TabContainer" region="center" style="padding: 0;">
+			<div id="errorsTab" dojoType="dijit.layout.BorderContainer" title="Error List" style="height:100%;width:100%;">
+				<table dojoType="dojox.grid.DataGrid" id="messagesGrid"
+					class="checkstyleGrid" store="checkstyleStore" 
+					query="{ folder: 0 }" rowsPerPage="50" rowSelector="20px"
+					region="top"
+					style="height:50%;"
+					>
+					<script type="dojo/connect" event="_onFetchBegin" args="size, req">
+						dojo.byId("totalErrors").innerHTML = size;
+					</script>
+					<thead>
+						<tr>
+							<th field="file" width="300px">File</th>
+							<th field="line" width="40px">Line</th>
+							<th field="msg" width="auto" formatter="formatMessage">Message</th>
+						</tr>
+					</thead>
+				</table>
+				<div dojoType="dijit.layout.ContentPane" region="bottom" splitter="true" style="height:45%;">
+					<div>
+						<div dojoType="dijit.form.ToggleButton" 
+							 id="showFileErrorsBtn"
+							 label="Show File Errors" 
+							 iconClass="dijitRadioIcon"
+							 onclick="showCurrentErrors()"
+							 disabled="true"
+							 ></div>
+						<div dojoType="dijit.form.ToggleButton" 
+							 id="showAllErrorsBtn"
+							 label="Show All Errors" 
+							 iconClass="dijitRadioIcon"
+							 checked="true"
+							 onclick="showAllErrors()"></div>
+						<div dojoType="dijit.form.Button" 
+							 id="makeFixesBtn"
+							 label="Make Fixes" 
+							 onclick="makeSimpleFixes()"></div>
+						<div dojoType="dijit.form.Button" 
+							 id="saveFileBtn"
+							 label="Save" 
+							 onclick="saveFile()"></div>
+						<div dojoType="dijit.form.Button" 
+							 id="saveAllFileBtn"
+							 label="Save All" 
+							 onclick="showSaveDialog()"></div>
+					</div>
+					<div>
+						<textarea id="editInput" rows="7" cols="100"></textarea>
+					</div>
+				</div>
+			</div>
+			<div id="chartTab" dojoType="dijit.layout.BorderContainer" style="width:100%;height:100%;" title="Worst Modules">
+				<div dojoType="dijit.layout.ContentPane" region="top">
+					This chart displays the folders of depth 2 in descending order of checkstyle violations.
+				</div>
+				<div dojoType="dijit.layout.ContentPane" region="center">
+					<div id="chart" style="height:400px; width: 1000px;"></div>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div dojoType="dijit.Dialog" id="changedFilesDlg" title="Save Changed Files">
+		<div id="checks">
+			
+		</div>
+		<div dojoType="dijit.form.Button" label="Save" onclick="saveAllChangedFiles()"></div>
+		<div dojoType="dijit.form.Button" label="Cancel" onclick="dijit.byId('changedFilesDlg').hide();"></div>
+	</div>
+</body>
+</html>
diff --git a/util/checkstyle/checkstyleUtil.js b/util/checkstyle/checkstyleUtil.js
new file mode 100644
index 0000000..046f060
--- /dev/null
+++ b/util/checkstyle/checkstyleUtil.js
@@ -0,0 +1,828 @@
+checkstyleUtil = {
+	errors: [],
+	
+	commentNames: ["summary", "description", "example", "tags", "this"]
+};
+
+checkstyleUtil.applyRules = function(fileName, contents){
+	// Do not process JSON files
+	if(contents.charAt(0) == "{"){
+		return;
+	}
+	
+	// Mark all the characters that are in comments.
+	var comments = checkstyleUtil.getComments(contents);
+	
+	// Apply all the rules to the file
+	for(var ruleName in checkstyleUtil.rules){
+		checkstyleUtil.rules[ruleName](fileName, contents, comments);
+	}
+};
+
+// Calculate the characters in a file that are in comment fields
+// These will be ignored by the checkstyle rules.
+checkstyleUtil.getComments = function(contents){
+	var comments = [];
+	
+	var i;
+	
+	// Initialize the array to false values.
+	for(i = 0; i < contents.length; i++){
+		comments[i] = 0;
+	}
+	
+	var sep = "\n";
+	
+	function markRange(start, stop){
+		for(var i = start; i < stop; i++){
+			comments[i] = 1;
+		}
+	}
+
+
+	function markRegexs() {
+		var idx = contents.indexOf("/g");
+		var i;
+		while(idx > -1) {
+			if(!comments[idx] && contents.charAt(idx - 1) != "*"){
+				// Look back until either a forward slash
+				// or a new line is found
+				var prevChar = contents.charAt(idx - 1);
+				i = idx;
+				while(prevChar != "\n" && prevChar != "/" && i > 0){
+					prevChar = contents.charAt(--i);
+				}
+				if(prevChar == "/" && i < idx - 1){
+					markRange(i, idx);
+				}
+			}
+			idx = contents.indexOf("/g", idx + 2)
+		}
+		
+		// Now mark all .match and .replace function calls
+		// They generally contain regular expressions, and are just too bloody difficult.
+		var fnNames = ["match", "replace"];
+		var name;
+		
+		for (i = 0; i < fnNames.length; i++){
+			name = fnNames[i];
+			
+			idx = contents.indexOf(name + "(");
+			
+			while(idx > -1){
+				// Find the end parenthesis
+				if(comments[idx]){
+					idx = contents.indexOf(name + "(", idx + name.length);
+				} else {
+					var fnEnd = contents.indexOf(")", idx);
+					markRange(idx, fnEnd + 1);
+				}
+			}
+		}
+		
+		// Now look for all the lines that declare a regex variable, e.g.
+		// var begRegExp = /^,|^NOT |^AND |^OR |^\(|^\)|^!|^&&|^\|\|/i; 
+		
+		idx = contents.indexOf(" = /");
+		
+		while(idx > -1){
+			if(!comments[idx] && contents.charAt(idx + 4) != "*"){
+				var eol = contents.indexOf("\n", idx + 1);
+				markRange(idx + 3, Math.max(eol, idx + 4));
+			}
+		
+			idx = contents.indexOf(" = /", idx + 3);
+		}
+	}
+
+	markRegexs();
+	
+	
+	var marker = null;
+	var ch;
+	
+	var DOUBLE_QUOTE = 1;
+	var SINGLE_QUOTE = 2;
+	var LINE_COMMENT = 3;
+	var MULTI_COMMENT = 4;
+	var UNMARK = 5;
+	
+	var pos;
+	
+	for (i = 0; i < contents.length; i++) {
+		var skip = false;
+		
+		if(comments[i]){
+			continue;
+		}
+		
+		ch = contents[i];
+		
+		switch(ch){
+			case "\"":
+				if(marker == DOUBLE_QUOTE) {
+					marker = UNMARK;
+				} else if (marker == null) {
+					marker = DOUBLE_QUOTE;
+					pos = i;
+				}
+				
+				break;
+			case "'":
+				if(marker == SINGLE_QUOTE) {
+					marker = UNMARK;
+				} else if (marker == null) {
+					marker = SINGLE_QUOTE;
+					pos = i;
+				}
+			
+				break;
+			case "/":
+				if(marker == null){
+					if(contents[i + 1] == "/"){
+						marker = LINE_COMMENT;
+						pos = i;
+						skip = true;
+					} else if(contents[i + 1] == "*"){
+						marker = MULTI_COMMENT;
+						pos = i;
+						skip = true;
+					}
+				}
+				
+				break;
+			case "*":
+				if (marker == MULTI_COMMENT){
+					if(contents[i + 1] == "/"){
+						marker = UNMARK;
+						skip = true;
+					}
+				}
+			
+				break;
+			case "\n":
+				if(marker == LINE_COMMENT){
+					marker = UNMARK;
+				}
+				break;
+		
+		}
+		if (marker != null) {	
+			comments[i] = 1;
+		}
+		if (marker == UNMARK){
+			marker = null;
+		}
+		if  (skip) {
+			i++;
+			comments[i] = 1;
+		}
+	}
+	
+	
+	return comments;
+}
+
+// Calculate the line number of the character at index 'pos'
+checkstyleUtil.getLineNumber = function(contents, pos){
+	var counter = 0;
+	var sep = "\n";
+		
+	for(var i = pos; i > -1; i--){
+		if(contents.charAt(i) == "\n"){
+			counter ++;
+		}
+	}
+	return counter + 1;
+};
+
+// Store the information for a single error.
+checkstyleUtil.addError = function(msg, fileName, contents, pos){
+	while(fileName.indexOf("../") == 0){
+		fileName = fileName.substring(3);
+	}
+	checkstyleUtil.errors.push({
+		file: fileName,
+		line: checkstyleUtil.getLineNumber(contents, pos),
+		message: msg
+	});
+};
+
+// Find the next character in 'contents' after the index 'start'
+// Spaces and tabs are ignored.
+checkstyleUtil.getNextChar = function(contents, start, comments, ignoreNewLine){
+	for(var i = start; i < contents.length; i++){
+		if(comments && comments[i]){
+			continue;
+		}
+		if(contents.charAt(i) != " " 
+			&& contents.charAt(i) != "\t" 
+			&& (!ignoreNewLine || contents.charCodeAt(i) != 13)){
+			return {
+				value: contents[i],
+				pos: i
+			};
+		}
+	}
+	return null;
+};
+
+// Find the next occurrence of the character in the 
+// 'contents' array after the index 'start'
+checkstyleUtil.findNextCharPos = function(contents, start, character){
+	for(var i = start; i < contents.length; i++){
+		if(contents.charAt(i) == character){
+			return i;
+		}
+	}
+	return -1;
+};
+
+// Creates a simple function that searches for the token, and 
+// adds an error if it is found
+checkstyleUtil.createSimpleSearch = function(token, message){
+	return function(fileName, contents, comments){
+		var idx = contents.indexOf(token);
+		
+		while(idx > -1){
+			
+			if(!comments[idx]){
+				checkstyleUtil.addError(message, fileName, contents, idx);
+			}
+			idx = contents.indexOf(token, idx + 1);
+		}
+	};
+};
+
+// Creates a function that fails a test if the given token
+// does not have a space to the left and right.
+checkstyleUtil.createSpaceWrappedSearch = function(token, message){
+	return function(fileName, contents, comments){
+		
+		var idx = contents.indexOf(token);
+		var before, after;
+		var tokenLength = token.length;
+
+		while(idx > -1){
+			before = contents.charAt(idx - 1);
+			after = contents.charAt(idx + tokenLength);
+			if(!comments[idx] && 
+				((before != " " && before != "\t" 
+					&& (token != "==" || before != "!")
+					&& (token != "=" || 
+						(before != "<" && 
+						 before != ">" && 
+						 before != "=" && 
+						 before != "!" && 
+						 before != "+" && 
+						 before != "-" && 
+						 before != "*" && 
+						 before != "/" && 
+						 before != "&" && 
+						 before != "|" ))) || 
+				(
+					(after != " " && contents.charCodeAt(idx + tokenLength) != 13 
+						&& contents.charCodeAt(idx + tokenLength) != 10)
+					&& (token != "==" || after != "=")
+					&& (token != "!=" || after != "=")
+					&& (token != "<" || after != "=")
+					&& (token != ">" || after != "=")
+					&& (token != "=" || after != "=")
+					&& (token != "&" || after != "=")
+					&& (token != "|" || after != "=")
+					&& (token != "+" || after != "=")
+					&& (token != "-" || after != "=")
+					&& (token != "*" || after != "=")
+					&& (token != "/" || after != "=")
+				))){
+				checkstyleUtil.addError(message, fileName, contents, idx);
+			}
+			idx = contents.indexOf(token, idx + token.length);
+		}
+	};
+};
+
+
+
+checkstyleUtil.isEOL = function(contents, pos){
+	var c = contents.charCodeAt(pos);
+	return c == 10 || c == 13 || contents.charAt(pos) == "\n";
+};
+
+// All the rules that will be applied to each file.
+checkstyleUtil.rules = {
+
+	"elseFollowedBySpace": function(fileName, contents, comments){
+		var idx = contents.indexOf("else ");
+		while(idx > -1){
+
+			if(!comments[idx] && contents.substring(idx + 5, idx + 7) != "if"){
+				checkstyleUtil.addError("\" else \" cannot be followed by a space", fileName, contents, idx);
+			}
+			idx = contents.indexOf("else {", idx + 1);
+		}
+	},
+	
+	"trailingComma" : function(fileName, contents, comments){
+		
+		var s = ",";
+		var idx = contents.indexOf(s);
+		var nextChar;
+		
+		while(idx > -1){
+			if(!comments[idx]){
+				nextChar = checkstyleUtil.getNextChar(contents, idx + 1, comments, true);
+				if(nextChar && nextChar.value == "}"){
+					checkstyleUtil.addError("Trailing commas are not permitted", fileName, contents, idx);
+				}
+			}
+			idx = contents.indexOf(s, idx + 1);
+		}
+	},
+	
+	"switchCaseNewLine" : function(fileName, contents, comments){
+		var s = "\tcase ";
+		var idx = contents.indexOf(s);
+		var nextColonIdx;
+		var eolIdx;
+		
+		while(idx > -1){
+			
+			if(!comments[idx]){
+				eolIdx = contents.indexOf("\n", idx + 4);
+				
+				if(eolIdx > idx){
+					// Count backwards from the end of the line.
+					// The first character, that is not a comment,
+					// Should be a ':'
+					
+					for(var i = eolIdx; i > idx + 4; i--){
+						var c = contents.charAt(i);
+						if(!comments[i] 
+							&& c != ' '
+							&& c != '\t'
+							&& c != ':'
+							&& !checkstyleUtil.isEOL(contents, i)){
+							checkstyleUtil.addError(
+								"A CASE statement should be followed by a new line", 
+								fileName, contents, idx);
+							break;
+						}
+						if(c == ':'){
+							break;
+						}
+					}
+				}
+			}
+			idx = contents.indexOf(s, idx + 4);
+		}
+	},
+	
+	"curlyBraceAtStartOfLine": function(fileName, contents, comments){
+		
+		var idx = contents.indexOf("\n");
+		
+		while(idx > -1){
+			var nextChar = checkstyleUtil.getNextChar(contents, idx + 1);
+			
+			if(nextChar && !comments[nextChar.pos] && nextChar.value == "{"){
+				// Go back three lines, and look for "dojo.declare".  If it exists in the last three lines,
+				// then it is ok to have  { at the start of this line.
+				
+				var nlCount = 0;
+				var i;
+				for(i = idx - 1; i > -1 && nlCount < 3; i--){
+					if(contents[i] == "\n"){
+						nlCount++;
+					}
+				}
+				var declarePos = contents.indexOf("dojo.declare", Math.max(0, i));
+				if(declarePos < 0 || declarePos > idx){
+					checkstyleUtil.addError("An opening curly brace should not be the first on a line", fileName, contents, idx);
+				}
+			}
+			idx = contents.indexOf("\n", idx + 1);
+		}
+	},
+	
+	"parenthesisSpaceCurlyBrace": checkstyleUtil.createSimpleSearch(") {", "A space is not permitted between a closing parenthesis and a curly brace"),
+	
+	"useTabs": function(fileName, contents, comments){
+		
+		var idx = contents.indexOf("  ");
+		
+		while(idx > -1){
+			var nextChar = checkstyleUtil.getNextChar(contents, idx + 1);
+			if(!comments[idx] && nextChar && nextChar.value.charCodeAt(0) != 13){
+				checkstyleUtil.addError("Tabs should be used instead of spaces", fileName, contents, idx);
+				var nextLine = checkstyleUtil.findNextCharPos(contents, idx + 1, "\n");
+				if(nextLine < 0){
+					break;
+				}
+				idx = contents.indexOf("  ", nextLine + 1);
+			} else{
+				idx = contents.indexOf("  ", idx + 2);
+			}
+		}
+	},
+	
+	"commentFormatting": function(fileName, contents, comments){
+		
+		var commentNames = checkstyleUtil.commentNames;
+		var invalidPrefixes = ["//", "//\t"];
+		var idx;
+		
+		for(var i = 0; i < commentNames.length; i++){
+			var comment = commentNames[i];
+
+			for(var j = 0; j < invalidPrefixes.length; j++){
+				idx = contents.indexOf(invalidPrefixes[j] + comment + ":");
+
+				// Make sure that there is a space before the comment.
+				while(idx > -1){
+					checkstyleUtil.addError("Must be just a space in a comment before \"" + comment + "\"" , fileName, contents, idx);
+					var nextLine = checkstyleUtil.findNextCharPos(contents, idx + 1, "\n");
+					if(nextLine < 0){
+						break;
+					}
+					idx = contents.indexOf(invalidPrefixes[j] + comment + ":", nextLine);
+				}
+			}
+			
+			idx = contents.indexOf(comment + ":");
+			
+			// Make sure that the comment name is on a line by itself. The body of the comment
+			// must be on the next line.
+			while(idx > -1){
+				if(comments[idx]){
+					var search = idx + comment.length + 1;
+				
+					// Make sure that there is nothing after the comment name on the same line.
+					while(!checkstyleUtil.isEOL(contents, search)){
+						if(contents[search] != " " && contents[search] != "\t"){
+							checkstyleUtil.addError("The comment \"" + comment + "\" must be followed by a new line" , 
+										fileName, contents, idx);
+							break;
+						}
+						search++;
+					}
+				}
+				idx = contents.indexOf(comment + ":", idx + comment.length + 2);
+			}
+		}
+	},
+	
+	"spacesAroundEquals": checkstyleUtil.createSpaceWrappedSearch("==", "The equals sign should be preceded and followed by a space"),
+	"spacesAroundNotEquals": checkstyleUtil.createSpaceWrappedSearch("!=", "The != sign should be preceded and followed by a space"),
+	"spacesAroundAssignment": checkstyleUtil.createSpaceWrappedSearch("=", "The = sign should be preceded and followed by a space"),
+	"spacesAroundOr": checkstyleUtil.createSpaceWrappedSearch("||", "The || sign should be preceded and followed by a space"),
+	"spacesAroundLessThan": checkstyleUtil.createSpaceWrappedSearch("<", "The < sign should be preceded and followed by a space"),
+	"spacesAroundGreaterThan": checkstyleUtil.createSpaceWrappedSearch(">", "The > sign should be preceded and followed by a space"),
+	"spacesAroundAnd": checkstyleUtil.createSpaceWrappedSearch("&&", "The && sign should be preceded and followed by a space")
+};
+
+var noSpaceAfter = ["catch","do","finally","for","if","switch","try","while","with"];
+
+// Add checks for all the elements that are not allowed to have a space after them.
+checkstyleUtil.createNoSpaceAfterFunction = function(name){
+	checkstyleUtil.rules["noSpaceAfter" + noSpaceAfter[i] + "1"] = 
+		checkstyleUtil.createSimpleSearch(" " + name +" ", "\" " + name + " \" cannot be followed by a space");
+	checkstyleUtil.rules["noSpaceAfter" + noSpaceAfter[i] + "2"] = 
+		checkstyleUtil.createSimpleSearch("\t" + name +" ", "\" " + name + " \" cannot be followed by a space");
+}
+
+for(var i = 0; i < noSpaceAfter.length; i++){
+	checkstyleUtil.createNoSpaceAfterFunction(noSpaceAfter[i]);
+}
+
+checkstyleUtil.clear = function(){
+	checkstyleUtil.errors = [];
+}
+
+checkstyleUtil.serializeErrors = function(){
+	var buf = [];
+	var errs = checkstyleUtil.errors;
+	for(var i = 0; i < errs.length; i++){
+		buf.push(errs[i].file + ":" + errs[i].line + " - " + errs[i].message);
+	}
+	return buf.join("\n");
+}
+
+checkstyleUtil.makeSimpleFixes = function(contents){
+	
+	var comments = checkstyleUtil.getComments(contents);
+	for(var i = 0; i < noSpaceAfter.length; i++){
+		contents = checkstyleUtil.fixSpaceAfter(contents, noSpaceAfter[i], comments);
+	}
+	/*
+	contents = contents.split("    ").join("\t")
+				.split("  ").join("\t")
+				.split(") {").join("){")
+				.split("\tif (").join("\tif(")
+				.split("} else").join("}else")
+				.split("}\telse").join("}else")
+				.split("}else {").join("}else{")
+				.split("\twhile (").join("\twhile(")
+				.split("\tfor (").join("\tfor(")
+				.split("\tswitch (").join("\tswitch(");
+	*/
+	
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "=  ", "= ", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "    ", "\t", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "  ", "\t", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "\tif (", "\tif(", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "} else", "}else", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "}\telse", "}else", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "}else {", "}else{", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "\twhile (", "\twhile(", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "\tfor (", "\tfor(", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "\tswitch (", "\tswitch(", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.replaceAllExceptComments(contents, ") {", "){", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "//summary:", "// summary:", {});
+	contents = checkstyleUtil.replaceAllExceptComments(contents, "//description:", "// description:", {});
+	comments = checkstyleUtil.getComments(contents);
+	
+	contents = checkstyleUtil.fixTrailingWhitespace(contents);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "===", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "!==", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "<=", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "<", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, ">=", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, ">", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "!=", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "==", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "=", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "||", comments);
+	comments = checkstyleUtil.getComments(contents);
+	contents = checkstyleUtil.fixSpaceBeforeAndAfter(contents, "&&", comments);
+	comments = checkstyleUtil.getComments(contents);
+	
+	contents = checkstyleUtil.fixCommentNames(contents);
+	
+	
+	
+	return contents;
+}
+
+checkstyleUtil.fixCommentNames = function(contents){
+	var commentNames = checkstyleUtil.commentNames;
+	var i;
+	
+	for(i = 0; i < commentNames.length; i++){
+		contents = checkstyleUtil.replaceAllExceptComments(contents, "//\t" + commentNames[i] + ":", "// " + commentNames[i] + ":", {});
+	}
+	
+	for(i = 0; i < commentNames.length; i++){
+		var commentName = commentNames[i];
+		var searchToken = "// " + commentName + ":";
+		var idx = contents.indexOf(searchToken);
+		
+		
+		while(idx > -1){
+			// If the comment name is not followed immediately by a new line, then insert a new line,
+			// two forward slashes and two tabs.
+			if(!checkstyleUtil.isEOL(contents, idx + commentName.length + 4)){
+				// Calculate how many tabs to put before the "//"
+				
+				var tabs = "";
+				var search = idx - 1;
+				while(!checkstyleUtil.isEOL(contents, search)){
+					tabs += contents.charAt(search);
+					search--;
+				}
+				var insertPos = idx + commentName.length + 4;
+				if(contents.charAt(insertPos) == " " || contents.charAt(insertPos) == "\t"){
+					contents = checkstyleUtil.deleteChar(contents, insertPos);
+				}
+				
+				contents = checkstyleUtil.insertChar(contents, "\n" + tabs + "//\t\t", idx + commentName.length + 4);
+			
+			}
+			idx = contents.indexOf(searchToken, idx + commentName.length);
+		}
+	}
+	return contents;
+}
+
+
+checkstyleUtil.replaceAllExceptComments = function(contents, old, newStr, comments){
+	var idx = contents.indexOf(old);
+	var toRemove = [];
+	
+	while(idx > -1){
+		if(!comments[idx]){
+			toRemove.push(idx);		
+		}
+
+		idx = contents.indexOf(old, idx + old.length);
+	}
+	
+	// Process the string backwards so we don't have to recompute the comments each time.
+	for(var i = toRemove.length - 1; i > -1; i--){
+		idx = toRemove[i];
+		if(!comments[idx]){
+			contents = contents.substring(0, idx)
+					+ newStr
+					+ contents.substring(idx + old.length, contents.length);
+		}
+	}
+	return contents;
+}
+
+checkstyleUtil.insertChar = function(contents, ch, pos){
+	return contents.substring(0, pos) + ch + contents.substring(pos);
+}
+checkstyleUtil.deleteChar = function(contents, pos){
+	return contents.substring(0, pos) + contents.substring(pos + 1);
+}
+
+checkstyleUtil.fixTrailingWhitespace = function(contents) {
+	var idx = contents.indexOf("\n");
+	
+	// Find each new line character, then iterate backwards until a non-whitespace character is found
+	// then remove the whitespace.
+	while(idx > -1){
+		var search = idx - 1;
+		
+		while(search > -1 && (contents.charAt(search) == " " || contents.charAt(search) == "\t")){
+			search--;
+		}
+		
+		if(search < idx -1){
+			contents = contents.substring(0, search + 1)
+					+ contents.substring(idx, contents.length);
+			
+			idx = contents.indexOf("\n", search + 2);
+		}else{
+			idx = contents.indexOf("\n", idx + 1);
+		}
+	}
+
+	return contents;
+}
+
+checkstyleUtil.fixSpaceAfter = function(contents, token, comments){
+	var idx = contents.indexOf(token + " ");
+	
+	while(idx > -1){
+		if(!comments[idx]){
+			contents = checkstyleUtil.deleteChar(contents, idx + token.length);
+		}
+		
+		idx = contents.indexOf(token + " ", idx + token.length);
+	}
+	return contents;
+}
+
+checkstyleUtil.fixSpaceBeforeAndAfter = function(contents, token, comments){
+	var idx = contents.indexOf(token);
+	var before, after;
+	var len = token.length;
+
+	while(idx > -1){
+		before = contents.charAt(idx - 1);
+		after = contents.charAt(idx + len);
+		if(!comments[idx]){
+			// Only insert a space before the token if:
+			// - char before is not a space or a tab
+			// - token is "==" and the char before is neither "!" or "="
+		
+			if(before != " " && before != "\t" 
+				&& (token != "==" || (before != "!" && before != "="))
+				&& (token != "=" || 
+						(before != "<" && 
+						 before != ">" && 
+						 before != "=" && 
+						 before != "!" && 
+						 before != "+" && 
+						 before != "-" && 
+						 before != "*" && 
+						 before != "/" && 
+						 before != "&" && 
+						 before != "|" ))
+				){
+				
+				contents = checkstyleUtil.insertChar(contents, " ", idx);
+				idx ++;
+			}
+			
+			// Only insert a space after the token if:
+			// - char after is not a space
+			// - char after is not a new line
+			// - char after is not "="
+			if((after != " " && contents.charCodeAt(idx + len) != 13 
+					&& contents.charCodeAt(idx + len) != 10)
+					&& (token != "==" || after != "=")
+					&& (token != "!=" || after != "=")
+					&& (token != "=" || after != "=")
+					&& (token != "<" || after != "=")
+					&& (token != ">" || after != "=")
+					&& (token != "&" || after != "=")
+					&& (token != "|" || after != "=")
+					&& (token != "+" || after != "=")
+					&& (token != "-" || after != "=")
+					&& (token != "*" || after != "=")
+					&& (token != "/" || after != "=")
+					
+					){
+				contents = contents = checkstyleUtil.insertChar(contents, " ", idx + token.length);
+				idx++;
+			}
+		}
+		idx = contents.indexOf(token, idx + token.length);
+	}
+	return contents;
+}
+
+// Creates the data file suitable to be loaded into a dojo.data.ItemFileReadStore
+checkstyleUtil.generateReport = function(skipPrint){
+	
+	var ids = 1;
+	var json = ["{id:'" +(ids++) + "', file: 'All', isFolder:true}"];
+
+	// A map of folders that have already been found.
+	var allFolders = {};
+	
+	var messageIds = {};
+	var messageCounter = 1;
+	var i, err;
+	
+	function getFolderName(fileName){
+		// Extract the folder name from a file name
+		var idx = fileName.lastIndexOf("/");
+		return fileName.substring(0, idx);
+	}
+	
+	// Add a folder to the list of folders.
+	function pushFolder(folderName){
+		if(!allFolders[folderName]){
+			allFolders[folderName] = true;
+			json.push("{id: '" +(ids++) + "', file: '" + folderName + "', folder: 1}");
+		}
+	}
+	
+	for(i = 0; i < checkstyleUtil.errors.length; i++){
+		err = checkstyleUtil.errors[i];
+		var message = err.message;
+		var messageId = messageIds[message];
+		if(!messageId){
+			messageId = "m" + messageCounter++;
+			messageIds[message] = messageId;
+			
+			json.push("{id:'" + messageId + 
+					"',msg:'" + message + 
+					"'}");
+		}
+	}
+	
+	pushFolder("All");
+	
+	// Create the JSON records for each error.
+	for(i = 0; i < checkstyleUtil.errors.length; i++){
+		err = checkstyleUtil.errors[i];
+		var folderName = getFolderName(err.file);
+		pushFolder(folderName);
+		
+		json.push("{id:'" +(ids++) + 
+					"', file:'" + err.file + 
+					"',line:" + err.line + 
+					",msg:{'_reference':'" + messageIds[err.message] + 
+					//"'},folder:'" + folderName +
+					"'},folder: 0" +
+					"}");
+		
+	}
+
+	// Add the date that the check was run to the store.
+	json.push("{id:'" +(ids++) + "', date: " +(new Date()).getTime() + "}");
+	
+	// Save the file.
+
+	if(!skipPrint){
+		print("Found " + checkstyleUtil.errors.length + " checkstyle errors. " +
+		"Open the file checkstyleReport.html to view the results.");
+	}
+					
+	return "{ identifier: 'id', label:'file', items: [" + json.join(",\n") + "]}";
+};
\ No newline at end of file
diff --git a/util/checkstyle/readme.txt b/util/checkstyle/readme.txt
new file mode 100644
index 0000000..6e44b3a
--- /dev/null
+++ b/util/checkstyle/readme.txt
@@ -0,0 +1,27 @@
+The checkstyle tool is provided to help Dojo developers conform to the Dojo style guides.
+
+Read the help by running the command:
+	checkstyle.sh help
+or
+	checkstyle.bat.help
+	
+If you want to use the checkstyleReport.html tool to fix style errors and save the files,
+make a copy of the file 'checkstyle.php.rename.html', and call it 'checkstyle.php'.
+This script will then be used to save fixed files.
+
+All fixed files end in '.checkstyle.js', e.g. dojo/back.js.checkstyle.js.
+Cnce you are satisfied with the changes, commit them all by typing:
+	checkstyle.sh commit
+	
+	
+Troubleshooting
+---------------
+1. It says the file was saved but nothing was saved
+
+	Use firebug's NET tab to see the result return from the checkstyle.php call.   If it's a
+	permission denied error, probably your webserver is running as a different user and
+	can't write into your workspace.   I solved this problem by doing:
+	
+	$ find . -type d -exec chmod 777 {} \;
+
+	from the root of my project.   Probably there's a better way.
\ No newline at end of file
diff --git a/util/checkstyle/runCheckstyle.js b/util/checkstyle/runCheckstyle.js
new file mode 100644
index 0000000..dcdb365
--- /dev/null
+++ b/util/checkstyle/runCheckstyle.js
@@ -0,0 +1,127 @@
+//Checkstyle script for Dojo
+var buildTimerStart = (new Date()).getTime();
+
+load("../buildscripts/jslib/logger.js");
+load("../buildscripts/jslib/fileUtil.js");
+load("../buildscripts/jslib/buildUtil.js");
+load("checkstyleUtil.js");
+
+//*****************************************************************************
+
+if(arguments[0] == "help"){
+	print("Usage: \n\tTo generate a HTML report on dojo, dijit and dojox folders use:\n\t\t"
+		+ "checkstyle \n\t"
+		+ "To specify a single directory to check in, including all child folders, use:\n\t\t"
+		+ "checkstyle dir={folderName}\n\t"
+		+ "To specify directories to ignore, use:\n\t\t"
+		+ "checkstyle ignoreDirs={folderName1},{folderName2}\n\t"
+		+ "To specify a list of files to process, use the 'files' parameter, passing a list of space separated files, e.g.\n\t\t"
+		+ "checkstyle files=\"dojo/_base/Color.js dojo/back.js\"\n\t"
+		+ "To force the script to fail when a specified file has failed the check, use the 'failOnError' parameter, e.g.\n\t\t"
+		+ "checkstyle failOnError=true files=\"dojo/_base/Color.js dojo/back.js\"\n\t"
+		+ "To commit fixes made by the checkstyleReport.html tool, use\n\t\t"
+		+ "checkstyle commit");
+		
+} else if(arguments[0] == "commit"){
+	runCommit();
+} else{
+	
+	//Convert arguments to keyword arguments.
+	var kwArgs = buildUtil.makeBuildOptions(arguments);
+
+	checkstyle();
+
+	var buildTime = ((new Date().getTime() - buildTimerStart) / 1000);
+	print("Build time: " + buildTime + " seconds");
+
+}
+//*****************************************************************************
+
+//********* Start checkstyle *********
+function checkstyle(){
+	
+	var dirs, i, ignoreDirs;
+	var reportFile = "./checkstyleData.js";
+
+	
+	if(kwArgs.files){
+		var files = kwArgs.files.split(" ");
+		
+		for(i = 0; i < files.length; i++){
+			checkstyleUtil.applyRules("../../" + files[i], fileUtil.readFile("../../" + files[i]));
+		}
+		if(checkstyleUtil.errors){
+			var errors = checkstyleUtil.serializeErrors();
+			if(kwArgs.failOnError == "true"){
+				throw Error("Checkstyle failed. \n" + errors);
+			} else{
+				print(errors);
+			}
+		}
+		return;
+	}
+	
+	
+	if(kwArgs.dir){
+		dirs = [kwArgs.dir];
+	} else{
+		dirs = ["dojo", "dijit", "dojox"];
+	}
+	if(kwArgs.ignoreDirs){
+		ignoreDirs = kwArgs.ignoreDirs.split(",");
+	}else{
+		ignoreDirs = [];
+	}
+	
+	for(i = 0; i < dirs.length; i++){
+		var fileList = fileUtil.getFilteredFileList("../../" + dirs[i], /\.js$/, true);
+		for(var j = 0; j < fileList.length; j++){
+			if(fileList[j].indexOf("/test") < 0
+				&& fileList[j].indexOf("/nls") < 0 
+				&& fileList[j].indexOf("/demos") < 0){
+				
+				var ignore = false;
+				if(ignoreDirs.length > 0){
+					for(var k = 0; k < ignoreDirs.length; k++){
+						if(fileList[j].indexOf(ignoreDirs[k]) > -1){
+							ignore = true;
+							break;
+						}else{
+							
+						}
+					}
+				}
+				
+				if(!ignore){
+					checkstyleUtil.applyRules(fileList[j], fileUtil.readFile(fileList[j]));
+				}
+			}
+		}
+	}
+	var report = checkstyleUtil.generateReport();
+	fileUtil.saveUtf8File(reportFile, report);
+}
+
+function runCommit(){
+	var dirs = ["dojo", "dijit", "dojox"];
+	
+	var committedFiles = [];
+
+	for(var i = 0; i < dirs.length; i++){
+		var fileList = fileUtil.getFilteredFileList("../../" + dirs[i], /\.checkstyle.js$/, true);
+		
+		for(var j = 0; j < fileList.length; j++){
+			if(fileList[j].indexOf("/test") < 0
+				&& fileList[j].indexOf("/nls") < 0 
+				&& fileList[j].indexOf("/demos") < 0){
+				var fileName = fileList[j].substring(0, fileList[j].length - ".checkstyle.js".length);
+				fileUtil.saveUtf8File(fileName, fileUtil.readFile(fileList[j]));
+				fileUtil.deleteFile(fileList[j]);
+				committedFiles.push(fileName);
+			}
+		}
+	}
+	print("Committed checkstyle fixes for the following files:\n" + committedFiles.join("\n"));
+}
+
+//********* End checkstyle *********
\ No newline at end of file
diff --git a/util/docscripts/LICENSE b/util/docscripts/LICENSE
new file mode 100644
index 0000000..4c93ded
--- /dev/null
+++ b/util/docscripts/LICENSE
@@ -0,0 +1,195 @@
+Dojo is available under *either* the terms of the modified BSD license *or* the
+Academic Free License version 2.1. As a recipient of Dojo, you may choose which
+license to receive this code under (except as noted in per-module LICENSE
+files). Some modules may not be the copyright of the Dojo Foundation. These
+modules contain explicit declarations of copyright in both the LICENSE files in
+the directories in which they reside and in the code itself. No external
+contributions are allowed under licenses which are fundamentally incompatible
+with the AFL or BSD licenses that Dojo is distributed under.
+
+The text of the AFL and BSD licenses is reproduced below. 
+
+-------------------------------------------------------------------------------
+The "New" BSD License:
+**********************
+
+Copyright (c) 2005-2010, The Dojo Foundation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this
+    list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+  * Neither the name of the Dojo Foundation nor the names of its contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------------------
+The Academic Free License, v. 2.1:
+**********************************
+
+This Academic Free License (the "License") applies to any original work of
+authorship (the "Original Work") whose owner (the "Licensor") has placed the
+following notice immediately following the copyright notice for the Original
+Work:
+
+Licensed under the Academic Free License version 2.1
+
+1) Grant of Copyright License. Licensor hereby grants You a world-wide,
+royalty-free, non-exclusive, perpetual, sublicenseable license to do the
+following:
+
+a) to reproduce the Original Work in copies;
+
+b) to prepare derivative works ("Derivative Works") based upon the Original
+Work;
+
+c) to distribute copies of the Original Work and Derivative Works to the
+public;
+
+d) to perform the Original Work publicly; and
+
+e) to display the Original Work publicly.
+
+2) Grant of Patent License. Licensor hereby grants You a world-wide,
+royalty-free, non-exclusive, perpetual, sublicenseable license, under patent
+claims owned or controlled by the Licensor that are embodied in the Original
+Work as furnished by the Licensor, to make, use, sell and offer for sale the
+Original Work and Derivative Works.
+
+3) Grant of Source Code License. The term "Source Code" means the preferred
+form of the Original Work for making modifications to it and all available
+documentation describing how to modify the Original Work. Licensor hereby
+agrees to provide a machine-readable copy of the Source Code of the Original
+Work along with each copy of the Original Work that Licensor distributes.
+Licensor reserves the right to satisfy this obligation by placing a
+machine-readable copy of the Source Code in an information repository
+reasonably calculated to permit inexpensive and convenient access by You for as
+long as Licensor continues to distribute the Original Work, and by publishing
+the address of that information repository in a notice immediately following
+the copyright notice that applies to the Original Work.
+
+4) Exclusions From License Grant. Neither the names of Licensor, nor the names
+of any contributors to the Original Work, nor any of their trademarks or
+service marks, may be used to endorse or promote products derived from this
+Original Work without express prior written permission of the Licensor. Nothing
+in this License shall be deemed to grant any rights to trademarks, copyrights,
+patents, trade secrets or any other intellectual property of Licensor except as
+expressly stated herein. No patent license is granted to make, use, sell or
+offer to sell embodiments of any patent claims other than the licensed claims
+defined in Section 2. No right is granted to the trademarks of Licensor even if
+such marks are included in the Original Work. Nothing in this License shall be
+interpreted to prohibit Licensor from licensing under different terms from this
+License any Original Work that Licensor otherwise would have a right to
+license.
+
+5) This section intentionally omitted.
+
+6) Attribution Rights. You must retain, in the Source Code of any Derivative
+Works that You create, all copyright, patent or trademark notices from the
+Source Code of the Original Work, as well as any notices of licensing and any
+descriptive text identified therein as an "Attribution Notice." You must cause
+the Source Code for any Derivative Works that You create to carry a prominent
+Attribution Notice reasonably calculated to inform recipients that You have
+modified the Original Work.
+
+7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
+the copyright in and to the Original Work and the patent rights granted herein
+by Licensor are owned by the Licensor or are sublicensed to You under the terms
+of this License with the permission of the contributor(s) of those copyrights
+and patent rights. Except as expressly stated in the immediately proceeding
+sentence, the Original Work is provided under this License on an "AS IS" BASIS
+and WITHOUT WARRANTY, either express or implied, including, without limitation,
+the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU.
+This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No
+license to Original Work is granted hereunder except under this disclaimer.
+
+8) Limitation of Liability. Under no circumstances and under no legal theory,
+whether in tort (including negligence), contract, or otherwise, shall the
+Licensor be liable to any person for any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License
+or the use of the Original Work including, without limitation, damages for loss
+of goodwill, work stoppage, computer failure or malfunction, or any and all
+other commercial damages or losses. This limitation of liability shall not
+apply to liability for death or personal injury resulting from Licensor's
+negligence to the extent applicable law prohibits such limitation. Some
+jurisdictions do not allow the exclusion or limitation of incidental or
+consequential damages, so this exclusion and limitation may not apply to You.
+
+9) Acceptance and Termination. If You distribute copies of the Original Work or
+a Derivative Work, You must make a reasonable effort under the circumstances to
+obtain the express assent of recipients to the terms of this License. Nothing
+else but this License (or another written agreement between Licensor and You)
+grants You permission to create Derivative Works based upon the Original Work
+or to exercise any of the rights granted in Section 1 herein, and any attempt
+to do so except under the terms of this License (or another written agreement
+between Licensor and You) is expressly prohibited by U.S. copyright law, the
+equivalent laws of other countries, and by international treaty. Therefore, by
+exercising any of the rights granted to You in Section 1 herein, You indicate
+Your acceptance of this License and all of its terms and conditions.
+
+10) Termination for Patent Action. This License shall terminate automatically
+and You may no longer exercise any of the rights granted to You by this License
+as of the date You commence an action, including a cross-claim or counterclaim,
+against Licensor or any licensee alleging that the Original Work infringes a
+patent. This termination provision shall not apply for an action alleging
+patent infringement by combinations of the Original Work with other software or
+hardware.
+
+11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this
+License may be brought only in the courts of a jurisdiction wherein the
+Licensor resides or in which Licensor conducts its primary business, and under
+the laws of that jurisdiction excluding its conflict-of-law provisions. The
+application of the United Nations Convention on Contracts for the International
+Sale of Goods is expressly excluded. Any use of the Original Work outside the
+scope of this License or after its termination shall be subject to the
+requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et
+seq., the equivalent laws of other countries, and international treaty. This
+section shall survive the termination of this License.
+
+12) Attorneys Fees. In any action to enforce the terms of this License or
+seeking damages relating thereto, the prevailing party shall be entitled to
+recover its costs and expenses, including, without limitation, reasonable
+attorneys' fees and costs incurred in connection with such action, including
+any appeal of such action. This section shall survive the termination of this
+License.
+
+13) Miscellaneous. This License represents the complete agreement concerning
+the subject matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent necessary to
+make it enforceable.
+
+14) Definition of "You" in This License. "You" throughout this License, whether
+in upper or lower case, means an individual or a legal entity exercising rights
+under, and complying with all of the terms of, this License. For legal
+entities, "You" includes any entity that controls, is controlled by, or is
+under common control with you. For purposes of this definition, "control" means
+(i) the power, direct or indirect, to cause the direction or management of such
+entity, whether by contract or otherwise, or (ii) ownership of fifty percent
+(50%) or more of the outstanding shares, or (iii) beneficial ownership of such
+entity.
+
+15) Right to Use. You may use the Original Work in all ways not otherwise
+restricted or conditioned by this License or by law, and Licensor promises not
+to interfere with or be responsible for such uses by You.
+
+This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved.
+Permission is hereby granted to copy and distribute this license without
+modification. This license may not be modified without the express written
+permission of its copyright owner.
diff --git a/util/docscripts/README b/util/docscripts/README
new file mode 100644
index 0000000..4c2b2e6
--- /dev/null
+++ b/util/docscripts/README
@@ -0,0 +1,12 @@
+A Collection of Documentation Utilities
+---------------------------------------
+
+_browse.php - A real time doc parser viewer. Requires PHP5, and an uncompressed -src release.
+api.xml - a generated API in XML format 
+cheat.php - A Single page which renders the Base Dojo API's. To use, make a file `cheat.html`
+	writable by the webserver. View the cheat.php page in a modern browser, and press ctrl+esc to save.
+generate.php - runner for api.xml generation
+makeCix.php - Generator for ActiveState Komodo Editor .cix API completion.
+
+modules/ - The modules for the namespaces to check for documentation.
+lib/ - the Dojo Documentation Parser source
\ No newline at end of file
diff --git a/util/docscripts/_browse.php b/util/docscripts/_browse.php
new file mode 100755
index 0000000..b688320
--- /dev/null
+++ b/util/docscripts/_browse.php
@@ -0,0 +1,236 @@
+<?php /*
+
+  _browse.php - rudimentary api browser designed to expose flaws in
+  either the dojo doc parser or the effort to document the Dojo Toolkit
+  API. it is embarasingly inefficient and sloppy, but works.
+  
+  this file requires PHP5, and a full source tree of the dojo toolkit.
+
+  it parses a module, and dumps relevant API information made in real
+  time. PLEASE use this to preview how the parse tool will interpret
+  your code.
+
+  it covers all files in dojtool's modules/ directory dynamically, so
+  can be used to preview documentation in custom namespace code, as well.
+
+*/
+
+// hide warnings
+error_reporting(1);
+$ajaxy = !empty($_REQUEST['ajaxy']);
+
+?>
+
+<?php if(!$ajaxy){ ?>
+	<html>
+		<head>
+		
+		  <title>API Preview tool | The Dojo Toolkit <title>
+		
+		  <script type="text/javascript" src="../../dojo/dojo.js" djConfig="parseOnLoad:true"></script>
+		
+		  <script type="text/javascript">
+			dojo.require("dijit.layout.BorderContainer");
+			dojo.require("dojox.layout.ExpandoPane");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dijit.layout.TabContainer");
+			dojo.require("dijit.layout.AccordionContainer");
+			dojo.require("dojo.fx.easing");
+			dojo.require("dijit.TitlePane");
+			function tgShow(id){
+			  var identity=document.getElementById(id);
+					if(identity.className=="sho"){ identity.className="nosho";
+					}else{ identity.className="sho"; }
+			}
+			dojo.addOnLoad(function(e){
+				dojo.connect(window,"onclick",function(e){
+					if(e.target && e.target.href){
+						e.preventDefault();
+						dijit.byId('apiPane').attr("href", e.target.href + "&ajaxy=true");
+					}
+				});
+			});
+		  </script>
+		  <style type="text/css">
+			@import "../../dijit/themes/soria/soria.css";
+			@import "../../dojox/layout/resources/ExpandoPane.css";
+			@import "../../dojo/resources/dojo.css"; 
+			body, html { width:100%; height:100%; margin:0; padding:0; }
+			.sho { display:block; }
+			.nosho { display:none; } 
+			.topbar li { display:inline; padding:5px; } 
+			.pad {
+				padding:20px;
+				padding-top:8px;
+			}
+			</style>
+		  </style>
+		</head>
+	<body class="soria">
+<?php
+
+} // $ajaxy
+
+include_once('includes/dojo.inc');
+
+$tree = '';
+// no dojo.require() call made?
+$u = 0; 
+$files = dojo_get_files(); 
+foreach ($files as $set){ 
+  list($namespace, $file) = $set;
+  $data[$namespace][] = $file;
+}
+$namespaces = array_keys($data); 
+
+$trees = array();
+$regexp = "";
+foreach ($data as $ns => $file){
+  $tree = "<ul>";
+  foreach ($data[$ns] as $file){
+    if(!preg_match('/tests\//i',$file)){
+      if($ifile == $file){ $tree .= "<li>".$file."</li>"; 
+      }else{ $tree .= "<li><a href=\"?ns=".$ns."&file=".$file."\">".$ns."/".$file."</a></li>"; }
+    }else{ $testfiles[] = $ns."/".$file; } 
+  }
+  $tree .= "</ul>";
+  $trees[$ns] = $tree;
+}
+
+
+unset($files); 
+
+if(!empty($_REQUEST['ns'])){
+  $ns = $_REQUEST['ns'];
+  $ifile = $_REQUEST['file'];
+  
+
+  if($ifile){
+    $apiData = dojo_get_contents($ns,$ifile);
+
+    $print .= "<h2>".$ns."/".$ifile."</h2><ul>";
+    foreach($apiData as $key => $val){
+      switch($key){
+        case "#resource" : break;
+        case "#requires" : 
+          $print .= "<li><h3>Requires:</h3><ul>";
+          foreach($val as $resource){
+            $print .= "<li>{$resource[1]} in {$resource[0]}";
+            if ($resource[2]) {
+              $print .= " in project {$resource[2]}";
+            }
+            $print .= "</li>"; 
+          }
+          $print .= "</ul></li>"; 
+          break;
+        case "#provides" :
+          $print .= "<li><h3>Provides:</h3><ul>";
+          $print .= "<li>$val</li>"; 
+          $print .= "</ul></li>"; 
+          break;
+        default:
+          $print .= "<li><h4>".$key."</h4><ul> ";
+          foreach($val as $key2 => $val2){
+  
+              switch($key2){
+                // most things using dojo.declare() trigger this, eg: dijits
+                case "classlike": $knownClasses[] = $key; break;
+
+                // these are partially useless for our "overview" api, but set showall=1 in the
+                // url if you want to see these, too. sortof.
+                case "type" : $print .= "<li><em>".$key2."</em><div><pre>".htmlentities($val2)."</pre></div></li>"; break;
+                case "private_parent" :
+                case "prototype" :
+                case "instance" :
+                case "private" :
+                  if($_REQUEST['showall']){ $print .= "<li>".$key2." - ".$val2."</li>"; }
+                  break;
+                
+                // another array we want inspect more closely 
+                case "parameters" : 
+                  $print .= "<li><em>parameters:</em> <ul>"; 
+                  foreach($val2 as $param => $paramData){
+                    $print .= "<li>".$param.": <em>(typeof ".$paramData['type'].")</em><div>";
+                    if(!empty($paramData['summary'])){
+                      $print .= "<pre>".htmlentities($paramData['summary'])."</pre>";
+                    }
+                    $print .= "</div></li>";
+                  } //print_r($val2);             
+                  $print .= "</ul></li>";
+                  break;
+                
+                // the stripped source, and some minimal toggling to show/hide  
+                case "source" : 
+                  $print .= "<li class=\"source\"><em>source: [<a onclick=\"tgShow('unique".++$u."');\">view</a>]</em> 
+                    <div class=\"nosho\" id=\"unique".$u."\">\n
+                    ".ltrim(str_replace("\n","<br>",str_replace("\t"," ",$val2)))."
+                    </div>
+                    ";  
+                  break;
+
+                case "tags":
+                  $print .= "<li><em>$key2</em>: " . implode(' ', $val2) . '</li>';
+                  break;
+
+                case "chains" :
+                case "mixins" :
+                  if (!empty($val2)) {
+                    $print .= "<li><em>" . $key2 . ":</em> <ul>";
+                    foreach ($val2 as $subtype => $chains) {
+                      foreach ($chains as $chain) {
+                        $print .= "<li>$chain: <em>($subtype)</em></li>";
+                      }
+                    }
+                    $print .= "</ul></li>";
+                  }
+                  break;
+
+                // these are the ones we care about, and are fulltext/sometimes html
+                case "examples" :
+                  foreach ($val2 as $example){
+                    $print .= "<li><em>example</em><div><pre>".htmlentities($example)."</pre></div></li>";
+                  }
+                  break;
+                case "returns" :
+                case "return_summary" :
+                case "exceptions" :
+                case "description" :
+                case "summary" : $print .= "<li><em>".$key2."</em><div><pre>".htmlentities($val2)."</pre></div></li>"; break;
+
+                // this is a key we don't know about above, so show it just in case
+                default: $print .= "<li>?? ".$key2." = ".$val2." (debug: ".gettype($val2).") ??</li>"; break;
+              }
+          } 
+          $print .= "</ul></li>"; break;
+      }
+    }
+    $print .= "</ul>";
+  }
+}
+
+if(!$ajaxy){ ?>
+<div dojoType="dijit.layout.BorderContainer" style="width:100%; height:100%;">
+	<div dojoType="dojox.layout.ExpandoPane" easeOut="dojo.fx.easing.backIn" easeIn="dojo.fx.easing.backOut" title="Namespaces" region="left" style="width:250px" splitter="true">
+		<div dojoType="dijit.layout.AccordionContainer" style="width:250px" tabPosition="top">
+			<?php
+				foreach($trees as $ns => $list){
+					print "\n\n<div dojoType=\"dijit.layout.ContentPane\" title=\"".$ns."\">";
+					print $list;
+					print "</div>";
+				}
+			?>
+		</div>
+	</div>
+    <div dojoType="dijit.layout.TabContainer" closeable="false" region="center">
+		<div dojoType="dijit.layout.ContentPane" id="apiPane" title="Crude API Browser">
+			<div class="pad"><?php echo $print; ?></div>
+		</div>
+    </div>
+</div>
+</body>
+</html>
+<?php }else{
+	// we just want the content we parsed
+	echo '<div class="pad">'.$print.'</div>';
+}
+?>
diff --git a/util/docscripts/_browse2.php b/util/docscripts/_browse2.php
new file mode 100644
index 0000000..7fc2404
--- /dev/null
+++ b/util/docscripts/_browse2.php
@@ -0,0 +1,258 @@
+<?php /*
+
+  _browse.php - rudimentary api browser designed to expose flaws in
+  either the dojo doc parser or the effort to document the Dojo Toolkit
+  API. it is embarasingly inefficient and sloppy, but works.
+  
+  this file requires PHP5, and a full source tree of the dojo toolkit.
+
+  it parses a module, and dumps relevant API information made in real
+  time. PLEASE use this to preview how the parse tool will interpret
+  your code.
+
+  it covers all files in dojtool's modules/ directory dynamically, so
+  can be used to preview documentation in custom namespace code, as well.
+
+*/
+
+// hide warnings
+error_reporting(1);
+$ajaxy = !empty($_REQUEST['ajaxy']);
+$showall = isset($_REQUEST['showall']);
+
+?>
+
+<?php if(!$ajaxy){ ?>
+	<html>
+		<head>
+		
+		  <title>API Preview tool | The Dojo Toolkit <title>
+		
+		  <script type="text/javascript" src="../../dojo/dojo.js" djConfig="parseOnLoad:true"></script>
+		
+		  <script type="text/javascript">
+			dojo.require("dijit.layout.BorderContainer");
+			dojo.require("dojox.layout.ExpandoPane");
+			dojo.require("dijit.layout.ContentPane");
+			dojo.require("dijit.layout.TabContainer");
+			dojo.require("dojo.fx.easing");
+			dojo.require("dijit.TitlePane");
+			function tgShow(id){
+			  var identity=document.getElementById(id);
+					if(identity.className=="sho"){ identity.className="nosho";
+					}else{ identity.className="sho"; }
+			}
+			dojo.addOnLoad(function(e){
+				dojo.connect(window,"onclick",function(e){
+					if(e.target && e.target.href){
+						e.preventDefault();
+						dijit.byId('apiPane').setHref(e.target.href + "&ajaxy=true");
+					}
+				});
+			});
+		  </script>
+		  <style type="text/css">
+			@import "../../dijit/themes/soria/soria.css";
+			@import "../../dojox/layout/resources/ExpandoPane.css";
+			@import "../../dojo/resources/dojo.css"; 
+			body, html { width:100%; height:100%; margin:0; padding:0; }
+			.sho { display:block; }
+			.nosho { display:none; } 
+			.topbar li { display:inline; padding:5px; } 
+			.pad {
+				padding:20px;
+				padding-top:8px;
+			}
+			</style>
+		  </style>
+		</head>
+	<body class="soria">
+<?php
+
+} // $ajaxy
+
+include_once('lib/parser2/dojo2.inc');
+
+$tree = '';
+// no dojo.require() call made?
+$u = 0; 
+$files = dojo_get_files(); 
+foreach ($files as $set){ 
+  list($namespace, $file) = $set;
+  $data[$namespace][] = $file;
+}
+$namespaces = array_keys($data); 
+
+$trees = array();
+$regexp = "";
+foreach ($data as $ns => $file){
+  $tree = "<ul>";
+  foreach ($data[$ns] as $file){
+    if(!preg_match('/tests\//i',$file)){
+      if($ifile == $file){ $tree .= "<li>".$file."</li>"; 
+      }else{ $tree .= "<li><a href=\"?ns=".$ns."&file=".$file."&showall=".$showall."\">".$ns."/".$file."</a></li>"; }
+    }else{ $testfiles[] = $ns."/".$file; } 
+  }
+  $tree .= "</ul>";
+  $trees[$ns] = $tree;
+}
+
+
+unset($files); 
+
+if(!empty($_REQUEST['ns'])){
+  $ns = $_REQUEST['ns'];
+  $ifile = $_REQUEST['file'];
+  
+
+  if($ifile){
+    $apiData = dojo_get_contents($ns,$ifile);
+
+    $print .= "<h2>".$ns."/".$ifile."</h2><ul>";
+    foreach($apiData as $key => $val){
+      switch($key){
+        case "#resource" : break;
+        case "#requires" : 
+          $print .= "<li><h3>Requires:</h3><ul>";
+          foreach($val as $resource){
+            $print .= "<li>{$resource[1]} in {$resource[0]}";
+            if ($resource[2]) {
+              $print .= " in project {$resource[2]}";
+            }
+            $print .= "</li>"; 
+          }
+          $print .= "</ul></li>"; 
+          break;
+        case "#provides" :
+          $print .= "<li><h3>Provides:</h3><ul>";
+          $print .= "<li>$val</li>"; 
+          $print .= "</ul></li>"; 
+          break;
+        default:
+          $print .= "<li><h4>".$key."</h4><ul> ";
+          foreach($val as $key2 => $val2){
+  
+              switch($key2){
+                // most things using dojo.declare() trigger this, eg: dijits
+                case "classlike":
+                  $knownClasses[] = $key;
+                  if ($_REQUEST['showall']) {
+                    $print .= "<li>$key2</li>";
+                  }
+                  break;
+
+                // these are partially useless for our "overview" api, but set showall=1 in the
+                // url if you want to see these, too. sortof.
+                case "type" : $print .= "<li><em>".$key2."</em><div><pre>".htmlentities($val2)."</pre></div></li>"; break;
+                case "private_parent" :
+                case "prototype" :
+                case "instance" :
+                case "private" :
+                case "deprecated" :
+                case "protected" :
+                case "attached" :
+                  if($_REQUEST['showall']){ $print .= "<li>".$key2." - ".$val2."</li>"; }
+                  break;
+                case "alias" :
+                case "constructor" :
+                  $print .= "<li>".$key2." - ".$val2."</li>";
+                  break;
+                
+                // another array we want inspect more closely 
+                case "parameters" : 
+                  $print .= "<li><em>parameters:</em> <ul>"; 
+                  foreach($val2 as $param => $paramData){
+                    $print .= "<li>".$param;
+                    if (!empty($paramData['type'])) {
+                      $print .= ": <em>(typeof ".$paramData['type'].")</em>";
+                    }
+                    $print .= "<div>";
+                    if(!empty($paramData['summary'])){
+                      $print .= "<pre>".htmlentities($paramData['summary'])."</pre>";
+                    }
+                    $print .= "</div></li>";
+                  } //print_r($val2);             
+                  $print .= "</ul></li>";
+                  break;
+                
+                // the stripped source, and some minimal toggling to show/hide  
+                case "source" : 
+                  $print .= "<li class=\"source\"><em>source: [<a onclick=\"tgShow('unique".++$u."');\">view</a>]</em> 
+                    <div class=\"nosho\" id=\"unique".$u."\">\n
+                    ".ltrim(str_replace("\n","<br>",str_replace("\t"," ",$val2)))."
+                    </div>
+                    ";  
+                  break;
+
+                case "tags":
+                  $print .= "<li><em>$key2</em>: " . implode(' ', $val2) . '</li>';
+                  break;
+
+                case "optional":
+                  if ($val2) {
+                    $print .= "<li><em>$key2</em></li>";
+                  }
+                  break;
+
+                case "chains" :
+                case "mixins" :
+                  if (!empty($val2)) {
+                    $print .= "<li><em>" . $key2 . ":</em> <ul>";
+                    foreach ($val2 as $subtype => $chains) {
+                      foreach ($chains as $chain) {
+                        $print .= "<li>$chain: <em>($subtype)</em></li>";
+                      }
+                    }
+                    $print .= "</ul></li>";
+                  }
+                  break;
+
+                // these are the ones we care about, and are fulltext/sometimes html
+                case "examples" :
+                  foreach ($val2 as $example){
+                    $print .= "<li><em>example</em><div><pre>".htmlentities($example)."</pre></div></li>";
+                  }
+                  break;
+                case "returns" :
+                case "return_summary" :
+                case "exceptions" :
+                case "description" :
+                case "summary" : $print .= "<li><em>".$key2."</em><div><pre>".htmlentities($val2)."</pre></div></li>"; break;
+
+                // this is a key we don't know about above, so show it just in case
+                default: $print .= "<li>?? ".$key2." = ".$val2." (debug: ".gettype($val2).") ??</li>"; break;
+              }
+          } 
+          $print .= "</ul></li>"; break;
+      }
+    }
+    $print .= "</ul>";
+  }
+}
+
+if(!$ajaxy){ ?>
+<div dojoType="dijit.layout.BorderContainer" style="width:100%; height:100%;">
+	<div dojoType="dojox.layout.ExpandoPane" easeOut="dojo.fx.easing.backIn" easeIn="dojo.fx.easing.backOut" title="Namespaces" region="left" style="width:250px" splitter="true">
+		<div dojoType="dijit.layout.TabContainer" tabPosition="bottom">
+			<?php
+				foreach($trees as $ns => $list){
+					print "<div attachParent=\"true\" dojoType=\"dijit.layout.ContentPane\" title=\"".$ns."\">";
+					print $list;
+					print "</div>";
+				}
+			?>
+		</div>
+	</div>
+    <div dojoType="dijit.layout.TabContainer" closeable="false" region="center">
+		<div dojoType="dijit.layout.ContentPane" id="apiPane" title="Crude API Browser">
+			<div class="pad"><?php echo $print; ?></div>
+		</div>
+    </div>
+</div>
+</body>
+</html>
+<?php }else{
+	// we just want the content we parsed
+	echo '<div class="pad">'.$print.'</div>';
+}
+?>
diff --git a/util/docscripts/cheat.php b/util/docscripts/cheat.php
new file mode 100644
index 0000000..e52e285
--- /dev/null
+++ b/util/docscripts/cheat.php
@@ -0,0 +1,148 @@
+<?php
+	
+	// for this to work, the file api.html needs to be writable locally. pass a "?build" to
+	// this url to trigger the generation. otherwise, work live from here. No JS ends up 
+	// in the output. api.css gets inlined in the output, making api.html standalone. 
+	
+	$head = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+		"http://www.w3.org/TR/html4/strict.dtd">
+	<html>
+		<head>
+			<title>API Overview - Dojo Toolkit</title>
+		
+		';
+
+	$foot = '</body></html>';
+
+	if(!empty($_POST['body'])){
+		
+		$head .= "<style type='text/css'>" . file_get_contents("cheat/cheat.css") ."</style></head><body>";
+		$page = $head . $_POST['body'] . "<div class='note'><p>Dojo " . $_POST['version'] . 
+			" Docs generated " . date("Y-m-d") . "</p></div>" . $foot;
+			
+		if(is_writable("./cheat.html")){
+			file_put_contents("./cheat.html", stripslashes($page));
+		}else{
+			header("HTTP", true, 500);
+			print "Unwritable File: cheat.html";
+		}
+		die;
+	}
+	
+	print $head;
+	
+?>
+
+		<link rel="stylesheet" href="cheat/cheat.css">
+
+		<script type="text/javascript" src="../../dojo/dojo.js"></script>
+
+		<script type="text/javascript">		
+			dojo.require("util.docscripts.cheat.lib");
+			dojo.addOnLoad(function(){
+				
+ 				// a list of things to ignore in the dojo namespace (either useless, or handled specially)
+				var ap = util.docscripts.cheat.lib;
+
+				if(ap.hasTag("excludePlugd")){
+					ap.ignore.push(
+						// skip plugd api's for Dojo Base
+						"pub", "sub", "unique", "first", "last", "end", "show", "hide", "toggle", 
+						"conflict", "animate", "wrap", "appendTo", "append", "hoverClass", "hover",
+						"qw","generateId"
+					);
+				}
+
+				// core Dojo stuff:
+				if(!ap.hasTag("excludeDojo")){
+					ap.addIn("dojo");
+					ap.addIn("dojo.NodeList.prototype");
+					ap.addIn("dojo.fx", ap.getUl("Effects"));
+					ap.addIn("dojo.Animation.prototype", ap.getUl("Effects"));
+				}
+				
+				if(!ap.hasTag("excludeKeys")){
+					var ul = ap.getUl("Key-Constants");
+					dojo.place("<li class='dblspan'>(dojo.keys.*)</li>", ul, "first");
+					ap.addIn("dojo.keys", ul);
+				}
+
+				ap.addIn({
+					"djConfig": dojo.mixin({},{ 
+							parseOnLoad:false,
+							requires:[]
+						},dojo.config),
+					"toString":function(){ return "djConfig" }
+				}, ap.getUl("djConfig"));
+
+				// fun quick way to pseudo-doc a tag
+//				ap.addIn({
+//					"args":{
+//						"load":function(data, ioArgs){},
+//						"error":function(error){},
+//						"handle":function(dataOrError){},
+//						url:"", timeout: ""
+//					},
+//					"toString":function(){
+//						// this is to trick the thing into introversion
+//						return "args"
+//					}
+//				}, ap.getUl("Ajax"))
+
+				if(ap.hasTag("includeColor")){
+					ap.addIn("dojo.Color.prototype", ap.getUl("Colors"));
+				}
+
+				var finish = function(){
+					ap.sortFields("container");
+					ap.buildNav();
+					ap.hasTag("build") && ap.save();
+					
+				}
+
+				if(ap.hasTag("includeDijit")){
+					dojo.require("dijit.dijit");
+					dojo.addOnLoad(function(){
+
+						ap.addIn("dijit._Widget.prototype", null, "dijit");
+						ap.addIn("dijit", null, "dijit");
+						ap.addIn("dijit._Templated.prototype", null, "dijit");
+						ap.addIn("dijit.WidgetSet.prototype", ap.getUl("Widget-Access"));
+						ap.addIn("dijit.popup", ap.getUl("Widget-Control"));
+						finish();
+					});
+					
+				}else{
+					finish();
+				}
+				
+				dojo.connect(dojo.global, "onkeypress", function(e){
+					if(e.keyCode == dojo.keys.ESCAPE && e.ctrlKey){
+						ap.save();
+					}
+				});
+				
+			});
+		</script>
+	
+	<body>
+		<fieldset id="top"><div>
+			<legend>Dojo API CheatSheet</legend>
+				<ul id="nav">
+					<li><a href="#top">Top</a></li>
+				</ul>
+				<div id="key">
+					<fieldset>
+						<legend>var</legend>
+						<ul>
+							<li>d = dojo,</li>
+							<li>$ = d.query,</li>
+							<li>dk = d.keys</li>
+						</ul>
+					</fieldset>
+				</div>				
+			</div>
+		</fieldset>
+		<div id="container"></div>
+	</body>
+</html>
diff --git a/util/docscripts/cheat/cheat.css b/util/docscripts/cheat/cheat.css
new file mode 100644
index 0000000..e2e5b87
--- /dev/null
+++ b/util/docscripts/cheat/cheat.css
@@ -0,0 +1,123 @@
+ at media print {
+	body,html {
+		margin:0; padding:0;
+		font-size:8pt;
+	}
+	#nav { display:none; }
+	#top { display:none; border:none; font-size:12pt; margin:0; padding:0; }
+	#container fieldset {
+		width:175px !important;
+		font-size:5pt !important;
+	}
+	#container legend {
+		font-weight:bold;
+		font-size:6pt !important;
+	}
+	#container span {
+		font-size:6pt !important;
+	}
+	#Key-Constants li {
+		font-size:5pt !important;
+		float:left !important;
+		width:65px !important;
+	}
+	#Key-Constants li.dblspan {
+		width:150px !important;
+	}
+}
+
+body {
+	font-size:11pt;
+}
+
+#nav { margin:0; padding:0; }
+#nav li { float:left; margin-right:10px; }
+#container {
+	margin:0 auto;
+}
+#nav li,
+#container li {
+	list-style-type:none;
+}
+
+#Key-Constants li {
+	float:left;
+	text-align:center;
+	font-size:8pt;
+	width:105px;
+} 
+#Key-Constants li.dblspan {
+	width:210px;
+	margin-top:-4px;
+}
+#container #nodelist li,
+#container #function li {
+	margin:0; padding:0;
+	padding-right:10px;
+	float:left;
+} 
+
+fieldset legend {
+/*	margin-left:14px; */
+	padding-left:7px; 
+	padding-right:7px;
+}
+#container fieldset {
+	margin-top:15px;
+	margin-right:8px;
+	margin-bottom:-0.5em;
+	padding-top:0.25em;
+	width:220px; 
+	border:0;
+	border-top:1px dotted #a7a7a7;
+}
+#container fieldset legend {
+	margin:0 auto;
+	text-align:center;
+	font-weight:bold;
+	color:#444;
+}
+#container ul {
+	margin:0; padding:0;
+}
+.f { float:right; 
+	margin-top:8px; 
+	margin-right:27px; 
+}
+
+#top { 
+	border:0; 
+	border-top:1px dotted #666; 
+	margin-bottom:-0.3em;
+} 
+#top legend {
+	color:#666;
+	font-size:27pt;
+	font-weight:bold;
+}
+#key { display:none; }
+
+li {
+	padding:3px 0;
+	font-size:9pt;
+	color:#333;
+}
+.sig { margin-left:1px; color:#999; /* visibility:hidden; */}
+.showApi .sig { color:#333; }
+
+.dijitInline {
+	/*  To inline block elements.
+		Similar to InlineBox below, but this has fewer side-effects in Moz.
+		Also, apparently works on a DIV as well as a FIELDSET.
+	*/
+	display:-moz-inline-box;		/* FF2 */
+	display:inline-block;			/* webkit and FF3 */
+	#zoom: 1; /* set hasLayout:true to mimic inline-block */
+	#display:inline; /* don't use .dj_ie since that increases the priority */
+	border:0;
+	padding:0;
+	vertical-align:top;
+	#vertical-align: auto;	/* makes TextBox,Button line up w/native counterparts on IE6 */
+}
+
+.note { color:#a7a7a7; text-align:center; font-size:9pt; }
\ No newline at end of file
diff --git a/util/docscripts/cheat/lib.js b/util/docscripts/cheat/lib.js
new file mode 100644
index 0000000..810ca1c
--- /dev/null
+++ b/util/docscripts/cheat/lib.js
@@ -0,0 +1,313 @@
+dojo.provide("util.docscripts.cheat.lib");
+(function(){
+	
+	var api = util.docscripts.cheat.lib;
+	dojo.mixin(api, {
+
+		varmap:{
+			// a map of things to prefix common things
+			"dojo":"d.",
+			"dojo.NodeList.prototype":"$('.nodes').",
+			"dojo.keys":" ",
+			"dojo.fx":"d.fx.",
+			"dojo.fx.easing":"",
+			"dijit._Widget.prototype":"_Widget.",
+			"dijit._Templated.prototype":"_Templated.",
+			"dijit.WidgetSet.prototype":"dijit.registry.",
+			"dojo.Animation.prototype":"anim.",
+			"dojo.Color.prototype":"color.",
+			"dojo.xhrArgs":"args."
+		},
+
+		ignore:[
+			// stuff to ignore:
+			"keys", "NodeList", "fx", "prototype", 
+			
+			// lifecycle stuff to hide
+			"loaded", "unloaded", "loadInit", "windowUnloaded",
+			"preamble", "WidgetSet", "registry", "inherited", "postscript",
+
+			// dijit.WidgetSet
+			"add", "remove", 
+
+			// 
+			"dijit", "form", "layout", "lang", "dir", "class",
+			"declaredClass", "wai", "typematic", "popup",
+
+			// dojo.Color
+			"r","g","b","a"
+		],
+
+		useful_privates:[
+			"_Widget", "_Templated", "_toArray"
+		],
+
+		tags: {
+			dojo:{
+				"Effects":[
+					"anim", "animateProperty", "fadeIn", "fadeOut", "animate", "fx.chain", "fx.combine", 
+					"_Animation", "_Line", "Animation" /* _Animation deprecated in 1.4 */
+				],
+
+				"Ajax":[
+					"xhr", "xhrGet", "xhrPost", "xhrPut", "xhrDelete", "rawXhrPut", "rawXhrPost", "contentHandlers"
+				],
+
+				"Language-Helpers":[
+					"isArray", "isFunction", "isString", "isObject", "isArrayLike", "unique", 
+					"eval", "isAlien", "trim", "Deferred", "_toArray", "replace", "when"
+				],
+
+				"Arrays":[
+					"at", "forEach", "indexOf", "map", "concat", "some", "every", "lastIndexOf",
+					"qw", "filter", "splice", "slice", "end"
+				],
+
+				"Event-System":[
+					"connect", "publish", "subscribe", "pub", "sub", "unsubscribe", "disconnect", 
+					"fixEvent", "stopEvent", "connectPublisher", "isCopyKey", "mouseButtons"
+				],
+
+				"NodeList-Events":[
+					"onmousedown", "onmouseenter", "onmouseleave", "onmousemove", "onmouseover",
+					 "onmouseout", "onblur", 
+					"onfocus", "onclick", "onchange", "onload", "onmousedown", "onmouseup", "onsubmit",
+					"onerror", "onkeydown", "onkeypress", "onkeyup", "hover"
+				],
+
+				"NodeList-Misc":[
+					"first", "last", "end", "_stash"
+				],
+
+				"Objects-OO":[
+					"mixin", "declare", "extend", "delegate", "hitch", "partial", "setObject",
+					"getObject", "exists", "instantiate", "safeMixin" /* ? */
+				],
+
+				"Package-System":[
+					"require", "provide", "load", "requireLocalization", "requireIf", "dfdLoad",
+					"moduleUrl", "requireAfterIf", "registerModulePath", "platformRequire"
+				],
+
+				"Document-Lifecycle":[
+					"addOnLoad", "addOnUnload", "addOnWindowUnload","loaded", 
+					"unloaded", "loadInit",  "windowUnloaded", "ready"
+				],
+
+
+				"DOM-Manipulation":[
+					"create", "wrap", "place", "byId", "query", "empty", "destroy", "generateId", "clone",
+					"body", "append", "appendTo", "addContent", "adopt", "orphan"
+				],
+
+				"DOM-Attributes":[
+					"hasAttr", "removeAttr", "position", "getNodeProp",
+					"setSelectable", "isDescendant", "val", "attr", "coords", "marginBox", "contentBox"
+				],
+
+				"Colors":[
+					"Color", "colorFromArray", "colorFromString", "blendColors", "colorFromRgb", "colorFromHex"
+				],
+
+				"Styles-CSS":[
+					"style", "addClass", "removeClass", "toggleClass", "hasClass", "getComputedStyle", "boxModel", 
+					"show", "hide", "toggle", "hoverClass"
+				],
+
+				"JSON":[
+					"fromJson", "toJson", "toJsonIndentStr", "formToObject", "queryToObject", "formToQuery", 
+					"formToJson", "objectToQuery", "fieldToObject"
+				],
+
+				"Miscellaneous":[
+					"experimental", "deprecated", "config", "version", "locale", "baseUrl"
+				],
+
+				"Advanced-Scope":[
+					"conflict", "withDoc", "withGlobal", "setContext", "doc", "global"
+				], 
+
+				"Sniffing":[
+					"isBrowser", "isFF", "isKhtml", "isMoz", "isMozilla", "isIE", "isOpera", "isBrowser", 
+					"isQuirks", "isWebKit", "isChrome", /* new 1.4 */ "isMac"
+				]
+			},
+			
+			dijit:{
+				"Widget-Development":[
+					"create", "postCreate","buildRendering","inherited",
+					"connect", "templateString", "templatePath", "widgetsInTemplate",
+					"dojoAttachEvent", "dojoAttachPoint", "disconnect", "postMixInProperties",
+					"attributeMap", "destroyRendering", "uninitialize", "_Widget", "_Templated"
+				],
+								
+				"Dijit-Attributes":[
+					"domNode", "srcNodeRef", "containerNode", "titleNode", "focusNode",
+					"style", "id", "title", "defaultDuration", "nodesWithKeyClick", "defaultDuration"
+				],
+				
+				"Widget-Access":[
+					"byId", "byNode", "getEnclosingWidget", "findWidgets"
+				],
+				
+				"Widget-Control":[
+					"placeAt", "attr", "toString", "destroy", "startup", "destroyRecursive",
+					"destroyDescendants", "getDescendants", "getChildren", "setAttribute",
+					"placeOnScreen", "placeOnScreenAroundNode", "placeOnScreenAroundRectangle",
+					"placeOnScreenAroundElement"
+				],
+				
+				"Widget-Events":[
+					"onClick", "onFocus", "onDblClick", "onKeyPress", "onMouseOver", "onBlur",
+					"onKeyDown", "onKeyUp", "onMouseEnter", "onMouseLeave", "onMouseOut", "onMouseMove",
+					"onMouseUp", "onMouseDown"
+				],
+				
+				"ARIA-A11y-i18n":[
+					"hasWaiRole", "getWaiRole", "setWaiRole", "hasWaiState", "removeWaiState",
+					"removeWaiRole", "getWaiState", "setWaiState", "waiRole", "waiState",
+					"isLeftToRight", "isFocusable", "getFocus", "isTabNavigable", "getFirstInTabbingOrder",
+					"getLastInTabbingOrder", "focus"
+				],
+				
+				"Dijit-Utils":[
+					"getUniqueId", "getDocumentWindow", "getViewport", "scrollIntoView", "BackgroundIframe",
+					"registerIframe", "moveToBookmark", "getBookmark", "isCollapsed", "placementRegistry",
+					"registerWin" 
+				]
+			}	
+		},
+
+		getTag: function(key, part){
+			part = part || "dojo";
+			if(api.tags[part]){ 
+				// summary: find the first matching function name in the tagMap
+				for(var i in api.tags[part]){
+					if(dojo.indexOf(api.tags[part][i], key) >= 0){
+						return i;
+					}
+				}
+			}
+			return "Unknown-Tag";
+		},
+
+		getUl: function(tag){
+			// find the UL within a <div> with this tag's id, or make it. 
+			// return the UL node
+			var n = dojo.byId(tag);
+			if(!n){
+				var x = dojo.place("<fieldset id='" +tag+ "'><div class='box'><legend align='center'>" + api._deslash(tag) + "</legend><ul></ul></div></fieldset>", "container");
+				n = dojo.query("ul", x)[0];
+			}
+			return n;
+
+		},
+
+		getSig: function(key, member, fn){
+			// makup up a function signature for this object
+			if(!dojo.isFunction(fn)){ 
+//				var t = (typeof fn).toLowerCase()
+//				switch(t){
+//					case "boolean" :
+//					case "string" :
+//					case "array" :
+//					case "number" :
+//						member += "<span class='sig'> [" + t + "]</span>";
+//						break;
+//					case "object" :
+//						for(var i in fn){
+//							console.log(i);
+//						}
+//						break;
+//					default: 
+//						console.log(t);
+//						break;
+//				}
+				return key + member; 
+			}
+			if(/^_?[A-Z]/.test(member)){
+				key = "<span class='sig'>new</span> " + key;
+
+// FIXME: determine the actual signature for the a declaredclass?
+//				if(fn.prototype._constructor){
+//					console.log(fn.prototype._constructor)	
+//				}
+				
+			}
+			return key + member + "<span class='sig'>" + fn.toString().replace(/function\s+/, "").split(")")[0] + ")" + "</span>";
+		},
+
+		save: function(){
+			dojo.xhrPost({ 
+				url:"cheat.php",
+				content: { body: dojo.body().innerHTML, version: dojo.version.toString() },
+				load: function(response){
+					window.location.href = "./cheat.html";
+				},
+				error: function(er){
+					console.log("Error in saving:", er.responseText);
+				}
+			});
+		},
+
+		buildNav: function(){
+
+			dojo.query("#container > fieldset").forEach(function(n){
+
+				var id = n.id;
+				var mySize = dojo.query(n).query("li").length;
+
+				dojo.place("<li><a href='#" + id + "'>" + api._deslash(id) + "</a> (" + mySize + ")</li>", "nav");
+
+			//	console.log(mySize, n.id || n);
+
+			}).addClass("dijitInline"); // .style("float","left");
+
+		},
+		
+		addIn: function(strsomething, fs, base){
+			var d = dojo, something;
+			if(d.isObject(strsomething)){
+				// only self referencing single-objects
+				something = strsomething[strsomething];
+			}else if(dojo.exists(strsomething)){
+				something = dojo.getObject(strsomething);
+			}
+			if(!something){ return; } 
+			
+			var k = api.varmap[strsomething] || (strsomething + ".");
+			for(var i in something){
+				if( (!i.match(/^_/) || dojo.indexOf(api.useful_privates, i) >= 0) && dojo.indexOf(api.ignore, i) == -1 ){
+					var ul = fs || api.getUl(api.getTag(i, base));
+					dojo.place("<li>" + api.getSig(k, i, something[i]) + "</li>", ul);
+				}
+			
+			}
+
+		},
+
+		_deslash: function(str){
+			return str.replace(/-/g, " ");
+		},
+		
+		sortFields: function(id){
+			// stolen from demos/faces/src.js
+			var d = dojo;
+			// don't ever let me see you doing this outside of a demo situation. there has
+			// got to be a better way.
+			id = d.byId(id);
+			d.query("> fieldset", id).sort(function(a,b){
+				var q = "ul > li", al = d.query(q, a).length, bl = d.query(q, b).length;
+				return al > bl ? 0 : al < bl ? 1 : -1;
+			}).forEach(function(n){
+				id.appendChild(n);
+			});
+		},
+		
+		hasTag: function(tag){
+			return window.location.href.indexOf(tag) >= 0;
+		}
+
+	});	
+
+})();
diff --git a/util/docscripts/generate.php b/util/docscripts/generate.php
new file mode 100755
index 0000000..58865e3
--- /dev/null
+++ b/util/docscripts/generate.php
@@ -0,0 +1,440 @@
+<?php
+
+# php generate.php
+# -- Runs everything in the modules directory
+# php generate.php dojo
+# php generate.php dijit
+# php generate.php dojox
+# -- Runs only the module starting with custom, custom2, etc.
+# php generate.php --store=file
+# php generate.php --store=mysql --db_host=localhost --db_user=api --db_password=password --db_name=api
+# -- Specifies storage type. "file" and "resource" currently supported
+# php generate.php --serialize=xml,json
+# -- Comma-separated list of serializations. "xml" and "json" supported
+# php generate.php --outfile=custom-api custom
+# -- Runs the custom module, serializes to custom-api.xml
+
+if ($_SERVER['HTTP_HOST']) {
+  die('Run from command line');
+}
+
+ini_set('memory_limit', '128M');
+ini_set('display_errors', 1);
+error_reporting(E_ALL ^ E_NOTICE);
+$debug = true;
+
+require_once('lib/parser2/dojo2.inc');
+// Use file serializers by default
+
+$keys = array();
+$namespaces = array();
+
+// Do this in 3 parts
+// 1. Turn all variables into single objects
+// 2. Internalize class members
+// 3. Serialize objects
+
+$args = array();
+$kwargs = array();
+$clean = false;
+$db_host = 'localhost';
+$db_user = 'root';
+$db_password = '';
+$db_name = 'generate';
+foreach (array_slice($argv, 1) as $arg) {
+  if ($arg{0} == '-') {
+    if (preg_match('%^--(outfile|store|serialize|db_host|db_user|db_password|db_name)=([^ ]+)$%', $arg, $match)) {
+      if ($match[1] == 'db_host') {
+        $db_host = $match[2];
+      }
+      elseif ($match[1] == 'db_user') {
+        $db_user = $match[2];
+      }
+      elseif ($match[1] == 'db_password') {
+        $db_password = $match[2];
+      }
+      elseif ($match[1] == 'db_name') {
+        $db_name == $match[2];
+      }
+      elseif ($match[1] == 'serialize') {
+        foreach (explode(',', $match[2]) as $serialize_type) {
+          $kwargs[$match[1]][$serialize_type] = true;
+        }
+      }
+      else {
+        $kwargs[$match[1]] = $match[2];
+      }
+    }
+    elseif ($arg == '--clean') {
+      $clean = true;
+    }
+    else {
+      die("ERROR: Unrecognized argument: $arg\n");
+    }
+  }
+  else {
+    $args[] = $arg;
+  }
+}
+if (!isset($kwargs['serialize'])) {
+  $kwargs['serialize'] = array(
+    'json' => true,
+    'xml' => true
+  );
+}
+if (!isset($kwargs['store'])) {
+  $kwargs['store'] = 'file';
+}
+
+require_once('lib/generator/' . $kwargs['store'] . '/Freezer.php');
+require_once('lib/generator/' . $kwargs['store'] . '/Serializer.php');
+require_once('lib/generator/JsonSerializer.php');
+require_once('lib/generator/XmlSerializer.php');
+
+if ($clean) {
+  Freezer::clean('cache', 'nodes');
+  Freezer::clean('cache', 'resources');
+  if ($kwargs['outfile']) {
+    if (isset($kwargs['serialize']['json'])) {
+      JsonSerializer::clean('cache', 'json', $kwargs['outfile']);
+    }
+    if (isset($kwargs['serialize']['xml'])) {
+      XmlSerializer::clean('cache', 'xml', $kwargs['outfile']);
+    }
+  }
+  else {
+    if (isset($kwargs['serialize']['json'])) {
+      JsonSerializer::clean('cache', 'json');
+    }
+    if (isset($kwargs['serialize']['xml'])) {
+      XmlSerializer::clean('cache', 'xml');
+    }
+  }
+}
+
+$files = dojo_get_files($args);
+$nodes = new Freezer('cache', 'nodes');
+$resources = new Freezer('cache', 'resources');
+
+print "=== PARSING FILES ===\n";
+flush();
+
+foreach ($files as $set){
+  list($namespace, $file) = $set;
+  if (!$namespaces[$namespace]) {
+    $namespaces[$namespace] = true;
+  }
+
+  $ctime = dojo_get_file_time($namespace, $file);
+  if ($ctime == $resources->open($namespace . '%' . $file, null)) {
+    continue;
+  }
+
+  printf("%-100s %6s KB\n", $namespace . '/' . $file, number_format(memory_get_usage() / 1024));
+  flush();
+
+  $contents = dojo_get_contents($namespace, $file);
+
+  $provides = $contents['#provides'];
+  unset($contents['#provides']);
+  $resource = $contents['#resource'];
+  unset($contents['#resource']);
+  $requires = $contents['#requires'];
+  unset($contents['#requires']);
+
+  foreach ($contents as $var => $content) {
+    foreach ($content as $key_key => $key_value) {
+      $key_type = 'undefined';
+      if (is_numeric($key_value)) {
+        $key_type = 'numeric';
+      }elseif(is_array($key_value)) {
+        $key_type = 'array';
+      }elseif(is_bool($key_value)) {
+        $key_type = 'bool';
+      }elseif(is_string($key_value)) {
+        $key_type = 'string';
+      }
+      $keys[$key_key][] = $key_type;
+      $keys[$key_key] = array_unique($keys[$key_key]);
+    }
+
+    $node = $nodes->open($var, array());
+
+    $new = !empty($node);
+
+    // Handle file-level information
+    if ($provides && (!is_array($node['#provides']) || !in_array($provides, $node['#provides']))) {
+      $node['#provides'][] = $provides;
+    }
+
+    if (!is_array($node['#namespaces']) || !in_array($namespace, $node['#namespaces'])) {
+      $node['#namespaces'][] = $namespace;
+    }
+
+    $node['#resource'][] = "$namespace/$resource";
+
+    if (trim($content['type']) && (empty($node['type']) || $content['type'] != 'Object')) {
+      $node['type'] = $content['type'];
+    }
+
+    if (!empty($content['tags'])) {
+      $node['tags'] = $content['tags'];
+    }
+
+    if (!empty($content['private'])) {
+      $node['private'] = $content['private'];
+    }
+
+    if (!empty($content['private_parent'])) {
+      $node['private_parent'] = $content['private_parent'];
+    }
+
+    if (trim($content['summary'])) {
+      $node['summary'] = $content['summary'];
+    }
+
+    if (trim($content['description'])) {
+      $node['description'] = $content['description'];
+    }
+
+    if (trim($content['exceptions'])) {
+      $node['exceptions'] = $content['exceptions'];
+    }
+
+    if ($content['private']) {
+      $node['private'] = $content['private'];
+    }
+
+    if ($content['private_parent']) {
+      $node['private_parent'] = $content['private_parent'];
+    }
+
+    if (is_array($content['alias'])) {
+      foreach ($content['alias'] as $alias) {
+        $node['alias'] = $alias;
+      }
+    }
+
+    if (is_array($content['examples'])) {
+      foreach ($content['examples'] as $example) {
+        if (!is_array($node['examples']) || !in_array($example, $node['examples'])) {
+          $node['examples'][] = $example;
+        }
+      }
+    }
+
+    if ($content['instance']) {
+      $node['instance'] = $content['instance'];
+    }
+    
+    if ($content['prototype']) {
+      $node['prototype'] = $content['prototype'];
+    }
+
+    if (!is_array($node['returns'])) {
+      $node['returns'] = array();
+    }
+    if (trim($content['returns'])) {
+      $node['returns'] = array_unique(array_merge($node['returns'], explode('|', $content['returns'])));
+    }
+
+    if (trim($content['return_summary'])) {
+      $node['return_summary'] = $content['return_summary'];
+    }
+
+    foreach (array('prototype', 'instance', 'normal') as $scope) {
+      if (!empty($content['mixins'][$scope])) {
+        if (empty($node['mixins'][$scope])) {
+          $node['mixins'][$scope] = array();
+        }
+        if (!is_array($content['mixins'][$scope])) {
+          print $content['mixins'][$scope];
+        }
+        $node['mixins'][$scope] = array_unique(array_merge($node['mixins'][$scope], $content['mixins'][$scope]));
+      }
+    }
+
+    if ($content['type'] == 'Function') {
+      if ($content['classlike']) {
+        $node['classlike'] = true;
+      }
+
+      if ($node['chains']) {
+        if (!$content['chains']['prototype']) {
+          $content['chains']['prototype'] = array();
+        }
+        $node['chains']['prototype'] = array_unique(array_merge($node['chains']['prototype'], $content['chains']['prototype']));
+        if (!$content['chains']['call']) {
+          $content['chains']['call'] = array();
+        }
+        $node['chains']['call'] = array_unique(array_merge($node['chains']['call'], $content['chains']['call']));
+      }
+      else {
+        $node['chains']['prototype'] = ($content['chains']['prototype']) ? $content['chains']['prototype'] : array();
+        $node['chains']['call'] = ($content['chains']['call']) ? $content['chains']['call'] : array();
+      }
+
+      if ($content['chains']) {
+        unset($content['chains']['prototype']);
+        unset($content['chains']['call']);
+        $types = array_keys($content['chains']);
+        if (!empty($types)) {
+          print_r($types);
+          die('Unexpected chain type');
+        }
+      }
+
+      if (!empty($content['parameters'])) {
+        if (!empty($node['parameters'])) {
+          $node_parameters = array_keys($node['parameters']);
+          $content_parameters = array_keys($content['parameters']);
+          $long_parameters = (count($node_parameters) > count($content_parameters)) ? $node_parameters : $content_parameters;
+          $short_parameters = (count($node_parameters) >  count($content_parameters)) ? $content_parameters : $node_parameters;
+
+          $match = true;
+          foreach ($long_parameters as $i => $parameter) {
+            if ($i < count($short_parameters) && $parameter != $short_parameters[$i]) {
+              $match = false;
+            }
+          }
+
+          if ($match) {
+            // Only process these if they match the first occurence
+            foreach ($content['parameters'] as $parameter_name => $parameter) {
+              if (empty($node['parameters'][$parameter_name]['type'])) {
+                $node['parameters'][$parameter_name]['type'] = $parameter['type'];
+              }
+              if (trim($parameter['summary'])) {
+                $node['parameters'][$parameter_name]['summary'] = $parameter['summary'];
+              }
+            }
+          }
+        }
+        else {
+          $node['parameters'] = $content['parameters'];
+        }
+      }
+    }
+
+    $nodes->save($var, $node);
+  }
+
+  $resources->save($namespace . '%' . $file, $ctime);
+
+  // print_r($keys);
+}
+
+unset($resources);
+
+print "=== BUILDING OBJECT STRUCTURE ===\n";
+flush();
+
+$roots = array();
+$ids = $nodes->ids();
+
+$percent = 0;
+
+foreach ($ids as $pos => $id) {
+  $new_percent = floor($pos / count($ids) * 50);
+  if ($new_percent % 5 == 0 && $percent % 5 != 0) {
+    print floor($new_percent) . "%\n";
+  }
+  $percent = $new_percent;
+
+  $parts = explode('.', $id);
+  if (count($parts) > 1) {
+    $name = array_pop($parts);
+    $parent = implode('.', $parts);
+
+    $node = $nodes->open($id, array());
+    if (!is_array($node['#namespaces']) || (count($args) && !count(array_intersect($args, $node['#namespaces'])))) {
+      continue;
+    }
+    if (!array_key_exists($parent, $roots)) {
+      $roots[$parent] = array();
+    }
+    if ($node['type'] == 'Function') {
+      $roots[$id]['function'] = true;
+    }
+    if ($node['classlike']) {
+      $roots[$id]['classlike'] = true;
+    }
+  }
+}
+
+// Figure out whether a root item has children or not
+$pos = 0;
+$root_count = count($roots);
+foreach ($roots as $id => $root) {
+  $new_percent = floor(50 + ($pos++ / $root_count * 50));
+  if ($new_percent % 5 == 0 && $percent % 5 != 0) {
+    print floor($new_percent) . "%\n";
+  }
+  $percent = $new_percent;
+
+  if ($root['function'] && !$root['classlike']) {
+    $has_children = false;
+    $parts = explode('.', $id);
+    if (count($parts) > 1) {
+      foreach ($roots as $possible_child_id => $possible_child) {
+        $child_parts = explode('.', $possible_child_id);
+        if (count($child_parts) == count($parts)+1 && strpos($possible_child_id, "$id.") === 0) {
+          $has_children = true;
+          break;
+        }
+      }
+      if (!$has_children) {
+        unset($roots[$id]);
+      }
+    }
+  }
+}
+
+print "=== SERIALIZING OBJECTS ===\n";
+
+// Aggregate and save
+$serializers = array();
+if ($kwargs['outfile']) {
+  if (isset($kwargs['serialize']['json'])) {
+    $serializers['json'] = new JsonSerializer('cache', 'json', $kwargs['outfile']);
+  }
+  if (isset($kwargs['serialize']['xml'])) {
+    $serializers['xml'] = new XmlSerializer('cache', 'xml', $kwargs['outfile']);
+  }
+}
+else {
+  if (isset($kwargs['serialize']['json'])) {
+    $serializers['json'] = new JsonSerializer('cache', 'json');
+  }
+  if (isset($kwargs['serialize']['xml'])) {
+    $serializers['xml'] = new XmlSerializer('cache', 'xml');
+  }
+}
+
+foreach ($roots as $id => $root) {
+  if(!$id){
+    // Minor bug
+    continue;
+  }
+
+  $node = $nodes->open($id, null);
+
+  $parts = explode('.', $id);
+  foreach ($ids as $child_id) {
+    $child_parts = explode('.', $child_id);
+    if (count($child_parts) == count($parts)+1 && strpos($child_id, "$id.") === 0 && !array_key_exists($child_id, $roots)) {
+      $node['#children'][array_pop($child_parts)] = $nodes->open($child_id, null);
+    }
+  }
+
+  printf("%-100s %6s KB\n", $id, number_format(memory_get_usage() / 1024));
+  flush();
+
+  foreach ($serializers as $serializer) {
+    $serializer->setObject($id, $node);
+  }
+}
+
+// * Assemble parent/child relationships
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/includes/dojo.inc b/util/docscripts/includes/dojo.inc
new file mode 100755
index 0000000..70c4c63
--- /dev/null
+++ b/util/docscripts/includes/dojo.inc
@@ -0,0 +1,565 @@
+<?php
+
+require_once('lib/parser/Dojo.php');
+require_once('lib/parser/DojoPackage.php');
+
+DojoFunctionBody::$suffix = ':';
+
+$_dojo_properties_modules = array();
+
+function _dojo_get_namespaces($limit=null){
+  static $namespaces;
+  if (!isset($namespaces)) {
+    $namespaces = array();
+    $files = scandir('modules');
+    foreach ($files as $file) {
+      if (substr($file, -7) == '.module') {
+        $namespace = substr($file, 0, -7);
+        if (!$limit || in_array($namespace, $limit)) {
+          include_once('modules/' . $file);
+          $namespaces[] = substr($file, 0, -7);
+        }
+      }
+      elseif (substr($file, -18) == '.module.properties') {
+        $namespace = substr($file, 0, -18);
+        if (!$limit || in_array($namespace, $limit)) {
+          global $_dojo_properties_modules;
+          foreach (preg_split('%[\n\r]+%', file_get_contents('modules/' . $file)) as $line) {
+            list($line, ) = preg_split('%[!#]%', $line, 2);
+            if ($line = trim($line)) {
+              list($key, $line) = explode('=', $line, 2);
+              $key = str_replace('\\ ', ' ', trim($key));
+              $line = preg_replace('%^\s+%', '', $line);
+              if ($key == 'location') {
+                $line = _dojo_ensure_directory($line);
+              }
+              $_dojo_properties_modules[$namespace][$key] = $line;
+            }
+          }
+          $namespaces[] = substr($file, 0, -18);
+        }
+      }
+    }
+  }
+  return $namespaces;
+}
+
+function dojo_get_include($node, $provide) {
+  if ($node->jsdoc_project_name == $provide->title) {
+    return 'Included automatically';
+  }
+  else {
+    return 'dojo.require("%s");';
+  }
+}
+
+function _dojo_ensure_directory($directory) {
+  if (!is_dir($directory)) {
+    die("$directory is not a directory\n");
+  }
+  else {
+    if(substr($directory, -1) != '/'){
+      $directory .= '/';
+    }
+  }
+  return $directory;
+}
+
+function dojo_get_file_time($namespace, $file) {
+  if (function_exists($namespace . '_code_location')) {
+    return filectime(_dojo_ensure_directory(call_user_func($namespace . '_code_location')) . $file);
+  }
+  else {
+    global $_dojo_properties_modules;
+    return filectime($_dojo_properties_modules[$namespace]['location'] . $file);
+  }
+}
+
+function dojo_get_files($limit=null) {
+    $namespaces = _dojo_get_namespaces($limit);
+    $files = array();
+    foreach ($namespaces as $namespace) {
+        if (function_exists($namespace . '_code_location')) {
+          $location = _dojo_ensure_directory(call_user_func($namespace . '_code_location'));
+        }
+        else {
+          global $_dojo_properties_modules;
+          $location = $_dojo_properties_modules[$namespace]['location'];
+        }
+        if (!$location) die($namespace . '_code_location does not return useful result');
+        $dojo = new Dojo($namespace, $location);
+        $list = $dojo->getFileList();
+        foreach ($list as $i => $item) {
+            // Skip internationalization/tests/demos files
+            if (preg_match('%(^|/|\\\\)(nls|tests|demos)(\\\\|/)%', $item)) {
+              unset($list[$i]);
+              continue;
+            }
+            $list[$i] = array($namespace, $item);
+        }
+        $files = array_merge($files, array_values($list));
+    }
+
+    return $files;
+}
+
+function dojo_get_conditions() {
+    return array('svg', 'vml');
+}
+
+function dojo_get_environments() {
+    return array(
+        'common' => array(
+            'browser' => true
+        )
+    );
+}
+
+function dojo_get_contents($namespace, $file_name) {
+  $output = array();
+
+  if (function_exists($namespace . '_code_location')) {
+    $location = _dojo_ensure_directory(call_user_func($namespace . '_code_location'));
+  }
+  else {
+    global $_dojo_properties_modules;
+    $location = $_dojo_properties_modules[$namespace]['location'];
+  }
+
+  $dojo = new Dojo($namespace, $location);
+  $package = new DojoPackage($dojo, $file_name);
+
+  $output['#provides'] = $package->getPackageName();
+  $output['#resource'] = $package->getResourceName();
+
+  if ($output['#provides'] == 'null' || !$output['#resource'] == 'null') return array();
+
+  $compound_calls = $package->getFunctionCalls('dojo.kwCompoundRequire');
+  // Handle compound require calls
+  foreach ($compound_calls as $call) {
+    if ($call->getParameter(0)->isA(DojoObject)) {
+      $object = $call->getParameter(0)->getObject();
+      foreach ($object->getValues() as $key => $values) {
+        foreach ($values as $value) {
+          if ($value->isA(DojoArray)) {
+            foreach ($value->getArray()->getItems() as $item) {
+              if ($item->isA(DojoString)) {
+                $output['#requires'][] = array($key, $item->getString());
+              }
+              elseif ($item->isA(DojoArray)) {
+                $item = $item->getArray();
+                if ($item->getItem(0)->isA(DojoString)) {
+                  $output['#requires'][] = array($key, $item->getItem(0)->getString());
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  unset($compound_calls);
+  unset($call);
+  unset($object);
+  unset($key);
+  unset($value);
+  unset($item);
+
+  $require_calls = $package->getFunctionCalls('dojo.require');
+  // Handle dojo.require calls
+  foreach ($require_calls as $call) {
+    $require = $call->getParameter(0);
+    if ($require->isA(DojoString)) {
+      $output['#requires'][] = array('common', $require->getString());
+    }
+  }
+  unset($require_calls);
+  unset($call);
+  unset($require);
+
+  $require_if_calls = array_merge($package->getFunctionCalls('dojo.requireIf'), $package->getFunctionCalls('dojo.requireAfterIf'));
+  // Handle dojo.requireAfterIf calls
+  foreach ($require_if_calls as $call) {
+    $environment = $call->getParameter(0);
+    $require = $call->getParameter(1);
+    if ($environment && $require) {
+      $environment = $environment->getValue();
+      $require = $require->getValue();
+
+      unset($env);
+      unset($req);
+
+      if ($require instanceof DojoString) {
+        $req = $require->getValue();
+      }
+      if ($environment instanceof DojoString) {
+        $env = $environment->getValue();
+      }
+      elseif ($environment instanceof DojoVariable) {
+        $environment = $environment->getValue();
+        if ($environment == "dojo.isBrowser") {
+          $env = 'browser';
+        }
+        elseif ($environment == "dojo.render.svg.capable") {
+          $env = 'svg';
+        }
+        elseif ($environment == "dojo.render.vml.capable") {
+          $env = 'vml';
+        }
+        elseif (preg_match('%^dojox.gfx.render\s*=\s*"([a-z]+)"%', $environment, $match)) {
+          $env = $match[1];
+        }
+      }
+      if ($env && $req) {
+        $output['#requires'][] = array($env, $req);
+      }
+    }
+  }
+  unset($require_if_calls);
+  unset($call);
+  unset($environment);
+  unset($require);
+  unset($env);
+  unset($req);
+
+  $declare_calls = array_merge($package->getFunctionCalls('dojo.declare'), $package->getFunctionCalls('d.declare'), $package->getFunctionCalls('dojo.widget.defineWidget'));
+  // This closely matches dojo.widget.defineWidget as declared in src/widget/Widget.js
+  foreach ($declare_calls as $call) {
+    $init = null;
+    if ($call->getName() == 'dojo.declare' || $call->getName() == 'd.declare') {
+      $args = array($call->getParameter(0), null, $call->getParameter(1), $call->getParameter(2), $call->getParameter(3));
+      $name = $args[0]->getString();
+      if ($args[3]->isA(DojoFunctionDeclare)) {
+        $init = $args[3]->getFunction();
+      }
+      if ($args[3]->isA(DojoObject)) {
+        $args[4] = $args[3];
+        $args[3] = null;
+      }
+    }
+    else {
+      if ($call->getParameter(3)->isA(DojoString)) {
+        $args = array($call->getParameter(0), $call->getParameter(3), $call->getParameter(1), $call->getParameter(4), $call->getParameter(2));
+      }
+      else {
+        $args = array($call->getParameter(0));
+        $p = 3;
+        if ($call->getParameter(1)->isA(DojoString)) {
+          array_push($args, $call->getParameter(1), $call->getParameter(2));
+        }
+        else {
+          array_push($args, null, $call->getParameter(1));
+          $p = 2;
+        }
+        if ($call->getParameter($p)->isA(DojoFunctionDeclare)) {
+          $init = $call->getParameter($p)->getFunction();
+          array_push($args, $call->getParameter($p), $call->getParameter($p + 1));
+        }
+        else {
+          array_push($args, null, $call->getParameter($p));
+        }
+      }
+    }
+
+    $name = $args[0]->getString();
+    $output[$name]['type'] = 'Function';
+
+    // $args looks like (name, null, superclass(es), initializer, mixins)      
+    if ($args[2]->isA(DojoVariable)) {
+      $output[$name]['chains']['prototype'][] = $args[2]->getVariable();
+      $output[$name]['chains']['call'][] = $args[2]->getVariable();
+    }
+    elseif ($args[2]->isA(DojoArray)) {
+      $items = $args[2]->getArray()->getItems();
+      foreach ($items as $i => $item) {
+        if ($item->isA(DojoVariable)) {
+          $item = $item->getVariable();
+          if (!$i) {
+            $output[$name]['chains']['prototype'][] = $item;
+          }
+          else {
+            $output[$name]['mixins']['prototype'][] = $item . '.prototype';
+          }
+          $output[$name]['chains']['call'][] = $item;
+        }
+      }
+    }
+
+    unset($init);
+    if ($args[4]->isA(DojoObject)) {
+      $object = $args[4]->getObject();
+      $object->setName($name);
+      $object->setAnonymous(true);
+      $object->addBlockCommentKeySet('example');
+      foreach ($object->getValues() as $key => $values) {
+        foreach ($values as $value) {
+          $object->addBlockCommentKey($key);
+          $full_name = "$name.$key";
+          if ($value->isA(DojoFunctionDeclare)) {
+            if (($key == 'initializer' || $key == 'constructor')) {
+              $init = $value->getFunction();
+              $init->setConstructor(true);
+              continue;
+            }
+            $function = $value->getFunction($value);
+            $function->setPrototype($name);
+          }
+          $output[$full_name]['prototype'] = $name;
+        }
+      }
+      $object->rollOut($output, 'Function');
+
+      $keys = $object->getBlockCommentKeys();
+      foreach ($keys as $key) {
+        if ($key == 'example') {
+          $output[$name]['examples'] = $object->getBlockComment('example');
+        }
+        elseif ($key == 'summary') {
+          $output[$name]['summary'] = $object->getBlockComment('summary');
+        }
+        elseif ($key == 'description') {
+          $output[$name]['description'] = $object->getBlockComment('description');
+        }
+      }
+      unset($keys);
+    }
+    
+    if ($init) {
+      $init->setFunctionName($name);
+      $init->rollOut($output);
+    }
+  }
+  unset($declare_calls);
+  unset($call);
+  unset($init);
+  unset($args);
+  unset($name);
+  unset($p);
+  unset($items);
+  unset($item);
+  unset($object);
+  unset($values);
+  unset($key);
+  unset($value);
+  unset($full_name);
+  unset($function);
+
+  $inherit_calls = $package->getFunctionCalls('dojo.inherits', true);
+  foreach ($inherit_calls as $call) {
+    if ($call->getParameter(0)->isA(DojoVariable) && $call->getParameter(1)->isA(DojoVariable)) {
+      $output[$call->getParameter(0)->getVariable()]['chains']['prototype'][] = $call->getParameter(1)->getVariable();
+    }
+  }
+  unset($inherit_calls);
+  unset($call);
+
+  $mixin_calls = array_merge($package->getFunctionCalls('dojo.extend'), $package->getFunctionCalls('dojo.lang.extend', true), $package->getFunctionCalls('dojo.mixin'), $package->getFunctionCalls('dojo.lang.mixin'));
+  $declarations = $package->getFunctionDeclarations();
+  $executions = $package->getExecutedFunctions();
+  $objects = $package->getObjects();
+
+  // Since there can be chase conditions between declarations and calls, we need to find which were "swallowed" by larger blocks
+  $swallowed_mixins = $package->removeSwallowed($mixin_calls);
+  $package->removeSwallowed($executions);
+  $package->removeSwallowed($objects);
+
+  foreach ($objects as $object) {
+    $output[$object->getName()]['type'] = 'Object';
+    $object->rollOut($output);
+  }
+  unset($objects);
+  unset($object);
+
+  $aliases = $package->getAliases();
+  unset($aliases);
+
+  // Handle function declarations
+  foreach ($declarations as $declaration) {
+    $package->removeSwallowed($declaration);
+    foreach ($declaration as $declaration_instance){
+      $declaration_instance->removeSwallowedMixins($swallowed_mixins);
+      $declaration_instance->rollOut($output);
+    }
+  }
+  unset($declarations);
+  unset($declaration);
+  unset($declaration_instance);
+
+  foreach ($executions as $execution) {
+    $execution->removeSwallowedMixins($swallowed_mixins);
+    $execution->rollOut($output);
+
+    unset($execution);
+  }
+  $mixin_calls = array_merge($mixin_calls, $swallowed_mixins);
+
+  unset($swallowed_mixins);
+  unset($executions);
+
+  // Handle. dojo.lang.extend and dojo.lang.mixin calls
+  foreach ($mixin_calls as $call) {
+    $is_prototype = false;
+    if ($call->getParameter(0)->isA(DojoVariable) || $call->getParameter(0)->isA(DojoFunctionDeclare)) {
+      if ($call->getParameter(0)->isA(DojoVariable)) {
+        $object = $call->getParameter(0)->getVariable();
+        if (strpos($object, '(') !== false) {
+          continue;
+        }
+      }
+      else {
+        $function = $call->getParameter(0)->getFunction();
+        $object = $function->getFunctionName();
+        if (!$object) {
+          $object = $call->getAssignment();
+          $function->setFunctionName($object);
+        }
+        $function->setConstructor(true);
+        $function->rollOut($output);
+      }
+      $call_name = $call->getName();
+
+      if(strlen($object) > 10 && substr($object, -10) == '.prototype') {
+        $is_prototype = true;
+        $object = substr($object, 0, -10);
+      }
+      if ($call_name == 'dojo.lang.extend' || $call_name == 'dojo.extend') {
+        $is_prototype = true;
+      }
+
+      $parameters = $call->getParameters();
+      array_shift($parameters);
+      foreach ($parameters as $parameter) {
+        if ($parameter->isA(DojoObject)) {
+          $properties = $parameter->getObject();
+          $keys = $properties->getValues();
+          foreach ($keys as $key => $functions) {
+            foreach ($functions as $function) {
+              $full_variable_name = "$object.$key";
+
+              if ($is_prototype) {
+                  $output[$full_variable_name]['prototype'] = $object;
+              }
+              if ($function->isA(DojoFunctionDeclare)) {
+                $function = $function->getFunction();
+                if ($is_prototype) {
+                  $function->setPrototype($object);
+                }
+                $function->setFunctionName($full_variable_name);
+                $function->rollOut($output);
+              }
+              elseif ($function->isA(DojoObject)) {
+                $output[$full_variable_name]['type'] = 'Object';
+                $obj = $function->getObject();
+                $obj->setName($full_variable_name);
+                $obj->rollOut($output);
+              }
+              else {
+                if ($call_name == 'dojo.lang.mixin' || $call_name == 'dojo.mixin') {
+                  if (!isset($output[$full_variable_name])) {
+                    $output[$full_variable_name] = array();
+                  }
+                }
+              }
+            }
+          }
+        }
+        elseif ($parameter->isA(DojoVariable)) {
+          if ($call_name == 'dojo.lang.extend' || $call_name == 'dojo.extend') {
+            $output[$object]['mixins']['prototype'][] = $parameter->getVariable();
+          }
+          elseif ($call_name == 'dojo.lang.mixin' || $call_name == 'dojo.mixin') {
+            $output[$object]['mixins']['normal'][] = $parameter->getVariable();
+          }
+        }
+        elseif ($parameter->isA(DojoString)) {
+          print_r($call);
+          throw new Exception('Odd string');
+          $properties = $parameter->getString();
+          // Note: inherits expects to be reading from prototype values
+          if (($call_name == 'dojo.lang.extend' || $call_name == 'dojo.extend') && strpos($properties, '.prototype') !== false) {
+            $output[$object]['chains']['prototype'][] = str_replace('.prototype', '', $properties);
+          }
+          elseif (($call_name == 'dojo.lang.extend' || $call_name == 'dojo.extend') && strpos($properties, 'new ') !== false) {
+            $output[$object]['chains']['prototype'][] = str_replace('new ', '', $properties);
+          }
+          else {
+            $output[$properties]['inherits'] = $object;
+          }
+        }
+      }
+    }
+  }
+  unset($mixin_calls);
+  unset($call);
+  unset($is_prototype);
+  unset($object);
+  unset($call_name);
+  unset($properties);
+  unset($keys);
+  unset($key);
+  unset($function);
+  unset($variable_name);
+  unset($full_variable_name);
+
+  $external_variables = $package->getExternalVariables();
+  foreach ($external_variables as $external_variable) {
+    if (empty($output[$external_variable])) {
+      $output[$external_variable] = array();
+    }
+  }
+
+  // Remember, dojo.provides creates new objects if needed
+  $parts = explode('.', $output['#provides']);
+  while (count($parts)) {
+      if (!array_key_exists(implode('.', $parts), $output)) {
+          $output[implode('.', $parts)] = array('type' => 'Object');
+      }
+      array_pop($parts);
+  }
+  unset($parts);
+
+  list($project,) = explode('.', $output['#provides'], 2);
+  if ($output['#requires']) {
+    foreach ($output['#requires'] as &$require) {
+      list($require_project,) = explode('.', $require[1]);
+      if ($require_project != $project) {
+        $require[2] = $require_project;
+      }
+    }
+  }
+
+  foreach ($output as $object_name => $object) {
+    if ($object_name{0} == '#') {
+      continue;
+    }
+    $parts = explode('.', $object_name);
+    $last = array_pop($parts);
+    if ($last{0} == '_') {
+      $output[$object_name]['private'] = true;
+    }
+    if (preg_match('%\._+[^A-Z]%', implode('.', $parts), $match)) {
+        $output[$object_name]['private_parent'] = true;
+    }
+    if ($object['type'] == 'Function') {
+      if (preg_match('%^(_*)[A-Z]%', $last, $match)) {
+        if (strlen($match[1]) < 2) {
+          unset($output[$object_name]['private']);
+        }
+        $output[$object_name]['classlike'] = true;
+      }
+      elseif ($object['prototype'] && $output[$object['prototype']]) {
+        $output[$object['prototype']]['classlike'] = true;
+      }
+      elseif ($object['instance'] && $output[$object['instance']]) {
+        $output[$object['instance']]['classlike'] = true;
+      }
+    }
+    $output[$object_name]['summary'] = htmlentities($object['summary']);
+  }
+
+  $package->destroy();
+
+  return $output;
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/generator/JsonSerializer.php b/util/docscripts/lib/generator/JsonSerializer.php
new file mode 100644
index 0000000..2056308
--- /dev/null
+++ b/util/docscripts/lib/generator/JsonSerializer.php
@@ -0,0 +1,141 @@
+<?php
+
+class JsonSerializer extends Serializer
+{
+  protected $header = array('{');
+  protected $footer = array('}');
+
+  protected function lineStarts($line) {
+    if (preg_match('%^\t"([^"]+)": {%', $line, $match)) {
+      return $match[1];
+    }
+  }
+
+  protected function lineEnds($line) {
+    if (preg_match('%^\t}%', $line, $match)) {
+      return true;
+    }
+  }
+
+  protected function linesToRaw($lines) {
+    $lines[0] = '{';
+    $lines[count($lines)-1] = '}';
+    return json_decode(implode("\n", $lines));
+  }
+
+  public function toObject($raw, $id=null) {
+    return $raw;
+  }
+
+  public function toString($raw, $id=null) {
+    if (!$id) {
+      if (!($id = $raw['id'])) {
+        throw new Exception('toString must be passed an ID or raw object must contain and ID');
+      }
+    }
+
+    $tab = "\t";
+    $new_json = "\"$id\": ";
+    $indent_level = 0;
+    $in_string = false;
+
+    $json = json_encode($raw);
+    $len = strlen($json);
+
+    for ($c = 0; $c < $len; $c++) {
+      $char = $json{$c};
+      switch($char) {
+      case '{':
+      case '[':
+        if (!$in_string) {
+          $new_json .= $char . "\n" . str_repeat($tab, ++$indent_level);
+        }
+        else {
+          $new_json .= $char;
+        }
+        break;
+      case '}':
+      case ']':
+        if(!$in_string) {
+          $new_json .= "\n" . str_repeat($tab, --$indent_level) . $char;
+        }
+        else {
+          $new_json .= $char;
+        }
+        break;
+      case ',':
+        if (!$in_string) {
+          $new_json .= ",\n" . str_repeat($tab, $indent_level);
+        }
+        else {
+          $new_json .= $char;
+        }
+        break;
+      case ':':
+        if (!$in_string) {
+          $new_json .= ": ";
+        }
+        else {
+          $new_json .= $char;
+        }
+        break;
+      case '"':
+        if($c > 0 && $json[$c-1] != '\\') {
+          $in_string = !$in_string;
+        }
+      default:
+        $new_json .= $char;
+        break;
+      }
+    }
+
+    return $new_json . ",\n";
+  }
+
+  protected function descend($node, $object) {
+    if (!is_array($object) && !is_object($object)) {
+      return $object;
+    }
+
+    foreach ($object as $key => $value) {
+      switch ($key{0}) {
+      case '@':
+        $node[substr($key, 1)] = $value;
+        break;
+      case '#':
+        if ($key == '#mixins') {
+          foreach ($value as $mixins) {
+            $scope = $mixins['@scope'];
+            foreach ($mixins['#mixin'] as $mixin) {
+              $node['mixins'][$scope][] = $this->descend(array(), $mixin);
+            }
+          }
+        }
+        elseif (count($value) == 1 && !in_array($key, array('#property', '#method', '#resource', '#parameter', '#provide', '#return-type'))) {
+          $node[substr($key, 1)] = $this->descend(array(), $value[0]);
+        }
+        else {
+          foreach ($value as $child) {
+            $node[] = $this->descend(array(), $child);
+          }
+        }
+        break;
+      default:
+        if ($key === 'content') {
+          if (count($object) == 1) {
+            return $value;
+          }
+          $node['content'] = $value;
+        }
+      }
+    }
+
+    return $node;
+  }
+
+  public function convertToRaw($object) {
+    return $this->descend(array(), $object);
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/generator/XmlSerializer.php b/util/docscripts/lib/generator/XmlSerializer.php
new file mode 100644
index 0000000..9004419
--- /dev/null
+++ b/util/docscripts/lib/generator/XmlSerializer.php
@@ -0,0 +1,118 @@
+<?php
+
+class XmlSerializer extends Serializer
+{
+  protected $header = array('<?xml version="1.0" encoding="UTF-8"?>', '<javascript>');
+  protected $footer = array('</javascript>');
+
+  protected function lineStarts($line) {
+    if (preg_match('%^\t<object [^>]*location="([^"]+)"%', $line, $match)) {
+      return $match[1];
+    }
+  }
+
+  protected function lineEnds($line) {
+    if (preg_match('%^\t</object>$%', $line, $match)) {
+      return true;
+    }
+  }
+
+  protected function linesToRaw($lines) {
+    return DOMDocument::loadXML(implode("\n", $lines));
+  }
+
+  public function toObject($raw, $id=null) {
+    return $this->ascend($raw, $raw->firstChild);
+  }
+
+  public function ascend($document, $node) {
+    $object = array();
+
+    if ($node->hasAttributes()) {
+      if ($node->attributes) {
+        foreach ($node->attributes as $attribute) {
+          $value = $attribute->value;
+          if ($value == 'true') {
+            $value = true;
+          }
+          elseif ($value == 'false') {
+            $value = false;
+          }
+          $object['@' . $attribute->name] = $value;
+        }
+      }
+    }
+    if ($node->childNodes) {
+      foreach ($node->childNodes as $child_node) {
+        if ($child_node->tagName) {
+          $object['#' . $child_node->tagName][] = $this->ascend($document, $child_node);
+        }
+        else {
+          // Text node
+          $object['content'] = $node->nodeValue;
+        }
+      }
+    }
+
+    return $object;
+  }
+
+  public function toString($raw, $id=null) {
+    if (!$id) {
+      if (!($id = $raw->firstChild->getAttribute('location'))) {
+        throw new Exception('toString must be passed an ID or raw object must contain and ID');
+      }
+    }
+
+    $lines = explode("\n", str_replace('<?xml version="1.0" encoding="UTF-8"?>' . "\n", '', $raw->saveXML()));
+    foreach ($lines as $i => $line) {
+      $indent = 0;
+      while (substr($line, 0, 2) == '  ') {
+        ++$indent;
+        $line = substr($line, 2);
+      }
+      $lines[$i] = str_repeat("\t", $indent) . $line;
+    }
+
+    if (count($lines) && substr($lines[0], -2) == '/>') {
+      $lines[0] = substr($lines[0], 0, -2) . '>';
+      array_splice($lines, 1, 0, array('</object>'));
+    }
+
+    return implode("\n", $lines);
+  }
+
+  protected function descend($document, $node, $object) {
+    foreach ($object as $key => $value) {
+      if (is_bool($value)) {
+        $value = $value ? 'true' : 'false';
+      }
+      switch ($key{0}) {
+      case '@':
+        $node->setAttribute(substr($key, 1), $value);
+        break;
+      case '#':
+        foreach ($value as $child) {
+          $this->descend($document, $node->appendChild($document->createElement(substr($key, 1))), $child);
+        }
+        break;
+      default:
+        if ($key === 'content') {
+          $node->appendChild($document->createTextNode($value));
+        }
+      }
+    }
+  }
+
+  public function convertToRaw($object) {
+    $document = new DOMDocument('1.0', 'UTF-8');
+    $document->preserveWhiteSpace = true;
+    $document->formatOutput = true;
+
+    $this->descend($document, $document->appendChild($document->createElement('object')), $object);
+
+    return $document;
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/generator/common/AbstractSerializer.php b/util/docscripts/lib/generator/common/AbstractSerializer.php
new file mode 100644
index 0000000..28bc89a
--- /dev/null
+++ b/util/docscripts/lib/generator/common/AbstractSerializer.php
@@ -0,0 +1,350 @@
+<?php
+
+abstract class AbstractSerializer
+{
+  protected $header = array(); // Array of lines to begin the file with
+  protected $footer = array(); // Array of lines to end the file with
+  protected $indent = "\t";
+
+  // Deal with object conversion
+  abstract public function toObject($raw, $id=null); // Convert raw output to an object
+  abstract public function toString($raw, $id=null); // Convert raw output to a string for serialization
+  abstract protected function convertToRaw($object); // Convert an object to a raw value
+
+  /**
+   * Get a list of all IDs related to this serializer
+   */
+  abstract public function ids();
+
+  /**
+   * Set a value for a given ID
+   */
+  abstract public function set($id, $value);
+
+  /**
+   * Get the string-serialized representation of an object for a given ID
+   */
+  abstract protected function getString($id);
+
+  /**
+   * Set an object (rather than a raw value) for a given ID.
+   * The object should be converted to a raw equivalent
+   */
+  public function setObject($id, $value) {
+    $raw = $this->toRaw($value, $id);
+    $this->set($id, $raw);
+    return $raw;
+  }
+
+  protected function buildResources(&$node, $object) {
+    if (!empty($object['#resource'])) {
+      $node['#resources'][] = array();
+      $resources_node = &$node['#resources'][count($node['#resources']) - 1];
+      foreach ($object['#resource'] as $resource) {
+        $resources_node['#resource'][] = array();
+        $resource_node = &$resources_node['#resource'][count($resources_node['#resource']) - 1];
+        $resource_node['content'] = $resource;
+      }
+    }
+
+    if (!empty($object['#provides'])) {
+      $node['#provides'][] = array();
+      $provides_node = &$node['#provides'][count($node['#provides']) - 1];
+      foreach ($object['#provides'] as $provide) {
+        $provides_node['#provide'][] = array();
+        $provide_node = &$provides_node['#provide'][count($provides_node['#provide']) - 1];
+        $provide_node['content'] = $provide;
+      }
+    }
+  }
+
+  protected function buildMethod(&$method_node, $method, $method_id, $child = TRUE) {
+    if ($child) {
+      $this->buildResources($method_node, $method);
+
+      $method_node['@name'] = $method_id;
+
+      if ($method_id == 'preamble' || $method_id == 'postscript') {
+        $method_node['@constructor'] = $method_id;
+      }
+
+      if ($method['instance'] && $method['prototype']) {
+        $method_node['@scope'] = 'instance-prototype';
+      }
+      elseif($method['instance']) {
+        $method_node['@scope'] = 'instance';
+      }
+      elseif($method['prototype']) {        
+        $method_node['@scope'] = 'prototype';
+      }
+      else {                      
+        $method_node['@scope'] = 'normal';
+      }
+
+      if (!empty($method['tags'])) {
+        $method_node['@tags'] = implode(' ', $method['tags']);
+      }
+
+      if ($method['private']) {
+        $method_node['@private'] = true;
+      }
+
+      if ($method['private_parent']) {
+        $method_node['@privateparent'] = true;
+      }
+
+      if (trim($method['summary'])) {
+        $method_node['#summary'][] = array();
+        $description_node = &$method_node['#summary'][count($method_node['#summary']) - 1];
+        $description_node['content'] = $method['summary'];
+      }
+
+      if (trim($method['description'])) {
+        $method_node['#description'][] = array();
+        $description_node = &$method_node['#description'][count($method_node['#description']) - 1];
+        $description_node['content'] = $method['description'];
+      }
+
+      if (!empty($method['examples'])) {
+        $method_node['#examples'][] = array();
+        $examples_node = &$method_node['#examples'][count($method_node['#examples']) - 1];
+        foreach ($method['examples'] as $example) {
+          $examples_node['#example'][] = array();
+          $example_node = &$examples_node['#example'][count($examples_node['#example']) - 1];
+          $example_node['content'] = $example;
+        }
+      }
+    }
+
+    if (trim($method['return_summary'])) {
+      $method_node['#return-description'][] = array();
+      $description_node = &$method_node['#return-description'][count($method_node['#return-description']) - 1];
+      $description_node['content'] = $method['return_summary'];
+    }
+
+    if (!empty($method['parameters'])) {
+      $method_node['#parameters'][] = array();
+      $parameters_node = &$method_node['#parameters'][count($method_node['#parameters']) - 1];
+      foreach ($method['parameters'] as $parameter_name => $parameter) {
+        $parameters_node['#parameter'][] = array();
+        $parameter_node = &$parameters_node['#parameter'][count($parameters_node['#parameter']) - 1];
+        $parameter_node['@name'] = $parameter_name;
+        $parameter_node['@type'] = $parameter['type'];
+        $parameter_node['@usage'] = ($parameter['optional']) ? 'optional' : (($parameter['repeating']) ? 'one-or-more' : 'required');
+        if ($parameter['summary']) {
+          $parameter_node['#summary'][] = array();
+          $description_node = &$parameter_node['#summary'][count($parameter_node['#summary']) - 1];
+          $description_node['content'] = $parameter['summary'];
+        }
+      }
+    }
+
+    if (!empty($method['returns'])) {
+      $method_node['#return-types'][] = array();
+      $returns_node = &$method_node['#return-types'][count($method_node['#return-types']) - 1];
+      foreach ($method['returns'] as $return) {
+        $returns_node['#return-type'][] = array();
+        $return_node = &$returns_node['#return-type'][count($returns_node['#return-type']) - 1];
+        $return_node['@type'] = $return;
+      }
+    }
+
+    return $method_node;
+  }
+
+  public function toAbstract($object, $id) {
+    $object_node = array();
+
+    $object_node['@location'] = $id;
+
+    $this->buildResources($object_node, $object);
+
+    $methods_node = NULL;
+    if ($object['type'] == 'Function') {
+      $object_node['@type'] = 'Function';
+      if (!$object['classlike']) {
+        $this->buildMethod($object_node, $object, $object['location'], FALSE);
+      }
+      else {
+        $object_node['@classlike'] = TRUE;
+
+        $methods_node = array();
+        $method_node = array(
+          '@constructor' => 'constructor'
+        );
+        if (!empty($object['chains']['prototype'])) {
+          $superclass = array_shift($object['chains']['prototype']);
+          $object_node['@superclass'] = $superclass;
+        }
+        $methods_node['#method'][] = $this->buildMethod($method_node, $object, $object['location'], FALSE);
+      }
+    }
+    elseif ($object['type'] != 'Object') {
+      $object_node['@type'] = $object['type'];
+    }
+
+    if (!empty($object['tags'])) {
+      $object_node['@tags'] = implode(' ', $object['tags']);
+    }
+
+    if ($object['private']) {
+      $object_node['@private'] = true;
+    }
+
+    if ($object['private_parent']) {
+      $object_node['@privateparent'] = true;
+    }
+
+    if (trim($object['summary'])) {
+      $object_node['#summary'][] = array();
+      $description_node = &$object_node['#summary'][count($object_node['#summary']) - 1];
+      $description_node['content'] = $object['summary'];
+    }
+
+    if (trim($object['description'])) {
+      $object_node['#description'][] = array();
+      $description_node = &$object_node['#description'][count($object_node['#description']) - 1];
+      $description_node['content'] = $object['description'];
+    }
+
+    if (!empty($object['examples'])) {
+      $object_node['#examples'][] = array();
+      $examples_node = &$object_node['#examples'][count($object_node['#examples']) - 1];
+      foreach ($object['examples'] as $example) {
+        $examples_node['#example'][] = array();
+        $example_node = &$examples_node['#example'][count($examples_node['#example']) - 1];
+        $example_node['content'] = $example;
+      }
+    }
+
+    $mixins = array();
+    if (!empty($object['chains']['prototype'])) {
+      foreach ($object['chains']['prototype'] as $mixin) {
+        // Classes are assumed here
+        $mixins['prototype']['prototype'][] = $mixin;
+      }
+    }
+    if (!empty($object['mixins']['prototype'])) {
+      foreach ($object['mixins']['prototype'] as $mixin) {
+        if (strlen($mixin) > 10 && substr($mixin, -10) == '.prototype') {
+          $mixins['prototype']['prototype'][] = substr($mixin, 0, -10);
+        }
+        else {
+          $mixins['prototype']['normal'][] = $mixin;
+        }
+      }
+    }
+    if (!empty($object['chains']['call'])) {
+      foreach ($object['chains']['call'] as $mixin) {
+        $mixins['instance']['instance'][] = $mixin;
+      }
+    }
+    if (!empty($object['mixins']['normal'])) {
+      foreach ($object['mixins']['normal'] as $mixin) {
+        if (strlen($mixin) > 10 && substr($mixin, -10) == '.prototype') {
+          $mixins['normal']['prototype'][] = substr($mixin, 0, -10);
+        }
+        else {
+          $mixins['normal']['normal'][] = $mixin;
+        }
+      }
+    }
+
+    foreach ($mixins as $scope => $mixins) {
+      $object_node['#mixins'][] = array();
+      $mixins_node = &$object_node['#mixins'][count($object_node['#mixins']) - 1];
+      $mixins_node['@scope'] = $scope;
+      foreach ($mixins as $scope => $mixins) {
+        foreach (array_unique($mixins) as $mixin) {
+          $mixins_node['#mixin'][] = array();
+          $mixin_node = &$mixins_node['#mixin'][count($mixins_node['#mixin']) - 1];
+          $mixin_node['@scope'] = $scope;
+          $mixin_node['@location'] = $mixin;
+        }
+      }
+    }
+
+    $methods = array();
+    $properties = array();
+    if (!empty($object['#children'])) {
+      foreach ($object['#children'] as $child_id => $child) {
+        if ($child['type'] == 'Function') {
+          $methods[$child_id] = $child;
+        }
+        else {
+          $properties[$child_id] = $child;
+        }
+      }
+    }
+
+    if (!empty($properties)) {                    
+      $object_node['#properties'][] = array();
+      $properties_node = &$object_node['#properties'][count($object_node['#properties']) - 1];
+      foreach ($properties as $property_id => $property) {
+        $properties_node['#property'][] = array();
+        $property_node = &$properties_node['#property'][count($properties_node['#property']) - 1];
+                                                    
+        $property_node['@name'] = $property_id;
+
+        $this->buildResources($property_node, $property);
+
+        if ($property['instance'] && $property['prototype']) {
+          $property_node['@scope'] = 'instance-prototype';
+        }
+        elseif($property['instance']) {
+          $property_node['@scope'] = 'instance';
+        }
+        elseif($property['prototype']) {
+          $property_node['@scope'] = 'prototype';
+        }
+        else {                        
+          $property_node['@scope'] = 'normal';
+        }
+
+        $property_node['@type'] = $property['type'];
+
+        if (!empty($property['tags'])) {
+          $property_node['@tags'] = implode(' ', $property['tags']);
+        }
+
+        if ($property['private']) {
+          $property_node['@private'] = true;
+        }
+
+        if ($property['private_parent']) {
+          $property_node['@privateparent'] = true;
+        }
+
+        if ($property['summary']) {                      
+          $property_node['#summary'][] = array();
+          $description_node = &$property_node['#summary'][count($property_node['#summary']) - 1];
+          $description_node['content'] = $property['summary'];
+        }
+      }
+    }
+
+    if (!empty($methods)) {
+      if (!$methods_node) {                     
+        $methods_node = array();
+      }                        
+
+      foreach ($methods as $method_id => $method) {
+        $method_node = array();
+        $methods_node['#method'][] = $this->buildMethod($method_node, $method, $method_id);
+      }
+    }
+
+    if ($methods_node) {
+      $object_node['#methods'][] = $methods_node;
+    }
+
+    return $object_node;
+  }
+
+  /**
+   * Convert an object to its raw representation
+   */
+  public function toRaw($object, $id) {
+    return $this->convertToRaw($this->toAbstract($object, $id));
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/generator/common/db.php b/util/docscripts/lib/generator/common/db.php
new file mode 100644
index 0000000..361f8b0
--- /dev/null
+++ b/util/docscripts/lib/generator/common/db.php
@@ -0,0 +1,18 @@
+<?php
+
+function db_query() {
+  global $db_host, $db_user, $db_password, $db_name;
+  static $db;
+  if (!$db) {
+    $db = mysql_connect($db_host, $db_user, $db_password) or die;
+    mysql_select_db($db_name, $db);
+  }
+
+  $args = func_get_args();
+  $query = (count($args) > 1) ? call_user_func_array('sprintf', $args) : $args[0];
+  return mysql_query($query, $db);
+}
+
+function db_fetch_assoc($query) {
+  return mysql_fetch_assoc($query);
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/generator/file/Freezer.php b/util/docscripts/lib/generator/file/Freezer.php
new file mode 100644
index 0000000..db821b8
--- /dev/null
+++ b/util/docscripts/lib/generator/file/Freezer.php
@@ -0,0 +1,133 @@
+<?php
+
+final class Freezer
+{
+  protected $key_delimeter = '%%%';
+
+  private $length = 99999;
+  private $nodes;
+  private $nodes_location = '';
+  private $queue;
+  private $limit = 500;
+
+  public static function clean($directory, $suffix) {
+    $loc = $directory . '/' . $suffix;
+    file_exists($loc) && unlink($loc);
+  }
+
+  public function __construct($directory, $suffix) {
+    $this->queue = array();
+    $this->nodes_location = $directory . '/' . $suffix;
+    touch($this->nodes_location);
+    $this->nodes = fopen($this->nodes_location, 'r');
+  }
+
+  public function __destruct() {
+    $this->flush();
+
+    fclose($this->nodes);
+  }
+
+  public function ids($flush = TRUE) {
+    if ($flush) {
+      $this->flush();
+    }
+
+    $ids = array();
+
+    rewind($this->nodes);
+    while (!feof($this->nodes)) {
+      $line = stream_get_line($this->nodes, $this->length, "\n");
+      list($key,) = explode($this->key_delimeter, $line);
+      if (trim($key)) {
+        $ids[] = $key;
+      }
+    }
+
+    return $ids;
+  }
+
+  public function open($key, $default) {
+    foreach (array_reverse($this->queue) as $queue) {
+      list($queue_key, $content) = $queue;
+      if ($queue_key == $key) {
+        return $content;
+      }
+    }
+
+    $key .= $this->key_delimeter;
+    rewind($this->nodes);
+    while (!feof($this->nodes)) {
+      $line = stream_get_line($this->nodes, $this->length, "\n");
+      if (strlen($line) > strlen($key) && substr($line, 0, strlen($key)) == $key) {
+        $line = substr($line, strlen($key));
+        return unserialize(str_replace("\\n", "\n", $line));
+      }
+    }
+    return $default;
+  }
+
+  public function save($key, $content) {
+    $this->queue[] = array($key, $content);
+    if (count($this->queue) > $this->limit) {
+      $this->flush();
+    }
+  }
+
+  private function flush() {
+    $deferred = array();
+    $keys = $this->ids(FALSE);
+
+    foreach ($this->queue as $queue) {
+      list($key, $content) = $queue;
+      $serialized = $key . $this->key_delimeter . str_replace("\n", "\\n", serialize($content));
+      if (!in_array($key, $keys)) {
+        $deferred[$key] = $serialized;
+        continue;
+      }
+
+      $key = $key . $this->key_delimeter;
+      $found = false;
+      $tmp = fopen($this->nodes_location . '_tmp', 'w');
+      rewind($this->nodes);
+      while (!feof($this->nodes)) {
+        if ($line = stream_get_line($this->nodes, $this->length, "\n")) {
+          if (strlen($line) > strlen($key) && substr($line, 0, strlen($key)) == $key) {
+            $found = true;
+            $line = $serialized;
+          }
+          if (strlen($line) > $this->length-2) {
+            die('Line too long: ' . $line . "\n");
+          }
+          fwrite($tmp, $line . "\n");
+        }
+      }
+      if (!$found) {
+        fwrite($tmp, $key . str_replace("\n", "\\n", serialize($content)) . "\n");
+      }
+      fclose($tmp);
+      fclose($this->nodes);
+
+      unlink($this->nodes_location);
+      rename($this->nodes_location . '_tmp', $this->nodes_location);
+      $this->nodes = fopen($this->nodes_location, 'r');
+    }
+
+    if (!empty($deferred)) {
+      fclose($this->nodes);
+      copy($this->nodes_location, $this->nodes_location . '_tmp');
+      $tmp = fopen($this->nodes_location . '_tmp', 'a');
+
+      foreach ($deferred as $line) {
+        fwrite($tmp, $line . "\n");
+      }
+      fclose($tmp);
+
+      unlink($this->nodes_location);
+      rename($this->nodes_location . '_tmp', $this->nodes_location);
+      $this->nodes = fopen($this->nodes_location, 'r');
+    }
+
+    $this->queue = array();
+  }
+}
diff --git a/util/docscripts/lib/generator/file/Serializer.php b/util/docscripts/lib/generator/file/Serializer.php
new file mode 100644
index 0000000..1a0af75
--- /dev/null
+++ b/util/docscripts/lib/generator/file/Serializer.php
@@ -0,0 +1,208 @@
+<?php
+
+require_once('lib/generator/common/AbstractSerializer.php');
+
+abstract class Serializer extends AbstractSerializer
+{
+  private $file_location;
+
+  private $file;
+  private $length = 9999;
+
+  private $queue;
+  private $limit = 50;
+
+  public static function clean($directory, $suffix, $filename='api') {
+    $loc = $directory . '/' . $filename . '.' . $suffix;
+    file_exists($loc) && unlink($loc);
+  }
+
+  public function __construct($directory, $suffix, $filename='api') {
+    $this->queue = array();
+    $this->file_location = $directory . '/' . $filename . '.' . $suffix;
+    touch($this->file_location);
+    $this->file = fopen($this->file_location, 'r');
+  }
+
+  public function __destruct() {
+    $this->flush();
+
+    fclose($this->file);
+  }
+
+  public function ids($flush = TRUE) {
+    if ($flush) {
+      $this->flush();
+    }
+
+    $ids = array();
+    $started = false;
+
+    rewind($this->file);
+    while (!feof($this->file)) {
+      $line = stream_get_line($this->file, $this->length, "\n");
+      if ($started && $this->lineEnds($line)) {
+        $started = false;
+        continue;
+      }
+      elseif ($id = $this->lineStarts($line)) {
+        $started = true;
+        $ids[] = $id;
+      }
+    }
+
+    return $ids;
+  }
+
+  protected function getString($id, $include_queue = TRUE) {
+    if ($include_queue) {
+      foreach (array_reverse($this->queue) as $queue) {
+        list($queue_id, $value) = $queue;
+        if ($queue_id == $id) {
+          return $this->toString($value, $id);
+          break;
+        }
+      }
+    }
+
+    $lines = array();
+    $started = false;
+    $strlen = strlen($this->indent);
+
+    rewind($this->file);
+    while (!feof($this->file)) {
+      $line = stream_get_line($this->file, $this->length, "\n");
+      if ($started) {
+        $lines[] = substr($line, $strlen);
+        if ($this->lineEnds($line)) {
+          return implode("\n", $lines) . "\n";
+        }
+      }
+      elseif ($this->lineStarts($line) == $id) {
+        $started = true;
+        $lines[] = substr($line, $strlen);
+      }
+    }
+  }
+
+  public function set($id, $value) {
+    $this->queue[] = array($id, $value);
+    if (count($this->queue) > $this->limit) {
+      $this->flush();
+    }
+  }
+
+  public function flush() {
+    $deferred = array();
+    $ids = $this->ids(FALSE);
+
+    foreach ($this->queue as $position => $queue) {
+      list($id, $value) = $queue;
+      $last = ($position + 1 == count($this->queue));
+      $tostring = $this->toString($value, $id);
+      if (!in_array($id, $ids)) {
+        if (!$last) {
+          $deferred[$id] = $tostring;
+          continue;
+        }
+      }
+
+      if (!$id) {
+        debug_print_backtrace();
+        die("Called set without an ID\n");
+      }
+
+      if ($tostring == $this->getString($id, FALSE)) {
+        continue;
+      }
+
+      $lines = array();
+      $started = false;
+      $found = false;
+      $header = false;
+      $buffer = array();
+
+      $tmp = fopen($this->file_location . '_tmp', 'w');
+      foreach ($this->header as $header_line) {
+        fwrite($tmp, $header_line . "\n");
+      }
+
+      rewind($this->file);
+      while (!feof($this->file)) {
+        $line = stream_get_line($this->file, $this->length, "\n");
+        if (!trim($line)) {
+          continue;
+        }
+
+        if ($started) {
+          $lines[] = $line;
+          if ($this->lineEnds($line)) {
+            $lines = explode("\n", $tostring);
+            foreach ($lines as $line) {
+              fwrite($tmp, $this->indent . $line . "\n");
+            }
+            $started = false;
+            $found = true;
+          }
+        }
+        elseif (!$found && $this->lineStarts($line) == $id) {
+          foreach ($buffer as $line) {
+            fwrite($tmp, $line . "\n");
+          }
+          $buffer = array();
+          $started = true;
+          $lines[] = $line;
+        }
+        else {        
+          // Search through non-block data for headers first, then footers
+          if (!isset($searching)) {
+            $searching = $this->header;
+          }
+
+          $buffer[] = $line;
+          if (count($buffer) == count($searching) && count(array_intersect($buffer, $searching)) == count($searching)) {
+            // Successful match
+            if ($searching === $this->header) {
+              $buffer = array();
+              $searching = $this->footer;
+            }
+            else {
+              // Break before the footer is added
+              break;
+            }
+          }
+          elseif(count($buffer) > count($searching)) {
+            fwrite($tmp, array_shift($buffer) . "\n");
+          }
+        }
+      }
+
+      if (!$found) {
+        if ($last) {
+          foreach ($deferred as $lines) {
+            foreach (explode("\n", $lines) as $line) {
+              fwrite($tmp, $this->indent . $line . "\n");
+            }
+          }
+        }
+        $lines = explode("\n", $tostring);
+        foreach ($lines as $line) {
+          fwrite($tmp, $this->indent . $line . "\n");
+        }
+      }
+
+      foreach ($this->footer as $footer_line) {
+        fwrite($tmp, $footer_line . "\n");
+      }
+
+      fclose($tmp);
+      fclose($this->file);
+
+      unlink($this->file_location);
+      rename($this->file_location . '_tmp', $this->file_location);
+      $this->file = fopen($this->file_location, 'r');
+    }
+
+    $this->queue = array();
+  }
+}
diff --git a/util/docscripts/lib/generator/mysql/Freezer.php b/util/docscripts/lib/generator/mysql/Freezer.php
new file mode 100644
index 0000000..da92267
--- /dev/null
+++ b/util/docscripts/lib/generator/mysql/Freezer.php
@@ -0,0 +1,47 @@
+<?php
+
+require_once('lib/generator/common/db.php');
+
+final class Freezer
+{
+  private $namespace = '';
+
+  public static function clean($directory, $namespace) {
+    db_query("TRUNCATE freezer");
+  }
+
+  function __construct($directory, $namespace) {
+    $this->namespace = $namespace;
+  }
+
+  public function ids($flush = TRUE) {
+    $ids = array();
+
+    $query = db_query("SELECT id FROM freezer WHERE namespace = '%s'", $this->namespace);
+    while ($row = db_fetch_assoc($query)) {
+      $ids[] = $row['id'];
+    }
+
+    return $ids;
+  }
+
+  public function open($key, $default) {
+    $query = db_query("SELECT value FROM freezer WHERE namespace = '%s' AND id = '%s' AND BINARY id = '%s'", $this->namespace, $key, $key);
+    if ($row = db_fetch_assoc($query)) {
+      return unserialize($row['value']);
+    }
+    return $default;
+  }
+
+  public function save($key, $content) {
+    $content = mysql_escape_string(serialize($content));
+
+    $query = db_query("SELECT 1 FROM freezer WHERE namespace = '%s' AND id = '%s' AND BINARY id = '%s'", $this->namespace, $key, $key);
+    if (db_fetch_assoc($query)) {
+      db_query("UPDATE freezer SET value = '%s' WHERE namespace = '%s' AND id = '%s' AND BINARY id = '%s'", $content, $this->namespace, $key, $key);
+    }
+    else {
+      db_query("INSERT INTO freezer (namespace, id, value) VALUES ('%s', '%s', '%s')", $this->namespace, $key, $content);
+    }
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/generator/mysql/Serializer.php b/util/docscripts/lib/generator/mysql/Serializer.php
new file mode 100644
index 0000000..080adf7
--- /dev/null
+++ b/util/docscripts/lib/generator/mysql/Serializer.php
@@ -0,0 +1,86 @@
+<?php
+
+require_once('lib/generator/common/db.php');
+require_once('lib/generator/common/AbstractSerializer.php');
+
+abstract class Serializer extends AbstractSerializer
+{
+  private $namespace;
+  private $file_location;
+
+  private $file;
+  private $length = 9999;
+
+  private $queue;
+  private $limit = 50;
+
+  public static function clean($directory, $namespace, $filename='api') {
+    db_query("TRUNCATE freezer");
+  }
+
+  public function __construct($directory, $suffix, $filename='api') {
+    $this->file_location = $directory . '/' . $filename . '.' . $suffix;
+    $this->namespace = $filename . '.' . $suffix;
+  }
+
+  public function __destruct() {
+    $tmp = fopen($this->file_location . '_tmp', 'w');
+
+    foreach ($this->header as $header_line) {
+      fwrite($tmp, $header_line . "\n");
+    }
+    foreach ($this->ids() as $id) {
+      foreach (explode("\n", $this->getString($id)) as $line) {
+        if ($line) {
+          fwrite($tmp, $this->indent . $line . "\n");
+        }
+      }
+    }
+    foreach ($this->footer as $footer_line) {
+      fwrite($tmp, $footer_line . "\n");
+    }
+
+    fclose($tmp);
+
+    if (file_exists($this->file_location)) {
+      unlink($this->file_location);
+    }
+
+    rename($this->file_location . '_tmp', $this->file_location);
+  }
+
+  public function ids() {
+    $ids = array();
+
+    $query = db_query("SELECT id FROM freezer WHERE namespace = '%s'", $this->namespace);
+    while ($row = db_fetch_assoc($query)) {
+      $ids[] = $row['id'];
+    }
+
+    return $ids;
+  }
+
+  protected function getString($id) {
+    $query = db_query("SELECT value FROM freezer WHERE namespace = '%s' AND id = '%s' AND BINARY id = '%s'", $this->namespace, $id, $id);
+    if ($result = db_fetch_assoc($query)) {
+      return $result['value'];
+    }
+  }
+
+  public function set($id, $value) {
+    if (!$id) {
+      debug_print_backtrace();
+      die("Called set without an ID\n");
+    }
+
+    $content = mysql_escape_string($this->toString($value, $id));
+
+    $query = db_query("SELECT 1 FROM freezer WHERE namespace = '%s' AND id = '%s' AND BINARY id = '%s'", $this->namespace, $id, $id);
+    if (db_fetch_assoc($query)) {
+      db_query("UPDATE freezer SET value = '%s' WHERE namespace = '%s' AND id = '%s' AND BINARY id = '%s'", $content, $this->namespace, $id, $id);
+    }
+    else {
+      db_query("INSERT INTO freezer (namespace, id, value) VALUES ('%s', '%s', '%s')", $this->namespace, $id, $content);
+    }
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/generator/resource/Freezer.php b/util/docscripts/lib/generator/resource/Freezer.php
new file mode 100644
index 0000000..ccc2a8b
--- /dev/null
+++ b/util/docscripts/lib/generator/resource/Freezer.php
@@ -0,0 +1,3 @@
+<?php
+
+require_once('lib/generator/file/Freezer.php');
\ No newline at end of file
diff --git a/util/docscripts/lib/generator/resource/Serializer.php b/util/docscripts/lib/generator/resource/Serializer.php
new file mode 100644
index 0000000..b5e8661
--- /dev/null
+++ b/util/docscripts/lib/generator/resource/Serializer.php
@@ -0,0 +1,176 @@
+<?php
+
+require_once('lib/generator/common/AbstractSerializer.php');
+
+abstract class Serializer extends AbstractSerializer
+{
+  private $directory;
+  private $suffix;
+
+  private $file;
+  private $length = 9999;
+
+  private $queue;
+  private $limit = 50;
+
+  public static function clean($directory, $suffix, $filename='provides') {
+    $directory .= '/provides';
+    if (!file_exists($directory)) {
+      mkdir($directory);
+      chmod($directory, 0755);
+    }
+    $suffix = '.' . $suffix;
+    $from = -strlen($suffix);
+    foreach (scandir($directory) as $file) {
+      if (substr($file, $from) == $suffix) {
+        file_exists($directory . '/' . $file) && unlink($directory . '/' . $file);
+      }
+    }
+  }
+
+  public function __construct($directory, $suffix, $filename='provides') {
+    $this->directory = $directory . '/provides';
+    if (!file_exists($this->directory)) {
+      mkdir($this->directory);
+      chmod($this->directory, 0755);
+    }
+    $this->suffix = '.' . $suffix;
+  }
+
+  public function ids() {
+    $ids = array();
+
+    $from = -strlen($this->suffix);
+    foreach (scandir($this->directory) as $file) {
+      if (substr($file, $from) == $this->suffix) {
+        $file = fopen($this->directory . '/' . $file, 'r');
+        while (!feof($file)) {
+          $line = stream_get_line($file, $this->length, "\n");
+          if ($started && $this->lineEnds($line)) {
+            $started = false;
+            continue;
+          }
+          elseif ($id = $this->lineStarts($line)) {
+            $started = true;
+            $ids[] = $id;
+          }
+        }
+      }
+    }
+
+    return array_unique($ids);
+  }
+
+  protected function getString($id, $include_queue = TRUE) {
+    return '';
+  }
+
+  public function set($id, $value) {
+  }
+
+  public function setObject($id, $value) {
+    $pretty = $this->toAbstract($value, $id);
+    $provides = $this->extractProvides($pretty);
+    $updates = array();
+    $lookups = array(array('#properties', '#property'), array('#methods', '#method'));
+    foreach ($lookups as $list) {
+      list($types, $type) = $list;
+      if ($pretty[$types]) {
+        foreach ($pretty[$types][0][$type] as $item) {
+          foreach ($this->extractProvides($item, $provides) as $provide => $item) {
+            $updates[$provide][$types][$item['@name']] = $item;
+            if (!array_key_exists($provide, $provides)) {
+              $provides[$provide] = array();
+            }
+            // $provides[$provide][$types][0][$type][] = $item;
+          }
+        }
+      }
+    }
+
+    foreach ($provides as $provide => $provide_value) {
+      $file_name = $this->directory . '/' . $provide . $this->suffix;
+
+      $found = false;
+      $output = implode("\n", $this->header) . "\n";
+      if (file_exists($file_name)) {
+        $contents = substr(file_get_contents($file_name), strlen(implode("\n", $this->header))+1, -strlen(implode("\n", $this->footer))-1);
+        $buffer = array();
+        foreach (explode("\n", $contents) as $line) {
+          if (!empty($buffer) && $this->lineEnds($line)) {
+            $buffer[] = $line;
+            $found = true;
+            $saved = array();
+            $raw = $this->linesToRaw($buffer);
+            $object = $this->toObject($raw);
+
+            foreach ($lookups as $list) {
+              list($types, $type) = $list;
+              if ($object[$types]) {
+                foreach ($object[$types][0][$type] as $item) {
+                  $saved[$types][$item['@name']] = $item;
+                }
+              }
+              if (isset($updates[$provide][$types])) {
+                foreach ($updates[$provide][$types] as $item) {
+                  $saved[$types][$item['@name']] = $item;
+                }
+              }
+            }
+
+            foreach ($saved as $types => $item) {
+              $provide_value[$types][0][$type][] = $item;
+            }
+
+            $raw = $this->convertToRaw($provide_value);
+            foreach (explode("\n", $this->toString($raw, $id)) as $line) {
+              $output .= $this->indent . $line . "\n";
+            }
+
+            $buffer = array();
+          }
+          elseif ($this->lineStarts($line) == $id) {
+            $buffer[] = substr($line, strlen($this->indent));
+          }
+          else {
+            $output .= $line . "\n";
+          }
+        }
+      }
+
+      if (!$found) {
+        foreach ($lookups as $list) {
+          list($types, $type) = $list;
+          if (isset($updates[$provide][$types])) {
+            foreach ($updates[$provide][$types] as $item) {
+              $provide_value[$types][0][$type][] = $item;
+            }
+          }
+        }
+        $raw = $this->convertToRaw($provide_value);
+        foreach (explode("\n", $this->toString($raw, $id)) as $line) {
+          $output .= $this->indent . $line . "\n";
+        }
+      }
+
+      $output .= implode("\n", $this->footer);
+      file_put_contents($file_name, $output);
+    }
+  }
+
+  private function extractProvides($value) {
+    $provides = array();
+    if ($value['#provides']) {
+      foreach ($value['#provides'] as $provide) {
+        foreach ($provide['#provide'] as $content) {
+          unset($value['#resources']);
+          unset($value['#provides']);
+          unset($value['#properties']);
+          unset($value['#methods']);
+          $provides[$content['content']] = $value;
+        }
+      }
+    }
+    return $provides;
+  }
+}
diff --git a/util/docscripts/lib/parser/Dojo.php b/util/docscripts/lib/parser/Dojo.php
new file mode 100644
index 0000000..d0b5639
--- /dev/null
+++ b/util/docscripts/lib/parser/Dojo.php
@@ -0,0 +1,82 @@
+<?php
+
+function destroy_all($item) {
+  if (is_array($item)) {
+    array_walk($item, 'destroy_all');
+  }
+  else {
+    if (is_string($item)) {
+      die($item);
+    }
+    $item->destroy();
+  }
+}
+
+class Dojo
+{
+  private $dir;
+  public $namespace;
+
+  public function __construct($namespace, $dir){
+    $this->setDir($dir);
+    $this->namespace = $namespace;
+  }
+  
+  public function __destruct() {
+    unset($this->dir);
+    unset($this->namespace);
+  }
+
+  public function getPackage($file){
+    return new DojoPackage($file);
+  }
+
+  public function getDir(){
+    return $this->dir;
+  }
+
+  public function setDir($dir){
+    $this->dir = $dir;
+  }
+
+  public function getFileList($dir = false, $recurse = false){
+    $output = array();
+    if ($dir === false) {
+      $dir = $this->getDir();
+    }
+
+    if (!$recurse) {
+      $old_dir = getcwd();
+      if (!is_dir($dir)) {
+        return array();
+      }
+      chdir($dir);
+      $dir = '.';
+    }
+    $files = scandir($dir);
+
+    foreach ($files as $file) {
+      if ($file{0} == '.') continue;
+      if (is_dir($dir . '/' . $file)) {
+        if ($recurse) {
+          $file = $dir . '/' . $file;
+        }
+        $output = array_merge($output, $this->getFileList($file, true));
+      }else{
+        if (substr($file, -3) == '.js' && substr($file, -6) != '.xd.js') {
+          if ($recurse) {
+            $file = $dir . '/' . $file;
+          }
+          $output[] = $file;
+        }
+      }
+    }
+
+    if (!$recurse) {
+      chdir($old_dir);
+    }
+    return $output;
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoArray.php b/util/docscripts/lib/parser/DojoArray.php
new file mode 100644
index 0000000..5aa716c
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoArray.php
@@ -0,0 +1,20 @@
+<?php
+
+require_once('DojoParameters.php');
+require_once('DojoBlock.php');
+
+class DojoArray extends DojoParameters
+{
+	private $object = 'DojoArray';
+	protected $terminator = ']';
+
+	public function getItems(){
+		return $this->getParameters();
+	}
+	
+	public function getItem($pos){
+		return $this->getParameter($pos);
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoBlock.php b/util/docscripts/lib/parser/DojoBlock.php
new file mode 100644
index 0000000..13c74cb
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoBlock.php
@@ -0,0 +1,37 @@
+<?php
+
+abstract class DojoBlock
+{
+  protected $package;
+  protected $destroyed = false;
+  public $start;
+  public $end;
+
+  public function __construct($package, $line_number = false, $position = false){
+    $this->package = $package;
+    if($line_number !== false && $position !== false){
+      $this->setStart($line_number, $position);
+    }
+  }
+  
+  public function destroy() {
+  }
+  
+  public function __destruct() {
+    unset($this->package);
+    unset($this->start);
+    unset($this->end);
+  }
+  
+  public function setStart($line_number, $position){
+    $this->start = array($line_number, $position);
+  }
+  
+  protected function setEnd($line_number, $position){
+      $this->end = array($line_number, $position);
+  }
+  
+  public abstract function build();
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoBoolean.php b/util/docscripts/lib/parser/DojoBoolean.php
new file mode 100644
index 0000000..75f1e95
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoBoolean.php
@@ -0,0 +1,16 @@
+<?php
+
+class DojoBoolean
+{
+	private $value = '';
+	
+	public function __construct($value){
+		$this->value = ($value == 'true');
+	}
+	
+	public function getValue(){
+		return $this->value;
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoExecutedFunction.php b/util/docscripts/lib/parser/DojoExecutedFunction.php
new file mode 100644
index 0000000..6f840f9
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoExecutedFunction.php
@@ -0,0 +1,108 @@
+<?php
+
+require_once('DojoFunctionDeclare.php');
+require_once('DojoParameters.php');
+require_once('Text.php');
+
+class DojoExecutedFunction extends DojoFunctionDeclare
+{
+  private $object = 'DojoExecutedFunction';
+
+  public function build(){
+    if(!$this->start){
+      die("DojoExecutedFunction->build() used before setting a start position");
+    }
+    if($this->end){
+      return $this->end;
+    }
+
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1]);
+    $line = $lines[$this->start[0]];
+    
+    $this->start = array($this->start[0], strpos($line, 'function'));
+
+    $this->end = parent::build(); // Basically, the end array here will hold the position of the final } in the function declaration.
+
+    $parameters = $this->getParameters();
+    if (count($parameters) && ($pos = strpos($lines[$this->end[0]], '(')) !== false) {
+      $arguments = new DojoParameters($this->package);
+      $arguments->start = array($this->end[0], $pos);
+      $arguments->build();
+      $arguments = $arguments->getParameters();
+      foreach ($parameters as $pos => $parameter) {
+        if ($arguments[$pos]) {
+          $argument = $arguments[$pos];
+          if ($argument->isA(DojoVariable) && $parameter->isA(DojoVariable)) {
+            if (preg_match('%(^|\|\|)([a-zA-Z0-9_.$]+)(\|\||$)%', $argument->getVariable(), $match)) {
+              $this->body->addResolvedParameter($parameter->getVariable(), $match[2]);
+            }
+          }
+        }
+      }
+    }
+    $lines = Text::chop($this->package->getCode(), $this->end[0], $this->end[1], false, false, true);
+    $closed = false;
+    foreach($lines as $line_number => $line){
+      $offset = 0;
+      if($line_number == $this->end[0]){
+        $offset = $this->end[1];
+      }
+      if(preg_match('%\S%', $line, $match, PREG_OFFSET_CAPTURE, $offset)){
+        if(!$closed){
+          if($match[0][0] != ')'){
+            return false;
+          }else{
+            $closed = true;
+            $offset = $match[0][1] + 1;
+          }
+        }
+      }
+      if(preg_match('%\S%', $line, $match, PREG_OFFSET_CAPTURE, $offset)){
+        if($closed){
+          if($match[0][0] != '('){
+            return false;
+          }else{
+            $parameters = new DojoParameters($this->package, $line_number, $match[0][1]);
+            $end = $parameters->build();
+            break;
+          }
+        }
+      }
+    }
+    return $end;
+  }
+
+  public function rollOut(&$output) {
+    if ($this->getFunctionName()) {
+      parent::rollOut($output);
+    }
+
+    $execution_variables = $this->getVariableNames($this->getFunctionName());
+    foreach ($execution_variables as $execution_variable) {
+      if (empty($output[$execution_variable])) {
+        $output[$execution_variable] = array();
+      }
+    }
+
+    $execution_declarations = $this->getFunctionDeclarations();
+    foreach ($execution_declarations as $declaration) {
+      $declaration->rollOut($output);
+    }
+
+    $execution_objects = $this->getObjects();
+    foreach ($execution_objects as $object) {
+      $object->rollOut($output);
+    }
+    unset($object);
+    unset($execution_objects);
+
+    if ($this->getFunctionName()) {
+      $instance_declarations = $this->getInstanceFunctions($this->getFunctionName());
+      foreach ($instance_declarations as $declaration) {
+        $declaration->rollOut($output);
+      }
+    }
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoFunction.php b/util/docscripts/lib/parser/DojoFunction.php
new file mode 100644
index 0000000..e69de29
diff --git a/util/docscripts/lib/parser/DojoFunctionBody.php b/util/docscripts/lib/parser/DojoFunctionBody.php
new file mode 100644
index 0000000..110c42f
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoFunctionBody.php
@@ -0,0 +1,707 @@
+<?php
+
+require_once('DojoBlock.php');
+
+class DojoFunctionBody extends DojoBlock
+{
+  private $object = 'DojoFunctionBody';
+
+  private $comment_end;
+
+  public static $prefix = '';
+  public static $suffix = '';
+
+  private $keys = array();
+  private $key_sets = array();
+  private $comments = array();
+  private $return_comments = array();
+  private $instance_variables = array();
+  private $resolved_parameters = array();
+  private $externalized = array();
+  private $externalized_objects = array();
+  private $externalized_avariables = array();
+  private $externalized_ivariables = array();
+  private $externalized_variables = array();  
+  private $externalized_mixins = array();
+  private $this_inheritance_calls = array();
+  private $extra_initial_comment_block = array();
+
+  public function destroy() {
+    if (!$this->destroyed) {
+      $this->destroyed = true;
+      array_walk($this->externalized, 'destroy_all');
+      unset($this->externalized);
+      array_walk($this->externalized_objects, 'destroy_all');
+      unset($this->externalized_objects);
+      array_walk($this->externalized_mixins, 'destroy_all');
+      unset($this->externalized_mixins);
+    }
+  }
+
+  public function build() {
+    if (!$this->start) {
+      die("DojoFunctionBody->build() used before setting a start position");
+    }
+    if ($this->end) {
+      return $this->end;
+    }
+
+    $balance = 0;
+    $start_position = $this->start[1];
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1], false, false, true);
+        return $this->end = Text::findTermination($lines, '}', '{}');
+  }
+
+  public function addBlockCommentLine($line) {
+    $this->extra_initial_comment_block[] = $line;
+  }
+
+  public function addBlockCommentBreak() {
+    $this->extra_initial_comment_block[] = -1;
+  }
+
+  public function addBlockCommentKey($key) {
+    $this->comments = array();
+    if ($key) {
+      $this->keys[] = $key;
+    }
+  }
+
+  /**
+   * This key can occur multiple times. eg: example
+   */
+  public function addBlockCommentKeySet($key) {
+    $this->comments = array();
+    if ($key) {
+      $this->key_sets[] = $key;
+    }
+  }
+
+  public function getSource() {
+    $this->getBlockCommentKeys();
+    $source = array();
+    $lines = Text::chop($this->package->getSource(), $this->comment_end[0], $this->comment_end[1], $this->end[0], $this->end[1]);
+    if ($this->start[0] == $this->comment_end[0] && $this->start[1] == $this->comment_end[1]) {
+      $lines[$this->start[0]] = substr($lines[$this->start[0]], $this->start[1] + 1);
+    }
+    $lines[$this->end[0]] = substr($lines[$this->end[0]], 0, $this->end[1]);
+    foreach ($lines as $line_number => $line) {
+      $trimmed_line = trim($line);
+      if ($trimmed_line === '') {
+        $source[] = '';
+      }
+      $source[] = $line;
+    }
+    while (!empty($source)) {
+      if (trim($source[0]) === '') {
+        array_shift($source);
+        continue;
+      }
+      break;
+    }
+    while (!empty($source)) {
+      if (trim($source[count($source) - 1]) === '') {
+        array_pop($source);
+        continue;
+      }
+      break;
+    }
+    return implode("\n", $source);
+  }
+
+  private function cleanBlock($text){
+    $lines = explode("\n", trim($text));
+    $output = array();
+    $indented = false;
+    $blank = false;
+    foreach ($lines as $i => $line) {
+      if ($line{0} == "|") {
+        if(!$indented){
+          $indented = true;
+          if (!$blank) {
+            $output[] = "";
+            if (!$i) {
+              $output[] = "";
+            }
+          }
+        }
+        $output[] = substr($line, 1);
+      }
+      else {
+        if($indented){
+          $indented = false;
+          if (empty($line)) {
+            if (!$blank) {
+              $output[] = "";
+            }
+          }
+        }
+        if (empty($line)) {
+          $blank = true;
+        }
+        $output[] = $line;
+      }
+    }
+    return implode("\n", $output);
+  }
+
+  public function getBlockComment($key) {
+    $this->getBlockCommentKeys();
+    $value = $this->comments[$key];
+    if (!empty($value)) {
+      if (is_array($value)) {
+        for ($i = 0; $i < count($value); $i++){
+          $value[$i] = $this->cleanBlock($value[$i]);
+        }
+      }
+      else {
+        $value = $this->cleanBlock($value);
+      }
+    }
+    return $value;
+  }
+
+  public function getBlockCommentKeys() {
+    if ($this->comments) { 
+      return array_keys($this->comments); 
+    }
+
+    $this->build();
+
+    $prefix = '\b';
+    if (self::$prefix) {
+      $prefix = preg_quote(self::$prefix, '%');
+    }
+    $suffix = '\b';
+    if (self::$suffix) {
+      $suffix = preg_quote(self::$suffix, '%');
+    }
+    $expression = '%^' . $prefix . '(' . implode('|', array_merge($this->keys, $this->key_sets)) . ')' . $suffix . '\W*%';
+
+    $lines = Text::chop($this->package->getSource(), $this->start[0], $this->start[1], $this->end[0], $this->end[1], true);
+    for ($i = 0; $i < 2; $i++) {
+      $started = false;
+      $between_blocks = true;
+      $wait_for_break = false;
+      $buffer = array();
+      $key = '';
+      if ($i == 1) {
+        $lines = $this->extra_initial_comment_block;
+      }
+      foreach ($lines as $line_number =>  $line) {
+        if ($line === -1) {
+          // Comes from manually added lines (block breaks, e.g. between object keys)
+          $between_blocks = true;
+          continue;
+        }
+
+        list($comment, , , $data, $multiline) = Text::findComments($line, $multiline);
+
+        if ($between_blocks) {
+          if ($comment) {
+            if (preg_match($expression, $comment)) {
+              $between_blocks = false;
+            }
+            elseif (!$i) {
+              continue 2;
+            }
+            else {
+              $wait_for_break = true;
+              continue;
+            }
+          }
+        }
+        elseif ($comment === false) {
+          $between_blocks = true;
+          continue;
+        }
+
+        if (preg_match($expression, $comment, $match)) {
+          if ($buffer && $key) {
+            if (in_array($key, $this->key_sets)) {
+              $this->comments[$key][] = implode("\n", $buffer);
+            }
+            else {
+              $this->comments[$key] = implode("\n", $buffer);
+            }
+            $buffer = array();
+          }
+          $key = $match[1];
+          if ($match[0] == $comment) {
+            $comment = '';
+          }else{
+            $comment = substr($comment, strlen($match[0]));
+          }
+        }
+
+        if ($data) {
+          $this->comment_end = array($line_number, 0);
+          break;
+        }
+
+        $buffer[] = $comment;
+      }
+
+      if ($buffer && $key) {
+        if (in_array($key, $this->key_sets)) {
+          $this->comments[$key][] = implode("\n", $buffer);
+        }
+        else {
+          $this->comments[$key] = implode("\n", $buffer);
+        }
+      }
+
+      if ($i == 0 && !$this->comment_end) {
+        $this->comment_end = $this->start;
+      }
+    }
+
+    return array_keys($this->comments);
+  }
+
+  public function addResolvedParameter($parameter, $value) {
+    $this->resolved_parameters[$parameter] = $value;
+  }
+
+  public function getLocalVariableNames() {
+    $internals = array();
+
+    $this->build();
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1], $this->end[0], $this->end[1], true);
+    // Find simple external variable assignment.
+    $matches = preg_grep('%(?:var|this)%', $lines);
+    foreach ($matches as $line_number => $line) {
+      // Check for var groups, or var name =
+      if (preg_match('%var\s+[a-zA-Z0-9_.$]+([^;]+,\s*[a-zA-Z0-9_.$]+)*%', $line, $match)) {
+        preg_match_all('%(?:var\s+([a-zA-Z_.$][\w.$]*)|,\s*([a-zA-Z_.$][\w.$]*))%', $match[0], $named_matches, PREG_SET_ORDER);
+        foreach ($named_matches as $named_match) {
+          if (!empty($named_match[1])) {
+            $internals[$named_match[1]] = false;
+          }
+          if (!empty($named_match[2])) {
+            $internals[$named_match[2]] = false;
+          }
+        }
+      }
+      if (preg_match('%var\s+([a-zA-Z_.$][\w.$]*)\s*=\s*([a-zA-Z_.$][a-zA-Z0-9_.$]*)\s*[;\n]%', $line, $match)) {
+        if (in_array($match[2], array('null', 'true', 'false', 'this'))) continue;
+        $internals[$match[1]] = $match[2];
+      }
+      if (preg_match('%(this\.[a-zA-Z_.$][\w.$]*)\s*=\s*([a-zA-Z_.$][\w.$]*)%', $line, $match)) {
+        $internals[$match[2]] = $match[1];
+      }
+    }
+
+    foreach ($this->resolved_parameters as $parameter => $value) {
+      $internals[$parameter] = $value;
+    }
+
+    return $internals;
+  }
+
+  /**
+   * If these occur inside this function AND reference a local variable, remove them
+   */
+  public function removeSwallowedMixins(&$possible_mixins) {
+    // If any of the mixins happened inside of an executed function, we need to see if
+    // they were used on external variables.
+    if ($this->externalized_mixins) {
+      return $this->externalized_mixins;
+    }
+
+    $this->build();
+    $internals = $this->getLocalVariableNames();
+
+    foreach ($possible_mixins as $i => $mixin) {
+      if (($this->start[0] < $mixin->start[0] || ($this->start[0] == $mixin->start[0] && $this->start[1] < $mixin->start[1])) &&
+          ($this->end[0] > $mixin->end[0] || ($this->end[0] == $mixin->end[0] && $this->end[1] > $mixin->end[1]))) {
+        $parameter = $mixin->getParameter(0);
+        if ($mixin->getName() == 'dojo.extend' && $parameter->isA(DojoFunctionDeclare)) {
+          $code = $this->package->getCode();
+          $line = substr($code[$parameter->start[0]], 0, $parameter->start[1]);
+          $line = substr($line, 0, strrpos($line, $mixin->getName()));
+          preg_match_all('%(?:([a-zA-Z0-9_.$\s]+)\s*=\s*)+%', $line, $matches);
+          foreach ($matches[1] as $match) {
+            $match = trim($match);
+            if (!preg_match('%^var\s+%', $match)) {
+              $found = true;
+              while ($found) {
+                $found = false;
+                foreach ($internals as $internal_name => $external_name) {
+                  if ($internal_name == 'this') continue;
+                  if (strpos($match, $internal_name . '.') === 0) {
+                    $last = $match;
+                    $match = $external_name . substr($match, strlen($internal_name));
+                    if ($last != $match) {
+                      $found = true;
+                    }
+                  }
+                }
+              }
+              $parameter->getFunction()->setFunctionName($match);
+            }
+          }
+          $this->externalized_mixins[] = $mixin;
+        }
+        elseif ($parameter->isA(DojoVariable)) {
+          $object = $parameter->getVariable();
+          if ($object == "this") {
+            unset($possible_mixins[$i]);
+          }
+          elseif (($mixin->start[0] > $this->start[0] || ($mixin->start[0] == $this->start[0] && $mixin->start[1] > $this->start[1]))
+              && ($mixin->end[0] < $this->end[0] || ($mixin->end[0] == $this->end[0] && $mixin->end[1] < $this->end[1]))) {
+            if (array_key_exists($object, $internals)) {
+                unset($possible_mixins[$i]);
+            }
+            else {
+              foreach ($internals as $internal_name => $external_name) {
+                if (strpos($object, $internal_name . '.') === 0) {
+                  $object = $external_name . substr($object, strlen($internal_name));
+                }
+              }
+
+              $parameter->setVariable($object);
+            }
+          }
+          $this->externalized_mixins[] = $mixin;
+        }
+        else {
+          $this->externalized_mixins[] = $mixin;
+          array_splice($possible_mixins, $i--, 1);
+        }
+      }
+    }
+  }
+
+  public function getExternalizedObjects($function_name=false, $parameter_names=array()){
+    if ($this->externalized_objects) {
+      return $this->externalized_objects;
+    }
+
+    $this->build();
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1], $this->end[0], $this->end[1], true);
+    foreach ($this->externalized_mixins as $mixin) {
+      $lines = Text::blankOutAtPositions($lines, $mixin->start[0], $mixin->start[1], $mixin->end[0], $mixin->end[1]);
+    }
+    $internals = $this->getLocalVariableNames();
+
+    $matches = preg_grep('%=\s*\{%', $lines);
+    foreach ($matches as $line_number => $line) {
+      if (preg_match('%(\b[a-zA-Z_.$][\w.$]*(?:\.[a-zA-Z_.$][\w.$]|\["[^"]+"\])*)\s*=\s*{%', $line, $match)) {
+        if (array_key_exists($match[1], $internals)) continue;
+
+        $externalized_object = new DojoObject($this->package, $line_number, strpos($line, '{', strpos($line, $match[0])));
+        $end = $externalized_object->build();
+
+        $name = $match[1];
+        if (strpos($name, 'this.') === 0) continue;
+
+        foreach ($internals as $internal_name => $external_name) {
+          if (strpos($name, $internal_name . '.') === 0) {
+            if (!$external_name) continue 2;
+            $name = $external_name . substr($name, strlen($internal_name));
+          }
+        }
+
+        if (strpos($name, '[') !== false) {
+          $source_lines = Text::chop($this->package->getSource(), $line_number, 0);
+          $source_line = trim($source_lines[$line_number]);
+          preg_match('%\b([a-zA-Z_.$][\w.$]*(?:\.[a-zA-Z_.$][\w.$]|\["[^"]+"\])*)\s*=\s*function%', $source_line, $source_match);
+          $name = preg_replace('%\["([^"]+)"\]%', '.$1', $source_match[1]);
+        }
+
+        if (strpos($name, 'this.') === 0) {
+          if (!$function_name) continue;
+
+          $name = $function_name . substr($name, 4);
+        }
+
+        if (in_array($name, $parameter_names)) {
+          continue;
+        }
+
+        $externalized_object->setName($name);
+        $this->externalized_objects[] = $externalized_object;
+      }
+    }
+
+    return $this->externalized_objects;
+  }
+
+  public function getExternalizedFunctionDeclarations($function_name=false) {
+    if ($this->externalized) {
+      return $this->externalized;
+    }
+
+    $this->build();
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1], $this->end[0], $this->end[1], true);
+    $internals = $this->getLocalVariableNames();
+
+    $matches = preg_grep('%function\s*\(%', $lines);
+    $last_line = 0;
+    foreach ($matches as $line_number => $line) {
+      if ($line_number < $last_line) continue;
+      if (preg_match('%(var)?\s*(\b[a-zA-Z_.$][\w.$]*(?:\.[a-zA-Z_.$][\w.$]*|\["[^"]+"\])*)\s*=\s*function\s*\(%', $line, $match)) {
+        if ($match[1] || array_key_exists($match[2], $internals)) continue;
+
+        $externalized = new DojoFunctionDeclare($this->package, $line_number, strpos($line, $match[0]));
+        $end = $externalized->build();
+        $last_line = $end[0];
+
+        $externalized->rebuildAliases($internals);
+        $externalized->setExecutedFunction($this);
+
+        $name = $match[2];
+        if (strpos($name, 'this.') === 0) continue;
+
+        foreach ($internals as $internal_name => $external_name) {
+          if (strpos($name, $internal_name . '.') === 0) {
+            if (!$external_name) continue 2;
+            $name = $external_name . substr($name, strlen($internal_name));
+          }
+        }
+
+        if (strpos($name, '[') !== false) {
+          $source_lines = Text::chop($this->package->getSource(), $line_number, 0);
+          $source_line = trim($source_lines[$line_number]);
+          preg_match('%\b([a-zA-Z_.$][\w.$]*(?:\.[a-zA-Z_.$][\w.$]|\["[^"]+"\])*)\s*=\s*function\b%', $source_line, $source_match);
+          $name = preg_replace('%\["([^"]+)"\]%', '.$1', $source_match[1]);
+        }
+
+        if (strpos($name, 'this.') === 0) {
+          if (!$function_name) continue;
+
+          $name = $function_name . substr($name, 4);
+        }
+
+        $parts = explode('.', $name);
+        if (count($parts) > 2 && array_pop(array_slice($parts, -2, 1)) == 'prototype') {
+          array_splice($parts, -2, 1);
+          $name = implode('.', $parts);
+          array_pop($parts);
+          $externalized->setPrototype(implode('.', $parts));
+        }
+
+        $externalized->setFunctionName($name);
+        $this->externalized[] = $externalized;
+      }
+      else {
+        $skipped = new DojoFunctionDeclare($this->package, $line_number, strpos($line, 'function'));
+        $end = $skipped->build();
+        $last_line = $end[0];
+      }
+    }
+
+    return $this->externalized;
+  }
+
+  public function getExternalizedAllVariableNames($function_name, $parameter_names=array()) {
+    if ($this->externalized_avariables) {
+      return $this->externalized_avariables;
+    }
+
+    $this->build();
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1], $this->end[0], $this->end[1], true);
+    $internals = $this->getLocalVariableNames();
+
+    $declarations = $this->getExternalizedFunctionDeclarations($function_name);
+    foreach ($declarations as $declaration) {
+      $declaration->build();
+      $lines = Text::blankOutAtPositions($lines, $declaration->start[0], $declaration->start[1], $declaration->end[0], $declaration->end[1]);
+    }
+
+    $objects = $this->getExternalizedObjects(false, $parameter_names);
+    foreach ($objects as $object) {
+      $object->build();
+      $lines = Text::blankOutAtPositions($lines, $object->start[0], $object->start[1], $object->end[0], $object->end[1]);
+    }
+
+    $lines = $this->package->removeCodeFrom($lines);
+
+    $variables = array();
+
+    foreach (preg_grep('%function%', $lines) as $line) {
+      if (preg_match('%function\s*\(([^)]+)\)%', $line, $match)) {
+        if (preg_match_all('%[a-zA-Z_.$][\w.$]+%', $match[0], $matches)) {
+          foreach ($matches[0] as $match) {
+            $internals[$match] = true;
+          }
+        }
+      }
+    }
+
+    foreach (preg_grep('%=%', $lines) as $line_number => $line) {
+      if (preg_match('%^\s*var\b%', $line)) continue;
+      if (preg_match('%\b([a-zA-Z_.$][\w.$]*(?:\.[a-zA-Z_.$][\w.$]|\["[^"]+"\])*)\s*=(?!=)\s*(function\s*\()?%', $line, $match)) {
+        if ($match[2] || array_key_exists($match[1], $internals)) continue;
+
+        $name = $match[1];
+
+        if (strpos($name, '[') !== false) {
+          $source_lines = Text::chop($this->package->getSource(), $line_number, 0);
+          $source_line = trim($source_lines[$line_number]);
+          preg_match('%\b([a-zA-Z_.$][\w.$]*(?:\.[a-zA-Z_.$][\w.$]|\["[^"]+"\])*)%', $source_line, $source_match);
+          $name = preg_replace('%\["([^"]+)"\]%', '.$1', $source_match[1]);
+        }
+
+        if (strpos($name, 'this.') === 0) {
+          if ($function_name) {
+            continue;
+          }
+          else {
+            $name = substr($name, 5);
+          }
+        }
+
+        $found = true;
+        while ($found) {
+          $found = false;
+          foreach ($internals as $internal_name => $external_name) {
+            if ($internal_name == 'this') continue;
+            if (strpos($name, $internal_name . '.') === 0) {
+              if (!$external_name) continue 2;
+              $last = $name;
+              $name = $external_name . substr($name, strlen($internal_name));
+              if ($last != $name) {
+                $found = true;
+              }
+            }
+          }
+        }
+
+        $variables[] = $name;
+      }
+    }
+
+    return $this->externalized_avariables = $variables;
+  }
+
+  public function getExternalizedInstanceVariableNames($function_name, $parameter_names=array()) {
+    if ($this->externalized_ivariables) {
+      return $this->externalized_ivariables;
+    }
+
+    $ivariables = array();
+
+    $variables = $this->getExternalizedAllVariableNames($function_name, $parameter_names);
+    foreach ($variables as $variable) {
+      if (strpos($variable, 'this.') === 0) {
+        $ivariables[] = substr($variable, 5);
+      }
+    }
+
+    return $this->externalized_ivariables = $ivariables;
+  }
+
+  public function getExternalizedVariableNames($function_name, $parameter_names=array()) {
+    if ($this->externalized_variables) {
+      return $this->externalized_variables;
+    }
+
+    $evariables = array();
+
+    $variables = $this->getExternalizedAllVariableNames($function_name, $parameter_names);
+    foreach ($variables as $variable) {
+      if (strpos($variable, 'this.') !== 0) {
+        $evariables[] = $variable;
+      }
+    }
+
+    return $this->externalized_variables = $evariables;
+  }
+
+  public function getInstanceVariableNames() {
+    if ($this->instance_variables) {
+      return $this->instance_variables;
+    }
+
+    $this->build();
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1], $this->end[0], $this->end[1], true);
+    foreach ($lines as $line) {
+      if (preg_match('%\bthis\.([a-zA-Z0-9._$]+)\s*=\s*(?!function)%', $line, $match)) {
+        $parts = explode('.', $match[1]);
+        if (count($parts) && !in_array(array_pop(array_slice($parts, -1, 1)), array('prototype', 'constructor'))){
+          $this->instance_variables[] = $match[1];
+        }
+      }
+    }
+    return $this->instance_variables;
+  }
+
+  public function getInstanceFunctions($function_name) {
+    $functions = array();
+    $this->build();
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1], $this->end[0], $this->end[1], true);
+    foreach ($lines as $line_number => $line) {
+      if (preg_match('%\bthis\.([a-zA-Z0-9._$]+)\s*=\s*function\b%', $line, $match, PREG_OFFSET_CAPTURE)) {
+        $function = new DojoFunctionDeclare($this->package, $line_number, $match[0][1]);
+        $function->setFunctionName($function_name);
+        $end = $function->build();
+        $functions[] = $function;
+      }
+    }
+    return $functions;
+  }
+
+  public function getReturnComments() {
+    if ($this->return_comments) {
+      return $this->return_comments;
+    }
+
+    $buffer = array();
+    $this->getBlockCommentKeys();
+    $lines = Text::chop($this->package->getSource(), $this->comment_end[0], $this->comment_end[1], $this->end[0], $this->end[1], true);
+    foreach ($lines as $line) {
+      if ($multiline) {
+        list($first, $middle, $last, $data, $multiline) = Text::findComments($line, $multiline);
+        if ($first) {
+          $buffer[] = trim($first);
+        }
+        if ($data) {
+          $multiline = false;
+          if ($buffer) {
+            $this->return_comments[] = implode(' ', array_diff($buffer, array('')));
+            $buffer = array();
+          }
+        }
+      }
+      if (strpos($line, 'return') !== false) {
+        if ($data && $buffer) {
+          $this->return_comments[] = implode(' ', array_diff($buffer, array('')));
+          $buffer = array();
+        }
+        list($first, $middle, $last, $data, $multiline) = Text::findComments($line, $multiline);
+        if ($last) {
+          $buffer[] = $last;
+        }
+      }
+    }
+
+    if ($data && $buffer) {
+      $this->return_comments[] = implode(' ', array_diff($buffer, array('')));
+    }
+
+    $this->return_comment = array_unique($this->return_comments);
+
+    return $this->return_comments;
+  }
+
+  public function getThisInheritanceCalls() {
+    if ($this->this_inheritance_calls) {
+      return $this->this_inheritance_calls;
+    }
+
+    $internalized = $this->getLocalVariableNames();
+
+    $this->build();
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1], $this->end[0], $this->end[1], true);
+    foreach ($lines as $line) {
+      if (preg_match('%\b([a-zA-Z0-9_.$]+)\.(?:apply|call)\s*\(%', $line, $match) && !array_key_exists($match[1], $internalized)) {
+        $this->this_inheritance_calls[] = $match[1];
+      }
+    }
+    return $this->this_inheritance_calls;
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoFunctionCall.php b/util/docscripts/lib/parser/DojoFunctionCall.php
new file mode 100644
index 0000000..3e1a236
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoFunctionCall.php
@@ -0,0 +1,81 @@
+<?php
+
+require_once('DojoParameters.php');
+require_once('DojoBlock.php');
+
+class DojoFunctionCall extends DojoBlock
+{
+  private $object = 'DojoFunctionCall';
+
+  private $name;
+  private $parameters;
+
+  public function __construct($package, $line_number = false, $position = false){
+    parent::__construct($package, $line_number, $position);
+    $this->parameters = new DojoParameters($package);
+  }
+
+  public function __destruct() {
+    parent::__destruct();
+    unset($this->parameters);
+  }
+
+  public function build() {
+    if (!$this->start) {
+      return null; // FIXME: does this ever die?
+        die("DojoFunctionCall->build() used before setting a start position");
+      }
+
+      $code = $this->package->getCode();
+      $this->parameters->setStart($this->start[0], strpos($code[$this->start[0]], '(', $this->start[1]));
+      $end = $this->parameters->build();
+
+      $this->setEnd($end[0], $end[1]);
+      return $end;
+  }
+
+  public function getAssignment() {
+    $this->build();
+    $code = $this->package->getCode();
+    $line = Text::blankOutAt($code[$this->start[0]], $this->start[1]);
+    if (preg_match('%([\w_.$]+)\s*=\s*$%', $line, $match)) {
+      return $match[1];
+    }
+  }
+
+  public function removeCodeFrom($lines){
+    for($i = $this->start[0]; $i <= $this->end[0]; $i++){
+      $line = $lines[$i];
+      if ($i == $this->start[0]) {
+        $lines[$i] = Text::blankOutAt($line, $this->start[1]);
+      }
+      elseif ($i == $this->end[0]) {
+        $lines[$i] = Text::blankOutAt($line, 0, $this->end[1]);
+      }else{
+        $lines[$i] = Text::blankOut($line, $line);
+      }
+    }
+    return $lines;
+  }
+
+  public function getName(){
+    if($this->name){
+    return $this->name;
+  }
+
+    $line = Text::chop($this->package->getCode(), $this->start[0], $this->start[1], $this->start[0]);
+    $line = $line[$this->start[0]];
+    return $this->name = trim(substr($line, 0, strpos($line, '(')));
+  }
+
+  public function getParameter($pos){
+    return $this->parameters->getParameter($pos);
+  }
+
+  public function getParameters(){
+    return $this->parameters->getParameters();
+  }
+
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoFunctionDeclare.php b/util/docscripts/lib/parser/DojoFunctionDeclare.php
new file mode 100644
index 0000000..c525748
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoFunctionDeclare.php
@@ -0,0 +1,464 @@
+<?php
+
+require_once('DojoFunctionBody.php');
+require_once('DojoBlock.php');
+require_once('DojoParameters.php');
+
+class DojoFunctionDeclare extends DojoBlock
+{
+  private $object = 'DojoFunctionDeclare';
+
+  private $parameters;
+  private $function_name;
+  protected $body;
+
+  private $in_executed_function = null;
+  private $anonymous = false;
+  private $prototype = '';
+  private $constructor = false;
+  private $aliases = '';
+
+  public function __construct($package, $line_number = false, $position = false){
+    parent::__construct($package, $line_number, $position);
+    $this->parameters = new DojoParameters($package);
+    $this->body = new DojoFunctionBody($package);
+  }
+
+  public static function parseVariable(&$comment) {
+    $summary = $comment;
+    $tags = array();
+    if (preg_match('%^\s*([a-z\s]+)\]\s*%', $summary, $match)) {
+      $tags = preg_split('%\s+%', $match[1]);
+      $summary = $comment = substr($summary, strlen($match[0]));
+    }
+
+    list($type, $summary) = preg_split('%\s%', $summary, 2);
+    $type = preg_replace('%(^[^a-zA-Z0-9._$]|[^a-zA-Z0-9._$?]$)%', '', $type);
+
+    $options = array();
+    if(!empty($type)){
+      if(strpos($type, '?')){
+        $type = substr($type, 0, strlen($type) - 1);
+        $options['optional'] = true;
+      }
+      if(strpos($type, '...')){
+        $type = substr($type, 0, strlen($type) - 3);
+        $options['repeating'] = true;
+      }
+    }
+
+    return array($tags, $type, $options, $summary);
+  }
+
+  public function destroy() {
+    if (!$this->destroyed) {
+      $this->destroyed = true;
+      $this->parameters->destroy();
+      unset($this->parameters);
+      $this->body->destroy();
+      unset($this->body);
+      if ($this->in_executed_function) {
+        $this->in_executed_function->destroy();
+      }
+      unset($this->in_executed_function);
+    }
+  }
+
+  public function getFunctionName(){
+    return $this->function_name;
+  }
+
+  public function getAliases(){
+    return $this->aliases;
+  }
+
+  public function rebuildAliases($map) {
+    if (is_array($this->aliases)) {
+      foreach ($this->aliases as $i => $alias) {
+        foreach ($map as $internal_name => $external_name) {
+          if (strpos($alias, $internal_name . '.') === 0) {
+            if (!$external_name) continue 2;
+            $alias = $external_name . substr($alias, strlen($internal_name));
+          }
+        }
+        $this->aliases[$i] = $alias;
+      }
+    }
+  }
+
+  public function setFunctionName($function_name){
+    $this->function_name = $function_name;
+  }
+
+  public function setPrototype($function_name){
+    $this->prototype = $function_name;
+  }
+  
+  public function getPrototype(){
+    return $this->prototype;
+  }
+  
+  public function setInstance($function_name){
+    $this->instance = $function_name;
+  }
+  
+  public function getInstance(){
+    return $this->instance;
+  }
+  
+  public function setConstructor($constructor){
+    $this->constructor = $constructor;
+  }
+  
+  public function isConstructor(){
+    return $this->constructor;
+  }
+
+  public function setAnonymous($anonymous) {
+    $this->anonymous = $anonymous;
+  }
+
+  public function isAnonymous(){
+    return $this->anonymous;
+  }
+  
+  public function isThis(){
+    return ($this->prototype || $this->instance);
+  }
+  
+  public function getThis(){
+    return ($this->prototype) ? $this->prototype : $this->instance;
+  }
+
+  public function setExecutedFunction($function) {
+    $this->in_executed_function = $function;
+  }
+  
+  public function getInstanceVariableNames(){
+    return array_unique($this->body->getInstanceVariableNames());
+  }
+
+  public function removeSwallowedMixins(&$mixins) {
+    return $this->body->removeSwallowedMixins($mixins);
+  }
+  
+  public function getReturnComments(){
+    return array_unique($this->body->getReturnComments());
+  }
+  
+  public function getThisInheritanceCalls(){
+    $output = array();
+    $calls = array_unique($this->body->getThisInheritanceCalls());
+
+    if ($this->in_executed_function) {
+      $internalized = $this->in_executed_function->getLocalVariableNames();
+    }
+
+    $parameters = $this->getParameterNames();
+    foreach ($calls as $call) {
+      if (!in_array($call, $parameters)) {
+        if ($internalized) {
+          foreach (array_keys($internalized) as $variable) {
+            if (strpos($call, $variable . '.') === 0) {
+              continue 2;
+            }
+          }
+        }
+        $output[] = $call;
+      }
+    }
+
+    return $output;
+  }
+
+  public function getVariableNames($function_name, $parameter_names=array()){
+    return $this->body->getExternalizedVariableNames($function_name, $parameter_names);
+  }
+
+  public function getFunctionDeclarations(){
+    return $this->body->getExternalizedFunctionDeclarations();
+  }
+
+  public function getObjects(){
+    return $this->body->getExternalizedObjects(false, $this->getParameterNames());
+  }
+
+  public function getLocalVariableNames(){
+    return $this->body->getLocalVariableNames();
+  }
+  
+  public function removeCodeFrom($lines){
+    $this->build();
+
+    return Text::blankOutAtPositions($lines, $this->start[0], $this->start[1], $this->end[0], $this->end[1]);
+  }
+  
+  public function build(){
+    if (!$this->start) {
+      die("DojoFunctionDeclare->build() used before setting a start position");
+    }
+    if($this->end){
+      return $this->end;
+    }
+  
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1]);
+    $line = trim($lines[$this->start[0]]);
+    if(strpos($line, 'function') === 0){
+      $line = substr($line, 8);
+      preg_match('%[^\s]%', $line, $match);
+      if($match[0] != '('){
+          $this->function_name = trim(substr($line, 0, strpos($line, '(')));
+      }
+    }else{
+      $name = trim(substr($line, 0, strpos($line, '=')));
+      $extra = substr($line, strpos($line, '=') + 1);
+      if(preg_match('%^\s+new\s+%', $name, $match) || preg_match('%^\s*new\s+%', $extra, $match)){
+        $this->anonymous = true;
+        $name = str_replace($match[0], '', $name);
+      }
+      if(($pos = strpos($name, '.prototype.')) !== false){
+        $this->prototype = substr($name, 0, $pos);
+        $name = str_replace('.prototype', '', $name);
+      }
+      if(($pos = strpos($name, 'this.')) === 0){
+        $this->instance = $this->getFunctionName();
+        $name = $this->getFunctionName() . "." . preg_replace('%^this\.%', '', $name);
+      }
+
+      if (!$this->isAnonymous()) {
+        $full_lines = Text::chop($this->package->getCode(), $this->start[0], 0);
+        $full_line = substr($full_lines[$this->start[0]], 0, $this->start[1]);
+        if (preg_match('%(?:[a-zA-Z0-9._$]+\s*=\s*)+$%', $full_line, $matches)) {
+          $aliases = preg_split('%\s*=\s*%', $matches[0]);
+          foreach ($aliases as $alias) {
+            $alias = trim($alias);
+            if ($alias) {
+              if (strpos($alias, 'this.') === 0) {
+                $alias = $this->getFunctionName() . "." . preg_replace('%^this\.%', '', $alias);
+              }
+              $this->aliases[] = $alias;
+            }
+          }
+        }
+      }
+
+      if (strpos($name, '[') !== false) {
+        $source_lines = Text::chop($this->package->getSource(), $this->start[0], $this->start[1]);
+        $source_line = trim($source_lines[$this->start[0]]);
+        preg_match('%^\s*([a-zA-Z_.$][\w.$]*(?:\.[a-zA-Z_.$][\w.$]|\["[^"]+"\])*)\s*=\s*function%', $source_line, $match);
+        $name = preg_replace('%\["([^"]+)"\]%', '.$1', $match[1]);
+      }
+      $this->function_name = $name;
+    }
+    
+    $this->parameters->setStart($this->start[0], strpos($lines[$this->start[0]], '('));
+    $end = $this->parameters->build();
+    
+    $lines = Text::chop($this->package->getCode(), $end[0], $end[1]);
+    foreach($lines as $line_number => $line){
+      if(($pos = strpos($line, '{')) !== false){
+        $this->body->setStart($line_number, $pos);
+        return $this->end = $this->body->build();
+      }
+    }
+  }
+  
+  public function getParameter($pos){
+    return $this->parameters->getParameter($pos);
+  }
+  
+  public function getParameters(){
+    return $this->parameters->getParameters();
+  }
+
+  public function getParameterNames(){
+    $names = array();
+    $parameters = $this->getParameters();
+    foreach ($parameters as $parameter) {
+      if($parameter->isA(DojoVariable)){
+        $names[] = $parameter->getVariable();
+      }
+    }
+    return $names;
+  }
+  
+  public function addBlockCommentKey($key){
+    $this->body->addBlockCommentKey($key);
+  }
+
+  public function addBlockCommentKeySet($key){
+    $this->body->addBlockCommentKeySet($key);
+  }
+
+  public function getBlockCommentKeys(){
+    return $this->body->getBlockCommentKeys();
+  }
+  
+  public function getBlockComment($key){
+    return $this->body->getBlockComment($key);
+  }
+  
+  public function getSource(){
+    return $this->body->getSource();
+  }
+  
+  public function getInstanceFunctions($function_name){
+    return $this->body->getInstanceFunctions($function_name);
+  }
+  
+  public function rollOut(&$output){
+    // Basically, any this.variables in here never impact this object, they apply to the "this" function
+    $masquerading_as_function = $function_name = $this->getFunctionName();
+    if (substr($masquerading_as_function, 0, 7) == 'window.'){
+      $masquerading_as_function = $function_name = substr($masquerading_as_function, 7);
+    }
+    $check_keys = array('summary','description','returns','tags','exceptions');
+
+    if (!empty($output[$function_name]['aliases'])) {
+      unset($output[$function_name]['aliases']); // This is implemented, it aliases nothing.
+    }
+
+    if ($this->isThis()) {
+      $masquerading_as_function = $this->getThis();
+    }
+
+    $output[$function_name]['type'] = 'Function';
+    if (!empty($output[$masquerading_as_function])) {
+      $output[$masquerading_as_function]['type'] = 'Function';
+    }
+
+    if ($aliases = $this->getAliases()) {
+      foreach ($aliases as $alias) {
+        if (empty($output[$alias])) {
+          $output[$alias]['aliases'] = $function_name;
+        }
+      }
+    }
+
+    $parameters = $this->getParameters();
+    foreach ($parameters as $parameter) {
+      if($parameter->isA(DojoVariable)){
+        $parameter_name = $parameter->getVariable();
+        $parameter_type = $parameter->getType();
+        if(strpos($parameter_type, '?')){
+          $parameter_type = substr($parameter_type, 0, strlen($parameter_type) - 1);
+          $output[$function_name]['parameters'][$parameter_name]['optional'] = true;
+        }
+        if(strpos($parameter_type, '...')){
+          $parameter_type = substr($parameter_type, 0, strlen($parameter_type) - 3);
+          $output[$function_name]['parameters'][$parameter_name]['repeating'] = true;
+        }
+        if (empty($output[$function_name]['parameters'][$parameter_name]['type']) || $parameter_type) {
+          $output[$function_name]['parameters'][$parameter_name]['type'] = $parameter_type;
+        }
+
+        $this->addBlockCommentKey($parameter->getVariable());
+      }
+    }
+
+    if ($this->isAnonymous()) {
+      $output[$function_name]['initialized'] = true;
+
+      $declarations = $this->body->getExternalizedFunctionDeclarations($function_name);
+      foreach ($declarations as $declaration) {
+        $declaration->rollout($output);
+      }
+
+      $variables = $this->body->getExternalizedInstanceVariableNames($function_name, $this->getParameterNames());
+      foreach($variables as $variable) {
+        $output[$function_name . '.' . $variable]['instance'] = $function_name;
+      }
+
+      $variables = $this->body->getExternalizedVariableNames($function_name, $this->getParameterNames());
+      foreach($variables as $variable) {
+        list($first,) = explode('.', $variable, 2);
+        if (!is_array($output[$function_name]['parameters']) || !array_key_exists($first, $output[$function_name]['parameters'])) {
+          if (empty($output[$variable])) {
+            $output[$variable] = array();
+          }
+        }
+      }
+    }
+
+    foreach($check_keys as $ck){
+      $this->addBlockCommentKey($ck);
+    }
+    $this->addBlockCommentKeySet('example');
+    $check_keys[] = 'example';
+
+    $output[$function_name]['source'] = $this->getSource();
+
+    $all_variables = array();
+    $instance_variables = $this->getInstanceVariableNames();
+    foreach($instance_variables as $instance_variable){
+      $this->addBlockCommentKey($instance_variable);
+      $all_variables[] = $instance_variable;
+
+      $full_variable_name = "{$masquerading_as_function}.{$instance_variable}";
+      $output[$full_variable_name]['instance'] = $masquerading_as_function;
+    }
+
+    $instance_functions = $this->getInstanceFunctions($function_name);
+    foreach($instance_functions as $instance_function){
+      $instance_function->rollOut($output);
+      $output[$instance_function->getFunctionName()]['instance'] = $function_name;
+    }
+
+    $comment_keys = $this->getBlockCommentKeys();
+    foreach($comment_keys as $key){
+      if ($key == 'returns') {
+        $output[$function_name]['return_summary'] = $this->getBlockComment($key);
+      }
+      elseif (in_array($key, $check_keys)) {
+        $output[$function_name][$key] = $this->getBlockComment($key);
+      }
+      if (in_array($key, $all_variables) && $comment = $this->getBlockComment($key)) {
+         list($type, $comment) = preg_split('%\s+%', $comment, 2);
+        $type = preg_replace('%(^[^a-zA-Z0-9._$]|[^a-zA-Z0-9._$?]$)%', '', $type);
+        if($type){
+          $output[$function_name . '.' . $key]['type'] = $type;
+        }
+        $output[$function_name . '.' . $key]['summary'] = $comment;
+      }
+      if (!empty($output[$function_name]['parameters']) && array_key_exists($key, $output[$function_name]['parameters']) && $comment = $this->getBlockComment($key)) {
+        list($tags, $parameter_type, $options, $summary) = DojoFunctionDeclare::parseVariable($comment);
+
+        // If type is specified in the parameters, and it doesn't
+        // match the first word in this comment block, assume that
+        // this first word doesn't represent its type
+        if (!empty($output[$function_name]['parameters'][$key]['type']) && $parameter_type != $output[$function_name]['parameters'][$key]['type']) {
+          $summary = $comment;
+          $parameter_type = $output[$function_name]['parameters'][$key]['type'];
+        }
+        $output[$function_name]['parameters'][$key] = array_merge($output[$function_name]['parameters'][$key], $options); 
+        $output[$function_name]['parameters'][$key]['type'] = $parameter_type;
+        $output[$function_name]['parameters'][$key]['summary'] = htmlentities($summary);
+      }
+    }
+
+    $returns = $this->getReturnComments();
+    if (count($returns)){
+      $output[$function_name]['returns'] = implode('|', $returns);
+    }
+
+    if ($output[$function_name]['example']) {
+      $output[$function_name]['examples'] = $output[$function_name]['example'];
+      unset($output[$function_name]['example']);
+    }
+
+    if($calls = $this->getThisInheritanceCalls()){
+      foreach ($calls as $call) {
+        $output[$function_name]['chains']['call'][] = $call;
+      }
+    }
+    
+    if($this->getPrototype()){
+      $output[$function_name]['prototype'] = $this->getPrototype();
+    }
+    if($this->getInstance()){
+      $output[$function_name]['instance'] = $this->getInstance();
+    }
+  }
+}
+
+?>
diff --git a/util/docscripts/lib/parser/DojoNull.php b/util/docscripts/lib/parser/DojoNull.php
new file mode 100644
index 0000000..68d3f36
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoNull.php
@@ -0,0 +1,18 @@
+<?php
+
+class DojoNull
+{
+	private $object = 'DojoNull';
+  
+	private $value = '';
+  
+	public function __construct($value){
+    		$this->value = $value;
+  	}
+  
+	public function getValue(){
+    		return $this->value;
+ 	}
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoObject.php b/util/docscripts/lib/parser/DojoObject.php
new file mode 100644
index 0000000..bbefb8f
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoObject.php
@@ -0,0 +1,209 @@
+<?php
+
+require_once('DojoBlock.php');
+require_once('DojoFunctionDeclare.php');
+require_once('DojoFunctionBody.php');
+require_once('Text.php');
+
+class DojoObject extends DojoBlock
+{
+  private $object = 'DojoObject';
+
+  private $values = array();
+  public $declarations = array();
+  private $name = '';
+  private $body;
+  private $extra_block_values = array();
+  private $anonymous = false;
+
+  public function __construct($package, $line_number = false, $position = false){
+    parent::__construct($package, $line_number, $position);
+    $this->body = new DojoFunctionBody($package, $line_number, $position);
+  }
+
+  public function __destruct() {
+    parent::__destruct();
+    unset($this->values);
+    unset($this->declarations);
+    unset($this->body);
+    unset($this->extra_block_values);
+    unset($this->anonymous);
+  }
+
+  public function setName($name){
+    $this->name = $name;
+  }
+
+  public function getName(){
+    return $this->name;
+  }
+  
+  public function setAnonymous($anonymous){
+    $this->anonymous = true;
+  }
+  
+  public function isAnonymous(){
+    return $this->anonymous;
+  }
+  
+  public function getBlockCommentKeys(){
+    return $this->body->getBlockCommentKeys();
+  }
+  
+  public function getBlockComment($key){
+    return $this->body->getBlockComment($key);
+  }
+  
+  public function addBlockCommentKey($key){
+    return $this->body->addBlockCommentKey($key);
+  }
+
+  public function addBlockCommentKeySet($key){
+    return $this->body->addBlockCOmmentKeySet($key);
+  }
+
+  public function build(){
+    if(!$this->start){
+      die("DojoObject->build() used before setting a start position");
+    }
+  
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1], false, false, true);
+    $end = array($this->start[0], $this->start[1]);
+  
+    do {
+      $lines = Text::chop($this->package->getCode(), $end[0], $end[1], false, false, true);
+      foreach ($lines as $line_number => $line) {
+        if (preg_match('%^\s*}%', $line)) {
+          break;
+        }
+        if (preg_match('%^(\s*)([a-zA-Z0-9_$]+|"\s+")\s*:%', $line, $match)) {
+          if ($end[0] != $this->start[0] && $end[1] != $this->start[1]) {
+            if ($end[0]+1 > $line_number) {
+              continue;
+            }
+            $between_lines = Text::chop($this->package->getSource(), $end[0]+1, 0, $line_number, strlen($match[1]), true);
+            foreach ($between_lines as $between_line) {
+              $this->body->addBlockCommentLine($between_line);
+            }
+          }
+          $end = array($line_number, strlen($match[0]));
+          if ($match[2]{0} == '"' || $match[2]{0} == "'") {
+            $key = trim(implode(Text::chop($this->package->getSource(), $line_number, strpos($line, '"') + 1, $line_number, strlen($match[0]) - 3, false)));
+          }else{
+            $key = $match[2];
+          }
+          break;
+        }
+      }
+      if (!$key) {
+        $end = Text::findTermination($lines, '}');
+      }else{
+        $parameter = new DojoParameter($this->package, $end[0], $end[1], '}');
+        $end = $parameter->build();
+        $this->values[$key][] = $parameter;
+      }
+    }
+    while ($lines[$end[0]]{$end[1]} != '}');
+    
+    $this->setEnd($end[0], $end[1]);
+    return $end;
+  }
+  
+  public function getKeys(){
+    if (!$this->values) {
+      $this->build();
+    }
+    return array_keys($this->values);
+  }
+  
+  public function getValues(){
+    if(!$this->values){
+      $this->build();
+    }
+    return $this->values;
+  }
+  
+  public function rollOut(&$output, $item_type = 'Object'){
+    $package_name = $this->package->getPackageName();
+    $name = $this->getName();
+    $variables = array();
+    $check_keys = array('summary','description');
+
+    foreach($this->getValues() as $key => $values){
+      foreach ($values as $value) {
+        if($value->isA(DojoFunctionDeclare)){
+          $function = $value->getFunction();
+          $this->declarations[] = $function;
+          if(!$function->isConstructor()){
+            $function->setFunctionName("{$name}.{$key}");
+            $function->rollOut($output);
+          }
+        }elseif ($value->isA(DojoObject)){
+          $object = $value->getObject();
+          $object->setName("{$name}.{$key}");
+          $object->rollOut($output);
+        }else{
+          $this->addBlockCommentKey($key);
+          $full_variable_name = "{$name}.{$key}";
+          if (empty($output[$full_variable_name])) {
+            $output[$full_variable_name] = array();
+          }
+        $variables[] = $key;
+        }
+      }
+    }
+
+    foreach($check_keys as $ck){
+      $this->addBlockCommentKey($ck);
+    }
+    $this->addBlockCommentKeySet("example");
+
+    $output[$name]['type'] = $item_type;
+    if ($comment = $this->getBlockComment('summary')) {
+      $output[$name]['summary'] = $comment;
+    }
+    if ($comment = $this->getBlockComment('description')) {
+      $output[$name]['description'] = $comment;
+    }
+    $examples = $this->getBlockComment('example');
+    if ($examples && count($examples)) {
+      $output[$name]['examples'] = $examples;
+    }
+
+    foreach($variables as $key){
+      $full_variable_name = "{$name}.{$key}";
+      if($comment = $this->getBlockComment($key)){
+        list($tags, $parameter_type, $options, $summary) = DojoFunctionDeclare::parseVariable($comment);
+        if (!empty($tags)) {
+          $output[$full_variable_name]['tags'] = $tags;
+        }
+        if (!empty($parameter_type)) {
+          $output[$full_variable_name]['type'] = $parameter_type;
+        }
+        $output[$full_variable_name]['summary'] = $summary;
+      }
+    }
+
+    foreach($check_keys as $ck){
+      if(!$this->isAnonymous() && $comment = $this->getBlockComment($ck)){
+        $output[$name][$ck] = $comment; 
+      }
+    }
+  }
+  
+  public function removeCodeFrom($lines){
+    for($i = $this->start[0]; $i <= $this->end[0]; $i++){
+      $line = $lines[$i];
+      if($i == $this->start[0]){
+        $lines[$i] = Text::blankOutAt($line, $this->start[1]);
+      }elseif ($i == $this->end[0]){
+        $lines[$i] = Text::blankOutAt($line, 0, $this->end[1]);
+      }else{
+        $lines[$i] = Text::blankOut($line, $line);
+      } 
+    }
+    return $lines;
+  }
+}
+
+?>
diff --git a/util/docscripts/lib/parser/DojoPackage.php b/util/docscripts/lib/parser/DojoPackage.php
new file mode 100644
index 0000000..cb5c79a
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoPackage.php
@@ -0,0 +1,515 @@
+<?php
+
+require_once('Text.php');
+require_once('DojoFunctionCall.php');
+require_once('DojoExecutedFunction.php');
+
+class DojoPackage
+{
+  private $dojo;
+  protected $file; // The file reference (including dir) to the file;
+  private $code; // The source - comments
+  protected $source;
+  protected $declarations = array(); // Builds an array of functions declarations by name, with meta
+  protected $executions = array();
+  protected $calls = array(); // Builds an array of calls
+  protected $objects = array(); // Builds an array of objects
+  protected $aliases = array(); // Builds a key/value list of aliases in this file
+
+  public function __construct(Dojo $dojo, $file){
+    $this->dojo = $dojo;
+    $this->setFile($file);
+  }
+
+  public function destroy() {
+    array_walk($this->declarations, 'destroy_all');
+    unset($this->declarations);
+    array_walk($this->executions, 'destroy_all');
+    unset($this->executions);
+    array_walk($this->calls, 'destroy_all');
+    unset($this->calls);
+    array_walk($this->objects, 'destroy_all');
+    unset($this->objects);
+    array_walk($this->aliases, 'destroy_all');
+    unset($this->aliases);
+  }
+  
+  public function getFile(){
+    return $this->file;
+  }
+  
+  public function setFile($file){
+    $this->file = $file;
+  }
+
+  public function getFunctionDeclarations(){
+    $lines = $this->getCode();
+    $end = array(0, 0);
+
+    $matches = preg_grep('%function%', $lines);
+    $last_line = 0;
+    foreach($matches as $line_number => $line){
+      if($line_number < $last_line){
+        continue;
+      }
+
+      if(preg_match('%(\bfunction\s+[a-zA-Z0-9_.$]+\b\s*\(|\b[a-zA-Z_.$][\w.$]*(?:\.[a-zA-Z_.$][\w.$]|\["[^"]+"\])*\s*=\s*(new\s*)?function\s*\()%', $line, $match)) {
+        $declaration = new DojoFunctionDeclare($this);
+        $declaration->setStart($line_number, strpos($line, $match[0]));
+        $end = $declaration->build();
+        $last_line = $end[0];
+        $this->declarations[$declaration->getFunctionName()][] = $declaration;
+      }
+    }
+    
+    return $this->declarations;
+  }
+
+  /**
+   * Searches the file for the format: (function(){})();
+   */
+  public function getExecutedFunctions(){
+    if ($this->executions) {
+      return $this->executions;
+    }
+
+    $lines = $this->getCode();
+    
+    $matches = preg_grep('%function%', $lines);
+    $last_line = 0;
+    foreach ($matches as $line_number => $line) {
+      if ($line_number < $last_line) {
+        continue;
+      }
+
+      if (preg_match('%(?:([a-zA-Z_.$][\w.$]*)\s*=\s*)?(?:new\s*)?\(\s*function\s*\([^)]*\)\s*{%', $line, $match)) {
+        $execution = new DojoExecutedFunction($this);
+        $execution->setAnonymous(true);
+        if ($match[1]) {
+          $execution->setFunctionName($match[1]);
+        }
+        $execution->setStart($line_number, strpos($line, $match[0]));
+        $end = $execution->build();
+        if ($end) {
+          $last_line = $end[0];
+          $callee = $lines[$end[0]];
+          $this->executions[] = $execution;
+        }
+      }
+    }
+    
+    return $this->executions;
+  }
+  
+  /**
+   * Use this to find everywhere in the code a function is called.
+   *
+   * @param unknown_type $name
+   */
+  public function getFunctionCalls($name){
+    if ($this->calls[$name]) {
+      return $this->calls[$name];
+    }
+
+    $this->calls[$name] = array();
+    $lines = $this->getCode();
+    $lines = preg_grep('%\b' . preg_quote($name) . '\s*\(%', $lines);
+    foreach ($lines as $line_number => $line) {
+      $position = strpos($line, $name);
+      if ($line_number < $last_line_number || ($line_number == $last_line_number && $position < $last_position)) {
+        continue;
+      }
+      $call = new DojoFunctionCall($this, $line_number, $position);
+      list($last_line_number, $last_position) = $call->build();
+      $this->calls[$name][] = $call;
+    }
+    return $this->calls[$name];
+  }
+  
+  public function removeCodeFrom($lines){
+    $keys = array_keys($lines);
+    $first = array_shift($keys);
+    $last = array_pop($keys);
+    for($i = $first; $i <= $last; $i++) {
+      $line = $lines[$i];
+      if (preg_match('%function\s*\([^)]*\)\s*{%', $line, $match, PREG_OFFSET_CAPTURE)) {
+        $declaration = new DojoFunctionDeclare($this, $i, $match[0][1]);
+        list($i, ) = $declaration->build();
+        $lines = $declaration->removeCodeFrom($lines);
+      }
+      elseif (preg_match('%^.*(with|switch)\s*\([^(]*\)\s*{%', $line, $match)) {
+        $with_lines = Text::chop($lines, $i, strlen($match[0]) - 1, null, null, true);
+        list($end_line, $end_pos) = Text::findTermination($with_lines, '}', '{}()[]');
+        for ($j = $i; $j <= $end_line; $j++) {
+          $line = $lines[$j];
+          if ($j == $i) {
+            $lines[$j] = Text::blankOutAt($line, strlen($match[0]) - 1);
+          }
+          elseif ($j == $end_line) {
+            $lines[$j] = Text::blankOutAt($line, 0, $end_pos);
+          }
+          else {
+            $lines[$j] = Text::blankOut($line, $line);
+          }
+        }
+      }
+    }
+    
+    return $lines;
+  }
+  
+  public function getAliases(){
+    if($this->aliases){
+      return $this->aliases;
+    }
+
+    return $this->aliases;
+  }
+
+  public function getObjects(){
+    if ($this->objects) {
+      return $this->objects;
+    }
+    
+    $lines = $this->getCode();
+    foreach ($lines as $line_number => $line) {
+      if ($line_number < $end_line_number) {
+        continue;
+      }
+      if (preg_match('%\b([a-zA-Z0-9_.$]+)\s*=\s*{%', $line, $match, PREG_OFFSET_CAPTURE)) {
+        $object = new DojoObject($this, $line_number, $match[0][1] + strlen($match[0][0]) - 1);
+        $object->setName($match[1][0]);
+        list($end_line_number, $end_position) = $object->build();
+        $this->objects[] = $object;
+      }
+    }
+    return $this->objects;
+  }
+  
+  public function getSource(){
+    if ($this->source) {
+      return $this->source;
+    }
+    $lines = preg_split("%\r?\n%", file_get_contents($this->dojo->getDir() . $this->file));
+    $lines[] = '';
+    $in_comment = false;
+    foreach ($lines as $line_number => $line) {
+      $pos = 0;
+      $found = true;
+      while ($found) {
+        $found = false;
+        if (!$in_comment) {
+          if (preg_match('%/\*={5,}%', $line, $match, PREG_OFFSET_CAPTURE, $pos)) {
+            $line = $lines[$line_number] = Text::blankOut($match[0][0], $line);
+            $found = true;
+            $in_comment = true;
+            $pos = $match[0][1] + strlen($match[0][0]);
+          }
+        }
+        elseif (preg_match('%={5,}\*/%', $line, $match, PREG_OFFSET_CAPTURE, $pos)) {
+          $line = $lines[$line_number] = Text::blankOut($match[0][0], $line);
+          $found = true;
+          $in_comment = false;
+          $pos = $match[0][1] + strlen($match[0][0]);
+        }
+      }
+    }
+    return $this->source = $lines;
+  }
+  
+  /**
+   * Removes comments and strings, preserving layout
+   */
+  public function getCode(){
+    if ($this->code) {
+      return $this->code;
+    }
+    
+    $lines = $this->getSource();
+    
+    $in_comment = false;
+    foreach ($lines as $line_number => $line) {
+      //print "$line_number $line\n";
+      if ($in_comment !== false) {
+        if (preg_match('%^.*\*/%U', $line, $match)) {
+          $line = Text::blankOut($match[0], $line);
+          $in_comment = false;
+        }
+        else {
+          $line = Text::blankOut($line, $line);
+        }
+      }
+      
+      $position = 0;
+      $in_single_string = false;
+      $in_double_string = false;
+      $in_regex = false;
+
+      for ($i = 0; $i < 100; $i++) {
+        $matches = array();
+
+        if ($in_comment === false && $in_regex === false && $in_single_string === false && $in_double_string === false) {
+          // Match the start of a line, the word return or case, or a character in: =([{,|&;:?
+          // Followed by zero or more spaces
+          // Followed by a forward slash
+          // Not followed by another forward slash
+          if (preg_match('%(?:^|\breturn\b|[=([{,|&;:?])\s*/(?!/)%', $line, $match, PREG_OFFSET_CAPTURE, $position)) {
+            $matches[$match[0][1] + strlen($match[0][0]) - 1] = '/';
+          }
+          if (preg_match('%(?:^|\b(?:case|return)\b|[=([{,|&;:?+])\s*(["\'])%', $line, $match, PREG_OFFSET_CAPTURE, $position)) {
+            $matches[$match[0][1] + strlen($match[0][0]) - 1] = $match[1][0];
+          }
+          if (($pos = strpos($line, '//', $position)) !== false) {
+            $matches[$pos] = '//';
+          }
+          if (($pos = strpos($line, '/*', $position)) !== false) {
+            $matches[$pos] = '/*';
+          }
+        }
+        elseif ($in_regex !== false) {
+          // A / not preceeded by a / or \
+          // Followed by 0 or more spaces
+          // Followed by one of the characters: img.)]},|&;: or end of line
+          if (preg_match('%(?<![/\\\\])/\s*([img.)\]},|&;:]|$)%', $line, $match, PREG_OFFSET_CAPTURE, $position)) {
+            //print_r($match);
+            $matches[$match[0][1]] = '/';
+          }
+        }
+        elseif ($in_single_string !== false || $in_double_string !== false) {
+          for ($j = 0; $j < 999; $j++) {
+            $q_pos = strpos($line, ($in_single_string) ? "'" : '"', $position);
+
+            $bs_pos = strpos($line, '\\\\', $position);
+            $m_pos = strpos($line, '\\' . ($in_single_string) ? "'" : '"', $position);
+
+            if ($bs_pos !== false && $bs_pos < $q_pos) {
+              $position = $bs_pos + 2;
+            }
+            if ($m_pos !== false && $m_pos < $q_pos) {
+              $position = max($position, $m_post + 2);
+            }
+
+            if ($bs_pos === false && $m_pos === false) {
+              break;
+            }
+          }
+          $test = substr($line, $position);
+          if (preg_match('%(' . ($in_single_string ? "'" : '"') . ')\s*([+.)\]},|&;:?]|==|$)%', $line, $match, PREG_OFFSET_CAPTURE, $position)) {
+            $matches[$match[0][1]] = $match[1][0];
+          }
+        }
+        elseif ($in_comment !== false) {
+          if (($pos = strpos($line, '*/', $position)) !== false) {
+            $matches[$pos] = '*/';
+          }
+        }
+        
+        if (!$matches) {
+          break;
+        }
+        
+        ksort($matches);
+        foreach ($matches as $position => $match) {
+          if ($in_comment === false && $in_regex === false && $in_single_string === false && $in_double_string === false) {
+            if ($match == '"') {
+              $in_double_string = $position;
+              break;
+            }
+            elseif ($match == "'") {
+              $in_single_string = $position;
+              break;
+            }
+            elseif ($match == '/') {
+              $in_regex = $position;
+              break;
+            }
+            elseif ($match == '//') {
+              $line = Text::blankOutAt($line, $position);
+              break;
+            }
+            elseif ($match == '/*') {
+              $in_comment = $position;
+              ++$position;
+              break;
+            }
+          }
+          elseif ($in_double_string !== false && $match == '"') {
+            $line = Text::blankOutAt($line, $in_double_string + 1, $position - 1);
+            $in_double_string = false;
+          }
+          elseif ($in_single_string !== false && $match == "'") {
+            $line = Text::blankOutAt($line, $in_single_string + 1, $position - 1);
+            $in_single_string = false;
+          }
+          elseif ($in_regex !== false && $match == '/') {
+            $line = Text::blankOutAt($line, $in_regex + 1, $position - 1);
+            $in_regex = false;
+          }
+          elseif ($in_comment !== false && $match == '*/') {
+            $line = Text::blankOutAt($line, $in_comment + 2, $position - 1);
+            $in_comment = false;
+          }
+        }
+        ++$position;
+      }
+      
+      if($i == 500){
+        die("\$i should not reach 500: $line");
+      }
+      
+      if ($in_comment !== false && !empty($line)) {
+        $line = Text::blankOutAt($line, $in_comment);
+        $in_comment = 0;
+      }
+      
+      //print "$line_number $line\n";
+      $lines[$line_number] = $line;
+    }
+
+    return $this->code = $lines;
+  }
+
+  /** 
+   * After all calls are done, return what's left
+   */
+  public function getExternalVariables(){
+    $lines = $this->getCode();
+
+    foreach ($this->objects as $pobject) {
+      foreach ($pobject->declarations as $declaration) {
+        $lines = Text::blankOutAtPositions($lines, $declaration->start[0], $declaration->start[1], $declaration->end[0], $declaration->end[1]);
+      }
+    }
+    foreach($this->declarations as $declarations){
+      foreach ($declarations as $declaration) {
+        $lines = Text::blankOutAtPositions($lines, $declaration->start[0], $declaration->start[1], $declaration->end[0], $declaration->end[1]);
+      }
+    }
+    foreach($this->calls as $call_name => $calls){
+      foreach($calls as $call){
+        $lines = Text::blankOutAtPositions($lines, $call->start[0], $call->start[1], $call->end[0], $call->end[1]);
+      }
+    }
+    foreach($this->executions as $execution){
+      $lines = Text::blankOutAtPositions($lines, $execution->start[0], $execution->start[1], $execution->end[0], $execution->end[1]);
+    }
+
+    $variables = array();
+    foreach (preg_grep('%=%', $lines) as $line_number => $line) {
+      if (preg_match('%\b([a-zA-Z_.$][\w.$]*)\s*=(?!=)\s*(function\s*\()?%', $line, $match)) {
+        $variables[] = $match[1];
+      }
+    }
+
+    return $variables;
+  }
+  
+  /**
+   * Remove items from the passed objects if they are inside of existing calls or declarations
+   */
+  public function removeSwallowed(&$objects){
+    $swallowed = array();
+    foreach ($objects as $i => $object) {
+      foreach ($this->objects as $pobject) {
+        if (($object->start[0] > $pobject->start[0] || ($object->start[0] == $pobject->start[0] && $object->start[1] > $pobject->start[1]))
+            && ($object->end[0] < $pobject->end[0] || ($object->end[0] == $pobject->end[0] && $object->end[1] < $pobject->end[1]))) {
+          if ($objects[$i]) {
+            $swallowed[] = $objects[$i];
+          }
+          unset($objects[$i]);
+        }        
+        foreach ($pobject->declarations as $declaration) {
+          if (($object->start[0] > $declaration->start[0] || ($object->start[0] == $declaration->start[0] && $object->start[1] > $declaration->start[1]))
+              && ($object->end[0] < $declaration->end[0] || ($object->end[0] == $declaration->end[0] && $object->end[1] < $declaration->end[1]))) {
+            if ($objects[$i]) {
+              $swallowed[] = $objects[$i];
+            }
+            unset($objects[$i]);
+          }
+        }
+      }
+      foreach($this->declarations as $declarations){
+        foreach ($declarations as $declaration) {
+          if(($object->start[0] > $declaration->start[0] || ($object->start[0] == $declaration->start[0] && $object->start[1] > $declaration->start[1]))
+              && ($object->end[0] < $declaration->end[0] || ($object->end[0] == $declaration->end[0] && $object->end[1] < $declaration->end[1]))) {
+            if ($objects[$i]) {
+              $swallowed[] = $objects[$i];
+            }
+            unset($objects[$i]);
+          }
+        }
+      }
+      foreach($this->calls as $call_name => $calls){
+        foreach($calls as $call){
+          if(($object->start[0] > $call->start[0] || ($object->start[0] == $call->start[0] && $object->start[1] > $call->start[1]))
+              && ($object->end[0] < $call->end[0] || ($object->end[0] == $call->end[0] && $object->end[1] < $call->end[1]))) {
+            if ($objects[$i]) {
+              $swallowed[] = $objects[$i];
+            }
+            unset($objects[$i]);
+          }
+        }
+      }
+      foreach($this->executions as $execution){
+        if(($object->start[0] > $execution->start[0] || ($object->start[0] == $execution->start[0] && $object->start[1] > $execution->start[1]))
+              && ($object->end[0] < $execution->end[0] || ($object->end[0] == $execution->end[0] && $object->end[1] < $execution->end[1]))) {
+            if ($objects[$i]) {
+              $swallowed[] = $objects[$i];
+            }
+            unset($objects[$i]);
+        }
+      }
+    }
+
+    return $swallowed;
+  }
+
+  public function getPackageName(){
+    $name = '';
+
+    if (!function_exists($this->dojo->namespace . '_package_name')) {
+      if (file_exists('modules/' . $this->dojo->namespace . '.module')){
+        include_once('modules/' . $this->dojo->namespace . '.module');
+      }
+      else {
+        $parts = explode('/', $this->file);
+        $file_parts = explode('.', array_pop($parts));
+        if (in_array('tests', $parts)) return;
+        array_pop($file_parts);
+        array_push($parts, implode('.', $file_parts));
+        array_unshift($parts, $this->dojo->namespace);
+        $name = implode('.', $parts);
+      }
+    }
+
+    if (function_exists($this->dojo->namespace . '_package_name')) {
+      $name = call_user_func($this->dojo->namespace . '_package_name', $this->dojo->namespace, $this->file);
+    }
+
+    if($name) return $name;
+    return 'null';
+  }
+
+  public function getResourceName(){
+    $name = '';
+
+    if (!function_exists($this->dojo->namespace . '_resource_name')) {
+      if (file_exists('modules/' . $this->dojo->namespace . '.module')) {
+        include_once('modules/' . $this->dojo->namespace . '.module');
+      }
+      else {
+        $name = $this->file;
+      }
+    }
+
+    if (function_exists($this->dojo->namespace . '_resource_name')) {
+      $name = call_user_func($this->dojo->namespace . '_resource_name', $this->dojo->namespace, $this->file);
+    }
+
+    if($name) return $name;
+    return 'null';
+  }
+
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoParameter.php b/util/docscripts/lib/parser/DojoParameter.php
new file mode 100644
index 0000000..64731a7
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoParameter.php
@@ -0,0 +1,166 @@
+<?php
+
+require_once('DojoString.php');
+require_once('DojoNull.php');
+require_once('DojoBoolean.php');
+require_once('DojoVariable.php');
+require_once('DojoObject.php');
+require_once('DojoFunctionDeclare.php');
+require_once('DojoBlock.php');
+
+class DojoParameter extends DojoBlock
+{
+  private $object = 'DojoParameter';
+
+  private $terminator = ')';
+
+  private $parameter_value;
+  private $parameter_type;
+
+  public function __construct($package, $line_number = false, $position = false, $terminator = ')'){
+    parent::__construct($package, $line_number, $position);
+    $this->terminator = $terminator;
+  }
+
+  public function __destruct() {
+    parent::__destruct();
+    unset($this->parameter_value);
+    unset($this->parameter_type);
+  }
+
+  public function exists(){
+    return !empty($this->parameter_value);
+  }
+
+  public function isA($class){
+    if (!$this->parameter_value) {
+      $this->getValue();
+    }
+    if ($this->parameter_value instanceof $class) {
+      return true;
+    }
+    return false;
+  }
+
+  public function build(){
+    if (!$this->start) {
+      debug_print_backtrace();
+      die("DojoParameter->build() used before setting a start position");
+    }
+
+    $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1], false, false, true);
+    list($line_number, $position) = Text::findTermination($lines, ',' . $this->terminator, '(){}[]');
+    $this->setEnd($line_number, $position);
+    return $this->end;
+  }
+
+  public function getString(){
+    if ($this->isA(DojoString)) {
+      return $this->parameter_value->getValue();
+    }
+    return '';
+  }
+
+  public function getObject(){
+    if ($this->isA(DojoObject)) {
+      return $this->parameter_value;
+    }
+    return new DojoObject($this->package);
+  }
+
+  public function getFunction(){
+    if ($this->isA(DojoFunctionDeclare)) {
+      $this->parameter_value->build();
+      return $this->parameter_value;
+    }
+    return new DojoFunctionDeclare($this->package);
+  }
+
+  public function getArray(){
+    if ($this->isA(DojoArray)) {
+      $this->parameter_value->build();
+      return $this->parameter_value;
+    }
+    require_once('DojoArray.php'); // Chase condition
+    return new DojoArray($this->package);
+  }
+
+  public function getVariable(){
+    if ($this->isA(DojoVariable)) {
+      return $this->parameter_value->getValue();
+    }
+    return new DojoVariable('');
+  }
+
+  public function setVariable($value){
+    if ($this->isA(DojoVariable)) {
+      $this->parameter_value->setValue($value);
+    }
+  }
+
+  public function getValue(){
+    if ($this->parameter_value) {
+      return $this->parameter_value;
+    }
+
+    $lines = Text::chop($this->package->getSource(), $this->start[0], $this->start[1], $this->end[0], $this->end[1], true);
+    $parameter_value = Text::trim(implode("\n", $lines));
+
+    if ($parameter_value{0} == '"' || $parameter_value{0} == "'") {
+      $this->parameter_value = new DojoString($parameter_value);
+    }
+    elseif ($parameter_value{0} == '{') {
+      foreach ($lines as $line_number => $line) {
+        if (($position = strpos($line, '{')) !== false) {
+          $this->parameter_value = new DojoObject($this->package, $line_number, $position);
+          break;
+        }
+      }
+    }
+    elseif (strpos($parameter_value, 'function') === 0) {
+      foreach ($lines as $line_number => $line) {
+        if (($position = strpos($line, 'function')) !== false) {
+          $this->parameter_value = new DojoFunctionDeclare($this->package, $line_number, $position);
+          break;
+        }
+      }
+    }
+    elseif ($parameter_value{0} == '[') {
+      foreach ($lines as $line_number => $line) {
+        if (($position = strpos($line, '[')) !== false) {
+          require_once('DojoArray.php'); // Chase condition
+          $this->parameter_value = new DojoArray($this->package, $line_number, $position);
+          break;
+        }
+      }
+    }
+    elseif ($parameter_value == 'null' || $parameter_value == 'undefined') {
+        $this->parameter_value = new DojoNull($parameter_value);
+    }
+    elseif ($parameter_value == 'true' || $parameter_value == 'false') {
+      $this->parameter_value = new DojoBoolean($parameter_value);
+    }
+    elseif (!empty($parameter_value)) {
+      $this->parameter_value = new DojoVariable($parameter_value);
+    }
+
+    return $this->parameter_value;
+  }
+  
+  public function getType(){
+    if ($this->parameter_type) {
+      return $this->parameter_type;
+    }
+
+    $type = array();
+    $lines = Text::chop($this->package->getSource(), $this->start[0], $this->start[1], $this->end[0], $this->end[1], true);
+    foreach ($lines as $line) {
+      list($first, $middle, $last, $data, $multiline) = Text::findComments($line, $multiline);
+      $type = array_merge($type, array($first, $middle, $last));
+    }
+
+    return $this->parameter_type = implode(' ', array_diff($type, array('')));
+  }
+}
+  
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoParameters.php b/util/docscripts/lib/parser/DojoParameters.php
new file mode 100644
index 0000000..ebf4521
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoParameters.php
@@ -0,0 +1,60 @@
+<?php
+
+require_once('DojoParameter.php');
+require_once('DojoBlock.php');
+
+class DojoParameters extends DojoBlock
+{
+  private $object = 'DojoParameters';
+
+  private $parameters = array();
+  protected $terminator = ')';
+
+  public function __construct($package, $line_number = false, $position = false){
+    parent::__construct($package, $line_number, $position);
+  }
+
+  public function destroy() {
+    array_walk($this->parameters, 'destroy_all');
+    unset($this->parameters);
+  }
+
+  public function build(){
+    if (!$this->start) {
+      die("DojoParameters->build() used before setting a start position");
+    }
+
+    $code = $this->package->getCode();
+    $end = array($this->start[0], $this->start[1]);
+
+    do {
+      $parameter = new DojoParameter($this->package, $end[0], $end[1], $this->terminator);
+      $end = $parameter->build();
+
+      $this->parameters[] = $parameter;
+    } while ($code[$end[0]]{$end[1]} != $this->terminator);
+
+    $this->setEnd($end[0], $end[1]);
+    return $end;
+  }
+
+  public function getParameter($pos){
+    if ($this->parameters && !empty($this->parameters[$pos])) {
+      return $this->parameters[$pos];
+    }
+    else {
+      return new DojoParameter($this->package);
+    }
+  }
+
+  public function getParameters(){
+    if ($this->parameters) {
+      return $this->parameters;
+    }
+    else{
+      return array();
+    }
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoString.php b/util/docscripts/lib/parser/DojoString.php
new file mode 100644
index 0000000..cc0bfc1
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoString.php
@@ -0,0 +1,18 @@
+<?php
+
+class DojoString
+{
+	private $object = 'DojoString';
+  
+	private $value = '';
+  
+	public function __construct($string){
+    		$this->value = preg_replace('%(^[\'"]|["\']$)%', '', $string);
+  	}
+  
+  	public function getValue(){
+    		return $this->value;
+  	}
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/DojoVariable.php b/util/docscripts/lib/parser/DojoVariable.php
new file mode 100644
index 0000000..6492c39
--- /dev/null
+++ b/util/docscripts/lib/parser/DojoVariable.php
@@ -0,0 +1,21 @@
+<?php
+
+class DojoVariable
+{
+  private $value = '';
+
+  public function __construct($value){
+    $this->value = $value;  
+  }
+
+  public function setValue($value) {
+    $this->value = $value;
+  }
+
+  public function getValue(){
+    return $this->value;
+  }
+
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser/README b/util/docscripts/lib/parser/README
new file mode 100755
index 0000000..4424b9b
--- /dev/null
+++ b/util/docscripts/lib/parser/README
@@ -0,0 +1,2 @@
+Even though it's written for Dojo, these files are a general-purpose solution for analyzing JavaScript source code.
+It doesn't create a tree, but instead provides an API for looking through source code.
diff --git a/util/docscripts/lib/parser/Text.php b/util/docscripts/lib/parser/Text.php
new file mode 100644
index 0000000..b5439bf
--- /dev/null
+++ b/util/docscripts/lib/parser/Text.php
@@ -0,0 +1,213 @@
+<?php
+
+class Text
+{
+  public static $variable = '\b[a-zA-Z_.$][\w.$]*';
+  public static $namespace = '\b[a-zA-Z_.$][\w.$]*(?:\.[a-zA-Z_.$][\w.$]*|\["[^"]+"\])*';
+
+  /**
+   * Blanks out a portion of a string with whitespace
+   * 
+   *  @param $to_blank Portion of the string to be removed
+   *  @param $string Overall string to remove it from
+   */
+  public static function blankOut($to_blank, $string) {
+    $length = strlen($to_blank);
+    if (!$length) {
+      return $string;
+    }
+
+    $blanks = array_fill(0, $length, ' ');
+    return preg_replace('%' . preg_quote($to_blank, '%') . '%', implode($blanks), $string, 1);
+  }
+
+  /**
+   * Makes sure a variable is formatted namespace.namespace.etc
+   *
+   * @param shell
+   *    Called shell because it might be missing some data
+   */
+  public static function normalizeVariableName($shell, $source, $start){
+    if (strpos($shell, '[') !== false) {
+      $source_line = array_shift(Text::chop($source, $start[0], $start[1], $start[0] + 1));
+      preg_match('%^\s*([a-zA-Z_.$][\w.$]*(?:\.[a-zA-Z_.$][\w.$]|\["[^"]+"\])*)\s*=\s*function%', $source_line, $match);
+      $shell = preg_replace('%\["([^"]+)"\]%', '.$1', $match[1]);
+    }
+    return $shell;
+  }
+
+  public static function getNextPosition($array, $line_position_pair) {
+    list($line_number, $position) = $line_position_pair;
+    ++$position;
+    if ($position >= strlen($array[$line_number])) {
+      ++$line_number;
+      $position = 0;
+      while (!strlen($array[$line_number])) {
+        ++$line_number;
+      }
+    }
+    return array($line_number, $position);
+  }
+
+  public static function blankOutAtPositions($to_blank, $start_line, $start_pos, $end_line = -1, $end_pos = -1) {
+    foreach ($to_blank as $line_number => $line) {
+      if ($line_number == $start_line) {
+        $to_blank[$line_number] = Text::blankOutAt($line, $start_pos);
+      }
+      if ($line_number > $start_line) {
+        if ($end_line == -1 || $line_number < $end_line) {
+          $to_blank[$line_number] = Text::blankOutAt($line, 0);
+        }
+        elseif ($line_number == $end_line) {
+          $to_blank[$line_number] = Text::blankOutAt($line, 0, $end_pos);
+        }
+      }
+    }
+    return $to_blank;
+  }
+
+  public static function blankOutAt($to_blank, $start, $end = -1) {
+    if ($end == -1) {
+      $end = strlen($to_blank) - 1;
+    }
+    $length = $end - $start + 1;
+    if (!$length) {
+      return $to_blank;
+    }
+    if ($length < 0) {
+      throw new Exception("Length is less than 0");
+    }
+    $blanks = array_fill(0, $length, ' ');
+    return substr($to_blank, 0, $start) . implode($blanks) .  substr($to_blank, $end + 1);
+  }
+
+  public static function trim($string) {
+    return trim(preg_replace('%(^\s*/\*.*\*/\s*?|\s*?/\*.*\*/\s*$|^\s*//.*\n\s*?|\s*?//.*$)%U', '', $string));
+  }
+
+  public static function chop($array, $start_line, $start_position, $end_line = false, $end_position = false, $exclusive = false) {
+    if (!is_numeric($end_line)) {
+      $end_line = end(array_keys($array));
+    }
+    if (!is_numeric($end_position)) {
+      $end_position = strlen($array[$end_line]) - 1;
+      if ($end_position < 0) {
+        $end_position = 0;
+      }
+    }
+
+    $lines = array_slice($array, $start_line, $end_line - $start_line + 1, true);
+      if ($start_position > 0) {
+        $lines[$start_line] = Text::blankOutAt($lines[$start_line], 0, $start_position - 1);
+      }
+      $lines[$end_line] = Text::blankOutAt($lines[$end_line], $end_position + 1, strlen($lines[$end_line]));
+      if ($exclusive) {
+        if ($lines[$start_line]{$start_position}) {
+          $lines[$start_line]{$start_position} = ' ';
+        }
+        if ($lines[$end_line]{$end_position}) {
+          $lines[$end_line]{$end_position} = ' ';
+        }
+      }
+
+      return $lines;
+  }
+
+  /**
+   * Always starts at the beginning. If you want a character to be ignored, it shouldn't be passed (see chop and blankOutAt)
+   */
+  public static function findTermination($source_array, $termination_characters, $enclosing_characters = '') {
+    $characters = array();
+    $terminators = array();
+    foreach (self::toArray($termination_characters) as $character) { 
+      $terminators[$character] = true;
+    }
+    foreach (self::toArray($enclosing_characters) as $index => $character) {
+      $characters[$character] = ($index % 2) ? -1 : 1;
+    }
+    $all_characters = array_merge(array_keys($terminators), array_keys($characters));
+
+    $balance = 0;
+
+    foreach ($source_array as $line_number => $line) {
+      $line = self::toArray($line);
+      foreach (array_intersect($line, $all_characters) as $position => $character) {
+        if (!$balance && $terminators[$character]) {
+          return array($line_number, $position);
+        }
+        $balance += $characters[$character];
+      }
+    }
+
+    return array($line_number, $position);
+  }
+
+  public static function toArray($string) {
+    return array_slice(preg_split('%%', $string), 1, -1);
+  }
+
+  /**
+   * Splits a comment line up
+   *
+   * @returns Array(whitespace, comment data, non-comment data, comment data, has non-comment-data, comment continues on next line)
+   */
+  public static function findComments($line, $started = false) {
+    if (empty($line) && !$started) {
+      return array(false, false, false, false, false);
+    }
+
+    $first = array();
+    $middle = array();
+    $last = array();
+    $data = false;
+    $multiline = false;
+
+    if ($started) {
+      // If we're already in a (multi-line) comment, look to close it up
+      if (($pos = strpos($line, '*/')) !== false) {
+        $first[] = trim(substr($line, 0, $pos));
+        $line = substr($line, $pos + 2);
+      }
+      else {
+        // We didn't find a terminator, we're still in a multi-line comment
+        $multiline = true;
+      }
+    }
+
+    $single_line = false; // Denotes that we're in a single-line comment.
+    if (!$multiline) {
+      // Split by //, /*, and */ while ignoring any surrounding whitespace
+      $parts = preg_split('%(\s*(?://|/\*|\*/)\s*)%', $line, -1, PREG_SPLIT_DELIM_CAPTURE);
+      foreach ($parts as $part) {
+        if (!($trimmed = trim($part))) continue;
+        if ($multiline && $trimmed == '*/') {
+          $multiline = false; // Multi-line ends!
+        }
+        elseif ($single_line || $multiline) { // If we're within a comment
+          if (!$data) {
+            $first[] = $part;
+          }
+          else { // If we've found any non-comment data, we start logging this as "after" the data
+            $last[] = $part;
+          }
+        }
+        elseif ($trimmed == '//') {
+          $single_line = true;
+        }
+        elseif ($trimmed == '/*') {
+          $multiline = true;
+        }
+        else {
+          $data = true;
+          $middle = array_merge($middle, $last);
+          $last = array();
+        }
+      }
+    }
+
+    return array(trim(implode('', $first)), trim(implode('', $middle)), trim(implode('', $last)), $data, $multiline);
+  }
+
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/Destructable.php b/util/docscripts/lib/parser2/Destructable.php
new file mode 100644
index 0000000..7ef391a
--- /dev/null
+++ b/util/docscripts/lib/parser2/Destructable.php
@@ -0,0 +1,21 @@
+<?php
+
+abstract class Destructable {
+  protected function mem_flush() {
+    foreach (func_get_args() as $key) {
+      if ($this->$key) {
+        if (is_object($this->$key)) {
+          $this->$key->__destruct();
+        }
+        elseif (is_array($this->$key)) {
+          foreach ($this->$key as $loc => $value) {
+            if (is_object($value)) {
+              $value->__destruct();
+            }
+          }
+        }
+        unset($this->$key);
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/Dojo.php b/util/docscripts/lib/parser2/Dojo.php
new file mode 100644
index 0000000..280c48a
--- /dev/null
+++ b/util/docscripts/lib/parser2/Dojo.php
@@ -0,0 +1,206 @@
+<?php
+
+require_once('JavaScriptStatements.php');
+require_once('JavaScriptFunction.php');
+require_once('DojoCommentBlock.php');
+
+class Dojo {
+  public static $block_keys = array('summary', 'description', 'returns', 'tags', 'this', 'exceptions');
+
+  public static function property_text(&$text, &$on) {
+    if (preg_match('%^\s*([a-z\s]+)\]\s*%', $text, $match)) {
+      $on['tags'] = preg_split('%\s+%', $match[1]);
+      $text = trim(substr($text, strlen($match[0])));
+    }
+
+    if (preg_match('%\s%', $text)) {
+      list($type, $summary) = preg_split('%\s+%', $text, 2);
+    }
+    else {
+      $type = $text;
+      $summary = '';
+    }
+
+    if(strpos($type, '?')){
+      $type = str_replace('?', '', $type);
+      $on['optional'] = true;
+    }
+    if(strpos($type, '...')){
+      $type = str_replace('...', '', $type);
+      $on['repeating'] = true;
+    }
+
+    $type = trim($type);
+    $summary = trim($summary);
+
+    if (!empty($on['type']) && $type != $on['type']) {
+      $summary = trim("$type $summary");
+    }
+    elseif (!empty($type) && (empty($on['type']) || $type != 'Object')) {
+      $on['type'] = $type;
+    }
+
+    if (!empty($summary)) {
+      $on['summary'] = self::format_summary($summary);
+    }
+  }
+
+  private static function roll_out_object($object, $name, &$output, $new_keys=array(), $on_prototype=NULL) {
+    $new_keys = array_unique(array_merge($new_keys, array_keys($object->values())));
+    foreach ($object->values() as $key => $values) {
+      foreach ($values as $value) {
+        self::roll_out($value, "$name.$key", FALSE, $output, $new_keys);
+        if ($on_prototype) {
+          $output["$name.$key"]['prototype'] = $on_prototype;
+        }
+      }
+    }
+    self::roll_out_comment_block($object, $name, $output, $new_keys);
+  }
+
+  private static function set_type($object, &$on) {
+    if (empty($on['type']) && ($type = $object->type()) && $type != 'null') {
+      if ($type == 'variable') {
+        $on['alias'] = $object->value();
+      }
+      elseif (empty($on['inferred_type']) || $type != 'Object') {
+        $on['inferred_type'] = $type;
+      }
+    }
+  }
+
+  public static function roll_out_comment_block($object, $name, &$output, $new_keys=array()) {
+    $comments = new DojoCommentBlock($object->comments(), self::$block_keys, array('example'));
+    foreach ($new_keys as $key) {
+      $comments->add_key($key);
+    }
+    self::roll_out_comments($comments, $name, self::$block_keys, $new_keys, $output);
+  }
+
+  private static function roll_out_comments($comments, $name, $keys, $new_keys, &$output) {
+    foreach ($comments->all() as $key => $text) {
+      if ($key == 'example') {
+        $output[$name]['examples'] = $text;
+      }
+      elseif ($key == 'tags') {
+        $output[$name]['tags'] = preg_split('%\s+%', trim($text));
+      }
+      elseif ($key == 'returns') {
+        $output[$name]['return_summary'] = $text;
+      }
+      elseif (in_array($key, $keys) && !empty($text)) {
+        $output[$name][$key] = ($key == 'summary') ? self::format_summary($text) : $text;
+      }
+      elseif (in_array($key, $new_keys)) {
+        self::property_text($text, $output[$name . '.' . $key]);
+      }
+      elseif (!empty($output[$name]['parameters']) && array_key_exists($key, $output[$name]['parameters'])) {
+        self::property_text($text, $output[$name]['parameters'][$key]);
+      }
+    }
+  }
+
+  public static function roll_out($object, $name, $into_function, &$output, $new_keys=array(), $is_prototype=FALSE) {
+    if (empty($output[$name])) {
+      $output[$name] = array();
+    }
+
+    self::set_type($object, $output[$name]);
+
+    $keys = self::$block_keys;
+    $this_keys = array();
+
+    if ($object instanceof JavaScriptObject || $object instanceof JavaScriptFunction) {
+      if ($object instanceof JavaScriptObject) {
+        self::roll_out_object($object, $name, $output, $keys, $is_prototype ? $name : NULL);
+      }
+      elseif ($object instanceof JavaScriptFunction) {
+        $comments = new DojoCommentBlock($object->comments(), $keys, array('example'));
+        $parent = $this_comment = $comments->get('this');
+        if (!$parent) {
+          $parent = $name;
+        }
+        elseif ($parent == 'namespace') {
+          $parent = implode('.', array_slice(explode('.', $name), 0, -1));
+        }
+        $body = new JavaScriptStatements($object->body());
+
+        foreach ($body->assignments(FALSE, $into_function) as $variable) {
+          if (substr($variable->name(), 0, 5) == 'this.') {
+            $variable_name = substr($variable->name(), 5);
+            $comments->add_key($variable_name);
+            $this_keys[] = $variable_name;
+            $full_variable_name = $parent . '.' . $variable_name;
+
+            if (!$this_comment) {
+              $found = FALSE;
+              if (!empty($output[$name]['prototype'])) {
+                $found = TRUE;
+                $full_variable_name = $output[$name]['prototype'] . '.' . $variable_name;
+                $output[$full_variable_name]['prototype'] = $output[$name]['prototype'];
+              }
+              if (!empty($output[$name]['instance'])) {
+                $found = TRUE;
+                $full_variable_name = $output[$name]['instance'] . '.' . $variable_name;
+                $output[$full_variable_name]['instance'] = $output[$name]['instance'];
+              }
+              if (!$found) {
+                $output[$full_variable_name]['instance'] = $name;
+              }
+            }
+
+            if ($variable_type = $variable->type()) {
+              if ($variable_type == 'Function') {
+                self::roll_out($variable->value(), $full_variable_name, FALSE, $output);
+              }
+              $output[$full_variable_name]['inferred_type'] = $variable_type;
+            }
+          }
+        }
+
+        $blocks = $comments->all();
+        foreach ($this_keys as $key) {
+          if ($blocks[$key]) {
+            self::property_text($blocks[$key], $output[$parent . '.' . $key]);
+          }
+        }
+
+        // TODO: Look for mixins on the same sort of values
+        foreach ($object->parameters() as $parameter) {
+          $comments->add_key($parameter->name);
+
+          $output[$name]['parameters'][$parameter->name]['name'] = $parameter->name;
+
+          $type = '';
+          if (!empty($parameter->comments)) {
+            $type = preg_replace('%(^/\*\s*|\s*\*/$)%', '', $parameter->comments[0]);
+          }
+
+          self::property_text($type, $output[$name]['parameters'][$parameter->name]);
+        }
+
+        if ($body->function_calls(TRUE, 'dojo.deprecated')) {
+          $output[$name]['deprecated'] = TRUE;
+        }
+
+        $returns = empty($output[$name]['returns']) ? array() : explode('|', $output[$name]['returns']);
+        foreach ($body->prefix('return') as $return) {
+          if (($pos = strrpos($return->line, '//')) !== false) {
+            $returns = array_merge($returns, preg_split('%\s*\|\s*%', trim(substr($return->line, $pos + 2))));
+          }
+        }
+        if (!empty($returns)) {
+          $output[$name]['returns'] = implode('|', array_unique($returns));
+        }
+
+        self::roll_out_comments($comments, $name, $keys, array(), $output);
+      }
+    }
+
+    return $new_keys;
+  }
+
+  private static function format_summary($summary) {
+    return preg_replace('%`([^`]+)`%', '<code>$1</code>', htmlentities($summary));
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/DojoCommentBlock.php b/util/docscripts/lib/parser2/DojoCommentBlock.php
new file mode 100644
index 0000000..8fc3ad9
--- /dev/null
+++ b/util/docscripts/lib/parser2/DojoCommentBlock.php
@@ -0,0 +1,98 @@
+<?php
+
+class DojoCommentBlock {
+  public static $prefix = '';
+  public static $suffix = ':';
+
+  protected $blocks;
+
+  protected $comments;
+  protected $keys = array();
+  protected $key_sets = array();
+
+  public function __construct($comments, $keys, $key_sets = array()) {
+    if (!is_array($comments)) {
+      throw new Exception('DojoCommentBlock expects an array of comments to be passed');
+    }
+    $this->comments = $comments;
+    $this->keys = $keys;
+    $this->key_sets = $key_sets;
+  }
+
+  public function __destruct() {
+    unset($this->blocks);
+    unset($this->comments);
+    unset($this->keys);
+    unset($this->key_sets);
+  }
+
+  public function add_key($key) {
+    unset($this->blocks);
+    $this->keys[] = $key;
+  }
+
+  public function return_type() {
+    // TODO: Add return type(s)
+  }
+
+  public function get($key) {
+    $comments = $this->all();
+    return $comments[$key] ? $comments[$key] : '';
+  }
+
+  public function all() {
+    if (isset($this->blocks)) {
+      return $this->blocks;
+    }
+
+    $expression = '%^' . self::$prefix . '(' . implode('|', array_merge($this->keys, $this->key_sets)) . ')' . self::$suffix . '\W*%';
+
+    $blocks = array();
+    $buffer = array();
+    $key = NULL;
+    foreach ($this->comments as $comment) {
+      if (empty($comment) && $key) {
+        $this->swallow($blocks, $key, $buffer);
+      }
+
+      $comment = preg_replace('%(^//\s*|^/\*\s*|\s*\*/$)%', '', $comment);
+      foreach (explode("\n", $comment) as $line) {
+        if (preg_match($expression, $line, $match)) {
+          if ($key && !empty($buffer)) {
+            $this->swallow($blocks, $key, $buffer);
+          }
+          $line = substr($line, strlen($match[0]));
+          $key = $match[1];
+        }
+
+        $line = trim($line);
+        if ($line && $line{0} == '|') {
+          $line = substr($line, 1);
+        }
+
+        if ($key) {
+          $buffer[] = $line;
+        }
+      }
+    }
+
+    if ($key && !empty($buffer)) {
+      $this->swallow($blocks, $key, $buffer);
+    }
+
+    return ($this->blocks = $blocks);
+  }
+
+  private function swallow(&$blocks, &$key, &$lines) {
+    $lines = preg_replace('%(^\n+|\n+$)%', '', implode("\n", $lines));
+    if (in_array($key, $this->keys)) {
+      $blocks[$key] = $lines;
+    }
+    else {
+      $blocks[$key][] = $lines;
+    }
+
+    $key = NULL;
+    $lines = array();
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptArray.php b/util/docscripts/lib/parser2/JavaScriptArray.php
new file mode 100644
index 0000000..dd58d03
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptArray.php
@@ -0,0 +1,98 @@
+<?php
+
+require_once('JavaScriptStatements.php');
+require_once('JavaScriptVariable.php');
+require_once('JavaScriptLiteral.php');
+require_once('JavaScriptString.php');
+require_once('JavaScriptNumber.php');
+require_once('JavaScriptRegExp.php');
+require_once('JavaScriptFunction.php');
+require_once('JavaScriptObject.php');
+require_once('Destructable.php');
+
+class JavaScriptArray extends Destructable {
+  protected $args;
+  protected $resolved_args;
+  public $length;
+
+  public function __construct($args) {
+    $this->length = count($args);
+    $this->args = $args;
+  }
+
+  public function __destruct() {
+    $this->mem_flush('args', 'resolved_args');
+  }
+
+  public function type() {
+    return 'Array';
+  }
+
+  public function get($position) {
+    $args = $this->all();
+    return $args[$position];
+  }
+
+  private function getType($position, $type) {
+    $args = $this->all();
+	if ($args[$position] && get_class($args[$position]) == $type) {
+      return $args[$position];
+    }
+  }
+
+  public function getVariable($position, $is_global = FALSE) {
+    if ($variable = $this->getType($position, 'JavaScriptVariable')) {
+      return (!$is_global || $variable->is_global()) ? $variable->value() : NULL;
+    }
+    if ($variable = $this->getType($position, 'JavaScriptLiteral')) {
+      return $is_global ? NULL : $variable->value();
+    }
+  }
+
+  public function getString($position) {
+    if ($string = $this->getType($position, 'JavaScriptString')) {
+      return $string->value();
+    }
+  }
+
+  public function getNumber($position) {
+    if ($number = $this->getType($position, 'JavaScriptNumber')) {
+      return $number->value();
+    }
+  }
+
+  public function getRegExp($position) {
+    if ($regexp = $this->getType($position, 'JavaScriptRegExp')) {
+      return $regexp->value();
+    }
+  }
+
+  public function getFunction($position) {
+    return $this->getType($position, 'JavaScriptFunction');
+  }
+
+  public function getArray($position) {
+    return $this->getType($position, 'JavaScriptArray');
+  }
+
+  public function getObject($position) {
+    return $this->getType($position, 'JavaScriptObject');
+  }
+
+  public function all() {
+    if (isset($this->resolved_args)) {
+      return $this->resolved_args;
+    }
+
+    $args = array();
+    foreach ($this->args as $arg) {
+      if (is_object($arg)) {
+        $args[] = $arg->convert();
+      }
+    }
+
+    return ($this->resolved_args = $args);
+  }
+}
+
+?>
diff --git a/util/docscripts/lib/parser2/JavaScriptAssignment.php b/util/docscripts/lib/parser2/JavaScriptAssignment.php
new file mode 100644
index 0000000..2dbc28c
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptAssignment.php
@@ -0,0 +1,56 @@
+<?php
+
+require_once('JavaScriptVariable.php');
+
+class JavaScriptAssignment extends JavaScriptVariable {
+  protected $value;
+  protected $resolved_value;
+
+  public function __construct($variable, $value) {
+    parent::__construct($variable);
+    $this->value = $value;
+  }
+
+  public function __destruct() {
+    $this->mem_flush('value', 'resolved_value');
+  }
+
+  public function name() {
+    return parent::value();
+  }
+
+  public function names() {
+    return parent::values();
+  }
+
+  public function value() {
+    if (!isset($this->resolved_value)) {
+      $value = $this->value;
+      if (is_array($value) && count($value) == 1) {
+        $value = $value[0];
+      }
+      $this->resolved_value = $value->convert();
+    }
+    return $this->resolved_value;
+  }
+
+  public function types() {
+    $value = $this->value();
+    if (is_array($value)) {
+      $mapped = array();
+      foreach ($value as $item) {
+        $mapped[] = $item->type();
+      }
+      return $mapped;
+    }
+    return array($value->type());
+  }
+
+  public function type() {
+    $types = array_diff($this->types(), array('variable'));
+    if (count($types) == 1) {
+      return array_pop($types);
+    }
+    return '';
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptFunction.php b/util/docscripts/lib/parser2/JavaScriptFunction.php
new file mode 100644
index 0000000..e3bf9d5
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptFunction.php
@@ -0,0 +1,42 @@
+<?php
+
+require_once('Destructable.php');
+
+class JavaScriptFunction extends Destructable {
+  protected $statement;
+
+  public function __construct($statement, $instantiated = FALSE) {
+    $this->statement = $statement;
+  }
+
+  public function __destruct() {
+    $this->mem_flush('statement');
+  }
+
+  public function type() {
+    return 'Function';
+  }
+
+  public function comments() {
+    return $this->statement->comments;
+  }
+
+  public function body() {
+    return $this->statement->second;
+  }
+
+  public function parameters() {
+    $parameters = array();
+    foreach ($this->statement->first as $parameter) {
+      $parameters[] = (object)array(
+        'name' => $parameter->value,
+        'comments' => $parameter->comments
+      );
+    }
+    return $parameters;
+  }
+
+  public function __toString() {
+    return '(' . $this->type() . ')';
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptFunctionCall.php b/util/docscripts/lib/parser2/JavaScriptFunctionCall.php
new file mode 100644
index 0000000..dc3335f
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptFunctionCall.php
@@ -0,0 +1,74 @@
+<?php
+
+require_once('JavaScriptStatements.php');
+require_once('JavaScriptArray.php');
+require_once('Destructable.php');
+
+class JavaScriptFunctionCall extends Destructable {
+  protected $call;
+  protected $args;
+
+  protected $assignment;
+  protected $resolved_args;
+  protected $name;
+  protected $global_scope;
+
+  public function __construct($call, $args, $instantiated = FALSE) {
+    $this->call = $call;
+    $this->args = $args;
+  }
+
+  public function __destruct() {
+    $this->mem_flush('call', 'args', 'assignment', 'resolved_args', 'name', 'global_scope');
+  }
+
+  private function resolve() {
+    if (!$this->call->is_lookup()) {
+      $this->global_scope = FALSE;
+      $this->name = NULL;
+    }
+    else {
+      list ($this->global_scope, $this->name) = $this->call->resolve();
+    }
+  }
+
+  public function name() {
+    if (!isset($this->name)) {
+      $this->resolve();
+    }
+    return $this->name;
+  }
+
+  public function setAssignment($assignment) {
+    $this->assignment = $assignment;
+  }
+
+  public function assignment() {
+    if ($this->assignment) {
+      if ($this->assignment->is_lookup()) {
+        list(, $assignment) = $this->assignment->resolve();
+        return $assignment;
+      }
+    }
+    return NULL;
+  }
+
+  public function is_global () {
+    if (!isset($this->global_scope)) {
+      $this->resolve();
+    }
+    return !!$this->global_scope;
+  }
+
+  public function type() {
+    // TODO: Try to resolve return type
+    return 'Object';
+  }
+
+  public function arguments() {
+    if (isset($this->resolved_args)) {
+      return $this->resolved_args;
+    }
+    return ($this->resolved_args = new JavaScriptArray($this->args));
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptLanguage.php b/util/docscripts/lib/parser2/JavaScriptLanguage.php
new file mode 100644
index 0000000..c8e7b08
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptLanguage.php
@@ -0,0 +1,265 @@
+<?php
+
+class JavaScriptLanguage {
+  public static function new_token($type, $value, $extras) {
+    return array('type' => $type, 'value' => $value, 'line_number' => $extras['line_number'], 'char_pos' => $extras['char_pos'], 'line' => $extras['exploded_lines'][$extras['line_number'] - 1]);
+  }
+
+  public static function tokenize($lines) {
+    $lines = str_replace("\r", '', $lines);
+    $tokens = array();
+
+    $exploded_lines = explode("\n", $lines);
+    $line_number = 1;
+    $char_pos = 0;
+    $extras = array('exploded_lines', 'line_number', 'char_pos');
+
+    $positions = array();
+    for ($i = 0; $i < strlen($lines); $i++) {
+      $char = $lines{$i};
+
+      $positions[$i] = $line_number . '|' . ++$char_pos;
+
+      if ($char == "\n") {
+        ++$line_number;
+        $char_pos = 0;
+      }
+    }
+
+    for ($i = 0; $i < strlen($lines); $i++) {
+      $char = $lines{$i};
+
+      list($line_number, $char_pos) = explode('|', $positions[$i], 2);
+
+      if (count($tokens)) {
+        $pop = &$tokens[count($tokens) - 1];
+      }
+      else {
+        $pop = array('type' => '', 'value' => '');
+      }
+
+      $last_expression = array('type' => '', 'value' => '');
+      // The last expression might be behind a comment
+      // This is needed for stuff like regex
+      for ($j = count($tokens) - 1; $j >= 0; $j--) {
+        if ($tokens[$j]['type'] != 'comment') {
+          $last_expression = $tokens[$j];
+          break;
+        }
+      }
+
+      if ($char == ' ' || $char == "\t") {
+        $pop['terminated'] = true;
+        continue;
+      }
+
+      switch($char){
+      case '-':
+      case '+':
+      case '<':
+      case '>':
+      case '=':
+      case '.':
+      case '|':
+      case '&':
+      case ':':
+        if ($char == '-' && !$pop['terminated'] && $pop['type'] == 'operator' && $pop['value'] == '-') {
+          $pop['value'] = '--';
+          break;
+        }
+        elseif ($char == '+' && !$pop['terminated'] && $pop['type'] == 'operator' && $pop['value'] == '+') {
+          $pop['value'] = '++';
+          break;
+        }
+        elseif ($char == '<' && !$pop['terminated'] && $pop['type'] == 'operator' && $pop['value'] == '<') {
+          $pop['value'] = '<<';
+          break;
+        }
+        elseif ($char == '>' && !$pop['terminated'] && $pop['type'] == 'operator' && ($pop['value'] == '>' || $pop['value'] == '>>')) {
+          $pop['value'] .= '>';
+          break;
+        }
+        elseif ($char == '=' && !$pop['terminated'] && $pop['type'] == 'operator' && in_array($pop['value'], array('+', '-', '*', '/', '%', '<<', '>>', '>>>', '&', '^', '|', '!', '!=', '=', '==', '>', '<'))) {
+          $pop['value'] .= $char;
+          break;
+        }
+        elseif ($char == '.' && !$pop['terminated'] && $pop['type'] == 'number') {
+          $pop['value'] .= $char;
+          break;
+        }
+        elseif ($char == '|' && !$pop['terminated'] && $pop['type'] == 'operator' && $pop['value'] == '|') {
+          $pop['value'] = '||';
+          break;
+        }
+        elseif ($char == '&' && !$pop['terminated'] && $pop['type'] == 'operator' && $pop['value'] == '&') {
+          $pop['value'] = '&&';
+          break;
+        }
+        elseif ($case == ':' && !$pop['terminated'] && $pop['type'] == 'operator' && $pop['value'] == '?') {
+          $pop['value'] = '?:';
+          break;
+        }
+      case "\n":
+      case ';':
+      case ',':
+      case '(':
+      case ')':
+      case '[':
+      case ']':
+      case '{':
+      case '}':
+      case '!':
+      case '?':
+      case '*':
+      case '%':
+      case '~':
+      case '^':
+        $tokens[] = self::new_token('operator', $char, compact($extras));
+        break;
+      case "'":
+      case '"':
+        $string = '';
+        $last = '';
+        for(++$i; $i < strlen($lines); $i++){
+          $letter = $lines{$i};
+          if ($last == '\\') {
+            $string .= $letter;
+            if ($letter == '\\') {
+              // Double backslash
+              $last = '';
+              continue;
+            }
+          }
+          elseif ($letter != $char) {
+            $string .= $letter;
+          }
+          else {
+            break;
+          }
+          $last = $letter;
+        }
+        $tokens[] = self::new_token('string', str_replace("\\$char", $char, $string), compact($extras));
+        break;
+      case '/':
+        // Single-line comment, multi-line comment, regular expression, or just a division sign
+        $content = $char;
+        $instruction = NULL;
+        $single = FALSE;
+        $multi = FALSE;
+        $escaped = FALSE;
+        $last = '';
+        $length = strlen($lines);
+        for ($j = $i + 1; $j <= $length; $j++) {
+          $letter = ($j == $length) ? "\n" : $lines{$j};
+          if ($single) {
+            if ($letter == "\n") {
+              $instruction = 'comment';
+              $i = $j - 1;
+              break;
+            }
+          }
+          elseif ($multi) {
+            if (strlen($content) > 2 && $letter == '/' && $last == '*') {
+              $content .= $letter;
+              $instruction = 'comment';
+              $i = $j;
+              break;
+            }
+          }
+          elseif ($last === '' && $letter == '/') {
+            $single = TRUE;
+          }
+          elseif ($last === '' && $letter == '*') {
+            $multi = TRUE;
+          }
+          elseif ($escaped) {
+            $escaped = FALSE;
+          }
+          elseif ($letter == '\\') {
+            $escaped = TRUE;
+          }
+          elseif ($last === '') {
+            // If it's not a comment, it might be a regex
+            // which can only occur after certain operators
+            if (in_array($last_expression['value'], array(')', ']')) || ($last_expression['type'] != 'operator' && $last_expression['value'] != 'return')) {
+              $content = '/';
+              $instruction = 'operator';
+              break;
+            }
+          }
+          elseif ($letter == '/') {
+            // When the regex ends, we need to look for modifiers
+            $content .= $letter;
+            $instruction = 'regex';
+            $i = $j;
+            for ($k = $j + 1; $k < $length; $k++) {
+              $modifier = $lines{$k};
+              if ($modifier == ' ' || $modifier == "\t") {
+                $last = $modifier;
+                continue;
+              }
+              elseif(in_array($modifier, array('i', 'm', 'g'))) {
+                $i = $k;
+                $content .= $modifier;
+              }
+              else {
+                break;
+              }
+            }
+            break;
+          }
+          elseif ($letter == "\n") {
+            // End of the expression with no regex terminator
+            // So it's a division sign
+            $content = '/';
+            $instruction = 'operator';
+            break;
+          }
+
+          $content .= $letter;
+          $last = $letter;
+        }
+
+        $tokens[] = self::new_token($instruction, $content, compact($extras));
+        break;
+      default:
+        if ($pop['type'] != 'name' && is_numeric($char)) {
+          if ($pop['value'] == '.' || $pop['type'] == 'number') {
+            $pop['type'] = 'number';
+            $pop['value'] .= $char;
+          }
+          else {
+            $tokens[] = self::new_token('number', $char, compact($extras));
+          }
+        }
+        else {
+          if (!$pop['terminated'] && $pop['type'] == 'name') {
+            $pop['value'] .= $char;
+          }
+          elseif ($pop['type'] == 'number' && strtolower(substr($pop['value'], 0, 2)) == '0x' && stripos('1234567890abcdef', $char) !== false) {
+            // Hex
+            $pop['value'] .= $char;
+          }
+          elseif (strtolower($char) == 'x' && $pop['value'] == '0') {
+            // Hex
+            $pop['value'] .= $char;
+          }
+          elseif (strtolower($char) == 'e' && $pop['type'] == 'number') {
+            // e-notation
+            $pop['value'] .= $char;
+          }
+          else {
+            $tokens[] = self::new_token('name', $char, compact($extras));
+          }
+        }
+      }
+    }
+
+    // print '<pre>';
+    // print_r($tokens);
+    // print '</pre>';
+    // die();
+
+    return $tokens;
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptLiteral.php b/util/docscripts/lib/parser2/JavaScriptLiteral.php
new file mode 100644
index 0000000..407cb0c
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptLiteral.php
@@ -0,0 +1,56 @@
+<?php
+
+require_once('Destructable.php');
+
+class JavaScriptLiteral extends Destructable {
+  protected $value;
+
+  public function __construct($value) {
+    $this->value = $value;
+  }
+
+  public function __destruct() {
+    $this->mem_flush('value');
+  }
+
+  public function value() {
+    return $this->value;
+  }
+
+  public function type() {
+    if (is_object($this->value)) {
+      if ($this->value->arity == 'this') {
+        return 'Object';
+      }
+      elseif (strlen($this->value->id) > 1 && in_array($this->value->id{0}, array('!', '=', '<', '>'))) {
+        return 'bool';
+      }
+      elseif (in_array($this->value->id, array('!', '>', '<', '&', '|'))) {
+        return 'bool';
+      }
+      elseif ($this->value->id == '+' && !is_numeric($this->value->second->value)) {
+        return 'String';
+      }
+      elseif (in_array($this->value->id, array('++', '--', '+', '-', '*', '/', '%'))) {
+        return 'Number';
+      }
+      elseif ($this->value->id == '&&' || $this->value->id == '||') {
+        $first = $this->value->first;
+        if (is_array($first)) {
+          $first = $first[0];
+        }
+        return $first->type();
+      }
+    }
+    elseif (is_null($this->value) || $this->value == 'null') {
+      return 'Object';
+    }
+    elseif (is_bool($this->value)) {
+      return 'bool';
+    }
+    elseif ($this->value == 'arguments') {
+      return 'Array';
+    }
+    throw new Exception("Unstringed literal type: {$this->value}");
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptNumber.php b/util/docscripts/lib/parser2/JavaScriptNumber.php
new file mode 100644
index 0000000..eeb1a07
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptNumber.php
@@ -0,0 +1,9 @@
+<?php
+
+require_once('JavaScriptLiteral.php');
+
+class JavaScriptNumber extends JavaScriptLiteral {
+  public function type() {
+    return 'Number';
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptObject.php b/util/docscripts/lib/parser2/JavaScriptObject.php
new file mode 100644
index 0000000..171c884
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptObject.php
@@ -0,0 +1,44 @@
+<?php
+
+require_once('Destructable.php');
+
+class JavaScriptObject extends Destructable {
+  protected $statement;
+  protected $keys;
+
+  public function __construct($statement) {
+    $this->statement = $statement;
+  }
+
+  public function __destruct() {
+    $this->mem_flush('statement', 'keys');
+  }
+
+  public function type() {
+    return 'Object';
+  }
+
+  public function comments() {
+    return $this->statement->comments;
+  }
+
+  public function values() {
+    if (isset($this->keys)) {
+      return $this->keys;
+    }
+
+    $keys = array();
+    foreach ($this->statement->first as $value) {
+      if (is_array($value)) {
+        $value = $value[0];
+      }
+      $keys[$value->key][] = $value->convert();
+    }
+
+    return ($this->keys = $keys);
+  }
+
+  public function __toString() {
+    return '(' . $this->type() . ')';
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptOr.php b/util/docscripts/lib/parser2/JavaScriptOr.php
new file mode 100644
index 0000000..e8bcf40
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptOr.php
@@ -0,0 +1,37 @@
+<?php
+
+class JavaScriptOr extends JavaScriptVariable {
+  protected $ors;
+
+  public function __construct($ors) {
+    if (!is_array($ors)) {
+      throw new Exception('JavaScriptOr expects to be passed an array');
+    }
+    $this->ors = $ors;
+  }
+
+  public function __destruct() {
+    $this->mem_flush('ors');
+  }
+
+  public function types() {
+    $mapped = array();
+    foreach ($this->ors as $item) {
+      $mapped[] = $item->type();
+    }
+    return $mapped;
+  }
+
+  public function type() {
+    $types = array_diff($this->types(), array('variable'));
+    if (count($types) == 1) {
+      return array_pop($types);
+    }
+    // Assume that if one of them is a boolean, they all are
+    if (in_array('bool', $types)) {
+      return 'bool';
+    }
+
+    return 'Object';
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptParser.php b/util/docscripts/lib/parser2/JavaScriptParser.php
new file mode 100644
index 0000000..668d6c2
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptParser.php
@@ -0,0 +1,129 @@
+<?php
+
+require_once('Parser.php');
+require_once('JavaScriptSymbol.php');
+
+class JavaScriptParser extends Parser {
+  protected $symbol_class = JavaScriptSymbol;
+
+  protected function build() {
+    $this->symbol(';');
+    $this->symbol("\n");
+    $this->symbol(',');
+    $this->symbol(')');
+    $this->symbol(']');
+    $this->symbol('}');
+    $this->symbol('else');
+    $this->symbol('case');
+    $this->symbol('default');
+    $this->symbol('catch');
+    $this->symbol('finally');
+
+    $symbol = $this->symbol(':');
+    $symbol->lbp = 'lbp_colon';
+    $symbol->led = 'led_colon';
+
+    $this->symbol('(end)');
+    $this->symbol('(name)');
+
+    $this->assignment('=')->led = 'led_equals';
+    $this->assignment('+=');
+    $this->assignment('-=');
+    $this->assignment('*=');
+    $this->assignment('/=');
+    $this->assignment('%=');
+    $this->assignment('<<=');
+    $this->assignment('>>=');
+    $this->assignment('>>>=');
+    $this->assignment('&=');
+    $this->assignment('^=');
+    $this->assignment('|=');
+
+    $this->infix('?:', 20);
+    $this->infixr('||', 21);
+    $this->infixr('&&', 22);
+    $this->infix('|', 23);
+    $this->infix('^', 24);
+    $this->infix('&', 25);
+
+    $this->infix('==', 30);
+    $this->infix('!=', 30);
+    $this->infix('===', 30);
+    $this->infix('!==', 30);
+
+    $this->infix('<', 40);
+    $this->infix('<=', 40);
+    $this->infix('>', 40);
+    $this->infix('>=', 40);
+    $this->infix('in', 40);
+    $this->infix('instanceof', 40);
+
+    $this->infix('<<', 45);
+    $this->infix('>>', 45);
+    $this->infix('>>>', 45);
+
+    $this->infix('+', 50);
+    $this->infix('-', 50);
+
+    $this->infix('*', 60);
+    $this->infix('/', 60);
+    $this->infix('%', 60);
+
+    // prefix is 70
+    $this->prefix('!');
+    $this->prefix('~');
+    $this->prefix('+');
+    $this->prefix('-');
+    $this->prefix('typeof');
+    $this->prefix('void');
+    $this->prefix('delete');
+    $this->prefix('throw');
+
+    // crement is 75
+    $symbol = $this->symbol('++');
+    $symbol->lbp = 'lbp_crement';
+    $symbol->led = 'led_crement';
+    $symbol->nud = 'nud_crement';
+    $symbol = $this->symbol('--');
+    $symbol->lbp = 'lbp_crement';
+    $symbol->led = 'led_crement';
+    $symbol->nud = 'nud_crement';
+
+    $this->infix('(', 80, 'led_parenthesis')->nud = 'nud_parenthesis';
+
+    $this->infix('.', 85, 'led_period');
+    $this->infix('[', 85, 'led_bracket');
+    $this->prefix('new')->lbp = 85;
+
+    // Non-defined stuff:
+
+    $this->infix('?', 20, 'led_questionmark');
+
+    $this->constant('true', TRUE);
+    $this->constant('false', FALSE);
+    $this->constant('null', 'null');
+    $this->constant('undefined', NULL);
+    $this->constant('arguments', 'arguments');
+
+    $this->symbol('(literal)')->nud = 'nud_itself';
+
+    $this->stmt('{', 'std_curly');
+    $this->stmt('var', 'std_var');
+    $this->stmt('do', 'std_do');
+    $this->stmt('while', 'std_while');
+    $this->stmt('for', 'std_for');
+    $this->stmt('if', 'std_if');
+    $this->stmt('switch', 'std_switch');
+    $this->stmt('try', 'std_try');
+    $this->stmt('break', 'std_break');
+    $this->stmt('return', 'std_return');
+    $this->stmt('function', 'nud_function');
+    $this->prefix('function', 'nud_function');
+
+    $symbol = $this->symbol('this');
+    $symbol->nud = 'nud_this';
+
+    $this->prefix('[', 'nud_bracket');
+    $this->prefix('{', 'nud_curly');
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptRegExp.php b/util/docscripts/lib/parser2/JavaScriptRegExp.php
new file mode 100644
index 0000000..163417d
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptRegExp.php
@@ -0,0 +1,9 @@
+<?php
+
+require_once('JavaScriptLiteral.php');
+
+class JavaScriptRegExp extends JavaScriptLiteral {
+  public function type() {
+    return 'RegExp';
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptStatements.php b/util/docscripts/lib/parser2/JavaScriptStatements.php
new file mode 100644
index 0000000..d986ab1
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptStatements.php
@@ -0,0 +1,146 @@
+<?php
+
+require_once('JavaScriptFunction.php');
+require_once('JavaScriptFunctionCall.php');
+require_once('JavaScriptAssignment.php');
+require_once('Destructable.php');
+
+class JavaScriptStatements extends Destructable {
+  protected $statements;
+  protected $function_calls;
+  protected $function_assignments;
+  protected $prefixes = array();
+
+  public function __construct($statements) {
+    if (!is_array($statements)) {
+      $statements = array($statements);
+    }
+    $this->statements = $statements;
+  }
+
+  public function __destruct() {
+    $this->mem_flush('statements', 'function_calls', 'function_assignments', 'prefixes');
+  }
+
+  public function function_calls($global_scope = FALSE, $name = NULL) {
+    $calls = $this->function_calls = isset($this->function_calls) ? $this->function_calls : $this->resolve_something('resolve_function_calls');
+    if ($name) {
+      $names = array_slice(func_get_args(), 1);
+      $filtered = array();
+      foreach ($names as $name) {
+        foreach ($calls as $call) {
+          if ($call->name() == $name) {
+            $filtered[] = $call;
+          }
+        }
+      }
+      $calls = $filtered;
+    }
+    if ($global_scope) {
+      $filtered = array();
+      foreach ($calls as $call) {
+        if ($call->is_global()) {
+          $filtered[] = $call;
+        }
+      }
+      $calls = $filtered;
+    }
+    return $calls;
+  }
+
+  private function resolve_function_calls($statement, $parent) {
+    if (is_object($statement) && $statement->id == '(' && $statement->arity == 'binary' && (is_object($statement->first) && $statement->first->is_lookup())) {
+      $call = new JavaScriptFunctionCall($statement->first, $statement->second);
+      if ($parent->id == '=') {
+        $name = $parent->first;
+        while ($name) {
+          if ($name && $name->arity == 'name') {
+            if ($name->global_scope) {
+              $call->setAssignment($parent->first);
+            }
+            break;
+          }
+          $name = $name->first;
+        }
+      }
+      return $call;
+    }
+  }
+
+  public function assignments($global_scope=FALSE, $into_functions=TRUE) {
+    $assignments = $this->function_assignments = isset($this->function_assignments) ? $this->function_assignments : $this->resolve_something('resolve_assignments', array(), !$into_functions);
+    if ($global_scope) {
+      $filtered = array();
+      foreach ($assignments as $item) {
+        if ($item->is_global()) {
+          $filtered[] = $item;
+        }
+      }
+      $assignments = $filtered;
+    }
+    return $assignments;
+  }
+
+  private function resolve_assignments($statement, $parent) {
+    if ($statement->id == '=' && $statement->second) {
+      return new JavaScriptAssignment($statement->first, $statement->second);
+    }
+  }
+
+  public function prefix($prefix_name) {
+    return isset($this->prefixes[$prefix_name]) ? $this->prefixes[$prefix_name] : $this->resolve_something('resolve_prefix', array($prefix_name));
+  }
+
+  private function resolve_prefix($statement, $parent, $prefix_name) {
+    if ($statement->arity == 'statement' && $statement->value == $prefix_name) {
+      return $statement;
+    }
+  }
+
+  private function resolve_something($found_callback, $passed_args = array(), $seen_function=FALSE, $somethings = array(), $statements = NULL, $parent = NULL) {
+    if (!$statements) {
+      $statements = $this->statements;
+    }
+
+    if (!is_array($statements)) {
+      $statements = array($statements);
+    }
+
+    foreach ($statements as $statement) {
+      if (is_array($statement)) {
+        foreach ($statement as $st) {
+          if (!$seen_function || $st->id != 'function') {
+            $somethings = $this->resolve_something($found_callback, $passed_args, $seen_function, $somethings, $st, NULL);
+          }
+        }
+        continue;
+      }
+
+      if ($statement->id == 'function') {
+        if ($seen_function) {
+          continue;
+        }
+        $seen_function = TRUE;
+      }
+
+      if ($something = call_user_func_array(array($this, $found_callback), array_merge(array($statement, $parent), $passed_args))) {
+        $somethings[] = $something;
+      }
+
+      if ($statement->first) {
+        $somethings = $this->resolve_something($found_callback, $passed_args, $seen_function, $somethings, $statement->first, $statement);
+      }
+      if ($statement->second) {
+        $somethings = $this->resolve_something($found_callback, $passed_args, $seen_function, $somethings, $statement->second, $statement);
+      }
+      if ($statement->third) {
+        $somethings = $this->resolve_something($found_callback, $passed_args, $seen_function, $somethings, $statement->third, $statement);
+      }
+      if (!empty($statement->block)) {
+        $somethings = $this->resolve_something($found_callback, $passed_args, $seen_function, $somethings, $statement->block, $statement);
+      }
+    }
+
+    return $somethings;
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptString.php b/util/docscripts/lib/parser2/JavaScriptString.php
new file mode 100644
index 0000000..729b333
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptString.php
@@ -0,0 +1,9 @@
+<?php
+
+require_once('JavaScriptLiteral.php');
+
+class JavaScriptString extends JavaScriptLiteral {
+  public function type() {
+    return 'String';
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptSymbol.php b/util/docscripts/lib/parser2/JavaScriptSymbol.php
new file mode 100644
index 0000000..548dc65
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptSymbol.php
@@ -0,0 +1,644 @@
+<?php
+
+require_once('Symbol.php');
+
+require_once('JavaScriptFunctionCall.php');
+require_once('JavaScriptLiteral.php');
+require_once('JavaScriptString.php');
+require_once('JavaScriptNumber.php');
+require_once('JavaScriptRegExp.php');
+require_once('JavaScriptFunction.php');
+require_once('JavaScriptTernary.php');
+require_once('JavaScriptObject.php');
+require_once('JavaScriptArray.php');
+require_once('JavaScriptVariable.php');
+require_once('JavaScriptAssignment.php');
+require_once('JavaScriptOr.php');
+
+class JavaScriptSymbol extends Symbol {
+  /**
+   * Guesses the type of the current symbol
+   */
+  public function type() {
+    switch($this->id){
+    case '{':
+      return 'Object';
+    case '[':
+      return 'Array';
+    case 'function':
+      return 'Function';
+    }
+  }
+
+  public function convert($recursing = FALSE) {
+    if ($this->arity == 'literal') {
+      switch($this->type){
+      case 'string':
+        return new JavaScriptString($this->value);
+      case 'number':
+        return new JavaScriptNumber($this->value);
+      case 'regex':
+        return new JavaScriptRegExp($this->value);
+      default:
+        return new JavaScriptLiteral($this->value);
+      }
+    }
+    else {
+      switch($this->id){
+      case '?':
+        return new JavaScriptTernary($this->first, $this->second, $this->third);
+      case '(':
+        return new JavaScriptFunctionCall($this->first, $this->second);
+      case 'function':
+        return new JavaScriptFunction($this);
+      case '{':
+        return new JavaScriptObject($this);
+      case '[':
+      case '.':
+        if ($this->arity == 'unary') {
+          return new JavaScriptArray($this->first);
+        }else{
+          return new JavaScriptVariable($this);
+        }
+      case '=':
+        return new JavaScriptAssignment($this->first, $this->second);
+      case '||':
+        $output = array();
+
+        $first = $this->first;
+        if (is_array($first) && count($first == 1)) {
+          $first = $first[0];
+        }
+        $first = $first->convert(TRUE);
+
+        if (is_array($first)) {
+          $output = array_merge($output, $first);
+        }
+        else {
+          $output[] = $first;
+        }
+
+        $seconds = $this->second;
+        if (!is_array($seconds)) {
+          $seconds = array($seconds);
+        }
+        foreach ($seconds as $second) {
+          $second = $second->convert(TRUE);
+          if (is_array($second)) {
+            $output = array_merge($output, $second);
+          }
+          else {
+            $output[] = $second;
+          }
+        }
+
+        return $recursing ? $output : new JavaScriptOr($output);
+      }
+
+      switch ($this->arity) {
+      case 'name':
+        if ($this->value == 'new') {
+          // TODO: Make new matter
+          if ($this->first->id == 'function') {
+            return new JavaScriptFunction($this->first, true);
+          }
+          elseif ($this->first->id == '(') {
+            return new JavaScriptFunctionCall($this->first, $this->second, true);
+          }
+          elseif ($this->first->id == '.' || $this->first->id == '[') {
+            return new JavaScriptVariable($this->first, true);
+          }
+          else {
+            throw new Exception("Line {$this->first->line_number}, char {$this->first->char_pos}: New statement preceeds unknown");
+          }
+        }
+        return new JavaScriptVariable($this);
+      case 'literal':
+      case 'operator':
+      case 'this':
+      case 'unary':
+        return new JavaScriptLiteral($this);
+      }
+    }
+    throw new Exception("No class for {$this->id}:{$this->arity}");
+  }
+
+  // led/nud/lbp functions
+
+  public function led_bracket($parser, $left) {
+    $this->first = $left;
+    $this->second = $parser->expression();
+    $this->arity = 'binary';
+    $parser->advance(']');
+    return $this;
+  }
+
+  public function nud_bracket($parser) {
+    $items = array();
+    if (!$parser->peek(']')) {
+      while (1) {
+        $items[] = $parser->expression();
+        if (!$parser->peek(',')) {
+          break;
+        }
+        $parser->advance(',');
+        if ($parser->peek(']')) {
+          // Be lenient about trailing commas
+          break;
+        }
+      }
+    }
+    $parser->advance(']');
+    $this->first = $items;
+    $this->arity = 'unary';
+    return $this;
+  }
+
+  public function std_break($parser) {
+    $parser->skip_terminators();
+    $this->arity = 'statement';
+    return $this;
+  }
+
+  public function lbp_colon($parser, $left) {
+    if ($left->arity == 'name' && $parser->peek2(array('for', 'while', 'do'))) {
+      return 100;
+    }
+    return 0;
+  }
+
+  public function led_colon($parser, $left) {
+    $this->first = $left;
+    if ($parser->token->arity != 'name') {
+      throw new Exception("Line {$left->line_number}, char {$left->char_pos}: Expected a property name");
+    }
+    $parser->token->arity = 'literal';
+    $this->second = $parser->expression();
+    $this->arity = 'binary';
+    $parser->skip_terminators();
+    return $this;
+  }
+
+  public function lbp_crement($parser, $left) {
+    if ($left->id == '.' || $left->id == '[' || $left->arity == 'name') {
+      return 100;
+    }
+    return 0;
+  }
+
+  public function led_crement($parser, $left) {
+    // Show that the in/decrementer is on the right
+    $this->first = $left;
+    $this->arity = 'unary';
+    return $this;
+  }
+
+  public function nud_crement($parser) {
+    // Show that the in/decrement is before the expression
+    $this->first = NULL;
+    $this->second = $parser->expression(75);
+    return $this;
+  }
+
+  public function nud_curly($parser) {
+    $values = array();
+
+    $this->comments = array();
+    if (!$parser->peek('}')) {
+      while (1) {
+        $token = $parser->token;
+        if ($token->arity != 'name' && $token->arity != 'literal') {
+          throw new Exception("Line {$token->line_number}, char {$token->char_pos}: Bad key: {$token->id}");
+        }
+        $comments = $parser->comments_before($token);
+        if (!empty($comments)) {
+          if (!empty($this->comments)) {
+            $this->comments[] = "\n";
+          }
+          $this->comments = array_merge($this->comments, $comments);
+        }
+        $parser->advance();
+        $parser->advance(':');
+        $expression = $parser->expression();
+        if (is_array($expression)) {
+          $expression = $expression[0];
+        }
+        $expression->key = $token->value;
+        $values[] = $expression;
+        if (!$parser->peek(',')) {
+          break;
+        }
+        $token = $parser->token;
+        $parser->advance(',');
+        if ($parser->peek('}')) {
+          // Be lenient about trailing commas
+          break;
+        }
+      }
+    }
+
+    if ($parser->peek('}')) {
+      $this->comments = array_merge($this->comments, $parser->comments_before($parser->token));
+    }
+    $parser->advance('}');
+    $this->first = $values;
+    $this->arity = 'unary';
+    return $this;
+  }
+
+  public function std_curly($parser) {
+    $statements = $parser->statements(array('}'));
+    $parser->advance('}');
+    return $statements;
+  }
+
+  public function std_do($parser) {
+    if ($parser->peek('{')) {
+      $this->first = $this->block($parser);
+    }
+    else {
+      $this->first = $parser->expression($parser);
+      $parser->skip_terminators();
+    }
+    $parser->advance('while');
+    $parser->advance('(');
+    $this->second = $parser->expression();
+    $parser->advance(')');
+    $parser->skip_terminators();
+    return $this;
+  }
+
+  public function led_equals($parser, $left) {
+    $this->first = $left;
+    $this->second = $parser->expression(9);
+    $parser->scope->assignment($this->first, $this->second);
+    return $this;
+  }
+
+  public function std_for($parser) {
+    $parser->advance('(');
+
+    if($parser->peek('var')) {
+      $token = $parser->token;
+      $parser->advance('var');
+      $this->first = $token->std($parser);
+      if ($parser->peek('in')) {
+        $parser->advance('in');
+        $this->second = $parser->expression();
+      }
+    }
+    else {
+      // Don't forget that expressionless for(;;) loops are valid
+      $this->first = $parser->peek(';') ? NULL : $parser->statements(array(')', ';'));
+    }
+
+    if (!$parser->peek(')')) {
+      // var can possibly swallow the ;
+      if ($parser->peek(';')) {
+        $parser->advance(';');
+      }
+      $this->second = $parser->peek(';') ? NULL : $parser->statements(array(';'));
+      $parser->advance(';');
+      $this->thid = $parser->peek(')') ? NULL : $parser->statements(array(')'));
+    }
+    $parser->advance(')');
+    if ($parser->peek('{')) {
+      $this->block = $this->block($parser);
+    }
+    elseif (!$parser->peek(';')) {
+      $this->block = $parser->expression();
+    }
+
+    $parser->skip_terminators();
+
+    $this->arity = 'statement';
+    return $this;
+  }
+
+  public function nud_function($parser) {
+    $arguments = array();
+    $parser->new_scope();
+    $this->scope = $parser->scope;
+    if ($parser->token->arity == 'name') {
+      $parser->scope->define($parser->token);
+      $this->name = $parser->token->value;
+      $parser->advance();
+    }
+    $parser->advance('(');
+    if (!$parser->peek(')')) {
+      while (1) {
+        if ($parser->token->arity != 'name') {
+          throw new Exception('Expected a parameter name');
+        }
+        $parser->scope->define($parser->token);
+        $argument = $parser->token;
+        $parser->advance();
+        $argument->comments = array_merge($parser->comments_before($argument), $parser->comments_after($argument));
+        $arguments[] = $argument;
+        if (!$parser->peek(',')) {
+          break;
+        }
+        $parser->advance(',');
+      }
+    }
+
+    $this->first = $arguments;
+    $parser->advance(')');
+    $parser->peek('{');
+    $this->comments = $parser->comments_after($parser->token);
+    $parser->advance('{');
+    $this->second = $parser->statements(array('}'));
+    $parser->advance('}');
+    $this->arity = 'function';
+    $parser->scope_pop();
+
+    return $this;
+  }
+
+  public function std_if($parser) {
+    $parser->advance('(');
+    $this->first = $parser->expression();
+    $parser->advance(')');
+    if ($parser->peek('{')) {
+      $this->second = $this->block($parser);
+    }
+    elseif (!$parser->peek(';')) {
+      $this->second = $parser->expression();
+    }
+
+    $parser->skip_terminators();
+    
+    if ($parser->peek('else')) {
+      $parser->advance('else');
+      if ($parser->peek('if')) {
+        $this->third = $parser->statement;
+      }
+      elseif ($parser->peek('{')) {
+        $this->third = $this->block($parser);
+      }
+      elseif (!$parser->peek(';')) {
+        $this->third = $parser->expression();
+      }
+
+      $parser->skip_terminators();
+    }
+    else {
+      $this->third = NULL;
+    }
+    $this->arity = 'statement';
+    return $this;
+  }
+
+  public function executed_function($function, $parser) {
+    // The function gets executed
+    if ($parser->peek('(')) {
+      // led_parenthesis might have already swallowed it
+      $parser->advance('(');
+    }
+
+    $arguments = array();
+    if (!$parser->peek(')')) {
+      while (1) {
+        $arguments[] = $parser->expression();
+        if (!$parser->peek(',')) {
+          break;
+        }
+        $parser->advance(',');
+      }
+    }
+    $parser->advance(')');
+    $parser->skip_terminators();
+
+    // Make assignments within the function scope (in $function)
+    // between the arguments in the expression and the passed arguments
+    foreach ($function->first as $i => $parameter) {
+      if ($arguments[$i]) {
+        // The passed argument is assigned immediately to the matching parameter
+        $function->scope->assignment($parameter, $arguments[$i]);
+      }
+    }
+
+    $this->first = $function;
+    $this->second = $arguments;
+    $this->arity = 'execution';
+    return $this;
+  }
+
+  public function led_parenthesis($parser, $left) {
+    if ($left->id == 'function') {
+      return $this->executed_function($left, $parser);
+    }
+
+    if ($left->id == '{') {
+      $expression = $parser->expression();
+      $parser->advance(')');
+      return $expression;
+    }
+
+    if (!$parser->peek(')')) {
+      while (1) {
+        $arguments[] = $parser->expression();
+        if (!$parser->peek(',')) {
+          break;
+        }
+        $parser->advance(',');
+      }
+    }
+
+    if ($left->arity == 'operator' && $left->id != '.' && $left->id != '[' && count($arguments) == 1) {
+      $arguments = $arguments[0];
+    }
+
+    // e.g. foo(bar) has a foo first, [bar] second
+    $this->arity = 'binary';
+    $this->first = $left;
+    $this->second = $arguments;
+
+    $parser->advance(')');
+    return $this;
+  }
+
+  public function nud_parenthesis($parser) {
+    // '(' can mean function call, or executed function
+    $is_function = $parser->peek('function');
+    $expressions = array();
+    while (1) {
+      $expressions[] = $parser->expression();
+      if ($parser->peek(')')) {
+        break;
+      }
+      $parser->advance(',');
+    }
+    $parser->advance(')');
+
+    if ($is_function && $parser->peek('(')) {
+      return $this->executed_function($expressions[0], $parser);
+    }
+
+    return $expressions;
+  }
+
+  public function led_period($parser, $left) {
+    $this->first = $left;
+    if ($parser->token->arity != 'name') {
+      throw new Exception('Expected a property name');
+    }
+    $parser->token->arity = 'literal';
+    $this->second = $parser->token;
+    $this->arity ='binary';
+    $parser->advance();
+    return $this;
+  }
+
+  public function led_questionmark($parser, $left) {
+    $this->first = $left;
+    $this->second = $parser->expression();
+    $parser->advance(':');
+    $this->third = $parser->expression();
+    $this->arity = 'ternary';
+    return $this;
+  }
+
+  public function nud_this($parser) {
+    $parser->scope->reserve($this);
+    $this->arity = 'this';
+    return $this;
+  }
+
+  public function std_try($parser) {
+    $this->first = $this->block($parser);
+
+    if ($parser->peek('catch')) {
+      $parser->advance('catch');
+      $catch = $parser->new_symbol('catch');
+      $parser->advance('(');
+      $catch->first = $parser->expression();
+      $parser->advance(')');
+      $catch->second = $this->block($parser);
+
+      $this->second = $catch;
+    }
+
+    if ($parser->peek('finally')) {
+      $parser->advance('finally');
+      $this->third = $this->block($parser);
+    }
+
+    $parser->skip_terminators();
+
+    $this->arity = 'statement';
+
+    return $this;
+  }
+
+  public function std_return($parser) {
+    if (!$parser->peek("\n") && !$parser->peek(';') && !$parser->peek('}')) {
+      $this->first = $parser->expression();
+    }
+    $parser->skip_terminators();
+    $this->arity = 'statement';
+    return $this;
+  }
+
+  public function std_switch($parser) {
+    // switch statements can have multiple
+    // levels of passthrough and expressions
+    // need to be aggregated for each current
+    // case statement until a break is reached
+    $branches = array();
+
+    $parser->advance('(');
+    $this->first = $parser->expression();
+    $parser->advance(')');
+    $parser->advance('{');
+    $this->second = array();
+
+    $cases = array();
+    while (1) {
+      if ($parser->peek('}')) {
+        break;
+      }
+
+      if ($parser->peek('default')) {
+        $cases[] = $parser->token;
+        $switch = 'default';
+        $parser->advance('default');
+      }
+      else {
+        $cases[] = $parser->token;
+        $parser->advance('case');
+        $switch = 'case';
+        $cases[] = $parser->expression();
+      }
+
+      $parser->advance(':');
+      $statements = $parser->statements(array('default', 'case', '}'));
+
+      if ($switch == 'default') {
+        $default = $parser->new_symbol('default');
+        $default->first = $statements;
+        $cases[] = $default;
+      }
+      elseif ($switch == 'case' && !empty($statements)) {
+        $case = $parser->new_symbol('case');
+        $case->first = $statements;
+        $cases[] = $case;
+      }
+    }
+
+    $this->second = $cases;
+    $parser->advance('}');
+    $this->arity = 'statement';
+
+    return $this;
+  }
+
+  public function std_var($parser) {
+    $assignments = array();
+    while (1) {
+      $parser->peek();
+      $token = $parser->token;
+      if ($token->arity != 'name') {
+        throw new Exception("Line {$token->line_number}, char {$token->char_pos}: Expected a new variable name");
+      }
+      $parser->scope->define($token);
+      $parser->advance();
+      if ($parser->peek('=')) {
+        $t = $parser->token;
+        $parser->advance('=');
+        $t->first = $token;
+        $t->second = $parser->expression();
+        $parser->scope->assignment($t->first, $t->second);
+        $t->arity = 'binary';
+        $assignments[] = $t;
+      }
+      else {
+        $t = $parser->new_symbol('=');
+        $t->first = $token;
+        $t->second = NULL;
+        $assignments[] = $t;
+      }
+      if (!$parser->peek(',')) {
+        break;
+      }
+      $parser->advance(',');
+    }
+    $parser->skip_terminators();
+    return $assignments;
+  }
+
+  public function std_while($parser) {
+    $parser->advance('(');
+    $this->first = $parser->statements(array(')'));
+    $parser->advance(')');
+    if ($parser->peek('{')) {
+      $this->second = $this->block($parser);
+    }
+    else {
+      $this->second = $parser->expression();
+    }
+    $parser->skip_terminators();
+    $this->arity = 'statement';
+    return $this;
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptTernary.php b/util/docscripts/lib/parser2/JavaScriptTernary.php
new file mode 100644
index 0000000..74d5dbc
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptTernary.php
@@ -0,0 +1,42 @@
+<?php
+
+require_once('Destructable.php');
+
+class JavaScriptTernary extends Destructable {
+  protected $expression;
+  protected $if_true;
+  protected $if_false;
+
+  public function __construct($expression, $if_true, $if_false) {
+    $this->expression = $expression;
+    $this->if_true = $if_true;
+    $this->if_false = $if_false;
+  }
+
+  public function __destruct() {
+    $this->mem_flush('expression', 'if_true', 'if_false');
+  }
+
+  public function type() {
+    $trues = $this->if_true;
+    if (!is_array($trues)) {
+      $trues = array($trues);
+    }
+    foreach ($trues as $true) {
+      if ($type = $true->type()) {
+        return $type;
+      }
+    }
+
+    $falses = $this->if_false;
+    if (!is_array($falses)) {
+      $falses = array($falses);
+    }
+    foreach ($falses as $false) {
+      if ($type = $false->type()) {
+        return $type;
+      }
+    }
+    return '';
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/JavaScriptVariable.php b/util/docscripts/lib/parser2/JavaScriptVariable.php
new file mode 100644
index 0000000..5143ea8
--- /dev/null
+++ b/util/docscripts/lib/parser2/JavaScriptVariable.php
@@ -0,0 +1,63 @@
+<?php
+
+require_once('Destructable.php');
+
+class JavaScriptVariable extends Destructable {
+  protected $variable;
+  protected $resolved_variables;
+  protected $global_scope;
+
+  public function __construct($variable, $instantiated = FALSE) {
+    $this->variable = $variable;
+  }
+
+  public function __destruct() {
+    $this->mem_flush('variable', 'resolved_variables', 'global_scope');
+  }
+
+  private function resolve() {
+    if (!$this->variable->is_lookup()) {
+      $this->global_scope = FALSE;
+      $this->resolved_variables = array();
+    }
+    else {
+      foreach ($this->variable->resolve(TRUE) as $resolved) {
+        list($global_scope, $variable) = $resolved;
+        if ($global_scope) {
+          $this->global_scope = TRUE;
+        }
+        $this->resolved_variables[] = $variable;
+      }
+    }
+  }
+
+  public function value() {
+    if (!isset($this->resolved_variables)) {
+      $this->resolve();
+    }
+    return count($this->resolved_variables) ? $this->resolved_variables[0] : NULL;
+  }
+
+  public function values() {
+    if (!isset($this->resolved_variables)) {
+      $this->resolve();
+    }
+    return is_array($this->resolved_variables) ? $this->resolved_variables : array();
+  }
+
+  public function type() {
+    // TODO: Things that receive this value should reassign to aliases as appropriate
+    return 'variable';
+  }
+
+  public function is_global () {
+    if (!isset($this->global_scope)) {
+      $this->resolve();
+    }
+    return !!$this->global_scope;
+  }
+
+  public function __toString() {
+    return '(' . $this->type() . ')';
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/Parser.php b/util/docscripts/lib/parser2/Parser.php
new file mode 100644
index 0000000..9ab4f50
--- /dev/null
+++ b/util/docscripts/lib/parser2/Parser.php
@@ -0,0 +1,407 @@
+<?php
+
+require_once('Scope.php');
+require_once('Symbol.php');
+require_once('Destructable.php');
+
+abstract class Parser extends Destructable {
+  private static $symbol_tables = array();
+
+  protected $scopes = array();
+  protected $tokens;
+  protected $token_pos = 0;
+  protected $token_length = 0;
+  private $symbol_table;
+
+  public $token;
+  public $scope;
+
+  abstract protected function build();
+  protected $symbol_class = Symbol;
+
+  public function __construct($tokens) {
+    $id = get_class($this);
+    if (empty(self::$symbol_tables[$id])) {
+      $this->symbol_table = array();
+      $this->build();
+      self::$symbol_tables[$id] = $this->symbol_table;
+    }
+    $this->symbol_table = self::$symbol_tables[$id];
+    $this->scopes[] = $this->scope = new Scope();
+    $this->tokens = $tokens;
+    $this->token_length = count($tokens);
+  }
+
+  public function __destruct() {
+    $this->mem_flush('scopes', 'tokens', 'token', 'scope');
+  }
+
+  public function skip_terminators() {
+    while ($this->peek(';')) {
+      $this->advance(';');
+    }
+  }
+
+  /**
+   * Quick error check as we advance through the tokens
+   *
+   * @param string $id Check that the current token is what's expected
+   */
+  public function advance($id = NULL) {
+    if ($id && !$this->peek($id)) {
+      throw new Exception("Line {$this->token->line_number}, character {$this->token->char_pos}: Expected '$id' but got {$this->token->id}:'{$this->token->value}'");
+    }
+
+    $this->token = $this->next();
+
+    while ($this->token->value == "\n") {
+      // We can ignore line-breaks that are mid-expression
+      $this->token = $this->next();
+    }
+  }
+
+  /**
+   * Look at the next non-whitespace token for a value. Also needed
+   * for std functions to move up to the next non-whitespace character
+   */
+  public function peek($id = NULL) {
+    if ($id && !is_array($id)) {
+      $id = array($id);
+    }
+    if ($id && in_array("\n", $id) && $this->token->value == "\n") {
+      return true;
+    }
+    while ($this->token->value == "\n") {
+      // We can ignore line-breaks that are mid-expression
+      $this->token = $this->next();
+    }
+    return $id ? in_array($this->token->id, $id) : NULL;
+  }
+
+  public function peek2($id) {
+    if (!is_array($id)) {
+      $id = array($id);
+    }
+
+    for ($i = $this->token_pos; $i < $this->token_length; $i++) {
+      $token = $this->tokens[$i];
+      if (in_array("\n", $id) && $token['value'] == "\n") {
+        return true;
+      }
+      if ($token['type'] != 'string' && $token['value'] != "\n") {
+        return in_array($token['value'], $id);
+      }
+    }
+  }
+
+  /**
+   * Grab all statements
+   */
+  public function statements($terminators = array()) {
+    if (!$this->token_pos) {
+      $this->advance();
+    }
+
+    $terminators[] = '(end)';
+
+    $statements = array();
+    while (1) {
+      // Statements occur within {} blocks as well
+      if ($this->peek($terminators)) {
+        break;
+      }
+      if ($statement = $this->statement($terminators)) {
+        $statements[] = $statement;
+      }
+    }
+    return $statements;
+  }
+
+  /**
+   * Grab a single statement
+   */
+  public function statement($exclude = array()) {
+    $skip = array_diff(array(';', "\n", ','), $exclude);
+    while (in_array($this->token->id, $skip)) {
+      $this->advance($this->token->id);
+    }
+
+    $token = $this->token;
+    if ($token->std) {
+      $this->token = $this->next(); // Line breaks are *really* important to some statements
+      $this->scope->reserve($token);
+      return $token->std($this);
+    }
+    $expression = $this->expression();
+
+    while (in_array($this->token->id, $skip)) {
+      $this->advance($this->token->id);
+    }
+
+    return $expression;
+  }
+
+  private function comments_from_pos($i) {
+    $last = NULL;
+    $comments = array();
+    for (; $i < $this->token_length; $i++) {
+      $token = $this->tokens[$i];
+      if ($token['type'] == 'comment') {
+        $comments[] = $token['value'];
+      }
+      elseif ($token['value'] != "\n") {
+        break;
+      }
+      elseif ($last == "\n") {
+        $comments[] = '';
+      }
+      $last = $token['value'];
+    }
+    return $comments;
+  }
+
+  public function comments_before($symbol) {
+    if (!isset($symbol->token_pos)) {
+      throw new Exception('Need valid token to look up comments');
+    }
+
+    $comments = FALSE;
+    for ($i = $symbol->token_pos - 1; $i > 0; $i--) {
+      $token = $this->tokens[$i];
+      if ($token['type'] == 'comment') {
+        $comments = TRUE;
+      }
+      elseif ($token['value'] != "\n") {
+        if ($comments) {
+          return $this->comments_from_pos($i + 1);
+        }
+        break;
+      }
+    }
+
+    return array();
+  }
+
+  public function comments_after($symbol) {
+    if (!isset($symbol->token_pos)) {
+      throw new Exception('Need valid token to look up comments');
+    }
+
+    return $this->comments_from_pos($symbol->token_pos + 1);
+  }
+
+  /**
+   * Simply advance through the tokens
+   */
+  public function next() {
+    if ($this->token_pos < $this->token_length) {
+      $token = $this->tokens[$this->token_pos++];
+
+      $value = $token['value'];
+      $type = $arity = $token['type'];
+
+      if ($arity == 'string' || $arity == 'number' || $arity == 'regex') {
+        $arity = 'literal';
+        $s = $this->new_symbol('(literal)');
+      }
+      elseif ($s = $this->new_symbol($value)) {
+        // short circuit
+      }
+      elseif ($arity == 'name') {
+        $s = $this->scope->find($value, $this->symbol_table);
+      }
+      elseif ($arity == 'comment') {
+        return $this->next();
+      }
+      else {
+        throw new Exception("Line {$token['line_number']}, char {$token['char_pos']}: Unknown operator ($arity:'$value')");
+      }
+
+      $s->token_pos = $this->token_pos - 1;
+      $s->line = $token['line'];
+      $s->line_number = $token['line_number'];
+      $s->char_pos = $token['char_pos'];
+      $s->value = $value;
+      $s->arity = $arity;
+      $s->type = $type;
+
+      return $s;
+    }
+
+    return $this->new_symbol('(end)');
+  }
+
+  /**
+   *  Creates a new scope, setting the old one as its parent
+   */
+  public function new_scope() {
+    $this->scopes[] = $scope = new Scope();
+    $scope->setParent($this->scope);
+    return ($this->scope = $scope);
+  }
+
+  /**
+   * Reassigns the parents scope
+   */
+  public function scope_pop() {
+    return ($this->scope = $this->scope->parent());
+  }
+
+  /**
+   * Moves through tokens with higher binding powers
+   * than the passed binding power
+   *
+   * @param int $bp
+   */
+  public function expression($bp = 0) {
+    $token = $this->token;
+    $this->advance();
+    while ($this->token->value == "\n") {
+      // We can ignore line-breaks that are mid-expression
+      $token = $this->token;
+      $this->advance();
+    }
+    $left = $token->nud($this);
+    while ($bp < $this->token->lbp($this, $left)) {
+      $token = $this->token;
+      $this->advance();
+      $left = $token->led($this, $left);
+    }
+
+    return $left;
+  }
+
+  public function new_symbol($id, $raw = FALSE) {
+    $symbol = $this->symbol_table[$id];
+    if ($symbol) {
+      if ($raw) {
+        return $symbol;
+      }
+      $symbol = clone $symbol;
+      $symbol->scope = $this->scope;
+      return $symbol;
+    }
+  }
+
+  /**
+   * Takes a symbol ID and a left binding power
+   * and returns a Symbol instance
+   *
+   * @param string $id
+   * @param int $b 
+   */
+  protected function symbol($id, $bp = 0) {
+    if (($s = $this->symbol_table[$id]) && is_numeric($s->lbp)) {
+      $s->lbp = max($bp, $s->lbp);
+    }
+    else {
+      $s = new $this->symbol_class();
+      $s->id = $id;
+      $s->lbp = $bp;
+      $this->symbol_table[$id] = $s;
+    }
+    return $s;
+  }
+
+  /**
+   * Creates a symbol with a left denotation function
+   * that will save the current symbol in its left property
+   * and the rest of the expression on its right
+   *
+   * @param string $id
+   * @param int $bp
+   * @param string $ld String to use for the left_denotation function
+   */
+  protected function infix($id, $bp, $led = NULL) {
+    $symbol = $this->symbol($id, $bp);
+    if ($led) {
+      $symbol->led = $led;
+    }
+    else {
+      $symbol->led = 'led_infix';
+      $symbol->bp = $bp;
+    }
+    return $symbol;
+  }
+
+  /**
+   * Creates a symbol with a left denotation function
+   * that will save symbols "below" it
+   *
+   * @param string $id
+   * @param int $bp
+   * @param string $led String to use for the left_denotation function
+   */
+  protected function infixr($id, $bp, $led = NULL) {
+    $symbol = $this->symbol($id, $bp);
+    if ($led) {
+      $symbol->led = $led;
+    }
+    else {
+      $symbol->led = 'led_infixr';
+      $symbol->bp = $bp;
+    }
+    return $symbol;
+  }
+
+  /**
+   * Create a symbol with a null denotation function
+   * that will set its left property to what its
+   * modifying
+   *
+   * @param string $id
+   * @param string $nud String to use for the null_denotation function
+   */
+  protected function prefix($id, $nud = NULL) {
+    $symbol = $this->symbol($id);
+    $symbol->nud = $nud ? $nud : 'nud_prefix';
+    return $symbol;
+  }
+
+  protected function itself($id) {
+    return $this->prefix($id, 'nud_itself');
+  }
+
+  /**
+   * Creates a symbol with a null denotation function that
+   * makes sure it's being assigned to a variable
+   * and sets its left property to what's being assigned
+   * to it. Also marks its assignment value to true
+   *
+   * @param string $id
+   */
+  protected function assignment($id) {
+    return $this->infixr($id, 10, 'led_assignment');
+  }
+
+  /**
+   * Creates a symbol with a null denotation function
+   * that turns a name token into a literal token
+   * by marking it reserved in the current scope
+   * and setting its value to a language-level literal
+   *
+   * @param string $id
+   * @param anything $null_denotation String to use for the null_denotation function
+   */
+  protected function constant($name, $value) {
+    $symbol = $this->symbol($name);
+    $symbol->nud = 'nud_constant';
+    $symbol->value = $value;
+    $symbol->arity = 'constant';
+    return $symbol;
+  }
+
+  /**
+   * Creates a symbol with a statement denotation function
+   * passed to it.
+   *
+   * @param string $id
+   * @param string $std String to use for the statement_denotation function
+   */
+  protected function stmt($id, $std) {
+    $symbol = $this->symbol($id);
+    $symbol->std = $std;
+    $symbol->nud = $std; // This makes statement nesting (with no block) possible
+    return $symbol;
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/Scope.php b/util/docscripts/lib/parser2/Scope.php
new file mode 100644
index 0000000..5c66b00
--- /dev/null
+++ b/util/docscripts/lib/parser2/Scope.php
@@ -0,0 +1,201 @@
+<?php
+
+require_once('Destructable.php');
+
+class Scope extends Destructable {
+  protected $_parent;
+  protected $definitions = array();
+  protected $assignments = array();
+
+  public function __destruct() {
+    $this->mem_flush('_parent', 'definitions', 'assignments');
+  }
+
+  /**
+   * Turns a name symbol into a variable symbol
+   *
+   * @param Symbol $symbol A name object occurring in the current scope
+   */
+  public function define(&$symbol) {
+    if ($token = $this->definitions[$symbol->value] && $token->reserved) {
+      throw new Exception("Already defined: {$symbol->value}");
+    }
+
+    $this->definitions[$symbol->value] = $symbol;
+    $symbol->reserved = FALSE;
+    $symbol->nud = 'nud_itself';
+    $symbol->led = NULL;
+    $symbol->std = NULL;
+    $symbol->lbp = 0;
+    $symbol->scope = $this;
+    $symbol->global_scope = empty($this->_parent);
+
+    return $symbol;
+  }
+
+  /**
+   * Mark an assignment made in the current scope between two symbols
+   *
+   * @param Symbol $to_expression The expression $expression is assigned to
+   * @param Symbol $expression The expression being assigned
+   */
+  public function assignment($to_expression, $expression) {
+    // Only let through assignments to actual lookups (foo or foo.bar.baz)
+    // where the assignment is also a lookup, or an object (which may contain lookups)
+    if (is_object($to_expression) && $to_expression->is_lookup()) {
+      if ($this !== $to_expression->scope) {
+        // The assignment might be referencing a higher scope (e.g. without var)
+        return $to_expression->scope->assignment($to_expression, $expression);
+      }
+
+      $this->assignments[$to_expression->value] = array();
+
+      $expressions = array($expression);
+      if ($possibilities = $this->possibilities($expression)) {
+        $expressions = $possibilities;
+      }
+      foreach ($expressions as $expression) {
+        if (is_object($expression) && ($expression->is_lookup() || $expression->id == '{')) {
+          $this->assignments[$to_expression->value][] = $expression;
+        }
+      }
+    }
+  }
+
+  protected function possibilities($symbol, $possibilities=array()) {
+    $symbols = $symbol;
+    if (!is_array($symbols)) {
+      $symbols = array($symbols);
+    }
+    foreach ($symbols as $symbol) {
+      if (is_array($symbol)) {
+        $possibilities = $this->possibilities($symbol, $possibilities);
+      }
+      elseif ($symbol->is_option()) {
+        $firsts = $symbol->first;
+        if (!is_array($firsts)) {
+          $firsts = array($firsts);
+        }
+        foreach ($firsts as $first) {
+          if (is_array($first)) {
+            $possibilities = $this->possibilities($first, $possibilities);
+          }
+          elseif ($first->possible_variable()) {
+            $possibilities[] = $first;
+          }
+        }
+
+        $seconds = $symbol->second;
+        if (!is_array($seconds)) {
+          $seconds = array($seconds);
+        }
+        foreach ($seconds as $second) {
+          if (is_array($second) || $second->is_option()) {
+            $possibilities = $this->possibilities($second, $possibilities);
+          }
+          elseif ($second->possible_variable()) {
+            $possibilities[] = $second;
+          }
+        }
+      }
+    }
+    return $possibilities;
+  }
+
+  public function assigned($variable, $as_array=FALSE) {
+    if (isset($this->assignments[$variable])) {
+      return $as_array ? $this->assignments[$variable] : $this->assignments[$variable][0];
+    }
+    if (isset($this->parent)) {
+      return $this->_parent->assigned($variable, $as_array);
+    }
+  }
+
+  /**
+   * Sets the current scope's parent
+   *
+   * @param Scope $parent
+   */
+  public function setParent($parent) {
+    if ($parent instanceof Scope) {
+      return ($this->_parent = $parent);
+    }
+  }
+
+  /**
+   * Returns the current parent
+   */
+  public function parent() {
+    // This is how pop() will work as well
+    return $this->_parent;
+  }
+
+  public function definition($name) {
+    return $this->definitions[$name];
+  }
+
+  /**
+   * Tries to look up through each scope
+   * to find a symbol with the same name
+   * and returns the global symbol or empty
+   * (name) symbol instead
+   */
+  public function find ($name, $symbol_table) {
+    if ($symbol_table[$name]) {
+      return clone $symbol_table[$name];
+    }
+
+    $scope = $this;
+    while (1) {
+      if ($symbol = $scope->definition($name)) {
+        return clone $symbol;
+      }
+      if (!$scope->parent()) {
+        if (array_key_exists($name, $symbol_table)) {
+          return $symbol_table[$name];
+        }
+        $symbol = $symbol_table['(name)'];
+        $s = clone $symbol;
+        $s->global_scope = TRUE;
+        $s->reserved = FALSE;
+        $s->nud = 'nud_itself';
+        $s->led = NULL;
+        $s->std = NULL;
+        $s->lbp = 0;
+        $s->scope = $scope;
+        return $s;
+      }
+      $scope = $scope->parent();
+    }
+  }
+
+  /**
+   * Marks a variable symbol as being reserved in the current scope
+   *
+   * @param Symbol @symbol The variable symbol to mark reserved
+   */
+  public function reserve($symbol) {
+    if ($symbol->arity != 'name' || $symbol->reserved) {
+      return;
+    }
+
+    if ($token = $this->definitions[$symbol->value]) {
+      if ($token->reserved) {
+        $symbol->reserved = TRUE;
+        if (!$this->parent()) {
+          $symbol->global_scope = TRUE;
+        }
+        return;
+      }
+      if ($token->arity == 'name') {
+        throw new Exception("Already defined: {$symbol->value}");
+      }
+    }
+
+    $symbol->reserved = TRUE;
+    if (!$this->parent()) {
+      $symbol->global_scope = TRUE;
+    }
+    $this->definitions[$symbol->value] = $symbol;
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/Symbol.php b/util/docscripts/lib/parser2/Symbol.php
new file mode 100644
index 0000000..bfadc3a
--- /dev/null
+++ b/util/docscripts/lib/parser2/Symbol.php
@@ -0,0 +1,252 @@
+<?php
+
+class Symbol {
+  public $id = NULL;
+  public $name = NULL;
+  public $value = NULL;
+  public $first = NULL;
+  public $second = NULL;
+  public $third = NULL;
+  public $lbp = 0;
+  public $reserved = FALSE;
+  public $global_scope = FALSE;
+  public $assignment = FALSE;
+  public $arity;
+  public $type;
+  public $line_number;
+  public $char_pos;
+
+  public $nud = 'nud_default';
+  public $led = 'led_default';
+  public $std = NULL;
+
+  public $bp = 0;
+
+  public function possible_variable() {
+    return $this->value == '.' || $this->value == '[' || $this->arity == 'name';
+  }
+
+  public function is_option() {
+    return $this->first && ($this->value == '||' || $this->value == '&&');
+  }
+
+  public function is_lookup($statement = NULL) {
+    if (!$statement) {
+      $statement = $this;
+    }
+
+    $first = $statement->first;
+    $second = $statement->second;
+
+    if ($first && $statement->arity == 'binary' && ($statement->id == '.' || $statement->id == '[')) {
+      return (is_object($first) && $first->is_lookup() && $second->arity == 'literal');
+    }
+    else {
+      return ($statement->arity == 'name' || $statement->arity == 'literal' || $statement->arity == 'this');
+    }
+  }
+
+  public function resolve($as_array = FALSE, $statement = NULL, $public = FALSE, $firsts = array()) {
+    if (!$statement) {
+      $public = TRUE; // Whether the call is non-resursive
+      $statement = $this;
+    }
+
+    $first = $statement->first;
+    $second = $statement->second;
+
+    $results = array();
+
+    if ($first && $statement->arity == 'binary' && ($statement->id == '.' || $statement->id == '[')) {
+      // foo.bar.baz or foo["bar"].baz
+      foreach ($this->resolve(TRUE, $first, FALSE, $firsts) as $resolved) {
+        list($is_global, $name) = $resolved;
+
+        if (!$second->arity == 'literal') {
+          throw new Exception(sprintf('Line %d, char %d: Lookup is not by literal: %s', $statement->line_number, $statement->char_pos, $second));
+        }
+
+        if (is_object($name) && $name->id == '{') {
+          $is_global = $first->global_scope;
+
+          // The parent item resolved to an object
+          // so we need to continue the lookup
+          foreach ($name->first as $value) {
+            // -> first has all values with their key
+            if ($value->key == $second->value) {
+              if ($value->first() == $statement->first()) {
+                 // Object references itself, within itself
+                continue;
+              }
+              if ($value->arity == 'name') {
+                // Contains an actual variable name
+                $results[] = array($value->global_scope, $value->value);
+                break 2;
+              }
+              elseif ($value->arity == 'binary' && ($value->id == '.' || $value->id == '[')) {
+                // Contains a new variable for us to resolve
+                $results = array_merge($results, $this->resolve(TRUE, $value, TRUE, $firsts));
+                break 2;
+              }
+              elseif (!$public && $value->id == '{') {
+                // Contains an object
+                $results[] = array(NULL, $value);
+                break 2;
+              }
+            }
+          }
+
+          $name = $first->value;
+        }
+
+        if (!is_string($name)) {
+          throw new Exception(sprintf('Line %d, char %d: Parent variable resolution returned an unknown (%s)', $statement->line_number, $statement->char_pos, $statement));
+        }
+
+        if ($is_global && $name == 'this') {
+          $results[] = array($is_global, $second->value);
+        }
+        else {
+          $results[] = array($is_global, sprintf('%s.%s', $name, $second->value));
+        }
+      }
+
+      return $as_array ? $results : $results[0];
+    }
+    elseif ($statement->arity == 'name' || $statement->arity == 'literal' || $statement->arity == 'this') {
+      // This is the first item in the variable (e.g. for foo.bar.baz, it would be foo)
+      // It only matters if it's an object or an assignment
+      if ($assignments = $statement->scope->assigned($statement->value, TRUE)) {
+        foreach ($assignments as $assignment) {
+          if ($assignment->first() != $statement->first() && !in_array($statement->first(), $firsts)) {
+            if ($assignment->arity == 'name') {
+              $results[] = array($assignment->global_scope, $assignment->value);
+            }
+            elseif ($assignment->arity == 'binary' && ($assignment->id == '.' || $assignment->id == '[')) {
+              // Deal with stuff like c = p.constructor;
+              // followed by p = c.superclass
+              // where they "look each other up"
+              $results = array_merge($results, $this->resolve(TRUE, $assignment, TRUE, array_merge($firsts, array($statement->first()))));
+            }
+            elseif (!$public && $assignment->id == '{') {
+              $results[] = array(NULL, $assignment);
+            }
+          }
+        }
+      }
+
+      if (count($results)) {
+        return $as_array ? $results : $results[0];
+      }
+
+      $result = array($statement->global_scope, $statement->value);
+      return $as_array ? array($result) : $result;
+    }
+
+    throw new Exception(sprintf('Line %d, char %d: Expected a variable in the form foo.bar with %s', $statement->line_number, $statement->char_pos, $statement->id));
+  }
+
+  public function first($statement = NULL) {
+    if (!$statement) {
+      $statement = $this;
+    }
+
+    $first = $statement->first;
+    $second = $statement->second;
+
+    if ($first && $statement->arity == 'binary' && ($statement->id == '.' || $statement->id == '[')) {
+      return $this->first($first);
+    }
+    elseif ($statement->arity == 'name') {
+      return $statement->value;
+    }
+  }
+
+  /**
+   * Creates a symbol with a statement denotation function
+   * that reads until it finds an opening {
+   */
+  public function block($parser) {
+    $parser->peek('{');
+    $token = $parser->token;
+    $parser->advance('{');
+    return $token->std($parser);
+  }
+
+  public function nud_default($parser) {
+    throw new Exception("Syntax error on line {$this->line_number}, character {$this->char_pos} ({$this->id}:'{$this->value}')");
+  }
+
+  public function nud_prefix($parser) {
+    $this->first = $parser->expression(70);
+    return $this;
+  }
+
+  public function nud_itself($parser) {
+    return $this;
+  }
+
+  public function nud_constant($parser) {
+    $parser->scope->reserve($this);
+    $this->value = $parser->new_symbol($this->id, TRUE)->value;
+    $this->arity = 'literal';
+    return $this;
+  }
+
+  public function led_default($parser, $left) {
+    throw new Exception("Unknown operator ({$this->id}:'{$this->value}')");
+  }
+
+  public function led_infix($parser, $left) {
+    $this->first = $left;
+    $this->second = $parser->expression($this->bp);
+    return $this;
+  }
+
+  public function led_infixr($parser, $left) {
+    $this->first = $left;
+    $this->second = $parser->expression($this->bp - 1);
+    return $this;
+  }
+
+  public function led_assignment($parser, $left) {
+    if ($left->id != '.' && $left->id != '[' && $left->arity != 'name') {
+      throw new Error('Bad lvalue');
+    }
+    $this->first = $left;
+    $this->second = $parser->expression(9);
+    $this->assignment = true;
+    $this->arity = 'binary';
+    return $this;
+  }
+
+  public function __call($method, $args) {
+    if ($method == 'lbp') {
+      if (is_numeric($this->lbp)) {
+        return $this->lbp;
+      }
+      return call_user_func_array(array($this, $this->lbp), $args);
+    }
+    if ($method == 'nud') {
+      return call_user_func_array(array($this, $this->nud), $args);
+    }
+    if ($method == 'led') {
+      return call_user_func_array(array($this, $this->led), $args);
+    }
+    if ($method == 'std') {
+      return call_user_func_array(array($this, $this->std), $args);
+    }
+  }
+
+  public function __toString() {
+    // debug_backtrace_clean();
+    if ($this->id == '(name)' || $this->id == '(literal)') {
+      return '(' . substr($this->id, 1, strlen($this->id) - 2) . " {$this->value})";
+    }
+    $first = is_array($this->first) ? ('[' . implode(', ', $this->first) . ']') : $this->first;
+    $second = is_array($this->second) ? ('[' . implode(', ', $this->second) . ']') : $this->second;
+    $third = is_array($this->third) ? ('[' . implode(', ', $this->third) . ']') : $this->third;
+    $out = array_diff(array($this->id, $first, $second, $third), array(NULL));
+    return '(' . implode(' ', $out) . ')';
+  }
+}
\ No newline at end of file
diff --git a/util/docscripts/lib/parser2/dojo2.inc b/util/docscripts/lib/parser2/dojo2.inc
new file mode 100644
index 0000000..114e334
--- /dev/null
+++ b/util/docscripts/lib/parser2/dojo2.inc
@@ -0,0 +1,383 @@
+<?php
+
+ini_set('display_errors', 1);
+error_reporting(E_ALL ^ E_NOTICE);
+
+require_once('JavaScriptLanguage.php');
+require_once('JavaScriptParser.php');
+require_once('JavaScriptStatements.php');
+require_once('JavaScriptFunction.php');
+require_once('Dojo.php');
+require_once('DojoCommentBlock.php');
+
+$_dojo_properties_modules = array();
+
+function _dojo_get_namespaces($limit=null){
+  static $namespaces;
+  if (!isset($namespaces)) {
+    $namespaces = array();
+    $files = scandir('modules');
+    foreach ($files as $file) {
+      if (substr($file, -7) == '.module') {
+        $namespace = substr($file, 0, -7);
+        if (!$limit || in_array($namespace, $limit)) {
+          include_once('modules/' . $file);
+          $namespaces[] = substr($file, 0, -7);
+        }
+      }
+      elseif (substr($file, -18) == '.module.properties') {
+        $namespace = substr($file, 0, -18);
+        if (!$limit || in_array($namespace, $limit)) {
+          global $_dojo_properties_modules;
+          foreach (preg_split('%[\n\r]+%', file_get_contents('modules/' . $file)) as $line) {
+            list($line, ) = preg_split('%[!#]%', $line, 2);
+            if ($line = trim($line)) {
+              list($key, $line) = explode('=', $line, 2);
+              $key = str_replace('\\ ', ' ', trim($key));
+              $line = preg_replace('%^\s+%', '', $line);
+              if ($key == 'location') {
+                $line = _dojo_ensure_directory($line);
+              }
+              $_dojo_properties_modules[$namespace][$key] = $line;
+            }
+          }
+          $namespaces[] = substr($file, 0, -18);
+        }
+      }
+    }
+  }
+  return $namespaces;
+}
+
+function dojo_get_include($node, $provide) {
+  if ($node->jsdoc_project_name == $provide->title) {
+    return 'Included automatically';
+  }
+  else {
+    return 'dojo.require("%s");';
+  }
+}
+
+function _dojo_ensure_directory($directory) {
+  if (!is_dir($directory)) {
+    die("$directory is not a directory\n");
+  }
+  else {
+    if(substr($directory, -1) != '/'){
+      $directory .= '/';
+    }
+  }
+  return $directory;
+}
+
+function dojo_get_file_time($namespace, $file) {
+  if (function_exists($namespace . '_code_location')) {
+    return filectime(_dojo_ensure_directory(call_user_func($namespace . '_code_location')) . $file);
+  }
+  else {
+    global $_dojo_properties_modules;
+    return filectime($_dojo_properties_modules[$namespace]['location'] . $file);
+  }
+}
+
+function _jsdoc_file_list($dir = false, $recurse = false){
+  $output = array();
+
+  if (!$recurse) {
+    $old_dir = getcwd();
+    if (!is_dir($dir)) {
+      return array();
+    }
+    chdir($dir);
+    $dir = '.';
+  }
+  $files = scandir($dir);
+
+  foreach ($files as $file) {
+    if ($file{0} == '.') continue;
+    if (is_dir($dir . '/' . $file)) {
+      if ($recurse) {
+        $file = $dir . '/' . $file;
+      }
+      $output = array_merge($output, _jsdoc_file_list($file, true));
+    }else{
+      if (substr($file, -3) == '.js' && substr($file, -6) != '.xd.js') {
+        if ($recurse) {
+          $file = $dir . '/' . $file;
+        }
+        $output[] = $file;
+      }
+    }
+  }
+
+  if (!$recurse) {
+    chdir($old_dir);
+  }
+  return $output;
+}
+
+function dojo_get_files($limit=null) {
+    $namespaces = _dojo_get_namespaces($limit);
+    $files = array();
+    foreach ($namespaces as $namespace) {
+        if (function_exists($namespace . '_code_location')) {
+          $location = _dojo_ensure_directory(call_user_func($namespace . '_code_location'));
+        }
+        else {
+          global $_dojo_properties_modules;
+          $location = $_dojo_properties_modules[$namespace]['location'];
+        }
+        if (!$location) die($namespace . '_code_location does not return useful result');
+        $list = _jsdoc_file_list($location);
+        foreach ($list as $i => $item) {
+            // Skip internationalization/tests/demos files
+            if (preg_match('%(^|/|\\\\)(nls|tests|demos)(\\\\|/)%', $item)) {
+              unset($list[$i]);
+              continue;
+            }
+            $list[$i] = array($namespace, $item);
+        }
+        $files = array_merge($files, array_values($list));
+    }
+
+    return $files;
+}
+
+function dojo_get_contents($namespace, $file_name) {
+  if (function_exists($namespace . '_code_location')) {
+    $location = _dojo_ensure_directory(call_user_func($namespace . '_code_location'));
+  }
+  else {
+    global $_dojo_properties_modules;
+    $location = $_dojo_properties_modules[$namespace]['location'];
+  }
+
+  $lines = preg_replace('%/\*={3,}|={3,}\*/%', '', file_get_contents($location . '/' . $file_name));
+  $parser = new JavaScriptParser(JavaScriptLanguage::tokenize($lines));
+  // print '<pre>';
+  // $statements = $parser->statements();
+  // print $statements[0]->resolve();
+  // print '</pre>';
+  // die();
+  $package = new JavaScriptStatements($parser->statements());
+
+  $output = array();
+
+  // Handle dojo.provide calls
+  foreach ($package->function_calls(TRUE, 'dojo.provide') as $call) {
+    if ($module = $call->arguments()->getString(0)) {
+      $output['#provides'] = $module;
+    }
+  }
+
+  $output['#resource'] = $file_name;
+
+  // Handle dojo.require calls
+  foreach ($package->function_calls(TRUE, 'dojo.require') as $call) {
+    if ($module = $call->arguments()->getString(0)) {
+      $output['#requires'][] = array('common', $module);
+    }
+  }
+
+  // Handle mixin/extend calls
+  foreach ($package->function_calls(TRUE, 'dojo.mixin', 'dojo.extend') as $call) {
+    $arguments = $call->arguments();
+    $assignment = $call->assignment();
+    $root = NULL;
+    if ($constructor = $arguments->getFunction(0)) {
+      if ($assignment) {
+        Dojo::roll_out($constructor, $assignment, FALSE, $output);
+      }
+    }
+    else {
+      $root = $arguments->getVariable(0, TRUE);
+      if ($call->name() == 'dojo.extend') {
+        $output[$root]['type'] = 'Function';
+      }
+    }
+
+    foreach (array_diff(array_unique(array($assignment, $root)), array(NULL)) as $root) {
+      $mixin = $call->name() == 'dojo.mixin';
+      for ($i = 1; $i < $arguments->length; $i++) {
+        if ($arguments->getObject($i)) {
+          $keys = array();
+          foreach ($arguments->getObject($i)->values() as $key => $values) {
+            $keys[] = $key;
+            $full_name = "$root.$key";
+            foreach ($values as $value) {
+              if ($value instanceof JavaScriptVariable) {
+                $key = $mixin ? $full_name : "$root.prototype.$key";
+                if ($key != $value->value()) {
+                  $output[$key]['alias'] = $value->value();
+                }
+              }
+              else {
+                Dojo::roll_out($value, $full_name, FALSE, $output);
+                $output[$full_name][$mixin ? 'attached' : 'prototype'] = $root;
+              }
+            }
+          }
+          Dojo::roll_out_comment_block($arguments->getObject($i), $root, $output, $keys);
+        }
+        elseif ($root && $full_name = $arguments->getVariable($i)) {
+          if ($mixin) {
+            $output[$root]['mixins']['normal'][] = $full_name;
+          }
+          else {
+            $output[$root]['chains']['prototype'][] = $full_name;
+          }
+        }
+      }
+    }
+  }
+
+  foreach ($package->function_calls(TRUE, 'dojo.declare') as $call) {
+    $arguments = $call->arguments();
+    $name = $arguments->getString(0);
+    if (!$name) {
+      continue;
+    }
+    $output[$name]['type'] = 'Function';
+    if ($superclass = $arguments->getVariable(1)) {
+      if ($superclass != 'null') {
+        $output[$name]['chains']['prototype'][] = $superclass;
+        $output[$name]['chains']['call'][] = $superclass;
+      }
+    }
+    elseif ($superclasses = $arguments->getArray(1)) {
+      for($i = 0; TRUE; $i++) {
+        if ($superclass = $superclasses->getVariable($i)) {
+          $output[$name]['chains']['prototype'][] = $superclass . ($i ? '.prototype' : '');
+          $output[$name]['chains']['call'][] = $superclass;
+        }
+        else {
+          break;
+        }
+      }
+    }
+    if ($mixin = $arguments->getObject(2)) {
+      $keys = $block_keys = Dojo::$block_keys;
+      $new_keys = array();
+      $constructors = array();
+      // Remember that bad code can have multiple matching keys
+      foreach ($mixin->values() as $key => $values) {
+        $new_keys[] = $key;
+        $full_name = "$name.$key";
+        foreach ($values as $value) {
+          if ($value instanceof JavaScriptFunction) {
+            if (in_array($key, array('constructor', 'preamble', 'postscript'))) {
+              $output[$full_name]['constructor'] = $key;
+              $output[$full_name]['prototype'] = $name;
+              $constructors[$full_name] = $value;
+              continue;
+            }
+          }
+          elseif ($value->type() == 'variable') {
+            if ($full_name != $value->value()) {
+              $output[$full_name]['alias'] = $value->value();
+            }
+            continue;
+          }
+
+          $output[$full_name]['prototype'] = $name;
+          $new_keys = array_unique(array_merge($new_keys, Dojo::roll_out($value, $full_name, FALSE, $output, $new_keys)));
+        }
+      }
+
+      foreach ($constructors as $full_name => $constructor) {
+        $new_keys = array_unique(array_merge($new_keys, Dojo::roll_out($constructor, $name, FALSE, $output, $new_keys)));
+        foreach ($output[$name] as $key => $value) {
+          if ($key != 'chains') {
+            $output[$full_name][$key] = $value;
+          }
+        }
+      }
+
+      Dojo::roll_out_comment_block($mixin, $name, $output, $new_keys);
+    }
+  }
+
+  // Variable assignments (global)
+  foreach ($package->assignments(TRUE) as $variable) {
+    foreach ($variable->names() as $name) {
+      $parts = explode('.', $name);
+      $name = implode('.', array_diff($parts, array('prototype')));
+      $last = array_pop($parts);
+
+      $is_prototype = ($last == 'prototype');
+
+      Dojo::roll_out($variable->value(), $name, FALSE, $output, array(), $is_prototype);
+
+      if (count($parts) && !$is_prototype) {
+        $output[$name]['attached'] = implode('.', $parts);
+      }
+    }
+  }
+
+  // dojo.provide creates new objects if needed
+  if (!empty($output['#provides'])) {
+    $parts = explode('.', $output['#provides']);
+    while (count($parts)) {
+      if (!array_key_exists(implode('.', $parts), $output)) {
+        $output[implode('.', $parts)] = array('type' => 'Object');
+      }
+      array_pop($parts);
+    }
+  }
+
+  // Set privacy, classlikeness, and clean up the summary a bit
+  foreach ($output as $object_name => $object) {
+    if ($object_name{0} == '#') {
+      continue;
+    }
+    $parts = explode('.', $object_name);
+    $last = array_pop($parts);
+    if ($last{0} == '_') {
+      $output[$object_name]['private'] = true;
+    }
+    if (preg_match('%\._+[^A-Z]%', implode('.', $parts), $match)) {
+        $output[$object_name]['private_parent'] = true;
+    }
+    if (is_array($object['tags'])) {
+      foreach ($object['tags'] as $tag) {
+        if ($tag == 'protected') {
+          unset($output[$object_name]['private']);
+          $output[$object_name]['protected'] = true;
+        }
+        elseif ($tag == 'private') {
+          unset($output[$object_name]['protected']);
+          $output[$object_name]['private'] = true;
+        }
+        elseif ($tag == 'deprecated') {
+          $output[$object_name]['deprecated'] = true;
+        }
+      }
+      $output[$object_name]['tags'] = array_diff($object['tags'], array('private', 'protected', 'deprecated'));
+    }
+
+    if (isset($object['inferred_type'])) {
+      if (empty($object['type'])) {
+        $output[$object_name]['type'] = $object['inferred_type'];
+      }
+      unset($output[$object_name]['inferred_type']);
+    }
+
+    if ($object['type'] == 'Function') {
+      if (preg_match('%^(_*)[A-Z]%', $last, $match)) {
+        if (strlen($match[1]) < 2) {
+          unset($output[$object_name]['private']);
+        }
+        $output[$object_name]['classlike'] = true;
+      }
+    }
+
+    if ($object['prototype'] && $output[$object['prototype']]) {
+      $output[$object['prototype']]['classlike'] = true;
+    }
+    elseif ($object['instance'] && $output[$object['instance']]) {
+      $output[$object['instance']]['classlike'] = true;
+    }
+  }
+
+  return $output;
+}
\ No newline at end of file
diff --git a/util/docscripts/makeCix.php b/util/docscripts/makeCix.php
new file mode 100755
index 0000000..a4e0a08
--- /dev/null
+++ b/util/docscripts/makeCix.php
@@ -0,0 +1,326 @@
+<?php
+//
+//	This is an experiemental file, used to generate dojo11.cix,
+//	the XML for ActiveState's Komodo Editor code-completion.
+//
+//  	it requires php5, a lot of memory, and write access to
+//  	the ./cache folder in this path.  It will parse the dojo
+//	tree (or read from cache if a file is unmodified), and dump
+//	the results to "valid" XML (i think).
+//
+//  to use:
+//  /usr/local/php5/bin/php -q makeCix.php > ../resources/dojo.cix
+//
+
+// $Rev: $ 
+$current_version = "1.5.0";
+
+header("Content-type: text/xml");
+
+ini_set("memory_limit","512M");
+include_once('includes/dojo.inc');
+
+$files = dojo_get_files();
+
+// our namespaces:
+$out = array("dijit" => array(), "dojox" => array(), "dojo" => array() );
+// put the results of each file into $array[$namespace]
+foreach ($files as $set){
+	list($namespace,$file) = $set;
+	$data = dojo_get_contents_cache($namespace, $file);
+	$out[$namespace] = array_merge($out[$namespace],$data);
+}
+// and do some weeeird array manipulations:
+$out = @expando_dojo($out);
+
+// start a new document
+$doc = new DOMDocument('1.0');
+// setup for codeintel:
+$codeintel = $doc->createElement('codeintel');
+$codeintel->setAttribute("description","Dojo Toolkit API - version " . $current_version);
+$codeintel->setAttribute("version","2.0");
+$codeintel->setAttribute("encoding","UTF-8");
+// wrap all the api in one "file" tag:
+$data = $doc->createElement('file');
+$data->setAttribute("lang","JavaScript");
+$data->setAttribute("path","");
+$f = $codeintel->appendChild($data);
+// and all the namespaces under one heading "dojo"
+$api = $doc->createElement('scope');
+$api->setAttribute("ilk","blob");
+$api->setAttribute("lang","JavaScript");
+$api->setAttribute("name","dojo");
+$namespace = $f->appendChild($api);
+
+// iterate through our modified array, and make an XML tree of the data:
+foreach ($out as $ns => $data){
+	
+		// each top-level namespace get's it own scope
+		$nsdata = $doc->createElement('scope');
+		$nsdata->setAttribute("ilk","class");
+		$nsdata->setAttribute("name",$ns);
+
+		foreach ($data as $obj => $info){
+			
+			$objElm = $doc->createElement('scope');
+			if(!empty($info['type'])){
+
+				$tt = $info['type'];
+				switch($tt){
+					case "Object" :
+						// inspect this object deeper, but append to namespace:
+						$nsdata->appendChild(dojo_inspect($data[$obj],$obj,$doc, "variable"));
+						break;
+					case "Function" :
+						if($info['classlike']){
+							// inspect deeper, append to namesapce:
+							$nsdata->setAttribute("ilk","class");
+							$nsdata->appendChild(dojo_inspect($data[$obj],$obj,$doc));
+						}else{
+							// functions usually have param data:
+							$objElm->setAttribute("ilk",strtolower($tt));
+							$objElm->setAttribute("name",$obj);
+							if(is_array($info['parameters'])){
+								// generate the signature
+								$sig = $obj."(";
+								foreach($info['parameters'] as $param => $pData){
+									$sig .= $param.",";
+									$paramElm = $doc->createElement('variable');
+									if(!empty($pData['type'])){
+										$paramElm->setAttribute("citdl",$pData['type']);
+									}
+									$paramElm->setAttribute("name",$param);
+									$paramElm->setAttribute("ilk","argument");
+									if($pData['summary']){
+										$paramElm->setAttribute("doc", fix_utf(htmlentities($pData['summary'])));
+									}
+									$objElm -> appendChild($paramElm);
+								}
+								$sig = substr($sig,0,strlen($sig)-1);
+								$sig .= ")";
+								$objElm->setAttribute("signature",$sig);
+								unset($sig);
+							}
+						}
+						break;
+				}
+				unset($tt);
+			}
+			// pertinent data:
+			if(!empty($info['returns'])){
+				$objElm->setAttribute("returns",htmlentities($info['returns']));
+			}
+			// helpful data:
+			if(!empty($info['summary'])){
+				$objElm->setAttribute("doc", fix_utf(htmlentities($v)));
+			}
+			
+			// avoid appending this node if we skipped popoulating it (in the case of nsdata->appendCHild())
+			if($objElm->hasAttribute("name")){
+				$nsdata->appendChild($objElm);
+			}
+		}
+
+		// and dump all the data to this namesapce
+		$namespace->appendChild($nsdata);	
+	
+}
+
+// append the APi to the document, and print:
+$doc->appendChild($codeintel);
+print $doc->saveXML();
+
+
+function dojo_inspect($data,$ns,$doc,$t="scope"){
+	// summary: inspect some namespace (as top), with some passed data.
+	if ($t == "argument") {
+		$elm = $doc->createElement("variable");
+		$elm->setAttribute("ilk", "argument");
+	} else {
+		$elm = $doc->createElement($t);
+	}
+	$elm->setAttribute("name",$ns);
+
+	foreach ($data as $obj => $info){
+		switch($obj){
+			// these are all the ones we don't _really_ care about in this context:
+			case "prototype" : //$elm->setAttribute("classref",$info['prototype']); break;
+			case "chains" :
+			case "mixins" :
+			case "instance" :
+			case "optional" :
+			case "classlike" :
+			case "examples" :
+			case "private_parent" :
+			case "description" : 
+			case "source" :
+			case "style" :
+				break;
+
+			// mmm, duplicated from above:
+			case "parameters" :
+				$sig = $ns."(";
+				foreach($info as $key => $val){
+					$sig .= $key.",";
+					$elm->appendChild(dojo_inspect($val,$key,$doc,"argument"));
+				}
+				$sig = substr($sig,0,strlen($sig)-1);
+				$sig .= ")";
+				$elm->setAttribute("signature",$sig);
+				break;
+
+			// some pertinant info about this element:
+			case "returns" : $elm->setAttribute("returns",htmlentities($info));
+			case "private" : $elm->setAttribute("attributes","private"); break;
+
+			case "type" :
+				if($info) {
+					switch ($info){
+						case "Function" :
+							$elm->setAttribute("ilk","function");
+							break;
+						default:
+							$elm->setAttribute("citdl",$info);
+							break;
+					}
+				}
+				break;
+
+			// ahhh, the blessed summary:
+			case "summary" : $elm->setAttribute("doc", fix_utf(htmlentities($info)));
+				break;
+
+			// just in case we missed something?
+			default :
+				$scope_type = "scope";
+				if (($data[$obj]["instance"] != NULL) ||
+				    ($data[$obj]["type"] == "Object")) {
+					$scope_type = "variable";
+				}
+				$elm->appendChild(dojo_inspect($data[$obj],$obj,$doc,$scope_type));
+				break;
+		}
+	}
+	// give it back as a domNode:
+	return $elm;
+
+}
+
+function dojo_get_contents_cache($namespace, $file, $forceNew = false){
+	// summary: a shim to dojo_get_contents, providing filemtime checking/caching
+	// 		from parsing: XML takes ~ 80000ms on my MacBook Pro, from cache:
+	// 		7000ms ... pass true as third param to force cache reloading.
+
+	// if the file hasn't been change since the last time, skip parsing it
+	$mtime = dojo_get_file_time($namespace, $file);
+	$cfile = "./cache/".md5($namespace.$file).".".$mtime;
+	
+	if(!$forceNew && file_exists($cfile)){
+		// read it from the cache:
+		$cache = file_get_contents($cfile);
+		$data = unserialize($cache);
+		
+	}else{
+		// parse the file, and save the cached results:
+		$data = @dojo_get_contents($namespace, $file);
+		$cache = serialize($data);
+		$fp = fopen($cfile,"w+");
+		fputs($fp,$cache);
+		fclose($fp);
+		
+	}
+	return $data;
+
+}
+
+function expando_dojo($array){
+	// ugly array manipulation to turn an array like:
+	// array( "one" => array("one","two","three"), "one.more"=>array("two","four","six")
+	// into:
+	// array("one" => array("more"=>array("two","four","six"), "one", "two", "three"));
+
+	$ret = array();
+	foreach($array as $namespace => $results){
+		foreach($results as $item => $data){
+			switch($item{0}){
+				case "#" : break;
+				default:
+					$list = explode(".",$item);
+					$n = count($list);
+					$me = $list[$n];
+					// NOT happy with this:
+					if(!($list[0]==$namespace)){ continue; }
+					switch($n){
+						case 8 :
+							fprintf("UNCAUGHT! %s", $item); // way tooooo deep.
+							break;
+						case 7 : 
+							$l1 = $list[1];
+							$l2 = $list[2];
+							$l3 = $list[3];
+							$l4 = $list[4];
+							$l5 = $list[5];
+							$l6 = $list[6];
+							if ($ret[$namespace][$l1][$l2][$l3][$l4][$l5][$l6] == NULL)
+								$ret[$namespace][$l1][$l2][$l3][$l4][$l5][$l6] = $data;
+							else
+								$ret[$namespace][$l1][$l2][$l3][$l4][$l5][$l6] = array_merge_recursive($data, $ret[$namespace][$l1][$l2][$l3][$l4][$l5][$l6]);
+							break;
+						case 6 :
+							$l1 = $list[1];
+							$l2 = $list[2];
+							$l3 = $list[3];
+							$l4 = $list[4];
+							$l5 = $list[5];
+							if ($ret[$namespace][$l1][$l2][$l3][$l4][$l5] == NULL)
+								$ret[$namespace][$l1][$l2][$l3][$l4][$l5] = $data;
+							else
+								$ret[$namespace][$l1][$l2][$l3][$l4][$l5] = array_merge_recursive($data, $ret[$namespace][$l1][$l2][$l3][$l4][$l5]);
+							break;
+						case 5 : 
+							$l1 = $list[1];
+							$l2 = $list[2];
+							$l3 = $list[3];
+							$l4 = $list[4];
+							if ($ret[$namespace][$l1][$l2][$l3][$l4] == NULL)
+								$ret[$namespace][$l1][$l2][$l3][$l4] = $data;
+							else
+								$ret[$namespace][$l1][$l2][$l3][$l4] = array_merge_recursive($data, $ret[$namespace][$l1][$l2][$l3][$l4]);
+							break;
+						case 4 :
+							$l1 = $list[1];
+							$l2 = $list[2];
+							$l3 = $list[3];
+							if ($ret[$namespace][$l1][$l2][$l3] == NULL)
+								$ret[$namespace][$l1][$l2][$l3] = $data;
+							else
+								$ret[$namespace][$l1][$l2][$l3] = array_merge_recursive($data, $ret[$namespace][$l1][$l2][$l3]);
+							break;
+						case 3 :
+							$l1 = $list[1];
+							$l2 = $list[2];
+							
+							if ($ret[$namespace][$l1][$l2] == NULL)
+								$ret[$namespace][$l1][$l2] = $data;
+							else
+								$ret[$namespace][$l1][$l2] = array_merge_recursive($data, $ret[$namespace][$l1][$l2]);
+							break;
+						case 2 :
+							$l1 = $list[1];
+							$ret[$namespace][$l1] = $data;
+							break;
+					}
+					break;
+			}
+			
+		}
+		
+	}
+	return $ret;
+}
+
+function fix_utf($str){
+	return iconv('utf-8','utf-8', $str);
+}
+
+?>
diff --git a/util/docscripts/modules/dijit.module b/util/docscripts/modules/dijit.module
new file mode 100755
index 0000000..a571476
--- /dev/null
+++ b/util/docscripts/modules/dijit.module
@@ -0,0 +1,29 @@
+<?php
+
+function dijit_code_location() {
+	return '../../dijit/';
+}
+
+function dijit_project_name() {
+	return 'dijit';
+}
+
+function dijit_resource_name($namespace, $file) {
+  return $file;
+}
+
+function dijit_package_name($namespace, $file) {
+  //return;
+  $parts = explode('/', $file);
+  if ($parts[0] == '_base') {
+		return $namespace;
+  }
+	$file_parts = explode('.', array_pop($parts));
+	if (in_array('tests', $parts)) return;
+	array_pop($file_parts);
+	array_push($parts, implode('.', $file_parts));
+	array_unshift($parts, $namespace);
+  return implode('.', $parts);
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/modules/dojo.module b/util/docscripts/modules/dojo.module
new file mode 100755
index 0000000..95c4c00
--- /dev/null
+++ b/util/docscripts/modules/dojo.module
@@ -0,0 +1,29 @@
+<?php
+
+function dojo_code_location() {
+  return '../../dojo/';
+}
+
+function dojo_project_name() {
+  return 'dojo';
+}
+
+function dojo_resource_name($namespace, $file) {
+  return $file;
+}
+
+function dojo_package_name($namespace, $file) {
+  //return;
+  $parts = explode('/', $file);
+  if ($parts[0] == '_base') {
+    return $namespace;
+  }
+  $file_parts = explode('.', array_pop($parts));
+  if (in_array('tests', $parts)) return;
+  array_pop($file_parts);
+  array_push($parts, implode('.', $file_parts));
+  array_unshift($parts, $namespace);
+  return implode('.', $parts);
+}
+
+?>
\ No newline at end of file
diff --git a/util/docscripts/modules/dojox.module.properties b/util/docscripts/modules/dojox.module.properties
new file mode 100755
index 0000000..46bf808
--- /dev/null
+++ b/util/docscripts/modules/dojox.module.properties
@@ -0,0 +1 @@
+location = ../../dojox/
\ No newline at end of file
diff --git a/dijit/LICENSE b/util/doh/LICENSE
similarity index 100%
copy from dijit/LICENSE
copy to util/doh/LICENSE
diff --git a/util/doh/README b/util/doh/README
new file mode 100644
index 0000000..2f1d91a
--- /dev/null
+++ b/util/doh/README
@@ -0,0 +1,12 @@
+DOH may be run standalone by issuing a command like the following:
+
+java -jar ../shrinksafe/js.jar runner.js testModule=tests.colors
+
+where the testModule argument is optional and shrinksafe/js.jar is just a
+convenient copy of the Rhino JavaScript engine -- the custom patch is not
+required.
+
+Optional arguments include:
+ * dojoUrl - specifies the location of dojo.js
+ * testUrl - specifies a Javascript file to load with initialization code
+ * testModule - specifies a test module in the dojo package namespace
diff --git a/util/doh/Robot.html b/util/doh/Robot.html
new file mode 100644
index 0000000..eef0f8f
--- /dev/null
+++ b/util/doh/Robot.html
@@ -0,0 +1,186 @@
+<html style="margin:0px; padding:0px;">
+<body style="margin:0px; padding:0px; border:0px none;background-color:transparent;" onload="init()">
+<script>
+	// support document.domain
+	// Yes, we need this try/catch to handle document.domain.
+	// If one page explicitly sets document.domain,
+	// ALL pages (this page, test case, page to be tested) must also explicitly set document.domain,
+	// or you get Permission Denied.
+	// So it's not as easy as just setting document.domain to whatever the browser reports,
+	// because you don't know if the user explicitly set that.
+	try{
+		// Was the passed domain just a stupid browser default?
+		// If so, this statement will work.
+		window.frameElement.ownerDocument;
+	}catch(e){
+		// Permission Denied.
+		// Means user explicitly set document.domain elsewhere.
+		// robot.js passes the document.domain as a GET parameter.
+		var domain=unescape(/[\\?&]domain=([^&#]*)/.exec(window.location.href)[1]);
+		document.domain=domain;
+	}
+	// find doh
+	var doc = window.frameElement.ownerDocument;
+	var w = doc.parentWindow || doc.defaultView || top;
+	doh = w.doh;
+
+	function init(){
+		var applet = document.getElementsByTagName('applet')[0];
+
+		doh.robot._killApplet = function(){
+			document.body.removeChild(applet);
+			applet = null;
+		};
+	}
+
+	// the box that the applet writes into to test the user's keyboard capabilities
+	var _robotField = null;
+
+
+	/*
+		Robot uses the event handlers below to measure system-level
+		properties that the java.awt.Robot class just expects us to know
+		magically. For instance, we don't know how big the user set their mouse
+		wheel to be in the Control Panel, so we measure it using onmousewheel.
+	*/
+
+	function _onfocus(robotField){
+		_robotField = robotField;
+		doh.robot._initWheel();
+	}
+
+	function _onblur(e){
+		setTimeout(function(){
+			document.body.removeChild(_robotField);
+		},0);
+	}
+
+	function _onmousedown(e){
+		e = e||window.event;
+		if(e.screenX == 0||e.clientX == 0){ return; }
+		var docScreenX = e.screenX-e.clientX;
+		var docScreenY = e.screenY-e.clientY;
+		doh.robot._setDocumentBounds(docScreenX, docScreenY);
+	}
+
+	function _onmousewheel(e){
+		e = e||window.event;
+		doh.robot.mouseWheelSize = e.detail ? (e.detail * -1) : (e.wheelDelta / 120);
+		if(e.preventDefault){ e.preventDefault(); }
+		else { e.returnValue = false; }
+		doh.robot._primePump = true;
+		doh.robot._initKeyboard();
+		return false;
+	}
+
+	var charCode = 32;
+	var keystring = "";
+	var expectedlength = 0;
+
+	doh.robot._nextKeyGroup = function(size){
+		// called from Robot
+		// moves to the next group of keys to press; shift, alt-graph etc.
+		expectedlength = size;
+		keystring = "";
+	};
+
+	function _onkeypress(e){
+		e = e||window.event;
+		var c = e.charCode ? e.charCode :
+                   (e.keyCode ? e.keyCode :
+                   (e.which ? e.which : 0)); // opera
+		if(doh.robot._primePump){
+			// event pump was primed with spaces and JS finally received one
+			// tell robot to stop sending spaces now
+			if(c == 32){
+				doh.robot._spaceReceived = true;
+			}
+			else if(c == 13){
+				// enter: start accepting keys
+				doh.robot._primePump = false;
+			}
+		}
+		else if(c == 32){
+			keystring += String.fromCharCode(charCode);
+			charCode = 32;
+			if(keystring.length >= expectedlength){
+				doh.robot._notified(keystring);
+			}
+		}
+		else if(c > 32){ // printable
+			charCode = c;
+		}
+		// keyboard discovery misbehaves on Safari/Mac
+		// prevent default action if possible
+		if(e.preventDefault){ e.preventDefault(); }
+		else { e.returnValue = false; }
+		return false;
+	}
+
+	doh.robot._onKeyboard = function(){
+	 	// called from Robot
+		// Robot calls _onKeyboard after it finishes discovering the keyboard
+		// need to untie from Java thread with setTimeout
+		setTimeout(function(){
+			var rf = document.getElementsByTagName('input')[0];
+			rf.style.visibility = "hidden";
+			doh.robot._run(window.frameElement);
+ 		}, 0);
+	};
+</script>
+<input type="text" tabIndex="-1" style="border:0px none;margin:0px;padding:0px;position:absolute;left:0px;top:0px;width:200px;height:42px;background-color:white;z-index:9999;opacity:0;filter:alpha(opacity=0);cursor:default;"
+	onmousewheel="_onmousewheel(arguments[0])"
+	onmousedown="_onmousedown(arguments[0])"
+	onkeypress="_onkeypress(arguments[0])"
+	onfocus="_onfocus(this)"
+	onblur="_onblur(arguments[0])">
+<script>
+	if(document.getElementsByTagName('input')[0].addEventListener){
+		document.getElementsByTagName('input')[0].addEventListener('DOMMouseScroll', _onmousewheel, false);
+	}
+</script>
+<script>
+	// taken from hostenv_browser.js
+	// Dojo is not always available to DOH
+	var needsSecurityManager='<param name="needsSecurityManager" value="'+((
+		(Math.max(navigator.appVersion.indexOf("WebKit"), navigator.appVersion.indexOf("Safari"), 0) > 0 && navigator.userAgent.indexOf("Chrome/") == -1 && parseFloat(navigator.appVersion.split("Version/")[1]) < 4) // Safari 3
+		|| (document.all && navigator.userAgent.indexOf("Opera") == -1 && parseFloat(navigator.appVersion.split("MSIE ")[1]) < 8)) // IE6,7
+		?"true":"false")+'">';
+	var appletString = '<applet width="1" height="1" code="DOHRobot.class" archive="robot/DOHRobot.jar" MAYSCRIPT style="position:absolute;left:0px;top:22px;"><param name="mayscript" value="true"><param name="scriptable" value="true"><param name="initial_focus" value="false">'+needsSecurityManager+'</applet>';
+	document.write(appletString);
+	// if no Java, the applet is officially dead
+	if(/MSIE/.test(navigator.appVersion)){
+		// navigator.javaEnabled() not known for its reliability in IE6
+		try{
+			// applet loads synchronously in IE6
+			document.applets[0].isActive();
+		}catch(e){
+			doh.robot._appletDead=true;
+			// IE skips the dojo.robot XHR test below in the else
+			// since the no java behavior is the same as no applet behavior in IE
+			doh.run();
+		}
+	}else if(!navigator.javaEnabled()){
+		// FF, Safari, Opera etc.
+		// unreliable in IE6
+		doh.robot._appletDead=true;
+		doh.run();
+	}else{
+		// Opera etc. have Java enabled, but load the applet asychronously so it might still be missing from server at this point
+		// Do an XHR to find out if the applet is there
+		// IE is taken care of in the first if, so no need for special ActiveX XHR for it
+		var dohRobotCheck=new XMLHttpRequest();
+		dohRobotCheck.onreadystatechange=function(){
+			if(dohRobotCheck.readyState == 4 && dohRobotCheck.status == 404){
+				// oops! no applet
+				// move the tests along
+				doh.robot._appletDead=true;
+				doh.run();
+			}
+		};
+		dohRobotCheck.open("HEAD", "robot/DOHRobot.jar");
+		dohRobotCheck.send(null);
+	}
+</script>
+</body>
+</html>
diff --git a/util/doh/_browserRunner.js b/util/doh/_browserRunner.js
new file mode 100644
index 0000000..86cbe5f
--- /dev/null
+++ b/util/doh/_browserRunner.js
@@ -0,0 +1,883 @@
+if(window["dojo"]){
+	dojo.provide("doh._browserRunner");
+}
+
+// FIXME: need to add prompting for monkey-do testing
+
+(function(){
+	try{
+		var topdog = (window.parent == window) || !Boolean(window.parent.doh);
+	}catch(e){
+		//can't access window.parent.doh, then consider ourselves as topdog
+		topdog=true;
+	}
+	if(topdog){
+		// we're the top-dog window.
+
+		// borrowed from Dojo, etc.
+		var byId = function(id){
+			return document.getElementById(id);
+		};
+
+		var _addOnEvt = function(	type,		// string
+									refOrName,	// function or string
+									scope){		// object, defaults is window
+
+			if(!scope){ scope = window; }
+
+			var funcRef = refOrName;
+			if(typeof refOrName == "string"){
+				funcRef = scope[refOrName];
+			}
+			var enclosedFunc = function(){ return funcRef.apply(scope, arguments); };
+
+			if((window["dojo"])&&(type == "load")){
+				dojo.addOnLoad(enclosedFunc);
+			}else{
+				if(window["attachEvent"]){
+					window.attachEvent("on"+type, enclosedFunc);
+				}else if(window["addEventListener"]){
+					window.addEventListener(type, enclosedFunc, false);
+				}else if(document["addEventListener"]){
+					document.addEventListener(type, enclosedFunc, false);
+				}
+			}
+		};
+
+		//
+		// Over-ride or implement base runner.js-provided methods
+		//
+		var escapeXml = function(str){
+			//summary:
+			//		Adds escape sequences for special characters in XML: &<>"'
+			//		Optionally skips escapes for single quotes
+			return str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """); // string
+		};
+
+		var formatTime = function(n){
+			switch(true){
+				case n<1000: //<1s
+					return n+"ms";
+				case n<60000: //<1m
+					return Math.round(n/100)/10+"s";
+				case n<3600000: //<1h
+					return Math.round(n/6000)/10+"m";
+				default: //>1h
+					return Math.round(n/360000)/10+"h";
+			}
+		};
+		
+		var _logBacklog = [], _loggedMsgLen = 0;
+		var sendToLogPane = function(args, skip){
+			var msg = "";
+			for(var x=0; x<args.length; x++){
+				msg += " "+args[x];
+			}
+
+			msg = escapeXml(msg);
+
+			// workarounds for IE. Wheeee!!!
+			msg = msg.replace("\t", "    ")
+				.replace(" ", " ")
+				.replace("\n", "<br> ");
+			if(!byId("logBody")){
+				_logBacklog.push(msg);
+				return;
+			}else if(_logBacklog.length && !skip){
+				var tm;
+				while((tm=_logBacklog.shift())){
+					sendToLogPane(tm, true);
+				}
+			}
+			var logBody=byId("logBody");
+			var tn = document.createElement("div");
+			tn.innerHTML = msg;
+			//tn.id="logmsg_"+logBody.childNodes.length;
+			logBody.appendChild(tn);
+			_loggedMsgLen++;
+		}
+
+		var findTarget = function(n){
+			while(n && !n.getAttribute('_target')){
+				n=n.parentNode;
+				if(!n.getAttribute){
+					n=null;
+				}
+			}
+			return n;
+		}
+		
+		doh._jumpToLog = function(e){
+			//console.log(e);
+			
+			var node = findTarget(e?e.target:window.event.srcElement);
+			if(!node){
+				return;
+			}
+			var _t = Number(node.getAttribute('_target'));
+			var lb = byId("logBody");
+			if(_t>=lb.childNodes.length){
+				return;
+			}
+			var t = lb.childNodes[_t];
+			t.scrollIntoView();
+			if(window.dojo){
+				//t.parentNode.parentNode is <div class="tabBody">, only it has a explicitly set background-color,
+				//all children of it are transparent
+				var bgColor = dojo.style(t.parentNode.parentNode,'backgroundColor');
+				//node.parentNode is the tr which has background-color set explicitly
+				var hicolor = dojo.style(node.parentNode,'backgroundColor');
+				var unhilight = dojo.animateProperty({
+					node: t,
+					duration: 500,
+					properties:
+					{
+						backgroundColor: { start:hicolor, end: bgColor }
+					},
+					onEnd: function(){
+						t.style.backgroundColor="";
+					}
+				});
+				var hilight = dojo.animateProperty({
+					node: t,
+					duration: 500,
+					properties:
+					{
+						backgroundColor: { start:bgColor, end: hicolor }
+					},
+					onEnd: function(){
+						unhilight.play();
+					}
+				});
+				hilight.play();
+			}
+		};
+
+		doh._jumpToSuite = function(e){
+			var node = findTarget(e ? e.target : window.event.srcElement);
+			if(!node){
+				return;
+			}
+			var _g = node.getAttribute('_target');
+			var gn = getGroupNode(_g);
+			if(!gn){
+				return;
+			}
+			gn.scrollIntoView();
+		};
+
+		doh._init = (function(oi){
+			return function(){
+				var lb = byId("logBody");
+				if(lb){
+					// clear the console before each run
+					while(lb.firstChild){
+						lb.removeChild(lb.firstChild);
+					}
+					_loggedMsgLen = 0;
+				}
+				this._totalTime = 0;
+				this._suiteCount = 0;
+				oi.apply(doh, arguments);
+			}
+		})(doh._init);
+
+		doh._setupGroupForRun = (function(os){
+			//overload _setupGroupForRun to record which log line to jump to when a suite is clicked
+			return function(groupName){
+				var tg = doh._groups[groupName];
+				doh._curTestCount = tg.length;
+				doh._curGroupCount = 1;
+				var gn = getGroupNode(groupName);
+				if(gn){
+					//two lines will be added, scroll the second line into view
+					gn.getElementsByTagName("td")[2].setAttribute('_target',_loggedMsgLen+1);
+				}
+				os.apply(doh,arguments);
+			}
+		})(doh._setupGroupForRun);
+		
+		doh._report = (function(or){
+			//overload _report to insert a tfoot
+			return function(){
+				var tb = byId("testList");
+				if(tb){
+					var tfoots=tb.getElementsByTagName('tfoot');
+					if(tfoots.length){
+						tb.removeChild(tfoots[0]);
+					}
+					var foot = tb.createTFoot();
+					var row = foot.insertRow(-1);
+					row.className = 'inProgress';
+					var cell=row.insertCell(-1);
+					cell.colSpan=2;
+					cell.innerHTML="Result";
+					cell = row.insertCell(-1);
+					cell.innerHTML=this._testCount+" tests in "+this._groupCount+" groups /<span class='failure'>"+this._errorCount+"</span> errors, <span class='failure'>"+this._failureCount+"</span> failures";
+					cell.setAttribute('_target',_loggedMsgLen+1);
+					row.insertCell(-1).innerHTML=formatTime(doh._totalTime);
+				}
+				
+				//This location can do the final performance rendering for the results
+				//of any performance tests.
+				var plotResults = null;
+				var standby;
+				if(doh.perfTestResults){
+					if(window.dojo){
+						//If we have dojo and here are perf tests results, 
+						//well, we'll use the dojo charting functions
+						dojo.require("dojox.charting.Chart2D");
+						dojo.require("dojox.charting.DataChart");
+						dojo.require("dojox.charting.plot2d.Scatter");
+						dojo.require("dojox.charting.plot2d.Lines");
+						dojo.require("dojo.data.ItemFileReadStore");
+						plotResults = doh._dojoPlotPerfResults;
+					}else{
+						plotResults = doh._asciiPlotPerfResults;
+					}
+					try{
+						var g;
+						var pBody = byId("perfTestsBody");
+						var chartsToRender = [];
+
+						if(doh.perfTestResults){
+							doh.showPerfTestsPage();
+						}
+						for(g in doh.perfTestResults){
+							var grp = doh.perfTestResults[g];
+							var hdr = document.createElement("h1");
+							hdr.appendChild(document.createTextNode("Group: " + g));
+							pBody.appendChild(hdr);
+							var ind = document.createElement("blockquote");
+							pBody.appendChild(ind);
+							var f;
+							for(f in grp){
+								var fResults = grp[f];
+								if(!fResults){ continue; }
+								var fhdr = document.createElement("h3");
+								fhdr.appendChild(document.createTextNode("TEST: " + f));
+								fhdr.style.textDecoration = "underline";
+								ind.appendChild(fhdr);
+								var div = document.createElement("div");
+								ind.appendChild(div);
+
+								//Figure out the basic info
+								var results = "<b>TRIAL SIZE: </b>"  + fResults.trials[0].testIterations + " iterations<br>" +
+									"<b>NUMBER OF TRIALS: </b>" + fResults.trials.length + "<br>";
+
+								//Figure out the average test pass cost.
+								var i;
+								var iAvgArray = [];
+								var tAvgArray = [];
+								for(i = 0; i < fResults.trials.length; i++){
+									iAvgArray.push(fResults.trials[i].average);
+									tAvgArray.push(fResults.trials[i].executionTime);
+								}
+								results += "<b>AVERAGE TRIAL EXECUTION TIME: </b>" + doh.average(tAvgArray).toFixed(10) + "ms.<br>";
+								results += "<b>MAXIMUM TEST ITERATION TIME: </b>" + doh.max(iAvgArray).toFixed(10) + "ms.<br>";
+								results += "<b>MINIMUM TEST ITERATION TIME: </b>" + doh.min(iAvgArray).toFixed(10) + "ms.<br>";
+								results += "<b>AVERAGE TEST ITERATION TIME: </b>" + doh.average(iAvgArray).toFixed(10) + "ms.<br>";
+								results += "<b>MEDIAN TEST ITERATION TIME: </b>" + doh.median(iAvgArray).toFixed(10) + "ms.<br>";
+								results += "<b>VARIANCE TEST ITERATION TIME: </b>" + doh.variance(iAvgArray).toFixed(10) + "ms.<br>";
+								results += "<b>STANDARD DEVIATION ON TEST ITERATION TIME: </b>" + doh.standardDeviation(iAvgArray).toFixed(10) + "ms.<br>";
+
+								//Okay, attach it all in.
+								div.innerHTML = results;
+
+								div = document.createElement("div");
+								div.innerHTML = "<h3>Average Test Execution Time (in milliseconds, with median line)</h3>";
+								ind.appendChild(div);
+								div = document.createElement("div");
+								dojo.style(div, "width", "600px");
+								dojo.style(div, "height", "250px");
+								ind.appendChild(div);
+								chartsToRender.push({
+									div: div,
+									title: "Average Test Execution Time",
+									data: iAvgArray
+								});
+
+								div = document.createElement("div");
+								div.innerHTML = "<h3>Average Trial Execution Time (in milliseconds, with median line)</h3>";
+								ind.appendChild(div);
+								div = document.createElement("div");
+								dojo.style(div, "width", "600px");
+								dojo.style(div, "height", "250px");
+								ind.appendChild(div);
+								chartsToRender.push({
+									div: div,
+									title: "Average Trial Execution Time",
+									data: tAvgArray
+								});
+							}
+						}
+
+						//Lazy-render these to give the browser time and not appear locked.
+						var delayedRenders = function() {
+							if(chartsToRender.length){
+								var chartData = chartsToRender.shift();
+								plotResults(chartData.div, chartData.title, chartData.data);
+							}
+							setTimeout(delayedRenders, 50);
+						};
+						setTimeout(delayedRenders, 150);
+					}catch(e){
+						doh.debug(e);
+					}
+				}
+				or.apply(doh,arguments);
+			}
+		})(doh._report);
+		
+		doh.error = undefined;
+		if(this["opera"] && opera.postError){
+			doh.debug = function(){
+				var msg = "";
+				for(var x=0; x<arguments.length; x++){
+					msg += " "+arguments[x];
+				}
+				sendToLogPane([msg]);
+				opera.postError("DEBUG:"+msg);
+			}
+		}else if(window["console"]){
+			if(console.error){
+				doh.error = function(){
+					sendToLogPane.call(window, arguments);
+					console.error.apply(console, arguments);
+				};
+			} 
+			if(console.debug){
+				doh.debug = function(){
+					sendToLogPane.call(window, arguments);
+					console.debug.apply(console, arguments);
+				};
+			}else if(console.info){
+				doh.debug = function(){
+					sendToLogPane.call(window, arguments);
+					console.info.apply(console, arguments);
+				};
+			}else{
+				doh.debug = function(){
+					var msg = "";
+					for(var x=0; x<arguments.length; x++){
+						msg += " "+arguments[x];
+					}
+					sendToLogPane([msg]);
+					console.log("DEBUG:"+msg);
+				};
+			}
+		}else{
+			doh.debug = function(){
+				sendToLogPane.call(window, arguments);
+			}
+		}
+		doh.error = doh.error || doh.debug;
+
+		var loaded = false;
+		var groupTemplate = null;
+		var testTemplate = null;
+
+		var groupNodes = {};
+
+		var _groupTogglers = {};
+
+		var _getGroupToggler = function(group, toggle){
+			if(_groupTogglers[group]){ return _groupTogglers[group]; }
+			var rolledUp = true;
+			return (_groupTogglers[group] = function(evt, forceOpen){
+				var nodes = groupNodes[group].__items;
+				var x;
+				if(rolledUp||forceOpen){
+					rolledUp = false;
+					for(x=0; x<nodes.length; x++){
+						nodes[x].style.display = "";
+					}
+					toggle.innerHTML = "▼";
+				}else{
+					rolledUp = true;
+					for(x=0; x<nodes.length; x++){
+						nodes[x].style.display = "none";
+					}
+					toggle.innerHTML = "►";
+				}
+			});
+		};
+
+		var addGroupToList = function(group){
+			if(!byId("testList")){ return; }
+			var tb = byId("testList").tBodies[0];
+			var tg = groupTemplate.cloneNode(true);
+			var tds = tg.getElementsByTagName("td");
+			var toggle = tds[0];
+			toggle.onclick = _getGroupToggler(group, toggle);
+			var cb = tds[1].getElementsByTagName("input")[0];
+			cb.group = group;
+			cb.onclick = function(evt){
+				doh._groups[group].skip = (!this.checked);
+			}
+			tds[2].innerHTML = "<div class='testGroupName'>"+group+"</div><div style='width:0;'> </div>";
+			tds[3].innerHTML = "";
+
+			tb.appendChild(tg);
+			return tg;
+		}
+
+		var addFixtureToList = function(group, fixture){
+			if(!testTemplate){ return; }
+			var cgn = groupNodes[group];
+			if(!cgn["__items"]){ cgn.__items = []; }
+			var tn = testTemplate.cloneNode(true);
+			var tds = tn.getElementsByTagName("td");
+
+			tds[2].innerHTML = fixture.name;
+			tds[3].innerHTML = "";
+
+			var nn = (cgn.__lastFixture||cgn.__groupNode).nextSibling;
+			if(nn){
+				nn.parentNode.insertBefore(tn, nn);
+			}else{
+				cgn.__groupNode.parentNode.appendChild(tn);
+			}
+			// FIXME: need to make group display toggleable!!
+			tn.style.display = "none";
+			cgn.__items.push(tn);
+			return (cgn.__lastFixture = tn);
+		}
+
+		var getFixtureNode = function(group, fixture){
+			if(groupNodes[group]){
+				return groupNodes[group][fixture.name];
+			}
+			return null;
+		}
+
+		var getGroupNode = function(group){
+			if(groupNodes[group]){
+				return groupNodes[group].__groupNode;
+			}
+			return null;
+		}
+
+		var updateBacklog = [];
+		doh._updateTestList = function(group, fixture, unwindingBacklog){
+			if(!loaded){
+				if(group && fixture){
+					updateBacklog.push([group, fixture]);
+				}
+				return;
+			}else if(updateBacklog.length && !unwindingBacklog){
+				var tr;
+				while((tr=updateBacklog.shift())){
+					doh._updateTestList(tr[0], tr[1], true);
+				}
+			}
+			if(group && fixture){
+				if(!groupNodes[group]){
+					groupNodes[group] = {
+						"__groupNode": addGroupToList(group)
+					};
+				}
+				if(!groupNodes[group][fixture.name]){
+					groupNodes[group][fixture.name] = addFixtureToList(group, fixture)
+				}
+			}
+		}
+
+		doh._testRegistered = doh._updateTestList;
+
+		doh._groupStarted = function(group){
+			if(this._suiteCount == 0){
+				this._runedSuite = 0;
+				this._currentGlobalProgressBarWidth = 0;
+				this._suiteCount = this._testCount;
+			}
+			// console.debug("_groupStarted", group);
+			if(doh._inGroup != group){
+				doh._groupTotalTime = 0;
+				doh._runed = 0;
+				doh._inGroup = group;
+				this._runedSuite++;
+			}
+			var gn = getGroupNode(group);
+			if(gn){
+				gn.className = "inProgress";
+			}
+		}
+
+		doh._groupFinished = function(group, success){
+			// console.debug("_groupFinished", group);
+			var gn = getGroupNode(group);
+			if(gn && doh._inGroup == group){
+				doh._totalTime += doh._groupTotalTime;
+				gn.getElementsByTagName("td")[3].innerHTML = formatTime(doh._groupTotalTime);
+				gn.getElementsByTagName("td")[2].lastChild.className = "";
+				doh._inGroup = null;
+				//doh._runedSuite++;
+				var failure = doh._updateGlobalProgressBar(this._runedSuite/this._groupCount,success,group);
+				gn.className = failure ? "failure" : "success";
+				//doh._runedSuite--;
+				doh._currentGlobalProgressBarWidth = parseInt(this._runedSuite/this._groupCount*10000)/100;
+				//byId("progressOuter").style.width = parseInt(this._runedSuite/this._suiteCount*100)+"%";
+			}
+			if(doh._inGroup == group){
+				this.debug("Total time for GROUP \"",group,"\" is ",formatTime(doh._groupTotalTime));
+			}
+		}
+
+		doh._testStarted = function(group, fixture){
+			// console.debug("_testStarted", group, fixture.name);
+			var fn = getFixtureNode(group, fixture);
+			if(fn){
+				fn.className = "inProgress";
+			}
+		}
+
+		var _nameTimes = {};
+		var _playSound = function(name){
+			if(byId("hiddenAudio") && byId("audio") && byId("audio").checked){
+				// console.debug("playing:", name);
+				var nt = _nameTimes[name];
+				// only play sounds once every second or so
+				if((!nt)||(((new Date)-nt) > 700)){
+					_nameTimes[name] = new Date();
+					var tc = document.createElement("span");
+					byId("hiddenAudio").appendChild(tc);
+					tc.innerHTML = '<embed src="_sounds/'+name+'.wav" autostart="true" loop="false" hidden="true" width="1" height="1"></embed>';
+				}
+			}
+		}
+
+		doh._updateGlobalProgressBar = function(p,success,group){
+			var outerContainer=byId("progressOuter");
+					
+			var gdiv=outerContainer.childNodes[doh._runedSuite-1];
+			if(!gdiv){
+				gdiv=document.createElement('div');
+				outerContainer.appendChild(gdiv);
+				gdiv.className='success';
+				gdiv.setAttribute('_target',group);
+			}
+			if(!success && !gdiv._failure){
+				gdiv._failure=true;
+				gdiv.className='failure';
+				if(group){
+					gdiv.setAttribute('title','failed group '+group);
+				}
+			}
+			var tp=parseInt(p*10000)/100;
+			gdiv.style.width = (tp-doh._currentGlobalProgressBarWidth)+"%";
+			return gdiv._failure;
+		}
+		doh._testFinished = function(group, fixture, success){
+			var fn = getFixtureNode(group, fixture);
+			var elapsed = fixture.endTime-fixture.startTime;
+			if(fn){
+				fn.getElementsByTagName("td")[3].innerHTML = formatTime(elapsed);
+				fn.className = (success) ? "success" : "failure";
+				fn.getElementsByTagName("td")[2].setAttribute('_target', _loggedMsgLen);
+				if(!success){
+					_playSound("doh");
+					var gn = getGroupNode(group);
+					if(gn){
+						gn.className = "failure";
+						_getGroupToggler(group)(null, true);
+					}
+				}
+			}
+			if(doh._inGroup == group){
+				var gn = getGroupNode(group);
+				doh._runed++;
+				if(gn && doh._curTestCount){
+					var p = doh._runed/doh._curTestCount;
+					var groupfail = this._updateGlobalProgressBar((doh._runedSuite+p-1)/doh._groupCount,success,group);
+					
+					var pbar = gn.getElementsByTagName("td")[2].lastChild;
+					pbar.className = groupfail?"failure":"success";
+					pbar.style.width = parseInt(p*100)+"%";
+					gn.getElementsByTagName("td")[3].innerHTML = parseInt(p*10000)/100+"%";
+				}
+			}
+			this._groupTotalTime += elapsed;
+			this.debug((success ? "PASSED" : "FAILED"), "test:", fixture.name, elapsed, 'ms');
+		}
+
+		// FIXME: move implementation to _browserRunner?
+		doh.registerUrl = function(	/*String*/ group, 
+										/*String*/ url, 
+										/*Integer*/ timeout){
+			var tg = new String(group);
+			this.register(group, {
+				name: url,
+				setUp: function(){
+					doh.currentGroupName = tg;
+					doh.currentGroup = this;
+					doh.currentUrl = url;
+					this.d = new doh.Deferred();
+					doh.currentTestDeferred = this.d;
+					doh.showTestPage();
+					byId("testBody").src = url;
+				},
+				timeout: timeout||10000, // 10s
+				// timeout: timeout||1000, // 10s
+				runTest: function(){
+					// FIXME: implement calling into the url's groups here!!
+					return this.d;
+				},
+				tearDown: function(){
+					doh.currentGroupName = null;
+					doh.currentGroup = null;
+					doh.currentTestDeferred = null;
+					doh.currentUrl = null;
+					// this.d.errback(false);
+					// byId("testBody").src = "about:blank";
+					doh.showLogPage();
+				}
+			});
+		}
+
+		// 
+		// Utility code for runner.html
+		//
+		// var isSafari = navigator.appVersion.indexOf("Safari") >= 0;
+		var tabzidx = 1;
+		var _showTab = function(toShow, toHide){
+			// FIXME: I don't like hiding things this way.
+			var i;
+			for(i = 0; i < toHide.length; i++){
+				var node = byId(toHide[i]);
+				if(node){
+					node.style.display="none";
+				}
+			}
+			toShow = byId(toShow);
+			if(toShow){
+				with(toShow.style){
+					display = "";
+					zIndex = ++tabzidx;
+				}
+			}
+		}
+
+		doh.showTestPage = function(){
+			_showTab("testBody", ["logBody", "perfTestsBody"]);
+		}
+
+		doh.showLogPage = function(){
+			_showTab("logBody", ["testBody", "perfTestsBody"]);
+		}
+
+		doh.showPerfTestsPage = function(){
+			_showTab("perfTestsBody", ["testBody", "logBody"]);
+		}
+
+		var runAll = true;
+		doh.toggleRunAll = function(){
+			// would be easier w/ query...sigh
+			runAll = !runAll;
+			if(!byId("testList")){ return; }
+			var tb = byId("testList").tBodies[0];
+			var inputs = tb.getElementsByTagName("input");
+			var x=0; var tn;
+			while((tn=inputs[x++])){
+				tn.checked = runAll;
+				doh._groups[tn.group].skip = (!runAll);
+			}
+		}
+
+		var listHeightTimer = null;
+		var setListHeight = function(){
+			if(listHeightTimer){
+				clearTimeout(listHeightTimer);
+			}
+			var tl = byId("testList");
+			if(!tl){ return; }
+			listHeightTimer = setTimeout(function(){
+				tl.style.display = "none";
+				tl.style.display = "";
+
+			}, 10);
+		}
+
+		_addOnEvt("resize", setListHeight);
+		_addOnEvt("load", setListHeight);
+		_addOnEvt("load", function(){
+			if(loaded){ return; }
+			loaded = true;
+			groupTemplate = byId("groupTemplate");
+			if(!groupTemplate){ 
+				// make sure we've got an ammenable DOM structure
+				return;
+			}
+			groupTemplate.parentNode.removeChild(groupTemplate);
+			groupTemplate.style.display = "";
+			testTemplate = byId("testTemplate");
+			testTemplate.parentNode.removeChild(testTemplate);
+			testTemplate.style.display = "";
+			doh._updateTestList();
+		});
+
+		_addOnEvt("load", 
+			function(){
+				// let robot code run if it gets to this first
+				var __onEnd = doh._onEnd;
+				doh._onEnd = function(){
+					__onEnd.apply(doh, arguments);
+					if(doh._failureCount == 0){
+						doh.debug("WOOHOO!!");
+						_playSound("woohoo");
+					}else{
+						console.debug("doh._failureCount:", doh._failureCount);
+					}
+					if(byId("play")){
+						toggleRunning();
+					}
+				}
+				if(!byId("play")){ 
+					// make sure we've got an amenable DOM structure
+					return;
+				}
+				var isRunning = false;
+				var toggleRunning = function(){
+					// ugg, this would be so much better w/ dojo.query()
+					if(isRunning){
+						byId("play").style.display = byId("pausedMsg").style.display = "";
+						byId("playingMsg").style.display = byId("pause").style.display = "none";
+						isRunning = false;
+					}else{
+						byId("play").style.display = byId("pausedMsg").style.display = "none";
+						byId("playingMsg").style.display = byId("pause").style.display = "";
+						isRunning = true;
+					}
+				}
+				doh.run = (function(oldRun){
+					return function(){
+						if(!doh._currentGroup){
+							toggleRunning();
+						}
+						return oldRun.apply(doh, arguments);
+					}
+				})(doh.run);
+				var btns = byId("toggleButtons").getElementsByTagName("span");
+				var node; var idx=0;
+				while((node=btns[idx++])){
+					node.onclick = toggleRunning;
+				}
+
+				//Performance report generating functions!
+				doh._dojoPlotPerfResults = function(div, name, dataArray) {
+					var median = doh.median(dataArray);
+					var medarray = [];
+
+					var i;
+					for(i = 0; i < dataArray.length; i++){
+						medarray.push(median);
+					}
+
+					var data = {
+						label: "name",
+						items: [
+							{name: name, trials: dataArray},
+							{name: "Median", trials: medarray}
+						]
+					};
+					var ifs = new dojo.data.ItemFileReadStore({data: data});
+
+					var min = Math.floor(doh.min(dataArray));
+					var max = Math.ceil(doh.max(dataArray));
+					var step = (max - min)/10;
+
+					//Lets try to pad out the bottom and top a bit
+					//Then recalc the step.
+					if(min > 0){
+						min = min - step;
+						if(min < 0){
+							min = 0;
+						}
+						min = Math.floor(min);
+					}
+					if(max > 0){
+						max = max + step;
+						max = Math.ceil(max);
+					}
+					step = (max - min)/10;
+
+					var chart = new dojox.charting.DataChart(div, {
+						type: dojox.charting.plot2d.Lines,
+						displayRange:dataArray.length,
+						xaxis: {min: 1, max: dataArray.length, majorTickStep: Math.ceil((dataArray.length - 1)/10), htmlLabels: false},
+						yaxis: {min: min, max: max, majorTickStep: step, vertical: true, htmlLabels: false}
+					});
+					chart.setStore(ifs, {name:"*"}, "trials");
+				};
+
+				doh._asciiPlotPerfResults = function(){
+					//TODO:  Implement!
+				};
+			}
+		);
+	}else{
+		// we're in an iframe environment. Time to mix it up a bit.
+
+		_doh = window.parent.doh;
+		var _thisGroup = _doh.currentGroupName;
+		var _thisUrl = _doh.currentUrl;
+		if(_thisGroup){
+			doh._testRegistered = function(group, tObj){
+				_doh._updateTestList(_thisGroup, tObj);
+			}
+			doh._onEnd = function(){
+				_doh._errorCount += doh._errorCount;
+				_doh._failureCount += doh._failureCount;
+				_doh._testCount += doh._testCount;
+				// should we be really adding raw group counts?
+				//_doh._groupCount += doh._groupCount;
+				_doh.currentTestDeferred.callback(true);
+			}
+			var otr = doh._getTestObj;
+			doh._getTestObj = function(){
+				var tObj = otr.apply(doh, arguments);
+				tObj.name = _thisUrl+"::"+arguments[0]+"::"+tObj.name;
+				return tObj;
+			}
+			doh.debug = doh.hitch(_doh, "debug");
+			doh.registerUrl = doh.hitch(_doh, "registerUrl");
+			doh._testStarted = function(group, fixture){
+				_doh._testStarted(_thisGroup, fixture);
+			}
+			doh._testFinished = function(g, f, s){
+				_doh._testFinished(_thisGroup, f, s);
+
+				//Okay, there may be performance info we need to filter back
+				//to the parent, so do that here.
+				if(doh.perfTestResults){
+					try{
+						gName = g.toString();
+						var localFName = f.name;
+						while(localFName.indexOf("::") >= 0){
+							localFName = localFName.substring(localFName.indexOf("::") + 2, localFName.length);
+						}
+						if(!_doh.perfTestResults){
+							_doh.perfTestResults = {};
+						}
+						if(!_doh.perfTestResults[gName]){
+							_doh.perfTestResults[gName] = {};
+						}
+						_doh.perfTestResults[gName][f.name] = doh.perfTestResults[gName][localFName];
+					}catch (e){
+						doh.debug(e);
+					}
+				}
+			}
+			doh._groupStarted = function(g){
+				if(!this._setParent){
+					_doh._curTestCount = this._testCount;
+					_doh._curGroupCount = this._groupCount;
+					this._setParent = true;
+				}
+			}
+			doh._report = function(){
+			};
+		}
+	}
+
+})();
diff --git a/util/doh/_rhinoRunner.js b/util/doh/_rhinoRunner.js
new file mode 100644
index 0000000..53f20fb
--- /dev/null
+++ b/util/doh/_rhinoRunner.js
@@ -0,0 +1,18 @@
+if(this["dojo"]){
+	dojo.provide("doh._rhinoRunner");
+}
+
+doh.debug = print;
+doh.error = print;
+
+// Override the doh._report method to make it quit with an 
+// appropriate exit code in case of test failures.
+(function(){
+	var oldReport = doh._report;
+	doh._report = function(){
+		oldReport.apply(doh, arguments);
+		if(this._failureCount > 0 || this._errorCount > 0){
+			quit(1);
+		}
+	}
+})();
diff --git a/util/doh/_sounds/LICENSE b/util/doh/_sounds/LICENSE
new file mode 100644
index 0000000..e8e11d4
--- /dev/null
+++ b/util/doh/_sounds/LICENSE
@@ -0,0 +1,10 @@
+License Disclaimer:
+
+All contents of this directory are Copyright (c) the Dojo Foundation, with the
+following exceptions:
+-------------------------------------------------------------------------------
+
+woohoo.wav, doh.wav, dohaaa.wav:
+	* Copyright original authors.
+	  Copied from:
+	  	http://simpson-homer.com/homer-simpson-soundboard.html
diff --git a/util/doh/_sounds/doh.wav b/util/doh/_sounds/doh.wav
new file mode 100644
index 0000000..5e8a583
Binary files /dev/null and b/util/doh/_sounds/doh.wav differ
diff --git a/util/doh/_sounds/dohaaa.wav b/util/doh/_sounds/dohaaa.wav
new file mode 100644
index 0000000..2220921
Binary files /dev/null and b/util/doh/_sounds/dohaaa.wav differ
diff --git a/util/doh/_sounds/woohoo.wav b/util/doh/_sounds/woohoo.wav
new file mode 100644
index 0000000..eb69217
Binary files /dev/null and b/util/doh/_sounds/woohoo.wav differ
diff --git a/util/doh/robot.js b/util/doh/robot.js
new file mode 100644
index 0000000..6260ce0
--- /dev/null
+++ b/util/doh/robot.js
@@ -0,0 +1,540 @@
+if(window["dojo"]){
+	dojo.provide("doh.robot");
+	dojo.experimental("doh.robot");
+	dojo.require("doh.runner");
+}else if(!doh["robot"]){
+	doh.robot={};
+}
+
+if(!doh.robot["_robotLoaded"]){
+(function(){
+
+	// loading state
+	var _robot = null;
+
+	var isSecure = (function(){
+		var key = Math.random();
+		return function(fcn){
+			return key;
+		};
+	})();
+
+	// no dojo available
+	// hijack doh.run instead
+	var _run = doh.run;
+	doh.run = function(){
+		if(!doh.robot._runsemaphore.unlock()){
+			// hijack doh._onEnd to clear the applet
+			// have to do it here because _browserRunner sets it in onload in standalone case
+			var __onEnd = doh._onEnd;
+			doh._onEnd = function(){
+				doh.robot.killRobot();
+				doh._onEnd = __onEnd;
+				doh._onEnd();
+			};
+			doh.robot.startRobot();
+		}
+	};
+
+	var cleanup=function(){
+		doh.robot.killRobot();
+	}
+	if(typeof dojo !== 'undefined'){
+		dojo.addOnUnload(cleanup)
+	}else{
+		window.onunload=cleanup;
+	}
+	var _keyPress = function(/*Number*/ charCode, /*Number*/ keyCode, /*Boolean*/ alt, /*Boolean*/ ctrl, /*Boolean*/ shift, /*Boolean*/ meta, /*Integer, optional*/ delay, /*Boolean*/ async){
+		// internal function to type one non-modifier key
+
+		// typecasting Numbers helps Sun's IE plugin lookup methods that take int arguments
+
+		// otherwise JS will send a double and Sun will complain
+		_robot.typeKey(isSecure(), Number(charCode), Number(keyCode), Boolean(alt), Boolean(ctrl), Boolean(shift), Boolean(meta), Number(delay||0), Boolean(async||false));
+	};
+
+	doh.robot = {
+	_robotLoaded: true,
+	_robotInitialized: false,
+	// prime the event pump for fast browsers like Google Chrome - it's so fast, it doesn't stop to listen for keypresses!
+	_spaceReceived: false,
+	_primePump: false,
+	
+	_killApplet: function(){}, // overridden by Robot.html
+
+	killRobot: function(){
+		if(doh.robot._robotLoaded){
+			doh.robot._robotLoaded = false;
+			document.documentElement.className = document.documentElement.className.replace(/ ?dohRobot/, "");
+			doh.robot._killApplet();
+		}
+	},
+
+	// Robot init methods
+
+	// controls access to doh.run
+	// basically, doh.run takes two calls to start the robot:
+	// one (or more after the robot loads) from the test page
+	// one from either the applet or an error condition
+	_runsemaphore: {
+		lock:["lock"],
+		unlock:function(){
+			try{
+				return this.lock.shift();
+			}catch(e){
+				return null;
+			}
+		}	
+	},
+	
+	startRobot: function(){
+		//startRobot should be called to initialize the robot (after the java applet is loaded).
+		//one good place to do this is in a dojo.addOnLoad handler. This function will be called
+		//automatically if it is not already called when doh.run() is invoked.
+		if(!this._robotInitialized){
+			this._robotInitialized = true;
+			// if the iframe requested the applet and got a 404, then _robot is obviously unavailable
+			// at least run the non-robot tests!
+			if(doh.robot._appletDead){
+				doh.robot._onKeyboard();
+			}else{
+				_robot._callLoaded(isSecure());
+			}
+		}
+	},
+	_initRobot: function(r){
+		// called from Robot
+		// Robot calls _initRobot in its startup sequence
+
+		// Prevent rerunning the whole test (see #8958 for details)
+		if(doh._initRobotCalled){ return; }
+		doh._initRobotCalled = true;
+
+		// add dohRobot class to HTML element so tests can use that in CSS rules if desired
+		document.documentElement.className += " dohRobot";
+		window.scrollTo(0, 0);
+//		document.documentElement.scrollTop = document.documentElement.scrollLeft = 0;
+		_robot = r;
+		_robot._setKey(isSecure());
+		// lazy load
+		doh.run();
+	},
+
+	// some utility functions to help the iframe use private variables
+	_run: function(frame){
+		frame.style.visibility = "hidden";
+		doh.run = _run;
+		doh.run();
+	},
+
+	_initKeyboard: function(){
+		_robot._initKeyboard(isSecure());
+	},
+
+	_initWheel: function(){
+		_robot._initWheel(isSecure());
+	},
+
+	_setDocumentBounds: function(docScreenX, docScreenY){
+		var robotView = document.getElementById("dohrobotview");
+		_robot.setDocumentBounds(isSecure(), Number(docScreenX), Number(docScreenY), Number(robotView.offsetLeft), Number(robotView.offsetTop));
+	},
+
+	_notified: function(keystring){
+		_robot._notified(isSecure(), keystring);
+	},
+
+	_time:0,
+
+	// if the applet is 404 or cert is denied, this becomes true and kills tests
+	_appletDead:false,
+
+	_assertRobot:function(){
+		// make sure the applet is there and cert accepted
+		// otherwise, skip the test requesting the robot action
+		if(doh.robot._appletDead){ throw new Error('doh.robot not available; skipping test.'); }
+	},
+
+	_mouseMove: function(/*Number*/ x, /*Number*/ y, /*Boolean*/ absolute, /*Integer, optional*/ duration){
+		if(absolute){
+			var scroll = {y: (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0),
+			x: (window.pageXOffset || (window["dojo"]?dojo._fixIeBiDiScrollLeft(document.documentElement.scrollLeft):undefined) || document.body.scrollLeft || 0)};
+			y -= scroll.y;
+			x -= scroll.x;
+		}
+		_robot.moveMouse(isSecure(), Number(x), Number(y), Number(0), Number(duration||100));
+	},
+
+	// Main doh.robot API
+	sequence:function(/*Function*/ f, /*Integer, optional*/ delay, /*Integer, optional*/ duration){
+		// summary:
+		//		Defer an action by adding it to the robot's incrementally delayed queue of actions to execute.
+		//
+		// f:
+		//		A function containing actions you want to defer.
+		//
+		// delay:
+		//		Delay, in milliseconds, to wait before firing.
+		//		The delay is a delta with respect to the previous automation call.
+		//		For example, the following code ends after 600ms:
+		//			doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms
+		//			doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all
+		//
+		// duration:
+		//		Delay to wait after firing.
+		//
+
+		delay = delay || 1;
+		doh.robot._time += delay;
+		setTimeout(function(){
+			doh.robot._time -= delay;
+			f();
+			if(duration){
+				setTimeout(function(){
+					doh.robot._time -= duration;
+				}, duration);
+			}
+		}, doh.robot._time);
+		if(duration){
+			doh.robot._time += duration;
+		}
+	},
+
+	typeKeys: function(/*String||Number*/ chars, /*Integer, optional*/ delay, /*Integer, optional*/ duration){
+		// summary:
+		//		Types a string of characters in order, or types a dojo.keys.* constant.
+		//
+		// description:
+		// 		Types a string of characters in order, or types a dojo.keys.* constant.
+		// 		Example: doh.robot.typeKeys("dijit.ed", 500);
+		//
+		// chars:
+		//		String of characters to type, or a dojo.keys.* constant
+		//
+		// delay:
+		//		Delay, in milliseconds, to wait before firing.
+		//		The delay is a delta with respect to the previous automation call.
+		//		For example, the following code ends after 600ms:
+		//			doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms
+		//			doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all
+		//
+		// duration:
+		//		Time, in milliseconds, to spend pressing all of the keys.
+		//		The default is (string length)*50 ms.
+		//
+
+		this._assertRobot();
+		this.sequence(function(){
+			var isNum = typeof(chars) == Number;
+			duration=duration||(isNum?50:chars.length*50);
+			if(isNum){
+				_keyPress(chars, chars, false, false, false, false, 0);
+			}else if(chars.length){
+				_keyPress(chars.charCodeAt(0), 0, false, false, false, false, 0);
+				for(var i = 1; i<chars.length; i++){
+					_keyPress(chars.charCodeAt(i), 0, false, false, false, false, Math.max(Math.floor(duration/chars.length)-20, 0)); // 20ms is fudge for processing time until robot handles wall clock
+				}
+			}
+		}, delay, duration);
+	},
+
+	keyPress: function(/*Integer*/ charOrCode, /*Integer, optional*/ delay, /*Object*/ modifiers, /*Boolean*/ asynchronous){
+		// summary:
+		//		Types a key combination, like SHIFT-TAB.
+		//
+		// description:
+		// 		Types a key combination, like SHIFT-TAB.
+		// 		Example: to press shift-tab immediately, call doh.robot.keyPress(dojo.keys.TAB, 0, {shift:true})
+		//
+		// charOrCode:
+		//		char/JS keyCode/dojo.keys.* constant for the key you want to press
+		//
+		// delay:
+		//		Delay, in milliseconds, to wait before firing.
+		//		The delay is a delta with respect to the previous automation call.
+		//		For example, the following code ends after 600ms:
+		//			doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms
+		//			doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all
+		//
+		// modifiers:
+		//		JSON object that represents all of the modifier keys being pressed.
+		//		It takes the following Boolean attributes:
+		//			- shift
+		//			- alt
+		//			- ctrl
+		//			- meta
+		//
+		// asynchronous:
+		//		If true, the delay happens asynchronously and immediately, outside of the browser's JavaScript thread and any previous calls.
+		//		This is useful for interacting with the browser's modal dialogs.
+		//
+
+		this._assertRobot();
+		if(!modifiers){
+			modifiers = {alt:false, ctrl:false, shift:false, meta:false};
+		}else{
+			// normalize modifiers
+			var attrs = ["alt", "ctrl", "shift", "meta"];
+			for(var i = 0; i<attrs.length; i++){
+				if(!modifiers[attrs[i]]){
+					modifiers[attrs[i]] = false;
+				}
+			}
+		}
+		var isChar = typeof(charOrCode)=="string";
+		if(asynchronous){
+			_keyPress(isChar?charOrCode.charCodeAt(0):0, isChar?0:charOrCode, modifiers.alt, modifiers.ctrl, modifiers.shift, modifiers.meta, delay, true);
+			return;
+		}
+		this.sequence(function(){
+			_keyPress(isChar?charOrCode.charCodeAt(0):0, isChar?0:charOrCode, modifiers.alt, modifiers.ctrl, modifiers.shift, modifiers.meta, 0);
+		},delay);
+	},
+
+	keyDown: function(/*Integer*/ charOrCode, /*Integer, optional*/ delay){
+		// summary:
+		//		Holds down a single key, like SHIFT or 'a'.
+		//
+		// description:
+		// 		Holds down a single key, like SHIFT or 'a'.
+		// 		Example: to hold down the 'a' key immediately, call doh.robot.keyDown('a')
+		//
+		// charOrCode:
+		//		char/JS keyCode/dojo.keys.* constant for the key you want to hold down
+		//		Warning: holding down a shifted key, like 'A', can have unpredictable results.
+		//
+		// delay:
+		//		Delay, in milliseconds, to wait before firing.
+		//		The delay is a delta with respect to the previous automation call.
+		//		For example, the following code ends after 600ms:
+		//			doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms
+		//			doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all
+		//
+
+		this._assertRobot();
+		this.sequence(function(){
+			var isChar = typeof(charOrCode)=="string";
+			_robot.downKey(isSecure(), isChar?charOrCode:0, isChar?0:charOrCode, 0);
+		},delay);
+	},
+
+	keyUp: function(/*Integer*/ charOrCode, /*Integer, optional*/ delay){
+		// summary:
+		//		Releases a single key, like SHIFT or 'a'.
+		//
+		// description:
+		// 		Releases a single key, like SHIFT or 'a'.
+		// 		Example: to release the 'a' key immediately, call doh.robot.keyUp('a')
+		//
+		// charOrCode:
+		//		char/JS keyCode/dojo.keys.* constant for the key you want to release
+		//		Warning: releasing a shifted key, like 'A', can have unpredictable results.
+		//
+		// delay:
+		//		Delay, in milliseconds, to wait before firing.
+		//		The delay is a delta with respect to the previous automation call.
+		//		For example, the following code ends after 600ms:
+		//			doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms
+		//			doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all
+		//
+
+		this._assertRobot();
+		this.sequence(function(){
+			var isChar=typeof(charOrCode)=="string";
+			_robot.upKey(isSecure(), isChar?charOrCode:0, isChar?0:charOrCode, 0);
+		},delay);
+	},
+
+
+	mouseClick: function(/*Object*/ buttons, /*Integer, optional*/ delay){
+		// summary:
+		//		Convenience function to do a press/release.
+		//		See doh.robot.mousePress for more info.
+		//
+		// description:
+		//		Convenience function to do a press/release.
+		//		See doh.robot.mousePress for more info.
+		//
+
+		this._assertRobot();
+		doh.robot.mousePress(buttons, delay);
+		doh.robot.mouseRelease(buttons, 1);
+	},
+
+	mousePress: function(/*Object*/ buttons, /*Integer, optional*/ delay){
+		// summary:
+		// 		Presses mouse buttons.
+		// description:
+		// 		Presses the mouse buttons you pass as true.
+		// 		Example: to press the left mouse button, pass {left:true}.
+		// 		Mouse buttons you don't specify keep their previous pressed state.
+		//
+		// buttons:	JSON object that represents all of the mouse buttons being pressed.
+		//		It takes the following Boolean attributes:
+		//			- left
+		//			- middle
+		//			- right
+		//
+		// delay:
+		//		Delay, in milliseconds, to wait before firing.
+		//		The delay is a delta with respect to the previous automation call.
+		//		For example, the following code ends after 600ms:
+		//			doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms
+		//			doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all
+		//
+
+		this._assertRobot();
+		if(!buttons){ return; }
+		this.sequence(function(){
+			var attrs = ["left", "middle", "right"];
+			for(var i = 0; i<attrs.length; i++){
+				if(!buttons[attrs[i]]){
+					buttons[attrs[i]] = false;
+				}
+			}
+			_robot.pressMouse(isSecure(), Boolean(buttons.left), Boolean(buttons.middle), Boolean(buttons.right), Number(0));
+		},delay);
+	},
+
+	mouseMove: function(/*Number*/ x, /*Number*/ y, /*Integer, optional*/ delay, /*Integer, optional*/ duration, /*Boolean*/ absolute){
+		// summary:
+		// 		Moves the mouse to the specified x,y offset relative to the viewport.
+		//
+		// x:
+		//		x offset relative to the viewport, in pixels, to move the mouse.
+		//
+		// y:
+		//		y offset relative to the viewport, in pixels, to move the mouse.
+		//
+		// delay:
+		//		Delay, in milliseconds, to wait before firing.
+		//		The delay is a delta with respect to the previous automation call.
+		//		For example, the following code ends after 600ms:
+		//			doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms
+		//			doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all
+		//
+		// duration:
+		//		Approximate time Robot will spend moving the mouse
+		//		The default is 100ms. This also affects how many mousemove events will
+		//		be generated, which is the log of the duration.
+		//
+		// absolute:
+		//		Boolean indicating whether the x and y values are absolute coordinates.
+		//		If false, then mouseMove expects that the x,y will be relative to the window. (clientX/Y)
+		//		If true, then mouseMove expects that the x,y will be absolute. (pageX/Y)
+		//
+
+		this._assertRobot();
+		duration = duration||100;
+		this.sequence(function(){
+			doh.robot._mouseMove(x, y, absolute, duration);
+		},delay,duration);
+	},
+
+	mouseRelease: function(/*Object*/ buttons, /*Integer, optional*/ delay){
+		// summary:
+		// 		Releases mouse buttons.
+		//
+		// description:
+		// 		Releases the mouse buttons you pass as true.
+		// 		Example: to release the left mouse button, pass {left:true}.
+		// 		Mouse buttons you don't specify keep their previous pressed state.
+		//		See doh.robot.mousePress for more info.
+		//
+
+		this._assertRobot();
+		if(!buttons){ return; }
+		this.sequence(function(){
+			var attrs = ["left", "middle", "right"];
+			for(var i = 0; i<attrs.length; i++){
+				if(!buttons[attrs[i]]){
+					buttons[attrs[i]] = false;
+				}
+			}
+			_robot.releaseMouse(isSecure(), Boolean(buttons.left), Boolean(buttons.middle), Boolean(buttons.right), Number(0));
+		},delay);
+	},
+
+	// mouseWheelSize: Integer value that determines the amount of wheel motion per unit
+	mouseWheelSize: 1,
+
+	mouseWheel: function(/*Number*/ wheelAmt, /*Integer, optional*/ delay, /*Integer, optional*/ duration){
+		// summary:
+		//		Spins the mouse wheel.
+		//
+		// description:
+		// 		Spins the wheel wheelAmt "notches."
+		// 		Negative wheelAmt scrolls up/away from the user.
+		// 		Positive wheelAmt scrolls down/toward the user.
+		// 		Note: this will all happen in one event.
+		// 		Warning: the size of one mouse wheel notch is an OS setting.
+		//		You can accesss this size from doh.robot.mouseWheelSize
+		//
+		// wheelAmt:
+		//		Number of notches to spin the wheel.
+		// 		Negative wheelAmt scrolls up/away from the user.
+		// 		Positive wheelAmt scrolls down/toward the user.
+		//
+		// delay:
+		//		Delay, in milliseconds, to wait before firing.
+		//		The delay is a delta with respect to the previous automation call.
+		//		For example, the following code ends after 600ms:
+		//			doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms
+		//			doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all
+		//
+		// duration:
+		//		Approximate time Robot will spend moving the mouse
+		//		By default, the Robot will wheel the mouse as fast as possible.
+		//
+
+
+		this._assertRobot();
+		if(!wheelAmt){ return; }
+		this.sequence(function(){
+			_robot.wheelMouse(isSecure(), Number(wheelAmt), Number(0), Number(duration||0));
+		},delay,duration);
+	},
+	
+	setClipboard: function(/*String*/data,/*String, optional*/format){
+		// summary:
+		//		Set clipboard content.
+		//
+		// description:
+		// 		Set data as clipboard content, overriding anything already there. The
+		//		data will be put to the clipboard using the given format.
+		//
+		// data:
+		//		New clipboard content to set
+		//
+		// format:
+		//		Set this to "text/html" to put richtext to the clipboard.
+		//		Otherwise, data is treated as plaintext. By default, plaintext
+		//		is used.
+		if(format==='text/html'){
+			_robot.setClipboardHtml(isSecure(),data);
+		}else{
+			_robot.setClipboardText(isSecure(),data);
+		}
+	}
+	};
+
+	// the applet itself
+	// needs to be down here so the handlers are set up
+	var iframesrc;
+	var scripts = document.getElementsByTagName("script");
+	for(var x = 0; x<scripts.length; x++){
+		var s = scripts[x].getAttribute('src');
+		if(s && (s.substr(s.length-9) == "runner.js")){
+			iframesrc = s.substr(0, s.length-9)+'Robot.html';
+			break;
+		}
+	}
+	// if loaded with dojo, there might not be a runner.js!
+	if(!iframesrc && window["dojo"]){
+		// if user set document.domain to something else, send it to the Robot too
+		iframesrc = dojo.moduleUrl("util", "doh/")+"Robot.html?domain="+escape(document.domain);
+	}
+	document.writeln('<div id="dohrobotview" style="border:0px none; margin:0px; padding:0px; position:absolute; bottom:0px; right:0px; width:1px; height:1px; overflow:hidden; visibility:hidden; background-color:red;"></div>'+
+		'<iframe application="true" style="border:0px none; z-index:32767; padding:0px; margin:0px; position:absolute; left:0px; top:0px; height:42px; width:200px; overflow:hidden; background-color:transparent;" tabIndex="-1" src="'+iframesrc+'" ALLOWTRANSPARENCY="true"></iframe>');
+})();
+}
diff --git a/util/doh/robot/DOHRobot.jar b/util/doh/robot/DOHRobot.jar
new file mode 100644
index 0000000..ed1dbc3
Binary files /dev/null and b/util/doh/robot/DOHRobot.jar differ
diff --git a/util/doh/robot/DOHRobot.java b/util/doh/robot/DOHRobot.java
new file mode 100644
index 0000000..3e28f82
--- /dev/null
+++ b/util/doh/robot/DOHRobot.java
@@ -0,0 +1,1660 @@
+import java.security.*;
+import java.applet.Applet;
+import java.awt.*;
+import java.util.*;
+import java.awt.event.*;
+import netscape.javascript.*;
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.URL;
+import java.awt.datatransfer.*;
+import javax.swing.JOptionPane;
+import javax.swing.JDialog;
+
+public final class DOHRobot extends Applet{
+	// order of execution:
+	// wait for user to trust applet
+	// load security manager to prevent Safari hang
+	// discover document root in screen coordinates
+	// discover keyboard capabilities
+	// tell doh to continue with the test
+
+	// link to doh
+	// To invoke doh, call eval with window.eval("jsexp")
+	// Note that the "window" is an iframe!
+	// You might need to break out of the iframe with an intermediate function
+	// in the parent window.
+	private JSObject window = null;
+
+	// java.awt.Robot
+	// drives the test
+	// you need to sign the applet JAR for this to work
+	private Robot robot = null;
+
+	// In order to preserve the execution order of Robot commands,
+	// we have to serialize commands by having them join() the previous one.
+	// Otherwise, if you run doh.robot.typeKeys("dijit"), you frequently get something
+	// like "diijt"
+	private static Thread previousThread = null;
+
+	// Keyboard discovery.
+	// At init, the Robot types keys into a textbox and JavaScript tells the
+	// Robot what it got back.
+	// charMap maps characters to the KeyEvent that generates the character on
+	// the user's machine.
+	// charMap uses the Java 1.4.2 (lack of) template syntax for wider
+	// compatibility.
+	private static HashMap charMap = null;
+	// Java key constants to iterate over
+	// not all are available on all machines!
+	private Vector vkKeys = null;
+	// some state variables
+	private boolean shift = false;
+	private boolean altgraph = false;
+	private boolean ctrl = false;
+	private boolean alt = false;
+	private boolean meta = false;
+	private boolean numlockDisabled = false;
+	// shake hands with JavaScript the first keypess to wake up FF2/Mac
+	private boolean jsready = false;
+	private String keystring = "";
+
+	// Firebug gets a little too curious about our applet for its own good
+	// setting firebugIgnore to true ensures Firebug doesn't break the applet
+	public boolean firebugIgnore = true;
+
+	private static String os=System.getProperty("os.name").toUpperCase();
+	private static Toolkit toolkit=Toolkit.getDefaultToolkit();
+	
+	private SecurityManager securitymanager;
+	private double key = -1;
+
+	// The screen x,y of the document upper left corner.
+	// We only set it once so people are less likely to take it over.
+	private boolean inited = false;
+	private int docScreenX = -100;
+	private int docScreenY = -100;
+	private int docScreenXMax;
+	private int docScreenYMax;
+	private boolean mouseSecurity = false;
+
+	// The last reported mouse x,y.
+	// If this is different from the real one, something's up.
+	private int lastMouseX;
+	private int lastMouseY;
+	public int dir=1;
+
+	// save a pointer to doh.robot for fast access
+	JSObject dohrobot = null;
+
+	// java.awt.Applet methods
+	public void stop(){
+		window = null;
+		dohrobot = null;
+		// only secure code run once
+		if(key != -2){
+			// prevent further execution of secure functions
+			key = -2;
+			// Java calls this when you close the window.
+			// It plays nice and restores the old security manager.
+			AccessController.doPrivileged(new PrivilegedAction(){
+				public Object run(){
+					log("Stop");
+					securitymanager.checkTopLevelWindow(null);
+					log("Security manager reset");
+					return null;
+				}
+			});
+		}
+	}
+
+	final private class onvisible extends ComponentAdapter{
+		public void componentShown(ComponentEvent evt){
+			// sets the security manager to fix a bug in liveconnect in Safari on Mac
+			if(key != -1){ return; }
+			Thread thread = new Thread(){
+				public void run(){
+					window = (JSObject) JSObject.getWindow(applet());   
+					AccessController.doPrivileged(new PrivilegedAction(){
+						public Object run(){
+							log("> init Robot");
+							try{
+								SecurityManager oldsecurity = System.getSecurityManager();
+								boolean needsSecurityManager = applet().getParameter("needsSecurityManager").equals("true");
+								log("Socket connections managed? "+needsSecurityManager);
+								try{
+									securitymanager = oldsecurity;
+									securitymanager.checkTopLevelWindow(null);
+									// xdomain
+									if(charMap == null){
+										if(!confirm("DOH has detected that the current Web page is attempting to access DOH,\n"+
+													"but belongs to a different domain than the one you agreed to let DOH automate.\n"+
+													"If you did not intend to start a new DOH test by visiting this Web page,\n"+
+													"press Cancel now and leave the Web page.\n"+
+													"Otherwise, press OK to trust this domain to automate DOH tests.")){
+											stop();
+											return null;
+										}
+									}
+									log("Found old security manager");
+								}catch(Exception e){
+									e.printStackTrace();
+									log("Making new security manager");
+									securitymanager = new RobotSecurityManager(needsSecurityManager,
+											oldsecurity);
+									securitymanager.checkTopLevelWindow(null);
+									System.setSecurityManager(securitymanager);
+								}
+								// instantiate the Robot
+								robot = new Robot();
+								robot.setAutoWaitForIdle(true);
+							}catch(Exception e){
+								log("Error calling _init_: "+e.getMessage());
+								key = -2;
+								e.printStackTrace();
+							}
+							log("< init Robot");
+							return null;
+						}
+					});
+					if(key == -2){
+						// applet not trusted
+						// start the test without it
+						window.eval("doh.robot._appletDead=true;doh.run();");
+					}else{
+						// now that the applet has really started, let doh know it's ok to use it
+						log("_initRobot");
+						try{
+							dohrobot = (JSObject) window.eval("doh.robot");
+							dohrobot.call("_initRobot", new Object[]{ applet() });
+						}catch(Exception e){
+							e.printStackTrace();
+						}
+					}
+				}
+			};
+			thread.start();
+		}
+	}
+
+	public void init(){
+		// ensure isShowing = true
+		addComponentListener(new onvisible());
+	}
+
+	// loading functions
+	public void _setKey(double key){
+		if(key == -1){
+			return;
+		}else if(this.key == -1){
+			this.key = key;
+		}
+	}
+
+	private boolean mouseSecure() throws Exception{
+		// Use MouseInfo to ensure that mouse is inside browser.
+		// Only works in Java 1.5, but the DOHRobot must compile for 1.4.
+		if(!mouseSecurity){ return true; }
+		Class mouseInfoClass;
+		Class pointerInfoClass;
+		try{
+			mouseInfoClass = Class.forName("java.awt.MouseInfo");
+			pointerInfoClass = Class.forName("java.awt.PointerInfo");
+		}catch(ClassNotFoundException e){
+			// Java 1.4
+			e.printStackTrace();
+			return true;
+		}
+		Method getPointerInfo = mouseInfoClass.getMethod("getPointerInfo", new Class[0]);
+		Method getLocation = pointerInfoClass.getMethod("getLocation", new Class[0]);
+		Object pointer=null;
+		try{
+			pointer = getPointerInfo.invoke(pointerInfoClass,new Object[0]);
+		}catch(java.lang.reflect.InvocationTargetException e){
+			e.getTargetException().printStackTrace();
+		}
+		Point mousePosition = (Point)(getLocation.invoke(pointer,new Object[0]));
+		return mousePosition.x >= docScreenX
+			&& mousePosition.x <= docScreenXMax
+			&& mousePosition.y >= docScreenY
+			&& mousePosition.y <= docScreenYMax;
+	}
+
+	private boolean isSecure(double key){
+		boolean result = this.key != -1 && this.key != -2 && this.key == key;
+		try{
+			result=result&&mouseSecure();
+		}catch(Exception e){
+			e.printStackTrace();
+			result=false;
+		}
+		if(!result&&this.key!=-2){
+			this.key=-2;
+			window.eval("doh.robot._appletDead=true;");
+			log("User aborted test; mouse moved off of browser");
+			alert("User aborted test; mouse moved off of browser.");
+		}
+		log("Key secure: " + result);
+		return result;
+	}
+
+	public void _callLoaded(final double sec){
+		log("> _callLoaded Robot");
+		Thread thread = new Thread(){
+			public void run(){
+				if(!isSecure(sec)){
+					return;
+				}
+				AccessController.doPrivileged(new PrivilegedAction(){
+					public Object run(){
+						Point p = getLocationOnScreen();
+						log("Document root: ~"+p.toString());
+						int x = p.x + 16;
+						int y = p.y + 8;
+						// click the mouse over the text box
+						try{
+							Thread.sleep(100);
+						}catch(Exception e){};
+						robot.mouseMove(x, y);
+						try{
+							Thread.sleep(100);
+						}catch(Exception e){};
+						robot.mousePress(InputEvent.BUTTON1_MASK);
+						try{
+							Thread.sleep(100);
+						}catch(Exception e){}
+						robot.mouseRelease(InputEvent.BUTTON1_MASK);
+						try{
+							Thread.sleep(100);
+						}catch(Exception e){}
+						log("< _callLoaded Robot");
+						return null;
+					}
+				});
+			}
+		};
+		thread.start();
+	}
+
+	// convenience functions
+	private DOHRobot applet(){
+		return this;
+	}
+
+	public void log(final String s){
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+				System.out.println((new Date()).toString() + ": " + s);
+				return null;
+			}
+		});
+	}
+
+	private void alert(final String s){
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+				window.eval("top.alert(\"" + s + "\");");
+				return null;
+			}
+		});
+	}
+
+	private boolean confirm(final String s){
+		// show a Java confirm dialog.
+		// Mac seems to lock up when showing a JS confirm from Java.
+		//return JOptionPane.showConfirmDialog(this, s, "doh.robot", JOptionPane.OK_CANCEL_OPTION)==JOptionPane.OK_OPTION);
+		JOptionPane pane = new JOptionPane(s, JOptionPane.DEFAULT_OPTION, JOptionPane.OK_CANCEL_OPTION);
+		JDialog dialog = pane.createDialog(this, "doh.robot");
+		dialog.setLocationRelativeTo(this);
+		dialog.show();
+		return ((Integer)pane.getValue()).intValue()==JOptionPane.OK_OPTION;
+	}
+
+	// mouse discovery code
+	public void setDocumentBounds(final double sec, int x, int y, int w, int h) throws Exception{
+		// call from JavaScript
+		// tells the Robot where the screen x,y of the upper left corner of the
+		// document are
+		// not screenX/Y of the window; really screenLeft/Top in IE, but not all
+		// browsers have this
+		log("> setDocumentBounds");
+		if(!isSecure(sec))
+			return;
+		if(!inited){
+			inited = true;
+			this.lastMouseX = this.docScreenX = x;
+			this.lastMouseY = this.docScreenY = y;
+			this.docScreenXMax = x + w;
+			this.docScreenYMax = y + h;
+			mouseSecurity=true;
+		}
+		log("< setDocumentBounds");
+	}
+
+	// keyboard discovery code
+	private void _mapKey(char charCode, int keyindex, boolean shift,
+			boolean altgraph){
+		log("_mapKey: " + charCode);
+		// if character is not in map, add it
+		if(!charMap.containsKey(new Integer(charCode))){
+			log("Notified: " + (char) charCode);
+			KeyEvent event = new KeyEvent(applet(), 0, 0,
+					(shift ? KeyEvent.SHIFT_MASK : 0)
+							+ (altgraph ? KeyEvent.ALT_GRAPH_MASK : 0),
+					((Integer) vkKeys.get(keyindex)).intValue(),
+					(char) charCode);
+			charMap.put(new Integer(charCode), event);
+			log("Mapped char " + (char) charCode + " to KeyEvent " + event);
+			if(((char) charCode) >= 'a' && ((char) charCode) <= 'z'){
+				// put shifted version of a-z in automatically
+				int uppercharCode = (int) Character
+						.toUpperCase((char) charCode);
+				event = new KeyEvent(applet(), 0, 0, KeyEvent.SHIFT_MASK
+						+ (altgraph ? KeyEvent.ALT_GRAPH_MASK : 0),
+						((Integer) vkKeys.get(keyindex)).intValue(),
+						(char) uppercharCode);
+				charMap.put(new Integer(uppercharCode), event);
+				log("Mapped char " + (char) uppercharCode + " to KeyEvent "
+						+ event);
+			}
+		}
+	}
+
+	public void _notified(final double sec, final String chars){
+		// decouple from JavaScript; thread join could hang it
+		Thread thread = new Thread("_notified"){
+			public void run(){
+				if(!isSecure(sec))
+					return;
+				AccessController.doPrivileged(new PrivilegedAction(){
+					public Object run(){
+						try{
+							// wait for release shift/altgraph to resolve
+							if(previousThread != null){
+								previousThread.join();
+							}
+						}catch(Exception e){
+						}
+						keystring += chars;
+						if(altgraph && !shift){
+							shift = false;
+							// Set robot auto delay now that FF/Mac inited all of the keys. 
+							// Good for DND.
+							robot.setAutoDelay(1);
+							try{
+								log(keystring);
+								int index = 0;
+								for (int i = 0; (i < vkKeys.size())
+										&& (index < keystring.length()); i++){
+									char c = keystring.charAt(index++);
+									_mapKey(c, i, false, false);
+								}
+								for (int i = 0; (i < vkKeys.size())
+										&& (index < keystring.length()); i++){
+									char c = keystring.charAt(index++);
+									_mapKey(c, i, true, false);
+								}
+								for (int i = 0; (i < vkKeys.size())
+										&& (index < keystring.length()); i++){
+									char c = keystring.charAt(index++);
+									_mapKey(c, i, false, true);
+								}
+								// notify DOH that the applet finished init
+								dohrobot.call("_onKeyboard", new Object[]{});
+							}catch(Exception e){
+								e.printStackTrace();
+							}
+							return null;
+						}else if(!shift){
+							shift = true;
+						}else{
+							shift = false;
+							altgraph = true;
+						}
+						pressNext();
+						// }
+						return null;
+					}
+				});
+			}
+		};
+		thread.start();
+	}
+
+	private void pressNext(){
+		final Thread myPreviousThread = previousThread;
+		Thread thread = new Thread("pressNext"){
+			public void run(){
+				try{
+					// wait for release shift/altgraph to resolve
+					if(myPreviousThread != null){
+						myPreviousThread.join();
+					}
+				}catch(Exception e){
+				}
+				// first time, press shift (have to do it here instead of
+				// _notified to avoid IllegalThreadStateException on Mac)
+				log("starting up, " + shift + " " + altgraph);
+				if(shift){
+					robot.keyPress(KeyEvent.VK_SHIFT);
+					log("Pressing shift");
+				}
+				try{
+					if(altgraph){
+						robot.keyPress(KeyEvent.VK_ALT_GRAPH);
+						log("Pressing alt graph");
+					}
+				}catch(Exception e){
+					log("Error pressing alt graph");
+					e.printStackTrace();
+					_notified(key, "");
+					return;
+				}
+				dohrobot.call("_nextKeyGroup", new Object[]{ new Integer(vkKeys.size()) });
+				for (int keyindex = 0; keyindex < vkKeys.size(); keyindex++){
+					try{
+						log("Press "
+								+ ((Integer) vkKeys.get(keyindex)).intValue());
+						robot.keyPress(((Integer) vkKeys.get(keyindex))
+								.intValue());
+						log("Release "
+								+ ((Integer) vkKeys.get(keyindex)).intValue());
+						robot.keyRelease(((Integer) vkKeys.get(keyindex))
+								.intValue());
+						if(altgraph && (keyindex == (vkKeys.size() - 1))){
+							robot.keyRelease(KeyEvent.VK_ALT_GRAPH);
+							log("Releasing alt graph");
+						}
+						if(shift && (keyindex == (vkKeys.size() - 1))){
+							robot.keyRelease(KeyEvent.VK_SHIFT);
+							log("Releasing shift");
+						}
+					}catch(Exception e){
+					}
+					try{
+						log("Press space");
+						robot.keyPress(KeyEvent.VK_SPACE);
+						log("Release space");
+						robot.keyRelease(KeyEvent.VK_SPACE);
+					}catch(Exception e){
+						e.printStackTrace();
+					}
+				}
+			}
+		};
+		previousThread = thread;
+		thread.start();
+	}
+
+	public void _initWheel(final double sec){
+		log("> initWheel");
+		Thread thread=new Thread(){
+			public void run(){
+				if(!isSecure(sec))
+					return;
+				Thread.yield();
+				// calibrate the mouse wheel now that textbox is focused
+				dir=1;
+				// fixed in 10.6.2 update 1 and 10.5.8 update 6:
+				// http://developer.apple.com/mac/library/releasenotes/CrossPlatform/JavaSnowLeopardUpdate1LeopardUpdate6RN/ResolvedIssues/ResolvedIssues.html
+				// Radar #6193836
+				if(os.indexOf("MAC") != -1){
+					// see if the version is greater than 10.5.8
+					String[] sfixedVersion = "10.5.8".split("\\.");
+					int[] fixedVersion = new int[3];
+					String[] sthisVersion = System.getProperty("os.version").split("\\.");
+					int[] thisVersion = new int[3];
+					for(int i=0; i<3; i++){
+						fixedVersion[i]=Integer.valueOf(sfixedVersion[i]).intValue();
+						thisVersion[i]=Integer.valueOf(sthisVersion[i]).intValue();
+					};
+					// 10.5.8, the fix level, should count as fixed
+					// on the other hand, 10.6.0 and 10.6.1 should not
+					boolean isFixed = !System.getProperty("os.version").equals("10.6.0")&&!System.getProperty("os.version").equals("10.6.1");
+					for(int i=0; i<fixedVersion.length&&isFixed; i++){
+						if(thisVersion[i]>fixedVersion[i]){
+							// definitely newer at this point
+							isFixed = true;
+							break;
+						}else if(thisVersion[i]<fixedVersion[i]){
+							// definitely older
+							isFixed = false;
+							break;
+						}
+						// equal; continue to next dot
+
+					}
+					// flip dir if not fixed
+					dir=isFixed?dir:-dir;
+				}
+				robot.mouseWheel(dir);
+				try{
+					Thread.sleep(100);
+				}catch(Exception e){}
+				log("< initWheel");
+			}
+		};
+		thread.start();
+	}
+
+	public void _initKeyboard(final double sec){
+		log("> initKeyboard");
+		// javascript entry point to discover the keyboard
+		if(charMap != null){
+			dohrobot.call("_onKeyboard", new Object[]{});
+			return;
+		}
+		Thread thread = new Thread(){
+			public void run(){
+				if(!isSecure(sec))
+					return;
+				AccessController.doPrivileged(new PrivilegedAction(){
+					public Object run(){
+						charMap = new HashMap();
+						KeyEvent event = new KeyEvent(applet(), 0, 0, 0,
+								KeyEvent.VK_SPACE, ' ');
+						charMap.put(new Integer(32), event);
+						try{
+							// a-zA-Z0-9 + 29 others
+							vkKeys = new Vector();
+							for (char i = 'a'; i <= 'z'; i++){
+								vkKeys.add(new Integer(KeyEvent.class.getField(
+										"VK_" + Character.toUpperCase((char) i))
+										.getInt(null)));
+							}
+							for (char i = '0'; i <= '9'; i++){
+								vkKeys.add(new Integer(KeyEvent.class.getField(
+										"VK_" + Character.toUpperCase((char) i))
+										.getInt(null)));
+							}
+							int[] mykeys = new int[]{ KeyEvent.VK_COMMA,
+									KeyEvent.VK_MINUS, KeyEvent.VK_PERIOD,
+									KeyEvent.VK_SLASH, KeyEvent.VK_SEMICOLON,
+									KeyEvent.VK_LEFT_PARENTHESIS,
+									KeyEvent.VK_NUMBER_SIGN, KeyEvent.VK_PLUS,
+									KeyEvent.VK_RIGHT_PARENTHESIS,
+									KeyEvent.VK_UNDERSCORE,
+									KeyEvent.VK_EXCLAMATION_MARK, KeyEvent.VK_DOLLAR,
+									KeyEvent.VK_CIRCUMFLEX, KeyEvent.VK_AMPERSAND,
+									KeyEvent.VK_ASTERISK, KeyEvent.VK_QUOTEDBL,
+									KeyEvent.VK_LESS, KeyEvent.VK_GREATER,
+									KeyEvent.VK_BRACELEFT, KeyEvent.VK_BRACERIGHT,
+									KeyEvent.VK_COLON, KeyEvent.VK_BACK_QUOTE,
+									KeyEvent.VK_QUOTE, KeyEvent.VK_OPEN_BRACKET,
+									KeyEvent.VK_BACK_SLASH, KeyEvent.VK_CLOSE_BRACKET,
+									KeyEvent.VK_EQUALS };
+							for (int i = 0; i < mykeys.length; i++){
+								vkKeys.add(new Integer(mykeys[i]));
+							}
+						}catch(Exception e){
+							e.printStackTrace();
+						}
+						robot.setAutoDelay(1);
+						// prime the event pump for Google Chome - so fast it doesn't even stop to listen for key events!
+						// send spaces until JS says to stop
+						int count=0;
+						boolean waitingOnSpace = true;
+						do{
+							log("Pressed space");
+							robot.keyPress(KeyEvent.VK_SPACE);
+							robot.keyRelease(KeyEvent.VK_SPACE);
+							count++;
+							waitingOnSpace = ((Boolean)window.eval("doh.robot._spaceReceived")).equals(Boolean.FALSE);
+							log("JS still waiting on a space? "+waitingOnSpace);
+						}while(count<500&&waitingOnSpace);
+						robot.keyPress(KeyEvent.VK_ENTER);
+						robot.keyRelease(KeyEvent.VK_ENTER);
+						robot.setAutoDelay(0);
+						log("< initKeyboard");
+						pressNext();
+						return null;
+					}
+				});
+			}
+		};
+		thread.start();
+	}
+
+	public void typeKey(double sec, final int charCode, final int keyCode,
+			final boolean alt, final boolean ctrl, final boolean shift, final boolean meta,
+			final int delay, final boolean async){
+		if(!isSecure(sec))
+			return;
+		// called by doh.robot._keyPress
+		// see it for details
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+				try{
+					log("> typeKey Robot " + charCode + ", " + keyCode + ", " + async);
+					KeyPressThread thread = new KeyPressThread(charCode,
+							keyCode, alt, ctrl, shift, meta, delay, async?null:previousThread);
+					previousThread = async?previousThread:thread;
+					thread.start();
+					log("< typeKey Robot");
+				}catch(Exception e){
+					log("Error calling typeKey");
+					e.printStackTrace();
+				}
+				return null;
+			}
+		});
+	}
+
+	public void upKey(double sec, final int charCode, final int keyCode, final int delay){
+		// called by doh.robot.keyDown
+		// see it for details
+		// a nice name like "keyUp" is reserved in Java
+		if(!isSecure(sec))
+			return;
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+				log("> upKey Robot " + charCode + ", " + keyCode);
+				KeyUpThread thread = new KeyUpThread(charCode, keyCode, delay, previousThread);
+				previousThread = thread;
+				thread.start();
+				log("< upKey Robot");
+				return null;
+			}
+		});
+	}
+
+	public void downKey(double sec, final int charCode, final int keyCode, final int delay){
+		// called by doh.robot.keyUp
+		// see it for details
+		// a nice name like "keyDown" is reserved in Java
+		if(!isSecure(sec))
+			return;
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+				log("> downKey Robot " + charCode + ", " + keyCode);
+				KeyDownThread thread = new KeyDownThread(charCode, keyCode, delay, previousThread);
+				previousThread = thread;
+				thread.start();
+				log("< downKey Robot");
+				return null;
+			}
+		});
+	}
+
+	public void pressMouse(double sec, final boolean left,
+			final boolean middle, final boolean right, final int delay){
+		if(!isSecure(sec))
+			return;
+		// called by doh.robot.mousePress
+		// see it for details
+		// a nice name like "mousePress" is reserved in Java
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+				log("> mousePress Robot " + left + ", " + middle + ", " + right);
+				MousePressThread thread = new MousePressThread(
+						(left ? InputEvent.BUTTON1_MASK : 0)
+								+ (middle ? InputEvent.BUTTON2_MASK : 0)
+								+ (right ? InputEvent.BUTTON3_MASK : 0), delay,
+						previousThread);
+				previousThread = thread;
+				thread.start();
+				log("< mousePress Robot");
+				return null;
+			}
+		});
+	}
+
+	public void releaseMouse(double sec, final boolean left,
+			final boolean middle, final boolean right, final int delay){
+		if(!isSecure(sec))
+			return;
+		// called by doh.robot.mouseRelease
+		// see it for details
+		// a nice name like "mouseRelease" is reserved in Java
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+				log("> mouseRelease Robot " + left + ", " + middle + ", "
+						+ right);
+				MouseReleaseThread thread = new MouseReleaseThread(
+						(left ? InputEvent.BUTTON1_MASK : 0)
+								+ (middle ? InputEvent.BUTTON2_MASK : 0)
+								+ (right ? InputEvent.BUTTON3_MASK : 0), delay,
+						previousThread);
+				previousThread = thread;
+				thread.start();
+				log("< mouseRelease Robot");
+				return null;
+			}
+		});
+	}
+
+	public void moveMouse(double sec, final int x1, final int y1, final int d, final int duration){
+		// called by doh.robot.mouseMove
+		// see it for details
+		// a nice name like "mouseMove" is reserved in Java
+		if(!isSecure(sec))
+			return;
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+				int x = x1 + docScreenX;
+				int y = y1 + docScreenY;
+				if(x > docScreenXMax || y > docScreenYMax){
+					// TODO: try to scroll view
+					log("Request to mouseMove denied");
+					return null;
+				}
+				int delay = d;
+				log("> mouseMove Robot " + x + ", " + y);
+				MouseMoveThread thread = new MouseMoveThread(x, y, delay,
+						duration, previousThread);
+				previousThread = thread;
+				thread.start();
+				log("< mouseMove Robot");
+				return null;
+			}
+		});
+	}
+
+	public void wheelMouse(double sec, final int amount, final int delay, final int duration){
+		// called by doh.robot.mouseWheel
+		// see it for details
+		if(!isSecure(sec))
+			return;
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+				MouseWheelThread thread = new MouseWheelThread(amount, delay, duration,
+						previousThread);
+				previousThread = thread;
+				thread.start();
+				return null;
+			}
+		});
+	}
+
+	private int getVKCode(int charCode, int keyCode){
+		int keyboardCode = 0;
+		if(charCode >= 32){
+			// if it is printable, then it lives in our hashmap
+			KeyEvent event = (KeyEvent) charMap.get(new Integer(charCode));
+			keyboardCode = event.getKeyCode();
+		}
+		else{
+			switch (keyCode){
+				case 13:
+					keyboardCode = KeyEvent.VK_ENTER;
+					break;
+				case 8:
+					keyboardCode = KeyEvent.VK_BACK_SPACE;
+					break;
+				case 25:// shift tab for Safari
+				case 9:
+					keyboardCode = KeyEvent.VK_TAB;
+					break;
+				case 12:
+					keyboardCode = KeyEvent.VK_CLEAR;
+					break;
+				case 16:
+					keyboardCode = KeyEvent.VK_SHIFT;
+					break;
+				case 17:
+					keyboardCode = KeyEvent.VK_CONTROL;
+					break;
+				case 18:
+					keyboardCode = KeyEvent.VK_ALT;
+					break;
+				case 63250:
+				case 19:
+					keyboardCode = KeyEvent.VK_PAUSE;
+					break;
+				case 20:
+					keyboardCode = KeyEvent.VK_CAPS_LOCK;
+					break;
+				case 27:
+					keyboardCode = KeyEvent.VK_ESCAPE;
+					break;
+				case 32:
+					log("it's a space");
+					keyboardCode = KeyEvent.VK_SPACE;
+					break;
+				case 63276:
+				case 33:
+					keyboardCode = KeyEvent.VK_PAGE_UP;
+					break;
+				case 63277:
+				case 34:
+					keyboardCode = KeyEvent.VK_PAGE_DOWN;
+					break;
+				case 63275:
+				case 35:
+					keyboardCode = KeyEvent.VK_END;
+					break;
+				case 63273:
+				case 36:
+					keyboardCode = KeyEvent.VK_HOME;
+					break;
+
+				/**
+				 * Constant for the <b>left</b> arrow key.
+				 */
+				case 63234:
+				case 37:
+					keyboardCode = KeyEvent.VK_LEFT;
+					break;
+
+				/**
+				 * Constant for the <b>up</b> arrow key.
+				 */
+				case 63232:
+				case 38:
+					keyboardCode = KeyEvent.VK_UP;
+					break;
+
+				/**
+				 * Constant for the <b>right</b> arrow key.
+				 */
+				case 63235:
+				case 39:
+					keyboardCode = KeyEvent.VK_RIGHT;
+					break;
+
+				/**
+				 * Constant for the <b>down</b> arrow key.
+				 */
+				case 63233:
+				case 40:
+					keyboardCode = KeyEvent.VK_DOWN;
+					break;
+				case 63272:
+				case 46:
+					keyboardCode = KeyEvent.VK_DELETE;
+					break;
+				case 63289:
+				case 144:
+					keyboardCode = KeyEvent.VK_NUM_LOCK;
+					break;
+				case 63249:
+				case 145:
+					keyboardCode = KeyEvent.VK_SCROLL_LOCK;
+					break;
+
+				/** Constant for the F1 function key. */
+				case 63236:
+				case 112:
+					keyboardCode = KeyEvent.VK_F1;
+					break;
+
+				/** Constant for the F2 function key. */
+				case 63237:
+				case 113:
+					keyboardCode = KeyEvent.VK_F2;
+					break;
+
+				/** Constant for the F3 function key. */
+				case 63238:
+				case 114:
+					keyboardCode = KeyEvent.VK_F3;
+					break;
+
+				/** Constant for the F4 function key. */
+				case 63239:
+				case 115:
+					keyboardCode = KeyEvent.VK_F4;
+					break;
+
+				/** Constant for the F5 function key. */
+				case 63240:
+				case 116:
+					keyboardCode = KeyEvent.VK_F5;
+					break;
+
+				/** Constant for the F6 function key. */
+				case 63241:
+				case 117:
+					keyboardCode = KeyEvent.VK_F6;
+					break;
+
+				/** Constant for the F7 function key. */
+				case 63242:
+				case 118:
+					keyboardCode = KeyEvent.VK_F7;
+					break;
+
+				/** Constant for the F8 function key. */
+				case 63243:
+				case 119:
+					keyboardCode = KeyEvent.VK_F8;
+					break;
+
+				/** Constant for the F9 function key. */
+				case 63244:
+				case 120:
+					keyboardCode = KeyEvent.VK_F9;
+					break;
+
+				/** Constant for the F10 function key. */
+				case 63245:
+				case 121:
+					keyboardCode = KeyEvent.VK_F10;
+					break;
+
+				/** Constant for the F11 function key. */
+				case 63246:
+				case 122:
+					keyboardCode = KeyEvent.VK_F11;
+					break;
+
+				/** Constant for the F12 function key. */
+				case 63247:
+				case 123:
+					keyboardCode = KeyEvent.VK_F12;
+					break;
+
+				/**
+				 * Constant for the F13 function key.
+				 * 
+				 * @since 1.2
+				 */
+				/*
+				 * F13 - F24 are used on IBM 3270 keyboard; break; use
+				 * random range for constants.
+				 */
+				case 124:
+					keyboardCode = KeyEvent.VK_F13;
+					break;
+
+				/**
+				 * Constant for the F14 function key.
+				 * 
+				 * @since 1.2
+				 */
+				case 125:
+					keyboardCode = KeyEvent.VK_F14;
+					break;
+
+				/**
+				 * Constant for the F15 function key.
+				 * 
+				 * @since 1.2
+				 */
+				case 126:
+					keyboardCode = KeyEvent.VK_F15;
+					break;
+
+				case 63302:
+				case 45:
+					keyboardCode = KeyEvent.VK_INSERT;
+					break;
+				case 47:
+					keyboardCode = KeyEvent.VK_HELP;
+					break;
+				default:
+					keyboardCode = keyCode;
+
+			}
+		}
+		log("Attempting to type " + (char) charCode + ":"
+				+ charCode + " " + keyCode);
+		log("Converted to " + keyboardCode);
+		return keyboardCode;
+	}
+
+	private boolean isUnsafe(int keyboardCode){
+		// run through exemption list
+		log("ctrl: "+ctrl+", alt: "+alt+", shift: "+shift);
+		if(((ctrl || alt) && keyboardCode == KeyEvent.VK_ESCAPE)
+							|| (alt && keyboardCode == KeyEvent.VK_TAB)
+							|| (ctrl && alt && keyboardCode == KeyEvent.VK_DELETE)){
+			log("You are not allowed to press this key combination!");
+			return true;
+		// bugged keys cases go next
+		}else{
+			log("Safe to press.");
+			return false;
+		}
+	}
+
+	private boolean disableNumlock(int vk, boolean shift){
+		boolean result = !numlockDisabled&&shift
+			&&os.indexOf("WINDOWS")!=-1
+			&&toolkit.getLockingKeyState(KeyEvent.VK_NUM_LOCK) // only works on Windows
+			&&(
+				// any numpad buttons are suspect
+				vk==KeyEvent.VK_LEFT
+				||vk==KeyEvent.VK_UP
+				||vk==KeyEvent.VK_RIGHT
+				||vk==KeyEvent.VK_DOWN
+				||vk==KeyEvent.VK_HOME
+				||vk==KeyEvent.VK_END
+				||vk==KeyEvent.VK_PAGE_UP
+				||vk==KeyEvent.VK_PAGE_DOWN
+		);
+		log("disable numlock: "+result);
+		return result;
+	}
+
+	private void _typeKey(final int cCode, final int kCode, final boolean a,
+			final boolean c, final boolean s, final boolean m){
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+				int charCode = cCode;
+				int keyCode = kCode;
+				boolean alt = a;
+				boolean ctrl = c;
+				boolean shift = s;
+				boolean meta = m;
+				boolean altgraph = false;
+				log("> _typeKey Robot " + charCode + ", " + keyCode);
+				try{
+					int keyboardCode=getVKCode(charCode, keyCode);
+					if(charCode >= 32){
+						// if it is printable, then it lives in our hashmap
+						KeyEvent event = (KeyEvent) charMap.get(new Integer(charCode));
+						// see if we need to press shift to generate this
+						// character
+						if(!shift){
+							shift = event.isShiftDown();
+						}
+						altgraph = event.isAltGraphDown();
+						keyboardCode = event.getKeyCode();
+					}
+
+					// Java bug: on Windows, shift+arrow key unpresses shift when numlock is on.
+					// See: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4838497
+					boolean disableNumlock=disableNumlock(keyboardCode,shift||applet().shift);
+					// run through exemption list
+					if(!isUnsafe(keyboardCode)){
+						if(shift){
+							log("Pressing shift");
+							robot.keyPress(KeyEvent.VK_SHIFT);
+						}
+						if(alt){
+							log("Pressing alt");
+							robot.keyPress(KeyEvent.VK_ALT);
+						}
+						if(altgraph){
+							log("Pressing altgraph");
+							robot.keyPress(KeyEvent.VK_ALT_GRAPH);
+						}
+						if(ctrl){
+							log("Pressing ctrl");
+							robot.keyPress(KeyEvent.VK_CONTROL);
+						}
+						if(meta){
+							log("Pressing meta");
+							robot.keyPress(KeyEvent.VK_META);
+						}
+						if(disableNumlock){
+							robot.keyPress(KeyEvent.VK_NUM_LOCK);
+							robot.keyRelease(KeyEvent.VK_NUM_LOCK);
+							numlockDisabled=true;
+						}else if(numlockDisabled&&!(applet().shift||shift)){
+							// only turn it back on when the user is finished pressing shifted arrow keys
+							robot.keyPress(KeyEvent.VK_NUM_LOCK);
+							robot.keyRelease(KeyEvent.VK_NUM_LOCK);
+							numlockDisabled=false;
+						}
+						if(keyboardCode != KeyEvent.VK_SHIFT
+								&& keyboardCode != KeyEvent.VK_ALT
+								&& keyboardCode != KeyEvent.VK_ALT_GRAPH
+								&& keyboardCode != KeyEvent.VK_CONTROL
+								&& keyboardCode != KeyEvent.VK_META){
+							try{
+								robot.keyPress(keyboardCode);
+								robot.keyRelease(keyboardCode);
+							}catch(Exception e){
+								log("Error while actually typing a key");
+								e.printStackTrace();
+							}
+
+						}
+						if(ctrl){
+							robot.keyRelease(KeyEvent.VK_CONTROL);
+							ctrl = false;
+						}
+						if(alt){
+							robot.keyRelease(KeyEvent.VK_ALT);
+							alt = false;
+						}
+						if(altgraph){
+							robot.keyRelease(KeyEvent.VK_ALT_GRAPH);
+							altgraph = false;
+						}
+						if(shift){
+							log("Releasing shift");
+							robot.keyRelease(KeyEvent.VK_SHIFT);
+							shift = false;
+						}
+						if(meta){
+							log("Releasing meta");
+							robot.keyRelease(KeyEvent.VK_META);
+							meta = false;
+						}
+					}
+				}catch(Exception e){
+					log("Error in _typeKey");
+					e.printStackTrace();
+				}
+				log("< _typeKey Robot");
+				return null;
+			}
+		});
+	}
+
+	public boolean hasFocus(){
+		try{
+			return ((Boolean) window
+					.eval("var result=false;if(window.parent.document.hasFocus){result=window.parent.document.hasFocus();}else{result=true;}result;"))
+					.booleanValue();
+		}catch(Exception e){
+			// runs even after you close the window!
+			return false;
+		}
+	}
+
+	// Threads for common Robot tasks
+	// (so as not to tie up the browser rendering thread!)
+	// declared inside so they have private access to the robot
+	// we do *not* want to expose that guy!
+	final private class KeyPressThread extends Thread{
+		private int charCode;
+		private int keyCode;
+		private boolean alt;
+		private boolean ctrl;
+		private boolean shift;
+		private boolean meta;
+		private int delay;
+		private Thread myPreviousThread = null;
+
+		public KeyPressThread(int charCode, int keyCode, boolean alt,
+				boolean ctrl, boolean shift, boolean meta, int delay, Thread myPreviousThread){
+			log("KeyPressThread constructor " + charCode + ", " + keyCode);
+			this.charCode = charCode;
+			this.keyCode = keyCode;
+			this.alt = alt;
+			this.ctrl = ctrl;
+			this.shift = shift;
+			this.meta = meta;
+			this.delay = delay;
+			this.myPreviousThread = myPreviousThread;
+		}
+
+		public void run(){
+			try{
+				if(myPreviousThread != null)
+					myPreviousThread.join();
+				// in different order so async works
+				while(!hasFocus()){
+					Thread.sleep(1000);
+				}
+				Thread.sleep(delay);
+				log("> run KeyPressThread");
+
+				_typeKey(charCode, keyCode, alt, ctrl, shift, meta);
+			}catch(Exception e){
+				log("Bad parameters passed to _typeKey");
+				e.printStackTrace();
+			}
+			log("< run KeyPressThread");
+
+		}
+	}
+
+	final private class KeyDownThread extends Thread{
+		private int charCode;
+		private int keyCode;
+		private int delay;
+		private Thread myPreviousThread = null;
+
+		public KeyDownThread(int charCode, int keyCode, int delay, Thread myPreviousThread){
+			log("KeyDownThread constructor " + charCode + ", " + keyCode);
+			this.charCode = charCode;
+			this.keyCode = keyCode;
+			this.delay = delay;
+			this.myPreviousThread = myPreviousThread;
+		}
+
+		public void run(){
+			try{
+				if(myPreviousThread != null)
+					myPreviousThread.join();
+				Thread.sleep(delay);
+				log("> run KeyDownThread");
+				while(!hasFocus()){
+					Thread.sleep(1000);
+				}
+				int vkCode=getVKCode(charCode, keyCode);
+				if(charCode >= 32){
+					// if it is printable, then it lives in our hashmap
+					KeyEvent event = (KeyEvent) charMap.get(new Integer(charCode));
+					// see if we need to press shift to generate this
+					// character
+					if(event.isShiftDown()){
+						robot.keyPress(KeyEvent.VK_SHIFT);
+						shift=true;
+					}
+					if(event.isAltGraphDown()){
+						robot.keyPress(KeyEvent.VK_ALT_GRAPH);
+						altgraph=true;
+					}
+				}else{
+					if(vkCode==KeyEvent.VK_ALT){
+						alt=true;
+					}else if(vkCode==KeyEvent.VK_CONTROL){
+						ctrl=true;
+					}else if(vkCode==KeyEvent.VK_SHIFT){
+						shift=true;
+					}else if(vkCode==KeyEvent.VK_ALT_GRAPH){
+						altgraph=true;
+					}else if(vkCode==KeyEvent.VK_META){
+						meta=true;
+					}else if(disableNumlock(vkCode,shift)){
+						robot.keyPress(KeyEvent.VK_NUM_LOCK);
+						robot.keyRelease(KeyEvent.VK_NUM_LOCK);
+						numlockDisabled=true;
+					}
+				}
+				if(!isUnsafe(vkCode)){
+					robot.keyPress(vkCode);
+				}
+			}catch(Exception e){
+				log("Bad parameters passed to downKey");
+				e.printStackTrace();
+			}
+			log("< run KeyDownThread");
+
+		}
+	}
+
+	final private class KeyUpThread extends Thread{
+		private int charCode;
+		private int keyCode;
+		private int delay;
+		private Thread myPreviousThread = null;
+
+		public KeyUpThread(int charCode, int keyCode, int delay, Thread myPreviousThread){
+			log("KeyUpThread constructor " + charCode + ", " + keyCode);
+			this.charCode = charCode;
+			this.keyCode = keyCode;
+			this.delay = delay;
+			this.myPreviousThread = myPreviousThread;
+		}
+
+		public void run(){
+			try{
+				if(myPreviousThread != null)
+					myPreviousThread.join();
+				Thread.sleep(delay);
+				log("> run KeyUpThread");
+				while(!hasFocus()){
+					Thread.sleep(1000);
+				}
+				int vkCode=getVKCode(charCode, keyCode);
+				if(charCode >= 32){
+					// if it is printable, then it lives in our hashmap
+					KeyEvent event = (KeyEvent) charMap.get(new Integer(charCode));
+					// see if we need to press shift to generate this
+					// character
+					if(event.isShiftDown()){
+						robot.keyRelease(KeyEvent.VK_SHIFT);
+						shift=false;
+					}
+					if(event.isAltGraphDown()){
+						robot.keyRelease(KeyEvent.VK_ALT_GRAPH);
+						altgraph=false;
+					}
+				}else{
+					if(vkCode==KeyEvent.VK_ALT){
+						alt=false;
+					}else if(vkCode==KeyEvent.VK_CONTROL){
+						ctrl=false;
+					}else if(vkCode==KeyEvent.VK_SHIFT){
+						shift=false;
+						if(numlockDisabled){
+							robot.keyPress(KeyEvent.VK_NUM_LOCK);
+							robot.keyRelease(KeyEvent.VK_NUM_LOCK);
+							numlockDisabled=false;
+						}
+					}else if(vkCode==KeyEvent.VK_ALT_GRAPH){
+						altgraph=false;
+					}else if(vkCode==KeyEvent.VK_META){
+						meta=false;
+					}
+				}
+				robot.keyRelease(vkCode);
+			}catch(Exception e){
+				log("Bad parameters passed to upKey");
+				e.printStackTrace();
+			}
+			log("< run KeyUpThread");
+
+		}
+	}
+
+	final private class MousePressThread extends Thread{
+		private int mask;
+		private int delay;
+		private Thread myPreviousThread = null;
+
+		public MousePressThread(int mask, int delay, Thread myPreviousThread){
+			this.mask = mask;
+			this.delay = delay;
+			this.myPreviousThread = myPreviousThread;
+		}
+
+		public void run(){
+			try{
+				if(myPreviousThread != null)
+					myPreviousThread.join();
+				Thread.sleep(delay);
+				log("> run MousePressThread");
+				while(!hasFocus()){
+					Thread.sleep(1000);
+				}
+				robot.mousePress(mask);
+				robot.waitForIdle();
+			}catch(Exception e){
+				log("Bad parameters passed to mousePress");
+				e.printStackTrace();
+			}
+			log("< run MousePressThread");
+
+		}
+	}
+
+	final private class MouseReleaseThread extends Thread{
+		private int mask;
+		private int delay;
+		private Thread myPreviousThread = null;
+
+		public MouseReleaseThread(int mask, int delay, Thread myPreviousThread){
+			this.mask = mask;
+			this.delay = delay;
+			this.myPreviousThread = myPreviousThread;
+		}
+
+		public void run(){
+			try{
+				if(myPreviousThread != null)
+					myPreviousThread.join();
+				Thread.sleep(delay);
+				log("> run MouseReleaseThread ");
+				while(!hasFocus()){
+					Thread.sleep(1000);
+				}
+				robot.mouseRelease(mask);
+				robot.waitForIdle();
+			}catch(Exception e){
+				log("Bad parameters passed to mouseRelease");
+				e.printStackTrace();
+			}
+
+			log("< run MouseReleaseThread ");
+
+		}
+	}
+
+	final private class MouseMoveThread extends Thread{
+		private int x;
+		private int y;
+		private int delay;
+		private int duration;
+		private Thread myPreviousThread = null;
+
+		public MouseMoveThread(int x, int y, int delay, int duration, Thread myPreviousThread){
+			this.x = x;
+			this.y = y;
+			this.delay = delay;
+			this.duration = duration;
+			this.myPreviousThread = myPreviousThread;
+		}
+
+		public double easeInOutQuad(double t, double b, double c, double d){
+			t /= d / 2;
+			if(t < 1)
+				return c / 2 * t * t + b;
+			t--;
+			return -c / 2 * (t * (t - 2) - 1) + b;
+		};
+
+		public void run(){
+			try{
+				if(myPreviousThread != null)
+					myPreviousThread.join();
+				Thread.sleep(delay);
+				log("> run MouseMoveThread " + x + ", " + y);
+				while(!hasFocus()){
+					Thread.sleep(1000);
+				}
+				int x1 = lastMouseX;
+				int x2 = x;
+				int y1 = lastMouseY;
+				int y2 = y;
+				// shrink range by 1 px on both ends
+				// manually move this 1px to trip DND code
+				if(x1 != x2){
+					int dx = x - lastMouseX;
+					if(dx > 0){
+						x1 += 1;
+						x2 -= 1;
+					}else{
+						x1 -= 1;
+						x2 += 1;
+					}
+				}
+				if(y1 != y2){
+					int dy = y - lastMouseY;
+					if(dy > 0){
+						y1 += 1;
+						y2 -= 1;
+					}else{
+						y1 -= 1;
+						y2 += 1;
+					}
+
+				}
+				// manual precision
+				robot.setAutoWaitForIdle(false);
+				int intermediateSteps = duration==1?0: // duration==1 -> user wants to jump the mouse
+					((((int)Math.ceil(Math.log(duration+1)))|1)); // |1 to ensure an odd # of intermediate steps for sensible interpolation
+				// assumption: intermediateSteps will always be >=0
+				int delay = duration/(intermediateSteps+1); // +1 to include last move
+				// First mouse movement fires at t=0 to official last know position of the mouse.
+				robot.mouseMove(lastMouseX, lastMouseY);
+				long date,date2;
+				date=new Date().getTime();
+				// Shift lastMouseX/Y in the direction of the movement for interpolating over the smaller interval.
+				lastMouseX=x1;
+				lastMouseY=y1;
+				// Now interpolate mouse movement from (lastMouseX=x1,lastMouseY=y1) to (x2,y2)
+				// precondition: the amount of time that has passed since the first mousemove is 0*delay.
+				// invariant: each time you end an iteration, after you increment t, the amount of time that has passed is t*delay
+				for (int t = 0; t < intermediateSteps; t++){
+					Thread.sleep(delay);
+					x1 = (int) easeInOutQuad((double) t, (double) lastMouseX,
+							(double) x2 - lastMouseX, (double) intermediateSteps-1);
+					y1 = (int) easeInOutQuad((double) t, (double) lastMouseY,
+							(double) y2 - lastMouseY, (double) intermediateSteps-1);
+					//log("("+x1+","+y1+")");
+					robot.mouseMove(x1, y1);
+				}
+				// postconditions:
+				//	t=intermediateSteps
+				// 	intermediateSteps*delay time has passed,
+				// 	time remaining = duration-intermediateSteps*delay = (steps+1)*delay-intermediateSteps*delay = delay
+				// You theoretically need 1 more delay for the whole duration to have passed.
+				// In practice, you want less than that due to roundoff errors in Java's clock granularity.
+				Thread.sleep(delay);
+				robot.mouseMove(x, y);
+				robot.setAutoWaitForIdle(true);
+				date2=new Date().getTime();
+				//log("mouseMove statistics: duration= "+duration+" steps="+intermediateSteps+" delay="+delay);
+				//log("mouseMove discrepency: "+(date2-date-duration)+"ms");
+				lastMouseX = x;
+				lastMouseY = y;
+			}catch(Exception e){
+				log("Bad parameters passed to mouseMove");
+				e.printStackTrace();
+			}
+
+			log("< run MouseMoveThread");
+
+		}
+	}
+
+	final private class MouseWheelThread extends Thread{
+		private int amount;
+		private int delay;
+		private int duration;
+		private Thread myPreviousThread = null;
+
+		public MouseWheelThread(int amount, int delay, int duration, Thread myPreviousThread){
+			this.amount = amount;
+			this.delay = delay;
+			this.duration = duration;
+			this.myPreviousThread = myPreviousThread;
+		}
+
+		public void run(){
+			try{
+				if(myPreviousThread != null)
+					myPreviousThread.join();
+				Thread.sleep(delay);
+				log("> run MouseWheelThread " + amount);
+				while(!hasFocus()){
+					Thread.sleep(1000);
+				}
+				robot.setAutoDelay(Math.max(duration/Math.abs(amount),1));
+				for(int i=0; i<Math.abs(amount); i++){
+					robot.mouseWheel(amount>0?dir:-dir);
+				}
+				robot.setAutoDelay(1);
+			}catch(Exception e){
+				log("Bad parameters passed to mouseWheel");
+				e.printStackTrace();
+			}
+			log("< run MouseWheelThread ");
+		}
+	}
+
+	final private class RobotSecurityManager extends SecurityManager{
+		// The applet's original security manager.
+		// There is a bug in some people's Safaris that causes Safari to
+		// basically hang on liveconnect calls.
+		// Our security manager fixes it.
+
+		private boolean isActive = false;
+		private boolean needsSecurityManager = false;
+		private SecurityManager oldsecurity = null;
+
+		public RobotSecurityManager(boolean needsSecurityManager, SecurityManager oldsecurity){
+			this.needsSecurityManager = needsSecurityManager;
+			this.oldsecurity = oldsecurity;
+		}
+
+		public boolean checkTopLevelWindow(Object window){
+			// If our users temporarily accept our cert for a session,
+			// then use the same session to browse to a malicious website also using our applet,
+			// that website can automatically execute the applet. 
+			// To resolve this issue, RobotSecurityManager overrides checkTopLevelWindow
+			// to check the JVM to see if there are other instances of the applet running on different domains.
+			// If there are, it prompts the user to confirm that they want to run the applet before continuing. 
+
+			// null is not supposed to be allowed
+			// so we allow it to distinguish our security manager.
+			if(window == null){
+				isActive = !isActive;
+				log("Active is now " + isActive);
+			}
+			return window == null ? true : oldsecurity
+					.checkTopLevelWindow(window);
+		}
+
+		public void checkPermission(Permission p){
+			// liveconnect SocketPermission resolve takes
+			// FOREVER (like 6 seconds) in Safari 3
+			// Java does like 50 of these on the first JS call
+			// 6*50=300 seconds!
+			if(isActive && needsSecurityManager
+					&& java.net.SocketPermission.class.isInstance(p)
+					&& p.getActions().matches(".*resolve.*")){
+				throw new SecurityException(
+						"DOH: liveconnect resolve locks up Safari 3. Denying resolve request.");
+			}else if(p.equals(new java.awt.AWTPermission("watchMousePointer"))){
+				// enable robot to watch mouse
+			}else{
+				oldsecurity.checkPermission(p);
+			}
+		}
+
+		public void checkPermission(Permission perm, Object context){
+			checkPermission(perm);
+		}
+	}
+	
+	public void setClipboardText(double sec, final String data) {
+		if(!isSecure(sec))
+			return;
+		// called by doh.robot.setClipboard
+		// see it for details
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+				StringSelection ss = new StringSelection(data);
+				getSystemClipboard().setContents(ss, ss);
+				return null;
+			}
+		});
+	}
+	
+	public void setClipboardHtml(double sec, final String data) {
+		if(!isSecure(sec))
+			return;
+		// called by doh.robot.setClipboard when format=='text/html'
+		// see it for details
+		AccessController.doPrivileged(new PrivilegedAction(){
+			public Object run(){
+			    String mimeType = "text/html;class=java.lang.String";//type + "; charset=" + charset;// + "; class=" + transferType;
+			    TextTransferable transferable = new TextTransferable(mimeType, data);
+			    getSystemClipboard().setContents(transferable, transferable);
+				return null;
+			}
+		});
+	}
+	private static java.awt.datatransfer.Clipboard getSystemClipboard() {
+		return toolkit.getSystemClipboard();
+	}
+	
+	private static class TextTransferable implements Transferable, ClipboardOwner {
+		private String data;
+		private static ArrayList htmlFlavors = new ArrayList();
+		
+		static{
+			try{
+				htmlFlavors.add(new DataFlavor("text/plain;charset=UTF-8;class=java.lang.String"));
+				htmlFlavors.add(new DataFlavor("text/html;charset=UTF-8;class=java.lang.String"));
+			}catch(ClassNotFoundException ex){
+				ex.printStackTrace();
+			}
+		}
+		
+		
+		public TextTransferable(String mimeType, String data){
+			this.data = data;
+		}
+		
+		public DataFlavor[] getTransferDataFlavors(){
+			return (DataFlavor[]) htmlFlavors.toArray(new DataFlavor[htmlFlavors.size()]);
+		}
+		
+		public boolean isDataFlavorSupported(DataFlavor flavor){
+			return htmlFlavors.contains(flavor);
+		}
+		
+		public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException{
+			if (String.class.equals(flavor.getRepresentationClass())){
+		        return data;
+		    }
+		
+		    throw new UnsupportedFlavorException(flavor);
+		
+		}
+		
+		public void lostOwnership(java.awt.datatransfer.Clipboard clipboard, Transferable contents){
+			data = null;
+		}
+	}
+}
diff --git a/util/doh/robot/README b/util/doh/robot/README
new file mode 100644
index 0000000..79bd158
--- /dev/null
+++ b/util/doh/robot/README
@@ -0,0 +1,19 @@
+Notes on generating JAR file:
+
+PC
+--
+1. Download JDK 1.4.
+2. create key file called "key" (using keytool and jarsigner?)
+3. compilerobot.bat
+
+MAC
+---
+I used the version of java preinstalled and the mac and it seemed to work.
+
+1. create key file:
+
+  $ keytool -genkey -alias dojo
+
+2. Run compilerobot.sh (creates DOHRobot.jar):
+
+  $ sh compilerobot.sh
diff --git a/util/doh/robot/compilerobot.bat b/util/doh/robot/compilerobot.bat
new file mode 100644
index 0000000..e0769fe
--- /dev/null
+++ b/util/doh/robot/compilerobot.bat
@@ -0,0 +1,10 @@
+setlocal
+set JDK14_HOME=C:\j2sdk1.4.2_19
+del DOHRobot*.class
+%JDK14_HOME%\bin\javac -target 1.4 -classpath %JDK14_HOME%\jre\lib\plugin.jar DOHRobot.java
+rem del DOHRobot.jar
+%JDK14_HOME%\bin\jar xvf DOHRobot.jar META-INF
+%JDK14_HOME%\bin\jar cvf DOHRobot.jar DOHRobot*.class META-INF
+rem %JDK14_HOME%\bin\jarsigner -keystore ./dohrobot DOHRobot.jar dojo <key
+del DOHRobot*.class
+endlocal
diff --git a/util/doh/robot/compilerobot.sh b/util/doh/robot/compilerobot.sh
new file mode 100644
index 0000000..2899ecc
--- /dev/null
+++ b/util/doh/robot/compilerobot.sh
@@ -0,0 +1,8 @@
+rm DOHRobot*.class
+javac -classpath /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Home/lib/plugin.jar DOHRobot.java
+
+rm DOHRobot.jar
+jar cvf DOHRobot.jar DOHRobot*.class
+rm DOHRobot*.class
+
+jarsigner DOHRobot.jar dojo
diff --git a/util/doh/robot/robot.css b/util/doh/robot/robot.css
new file mode 100644
index 0000000..6fee7a6
--- /dev/null
+++ b/util/doh/robot/robot.css
@@ -0,0 +1,4 @@
+/* robot */
+HTML.dohRobot * {
+	cursor: progress !important;
+}
diff --git a/util/doh/runner.html b/util/doh/runner.html
new file mode 100644
index 0000000..930d755
--- /dev/null
+++ b/util/doh/runner.html
@@ -0,0 +1,320 @@
+<html>
+	<!--
+		NOTE: we are INTENTIONALLY in quirks mode. It makes it much easier to
+		get a "full screen" UI w/ straightforward CSS.
+	-->
+	<!--
+		// TODO: provide a UI for prompted tests
+	-->
+	<head>
+		<title>The Dojo Unit Test Harness, $Rev: 22331 $</title>
+
+		<script type="text/javascript">
+			// workaround for bug in Safari 3.  See #7189
+			if (/3[\.0-9]+ Safari/.test(navigator.appVersion))
+			{
+				window.console = {
+				    origConsole: window.console,
+				    log: function(s){
+						this.origConsole.log(s);
+					},
+					info: function(s){
+						this.origConsole.info(s);
+					},
+					error: function(s){
+						this.origConsole.error(s);
+					},
+					warn: function(s){
+						this.origConsole.warn(s);
+					}
+				};
+			}
+		</script>
+
+		<script type="text/javascript">
+			window.dojoUrl = "../../dojo/dojo.js";
+			window.testUrl = "";
+			window.testModule = "";
+
+			// parse out our test URL and our Dojo URL from the query string
+			var qstr = window.location.search.substr(1);
+			if(qstr.length){
+				var qparts = qstr.split("&");
+				for(var x=0; x<qparts.length; x++){
+					var tp = qparts[x].split("="), name=tp[0], value=tp[1].replace(/[<>"':\(\)]/g, "");	// replace() to avoid XSS attack
+					//Avoid URLs that use the same protocol but on other domains, for security reasons.
+					if (value.indexOf("//") === 0 || value.indexOf("\\\\") === 0) {
+						throw "Insupported URL";
+					}
+					switch(name){
+						case "dojoUrl":
+						case "testUrl":
+						case "testModule":
+							window[name] = value;
+							break;
+						case "registerModulePath":
+							var modules = value.split(";");
+							window.registerModulePath=[];
+							for (var i=0; i<modules.length;i++){
+								window.registerModulePath.push(modules[i].split(","));
+							}
+						break;
+					}
+				}
+			}
+
+			document.write("<scr"+"ipt type='text/javascript' djConfig='isDebug: true' src='"+dojoUrl+"'></scr"+"ipt>");
+		</script>
+		<script type="text/javascript">
+			try{
+				dojo.require("doh.runner");
+			}catch(e){
+				document.write("<scr"+"ipt type='text/javascript' src='runner.js'></scr"+"ipt>");
+			}
+			if(testUrl.length){
+				document.write("<scr"+"ipt type='text/javascript' src='"+testUrl+".js'></scr"+"ipt>");
+			}
+		</script>
+		<style type="text/css">
+			@import "../../dojo/resources/dojo.css";
+			/*
+			body {
+				margin: 0px;
+				padding: 0px;
+				font-size: 13px;
+				color: #292929;
+				font-family: Myriad, Lucida Grande, Bitstream Vera Sans, Arial, Helvetica, sans-serif;
+				*font-size: small;
+				*font: x-small;
+			}
+
+			th, td {
+				font-size: 13px;
+				color: #292929;
+				font-family: Myriad, Lucida Grande, Bitstream Vera Sans, Arial, Helvetica, sans-serif;
+				font-weight: normal;
+			}
+
+			* body {
+				line-height: 1.25em;
+			}
+			
+			table {
+				border-collapse: collapse;
+			}
+			*/
+
+			#testLayout {
+				position: relative;
+				left: 0px;
+				top: 0px;
+				width: 100%;
+				height: 100%;
+				border: 1px solid black;
+				border: 0px;
+			}
+
+			.tabBody {
+				margin: 0px;
+				padding: 0px;
+				/*
+				border: 1px solid black;
+				*/
+				background-color: #DEDEDE;
+				border: 0px;
+				width: 100%;
+				height: 100%;
+				position: absolute;
+				left: 0px; 
+				top: 0px;
+				overflow: auto;
+			}
+
+			#logBody {
+				padding-left: 5px;
+				padding-top: 5px;
+				font-family: Monaco, monospace;
+				font-size: 11px;
+				white-space: pre;
+			}
+
+			#progressOuter {
+				background:#e9e9e9 url("http://o.aolcdn.com/dojo/1.3/dijit/themes/tundra/images/dojoTundraGradientBg.png") repeat-x 0 0;
+				height: 1em;
+				/*the following trick is necessary to prevent IE from wrapping the last piece of progress bar into a new line*/
+				_margin:1px;
+				_padding: -1px;
+				
+				/*
+				border-color: #e8e8e8;
+				*/
+			}
+
+			#progressOuter .success, #progressOuter .failure{
+				float: left;
+				height: 1em;
+			}
+
+			#play, #pause {
+				font-family: Arial;
+				font-size: 1.4em;
+				border: 1px solid #DEDEDE;
+				cursor: pointer;
+				padding-right: 0.5em;
+			}
+
+			.header {
+				border: 1px solid #DEDEDE;
+			}
+
+			button.tab {
+				border-width: 1px 1px 0px 1px;
+				border-style: solid;
+				border-color: #DEDEDE;
+				margin-right: 5px;
+			}
+
+			#testListContainer {
+				/*
+				border: 1px solid black;
+				*/
+				position: relative;
+				height: 99%;
+				width: 100%;
+				overflow: auto;
+			}
+
+			#testList {
+				border-collapse: collapse;
+				position: absolute;
+				left: 0px;
+				width: 100%;
+			}
+
+			#testList td {
+				border-bottom: 1px solid #DEDEDE;
+				border-right : 1px solid #DEDEDE;
+				padding: 3px;
+			}
+
+			#testListHeader th {
+				border-bottom: 1px solid #DEDEDE;
+				border-right : 1px solid #DEDEDE;
+				padding: 3px;
+				font-weight: bolder;
+				font-style: italic;
+			}
+			
+			#testList tfoot {
+				font-weight: bold;
+			}
+
+			#toggleButtons {
+				float: left;
+				background-color: #DEDEDE;
+			}
+
+			div.testGroupName {
+				position: absolute;
+			}
+
+			.inProgress {
+				background-color: #85afde;
+			}
+
+			.success {
+				background-color: #7cdea7;
+			}
+
+			.failure {
+				background-color: #de827b;
+			}
+		</style>
+	</head>
+	<body>
+		<table id="testLayout" cellpadding="0" cellspacing="0" style="margin: 0;">
+			<tr valign="top" height="40">
+				<td colspan="2" id="logoBar">
+					<h3 style="margin: 5px 5px 0px 5px; float: left;">D.O.H.: The Dojo Objective Harness</h3>
+					<img src="small_logo.png" height="40" style="margin: 0px 5px 0px 5px; float: right;">
+					<span style="margin: 10px 5px 0px 5px; float: right;">
+						<input type="checkbox" id="audio" name="audio">
+						<label for="audio">sounds?</label>
+					</span>
+				</td>
+			</tr>
+			<tr valign="top" height="10">
+				<td colspan="2"><div id="progressOuter" onclick="doh._jumpToSuite(arguments[0]);"></div></td>
+			</tr>
+			<tr valign="top" height="30">
+				<td width="30%" class="header">
+					<span id="toggleButtons" onclick="doh.togglePaused();">
+						<button id="play">►</button>
+						<button id="pause" style="display: none;">║</button>
+					</span>
+					<span id="runningStatus">
+						<span id="pausedMsg">Stopped</span>
+						<span id="playingMsg" style="display: none;">Tests Running</span>
+					</span>
+				</td>
+				<td width="*" class="header" valign="bottom">
+					<button class="tab" onclick="doh.showTestPage();">Test Page</button>
+					<button class="tab" onclick="doh.showLogPage();">Log</button>
+                    <button class="tab" onclick="doh.showPerfTestsPage();">Performance Tests Results</button>
+				</td>
+			</tr>
+			<tr valign="top" style="border: 0; padding: 0; margin: 0;">
+				<td height="100%" style="border: 0; padding: 0; margin: 0;">
+					<div id="testListContainer">
+						<table cellpadding="0" cellspacing="0" border="0"
+							width="100%" id="testList" style="margin: 0;" onclick="doh._jumpToLog(arguments[0]);">
+							<thead>
+								<tr id="testListHeader" style="border: 0; padding: 0; margin: 0;" >
+									<th> </th>
+									<th width="20">
+										<input type="checkbox" checked 
+											onclick="doh.toggleRunAll();">
+									</th>
+									<th width="*" style="text-align: left;">test</th>
+									<th width="50">time</th>
+								</tr>
+							</thead>
+							<tbody valign="top">
+								<tr id="groupTemplate" style="display: none;">
+									<td style="font-family: Arial; width: 15px;">►</td>
+									<td>
+										<input type="checkbox" checked>
+									</td>
+									<td>group name</td>
+									<td>10ms</td>
+								</tr>
+								<tr id="testTemplate" style="display: none;">
+									<td> </td>
+									<td> </td>
+									<td style="padding-left: 20px;">test name</td>
+									<td>10ms</td>
+								</tr>
+							</tbody>
+						</table>
+					</div>
+				</td>
+				<td>
+					<div style="position: relative; width: 99%; height: 100%; top: 0px; left: 0px;">
+						<div class="tabBody"
+							style="z-index: 1;">
+							<pre id="logBody"></pre>
+							<div id="perfTestsBody" style="background-color: white;"></div>
+						</div>
+						<iframe id="testBody" class="tabBody"
+							style="z-index: -1;"></iframe>
+						<!--
+							src="http://redesign.dojotoolkit.org"></iframe>
+						-->
+					</div>
+				</td>
+			</tr>
+		</table>
+		<span id="hiddenAudio"></span>
+	</body>
+</html>
+
diff --git a/util/doh/runner.js b/util/doh/runner.js
new file mode 100644
index 0000000..729299c
--- /dev/null
+++ b/util/doh/runner.js
@@ -0,0 +1,1503 @@
+// package system gunk.
+try{
+	dojo.provide("doh.runner");
+}catch(e){
+	if(!this["doh"]){
+		doh = {};
+	}
+}
+
+//
+// Utility Functions and Classes
+//
+
+doh.selfTest = false;
+
+doh.global = this;
+
+doh.hitch = function(/*Object*/thisObject, /*Function|String*/method /*, ...*/){
+	var args = [];
+	for(var x=2; x<arguments.length; x++){
+		args.push(arguments[x]);
+	}
+	var fcn = ((typeof method == "string") ? thisObject[method] : method) || function(){};
+	return function(){
+		var ta = args.concat([]); // make a copy
+		for(var x=0; x<arguments.length; x++){
+			ta.push(arguments[x]);
+		}
+		return fcn.apply(thisObject, ta); // Function
+	};
+}
+
+doh._mixin = function(/*Object*/ obj, /*Object*/ props){
+	// summary:
+	//		Adds all properties and methods of props to obj. This addition is
+	//		"prototype extension safe", so that instances of objects will not
+	//		pass along prototype defaults.
+	var tobj = {};
+	for(var x in props){
+		// the "tobj" condition avoid copying properties in "props"
+		// inherited from Object.prototype.  For example, if obj has a custom
+		// toString() method, don't overwrite it with the toString() method
+		// that props inherited from Object.protoype
+		if(tobj[x] === undefined || tobj[x] != props[x]){
+			obj[x] = props[x];
+		}
+	}
+	// IE doesn't recognize custom toStrings in for..in
+	if(	this["document"] 
+		&& document.all
+		&& (typeof props["toString"] == "function")
+		&& (props["toString"] != obj["toString"])
+		&& (props["toString"] != tobj["toString"])
+	){
+		obj.toString = props.toString;
+	}
+	return obj; // Object
+}
+
+doh.mixin = function(/*Object*/obj, /*Object...*/props){
+	// summary:	Adds all properties and methods of props to obj. 
+	for(var i=1, l=arguments.length; i<l; i++){
+		doh._mixin(obj, arguments[i]);
+	}
+	return obj; // Object
+}
+
+doh.extend = function(/*Object*/ constructor, /*Object...*/ props){
+	// summary:
+	//		Adds all properties and methods of props to constructor's
+	//		prototype, making them available to all instances created with
+	//		constructor.
+	for(var i=1, l=arguments.length; i<l; i++){
+		doh._mixin(constructor.prototype, arguments[i]);
+	}
+	return constructor; // Object
+}
+
+
+doh._line = "------------------------------------------------------------";
+
+/*
+doh._delegate = function(obj, props){
+	// boodman-crockford delegation
+	function TMP(){};
+	TMP.prototype = obj;
+	var tmp = new TMP();
+	if(props){
+		dojo.lang.mixin(tmp, props);
+	}
+	return tmp;
+}
+*/
+
+doh.debug = function(){
+	// summary:
+	//		takes any number of arguments and sends them to whatever debugging
+	//		or logging facility is available in this environment
+
+	// YOUR TEST RUNNER NEEDS TO IMPLEMENT THIS
+}
+
+doh.error = function(){
+	// summary:
+	//		logging method to be used to send Error objects, so that
+	//		whatever debugging or logging facility you have can decide to treat it
+	//		as an Error object and show additional information - such as stack trace
+
+	// YOUR TEST RUNNER NEEDS TO IMPLEMENT THIS
+}
+
+doh._AssertFailure = function(msg, hint){
+	// idea for this as way of dis-ambiguating error types is from JUM. 
+	// The JUM is dead! Long live the JUM!
+
+	if(!(this instanceof doh._AssertFailure)){
+		return new doh._AssertFailure(msg, hint);
+	}
+	if(hint){
+		msg = (new String(msg||""))+" with hint: \n\t\t"+(new String(hint)+"\n");
+	}
+	this.message = new String(msg||"");
+	return this;
+}
+doh._AssertFailure.prototype = new Error();
+doh._AssertFailure.prototype.constructor = doh._AssertFailure;
+doh._AssertFailure.prototype.name = "doh._AssertFailure";
+
+doh.Deferred = function(canceller){
+	this.chain = [];
+	this.id = this._nextId();
+	this.fired = -1;
+	this.paused = 0;
+	this.results = [null, null];
+	this.canceller = canceller;
+	this.silentlyCancelled = false;
+};
+
+doh.extend(doh.Deferred, {
+	getTestErrback: function(cb, scope){
+		// summary: Replaces outer getTextCallback's in nested situations to avoid multiple callback(true)'s
+		var _this = this;
+		return function(){
+			try{
+				cb.apply(scope||doh.global||_this, arguments);
+			}catch(e){
+				_this.errback(e);
+			}
+		};
+	},
+
+	getTestCallback: function(cb, scope){
+		var _this = this;
+		return function(){
+			try{
+				cb.apply(scope||doh.global||_this, arguments);
+			}catch(e){
+				_this.errback(e);
+				return;
+			}
+			_this.callback(true);
+		};
+	},
+
+	getFunctionFromArgs: function(){
+		var a = arguments;
+		if((a[0])&&(!a[1])){
+			if(typeof a[0] == "function"){
+				return a[0];
+			}else if(typeof a[0] == "string"){
+				return doh.global[a[0]];
+			}
+		}else if((a[0])&&(a[1])){
+			return doh.hitch(a[0], a[1]);
+		}
+		return null;
+	},
+
+	makeCalled: function() {
+		var deferred = new doh.Deferred();
+		deferred.callback();
+		return deferred;
+	},
+
+	_nextId: (function(){
+		var n = 1;
+		return function(){ return n++; };
+	})(),
+
+	cancel: function(){
+		if(this.fired == -1){
+			if (this.canceller){
+				this.canceller(this);
+			}else{
+				this.silentlyCancelled = true;
+			}
+			if(this.fired == -1){
+				this.errback(new Error("Deferred(unfired)"));
+			}
+		}else if(this.fired == 0 &&
+					(this.results[0] instanceof doh.Deferred)){
+			this.results[0].cancel();
+		}
+	},
+			
+
+	_pause: function(){
+		this.paused++;
+	},
+
+	_unpause: function(){
+		this.paused--;
+		if ((this.paused == 0) && (this.fired >= 0)) {
+			this._fire();
+		}
+	},
+
+	_continue: function(res){
+		this._resback(res);
+		this._unpause();
+	},
+
+	_resback: function(res){
+		this.fired = ((res instanceof Error) ? 1 : 0);
+		this.results[this.fired] = res;
+		this._fire();
+	},
+
+	_check: function(){
+		if(this.fired != -1){
+			if(!this.silentlyCancelled){
+				throw new Error("already called!");
+			}
+			this.silentlyCancelled = false;
+			return;
+		}
+	},
+
+	callback: function(res){
+		this._check();
+		this._resback(res);
+	},
+
+	errback: function(res){
+		this._check();
+		if(!(res instanceof Error)){
+			res = new Error(res);
+		}
+		this._resback(res);
+	},
+
+	addBoth: function(cb, cbfn){
+		var enclosed = this.getFunctionFromArgs(cb, cbfn);
+		if(arguments.length > 2){
+			enclosed = doh.hitch(null, enclosed, arguments, 2);
+		}
+		return this.addCallbacks(enclosed, enclosed);
+	},
+
+	addCallback: function(cb, cbfn){
+		var enclosed = this.getFunctionFromArgs(cb, cbfn);
+		if(arguments.length > 2){
+			enclosed = doh.hitch(null, enclosed, arguments, 2);
+		}
+		return this.addCallbacks(enclosed, null);
+	},
+
+	addErrback: function(cb, cbfn){
+		var enclosed = this.getFunctionFromArgs(cb, cbfn);
+		if(arguments.length > 2){
+			enclosed = doh.hitch(null, enclosed, arguments, 2);
+		}
+		return this.addCallbacks(null, enclosed);
+	},
+
+	addCallbacks: function(cb, eb){
+		this.chain.push([cb, eb]);
+		if(this.fired >= 0){
+			this._fire();
+		}
+		return this;
+	},
+
+	_fire: function(){
+		var chain = this.chain;
+		var fired = this.fired;
+		var res = this.results[fired];
+		var self = this;
+		var cb = null;
+		while(chain.length > 0 && this.paused == 0){
+			// Array
+			var pair = chain.shift();
+			var f = pair[fired];
+			if(f == null){
+				continue;
+			}
+			try {
+				res = f(res);
+				fired = ((res instanceof Error) ? 1 : 0);
+				if(res instanceof doh.Deferred){
+					cb = function(res){
+						self._continue(res);
+					};
+					this._pause();
+				}
+			}catch(err){
+				fired = 1;
+				res = err;
+			}
+		}
+		this.fired = fired;
+		this.results[fired] = res;
+		if((cb)&&(this.paused)){
+			res.addBoth(cb);
+		}
+	}
+});
+
+//
+// State Keeping and Reporting
+//
+
+doh._testCount = 0;
+doh._groupCount = 0;
+doh._errorCount = 0;
+doh._failureCount = 0;
+doh._currentGroup = null;
+doh._currentTest = null;
+doh._paused = true;
+
+doh._init = function(){
+	this._currentGroup = null;
+	this._currentTest = null;
+	this._errorCount = 0;
+	this._failureCount = 0;
+	this.debug(this._testCount, "tests to run in", this._groupCount, "groups");
+}
+
+// doh._urls = [];
+doh._groups = {};
+
+//
+// Test Registration
+//
+
+doh.registerTestNs = function(/*String*/ group, /*Object*/ ns){
+	// summary:
+	//		adds the passed namespace object to the list of objects to be
+	//		searched for test groups. Only "public" functions (not prefixed
+	//		with "_") will be added as tests to be run. If you'd like to use
+	//		fixtures (setUp(), tearDown(), and runTest()), please use
+	//		registerTest() or registerTests().
+	for(var x in ns){
+		if(	(x.charAt(0) != "_") &&
+			(typeof ns[x] == "function") ){
+			this.registerTest(group, ns[x]);
+		}
+	}
+}
+
+doh._testRegistered = function(group, fixture){
+	// slot to be filled in
+}
+
+doh._groupStarted = function(group){
+	// slot to be filled in
+}
+
+doh._groupFinished = function(group, success){
+	// slot to be filled in
+}
+
+doh._testStarted = function(group, fixture){
+	// slot to be filled in
+}
+
+doh._testFinished = function(group, fixture, success){
+	// slot to be filled in
+}
+
+doh.registerGroup = function(	/*String*/ group, 
+								/*Array||Function||Object*/ tests, 
+								/*Function*/ setUp, 
+								/*Function*/ tearDown,
+								/*String*/ type){
+	// summary:
+	//		registers an entire group of tests at once and provides a setUp and
+	//		tearDown facility for groups. If you call this method with only
+	//		setUp and tearDown parameters, they will replace previously
+	//		installed setUp or tearDown functions for the group with the new
+	//		methods.
+	// group:
+	//		string name of the group
+	// tests:
+	//		either a function or an object or an array of functions/objects. If
+	//		an object, it must contain at *least* a "runTest" method, and may
+	//		also contain "setUp" and "tearDown" methods. These will be invoked
+	//		on either side of the "runTest" method (respectively) when the test
+	//		is run. If an array, it must contain objects matching the above
+	//		description or test functions.
+	// setUp: a function for initializing the test group
+	// tearDown: a function for initializing the test group
+	// type: The type of tests these are, such as a group of performance tests
+	//		null/undefied are standard DOH tests, the valye 'perf' enables 
+	//		registering them as performance tests.
+	if(tests){
+		this.register(group, tests, type);
+	}
+	if(setUp){
+		this._groups[group].setUp = setUp;
+	}
+	if(tearDown){
+		this._groups[group].tearDown = tearDown;
+	}
+}
+
+doh._getTestObj = function(group, test, type){
+	var tObj = test;
+	if(typeof test == "string"){
+		if(test.substr(0, 4)=="url:"){
+			return this.registerUrl(group, test);
+		}else{
+			tObj = {
+				name: test.replace("/\s/g", "_") // FIXME: bad escapement
+			};
+			tObj.runTest = new Function("t", test);
+		}
+	}else if(typeof test == "function"){
+		// if we didn't get a fixture, wrap the function
+		tObj = { "runTest": test };
+		if(test["name"]){
+			tObj.name = test.name;
+		}else{
+			try{
+				var fStr = "function ";
+				var ts = tObj.runTest+"";
+				if(0 <= ts.indexOf(fStr)){
+					tObj.name = ts.split(fStr)[1].split("(", 1)[0];
+				}
+				// doh.debug(tObj.runTest.toSource());
+			}catch(e){
+			}
+		}
+		// FIXME: try harder to get the test name here
+	}
+
+	//Augment the test with some specific options to make it identifiable as a 
+	//particular type of test so it can be executed properly.
+	if(type === "perf" || tObj.testType === "perf"){
+		tObj.testType = "perf";
+
+		//Build an object on the root DOH class to contain all the test results.
+		//Cache it on the test object for quick lookup later for results storage.
+		if(!doh.perfTestResults){
+			doh.perfTestResults = {};
+			doh.perfTestResults[group] = {};
+		}
+		if(!doh.perfTestResults[group]){
+			doh.perfTestResults[group] = {};
+		}
+		if(!doh.perfTestResults[group][tObj.name]){
+			doh.perfTestResults[group][tObj.name] = {};
+		}
+		tObj.results = doh.perfTestResults[group][tObj.name];
+		
+		//If it's not set, then set the trial duration 
+		//default to 100ms.
+		if(!("trialDuration" in tObj)){
+			tObj.trialDuration = 100;
+		}
+		
+		//If it's not set, then set the delay between trial runs to 100ms
+		//default to 100ms to allow for GC and to make IE happy.
+		if(!("trialDelay" in tObj)){
+			tObj.trialDelay = 100;
+		}
+
+		//If it's not set, then set number of times a trial is run to 10.
+		if(!("trialIterations" in tObj)){
+			tObj.trialIterations = 10;
+		}
+	} 
+	return tObj;
+}
+
+doh.registerTest = function(/*String*/ group, /*Function||Object*/ test, /*String*/ type){
+	// summary:
+	//		add the provided test function or fixture object to the specified
+	//		test group.
+	// group:
+	//		string name of the group to add the test to
+	// test:
+	//		either a function or an object. If an object, it must contain at
+	//		*least* a "runTest" method, and may also contain "setUp" and
+	//		"tearDown" methods. These will be invoked on either side of the
+	//		"runTest" method (respectively) when the test is run.
+	// type:
+	//		An identifier denoting the type of testing that the test performs, such
+	//		as a performance test.  If null, defaults to regular DOH test.
+	if(!this._groups[group]){
+		this._groupCount++;
+		this._groups[group] = [];
+		this._groups[group].inFlight = 0;
+	}
+	var tObj = this._getTestObj(group, test, type);
+	if(!tObj){ return null; }
+	this._groups[group].push(tObj);
+	this._testCount++;
+	this._testRegistered(group, tObj);
+	return tObj;
+}
+
+doh.registerTests = function(/*String*/ group, /*Array*/ testArr, /*String*/ type){
+	// summary:
+	//		registers a group of tests, treating each element of testArr as
+	//		though it were being (along with group) passed to the registerTest
+	//		method.  It also uses the type to decide how the tests should
+	//		behave, by defining the type of tests these are, such as performance tests
+	for(var x=0; x<testArr.length; x++){
+		this.registerTest(group, testArr[x], type);
+	}
+}
+
+// FIXME: move implementation to _browserRunner?
+doh.registerUrl = function(	/*String*/ group, 
+								/*String*/ url, 
+								/*Integer*/ timeout,
+								/*String*/ type){
+	this.debug("ERROR:");
+	this.debug("\tNO registerUrl() METHOD AVAILABLE.");
+	// this._urls.push(url);
+}
+
+doh.registerString = function(group, str, type){
+}
+
+// FIXME: remove the doh.add alias SRTL.
+doh.register = doh.add = function(groupOrNs, testOrNull, type){
+	// summary:
+	// 		"magical" variant of registerTests, registerTest, and
+	// 		registerTestNs. Will accept the calling arguments of any of these
+	// 		methods and will correctly guess the right one to register with.
+	if(	(arguments.length == 1)&&
+		(typeof groupOrNs == "string") ){
+		if(groupOrNs.substr(0, 4)=="url:"){
+			this.registerUrl(groupOrNs, null, null, type);
+		}else{
+			this.registerTest("ungrouped", groupOrNs, type);
+		}
+	}
+	if(arguments.length == 1){
+		this.debug("invalid args passed to doh.register():", groupOrNs, ",", testOrNull);
+		return;
+	}
+	if(typeof testOrNull == "string"){
+		if(testOrNull.substr(0, 4)=="url:"){
+			this.registerUrl(testOrNull, null, null, type);
+		}else{
+			this.registerTest(groupOrNs, testOrNull, type);
+		}
+		// this.registerTestNs(groupOrNs, testOrNull);
+		return;
+	}
+	if(doh._isArray(testOrNull)){
+		this.registerTests(groupOrNs, testOrNull, type);
+		return;
+	}
+	this.registerTest(groupOrNs, testOrNull, type);
+};
+
+doh.registerDocTests = function(module){
+	// no-op for when Dojo isn't loaded into the page
+	this.debug("registerDocTests() requires dojo to be loaded into the environment. Skipping doctest set for module:", module);
+};
+(function(){
+	if(typeof dojo != "undefined"){
+		try{
+			dojo.require("dojox.testing.DocTest");
+		}catch(e){
+			// if the DocTest module isn't available (e.g., the build we're
+			// running from doesn't include it), stub it out and log the error
+			console.debug(e);
+
+			doh.registerDocTests = function(){}
+			return;
+		}
+		doh.registerDocTests = function(module){
+			//	summary:
+			//		Get all the doctests from the given module and register each of them
+			//		as a single test case here.
+			//
+			
+			var docTest = new dojox.testing.DocTest();
+			var docTests = docTest.getTests(module);
+			var len = docTests.length;
+			var tests = [];
+			for (var i=0; i<len; i++){
+				var test = docTests[i];
+				// Extract comment on first line and add to test name.
+				var comment = "";
+				if (test.commands.length && test.commands[0].indexOf("//")!=-1) {
+					var parts = test.commands[0].split("//");
+					comment = ", "+parts[parts.length-1]; // Get all after the last //, so we dont get trapped by http:// or alikes :-).
+				}
+				tests.push({
+					runTest: (function(test){ 
+						return function(t){
+							var r = docTest.runTest(test.commands, test.expectedResult);
+							t.assertTrue(r.success);
+						}
+					})(test),
+					name:"Line "+test.line+comment
+				}
+				);
+			}
+			this.register("DocTests: "+module, tests);
+		}
+	}
+})();
+
+//
+// Assertions and In-Test Utilities
+//
+
+doh.t = doh.assertTrue = function(/*Object*/ condition, /*String?*/ hint){
+	// summary:
+	//		is the passed item "truthy"?
+	if(arguments.length < 1){ 
+		throw new doh._AssertFailure("assertTrue failed because it was not passed at least 1 argument"); 
+	} 
+	if(!eval(condition)){
+		throw new doh._AssertFailure("assertTrue('" + condition + "') failed", hint);
+	}
+}
+
+doh.f = doh.assertFalse = function(/*Object*/ condition, /*String?*/ hint){
+	// summary:
+	//		is the passed item "falsey"?
+	if(arguments.length < 1){ 
+		throw new doh._AssertFailure("assertFalse failed because it was not passed at least 1 argument"); 
+	} 
+	if(eval(condition)){
+		throw new doh._AssertFailure("assertFalse('" + condition + "') failed", hint);
+	}
+}
+
+doh.e = doh.assertError = function(/*Error object*/expectedError, /*Object*/scope, /*String*/functionName, /*Array*/args, /*String?*/ hint){
+	//	summary:
+	//		Test for a certain error to be thrown by the given function.
+	//	example:
+	//		t.assertError(dojox.data.QueryReadStore.InvalidAttributeError, store, "getValue", [item, "NOT THERE"]);
+	//		t.assertError(dojox.data.QueryReadStore.InvalidItemError, store, "getValue", ["not an item", "NOT THERE"]);
+	try{
+		scope[functionName].apply(scope, args);
+	}catch (e){
+		if(e instanceof expectedError){
+			return true;
+		}else{
+			throw new doh._AssertFailure("assertError() failed:\n\texpected error\n\t\t"+expectedError+"\n\tbut got\n\t\t"+e+"\n\n", hint);
+		}
+	}
+	throw new doh._AssertFailure("assertError() failed:\n\texpected error\n\t\t"+expectedError+"\n\tbut no error caught\n\n", hint);
+}
+
+
+doh.is = doh.assertEqual = function(/*Object*/ expected, /*Object*/ actual, /*String?*/ hint){
+	// summary:
+	//		are the passed expected and actual objects/values deeply
+	//		equivalent?
+
+	// Compare undefined always with three equal signs, because undefined==null
+	// is true, but undefined===null is false. 
+	if((expected === undefined)&&(actual === undefined)){ 
+		return true;
+	}
+	if(arguments.length < 2){ 
+		throw doh._AssertFailure("assertEqual failed because it was not passed 2 arguments"); 
+	} 
+	if((expected === actual)||(expected == actual)||
+				( typeof expected == "number" && typeof actual == "number" && isNaN(expected) && isNaN(actual) )){ 
+		return true;
+	}
+	if(	(this._isArray(expected) && this._isArray(actual))&&
+		(this._arrayEq(expected, actual)) ){
+		return true;
+	}
+	if( ((typeof expected == "object")&&((typeof actual == "object")))&&
+		(this._objPropEq(expected, actual)) ){
+		return true;
+	}
+	throw new doh._AssertFailure("assertEqual() failed:\n\texpected\n\t\t"+expected+"\n\tbut got\n\t\t"+actual+"\n\n", hint);
+}
+
+doh.isNot = doh.assertNotEqual = function(/*Object*/ notExpected, /*Object*/ actual, /*String?*/ hint){
+	// summary:
+	//		are the passed notexpected and actual objects/values deeply
+	//		not equivalent?
+
+	// Compare undefined always with three equal signs, because undefined==null
+	// is true, but undefined===null is false. 
+	if((notExpected === undefined)&&(actual === undefined)){ 
+        throw new doh._AssertFailure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
+	}
+	if(arguments.length < 2){ 
+		throw doh._AssertFailure("assertEqual failed because it was not passed 2 arguments"); 
+	} 
+	if((notExpected === actual)||(notExpected == actual)){ 
+        throw new doh._AssertFailure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
+	}
+	if(	(this._isArray(notExpected) && this._isArray(actual))&&
+		(this._arrayEq(notExpected, actual)) ){
+		throw new doh._AssertFailure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
+	}
+	if( ((typeof notExpected == "object")&&((typeof actual == "object")))&&
+		(this._objPropEq(notExpected, actual)) ){
+        throw new doh._AssertFailure("assertNotEqual() failed: not expected |"+notExpected+"| but got |"+actual+"|", hint);
+	}
+    return true;
+}
+
+doh._arrayEq = function(expected, actual){
+	if(expected.length != actual.length){ return false; }
+	// FIXME: we're not handling circular refs. Do we care?
+	for(var x=0; x<expected.length; x++){
+		if(!doh.assertEqual(expected[x], actual[x])){ return false; }
+	}
+	return true;
+}
+
+doh._objPropEq = function(expected, actual){
+	// Degenerate case: if they are both null, then their "properties" are equal.
+	if(expected === null && actual === null){
+		return true;
+	}
+	// If only one is null, they aren't equal.
+	if(expected === null || actual === null){
+		return false;
+	}
+	if(expected instanceof Date){
+		return actual instanceof Date && expected.getTime()==actual.getTime();
+	}
+	var x;
+	// Make sure ALL THE SAME properties are in both objects!
+	for(x in actual){ // Lets check "actual" here, expected is checked below.
+		if(expected[x] === undefined){
+			return false;
+		}
+	};
+
+	for(x in expected){
+		if(!doh.assertEqual(expected[x], actual[x])){
+			return false;
+		}
+	}
+	return true;
+}
+
+doh._isArray = function(it){
+	return (it && it instanceof Array || typeof it == "array" || 
+		(
+			!!doh.global["dojo"] &&
+			doh.global["dojo"]["NodeList"] !== undefined && 
+			it instanceof doh.global["dojo"]["NodeList"]
+		)
+	);
+}
+
+//
+// Runner-Wrapper
+//
+
+doh._setupGroupForRun = function(/*String*/ groupName, /*Integer*/ idx){
+	var tg = this._groups[groupName];
+	this.debug(this._line);
+	this.debug("GROUP", "\""+groupName+"\"", "has", tg.length, "test"+((tg.length > 1) ? "s" : "")+" to run");
+}
+
+doh._handleFailure = function(groupName, fixture, e){
+	// this.debug("FAILED test:", fixture.name);
+	// mostly borrowed from JUM
+	this._groups[groupName].failures++;
+	var out = "";
+	if(e instanceof this._AssertFailure){
+		this._failureCount++;
+		if(e["fileName"]){ out += e.fileName + ':'; }
+		if(e["lineNumber"]){ out += e.lineNumber + ' '; }
+		out += e+": "+e.message;
+		this.debug("\t_AssertFailure:", out);
+	}else{
+		this._errorCount++;
+	}
+	this.error(e);
+	if(fixture.runTest["toSource"]){
+		var ss = fixture.runTest.toSource();
+		this.debug("\tERROR IN:\n\t\t", ss);
+	}else{
+		this.debug("\tERROR IN:\n\t\t", fixture.runTest);
+	}
+
+	if(e.rhinoException){
+		e.rhinoException.printStackTrace();
+	}else if(e.javaException){
+		e.javaException.printStackTrace();
+	} 
+}
+
+try{
+	setTimeout(function(){}, 0);
+}catch(e){
+	setTimeout = function(func){
+		return func();
+	}
+}
+
+doh._runPerfFixture = function(/*String*/groupName, /*Object*/fixture){
+	//	summary:
+	//		This function handles how to execute a 'performance' test
+	//		which is different from a straight UT style test.  These
+	//		will often do numerous iterations of the same operation and
+	//		gather execution statistics about it, like max, min, average, 
+	//		etc.  It makes use of the already in place DOH deferred test 
+	//		handling since it is a good idea to put a pause inbetween each 
+	//		iteration to allow for GC cleanup and the like.
+	//
+	//	groupName:
+	//		The test group that contains this performance test.
+	//	fixture:
+	//		The performance test fixture.
+	var tg = this._groups[groupName];
+	fixture.startTime = new Date();
+
+	//Perf tests always need to act in an async manner as there is a 
+	//number of iterations to flow through.
+	var def = new doh.Deferred();
+	tg.inFlight++;
+	def.groupName = groupName;
+	def.fixture = fixture;
+
+	def.addErrback(function(err){
+		doh._handleFailure(groupName, fixture, err);
+	});
+
+	//Set up the finalizer.
+	var retEnd = function(){
+		if(fixture["tearDown"]){ fixture.tearDown(doh); }
+		tg.inFlight--;
+		if((!tg.inFlight)&&(tg.iterated)){
+			doh._groupFinished(groupName, !tg.failures);
+		}
+		doh._testFinished(groupName, fixture, def.results[0]);
+		if(doh._paused){
+			doh.run();
+		}
+	};
+
+	//Since these can take who knows how long, we don't want to timeout
+	//unless explicitly set
+	var timer;
+	var to = fixture.timeout; 
+	if(to > 0) {
+		timer = setTimeout(function(){
+			// ret.cancel();
+			// retEnd();
+			def.errback(new Error("test timeout in "+fixture.name.toString()));
+		}, to);
+	}
+	
+	//Set up the end calls to the test into the deferred we'll return.
+	def.addBoth(function(arg){
+		if(timer){
+			clearTimeout(timer);
+		}
+		retEnd();
+	});
+
+	//Okay, now set up the timing loop for the actual test.
+	//This is down as an async type test where there is a delay
+	//between each execution to allow for GC time, etc, so the GC
+	//has less impact on the tests.
+	var res = fixture.results;
+	res.trials = [];
+
+	//Try to figure out how many calls are needed to hit a particular threshold.
+	var itrDef = doh._calcTrialIterations(groupName, fixture);
+	itrDef.addErrback(function(err){
+		fixture.endTime = new Date();
+		def.errback(err);
+	});
+
+	//Blah, since tests can be deferred, the actual run has to be deferred until after
+	//we know how many iterations to run.  This is just plain ugly.
+	itrDef.addCallback(function(iterations){
+		if(iterations){
+			var countdown = fixture.trialIterations;
+			doh.debug("TIMING TEST: [" + fixture.name + 
+					  "]\n\t\tITERATIONS PER TRIAL: " + 
+					  iterations + "\n\tTRIALS: " +
+					  countdown);
+
+			//Figure out how many times we want to run our 'trial'.
+			//Where each trial consists of 'iterations' of the test.
+
+			var trialRunner = function() {
+				//Set up our function to execute a block of tests
+				var start = new Date();
+				var tTimer = new doh.Deferred();
+				var tCountdown = iterations;
+
+				var tState = {
+					countdown: iterations
+				};
+				var testRunner = function(state){
+					while(state){
+						try{
+							state.countdown--;
+							if(state.countdown){
+								var ret = fixture.runTest(doh);
+								if(ret instanceof doh.Deferred){
+									//Deferreds have to be handled async,
+									//otherwise we just keep looping.
+									var atState = {
+										countdown: state.countdown
+									};
+									ret.addCallback(function(){
+										testRunner(atState);
+									});
+									ret.addErrback(function(err) {
+										doh._handleFailure(groupName, fixture, err);
+										fixture.endTime = new Date();
+										def.errback(err);
+									});
+									state = null;
+								}
+							}else{
+								tTimer.callback(new Date());
+								state = null;
+							}
+						}catch(err){
+							fixture.endTime = new Date();
+							tTimer.errback(err);
+						}
+					}
+				};
+				tTimer.addCallback(function(end){
+					//Figure out the results and try to factor out function call costs.
+					var tResults = {
+						trial: (fixture.trialIterations - countdown),
+						testIterations: iterations,
+						executionTime: (end.getTime() - start.getTime()),
+						average: (end.getTime() - start.getTime())/iterations
+					};
+					res.trials.push(tResults);
+					doh.debug("\n\t\tTRIAL #: " +
+							  tResults.trial + "\n\tTIME: " + 
+							  tResults.executionTime + "ms.\n\tAVG TEST TIME: " +
+							  (tResults.executionTime/tResults.testIterations) + "ms.");
+
+					//Okay, have we run all the trials yet?
+					countdown--;
+					if(countdown){
+						setTimeout(trialRunner, fixture.trialDelay);
+					}else{
+						//Okay, we're done, lets compute some final performance results.
+						var t = res.trials;
+
+
+
+						//We're done.
+						fixture.endTime = new Date();
+						def.callback(true);
+					}
+				});
+				tTimer.addErrback(function(err){
+					fixture.endTime = new Date();
+					def.errback(err);
+				});
+				testRunner(tState);
+			};
+			trialRunner();
+		}
+	});
+
+	//Set for a pause, returned the deferred.
+	if(def.fired < 0){
+		doh.pause();
+	}
+	return def;
+};
+
+doh._calcTrialIterations =  function(/*String*/ groupName, /*Object*/ fixture){
+	//	summary:
+	//		This function determines the rough number of iterations to
+	//		use to reach a particular MS threshold.  This returns a deferred
+	//		since tests can theoretically by async.  Async tests aren't going to
+	//		give great perf #s, though.
+	//		The callback is passed the # of iterations to hit the requested 
+	//		threshold.
+	//
+	//	fixture:
+	//		The test fixture we want to calculate iterations for.
+	var def = new doh.Deferred();
+	var calibrate = function () {
+		var testFunc = fixture.runTest;
+
+		//Set the initial state.  We have to do this as a loop instead
+		//of a recursive function.  Otherwise, it blows the call stack
+		//on some browsers.
+		var iState = {
+			start: new Date(),
+			curIter: 0,
+			iterations: 5
+		};
+		var handleIteration = function(state){
+			while(state){
+				if(state.curIter < state.iterations){
+					try{
+						var ret = testFunc(doh);
+						if(ret instanceof doh.Deferred){
+							var aState = {
+								start: state.start,
+								curIter: state.curIter + 1,
+								iterations: state.iterations
+							};
+							ret.addCallback(function(){
+								handleIteration(aState);
+							});
+							ret.addErrback(function(err) {
+								fixture.endTime = new Date();
+								def.errback(err);
+							});
+							state = null;
+						}else{
+							state.curIter++;
+						}
+					}catch(err){
+						fixture.endTime = new Date();
+						def.errback(err);
+						return;
+					}
+				}else{
+					var end = new Date();
+					var totalTime = (end.getTime() - state.start.getTime());
+					if(totalTime < fixture.trialDuration){
+						var nState = {
+							iterations: state.iterations * 2,
+							curIter: 0
+						}
+						state = null;
+						setTimeout(function(){
+							nState.start = new Date();
+							handleIteration(nState);
+						}, 50);
+					}else{
+						var itrs = state.iterations;
+						setTimeout(function(){def.callback(itrs)}, 50);
+						state = null;
+					}
+				}
+			}
+		};
+		handleIteration(iState);
+	};
+	setTimeout(calibrate, 10);
+	return def;
+};
+
+doh._runRegFixture = function(/*String*/groupName, /*Object*/fixture){
+	//	summary:
+	//		Function to run a generic doh test.  These are not
+	//		specialized tests, like performance groups and such.
+	//
+	//	groupName:
+	//		The groupName of the test.
+	//	fixture:
+	//		The test fixture to execute.
+	var tg = this._groups[groupName];
+	fixture.startTime = new Date();
+	var ret = fixture.runTest(this); 
+	fixture.endTime = new Date();
+	// if we get a deferred back from the test runner, we know we're
+	// gonna wait for an async result. It's up to the test code to trap
+	// errors and give us an errback or callback.
+	if(ret instanceof doh.Deferred){
+		tg.inFlight++;
+		ret.groupName = groupName;
+		ret.fixture = fixture;
+
+		ret.addErrback(function(err){
+			doh._handleFailure(groupName, fixture, err);
+		});
+
+		var retEnd = function(){
+			if(fixture["tearDown"]){ fixture.tearDown(doh); }
+			tg.inFlight--;
+			if((!tg.inFlight)&&(tg.iterated)){
+				doh._groupFinished(groupName, !tg.failures);
+			}
+			doh._testFinished(groupName, fixture, ret.results[0]);
+			if(doh._paused){
+				doh.run();
+			}
+		}
+
+		var timer = setTimeout(function(){
+			fixture.endTime = new Date();
+			ret.errback(new Error("test timeout in "+fixture.name.toString()));
+		}, fixture["timeout"]||1000);
+
+		ret.addBoth(function(arg){
+			clearTimeout(timer);
+			fixture.endTime = new Date();
+			retEnd();
+		});
+		if(ret.fired < 0){
+			doh.pause();
+		}
+		return ret;
+	}
+};
+
+doh._runFixture = function(groupName, fixture){
+	var tg = this._groups[groupName];
+	this._testStarted(groupName, fixture);
+	var threw = false;
+	var err = null;
+	// run it, catching exceptions and reporting them
+	try{
+		// let doh reference "this.group.thinger..." which can be set by
+		// another test or group-level setUp function
+		fixture.group = tg; 
+		// only execute the parts of the fixture we've got
+
+		if(fixture["setUp"]){ fixture.setUp(this); }
+		if(fixture["runTest"]){  // should we error out of a fixture doesn't have a runTest?
+			if(fixture.testType === "perf"){
+				//Always async deferred, so return it.
+				return doh._runPerfFixture(groupName, fixture);
+			}else{
+				//May or may not by async.
+				var ret = doh._runRegFixture(groupName, fixture);
+				if(ret){
+					return ret;
+				}
+			}
+		}
+		if(fixture["tearDown"]){ fixture.tearDown(this); }
+	}catch(e){
+		threw = true;
+		err = e;
+		if(!fixture.endTime){
+			fixture.endTime = new Date();
+		}
+	}
+	var d = new doh.Deferred();
+	setTimeout(this.hitch(this, function(){
+		if(threw){
+			this._handleFailure(groupName, fixture, err);
+		}
+		this._testFinished(groupName, fixture, !threw);
+
+		if((!tg.inFlight)&&(tg.iterated)){
+			doh._groupFinished(groupName, !tg.failures);
+		}else if(tg.inFlight > 0){
+			setTimeout(this.hitch(this, function(){
+				doh.runGroup(groupName); // , idx);
+			}), 100);
+			this._paused = true;
+		}
+		if(doh._paused){
+			doh.run();
+		}
+	}), 30);
+	doh.pause();
+	return d;
+}
+
+doh._testId = 0;
+doh.runGroup = function(/*String*/ groupName, /*Integer*/ idx){
+	// summary:
+	//		runs the specified test group
+
+	// the general structure of the algorithm is to run through the group's
+	// list of doh, checking before and after each of them to see if we're in
+	// a paused state. This can be caused by the test returning a deferred or
+	// the user hitting the pause button. In either case, we want to halt
+	// execution of the test until something external to us restarts it. This
+	// means we need to pickle off enough state to pick up where we left off.
+
+	// FIXME: need to make fixture execution async!!
+
+	var tg = this._groups[groupName];
+	if(tg.skip === true){ return; }
+	if(this._isArray(tg)){
+		if(idx<=tg.length){
+			if((!tg.inFlight)&&(tg.iterated == true)){
+				if(tg["tearDown"]){ tg.tearDown(this); }
+				doh._groupFinished(groupName, !tg.failures);
+				return;
+			}
+		}
+		if(!idx){
+			tg.inFlight = 0;
+			tg.iterated = false;
+			tg.failures = 0;
+		}
+		doh._groupStarted(groupName);
+		if(!idx){
+			this._setupGroupForRun(groupName, idx);
+			if(tg["setUp"]){ tg.setUp(this); }
+		}
+		for(var y=(idx||0); y<tg.length; y++){
+			if(this._paused){
+				this._currentTest = y;
+				// this.debug("PAUSED at:", tg[y].name, this._currentGroup, this._currentTest);
+				return;
+			}
+			doh._runFixture(groupName, tg[y]);
+			if(this._paused){
+				this._currentTest = y+1;
+				if(this._currentTest == tg.length){
+					tg.iterated = true;
+				}
+				// this.debug("PAUSED at:", tg[y].name, this._currentGroup, this._currentTest);
+				return;
+			}
+		}
+		tg.iterated = true;
+		if(!tg.inFlight){
+			if(tg["tearDown"]){ tg.tearDown(this); }
+			doh._groupFinished(groupName, !tg.failures);
+		}
+	}
+}
+
+doh._onEnd = function(){}
+
+doh._report = function(){
+	// summary:
+	//		a private method to be implemented/replaced by the "locally
+	//		appropriate" test runner
+
+	// this.debug("ERROR:");
+	// this.debug("\tNO REPORTING OUTPUT AVAILABLE.");
+	// this.debug("\tIMPLEMENT doh._report() IN YOUR TEST RUNNER");
+
+	this.debug(this._line);
+	this.debug("| TEST SUMMARY:");
+	this.debug(this._line);
+	this.debug("\t", this._testCount, "tests in", this._groupCount, "groups");
+	this.debug("\t", this._errorCount, "errors");
+	this.debug("\t", this._failureCount, "failures");
+}
+
+doh.togglePaused = function(){
+	this[(this._paused) ? "run" : "pause"]();
+}
+
+doh.pause = function(){
+	// summary:
+	//		halt test run. Can be resumed.
+	this._paused = true;
+}
+
+doh.run = function(){
+	// summary:
+	//		begins or resumes the test process.
+	// this.debug("STARTING");
+	this._paused = false;
+	var cg = this._currentGroup;
+	var ct = this._currentTest;
+	var found = false;
+	if(!cg){
+		this._init(); // we weren't paused
+		found = true;
+	}
+	this._currentGroup = null;
+	this._currentTest = null;
+
+	for(var x in this._groups){
+		if(
+			( (!found)&&(x == cg) )||( found )
+		){
+			if(this._paused){ return; }
+			this._currentGroup = x;
+			if(!found){
+				found = true;
+				this.runGroup(x, ct);
+			}else{
+				this.runGroup(x);
+			}
+			if(this._paused){ return; }
+		}
+	}
+	this._currentGroup = null;
+	this._currentTest = null;
+	this._paused = false;
+	this._onEnd();
+	this._report();
+}
+
+//Statistics functions to handle computing performance metrics.
+//Taken from dojox.math
+//	basic statistics
+doh.standardDeviation = function(/* Number[] */a){
+	//	summary:
+	//		Returns the standard deviation of the passed arguments.
+	return Math.sqrt(this.variance(a));	//	Number
+};
+
+doh.variance = function(/* Number[] */a){
+	//	summary:
+	//		Find the variance in the passed array of numbers.
+	var mean=0, squares=0;
+	dojo.forEach(a, function(item){
+		mean+=item;
+		squares+=Math.pow(item,2);
+	});
+	return (squares/a.length)-Math.pow(mean/a.length, 2);	//	Number
+};
+
+doh.mean = function(/* Number[] */a){
+	//	summary:
+	//		Returns the mean value in the passed array.
+	var t=0;
+	dojo.forEach(a, function(v){
+		t += v;
+	});
+	return t / Math.max(a.length, 1);	//	Number
+};
+
+doh.min = function(/* Number[] */a){
+	//	summary:
+	//		Returns the min value in the passed array.
+	return Math.min.apply(null, a);		//	Number
+};
+
+doh.max = function(/* Number[] */a){
+	//	summary:
+	//		Returns the max value in the passed array.
+	return Math.max.apply(null, a);		//	Number
+},
+
+doh.median= function(/* Number[] */a){
+	//	summary:
+	//		Returns the value closest to the middle from a sorted version of the passed array.
+	return a.slice(0).sort()[Math.ceil(a.length/2)-1];	//	Number
+},
+
+doh.mode = function(/* Number[] */a){
+	//	summary:
+	//		Returns the mode from the passed array (number that appears the most often).
+	//		This is not the most efficient method, since it requires a double scan, but
+	//		is ensures accuracy.
+	var o = {}, r = 0, m = Number.MIN_VALUE;
+	dojo.forEach(a, function(v){
+		(o[v]!==undefined)?o[v]++:o[v]=1;
+	});
+
+	//	we did the lookup map because we need the number that appears the most.
+	for(var p in o){
+		if(m < o[p]){
+			m = o[p], r = p;
+		}
+	}
+	return r;	//	Number
+};
+
+doh.average = function(/* Number [] */ a){
+	var i;
+	var s = 0;
+	for(i = 0; i < a.length; i++){
+		s += a[i];
+	}
+	return s/a.length;
+}
+
+tests = doh;
+
+(function(){
+	// scope protection
+	var x;
+	try{
+		if(typeof dojo != "undefined"){
+			dojo.platformRequire({
+				browser: ["doh._browserRunner"],
+				rhino: ["doh._rhinoRunner"],
+				spidermonkey: ["doh._rhinoRunner"]
+			});
+			try{
+				var _shouldRequire = dojo.isBrowser ? (dojo.global == dojo.global["parent"] || !Boolean(dojo.global.parent.doh) ) : true;
+			}catch(e){
+				//can't access dojo.global.parent.doh, then we need to do require
+				_shouldRequire = true;
+			}
+			if(_shouldRequire){
+				if(dojo.isBrowser){
+					dojo.addOnLoad(function(){
+						if (dojo.global.registerModulePath){
+							dojo.forEach(dojo.global.registerModulePath, function(m){
+								dojo.registerModulePath(m[0], m[1]);
+							});
+						}
+						if(dojo.byId("testList")){
+							var _tm = ( (dojo.global.testModule && dojo.global.testModule.length) ? dojo.global.testModule : "dojo.tests.module");
+							dojo.forEach(_tm.split(","), dojo.require, dojo);
+							setTimeout(function(){
+								doh.run();
+							}, 500);
+						}
+					});
+				}else{
+					// dojo.require("doh._base");
+				}
+			}
+		}else{
+			if(typeof load == "function" &&
+				(typeof Packages == "function" || typeof Packages == "object")){
+				throw new Error();
+			}else if(typeof load == "function"){
+				throw new Error();
+			}
+
+			if(this["document"]){
+				// if we survived all of that, we're probably in a browser but
+				// don't have Dojo handy. Load _browserRunner.js using a
+				// document.write() call.
+
+				// find runner.js, load _browserRunner relative to it
+				var scripts = document.getElementsByTagName("script"), runnerFile;
+				for(x=0; x<scripts.length; x++){
+					var s = scripts[x].src;
+					if(s){
+						if(!runnerFile && s.substr(s.length - 9) == "runner.js"){
+							runnerFile = s;
+						}else if(s.substr(s.length - 17) == "_browserRunner.js"){
+							runnerFile = null;
+							break;
+						}
+					}
+				}
+				if(runnerFile){
+					document.write("<scri"+"pt src='" + runnerFile.substr(0, runnerFile.length - 9)
+						+ "_browserRunner.js' type='text/javascript'></scr"+"ipt>");
+				}
+			}
+		}
+	}catch(e){
+		print("\n"+doh._line);
+		print("The Dojo Unit Test Harness, $Rev: 22059 $");
+		print("Copyright (c) 2010, The Dojo Foundation, All Rights Reserved");
+		print(doh._line, "\n");
+
+		try{
+			var dojoUrl = "../../dojo/dojo.js";
+			var testUrl = "";
+			var testModule = "dojo.tests.module";
+			var dohBase = "";
+			for(x=0; x<arguments.length; x++){
+				if(arguments[x].indexOf("=") > 0){
+					var tp = arguments[x].split("=");
+					if(tp[0] == "dohBase"){
+						dohBase = tp[1];
+						//Convert slashes to unix style and make sure properly
+						//ended.
+						dohBase = dohBase.replace(/\\/g, "/");
+						if(dohBase.charAt(dohBase.length - 1) != "/"){
+							dohBase += "/";
+						}
+					}
+					if(tp[0] == "dojoUrl"){
+						dojoUrl = tp[1];
+					}
+					if(tp[0] == "testUrl"){
+						testUrl = tp[1];
+					}
+					if(tp[0] == "testModule"){
+						testModule = tp[1];
+					}
+				}
+			}
+
+			load(dohBase + "_rhinoRunner.js");
+
+			if(dojoUrl.length){
+				if(!this["djConfig"]){
+					djConfig = {};
+				}
+				djConfig.baseUrl = dojoUrl.split("dojo.js")[0];
+				load(dojoUrl);
+			}
+			if(testUrl.length){
+				load(testUrl);
+			}
+			if(testModule.length){
+				dojo.forEach(testModule.split(","), dojo.require, dojo);
+			}
+		}catch(e){
+			print("An exception occurred: " + e);
+		}
+
+		doh.run();
+	}
+}).apply(this, typeof arguments != "undefined" ? arguments : [null]);
diff --git a/util/doh/runner.sh b/util/doh/runner.sh
new file mode 100755
index 0000000..c4ced4a
--- /dev/null
+++ b/util/doh/runner.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+java -jar ../shrinksafe/js.jar runner.js "$@"
diff --git a/util/doh/small_logo.png b/util/doh/small_logo.png
new file mode 100644
index 0000000..2fda23c
Binary files /dev/null and b/util/doh/small_logo.png differ
diff --git a/util/doh/tests/robot.html b/util/doh/tests/robot.html
new file mode 100644
index 0000000..4b7f932
--- /dev/null
+++ b/util/doh/tests/robot.html
@@ -0,0 +1,80 @@
+<html>
+<head>
+	<style>
+		@import "../robot/robot.css";
+	</style>
+	<script src="../runner.js"></script>
+	<script src="../robot.js"></script>
+</head>
+<body>
+<form>
+<input type="text" value="hi" id="textbox" style="position:absolute; left:0px; top:20px; font-family:system;"></input>
+</form>
+<script>
+var textbox=document.getElementById('textbox');
+var BACKSPACE=8;
+var END=35;
+var LEFT_ARROW=37;
+var SHIFT=16;
+doh.register("doh.robot",[
+{
+	name:"dojorobot1",
+	timeout:6900,
+	setUp:function(){
+		textbox.value="hi";
+	},
+	runTest:function(){
+		var d=new doh.Deferred();
+		doh.robot.mouseMove(30, 30, 500);
+		doh.robot.mouseClick({left:true}, 500);
+		doh.robot.typeKeys(" again", 500, 2500);
+		doh.robot.sequence(function(){
+			if(textbox.value=="hi again"){
+				textbox.value += ": passed";
+				d.callback(true);
+			}else{
+				textbox.value += ": failed";
+				d.errback(new Error("Expected value 'hi again', got "+textbox.value));
+			}
+		}, 900);
+		return d;
+	}
+},
+{
+	name:"shiftarrow",
+	timeout:10000,
+	setUp:function(){
+		textbox.value="hi again";
+	},
+	runTest:function(){
+		var d=new doh.Deferred();
+		doh.robot.keyPress(END,500);
+		// test shift+arrow with keyPress
+		for(var i=0; i<3; i++){
+			doh.robot.keyPress(LEFT_ARROW,500,{shift:true});
+		}
+		// test shift+arrow with keyDown then keyUp
+		doh.robot.keyDown(SHIFT,500);
+		for(var i=0; i<3; i++){
+			doh.robot.keyDown(LEFT_ARROW,500);
+			doh.robot.keyUp(LEFT_ARROW,20);
+		}
+		doh.robot.keyUp(SHIFT,500);
+		doh.robot.keyPress(BACKSPACE,500);
+		doh.robot.sequence(function(){
+			if(textbox.value=="hi"){
+				textbox.value += ": passed";
+				d.callback(true);
+			}else{
+				textbox.value += ": failed";
+				d.errback(new Error("Expected value 'hi', got "+textbox.value));
+			}
+		}, 900);
+		return d;
+	}
+}
+]);
+doh.run();
+</script>
+</body>
+</html>
diff --git a/util/jsdoc/INSTALL b/util/jsdoc/INSTALL
new file mode 100644
index 0000000..329ed58
--- /dev/null
+++ b/util/jsdoc/INSTALL
@@ -0,0 +1,55 @@
+Drupal
+======
+
+Prerequisites
+=============
+
+PHP5
+See: Installing Libraries (below)
+
+Installing Drupal
+=================
+
+http://drupal.org/drupal-5.7 (tested on 5.7 at the time of this writing)
+http://drupal.org/getting-started/5/install
+
+Installing Libraries
+====================
+
+Read the EXTERNALS file in jsdoc/lib
+
+Installing the Module
+=====================
+
+http://drupal.org/node/70151
+Drop the jsdoc folder into sites/all/modules
+
+Enable the Module
+=================
+
+Enable in: Administer->Site building->Modules
+
+Configure
+=========
+
+* Make sure that PHP has write persmissions to the util/jsdoc/cache directory
+* Fill in the configuration in: Administer->Site configuration->JavaScript Documentation
+** Under "Directory to run your file from",
+   enter the FULL PATH to util/docscripts (eg /var/www/dojotoolkit/util/docscripts)
+** Under "Location of file used to parse your code",
+   enter the FULL PATH to util/docscripts/includes/dojo.inc
+   (eg /var/www/dojotoolkit/util/docscripts/includes/dojo.inc)
+** Under  "This will be used as a base of our functions", enter "dojo"
+* If you want to add a new namespace, see the plugins in util/docscripts/modules
+  (dojox.module is probably the easiest to copy).
+  Function names should begin with the file name prefix of the module file
+  eg dojo.module's functions start with "dojo".
+* Remove (or change the file type) of these modules to exclude them from
+  processing.
+
+Run Cron
+========
+
+In the base of your Drupal folder, you'll see cron.php. This has a 30s processing limit,
+so you'll need to run it until your DB is fully populated. Run either in your browser
+or with cron and a wget/curl command.
\ No newline at end of file
diff --git a/util/jsdoc/LICENSE b/util/jsdoc/LICENSE
new file mode 100644
index 0000000..4c93ded
--- /dev/null
+++ b/util/jsdoc/LICENSE
@@ -0,0 +1,195 @@
+Dojo is available under *either* the terms of the modified BSD license *or* the
+Academic Free License version 2.1. As a recipient of Dojo, you may choose which
+license to receive this code under (except as noted in per-module LICENSE
+files). Some modules may not be the copyright of the Dojo Foundation. These
+modules contain explicit declarations of copyright in both the LICENSE files in
+the directories in which they reside and in the code itself. No external
+contributions are allowed under licenses which are fundamentally incompatible
+with the AFL or BSD licenses that Dojo is distributed under.
+
+The text of the AFL and BSD licenses is reproduced below. 
+
+-------------------------------------------------------------------------------
+The "New" BSD License:
+**********************
+
+Copyright (c) 2005-2010, The Dojo Foundation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this
+    list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+  * Neither the name of the Dojo Foundation nor the names of its contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------------------
+The Academic Free License, v. 2.1:
+**********************************
+
+This Academic Free License (the "License") applies to any original work of
+authorship (the "Original Work") whose owner (the "Licensor") has placed the
+following notice immediately following the copyright notice for the Original
+Work:
+
+Licensed under the Academic Free License version 2.1
+
+1) Grant of Copyright License. Licensor hereby grants You a world-wide,
+royalty-free, non-exclusive, perpetual, sublicenseable license to do the
+following:
+
+a) to reproduce the Original Work in copies;
+
+b) to prepare derivative works ("Derivative Works") based upon the Original
+Work;
+
+c) to distribute copies of the Original Work and Derivative Works to the
+public;
+
+d) to perform the Original Work publicly; and
+
+e) to display the Original Work publicly.
+
+2) Grant of Patent License. Licensor hereby grants You a world-wide,
+royalty-free, non-exclusive, perpetual, sublicenseable license, under patent
+claims owned or controlled by the Licensor that are embodied in the Original
+Work as furnished by the Licensor, to make, use, sell and offer for sale the
+Original Work and Derivative Works.
+
+3) Grant of Source Code License. The term "Source Code" means the preferred
+form of the Original Work for making modifications to it and all available
+documentation describing how to modify the Original Work. Licensor hereby
+agrees to provide a machine-readable copy of the Source Code of the Original
+Work along with each copy of the Original Work that Licensor distributes.
+Licensor reserves the right to satisfy this obligation by placing a
+machine-readable copy of the Source Code in an information repository
+reasonably calculated to permit inexpensive and convenient access by You for as
+long as Licensor continues to distribute the Original Work, and by publishing
+the address of that information repository in a notice immediately following
+the copyright notice that applies to the Original Work.
+
+4) Exclusions From License Grant. Neither the names of Licensor, nor the names
+of any contributors to the Original Work, nor any of their trademarks or
+service marks, may be used to endorse or promote products derived from this
+Original Work without express prior written permission of the Licensor. Nothing
+in this License shall be deemed to grant any rights to trademarks, copyrights,
+patents, trade secrets or any other intellectual property of Licensor except as
+expressly stated herein. No patent license is granted to make, use, sell or
+offer to sell embodiments of any patent claims other than the licensed claims
+defined in Section 2. No right is granted to the trademarks of Licensor even if
+such marks are included in the Original Work. Nothing in this License shall be
+interpreted to prohibit Licensor from licensing under different terms from this
+License any Original Work that Licensor otherwise would have a right to
+license.
+
+5) This section intentionally omitted.
+
+6) Attribution Rights. You must retain, in the Source Code of any Derivative
+Works that You create, all copyright, patent or trademark notices from the
+Source Code of the Original Work, as well as any notices of licensing and any
+descriptive text identified therein as an "Attribution Notice." You must cause
+the Source Code for any Derivative Works that You create to carry a prominent
+Attribution Notice reasonably calculated to inform recipients that You have
+modified the Original Work.
+
+7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
+the copyright in and to the Original Work and the patent rights granted herein
+by Licensor are owned by the Licensor or are sublicensed to You under the terms
+of this License with the permission of the contributor(s) of those copyrights
+and patent rights. Except as expressly stated in the immediately proceeding
+sentence, the Original Work is provided under this License on an "AS IS" BASIS
+and WITHOUT WARRANTY, either express or implied, including, without limitation,
+the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU.
+This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No
+license to Original Work is granted hereunder except under this disclaimer.
+
+8) Limitation of Liability. Under no circumstances and under no legal theory,
+whether in tort (including negligence), contract, or otherwise, shall the
+Licensor be liable to any person for any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License
+or the use of the Original Work including, without limitation, damages for loss
+of goodwill, work stoppage, computer failure or malfunction, or any and all
+other commercial damages or losses. This limitation of liability shall not
+apply to liability for death or personal injury resulting from Licensor's
+negligence to the extent applicable law prohibits such limitation. Some
+jurisdictions do not allow the exclusion or limitation of incidental or
+consequential damages, so this exclusion and limitation may not apply to You.
+
+9) Acceptance and Termination. If You distribute copies of the Original Work or
+a Derivative Work, You must make a reasonable effort under the circumstances to
+obtain the express assent of recipients to the terms of this License. Nothing
+else but this License (or another written agreement between Licensor and You)
+grants You permission to create Derivative Works based upon the Original Work
+or to exercise any of the rights granted in Section 1 herein, and any attempt
+to do so except under the terms of this License (or another written agreement
+between Licensor and You) is expressly prohibited by U.S. copyright law, the
+equivalent laws of other countries, and by international treaty. Therefore, by
+exercising any of the rights granted to You in Section 1 herein, You indicate
+Your acceptance of this License and all of its terms and conditions.
+
+10) Termination for Patent Action. This License shall terminate automatically
+and You may no longer exercise any of the rights granted to You by this License
+as of the date You commence an action, including a cross-claim or counterclaim,
+against Licensor or any licensee alleging that the Original Work infringes a
+patent. This termination provision shall not apply for an action alleging
+patent infringement by combinations of the Original Work with other software or
+hardware.
+
+11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this
+License may be brought only in the courts of a jurisdiction wherein the
+Licensor resides or in which Licensor conducts its primary business, and under
+the laws of that jurisdiction excluding its conflict-of-law provisions. The
+application of the United Nations Convention on Contracts for the International
+Sale of Goods is expressly excluded. Any use of the Original Work outside the
+scope of this License or after its termination shall be subject to the
+requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et
+seq., the equivalent laws of other countries, and international treaty. This
+section shall survive the termination of this License.
+
+12) Attorneys Fees. In any action to enforce the terms of this License or
+seeking damages relating thereto, the prevailing party shall be entitled to
+recover its costs and expenses, including, without limitation, reasonable
+attorneys' fees and costs incurred in connection with such action, including
+any appeal of such action. This section shall survive the termination of this
+License.
+
+13) Miscellaneous. This License represents the complete agreement concerning
+the subject matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent necessary to
+make it enforceable.
+
+14) Definition of "You" in This License. "You" throughout this License, whether
+in upper or lower case, means an individual or a legal entity exercising rights
+under, and complying with all of the terms of, this License. For legal
+entities, "You" includes any entity that controls, is controlled by, or is
+under common control with you. For purposes of this definition, "control" means
+(i) the power, direct or indirect, to cause the direction or management of such
+entity, whether by contract or otherwise, or (ii) ownership of fifty percent
+(50%) or more of the outstanding shares, or (iii) beneficial ownership of such
+entity.
+
+15) Right to Use. You may use the Original Work in all ways not otherwise
+restricted or conditioned by this License or by law, and Licensor promises not
+to interfere with or be responsible for such uses by You.
+
+This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved.
+Permission is hereby granted to copy and distribute this license without
+modification. This license may not be modified without the express written
+permission of its copyright owner.
diff --git a/util/jsdoc/THEMING b/util/jsdoc/THEMING
new file mode 100755
index 0000000..e69de29
diff --git a/util/jsdoc/jsdoc.css b/util/jsdoc/jsdoc.css
new file mode 100644
index 0000000..8aae217
--- /dev/null
+++ b/util/jsdoc/jsdoc.css
@@ -0,0 +1,24 @@
+/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */
+.javascript .de1, .javascript .de2 {font-weight:normal;background:transparent;color:#000; padding-left: 5px;}
+.javascript .kw1 {color: #a1a100;}
+.javascript .kw2 {color: #000; font-weight: bold;}
+.javascript .kw3 {color: #000066;}
+.javascript .kw4 {color: #f63333;}
+.javascript .co1, .javascript .co2, .javascript .coMULTI {color: #808080;}
+.javascript .es0 {color: #000033; font-weight: bold;}
+.javascript .br0 {color: #66cc66;}
+.javascript .st0 {color: #ff0000;}
+.javascript .nu0 {color: #ff33ff;}
+.javascript .me0 {color: #006600;}
+
+.html4strict .de1, .html4strict .de2 {font-weight:normal;background:transparent;color:#000; padding-left: 5px;}
+.html4strict .kw1 {color: #a1a100;}
+.html4strict .kw2 {color: #000; font-weight: bold;}
+.html4strict .kw3 {color: #000066;}
+.html4strict .kw4 {color: #f63333;}
+.html4strict .co1, .html4strict .co2, .html4strict .coMULTI {color: #808080;}
+.html4strict .es0 {color: #000033; font-weight: bold;}
+.html4strict .br0 {color: #66cc66;}
+.html4strict .st0 {color: #ff0000;}
+.html4strict .nu0 {color: #ff33ff;}
+.html4strict .me0 {color: #006600;}
\ No newline at end of file
diff --git a/util/jsdoc/jsdoc.info b/util/jsdoc/jsdoc.info
new file mode 100755
index 0000000..e4f73d2
--- /dev/null
+++ b/util/jsdoc/jsdoc.info
@@ -0,0 +1,4 @@
+; $Id $
+name = "JavaScript Documentation"
+description = "Reads and displays documentation for JavaScript code"
+package = Documentation
diff --git a/util/jsdoc/jsdoc.install b/util/jsdoc/jsdoc.install
new file mode 100755
index 0000000..b944fb4
--- /dev/null
+++ b/util/jsdoc/jsdoc.install
@@ -0,0 +1,23 @@
+<?php
+
+function jsdoc_install() {
+  switch ($GLOBALS['db_type']) {
+  case 'mysql':
+  case 'mysqli':
+      db_query("CREATE TABLE {jsdoc_variables} (
+        sid INTEGER NOT NULL PRIMARY KEY,
+        variable VARCHAR(255) NOT NULL UNIQUE,
+        private BOOLEAN NOT NULL
+      ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
+
+      db_query("CREATE TABLE {jsdoc_objects} (
+        nid INTEGER NOT NULL PRIMARY KEY REFERENCES {node} (nid), -- node-type: jsdoc_object
+        did INTEGER NOT NULL REFERENCES {node} (nid), -- node-type: jsdoc_doc
+        json LONGTEXT NOT NULL,
+        INDEX (did)
+      ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
+    break;
+  case 'pgsql':
+    break;
+  }
+}
\ No newline at end of file
diff --git a/util/jsdoc/jsdoc.js b/util/jsdoc/jsdoc.js
new file mode 100644
index 0000000..9a7fadc
--- /dev/null
+++ b/util/jsdoc/jsdoc.js
@@ -0,0 +1,91 @@
+jsdoc = {nodes: {}};
+
+dojo.addOnLoad(function(){
+	dojo.query("#jsdoc-manage table").forEach(function(table){
+		dojo.connect(dojo.byId("jsdoc-manage"), "onsubmit", function(e){
+			var valid = true;
+			dojo.query("select", table).forEach(function(select){
+				if(select.options.length > 1 && select.selectedIndex == 0){
+					valid = false;
+				}
+			});
+			if(!valid){
+				alert("All variables must either be marked as new, or used in a rename.");
+				dojo.stopEvent(e);
+			}
+		});
+
+		var available = {};
+
+		dojo.query("input", table).forEach(function(checkbox){
+			checkbox.checked = true;
+			var parts = checkbox.value.split("|");
+			var node = {
+				project: parts[0],
+				resource: parts[1],
+				title: parts[2],
+				nid: parts[3],
+				vid: parts[4]
+			}
+			jsdoc.nodes[node.nid + "_" + node.vid] = node;
+			dojo.connect(checkbox, "onchange", function(e){
+				var checked = e.target.checked;
+
+				if(!available[node.project]){
+					e.target.checked = true;
+				}
+				if(available[node.project] || checked){
+					dojo.publish("/jsdoc/onchange", [checkbox.checked, node.nid + "_" + node.vid]);
+				}
+
+				if(!checked && available[node.project]){
+					--available[node.project];
+				}else if(checked) {
+					++available[node.project];
+				}
+			});
+		});
+
+		dojo.query("select", table).forEach(function(select){
+			var project = select.name.slice(9, select.name.indexOf("]"));
+			available[project] = (available[project] || 0) + 1;
+
+			dojo.connect(select, "onchange", function(){
+				if(select.selectedIndex == 0){
+					if(select.last){
+						dojo.publish("/jsdoc/onchange", [false, select.last, select]);
+						select.last = 0;
+					}
+				}else if(select.selectedIndex > 0){
+					if(select.last){
+						dojo.publish("/jsdoc/onchange", [false, select.last, select]);
+					}
+					var option = select.options[select.selectedIndex];
+					select.last = option.value;
+					dojo.publish("/jsdoc/onchange", [true, option.value, select]);
+				}
+			});
+
+			dojo.subscribe("/jsdoc/onchange", null, function(checked, id, current){
+				if(current === select){
+					return;
+				}
+
+				var node = jsdoc.nodes[id];
+
+				if(!checked){
+					if(select.name.indexOf("modified[" + node.project + "]") == 0){
+						var i = select.options.length++;
+						select.options[i].value = id;
+						select.options[i].text = node.title + " in " + node.resource;
+					}
+				}else{
+					dojo.query("option[value=" + id + "]", select).orphan();
+					if(!select.options.length){
+						select.selectedIndex = 0;
+					}
+				}
+			});
+		});
+	});
+});
\ No newline at end of file
diff --git a/util/jsdoc/jsdoc.module b/util/jsdoc/jsdoc.module
new file mode 100755
index 0000000..ff25009
--- /dev/null
+++ b/util/jsdoc/jsdoc.module
@@ -0,0 +1,3003 @@
+<?php
+// $Id$
+
+/**
+* @file
+* Documentation front-end for JavaScript projects.
+*
+* Allows JavaScript projects to parse their code and return an object structure
+* that will be used to generate custom Drupal nodes.
+*/
+
+// Public API (intended for use in a JS source page)
+// =================================================
+
+// Implemented global hook functions
+// =================================
+
+/**
+ * Implementation of hook_node_info().
+ */
+function jsdoc_node_info() {
+  return array(
+		'jsdoc_doc' => array('name' => t('Documentation'), 'module' => 'jsdoc_doc', 'description' => t('A JavaScript documentation file')),
+    'jsdoc_object' => array('name' => t('JavaScript Object'), 'module' => 'jsdoc_object', 'description' => t('An implemented JavaScript object'))
+  );
+}
+
+/**
+ * Implementation of hook_perm().
+ */
+function jsdoc_perm() {
+  return array('edit jsdoc');
+}
+
+/**
+ * Implementation of hook_menu().
+ */
+function jsdoc_menu($may_cache) {
+  $items = array();
+  $version = isset($_SESSION['jsdoc_version']) ? $_SESSION['jsdoc_version'] : null;
+
+  if ($may_cache) {
+    $items[] = array(
+      'path' => 'admin/settings/jsdoc',
+      'title' => t('JavaScript Documentation'),
+      'callback' => 'drupal_get_form',
+      'callback arguments' => array('jsdoc_admin'),
+      'access' => user_access('access administration pages'),
+      'type' => MENU_NORMAL_ITEM
+    );
+
+    $items[] = array(
+      'path' => 'jsdoc/jsonp',
+      'type' => MENU_CALLBACK,
+      'callback' => 'jsdoc_jsonp',
+      'access' => true
+    );
+
+    $items[] = array(
+      'path' => 'jsdoc/feedback',
+      'type' => MENU_CALLBACK,
+      'callback' => 'jsdoc_feedback',
+      'access' => true
+    );
+
+  $items[] = array(
+    'path' => 'jsdoc/feedback/review',
+    'type' => MENU_CALLBACK,
+    'callback' => 'jsdoc_feedback_review',
+    'access' => true
+  );
+
+    $items[] = array(
+      'path' => 'jsdoc/404',
+      'title' => t('Page not found'),
+      'type' => MENU_CALLBACK,
+      'callback' => 'jsdoc_404',
+      'access' => true
+    );
+  }
+  else {
+    if (arg(0) == 'jsdoc' && arg(1) != 'jsonp') {
+      $version = false;
+      $resource = false;
+      $name = '';
+      $path = '';
+
+      $switch = false;
+      $args = array();
+      for ($i = 0; $arg = arg($i); $i++){
+        if ($arg == '.switch') {
+          $switch = arg($i + 1);
+          break;
+        }
+        $args[] = $arg;
+      }
+
+      if (count($args) == 4) {
+        // Old URL
+        $version = $args[2];
+        $name = $args[3];
+        drupal_goto("jsdoc/$version/$name");
+        return;
+      }
+      if ($args[2]) {
+        // If we have 2 arguments, assume that we don't have a resource or project
+        // So basically, we assume that version is more important than project
+        $version = $args[1];
+        $name = $args[2];
+        $path = "jsdoc/$version/$name";
+      }
+      elseif ($args[1]) {
+        // Allow the user to only pass the name
+        $name = $args[1];
+        $path = "jsdoc/$name";
+      }
+
+      $node = jsdoc_get_closest($name, $version);
+
+      if (!$node || !$node->nid) {
+        return;
+      }
+      else {
+        jsdoc_current_node($node);
+
+        $item = array(
+          'path' => $path,
+          'title' => t('View'),
+          'access' => node_access('view', $node),
+          'type' => MENU_CALLBACK
+        );
+
+        $version  = jsdoc_get_version($node);
+
+        $path = array('jsdoc', $version->title, $name);
+        if ($switch) {
+          $path[1] = $switch;
+          drupal_goto(implode('/', $path));
+          return;
+        }
+
+        $versions = jsdoc_get_versions($node, $name);
+        if (count($versions) > 1) {
+          $path = explode('/', $node->jsdoc_url);
+          foreach (array_reverse($versions) as $release) {
+            $path[2] = $release->title;
+
+            $items[] = array(
+              'path' => $_GET['q'] . '/.switch/' . $release->title,
+              'title' => $project->title . ' ' . $release->title,
+              'type' => ($release->nid == $version->nid) ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK
+            );
+          }
+        }
+
+        $item['callback'] = ($name == $node->title) ? 'jsdoc_object_node_view' : 'jsdoc_child_node_view';
+        $item['callback arguments'] = ($name == $node->title) ? array($node) : array($node, $name);
+      }
+      $items[] = $item;
+    }
+  }
+
+  return $items;
+}
+
+/**
+ * Impelementation of hook_block
+ */
+function jsdoc_block($op='list', $delta=0) {
+  if ($op == 'list') {
+    if (module_exists('search')) {
+      $block[0]['info'] = t('JavaScript Documentation Search');
+    }
+    $block[1]['info'] = t('JavaScript Namespace List');
+    return $block;
+  }
+  elseif ($op == 'view') {
+    if ($delta == 0 && module_exists('search')) {
+      $block['subject'] = 'Search';
+      $block['content'] = preg_replace('%ignore.*endignore%s', theme('jsdoc_search', 'search'), drupal_get_form('_jsdoc_block_search'));
+      return $block;
+    }
+    elseif ($delta == 1) {
+      $namespaces = array();
+
+      $current = jsdoc_current_node();
+      list($current_namespace,) = explode('.', $current->title, 2);
+
+      if (!($version = jsdoc_get_version($current))) {
+        foreach (jsdoc_get_versions() as $version) {
+          if ($version->title != 'HEAD') {
+            break;
+          }
+        }
+      }
+
+      if ($content = cache_get("jsdoc_namespaces_{$version->title}:$current_namespace")) {
+        $content = $content->data;
+      }
+      else {
+        $query = db_query("SELECT n.nid, n.title, version.title AS version FROM {node} AS n JOIN {jsdoc_objects} j ON (j.nid = n.nid) JOIN {node} AS version ON (version.nid = j.did) WHERE j.did = %d", $version->nid);
+        while ($node = db_fetch_object($query)) {
+          if (strpos($node->title, '._') !== false) {
+            continue;
+          }
+          $parts = explode('.', $node->title);
+          if (count($parts)) {
+            for ($i = 1; $i <= count($parts); $i++) {
+              $parent = implode('.', array_slice($parts, 0, $i));
+              if (!$namespaces[$parent]) {
+                $namespaces[$parent] = (object)array(
+                  'title' => $parent,
+                  'children' => array()
+                );
+              }
+            }
+
+            array_pop($parts);
+            $parent = implode('.', $parts);
+            if ($parent) {
+              $children = &$namespaces[$parent]->children;
+            }
+            else {
+              $children = &$namespaces;
+            }
+            $children[$node->title]->jsdoc_url = 'jsdoc/' . $node->version . '/' . $node->title;
+            $children[$node->title]->url = url('jsdoc/' . $node->version . '/' . $node->title);
+            $children[$node->title]->a = l($node->title, 'jsdoc/' . $node->version . '/' . $node->title);
+          }
+        }
+
+        uksort($namespaces, 'strnatcasecmp');
+        foreach ($namespaces as $namespace) {
+          if ($namespace->children) {
+            uksort($namespace->children, 'strnatcasecmp');
+          }
+        }
+
+        $content = theme('jsdoc_namespaces', $namespaces, $version->title, $current->title);
+        cache_set("jsdoc_namespaces_{$version->title}:$current_namespace", 'cache', $content, time() + 86400);
+      }
+
+      //$namespaces = unserialize(cache_get('jsdoc_namespaces', 'cache')->data);
+      $block['subject'] = 'Objects';
+      $block['content'] = $content;
+      return $block;
+    }
+  }
+}
+
+function _jsdoc_block_search() {
+  if (module_exists('search')) {
+    return array(
+      'ignore' => array(
+        '#value' => 'ignore'
+      ),
+      'search' => array(
+        '#type' => 'textfield'
+      ),
+      'go' => array(
+        '#type' => 'submit',
+        '#value' => 'Go'
+      ),
+      'endignore' => array(
+        '#value' => 'endignore'
+      )
+    );
+  }
+}
+
+function _jsdoc_block_search_submit($form_id, $form) {
+  // TODO
+  $search = $form['search'];
+  if (strpos($search, ' ') === false) {
+    $query = db_query("SELECT title FROM {node} WHERE type = 'jsdoc_object' AND title = '%s' GROUP BY BINARY title", $search);
+    if (db_num_rows($query) == 1) {
+      $object = jsdoc_object_node_load(db_result($query));
+      watchdog('search', t('%keys (@type).', array('%keys' => $search, '@type' => 'JavaScript Documentation')), WATCHDOG_NOTICE, l(t('result'), $object->jsdoc_url));
+      drupal_goto($object->jsdoc_url);
+      return;
+    }
+    else {
+      $query = db_query("SELECT title FROM {node} WHERE type = 'jsdoc_object' AND title LIKE '%%%s%%' GROUP BY BINARY title", $search);
+      if (db_num_rows($query) == 1) {
+        $object = jsdoc_object_node_load(db_result($query));
+        watchdog('search', t('%keys (@type).', array('%keys' => $search, '@type' => 'JavaScript Documentation')), WATCHDOG_NOTICE, l(t('result'), $object->jsdoc_url));
+        drupal_goto($object->jsdoc_url);
+        return;
+      }
+    }
+  }
+
+  drupal_goto('search/jsdoc/' . $search);
+}
+
+/**
+ * shutdown function to make sure we always mark the last node processed.
+ */
+function jsdoc_update_shutdown() {
+  global $jsdoc_last_change, $jsdoc_last_nid;
+
+  if ($jsdoc_last_change && $jsdoc_last_nid) {
+    variable_set('jsdoc_cron_last', $jsdoc_last_change);
+    variable_set('jsdoc_cron_last_nid', $jsdoc_last_nid);
+  }
+}
+
+/**
+ * Implementation of hook_update_index().
+ *
+ * Handle node status the way that the node module does... through remembering nids, last change time,
+ * and last comment change time.
+ *
+ * We need to save things by version/node pair though. That way, we can keep things so that the latest
+ * update is always the latest version of the node.
+ */
+function jsdoc_update_index() {
+  global $jsdoc_last_change, $jsdoc_last_nid;
+
+  register_shutdown_function('jsdoc_update_shutdown');
+
+  $jsdoc_last_change = variable_get('jsdoc_cron_last', 0);
+  $jsdoc_last_nid = variable_get('jsdoc_cron_last_nid', 0);
+  $limit = (int)variable_get('search_cron_limit', 500);
+
+  // $result = db_query_range("SELECT GREATEST(IF(c.last_comment_timestamp IS NULL, 0, c.last_comment_timestamp), n.changed) as last_change, n.nid FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.type = 'jsdoc_variable' AND n.status = 1 AND ((GREATEST(n.changed, c.last_comment_timestamp) = %d AND n.nid > %d) OR (n.changed > %d OR c.last_comment_timestamp > %d)) ORDER BY GREATEST(n.changed, c.last_comment_timestamp) ASC, n.nid ASC", $last, $last_nid, $last, $la [...]
+  $result = db_query_range("SELECT n.changed as last_change, n.nid FROM {node} n WHERE n.type = 'jsdoc_object' AND ((n.changed = %d AND n.nid > %d) OR n.changed > %d) ORDER BY n.changed ASC, n.nid ASC", $jsdoc_last_change, $jsdoc_last_nid, $jsdoc_last_change, 0, $limit);
+  while ($node = db_fetch_object($result)) {
+    $node = node_load($node->nid);
+    $type = 'jsdoc_' . jsdoc_get_version($node)->title;
+
+    $items = array($node);
+    foreach (jsdoc_get_methods($node) as $method) {
+      $method->title = "{$node->title}.{$method->name}";
+      $items[] = $method;
+    }
+    foreach (jsdoc_get_properties($node) as $property) {
+      $property->title = "{$node->title}.{$property->name}";
+      $items[] = $property;
+    }
+    foreach ($items as $item) {
+      $text = '<h1>'. implode(' ', _jsdoc_build_terms($item->title)) . '</h1> ' . jsdoc_get_teaser($item) . ' ' . jsdoc_get_body($item);
+
+      if (!($sid = db_result(db_query("SELECT sid FROM {jsdoc_variables} WHERE variable = '%s'", $item->title)))) {
+        $sid = db_next_id('{jsdoc_variables}_sid');
+        db_query("INSERT INTO {jsdoc_variables} (sid, variable, private) VALUES (%d, '%s', %d)", $sid, $item->title, jsdoc_is_private($item) || jsdoc_has_private_parent($item));
+      }
+
+      search_index($sid, $type, $text);
+    }
+
+    $jsdoc_last_change = $node->changed;
+    $jsdoc_last_nid = $node->nid;
+  }
+
+  variable_set('jsdoc_cron_last', $jsdoc_last_change);
+  variable_set('jsdoc_cron_last_nid', $jsdoc_last_nid);
+}
+
+/**
+ * Implementation of hook_search().
+ */
+function jsdoc_search($op = 'search', $keys = null) {
+  switch ($op) {
+    case 'name':
+      return t('JavaScript Documentation');
+    case 'search':
+      // Get all projects
+      // Get all versions marked 'HEAD' in each project
+      $version = search_query_extract($keys, 'version');
+      if (empty($version)) {
+        $version = jsdoc_get_version()->title;
+      }
+      $keys = search_query_insert($keys, 'version');
+
+      $private = search_query_extract($keys, 'private');
+      $keys = search_query_insert($keys, 'private');
+
+      $where = '1';
+      if (!$private) {
+        $where = "j.private = 0";
+      }
+
+      $find = do_search(
+        '(' . implode('), (', _jsdoc_build_terms($keys)) . ')',
+        'jsdoc_' . $version,
+        "INNER JOIN {jsdoc_variables} j ON (j.sid = i.sid)",
+        $where,
+        array(),
+        'i.relevance + (15 / CHAR_LENGTH(j.variable)) AS score',
+        "INNER JOIN {jsdoc_variables} j ON (j.sid = i.sid)"
+      );
+      $results = array();
+      foreach ($find as $item) {
+        $variable = db_result(db_query("SELECT variable FROM {jsdoc_variables} WHERE sid = %d", $item->sid));
+        $actual = $node = jsdoc_object_node_load($variable, $version);
+        if (!$node->nid) {
+          $parts = explode('.', $variable);
+          array_pop($parts);
+          $node = jsdoc_object_node_load(implode('.', $parts), $version);
+          $actual = _jsdoc_resolve_child($node, $variable);
+        }
+
+        $info = jsdoc_node_info();
+        $results[] = array(
+          'url' => $actual->jsdoc_url,
+          'link' => url($actual->jsdoc_url),
+          'type' => "Version $version",
+          'title' => $actual->title,
+          'user' => '',
+          'date' => '',
+          'node' => $node,
+          'score' => $item->score,
+          'snippet' => (jsdoc_get_teaser($actual)) ? search_excerpt($keys, jsdoc_get_teaser($actual)) : ''
+        );
+      }
+
+      $term = trim(search_query_insert(search_query_insert($keys, 'private'), 'version'));
+      if (count($results) == 1 && $results[0]['title'] == $term) {
+        return drupal_goto($results[0]['url']);
+      }
+
+      return $results;
+  }
+}
+
+/**
+ * Implementation of hook_search_validate()
+ */
+function jsdoc_search_validate($form_id, $form_values, $form) {
+  $keys = $form_values['processed_keys'];
+
+  $version = $form_values['jsdoc_version'];
+  $keys = search_query_insert($keys, 'version', $version);
+
+  if ($form_values['jsdoc_private']) {
+    $keys = search_query_insert($keys, 'private', 'true');
+  }
+  else {
+    $keys = search_query_insert($keys, 'private');
+  }
+
+  if (!empty($keys)) {
+    form_set_value($form['basic']['inline']['processed_keys'], trim($keys));
+  }
+}
+
+/**
+ * Implementation of hook_form_alter().
+ */
+function jsdoc_form_alter($form_id, &$form) {
+  if ($form['type']['#value'] == 'jsdoc_object') {
+    unset($form['taxonomy']);
+  }
+  elseif ($form_id == 'search_form' && $form['module']['#value'] == 'jsdoc') {
+    foreach (jsdoc_get_versions() as $version) {
+      $options[$version->title] = $version->title;
+    }
+
+    if (empty($options)) {
+      $options = array('' => '-----');
+    }
+
+    $form['jsdoc_version'] = array(
+      '#title' => t('Version'),
+      '#type' => 'select',
+      '#options' => $options,
+      '#default_value' => jsdoc_get_version()->title
+    );
+
+    if ($version = search_query_extract($form['basic']['inline']['keys']['#default_value'], 'version')) {
+      $form['jsdoc_version']['#default_value'] = $version;
+    }
+
+    $private = search_query_extract($form['basic']['inline']['keys']['#default_value'], 'private');
+
+    $form['jsdoc_private'] = array(
+      '#title' => t('Include Private Variables'),
+      '#type' => 'checkbox',
+      '#default_value' => $private
+    );
+
+    $form['#validate']['jsdoc_search_validate'] = array();
+  }
+}
+
+/**
+ * Implementation of hook_help().
+ */
+function jsdoc_help($section = '') {
+  $output = '';
+  
+  switch ($section) {
+    case 'admin/help#jsdoc':
+      return '<p>' . t('View and edit JavaScript Documentation') . '</p>';
+    case 'admin/modules#jsdoc':
+      return t('View and edit JavaScript Documentation');
+      case 'admin/settings/jsdoc/ignore':
+        return t("
+  <p>There will be several vocabularies created by this resource. Two of the more important are \"JavaScript Environments\" and \"JavaScript Conditions\". You should read their explanations below and make sure that these values exist in your vocabularies.</p>
+  <p>In order for this to work, you need to declare both a file and two functions within that file. When the cron task runs, it will call a function that gets a list of files within your project. The files will be run one by one, each calling the second function. Our task expects an array to be returned in the following format:</p>
+  <ul>
+    <li><em>variable</em>: The name of the variable</li>
+    <li><strong>Resource Specific</strong></li>
+    <li><em>#requires</em>: The string literal '#requires'</li>
+    <li><em>#provides</em>: The string literal '#provides'. It should match the requires statements of other files</li>
+    <li><em>resource</em>: Your code might load different files depending on different conditions. A resource is a string to indicate the location of a file</li>
+    <li><em>environment</em>: An indicator of where your code is running. Only one is available during run-time. Must correspond to the entry in \"JavaScript Environments\"</li>
+    <li><em>condition</em>: An indicator of a condition under which your code is running. Multiple conditions are available at run-time. Must correspond to an entry in \"JavaScript Conditions\"</li>
+    <li><strong>Object Specific</strong></li>
+    <li><em>private</em>: True if this object isn't meant to be public</li>
+    <li><em>type</em>: Object type. If it's a function, set to 'Function'</li>
+    <li><em>summary</em>: A short description of what the item does.</li>
+    <li><em>description</em>: An extended description of what the item does.</li>
+    <li><strong>Function Specific</strong></li>
+    <li><em>aliases</em>: The name of a function/variable this references. In code, it would have been fn1 = fn2, where fn1 aliases fn2</li>
+    <li><em>instance</em>: The name of a function that the 'this' variable refers to. Useful if a function is declared in a constructor.</li>
+    <li><em>initialized</em>: True if this variable references an initialized function.</li>
+    <li><em>classlike</em>: True if a function acts like a class.</li>
+    <li><em>prototype</em>: This object is attached via the prototype of this function</li>
+    <li><em>returns</em>: Object type of the function return.</li>
+    <li><em>return summary</em>: Summary of the function return.</li>
+    <li><em>chains</em>: The string literal 'chains'</li>
+    <li><em>chain-type</em>: call, or prototype. Basically, either doing this.call(parent); or this.prototype = new parent; respectively</li>
+    <li><em>function</em>: A function name</li>
+    <li><em>parameters</em>: The string literal 'parameters'</li>
+    <li><em>parameter</em>: The name of the parameter</li>
+    <li><em>optional</v>: True if the parameter is documented as optional</li>
+    <li><em>repeating</em>: True if the parameter is documented as repeating</li>
+    <li><em>type</em>: Object type of the parameter.</li>
+    <li><em>source</em>: Source Code (if it's a function)</li>
+  </ul>
+  <pre>array(
+  'variable' => array(
+    '#requires' => array(
+      array('environment/condition', 'resource')
+    )
+    'type' => '',   
+    'source' => '',
+    'summary' => '',
+    'description' => '',
+    'aliases' => '',
+    'instance' => '',
+    'initialized' => boolean,
+    'prototype' => '',
+    'returns' => '',
+    'return_summary' => '',
+    'chains' => array(
+      array('chain-type', 'function')
+    ),
+    'parameters' => array(
+      'parameter' => array(
+        'optional' => boolean,
+        'repeating' => boolean,
+        'type' => '',
+        'summary' => ''
+      )
+    )
+  )
+)</pre>");
+  }
+
+  return '';
+}
+
+// Views
+// =====
+
+function jsdoc_doc_form(&$node) {
+	$form = array(
+		'#attributes' => array(
+			'enctype' => 'multipart/form-data'
+		)
+	);
+
+	$form['title'] = array(
+		'#type' => 'textfield',
+		'#title' => t('Version Number'),
+		'#default_value' => $node->title
+	);
+
+	$form['counts'] = array(
+		'#type' => 'item',
+		'#title' => t('Objects'),
+		'#value' => ($node->nid ? db_result(db_query("SELECT COUNT(*) FROM {jsdoc_objects} WHERE did = %d", $node->nid)) : 0)
+	);
+
+	$form['upload'] = array(
+		'#title' => t('Documentation File'),
+		'#type' => 'file'
+	);
+
+	$form['download'] = array(
+		'#title' => t('Documentation URL'),
+		'#type' => 'textfield'
+	);
+
+	return $form;
+}
+
+function jsdoc_doc_view($node, $teaser = FALSE, $page = FALSE) {
+  $node->content['counts'] = array(
+    '#type' => 'item',
+    '#title' => t('Objects'),
+    '#value' => db_result(db_query("SELECT COUNT(*) FROM {jsdoc_objects} WHERE did = %d", $node->nid))
+  );
+
+  return $node;
+}
+
+function jsdoc_doc_update($node) {
+  jsdoc_doc_insert($node);
+}
+
+function jsdoc_doc_insert($node) {
+  $start = time();
+  if ($file = file_check_upload()) {
+    $doc = fopen($file->filepath, 'r');
+  }
+  elseif ($node->download) {
+    $doc = fopen($node->download, 'r');
+  }
+  else {
+    return;
+  }
+
+  $buffer = array();
+  while (!feof($doc)) {
+    set_time_limit(30);
+
+    $line = stream_get_line($doc, 9999, "\n");
+    if (preg_match('%^\t"([^"]+)": \{%', $line, $match)) {
+      $id = $match[1];
+      $in = true;
+    }
+    elseif (preg_match('%^\t\}%', $line, $match)) {
+      $in = false;
+      $json = json_decode('{' . implode("\n", $buffer) . '}');
+
+      if ($nid = db_result(db_query("SELECT n.nid FROM {node} AS n INNER JOIN {jsdoc_objects} j ON (j.nid = n.nid) WHERE BINARY n.title = '%s' AND j.did = %d", $id, $node->nid))) {
+        $object = node_load($nid);
+        $object->json = $json;
+      }
+      else {
+        $object = (object)array(
+          'title' => $id,
+          'type' => 'jsdoc_object',
+          'version' => $node,
+          'json' => $json
+        );
+      }
+
+      node_save($object);
+      node_load($object->nid, NULL, TRUE);
+      $buffer = array();
+    }
+    elseif($in) {
+      $buffer[] = $line;
+    }
+  }
+
+  // cache_set("jsdoc_namespaces_{$version->title}
+
+  $query = db_query("DELETE FROM {cache} WHERE cid LIKE 'jsdoc_namespaces_%s:%%'", $node->title);
+
+  $query = db_query("SELECT n.nid FROM {node} AS n INNER JOIN {jsdoc_objects} AS j ON (j.nid = n.nid) WHERE type = 'jsdoc_object' AND j.did = %d AND changed < %d", $node->nid, $start);
+  while ($nid = db_fetch_object($query)) {
+    set_time_limit(30);
+    node_delete($nid->nid);
+  }
+}
+
+function jsdoc_doc_delete(&$node) {
+  $query = db_query("SELECT nid FROM {jsdoc_objects} WHERE did = %d", $node->nid);
+  while ($nid = db_fetch_object($query)) {
+    set_time_limit(30);
+    node_delete($nid->nid);
+  }
+}
+
+// Implemented node-type hook functions
+// ====================================
+
+/**
+ * Implementation of hook_access().
+ */
+function jsdoc_object_access($op, $node) {
+  if ($op == 'update') {
+    return user_access('edit jsdoc');
+  }
+  elseif ($op == 'view') {
+    return user_access('access content');
+  }
+
+  return false;
+}
+
+/**
+ * Implementation of hook_insert().
+ */
+function jsdoc_object_insert($node) {
+  db_query("INSERT INTO {jsdoc_objects} (nid, did, json) VALUES (%d, %d, '%s')", $node->nid, $node->version->nid, serialize($node->json));
+}
+
+/**
+ * Implementation of hook_update().
+ */
+function jsdoc_object_update($node) {
+  db_query("UPDATE {jsdoc_objects} SET json = '%s' WHERE nid = %d", serialize($node->json), $node->nid);
+}
+
+/**
+ * Implementation of hook_delete
+ */
+function jsdoc_object_delete(&$node) {
+  $type = 'jsdoc_' . $node->title;
+  $query = db_query("SELECT sid FROM {jsdoc_variables} WHERE variable = '%s'", $node->title);
+  if ($sid = db_fetch_object($query)) {
+    search_wipe($sid->sid, $type);
+  }
+  db_query("DELETE FROM {jsdoc_objects} WHERE nid = %d", $node->nid);
+}
+
+function _jsdoc_convert_object(&$node, $object, $parent = FALSE, $method = FALSE) {
+  $node->teaser = $object->summary;
+  $node->body = $object->description;
+
+  if (!$node->title && $object->name) {
+    $node->title = $object->name;
+  }
+
+  if (!$node->jsdoc_version) {
+    $node->jsdoc_version = $parent->jsdoc_version;
+  }
+
+  if ($method) {
+    $node->jsdoc_raw_type = 'Function';
+  }
+  else {
+    $node->jsdoc_raw_type = $object->type ? $object->type : 'Object';
+  }
+
+  $node->jsdoc_classlike = $object->classlike;
+
+  $node->jsdoc_formatted = _jsdoc_format_type($node->jsdoc_raw_type, $node->jsdoc_classlike);
+
+  $returndescription = 'return-description';
+  $node->jsdoc_return_summary = $object->$returndescription;
+
+  $returntypes = 'return-types';
+  $node->jsdoc_return_types = $object->$returntypes;
+
+  $node->jsdoc_examples = $object->examples;
+
+  $node->jsdoc_resources = $object->resources;
+
+  $node->jsdoc_provides = $object->provides;
+
+  $node->jsdoc_superclass = $object->superclass;
+
+  $node->jsdoc_mixins = $object->mixins;
+
+  if (!empty($object->tags)) {
+    $node->jsdoc_tags = array();
+    foreach (explode(' ', $object->tags) as $tag) {
+      $node->jsdoc_tags[$tag] = TRUE;
+    }
+  }
+
+  $node->jsdoc_private = $object->private;
+
+  $node->jsdoc_protected = $object->protected;
+
+  $node->jsdoc_deprecated = $object->deprecated;
+
+  $node->jsdoc_private_parent = $object->privateparent;
+
+  $node->jsdoc_scope = $object->scope ? $object->scope : 'normal';
+
+  if ($node->jsdoc_raw_type == 'Function') {
+    if (!$node->jsdoc_classlike) {
+      $parameters = $object->parameters;
+    }
+    else {
+      if (is_array($object->methods)) {
+        $constructors = array();
+        foreach ($object->methods as $method) {
+          if ($method->constructor) {
+            $constructors[$method->constructor] = $method;
+          }
+        }
+        foreach (array('constructor', 'preamble', 'postscript') as $constructor) {
+          if ($method = $constructors[$constructor]) {
+            $node->jsdoc_constructor = $method;
+            if (!empty($method->parameters)) {
+              $parameters = $method->parameters;
+              break;
+            }
+          }
+        }
+        if (!$node->jsdoc_constructor && !empty($constructors)) {
+          $node->jsdoc_constructor = reset($constructors);
+        }
+      }
+    }
+
+    $node->jsdoc_parameters = $parameters;
+  }
+
+  if (!empty($object->methods)) {
+    foreach ($object->methods as $method) {
+      if (!$method->constructor) {
+        $method->jsdoc_url = 'jsdoc/' . jsdoc_get_version($node)->title . '/' . $node->title . '.' . $method->name;
+        $node->jsdoc_methods[] = $method;
+      }
+    }
+  }
+
+  if (!empty($object->properties)) {
+    foreach ($object->properties as $property) {
+      $property->jsdoc_url = 'jsdoc/' . jsdoc_get_version($node)->title . '/' . $node->title . '.' . $property->name;
+      $node->jsdoc_properties[] = $property;
+    }
+  }
+
+  if ($object->jsdoc_url) {
+    $node->jsdoc_url = $object->jsdoc_url;
+  }
+  else {
+    $node->jsdoc_url = 'jsdoc/' . jsdoc_get_version($node)->title . '/' . $node->title;
+  }
+
+  unset($node->json);
+
+  return $node;
+}
+
+/**
+ * Implementation of hook_load().
+ */
+function jsdoc_object_load($node, $method = FALSE) {
+  // TODO: Deal with alias
+  _jsdoc_init();
+
+  $additions = db_fetch_object(db_query("SELECT json, did FROM {jsdoc_objects} WHERE nid = %d", $node->nid));
+  $additions->title = $node->title;
+  $additions->json = unserialize($additions->json);
+  $node->jsdoc_version = $additions->jsdoc_version = node_load($additions->did);
+
+  _jsdoc_convert_object($additions, $additions->json, $node, $method);
+
+  return $additions;
+}
+
+/**
+ * Implementation of hook_view().
+ */
+function jsdoc_object_view($node, $teaser = false, $page = false) {
+  $node->teaser = '';
+  $node->body = '';
+  if (!$teaser) {
+    $node->body = l($node->title, $node->jsdoc_url);
+  }
+  $node->title = t('Object');
+  $node->taxonomy = array();
+  $node = node_prepare($node, $teaser);
+  return $node;
+}
+
+/**
+ * Path: admin/settings/jsdoc
+ */
+function jsdoc_admin() {
+  $form = array();
+  
+  $formats = filter_formats();
+  $options = array();
+  foreach ($formats as $format) {
+    $options[$format->format] = $format->name;
+  }
+
+  $form['jsdoc_input_format'] = array(
+    '#title' => t('Default Input Format'),
+    '#type' => 'radios',
+    '#options' => $options,
+    '#required' => true,
+    '#default_value' => variable_get('jsdoc_input_format', 1)
+  );
+
+  return system_settings_form($form);
+}
+
+function jsdoc_get_version(&$node = FALSE) {
+  if (!$node) {
+    foreach (jsdoc_get_versions() as $version) {
+      if ($version->title != 'HEAD') {
+        return $version;
+      }
+    }
+  }
+  return $node->jsdoc_version;
+}
+
+function jsdoc_get_versions($node = FALSE, $title = NULL) {
+  static $cache = array();
+  $versions = array();
+
+  if ($node) {
+    if ($node->title) {
+      $cache_key = $node->title;
+      if ($cache[$cache_key]) {
+        return $cache[$cache_key];
+      }
+    }
+    $with_json = ($title) ? ', j.json' : '';
+    $query = db_query("SELECT j.did AS nid $with_json FROM {jsdoc_objects} j INNER JOIN {node} n ON (n.nid = j.nid) WHERE n.title = '%s' GROUP BY j.did", $node->title);
+  }
+  else {
+    $cache_key = '%ALL%';
+    if (isset($cache[$cache_key])) {
+      return $cache[$cache_key];
+    }
+    $query = db_query("SELECT nid FROM {node} WHERE type = 'jsdoc_doc' ORDER BY nid DESC");
+  }
+
+  while ($version = db_fetch_object($query)) {
+    if ($version->json && $node->title != $title) {
+      $parts = explode('.', $title);
+      if (count($parts) > 1) {
+        $last = array_pop($parts);
+        $parent = implode('.', $parts);
+        $found = FALSE;
+        $json = unserialize($version->json);
+        $properties = array();
+        if ($json->methods) {
+          $properties = array_merge($properties, $json->methods);
+        }
+        if ($json->properties) {
+          $properties = array_merge($properties, $json->properties);
+        }
+        foreach ($properties as $property) {
+          if ($property->scope == 'normal' && $property->name == $title) {
+            $found = TRUE;
+            break;
+          }
+          elseif ($property->name == $last) {
+            $found = TRUE;
+            break;
+          }
+        }
+        if (!$found) {
+          continue;
+        }
+      }
+    }
+    $versions[] = node_load($version->nid);
+  }
+
+  if ($cache_key) {
+    $cache[$cache_key] = $versions;
+  }
+
+  return $versions;
+}
+
+function jsdoc_get_return_summary(&$node) {
+  if (isset($node->jsdoc_return_summary_formatted)) {
+    return $node->jsdoc_return_summary_formatted;
+  }
+
+  return ($node->jsdoc_return_summary_formatted = trim(preg_replace('%(^<p>|</p>$)%', '', str_replace("\n", ' ', $object->jsdoc_return_summary))));
+}
+
+function jsdoc_get_return_types(&$node) {
+  if (empty($node->jsdoc_return_types)) {
+    return array();
+  }
+  return $node->jsdoc_return_types;
+}
+
+function jsdoc_get_parameters(&$node) {
+  if (isset($node->jsdoc_formatted_parameters)) {
+    return $node->jsdoc_formatted_parameters;
+  }
+
+  if (empty($node->jsdoc_parameters)) {
+    $node->jsdoc_parameters = array();
+  }
+
+  foreach ($node->jsdoc_parameters as $i => $parameter) {
+    $node->jsdoc_parameters[$i]->jsdoc_formatted = _jsdoc_format_type($parameter->type, false, $parameter->usage == 'optional', $parameter->usage == 'repeating' || $parameter->usage == 'one-or-more');
+  }
+
+  return ($node->jsdoc_formatted_parameters = $node->jsdoc_parameters);
+}
+
+function jsdoc_get_examples(&$node, $markedup=false) {
+  if (empty($node->jsdoc_examples)) {
+    return array();
+  }
+  if (isset($node->jsdoc_formatted_examples)) {
+    return $node->jsdoc_formatted_examples;
+  }
+
+  $examples = array();
+  foreach ($node->jsdoc_examples as $example) {
+    $examples[] = _jsdoc_markup_text($example, jsdoc_get_version($node), $node->title);
+  }
+
+  return ($node->jsdoc_formatted_examples = $examples);
+}
+
+function jsdoc_get_parent_prototype(&$node) {
+  if ($node->jsdoc_superclass) {
+    return jsdoc_object_node_load($node->jsdoc_superclass, jsdoc_get_version($node));
+  }
+}
+
+function jsdoc_is_initialized(&$node) {
+  return false;
+}
+
+function jsdoc_get_tags(&$node) {
+  if (empty($node->jsdoc_tags)) {
+    return array();
+  }
+  return $node->jsdoc_tags;
+}
+
+function jsdoc_is_classlike(&$node) {
+  return $node->jsdoc_classlike;
+}
+
+function jsdoc_get_teaser(&$node) {
+  if (isset($node->formatted_teaser)) {
+    return $node->formatted_teaser;
+  }
+
+  return ($node->formatted_teaser = $node->teaser);
+}
+
+function jsdoc_get_body(&$node) {
+  $version = jsdoc_get_version($node)->title;
+  $body = trim($node->body);
+  $variables = _jsdoc_get_variables();
+  foreach (array_unique(preg_split('%\s+%', strip_tags($body))) as $variable) {
+    if ($variables[$variable] && $variable != $node->title) {
+      $body = str_replace($variable, l($variable, 'jsdoc/' . $version . '/' . $variable), $body);
+    }
+  }
+  return $body;
+}
+
+function jsdoc_is_function(&$node) {
+  return (jsdoc_get_type($node) == 'Function' || jsdoc_get_type($node) == 'Constructor');
+}
+
+function jsdoc_is_private(&$node) {
+  return $node->jsdoc_private;
+}
+
+function jsdoc_is_protected(&$node) {
+  return $node->jsdoc_protected;
+}
+
+function jsdoc_is_deprecated(&$node) {
+  return $node->jsdoc_deprecated;
+}
+
+function jsdoc_has_private_parent(&$node) {
+  foreach (jsdoc_get_namespace_parents($node) as $parent) {
+    if ($parent->jsdoc_private) {
+      return true;
+    }
+  }
+
+  return $node->jsdoc_private_parent;
+}
+
+function jsdoc_get_type(&$node) {
+  if (isset($node->jsdoc_type)) {
+    return $node->jsdoc_type;
+  }
+
+  if (is_object($node->type)) {
+    $type = $node->type->title;
+  }
+  else {
+    $type = $node->jsdoc_raw_type;
+    unset($node->jsdoc_raw_type);
+  }
+
+  if ($type == 'Function') {
+    if (jsdoc_is_classlike($node)) {
+      $type = 'Constructor';
+    }
+    elseif (count(jsdoc_get_child_instances($node, true)) || count(jsdoc_get_child_prototypes($node, true))) {
+      $type = 'Constructor';
+    }
+  }
+
+  return ($node->jsdoc_type = $type);
+}
+
+function jsdoc_get_resource(&$node) {
+  if (count($node->jsdoc_resources) == 1) {
+    return $node->jsdoc_resources[0];
+  }
+}
+
+function jsdoc_get_source($node, $resolve=false, $depth=0) {
+  return '';
+}
+
+function jsdoc_get_provide(&$node) {
+  if (count($node->jsdoc_provides) == 1) {
+    return $node->jsdoc_provides[0];
+  }
+}
+
+function jsdoc_get_mixins(&$node, $type = NULL) {
+  if (empty($node->jsdoc_mixins)) {
+    return array();
+  }
+  if (isset($node->jsdoc_resolved_mixins)) {
+    return $type ? $node->jsdoc_resolved_mixins[$type] : $node->jsdoc_resolved_mixins;
+  }
+
+  $version = jsdoc_get_version($node);
+  $resolved_mixins = array('prototype' => array(), 'instance' => array(), 'normal' => array());
+  foreach ($node->jsdoc_mixins as $from => $mixins) {
+    foreach ($mixins as $mixin) {
+      $location = $mixin->location;
+      if (substr($location, -10) == '.prototype') {
+        $location = substr($location, 0, -10);
+      }
+      $mixin_node = jsdoc_object_node_load($location, $version);
+      if ($mixin_node->nid) {
+        $resolved_mixins[$from][] = (object)array(
+          'attached' => $node,
+          'scope' => $mixin->scope,
+          'node' => $mixin_node
+        );
+      }
+    }
+  }
+
+  $node->jsdoc_resolved_mixins = $resolved_mixins;
+
+  return jsdoc_get_mixins($node, $type);
+}
+
+function _jsdoc_get_attributes($attribute, &$node, $is_method, $scope) {
+  $attribute = 'jsdoc_' . $attribute;
+
+  $items = array();
+  if (!empty($node->$attribute)) {
+    foreach ($node->$attribute as $item){
+      $converted = (object)array(
+        'title' => "{$node->title}.{$item->name}",
+        'name' => $item->name
+      );
+      if ($scope) {
+        $scopes = explode('-', $item->scope);
+        if (in_array($scope, $scopes)) {
+          $items[] = _jsdoc_convert_object($converted, $item, $node, $is_method);
+        }
+      }
+      else {
+        $items[] = _jsdoc_convert_object($converted, $item, $node, $is_method);
+      }
+    }
+  }
+
+  if (!$scope || $scope == 'normal') {
+    $query = db_query("SELECT n.nid, n.title FROM {node} AS n INNER JOIN {jsdoc_objects} AS j ON (j.nid = n.nid) WHERE n.title LIKE '%s.%%' AND j.did = %d", $node->title, jsdoc_get_version($node)->nid);
+    while ($result = db_fetch_object($query)) {
+      $parts = explode('.', $result->title);
+      $name = array_pop($parts);
+      if (implode('.', $parts) == $node->title) {
+        $item = node_load($result->nid);
+        $item->name = $name;
+        if ($is_method) {
+          if ($item->jdsoc_raw_type == 'Function') {
+            $items[] = $item;
+          }
+        }
+        else {
+          $items[] = $item;
+        }
+      }
+    }
+  }
+
+  return $items;
+}
+
+function jsdoc_get_methods(&$node, $scope = NULL) {
+  return _jsdoc_get_attributes('methods', $node, TRUE, $scope);
+}
+
+function jsdoc_get_properties(&$node, $scope = NULL) {
+  return _jsdoc_get_attributes('properties', $node, FALSE, $scope);
+}
+
+function jsdoc_get_child_instances() {
+  return array();
+}
+
+function jsdoc_get_child_prototypes() {
+  return array();
+}
+
+function jsdoc_is_namespace(&$node) {
+  return !!$node->nid && $node->jsdoc_raw_type != 'Function';
+}
+
+
+// Node Load Functions
+// ===================
+
+/**
+ * Custom version of node_load for versions
+ */
+function jsdoc_version_node_load($version_name) {
+  return node_load(array(
+    'type' => 'jsdoc_doc',
+    'title' => $version_name
+  ));
+}
+
+function jsdoc_object_node_load($name, $version=false, $exact=true, $broad=false) {
+  $nodes = jsdoc_object_nodes_load($name, $version, $exact, $broad);
+  if (count($nodes) == 1) {
+    return $nodes[0];
+  }
+  elseif (!empty($nodes)) {
+    $version = jsdoc_get_version();
+    foreach($nodes as $match) {
+      if ($match->version->nid == $version->nid) {
+        return $match;
+      }
+    }
+  }
+  return (object)array();
+}
+
+/**
+ * Custom version of node_load for objects
+ */
+function jsdoc_object_nodes_load($name, $version=false, $exact=true, $broad=false) {
+  static $cache = array();
+
+  $lower_name = strtolower($name);
+
+  $override_name = false;
+  $name_override = $name;
+
+  if ($lower_name == 'bool') {
+    $name = 'Boolean';
+  }
+  elseif ($lower_name == 'int' || $lower_name == 'integer') {
+    $override_name = true;
+    $name_override = 'Integer';
+    $name = 'Number';
+  }
+  elseif ($lower_name == 'float' || $lower_name == 'decimal') {
+    $override_name = true;
+    $name_override = ucfirst($lower_name);
+    $name = 'Number';
+  }
+
+  $global_vars = array('Array', 'Boolean', 'Date', 'Error', 'Function', 'Number', 'Object', 'RegExp', 'String');
+  $lower_global_vars = array('array', 'boolean', 'date', 'error', 'function', 'number', 'object', 'regexp', 'string');
+  if (($pos = array_search($lower_name, $lower_global_vars)) !== false) {
+    $name = $global_vars[$pos];
+  }
+
+  if (in_array($name, $global_vars)) {
+    return array((object)array(
+      'title' => ($override_name) ? $name_override : $name,
+      'jsdoc_url' => 'http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:' . $name
+    ));
+  }
+  elseif ($lower_name == 'window') {
+    return array((object)array(
+      'title' => $name,
+      'jsdoc_url' => 'http://developer.mozilla.org/en/docs/DOM:window'
+    ));
+  }
+  elseif ($lower_name == 'documentelement' || $lower_name == 'document') {
+    return array((object)array(
+      'title' => $name,
+      'jsdoc_url' => 'http://developer.mozilla.org/en/docs/DOM:document'
+    ));
+  }
+  elseif (in_array($lower_name, array('node', 'htmlelment', 'domnode'))) {
+    return array((object)array(
+      'title' => $name,
+      'jsdoc_url' => 'http://developer.mozilla.org/en/docs/DOM:element'
+    ));
+  }
+  elseif ($name == 'Constructor') {
+    return array((object)array(
+      'title' => $name,
+      'jsdoc_url' => 'http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Class-Based_vs._Prototype-Based_Languages#Defining_a_Class'
+    ));
+  }
+
+  // Resolve the version the best that we can
+  if (is_object($version) && $version->nid) {
+    $version_nid = $version->nid;
+  }
+  elseif (is_string($version)) {
+    $version_nid = jsdoc_version_node_load($version)->nid;
+  }
+  elseif (is_numeric($version)) {
+    $version_nid = $version;
+  }
+
+  if ($version_nid && (!is_object($version) || !$version->nid)) {
+    $version = node_load($version_nid);
+  }
+
+  if ($name) {
+    $cache_key = sprintf('%s,%s,%s,%s', $name, $version_nid, $exact, $broad);
+    if (isset($cache[$cache_key])) {
+      $nodes = array();
+      foreach ($cache[$cache_key] as $nid) {
+        $nodes[] = node_load($nid);
+      }
+      if (empty($nodes)) {
+        if ($broad) {
+          return array((object)array(
+            'title' => $name
+          ));
+        }
+        else {
+          return array();
+        }
+      }
+      return $nodes;
+    }
+
+    // We have a few situations:
+    //    name
+    //    project, name
+    //    project, version, name
+    //    project, version, resource, name
+
+    // If we're missing the version, assume the latest release
+    // If we're missing the project, look up stuff by name
+
+    $binary = ($exact) ? 'BINARY' : '';
+    $title_check = ($exact) ? "= '%s'" : "LIKE '%%%s%%'";
+    $nodes = array();
+    $results = array();
+
+    if ($version_nid) {
+      $query = db_query("SELECT n.nid FROM {node} n INNER JOIN {jsdoc_objects} j ON (j.nid = n.nid) WHERE n.title $title_check AND $binary n.title $title_check AND j.did = %d", $name, $name, $version_nid);
+    }
+    else {
+      $version_nids = array(-1);
+      foreach (jsdoc_get_versions() as $version) {
+        $version_nids[] = $version->nid;
+      }
+      $query = db_query("SELECT n.nid, j.did, version.title AS version FROM {node} n INNER JOIN {jsdoc_objects} j ON (j.nid = n.nid) INNER JOIN {node} version ON (version.nid = j.did) WHERE n.title $title_check AND $binary n.title $title_check AND j.did IN (%s) ORDER BY version.created DESC", $name, $name, implode(',', $version_nids));
+    }
+
+    while ($result = db_fetch_object($query)) {
+      if ($result->version) {
+        if ($result->version != 'HEAD') {
+          $nodes[] = node_load($result->nid);
+          break;
+        }
+      }
+      else {
+        $nodes[] = node_load($result->nid);
+      }
+    }
+
+    $cache[$cache_key] = array_map('_jsdoc_extract_nids', $nodes);
+  }
+
+  if (empty($nodes)) {
+    if ($broad) {
+      return array((object)array(
+        'title' => $name
+      ));
+    }
+    else {
+      return array();
+    }
+  }
+
+  return $nodes;
+}
+
+function _jsdoc_extract_nids($node) {
+  return $node->nid;
+}
+
+function jsdoc_parameter_weight_sort($a, $b){
+  return ($a['weight'] == $b['weight']) ? 0 : ($a['weight'] < $b['weight']) ? -1 : 1;
+}
+
+/**
+ * Path: jsdoc/404
+ */
+function jsdoc_404() {
+  $args = explode('/', $_REQUEST['destination']);
+  if (count($args) == 1 && $args[0] != 'jsdoc') {
+    global $_menu;
+    unset($_menu['items']);
+    menu_set_active_item('jsdoc/' . $args[0]);
+    print theme('page', menu_execute_active_handler());
+    exit();
+  }
+
+  return '<p>' . t('The page you requested was not found.') . '</p>';
+}
+
+/**
+ * Path: jsdoc/feedback
+ */
+function jsdoc_feedback() {
+  $count = 0;
+  if ($_POST['page'] && $_POST['feedback']) {
+    $feedback = array();
+    if ($cached = cache_get('jsdoc_feedback')) {
+      $feedback = unserialize($cached->data);
+    }
+
+    if (!isset($feedback[$_POST['page']][$_POST['feedback']])) {
+      $feedback[$_POST['page']][$_POST['feedback']] = 0;
+    }
+
+    $count = ++$feedback[$_POST['page']][$_POST['feedback']];
+
+    cache_set('jsdoc_feedback', 'cache', serialize($feedback));
+  }
+
+  print $count;
+}
+
+function jsdoc_feedback_review() {
+  drupal_set_title(t('Feedback Review'));
+
+  $feedback = array();
+  if ($cached = cache_get('jsdoc_feedback')) {
+    $feedback = unserialize($cached->data);
+  }
+
+  $by_count = array();
+  foreach ($feedback as $page => $stats) {
+    $total = 0;
+    foreach ($stats as $type => $count) {
+      $total += $count;
+    }
+    $by_count[$total][] = array(
+      'page' => $page,
+      'feedback' => $stats
+    );
+  }
+
+  krsort($by_count);
+
+  $output = '<ul>';
+  foreach ($by_count as $pages) {
+    foreach ($pages as $page) {
+      $output .= '<li>' . l($page['page'], sprintf('jsdoc/%s', $page['page'])) . '<ul>';
+      foreach ($page['feedback'] as $type => $count) {
+        $output .= '<li>' . $type . ': ' . $count . '</li>';
+      }
+      $output .= '</ul></li>';
+    }
+  }
+  $output .= '</ul>';
+
+  return $output;
+}
+
+/**
+ * Path: jsdoc/jsonp
+ */
+function jsdoc_jsonp($batch=false, $json=false) {
+  $recursion = false;
+  if ($json) {
+    $recursion = true;
+    $_JSON = $json;
+  }
+  else {
+    $_JSON = array();
+    foreach (explode('&', getenv('QUERY_STRING')) as $query_string) {
+      list($key, $value) = explode('=', $query_string, 2);
+      $value = urldecode($value);
+      if (isset($_JSON[$key])) {
+        if (!is_array($_JSON[$key])) {
+          $_JSON[$key] = array($_JSON[$key]);
+        }
+        $_JSON[$key][] = $value;
+      }
+      else {
+        $_JSON[$key] = $value;
+      }
+    }
+  }
+
+  $names = array();
+  if ($batch) {
+    $names = (is_array($_JSON['names'])) ? $_JSON['names'] : array($_JSON['names']);
+  }
+  else {
+    $names = array($_JSON['name']);
+  }
+
+  $attributes = ($_JSON['attributes']) ? $_JSON['attributes'] : array('summary', 'type', 'returns', 'parameters');
+  if (!is_array($attributes)) {
+    $attributes = array($attributes);
+  }
+
+  foreach ($names as $name) {
+    if (empty($name)) {
+      continue;
+    }
+    if ($_JSON['exact']) {
+      if ($nodes = jsdoc_object_node_load($name, $_JSON['version'], true)){
+        $nodes = array($nodes);
+      }
+    }
+    else {
+      $nodes = jsdoc_object_nodes_load($name, $_JSON['version'], false);
+    }
+    foreach ($nodes as $node) {
+      $formatted = (object)array('name' => $name);
+      foreach ($attributes as $attribute) {
+        switch ($attribute) {
+          case 'summary':
+            $formatted->summary = jsdoc_get_teaser($node);
+            break;
+          case 'type':
+            $formatted->type = jsdoc_get_type($node);
+            break;
+          case 'returns':
+            $formatted->returns = array(
+              'types' => array(),
+              'summary' => jsdoc_get_return_summary($node)
+            );
+            foreach (jsdoc_get_return_types($node) as $type) {
+              $themed = _jsdoc_get_type_themed($type->type, $node, true);
+              if ($themed) {
+                $formatted->returns['types'][] = $themed;
+              }
+              else {
+                $formatted->returns['types'][] = array(
+                  'title' => $type
+                );
+              }
+            }
+          case 'parameters':
+            $formatted->parameters = _jsdoc_get_parameters_themed($node, true);
+            if (!count($formatted->parameters)) {
+              unset($formatted->parameters);
+            }
+            break;
+        }
+      }
+      if ($_JSON['recursive']) {
+        $children = array_keys(jsdoc_get_child_variables($node));
+        if (!empty($children))
+          $formatted->children = jsdoc_jsonp(true, array(
+            'attributes' => $_JSON['attributes'],
+            'names' => $children,
+            'recursive' => $_JSON['recursive']
+          ));
+      }
+      $output[] = $formatted;
+    }
+  }
+
+  $found = array();
+  foreach ($output as $object) {
+    $found[] = $object->name;
+  }
+  foreach (array_diff($names, $found) as $name) {
+    $output[] = (object)array(
+      'name' => $name
+    );
+  }
+
+  if ($recursion) {
+    return $output;
+  }
+  print $_GET['callback'] . '(' . str_replace('"__className":"stdClass",', '', json_encode($output)) . ');';
+}
+
+function jsdoc_get_closest($name, $version) {
+  $node = jsdoc_object_node_load($name, $version);
+  if (!$node->nid) {
+    $parts = explode('.', $name);
+    while (!$node->nid) {
+      array_pop($parts);
+      if (empty($parts)) {
+        break;
+      }
+      $node = jsdoc_object_node_load(implode('.', $parts), $version);
+    }
+  }
+  return $node;
+}
+
+function _jsdoc_resolve_child($node, $name) {
+  list($prototype_chain, $mixin_chain, $children) = jsdoc_get_oo_info($node, $name);
+
+  $actual = (object)array(
+    'title' => $name,
+    'jsdoc_version' => jsdoc_get_version($node)
+  );
+
+  foreach ($children as $possible) {
+    if ($possible->title == $name || $node->title . '.' . $possible->title == $name) {
+      $actual = $possible->node;
+      $actual->type = $possible->type;
+      unset($actual->jsdoc_type);
+      break;
+    }
+  }
+
+  $actual->format = $node->format;
+  $actual->title = $name;
+
+  if (empty($actual->teaser) && empty($actual->body)) {
+    $actual->teaser = ' ';
+    $actual->body = ' ';
+  }
+
+  return $actual;
+}
+
+/**
+ * A menu callback
+ * Will only ever be a function or property
+ */
+function jsdoc_child_node_view($node, $name) {
+  $actual = _jsdoc_resolve_child($node, $name);
+
+  drupal_set_title(theme('jsdoc_object_title', _jsdoc_get_title_themed($actual)));
+
+  $form = _jsdoc_node_prepare($actual);
+
+  if ($provide = jsdoc_get_provide($actual)) {
+    $form['require'] = array(
+      '#value' => theme('jsdoc_object_require', $provide),
+      '#weight' => -20
+    );
+  }
+
+  if ($resource = jsdoc_get_resource($actual)) {
+    $form['resource'] = array(
+      '#value' => theme('jsdoc_object_resource', jsdoc_get_resource($node))
+    );
+  }
+
+  $examples = array();
+  foreach (jsdoc_get_examples($actual, true) as $weight => $example) {
+    $examples[] = theme('jsdoc_object_example', $example, $weight + 1);
+  }
+  if (!empty($examples)) {
+    $form['examples'] = array(
+      '#value' => theme('jsdoc_object_examples', $examples),
+      '#weight' => 35
+    );
+  }
+
+  if (jsdoc_is_function($actual)) {
+    $parameters = _jsdoc_get_parameters_themed($actual);
+
+    if (count($parameters)) {
+      $form['parameters'] = array(
+        '#value' => theme('jsdoc_function_parameters', $parameters, _jsdoc_get_object_themed($actual, $actual->title)),
+        '#weight' => 20
+      );
+    }
+
+    $function = (object)array(
+      'source' => jsdoc_get_source($actual, true),
+      'markedup' => _jsdoc_markup_code(jsdoc_get_source($actual, true), jsdoc_get_version($node)->nid, $actual->title, FALSE),
+      'signature' => _jsdoc_build_function_signature($actual, $parameters)
+    );
+    if (count($parameters)) {
+      $function->parameters = $parameters;
+    }
+
+    $form['function'] = array(
+      '#value' => theme('jsdoc_function_information', $function, $children, _jsdoc_get_object_themed($actual, $actual->title)),
+      '#weight' => 30
+    );
+  }
+  elseif (($object = jsdoc_object_node_load(jsdoc_get_type($actual), jsdoc_get_version($node))) && $object->nid) {
+    list($prototype_chain, $mixin_chain, $children) = jsdoc_get_oo_info($object);
+
+    $theme_children = array();
+    foreach ($children as $child) {
+      if ($child->instance || $child->prototype) {
+        $theme_children[] = $child;
+      }
+    }
+
+    if (count($theme_children)) {
+      $form['children'] = array(
+        '#value' => theme('jsdoc_object_children', $theme_children),
+        '#weight' => 40
+      );
+    }
+  }
+
+  return drupal_render_form('jsdoc_child_form', $form);
+}
+
+/**
+ * Climbs up the prototype chain through mixins
+ *
+ * Move down the prototype chain
+ * The prototype chains of the parents have already been calculated
+ * For each one, inject its resolved mixins above the current class
+ */
+function _jsdoc_resolve_mixins($node, $from) {
+  $resolved_mixins = array();
+
+  $all_mixins = array();
+  if ($from == 'prototype') {
+    $prototype_chain = jsdoc_get_prototype_chain($node);
+    foreach ($prototype_chain as $parent) {
+      if (!$parent->nid) { continue; }
+      $all_mixins[] = $parent;
+    }
+  }
+  $all_mixins[] = $node;
+
+  foreach ($all_mixins as $parent) {
+    foreach (jsdoc_get_mixins($parent, $from) as $mixin) {
+      foreach (_jsdoc_resolve_mixins($mixin->node, $from) as $other_mixin) {
+        if (!$other_mixin->node->nid) { continue; }
+        $resolved_mixins[] = $other_mixin;
+      }
+      $resolved_mixins[] = $mixin;
+    }
+    $resolved_mixins[] = (object)array(
+      'attached' => $node,
+      'scope' => 'prototype',
+      'node' => $parent
+    );
+  }
+
+  for ($i = 0; $i < count($resolved_mixins); $i++) {
+    for ($j = $i + 1; $j < count($resolved_mixins); $j++) {
+      if ($resolved_mixins[$i]->node->title == $resolved_mixins[$j]->node->title) {
+        array_splice($resolved_mixins, $i, 1);
+        continue 2;
+      }
+    }
+  }
+
+  return $resolved_mixins;
+}
+
+function jsdoc_get_oo_info(&$node, $child=NULL) {
+  if (isset($node->jsdoc_oo_info)) {
+    return $node->jsdoc_oo_info;
+  }
+
+  $returned_mixin_chain = array();
+  $mixin_chain = array();
+
+  if (jsdoc_is_classlike($node)) {
+    $prototype_chain = jsdoc_get_prototype_chain($node);
+
+    // Start out with simply the prototype chain
+    $prototype_chain_values = array();
+    foreach ($prototype_chain as $prototype) {
+      if ($prototype->nid) {
+        $prototype_chain_values[] = $prototype->title;
+      }
+    }
+
+    // Resolve prototype-level items
+    foreach (_jsdoc_resolve_mixins($node, 'prototype') as $mixin) {
+      $mixin_chain[] = (object)array(
+        'attached' => $mixin->attached,
+        'scope' => 'prototype',
+        'from' => $mixin->scope,
+        'methods' => jsdoc_get_methods($mixin->node, $mixin->scope),
+        'properties' => jsdoc_get_properties($mixin->node, $mixin->scope),
+        'in_prototype_chain' => in_array($mixin->node->title, $prototype_chain_values),
+        'node' => $mixin->node
+      );
+    }
+
+    $returned_mixin_chain = array();
+    $returned_mixin_titles = array();
+    foreach ($mixin_chain as $mixin) {
+      if ($mixin->in_prototype_chain || $mixin->attached->title == $node->title) {
+        if ($mixin->node->title != $node->title && !$returned_mixin_titles[$mixin->node->title]) {
+          $returned_mixin_titles[$mixin->node->title] = TRUE;
+          $returned_mixin_chain[] = $mixin;
+        }
+      }
+    }
+
+    $mixin_chain[] = (object)array(
+      'scope' => 'prototype',
+      'from' => 'prototype',
+      'methods' => jsdoc_get_methods($node, 'prototype'),
+      'properties' => jsdoc_get_properties($node, 'prototype'),
+      'in_prototype_chain' => true,
+      'node' => $node
+    );
+
+    // Now with instance-level items
+
+    foreach (_jsdoc_resolve_mixins($node, 'instance') as $mixin) {
+      $mixin_chain[] = (object)array(
+        'scope' => 'instance',
+        'from' => $mixin->scope,
+        'methods' => jsdoc_get_methods($mixin->node, $mixin->scope),
+        'properties' => jsdoc_get_properties($mixin->node, $mixin->scope),
+        'in_prototype_chain' => in_array($mixin->node->title, $prototype_chain_values),
+        'node' => $mixin->node
+      );
+    }
+
+    $mixin_chain[] = (object)array(
+      'scope' => 'instance',
+      'from' => 'instance',
+      'methods' => jsdoc_get_methods($node, 'instance'),
+      'properties' => jsdoc_get_properties($node, 'instance'),
+      'in_prototype_chain' => false,
+      'node' => $node
+    );
+
+    array_pop($prototype_chain);
+  }
+
+  $mixin_chain[] = (object)array(
+    'scope' => 'normal',
+    'from' => 'instance',
+    'methods' => jsdoc_get_methods($node, 'normal'),
+    'properties' => jsdoc_get_properties($node, 'normal'),
+    'in_prototype_chain' => false,
+    'node' => $node
+  );
+
+  $child_attribute = false;
+  if ($child) {
+    list($child_attribute) = array_slice(explode('.', $child), -1);
+  }
+  $children = array();
+  foreach ($mixin_chain as $mixin) {
+    foreach (array('methods', 'properties') as $child_type) {
+      foreach ($mixin->$child_type as $item) {
+        list($item_attribute) = array_slice(explode('.', $item->title), -1);
+
+        if ($child_attribute && $item_attribute != $child_attribute) {
+          continue;
+        }
+
+        if ($mixin->scope == 'normal') {
+          $title = $item->title;
+        }
+        else {
+          $title = $item_attribute;
+        }
+
+        if (jsdoc_get_type($item) == 'Constructor' && ($resolved = jsdoc_resolve_constructor($item))) {
+          $item->jsdoc_parameters = $resolved->jsdoc_parameters;
+          $item->jsdoc_return_summary = $resolved->jsdoc_return_summary;
+          $item->jsdoc_return_types = $resolved->jsdoc_return_types;
+          $item->teaser = $resolved->teaser;
+        }
+
+        if ($children[$title]) {
+          $found = false;
+          if ($children[$title]->inheritance) {
+            foreach ($children[$title]->inheritance as $parent) {
+              if ($parent->title == $mixin->node->title) {
+                $found = true;
+                break;
+              }
+            }
+          }
+          if (!$found) {
+            if ($mixin->node->title == $node->title) {
+              $children[$title]->override = true;
+            }
+            else {
+              $children[$title]->inheritance[] = _jsdoc_get_object_themed($mixin->node);
+            }
+            $inherited = _jsdoc_get_object_themed($item, $title);
+            foreach ($inherited as $key => $value) {
+              if ($key == 'summary' && trim($value) == '') {
+                continue;
+              }
+              $children[$title]->$key = $value;
+            }
+          }
+        }
+        else {
+          $children[$title] = _jsdoc_get_object_themed($item, $title);
+          $children[$title]->node = $item;
+          if ($mixin->node->title != $node->title && ($mixin->scope != 'normal' || implode('.', array_slice(explode('.', $title), 0, -1)) != $node->title)) {
+            $children[$title]->inheritance[] = _jsdoc_get_object_themed($mixin->node);
+          }
+        }
+
+        $scope = $mixin->scope;
+        $children[$title]->$scope = TRUE;
+
+        if ($title == $item->title) {
+          $children[$title]->actual_title = $title;
+        }
+        else {
+          $children[$title]->actual_title = $mixin->node->title . '.' . $title;
+        }
+
+        $type = $item->jsdoc_scope;
+        $children[$title]->$type = true;
+
+        if (trim(jsdoc_get_teaser($item)) != '') {
+          $children[$title]->summary = jsdoc_get_teaser($item);
+        }
+      }
+    }
+  }
+  uksort($children, "strnatcasecmp");
+
+  return ($node->jsdoc_oo_info = array($prototype_chain, $returned_mixin_chain, $children));
+}
+
+/**
+ * A menu callback
+ * Will only ever be a constructor or namespace
+ */
+function jsdoc_object_node_view($node) {
+  ini_set('memory_limit', '128M');
+  // Test for the basics
+  if (!$node) {
+    return drupal_not_found();
+  }
+
+  drupal_set_title(theme('jsdoc_object_title', _jsdoc_get_title_themed($node)));
+
+  if (empty($node->teaser) && empty($node->body)) {
+    $node->teaser = ' ';
+    $node->body = ' ';
+  }
+
+  $form = _jsdoc_node_prepare($node);
+
+  if ($provide = jsdoc_get_provide($node)) {
+    $form['require'] = array(
+      '#value' => theme('jsdoc_object_require', $provide),
+      '#weight' => -20
+    );
+  }
+
+  if ($resource = jsdoc_get_resource($node)) {
+    $form['resource'] = array(
+      '#value' => theme('jsdoc_object_resource', jsdoc_get_resource($node))
+    );
+  }
+
+  $examples = array();
+  foreach (jsdoc_get_examples($node, true) as $weight => $example) {
+    $examples[] = theme('jsdoc_object_example', $example, $weight + 1);
+  }
+  if (!empty($examples)) {
+    $form['examples'] = array(
+      '#value' => theme('jsdoc_object_examples', $examples),
+      '#weight' => 35
+    );
+  }
+
+  list($prototype_chain, $mixin_chain, $children) = jsdoc_get_oo_info($node);
+
+  if (jsdoc_is_classlike($node)) {
+    $form['prototype_chain'] = array(
+      '#value' => theme('jsdoc_object_prototype_chain', $prototype_chain),
+      '#weight' => 10
+    );
+  }
+
+  if (!empty($mixin_chain)) {
+    $form['parent_mixins'] = array(
+      '#value' => theme('jsdoc_object_mixins', $mixin_chain),
+      '#weight' => 40
+    );
+  }
+
+  if (jsdoc_is_function($node)) {
+    $actual = $node;
+    if (jsdoc_is_classlike($node)) {
+      $actual = jsdoc_resolve_constructor($node);
+    }
+
+    $parameters = _jsdoc_get_parameters_themed($actual);
+
+    if (count($parameters)) {
+      $form['parameters'] = array(
+        '#value' => theme('jsdoc_function_parameters', $parameters, _jsdoc_get_object_themed($node, $node->title)),
+        '#weight' => 20
+      );
+    }
+
+    $base = false;
+    if (jsdoc_get_type($node) == 'Constructor') {
+      $base = $node->title;
+    }
+
+    $function = (object)array(
+      'source' => jsdoc_get_source($actual, true),
+      'markedup' => _jsdoc_markup_code(jsdoc_get_source($actual, true), jsdoc_get_version($node)->nid, $actual->title, $base),
+      'signature' => _jsdoc_build_function_signature($actual, $parameters)
+    );
+    if (count($parameters)) {
+      $function->parameters = $parameters;
+    }
+
+    $form['function'] = array(
+      '#value' => theme('jsdoc_function_information', $function, $children, _jsdoc_get_object_themed($node, $node->title)),
+      '#weight' => 30
+    );
+  }
+
+  if (count($children)) {
+    $form['children'] = array(
+      '#value' => theme('jsdoc_object_children', $children),
+      '#weight' => 40
+    );
+  }
+
+  if (function_exists('comment_render') && $node->comment) {
+    $form['comments'] = array(
+      '#value' => comment_render($node),
+      '#weight' => 50
+    );
+  }
+
+  return drupal_render_form('jsdoc_object_form', $form);
+}
+
+function _jsdoc_get_title_themed($node) {
+  $themed = _jsdoc_get_object_themed($node);
+  $themed->crumbs = array();
+
+  if ($type = jsdoc_get_type($node)) {
+    $type = jsdoc_object_node_load($type, jsdoc_get_version($node));
+    $themed->type = (object)array(
+      'title' => $type->title,
+      'url' => $type->jsdoc_url
+    );
+    if ($type->jsdoc_url) {
+      $themed->type->a = l($type->title, $type->jsdoc_url);
+    }
+    else {
+      $themed->type->a = $type->title;
+    }
+  }
+
+  $themed->return = (object)array(
+    'types' => array(),
+    'summary' => jsdoc_get_return_summary($node)
+  );
+  foreach (jsdoc_get_return_types($node) as $type) {
+    $themed->return->types[] = _jsdoc_get_type_themed($type->type, $node, false);
+  }
+
+  $parts = explode('.', $node->title);
+  $title_text = "";
+  $end = array_pop($parts);
+  foreach ($parts as $part) {
+    if (!empty($title_text)) {
+      $title_text .= '.';
+    }
+    $title_text .= $part;
+
+    $obj = jsdoc_object_node_load($title_text, jsdoc_get_version($node));
+    if ($obj->nid) {
+      $themed->crumbs[] = l($part, $obj->jsdoc_url);
+    }
+    else {
+      $themed->crumbs[] = $part;
+    }
+  }
+  $themed->crumbs[] = $end;
+
+  drupal_set_breadcrumb($themed->crumbs);
+
+  return $themed;  
+}
+
+function _jsdoc_get_object_themed(&$node, $title=null, $depth=0) {
+  if (is_null($title)) {
+    $title = $node->title;
+  }
+  if (isset($node->jsdoc_object_themed)) {
+    return $node->jsdoc_object_themed;
+  }
+
+  $object = $node->jsdoc_object_themed = (object)array(
+    'title' => $title,
+    'url' => $node->jsdoc_url,
+    'tags' => jsdoc_get_tags($node),
+    'summary' => jsdoc_get_teaser($node),
+    'singleton' => jsdoc_is_initialized($node),
+    'namespace' => jsdoc_is_namespace($node) && !jsdoc_is_classlike($node),
+    'private' => jsdoc_is_private($node),
+    'protected' => jsdoc_is_protected($node),
+    'deprecated' => jsdoc_is_deprecated($node),
+    'private_parent' => jsdoc_has_private_parent($node)
+  );
+
+  if ($object->url) {
+    $object->a = l($node->title, $node->jsdoc_url);
+  }
+  else {
+    $object->a = $object->title;
+  }
+
+  if ($type = jsdoc_get_type($node)) {
+    $optional = false;
+    if (strpos($type, '?') !== false){
+      $optional = true;
+      $type = str_replace('?', '', $type);
+    }
+    $repeating = false;
+    if (strpos($type, '...') !== false){
+      $repeating = true;
+      $type = str_replace('...', '', $type);
+    }
+
+    $type = jsdoc_object_node_load($type, jsdoc_get_version($node));
+
+    $object->type = (object)array(
+      'title' => $type->title,
+      'url' => $type->jsdoc_url,
+      'optional' => $optional,
+      'repeating' => $repeating
+    );
+
+    if ($type->jsdoc_url) {
+      $object->type->a = l($type->title, $type->jsdoc_url);
+    }
+    else {
+      $object->type->a = $type->title;
+    }
+
+    if (jsdoc_is_function($node)) {
+      $parameters = _jsdoc_get_parameters_themed($node, false, $depth);
+      if (!empty($parameters)) {
+        $object->parameters = $parameters;
+      }
+
+      $object->return = (object)array(
+        'types' => array(),
+        'summary' => jsdoc_get_return_summary($node)
+      );
+      foreach (jsdoc_get_return_types($node) as $type) {
+        $object->return->types[] = _jsdoc_get_type_themed($type->type, $node, false);
+      }
+
+      $signature = _jsdoc_build_function_signature($node, $parameters);
+      if (!empty($signature)) {
+        $object->signature = $signature;
+      }
+
+      $source = jsdoc_get_source($node, true, $depth);
+      if (!empty($source)) {
+        $object->source = $source;
+      }
+    }
+  }
+
+  return ($node->jsdoc_object_themed = $object);
+}
+
+function jsdoc_resolve_constructor(&$node) {
+  if ($node->jsdoc_resolved_constructor) {
+    return $node->jsdoc_resolved_constructor;
+  }
+
+  if ($node->jsdoc_constructor) {
+    $constructor = (object)array();
+    _jsdoc_convert_object($constructor, $node->jsdoc_constructor, $node, TRUE);
+    return ($node->jsdoc_resolved_constructor = $constructor);
+  }
+
+  $superclass = jsdoc_get_parent_prototype($node);
+  while ($superclass) {
+    $constructor = (object)array();
+    _jsdoc_convert_object($constructor, $superclass->jsdoc_constructor, $node, TRUE);
+    if ($constructor->jsdoc_parameters) {
+      return ($node->jsdoc_resolved_constructor = $constructor);
+    }
+    $superclass = jsdoc_get_parent_prototype($superclass);
+  }
+
+  return ($node->jsdoc_resolved_constructor = $node->jsdoc_constructor);
+}
+
+function _jsdoc_get_fields($type, &$node) {
+  // I basically want to find the children of this as
+  // if it appeared in the normal API.
+  static $cache = array();
+  $version = jsdoc_get_version($node);
+  if (isset($cache[$version->title][$type])) {
+    return $cache[$version->title][$type];
+  }
+
+  $fields = $cache[$version->title][$type] = array();
+  $obj = jsdoc_object_node_load($type, $version, TRUE, TRUE);
+  // It will have an nid if it's local. For example type: Function isn't local
+  if ($obj && $obj->nid) {
+    list($prototype_chain, $mixin_chain, $children) = jsdoc_get_oo_info($obj);
+
+    foreach ($children as $child) {
+      $title = $child->title;
+
+      $field = (object)array(
+        'title' => $title,
+        'summary' => $child->summary,
+        'types' => false
+      );
+      if (!$cleaned) {
+        $field->url = 'jsdoc/' . $version->title . '/' . $obj->title . '.' . $child->title;
+        $field->a = l($title, $field->url);
+      }
+
+      $field_types = preg_split('%\|+%', jsdoc_get_type($child));
+      foreach ($field_types as $field_type) {
+        $found = 0;
+        $field_type = str_replace('?', '', $field_type, $found);
+        $optional = ($found > 0);
+        $found = 0;
+        $field_type = str_replace('...', '', $field_type, $found);
+        $repeating = ($found > 0);
+
+        $field_obj = jsdoc_object_node_load($field_type, $version);
+        $field_type = (object)array(
+          'title' => $field_obj->title,
+          'repeating' => $repeating,
+          'optional' => $optional,
+          'summary' => jsdoc_get_teaser($field_obj)
+          );
+        if (!$cleaned) {
+          $field_type->url = $field_obj->jsdoc_url;
+          $field_type->a = l($field_obj->title, $field_obj->jsdoc_url);
+        }
+        $field->types[] = $field_type;
+      }
+
+      $fields[$field->title] = $field;
+    }
+
+    if (empty($fields)) {
+      return;
+    }else{
+      uksort($fields, 'strnatcasecmp');
+      return ($cache[$version->title][$type] = $fields);
+    }
+  }
+}
+
+function _jsdoc_get_type_themed($type, $node, $cleaned){
+  $obj = jsdoc_object_node_load($type, jsdoc_get_version($node), TRUE, TRUE);
+  if ($obj) {
+    $type = (object)array(
+      'title' => $obj->title,
+      'summary' => jsdoc_get_teaser($obj),
+      'fields' => false
+    );
+    if (!$cleaned && $obj->jsdoc_url) {
+      $type->url = $obj->jsdoc_url;
+      $type->a = l($obj->title, $obj->jsdoc_url);
+    }
+
+    return $type;
+  }
+}
+
+function _jsdoc_get_parameters_themed(&$node, $cleaned=false) {
+  if (isset($node->jsdoc_parameters_themed)) {
+    return $node->jsdoc_parameters_themed;
+  }
+
+  $parameters = $node->jsdoc_parameters_themed = array();
+  $retrieved_parameters = jsdoc_get_parameters($node);
+
+  foreach ($retrieved_parameters as $item) {
+    $parameter = (object)$item->jsdoc_formatted;
+    $parameter->summary = $item->summary;
+    $parameter->name = $item->name;
+    $parameter->optional = $item->usage == 'optional';
+    $parameter->repeating = $item->usage == 'repeating' || $item->usage == 'one-or-more';
+    $parameter->types = false;
+    if ($cleaned) {
+      unset($parameter->html_type_prefix);
+      unset($parameter->html_type_suffix);
+      unset($parameter->separator);
+    }
+
+    $type = $item->type;
+    $types = array();
+    if (strpos($type, '|') !== false) {
+      $types = preg_split('%\s*\|+\s*%', $type);
+    }
+    elseif ($type) {
+      $types = array($type);
+    }
+
+    foreach ($types as $type) {
+      if ($type = _jsdoc_get_type_themed($type, $node, $cleaned)) {
+        $type->fields = _jsdoc_get_fields($type->title, $node);
+        $parameter->types[] = $type;
+      }
+    }
+
+    if (empty($parameter->types)) {
+      unset($parameter->html_type_prefix);
+      unset($parameter->html_type_suffix);
+      unset($parameter->separator);
+    }
+
+    unset($parameter->type);
+    $parameters[] = $parameter;
+  }
+
+  return ($node->jsdoc_parameters_themed = $parameters);
+}
+
+function _jsdoc_format_type($type, $classlike = false, $optional = false, $repeating = false) {
+  $output = array();
+  $name = '';
+
+  if ($type) {
+    $output['html_type_prefix'] = '/*';
+    $output['html_type_suffix'] = '*/';
+    $output['type'] = $type;
+    if ($type == 'Function' && $classlike) {
+      $output['type'] = 'Constructor';
+    }
+    if ($optional) {
+      $output['type'] .= '?';
+    }
+    if ($repeating) {
+      $output['type'] .= '...';
+    }
+  }
+  if ($type) {
+    $output['separator'] .= ' ';
+  }
+
+  return $output;
+}
+
+function _jsdoc_flatten(&$item, $key) {
+  if (is_object($item)) {
+    $item = $item->title;
+  }
+}
+
+function jsdoc_get_namespace_parents(&$node) {
+  if (isset($node->jsdoc_namespace_parents)) {
+    return $node->jsdoc_namespace_parents;
+  }
+
+  $parents = array();
+
+  $parts = explode('.', $node->title);
+  array_pop($parts);
+  while (count($parts)) {
+    $parents[] = jsdoc_object_node_load(implode('.', $parts), jsdoc_get_version($node));
+    array_pop($parts);
+  }
+
+  return ($node->jsdoc_namespace_parents = $parents);
+}
+
+function jsdoc_get_prototype_chain(&$node) {
+  if (isset($node->jsdoc_prototype_chain)) {
+    return $node->jsdoc_prototype_chain;
+  }
+
+  $chain = array($node);
+
+  $superclass = $node->jsdoc_superclass;
+  while ($superclass) {
+    $superclass = jsdoc_object_node_load($superclass, jsdoc_get_version($node));
+    $chain[] = $superclass;
+    $superclass = $superclass->jsdoc_superclass;
+  }
+
+  $chain[] = jsdoc_object_node_load('Object');
+
+  return ($node->jsdoc_prototype_chain = array_reverse($chain));
+}
+
+function jsdoc_current_node($node=null) {
+  static $current;
+  if (is_null($node)) {
+    return $current;
+  }
+  $current = $node;
+}
+
+function _jsdoc_build_function_signature($node, $parameters) {
+  if (isset($node->jsdoc_function_signature)) {
+    return $node->jsdoc_function_signature;
+  }
+
+  if (jsdoc_get_type($node) != 'Function' && jsdoc_get_type($node) != 'Constructor') {
+    return;
+  }
+
+  $signature = '(';
+
+  if ($parameters) {
+    foreach ($parameters as $weight => $parameter) {
+      if ($weight) {
+        $signature .= ', ';
+      }
+      $types = array();
+      if ($parameter->types) {
+        foreach ($parameter->types as $type) {
+          $types[] = $type->a;
+        }
+      }
+      $signature .= $parameter->html_type_prefix . implode('|', $types);
+      if ($parameter->optional) {
+        $signature .= '?';
+      }
+      if ($parameter->repeating) {
+        $signature .= '...';
+      }
+      $signature .= $parameter->html_type_suffix . $parameter->separator . $parameter->name;
+    }
+  }
+
+  $signature .= ')';
+
+  return ($node->jsdoc_function_signature = $signature);
+}
+
+function _jsdoc_resource_expand($tree, $child, $depth, &$resources){
+  $output = array();
+  foreach ($tree as $leaf) {
+    if ($leaf->depth == $depth && in_array($child, $leaf->children) && !in_array($leaf->vid, $resources)) {
+      $resources[] = $leaf->vid;
+      $output[] = $leaf;
+    }
+  }
+
+  return $output;
+}
+
+function _jsdoc_file_location() {
+  static $location;
+
+  if (!isset($location)) {
+    $location = variable_get('jsdoc_file_location', false);
+  }
+
+  return $location;
+}
+
+function _jsdoc_dir_location() {
+  static $location;
+
+  if (!isset($location)) {
+    $location = variable_get('jsdoc_dir_location', false);
+  }
+
+  return $location;
+}
+
+function _jsdoc_base() {
+  static $base;
+
+  if (!isset($base)) {
+    $base = variable_get('jsdoc_base', 'jsdoc');
+  }
+
+  return $base;
+}
+
+function _jsdoc_build_terms($title) {
+  $output = array($title, array());
+  $parts = explode('.', $title);
+  foreach ($parts as $part) {
+    if (preg_match('%^[_.$]*([a-zA-Z][a-z0-9_.$]*(?:[A-Z][a-z0-9_.$]*)+)%', $part, $match)) {
+      if (preg_match_all('%(^[a-zA-Z][a-z0-9_.$]*|[A-Z][a-z0-9_.$]*)%', $match[1], $cased)) {
+        $output[1] = array_merge($output[1], $cased[0]);
+      }
+    }
+  }
+  $output[1] = implode(' ', $output[1]);
+  $output[2] = implode(' ', $parts);
+  return $output;
+}
+
+function _jsdoc_get_base_path() {
+  static $path;
+
+  if (!isset($path)) {
+    $path = getcwd();
+  }
+
+  return $path;
+}
+
+function _jsdoc_cron_chdir($enter=false) {
+  static $location;
+
+  if ($enter) {
+    $location = _jsdoc_get_base_path();
+    if (!is_dir(_jsdoc_dir_location())){
+        print t('Check Drupal logs for errors');
+        watchdog('jsdoc', _jsdoc_dir_location() . t(' should be a directory'), WATCHDOG_ERROR);
+        return false;
+    }
+    if (!@chdir(_jsdoc_dir_location())) {
+        print t('Check Drupal logs for errors');
+        watchdog('jsdoc', _jsdoc_dir_location() . t(' could not be accessed'), WATCHDOG_ERROR);
+        return false;
+    }
+    include_once(_jsdoc_file_location());
+  }
+  else {
+    chdir($location);
+  }
+}
+
+// Private Utility Functions
+// =========================
+
+function _jsdoc_theme_clone($node) {
+  $clone = drupal_clone($node);
+  foreach ($clone as $key => $value) {
+    if (substr($key, 0, 6) == 'jsdoc_') {
+      unset($clone->$key);
+    }
+  }
+  return $clone;
+}
+
+function _jsdoc_node_prepare($node) {
+  $node->format = variable_get('jsdoc_input_format', 1);
+
+  $form = node_prepare($node)->content;
+  $form['summary']['#weight'] = $form['body']['#weight'] - 1;
+
+  $teaser = jsdoc_get_teaser($node);
+  if (!$node->body || $node->body == t('n/a')) {
+    $node->body = $teaser;
+    $teaser = '';
+  }
+  $body = jsdoc_get_body($node);
+  if ($body == t('n/a')) {
+    $body = '';
+  }
+
+  $form['summary']['#value'] = theme('jsdoc_object_summary', $teaser);
+  $form['description']['#value'] = theme('jsdoc_object_description', $teaser, $body);
+
+  unset($form['body']);
+
+  return $form;
+}
+
+function _jsdoc_get_variables() {
+  static $variables;
+  if (empty($variables)) {
+    if ($variables = cache_get('jsdoc_variables')) {
+      $variables = unserialize($variables->data);
+    }
+    else {
+      $variables = array();
+      $query = db_query("SELECT variable FROM {jsdoc_variables}");
+      while ($variable = db_fetch_object($query)) {
+        if (preg_match('%^(dojo|dijit|dojox)\.%', $variable->variable)) {
+          $variables[$variable->variable] = TRUE;
+        }
+      }
+      cache_set('jsdoc_variables', 'cache', serialize($variables), time() + 86400);
+    }
+  }
+
+  return $variables;
+}
+
+function _jsdoc_markup_code($text, $version, $exclude, $base=false) {
+  $variables = _jsdoc_get_variables();
+
+  $min = 99;
+  $lines = preg_split('%\r?\n%', $text);
+  foreach ($lines as $line) {
+    if (!empty($line)) {
+      if (preg_match('%^\t+%', $line, $match)) {
+        if (strlen($match[0]) < $min) {
+          $min = strlen($match[0]);
+        }
+      }
+    }
+  }
+  if ($min) {
+    foreach ($lines as $i => $line) {
+      $lines[$i] = preg_replace('%^\t{' . $min . '}%', '', $line);
+    }
+  }
+  $text = implode("\n", $lines);
+
+  _jsdoc_init();
+  $language = 'javascript';
+  if (preg_match('%(^\W*<|>\W*$)%', $text)) {
+    $language = 'html4strict';
+  }
+  $highlighter =& new GeSHi($text, $language);
+  $highlighter->enable_classes();
+  $highlighter->enable_keyword_links(false);
+  $highlighter->set_overall_style('color: #666;', true);
+  $highlighter->set_tab_width(4);
+  $highlighter->add_keyword_group(4, '', true, array('Math', 'Error', 'Array'));
+  $text = $highlighter->parse_code();
+  $replaced = array();
+  if (preg_match_all('%[\w.$]+(?:\.(?:<span class="me\d+">)?[\w.$]+(?:</span>)?)+%', $text, $matches)) {
+    natcasesort(array_unique($matches[0]));
+    $matches = array_reverse($matches[0]);
+    foreach ($matches as $i => $match) {
+      $variable = preg_replace('%<[^>]+>%', '', $match);
+      if ($variables && $variables[$variable] && $variable != $exclude) {
+        $replaced[$i] = $match;
+        $text = str_replace($match, "%$i%", $text);
+      }
+    }
+    foreach ($matches as $i => $match) {
+      $variable = preg_replace('%<[^>]+>%', '', $match);
+      if ($variables && $variables[$variable]) {
+        $text = str_replace("%$i%", l($match, 'jsdoc/' . $version->title . '/' . $variable, array('style' => 'border-bottom: 1px dotted #ccc;'), NULL, NULL, FALSE, TRUE), $text);
+      }
+    }
+  }
+  if ($base && preg_match_all('%<span class="kw1">this</span>(\.(?:<span class="me\d+">[\w.$]+</span>)+)%', $text, $matches, PREG_SET_ORDER)) {
+    foreach ($matches as $match) {
+      $variable = $base . preg_replace('%<[^>]+>%', '', $match[1]);
+      if ($variables && $variables[$variable]) {
+        $version = node_load($variables[$variable]);
+        $text = str_replace($match[0], l($match[0], 'jsdoc/' . $version->title . '/' . $variable, array('style' => 'border-bottom: 1px dotted #ccc;'), NULL, NULL, FALSE, TRUE), $text);
+      }
+    }
+  }
+  return $text;
+}
+
+function _jsdoc_markup_text($text, $version, $exclude, $format = false){
+  if (!$format) {
+    $format = variable_get('jsdoc_input_format', 1);
+  }
+
+  $lines = array();
+  $tabbed = FALSE;
+  foreach (explode("\n", $text) as $line) {
+    if ($line{0} == "\t") {
+      if (!$tabbed) {
+        if (empty($lines)) {
+          $lines[] = "";
+        }
+        $lines[] = "";
+      }
+      $tabbed = TRUE;
+    }
+    else {
+      $tabbed = FALSE;
+    }
+    $lines[] = $line;
+  }
+  $text = implode("\n", $lines);
+
+  $tokens = array();
+  if (preg_match_all('%`([^`]+)`%', $text, $matches)) {
+    foreach (array_unique($matches[0]) as $i => $match) {
+      $code = substr($match, 1, -1);
+      $tokens[$i] = "<code>$code</code>";
+      $text = str_replace($match, "!$i!", $text);
+    }
+  }
+
+  $text = check_markup($text, $format, FALSE);
+
+  if (preg_match_all('%(?:\s*(?:<pre>|<code>)\s*)+(.*?)(?:\s*(?:</pre>|</code>)\s*)+%s', $text, $matches, PREG_SET_ORDER)) {
+    foreach ($matches as $match) {
+      $match[1] = str_replace('<', '<', str_replace('>', '>', $match[1]));
+      $text = str_replace($match[0], _jsdoc_markup_code($match[1], $version, $exclude), $text);
+    }
+  }
+
+  foreach ($tokens as $i => $token) {
+    $text = str_replace("!$i!", $token, $text);
+  }
+
+  return $text;
+}
+
+function _jsdoc_init() {
+  include_once(_jsdoc_get_base_path() . '/' . drupal_get_path('module', 'jsdoc') . '/lib/geshi/geshi.php');
+  drupal_add_css(drupal_get_path('module', 'jsdoc') . '/jsdoc.css');
+}
+
+// Theme functions
+// ===============
+
+/**
+ * When an object occurs in more than one file, we want
+ * to show this to the user so that they can choose
+ * the likely location until we disambiguate it.
+ */
+function theme_jsdoc_object_resources($node, $resources) {
+  $output = '<div class="jsdoc_object_resources">';
+  $output .= '<fieldset>';
+  $output .= '<legend>Appears in Resources</legend>';
+  $output .= '<div class="fieldset-wrapper">';
+  foreach ($resources as $resource) {
+    $output .= '<div class="form-item">';
+    $output .= $resource->href;
+    $output .= '</div>';
+  }
+  $output .= '</div>';
+  $output .= '</fieldset>';
+  $output .= '</div>';
+
+  return $output;
+}
+
+/**
+ * Theme the object type block.
+ */
+function theme_jsdoc_object_title($title) {
+  $output = implode('.', $title->crumbs);
+  if ($title->type) {
+    $output .= ': ' . $title->type->a;
+  }
+  return $output;
+}
+
+/**
+ * Theme the statement used to require this file
+ */
+function theme_jsdoc_object_require($require) {
+  return '<div class="form-item"><label>To Include:</label>include "' . $require . '";</div>';
+}
+
+/**
+ * Theme the location this file exists in
+ */
+function theme_jsdoc_object_resource($resource) {
+  return '<div class="form-item"><label>Found in:</label> ' . $resource . '</div>';
+}
+
+/**
+ * Theme the list of mixins for a given object
+ */
+function theme_jsdoc_object_mixins($mixins) {
+  $output = '<div class="form-item"><label>Mixins:</label>';
+  $counter = 0;
+  foreach ($mixins as $mixin) {
+    if ($mixin->in_prototype_chain) {
+      continue;
+    }
+    if ($counter) {
+      $output .= ', ';
+    }
+    if (!$mixin->from == 'normal') {
+      $output .= '[static] ';
+    }
+    $output .= l($mixin->node->title, $mixin->node->jsdoc_url);
+    if ($mixin->mixin_from) {
+      $output .= '<small> (from ' . $mixin->mixin_from . ')</small>';
+    }
+
+    ++$counter;
+  }
+  if(!$counter){ $output .= 'None'; }
+  return $output . '</div>';
+}
+
+function theme_jsdoc_object_children($children) {
+  $output = '<div class="jsdoc_object_children">';
+  $output .= '<fieldset>';
+  $output .= '<legend>Fields</legend>';
+  $output .= '<div class="fieldset-wrapper">';
+
+  foreach ($children as $child) {
+    $output .= '<div class="form-item">';
+    $output .= l($child->title, $child->url);
+    if ($child->type && $key!='Functions' && $key!="Constructors") {
+      $output .= ': <small>' . $child->type->a . '</small> ';
+    }
+    if($child->signature){
+      $output .= $child->signature;
+    }
+    else if($key=="Functions"){
+      $output .= '() ';
+    }
+    if ($child->inheritance) {
+      $output .= ' <div><small>';
+      if ($child->override) {
+        $output .= ' Overrides ';
+      }
+      else {
+        $output .= ' Defined by ';
+      }
+      foreach ($child->inheritance as $i => $parent) {
+        if ($i) {
+          $output .= ', ';
+        }
+        $output .= l($parent->title, $parent->url);
+      }
+      $output .= '</small></div>';
+    }
+    if ($child->summary) {
+      $output .= '<div>' . str_replace("<", "<", str_replace(">", ">", $child->summary)) . '</div>';
+    }
+    $output .= '</div>';
+  }
+  
+  $output .= '</div>';
+  $output .= '</fieldset>';
+  $output .= '</div>';
+
+  return $output;
+}
+
+/**
+ * Theme the prototype chain
+ */
+function theme_jsdoc_object_prototype_chain($chain) {
+  $output = '<div class="form-item"><label>Prototype Chain:</label>' ;
+  foreach ($chain as $i => $node) {
+    if ($i) {
+      $output .= ' » ';
+    }
+    $output .= l($node->title, $node->jsdoc_url);
+  }
+  return $output .= '</div>';
+}
+
+function theme_jsdoc_object_parent($node) {
+  return '<div class="form-item"><label>Parent Object:</label>' . $node->object_type_link . '</div>';
+}
+
+/**
+ *  Theme the function signature and source.
+ *
+ *  One of the things to note is that we pass fields
+ *  because the constructor isn't always listed as the
+ *  constructor because of the famous dojo.declare
+ */
+function theme_jsdoc_function_information($function, $fields, $obj) {
+  $output .= '<div class="jsdoc_function_information">';
+  $output .= '<fieldset class="collapsible">';
+  $output .= '<legend>' . 'Function Information' . '</legend>';
+  $output .= '<div class="fieldset-wrapper">';
+  $output .= '<div class="form-item">';
+  $output .= 'function ' . $function->signature;
+  $output .= '</div>';
+  $output .= '</div>';
+  $output .= '</fieldset>';
+  $output .= '</div>';
+
+  return $output;
+}
+
+function theme_jsdoc_function_parameters($parameters, $node) {
+  $output = '<div class="jsdoc_function_parameters">';
+  $output .= '<fieldset>';
+  $output .= '<legend>' . 'Parameters' . '</legend>';
+  $output .= '<div class="fieldset-wrapper">';
+  foreach ($parameters as $parameter) {
+    $output .= '<div class="form-item"><label>';
+    $types = array();
+    if ($parameter->types) {
+      foreach ($parameter->types as $type) {
+        $types[] = '<em>' . $type->a . '</em>';
+      }
+    }
+    if (count($types)) {
+      $output .= implode('|', $types) . ' ';
+    }
+    $output .= $parameter->name;
+    $output .= '</label>';
+    $output .= $parameter->summary;
+    if (count($types) && $parameter->types[0]->fields) {
+      if ($parameter->summary && $parameter->types[0]->summary) {
+        $output .= '<br><br>';
+      }
+      $output .= $parameter->types[0]->summary;
+      if ($parameter->types[0]->summary) {
+        $output .= '<br>';
+      }
+      foreach ($parameter->types[0]->fields as $i => $field) {
+        $output .= '<br>';
+
+        $field_types = array();
+        $repeating = false;
+        $optional = false;
+        if ($field->types) {
+          foreach ($field->types as $type) {
+            if ($type->repeating) {
+              $repeating = true;
+            }
+            if ($type->optional) {
+              $optional = true;
+            }
+            $field_types[] = '<em>' . $type->a . '</em>';
+          }
+        }
+
+        $output .= '    ';
+        if (count($field_types)) {
+          $output .= implode('|', $field_types) . ' ';
+        }
+        $output .= $field->a;
+        if ($repeating) {
+          $output .= ' <small><em>repeating</em></small>';
+        }
+        if ($optional) {
+          $output .= ' <small><em>optional</em></small>';
+        }
+        if ($field->summary) {
+          $output .= ': ' . $field->summary;
+        }
+      }
+    }
+    $output .= '</div>';
+  }
+  $output .= '</div>';
+  $output .= '</fieldset>';
+  $output .= '</div>';
+
+  return $output;
+}
+
+function theme_jsdoc_object_summary($summary) {
+  return '';
+}
+
+function theme_jsdoc_object_description($summary, $description) {
+  return $summary . $description;
+}
+
+function theme_jsdoc_object_example($example, $weight) {
+  return '<div class="form-item"><label>Example #' . $weight . '</label>' . $example . '</div>';
+}
+
+function theme_jsdoc_object_examples($examples) {
+  $output = '<div class="jsdoc_object_examples">';
+  $output .= '<fieldset>';
+  $output .= '<legend>Examples</legend>';
+  $output .= '<div class="fieldset-wrapper">';
+  $output .= implode('', $examples);
+  $output .= '</div></fieldset></div>';
+  return $output;
+}
+
+function theme_jsdoc_search($name) {
+  return '<div class="form-item"><input class="form-text" name="' . $name . '" /> <input class="form-submit" type="submit" name="op" value="Go" /></div>';
+}
+
+function theme_jsdoc_namespaces($namespaces, $version) {
+  $output = '<ul>';
+  foreach ($namespaces as $namespace) {
+    $output .= "<li>{$namespace->a}";
+    if (!empty($namespace->children)) {
+      $output .= '<ul>';
+      foreach ($namespace->children as $child) {
+        $output .= "<li>{$child->a}</li>";
+      }
+      $output .= '</ul>';
+    }
+    $output .= "</li>";
+  }
+  $output .= '</ul>';
+  return $output;
+}
+
+function theme_jsdoc_resource_source_link($project, $resource) {
+  return $resource;
+}
+
+function theme_jsdoc_resolve_constructor($objects) {
+}
+
+function theme_jsdoc_ide($content){
+  return theme('page', $content);
+}
\ No newline at end of file
diff --git a/util/jsdoc/lib/EXTERNALS b/util/jsdoc/lib/EXTERNALS
new file mode 100644
index 0000000..99383c7
--- /dev/null
+++ b/util/jsdoc/lib/EXTERNALS
@@ -0,0 +1,2 @@
+Get the GeSHi package from: http://qbnz.com/highlighter/ and place in the directory.
+It should be placed so that geshi.php is in lib/geshi/geshi.php
\ No newline at end of file
diff --git a/util/jsdoc/template.php b/util/jsdoc/template.php
new file mode 100644
index 0000000..1d561b9
--- /dev/null
+++ b/util/jsdoc/template.php
@@ -0,0 +1,16 @@
+<?php
+
+// Use this theme function to do a final manipulation of the form
+
+function phptemplate_jsdoc_object_form($form) {
+}
+
+function phptemplate_jsdoc_object_form($form) {
+}
+
+// Use these functions to create the equivalent tpl.php files
+
+// function theme_jsdoc_object_children($children) {
+function phptemplate_jsdoc_object_children($children) {
+  return _phptemplate_callback('jsdoc_object_children', array('children' => $children));
+}
\ No newline at end of file
diff --git a/util/migration/dijitCss14to15.sed b/util/migration/dijitCss14to15.sed
new file mode 100644
index 0000000..92eaf67
--- /dev/null
+++ b/util/migration/dijitCss14to15.sed
@@ -0,0 +1,67 @@
+#!/bin/sed -f
+
+# Sed script for migration of custom CSS files against dijit 1.4 to run against dijit 1.5
+# Usage:
+#   $ for file in $(find . -name '*.css' -print)
+# do
+#   sed -f dijitCss14to15.sed -i .bak $file
+# done
+
+# Spinner
+s/.dijitSpinnerUpArrowHover .dijitUpArrowButton/.dijitSpinner .dijitUpArrowButtonHover/
+s/.dijitSpinnerUpArrowActive .dijitUpArrowButton/.dijitSpinner .dijitUpArrowButtonActive/
+s/.dijitSpinnerDownArrowHover .dijitDownArrowButton/.dijitSpinner .dijitDownArrowButtonHover/
+s/.dijitSpinnerDownArrowActive .dijitDownArrowButton/.dijitSpinner .dijitDownArrowButtonActive/
+
+# ComboButton
+s/.dijitComboButtonHover .dijitButtonContents/.dijitComboButton .dijitButtonContentsHover/
+s/.dijitComboButtonActive .dijitButtonContents/.dijitComboButton .dijitButtonContentsActive/
+s/.dijitComboButtonDownArrowHover .dijitArrowButton/.dijitComboButton .dijitDownArrowButtonHover/
+s/.dijitComboButtonDownArrowActive .dijitArrowButton/.dijitComboButton .dijitDownArrowButtonActive/
+s/.dijitComboButtonDownArrowHover .dijitDownArrowButton/.dijitComboButton .dijitDownArrowButtonHover/
+s/.dijitComboButtonDownArrowActive .dijitDownArrowButton/.dijitComboButton .dijitDownArrowButtonActive/
+
+# Accordion
+s/.dijitAccordionFocused/.dijitAccordionTitleFocused/
+s/.dijitAccordionTitle-hover/.dijitAccordionTitleHover/
+s/.dijitAccordionTitle-selected/.dijitAccordionTitleSelected/
+
+# TabContainer
+s/.dijitTabBtnDisabled/.dijitTabDisabled/
+
+# TabContainer tab close button
+s/.dijitTab .closeButton/.dijitTabCloseButton/
+s/.dijitTabCloseButton-hover/.dijitTabCloseButtonHover/
+s/.dijitTabCloseButtonHover .closeImage/.dijitTabCloseButtonHover/
+s/.dijitTab .closeImage/.dijitTabCloseButton/
+s/.dijitTab .closeText/.dijitTabCloseText/
+s/.dijitTabCloseButtonHover .dijitClosable .closeImage/.dijitTabCloseButtonHover/
+s/.dijitTab .dijitClosable .closeImage/.dijitTabCloseButton/
+s/.dijitTab .dijitClosable .closeText/.dijitTabCloseText/
+
+# TabContainer: left/right/menu buttons
+s/.tabStripButton img/.dijitTabStripIcon/
+s/.tabStripMenuButton img/.dijitTabStripMenuIcon/
+s/.tabStripSlideButtonLeft img/.dijitTabStripSlideLeftIcon/
+s/.tabStripSlideButtonRight img/.dijitTabStripSlideRightIcon/
+s/.tabStripButton IMG/.dijitTabStripIcon/
+s/.tabStripMenuButton IMG/.dijitTabStripMenuIcon/
+s/.tabStripSlideButtonLeft IMG/.dijitTabStripSlideLeftIcon/
+s/.tabStripSlideButtonRight IMG/.dijitTabStripSlideRightIcon/
+
+# Dialog
+s/.dijitDialogCloseIcon-hover/.dijitDialogCloseIconHover/
+
+# Tree
+s/.dijitTreeNodeHover/.dijitTreeRowHover/
+s/.dijitTreeNodeSelected/.dijitTreeRowSelected/
+
+# TitlePane
+s/.dijitTitlePaneTitle-hover/.dijitTitlePaneTitleHover/
+
+# InlineEditBox
+s/.dijitInlineEditBoxDisplayMode-hover/.dijitInlineEditBoxDisplayModeHover/
+s/.dijitInlineEditBoxDisplayMode-disabled/.dijitInlineEditBoxDisplayModeDisabled/
+
+# Editor
+s/.RichTextEditable/.dijitEditor/
\ No newline at end of file
diff --git a/util/shrinksafe/LICENSE b/util/shrinksafe/LICENSE
new file mode 100644
index 0000000..045e3aa
--- /dev/null
+++ b/util/shrinksafe/LICENSE
@@ -0,0 +1,6 @@
+Mozilla Rhino (js.jar from http://www.mozilla.org/rhino/) was
+initially developed by Netscape Communications Corporation and is
+provided by the Dojo Foundation "as is" under the MPL 1.1 license,
+available at http://www.mozilla.org/MPL
+
+shrinksafe.jar is based on work in Rhino and is also provided under the MPL 1.1 license.
\ No newline at end of file
diff --git a/util/shrinksafe/MPL-1.1.html b/util/shrinksafe/MPL-1.1.html
new file mode 100644
index 0000000..ebcc169
--- /dev/null
+++ b/util/shrinksafe/MPL-1.1.html
@@ -0,0 +1,389 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+<head>
+ <title>Mozilla Public License version 1.1</title>
+ <style type="text/css">
+  .very-strong{
+   text-transform:uppercase;
+  }
+  dt{
+   font-weight:bold;
+  }
+  dd p{
+   margin:0;
+  }
+ </style>
+</head>
+<body>
+ <p><small>(<a href="MPL-1.1.txt">Plain text version</a>)</p>
+ <h1>Mozilla Public License Version 1.1</h1>
+ <h2 id="section-1">1. Definitions.</h2>
+ <dl>
+  <dt id="section-1.0.1">1.0.1. "Commercial Use"
+  <dd>means distribution or otherwise making the Covered Code available to a third party.
+  <dt id="section-1.1">1.1. "Contributor"
+  <dd>means each entity that creates or contributes to the creation of Modifications.
+  <dt id="section-1.2">1.2. "Contributor Version"
+  <dd>means the combination of the Original Code, prior Modifications used by a Contributor,
+   and the Modifications made by that particular Contributor.
+  <dt id="section-1.3">1.3. "Covered Code"
+  <dd>means the Original Code or Modifications or the combination of the Original Code and
+   Modifications, in each case including portions thereof.
+  <dt id="section-1.4">1.4. "Electronic Distribution Mechanism"
+  <dd>means a mechanism generally accepted in the software development community for the
+   electronic transfer of data.
+  <dt id="section-1.5">1.5. "Executable"
+  <dd>means Covered Code in any form other than Source Code.
+  <dt id="section-1.6">1.6. "Initial Developer"
+  <dd>means the individual or entity identified as the Initial Developer in the Source Code
+   notice required by <a href="#exhibit-a">Exhibit A</a>.
+  <dt id="section-1.7">1.7. "Larger Work"
+  <dd>means a work which combines Covered Code or portions thereof with code not governed
+   by the terms of this License.
+  <dt id="section-1.8">1.8. "License"
+  <dd>means this document.
+  <dt id="section-1.8.1">1.8.1. "Licensable"
+  <dd>means having the right to grant, to the maximum extent possible, whether at the
+   time of the initial grant or subsequently acquired, any and all of the rights
+   conveyed herein.
+  <dt id="section-1.9">1.9. "Modifications"
+  <dd>
+   <p>means any addition to or deletion from the substance or structure of either the
+    Original Code or any previous Modifications. When Covered Code is released as a
+    series of files, a Modification is:
+   <ol type="a">
+    <li id="section-1.9-a">Any addition to or deletion from the contents of a file
+     containing Original Code or previous Modifications.
+    <li id="section-1.9-b">Any new file that contains any part of the Original Code or
+     previous Modifications.
+   </ol>
+  <dt id="section-1.10">1.10. "Original Code"
+  <dd>means Source Code of computer software code which is described in the Source Code
+   notice required by <a href="#exhibit-a">Exhibit A</a> as Original Code, and which,
+   at the time of its release under this License is not already Covered Code governed
+   by this License.
+  <dt id="section-1.10.1">1.10.1. "Patent Claims"
+  <dd>means any patent claim(s), now owned or hereafter acquired, including without
+   limitation, method, process, and apparatus claims, in any patent Licensable by
+   grantor.
+  <dt id="section-1.11">1.11. "Source Code"
+  <dd>means the preferred form of the Covered Code for making modifications to it,
+   including all modules it contains, plus any associated interface definition files,
+   scripts used to control compilation and installation of an Executable, or source
+   code differential comparisons against either the Original Code or another well known,
+   available Covered Code of the Contributor's choice. The Source Code can be in a
+   compressed or archival form, provided the appropriate decompression or de-archiving
+   software is widely available for no charge.
+  <dt id="section-1.12">1.12. "You" (or "Your")
+  <dd>means an individual or a legal entity exercising rights under, and complying with
+   all of the terms of, this License or a future version of this License issued under
+   <a href="#section-6.1">Section 6.1.</a> For legal entities, "You" includes any entity
+   which controls, is controlled by, or is under common control with You. For purposes of
+   this definition, "control" means (a) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or otherwise, or (b)
+   ownership of more than fifty percent (50%) of the outstanding shares or beneficial
+   ownership of such entity.
+ </dl>
+ <h2 id="section-2">2. Source Code License.</h2>
+ <h3 id="section-2.1">2.1. The Initial Developer Grant.</h3>
+ <p>The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive
+  license, subject to third party intellectual property claims:
+ <ol type="a">
+  <li id="section-2.1-a">under intellectual property rights (other than patent or
+   trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform,
+   sublicense and distribute the Original Code (or portions thereof) with or without
+   Modifications, and/or as part of a Larger Work; and
+  <li id="section-2.1-b">under Patents Claims infringed by the making, using or selling
+   of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or
+   otherwise dispose of the Original Code (or portions thereof).
+  <li id="section-2.1-c">the licenses granted in this Section 2.1
+   (<a href="#section-2.1-a">a</a>) and (<a href="#section-2.1-b">b</a>) are effective on
+   the date Initial Developer first distributes Original Code under the terms of this
+   License.
+  <li id="section-2.1-d">Notwithstanding Section 2.1 (<a href="#section-2.1-b">b</a>)
+   above, no patent license is granted: 1) for code that You delete from the Original Code;
+   2) separate from the Original Code; or 3) for infringements caused by: i) the
+   modification of the Original Code or ii) the combination of the Original Code with other
+   software or devices.
+ </ol>
+ <h3 id="section-2.2">2.2. Contributor Grant.</h3>
+ <p>Subject to third party intellectual property claims, each Contributor hereby grants You
+  a world-wide, royalty-free, non-exclusive license
+ <ol type="a">
+  <li id="section-2.2-a">under intellectual property rights (other than patent or trademark)
+   Licensable by Contributor, to use, reproduce, modify, display, perform, sublicense and
+   distribute the Modifications created by such Contributor (or portions thereof) either on
+   an unmodified basis, with other Modifications, as Covered Code and/or as part of a Larger
+   Work; and
+  <li id="section-2.2-b">under Patent Claims infringed by the making, using, or selling of
+   Modifications made by that Contributor either alone and/or in combination with its
+   Contributor Version (or portions of such combination), to make, use, sell, offer for
+   sale, have made, and/or otherwise dispose of: 1) Modifications made by that Contributor
+   (or portions thereof); and 2) the combination of Modifications made by that Contributor
+   with its Contributor Version (or portions of such combination).
+  <li id="section-2.2-c">the licenses granted in Sections 2.2
+   (<a href="#section-2.2-a">a</a>) and 2.2 (<a href="#section-2.2-b">b</a>) are effective
+   on the date Contributor first makes Commercial Use of the Covered Code.
+  <li id="section-2.2-d">Notwithstanding Section 2.2 (<a href="#section-2.2-b">b</a>)
+   above, no patent license is granted: 1) for any code that Contributor has deleted from
+   the Contributor Version; 2) separate from the Contributor Version; 3) for infringements
+   caused by: i) third party modifications of Contributor Version or ii) the combination of
+   Modifications made by that Contributor with other software (except as part of the
+   Contributor Version) or other devices; or 4) under Patent Claims infringed by Covered Code
+   in the absence of Modifications made by that Contributor.
+ </ol>
+ <h2 id="section-3">3. Distribution Obligations.</h2>
+ <h3 id="section-3.1">3.1. Application of License.</h3>
+ <p>The Modifications which You create or to which You contribute are governed by the terms
+  of this License, including without limitation Section <a href="#section-2.2">2.2</a>. The
+  Source Code version of Covered Code may be distributed only under the terms of this License
+  or a future version of this License released under Section <a href="#section-6.1">6.1</a>,
+  and You must include a copy of this License with every copy of the Source Code You
+  distribute. You may not offer or impose any terms on any Source Code version that alters or
+  restricts the applicable version of this License or the recipients' rights hereunder.
+  However, You may include an additional document offering the additional rights described in
+  Section <a href="#section-3.5">3.5</a>.
+ <h3 id="section-3.2">3.2. Availability of Source Code.</h3>
+ <p>Any Modification which You create or to which You contribute must be made available in
+  Source Code form under the terms of this License either on the same media as an Executable
+  version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an
+  Executable version available; and if made available via Electronic Distribution Mechanism,
+  must remain available for at least twelve (12) months after the date it initially became
+  available, or at least six (6) months after a subsequent version of that particular
+  Modification has been made available to such recipients. You are responsible for ensuring
+  that the Source Code version remains available even if the Electronic Distribution
+  Mechanism is maintained by a third party.
+ <h3 id="section-3.3">3.3. Description of Modifications.</h3>
+ <p>You must cause all Covered Code to which You contribute to contain a file documenting the
+  changes You made to create that Covered Code and the date of any change. You must include a
+  prominent statement that the Modification is derived, directly or indirectly, from Original
+  Code provided by the Initial Developer and including the name of the Initial Developer in
+  (a) the Source Code, and (b) in any notice in an Executable version or related documentation
+  in which You describe the origin or ownership of the Covered Code.
+ <h3 id="section-3.4">3.4. Intellectual Property Matters</h3>
+ <h4 id="section-3.4-a">(a) Third Party Claims</h4>
+ <p>If Contributor has knowledge that a license under a third party's intellectual property
+  rights is required to exercise the rights granted by such Contributor under Sections
+  <a href="#section-2.1">2.1</a> or <a href="#section-2.2">2.2</a>, Contributor must include a
+  text file with the Source Code distribution titled "LEGAL" which describes the claim and the
+  party making the claim in sufficient detail that a recipient will know whom to contact. If
+  Contributor obtains such knowledge after the Modification is made available as described in
+  Section <a href="#section-3.2">3.2</a>, Contributor shall promptly modify the LEGAL file in
+  all copies Contributor makes available thereafter and shall take other steps (such as
+  notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who
+  received the Covered Code that new knowledge has been obtained.
+ <h4 id="section-3.4-b">(b) Contributor APIs</h4>
+ <p>If Contributor's Modifications include an application programming interface and Contributor
+  has knowledge of patent licenses which are reasonably necessary to implement that
+  <abbr>API</abbr>, Contributor must also include this information in the
+  <strong class="very-strong">legal</strong> file.
+ <h4 id="section-3.4-c">(c) Representations.</h4>
+ <p>Contributor represents that, except as disclosed pursuant to Section 3.4
+  (<a href="#section-3.4-a">a</a>) above, Contributor believes that Contributor's Modifications
+  are Contributor's original creation(s) and/or Contributor has sufficient rights to grant the
+  rights conveyed by this License.
+ <h3 id="section-3.5">3.5. Required Notices.</h3>
+ <p>You must duplicate the notice in <a href="#exhibit-a">Exhibit A</a> in each file of the
+  Source Code. If it is not possible to put such notice in a particular Source Code file due to
+  its structure, then You must include such notice in a location (such as a relevant directory)
+  where a user would be likely to look for such a notice. If You created one or more
+  Modification(s) You may add your name as a Contributor to the notice described in
+  <a href="#exhibit-a">Exhibit A</a>. You must also duplicate this License in any documentation
+  for the Source Code where You describe recipients' rights or ownership rights relating to
+  Covered Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity
+  or liability obligations to one or more recipients of Covered Code. However, You may do so
+  only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You
+  must make it absolutely clear than any such warranty, support, indemnity or liability
+  obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer
+  and every Contributor for any liability incurred by the Initial Developer or such Contributor
+  as a result of warranty, support, indemnity or liability terms You offer.
+ <h3 id="section-3.6">3.6. Distribution of Executable Versions.</h3>
+ <p>You may distribute Covered Code in Executable form only if the requirements of Sections
+  <a href="#section-3.1">3.1</a>, <a href="#section-3.2">3.2</a>,
+  <a href="#section-3.3">3.3</a>, <a href="#section-3.4">3.4</a> and
+  <a href="#section-3.5">3.5</a> have been met for that Covered Code, and if You include a
+  notice stating that the Source Code version of the Covered Code is available under the terms
+  of this License, including a description of how and where You have fulfilled the obligations
+  of Section <a href="#section-3.2">3.2</a>. The notice must be conspicuously included in any
+  notice in an Executable version, related documentation or collateral in which You describe
+  recipients' rights relating to the Covered Code. You may distribute the Executable version of
+  Covered Code or ownership rights under a license of Your choice, which may contain terms
+  different from this License, provided that You are in compliance with the terms of this
+  License and that the license for the Executable version does not attempt to limit or alter the
+  recipient's rights in the Source Code version from the rights set forth in this License. If
+  You distribute the Executable version under a different license You must make it absolutely
+  clear that any terms which differ from this License are offered by You alone, not by the
+  Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and
+  every Contributor for any liability incurred by the Initial Developer or such Contributor as
+  a result of any such terms You offer.
+ <h3 id="section-3.7">3.7. Larger Works.</h3>
+ <p>You may create a Larger Work by combining Covered Code with other code not governed by the
+  terms of this License and distribute the Larger Work as a single product. In such a case,
+  You must make sure the requirements of this License are fulfilled for the Covered Code.
+ <h2 id="section-4">4. Inability to Comply Due to Statute or Regulation.</h2>
+ <p>If it is impossible for You to comply with any of the terms of this License with respect to
+  some or all of the Covered Code due to statute, judicial order, or regulation then You must:
+  (a) comply with the terms of this License to the maximum extent possible; and (b) describe
+  the limitations and the code they affect. Such description must be included in the
+  <strong class="very-strong">legal</strong> file described in Section
+  <a href="#section-3.4">3.4</a> and must be included with all distributions of the Source Code.
+  Except to the extent prohibited by statute or regulation, such description must be
+  sufficiently detailed for a recipient of ordinary skill to be able to understand it.
+ <h2 id="section-5">5. Application of this License.</h2>
+ <p>This License applies to code to which the Initial Developer has attached the notice in
+  <a href="#exhibit-a">Exhibit A</a> and to related Covered Code.
+ <h2 id="section-6">6. Versions of the License.</h2>
+ <h3 id="section-6.1">6.1. New Versions</h3>
+ <p>Netscape Communications Corporation ("Netscape") may publish revised and/or new versions
+  of the License from time to time. Each version will be given a distinguishing version number.
+ <h3 id="section-6.2">6.2. Effect of New Versions</h3>
+ <p>Once Covered Code has been published under a particular version of the License, You may
+  always continue to use it under the terms of that version. You may also choose to use such
+  Covered Code under the terms of any subsequent version of the License published by Netscape.
+  No one other than Netscape has the right to modify the terms applicable to Covered Code
+  created under this License.
+ <h3 id="section-6.3">6.3. Derivative Works</h3>
+ <p>If You create or use a modified version of this License (which you may only do in order to
+ apply it to code which is not already Covered Code governed by this License), You must (a)
+ rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "MPL",
+ "NPL" or any confusingly similar phrase do not appear in your license (except to note that
+ your license differs from this License) and (b) otherwise make it clear that Your version of
+ the license contains terms which differ from the Mozilla Public License and Netscape Public
+ License. (Filling in the name of the Initial Developer, Original Code or Contributor in the
+ notice described in <a href="#exhibit-a">Exhibit A</a> shall not of themselves be deemed to
+ be modifications of this License.)
+ <h2 id="section-7">7. <strong class="very-strong">Disclaimer of warranty</strong></h2>
+ <p><strong class="very-strong">Covered code is provided under this license on an "as is"
+  basis, without warranty of any kind, either expressed or implied, including, without
+  limitation, warranties that the covered code is free of defects, merchantable, fit for a
+  particular purpose or non-infringing. The entire risk as to the quality and performance of
+  the covered code is with you. Should any covered code prove defective in any respect, you
+  (not the initial developer or any other contributor) assume the cost of any necessary
+  servicing, repair or correction. This disclaimer of warranty constitutes an essential part
+  of this license. No use of any covered code is authorized hereunder except under this
+  disclaimer.</strong>
+ <h2 id="section-8">8. Termination</h2>
+ <p id="section-8.1">8.1. This License and the rights granted hereunder will terminate
+  automatically if You fail to comply with terms herein and fail to cure such breach
+  within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which
+  are properly granted shall survive any termination of this License. Provisions which, by
+  their nature, must remain in effect beyond the termination of this License shall survive.
+ <p id="section-8.2">8.2. If You initiate litigation by asserting a patent infringement
+  claim (excluding declatory judgment actions) against Initial Developer or a Contributor
+  (the Initial Developer or Contributor against whom You file such action is referred to
+  as "Participant") alleging that:
+ <ol type="a">
+  <li id="section-8.2-a">such Participant's Contributor Version directly or indirectly
+   infringes any patent, then any and all rights granted by such Participant to You under
+   Sections <a href="#section-2.1">2.1</a> and/or <a href="#section-2.2">2.2</a> of this
+   License shall, upon 60 days notice from Participant terminate prospectively, unless if
+   within 60 days after receipt of notice You either: (i) agree in writing to pay
+   Participant a mutually agreeable reasonable royalty for Your past and future use of
+   Modifications made by such Participant, or (ii) withdraw Your litigation claim with
+   respect to the Contributor Version against such Participant. If within 60 days of
+   notice, a reasonable royalty and payment arrangement are not mutually agreed upon in
+   writing by the parties or the litigation claim is not withdrawn, the rights granted by
+   Participant to You under Sections <a href="#section-2.1">2.1</a> and/or
+   <a href="#section-2.2">2.2</a> automatically terminate at the expiration of the 60 day
+   notice period specified above.
+  <li id="section-8.2-b">any software, hardware, or device, other than such Participant's
+   Contributor Version, directly or indirectly infringes any patent, then any rights
+   granted to You by such Participant under Sections 2.1(<a href="#section-2.1-b">b</a>)
+   and 2.2(<a href="#section-2.2-b">b</a>) are revoked effective as of the date You first
+   made, used, sold, distributed, or had made, Modifications made by that Participant.
+ </ol>
+ <p id="section-8.3">8.3. If You assert a patent infringement claim against Participant
+  alleging that such Participant's Contributor Version directly or indirectly infringes
+  any patent where such claim is resolved (such as by license or settlement) prior to the
+  initiation of patent infringement litigation, then the reasonable value of the licenses
+  granted by such Participant under Sections <a href="#section-2.1">2.1</a> or
+  <a href="#section-2.2">2.2</a> shall be taken into account in determining the amount or
+  value of any payment or license.
+ <p id="section-8.4">8.4. In the event of termination under Sections
+  <a href="#section-8.1">8.1</a> or <a href="#section-8.2">8.2</a> above, all end user
+  license agreements (excluding distributors and resellers) which have been validly
+  granted by You or any distributor hereunder prior to termination shall survive
+  termination.
+ <h2 id="section-9">9. <strong class="very-strong">Limitation of liability</strong></h2>
+ <p><strong class="very-strong">Under no circumstances and under no legal theory, whether
+  tort (including negligence), contract, or otherwise, shall you, the initial developer,
+  any other contributor, or any distributor of covered code, or any supplier of any of
+  such parties, be liable to any person for any indirect, special, incidental, or
+  consequential damages of any character including, without limitation, damages for loss
+  of goodwill, work stoppage, computer failure or malfunction, or any and all other
+  commercial damages or losses, even if such party shall have been informed of the
+  possibility of such damages. This limitation of liability shall not apply to liability
+  for death or personal injury resulting from such party's negligence to the extent
+  applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion
+  or limitation of incidental or consequential damages, so this exclusion and limitation
+  may not apply to you.</strong>
+ <h2 id="section-10">10. <abbr title="United States">U.S.</abbr> government end users</h2>
+ <p>The Covered Code is a "commercial item," as that term is defined in 48
+  <abbr>C.F.R.</abbr> 2.101 (<abbr title="October">Oct.</abbr> 1995), consisting of
+  "commercial computer software" and "commercial computer software documentation," as such
+  terms are used in 48 <abbr>C.F.R.</abbr> 12.212 (<abbr title="September">Sept.</abbr>
+  1995). Consistent with 48 <abbr>C.F.R.</abbr> 12.212 and 48 <abbr>C.F.R.</abbr>
+  227.7202-1 through 227.7202-4 (June 1995), all <abbr>U.S.</abbr> Government End Users
+  acquire Covered Code with only those rights set forth herein.
+ <h2 id="section-11">11. Miscellaneous</h2>
+ <p>This License represents the complete agreement concerning subject matter hereof. If
+  any provision of this License is held to be unenforceable, such provision shall be
+  reformed only to the extent necessary to make it enforceable. This License shall be
+  governed by California law provisions (except to the extent applicable law, if any,
+  provides otherwise), excluding its conflict-of-law provisions. With respect to
+  disputes in which at least one party is a citizen of, or an entity chartered or
+  registered to do business in the United States of America, any litigation relating to
+  this License shall be subject to the jurisdiction of the Federal Courts of the
+  Northern District of California, with venue lying in Santa Clara County, California,
+  with the losing party responsible for costs, including without limitation, court
+  costs and reasonable attorneys' fees and expenses. The application of the United
+  Nations Convention on Contracts for the International Sale of Goods is expressly
+  excluded. Any law or regulation which provides that the language of a contract
+  shall be construed against the drafter shall not apply to this License.
+ <h2 id="section-12">12. Responsibility for claims</h2>
+ <p>As between Initial Developer and the Contributors, each party is responsible for
+  claims and damages arising, directly or indirectly, out of its utilization of rights
+  under this License and You agree to work with Initial Developer and Contributors to
+  distribute such responsibility on an equitable basis. Nothing herein is intended or
+  shall be deemed to constitute any admission of liability.
+ <h2 id="section-13">13. Multiple-licensed code</h2>
+ <p>Initial Developer may designate portions of the Covered Code as
+  "Multiple-Licensed". "Multiple-Licensed" means that the Initial Developer permits
+  you to utilize portions of the Covered Code under Your choice of the <abbr>MPL</abbr>
+  or the alternative licenses, if any, specified by the Initial Developer in the file
+  described in <a href="#exhibit-a">Exhibit A</a>.
+ <h2 id="exhibit-a">Exhibit A - Mozilla Public License.</h2>
+ <pre>"The contents of this file are subject to the Mozilla Public License
+Version 1.1 (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.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+License for the specific language governing rights and limitations
+under the License.
+
+The Original Code is ______________________________________.
+
+The Initial Developer of the Original Code is ________________________.
+Portions created by ______________________ are Copyright (C) ______
+_______________________. All Rights Reserved.
+
+Contributor(s): ______________________________________.
+
+Alternatively, the contents of this file may be used under the terms
+of the _____ license (the  "[___] License"), in which case the
+provisions of [______] License are applicable instead of those
+above. If you wish to allow use of your version of this file only
+under the terms of the [____] License and not to allow others to use
+your version of this file under the MPL, indicate your decision by
+deleting the provisions above and replace them with the notice and
+other provisions required by the [___] License. If you do not delete
+the provisions above, a recipient may use your version of this file
+under either the MPL or the [___] License."</pre>
+ <p>NOTE: The text of this Exhibit A may differ slightly from the text of
+  the notices in the Source Code files of the Original Code. You should
+  use the text of this Exhibit A rather than the text found in the
+  Original Code Source Code for Your Modifications.
+</body>
+</html>
diff --git a/util/shrinksafe/README b/util/shrinksafe/README
new file mode 100644
index 0000000..c03dc7b
--- /dev/null
+++ b/util/shrinksafe/README
@@ -0,0 +1,16 @@
+shrinksafe.jar requires js.jar (Rhino) in the same directory.
+
+Usage:
+
+java -jar shrinksafe.jar somescript.js > minifiedscript.js
+
+There is a build-time version dependency between shrinksafe.jar and js.jar.
+Shrinksafe must be built and used with a particular version of Rhino.  To build,
+run build.sh in this directory.  Mozilla Rhino is licensed under MPL
+1.1 (see LICENSE) and is available from http://www.mozilla.org/rhino.
+
+shrinksafe.jar is known to work with these Rhino versions:
+- 1.7R1
+
+This version of ShrinkSafe will be incompatible with Rhino 1.7R3 and beyond
+due to changes in the Rhino API.
diff --git a/util/shrinksafe/build.sh b/util/shrinksafe/build.sh
new file mode 100755
index 0000000..d379478
--- /dev/null
+++ b/util/shrinksafe/build.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+RHINO=../js.jar
+TEST=$1
+
+# create shrinksafe.jar from src/
+rm -rf bin
+mkdir bin
+cd src
+javac -classpath $RHINO:. -d ../bin org/dojotoolkit/shrinksafe/Main.java
+mkdir ../bin/org/dojotoolkit/shrinksafe/resources
+cp org/dojotoolkit/shrinksafe/resources/Messages.properties ../bin/org/dojotoolkit/shrinksafe/resources/Messages.properties
+cd ../bin
+jar cfm ../shrinksafe.jar ../src/manifest *
+cd ..
+rm -rf bin
+
+# call build.sh test to run the unit tests immediately
+if [ "$TEST" == "test" ]; then
+	echo "Running tests."
+	cd tests
+	./runner.sh  #| grep errors -1
+fi
+
diff --git a/util/shrinksafe/js.jar b/util/shrinksafe/js.jar
new file mode 100644
index 0000000..c081d16
Binary files /dev/null and b/util/shrinksafe/js.jar differ
diff --git a/util/shrinksafe/shrinksafe.jar b/util/shrinksafe/shrinksafe.jar
new file mode 100644
index 0000000..53c37f9
Binary files /dev/null and b/util/shrinksafe/shrinksafe.jar differ
diff --git a/util/shrinksafe/src/manifest b/util/shrinksafe/src/manifest
new file mode 100644
index 0000000..85b8ea3
--- /dev/null
+++ b/util/shrinksafe/src/manifest
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: org.dojotoolkit.shrinksafe.Main
+Class-Path: js.jar
diff --git a/util/shrinksafe/src/org/dojotoolkit/shrinksafe/Compressor.java b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/Compressor.java
new file mode 100644
index 0000000..4288d64
--- /dev/null
+++ b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/Compressor.java
@@ -0,0 +1,1017 @@
+/*
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alex Russell
+ *   Richard Backhouse
+ */
+
+ package org.dojotoolkit.shrinksafe;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.mozilla.javascript.CompilerEnvirons;
+import org.mozilla.javascript.Decompiler;
+import org.mozilla.javascript.FunctionNode;
+import org.mozilla.javascript.Interpreter;
+import org.mozilla.javascript.Kit;
+import org.mozilla.javascript.Parser;
+import org.mozilla.javascript.ScriptOrFnNode;
+import org.mozilla.javascript.ScriptRuntime;
+import org.mozilla.javascript.Token;
+import org.mozilla.javascript.UintMap;
+
+/**
+ * @author rbackhouse
+ *
+ */
+public class Compressor {
+    private static final int FUNCTION_END = Token.LAST_TOKEN + 1;
+    
+    /**
+     * Compress the script
+     * <p>
+     * 
+     * @param encodedSource encoded source string
+     * @param flags Flags specifying format of decompilation output
+     * @param properties Decompilation properties
+     * @param parseTree Mapping for each function node and corresponding parameters & variables names
+     * @return compressed script
+     */
+    private static String compress(String encodedSource, 
+    		                       int flags, 
+    		                       UintMap properties, 
+    		                       ScriptOrFnNode parseTree, 
+    		                       boolean escapeUnicode,
+    		                       String stripConsole,
+    		                       TokenMapper tm,
+    		                       Map replacedTokensLookup){
+         int indent = properties.getInt(Decompiler.INITIAL_INDENT_PROP, 0);
+         if (indent < 0) throw new IllegalArgumentException();
+         int indentGap = properties.getInt(Decompiler.INDENT_GAP_PROP, 4);
+         if (indentGap < 0) throw new IllegalArgumentException();
+         int caseGap = properties.getInt(Decompiler.CASE_GAP_PROP, 2);
+         if (caseGap < 0) throw new IllegalArgumentException();
+
+         String stripConsoleRegex = "assert|count|debug|dir|dirxml|group|groupEnd|info|profile|profileEnd|time|timeEnd|trace|log";
+         if (stripConsole == null) {
+        	 // may be null if unspecified on Main cmd line
+        	 stripConsoleRegex = null;
+         } else if (stripConsole.equals("normal")) {
+        	 // leave default
+         } else if (stripConsole.equals("warn")) {
+        	 stripConsoleRegex += "|warn";
+         } else if (stripConsole.equals("all")) {
+        	 stripConsoleRegex += "|warn|error";
+         } else {
+        	 throw new IllegalArgumentException("unrecognised value for stripConsole: " + stripConsole + "!");
+         }
+         
+         Pattern stripConsolePattern = null;
+         if (stripConsoleRegex != null) {
+        	 stripConsolePattern = Pattern.compile(stripConsoleRegex);
+         }
+
+         StringBuffer result = new StringBuffer();
+         boolean justFunctionBody = (0 != (flags & Decompiler.ONLY_BODY_FLAG));
+         boolean toSource = (0 != (flags & Decompiler.TO_SOURCE_FLAG));
+         int braceNesting = 0;
+         boolean afterFirstEOL = false;
+         int i = 0;
+         int prevToken = 0;
+         boolean primeFunctionNesting = false;
+         boolean inArgsList = false;
+         boolean primeInArgsList = false;
+
+         boolean discardingConsole = false; // control skipping "console.stuff()"
+         int     consoleParenCount = 0; // counter for parenthesis counting
+         StringBuffer discardMe = new StringBuffer(); // throwaway buffer
+         ReplacedTokens dummyTokens = new ReplacedTokens(new HashMap(), new int[]{}, replacedTokensLookup, null);
+         int lastMeaningfulToken = Token.SEMI;
+         int lastMeaningfulTokenBeforeConsole = Token.SEMI;
+
+         int topFunctionType;
+         if (encodedSource.charAt(i) == Token.SCRIPT) {
+             ++i;
+             topFunctionType = -1;
+         } else {
+             topFunctionType = encodedSource.charAt(i + 1);
+         }
+         if (!toSource) {
+             // add an initial newline to exactly match js.
+             // result.append('\n');
+             for (int j = 0; j < indent; j++){
+                 // result.append(' ');
+                 result.append("");
+             }
+         } else {
+             if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
+                 result.append('(');
+             }
+         }
+         
+         Stack positionStack = new Stack();
+         Stack functionPositionStack = new Stack();
+         
+         int length = encodedSource.length();
+         int lineCount = 1;
+         
+         while (i < length) {
+           if(i>0){
+               prevToken = encodedSource.charAt(i-1);
+           }
+            if (discardingConsole) {
+                // while we are skipping a console command, discard tokens
+                int thisToken = encodedSource.charAt(i);
+                /* Logic for controlling state of discardingConsole */
+                switch (thisToken) {
+                case Token.LP:
+                    consoleParenCount++;
+                    break;
+                case Token.RP:
+                    consoleParenCount--;
+                    if (consoleParenCount == 0) {
+                        // paren count fell to zero, must be end of console call
+                        discardingConsole = false;
+                        
+                        if (i < (length - 1)) {
+                        	int nextToken = getNext(encodedSource, length, i);
+
+                        	if ((lastMeaningfulTokenBeforeConsole != Token.SEMI &&
+                        			lastMeaningfulTokenBeforeConsole != Token.LC &&
+                        			lastMeaningfulTokenBeforeConsole != Token.RC) ||
+                        			nextToken != Token.SEMI) {
+                        		// Either the previous or the following token
+                        		// may use our return value, insert undefined
+                        		// e.g. true ? console.log("bizarre") : (bar = true);
+                        		result.append("undefined");
+                        	} else {
+                            	if (Token.SEMI == nextToken) {
+                            		// munch following semicolon
+                            		i++;
+                            	}
+                        	}
+						}
+						if ((i < (length - 1))
+								&& (Token.EOL == getNext(encodedSource, length, i))) {
+							// as a nicety, munch following linefeed
+							i++;
+						}
+                    }
+                    break;
+                }
+                /*
+                 * advance i - borrow code from later switch statements (could
+                 * mingle this whole discardingConsole block in with rest of
+                 * function but it would be _ugly_) Use discardMe in place of
+                 * result, so we don't use the processed source Specific case
+                 * blocks for all source elements > 1 char long
+                 */
+                switch (thisToken) {
+                case Token.NAME:
+                case Token.REGEXP:
+                    int jumpPos = getSourceStringEnd(encodedSource, i + 1,
+                            escapeUnicode);
+                    if (Token.OBJECTLIT == encodedSource.charAt(jumpPos)) {
+                        i = printSourceString(encodedSource, i + 1, false,
+                                discardMe, escapeUnicode);
+                    } else {
+                        i = tm.sourceCompress(encodedSource, i + 1, false,
+                                discardMe, prevToken, inArgsList, braceNesting,
+                                dummyTokens);
+                    }
+                    break;
+                case Token.STRING:
+                    i = printSourceString(encodedSource, i + 1, true,
+                            discardMe, escapeUnicode);
+                    break;
+                case Token.NUMBER:
+                    i = printSourceNumber(encodedSource, i + 1, discardMe);
+                    break;
+                default:
+                    // all plain tokens (no data to skip)
+                    i++;
+                }
+                // while discarding console, avoid the normal processing
+                continue;
+            }
+
+           // System.out.println(Token.name(getNext(source, length, i)));
+           int thisToken = encodedSource.charAt(i);
+
+           switch(thisToken) {
+             case Token.NAME:
+             case Token.REGEXP:  // re-wrapped in '/'s in parser...
+                 int jumpPos = getSourceStringEnd(encodedSource, i+1, escapeUnicode);
+                 if (stripConsolePattern != null && thisToken == Token.NAME) {
+                	 // Check to see if this is a console.something() call that we
+                	 //  care about, if so switch on discardingConsole
+                     int nextTokenAt = tm.sourceCompress(encodedSource, i + 1, false, discardMe, prevToken, 
+                             inArgsList, braceNesting, dummyTokens);
+                	 if (encodedSource.substring(i+2, i+2+encodedSource.charAt(i+1)).equals("console") &&
+                         (encodedSource.charAt(nextTokenAt) == Token.DOT)) {
+                		 // Find the name of the console method and check it
+                    	 int afterFnName = printSourceString(encodedSource, nextTokenAt+2, false, discardMe, escapeUnicode);
+                    	 Matcher m = stripConsolePattern.matcher(encodedSource.substring(nextTokenAt + 3, afterFnName));
+                    	 if (m.matches()) {
+                    		 // Must be an open parenthesis e.g. "console.log("
+                    		 if (encodedSource.charAt(afterFnName) == Token.LP) {
+		                		 discardingConsole = true;
+		                		 consoleParenCount = 0;
+		                		 lastMeaningfulTokenBeforeConsole = lastMeaningfulToken;
+		                		 continue;
+                    		 }
+                    	 }
+                     }
+                 }
+                 if(Token.OBJECTLIT == encodedSource.charAt(jumpPos)){
+                     i = printSourceString(encodedSource, i + 1, false, result, escapeUnicode);
+                 }else{
+                	 ReplacedTokens replacedTokens = null;
+                	 if (positionStack.size() > 0) {
+                		 Integer pos = (Integer)positionStack.peek();
+                         replacedTokens = (ReplacedTokens)replacedTokensLookup.get(pos);
+                	 }
+                	 else {
+                		 replacedTokens = new ReplacedTokens(new HashMap(), new int[]{}, replacedTokensLookup, null);
+                	 }
+
+                     i = tm.sourceCompress(	encodedSource, i + 1, false, result, prevToken, 
+                                             inArgsList, braceNesting, replacedTokens);
+                 }
+                 continue;
+             case Token.STRING:
+
+// NOTE: this is the disabled "string munging" code provided in bugs.dojotoolkit.org/ticket/8828
+// simply uncomment this block, and run the build.sh script located in the root shrinksafe folder.
+// there is a far-egde-case this is deemed unsafe in, so is entirely disabled for sanity of devs.
+//
+//                 StringBuffer buf = new StringBuffer();
+//                 i--;
+//                 do {
+//                    i++;
+//                    i = printSourceString(encodedSource, i + 1, false, buf, escapeUnicode);
+//                 } while(Token.ADD == encodedSource.charAt(i) &&
+//                   Token.STRING == getNext(encodedSource, length, i));
+//                 result.append('"');
+//                 result.append(escapeString(buf.toString(), escapeUnicode));
+//                 result.append('"');
+//
+// now comment out this line to complete the patch:
+                 i = printSourceString(encodedSource, i + 1, true, result, escapeUnicode); 
+
+                 continue;
+             case Token.NUMBER:
+                 i = printSourceNumber(encodedSource, i + 1, result);
+                 continue;
+             case Token.TRUE:
+                 result.append("true");
+                 break;
+             case Token.FALSE:
+                 result.append("false");
+                 break;
+             case Token.NULL:
+                 result.append("null");
+                 break;
+             case Token.THIS:
+                 result.append("this");
+                 break;
+             case Token.FUNCTION: {
+                 ++i; // skip function type
+                 tm.incrementFunctionNumber();
+                 primeInArgsList = true;
+                 primeFunctionNesting = true;
+                 result.append("function");
+                 if (Token.LP != getNext(encodedSource, length, i)) {
+                     result.append(' ');
+                 }
+                 Integer functionPos = new Integer(i-1);
+                 functionPositionStack.push(functionPos);
+                 DebugData debugData = tm.getDebugData(functionPos);
+                 debugData.compressedStart = lineCount;
+                 break;
+             }
+             case FUNCTION_END: {
+            	 Integer functionPos = (Integer)functionPositionStack.pop();
+                 DebugData debugData = tm.getDebugData(functionPos);
+                 debugData.compressedEnd = lineCount;
+                 break;
+             }
+             case Token.COMMA:
+                 result.append(",");
+                 break;
+             case Token.LC:
+                 ++braceNesting;
+                 if (Token.EOL == getNext(encodedSource, length, i)){
+                     indent += indentGap;
+                 }
+                 result.append('{');
+                 // // result.append('\n');
+                 break;
+             case Token.RC: {
+                 if (tm.leaveNestingLevel(braceNesting)) {
+                     positionStack.pop();
+                 }
+                 --braceNesting;
+                 /* don't print the closing RC if it closes the
+                  * toplevel function and we're called from
+                  * decompileFunctionBody.
+                  */
+                 if(justFunctionBody && braceNesting == 0){
+                     break;
+                 }
+                 // // result.append('\n');
+                 result.append('}');
+                 // // result.append(' ');
+                 switch (getNext(encodedSource, length, i)) {
+                     case Token.EOL:
+                     case FUNCTION_END:
+                        if (
+                            (getNext(encodedSource, length, i+1) != Token.SEMI) &&
+                            (getNext(encodedSource, length, i+1) != Token.LP) &&
+                            (getNext(encodedSource, length, i+1) != Token.RP) &&
+                            (getNext(encodedSource, length, i+1) != Token.RB) &&
+                            (getNext(encodedSource, length, i+1) != Token.RC) &&
+                            (getNext(encodedSource, length, i+1) != Token.COMMA) &&
+                            (getNext(encodedSource, length, i+1) != Token.COLON) &&
+                            (getNext(encodedSource, length, i+1) != Token.DOT) &&
+                            (getNext(encodedSource, length, i) == FUNCTION_END )
+                         ){
+						    result.append(';');
+                         }
+                         indent -= indentGap;
+                         break;
+                     case Token.WHILE:
+                     case Token.ELSE:
+                         indent -= indentGap;
+                         // result.append(' ');
+                         result.append("");
+                         break;
+                 }
+                 break;
+             }
+             case Token.LP:
+                 if(primeInArgsList){
+                     inArgsList = true;
+                     primeInArgsList = false;
+                 }
+                 if(primeFunctionNesting){
+                     positionStack.push(new Integer(i));
+                     tm.enterNestingLevel(braceNesting);
+                     primeFunctionNesting = false;
+                 }
+                 result.append('(');
+                 break;
+             case Token.RP:
+			    if(inArgsList){
+                    inArgsList = false;
+				}
+                 result.append(')');
+  			/*
+                 if (Token.LC == getNext(source, length, i)){
+                     result.append(' ');
+                 }
+  			*/
+                 break;
+             case Token.LB:
+                 result.append('[');
+                 break;
+             case Token.RB:
+                 result.append(']');
+                 break;
+             case Token.EOL: {
+                 if (toSource) break;
+                 boolean newLine = true;
+                 if (!afterFirstEOL) {
+                     afterFirstEOL = true;
+                     if (justFunctionBody) {
+                         /* throw away just added 'function name(...) {'
+                          * and restore the original indent
+                          */
+                         result.setLength(0);
+                         indent -= indentGap;
+                         newLine = false;
+                     }
+                 }
+                 if (newLine) {
+                     result.append('\n');
+                     lineCount++;
+                 }
+                 /* add indent if any tokens remain,
+                  * less setback if next token is
+                  * a label, case or default.
+                  */
+                 if (i + 1 < length) {
+                     int less = 0;
+                     int nextToken = encodedSource.charAt(i + 1);
+                     if (nextToken == Token.CASE
+                         || nextToken == Token.DEFAULT)
+                     {
+                         less = indentGap - caseGap;
+                     } else if (nextToken == Token.RC) {
+                         less = indentGap;
+                     }
+                     /* elaborate check against label... skip past a
+                      * following inlined NAME and look for a COLON.
+                      */
+                     else if (nextToken == Token.NAME) {
+                         int afterName = getSourceStringEnd(encodedSource, i + 2, escapeUnicode);
+                         if (encodedSource.charAt(afterName) == Token.COLON)
+                             less = indentGap;
+                     }
+                     for (; less < indent; less++){
+                         // result.append(' ');
+                         result.append("");
+                     }
+                 }
+                 break;
+             }
+             case Token.DOT:
+                 result.append('.');
+                 break;
+             case Token.NEW:
+                 result.append("new ");
+                 break;
+             case Token.DELPROP:
+                 result.append("delete ");
+                 break;
+             case Token.IF:
+                 result.append("if");
+                 break;
+             case Token.ELSE:
+                 result.append("else");
+                 break;
+             case Token.FOR:
+                 result.append("for");
+                 break;
+             case Token.IN:
+                 result.append(" in ");
+                 break;
+             case Token.WITH:
+                 result.append("with");
+                 break;
+             case Token.WHILE:
+                 result.append("while");
+                 break;
+             case Token.DO:
+                 result.append("do");
+                 break;
+             case Token.TRY:
+                 result.append("try");
+                 break;
+             case Token.CATCH:
+                 result.append("catch");
+                 break;
+             case Token.FINALLY:
+                 result.append("finally");
+                 break;
+             case Token.THROW:
+                 result.append("throw ");
+                 break;
+             case Token.SWITCH:
+                 result.append("switch");
+                 break;
+             case Token.BREAK:
+                 result.append("break");
+                 if(Token.NAME == getNext(encodedSource, length, i)){
+                     result.append(' ');
+  			}
+                 break;
+             case Token.CONTINUE:
+                 result.append("continue");
+                 if(Token.NAME == getNext(encodedSource, length, i)){
+                     result.append(' ');
+  			}
+                 break;
+             case Token.CASE:
+                 result.append("case ");
+                 break;
+             case Token.DEFAULT:
+                 result.append("default");
+                 break;
+             case Token.RETURN:
+                 result.append("return");
+                 if(Token.SEMI != getNext(encodedSource, length, i)){
+                     result.append(' ');
+                 }
+                 break;
+             case Token.VAR:
+                 result.append("var ");
+                 break;
+             case Token.SEMI:
+                 result.append(';');
+                 // result.append('\n');
+  			/*
+                 if (Token.EOL != getNext(source, length, i)) {
+                     // separators in FOR
+                     result.append(' ');
+                 }
+  			*/
+                 break;
+             case Token.ASSIGN:
+                 result.append("=");
+                 break;
+             case Token.ASSIGN_ADD:
+                 result.append("+=");
+                 break;
+             case Token.ASSIGN_SUB:
+                 result.append("-=");
+                 break;
+             case Token.ASSIGN_MUL:
+                 result.append("*=");
+                 break;
+             case Token.ASSIGN_DIV:
+                 result.append("/=");
+                 break;
+             case Token.ASSIGN_MOD:
+                 result.append("%=");
+                 break;
+             case Token.ASSIGN_BITOR:
+                 result.append("|=");
+                 break;
+             case Token.ASSIGN_BITXOR:
+                 result.append("^=");
+                 break;
+             case Token.ASSIGN_BITAND:
+                 result.append("&=");
+                 break;
+             case Token.ASSIGN_LSH:
+                 result.append("<<=");
+                 break;
+             case Token.ASSIGN_RSH:
+                 result.append(">>=");
+                 break;
+             case Token.ASSIGN_URSH:
+                 result.append(">>>=");
+                 break;
+             case Token.HOOK:
+                 result.append("?");
+                 break;
+             case Token.OBJECTLIT:
+                 // pun OBJECTLIT to mean colon in objlit property
+                 // initialization.
+                 // This needs to be distinct from COLON in the general case
+                 // to distinguish from the colon in a ternary... which needs
+                 // different spacing.
+                 result.append(':');
+                 break;
+             case Token.COLON:
+                 if (Token.EOL == getNext(encodedSource, length, i))
+                     // it's the end of a label
+                     result.append(':');
+                 else
+                     // it's the middle part of a ternary
+                     result.append(":");
+                 break;
+             case Token.OR:
+                 result.append("||");
+                 break;
+             case Token.AND:
+                 result.append("&&");
+                 break;
+             case Token.BITOR:
+                 result.append("|");
+                 break;
+             case Token.BITXOR:
+                 result.append("^");
+                 break;
+             case Token.BITAND:
+                 result.append("&");
+                 break;
+             case Token.SHEQ:
+                 result.append("===");
+                 break;
+             case Token.SHNE:
+                 result.append("!==");
+                 break;
+             case Token.EQ:
+                 result.append("==");
+                 break;
+             case Token.NE:
+                 result.append("!=");
+                 break;
+             case Token.LE:
+                 result.append("<=");
+                 break;
+             case Token.LT:
+                 result.append("<");
+                 break;
+             case Token.GE:
+                 result.append(">=");
+                 break;
+             case Token.GT:
+                 result.append(">");
+                 break;
+             case Token.INSTANCEOF:
+  			// FIXME: does this really need leading space?
+                 result.append(" instanceof ");
+                 break;
+             case Token.LSH:
+                 result.append("<<");
+                 break;
+             case Token.RSH:
+                 result.append(">>");
+                 break;
+             case Token.URSH:
+                 result.append(">>>");
+                 break;
+             case Token.TYPEOF:
+                 result.append("typeof ");
+                 break;
+             case Token.VOID:
+                 result.append("void ");
+                 break;
+             case Token.NOT:
+                 result.append('!');
+                 break;
+             case Token.BITNOT:
+                 result.append('~');
+                 break;
+             case Token.POS:
+                 result.append('+');
+                 break;
+             case Token.NEG:
+                 result.append('-');
+                 break;
+             case Token.INC:
+                 if(Token.ADD == prevToken){
+                    result.append(' ');
+                 }
+                 result.append("++");
+                 if(Token.ADD == getNext(encodedSource, length, i)){
+                     result.append(' ');
+                 }
+                 break;
+             case Token.DEC:
+                 if(Token.SUB == prevToken){
+                     result.append(' ');
+                 }
+                 result.append("--");
+                 if(Token.SUB == getNext(encodedSource, length, i)){
+                     result.append(' ');
+                 }
+                 break;
+             case Token.ADD:
+                 result.append("+");
+                 int nextToken = encodedSource.charAt(i + 1);
+                 if (nextToken == Token.POS) {
+                     result.append(' ');
+                 }
+                 break;
+             case Token.SUB:
+                 result.append("-");
+                 nextToken = encodedSource.charAt(i + 1);
+                 if (nextToken == Token.NEG) {
+                     result.append(' ');
+                 }
+                 break;
+             case Token.MUL:
+                 result.append("*");
+                 break;
+             case Token.DIV:
+                 result.append("/");
+                 break;
+             case Token.MOD:
+                 result.append("%");
+                 break;
+             case Token.COLONCOLON:
+                 result.append("::");
+                 break;
+             case Token.DOTDOT:
+                 result.append("..");
+                 break;
+             case Token.XMLATTR:
+                 result.append('@');
+                 break;
+            case Token.DEBUGGER:
+                System.out.println("WARNING: Found a `debugger;` statement in code being compressed");
+                result.append("debugger");
+                break;
+             default:
+                 // If we don't know how to decompile it, raise an exception.
+                 throw new RuntimeException();
+             }
+             if (thisToken != Token.EOL) {
+                 lastMeaningfulToken = thisToken;
+             }
+             ++i;
+         }
+         if (!toSource) {
+             // add that trailing newline if it's an outermost function.
+             // if (!justFunctionBody){
+             //    result.append('\n');
+  		// }
+         } else {
+             if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
+                 result.append(')');
+             }
+         }
+         return result.toString();
+    }
+
+    /**
+     * Collect the replaced tokens and store them in a lookup table for the next
+     * source pass. 
+     * 
+     * @param encodedSource encoded source string
+     * @param escapeUnicode escape chars with unicode.
+     * @param tm token mapper object.
+     * @return Map containing replaced tokens lookup information
+     */
+    private static Map collectReplacedTokens(String encodedSource, boolean escapeUnicode, TokenMapper tm) {
+    	int length = encodedSource.length();
+    	
+		int i = 0;
+		int prevToken = 0;
+		int braceNesting = 0;
+		
+		boolean inArgsList = false;
+        boolean primeFunctionNesting = false;
+        boolean primeInArgsList = false;
+		
+        if (encodedSource.charAt(i) == Token.SCRIPT) {
+            ++i;
+        }
+
+        Stack positionStack = new Stack();
+        Stack functionPositionStack = new Stack();
+        Map tokenLookup = new HashMap();
+        
+		while (i < length) {
+			if (i > 0) {
+				prevToken = encodedSource.charAt(i - 1);
+			}
+			switch (encodedSource.charAt(i)) {
+				case Token.NAME:
+				case Token.REGEXP: {
+					int jumpPos = getSourceStringEnd(encodedSource, i + 1, escapeUnicode);
+					if (Token.OBJECTLIT == encodedSource.charAt(jumpPos)) {
+						i = printSourceString(encodedSource, i + 1, false, null, escapeUnicode);
+					} else {
+						i = tm.sourceCompress(encodedSource, i + 1, false, null, prevToken, inArgsList, braceNesting, null);
+					}
+					continue;
+				}
+				case Token.STRING: {
+					i = printSourceString(encodedSource, i + 1, true, null, escapeUnicode);
+					continue;
+				}
+				case Token.NUMBER: {
+					i = printSourceNumber(encodedSource, i + 1, null);
+					continue;
+				}
+				case Token.FUNCTION: {
+					++i; // skip function type
+					tm.incrementFunctionNumber();
+					primeInArgsList = true;
+					primeFunctionNesting = true;
+					functionPositionStack.push(new Integer(i-1));
+					break;
+				}
+				case Token.LC: {
+					++braceNesting;
+					break;
+				}
+				case Token.RC: {
+					Map m = tm.getCurrentTokens();
+					if (tm.leaveNestingLevel(braceNesting)) {
+						Integer pos = (Integer)positionStack.pop();
+						Integer functionPos = (Integer)functionPositionStack.pop();
+						int[] parents = new int[positionStack.size()];
+						int idx = 0;
+						for (Iterator itr = positionStack.iterator(); itr.hasNext();) {
+							parents[idx++] = ((Integer)itr.next()).intValue();
+						}
+						DebugData debugData = tm.getDebugData(functionPos);
+						ReplacedTokens replacedTokens = new ReplacedTokens(m, parents, tokenLookup, debugData); 
+						tokenLookup.put(pos, replacedTokens);
+					}
+					--braceNesting;
+					break;
+				}
+				case Token.LP: {
+					if (primeInArgsList) {
+						inArgsList = true;
+						primeInArgsList = false;
+					}
+					if (primeFunctionNesting) {
+						positionStack.push(new Integer(i));
+						tm.enterNestingLevel(braceNesting);
+						primeFunctionNesting = false;
+					}
+					break;
+				}
+				case Token.RP: {
+					if (inArgsList) {
+						inArgsList = false;
+					}
+					break;
+				}
+			}
+			++i;
+		}
+		return tokenLookup;
+	}
+
+    private static int getNext(String source, int length, int i) {
+        return (i + 1 < length) ? source.charAt(i + 1) : Token.EOF;
+    }
+
+    private static int getSourceStringEnd(String source, int offset, boolean escapeUnicode) {
+        return printSourceString(source, offset, false, null, escapeUnicode);
+    }
+
+    private static int printSourceString(String source, int offset,
+                                         boolean asQuotedString,
+                                         StringBuffer sb,
+                                         boolean escapeUnicode) {
+        int length = source.charAt(offset);
+        ++offset;
+        if ((0x8000 & length) != 0) {
+            length = ((0x7FFF & length) << 16) | source.charAt(offset);
+            ++offset;
+        }
+        if (sb != null) {
+            String str = source.substring(offset, offset + length);
+            if (!asQuotedString) {
+                sb.append(str);
+            } else {
+                sb.append('"');
+                sb.append(escapeString(str, escapeUnicode));
+                sb.append('"');
+            }
+        }
+        return offset + length;
+    }
+    
+    private static int printSourceNumber(String source, int offset,	StringBuffer sb) {
+		double number = 0.0;
+		char type = source.charAt(offset);
+		++offset;
+		if (type == 'S') {
+			if (sb != null) {
+				int ival = source.charAt(offset);
+				number = ival;
+			}
+			++offset;
+		} else if (type == 'J' || type == 'D') {
+			if (sb != null) {
+				long lbits;
+				lbits = (long) source.charAt(offset) << 48;
+				lbits |= (long) source.charAt(offset + 1) << 32;
+				lbits |= (long) source.charAt(offset + 2) << 16;
+				lbits |= source.charAt(offset + 3);
+				if (type == 'J') {
+					number = lbits;
+				} else {
+					number = Double.longBitsToDouble(lbits);
+				}
+			}
+			offset += 4;
+		} else {
+			// Bad source
+			throw new RuntimeException();
+		}
+		if (sb != null) {
+			sb.append(ScriptRuntime.numberToString(number, 10));
+		}
+		return offset;
+	}
+    
+    private static String escapeString(String s, boolean escapeUnicode) {
+        return escapeString(s, '"', escapeUnicode);
+    }
+    
+    private static String escapeString(String s, char escapeQuote, boolean escapeUnicode) {
+        if (!(escapeQuote == '"' || escapeQuote == '\'')) Kit.codeBug();
+        StringBuffer sb = null;
+
+        for(int i = 0, L = s.length(); i != L; ++i) {
+            int c = s.charAt(i);
+
+            if (' ' <= c && c <= '~' && c != escapeQuote && c != '\\') {
+                // an ordinary print character (like C isprint()) and not "
+                // or \ .
+                if (sb != null) {
+                    sb.append((char)c);
+                }
+                continue;
+            }
+            if (sb == null) {
+                sb = new StringBuffer(L + 3);
+                sb.append(s);
+                sb.setLength(i);
+            }
+
+            int escape = -1;
+            switch (c) {
+                case '\b':  escape = 'b';  break;
+                case '\f':  escape = 'f';  break;
+                case '\n':  escape = 'n';  break;
+                case '\r':  escape = 'r';  break;
+                case '\t':  escape = 't';  break;
+                case 0xb:   escape = 'v';  break; // Java lacks \v.
+                case ' ':   escape = ' ';  break;
+                case '\\':  escape = '\\'; break;
+            }
+            if (escape >= 0) {
+                // an \escaped sort of character
+                sb.append('\\');
+                sb.append((char)escape);
+            } else if (c == escapeQuote) {
+                sb.append('\\');
+                sb.append(escapeQuote);
+            } else {
+            	if (escapeUnicode || c == 0) { // always escape the null character (#5027)
+	                int hexSize;
+	                if (c < 256) {
+	                    // 2-digit hex
+	                    sb.append("\\x");
+	                    hexSize = 2;
+	                } else {
+	                    // Unicode.
+	                    sb.append("\\u");
+	                    hexSize = 4;
+	                }
+	                // append hexadecimal form of c left-padded with 0
+	                for (int shift = (hexSize - 1) * 4; shift >= 0; shift -= 4) {
+	                    int digit = 0xf & (c >> shift);
+	                    int hc = (digit < 10) ? '0' + digit : 'a' - 10 + digit;
+	                    sb.append((char)hc);
+	                }
+            	}
+            	else {
+            		sb.append((char)c);
+            	}
+            }
+        }
+        return (sb == null) ? s : sb.toString();
+    }
+    
+    public static final String compressScript(String source, int indent, int lineno, String stripConsole) {
+    	return compressScript(source, indent, lineno, false, stripConsole);
+    }
+    
+    public static final String compressScript(String source, int indent, int lineno, boolean escapeUnicode, String stripConsole) {
+    	return compressScript(source, indent, lineno, escapeUnicode, stripConsole, null);
+    }
+        
+    public static final String compressScript(String source, int indent, int lineno, boolean escapeUnicode, String stripConsole, StringBuffer debugData) {
+        CompilerEnvirons compilerEnv = new CompilerEnvirons();
+
+        Parser parser = new Parser(compilerEnv, compilerEnv.getErrorReporter());
+        
+        ScriptOrFnNode tree = parser.parse(source, null, lineno);
+        String encodedSource = parser.getEncodedSource();
+   	 	if (encodedSource.length() == 0) { return ""; }
+   	 	
+        Interpreter compiler = new Interpreter();
+        compiler.compile(compilerEnv, tree, encodedSource, false);
+        UintMap properties = new UintMap(1);
+        properties.put(Decompiler.INITIAL_INDENT_PROP, indent);
+        
+        TokenMapper tm = new TokenMapper(tree);
+        Map replacedTokensLookup = collectReplacedTokens(encodedSource, escapeUnicode, tm);
+        tm.reset();
+        
+        String compressedSource = compress(encodedSource, 0, properties, tree, escapeUnicode, stripConsole, tm, replacedTokensLookup);
+        if (debugData != null) {
+        	debugData.append("[\n");
+        	int count = 1;
+	        for (Iterator itr = replacedTokensLookup.keySet().iterator(); itr.hasNext();) {
+	        	Integer pos = (Integer)itr.next();
+	        	ReplacedTokens replacedTokens = (ReplacedTokens)replacedTokensLookup.get(pos);
+	        	debugData.append(replacedTokens.toJson());
+	        	if (count++ < replacedTokensLookup.size()) {
+	        		debugData.append(',');
+	        	}
+	        	debugData.append("\n");
+	        }
+        	debugData.append("]");
+        }
+        return compressedSource;
+    }
+}
diff --git a/util/shrinksafe/src/org/dojotoolkit/shrinksafe/DebugData.java b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/DebugData.java
new file mode 100644
index 0000000..d5437dd
--- /dev/null
+++ b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/DebugData.java
@@ -0,0 +1,37 @@
+/*
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Richard Backhouse
+ */
+package org.dojotoolkit.shrinksafe;
+
+/*
+ * The class provides a simple data structure to collect debug information
+ * for a given function. 
+ */
+public class DebugData {
+	public int start = 0;
+	public int end = 0;
+	public int compressedStart = 0;
+	public int compressedEnd = 0;
+	public String[] paramAndVarNames = null;
+}
diff --git a/util/shrinksafe/src/org/dojotoolkit/shrinksafe/Main.java b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/Main.java
new file mode 100644
index 0000000..3cef2bd
--- /dev/null
+++ b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/Main.java
@@ -0,0 +1,315 @@
+/*
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alex Russell
+ *   Richard Backhouse
+ */
+ 
+package org.dojotoolkit.shrinksafe;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ContextAction;
+import org.mozilla.javascript.Kit;
+import org.mozilla.javascript.tools.ToolErrorReporter;
+import org.mozilla.javascript.tools.shell.Global;
+import org.mozilla.javascript.tools.shell.QuitAction;
+import org.mozilla.javascript.tools.shell.ShellContextFactory;
+
+public class Main {
+	protected static final Global global = new Global();
+	protected static final ShellContextFactory shellContextFactory = new ShellContextFactory();
+	protected static ToolErrorReporter errorReporter;
+	protected static int exitCode = 0;
+	protected static boolean escapeUnicode = false; 
+	protected static String stripConsole = null;
+
+	static {
+		global.initQuitAction(new IProxy(IProxy.SYSTEM_EXIT, null));
+	}
+
+	/**
+	 * Proxy class to avoid proliferation of anonymous classes.
+	 */
+	private static class IProxy implements ContextAction, QuitAction
+	{
+		private static final int PROCESS_FILES = 1;
+		private static final int SYSTEM_EXIT = 3;
+
+		private int type;
+		private String[] args;
+
+		IProxy(int type, String[] args) {
+			this.type = type;
+			this.args = args;
+		}
+
+		public Object run(Context cx) {
+			if (type == PROCESS_FILES) {
+				try {
+					processFiles(cx, args);
+				} catch (IOException ioe) {
+					Context.reportError(ioe.toString());
+				}
+			} else {
+				throw Kit.codeBug();
+			}
+			return null;
+		}
+
+		public void quit(Context cx, int exitCode) {
+			if (type == SYSTEM_EXIT) {
+				System.exit(exitCode);
+				return;
+			}
+			throw Kit.codeBug();
+		}
+	}
+	
+	public static void main(String[] args) {
+		errorReporter = new ToolErrorReporter(false, global.getErr());
+		shellContextFactory.setErrorReporter(errorReporter);
+		IProxy iproxy = new IProxy(IProxy.PROCESS_FILES, processOptions(args));
+		global.init(shellContextFactory);
+		shellContextFactory.call(iproxy);
+	}
+	
+	public static String[] processOptions(String args[]) {
+		List fileList = new ArrayList();
+		String usageError = null;
+		boolean showUsage = false;
+		
+		for (int i = 0; i < args.length; i++) {
+			String arg = args[i];
+			if (!arg.startsWith("-")) {
+				fileList.add(arg);
+			}
+			else if (arg.equals("-js-version")) {
+				if (++i == args.length) {
+					usageError = arg;
+				}
+				int version = 0;
+				try {
+					version = Integer.parseInt(args[i]);
+				} catch (NumberFormatException ex) {
+					usageError = args[i];
+				}
+				if (!Context.isValidLanguageVersion(version)) {
+					usageError = args[i];
+				}
+				if (usageError != null)
+				shellContextFactory.setLanguageVersion(version);
+			}
+/*
+			else if (arg.equals("-opt") || arg.equals("-O")) {
+				if (++i == args.length) {
+					usageError = arg;
+				}
+				int opt = 0;
+				try {
+					opt = Integer.parseInt(args[i]);
+				} catch (NumberFormatException ex) {
+					usageError = args[i];
+				}
+				if (opt == -2) {
+					// Compatibility with Cocoon Rhino fork
+					opt = -1;
+				} else if (!Context.isValidOptimizationLevel(opt)) {
+					usageError = args[i];
+				}
+				if (usageError != null) {
+					shellContextFactory.setOptimizationLevel(opt);
+				}
+			}
+			else if (arg.equals("-debug")) {
+				shellContextFactory.setGeneratingDebug(true);
+			}
+*/
+			else if (arg.equals("-?") || arg.equals("-help")) {
+				showUsage = true;
+			}
+			else if (arg.equals("-escape-unicode")) {
+				escapeUnicode = true;
+			}
+			else if (arg.equals("-stripConsole")) {
+				if (i >= (args.length-1)) {
+					usageError = getMessage("msg.shell.stripConsoleMissingArg");
+				} else {
+					stripConsole = args[++i];
+					if (!stripConsole.equals("normal") &&
+							!stripConsole.equals("warn") &&
+							!stripConsole.equals("all")) {
+						usageError = getMessage("msg.shell.stripConsoleInvalid");
+					}
+				}
+			}
+
+		}
+
+		// print error and usage message
+		if (usageError != null) {
+			global.getOut().println(getMessage("msg.shell.invalid", usageError));
+		}
+		if (usageError != null || showUsage) {
+			global.getOut().println(getMessage("msg.shell.usage"));
+			System.exit(1);
+		}
+
+		String[] files = new String[fileList.size()];
+		files = (String[])fileList.toArray(files);
+		return files;
+	}
+	
+	static void processFiles(Context cx, String[] files) throws IOException {
+		StringBuffer cout = new StringBuffer();
+		if (files.length > 0) {
+			for (int i=0; i < files.length; i++) {
+				try {
+					String source = (String)readFileOrUrl(files[i], true);
+					cout.append(Compressor.compressScript(source, 0, 1, escapeUnicode, stripConsole));
+				} catch(IOException ex) {
+					// continue processing files
+				}
+			}
+		} else {
+			byte[] data = Kit.readStream(global.getIn(), 4096);
+			// Convert to String using the default encoding
+			String source = new String(data);
+			if (source != null) {
+				cout.append(Compressor.compressScript(source, 0, 1, escapeUnicode, stripConsole));
+			}
+		}
+
+		global.getOut().println(cout);
+	}
+
+	private static Object readFileOrUrl(String path, boolean convertToString) throws IOException {
+		URL url = null;
+		// Assume path is URL if it contains a colon and there are at least
+		// 2 characters in the protocol part. The later allows under Windows
+		// to interpret paths with driver letter as file, not URL.
+		if (path.indexOf(':') >= 2) {
+			try {
+				url = new URL(path);
+			} catch (MalformedURLException ex) {
+			}
+		}
+
+		InputStream is = null;
+		int capacityHint = 0;
+		if (url == null) {
+			File file = new File(path);
+			capacityHint = (int)file.length();
+			try {
+				is = new FileInputStream(file);
+			} catch (IOException ex) {
+				Context.reportError(getMessage("msg.couldnt.open", path));
+				throw ex;
+			}
+		} else {
+			try {
+				URLConnection uc = url.openConnection();
+				is = uc.getInputStream();
+				capacityHint = uc.getContentLength();
+				// Ignore insane values for Content-Length
+				if (capacityHint > (1 << 20)) {
+					capacityHint = -1;
+				}
+			} catch (IOException ex) {
+				Context.reportError(getMessage("msg.couldnt.open.url", url.toString(), ex.toString()));
+				throw ex;
+			}
+		}
+		if (capacityHint <= 0) {
+			capacityHint = 4096;
+		}
+
+		byte[] data;
+		try {
+			try {
+				is = new BufferedInputStream(is);
+				data = Kit.readStream(is, capacityHint);
+			} finally {
+				is.close();
+			}
+		} catch (IOException ex) {
+			Context.reportError(ex.toString());
+			throw ex;
+		}
+
+		Object result;
+		if (convertToString) {
+			// Convert to String using the default encoding
+			// TODO: Use 'charset=' argument of Content-Type if URL?
+			result = new String(data);
+		} else {
+			result = data;
+		}
+		return result;
+	}
+	
+	private static String getMessage(String messageId) {
+		return getMessage(messageId, (Object []) null);
+	}
+
+	private static String getMessage(String messageId, String argument) {
+		return getMessage(messageId, new Object[]{argument});
+	}
+
+	private static String getMessage(String messageId, Object arg1, Object arg2) {
+		return getMessage(messageId, new Object[]{arg1, arg2});
+	}
+
+	private static String getMessage(String messageId, Object[] args) {
+		Context cx = Context.getCurrentContext();
+		Locale locale = cx == null ? Locale.getDefault() : cx.getLocale();
+
+		ResourceBundle rb = ResourceBundle.getBundle("org.dojotoolkit.shrinksafe.resources.Messages", locale);
+
+		String formatString = null;
+		try {
+			formatString = rb.getString(messageId);
+		} catch (java.util.MissingResourceException mre) {
+			throw new RuntimeException("no message resource found for message property " + messageId);
+		}
+
+		if (args == null) {
+			return formatString;
+		} else {
+			MessageFormat formatter = new MessageFormat(formatString);
+			return formatter.format(args);
+		}
+	}
+}
diff --git a/util/shrinksafe/src/org/dojotoolkit/shrinksafe/ReplacedTokens.java b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/ReplacedTokens.java
new file mode 100644
index 0000000..f5a2d87
--- /dev/null
+++ b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/ReplacedTokens.java
@@ -0,0 +1,198 @@
+/*
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Richard Backhouse
+ */
+package org.dojotoolkit.shrinksafe;
+
+import java.util.Iterator;
+import java.util.Map;
+
+
+/*
+ * This Class provides a container for the replaced tokens applied for a given scope
+ * It provides a method to traverse down through the hierarchy to seach for a 
+ * replacement match. It also provides a method that generates debug information.
+ */
+
+public class ReplacedTokens {
+	private int[] parents = null;
+	private Map replacements = null;
+	private Map lookup = null;
+	private DebugData debugData = null;
+	
+	public ReplacedTokens(Map replacements, int[] parents, Map lookup, DebugData debugData) {
+		this.replacements = replacements; 
+		this.parents = parents;
+		this.lookup = lookup;
+		this.debugData = debugData;
+	}
+	
+	public String find(String token) {
+		String replacedToken = null;
+		if (replacements != null) {
+			replacedToken = (String)replacements.get(token);
+		}
+		if (replacedToken == null) {
+			for (int i = parents.length; i > 0; i--) {
+				int parentPos = parents[i-1];
+				ReplacedTokens parent = (ReplacedTokens)lookup.get(new Integer(parentPos));
+				if (parent.replacements != null) {
+					replacedToken = (String)parent.replacements.get(token);
+					if (replacedToken != null) {
+						break;
+					}
+				}
+			}
+		}
+		if (replacedToken == null) {
+			replacedToken = token;
+		}
+		return replacedToken;
+	}
+	
+	public String printDebugData() {
+		StringBuffer sb = new StringBuffer();
+		if (debugData != null) {
+			sb.append("Start:"+debugData.start);
+			sb.append(' ');
+			sb.append("End:"+debugData.end);
+			sb.append(' ');
+			sb.append("Compressed Start:"+debugData.compressedStart);
+			sb.append(' ');
+			sb.append("Compressed End:"+debugData.compressedEnd);
+			sb.append(' ');
+			if (debugData.paramAndVarNames != null) {
+				sb.append("Params and Vars: [");
+				for (String paramVar: debugData.paramAndVarNames) {
+					sb.append(paramVar);
+					sb.append(' ');
+				}
+				sb.append("]\n");
+			}
+			if (replacements != null && replacements.size() > 0) {
+				sb.append("\t");
+				sb.append("Replacements:\n");
+				for (Iterator itr = replacements.keySet().iterator(); itr.hasNext();) {
+					String token = (String)itr.next();
+					String replacement = (String)replacements.get(token);
+					if (!token.equals(replacement)) {
+						sb.append("\t\t");
+						sb.append('[');
+						sb.append(token);
+						sb.append(']');
+						sb.append(" replaced with ");
+						sb.append('[');
+						sb.append(replacement);
+						sb.append(']');
+						sb.append('\n');
+					}
+				}
+				sb.append("\n");
+			}
+			for (int i = parents.length; i > 0; i--) {
+				int parentPos = parents[i-1];
+				ReplacedTokens parent = (ReplacedTokens)lookup.get(new Integer(parentPos));
+				if (parent.replacements != null && parent.replacements.size() > 0) {
+					sb.append("\t");
+					sb.append("Parent Replacements level ["+i+"]:\n");
+					for (Iterator itr = parent.replacements.keySet().iterator(); itr.hasNext();) {
+						String token = (String)itr.next();
+						String replacement = (String)parent.replacements.get(token);
+						if (!token.equals(replacement)) {
+							sb.append("\t\t");
+							sb.append('[');
+							sb.append(token);
+							sb.append(']');
+							sb.append(" replaced with ");
+							sb.append('[');
+							sb.append(replacement);
+							sb.append(']');
+							sb.append('\n');
+						}
+					}
+					sb.append("\n");
+				}
+			}
+		}
+		return sb.toString();
+	}
+	
+	public String toJson() {
+		StringBuffer json = new StringBuffer();
+		json.append('{');
+		if (debugData != null) {
+			json.append("start: "+debugData.start);
+			json.append(", ");
+			json.append("end: "+debugData.end);
+			json.append(", ");
+			json.append("compressedStart: "+debugData.compressedStart);
+			json.append(", ");
+			json.append("compressedEnd: "+debugData.compressedEnd);
+			json.append(", ");
+			json.append("replacements: {");
+			if (replacements != null && replacements.size() > 0) {
+				json.append(replacementsToJson(replacements));
+			}
+			json.append('}');
+			if (parents.length > 0) {
+				json.append(", ");
+				json.append("parentReplacements: [");
+			}
+			int count = 1;
+			for (int i = 0; i < parents.length; i++) {
+				json.append('{');
+				int parentPos = parents[i];
+				ReplacedTokens parent = (ReplacedTokens)lookup.get(new Integer(parentPos));
+				if (parent.replacements != null && parent.replacements.size() > 0) {
+					json.append(replacementsToJson(parent.replacements));
+				}
+				json.append('}');
+				if (count++ < parents.length) {
+					json.append(", ");
+				}
+			}
+			if (parents.length > 0) {
+				json.append("]");
+			}
+		}
+		json.append("}");
+		return json.toString();
+	}
+	
+	private static String replacementsToJson(Map replacements) {
+		StringBuffer sb = new StringBuffer();
+		int count = 1;
+		for (Iterator itr = replacements.keySet().iterator(); itr.hasNext();) {
+			String token = (String)itr.next();
+			String replacement = (String)replacements.get(token);
+			sb.append("\""+replacement+'\"');
+			sb.append(" : ");
+			sb.append("\""+token+"\"");
+			if (count++ < replacements.size()) {
+				sb.append(", ");
+			}
+		}
+		
+		return sb.toString();
+	}
+}
diff --git a/util/shrinksafe/src/org/dojotoolkit/shrinksafe/TokenMapper.java b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/TokenMapper.java
new file mode 100644
index 0000000..32c2b2e
--- /dev/null
+++ b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/TokenMapper.java
@@ -0,0 +1,325 @@
+/*
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alex Russell
+ *   Richard Backhouse
+ */
+ 
+package org.dojotoolkit.shrinksafe;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.mozilla.javascript.ScriptOrFnNode;
+import org.mozilla.javascript.ScriptRuntime;
+import org.mozilla.javascript.Token;
+
+public class TokenMapper {
+	private List functionBracePositions = new ArrayList();
+
+	/**
+	 * Map of all replaced tokens
+	 */
+	private List replacedTokens = new ArrayList();
+
+	/**
+	 * Map of each Function node and all the variables in its current function
+	 * scope, other variables found while traversing the prototype chain and
+	 * variables found in the top-level scope.
+	 */
+	private List functionVarMappings = new ArrayList();
+	private Map debugDataList = new HashMap();
+
+	private int functionNum = 0;
+
+	private int parentScope = 0;
+
+	private int lastTokenCount = 0;
+	
+	public TokenMapper(ScriptOrFnNode parseTree) {
+		collectFunctionMappings(parseTree);
+	}
+
+	public void incrementFunctionNumber() {
+		functionNum++;
+	}
+	
+	/**
+	 * Generate new compressed tokens
+	 * <p>
+	 * 
+	 * @param token
+	 *            value of the string token
+	 * @param hasNewMapping
+	 *            boolean value indicating a new variable binding
+	 * @return compressed token
+	 */
+	private String getMappedToken(String token, boolean hasNewMapping) {
+		String newToken = null;
+		Map tokens = null;
+		String blank = new String("");
+		int localScope = functionBracePositions.size() - 1;
+
+		String oldToken = getPreviousTokenMapping(token, hasNewMapping);
+
+		if (!oldToken.equalsIgnoreCase(blank)) {
+			return oldToken;
+		} else if ((hasNewMapping || isInScopeChain(token))) {
+			newToken = new String("_" + Integer.toHexString(++lastTokenCount));
+			if (newToken.length() >= token.length() && token.charAt(0) != '_') {
+				newToken = token;
+				lastTokenCount--;
+			}
+			tokens = (Map) replacedTokens.get(hasNewMapping ? localScope : parentScope);
+			tokens.put(token, newToken);
+			return newToken;
+		}
+		return token;
+	}
+
+	/**
+	 * Checks for variable names in prototype chain
+	 * <p>
+	 * 
+	 * @param token
+	 *            value of the string token
+	 * @return boolean value indicating if the token is present in the chained
+	 *         scope
+	 */
+	private boolean isInScopeChain(String token) {
+		int scope = functionBracePositions.size();
+		Map chainedScopeVars = (Map) functionVarMappings.get(functionNum);
+		if (!chainedScopeVars.isEmpty()) {
+			for (int i = scope; i > 0; i--) {
+				if (chainedScopeVars.containsKey(new Integer(i))) {
+					parentScope = i - 1;
+					List temp = Arrays.asList((String[]) chainedScopeVars.get(new Integer(i)));
+					if (temp.indexOf(token) != -1) {
+						return true;
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Checks previous token mapping
+	 * <p>
+	 * 
+	 * @param token
+	 *            value of the string token
+	 * @param hasNewMapping
+	 *            boolean value indicating a new variable binding
+	 * @return string value of the previous token or blank string
+	 */
+	private String getPreviousTokenMapping(String token, boolean hasNewMapping) {
+		String result = new String("");
+		int scope = replacedTokens.size() - 1;
+
+		if (scope < 0) {
+			return result;
+		}
+
+		if (hasNewMapping) {
+			Map tokens = (Map) (replacedTokens.get(scope));
+			if (tokens.containsKey(token)) {
+				result = (String) tokens.get(token);
+				return result;
+			}
+		} else {
+			for (int i = scope; i > -1; i--) {
+				Map tokens = (Map) (replacedTokens.get(i));
+				if (tokens.containsKey(token)) {
+					result = (String) tokens.get(token);
+					return result;
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Generate mappings for each Function node and parameters and variables
+	 * names associated with it.
+	 * <p>
+	 * 
+	 * @param parseTree
+	 *            Mapping for each function node and corresponding parameters &
+	 *            variables names
+	 */
+	private void collectFunctionMappings(ScriptOrFnNode parseTree) {
+		int level = -1;
+		collectFuncNodes(parseTree, level, null);
+	}
+
+	/**
+	 * Recursive method to traverse all Function nodes
+	 * <p>
+	 * 
+	 * @param parseTree
+	 *            Mapping for each function node and corresponding parameters &
+	 *            variables names
+	 * @param level
+	 *            scoping level
+	 */
+	private void collectFuncNodes(ScriptOrFnNode parseTree, int level, ScriptOrFnNode parent) {
+		level++;
+		
+        DebugData debugData = new DebugData();
+        debugData.start = parseTree.getBaseLineno();
+        debugData.end = parseTree.getEndLineno();
+        debugData.paramAndVarNames = parseTree.getParamAndVarNames();
+        debugDataList.put(new Integer(parseTree.getEncodedSourceStart()), debugData);
+        
+		functionVarMappings.add(new HashMap());
+
+		Map bindingNames = (Map) functionVarMappings.get(functionVarMappings.size() - 1);
+		bindingNames.put(new Integer(level), parseTree.getParamAndVarNames());
+
+	    if (parent != null) {
+	        bindingNames.put(new Integer(level-1), parent.getParamAndVarNames());
+	    }
+	    
+		int nestedCount = parseTree.getFunctionCount();
+		for (int i = 0; i != nestedCount; ++i) {
+			collectFuncNodes(parseTree.getFunctionNode(i), level, parseTree);
+			bindingNames = (Map) functionVarMappings.get(functionVarMappings.size() - 1);
+			bindingNames.put(new Integer(level), parseTree.getParamAndVarNames());
+        }
+	}
+
+	/**
+	 * Compress the script
+	 * <p>
+	 * 
+	 * @param encodedSource
+	 *            encoded source string
+	 * @param offset
+	 *            position within the encoded source
+	 * @param asQuotedString
+	 *            boolean value indicating a quoted string
+	 * @param sb
+	 *            String buffer reference
+	 * @param prevToken
+	 *            Previous token in encoded source
+	 * @param inArgsList
+	 *            boolean value indicating position inside arguments list
+	 * @param currentLevel
+	 *            embeded function level
+	 * @param parseTree
+	 *            Mapping of each function node and corresponding parameters &
+	 *            variables names
+	 * @return compressed script
+	 */
+	public int sourceCompress(String encodedSource, int offset,
+			boolean asQuotedString, StringBuffer sb, int prevToken,
+			boolean inArgsList, int currentLevel, ReplacedTokens replacedTokens) {
+
+		boolean hasNewMapping = false;
+
+		int length = encodedSource.charAt(offset);
+		++offset;
+		if ((0x8000 & length) != 0) {
+			length = ((0x7FFF & length) << 16) | encodedSource.charAt(offset);
+			++offset;
+		}
+		String str = encodedSource.substring(offset, offset + length);
+		if ((prevToken == Token.VAR) || (inArgsList)) {
+			hasNewMapping = true;
+		}
+		if (sb != null) {
+			String sourceStr = new String(str);
+			
+			if (((functionBracePositions.size() > 0) && 
+				(currentLevel >= (((Integer) functionBracePositions.get(functionBracePositions.size() - 1)).intValue()))) || 
+				(inArgsList)) {
+				if (prevToken != Token.DOT) {
+					// Look for replacement token in provided lookup object.
+					str = replacedTokens.find(str);
+				}
+			}
+			if ((!inArgsList) && (asQuotedString)) {
+				if ((prevToken == Token.LC) || (prevToken == Token.COMMA)) {
+					str = sourceStr;
+				}
+			}
+			if (!asQuotedString) {
+				sb.append(str);
+			} else {
+				sb.append('"');
+				sb.append(ScriptRuntime.escapeString(str));
+				sb.append('"');
+			}
+		}
+		else if (((functionBracePositions.size() > 0) && 
+				(currentLevel >= (((Integer) functionBracePositions.get(functionBracePositions.size() - 1)).intValue()))) || 
+				(inArgsList)) {
+			if (prevToken != Token.DOT) {
+				getMappedToken(str, hasNewMapping);
+			}
+		}
+		return offset + length;
+	}
+
+	public void enterNestingLevel(int braceNesting) {
+		functionBracePositions.add(new Integer(braceNesting + 1));
+		replacedTokens.add(new HashMap());
+	}
+
+	public boolean leaveNestingLevel(int braceNesting) {
+		boolean tokensRemoved = false;
+		Integer bn = new Integer(braceNesting);
+
+		if ((functionBracePositions.contains(bn)) && (replacedTokens.size() > 0)) {
+			// remove our mappings now!
+			int scopedSize = replacedTokens.size();
+			replacedTokens.remove(scopedSize - 1);
+			functionBracePositions.remove(bn);
+			tokensRemoved = true;
+		}
+		return tokensRemoved;
+	}
+	
+	public Map getCurrentTokens() {
+		Map m = null;
+		if (replacedTokens.size() > 0) {
+			m = (Map)replacedTokens.get(replacedTokens.size() - 1);
+		}
+		return m;
+	}
+	
+	public DebugData getDebugData(Integer functionPosition) {
+		return (DebugData)debugDataList.get(functionPosition);
+	}
+	
+	public void reset() {
+		functionNum = 0;
+		parentScope = 0;
+		lastTokenCount = 0;
+		functionBracePositions = new ArrayList();
+		replacedTokens = new ArrayList();
+	}
+}
diff --git a/util/shrinksafe/src/org/dojotoolkit/shrinksafe/resources/Messages.properties b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/resources/Messages.properties
new file mode 100644
index 0000000..947132d
--- /dev/null
+++ b/util/shrinksafe/src/org/dojotoolkit/shrinksafe/resources/Messages.properties
@@ -0,0 +1,53 @@
+# Version: MPL 1.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Rhino code, released
+# May 6, 1999.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1997-1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Alex Russell
+#   Richard Backhouse
+
+msg.couldnt.open =\
+    Couldn''t open file "{0}".
+
+msg.couldnt.open.url =\
+    Couldn''t open URL "{0}: {1}".
+
+msg.shell.invalid =\
+    Invalid option "{0}"
+
+msg.shell.stripConsoleMissingArg =\
+    No behaviour provided for stripConsole
+
+msg.shell.stripConsoleInvalid =\
+    Invalid value provided for stripConsole
+
+msg.shell.usage =\
+    Dojo ShrinkSafe 2.0 $Rev: 22183 $ \n\
+    \n\
+    Usage: java -jar shrinksafe.jar [options...] [files or urls]\n\
+    Valid options are:\n\
+    \    -?, -help        Displays help messages.\n\
+    \    -escape-unicode  Use Javascript \\u#### notation for non-ASCII Characters.\n\
+    \    -js-version n    Sets the version of Javascript used.  See the -version\n\
+    \                     option in Rhino for info.  e.g. 100|110|120|130|140\n\
+    \    -stripConsole [ normal | warn | all ]\n\
+    \                     If not specified, all console calls are left alone.\n\
+    \                     normal - all console calls except warn and error are stripped.\n\
+    \                     warn - all console calls except error are stripped.\n\
+    \                     all - all console calls are stripped.\n\
diff --git a/util/shrinksafe/tests/1768.js b/util/shrinksafe/tests/1768.js
new file mode 100644
index 0000000..4e18073
--- /dev/null
+++ b/util/shrinksafe/tests/1768.js
@@ -0,0 +1,16 @@
+// testing a simple var list with embedded things.
+var result = 0;
+
+(function(){
+	var a = 2,
+		b = 3,
+		superLong = 4,
+		aFunction = function(arg){
+			var inList = superLong;
+			result = inList;
+		}
+	;
+	
+	aFunction(superLong);
+	
+})();
\ No newline at end of file
diff --git a/util/shrinksafe/tests/3241.js b/util/shrinksafe/tests/3241.js
new file mode 100644
index 0000000..462df32
--- /dev/null
+++ b/util/shrinksafe/tests/3241.js
@@ -0,0 +1,14 @@
+result = "";
+
+(function() {
+function MyClass(){
+    this.foo = function(argument1, argument2){
+            var mytest = test;
+			return mytest;
+    }
+    this.bar = function(){}
+}
+var test = "data";
+
+result = new MyClass().foo();
+})();
diff --git a/util/shrinksafe/tests/5303.js b/util/shrinksafe/tests/5303.js
new file mode 100644
index 0000000..de20cec
--- /dev/null
+++ b/util/shrinksafe/tests/5303.js
@@ -0,0 +1,21 @@
+result = "";
+
+(function() {
+    CallMe = function(callback) {
+        callback();
+    };
+
+    var say_hello_twice = function() {
+        say_hello();
+
+        CallMe(function(){
+            say_hello();
+        });
+    };
+
+    var say_hello = function() {
+        result += 'hello world';
+    };
+
+    say_hello_twice();
+})();
diff --git a/util/shrinksafe/tests/8828.js b/util/shrinksafe/tests/8828.js
new file mode 100644
index 0000000..74b6b65
--- /dev/null
+++ b/util/shrinksafe/tests/8828.js
@@ -0,0 +1,55 @@
+var result = [], string_tests;
+
+(function(){
+	// testing string munging
+
+	var n = "c";
+	result.push("a" + "b", "a" + n);
+
+	var ll = "+";
+	result.push(ll);
+
+	var color = "red";
+	var f = "The" + "Quick" + color + "Fox";
+	result.push(f);
+
+	var h = 4;
+	var multiline = "this" +
+		"is" + "a" + "test"
+		+ "spanning" +
+		h + "lines"
+	;
+	result.push(multiline);
+
+	// aliases. all "bar"
+	var a = "bar", b = 'bar', c = a;
+
+	// a multi-line string outside of the array
+	var ml = "testing" +
+		"multiple" +
+		"lines";
+
+	var val = [
+		"test" + "ing",
+		"test" + a + "simple",
+		"testing" + "combined" + b + "variables",
+		"test \"+" + "weird syntax",
+		'test' + 'basic',
+		'test "mixed"',
+		ml,
+		'test "mixed" and' + 'munge',
+		"t" + "e" + "s" + "t",
+		"t" + "e" + "s" + c + "t",
+		// weirdest example imaginable?:
+		'"slightly"+"off"',
+		// fail:
+		!"a" + "b",
+		(!"a") + "b",
+		!("a") + "b"
+	];
+
+	string_tests = function(){
+		return val;
+	}
+
+})();
\ No newline at end of file
diff --git a/util/shrinksafe/tests/8974.js b/util/shrinksafe/tests/8974.js
new file mode 100644
index 0000000..67a73de
--- /dev/null
+++ b/util/shrinksafe/tests/8974.js
@@ -0,0 +1,7 @@
+result = "";
+
+(function() {
+    var _3 = -1;
+    var variableone = 1, variabletwo = 2, variable3 = 3;
+    result = _3;
+})();
diff --git a/util/shrinksafe/tests/9444.js b/util/shrinksafe/tests/9444.js
new file mode 100644
index 0000000..d4be030
--- /dev/null
+++ b/util/shrinksafe/tests/9444.js
@@ -0,0 +1,11 @@
+(function(){
+	
+	var someComplicatedStuff = function(){
+		debugger;
+	}
+	
+	for(var i = 0; i < 10; i++){
+		if(i % 2 === 0) someComplicatedStuff();
+	}
+	
+})()
\ No newline at end of file
diff --git a/util/shrinksafe/tests/9676.js b/util/shrinksafe/tests/9676.js
new file mode 100644
index 0000000..6f60f6e
--- /dev/null
+++ b/util/shrinksafe/tests/9676.js
@@ -0,0 +1,3 @@
+// make sure plus and pos don't become inc.
+var result = 1 + +2 - -3;
+
diff --git a/util/shrinksafe/tests/escapeunicode.js b/util/shrinksafe/tests/escapeunicode.js
new file mode 100644
index 0000000..0044dc9
--- /dev/null
+++ b/util/shrinksafe/tests/escapeunicode.js
@@ -0,0 +1 @@
+"\u03B1";//+" ω"
\ No newline at end of file
diff --git a/util/shrinksafe/tests/module.js b/util/shrinksafe/tests/module.js
new file mode 100644
index 0000000..86f6b85
--- /dev/null
+++ b/util/shrinksafe/tests/module.js
@@ -0,0 +1,209 @@
+dojo.provide("shrinksafe.tests.module");
+
+// basic helper functions for running multiple tests.
+shrinksafe.tests.module.getContents = function(path){
+	// summary: Load a file from this /tests/ path into a variable
+	path = "../shrinksafe/tests/" + path;
+	return readFile(path); // String
+}
+
+shrinksafe.tests.module.compress = function(source, stripConsole, escapeUnicode){
+	// summary: Shorthand to compress some String version of JS code
+	return new String(Packages.org.dojotoolkit.shrinksafe.Compressor.compressScript(source, 0, 1, escapeUnicode, stripConsole)).toString();
+}
+
+shrinksafe.tests.module.loader = function(path, stripConsole, escapeUnicode){
+	// summary: Simple function to load and compress some file. Returns and object
+	//	 with 'original' and 'compressed' members, respectively. 
+	var s = shrinksafe.tests.module.getContents(path);
+	return {
+		original: s, 
+		compressed: shrinksafe.tests.module.compress(s, stripConsole, escapeUnicode || false)
+	};
+}
+
+try{
+	tests.register("shrinksafe", 
+	[
+		function forwardReference(t){
+			
+			var src = shrinksafe.tests.module.loader("3241.js", null);
+
+			t.assertTrue(src.original.length > src.compressed.length);
+			t.assertTrue(src.compressed.indexOf("test") == -1)
+
+			eval(src.compressed);
+			t.assertEqual("data", result);
+			delete result;
+		},
+
+		function nestedReference(t){
+			var src = shrinksafe.tests.module.loader("5303.js", null);
+			
+			t.assertTrue(src.original.length > src.compressed.length);
+			t.assertTrue(src.compressed.indexOf("say_hello") == -1)
+			t.assertTrue(src.compressed.indexOf("callback") == -1)
+
+			eval(src.compressed);
+			// make sure it runs to completion
+			t.assertEqual("hello worldhello world", result);
+			// globals must not be renamed
+			t.assertEqual("function", typeof CallMe);
+			delete result;
+		},
+		
+		function varConflict(t){
+			// ensuring a shrunken variable won't overwrite an existing variable 
+			// name, regardless of scope.
+			var src = shrinksafe.tests.module.loader("8974.js", null);
+
+			t.assertTrue(src.original.length > src.compressed.length);
+			t.assertTrue(src.compressed.indexOf("variabletwo") == -1)
+
+			eval(src.compressed);
+			t.assertEqual(-1, result);
+			delete result;
+		},
+		
+		function varlists(t){
+			// test to ensure var a, b, c; always works
+			var src = shrinksafe.tests.module.loader("1768.js", null);
+			
+			// ensure the things we expect to hide are hidden
+			t.t(src.compressed.indexOf("superlong") == -1);
+			t.t(src.compressed.indexOf("aFunction") == -1);
+			t.t(src.compressed.indexOf("inList") == -1);
+			
+			// sanity checking:
+			var boo = eval(src.compressed);
+			t.is(4, result);
+			delete result;
+			
+		},
+		
+		function stripConsoleNormal(t){
+			var src = shrinksafe.tests.module.loader("stripconsole.js", "normal");
+
+			t.assertTrue(src.compressed.indexOf("console.debug(\"debug here!\"") == -1)
+			t.assertTrue(src.compressed.indexOf("console.warn(\"warn here!\")") != -1)
+			t.assertTrue(src.compressed.indexOf("console.error(\"error here!\")") != -1)
+
+			eval(src.compressed);
+			// make sure expected output occurs.
+			t.assertEqual("WARN: warn here!ERROR: error here!notconsole debug here!notconsole warn here!", result);
+			delete result;
+		},
+
+		function stripConsoleWarns(t){
+			var src = shrinksafe.tests.module.loader("stripconsole.js", "warn");
+
+			t.assertTrue(src.original.length > src.compressed.length);
+			t.assertTrue(src.compressed.indexOf("console.debug(\"debug here!\"") == -1)
+			t.assertTrue(src.compressed.indexOf("console.warn(\"warn here!\")") == -1)
+			t.assertTrue(src.compressed.indexOf("console.error(\"error here!\")") != -1)
+
+			eval(src.compressed);
+			// make sure expected output occurs.
+			t.assertEqual("ERROR: error here!notconsole debug here!notconsole warn here!", result);
+			delete result;
+		},
+
+		function stripConsoleAll(t){
+			var src = shrinksafe.tests.module.loader("stripconsole.js", "all");
+
+			t.assertTrue(src.original.length > src.compressed.length);
+			t.assertTrue(src.compressed.indexOf("console.debug(\"debug here!\"") == -1)
+			t.assertTrue(src.compressed.indexOf("console.warn(\"warn here!\")") == -1)
+			t.assertTrue(src.compressed.indexOf("console.error(\"error here!\")") == -1)
+
+			eval(src.compressed);
+			// make sure expected output occurs.
+			t.assertEqual("notconsole debug here!notconsole warn here!", result);
+			delete result;
+		},
+
+		function stripConsoleComplex(t){
+			var src = shrinksafe.tests.module.loader("stripcomplex.js", "normal");
+
+			t.assertTrue(src.original.length > src.compressed.length);
+
+			eval(src.compressed);
+			// make sure expected output occurs.
+			t.assertEqual("ERROR: wooosome \\ dodgy \" characters *$!?//3-3fn saw arg 'wooo'.ERROR: Error return statement.", result);
+			delete result;
+		},
+
+		function debuggerCall(t){
+			// make sure we don't die when we find a debugger; statement 
+			var src = shrinksafe.tests.module.loader("9444.js", null);
+			t.t(src.compressed.indexOf("debugger") > -1);
+		},
+		
+		function nestedReference(t){
+			var src = shrinksafe.tests.module.loader("9676.js", null);
+			eval(src.compressed); // will throw on failure
+			t.assertEqual(6, result);
+			delete result;
+		},
+
+		function escapeUnicode(t){
+			var src = shrinksafe.tests.module.loader("escapeunicode.js", null);
+			t.assertTrue(src.compressed.indexOf('"\u03b1";') == 0);
+//			t.is('"\u03b1 \u03c9";', src.compressed); // extended test isn't working... encoding problem with input?
+
+			src = shrinksafe.tests.module.loader("escapeunicode.js", null, true);
+			t.assertTrue(src.compressed.indexOf('"\\u03b1";') == 0);
+//			t.is('"\\u03b1 \\u03c9";', src.compressed);
+		},
+
+		function mungeStrings(t){
+			
+			// this test is skipped intentionally. You must manually enabled the 
+			// code in Compressor.java which enables this functionality. The functionality
+			// is not considered completely "safe" and thus has been disabled.
+			// simply uncomment the block in Compressor.java to reinstate functionality. 
+			// original patch came under [ccla]. See bugs.dojotoolkit.org/ticket/8828
+			return; 
+			
+			var src = shrinksafe.tests.module.loader("8828.js");
+			
+			t.t(src.compressed.indexOf("ab") > -1); // basic test
+			t.t(src.compressed.indexOf('"a"+n') > -1); // basic expected miss
+			t.t(src.compressed.indexOf('thisisatestspanning"+h') > -1);
+			t.t(src.compressed.indexOf("testingmultiplelines") > -1);
+			t.t(src.compressed.indexOf("testingcombined\"+") > -1);
+			
+			var boo = eval(src.compressed);
+			t.is(5, result.length);
+			
+			t.t(result[3].indexOf("TheQuickredFox") > -1); // complex var post eval
+			t.is(result[4], "thisisatestspanning4lines"); // multiline post eval
+			
+			delete result;
+			
+			var expected = [
+				"testing","testbarsimple",
+				"testingcombinedbarvariables",
+				"test \"+weird syntax",
+				"testbasic",
+				"test \"mixed\"",
+				"testingmultiplelines",
+				"test \"mixed\" andmunge",
+				"test",
+				"tesbart",
+				"\"slightly\"+\"off\"",
+				// fails:
+				"falseb", "falseb", "falseb"
+			];
+			
+			var data = string_tests();
+			data.forEach(function(str, i){
+				t.is(expected[i], str);
+			});
+			
+			delete string_tests;
+		}
+	]);
+}catch(e){
+	doh.debug(e);
+}
diff --git a/util/shrinksafe/tests/runner.sh b/util/shrinksafe/tests/runner.sh
new file mode 100755
index 0000000..e678321
--- /dev/null
+++ b/util/shrinksafe/tests/runner.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+cd ../../doh
+java -classpath ../shrinksafe/js.jar:../shrinksafe/shrinksafe.jar org.mozilla.javascript.tools.shell.Main runner.js testModule=shrinksafe.tests.module testUrl=../shrinksafe/tests/module.js
diff --git a/util/shrinksafe/tests/stripcomplex.js b/util/shrinksafe/tests/stripcomplex.js
new file mode 100644
index 0000000..5b68af9
--- /dev/null
+++ b/util/shrinksafe/tests/stripcomplex.js
@@ -0,0 +1,42 @@
+result = "";
+
+/* For the purpose of these tests, we have no actual console with
+   which to test output, so create a dummy console and capture to
+   'result', which is examined by the test framework post eval. */
+var console = {
+	log: function(arg) { result += "LOG: " + arg; },
+	debug: function(arg) { result += "DEBUG: " + arg; },
+	warn: function(arg) { result += "WARN: " + arg; },
+	error: function(arg) { result += "ERROR: " + arg; },
+	dir: function(arg) { result += "DIR: " + arg; }
+};
+(function() {
+	var fn = function(arg) {
+		return "fn saw arg '" + arg + "'.";
+	}
+	var str = "wooo";
+	console.debug(str + "some \\ dodgy \" characters *$!?//" + (1+2) + (~2) + fn(str));
+	console.error(str + "some \\ dodgy \" characters *$!?//" + (1+2) + (~2) + fn(str));
+	
+	// from ticket http://bugs.dojotoolkit.org/ticket/8549
+	console.log("hello :) world!");
+	console.log(" anything /) with a paren ");
+	console.log(/^\)$/.test("hi"));
+
+	//It would be interesting to see how this comes out:
+	if(true)
+	    console.log("foo");
+	else
+	   var two = "two";
+	
+	var bar;
+	true ? console.log("bizarre") : (bar = true);
+	true ? (bar = true) : console.log("bizarre");
+	
+	(function() {
+		return console.debug("Debug return statement.");
+	})();
+	(function() {
+		return console.error("Error return statement.");
+	})();
+})();
\ No newline at end of file
diff --git a/util/shrinksafe/tests/stripconsole.js b/util/shrinksafe/tests/stripconsole.js
new file mode 100644
index 0000000..f892248
--- /dev/null
+++ b/util/shrinksafe/tests/stripconsole.js
@@ -0,0 +1,28 @@
+result = "";
+
+/* For the purpose of these tests, we have no actual console with
+   which to test output, so create a dummy console and capture to
+   'result', which is examined by the test framework post eval. */
+var console = {
+	debug: function(arg) { result += "DEBUG: " + arg; },
+	warn: function(arg) { result += "WARN: " + arg; },
+	error: function(arg) { result += "ERROR: " + arg; },
+	dir: function(arg) { result += "DIR: " + arg; }
+};
+/* Make something that looks a bit like console to ensure it
+   isn't stripped. */
+var notconsole = {
+	debug: function(arg) { result += arg; },
+	warn: function(arg) { result += arg; }
+};
+(function() {
+	var variable = 'variable';
+
+	console.debug("debug here!" + variable);
+	console.warn("warn here!");
+	console.error("error here!");
+	notconsole.debug("notconsole debug here!");
+	notconsole.warn("notconsole warn here!");
+
+	console.dir(notconsole);
+})();

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/dojo.git



More information about the Pkg-javascript-commits mailing list